From 1334f77b1ecef00ac31076ce6bf22bdfeb82d347 Mon Sep 17 00:00:00 2001 From: lace <> Date: Thu, 31 Oct 2002 14:31:15 +0000 Subject: [PATCH 1/1] :pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos --- .cvsignore | 18 + .gdbinit | 4 + COPYING | 340 + CREDITS | 41 + ChangeLog | 1093 + INSTALL | 74 + LGPL.txt | 504 + Makefile | 788 + NEWS | 15 + README | 24 + aboot.bat | 3 + apps/tests/alive/Makefile | 21 + apps/tests/alive/alive.c | 48 + apps/tests/apc/apc.c | 85 + apps/tests/apc/makefile | 21 + apps/tests/args/args.c | 39 + apps/tests/args/makefile | 19 + apps/tests/atomtest/atomtest.c | 114 + apps/tests/atomtest/makefile | 21 + apps/tests/bench/bench-syscall.c | 8 + apps/tests/bench/bench-thread.c | 82 + apps/tests/bench/makefile | 21 + apps/tests/bitblt/bitblt.cpp | 138 + apps/tests/bitblt/lena.bmp | Bin 0 -> 89322 bytes apps/tests/bitblt/makefile | 66 + apps/tests/consume/Makefile | 19 + apps/tests/consume/consume.c | 31 + apps/tests/count/Makefile | 21 + apps/tests/count/count.c | 15 + apps/tests/dibtest/dibtest.c | 81 + apps/tests/dibtest/makefile | 21 + apps/tests/dump_shared_data/dump_shared_data.c | 51 + apps/tests/dump_shared_data/makefile | 20 + apps/tests/event/event.c | 33 + apps/tests/event/makefile | 21 + apps/tests/file/Makefile | 19 + apps/tests/file/file.c | 54 + apps/tests/gditest/gditest.c | 344 + apps/tests/gditest/makefile | 21 + apps/tests/hello/hello.c | 8 + apps/tests/hello/makefile | 19 + apps/tests/isotest/isotest.c | 229 + apps/tests/isotest/makefile | 23 + apps/tests/lpc/conport.c | 205 + apps/tests/lpc/creport.c | 192 + apps/tests/lpc/dumpinfo.c | 239 + apps/tests/lpc/dumpinfo.h | 8 + apps/tests/lpc/lpcclt.c | 92 + apps/tests/lpc/lpcsrv.c | 139 + apps/tests/lpc/lpctest.h | 5 + apps/tests/lpc/makefile | 45 + apps/tests/mktime/makefile | 19 + apps/tests/mktime/mktime.c | 28 + apps/tests/mstest/Makefile | 45 + apps/tests/mstest/msclient.c | 46 + apps/tests/mstest/msserver.c | 40 + apps/tests/mutex/makefile | 22 + apps/tests/mutex/mutex.c | 116 + apps/tests/nptest/Makefile | 44 + apps/tests/nptest/npclient.c | 100 + apps/tests/nptest/npserver.c | 120 + apps/tests/patblt/Penguin.bmp | Bin 0 -> 106226 bytes apps/tests/patblt/makefile | 66 + apps/tests/patblt/patblt.cpp | 270 + apps/tests/pteb/Makefile | 21 + apps/tests/pteb/pteb.c | 23 + apps/tests/regdump/makefile | 22 + apps/tests/regdump/regdump.c | 234 + apps/tests/regtest/makefile | 22 + apps/tests/regtest/regtest.c | 882 + apps/tests/sectest/Makefile | 19 + apps/tests/sectest/sectest.c | 71 + apps/tests/sertest/makefile | 22 + apps/tests/sertest/sertest.c | 113 + apps/tests/shm/makefile | 47 + apps/tests/shm/shmclt.c | 61 + apps/tests/shm/shmsrv.c | 53 + apps/tests/simple/makefile | 20 + apps/tests/simple/simple.c | 15 + apps/tests/stretchblt/lena.bmp | Bin 0 -> 89322 bytes apps/tests/stretchblt/makefile | 66 + apps/tests/stretchblt/stretchblt.cpp | 258 + apps/tests/tcpsvr/makefile | 21 + apps/tests/tcpsvr/tcpsvr.c | 173 + apps/tests/test_old/bug2.c | 11 + apps/tests/test_old/bug3.c | 53 + apps/tests/test_old/makefile | 73 + apps/tests/test_old/temptest.c | 27 + apps/tests/test_old/test-fseek.c | 85 + apps/tests/test_old/test-fwrite.c | 68 + apps/tests/test_old/test-stdio.c | 55 + apps/tests/test_old/test_rdwr.c | 129 + apps/tests/test_old/testfsd.c | 315 + apps/tests/test_old/testsuite.c | 65 + apps/tests/test_old/testsuite.h | 44 + apps/tests/test_old/time_t.c | 12 + apps/tests/test_old/tst-printf.c | 311 + apps/tests/test_old/tstdiomisc.c | 56 + apps/tests/tests/GetSysMetrics/GetSysMetrics.c | 102 + apps/tests/tests/GetSysMetrics/Makefile | 20 + apps/tests/tests/GetSystemInfo/GetSystemInfo.c | 37 + apps/tests/tests/GetSystemInfo/Makefile | 26 + apps/tests/tests/Mutex/Makefile | 26 + apps/tests/tests/Mutex/fivemutex.c | 124 + apps/tests/tests/Mutex/rapidmutex.c | 89 + apps/tests/tests/Parent_Child/Makefile | 26 + apps/tests/tests/Parent_Child/Parent_Child.c | 151 + apps/tests/tests/guitest/Makefile | 36 + apps/tests/tests/guitest/guitest.c | 751 + apps/tests/tests/guitest/guitest.rc | 17 + apps/tests/tests/hello/Makefile | 26 + apps/tests/tests/hello/hello.c | 83 + apps/tests/tests/hello2/Makefile | 26 + apps/tests/tests/hello2/hello2.c | 9 + apps/tests/tests/make_install.bat | 51 + apps/tests/tests/new/Makefile | 26 + apps/tests/tests/new/new.c | 154 + apps/tests/tests/readme.txt | 31 + apps/tests/tests/rolex/Makefile | 39 + apps/tests/tests/rolex/rolex.c | 254 + apps/tests/tests/rolex/rolex.spec | 8 + apps/tests/tests/volinfo/Makefile | 36 + apps/tests/tests/volinfo/volinfo.c | 29 + apps/tests/thread/makefile | 21 + apps/tests/thread/thread.c | 89 + apps/tests/tokentest/makefile | 21 + apps/tests/tokentest/tokentest.c | 528 + apps/tests/vmtest/Makefile | 21 + apps/tests/vmtest/vmtest.c | 54 + apps/tests/winhello/makefile | 21 + apps/tests/winhello/winhello.c | 107 + apps/utils/cabman/cabinet.cpp | 2652 ++ apps/utils/cabman/cabinet.h | 431 + apps/utils/cabman/cabman.h | 47 + apps/utils/cabman/dff.txt | 55 + apps/utils/cabman/dfp.cpp | 992 + apps/utils/cabman/dfp.h | 130 + apps/utils/cabman/main.cpp | 493 + apps/utils/cabman/makefile | 64 + apps/utils/cabman/mszip.cpp | 172 + apps/utils/cabman/mszip.h | 41 + apps/utils/cabman/raw.cpp | 69 + apps/utils/cabman/raw.h | 35 + apps/utils/cabman/test.cpp | 164 + apps/utils/cabman/test.h | 32 + apps/utils/cat/cat.c | 26 + apps/utils/cat/makefile | 19 + apps/utils/net/ping/.cvsignore | 1 + apps/utils/net/roshttpd/common/.cvsignore | 1 + apps/utils/net/roshttpd/common/list.cpp | 94 + apps/utils/net/roshttpd/common/roshttpd.rc | 39 + apps/utils/net/roshttpd/common/socket.cpp | 343 + apps/utils/net/roshttpd/common/thread.cpp | 80 + apps/utils/net/roshttpd/config.cpp | 130 + apps/utils/net/roshttpd/error.cpp | 16 + apps/utils/net/roshttpd/http.cpp | 380 + apps/utils/net/roshttpd/httpd.cpp | 492 + apps/utils/net/roshttpd/include/config.h | 49 + apps/utils/net/roshttpd/include/debug.h | 17 + apps/utils/net/roshttpd/include/error.h | 15 + apps/utils/net/roshttpd/include/http.h | 57 + apps/utils/net/roshttpd/include/httpd.h | 85 + apps/utils/net/roshttpd/include/iterator.h | 20 + apps/utils/net/roshttpd/include/list.h | 233 + apps/utils/net/roshttpd/include/socket.h | 141 + apps/utils/net/roshttpd/include/thread.h | 34 + apps/utils/net/roshttpd/makefile | 29 + apps/utils/net/roshttpd/roshttpd.cpp | 66 + apps/utils/net/telnet/Makefile | 26 + apps/utils/net/telnet/ansi.cpp | 307 + apps/utils/net/telnet/console.cpp | 43 + apps/utils/net/telnet/console.h | 12 + apps/utils/net/telnet/helpsock.cpp | 40 + apps/utils/net/telnet/main.cpp | 180 + apps/utils/net/telnet/nvt.cpp | 296 + apps/utils/net/telnet/telnet.cpp | 130 + apps/utils/net/telnet/telnet.h | 24 + apps/utils/net/telnet/telnet.rc | 39 + apps/utils/net/telnet/vm.cpp | 424 + apps/utils/objdir/makefile | 21 + apps/utils/objdir/objdir.c | 369 + apps/utils/partinfo/makefile | 23 + apps/utils/partinfo/partinfo.c | 212 + apps/utils/pice/loader/main.c | 1001 + apps/utils/pice/loader/makefile | 37 + apps/utils/pice/loader/retypes.h | 15 + apps/utils/pice/loader/stab.def | 264 + apps/utils/pice/loader/stab_gnu.h | 37 + apps/utils/pice/loader/stdinc.h | 28 + apps/utils/pice/loader/terminal.c | 430 + apps/utils/pice/loader/terminal.h | 34 + apps/utils/pice/makefile | 21 + apps/utils/pice/module/animation.h | 2116 ++ apps/utils/pice/module/bp.c | 752 + apps/utils/pice/module/bp.h | 62 + apps/utils/pice/module/charset.h | 2564 ++ apps/utils/pice/module/dblflt.c | 133 + apps/utils/pice/module/dblflt.h | 32 + apps/utils/pice/module/debug.c | 192 + apps/utils/pice/module/debug.h | 47 + apps/utils/pice/module/disassembler.c | 716 + apps/utils/pice/module/disassembler.h | 159 + apps/utils/pice/module/disassemblerdata.h | 1802 ++ apps/utils/pice/module/disassemblerdefines.h | 515 + apps/utils/pice/module/gpfault.c | 142 + apps/utils/pice/module/gpfault.h | 34 + apps/utils/pice/module/hardware.c | 1042 + apps/utils/pice/module/hardware.h | 166 + apps/utils/pice/module/hercules.c | 486 + apps/utils/pice/module/hercules.h | 32 + apps/utils/pice/module/hooks.c | 177 + apps/utils/pice/module/hooks.h | 49 + apps/utils/pice/module/init.c | 379 + apps/utils/pice/module/init.h | 35 + apps/utils/pice/module/ldrsym.h | 38 + apps/utils/pice/module/logo.h | 100 + apps/utils/pice/module/makefile | 35 + apps/utils/pice/module/output.c | 290 + apps/utils/pice/module/output.h | 42 + apps/utils/pice/module/parse.c | 4099 +++ apps/utils/pice/module/parse.h | 181 + apps/utils/pice/module/patch.c | 234 + apps/utils/pice/module/patch.h | 34 + apps/utils/pice/module/pci_ids.h | 905 + apps/utils/pice/module/pgflt.c | 402 + apps/utils/pice/module/pgflt.h | 34 + apps/utils/pice/module/pice.rc | 39 + apps/utils/pice/module/pice_ver.h | 36 + apps/utils/pice/module/precomp.h | 65 + apps/utils/pice/module/privateice.c | 202 + apps/utils/pice/module/regs.h | 122 + apps/utils/pice/module/remods.h | 33 + apps/utils/pice/module/retypes.h | 52 + apps/utils/pice/module/scancodes.h | 106 + apps/utils/pice/module/serial.c | 656 + apps/utils/pice/module/serial.h | 36 + apps/utils/pice/module/serial_port.h | 173 + apps/utils/pice/module/shell.c | 1692 ++ apps/utils/pice/module/shell.h | 91 + apps/utils/pice/module/stab.def | 265 + apps/utils/pice/module/stab_gnu.h | 67 + apps/utils/pice/module/symbols.c | 2984 ++ apps/utils/pice/module/symbols.h | 92 + apps/utils/pice/module/syscall.c | 231 + apps/utils/pice/module/syscall.h | 35 + apps/utils/pice/module/trace.c | 91 + apps/utils/pice/module/trace.h | 35 + apps/utils/pice/module/utils.c | 2429 ++ apps/utils/pice/module/utils.h | 325 + apps/utils/pice/module/vga.c | 572 + apps/utils/pice/module/vga.h | 32 + apps/utils/pice/module/vga_utils.asm | 729 + apps/utils/pice/pice.cfg | 4 + apps/utils/pice/readme.txt | 107 + apps/utils/pice/shared/shared.h | 204 + apps/utils/ps/makefile | 21 + apps/utils/ps/ps.cpp | 42 + apps/utils/stats/Makefile | 21 + apps/utils/stats/stats.c | 459 + baseaddress.cfg | 55 + boot.bat | 1 + boot.hiv | 46 + bootc.lst | 7 + bootcd.bat | 24 + bootflop.bat | 32 + config | 33 + dk/nkm/.cvsignore | 1 + dk/nkm/Makefile | 150 + dk/psx/.cvsignore | 2 + dk/psx/Makefile | 59 + dk/readme.txt | 21 + dk/w32/.cvsignore | 1 + dk/w32/Makefile | 231 + doc/DIRS | 24 + doc/HACKING | 130 + doc/INDEX | 6 + doc/INTERNALS | 43 + doc/apc | 36 + doc/news1 | 142 + doc/news2 | 52 + doc/notes | 570 + doc/roadmap | 26 + doc/todo | 37 + drivers/bus/acpi/.cvsignore | 5 + drivers/bus/acpi/acpi.rc | 37 + drivers/bus/acpi/changed.txt | 21 + drivers/bus/acpi/dispatcher/.cvsignore | 5 + drivers/bus/acpi/dispatcher/dsfield.c | 423 + drivers/bus/acpi/dispatcher/dsmethod.c | 497 + drivers/bus/acpi/dispatcher/dsmthdat.c | 693 + drivers/bus/acpi/dispatcher/dsobject.c | 641 + drivers/bus/acpi/dispatcher/dsopcode.c | 875 + drivers/bus/acpi/dispatcher/dsutils.c | 750 + drivers/bus/acpi/dispatcher/dswexec.c | 653 + drivers/bus/acpi/dispatcher/dswload.c | 679 + drivers/bus/acpi/dispatcher/dswscope.c | 161 + drivers/bus/acpi/dispatcher/dswstate.c | 877 + drivers/bus/acpi/events/.cvsignore | 5 + drivers/bus/acpi/events/evevent.c | 769 + drivers/bus/acpi/events/evmisc.c | 443 + drivers/bus/acpi/events/evregion.c | 606 + drivers/bus/acpi/events/evrgnini.c | 417 + drivers/bus/acpi/events/evsci.c | 271 + drivers/bus/acpi/events/evxface.c | 609 + drivers/bus/acpi/events/evxfevnt.c | 485 + drivers/bus/acpi/events/evxfregn.c | 380 + drivers/bus/acpi/executer/.cvsignore | 5 + drivers/bus/acpi/executer/amconfig.c | 304 + drivers/bus/acpi/executer/amconvrt.c | 518 + drivers/bus/acpi/executer/amcreate.c | 720 + drivers/bus/acpi/executer/amdump.c | 41 + drivers/bus/acpi/executer/amdyadic.c | 875 + drivers/bus/acpi/executer/amfield.c | 279 + drivers/bus/acpi/executer/amfldio.c | 673 + drivers/bus/acpi/executer/ammisc.c | 513 + drivers/bus/acpi/executer/ammonad.c | 962 + drivers/bus/acpi/executer/ammutex.c | 281 + drivers/bus/acpi/executer/amnames.c | 389 + drivers/bus/acpi/executer/amprep.c | 404 + drivers/bus/acpi/executer/amregion.c | 409 + drivers/bus/acpi/executer/amresnte.c | 506 + drivers/bus/acpi/executer/amresolv.c | 426 + drivers/bus/acpi/executer/amresop.c | 481 + drivers/bus/acpi/executer/amstore.c | 569 + drivers/bus/acpi/executer/amstoren.c | 257 + drivers/bus/acpi/executer/amstorob.c | 433 + drivers/bus/acpi/executer/amsystem.c | 326 + drivers/bus/acpi/executer/amutils.c | 363 + drivers/bus/acpi/executer/amxface.c | 98 + drivers/bus/acpi/hardware/.cvsignore | 5 + drivers/bus/acpi/hardware/hwacpi.c | 305 + drivers/bus/acpi/hardware/hwgpe.c | 207 + drivers/bus/acpi/hardware/hwregs.c | 966 + drivers/bus/acpi/hardware/hwsleep.c | 188 + drivers/bus/acpi/hardware/hwtimer.c | 200 + drivers/bus/acpi/include/accommon.h | 725 + drivers/bus/acpi/include/acconfig.h | 153 + drivers/bus/acpi/include/acdebug.h | 411 + drivers/bus/acpi/include/acdispat.h | 450 + drivers/bus/acpi/include/acevents.h | 203 + drivers/bus/acpi/include/acexcep.h | 247 + drivers/bus/acpi/include/acglobal.h | 301 + drivers/bus/acpi/include/achware.h | 149 + drivers/bus/acpi/include/acinterp.h | 632 + drivers/bus/acpi/include/aclocal.h | 832 + drivers/bus/acpi/include/acmacros.h | 501 + drivers/bus/acpi/include/acnamesp.h | 430 + drivers/bus/acpi/include/acobject.h | 425 + drivers/bus/acpi/include/acoutput.h | 132 + drivers/bus/acpi/include/acparser.h | 346 + drivers/bus/acpi/include/acpi.h | 51 + drivers/bus/acpi/include/acpiosxf.h | 341 + drivers/bus/acpi/include/acpixf.h | 340 + drivers/bus/acpi/include/acresrc.h | 304 + drivers/bus/acpi/include/acstruct.h | 157 + drivers/bus/acpi/include/actables.h | 185 + drivers/bus/acpi/include/actbl.h | 217 + drivers/bus/acpi/include/actbl1.h | 123 + drivers/bus/acpi/include/actbl2.h | 189 + drivers/bus/acpi/include/actbl71.h | 144 + drivers/bus/acpi/include/actypes.h | 1060 + drivers/bus/acpi/include/amlcode.h | 420 + drivers/bus/acpi/include/platform/acenv.h | 288 + drivers/bus/acpi/include/platform/acgcc.h | 147 + drivers/bus/acpi/include/platform/aclinux.h | 66 + drivers/bus/acpi/include/platform/acwin.h | 71 + drivers/bus/acpi/include/platform/types.h | 796 + drivers/bus/acpi/makefile | 246 + drivers/bus/acpi/namespace/.cvsignore | 5 + drivers/bus/acpi/namespace/nsaccess.c | 551 + drivers/bus/acpi/namespace/nsalloc.c | 566 + drivers/bus/acpi/namespace/nseval.c | 506 + drivers/bus/acpi/namespace/nsinit.c | 278 + drivers/bus/acpi/namespace/nsload.c | 528 + drivers/bus/acpi/namespace/nsnames.c | 249 + drivers/bus/acpi/namespace/nsobject.c | 361 + drivers/bus/acpi/namespace/nssearch.c | 346 + drivers/bus/acpi/namespace/nsutils.c | 815 + drivers/bus/acpi/namespace/nswalk.c | 272 + drivers/bus/acpi/namespace/nsxfname.c | 300 + drivers/bus/acpi/namespace/nsxfobj.c | 694 + drivers/bus/acpi/ospm/.cvsignore | 5 + drivers/bus/acpi/ospm/acpienum.c | 235 + drivers/bus/acpi/ospm/acpisys.c | 168 + drivers/bus/acpi/ospm/bn.c | 598 + drivers/bus/acpi/ospm/busmgr/bm.c | 1047 + drivers/bus/acpi/ospm/busmgr/bmnotify.c | 310 + drivers/bus/acpi/ospm/busmgr/bmpm.c | 397 + drivers/bus/acpi/ospm/busmgr/bmpower.c | 669 + drivers/bus/acpi/ospm/busmgr/bmrequest.c | 164 + drivers/bus/acpi/ospm/busmgr/bmsearch.c | 191 + drivers/bus/acpi/ospm/busmgr/bmutils.c | 606 + drivers/bus/acpi/ospm/busmgr/bmxface.c | 331 + drivers/bus/acpi/ospm/fdo.c | 512 + drivers/bus/acpi/ospm/include/acpisys.h | 124 + drivers/bus/acpi/ospm/include/bm.h | 624 + drivers/bus/acpi/ospm/include/bmpower.h | 75 + drivers/bus/acpi/ospm/include/bn.h | 113 + drivers/bus/acpi/ospm/osl.c | 613 + drivers/bus/acpi/ospm/pdo.c | 221 + drivers/bus/acpi/parser/.cvsignore | 5 + drivers/bus/acpi/parser/psargs.c | 733 + drivers/bus/acpi/parser/psopcode.c | 650 + drivers/bus/acpi/parser/psparse.c | 1229 + drivers/bus/acpi/parser/psscope.c | 264 + drivers/bus/acpi/parser/pstree.c | 288 + drivers/bus/acpi/parser/psutils.c | 556 + drivers/bus/acpi/parser/pswalk.c | 283 + drivers/bus/acpi/parser/psxface.c | 163 + drivers/bus/acpi/resource/rsaddr.c | 801 + drivers/bus/acpi/resource/rscalc.c | 868 + drivers/bus/acpi/resource/rscreate.c | 421 + drivers/bus/acpi/resource/rsdump.c | 929 + drivers/bus/acpi/resource/rsio.c | 528 + drivers/bus/acpi/resource/rsirq.c | 556 + drivers/bus/acpi/resource/rslist.c | 500 + drivers/bus/acpi/resource/rsmemory.c | 557 + drivers/bus/acpi/resource/rsmisc.c | 606 + drivers/bus/acpi/resource/rsutils.c | 387 + drivers/bus/acpi/resource/rsxface.c | 221 + drivers/bus/acpi/tables/.cvsignore | 5 + drivers/bus/acpi/tables/tbconvrt.c | 551 + drivers/bus/acpi/tables/tbget.c | 611 + drivers/bus/acpi/tables/tbinstal.c | 534 + drivers/bus/acpi/tables/tbutils.c | 355 + drivers/bus/acpi/tables/tbxface.c | 387 + drivers/bus/acpi/tables/tbxfroot.c | 212 + drivers/bus/acpi/utils/.cvsignore | 5 + drivers/bus/acpi/utils/cmalloc.c | 170 + drivers/bus/acpi/utils/cmclib.c | 815 + drivers/bus/acpi/utils/cmcopy.c | 707 + drivers/bus/acpi/utils/cmdebug.c | 555 + drivers/bus/acpi/utils/cmdelete.c | 589 + drivers/bus/acpi/utils/cmeval.c | 306 + drivers/bus/acpi/utils/cmglobal.c | 482 + drivers/bus/acpi/utils/cminit.c | 247 + drivers/bus/acpi/utils/cmobject.c | 622 + drivers/bus/acpi/utils/cmutils.c | 1006 + drivers/bus/acpi/utils/cmxface.c | 459 + drivers/bus/isapnp/.cvsignore | 8 + drivers/bus/isapnp/isapnp.c | 1718 ++ drivers/bus/isapnp/isapnp.h | 329 + drivers/bus/isapnp/isapnp.rc | 38 + drivers/bus/isapnp/makefile | 13 + drivers/bus/pci/.cvsignore | 4 + drivers/bus/pci/fdo.c | 458 + drivers/bus/pci/makefile | 13 + drivers/bus/pci/pci.c | 613 + drivers/bus/pci/pci.h | 129 + drivers/bus/pci/pci.rc | 38 + drivers/bus/pci/pcidef.h | 315 + drivers/bus/pci/pdo.c | 242 + drivers/dd/beep/.cvsignore | 4 + drivers/dd/beep/beep.c | 285 + drivers/dd/beep/beep.rc | 39 + drivers/dd/beep/makefile | 13 + drivers/dd/blue/.cvsignore | 5 + drivers/dd/blue/blue.c | 634 + drivers/dd/blue/blue.rc | 39 + drivers/dd/blue/makefile | 13 + drivers/dd/floppy/.cvsignore | 2 + drivers/dd/floppy/Makefile | 16 + drivers/dd/floppy/dpc.c | 215 + drivers/dd/floppy/floppy.c | 556 + drivers/dd/floppy/floppy.h | 260 + drivers/dd/floppy/floppy.rc | 39 + drivers/dd/floppy/isr.c | 182 + drivers/dd/ide/.cvsignore | 5 + drivers/dd/ide/ide.c | 2263 ++ drivers/dd/ide/ide.h | 256 + drivers/dd/ide/ide.rc | 39 + drivers/dd/ide/makefile | 17 + drivers/dd/ide/partitio.h | 41 + drivers/dd/mouse/.cvsignore | 1 + drivers/dd/mouse/makefile | 13 + drivers/dd/mouse/mouse.c | 270 + drivers/dd/null/.cvsignore | 7 + drivers/dd/null/makefile | 15 + drivers/dd/null/null.c | 164 + drivers/dd/null/null.h | 19 + drivers/dd/null/null.rc | 39 + drivers/dd/parallel/.cvsignore | 7 + drivers/dd/parallel/makefile | 13 + drivers/dd/parallel/parallel.c | 156 + drivers/dd/parallel/parallel.h | 137 + drivers/dd/parallel/parallel.rc | 39 + drivers/dd/ramdrv/.cvsignore | 7 + drivers/dd/ramdrv/makefile | 21 + drivers/dd/ramdrv/ramdrv.c | 242 + drivers/dd/ramdrv/ramdrv.h | 5 + drivers/dd/sdisk/makefile | 13 + drivers/dd/sdisk/sdisk.c | 162 + drivers/dd/serial/.cvsignore | 8 + drivers/dd/serial/makefile | 13 + drivers/dd/serial/serial.c | 161 + drivers/dd/serial/serial.rc | 39 + drivers/dd/sound/.cvsignore | 7 + drivers/dd/sound/dsp.c | 77 + drivers/dd/sound/dsp.h | 17 + drivers/dd/sound/makefile | 33 + drivers/dd/sound/mixer.c | 49 + drivers/dd/sound/mixer.h | 8 + drivers/dd/sound/sb16.h | 9 + drivers/dd/sound/sb_waveout.c | 3 + drivers/dd/sound/sound.c | 124 + drivers/dd/sound/wave.c | 126 + drivers/dd/sound/wave.h | 24 + drivers/dd/test/.cvsignore | 5 + drivers/dd/test/makefile | 13 + drivers/dd/test/test.c | 107 + drivers/dd/vga/display/.cvsignore | 3 + drivers/dd/vga/display/main/enable.c | 481 + drivers/dd/vga/display/main/gdiinfo.h | 119 + drivers/dd/vga/display/makefile | 40 + drivers/dd/vga/display/objects/bitblt.c | 382 + drivers/dd/vga/display/objects/bitblt.h | 22 + drivers/dd/vga/display/objects/brush.h | 58 + drivers/dd/vga/display/objects/lineto.c | 105 + drivers/dd/vga/display/objects/offscreen.c | 191 + drivers/dd/vga/display/objects/paint.c | 231 + drivers/dd/vga/display/objects/pointer.c | 350 + drivers/dd/vga/display/objects/screen.c | 170 + drivers/dd/vga/display/objects/transblt.c | 34 + drivers/dd/vga/display/vgaddi.def | 11 + drivers/dd/vga/display/vgaddi.edf | 11 + drivers/dd/vga/display/vgaddi.h | 235 + drivers/dd/vga/display/vgaddi.rc | 38 + drivers/dd/vga/display/vgavideo/vgavideo.c | 723 + drivers/dd/vga/display/vgavideo/vgavideo.h | 66 + drivers/dd/vga/makefile | 22 + drivers/dd/vga/miniport/.cvsignore | 6 + drivers/dd/vga/miniport/initvga.c | 128 + drivers/dd/vga/miniport/makefile | 18 + drivers/dd/vga/miniport/vgamp.c | 483 + drivers/dd/vga/miniport/vgamp.rc | 38 + drivers/dd/vga/miniport/vgavideo.c | 94 + drivers/dd/vga/miniport/vgavideo.h | 34 + drivers/dd/vidport/.cvsignore | 2 + drivers/dd/vidport/makefile | 15 + drivers/dd/vidport/vidport.c | 806 + drivers/dd/vidport/vidport.def | 60 + drivers/dd/vidport/vidport.edf | 61 + drivers/dd/vidport/vidport.h | 16 + drivers/dd/vidport/vidport.rc | 39 + drivers/fs/cdfs/.cvsignore | 6 + drivers/fs/cdfs/cdfs.c | 108 + drivers/fs/cdfs/cdfs.h | 398 + drivers/fs/cdfs/cdfs.rc | 39 + drivers/fs/cdfs/cleanup.c | 104 + drivers/fs/cdfs/close.c | 115 + drivers/fs/cdfs/common.c | 257 + drivers/fs/cdfs/create.c | 263 + drivers/fs/cdfs/dirctl.c | 760 + drivers/fs/cdfs/fcb.c | 707 + drivers/fs/cdfs/finfo.c | 437 + drivers/fs/cdfs/fsctl.c | 520 + drivers/fs/cdfs/makefile | 16 + drivers/fs/cdfs/misc.c | 137 + drivers/fs/cdfs/rw.c | 230 + drivers/fs/cdfs/volinfo.c | 243 + drivers/fs/ext2/attr.c | 136 + drivers/fs/ext2/blockdev.c | 155 + drivers/fs/ext2/dir.c | 338 + drivers/fs/ext2/ext2fs.h | 289 + drivers/fs/ext2/ext2fs.rc | 39 + drivers/fs/ext2/file.c | 61 + drivers/fs/ext2/inode.c | 148 + drivers/fs/ext2/makefile | 26 + drivers/fs/ext2/quota.c | 49 + drivers/fs/ext2/rw.c | 219 + drivers/fs/ext2/security.c | 41 + drivers/fs/ext2/super.c | 201 + drivers/fs/fs_rec/.cvsignore | 6 + drivers/fs/fs_rec/blockdev.c | 166 + drivers/fs/fs_rec/cdfs.c | 143 + drivers/fs/fs_rec/fat.c | 141 + drivers/fs/fs_rec/fs_rec.c | 243 + drivers/fs/fs_rec/fs_rec.h | 81 + drivers/fs/fs_rec/fs_rec.rc | 39 + drivers/fs/fs_rec/makefile | 26 + drivers/fs/fs_rec/ntfs.c | 142 + drivers/fs/minix/.cvsignore | 2 + drivers/fs/minix/Makefile | 22 + drivers/fs/minix/bitops.c | 203 + drivers/fs/minix/bitops.h | 30 + drivers/fs/minix/block.c | 109 + drivers/fs/minix/blockdev.c | 154 + drivers/fs/minix/cache.c | 45 + drivers/fs/minix/dir.c | 234 + drivers/fs/minix/inode.c | 136 + drivers/fs/minix/minix.h | 133 + drivers/fs/minix/minix.rc | 39 + drivers/fs/minix/minix_fs.h | 80 + drivers/fs/minix/mount.c | 160 + drivers/fs/minix/rw.c | 162 + drivers/fs/ms/.cvsignore | 2 + drivers/fs/ms/Makefile | 18 + drivers/fs/ms/create.c | 310 + drivers/fs/ms/finfo.c | 198 + drivers/fs/ms/fsctrl.c | 71 + drivers/fs/ms/msfs.c | 79 + drivers/fs/ms/msfs.h | 60 + drivers/fs/ms/msfs.rc | 39 + drivers/fs/ms/rw.c | 175 + drivers/fs/mup/.cvsignore | 6 + drivers/fs/mup/create.c | 71 + drivers/fs/mup/makefile | 15 + drivers/fs/mup/mup.c | 105 + drivers/fs/mup/mup.h | 29 + drivers/fs/mup/mup.rc | 39 + drivers/fs/np/.cvsignore | 6 + drivers/fs/np/Makefile | 19 + drivers/fs/np/create.c | 454 + drivers/fs/np/finfo.c | 205 + drivers/fs/np/fsctrl.c | 513 + drivers/fs/np/npfs.c | 93 + drivers/fs/np/npfs.h | 96 + drivers/fs/np/npfs.rc | 39 + drivers/fs/np/rw.c | 308 + drivers/fs/np/volume.c | 120 + drivers/fs/ntfs/.cvsignore | 6 + drivers/fs/ntfs/attrib.c | 217 + drivers/fs/ntfs/blockdev.c | 255 + drivers/fs/ntfs/create.c | 243 + drivers/fs/ntfs/dirctl.c | 709 + drivers/fs/ntfs/fcb.c | 674 + drivers/fs/ntfs/finfo.c | 268 + drivers/fs/ntfs/fsctl.c | 479 + drivers/fs/ntfs/makefile | 16 + drivers/fs/ntfs/mft.c | 100 + drivers/fs/ntfs/ntfs.c | 104 + drivers/fs/ntfs/ntfs.h | 430 + drivers/fs/ntfs/ntfs.rc | 39 + drivers/fs/ntfs/volinfo.c | 242 + drivers/fs/template/makefile | 15 + drivers/fs/template/template.c | 284 + drivers/fs/vfat/.cvsignore | 6 + drivers/fs/vfat/blockdev.c | 189 + drivers/fs/vfat/cleanup.c | 90 + drivers/fs/vfat/close.c | 115 + drivers/fs/vfat/create.c | 875 + drivers/fs/vfat/dir.c | 416 + drivers/fs/vfat/direntry.c | 206 + drivers/fs/vfat/dirwr.c | 652 + drivers/fs/vfat/ea.c | 47 + drivers/fs/vfat/fat.c | 817 + drivers/fs/vfat/fcb.c | 577 + drivers/fs/vfat/finfo.c | 666 + drivers/fs/vfat/fsctl.c | 436 + drivers/fs/vfat/iface.c | 96 + drivers/fs/vfat/makefile | 42 + drivers/fs/vfat/misc.c | 196 + drivers/fs/vfat/rw.c | 1068 + drivers/fs/vfat/shutdown.c | 56 + drivers/fs/vfat/string.c | 192 + drivers/fs/vfat/vfat.h | 524 + drivers/fs/vfat/vfat005.1st | 12 + drivers/fs/vfat/vfat_fr.txt | 97 + drivers/fs/vfat/vfatfs.def | 1 + drivers/fs/vfat/vfatfs.rc | 39 + drivers/fs/vfat/volume.c | 287 + drivers/input/include/mouse.h | 50 + drivers/input/keyboard/.cvsignore | 2 + drivers/input/keyboard/keyboard.c | 862 + drivers/input/keyboard/keyboard.h | 87 + drivers/input/keyboard/keyboard.rc | 39 + drivers/input/keyboard/makefile | 13 + drivers/input/mouclass/.cvsignore | 2 + drivers/input/mouclass/makefile | 13 + drivers/input/mouclass/mouclass.c | 286 + drivers/input/mouclass/mouclass.h | 7 + drivers/input/mouclass/mouclass.rc | 39 + drivers/input/psaux/.cvsignore | 2 + drivers/input/psaux/controller.c | 156 + drivers/input/psaux/controller.h | 139 + drivers/input/psaux/keyboard.h | 51 + drivers/input/psaux/makefile | 13 + drivers/input/psaux/mouse.c | 233 + drivers/input/psaux/mouse.h | 80 + drivers/input/psaux/psaux.c | 196 + drivers/input/psaux/psaux.h | 12 + drivers/input/psaux/psaux.rc | 39 + drivers/input/sermouse/.cvsignore | 2 + drivers/input/sermouse/makefile | 16 + drivers/input/sermouse/mouse.c | 272 + drivers/input/sermouse/mouse.h | 12 + drivers/input/sermouse/sermouse.c | 373 + drivers/input/sermouse/sermouse.h | 80 + drivers/input/sermouse/sermouse.rc | 39 + drivers/lib/bzip2/CHANGES | 167 + drivers/lib/bzip2/LICENSE | 39 + drivers/lib/bzip2/Makefile | 18 + drivers/lib/bzip2/Makefile-libbz2_so | 43 + drivers/lib/bzip2/README | 166 + drivers/lib/bzip2/README.COMPILATION.PROBLEMS | 130 + drivers/lib/bzip2/README.reactos | 8 + drivers/lib/bzip2/Y2K_INFO | 34 + drivers/lib/bzip2/blocksort.c | 1134 + drivers/lib/bzip2/bzip2.1 | 439 + drivers/lib/bzip2/bzip2.1.preformatted | 462 + drivers/lib/bzip2/bzip2.c | 2044 ++ drivers/lib/bzip2/bzip2.txt | 376 + drivers/lib/bzip2/bzip2recover.c | 435 + drivers/lib/bzip2/bzlib.c | 1579 + drivers/lib/bzip2/bzlib.h | 323 + drivers/lib/bzip2/bzlib_private.h | 530 + drivers/lib/bzip2/compress.c | 714 + drivers/lib/bzip2/crctable.c | 144 + drivers/lib/bzip2/decompress.c | 660 + drivers/lib/bzip2/dllmain.c | 16 + drivers/lib/bzip2/dlltest.c | 176 + drivers/lib/bzip2/dlltest.dsp | 93 + drivers/lib/bzip2/huffman.c | 228 + drivers/lib/bzip2/libbz2.def | 27 + drivers/lib/bzip2/libbz2.dsp | 130 + drivers/lib/bzip2/makefile.msc | 63 + drivers/lib/bzip2/manual.ps | 3808 +++ drivers/lib/bzip2/manual.texi | 2215 ++ drivers/lib/bzip2/manual_1.html | 47 + drivers/lib/bzip2/manual_2.html | 484 + drivers/lib/bzip2/manual_3.html | 1773 ++ drivers/lib/bzip2/manual_4.html | 528 + drivers/lib/bzip2/manual_toc.html | 173 + drivers/lib/bzip2/randtable.c | 124 + drivers/lib/bzip2/sample1.ref | Bin 0 -> 308 bytes drivers/lib/bzip2/sample2.ref | Bin 0 -> 7027 bytes drivers/lib/bzip2/sample3.ref | 30007 +++++++++++++++++++ drivers/lib/bzip2/spewG.c | 39 + drivers/lib/bzip2/unbzip2.def | 4 + drivers/lib/bzip2/unbzip2.edf | 5 + drivers/lib/bzip2/unzcrash.c | 126 + drivers/lib/bzip2/words0 | 5 + drivers/lib/bzip2/words1 | 4 + drivers/lib/bzip2/words2 | 5 + drivers/lib/bzip2/words3 | 23 + drivers/lib/zlib/.cvsignore | 1 + drivers/lib/zlib/ChangeLog | 481 + drivers/lib/zlib/FAQ | 100 + drivers/lib/zlib/INDEX | 86 + drivers/lib/zlib/Make_vms.com | 115 + drivers/lib/zlib/Makefile | 29 + drivers/lib/zlib/Makefile.in | 175 + drivers/lib/zlib/Makefile.riscos | 151 + drivers/lib/zlib/README | 147 + drivers/lib/zlib/adler32.c | 48 + drivers/lib/zlib/algorithm.txt | 213 + drivers/lib/zlib/amiga/Makefile.pup | 66 + drivers/lib/zlib/amiga/Makefile.sas | 64 + drivers/lib/zlib/compress.c | 68 + drivers/lib/zlib/configure | 212 + drivers/lib/zlib/contrib/README.contrib | 34 + drivers/lib/zlib/contrib/asm386/gvmat32.asm | 559 + drivers/lib/zlib/contrib/asm386/gvmat32c.c | 200 + drivers/lib/zlib/contrib/asm386/mkgvmt32.bat | 1 + drivers/lib/zlib/contrib/asm386/zlibvc.def | 74 + drivers/lib/zlib/contrib/asm386/zlibvc.dsp | 651 + drivers/lib/zlib/contrib/asm386/zlibvc.dsw | 41 + drivers/lib/zlib/contrib/asm586/README.586 | 43 + drivers/lib/zlib/contrib/asm586/match.S | 354 + drivers/lib/zlib/contrib/asm686/README.686 | 34 + drivers/lib/zlib/contrib/asm686/match.S | 327 + drivers/lib/zlib/contrib/delphi/zlib.mak | 36 + drivers/lib/zlib/contrib/delphi/zlibdef.pas | 169 + drivers/lib/zlib/contrib/delphi2/d_zlib.bpr | 224 + drivers/lib/zlib/contrib/delphi2/d_zlib.cpp | 17 + drivers/lib/zlib/contrib/delphi2/readme.txt | 17 + drivers/lib/zlib/contrib/delphi2/zlib.bpg | 26 + drivers/lib/zlib/contrib/delphi2/zlib.bpr | 225 + drivers/lib/zlib/contrib/delphi2/zlib.cpp | 22 + drivers/lib/zlib/contrib/delphi2/zlib.pas | 534 + drivers/lib/zlib/contrib/delphi2/zlib32.bpr | 174 + drivers/lib/zlib/contrib/delphi2/zlib32.cpp | 42 + drivers/lib/zlib/contrib/iostream/test.cpp | 24 + drivers/lib/zlib/contrib/iostream/zfstream.cpp | 329 + drivers/lib/zlib/contrib/iostream/zfstream.h | 142 + drivers/lib/zlib/contrib/iostream2/zstream.h | 307 + .../lib/zlib/contrib/iostream2/zstream_test.cpp | 25 + drivers/lib/zlib/contrib/minizip/ChangeLogUnzip | 38 + drivers/lib/zlib/contrib/minizip/Makefile | 25 + drivers/lib/zlib/contrib/minizip/miniunz.c | 508 + drivers/lib/zlib/contrib/minizip/minizip.c | 302 + drivers/lib/zlib/contrib/minizip/readme.txt | 37 + drivers/lib/zlib/contrib/minizip/unzip.c | 1294 + drivers/lib/zlib/contrib/minizip/unzip.def | 15 + drivers/lib/zlib/contrib/minizip/unzip.h | 275 + drivers/lib/zlib/contrib/minizip/zip.c | 718 + drivers/lib/zlib/contrib/minizip/zip.def | 5 + drivers/lib/zlib/contrib/minizip/zip.h | 150 + drivers/lib/zlib/contrib/minizip/zlibvc.def | 74 + drivers/lib/zlib/contrib/minizip/zlibvc.dsp | 651 + drivers/lib/zlib/contrib/minizip/zlibvc.dsw | 41 + drivers/lib/zlib/contrib/untgz/Makefile | 14 + drivers/lib/zlib/contrib/untgz/makefile.w32 | 63 + drivers/lib/zlib/contrib/untgz/untgz.c | 522 + drivers/lib/zlib/contrib/visual-basic.txt | 69 + drivers/lib/zlib/crc32.c | 162 + drivers/lib/zlib/deflate.c | 1350 + drivers/lib/zlib/deflate.h | 318 + drivers/lib/zlib/descrip.mms | 48 + drivers/lib/zlib/example.c | 556 + drivers/lib/zlib/gzio.c | 875 + drivers/lib/zlib/infblock.c | 403 + drivers/lib/zlib/infblock.h | 39 + drivers/lib/zlib/infcodes.c | 251 + drivers/lib/zlib/infcodes.h | 27 + drivers/lib/zlib/inffast.c | 183 + drivers/lib/zlib/inffast.h | 17 + drivers/lib/zlib/inffixed.h | 151 + drivers/lib/zlib/inflate.c | 366 + drivers/lib/zlib/inftrees.c | 454 + drivers/lib/zlib/inftrees.h | 58 + drivers/lib/zlib/infutil.c | 87 + drivers/lib/zlib/infutil.h | 98 + drivers/lib/zlib/makefile.reactos | 26 + drivers/lib/zlib/maketree.c | 85 + drivers/lib/zlib/minigzip.c | 320 + drivers/lib/zlib/msdos/Makefile.b32 | 104 + drivers/lib/zlib/msdos/Makefile.bor | 125 + drivers/lib/zlib/msdos/Makefile.dj2 | 100 + drivers/lib/zlib/msdos/Makefile.emx | 69 + drivers/lib/zlib/msdos/Makefile.msc | 121 + drivers/lib/zlib/msdos/Makefile.tc | 108 + drivers/lib/zlib/msdos/Makefile.w32 | 97 + drivers/lib/zlib/msdos/Makefile.wat | 103 + drivers/lib/zlib/msdos/zlib.def | 60 + drivers/lib/zlib/msdos/zlib.rc | 32 + drivers/lib/zlib/nt/Makefile.emx | 138 + drivers/lib/zlib/nt/Makefile.gcc | 87 + drivers/lib/zlib/nt/Makefile.nt | 88 + drivers/lib/zlib/nt/zlib.dnt | 47 + drivers/lib/zlib/os2/Makefile.os2 | 136 + drivers/lib/zlib/os2/zlib.def | 51 + drivers/lib/zlib/trees.c | 1214 + drivers/lib/zlib/trees.h | 128 + drivers/lib/zlib/uncompr.c | 58 + drivers/lib/zlib/zconf.h | 279 + drivers/lib/zlib/zlib.3 | 107 + drivers/lib/zlib/zlib.h | 893 + drivers/lib/zlib/zlib.html | 971 + drivers/lib/zlib/zutil.c | 225 + drivers/lib/zlib/zutil.h | 220 + drivers/net/afd/.cvsignore | 1 + drivers/net/afd/afd.def | 7 + drivers/net/afd/afd.rc | 38 + drivers/net/afd/afd/afd.c | 202 + drivers/net/afd/afd/dispatch.c | 843 + drivers/net/afd/afd/event.c | 272 + drivers/net/afd/afd/opnclose.c | 263 + drivers/net/afd/afd/rdwr.c | 119 + drivers/net/afd/afd/routines.c | 241 + drivers/net/afd/afd/tdi.c | 1210 + drivers/net/afd/include/afd.h | 409 + drivers/net/afd/include/debug.h | 97 + drivers/net/afd/makefile | 22 + drivers/net/dd/ne2000/.cvsignore | 4 + drivers/net/dd/ne2000/Makefile | 19 + drivers/net/dd/ne2000/include/8390.h | 161 + drivers/net/dd/ne2000/include/debug.h | 92 + drivers/net/dd/ne2000/include/ne2000.h | 250 + drivers/net/dd/ne2000/ne2000.rc | 38 + drivers/net/dd/ne2000/ne2000/8390.c | 1367 + drivers/net/dd/ne2000/ne2000/main.c | 812 + drivers/net/ndis/.cvsignore | 5 + drivers/net/ndis/DIRS | 1 + drivers/net/ndis/Makefile | 31 + drivers/net/ndis/include/buffer.h | 56 + drivers/net/ndis/include/debug.h | 95 + drivers/net/ndis/include/miniport.h | 133 + drivers/net/ndis/include/ndissys.h | 101 + drivers/net/ndis/include/protocol.h | 53 + drivers/net/ndis/ndis.def | 316 + drivers/net/ndis/ndis.edf | 316 + drivers/net/ndis/ndis.rc | 38 + drivers/net/ndis/ndis/40gone.c | 749 + drivers/net/ndis/ndis/50gone.c | 408 + drivers/net/ndis/ndis/SOURCES | 29 + drivers/net/ndis/ndis/buffer.c | 1033 + drivers/net/ndis/ndis/cl.c | 202 + drivers/net/ndis/ndis/cm.c | 418 + drivers/net/ndis/ndis/co.c | 226 + drivers/net/ndis/ndis/control.c | 197 + drivers/net/ndis/ndis/hardware.c | 134 + drivers/net/ndis/ndis/io.c | 467 + drivers/net/ndis/ndis/main.c | 71 + drivers/net/ndis/ndis/memory.c | 229 + drivers/net/ndis/ndis/miniport.c | 1336 + drivers/net/ndis/ndis/protocol.c | 629 + drivers/net/ndis/ndis/string.c | 149 + drivers/net/ndis/ndis/stubs.c | 1023 + drivers/net/ndis/ndis/time.c | 86 + drivers/net/ndis/readme.txt | 18 + drivers/net/packet/.cvsignore | 5 + drivers/net/packet/Makefile | 41 + drivers/net/packet/bucket_lookup.c | 251 + drivers/net/packet/bucket_lookup.h | 43 + drivers/net/packet/count_packets.c | 51 + drivers/net/packet/count_packets.h | 51 + drivers/net/packet/debug.h | 52 + drivers/net/packet/dump.c | 587 + drivers/net/packet/functions.c | 82 + drivers/net/packet/functions.h | 67 + drivers/net/packet/jitter.c | 677 + drivers/net/packet/jitter.h | 391 + drivers/net/packet/memory_t.c | 65 + drivers/net/packet/memory_t.h | 119 + drivers/net/packet/normal_lookup.c | 191 + drivers/net/packet/normal_lookup.h | 45 + drivers/net/packet/ntddpack.h | 30 + drivers/net/packet/openclos.c | 634 + drivers/net/packet/packet.c | 1332 + drivers/net/packet/packet.def | 8 + drivers/net/packet/packet.edf | 8 + drivers/net/packet/packet.h | 957 + drivers/net/packet/packet.rc | 47 + drivers/net/packet/read.c | 664 + drivers/net/packet/resource.h | 15 + drivers/net/packet/tcp_session.c | 283 + drivers/net/packet/tcp_session.h | 85 + drivers/net/packet/time_calls.c | 236 + drivers/net/packet/time_calls.h | 262 + drivers/net/packet/tme.c | 378 + drivers/net/packet/tme.h | 182 + drivers/net/packet/valid_insns.h | 73 + drivers/net/packet/win_bpf.h | 325 + drivers/net/packet/win_bpf_filter.c | 961 + drivers/net/packet/win_bpf_filter_init.c | 569 + drivers/net/packet/win_bpf_filter_init.h | 31 + drivers/net/packet/write.c | 332 + drivers/net/tcpip/.cvsignore | 5 + drivers/net/tcpip/DIRS | 5 + drivers/net/tcpip/datalink/Makefile | 7 + drivers/net/tcpip/datalink/SOURCES | 13 + drivers/net/tcpip/datalink/arp.c | 284 + drivers/net/tcpip/datalink/lan.c | 994 + drivers/net/tcpip/datalink/loopback.c | 214 + drivers/net/tcpip/include/address.h | 78 + drivers/net/tcpip/include/arp.h | 37 + drivers/net/tcpip/include/checksum.h | 27 + drivers/net/tcpip/include/datagram.h | 59 + drivers/net/tcpip/include/debug.h | 106 + drivers/net/tcpip/include/dispatch.h | 61 + drivers/net/tcpip/include/fileobjs.h | 41 + drivers/net/tcpip/include/icmp.h | 68 + drivers/net/tcpip/include/info.h | 93 + drivers/net/tcpip/include/ip.h | 266 + drivers/net/tcpip/include/lan.h | 98 + drivers/net/tcpip/include/loopback.h | 25 + drivers/net/tcpip/include/neighbor.h | 103 + drivers/net/tcpip/include/pool.h | 19 + drivers/net/tcpip/include/rawip.h | 28 + drivers/net/tcpip/include/receive.h | 64 + drivers/net/tcpip/include/route.h | 80 + drivers/net/tcpip/include/router.h | 63 + drivers/net/tcpip/include/routines.h | 78 + drivers/net/tcpip/include/tcp.h | 112 + drivers/net/tcpip/include/tcpip.h | 131 + drivers/net/tcpip/include/ticonsts.h | 56 + drivers/net/tcpip/include/titypes.h | 372 + drivers/net/tcpip/include/transmit.h | 47 + drivers/net/tcpip/include/udp.h | 68 + drivers/net/tcpip/makefile | 45 + drivers/net/tcpip/network/Makefile | 7 + drivers/net/tcpip/network/SOURCES | 20 + drivers/net/tcpip/network/icmp.c | 310 + drivers/net/tcpip/network/ip.c | 1164 + drivers/net/tcpip/network/neighbor.c | 518 + drivers/net/tcpip/network/receive.c | 640 + drivers/net/tcpip/network/route.c | 702 + drivers/net/tcpip/network/router.c | 541 + drivers/net/tcpip/network/transmit.c | 342 + drivers/net/tcpip/readme.txt | 19 + drivers/net/tcpip/tcpip.def | 32 + drivers/net/tcpip/tcpip.edf | 32 + drivers/net/tcpip/tcpip.rc | 38 + drivers/net/tcpip/tcpip/Makefile | 7 + drivers/net/tcpip/tcpip/SOURCES | 28 + drivers/net/tcpip/tcpip/address.c | 417 + drivers/net/tcpip/tcpip/checksum.c | 50 + drivers/net/tcpip/tcpip/dispatch.c | 1051 + drivers/net/tcpip/tcpip/fileobjs.c | 556 + drivers/net/tcpip/tcpip/info.c | 339 + drivers/net/tcpip/tcpip/main.c | 924 + drivers/net/tcpip/tcpip/pool.c | 50 + drivers/net/tcpip/tcpip/resource.rc | 10 + drivers/net/tcpip/tcpip/routines.c | 533 + drivers/net/tcpip/tcpip/tcpip.def | 32 + drivers/net/tcpip/transport/DIRS | 5 + drivers/net/tcpip/transport/datagram/Makefile | 7 + drivers/net/tcpip/transport/datagram/SOURCES | 13 + drivers/net/tcpip/transport/datagram/datagram.c | 681 + drivers/net/tcpip/transport/rawip/Makefile | 7 + drivers/net/tcpip/transport/rawip/SOURCES | 13 + drivers/net/tcpip/transport/rawip/rawip.c | 222 + drivers/net/tcpip/transport/tcp/Makefile | 7 + drivers/net/tcpip/transport/tcp/SOURCES | 13 + drivers/net/tcpip/transport/tcp/tcp.c | 498 + drivers/net/tcpip/transport/udp/Makefile | 7 + drivers/net/tcpip/transport/udp/SOURCES | 12 + drivers/net/tcpip/transport/udp/udp.c | 360 + drivers/net/tdi/Makefile | 41 + drivers/net/tdi/cte/string.c | 28 + drivers/net/tdi/cte/stubs.c | 121 + drivers/net/tdi/misc/.cvsignore | 1 + drivers/net/tdi/misc/main.c | 19 + drivers/net/tdi/misc/tdi.def | 47 + drivers/net/tdi/misc/tdi.edf | 47 + drivers/net/tdi/misc/tdi.rc | 39 + drivers/net/tdi/tdi/dereg.c | 170 + drivers/net/tdi/tdi/handler.c | 181 + drivers/net/tdi/tdi/obsolete.c | 27 + drivers/net/tdi/tdi/stubs.c | 104 + drivers/net/tditest/.cvsignore | 5 + drivers/net/tditest/DIRS | 1 + drivers/net/tditest/include/debug.h | 90 + drivers/net/tditest/include/tditest.h | 131 + drivers/net/tditest/makefile | 19 + drivers/net/tditest/readme.txt | 18 + drivers/net/tditest/tditest.def | 7 + drivers/net/tditest/tditest.rc | 38 + drivers/net/tditest/tditest/Makefile | 8 + drivers/net/tditest/tditest/SOURCES | 14 + drivers/net/tditest/tditest/tditest.c | 953 + drivers/net/wshtcpip/.cvsignore | 10 + drivers/net/wshtcpip/debug.h | 65 + drivers/net/wshtcpip/makefile | 19 + drivers/net/wshtcpip/wshtcpip.c | 397 + drivers/net/wshtcpip/wshtcpip.def | 23 + drivers/net/wshtcpip/wshtcpip.edf | 23 + drivers/net/wshtcpip/wshtcpip.h | 33 + drivers/net/wshtcpip/wshtcpip.rc | 39 + drivers/net/wshtcpip/wshtcpip_specs | 78 + drivers/readme | 11 + drivers/storage/atapi/.cvsignore | 5 + drivers/storage/atapi/atapi.c | 2146 ++ drivers/storage/atapi/atapi.h | 177 + drivers/storage/atapi/atapi.rc | 39 + drivers/storage/atapi/makefile | 17 + drivers/storage/cdrom/.cvsignore | 5 + drivers/storage/cdrom/cdrom.c | 769 + drivers/storage/cdrom/cdrom.rc | 39 + drivers/storage/cdrom/makefile | 17 + drivers/storage/class2/.cvsignore | 5 + drivers/storage/class2/class2.c | 1687 ++ drivers/storage/class2/class2.def | 29 + drivers/storage/class2/class2.edf | 29 + drivers/storage/class2/class2.rc | 38 + drivers/storage/class2/makefile | 13 + drivers/storage/disk/.cvsignore | 5 + drivers/storage/disk/disk.c | 1011 + drivers/storage/disk/disk.h | 250 + drivers/storage/disk/disk.rc | 39 + drivers/storage/disk/makefile | 17 + drivers/storage/disk/partitio.h | 41 + drivers/storage/scsiport/.cvsignore | 5 + drivers/storage/scsiport/makefile | 13 + drivers/storage/scsiport/scsiport.c | 1616 + drivers/storage/scsiport/scsiport.def | 52 + drivers/storage/scsiport/scsiport.edf | 52 + drivers/storage/scsiport/scsiport.rc | 38 + gdb.ini | 4 + hal/hal/.cvsignore | 7 + hal/hal/Makefile | 23 + hal/hal/hal.c | 975 + hal/hal/hal.def | 100 + hal/hal/hal.edf | 100 + hal/hal/hal.rc | 37 + hal/halx86/.cvsignore | 7 + hal/halx86/Makefile | 100 + hal/halx86/adapter.c | 154 + hal/halx86/beep.c | 77 + hal/halx86/bios32.c | 144 + hal/halx86/bus.c | 525 + hal/halx86/display.c | 302 + hal/halx86/dma.c | 115 + hal/halx86/drive.c | 31 + hal/halx86/enum.c | 25 + hal/halx86/fmutex.c | 53 + hal/halx86/halinit.c | 71 + hal/halx86/halx86mp.rc | 37 + hal/halx86/halx86up.rc | 37 + hal/halx86/include/bus.h | 125 + hal/halx86/include/hal.h | 48 + hal/halx86/include/mps.h | 435 + hal/halx86/irql.c | 387 + hal/halx86/isa.c | 62 + hal/halx86/kdbg.c | 533 + hal/halx86/mbr.c | 25 + hal/halx86/mca.c | 82 + hal/halx86/misc.c | 105 + hal/halx86/mp.c | 2367 ++ hal/halx86/mps.S | 76 + hal/halx86/mpsboot.asm | 106 + hal/halx86/mpsirql.c | 416 + hal/halx86/pci.c | 509 + hal/halx86/perfcnt.c | 62 + hal/halx86/portio.c | 182 + hal/halx86/pwroff.c | 114 + hal/halx86/reboot.c | 74 + hal/halx86/spinlock.c | 95 + hal/halx86/sysbus.c | 64 + hal/halx86/sysinfo.c | 23 + hal/halx86/time.c | 307 + hal/halx86/udelay.c | 223 + iface/addsys/.cvsignore | 3 + iface/addsys/genw32k.c | 379 + iface/addsys/makefile | 51 + iface/addsys/w32ksvc.db | 544 + iface/dll/.cvsignore | 2 + iface/dll/defedf.c | 315 + iface/dll/makefile | 24 + iface/native/.cvsignore | 2 + iface/native/genntdll.c | 370 + iface/native/makefile | 40 + iface/native/sysfuncs.lst | 211 + include/.cvsignore | 1 + include/afd/shared.h | 199 + include/ascii.h | 2997 ++ include/base.h | 493 + include/coff.h | 339 + include/crtdll/alloc.h | 77 + include/crtdll/assert.h | 69 + include/crtdll/conio.h | 67 + include/crtdll/crtdll.h | 1 + include/crtdll/ctype.h | 142 + include/crtdll/dir.h | 103 + include/crtdll/direct.h | 27 + include/crtdll/dirent.h | 61 + include/crtdll/dos.h | 158 + include/crtdll/errno.h | 134 + include/crtdll/excpt.h | 121 + include/crtdll/fcntl.h | 125 + include/crtdll/float.h | 199 + include/crtdll/internal/atexit.h | 33 + include/crtdll/internal/file.h | 93 + include/crtdll/internal/ieee.h | 25 + include/crtdll/internal/quad.h | 131 + include/crtdll/io.h | 140 + include/crtdll/locale.h | 84 + include/crtdll/malloc.h | 53 + include/crtdll/math.h | 161 + include/crtdll/mbctype.h | 47 + include/crtdll/mbstring.h | 108 + include/crtdll/process.h | 160 + include/crtdll/search.h | 35 + include/crtdll/setjmp.h | 46 + include/crtdll/share.h | 17 + include/crtdll/signal.h | 111 + include/crtdll/stdarg.h | 107 + include/crtdll/stddef.h | 173 + include/crtdll/stdio.h | 357 + include/crtdll/stdlib.h | 210 + include/crtdll/string.h | 192 + include/crtdll/sys/fcntl.h | 8 + include/crtdll/sys/file.h | 9 + include/crtdll/sys/locking.h | 38 + include/crtdll/sys/stat.h | 113 + include/crtdll/sys/time.h | 3 + include/crtdll/sys/timeb.h | 60 + include/crtdll/sys/types.h | 77 + include/crtdll/sys/unistd.h | 9 + include/crtdll/sys/utime.h | 75 + include/crtdll/tchar.h | 231 + include/crtdll/time.h | 119 + include/crtdll/wchar.h | 32 + include/csrss/csrss.h | 440 + include/ddk/ccfuncs.h | 328 + include/ddk/cctypes.h | 86 + include/ddk/class2.h | 216 + include/ddk/cmfuncs.h | 47 + include/ddk/cmtypes.h | 100 + include/ddk/dbgfuncs.h | 23 + include/ddk/defines.h | 234 + include/ddk/exfuncs.h | 912 + include/ddk/extypes.h | 238 + include/ddk/fsfuncs.h | 612 + include/ddk/fstypes.h | 96 + include/ddk/halfuncs.h | 309 + include/ddk/haltypes.h | 448 + include/ddk/i386/irql.h | 7 + include/ddk/i386/pagesize.h | 6 + include/ddk/i386/tss.h | 57 + include/ddk/ioctrl.h | 23 + include/ddk/iodef.h | 393 + include/ddk/iofuncs.h | 1229 + include/ddk/iotypes.h | 854 + include/ddk/kdfuncs.h | 99 + include/ddk/kedef.h | 66 + include/ddk/kefuncs.h | 493 + include/ddk/ketypes.h | 288 + include/ddk/ldrfuncs.h | 17 + include/ddk/ldrtypes.h | 17 + include/ddk/miniport.h | 25 + include/ddk/mmfuncs.h | 553 + include/ddk/mmtypes.h | 88 + include/ddk/ntdd8042.h | 98 + include/ddk/ntddbeep.h | 50 + include/ddk/ntddblue.h | 64 + include/ddk/ntddk.h | 90 + include/ddk/ntddkbd.h | 19 + include/ddk/ntddscsi.h | 92 + include/ddk/ntddser.h | 455 + include/ddk/ntddvid.h | 453 + include/ddk/ntdef.h | 13 + include/ddk/ntifs.h | 41 + include/ddk/obfuncs.h | 180 + include/ddk/obtypes.h | 199 + include/ddk/pnpfuncs.h | 176 + include/ddk/pnptypes.h | 194 + include/ddk/pofuncs.h | 61 + include/ddk/potypes.h | 101 + include/ddk/psfuncs.h | 98 + include/ddk/pstypes.h | 57 + include/ddk/rtl.h | 2183 ++ include/ddk/rtltypes.h | 214 + include/ddk/scsi.h | 1306 + include/ddk/sefuncs.h | 152 + include/ddk/service.h | 60 + include/ddk/setypes.h | 164 + include/ddk/srb.h | 534 + include/ddk/status.h | 713 + include/ddk/structs.h | 10 + include/ddk/types.h | 32 + include/ddk/winddi.h | 1366 + include/ddk/zw.h | 5308 ++++ include/ddk/zwtypes.h | 1662 + include/debug.h | 98 + include/defines.h | 4727 +++ include/devices.h | 16 + include/dflat32/classdef.h | 31 + include/dflat32/classes.h | 56 + include/dflat32/commands.h | 121 + include/dflat32/config.h | 48 + include/dflat32/dflat.h | 487 + include/dflat32/dflatmsg.h | 100 + include/dflat32/dialbox.h | 55 + include/dflat32/htree.h | 31 + include/dflat32/keys.h | 119 + include/dflat32/menu.h | 63 + include/dflat32/rect.h | 24 + include/dflat32/system.h | 99 + include/dflat32/video.h | 18 + include/errors.h | 1163 + include/excpt.h | 121 + include/fmifs.h | 129 + include/freetype/config/ftconfig.h | 187 + include/freetype/config/ftmodule.h | 10 + include/freetype/config/ftoption.h | 395 + include/freetype/freetype.h | 2286 ++ include/freetype/ftbbox.h | 72 + include/freetype/fterrors.h | 166 + include/freetype/ftglyph.h | 422 + include/freetype/ftimage.h | 1003 + include/freetype/ftmm.h | 175 + include/freetype/ftmodule.h | 274 + include/freetype/ftnames.h | 52 + include/freetype/ftoutln.h | 344 + include/freetype/ftrender.h | 191 + include/freetype/ftsystem.h | 101 + include/freetype/fttypes.h | 400 + include/freetype/internal/autohint.h | 195 + include/freetype/internal/ftcalc.h | 123 + include/freetype/internal/ftdebug.h | 225 + include/freetype/internal/ftdriver.h | 182 + include/freetype/internal/ftextend.h | 178 + include/freetype/internal/ftlist.h | 113 + include/freetype/internal/ftmemory.h | 127 + include/freetype/internal/ftobjs.h | 532 + include/freetype/internal/ftstream.h | 361 + include/freetype/internal/psnames.h | 220 + include/freetype/internal/sfnt.h | 492 + include/freetype/internal/t1errors.h | 67 + include/freetype/internal/t1types.h | 188 + include/freetype/internal/t2errors.h | 121 + include/freetype/internal/t2types.h | 218 + include/freetype/internal/tterrors.h | 121 + include/freetype/internal/tttypes.h | 1582 + include/freetype/t1tables.h | 235 + include/freetype/ttnameid.h | 698 + include/freetype/tttables.h | 583 + include/freetype/tttags.h | 66 + include/funcs.h | 7594 +++++ include/getopt.h | 53 + include/in.h | 491 + include/kernel32/cptable.h | 127 + include/kernel32/error.h | 12 + include/kernel32/heap.h | 108 + include/kernel32/kernel32.h | 45 + include/kernel32/lctable.h | 36 + include/kernel32/nls.h | 26 + include/kernel32/proc.h | 23 + include/kernel32/process.h | 63 + include/kernel32/thread.h | 15 + include/kernel32/winnls.h | 427 + include/libc/atexit.h | 33 + include/libc/file.h | 56 + include/libc/ieee.h | 46 + include/lsass/lsass.h | 130 + include/lsass/ntsecapi.h | 32 + include/messages.h | 1099 + include/msvcrt/alloc.h | 85 + include/msvcrt/assert.h | 69 + include/msvcrt/conio.h | 67 + include/msvcrt/ctype.h | 139 + include/msvcrt/dir.h | 148 + include/msvcrt/direct.h | 46 + include/msvcrt/errno.h | 120 + include/msvcrt/fcntl.h | 127 + include/msvcrt/float.h | 199 + include/msvcrt/internal/atexit.h | 33 + include/msvcrt/internal/console.h | 12 + include/msvcrt/internal/file.h | 96 + include/msvcrt/internal/ieee.h | 25 + include/msvcrt/internal/rterror.h | 29 + include/msvcrt/internal/stdio.h | 12 + include/msvcrt/internal/tls.h | 38 + include/msvcrt/io.h | 155 + include/msvcrt/locale.h | 84 + include/msvcrt/malloc.h | 53 + include/msvcrt/math.h | 161 + include/msvcrt/mbctype.h | 49 + include/msvcrt/mbstring.h | 108 + include/msvcrt/msvcrtdbg.h | 43 + include/msvcrt/process.h | 160 + include/msvcrt/search.h | 35 + include/msvcrt/share.h | 17 + include/msvcrt/signal.h | 111 + include/msvcrt/stdarg.h | 114 + include/msvcrt/stddef.h | 174 + include/msvcrt/stdio.h | 375 + include/msvcrt/stdlib.h | 232 + include/msvcrt/string.h | 194 + include/msvcrt/sys/fcntl.h | 8 + include/msvcrt/sys/file.h | 9 + include/msvcrt/sys/locking.h | 38 + include/msvcrt/sys/stat.h | 142 + include/msvcrt/sys/time.h | 3 + include/msvcrt/sys/timeb.h | 60 + include/msvcrt/sys/types.h | 82 + include/msvcrt/sys/unistd.h | 9 + include/msvcrt/sys/utime.h | 75 + include/msvcrt/time.h | 126 + include/msvcrt/wchar.h | 32 + include/napi/core.h | 35 + include/napi/dbg.h | 63 + include/napi/i386/segment.h | 353 + include/napi/lpc.h | 197 + include/napi/npipe.h | 196 + include/napi/shared_data.h | 68 + include/napi/teb.h | 233 + include/napi/types.h | 108 + include/napi/win32.h | 24 + include/net/miniport.h | 849 + include/net/ndis.h | 5610 ++++ include/net/ndisoid.h | 410 + include/net/netevent.h | 16 + include/net/ntddndis.h | 35 + include/net/tdi.h | 644 + include/net/tdiinfo.h | 96 + include/net/tdikrnl.h | 804 + include/ntddk.h | 5 + include/ntdll/.cvsignore | 1 + include/ntdll/base.h | 1 + include/ntdll/csr.h | 38 + include/ntdll/dbg.h | 39 + include/ntdll/ldr.h | 135 + include/ntdll/ntdll.h | 28 + include/ntdll/pagesize.h | 7 + include/ntdll/registry.h | 6 + include/ntdll/rtl.h | 616 + include/ntdll/trace.h | 18 + include/ntos.h | 75 + include/ntos/cdrom.h | 44 + include/ntos/console.h | 54 + include/ntos/disk.h | 160 + include/ntos/except.h | 145 + include/ntos/file.h | 116 + include/ntos/gditypes.h | 91 + include/ntos/heap.h | 24 + include/ntos/kdbgsyms.h | 46 + include/ntos/keyboard.h | 213 + include/ntos/minmax.h | 7 + include/ntos/mm.h | 63 + include/ntos/ntdef.h | 29 + include/ntos/port.h | 23 + include/ntos/ps.h | 78 + include/ntos/registry.h | 55 + include/ntos/security.h | 344 + include/ntos/synch.h | 32 + include/ntos/time.h | 40 + include/ntos/types.h | 432 + include/ole32/basetyps.h | 37 + include/ole32/guiddef.h | 183 + include/ole32/obj_base.h | 680 + include/ole32/obj_cache.h | 116 + include/ole32/obj_channel.h | 181 + include/ole32/obj_clientserver.h | 258 + include/ole32/obj_commdlgbrowser.h | 43 + include/ole32/obj_connection.h | 145 + include/ole32/obj_contextmenu.h | 125 + include/ole32/obj_control.h | 458 + include/ole32/obj_dataobject.h | 323 + include/ole32/obj_dockingwindowframe.h | 45 + include/ole32/obj_dragdrop.h | 91 + include/ole32/obj_enumidlist.h | 45 + include/ole32/obj_errorinfo.h | 94 + include/ole32/obj_extracticon.h | 51 + include/ole32/obj_inplace.h | 482 + include/ole32/obj_marshal.h | 111 + include/ole32/obj_misc.h | 192 + include/ole32/obj_moniker.h | 350 + include/ole32/obj_oleaut.h | 824 + include/ole32/obj_olefont.h | 119 + include/ole32/obj_oleobj.h | 196 + include/ole32/obj_oleundo.h | 289 + include/ole32/obj_oleview.h | 94 + include/ole32/obj_picture.h | 108 + include/ole32/obj_property.h | 413 + include/ole32/obj_propertystorage.h | 438 + include/ole32/obj_queryassociations.h | 94 + include/ole32/obj_serviceprovider.h | 47 + include/ole32/obj_shellbrowser.h | 99 + include/ole32/obj_shellextinit.h | 34 + include/ole32/obj_shellfolder.h | 356 + include/ole32/obj_shelllink.h | 146 + include/ole32/obj_shellview.h | 159 + include/ole32/obj_storage.h | 650 + include/ole32/obj_webbrowser.h | 100 + include/ole32/objbase.h | 122 + include/ole32/ole32.h | 45 + include/ole32/olectl.h | 34 + include/ole32/rpc.h | 45 + include/ole32/rpcdce.h | 14 + include/ole32/rpcdcep.h | 30 + include/ole32/unknwn.h | 37 + include/ole32/winerror.h | 59 + include/ole32/wtypes.h | 208 + include/pe.h | 1065 + include/reactos/.cvsignore | 2 + include/reactos/config.h | 39 + include/reactos/resource.h | 36 + include/reactos/version.h | 29 + include/services/services.h | 5 + include/services/services.idl | 16 + include/snmp.h | 290 + include/sockets.h | 965 + include/structs.h | 4463 +++ include/tchar.h | 231 + include/unicode.h | 3030 ++ include/user32/callback.h | 85 + include/user32/wininternal.h | 22 + include/win32k/bitmaps.h | 299 + include/win32k/brush.h | 78 + include/win32k/cliprgn.h | 81 + include/win32k/color.h | 114 + include/win32k/coord.h | 129 + include/win32k/dc.h | 241 + include/win32k/debug.h | 12 + include/win32k/debug1.h | 100 + include/win32k/driver.h | 168 + include/win32k/fillshap.h | 68 + include/win32k/float.h | 102 + include/win32k/gdiobj.h | 91 + include/win32k/icm.h | 81 + include/win32k/kapi.h | 23 + include/win32k/line.h | 97 + include/win32k/math.h | 163 + include/win32k/metafile.h | 180 + include/win32k/misc.h | 8 + include/win32k/ntuser.h | 1732 ++ include/win32k/paint.h | 12 + include/win32k/path.h | 54 + include/win32k/pen.h | 40 + include/win32k/print.h | 48 + include/win32k/region.h | 153 + include/win32k/text.h | 261 + include/win32k/userobj.h | 46 + include/win32k/win32k.h | 1 + include/win32k/wingl.h | 38 + include/windows.h | 165 + include/wine/config.h | 710 + include/wine/debugtools.h | 115 + include/wine/wineros.h | 10 + include/winsock2.h | 1572 + include/ws2spi.h | 566 + include/wsahelp.h | 349 + install-system.sh | 1 + install.bat | 129 + install.sh | 1 + installwine.bat | 61 + lib/advapi32/.cvsignore | 9 + lib/advapi32/advapi32.def | 411 + lib/advapi32/advapi32.edf | 411 + lib/advapi32/advapi32.rc | 39 + lib/advapi32/makefile | 55 + lib/advapi32/misc/dllmain.c | 39 + lib/advapi32/misc/shutdown.c | 193 + lib/advapi32/misc/sysfunc.c | 410 + lib/advapi32/reg/reg.c | 2504 ++ lib/advapi32/sec/ac.c | 375 + lib/advapi32/sec/lsa.c | 586 + lib/advapi32/sec/misc.c | 112 + lib/advapi32/sec/sec.c | 366 + lib/advapi32/sec/sid.c | 243 + lib/advapi32/service/scm.c | 749 + lib/advapi32/service/sctrl.c | 426 + lib/advapi32/service/undoc.c | 50 + lib/advapi32/token/privilege.c | 177 + lib/advapi32/token/token.c | 245 + lib/crtdll/.cvsignore | 6 + lib/crtdll/assert/.cvsignore | 3 + lib/crtdll/assert/assert.c | 12 + lib/crtdll/conio/.cvsignore | 3 + lib/crtdll/conio/cgets.c | 64 + lib/crtdll/conio/cprintf.c | 17 + lib/crtdll/conio/cputs.c | 23 + lib/crtdll/conio/cscanf.c | 19 + lib/crtdll/conio/getch.c | 39 + lib/crtdll/conio/getche.c | 33 + lib/crtdll/conio/kbhit.c | 32 + lib/crtdll/conio/putch.c | 21 + lib/crtdll/conio/ungetch.c | 28 + lib/crtdll/crtdll.def | 567 + lib/crtdll/crtdll.rc | 37 + lib/crtdll/ctype/.cvsignore | 3 + lib/crtdll/ctype/isalnum.c | 23 + lib/crtdll/ctype/isalpha.c | 23 + lib/crtdll/ctype/isascii.c | 29 + lib/crtdll/ctype/iscntrl.c | 14 + lib/crtdll/ctype/iscsym.c | 21 + lib/crtdll/ctype/isctype.c | 283 + lib/crtdll/ctype/isdigit.c | 14 + lib/crtdll/ctype/isgraph.c | 14 + lib/crtdll/ctype/islower.c | 13 + lib/crtdll/ctype/isprint.c | 13 + lib/crtdll/ctype/ispunct.c | 14 + lib/crtdll/ctype/isspace.c | 22 + lib/crtdll/ctype/isupper.c | 13 + lib/crtdll/ctype/isxdigit.c | 15 + lib/crtdll/ctype/toascii.c | 9 + lib/crtdll/ctype/tolower.c | 35 + lib/crtdll/ctype/toupper.c | 33 + lib/crtdll/direct/.cvsignore | 3 + lib/crtdll/direct/chdir.c | 18 + lib/crtdll/direct/chdrive.c | 26 + lib/crtdll/direct/getcwd.c | 25 + lib/crtdll/direct/getdcwd.c | 23 + lib/crtdll/direct/getdfree.c | 20 + lib/crtdll/direct/getdrive.c | 26 + lib/crtdll/direct/mkdir.c | 10 + lib/crtdll/direct/rmdir.c | 11 + lib/crtdll/dirent/.cvsignore | 3 + lib/crtdll/dirent/dirent.c | 316 + lib/crtdll/except/.cvsignore | 3 + lib/crtdll/except/abnorter.c | 7 + lib/crtdll/except/exhand2.c | 11 + lib/crtdll/except/matherr.c | 22 + lib/crtdll/except/unwind.c | 14 + lib/crtdll/float/.cvsignore | 3 + lib/crtdll/float/chgsign.c | 13 + lib/crtdll/float/clearfp.c | 13 + lib/crtdll/float/cntrlfp.c | 38 + lib/crtdll/float/copysign.c | 13 + lib/crtdll/float/fpclass.c | 65 + lib/crtdll/float/fpreset.c | 8 + lib/crtdll/float/isnan.c | 77 + lib/crtdll/float/logb.c | 31 + lib/crtdll/float/nafter.c | 12 + lib/crtdll/float/nextaf.c | 48 + lib/crtdll/float/scalb.c | 12 + lib/crtdll/float/statfp.c | 14 + lib/crtdll/io/.cvsignore | 3 + lib/crtdll/io/access.c | 38 + lib/crtdll/io/chmod.c | 31 + lib/crtdll/io/chsize.c | 11 + lib/crtdll/io/close.c | 14 + lib/crtdll/io/commit.c | 16 + lib/crtdll/io/create.c | 7 + lib/crtdll/io/dup.c | 12 + lib/crtdll/io/dup2.c | 8 + lib/crtdll/io/eof.c | 19 + lib/crtdll/io/filelen.c | 8 + lib/crtdll/io/find.c | 81 + lib/crtdll/io/fmode.c | 9 + lib/crtdll/io/isatty.c | 14 + lib/crtdll/io/locking.c | 11 + lib/crtdll/io/lseek.c | 9 + lib/crtdll/io/mktemp.c | 73 + lib/crtdll/io/open.c | 268 + lib/crtdll/io/pipe.c | 26 + lib/crtdll/io/read.c | 22 + lib/crtdll/io/setmode.c | 19 + lib/crtdll/io/sopen.c | 7 + lib/crtdll/io/tell.c | 10 + lib/crtdll/io/umask.c | 11 + lib/crtdll/io/unlink.c | 20 + lib/crtdll/io/utime.c | 22 + lib/crtdll/io/write.c | 24 + lib/crtdll/libc/.cvsignore | 3 + lib/crtdll/libc/atexit.h | 33 + lib/crtdll/libc/file.h | 64 + lib/crtdll/locale/.cvsignore | 3 + lib/crtdll/locale/locale.c | 143 + lib/crtdll/makefile | 160 + lib/crtdll/malloc/.cvsignore | 3 + lib/crtdll/malloc/expand.c | 44 + lib/crtdll/malloc/heap.c | 29 + lib/crtdll/math/.cvsignore | 3 + lib/crtdll/math/acos.c | 26 + lib/crtdll/math/acosh.c | 8 + lib/crtdll/math/asin.c | 26 + lib/crtdll/math/asinh.c | 9 + lib/crtdll/math/atan.c | 32 + lib/crtdll/math/atan2.c | 12 + lib/crtdll/math/atanh.c | 8 + lib/crtdll/math/cabs.c | 11 + lib/crtdll/math/ceil.c | 23 + lib/crtdll/math/cos.c | 11 + lib/crtdll/math/cosh.c | 8 + lib/crtdll/math/exp.c | 42 + lib/crtdll/math/fabs.c | 32 + lib/crtdll/math/floor.c | 50 + lib/crtdll/math/fmod.c | 35 + lib/crtdll/math/frexp.c | 20 + lib/crtdll/math/ftol.c | 5 + lib/crtdll/math/huge_val.c | 7 + lib/crtdll/math/hypot.c | 98 + lib/crtdll/math/j0_y0.c | 11 + lib/crtdll/math/j1_y1.c | 11 + lib/crtdll/math/jn_yn.c | 11 + lib/crtdll/math/ldexp.c | 31 + lib/crtdll/math/log.c | 33 + lib/crtdll/math/log10.c | 34 + lib/crtdll/math/modf.c | 141 + lib/crtdll/math/pow.c | 85 + lib/crtdll/math/sin.c | 32 + lib/crtdll/math/sinh.c | 16 + lib/crtdll/math/sqrt.c | 32 + lib/crtdll/math/stubs.c | 84 + lib/crtdll/math/tan.c | 33 + lib/crtdll/math/tanh.c | 17 + lib/crtdll/mbstring/.cvsignore | 3 + lib/crtdll/mbstring/hanzen.c | 101 + lib/crtdll/mbstring/ischira.c | 33 + lib/crtdll/mbstring/iskana.c | 17 + lib/crtdll/mbstring/iskmoji.c | 6 + lib/crtdll/mbstring/iskpun.c | 15 + lib/crtdll/mbstring/islead.c | 8 + lib/crtdll/mbstring/islwr.c | 23 + lib/crtdll/mbstring/ismbal.c | 19 + lib/crtdll/mbstring/ismbaln.c | 10 + lib/crtdll/mbstring/ismbc.c | 106 + lib/crtdll/mbstring/ismbgra.c | 8 + lib/crtdll/mbstring/ismbkaln.c | 16 + lib/crtdll/mbstring/ismblead.c | 59 + lib/crtdll/mbstring/ismbpri.c | 8 + lib/crtdll/mbstring/ismbpun.c | 14 + lib/crtdll/mbstring/ismbtrl.c | 39 + lib/crtdll/mbstring/isuppr.c | 23 + lib/crtdll/mbstring/jistojms.c | 24 + lib/crtdll/mbstring/jmstojis.c | 25 + lib/crtdll/mbstring/mbbtype.c | 51 + lib/crtdll/mbstring/mbccpy.c | 12 + lib/crtdll/mbstring/mbclen.c | 27 + lib/crtdll/mbstring/mbscat.c | 6 + lib/crtdll/mbstring/mbschr.c | 6 + lib/crtdll/mbstring/mbscmp.c | 7 + lib/crtdll/mbstring/mbscoll.c | 95 + lib/crtdll/mbstring/mbscpy.c | 7 + lib/crtdll/mbstring/mbscspn.c | 18 + lib/crtdll/mbstring/mbsdec.c | 14 + lib/crtdll/mbstring/mbsdup.c | 25 + lib/crtdll/mbstring/mbsicmp.c | 62 + lib/crtdll/mbstring/mbsicoll.c | 54 + lib/crtdll/mbstring/mbsinc.c | 10 + lib/crtdll/mbstring/mbslen.c | 15 + lib/crtdll/mbstring/mbslwr.c | 40 + lib/crtdll/mbstring/mbsncat.c | 58 + lib/crtdll/mbstring/mbsnccnt.c | 29 + lib/crtdll/mbstring/mbsncmp.c | 103 + lib/crtdll/mbstring/mbsncoll.c | 109 + lib/crtdll/mbstring/mbsncpy.c | 77 + lib/crtdll/mbstring/mbsnextc.c | 18 + lib/crtdll/mbstring/mbsnicmp.c | 39 + lib/crtdll/mbstring/mbsnicoll.c | 10 + lib/crtdll/mbstring/mbsninc.c | 13 + lib/crtdll/mbstring/mbsnset.c | 64 + lib/crtdll/mbstring/mbspbrk.c | 15 + lib/crtdll/mbstring/mbsrchr.c | 30 + lib/crtdll/mbstring/mbsrev.c | 28 + lib/crtdll/mbstring/mbsset.c | 37 + lib/crtdll/mbstring/mbsspn.c | 15 + lib/crtdll/mbstring/mbsspnp.c | 14 + lib/crtdll/mbstring/mbsstr.c | 20 + lib/crtdll/mbstring/mbstok.c | 53 + lib/crtdll/mbstring/mbstrlen.c | 16 + lib/crtdll/mbstring/mbsupr.c | 50 + lib/crtdll/misc/.cvsignore | 3 + lib/crtdll/misc/CRT_noglob.c | 18 + lib/crtdll/misc/CRTfmode.c | 21 + lib/crtdll/misc/CRTglob.c | 19 + lib/crtdll/misc/CRTinit.c | 33 + lib/crtdll/misc/GetArgs.c | 133 + lib/crtdll/misc/amsg.c | 24 + lib/crtdll/misc/crt1.c | 157 + lib/crtdll/misc/dllcrt1.c | 105 + lib/crtdll/misc/dllmain.c | 49 + lib/crtdll/misc/gccmain.c | 85 + lib/crtdll/misc/init.c | 75 + lib/crtdll/misc/initter.c | 7 + lib/crtdll/misc/initterm.c | 35 + lib/crtdll/misc/main.c | 95 + lib/crtdll/misc/purecall.c | 5 + lib/crtdll/misc/setnew.c | 29 + lib/crtdll/misc/sleep.c | 7 + lib/crtdll/misc/unwind.c | 10 + lib/crtdll/process/.cvsignore | 3 + lib/crtdll/process/_cwait.c | 30 + lib/crtdll/process/_system.c | 83 + lib/crtdll/process/dll.c | 33 + lib/crtdll/process/execl.c | 20 + lib/crtdll/process/execle.c | 33 + lib/crtdll/process/execlp.c | 17 + lib/crtdll/process/execlpe.c | 29 + lib/crtdll/process/execv.c | 9 + lib/crtdll/process/execve.c | 7 + lib/crtdll/process/execvp.c | 9 + lib/crtdll/process/execvpe.c | 11 + lib/crtdll/process/procid.c | 10 + lib/crtdll/process/spawnl.c | 21 + lib/crtdll/process/spawnle.c | 29 + lib/crtdll/process/spawnlp.c | 19 + lib/crtdll/process/spawnlpe.c | 30 + lib/crtdll/process/spawnv.c | 9 + lib/crtdll/process/spawnve.c | 338 + lib/crtdll/process/spawnvp.c | 9 + lib/crtdll/process/spawnvpe.c | 12 + lib/crtdll/process/thread.c | 28 + lib/crtdll/process/threadid.c | 12 + lib/crtdll/quad/.cvsignore | 3 + lib/crtdll/quad/divdi3.c | 66 + lib/crtdll/quad/moddi3.c | 65 + lib/crtdll/quad/qdivrem.c | 281 + lib/crtdll/quad/udivdi3.c | 52 + lib/crtdll/quad/umoddi3.c | 54 + lib/crtdll/search/.cvsignore | 3 + lib/crtdll/search/lfind.c | 17 + lib/crtdll/search/lsearch.c | 16 + lib/crtdll/setjmp/.cvsignore | 3 + lib/crtdll/setjmp/setjmp.c | 143 + lib/crtdll/signal/.cvsignore | 3 + lib/crtdll/signal/signal.c | 107 + lib/crtdll/signal/xcptfil.c | 11 + lib/crtdll/signal/xcptinfo.c | 6 + lib/crtdll/stdio/.cvsignore | 3 + lib/crtdll/stdio/FILE.DOC | 43 + lib/crtdll/stdio/allocfil.c | 98 + lib/crtdll/stdio/clearerr.c | 19 + lib/crtdll/stdio/doscan.c | 409 + lib/crtdll/stdio/fclose.c | 51 + lib/crtdll/stdio/fdopen.c | 62 + lib/crtdll/stdio/feof.c | 19 + lib/crtdll/stdio/ferror.c | 13 + lib/crtdll/stdio/fflush.c | 111 + lib/crtdll/stdio/fgetc.c | 25 + lib/crtdll/stdio/fgetchar.c | 13 + lib/crtdll/stdio/fgetpos.c | 15 + lib/crtdll/stdio/fgets.c | 22 + lib/crtdll/stdio/filbuf.c | 131 + lib/crtdll/stdio/fileno.c | 13 + lib/crtdll/stdio/flsbuf.c | 179 + lib/crtdll/stdio/fopen.c | 77 + lib/crtdll/stdio/fprintf.c | 56 + lib/crtdll/stdio/fputc.c | 17 + lib/crtdll/stdio/fputchar.c | 15 + lib/crtdll/stdio/fputs.c | 38 + lib/crtdll/stdio/fread.c | 83 + lib/crtdll/stdio/freopen.c | 67 + lib/crtdll/stdio/frlist.c | 13 + lib/crtdll/stdio/fscanf.c | 60 + lib/crtdll/stdio/fseek.c | 56 + lib/crtdll/stdio/fsetpos.c | 16 + lib/crtdll/stdio/fsopen.c | 101 + lib/crtdll/stdio/ftell.c | 47 + lib/crtdll/stdio/fwalk.c | 18 + lib/crtdll/stdio/fwrite.c | 84 + lib/crtdll/stdio/getc.c | 57 + lib/crtdll/stdio/getchar.c | 10 + lib/crtdll/stdio/getenv.c | 16 + lib/crtdll/stdio/gets.c | 107 + lib/crtdll/stdio/getw.c | 33 + lib/crtdll/stdio/perror.c | 17 + lib/crtdll/stdio/popen.c | 62 + lib/crtdll/stdio/printf.c | 54 + lib/crtdll/stdio/putc.c | 54 + lib/crtdll/stdio/putchar.c | 22 + lib/crtdll/stdio/puts.c | 17 + lib/crtdll/stdio/putw.c | 31 + lib/crtdll/stdio/remove.c | 9 + lib/crtdll/stdio/rename.c | 16 + lib/crtdll/stdio/rewind.c | 16 + lib/crtdll/stdio/rmtmp.c | 72 + lib/crtdll/stdio/scanf.c | 72 + lib/crtdll/stdio/setbuf.c | 13 + lib/crtdll/stdio/setbuffe.c | 12 + lib/crtdll/stdio/setlineb.c | 9 + lib/crtdll/stdio/setvbuf.c | 62 + lib/crtdll/stdio/sprintf.c | 84 + lib/crtdll/stdio/sscanf.c | 79 + lib/crtdll/stdio/stdhnd.c | 43 + lib/crtdll/stdio/stdiohk.c | 19 + lib/crtdll/stdio/tempnam.c | 21 + lib/crtdll/stdio/tmpfile.c | 72 + lib/crtdll/stdio/tmpnam.c | 15 + lib/crtdll/stdio/ungetc.c | 75 + lib/crtdll/stdio/vfprintf.c | 861 + lib/crtdll/stdio/vfscanf.c | 1198 + lib/crtdll/stdio/vfwprint.c | 865 + lib/crtdll/stdio/vprintf.c | 47 + lib/crtdll/stdio/vscanf.c | 36 + lib/crtdll/stdio/vsprintf.c | 68 + lib/crtdll/stdio/vsscanf.c | 58 + lib/crtdll/stdlib/.cvsignore | 3 + lib/crtdll/stdlib/_exit.c | 46 + lib/crtdll/stdlib/abort.c | 16 + lib/crtdll/stdlib/abs.c | 8 + lib/crtdll/stdlib/atexit.c | 18 + lib/crtdll/stdlib/atof.c | 8 + lib/crtdll/stdlib/atoi.c | 8 + lib/crtdll/stdlib/atol.c | 8 + lib/crtdll/stdlib/atold.c | 8 + lib/crtdll/stdlib/bsearch.c | 25 + lib/crtdll/stdlib/calloc.c | 12 + lib/crtdll/stdlib/div.c | 24 + lib/crtdll/stdlib/ecvt.c | 12 + lib/crtdll/stdlib/ecvtbuf.c | 108 + lib/crtdll/stdlib/errno.c | 36 + lib/crtdll/stdlib/fcvt.c | 12 + lib/crtdll/stdlib/fcvtbuf.c | 61 + lib/crtdll/stdlib/fullpath.c | 32 + lib/crtdll/stdlib/gcvt.c | 31 + lib/crtdll/stdlib/itoa.c | 138 + lib/crtdll/stdlib/itow.c | 177 + lib/crtdll/stdlib/labs.c | 8 + lib/crtdll/stdlib/ldiv.c | 25 + lib/crtdll/stdlib/llabs.c | 9 + lib/crtdll/stdlib/lldiv.c | 26 + lib/crtdll/stdlib/makepath.c | 36 + lib/crtdll/stdlib/malloc.c | 87 + lib/crtdll/stdlib/mbstow.c | 17 + lib/crtdll/stdlib/mbstowcs.c | 12 + lib/crtdll/stdlib/obsol.c | 24 + lib/crtdll/stdlib/putenv.c | 30 + lib/crtdll/stdlib/qsort.c | 237 + lib/crtdll/stdlib/rand.c | 17 + lib/crtdll/stdlib/rot.c | 56 + lib/crtdll/stdlib/senv.c | 28 + lib/crtdll/stdlib/splitp.c | 47 + lib/crtdll/stdlib/strtod.c | 97 + lib/crtdll/stdlib/strtol.c | 91 + lib/crtdll/stdlib/strtold.c | 122 + lib/crtdll/stdlib/strtoll.c | 84 + lib/crtdll/stdlib/strtoul.c | 76 + lib/crtdll/stdlib/strtoull.c | 76 + lib/crtdll/stdlib/swab.c | 18 + lib/crtdll/stdlib/wcstom.c | 14 + lib/crtdll/stdlib/wcstomb.c | 122 + lib/crtdll/stdlib/wcstombs.c | 152 + lib/crtdll/string/.cvsignore | 3 + lib/crtdll/string/memccpy.c | 9 + lib/crtdll/string/memchr.c | 18 + lib/crtdll/string/memcmp.c | 17 + lib/crtdll/string/memcpy.c | 16 + lib/crtdll/string/memcpy.s | 20 + lib/crtdll/string/memicmp.c | 20 + lib/crtdll/string/memmove.c | 36 + lib/crtdll/string/memmove.s | 33 + lib/crtdll/string/memset.c | 13 + lib/crtdll/string/memset.s | 51 + lib/crtdll/string/str_old.c | 49 + lib/crtdll/string/strcat.c | 12 + lib/crtdll/string/strchr.c | 21 + lib/crtdll/string/strcmp.c | 15 + lib/crtdll/string/strcoll.c | 28 + lib/crtdll/string/strcpy.c | 10 + lib/crtdll/string/strcspn.c | 20 + lib/crtdll/string/strdup.c | 16 + lib/crtdll/string/strerror.c | 101 + lib/crtdll/string/stricmp.c | 22 + lib/crtdll/string/strlen.c | 14 + lib/crtdll/string/strlwr.c | 23 + lib/crtdll/string/strncat.c | 22 + lib/crtdll/string/strncmp.c | 18 + lib/crtdll/string/strncpy.c | 21 + lib/crtdll/string/strnicmp.c | 17 + lib/crtdll/string/strnlen.c | 14 + lib/crtdll/string/strpbrk.c | 18 + lib/crtdll/string/strrchr.c | 21 + lib/crtdll/string/strrev.c | 18 + lib/crtdll/string/strset.c | 28 + lib/crtdll/string/strspn.c | 16 + lib/crtdll/string/strspnp.c | 16 + lib/crtdll/string/strstr.c | 23 + lib/crtdll/string/strtok.c | 51 + lib/crtdll/string/strtoul.c | 27 + lib/crtdll/string/strupr.c | 24 + lib/crtdll/string/strxfrm.c | 22 + lib/crtdll/sys_stat/.cvsignore | 3 + lib/crtdll/sys_stat/fstat.c | 54 + lib/crtdll/sys_stat/ftime.c | 47 + lib/crtdll/sys_stat/futime.c | 39 + lib/crtdll/sys_stat/stat.c | 55 + lib/crtdll/sys_stat/systime.c | 67 + lib/crtdll/tchar/.cvsignore | 3 + lib/crtdll/tchar/strdec.c | 7 + lib/crtdll/tchar/strinc.c | 6 + lib/crtdll/tchar/strncnt.c | 8 + lib/crtdll/tchar/strnextc.c | 6 + lib/crtdll/tchar/strninc.c | 7 + lib/crtdll/tchar/strspnp.c | 9 + lib/crtdll/time/.cvsignore | 3 + lib/crtdll/time/clock.c | 31 + lib/crtdll/time/ctime.c | 1413 + lib/crtdll/time/difftime.c | 8 + lib/crtdll/time/posixrul.h | 49 + lib/crtdll/time/strdate.c | 30 + lib/crtdll/time/strftime.c | 264 + lib/crtdll/time/strtime.c | 29 + lib/crtdll/time/time.c | 219 + lib/crtdll/time/tzfile.h | 160 + lib/crtdll/wchar/.cvsignore | 3 + lib/crtdll/wchar/wcscat.c | 19 + lib/crtdll/wchar/wcschr.c | 16 + lib/crtdll/wchar/wcscmp.c | 16 + lib/crtdll/wchar/wcscoll.c | 17 + lib/crtdll/wchar/wcscpy.c | 11 + lib/crtdll/wchar/wcscspn.c | 20 + lib/crtdll/wchar/wcsdup.c | 19 + lib/crtdll/wchar/wcsftime.c | 6 + lib/crtdll/wchar/wcsicmp.c | 16 + lib/crtdll/wchar/wcslen.c | 23 + lib/crtdll/wchar/wcslwr.c | 22 + lib/crtdll/wchar/wcsncat.c | 21 + lib/crtdll/wchar/wcsncmp.c | 16 + lib/crtdll/wchar/wcsncpy.c | 21 + lib/crtdll/wchar/wcsnicmp.c | 14 + lib/crtdll/wchar/wcsnlen.c | 12 + lib/crtdll/wchar/wcspbrk.c | 16 + lib/crtdll/wchar/wcsrchr.c | 16 + lib/crtdll/wchar/wcsrev.c | 18 + lib/crtdll/wchar/wcsset.c | 27 + lib/crtdll/wchar/wcsspn.c | 20 + lib/crtdll/wchar/wcsstr.c | 23 + lib/crtdll/wchar/wcstod.c | 95 + lib/crtdll/wchar/wcstok.c | 54 + lib/crtdll/wchar/wcstol.c | 60 + lib/crtdll/wchar/wcstombs.c | 7 + lib/crtdll/wchar/wcsupr.c | 12 + lib/crtdll/wchar/wcsxfrm.c | 23 + lib/crtdll/wchar/wtoi.c | 11 + lib/fmifs/.cvsignore | 3 + lib/fmifs/chkdsk.c | 52 + lib/fmifs/compress.c | 30 + lib/fmifs/diskcopy.c | 25 + lib/fmifs/dllmain.c | 27 + lib/fmifs/extend.c | 25 + lib/fmifs/fmifs.def | 23 + lib/fmifs/fmifs.edf | 23 + lib/fmifs/fmifs.rc | 38 + lib/fmifs/format.c | 49 + lib/fmifs/init.c | 42 + lib/fmifs/label.c | 26 + lib/fmifs/makefile | 30 + lib/fmifs/media.c | 26 + lib/gdi32/.cvsignore | 3 + lib/gdi32/gdi32.def | 344 + lib/gdi32/gdi32.edf | 344 + lib/gdi32/gdi32.rc | 38 + lib/gdi32/gdi32_specs | 78 + lib/gdi32/main/dllmain.c | 66 + lib/gdi32/makefile | 32 + lib/gdi32/misc/.cvsignore | 1 + lib/gdi32/misc/stubs.c | 2861 ++ lib/gdi32/misc/stubsa.c | 541 + lib/gdi32/misc/stubsw.c | 558 + lib/gdi32/objects/bitblt.c | 267 + lib/gdi32/objects/brush.c | 18 + lib/gdi32/objects/dc.c | 177 + lib/gdi32/objects/line.c | 34 + lib/gdi32/objects/pen.c | 29 + lib/gdi32/objects/region.c | 156 + lib/gdi32/objects/text.c | 240 + lib/iphlpapi/.cvsignore | 23 + lib/iphlpapi/debug.h | 65 + lib/iphlpapi/iphlpapi.c | 314 + lib/iphlpapi/iphlpapi.def | 17 + lib/iphlpapi/iphlpapi.edf | 17 + lib/iphlpapi/iphlpapi.rc | 39 + lib/iphlpapi/makefile | 19 + lib/iprtprio/.cvsignore | 17 + lib/iprtprio/iprtprio.c | 119 + lib/iprtprio/iprtprio.def | 9 + lib/iprtprio/iprtprio.edf | 9 + lib/iprtprio/iprtprio.rc | 39 + lib/iprtprio/makefile | 19 + lib/kernel32/.cvsignore | 9 + lib/kernel32/except/.cvsignore | 3 + lib/kernel32/except/except.c | 153 + lib/kernel32/file/.cvsignore | 3 + lib/kernel32/file/backup.c | 74 + lib/kernel32/file/cnotify.c | 82 + lib/kernel32/file/copy.c | 284 + lib/kernel32/file/create.c | 263 + lib/kernel32/file/curdir.c | 386 + lib/kernel32/file/delete.c | 135 + lib/kernel32/file/deviceio.c | 192 + lib/kernel32/file/dir.c | 624 + lib/kernel32/file/dosdev.c | 109 + lib/kernel32/file/file.c | 811 + lib/kernel32/file/find.c | 494 + lib/kernel32/file/iocompl.c | 141 + lib/kernel32/file/lfile.c | 208 + lib/kernel32/file/lock.c | 175 + lib/kernel32/file/mailslot.c | 171 + lib/kernel32/file/move.c | 157 + lib/kernel32/file/npipe.c | 824 + lib/kernel32/file/pipe.c | 106 + lib/kernel32/file/rw.c | 248 + lib/kernel32/file/tape.c | 143 + lib/kernel32/file/volume.c | 709 + lib/kernel32/kernel32.def | 691 + lib/kernel32/kernel32.edf | 695 + lib/kernel32/kernel32.rc | 38 + lib/kernel32/makefile | 95 + lib/kernel32/mem/.cvsignore | 3 + lib/kernel32/mem/global.c | 444 + lib/kernel32/mem/heap.c | 202 + lib/kernel32/mem/isbad.c | 219 + lib/kernel32/mem/local.c | 106 + lib/kernel32/mem/procmem.c | 69 + lib/kernel32/mem/section.c | 309 + lib/kernel32/mem/virtual.c | 201 + lib/kernel32/misc/.cvsignore | 3 + lib/kernel32/misc/atom.c | 536 + lib/kernel32/misc/comm.c | 659 + lib/kernel32/misc/console.c | 2444 ++ lib/kernel32/misc/debug.c | 118 + lib/kernel32/misc/dllmain.c | 167 + lib/kernel32/misc/env.c | 464 + lib/kernel32/misc/error.c | 81 + lib/kernel32/misc/handle.c | 160 + lib/kernel32/misc/ldr.c | 370 + lib/kernel32/misc/profile.c | 381 + lib/kernel32/misc/res.c | 380 + lib/kernel32/misc/stubs.c | 1475 + lib/kernel32/misc/sysinfo.c | 126 + lib/kernel32/misc/time.c | 429 + lib/kernel32/nls/.cvsignore | 3 + lib/kernel32/nls/LGPL.c | 17 + lib/kernel32/nls/afk.nls | 113 + lib/kernel32/nls/ara.nls | 114 + lib/kernel32/nls/arb.nls | 114 + lib/kernel32/nls/are.nls | 114 + lib/kernel32/nls/arg.nls | 114 + lib/kernel32/nls/ari.nls | 114 + lib/kernel32/nls/ark.nls | 114 + lib/kernel32/nls/arm.nls | 114 + lib/kernel32/nls/aro.nls | 114 + lib/kernel32/nls/arq.nls | 114 + lib/kernel32/nls/ars.nls | 114 + lib/kernel32/nls/art.nls | 114 + lib/kernel32/nls/aru.nls | 114 + lib/kernel32/nls/bel.nls | 113 + lib/kernel32/nls/bgr.nls | 112 + lib/kernel32/nls/cat.nls | 113 + lib/kernel32/nls/cht.nls | 113 + lib/kernel32/nls/codepage.c | 122 + lib/kernel32/nls/cpmisc.c | 101 + lib/kernel32/nls/cptable.c | 402 + lib/kernel32/nls/cze.nls | 114 + lib/kernel32/nls/dan.nls | 113 + lib/kernel32/nls/dea.nls | 113 + lib/kernel32/nls/dec.nls | 113 + lib/kernel32/nls/del.nls | 112 + lib/kernel32/nls/des.nls | 113 + lib/kernel32/nls/deu.nls | 113 + lib/kernel32/nls/dnk.nls | 0 lib/kernel32/nls/empty.nls | 114 + lib/kernel32/nls/ena.nls | 112 + lib/kernel32/nls/enb.nls | 112 + lib/kernel32/nls/enc.nls | 112 + lib/kernel32/nls/eng.nls | 112 + lib/kernel32/nls/enj.nls | 112 + lib/kernel32/nls/enl.nls | 113 + lib/kernel32/nls/ens.nls | 112 + lib/kernel32/nls/ent.nls | 113 + lib/kernel32/nls/enu.nls | 112 + lib/kernel32/nls/enz.nls | 112 + lib/kernel32/nls/esa.nls | 112 + lib/kernel32/nls/esb.nls | 112 + lib/kernel32/nls/esc.nls | 112 + lib/kernel32/nls/esd.nls | 112 + lib/kernel32/nls/ese.nls | 114 + lib/kernel32/nls/esf.nls | 112 + lib/kernel32/nls/esg.nls | 113 + lib/kernel32/nls/esh.nls | 112 + lib/kernel32/nls/esi.nls | 113 + lib/kernel32/nls/esl.nls | 112 + lib/kernel32/nls/esm.nls | 112 + lib/kernel32/nls/esn.nls | 112 + lib/kernel32/nls/eso.nls | 113 + lib/kernel32/nls/esp.nls | 112 + lib/kernel32/nls/esperanto.nls | 129 + lib/kernel32/nls/esr.nls | 112 + lib/kernel32/nls/ess.nls | 112 + lib/kernel32/nls/est.nls | 115 + lib/kernel32/nls/esu.nls | 112 + lib/kernel32/nls/esv.nls | 113 + lib/kernel32/nls/esy.nls | 113 + lib/kernel32/nls/esz.nls | 113 + lib/kernel32/nls/euq.nls | 115 + lib/kernel32/nls/fin.nls | 112 + lib/kernel32/nls/fos.nls | 114 + lib/kernel32/nls/fra.nls | 112 + lib/kernel32/nls/frb.nls | 112 + lib/kernel32/nls/frc.nls | 112 + lib/kernel32/nls/frl.nls | 114 + lib/kernel32/nls/frs.nls | 114 + lib/kernel32/nls/grc.nls | 114 + lib/kernel32/nls/hkg.nls | 110 + lib/kernel32/nls/hrv.nls | 115 + lib/kernel32/nls/hun.nls | 114 + lib/kernel32/nls/ind.nls | 112 + lib/kernel32/nls/irl.nls | 114 + lib/kernel32/nls/isl.nls | 114 + lib/kernel32/nls/ita.nls | 114 + lib/kernel32/nls/its.nls | 114 + lib/kernel32/nls/jpn.nls | 114 + lib/kernel32/nls/koj.nls | 114 + lib/kernel32/nls/kor.nls | 115 + lib/kernel32/nls/lcAFK.c | 145 + lib/kernel32/nls/lcBEL.c | 144 + lib/kernel32/nls/lcBGR.c | 147 + lib/kernel32/nls/lcCAT.c | 144 + lib/kernel32/nls/lcCSY.c | 149 + lib/kernel32/nls/lcDAN.c | 149 + lib/kernel32/nls/lcDEA.c | 151 + lib/kernel32/nls/lcDEC.c | 153 + lib/kernel32/nls/lcDEL.c | 152 + lib/kernel32/nls/lcDES.c | 153 + lib/kernel32/nls/lcDEU.c | 152 + lib/kernel32/nls/lcELL.c | 151 + lib/kernel32/nls/lcENA.c | 148 + lib/kernel32/nls/lcENB.c | 150 + lib/kernel32/nls/lcENC.c | 151 + lib/kernel32/nls/lcENG.c | 148 + lib/kernel32/nls/lcENI.c | 148 + lib/kernel32/nls/lcENJ.c | 150 + lib/kernel32/nls/lcENL.c | 144 + lib/kernel32/nls/lcENS.c | 144 + lib/kernel32/nls/lcENT.c | 144 + lib/kernel32/nls/lcENU.c | 155 + lib/kernel32/nls/lcENZ.c | 148 + lib/kernel32/nls/lcESA.c | 151 + lib/kernel32/nls/lcESB.c | 151 + lib/kernel32/nls/lcESC.c | 151 + lib/kernel32/nls/lcESD.c | 151 + lib/kernel32/nls/lcESE.c | 144 + lib/kernel32/nls/lcESF.c | 151 + lib/kernel32/nls/lcESG.c | 151 + lib/kernel32/nls/lcESH.c | 144 + lib/kernel32/nls/lcESI.c | 144 + lib/kernel32/nls/lcESL.c | 151 + lib/kernel32/nls/lcESM.c | 151 + lib/kernel32/nls/lcESN.c | 151 + lib/kernel32/nls/lcESO.c | 151 + lib/kernel32/nls/lcESP.c | 151 + lib/kernel32/nls/lcESR.c | 151 + lib/kernel32/nls/lcESS.c | 151 + lib/kernel32/nls/lcESU.c | 144 + lib/kernel32/nls/lcESV.c | 151 + lib/kernel32/nls/lcESY.c | 151 + lib/kernel32/nls/lcESZ.c | 151 + lib/kernel32/nls/lcETI.c | 144 + lib/kernel32/nls/lcEUQ.c | 144 + lib/kernel32/nls/lcFIN.c | 150 + lib/kernel32/nls/lcFOS.c | 144 + lib/kernel32/nls/lcFRA.c | 152 + lib/kernel32/nls/lcFRB.c | 153 + lib/kernel32/nls/lcFRC.c | 151 + lib/kernel32/nls/lcFRL.c | 152 + lib/kernel32/nls/lcFRS.c | 150 + lib/kernel32/nls/lcHRV.c | 146 + lib/kernel32/nls/lcHUN.c | 149 + lib/kernel32/nls/lcIND.c | 144 + lib/kernel32/nls/lcISL.c | 151 + lib/kernel32/nls/lcITA.c | 152 + lib/kernel32/nls/lcITS.c | 151 + lib/kernel32/nls/lcLTH.c | 145 + lib/kernel32/nls/lcLVI.c | 144 + lib/kernel32/nls/lcNLB.c | 152 + lib/kernel32/nls/lcNLD.c | 155 + lib/kernel32/nls/lcNON.c | 150 + lib/kernel32/nls/lcNOR.c | 150 + lib/kernel32/nls/lcPLK.c | 146 + lib/kernel32/nls/lcPTB.c | 148 + lib/kernel32/nls/lcPTG.c | 153 + lib/kernel32/nls/lcROM.c | 148 + lib/kernel32/nls/lcRUS.c | 148 + lib/kernel32/nls/lcSKY.c | 150 + lib/kernel32/nls/lcSLV.c | 152 + lib/kernel32/nls/lcSQI.c | 144 + lib/kernel32/nls/lcSRB.c | 144 + lib/kernel32/nls/lcSRL.c | 144 + lib/kernel32/nls/lcSVE.c | 148 + lib/kernel32/nls/lcSVF.c | 149 + lib/kernel32/nls/lcTRK.c | 148 + lib/kernel32/nls/lcUKR.c | 144 + lib/kernel32/nls/lctable.c | 639 + lib/kernel32/nls/locale.c | 1280 + lib/kernel32/nls/lth.nls | 114 + lib/kernel32/nls/lvi.nls | 114 + lib/kernel32/nls/mbtowc.c | 83 + lib/kernel32/nls/nlb.nls | 114 + lib/kernel32/nls/nld.nls | 114 + lib/kernel32/nls/nls.nls | 119 + lib/kernel32/nls/non.nls | 114 + lib/kernel32/nls/nor.nls | 115 + lib/kernel32/nls/ole2nls.c | 3113 ++ lib/kernel32/nls/plk.nls | 115 + lib/kernel32/nls/prc.nls | 110 + lib/kernel32/nls/ptb.nls | 114 + lib/kernel32/nls/ptg.nls | 115 + lib/kernel32/nls/rom.nls | 115 + lib/kernel32/nls/rus.nls | 115 + lib/kernel32/nls/sgp.nls | 110 + lib/kernel32/nls/sky.nls | 114 + lib/kernel32/nls/slv.nls | 115 + lib/kernel32/nls/sqi.nls | 114 + lib/kernel32/nls/srb.nls | 113 + lib/kernel32/nls/srl.nls | 113 + lib/kernel32/nls/sve.nls | 115 + lib/kernel32/nls/svf.nls | 114 + lib/kernel32/nls/tha.nls | 114 + lib/kernel32/nls/trk.nls | 115 + lib/kernel32/nls/ukr.nls | 113 + lib/kernel32/nls/vie.nls | 115 + lib/kernel32/nls/wctomb.c | 101 + lib/kernel32/nls/zhh.nls | 113 + lib/kernel32/nls/zhi.nls | 115 + lib/kernel32/nls/zhs.nls | 113 + lib/kernel32/process/.cvsignore | 3 + lib/kernel32/process/cmdline.c | 100 + lib/kernel32/process/create.c | 998 + lib/kernel32/process/proc.c | 706 + lib/kernel32/process/session.c | 28 + lib/kernel32/string/.cvsignore | 3 + lib/kernel32/string/lstring.c | 136 + lib/kernel32/synch/.cvsignore | 3 + lib/kernel32/synch/critical.c | 32 + lib/kernel32/synch/event.c | 228 + lib/kernel32/synch/intrlck.c | 162 + lib/kernel32/synch/mutex.c | 201 + lib/kernel32/synch/sem.c | 214 + lib/kernel32/synch/timer.c | 188 + lib/kernel32/synch/wait.c | 143 + lib/kernel32/thread/.cvsignore | 3 + lib/kernel32/thread/fiber.c | 93 + lib/kernel32/thread/thread.c | 476 + lib/kernel32/thread/tls.c | 99 + lib/makefile | 14 + lib/msafd/.cvsignore | 7 + lib/msafd/include/debug.h | 65 + lib/msafd/include/helpers.h | 62 + lib/msafd/include/msafd.h | 310 + lib/msafd/makefile | 34 + lib/msafd/misc/dllmain.c | 884 + lib/msafd/misc/event.c | 105 + lib/msafd/misc/helpers.c | 242 + lib/msafd/misc/sndrcv.c | 350 + lib/msafd/misc/stubs.c | 212 + lib/msafd/msafd.def | 10 + lib/msafd/msafd.edf | 10 + lib/msafd/msafd.rc | 39 + lib/msvcrt/.cvsignore | 6 + lib/msvcrt/Makefile | 448 + lib/msvcrt/conio/.cvsignore | 3 + lib/msvcrt/conio/cgets.c | 64 + lib/msvcrt/conio/cprintf.c | 17 + lib/msvcrt/conio/cputs.c | 23 + lib/msvcrt/conio/cscanf.c | 18 + lib/msvcrt/conio/getch.c | 40 + lib/msvcrt/conio/getche.c | 31 + lib/msvcrt/conio/kbhit.c | 31 + lib/msvcrt/conio/putch.c | 21 + lib/msvcrt/conio/ungetch.c | 29 + lib/msvcrt/ctype/.cvsignore | 3 + lib/msvcrt/ctype/isalnum.c | 23 + lib/msvcrt/ctype/isalpha.c | 23 + lib/msvcrt/ctype/isascii.c | 29 + lib/msvcrt/ctype/iscntrl.c | 14 + lib/msvcrt/ctype/iscsym.c | 21 + lib/msvcrt/ctype/isctype.c | 293 + lib/msvcrt/ctype/isdigit.c | 14 + lib/msvcrt/ctype/isgraph.c | 14 + lib/msvcrt/ctype/islower.c | 13 + lib/msvcrt/ctype/isprint.c | 13 + lib/msvcrt/ctype/ispunct.c | 14 + lib/msvcrt/ctype/isspace.c | 22 + lib/msvcrt/ctype/isupper.c | 13 + lib/msvcrt/ctype/isxdigit.c | 15 + lib/msvcrt/ctype/toascii.c | 9 + lib/msvcrt/ctype/tolower.c | 36 + lib/msvcrt/ctype/toupper.c | 36 + lib/msvcrt/direct/.cvsignore | 3 + lib/msvcrt/direct/chdir.c | 24 + lib/msvcrt/direct/chdrive.c | 23 + lib/msvcrt/direct/getcwd.c | 42 + lib/msvcrt/direct/getdcwd.c | 44 + lib/msvcrt/direct/getdfree.c | 20 + lib/msvcrt/direct/getdrive.c | 25 + lib/msvcrt/direct/mkdir.c | 17 + lib/msvcrt/direct/rmdir.c | 16 + lib/msvcrt/except/.cvsignore | 3 + lib/msvcrt/except/abnorter.c | 7 + lib/msvcrt/except/exhand2.c | 17 + lib/msvcrt/except/matherr.c | 28 + lib/msvcrt/except/seh.s | 366 + lib/msvcrt/except/unwind.c | 10 + lib/msvcrt/except/xcptfil.c | 11 + lib/msvcrt/float/.cvsignore | 3 + lib/msvcrt/float/chgsign.c | 13 + lib/msvcrt/float/clearfp.c | 13 + lib/msvcrt/float/cntrlfp.c | 36 + lib/msvcrt/float/copysign.c | 13 + lib/msvcrt/float/fpclass.c | 65 + lib/msvcrt/float/fpecode.c | 7 + lib/msvcrt/float/fpreset.c | 8 + lib/msvcrt/float/isnan.c | 77 + lib/msvcrt/float/logb.c | 31 + lib/msvcrt/float/nafter.c | 12 + lib/msvcrt/float/scalb.c | 11 + lib/msvcrt/float/statfp.c | 14 + lib/msvcrt/io/.cvsignore | 3 + lib/msvcrt/io/access.c | 72 + lib/msvcrt/io/chmod.c | 57 + lib/msvcrt/io/chsize.c | 15 + lib/msvcrt/io/close.c | 16 + lib/msvcrt/io/commit.c | 23 + lib/msvcrt/io/create.c | 17 + lib/msvcrt/io/dup.c | 33 + lib/msvcrt/io/dup2.c | 7 + lib/msvcrt/io/eof.c | 15 + lib/msvcrt/io/filelen.c | 16 + lib/msvcrt/io/find.c | 285 + lib/msvcrt/io/fmode.c | 11 + lib/msvcrt/io/isatty.c | 16 + lib/msvcrt/io/locking.c | 10 + lib/msvcrt/io/lseek.c | 17 + lib/msvcrt/io/mktemp.c | 128 + lib/msvcrt/io/open.c | 490 + lib/msvcrt/io/pipe.c | 45 + lib/msvcrt/io/read.c | 73 + lib/msvcrt/io/setmode.c | 24 + lib/msvcrt/io/sopen.c | 12 + lib/msvcrt/io/tell.c | 14 + lib/msvcrt/io/umask.c | 11 + lib/msvcrt/io/unlink.c | 33 + lib/msvcrt/io/utime.c | 39 + lib/msvcrt/io/write.c | 88 + lib/msvcrt/locale/.cvsignore | 3 + lib/msvcrt/locale/locale.c | 141 + lib/msvcrt/math/.cvsignore | 3 + lib/msvcrt/math/acos.c | 26 + lib/msvcrt/math/adjust.c | 7 + lib/msvcrt/math/asin.c | 26 + lib/msvcrt/math/atan.c | 34 + lib/msvcrt/math/atan2.c | 15 + lib/msvcrt/math/cabs.c | 11 + lib/msvcrt/math/ceil.c | 15 + lib/msvcrt/math/cos.c | 13 + lib/msvcrt/math/cosh.c | 8 + lib/msvcrt/math/exp.c | 43 + lib/msvcrt/math/fabs.c | 33 + lib/msvcrt/math/floor.c | 37 + lib/msvcrt/math/fmod.c | 36 + lib/msvcrt/math/frexp.c | 19 + lib/msvcrt/math/ftol.c | 6 + lib/msvcrt/math/huge_val.c | 6 + lib/msvcrt/math/hypot.c | 98 + lib/msvcrt/math/j0_y0.c | 12 + lib/msvcrt/math/j1_y1.c | 11 + lib/msvcrt/math/jn_yn.c | 11 + lib/msvcrt/math/ldexp.c | 33 + lib/msvcrt/math/log.c | 35 + lib/msvcrt/math/log10.c | 35 + lib/msvcrt/math/modf.c | 132 + lib/msvcrt/math/pow.c | 86 + lib/msvcrt/math/sin.c | 33 + lib/msvcrt/math/sinh.c | 16 + lib/msvcrt/math/sqrt.c | 32 + lib/msvcrt/math/stubs.c | 84 + lib/msvcrt/math/tan.c | 34 + lib/msvcrt/math/tanh.c | 17 + lib/msvcrt/mbstring/.cvsignore | 3 + lib/msvcrt/mbstring/hanzen.c | 101 + lib/msvcrt/mbstring/ischira.c | 33 + lib/msvcrt/mbstring/iskana.c | 17 + lib/msvcrt/mbstring/iskmoji.c | 6 + lib/msvcrt/mbstring/iskpun.c | 15 + lib/msvcrt/mbstring/islead.c | 8 + lib/msvcrt/mbstring/islwr.c | 23 + lib/msvcrt/mbstring/ismbal.c | 17 + lib/msvcrt/mbstring/ismbaln.c | 9 + lib/msvcrt/mbstring/ismbc.c | 105 + lib/msvcrt/mbstring/ismbgra.c | 8 + lib/msvcrt/mbstring/ismbkaln.c | 16 + lib/msvcrt/mbstring/ismblead.c | 59 + lib/msvcrt/mbstring/ismbpri.c | 8 + lib/msvcrt/mbstring/ismbpun.c | 14 + lib/msvcrt/mbstring/ismbtrl.c | 39 + lib/msvcrt/mbstring/isuppr.c | 23 + lib/msvcrt/mbstring/jistojms.c | 24 + lib/msvcrt/mbstring/jmstojis.c | 25 + lib/msvcrt/mbstring/mbbtype.c | 48 + lib/msvcrt/mbstring/mbccpy.c | 12 + lib/msvcrt/mbstring/mbclen.c | 30 + lib/msvcrt/mbstring/mbscat.c | 6 + lib/msvcrt/mbstring/mbschr.c | 6 + lib/msvcrt/mbstring/mbscmp.c | 7 + lib/msvcrt/mbstring/mbscoll.c | 97 + lib/msvcrt/mbstring/mbscpy.c | 7 + lib/msvcrt/mbstring/mbscspn.c | 19 + lib/msvcrt/mbstring/mbsdec.c | 14 + lib/msvcrt/mbstring/mbsdup.c | 25 + lib/msvcrt/mbstring/mbsicmp.c | 62 + lib/msvcrt/mbstring/mbsicoll.c | 55 + lib/msvcrt/mbstring/mbsinc.c | 10 + lib/msvcrt/mbstring/mbslen.c | 15 + lib/msvcrt/mbstring/mbslwr.c | 45 + lib/msvcrt/mbstring/mbsncat.c | 59 + lib/msvcrt/mbstring/mbsnccnt.c | 29 + lib/msvcrt/mbstring/mbsncmp.c | 103 + lib/msvcrt/mbstring/mbsncoll.c | 109 + lib/msvcrt/mbstring/mbsncpy.c | 77 + lib/msvcrt/mbstring/mbsnextc.c | 16 + lib/msvcrt/mbstring/mbsnicmp.c | 40 + lib/msvcrt/mbstring/mbsnicoll.c | 11 + lib/msvcrt/mbstring/mbsninc.c | 13 + lib/msvcrt/mbstring/mbsnset.c | 64 + lib/msvcrt/mbstring/mbspbrk.c | 16 + lib/msvcrt/mbstring/mbsrchr.c | 30 + lib/msvcrt/mbstring/mbsrev.c | 28 + lib/msvcrt/mbstring/mbsset.c | 37 + lib/msvcrt/mbstring/mbsspn.c | 16 + lib/msvcrt/mbstring/mbsspnp.c | 15 + lib/msvcrt/mbstring/mbsstr.c | 20 + lib/msvcrt/mbstring/mbstok.c | 53 + lib/msvcrt/mbstring/mbstrlen.c | 16 + lib/msvcrt/mbstring/mbsupr.c | 51 + lib/msvcrt/misc/.cvsignore | 3 + lib/msvcrt/misc/amsg.c | 47 + lib/msvcrt/misc/assert.c | 12 + lib/msvcrt/misc/dllmain.c | 220 + lib/msvcrt/misc/getargs.c | 155 + lib/msvcrt/misc/initterm.c | 35 + lib/msvcrt/misc/purecall.c | 7 + lib/msvcrt/misc/tls.c | 101 + lib/msvcrt/msvcrt.def | 773 + lib/msvcrt/msvcrt.rc | 37 + lib/msvcrt/process/.cvsignore | 3 + lib/msvcrt/process/_cwait.c | 32 + lib/msvcrt/process/_system.c | 121 + lib/msvcrt/process/dll.c | 31 + lib/msvcrt/process/process.c | 478 + lib/msvcrt/process/procid.c | 8 + lib/msvcrt/process/thread.c | 45 + lib/msvcrt/process/threadid.c | 12 + lib/msvcrt/search/.cvsignore | 3 + lib/msvcrt/search/lfind.c | 19 + lib/msvcrt/search/lsearch.c | 17 + lib/msvcrt/setjmp/.cvsignore | 3 + lib/msvcrt/setjmp/setjmp.c | 137 + lib/msvcrt/signal/.cvsignore | 3 + lib/msvcrt/signal/signal.c | 107 + lib/msvcrt/stdio/.cvsignore | 3 + lib/msvcrt/stdio/allocfil.c | 98 + lib/msvcrt/stdio/clearerr.c | 19 + lib/msvcrt/stdio/fclose.c | 51 + lib/msvcrt/stdio/fdopen.c | 102 + lib/msvcrt/stdio/feof.c | 19 + lib/msvcrt/stdio/ferror.c | 13 + lib/msvcrt/stdio/fflush.c | 111 + lib/msvcrt/stdio/fgetc.c | 23 + lib/msvcrt/stdio/fgetchar.c | 12 + lib/msvcrt/stdio/fgetpos.c | 14 + lib/msvcrt/stdio/fgets.c | 22 + lib/msvcrt/stdio/filbuf.c | 131 + lib/msvcrt/stdio/fileno.c | 14 + lib/msvcrt/stdio/flsbuf.c | 179 + lib/msvcrt/stdio/fopen.c | 145 + lib/msvcrt/stdio/fprintf.c | 56 + lib/msvcrt/stdio/fputc.c | 17 + lib/msvcrt/stdio/fputchar.c | 14 + lib/msvcrt/stdio/fputs.c | 36 + lib/msvcrt/stdio/fread.c | 87 + lib/msvcrt/stdio/freopen.c | 122 + lib/msvcrt/stdio/fscanf.c | 59 + lib/msvcrt/stdio/fseek.c | 54 + lib/msvcrt/stdio/fsetpos.c | 15 + lib/msvcrt/stdio/fsopen.c | 177 + lib/msvcrt/stdio/ftell.c | 46 + lib/msvcrt/stdio/fwalk.c | 18 + lib/msvcrt/stdio/fwrite.c | 111 + lib/msvcrt/stdio/getc.c | 70 + lib/msvcrt/stdio/getchar.c | 10 + lib/msvcrt/stdio/gets.c | 106 + lib/msvcrt/stdio/getw.c | 30 + lib/msvcrt/stdio/perror.c | 20 + lib/msvcrt/stdio/popen.c | 227 + lib/msvcrt/stdio/printf.c | 54 + lib/msvcrt/stdio/putc.c | 68 + lib/msvcrt/stdio/putchar.c | 30 + lib/msvcrt/stdio/puts.c | 28 + lib/msvcrt/stdio/putw.c | 30 + lib/msvcrt/stdio/remove.c | 24 + lib/msvcrt/stdio/rename.c | 27 + lib/msvcrt/stdio/rewind.c | 15 + lib/msvcrt/stdio/rmtmp.c | 72 + lib/msvcrt/stdio/scanf.c | 58 + lib/msvcrt/stdio/setbuf.c | 12 + lib/msvcrt/stdio/setvbuf.c | 62 + lib/msvcrt/stdio/sprintf.c | 84 + lib/msvcrt/stdio/sscanf.c | 65 + lib/msvcrt/stdio/stdhnd.c | 40 + lib/msvcrt/stdio/tempnam.c | 42 + lib/msvcrt/stdio/tmpfile.c | 67 + lib/msvcrt/stdio/tmpnam.c | 28 + lib/msvcrt/stdio/ungetc.c | 71 + lib/msvcrt/stdio/vfprintf.c | 1077 + lib/msvcrt/stdio/vfscanf.c | 1199 + lib/msvcrt/stdio/vfwprint.c | 1057 + lib/msvcrt/stdio/vprintf.c | 47 + lib/msvcrt/stdio/vscanf.c | 34 + lib/msvcrt/stdio/vsprintf.c | 68 + lib/msvcrt/stdio/vsscanf.c | 50 + lib/msvcrt/stdlib/.cvsignore | 3 + lib/msvcrt/stdlib/_exit.c | 46 + lib/msvcrt/stdlib/abort.c | 16 + lib/msvcrt/stdlib/abs.c | 8 + lib/msvcrt/stdlib/atexit.c | 18 + lib/msvcrt/stdlib/atof.c | 8 + lib/msvcrt/stdlib/atoi.c | 8 + lib/msvcrt/stdlib/atoi64.c | 31 + lib/msvcrt/stdlib/atol.c | 8 + lib/msvcrt/stdlib/atold.c | 8 + lib/msvcrt/stdlib/bsearch.c | 25 + lib/msvcrt/stdlib/div.c | 24 + lib/msvcrt/stdlib/ecvt.c | 12 + lib/msvcrt/stdlib/ecvtbuf.c | 108 + lib/msvcrt/stdlib/errno.c | 42 + lib/msvcrt/stdlib/fcvt.c | 12 + lib/msvcrt/stdlib/fcvtbuf.c | 61 + lib/msvcrt/stdlib/fullpath.c | 29 + lib/msvcrt/stdlib/gcvt.c | 31 + lib/msvcrt/stdlib/getenv.c | 35 + lib/msvcrt/stdlib/itoa.c | 212 + lib/msvcrt/stdlib/itow.c | 212 + lib/msvcrt/stdlib/labs.c | 8 + lib/msvcrt/stdlib/ldiv.c | 25 + lib/msvcrt/stdlib/makepath.c | 69 + lib/msvcrt/stdlib/malloc.c | 24 + lib/msvcrt/stdlib/mbstow.c | 17 + lib/msvcrt/stdlib/mbstowcs.c | 11 + lib/msvcrt/stdlib/obsol.c | 24 + lib/msvcrt/stdlib/putenv.c | 51 + lib/msvcrt/stdlib/qsort.c | 237 + lib/msvcrt/stdlib/rand.c | 20 + lib/msvcrt/stdlib/rot.c | 56 + lib/msvcrt/stdlib/senv.c | 56 + lib/msvcrt/stdlib/splitp.c | 91 + lib/msvcrt/stdlib/strtod.c | 97 + lib/msvcrt/stdlib/strtol.c | 91 + lib/msvcrt/stdlib/strtold.c | 122 + lib/msvcrt/stdlib/strtoll.c | 84 + lib/msvcrt/stdlib/strtoul.c | 74 + lib/msvcrt/stdlib/strtoull.c | 76 + lib/msvcrt/stdlib/swab.c | 18 + lib/msvcrt/stdlib/wcstod.c | 95 + lib/msvcrt/stdlib/wcstol.c | 33 + lib/msvcrt/stdlib/wcstom.c | 14 + lib/msvcrt/stdlib/wcstomb.c | 122 + lib/msvcrt/stdlib/wcstombs.c | 152 + lib/msvcrt/stdlib/wcstoul.c | 101 + lib/msvcrt/stdlib/wtoi.c | 11 + lib/msvcrt/stdlib/wtoi64.c | 31 + lib/msvcrt/string/.cvsignore | 3 + lib/msvcrt/string/memccpy.c | 9 + lib/msvcrt/string/memchr.c | 17 + lib/msvcrt/string/memcmp.c | 17 + lib/msvcrt/string/memcpy.c | 16 + lib/msvcrt/string/memicmp.c | 20 + lib/msvcrt/string/memmove.c | 36 + lib/msvcrt/string/memset.c | 13 + lib/msvcrt/string/strcat.c | 12 + lib/msvcrt/string/strchr.c | 19 + lib/msvcrt/string/strcmp.c | 14 + lib/msvcrt/string/strcoll.c | 39 + lib/msvcrt/string/strcpy.c | 11 + lib/msvcrt/string/strcspn.c | 19 + lib/msvcrt/string/strdup.c | 16 + lib/msvcrt/string/strerror.c | 108 + lib/msvcrt/string/stricmp.c | 22 + lib/msvcrt/string/strlen.c | 14 + lib/msvcrt/string/strlwr.c | 23 + lib/msvcrt/string/strncat.c | 22 + lib/msvcrt/string/strncmp.c | 18 + lib/msvcrt/string/strncpy.c | 21 + lib/msvcrt/string/strnicmp.c | 17 + lib/msvcrt/string/strnlen.c | 14 + lib/msvcrt/string/strpbrk.c | 18 + lib/msvcrt/string/strrchr.c | 20 + lib/msvcrt/string/strrev.c | 18 + lib/msvcrt/string/strset.c | 28 + lib/msvcrt/string/strspn.c | 16 + lib/msvcrt/string/strstr.c | 22 + lib/msvcrt/string/strtok.c | 50 + lib/msvcrt/string/strupr.c | 24 + lib/msvcrt/string/strxfrm.c | 22 + lib/msvcrt/sys_stat/.cvsignore | 3 + lib/msvcrt/sys_stat/fstat.c | 146 + lib/msvcrt/sys_stat/futime.c | 43 + lib/msvcrt/sys_stat/stat.c | 190 + lib/msvcrt/time/.cvsignore | 3 + lib/msvcrt/time/clock.c | 29 + lib/msvcrt/time/ctime.c | 1441 + lib/msvcrt/time/difftime.c | 8 + lib/msvcrt/time/posixrul.h | 49 + lib/msvcrt/time/strdate.c | 47 + lib/msvcrt/time/strftime.c | 264 + lib/msvcrt/time/strtime.c | 47 + lib/msvcrt/time/time.c | 223 + lib/msvcrt/time/tzfile.h | 160 + lib/msvcrt/wstring/.cvsignore | 3 + lib/msvcrt/wstring/wcscat.c | 18 + lib/msvcrt/wstring/wcschr.c | 16 + lib/msvcrt/wstring/wcscmp.c | 15 + lib/msvcrt/wstring/wcscoll.c | 26 + lib/msvcrt/wstring/wcscpy.c | 11 + lib/msvcrt/wstring/wcscspn.c | 20 + lib/msvcrt/wstring/wcsdup.c | 16 + lib/msvcrt/wstring/wcsicmp.c | 17 + lib/msvcrt/wstring/wcslen.c | 14 + lib/msvcrt/wstring/wcslwr.c | 22 + lib/msvcrt/wstring/wcsncat.c | 21 + lib/msvcrt/wstring/wcsncmp.c | 16 + lib/msvcrt/wstring/wcsncpy.c | 21 + lib/msvcrt/wstring/wcsnicmp.c | 14 + lib/msvcrt/wstring/wcsnlen.c | 10 + lib/msvcrt/wstring/wcspbrk.c | 16 + lib/msvcrt/wstring/wcsrchr.c | 15 + lib/msvcrt/wstring/wcsrev.c | 18 + lib/msvcrt/wstring/wcsset.c | 27 + lib/msvcrt/wstring/wcsspn.c | 20 + lib/msvcrt/wstring/wcsstr.c | 23 + lib/msvcrt/wstring/wcstok.c | 52 + lib/msvcrt/wstring/wcsupr.c | 12 + lib/msvcrt/wstring/wcsxfrm.c | 23 + lib/ntdll/.cvsignore | 9 + lib/ntdll/csr/.cvsignore | 3 + lib/ntdll/csr/capture.c | 86 + lib/ntdll/csr/lpc.c | 185 + lib/ntdll/csr/probe.c | 61 + lib/ntdll/csr/thread.c | 57 + lib/ntdll/dbg/.cvsignore | 3 + lib/ntdll/dbg/brkpoint.c | 29 + lib/ntdll/dbg/debug.c | 172 + lib/ntdll/dbg/print.c | 74 + lib/ntdll/dbg/winedbg.c | 251 + lib/ntdll/def/.cvsignore | 1 + lib/ntdll/def/ntdll.def | 948 + lib/ntdll/def/ntdll.edf | 947 + lib/ntdll/def/ntdll.rc | 37 + lib/ntdll/ldr/.cvsignore | 3 + lib/ntdll/ldr/startup.c | 280 + lib/ntdll/ldr/utils.c | 1912 ++ lib/ntdll/main/.cvsignore | 3 + lib/ntdll/main/dllmain.c | 23 + lib/ntdll/makefile | 82 + lib/ntdll/rtl/.cvsignore | 3 + lib/ntdll/rtl/access.c | 64 + lib/ntdll/rtl/acl.c | 552 + lib/ntdll/rtl/apc.c | 52 + lib/ntdll/rtl/atom.c | 700 + lib/ntdll/rtl/bitmap.c | 664 + lib/ntdll/rtl/callback.c | 37 + lib/ntdll/rtl/compress.c | 212 + lib/ntdll/rtl/critical.c | 171 + lib/ntdll/rtl/dos8dot3.c | 252 + lib/ntdll/rtl/env.c | 496 + lib/ntdll/rtl/error.c | 965 + lib/ntdll/rtl/exception.c | 57 + lib/ntdll/rtl/handle.c | 168 + lib/ntdll/rtl/heap.c | 1632 + lib/ntdll/rtl/i386/except.s | 291 + lib/ntdll/rtl/i386/exception.c | 433 + lib/ntdll/rtl/image.c | 146 + lib/ntdll/rtl/intrlck.c | 163 + lib/ntdll/rtl/largeint.c | 250 + lib/ntdll/rtl/luid.c | 49 + lib/ntdll/rtl/math.c | 197 + lib/ntdll/rtl/mem.c | 156 + lib/ntdll/rtl/message.c | 123 + lib/ntdll/rtl/misc.c | 77 + lib/ntdll/rtl/nls.c | 543 + lib/ntdll/rtl/path.c | 861 + lib/ntdll/rtl/ppb.c | 295 + lib/ntdll/rtl/process.c | 483 + lib/ntdll/rtl/propvar.c | 62 + lib/ntdll/rtl/registry.c | 982 + lib/ntdll/rtl/resource.c | 302 + lib/ntdll/rtl/sd.c | 660 + lib/ntdll/rtl/security.c | 65 + lib/ntdll/rtl/sid.c | 311 + lib/ntdll/rtl/thread.c | 273 + lib/ntdll/rtl/time.c | 337 + lib/ntdll/rtl/timezone.c | 200 + lib/ntdll/rtl/trace.c | 127 + lib/ntdll/rtl/unicode.c | 1792 ++ lib/ntdll/stdio/.cvsignore | 3 + lib/ntdll/stdio/sprintf.c | 539 + lib/ntdll/stdio/swprintf.c | 542 + lib/ntdll/stdlib/.cvsignore | 3 + lib/ntdll/stdlib/abs.c | 8 + lib/ntdll/stdlib/atoi.c | 8 + lib/ntdll/stdlib/atoi64.c | 41 + lib/ntdll/stdlib/atol.c | 8 + lib/ntdll/stdlib/itoa.c | 163 + lib/ntdll/stdlib/itow.c | 163 + lib/ntdll/stdlib/labs.c | 8 + lib/ntdll/stdlib/mbstowcs.c | 41 + lib/ntdll/stdlib/qsort.c | 266 + lib/ntdll/stdlib/splitp.c | 42 + lib/ntdll/stdlib/strtol.c | 89 + lib/ntdll/stdlib/strtoul.c | 73 + lib/ntdll/stdlib/wcstol.c | 89 + lib/ntdll/stdlib/wcstombs.c | 41 + lib/ntdll/stdlib/wcstoul.c | 73 + lib/ntdll/stdlib/wtoi.c | 8 + lib/ntdll/stdlib/wtoi64.c | 41 + lib/ntdll/stdlib/wtol.c | 8 + lib/ntdll/string/.cvsignore | 3 + lib/ntdll/string/ctype.c | 433 + lib/ntdll/string/memccpy.c | 9 + lib/ntdll/string/memchr.c | 17 + lib/ntdll/string/memcmp.c | 17 + lib/ntdll/string/memcpy.c | 16 + lib/ntdll/string/memicmp.c | 20 + lib/ntdll/string/memmove.c | 36 + lib/ntdll/string/memset.c | 13 + lib/ntdll/string/strcat.c | 12 + lib/ntdll/string/strchr.c | 21 + lib/ntdll/string/strcmp.c | 15 + lib/ntdll/string/strcpy.c | 10 + lib/ntdll/string/strcspn.c | 20 + lib/ntdll/string/stricmp.c | 22 + lib/ntdll/string/strlen.c | 14 + lib/ntdll/string/strlwr.c | 23 + lib/ntdll/string/strncat.c | 22 + lib/ntdll/string/strncmp.c | 18 + lib/ntdll/string/strncpy.c | 21 + lib/ntdll/string/strnicmp.c | 17 + lib/ntdll/string/strnlen.c | 14 + lib/ntdll/string/strpbrk.c | 18 + lib/ntdll/string/strrchr.c | 21 + lib/ntdll/string/strspn.c | 16 + lib/ntdll/string/strstr.c | 23 + lib/ntdll/string/strupr.c | 24 + lib/ntdll/string/wstring.c | 288 + lib/ntdll/stubs/.cvsignore | 3 + lib/ntdll/stubs/stubs.c | 153 + lib/ole32/.cvsignore | 2 + lib/ole32/CoXxx.c | 470 + lib/ole32/DllMain.c | 43 + lib/ole32/Misc.c | 115 + lib/ole32/Moniker.c | 508 + lib/ole32/Ole2.c | 2228 ++ lib/ole32/Ole32.h | 43 + lib/ole32/OleAuto.c | 36 + lib/ole32/Storage.c | 778 + lib/ole32/antimoniker.c | 645 + lib/ole32/bindctx.c | 544 + lib/ole32/compobj.c | 2060 ++ lib/ole32/compositemoniker.c | 1702 ++ lib/ole32/datacache.c | 2030 ++ lib/ole32/filemoniker.c | 1340 + lib/ole32/include/compobj.h | 15 + lib/ole32/include/debug.h | 91 + lib/ole32/include/ole32_main.h | 6 + lib/ole32/include/storage32.h | 864 + lib/ole32/itemmoniker.c | 973 + lib/ole32/makefile | 47 + lib/ole32/memlockbytes.c | 581 + lib/ole32/ole32.def | 307 + lib/ole32/ole32.rc | 38 + lib/ole32/rpcrt4_main.c | 306 + lib/ole32/stg_bigblockfile.c | 837 + lib/ole32/stg_stream.c | 835 + lib/ole32/storage32.c | 6989 +++++ lib/oleaut32/.cvsignore | 3 + lib/oleaut32/dllmain.c | 37 + lib/oleaut32/makefile | 21 + lib/oleaut32/oleaut32.def | 495 + lib/oleaut32/oleaut32.rc | 38 + lib/oleaut32/stubs.c | 2160 ++ lib/packet/.cvsignore | 19 + lib/packet/Packet32.c | 2056 ++ lib/packet/include/devioctl.h | 90 + lib/packet/include/ntddndis.h | 1400 + lib/packet/include/packet32.h | 289 + lib/packet/makefile | 25 + lib/packet/packet.def | 34 + lib/packet/packet.edf | 32 + lib/packet/packet.rc | 44 + lib/packet/resource.h | 15 + lib/packet/trace.c | 53 + lib/packet/trace.h | 62 + lib/psapi/enum/module.c | 274 + lib/psapi/enum/process.c | 110 + lib/psapi/include/internal/psapi.h | 90 + lib/psapi/makefile | 26 + lib/psapi/misc/dllmain.c | 32 + lib/psapi/misc/malloc.c | 65 + lib/psapi/misc/stubs.c | 63 + lib/psapi/misc/win32.c | 938 + lib/psapi/psapi.def | 29 + lib/psapi/psapi.edf | 29 + lib/psapi/psapi.rc | 38 + lib/rpcrt4/Makefile | 137 + lib/rpcrt4/include/rpc.h | 117 + lib/rpcrt4/include/rpcrt4/rpc.h | 43 + lib/rpcrt4/midl/Makefile | 51 + lib/rpcrt4/midl/hello.idl | 34 + lib/rpcrt4/midl/idl.l | 114 + lib/rpcrt4/midl/idl.y | 201 + lib/rpcrt4/midl/interface.c | 74 + lib/rpcrt4/midl/midl.c | 79 + lib/rpcrt4/midl/midl.h | 37 + lib/rpcrt4/midl/option.c | 16 + lib/rpcrt4/midl/types.c | 190 + lib/rpcrt4/midl/types.h | 42 + lib/secur32/.cvsignore | 3 + lib/secur32/Makefile | 22 + lib/secur32/dllmain.c | 42 + lib/secur32/lsa.c | 309 + lib/secur32/secur32.def | 9 + lib/secur32/secur32.edf | 9 + lib/secur32/secur32.rc | 38 + lib/shell32/.cvsignore | 19 + lib/shell32/control/control.c | 551 + lib/shell32/control/control.h | 174 + lib/shell32/control/framewnd.c | 458 + lib/shell32/control/framewnd.h | 45 + lib/shell32/control/listview.c | 660 + lib/shell32/control/listview.h | 48 + lib/shell32/control/settings.c | 157 + lib/shell32/control/settings.h | 44 + lib/shell32/control/trace.c | 82 + lib/shell32/control/trace.h | 72 + lib/shell32/makefile | 55 + lib/shell32/misc/_stubs.cpp | 89 + lib/shell32/misc/dllmain.c | 71 + lib/shell32/misc/shlwapi.h | 726 + lib/shell32/misc/stubs.c | 2615 ++ lib/shell32/res/control.ico | Bin 0 -> 1078 bytes lib/shell32/res/small.ico | Bin 0 -> 318 bytes lib/shell32/resource.h | 54 + lib/shell32/roshel32.rc | 290 + lib/shell32/shell32.def | 381 + lib/shell32/shell32.edf | 381 + lib/shell32/shell32.h | 104 + lib/shell32/shell32.rc | 38 + lib/snmpapi/.cvsignore | 23 + lib/snmpapi/debug.h | 65 + lib/snmpapi/makefile | 19 + lib/snmpapi/snmpapi.c | 408 + lib/snmpapi/snmpapi.def | 43 + lib/snmpapi/snmpapi.edf | 43 + lib/snmpapi/snmpapi.rc | 39 + lib/user32/.cvsignore | 9 + lib/user32/Makefile | 76 + lib/user32/controls/.cvsignore | 4 + lib/user32/controls/combobox.c | 42 + lib/user32/controls/listbox.c | 41 + lib/user32/controls/scrollbar.c | 103 + lib/user32/include/debug.h | 72 + lib/user32/include/user32.h | 11 + lib/user32/include/window.h | 13 + lib/user32/include/winsta.h | 6 + lib/user32/misc/.cvsignore | 5 + lib/user32/misc/dde.c | 332 + lib/user32/misc/desktop.c | 256 + lib/user32/misc/display.c | 167 + lib/user32/misc/dllmain.c | 76 + lib/user32/misc/exit.c | 66 + lib/user32/misc/object.c | 89 + lib/user32/misc/resources.c | 59 + lib/user32/misc/sprintf.c | 940 + lib/user32/misc/stubs.c | 531 + lib/user32/misc/timer.c | 55 + lib/user32/misc/winhelp.c | 148 + lib/user32/misc/winsta.c | 136 + lib/user32/resources/obm_btncorners.bmp | Bin 0 -> 118 bytes lib/user32/resources/obm_btsize.bmp | Bin 0 -> 122 bytes lib/user32/resources/obm_check.bmp | Bin 0 -> 118 bytes lib/user32/resources/obm_checkboxes.bmp | Bin 0 -> 374 bytes lib/user32/resources/obm_close.bmp | Bin 0 -> 478 bytes lib/user32/resources/obm_combo.bmp | Bin 0 -> 98 bytes lib/user32/resources/obm_dnarrow.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_dnarrowd.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_dnarrowi.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_lfarrow.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_lfarrowd.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_lfarrowi.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_mnarrow.bmp | Bin 0 -> 106 bytes lib/user32/resources/obm_old_close.bmp | Bin 0 -> 478 bytes lib/user32/resources/obm_old_dnarrow.bmp | Bin 0 -> 122 bytes lib/user32/resources/obm_old_lfarrow.bmp | Bin 0 -> 122 bytes lib/user32/resources/obm_old_reduce.bmp | Bin 0 -> 138 bytes lib/user32/resources/obm_old_restore.bmp | Bin 0 -> 138 bytes lib/user32/resources/obm_old_rgarrow.bmp | Bin 0 -> 122 bytes lib/user32/resources/obm_old_uparrow.bmp | Bin 0 -> 122 bytes lib/user32/resources/obm_old_zoom.bmp | Bin 0 -> 138 bytes lib/user32/resources/obm_reduce.bmp | Bin 0 -> 230 bytes lib/user32/resources/obm_reduced.bmp | Bin 0 -> 230 bytes lib/user32/resources/obm_restore.bmp | Bin 0 -> 230 bytes lib/user32/resources/obm_restored.bmp | Bin 0 -> 230 bytes lib/user32/resources/obm_rgarrow.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_rgarrowd.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_rgarrowi.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_size.bmp | Bin 0 -> 114 bytes lib/user32/resources/obm_trtype.bmp | Bin 0 -> 230 bytes lib/user32/resources/obm_uparrow.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_uparrowd.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_uparrowi.bmp | Bin 0 -> 322 bytes lib/user32/resources/obm_zoom.bmp | Bin 0 -> 230 bytes lib/user32/resources/obm_zoomd.bmp | Bin 0 -> 230 bytes lib/user32/resources/ocr_appstarting.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_cross.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_dragobject.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_hand.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_help.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_ibeam.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_icon.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_no.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_normal.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_size.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_sizeall.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_sizenesw.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_sizens.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_sizenwse.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_sizewe.cur | Bin 0 -> 328 bytes lib/user32/resources/ocr_up.cur | Bin 0 -> 326 bytes lib/user32/resources/ocr_wait.cur | Bin 0 -> 326 bytes lib/user32/resources/oic_bang.ico | Bin 0 -> 766 bytes lib/user32/resources/oic_hand.ico | Bin 0 -> 766 bytes lib/user32/resources/oic_note.ico | Bin 0 -> 766 bytes lib/user32/resources/oic_ques.ico | Bin 0 -> 766 bytes lib/user32/resources/oic_sample.ico | Bin 0 -> 766 bytes lib/user32/user32.def | 702 + lib/user32/user32.edf | 701 + lib/user32/user32.rc | 65 + lib/user32/windows/.cvsignore | 4 + lib/user32/windows/accel.c | 128 + lib/user32/windows/bitmap.c | 266 + lib/user32/windows/class.c | 299 + lib/user32/windows/clipboard.c | 177 + lib/user32/windows/cursor.c | 191 + lib/user32/windows/dc.c | 75 + lib/user32/windows/defwnd.c | 1587 + lib/user32/windows/dialog.c | 458 + lib/user32/windows/draw.c | 228 + lib/user32/windows/font.c | 108 + lib/user32/windows/hook.c | 82 + lib/user32/windows/icon.c | 167 + lib/user32/windows/input.c | 279 + lib/user32/windows/mdi.c | 98 + lib/user32/windows/menu.c | 583 + lib/user32/windows/message.c | 497 + lib/user32/windows/messagebox.c | 97 + lib/user32/windows/nonclient.c | 478 + lib/user32/windows/paint.c | 161 + lib/user32/windows/prop.c | 181 + lib/user32/windows/rect.c | 200 + lib/user32/windows/text.c | 297 + lib/user32/windows/window.c | 939 + lib/version/.cvsignore | 3 + lib/version/makefile | 21 + lib/version/misc/libmain.c | 23 + lib/version/misc/stubs.c | 223 + lib/version/version.def | 19 + lib/version/version.edf | 19 + lib/version/version.rc | 38 + lib/version/version_specs | 78 + lib/winmm/.cvsignore | 4 + lib/winmm/Makefile | 21 + lib/winmm/dllmain.c | 36 + lib/winmm/misc/stubs.c | 32 + lib/winmm/winmm.def | 6 + lib/winmm/winmm.edf | 6 + lib/winmm/winmm.rc | 38 + lib/ws2_32/.cvsignore | 7 + lib/ws2_32/include/catalog.h | 60 + lib/ws2_32/include/debug.h | 66 + lib/ws2_32/include/handle.h | 47 + lib/ws2_32/include/upcall.h | 114 + lib/ws2_32/include/ws2_32.h | 88 + lib/ws2_32/makefile | 26 + lib/ws2_32/misc/bsd.c | 44 + lib/ws2_32/misc/catalog.c | 314 + lib/ws2_32/misc/dllmain.c | 578 + lib/ws2_32/misc/event.c | 202 + lib/ws2_32/misc/handle.c | 277 + lib/ws2_32/misc/ns.c | 515 + lib/ws2_32/misc/sndrcv.c | 280 + lib/ws2_32/misc/stubs.c | 457 + lib/ws2_32/misc/upcall.c | 220 + lib/ws2_32/ws2_32.def | 116 + lib/ws2_32/ws2_32.edf | 116 + lib/ws2_32/ws2_32.rc | 39 + lib/ws2_32/ws2_32_specs | 78 + lib/ws2help/.cvsignore | 23 + lib/ws2help/debug.h | 65 + lib/ws2help/makefile | 19 + lib/ws2help/ws2help.c | 327 + lib/ws2help/ws2help.def | 30 + lib/ws2help/ws2help.edf | 30 + lib/ws2help/ws2help.h | 22 + lib/ws2help/ws2help.rc | 39 + lib/wshirda/.cvsignore | 23 + lib/wshirda/debug.h | 65 + lib/wshirda/makefile | 19 + lib/wshirda/wshirda.c | 206 + lib/wshirda/wshirda.def | 19 + lib/wshirda/wshirda.edf | 18 + lib/wshirda/wshirda.h | 22 + lib/wshirda/wshirda.rc | 39 + loaders/boot/boot.asm | 309 + loaders/boot/boot.inc | 196 + loaders/boot/boot.mak | 77 + loaders/boot/bootbk.asm | 313 + loaders/boot/osldr.asm | 340 + loaders/boot/osldr.txt | 12 + loaders/dos/loadros.asm | 1302 + loaders/dos/makefile | 31 + makedisk.bat | 33 + media/fonts/helb____.ttf | Bin 0 -> 51648 bytes media/fonts/timr____.ttf | Bin 0 -> 61816 bytes media/nls/c_037.nls | Bin 0 -> 66082 bytes media/nls/c_10000.nls | Bin 0 -> 66082 bytes media/nls/c_10006.nls | Bin 0 -> 66082 bytes media/nls/c_10007.nls | Bin 0 -> 66082 bytes media/nls/c_10029.nls | Bin 0 -> 66082 bytes media/nls/c_1006.nls | Bin 0 -> 66082 bytes media/nls/c_10079.nls | Bin 0 -> 66082 bytes media/nls/c_10081.nls | Bin 0 -> 66082 bytes media/nls/c_1026.nls | Bin 0 -> 66082 bytes media/nls/c_1250.nls | Bin 0 -> 66082 bytes media/nls/c_1251.nls | Bin 0 -> 66082 bytes media/nls/c_1252.nls | Bin 0 -> 66082 bytes media/nls/c_1253.nls | Bin 0 -> 66082 bytes media/nls/c_1254.nls | Bin 0 -> 66082 bytes media/nls/c_1255.nls | Bin 0 -> 66082 bytes media/nls/c_1256.nls | Bin 0 -> 66082 bytes media/nls/c_1257.nls | Bin 0 -> 66082 bytes media/nls/c_1258.nls | Bin 0 -> 66082 bytes media/nls/c_20866.nls | Bin 0 -> 66082 bytes media/nls/c_28591.nls | Bin 0 -> 66082 bytes media/nls/c_28592.nls | Bin 0 -> 66082 bytes media/nls/c_28593.nls | Bin 0 -> 66082 bytes media/nls/c_28594.nls | Bin 0 -> 66082 bytes media/nls/c_28595.nls | Bin 0 -> 66082 bytes media/nls/c_28596.nls | Bin 0 -> 66082 bytes media/nls/c_28597.nls | Bin 0 -> 66082 bytes media/nls/c_28598.nls | Bin 0 -> 66082 bytes media/nls/c_28599.nls | Bin 0 -> 66082 bytes media/nls/c_424.nls | Bin 0 -> 66082 bytes media/nls/c_437.nls | Bin 0 -> 66594 bytes media/nls/c_500.nls | Bin 0 -> 66082 bytes media/nls/c_737.nls | Bin 0 -> 66594 bytes media/nls/c_775.nls | Bin 0 -> 66594 bytes media/nls/c_850.nls | Bin 0 -> 66594 bytes media/nls/c_852.nls | Bin 0 -> 66594 bytes media/nls/c_855.nls | Bin 0 -> 66594 bytes media/nls/c_856.nls | Bin 0 -> 66594 bytes media/nls/c_857.nls | Bin 0 -> 66594 bytes media/nls/c_860.nls | Bin 0 -> 66594 bytes media/nls/c_861.nls | Bin 0 -> 66594 bytes media/nls/c_862.nls | Bin 0 -> 66594 bytes media/nls/c_863.nls | Bin 0 -> 66594 bytes media/nls/c_864.nls | Bin 0 -> 66594 bytes media/nls/c_865.nls | Bin 0 -> 66594 bytes media/nls/c_866.nls | Bin 0 -> 66594 bytes media/nls/c_869.nls | Bin 0 -> 66594 bytes media/nls/c_874.nls | Bin 0 -> 66082 bytes media/nls/c_875.nls | Bin 0 -> 66082 bytes media/nls/c_878.nls | Bin 0 -> 66082 bytes media/nls/c_932.nls | Bin 0 -> 162850 bytes media/nls/c_936.nls | Bin 0 -> 196642 bytes media/nls/c_949.nls | Bin 0 -> 196642 bytes media/nls/c_950.nls | Bin 0 -> 196642 bytes media/nls/l_intl.nls | Bin 0 -> 4870 bytes ntoskrnl/.cvsignore | 11 + ntoskrnl/Makefile | 710 + ntoskrnl/Makefile.i386 | 54 + ntoskrnl/cc/.cvsignore | 3 + ntoskrnl/cc/cacheman.c | 42 + ntoskrnl/cc/copy.c | 671 + ntoskrnl/cc/misc.c | 109 + ntoskrnl/cc/pin.c | 127 + ntoskrnl/cc/view.c | 916 + ntoskrnl/cm/.cvsignore | 3 + ntoskrnl/cm/cm.h | 499 + ntoskrnl/cm/import.c | 610 + ntoskrnl/cm/ntfunc.c | 1601 + ntoskrnl/cm/regfile.c | 1906 ++ ntoskrnl/cm/registry.c | 779 + ntoskrnl/cm/regobj.c | 470 + ntoskrnl/cm/rtlfunc.c | 747 + ntoskrnl/dbg/.cvsignore | 3 + ntoskrnl/dbg/dbgctrl.c | 63 + ntoskrnl/dbg/errinfo.c | 281 + ntoskrnl/dbg/i386/.cvsignore | 1 + ntoskrnl/dbg/i386/kdb_help.S | 89 + ntoskrnl/dbg/kdb.c | 689 + ntoskrnl/dbg/kdb.h | 12 + ntoskrnl/dbg/kdb_keyboard.c | 354 + ntoskrnl/dbg/kdb_stabs.c | 885 + ntoskrnl/dbg/print.c | 98 + ntoskrnl/dbg/rdebug.c | 154 + ntoskrnl/dbg/user.c | 110 + ntoskrnl/ex/.cvsignore | 3 + ntoskrnl/ex/btree.c | 662 + ntoskrnl/ex/callback.c | 87 + ntoskrnl/ex/fmutex.c | 67 + ntoskrnl/ex/hashtab.c | 320 + ntoskrnl/ex/i386/.cvsignore | 2 + ntoskrnl/ex/i386/interlck.c | 162 + ntoskrnl/ex/init.c | 67 + ntoskrnl/ex/interlck.c | 216 + ntoskrnl/ex/list.c | 377 + ntoskrnl/ex/lookas.c | 320 + ntoskrnl/ex/napi.c | 39 + ntoskrnl/ex/power.c | 68 + ntoskrnl/ex/resource.c | 798 + ntoskrnl/ex/stree.c | 1356 + ntoskrnl/ex/sysinfo.c | 1163 + ntoskrnl/ex/time.c | 135 + ntoskrnl/ex/win32k.c | 318 + ntoskrnl/ex/work.c | 194 + ntoskrnl/ex/zone.c | 107 + ntoskrnl/fs/.cvsignore | 3 + ntoskrnl/fs/dbcsname.c | 126 + ntoskrnl/fs/filelock.c | 381 + ntoskrnl/fs/mcb.c | 228 + ntoskrnl/fs/mdl.c | 270 + ntoskrnl/fs/name.c | 112 + ntoskrnl/fs/notify.c | 248 + ntoskrnl/fs/oplock.c | 123 + ntoskrnl/fs/pool.c | 151 + ntoskrnl/fs/tunnel.c | 123 + ntoskrnl/fs/unc.c | 47 + ntoskrnl/fs/util.c | 317 + ntoskrnl/include/internal/arch/ke.h | 30 + ntoskrnl/include/internal/arch/mm.h | 28 + ntoskrnl/include/internal/arch/ps.h | 33 + ntoskrnl/include/internal/cc.h | 89 + ntoskrnl/include/internal/config.h | 7 + ntoskrnl/include/internal/ctype.h | 76 + ntoskrnl/include/internal/dbg.h | 19 + ntoskrnl/include/internal/debug.h | 93 + ntoskrnl/include/internal/ex.h | 68 + ntoskrnl/include/internal/hal/bus.h | 121 + ntoskrnl/include/internal/hal/hal.h | 48 + ntoskrnl/include/internal/hal/mps.h | 435 + ntoskrnl/include/internal/handle.h | 26 + ntoskrnl/include/internal/i386/fpu.h | 28 + ntoskrnl/include/internal/i386/ke.h | 138 + ntoskrnl/include/internal/i386/mm.h | 57 + ntoskrnl/include/internal/i386/ps.h | 94 + ntoskrnl/include/internal/i386/segment.h | 50 + ntoskrnl/include/internal/id.h | 19 + ntoskrnl/include/internal/ifs.h | 8 + ntoskrnl/include/internal/io.h | 350 + ntoskrnl/include/internal/kd.h | 107 + ntoskrnl/include/internal/ke.h | 112 + ntoskrnl/include/internal/ldr.h | 133 + ntoskrnl/include/internal/mm.h | 610 + ntoskrnl/include/internal/module.h | 61 + ntoskrnl/include/internal/nt.h | 7 + ntoskrnl/include/internal/ntoskrnl.h | 67 + ntoskrnl/include/internal/ob.h | 112 + ntoskrnl/include/internal/po.h | 27 + ntoskrnl/include/internal/pool.h | 28 + ntoskrnl/include/internal/port.h | 146 + ntoskrnl/include/internal/ps.h | 508 + ntoskrnl/include/internal/registry.h | 14 + ntoskrnl/include/internal/safe.h | 16 + ntoskrnl/include/internal/se.h | 127 + ntoskrnl/include/internal/trap.h | 58 + ntoskrnl/include/internal/v86m.h | 101 + ntoskrnl/include/internal/xhal.h | 39 + ntoskrnl/io/.cvsignore | 3 + ntoskrnl/io/adapter.c | 44 + ntoskrnl/io/arcname.c | 420 + ntoskrnl/io/buildirp.c | 521 + ntoskrnl/io/cancel.c | 85 + ntoskrnl/io/cleanup.c | 268 + ntoskrnl/io/cntrller.c | 166 + ntoskrnl/io/create.c | 554 + ntoskrnl/io/device.c | 737 + ntoskrnl/io/dir.c | 173 + ntoskrnl/io/driver.c | 605 + ntoskrnl/io/errlog.c | 60 + ntoskrnl/io/error.c | 62 + ntoskrnl/io/event.c | 97 + ntoskrnl/io/file.c | 351 + ntoskrnl/io/flush.c | 86 + ntoskrnl/io/fs.c | 733 + ntoskrnl/io/iocomp.c | 83 + ntoskrnl/io/ioctrl.c | 117 + ntoskrnl/io/iomgr.c | 279 + ntoskrnl/io/iowork.c | 91 + ntoskrnl/io/irp.c | 397 + ntoskrnl/io/lock.c | 49 + ntoskrnl/io/mailslot.c | 67 + ntoskrnl/io/mdl.c | 85 + ntoskrnl/io/npipe.c | 76 + ntoskrnl/io/page.c | 128 + ntoskrnl/io/parttab.c | 62 + ntoskrnl/io/pnpmgr.c | 1217 + ntoskrnl/io/pnproot.c | 965 + ntoskrnl/io/process.c | 92 + ntoskrnl/io/queue.c | 138 + ntoskrnl/io/resource.c | 265 + ntoskrnl/io/rw.c | 360 + ntoskrnl/io/share.c | 342 + ntoskrnl/io/shutdown.c | 128 + ntoskrnl/io/symlink.c | 453 + ntoskrnl/io/timer.c | 87 + ntoskrnl/io/vpb.c | 365 + ntoskrnl/io/xhaldisp.c | 49 + ntoskrnl/io/xhaldrv.c | 808 + ntoskrnl/kd/.cvsignore | 3 + ntoskrnl/kd/dlog.c | 222 + ntoskrnl/kd/gdbstub.c | 1348 + ntoskrnl/kd/kdebug.c | 456 + ntoskrnl/kd/mda.c | 151 + ntoskrnl/kd/service.c | 116 + ntoskrnl/ke/.cvsignore | 3 + ntoskrnl/ke/apc.c | 562 + ntoskrnl/ke/bug.c | 184 + ntoskrnl/ke/catch.c | 209 + ntoskrnl/ke/critical.c | 34 + ntoskrnl/ke/dpc.c | 231 + ntoskrnl/ke/error.c | 38 + ntoskrnl/ke/event.c | 93 + ntoskrnl/ke/i386/.cvsignore | 3 + ntoskrnl/ke/i386/bios.c | 94 + ntoskrnl/ke/i386/brkpoint.c | 46 + ntoskrnl/ke/i386/bthread.S | 146 + ntoskrnl/ke/i386/exp.c | 629 + ntoskrnl/ke/i386/fpu.c | 74 + ntoskrnl/ke/i386/gdt.c | 212 + ntoskrnl/ke/i386/i386-mcount.S | 52 + ntoskrnl/ke/i386/idt.c | 31 + ntoskrnl/ke/i386/irq.c | 718 + ntoskrnl/ke/i386/irqhand.s | 403 + ntoskrnl/ke/i386/kernel.c | 142 + ntoskrnl/ke/i386/ldt.c | 72 + ntoskrnl/ke/i386/multiboot.S | 368 + ntoskrnl/ke/i386/stkswitch.S | 82 + ntoskrnl/ke/i386/syscall.S | 254 + ntoskrnl/ke/i386/thread.c | 198 + ntoskrnl/ke/i386/trap.s | 345 + ntoskrnl/ke/i386/tskswitch.S | 155 + ntoskrnl/ke/i386/tss.c | 208 + ntoskrnl/ke/i386/usercall.c | 101 + ntoskrnl/ke/i386/usertrap.c | 149 + ntoskrnl/ke/i386/v86m.c | 812 + ntoskrnl/ke/i386/v86m_sup.S | 213 + ntoskrnl/ke/kqueue.c | 198 + ntoskrnl/ke/kthread.c | 238 + ntoskrnl/ke/main.c | 764 + ntoskrnl/ke/mutex.c | 169 + ntoskrnl/ke/process.c | 102 + ntoskrnl/ke/queue.c | 97 + ntoskrnl/ke/sem.c | 108 + ntoskrnl/ke/spinlock.c | 115 + ntoskrnl/ke/timer.c | 459 + ntoskrnl/ke/wait.c | 877 + ntoskrnl/ldr/.cvsignore | 3 + ntoskrnl/ldr/init.c | 376 + ntoskrnl/ldr/loader.c | 1611 + ntoskrnl/ldr/resource.c | 184 + ntoskrnl/ldr/rtl.c | 235 + ntoskrnl/ldr/sysdll.c | 288 + ntoskrnl/ldr/userldr.c | 69 + ntoskrnl/lpc/.cvsignore | 3 + ntoskrnl/lpc/close.c | 98 + ntoskrnl/lpc/complete.c | 60 + ntoskrnl/lpc/connect.c | 755 + ntoskrnl/lpc/create.c | 178 + ntoskrnl/lpc/listen.c | 79 + ntoskrnl/lpc/port.c | 131 + ntoskrnl/lpc/query.c | 74 + ntoskrnl/lpc/queue.c | 88 + ntoskrnl/lpc/receive.c | 46 + ntoskrnl/lpc/reply.c | 338 + ntoskrnl/lpc/send.c | 317 + ntoskrnl/mkconfig.c | 112 + ntoskrnl/mm/.cvsignore | 3 + ntoskrnl/mm/anonmem.c | 877 + ntoskrnl/mm/aspace.c | 109 + ntoskrnl/mm/balance.c | 294 + ntoskrnl/mm/cont.c | 153 + ntoskrnl/mm/drvlck.c | 86 + ntoskrnl/mm/freelist.c | 824 + ntoskrnl/mm/i386/.cvsignore | 2 + ntoskrnl/mm/i386/memsafe.s | 83 + ntoskrnl/mm/i386/page.c | 1124 + ntoskrnl/mm/i386/pfault.c | 95 + ntoskrnl/mm/iospace.c | 173 + ntoskrnl/mm/kmap.c | 209 + ntoskrnl/mm/marea.c | 422 + ntoskrnl/mm/mdl.c | 453 + ntoskrnl/mm/mm.c | 443 + ntoskrnl/mm/mminit.c | 365 + ntoskrnl/mm/mpw.c | 135 + ntoskrnl/mm/ncache.c | 136 + ntoskrnl/mm/npool.c | 1055 + ntoskrnl/mm/pagefile.c | 689 + ntoskrnl/mm/pageop.c | 241 + ntoskrnl/mm/pager.c | 78 + ntoskrnl/mm/pagfault.c | 19 + ntoskrnl/mm/paging.c | 19 + ntoskrnl/mm/pool.c | 154 + ntoskrnl/mm/ppool.c | 265 + ntoskrnl/mm/region.c | 303 + ntoskrnl/mm/rmap.c | 443 + ntoskrnl/mm/section.c | 3547 +++ ntoskrnl/mm/slab.c | 322 + ntoskrnl/mm/virtual.c | 362 + ntoskrnl/mm/wset.c | 66 + ntoskrnl/nls/.cvsignore | 3 + ntoskrnl/nls/nls.c | 21 + ntoskrnl/nt/.cvsignore | 3 + ntoskrnl/nt/channel.c | 73 + ntoskrnl/nt/evtpair.c | 304 + ntoskrnl/nt/misc.c | 34 + ntoskrnl/nt/mutant.c | 221 + ntoskrnl/nt/nt.c | 32 + ntoskrnl/nt/ntevent.c | 334 + ntoskrnl/nt/ntsem.c | 188 + ntoskrnl/nt/nttimer.c | 349 + ntoskrnl/nt/plugplay.c | 27 + ntoskrnl/nt/profile.c | 576 + ntoskrnl/nt/vdm.c | 52 + ntoskrnl/ntoskrnl.dbg.lnk | 86 + ntoskrnl/ntoskrnl.def | 1059 + ntoskrnl/ntoskrnl.edf | 1057 + ntoskrnl/ntoskrnl.full.def | 1070 + ntoskrnl/ntoskrnl.lnk | 99 + ntoskrnl/ntoskrnl.mc | 1029 + ntoskrnl/ntoskrnl.rc | 39 + ntoskrnl/ntoskrnl.txt | 1084 + ntoskrnl/ob/.cvsignore | 3 + ntoskrnl/ob/dirobj.c | 348 + ntoskrnl/ob/handle.c | 749 + ntoskrnl/ob/namespc.c | 445 + ntoskrnl/ob/ntobj.c | 220 + ntoskrnl/ob/object.c | 598 + ntoskrnl/ob/security.c | 97 + ntoskrnl/objects/.cvsignore | 2 + ntoskrnl/po/.cvsignore | 3 + ntoskrnl/po/power.c | 200 + ntoskrnl/ps/.cvsignore | 3 + ntoskrnl/ps/create.c | 689 + ntoskrnl/ps/debug.c | 275 + ntoskrnl/ps/idle.c | 69 + ntoskrnl/ps/kill.c | 372 + ntoskrnl/ps/locale.c | 272 + ntoskrnl/ps/process.c | 1248 + ntoskrnl/ps/psmgr.c | 102 + ntoskrnl/ps/suspend.c | 217 + ntoskrnl/ps/thread.c | 650 + ntoskrnl/ps/tinfo.c | 336 + ntoskrnl/ps/w32call.c | 251 + ntoskrnl/ps/win32.c | 104 + ntoskrnl/rtl/.cvsignore | 3 + ntoskrnl/rtl/atom.c | 917 + ntoskrnl/rtl/bitmap.c | 649 + ntoskrnl/rtl/capture.c | 120 + ntoskrnl/rtl/compress.c | 205 + ntoskrnl/rtl/ctype.c | 443 + ntoskrnl/rtl/dos8dot3.c | 253 + ntoskrnl/rtl/error.c | 963 + ntoskrnl/rtl/handle.c | 186 + ntoskrnl/rtl/i386/.cvsignore | 2 + ntoskrnl/rtl/i386/except.s | 291 + ntoskrnl/rtl/i386/exception.c | 475 + ntoskrnl/rtl/i386/memcpy.c | 34 + ntoskrnl/rtl/i386/memset.c | 31 + ntoskrnl/rtl/i386/seh.s | 366 + ntoskrnl/rtl/largeint.c | 250 + ntoskrnl/rtl/mem.c | 206 + ntoskrnl/rtl/memchr.c | 42 + ntoskrnl/rtl/memcmp.c | 47 + ntoskrnl/rtl/memcpy.c | 31 + ntoskrnl/rtl/memmove.c | 35 + ntoskrnl/rtl/memset.c | 14 + ntoskrnl/rtl/message.c | 123 + ntoskrnl/rtl/nls.c | 617 + ntoskrnl/rtl/purecall.c | 23 + ntoskrnl/rtl/qsort.c | 266 + ntoskrnl/rtl/regio.c | 158 + ntoskrnl/rtl/sprintf.c | 553 + ntoskrnl/rtl/stdlib.c | 259 + ntoskrnl/rtl/string.c | 308 + ntoskrnl/rtl/strtok.c | 111 + ntoskrnl/rtl/swprintf.c | 541 + ntoskrnl/rtl/time.c | 267 + ntoskrnl/rtl/timezone.c | 200 + ntoskrnl/rtl/unicode.c | 1569 + ntoskrnl/rtl/wstring.c | 308 + ntoskrnl/se/.cvsignore | 3 + ntoskrnl/se/access.c | 63 + ntoskrnl/se/acl.c | 325 + ntoskrnl/se/lsa.c | 83 + ntoskrnl/se/luid.c | 69 + ntoskrnl/se/priv.c | 306 + ntoskrnl/se/sd.c | 394 + ntoskrnl/se/semgr.c | 501 + ntoskrnl/se/sid.c | 669 + ntoskrnl/se/token.c | 1286 + rosbin.txt | 67 + rules.mak | 116 + services/eventlog/.cvsignore | 4 + services/eventlog/eventlog.c | 113 + services/eventlog/eventlog.h | 12 + services/eventlog/eventlog.rc | 38 + services/eventlog/logport.c | 187 + services/eventlog/makefile | 21 + services/rpcss/.cvsignore | 4 + services/rpcss/endpoint.c | 47 + services/rpcss/makefile | 21 + services/rpcss/rpcss.c | 110 + services/rpcss/rpcss.h | 9 + services/rpcss/rpcss.rc | 38 + subsys/csrss/.cvsignore | 7 + subsys/csrss/api.h | 163 + subsys/csrss/api/.cvsignore | 3 + subsys/csrss/api/conio.c | 2150 ++ subsys/csrss/api/handle.c | 93 + subsys/csrss/api/process.c | 261 + subsys/csrss/api/user.c | 69 + subsys/csrss/api/wapi.c | 182 + subsys/csrss/csrss.c | 137 + subsys/csrss/csrss.rc | 38 + subsys/csrss/init.c | 212 + subsys/csrss/lpcstub.c | 42 + subsys/csrss/makefile | 37 + subsys/csrss/print.c | 63 + subsys/csrss/video.c | 126 + subsys/ntvdm/.cvsignore | 6 + subsys/ntvdm/makefile | 21 + subsys/ntvdm/ntvdm.c | 144 + subsys/ntvdm/ntvdm.rc | 38 + subsys/smss/.cvsignore | 6 + subsys/smss/init.c | 837 + subsys/smss/makefile | 21 + subsys/smss/smapi.c | 125 + subsys/smss/smss.c | 102 + subsys/smss/smss.h | 40 + subsys/smss/smss.rc | 38 + subsys/system/autochk/.cvsignore | 6 + subsys/system/autochk/autochk.c | 89 + subsys/system/autochk/autochk.rc | 38 + subsys/system/autochk/makefile | 21 + subsys/system/gstart/.cvsignore | 6 + subsys/system/gstart/Makefile | 21 + subsys/system/gstart/gstart.c | 89 + subsys/system/gstart/gstart.rc | 38 + subsys/system/lsass/init.c | 43 + subsys/system/lsass/lsasrv.def | 68 + subsys/system/lsass/lsass.c | 72 + subsys/system/lsass/lsass.rc | 38 + subsys/system/lsass/makefile | 19 + subsys/system/services/.cvsignore | 6 + subsys/system/services/database.c | 723 + subsys/system/services/makefile | 21 + subsys/system/services/services.c | 303 + subsys/system/services/services.h | 19 + subsys/system/services/services.rc | 38 + subsys/system/shell/.cvsignore | 6 + subsys/system/shell/makefile | 21 + subsys/system/shell/shell.c | 504 + subsys/system/shell/shell.rc | 38 + subsys/system/usetup/.cvsignore | 5 + subsys/system/usetup/console.c | 1025 + subsys/system/usetup/console.h | 127 + subsys/system/usetup/drivesup.c | 163 + subsys/system/usetup/drivesup.h | 37 + subsys/system/usetup/makefile | 21 + subsys/system/usetup/partlist.c | 693 + subsys/system/usetup/partlist.h | 113 + subsys/system/usetup/usetup.c | 1146 + subsys/system/usetup/usetup.h | 43 + subsys/system/usetup/usetup.rc | 38 + subsys/system/winlogon/.cvsignore | 6 + subsys/system/winlogon/makefile | 21 + subsys/system/winlogon/winlogon.c | 364 + subsys/system/winlogon/winlogon.rc | 38 + subsys/win32k/.cvsignore | 8 + subsys/win32k/dib/.cvsignore | 3 + subsys/win32k/dib/dib.h | 35 + subsys/win32k/dib/dib1bpp.c | 122 + subsys/win32k/dib/dib24bpp.c | 155 + subsys/win32k/dib/dib4bpp.c | 164 + subsys/win32k/eng/.cvsignore | 3 + subsys/win32k/eng/bitblt.c | 225 + subsys/win32k/eng/brush.c | 25 + subsys/win32k/eng/brush.h | 58 + subsys/win32k/eng/clip.c | 135 + subsys/win32k/eng/clip.h | 17 + subsys/win32k/eng/copybits.c | 209 + subsys/win32k/eng/debug.c | 21 + subsys/win32k/eng/device.c | 61 + subsys/win32k/eng/handle.c | 114 + subsys/win32k/eng/handle.h | 27 + subsys/win32k/eng/lineto.c | 141 + subsys/win32k/eng/mem.c | 53 + subsys/win32k/eng/mouse.c | 303 + subsys/win32k/eng/objects.h | 194 + subsys/win32k/eng/paint.c | 162 + subsys/win32k/eng/palette.c | 82 + subsys/win32k/eng/surface.c | 245 + subsys/win32k/eng/transblt.c | 94 + subsys/win32k/eng/xlate.c | 287 + subsys/win32k/freetype/.cvsignore | 3 + subsys/win32k/freetype/CHANGES | 904 + subsys/win32k/freetype/builds/.cvsignore | 3 + subsys/win32k/freetype/builds/ansi/ansi.mk | 134 + subsys/win32k/freetype/builds/detect.mk | 130 + subsys/win32k/freetype/builds/dos/detect.mk | 87 + subsys/win32k/freetype/builds/dos/dos-gcc.mk | 134 + subsys/win32k/freetype/builds/freetype.mk | 279 + subsys/win32k/freetype/builds/mac/ftlib.prj | Bin 0 -> 603 bytes subsys/win32k/freetype/builds/mac/readme | 11 + subsys/win32k/freetype/builds/modules.mk | 75 + subsys/win32k/freetype/builds/os2/detect.mk | 62 + subsys/win32k/freetype/builds/os2/os2-dev.mk | 137 + subsys/win32k/freetype/builds/os2/os2-gcc.mk | 135 + subsys/win32k/freetype/builds/unix/aclocal.m4 | 430 + subsys/win32k/freetype/builds/unix/config.guess | 1273 + subsys/win32k/freetype/builds/unix/config.sub | 1319 + subsys/win32k/freetype/builds/unix/configure | 2514 ++ subsys/win32k/freetype/builds/unix/configure.in | 74 + subsys/win32k/freetype/builds/unix/detect.mk | 59 + subsys/win32k/freetype/builds/unix/ftconfig.in | 172 + subsys/win32k/freetype/builds/unix/ftsystem.c | 306 + subsys/win32k/freetype/builds/unix/install-sh | 250 + subsys/win32k/freetype/builds/unix/ltconfig | 3078 ++ subsys/win32k/freetype/builds/unix/ltmain.sh | 4012 +++ subsys/win32k/freetype/builds/unix/mkinstalldirs | 40 + subsys/win32k/freetype/builds/unix/unix.in | 216 + subsys/win32k/freetype/builds/win32/detect.mk | 90 + subsys/win32k/freetype/builds/win32/w32-dev.mk | 140 + subsys/win32k/freetype/builds/win32/w32-gcc.mk | 138 + subsys/win32k/freetype/builds/win32/w32-icc.mk | 122 + subsys/win32k/freetype/builds/win32/w32-lcc.mk | 130 + subsys/win32k/freetype/builds/win32/w32-vcc.mk | 129 + subsys/win32k/freetype/ctype.c | 706 + subsys/win32k/freetype/docs/build | 264 + .../win32k/freetype/docs/design/build-system.html | 910 + .../win32k/freetype/docs/design/demo-programs.png | 1 + .../win32k/freetype/docs/design/drivers-list.png | 1 + subsys/win32k/freetype/docs/design/index.html | 791 + subsys/win32k/freetype/docs/design/io-frames.html | 343 + .../freetype/docs/design/library-compilation.png | 1 + subsys/win32k/freetype/docs/design/logo1.png | 1 + .../freetype/docs/design/objects_diagram.png | 1 + .../freetype/docs/design/objects_diagram2.png | 1 + .../freetype/docs/design/platform-detection.png | 1 + .../freetype/docs/design/system-interface.html | 258 + subsys/win32k/freetype/docs/docmaker.py | 516 + subsys/win32k/freetype/docs/freetype2.html | 352 + subsys/win32k/freetype/docs/ft2faq.html | 502 + subsys/win32k/freetype/docs/glnames.py | 1706 ++ subsys/win32k/freetype/docs/glyphs/Image1.png | 1 + subsys/win32k/freetype/docs/glyphs/Image2.png | 1 + subsys/win32k/freetype/docs/glyphs/Image3.png | 1 + subsys/win32k/freetype/docs/glyphs/Image4.png | 1 + subsys/win32k/freetype/docs/glyphs/bbox1.png | 1 + subsys/win32k/freetype/docs/glyphs/bbox2.png | 1 + .../freetype/docs/glyphs/body_comparison.png | 1 + .../win32k/freetype/docs/glyphs/bravo_kerned.png | 1 + .../win32k/freetype/docs/glyphs/bravo_unkerned.png | 1 + subsys/win32k/freetype/docs/glyphs/clipping.png | 1 + subsys/win32k/freetype/docs/glyphs/down_flow.png | 1 + subsys/win32k/freetype/docs/glyphs/grid_1.png | 1 + subsys/win32k/freetype/docs/glyphs/index.html | 1626 + .../win32k/freetype/docs/glyphs/points_conic.png | 1 + .../win32k/freetype/docs/glyphs/points_conic2.png | 1 + .../win32k/freetype/docs/glyphs/points_cubic.png | 1 + .../win32k/freetype/docs/glyphs/points_segment.png | 1 + subsys/win32k/freetype/docs/glyphs/twlewis1.png | 1 + subsys/win32k/freetype/docs/glyphs/twlewis2.png | 1 + subsys/win32k/freetype/docs/glyphs/up_flow.png | 1 + subsys/win32k/freetype/docs/tutorial/index.html | 871 + subsys/win32k/freetype/docs/tutorial/step1.html | 956 + subsys/win32k/freetype/docs/tutorial/step2.html | 1399 + subsys/win32k/freetype/grfont.c | 415 + subsys/win32k/freetype/grfont.h | 16 + .../freetype/include/freetype/config/ftconfig.h | 187 + .../freetype/include/freetype/config/ftmodule.h | 10 + .../freetype/include/freetype/config/ftoption.h | 395 + subsys/win32k/freetype/include/freetype/freetype.h | 2286 ++ subsys/win32k/freetype/include/freetype/ftbbox.h | 72 + subsys/win32k/freetype/include/freetype/fterrors.h | 166 + subsys/win32k/freetype/include/freetype/ftglyph.h | 422 + subsys/win32k/freetype/include/freetype/ftimage.h | 1003 + subsys/win32k/freetype/include/freetype/ftmm.h | 175 + subsys/win32k/freetype/include/freetype/ftmodule.h | 274 + subsys/win32k/freetype/include/freetype/ftnames.h | 52 + subsys/win32k/freetype/include/freetype/ftoutln.h | 344 + subsys/win32k/freetype/include/freetype/ftrender.h | 191 + subsys/win32k/freetype/include/freetype/ftsystem.h | 101 + subsys/win32k/freetype/include/freetype/fttypes.h | 400 + .../freetype/include/freetype/internal/autohint.h | 195 + .../freetype/include/freetype/internal/ftcalc.h | 123 + .../freetype/include/freetype/internal/ftdebug.h | 225 + .../freetype/include/freetype/internal/ftdriver.h | 182 + .../freetype/include/freetype/internal/ftextend.h | 178 + .../freetype/include/freetype/internal/ftlist.h | 113 + .../freetype/include/freetype/internal/ftmemory.h | 127 + .../freetype/include/freetype/internal/ftobjs.h | 532 + .../freetype/include/freetype/internal/ftstream.h | 361 + .../freetype/include/freetype/internal/psnames.h | 220 + .../freetype/include/freetype/internal/sfnt.h | 492 + .../freetype/include/freetype/internal/t1errors.h | 67 + .../freetype/include/freetype/internal/t1types.h | 188 + .../freetype/include/freetype/internal/t2errors.h | 121 + .../freetype/include/freetype/internal/t2types.h | 218 + .../freetype/include/freetype/internal/tterrors.h | 121 + .../freetype/include/freetype/internal/tttypes.h | 1582 + subsys/win32k/freetype/include/freetype/t1tables.h | 235 + subsys/win32k/freetype/include/freetype/ttnameid.h | 698 + subsys/win32k/freetype/include/freetype/tttables.h | 583 + subsys/win32k/freetype/include/freetype/tttags.h | 66 + subsys/win32k/freetype/license.txt | 164 + subsys/win32k/freetype/obj/README | 1 + subsys/win32k/freetype/src/autohint/.cvsignore | 3 + .../freetype/src/autohint/CatharonLicense.txt | 123 + subsys/win32k/freetype/src/autohint/ahangles.c | 137 + subsys/win32k/freetype/src/autohint/ahangles.h | 63 + subsys/win32k/freetype/src/autohint/ahglobal.c | 402 + subsys/win32k/freetype/src/autohint/ahglobal.h | 52 + subsys/win32k/freetype/src/autohint/ahglyph.c | 1299 + subsys/win32k/freetype/src/autohint/ahglyph.h | 93 + subsys/win32k/freetype/src/autohint/ahhint.c | 1398 + subsys/win32k/freetype/src/autohint/ahhint.h | 72 + subsys/win32k/freetype/src/autohint/ahloader.h | 124 + subsys/win32k/freetype/src/autohint/ahmodule.c | 127 + subsys/win32k/freetype/src/autohint/ahmodule.h | 32 + subsys/win32k/freetype/src/autohint/ahoptim.c | 889 + subsys/win32k/freetype/src/autohint/ahoptim.h | 136 + subsys/win32k/freetype/src/autohint/ahtypes.h | 492 + subsys/win32k/freetype/src/autohint/autohint.c | 43 + subsys/win32k/freetype/src/autohint/mather.py | 78 + subsys/win32k/freetype/src/autohint/module.mk | 7 + subsys/win32k/freetype/src/autohint/rules.mk | 77 + subsys/win32k/freetype/src/base/.cvsignore | 3 + subsys/win32k/freetype/src/base/ftbase.c | 42 + subsys/win32k/freetype/src/base/ftcalc.c | 773 + subsys/win32k/freetype/src/base/ftdebug.c | 124 + subsys/win32k/freetype/src/base/ftextend.c | 332 + subsys/win32k/freetype/src/base/ftglyph.c | 1184 + subsys/win32k/freetype/src/base/ftinit.c | 155 + subsys/win32k/freetype/src/base/ftlist.c | 301 + subsys/win32k/freetype/src/base/ftmm.c | 176 + subsys/win32k/freetype/src/base/ftnames.c | 70 + subsys/win32k/freetype/src/base/ftobjs.c | 3246 ++ subsys/win32k/freetype/src/base/ftoutln.c | 842 + subsys/win32k/freetype/src/base/ftstream.c | 818 + subsys/win32k/freetype/src/base/ftsystem.c | 307 + subsys/win32k/freetype/src/base/rules.mk | 83 + subsys/win32k/freetype/src/cff/.cvsignore | 1 + subsys/win32k/freetype/src/cff/cff.c | 40 + subsys/win32k/freetype/src/cff/module.mk | 7 + subsys/win32k/freetype/src/cff/rules.mk | 69 + subsys/win32k/freetype/src/cff/t2driver.c | 377 + subsys/win32k/freetype/src/cff/t2driver.h | 30 + subsys/win32k/freetype/src/cff/t2gload.c | 2045 ++ subsys/win32k/freetype/src/cff/t2gload.h | 213 + subsys/win32k/freetype/src/cff/t2load.c | 757 + subsys/win32k/freetype/src/cff/t2load.h | 69 + subsys/win32k/freetype/src/cff/t2objs.c | 600 + subsys/win32k/freetype/src/cff/t2objs.h | 148 + subsys/win32k/freetype/src/cff/t2parse.c | 641 + subsys/win32k/freetype/src/cff/t2parse.h | 70 + subsys/win32k/freetype/src/cff/t2tokens.h | 96 + subsys/win32k/freetype/src/cid/.cvsignore | 3 + subsys/win32k/freetype/src/cid/cidafm.c | 293 + subsys/win32k/freetype/src/cid/cidafm.h | 78 + subsys/win32k/freetype/src/cid/cidgload.c | 1558 + subsys/win32k/freetype/src/cid/cidgload.h | 198 + subsys/win32k/freetype/src/cid/cidload.c | 537 + subsys/win32k/freetype/src/cid/cidload.h | 70 + subsys/win32k/freetype/src/cid/cidobjs.c | 380 + subsys/win32k/freetype/src/cid/cidobjs.h | 141 + subsys/win32k/freetype/src/cid/cidparse.c | 1024 + subsys/win32k/freetype/src/cid/cidparse.h | 353 + subsys/win32k/freetype/src/cid/cidriver.c | 259 + subsys/win32k/freetype/src/cid/cidriver.h | 29 + subsys/win32k/freetype/src/cid/cidtokens.h | 99 + subsys/win32k/freetype/src/cid/module.mk | 6 + subsys/win32k/freetype/src/cid/rules.mk | 69 + subsys/win32k/freetype/src/cid/type1cid.c | 40 + subsys/win32k/freetype/src/macfond/.cvsignore | 3 + subsys/win32k/freetype/src/macfond/fonddrvr.c | 616 + subsys/win32k/freetype/src/otlayout/.cvsignore | 3 + subsys/win32k/freetype/src/otlayout/oltypes.c | 614 + subsys/win32k/freetype/src/otlayout/oltypes.h | 310 + subsys/win32k/freetype/src/psnames/.cvsignore | 3 + subsys/win32k/freetype/src/psnames/module.mk | 7 + subsys/win32k/freetype/src/psnames/psmodule.c | 320 + subsys/win32k/freetype/src/psnames/psmodule.h | 29 + subsys/win32k/freetype/src/psnames/psnames.c | 24 + subsys/win32k/freetype/src/psnames/pstables.h | 2942 ++ subsys/win32k/freetype/src/psnames/rules.mk | 70 + subsys/win32k/freetype/src/raster1/.cvsignore | 3 + subsys/win32k/freetype/src/raster1/ftraster.c | 3300 ++ subsys/win32k/freetype/src/raster1/ftraster.h | 50 + subsys/win32k/freetype/src/raster1/ftrend1.c | 275 + subsys/win32k/freetype/src/raster1/ftrend1.h | 37 + subsys/win32k/freetype/src/raster1/module.mk | 7 + subsys/win32k/freetype/src/raster1/raster1.c | 35 + subsys/win32k/freetype/src/raster1/rules.mk | 69 + subsys/win32k/freetype/src/sfnt/.cvsignore | 3 + subsys/win32k/freetype/src/sfnt/module.mk | 7 + subsys/win32k/freetype/src/sfnt/rules.mk | 73 + subsys/win32k/freetype/src/sfnt/sfdriver.c | 225 + subsys/win32k/freetype/src/sfnt/sfdriver.h | 29 + subsys/win32k/freetype/src/sfnt/sfnt.c | 57 + subsys/win32k/freetype/src/sfnt/sfobjs.c | 561 + subsys/win32k/freetype/src/sfnt/sfobjs.h | 57 + subsys/win32k/freetype/src/sfnt/ttcmap.c | 550 + subsys/win32k/freetype/src/sfnt/ttcmap.h | 45 + subsys/win32k/freetype/src/sfnt/ttload.c | 1676 ++ subsys/win32k/freetype/src/sfnt/ttload.h | 132 + subsys/win32k/freetype/src/sfnt/ttpost.c | 536 + subsys/win32k/freetype/src/sfnt/ttpost.h | 52 + subsys/win32k/freetype/src/sfnt/ttsbit.c | 1444 + subsys/win32k/freetype/src/sfnt/ttsbit.h | 65 + subsys/win32k/freetype/src/smooth/.cvsignore | 3 + subsys/win32k/freetype/src/smooth/ftgrays.c | 1969 ++ subsys/win32k/freetype/src/smooth/ftgrays.h | 52 + subsys/win32k/freetype/src/smooth/ftsmooth.c | 220 + subsys/win32k/freetype/src/smooth/ftsmooth.h | 35 + subsys/win32k/freetype/src/smooth/module.mk | 7 + subsys/win32k/freetype/src/smooth/rules.mk | 69 + subsys/win32k/freetype/src/smooth/smooth.c | 35 + subsys/win32k/freetype/src/truetype/.cvsignore | 3 + subsys/win32k/freetype/src/truetype/module.mk | 7 + subsys/win32k/freetype/src/truetype/rules.mk | 70 + subsys/win32k/freetype/src/truetype/truetype.c | 47 + subsys/win32k/freetype/src/truetype/ttdriver.c | 511 + subsys/win32k/freetype/src/truetype/ttdriver.h | 31 + subsys/win32k/freetype/src/truetype/ttgload.c | 1477 + subsys/win32k/freetype/src/truetype/ttgload.h | 69 + subsys/win32k/freetype/src/truetype/ttinterp.c | 7544 +++++ subsys/win32k/freetype/src/truetype/ttinterp.h | 278 + subsys/win32k/freetype/src/truetype/ttobjs.c | 734 + subsys/win32k/freetype/src/truetype/ttobjs.h | 412 + subsys/win32k/freetype/src/truetype/ttpload.c | 273 + subsys/win32k/freetype/src/truetype/ttpload.h | 51 + subsys/win32k/freetype/src/type1/.cvsignore | 3 + subsys/win32k/freetype/src/type1/module.mk0 | 6 + subsys/win32k/freetype/src/type1/rules.mk0 | 74 + subsys/win32k/freetype/src/type1/t1afm.c | 293 + subsys/win32k/freetype/src/type1/t1afm.h | 70 + subsys/win32k/freetype/src/type1/t1driver.c | 381 + subsys/win32k/freetype/src/type1/t1driver.h | 30 + subsys/win32k/freetype/src/type1/t1gload.c | 1823 ++ subsys/win32k/freetype/src/type1/t1gload.h | 326 + subsys/win32k/freetype/src/type1/t1hinter.c | 1347 + subsys/win32k/freetype/src/type1/t1hinter.h | 273 + subsys/win32k/freetype/src/type1/t1load.c | 1594 + subsys/win32k/freetype/src/type1/t1load.h | 57 + subsys/win32k/freetype/src/type1/t1objs.c | 544 + subsys/win32k/freetype/src/type1/t1objs.h | 172 + subsys/win32k/freetype/src/type1/t1parse.c | 761 + subsys/win32k/freetype/src/type1/t1parse.h | 261 + subsys/win32k/freetype/src/type1/t1tokens.c | 1101 + subsys/win32k/freetype/src/type1/t1tokens.h | 258 + subsys/win32k/freetype/src/type1/type1.c | 59 + subsys/win32k/freetype/src/type1z/.cvsignore | 3 + subsys/win32k/freetype/src/type1z/Readme.txt | 10 + subsys/win32k/freetype/src/type1z/module.mk | 7 + subsys/win32k/freetype/src/type1z/rules.mk | 72 + subsys/win32k/freetype/src/type1z/type1z.c | 49 + subsys/win32k/freetype/src/type1z/z1afm.c | 293 + subsys/win32k/freetype/src/type1z/z1afm.h | 79 + subsys/win32k/freetype/src/type1z/z1driver.c | 340 + subsys/win32k/freetype/src/type1z/z1driver.h | 29 + subsys/win32k/freetype/src/type1z/z1gload.c | 1482 + subsys/win32k/freetype/src/type1z/z1gload.h | 187 + subsys/win32k/freetype/src/type1z/z1load.c | 1725 ++ subsys/win32k/freetype/src/type1z/z1load.h | 93 + subsys/win32k/freetype/src/type1z/z1objs.c | 398 + subsys/win32k/freetype/src/type1z/z1objs.h | 161 + subsys/win32k/freetype/src/type1z/z1parse.c | 1398 + subsys/win32k/freetype/src/type1z/z1parse.h | 363 + subsys/win32k/freetype/src/type1z/z1tokens.h | 132 + subsys/win32k/freetype/src/winfonts/.cvsignore | 3 + subsys/win32k/freetype/src/winfonts/module.mk | 6 + subsys/win32k/freetype/src/winfonts/rules.mk | 64 + subsys/win32k/freetype/src/winfonts/winfnt.c | 623 + subsys/win32k/freetype/src/winfonts/winfnt.h | 150 + subsys/win32k/include/callback.h | 32 + subsys/win32k/include/class.h | 45 + subsys/win32k/include/copybits.h | 9 + subsys/win32k/include/dce.h | 48 + subsys/win32k/include/dib.h | 6 + subsys/win32k/include/eng.h | 6 + subsys/win32k/include/error.h | 14 + subsys/win32k/include/guicheck.h | 14 + subsys/win32k/include/input.h | 7 + subsys/win32k/include/mouse.h | 8 + subsys/win32k/include/msgqueue.h | 128 + subsys/win32k/include/object.h | 117 + subsys/win32k/include/paint.h | 6 + subsys/win32k/include/painting.h | 22 + subsys/win32k/include/palette.h | 25 + subsys/win32k/include/rect.h | 12 + subsys/win32k/include/surface.h | 6 + subsys/win32k/include/window.h | 116 + subsys/win32k/include/winpos.h | 19 + subsys/win32k/include/winsta.h | 44 + subsys/win32k/ldr/.cvsignore | 3 + subsys/win32k/ldr/loader.c | 39 + subsys/win32k/main/.cvsignore | 4 + subsys/win32k/main/dllmain.c | 117 + subsys/win32k/main/svctabm.c | 17 + subsys/win32k/makefile | 91 + subsys/win32k/misc/.cvsignore | 3 + subsys/win32k/misc/driver.c | 273 + subsys/win32k/misc/error.c | 31 + subsys/win32k/misc/math.c | 285 + subsys/win32k/misc/object.c | 518 + subsys/win32k/ntuser/.cvsignore | 3 + subsys/win32k/ntuser/callback.c | 246 + subsys/win32k/ntuser/class.c | 343 + subsys/win32k/ntuser/guicheck.c | 94 + subsys/win32k/ntuser/hook.c | 93 + subsys/win32k/ntuser/input.c | 240 + subsys/win32k/ntuser/keyboard.c | 222 + subsys/win32k/ntuser/message.c | 468 + subsys/win32k/ntuser/metric.c | 69 + subsys/win32k/ntuser/msgqueue.c | 602 + subsys/win32k/ntuser/painting.c | 832 + subsys/win32k/ntuser/prop.c | 136 + subsys/win32k/ntuser/stubs.c | 1938 ++ subsys/win32k/ntuser/userobj.c | 125 + subsys/win32k/ntuser/windc.c | 531 + subsys/win32k/ntuser/window.c | 1045 + subsys/win32k/ntuser/winpos.c | 828 + subsys/win32k/ntuser/winsta.c | 872 + subsys/win32k/objects/.cvsignore | 3 + subsys/win32k/objects/bezier.c | 184 + subsys/win32k/objects/bitmaps.c | 511 + subsys/win32k/objects/brush.c | 246 + subsys/win32k/objects/cliprgn.c | 159 + subsys/win32k/objects/color.c | 505 + subsys/win32k/objects/coord.c | 358 + subsys/win32k/objects/dc.c | 1304 + subsys/win32k/objects/dib.c | 774 + subsys/win32k/objects/fillshap.c | 181 + subsys/win32k/objects/font.c | 2 + subsys/win32k/objects/gdiobj.c | 524 + subsys/win32k/objects/icm.c | 143 + subsys/win32k/objects/line.c | 315 + subsys/win32k/objects/metafile.c | 236 + subsys/win32k/objects/objconv.c | 61 + subsys/win32k/objects/paint.c | 52 + subsys/win32k/objects/palette.c | 386 + subsys/win32k/objects/path.c | 1028 + subsys/win32k/objects/pen.c | 54 + subsys/win32k/objects/print.c | 75 + subsys/win32k/objects/rect.c | 93 + subsys/win32k/objects/region.c | 1990 ++ subsys/win32k/objects/text.c | 760 + subsys/win32k/objects/wingl.c | 61 + subsys/win32k/stubs/.cvsignore | 3 + subsys/win32k/stubs/stubs.c | 134 + subsys/win32k/win32k.def | 183 + subsys/win32k/win32k.edf | 187 + subsys/win32k/win32k.rc | 39 + system.hiv | 305 + tools/.cvsignore | 9 + tools/Makefile | 79 + tools/buildno.c | 329 + tools/config.mk | 36 + tools/create_nls/Makefile | 54 + tools/create_nls/Readme | 23 + tools/create_nls/create_nls.c | 965 + tools/create_nls/unicode.org/.cvsignore | 1 + tools/depend.mk | 35 + tools/depends.c | 56 + tools/helper.mk | 629 + tools/mkconfig.c | 112 + tools/rcopy.c | 87 + tools/rdel.c | 91 + tools/rmkdir.c | 102 + tools/rrmdir.c | 92 + tools/rsym.c | 255 + tools/wmc/.cvsignore | 6 + tools/wmc/config.h | 454 + tools/wmc/getopt.c | 1050 + tools/wmc/getopt.h | 131 + tools/wmc/lang.c | 155 + tools/wmc/lang.h | 26 + tools/wmc/language.c | 107 + tools/wmc/makefile | 58 + tools/wmc/makefile.in | 49 + tools/wmc/mcl.c | 736 + tools/wmc/mcy.y | 662 + tools/wmc/misc.c | 77 + tools/wmc/utils.c | 242 + tools/wmc/utils.h | 44 + tools/wmc/windows.h | 35 + tools/wmc/wmc.c | 269 + tools/wmc/wmc.h | 76 + tools/wmc/wmc.man | 103 + tools/wmc/wmctypes.h | 106 + tools/wmc/write.c | 631 + tools/wmc/write.h | 14 + tools/wmc/y_tab.c | 1774 ++ tools/wmc/y_tab.h | 30 + 3949 files changed, 856205 insertions(+) create mode 100644 .cvsignore create mode 100644 .gdbinit create mode 100644 COPYING create mode 100644 CREDITS create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 LGPL.txt create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README create mode 100644 aboot.bat create mode 100644 apps/tests/alive/Makefile create mode 100644 apps/tests/alive/alive.c create mode 100644 apps/tests/apc/apc.c create mode 100644 apps/tests/apc/makefile create mode 100644 apps/tests/args/args.c create mode 100644 apps/tests/args/makefile create mode 100644 apps/tests/atomtest/atomtest.c create mode 100644 apps/tests/atomtest/makefile create mode 100644 apps/tests/bench/bench-syscall.c create mode 100644 apps/tests/bench/bench-thread.c create mode 100644 apps/tests/bench/makefile create mode 100644 apps/tests/bitblt/bitblt.cpp create mode 100644 apps/tests/bitblt/lena.bmp create mode 100644 apps/tests/bitblt/makefile create mode 100644 apps/tests/consume/Makefile create mode 100644 apps/tests/consume/consume.c create mode 100644 apps/tests/count/Makefile create mode 100644 apps/tests/count/count.c create mode 100644 apps/tests/dibtest/dibtest.c create mode 100644 apps/tests/dibtest/makefile create mode 100644 apps/tests/dump_shared_data/dump_shared_data.c create mode 100644 apps/tests/dump_shared_data/makefile create mode 100644 apps/tests/event/event.c create mode 100644 apps/tests/event/makefile create mode 100644 apps/tests/file/Makefile create mode 100644 apps/tests/file/file.c create mode 100644 apps/tests/gditest/gditest.c create mode 100644 apps/tests/gditest/makefile create mode 100644 apps/tests/hello/hello.c create mode 100644 apps/tests/hello/makefile create mode 100644 apps/tests/isotest/isotest.c create mode 100644 apps/tests/isotest/makefile create mode 100644 apps/tests/lpc/conport.c create mode 100644 apps/tests/lpc/creport.c create mode 100644 apps/tests/lpc/dumpinfo.c create mode 100644 apps/tests/lpc/dumpinfo.h create mode 100644 apps/tests/lpc/lpcclt.c create mode 100644 apps/tests/lpc/lpcsrv.c create mode 100644 apps/tests/lpc/lpctest.h create mode 100644 apps/tests/lpc/makefile create mode 100644 apps/tests/mktime/makefile create mode 100644 apps/tests/mktime/mktime.c create mode 100644 apps/tests/mstest/Makefile create mode 100644 apps/tests/mstest/msclient.c create mode 100644 apps/tests/mstest/msserver.c create mode 100644 apps/tests/mutex/makefile create mode 100644 apps/tests/mutex/mutex.c create mode 100644 apps/tests/nptest/Makefile create mode 100644 apps/tests/nptest/npclient.c create mode 100644 apps/tests/nptest/npserver.c create mode 100644 apps/tests/patblt/Penguin.bmp create mode 100644 apps/tests/patblt/makefile create mode 100644 apps/tests/patblt/patblt.cpp create mode 100644 apps/tests/pteb/Makefile create mode 100644 apps/tests/pteb/pteb.c create mode 100644 apps/tests/regdump/makefile create mode 100644 apps/tests/regdump/regdump.c create mode 100644 apps/tests/regtest/makefile create mode 100644 apps/tests/regtest/regtest.c create mode 100644 apps/tests/sectest/Makefile create mode 100644 apps/tests/sectest/sectest.c create mode 100644 apps/tests/sertest/makefile create mode 100644 apps/tests/sertest/sertest.c create mode 100644 apps/tests/shm/makefile create mode 100644 apps/tests/shm/shmclt.c create mode 100644 apps/tests/shm/shmsrv.c create mode 100644 apps/tests/simple/makefile create mode 100644 apps/tests/simple/simple.c create mode 100644 apps/tests/stretchblt/lena.bmp create mode 100644 apps/tests/stretchblt/makefile create mode 100644 apps/tests/stretchblt/stretchblt.cpp create mode 100644 apps/tests/tcpsvr/makefile create mode 100644 apps/tests/tcpsvr/tcpsvr.c create mode 100644 apps/tests/test_old/bug2.c create mode 100644 apps/tests/test_old/bug3.c create mode 100644 apps/tests/test_old/makefile create mode 100644 apps/tests/test_old/temptest.c create mode 100644 apps/tests/test_old/test-fseek.c create mode 100644 apps/tests/test_old/test-fwrite.c create mode 100644 apps/tests/test_old/test-stdio.c create mode 100644 apps/tests/test_old/test_rdwr.c create mode 100644 apps/tests/test_old/testfsd.c create mode 100644 apps/tests/test_old/testsuite.c create mode 100644 apps/tests/test_old/testsuite.h create mode 100644 apps/tests/test_old/time_t.c create mode 100644 apps/tests/test_old/tst-printf.c create mode 100644 apps/tests/test_old/tstdiomisc.c create mode 100644 apps/tests/tests/GetSysMetrics/GetSysMetrics.c create mode 100644 apps/tests/tests/GetSysMetrics/Makefile create mode 100644 apps/tests/tests/GetSystemInfo/GetSystemInfo.c create mode 100644 apps/tests/tests/GetSystemInfo/Makefile create mode 100644 apps/tests/tests/Mutex/Makefile create mode 100644 apps/tests/tests/Mutex/fivemutex.c create mode 100644 apps/tests/tests/Mutex/rapidmutex.c create mode 100644 apps/tests/tests/Parent_Child/Makefile create mode 100644 apps/tests/tests/Parent_Child/Parent_Child.c create mode 100644 apps/tests/tests/guitest/Makefile create mode 100644 apps/tests/tests/guitest/guitest.c create mode 100644 apps/tests/tests/guitest/guitest.rc create mode 100644 apps/tests/tests/hello/Makefile create mode 100644 apps/tests/tests/hello/hello.c create mode 100644 apps/tests/tests/hello2/Makefile create mode 100644 apps/tests/tests/hello2/hello2.c create mode 100644 apps/tests/tests/make_install.bat create mode 100644 apps/tests/tests/new/Makefile create mode 100644 apps/tests/tests/new/new.c create mode 100644 apps/tests/tests/readme.txt create mode 100644 apps/tests/tests/rolex/Makefile create mode 100644 apps/tests/tests/rolex/rolex.c create mode 100644 apps/tests/tests/rolex/rolex.spec create mode 100644 apps/tests/tests/volinfo/Makefile create mode 100644 apps/tests/tests/volinfo/volinfo.c create mode 100644 apps/tests/thread/makefile create mode 100644 apps/tests/thread/thread.c create mode 100644 apps/tests/tokentest/makefile create mode 100644 apps/tests/tokentest/tokentest.c create mode 100644 apps/tests/vmtest/Makefile create mode 100644 apps/tests/vmtest/vmtest.c create mode 100644 apps/tests/winhello/makefile create mode 100644 apps/tests/winhello/winhello.c create mode 100644 apps/utils/cabman/cabinet.cpp create mode 100644 apps/utils/cabman/cabinet.h create mode 100644 apps/utils/cabman/cabman.h create mode 100644 apps/utils/cabman/dff.txt create mode 100644 apps/utils/cabman/dfp.cpp create mode 100644 apps/utils/cabman/dfp.h create mode 100644 apps/utils/cabman/main.cpp create mode 100644 apps/utils/cabman/makefile create mode 100644 apps/utils/cabman/mszip.cpp create mode 100644 apps/utils/cabman/mszip.h create mode 100644 apps/utils/cabman/raw.cpp create mode 100644 apps/utils/cabman/raw.h create mode 100644 apps/utils/cabman/test.cpp create mode 100644 apps/utils/cabman/test.h create mode 100644 apps/utils/cat/cat.c create mode 100644 apps/utils/cat/makefile create mode 100644 apps/utils/net/ping/.cvsignore create mode 100644 apps/utils/net/roshttpd/common/.cvsignore create mode 100644 apps/utils/net/roshttpd/common/list.cpp create mode 100644 apps/utils/net/roshttpd/common/roshttpd.rc create mode 100644 apps/utils/net/roshttpd/common/socket.cpp create mode 100644 apps/utils/net/roshttpd/common/thread.cpp create mode 100644 apps/utils/net/roshttpd/config.cpp create mode 100644 apps/utils/net/roshttpd/error.cpp create mode 100644 apps/utils/net/roshttpd/http.cpp create mode 100644 apps/utils/net/roshttpd/httpd.cpp create mode 100644 apps/utils/net/roshttpd/include/config.h create mode 100644 apps/utils/net/roshttpd/include/debug.h create mode 100644 apps/utils/net/roshttpd/include/error.h create mode 100644 apps/utils/net/roshttpd/include/http.h create mode 100644 apps/utils/net/roshttpd/include/httpd.h create mode 100644 apps/utils/net/roshttpd/include/iterator.h create mode 100644 apps/utils/net/roshttpd/include/list.h create mode 100644 apps/utils/net/roshttpd/include/socket.h create mode 100644 apps/utils/net/roshttpd/include/thread.h create mode 100644 apps/utils/net/roshttpd/makefile create mode 100644 apps/utils/net/roshttpd/roshttpd.cpp create mode 100644 apps/utils/net/telnet/Makefile create mode 100644 apps/utils/net/telnet/ansi.cpp create mode 100644 apps/utils/net/telnet/console.cpp create mode 100644 apps/utils/net/telnet/console.h create mode 100644 apps/utils/net/telnet/helpsock.cpp create mode 100644 apps/utils/net/telnet/main.cpp create mode 100644 apps/utils/net/telnet/nvt.cpp create mode 100644 apps/utils/net/telnet/telnet.cpp create mode 100644 apps/utils/net/telnet/telnet.h create mode 100644 apps/utils/net/telnet/telnet.rc create mode 100644 apps/utils/net/telnet/vm.cpp create mode 100644 apps/utils/objdir/makefile create mode 100644 apps/utils/objdir/objdir.c create mode 100644 apps/utils/partinfo/makefile create mode 100644 apps/utils/partinfo/partinfo.c create mode 100644 apps/utils/pice/loader/main.c create mode 100644 apps/utils/pice/loader/makefile create mode 100644 apps/utils/pice/loader/retypes.h create mode 100644 apps/utils/pice/loader/stab.def create mode 100644 apps/utils/pice/loader/stab_gnu.h create mode 100644 apps/utils/pice/loader/stdinc.h create mode 100644 apps/utils/pice/loader/terminal.c create mode 100644 apps/utils/pice/loader/terminal.h create mode 100644 apps/utils/pice/makefile create mode 100644 apps/utils/pice/module/animation.h create mode 100644 apps/utils/pice/module/bp.c create mode 100644 apps/utils/pice/module/bp.h create mode 100644 apps/utils/pice/module/charset.h create mode 100644 apps/utils/pice/module/dblflt.c create mode 100644 apps/utils/pice/module/dblflt.h create mode 100644 apps/utils/pice/module/debug.c create mode 100644 apps/utils/pice/module/debug.h create mode 100644 apps/utils/pice/module/disassembler.c create mode 100644 apps/utils/pice/module/disassembler.h create mode 100644 apps/utils/pice/module/disassemblerdata.h create mode 100644 apps/utils/pice/module/disassemblerdefines.h create mode 100644 apps/utils/pice/module/gpfault.c create mode 100644 apps/utils/pice/module/gpfault.h create mode 100644 apps/utils/pice/module/hardware.c create mode 100644 apps/utils/pice/module/hardware.h create mode 100644 apps/utils/pice/module/hercules.c create mode 100644 apps/utils/pice/module/hercules.h create mode 100644 apps/utils/pice/module/hooks.c create mode 100644 apps/utils/pice/module/hooks.h create mode 100644 apps/utils/pice/module/init.c create mode 100644 apps/utils/pice/module/init.h create mode 100644 apps/utils/pice/module/ldrsym.h create mode 100644 apps/utils/pice/module/logo.h create mode 100644 apps/utils/pice/module/makefile create mode 100644 apps/utils/pice/module/output.c create mode 100644 apps/utils/pice/module/output.h create mode 100644 apps/utils/pice/module/parse.c create mode 100644 apps/utils/pice/module/parse.h create mode 100644 apps/utils/pice/module/patch.c create mode 100644 apps/utils/pice/module/patch.h create mode 100644 apps/utils/pice/module/pci_ids.h create mode 100644 apps/utils/pice/module/pgflt.c create mode 100644 apps/utils/pice/module/pgflt.h create mode 100644 apps/utils/pice/module/pice.rc create mode 100644 apps/utils/pice/module/pice_ver.h create mode 100644 apps/utils/pice/module/precomp.h create mode 100644 apps/utils/pice/module/privateice.c create mode 100644 apps/utils/pice/module/regs.h create mode 100644 apps/utils/pice/module/remods.h create mode 100644 apps/utils/pice/module/retypes.h create mode 100644 apps/utils/pice/module/scancodes.h create mode 100644 apps/utils/pice/module/serial.c create mode 100644 apps/utils/pice/module/serial.h create mode 100644 apps/utils/pice/module/serial_port.h create mode 100644 apps/utils/pice/module/shell.c create mode 100644 apps/utils/pice/module/shell.h create mode 100644 apps/utils/pice/module/stab.def create mode 100644 apps/utils/pice/module/stab_gnu.h create mode 100644 apps/utils/pice/module/symbols.c create mode 100644 apps/utils/pice/module/symbols.h create mode 100644 apps/utils/pice/module/syscall.c create mode 100644 apps/utils/pice/module/syscall.h create mode 100644 apps/utils/pice/module/trace.c create mode 100644 apps/utils/pice/module/trace.h create mode 100644 apps/utils/pice/module/utils.c create mode 100644 apps/utils/pice/module/utils.h create mode 100644 apps/utils/pice/module/vga.c create mode 100644 apps/utils/pice/module/vga.h create mode 100644 apps/utils/pice/module/vga_utils.asm create mode 100644 apps/utils/pice/pice.cfg create mode 100644 apps/utils/pice/readme.txt create mode 100644 apps/utils/pice/shared/shared.h create mode 100644 apps/utils/ps/makefile create mode 100644 apps/utils/ps/ps.cpp create mode 100644 apps/utils/stats/Makefile create mode 100644 apps/utils/stats/stats.c create mode 100644 baseaddress.cfg create mode 100644 boot.bat create mode 100644 boot.hiv create mode 100644 bootc.lst create mode 100755 bootcd.bat create mode 100644 bootflop.bat create mode 100644 config create mode 100644 dk/nkm/.cvsignore create mode 100644 dk/nkm/Makefile create mode 100644 dk/psx/.cvsignore create mode 100644 dk/psx/Makefile create mode 100644 dk/readme.txt create mode 100644 dk/w32/.cvsignore create mode 100644 dk/w32/Makefile create mode 100644 doc/DIRS create mode 100644 doc/HACKING create mode 100644 doc/INDEX create mode 100644 doc/INTERNALS create mode 100644 doc/apc create mode 100644 doc/news1 create mode 100644 doc/news2 create mode 100644 doc/notes create mode 100644 doc/roadmap create mode 100644 doc/todo create mode 100644 drivers/bus/acpi/.cvsignore create mode 100644 drivers/bus/acpi/acpi.rc create mode 100644 drivers/bus/acpi/changed.txt create mode 100644 drivers/bus/acpi/dispatcher/.cvsignore create mode 100644 drivers/bus/acpi/dispatcher/dsfield.c create mode 100644 drivers/bus/acpi/dispatcher/dsmethod.c create mode 100644 drivers/bus/acpi/dispatcher/dsmthdat.c create mode 100644 drivers/bus/acpi/dispatcher/dsobject.c create mode 100644 drivers/bus/acpi/dispatcher/dsopcode.c create mode 100644 drivers/bus/acpi/dispatcher/dsutils.c create mode 100644 drivers/bus/acpi/dispatcher/dswexec.c create mode 100644 drivers/bus/acpi/dispatcher/dswload.c create mode 100644 drivers/bus/acpi/dispatcher/dswscope.c create mode 100644 drivers/bus/acpi/dispatcher/dswstate.c create mode 100644 drivers/bus/acpi/events/.cvsignore create mode 100644 drivers/bus/acpi/events/evevent.c create mode 100644 drivers/bus/acpi/events/evmisc.c create mode 100644 drivers/bus/acpi/events/evregion.c create mode 100644 drivers/bus/acpi/events/evrgnini.c create mode 100644 drivers/bus/acpi/events/evsci.c create mode 100644 drivers/bus/acpi/events/evxface.c create mode 100644 drivers/bus/acpi/events/evxfevnt.c create mode 100644 drivers/bus/acpi/events/evxfregn.c create mode 100644 drivers/bus/acpi/executer/.cvsignore create mode 100644 drivers/bus/acpi/executer/amconfig.c create mode 100644 drivers/bus/acpi/executer/amconvrt.c create mode 100644 drivers/bus/acpi/executer/amcreate.c create mode 100644 drivers/bus/acpi/executer/amdump.c create mode 100644 drivers/bus/acpi/executer/amdyadic.c create mode 100644 drivers/bus/acpi/executer/amfield.c create mode 100644 drivers/bus/acpi/executer/amfldio.c create mode 100644 drivers/bus/acpi/executer/ammisc.c create mode 100644 drivers/bus/acpi/executer/ammonad.c create mode 100644 drivers/bus/acpi/executer/ammutex.c create mode 100644 drivers/bus/acpi/executer/amnames.c create mode 100644 drivers/bus/acpi/executer/amprep.c create mode 100644 drivers/bus/acpi/executer/amregion.c create mode 100644 drivers/bus/acpi/executer/amresnte.c create mode 100644 drivers/bus/acpi/executer/amresolv.c create mode 100644 drivers/bus/acpi/executer/amresop.c create mode 100644 drivers/bus/acpi/executer/amstore.c create mode 100644 drivers/bus/acpi/executer/amstoren.c create mode 100644 drivers/bus/acpi/executer/amstorob.c create mode 100644 drivers/bus/acpi/executer/amsystem.c create mode 100644 drivers/bus/acpi/executer/amutils.c create mode 100644 drivers/bus/acpi/executer/amxface.c create mode 100644 drivers/bus/acpi/hardware/.cvsignore create mode 100644 drivers/bus/acpi/hardware/hwacpi.c create mode 100644 drivers/bus/acpi/hardware/hwgpe.c create mode 100644 drivers/bus/acpi/hardware/hwregs.c create mode 100644 drivers/bus/acpi/hardware/hwsleep.c create mode 100644 drivers/bus/acpi/hardware/hwtimer.c create mode 100644 drivers/bus/acpi/include/accommon.h create mode 100644 drivers/bus/acpi/include/acconfig.h create mode 100644 drivers/bus/acpi/include/acdebug.h create mode 100644 drivers/bus/acpi/include/acdispat.h create mode 100644 drivers/bus/acpi/include/acevents.h create mode 100644 drivers/bus/acpi/include/acexcep.h create mode 100644 drivers/bus/acpi/include/acglobal.h create mode 100644 drivers/bus/acpi/include/achware.h create mode 100644 drivers/bus/acpi/include/acinterp.h create mode 100644 drivers/bus/acpi/include/aclocal.h create mode 100644 drivers/bus/acpi/include/acmacros.h create mode 100644 drivers/bus/acpi/include/acnamesp.h create mode 100644 drivers/bus/acpi/include/acobject.h create mode 100644 drivers/bus/acpi/include/acoutput.h create mode 100644 drivers/bus/acpi/include/acparser.h create mode 100644 drivers/bus/acpi/include/acpi.h create mode 100644 drivers/bus/acpi/include/acpiosxf.h create mode 100644 drivers/bus/acpi/include/acpixf.h create mode 100644 drivers/bus/acpi/include/acresrc.h create mode 100644 drivers/bus/acpi/include/acstruct.h create mode 100644 drivers/bus/acpi/include/actables.h create mode 100644 drivers/bus/acpi/include/actbl.h create mode 100644 drivers/bus/acpi/include/actbl1.h create mode 100644 drivers/bus/acpi/include/actbl2.h create mode 100644 drivers/bus/acpi/include/actbl71.h create mode 100644 drivers/bus/acpi/include/actypes.h create mode 100644 drivers/bus/acpi/include/amlcode.h create mode 100644 drivers/bus/acpi/include/platform/acenv.h create mode 100644 drivers/bus/acpi/include/platform/acgcc.h create mode 100644 drivers/bus/acpi/include/platform/aclinux.h create mode 100644 drivers/bus/acpi/include/platform/acwin.h create mode 100644 drivers/bus/acpi/include/platform/types.h create mode 100644 drivers/bus/acpi/makefile create mode 100644 drivers/bus/acpi/namespace/.cvsignore create mode 100644 drivers/bus/acpi/namespace/nsaccess.c create mode 100644 drivers/bus/acpi/namespace/nsalloc.c create mode 100644 drivers/bus/acpi/namespace/nseval.c create mode 100644 drivers/bus/acpi/namespace/nsinit.c create mode 100644 drivers/bus/acpi/namespace/nsload.c create mode 100644 drivers/bus/acpi/namespace/nsnames.c create mode 100644 drivers/bus/acpi/namespace/nsobject.c create mode 100644 drivers/bus/acpi/namespace/nssearch.c create mode 100644 drivers/bus/acpi/namespace/nsutils.c create mode 100644 drivers/bus/acpi/namespace/nswalk.c create mode 100644 drivers/bus/acpi/namespace/nsxfname.c create mode 100644 drivers/bus/acpi/namespace/nsxfobj.c create mode 100644 drivers/bus/acpi/ospm/.cvsignore create mode 100644 drivers/bus/acpi/ospm/acpienum.c create mode 100644 drivers/bus/acpi/ospm/acpisys.c create mode 100644 drivers/bus/acpi/ospm/bn.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bm.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmnotify.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmpm.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmpower.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmrequest.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmsearch.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmutils.c create mode 100644 drivers/bus/acpi/ospm/busmgr/bmxface.c create mode 100644 drivers/bus/acpi/ospm/fdo.c create mode 100644 drivers/bus/acpi/ospm/include/acpisys.h create mode 100644 drivers/bus/acpi/ospm/include/bm.h create mode 100644 drivers/bus/acpi/ospm/include/bmpower.h create mode 100644 drivers/bus/acpi/ospm/include/bn.h create mode 100644 drivers/bus/acpi/ospm/osl.c create mode 100644 drivers/bus/acpi/ospm/pdo.c create mode 100644 drivers/bus/acpi/parser/.cvsignore create mode 100644 drivers/bus/acpi/parser/psargs.c create mode 100644 drivers/bus/acpi/parser/psopcode.c create mode 100644 drivers/bus/acpi/parser/psparse.c create mode 100644 drivers/bus/acpi/parser/psscope.c create mode 100644 drivers/bus/acpi/parser/pstree.c create mode 100644 drivers/bus/acpi/parser/psutils.c create mode 100644 drivers/bus/acpi/parser/pswalk.c create mode 100644 drivers/bus/acpi/parser/psxface.c create mode 100644 drivers/bus/acpi/resource/rsaddr.c create mode 100644 drivers/bus/acpi/resource/rscalc.c create mode 100644 drivers/bus/acpi/resource/rscreate.c create mode 100644 drivers/bus/acpi/resource/rsdump.c create mode 100644 drivers/bus/acpi/resource/rsio.c create mode 100644 drivers/bus/acpi/resource/rsirq.c create mode 100644 drivers/bus/acpi/resource/rslist.c create mode 100644 drivers/bus/acpi/resource/rsmemory.c create mode 100644 drivers/bus/acpi/resource/rsmisc.c create mode 100644 drivers/bus/acpi/resource/rsutils.c create mode 100644 drivers/bus/acpi/resource/rsxface.c create mode 100644 drivers/bus/acpi/tables/.cvsignore create mode 100644 drivers/bus/acpi/tables/tbconvrt.c create mode 100644 drivers/bus/acpi/tables/tbget.c create mode 100644 drivers/bus/acpi/tables/tbinstal.c create mode 100644 drivers/bus/acpi/tables/tbutils.c create mode 100644 drivers/bus/acpi/tables/tbxface.c create mode 100644 drivers/bus/acpi/tables/tbxfroot.c create mode 100644 drivers/bus/acpi/utils/.cvsignore create mode 100644 drivers/bus/acpi/utils/cmalloc.c create mode 100644 drivers/bus/acpi/utils/cmclib.c create mode 100644 drivers/bus/acpi/utils/cmcopy.c create mode 100644 drivers/bus/acpi/utils/cmdebug.c create mode 100644 drivers/bus/acpi/utils/cmdelete.c create mode 100644 drivers/bus/acpi/utils/cmeval.c create mode 100644 drivers/bus/acpi/utils/cmglobal.c create mode 100644 drivers/bus/acpi/utils/cminit.c create mode 100644 drivers/bus/acpi/utils/cmobject.c create mode 100644 drivers/bus/acpi/utils/cmutils.c create mode 100644 drivers/bus/acpi/utils/cmxface.c create mode 100644 drivers/bus/isapnp/.cvsignore create mode 100644 drivers/bus/isapnp/isapnp.c create mode 100644 drivers/bus/isapnp/isapnp.h create mode 100644 drivers/bus/isapnp/isapnp.rc create mode 100644 drivers/bus/isapnp/makefile create mode 100644 drivers/bus/pci/.cvsignore create mode 100644 drivers/bus/pci/fdo.c create mode 100644 drivers/bus/pci/makefile create mode 100644 drivers/bus/pci/pci.c create mode 100644 drivers/bus/pci/pci.h create mode 100644 drivers/bus/pci/pci.rc create mode 100644 drivers/bus/pci/pcidef.h create mode 100644 drivers/bus/pci/pdo.c create mode 100644 drivers/dd/beep/.cvsignore create mode 100644 drivers/dd/beep/beep.c create mode 100644 drivers/dd/beep/beep.rc create mode 100644 drivers/dd/beep/makefile create mode 100644 drivers/dd/blue/.cvsignore create mode 100644 drivers/dd/blue/blue.c create mode 100644 drivers/dd/blue/blue.rc create mode 100644 drivers/dd/blue/makefile create mode 100644 drivers/dd/floppy/.cvsignore create mode 100644 drivers/dd/floppy/Makefile create mode 100644 drivers/dd/floppy/dpc.c create mode 100644 drivers/dd/floppy/floppy.c create mode 100644 drivers/dd/floppy/floppy.h create mode 100644 drivers/dd/floppy/floppy.rc create mode 100644 drivers/dd/floppy/isr.c create mode 100644 drivers/dd/ide/.cvsignore create mode 100644 drivers/dd/ide/ide.c create mode 100644 drivers/dd/ide/ide.h create mode 100644 drivers/dd/ide/ide.rc create mode 100644 drivers/dd/ide/makefile create mode 100644 drivers/dd/ide/partitio.h create mode 100644 drivers/dd/mouse/.cvsignore create mode 100644 drivers/dd/mouse/makefile create mode 100644 drivers/dd/mouse/mouse.c create mode 100644 drivers/dd/null/.cvsignore create mode 100644 drivers/dd/null/makefile create mode 100644 drivers/dd/null/null.c create mode 100644 drivers/dd/null/null.h create mode 100644 drivers/dd/null/null.rc create mode 100644 drivers/dd/parallel/.cvsignore create mode 100644 drivers/dd/parallel/makefile create mode 100644 drivers/dd/parallel/parallel.c create mode 100644 drivers/dd/parallel/parallel.h create mode 100644 drivers/dd/parallel/parallel.rc create mode 100644 drivers/dd/ramdrv/.cvsignore create mode 100644 drivers/dd/ramdrv/makefile create mode 100644 drivers/dd/ramdrv/ramdrv.c create mode 100644 drivers/dd/ramdrv/ramdrv.h create mode 100644 drivers/dd/sdisk/makefile create mode 100644 drivers/dd/sdisk/sdisk.c create mode 100644 drivers/dd/serial/.cvsignore create mode 100644 drivers/dd/serial/makefile create mode 100644 drivers/dd/serial/serial.c create mode 100644 drivers/dd/serial/serial.rc create mode 100644 drivers/dd/sound/.cvsignore create mode 100644 drivers/dd/sound/dsp.c create mode 100644 drivers/dd/sound/dsp.h create mode 100644 drivers/dd/sound/makefile create mode 100644 drivers/dd/sound/mixer.c create mode 100644 drivers/dd/sound/mixer.h create mode 100644 drivers/dd/sound/sb16.h create mode 100644 drivers/dd/sound/sb_waveout.c create mode 100644 drivers/dd/sound/sound.c create mode 100644 drivers/dd/sound/wave.c create mode 100644 drivers/dd/sound/wave.h create mode 100644 drivers/dd/test/.cvsignore create mode 100644 drivers/dd/test/makefile create mode 100644 drivers/dd/test/test.c create mode 100644 drivers/dd/vga/display/.cvsignore create mode 100644 drivers/dd/vga/display/main/enable.c create mode 100644 drivers/dd/vga/display/main/gdiinfo.h create mode 100644 drivers/dd/vga/display/makefile create mode 100644 drivers/dd/vga/display/objects/bitblt.c create mode 100644 drivers/dd/vga/display/objects/bitblt.h create mode 100644 drivers/dd/vga/display/objects/brush.h create mode 100644 drivers/dd/vga/display/objects/lineto.c create mode 100644 drivers/dd/vga/display/objects/offscreen.c create mode 100644 drivers/dd/vga/display/objects/paint.c create mode 100644 drivers/dd/vga/display/objects/pointer.c create mode 100644 drivers/dd/vga/display/objects/screen.c create mode 100644 drivers/dd/vga/display/objects/transblt.c create mode 100644 drivers/dd/vga/display/vgaddi.def create mode 100644 drivers/dd/vga/display/vgaddi.edf create mode 100644 drivers/dd/vga/display/vgaddi.h create mode 100644 drivers/dd/vga/display/vgaddi.rc create mode 100644 drivers/dd/vga/display/vgavideo/vgavideo.c create mode 100644 drivers/dd/vga/display/vgavideo/vgavideo.h create mode 100644 drivers/dd/vga/makefile create mode 100644 drivers/dd/vga/miniport/.cvsignore create mode 100644 drivers/dd/vga/miniport/initvga.c create mode 100644 drivers/dd/vga/miniport/makefile create mode 100644 drivers/dd/vga/miniport/vgamp.c create mode 100644 drivers/dd/vga/miniport/vgamp.rc create mode 100644 drivers/dd/vga/miniport/vgavideo.c create mode 100644 drivers/dd/vga/miniport/vgavideo.h create mode 100644 drivers/dd/vidport/.cvsignore create mode 100644 drivers/dd/vidport/makefile create mode 100644 drivers/dd/vidport/vidport.c create mode 100644 drivers/dd/vidport/vidport.def create mode 100644 drivers/dd/vidport/vidport.edf create mode 100644 drivers/dd/vidport/vidport.h create mode 100644 drivers/dd/vidport/vidport.rc create mode 100644 drivers/fs/cdfs/.cvsignore create mode 100644 drivers/fs/cdfs/cdfs.c create mode 100644 drivers/fs/cdfs/cdfs.h create mode 100644 drivers/fs/cdfs/cdfs.rc create mode 100644 drivers/fs/cdfs/cleanup.c create mode 100644 drivers/fs/cdfs/close.c create mode 100644 drivers/fs/cdfs/common.c create mode 100644 drivers/fs/cdfs/create.c create mode 100644 drivers/fs/cdfs/dirctl.c create mode 100644 drivers/fs/cdfs/fcb.c create mode 100644 drivers/fs/cdfs/finfo.c create mode 100644 drivers/fs/cdfs/fsctl.c create mode 100644 drivers/fs/cdfs/makefile create mode 100644 drivers/fs/cdfs/misc.c create mode 100644 drivers/fs/cdfs/rw.c create mode 100644 drivers/fs/cdfs/volinfo.c create mode 100644 drivers/fs/ext2/attr.c create mode 100644 drivers/fs/ext2/blockdev.c create mode 100644 drivers/fs/ext2/dir.c create mode 100644 drivers/fs/ext2/ext2fs.h create mode 100644 drivers/fs/ext2/ext2fs.rc create mode 100644 drivers/fs/ext2/file.c create mode 100644 drivers/fs/ext2/inode.c create mode 100644 drivers/fs/ext2/makefile create mode 100644 drivers/fs/ext2/quota.c create mode 100644 drivers/fs/ext2/rw.c create mode 100644 drivers/fs/ext2/security.c create mode 100644 drivers/fs/ext2/super.c create mode 100644 drivers/fs/fs_rec/.cvsignore create mode 100644 drivers/fs/fs_rec/blockdev.c create mode 100644 drivers/fs/fs_rec/cdfs.c create mode 100644 drivers/fs/fs_rec/fat.c create mode 100644 drivers/fs/fs_rec/fs_rec.c create mode 100644 drivers/fs/fs_rec/fs_rec.h create mode 100644 drivers/fs/fs_rec/fs_rec.rc create mode 100644 drivers/fs/fs_rec/makefile create mode 100644 drivers/fs/fs_rec/ntfs.c create mode 100644 drivers/fs/minix/.cvsignore create mode 100644 drivers/fs/minix/Makefile create mode 100644 drivers/fs/minix/bitops.c create mode 100644 drivers/fs/minix/bitops.h create mode 100644 drivers/fs/minix/block.c create mode 100644 drivers/fs/minix/blockdev.c create mode 100644 drivers/fs/minix/cache.c create mode 100644 drivers/fs/minix/dir.c create mode 100644 drivers/fs/minix/inode.c create mode 100644 drivers/fs/minix/minix.h create mode 100644 drivers/fs/minix/minix.rc create mode 100644 drivers/fs/minix/minix_fs.h create mode 100644 drivers/fs/minix/mount.c create mode 100644 drivers/fs/minix/rw.c create mode 100644 drivers/fs/ms/.cvsignore create mode 100644 drivers/fs/ms/Makefile create mode 100644 drivers/fs/ms/create.c create mode 100644 drivers/fs/ms/finfo.c create mode 100644 drivers/fs/ms/fsctrl.c create mode 100644 drivers/fs/ms/msfs.c create mode 100644 drivers/fs/ms/msfs.h create mode 100644 drivers/fs/ms/msfs.rc create mode 100644 drivers/fs/ms/rw.c create mode 100644 drivers/fs/mup/.cvsignore create mode 100644 drivers/fs/mup/create.c create mode 100644 drivers/fs/mup/makefile create mode 100644 drivers/fs/mup/mup.c create mode 100644 drivers/fs/mup/mup.h create mode 100644 drivers/fs/mup/mup.rc create mode 100644 drivers/fs/np/.cvsignore create mode 100644 drivers/fs/np/Makefile create mode 100644 drivers/fs/np/create.c create mode 100644 drivers/fs/np/finfo.c create mode 100644 drivers/fs/np/fsctrl.c create mode 100644 drivers/fs/np/npfs.c create mode 100644 drivers/fs/np/npfs.h create mode 100644 drivers/fs/np/npfs.rc create mode 100644 drivers/fs/np/rw.c create mode 100644 drivers/fs/np/volume.c create mode 100644 drivers/fs/ntfs/.cvsignore create mode 100644 drivers/fs/ntfs/attrib.c create mode 100644 drivers/fs/ntfs/blockdev.c create mode 100644 drivers/fs/ntfs/create.c create mode 100644 drivers/fs/ntfs/dirctl.c create mode 100644 drivers/fs/ntfs/fcb.c create mode 100644 drivers/fs/ntfs/finfo.c create mode 100644 drivers/fs/ntfs/fsctl.c create mode 100644 drivers/fs/ntfs/makefile create mode 100644 drivers/fs/ntfs/mft.c create mode 100644 drivers/fs/ntfs/ntfs.c create mode 100644 drivers/fs/ntfs/ntfs.h create mode 100644 drivers/fs/ntfs/ntfs.rc create mode 100644 drivers/fs/ntfs/volinfo.c create mode 100644 drivers/fs/template/makefile create mode 100644 drivers/fs/template/template.c create mode 100644 drivers/fs/vfat/.cvsignore create mode 100644 drivers/fs/vfat/blockdev.c create mode 100644 drivers/fs/vfat/cleanup.c create mode 100644 drivers/fs/vfat/close.c create mode 100644 drivers/fs/vfat/create.c create mode 100644 drivers/fs/vfat/dir.c create mode 100644 drivers/fs/vfat/direntry.c create mode 100644 drivers/fs/vfat/dirwr.c create mode 100644 drivers/fs/vfat/ea.c create mode 100644 drivers/fs/vfat/fat.c create mode 100644 drivers/fs/vfat/fcb.c create mode 100644 drivers/fs/vfat/finfo.c create mode 100644 drivers/fs/vfat/fsctl.c create mode 100644 drivers/fs/vfat/iface.c create mode 100644 drivers/fs/vfat/makefile create mode 100644 drivers/fs/vfat/misc.c create mode 100644 drivers/fs/vfat/rw.c create mode 100644 drivers/fs/vfat/shutdown.c create mode 100644 drivers/fs/vfat/string.c create mode 100644 drivers/fs/vfat/vfat.h create mode 100644 drivers/fs/vfat/vfat005.1st create mode 100644 drivers/fs/vfat/vfat_fr.txt create mode 100644 drivers/fs/vfat/vfatfs.def create mode 100644 drivers/fs/vfat/vfatfs.rc create mode 100644 drivers/fs/vfat/volume.c create mode 100644 drivers/input/include/mouse.h create mode 100644 drivers/input/keyboard/.cvsignore create mode 100644 drivers/input/keyboard/keyboard.c create mode 100644 drivers/input/keyboard/keyboard.h create mode 100644 drivers/input/keyboard/keyboard.rc create mode 100644 drivers/input/keyboard/makefile create mode 100644 drivers/input/mouclass/.cvsignore create mode 100644 drivers/input/mouclass/makefile create mode 100644 drivers/input/mouclass/mouclass.c create mode 100644 drivers/input/mouclass/mouclass.h create mode 100644 drivers/input/mouclass/mouclass.rc create mode 100644 drivers/input/psaux/.cvsignore create mode 100644 drivers/input/psaux/controller.c create mode 100644 drivers/input/psaux/controller.h create mode 100644 drivers/input/psaux/keyboard.h create mode 100644 drivers/input/psaux/makefile create mode 100644 drivers/input/psaux/mouse.c create mode 100644 drivers/input/psaux/mouse.h create mode 100644 drivers/input/psaux/psaux.c create mode 100644 drivers/input/psaux/psaux.h create mode 100644 drivers/input/psaux/psaux.rc create mode 100644 drivers/input/sermouse/.cvsignore create mode 100644 drivers/input/sermouse/makefile create mode 100644 drivers/input/sermouse/mouse.c create mode 100644 drivers/input/sermouse/mouse.h create mode 100644 drivers/input/sermouse/sermouse.c create mode 100644 drivers/input/sermouse/sermouse.h create mode 100644 drivers/input/sermouse/sermouse.rc create mode 100644 drivers/lib/bzip2/CHANGES create mode 100644 drivers/lib/bzip2/LICENSE create mode 100644 drivers/lib/bzip2/Makefile create mode 100644 drivers/lib/bzip2/Makefile-libbz2_so create mode 100644 drivers/lib/bzip2/README create mode 100644 drivers/lib/bzip2/README.COMPILATION.PROBLEMS create mode 100644 drivers/lib/bzip2/README.reactos create mode 100644 drivers/lib/bzip2/Y2K_INFO create mode 100644 drivers/lib/bzip2/blocksort.c create mode 100644 drivers/lib/bzip2/bzip2.1 create mode 100644 drivers/lib/bzip2/bzip2.1.preformatted create mode 100644 drivers/lib/bzip2/bzip2.c create mode 100644 drivers/lib/bzip2/bzip2.txt create mode 100644 drivers/lib/bzip2/bzip2recover.c create mode 100644 drivers/lib/bzip2/bzlib.c create mode 100644 drivers/lib/bzip2/bzlib.h create mode 100644 drivers/lib/bzip2/bzlib_private.h create mode 100644 drivers/lib/bzip2/compress.c create mode 100644 drivers/lib/bzip2/crctable.c create mode 100644 drivers/lib/bzip2/decompress.c create mode 100644 drivers/lib/bzip2/dllmain.c create mode 100644 drivers/lib/bzip2/dlltest.c create mode 100644 drivers/lib/bzip2/dlltest.dsp create mode 100644 drivers/lib/bzip2/huffman.c create mode 100644 drivers/lib/bzip2/libbz2.def create mode 100644 drivers/lib/bzip2/libbz2.dsp create mode 100644 drivers/lib/bzip2/makefile.msc create mode 100644 drivers/lib/bzip2/manual.ps create mode 100644 drivers/lib/bzip2/manual.texi create mode 100644 drivers/lib/bzip2/manual_1.html create mode 100644 drivers/lib/bzip2/manual_2.html create mode 100644 drivers/lib/bzip2/manual_3.html create mode 100644 drivers/lib/bzip2/manual_4.html create mode 100644 drivers/lib/bzip2/manual_toc.html create mode 100644 drivers/lib/bzip2/randtable.c create mode 100644 drivers/lib/bzip2/sample1.ref create mode 100644 drivers/lib/bzip2/sample2.ref create mode 100644 drivers/lib/bzip2/sample3.ref create mode 100644 drivers/lib/bzip2/spewG.c create mode 100644 drivers/lib/bzip2/unbzip2.def create mode 100644 drivers/lib/bzip2/unbzip2.edf create mode 100644 drivers/lib/bzip2/unzcrash.c create mode 100644 drivers/lib/bzip2/words0 create mode 100644 drivers/lib/bzip2/words1 create mode 100644 drivers/lib/bzip2/words2 create mode 100644 drivers/lib/bzip2/words3 create mode 100644 drivers/lib/zlib/.cvsignore create mode 100644 drivers/lib/zlib/ChangeLog create mode 100644 drivers/lib/zlib/FAQ create mode 100644 drivers/lib/zlib/INDEX create mode 100644 drivers/lib/zlib/Make_vms.com create mode 100644 drivers/lib/zlib/Makefile create mode 100644 drivers/lib/zlib/Makefile.in create mode 100644 drivers/lib/zlib/Makefile.riscos create mode 100644 drivers/lib/zlib/README create mode 100644 drivers/lib/zlib/adler32.c create mode 100644 drivers/lib/zlib/algorithm.txt create mode 100644 drivers/lib/zlib/amiga/Makefile.pup create mode 100644 drivers/lib/zlib/amiga/Makefile.sas create mode 100644 drivers/lib/zlib/compress.c create mode 100644 drivers/lib/zlib/configure create mode 100644 drivers/lib/zlib/contrib/README.contrib create mode 100644 drivers/lib/zlib/contrib/asm386/gvmat32.asm create mode 100644 drivers/lib/zlib/contrib/asm386/gvmat32c.c create mode 100644 drivers/lib/zlib/contrib/asm386/mkgvmt32.bat create mode 100644 drivers/lib/zlib/contrib/asm386/zlibvc.def create mode 100644 drivers/lib/zlib/contrib/asm386/zlibvc.dsp create mode 100644 drivers/lib/zlib/contrib/asm386/zlibvc.dsw create mode 100644 drivers/lib/zlib/contrib/asm586/README.586 create mode 100644 drivers/lib/zlib/contrib/asm586/match.S create mode 100644 drivers/lib/zlib/contrib/asm686/README.686 create mode 100644 drivers/lib/zlib/contrib/asm686/match.S create mode 100644 drivers/lib/zlib/contrib/delphi/zlib.mak create mode 100644 drivers/lib/zlib/contrib/delphi/zlibdef.pas create mode 100644 drivers/lib/zlib/contrib/delphi2/d_zlib.bpr create mode 100644 drivers/lib/zlib/contrib/delphi2/d_zlib.cpp create mode 100644 drivers/lib/zlib/contrib/delphi2/readme.txt create mode 100644 drivers/lib/zlib/contrib/delphi2/zlib.bpg create mode 100644 drivers/lib/zlib/contrib/delphi2/zlib.bpr create mode 100644 drivers/lib/zlib/contrib/delphi2/zlib.cpp create mode 100644 drivers/lib/zlib/contrib/delphi2/zlib.pas create mode 100644 drivers/lib/zlib/contrib/delphi2/zlib32.bpr create mode 100644 drivers/lib/zlib/contrib/delphi2/zlib32.cpp create mode 100644 drivers/lib/zlib/contrib/iostream/test.cpp create mode 100644 drivers/lib/zlib/contrib/iostream/zfstream.cpp create mode 100644 drivers/lib/zlib/contrib/iostream/zfstream.h create mode 100644 drivers/lib/zlib/contrib/iostream2/zstream.h create mode 100644 drivers/lib/zlib/contrib/iostream2/zstream_test.cpp create mode 100644 drivers/lib/zlib/contrib/minizip/ChangeLogUnzip create mode 100644 drivers/lib/zlib/contrib/minizip/Makefile create mode 100644 drivers/lib/zlib/contrib/minizip/miniunz.c create mode 100644 drivers/lib/zlib/contrib/minizip/minizip.c create mode 100644 drivers/lib/zlib/contrib/minizip/readme.txt create mode 100644 drivers/lib/zlib/contrib/minizip/unzip.c create mode 100644 drivers/lib/zlib/contrib/minizip/unzip.def create mode 100644 drivers/lib/zlib/contrib/minizip/unzip.h create mode 100644 drivers/lib/zlib/contrib/minizip/zip.c create mode 100644 drivers/lib/zlib/contrib/minizip/zip.def create mode 100644 drivers/lib/zlib/contrib/minizip/zip.h create mode 100644 drivers/lib/zlib/contrib/minizip/zlibvc.def create mode 100644 drivers/lib/zlib/contrib/minizip/zlibvc.dsp create mode 100644 drivers/lib/zlib/contrib/minizip/zlibvc.dsw create mode 100644 drivers/lib/zlib/contrib/untgz/Makefile create mode 100644 drivers/lib/zlib/contrib/untgz/makefile.w32 create mode 100644 drivers/lib/zlib/contrib/untgz/untgz.c create mode 100644 drivers/lib/zlib/contrib/visual-basic.txt create mode 100644 drivers/lib/zlib/crc32.c create mode 100644 drivers/lib/zlib/deflate.c create mode 100644 drivers/lib/zlib/deflate.h create mode 100644 drivers/lib/zlib/descrip.mms create mode 100644 drivers/lib/zlib/example.c create mode 100644 drivers/lib/zlib/gzio.c create mode 100644 drivers/lib/zlib/infblock.c create mode 100644 drivers/lib/zlib/infblock.h create mode 100644 drivers/lib/zlib/infcodes.c create mode 100644 drivers/lib/zlib/infcodes.h create mode 100644 drivers/lib/zlib/inffast.c create mode 100644 drivers/lib/zlib/inffast.h create mode 100644 drivers/lib/zlib/inffixed.h create mode 100644 drivers/lib/zlib/inflate.c create mode 100644 drivers/lib/zlib/inftrees.c create mode 100644 drivers/lib/zlib/inftrees.h create mode 100644 drivers/lib/zlib/infutil.c create mode 100644 drivers/lib/zlib/infutil.h create mode 100644 drivers/lib/zlib/makefile.reactos create mode 100644 drivers/lib/zlib/maketree.c create mode 100644 drivers/lib/zlib/minigzip.c create mode 100644 drivers/lib/zlib/msdos/Makefile.b32 create mode 100644 drivers/lib/zlib/msdos/Makefile.bor create mode 100644 drivers/lib/zlib/msdos/Makefile.dj2 create mode 100644 drivers/lib/zlib/msdos/Makefile.emx create mode 100644 drivers/lib/zlib/msdos/Makefile.msc create mode 100644 drivers/lib/zlib/msdos/Makefile.tc create mode 100644 drivers/lib/zlib/msdos/Makefile.w32 create mode 100644 drivers/lib/zlib/msdos/Makefile.wat create mode 100644 drivers/lib/zlib/msdos/zlib.def create mode 100644 drivers/lib/zlib/msdos/zlib.rc create mode 100644 drivers/lib/zlib/nt/Makefile.emx create mode 100644 drivers/lib/zlib/nt/Makefile.gcc create mode 100644 drivers/lib/zlib/nt/Makefile.nt create mode 100644 drivers/lib/zlib/nt/zlib.dnt create mode 100644 drivers/lib/zlib/os2/Makefile.os2 create mode 100644 drivers/lib/zlib/os2/zlib.def create mode 100644 drivers/lib/zlib/trees.c create mode 100644 drivers/lib/zlib/trees.h create mode 100644 drivers/lib/zlib/uncompr.c create mode 100644 drivers/lib/zlib/zconf.h create mode 100644 drivers/lib/zlib/zlib.3 create mode 100644 drivers/lib/zlib/zlib.h create mode 100644 drivers/lib/zlib/zlib.html create mode 100644 drivers/lib/zlib/zutil.c create mode 100644 drivers/lib/zlib/zutil.h create mode 100644 drivers/net/afd/.cvsignore create mode 100644 drivers/net/afd/afd.def create mode 100644 drivers/net/afd/afd.rc create mode 100644 drivers/net/afd/afd/afd.c create mode 100644 drivers/net/afd/afd/dispatch.c create mode 100644 drivers/net/afd/afd/event.c create mode 100644 drivers/net/afd/afd/opnclose.c create mode 100644 drivers/net/afd/afd/rdwr.c create mode 100644 drivers/net/afd/afd/routines.c create mode 100644 drivers/net/afd/afd/tdi.c create mode 100644 drivers/net/afd/include/afd.h create mode 100644 drivers/net/afd/include/debug.h create mode 100644 drivers/net/afd/makefile create mode 100644 drivers/net/dd/ne2000/.cvsignore create mode 100644 drivers/net/dd/ne2000/Makefile create mode 100644 drivers/net/dd/ne2000/include/8390.h create mode 100644 drivers/net/dd/ne2000/include/debug.h create mode 100644 drivers/net/dd/ne2000/include/ne2000.h create mode 100644 drivers/net/dd/ne2000/ne2000.rc create mode 100644 drivers/net/dd/ne2000/ne2000/8390.c create mode 100644 drivers/net/dd/ne2000/ne2000/main.c create mode 100644 drivers/net/ndis/.cvsignore create mode 100644 drivers/net/ndis/DIRS create mode 100644 drivers/net/ndis/Makefile create mode 100644 drivers/net/ndis/include/buffer.h create mode 100644 drivers/net/ndis/include/debug.h create mode 100644 drivers/net/ndis/include/miniport.h create mode 100644 drivers/net/ndis/include/ndissys.h create mode 100644 drivers/net/ndis/include/protocol.h create mode 100644 drivers/net/ndis/ndis.def create mode 100644 drivers/net/ndis/ndis.edf create mode 100644 drivers/net/ndis/ndis.rc create mode 100644 drivers/net/ndis/ndis/40gone.c create mode 100644 drivers/net/ndis/ndis/50gone.c create mode 100644 drivers/net/ndis/ndis/SOURCES create mode 100644 drivers/net/ndis/ndis/buffer.c create mode 100644 drivers/net/ndis/ndis/cl.c create mode 100644 drivers/net/ndis/ndis/cm.c create mode 100644 drivers/net/ndis/ndis/co.c create mode 100644 drivers/net/ndis/ndis/control.c create mode 100644 drivers/net/ndis/ndis/hardware.c create mode 100644 drivers/net/ndis/ndis/io.c create mode 100644 drivers/net/ndis/ndis/main.c create mode 100644 drivers/net/ndis/ndis/memory.c create mode 100644 drivers/net/ndis/ndis/miniport.c create mode 100644 drivers/net/ndis/ndis/protocol.c create mode 100644 drivers/net/ndis/ndis/string.c create mode 100644 drivers/net/ndis/ndis/stubs.c create mode 100644 drivers/net/ndis/ndis/time.c create mode 100644 drivers/net/ndis/readme.txt create mode 100644 drivers/net/packet/.cvsignore create mode 100644 drivers/net/packet/Makefile create mode 100644 drivers/net/packet/bucket_lookup.c create mode 100644 drivers/net/packet/bucket_lookup.h create mode 100644 drivers/net/packet/count_packets.c create mode 100644 drivers/net/packet/count_packets.h create mode 100644 drivers/net/packet/debug.h create mode 100644 drivers/net/packet/dump.c create mode 100644 drivers/net/packet/functions.c create mode 100644 drivers/net/packet/functions.h create mode 100644 drivers/net/packet/jitter.c create mode 100644 drivers/net/packet/jitter.h create mode 100644 drivers/net/packet/memory_t.c create mode 100644 drivers/net/packet/memory_t.h create mode 100644 drivers/net/packet/normal_lookup.c create mode 100644 drivers/net/packet/normal_lookup.h create mode 100644 drivers/net/packet/ntddpack.h create mode 100644 drivers/net/packet/openclos.c create mode 100644 drivers/net/packet/packet.c create mode 100644 drivers/net/packet/packet.def create mode 100644 drivers/net/packet/packet.edf create mode 100644 drivers/net/packet/packet.h create mode 100644 drivers/net/packet/packet.rc create mode 100644 drivers/net/packet/read.c create mode 100644 drivers/net/packet/resource.h create mode 100644 drivers/net/packet/tcp_session.c create mode 100644 drivers/net/packet/tcp_session.h create mode 100644 drivers/net/packet/time_calls.c create mode 100644 drivers/net/packet/time_calls.h create mode 100644 drivers/net/packet/tme.c create mode 100644 drivers/net/packet/tme.h create mode 100644 drivers/net/packet/valid_insns.h create mode 100644 drivers/net/packet/win_bpf.h create mode 100644 drivers/net/packet/win_bpf_filter.c create mode 100644 drivers/net/packet/win_bpf_filter_init.c create mode 100644 drivers/net/packet/win_bpf_filter_init.h create mode 100644 drivers/net/packet/write.c create mode 100644 drivers/net/tcpip/.cvsignore create mode 100644 drivers/net/tcpip/DIRS create mode 100644 drivers/net/tcpip/datalink/Makefile create mode 100644 drivers/net/tcpip/datalink/SOURCES create mode 100644 drivers/net/tcpip/datalink/arp.c create mode 100644 drivers/net/tcpip/datalink/lan.c create mode 100644 drivers/net/tcpip/datalink/loopback.c create mode 100644 drivers/net/tcpip/include/address.h create mode 100644 drivers/net/tcpip/include/arp.h create mode 100644 drivers/net/tcpip/include/checksum.h create mode 100644 drivers/net/tcpip/include/datagram.h create mode 100644 drivers/net/tcpip/include/debug.h create mode 100644 drivers/net/tcpip/include/dispatch.h create mode 100644 drivers/net/tcpip/include/fileobjs.h create mode 100644 drivers/net/tcpip/include/icmp.h create mode 100644 drivers/net/tcpip/include/info.h create mode 100644 drivers/net/tcpip/include/ip.h create mode 100644 drivers/net/tcpip/include/lan.h create mode 100644 drivers/net/tcpip/include/loopback.h create mode 100644 drivers/net/tcpip/include/neighbor.h create mode 100644 drivers/net/tcpip/include/pool.h create mode 100644 drivers/net/tcpip/include/rawip.h create mode 100644 drivers/net/tcpip/include/receive.h create mode 100644 drivers/net/tcpip/include/route.h create mode 100644 drivers/net/tcpip/include/router.h create mode 100644 drivers/net/tcpip/include/routines.h create mode 100644 drivers/net/tcpip/include/tcp.h create mode 100644 drivers/net/tcpip/include/tcpip.h create mode 100644 drivers/net/tcpip/include/ticonsts.h create mode 100644 drivers/net/tcpip/include/titypes.h create mode 100644 drivers/net/tcpip/include/transmit.h create mode 100644 drivers/net/tcpip/include/udp.h create mode 100644 drivers/net/tcpip/makefile create mode 100644 drivers/net/tcpip/network/Makefile create mode 100644 drivers/net/tcpip/network/SOURCES create mode 100644 drivers/net/tcpip/network/icmp.c create mode 100644 drivers/net/tcpip/network/ip.c create mode 100644 drivers/net/tcpip/network/neighbor.c create mode 100644 drivers/net/tcpip/network/receive.c create mode 100644 drivers/net/tcpip/network/route.c create mode 100644 drivers/net/tcpip/network/router.c create mode 100644 drivers/net/tcpip/network/transmit.c create mode 100644 drivers/net/tcpip/readme.txt create mode 100644 drivers/net/tcpip/tcpip.def create mode 100644 drivers/net/tcpip/tcpip.edf create mode 100644 drivers/net/tcpip/tcpip.rc create mode 100644 drivers/net/tcpip/tcpip/Makefile create mode 100644 drivers/net/tcpip/tcpip/SOURCES create mode 100644 drivers/net/tcpip/tcpip/address.c create mode 100644 drivers/net/tcpip/tcpip/checksum.c create mode 100644 drivers/net/tcpip/tcpip/dispatch.c create mode 100644 drivers/net/tcpip/tcpip/fileobjs.c create mode 100644 drivers/net/tcpip/tcpip/info.c create mode 100644 drivers/net/tcpip/tcpip/main.c create mode 100644 drivers/net/tcpip/tcpip/pool.c create mode 100644 drivers/net/tcpip/tcpip/resource.rc create mode 100644 drivers/net/tcpip/tcpip/routines.c create mode 100644 drivers/net/tcpip/tcpip/tcpip.def create mode 100644 drivers/net/tcpip/transport/DIRS create mode 100644 drivers/net/tcpip/transport/datagram/Makefile create mode 100644 drivers/net/tcpip/transport/datagram/SOURCES create mode 100644 drivers/net/tcpip/transport/datagram/datagram.c create mode 100644 drivers/net/tcpip/transport/rawip/Makefile create mode 100644 drivers/net/tcpip/transport/rawip/SOURCES create mode 100644 drivers/net/tcpip/transport/rawip/rawip.c create mode 100644 drivers/net/tcpip/transport/tcp/Makefile create mode 100644 drivers/net/tcpip/transport/tcp/SOURCES create mode 100644 drivers/net/tcpip/transport/tcp/tcp.c create mode 100644 drivers/net/tcpip/transport/udp/Makefile create mode 100644 drivers/net/tcpip/transport/udp/SOURCES create mode 100644 drivers/net/tcpip/transport/udp/udp.c create mode 100644 drivers/net/tdi/Makefile create mode 100644 drivers/net/tdi/cte/string.c create mode 100644 drivers/net/tdi/cte/stubs.c create mode 100644 drivers/net/tdi/misc/.cvsignore create mode 100644 drivers/net/tdi/misc/main.c create mode 100644 drivers/net/tdi/misc/tdi.def create mode 100644 drivers/net/tdi/misc/tdi.edf create mode 100644 drivers/net/tdi/misc/tdi.rc create mode 100644 drivers/net/tdi/tdi/dereg.c create mode 100644 drivers/net/tdi/tdi/handler.c create mode 100644 drivers/net/tdi/tdi/obsolete.c create mode 100644 drivers/net/tdi/tdi/stubs.c create mode 100644 drivers/net/tditest/.cvsignore create mode 100644 drivers/net/tditest/DIRS create mode 100644 drivers/net/tditest/include/debug.h create mode 100644 drivers/net/tditest/include/tditest.h create mode 100644 drivers/net/tditest/makefile create mode 100644 drivers/net/tditest/readme.txt create mode 100644 drivers/net/tditest/tditest.def create mode 100644 drivers/net/tditest/tditest.rc create mode 100644 drivers/net/tditest/tditest/Makefile create mode 100644 drivers/net/tditest/tditest/SOURCES create mode 100644 drivers/net/tditest/tditest/tditest.c create mode 100644 drivers/net/wshtcpip/.cvsignore create mode 100644 drivers/net/wshtcpip/debug.h create mode 100644 drivers/net/wshtcpip/makefile create mode 100644 drivers/net/wshtcpip/wshtcpip.c create mode 100644 drivers/net/wshtcpip/wshtcpip.def create mode 100644 drivers/net/wshtcpip/wshtcpip.edf create mode 100644 drivers/net/wshtcpip/wshtcpip.h create mode 100644 drivers/net/wshtcpip/wshtcpip.rc create mode 100644 drivers/net/wshtcpip/wshtcpip_specs create mode 100644 drivers/readme create mode 100644 drivers/storage/atapi/.cvsignore create mode 100644 drivers/storage/atapi/atapi.c create mode 100644 drivers/storage/atapi/atapi.h create mode 100644 drivers/storage/atapi/atapi.rc create mode 100644 drivers/storage/atapi/makefile create mode 100644 drivers/storage/cdrom/.cvsignore create mode 100644 drivers/storage/cdrom/cdrom.c create mode 100644 drivers/storage/cdrom/cdrom.rc create mode 100644 drivers/storage/cdrom/makefile create mode 100644 drivers/storage/class2/.cvsignore create mode 100644 drivers/storage/class2/class2.c create mode 100644 drivers/storage/class2/class2.def create mode 100644 drivers/storage/class2/class2.edf create mode 100644 drivers/storage/class2/class2.rc create mode 100644 drivers/storage/class2/makefile create mode 100644 drivers/storage/disk/.cvsignore create mode 100644 drivers/storage/disk/disk.c create mode 100644 drivers/storage/disk/disk.h create mode 100644 drivers/storage/disk/disk.rc create mode 100644 drivers/storage/disk/makefile create mode 100644 drivers/storage/disk/partitio.h create mode 100644 drivers/storage/scsiport/.cvsignore create mode 100644 drivers/storage/scsiport/makefile create mode 100644 drivers/storage/scsiport/scsiport.c create mode 100644 drivers/storage/scsiport/scsiport.def create mode 100644 drivers/storage/scsiport/scsiport.edf create mode 100644 drivers/storage/scsiport/scsiport.rc create mode 100644 gdb.ini create mode 100644 hal/hal/.cvsignore create mode 100644 hal/hal/Makefile create mode 100644 hal/hal/hal.c create mode 100644 hal/hal/hal.def create mode 100644 hal/hal/hal.edf create mode 100644 hal/hal/hal.rc create mode 100644 hal/halx86/.cvsignore create mode 100644 hal/halx86/Makefile create mode 100644 hal/halx86/adapter.c create mode 100644 hal/halx86/beep.c create mode 100644 hal/halx86/bios32.c create mode 100644 hal/halx86/bus.c create mode 100644 hal/halx86/display.c create mode 100644 hal/halx86/dma.c create mode 100644 hal/halx86/drive.c create mode 100644 hal/halx86/enum.c create mode 100644 hal/halx86/fmutex.c create mode 100644 hal/halx86/halinit.c create mode 100644 hal/halx86/halx86mp.rc create mode 100644 hal/halx86/halx86up.rc create mode 100644 hal/halx86/include/bus.h create mode 100644 hal/halx86/include/hal.h create mode 100644 hal/halx86/include/mps.h create mode 100644 hal/halx86/irql.c create mode 100644 hal/halx86/isa.c create mode 100644 hal/halx86/kdbg.c create mode 100644 hal/halx86/mbr.c create mode 100644 hal/halx86/mca.c create mode 100644 hal/halx86/misc.c create mode 100644 hal/halx86/mp.c create mode 100644 hal/halx86/mps.S create mode 100644 hal/halx86/mpsboot.asm create mode 100644 hal/halx86/mpsirql.c create mode 100644 hal/halx86/pci.c create mode 100644 hal/halx86/perfcnt.c create mode 100644 hal/halx86/portio.c create mode 100644 hal/halx86/pwroff.c create mode 100644 hal/halx86/reboot.c create mode 100644 hal/halx86/spinlock.c create mode 100644 hal/halx86/sysbus.c create mode 100644 hal/halx86/sysinfo.c create mode 100644 hal/halx86/time.c create mode 100644 hal/halx86/udelay.c create mode 100644 iface/addsys/.cvsignore create mode 100644 iface/addsys/genw32k.c create mode 100644 iface/addsys/makefile create mode 100644 iface/addsys/w32ksvc.db create mode 100644 iface/dll/.cvsignore create mode 100644 iface/dll/defedf.c create mode 100644 iface/dll/makefile create mode 100644 iface/native/.cvsignore create mode 100644 iface/native/genntdll.c create mode 100644 iface/native/makefile create mode 100644 iface/native/sysfuncs.lst create mode 100644 include/.cvsignore create mode 100644 include/afd/shared.h create mode 100644 include/ascii.h create mode 100644 include/base.h create mode 100644 include/coff.h create mode 100644 include/crtdll/alloc.h create mode 100644 include/crtdll/assert.h create mode 100644 include/crtdll/conio.h create mode 100644 include/crtdll/crtdll.h create mode 100644 include/crtdll/ctype.h create mode 100644 include/crtdll/dir.h create mode 100644 include/crtdll/direct.h create mode 100644 include/crtdll/dirent.h create mode 100644 include/crtdll/dos.h create mode 100644 include/crtdll/errno.h create mode 100644 include/crtdll/excpt.h create mode 100644 include/crtdll/fcntl.h create mode 100644 include/crtdll/float.h create mode 100644 include/crtdll/internal/atexit.h create mode 100644 include/crtdll/internal/file.h create mode 100644 include/crtdll/internal/ieee.h create mode 100644 include/crtdll/internal/quad.h create mode 100644 include/crtdll/io.h create mode 100644 include/crtdll/locale.h create mode 100644 include/crtdll/malloc.h create mode 100644 include/crtdll/math.h create mode 100644 include/crtdll/mbctype.h create mode 100644 include/crtdll/mbstring.h create mode 100644 include/crtdll/process.h create mode 100644 include/crtdll/search.h create mode 100644 include/crtdll/setjmp.h create mode 100644 include/crtdll/share.h create mode 100644 include/crtdll/signal.h create mode 100644 include/crtdll/stdarg.h create mode 100644 include/crtdll/stddef.h create mode 100644 include/crtdll/stdio.h create mode 100644 include/crtdll/stdlib.h create mode 100644 include/crtdll/string.h create mode 100644 include/crtdll/sys/fcntl.h create mode 100644 include/crtdll/sys/file.h create mode 100644 include/crtdll/sys/locking.h create mode 100644 include/crtdll/sys/stat.h create mode 100644 include/crtdll/sys/time.h create mode 100644 include/crtdll/sys/timeb.h create mode 100644 include/crtdll/sys/types.h create mode 100644 include/crtdll/sys/unistd.h create mode 100644 include/crtdll/sys/utime.h create mode 100644 include/crtdll/tchar.h create mode 100644 include/crtdll/time.h create mode 100644 include/crtdll/wchar.h create mode 100644 include/csrss/csrss.h create mode 100644 include/ddk/ccfuncs.h create mode 100644 include/ddk/cctypes.h create mode 100644 include/ddk/class2.h create mode 100644 include/ddk/cmfuncs.h create mode 100644 include/ddk/cmtypes.h create mode 100644 include/ddk/dbgfuncs.h create mode 100644 include/ddk/defines.h create mode 100644 include/ddk/exfuncs.h create mode 100644 include/ddk/extypes.h create mode 100644 include/ddk/fsfuncs.h create mode 100644 include/ddk/fstypes.h create mode 100644 include/ddk/halfuncs.h create mode 100644 include/ddk/haltypes.h create mode 100644 include/ddk/i386/irql.h create mode 100644 include/ddk/i386/pagesize.h create mode 100644 include/ddk/i386/tss.h create mode 100644 include/ddk/ioctrl.h create mode 100644 include/ddk/iodef.h create mode 100644 include/ddk/iofuncs.h create mode 100644 include/ddk/iotypes.h create mode 100644 include/ddk/kdfuncs.h create mode 100644 include/ddk/kedef.h create mode 100644 include/ddk/kefuncs.h create mode 100644 include/ddk/ketypes.h create mode 100644 include/ddk/ldrfuncs.h create mode 100644 include/ddk/ldrtypes.h create mode 100644 include/ddk/miniport.h create mode 100644 include/ddk/mmfuncs.h create mode 100644 include/ddk/mmtypes.h create mode 100644 include/ddk/ntdd8042.h create mode 100644 include/ddk/ntddbeep.h create mode 100644 include/ddk/ntddblue.h create mode 100644 include/ddk/ntddk.h create mode 100644 include/ddk/ntddkbd.h create mode 100644 include/ddk/ntddscsi.h create mode 100644 include/ddk/ntddser.h create mode 100644 include/ddk/ntddvid.h create mode 100644 include/ddk/ntdef.h create mode 100644 include/ddk/ntifs.h create mode 100644 include/ddk/obfuncs.h create mode 100644 include/ddk/obtypes.h create mode 100644 include/ddk/pnpfuncs.h create mode 100644 include/ddk/pnptypes.h create mode 100644 include/ddk/pofuncs.h create mode 100644 include/ddk/potypes.h create mode 100644 include/ddk/psfuncs.h create mode 100644 include/ddk/pstypes.h create mode 100644 include/ddk/rtl.h create mode 100644 include/ddk/rtltypes.h create mode 100644 include/ddk/scsi.h create mode 100644 include/ddk/sefuncs.h create mode 100644 include/ddk/service.h create mode 100644 include/ddk/setypes.h create mode 100644 include/ddk/srb.h create mode 100644 include/ddk/status.h create mode 100644 include/ddk/structs.h create mode 100644 include/ddk/types.h create mode 100644 include/ddk/winddi.h create mode 100644 include/ddk/zw.h create mode 100644 include/ddk/zwtypes.h create mode 100644 include/debug.h create mode 100644 include/defines.h create mode 100644 include/devices.h create mode 100644 include/dflat32/classdef.h create mode 100644 include/dflat32/classes.h create mode 100644 include/dflat32/commands.h create mode 100644 include/dflat32/config.h create mode 100644 include/dflat32/dflat.h create mode 100644 include/dflat32/dflatmsg.h create mode 100644 include/dflat32/dialbox.h create mode 100644 include/dflat32/htree.h create mode 100644 include/dflat32/keys.h create mode 100644 include/dflat32/menu.h create mode 100644 include/dflat32/rect.h create mode 100644 include/dflat32/system.h create mode 100644 include/dflat32/video.h create mode 100644 include/errors.h create mode 100644 include/excpt.h create mode 100644 include/fmifs.h create mode 100644 include/freetype/config/ftconfig.h create mode 100644 include/freetype/config/ftmodule.h create mode 100644 include/freetype/config/ftoption.h create mode 100644 include/freetype/freetype.h create mode 100644 include/freetype/ftbbox.h create mode 100644 include/freetype/fterrors.h create mode 100644 include/freetype/ftglyph.h create mode 100644 include/freetype/ftimage.h create mode 100644 include/freetype/ftmm.h create mode 100644 include/freetype/ftmodule.h create mode 100644 include/freetype/ftnames.h create mode 100644 include/freetype/ftoutln.h create mode 100644 include/freetype/ftrender.h create mode 100644 include/freetype/ftsystem.h create mode 100644 include/freetype/fttypes.h create mode 100644 include/freetype/internal/autohint.h create mode 100644 include/freetype/internal/ftcalc.h create mode 100644 include/freetype/internal/ftdebug.h create mode 100644 include/freetype/internal/ftdriver.h create mode 100644 include/freetype/internal/ftextend.h create mode 100644 include/freetype/internal/ftlist.h create mode 100644 include/freetype/internal/ftmemory.h create mode 100644 include/freetype/internal/ftobjs.h create mode 100644 include/freetype/internal/ftstream.h create mode 100644 include/freetype/internal/psnames.h create mode 100644 include/freetype/internal/sfnt.h create mode 100644 include/freetype/internal/t1errors.h create mode 100644 include/freetype/internal/t1types.h create mode 100644 include/freetype/internal/t2errors.h create mode 100644 include/freetype/internal/t2types.h create mode 100644 include/freetype/internal/tterrors.h create mode 100644 include/freetype/internal/tttypes.h create mode 100644 include/freetype/t1tables.h create mode 100644 include/freetype/ttnameid.h create mode 100644 include/freetype/tttables.h create mode 100644 include/freetype/tttags.h create mode 100644 include/funcs.h create mode 100644 include/getopt.h create mode 100644 include/in.h create mode 100644 include/kernel32/cptable.h create mode 100644 include/kernel32/error.h create mode 100644 include/kernel32/heap.h create mode 100644 include/kernel32/kernel32.h create mode 100644 include/kernel32/lctable.h create mode 100644 include/kernel32/nls.h create mode 100644 include/kernel32/proc.h create mode 100644 include/kernel32/process.h create mode 100644 include/kernel32/thread.h create mode 100644 include/kernel32/winnls.h create mode 100644 include/libc/atexit.h create mode 100644 include/libc/file.h create mode 100644 include/libc/ieee.h create mode 100644 include/lsass/lsass.h create mode 100644 include/lsass/ntsecapi.h create mode 100644 include/messages.h create mode 100644 include/msvcrt/alloc.h create mode 100644 include/msvcrt/assert.h create mode 100644 include/msvcrt/conio.h create mode 100644 include/msvcrt/ctype.h create mode 100644 include/msvcrt/dir.h create mode 100644 include/msvcrt/direct.h create mode 100644 include/msvcrt/errno.h create mode 100644 include/msvcrt/fcntl.h create mode 100644 include/msvcrt/float.h create mode 100644 include/msvcrt/internal/atexit.h create mode 100644 include/msvcrt/internal/console.h create mode 100644 include/msvcrt/internal/file.h create mode 100644 include/msvcrt/internal/ieee.h create mode 100644 include/msvcrt/internal/rterror.h create mode 100644 include/msvcrt/internal/stdio.h create mode 100644 include/msvcrt/internal/tls.h create mode 100644 include/msvcrt/io.h create mode 100644 include/msvcrt/locale.h create mode 100644 include/msvcrt/malloc.h create mode 100644 include/msvcrt/math.h create mode 100644 include/msvcrt/mbctype.h create mode 100644 include/msvcrt/mbstring.h create mode 100644 include/msvcrt/msvcrtdbg.h create mode 100644 include/msvcrt/process.h create mode 100644 include/msvcrt/search.h create mode 100644 include/msvcrt/share.h create mode 100644 include/msvcrt/signal.h create mode 100644 include/msvcrt/stdarg.h create mode 100644 include/msvcrt/stddef.h create mode 100644 include/msvcrt/stdio.h create mode 100644 include/msvcrt/stdlib.h create mode 100644 include/msvcrt/string.h create mode 100644 include/msvcrt/sys/fcntl.h create mode 100644 include/msvcrt/sys/file.h create mode 100644 include/msvcrt/sys/locking.h create mode 100644 include/msvcrt/sys/stat.h create mode 100644 include/msvcrt/sys/time.h create mode 100644 include/msvcrt/sys/timeb.h create mode 100644 include/msvcrt/sys/types.h create mode 100644 include/msvcrt/sys/unistd.h create mode 100644 include/msvcrt/sys/utime.h create mode 100644 include/msvcrt/time.h create mode 100644 include/msvcrt/wchar.h create mode 100644 include/napi/core.h create mode 100644 include/napi/dbg.h create mode 100644 include/napi/i386/segment.h create mode 100644 include/napi/lpc.h create mode 100644 include/napi/npipe.h create mode 100644 include/napi/shared_data.h create mode 100644 include/napi/teb.h create mode 100644 include/napi/types.h create mode 100644 include/napi/win32.h create mode 100644 include/net/miniport.h create mode 100644 include/net/ndis.h create mode 100644 include/net/ndisoid.h create mode 100644 include/net/netevent.h create mode 100644 include/net/ntddndis.h create mode 100644 include/net/tdi.h create mode 100644 include/net/tdiinfo.h create mode 100644 include/net/tdikrnl.h create mode 100644 include/ntddk.h create mode 100644 include/ntdll/.cvsignore create mode 100644 include/ntdll/base.h create mode 100644 include/ntdll/csr.h create mode 100644 include/ntdll/dbg.h create mode 100644 include/ntdll/ldr.h create mode 100644 include/ntdll/ntdll.h create mode 100644 include/ntdll/pagesize.h create mode 100644 include/ntdll/registry.h create mode 100644 include/ntdll/rtl.h create mode 100644 include/ntdll/trace.h create mode 100644 include/ntos.h create mode 100644 include/ntos/cdrom.h create mode 100644 include/ntos/console.h create mode 100644 include/ntos/disk.h create mode 100644 include/ntos/except.h create mode 100644 include/ntos/file.h create mode 100644 include/ntos/gditypes.h create mode 100644 include/ntos/heap.h create mode 100644 include/ntos/kdbgsyms.h create mode 100644 include/ntos/keyboard.h create mode 100644 include/ntos/minmax.h create mode 100644 include/ntos/mm.h create mode 100644 include/ntos/ntdef.h create mode 100644 include/ntos/port.h create mode 100644 include/ntos/ps.h create mode 100644 include/ntos/registry.h create mode 100644 include/ntos/security.h create mode 100644 include/ntos/synch.h create mode 100644 include/ntos/time.h create mode 100644 include/ntos/types.h create mode 100644 include/ole32/basetyps.h create mode 100644 include/ole32/guiddef.h create mode 100644 include/ole32/obj_base.h create mode 100644 include/ole32/obj_cache.h create mode 100644 include/ole32/obj_channel.h create mode 100644 include/ole32/obj_clientserver.h create mode 100644 include/ole32/obj_commdlgbrowser.h create mode 100644 include/ole32/obj_connection.h create mode 100644 include/ole32/obj_contextmenu.h create mode 100644 include/ole32/obj_control.h create mode 100644 include/ole32/obj_dataobject.h create mode 100644 include/ole32/obj_dockingwindowframe.h create mode 100644 include/ole32/obj_dragdrop.h create mode 100644 include/ole32/obj_enumidlist.h create mode 100644 include/ole32/obj_errorinfo.h create mode 100644 include/ole32/obj_extracticon.h create mode 100644 include/ole32/obj_inplace.h create mode 100644 include/ole32/obj_marshal.h create mode 100644 include/ole32/obj_misc.h create mode 100644 include/ole32/obj_moniker.h create mode 100644 include/ole32/obj_oleaut.h create mode 100644 include/ole32/obj_olefont.h create mode 100644 include/ole32/obj_oleobj.h create mode 100644 include/ole32/obj_oleundo.h create mode 100644 include/ole32/obj_oleview.h create mode 100644 include/ole32/obj_picture.h create mode 100644 include/ole32/obj_property.h create mode 100644 include/ole32/obj_propertystorage.h create mode 100644 include/ole32/obj_queryassociations.h create mode 100644 include/ole32/obj_serviceprovider.h create mode 100644 include/ole32/obj_shellbrowser.h create mode 100644 include/ole32/obj_shellextinit.h create mode 100644 include/ole32/obj_shellfolder.h create mode 100644 include/ole32/obj_shelllink.h create mode 100644 include/ole32/obj_shellview.h create mode 100644 include/ole32/obj_storage.h create mode 100644 include/ole32/obj_webbrowser.h create mode 100644 include/ole32/objbase.h create mode 100644 include/ole32/ole32.h create mode 100644 include/ole32/olectl.h create mode 100644 include/ole32/rpc.h create mode 100644 include/ole32/rpcdce.h create mode 100644 include/ole32/rpcdcep.h create mode 100644 include/ole32/unknwn.h create mode 100644 include/ole32/winerror.h create mode 100644 include/ole32/wtypes.h create mode 100644 include/pe.h create mode 100644 include/reactos/.cvsignore create mode 100644 include/reactos/config.h create mode 100644 include/reactos/resource.h create mode 100644 include/reactos/version.h create mode 100644 include/services/services.h create mode 100644 include/services/services.idl create mode 100644 include/snmp.h create mode 100644 include/sockets.h create mode 100644 include/structs.h create mode 100644 include/tchar.h create mode 100644 include/unicode.h create mode 100644 include/user32/callback.h create mode 100644 include/user32/wininternal.h create mode 100644 include/win32k/bitmaps.h create mode 100644 include/win32k/brush.h create mode 100644 include/win32k/cliprgn.h create mode 100644 include/win32k/color.h create mode 100644 include/win32k/coord.h create mode 100644 include/win32k/dc.h create mode 100644 include/win32k/debug.h create mode 100644 include/win32k/debug1.h create mode 100644 include/win32k/driver.h create mode 100644 include/win32k/fillshap.h create mode 100644 include/win32k/float.h create mode 100644 include/win32k/gdiobj.h create mode 100644 include/win32k/icm.h create mode 100644 include/win32k/kapi.h create mode 100644 include/win32k/line.h create mode 100644 include/win32k/math.h create mode 100644 include/win32k/metafile.h create mode 100644 include/win32k/misc.h create mode 100644 include/win32k/ntuser.h create mode 100644 include/win32k/paint.h create mode 100644 include/win32k/path.h create mode 100644 include/win32k/pen.h create mode 100644 include/win32k/print.h create mode 100644 include/win32k/region.h create mode 100644 include/win32k/text.h create mode 100644 include/win32k/userobj.h create mode 100644 include/win32k/win32k.h create mode 100644 include/win32k/wingl.h create mode 100644 include/windows.h create mode 100644 include/wine/config.h create mode 100644 include/wine/debugtools.h create mode 100644 include/wine/wineros.h create mode 100644 include/winsock2.h create mode 100644 include/ws2spi.h create mode 100644 include/wsahelp.h create mode 100644 install-system.sh create mode 100644 install.bat create mode 100644 install.sh create mode 100644 installwine.bat create mode 100644 lib/advapi32/.cvsignore create mode 100644 lib/advapi32/advapi32.def create mode 100644 lib/advapi32/advapi32.edf create mode 100644 lib/advapi32/advapi32.rc create mode 100644 lib/advapi32/makefile create mode 100644 lib/advapi32/misc/dllmain.c create mode 100644 lib/advapi32/misc/shutdown.c create mode 100644 lib/advapi32/misc/sysfunc.c create mode 100644 lib/advapi32/reg/reg.c create mode 100644 lib/advapi32/sec/ac.c create mode 100644 lib/advapi32/sec/lsa.c create mode 100644 lib/advapi32/sec/misc.c create mode 100644 lib/advapi32/sec/sec.c create mode 100644 lib/advapi32/sec/sid.c create mode 100644 lib/advapi32/service/scm.c create mode 100644 lib/advapi32/service/sctrl.c create mode 100644 lib/advapi32/service/undoc.c create mode 100644 lib/advapi32/token/privilege.c create mode 100644 lib/advapi32/token/token.c create mode 100644 lib/crtdll/.cvsignore create mode 100644 lib/crtdll/assert/.cvsignore create mode 100644 lib/crtdll/assert/assert.c create mode 100644 lib/crtdll/conio/.cvsignore create mode 100644 lib/crtdll/conio/cgets.c create mode 100644 lib/crtdll/conio/cprintf.c create mode 100644 lib/crtdll/conio/cputs.c create mode 100644 lib/crtdll/conio/cscanf.c create mode 100644 lib/crtdll/conio/getch.c create mode 100644 lib/crtdll/conio/getche.c create mode 100644 lib/crtdll/conio/kbhit.c create mode 100644 lib/crtdll/conio/putch.c create mode 100644 lib/crtdll/conio/ungetch.c create mode 100644 lib/crtdll/crtdll.def create mode 100644 lib/crtdll/crtdll.rc create mode 100644 lib/crtdll/ctype/.cvsignore create mode 100644 lib/crtdll/ctype/isalnum.c create mode 100644 lib/crtdll/ctype/isalpha.c create mode 100644 lib/crtdll/ctype/isascii.c create mode 100644 lib/crtdll/ctype/iscntrl.c create mode 100644 lib/crtdll/ctype/iscsym.c create mode 100644 lib/crtdll/ctype/isctype.c create mode 100644 lib/crtdll/ctype/isdigit.c create mode 100644 lib/crtdll/ctype/isgraph.c create mode 100644 lib/crtdll/ctype/islower.c create mode 100644 lib/crtdll/ctype/isprint.c create mode 100644 lib/crtdll/ctype/ispunct.c create mode 100644 lib/crtdll/ctype/isspace.c create mode 100644 lib/crtdll/ctype/isupper.c create mode 100644 lib/crtdll/ctype/isxdigit.c create mode 100644 lib/crtdll/ctype/toascii.c create mode 100644 lib/crtdll/ctype/tolower.c create mode 100644 lib/crtdll/ctype/toupper.c create mode 100644 lib/crtdll/direct/.cvsignore create mode 100644 lib/crtdll/direct/chdir.c create mode 100644 lib/crtdll/direct/chdrive.c create mode 100644 lib/crtdll/direct/getcwd.c create mode 100644 lib/crtdll/direct/getdcwd.c create mode 100644 lib/crtdll/direct/getdfree.c create mode 100644 lib/crtdll/direct/getdrive.c create mode 100644 lib/crtdll/direct/mkdir.c create mode 100644 lib/crtdll/direct/rmdir.c create mode 100644 lib/crtdll/dirent/.cvsignore create mode 100644 lib/crtdll/dirent/dirent.c create mode 100644 lib/crtdll/except/.cvsignore create mode 100644 lib/crtdll/except/abnorter.c create mode 100644 lib/crtdll/except/exhand2.c create mode 100644 lib/crtdll/except/matherr.c create mode 100644 lib/crtdll/except/unwind.c create mode 100644 lib/crtdll/float/.cvsignore create mode 100644 lib/crtdll/float/chgsign.c create mode 100644 lib/crtdll/float/clearfp.c create mode 100644 lib/crtdll/float/cntrlfp.c create mode 100644 lib/crtdll/float/copysign.c create mode 100644 lib/crtdll/float/fpclass.c create mode 100644 lib/crtdll/float/fpreset.c create mode 100644 lib/crtdll/float/isnan.c create mode 100644 lib/crtdll/float/logb.c create mode 100644 lib/crtdll/float/nafter.c create mode 100644 lib/crtdll/float/nextaf.c create mode 100644 lib/crtdll/float/scalb.c create mode 100644 lib/crtdll/float/statfp.c create mode 100644 lib/crtdll/io/.cvsignore create mode 100644 lib/crtdll/io/access.c create mode 100644 lib/crtdll/io/chmod.c create mode 100644 lib/crtdll/io/chsize.c create mode 100644 lib/crtdll/io/close.c create mode 100644 lib/crtdll/io/commit.c create mode 100644 lib/crtdll/io/create.c create mode 100644 lib/crtdll/io/dup.c create mode 100644 lib/crtdll/io/dup2.c create mode 100644 lib/crtdll/io/eof.c create mode 100644 lib/crtdll/io/filelen.c create mode 100644 lib/crtdll/io/find.c create mode 100644 lib/crtdll/io/fmode.c create mode 100644 lib/crtdll/io/isatty.c create mode 100644 lib/crtdll/io/locking.c create mode 100644 lib/crtdll/io/lseek.c create mode 100644 lib/crtdll/io/mktemp.c create mode 100644 lib/crtdll/io/open.c create mode 100644 lib/crtdll/io/pipe.c create mode 100644 lib/crtdll/io/read.c create mode 100644 lib/crtdll/io/setmode.c create mode 100644 lib/crtdll/io/sopen.c create mode 100644 lib/crtdll/io/tell.c create mode 100644 lib/crtdll/io/umask.c create mode 100644 lib/crtdll/io/unlink.c create mode 100644 lib/crtdll/io/utime.c create mode 100644 lib/crtdll/io/write.c create mode 100644 lib/crtdll/libc/.cvsignore create mode 100644 lib/crtdll/libc/atexit.h create mode 100644 lib/crtdll/libc/file.h create mode 100644 lib/crtdll/locale/.cvsignore create mode 100644 lib/crtdll/locale/locale.c create mode 100644 lib/crtdll/makefile create mode 100644 lib/crtdll/malloc/.cvsignore create mode 100644 lib/crtdll/malloc/expand.c create mode 100644 lib/crtdll/malloc/heap.c create mode 100644 lib/crtdll/math/.cvsignore create mode 100644 lib/crtdll/math/acos.c create mode 100644 lib/crtdll/math/acosh.c create mode 100644 lib/crtdll/math/asin.c create mode 100644 lib/crtdll/math/asinh.c create mode 100644 lib/crtdll/math/atan.c create mode 100644 lib/crtdll/math/atan2.c create mode 100644 lib/crtdll/math/atanh.c create mode 100644 lib/crtdll/math/cabs.c create mode 100644 lib/crtdll/math/ceil.c create mode 100644 lib/crtdll/math/cos.c create mode 100644 lib/crtdll/math/cosh.c create mode 100644 lib/crtdll/math/exp.c create mode 100644 lib/crtdll/math/fabs.c create mode 100644 lib/crtdll/math/floor.c create mode 100644 lib/crtdll/math/fmod.c create mode 100644 lib/crtdll/math/frexp.c create mode 100644 lib/crtdll/math/ftol.c create mode 100644 lib/crtdll/math/huge_val.c create mode 100644 lib/crtdll/math/hypot.c create mode 100644 lib/crtdll/math/j0_y0.c create mode 100644 lib/crtdll/math/j1_y1.c create mode 100644 lib/crtdll/math/jn_yn.c create mode 100644 lib/crtdll/math/ldexp.c create mode 100644 lib/crtdll/math/log.c create mode 100644 lib/crtdll/math/log10.c create mode 100644 lib/crtdll/math/modf.c create mode 100644 lib/crtdll/math/pow.c create mode 100644 lib/crtdll/math/sin.c create mode 100644 lib/crtdll/math/sinh.c create mode 100644 lib/crtdll/math/sqrt.c create mode 100644 lib/crtdll/math/stubs.c create mode 100644 lib/crtdll/math/tan.c create mode 100644 lib/crtdll/math/tanh.c create mode 100644 lib/crtdll/mbstring/.cvsignore create mode 100644 lib/crtdll/mbstring/hanzen.c create mode 100644 lib/crtdll/mbstring/ischira.c create mode 100644 lib/crtdll/mbstring/iskana.c create mode 100644 lib/crtdll/mbstring/iskmoji.c create mode 100644 lib/crtdll/mbstring/iskpun.c create mode 100644 lib/crtdll/mbstring/islead.c create mode 100644 lib/crtdll/mbstring/islwr.c create mode 100644 lib/crtdll/mbstring/ismbal.c create mode 100644 lib/crtdll/mbstring/ismbaln.c create mode 100644 lib/crtdll/mbstring/ismbc.c create mode 100644 lib/crtdll/mbstring/ismbgra.c create mode 100644 lib/crtdll/mbstring/ismbkaln.c create mode 100644 lib/crtdll/mbstring/ismblead.c create mode 100644 lib/crtdll/mbstring/ismbpri.c create mode 100644 lib/crtdll/mbstring/ismbpun.c create mode 100644 lib/crtdll/mbstring/ismbtrl.c create mode 100644 lib/crtdll/mbstring/isuppr.c create mode 100644 lib/crtdll/mbstring/jistojms.c create mode 100644 lib/crtdll/mbstring/jmstojis.c create mode 100644 lib/crtdll/mbstring/mbbtype.c create mode 100644 lib/crtdll/mbstring/mbccpy.c create mode 100644 lib/crtdll/mbstring/mbclen.c create mode 100644 lib/crtdll/mbstring/mbscat.c create mode 100644 lib/crtdll/mbstring/mbschr.c create mode 100644 lib/crtdll/mbstring/mbscmp.c create mode 100644 lib/crtdll/mbstring/mbscoll.c create mode 100644 lib/crtdll/mbstring/mbscpy.c create mode 100644 lib/crtdll/mbstring/mbscspn.c create mode 100644 lib/crtdll/mbstring/mbsdec.c create mode 100644 lib/crtdll/mbstring/mbsdup.c create mode 100644 lib/crtdll/mbstring/mbsicmp.c create mode 100644 lib/crtdll/mbstring/mbsicoll.c create mode 100644 lib/crtdll/mbstring/mbsinc.c create mode 100644 lib/crtdll/mbstring/mbslen.c create mode 100644 lib/crtdll/mbstring/mbslwr.c create mode 100644 lib/crtdll/mbstring/mbsncat.c create mode 100644 lib/crtdll/mbstring/mbsnccnt.c create mode 100644 lib/crtdll/mbstring/mbsncmp.c create mode 100644 lib/crtdll/mbstring/mbsncoll.c create mode 100644 lib/crtdll/mbstring/mbsncpy.c create mode 100644 lib/crtdll/mbstring/mbsnextc.c create mode 100644 lib/crtdll/mbstring/mbsnicmp.c create mode 100644 lib/crtdll/mbstring/mbsnicoll.c create mode 100644 lib/crtdll/mbstring/mbsninc.c create mode 100644 lib/crtdll/mbstring/mbsnset.c create mode 100644 lib/crtdll/mbstring/mbspbrk.c create mode 100644 lib/crtdll/mbstring/mbsrchr.c create mode 100644 lib/crtdll/mbstring/mbsrev.c create mode 100644 lib/crtdll/mbstring/mbsset.c create mode 100644 lib/crtdll/mbstring/mbsspn.c create mode 100644 lib/crtdll/mbstring/mbsspnp.c create mode 100644 lib/crtdll/mbstring/mbsstr.c create mode 100644 lib/crtdll/mbstring/mbstok.c create mode 100644 lib/crtdll/mbstring/mbstrlen.c create mode 100644 lib/crtdll/mbstring/mbsupr.c create mode 100644 lib/crtdll/misc/.cvsignore create mode 100644 lib/crtdll/misc/CRT_noglob.c create mode 100644 lib/crtdll/misc/CRTfmode.c create mode 100644 lib/crtdll/misc/CRTglob.c create mode 100644 lib/crtdll/misc/CRTinit.c create mode 100644 lib/crtdll/misc/GetArgs.c create mode 100644 lib/crtdll/misc/amsg.c create mode 100644 lib/crtdll/misc/crt1.c create mode 100644 lib/crtdll/misc/dllcrt1.c create mode 100644 lib/crtdll/misc/dllmain.c create mode 100644 lib/crtdll/misc/gccmain.c create mode 100644 lib/crtdll/misc/init.c create mode 100644 lib/crtdll/misc/initter.c create mode 100644 lib/crtdll/misc/initterm.c create mode 100644 lib/crtdll/misc/main.c create mode 100644 lib/crtdll/misc/purecall.c create mode 100644 lib/crtdll/misc/setnew.c create mode 100644 lib/crtdll/misc/sleep.c create mode 100644 lib/crtdll/misc/unwind.c create mode 100644 lib/crtdll/process/.cvsignore create mode 100644 lib/crtdll/process/_cwait.c create mode 100644 lib/crtdll/process/_system.c create mode 100644 lib/crtdll/process/dll.c create mode 100644 lib/crtdll/process/execl.c create mode 100644 lib/crtdll/process/execle.c create mode 100644 lib/crtdll/process/execlp.c create mode 100644 lib/crtdll/process/execlpe.c create mode 100644 lib/crtdll/process/execv.c create mode 100644 lib/crtdll/process/execve.c create mode 100644 lib/crtdll/process/execvp.c create mode 100644 lib/crtdll/process/execvpe.c create mode 100644 lib/crtdll/process/procid.c create mode 100644 lib/crtdll/process/spawnl.c create mode 100644 lib/crtdll/process/spawnle.c create mode 100644 lib/crtdll/process/spawnlp.c create mode 100644 lib/crtdll/process/spawnlpe.c create mode 100644 lib/crtdll/process/spawnv.c create mode 100644 lib/crtdll/process/spawnve.c create mode 100644 lib/crtdll/process/spawnvp.c create mode 100644 lib/crtdll/process/spawnvpe.c create mode 100644 lib/crtdll/process/thread.c create mode 100644 lib/crtdll/process/threadid.c create mode 100644 lib/crtdll/quad/.cvsignore create mode 100644 lib/crtdll/quad/divdi3.c create mode 100644 lib/crtdll/quad/moddi3.c create mode 100644 lib/crtdll/quad/qdivrem.c create mode 100644 lib/crtdll/quad/udivdi3.c create mode 100644 lib/crtdll/quad/umoddi3.c create mode 100644 lib/crtdll/search/.cvsignore create mode 100644 lib/crtdll/search/lfind.c create mode 100644 lib/crtdll/search/lsearch.c create mode 100644 lib/crtdll/setjmp/.cvsignore create mode 100644 lib/crtdll/setjmp/setjmp.c create mode 100644 lib/crtdll/signal/.cvsignore create mode 100644 lib/crtdll/signal/signal.c create mode 100644 lib/crtdll/signal/xcptfil.c create mode 100644 lib/crtdll/signal/xcptinfo.c create mode 100644 lib/crtdll/stdio/.cvsignore create mode 100644 lib/crtdll/stdio/FILE.DOC create mode 100644 lib/crtdll/stdio/allocfil.c create mode 100644 lib/crtdll/stdio/clearerr.c create mode 100644 lib/crtdll/stdio/doscan.c create mode 100644 lib/crtdll/stdio/fclose.c create mode 100644 lib/crtdll/stdio/fdopen.c create mode 100644 lib/crtdll/stdio/feof.c create mode 100644 lib/crtdll/stdio/ferror.c create mode 100644 lib/crtdll/stdio/fflush.c create mode 100644 lib/crtdll/stdio/fgetc.c create mode 100644 lib/crtdll/stdio/fgetchar.c create mode 100644 lib/crtdll/stdio/fgetpos.c create mode 100644 lib/crtdll/stdio/fgets.c create mode 100644 lib/crtdll/stdio/filbuf.c create mode 100644 lib/crtdll/stdio/fileno.c create mode 100644 lib/crtdll/stdio/flsbuf.c create mode 100644 lib/crtdll/stdio/fopen.c create mode 100644 lib/crtdll/stdio/fprintf.c create mode 100644 lib/crtdll/stdio/fputc.c create mode 100644 lib/crtdll/stdio/fputchar.c create mode 100644 lib/crtdll/stdio/fputs.c create mode 100644 lib/crtdll/stdio/fread.c create mode 100644 lib/crtdll/stdio/freopen.c create mode 100644 lib/crtdll/stdio/frlist.c create mode 100644 lib/crtdll/stdio/fscanf.c create mode 100644 lib/crtdll/stdio/fseek.c create mode 100644 lib/crtdll/stdio/fsetpos.c create mode 100644 lib/crtdll/stdio/fsopen.c create mode 100644 lib/crtdll/stdio/ftell.c create mode 100644 lib/crtdll/stdio/fwalk.c create mode 100644 lib/crtdll/stdio/fwrite.c create mode 100644 lib/crtdll/stdio/getc.c create mode 100644 lib/crtdll/stdio/getchar.c create mode 100644 lib/crtdll/stdio/getenv.c create mode 100644 lib/crtdll/stdio/gets.c create mode 100644 lib/crtdll/stdio/getw.c create mode 100644 lib/crtdll/stdio/perror.c create mode 100644 lib/crtdll/stdio/popen.c create mode 100644 lib/crtdll/stdio/printf.c create mode 100644 lib/crtdll/stdio/putc.c create mode 100644 lib/crtdll/stdio/putchar.c create mode 100644 lib/crtdll/stdio/puts.c create mode 100644 lib/crtdll/stdio/putw.c create mode 100644 lib/crtdll/stdio/remove.c create mode 100644 lib/crtdll/stdio/rename.c create mode 100644 lib/crtdll/stdio/rewind.c create mode 100644 lib/crtdll/stdio/rmtmp.c create mode 100644 lib/crtdll/stdio/scanf.c create mode 100644 lib/crtdll/stdio/setbuf.c create mode 100644 lib/crtdll/stdio/setbuffe.c create mode 100644 lib/crtdll/stdio/setlineb.c create mode 100644 lib/crtdll/stdio/setvbuf.c create mode 100644 lib/crtdll/stdio/sprintf.c create mode 100644 lib/crtdll/stdio/sscanf.c create mode 100644 lib/crtdll/stdio/stdhnd.c create mode 100644 lib/crtdll/stdio/stdiohk.c create mode 100644 lib/crtdll/stdio/tempnam.c create mode 100644 lib/crtdll/stdio/tmpfile.c create mode 100644 lib/crtdll/stdio/tmpnam.c create mode 100644 lib/crtdll/stdio/ungetc.c create mode 100644 lib/crtdll/stdio/vfprintf.c create mode 100644 lib/crtdll/stdio/vfscanf.c create mode 100644 lib/crtdll/stdio/vfwprint.c create mode 100644 lib/crtdll/stdio/vprintf.c create mode 100644 lib/crtdll/stdio/vscanf.c create mode 100644 lib/crtdll/stdio/vsprintf.c create mode 100644 lib/crtdll/stdio/vsscanf.c create mode 100644 lib/crtdll/stdlib/.cvsignore create mode 100644 lib/crtdll/stdlib/_exit.c create mode 100644 lib/crtdll/stdlib/abort.c create mode 100644 lib/crtdll/stdlib/abs.c create mode 100644 lib/crtdll/stdlib/atexit.c create mode 100644 lib/crtdll/stdlib/atof.c create mode 100644 lib/crtdll/stdlib/atoi.c create mode 100644 lib/crtdll/stdlib/atol.c create mode 100644 lib/crtdll/stdlib/atold.c create mode 100644 lib/crtdll/stdlib/bsearch.c create mode 100644 lib/crtdll/stdlib/calloc.c create mode 100644 lib/crtdll/stdlib/div.c create mode 100644 lib/crtdll/stdlib/ecvt.c create mode 100644 lib/crtdll/stdlib/ecvtbuf.c create mode 100644 lib/crtdll/stdlib/errno.c create mode 100644 lib/crtdll/stdlib/fcvt.c create mode 100644 lib/crtdll/stdlib/fcvtbuf.c create mode 100644 lib/crtdll/stdlib/fullpath.c create mode 100644 lib/crtdll/stdlib/gcvt.c create mode 100644 lib/crtdll/stdlib/itoa.c create mode 100644 lib/crtdll/stdlib/itow.c create mode 100644 lib/crtdll/stdlib/labs.c create mode 100644 lib/crtdll/stdlib/ldiv.c create mode 100644 lib/crtdll/stdlib/llabs.c create mode 100644 lib/crtdll/stdlib/lldiv.c create mode 100644 lib/crtdll/stdlib/makepath.c create mode 100644 lib/crtdll/stdlib/malloc.c create mode 100644 lib/crtdll/stdlib/mbstow.c create mode 100644 lib/crtdll/stdlib/mbstowcs.c create mode 100644 lib/crtdll/stdlib/obsol.c create mode 100644 lib/crtdll/stdlib/putenv.c create mode 100644 lib/crtdll/stdlib/qsort.c create mode 100644 lib/crtdll/stdlib/rand.c create mode 100644 lib/crtdll/stdlib/rot.c create mode 100644 lib/crtdll/stdlib/senv.c create mode 100644 lib/crtdll/stdlib/splitp.c create mode 100644 lib/crtdll/stdlib/strtod.c create mode 100644 lib/crtdll/stdlib/strtol.c create mode 100644 lib/crtdll/stdlib/strtold.c create mode 100644 lib/crtdll/stdlib/strtoll.c create mode 100644 lib/crtdll/stdlib/strtoul.c create mode 100644 lib/crtdll/stdlib/strtoull.c create mode 100644 lib/crtdll/stdlib/swab.c create mode 100644 lib/crtdll/stdlib/wcstom.c create mode 100644 lib/crtdll/stdlib/wcstomb.c create mode 100644 lib/crtdll/stdlib/wcstombs.c create mode 100644 lib/crtdll/string/.cvsignore create mode 100644 lib/crtdll/string/memccpy.c create mode 100644 lib/crtdll/string/memchr.c create mode 100644 lib/crtdll/string/memcmp.c create mode 100644 lib/crtdll/string/memcpy.c create mode 100644 lib/crtdll/string/memcpy.s create mode 100644 lib/crtdll/string/memicmp.c create mode 100644 lib/crtdll/string/memmove.c create mode 100644 lib/crtdll/string/memmove.s create mode 100644 lib/crtdll/string/memset.c create mode 100644 lib/crtdll/string/memset.s create mode 100644 lib/crtdll/string/str_old.c create mode 100644 lib/crtdll/string/strcat.c create mode 100644 lib/crtdll/string/strchr.c create mode 100644 lib/crtdll/string/strcmp.c create mode 100644 lib/crtdll/string/strcoll.c create mode 100644 lib/crtdll/string/strcpy.c create mode 100644 lib/crtdll/string/strcspn.c create mode 100644 lib/crtdll/string/strdup.c create mode 100644 lib/crtdll/string/strerror.c create mode 100644 lib/crtdll/string/stricmp.c create mode 100644 lib/crtdll/string/strlen.c create mode 100644 lib/crtdll/string/strlwr.c create mode 100644 lib/crtdll/string/strncat.c create mode 100644 lib/crtdll/string/strncmp.c create mode 100644 lib/crtdll/string/strncpy.c create mode 100644 lib/crtdll/string/strnicmp.c create mode 100644 lib/crtdll/string/strnlen.c create mode 100644 lib/crtdll/string/strpbrk.c create mode 100644 lib/crtdll/string/strrchr.c create mode 100644 lib/crtdll/string/strrev.c create mode 100644 lib/crtdll/string/strset.c create mode 100644 lib/crtdll/string/strspn.c create mode 100644 lib/crtdll/string/strspnp.c create mode 100644 lib/crtdll/string/strstr.c create mode 100644 lib/crtdll/string/strtok.c create mode 100644 lib/crtdll/string/strtoul.c create mode 100644 lib/crtdll/string/strupr.c create mode 100644 lib/crtdll/string/strxfrm.c create mode 100644 lib/crtdll/sys_stat/.cvsignore create mode 100644 lib/crtdll/sys_stat/fstat.c create mode 100644 lib/crtdll/sys_stat/ftime.c create mode 100644 lib/crtdll/sys_stat/futime.c create mode 100644 lib/crtdll/sys_stat/stat.c create mode 100644 lib/crtdll/sys_stat/systime.c create mode 100644 lib/crtdll/tchar/.cvsignore create mode 100644 lib/crtdll/tchar/strdec.c create mode 100644 lib/crtdll/tchar/strinc.c create mode 100644 lib/crtdll/tchar/strncnt.c create mode 100644 lib/crtdll/tchar/strnextc.c create mode 100644 lib/crtdll/tchar/strninc.c create mode 100644 lib/crtdll/tchar/strspnp.c create mode 100644 lib/crtdll/time/.cvsignore create mode 100644 lib/crtdll/time/clock.c create mode 100644 lib/crtdll/time/ctime.c create mode 100644 lib/crtdll/time/difftime.c create mode 100644 lib/crtdll/time/posixrul.h create mode 100644 lib/crtdll/time/strdate.c create mode 100644 lib/crtdll/time/strftime.c create mode 100644 lib/crtdll/time/strtime.c create mode 100644 lib/crtdll/time/time.c create mode 100644 lib/crtdll/time/tzfile.h create mode 100644 lib/crtdll/wchar/.cvsignore create mode 100644 lib/crtdll/wchar/wcscat.c create mode 100644 lib/crtdll/wchar/wcschr.c create mode 100644 lib/crtdll/wchar/wcscmp.c create mode 100644 lib/crtdll/wchar/wcscoll.c create mode 100644 lib/crtdll/wchar/wcscpy.c create mode 100644 lib/crtdll/wchar/wcscspn.c create mode 100644 lib/crtdll/wchar/wcsdup.c create mode 100644 lib/crtdll/wchar/wcsftime.c create mode 100644 lib/crtdll/wchar/wcsicmp.c create mode 100644 lib/crtdll/wchar/wcslen.c create mode 100644 lib/crtdll/wchar/wcslwr.c create mode 100644 lib/crtdll/wchar/wcsncat.c create mode 100644 lib/crtdll/wchar/wcsncmp.c create mode 100644 lib/crtdll/wchar/wcsncpy.c create mode 100644 lib/crtdll/wchar/wcsnicmp.c create mode 100644 lib/crtdll/wchar/wcsnlen.c create mode 100644 lib/crtdll/wchar/wcspbrk.c create mode 100644 lib/crtdll/wchar/wcsrchr.c create mode 100644 lib/crtdll/wchar/wcsrev.c create mode 100644 lib/crtdll/wchar/wcsset.c create mode 100644 lib/crtdll/wchar/wcsspn.c create mode 100644 lib/crtdll/wchar/wcsstr.c create mode 100644 lib/crtdll/wchar/wcstod.c create mode 100644 lib/crtdll/wchar/wcstok.c create mode 100644 lib/crtdll/wchar/wcstol.c create mode 100644 lib/crtdll/wchar/wcstombs.c create mode 100644 lib/crtdll/wchar/wcsupr.c create mode 100644 lib/crtdll/wchar/wcsxfrm.c create mode 100644 lib/crtdll/wchar/wtoi.c create mode 100644 lib/fmifs/.cvsignore create mode 100644 lib/fmifs/chkdsk.c create mode 100644 lib/fmifs/compress.c create mode 100644 lib/fmifs/diskcopy.c create mode 100644 lib/fmifs/dllmain.c create mode 100644 lib/fmifs/extend.c create mode 100644 lib/fmifs/fmifs.def create mode 100644 lib/fmifs/fmifs.edf create mode 100644 lib/fmifs/fmifs.rc create mode 100644 lib/fmifs/format.c create mode 100644 lib/fmifs/init.c create mode 100644 lib/fmifs/label.c create mode 100644 lib/fmifs/makefile create mode 100644 lib/fmifs/media.c create mode 100644 lib/gdi32/.cvsignore create mode 100644 lib/gdi32/gdi32.def create mode 100644 lib/gdi32/gdi32.edf create mode 100644 lib/gdi32/gdi32.rc create mode 100644 lib/gdi32/gdi32_specs create mode 100644 lib/gdi32/main/dllmain.c create mode 100644 lib/gdi32/makefile create mode 100644 lib/gdi32/misc/.cvsignore create mode 100644 lib/gdi32/misc/stubs.c create mode 100644 lib/gdi32/misc/stubsa.c create mode 100644 lib/gdi32/misc/stubsw.c create mode 100644 lib/gdi32/objects/bitblt.c create mode 100644 lib/gdi32/objects/brush.c create mode 100644 lib/gdi32/objects/dc.c create mode 100644 lib/gdi32/objects/line.c create mode 100644 lib/gdi32/objects/pen.c create mode 100644 lib/gdi32/objects/region.c create mode 100644 lib/gdi32/objects/text.c create mode 100644 lib/iphlpapi/.cvsignore create mode 100644 lib/iphlpapi/debug.h create mode 100644 lib/iphlpapi/iphlpapi.c create mode 100644 lib/iphlpapi/iphlpapi.def create mode 100644 lib/iphlpapi/iphlpapi.edf create mode 100644 lib/iphlpapi/iphlpapi.rc create mode 100644 lib/iphlpapi/makefile create mode 100644 lib/iprtprio/.cvsignore create mode 100644 lib/iprtprio/iprtprio.c create mode 100644 lib/iprtprio/iprtprio.def create mode 100644 lib/iprtprio/iprtprio.edf create mode 100644 lib/iprtprio/iprtprio.rc create mode 100644 lib/iprtprio/makefile create mode 100644 lib/kernel32/.cvsignore create mode 100644 lib/kernel32/except/.cvsignore create mode 100644 lib/kernel32/except/except.c create mode 100644 lib/kernel32/file/.cvsignore create mode 100644 lib/kernel32/file/backup.c create mode 100644 lib/kernel32/file/cnotify.c create mode 100644 lib/kernel32/file/copy.c create mode 100644 lib/kernel32/file/create.c create mode 100644 lib/kernel32/file/curdir.c create mode 100644 lib/kernel32/file/delete.c create mode 100644 lib/kernel32/file/deviceio.c create mode 100644 lib/kernel32/file/dir.c create mode 100644 lib/kernel32/file/dosdev.c create mode 100644 lib/kernel32/file/file.c create mode 100644 lib/kernel32/file/find.c create mode 100644 lib/kernel32/file/iocompl.c create mode 100644 lib/kernel32/file/lfile.c create mode 100644 lib/kernel32/file/lock.c create mode 100644 lib/kernel32/file/mailslot.c create mode 100644 lib/kernel32/file/move.c create mode 100644 lib/kernel32/file/npipe.c create mode 100644 lib/kernel32/file/pipe.c create mode 100644 lib/kernel32/file/rw.c create mode 100644 lib/kernel32/file/tape.c create mode 100644 lib/kernel32/file/volume.c create mode 100644 lib/kernel32/kernel32.def create mode 100644 lib/kernel32/kernel32.edf create mode 100644 lib/kernel32/kernel32.rc create mode 100644 lib/kernel32/makefile create mode 100644 lib/kernel32/mem/.cvsignore create mode 100644 lib/kernel32/mem/global.c create mode 100644 lib/kernel32/mem/heap.c create mode 100644 lib/kernel32/mem/isbad.c create mode 100644 lib/kernel32/mem/local.c create mode 100644 lib/kernel32/mem/procmem.c create mode 100644 lib/kernel32/mem/section.c create mode 100644 lib/kernel32/mem/virtual.c create mode 100644 lib/kernel32/misc/.cvsignore create mode 100644 lib/kernel32/misc/atom.c create mode 100644 lib/kernel32/misc/comm.c create mode 100644 lib/kernel32/misc/console.c create mode 100644 lib/kernel32/misc/debug.c create mode 100644 lib/kernel32/misc/dllmain.c create mode 100644 lib/kernel32/misc/env.c create mode 100644 lib/kernel32/misc/error.c create mode 100644 lib/kernel32/misc/handle.c create mode 100644 lib/kernel32/misc/ldr.c create mode 100644 lib/kernel32/misc/profile.c create mode 100644 lib/kernel32/misc/res.c create mode 100644 lib/kernel32/misc/stubs.c create mode 100644 lib/kernel32/misc/sysinfo.c create mode 100644 lib/kernel32/misc/time.c create mode 100644 lib/kernel32/nls/.cvsignore create mode 100644 lib/kernel32/nls/LGPL.c create mode 100644 lib/kernel32/nls/afk.nls create mode 100644 lib/kernel32/nls/ara.nls create mode 100644 lib/kernel32/nls/arb.nls create mode 100644 lib/kernel32/nls/are.nls create mode 100644 lib/kernel32/nls/arg.nls create mode 100644 lib/kernel32/nls/ari.nls create mode 100644 lib/kernel32/nls/ark.nls create mode 100644 lib/kernel32/nls/arm.nls create mode 100644 lib/kernel32/nls/aro.nls create mode 100644 lib/kernel32/nls/arq.nls create mode 100644 lib/kernel32/nls/ars.nls create mode 100644 lib/kernel32/nls/art.nls create mode 100644 lib/kernel32/nls/aru.nls create mode 100644 lib/kernel32/nls/bel.nls create mode 100644 lib/kernel32/nls/bgr.nls create mode 100644 lib/kernel32/nls/cat.nls create mode 100644 lib/kernel32/nls/cht.nls create mode 100644 lib/kernel32/nls/codepage.c create mode 100644 lib/kernel32/nls/cpmisc.c create mode 100644 lib/kernel32/nls/cptable.c create mode 100644 lib/kernel32/nls/cze.nls create mode 100644 lib/kernel32/nls/dan.nls create mode 100644 lib/kernel32/nls/dea.nls create mode 100644 lib/kernel32/nls/dec.nls create mode 100644 lib/kernel32/nls/del.nls create mode 100644 lib/kernel32/nls/des.nls create mode 100644 lib/kernel32/nls/deu.nls create mode 100644 lib/kernel32/nls/dnk.nls create mode 100644 lib/kernel32/nls/empty.nls create mode 100644 lib/kernel32/nls/ena.nls create mode 100644 lib/kernel32/nls/enb.nls create mode 100644 lib/kernel32/nls/enc.nls create mode 100644 lib/kernel32/nls/eng.nls create mode 100644 lib/kernel32/nls/enj.nls create mode 100644 lib/kernel32/nls/enl.nls create mode 100644 lib/kernel32/nls/ens.nls create mode 100644 lib/kernel32/nls/ent.nls create mode 100644 lib/kernel32/nls/enu.nls create mode 100644 lib/kernel32/nls/enz.nls create mode 100644 lib/kernel32/nls/esa.nls create mode 100644 lib/kernel32/nls/esb.nls create mode 100644 lib/kernel32/nls/esc.nls create mode 100644 lib/kernel32/nls/esd.nls create mode 100644 lib/kernel32/nls/ese.nls create mode 100644 lib/kernel32/nls/esf.nls create mode 100644 lib/kernel32/nls/esg.nls create mode 100644 lib/kernel32/nls/esh.nls create mode 100644 lib/kernel32/nls/esi.nls create mode 100644 lib/kernel32/nls/esl.nls create mode 100644 lib/kernel32/nls/esm.nls create mode 100644 lib/kernel32/nls/esn.nls create mode 100644 lib/kernel32/nls/eso.nls create mode 100644 lib/kernel32/nls/esp.nls create mode 100644 lib/kernel32/nls/esperanto.nls create mode 100644 lib/kernel32/nls/esr.nls create mode 100644 lib/kernel32/nls/ess.nls create mode 100644 lib/kernel32/nls/est.nls create mode 100644 lib/kernel32/nls/esu.nls create mode 100644 lib/kernel32/nls/esv.nls create mode 100644 lib/kernel32/nls/esy.nls create mode 100644 lib/kernel32/nls/esz.nls create mode 100644 lib/kernel32/nls/euq.nls create mode 100644 lib/kernel32/nls/fin.nls create mode 100644 lib/kernel32/nls/fos.nls create mode 100644 lib/kernel32/nls/fra.nls create mode 100644 lib/kernel32/nls/frb.nls create mode 100644 lib/kernel32/nls/frc.nls create mode 100644 lib/kernel32/nls/frl.nls create mode 100644 lib/kernel32/nls/frs.nls create mode 100644 lib/kernel32/nls/grc.nls create mode 100644 lib/kernel32/nls/hkg.nls create mode 100644 lib/kernel32/nls/hrv.nls create mode 100644 lib/kernel32/nls/hun.nls create mode 100644 lib/kernel32/nls/ind.nls create mode 100644 lib/kernel32/nls/irl.nls create mode 100644 lib/kernel32/nls/isl.nls create mode 100644 lib/kernel32/nls/ita.nls create mode 100644 lib/kernel32/nls/its.nls create mode 100644 lib/kernel32/nls/jpn.nls create mode 100644 lib/kernel32/nls/koj.nls create mode 100644 lib/kernel32/nls/kor.nls create mode 100644 lib/kernel32/nls/lcAFK.c create mode 100644 lib/kernel32/nls/lcBEL.c create mode 100644 lib/kernel32/nls/lcBGR.c create mode 100644 lib/kernel32/nls/lcCAT.c create mode 100644 lib/kernel32/nls/lcCSY.c create mode 100644 lib/kernel32/nls/lcDAN.c create mode 100644 lib/kernel32/nls/lcDEA.c create mode 100644 lib/kernel32/nls/lcDEC.c create mode 100644 lib/kernel32/nls/lcDEL.c create mode 100644 lib/kernel32/nls/lcDES.c create mode 100644 lib/kernel32/nls/lcDEU.c create mode 100644 lib/kernel32/nls/lcELL.c create mode 100644 lib/kernel32/nls/lcENA.c create mode 100644 lib/kernel32/nls/lcENB.c create mode 100644 lib/kernel32/nls/lcENC.c create mode 100644 lib/kernel32/nls/lcENG.c create mode 100644 lib/kernel32/nls/lcENI.c create mode 100644 lib/kernel32/nls/lcENJ.c create mode 100644 lib/kernel32/nls/lcENL.c create mode 100644 lib/kernel32/nls/lcENS.c create mode 100644 lib/kernel32/nls/lcENT.c create mode 100644 lib/kernel32/nls/lcENU.c create mode 100644 lib/kernel32/nls/lcENZ.c create mode 100644 lib/kernel32/nls/lcESA.c create mode 100644 lib/kernel32/nls/lcESB.c create mode 100644 lib/kernel32/nls/lcESC.c create mode 100644 lib/kernel32/nls/lcESD.c create mode 100644 lib/kernel32/nls/lcESE.c create mode 100644 lib/kernel32/nls/lcESF.c create mode 100644 lib/kernel32/nls/lcESG.c create mode 100644 lib/kernel32/nls/lcESH.c create mode 100644 lib/kernel32/nls/lcESI.c create mode 100644 lib/kernel32/nls/lcESL.c create mode 100644 lib/kernel32/nls/lcESM.c create mode 100644 lib/kernel32/nls/lcESN.c create mode 100644 lib/kernel32/nls/lcESO.c create mode 100644 lib/kernel32/nls/lcESP.c create mode 100644 lib/kernel32/nls/lcESR.c create mode 100644 lib/kernel32/nls/lcESS.c create mode 100644 lib/kernel32/nls/lcESU.c create mode 100644 lib/kernel32/nls/lcESV.c create mode 100644 lib/kernel32/nls/lcESY.c create mode 100644 lib/kernel32/nls/lcESZ.c create mode 100644 lib/kernel32/nls/lcETI.c create mode 100644 lib/kernel32/nls/lcEUQ.c create mode 100644 lib/kernel32/nls/lcFIN.c create mode 100644 lib/kernel32/nls/lcFOS.c create mode 100644 lib/kernel32/nls/lcFRA.c create mode 100644 lib/kernel32/nls/lcFRB.c create mode 100644 lib/kernel32/nls/lcFRC.c create mode 100644 lib/kernel32/nls/lcFRL.c create mode 100644 lib/kernel32/nls/lcFRS.c create mode 100644 lib/kernel32/nls/lcHRV.c create mode 100644 lib/kernel32/nls/lcHUN.c create mode 100644 lib/kernel32/nls/lcIND.c create mode 100644 lib/kernel32/nls/lcISL.c create mode 100644 lib/kernel32/nls/lcITA.c create mode 100644 lib/kernel32/nls/lcITS.c create mode 100644 lib/kernel32/nls/lcLTH.c create mode 100644 lib/kernel32/nls/lcLVI.c create mode 100644 lib/kernel32/nls/lcNLB.c create mode 100644 lib/kernel32/nls/lcNLD.c create mode 100644 lib/kernel32/nls/lcNON.c create mode 100644 lib/kernel32/nls/lcNOR.c create mode 100644 lib/kernel32/nls/lcPLK.c create mode 100644 lib/kernel32/nls/lcPTB.c create mode 100644 lib/kernel32/nls/lcPTG.c create mode 100644 lib/kernel32/nls/lcROM.c create mode 100644 lib/kernel32/nls/lcRUS.c create mode 100644 lib/kernel32/nls/lcSKY.c create mode 100644 lib/kernel32/nls/lcSLV.c create mode 100644 lib/kernel32/nls/lcSQI.c create mode 100644 lib/kernel32/nls/lcSRB.c create mode 100644 lib/kernel32/nls/lcSRL.c create mode 100644 lib/kernel32/nls/lcSVE.c create mode 100644 lib/kernel32/nls/lcSVF.c create mode 100644 lib/kernel32/nls/lcTRK.c create mode 100644 lib/kernel32/nls/lcUKR.c create mode 100644 lib/kernel32/nls/lctable.c create mode 100644 lib/kernel32/nls/locale.c create mode 100644 lib/kernel32/nls/lth.nls create mode 100644 lib/kernel32/nls/lvi.nls create mode 100644 lib/kernel32/nls/mbtowc.c create mode 100644 lib/kernel32/nls/nlb.nls create mode 100644 lib/kernel32/nls/nld.nls create mode 100644 lib/kernel32/nls/nls.nls create mode 100644 lib/kernel32/nls/non.nls create mode 100644 lib/kernel32/nls/nor.nls create mode 100644 lib/kernel32/nls/ole2nls.c create mode 100644 lib/kernel32/nls/plk.nls create mode 100644 lib/kernel32/nls/prc.nls create mode 100644 lib/kernel32/nls/ptb.nls create mode 100644 lib/kernel32/nls/ptg.nls create mode 100644 lib/kernel32/nls/rom.nls create mode 100644 lib/kernel32/nls/rus.nls create mode 100644 lib/kernel32/nls/sgp.nls create mode 100644 lib/kernel32/nls/sky.nls create mode 100644 lib/kernel32/nls/slv.nls create mode 100644 lib/kernel32/nls/sqi.nls create mode 100644 lib/kernel32/nls/srb.nls create mode 100644 lib/kernel32/nls/srl.nls create mode 100644 lib/kernel32/nls/sve.nls create mode 100644 lib/kernel32/nls/svf.nls create mode 100644 lib/kernel32/nls/tha.nls create mode 100644 lib/kernel32/nls/trk.nls create mode 100644 lib/kernel32/nls/ukr.nls create mode 100644 lib/kernel32/nls/vie.nls create mode 100644 lib/kernel32/nls/wctomb.c create mode 100644 lib/kernel32/nls/zhh.nls create mode 100644 lib/kernel32/nls/zhi.nls create mode 100644 lib/kernel32/nls/zhs.nls create mode 100644 lib/kernel32/process/.cvsignore create mode 100644 lib/kernel32/process/cmdline.c create mode 100644 lib/kernel32/process/create.c create mode 100644 lib/kernel32/process/proc.c create mode 100644 lib/kernel32/process/session.c create mode 100644 lib/kernel32/string/.cvsignore create mode 100644 lib/kernel32/string/lstring.c create mode 100644 lib/kernel32/synch/.cvsignore create mode 100644 lib/kernel32/synch/critical.c create mode 100644 lib/kernel32/synch/event.c create mode 100644 lib/kernel32/synch/intrlck.c create mode 100644 lib/kernel32/synch/mutex.c create mode 100644 lib/kernel32/synch/sem.c create mode 100644 lib/kernel32/synch/timer.c create mode 100644 lib/kernel32/synch/wait.c create mode 100644 lib/kernel32/thread/.cvsignore create mode 100644 lib/kernel32/thread/fiber.c create mode 100644 lib/kernel32/thread/thread.c create mode 100644 lib/kernel32/thread/tls.c create mode 100644 lib/makefile create mode 100644 lib/msafd/.cvsignore create mode 100644 lib/msafd/include/debug.h create mode 100644 lib/msafd/include/helpers.h create mode 100644 lib/msafd/include/msafd.h create mode 100644 lib/msafd/makefile create mode 100644 lib/msafd/misc/dllmain.c create mode 100644 lib/msafd/misc/event.c create mode 100644 lib/msafd/misc/helpers.c create mode 100644 lib/msafd/misc/sndrcv.c create mode 100644 lib/msafd/misc/stubs.c create mode 100644 lib/msafd/msafd.def create mode 100644 lib/msafd/msafd.edf create mode 100644 lib/msafd/msafd.rc create mode 100644 lib/msvcrt/.cvsignore create mode 100644 lib/msvcrt/Makefile create mode 100644 lib/msvcrt/conio/.cvsignore create mode 100644 lib/msvcrt/conio/cgets.c create mode 100644 lib/msvcrt/conio/cprintf.c create mode 100644 lib/msvcrt/conio/cputs.c create mode 100644 lib/msvcrt/conio/cscanf.c create mode 100644 lib/msvcrt/conio/getch.c create mode 100644 lib/msvcrt/conio/getche.c create mode 100644 lib/msvcrt/conio/kbhit.c create mode 100644 lib/msvcrt/conio/putch.c create mode 100644 lib/msvcrt/conio/ungetch.c create mode 100644 lib/msvcrt/ctype/.cvsignore create mode 100644 lib/msvcrt/ctype/isalnum.c create mode 100644 lib/msvcrt/ctype/isalpha.c create mode 100644 lib/msvcrt/ctype/isascii.c create mode 100644 lib/msvcrt/ctype/iscntrl.c create mode 100644 lib/msvcrt/ctype/iscsym.c create mode 100644 lib/msvcrt/ctype/isctype.c create mode 100644 lib/msvcrt/ctype/isdigit.c create mode 100644 lib/msvcrt/ctype/isgraph.c create mode 100644 lib/msvcrt/ctype/islower.c create mode 100644 lib/msvcrt/ctype/isprint.c create mode 100644 lib/msvcrt/ctype/ispunct.c create mode 100644 lib/msvcrt/ctype/isspace.c create mode 100644 lib/msvcrt/ctype/isupper.c create mode 100644 lib/msvcrt/ctype/isxdigit.c create mode 100644 lib/msvcrt/ctype/toascii.c create mode 100644 lib/msvcrt/ctype/tolower.c create mode 100644 lib/msvcrt/ctype/toupper.c create mode 100644 lib/msvcrt/direct/.cvsignore create mode 100644 lib/msvcrt/direct/chdir.c create mode 100644 lib/msvcrt/direct/chdrive.c create mode 100644 lib/msvcrt/direct/getcwd.c create mode 100644 lib/msvcrt/direct/getdcwd.c create mode 100644 lib/msvcrt/direct/getdfree.c create mode 100644 lib/msvcrt/direct/getdrive.c create mode 100644 lib/msvcrt/direct/mkdir.c create mode 100644 lib/msvcrt/direct/rmdir.c create mode 100644 lib/msvcrt/except/.cvsignore create mode 100644 lib/msvcrt/except/abnorter.c create mode 100644 lib/msvcrt/except/exhand2.c create mode 100644 lib/msvcrt/except/matherr.c create mode 100755 lib/msvcrt/except/seh.s create mode 100644 lib/msvcrt/except/unwind.c create mode 100644 lib/msvcrt/except/xcptfil.c create mode 100644 lib/msvcrt/float/.cvsignore create mode 100644 lib/msvcrt/float/chgsign.c create mode 100644 lib/msvcrt/float/clearfp.c create mode 100644 lib/msvcrt/float/cntrlfp.c create mode 100644 lib/msvcrt/float/copysign.c create mode 100644 lib/msvcrt/float/fpclass.c create mode 100644 lib/msvcrt/float/fpecode.c create mode 100644 lib/msvcrt/float/fpreset.c create mode 100644 lib/msvcrt/float/isnan.c create mode 100644 lib/msvcrt/float/logb.c create mode 100644 lib/msvcrt/float/nafter.c create mode 100644 lib/msvcrt/float/scalb.c create mode 100644 lib/msvcrt/float/statfp.c create mode 100644 lib/msvcrt/io/.cvsignore create mode 100644 lib/msvcrt/io/access.c create mode 100644 lib/msvcrt/io/chmod.c create mode 100644 lib/msvcrt/io/chsize.c create mode 100644 lib/msvcrt/io/close.c create mode 100644 lib/msvcrt/io/commit.c create mode 100644 lib/msvcrt/io/create.c create mode 100644 lib/msvcrt/io/dup.c create mode 100644 lib/msvcrt/io/dup2.c create mode 100644 lib/msvcrt/io/eof.c create mode 100644 lib/msvcrt/io/filelen.c create mode 100644 lib/msvcrt/io/find.c create mode 100644 lib/msvcrt/io/fmode.c create mode 100644 lib/msvcrt/io/isatty.c create mode 100644 lib/msvcrt/io/locking.c create mode 100644 lib/msvcrt/io/lseek.c create mode 100644 lib/msvcrt/io/mktemp.c create mode 100644 lib/msvcrt/io/open.c create mode 100644 lib/msvcrt/io/pipe.c create mode 100644 lib/msvcrt/io/read.c create mode 100644 lib/msvcrt/io/setmode.c create mode 100644 lib/msvcrt/io/sopen.c create mode 100644 lib/msvcrt/io/tell.c create mode 100644 lib/msvcrt/io/umask.c create mode 100644 lib/msvcrt/io/unlink.c create mode 100644 lib/msvcrt/io/utime.c create mode 100644 lib/msvcrt/io/write.c create mode 100644 lib/msvcrt/locale/.cvsignore create mode 100644 lib/msvcrt/locale/locale.c create mode 100644 lib/msvcrt/math/.cvsignore create mode 100644 lib/msvcrt/math/acos.c create mode 100644 lib/msvcrt/math/adjust.c create mode 100644 lib/msvcrt/math/asin.c create mode 100644 lib/msvcrt/math/atan.c create mode 100644 lib/msvcrt/math/atan2.c create mode 100644 lib/msvcrt/math/cabs.c create mode 100644 lib/msvcrt/math/ceil.c create mode 100644 lib/msvcrt/math/cos.c create mode 100644 lib/msvcrt/math/cosh.c create mode 100644 lib/msvcrt/math/exp.c create mode 100644 lib/msvcrt/math/fabs.c create mode 100644 lib/msvcrt/math/floor.c create mode 100644 lib/msvcrt/math/fmod.c create mode 100644 lib/msvcrt/math/frexp.c create mode 100644 lib/msvcrt/math/ftol.c create mode 100644 lib/msvcrt/math/huge_val.c create mode 100644 lib/msvcrt/math/hypot.c create mode 100644 lib/msvcrt/math/j0_y0.c create mode 100644 lib/msvcrt/math/j1_y1.c create mode 100644 lib/msvcrt/math/jn_yn.c create mode 100644 lib/msvcrt/math/ldexp.c create mode 100644 lib/msvcrt/math/log.c create mode 100644 lib/msvcrt/math/log10.c create mode 100644 lib/msvcrt/math/modf.c create mode 100644 lib/msvcrt/math/pow.c create mode 100644 lib/msvcrt/math/sin.c create mode 100644 lib/msvcrt/math/sinh.c create mode 100644 lib/msvcrt/math/sqrt.c create mode 100644 lib/msvcrt/math/stubs.c create mode 100644 lib/msvcrt/math/tan.c create mode 100644 lib/msvcrt/math/tanh.c create mode 100644 lib/msvcrt/mbstring/.cvsignore create mode 100644 lib/msvcrt/mbstring/hanzen.c create mode 100644 lib/msvcrt/mbstring/ischira.c create mode 100644 lib/msvcrt/mbstring/iskana.c create mode 100644 lib/msvcrt/mbstring/iskmoji.c create mode 100644 lib/msvcrt/mbstring/iskpun.c create mode 100644 lib/msvcrt/mbstring/islead.c create mode 100644 lib/msvcrt/mbstring/islwr.c create mode 100644 lib/msvcrt/mbstring/ismbal.c create mode 100644 lib/msvcrt/mbstring/ismbaln.c create mode 100644 lib/msvcrt/mbstring/ismbc.c create mode 100644 lib/msvcrt/mbstring/ismbgra.c create mode 100644 lib/msvcrt/mbstring/ismbkaln.c create mode 100644 lib/msvcrt/mbstring/ismblead.c create mode 100644 lib/msvcrt/mbstring/ismbpri.c create mode 100644 lib/msvcrt/mbstring/ismbpun.c create mode 100644 lib/msvcrt/mbstring/ismbtrl.c create mode 100644 lib/msvcrt/mbstring/isuppr.c create mode 100644 lib/msvcrt/mbstring/jistojms.c create mode 100644 lib/msvcrt/mbstring/jmstojis.c create mode 100644 lib/msvcrt/mbstring/mbbtype.c create mode 100644 lib/msvcrt/mbstring/mbccpy.c create mode 100644 lib/msvcrt/mbstring/mbclen.c create mode 100644 lib/msvcrt/mbstring/mbscat.c create mode 100644 lib/msvcrt/mbstring/mbschr.c create mode 100644 lib/msvcrt/mbstring/mbscmp.c create mode 100644 lib/msvcrt/mbstring/mbscoll.c create mode 100644 lib/msvcrt/mbstring/mbscpy.c create mode 100644 lib/msvcrt/mbstring/mbscspn.c create mode 100644 lib/msvcrt/mbstring/mbsdec.c create mode 100644 lib/msvcrt/mbstring/mbsdup.c create mode 100644 lib/msvcrt/mbstring/mbsicmp.c create mode 100644 lib/msvcrt/mbstring/mbsicoll.c create mode 100644 lib/msvcrt/mbstring/mbsinc.c create mode 100644 lib/msvcrt/mbstring/mbslen.c create mode 100644 lib/msvcrt/mbstring/mbslwr.c create mode 100644 lib/msvcrt/mbstring/mbsncat.c create mode 100644 lib/msvcrt/mbstring/mbsnccnt.c create mode 100644 lib/msvcrt/mbstring/mbsncmp.c create mode 100644 lib/msvcrt/mbstring/mbsncoll.c create mode 100644 lib/msvcrt/mbstring/mbsncpy.c create mode 100644 lib/msvcrt/mbstring/mbsnextc.c create mode 100644 lib/msvcrt/mbstring/mbsnicmp.c create mode 100644 lib/msvcrt/mbstring/mbsnicoll.c create mode 100644 lib/msvcrt/mbstring/mbsninc.c create mode 100644 lib/msvcrt/mbstring/mbsnset.c create mode 100644 lib/msvcrt/mbstring/mbspbrk.c create mode 100644 lib/msvcrt/mbstring/mbsrchr.c create mode 100644 lib/msvcrt/mbstring/mbsrev.c create mode 100644 lib/msvcrt/mbstring/mbsset.c create mode 100644 lib/msvcrt/mbstring/mbsspn.c create mode 100644 lib/msvcrt/mbstring/mbsspnp.c create mode 100644 lib/msvcrt/mbstring/mbsstr.c create mode 100644 lib/msvcrt/mbstring/mbstok.c create mode 100644 lib/msvcrt/mbstring/mbstrlen.c create mode 100644 lib/msvcrt/mbstring/mbsupr.c create mode 100644 lib/msvcrt/misc/.cvsignore create mode 100644 lib/msvcrt/misc/amsg.c create mode 100644 lib/msvcrt/misc/assert.c create mode 100644 lib/msvcrt/misc/dllmain.c create mode 100644 lib/msvcrt/misc/getargs.c create mode 100644 lib/msvcrt/misc/initterm.c create mode 100644 lib/msvcrt/misc/purecall.c create mode 100644 lib/msvcrt/misc/tls.c create mode 100644 lib/msvcrt/msvcrt.def create mode 100644 lib/msvcrt/msvcrt.rc create mode 100644 lib/msvcrt/process/.cvsignore create mode 100644 lib/msvcrt/process/_cwait.c create mode 100644 lib/msvcrt/process/_system.c create mode 100644 lib/msvcrt/process/dll.c create mode 100644 lib/msvcrt/process/process.c create mode 100644 lib/msvcrt/process/procid.c create mode 100644 lib/msvcrt/process/thread.c create mode 100644 lib/msvcrt/process/threadid.c create mode 100644 lib/msvcrt/search/.cvsignore create mode 100644 lib/msvcrt/search/lfind.c create mode 100644 lib/msvcrt/search/lsearch.c create mode 100644 lib/msvcrt/setjmp/.cvsignore create mode 100644 lib/msvcrt/setjmp/setjmp.c create mode 100644 lib/msvcrt/signal/.cvsignore create mode 100644 lib/msvcrt/signal/signal.c create mode 100644 lib/msvcrt/stdio/.cvsignore create mode 100644 lib/msvcrt/stdio/allocfil.c create mode 100644 lib/msvcrt/stdio/clearerr.c create mode 100644 lib/msvcrt/stdio/fclose.c create mode 100644 lib/msvcrt/stdio/fdopen.c create mode 100644 lib/msvcrt/stdio/feof.c create mode 100644 lib/msvcrt/stdio/ferror.c create mode 100644 lib/msvcrt/stdio/fflush.c create mode 100644 lib/msvcrt/stdio/fgetc.c create mode 100644 lib/msvcrt/stdio/fgetchar.c create mode 100644 lib/msvcrt/stdio/fgetpos.c create mode 100644 lib/msvcrt/stdio/fgets.c create mode 100644 lib/msvcrt/stdio/filbuf.c create mode 100644 lib/msvcrt/stdio/fileno.c create mode 100644 lib/msvcrt/stdio/flsbuf.c create mode 100644 lib/msvcrt/stdio/fopen.c create mode 100644 lib/msvcrt/stdio/fprintf.c create mode 100644 lib/msvcrt/stdio/fputc.c create mode 100644 lib/msvcrt/stdio/fputchar.c create mode 100644 lib/msvcrt/stdio/fputs.c create mode 100644 lib/msvcrt/stdio/fread.c create mode 100644 lib/msvcrt/stdio/freopen.c create mode 100644 lib/msvcrt/stdio/fscanf.c create mode 100644 lib/msvcrt/stdio/fseek.c create mode 100644 lib/msvcrt/stdio/fsetpos.c create mode 100644 lib/msvcrt/stdio/fsopen.c create mode 100644 lib/msvcrt/stdio/ftell.c create mode 100644 lib/msvcrt/stdio/fwalk.c create mode 100644 lib/msvcrt/stdio/fwrite.c create mode 100644 lib/msvcrt/stdio/getc.c create mode 100644 lib/msvcrt/stdio/getchar.c create mode 100644 lib/msvcrt/stdio/gets.c create mode 100644 lib/msvcrt/stdio/getw.c create mode 100644 lib/msvcrt/stdio/perror.c create mode 100644 lib/msvcrt/stdio/popen.c create mode 100644 lib/msvcrt/stdio/printf.c create mode 100644 lib/msvcrt/stdio/putc.c create mode 100644 lib/msvcrt/stdio/putchar.c create mode 100644 lib/msvcrt/stdio/puts.c create mode 100644 lib/msvcrt/stdio/putw.c create mode 100644 lib/msvcrt/stdio/remove.c create mode 100644 lib/msvcrt/stdio/rename.c create mode 100644 lib/msvcrt/stdio/rewind.c create mode 100644 lib/msvcrt/stdio/rmtmp.c create mode 100644 lib/msvcrt/stdio/scanf.c create mode 100644 lib/msvcrt/stdio/setbuf.c create mode 100644 lib/msvcrt/stdio/setvbuf.c create mode 100644 lib/msvcrt/stdio/sprintf.c create mode 100644 lib/msvcrt/stdio/sscanf.c create mode 100644 lib/msvcrt/stdio/stdhnd.c create mode 100644 lib/msvcrt/stdio/tempnam.c create mode 100644 lib/msvcrt/stdio/tmpfile.c create mode 100644 lib/msvcrt/stdio/tmpnam.c create mode 100644 lib/msvcrt/stdio/ungetc.c create mode 100644 lib/msvcrt/stdio/vfprintf.c create mode 100644 lib/msvcrt/stdio/vfscanf.c create mode 100644 lib/msvcrt/stdio/vfwprint.c create mode 100644 lib/msvcrt/stdio/vprintf.c create mode 100644 lib/msvcrt/stdio/vscanf.c create mode 100644 lib/msvcrt/stdio/vsprintf.c create mode 100644 lib/msvcrt/stdio/vsscanf.c create mode 100644 lib/msvcrt/stdlib/.cvsignore create mode 100644 lib/msvcrt/stdlib/_exit.c create mode 100644 lib/msvcrt/stdlib/abort.c create mode 100644 lib/msvcrt/stdlib/abs.c create mode 100644 lib/msvcrt/stdlib/atexit.c create mode 100644 lib/msvcrt/stdlib/atof.c create mode 100644 lib/msvcrt/stdlib/atoi.c create mode 100644 lib/msvcrt/stdlib/atoi64.c create mode 100644 lib/msvcrt/stdlib/atol.c create mode 100644 lib/msvcrt/stdlib/atold.c create mode 100644 lib/msvcrt/stdlib/bsearch.c create mode 100644 lib/msvcrt/stdlib/div.c create mode 100644 lib/msvcrt/stdlib/ecvt.c create mode 100644 lib/msvcrt/stdlib/ecvtbuf.c create mode 100644 lib/msvcrt/stdlib/errno.c create mode 100644 lib/msvcrt/stdlib/fcvt.c create mode 100644 lib/msvcrt/stdlib/fcvtbuf.c create mode 100644 lib/msvcrt/stdlib/fullpath.c create mode 100644 lib/msvcrt/stdlib/gcvt.c create mode 100644 lib/msvcrt/stdlib/getenv.c create mode 100644 lib/msvcrt/stdlib/itoa.c create mode 100644 lib/msvcrt/stdlib/itow.c create mode 100644 lib/msvcrt/stdlib/labs.c create mode 100644 lib/msvcrt/stdlib/ldiv.c create mode 100644 lib/msvcrt/stdlib/makepath.c create mode 100644 lib/msvcrt/stdlib/malloc.c create mode 100644 lib/msvcrt/stdlib/mbstow.c create mode 100644 lib/msvcrt/stdlib/mbstowcs.c create mode 100644 lib/msvcrt/stdlib/obsol.c create mode 100644 lib/msvcrt/stdlib/putenv.c create mode 100644 lib/msvcrt/stdlib/qsort.c create mode 100644 lib/msvcrt/stdlib/rand.c create mode 100644 lib/msvcrt/stdlib/rot.c create mode 100644 lib/msvcrt/stdlib/senv.c create mode 100644 lib/msvcrt/stdlib/splitp.c create mode 100644 lib/msvcrt/stdlib/strtod.c create mode 100644 lib/msvcrt/stdlib/strtol.c create mode 100644 lib/msvcrt/stdlib/strtold.c create mode 100644 lib/msvcrt/stdlib/strtoll.c create mode 100644 lib/msvcrt/stdlib/strtoul.c create mode 100644 lib/msvcrt/stdlib/strtoull.c create mode 100644 lib/msvcrt/stdlib/swab.c create mode 100644 lib/msvcrt/stdlib/wcstod.c create mode 100644 lib/msvcrt/stdlib/wcstol.c create mode 100644 lib/msvcrt/stdlib/wcstom.c create mode 100644 lib/msvcrt/stdlib/wcstomb.c create mode 100644 lib/msvcrt/stdlib/wcstombs.c create mode 100644 lib/msvcrt/stdlib/wcstoul.c create mode 100644 lib/msvcrt/stdlib/wtoi.c create mode 100644 lib/msvcrt/stdlib/wtoi64.c create mode 100644 lib/msvcrt/string/.cvsignore create mode 100644 lib/msvcrt/string/memccpy.c create mode 100644 lib/msvcrt/string/memchr.c create mode 100644 lib/msvcrt/string/memcmp.c create mode 100644 lib/msvcrt/string/memcpy.c create mode 100644 lib/msvcrt/string/memicmp.c create mode 100644 lib/msvcrt/string/memmove.c create mode 100644 lib/msvcrt/string/memset.c create mode 100644 lib/msvcrt/string/strcat.c create mode 100644 lib/msvcrt/string/strchr.c create mode 100644 lib/msvcrt/string/strcmp.c create mode 100644 lib/msvcrt/string/strcoll.c create mode 100644 lib/msvcrt/string/strcpy.c create mode 100644 lib/msvcrt/string/strcspn.c create mode 100644 lib/msvcrt/string/strdup.c create mode 100644 lib/msvcrt/string/strerror.c create mode 100644 lib/msvcrt/string/stricmp.c create mode 100644 lib/msvcrt/string/strlen.c create mode 100644 lib/msvcrt/string/strlwr.c create mode 100644 lib/msvcrt/string/strncat.c create mode 100644 lib/msvcrt/string/strncmp.c create mode 100644 lib/msvcrt/string/strncpy.c create mode 100644 lib/msvcrt/string/strnicmp.c create mode 100644 lib/msvcrt/string/strnlen.c create mode 100644 lib/msvcrt/string/strpbrk.c create mode 100644 lib/msvcrt/string/strrchr.c create mode 100644 lib/msvcrt/string/strrev.c create mode 100644 lib/msvcrt/string/strset.c create mode 100644 lib/msvcrt/string/strspn.c create mode 100644 lib/msvcrt/string/strstr.c create mode 100644 lib/msvcrt/string/strtok.c create mode 100644 lib/msvcrt/string/strupr.c create mode 100644 lib/msvcrt/string/strxfrm.c create mode 100644 lib/msvcrt/sys_stat/.cvsignore create mode 100644 lib/msvcrt/sys_stat/fstat.c create mode 100644 lib/msvcrt/sys_stat/futime.c create mode 100644 lib/msvcrt/sys_stat/stat.c create mode 100644 lib/msvcrt/time/.cvsignore create mode 100644 lib/msvcrt/time/clock.c create mode 100644 lib/msvcrt/time/ctime.c create mode 100644 lib/msvcrt/time/difftime.c create mode 100644 lib/msvcrt/time/posixrul.h create mode 100644 lib/msvcrt/time/strdate.c create mode 100644 lib/msvcrt/time/strftime.c create mode 100644 lib/msvcrt/time/strtime.c create mode 100644 lib/msvcrt/time/time.c create mode 100644 lib/msvcrt/time/tzfile.h create mode 100644 lib/msvcrt/wstring/.cvsignore create mode 100644 lib/msvcrt/wstring/wcscat.c create mode 100644 lib/msvcrt/wstring/wcschr.c create mode 100644 lib/msvcrt/wstring/wcscmp.c create mode 100644 lib/msvcrt/wstring/wcscoll.c create mode 100644 lib/msvcrt/wstring/wcscpy.c create mode 100644 lib/msvcrt/wstring/wcscspn.c create mode 100644 lib/msvcrt/wstring/wcsdup.c create mode 100644 lib/msvcrt/wstring/wcsicmp.c create mode 100644 lib/msvcrt/wstring/wcslen.c create mode 100644 lib/msvcrt/wstring/wcslwr.c create mode 100644 lib/msvcrt/wstring/wcsncat.c create mode 100644 lib/msvcrt/wstring/wcsncmp.c create mode 100644 lib/msvcrt/wstring/wcsncpy.c create mode 100644 lib/msvcrt/wstring/wcsnicmp.c create mode 100644 lib/msvcrt/wstring/wcsnlen.c create mode 100644 lib/msvcrt/wstring/wcspbrk.c create mode 100644 lib/msvcrt/wstring/wcsrchr.c create mode 100644 lib/msvcrt/wstring/wcsrev.c create mode 100644 lib/msvcrt/wstring/wcsset.c create mode 100644 lib/msvcrt/wstring/wcsspn.c create mode 100644 lib/msvcrt/wstring/wcsstr.c create mode 100644 lib/msvcrt/wstring/wcstok.c create mode 100644 lib/msvcrt/wstring/wcsupr.c create mode 100644 lib/msvcrt/wstring/wcsxfrm.c create mode 100644 lib/ntdll/.cvsignore create mode 100644 lib/ntdll/csr/.cvsignore create mode 100644 lib/ntdll/csr/capture.c create mode 100644 lib/ntdll/csr/lpc.c create mode 100644 lib/ntdll/csr/probe.c create mode 100644 lib/ntdll/csr/thread.c create mode 100644 lib/ntdll/dbg/.cvsignore create mode 100644 lib/ntdll/dbg/brkpoint.c create mode 100644 lib/ntdll/dbg/debug.c create mode 100644 lib/ntdll/dbg/print.c create mode 100644 lib/ntdll/dbg/winedbg.c create mode 100644 lib/ntdll/def/.cvsignore create mode 100644 lib/ntdll/def/ntdll.def create mode 100644 lib/ntdll/def/ntdll.edf create mode 100644 lib/ntdll/def/ntdll.rc create mode 100644 lib/ntdll/ldr/.cvsignore create mode 100644 lib/ntdll/ldr/startup.c create mode 100644 lib/ntdll/ldr/utils.c create mode 100644 lib/ntdll/main/.cvsignore create mode 100644 lib/ntdll/main/dllmain.c create mode 100644 lib/ntdll/makefile create mode 100644 lib/ntdll/rtl/.cvsignore create mode 100644 lib/ntdll/rtl/access.c create mode 100644 lib/ntdll/rtl/acl.c create mode 100644 lib/ntdll/rtl/apc.c create mode 100644 lib/ntdll/rtl/atom.c create mode 100644 lib/ntdll/rtl/bitmap.c create mode 100644 lib/ntdll/rtl/callback.c create mode 100644 lib/ntdll/rtl/compress.c create mode 100644 lib/ntdll/rtl/critical.c create mode 100644 lib/ntdll/rtl/dos8dot3.c create mode 100644 lib/ntdll/rtl/env.c create mode 100644 lib/ntdll/rtl/error.c create mode 100644 lib/ntdll/rtl/exception.c create mode 100644 lib/ntdll/rtl/handle.c create mode 100644 lib/ntdll/rtl/heap.c create mode 100755 lib/ntdll/rtl/i386/except.s create mode 100755 lib/ntdll/rtl/i386/exception.c create mode 100644 lib/ntdll/rtl/image.c create mode 100644 lib/ntdll/rtl/intrlck.c create mode 100644 lib/ntdll/rtl/largeint.c create mode 100644 lib/ntdll/rtl/luid.c create mode 100644 lib/ntdll/rtl/math.c create mode 100644 lib/ntdll/rtl/mem.c create mode 100644 lib/ntdll/rtl/message.c create mode 100644 lib/ntdll/rtl/misc.c create mode 100644 lib/ntdll/rtl/nls.c create mode 100644 lib/ntdll/rtl/path.c create mode 100644 lib/ntdll/rtl/ppb.c create mode 100644 lib/ntdll/rtl/process.c create mode 100644 lib/ntdll/rtl/propvar.c create mode 100644 lib/ntdll/rtl/registry.c create mode 100644 lib/ntdll/rtl/resource.c create mode 100644 lib/ntdll/rtl/sd.c create mode 100644 lib/ntdll/rtl/security.c create mode 100644 lib/ntdll/rtl/sid.c create mode 100644 lib/ntdll/rtl/thread.c create mode 100644 lib/ntdll/rtl/time.c create mode 100644 lib/ntdll/rtl/timezone.c create mode 100644 lib/ntdll/rtl/trace.c create mode 100644 lib/ntdll/rtl/unicode.c create mode 100644 lib/ntdll/stdio/.cvsignore create mode 100644 lib/ntdll/stdio/sprintf.c create mode 100644 lib/ntdll/stdio/swprintf.c create mode 100644 lib/ntdll/stdlib/.cvsignore create mode 100644 lib/ntdll/stdlib/abs.c create mode 100644 lib/ntdll/stdlib/atoi.c create mode 100644 lib/ntdll/stdlib/atoi64.c create mode 100644 lib/ntdll/stdlib/atol.c create mode 100644 lib/ntdll/stdlib/itoa.c create mode 100644 lib/ntdll/stdlib/itow.c create mode 100644 lib/ntdll/stdlib/labs.c create mode 100644 lib/ntdll/stdlib/mbstowcs.c create mode 100644 lib/ntdll/stdlib/qsort.c create mode 100644 lib/ntdll/stdlib/splitp.c create mode 100644 lib/ntdll/stdlib/strtol.c create mode 100644 lib/ntdll/stdlib/strtoul.c create mode 100644 lib/ntdll/stdlib/wcstol.c create mode 100644 lib/ntdll/stdlib/wcstombs.c create mode 100644 lib/ntdll/stdlib/wcstoul.c create mode 100644 lib/ntdll/stdlib/wtoi.c create mode 100644 lib/ntdll/stdlib/wtoi64.c create mode 100644 lib/ntdll/stdlib/wtol.c create mode 100644 lib/ntdll/string/.cvsignore create mode 100644 lib/ntdll/string/ctype.c create mode 100644 lib/ntdll/string/memccpy.c create mode 100644 lib/ntdll/string/memchr.c create mode 100644 lib/ntdll/string/memcmp.c create mode 100644 lib/ntdll/string/memcpy.c create mode 100644 lib/ntdll/string/memicmp.c create mode 100644 lib/ntdll/string/memmove.c create mode 100644 lib/ntdll/string/memset.c create mode 100644 lib/ntdll/string/strcat.c create mode 100644 lib/ntdll/string/strchr.c create mode 100644 lib/ntdll/string/strcmp.c create mode 100644 lib/ntdll/string/strcpy.c create mode 100644 lib/ntdll/string/strcspn.c create mode 100644 lib/ntdll/string/stricmp.c create mode 100644 lib/ntdll/string/strlen.c create mode 100644 lib/ntdll/string/strlwr.c create mode 100644 lib/ntdll/string/strncat.c create mode 100644 lib/ntdll/string/strncmp.c create mode 100644 lib/ntdll/string/strncpy.c create mode 100644 lib/ntdll/string/strnicmp.c create mode 100644 lib/ntdll/string/strnlen.c create mode 100644 lib/ntdll/string/strpbrk.c create mode 100644 lib/ntdll/string/strrchr.c create mode 100644 lib/ntdll/string/strspn.c create mode 100644 lib/ntdll/string/strstr.c create mode 100644 lib/ntdll/string/strupr.c create mode 100644 lib/ntdll/string/wstring.c create mode 100644 lib/ntdll/stubs/.cvsignore create mode 100644 lib/ntdll/stubs/stubs.c create mode 100644 lib/ole32/.cvsignore create mode 100644 lib/ole32/CoXxx.c create mode 100644 lib/ole32/DllMain.c create mode 100644 lib/ole32/Misc.c create mode 100644 lib/ole32/Moniker.c create mode 100644 lib/ole32/Ole2.c create mode 100644 lib/ole32/Ole32.h create mode 100644 lib/ole32/OleAuto.c create mode 100644 lib/ole32/Storage.c create mode 100644 lib/ole32/antimoniker.c create mode 100644 lib/ole32/bindctx.c create mode 100644 lib/ole32/compobj.c create mode 100644 lib/ole32/compositemoniker.c create mode 100644 lib/ole32/datacache.c create mode 100644 lib/ole32/filemoniker.c create mode 100644 lib/ole32/include/compobj.h create mode 100644 lib/ole32/include/debug.h create mode 100644 lib/ole32/include/ole32_main.h create mode 100644 lib/ole32/include/storage32.h create mode 100644 lib/ole32/itemmoniker.c create mode 100644 lib/ole32/makefile create mode 100644 lib/ole32/memlockbytes.c create mode 100644 lib/ole32/ole32.def create mode 100644 lib/ole32/ole32.rc create mode 100644 lib/ole32/rpcrt4_main.c create mode 100644 lib/ole32/stg_bigblockfile.c create mode 100644 lib/ole32/stg_stream.c create mode 100644 lib/ole32/storage32.c create mode 100644 lib/oleaut32/.cvsignore create mode 100644 lib/oleaut32/dllmain.c create mode 100644 lib/oleaut32/makefile create mode 100644 lib/oleaut32/oleaut32.def create mode 100644 lib/oleaut32/oleaut32.rc create mode 100644 lib/oleaut32/stubs.c create mode 100644 lib/packet/.cvsignore create mode 100644 lib/packet/Packet32.c create mode 100644 lib/packet/include/devioctl.h create mode 100644 lib/packet/include/ntddndis.h create mode 100644 lib/packet/include/packet32.h create mode 100644 lib/packet/makefile create mode 100644 lib/packet/packet.def create mode 100644 lib/packet/packet.edf create mode 100644 lib/packet/packet.rc create mode 100644 lib/packet/resource.h create mode 100644 lib/packet/trace.c create mode 100644 lib/packet/trace.h create mode 100644 lib/psapi/enum/module.c create mode 100644 lib/psapi/enum/process.c create mode 100644 lib/psapi/include/internal/psapi.h create mode 100644 lib/psapi/makefile create mode 100644 lib/psapi/misc/dllmain.c create mode 100644 lib/psapi/misc/malloc.c create mode 100644 lib/psapi/misc/stubs.c create mode 100644 lib/psapi/misc/win32.c create mode 100644 lib/psapi/psapi.def create mode 100644 lib/psapi/psapi.edf create mode 100644 lib/psapi/psapi.rc create mode 100644 lib/rpcrt4/Makefile create mode 100644 lib/rpcrt4/include/rpc.h create mode 100644 lib/rpcrt4/include/rpcrt4/rpc.h create mode 100644 lib/rpcrt4/midl/Makefile create mode 100644 lib/rpcrt4/midl/hello.idl create mode 100644 lib/rpcrt4/midl/idl.l create mode 100644 lib/rpcrt4/midl/idl.y create mode 100644 lib/rpcrt4/midl/interface.c create mode 100644 lib/rpcrt4/midl/midl.c create mode 100644 lib/rpcrt4/midl/midl.h create mode 100644 lib/rpcrt4/midl/option.c create mode 100644 lib/rpcrt4/midl/types.c create mode 100644 lib/rpcrt4/midl/types.h create mode 100644 lib/secur32/.cvsignore create mode 100644 lib/secur32/Makefile create mode 100644 lib/secur32/dllmain.c create mode 100644 lib/secur32/lsa.c create mode 100644 lib/secur32/secur32.def create mode 100644 lib/secur32/secur32.edf create mode 100644 lib/secur32/secur32.rc create mode 100644 lib/shell32/.cvsignore create mode 100644 lib/shell32/control/control.c create mode 100644 lib/shell32/control/control.h create mode 100644 lib/shell32/control/framewnd.c create mode 100644 lib/shell32/control/framewnd.h create mode 100644 lib/shell32/control/listview.c create mode 100644 lib/shell32/control/listview.h create mode 100644 lib/shell32/control/settings.c create mode 100644 lib/shell32/control/settings.h create mode 100644 lib/shell32/control/trace.c create mode 100644 lib/shell32/control/trace.h create mode 100644 lib/shell32/makefile create mode 100644 lib/shell32/misc/_stubs.cpp create mode 100644 lib/shell32/misc/dllmain.c create mode 100644 lib/shell32/misc/shlwapi.h create mode 100644 lib/shell32/misc/stubs.c create mode 100644 lib/shell32/res/control.ico create mode 100644 lib/shell32/res/small.ico create mode 100644 lib/shell32/resource.h create mode 100644 lib/shell32/roshel32.rc create mode 100644 lib/shell32/shell32.def create mode 100644 lib/shell32/shell32.edf create mode 100644 lib/shell32/shell32.h create mode 100644 lib/shell32/shell32.rc create mode 100644 lib/snmpapi/.cvsignore create mode 100644 lib/snmpapi/debug.h create mode 100644 lib/snmpapi/makefile create mode 100644 lib/snmpapi/snmpapi.c create mode 100644 lib/snmpapi/snmpapi.def create mode 100644 lib/snmpapi/snmpapi.edf create mode 100644 lib/snmpapi/snmpapi.rc create mode 100644 lib/user32/.cvsignore create mode 100644 lib/user32/Makefile create mode 100644 lib/user32/controls/.cvsignore create mode 100644 lib/user32/controls/combobox.c create mode 100644 lib/user32/controls/listbox.c create mode 100644 lib/user32/controls/scrollbar.c create mode 100644 lib/user32/include/debug.h create mode 100644 lib/user32/include/user32.h create mode 100644 lib/user32/include/window.h create mode 100644 lib/user32/include/winsta.h create mode 100644 lib/user32/misc/.cvsignore create mode 100644 lib/user32/misc/dde.c create mode 100644 lib/user32/misc/desktop.c create mode 100644 lib/user32/misc/display.c create mode 100644 lib/user32/misc/dllmain.c create mode 100644 lib/user32/misc/exit.c create mode 100644 lib/user32/misc/object.c create mode 100644 lib/user32/misc/resources.c create mode 100644 lib/user32/misc/sprintf.c create mode 100644 lib/user32/misc/stubs.c create mode 100644 lib/user32/misc/timer.c create mode 100644 lib/user32/misc/winhelp.c create mode 100644 lib/user32/misc/winsta.c create mode 100644 lib/user32/resources/obm_btncorners.bmp create mode 100644 lib/user32/resources/obm_btsize.bmp create mode 100644 lib/user32/resources/obm_check.bmp create mode 100644 lib/user32/resources/obm_checkboxes.bmp create mode 100644 lib/user32/resources/obm_close.bmp create mode 100644 lib/user32/resources/obm_combo.bmp create mode 100644 lib/user32/resources/obm_dnarrow.bmp create mode 100644 lib/user32/resources/obm_dnarrowd.bmp create mode 100644 lib/user32/resources/obm_dnarrowi.bmp create mode 100644 lib/user32/resources/obm_lfarrow.bmp create mode 100644 lib/user32/resources/obm_lfarrowd.bmp create mode 100644 lib/user32/resources/obm_lfarrowi.bmp create mode 100644 lib/user32/resources/obm_mnarrow.bmp create mode 100644 lib/user32/resources/obm_old_close.bmp create mode 100644 lib/user32/resources/obm_old_dnarrow.bmp create mode 100644 lib/user32/resources/obm_old_lfarrow.bmp create mode 100644 lib/user32/resources/obm_old_reduce.bmp create mode 100644 lib/user32/resources/obm_old_restore.bmp create mode 100644 lib/user32/resources/obm_old_rgarrow.bmp create mode 100644 lib/user32/resources/obm_old_uparrow.bmp create mode 100644 lib/user32/resources/obm_old_zoom.bmp create mode 100644 lib/user32/resources/obm_reduce.bmp create mode 100644 lib/user32/resources/obm_reduced.bmp create mode 100644 lib/user32/resources/obm_restore.bmp create mode 100644 lib/user32/resources/obm_restored.bmp create mode 100644 lib/user32/resources/obm_rgarrow.bmp create mode 100644 lib/user32/resources/obm_rgarrowd.bmp create mode 100644 lib/user32/resources/obm_rgarrowi.bmp create mode 100644 lib/user32/resources/obm_size.bmp create mode 100644 lib/user32/resources/obm_trtype.bmp create mode 100644 lib/user32/resources/obm_uparrow.bmp create mode 100644 lib/user32/resources/obm_uparrowd.bmp create mode 100644 lib/user32/resources/obm_uparrowi.bmp create mode 100644 lib/user32/resources/obm_zoom.bmp create mode 100644 lib/user32/resources/obm_zoomd.bmp create mode 100644 lib/user32/resources/ocr_appstarting.cur create mode 100644 lib/user32/resources/ocr_cross.cur create mode 100644 lib/user32/resources/ocr_dragobject.cur create mode 100644 lib/user32/resources/ocr_hand.cur create mode 100644 lib/user32/resources/ocr_help.cur create mode 100644 lib/user32/resources/ocr_ibeam.cur create mode 100644 lib/user32/resources/ocr_icon.cur create mode 100644 lib/user32/resources/ocr_no.cur create mode 100644 lib/user32/resources/ocr_normal.cur create mode 100644 lib/user32/resources/ocr_size.cur create mode 100644 lib/user32/resources/ocr_sizeall.cur create mode 100644 lib/user32/resources/ocr_sizenesw.cur create mode 100644 lib/user32/resources/ocr_sizens.cur create mode 100644 lib/user32/resources/ocr_sizenwse.cur create mode 100644 lib/user32/resources/ocr_sizewe.cur create mode 100644 lib/user32/resources/ocr_up.cur create mode 100644 lib/user32/resources/ocr_wait.cur create mode 100644 lib/user32/resources/oic_bang.ico create mode 100644 lib/user32/resources/oic_hand.ico create mode 100644 lib/user32/resources/oic_note.ico create mode 100644 lib/user32/resources/oic_ques.ico create mode 100644 lib/user32/resources/oic_sample.ico create mode 100644 lib/user32/user32.def create mode 100644 lib/user32/user32.edf create mode 100644 lib/user32/user32.rc create mode 100644 lib/user32/windows/.cvsignore create mode 100644 lib/user32/windows/accel.c create mode 100644 lib/user32/windows/bitmap.c create mode 100644 lib/user32/windows/class.c create mode 100644 lib/user32/windows/clipboard.c create mode 100644 lib/user32/windows/cursor.c create mode 100644 lib/user32/windows/dc.c create mode 100644 lib/user32/windows/defwnd.c create mode 100644 lib/user32/windows/dialog.c create mode 100644 lib/user32/windows/draw.c create mode 100644 lib/user32/windows/font.c create mode 100644 lib/user32/windows/hook.c create mode 100644 lib/user32/windows/icon.c create mode 100644 lib/user32/windows/input.c create mode 100644 lib/user32/windows/mdi.c create mode 100644 lib/user32/windows/menu.c create mode 100644 lib/user32/windows/message.c create mode 100644 lib/user32/windows/messagebox.c create mode 100644 lib/user32/windows/nonclient.c create mode 100644 lib/user32/windows/paint.c create mode 100644 lib/user32/windows/prop.c create mode 100644 lib/user32/windows/rect.c create mode 100644 lib/user32/windows/text.c create mode 100644 lib/user32/windows/window.c create mode 100644 lib/version/.cvsignore create mode 100644 lib/version/makefile create mode 100644 lib/version/misc/libmain.c create mode 100644 lib/version/misc/stubs.c create mode 100644 lib/version/version.def create mode 100644 lib/version/version.edf create mode 100644 lib/version/version.rc create mode 100644 lib/version/version_specs create mode 100644 lib/winmm/.cvsignore create mode 100644 lib/winmm/Makefile create mode 100644 lib/winmm/dllmain.c create mode 100644 lib/winmm/misc/stubs.c create mode 100644 lib/winmm/winmm.def create mode 100644 lib/winmm/winmm.edf create mode 100644 lib/winmm/winmm.rc create mode 100644 lib/ws2_32/.cvsignore create mode 100644 lib/ws2_32/include/catalog.h create mode 100644 lib/ws2_32/include/debug.h create mode 100644 lib/ws2_32/include/handle.h create mode 100644 lib/ws2_32/include/upcall.h create mode 100644 lib/ws2_32/include/ws2_32.h create mode 100644 lib/ws2_32/makefile create mode 100644 lib/ws2_32/misc/bsd.c create mode 100644 lib/ws2_32/misc/catalog.c create mode 100644 lib/ws2_32/misc/dllmain.c create mode 100644 lib/ws2_32/misc/event.c create mode 100644 lib/ws2_32/misc/handle.c create mode 100644 lib/ws2_32/misc/ns.c create mode 100644 lib/ws2_32/misc/sndrcv.c create mode 100644 lib/ws2_32/misc/stubs.c create mode 100644 lib/ws2_32/misc/upcall.c create mode 100644 lib/ws2_32/ws2_32.def create mode 100644 lib/ws2_32/ws2_32.edf create mode 100644 lib/ws2_32/ws2_32.rc create mode 100644 lib/ws2_32/ws2_32_specs create mode 100644 lib/ws2help/.cvsignore create mode 100644 lib/ws2help/debug.h create mode 100644 lib/ws2help/makefile create mode 100644 lib/ws2help/ws2help.c create mode 100644 lib/ws2help/ws2help.def create mode 100644 lib/ws2help/ws2help.edf create mode 100644 lib/ws2help/ws2help.h create mode 100644 lib/ws2help/ws2help.rc create mode 100644 lib/wshirda/.cvsignore create mode 100644 lib/wshirda/debug.h create mode 100644 lib/wshirda/makefile create mode 100644 lib/wshirda/wshirda.c create mode 100644 lib/wshirda/wshirda.def create mode 100644 lib/wshirda/wshirda.edf create mode 100644 lib/wshirda/wshirda.h create mode 100644 lib/wshirda/wshirda.rc create mode 100644 loaders/boot/boot.asm create mode 100644 loaders/boot/boot.inc create mode 100644 loaders/boot/boot.mak create mode 100644 loaders/boot/bootbk.asm create mode 100644 loaders/boot/osldr.asm create mode 100644 loaders/boot/osldr.txt create mode 100644 loaders/dos/loadros.asm create mode 100644 loaders/dos/makefile create mode 100644 makedisk.bat create mode 100644 media/fonts/helb____.ttf create mode 100644 media/fonts/timr____.ttf create mode 100644 media/nls/c_037.nls create mode 100644 media/nls/c_10000.nls create mode 100644 media/nls/c_10006.nls create mode 100644 media/nls/c_10007.nls create mode 100644 media/nls/c_10029.nls create mode 100644 media/nls/c_1006.nls create mode 100644 media/nls/c_10079.nls create mode 100644 media/nls/c_10081.nls create mode 100644 media/nls/c_1026.nls create mode 100644 media/nls/c_1250.nls create mode 100644 media/nls/c_1251.nls create mode 100644 media/nls/c_1252.nls create mode 100644 media/nls/c_1253.nls create mode 100644 media/nls/c_1254.nls create mode 100644 media/nls/c_1255.nls create mode 100644 media/nls/c_1256.nls create mode 100644 media/nls/c_1257.nls create mode 100644 media/nls/c_1258.nls create mode 100644 media/nls/c_20866.nls create mode 100644 media/nls/c_28591.nls create mode 100644 media/nls/c_28592.nls create mode 100644 media/nls/c_28593.nls create mode 100644 media/nls/c_28594.nls create mode 100644 media/nls/c_28595.nls create mode 100644 media/nls/c_28596.nls create mode 100644 media/nls/c_28597.nls create mode 100644 media/nls/c_28598.nls create mode 100644 media/nls/c_28599.nls create mode 100644 media/nls/c_424.nls create mode 100644 media/nls/c_437.nls create mode 100644 media/nls/c_500.nls create mode 100644 media/nls/c_737.nls create mode 100644 media/nls/c_775.nls create mode 100644 media/nls/c_850.nls create mode 100644 media/nls/c_852.nls create mode 100644 media/nls/c_855.nls create mode 100644 media/nls/c_856.nls create mode 100644 media/nls/c_857.nls create mode 100644 media/nls/c_860.nls create mode 100644 media/nls/c_861.nls create mode 100644 media/nls/c_862.nls create mode 100644 media/nls/c_863.nls create mode 100644 media/nls/c_864.nls create mode 100644 media/nls/c_865.nls create mode 100644 media/nls/c_866.nls create mode 100644 media/nls/c_869.nls create mode 100644 media/nls/c_874.nls create mode 100644 media/nls/c_875.nls create mode 100644 media/nls/c_878.nls create mode 100644 media/nls/c_932.nls create mode 100644 media/nls/c_936.nls create mode 100644 media/nls/c_949.nls create mode 100644 media/nls/c_950.nls create mode 100644 media/nls/l_intl.nls create mode 100644 ntoskrnl/.cvsignore create mode 100644 ntoskrnl/Makefile create mode 100644 ntoskrnl/Makefile.i386 create mode 100644 ntoskrnl/cc/.cvsignore create mode 100644 ntoskrnl/cc/cacheman.c create mode 100644 ntoskrnl/cc/copy.c create mode 100644 ntoskrnl/cc/misc.c create mode 100644 ntoskrnl/cc/pin.c create mode 100644 ntoskrnl/cc/view.c create mode 100644 ntoskrnl/cm/.cvsignore create mode 100644 ntoskrnl/cm/cm.h create mode 100644 ntoskrnl/cm/import.c create mode 100644 ntoskrnl/cm/ntfunc.c create mode 100644 ntoskrnl/cm/regfile.c create mode 100644 ntoskrnl/cm/registry.c create mode 100644 ntoskrnl/cm/regobj.c create mode 100644 ntoskrnl/cm/rtlfunc.c create mode 100644 ntoskrnl/dbg/.cvsignore create mode 100644 ntoskrnl/dbg/dbgctrl.c create mode 100644 ntoskrnl/dbg/errinfo.c create mode 100644 ntoskrnl/dbg/i386/.cvsignore create mode 100644 ntoskrnl/dbg/i386/kdb_help.S create mode 100644 ntoskrnl/dbg/kdb.c create mode 100644 ntoskrnl/dbg/kdb.h create mode 100644 ntoskrnl/dbg/kdb_keyboard.c create mode 100644 ntoskrnl/dbg/kdb_stabs.c create mode 100644 ntoskrnl/dbg/print.c create mode 100644 ntoskrnl/dbg/rdebug.c create mode 100644 ntoskrnl/dbg/user.c create mode 100644 ntoskrnl/ex/.cvsignore create mode 100644 ntoskrnl/ex/btree.c create mode 100644 ntoskrnl/ex/callback.c create mode 100644 ntoskrnl/ex/fmutex.c create mode 100644 ntoskrnl/ex/hashtab.c create mode 100644 ntoskrnl/ex/i386/.cvsignore create mode 100644 ntoskrnl/ex/i386/interlck.c create mode 100644 ntoskrnl/ex/init.c create mode 100644 ntoskrnl/ex/interlck.c create mode 100644 ntoskrnl/ex/list.c create mode 100644 ntoskrnl/ex/lookas.c create mode 100644 ntoskrnl/ex/napi.c create mode 100644 ntoskrnl/ex/power.c create mode 100644 ntoskrnl/ex/resource.c create mode 100644 ntoskrnl/ex/stree.c create mode 100644 ntoskrnl/ex/sysinfo.c create mode 100644 ntoskrnl/ex/time.c create mode 100644 ntoskrnl/ex/win32k.c create mode 100644 ntoskrnl/ex/work.c create mode 100644 ntoskrnl/ex/zone.c create mode 100644 ntoskrnl/fs/.cvsignore create mode 100644 ntoskrnl/fs/dbcsname.c create mode 100644 ntoskrnl/fs/filelock.c create mode 100644 ntoskrnl/fs/mcb.c create mode 100644 ntoskrnl/fs/mdl.c create mode 100644 ntoskrnl/fs/name.c create mode 100644 ntoskrnl/fs/notify.c create mode 100644 ntoskrnl/fs/oplock.c create mode 100644 ntoskrnl/fs/pool.c create mode 100644 ntoskrnl/fs/tunnel.c create mode 100644 ntoskrnl/fs/unc.c create mode 100644 ntoskrnl/fs/util.c create mode 100644 ntoskrnl/include/internal/arch/ke.h create mode 100644 ntoskrnl/include/internal/arch/mm.h create mode 100644 ntoskrnl/include/internal/arch/ps.h create mode 100644 ntoskrnl/include/internal/cc.h create mode 100644 ntoskrnl/include/internal/config.h create mode 100644 ntoskrnl/include/internal/ctype.h create mode 100644 ntoskrnl/include/internal/dbg.h create mode 100644 ntoskrnl/include/internal/debug.h create mode 100644 ntoskrnl/include/internal/ex.h create mode 100644 ntoskrnl/include/internal/hal/bus.h create mode 100644 ntoskrnl/include/internal/hal/hal.h create mode 100644 ntoskrnl/include/internal/hal/mps.h create mode 100644 ntoskrnl/include/internal/handle.h create mode 100644 ntoskrnl/include/internal/i386/fpu.h create mode 100644 ntoskrnl/include/internal/i386/ke.h create mode 100644 ntoskrnl/include/internal/i386/mm.h create mode 100644 ntoskrnl/include/internal/i386/ps.h create mode 100644 ntoskrnl/include/internal/i386/segment.h create mode 100644 ntoskrnl/include/internal/id.h create mode 100644 ntoskrnl/include/internal/ifs.h create mode 100644 ntoskrnl/include/internal/io.h create mode 100644 ntoskrnl/include/internal/kd.h create mode 100644 ntoskrnl/include/internal/ke.h create mode 100644 ntoskrnl/include/internal/ldr.h create mode 100644 ntoskrnl/include/internal/mm.h create mode 100644 ntoskrnl/include/internal/module.h create mode 100644 ntoskrnl/include/internal/nt.h create mode 100644 ntoskrnl/include/internal/ntoskrnl.h create mode 100644 ntoskrnl/include/internal/ob.h create mode 100644 ntoskrnl/include/internal/po.h create mode 100644 ntoskrnl/include/internal/pool.h create mode 100644 ntoskrnl/include/internal/port.h create mode 100644 ntoskrnl/include/internal/ps.h create mode 100644 ntoskrnl/include/internal/registry.h create mode 100644 ntoskrnl/include/internal/safe.h create mode 100644 ntoskrnl/include/internal/se.h create mode 100644 ntoskrnl/include/internal/trap.h create mode 100644 ntoskrnl/include/internal/v86m.h create mode 100644 ntoskrnl/include/internal/xhal.h create mode 100644 ntoskrnl/io/.cvsignore create mode 100644 ntoskrnl/io/adapter.c create mode 100644 ntoskrnl/io/arcname.c create mode 100644 ntoskrnl/io/buildirp.c create mode 100644 ntoskrnl/io/cancel.c create mode 100644 ntoskrnl/io/cleanup.c create mode 100644 ntoskrnl/io/cntrller.c create mode 100644 ntoskrnl/io/create.c create mode 100644 ntoskrnl/io/device.c create mode 100644 ntoskrnl/io/dir.c create mode 100644 ntoskrnl/io/driver.c create mode 100644 ntoskrnl/io/errlog.c create mode 100644 ntoskrnl/io/error.c create mode 100644 ntoskrnl/io/event.c create mode 100644 ntoskrnl/io/file.c create mode 100644 ntoskrnl/io/flush.c create mode 100644 ntoskrnl/io/fs.c create mode 100644 ntoskrnl/io/iocomp.c create mode 100644 ntoskrnl/io/ioctrl.c create mode 100644 ntoskrnl/io/iomgr.c create mode 100644 ntoskrnl/io/iowork.c create mode 100644 ntoskrnl/io/irp.c create mode 100644 ntoskrnl/io/lock.c create mode 100644 ntoskrnl/io/mailslot.c create mode 100644 ntoskrnl/io/mdl.c create mode 100644 ntoskrnl/io/npipe.c create mode 100644 ntoskrnl/io/page.c create mode 100644 ntoskrnl/io/parttab.c create mode 100644 ntoskrnl/io/pnpmgr.c create mode 100644 ntoskrnl/io/pnproot.c create mode 100644 ntoskrnl/io/process.c create mode 100644 ntoskrnl/io/queue.c create mode 100644 ntoskrnl/io/resource.c create mode 100644 ntoskrnl/io/rw.c create mode 100644 ntoskrnl/io/share.c create mode 100644 ntoskrnl/io/shutdown.c create mode 100644 ntoskrnl/io/symlink.c create mode 100644 ntoskrnl/io/timer.c create mode 100644 ntoskrnl/io/vpb.c create mode 100644 ntoskrnl/io/xhaldisp.c create mode 100644 ntoskrnl/io/xhaldrv.c create mode 100644 ntoskrnl/kd/.cvsignore create mode 100644 ntoskrnl/kd/dlog.c create mode 100644 ntoskrnl/kd/gdbstub.c create mode 100644 ntoskrnl/kd/kdebug.c create mode 100644 ntoskrnl/kd/mda.c create mode 100644 ntoskrnl/kd/service.c create mode 100644 ntoskrnl/ke/.cvsignore create mode 100644 ntoskrnl/ke/apc.c create mode 100644 ntoskrnl/ke/bug.c create mode 100644 ntoskrnl/ke/catch.c create mode 100644 ntoskrnl/ke/critical.c create mode 100644 ntoskrnl/ke/dpc.c create mode 100644 ntoskrnl/ke/error.c create mode 100644 ntoskrnl/ke/event.c create mode 100644 ntoskrnl/ke/i386/.cvsignore create mode 100644 ntoskrnl/ke/i386/bios.c create mode 100644 ntoskrnl/ke/i386/brkpoint.c create mode 100644 ntoskrnl/ke/i386/bthread.S create mode 100644 ntoskrnl/ke/i386/exp.c create mode 100644 ntoskrnl/ke/i386/fpu.c create mode 100644 ntoskrnl/ke/i386/gdt.c create mode 100644 ntoskrnl/ke/i386/i386-mcount.S create mode 100644 ntoskrnl/ke/i386/idt.c create mode 100644 ntoskrnl/ke/i386/irq.c create mode 100644 ntoskrnl/ke/i386/irqhand.s create mode 100644 ntoskrnl/ke/i386/kernel.c create mode 100644 ntoskrnl/ke/i386/ldt.c create mode 100644 ntoskrnl/ke/i386/multiboot.S create mode 100644 ntoskrnl/ke/i386/stkswitch.S create mode 100644 ntoskrnl/ke/i386/syscall.S create mode 100644 ntoskrnl/ke/i386/thread.c create mode 100644 ntoskrnl/ke/i386/trap.s create mode 100644 ntoskrnl/ke/i386/tskswitch.S create mode 100644 ntoskrnl/ke/i386/tss.c create mode 100644 ntoskrnl/ke/i386/usercall.c create mode 100644 ntoskrnl/ke/i386/usertrap.c create mode 100644 ntoskrnl/ke/i386/v86m.c create mode 100644 ntoskrnl/ke/i386/v86m_sup.S create mode 100644 ntoskrnl/ke/kqueue.c create mode 100644 ntoskrnl/ke/kthread.c create mode 100644 ntoskrnl/ke/main.c create mode 100644 ntoskrnl/ke/mutex.c create mode 100644 ntoskrnl/ke/process.c create mode 100644 ntoskrnl/ke/queue.c create mode 100644 ntoskrnl/ke/sem.c create mode 100644 ntoskrnl/ke/spinlock.c create mode 100644 ntoskrnl/ke/timer.c create mode 100644 ntoskrnl/ke/wait.c create mode 100644 ntoskrnl/ldr/.cvsignore create mode 100644 ntoskrnl/ldr/init.c create mode 100644 ntoskrnl/ldr/loader.c create mode 100644 ntoskrnl/ldr/resource.c create mode 100644 ntoskrnl/ldr/rtl.c create mode 100644 ntoskrnl/ldr/sysdll.c create mode 100644 ntoskrnl/ldr/userldr.c create mode 100644 ntoskrnl/lpc/.cvsignore create mode 100644 ntoskrnl/lpc/close.c create mode 100644 ntoskrnl/lpc/complete.c create mode 100644 ntoskrnl/lpc/connect.c create mode 100644 ntoskrnl/lpc/create.c create mode 100644 ntoskrnl/lpc/listen.c create mode 100644 ntoskrnl/lpc/port.c create mode 100644 ntoskrnl/lpc/query.c create mode 100644 ntoskrnl/lpc/queue.c create mode 100644 ntoskrnl/lpc/receive.c create mode 100644 ntoskrnl/lpc/reply.c create mode 100644 ntoskrnl/lpc/send.c create mode 100644 ntoskrnl/mkconfig.c create mode 100644 ntoskrnl/mm/.cvsignore create mode 100644 ntoskrnl/mm/anonmem.c create mode 100644 ntoskrnl/mm/aspace.c create mode 100644 ntoskrnl/mm/balance.c create mode 100644 ntoskrnl/mm/cont.c create mode 100644 ntoskrnl/mm/drvlck.c create mode 100644 ntoskrnl/mm/freelist.c create mode 100644 ntoskrnl/mm/i386/.cvsignore create mode 100644 ntoskrnl/mm/i386/memsafe.s create mode 100644 ntoskrnl/mm/i386/page.c create mode 100644 ntoskrnl/mm/i386/pfault.c create mode 100644 ntoskrnl/mm/iospace.c create mode 100644 ntoskrnl/mm/kmap.c create mode 100644 ntoskrnl/mm/marea.c create mode 100644 ntoskrnl/mm/mdl.c create mode 100644 ntoskrnl/mm/mm.c create mode 100644 ntoskrnl/mm/mminit.c create mode 100644 ntoskrnl/mm/mpw.c create mode 100644 ntoskrnl/mm/ncache.c create mode 100644 ntoskrnl/mm/npool.c create mode 100644 ntoskrnl/mm/pagefile.c create mode 100644 ntoskrnl/mm/pageop.c create mode 100644 ntoskrnl/mm/pager.c create mode 100644 ntoskrnl/mm/pagfault.c create mode 100644 ntoskrnl/mm/paging.c create mode 100644 ntoskrnl/mm/pool.c create mode 100644 ntoskrnl/mm/ppool.c create mode 100644 ntoskrnl/mm/region.c create mode 100644 ntoskrnl/mm/rmap.c create mode 100644 ntoskrnl/mm/section.c create mode 100644 ntoskrnl/mm/slab.c create mode 100644 ntoskrnl/mm/virtual.c create mode 100644 ntoskrnl/mm/wset.c create mode 100644 ntoskrnl/nls/.cvsignore create mode 100644 ntoskrnl/nls/nls.c create mode 100644 ntoskrnl/nt/.cvsignore create mode 100644 ntoskrnl/nt/channel.c create mode 100644 ntoskrnl/nt/evtpair.c create mode 100644 ntoskrnl/nt/misc.c create mode 100644 ntoskrnl/nt/mutant.c create mode 100644 ntoskrnl/nt/nt.c create mode 100644 ntoskrnl/nt/ntevent.c create mode 100644 ntoskrnl/nt/ntsem.c create mode 100644 ntoskrnl/nt/nttimer.c create mode 100644 ntoskrnl/nt/plugplay.c create mode 100644 ntoskrnl/nt/profile.c create mode 100644 ntoskrnl/nt/vdm.c create mode 100644 ntoskrnl/ntoskrnl.dbg.lnk create mode 100644 ntoskrnl/ntoskrnl.def create mode 100644 ntoskrnl/ntoskrnl.edf create mode 100644 ntoskrnl/ntoskrnl.full.def create mode 100644 ntoskrnl/ntoskrnl.lnk create mode 100644 ntoskrnl/ntoskrnl.mc create mode 100644 ntoskrnl/ntoskrnl.rc create mode 100644 ntoskrnl/ntoskrnl.txt create mode 100644 ntoskrnl/ob/.cvsignore create mode 100644 ntoskrnl/ob/dirobj.c create mode 100644 ntoskrnl/ob/handle.c create mode 100644 ntoskrnl/ob/namespc.c create mode 100644 ntoskrnl/ob/ntobj.c create mode 100644 ntoskrnl/ob/object.c create mode 100644 ntoskrnl/ob/security.c create mode 100644 ntoskrnl/objects/.cvsignore create mode 100644 ntoskrnl/po/.cvsignore create mode 100644 ntoskrnl/po/power.c create mode 100644 ntoskrnl/ps/.cvsignore create mode 100644 ntoskrnl/ps/create.c create mode 100644 ntoskrnl/ps/debug.c create mode 100644 ntoskrnl/ps/idle.c create mode 100644 ntoskrnl/ps/kill.c create mode 100644 ntoskrnl/ps/locale.c create mode 100644 ntoskrnl/ps/process.c create mode 100644 ntoskrnl/ps/psmgr.c create mode 100644 ntoskrnl/ps/suspend.c create mode 100644 ntoskrnl/ps/thread.c create mode 100644 ntoskrnl/ps/tinfo.c create mode 100644 ntoskrnl/ps/w32call.c create mode 100644 ntoskrnl/ps/win32.c create mode 100644 ntoskrnl/rtl/.cvsignore create mode 100644 ntoskrnl/rtl/atom.c create mode 100644 ntoskrnl/rtl/bitmap.c create mode 100644 ntoskrnl/rtl/capture.c create mode 100644 ntoskrnl/rtl/compress.c create mode 100644 ntoskrnl/rtl/ctype.c create mode 100644 ntoskrnl/rtl/dos8dot3.c create mode 100644 ntoskrnl/rtl/error.c create mode 100644 ntoskrnl/rtl/handle.c create mode 100644 ntoskrnl/rtl/i386/.cvsignore create mode 100755 ntoskrnl/rtl/i386/except.s create mode 100755 ntoskrnl/rtl/i386/exception.c create mode 100644 ntoskrnl/rtl/i386/memcpy.c create mode 100644 ntoskrnl/rtl/i386/memset.c create mode 100755 ntoskrnl/rtl/i386/seh.s create mode 100644 ntoskrnl/rtl/largeint.c create mode 100644 ntoskrnl/rtl/mem.c create mode 100644 ntoskrnl/rtl/memchr.c create mode 100644 ntoskrnl/rtl/memcmp.c create mode 100644 ntoskrnl/rtl/memcpy.c create mode 100644 ntoskrnl/rtl/memmove.c create mode 100644 ntoskrnl/rtl/memset.c create mode 100644 ntoskrnl/rtl/message.c create mode 100644 ntoskrnl/rtl/nls.c create mode 100644 ntoskrnl/rtl/purecall.c create mode 100644 ntoskrnl/rtl/qsort.c create mode 100644 ntoskrnl/rtl/regio.c create mode 100644 ntoskrnl/rtl/sprintf.c create mode 100644 ntoskrnl/rtl/stdlib.c create mode 100644 ntoskrnl/rtl/string.c create mode 100644 ntoskrnl/rtl/strtok.c create mode 100644 ntoskrnl/rtl/swprintf.c create mode 100644 ntoskrnl/rtl/time.c create mode 100644 ntoskrnl/rtl/timezone.c create mode 100644 ntoskrnl/rtl/unicode.c create mode 100644 ntoskrnl/rtl/wstring.c create mode 100644 ntoskrnl/se/.cvsignore create mode 100644 ntoskrnl/se/access.c create mode 100644 ntoskrnl/se/acl.c create mode 100644 ntoskrnl/se/lsa.c create mode 100644 ntoskrnl/se/luid.c create mode 100644 ntoskrnl/se/priv.c create mode 100644 ntoskrnl/se/sd.c create mode 100644 ntoskrnl/se/semgr.c create mode 100644 ntoskrnl/se/sid.c create mode 100644 ntoskrnl/se/token.c create mode 100644 rosbin.txt create mode 100644 rules.mak create mode 100644 services/eventlog/.cvsignore create mode 100644 services/eventlog/eventlog.c create mode 100644 services/eventlog/eventlog.h create mode 100644 services/eventlog/eventlog.rc create mode 100644 services/eventlog/logport.c create mode 100644 services/eventlog/makefile create mode 100644 services/rpcss/.cvsignore create mode 100644 services/rpcss/endpoint.c create mode 100644 services/rpcss/makefile create mode 100644 services/rpcss/rpcss.c create mode 100644 services/rpcss/rpcss.h create mode 100644 services/rpcss/rpcss.rc create mode 100644 subsys/csrss/.cvsignore create mode 100644 subsys/csrss/api.h create mode 100644 subsys/csrss/api/.cvsignore create mode 100644 subsys/csrss/api/conio.c create mode 100644 subsys/csrss/api/handle.c create mode 100644 subsys/csrss/api/process.c create mode 100644 subsys/csrss/api/user.c create mode 100644 subsys/csrss/api/wapi.c create mode 100644 subsys/csrss/csrss.c create mode 100644 subsys/csrss/csrss.rc create mode 100644 subsys/csrss/init.c create mode 100644 subsys/csrss/lpcstub.c create mode 100644 subsys/csrss/makefile create mode 100644 subsys/csrss/print.c create mode 100644 subsys/csrss/video.c create mode 100644 subsys/ntvdm/.cvsignore create mode 100644 subsys/ntvdm/makefile create mode 100644 subsys/ntvdm/ntvdm.c create mode 100644 subsys/ntvdm/ntvdm.rc create mode 100644 subsys/smss/.cvsignore create mode 100644 subsys/smss/init.c create mode 100644 subsys/smss/makefile create mode 100644 subsys/smss/smapi.c create mode 100644 subsys/smss/smss.c create mode 100644 subsys/smss/smss.h create mode 100644 subsys/smss/smss.rc create mode 100644 subsys/system/autochk/.cvsignore create mode 100644 subsys/system/autochk/autochk.c create mode 100644 subsys/system/autochk/autochk.rc create mode 100644 subsys/system/autochk/makefile create mode 100644 subsys/system/gstart/.cvsignore create mode 100644 subsys/system/gstart/Makefile create mode 100644 subsys/system/gstart/gstart.c create mode 100644 subsys/system/gstart/gstart.rc create mode 100644 subsys/system/lsass/init.c create mode 100644 subsys/system/lsass/lsasrv.def create mode 100644 subsys/system/lsass/lsass.c create mode 100644 subsys/system/lsass/lsass.rc create mode 100644 subsys/system/lsass/makefile create mode 100644 subsys/system/services/.cvsignore create mode 100644 subsys/system/services/database.c create mode 100644 subsys/system/services/makefile create mode 100644 subsys/system/services/services.c create mode 100644 subsys/system/services/services.h create mode 100644 subsys/system/services/services.rc create mode 100644 subsys/system/shell/.cvsignore create mode 100644 subsys/system/shell/makefile create mode 100644 subsys/system/shell/shell.c create mode 100644 subsys/system/shell/shell.rc create mode 100644 subsys/system/usetup/.cvsignore create mode 100644 subsys/system/usetup/console.c create mode 100644 subsys/system/usetup/console.h create mode 100644 subsys/system/usetup/drivesup.c create mode 100644 subsys/system/usetup/drivesup.h create mode 100644 subsys/system/usetup/makefile create mode 100644 subsys/system/usetup/partlist.c create mode 100644 subsys/system/usetup/partlist.h create mode 100644 subsys/system/usetup/usetup.c create mode 100644 subsys/system/usetup/usetup.h create mode 100644 subsys/system/usetup/usetup.rc create mode 100644 subsys/system/winlogon/.cvsignore create mode 100644 subsys/system/winlogon/makefile create mode 100644 subsys/system/winlogon/winlogon.c create mode 100644 subsys/system/winlogon/winlogon.rc create mode 100644 subsys/win32k/.cvsignore create mode 100644 subsys/win32k/dib/.cvsignore create mode 100644 subsys/win32k/dib/dib.h create mode 100644 subsys/win32k/dib/dib1bpp.c create mode 100644 subsys/win32k/dib/dib24bpp.c create mode 100644 subsys/win32k/dib/dib4bpp.c create mode 100644 subsys/win32k/eng/.cvsignore create mode 100644 subsys/win32k/eng/bitblt.c create mode 100644 subsys/win32k/eng/brush.c create mode 100644 subsys/win32k/eng/brush.h create mode 100644 subsys/win32k/eng/clip.c create mode 100644 subsys/win32k/eng/clip.h create mode 100644 subsys/win32k/eng/copybits.c create mode 100644 subsys/win32k/eng/debug.c create mode 100644 subsys/win32k/eng/device.c create mode 100644 subsys/win32k/eng/handle.c create mode 100644 subsys/win32k/eng/handle.h create mode 100644 subsys/win32k/eng/lineto.c create mode 100644 subsys/win32k/eng/mem.c create mode 100644 subsys/win32k/eng/mouse.c create mode 100644 subsys/win32k/eng/objects.h create mode 100644 subsys/win32k/eng/paint.c create mode 100644 subsys/win32k/eng/palette.c create mode 100644 subsys/win32k/eng/surface.c create mode 100644 subsys/win32k/eng/transblt.c create mode 100644 subsys/win32k/eng/xlate.c create mode 100644 subsys/win32k/freetype/.cvsignore create mode 100644 subsys/win32k/freetype/CHANGES create mode 100644 subsys/win32k/freetype/builds/.cvsignore create mode 100644 subsys/win32k/freetype/builds/ansi/ansi.mk create mode 100644 subsys/win32k/freetype/builds/detect.mk create mode 100644 subsys/win32k/freetype/builds/dos/detect.mk create mode 100644 subsys/win32k/freetype/builds/dos/dos-gcc.mk create mode 100644 subsys/win32k/freetype/builds/freetype.mk create mode 100644 subsys/win32k/freetype/builds/mac/ftlib.prj create mode 100644 subsys/win32k/freetype/builds/mac/readme create mode 100644 subsys/win32k/freetype/builds/modules.mk create mode 100644 subsys/win32k/freetype/builds/os2/detect.mk create mode 100644 subsys/win32k/freetype/builds/os2/os2-dev.mk create mode 100644 subsys/win32k/freetype/builds/os2/os2-gcc.mk create mode 100644 subsys/win32k/freetype/builds/unix/aclocal.m4 create mode 100644 subsys/win32k/freetype/builds/unix/config.guess create mode 100644 subsys/win32k/freetype/builds/unix/config.sub create mode 100644 subsys/win32k/freetype/builds/unix/configure create mode 100644 subsys/win32k/freetype/builds/unix/configure.in create mode 100644 subsys/win32k/freetype/builds/unix/detect.mk create mode 100644 subsys/win32k/freetype/builds/unix/ftconfig.in create mode 100644 subsys/win32k/freetype/builds/unix/ftsystem.c create mode 100644 subsys/win32k/freetype/builds/unix/install-sh create mode 100644 subsys/win32k/freetype/builds/unix/ltconfig create mode 100644 subsys/win32k/freetype/builds/unix/ltmain.sh create mode 100644 subsys/win32k/freetype/builds/unix/mkinstalldirs create mode 100644 subsys/win32k/freetype/builds/unix/unix.in create mode 100644 subsys/win32k/freetype/builds/win32/detect.mk create mode 100644 subsys/win32k/freetype/builds/win32/w32-dev.mk create mode 100644 subsys/win32k/freetype/builds/win32/w32-gcc.mk create mode 100644 subsys/win32k/freetype/builds/win32/w32-icc.mk create mode 100644 subsys/win32k/freetype/builds/win32/w32-lcc.mk create mode 100644 subsys/win32k/freetype/builds/win32/w32-vcc.mk create mode 100644 subsys/win32k/freetype/ctype.c create mode 100644 subsys/win32k/freetype/docs/build create mode 100644 subsys/win32k/freetype/docs/design/build-system.html create mode 100644 subsys/win32k/freetype/docs/design/demo-programs.png create mode 100644 subsys/win32k/freetype/docs/design/drivers-list.png create mode 100644 subsys/win32k/freetype/docs/design/index.html create mode 100644 subsys/win32k/freetype/docs/design/io-frames.html create mode 100644 subsys/win32k/freetype/docs/design/library-compilation.png create mode 100644 subsys/win32k/freetype/docs/design/logo1.png create mode 100644 subsys/win32k/freetype/docs/design/objects_diagram.png create mode 100644 subsys/win32k/freetype/docs/design/objects_diagram2.png create mode 100644 subsys/win32k/freetype/docs/design/platform-detection.png create mode 100644 subsys/win32k/freetype/docs/design/system-interface.html create mode 100644 subsys/win32k/freetype/docs/docmaker.py create mode 100644 subsys/win32k/freetype/docs/freetype2.html create mode 100644 subsys/win32k/freetype/docs/ft2faq.html create mode 100644 subsys/win32k/freetype/docs/glnames.py create mode 100644 subsys/win32k/freetype/docs/glyphs/Image1.png create mode 100644 subsys/win32k/freetype/docs/glyphs/Image2.png create mode 100644 subsys/win32k/freetype/docs/glyphs/Image3.png create mode 100644 subsys/win32k/freetype/docs/glyphs/Image4.png create mode 100644 subsys/win32k/freetype/docs/glyphs/bbox1.png create mode 100644 subsys/win32k/freetype/docs/glyphs/bbox2.png create mode 100644 subsys/win32k/freetype/docs/glyphs/body_comparison.png create mode 100644 subsys/win32k/freetype/docs/glyphs/bravo_kerned.png create mode 100644 subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png create mode 100644 subsys/win32k/freetype/docs/glyphs/clipping.png create mode 100644 subsys/win32k/freetype/docs/glyphs/down_flow.png create mode 100644 subsys/win32k/freetype/docs/glyphs/grid_1.png create mode 100644 subsys/win32k/freetype/docs/glyphs/index.html create mode 100644 subsys/win32k/freetype/docs/glyphs/points_conic.png create mode 100644 subsys/win32k/freetype/docs/glyphs/points_conic2.png create mode 100644 subsys/win32k/freetype/docs/glyphs/points_cubic.png create mode 100644 subsys/win32k/freetype/docs/glyphs/points_segment.png create mode 100644 subsys/win32k/freetype/docs/glyphs/twlewis1.png create mode 100644 subsys/win32k/freetype/docs/glyphs/twlewis2.png create mode 100644 subsys/win32k/freetype/docs/glyphs/up_flow.png create mode 100644 subsys/win32k/freetype/docs/tutorial/index.html create mode 100644 subsys/win32k/freetype/docs/tutorial/step1.html create mode 100644 subsys/win32k/freetype/docs/tutorial/step2.html create mode 100644 subsys/win32k/freetype/grfont.c create mode 100644 subsys/win32k/freetype/grfont.h create mode 100644 subsys/win32k/freetype/include/freetype/config/ftconfig.h create mode 100644 subsys/win32k/freetype/include/freetype/config/ftmodule.h create mode 100644 subsys/win32k/freetype/include/freetype/config/ftoption.h create mode 100644 subsys/win32k/freetype/include/freetype/freetype.h create mode 100644 subsys/win32k/freetype/include/freetype/ftbbox.h create mode 100644 subsys/win32k/freetype/include/freetype/fterrors.h create mode 100644 subsys/win32k/freetype/include/freetype/ftglyph.h create mode 100644 subsys/win32k/freetype/include/freetype/ftimage.h create mode 100644 subsys/win32k/freetype/include/freetype/ftmm.h create mode 100644 subsys/win32k/freetype/include/freetype/ftmodule.h create mode 100644 subsys/win32k/freetype/include/freetype/ftnames.h create mode 100644 subsys/win32k/freetype/include/freetype/ftoutln.h create mode 100644 subsys/win32k/freetype/include/freetype/ftrender.h create mode 100644 subsys/win32k/freetype/include/freetype/ftsystem.h create mode 100644 subsys/win32k/freetype/include/freetype/fttypes.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/autohint.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftcalc.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftdebug.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftdriver.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftextend.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftlist.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftmemory.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftobjs.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/ftstream.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/psnames.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/sfnt.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/t1errors.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/t1types.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/t2errors.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/t2types.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/tterrors.h create mode 100644 subsys/win32k/freetype/include/freetype/internal/tttypes.h create mode 100644 subsys/win32k/freetype/include/freetype/t1tables.h create mode 100644 subsys/win32k/freetype/include/freetype/ttnameid.h create mode 100644 subsys/win32k/freetype/include/freetype/tttables.h create mode 100644 subsys/win32k/freetype/include/freetype/tttags.h create mode 100644 subsys/win32k/freetype/license.txt create mode 100644 subsys/win32k/freetype/obj/README create mode 100644 subsys/win32k/freetype/src/autohint/.cvsignore create mode 100644 subsys/win32k/freetype/src/autohint/CatharonLicense.txt create mode 100644 subsys/win32k/freetype/src/autohint/ahangles.c create mode 100644 subsys/win32k/freetype/src/autohint/ahangles.h create mode 100644 subsys/win32k/freetype/src/autohint/ahglobal.c create mode 100644 subsys/win32k/freetype/src/autohint/ahglobal.h create mode 100644 subsys/win32k/freetype/src/autohint/ahglyph.c create mode 100644 subsys/win32k/freetype/src/autohint/ahglyph.h create mode 100644 subsys/win32k/freetype/src/autohint/ahhint.c create mode 100644 subsys/win32k/freetype/src/autohint/ahhint.h create mode 100644 subsys/win32k/freetype/src/autohint/ahloader.h create mode 100644 subsys/win32k/freetype/src/autohint/ahmodule.c create mode 100644 subsys/win32k/freetype/src/autohint/ahmodule.h create mode 100644 subsys/win32k/freetype/src/autohint/ahoptim.c create mode 100644 subsys/win32k/freetype/src/autohint/ahoptim.h create mode 100644 subsys/win32k/freetype/src/autohint/ahtypes.h create mode 100644 subsys/win32k/freetype/src/autohint/autohint.c create mode 100644 subsys/win32k/freetype/src/autohint/mather.py create mode 100644 subsys/win32k/freetype/src/autohint/module.mk create mode 100644 subsys/win32k/freetype/src/autohint/rules.mk create mode 100644 subsys/win32k/freetype/src/base/.cvsignore create mode 100644 subsys/win32k/freetype/src/base/ftbase.c create mode 100644 subsys/win32k/freetype/src/base/ftcalc.c create mode 100644 subsys/win32k/freetype/src/base/ftdebug.c create mode 100644 subsys/win32k/freetype/src/base/ftextend.c create mode 100644 subsys/win32k/freetype/src/base/ftglyph.c create mode 100644 subsys/win32k/freetype/src/base/ftinit.c create mode 100644 subsys/win32k/freetype/src/base/ftlist.c create mode 100644 subsys/win32k/freetype/src/base/ftmm.c create mode 100644 subsys/win32k/freetype/src/base/ftnames.c create mode 100644 subsys/win32k/freetype/src/base/ftobjs.c create mode 100644 subsys/win32k/freetype/src/base/ftoutln.c create mode 100644 subsys/win32k/freetype/src/base/ftstream.c create mode 100644 subsys/win32k/freetype/src/base/ftsystem.c create mode 100644 subsys/win32k/freetype/src/base/rules.mk create mode 100644 subsys/win32k/freetype/src/cff/.cvsignore create mode 100644 subsys/win32k/freetype/src/cff/cff.c create mode 100644 subsys/win32k/freetype/src/cff/module.mk create mode 100644 subsys/win32k/freetype/src/cff/rules.mk create mode 100644 subsys/win32k/freetype/src/cff/t2driver.c create mode 100644 subsys/win32k/freetype/src/cff/t2driver.h create mode 100644 subsys/win32k/freetype/src/cff/t2gload.c create mode 100644 subsys/win32k/freetype/src/cff/t2gload.h create mode 100644 subsys/win32k/freetype/src/cff/t2load.c create mode 100644 subsys/win32k/freetype/src/cff/t2load.h create mode 100644 subsys/win32k/freetype/src/cff/t2objs.c create mode 100644 subsys/win32k/freetype/src/cff/t2objs.h create mode 100644 subsys/win32k/freetype/src/cff/t2parse.c create mode 100644 subsys/win32k/freetype/src/cff/t2parse.h create mode 100644 subsys/win32k/freetype/src/cff/t2tokens.h create mode 100644 subsys/win32k/freetype/src/cid/.cvsignore create mode 100644 subsys/win32k/freetype/src/cid/cidafm.c create mode 100644 subsys/win32k/freetype/src/cid/cidafm.h create mode 100644 subsys/win32k/freetype/src/cid/cidgload.c create mode 100644 subsys/win32k/freetype/src/cid/cidgload.h create mode 100644 subsys/win32k/freetype/src/cid/cidload.c create mode 100644 subsys/win32k/freetype/src/cid/cidload.h create mode 100644 subsys/win32k/freetype/src/cid/cidobjs.c create mode 100644 subsys/win32k/freetype/src/cid/cidobjs.h create mode 100644 subsys/win32k/freetype/src/cid/cidparse.c create mode 100644 subsys/win32k/freetype/src/cid/cidparse.h create mode 100644 subsys/win32k/freetype/src/cid/cidriver.c create mode 100644 subsys/win32k/freetype/src/cid/cidriver.h create mode 100644 subsys/win32k/freetype/src/cid/cidtokens.h create mode 100644 subsys/win32k/freetype/src/cid/module.mk create mode 100644 subsys/win32k/freetype/src/cid/rules.mk create mode 100644 subsys/win32k/freetype/src/cid/type1cid.c create mode 100644 subsys/win32k/freetype/src/macfond/.cvsignore create mode 100644 subsys/win32k/freetype/src/macfond/fonddrvr.c create mode 100644 subsys/win32k/freetype/src/otlayout/.cvsignore create mode 100644 subsys/win32k/freetype/src/otlayout/oltypes.c create mode 100644 subsys/win32k/freetype/src/otlayout/oltypes.h create mode 100644 subsys/win32k/freetype/src/psnames/.cvsignore create mode 100644 subsys/win32k/freetype/src/psnames/module.mk create mode 100644 subsys/win32k/freetype/src/psnames/psmodule.c create mode 100644 subsys/win32k/freetype/src/psnames/psmodule.h create mode 100644 subsys/win32k/freetype/src/psnames/psnames.c create mode 100644 subsys/win32k/freetype/src/psnames/pstables.h create mode 100644 subsys/win32k/freetype/src/psnames/rules.mk create mode 100644 subsys/win32k/freetype/src/raster1/.cvsignore create mode 100644 subsys/win32k/freetype/src/raster1/ftraster.c create mode 100644 subsys/win32k/freetype/src/raster1/ftraster.h create mode 100644 subsys/win32k/freetype/src/raster1/ftrend1.c create mode 100644 subsys/win32k/freetype/src/raster1/ftrend1.h create mode 100644 subsys/win32k/freetype/src/raster1/module.mk create mode 100644 subsys/win32k/freetype/src/raster1/raster1.c create mode 100644 subsys/win32k/freetype/src/raster1/rules.mk create mode 100644 subsys/win32k/freetype/src/sfnt/.cvsignore create mode 100644 subsys/win32k/freetype/src/sfnt/module.mk create mode 100644 subsys/win32k/freetype/src/sfnt/rules.mk create mode 100644 subsys/win32k/freetype/src/sfnt/sfdriver.c create mode 100644 subsys/win32k/freetype/src/sfnt/sfdriver.h create mode 100644 subsys/win32k/freetype/src/sfnt/sfnt.c create mode 100644 subsys/win32k/freetype/src/sfnt/sfobjs.c create mode 100644 subsys/win32k/freetype/src/sfnt/sfobjs.h create mode 100644 subsys/win32k/freetype/src/sfnt/ttcmap.c create mode 100644 subsys/win32k/freetype/src/sfnt/ttcmap.h create mode 100644 subsys/win32k/freetype/src/sfnt/ttload.c create mode 100644 subsys/win32k/freetype/src/sfnt/ttload.h create mode 100644 subsys/win32k/freetype/src/sfnt/ttpost.c create mode 100644 subsys/win32k/freetype/src/sfnt/ttpost.h create mode 100644 subsys/win32k/freetype/src/sfnt/ttsbit.c create mode 100644 subsys/win32k/freetype/src/sfnt/ttsbit.h create mode 100644 subsys/win32k/freetype/src/smooth/.cvsignore create mode 100644 subsys/win32k/freetype/src/smooth/ftgrays.c create mode 100644 subsys/win32k/freetype/src/smooth/ftgrays.h create mode 100644 subsys/win32k/freetype/src/smooth/ftsmooth.c create mode 100644 subsys/win32k/freetype/src/smooth/ftsmooth.h create mode 100644 subsys/win32k/freetype/src/smooth/module.mk create mode 100644 subsys/win32k/freetype/src/smooth/rules.mk create mode 100644 subsys/win32k/freetype/src/smooth/smooth.c create mode 100644 subsys/win32k/freetype/src/truetype/.cvsignore create mode 100644 subsys/win32k/freetype/src/truetype/module.mk create mode 100644 subsys/win32k/freetype/src/truetype/rules.mk create mode 100644 subsys/win32k/freetype/src/truetype/truetype.c create mode 100644 subsys/win32k/freetype/src/truetype/ttdriver.c create mode 100644 subsys/win32k/freetype/src/truetype/ttdriver.h create mode 100644 subsys/win32k/freetype/src/truetype/ttgload.c create mode 100644 subsys/win32k/freetype/src/truetype/ttgload.h create mode 100644 subsys/win32k/freetype/src/truetype/ttinterp.c create mode 100644 subsys/win32k/freetype/src/truetype/ttinterp.h create mode 100644 subsys/win32k/freetype/src/truetype/ttobjs.c create mode 100644 subsys/win32k/freetype/src/truetype/ttobjs.h create mode 100644 subsys/win32k/freetype/src/truetype/ttpload.c create mode 100644 subsys/win32k/freetype/src/truetype/ttpload.h create mode 100644 subsys/win32k/freetype/src/type1/.cvsignore create mode 100644 subsys/win32k/freetype/src/type1/module.mk0 create mode 100644 subsys/win32k/freetype/src/type1/rules.mk0 create mode 100644 subsys/win32k/freetype/src/type1/t1afm.c create mode 100644 subsys/win32k/freetype/src/type1/t1afm.h create mode 100644 subsys/win32k/freetype/src/type1/t1driver.c create mode 100644 subsys/win32k/freetype/src/type1/t1driver.h create mode 100644 subsys/win32k/freetype/src/type1/t1gload.c create mode 100644 subsys/win32k/freetype/src/type1/t1gload.h create mode 100644 subsys/win32k/freetype/src/type1/t1hinter.c create mode 100644 subsys/win32k/freetype/src/type1/t1hinter.h create mode 100644 subsys/win32k/freetype/src/type1/t1load.c create mode 100644 subsys/win32k/freetype/src/type1/t1load.h create mode 100644 subsys/win32k/freetype/src/type1/t1objs.c create mode 100644 subsys/win32k/freetype/src/type1/t1objs.h create mode 100644 subsys/win32k/freetype/src/type1/t1parse.c create mode 100644 subsys/win32k/freetype/src/type1/t1parse.h create mode 100644 subsys/win32k/freetype/src/type1/t1tokens.c create mode 100644 subsys/win32k/freetype/src/type1/t1tokens.h create mode 100644 subsys/win32k/freetype/src/type1/type1.c create mode 100644 subsys/win32k/freetype/src/type1z/.cvsignore create mode 100644 subsys/win32k/freetype/src/type1z/Readme.txt create mode 100644 subsys/win32k/freetype/src/type1z/module.mk create mode 100644 subsys/win32k/freetype/src/type1z/rules.mk create mode 100644 subsys/win32k/freetype/src/type1z/type1z.c create mode 100644 subsys/win32k/freetype/src/type1z/z1afm.c create mode 100644 subsys/win32k/freetype/src/type1z/z1afm.h create mode 100644 subsys/win32k/freetype/src/type1z/z1driver.c create mode 100644 subsys/win32k/freetype/src/type1z/z1driver.h create mode 100644 subsys/win32k/freetype/src/type1z/z1gload.c create mode 100644 subsys/win32k/freetype/src/type1z/z1gload.h create mode 100644 subsys/win32k/freetype/src/type1z/z1load.c create mode 100644 subsys/win32k/freetype/src/type1z/z1load.h create mode 100644 subsys/win32k/freetype/src/type1z/z1objs.c create mode 100644 subsys/win32k/freetype/src/type1z/z1objs.h create mode 100644 subsys/win32k/freetype/src/type1z/z1parse.c create mode 100644 subsys/win32k/freetype/src/type1z/z1parse.h create mode 100644 subsys/win32k/freetype/src/type1z/z1tokens.h create mode 100644 subsys/win32k/freetype/src/winfonts/.cvsignore create mode 100644 subsys/win32k/freetype/src/winfonts/module.mk create mode 100644 subsys/win32k/freetype/src/winfonts/rules.mk create mode 100644 subsys/win32k/freetype/src/winfonts/winfnt.c create mode 100644 subsys/win32k/freetype/src/winfonts/winfnt.h create mode 100644 subsys/win32k/include/callback.h create mode 100644 subsys/win32k/include/class.h create mode 100644 subsys/win32k/include/copybits.h create mode 100644 subsys/win32k/include/dce.h create mode 100644 subsys/win32k/include/dib.h create mode 100644 subsys/win32k/include/eng.h create mode 100644 subsys/win32k/include/error.h create mode 100644 subsys/win32k/include/guicheck.h create mode 100644 subsys/win32k/include/input.h create mode 100644 subsys/win32k/include/mouse.h create mode 100644 subsys/win32k/include/msgqueue.h create mode 100644 subsys/win32k/include/object.h create mode 100644 subsys/win32k/include/paint.h create mode 100644 subsys/win32k/include/painting.h create mode 100644 subsys/win32k/include/palette.h create mode 100644 subsys/win32k/include/rect.h create mode 100644 subsys/win32k/include/surface.h create mode 100644 subsys/win32k/include/window.h create mode 100644 subsys/win32k/include/winpos.h create mode 100644 subsys/win32k/include/winsta.h create mode 100644 subsys/win32k/ldr/.cvsignore create mode 100644 subsys/win32k/ldr/loader.c create mode 100644 subsys/win32k/main/.cvsignore create mode 100644 subsys/win32k/main/dllmain.c create mode 100644 subsys/win32k/main/svctabm.c create mode 100644 subsys/win32k/makefile create mode 100644 subsys/win32k/misc/.cvsignore create mode 100644 subsys/win32k/misc/driver.c create mode 100644 subsys/win32k/misc/error.c create mode 100644 subsys/win32k/misc/math.c create mode 100644 subsys/win32k/misc/object.c create mode 100644 subsys/win32k/ntuser/.cvsignore create mode 100644 subsys/win32k/ntuser/callback.c create mode 100644 subsys/win32k/ntuser/class.c create mode 100644 subsys/win32k/ntuser/guicheck.c create mode 100644 subsys/win32k/ntuser/hook.c create mode 100644 subsys/win32k/ntuser/input.c create mode 100644 subsys/win32k/ntuser/keyboard.c create mode 100644 subsys/win32k/ntuser/message.c create mode 100644 subsys/win32k/ntuser/metric.c create mode 100644 subsys/win32k/ntuser/msgqueue.c create mode 100644 subsys/win32k/ntuser/painting.c create mode 100644 subsys/win32k/ntuser/prop.c create mode 100644 subsys/win32k/ntuser/stubs.c create mode 100644 subsys/win32k/ntuser/userobj.c create mode 100644 subsys/win32k/ntuser/windc.c create mode 100644 subsys/win32k/ntuser/window.c create mode 100644 subsys/win32k/ntuser/winpos.c create mode 100644 subsys/win32k/ntuser/winsta.c create mode 100644 subsys/win32k/objects/.cvsignore create mode 100644 subsys/win32k/objects/bezier.c create mode 100644 subsys/win32k/objects/bitmaps.c create mode 100644 subsys/win32k/objects/brush.c create mode 100644 subsys/win32k/objects/cliprgn.c create mode 100644 subsys/win32k/objects/color.c create mode 100644 subsys/win32k/objects/coord.c create mode 100644 subsys/win32k/objects/dc.c create mode 100644 subsys/win32k/objects/dib.c create mode 100644 subsys/win32k/objects/fillshap.c create mode 100644 subsys/win32k/objects/font.c create mode 100644 subsys/win32k/objects/gdiobj.c create mode 100644 subsys/win32k/objects/icm.c create mode 100644 subsys/win32k/objects/line.c create mode 100644 subsys/win32k/objects/metafile.c create mode 100644 subsys/win32k/objects/objconv.c create mode 100644 subsys/win32k/objects/paint.c create mode 100644 subsys/win32k/objects/palette.c create mode 100644 subsys/win32k/objects/path.c create mode 100644 subsys/win32k/objects/pen.c create mode 100644 subsys/win32k/objects/print.c create mode 100644 subsys/win32k/objects/rect.c create mode 100644 subsys/win32k/objects/region.c create mode 100644 subsys/win32k/objects/text.c create mode 100644 subsys/win32k/objects/wingl.c create mode 100644 subsys/win32k/stubs/.cvsignore create mode 100644 subsys/win32k/stubs/stubs.c create mode 100644 subsys/win32k/win32k.def create mode 100644 subsys/win32k/win32k.edf create mode 100644 subsys/win32k/win32k.rc create mode 100644 system.hiv create mode 100644 tools/.cvsignore create mode 100644 tools/Makefile create mode 100644 tools/buildno.c create mode 100644 tools/config.mk create mode 100644 tools/create_nls/Makefile create mode 100644 tools/create_nls/Readme create mode 100644 tools/create_nls/create_nls.c create mode 100644 tools/create_nls/unicode.org/.cvsignore create mode 100644 tools/depend.mk create mode 100644 tools/depends.c create mode 100644 tools/helper.mk create mode 100644 tools/mkconfig.c create mode 100644 tools/rcopy.c create mode 100644 tools/rdel.c create mode 100644 tools/rmkdir.c create mode 100644 tools/rrmdir.c create mode 100644 tools/rsym.c create mode 100644 tools/wmc/.cvsignore create mode 100644 tools/wmc/config.h create mode 100644 tools/wmc/getopt.c create mode 100644 tools/wmc/getopt.h create mode 100644 tools/wmc/lang.c create mode 100644 tools/wmc/lang.h create mode 100644 tools/wmc/language.c create mode 100644 tools/wmc/makefile create mode 100644 tools/wmc/makefile.in create mode 100644 tools/wmc/mcl.c create mode 100644 tools/wmc/mcy.y create mode 100644 tools/wmc/misc.c create mode 100644 tools/wmc/utils.c create mode 100644 tools/wmc/utils.h create mode 100644 tools/wmc/windows.h create mode 100644 tools/wmc/wmc.c create mode 100644 tools/wmc/wmc.h create mode 100644 tools/wmc/wmc.man create mode 100644 tools/wmc/wmctypes.h create mode 100644 tools/wmc/write.c create mode 100644 tools/wmc/write.h create mode 100644 tools/wmc/y_tab.c create mode 100644 tools/wmc/y_tab.h diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..80ccb71 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,18 @@ +dist +reactos +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..8a322d4 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,4 @@ +directory /mnt/windows/CvsHome/reactos/ntoskrnl +symbol-file ntoskrnl/ntoskrnl.nostrip.exe -mapped +set remotebaud 115200 +target remote com2 diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..dc63aac --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/CREDITS b/CREDITS new file mode 100644 index 0000000..9184dbb --- /dev/null +++ b/CREDITS @@ -0,0 +1,41 @@ +In no particular order + +Rex Jolliff (rex@lvcablemodem.com) +Boudewijn Dekker (ariadne@xs4all.nl) +Eric Kohl (ekohl@rz-online.de) +Emanuele Aliberti (ea@iol.it) +David Welch (welch@cwcom.net) +Iwan Fatahi (i_fatahi@hotmail.com) +Robert Bergkvist (fragdance@hotmail.com) +Victor Kirhenshtein (sauros@iname.com) +Jason Filby (jasonfilby@yahoo.com) +Brian Palmer (brianp@sginet.com) +Phillip Susi (phreak@iag.net) +Paolo Pantaleo (paolopan@freemail.it) +Casper S. Hornstrup (chorns@users.sourceforge.net) + +Source and inspiration from + +WINE (http://www.winehq.com) +WinFree (http://www.stack.nl/~onno/win32/) +Linux (http://www.kernel.org) + +References (Rex's at least) + +Baker, Art. The Windows NT Device Driver Book. Prentice Hall, 1997. +Borate, Dabak & Phadke. Undocumented Windows NT. M&T Books, 1999. +Brain, Marshall. Win32 System Services. Prentice Hall, 1996. +Cant, Chris. Writing Windows WDM Device Drivers. R&D Books, 1999. +Canton & Sanchez. IBM Microcomputers: A Programmer's Handbook. McGraw Hill, 1990. +Davis & Wallace. Windows Undocumented File Formats. R&D Books, 1997. +Mason & Viscarola. Windows NT Device Driver Development. Macmillan, 1999. +Mitchell, Stan. Inside the Windows 95 File System. O'Reilly, 1997. +Murray, James D. Windows NT Event Logging. O'Reilly, 1998. +Nagar, Rajeev. Windows NT File System Internals. O'Reilly, 1997. +Osbourne, Sandra. Windows NT Registry: A Settings Reference. New Riders, 1998. +Pietrek, Matt. Windows 95 System Programming Secrets. IDG, 1995. +Richter, Jeffery. Advanced Windows, 3rd ed. Microsoft, 1997. +Simon, Richard J. Windows NT Win32 API Superbible. Waite Group, 1996. +Solomon, David A. Inside Windows NT, 2nd Ed. Microsoft, 1998. +"The NT Insider." Open Systems Resources, 1999-2000. + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..87c9dfa --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1093 @@ +2002-10-26 Casper S. Hornstrup + + * lib/msvcrt/except/seh.s: Fix end-of-line formatting. + * lib/ntdll/rtl/i386/exception.c: Ditto. + * lib/ntdll/rtl/i386/except.s: Ditto. + * ntoskrnl/rtl/i386/except.s: Ditto. + * ntoskrnl/rtl/i386/seh.s: Ditto. + +2002-10-26 Casper S. Hornstrup + + * lib/msvcrt/Makefile (OBJECTS_EXCEPT): Add except/seh.o; Remove + except/exhand3.o. + * lib/msvcrt/except/exhand2.c (MsvcrtDebug): New function. + * lib/msvcrt/except/unwind.c (PEXCEPTION_FRAME): Remove. + (_global_unwind2): Correct prototype. + * lib/ntdll/makefile (RTL_I386_OBJECTS, ARCH_OBJECTS): New groups. + (TARGET_OBJECTS): Add ARCH_OBJECTS group. + * lib/ntdll/rtl/exception.c (KiUserExceptionDispatcher): Set + NumberParameters in exception record. + (RtlRaiseStatus): Remove. + * ntoskrnl/Makefile (OBJECTS_RTL): Remove rtl/seh.o. + (OBJECTS_RTL_I386): Add rtl/i386/except.o, rtl/i386/exception.o, and + rtl/i386/seh.o. + * ntoskrnl/ke/catch.c (RtlpExecuteHandlerForException, + RtlpDumpExceptionRegistrations, RtlpDispatchException, + RtlpExecuteHandler, RtlpExceptionHandler, RtlpUnwindHandler, + RtlpExecuteHandlerForException, RtlpExecuteHandlerForUnwind, + RtlUnwind): Remove. + (RtlpDispatchException): Add prototype. + * ntoskrnl/ke/i386/usertrap.c (ExceptionTypeStrings): Remove. + * ntoskrnl/ps/create.c (PsCreateTeb): Mark end of exception + registration list. + * tools/helper.mk (TARGET_ASFLAGS): Add -g if DBG = 1. + * lib/msvcrt/except/exhand3.c: Remove. + * ntoskrnl/rtl/seh.c: Ditto. + * lib/msvcrt/except/seh.s: New file. + * lib/ntdll/rtl/i386/except.s: Ditto. + * lib/ntdll/rtl/i386/exception.c: Ditto. + * ntoskrnl/rtl/i386/except.s: Ditto. + * ntoskrnl/rtl/i386/exception.c: Ditto. + * ntoskrnl/rtl/i386/seh.s: Ditto. + +2002-10-26 Casper S. Hornstrup + + * lib/kernel32/process/create.c (_except_handler): New function. + (BaseProcessStart): Ditto. + (KlCreateFirstThread): Return INVALID_HANDLE_VALUE on error; Call + BaseProcessStart() before process entry point. + * lib/kernel32/thread/thread.c (_except_handler): New function. + (ThreadStartup): Protect thread using SEH constructs. + +2002-10-26 Casper S. Hornstrup + + * include/ddk/zw.h (NtProcessStartup): Use standard calling convention. + * subsys/csrss/csrss.c (NtProcessStartup): Ditto. + * subsys/smss/smss.c (NtProcessStartup): Ditto. + * subsys/system/autochk/autochk.c (NtProcessStartup): Ditto. + * subsys/system/usetup/usetup.c (NtProcessStartup): Ditto. + +2002-10-25 Casper S. Hornstrup + + * apps/tests/tokentest/tokentest.c (ROS_ACE_HEADER): Move field + AccessMask ... + (ROS_ACE): ... here. + (DisplayDacl): Make pAce an ROS_ACE*; Use new path for AceType; Use + sizeof(ACE) instead of sizeof(ACE_HEADER). + * include/ntos/security.h (ACE_HEADER): Move field AccessMask ... + (ACE): ... here. + * lib/ntdll/rtl/acl.c: Use new path for AccessMask. + * ntoskrnl/se/semgr.c: Ditto. + * ntoskrnl/se/acl.c (SepInitDACLs): Use new path for AccessMask; Use + sizeof(ACE) instead of sizeof(ACE_HEADER). + * ntoskrnl/se/token.c (SepCreateSystemProcessToken): Use sizeof(ACE) + instead of sizeof(ACE_HEADER). + +2002-10-20 Casper S. Hornstrup + + * include/napi/teb.h (RTL_USER_PROCESS_PARAMETERS): Use field names + as described in Windows NT/2000 Native API Reference. + * lib/kernel32/file/file.c: Use new field names. + * lib/kernel32/misc/console.c: Ditto. + * lib/kernel32/process/create.c: Ditto. + * lib/kernel32/process/proc.c: Ditto. + * lib/ntdll/rtl/path.c: Ditto. + * lib/ntdll/rtl/ppb.c: Ditto. + * lib/ntdll/rtl/process.c: Ditto. + +2002-10-19 Casper S. Hornstrup + + * include/ntos.h: Include relevant files. + * include/internal/ke.h: Include files relative to + ntoskrnl/include. + * include/internal/arch/ke.h: Ditto. + +2002-10-01 Casper S. Hornstrup + + * drivers/dd/floppy/floppy.c: Changed PAGESIZE to PAGE_SIZE. + * drivers/fs/cdfs/fcb.c: Ditto. + * drivers/fs/cdfs/fsctl.c: Ditto. + * drivers/fs/cdfs/rw.c: Ditto. + * drivers/fs/ext2/dir.c: Ditto. + * drivers/fs/ext2/inode.c: Ditto. + * drivers/fs/ext2/rw.c: Ditto. + * drivers/fs/ext2/super.c: Ditto. + * drivers/fs/minix/blockdev.c: Ditto. + * drivers/fs/minix/cache.c: Ditto. + * drivers/fs/minix/inode.c: Ditto. + * drivers/fs/minix/rw.c: Ditto. + * drivers/fs/ntfs/fcb.c: Ditto. + * drivers/fs/ntfs/ntfs.h: Ditto. + * drivers/fs/vfat/create.c: Ditto. + * drivers/fs/vfat/direntry.c: Ditto. + * drivers/fs/vfat/dirwr.c: Ditto. + * drivers/fs/vfat/fat.c: Ditto. + * drivers/fs/vfat/fcb.c: Ditto. + * drivers/fs/vfat/fsctl.c: Ditto. + * drivers/fs/vfat/rw.c: Ditto. + * drivers/storage/class2/class2.c: Ditto. + * drivers/storage/scsiport/scsiport.c: Ditto. + * hal/halx86/adapter.c: Ditto. + * hal/halx86/mp.c: Ditto. + * include/ddk/mmfuncs.h: Ditto. + * include/ddk/mmtypes.h: Ditto. + * include/ddk/i386/pagesize.h: Ditto. + * include/ntdll/pagesize.h: Ditto. + * lib/kernel32/process/create.c: Ditto. + * lib/kernel32/thread/thread.c: Ditto. + * lib/ntdll/ldr/utils.c: Ditto. + * lib/ntdll/rtl/env.c: Ditto. + * lib/ntdll/rtl/heap.c: Ditto. + * lib/ntdll/rtl/ppb.c: Ditto. + * lib/ntdll/rtl/process.c: Ditto. + * lib/ntdll/rtl/thread.c: Ditto. + * ntoskrnl/cc/copy.c: Ditto. + * ntoskrnl/cc/view.c: Ditto. + * ntoskrnl/ex/sysinfo.c: Ditto. + * ntoskrnl/include/internal/i386/mm.h: Ditto. + * ntoskrnl/io/mdl.c: Ditto. + * ntoskrnl/ke/kthread.c: Ditto. + * ntoskrnl/ke/i386/kernel.c: Ditto. + * ntoskrnl/ldr/init.c: Ditto. + * ntoskrnl/ldr/loader.c: Ditto. + * ntoskrnl/mm/anonmem.c: Ditto. + * ntoskrnl/mm/cont.c: Ditto. + * ntoskrnl/mm/freelist.c: Ditto. + * ntoskrnl/mm/iospace.c: Ditto. + * ntoskrnl/mm/kmap.c: Ditto. + * ntoskrnl/mm/marea.c: Ditto. + * ntoskrnl/mm/mdl.c: Ditto. + * ntoskrnl/mm/mminit.c: Ditto. + * ntoskrnl/mm/ncache.c: Ditto. + * ntoskrnl/mm/npool.c: Ditto. + * ntoskrnl/mm/pagefile.c: Ditto. + * ntoskrnl/mm/pageop.c: Ditto. + * ntoskrnl/mm/section.c: Ditto. + * ntoskrnl/mm/slab.c: Ditto. + * ntoskrnl/mm/i386/page.c: Ditto. + * ntoskrnl/ob/handle.c: Ditto. + * ntoskrnl/ps/create.c: Ditto. + * ntoskrnl/ps/process.c: Ditto. + * ntoskrnl/ps/w32call.c: Ditto. + * subsys/win32k/include/object.h: Ditto. + +2002-10-01 Casper S. Hornstrup + + * lib/ntdll/string/ctype.c: Undefine __MSVCRT__ to not have mingw + runtime import _pctype. + +2002-09-30 Casper S. Hornstrup + + * lib/user32/misc/desktop.c (string.h): Include. + * lib/user32/misc/resources.c: Ditto. + * lib/user32/misc/winhelp.c: Ditto. + * lib/user32/windows/accel.c: Ditto. + * lib/user32/windows/bitmap.c: Ditto. + * subsys/win32k/freetype/ctype.c: Undefine __MSVCRT__ and _pctype to not + have mingw runtime import _pctype. + +2002-09-30 Casper S. Hornstrup + + * ntoskrnl/cc/view.c (alloca): Prototype. + * ntoskrnl/rtl/ctype.c: Undefine __MSVCRT__ to not have mingw runtime + import _pctype. + +2002-08-26 David Welch + + * lib/gdi32/misc/dllmain.c (GdiDllInitialize): Don't initialize + win32k.sys for each process. + * subsys/csrss/init.c (CsrServerInitialization): Initialize + win32k.sys as well. + +2002-08-26 David Welch + + * ntoskrnl/ps/process.c (NtCreateProcess): Reference the + parent process's handle using ExGetPreviousMode. + +2002-08-26 David Welch + + * lib/user32/misc/dllmain.c (Init): Initialize gdi32 as well. + +2002-08-26 David Welch + + * iface/addsys/genw32k.c (main, process): Generate a set of + stubs for csrss as well. + +2002-08-26 David Welch + + * lib/kernel32/process/create.c (CreateProcessW): Initialize + all the members of the new process's PPB. + +2002-08-17 David Welch + + * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): Ensure the + process isn't freed in the middle of our operations. + +2002-08-17 David Welch + + * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): Fixed. + +2002-08-17 David Welch + + * ntoskrnl/ps/create.c (PiDeleteThread): Don't dereference + the thread's process while holding the thread list lock. + +2002-08-17 David Welch + + * ntoskrnl/mm/section.c (MmMapViewOfSection): Check there is + enough space for all parts of an image before mapping it; if + there isn't enough space free at the preferred base address + then try to choose a different one. + +2002-08-17 David Welch + + * ntoskrnl/mm/mpw.c (MmInitMpwThread): Run the MPW thread at + idle priority. + +2002-08-17 David Welch + + * ntoskrnl/mm/kmap.c (ExUnmapPage, ExAllocatePageWithPhysPage, + MiFreeNonPagedPoolRegion, MiAllocNonPagedPoolRegion): Maintain + a hint of the next free page; makes running with whole page + allocation more bearable. + +2002-08-17 David Welch + + * ntoskrnl/mm/anonmem.c (MmPageOutVirtualMemory): Show an + out of swap space message if we are out of swap space. + * ntoskrnl/mm/section.c (MmPageOutSectionView): Show an + out of swap space message if we are out of swap space. + * ntoskrnl/mm/pagefile.c (MmAllocSwapPage): Don't automatically + show an out of swap space message on failure. + * ntoskrnl/mm/pagefile.c (MmShowOutOfSpaceMessagePagingFile): New + function to notify the user that the pagefile is full. + +2002-08-17 David Welch + + * drivers/lib/zlib/Makefile: Create a dummy zlib.sym + +2002-08-16 David Welch + + * ntoskrnl/mm/npool.c (ExAllocateWholePageBlock): Converted + to use PHYSICAL_ADDRESS type for page address. + +2002-08-16 David Welch + + * subsys/win32k/ntuser/class.c (W32kCreateClass): Corrected + typo when calculating the offset into the class object to + put the class name string. + +2002-08-16 David Welch + + * ntoskrnl/ps/thread.c (PsDispatchThreadNoLock): Don't call + the reaper function directly; set an event to wake up a seperate + reaper thread. + * ntoskrnl/ps/thread.c (PsReaperThreadMain): New function that + waits for a notification and then calls PsReapThreads. + * ntoskrnl/ps/thread.c (PsInitThreadManagement): Create the + reaper thread. + +2002-08-15 David Welch + + * lib/advapi32/misc/dllmain.c (DllMain): Removed debug message. + +2002-08-14 David Welch + + * subsys/smss/init.c (SmPagingFilesQueryRoutine): If possible + take the size of the paging file from the registry. + +2002-08-14 David Welch + + * ntoskrnl/mm/section.c (MmCreateDataFileSection): Extend the + section if necessary. + +2002-08-14 David Welch + + * ntoskrnl/mm/pagefile.c (NtCreatePagingFile): Set the file + size using the FileAllocationInformation class. + +2002-08-14 David Welch + + * ntoskrnl/mm/anonmem.c (MmWritePageVirtualMemory): Implemented + function to write anonymous memory pages to the swap file. + * ntoskrnl/mm/anonmem.c (MmFreeVirtualMemoryPage): Free any + swap page associated with the page. + * ntoskrnl/mm/mpw.c (MmWriteDirtyPages): New function to find + pages to write to disk. + * ntoskrnl/mm/mpw.c (MmMpwThreadMain): Implemented MPW functionality. + * ntoskrnl/mm/rmap.c (MmWritePagePhysicalAddress): New function + to write a single page back to disk. + * ntoskrnl/mm/rmap.c (MmSetCleanAllRmaps, MmSetDirtyAllRmaps, + MmIsDirtyPageRmap): New rmap function to support the MPW thread. + * ntoskrnl/mm/section.c (MmWritePageSectionView): Implemented + function to write back section pages. + * ntoskrnl/mm/section.c (MmFreeSectionPage): Free any swap + entry associated with the page; mark pages shared with + the cache as dirty if necessary. + +2002-08-14 David Welch + + * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set name of + the module into the module text structure. + +2002-08-14 David Welch + + * ntoskrnl/io/rw.c (NtReadFile, NtWriteFile): Use the correct + test for whether to wait for the completion of i/o. + +2002-08-14 David Welch + + * ntoskrnl/cm/ntfunc.c (NtFlushKey): Request synchronous i/o + from NtOpenFile. + * ntoskrnl/cm/regfile (CmiInitPermanentRegistryHive): Request + synchronous i/o from NtCreateFile. + * ntoskrnl/dbg/kdb_stabs.c (LdrpLoadModuleSymbols): Request + synchronous i/o from NtOpenFile. + * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Request synchronous i/o + from NtOpenFile. + +2002-08-14 David Welch + + * ntoskrnl/cc/view.c (CcRosSuggestFreeCacheSegment): Maintain the + correct reference count. + +2002-08-14 David Welch + + * ntoskrnl/cc/view.c (CcRosFlushCacheSegment): New function to + write back a modified cache segment. + * ntoskrnl/cc/view.c (CcRosFlushDirtyPages): New function to + flush some dirty pages from the cache. + * ntoskrnl/cc/view.c (CcRosMarkDirtyCacheSegment): New function to + mark a cache segment modified while mapped into memory as dirty. + +2002-08-14 David Welch + + * ntoskrnl/cc/pin.c (CcMapData, CcUnpinData, CcSetDirtyPinnedData): + Store the dirty status in the BCB; don't write back dirty data + immediately. + +2002-08-14 David Welch + + * include/ntos/mm.h: Added SEC_XXXX defines from 'Windows NT/2000 + Native API Reference' + +2002-08-14 David Welch + + * drivers/fs/vfat/ea.c (VfatSetExtendedAttributes): Empty + placeholder for extended attribute functions. + +2002-08-14 David Welch + + * drivers/fs/vfat/finfo.c (VfatSetAllocationSizeInformation): + Added function to set allocation size. + +2002-08-14 David Welch + + * drivers/fs/vfat/fcb.c (vfatFCBInitializeCache): Renamed + to vfatFCBInitializeCacheFromVolume. + * drivers/fs/vfat/fcb.c (vfatMakeFCBFromDirEntry): Don't + initialise the cache with a file object representing the + volume unless the FCB is for a directory. + +2002-08-14 David Welch + + * drivers/fs/vfat/create.c (VfatPagingFileCreate): Added a + new function for handling paging file only code. + * drivers/fs/vfat/create.c (VfatSupersedeFile): Added a + new function for doing a file supersede. + * drivers/fs/vfat/create.c (VfatCreateFile): Reformatted and + adjusted control flow. Set allocation size and extended attributes + on create. + * drivers/fs/vfat/create.c (VfatCreate): Removed goto. + +2002-08-14 David Welch + + * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Renamed + updEntry to VfatUpdateEntry. + * drivers/fs/vfat/close.c (VfatCloseFile): Renamed + updEntry to VfatUpdateEntry. + * drivers/fs/vfat/dirwr.c (updEntry): Renamed to + VfatUpdateEntry. + * drivers/fs/vfat/dirwr.c (addEntry): Renamed to + VfatAddEntry. + +2002-08-14 David Welch + + * apps/tests/sectest/sectest.c (main): Fixed formatting. + +2002-08-10 David Welch + + * ntoskrnl/mm/i386/page.c (MmSetPageProtect): Fixed + behaviour when called on the system address space. + +2002-08-10 David Welch + + * ntoskrnl/mm/virtual.c (MmQueryAnonMem, MmProtectAnonMem, + NtAllocateVirtualMemory, NtFreeVirtualMemory): Renamed + segments to regions; moved region code to seperate file. + Implemented NtQueryVirtualMemory and NtProtectVirtualMemory + for anonymous memory areas. + +2002-08-10 David Welch + + * ntoskrnl/mm/anonmem.c: Moved functions relating to + areas created with NtAllocateVirtualMemory to a + seperate file. + +2002-08-10 David Welch + + * ntoskrnl/mm/section.c (MmQuerySectionView): Implemented + NtQueryVirtualMemory for section views. + +2002-08-10 David Welch + + * ntoskrnl/mm/section.c (MmAccessFaultSectionView, + MmNotPresentFaultSectionView, MmProtectSectionView, + MmMapViewOfSegment, MmAlterViewAttributes): Implemented + NtProtectVirtualMemory for section views. + +2002-08-10 David Welch + + * ntoskrnl/ke/main.c: Removed SEH test code. + +2002-08-10 David Welch + + * lib/ntdll/ldr/utils.c (LdrFixupImports): Remove the readonly + protection from the IAT before writing to it. + +2002-08-10 David Welch + + * lib/ntdll/ldr/utils.c (LdrAdjustDllName): Properly null terminate + the base name of the DLL. + +2002-08-10 David Welch + + * ntoskrnl/ldr/loader.c (LdrPEProcessModule): Set the text segment + of modules to readonly after loading. + +2002-08-09 David Welch + + * ntoskrnl/ps/create.c (NtCreateThread): Call PsSuspendThread + if NtCreateThread has CreateSuspended as TRUE. + * ntoskrnl/ps/suspend.c (PsSuspendThread, PsResumeThread, + PiSuspendThreadKernelRoutine): Fixed suspend functionality. + +2002-08-09 David Welch + + * ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy + the LDR variable from the right address. + +2002-08-09 David Welch + + * ntoskrnl/ke/apc.c (KiDeliverNormalApc): Check for + kernel APCs pending on exit from the kernel. + * ntoskrnl/ke/apc.c (KiDeliverNormalApc, KiDeliverUserApc, + KiDeliverApc): Set the APC's inserted flag to FALSE after + removing it from the thread's queue. + +2002-08-09 David Welch + + * lib/kernel32/thread/thread.c (ThreadStartup): Don't + call DLL entrypoints; this is done by LdrInitializeThunk. + * lib/ntdll/ldr/startup.c (LdrInitializeThunk): Call + DLLs in initialization order; take the loader lock before + calling. + +2002-08-09 David Welch + + * apps/tests/thread/thread.c (main): Test suspend and + resume functionality. + +2002-08-08 David Welch + + * ntoskrnl/mm/section (NtQuerySection): Return the + right result length. + +2002-08-08 David Welch + + * ntoskrnl/ke/usertrap.c (print_user_address): Check for + a NULL LDR structure in the PEB; copy the LDR pointer in + safely. + +2002-08-08 David Welch + + * ntoskrnl/ke/apc.c (KiDeliverUserApc): Deliver all present + APCs; release the APC spinlock while acccessing user memory. + +2002-08-08 David Welch + + * include/internal/ps.h: Adjusted offsets into the ETHREAD + structure. + * include/internal/ps.h: Removed redundant members from the + KTHREAD structure. + * ntoskrnl/ke/kthread.c (KeInitializeThread): Removed + redundant members from the KTHREAD structure. + +2002-08-08 David Welch + + * ntoskrnl/dbg/kdb.c (KdbEnterDebuggerException): New + function to enter the debugger on an exception. + * ntoskrnl/kd/kdebug.c (KdInitSystem): Initialize the + local kernel debugger if enabled. + * ntoskrnl/ke/catch.c (KiDispatchException): Enter the + local kernel debugger on an exception. + +2002-08-08 David Welch + + * include/ntdll/ldr.h: Added definition for a DLL entrypoint. + * lib/kernel32/process/create.c (KlCreateFirstThread): Put + the argument to the NtProcessStartup function on the stack. + * lib/kernel32/process/create.c (KlInitPeb): Read the + base address of the new image from the PEB. + * lib/kernel32/process/create.c (CreateProcessW): Start the + first thread at the entrypoint of the new image. + * lib/ntdll/ldr/startup.c (LdrInitializeThunk): If the + function is called after the initial startup then just call the + entrypoints for the loaded DLLs with DLL_THREAD_ATTACH. Don't + call the entrypoint of the image. + * lib/ntdll/rtl/process.c (RtlpCreateFirstThread): Put the + argument to the NtProcessStartup function on the stack. + * lib/ntdll/rtl/process.c (KlInitPeb): Read the base address of + the new image from the PEB. + * lib/ntdll/rtl/process.c (RtlCreateUserProcess): Start the + first thread at the entrypoint of the new image. + * ntoskrnl/ke/i386/bthread.S (PsBeginThreadWithContextInternal): + Use the system call path to begin a usermode thread. + * ntoskrnl/ke/i386/thread.c (Ke386InitThreadWithContext): Convert + the supplied context into a trap frame. + * ntoskrnl/ldr/init.c (LdrLoadInitialProcess): Put the PEB argument + to the NtProcessStartup function on the new stack; start the + first thread at the entrypoint of the image. + * ntoskrnl/ps/create.c (NtCreateThread): Create an APC to call + LdrInitializeThunk in the context of a new thread before its + entrypoint. + +2002-08-08 David Welch + + * drivers/fs/vfat/cleanup.c (VfatCleanupFile): Uninitialise + the cache on file cleanup. + * drivers/fs/vfat/fcb.c (vfatReleaseFcb): Don't uninitialise + the cache on file close. + * ntoskrnl/cc/copy.c: Renamed zero page global variable. + * ntoskrnl/cc/view.c: Added cache delete function. + +2002-07-13 Casper S. Hornstrup + + * rules.mak (RSYM): Define. + * include/ddk/zwtypes.h (DebugDbgLoadSymbols): Add to enum + _DEBUG_CONTROL_CODE. + * include/ntdll/ldr.h (LDR_SYMBOL_INFO, LdrpLoadUserModuleSymbols): Add. + (LdrLoadModuleSymbols): Remove. + * include/ntos/kdbgsyms.h (ST_FILENAME, ST_FUNCTION, + ST_LINENUMBER): Add. + (SYMBOL). Make Name an ANSI_STRING. + (IMAGE_SYMBOL_INFO, AreSymbolsParsed): Add. + * lib/ntdll/ldr/startup.c (LdrInitializeThunk): Call + LdrpLoadUserModuleSymbols() not LdrLoadModuleSymbols(). + * lib/ntdll/ldr/utils.c (LdrLoadModuleSymbols): Rename to + LdrpLoadUserModuleSymbols. + (LdrpLoadUserModuleSymbols): Use DebugDbgLoadSymbols debug control code. + (LdrLoadDll): assert if out of memory. + (LdrLoadDll): Call + LdrpLoadUserModuleSymbols(), not LdrLoadModuleSymbols(). + * lib/ntdll/string/ctype.c (_pctype): #undef. + * ntoskrnl/dbg/dbgctrl.c (NtSystemDebugControl): Call + LdrLoadUserModuleSymbols on DebugDbgLoadSymbols. + * ntoskrnl/include/internal/ldr.h (LdrGetAddressInformation): Add. + * ntoskrnl/include/internal/module.h (MODULE_TEXT_SECTION): Make SymbolInfo + an IMAGE_SYMBOL_INFO. + * ntoskrnl/ke/i386/exp.c (LdrGetAddressInformation): Add prototype. + (print_address): Change #ifdef KDBG to #ifdef DBG. + (KiDoubleFaultHandler, KiDumpTrapFrame, KeDumpStackFrames): Dump + one stack frame per line. + * ntoskrnl/ke/i386/multiboot.S: Create pagetables for more kernel + address space so larger modules can be passed from the boot loader. + * ntoskrnl/ke/i386/usertrap.c (LdrGetAddressInformation): Add prototype. + (print_user_address): Print symbols using LdrGetAddressInformation(). + * ntoskrnl/ldr/loader.c (SYMBOLFILE_HEADER, IMAGE_SYMBOL_INFO_CACHE, + STAB_ENTRY, N_FUN, N_SLINE, N_SO, SymbolListHead): Add. + (TAG_SYM_BUF): Remove. + (LdrInitDebug): Remove unneeded code. + (LdrInit1): Prepare for loading symbols. + (LdrpReadLine, HexL, LdrpParseLine, LdrpLoadModuleSymbolsFromBuffer, + LdrpLoadUserModuleSymbolsFromBuffer): Remove. + (LdrpParseImageSymbols, LdrpGetFileName, LdrpGetFunctionName, + LdrpGetLineNumber, LdrGetAddressInformation, LdrpLookupUserSymbolInfo): Add. + (LdrpLoadModuleSymbols, LdrInitializeBootStartDriver): Change to use new + symbol structures. + (LdrLoadUserModuleSymbols): Cache symbol buffers. + (LdrUnloadModuleSymbols): Implement. + (LdrLoadModule, LdrUnloadModule): Change #ifdef KDBG to #ifdef DBG. + (LdrPEProcessModule): Split a line into two lines. + (LdrPEProcessModule): Setup for loading symbols. + * ntoskrnl/ldr/sysdll.c (LdrpMapSystemDll): Open with FILE_SHARE_READ. + * ntoskrnl/ps/process.c (PiFreeSymbols): Call LdrUnloadModuleSymbols() to + free symbols. + (PiDeleteProcess): Change #ifdef KDBG to #ifdef DBG. + * ntoskrnl/rtl/ctype.c (_pctype): #undef. + * ntoskrnl/rtl/string.c (strncpy): Terminate destination string. + * tools/Makefile (rsym): Add target. + * tools/helper.mk: Include config and use -g if DBG = 1. + +2002-07-13 Casper S. Hornstrup + + * Makefile (install_before): Install system.hiv to correct location. + +2002-07-04 David Welch + + * subsys/win32k/include/callback.h: Fixed callback argument + definitions. + * subsys/win32k/ntuser/winpos.c: Implemented some more of the windows + sizing/moving code. + * subsys/win32k/ntuser/painting.c: Implemented some more of the + window painting code. + * subsys/win32k/objects/coord.c: Implemented LPtoDP and DPtoLP. + * subsys/win32k/objects/region.c: Added stubs for some more + region functions. + +2002-07-04 David Welch + + * ntoskrnl/ps/process.c (NtCreateProcess): Duplicate the + process desktop handle as well. + +2002-07-04 David Welch + + * ntoskrnl/se/token.c: Don't call the ZwXXX variant of + system calls when in system context. + +2002-07-04 David Welch + + * ntoskrnl/Makefile: Added file with MDA output code. + * ntoskrnl/kd/kdebug.c: Recognize MDA as a destination for + debug output. + +2002-07-04 David Welch + + * lib/user32/windows/defwnd.c: Implemented some more of the + default window handler. + +2002-07-04 David Welch + + * lib/user32/misc/stubs.c: Removed some stubs to seperate files. + +2002-07-04 David Welch + + * lib/user32/user32.def: Export ScreenToClient otherwise we + get problems when code in user32 tries to call it. + +2002-07-04 David Welch + + * include/win32k/region.h: Added prototypes for some missing + region functions. + +2002-07-04 David Welch + + * include/win32k/ntuser.h: Added prototypes for some missing + NtUserXXX functions. + +2002-07-04 David Welch + + * include/user32/wininternal.h: Added some constants for + private GetDCEx styles that WINE needs. + +2002-07-04 David Welch + + * include/user32/callback.h: Fixed callbacks for messages with + parameters. + +2002-07-04 David Welch + + * include/napi/win32.h (W32THREAD): Added pointer to the + thread's desktop. + * include/napi/win32.h (W32PROCESS): Removed handle table, + added a pointer to the process's window station. + * subsys/win32k/ntuser/guicheck.c (W32kGuiCheck): Reference + a process's window station on the first win32k system call. Reference + a thread's desktop on the first win32k system call. + +2002-07-04 David Welch + + * include/messages.h: Added some missing WM_XXX constants. + +2002-07-04 David Welch + + * drivers/dd/ide/makefile: Compiling with debugging messages + needs libgcc to be linked in. + +2002-07-04 David Welch + + * iface/addsys/genw32k.c: Generate a variable with the + number of system calls. + * iface/native/genntdll.c: Generate a proper stack frame for + the user system call stubs. + * ntoskrnl/ke/i386/syscall.S: Generate a proper stack frame for + the handler for system calls. + +2002-07-04 David Welch + + * Makefile: Build the GUI startup application. + * subsys/system/gstart/gstart.c: Application to start up + the GUI. + +2002-06-18 David Welch + + * tools/helper.mk: Make an import library a proper target + depending on the .def file. + +2002-06-18 David Welch + + * subsys/win32k/ntuser/window.c (NtUserGetWindowLong): Began + implementation. + +2002-06-18 David Welch + + * subsys/win32k/misc/object.c (ObmCreateHandle): Return the + correct handle value. + +2002-06-18 David Welch + + * subsys/win32k/makefile: Make win32k depend on the file containing + the service table. + +2002-06-18 David Welch + + * ntoskrnl/ke/i386/stkswitch.S (KeSwitchStackAndRet, + KePushAndStackSwitchAndSysRet): Push one value only. + * ntoskrnl/ps/w32call.c (NtCallbackReturn, NtW32Call): Moved + these functions to a new file. Restore the old trap frame after + returning from a callback. + +2002-06-18 David Welch + + * lib/user32/windows/message.c (CallWindowProcA, CallWindowProcW): + Convert message to Unicode or ASCII if necessary. + +2002-06-18 David Welch + + * include/user32/callback.h: Added WM_CREATE and WM_NCCALCSIZE + callbacks. + * lib/user32/windows/window.c (User32SendCREATEMessageForKernel, + User32SendNCCREATEMessageForKernel): Implemented. + * subsys/win32k/ntuser/callback.c (W32kSendCREATEMessage): + Implemented. + +2002-06-18 David Welch + + * include/structs.h: Added Unicode and ASCII versions of + CREATESTRUCT. + +2002-06-16 David Welch + + * tools/helper.mk: Make the install target depend on all the + files to be installed. + +2002-06-16 David Welch + + * ntoskrnl/ps/thread.c (NtCallbackReturn): Set TSS.Esp0 to the + top of the old stack. + * ntoskrnl/ps/thread.c (NtW32Call): Set TSS.Esp0 to the top of + the new stack. Free the callback stack correctly. Don't copy + portion of the trap frame that doesn't exist in non-v86-mode + interrupts. + * ntoskrnl/ps/thread.c (PsFreeCallbackStack): New function to + free a stack allocated with PsAllocateCallbackStack. + +2002-06-16 David Welch + + * drivers/dd/null/makefile: Commented out local LDFLAGS as + these cause bad relocations in the stripped image. + +2002-06-16 David Welch + + * config: Corrected spelling error. + +2002-06-11 David Welch + + * subsys/system/winlogon/winlogon.c (WinMain): Check for + failure when creating a window system. + +2002-06-11 David Welch + + * ntoskrnl/ob/handle.c (ObDuplicateObject): Added this internal + function for duplicating objects. + * ntoskrnl/ps/process.c (NtCreateProcess): Duplicate the parent + process's window station to the child process. + * ntoskrnl/ps/process.c (PsInitProcessManagement): Initialize the + first process's window station. + +2002-06-11 David Welch + + * ntoskrnl/mm/marea.c (MmCreateMemoryArea): Initialise + page operation structure members. + * ntoskrnl/mm/pageop.c (MmReleasePageOp, MmGetPageOp): Increment + or decrement the page operation count in the memory area. + * ntoskrnl/mm/virtual.c (MmNotPresentFaultVirtualMemory, + MmPageOutVirtualMemory): Check for a deleted memory area before + handling the fault. + * ntoskrnl/mm/virtual.c (MmFreeVirtualMemory): Wait for all + page operations to finish before freeing the memory area. + +2002-06-11 David Welch + + * ntoskrnl/ke/i386/syscall.S (interrupt_handler2e): Corrected + test for previous mode, upper 16-bit of CS on the stack after an + interrupt are arbitary. + +2002-06-11 David Welch + + * lib/user32/misc/winsta.c: Cleaned up indentation. + +2002-06-11 David Welch + + * apps/tests/winhello/winhello.c (WinMain, MainWndProc): + Cleaned up formatting, some more error checks. + +2002-06-04 David Welch + + * ntoskrnl/mm/virtual.c (MmSecureVirtualMemory, + MmUnsecureVirtualMemory, NtQueryVirtualMemory): Corrected indentation. + +2002-06-04 David Welch + + * ntoskrnl/ke/i386/exp.c (KiDoubleFaultHandler): Print CR3 + correctly. + +2002-06-04 David Welch + + * ntoskrnl/include/internal/ps.h: Added KTHREAD_STACK_LIMIT definition. + * ntoskrnl/ke/i386/tskswitch.S (Ki386ContextSwitch): Force all the + pages of the kernel stack to be accessible from this process. + +2002-06-04 David Welch + + * ntoskrnl/cc/view.c (ReadCacheSegmentChain): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/cc/copy.c (CcRosCreateCacheSegment): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/cc/copy.c (CcFreeCachePage): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/include/internal/mm.h: Changed prototypes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/include/internal/ps.h (KPROCESS): Changed type of + page directory base to PHYSICAL_ADDRESS. + * ntoskrnl/include/internal/i386/mm.h: Changed prototypes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/ke/kthread.c (KeFreeStackPage): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/ke/kthread.c (KeInitializeThread): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/ke/process.c (KeAttachProcess, KeDetachProcess): Changes + to use PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/ke/kernel.c (PcrPages, KeApplicationProcessorInit): Changes + to use PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/balance.c (MM_ALLOCATION_REQUEST): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/balance.c (MmReleasePageMemoryConsumer): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/balance.c (MmRequestPageMemoryConsumer): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/cont.c (MmFreeContinuousPage): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/cont.c (MmAllocateContinuousAlignedMemory): Changes to + use PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/freelist.c (MmTransferOwnershipPage, + MmGetLRUFirstUserPage, MmGetLRUNextUserPage, MmGetContinuousPages, + MmInitializePageList, MmSetFlagsPage, MmSetRmapListHeadPage, + MmGetRmapListHeadPage, MmMarkPageMapped, MmMarkPageUnmapped, + MmGetFlagsPage, MmSetSavedSwapEntryPage, MmGetSavedSwapEntryPage, + MmReferencePage, MmGetReferenceCountPage, MmIsUsablePage, + MmDereferencePage, MmGetLockCountPage, MmLockPage, MmUnlockPage, + MmAllocPage): Changes to use PHYSICAL_ADDRESS type for physical + addresses. + * ntoskrnl/mm/iospace.c (MmMapIoSpace): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/kmap.c (ExAllocatePage, MiZeroPage, MiCopyFromUserPage, + ExAllocatePageWithPhysPage): Changes to use PHYSICAL_ADDRESS type for + physical addresses. + * ntoskrnl/mm/marea.c (MmFreeMemoryArea): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/mdl.c (MmUnlockPages, MmMapLockedPages, + MmProbeAndLockPages): Changes to use PHYSICAL_ADDRESS type for + physical addresses. + * ntoskrnl/mm/mm.c (MmSharedDataPagePhysicalAddress, + MmCommitPagedPoolAddress, MmNotPresentFault): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/mminit.c (MmInitVirtualMemory): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/ncache.c (MmAllocateNonCachedMemory, + MmFreeNonCachedPage): Changes to use PHYSICAL_ADDRESS type for + physical addresses. + * ntoskrnl/mm/npool.c (grow_kernel_pool): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/rmap.c (MmPageOutPhysicalAddress, MmInsertRmap, + MmDeleteAllRmaps, MmDeleteRmap): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/section.c (MiReadPage, MmNotPresentFaultSectionView, + MmAccessFaultSectionView, MmPageOutDeleteMapping, + MmPageOutSectionView, MmFreeSectionPage): Changes to use + PHYSICAL_ADDRESS type for physical addresses. + * ntoskrnl/mm/slab.c (ExGrowSlabCache): Changes to use + PHYSICAL_ADDRESS type for physical address. + * ntoskrnl/mm/virtual.c (MmPageOutVirtualMemory, + MmNotPresentFaultVirtualMemory, MmFreeVirtualMemoryPage): Changes to + use PHYSICAL_ADDRESS type for physical address. + * ntoskrnl/mm/wset.c (MmTrimUserMemory): Changes to use + PHYSICAL_ADDRESS type for physical address. + * ntoskrnl/mm/page.c (Mmi386ReleaseMmInfo, MmCopyMmInfo, + MmGetPhysicalAddressForProcess, MmCreateVirtualMapping, + MmCreateVirtualMappingUnsafe, MmCreateVirtualMappingForProcess, + MmDeleteVirtualMapping): Changes to use PHYSICAL_ADDRESS type for + physical address. + * ntoskrnl/ps/process (PsInitProcessManagment): Changes to use + PHYSICAL_ADDRESS type for physical address. + * ntoskrnl/ps/thread.c (PsAllocateCallbackStack): Changes to use + PHYSICAL_ADDRESS type for physical address. + +2002-06-04 David Welch + + * Lots of change since the ChangeLog was last updated. + +2001-03-18 David Welch + + * ntoskrnl/ke/apc.c (KiDeliverApc): Bug fix. + * ntoskrnl/ke/apc.c (KeInsertQueueApc): More comments. + * ntoskrnl/ke/catch.c (KiDispatchException): Bug fix. + * ntoskrnl/ke/timer.c (KeDelayExecutionThread): Don't use removed + function KeAddTimeoutThread. + * ntoskrnl/ke/timer.c (KeAddTimeoutThread): Removed. + * ntoskrnl/ke/wait.c (KeWaitForSingleObject, KeWaitForMultipleObjects): + Don't use KeAddTimeoutThread. + * ntoskrnl/mm/freelist.c (MmAllocateContiguousAlignedMemory): Bug fix + * ntoskrnl/mm/freelist.c (MmAllocatePage): Allocate from the top + memory. + +2001-03-17 David Welch + + * ntoskrnl/ke/catch.c (KiDispatchException): Implementation of + exception handling, user-mode only. + +2001-03-16 David Welch + + * include/ddk/zw.h: Corrected declarations of NtCreateProfile, + NtQueryIntervalProfile, NtSetIntervalProfile. + * include/ddk/zwtypes.h: Added definitions of KPROFILE_SOURCE. + * ntoskrnl/include/internal/ke.h: Added the interrupted EIP as a + parameter to KiUpdateSystemTime for profiling purposes. + * ntoskrnl/include/internal/nt: Added declaration for profiling + support initialization. + * ntoskrnl/ke/timer.c (KiUpdateSystemTime, KeExpireTimers): Call + the profiling code on a timer interrupt with the interrupt EIP. + * ntoskrnl/ke/i386/irq.c (KiDispatchInterrupt): Pass the interrupted + EIP to KiUpdateSystemTime. + * ntoskrnl/mm/virtual.c (NtReadVirtualMemory, NtWriteVirtualMemory): + Release the MDLs used properly. + * ntoskrnl/nt/nt.c: Call the profiling support initialization. + * ntoskrnl/nt/ntevent.c (NtCreateEvent): Don't try copying the + ObjectAttributes parameter if it is NULL. + * ntoskrnl/nt/profile.c: Implemented profiling. + +2001-03-16 David Welch + + * ntoskrnl/include/internal/safe.h: Corrected typo. + * ntoskrnl/nt/ntevent.c (NtCreateEvent, NtOpenEvent, NtQueryEvent): + Corrected typos. + * ntoskrnl/rtl/mem.c: Missing header file. + +2001-03-16 David Welch + + * ntoskrnl/include/internal/safe.h: Add definitions for handling + potentially unsafe pointers. + +2001-03-16 David Welch + + * ntoskrnl/include/internal/mm.h: Removed MmSafeCopyToUser and + MmSafeCopyFromUser as source files need these but don't want internal + mm definitions. + * ntoskrnl/nt/ntevent.c (NtCreateEvent, NtOpenEvent, NtPulseEvent, + NtQueryEvent, NtResetEvent, NtSetEvent): Copy data to and from + user mode safely. + * ntoskrnl/rtl/mem.c (MmCopyToCaller, MmCopyFromCaller): Helper + functions for copying data to and from potentially unsafe pointers. + +2000-12-23 David Welch + + * All task switching is done in software. + * Beginnings of v86 mode support. + +2000-12-22 David Welch + + * ntoskrnl/ps/kill.c (PiTerminateProcessThreads): Drop + PiThreadListLock before calling PsTerminateOtherThread + +2000-12-16 David Welch + + * ntoskrnl/ex/fmutex.c (ExReleaseFastMutexUnsafe): Only set the + fast mutex's owner back to NULL if it is being released + +2000-12-10 David Welch + + * ntoskrnl/ke/i386/vm86_sup.S (Ki386RetToV86Mode): Added function + to do the raw switch to v86 mode. + * ntoskrnl/include/internal/vm86.h: Definitions for the v86 mode + support. + +2000-12-10 David Welch + + * ntoskrnl/ke/i386/trap.s (PsBeginThreadWithContextInternal): Moved + to ntoskrnl/ke/i386/bswitch.S. + * ntoskrnl/ke/i386/trap.s (interrupt_handler2e): Moved to + ntoskrnl/ke/i386/syscall.S. + * ntoskrnl/ke/i386/trap.s (old_interrupt_handler2e): Removed. + +2000-12-04 David Welch + + * ntoskrnl/ke/i386/irq.c (KiInterruptDispatch): Record the last PC + value for a rescheduled thread. + * ntoskrnl/ke/i386/irqhand.s: Construct a primitive trap frame + in interrupt handlers. + +2000-08-30 David Welch + + * Added calibration of KeStallExecutionProcessor timing + (code from linux 2.2.16). + + * Corrected compilation bugs in user32 library. + + * Corrected compilation bugs related to anonymous structs + in ndis code. + + * Pass command line to kernel from loadros. + + * Corrected PIC mask calculation. + +2000-05-27 David Welch + + * Fixed issue with closing non-existent or already closed + handle. + +2000-01-26 David Welch + + * ZwCreateProcess now maps ntdll rather than the user-mode + code. + +1999-09-06 David Welch + + * Implemented ZwOpenProcess. + + * Partially implemented killing other threads (possible memory + leaks). + + * Made a start on a proper implemention of APCs (based on + article in NT insider). + +1998-12-08 David Welch + + * Corrected bug in shell (Read two keypresses and assumed they + where the key going up and down respectively). + + * Corrected race in dpc handling. + + * Took out cleanup sections in ZwReadFile (now handled by the + APC). + + * Disabled broken code in kernel32. + + + + + + + + + + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..81997a6 --- /dev/null +++ b/INSTALL @@ -0,0 +1,74 @@ +1. Build environment + +To build the system you need either mingw32 installed on Windows or a mingw32 +cross compiler running on unix. + + +2. Building ReactOS + +To build from Windows run 'make' (wihout the quotes) from the top directory. +To build from unix, edit rules.mak and change the PREFIX variable to the +correct value for your cross-compiler, then run 'make'. + + +3. Installation + +The system can only be installed on the first partition on the first harddisk. +The partition must be formatted as FAT16 or FAT32. The system can only be +started from DOS and not from a Windows DOS-prompt. + +ReactOS can be installed from the source distribution or from the binary +distribution. The two ways to install ReactOS are explained below. + + +3.1 Installation from sources + +To install ReactOS after building it, type 'make install'. This will create +the directory 'reactos' in the top directory. Copy this directory to the root +of your first partition on your first harddisk. This is usually c:\ on a +Windows machine. + +If you don't want to copy the files manually every time you run a 'make install', +you can specify the directory where the files are to be copied to during +installation. + +In rules.mak find the variable INSTALL_DIR and change the assigned value to the +name of the directory where the files are to be copied to. If you are using +Windows this could be: + + INSTALL_DIR = c:\reactos + +If you are on linux this could be: + + INSTALL_DIR = /mnt/windows/reactos + +Save the changes to rules.mak and run 'make install' to install the files to +the new location. + + +3.2 Installation from binany distribution + +To install ReactOS from the binary distribution, extract the archive contents +to c:\reactos. Remember to extract the files with full paths. + + +4. Booting ReactOS + +Startup in DOS mode. 'cd' to c:\reactos and type 'boot' and press . +ReactOS will now boot and when it has booted, you are asked for a username and +password. Just press twice as ReactOS does not currently have user +validation. A simple shell is started where you can use simple commands like +'cd' and 'dir'. + +You may also want to try running the enhanced shell, cmd.exe, found in +the rosapps CVS module. + + +5. Help + +If you run into problems or have suggestions for making ReactOS better, please +surf to the address below and subscribe to one or more of the mailing lists. + +http://www.reactos.com/index.php?tab=discussion§ion=lists + +ReactOS Development Team diff --git a/LGPL.txt b/LGPL.txt new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/LGPL.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f640f2b --- /dev/null +++ b/Makefile @@ -0,0 +1,788 @@ +# +# Global makefile +# + +PATH_TO_TOP = . + +# +# Define to build WINE modules +# +ifeq ($(ROS_BUILD_WINE),) +ROS_BUILD_WINE = no +else +ROS_BUILD_WINE = yes +endif + +include $(PATH_TO_TOP)/rules.mak + +# Required to run the system +COMPONENTS = iface_native iface_additional hallib ntoskrnl + + +# Hardware Abstraction Layers +# halx86 +HALS = halx86 + +# Bus drivers +# acpi isapnp pci +BUS = acpi isapnp pci + +# User mode libraries +# advapi32 crtdll fmifs gdi32 kernel32 libpcap packet msafd msvcrt ntdll ole32 +# oleaut32 psapi rpcrt4 secur32 shell32 user32 version ws2help ws2_32 wsock32 wshirda +DLLS = advapi32 crtdll fmifs gdi32 kernel32 packet msafd msvcrt ntdll \ + secur32 user32 version winmm ws2help ws2_32 wshirda +SUBSYS = smss win32k csrss + +# +# Select the server(s) you want to build +# +#SERVERS = posix linux os2 +SERVERS = win32 + +# Boot loaders +# dos +LOADERS = dos + +# Driver support libraries +#bzip2 zlib +DRIVERS_LIB = bzip2 zlib + +# Kernel mode device drivers +# beep blue floppy ide keyboard mouse null parallel ramdrv serenum serial vga vidport +DEVICE_DRIVERS = beep blue floppy ide null serial vga vidport + +# Kernel mode input drivers +# keyboard mouclass psaux sermouse +INPUT_DRIVERS = keyboard mouclass psaux + +# Kernel mode file system drivers +# cdfs ext2 fs_rec ms np vfat +FS_DRIVERS = cdfs fs_rec ms np vfat mup ntfs + +# Kernel mode networking drivers +# afd ndis packet tcpip tdi wshtcpip +NET_DRIVERS = afd ndis packet tcpip tdi wshtcpip + +# Kernel mode networking device drivers +# ne2000 +NET_DEVICE_DRIVERS = ne2000 + +# Kernel mode storage drivers +# atapi cdrom class2 disk scsiport +STORAGE_DRIVERS = atapi cdrom class2 disk scsiport + +# System applications +# autochk lsass services shell winlogon +SYS_APPS = autochk services shell winlogon gstart usetup + +# System services +# rpcss eventlog +SYS_SVC = rpcss eventlog + +# Test applications +# alive apc args atomtest bench consume count dump_shared_data +# event file gditest hello isotest lpc mstest mutex nptest +# pteb regtest sectest shm simple thread vmtest winhello +TEST_APPS = alive apc args atomtest bench consume count dump_shared_data \ + event file gditest hello isotest lpc mstest mutex nptest \ + pteb regtest sectest shm simple thread tokentest vmtest winhello dibtest + +# Test applications +# cabman cat net objdir partinfo pice ps stats +UTIL_APPS = cat objdir partinfo stats + +# +# Win32 Subsystem support (Based on WINE) +# FIXME: Move to this its own Makefile +# + +WINE_OTHER = unicode library + +WINE_TOOLS = bin2res wrc winebuild + +WINE_DLLS = comcat crtdll comctl32 commdlg dsound dplayx imagehlp ole32 richedit \ +shlwapi shell32 shdocvw twain urlmon winspool \ +rpcrt4 # needed to make rcprt4 implib + +# mapi32 oleaut32 oledlg olepro32 olecli olesvr shfolder +# winmm ddraw dinput dplay serialui tapi32 urlmon wintrust +# msinfo lzexpand (missing imports) + +WINE_PROGS = control expand osversioncheck regedit regsvr32 winver uninstaller +# (waiting on wrc fix for the rest of these) +# clock cmdlgtst notepad progman wcmd +# winefile winemine winetest uninstaller + + +ifeq ($(ROS_BUILD_WINE),yes) +WINE_MODULES = $(WINE_OTHER) $(WINE_TOOLS) $(WINE_DLLS) $(WINE_PROGS) +else +WINE_MODULES = +endif + +KERNEL_DRIVERS = $(DRIVERS_LIB) $(DEVICE_DRIVERS) $(INPUT_DRIVERS) $(FS_DRIVERS) \ + $(NET_DRIVERS) $(NET_DEVICE_DRIVERS) $(STORAGE_DRIVERS) + +all: tools dk implib $(COMPONENTS) $(HALS) $(BUS) $(DLLS) $(SUBSYS) \ + $(LOADERS) $(KERNEL_DRIVERS) $(SYS_APPS) $(SYS_SVC) $(TEST_APPS) \ + $(UTIL_APPS) $(WINE_MODULES) + +implib: $(COMPONENTS:%=%_implib) $(HALS:%=%_implib) $(BUS:%=%_implib) \ + $(DLLS:%=%_implib) $(LOADERS:%=%_implib) \ + $(KERNEL_DRIVERS:%=%_implib) $(SUBSYS:%=%_implib) \ + $(SYS_APPS:%=%_implib) $(SYS_SVC:%=%_implib) \ + $(TEST_APPS:%=%_implib) $(UTIL_APPS:%=%_implib) \ + $(WINE_MODULES:%=%_implib) + +clean: tools dk_clean $(HALS:%=%_clean) \ + $(COMPONENTS:%=%_clean) $(BUS:%=%_clean) $(DLLS:%=%_clean) \ + $(LOADERS:%=%_clean) $(KERNEL_DRIVERS:%=%_clean) $(SUBSYS:%=%_clean) \ + $(SYS_APPS:%=%_clean) $(SYS_SVC:%=%_clean) $(TEST_APPS:%=%_clean) \ + $(UTIL_APPS:%=%_clean) $(NET_APPS:%=%_clean) $(WINE_MODULES:%=%_clean) \ + clean_after tools_clean + +clean_after: + $(RM) $(PATH_TO_TOP)/include/roscfg.h + +install: tools install_dirs install_before \ + $(COMPONENTS:%=%_install) $(HALS:%=%_install) $(BUS:%=%_install) \ + $(DLLS:%=%_install) $(LOADERS:%=%_install) \ + $(KERNEL_DRIVERS:%=%_install) $(SUBSYS:%=%_install) \ + $(SYS_APPS:%=%_install) $(SYS_SVC:%=%_install) \ + $(TEST_APPS:%=%_install) $(UTIL_APPS:%=%_install) \ + $(WINE_MODULES:%=%_install) + +dist: $(TOOLS_PATH)/rcopy$(EXE_POSTFIX) dist_clean dist_dirs \ + $(HALS:%=%_dist) $(COMPONENTS:%=%_dist) $(BUS:%=%_dist) $(DLLS:%=%_dist) \ + $(LOADERS:%=%_dist) $(KERNEL_DRIVERS:%=%_dist) $(SUBSYS:%=%_dist) \ + $(SYS_APPS:%=%_dist) $(SYS_SVC:%=%_dist) $(TEST_APPS:%=%_dist) \ + $(UTIL_APPS:%=%_dist) $(NET_APPS:%=%_dist) $(WINE_MODULES:%=%_dist) + +.PHONY: all implib clean clean_before install dist + + +# +# System Applications +# +$(SYS_APPS): %: + make -C subsys/system/$* + +$(SYS_APPS:%=%_implib): %_implib: + make -C subsys/system/$* implib + +$(SYS_APPS:%=%_clean): %_clean: + make -C subsys/system/$* clean + +$(SYS_APPS:%=%_dist): %_dist: + make -C subsys/system/$* dist + +$(SYS_APPS:%=%_install): %_install: + make -C subsys/system/$* install + +.PHONY: $(SYS_APPS) $(SYS_APPS:%=%_implib) $(SYS_APPS:%=%_clean) $(SYS_APPS:%=%_install) $(SYS_APPS:%=%_dist) + +# +# System Services +# +$(SYS_SVC): %: + make -C services/$* + +$(SYS_SVC:%=%_implib): %_implib: + make -C services/$* implib + +$(SYS_SVC:%=%_clean): %_clean: + make -C services/$* clean + +$(SYS_SVC:%=%_dist): %_dist: + make -C services/$* dist + +$(SYS_SVC:%=%_install): %_install: + make -C services/$* install + +.PHONY: $(SYS_SVC) $(SYS_SVC:%=%_implib) $(SYS_SVC:%=%_clean) $(SYS_SVC:%=%_install) $(SYS_SVC:%=%_dist) + + +# +# Test Applications +# +$(TEST_APPS): %: + make -C apps/tests/$* + +$(TEST_APPS:%=%_implib): %_implib: + make -C apps/tests/$* implib + +$(TEST_APPS:%=%_clean): %_clean: + make -C apps/tests/$* clean + +$(TEST_APPS:%=%_dist): %_dist: + make -C apps/tests/$* dist + +$(TEST_APPS:%=%_install): %_install: + make -C apps/tests/$* install + +.PHONY: $(TEST_APPS) $(TEST_APPS:%=%_implib) $(TEST_APPS:%=%_clean) $(TEST_APPS:%=%_install) $(TEST_APPS:%=%_dist) + + +# +# Utility Applications +# +$(UTIL_APPS): %: + make -C apps/utils/$* + +$(UTIL_APPS:%=%_implib): %_implib: + make -C apps/utils/$* implib + +$(UTIL_APPS:%=%_clean): %_clean: + make -C apps/utils/$* clean + +$(UTIL_APPS:%=%_dist): %_dist: + make -C apps/utils/$* dist + +$(UTIL_APPS:%=%_install): %_install: + make -C apps/utils/$* install + +.PHONY: $(UTIL_APPS) $(UTIL_APPS:%=%_implib) $(UTIL_APPS:%=%_clean) $(UTIL_APPS:%=%_install) $(UTIL_APPS:%=%_dist) + + +# +# Other Wine Modules +# +$(WINE_OTHER): %: + make -f makefile.ros -C $(WINE_PATH)/$* + +$(WINE_OTHER:%=%_implib): %_implib: + make -f makefile.ros -C $(WINE_PATH)/$* implib + +$(WINE_OTHER:%=%_clean): %_clean: + make -f makefile.ros -C $(WINE_PATH)/$* clean + +$(WINE_OTHER:%=%_dist): %_dist: + make -f makefile.ros -C $(WINE_PATH)/$* dist + +$(WINE_OTHER:%=%_install): %_install: + make -f makefile.ros -C $(WINE_PATH)/$* install + +.PHONY: $(WINE_OTHER) $(WINE_OTHER:%=%_implib) $(WINE_OTHER:%=%_clean) $(WINE_OTHER:%=%_install) $(WINE_OTHER:%=%_dist) + + +# +# Wine Tools +# +$(WINE_TOOLS): %: + make -f makefile.ros -C $(WINE_PATH)/tools/$* + +$(WINE_TOOLS:%=%_implib): %_implib: + make -f makefile.ros -C $(WINE_PATH)/tools/$* implib + +$(WINE_TOOLS:%=%_clean): %_clean: + make -f makefile.ros -C $(WINE_PATH)/tools/$* clean + +$(WINE_TOOLS:%=%_dist): %_dist: + make -f makefile.ros -C $(WINE_PATH)/tools/$* dist + +$(WINE_TOOLS:%=%_install): %_install: + make -f makefile.ros -C $(WINE_PATH)/tools/$* install + +.PHONY: $(WINE_DLLS) $(WINE_DLLS:%=%_implib) $(WINE_DLLS:%=%_clean) $(WINE_DLLS:%=%_install) $(WINE_DLLS:%=%_dist) + + +# +# Wine DLLs +# +$(WINE_DLLS): %: + make -f makefile.ros -C $(WINE_PATH)/dlls/$* + +$(WINE_DLLS:%=%_implib): %_implib: + make -f makefile.ros -C $(WINE_PATH)/dlls/$* implib + +$(WINE_DLLS:%=%_clean): %_clean: + make -f makefile.ros -C $(WINE_PATH)/dlls/$* clean + +$(WINE_DLLS:%=%_dist): %_dist: + make -f makefile.ros -C $(WINE_PATH)/dlls/$* dist + +$(WINE_DLLS:%=%_install): %_install: + make -f makefile.ros -C $(WINE_PATH)/dlls/$* install + +.PHONY: $(WINE_DLLS) $(WINE_DLLS:%=%_implib) $(WINE_DLLS:%=%_clean) $(WINE_DLLS:%=%_install) $(WINE_DLLS:%=%_dist) + + +# +# Wine programs +# +$(WINE_PROGS): %: + make -f makefile.ros -C $(WINE_PATH)/programs/$* + +$(WINE_PROGS:%=%_implib): %_implib: + make -f makefile.ros -C $(WINE_PATH)/programs/$* implib + +$(WINE_PROGS:%=%_clean): %_clean: + make -f makefile.ros -C $(WINE_PATH)/programs/$* clean + +$(WINE_PROGS:%=%_dist): %_dist: + make -f makefile.ros -C $(WINE_PATH)/programs/$* dist + +$(WINE_PROGS:%=%_install): %_install: + make -f makefile.ros -C $(WINE_PATH)/programs/$* install + +.PHONY: $(WINE_PROGS) $(WINE_PROGS:%=%_implib) $(WINE_PROGS:%=%_clean) $(WINE_PROGS:%=%_install) $(WINE_PROGS:%=%_dist) + + +# +# Tools +# +tools: + make -C tools + +tools_implib: + +tools_clean: + make -C tools clean + +tools_install: + +tools_dist: + +.PHONY: tools tools_implib tools_clean tools_install tools_dist + + +# +# Developer Kits +# +dk: + $(RMKDIR) $(DK_PATH) + $(RMKDIR) $(DDK_PATH) + $(RMKDIR) $(DDK_PATH_LIB) + $(RMKDIR) $(DDK_PATH_INC) + $(RMKDIR) $(SDK_PATH) + $(RMKDIR) $(SDK_PATH_LIB) + $(RMKDIR) $(SDK_PATH_INC) + $(RMKDIR) $(XDK_PATH) + $(RMKDIR) $(XDK_PATH_LIB) + $(RMKDIR) $(XDK_PATH_INC) + +dk_implib: + +# WARNING! Be very sure that there are no important files +# in these directories before cleaning them!!! +dk_clean: + $(RM) $(DDK_PATH_LIB)/*.a +# $(RM) $(DDK_PATH_INC)/*.h + $(RMDIR) $(DDK_PATH_LIB) +# $(RMDIR) $(DDK_PATH_INC) + $(RM) $(SDK_PATH_LIB)/*.a +# $(RM) $(SDK_PATH_INC)/*.h + $(RMDIR) $(SDK_PATH_LIB) +# $(RMDIR) $(SDK_PATH_INC) + $(RM) $(XDK_PATH_LIB)/*.a +# $(RM) $(XDK_PATH_INC)/*.h + $(RMDIR) $(XDK_PATH_LIB) +# $(RMDIR) $(XDK_PATH_INC) + +dk_install: + +dk_dist: + +.PHONY: dk dk_implib dk_clean dk_install dk_dist + + +# +# Interfaces +# +iface_native: + make -C iface/native + +iface_native_implib: + +iface_native_clean: + make -C iface/native clean + +iface_native_install: + +iface_native_dist: + +iface_additional: + make -C iface/addsys + +iface_additional_implib: + +iface_additional_clean: + make -C iface/addsys clean + +iface_additional_install: + +iface_additional_dist: + +.PHONY: iface_native iface_native_implib iface_native_clean iface_native_install \ + iface_native_dist \ + iface_additional iface_additional_implib iface_additional_clean \ + iface_additional_install iface_additional_dist + +# +# Bus driver rules +# +$(BUS): %: + make -C drivers/bus/$* + +$(BUS:%=%_implib): %_implib: + make -C drivers/bus/$* implib + +$(BUS:%=%_clean): %_clean: + make -C drivers/bus/$* clean + +$(BUS:%=%_install): %_install: + make -C drivers/bus/$* install + +$(BUS:%=%_dist): %_dist: + make -C drivers/bus/$* dist + +.PHONY: $(BUS) $(BUS:%=%_implib) $(BUS:%=%_clean) \ + $(BUS:%=%_install) $(BUS:%=%_dist) + +# +# Driver support libraries rules +# +$(DRIVERS_LIB): %: + make -C drivers/lib/$* + +$(DRIVERS_LIB:%=%_implib): %_implib: + make -C drivers/lib/$* implib + +$(DRIVERS_LIB:%=%_clean): %_clean: + make -C drivers/lib/$* clean + +$(DRIVERS_LIB:%=%_install): %_install: + make -C drivers/lib/$* install + +$(DRIVERS_LIB:%=%_dist): %_dist: + make -C drivers/lib/$* dist + +.PHONY: $(DRIVERS_LIB) $(DRIVERS_LIB:%=%_implib) $(DRIVERS_LIB:%=%_clean) \ + $(DRIVERS_LIB:%=%_install) $(DRIVERS_LIB:%=%_dist) + +# +# Device driver rules +# +$(DEVICE_DRIVERS): %: + make -C drivers/dd/$* + +$(DEVICE_DRIVERS:%=%_implib): %_implib: + make -C drivers/dd/$* implib + +$(DEVICE_DRIVERS:%=%_clean): %_clean: + make -C drivers/dd/$* clean + +$(DEVICE_DRIVERS:%=%_install): %_install: + make -C drivers/dd/$* install + +$(DEVICE_DRIVERS:%=%_dist): %_dist: + make -C drivers/dd/$* dist + +.PHONY: $(DEVICE_DRIVERS) $(DEVICE_DRIVERS:%=%_implib) $(DEVICE_DRIVERS:%=%_clean) \ + $(DEVICE_DRIVERS:%=%_install) $(DEVICE_DRIVERS:%=%_dist) + +# +# Input driver rules +# +$(INPUT_DRIVERS): %: + make -C drivers/input/$* + +$(INPUT_DRIVERS:%=%_implib): %_implib: + make -C drivers/input/$* implib + +$(INPUT_DRIVERS:%=%_clean): %_clean: + make -C drivers/input/$* clean + +$(INPUT_DRIVERS:%=%_install): %_install: + make -C drivers/input/$* install + +$(INPUT_DRIVERS:%=%_dist): %_dist: + make -C drivers/input/$* dist + +.PHONY: $(INPUT_DRIVERS) $(INPUT_DRIVERS:%=%_implib) $(INPUT_DRIVERS:%=%_clean)\ + $(INPUT_DRIVERS:%=%_install) $(INPUT_DRIVERS:%=%_dist) + +$(FS_DRIVERS): %: + make -C drivers/fs/$* + +$(FS_DRIVERS:%=%_implib): %_implib: + make -C drivers/fs/$* implib + +$(FS_DRIVERS:%=%_clean): %_clean: + make -C drivers/fs/$* clean + +$(FS_DRIVERS:%=%_install): %_install: + make -C drivers/fs/$* install + +$(FS_DRIVERS:%=%_dist): %_dist: + make -C drivers/fs/$* dist + +.PHONY: $(FS_DRIVERS) $(FS_DRIVERS:%=%_implib) $(FS_DRIVERS:%=%_clean) \ + $(FS_DRIVERS:%=%_install) $(FS_DRIVERS:%=%_dist) + +# +# Network driver rules +# +$(NET_DRIVERS): %: + make -C drivers/net/$* + +$(NET_DRIVERS:%=%_implib): %_implib: + make -C drivers/net/$* implib + +$(NET_DRIVERS:%=%_clean): %_clean: + make -C drivers/net/$* clean + +$(NET_DRIVERS:%=%_install): %_install: + make -C drivers/net/$* install + +$(NET_DRIVERS:%=%_dist): %_dist: + make -C drivers/net/$* dist + +.PHONY: $(NET_DRIVERS) $(NET_DRIVERS:%=%_implib) $(NET_DRIVERS:%=%_clean) \ + $(NET_DRIVERS:%=%_install) $(NET_DRIVERS:%=%_dist) + +$(NET_DEVICE_DRIVERS): %: + make -C drivers/net/dd/$* + +$(NET_DEVICE_DRIVERS:%=%_implib): %_implib: + make -C drivers/net/dd/$* implib + +$(NET_DEVICE_DRIVERS:%=%_clean): %_clean: + make -C drivers/net/dd/$* clean + +$(NET_DEVICE_DRIVERS:%=%_install): %_install: + make -C drivers/net/dd/$* install + +$(NET_DEVICE_DRIVERS:%=%_dist): %_dist: + make -C drivers/net/dd/$* dist + +.PHONY: $(NET_DEVICE_DRIVERS) $(NET_DEVICE_DRIVERS:%=%_clean) $(NET_DEVICE_DRIVERS:%=%_implib) \ + $(NET_DEVICE_DRIVERS:%=%_install) $(NET_DEVICE_DRIVERS:%=%_dist) + +# +# storage driver rules +# +$(STORAGE_DRIVERS): %: + make -C drivers/storage/$* + +$(STORAGE_DRIVERS:%=%_implib): %_implib: + make -C drivers/storage/$* implib + +$(STORAGE_DRIVERS:%=%_clean): %_clean: + make -C drivers/storage/$* clean + +$(STORAGE_DRIVERS:%=%_install): %_install: + make -C drivers/storage/$* install + +$(STORAGE_DRIVERS:%=%_dist): %_dist: + make -C drivers/storage/$* dist + +.PHONY: $(STORAGE_DRIVERS) $(STORAGE_DRIVERS:%=%_clean) \ + $(STORAGE_DRIVERS:%=%_install) $(STORAGE_DRIVERS:%=%_dist) + +# +# Kernel loaders +# + +$(LOADERS): %: + make -C loaders/$* + +$(LOADERS:%=%_implib): %_implib: + +$(LOADERS:%=%_clean): %_clean: + make -C loaders/$* clean + +$(LOADERS:%=%_install): %_install: + make -C loaders/$* install + +$(LOADERS:%=%_dist): %_dist: + make -C loaders/$* dist + +.PHONY: $(LOADERS) $(LOADERS:%=%_implib) $(LOADERS:%=%_clean) $(LOADERS:%=%_install) \ + $(LOADERS:%=%_dist) + +# +# Required system components +# + +ntoskrnl: + make -C ntoskrnl + +ntoskrnl_implib: + make -C ntoskrnl implib + +ntoskrnl_clean: + make -C ntoskrnl clean + +ntoskrnl_install: + make -C ntoskrnl install + +ntoskrnl_dist: + make -C ntoskrnl dist + +.PHONY: ntoskrnl ntoskrnl_implib ntoskrnl_clean ntoskrnl_install ntoskrnl_dist + +# +# Hardware Abstraction Layer import library +# + +hallib: + make -C hal/hal + +hallib_implib: + make -C hal/hal implib + +hallib_clean: + make -C hal/hal clean + +hallib_install: + make -C hal/hal install + +hallib_dist: + make -C hal/hal dist + +.PHONY: hallib hallib_implib hallib_clean hallib_install hallib_dist + +# +# Hardware Abstraction Layers +# + +$(HALS): %: + make -C hal/$* + +$(HALS:%=%_implib): %_implib: + make -C hal/$* implib + +$(HALS:%=%_clean): %_clean: + make -C hal/$* clean + +$(HALS:%=%_install): %_install: + make -C hal/$* install + +$(HALS:%=%_dist): %_dist: + make -C hal/$* dist + +.PHONY: $(HALS) $(HALS:%=%_implib) $(HALS:%=%_clean) $(HALS:%=%_install) $(HALS:%=%_dist) + +# +# Required DLLs +# + +$(DLLS): %: + make -C lib/$* + +$(DLLS:%=%_implib): %_implib: + make -C lib/$* implib + +$(DLLS:%=%_clean): %_clean: + make -C lib/$* clean + +$(DLLS:%=%_install): %_install: + make -C lib/$* install + +$(DLLS:%=%_dist): %_dist: + make -C lib/$* dist + +.PHONY: $(DLLS) $(DLLS:%=%_implib) $(DLLS:%=%_clean) $(DLLS:%=%_install) $(DLLS:%=%_dist) + +# +# Subsystem support modules +# + +$(SUBSYS): %: + make -C subsys/$* + +$(SUBSYS:%=%_implib): %_implib: + make -C subsys/$* implib + +$(SUBSYS:%=%_clean): %_clean: + make -C subsys/$* clean + +$(SUBSYS:%=%_install): %_install: + make -C subsys/$* install + +$(SUBSYS:%=%_dist): %_dist: + make -C subsys/$* dist + +.PHONY: $(SUBSYS) $(SUBSYS:%=%_implib) $(SUBSYS:%=%_clean) $(SUBSYS:%=%_install) \ + $(SUBSYS:%=%_dist) + +# +# Create an installation +# + +install_clean: + $(RM) $(INSTALL_DIR)/system32/drivers/*.* + $(RM) $(INSTALL_DIR)/system32/config/*.* + $(RM) $(INSTALL_DIR)/system32/*.* + $(RM) $(INSTALL_DIR)/symbols/*.* + $(RM) $(INSTALL_DIR)/media/fonts/*.* + $(RM) $(INSTALL_DIR)/media/*.* + $(RM) $(INSTALL_DIR)/bin/*.* + $(RM) $(INSTALL_DIR)/*.com + $(RM) $(INSTALL_DIR)/*.bat + $(RMDIR) $(INSTALL_DIR)/system32/drivers + $(RMDIR) $(INSTALL_DIR)/system32/config + $(RMDIR) $(INSTALL_DIR)/system32 + $(RMDIR) $(INSTALL_DIR)/symbols + $(RMDIR) $(INSTALL_DIR)/media/fonts + $(RMDIR) $(INSTALL_DIR)/media + $(RMDIR) $(INSTALL_DIR)/bin + $(RMDIR) $(INSTALL_DIR) + +install_dirs: + $(RMKDIR) $(INSTALL_DIR) + $(RMKDIR) $(INSTALL_DIR)/bin + $(RMKDIR) $(INSTALL_DIR)/media + $(RMKDIR) $(INSTALL_DIR)/media/fonts + $(RMKDIR) $(INSTALL_DIR)/symbols + $(RMKDIR) $(INSTALL_DIR)/system32 + $(RMKDIR) $(INSTALL_DIR)/system32/config + $(RMKDIR) $(INSTALL_DIR)/system32/drivers + +install_before: + $(CP) bootc.lst $(INSTALL_DIR)/bootc.lst + $(CP) boot.bat $(INSTALL_DIR)/boot.bat + $(CP) aboot.bat $(INSTALL_DIR)/aboot.bat + $(CP) system.hiv $(INSTALL_DIR)/system32/config/system.hiv + $(CP) media/fonts/helb____.ttf $(INSTALL_DIR)/media/fonts/helb____.ttf + $(CP) media/fonts/timr____.ttf $(INSTALL_DIR)/media/fonts/timr____.ttf + +.PHONY: install_clean install_dirs install_before + + +# +# Make a distribution saveset +# + +dist_clean: + $(RM) $(DIST_DIR)/symbols/*.sym + $(RM) $(DIST_DIR)/drivers/*.sys + $(RM) $(DIST_DIR)/subsys/*.exe + $(RM) $(DIST_DIR)/dlls/*.dll + $(RM) $(DIST_DIR)/apps/*.exe + $(RM) $(DIST_DIR)/*.exe + $(RMDIR) $(DIST_DIR)/symbols + $(RMDIR) $(DIST_DIR)/subsys + $(RMDIR) $(DIST_DIR)/drivers + $(RMDIR) $(DIST_DIR)/dlls + $(RMDIR) $(DIST_DIR)/apps + $(RMDIR) $(DIST_DIR) + +dist_dirs: + $(RMKDIR) $(DIST_DIR) + $(RMKDIR) $(DIST_DIR)/apps + $(RMKDIR) $(DIST_DIR)/dlls + $(RMKDIR) $(DIST_DIR)/drivers + $(RMKDIR) $(DIST_DIR)/subsys + $(RMKDIR) $(DIST_DIR)/symbols + +.PHONY: dist_clean dist_dirs + + +etags: + find . -name "*.[ch]" -print | etags --language=c - + +# EOF + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..65a0f1e --- /dev/null +++ b/NEWS @@ -0,0 +1,15 @@ +0.0.14: Converted to PE format + All system libraries are now dlls + +0.0.13: Mostly bugfixes (I think) + +0.0.12: Added support for multiple processes (not really tested) + System calls + kernel32 now compiles (only as a static library) + Fixed invalid tss bug (hopefully) + Added section support + Added some of the ZwxxxVirtual calls + Added prototype caching functions (only the Minix fsd actually + uses them) + Added handle access and type checking + Prototype APC implementation (no support for user APCs) diff --git a/README b/README new file mode 100644 index 0000000..c07458c --- /dev/null +++ b/README @@ -0,0 +1,24 @@ +About Reactos + +1. What is Reactos + +A project aiming to make an approximate clone of Windows NT, compatible +with most Windows applications. + +The project has a website at http://www.reactos.com/ + +2. Building Reactos + +See the INSTALL file for more details. + +3. More information + +See the doc subdirectory for some sparse notes + +4. Who is responsible + +See the CREDITS file + +5. Recent developments + +See the NEWS file diff --git a/aboot.bat b/aboot.bat new file mode 100644 index 0000000..a7540e6 --- /dev/null +++ b/aboot.bat @@ -0,0 +1,3 @@ +loadros system32\ntoskrnl.exe system32\hal.dll system32\drivers\acpi.sys /DEBUGPORT=SCREEN bootc.lst +rem comment added and changed for no reason + diff --git a/apps/tests/alive/Makefile b/apps/tests/alive/Makefile new file mode 100644 index 0000000..7fdd123 --- /dev/null +++ b/apps/tests/alive/Makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = alive + +TARGET_SDKLIBS = kernel32.a user32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/alive/alive.c b/apps/tests/alive/alive.c new file mode 100644 index 0000000..5c99760 --- /dev/null +++ b/apps/tests/alive/alive.c @@ -0,0 +1,48 @@ +/* $Id$ + * + */ +#include +#include + +HANDLE StandardOutput = INVALID_HANDLE_VALUE; +CHAR Message [80]; +DWORD CharactersToWrite = 0; +DWORD WrittenCharacters = 0; +INT d = 0, h = 0, m = 0, s = 0; + +int +main (int argc, char * argv []) +{ + StandardOutput = GetStdHandle (STD_OUTPUT_HANDLE); + if (INVALID_HANDLE_VALUE == StandardOutput) + { + return (EXIT_FAILURE); + } + while (TRUE) + { + /* Prepare the message and update it */ + CharactersToWrite = + wsprintf ( + Message, + "Alive for %dd %dh %d' %d\" \r", + d, h, m, s + ); + WriteConsole ( + StandardOutput, + Message, + CharactersToWrite, + & WrittenCharacters, + NULL + ); + /* suspend the execution for 1s */ + Sleep (1000); + /* increment seconds */ + ++ s; + if (60 == s) { s = 0; ++ m; } + if (60 == m) { m = 0; ++ h; } + if (24 == h) { h = 0; ++ d; } + } + return (EXIT_SUCCESS); +} + +/* EOF */ diff --git a/apps/tests/apc/apc.c b/apps/tests/apc/apc.c new file mode 100644 index 0000000..aac7fee --- /dev/null +++ b/apps/tests/apc/apc.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +VOID STDCALL +ApcRoutine(PVOID Context, + PIO_STATUS_BLOCK IoStatus, + ULONG Reserved) +{ + printf("(apc.exe) ApcRoutine(Context %p)\n", Context); +} + +int main(int argc, char* argv[]) +{ + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING FileName = UNICODE_STRING_INITIALIZER(L"\\C:\\a.txt"); + IO_STATUS_BLOCK IoStatus; + CHAR Buffer[256]; + HANDLE EventHandle; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + printf("APC test program\n"); + + EventHandle = CreateEventW(NULL, + FALSE, + FALSE, + NULL); + if (EventHandle == INVALID_HANDLE_VALUE) + { + printf("Failed to create event\n"); + return 0; + } + + printf("Opening file\n"); + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + 0, + NULL, + NULL); + + printf("Creating file\n"); + FileHandle = CreateFileW(L"C:\\a.txt", + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + if (FileHandle == INVALID_HANDLE_VALUE) + { + printf("Open failed\n"); + return 0; + } + printf("Reading file\n"); + Status = ZwReadFile(FileHandle, + NULL, + (PIO_APC_ROUTINE)ApcRoutine, + (PVOID)0xdeadbeef, + &IoStatus, + Buffer, + 256, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + printf("Read failed\n"); + } + printf("Waiting\n"); + WaitForSingleObjectEx(EventHandle, INFINITE, TRUE); + printf("Returned from wait\n"); + ZwClose(FileHandle); + printf("Program finished\n"); + return 0; +} + diff --git a/apps/tests/apc/makefile b/apps/tests/apc/makefile new file mode 100644 index 0000000..28f8f14 --- /dev/null +++ b/apps/tests/apc/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = apc + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/args/args.c b/apps/tests/args/args.c new file mode 100644 index 0000000..91b0d0e --- /dev/null +++ b/apps/tests/args/args.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +int main(int argc, char* argv[]) +{ + int i; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + printf("GetCommandLineA() %s\n",GetCommandLineA()); + debug_printf("GetCommandLineA() %s\n",GetCommandLineA()); + debug_printf("argc %d\n", argc); + for (i=0; i +#include +#include +#include + +#define BUFFER_SIZE 256 + +int main(int argc, char* argv[]) +{ + PRTL_ATOM_TABLE AtomTable = NULL; + RTL_ATOM AtomA = -1, AtomB = -1, AtomC = -1; + NTSTATUS Status; + WCHAR Buffer[BUFFER_SIZE]; + ULONG NameLength, Data1, Data2; + + printf("Atom table test app\n\n"); + + printf("RtlCreateAtomTable()\n"); + Status = RtlCreateAtomTable(37, + &AtomTable); + printf(" Status 0x%08lx\n", Status); + + if (NT_SUCCESS(Status)) + { + printf(" AtomTable %p\n", AtomTable); + + printf("RtlAddAtomToAtomTable()\n"); + Status = RtlAddAtomToAtomTable(AtomTable, + L"TestAtomA", + &AtomA); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" AtomA 0x%x\n", AtomA); + } + + printf("RtlAddAtomToAtomTable()\n"); + Status = RtlAddAtomToAtomTable(AtomTable, + L"TestAtomB", + &AtomB); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" AtomB 0x%x\n", AtomB); + } + + + printf("RtlLookupAtomInAtomTable()\n"); + Status = RtlLookupAtomInAtomTable(AtomTable, + L"TestAtomA", + &AtomC); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" AtomC 0x%x\n", AtomC); + } + + + printf("RtlPinAtomInAtomTable()\n"); + Status = RtlPinAtomInAtomTable(AtomTable, + AtomC); + printf(" Status 0x%08lx\n", Status); + + printf("RtlPinAtomInAtomTable()\n"); + Status = RtlPinAtomInAtomTable(AtomTable, + AtomC); + printf(" Status 0x%08lx\n", Status); + + +// printf("RtlDeleteAtomFromAtomTable()\n"); +// Status = RtlDeleteAtomFromAtomTable(AtomTable, +// AtomC); +// printf(" Status 0x%08lx\n", Status); + + +// printf("RtlEmptyAtomTable()\n"); +// Status = RtlEmptyAtomTable(AtomTable, +// TRUE); +// printf(" Status 0x%08lx\n", Status); + + +// printf("RtlLookupAtomInAtomTable()\n"); +// Status = RtlLookupAtomInAtomTable(AtomTable, +// L"TestAtomA", +// &AtomC); +// printf(" Status 0x%08lx\n", Status); + + + printf("RtlQueryAtomInAtomTable()\n"); + NameLength = sizeof(WCHAR) * BUFFER_SIZE; + Status = RtlQueryAtomInAtomTable(AtomTable, + AtomC, + &Data1, + &Data2, + Buffer, + &NameLength); + printf(" Status 0x%08lx\n", Status); + if (NT_SUCCESS(Status)) + { + printf(" RefCount %ld\n", Data1); + printf(" PinCount %ld\n", Data2); + printf(" NameLength %lu\n", NameLength); + printf(" AtomName: %S\n", Buffer); + } + + printf("RtlDestroyAtomTable()\n"); + RtlDestroyAtomTable(AtomTable); + + + printf("Atom table test app finished\n"); + } + + return(0); +} diff --git a/apps/tests/atomtest/makefile b/apps/tests/atomtest/makefile new file mode 100644 index 0000000..f78316b --- /dev/null +++ b/apps/tests/atomtest/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = atomtest + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/bench/bench-syscall.c b/apps/tests/bench/bench-syscall.c new file mode 100644 index 0000000..447bc0f --- /dev/null +++ b/apps/tests/bench/bench-syscall.c @@ -0,0 +1,8 @@ +/* + * + */ + +int main(int argc, char* argv[]) +{ + +} diff --git a/apps/tests/bench/bench-thread.c b/apps/tests/bench/bench-thread.c new file mode 100644 index 0000000..ae17b2b --- /dev/null +++ b/apps/tests/bench/bench-thread.c @@ -0,0 +1,82 @@ +#include +#include + +#define NR_THREADS (30) + + +DWORD WINAPI +thread_main1(LPVOID param) +{ + printf("Thread 1 running (Counter %lu)\n", (DWORD)param); + SleepEx(INFINITE, TRUE); + return 0; +} + + +DWORD WINAPI +thread_main2(LPVOID param) +{ + printf("Thread 2 running (Counter %lu)\n", (DWORD)param); + Sleep(INFINITE); + return 0; +} + + +int main (void) +{ + HANDLE hThread; + DWORD i=0; + DWORD id; + +#if 1 + printf("Creating %d threads...\n",NR_THREADS*2); + for (i=0;i +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + HInst = HInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow( + WndClassName, TEXT("BitBlt Bitmap Rendering Demo"), + WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 220, 230, + NULL, NULL, HInst, NULL + ); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +BITMAP bmp; +LPCSTR filename = TEXT("lena.bmp"); +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load a bitmap from file + HBITMAP HBmp = + static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + // extract dimensions of the bitmap + GetObject(HBmp, sizeof(BITMAP), &bmp); + + // associate the bitmap with the memory DC + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + } + } + case WM_PAINT: + { + PAINTSTRUCT ps; + const HDC Hdc = BeginPaint(HWnd, &ps); + try + { + // + // TODO: add palette support (see Chapter 9)... + // + + BitBlt(Hdc, 20, 15, + bmp.bmWidth, bmp.bmHeight, + HMemDC, 0, 0, + SRCCOPY); + } + catch (...) + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + DeleteObject(SelectObject(HMemDC, HOldBmp)); + DeleteDC(HMemDC); + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ diff --git a/apps/tests/bitblt/lena.bmp b/apps/tests/bitblt/lena.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e9916963852a9748baf1b9ac6093fb3b9179dbbc GIT binary patch literal 89322 zcma&vKawKP@-6s!8<;{I4aBE`G%DEWW8?zHjNC!81K0uV0Q9jj5Jsnj(W`b)EkC7u z2R)zTkx*23-}jro@#QATpUMnBas0T4NASP@AOGY3{BJM$_rLk?zx(h1^56gMzyJ2~ zzj}Om`G36r|Nbv8^iTRl^JZ=GI$bT-i}|u!d0Z^#%T3qMr@m;u znlBH-cC}cp{cpb94ZHnzKb_3Hc|KdbzD{!ivt>2kznnWiUrr`Ix}MEe_w%mP`EIt@ z%~$({wmvRaCvDlC=BtCRs#mwm^>MX1uR86r+PLMb$3L2ry5iohOK-ckyt7Z!UF-gq zHr(`{KHNODe)rz*--rFj_VBSge(X=52ko48JpVXdTKjpr{5)NMp05smc)Y#;?uX-a z-gm>b8!n6WuIu+*e^~d&?yGrvSZ~I*8V~mC&2H80)}6=wsyi$@w|QD_PV@C~>3+Aj zHM<`^kJq0K16?ri-t9jc05*$( z1%sgR^>sFx%)C0Atv8#!$3n$o;si9!*VFj`NAvZLt(Pm^s2`5=)o~H!zaQFm(-SM+wfc5X~vtTfq{(*tFkKY0I zyl1|3e`eoqII{TN(9Q15U9CTWM=YMFyEGWcBMj_eU{P%~T!!Q4aQe|5K6+Pj`B4~n z-|RkIr`Bz6kAwB#mM^`(zTQ^PvuRrOe+~?1$8B_b%2JLOdVaQQW0rl}$-C{wZ-575 zA4pg{%+L@rVU^|3^&2qQ^xble2fB5?T&!#C&tTx?Wipxg#L~fRzM0N8^Z91GzjeUB z?&tH6z%=*_Khyz3Zy0*P=<9Px00z4Ae0`cNdepI8Zk8+k0~-PSx&wnt2%*?u9QbAT z=i?CuHSq5YF!Deb5*VqVVDKIWs5b218wot|KrryI{;|e>o?b%&m$%=}yu7?Fmi>Bj zS@q{O-n;&^8OBln82%#+I@W)@6w_A=AuPMYVtrWk0l@b1b9epKpMPwQKX#Xq2Vj8p zHFmEC&j5c}bm#SI-}i?i*s|bbbl12x29f-F)xiMkFza%@X0_#fWtbOWJT{|z15dCq zft3}HFf(SWVViBg-EViBRkz*reb+DZY8Yd+1g%BBdD(9^yM8!z-OhzASN(2#SmeBG zSUwuihOfdK2K%r;{wprv6ds77&rVLJ%jKe5u295zQB=RK$L18q;a{BZc*H>Yi)SkM zasi_k2mtgUBK?Me0>Cyr5E2Lv+(}@>!1X7KJANR6BiIb*U|_*d76vwZXorEggD+b@ zj*AVR&VR>1sKAA7Pe1q9-@EJY;rw%R`mt?1!29n|LF0iE1609qgK#_m1ItCPGufJn z8KQWAXAdMEoWQ2q>+6J>3|_}~{osYwVqt{Vo9k2U%`EG{tG*Kkmh;61bM;$P&||S- zJ8YsufMf_T_8iCMbUhy~kkfTrULb_tkuRr_KXMg-L zoXZ!C7ytvR021EGgJ58|!9dp?m&-wiXH2ybO}W7X3NLpMRFsQnBZRP=QF0xt#ORZU z2yE|Xk^86O3xa_~zIILz001vQBCeM!Fxd73kH8&lhg~qB6L0V9`RXPAe6R0c#^cBO z;fiMr6azT#qy~OquwAWBgdcMg13bcFxtmTS7#0-o>Nt-Wh!<#&&m;Yt{QCm{o<0O& zlY-RXvmpG_5q!r$0Pv*)BLk|PuRpGDzqFT0+$(WQ4-l>efM6gd?*AhO?!eeLB@jnI z4s|dv|mi5O#pu&M-004*{h^!J6JOSWu9*7!zVBm5mfl(5K1a^nZ%Zu(^==@bw{UzZ* zG$9OltoAP|cwpem7u+$x9c+)EhuiP{?H5(R9cTtsjeUCHfq{?0z#D`c9h?4aq)aLh zXasBUHv5)M1Bo)hIO@0EFmywEPvlx(`a0e34hUgw3;OnBhqegeW%GXY1eN!Loj1g8(40K!pP$g7@K&sBl|R;g=W~9YNUO zLIjQ^@CzZlfBYtOUS5K8H@eyc10D+l#Q27#OI;ZjW{2mrBTmz%hA5U`U{>Tx{TKU#FX8w;x1v;Q<(+ z1ZV~y$!G8RgnWuGC-LS<0!Rh0tl`fKEDHv50(iig)BXS(Gy}Kt`ZB=`!*)j|=@ws} zZ(eNX-1@950Jy400}Ra2@ag1Agf(046BVwGBL=2%BC92}uv>JrV#7cH&@k|fgytRo z=7cXz*usH7asmkn$Fx8N1x*l^7`PCDCz_=UytIGwJi6RLE>&-{gf>%-{5#$Vw;EK=Ga7%1!C+2AQPG^Pat zgL_o?FAOv_c=>U;Vt`*@00W2P4GHKdU8LWZ>wW&v=F|lP5)p&>%{H-8q6!RB*ZdyxgJ&XY-E#Ef@nTQP>OXk|~NBqz~l@?-*!=5ON3=G%@f1 zL&-vSy~P6y?tn1x+1+g$H7GXx`NRXw^xrUm_hyvRdVjinaJzc4>=+uak<~Cz-9C=B zAi;lYp_}B7QQ8uQO*&4A|BjV8eUH36{%7%(Eb+R-{K3F%*>MXlbl5{44A2S7#d@{u z03aCXpyIgSoduz}7^aRLSM$ma!9ZPDE+go0GQd~{8>I{diCn)_bOHhSfk|FUnrOLi z7$BP$1%|RdR7lOW@g593TEfOZF+dDFM+B5W>47+cz~HV2K4BorysRHz&|-mL;Kvyi z+~Npy_{$3<=i&oYJh0qswyuHogMo;{KQK@L_y-0y4=TU|fx(1QCLl0*rZLLykbw__#j|!(Id@RoHI^c-Rhy zdlo&-gjXSR7n4UeZJbaTc=UW;!V<)Qct7Uml*1nE!P6VdKIYVlI|xNoo)8%L1xldA z;fnVM1E`Q30K3C>-*0w$gCP9%gMytN<%pL3OA;1yT)-F9U~vu5*si25qc9L)z(B4% z0f)a++W3@&;c`gK7%dTBfE08egzJM;Vqo@Teb(1V#+RDLnDOJs!L(fiWU@ z%Oueu4DbgDGz>I%Fh+>Q2J%85KYo*5Nq|Jatm@W+0XI7AZZII_Tkast|5rOac;G8_ zOeHova0lz{nlF$nN`P=AffjggbN&khqcDI02_pTl+g<0g4h}Pv47_;uVBy~38R?A{ z8Y(=t0iHJ@0oOl?cZe{c2^}x_{*EtbAb|nqfeNYs7044x1Uv3KXy6Wp#bPb7KWw(= zqpO`VD)xK?Gp|AhNI|0RVu3CK!Bs|D}T~9p}Q9@>dyp^Rr z!~+csUl@ol2oE$E>|lvI04jdrfq@njBs)|QVlW^8*<9Yo=#lkda>wN zLdARDpmK)Cv7DgQ5{!Z20|xD&s36vFtsFtc0uKRDV&LuzLIUA|F(|kQ4PyG%Dk=1{ z%P5=F@ORmI8%kYpVZhWmN=MG!aU(W-)`WK$L=W8Kg3%X55H=aG;|1zV2^;&A3gEh^1#d8Y3;?U;Ec2t48_a~!zLyq02re+s`FK6-PSrWf%n?YP8(J`cOPT3XXA2%@)ZH z1rN*3ZMr;l^Zs!Dn2}8L&8yKqU%XB;W5n%}c&uzrM_P{`r|VFy`5lI4V%pCzhZb?% zTJ+ZqGj#DXA@3y+V!ddCqzB!wq|jz9OCTvEMcDVN)h3xzPG@yJ-HHuf_uGTh{%E{p zqW)aKa?#DEp2p~{HD}ZqX*?Oucga4I!L?X!5JJHQunEF}CKNNWyB@}Vq*o-9e6p$Y za{Z5}@CyJX6umm?0UEmqVc5S(#-{Bh1b)Z~IBo?4`{R$p>F43}!3*rqKM$8*&YK>3 z`}n!(F@Q8cf|MHjF3$xA1I1l(BN&r9W)y%lM2?9L*xlnO2JTAW9uX80iUdjn$j3(v ztlVtxmWBKLpZ)HKfip>WGvFfjuK)oI!uAxJ zS)5Gz#GvKeg?SqU?hR9pV492&+UM(s8uFfc2@+BFluG4eM^(ZCGk0iGMgH zNjRDJN=0_Z9HW0;GLk+XAs849`oKUt@P_e>g9He746u6%tw18tA`B#86g2S&VS^B0 zO)V7+gyfgVgTGpX2d4=JW{6raxIH8#XkH)(9-9nkH3Mh9pa4+C1CB459Q?6LZHyap zwdl0>hydgME|U^u$r&=h9RraKW(14|1I2zk z!WRZoEv6a%VE}TWr2-ZB_t4GP#)hXL$)vg1qdOK;0V|!s&9eG6$fS#fnAaS#TzaB@7FUp zFkiT$30c3V9TxNfJSaRJk$;cc(JCA@SLmciL#eXC zKWJWe)O1d+yduFT48XaY4GC!J;n{k-e>X6V_m(2KD?nEZ41C#cd>oSiv3ps+kM-44 zRU5w$Ap{$mj(uq*PdF{KHj=>Atqr@k^X1oUagJ7Tg_GrEKHHyu#|`WKVt7`Ty9+3C z7YqOI%vx#L)M$?wn7cRAGrPS<4G&}*$Q+cit>bCCF&8jRXt3l6xazg!FwMYCm@|?g zWINR($HUQJDd5Gp(Sb?vH4LP$?i%132IDc9XoZ}H0pAcHl}}4hAnHj;VTOF^0oIQ% z2n>`LW_Bh37%`Bs{|yYG2+jp!PXj`{uUG4ia%}-; zc)*Ot&_tktQU@E}DhJ*$U2gYpMb7&MgAoj2g95;4`m(H1Z$4B3RmT3txb(=IWSTX{ z^)wTv-mt!7KxotQ19;#aDqy<}gtzO*didd*IV6>09w$?Z&Oh#epl=Y3=$e}+s=`0k zZ${znJKks`@k`@%l74g}TEGU*lL5!wZdD|J^E;rV6lexT=4!=XQ&9~t=Kw$)SgD3& zp7DTgVbJISPO2R{ESKsH-`X<)ox znO4$W0&}(fEn6GIFHrYD!7u?62LsqWOvN;M82hi9j{pO2pbw4ujUaQ_cFUDB-X{6K zk~)|zoK!)IAJ#NkWe9~8%OzxTAN$+ocHHi!uk=JDfzSH?h5=Mi7y!vH4E$mJ_Oy{e z1zZJy27`Q+3+8G!=9DvU7#VQNkgr5>!9Z^Z6=`t|4FJ~;^Cwuy@Yf(AJkZ?1HW=8A z7_f-oLxr$uAQQnLPuRGxN$vq$4WnSS=m-zQ7r+2tP$41yU%~cb9t;3O@$do%66Z0U zoel?&TcvW~u<0p(2oXAn2-G9tA7A1Px@=O+^Bn{Jq`uOJW0yK^eOr$?uI^pJK(WLF z20A|&2oES8$b5mp6&Q3fz?B&o^8>~Fv32|cbB`EkNFbS-^_eD;V0()rsA8c?{(PDP zpQIB0Re&7Z=Z@WXt|wPG>Q!KH{mTai97OXZGl04`U=YduIvaKop8^2|4>7l7R~=;d zgF%E1zm|jXxPn0zmn3X+MubGILCDiCOAod}hVa0>a$ux_$DC1O!&A+#tg6v42vdncLFH^%uMgYp zcG!Bl-wfB|`5+%iFuzU{6x8?Ez{wviZ*IuwA`wTruG!sRZ14R3m{%K4>Vr9Mf>8J( zF>bp}x z)yXp}TH952Xy1&^?p2EHX|)O)3mC~B{|5|=HKi%2UhP~%Ze+@H_k8i>wNcsJl_v%S zgV7y?5M<|=Lv!bI$zk~~^};n_)!`atrv=6^^|Ti25rJ zrg~7*crRZ4;(6+h{nQ<}Jn}o0G?pPTB+-6e9<2WS?*2UZU*0F-{p3%KZ zEeHq5KWB1MM`wy~vrH;!z;d--Y^OK47}AMx7m=4nkB=Ipp&d_04BY*D!$2HRjkxcR z)x#P1%>#D2D$+(GuUhL zs2Td$j;%*)V?PVi9>+xs1&{hv^9XqagZP3!05DD)B~RG&z>b$JNW4*F%n*YD*NB0KW6hiY0f0McR6lz|Fwl&CKMt@fj2f~uHN*dW4+=~i7}S(M z(<>Dy3{+Zp*nRZd_h0}LSRW@0RKdH9$|j!T+$qR67xUWKuYvG>7b7Rc^mV~G(7oR< zVBW1L%e7V5=qYzR#{+}Kl>;|~3Tm)hbCmW4gF6xeiSa#8?x5HJ3|N0`_~fAnYWDCw zlLZf7P#B0W&`aq$$)D|Nx#baDVKKw1cp&!@#|;F90Y1V3yHkBU{(1=nV*g%*2m`#p z#!Lc)m_(jT`;B8OiQW{9Ot=}L!=itC`%pAdb4I+(oMUZN;14_ob^7h!!@uDned{{E z-k&}%3>2a1+uT=zXx87hxWEi@6_MVppT#D@z!wR?KurIhnt}U)aNyBc2LLo)8^BA_ zr0X(1a={~popDEBkEw?-D|6?82L>unSge(4qlN)I;IFi@(gMH;gJ$&ab}yWa^GczG zVvjEXK*AFSQc{=zp{+A&Yt5nuPK)J!HtQ-yuf}V?TnupscOIw%jGYl0!|U{gkrhZp z56l;*-Ja~<7~2TJcToofVUo#94UOQ0Zbf65E+H7ylgJS(u6|$dJ`^VFL&KioVJcJ* zU+^$-x^x`-kAu8Az9B$u7#NAy({&B2jD4jm0Khe6_*X4i0FYDw00aY#1oGJ20XEot z%@U%85d%>LXd#jN7$-)volu8TRRqrTE~EMf5+0Z5WMSaWR8JV-FuVGQffh#~H1PC0 z2Ixjq`z{3=9ts<=ep3r28Vd#y5|NR29(e!q2!Hax4hFbRvoqV_)O>;A z9|1t-%~$IcmT+tA59HH`f2U0^7~`w;?Rcd6Omx9L0BEbZyzojYcrg`JtOi-Hg<0vD zIR*THUbfrg_3}QPf14(gA4otFl8Gw#GWtlQ>C$v&Vc@BU!vL-2QVF1YR zFB!kD3Zmn3B}X?<2C8*YBjW^qmnsDbVZqC4l_1)f}D!bd9 zBUB0lP+WxXMgq}1e#1a`Ah98E5>3eufX#@3;C2=ahzsPP$`=F!lwoEM8|T9Sk5EXs zV*?2^ijefU69NfQrhoDUhX)46S>sSa-Bf==gDpQW3#Um7Z??lxZQ&y8H+PIxH#k!d zkStbi%}m0S=3nUcN#X)tz(OI@!N8%@RR?)hnutwhd=P?(@Qo-zVsqwW{aV6&zT54u zTPq4pGMslD;U}BTA0cT8KQn1~Egm&G?qG3QH0tONqSa0$T1H8{Evq-5qub0|m7AXfO zccFN!Y7>tKEkNqNFi>8=YNIST!U@51swiwN?mj!}ClpIY0>{QD81W-lQaArTnB0QaZR^C?Cm7NCqb?mpeJA%jF&X46D=a z*Nd7T*os3nSdhQ==*eZE*lgW8bA0-Qfl>wfv)q~f1jfNMHNO-RsPv%lziP>d`O`=O zv3pD$B~XtK0Nk_3&~j3VYEo;q*k^N_d+hDWn7A%GobU_)S3ZV0rp56< zr3V`iRB9+NPMlbnfq}k1N)-lmqv~kG-0*i03=}7{lTR>s=z+5P_sWxiq47XlYt~@k zm@p{Cd&6c%y{V$uHp6;zJiIqI+O4<61BR{@B^z0+<`Hn5GbWCM0Sr>>#gP2A&+1VK zfrq6*XgT?I@0~*ysG2MoPN(a(KTj9OZoU6}|9G7av( zu=wV)JxPLuHoyx2r9w|4s*wb0_=hM)U_9{vNZbq0T5bUbYTz6DqabXl;}k_?wdrxA z#BMRfmnD1CDNXGAv(Y3*fC>yu^&7|mz?33bsv{x`VZfP?;9|iY4C@Vb#7C@BC&2EK z2AMd>?ej7QWM-Bqg4^rjvRa*feEeV?EIM6pRo#Q7dNcxKGV{-;(kFFEc`PXAOtrB~ z<4*~~ba*hp*Hlu7zM=z1{x^{|>cCVD6$3;Gq#6FTHxV9Cx^uJUj(32HB+V>D%JO8s zGVfV;Z`!7R*Sh{Ki`KoWWzso%GL>noo%JkrdCwS#%Ke4`*O^iO7Y1~GVPKGj-p2J5 z1_Fi*{4Wv+0~9dsNEn^M7$oM+vHqjQ9eDbMfeH#59+LQqgS#wO2ZGKL0}KEIA=24q z7%mdJ0)(WFo1ru0n=qS`ZaFFAL6uSS^SR02&T7F|_m-$oPyh+5L>4QOZzE#xMVsUa zm;L)}{We`5HmmLB@-bcXFT~qwdq`2%Pt!@0LGP~BS)sGZxfMKayhLV!OopzGE;uy~+hpsN(zM!F+1Amnf0KbihfJZvD3Nul&W ziGd7f4B&idAq$b1*!M*gun!Ce zv^BsRXoG<;z$S^onkR~P2s0pC?+k(Lb{Cb;BL;Gjgu!{l02ow^P)08?Q10N%*3Bt= zk-&ou!UIMAS!9` zfUDExmsAs3aEC!Tf>8a4hwwlnfsFc$BmLGG0E*JR6Mo)0=?Fjqt{?O}G662EjnQ*aHJ#@W4RO zqSHhmd$ME?16eVOlp+i9Kyw7~3zZ-E3j-qnoc|j8&#oaD7;A?T5;kR+*l^sV@>Fqj zpDUcI@-hUrYJ}(W%=ve#fzdgA+&Jzg}|GIy^KoQP6;}J__u#<&d?+ug8 z1EsWas1*m(*B4*at#Bj;yjt*jl*QN1rL2F!omsD+0Gh`5LXDw1;?_2?#5S*0R#~c8y*;M z#5+~i>9~z?VXcsezLWp}fNNo33=AU`9(v$0_D4zZV1s8WC{#2Iuz1xKH(yZ8&F=e@ z%A*?l8BL+ne!IOe$82W4cfYZMmG+b8o@d{Hq=o{CSef-1v>x*m28?}g@XkOY5^)L% z*Z@UjE#a%!NB2NQ?(}%LsXbv|QzUW)-B#~yL?wD=ceu`0CxFS^LP81`!`$h{c94_t zr-gxBOkuz(V|k%DF_3)V7X}dB9Ro43!BvJXFc1Sx{0Az<3?&tiaCrEZ#9$udG)F`g zv{Yv1WOwnZX$2_)mgC%5uPwmDT04u;K>&}Q$gd0rU}1zV8lQrKXYp}3U-kJ$q#f0SuV$}05Cu&Q1W<~ zp_#S6FDP>+=0*U81jp-$!&o0Y0s!Z$f`|)PGvPRkcz&I79ejOm)|eF~!Jb){|f^#E-z4y zpzu&n%kE|IN6M%PMUTON$)l<&S4V1Ho@Vbs(#5KxR$8poBx@F`P`UCgwYR_*31pb# zOBWpVR7yZ^Hw?Jh!gi7aqH;U&tm7*OOrBEbCk!-6@E>^KI|iERACKQKfC}FJ(1evM z-m^tvV3S0_e6!im?HJq2!R^vD8@t(0W+Uwr!B!0bIEcVt1VgyOpiNaFR4|4mW$Vor z4AvbIATn!LkeLp7jp|!31ra72vk%YVu)m(KLdC7f&c$rjo89T>>q`KWUV_82c-g&S zVD-QN6|qhY?Y1I`FxqwWlZg2x<^(*#d!)%@xa`tn%(O$ z!^#nTQX7^_d+=am%15bJ&6UR>&5D*m)z<^S#w0Xa@YgB*E7A1?An}1&x z44Av`$;Gab18jJSnbxaytiMXl*fOM{mMqC4EpsJsf=mEpb*MQqj1lt@jovuaN?Qw& zk0+gZOu`Tsbz3X-3;{4$rm!T)xwi&@FAU%l5dj{M(yyRETA(6=27rcvhuz168v9KD z)QtC*Hu)liki$q3+ub`Cz!8KKj-SWV2R5)=E0SQ$5}*P`r0r?NTwX8$sA(`e&Gb~76uY0{(*sW0{}4G@$el6&tQm8sXXCddf-u8UcMka5TzG`Pi{5K?_ZaeLvOE750BWSO{@cAp3O<_mH)de#qisL!@Uyw>jz3OTmK6rT z=8l02N8nFGLV9x4FkC=jaHp?`nSwL`Gz^r~A%;~D*;1@9;HA+Q{Qt$k=^iFHxF0|B zK&>#!+;KLi`q=Ep330w4`}Ww$t?_`25CGJe5)>?!hsAto)NQbH1T~hk`j{`bbqo^F zg#Rmg&{r(i6rkgcl*;bF9ncT6xc)%sm4nIB-FFz6*oT(&ad-ld*=v}>XZw7j-&x0J zXDzb90=T^`)82o-yujPbodh18nIVRwh!$JYmB`$+%m6Foz8=Yer?{X7buci(pzM1$ z{fGgjBRTWL4>iBQp(w-5WC$IXp4L$OA1iaCZlMK`vWT z^dgiN+X_{TccB^d@?~tHLZ(YyS#O*wAfybnH7B2h%*tW}Bc0xZie)L7S3xoR1e2DG1u#> z%kx1)CK$-DLP~k+vRv)JeT)lBD`Rty1qed?Jn}$u{eO_a!xxknXuco=KNv8t6q_2? zSH&_ld34ib0zkE1`@FOxa1l_snv>>*qU)Hv9Y}IvmdbIMCkP{mUik;6GPm+X}=ok@NAYTU2jf2Oa{v-&| z5Ws{;&{y1tx&l?!fx-T|KVD_&lSo7q$-2y{KQpX6b=j40aOGPuPL07};7Jyi4EO^B z{b=;kfei@)KnIWjEyV!KBOU+)i@;u9Rxctxp;OY)haiNMeJBJ;T@o(JFtX66f&@FJ z)@GyygCMpnzA9g!8^Z&d{*WM&B-!q-95GE;LPAF^GxIxK>_{MWoB}h`%5emb1|fg6 zCl^qaMU56m(#jkSgPW`?S?+?R7Zo%6UXarh~2l_1P7u4j3jrPGn1flWB5G_;G zq+s#DoeCbKKC}?Kr;!0Uh+>rXIoqFyt$BaKDUu+mgAAPbP%fswZA~fKj`H*)Q%<77 zz@WJU$T`XyNx13T!Ywuk4DNd1fq^tf!y6(%2}Lf?88-lprk*;K+*+I zRPYxDK*D8wZ{-Wd8N(>U_sS7P9wa}IdpQXKQcISU1vXIVbzIxIg({efyLT`Et9-$7 zE-nx;q6h~mB0_P<9}GBs2pKr{>Flg_$ctj&uT*-3tKm1qp0|Ry(rUQIQl64v2K=QuYyqR)JlPKPP><*vik!|cISg-?F(g=+W z{FFw@mb8PStWpKJ+Kl>8qONnN#RFsPuo4(bk{I~pc5@%x0e*{>bwZi779IRY5=gz- zpS0kTv_p76IPf5W?|Pu(f+4Y3E~ztH#2ruqEF$3QGn2S;B-frNw&1C0kNM^yDQ=EaVQ ztO-BeIHBXVm;_O;<{N7RN$y%CNR#_@!a-a>3W5O>fB{1<*}Z~6Pkpk>E(AN|&vNnF zd^Zw+{3hmEjcc&*1dZ1em1HRi#Ba(AQ6L9V;XG`=;4&=ej!;y}aLbI$dUw9rQp(@L&UJzQ$1Wh8o_4KGwQYA0SxL_^YUYGg@NPo-R_!r z08P;hnOP`3S-eqiP9?*EtE!Ne_4$IoFfbJW>{JlxHn%1+h5@~zuX3;)0DvB_&)7F# zFsgzl805@fV7Ox--alg>^^LOzj&(~F(VbF_uMb72rtmfgz96~c_2IZX?o@-TIGxM) z+Bo86MG1*vTd1gnqvF2g3~Pl55=b%0(hQ>j!PpN8AdKd?0U&3pv96D#f-(6bUS_>s z_xt@DA~nV*i=C{j?xHUIQ>3Tvak|{C=%&;A^>W4ruS+rS#8>+_Pcg|#8Dzx;`&5xd zlb0_j{Z;^ooNKKcu;M#kPzN97D0Ais3F#ayqN2F~<2pn8++q!ofFFBQp3k2j@4w#O ze#Zp_0HYtdyMsm@2azsZhxVfhgM>s$p|4eSh($MNgCYgm!?BS-hE8^A1B5kTm`cV% zOswLRJBUXJ8$>E3U@X&fl&y_Ocv6P+Krz6b2bvyGJWxE4LdslBFu)^c0A?0`2(J== z>;2C5A)6frpz2+c8e@xyIrp`Mv7(WTYd7VJmryG(><9+i&As6L7}`ti4dLy)QztlZ zYdk)`&?1H40quk{=N*MW9oZ2jq~UEAq$zIPoRst^EjV7@ZTNP!Dq#YIule$EUOpJ8 zg#fxsnvTgbew#I0W*|IYe!p3~-G~tWkl_dh>_@9+s>{>55p{vnf?U zY(ziHl?4DTXQV5NH;6_jmFN&BL-v5We3(wkw*2*{t4rZW(wn@I){FH=3|w2F_aFfW zkig>oHl}aQa>AUcj2~YR7*vGVU=VK-HHZWXU15d{d4lkE`}O|*%Vu=QU#dzJS zzAzA3n25V3!Q&3TVZi;b_J>;lU>Q*b1?jhjfdoEsZ94vxs*>)QQ6IaH;;=mhfCn3l zB#`&ROtmpjn9M*5O8?Y^mk|TapTam%GS(CyMg!F*WAZ*X| zYZ=#eJFUg$D>>lN2jmTH$QKww0^xx&YsHE5q|fHHw^erI1$wf3f|w;8-GX=wneE0gCc=v46OE{*6$cFT>=l2+#|nx zizC=x1ZX7~U;tO7MO7JeWlat`V0d8QOB|j?*HBL33kL1!*L*=`24J9C@j(1tX4$H2 z0|}5WG+ikxJb(eVwff*JStOcsDNLr;2oC^2^d3V61|48H-~}jw%^I0_brkIk)a?F9 z??VM8i3d0rw_kLJ4RV`SNyjUNEA4Ax{>>BbaT8Un&z-mrLpYKkV*4@H}zuPp}P3q%L3Pck(O zZ~4(f_*1=31F;Q)$ORZ32e0vwzAoO~^oZo)QRjV-|Xfa9pJZYS;af3ljnYcKXjo-h+ zfZ-k(Xv1I1*BMax;(?-(jOhBdz@TAZ_sRM&014(b+Tu-AP#9$7B$N>wrr52n;c9V)e>{g`)SxTl0y~`fU9HN4L z-LvoX1>bF!wcTig3Jd^%tb#1iZrJVp;t8$`k1uIKtY}b7$xEZ4A_!n;AIzEHVJ=+2 zU>0`_+~WSNKU{aa_v`uHR^c!9zMfDbJA)1ktO6J@fSfb2iwABQ`xP5HXwB0BB&vBs zV*ns&ZaqM{=l?6xyn2KIubL^i_<^d=->35j^F^udq6aEb;8O$%1~?S}OlR+FAx~GH zE(07DM8_rrpbBTFM#7v?W$H%j7Y~feu(^-5eMdJ31Jiu(ft907|r4CH{I&5uPMhrw+Ahb*GfO>F-%UA&MlfIt$uCmG}n-o%4c zzA=ssHWCR-z=%g%q_P@B#1uq)>WeleA!j5e_hBpZjgN;YvXg_aYo`AKK%Gq2Q6sCY zasQB8-tNy-B44ckKi;!p_{+-@L~FKAjxK2;+AI#8JE*`d1HX8{s5fAn(QP#J@C8Nb zA%{=_y+m7%lLc%Vby3Y2yzTZM0z=s$!K`0_No8qmO5mk9BY(Z>O9fWt2zFdp$z41U zU+-REpt3+SC3Y}S3;ovRCLS=*1JMuTD9ZpkNEp&ZBL>Dek*#CyhxH$(e<0y+474?; z!9Z3@;sKX8^1w3&YU}%*c>oi*U3VJnb3UB8hK>Cjmwl}naVI7Y)=Bvq!S0R#@B`Lc zTNK%pW*E9uma}Ym4XP0a7QJ&UKPM>p4@;2pGnZZF91~zZVL(TXtp-Joeb40e#g&`Y zwcT;%9R04Vg5<;P!*1cbcQDY~7&z7bMcN!eFi`P++d>2$P(%SE`mMDJ?tpSHFhs=K_4pNPOEMIUDCswFf7`O|AKQMqI{>A`zP_<;a;ED~OFd#Mz z59~72u{>BcSXs)g#O%t_0r5+a5RqekxwC1f5=7URVGh{A0D}&jVTviF6;|Lu7P4%d zg=VlzEAa&!N56uG6drRQ8`&p*VS)nKI!I_vp~0YGKrf^elPg-1$?wyNkm|h30ubv! z75ct^y#GM^FR!>~8vw+EvtWchi+g0FI(cGZ6k)Ui0KjC}W~Eq$lC5IhvO(=V&I>l% z_mmQdBXEE&tU-Qz%dD|K?IYgoZ;kvPL86QHgjPk|-0OfEi|W7eKpA%?BH&Q;EfNre zJ6X41{SaM5IV6m79!}UdrMZa^%L~B3Q-bJ01rG*j{P4iQJvxXUxW|U)Y_-wygqd^c zd1e?86r{xw$WmS?{g>>>Y^0NLG?isyM;_U_06*Vj&QyGt5q6cE%ZeVd&?)q8Q z0TO61C^pE`9gna|1VJKl5HQeCG-9BTQy55}Xx>rbGd6f(CVQgOoRom2J$691JmGYD zyS!OWdzri<9~~7KROQEzlGXa@#5me6YMK2j$jceCXSQbl%x0r@er z9x#v|OI#fNGkT3g$_cauM6AyjWS5~*hT(z2z~6e{!3GY#Fpwl+X~LR6s@M<)4!J@F z7~e1u7zo!is57j*Dl|*=*HXDa&jjk|6x$2v{BC2n|IE7G>{l;YH1ki6$nnNzR;rN! zTL9#f3)O}lBzQ>_AUs@3p`wB+NXu=GC2Md2{mx zF>Z!7D~ALc27v$l!w=W~@R3aCWfA(xu}5Kk;+L@wr_Y)rQ9w4DSTX(I81Vk%={<~U z`Yc&EZwux%7$^<|m_Q=4Dx!n@uEF7p3K|BUVuXkFA8c^PKuZ+=i2;NUsBu-+7ucGz z@`Q~F+P&{r*e4+hU!F5j1)E)T*RrDqvp7z8 zWyia~;KQU+CgP)S_iYqILISsJGO&+4n-6S6-dF*rNjYAxpK?ChLBgk25F6BnKch!7 zq_{#y>VgtcLk!ZA;Tw`&$9kE4A9TT1Genjs+7Am zPk{%XG0Hb03#vsVRE)D* zEfdiU!$BRmA~f^4!%=v}lfJcj2{*!;3!_%?KLX2sR-T3jfEfvRbW<<{6&|5t9Q8Hi z+c5wv+fw&7BG6;1j^&_%B%=uqWrtjYKCx`sxX_s-`sE~dbUj}2!!=$w4e}ho0)QV7(gbdCL9|WBX*Cuat$#)Fd#{2-ms>>^KmyG)AI$n(=-R}TBnghS-_Ws z;X%T%VW6xWTYojC|K7p_$bT##$>fpaID!&Iwmr}lK75m|Gc5i?d}7mAUBt-Apr$QMmlm>Ep>>wu$gC@1dm`prjGOG z+c{k8T- z-2rC|lt1l~Fwf5YM!#gaL?>foqU!zax0(>s!Kwl#6C+|sVQ_Y~Ilx2l0Pn!3+(eGs zR1$tFXaSh4k#t{mBjBX2s9O86@bt<2!f21jde&&Wx|# z-ydfRJk>wO1$P7R_^-;$$Xd-{Ps-@w1@0%uS4Up}1AN?=AfgFXI}pY}d-;Mp2AV2p zFer033^Xw0n6{a245;Jn_xAil*|Sg}ezTEne|??O_-CbJh-+RI#fr}Gf!RXY$)mUP6gC%|_qR{Gr(Vt^Bg(-V^Z-`QqWq`NrUzyT-zM4PH?i2`8Dhzbq0|V`y zjS3#`PY(n$WY&=aj5|oF;YqHb(nMq0u<#I}_=JaZHTDcHX8x#9vTqxz*DY;f}v z-iITORd)0)#KQ)pN9vQ4u@4*LBFJn#tlL-1?)~k}UKv!G-`ewcO-jRn+ex4|CZE4B zV6sVgsHm7Qkf%b7U?AI{FP}<{^)kS_-APbiro>voh7Nhy)Pa|xXZAN+06pKXz-Uu?kZoOJQrP1 z9T-T1bDApf`Qn&fX>@ln9=E$sgK@wAl$y)vrZ=o%*S)Xq#HxhAKrb^lHfR`NaVB12 z>9ULC=%~Vmlirh2uW_bffWW{&)+CVaXrvC@1Vn%QSSjb&UDS1)&+^+6zvqEMxTqAm zDNv2>4GcDM)3dcHhGK@G0#{H4HI|VEF@R>t8*yJU#=$^x&TmzPA~~ENH*7y{m4kyI z@r`CCgn&Qsps$($n7=4C3=I6a^mAa)Fr0aoV8AcpS?3#77EHoGYvbGMPV3mE<|Dqr z3?p{{1C=*EMG4#s%<4E}|G9++zF{B%LaQltYhOIz8vc@n4>1ty-@#xrE-=t?%e6R> zHkK#B$pZ7)`Z63oOA>4Z3kpJw(;*S`!Dz;f3r3VZAp~k+0$Uqzz+iwo0}_qr<3ws% z3O(R_-eA!42|6&xfrq~GaSN0d3v+HCrjKohyOslyKsK{1Wpw$pEJaKW6>rMVhHKC` z->t-Yazu9|Po^MhqJg&Q=@bjTBn|AqT{`g8LW9BpihI*_O%ulS^~0uS8!bgQ2Q6OU zIP7I@n+3TGLaTBD?B2Pyc%m5k3j;v1UYj%o9)s%(18f~(@azQwn_!?E1aCSdDMS)j zpXjGdf&ut63>|#4enUd@1z&n#tRu2N=k+@V$`?oxR2fOApjMuGEDaC_NYcAnNWkt- zwH-8J>#4kPTxZ8G;Li(z#5Avy$&1u&3JQ)^j|nJo4#O?Wz6}HH>M2N|g`wZl)$H4h z8$y^Stl$?MOlOE84mVqP%}iTv)*MPHx`|Q81?z{^kaU4uO|nL})7kv;EwefH0k#$1 z)sK_Di56XR(R*e9#d;Qyde83g!$}e={Fa%%U2=T}wLR$8##(9*G(DLjg#CvsS$^sG z(0=q*ZE9B5OCXrqmiz!Dv%OhBZCRo`)gq9qI1wbunnmp0CQ)SL0pzA(w%EE{NxjpX z+xr_TavX`>)|6#!TBeZjK(#vnzMuJqfkcSkc|eZzD>g(0!9a>hf`M543j+lPC#TNi z1jS||rfQ-md;*hBZgy8qj%@G-)Ix5z8IX5Y?JxR%YJ*f+A1DlUH|}knr9E>8rHnQtP~UDm)ocy(Z($U+bueudo~5_I)xP`flhCAFG~nvqJ60 zYuB$%oa}t1_Rl70)~Xn!?k)_L8KP6lB-}E?P1Y1|a{f?lCPJZ6ejj{nRfilr822`Kw>%b$RYe#*+>V5R*2p>p<%$xQ20u21v*x z1rK-!Kx9B+U|s8WpLrlDf;$f+HiUs1m8F!rB#Rz7qHzN8j)8`U$ilLIJsK&-zAw>S zjO-=9nHlHB0Uu_=Rm+NZAN%X?6vQf$Ck*ntjk;PI_83$r=rgFp0}DwUL1MZndd~q* z5jB{6PUC^rE#8oW5)$i$fy0$7JJs((=gI49XGgF8&C}!YQjYH?S(NRb?DQ)$zn3>q z^$~tBQ{&Mfa!Ia-j%~BRv3{#FtWv{2Fc4rg9yl8Bp#rS|poNN-8~7Pqxg$t8R`94d zqP_1E2kjowAa}FhpQX5?6@!6*q)|jL@HFu2Bf0Usr-nmVw5Ac0#j-q5!h8%3GW;K{ zA>j)H$r1en1J67F2IU2~fI-isW$bHAKOP_i6dE3Yfm(wA44Un0@SgLCG?4JqZzk`! zLNnvpTjnUEz9o~g-$i|Srp3(&%h8oVCGT)TBY_&`?U;RWzIOsf4UKe#GYta}Qk86( zTrjgNdgOrYgRKUh_SnkQk@5X0(E&~vNCH#;Hl0q2Uf75ec6Lm);5XBMvVXBYd7qX- z)8+y~{#ug(n4ydw0Hi$u;Ba;Z2>^giEc56XFenYbExu4r5Ez6C+PxG8F8=znOe(Gj z57awH^7oN@iV%BserGs7H7}q=$-;2kw>9wjcjI8aBCw+CfyolwSmrbqf_o3_wmzCwVDnqC72_rziD|839=W^-{xYp#S%>ni?EbL>hHDZmDH~7>KqcNs@zmP-mSf{i>r><$TO4K@!9j0aqywcw=;@c@a~ zEUwNl?Fj=E+xk|P7unT+=*CD5#|e;Q^M z5F`xA0@Wm(x0}wrU~EBpzuEPBc~LW)oB}U^|49OK3K!v|^?f{o>E@PXgVG8l1BQl& z$bc$8Zd6bh_$UnAVbJi9@g4>U|5vMBZ9Nq^zN;=Eh9iM0ED8Y1)>6v!iQujnY{Wq0 zf%b;~fC0crFHu2!YomhvidiH!~m$|JPEKXs=i5u5jC@yGDz0@A_*CQ^S=0&QDkk5J(n&||!0 z){*7niv&DUbvrx&v%x@6fgf_dd3?kFUl<5ixN$r}LMZX7M1cV%iXjP}G0;3hZt8&n zp7AaSA8|opAnH24;LZaDfKdkAHQ^ltlt7CRnKhFFC{Bu?oI z*qrl$0d{W~Xt(L{$u)#1v+H-NF=7s2~HshJO)4QUs|XQ9YPBBf0Ku zM4(9y+(hviu#{f;f&xHE0{q;3LCAj?a{_k^Jd`2r*O-$*n<^-4${8~BmIk*; zh5^Z?7DvP{q-X>iRDy_K2nHeoM=>x`K{)~zmz%mr1kr@_p{$Xihiv7Y7DP@Bb5{=4 zENDLks8esi71p>83Al1^Yvz8Ug2x%}Y`|y?Ictf6R&!1j6b1x|O%R?E4SlUU1^@{n zt&q^>j1tNvW7BwGl!cWfwBU3Ug!eSjSFWG}ghU4!!sY7|Bt{Sh0BUto9&&j5{H?}d zzPZHiG@-$sb}+vt4I3CF%M@lv{jG^ek!kj(US)uTgz1!o3GoY&h((q2TCLz!ZbDZC z5|w#gl*JjoXV%&ytKL5|zBmOtJgkRzl^%zkJ!a(tDd)EgdF5ya6^5!0j`>lo;34`j zk3|SoA7~t9DkLF8d_e_<6$=1BaYBvvxQ2v;1V9`?;)0(r06b!F61DCThUErh=z;;k zdi1w=tE9)>VEMaT`Is(_t-mZj0;4))gn{oQdJwmzGf6&}>mh|KE30`g&yLeF2pz~O;7!Cdek z82H;4_?{gNjp8UASjLy`tnU2u8(b-e!EU4CxQzs$Qyo(CRzPYH&UrwR`b000T_Q1ZZW+AIuz zr~Mic%>@(y+<)plbV578|MWoP1Z=P$pond|;t=KTx_$K`k34zh?(Hr`bs6J+BV(oC zbkO<3z;B_VvL6{FM$upfi^4`$0_G%<03IR>lCq|XT3X=van}Qph$RUE2@NWc1`d%l z<6CX>;`+xPwvxshY@lGP>|tW?tl&Z}3&Eo}oI5NNCdm#glcv zbtV{)Pwod~^#fn|fhPsDi%rfee1mM-oa;x!% zhrpnGfdje3iX(Co2E>mV>WHmJ7Z3nEFwl<8Qo#TTQM2=$W*@5os`80NS7nfcZJiXN zGgc(DT-h}4?_u009%$qJ>9GO3C}Ph3{N&6OQlESg4A^NrKOO?Zk%cWlXc(xt;BO3w z3+@=;5&p!$zW~q(A@YC)k^gA@P(hxGfHnf&>-+EH_4jc69F9LcN*1AgQZODNo~8Fr z+2csW(b43k1_m<2oO`cMM%T5xL8SsRU09~a3}Dbuq3c2jI>Ac`A7XuvNL80c59nB< zZ{mEsEq@Viv9;O+Z*0tC5r#O^0FP4;Gafv~^bd2hzVm63i(0a~sbj|*B?S$CMh^)% zILIKS!2mHJUap^G*tn$NcC~5pTjpw$p9(+f1Op*qV=Sw=$e6plm>bEx{MF2-mphP$`0zE565uLj{J0yw=13 zRBX!^IMXmtvM>P10hb~5?bhCZ_zhF*S>CqCA66lyx**H(7(LN}H&+pw9#9MuY$Obs z$1iw~1wQBVs9zpLhTw(#{BL-}S)Aqg81J!jYNLw$~a>WIbgk5@%QqZaSY}GG0 zvs@T20ZeDUWnr2U26}9~-Chm{PT`H+0U%ps7cJ<+GCBe2Ad0bpq|G%LVwH6qEzam6 zfe`~?23aOzK;=v`F{1;3&G$M>r#Cx1VB!yRrb{Eq3bZMe2@(q7|HgoU@2)|m;oJ>+ zvyMtl5e(#KeFjAZQ6E*;sqAiAdTI<*%*n6 z2vp3n-~<_D`GljzWt$zU$%L|klZ1!w<`)QnQV3xNJ|feOjR(RHK|-aNgbWVaQ*)8; zvA!zP{3A8Lc&QRGg#iHAM_f;K0^VX{g@O%u`Kp8l#Rg^NcrkuI zu0Q0!)^%%*C<-&*Kw_GV=~2OAJuKH-U!G~uWIIP5_y-1BjtIB6xZp_-6bAa}z-sq_ z|A2w}Dqql~V8H-FAVFcR?rIp2Rg+Z7x{uROB^=pw#LqFvB35dM-Sd%}tVacDtG$WE z&SaCvoH@7*HQU}s8`!)K57Yoj)j@<}>8Q9-GYbnvr$ZcWF=sSG+(*)h)o-ix?L>@` zrEN-Ey2Tm>yyv(*E`??@Kb7G+#d_~*)KwRlS!i0Z>49F0&3?w4ZOzuDOg#W@oO&=Et++pw(7mV(pcmNwP zrAOA>shPAJ=k4?N*7htXGT?`~LWL`GWvS_%VBZ~;!tWa(Z3&MEDaZMZ$V8VZQPx)G z`}hbR;h4Zvpkbfti4ndILzbayTzeWrXVhEMvX)}X@X;GEpsx@@>#jf|!jhBC!j?eA zMkw2Tic#fo2Oe44s#jIwht>AVOYC@dyzNeJLzNk1)Hg$C$CyzrHdJsNUV?}Cj>MRp zh`>Qq_{J8E!KgKs^8GRuveTXYhy7HK}V!*rRhqbR;-&!8Aw7!LMXek%IV_f#5LH~>QGJbkA55>yJTdvillnK^E=(VzDxpxkbg7oLmvE1 z4$m0yW>iqMthGM91%`JF)NIi+25LS2e~E!-(>FXs(SZ%yl{+XT#77_jk?D;TBmfSd zy)vq-0er&%U_hPH{4zzt!@z*W{f4-FrgFGi!^n^5x1tEIp6ZukaK%{$DV|8Iks2fg zy2k9rol3T_HK#yoha8NTsV)mV?qh^*pdvyYc>_mmjF5ub+81&Y6YQMt@dqpk+P_&U zrOadKEu8sD$yBLHvInC8Xp(?Ch&*8EXag-2k&?wUt^snwAz_1e6{8fOA!gvS>3(7smsYNho$)dXc5ee9!JjLT4+j&ph88oN}yN52; z*U7rHMF+(L|8op<2@N8iH}@J6B+$p`UpjE)1bp6rk@uSNO18HfrnPvhMm9VIO)U{AA0F+{*bbNKpIeMO)jvz zcp<}_m9c0uw?1)?!R0m&h`#}ev> z$!hz)%+6`rl_K@Sj)sr@oMjRi{SIt!ZRY+11CUTSuXq7f`f}qdJsDqfy2plpVW9ND zod;k*7}foOfsq8hMFfS45(xm%ECnY~0@E(Z;p?vs30QP<{JFH33zM~kuz~^Qjy4am z@ISlYlCLKjsuU7P4Vh8Ox9NNsI7KKXW<2o-90ZSG`XfuN*LWi+f*gd9ZFQADMJ^{; zSZ0E$Iw!s$eImq$fxa_?(2Xz%8?3d(j8g~<3^wpU5ghjG%Zoh^JC!FU<-5T$I)q?Q zSDr9DZ@d@bCw^?hKPL+e&KD0v8#s_*R+@4+y_rcw2yi}|lQc^hSS}6JEn&b+RRx-5 zl2il|SSFDR=dzJ+=l9<$+ZB#!WWK;nHF?kg(7@niYYhYAu`v>kMFo{Erop~=pv@XT zX~H`O^d1)NlB9hqD>b@{_P1e!;)Hgl9zy~x+3Tfdm+R;6jrARpLWiGVAYnZB<34G! z!RI+@Qm-WqnCatChvgXAR5q1G@DLJ+Bq+Iv_LDaVDk2Ojf9O4760#Fx*duFW$pBe( z-{(YctoV9vSAD6ZP|`srpsjC51y-tJgPcJEn_7|p0GstD{@Q;!&qTA$)?Q!aoB8Ew zavgqCL2ZfYp$~em>Q90PCQgeBpcWbf1RH!u0MHKVJGE;3m+9$~xRtats9lmj z0`r`s)VkZOC_dGUT*D&Tz;>W#lke0WHi$O3W1v-`6xyHJAYYr7DG6do)M@w|Uq}@R zHw?%THBCqsW1qE;t*B}*;=>sGX0JK(ALn?$8vf3*f zkN7NiAhD1oXOhUn+r4$+!82(IO0JtCI%$te=n4#F^ z+zbIz>TU$m#@IX|OZo}`Y`@7tSR-@HYSydOva$q|VmWDomOJIb7`=GFWdnd4$^8O3 z_aRa6|5bK2R*fsc622MS&0seJ$Y99;GJp&q1IPepfHN=|m<%8T$N)0f_kC3}vJC8f z?{Vhn2w9eGb#--h&yT2Ndf(FI0pkvmG32BJW`#Tv`2Llo0Bu8u$*Ehf-KV&C6}&!XFr z<&{{TodI|#isX#^EQ-U!<%59+2rk8s^|y!tKH!+Q7h|0y8_ZU?+R-u|7RS000trBdW>+JS3EH0$H>(LkR9FA;JKJ zNN6xVo)h@C!NUe_;cK@E21CFW&H>V4jK{zLJHn_?!S)R`qR^Aa2 zxDgooH>JfB;=$!P(owHxEIJS&hq}b>fCN_}OtV9Y#(&wO;{N?fjCkDB-|?!5WtP32 zL}@nhobIpP1A~Et!2>Zp0GRF7H$FZi`50sZj}b#ff?^CFzMQ?Zk^^9d%+U#V ztg^LFrtmM{jW5NQlXuKi@25)7CbRTGXcjObgp*ewnNe~Q4jL0L((C^HzKqs7D z`HZCGVoY?!#HfWUYO_{mt}oA!V%LFz{VcSz-&PB`liWS%^tTIMnSjT?oNq||_LAim z?_c@aRJNI`$ULyryS7= zW0WSCb)9gG6)p(qHo9r3nX^>dh9t$RMIMMlyy6e{rwtf@fuH^>20#c5$PrQ}ZVthP z8)z(;;|W_M`h)>vK|72l2Bsc}(WmKaeSvX6!VM5&i4i)gb}wQeS>YQ1fNjzxAr%mJ zob1LlXN!L7e{LyOhO7Vs7sS4JI*mBoWC8R#$gM*TA_buZQw(*&0|^4FAvGwRQ5a`5 zHE)NJs0GnGKnMK~*z)Z3r%`|*gOu+WEObpec78<}{RT}=wc$jHKs45yPE9Z`ev@S2 zRzFTr7>YozCBA^`!3LS>e1UZ3hwv}=iady9lOY*QnK39}?~_nLG9Zx9hGtM0B(xC` zxC6XV7)%T#93&7lFR(^5cmNEf9e7}3Kyzc|#pnTmc1O)F`(S{&==P<85KZ{T_%Ui< zV1V)$V=|eL&Q6AiMC2#^Phk+#!v?nmg*Y1V3+`$Ndq5>Ro`evPh=w*GcTQ-yXK?@t zf%U1E) zJk!P<-*`*i-~#I4w6lxbn_KVXuXD!|TyGf~#E{gi2DU*A81&8l!UG8k`ByeL2tuR4 z#K3l70GSbf;9tVMumK677qdu|GhbQHasefLlYn)Ji{Z||;Q9HD+vos^pZGch5{C8H z7+@b5z!JPl2O{4bRUi)>It{HAAM=3Z`5zb%0EZS-P{2<_C?|jc3R4RPR03$uw203g zv;V+=vA_qaUgOb;?`DED$dG`G$i&K!Jake002KfULjX@Sg9?yI42*G281hF{#3PU( zOk-cZ9?K6vp04P^Lq(;;^Rtu7YbJZ9f0m)4bm)+hV^GGBWI0L(7(cQUA>x@T@!16m zXGKtc9p%TFBpzT8 zO$!gGaBLAa8K$ypEKm)$CK(Jks6!sOvx_jX;G5iVA%SHlfdBx|rZBjn<_ZsNo)v^D zfxDOU+h?eNyr8K8pUXOU02pi14~X3{G+sRV1%Lta)v+b9wYkjBzD4o{RiaV>>BtF~ zPgLXkgbdOsW(Qv}((n0}5x;~6jGG>r3)Vom*jyV5;SGrN4(Ui1#%y<-`+oCI+J)-2 zX64XvO4f9)VQBhpxSC&##F=Z}@ca(f7~}|@un?4zfU$@~bB2=gi@*jM0T|GoLkJd* z)CnUNurnor7?3C?5|9?Gth*HhJk@=_+p>t(69*snALu}_&F~MF*>oL)3-!s*Gq6e| zdZilgSaAl+Vd%x&Fn?(Q+@47Vri~n-G)lcF7%&~MyU->E{F%lAW{E~bWf%#cH8f!z ze?)-;2}lTr?{pUUYQR9DgFt!zgcx|cWC0?Vg3;(M>3}0+N{U5x3*KW&$^wqGcQzuS zf5Ue$aiC1Z+R+&|;-U(cm5>L@Kfu7h)B*Tht^gh|lhHo`g8hz@0T`?t&cDzCD-7JY zqVkT>g9!?bMqnHxUy{3#M!(OKZ*&qOrspDn!Lfo4AdzBiH6zKSk0tp9)eO%xh42152fm^kxboS6m|mO^ z7s3G90a1Jqrj!%dM^}IWSXx)TxQ7HXt5kTsBhOX{8!WSU4Q8nU?BnZL4uyw7kN=&jaVL)i0ogXye zq6a1hu*-r0slc@KzyqJHKlvfR7#M)np$j^UzyLi3V4yvr$PXC4VI4Pz#{H}eS8i^o z6yfPqIBa;hgis5@{9IFSl?w1O12?P^>+6{8G>&5|V8F!_$_b+ur3v>gHE{Rrq*0qN zh=Al$dRE;($8m6CmcBns@2j>D0%%c8LL>GU$N>J^0i|(sFv<7dHZ*7>rlpu80F0N1 zM>2ZlqK#lNYKapDC4^9cqP9q!Riw=e@43J8Q-s4}_s9VqyD zW=t3iu*SpKFBpz7pfDgnR}&TkSRWopIH(>NvEUmFg#6>t!GJNEN)fW~V)OLDYO&{* z2UQ&k!b&@p=VoHSOfw|{H69IAAQCW5Jo*9M2z!JafB~_Fm$Z@M&FT<=!;pc!=38(^ z6vE!bfq;Ier_=KS3^2M@)~Pudo9e}CKaTSj4ssoA-Al2h&HxYK^7VReK8uz-y!2n+ z8%P8U^c!*o9CK^7f>^!Tk|tn!1{-*tSp4BZVrN<7ipB^7iwVI)bfZX65=<(P5Wv6& zVX%AQOjH3#;Da(L1}?qf`x9cQFOiFd3eHw+@CgI_t1zG)VIbo0TMSTVBO65)Vwdlg zKt!M<&oHwWtKfV-r#EZ#*c6P!}k0$THd`bfBm^aq$yo>Y8|KiFi zB%;D`BMt)5qXmEiMOeBd*bqe-Oqi}BUJ?moYSISlJU&tLdFd!4XrCyMOpq!u&Q5@^ z!Ym935Q`G9b`&tQTrfDn&INj`2s+#!cK9+XqD$&jkAQ@DL3R)ZSa{&{XHvq(g#`eF zg98RqB_Lj(B`?503l9uUc$^m;cmVz1KoEI=hYEw3vYfz-!p;8uYWqPfpg6!%r6>Vo zfl*+C^C}SWiWuN!ULF$No4FZ2boT13K1j@^gM1K1|bj{8Z~^E z1q5S3AYlQ49hO=4X)Ie2vfID$aUnW6N~J-hp!*=ollm3U7@A@LHdu_l>?9VH2RhR* zy#}ohWa5uhOkY*Rz|;eS3L**ClMNS0BqGGD_8H;bn2$C6wqW4#{WmohiUU6KL-z+Z zG{j6g&9VD!T^RAN>9Y_VN67d2w-sZI-l~EX1J2Re_p$*GMo$ta|6gq_t0pes^_YHf zZ5TlDpOh0GV9Eg2$J4=yDWu6h{2&$dEs{ogKGC21ETWiL>UCrTOrU`><&bST0lSNk zPC3a?B58pg`GFY3cP1^p!}RC@@WYw-G62KwczRSHYn8m^$`CsP+HrqV3Hq05vVmZz zHc%K4TmTHr05%8&k90H`GG6~-4NNp4GZBva4pw;h{cDARxdw$bBJy{W_vQudFk0n? z9pqqF=BG9zLW$j!KP7$g0`BDI`Oo>S15_dd#6Y5nB%s#^Fm59TFntnUV+4S)=97G% ze-#7P18L-XaKZ*lUD7#7;86KL5+m?mBEI%jGWbjS^wc{nva6+#rE{qJUMw0>EKKV1Pn|MM8%f-fmeu z|Bkte#&KBv&EQVFFoKvGKnpxu!3qO?h^B-XRAp$3=@$%`Tr?O79!p6e0Sxf={nMY{ z=QrkvmW5S-E7KpSfaB_cu0m5bNS$zvfhh)3A6R(cZzK>NPzKCKWJgAtA_W5#1DJJX z`T+orcraxmWq-5*Tira&05H7l*&SAp=Tk5wG_Zrc00XCKyIW)@zQ#Q#-!A}+>~Oo= z$h?|3EIN)D?s5NWgPapz#(YnFdBV35pGS&hjk16TTN{zd$P@rg@zin#ZXprVfCK;_ zNU|eiP%eh~=_$V30tvd)_$^@X`GtimUl5$Y6+B>W42tS7Iz%U^AyZEPY()jYP$Z0M zgA7m%unapGcz*pu(D^45lxEFvG5xZ$@PK1V54B=*!@&ba{}u_$0}BSUbz7o&)L@H3 zF>Wvr5-0|6d8QXJgzSW8CQcbpC4g(YTE!fCWHE5eO*1s0^RX;2C=xglkg(`tq`ndV zF{K7nqK*%`cuNfm0OHHfY`L+p0Xt9xTTX!0F{L#|O+X0H!M*>+h>$~`e*|)Xfyb49 z-0;`#vn9$*)00!|f`pnoNC-<509Jv*;p|Xb1`qf5TVOye;G3`n9knvP6&Bn*y;1eQ z@ib@w&fjwmao?2CvXU^+^a%$XF;WNvU-BUE;3AJN6czW+AB-?z)Kk*KZ}oskfFc$i z7#Khhnt~lLu+$074XqKSOe6rx;ckZu=LoKqB-&VyYpwm)6Cl7os0 z^Z+Nfjf+_B5C-J|g+Y1@MM4@!dS-lCMVI~^vqeii85Dtpz`1zI!rgFc?TF(G14urT zf;kdr7aqy@JcpMI0lte80agYNVneU5S>bB(`o}knj>gmF>x}VzjS|z;DDKY)&JNc1 z2;&4E9*Ny#aAdV6J4`*JUV27NiJJd2-GAWCIBUcApvAd@`mlXK_&Aw@gph|xv2sPp9QRN0nS7IbXe^*>m8|)O`cJqW zqsQF(K4gwf@jm1wJ6Kks=+jF#oWr_9)blYtFyQ0@fGzt&0Nh8w+r8@;53KLRJ(n)g z^szghm~kM(UL6zigxv)L%8lTzu;0_a1Kwaohttq9eZZ85g^_UJ=QmbqKo2l>6c{i$ z1w!C0k&y@Y4-AX~3PMVV#lYh;;eg>N+x;7BE-`p)#)9uv!Q=tUcWIw6KwStW&~}7@ z2)P3lOkD>jsO!Q5^;`=+jE2J3SaX2-188^I!wx=d5OJ##pf(t`*UFkZ7;xWamw^ur z$xEp%+%lYo(lKcrRG<{B^)DZ8DFqW3c+}=p`1*CcJ4WYKShCnU|C_Xr&jF6Cl8D-1NJz=aUR@;EaYGM z4yf>FN>T;DHyCIvz=@c`;HaLjJmC1H^Dp6`xgmzjPWp!A=fv~`f~g533BUk+LSge^ z|A!$2S#{)=5k8IscjOq`8wn?aNMmAUKvp8U$0-;SQZP_42nMVK+EQB}LXklb1sK^& zoreIyKC-_NpHxwCc#ns^4mKc@n%2kAn0ujmkN^fIy}$A*uz@9bFBni3&PpAA$K6Kn zF?ta7&J~~n(toI+7FV0q`q}E9>;wZmDT603zrFoofVb7}OU6}}2b5%^Nb5+;`=3sL z`hh85-u_^B*1cg48bBh@Z-GIyVm<{7P^0iGffh6*fq;iJ@kZw$oHMrnXZi(z!8aIa zEC2(9fB}FchD-X!9nQGcvy5D#N&ppHPGK;WK;>MK5O+4dEAM3h;yBEJ&Sw?k%?s(_ zv&)A2_~6SEXIpccNT5V4czAmPft+AjSTO)9#6V;NL_x#{7?u!|=5w5Y0u1nUtqj|z z{=;eD0VMRek=+FR1uG{U=;m5k$Jgr#>usKpo|jr2vr?Af#wIV|K6~@w3KV{0f&7na zKfP-LI{~?lT!GKhFd2%@e_`e=86W!pjflW6{dIbe#c7Sdi3o6lN34U9o1>$6P72dg zPk%o?y}Z2tA$g?6h5mecerGKgz7_i4ERxae6sgQg>|V?lW>o6i)APs0<&6t9AI6n^ z1B1qb1q1Am6nw(K*P%psv0h&dAO_~Y8Zj+4#dg5J=+D8^tE2{Rrx$xM@cW7uyGLH8 zwj6)2*Ao{ce+gj)13{G@0ZE|q)H41M81N~Iy;OS$3dDkNf~j9&5N}2Hs{t@{CIMlu zD7|1HVDMF}&j~H@QE7>HgCA@y6)5#PKq!7!e?%gx*%FZr+4v(dx*{!9Ky{ZRPy5%` z*LQd|qvohl=z0vK2@E6wDqt4DQb)y!phrgj(EIbxKmXp|ZQeh4e(qbBl6c;~U}9$Q zQG->Z!UM8_amUXEa=T}S6@dZXK6#)K;q!K4ps}EsJi-9qVPatL0I5MR&_M8I8(`FJ zO9df(#))0vi7Z5Ra`EV+GtDdp2C5}O8u52!fTF^;Cq2aFiv<34-3jZ)4lgNJ7(Oyh zo-4$53F47|R)cK>dJo3It-}l$Kmw`!M5A2^_-{1dSGNt{;89xnYCoGo#O%2kUCI*HNK7>NA z8M%=;Xs7@F^UvwYZ_G+#VKf$$;QC|`Ec8b_;wxDfdh{zXOdUM%aWAj(fCb}k3dIK` z3{6NlP!D{Afe{P7j3gOJVx}87@pnV|(jgPjq9f$_p-A(6gjGR+&r9s|Y%15|IX3i;sZ>~G+9l*f!w1~Z^vcLe-<9&_A_~2~S>XGZ) zXW0Ao^@EIn0iR3_z`l@e9ex2iRf7%xV2}xsXJdy{HD~4JGfK&6Nf}`vp z<2@1rt{i8Q=D(>M$ovZiEEMR}E^)@pET$gcz7Pv|ycf5E(_(!AgIR?^c53AwiJQ0c z2sUu^ATVeK!An8HPC^*(H%CBvu!LXl=3gCu2=bV_R4@hxTezb^0?*IyGzR&TtO3*o14LeKxDI%X0Z{Et z<|4$46fMNg@N7L)E;LHogPHZ|vf_B%wq4W|v!@z!8C1ASQ51wel_ziybAP)91IY`(VUQ3WV2nq5_9b~oBZmi^13Lh)X8uJRu*0vz zuLrS91)+B_!2Ug`CLHk0f?re%$pnJ|?G@6<79QwZ*c#>aml(RnMHNH_C={vc#QNFK zEp5(-`!Keg?*Jiy2g*JG0E)M$14lft#(;Vt(;i1Gm^|=_ z1p2RdIAB17O3@PoSckC$w-4{9R11Rvj!f7H7%a|KclKS?02Z182DO3FVXRHzkfFds z$4?=V;i=XQC=v<=I~u4)UQu?g(b>ZMxH(`jOauuKLJ*SiKSq2DK}3XR0eC%m7LP-v zVez%OL-GK|G!SOM`ZR7n|C$vhK-h%`4E8TLEOi@{fV1|P_9#mEwj}{aSsM!k09G(G zL>49%uqXjfK{Xu1=OjR zP$8DurXGkUOuCxfaEA%7Mf3pi=saKkKmuO_!2uHW>%spR)TVE0$_-00Qo~{1G|z2w zlIei~z`$rRG+^*w_8a;|0xhZH;Qt!B@xtTST^QIDihLXc(iD(f2LX^2;3W)TDS-N( zFfcE0+y%-I$EOPbgNE(#XyO87uJw%zkZt;Ist2&I=GNB0Mv;IfU?#bGVgKRNhdX9RWm-yF)gVWkmpeiUT3=LwS zFvt!nf|C`EUdKtSTc|z^fT59pa)K@|KTyO29^gR@Kq~{(`XGT(9OmGT|7_?lFq{G= z=aZU^9t5kkmV+qW$N+E9#mnm-W`yx*W2~vH$}C!Yy5Rwh9tJKFiUD)O9V2auffQ+> zVq{^b3hKgmH@AA>6Lp1|vd9MjN_vXw)fg=D@Qan!zyQ`41I|Vq1;arF!9c6TZmCm= zf#`u4=xUHa`;Myy8~2+Ae%?;kE)T!}BfeukF#uwnGOTr!aKa$9!4O3Q$3TKVu&Bt+ zV*O=DF>utP5+#9x0jMNQxG)7r_;ldJ5R?ayV8h>0{%E}L0NCIlrDGLfa)Gb`em(ph z<0=e-gu(eCe^bIRKXwNpFoX4c3q%~ZN<+3zP-aORGX2aMM+``43kD_(s1YrJfNl|D z!M&=6H$wh)@=gq>5-)Qzy@>XrqoGv=bSC(T+T;jxx*2kV3-C}~r%THr!N3?+^aTU6 zzu@l}0LBdm-?~2sWq@v{Ut`d?Z~{Rnnh@iWxUJzPrde6P7HH0NKFOvABXyxZvnJwzFVj zz_&YSGkSo;zha={KST`(BquLc6fc*AhlUg!KI#v0`ULa`yaZ1E$XNPkpaVfWW0d^13_Ezf{_#q zJs=g|1p|Wz;>8$_t6lR_ei!5IQ4|Y%pojU@xIY*$@nqDN8;0|SKb!QN-+G42MPs`*h2MrAzJ0{iZ0J};iQkjv&%6y!b52QLoopAEN7YwYu7%R_q?^-cQ+4SNxej^9*-@w2ep`5_B zz^J(mpd$Y+i_e4v6Z za{DW3W>Q5lK+pA}2lx(L|FjI~mI#8F3`=1B$ER0@^8P-% zrdyD^AzNzw=`7wK@0F5xr3aK@=_yG3!loevMg9XnGqJ$>a8k=l2^Rdw02UTNjuxMG zPY4*Cup)tRDp^2lnbf{ex8H}o|bXN0|SW#eh2%EM-{@t+uwEE zK*eA5z?6cTFA*WCpyYtYLoL+4az0o}I51yO2eO?QC;-@YCqAV_oHgWzgXn|^LdGw} z`V1+F^&MMiAjm*sdk;HKjH(eBaG*GY|F;9KnmGNvDAVX5y~t- zhel|6%zbooa%a>7#Xv&#&;wD1k%+2-$IP1u28_jEKq+VxkPnePV!*dFB^-gEG5{Bz z5kZPj7=RP$B5wgX+({5sRbXDg`m0@+EPs`E3~KlZN} zkO%6&0|rKR%xB1!-|~26Z&6}FLO=je47g?;;0Xf+LY|p_+l?p{C=`1s_rntRU6+Q@ zj1>cpBqTd%4?;*l7&!Qc!66n0C>3^Km}Me|aYiaQcFVlL`he8{ic73Mxo_&0MyHQ`7NI+jU#AwON!iofH5uv|#5ELWW8=Ns8;qc7VP z3sNY@e>L1D1;8mC|= zA%FoII}{Bp6tl8imI`4sFO9?yuZQX}J>+lOTO6KXV2~%>0e|SzM+agr01)9<0IaqP zVRC1p2cTS2!o-5?sN9BkD+b^J?gp9=Do{@32l8|Bt}wuafk>D#U@-q;_tj20fs>y= z3*P-hHGn=`cz~HZtrjx0H6dnV;7AV)g=4Ub-6es!-zd;+Fu;%ftOr5`2R0A`tT+S= z5QhjDMt?2+3t}KZ8YWISD2#S_}-%Um5)q9w-_-svEfi z1K1dmWkg`8Vf6qNDlh;Q*nJ!fh(o@uNzI}O)dr)`5lvV%C=C2*V^m=eev1J!M2#3G zU&H_mAm;V%`^*Gnd7=`2s31R|J5WA}n`3m|qWc#BDHE9#a8R#L;iyAR_*WQY6^rnI zOG%6=26i1jCJJOIQ6d5*0!hF!vgHCAE)O}-okVBc?d?NW6WuW!h~7X<|HLeS$CtBn zdiRh_@z(KGhr|UE0kii=aC$yiYUXO35f;G4T}M*j%y4o>yS(g=>8SGV>`r;Kl6J% zFsK_d@r&AGM@gU&0n^u5V9yXR?e0yR|7!GDU%R`1SAS1p=n;2P9t;=)2@A!x4j?HT zKm~LaWkdl{Ks|uD2Oh!<{+l)kAtMH<5)c~Fqx48nV1x#BU`p{M0szt=I03*8ze1M} zl}#ip%(gNp7zhJ9u6SxZ%6;Ru=r!J-@J6LzX}{Lbw%NhT;sXPb2c-og1>K0^&GZu_ zhY&}O!~M7Qol6Jq`3hH_T{Kkv!G?gs$OU)LYY&qNb) zJ{By6*6!j&$FXru{w)UBveaskkgabN4~2m{B#g#_nx4*rDgmq?CBU#@dy@e`{$(oh z5f~;UL;}g96VRd?JJ5)^8!qYQpzkY9e;#w&#S_yrZb5(dpsyAQb1N|TQH=!)4_GH0 zJb=BjRF@(-))xT90OpIE3xfk2m>>*b2FZc+;!G`U?0Mqu*x6KQjVB+wh zRlng%6WZ5oM^$sf#sYr$5QGrIXhym+UeUg|z>;PLz;z>;@_!>j2pnVzZ@`064?|?XKz#(PiF|2);<=D87Pvyo0Rv49w3@9Z#(%Bt z*kb)r@TqRhnF$J0KrU8Zb_@g~aDa_QknDJUuZFo#=|Q;Mv2f_=%{#eaFks4%+;GpT z@~gan+~hosPQ${Wm4U!u0RTInF|gbatv~Jl1p^U;T0e~d#5#3O8oGOif@GBx3cA&` zn;q2L(teN-oP4%^XaN#f0s;OWDj+vR@MClx-}mRx<}hM{c#WQ|rld84h`+DwyBK}h>D!Be!+x${ zcTxb5lef-uynf`7(>zzA7--t~83Wd-5(|XE(s4X7Fzg;4knwB__2pL&(|eb~05V&6 zAc8PFfFKOfu>}So->C;ozvX$*ErwYBMkkm%V153@{r~-mBi!(bHGO{0_?de5AiBO< zcuZC_G#q0frqTBY!>i(I@tSF|Y#G2%Ua=P+H^i4cR@+=*0BK-A<`+f2ceXAKdUgN8 zV-p#QoElLQ!*6*YeaD{}U~&K9`@mpeUNWjpC{j41~2q72{4?6o25gbCC zkpmP1Us)>#@=qPxh!(jH1wACG8K$2ADDMrB#QlXqyd!$am>A?Q7?|!KW{ACl3Je#! zuSj4TG}inE0}E`v?r^DM0KpFlP#L}p2|Vrx29&0Y9$3eMZ!jS3>+&o9pBUiB@{;(+ z(+2?R_-k_?_SHPqgwa3Ry+M$BTNo5A^aOzckbp;H?nwxA6dL#2AOT*b-piKbHrzi) zYI-aV33R16_KEKk0}=vMKej9o7cdY4SVoDW0Y9qbpD*L@>em*l?jN=M>IDGoa5okV z5ELQ?iUC-Cc&HJf2KvkcqmI-xFo9#`^?8>__?8fQ!DX8(`-xzHD8Qq8A%VNckL}Y( zcp&Ksxe4mj`oKyL7z+{wW>y$0A7h|wQ0ve5$eo$@2c>Tv`l zh=+_Z?kWWK3lKF}i;M-S=nRUvYxja-NI@4d4kTC#%tG-404V#u&ni_K5_d-e^ZUArXO_L-Wi=KrB-03xL{a<-d~<)P5`L zv)_NeO9wB_ho>k zWjJX5mFpsqB!Pto;v-^UO1>{4ASMnf)B}G1AVD@*b^?#S3MA}Lab+_!zjKa=1q`O8 zuLnaL6kNeo5~vc0<706rkdg^vXd08mZ7deYs!(}4Z6RSHsDlhyM)GC{^OHWuppmQ- z$^9*C!vnk&n;yuGe*=Rf42*i$AW7aba>L00i}qW)dCmQ4%LyK_xRe6XK+yu8&lso% z$lCA5S*76qW{dUz007pH-F%0ER;!8uN&!`ajv!iOKt_QsNbq;fM0iR;U@$ln`yOFn zxP0zv?pw29jINcjdjYJi2Q4%xX#I9-pYKj>z6u*)cQ6nb7zH$ap4`V4yJKQ@$^ZoS zVxVgWUEQD(x0ZrU`fz-;A7CJ+@Y5RlDM)H-n@p8&D2$_6^yQP!0N~Yufl$X16jnU2 z=mCDI1}d4$1L+HxE+0c%MxI7@f2I%FKZ3y;1Ksydu40XS>i~~uOmE&o0%Cx5q_@Gq z09AUi1wdi}HyOVsL0d9{6$Z=&1|bv}Q3ySf2-x3Fc_;T|;sKMzMZzc~YV^@0ImFnItZaIZA? zffj~J?D0sTH3n+&PlP#Ou)1|$VDJ?K{JJ9K%hqp;vC{Q`A<}=8qOqmIjeWrpgb;!| zLmV;~kGIgp!*6LI8&ZGT^wU>5Kz9XzVSV1R95j6V2L=*T{2@v478o4#K&(IV!3_1E zP8tjZ20em|U%fO4q!^f&6$9)S6&I|6NcrX?!mxgG~q8+I)QC28%XHUizj9WV2kY- zJ^Q3Em~Zu#75UUseRZ`xm>auKz#I;Gq||rJ0~G^-$B`z~Uif=5!J2+$+3D;Cf-JwKvk)&N4h56g3<92QCZ})Rf`uf)x2#^XV zFFRXR$9bcGxxl+paQ{IRxZZxyoqE6kSIhXuH3mZXqo1hc9}FZ5_?`!v4i6sqgn{0o z)s3p}VESd}7zW2i=l*}S&T?d0N1JNdvxm0D${I8lpF5v{vBJst8lE{Jv3j*{9AD;p z4E%)$#6V>v7>FPY28P}B#I%Fmld|>Sc>REfjIH(CJXquis;USHfgU1h0YS?$)Rzy5 z0{f2#a{(|w6mW?!x_P| zK?3SPQ$m!$2X!HyGmeSHKwvXIsNrC0LQYu545YtUPfskq2%ifukYib`OQ~BMH{o zL9l@!v_ECZ3v#RD6zdx`_7``{ogbdK9F&=l@A(l49PAQ=2oKtD+qIJ(K&9yyThIM| z%KV^lf))=F{FI!TtzZ~O!d>HFEuJ$yGQy3HFg0PMU`vHz$WYc)0wLi~=Kk*AgVBBU zsl2_$M%g2#WU8q!00WeT$p>k5f9u0fe{Og0zpoy6BqBYbm~6y?Wef=gA^?yvB&JRW z3@l}V8TS`SV3jzbA^jsA0@psHV!jv{caOU?@8`kX%e~D@^UP`79*igI?_b+^dto3F zmNu-mIQ?)~C+|1$-#VBii6j4>n`UY^ei z3_kNfF#wwl421t18kVhGC*zG+z)g^HNeNpJ9=Ei&acuRtZ`<13-m%&KhJi099AEY; z48Hx`*n0Wsxx=N7zvuDQ5^mc|lK=n! literal 0 HcmV?d00001 diff --git a/apps/tests/bitblt/makefile b/apps/tests/bitblt/makefile new file mode 100644 index 0000000..8ce9863 --- /dev/null +++ b/apps/tests/bitblt/makefile @@ -0,0 +1,66 @@ +# Makefile - Proj_Listing1_5.dsp + +ifndef CFG +CFG=Proj_Listing1_5 - Win32 Debug +endif +CC=gcc +CFLAGS= +CXX=g++ +CXXFLAGS=$(CFLAGS) +RC=windres -O COFF +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Release" +CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +else +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Debug" +CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +endif +endif + +ifndef TARGET +TARGET=bitblt.exe +endif + +.PHONY: all +all: $(TARGET) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.res: %.rc + $(RC) $(CPPFLAGS) -o $@ -i $< + +SOURCE_FILES= \ + bitblt.cpp + +HEADER_FILES= + +RESOURCE_FILES= + +SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES) + +OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS))))) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +.PHONY: clean +clean: + -del $(OBJS) $(TARGET) + +.PHONY: depends +depends: + -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing1_5.dep + +-include Proj_Listing1_5.dep + diff --git a/apps/tests/consume/Makefile b/apps/tests/consume/Makefile new file mode 100644 index 0000000..22f8c19 --- /dev/null +++ b/apps/tests/consume/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = consume + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/consume/consume.c b/apps/tests/consume/consume.c new file mode 100644 index 0000000..81a52ca --- /dev/null +++ b/apps/tests/consume/consume.c @@ -0,0 +1,31 @@ +#include +#include +#include + +#define SIZE (65*1024*1024) + +ULONG x[SIZE / 4096]; + +int main() +{ + int i; + PUCHAR BaseAddress; + + BaseAddress = VirtualAlloc(NULL, + SIZE, + MEM_COMMIT, + PAGE_READONLY); + if (BaseAddress == NULL) + { + printf("Failed to allocate virtual memory"); + return(1); + } + printf("BaseAddress %p\n", BaseAddress); + for (i = 0; i < (SIZE / 4096); i++) + { + printf("%.8x ", i*4096); + x[i] = BaseAddress[i*4096]; + } + + return(0); +} diff --git a/apps/tests/count/Makefile b/apps/tests/count/Makefile new file mode 100644 index 0000000..8219d01 --- /dev/null +++ b/apps/tests/count/Makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = count + +TARGET_SDKLIBS = kernel32.a user32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/count/count.c b/apps/tests/count/count.c new file mode 100644 index 0000000..48b8f55 --- /dev/null +++ b/apps/tests/count/count.c @@ -0,0 +1,15 @@ +/* $Id$ + * + */ +#include + +int n = 0; + +int +main (int argc, char * argv []) +{ + while (1) printf ("%d ", n ++ ); + return (0); +} + +/* EOF */ diff --git a/apps/tests/dibtest/dibtest.c b/apps/tests/dibtest/dibtest.c new file mode 100644 index 0000000..81d532b --- /dev/null +++ b/apps/tests/dibtest/dibtest.c @@ -0,0 +1,81 @@ +#include + +extern BOOL STDCALL GdiDllInitialize(HANDLE hInstance, DWORD Event, LPVOID Reserved); + +void __stdcall Test1BPP (HDC Desktop) +{ + HDC TestDC; + HPEN WhitePen; + HBITMAP DIB1; + BITMAPINFOHEADER BitInf; + PBITMAPINFO BitPalInf; + DWORD bmiSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2; + + // Create a 1BPP DIB + BitPalInf = (PBITMAPINFO)malloc(bmiSize); + BitInf.biSize = sizeof(BITMAPINFOHEADER); + BitInf.biWidth = 50; + BitInf.biHeight = -50; // it's top down (since BI_RGB is used, the sign is operative of direction) + BitInf.biPlanes = 1; + BitInf.biBitCount = 1; + BitInf.biCompression = BI_RGB; + BitInf.biSizeImage = 0; + BitInf.biXPelsPerMeter = 0; + BitInf.biYPelsPerMeter = 0; + BitInf.biClrUsed = 0; + BitInf.biClrImportant = 0; + BitPalInf->bmiHeader = BitInf; + BitPalInf->bmiColors[1].rgbBlue = 255; + BitPalInf->bmiColors[1].rgbGreen = 255; + BitPalInf->bmiColors[1].rgbRed = 255; + BitPalInf->bmiColors[1].rgbReserved = 255; + BitPalInf->bmiColors[0].rgbBlue = 0; + BitPalInf->bmiColors[0].rgbGreen = 0; + BitPalInf->bmiColors[0].rgbRed = 0; + BitPalInf->bmiColors[0].rgbReserved = 0; + + DIB1 = (HBITMAP) CreateDIBSection(NULL, BitPalInf, DIB_RGB_COLORS, NULL, NULL, 0); + TestDC = CreateCompatibleDC(NULL); + SelectObject(TestDC, DIB1); + + // Draw a white rectangle on the 1BPP DIB + WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); + SelectObject(TestDC, WhitePen); + Rectangle(TestDC, 0, 0, 40, 40); + + // Blt the 1BPP DIB to the display + BitBlt(Desktop, 0, 0, 50, 50, TestDC, 0, 0, SRCCOPY); + + free(BitPalInf); +// Rectangle(Desktop, 50, 50, 200, 200); +} + +void DIBTest(void) +{ + HDC Desktop; + + // Set up a DC called Desktop that accesses DISPLAY + Desktop = CreateDCA("DISPLAY", NULL, NULL, NULL); + if(Desktop == NULL) { + printf("Can't create desktop\n"); + return; + } + + // 1BPP Test + Test1BPP(Desktop); + + Sleep(50000); + + // Free up everything + DeleteDC(Desktop); +} + +int main(int argc, char* argv[]) +{ + printf("Entering DIBTest..\n"); + + GdiDllInitialize (NULL, DLL_PROCESS_ATTACH, NULL); + DIBTest(); + + return 0; +} diff --git a/apps/tests/dibtest/makefile b/apps/tests/dibtest/makefile new file mode 100644 index 0000000..b80799b --- /dev/null +++ b/apps/tests/dibtest/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = dibtest + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/dump_shared_data/dump_shared_data.c b/apps/tests/dump_shared_data/dump_shared_data.c new file mode 100644 index 0000000..0b4a9e8 --- /dev/null +++ b/apps/tests/dump_shared_data/dump_shared_data.c @@ -0,0 +1,51 @@ +#include +#include + +int main() +{ + int i; + + printf("TickCountLow: %x\n", + SharedUserData->TickCountLow); + printf("Drives: "); + for (i = 0; i < 26; i++) + { + printf("%c", (SharedUserData->DosDeviceMap & (1 << i))?'1':'0'); + } + printf("\n"); + for (i = 0; i < 26; i++) + { + if (SharedUserData->DosDeviceMap & (1 << i)) + { + printf("%c: ", 'A'+i); + switch(SharedUserData->DosDeviceDriveType[i]) + { + case DOSDEVICE_DRIVE_UNKNOWN: + printf("Unknown\n"); + break; + case DOSDEVICE_DRIVE_CALCULATE: + printf("No root\n"); + break; + case DOSDEVICE_DRIVE_REMOVABLE: + printf("Removable\n"); + break; + case DOSDEVICE_DRIVE_FIXED: + printf("Fixed\n"); + break; + case DOSDEVICE_DRIVE_REMOTE: + printf("Remote\n"); + break; + case DOSDEVICE_DRIVE_CDROM: + printf("CD-ROM\n"); + break; + case DOSDEVICE_DRIVE_RAMDISK: + printf("Ram disk\n"); + break; + default: + printf("undefined type\n"); + break; + } + } + } + printf("\n\n"); +} diff --git a/apps/tests/dump_shared_data/makefile b/apps/tests/dump_shared_data/makefile new file mode 100644 index 0000000..5671945 --- /dev/null +++ b/apps/tests/dump_shared_data/makefile @@ -0,0 +1,20 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = dump_shared_data + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF + diff --git a/apps/tests/event/event.c b/apps/tests/event/event.c new file mode 100644 index 0000000..9942bea --- /dev/null +++ b/apps/tests/event/event.c @@ -0,0 +1,33 @@ +#include +#include + +HANDLE events[2]; + +DWORD WINAPI thread( LPVOID crap ) +{ + SetEvent( events[0] ); + if( crap ) + SetEvent( events[1] ); + return 1; +} + +int main( void ) +{ + DWORD id, Status; + printf( "Creating events\n" ); + events[0] = CreateEvent( 0, TRUE, FALSE, 0 ); + events[1] = CreateEvent( 0, TRUE, FALSE, 0 ); + printf( "Created events\n" ); + CreateThread( 0, 0, thread, 0, 0, &id ); + printf( "WaitForSingleObject %s\n", ( WaitForSingleObject( events[0], INFINITE ) == WAIT_OBJECT_0 ? "worked" : "failed" ) ); + ResetEvent( events[0] ); + CreateThread( 0, 0, thread, 0, 0, &id ); + printf( "WaitForMultipleObjects with waitall = FALSE %s\n", ( WaitForMultipleObjects( 2, events, FALSE, INFINITE ) == WAIT_OBJECT_0 ? "worked" : "failed" ) ); + ResetEvent( events[0] ); + CreateThread( 0, 0, thread, (void *)1, 0, &id ); + Status = WaitForMultipleObjects( 2, events, TRUE, INFINITE ); + printf( "WaitForMultipleObjects with waitall = TRUE %s\n", ( Status == WAIT_OBJECT_0 || Status == WAIT_OBJECT_0 + 1 ? "worked" : "failed" ) ); + ResetEvent( events[0] ); + printf( "WaitForSingleObject with timeout %s\n", ( WaitForSingleObject( events[0], 100 ) == WAIT_TIMEOUT ? "worked" : "failed" ) ); + return 0; +} diff --git a/apps/tests/event/makefile b/apps/tests/event/makefile new file mode 100644 index 0000000..ae8e31b --- /dev/null +++ b/apps/tests/event/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = event + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/file/Makefile b/apps/tests/file/Makefile new file mode 100644 index 0000000..7ccad3c --- /dev/null +++ b/apps/tests/file/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = file + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/file/file.c b/apps/tests/file/file.c new file mode 100644 index 0000000..27f716e --- /dev/null +++ b/apps/tests/file/file.c @@ -0,0 +1,54 @@ +/*********************************************************** + * File read/write test utility * + **********************************************************/ + +#include +#include +#include + +int main( void ) +{ + HANDLE file; + char buffer[4096]; + DWORD wrote; + int c; + + file = CreateFile("test.dat", + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + 0, + 0); + + if (file == INVALID_HANDLE_VALUE) + { + printf("Error opening file (Status %x)\n", GetLastError()); + return 1; + } + for( c = 0; c < sizeof( buffer ); c++ ) + buffer[c] = (char)c; + printf("Writing file\n"); + if (WriteFile( file, buffer, 4096, &wrote, NULL) == FALSE) + { + printf("Error writing file (Status %x)\n", GetLastError()); + exit(2); + } + printf("Reading file\n"); + SetFilePointer( file, 0, 0, FILE_BEGIN ); + if (ReadFile( file, buffer, 4096, &wrote, NULL) == FALSE) + { + printf("Error reading file (Status %x)\n", GetLastError()); + exit(3); + } + for( c = 0; c < sizeof( buffer ); c++ ) + if( buffer[c] != (char)c ) + { + printf( "Error: data read back is not what was written\n" ); + CloseHandle( file ); + return 0; + } + printf("Finished, works fine\n"); + CloseHandle( file ); + return 0; +} diff --git a/apps/tests/gditest/gditest.c b/apps/tests/gditest/gditest.c new file mode 100644 index 0000000..4a8cd1b --- /dev/null +++ b/apps/tests/gditest/gditest.c @@ -0,0 +1,344 @@ +/* + * gditest + dec 26, 2001 -- gditest bug fix by Richard Campbell + */ + +#include + +extern BOOL STDCALL GdiDllInitialize(HANDLE hInstance, DWORD Event, LPVOID Reserved); + +void __stdcall Background (HDC Desktop) +{ + HPEN Pen; + int x, y; + + Pen = CreatePen(PS_SOLID, 1, RGB(64, 64, 128)); + + SelectObject (Desktop, Pen); + + MoveToEx (Desktop, 0, 0, NULL); + LineTo (Desktop, 640, 480); + for (y = 479, x = 0; x < 640; x+=42) + { + MoveToEx (Desktop, 0, 0, NULL); + LineTo (Desktop, x, y); + } + for (y = 0, x = 639; y < 480; y+=42) + { + MoveToEx (Desktop, 0, 0, NULL); + LineTo (Desktop, x, y); + } +} + +void gditest( void ){ + HDC Desktop, MyDC, DC24; + HPEN RedPen, GreenPen, BluePen, WhitePen; + HBITMAP MyBitmap, DIB24; + HFONT hf, tf; + BITMAPINFOHEADER BitInf; + BITMAPINFO BitPalInf; + HRGN hRgn1, hRgn2, hRgn3; + HBRUSH BlueBrush, DefBrush; + + // Set up a DC called Desktop that accesses DISPLAY + Desktop = CreateDCA("DISPLAY", NULL, NULL, NULL); + if (Desktop == NULL){ + printf("Can't create desktop\n"); + return; + } + + // Background + Background (Desktop); + + +//ei + BlueBrush = CreateSolidBrush( RGB(0, 0, 0xff) ); + DefBrush = SelectObject( Desktop, BlueBrush ); + + hRgn1 = CreateRectRgn( 1, 2, 100, 101 ); + hRgn2 = CreateRectRgn( 10, 20, 150, 151 ); + hRgn3 = CreateRectRgn( 1, 1, 1, 1); + CombineRgn( hRgn3, hRgn1, hRgn2, RGN_XOR ); + + PaintRgn( Desktop, hRgn3 ); + SelectObject( Desktop, DefBrush ); + DeleteObject( BlueBrush ); + + // Create a blue pen and select it into the DC + BluePen = CreatePen(PS_SOLID, 8, RGB(0, 0, 0xff)); + SelectObject(Desktop, BluePen); + + // Draw a shape on the DC + MoveToEx(Desktop, 50, 50, NULL); + LineTo(Desktop, 200, 60); + LineTo(Desktop, 200, 300); + LineTo(Desktop, 50, 50); + MoveToEx(Desktop, 50, 50, NULL); + LineTo(Desktop, 200, 50); + + WhitePen = CreatePen(PS_SOLID, 3, RGB(0xff, 0xff, 0xff)); + SelectObject(Desktop, WhitePen); + + MoveToEx(Desktop, 20, 70, NULL); + LineTo(Desktop, 500, 70); + MoveToEx(Desktop, 70, 20, NULL); + LineTo(Desktop, 70, 150); + + // Test font support + GreenPen = CreatePen(PS_SOLID, 3, RGB(0, 0xff, 0)); + RedPen = CreatePen(PS_SOLID, 3, RGB(0xff, 0, 0)); + + hf = CreateFontA(24, 0, 0, TA_BASELINE, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "Helmet"); + SelectObject(Desktop, hf); + SetTextColor(Desktop, RGB(0xff, 0, 0)); + TextOutA(Desktop, 70, 70, "React", 5); + SetTextColor(Desktop, RGB(0, 0xff, 0)); + TextOutA(Desktop, 140, 70, "OS", 2); + + tf = CreateFontA(14, 0, 0, TA_BASELINE, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "Timmons"); + SelectObject(Desktop, tf); + SetTextColor(Desktop, RGB(0xff, 0xff, 0xff)); + TextOutA(Desktop, 70, 90, "This is a test of ReactOS text, using the FreeType 2 library!", 61); + + // TEST 1: Copy from the VGA into a device compatible DC, draw on it, then blt it to the VGA again + MyDC = CreateCompatibleDC(Desktop); + MyBitmap = CreateCompatibleBitmap(Desktop, 151, 251); + SelectObject(MyDC, MyBitmap); + BitBlt(MyDC, 0, 0, 151, 251, Desktop, 50, 50, SRCCOPY); // can we say 151, 251 since bottom corner is not inclusive? + + SelectObject(MyDC, GreenPen); + Rectangle(MyDC, 10, 10, 50, 50); + + // TEST 2: Copy from the device compatible DC into a 24BPP bitmap, draw on it, then blt to the VGA again + BitInf.biSize = sizeof(BITMAPINFOHEADER); + BitInf.biWidth = 152; + BitInf.biHeight = -252; // it's top down (since BI_RGB is used, the sign is operative of direction) + BitInf.biPlanes = 1; + BitInf.biBitCount = 24; + BitInf.biCompression = BI_RGB; + BitInf.biSizeImage = 0; + BitInf.biXPelsPerMeter = 0; + BitInf.biYPelsPerMeter = 0; + BitInf.biClrUsed = 0; + BitInf.biClrImportant = 0; + BitPalInf.bmiHeader = BitInf; + DIB24 = (HBITMAP) CreateDIBSection(NULL, &BitPalInf, DIB_RGB_COLORS, NULL, NULL, 0); + DC24 = CreateCompatibleDC(NULL); + SelectObject(DC24, DIB24); + + BitBlt(DC24, 0, 0, 101, 201, MyDC, 0, 0, SRCCOPY); + SelectObject(DC24, RedPen); + Rectangle(DC24, 80, 90, 100, 110); + MoveToEx(DC24, 80, 90, NULL); + LineTo(DC24, 100, 110); + BitBlt(Desktop, 200, 200, 110, 120, DC24, 0, 0, SRCCOPY); + + Sleep( 10000 ); // fixme delay only 10000 (for 10 seconds) + // Free up everything + DeleteDC(Desktop); + DeleteDC(MyDC); +} + +void DumpRgnData( HRGN hRgn ) +{ + int size, ret, i; + LPRGNDATA rgnData; + + size = GetRegionData( hRgn, 0, NULL ); + if( size == 0 ){ + printf("GetRegionData returned 0\n"); + return; + } + rgnData = (LPRGNDATA) malloc( size ); + ret = GetRegionData( hRgn, size, rgnData ); + if( ret == 0 ){ + printf("GetRegionData( hRgn, size, rgnData ) returned 0\n"); + return; + } + printf("Bounds: left=%d top=%d right=%d bottom=%d, count: %d, type: %i\n\n", + rgnData->rdh.rcBound.left, rgnData->rdh.rcBound.top, rgnData->rdh.rcBound.right, rgnData->rdh.rcBound.bottom, + rgnData->rdh.nCount, rgnData->rdh.iType); + printf("Rects:\t i \t left \t top \t right \t bottom\n"); + for ( i = 0; i < rgnData->rdh.nCount; i++ ) { + PRECT pr = (PRECT) rgnData->Buffer + i; + printf("\t %d \t %d \t %d \t %d \t %d\n", i, pr->left, pr->top, pr->right, pr->bottom ); + } + printf("\n"); +} + +void rgntest( void ) +{ + HRGN hRgn1, hRgn2, hRgn3; + RECT Rect; + int i; + + hRgn1 = CreateRectRgn( 1, 2, 100, 101 ); + if( hRgn1 == NULL ) { + printf("Failed at hRgn1 = CreateRectRgn( 1, 2, 100, 101 )\n"); + return; + } + i = GetRgnBox( hRgn1, &Rect ); + if( i==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("GetRgnBox( hRgn1, &Rect ): i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + + DumpRgnData( hRgn1 ); + + hRgn2 = CreateRectRgn( 51, 53, 150, 152 ); + if( hRgn2 == NULL ) { + printf("Failed at hRgn2 = CreateRectRgn( 51, 53, 150, 152 )\n"); + return; + } + i = GetRgnBox( hRgn2, &Rect ); + if( i==0 ){ + printf("Failed GetRgnBox( hRgn2, &Rect )\n"); + return; + } + printf("GetRgnBox( hRgn2, &Rect ): i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + + DumpRgnData( hRgn2 ); + + if( EqualRgn( hRgn1, hRgn2 ) == TRUE ){ + printf("\t hRgn1, hRgn2 are equal\n"); + } + else{ + printf("\t hRgn1, hRgn2 are NOT equal\n\n"); + } + + i = OffsetRgn(hRgn1,50,51); + if( i==ERROR ){ + printf("Failed OffsetRgn(hRgn1,50,51)\n"); + return; + } + + i = GetRgnBox( hRgn1, &Rect ); + if( i==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("After offset\nGetRgnBox( hRgn1, &Rect ): i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + + if( EqualRgn( hRgn1, hRgn2 ) == TRUE ){ + printf("\t hRgn1, hRgn2 are equal after offset\n"); + } + else{ + printf("\t hRgn1, hRgn2 are NOT equal after offset!\n\n"); + } + + i = SetRectRgn(hRgn1, 10, 11, 110, 111 ); + if( i==0 ){ + printf("Failed SetRectRgn(hRgn1... )\n"); + return; + } + i = GetRgnBox( hRgn1, &Rect ); + if( i==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("after SetRectRgn(hRgn1, 10, 11, 110, 111 ):\n i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + + hRgn3 = CreateRectRgn( 1, 1, 1, 1); + i = CombineRgn( hRgn3, hRgn1, hRgn2, RGN_AND ); + if( i==ERROR ){ + printf("Fail: CombineRgn( hRgn3, hRgn1, hRgn2, RGN_AND ). LastError: %d\n", GetLastError); + return; + } + + if( GetRgnBox( hRgn3, &Rect )==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("After CombineRgn( hRgn3, hRgn1, hRgn2, RGN_AND ): \nGetRgnBox( hRgn3, &Rect ): CR_i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + DumpRgnData( hRgn3 ); + + i = CombineRgn( hRgn3, hRgn1, hRgn2, RGN_OR ); + if( i==ERROR ){ + printf("Fail: CombineRgn( hRgn3, hRgn1, hRgn2, RGN_OR ). LastError: %d\n", GetLastError); + return; + } + + if( GetRgnBox( hRgn3, &Rect )==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("After CombineRgn( hRgn3, hRgn1, hRgn2, RGN_OR ): \nGetRgnBox( hRgn3, &Rect ): CR_i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + DumpRgnData( hRgn3 ); + + i = CombineRgn( hRgn3, hRgn1, hRgn2, RGN_DIFF ); + if( i==ERROR ){ + printf("Fail: CombineRgn( hRgn3, hRgn1, hRgn2, RGN_DIFF ). LastError: %d\n", GetLastError); + return; + } + + if( GetRgnBox( hRgn3, &Rect )==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("After CombineRgn( hRgn3, hRgn1, hRgn2, RGN_DIFF ): \nGetRgnBox( hRgn3, &Rect ): CR_i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + DumpRgnData( hRgn3 ); + + i = CombineRgn( hRgn3, hRgn1, hRgn2, RGN_XOR ); + if( i==ERROR ){ + printf("Fail: CombineRgn( hRgn3, hRgn1, hRgn2, RGN_XOR ). LastError: %d\n", GetLastError); + return; + } + + if( GetRgnBox( hRgn3, &Rect )==0 ){ + printf("Failed GetRgnBox( hRgn3, &Rect )\n"); + return; + } + printf("After CombineRgn( hRgn3, hRgn1, hRgn2, RGN_XOR ): \nGetRgnBox( hRgn3, &Rect ): CR_i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + DumpRgnData( hRgn3 ); + + i = CombineRgn( hRgn1, hRgn3, hRgn2, RGN_COPY ); + if( i==ERROR ){ + printf("Fail: CombineRgn( hRgn1, hRgn3, hRgn2, RGN_COPY ). LastError: %d\n", GetLastError); + return; + } + + if( GetRgnBox( hRgn1, &Rect )==0 ){ + printf("Failed GetRgnBox( hRgn1, &Rect )\n"); + return; + } + printf("After CombineRgn( hRgn1, hRgn3, hRgn2, RGN_COPY ): \nGetRgnBox( hRgn1, &Rect ): CR_i=%d, left=%d top=%d right=%d bottom=%d\n\n", + i, Rect.left, Rect.top, Rect.right, Rect.bottom ); + DumpRgnData( hRgn1 ); + + + DeleteObject( hRgn1 ); + DeleteObject( hRgn2 ); + DeleteObject( hRgn3 ); + printf("region test finished\n"); +} + +int main (int argc, char* argv[]) +{ + printf("Entering GDITest..\n"); + printf("use gditest for older tests\n"); + printf("use gditest 1 for region test\n"); + + GdiDllInitialize (NULL, DLL_PROCESS_ATTACH, NULL); + if( argc < 2 ) + gditest(); + else { + if( !strncmp( argv[1], "1", 1 ) ) { + rgntest(); + } + } + + return 0; +} diff --git a/apps/tests/gditest/makefile b/apps/tests/gditest/makefile new file mode 100644 index 0000000..d17a5a8 --- /dev/null +++ b/apps/tests/gditest/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = gditest + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/hello/hello.c b/apps/tests/hello/hello.c new file mode 100644 index 0000000..9e79338 --- /dev/null +++ b/apps/tests/hello/hello.c @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char* argv[]) +{ + printf("Hello world\n"); + return(0); +} diff --git a/apps/tests/hello/makefile b/apps/tests/hello/makefile new file mode 100644 index 0000000..f841e2e --- /dev/null +++ b/apps/tests/hello/makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = hello + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/isotest/isotest.c b/apps/tests/isotest/isotest.c new file mode 100644 index 0000000..684cc33 --- /dev/null +++ b/apps/tests/isotest/isotest.c @@ -0,0 +1,229 @@ +/* + * isotest - display cdrom information + */ + +#include +//#include +#include +#include + + +void HexDump(char *buffer, ULONG size) +{ + ULONG offset = 0; + unsigned char *ptr; + + while (offset < (size & ~15)) + { + ptr = (unsigned char*)((ULONG)buffer + offset); + printf("%08lx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx-%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", + offset, + ptr[0], + ptr[1], + ptr[2], + ptr[3], + ptr[4], + ptr[5], + ptr[6], + ptr[7], + ptr[8], + ptr[9], + ptr[10], + ptr[11], + ptr[12], + ptr[13], + ptr[14], + ptr[15]); + + printf(" %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", + isprint(ptr[0])?ptr[0]:'.', + isprint(ptr[1])?ptr[1]:'.', + isprint(ptr[2])?ptr[2]:'.', + isprint(ptr[3])?ptr[3]:'.', + isprint(ptr[4])?ptr[4]:'.', + isprint(ptr[5])?ptr[5]:'.', + isprint(ptr[6])?ptr[6]:'.', + isprint(ptr[7])?ptr[7]:'.', + isprint(ptr[8])?ptr[8]:'.', + isprint(ptr[9])?ptr[9]:'.', + isprint(ptr[10])?ptr[10]:'.', + isprint(ptr[11])?ptr[11]:'.', + isprint(ptr[12])?ptr[12]:'.', + isprint(ptr[13])?ptr[13]:'.', + isprint(ptr[14])?ptr[14]:'.', + isprint(ptr[15])?ptr[15]:'.'); + + offset += 16; + } + + ptr = (unsigned char*)((ULONG)buffer + offset); + if (offset < size) + { + printf("%08lx ", offset); + while (offset < size) + { + printf(" %02hx", *ptr); + offset++; + ptr++; + } + } + + printf("\n\n"); +} + + +#ifndef EVENT_ALL_ACCESS +#define EVENT_ALL_ACCESS (0x1f0003L) +#endif + +BOOL +ReadBlock(HANDLE FileHandle, + PVOID Buffer, + PLARGE_INTEGER Offset, + ULONG Length, + PULONG BytesRead) +{ + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE EventHandle; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, 0, NULL, NULL); + + Status = NtCreateEvent(&EventHandle, + EVENT_ALL_ACCESS, + &ObjectAttributes, + TRUE, + FALSE); + if (!NT_SUCCESS(Status)) + { + printf("NtCreateEvent() failed\n"); + return(FALSE); + } + + Status = NtReadFile(FileHandle, + EventHandle, + NULL, + NULL, + &IoStatusBlock, + Buffer, + Length, + Offset, + NULL); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(EventHandle, FALSE, NULL); + Status = IoStatusBlock.Status; + } + + NtClose(EventHandle); + + if (Status != STATUS_PENDING && BytesRead != NULL) + { + *BytesRead = IoStatusBlock.Information; + } + if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) + { + printf("ReadBlock() failed (Status: %lx)\n", Status); + return(FALSE); + } + + return(TRUE); +} + + + +int main (int argc, char *argv[]) +{ + HANDLE hDisk; + DWORD dwRead; + DWORD i; + char *Buffer; + CHAR Filename[80]; + LARGE_INTEGER FilePosition; + + if (argc != 2) + { + printf("Usage: isotest [Drive:]\n"); + return 0; + } + + strcpy(Filename, "\\\\.\\"); + strcat(Filename, argv[1]); + + hDisk = CreateFile(Filename, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (hDisk == INVALID_HANDLE_VALUE) + { + printf("CreateFile(): Invalid disk handle!\n"); + return 0; + } + + Buffer = (char*)malloc(2048); + if (Buffer == NULL) + { + CloseHandle(hDisk); + printf("Out of memory!\n"); + return 0; + } + memset(Buffer, 0, 2048); + + + FilePosition.QuadPart = 16 * 2048; +#if 0 + SetLastError(NO_ERROR); + SetFilePointer(hDisk, + FilePosition.u.LowPart, + &FilePosition.u.HighPart, + FILE_BEGIN); + if (GetLastError() != NO_ERROR) + { + CloseHandle(hDisk); + free(Buffer); + printf("SetFilePointer() failed!\n"); + return 0; + } + + if (ReadFile(hDisk, + Buffer, + 2048, + &dwRead, + NULL) == FALSE) + { + CloseHandle(hDisk); + free(Buffer); + printf("ReadFile() failed!\n"); + return 0; + } +#endif + + if (ReadBlock(hDisk, + Buffer, + &FilePosition, + 2048, + &dwRead) == FALSE) + { + CloseHandle(hDisk); + free(Buffer); +#if 0 + printf("ReadBlock() failed!\n"); +#endif + return 0; + } + + HexDump(Buffer, 128); + + CloseHandle(hDisk); + + free(Buffer); + + return 0; +} + +/* EOF */ diff --git a/apps/tests/isotest/makefile b/apps/tests/isotest/makefile new file mode 100644 index 0000000..cad97f2 --- /dev/null +++ b/apps/tests/isotest/makefile @@ -0,0 +1,23 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = isotest + +#TARGET_CFLAGS = -fnative_struct + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/lpc/conport.c b/apps/tests/lpc/conport.c new file mode 100644 index 0000000..bb3dc7f --- /dev/null +++ b/apps/tests/lpc/conport.c @@ -0,0 +1,205 @@ +/* $Id$ + * + * reactos/apps/lpc/conport.c + * + * To be run in a real WNT 4.0 system with + * "\SmApiPort" as argument. Do not try to + * connect to "\Windows\ApiPort" since that + * reboots immeditely. + * + * Use Russinovich' HandleEx to verify + * conport.exe owns two unnamed LPC ports: + * the one created by kernel32.dll connecting + * to csrss.exe, and one connected to here. + * + * 19990627 (Emanuele Aliberti) + * Initial implementation. + * 19990704 (EA) + * Dump object's attributes moved in dumpinfo.c. + */ +#include +#include +#include +#define PROTO_LPC +#include +#include "dumpinfo.h" + +#define LPC_CONNECT_FLAG1 0x00000001 +#define LPC_CONNECT_FLAG2 0x00000010 +#define LPC_CONNECT_FLAG3 0x00000100 +#define LPC_CONNECT_FLAG4 0x00001000 +#define LPC_CONNECT_FLAG5 0x00010000 + +NTSTATUS +(STDCALL * ConnectPort)( + OUT PHANDLE PortHandle, + IN PUNICODE_STRING PortName, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN DWORD Unknown3, + IN DWORD Unknown4, + IN DWORD Unknown5, + IN DWORD Unknown6, + IN ULONG Flags + ); + +NTSTATUS +(STDCALL * QueryObject)( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +(STDCALL * YieldExecution)(VOID); + +#define BUF_SIZE 1024 +#define MAXARG 1000000 + + +VOID +TryConnectPort(char *port_name) +{ + DWORD Status = 0; + HANDLE Port = 0; + int i; + UNICODE_STRING PortName; + OBJECT_ATTRIBUTES ObjectAttributes; + WORD Name [BUF_SIZE] = {0}; + int dwx = 0; + char * port_name_save = port_name; + + /* + * Convert the port's name to Unicode. + */ + for ( + PortName.Length = 0; + ( *port_name + && (PortName.Length < BUF_SIZE) + ); + ) + { + Name[PortName.Length++] = (WORD) *port_name++; + } + Name[PortName.Length] = 0; + + PortName.Length = PortName.Length * sizeof (WORD); + PortName.MaximumLength = PortName.Length + sizeof (WORD); + PortName.Buffer = (PWSTR) Name; + /* + * Prepare the port object attributes. + */ + ObjectAttributes.Length = + sizeof (OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = + NULL; + ObjectAttributes.ObjectName = + NULL /*& PortName */; + ObjectAttributes.Attributes = + OBJ_CASE_INSENSITIVE; + ObjectAttributes.SecurityDescriptor = + NULL; + ObjectAttributes.SecurityQualityOfService = + NULL; + /* + * Try to issue a connection request. + */ + Port = 0; + Status = ConnectPort( + & Port, /* & PortHandle */ + & PortName, /* & PortName */ + & ObjectAttributes, /* & PortAttributes */ + NULL, /* & SecurityQos */ + NULL, /* & SectionInfo */ + NULL, /* & MapInfo */ + NULL, /* & MaxMessageSize */ + LPC_CONNECT_FLAG5 /* & ConnectInfoLength */ + ); + if (Status == STATUS_SUCCESS) + { + DumpInfo( + Name, + Status, + "connected", + Port + ); + /* Hot waiting */ + for (dwx=0; dwx +#include +#include +#define PROTO_LPC +#include +#include "dumpinfo.h" + +#define LPC_CONNECT_FLAG1 0x00000001 +#define LPC_CONNECT_FLAG2 0x00000010 +#define LPC_CONNECT_FLAG3 0x00000100 +#define LPC_CONNECT_FLAG4 0x00001000 +#define LPC_CONNECT_FLAG5 0x00010000 + +NTSTATUS +(STDCALL * CreatePort)( + /*OUT PHANDLE PortHandle,*/ + PVOID Buffer, + IN POBJECT_ATTRIBUTES PortAttributes OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN DWORD Unknown3, + IN ULONG Flags + ); + +NTSTATUS +(STDCALL * QueryObject)( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +(STDCALL * YieldExecution)(VOID); + +#define BUF_SIZE 1024 +#define MAXARG 5000000 + + +VOID +TryCreatePort(char *port_name) +{ + DWORD Status = 0; + HANDLE Port = 0; + int i; + UNICODE_STRING PortName; + OBJECT_ATTRIBUTES ObjectAttributes; + WORD Name [BUF_SIZE] = {0}; + int dwx = 0; + char * port_name_save = port_name; + + /* + * Convert the port's name to Unicode. + */ + for ( + PortName.Length = 0; + ( *port_name + && (PortName.Length < BUF_SIZE) + ); + ) + { + Name[PortName.Length++] = (WORD) *port_name++; + } + Name[PortName.Length] = 0; + + PortName.Length = PortName.Length * sizeof (WORD); + PortName.MaximumLength = PortName.Length + sizeof (WORD); + PortName.Buffer = (PWSTR) Name; + /* + * Prepare the port object attributes. + */ + ObjectAttributes.Length = + sizeof (OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = + NULL; + ObjectAttributes.ObjectName = + & PortName; + ObjectAttributes.Attributes = + 0; //OBJ_CASE_INSENSITIVE --> STATUS_INVALID_PARAMETER ==> case sensitive!; + ObjectAttributes.SecurityDescriptor = + NULL; + ObjectAttributes.SecurityQualityOfService = + NULL; + /* + * Try to issue a connection request. + */ + Port = 0; + Status = CreatePort( + & Port, + & ObjectAttributes, + 0, /* ACCESS_MASK? */ + 0, /* Unknown3 */ + LPC_CONNECT_FLAG5 + ); + if (Status == STATUS_SUCCESS) + { + DumpInfo( + Name, + Status, + "created", + Port + ); + /* Hot waiting */ + for (dwx=0; dwx +#include +#include +#include + +#define BUF_SIZE 1024 +#define MAX_BASIC_INFO_SIZE 512 + + +extern +NTSTATUS +(STDCALL * QueryObject)( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +extern +NTSTATUS +(STDCALL * QueryInformationPort)( + IN HANDLE PortHandle, + IN CINT PortInformationClass, /* guess */ + OUT PVOID PortInformation, /* guess */ + IN ULONG PortInformationLength, /* guess */ + OUT PULONG ReturnLength /* guess */ + ); + + +/* +static +VOID +DumpBuffer( + char *Name, + BYTE *buffer, + ULONG size + ) +{ + register ULONG i = 0; + + printf("%s [%d] = ",Name,size); + for ( i = 0; + i != size; + ++i + ) + { + printf("%02X",buffer[i]); + } + printf("\n"); +} +*/ + +VOID +DumpInfo ( + LPCWSTR Name, + NTSTATUS Status, + LPCWSTR Comment, + HANDLE Port + ) +{ + BYTE ObjectInformation [BUF_SIZE] = {0}; + ULONG ResultLength; + + wprintf( + L"Port \"%s\" %s:\n", + Name, + Comment + ); + + printf("\tStatus = %08X\n",Status); + printf("\tPort = %08X\n\n",Port); + /* + * Query object information. + */ + printf("Basic Information:\n"); + Status = QueryObject( + Port, + ObjectBasicInformation, + ObjectInformation, + sizeof (LPC_PORT_BASIC_INFORMATION), + & ResultLength + ); + if (Status == STATUS_SUCCESS) + { + PLPC_PORT_BASIC_INFORMATION i; + + i = (PLPC_PORT_BASIC_INFORMATION) ObjectInformation; + + printf( "\tUnknown01 = 0x%08X\n", i->Unknown0 ); + printf( "\tUnknown02 = 0x%08X\n", i->Unknown1 ); + printf( "\tUnknown03 = 0x%08X\n", i->Unknown2 ); + printf( "\tUnknown04 = 0x%08X\n", i->Unknown3 ); + printf( "\tUnknown05 = 0x%08X\n", i->Unknown4 ); + printf( "\tUnknown06 = 0x%08X\n", i->Unknown5 ); + printf( "\tUnknown07 = 0x%08X\n", i->Unknown6 ); + printf( "\tUnknown08 = 0x%08X\n", i->Unknown7 ); + printf( "\tUnknown09 = 0x%08X\n", i->Unknown8 ); + printf( "\tUnknown10 = 0x%08X\n", i->Unknown9 ); + printf( "\tUnknown11 = 0x%08X\n", i->Unknown10 ); + printf( "\tUnknown12 = 0x%08X\n", i->Unknown11 ); + printf( "\tUnknown13 = 0x%08X\n", i->Unknown12 ); + printf( "\tUnknown14 = 0x%08X\n", i->Unknown13 ); + } + else + { + printf("\tStatus = %08X\n",Status); + } + printf("Type Information:\n"); + Status = QueryObject( + Port, + ObjectTypeInformation, + ObjectInformation, + sizeof ObjectInformation, + & ResultLength + ); + if (Status == STATUS_SUCCESS) + { + OBJECT_TYPE_INFORMATION * i; + + i = (OBJECT_TYPE_INFORMATION *) ObjectInformation; + + wprintf( + L"\tName: \"%s\"\n", + (i->Name.Length ? i->Name.Buffer : L"") + ); +/* +FIXME: why this always raise an access violation exception? + wprintf( + L"\tType: \"%s\"\n", + (i->Type.Length ? i->Type.Buffer : L"") + ); +/**/ + printf( + "\tTotal Handles: %d\n", + i->TotalHandles + ); + printf( + "\tReference Count: %d\n", + i->ReferenceCount + ); + } + else + { + printf("\tStatus = %08X\n",Status); + } + printf("Name Information:\n"); + Status = QueryObject( + Port, + ObjectNameInformation, + ObjectInformation, + sizeof ObjectInformation, + & ResultLength + ); + if (Status == STATUS_SUCCESS) + { + OBJECT_NAME_INFORMATION * i; + + i = (OBJECT_NAME_INFORMATION *) ObjectInformation; + wprintf( + L"\tName: \"%s\"\n", + (i->Name.Length ? i->Name.Buffer : L"") + ); + } + else + { + printf("\tStatus = %08X\n",Status); + } + printf("Data Information:\n"); + Status = QueryObject( + Port, + ObjectDataInformation, + ObjectInformation, + sizeof ObjectInformation, + & ResultLength + ); + if (Status == STATUS_SUCCESS) + { + OBJECT_DATA_INFORMATION * i; + + i = (OBJECT_DATA_INFORMATION *) ObjectInformation; + printf( + "\tInherit Handle: %s\n", + (i->bInheritHandle ? "TRUE" : "FALSE") + ); + printf( + "\tProtect from Close: %s\n", + (i->bProtectFromClose ? "TRUE" : "FALSE") + ); + } + else + { + printf("\tStatus = %08X\n",Status); + } +//--- + printf("Port Information:\n"); +/* Status = QueryInformationPort( + Port, + 1, /* info class * / + ObjectInformation, + sizeof ObjectInformation, + & ResultLength + ); + if (Status == STATUS_SUCCESS) + { + DWORD * i = ObjectInformation; + int j = 0; + + while (j < ResultLength / sizeof (DWORD)) + { + printf("\t%08X\n",i[j]); + ++j; + } + } + else + { + printf("\tStatus = %08X\n",Status); + } +*/ +} + + +/* EOF */ diff --git a/apps/tests/lpc/dumpinfo.h b/apps/tests/lpc/dumpinfo.h new file mode 100644 index 0000000..51e7873 --- /dev/null +++ b/apps/tests/lpc/dumpinfo.h @@ -0,0 +1,8 @@ +VOID +DumpInfo ( + LPCWSTR Name, + NTSTATUS Status, + LPCWSTR Comment, + HANDLE Port + ); + diff --git a/apps/tests/lpc/lpcclt.c b/apps/tests/lpc/lpcclt.c new file mode 100644 index 0000000..b7e01f6 --- /dev/null +++ b/apps/tests/lpc/lpcclt.c @@ -0,0 +1,92 @@ +/* $Id$ + * + * DESCRIPTION: Simple LPC Client + * PROGRAMMER: David Welch + */ +#include +#include +#include +#include +#include +#include +#include + +#include "lpctest.h" + +const char * MyName = "LPC-CLI"; +HANDLE OutputHandle; +HANDLE InputHandle; + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +int main(int argc, char* argv[]) +{ + UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(TEST_PORT_NAME_U); + NTSTATUS Status; + HANDLE PortHandle; + LPC_MAX_MESSAGE Request; + ULONG ConnectInfo; + ULONG ConnectInfoLength = 0; + SECURITY_QUALITY_OF_SERVICE Sqos; + + printf("%s: Lpc test client\n", MyName); + + printf("%s: Connecting to port \"%s\"...\n", MyName, TEST_PORT_NAME); + ConnectInfoLength = 0; + ZeroMemory (& Sqos, sizeof Sqos); + Status = NtConnectPort(&PortHandle, + &PortName, + & Sqos, + 0, + 0, + 0, + NULL, + &ConnectInfoLength); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtConnectPort() failed with status = 0x%08X.\n", MyName, Status); + return EXIT_FAILURE; + } + + printf("%s: Connected to \"%s\" with anonymous port 0x%x.\n", MyName, TEST_PORT_NAME, PortHandle); + + ZeroMemory(& Request, sizeof Request); + strcpy(Request.Data, GetCommandLineA()); + Request.Header.DataSize = strlen(Request.Data); + Request.Header.MessageSize = sizeof(LPC_MESSAGE_HEADER) + + Request.Header.DataSize; + + printf("%s: Sending to port 0x%x message \"%s\"...\n", + MyName, + PortHandle, + (char *) Request.Data); + Status = NtRequestPort(PortHandle, + &Request.Header); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtRequestPort(0x%x) failed with status = 0x%8X.\n", + MyName, + PortHandle, + Status); + return EXIT_FAILURE; + } + + printf("%s: Sending datagram to port 0x%x succeeded.\n", MyName, PortHandle); + + Sleep(2000); + + printf("%s: Disconnecting...", MyName); + NtClose (PortHandle); + + return EXIT_SUCCESS; +} diff --git a/apps/tests/lpc/lpcsrv.c b/apps/tests/lpc/lpcsrv.c new file mode 100644 index 0000000..0dfbdb6 --- /dev/null +++ b/apps/tests/lpc/lpcsrv.c @@ -0,0 +1,139 @@ +/* $Id$ + * + * DESCRIPTION: Simple LPC Server + * PROGRAMMER: David Welch + */ +#include +#include +#include +#include +#include +#include +#include + +#include "lpctest.h" + +static const char * MyName = "LPC-SRV"; + +HANDLE OutputHandle; +HANDLE InputHandle; + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +int main(int argc, char* argv[]) +{ + UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(TEST_PORT_NAME_U); + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE NamedPortHandle; + HANDLE PortHandle; + LPC_MAX_MESSAGE ConnectMsg; + + printf("%s: Lpc test server\n", MyName); + + InitializeObjectAttributes(&ObjectAttributes, + &PortName, + 0, + NULL, + NULL); + + printf("%s: Creating port \"%s\"...\n", MyName, TEST_PORT_NAME); + Status = NtCreatePort(&NamedPortHandle, + &ObjectAttributes, + 0, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtCreatePort() failed with status = 0x%08lX.\n", MyName, Status); + return EXIT_FAILURE; + } + printf("%s: Port \"%s\" created (0x%x).\n\n", MyName, TEST_PORT_NAME, NamedPortHandle); + + for (;;) + { + printf("%s: Listening for connections requests on port 0x%x...\n", MyName, NamedPortHandle); + Status = NtListenPort(NamedPortHandle, + &ConnectMsg.Header); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtListenPort() failed with status = 0x%08lX.\n", MyName, Status); + return EXIT_FAILURE; + } + + printf("%s: Received connection request 0x%08x on port 0x%x.\n", MyName, + ConnectMsg.Header.MessageId, NamedPortHandle); + printf("%s: Request from: PID=%x, TID=%x.\n", MyName, + ConnectMsg.Header.Cid.UniqueProcess, ConnectMsg.Header.Cid.UniqueThread); + + printf("%s: Accepting connection request 0x%08x...\n", MyName, + ConnectMsg.Header.MessageId); + Status = NtAcceptConnectPort(&PortHandle, + NamedPortHandle, + & ConnectMsg.Header, + TRUE, + 0, + NULL); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtAcceptConnectPort() failed with status = 0x%08lX.\n", MyName, Status); + return EXIT_FAILURE; + } + printf("%s: Connection request 0x%08x accepted as port 0x%x.\n", MyName, + ConnectMsg.Header.MessageId, PortHandle); + + printf("%s: Completing connection for port 0x%x (0x%08x).\n", MyName, + PortHandle, ConnectMsg.Header.MessageId); + Status = NtCompleteConnectPort(PortHandle); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtCompleteConnectPort() failed with status = 0x%08lX.\n", MyName, Status); + return EXIT_FAILURE; + } + + printf("%s: Entering server loop for port 0x%x...\n", MyName, PortHandle); + for(;;) + { + LPC_MAX_MESSAGE Request; + + Status = NtReplyWaitReceivePort(PortHandle, + 0, + NULL, + &Request.Header); + if (!NT_SUCCESS(Status)) + { + printf("%s: NtReplyWaitReceivePort() failed with status = 0x%08lX.\n", MyName, Status); + return EXIT_FAILURE; + } + + if (LPC_DATAGRAM == PORT_MESSAGE_TYPE(Request)) + { + printf("%s: Datagram message contents are <%s>.\n", + MyName, + Request.Data); + } + else + { + printf("%s: Message with type %d received on port 0x%x.\n", MyName, + PORT_MESSAGE_TYPE(Request), PortHandle); + NtClose(PortHandle); + printf("%s: Connected port 0x%x closed.\n\n", MyName, PortHandle); + break; + } + } + } + return EXIT_SUCCESS; +} + + +/* EOF */ diff --git a/apps/tests/lpc/lpctest.h b/apps/tests/lpc/lpctest.h new file mode 100644 index 0000000..6e65208 --- /dev/null +++ b/apps/tests/lpc/lpctest.h @@ -0,0 +1,5 @@ +#ifndef _LPCTEST_H +#define _LPCTEST_H +#define TEST_PORT_NAME "\\TestPort" +#define TEST_PORT_NAME_U L"\\TestPort" +#endif diff --git a/apps/tests/lpc/makefile b/apps/tests/lpc/makefile new file mode 100644 index 0000000..afa9b5c --- /dev/null +++ b/apps/tests/lpc/makefile @@ -0,0 +1,45 @@ +# +# +# +PATH_TO_TOP = ../../.. + +include $(PATH_TO_TOP)/rules.mak + +SRV_OBJECTS= lpcsrv.o +CLT_OBJECTS= lpcclt.o + +PROGS= lpcsrv.exe lpcclt.exe + +BASE_CFLAGS = -I$(PATH_TO_TOP)/include + +LIBS = $(SDK_PATH_LIB)/kernel32.a \ + $(SDK_PATH_LIB)/ntdll.a + +all: $(PROGS) + +.phony: all + +implib: + +clean: + - $(RM) lpcsrv.o lpcsrv.exe lpcsrv.sym lpcclt.o lpcclt.exe lpcsrv.sym + +.phony: implib clean + +install: $(PROGS:%=$(INSTALL_DIR)/bin/%) + +$(PROGS:%=$(INSTALL_DIR)/bin/%): $(INSTALL_DIR)/bin/%: % + $(CP) $* $(INSTALL_DIR)/bin/$* + +dist: $(PROGS:%=$(DIST_DIR)/apps/%) + +$(PROGS:%=$(DIST_DIR)/apps/%): $(DIST_DIR)/apps/%: % + $(CP) $* $(DIST_DIR)/apps/$* + +lpcsrv.exe: $(SRV_OBJECTS) $(LIBS) + $(CC) $(SRV_OBJECTS) $(LIBS) -o lpcsrv.exe + $(NM) --numeric-sort lpcsrv.exe > lpcsrv.sym + +lpcclt.exe: $(CLT_OBJECTS) $(LIBS) + $(CC) $(CLT_OBJECTS) $(LIBS) -o lpcclt.exe + $(NM) --numeric-sort lpcclt.exe > lpcclt.sym diff --git a/apps/tests/mktime/makefile b/apps/tests/mktime/makefile new file mode 100644 index 0000000..73543bf --- /dev/null +++ b/apps/tests/mktime/makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = mktime + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/mktime/mktime.c b/apps/tests/mktime/mktime.c new file mode 100644 index 0000000..f38b91e --- /dev/null +++ b/apps/tests/mktime/mktime.c @@ -0,0 +1,28 @@ + +#include +#include + +struct tm time_str; + +char daybuf[20]; + +int main(void) +{ + printf("Testing mktime() by asking\n"); + printf("What day of the week is July 4, 2001?\n"); + + time_str.tm_year = 2001 - 1900; + time_str.tm_mon = 7 - 1; + time_str.tm_mday = 4; + time_str.tm_hour = 0; + time_str.tm_min = 0; + time_str.tm_sec = 1; + time_str.tm_isdst = -1; + if (mktime(&time_str) == -1) + (void)puts("-unknown-"); + else { + (void)strftime(daybuf, sizeof(daybuf), "%A", &time_str); + (void)puts(daybuf); + } + return 0; +} \ No newline at end of file diff --git a/apps/tests/mstest/Makefile b/apps/tests/mstest/Makefile new file mode 100644 index 0000000..fd46a80 --- /dev/null +++ b/apps/tests/mstest/Makefile @@ -0,0 +1,45 @@ +# +# +# +PATH_TO_TOP = ../../.. + +include $(PATH_TO_TOP)/rules.mak + +SRV_OBJECTS = msserver.o +CLT_OBJECTS = msclient.o + +PROGS = msserver.exe msclient.exe + +BASE_CFLAGS = -I$(PATH_TO_TOP)/include + +LIBS = $(SDK_PATH_LIB)/kernel32.a \ + $(SDK_PATH_LIB)/ntdll.a + +all: $(PROGS) + +.phony: all + +implib: + +clean: + - $(RM) *.o *.exe *.sym + +.phony: implib clean + +install: $(PROGS:%=$(INSTALL_DIR)/bin/%) + +$(PROGS:%=$(INSTALL_DIR)/bin/%): $(INSTALL_DIR)/bin/%: % + $(CP) $* $(INSTALL_DIR)/bin/$* + +dist: $(PROGS:%=$(DIST_DIR)/apps/%) + +$(PROGS:%=$(DIST_DIR)/apps/%): $(DIST_DIR)/apps/%: % + $(CP) $* $(DIST_DIR)/apps/$* + +msserver.exe: $(SRV_OBJECTS) $(LIBS) + $(CC) $(SRV_OBJECTS) $(LIBS) -o msserver.exe + $(NM) --numeric-sort msserver.exe > msserver.sym + +msclient.exe: $(CLT_OBJECTS) $(LIBS) + $(CC) $(CLT_OBJECTS) $(LIBS) -o msclient.exe + $(NM) --numeric-sort msclient.exe > msclient.sym diff --git a/apps/tests/mstest/msclient.c b/apps/tests/mstest/msclient.c new file mode 100644 index 0000000..873148f --- /dev/null +++ b/apps/tests/mstest/msclient.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +#define BUFSIZE 1024 +#define MAILSLOT_TIMEOUT 1000 + + +int main(int argc, char *argv[]) +{ + HANDLE hMailslot; + LPSTR lpszMailslotName = "\\\\.\\MAILSLOT\\mymailslot"; + LPSTR lpszTestMessage = "Mailslot test message!"; + DWORD cbLength, cbWritten; + + hMailslot = CreateFile(lpszMailslotName, + GENERIC_WRITE, + FILE_SHARE_READ, + (LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + (HANDLE)NULL); + printf("hMailslot %x\n", (DWORD)hMailslot); + if (hMailslot == INVALID_HANDLE_VALUE) + { + printf("CreateFile() failed\n"); + return 0; + } + + cbLength = (ULONG)strlen(lpszTestMessage)+1; + + WriteFile(hMailslot, + lpszTestMessage, + cbLength, + &cbWritten, + NULL); + + CloseHandle(hMailslot); + + return 0; +} + +/* EOF */ + diff --git a/apps/tests/mstest/msserver.c b/apps/tests/mstest/msserver.c new file mode 100644 index 0000000..939c0aa --- /dev/null +++ b/apps/tests/mstest/msserver.c @@ -0,0 +1,40 @@ + + +#include + + +int main(int argc, char *argv[]) +{ + HANDLE hMailslot; + CHAR chBuf[512]; + BOOL fResult; + DWORD cbRead; + LPTSTR lpszMailslotName = "\\\\.\\mailslot\\mymailslot"; + + hMailslot = CreateMailslot(lpszMailslotName, + 512, + MAILSLOT_WAIT_FOREVER, + NULL); +for (;;) +{ + fResult = ReadFile(hMailslot, + chBuf, + 512, + &cbRead, + NULL); + if (fResult == FALSE) + { + printf("ReadFile() failed!\n"); + CloseHandle(hMailslot); + return 0; + } + + printf("Data read: %s\n", chBuf); +} + + CloseHandle(hMailslot); + + return 0; +} + +/* EOF */ diff --git a/apps/tests/mutex/makefile b/apps/tests/mutex/makefile new file mode 100644 index 0000000..fc71445 --- /dev/null +++ b/apps/tests/mutex/makefile @@ -0,0 +1,22 @@ +# +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = mutex + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/mutex/mutex.c b/apps/tests/mutex/mutex.c new file mode 100644 index 0000000..0026880 --- /dev/null +++ b/apps/tests/mutex/mutex.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include + + +HANDLE OutputHandle; +HANDLE InputHandle; + +HANDLE hThread[2]; +DWORD dwCounter = 0; +HANDLE hMutex; + + +void dprintf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +DWORD WINAPI thread1(LPVOID crap) +{ + DWORD dwError = 0; + DWORD i; + + dprintf("Thread 1 running!\n"); + + for (i = 0; i < 10; i++) + { + dwError = WaitForSingleObject(hMutex, INFINITE); + if (dwError == WAIT_FAILED) + { + dprintf("Thread2: WaitForSingleObject failed!\n"); + return 1; + } + else if (dwError == WAIT_ABANDONED_0) + { + dprintf("Thread2: WaitForSingleObject returned WAIT_ABANDONED_0\n"); + } + + dprintf("Thread1: dwCounter : %lu -->", dwCounter); + dwCounter++; + dprintf(" %lu\n", dwCounter); + ReleaseMutex(hMutex); + } + + return 1; +} + +DWORD WINAPI thread2(LPVOID crap) +{ + DWORD dwError = 0; + DWORD i; + dprintf("Thread 2 running!\n"); + + for (i = 0; i < 10; i++) + { + dwError = WaitForSingleObject(hMutex, INFINITE); + if (dwError == WAIT_FAILED) + { + dprintf("Thread2: WaitForSingleObject failed!\n"); + return 1; + } + else if (dwError == WAIT_ABANDONED_0) + { + dprintf("Thread2: WaitForSingleObject returned WAIT_ABANDONED_0\n"); + } + + dprintf("Thread2: dwCounter : %lu -->", dwCounter); + dwCounter++; + dprintf(" %lu\n", dwCounter); + ReleaseMutex(hMutex); + } + + return 1; +} + + +int main(int argc, char* argv[]) +{ + DWORD dwError; + DWORD id1,id2; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + dprintf("Calling CreateMutex()\n"); + hMutex = CreateMutexW(NULL, FALSE, L"TestMutex"); + if (hMutex == INVALID_HANDLE_VALUE) + { + dprintf("CreateMutex() failed! Error: %lu\n", GetLastError); + return 0; + } + dprintf("CreateMutex() succeeded!\n"); + + hThread[0] = CreateThread(0, 0, thread1, 0, 0, &id1); + hThread[1] = CreateThread(0, 0, thread2, 0, 0, &id2); + + dprintf("Calling WaitForMultipleObject()\n"); + dwError = WaitForMultipleObjects(2, hThread, TRUE, INFINITE); + dprintf("WaitForMultipleObject() Error: %lu\n", dwError); + + CloseHandle(hThread[0]); + CloseHandle(hThread[1]); + + CloseHandle(hMutex); + + return 0; +} diff --git a/apps/tests/nptest/Makefile b/apps/tests/nptest/Makefile new file mode 100644 index 0000000..6f87406 --- /dev/null +++ b/apps/tests/nptest/Makefile @@ -0,0 +1,44 @@ +# +# +# +PATH_TO_TOP = ../../.. + +include $(PATH_TO_TOP)/rules.mak + +SRV_OBJECTS = npserver.o +CLT_OBJECTS = npclient.o + +PROGS = npserver.exe npclient.exe + +BASE_CFLAGS = -I$(PATH_TO_TOP)/include + +LIBS = $(SDK_PATH_LIB)/kernel32.a + +all: $(PROGS) + +.phony: all + +implib: + +clean: + - $(RM) *.o *.exe *.sym + +.phony: implib clean + +install: $(PROGS:%=$(INSTALL_DIR)/bin/%) + +$(PROGS:%=$(INSTALL_DIR)/bin/%): $(INSTALL_DIR)/bin/%: % + $(CP) $* $(INSTALL_DIR)/bin/$* + +dist: $(PROGS:%=$(DIST_DIR)/apps/%) + +$(PROGS:%=$(DIST_DIR)/apps/%): $(DIST_DIR)/apps/%: % + $(CP) $* $(DIST_DIR)/apps/$* + +npserver.exe: $(SRV_OBJECTS) $(LIBS) + $(CC) $(SRV_OBJECTS) $(LIBS) -o npserver.exe + $(NM) --numeric-sort npserver.exe > npserver.sym + +npclient.exe: $(CLT_OBJECTS) $(LIBS) + $(CC) $(CLT_OBJECTS) $(LIBS) -o npclient.exe + $(NM) --numeric-sort npclient.exe > npclient.sym diff --git a/apps/tests/nptest/npclient.c b/apps/tests/nptest/npclient.c new file mode 100644 index 0000000..6d93f3a --- /dev/null +++ b/apps/tests/nptest/npclient.c @@ -0,0 +1,100 @@ +#include + +VOID MyErrExit(LPTSTR Message) +{ +// MessageBox(NULL, Message, NULL, MB_OK); + puts(Message); + ExitProcess(0); +} + +int main(int argc, char *argv[]) +{ + HANDLE hPipe; + LPVOID lpvMessage; + CHAR chBuf[512]; + BOOL fSuccess; + DWORD cbRead, cbWritten, dwMode; + LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe"; + +// Try to open a named pipe; wait for it, if necessary. + + while (1) + { + hPipe = CreateFile( + lpszPipename, // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // no security attributes + OPEN_EXISTING, // opens existing pipe + 0, // default attributes + NULL); // no template file + + // Break if the pipe handle is valid. + + if (hPipe != INVALID_HANDLE_VALUE) + break; + + // Exit if an error other than ERROR_PIPE_BUSY occurs. + + if (GetLastError() != ERROR_PIPE_BUSY) + MyErrExit("Could not open pipe"); + + // All pipe instances are busy, so wait for 20 seconds. + + if (! WaitNamedPipe(lpszPipename, 20000) ) + MyErrExit("Could not open pipe"); + } + +// The pipe connected; change to message-read mode. + + dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time + if (!fSuccess) + MyErrExit("SetNamedPipeHandleState"); + +// Send a message to the pipe server. + + lpvMessage = (argc > 1) ? argv[1] : "default message"; + + fSuccess = WriteFile( + hPipe, // pipe handle + lpvMessage, // message + strlen(lpvMessage) + 1, // message length + &cbWritten, // bytes written + NULL); // not overlapped + if (! fSuccess) + MyErrExit("WriteFile"); + + do + { + // Read from the pipe. + + fSuccess = ReadFile( + hPipe, // pipe handle + chBuf, // buffer to receive reply + 512, // size of buffer + &cbRead, // number of bytes read + NULL); // not overlapped + + if (! fSuccess && GetLastError() != ERROR_MORE_DATA) + break; + + // Reply from the pipe is written to STDOUT. + + if (! WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), + chBuf, cbRead, &cbWritten, NULL)) + { + break; + } + + } while (! fSuccess); // repeat loop if ERROR_MORE_DATA + + CloseHandle(hPipe); + + return 0; +} diff --git a/apps/tests/nptest/npserver.c b/apps/tests/nptest/npserver.c new file mode 100644 index 0000000..0969b42 --- /dev/null +++ b/apps/tests/nptest/npserver.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include + +#define BUFSIZE 1024 +#define PIPE_TIMEOUT 1000 + +VOID InstanceThread (LPVOID); + +VOID +GetAnswerToRequest(LPTSTR lpRequest, + LPTSTR lpReply, + LPDWORD lpcbReplyBytes) +{ +} + +VOID MyErrExit(LPTSTR Message) +{ +// MessageBox(NULL, Message, NULL, MB_OK); + puts(Message); + ExitProcess(0); +} + + + + +int xx = 0; + +int main(int argc, char *argv[]) +{ + BOOL fConnected; + DWORD dwThreadId; + HANDLE hPipe, hThread; + LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); + +// for (;;) +// { + hPipe = CreateNamedPipe(lpszPipename, + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | + PIPE_READMODE_MESSAGE | + PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + BUFSIZE, + BUFSIZE, + PIPE_TIMEOUT, + NULL); + if (hPipe == INVALID_HANDLE_VALUE) + { + printf("CreateNamedPipe() failed\n"); + return 0; + } + + fConnected = ConnectNamedPipe(hPipe, + NULL) ? TRUE : (GetLastError () == + ERROR_PIPE_CONNECTED); + if (fConnected) + { + printf("Pipe connected!\n"); + + DisconnectNamedPipe(hPipe); + +#if 0 + hThread = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE) InstanceThread, + (LPVOID) hPipe, + 0, + &dwThreadId); + if (hThread == NULL) + MyErrExit("CreateThread"); +#endif + } + else + { +// CloseHandle(hPipe); + } +// } + + CloseHandle(hPipe); + + return 0; +} + +VOID InstanceThread (LPVOID lpvParam) +{ + CHAR chRequest[BUFSIZE]; + CHAR chReply[BUFSIZE]; + DWORD cbBytesRead, cbReplyBytes, cbWritten; + BOOL fSuccess; + HANDLE hPipe; + + hPipe = (HANDLE)lpvParam; + while (1) + { + fSuccess = ReadFile(hPipe, + chRequest, + BUFSIZE, + &cbBytesRead, + NULL); + if (!fSuccess || cbBytesRead == 0) + break; + + GetAnswerToRequest(chRequest, chReply, &cbReplyBytes); + + fSuccess = WriteFile(hPipe, + chReply, + cbReplyBytes, + &cbWritten, + NULL); + if (!fSuccess || cbReplyBytes != cbWritten) + break; + } + + FlushFileBuffers(hPipe); + DisconnectNamedPipe(hPipe); + CloseHandle(hPipe); +} diff --git a/apps/tests/patblt/Penguin.bmp b/apps/tests/patblt/Penguin.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ec4e1daaf93a7a27636f529bba69807356f3aff6 GIT binary patch literal 106226 zcmb@vy|o@mwrz*!LQ6ED1P&Mg11J>)ijZIfY&bRm22g@R7yyX|K;;-E0X9IP19)rB zwRdEG2dAq0@;-ESR%B%S?zQ$$MCO<0|M)-uzyIrhyyD-R{QrN?|Nrm&|NqVZ|HrHU zE$3IS{-3$;#hiZq_?hFcA3u8h`uXFppFjWl`QytEjwCGbBl*9QLq3HmwpB>4 z$-&^K*(R8ycia1%zdD$0u$f=d4vl|Hf?6KTvFS9P{ER9E%uM=M(q3Bl8|`d)2eXrE z74Np>uOHu1w_Qx{x9-x&im_$VOUIK-j&wQ+x@(yf_+~9GlbPdHv7fdAl^7SxWES!n zM5lCh{1a$@{!E#f|8?sU&1uR;V8--CVu&&lDV)NCXaY$lEbvN7{K&C83Xnbm?HH_R z-EY507e%VjTFWpJ8}V{zQKAgb2IgsB_8>dN+Pe1M0dP*HgxDP6H=i+BF|#)9WvkQF zl!PK=E-=&`-rR>hy$_t=r&Jx)rjdy~dT#Gb96qH-i?z*SUp%7jXgoSC1AgUFcm}Y` z7^pfl#KEir7%F~_&|-2Ju4Sf?s+|BAfH|jFg=P6p(pzFC50s7)Ov#mgwQbJL3=FEE zYO(?+fsX3buWItY^xEb_?9C}=w$nQap z68s4g4Emfc++z349o(?wYRY!5@<^fRMuKCFVN%-9tsCSA?7Q^EMlcQ}1tWL}2`zZ+ zc&_d`+BR#Olsvr*z_cdbw11I+#@oJk)A*EM)O(4|{~;cNksdi9uA0gOlOw&7LuPQ| z%-Ae51!Pa#Yzv+#%rSMps@ctiIyo4a=bb(|Q!Cj2`UTQxJh^j>kLMC9U=M@3{9ss* z$1_|{fhKxRnJXVbEQfBwO0$$%Eu88|N{cF}GykUd403zi(`1f(X_@1G*>ujWYvOtJ zZPqdu_NP0I0sJ^EGYea0*d!Jn5%pFfQH&Nq(ZMex9N>Yi*k=IARH0kf2FWah&a1Ub zvgChFT`-~rC{?^F&!&5RCA1p(s(#L6@HGab)&o`QlmYi9ihY}QC_|2>PtHRD=1DOp zJmA#>U@)RcVyBM;gy)7mlJT;LQb7B$K(6~(?17d>gglAldyaUUw!v#8 zgHCF_LZ<_RmS4A>OOBg1Z|MiUf3Op@P%Ih8L;8iw%)FBy%^0L__Ez~K){(5JG`*RT z{-*-4IS09*!jZeV1?0D*jTFwFTiwEgXe&Nz_Ew;c&+xYT^bW4!K{dX3j{!h3apcj? zDNwxxDg?5Mt^m!6F`zs^TEK+yzcf0~ZeJP?gilj;iX|xFJU=%8!G67a^*)tN4E8v9 z41S8~hMz-zC~~yFon2IjEMx=unM1X(hN##VV6?&cKgcxY&+%0(7rX)Z+->3j7N}BQ z)SLLUmxl_cKy%6!=#t~B#QOU5_3IPG$ehIIA5Wj;R)_ud$I}cr130~dW#$V2&Ryw6 zfG8rFkYg<~Vu293i+q$4;H5P!1o$Z&1$$v>Q{XMY=(_FW>D#G^=1T~9KrMzuJ7OQh zuHGN~)cdIZAf0?>ayuM{fx=QJcc=Qdi87Kij6N0NFE(%n+60qCSmY}{P4uMADXulJ zN4_RL2a;;}h5gf~Z|`z^`26m}r>CdSPn@6Lefm6X_-rER7W3hdrQiHmdpm;|jg@5pn3ZuT)t#46BiXBb;q*4a3r?2lme0}SKv z=d|$d)7N)TpWi(_luvaJcq4mAe3>>aY=iHfLNB=z@}j9fOh~aN*1yTB*T8?}48`N`4T&Y`tQTj^FIp5P!I4%`&6HTLtU!R_U{OQ9t zj=hoGL~re0`4o_5! z>V7LtwW_{$-gT!=2r5iBGl3d_odZ-5VCP&BJV#ds1pC6@yGdh0126(r&=_;{vZ{&p zAN)k9x+|hpM4SSFx~MzaELa@O@*q*$r(c2p3kT}HM-a{N1FQbl#8cq^sg@sW|EXHe z@KpDAZ{r|j4<3OK0lok5A<@Q~x>~qmKl%U_szrGMxCvcSVU?9&`d*^wtFv;LJwKE&-| z(x+cvo*)6-QomLGAFto1sgwyt=;HO;ar5tzsLL<#up~KQq4`7rvHVY9kLnlo#r}SI zvjm!`GGl${Wwa6a(1Oej2u8VwABp)l>@NzOZ{|FN0N+;VtpJ(fyWovX4& zW@HB|#U9BH%MfugkF3GFdf)S11g6D43uO+YGZgLyXOI~EP9|D~slOF~CCR^MqJ;rI zHshe)jbz4l9kq4?e|S*ykTX0;!~hS(5*L#(gaHd}twJzP?@1>l{KUZmA*;#_`oj1G zD6TWVe9Btm(-{8)e6*Zn%B(xXo1V8+L{4$NRb+^x!SRu!+r!F~$g)pet{lnM3$ zTO)4?R(e{3N2XlFNl)d}pey!{rYfG2ur+522s!>~X6Pi(w1GTjI(ZjeqiQHOKt`-$ zJbqmU6!JkjkiVA=hY*k;c(@)*G?xKXQV=3xRA#e6 zweASM{rH7sVV{F=Oc~jbS9HaGgS!EH_?}5dGa}QNXw~@SYtW5A{1!c_8Y^DJ_2d(ydAn_>sbK2l@-lK;n!6H5iNZXE3hAB9Tse z>;!X*O$f`dJo)_er0)+6KF0uTv3o7#CiXdlE(9GlTWH7C&X$otmJJI~l~YV}7hE_B zx#?Q>uJO?I82_Mquy?m-#I&ui-x3)noKQ zp($Y`seKxZ!J;`UaAXd^sN7xS7qta`)qT_$z5n&oBk`Tq{zUlh^xeslwoVWLAL$a9 zJ2K>3d65HQM+qdsq+vRom;;4SaS4fU8vOq2tGC&SWBo1C)$Azry5VRcBL3lqt}uIP zv%OX9LD5n1=GNMLpVO~e{}s)~)EDn03Uf#Rp_yYUrf}PzxwMPS<<9AIdEej7hNJuj zel{Q3T^4&tp!Q3b*4^_V!J1Ws473A3uXF9;Bfi02fF|ZIa8y~d&5ZUkdY?n=-P0ZH zNvDtzK$ie(?bFa5du1vsBcL=|Nnt;QcE+s%NX|&D!dmRn30-MdP_gQS@#YvSp~Mk7 z5jZ91vM^ldV&684%CL|TjvhA$)K{&UAZcC~Fx@kTq4_hZ!|5jA&>W}7Yf^@*DbOKJ zNp~hvCYPA~cX9kVFaYm`KYPrdi~tt<;|q=!9TF5j@_kEZ3yko&dsP3y)QhPzk_s63 zV2^EA<30b1`~Q`HKSTTmeXan3KM4mywV0F5v&$(cG-u%&T4O^y3n^d1ND1Anf!c2U+`@Pc+ zDFwtBbx+PrbLQ1s$<*2x`|eH}#3kC#qQCZ^ou5y6!lV-!?cccgW;i1~q>6HP;u(Cz zevENRP@S%Mr*Lh);#&Kk$tM3NHb3D1^^3h7@z(uAjk^C>g52*V6)KTbZudDC`*y4j z&B(Cxp@k9OPyqo&vJr%mn#)C93~Gl5=H#TzoC^}Dh}K|cdchM{BDlqJ6BOv-__sWn z+s=6U`h{lR&a40<^eNoQ(qO0Hbnx8gl7!QY0gI`J0nH)q%Vk%62T85GnjAze-#S%i*1p5Dts&V_Rl*ryDy6ybdC9{7`B zf>W{MY$MF8hr*?Is;BGB!YOYp!UB645(8(B6-xn==u3jdUQ3WAV%CRo{1f&|0)4^Q z{{?=0Kd3Lv*z=Vn?`NI?pTPr%rvCX^8^GL61bhCW+>u)TVe|dxsxMO|%RABj)DdPZ zMCUoEBQj=wx|gIv+Xz7NUZP1!twLXs9tEnsMckQN+P@B)?d1ihz@+3s7sxXa_5NU= zp_=Y?jaULFiA=}=LsK!H9%*pPq@+}KNIN^nP&<+Q5*__s?2}W*lK?i#;NZd!%|4f) zn^=$a9!C;SU-F+%PYL}Ve1B?TDQ8hF1MDcqz$N}sxg*}p>y8D}EENp#1RnUsKJpsu z3$l1e?;(hEC@sLAO!#q_QSsf*nJ3_7dOahBy>v_+7SiDo;d;Krt>{}lncS_=TkK2R zlbYSZ)K%qH)t!O81fe=w$frPhNm$dt6zMc;-9&%gA%FGsbU%;V$L`{YLs$tVweT@L(4p{iHD{zbd z!CoHl2!|)R*Z{3UB;T%KfFuwL@fL+blk=E54FG$(IDkcW0L~>Uo-1TJ2O%LB$0>+h zibZ^&nDRM`S&k&)Y_BA5@;Lf zV#Z_sHrQH9!8YlaF604KSn&fSIk!eEW4=9l3tAUcC(GR)0cp&@gaW-B|1E^o{yY?T z`{CW&x9{G+XT`q}K#YGvzitQ)xEUEtFNp|qg@L+x@unVJu@lv?a5@1aa%a%+A=1%;Tid_UrlfGe7zi;^A4HQIA=q2E-cSj=|6!76#2QVwi>?{YqPNS9(?VBCrT#S}}$7EXb!f@TBl?CI+J z+hES{c*aTHp%k{X6Pd0%D$GN0O|gV~nYGPA8Xy6cCU%XN9Bv7`=j`-7J-vSW{`K3p zo|6Fh*D(g!`-{!5U8$RQ3=AWg6$n#6_0LLs@`LoP0Oc*_lr7IY+Erf=<=+K)E`n?S zjo#m|CqI_A|BwY%0ff+gIw)abfZAUkAiI<~V2luxNedPC$QtEK4rXRaD_}dFGV+>f&IJ{fG+hYU=2}+$>3x{DlMG;VGN=DB3O~b=_w|7JLu6syUfaCq?3x z1K#fBRCl!masN^JcgA{2lgR5T@1I`3dHe1UjwDI~&hOvP%U(fum40Uj*inOOLeEOz z1awTH;u>&4nV_u-pIDCzvgXEvx~HbVd#^y}%+)<-TtLW?riSK9f&3>%F}8lZY?s9^XF+V!)*H z#z&0kN~}hXVIYU|uW3RtRTO)PT~=8|ozRVOk90wRBC~Pr{616 zuITLBU=0AZ)T(1$oSm(~gYssu@s=1f-y{HD`#-ARIA9{UF7xXCd8LO}fZXlL_Wn7t z&;R}V8r=tJ|2Hqz=KnXF+3IW>56p)FBx2vlhy*gdK~l63VkPU{U)j<*#T0jn z75*?rsD>yh#t|Ftv#287rlwOEW{>UkjH=D9#?!uOYE7FB2{XZg{A$OXP8ps}(3b=} z(D+?qF#sgg?^^$aglzP>%bN|pyx+yqSNwR&_v8D@_i)~_5-%Gsy1pg!?fjJrjw11FihbQ<$f=@*0|I0w1 zhW-wFwC2CuSDbF=d_O-EM0L*ST7V;2k(LLOM#^PIGz>^Yj*=c#_vDWrUzxEDZZwJg zjTX~IL{DF#OS`_Er1o4Xj$$H5+u(5eaX2Akr_*#>thUtd67j_pFTEZ7WnN7A}nK49spZ>b4yQgI46 zDNM-p%j`NfC%BJxg#2#pa~Ff}!TaM4@=<-adb;rQ6)pn3vHSynTs~(1fbmi={u?O2 zapj@J4f}`u=NJFjiUYzzMnFh`$(%VWWx)oXJ(_M6AyLYKVNLENtcWh|f!sGub<+>p zd?=y;U<+zNf;|~ws(__+&v=MNH6a&KIwJ-qaZ}zkr$aJRDoCR;Ccd#on`vel({+zOH_3K9)ZL|F`GBc>Oy%x12+lsd{exTkOy7{fnJmR;Xe% zzTG8F;4j!H4WYhrM<`?Su>|5F@Z#a!3*CBsa1s*qtcMiQ4BXWE+&zx~>c54#Ix1#% z2Lm_+X%c95vCqJ`JMgppw_`|o%Q&5#AS2ndL{tYNjY|iH2g88sIxyn`aP~a4%O0Qh zpXEMLUhvNQJjQx@{g{VAZUGG)AOGe0dDdfr>#FZ+o@;6zUYy*AL|gu?i()@|kJ2CD zYx+=~NbN{`;2&~WhP#tczPTK*gGa5m)gx%++on!_E>HQrby*Sb9{g%2h7AWc6XF_l z8EuPAM-HjLw;g8Gk@S``IyTIS^nH!SePVAMF#f*qkL70zi0Du3v+X1HID6jZsu>{h z`SZ=}-(mT8cpubml^*o|kyE$kZpmBSTQd65h^E>g>z4-@I&>m0IFPU4BH5PFO}0P* zTSZLC0Y3Tb2rjg4=mw!X6@aShOF}}h0r1!w3xUh(bW{$qI(@Sx8IP@%0Xu$*fqf}> z1{3%>W{#P%S{^k}zXy2sbgTW%Z@^#FyX4aV_!B-};`WzZfj>5%psyhtvaiekx7gfZ zdQ5`-KPviv)bwB9GYyYExjEPu|<; zt8TuM3idrJ7v{M+=QX$70&m1R-V~xJ(9I7*!k}6=XrJ&Z@Q8;PTkHZ-%)n-`$1rSq zGMi&GkXt=UIFK&(;|pdY)51mo87HHfV|kFvw7K~S>+)0ZKFvZg#=O_Zi@kRK5JIo7 z<%bh|55~^~iG0m|-sFE5vwx}nh0tT_5w8c(uZv*6yYw%_2v<3po(4B_|C@Y&TiT6G zF$UKPku$&#_Nx;hcMgPALFc?t6#%Rdca=XNf#2SBDL-qulMjlEU%(jHvL|mxZFVxZ z*a4DJg$;cy=BPU6Q=p?wU$n5pNam@?t)cbNfie40=n#SjIm)EQ|F*Mhpf_9`zFGTU?>t;wIQ|>GKebN6#%?~s8$W+BKEXx=CvniN2!KCwv_Q*D z$st7HzZH1EUf3e;M~P!0x|4I=8sNLZ2RwR;F$0HE+Ya&C=_u*L8^%faHgu%?a&Z$( zXVX(r8>4NT@@b*GuTLDauYW`(8u!5o3Nz?W zd%KRHY7KsqlZ5+v)S_8{1VRuJ$ef#RM;S@pD4#Md+;O&WD|Sd!q!F+`O>wL2yjWtJ z5V}YY14Me#0UpO+$T=JBV;&6dqWTT@4g+Fk{{yrC0`y%YoRz{qWB+eZpXQ_YF-jNq zH{}-oOO-)-fd~GE2oYK2sQwu)6(QpAyQ&3#5jET^gu(#!@kd>Y4@jvP>9oxZa`6Dp zMdbjtT?=8Obo;$=VlYmFh1>x%HD`Lrlo>hTbT_?p`Zv6JrG-l@zmWU0!@wNueRq3E zU<}B200o|C9|ByD^$vb7Abe1{Iq{pRJ~hsMeo_ASL4-9a%>O6Q`~EYpom>E`Ub#fi z3btp(sugW!^6#1n;pTga|+-0~T+ff)*e|cZVNW z0T`KM3RsNS_06#hCUqdU7=?R_mfI#dEtUxm%_?-z(%U${ zHXpse;d;P)F>mh{;Jxy{+1q)zzAj$Oe}ol_2u<7-4O?nZ-V`IQ*zs z=RDE`p+W0;j!_{RR_v?XTiEbW2f-@^^jL&WLO7+u-s*D00&8+)i5yauy`+G>G{4O< zwk=GK>D}`GAeHKh;z5-P!~GkDs1lKS~IA|It2w zQGRaoZG{J77YRt;FS#=|#B8xw??-7OoobJXTe_-0NCfhhKLv6bsU?5UNu;oXt~87E z(bx21&fq#i*JkYFJM>-)M4JQ20CQB+>UHzR1h%8yS~v+8cG%qQz$S-FhT$=kBHg_# z@D9KkDsOO*)~?*v_ZkLX5T9 zTD@>TZiyilLS&Q`?K<-6^mPjXDbOVcNQVTzk2dcA+^RI^Tn1pnCyqnUJaFd~eGI_r zA3?x?VR;#F5W*n)a##_C9Cz%u*|Xrx7+SI|OfB2&jH>hw6&GN|vH65`b?u&g!dVBe z&ClF%_M#5_d_pF_(lyl2CD5bw-Q3jx;Pt=!{QvbD&z&C|=O?e(T8w*%V*Pv0jRP2^ z{EF-w53M2fG2`Jr(Dp2%C`T7gNZ(r~WPlpKVl5{q-{S~3Z&WU*wZrx6DHe=j#sRp_ z-T_<|dpo7sl-%w}B!}~1QZFZe#?x8UkWAsFU|ZgH0Nw_p@hZK6t^*``F&-a7aAQwIK^-g9jLf&IGt$vK1=%g+KYukZEkP2T44 z$zI4n;P>0Z+($^N$E*_ro<2T({D_#Co+xI{ooXj92>`gdUY3mU z2f2$MWy9VwnyX<4gMy@TgZljFBKc}Ov0f5zMb+n*QvnHsagKxK=HxEg@40n>Hbb>Q z=3-M682gkqDd0H&VnxdMIZ~yOW2c<6?J(=E=yEymCqa-8#+-YYIm9ouU~nGoDHeYjXAr6T^?k5$M+|P zy9&3mQ`I1Zl3MxZGNM%IsX}=UPz2gJ$SmYW0BBwd)C>$}WDYh~ES7C#h&XK?ij1Ku z#tdnCPonlIZH5Y&OKCy=jGRfyZ>QtDoEq3Wk>rn9o&ldre!+t=Xv9~4@77*oso-tI z$L=2K9ACdKQUVvy+iiO|w0Y0y3aMz_rTgEU5SkA>hXZPpZj-;t7Q^37H zIx3c<@u16*0%&~BCU%awtUITpLxK)FIVFcY$gF`}fe3sw-cQ3t>CX<2*t@=8V=w{W zK|S$Z(}sS5{~x#Z{tm2#u(tf)+x#tm`|qvkzrKIxcS8-)5B8mKG@b;qlNJbNcp2=)OV#z1wCFptMS z6r1T}JYIG%K%PT%C(#@-z2zly@t~0a?=d{cLN1a~IBWJHMD6^9dx-(_4v#LMNFN^` z>}R2$$Um$9yJ}wG+^}gf=Ud+082p#8Kh4;fr@uab&2NZ+HdC#znBh(}>Ehj6cSKPp zfEf+*kC&obIgsy&TZKy*EZZG>(sB6(ULey{CW#H;K*c$xi=|E>w-;M(u@c3u0oB4C z_6#ON%0yBi8qC0QK&EY{InJ~rw{T^G#uK;ivpa2oJG))(hXmdV6$tgm=4<(rj*sV~ zEdJBl`)G%Ud-tuq8@3k-ntJJ0^2~mY{hb%j+IjI-0zDS@oo4|)=~5dYOABPW0!mIL zcnJ{+UQU#JMVtg-{9rGf=7TGV+$z#o0y9A!49bti5<*yjTide57D9WRW*ukIjhjD1 zEibv;79h7lz63SjyQ>M2Mie0C9k)2|ZVwN*br1Id{+*wYECamUUuorsdC{>a-`$SD zKR#W0UwjwQXQ=(d<#X(Pi@W=RXRUt{zqOO6IDfu>onWN?4D4&?H&NCj5yU+rD;q|= z1n;_gBzWKfjN(@~SLo%0hyuSFua*P66u~LjOR9wFqhH2AZxSJc_$!Bk-L`z4OoZ{FnKgAAI1 z*n@c67x1`el@s@z$MkR5Ki=-uP2;nW`?fy~O!_N77|sJ+jA3|;_J zh-`8gAZpEB02n+-BYG}tsK-Z$pAU0^6PPC_br;|a0|<#|M4ihNj@PjLqPv4>CS7-s zj?;dZBJR$LHxo=Eg+b8-Q{K350Ul;>3$PK$B^=l=PxJ8l!f#|p5P;dIFlYXl*I=Jt zp$M~`wTqRi^~r`GQs&r;s#T$&MlL@y5*(Be}sM8|Lc4HL{xqx{08cMO!u)u z@A=huE;7jhyVxJ?_fnVc*bD~J!ivit=cTC^`;^zh18||0E3^YG zd~YXa0EQt20fSgzHt50(tJ6jN&W>lmlM|+yW)iX_hys5PnZaGBc4bPDmSjKQVup3a z*dJ;UNkjdbGE~H43O^w{OQ+V-n^YpMSPr3OF-}(cM^cH@?zRmrU=UfB36Nd z!RW4mI)pGE)E7=jGw@gocmib6%~{)Efyv}n{Fmp2)+s&1en&;!vcUu+)crHsV-FsX z&b$~E27d~7`s8y^y%e8(Rlf%RVL4aTSJ$!g>U|639Gf3c|F1W%{}ssx`@+w+IoR+? z{QvPD^gTek7k~TT)%&#u0lSO8%VuN&{qbqP2Z5r`r$LekB{Q=7;{L}vGepqW6wwB) zBEnTzfLalcV+Q8nRG+=rLxN&}=`KiA++tQqgMbA5B?rn4>M$d-Zh|WCAZ7OTJ+awl zTi2$BZS8I#v{-T&|7<^q_kj94Iqo_zs;_c4zk4_VTkB|?U(4_78|LfpV+`2L$(NX7 z?K%E<^{+RtAi*D)+Z=qE!9T;}yE6;&V!79U_us|-@9zKn$)2L>p6>Y?OdyZy`+<ta^8tSl3Jj_{3_xpv76{FU3goNw z8FE|TlBVF3#0B_rm%6k-M>%Xc)mJZXx7t2s=(nm&N3ENRwjg*l-H_WhQSO#3pJ;sS z9}XgAxE$<>gwX7X_z>5(ceAwfDLw|@KgW?ows?bmbp4giUIrlZ1bx8*1{nPX{uqFK zjq`V_PftP*43cjS~8-7)Fz0@02z=T;AJZ86Ts2SsBf9emD65@wiC^?6hK&7ZGh z^8>kOum=d>#}Yt=asP1ve2?`71}MOR{fYoCf6x8Hj>zukk3<;-9*q44P*9g~=?~S9 zzt7#q%F+(OpQ#BOp_0zSu#1O{=%O! zI{sPR%_V;=3V&Y)@LY#CINtrK&BxjU|0tpGLx?}#CZ}sZ+&?RT{$h90ykS}job!X; z;~@PP%ZaH^Kmo1P?^Sw8V3)}k`>gLjI)|mXq#n%%=18p)#M+~3o~Hnxi2}1oRux1G zN8;2?Isj<5vG9}`;7tgyJXpXoa?tf`*8ql{=s&P8uI&_NJZZXansOVwNSb}*Q zr!!(A!ffwAe&vv+k>;TErf=|{m7daz#`~@gHvi$k-~TH%{||r%dlfHm;CYkA3=seS z`Ci})|8Fn$tN=z1{^tSvb0giO^t$;2|JoUC0PttI8N-lpFQ0#$Al9k&^D;orB|=1w z-crzHj#wjHZi)RkW`t!XvZGk?y;ZdQXkvA`&8EzlaST3bB0E@LAZcMDJ_Eq2{xHC< z+g--Mz*KHV%dx{tVrFqZrtWk)!A_x^CI{{^i&lwB2t10OG$!4gV*`TpZu+vs&!Os< z0mS)FukrU_9}>9CQ~efrRS^=f!5Y=q_eT^5&A&^$ggv`;*qJf-rP%Pm55N`pzQ$SqyO!T=pPGGK;IZXp!2R-u{SpPG zw}ZuA9}mj_KDT0a2r@f}d=D;rJIo=|bB38JvMB47V?>tA%A&V87ycWf+5l8-ZV9I! zy&UaFr>9mBO(q&Pnkv94kl6}t5N$1>9V(O}78o`pC*$lnEmOeWTavzP#4b)kqMp|PQL)mI2{Ysz+paOHtHPQ*^r;5FY8rTIgMlwAEbCvb)YSoJRF zh7;rj=30BOuihue=Xd~5gipA~{_Y?Gpi&U-tUzJq-e=kkU9tcVE^hBa4h!PW`G!6dJAKmCq1})4u8OP z;JzpLJ>J8=ycIym;DJd|(X}o5mC<;*=fK(U@o&bR$#ZDjBAS`GnZ2xZGJhme_(|M8 zpc|2yk9 zGhov8dl)>bZzk+vJZT{k=ozrt?#$WGXGcVfFw{?SCXHySIxd!0#1vSZl)k7O5hGTVZ-PD&<`jvZtxl(> zspKpkqr0*8+oLEhTFs<8bEe1w(}^>EbRdTk0BLP|R3*kg z=fYe?$0XF{Prkpu&tLX_s;!OKa~OLmc`ZK>kRRY{o^#7$1pGvNUGm+RcBAXOqrEI> z7Ci|kQT!CII9-~+LqHebnO02Y_o;Ya-ne{X@v zsJ>?Zh3CAW{-F1{=H1JZDA$t(KIEfWsvFnylo$IwMa zQFL`(@hKD#y^OQ+iYNi2*jLcaU%Sn3q0x0QE(Vrgwceco!4Q~1t9aO>PQjg@!F6po z?71pt7}+BlAWwphSW^t@mM`$aTuVkHQ?Z;-^$CL_ma6q6A~8|FMR^q9h|khI=_*(SB9k^I(5$!e8IM6DSJyU_YEP z!t8#ssJGXYRPW!jdSQARw_$yyS#!7f5lwx;ku~D0o?R#^zEMiBN1;*2C3{LOVczmR>Xb>OVb1>RD_6=pBW7gfIoAmLH78# zL?Cy__4_RKY28E8OZir`Bl!2yM*-EqM3dV+W5j zT4=A{Q+TR$Mx*^=ui3{6$^a4s{6u_{dFegAznP5#V)pqhCj7{%TR7rp@xScuVQ~wP zrv6+u(QUpz_}xT*(-W_MKFA67izgZReXh09t2>i5QSkO*H5Y5u}?7Q z?{M?RX5NAyAOwC;KX|L|{{o<*6UgEY5+CqjcT_(fdG~kK`<|-zLj>Ue`W+*q&42gi zLGOKz1RK&vu!n;jTxRbH2ajl=_8?s?;fyAs1b|JVB3?n?%NH|?QBtsJP!b5UBxr+^ zDYP_VgC)Vi8$7P}aNvPYgo8b+J8VYzl)AV0Kbbx3h?d2hkw`U-O{clWKzkMrWwJdc z%5&nzK)?^=`@8F;b2Q*L{@3#Ji6s&e0`_Fb1#NU+k5zuPpSZ8W4+?1Ja)Mo%C}il8 zzqHs@{?musZ?-S+pWFQWu{GWT3-<2W8BplaZ%7}dw?Cc2pC54cGecki>4zh-yX7On z2zNwjBKp@$#4U=T^6W6bnG}A!oSd84n35^B+q$XZ@Aq)$54})^Lzo5rG~Qb{7f5^! z(y{F&lchU;oZEEH@!u88ytq-r{^RKr>dxJq?*~Zpjvg;)(O2ppF~?SSd${imysDs)I_=x?^uTC9B_@ z3#9693mIy1c+^*sKoZi~ahD;d=5h015^I7K2GhD6mumNjN5OxDzd(0Xy+xq-|J1eg{_N(~kJ6oH< z$8)kxi_z#_0ni?Mk~Ce)!4qY~!uYeS0?#~|Au=t}UEoDbRR}Tx>0sGJF))AOp-O?I z?qFOt*tnVADxzt2kPvJjZ1CR(%YdjmO{w>7c2IxB-nz6PT?Y8!K?b}?UoA9%ok?9Y zts2a$%mX}viimhaOV!W0NAlzQ*(B8fjA2MlfJEk(il4=v8c*~W&0M872ul_Iv@W53 zwsmiDzW&`4v0h2hb66t4U_2(>AafuG_*j?{FabY2NS84cOaq(Gtdi#G&gjQ7AaV@A z2V<3~l3n!*Dyv?LtI`jmMHg4CxbH9zJPYumMHNV97uftXl1DhWd12mj8+%o~ zT}?vAU`ZBrT@c=8bfyLa%Ff(nu_yKt!bKfIh!+5RjeIf}?_`3#K|mhEXanZ;4g7B- ze9quqReZO*Jwnsyn=?P7NSv?g|EK=`^&eg13IB880b3(O7CADjR5bk=oi-}&$JST9+5cLRHV+58hjmTSO& z2$-QTnsk$~`WZ2ShvRJUDTtN3g1GRm_y7;j3Xla=ISwjr z11(IK1gL(rvHo6{e_q}y1q|ww9KDwjzRmLOdsdS!5Q+7OF7S~Ofl>7vf6sFN zx}1-0Xb&hBh3xMk!Jbz+jQNG8W*^N&Edv=Fx&(To_b)p8=z-Xe+QW(nrH^q%UHAuY z+70g@!~q`F*X!>Z?>xeh>=n?F_@V{UYJ4SF;44bRm-2Y%LM6u20>Syp_c!b=2ArIze)_@yT)=l21L4(I2W&6%k*(xhF@MXST9P2MEA}z(PF(Dl0o>KL z;}@FgG7lzDmKFzfF@ z8obk`2iti=h{Oc-Jz-gXf=|d=2cP)_p*auU>QK_$id)I00!=Y6?%fq}FXt>m2YaX~ zLde(hz_!QGg)XGXcDj90vST1;@9GX@TekmFz!0yjbt1Gj1E9JC9#7AuGyR&E^}Gc+ zrWPfSD3S>F(QFcT;7!+Lc8OH&N8NGxFn}*G;PUxZ9-2KXJ%umo?y=_bz!aNrpts-b z;M>bD{JYzH^*(#L{2~ViNuotP*r$)aGjw~L0|Oqg@5)|5jG!a#bF5s<0ldfp0Z~9K zFGNwtOZ&$$S36r+yPb-QJ>`?8wOdo9y=*V{yTgEKQ=8YqH?SFA*NWSbJ%a1b@#y_z zrVA$}-klm}G`q)Pzyx~D*J*au=fZF7Kf8Nu_<#7wBmA0r&HiYkkQa5e6x$pg@am3% z9!vb^*jM*|duQwR9IyIKTOKEo%b^8*6nlS~qv{t+=Z^>mhMVA4WYwpJ%EfOKr9>%^ z!wKNgCbL?*2vJ;*g(wN|+;-P?+5((de=%(iMez5wNz1hm7RX@I4(ARyGfE>~HV4-B z?$sTED)CCEAH0RR^uCr`rPd7icG1RZ29pKS;!R|Si z0EAWUn^b3w7fsF=Z_nGh4>tdHQM4Qo@efoDhFVF)?5ish8q9*ZlJ3N!42y6S@qVBXHlA5h|MXc43v(kH=I4_v|i zYwGJ7U;tlK!{*1|gKKR*U?&V8`0)j(I|d+TnAO>SpCL>9Pfss>oM+?w``Ulr&%ePh z322=tug1UK*i*XnCwUvoFforZVBl9eND9f`3REwS0n%{qS_`k(^ z{umDzuJxeZ3HmVg&`OunE*VYM8zE!9z*8c_Wo_Eu0AGo$`Bgd)C6ZFCi_NNgfe&UN zl%rteGCCTGn~#*6@SG>M)Jn-lZC06_!LoqC!qY4T+J0(Tky~577`IG^y5_35(hlR{ z7^HjY)R>?oI4&TUNC~~~GOuCX27_$tihbYS@ljs(+9PMT^j8&yLnTZO8c4d!a#cSY zZZ7k(yAyH!hW&5;p6_Jl1+jYckf_apI>)8@u|EQz917=W*qsjy=u~eqs#r%qDkfzy z%AJyvIapd!@W@{PS_V8k(n1qdudCi$tz}671_oZSngMuOoM>SR+giJzz^!qd&gyXs z&^1TGKwiw6E}TW@)$%DL_B94c$J(E@z8XS=Bm-R0eMW!C?-sAOP7&N)aFN&U>_tlpgU3)enUSn zL&`#X^$5TkfAFx!EpQ;;MBC5w3vGYCa~n@7;>($FQtiko*ze|S*F)T4NxBZqd_0+a zp6L~Ph9v3-du|cuAK;trJ3QIeRqwI+G4DLZA@o}wNC-#})bqv;F1sIM$$C%Cl#D=!IQNp9Gun_3w9)8%_E_P(o`nH1VgwTVHLXvmn^C@HrFjEZkB%}g-_ zO+}AMq)eB5qh45ej)Q&gb`@uX)#<^$Zv>?-$a!x2ZH;sr#FpgM?D^GBDaF~N%&>ZB z!J@wfLWQy+?KFHL!7R$8s`vx&m_VI&Hh_H_`z7~ zt^~D?zuMCYD>7z|j0AY{7i=z@4;~{ya*_{D&78BNJrQ4syI`EUrwTb^&%px*2p9$Q z9p|pDUB(nqD-QNzN%h5*M#$9gn0D~N?_!ulBqxc^4!a26$ssYZ-bQ&~&%^uV$MVAi z*L!gR`K??b&l$bvnO?LX6&^z$giQ*UVdUq~Y7P$o1UJeg5uoe0uhxo)y$E>GXz1IvZ zHoJ#XN4M~6KJ2hvS-TmDGzBd2Wn?JDmsy;r#8bAwq4$aQV`PGTzOH$IN8QCf7B8Yna9g}%Dv^k{a;E%< zRb?{W9M7Xn$l4Z?P~sqDCc~Br!hDb9tBzs`oW+K-$Eb4K!Qijm7JGu$Uk~?O}j6AZ*C) zF+ax?d*0sZF~pAuZaKxivbbR%NR%dQSR{~awNnLBl!$oM9qChe6www&;s)x~Y3mN; zn?B${i^4pd(4K&$UAN^cy@=K}ba+IFS9u!@IWo0tc1wcFr}?$~Y~a9#;H|D#^>c~Y zCnq+a!#|i67p^vK!M8M7=81isI%ko# z1D@rC3hfNDLtyC=f1|vBotJj>YIm4N>5myuC=1>NaAc=St?0P~ayS&&3K+f_bZfTX@OmuZT7%<%L(vU4xC{7lKrTLoS0$Auv2RiC1@KT_SDU1sF@~ME(2yw|BHY> zFn?}-W22mR8>e8y1FGu_>JflHdXF(j=7e&I^^!J${P(D-_J^2R6Z&@-_*-iT>GyxX z@9jh!*?IoJE>a^#O?rE!V~->*n}gm5`=|V=Ea#Re?0)Ezbqx$#vcFqqo#2&jh|4zac#ZmD|)W^is(339>qVcc{T;Q7%7zzm>i2)Q5ze?XTmcN%J5Vcydux)wDlrhth zx*i^Q39-gvhcs84GhhO*q2P3+$~zu^dd(A8d5KW{w$%K#H-8d)9JC?~~XE zIl>PEB!MoUA7$3nV(qV^41fw`;;jFecQt)==jm_$!bbG|(GYN%4_5s&+HVKl(auZ!X)H@X#xn5>$%znUFzv13I$^!y+b&889DE#6AD5LkjtC^>NsQ!ni@4KJ>2sJi;0-WA3&|_Cf ze_y;`XD8oPelNwI*K=hbFO$$EkMO_y6knUqJQW!XSTiv2R8vQ$6}sknL=0v`aA^Mm z26bkCx0-sH+}zq?gYlB-p@lTwHk&8|=%R6hHf9E}={9>B=dPor9a>xCvD`8 z57G>tzRIDTr=7ISEx_h((s*}^C0(#{PG;JSe12RHa&oEm2X7B8d}a70Z}j#uXT5%u zm@gkR;;ZWOI3ETWlbL8515oVQ;Ysy+^V=Ex2m4X|u>rq$BRKrRfDlU90T#xk1-$dg zy?T$$kp%JggL<_*lPvJL^Z@M4znK+^W%g}|72gyqgq)F}fZ2VC6y~#hFS@iKU(2>qtvpCR*gK>a^UNC0wNI(QrPdz2 zn?Ub_kQyJPlgZoMgm}r<@n>T{p*|Srl}RE#NHD+;Ko<|N$5))s@9~~#d@sl5XY&1r z6vBY~5)&$)kjqX1XSKSB6(@d2z#S z-KVDn#e?qSf9`tkoyLuTw_&iM`I+PaFJT@LzsGJ7DiO)?mi4qp$9$(0*GH%U`h3^071UE`P^`(4!?O z^ENw({m5d?+QQ!ze^Jjl^PEE}AfSkEaaB!oS;>yUr~JKG3(r|RXd%?e(tjcG7j$@8 zFm4y1JKAr8MV&~u_u0;a1X<~b?&%2X>?&Yxl?QZ(LxGF!eFt#Ez5^Ho;8Xm5Qjy3G zX~bT}=JPx(M=e2skDd2ZIjjYET{C|~0kPjg{T2S@^~FA$`B~j%V~2i zTq^OZ-AH_C5m^U-!rXTSc%zb)x2B~O2{4Ny7F!ihJJuQ-aC)b}c1JCFV@^rqINNN; zYG_4ge0`(-CfJYmr~CAz z_ZoxWC=V$d8?cVQnTlg&G|;L&2laIgLx@PTUZ6Ig^pSpyga{QpO9q2{(|&Y)?xxHZ z6J1q&NE0J}8HO3pI-uTacNz@XFqdKv^K6+OVPt97-`_XRm+|rF4d_Nn$s`9w*9Pzr zp8Ou8!M_j3WBk#^d{5Ucyt;WH7yh&N8kg^SJ75KSHg@ujHNL4Ts*k7JcQx1GTOeQA zd-sONIfYz|)4}`z*udV!2H~DYCIoEZyd_eTwM^H0MJSoxI)d^5DI87l=w9t)+NeAr^TLV!oc1|9pT30NCmM^xcA17Fckhm+j$o6 zA;hi%fd2rDe)mY`D&OP;-Cy+%<0C58J<7q31HljA zz13Q>!660pLlI=w%(P5{xh(dylVX?wCs^CwM_hTV1si7bZr62DaSXc~qdD{7j>9)} zi2%r{7ao5f&32_Xde3j@0>LrQ^MSQ23-f~Z?a$^G=b^wo)*Aw#2fu#ieUB{LqW5BN z)5ZRZ?T;Cd4bl4$6I0`>CV~Ip9mq>?6qEytmqdXl!4YApvbhDQs8lpedw@pfkR005 zLA_--Q%vlsRW~tZ=!F3k`(`#hQ66f6ilfKsdR5le#IgW$wpb!Q{#ibm695)?UiZTi zq$K@17zdy<%Jq&1RmPHI7oEQLlEpnFFu0=tY|t0@1%~~dWHCnXJ=}(=k9IfqUB0fC z9X&s=7K3q~-?)pjk8iN~ornKf=Kjd@`z|GGNsi@DPu21eqBh5zWTN-HM;zcY;>CF2 z?i5<~xRL;L0hp5hMW!_sV>6}}Y?vvvhxE`L_VeyGR4~Y|#)GuGJz@|1V*l>X{-rb}A1ns@VBvw$?fVwG=_-AK z{O7;Gb)I{=)_C{%=Pr+NvH4?I*7DO+;4k*5yVzTdTUq9%Kl~F@T8v4+^qW19_#hV) z6-3f=s9s2o{KothVlb=2o?4^*mZT|rq`@IjY90L}O?mLhOwX$<=y6q6TnBzRVfBUF zGK)RJYe`b-40g3mwF`zi*fWMogR$}Uj^>@P&io)9aiR3t$TK~we2st7cztYY^{pz0 zDlYIz)ZjOfGl3ovek^}>YlMzkU3Cv zut(z~E~$XaAAirw`3a-|ySDZOVGr;ZFWfYb?}9zA>^=OYG^e)16#JVjPX4biAM!%D zO{cBy8wkJH_uY+nng{GP3G;Up+`-LX!`9U;>bt}92t4pdQbj9?y(BZ~!lva{?@|5A zv0#I@Rfq&9(OTLGs#8Tp48yO2VW>KET5U`VB@4?UT zE<>nRfbkgoI{SF^9AUsN_Snql<2(ckY_X$<0FTiie&;|IjtMfiTzDL5Y=pL{q z#0Gw>^6NK$8s%y2pPv5mHNBnd{l54=|!W=egYVJ+~75@|R|WTol3nehIoqlqLkYEGgI!C8m{%+myZ*OVGl)?S=4~ zEZBQ6^O48^zgn9cQ~rj17IF}xm280qs`@ep>PS`xma%ns#{B9xiUI1JW8|as*}uy{ zpeF+enUUc)BmBfzSlQ!wukYvy5b)!p^P|{#c89gUW1msY03E5Ly}qeBc}k#Zp5$i9 z-j}t-RR+ZDjJ21BN%IVM(%Jh96Z=y5fOL)*>UwcRlYhB&%tKnJRcMu)4XFL69rgyw9>axY zOn_$qkTQlx;4^(-zTV1hNF@Ah+GE=n^-_V@NTpxJtJxnr&tJmjW!lj_JVKC4Sm1kF zIiFWFXKI~b=V|z2-V^%+gL5vHrFqk_ zeg~}!vxEAP9ZFwxFXW zfXgOg`2)O@ScyQl;i53dH@txK_&@zsBF*Fa7WA^v%4k85PGaQS( zWDiI<`=pyM*iTi9K#L%v9|!nbv6P%*7ql>dI6%dkTIGQo!0QHc6@Q<$+}5Sn^hCJP zz#i&(K*{8X5NdqOyvf%Yd1*7K0CuVEt`^pQ^|HTJ$R))tK^$v;qk>f=!KL>^c{#Fb zhcROql>61fRMB(;t@c@r2We(0#w2e4%7C8DuCP+}s@SxxjW?;CcY;I%8UPreatBWI z7=q2gpa~tR>2mQUPI}AQwQyn2Ie*>(lyPG)^kR>PKJxjY_pIGl>yw#b{4E|j2 zyl(q?=N^pC&@%|$72%Bx*La%xYClmP*z**5a%%0h6Sw!b4yY=+FssM7KsgcQF#fCP zClM5Rv8SM-ta!2pEer_MOOn!^s*Th6Rab`UIDt+J|Ka{}{0bqIb_avU&)vu91 zz#nLnz!$8yy9yiwpwv$JwWY*O6kawM$@7c{9<0k~<6I_F01A(IBLruMdnR8V$Obr3 z8KnT}N@jdPJ;Ftrt)lcOGr;4#a>V#I1lbvd84N6ze-?GwsMi3*+4ECNOoAKu*&O2t zT|$Cv=V5UV_88!RO`zwpzV`SPYkFSA2Y7yPzxZ`JXHxge^PVn+DgV6A{0Wtsmum!& zKsLYwfj^tOhI_s*wy)(MoxT*k+7NXwyAcXzU<;HA2RtrCvFGMbI{A9mV0?0t82G*Q z9AE=-VOC`a{z?F7A7v0Z){)2e7x;*&37tq>#_R-S0NVL8l5&y3T!xLo%X_!&2=CDW zMdV5krO)rK^$P;u=QqJVqJ{*<_5|QPz`h3mDE;o?%j22Mi)_H(R|I!XP;EtU``li; zN4YQU*9=tS=iT89r62sryL;|t2<;=xz=;&VKJx_o&VTY%S;bT!Ex&Po@|CY(uUj3D zP%5lKX7=IpFT8Wu)A-Yxt`GR@q+0DgxpQwwtj8AU%6WaRGH z#G_xpOL{FoPwm{*@6X}_t;QAX5qo5dh2Pa(bTXpuMqc7O|G~)nzsIZI>5Mkkvjn2) zza%&k=KhKe(dPJ}J^C*8JDTBRGI0lTLJyQ-`RmM*`kH*CaCZc-UhWGdQSOMWY|t1e zudP-2Mz}H{w~m)>8q;c-YGI~vK%Lp~p8}7~XNQ0O6+9-+yvH7-WQbxT-QDxT(`h-7 zF9SM$?M;V$=QMM75syc&@h{gC4{HBe0pjL)OUJ)n5?xp0?@C|n-(vs@d_28wKJR9| zsNXw3G36qo=ijS?H@d$6Nb|uho*!_)FB8F@O~hDu&&vbINLp61!Ibqzp6BLSzU$h< z`jZH9nIXmyJ@D`{`KQcS!c}qdMY?e!NP9Wh?_HIzwii5raEv@tcGhKmjro~AQ_tNR z_RvLZ@e3M}CZCqa0HkH{=F+X3j-*5CdHBb4j)NzWOP<#$nG(f_BoDxH#;4*viqx8F?BS?Jdfer92l)&15 zruOoBPxpZ)dppkKOa2~fda41)I5HXs)G?iH2dK&|qrZHWBb3aWrr=tWE(1E@NCXH` zaW;HRjDQ{>hZ!Dg8z@|<4fbMyy)6kyXd5Wc%WXQyn9M$COOVTz+Df|gHPY#i5rVhYU^&&8Taq4o8F8pDv|O7BU!z_7<0iN$Ti5xDJ`(T?(@VN$2}9G zKUnphUH+SjaE15aqFw;Z`-UE`P`-oum0+vG*O%`^G1}r486o#Mve;jdX?%SDREivR zMGE%x9>>Ze9%2>y;62z^#dFC^5}E;>x<;P8`UETg&3~7_M;vWzXn<-oC+9xWRo4@3 z2L3|67HNTRI9emY9C(c>{(S}jNwGE(r}jREwNr68i4tg+1THAFw*b$MfIaB7bB;g`@W? z7X_3;H+8Xi1f6&B@;X4aAU^mj-3*K2>W$QO2~n5tIWmoKqY$9AFeg2Sz5o(D9(l!h=1UG>2;KYUc{%m&VZ(ZR)X_yzv~cdp@X}$b;Hi z`!lrwd8HTKD+i#T|I6L+_qTFvR$K*7GKr@1afUyQ|4|pU9~;14<6I^kGlj{5>}*=q z{{fi6-MM7`3w%(?k;~?sTfO9NHQQpjoNy^%7v@Xp`Kf)Ec^Z6FEroqJ*4>h|*o%Gj z7=VLT;7>k&cSxWO;FqSG(_4f6az&M`%NP#n9mcK@n#m#H%#nq7{$OI}7`Dp-%yNt1cfy#jlrZ z-m%!D#|v=q!)}4S0Eg3K28#FVKboJj4k9EdIXcR7#Zl+0DDW9npnra12I0Oc%?-bh8As(v*Cm4XfW&Yd8`NO9DvPF60fJaBea#G+8|Z29U&3A<LD1VH8>{djay zpl#6cTc*W8T8|EmObqtNB-8+C30mdz*H=VyXe5V26^RVBpaK#F+>&}#6%Y196c`{C zs_RRLp-37@b(G%2yM5LY7cRgpkbX&QTxrOx2^oIChRBd&FvEv(cXfYE|Gu;fJ}BpZ z@!t)5>)vV7rV9L>FYSiVDP4a4mJu5O^0|f~z7%%0Jlff4|6oigClwyC4_d*pEJ>O} zGf))El{;gM^;%`4yz%`RIgxx8r3g1tMyDfF#A+<2pw-KuJ_pK88HgL?I4Fz(OBpaW zZ6h@aG{voVZ}=(#je{S}B8RGb5p5>AUZvk*4CGc3_+Zaa^Z0J?*74sWzJLC?#orO2 zAU@;94g0zC8-4Ja>kh_fq-giZTtIkfUJWbRfat zK|(W5rYerm0b5TjT_gm>Jh+SM=Lp6v3B|P#s5=H9o)!CBU(9{!>$c34^%N1=5 zmvHD<_?x;X(+?x(**yOSMbo#_-@rx*Z?S^A%3N{&@6A1SLp5`F^)dgGfLBAmzGrVT ztN;CI1A2fsT%lsYSnLHDj>0c^2g|^QW~<6I4-NPs#OnQ+4U6UHZGF_8yM1rs<5$!O z`9_F5?#!i1k2MBz6XpMHP}UfCy?~{N+7haoVyH8 zBRxjTOA)lf{PFQqM%9n`{F|j6*zdFX!TTou8v_>U&H5eL-nsVkA;i6{dwN^xf6IV- z;nR8&uB82|AK4P`3kBhCX8S%{8+nWLSo>hF>emv0boE=L&wCu@M9 z{jw}Ozx^C>>rjCZ<|+38L#F;4Xa%(jm-HS$KH6V}PBD!EMn2=u-u@?49~DoI6~Ugu zV4wCmn=|>`qC0x5`=^VPoK9yj)EcIyBsLON`Q7FxColG_s7DV$B-;F_(3g3>Z`BAM z)fd@={UCo27q=TMj4q!twrlNMyVlw!?IS1L@CP3OC>ktnNRX$Eg?WsBwLf@wS-+|u zuxkSj_OrS>Aw46>$7CYMCqD3$Pm**Wtw;+zsEh$n{}uqS(G3esFvF^kRp@SvYdk;~6Ytap&MoMl_#R&C2npf~NMfLj8k#TfyN$%BfK zuP+hvh>XuX<_Ch$!44H>T^H0t2+e?*mpGa{W{m9cwUHp`R*eRX zWNH95vpR?J2{{rcAW-vwt^QbMh*|#LOh)_b>FLM25BV%X&NAS=5A?7Bnv?WSMMFq{ z)Zft>dcTd=2ITjOv48%V(?m%8ZE4u)Vd5o?Hv)L?i+BgZ>ru|0Z@-rC&= zU(_$iqv#R6$Bi0oLMqHSqMH7-y+9IKV-S}L6rsnJjBq!u&Sl!y7!1-k$jSMeyZB>b zw^(U_fBoUd>nDzUB4NAHb(J3XpD?*{K*ay}?}B-7oc|22TmjZ|y??RI>2d-JkvOec z0rr#`T?_PX&w23A@=t{mfYA?Vp1^fu_+np)EFsvazdeJ`FgRjM@@z1?$&PoRQm2p3 zaaovmafPuF5=5-+5&Id>{ceh-!2tg%do{7`Pd_;V@Q0u8KIQ93dDi|b*njzyAIau* zCXO%3q(GkAetrG^GoQV~<tnYj|z zu_>3xC=!YL@BWPDJx;yGU|-1T<`Uzvqck1^ki}%y4oA3=b<+xw^d0+0@BaJUSZQgL zgy6Lg@p!iq5UiJ}-!_5AX>Be&QEC ze1kE-A1}b`U%Y9h#lx03Xf%_3l#u24il;<^TBg^qtETGe2DM=n7EF-^Yf1X+2}efVENvgN$t! zc!4~Mo)=-X0a*vVZ0$>h$G>|ry81gnzvG7rrCiV6R;9^Y?C+Jptj2&oz^P>+uX-KS5{a>0%PsOl5*_sF|U z1wQ920lNH)%U~mjp=L0=QJK#eFe+E`U_T!)$iOnwwfXbY`76+Se;I(kS=j^4i~oQ^ zq@LYv{@yy+7uCnIr|3iWDfxJNATK4`yahb@(Kg)kgu&I?h^Bg9)$c-_kHqoXkC0bE zE#}ALgcjs9rzWQ4#1P^g#fpfd?wrBCjA<{_4cHTYN`+YatmV}5zz_B)eNm4ADE6U3 zayS?Gfj+SYcUSpI}OMFPuwBqB(GvxnONAy)wrn-p~ zARUa0{W1WJ@74|5b{P*u4E8@?7kkfv{L8saLXCeS=+idzRviTCWAK{@_E{!;d!4X9 zPaHnD0X$^Q2>YRe4Dt;w?EMGVdwItF^rGIInV0+i>8)ImyPYcbTgEN9yK|N~Hh;8v z1A)78Kh!NP%%Xwoa=Ofa(gA(Io0CYIZLI9MjsYJMgaI5t1sgzu93fFaTJIb7$ZjmB zB>`IxO2kC)d|^*ty9xk%yD0Ft2H*0@O2YM6`yT7g#|&ud%Yd9y^3yMg5>p>4{9vo+ zGXAmi!9F{_*%u1%A%Q_mMwm5yhS#0^a5u5-$4{*8lJhpM{Uz-EO?4>p^p9_3SIHKL z<8u#0ql8=FLKB-$?jXkv6<6dI+Q$NyPAC6xA@-BKyQqqjUik<{oCKR<-eNK^<&?7tg)X7xHe;MhXX|9k2Et4+S#Hr)R)G1{@L2od zQ!Z;rV2?ej^jaV~O&AfIpN-q1o^#B2LVA5XkYneG`x@&>g4qVZ0D%2&?6|~7@1yZ5 z{d=GK2imWnzhoOf%U7O3f6e1ZxXZHs4WCU2@J0GWdGYkk`OGgmsys~a*+29);{C7w zn<~$+Z!6w=sm+=M3*|N?h7e?-=;Q47)~G)D(_A7x&2O+*%L}<0nH)4eLK%ceXetQV zRDI)r9t-g_jP2e9-k*%+PYY=CHTwa$rXnqLV?UQJBhw~^$Gd4ZEW<)9e6ngATb1mKlA2IbJ_I|l&4 zx>vSlJ$--ms#qWZvTy*9_4hFeU=fd*$qfs8qFnK<>jb3zUvCD{8taE%M1DCHjURa@?qruQx>D=UkL5hxc+(BfRD5dc(;UqP zCeKeH@GC_;v;79B(b=?JcKu&_M$Yk;P!~tcg{F3kwH*MmPhtlW{q{PQRJ9ua??s6Met~G)QLud%_%3dfXPn7tCN&7h#TzgVRA*pdIa$xcr`bO!(F6PIzm zXa?}@&p&kE2n{4yO{zbC)?7(%kOhehF|4iaW1hsyl{f;oumpHtqEB$k6?6lan|KWN z!{g8w47Lf=#RK_doNnCBW3x z{v_=LjRQq-qZ}^GuqN>928lmBA)R`FN9IoQ`0pEWwx=WC4j;!I!?ZB&QD%Pz`8HY`7AS&9EI39^#jIVsD+dC@sp`T0=qr$#!#a9}uC0$U{78pBLk7h5 z8)}P9{GR+bzb5LuKjlm)qwK6Gq#JM9s}=?YhSGmBA~N06v)#3P~XjO8G}-f1dg=GaxzZtxev)uN>a_z@z>h<#rByB0P9ZF4C29$33IZ zIUJG=$C&7U8}v23_hT#vC(QVRUsrhBs6BX_2l6S4S<7H=nbaO01YVVf5_yZUV)qub ztVmg?Jv_tdO0IJ$Tgo~zR;>ZU<<6WLJBfSIb$a$$Grk)2zv+!IZi@VpU(WZ)_W!Gg zVwFF2O36qO>*GTV9QP9VMI?pb2XaS}!B^fRbLbP<{s5D|#N?+184i4{MuQ7kgmK;Q zt8C}XA*?lX`^OY-N4$nWt^i&(kF{fATN~SjI8~WZl@ z>GM3RzVZURos@0bu&egjmoM$2o{I_3U?{l%dN`O`>ojJheCaVMi<%yGvVILPMAPwNK&g^BcYRf zO^tc4Ll1fbxjsp&SvUVJo~eG}RDuD?$OSNYK!8;El3?01R4aM`FDX)jv_S-Bt|$a= zr;YeZAV;~KphkDRgsb{D@ZO!c_oe&t;1@eJ3a6qe3prW;r*lTc@A1Bs2dV>DfmGGq za9p7rBbyd9=Zst3L)ErylS-w1NRQ|09+xinYOIw9aIr5QVB2Bn-fhnakTt89A9xWw zdImm_BhpJS4oDaF_KyM{X7T}O1$%V5Y3N$;Av54HE{Ev2FA8qq`Fwjx1OIk!!tjkI%*oX^^PHA$SKf6DG2Y<}B@2aexeyCv0gv#yPlZL;Z2o4vAA?Uz-(m$Hkk z!Db%OQ*bc9#Qj!%OO^*nZ1Jc(o*@`d^VY6ipV8q@i%oqvD(aMPr!3v<(K&YoH`$d@ zz_DluF{^InX|Y=bLUM!g0NO5Jg+|oiRb)ptIX~HcqFGg7Z>g;95OTO=dwNC3>?JhX zh4_IedLSpSS?O+UPww)S#NMrGsWFM^Y^Z~gN})qKHtTXIULUqgIy)`d+fdJVzY$fP zbv5q;@78{|7iPiVQq4wBMT5Mm9Q4v~l++ku9+h=&rqdxVz;UsbHL>Ugi<1vF_O||k zKf76LsJ2@O!qz~cfCnT-`UNvL-?YdNiYRfPzu|V>XnbfOkI1NXpM4&`@_dGTtuxqb zRe!gZ5+0EfYZKfS?P~W zdmd*2M}UjIJlV}6_>~@ZRmtNSGmBMF20f7yNA%)pJ zNaY!ADvtKUR;{;2?W%4^_7=orwig$i&KXT#s?n5_1r_XV?gQPpyY2*_Q-2TqhStb| zUm$cKP81HVk3f9xHvGXm=!$1@z9OE5b}K^^z?A^vk%K)KYu&_enrbAz?>wJtI9ltR zL{}jEno-$zHp@JsmD#7Z3OAF980|;Du-n?jVv0m+yf5Kf?FzxFxZ1dxchh1!oXsZq zD_e+ip^GTBFq9M6YrCvkf5jWLxO8vG8FUMkLXr4mF};zHNN0uSPm+)lafXe=t^}a7 zyJQQmeJbAylL->s7xrd=uGYy+Z!g>V{TrdK3-!N$)nxWheM8{HrES$#TI8`P_F~5w zF*dY$x6G8`JI3EYj6Unq>SeBXanuf2b_Xc8_U=J?md=?k%mz}-qtdeF7Rc&gP968IT+4IZu#bXnsTSv)_75+ZP(Gjd^EbO&n&^*Bwc;siRoqrl(-KV<{& ztnOXwY1AjOs~|sM(JOcQ47IK>66>!{Z$!^AzZfA^56f)+AD73tQ#ia*_!sZxY=N@= z5sf!^Ki$%Lmd#e>_$)h8MTmRt%4sJ-&n~s{j8{wPV+D=G47UL|XcbYA7}Ro+LI__G zTOlo?cZb5RDFt)qeBF|XTS#ZJ2pUwTCp@0Tb60CZH{X=|%9qFW4=Vf@YCXX%>?!c^$X|5_*%Nr8-1iiCE?Y*3Pjis6TMv9sSIBXWVa;v+ zNYy?YTe!B_D;vesxYSE7S>mVo2K!Sgg#+g8;otgY0JmslvA&2Lh5X}y2Hs$Hp7F-^mVRLo{rW$&|cVLDN4 z+MMWzg_vHw8Gehas%noum=96f^sbXk4`v>NGu8JMUk2mGKH1)Z3-He89p80!(5DXx z^qDS<2S}SPH8QSe28R>i2b{#~nc6>$x`5BGj?~$XgP%~#QQJPy{hLA)yd9BsycfgS zxfEpQA`NG&s@gl}i4v1O-8u(flL18Tv7#i)%LwnU_K z7l2n@h&RVhxchBZ@h9;PMPUr77Xb$fQ zJUyiEy*$eFFu&99SheYwLl4n~BeLla@m;0zV9|wG^{MKb=Z{9)x-)Q#P}}8c%p!-H z#>y7sM@-Wqp^f_Cofc|bTRDS8`dW=xCxYE*bu80`CT6Sm@lGb-G|v+PyrJ&>Fmi*g zy#b#v(ltO#S$H#!WFDuh@n7{JTRkS!_hTIT$~U^>&iyySee95ekC6@!J;v~^yPBh! z!(x}C&VryB4u4aY9ju4dL)Xx|kb3Veh2MEMqxWGcU|P!CBWh*?b7;d_;;jw(QeLg3 zws{=cFh-VA{hTu*zLmJPI?xXKrayR(zQn`}?#k7~eVvj8U7ew6q9C^*tY=~3#^SM@ z7vlZlZy@(qpauU2{}dhua*Sqn8sOFQ>Z(0*%%VaT_1MHdXL0e^vZIZECfq z@X8aEpE>_Tp@d4ddOunQ3miBK=gxCh7)L&+c_`iKZ5Zjh!$b2r$SikA7}df z&GUI8-YJSc@Jm0kwMUlStAFC4+r5lPD5*8^?^gCUH`6UjVil`Di{je7PZPqvdbt`5 z5YTWvbyJ&G{AJ=*41tz02Y zct)Hf=(>y>@d|*?*7{fso4)~uc%ORUnyq&VO>j5d4qei3)+rpmluYfa(N?k-GfZL7 zdKR;^eDjYU2)1VwR@|2sA5V!K4X5Kwd!KltVL4cl;1Zr)T?j=MeZ69Md2Ac!`4WLlcPG~ zr_X4KhM|cKnaifQZx+r_wBR7ZhJ zZRfbV;3mx+p7f@uZPixQ%-#+s`isJL=uatIZ&Vz%AzcO6OJw3+ge(`^U+mQJH%FVp z`%g`7jhc4b-PWo!%j}DNthR}1LaMx2tAhrMc!4=(D-1u4JKR+@+EUQEI_9J3MiH{h$t2v@oov``V|9vMKpzS7o?<>i{ziT+eb&?>U{AQTZ8~`y~d` zK4yA6)m4b1Y6IUN6BMo6u&&T7dJ7h_Hch|uM@dyx%?0*IQHXx|N;rk+U+9@;oc;V~<;u5x2uht{6%~tMV4Lo%vPTK!)C}n( Proj_Listing2_1.dep + +-include Proj_Listing2_1.dep + diff --git a/apps/tests/patblt/patblt.cpp b/apps/tests/patblt/patblt.cpp new file mode 100644 index 0000000..84c5d7b --- /dev/null +++ b/apps/tests/patblt/patblt.cpp @@ -0,0 +1,270 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 2 - Listing 2.1 (PatBlt Tracking Rect Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE, LPTSTR, + int nCmdShow) +{ + HInst = HInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW; + wc.lpszClassName = WndClassName; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = static_cast( + GetStockObject(BLACK_BRUSH) + ); + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, + TEXT("PatBlt Tracking Rect Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPCHILDREN, + CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + NULL, NULL, HInst, NULL); + + if (HWnd) + { + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; +const char* filename = "PENGUIN.BMP"; +RECT RImage = {225, 110, 225, 110}; + +// tracking related +bool is_tracking = false; +HDC HScreenDC = NULL; +POINT PMouse = {0, 0}; +RECT RTrack = {0, 0, 0, 0}; +const int line_width = 5; + + +// utility function to map to/from window coordinates +void MapRect(IN HWND HWndFrom, IN HWND HWndTo, IN OUT RECT& RMap) +{ + MapWindowPoints( + HWndFrom, HWndTo, + reinterpret_cast(&RMap), 2 + ); +} +//------------------------------------------------------------------ + + +// utility function that uses the PatBlt function to +// render a tracking rectangle +void RenderTrackingRect(IN HDC HDestDC, IN const RECT& RRender) +{ + const int width = RRender.right - RRender.left; + const int height = RRender.bottom - RRender.top; + const DWORD dwROP3 = DSTINVERT; // experiment with others + + // render top bar + PatBlt(HDestDC, + RRender.left, RRender.top, + width, line_width, + dwROP3); + // render bottom bar + PatBlt(HDestDC, + RRender.left, RRender.bottom - line_width, + width, line_width, + dwROP3); + // render left bar + PatBlt(HDestDC, + RRender.left, RRender.top + line_width, + line_width, height - (2 * line_width), + dwROP3); + // render right bar + PatBlt(HDestDC, + RRender.right - line_width, RRender.top + line_width, + line_width, height - (2 * line_width), + dwROP3); + +} +//------------------------------------------------------------------ + + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load the penguin bitmap + HBITMAP HBmp = static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, 0, 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE) + ); + if (HBmp) + { + // get the bitmap's dimensions + BITMAP bmp; + if (GetObject(HBmp, sizeof(BITMAP), &bmp)) + { + RImage.right += bmp.bmWidth; + RImage.bottom += bmp.bmHeight; + + // realize the bitmap + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + else DeleteObject(HBmp); + } + } + break; + } + case WM_LBUTTONDOWN: + { + PMouse.x = LOWORD(LParam); + PMouse.y = HIWORD(LParam); + + RECT RClient; + if (PtInRect(&RImage, PMouse) && + GetClientRect(HWnd, &RClient)) + { + MapRect(HWnd, HWND_DESKTOP, RClient); + ClipCursor(&RClient); + + // grab a handle to the screen DC and clip + // all output to the client area of our window + HScreenDC = GetDC(NULL); + HRGN HClipRgn = CreateRectRgnIndirect(&RClient); + SelectClipRgn(HScreenDC, HClipRgn); + DeleteObject(HClipRgn); + + CopyRect(&RTrack, &RImage); + MapRect(HWnd, HWND_DESKTOP, RTrack); + + // render the first tracking rect + RenderTrackingRect(HScreenDC, RTrack); + is_tracking = true; + } + break; + } + case WM_MOUSEMOVE: + { + if (HScreenDC && is_tracking) + { + POINT PCurrent = {LOWORD(LParam), HIWORD(LParam)}; + const int dX = PCurrent.x - PMouse.x; + const int dY = PCurrent.y - PMouse.y; + + // erase the previous rectangle + RenderTrackingRect(HScreenDC, RTrack); + // update the postion + OffsetRect(&RTrack, dX, dY); + // render the new tracking rectangle + RenderTrackingRect(HScreenDC, RTrack); + + // update the mouse position + memcpy(&PMouse, &PCurrent, sizeof(POINT)); + } + break; + } + case WM_LBUTTONUP: + { + // clean up + if (is_tracking) + { + is_tracking = false; + SelectClipRgn(HScreenDC, NULL); + ReleaseDC(NULL, HScreenDC); + + InvalidateRect(HWnd, &RImage, true); + CopyRect(&RImage, &RTrack); + MapRect(HWND_DESKTOP, HWnd, RImage); + InvalidateRect(HWnd, &RImage, true); + + ClipCursor(NULL); + } + break; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC Hdc = BeginPaint(HWnd, &ps); + try + { + // + // TODO: Add palette support... + // + + // render the penguin + BitBlt(Hdc, RImage.left, RImage.top, + RImage.right - RImage.left, + RImage.bottom - RImage.top, + HMemDC, 0, 0, + SRCCOPY); + } + catch (...) + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + if (HOldBmp) + { + DeleteObject(SelectObject(HMemDC, HOldBmp)); + } + if (HMemDC) + { + DeleteDC(HMemDC); + } + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ diff --git a/apps/tests/pteb/Makefile b/apps/tests/pteb/Makefile new file mode 100644 index 0000000..c5158d5 --- /dev/null +++ b/apps/tests/pteb/Makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = pteb + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/pteb/pteb.c b/apps/tests/pteb/pteb.c new file mode 100644 index 0000000..6e3592d --- /dev/null +++ b/apps/tests/pteb/pteb.c @@ -0,0 +1,23 @@ +#include +#include + + +int main(int argc, char* argv[]) +{ + int x; + PTEB Teb; + + printf("TEB dumpper\n"); + __asm__("movl %%fs:0x18, %0\n\t" + : "=a" (x) + : /* no inputs */); + printf("fs[0x18] %x\n", x); + + Teb = (PTEB)x; + + printf("StackBase: 0x%08lX\n", Teb->Tib.StackBase); + printf("StackLimit: 0x%08lX\n", Teb->Tib.StackLimit); + printf("DeallocationStack: 0x%08lX\n", Teb->DeallocationStack); + + return(0); +} diff --git a/apps/tests/regdump/makefile b/apps/tests/regdump/makefile new file mode 100644 index 0000000..cafcc19 --- /dev/null +++ b/apps/tests/regdump/makefile @@ -0,0 +1,22 @@ +# +# $Id: makefile,v 1.0 + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = regdump + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/regdump/regdump.c b/apps/tests/regdump/regdump.c new file mode 100644 index 0000000..93ac162 --- /dev/null +++ b/apps/tests/regdump/regdump.c @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +void dprintf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +#define MAX_NAME_LEN 500 +/* +BOOL DumpRegKey(TCHAR* KeyPath, HKEY hKey) +{ + TCHAR keyPath[1000]; + int keyPathLen = 0; + + keyPath[0] = _T('\0'); + + dprintf("\n[%s]\n", KeyPath); + + if (hKey != NULL) { + HKEY hNewKey; + LONG errCode = RegOpenKeyEx(hKey, keyPath, 0, KEY_READ, &hNewKey); + if (errCode == ERROR_SUCCESS) { + TCHAR Name[MAX_NAME_LEN]; + DWORD cName = MAX_NAME_LEN; + FILETIME LastWriteTime; + DWORD dwIndex = 0L; + while (RegEnumKeyEx(hNewKey, dwIndex, Name, &cName, NULL, NULL, NULL, &LastWriteTime) == ERROR_SUCCESS) { + HKEY hSubKey; + DWORD dwCount = 0L; + + dprintf("\n[%s\\%s]\n", KeyPath, Name); + + errCode = RegOpenKeyEx(hNewKey, Name, 0, KEY_READ, &hSubKey); + if (errCode == ERROR_SUCCESS) { + TCHAR SubName[MAX_NAME_LEN]; + DWORD cSubName = MAX_NAME_LEN; +// if (RegEnumKeyEx(hSubKey, 0, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + while (RegEnumKeyEx(hSubKey, dwCount, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + dprintf("\t%s (%d)\n", SubName, dwCount); + cSubName = MAX_NAME_LEN; + ++dwCount; + } + } + RegCloseKey(hSubKey); + + //AddEntryToTree(hwndTV, pnmtv->itemNew.hItem, Name, NULL, dwCount); + cName = MAX_NAME_LEN; + ++dwIndex; + } + RegCloseKey(hNewKey); + } + } else { + } + dprintf("\n"); + return TRUE; +} + */ + +BOOL _DumpRegKey(TCHAR* KeyPath, HKEY hKey) +{ + if (hKey != NULL) { + HKEY hNewKey; + LONG errCode = RegOpenKeyEx(hKey, NULL, 0, KEY_READ, &hNewKey); + if (errCode == ERROR_SUCCESS) { + TCHAR Name[MAX_NAME_LEN]; + DWORD cName = MAX_NAME_LEN; + FILETIME LastWriteTime; + DWORD dwIndex = 0L; + TCHAR* pKeyName = &KeyPath[_tcslen(KeyPath)]; + while (RegEnumKeyEx(hNewKey, dwIndex, Name, &cName, NULL, NULL, NULL, &LastWriteTime) == ERROR_SUCCESS) { + HKEY hSubKey; + DWORD dwCount = 0L; + _tcscat(KeyPath, _T("\\")); + _tcscat(KeyPath, Name); + dprintf("\n[%s]\n", KeyPath); + errCode = RegOpenKeyEx(hNewKey, Name, 0, KEY_READ, &hSubKey); + if (errCode == ERROR_SUCCESS) { +#if 1 + _DumpRegKey(KeyPath, hSubKey); +#else + TCHAR SubName[MAX_NAME_LEN]; + DWORD cSubName = MAX_NAME_LEN; +// if (RegEnumKeyEx(hSubKey, 0, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + while (RegEnumKeyEx(hSubKey, dwCount, SubName, &cSubName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + dprintf("\t%s (%d)\n", SubName, dwCount); + cSubName = MAX_NAME_LEN; + ++dwCount; + } +#endif + } + RegCloseKey(hSubKey); + cName = MAX_NAME_LEN; + *pKeyName = _T('\0'); + ++dwIndex; + } + RegCloseKey(hNewKey); + } + } else { + } + return TRUE; +} + +BOOL DumpRegKey(TCHAR* KeyPath, HKEY hKey) +{ + dprintf("\n[%s]\n", KeyPath); + return _DumpRegKey(KeyPath, hKey); +} + +void RegKeyPrint(int which) +{ + TCHAR szKeyPath[1000]; + + switch (which) { + case '1': + strcpy(szKeyPath, _T("HKEY_CLASSES_ROOT")); + DumpRegKey(szKeyPath, HKEY_CLASSES_ROOT); + break; + case '2': + strcpy(szKeyPath, _T("HKEY_CURRENT_USER")); + DumpRegKey(szKeyPath, HKEY_CURRENT_USER); + break; + case '3': + strcpy(szKeyPath, _T("HKEY_LOCAL_MACHINE")); + DumpRegKey(szKeyPath, HKEY_LOCAL_MACHINE); + break; + case '4': + strcpy(szKeyPath, _T("HKEY_USERS")); + DumpRegKey(szKeyPath, HKEY_USERS); + break; + case '5': + strcpy(szKeyPath, _T("HKEY_CURRENT_CONFIG")); + DumpRegKey(szKeyPath, HKEY_CURRENT_CONFIG); + break; + case '6': +// DumpRegKey(szKeyPath, HKEY_CLASSES_ROOT); +// DumpRegKey(szKeyPath, HKEY_CURRENT_USER); +// DumpRegKey(szKeyPath, HKEY_LOCAL_MACHINE); +// DumpRegKey(szKeyPath, HKEY_USERS); +// DumpRegKey(szKeyPath, HKEY_CURRENT_CONFIG); + dprintf("unimplemented...\n"); + break; + } + +} + +int main(int argc, char* argv[]) +{ + char Buffer[10]; + TCHAR szKeyPath[1000]; + DWORD Result; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + if (argc > 1) { + +// if (0 == _tcsstr(argv[1], _T("HKLM"))) { + + if (strstr(argv[1], _T("help"))) { + + } else if (strstr(argv[1], _T("HKCR"))) { + RegKeyPrint('1'); + } else if (strstr(argv[1], _T("HKCU"))) { + RegKeyPrint('2'); + } else if (strstr(argv[1], _T("HKLM"))) { + RegKeyPrint('3'); + } else if (strstr(argv[1], _T("HKU"))) { + RegKeyPrint('4'); + } else if (strstr(argv[1], _T("HKCC"))) { + RegKeyPrint('5'); + } else if (strstr(argv[1], _T("HKRR"))) { + RegKeyPrint('6'); + } else { + dprintf("started with argc = %d, argv[1] = %s (unknown?)\n", argc, argv[1]); + } + + } else while (1) { + dprintf("choose test :\n"); + dprintf(" 0 = Exit\n"); + dprintf(" 1 = HKEY_CLASSES_ROOT\n"); + dprintf(" 2 = HKEY_CURRENT_USER\n"); + dprintf(" 3 = HKEY_LOCAL_MACHINE\n"); + dprintf(" 4 = HKEY_USERS\n"); + dprintf(" 5 = HKEY_CURRENT_CONFIG\n"); + dprintf(" 6 = REGISTRY ROOT\n"); + ReadConsoleA(InputHandle, Buffer, 3, &Result, NULL) ; + switch (Buffer[0]) { + case '0': + return(0); + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + RegKeyPrint(Buffer[0]/* - '0'*/); + break; + default: + dprintf("invalid input.\n"); + break; + } + } + return 0; +} +/* +[HKEY_LOCAL_MACHINE] + +[HKEY_LOCAL_MACHINE\HARDWARE] + +[HKEY_LOCAL_MACHINE\HARDWARE\ACPI] + +[HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT] + +[HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\VIA694] + +[HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\VIA694\AWRDACPI] + + */ \ No newline at end of file diff --git a/apps/tests/regtest/makefile b/apps/tests/regtest/makefile new file mode 100644 index 0000000..7f83b47 --- /dev/null +++ b/apps/tests/regtest/makefile @@ -0,0 +1,22 @@ +# +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = regtest + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/regtest/regtest.c b/apps/tests/regtest/regtest.c new file mode 100644 index 0000000..88e11b2 --- /dev/null +++ b/apps/tests/regtest/regtest.c @@ -0,0 +1,882 @@ +#include +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +void dprintf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + +void do_enumeratekey(PWSTR Name) +{ + ULONG Index,Length,i; + KEY_BASIC_INFORMATION KeyInformation[5]; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hKey1; + UNICODE_STRING KeyName; + + RtlInitUnicodeString(&KeyName, Name); + InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE + , NULL, NULL); + Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes); + dprintf("NtEnumerateKey : \n"); + Index=0; + while(Status == STATUS_SUCCESS) + { + Status=NtEnumerateKey(hKey1,Index++,KeyBasicInformation + ,&KeyInformation[0], sizeof(KeyInformation) + ,&Length); + if(Status== STATUS_SUCCESS) + { + dprintf("\tSubKey Name = "); + for (i=0;i + +int main(int argc, char* argv[]) +{ + HANDLE hFile; + HANDLE Section; + PVOID BaseAddress; + + printf("Section Test\n"); + + hFile = CreateFile(_T("sectest.txt"), + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + 0, + 0); + if (hFile == INVALID_HANDLE_VALUE) + { + printf("Failed to create file (err=%d)", GetLastError()); + return 1; + } + + Section = CreateFileMapping(hFile, + NULL, + PAGE_READWRITE, + 0, + 4096, + NULL); + if (Section == NULL) + { + printf("Failed to create section (err=%d)", GetLastError()); + return 1; + } + + printf("Mapping view of section\n"); + BaseAddress = MapViewOfFile(Section, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 4096); + printf("BaseAddress %x\n", (UINT) BaseAddress); + if (BaseAddress == NULL) + { + printf("Failed to map section (%d)\n", GetLastError()); + return 1; + } + + printf("Clearing section\n"); + FillMemory(BaseAddress, 4096, ' '); + printf("Copying test data to section\n"); + strcpy(BaseAddress, "test data"); + + if (!UnmapViewOfFile(BaseAddress)) + { + printf("Failed to unmap view of file (%d)\n", GetLastError()); + return 1; + } + + if (!CloseHandle(hFile)) + { + printf("Failed to close file (%d)\n", GetLastError()); + return 1; + } + + return 0; +} + diff --git a/apps/tests/sertest/makefile b/apps/tests/sertest/makefile new file mode 100644 index 0000000..0e4c6a9 --- /dev/null +++ b/apps/tests/sertest/makefile @@ -0,0 +1,22 @@ +# +# $Id: makefile,v 1.0 + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = sertest + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/sertest/sertest.c b/apps/tests/sertest/sertest.c new file mode 100644 index 0000000..dc53aad --- /dev/null +++ b/apps/tests/sertest/sertest.c @@ -0,0 +1,113 @@ +#include +#include + +#define BUFSIZE 128 +#define MAX_PORTNAME_LEN 20 +#define APP_VERSION_STR "0.01" + +int main(int argc, char *argv[]) +{ + CHAR txBuffer[BUFSIZE]; + CHAR rxBuffer[BUFSIZE]; + DWORD dwBaud = 9600; + DWORD dwNumWritten; + DWORD dwNumRead; + DWORD dwErrors; + DCB dcb; + BOOL bResult; + HANDLE hPort; + int i; + int nPortNum = 1; + + TCHAR szPortName[MAX_PORTNAME_LEN]; + + if (argc > 1) { + //sscanf(argv[1], "%d", &dwBaud); + sscanf(argv[1], "%d", &nPortNum); + } + sprintf(szPortName, _T("COM%d"), nPortNum); + + printf("Serial Port Test Application Version %s\n", APP_VERSION_STR); + printf("Attempting to open serial port %d - %s\n", nPortNum, szPortName); + hPort = CreateFile(szPortName, + GENERIC_READ|GENERIC_WRITE, + 0, // exclusive + NULL, // sec attr + OPEN_EXISTING, + 0, // no attributes + NULL); // no template + + if (hPort == (HANDLE)-1) { + printf("ERROR: CreateFile() failed with result: %lx\n", hPort); + return 1; + } + printf("CreateFile() returned: %lx\n", hPort); + + printf("Fiddling with DTR and RTS control lines...\n"); + bResult = EscapeCommFunction(hPort, SETDTR); + if (!bResult) { + printf("WARNING: EscapeCommFunction(SETDTR) failed: %lx\n", bResult); + } + bResult = EscapeCommFunction(hPort, SETRTS); + if (!bResult) { + printf("WARNING: EscapeCommFunction(SETRTS) failed: %lx\n", bResult); + } + + printf("Getting the default line characteristics...\n"); + dcb.DCBlength = sizeof(DCB); + if (!GetCommState(hPort, &dcb)) { + printf("ERROR: failed to get the dcb: %d\n", GetLastError()); + return 2; + } + printf("Setting the line characteristics to 9600,8,N,1\n"); + dcb.BaudRate = dwBaud; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + + bResult = SetCommState(hPort, &dcb); + if (!bResult) { + printf("ERROR: failed to set the comm state: %lx\n", bResult); + return 3; + } + printf("INFO: preparing the transmit buffer: %lx\n", bResult); + for (i = 0; i < BUFSIZE; i++) { + txBuffer[i] = (CHAR)i; + } + for (i = 0; i < BUFSIZE; i++) { + printf(" %d ", txBuffer[i]); + } + for (i = 0; i < BUFSIZE; i++) { + rxBuffer[i] = 0xFF; + } + printf("\n"); + printf("Writting transmit buffer to the serial port\n"); + bResult = WriteFile(hPort, txBuffer, BUFSIZE, &dwNumWritten, NULL); + if (!bResult) { + printf("ERROR: failed to write to the serial port: %lx\n", bResult); + return 4; + } + printf("WriteFile() returned: %lx, byteswritten: %lx\n", bResult, dwNumWritten); +#if 0 + printf("Attempting to read %d bytes from the serial port\n", BUFSIZE); + bResult = ReadFile(hPort, rxBuffer, BUFSIZE, &dwNumRead, NULL); + if (!bResult) { + printf("ERROR: failed to read from the serial port: %lx\n", bResult); + return 5; + } + printf("ReadFile() returned: %lx, bytesread: %lx\n", bResult, dwNumRead); + for (i = 0; i < BUFSIZE; i++) { + printf(" %d ",rxBuffer[i]); + } +#endif + printf("Attempting to close the serial port\n"); + bResult = ClearCommError(hPort, &dwErrors, NULL); + printf("ClearCommError returned: %lx, dwErrors: %lx\n", bResult, dwErrors); + bResult = CloseHandle(hPort); + if (!bResult) { + printf("ERROR: failed to close the serial port: %lx\n", bResult); + return 6; + } + printf("Finished\n"); + return 0; +} diff --git a/apps/tests/shm/makefile b/apps/tests/shm/makefile new file mode 100644 index 0000000..2bc060f --- /dev/null +++ b/apps/tests/shm/makefile @@ -0,0 +1,47 @@ +# +# +# +PATH_TO_TOP = ../../.. + +include $(PATH_TO_TOP)/rules.mak + +SRV_OBJECTS= shmsrv.o +CLT_OBJECTS= shmclt.o + +PROGS= shmsrv.exe shmclt.exe + +BASE_CFLAGS = -I$(PATH_TO_TOP)/include + +LIBS = $(SDK_PATH_LIB)/kernel32.a \ + $(SDK_PATH_LIB)/ntdll.a + +all: $(PROGS) + +.phony: all + +implib: + +clean: + - $(RM) *.o *.exe *.sym + +.phony: implib clean + +install: $(PROGS:%=$(INSTALL_DIR)/bin/%) + +$(PROGS:%=$(INSTALL_DIR)/bin/%): $(INSTALL_DIR)/bin/%: % + $(CP) $* $(INSTALL_DIR)/bin/$* + +dist: $(PROGS:%=$(DIST_DIR)/apps/%) + +$(PROGS:%=$(DIST_DIR)/apps/%): $(DIST_DIR)/apps/%: % + $(CP) $* $(DIST_DIR)/apps/$* + +shmsrv.exe: $(SRV_OBJECTS) $(LIBS) + $(CC) $(SRV_OBJECTS) $(LIBS) -o shmsrv.exe + $(NM) --numeric-sort shmsrv.exe > shmsrv.sym + +shmclt.exe: $(CLT_OBJECTS) $(LIBS) + $(CC) $(CLT_OBJECTS) $(LIBS) -o shmclt.exe + $(NM) --numeric-sort shmsrv.exe > shmclt.sym + +# EOF diff --git a/apps/tests/shm/shmclt.c b/apps/tests/shm/shmclt.c new file mode 100644 index 0000000..4b1f5da --- /dev/null +++ b/apps/tests/shm/shmclt.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +HANDLE OutputHandle; +HANDLE InputHandle; + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + + +int +main(int argc, char* argv[]) +{ + HANDLE Section; + PVOID BaseAddress; + char buffer[256]; + + printf("Shm test server\n"); + + Section = OpenFileMappingW ( +// PAGE_EXECUTE_READWRITE, invalid parameter + FILE_MAP_WRITE, + FALSE, + L"TestSection" + ); + if (Section == NULL) + { + printf("Failed to open section (err=%d)", GetLastError()); + return 1; + } + + BaseAddress = MapViewOfFile(Section, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 8192); + if (BaseAddress == NULL) + { + printf("Failed to map section (err=%d)\n", GetLastError()); + return 1; + } + printf("BaseAddress %x\n", (UINT) BaseAddress); + printf("Copying from section\n"); + strcpy(buffer, BaseAddress); + printf("Copyed <%s>\n", buffer); + +// for(;;); + return 0; +} + diff --git a/apps/tests/shm/shmsrv.c b/apps/tests/shm/shmsrv.c new file mode 100644 index 0000000..9871ed8 --- /dev/null +++ b/apps/tests/shm/shmsrv.c @@ -0,0 +1,53 @@ +/* $Id$ + * + * FILE : reactos/apps/shm/shmsrv.c + * AUTHOR: David Welch + */ +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + HANDLE Section; + PVOID BaseAddress; + + printf("Shm test server\n"); + + Section = CreateFileMappingW ( + (HANDLE) 0xFFFFFFFF, + NULL, + PAGE_READWRITE, + 0, + 8192, + L"TestSection" + ); + if (Section == NULL) + { + printf("Failed to create section (err=%d)", GetLastError()); + return 1; + } + + printf("Mapping view of section\n"); + BaseAddress = MapViewOfFile(Section, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 8192); + printf("BaseAddress %x\n", (UINT) BaseAddress); + if (BaseAddress == NULL) + { + printf("Failed to map section\n"); + } + + printf("Copying to section\n"); + printf("Copying %s\n", GetCommandLineA()); + strcpy(BaseAddress, GetCommandLineA()); + + Sleep(INFINITE); + + return 0; +} + diff --git a/apps/tests/simple/makefile b/apps/tests/simple/makefile new file mode 100644 index 0000000..6c9d251 --- /dev/null +++ b/apps/tests/simple/makefile @@ -0,0 +1,20 @@ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = simple + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/simple/simple.c b/apps/tests/simple/simple.c new file mode 100644 index 0000000..915cc71 --- /dev/null +++ b/apps/tests/simple/simple.c @@ -0,0 +1,15 @@ +/* + * The simplest Windows program you will ever write. + * + * This source code is in the PUBLIC DOMAIN and has NO WARRANTY. + * + * Colin Peters , July 1, 2001. + */ +#include + +int STDCALL +WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow) +{ + MessageBox (NULL, "Hello, ReactOS!", "Hello", MB_OK); + return 0; +} diff --git a/apps/tests/stretchblt/lena.bmp b/apps/tests/stretchblt/lena.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e9916963852a9748baf1b9ac6093fb3b9179dbbc GIT binary patch literal 89322 zcma&vKawKP@-6s!8<;{I4aBE`G%DEWW8?zHjNC!81K0uV0Q9jj5Jsnj(W`b)EkC7u z2R)zTkx*23-}jro@#QATpUMnBas0T4NASP@AOGY3{BJM$_rLk?zx(h1^56gMzyJ2~ zzj}Om`G36r|Nbv8^iTRl^JZ=GI$bT-i}|u!d0Z^#%T3qMr@m;u znlBH-cC}cp{cpb94ZHnzKb_3Hc|KdbzD{!ivt>2kznnWiUrr`Ix}MEe_w%mP`EIt@ z%~$({wmvRaCvDlC=BtCRs#mwm^>MX1uR86r+PLMb$3L2ry5iohOK-ckyt7Z!UF-gq zHr(`{KHNODe)rz*--rFj_VBSge(X=52ko48JpVXdTKjpr{5)NMp05smc)Y#;?uX-a z-gm>b8!n6WuIu+*e^~d&?yGrvSZ~I*8V~mC&2H80)}6=wsyi$@w|QD_PV@C~>3+Aj zHM<`^kJq0K16?ri-t9jc05*$( z1%sgR^>sFx%)C0Atv8#!$3n$o;si9!*VFj`NAvZLt(Pm^s2`5=)o~H!zaQFm(-SM+wfc5X~vtTfq{(*tFkKY0I zyl1|3e`eoqII{TN(9Q15U9CTWM=YMFyEGWcBMj_eU{P%~T!!Q4aQe|5K6+Pj`B4~n z-|RkIr`Bz6kAwB#mM^`(zTQ^PvuRrOe+~?1$8B_b%2JLOdVaQQW0rl}$-C{wZ-575 zA4pg{%+L@rVU^|3^&2qQ^xble2fB5?T&!#C&tTx?Wipxg#L~fRzM0N8^Z91GzjeUB z?&tH6z%=*_Khyz3Zy0*P=<9Px00z4Ae0`cNdepI8Zk8+k0~-PSx&wnt2%*?u9QbAT z=i?CuHSq5YF!Deb5*VqVVDKIWs5b218wot|KrryI{;|e>o?b%&m$%=}yu7?Fmi>Bj zS@q{O-n;&^8OBln82%#+I@W)@6w_A=AuPMYVtrWk0l@b1b9epKpMPwQKX#Xq2Vj8p zHFmEC&j5c}bm#SI-}i?i*s|bbbl12x29f-F)xiMkFza%@X0_#fWtbOWJT{|z15dCq zft3}HFf(SWVViBg-EViBRkz*reb+DZY8Yd+1g%BBdD(9^yM8!z-OhzASN(2#SmeBG zSUwuihOfdK2K%r;{wprv6ds77&rVLJ%jKe5u295zQB=RK$L18q;a{BZc*H>Yi)SkM zasi_k2mtgUBK?Me0>Cyr5E2Lv+(}@>!1X7KJANR6BiIb*U|_*d76vwZXorEggD+b@ zj*AVR&VR>1sKAA7Pe1q9-@EJY;rw%R`mt?1!29n|LF0iE1609qgK#_m1ItCPGufJn z8KQWAXAdMEoWQ2q>+6J>3|_}~{osYwVqt{Vo9k2U%`EG{tG*Kkmh;61bM;$P&||S- zJ8YsufMf_T_8iCMbUhy~kkfTrULb_tkuRr_KXMg-L zoXZ!C7ytvR021EGgJ58|!9dp?m&-wiXH2ybO}W7X3NLpMRFsQnBZRP=QF0xt#ORZU z2yE|Xk^86O3xa_~zIILz001vQBCeM!Fxd73kH8&lhg~qB6L0V9`RXPAe6R0c#^cBO z;fiMr6azT#qy~OquwAWBgdcMg13bcFxtmTS7#0-o>Nt-Wh!<#&&m;Yt{QCm{o<0O& zlY-RXvmpG_5q!r$0Pv*)BLk|PuRpGDzqFT0+$(WQ4-l>efM6gd?*AhO?!eeLB@jnI z4s|dv|mi5O#pu&M-004*{h^!J6JOSWu9*7!zVBm5mfl(5K1a^nZ%Zu(^==@bw{UzZ* zG$9OltoAP|cwpem7u+$x9c+)EhuiP{?H5(R9cTtsjeUCHfq{?0z#D`c9h?4aq)aLh zXasBUHv5)M1Bo)hIO@0EFmywEPvlx(`a0e34hUgw3;OnBhqegeW%GXY1eN!Loj1g8(40K!pP$g7@K&sBl|R;g=W~9YNUO zLIjQ^@CzZlfBYtOUS5K8H@eyc10D+l#Q27#OI;ZjW{2mrBTmz%hA5U`U{>Tx{TKU#FX8w;x1v;Q<(+ z1ZV~y$!G8RgnWuGC-LS<0!Rh0tl`fKEDHv50(iig)BXS(Gy}Kt`ZB=`!*)j|=@ws} zZ(eNX-1@950Jy400}Ra2@ag1Agf(046BVwGBL=2%BC92}uv>JrV#7cH&@k|fgytRo z=7cXz*usH7asmkn$Fx8N1x*l^7`PCDCz_=UytIGwJi6RLE>&-{gf>%-{5#$Vw;EK=Ga7%1!C+2AQPG^Pat zgL_o?FAOv_c=>U;Vt`*@00W2P4GHKdU8LWZ>wW&v=F|lP5)p&>%{H-8q6!RB*ZdyxgJ&XY-E#Ef@nTQP>OXk|~NBqz~l@?-*!=5ON3=G%@f1 zL&-vSy~P6y?tn1x+1+g$H7GXx`NRXw^xrUm_hyvRdVjinaJzc4>=+uak<~Cz-9C=B zAi;lYp_}B7QQ8uQO*&4A|BjV8eUH36{%7%(Eb+R-{K3F%*>MXlbl5{44A2S7#d@{u z03aCXpyIgSoduz}7^aRLSM$ma!9ZPDE+go0GQd~{8>I{diCn)_bOHhSfk|FUnrOLi z7$BP$1%|RdR7lOW@g593TEfOZF+dDFM+B5W>47+cz~HV2K4BorysRHz&|-mL;Kvyi z+~Npy_{$3<=i&oYJh0qswyuHogMo;{KQK@L_y-0y4=TU|fx(1QCLl0*rZLLykbw__#j|!(Id@RoHI^c-Rhy zdlo&-gjXSR7n4UeZJbaTc=UW;!V<)Qct7Uml*1nE!P6VdKIYVlI|xNoo)8%L1xldA z;fnVM1E`Q30K3C>-*0w$gCP9%gMytN<%pL3OA;1yT)-F9U~vu5*si25qc9L)z(B4% z0f)a++W3@&;c`gK7%dTBfE08egzJM;Vqo@Teb(1V#+RDLnDOJs!L(fiWU@ z%Oueu4DbgDGz>I%Fh+>Q2J%85KYo*5Nq|Jatm@W+0XI7AZZII_Tkast|5rOac;G8_ zOeHova0lz{nlF$nN`P=AffjggbN&khqcDI02_pTl+g<0g4h}Pv47_;uVBy~38R?A{ z8Y(=t0iHJ@0oOl?cZe{c2^}x_{*EtbAb|nqfeNYs7044x1Uv3KXy6Wp#bPb7KWw(= zqpO`VD)xK?Gp|AhNI|0RVu3CK!Bs|D}T~9p}Q9@>dyp^Rr z!~+csUl@ol2oE$E>|lvI04jdrfq@njBs)|QVlW^8*<9Yo=#lkda>wN zLdARDpmK)Cv7DgQ5{!Z20|xD&s36vFtsFtc0uKRDV&LuzLIUA|F(|kQ4PyG%Dk=1{ z%P5=F@ORmI8%kYpVZhWmN=MG!aU(W-)`WK$L=W8Kg3%X55H=aG;|1zV2^;&A3gEh^1#d8Y3;?U;Ec2t48_a~!zLyq02re+s`FK6-PSrWf%n?YP8(J`cOPT3XXA2%@)ZH z1rN*3ZMr;l^Zs!Dn2}8L&8yKqU%XB;W5n%}c&uzrM_P{`r|VFy`5lI4V%pCzhZb?% zTJ+ZqGj#DXA@3y+V!ddCqzB!wq|jz9OCTvEMcDVN)h3xzPG@yJ-HHuf_uGTh{%E{p zqW)aKa?#DEp2p~{HD}ZqX*?Oucga4I!L?X!5JJHQunEF}CKNNWyB@}Vq*o-9e6p$Y za{Z5}@CyJX6umm?0UEmqVc5S(#-{Bh1b)Z~IBo?4`{R$p>F43}!3*rqKM$8*&YK>3 z`}n!(F@Q8cf|MHjF3$xA1I1l(BN&r9W)y%lM2?9L*xlnO2JTAW9uX80iUdjn$j3(v ztlVtxmWBKLpZ)HKfip>WGvFfjuK)oI!uAxJ zS)5Gz#GvKeg?SqU?hR9pV492&+UM(s8uFfc2@+BFluG4eM^(ZCGk0iGMgH zNjRDJN=0_Z9HW0;GLk+XAs849`oKUt@P_e>g9He746u6%tw18tA`B#86g2S&VS^B0 zO)V7+gyfgVgTGpX2d4=JW{6raxIH8#XkH)(9-9nkH3Mh9pa4+C1CB459Q?6LZHyap zwdl0>hydgME|U^u$r&=h9RraKW(14|1I2zk z!WRZoEv6a%VE}TWr2-ZB_t4GP#)hXL$)vg1qdOK;0V|!s&9eG6$fS#fnAaS#TzaB@7FUp zFkiT$30c3V9TxNfJSaRJk$;cc(JCA@SLmciL#eXC zKWJWe)O1d+yduFT48XaY4GC!J;n{k-e>X6V_m(2KD?nEZ41C#cd>oSiv3ps+kM-44 zRU5w$Ap{$mj(uq*PdF{KHj=>Atqr@k^X1oUagJ7Tg_GrEKHHyu#|`WKVt7`Ty9+3C z7YqOI%vx#L)M$?wn7cRAGrPS<4G&}*$Q+cit>bCCF&8jRXt3l6xazg!FwMYCm@|?g zWINR($HUQJDd5Gp(Sb?vH4LP$?i%132IDc9XoZ}H0pAcHl}}4hAnHj;VTOF^0oIQ% z2n>`LW_Bh37%`Bs{|yYG2+jp!PXj`{uUG4ia%}-; zc)*Ot&_tktQU@E}DhJ*$U2gYpMb7&MgAoj2g95;4`m(H1Z$4B3RmT3txb(=IWSTX{ z^)wTv-mt!7KxotQ19;#aDqy<}gtzO*didd*IV6>09w$?Z&Oh#epl=Y3=$e}+s=`0k zZ${znJKks`@k`@%l74g}TEGU*lL5!wZdD|J^E;rV6lexT=4!=XQ&9~t=Kw$)SgD3& zp7DTgVbJISPO2R{ESKsH-`X<)ox znO4$W0&}(fEn6GIFHrYD!7u?62LsqWOvN;M82hi9j{pO2pbw4ujUaQ_cFUDB-X{6K zk~)|zoK!)IAJ#NkWe9~8%OzxTAN$+ocHHi!uk=JDfzSH?h5=Mi7y!vH4E$mJ_Oy{e z1zZJy27`Q+3+8G!=9DvU7#VQNkgr5>!9Z^Z6=`t|4FJ~;^Cwuy@Yf(AJkZ?1HW=8A z7_f-oLxr$uAQQnLPuRGxN$vq$4WnSS=m-zQ7r+2tP$41yU%~cb9t;3O@$do%66Z0U zoel?&TcvW~u<0p(2oXAn2-G9tA7A1Px@=O+^Bn{Jq`uOJW0yK^eOr$?uI^pJK(WLF z20A|&2oES8$b5mp6&Q3fz?B&o^8>~Fv32|cbB`EkNFbS-^_eD;V0()rsA8c?{(PDP zpQIB0Re&7Z=Z@WXt|wPG>Q!KH{mTai97OXZGl04`U=YduIvaKop8^2|4>7l7R~=;d zgF%E1zm|jXxPn0zmn3X+MubGILCDiCOAod}hVa0>a$ux_$DC1O!&A+#tg6v42vdncLFH^%uMgYp zcG!Bl-wfB|`5+%iFuzU{6x8?Ez{wviZ*IuwA`wTruG!sRZ14R3m{%K4>Vr9Mf>8J( zF>bp}x z)yXp}TH952Xy1&^?p2EHX|)O)3mC~B{|5|=HKi%2UhP~%Ze+@H_k8i>wNcsJl_v%S zgV7y?5M<|=Lv!bI$zk~~^};n_)!`atrv=6^^|Ti25rJ zrg~7*crRZ4;(6+h{nQ<}Jn}o0G?pPTB+-6e9<2WS?*2UZU*0F-{p3%KZ zEeHq5KWB1MM`wy~vrH;!z;d--Y^OK47}AMx7m=4nkB=Ipp&d_04BY*D!$2HRjkxcR z)x#P1%>#D2D$+(GuUhL zs2Td$j;%*)V?PVi9>+xs1&{hv^9XqagZP3!05DD)B~RG&z>b$JNW4*F%n*YD*NB0KW6hiY0f0McR6lz|Fwl&CKMt@fj2f~uHN*dW4+=~i7}S(M z(<>Dy3{+Zp*nRZd_h0}LSRW@0RKdH9$|j!T+$qR67xUWKuYvG>7b7Rc^mV~G(7oR< zVBW1L%e7V5=qYzR#{+}Kl>;|~3Tm)hbCmW4gF6xeiSa#8?x5HJ3|N0`_~fAnYWDCw zlLZf7P#B0W&`aq$$)D|Nx#baDVKKw1cp&!@#|;F90Y1V3yHkBU{(1=nV*g%*2m`#p z#!Lc)m_(jT`;B8OiQW{9Ot=}L!=itC`%pAdb4I+(oMUZN;14_ob^7h!!@uDned{{E z-k&}%3>2a1+uT=zXx87hxWEi@6_MVppT#D@z!wR?KurIhnt}U)aNyBc2LLo)8^BA_ zr0X(1a={~popDEBkEw?-D|6?82L>unSge(4qlN)I;IFi@(gMH;gJ$&ab}yWa^GczG zVvjEXK*AFSQc{=zp{+A&Yt5nuPK)J!HtQ-yuf}V?TnupscOIw%jGYl0!|U{gkrhZp z56l;*-Ja~<7~2TJcToofVUo#94UOQ0Zbf65E+H7ylgJS(u6|$dJ`^VFL&KioVJcJ* zU+^$-x^x`-kAu8Az9B$u7#NAy({&B2jD4jm0Khe6_*X4i0FYDw00aY#1oGJ20XEot z%@U%85d%>LXd#jN7$-)volu8TRRqrTE~EMf5+0Z5WMSaWR8JV-FuVGQffh#~H1PC0 z2Ixjq`z{3=9ts<=ep3r28Vd#y5|NR29(e!q2!Hax4hFbRvoqV_)O>;A z9|1t-%~$IcmT+tA59HH`f2U0^7~`w;?Rcd6Omx9L0BEbZyzojYcrg`JtOi-Hg<0vD zIR*THUbfrg_3}QPf14(gA4otFl8Gw#GWtlQ>C$v&Vc@BU!vL-2QVF1YR zFB!kD3Zmn3B}X?<2C8*YBjW^qmnsDbVZqC4l_1)f}D!bd9 zBUB0lP+WxXMgq}1e#1a`Ah98E5>3eufX#@3;C2=ahzsPP$`=F!lwoEM8|T9Sk5EXs zV*?2^ijefU69NfQrhoDUhX)46S>sSa-Bf==gDpQW3#Um7Z??lxZQ&y8H+PIxH#k!d zkStbi%}m0S=3nUcN#X)tz(OI@!N8%@RR?)hnutwhd=P?(@Qo-zVsqwW{aV6&zT54u zTPq4pGMslD;U}BTA0cT8KQn1~Egm&G?qG3QH0tONqSa0$T1H8{Evq-5qub0|m7AXfO zccFN!Y7>tKEkNqNFi>8=YNIST!U@51swiwN?mj!}ClpIY0>{QD81W-lQaArTnB0QaZR^C?Cm7NCqb?mpeJA%jF&X46D=a z*Nd7T*os3nSdhQ==*eZE*lgW8bA0-Qfl>wfv)q~f1jfNMHNO-RsPv%lziP>d`O`=O zv3pD$B~XtK0Nk_3&~j3VYEo;q*k^N_d+hDWn7A%GobU_)S3ZV0rp56< zr3V`iRB9+NPMlbnfq}k1N)-lmqv~kG-0*i03=}7{lTR>s=z+5P_sWxiq47XlYt~@k zm@p{Cd&6c%y{V$uHp6;zJiIqI+O4<61BR{@B^z0+<`Hn5GbWCM0Sr>>#gP2A&+1VK zfrq6*XgT?I@0~*ysG2MoPN(a(KTj9OZoU6}|9G7av( zu=wV)JxPLuHoyx2r9w|4s*wb0_=hM)U_9{vNZbq0T5bUbYTz6DqabXl;}k_?wdrxA z#BMRfmnD1CDNXGAv(Y3*fC>yu^&7|mz?33bsv{x`VZfP?;9|iY4C@Vb#7C@BC&2EK z2AMd>?ej7QWM-Bqg4^rjvRa*feEeV?EIM6pRo#Q7dNcxKGV{-;(kFFEc`PXAOtrB~ z<4*~~ba*hp*Hlu7zM=z1{x^{|>cCVD6$3;Gq#6FTHxV9Cx^uJUj(32HB+V>D%JO8s zGVfV;Z`!7R*Sh{Ki`KoWWzso%GL>noo%JkrdCwS#%Ke4`*O^iO7Y1~GVPKGj-p2J5 z1_Fi*{4Wv+0~9dsNEn^M7$oM+vHqjQ9eDbMfeH#59+LQqgS#wO2ZGKL0}KEIA=24q z7%mdJ0)(WFo1ru0n=qS`ZaFFAL6uSS^SR02&T7F|_m-$oPyh+5L>4QOZzE#xMVsUa zm;L)}{We`5HmmLB@-bcXFT~qwdq`2%Pt!@0LGP~BS)sGZxfMKayhLV!OopzGE;uy~+hpsN(zM!F+1Amnf0KbihfJZvD3Nul&W ziGd7f4B&idAq$b1*!M*gun!Ce zv^BsRXoG<;z$S^onkR~P2s0pC?+k(Lb{Cb;BL;Gjgu!{l02ow^P)08?Q10N%*3Bt= zk-&ou!UIMAS!9` zfUDExmsAs3aEC!Tf>8a4hwwlnfsFc$BmLGG0E*JR6Mo)0=?Fjqt{?O}G662EjnQ*aHJ#@W4RO zqSHhmd$ME?16eVOlp+i9Kyw7~3zZ-E3j-qnoc|j8&#oaD7;A?T5;kR+*l^sV@>Fqj zpDUcI@-hUrYJ}(W%=ve#fzdgA+&Jzg}|GIy^KoQP6;}J__u#<&d?+ug8 z1EsWas1*m(*B4*at#Bj;yjt*jl*QN1rL2F!omsD+0Gh`5LXDw1;?_2?#5S*0R#~c8y*;M z#5+~i>9~z?VXcsezLWp}fNNo33=AU`9(v$0_D4zZV1s8WC{#2Iuz1xKH(yZ8&F=e@ z%A*?l8BL+ne!IOe$82W4cfYZMmG+b8o@d{Hq=o{CSef-1v>x*m28?}g@XkOY5^)L% z*Z@UjE#a%!NB2NQ?(}%LsXbv|QzUW)-B#~yL?wD=ceu`0CxFS^LP81`!`$h{c94_t zr-gxBOkuz(V|k%DF_3)V7X}dB9Ro43!BvJXFc1Sx{0Az<3?&tiaCrEZ#9$udG)F`g zv{Yv1WOwnZX$2_)mgC%5uPwmDT04u;K>&}Q$gd0rU}1zV8lQrKXYp}3U-kJ$q#f0SuV$}05Cu&Q1W<~ zp_#S6FDP>+=0*U81jp-$!&o0Y0s!Z$f`|)PGvPRkcz&I79ejOm)|eF~!Jb){|f^#E-z4y zpzu&n%kE|IN6M%PMUTON$)l<&S4V1Ho@Vbs(#5KxR$8poBx@F`P`UCgwYR_*31pb# zOBWpVR7yZ^Hw?Jh!gi7aqH;U&tm7*OOrBEbCk!-6@E>^KI|iERACKQKfC}FJ(1evM z-m^tvV3S0_e6!im?HJq2!R^vD8@t(0W+Uwr!B!0bIEcVt1VgyOpiNaFR4|4mW$Vor z4AvbIATn!LkeLp7jp|!31ra72vk%YVu)m(KLdC7f&c$rjo89T>>q`KWUV_82c-g&S zVD-QN6|qhY?Y1I`FxqwWlZg2x<^(*#d!)%@xa`tn%(O$ z!^#nTQX7^_d+=am%15bJ&6UR>&5D*m)z<^S#w0Xa@YgB*E7A1?An}1&x z44Av`$;Gab18jJSnbxaytiMXl*fOM{mMqC4EpsJsf=mEpb*MQqj1lt@jovuaN?Qw& zk0+gZOu`Tsbz3X-3;{4$rm!T)xwi&@FAU%l5dj{M(yyRETA(6=27rcvhuz168v9KD z)QtC*Hu)liki$q3+ub`Cz!8KKj-SWV2R5)=E0SQ$5}*P`r0r?NTwX8$sA(`e&Gb~76uY0{(*sW0{}4G@$el6&tQm8sXXCddf-u8UcMka5TzG`Pi{5K?_ZaeLvOE750BWSO{@cAp3O<_mH)de#qisL!@Uyw>jz3OTmK6rT z=8l02N8nFGLV9x4FkC=jaHp?`nSwL`Gz^r~A%;~D*;1@9;HA+Q{Qt$k=^iFHxF0|B zK&>#!+;KLi`q=Ep330w4`}Ww$t?_`25CGJe5)>?!hsAto)NQbH1T~hk`j{`bbqo^F zg#Rmg&{r(i6rkgcl*;bF9ncT6xc)%sm4nIB-FFz6*oT(&ad-ld*=v}>XZw7j-&x0J zXDzb90=T^`)82o-yujPbodh18nIVRwh!$JYmB`$+%m6Foz8=Yer?{X7buci(pzM1$ z{fGgjBRTWL4>iBQp(w-5WC$IXp4L$OA1iaCZlMK`vWT z^dgiN+X_{TccB^d@?~tHLZ(YyS#O*wAfybnH7B2h%*tW}Bc0xZie)L7S3xoR1e2DG1u#> z%kx1)CK$-DLP~k+vRv)JeT)lBD`Rty1qed?Jn}$u{eO_a!xxknXuco=KNv8t6q_2? zSH&_ld34ib0zkE1`@FOxa1l_snv>>*qU)Hv9Y}IvmdbIMCkP{mUik;6GPm+X}=ok@NAYTU2jf2Oa{v-&| z5Ws{;&{y1tx&l?!fx-T|KVD_&lSo7q$-2y{KQpX6b=j40aOGPuPL07};7Jyi4EO^B z{b=;kfei@)KnIWjEyV!KBOU+)i@;u9Rxctxp;OY)haiNMeJBJ;T@o(JFtX66f&@FJ z)@GyygCMpnzA9g!8^Z&d{*WM&B-!q-95GE;LPAF^GxIxK>_{MWoB}h`%5emb1|fg6 zCl^qaMU56m(#jkSgPW`?S?+?R7Zo%6UXarh~2l_1P7u4j3jrPGn1flWB5G_;G zq+s#DoeCbKKC}?Kr;!0Uh+>rXIoqFyt$BaKDUu+mgAAPbP%fswZA~fKj`H*)Q%<77 zz@WJU$T`XyNx13T!Ywuk4DNd1fq^tf!y6(%2}Lf?88-lprk*;K+*+I zRPYxDK*D8wZ{-Wd8N(>U_sS7P9wa}IdpQXKQcISU1vXIVbzIxIg({efyLT`Et9-$7 zE-nx;q6h~mB0_P<9}GBs2pKr{>Flg_$ctj&uT*-3tKm1qp0|Ry(rUQIQl64v2K=QuYyqR)JlPKPP><*vik!|cISg-?F(g=+W z{FFw@mb8PStWpKJ+Kl>8qONnN#RFsPuo4(bk{I~pc5@%x0e*{>bwZi779IRY5=gz- zpS0kTv_p76IPf5W?|Pu(f+4Y3E~ztH#2ruqEF$3QGn2S;B-frNw&1C0kNM^yDQ=EaVQ ztO-BeIHBXVm;_O;<{N7RN$y%CNR#_@!a-a>3W5O>fB{1<*}Z~6Pkpk>E(AN|&vNnF zd^Zw+{3hmEjcc&*1dZ1em1HRi#Ba(AQ6L9V;XG`=;4&=ej!;y}aLbI$dUw9rQp(@L&UJzQ$1Wh8o_4KGwQYA0SxL_^YUYGg@NPo-R_!r z08P;hnOP`3S-eqiP9?*EtE!Ne_4$IoFfbJW>{JlxHn%1+h5@~zuX3;)0DvB_&)7F# zFsgzl805@fV7Ox--alg>^^LOzj&(~F(VbF_uMb72rtmfgz96~c_2IZX?o@-TIGxM) z+Bo86MG1*vTd1gnqvF2g3~Pl55=b%0(hQ>j!PpN8AdKd?0U&3pv96D#f-(6bUS_>s z_xt@DA~nV*i=C{j?xHUIQ>3Tvak|{C=%&;A^>W4ruS+rS#8>+_Pcg|#8Dzx;`&5xd zlb0_j{Z;^ooNKKcu;M#kPzN97D0Ais3F#ayqN2F~<2pn8++q!ofFFBQp3k2j@4w#O ze#Zp_0HYtdyMsm@2azsZhxVfhgM>s$p|4eSh($MNgCYgm!?BS-hE8^A1B5kTm`cV% zOswLRJBUXJ8$>E3U@X&fl&y_Ocv6P+Krz6b2bvyGJWxE4LdslBFu)^c0A?0`2(J== z>;2C5A)6frpz2+c8e@xyIrp`Mv7(WTYd7VJmryG(><9+i&As6L7}`ti4dLy)QztlZ zYdk)`&?1H40quk{=N*MW9oZ2jq~UEAq$zIPoRst^EjV7@ZTNP!Dq#YIule$EUOpJ8 zg#fxsnvTgbew#I0W*|IYe!p3~-G~tWkl_dh>_@9+s>{>55p{vnf?U zY(ziHl?4DTXQV5NH;6_jmFN&BL-v5We3(wkw*2*{t4rZW(wn@I){FH=3|w2F_aFfW zkig>oHl}aQa>AUcj2~YR7*vGVU=VK-HHZWXU15d{d4lkE`}O|*%Vu=QU#dzJS zzAzA3n25V3!Q&3TVZi;b_J>;lU>Q*b1?jhjfdoEsZ94vxs*>)QQ6IaH;;=mhfCn3l zB#`&ROtmpjn9M*5O8?Y^mk|TapTam%GS(CyMg!F*WAZ*X| zYZ=#eJFUg$D>>lN2jmTH$QKww0^xx&YsHE5q|fHHw^erI1$wf3f|w;8-GX=wneE0gCc=v46OE{*6$cFT>=l2+#|nx zizC=x1ZX7~U;tO7MO7JeWlat`V0d8QOB|j?*HBL33kL1!*L*=`24J9C@j(1tX4$H2 z0|}5WG+ikxJb(eVwff*JStOcsDNLr;2oC^2^d3V61|48H-~}jw%^I0_brkIk)a?F9 z??VM8i3d0rw_kLJ4RV`SNyjUNEA4Ax{>>BbaT8Un&z-mrLpYKkV*4@H}zuPp}P3q%L3Pck(O zZ~4(f_*1=31F;Q)$ORZ32e0vwzAoO~^oZo)QRjV-|Xfa9pJZYS;af3ljnYcKXjo-h+ zfZ-k(Xv1I1*BMax;(?-(jOhBdz@TAZ_sRM&014(b+Tu-AP#9$7B$N>wrr52n;c9V)e>{g`)SxTl0y~`fU9HN4L z-LvoX1>bF!wcTig3Jd^%tb#1iZrJVp;t8$`k1uIKtY}b7$xEZ4A_!n;AIzEHVJ=+2 zU>0`_+~WSNKU{aa_v`uHR^c!9zMfDbJA)1ktO6J@fSfb2iwABQ`xP5HXwB0BB&vBs zV*ns&ZaqM{=l?6xyn2KIubL^i_<^d=->35j^F^udq6aEb;8O$%1~?S}OlR+FAx~GH zE(07DM8_rrpbBTFM#7v?W$H%j7Y~feu(^-5eMdJ31Jiu(ft907|r4CH{I&5uPMhrw+Ahb*GfO>F-%UA&MlfIt$uCmG}n-o%4c zzA=ssHWCR-z=%g%q_P@B#1uq)>WeleA!j5e_hBpZjgN;YvXg_aYo`AKK%Gq2Q6sCY zasQB8-tNy-B44ckKi;!p_{+-@L~FKAjxK2;+AI#8JE*`d1HX8{s5fAn(QP#J@C8Nb zA%{=_y+m7%lLc%Vby3Y2yzTZM0z=s$!K`0_No8qmO5mk9BY(Z>O9fWt2zFdp$z41U zU+-REpt3+SC3Y}S3;ovRCLS=*1JMuTD9ZpkNEp&ZBL>Dek*#CyhxH$(e<0y+474?; z!9Z3@;sKX8^1w3&YU}%*c>oi*U3VJnb3UB8hK>Cjmwl}naVI7Y)=Bvq!S0R#@B`Lc zTNK%pW*E9uma}Ym4XP0a7QJ&UKPM>p4@;2pGnZZF91~zZVL(TXtp-Joeb40e#g&`Y zwcT;%9R04Vg5<;P!*1cbcQDY~7&z7bMcN!eFi`P++d>2$P(%SE`mMDJ?tpSHFhs=K_4pNPOEMIUDCswFf7`O|AKQMqI{>A`zP_<;a;ED~OFd#Mz z59~72u{>BcSXs)g#O%t_0r5+a5RqekxwC1f5=7URVGh{A0D}&jVTviF6;|Lu7P4%d zg=VlzEAa&!N56uG6drRQ8`&p*VS)nKI!I_vp~0YGKrf^elPg-1$?wyNkm|h30ubv! z75ct^y#GM^FR!>~8vw+EvtWchi+g0FI(cGZ6k)Ui0KjC}W~Eq$lC5IhvO(=V&I>l% z_mmQdBXEE&tU-Qz%dD|K?IYgoZ;kvPL86QHgjPk|-0OfEi|W7eKpA%?BH&Q;EfNre zJ6X41{SaM5IV6m79!}UdrMZa^%L~B3Q-bJ01rG*j{P4iQJvxXUxW|U)Y_-wygqd^c zd1e?86r{xw$WmS?{g>>>Y^0NLG?isyM;_U_06*Vj&QyGt5q6cE%ZeVd&?)q8Q z0TO61C^pE`9gna|1VJKl5HQeCG-9BTQy55}Xx>rbGd6f(CVQgOoRom2J$691JmGYD zyS!OWdzri<9~~7KROQEzlGXa@#5me6YMK2j$jceCXSQbl%x0r@er z9x#v|OI#fNGkT3g$_cauM6AyjWS5~*hT(z2z~6e{!3GY#Fpwl+X~LR6s@M<)4!J@F z7~e1u7zo!is57j*Dl|*=*HXDa&jjk|6x$2v{BC2n|IE7G>{l;YH1ki6$nnNzR;rN! zTL9#f3)O}lBzQ>_AUs@3p`wB+NXu=GC2Md2{mx zF>Z!7D~ALc27v$l!w=W~@R3aCWfA(xu}5Kk;+L@wr_Y)rQ9w4DSTX(I81Vk%={<~U z`Yc&EZwux%7$^<|m_Q=4Dx!n@uEF7p3K|BUVuXkFA8c^PKuZ+=i2;NUsBu-+7ucGz z@`Q~F+P&{r*e4+hU!F5j1)E)T*RrDqvp7z8 zWyia~;KQU+CgP)S_iYqILISsJGO&+4n-6S6-dF*rNjYAxpK?ChLBgk25F6BnKch!7 zq_{#y>VgtcLk!ZA;Tw`&$9kE4A9TT1Genjs+7Am zPk{%XG0Hb03#vsVRE)D* zEfdiU!$BRmA~f^4!%=v}lfJcj2{*!;3!_%?KLX2sR-T3jfEfvRbW<<{6&|5t9Q8Hi z+c5wv+fw&7BG6;1j^&_%B%=uqWrtjYKCx`sxX_s-`sE~dbUj}2!!=$w4e}ho0)QV7(gbdCL9|WBX*Cuat$#)Fd#{2-ms>>^KmyG)AI$n(=-R}TBnghS-_Ws z;X%T%VW6xWTYojC|K7p_$bT##$>fpaID!&Iwmr}lK75m|Gc5i?d}7mAUBt-Apr$QMmlm>Ep>>wu$gC@1dm`prjGOG z+c{k8T- z-2rC|lt1l~Fwf5YM!#gaL?>foqU!zax0(>s!Kwl#6C+|sVQ_Y~Ilx2l0Pn!3+(eGs zR1$tFXaSh4k#t{mBjBX2s9O86@bt<2!f21jde&&Wx|# z-ydfRJk>wO1$P7R_^-;$$Xd-{Ps-@w1@0%uS4Up}1AN?=AfgFXI}pY}d-;Mp2AV2p zFer033^Xw0n6{a245;Jn_xAil*|Sg}ezTEne|??O_-CbJh-+RI#fr}Gf!RXY$)mUP6gC%|_qR{Gr(Vt^Bg(-V^Z-`QqWq`NrUzyT-zM4PH?i2`8Dhzbq0|V`y zjS3#`PY(n$WY&=aj5|oF;YqHb(nMq0u<#I}_=JaZHTDcHX8x#9vTqxz*DY;f}v z-iITORd)0)#KQ)pN9vQ4u@4*LBFJn#tlL-1?)~k}UKv!G-`ewcO-jRn+ex4|CZE4B zV6sVgsHm7Qkf%b7U?AI{FP}<{^)kS_-APbiro>voh7Nhy)Pa|xXZAN+06pKXz-Uu?kZoOJQrP1 z9T-T1bDApf`Qn&fX>@ln9=E$sgK@wAl$y)vrZ=o%*S)Xq#HxhAKrb^lHfR`NaVB12 z>9ULC=%~Vmlirh2uW_bffWW{&)+CVaXrvC@1Vn%QSSjb&UDS1)&+^+6zvqEMxTqAm zDNv2>4GcDM)3dcHhGK@G0#{H4HI|VEF@R>t8*yJU#=$^x&TmzPA~~ENH*7y{m4kyI z@r`CCgn&Qsps$($n7=4C3=I6a^mAa)Fr0aoV8AcpS?3#77EHoGYvbGMPV3mE<|Dqr z3?p{{1C=*EMG4#s%<4E}|G9++zF{B%LaQltYhOIz8vc@n4>1ty-@#xrE-=t?%e6R> zHkK#B$pZ7)`Z63oOA>4Z3kpJw(;*S`!Dz;f3r3VZAp~k+0$Uqzz+iwo0}_qr<3ws% z3O(R_-eA!42|6&xfrq~GaSN0d3v+HCrjKohyOslyKsK{1Wpw$pEJaKW6>rMVhHKC` z->t-Yazu9|Po^MhqJg&Q=@bjTBn|AqT{`g8LW9BpihI*_O%ulS^~0uS8!bgQ2Q6OU zIP7I@n+3TGLaTBD?B2Pyc%m5k3j;v1UYj%o9)s%(18f~(@azQwn_!?E1aCSdDMS)j zpXjGdf&ut63>|#4enUd@1z&n#tRu2N=k+@V$`?oxR2fOApjMuGEDaC_NYcAnNWkt- zwH-8J>#4kPTxZ8G;Li(z#5Avy$&1u&3JQ)^j|nJo4#O?Wz6}HH>M2N|g`wZl)$H4h z8$y^Stl$?MOlOE84mVqP%}iTv)*MPHx`|Q81?z{^kaU4uO|nL})7kv;EwefH0k#$1 z)sK_Di56XR(R*e9#d;Qyde83g!$}e={Fa%%U2=T}wLR$8##(9*G(DLjg#CvsS$^sG z(0=q*ZE9B5OCXrqmiz!Dv%OhBZCRo`)gq9qI1wbunnmp0CQ)SL0pzA(w%EE{NxjpX z+xr_TavX`>)|6#!TBeZjK(#vnzMuJqfkcSkc|eZzD>g(0!9a>hf`M543j+lPC#TNi z1jS||rfQ-md;*hBZgy8qj%@G-)Ix5z8IX5Y?JxR%YJ*f+A1DlUH|}knr9E>8rHnQtP~UDm)ocy(Z($U+bueudo~5_I)xP`flhCAFG~nvqJ60 zYuB$%oa}t1_Rl70)~Xn!?k)_L8KP6lB-}E?P1Y1|a{f?lCPJZ6ejj{nRfilr822`Kw>%b$RYe#*+>V5R*2p>p<%$xQ20u21v*x z1rK-!Kx9B+U|s8WpLrlDf;$f+HiUs1m8F!rB#Rz7qHzN8j)8`U$ilLIJsK&-zAw>S zjO-=9nHlHB0Uu_=Rm+NZAN%X?6vQf$Ck*ntjk;PI_83$r=rgFp0}DwUL1MZndd~q* z5jB{6PUC^rE#8oW5)$i$fy0$7JJs((=gI49XGgF8&C}!YQjYH?S(NRb?DQ)$zn3>q z^$~tBQ{&Mfa!Ia-j%~BRv3{#FtWv{2Fc4rg9yl8Bp#rS|poNN-8~7Pqxg$t8R`94d zqP_1E2kjowAa}FhpQX5?6@!6*q)|jL@HFu2Bf0Usr-nmVw5Ac0#j-q5!h8%3GW;K{ zA>j)H$r1en1J67F2IU2~fI-isW$bHAKOP_i6dE3Yfm(wA44Un0@SgLCG?4JqZzk`! zLNnvpTjnUEz9o~g-$i|Srp3(&%h8oVCGT)TBY_&`?U;RWzIOsf4UKe#GYta}Qk86( zTrjgNdgOrYgRKUh_SnkQk@5X0(E&~vNCH#;Hl0q2Uf75ec6Lm);5XBMvVXBYd7qX- z)8+y~{#ug(n4ydw0Hi$u;Ba;Z2>^giEc56XFenYbExu4r5Ez6C+PxG8F8=znOe(Gj z57awH^7oN@iV%BserGs7H7}q=$-;2kw>9wjcjI8aBCw+CfyolwSmrbqf_o3_wmzCwVDnqC72_rziD|839=W^-{xYp#S%>ni?EbL>hHDZmDH~7>KqcNs@zmP-mSf{i>r><$TO4K@!9j0aqywcw=;@c@a~ zEUwNl?Fj=E+xk|P7unT+=*CD5#|e;Q^M z5F`xA0@Wm(x0}wrU~EBpzuEPBc~LW)oB}U^|49OK3K!v|^?f{o>E@PXgVG8l1BQl& z$bc$8Zd6bh_$UnAVbJi9@g4>U|5vMBZ9Nq^zN;=Eh9iM0ED8Y1)>6v!iQujnY{Wq0 zf%b;~fC0crFHu2!YomhvidiH!~m$|JPEKXs=i5u5jC@yGDz0@A_*CQ^S=0&QDkk5J(n&||!0 z){*7niv&DUbvrx&v%x@6fgf_dd3?kFUl<5ixN$r}LMZX7M1cV%iXjP}G0;3hZt8&n zp7AaSA8|opAnH24;LZaDfKdkAHQ^ltlt7CRnKhFFC{Bu?oI z*qrl$0d{W~Xt(L{$u)#1v+H-NF=7s2~HshJO)4QUs|XQ9YPBBf0Ku zM4(9y+(hviu#{f;f&xHE0{q;3LCAj?a{_k^Jd`2r*O-$*n<^-4${8~BmIk*; zh5^Z?7DvP{q-X>iRDy_K2nHeoM=>x`K{)~zmz%mr1kr@_p{$Xihiv7Y7DP@Bb5{=4 zENDLks8esi71p>83Al1^Yvz8Ug2x%}Y`|y?Ictf6R&!1j6b1x|O%R?E4SlUU1^@{n zt&q^>j1tNvW7BwGl!cWfwBU3Ug!eSjSFWG}ghU4!!sY7|Bt{Sh0BUto9&&j5{H?}d zzPZHiG@-$sb}+vt4I3CF%M@lv{jG^ek!kj(US)uTgz1!o3GoY&h((q2TCLz!ZbDZC z5|w#gl*JjoXV%&ytKL5|zBmOtJgkRzl^%zkJ!a(tDd)EgdF5ya6^5!0j`>lo;34`j zk3|SoA7~t9DkLF8d_e_<6$=1BaYBvvxQ2v;1V9`?;)0(r06b!F61DCThUErh=z;;k zdi1w=tE9)>VEMaT`Is(_t-mZj0;4))gn{oQdJwmzGf6&}>mh|KE30`g&yLeF2pz~O;7!Cdek z82H;4_?{gNjp8UASjLy`tnU2u8(b-e!EU4CxQzs$Qyo(CRzPYH&UrwR`b000T_Q1ZZW+AIuz zr~Mic%>@(y+<)plbV578|MWoP1Z=P$pond|;t=KTx_$K`k34zh?(Hr`bs6J+BV(oC zbkO<3z;B_VvL6{FM$upfi^4`$0_G%<03IR>lCq|XT3X=van}Qph$RUE2@NWc1`d%l z<6CX>;`+xPwvxshY@lGP>|tW?tl&Z}3&Eo}oI5NNCdm#glcv zbtV{)Pwod~^#fn|fhPsDi%rfee1mM-oa;x!% zhrpnGfdje3iX(Co2E>mV>WHmJ7Z3nEFwl<8Qo#TTQM2=$W*@5os`80NS7nfcZJiXN zGgc(DT-h}4?_u009%$qJ>9GO3C}Ph3{N&6OQlESg4A^NrKOO?Zk%cWlXc(xt;BO3w z3+@=;5&p!$zW~q(A@YC)k^gA@P(hxGfHnf&>-+EH_4jc69F9LcN*1AgQZODNo~8Fr z+2csW(b43k1_m<2oO`cMM%T5xL8SsRU09~a3}Dbuq3c2jI>Ac`A7XuvNL80c59nB< zZ{mEsEq@Viv9;O+Z*0tC5r#O^0FP4;Gafv~^bd2hzVm63i(0a~sbj|*B?S$CMh^)% zILIKS!2mHJUap^G*tn$NcC~5pTjpw$p9(+f1Op*qV=Sw=$e6plm>bEx{MF2-mphP$`0zE565uLj{J0yw=13 zRBX!^IMXmtvM>P10hb~5?bhCZ_zhF*S>CqCA66lyx**H(7(LN}H&+pw9#9MuY$Obs z$1iw~1wQBVs9zpLhTw(#{BL-}S)Aqg81J!jYNLw$~a>WIbgk5@%QqZaSY}GG0 zvs@T20ZeDUWnr2U26}9~-Chm{PT`H+0U%ps7cJ<+GCBe2Ad0bpq|G%LVwH6qEzam6 zfe`~?23aOzK;=v`F{1;3&G$M>r#Cx1VB!yRrb{Eq3bZMe2@(q7|HgoU@2)|m;oJ>+ zvyMtl5e(#KeFjAZQ6E*;sqAiAdTI<*%*n6 z2vp3n-~<_D`GljzWt$zU$%L|klZ1!w<`)QnQV3xNJ|feOjR(RHK|-aNgbWVaQ*)8; zvA!zP{3A8Lc&QRGg#iHAM_f;K0^VX{g@O%u`Kp8l#Rg^NcrkuI zu0Q0!)^%%*C<-&*Kw_GV=~2OAJuKH-U!G~uWIIP5_y-1BjtIB6xZp_-6bAa}z-sq_ z|A2w}Dqql~V8H-FAVFcR?rIp2Rg+Z7x{uROB^=pw#LqFvB35dM-Sd%}tVacDtG$WE z&SaCvoH@7*HQU}s8`!)K57Yoj)j@<}>8Q9-GYbnvr$ZcWF=sSG+(*)h)o-ix?L>@` zrEN-Ey2Tm>yyv(*E`??@Kb7G+#d_~*)KwRlS!i0Z>49F0&3?w4ZOzuDOg#W@oO&=Et++pw(7mV(pcmNwP zrAOA>shPAJ=k4?N*7htXGT?`~LWL`GWvS_%VBZ~;!tWa(Z3&MEDaZMZ$V8VZQPx)G z`}hbR;h4Zvpkbfti4ndILzbayTzeWrXVhEMvX)}X@X;GEpsx@@>#jf|!jhBC!j?eA zMkw2Tic#fo2Oe44s#jIwht>AVOYC@dyzNeJLzNk1)Hg$C$CyzrHdJsNUV?}Cj>MRp zh`>Qq_{J8E!KgKs^8GRuveTXYhy7HK}V!*rRhqbR;-&!8Aw7!LMXek%IV_f#5LH~>QGJbkA55>yJTdvillnK^E=(VzDxpxkbg7oLmvE1 z4$m0yW>iqMthGM91%`JF)NIi+25LS2e~E!-(>FXs(SZ%yl{+XT#77_jk?D;TBmfSd zy)vq-0er&%U_hPH{4zzt!@z*W{f4-FrgFGi!^n^5x1tEIp6ZukaK%{$DV|8Iks2fg zy2k9rol3T_HK#yoha8NTsV)mV?qh^*pdvyYc>_mmjF5ub+81&Y6YQMt@dqpk+P_&U zrOadKEu8sD$yBLHvInC8Xp(?Ch&*8EXag-2k&?wUt^snwAz_1e6{8fOA!gvS>3(7smsYNho$)dXc5ee9!JjLT4+j&ph88oN}yN52; z*U7rHMF+(L|8op<2@N8iH}@J6B+$p`UpjE)1bp6rk@uSNO18HfrnPvhMm9VIO)U{AA0F+{*bbNKpIeMO)jvz zcp<}_m9c0uw?1)?!R0m&h`#}ev> z$!hz)%+6`rl_K@Sj)sr@oMjRi{SIt!ZRY+11CUTSuXq7f`f}qdJsDqfy2plpVW9ND zod;k*7}foOfsq8hMFfS45(xm%ECnY~0@E(Z;p?vs30QP<{JFH33zM~kuz~^Qjy4am z@ISlYlCLKjsuU7P4Vh8Ox9NNsI7KKXW<2o-90ZSG`XfuN*LWi+f*gd9ZFQADMJ^{; zSZ0E$Iw!s$eImq$fxa_?(2Xz%8?3d(j8g~<3^wpU5ghjG%Zoh^JC!FU<-5T$I)q?Q zSDr9DZ@d@bCw^?hKPL+e&KD0v8#s_*R+@4+y_rcw2yi}|lQc^hSS}6JEn&b+RRx-5 zl2il|SSFDR=dzJ+=l9<$+ZB#!WWK;nHF?kg(7@niYYhYAu`v>kMFo{Erop~=pv@XT zX~H`O^d1)NlB9hqD>b@{_P1e!;)Hgl9zy~x+3Tfdm+R;6jrARpLWiGVAYnZB<34G! z!RI+@Qm-WqnCatChvgXAR5q1G@DLJ+Bq+Iv_LDaVDk2Ojf9O4760#Fx*duFW$pBe( z-{(YctoV9vSAD6ZP|`srpsjC51y-tJgPcJEn_7|p0GstD{@Q;!&qTA$)?Q!aoB8Ew zavgqCL2ZfYp$~em>Q90PCQgeBpcWbf1RH!u0MHKVJGE;3m+9$~xRtats9lmj z0`r`s)VkZOC_dGUT*D&Tz;>W#lke0WHi$O3W1v-`6xyHJAYYr7DG6do)M@w|Uq}@R zHw?%THBCqsW1qE;t*B}*;=>sGX0JK(ALn?$8vf3*f zkN7NiAhD1oXOhUn+r4$+!82(IO0JtCI%$te=n4#F^ z+zbIz>TU$m#@IX|OZo}`Y`@7tSR-@HYSydOva$q|VmWDomOJIb7`=GFWdnd4$^8O3 z_aRa6|5bK2R*fsc622MS&0seJ$Y99;GJp&q1IPepfHN=|m<%8T$N)0f_kC3}vJC8f z?{Vhn2w9eGb#--h&yT2Ndf(FI0pkvmG32BJW`#Tv`2Llo0Bu8u$*Ehf-KV&C6}&!XFr z<&{{TodI|#isX#^EQ-U!<%59+2rk8s^|y!tKH!+Q7h|0y8_ZU?+R-u|7RS000trBdW>+JS3EH0$H>(LkR9FA;JKJ zNN6xVo)h@C!NUe_;cK@E21CFW&H>V4jK{zLJHn_?!S)R`qR^Aa2 zxDgooH>JfB;=$!P(owHxEIJS&hq}b>fCN_}OtV9Y#(&wO;{N?fjCkDB-|?!5WtP32 zL}@nhobIpP1A~Et!2>Zp0GRF7H$FZi`50sZj}b#ff?^CFzMQ?Zk^^9d%+U#V ztg^LFrtmM{jW5NQlXuKi@25)7CbRTGXcjObgp*ewnNe~Q4jL0L((C^HzKqs7D z`HZCGVoY?!#HfWUYO_{mt}oA!V%LFz{VcSz-&PB`liWS%^tTIMnSjT?oNq||_LAim z?_c@aRJNI`$ULyryS7= zW0WSCb)9gG6)p(qHo9r3nX^>dh9t$RMIMMlyy6e{rwtf@fuH^>20#c5$PrQ}ZVthP z8)z(;;|W_M`h)>vK|72l2Bsc}(WmKaeSvX6!VM5&i4i)gb}wQeS>YQ1fNjzxAr%mJ zob1LlXN!L7e{LyOhO7Vs7sS4JI*mBoWC8R#$gM*TA_buZQw(*&0|^4FAvGwRQ5a`5 zHE)NJs0GnGKnMK~*z)Z3r%`|*gOu+WEObpec78<}{RT}=wc$jHKs45yPE9Z`ev@S2 zRzFTr7>YozCBA^`!3LS>e1UZ3hwv}=iady9lOY*QnK39}?~_nLG9Zx9hGtM0B(xC` zxC6XV7)%T#93&7lFR(^5cmNEf9e7}3Kyzc|#pnTmc1O)F`(S{&==P<85KZ{T_%Ui< zV1V)$V=|eL&Q6AiMC2#^Phk+#!v?nmg*Y1V3+`$Ndq5>Ro`evPh=w*GcTQ-yXK?@t zf%U1E) zJk!P<-*`*i-~#I4w6lxbn_KVXuXD!|TyGf~#E{gi2DU*A81&8l!UG8k`ByeL2tuR4 z#K3l70GSbf;9tVMumK677qdu|GhbQHasefLlYn)Ji{Z||;Q9HD+vos^pZGch5{C8H z7+@b5z!JPl2O{4bRUi)>It{HAAM=3Z`5zb%0EZS-P{2<_C?|jc3R4RPR03$uw203g zv;V+=vA_qaUgOb;?`DED$dG`G$i&K!Jake002KfULjX@Sg9?yI42*G281hF{#3PU( zOk-cZ9?K6vp04P^Lq(;;^Rtu7YbJZ9f0m)4bm)+hV^GGBWI0L(7(cQUA>x@T@!16m zXGKtc9p%TFBpzT8 zO$!gGaBLAa8K$ypEKm)$CK(Jks6!sOvx_jX;G5iVA%SHlfdBx|rZBjn<_ZsNo)v^D zfxDOU+h?eNyr8K8pUXOU02pi14~X3{G+sRV1%Lta)v+b9wYkjBzD4o{RiaV>>BtF~ zPgLXkgbdOsW(Qv}((n0}5x;~6jGG>r3)Vom*jyV5;SGrN4(Ui1#%y<-`+oCI+J)-2 zX64XvO4f9)VQBhpxSC&##F=Z}@ca(f7~}|@un?4zfU$@~bB2=gi@*jM0T|GoLkJd* z)CnUNurnor7?3C?5|9?Gth*HhJk@=_+p>t(69*snALu}_&F~MF*>oL)3-!s*Gq6e| zdZilgSaAl+Vd%x&Fn?(Q+@47Vri~n-G)lcF7%&~MyU->E{F%lAW{E~bWf%#cH8f!z ze?)-;2}lTr?{pUUYQR9DgFt!zgcx|cWC0?Vg3;(M>3}0+N{U5x3*KW&$^wqGcQzuS zf5Ue$aiC1Z+R+&|;-U(cm5>L@Kfu7h)B*Tht^gh|lhHo`g8hz@0T`?t&cDzCD-7JY zqVkT>g9!?bMqnHxUy{3#M!(OKZ*&qOrspDn!Lfo4AdzBiH6zKSk0tp9)eO%xh42152fm^kxboS6m|mO^ z7s3G90a1Jqrj!%dM^}IWSXx)TxQ7HXt5kTsBhOX{8!WSU4Q8nU?BnZL4uyw7kN=&jaVL)i0ogXye zq6a1hu*-r0slc@KzyqJHKlvfR7#M)np$j^UzyLi3V4yvr$PXC4VI4Pz#{H}eS8i^o z6yfPqIBa;hgis5@{9IFSl?w1O12?P^>+6{8G>&5|V8F!_$_b+ur3v>gHE{Rrq*0qN zh=Al$dRE;($8m6CmcBns@2j>D0%%c8LL>GU$N>J^0i|(sFv<7dHZ*7>rlpu80F0N1 zM>2ZlqK#lNYKapDC4^9cqP9q!Riw=e@43J8Q-s4}_s9VqyD zW=t3iu*SpKFBpz7pfDgnR}&TkSRWopIH(>NvEUmFg#6>t!GJNEN)fW~V)OLDYO&{* z2UQ&k!b&@p=VoHSOfw|{H69IAAQCW5Jo*9M2z!JafB~_Fm$Z@M&FT<=!;pc!=38(^ z6vE!bfq;Ier_=KS3^2M@)~Pudo9e}CKaTSj4ssoA-Al2h&HxYK^7VReK8uz-y!2n+ z8%P8U^c!*o9CK^7f>^!Tk|tn!1{-*tSp4BZVrN<7ipB^7iwVI)bfZX65=<(P5Wv6& zVX%AQOjH3#;Da(L1}?qf`x9cQFOiFd3eHw+@CgI_t1zG)VIbo0TMSTVBO65)Vwdlg zKt!M<&oHwWtKfV-r#EZ#*c6P!}k0$THd`bfBm^aq$yo>Y8|KiFi zB%;D`BMt)5qXmEiMOeBd*bqe-Oqi}BUJ?moYSISlJU&tLdFd!4XrCyMOpq!u&Q5@^ z!Ym935Q`G9b`&tQTrfDn&INj`2s+#!cK9+XqD$&jkAQ@DL3R)ZSa{&{XHvq(g#`eF zg98RqB_Lj(B`?503l9uUc$^m;cmVz1KoEI=hYEw3vYfz-!p;8uYWqPfpg6!%r6>Vo zfl*+C^C}SWiWuN!ULF$No4FZ2boT13K1j@^gM1K1|bj{8Z~^E z1q5S3AYlQ49hO=4X)Ie2vfID$aUnW6N~J-hp!*=ollm3U7@A@LHdu_l>?9VH2RhR* zy#}ohWa5uhOkY*Rz|;eS3L**ClMNS0BqGGD_8H;bn2$C6wqW4#{WmohiUU6KL-z+Z zG{j6g&9VD!T^RAN>9Y_VN67d2w-sZI-l~EX1J2Re_p$*GMo$ta|6gq_t0pes^_YHf zZ5TlDpOh0GV9Eg2$J4=yDWu6h{2&$dEs{ogKGC21ETWiL>UCrTOrU`><&bST0lSNk zPC3a?B58pg`GFY3cP1^p!}RC@@WYw-G62KwczRSHYn8m^$`CsP+HrqV3Hq05vVmZz zHc%K4TmTHr05%8&k90H`GG6~-4NNp4GZBva4pw;h{cDARxdw$bBJy{W_vQudFk0n? z9pqqF=BG9zLW$j!KP7$g0`BDI`Oo>S15_dd#6Y5nB%s#^Fm59TFntnUV+4S)=97G% ze-#7P18L-XaKZ*lUD7#7;86KL5+m?mBEI%jGWbjS^wc{nva6+#rE{qJUMw0>EKKV1Pn|MM8%f-fmeu z|Bkte#&KBv&EQVFFoKvGKnpxu!3qO?h^B-XRAp$3=@$%`Tr?O79!p6e0Sxf={nMY{ z=QrkvmW5S-E7KpSfaB_cu0m5bNS$zvfhh)3A6R(cZzK>NPzKCKWJgAtA_W5#1DJJX z`T+orcraxmWq-5*Tira&05H7l*&SAp=Tk5wG_Zrc00XCKyIW)@zQ#Q#-!A}+>~Oo= z$h?|3EIN)D?s5NWgPapz#(YnFdBV35pGS&hjk16TTN{zd$P@rg@zin#ZXprVfCK;_ zNU|eiP%eh~=_$V30tvd)_$^@X`GtimUl5$Y6+B>W42tS7Iz%U^AyZEPY()jYP$Z0M zgA7m%unapGcz*pu(D^45lxEFvG5xZ$@PK1V54B=*!@&ba{}u_$0}BSUbz7o&)L@H3 zF>Wvr5-0|6d8QXJgzSW8CQcbpC4g(YTE!fCWHE5eO*1s0^RX;2C=xglkg(`tq`ndV zF{K7nqK*%`cuNfm0OHHfY`L+p0Xt9xTTX!0F{L#|O+X0H!M*>+h>$~`e*|)Xfyb49 z-0;`#vn9$*)00!|f`pnoNC-<509Jv*;p|Xb1`qf5TVOye;G3`n9knvP6&Bn*y;1eQ z@ib@w&fjwmao?2CvXU^+^a%$XF;WNvU-BUE;3AJN6czW+AB-?z)Kk*KZ}oskfFc$i z7#Khhnt~lLu+$074XqKSOe6rx;ckZu=LoKqB-&VyYpwm)6Cl7os0 z^Z+Nfjf+_B5C-J|g+Y1@MM4@!dS-lCMVI~^vqeii85Dtpz`1zI!rgFc?TF(G14urT zf;kdr7aqy@JcpMI0lte80agYNVneU5S>bB(`o}knj>gmF>x}VzjS|z;DDKY)&JNc1 z2;&4E9*Ny#aAdV6J4`*JUV27NiJJd2-GAWCIBUcApvAd@`mlXK_&Aw@gph|xv2sPp9QRN0nS7IbXe^*>m8|)O`cJqW zqsQF(K4gwf@jm1wJ6Kks=+jF#oWr_9)blYtFyQ0@fGzt&0Nh8w+r8@;53KLRJ(n)g z^szghm~kM(UL6zigxv)L%8lTzu;0_a1Kwaohttq9eZZ85g^_UJ=QmbqKo2l>6c{i$ z1w!C0k&y@Y4-AX~3PMVV#lYh;;eg>N+x;7BE-`p)#)9uv!Q=tUcWIw6KwStW&~}7@ z2)P3lOkD>jsO!Q5^;`=+jE2J3SaX2-188^I!wx=d5OJ##pf(t`*UFkZ7;xWamw^ur z$xEp%+%lYo(lKcrRG<{B^)DZ8DFqW3c+}=p`1*CcJ4WYKShCnU|C_Xr&jF6Cl8D-1NJz=aUR@;EaYGM z4yf>FN>T;DHyCIvz=@c`;HaLjJmC1H^Dp6`xgmzjPWp!A=fv~`f~g533BUk+LSge^ z|A!$2S#{)=5k8IscjOq`8wn?aNMmAUKvp8U$0-;SQZP_42nMVK+EQB}LXklb1sK^& zoreIyKC-_NpHxwCc#ns^4mKc@n%2kAn0ujmkN^fIy}$A*uz@9bFBni3&PpAA$K6Kn zF?ta7&J~~n(toI+7FV0q`q}E9>;wZmDT603zrFoofVb7}OU6}}2b5%^Nb5+;`=3sL z`hh85-u_^B*1cg48bBh@Z-GIyVm<{7P^0iGffh6*fq;iJ@kZw$oHMrnXZi(z!8aIa zEC2(9fB}FchD-X!9nQGcvy5D#N&ppHPGK;WK;>MK5O+4dEAM3h;yBEJ&Sw?k%?s(_ zv&)A2_~6SEXIpccNT5V4czAmPft+AjSTO)9#6V;NL_x#{7?u!|=5w5Y0u1nUtqj|z z{=;eD0VMRek=+FR1uG{U=;m5k$Jgr#>usKpo|jr2vr?Af#wIV|K6~@w3KV{0f&7na zKfP-LI{~?lT!GKhFd2%@e_`e=86W!pjflW6{dIbe#c7Sdi3o6lN34U9o1>$6P72dg zPk%o?y}Z2tA$g?6h5mecerGKgz7_i4ERxae6sgQg>|V?lW>o6i)APs0<&6t9AI6n^ z1B1qb1q1Am6nw(K*P%psv0h&dAO_~Y8Zj+4#dg5J=+D8^tE2{Rrx$xM@cW7uyGLH8 zwj6)2*Ao{ce+gj)13{G@0ZE|q)H41M81N~Iy;OS$3dDkNf~j9&5N}2Hs{t@{CIMlu zD7|1HVDMF}&j~H@QE7>HgCA@y6)5#PKq!7!e?%gx*%FZr+4v(dx*{!9Ky{ZRPy5%` z*LQd|qvohl=z0vK2@E6wDqt4DQb)y!phrgj(EIbxKmXp|ZQeh4e(qbBl6c;~U}9$Q zQG->Z!UM8_amUXEa=T}S6@dZXK6#)K;q!K4ps}EsJi-9qVPatL0I5MR&_M8I8(`FJ zO9df(#))0vi7Z5Ra`EV+GtDdp2C5}O8u52!fTF^;Cq2aFiv<34-3jZ)4lgNJ7(Oyh zo-4$53F47|R)cK>dJo3It-}l$Kmw`!M5A2^_-{1dSGNt{;89xnYCoGo#O%2kUCI*HNK7>NA z8M%=;Xs7@F^UvwYZ_G+#VKf$$;QC|`Ec8b_;wxDfdh{zXOdUM%aWAj(fCb}k3dIK` z3{6NlP!D{Afe{P7j3gOJVx}87@pnV|(jgPjq9f$_p-A(6gjGR+&r9s|Y%15|IX3i;sZ>~G+9l*f!w1~Z^vcLe-<9&_A_~2~S>XGZ) zXW0Ao^@EIn0iR3_z`l@e9ex2iRf7%xV2}xsXJdy{HD~4JGfK&6Nf}`vp z<2@1rt{i8Q=D(>M$ovZiEEMR}E^)@pET$gcz7Pv|ycf5E(_(!AgIR?^c53AwiJQ0c z2sUu^ATVeK!An8HPC^*(H%CBvu!LXl=3gCu2=bV_R4@hxTezb^0?*IyGzR&TtO3*o14LeKxDI%X0Z{Et z<|4$46fMNg@N7L)E;LHogPHZ|vf_B%wq4W|v!@z!8C1ASQ51wel_ziybAP)91IY`(VUQ3WV2nq5_9b~oBZmi^13Lh)X8uJRu*0vz zuLrS91)+B_!2Ug`CLHk0f?re%$pnJ|?G@6<79QwZ*c#>aml(RnMHNH_C={vc#QNFK zEp5(-`!Keg?*Jiy2g*JG0E)M$14lft#(;Vt(;i1Gm^|=_ z1p2RdIAB17O3@PoSckC$w-4{9R11Rvj!f7H7%a|KclKS?02Z182DO3FVXRHzkfFds z$4?=V;i=XQC=v<=I~u4)UQu?g(b>ZMxH(`jOauuKLJ*SiKSq2DK}3XR0eC%m7LP-v zVez%OL-GK|G!SOM`ZR7n|C$vhK-h%`4E8TLEOi@{fV1|P_9#mEwj}{aSsM!k09G(G zL>49%uqXjfK{Xu1=OjR zP$8DurXGkUOuCxfaEA%7Mf3pi=saKkKmuO_!2uHW>%spR)TVE0$_-00Qo~{1G|z2w zlIei~z`$rRG+^*w_8a;|0xhZH;Qt!B@xtTST^QIDihLXc(iD(f2LX^2;3W)TDS-N( zFfcE0+y%-I$EOPbgNE(#XyO87uJw%zkZt;Ist2&I=GNB0Mv;IfU?#bGVgKRNhdX9RWm-yF)gVWkmpeiUT3=LwS zFvt!nf|C`EUdKtSTc|z^fT59pa)K@|KTyO29^gR@Kq~{(`XGT(9OmGT|7_?lFq{G= z=aZU^9t5kkmV+qW$N+E9#mnm-W`yx*W2~vH$}C!Yy5Rwh9tJKFiUD)O9V2auffQ+> zVq{^b3hKgmH@AA>6Lp1|vd9MjN_vXw)fg=D@Qan!zyQ`41I|Vq1;arF!9c6TZmCm= zf#`u4=xUHa`;Myy8~2+Ae%?;kE)T!}BfeukF#uwnGOTr!aKa$9!4O3Q$3TKVu&Bt+ zV*O=DF>utP5+#9x0jMNQxG)7r_;ldJ5R?ayV8h>0{%E}L0NCIlrDGLfa)Gb`em(ph z<0=e-gu(eCe^bIRKXwNpFoX4c3q%~ZN<+3zP-aORGX2aMM+``43kD_(s1YrJfNl|D z!M&=6H$wh)@=gq>5-)Qzy@>XrqoGv=bSC(T+T;jxx*2kV3-C}~r%THr!N3?+^aTU6 zzu@l}0LBdm-?~2sWq@v{Ut`d?Z~{Rnnh@iWxUJzPrde6P7HH0NKFOvABXyxZvnJwzFVj zz_&YSGkSo;zha={KST`(BquLc6fc*AhlUg!KI#v0`ULa`yaZ1E$XNPkpaVfWW0d^13_Ezf{_#q zJs=g|1p|Wz;>8$_t6lR_ei!5IQ4|Y%pojU@xIY*$@nqDN8;0|SKb!QN-+G42MPs`*h2MrAzJ0{iZ0J};iQkjv&%6y!b52QLoopAEN7YwYu7%R_q?^-cQ+4SNxej^9*-@w2ep`5_B zz^J(mpd$Y+i_e4v6Z za{DW3W>Q5lK+pA}2lx(L|FjI~mI#8F3`=1B$ER0@^8P-% zrdyD^AzNzw=`7wK@0F5xr3aK@=_yG3!loevMg9XnGqJ$>a8k=l2^Rdw02UTNjuxMG zPY4*Cup)tRDp^2lnbf{ex8H}o|bXN0|SW#eh2%EM-{@t+uwEE zK*eA5z?6cTFA*WCpyYtYLoL+4az0o}I51yO2eO?QC;-@YCqAV_oHgWzgXn|^LdGw} z`V1+F^&MMiAjm*sdk;HKjH(eBaG*GY|F;9KnmGNvDAVX5y~t- zhel|6%zbooa%a>7#Xv&#&;wD1k%+2-$IP1u28_jEKq+VxkPnePV!*dFB^-gEG5{Bz z5kZPj7=RP$B5wgX+({5sRbXDg`m0@+EPs`E3~KlZN} zkO%6&0|rKR%xB1!-|~26Z&6}FLO=je47g?;;0Xf+LY|p_+l?p{C=`1s_rntRU6+Q@ zj1>cpBqTd%4?;*l7&!Qc!66n0C>3^Km}Me|aYiaQcFVlL`he8{ic73Mxo_&0MyHQ`7NI+jU#AwON!iofH5uv|#5ELWW8=Ns8;qc7VP z3sNY@e>L1D1;8mC|= zA%FoII}{Bp6tl8imI`4sFO9?yuZQX}J>+lOTO6KXV2~%>0e|SzM+agr01)9<0IaqP zVRC1p2cTS2!o-5?sN9BkD+b^J?gp9=Do{@32l8|Bt}wuafk>D#U@-q;_tj20fs>y= z3*P-hHGn=`cz~HZtrjx0H6dnV;7AV)g=4Ub-6es!-zd;+Fu;%ftOr5`2R0A`tT+S= z5QhjDMt?2+3t}KZ8YWISD2#S_}-%Um5)q9w-_-svEfi z1K1dmWkg`8Vf6qNDlh;Q*nJ!fh(o@uNzI}O)dr)`5lvV%C=C2*V^m=eev1J!M2#3G zU&H_mAm;V%`^*Gnd7=`2s31R|J5WA}n`3m|qWc#BDHE9#a8R#L;iyAR_*WQY6^rnI zOG%6=26i1jCJJOIQ6d5*0!hF!vgHCAE)O}-okVBc?d?NW6WuW!h~7X<|HLeS$CtBn zdiRh_@z(KGhr|UE0kii=aC$yiYUXO35f;G4T}M*j%y4o>yS(g=>8SGV>`r;Kl6J% zFsK_d@r&AGM@gU&0n^u5V9yXR?e0yR|7!GDU%R`1SAS1p=n;2P9t;=)2@A!x4j?HT zKm~LaWkdl{Ks|uD2Oh!<{+l)kAtMH<5)c~Fqx48nV1x#BU`p{M0szt=I03*8ze1M} zl}#ip%(gNp7zhJ9u6SxZ%6;Ru=r!J-@J6LzX}{Lbw%NhT;sXPb2c-og1>K0^&GZu_ zhY&}O!~M7Qol6Jq`3hH_T{Kkv!G?gs$OU)LYY&qNb) zJ{By6*6!j&$FXru{w)UBveaskkgabN4~2m{B#g#_nx4*rDgmq?CBU#@dy@e`{$(oh z5f~;UL;}g96VRd?JJ5)^8!qYQpzkY9e;#w&#S_yrZb5(dpsyAQb1N|TQH=!)4_GH0 zJb=BjRF@(-))xT90OpIE3xfk2m>>*b2FZc+;!G`U?0Mqu*x6KQjVB+wh zRlng%6WZ5oM^$sf#sYr$5QGrIXhym+UeUg|z>;PLz;z>;@_!>j2pnVzZ@`064?|?XKz#(PiF|2);<=D87Pvyo0Rv49w3@9Z#(%Bt z*kb)r@TqRhnF$J0KrU8Zb_@g~aDa_QknDJUuZFo#=|Q;Mv2f_=%{#eaFks4%+;GpT z@~gan+~hosPQ${Wm4U!u0RTInF|gbatv~Jl1p^U;T0e~d#5#3O8oGOif@GBx3cA&` zn;q2L(teN-oP4%^XaN#f0s;OWDj+vR@MClx-}mRx<}hM{c#WQ|rld84h`+DwyBK}h>D!Be!+x${ zcTxb5lef-uynf`7(>zzA7--t~83Wd-5(|XE(s4X7Fzg;4knwB__2pL&(|eb~05V&6 zAc8PFfFKOfu>}So->C;ozvX$*ErwYBMkkm%V153@{r~-mBi!(bHGO{0_?de5AiBO< zcuZC_G#q0frqTBY!>i(I@tSF|Y#G2%Ua=P+H^i4cR@+=*0BK-A<`+f2ceXAKdUgN8 zV-p#QoElLQ!*6*YeaD{}U~&K9`@mpeUNWjpC{j41~2q72{4?6o25gbCC zkpmP1Us)>#@=qPxh!(jH1wACG8K$2ADDMrB#QlXqyd!$am>A?Q7?|!KW{ACl3Je#! zuSj4TG}inE0}E`v?r^DM0KpFlP#L}p2|Vrx29&0Y9$3eMZ!jS3>+&o9pBUiB@{;(+ z(+2?R_-k_?_SHPqgwa3Ry+M$BTNo5A^aOzckbp;H?nwxA6dL#2AOT*b-piKbHrzi) zYI-aV33R16_KEKk0}=vMKej9o7cdY4SVoDW0Y9qbpD*L@>em*l?jN=M>IDGoa5okV z5ELQ?iUC-Cc&HJf2KvkcqmI-xFo9#`^?8>__?8fQ!DX8(`-xzHD8Qq8A%VNckL}Y( zcp&Ksxe4mj`oKyL7z+{wW>y$0A7h|wQ0ve5$eo$@2c>Tv`l zh=+_Z?kWWK3lKF}i;M-S=nRUvYxja-NI@4d4kTC#%tG-404V#u&ni_K5_d-e^ZUArXO_L-Wi=KrB-03xL{a<-d~<)P5`L zv)_NeO9wB_ho>k zWjJX5mFpsqB!Pto;v-^UO1>{4ASMnf)B}G1AVD@*b^?#S3MA}Lab+_!zjKa=1q`O8 zuLnaL6kNeo5~vc0<706rkdg^vXd08mZ7deYs!(}4Z6RSHsDlhyM)GC{^OHWuppmQ- z$^9*C!vnk&n;yuGe*=Rf42*i$AW7aba>L00i}qW)dCmQ4%LyK_xRe6XK+yu8&lso% z$lCA5S*76qW{dUz007pH-F%0ER;!8uN&!`ajv!iOKt_QsNbq;fM0iR;U@$ln`yOFn zxP0zv?pw29jINcjdjYJi2Q4%xX#I9-pYKj>z6u*)cQ6nb7zH$ap4`V4yJKQ@$^ZoS zVxVgWUEQD(x0ZrU`fz-;A7CJ+@Y5RlDM)H-n@p8&D2$_6^yQP!0N~Yufl$X16jnU2 z=mCDI1}d4$1L+HxE+0c%MxI7@f2I%FKZ3y;1Ksydu40XS>i~~uOmE&o0%Cx5q_@Gq z09AUi1wdi}HyOVsL0d9{6$Z=&1|bv}Q3ySf2-x3Fc_;T|;sKMzMZzc~YV^@0ImFnItZaIZA? zffj~J?D0sTH3n+&PlP#Ou)1|$VDJ?K{JJ9K%hqp;vC{Q`A<}=8qOqmIjeWrpgb;!| zLmV;~kGIgp!*6LI8&ZGT^wU>5Kz9XzVSV1R95j6V2L=*T{2@v478o4#K&(IV!3_1E zP8tjZ20em|U%fO4q!^f&6$9)S6&I|6NcrX?!mxgG~q8+I)QC28%XHUizj9WV2kY- zJ^Q3Em~Zu#75UUseRZ`xm>auKz#I;Gq||rJ0~G^-$B`z~Uif=5!J2+$+3D;Cf-JwKvk)&N4h56g3<92QCZ})Rf`uf)x2#^XV zFFRXR$9bcGxxl+paQ{IRxZZxyoqE6kSIhXuH3mZXqo1hc9}FZ5_?`!v4i6sqgn{0o z)s3p}VESd}7zW2i=l*}S&T?d0N1JNdvxm0D${I8lpF5v{vBJst8lE{Jv3j*{9AD;p z4E%)$#6V>v7>FPY28P}B#I%Fmld|>Sc>REfjIH(CJXquis;USHfgU1h0YS?$)Rzy5 z0{f2#a{(|w6mW?!x_P| zK?3SPQ$m!$2X!HyGmeSHKwvXIsNrC0LQYu545YtUPfskq2%ifukYib`OQ~BMH{o zL9l@!v_ECZ3v#RD6zdx`_7``{ogbdK9F&=l@A(l49PAQ=2oKtD+qIJ(K&9yyThIM| z%KV^lf))=F{FI!TtzZ~O!d>HFEuJ$yGQy3HFg0PMU`vHz$WYc)0wLi~=Kk*AgVBBU zsl2_$M%g2#WU8q!00WeT$p>k5f9u0fe{Og0zpoy6BqBYbm~6y?Wef=gA^?yvB&JRW z3@l}V8TS`SV3jzbA^jsA0@psHV!jv{caOU?@8`kX%e~D@^UP`79*igI?_b+^dto3F zmNu-mIQ?)~C+|1$-#VBii6j4>n`UY^ei z3_kNfF#wwl421t18kVhGC*zG+z)g^HNeNpJ9=Ei&acuRtZ`<13-m%&KhJi099AEY; z48Hx`*n0Wsxx=N7zvuDQ5^mc|lK=n! literal 0 HcmV?d00001 diff --git a/apps/tests/stretchblt/makefile b/apps/tests/stretchblt/makefile new file mode 100644 index 0000000..fa3421f --- /dev/null +++ b/apps/tests/stretchblt/makefile @@ -0,0 +1,66 @@ +# Makefile - Proj_Listing1_5.dsp + +ifndef CFG +CFG=Proj_Listing1_5 - Win32 Debug +endif +CC=gcc +CFLAGS= +CXX=g++ +CXXFLAGS=$(CFLAGS) +RC=windres -O COFF +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Release" +CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +else +ifeq "$(CFG)" "Proj_Listing1_5 - Win32 Debug" +CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W +LD=$(CXX) $(CXXFLAGS) +LDFLAGS= +LDFLAGS+=-Wl,--subsystem,windows +LIBS+=-lkernel32 -luser32 -lgdi32 +endif +endif + +ifndef TARGET +TARGET=stretchblt.exe +endif + +.PHONY: all +all: $(TARGET) + +%.o: %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $< + +%.res: %.rc + $(RC) $(CPPFLAGS) -o $@ -i $< + +SOURCE_FILES= \ + stretchblt.cpp + +HEADER_FILES= + +RESOURCE_FILES= + +SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES) + +OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS))))) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +.PHONY: clean +clean: + -del $(OBJS) $(TARGET) + +.PHONY: depends +depends: + -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing1_5.dep + +-include Proj_Listing1_5.dep + diff --git a/apps/tests/stretchblt/stretchblt.cpp b/apps/tests/stretchblt/stretchblt.cpp new file mode 100644 index 0000000..40035f0 --- /dev/null +++ b/apps/tests/stretchblt/stretchblt.cpp @@ -0,0 +1,258 @@ + +// ------------------------------------------------------------------ +// Windows 2000 Graphics API Black Book +// Chapter 1 - Listing 1.5 (StretchBlt Zooming Demo) +// +// Created by Damon Chandler +// Updates can be downloaded at: +// +// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu +// if you have any questions about this code. +// ------------------------------------------------------------------ + + +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +#include +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + +HWND HListBox = NULL; +const int ID_LISTBOX = 101; + +HINSTANCE HInst; +const char* WndClassName = "GMainWnd"; +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam); + + +int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance, + LPTSTR lpCmdLine, int nCmdShow) +{ + HInst = HInstance; + + WNDCLASS wc; + memset(&wc, 0, sizeof(WNDCLASS)); + + wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = MainWndProc; + wc.hInstance = HInstance; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = reinterpret_cast(COLOR_BTNFACE + 1); + wc.lpszClassName = WndClassName; + + if (RegisterClass(&wc)) + { + HWND HWnd = + CreateWindow(WndClassName, TEXT("StretchBlt Zooming Demo"), + WS_OVERLAPPEDWINDOW | WS_CAPTION | + WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 675, 560, + NULL, NULL, HInst, NULL); + + if (HWnd) + { + HListBox = + CreateWindowEx(WS_EX_CLIENTEDGE, "LISTBOX", "", + LBS_NOTIFY | WS_CHILD | WS_VISIBLE, + 530, 5, 130, 150, HWnd, + reinterpret_cast(ID_LISTBOX), + HInst, NULL); + if (HListBox) + { + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 25%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 50%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 75%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 100%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 125%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 150%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 200%")); + SNDMSG(HListBox, LB_ADDSTRING, 0, + reinterpret_cast("Zoom 300%")); + } + + ShowWindow(HWnd, nCmdShow); + UpdateWindow(HWnd); + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } + return 0; +} +//------------------------------------------------------------------ + + +// image related +BITMAP bmp; +const char* filename = "LENA.BMP"; +HDC HMemDC = NULL; +HBITMAP HOldBmp = NULL; + +// zooming related +float zoom_factor = 0.5; +RECT RDest = {5, 5, 0, 0}; +enum {ID_ZOOM25, ID_ZOOM50, ID_ZOOM75, ID_ZOOM100, + ID_ZOOM125, ID_ZOOM150, ID_ZOOM200, ID_ZOOM300}; + +LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam, + LPARAM LParam) +{ + switch (Msg) + { + case WM_CREATE: + { + // create a memory DC + HMemDC = CreateCompatibleDC(NULL); + if (HMemDC) + { + // load a bitmap from file + HBITMAP HBmp = + static_cast( + LoadImage(HInst, filename, IMAGE_BITMAP, + 0, 0, LR_LOADFROMFILE) + ); + if (HBmp) + { + // extract dimensions of the bitmap + GetObject(HBmp, sizeof(BITMAP), &bmp); + + // associate the bitmap with the memory DC + HOldBmp = static_cast( + SelectObject(HMemDC, HBmp) + ); + } + } + } + case WM_COMMAND: + { + if (WParam == MAKEWPARAM(ID_LISTBOX, LBN_SELCHANGE)) + { + switch (SNDMSG(HListBox, LB_GETCURSEL, 0, 0)) + { + case ID_ZOOM25: zoom_factor = 0.25; break; + case ID_ZOOM50: zoom_factor = 0.50; break; + case ID_ZOOM75: zoom_factor = 0.75; break; + case ID_ZOOM100: zoom_factor = 1.00; break; + case ID_ZOOM125: zoom_factor = 1.25; break; + case ID_ZOOM150: zoom_factor = 1.50; break; + case ID_ZOOM200: zoom_factor = 2.00; break; + case ID_ZOOM300: zoom_factor = 3.00; break; + } + + // calculate the new width and height + const int new_width = + static_cast(zoom_factor * bmp.bmWidth); + const int new_height = + static_cast(zoom_factor * bmp.bmHeight); + + // is zooming in? + bool zoom_in = (new_width > RDest.right - RDest.left); + + // caculate the area that needs to be updated + RECT RUpdate = { + RDest.left, RDest.top, + RDest.left + max(new_width, RDest.right - RDest.left), + RDest.top + max(new_height, RDest.bottom - RDest.top) + }; + + // adjust the dimenstions of the + // destination rectangle + RDest.right = RDest.left + new_width; + RDest.bottom = RDest.top + new_height; + + // create an update region from the XOR combination + // of the update and destination rectangles + HRGN HUpdateRgn = CreateRectRgnIndirect(&RUpdate); + HRGN HDestRgn = CreateRectRgnIndirect(&RDest); + int result = + CombineRgn(HUpdateRgn, HUpdateRgn, HDestRgn, RGN_XOR); + + // incite a repaint + if (result != NULLREGION && result != ERROR) + { + InvalidateRgn(HWnd, HUpdateRgn, true); + RedrawWindow(HWnd, &RDest, NULL, RDW_NOERASE | RDW_INVALIDATE); + } + else if (result == NULLREGION) + { + InvalidateRect(HWnd, &RUpdate, zoom_in ? false : true); + } + + // clean up + DeleteObject(HUpdateRgn); + DeleteObject(HDestRgn); + } + break; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + const HDC Hdc = BeginPaint(HWnd, &ps); + try + { + // + // TODO: add palette support (see Chapter 9)... + // + + if (RDest.right - RDest.left > 0) + { + // use BitBlt when not zooming + if (zoom_factor == 1.0) + { + BitBlt(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + HMemDC, 0, 0, + SRCCOPY); + } + else + { + if (zoom_factor < 1.0) + { + SetStretchBltMode(Hdc, COLORONCOLOR); + } + + // render the zoomed image + StretchBlt(Hdc, RDest.left, RDest.top, + RDest.right - RDest.left, + RDest.bottom - RDest.top, + HMemDC, 0, 0, + bmp.bmWidth, bmp.bmHeight, + SRCCOPY); + } + } + } + catch (...) + { + EndPaint(HWnd, &ps); + } + EndPaint(HWnd, &ps); + break; + } + case WM_DESTROY: + { + // clean up + DeleteObject(SelectObject(HMemDC, HOldBmp)); + DeleteDC(HMemDC); + + PostQuitMessage(0); + return 0; + } + } + return DefWindowProc(HWnd, Msg, WParam, LParam); +} +//------------------------------------------------------------------ + + + diff --git a/apps/tests/tcpsvr/makefile b/apps/tests/tcpsvr/makefile new file mode 100644 index 0000000..6db2646 --- /dev/null +++ b/apps/tests/tcpsvr/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = tcpsvr + +TARGET_SDKLIBS = kernel32.a ws2_32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/tcpsvr/tcpsvr.c b/apps/tests/tcpsvr/tcpsvr.c new file mode 100644 index 0000000..5bb460b --- /dev/null +++ b/apps/tests/tcpsvr/tcpsvr.c @@ -0,0 +1,173 @@ +/* tcpServer.c + * + * Simple Winsock TCP server test. + * Later will be used as base for ReactOS telnetd + * + * HISTORY: + * 6-15-02 - Added Winsock support to UNIX tcp test + * 6-16-02 - Removed Unix support + * 6-17-02 - Added extra comments to code + * + */ + +#include +#include + +#undef ERROR +#define SUCCESS 0 +#define ERROR 1 + +#define END_LINE 0x0A +#define SERVER_PORT 23 +#define MAX_MSG 100 + +/* function readline */ +int read_line(); + +int main (int argc, char *argv[]) { + + WORD wVersionRequested; + WSADATA WsaData; + INT Status; + int sd, newSd, cliLen; + + struct sockaddr_in cliAddr, servAddr; + char line[MAX_MSG]; + + wVersionRequested = MAKEWORD(2, 2); + + Status = WSAStartup(wVersionRequested, &WsaData); + if (Status != 0) { + printf("Could not initialize winsock dll.\n"); + return FALSE; + } + + /* create socket */ + sd = socket(AF_INET, SOCK_STREAM, 0); + if(sd<0) { + perror("cannot open socket "); + WSACleanup(); + return ERROR; + } + + /* bind server port */ + servAddr.sin_family = AF_INET; + servAddr.sin_addr.s_addr = htonl(INADDR_ANY); + servAddr.sin_port = htons(SERVER_PORT); + + if(bind(sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) { + perror("cannot bind port "); + WSACleanup(); + return ERROR; + } + + listen(sd,5); + + while(1) { + + printf("%s: \n + To start test, Please telnet to localhost (127.0.0.1) port 23 \n + When connected input raw data followed by End of Line\n + Test is now running on TCP port %u\n",argv[0],SERVER_PORT); + + cliLen = sizeof(cliAddr); + newSd = accept(sd, (struct sockaddr *) &cliAddr, &cliLen); + if(newSd<0) { + perror("cannot accept connection "); + WSACleanup(); + return ERROR; + } + + /* init line */ + memset(line,0x0,MAX_MSG); + + /* receive segments */ + while(read_line(newSd,line)!=ERROR) { + + printf("%s: received from %s:TCP%d : %s\n", argv[0], + inet_ntoa(cliAddr.sin_addr), + ntohs(cliAddr.sin_port), line); + /* init line */ + memset(line,0x0,MAX_MSG); + + } /* while(read_line) */ + + } /* while (1) */ + +} + + +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ +/* this function is experimental.. I don't know yet if it works */ +/* correctly or not. Use Steven's readline() function to have */ +/* something robust. */ +/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ + +/* rcv_line is my function readline(). Data is read from the socket when */ +/* needed, but not byte after bytes. All the received data is read. */ +/* This means only one call to recv(), instead of one call for */ +/* each received byte. */ +/* You can set END_CHAR to whatever means endofline for you. (0x0A is \n)*/ +/* read_lin returns the number of bytes returned in line_to_return */ +int read_line(int newSd, char *line_to_return) { + + static int rcv_ptr=0; + static char rcv_msg[MAX_MSG]; + static int n; + int offset; + + offset=0; + + while(1) { + if(rcv_ptr==0) { + /* read data from socket */ + memset(rcv_msg,0x0,MAX_MSG); /* init buffer */ + n = recv(newSd, rcv_msg, MAX_MSG, 0); /* wait for data */ + if (n<0) { + perror(" cannot receive data "); + return ERROR; + } else if (n==0) { + printf(" connection closed by client\n"); + close(newSd); + WSACleanup(); + return ERROR; + } + } + + /* if new data read on socket */ + /* OR */ + /* if another line is still in buffer */ + + /* copy line into 'line_to_return' */ + while(*(rcv_msg+rcv_ptr)!=END_LINE && rcv_ptr return line */ + if(rcv_ptr==n-1) { + /* set last byte to END_LINE */ + *(line_to_return+offset)=END_LINE; + rcv_ptr=0; + return ++offset; + } + + /* end of line but still some data in buffer => return line */ + if(rcv_ptr */ + /* wait for more data to arrive on socket */ + if(rcv_ptr == n) { + rcv_ptr = 0; + } + + } /* while */ +} + + diff --git a/apps/tests/test_old/bug2.c b/apps/tests/test_old/bug2.c new file mode 100644 index 0000000..79b89a4 --- /dev/null +++ b/apps/tests/test_old/bug2.c @@ -0,0 +1,11 @@ +#include + +int +main (void) +{ + int i; + puts ("This should print \"wow = I\" for I from 0 to 39 inclusive."); + for (i = 0; i < 40; i++) + printf ("%s = %d\n", "wow", i); + return 0; +} diff --git a/apps/tests/test_old/bug3.c b/apps/tests/test_old/bug3.c new file mode 100644 index 0000000..6b2ed6b --- /dev/null +++ b/apps/tests/test_old/bug3.c @@ -0,0 +1,53 @@ +#include +#include + +int +main (void) +{ + FILE *f; + int i; + const char filename[] = "/tmp/bug3.test"; + + f = fopen(filename, "w+"); + for (i=0; i<9000; i++) + putc ('x', f); + fseek (f, 8180L, 0); + fwrite ("Where does this text go?", 1, 24, f); + fflush (f); + + rewind (f); + for (i=0; i<9000; i++) + { + int j; + + if ((j = getc(f)) != 'x') + { + if (i != 8180) + { + printf ("Test FAILED!"); + return 1; + } + else + { + char buf[25]; + + buf[0] = j; + fread (buf + 1, 1, 23, f); + buf[24] = '\0'; + if (strcmp (buf, "Where does this text go?") != 0) + { + printf ("%s\nTest FAILED!\n", buf); + return 1; + } + i += 23; + } + } + } + + fclose(f); + remove(filename); + + puts ("Test succeeded."); + + return 0; +} diff --git a/apps/tests/test_old/makefile b/apps/tests/test_old/makefile new file mode 100644 index 0000000..8f69cac --- /dev/null +++ b/apps/tests/test_old/makefile @@ -0,0 +1,73 @@ +# +# +# +PATH_TO_TOP = ../.. + +PROGS= test-stdio tst-printf tstdiomisc bug2 bug3 \ + temptest test-fseek test_rdwr testfsd time_t + +all: $(PROGS:%=%.exe) + +.phony: all + +implib: + +clean: + - $(RM) *.o *.exe *.sym + +.phony: implib clean + +install: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe) + +$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe + +dist: $(PROGS:%=$(DIST_DIR)/apps/%.exe) + +$(PROGS:%=$(DIST_DIR)/apps/%.exe): $(DIST_DIR)/apps/%.exe: %.exe + $(CP) $*.exe $(DIST_DIR)/apps/$*.exe + +bug2.exe: bug2.c + $(CC) bug2.c -lkernel32 -o bug2.exe + $(NM) --numeric-sort bug2.exe > bug2.sym + +bug3.exe: bug3.c + $(CC) bug3.c -lkernel32 -o bug3.exe + $(NM) --numeric-sort bug3.exe > bug3.sym + +temptest.exe: temptest.c + $(CC) temptest.c -lkernel32 -o temptest.exe + $(NM) --numeric-sort temptest.exe > temptest.sym + +test-fseek.exe: test-fseek.c + $(CC) test-fseek.c -lkernel32 -o test-fseek.exe + $(NM) --numeric-sort test-fseek.exe > test-fseek.sym + +test-fwrite.exe: test-fwrite.c + $(CC) test-fwrite.c -lkernel32 -o test-fwrite.exe + $(NM) --numeric-sort test-fwrite.exe > test-fwrite.sym + +test_rdwr.exe: test_rdwr.c + $(CC) test_rdwr.c -lkernel32 -o test_rdwr.exe + $(NM) --numeric-sort test_rdwr.exe > test_rdwr.sym + +test-stdio.exe: test-stdio.c + $(CC) test-stdio.c -lkernel32 -o test-stdio.exe + $(NM) --numeric-sort test-stdio.exe > test-stdio.sym + +tst-printf.exe: tst-printf.c + $(CC) tst-printf.c -lkernel32 -o tst-printf.exe + $(NM) --numeric-sort tst-printf.exe > tst-printf.sym + +tstdiomisc.exe: tstdiomisc.c + $(CC) tstdiomisc.c -lkernel32 -o tstdiomisc.exe + $(NM) --numeric-sort tstdiomisc.exe > tstdiomisc.sym + +testfsd.exe: testfsd.c testsuite.c + $(CC) testfsd.c testsuite.c -lkernel32 -o testfsd.exe + $(NM) --numeric-sort testfsd.exe > testfsd.sym + +time_t.exe: time_t.c + $(CC) time_t.c -lkernel32 -o time_t.exe + $(NM) --numeric-sort time_t.exe > time_t.sym + +include ../../rules.mak diff --git a/apps/tests/test_old/temptest.c b/apps/tests/test_old/temptest.c new file mode 100644 index 0000000..35ea4dc --- /dev/null +++ b/apps/tests/test_old/temptest.c @@ -0,0 +1,27 @@ +#include +#include + +char *files[500]; + +int +main (int argc, char *argv[]) +{ + FILE *fp; + int i; + + for (i = 0; i < 500; i++) { + files[i] = tempnam (NULL, "file"); + if (files[i] == NULL) { + printf ("tempnam failed\n"); + exit (1); + } + printf ("file: %s\n", files[i]); + fp = fopen (files[i], "w"); + fclose (fp); + } + + for (i = 0; i < 500; i++) + remove (files[i]); + + exit (0); +} diff --git a/apps/tests/test_old/test-fseek.c b/apps/tests/test_old/test-fseek.c new file mode 100644 index 0000000..e736ed7 --- /dev/null +++ b/apps/tests/test_old/test-fseek.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#define TESTFILE "/tmp/test.dat" + +int +main (void) +{ + FILE *fp; + int i, j; + + puts ("\nFile seek test"); + fp = fopen (TESTFILE, "w"); + if (fp == NULL) + { + perror (TESTFILE); + return 1; + } + + for (i = 0; i < 256; i++) + putc (i, fp); + if (freopen (TESTFILE, "r", fp) != fp) + { + perror ("Cannot open file for reading"); + return 1; + } + + for (i = 1; i <= 255; i++) + { + printf ("%3d\n", i); + fseek (fp, (long) -i, SEEK_END); + if ((j = getc (fp)) != 256 - i) + { + printf ("SEEK_END failed %d\n", j); + break; + } + if (fseek (fp, (long) i, SEEK_SET)) + { + puts ("Cannot SEEK_SET"); + break; + } + if ((j = getc (fp)) != i) + { + printf ("SEEK_SET failed %d\n", j); + break; + } + if (fseek (fp, (long) i, SEEK_SET)) + { + puts ("Cannot SEEK_SET"); + break; + } + if (fseek (fp, (long) (i >= 128 ? -128 : 128), SEEK_CUR)) + { + puts ("Cannot SEEK_CUR"); + break; + } + if ((j = getc (fp)) != (i >= 128 ? i - 128 : i + 128)) + { + printf ("SEEK_CUR failed %d\n", j); + break; + } + } + fclose (fp); + remove (TESTFILE); + + puts ((i > 255) ? "Test succeeded." : "Test FAILED!"); + return (i > 255) ? 0 : 1; +} diff --git a/apps/tests/test_old/test-fwrite.c b/apps/tests/test_old/test-fwrite.c new file mode 100644 index 0000000..ce54169 --- /dev/null +++ b/apps/tests/test_old/test-fwrite.c @@ -0,0 +1,68 @@ +#include +#include + +int +main (int argc, char *argv[]) +{ + FILE *f = tmpfile (); + char obuf[99999], ibuf[sizeof obuf]; + char *line; + size_t linesz; + + if (! f) + { + perror ("tmpfile"); + return 1; + } + + if (fputs ("line\n", f) == EOF) + { + perror ("fputs"); + return 1; + } + + memset (obuf, 'z', sizeof obuf); + memset (ibuf, 'y', sizeof ibuf); + + if (fwrite (obuf, sizeof obuf, 1, f) != 1) + { + perror ("fwrite"); + return 1; + } + + rewind (f); + + line = NULL; + linesz = 0; + if (getline (&line, &linesz, f) != 5) + { + perror ("getline"); + return 1; + } + if (strcmp (line, "line\n")) + { + puts ("Lines differ. Test FAILED!"); + return 1; + } + + if (fread (ibuf, sizeof ibuf, 1, f) != 1) + { + perror ("fread"); + return 1; + } + + if (memcmp (ibuf, obuf, sizeof ibuf)) + { + puts ("Buffers differ. Test FAILED!"); + return 1; + } + + asprintf (&line, "\ +GDB is free software and you are welcome to distribute copies of it\n\ + under certain conditions; type \"show copying\" to see the conditions.\n\ +There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\ +"); + + puts ("Test succeeded."); + return 0; +} diff --git a/apps/tests/test_old/test-stdio.c b/apps/tests/test_old/test-stdio.c new file mode 100644 index 0000000..913abc2 --- /dev/null +++ b/apps/tests/test_old/test-stdio.c @@ -0,0 +1,55 @@ +#include +#include + +int main() +{ + char msg1[] = "testing _write\n"; + char msg2[] = "testing putchar."; + char msg3[] = "testing printf."; + char tmpbuf[255]; + FILE* f1; + + write(1, msg1, strlen(msg1)); + + write(1, msg2, strlen(msg2)); + putchar('o'); putchar('k'); putchar('\n'); + + write(1, msg3, strlen(msg3)); + printf("ok\n"); + + printf("Testing fopen\n"); + f1 = fopen("tmp.txt","w+b"); + if (f1 == NULL) + { + printf("fopen failed\n"); + return(1); + } + + printf("Testing fwrite\n"); + if (fwrite(msg1, 1, strlen(msg1)+1, f1) != (strlen(msg1)+1)) + { + printf("fwrite failed\n"); + return(1); + } + + printf("Testing fread\n"); + fseek(f1, 0, SEEK_SET); + if (fread(tmpbuf, 1, strlen(msg1)+1, f1) != (strlen(msg1)+1)) + { + printf("fread failed\n"); + return(1); + } + if (strcmp(tmpbuf,msg1) != 0) + { + printf("fread failed, data corrupt\n"); + return(1); + } + + printf("Testing fclose\n"); + if (fclose(f1) != 0) + { + printf("fclose failed\n"); + return(1); + } + return(0); +} diff --git a/apps/tests/test_old/test_rdwr.c b/apps/tests/test_old/test_rdwr.c new file mode 100644 index 0000000..a3b01b7 --- /dev/null +++ b/apps/tests/test_old/test_rdwr.c @@ -0,0 +1,129 @@ +/* Copyright (C) 1991, 1992, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + + +int +main (int argc, char **argv) +{ + static const char hello[] = "Hello, world.\n"; + static const char replace[] = "Hewwo, world.\n"; + static const size_t replace_from = 2, replace_to = 4; + char filename[FILENAME_MAX]; + char *name = strrchr (*argv, '/'); + char buf[BUFSIZ]; + FILE *f; + int lose = 0; + + if (name != NULL) + ++name; + else + name = *argv; + + (void) sprintf (filename, "/tmp/%s.test", name); + + f = fopen (filename, "w+"); + if (f == NULL) + { + perror (filename); + exit (1); + } + + (void) fputs (hello, f); + rewind (f); + (void) fgets (buf, sizeof (buf), f); + rewind (f); + (void) fputs (buf, f); + rewind (f); + { + size_t i; + for (i = 0; i < replace_from; ++i) + { + int c = getc (f); + if (c == EOF) + { + printf ("EOF at %Zu.\n", i); + lose = 1; + break; + } + else if (c != hello[i]) + { + printf ("Got '%c' instead of '%c' at %Zu.\n", + (unsigned char) c, hello[i], i); + lose = 1; + break; + } + } + } + + { + long int where = ftell (f); + if (where == (long int) replace_from) + { + register size_t i; + for (i = replace_from; i < replace_to; ++i) + if (putc(replace[i], f) == EOF) + { + printf ("putc('%c') got %s at %Zu.\n", + replace[i], strerror (errno), i); + lose = 1; + break; + } + } + else if (where == -1L) + { + printf ("ftell got %s (should be at %Zu).\n", + strerror (errno), replace_from); + lose = 1; + } + else + { + printf ("ftell returns %lu; should be %Zu.\n", where, replace_from); + lose = 1; + } + } + + if (!lose) + { + rewind (f); + if (fgets (buf, sizeof (buf), f) == NULL) + { + printf ("fgets got %s.\n", strerror(errno)); + lose = 1; + } + else if (strcmp (buf, replace)) + { + printf ("Read \"%s\" instead of \"%s\".\n", buf, replace); + lose = 1; + } + } + + if (lose) + printf ("Test FAILED! Losing file is \"%s\".\n", filename); + else + { + (void) remove (filename); + puts ("Test succeeded."); + } + + exit (lose ? EXIT_FAILURE : EXIT_SUCCESS); +} diff --git a/apps/tests/test_old/testfsd.c b/apps/tests/test_old/testfsd.c new file mode 100644 index 0000000..9c304c0 --- /dev/null +++ b/apps/tests/test_old/testfsd.c @@ -0,0 +1,315 @@ +/* $Id$ + * + * FILE: testFSD.c + * PURPOSE: A test set for the File System Driver + * PROJECT: ReactOS kernel + * COPYRIGHT: See COPYING in the top level directory + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + * + */ + +#include +#include +#include +#include + +#include "testsuite.h" + +const char *rootDir = "c:\\"; +const char *systemRootDir = "c:\\ReactOS"; +const char *systemDllDir = "c:\\ReactOS\\System32"; +const char *bogusRootFile = "c:\\bogus"; +const char *bogusDirAndFile = "c:\\bogus\\bogus"; +const char *bogusSystemRootFile = "c:\\ReactOS\\bogus"; +const char *bogusSystemDllFile = "c:\\ReactOS\\System32\\bogus"; +const char *shortFile = "c:\\ReactOS\\boot.bat"; +const char *longFile = "c:\\ReactOS\\loadros.com"; + +void testOpenExistant (void) +{ + HANDLE fileHandle; + + fileHandle = CreateFile (rootDir, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile (systemRootDir, GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile (systemDllDir, GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); +} + +void testOpenNonExistant (void) +{ + DWORD status; + HANDLE fileHandle; + + fileHandle = CreateFile (bogusRootFile, GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_FILE_NOT_FOUND); + CloseHandle (fileHandle); + fileHandle = CreateFile (bogusDirAndFile, GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_PATH_NOT_FOUND); + CloseHandle (fileHandle); + fileHandle = CreateFile (bogusSystemRootFile, GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_FILE_NOT_FOUND); + CloseHandle (fileHandle); + fileHandle = CreateFile (bogusSystemDllFile, GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_FILE_NOT_FOUND); + CloseHandle (fileHandle); +} + +void testCreateExistant (void) +{ + DWORD status; + HANDLE fileHandle; + + fileHandle = CreateFile (rootDir, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_ALREADY_EXISTS); + fileHandle = CreateFile (systemRootDir, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_ALREADY_EXISTS); + fileHandle = CreateFile (systemDllDir, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_ALREADY_EXISTS); +} + +void testCreateNonExistant (void) +{ + DWORD status; + HANDLE fileHandle; + + fileHandle = CreateFile (bogusRootFile, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile (bogusSystemRootFile, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile (bogusSystemDllFile, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); +#if 0 + fileHandle = CreateFile (bogusDirAndFile, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle == INVALID_HANDLE_VALUE); + status = GetLastError (); + ASSERT (status == ERROR_PATH_NOT_FOUND); + CloseHandle (fileHandle); +#endif +} + +void testDeleteFiles (void) +{ + BOOL returnValue; + HANDLE fileHandle; + + fileHandle = CreateFile ("bogus", GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + returnValue = DeleteFile ("bogus"); + ASSERT_MSG (returnValue, + "Delete of bogus failed, error:%d", + GetLastError ()); + +#if 0 + returnValue = DeleteFile (bogusRootFile); + ASSERT_MSG (returnValue, + "Delete of %s failed, error:%d", + bogusRootFile, + GetLastError ()); + returnValue = DeleteFile (bogusRootFile); + ASSERT_MSG (!returnValue, + "2nd Delete of %s succeeded but should fail", + bogusRootFile); + returnValue = DeleteFile (bogusSystemRootFile); + ASSERT_MSG (returnValue, + "Delete of %s failed, error:%d", + bogusSystemRootFile, + GetLastError ()); + returnValue = DeleteFile (bogusSystemRootFile); + ASSERT_MSG (!returnValue, + "2nd Delete of %s succeeded but should fail", + bogusSystemRootFile); + returnValue = DeleteFile (bogusSystemDllFile); + ASSERT_MSG (returnValue, + "Delete of %s failed, error:%d", + bogusSystemDllFile, + GetLastError ()); + returnValue = DeleteFile (bogusSystemDllFile); + ASSERT_MSG (!returnValue, + "2nd Delete of %s succeeded but should fail", + bogusSystemDllFile); + returnValue = DeleteFile (bogusDirAndFile); + ASSERT_MSG (!returnValue, + "Delete of %s succeded but should fail", + bogusDirAndFile); +#endif +} + +void testOpenWithBlankPathElements (void) +{ + HANDLE fileHandle; + + fileHandle = CreateFile ("c:", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile ("c:\\\\", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile ("c:\\\\reactos\\", GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile ("c:\\reactos\\\\", GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile ("c:\\reactos\\\\system32\\", GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile ("c:\\reactos\\system32\\\\", GENERIC_READ, 0, 0, + OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); +} + +void testReadOnInvalidHandle (void) +{ + BOOL returnValue; + char buffer [256]; + DWORD bytesRead; + + returnValue = ReadFile (INVALID_HANDLE_VALUE, + buffer, + 256, + &bytesRead, + NULL); + ASSERT_MSG (!returnValue, + "Read from invalid handle succeeded but should fail",0); + ASSERT (GetLastError () != ENOFILE); +} + +void testReadOnZeroLengthFile (void) +{ + BOOL returnValue; + HANDLE fileHandle; + char buffer [256]; + DWORD bytesRead; + + fileHandle = CreateFile (bogusRootFile, GENERIC_READ, 0, 0, + CREATE_NEW, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + CloseHandle (fileHandle); + fileHandle = CreateFile (bogusRootFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + returnValue = ReadFile (fileHandle, buffer, 256, &bytesRead, NULL); + ASSERT_MSG (!returnValue, + "Read from zero length file succeeded but should fail",0); + ASSERT (GetLastError () != ERROR_HANDLE_EOF); + CloseHandle (fileHandle); + returnValue = DeleteFile (bogusRootFile); + ASSERT_MSG (returnValue, + "Delete of %s failed, error:%d", + bogusRootFile, + GetLastError ()); +} + +void testReadOnShortFile (void) +{ + BOOL returnValue; + HANDLE fileHandle; + char buffer [256]; + DWORD bytesRead; + + fileHandle = CreateFile (shortFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + returnValue = ReadFile (fileHandle, + buffer, + 256, + &bytesRead, + NULL); + ASSERT_MSG (returnValue, + "Read from short length file failed, error:%d", + GetLastError ()); + ASSERT (bytesRead > 0 && bytesRead < 256); + CloseHandle (fileHandle); +} + +void testReadOnLongFile (void) +{ + BOOL returnValue; + HANDLE fileHandle; + char buffer [256]; + DWORD bytesRead; + int count; + + fileHandle = CreateFile (longFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + ASSERT (fileHandle != INVALID_HANDLE_VALUE); + for (count = 0; count < 20; count++) + { + returnValue = ReadFile (fileHandle, + buffer, + 256, + &bytesRead, + NULL); + ASSERT_MSG (returnValue, + "Read from short length file failed, error:%d", + GetLastError ()); + ASSERT (bytesRead == 256); + } + CloseHandle (fileHandle); +} + +int main (void) +{ + TEST_RUNNER testRunner; + TEST_SUITE testsToRun [] = + { + ADD_TEST (testOpenExistant), + ADD_TEST (testOpenNonExistant), + ADD_TEST (testCreateExistant), + ADD_TEST (testCreateNonExistant), + ADD_TEST (testDeleteFiles), +/* ADD_TEST (testOverwriteExistant),*/ +/* ADD_TEST (testOverwriteNonExistant),*/ + ADD_TEST (testOpenWithBlankPathElements), + ADD_TEST (testReadOnInvalidHandle), + ADD_TEST (testReadOnZeroLengthFile), + ADD_TEST (testReadOnShortFile), + ADD_TEST (testReadOnLongFile), +/* ADD_TEST (test), */ + END_TESTS + }; + + memset (&testRunner, 0, sizeof (TEST_RUNNER)); + tsRunTests (&testRunner, testsToRun); + tsReportResults (&testRunner); +} + + diff --git a/apps/tests/test_old/testsuite.c b/apps/tests/test_old/testsuite.c new file mode 100644 index 0000000..617bde8 --- /dev/null +++ b/apps/tests/test_old/testsuite.c @@ -0,0 +1,65 @@ + +#include +#include + +#include "testsuite.h" + +static PTEST_RUNNER iTestRunner = 0; + +void tsRunTests (PTEST_RUNNER pTestRunner, PTEST_SUITE pTests) +{ + int testIndex; + + iTestRunner = pTestRunner; + for (testIndex = 0; pTests [testIndex].testFunc != 0; testIndex++) + { + pTests [testIndex].testFunc (); + pTestRunner->tests++; + } +} + +void tsReportResults (PTEST_RUNNER pTestRunner) +{ + printf ("\nTotal of %d tests.\n" + "Assertions: %d\n" + " Assertions which passed: %d\n" + " Assertions which failed: %d\n", + pTestRunner->tests, + pTestRunner->assertions, + pTestRunner->successes, + pTestRunner->failures); + if (pTestRunner->failures == 0) + { + printf ("\n*** OK ***\n"); + } + else + { + printf ("\n*** FAIL ***\n"); + } +} + +void tsDoAssertion (BOOL pTest, + PCHAR pTestText, + PCHAR pFunction, + int pLine, + ...) +{ + va_list ap; + + iTestRunner->assertions++; + if (!pTest) + { + va_start (ap, pLine); + printf ("%s(%d): ", pFunction, pLine); + vprintf (pTestText, ap); + printf ("\n"); + va_end(ap); + iTestRunner->failures++; + } + else + { + iTestRunner->successes++; + } +} + + diff --git a/apps/tests/test_old/testsuite.h b/apps/tests/test_old/testsuite.h new file mode 100644 index 0000000..0abc2ef --- /dev/null +++ b/apps/tests/test_old/testsuite.h @@ -0,0 +1,44 @@ + +#ifndef H_TESTSUITE_H +#define H_TESTSUITE_H + +struct TestSuite +{ + char *name; + void (*testFunc)(void); +}; + +typedef struct TestSuite TEST_SUITE, *PTEST_SUITE; + +#define ADD_TEST(x) {#x, x} +#define END_TESTS {0, 0} +#define COUNT_TESTS(x) (sizeof x/sizeof (struct TestSuite)) + +struct TestRunner +{ + int tests; + int assertions; + int failures; + int successes; +}; + +typedef struct TestRunner TEST_RUNNER, *PTEST_RUNNER; + +void tsDoAssertion (BOOL pTest, + PCHAR pTestText, + PCHAR pFunction, + int pLine, + ...); + +#ifdef ASSERT +#undef ASSERT +#endif +#define ASSERT(x) tsDoAssertion (x, "assertion \"" ## #x ## "\" failed", __FUNCTION__, __LINE__) +#define ASSERT_MSG(x,y,a...) tsDoAssertion (x, y, __FUNCTION__, __LINE__,a) + +void tsRunTests (PTEST_RUNNER pTestRunner, PTEST_SUITE pTests); +void tsReportResults (PTEST_RUNNER pTestRunner); + +#endif + + diff --git a/apps/tests/test_old/time_t.c b/apps/tests/test_old/time_t.c new file mode 100644 index 0000000..6335355 --- /dev/null +++ b/apps/tests/test_old/time_t.c @@ -0,0 +1,12 @@ +#include +#include + +int main(void) +{ + struct tm *ptr; + time_t lt; + + lt = time(NULL); + ptr = localtime(<); + printf(asctime(ptr)); +} \ No newline at end of file diff --git a/apps/tests/test_old/tst-printf.c b/apps/tests/test_old/tst-printf.c new file mode 100644 index 0000000..8c4feed --- /dev/null +++ b/apps/tests/test_old/tst-printf.c @@ -0,0 +1,311 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef BSD +#include +#define EXIT_SUCCESS 0 +#else +#include +#include +#include +#endif + +#include + +void rfg1 (void); +void rfg2 (void); + + +void +fmtchk (const char *fmt) +{ + (void) fputs(fmt, stdout); + (void) printf(":\t`"); + (void) printf(fmt, 0x12); + (void) printf("'\n"); +} + +void +fmtst1chk (const char *fmt) +{ + (void) fputs(fmt, stdout); + (void) printf(":\t`"); + (void) printf(fmt, 4, 0x12); + (void) printf("'\n"); +} + +void +fmtst2chk (const char *fmt) +{ + (void) fputs(fmt, stdout); + (void) printf(":\t`"); + (void) printf(fmt, 4, 4, 0x12); + (void) printf("'\n"); +} + +/* This page is covered by the following copyright: */ + +/* (C) Copyright C E Chew + * + * Feel free to copy, use and distribute this software provided: + * + * 1. you do not pretend that you wrote it + * 2. you leave this copyright notice intact. + */ + +/* + * Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans. + */ + +#define DEC -123 +#define INT 255 +#define UNS (~0) + +/* Formatted Output Test + * + * This exercises the output formatting code. + */ + +void +fp_test (void) +{ + int i, j, k, l; + char buf[7]; + char *prefix = buf; + char tp[20]; + + puts("\nFormatted output test"); + printf("prefix 6d 6o 6x 6X 6u\n"); + strcpy(prefix, "%"); + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 2; k++) { + for (l = 0; l < 2; l++) { + strcpy(prefix, "%"); + if (i == 0) strcat(prefix, "-"); + if (j == 0) strcat(prefix, "+"); + if (k == 0) strcat(prefix, "#"); + if (l == 0) strcat(prefix, "0"); + printf("%5s |", prefix); + strcpy(tp, prefix); + strcat(tp, "6d |"); + printf(tp, DEC); + strcpy(tp, prefix); + strcat(tp, "6o |"); + printf(tp, INT); + strcpy(tp, prefix); + strcat(tp, "6x |"); + printf(tp, INT); + strcpy(tp, prefix); + strcat(tp, "6X |"); + printf(tp, INT); + strcpy(tp, prefix); + strcat(tp, "6u |"); + printf(tp, UNS); + printf("\n"); + } + } + } + } + printf("%10s\n", (char *) NULL); + printf("%-10s\n", (char *) NULL); +} + +int +main (int argc, char *argv[]) +{ + static char shortstr[] = "Hi, Z."; + static char longstr[] = "Good morning, Doctor Chandra. This is Hal. \ +I am ready for my first lesson today."; + + fmtchk("%.4x"); + fmtchk("%04x"); + fmtchk("%4.4x"); + fmtchk("%04.4x"); + fmtchk("%4.3x"); + fmtchk("%04.3x"); + + fmtst1chk("%.*x"); + fmtst1chk("%0*x"); + fmtst2chk("%*.*x"); + fmtst2chk("%0*.*x"); + +#ifndef BSD + printf("bad format:\t\"%b\"\n"); + printf("nil pointer (padded):\t\"%10p\"\n", (void *) NULL); +#endif + + printf("decimal negative:\t\"%d\"\n", -2345); + printf("octal negative:\t\"%o\"\n", -2345); + printf("hex negative:\t\"%x\"\n", -2345); + printf("long decimal number:\t\"%ld\"\n", -123456L); + printf("long octal negative:\t\"%lo\"\n", -2345L); + printf("long unsigned decimal number:\t\"%lu\"\n", -123456L); + printf("zero-padded LDN:\t\"%010ld\"\n", -123456L); + printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456); + printf("space-padded LDN:\t\"%10ld\"\n", -123456L); + printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L); + + printf("zero-padded string:\t\"%010s\"\n", shortstr); + printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr); + printf("space-padded string:\t\"%10s\"\n", shortstr); + printf("left-adjusted S string:\t\"%-10s\"\n", shortstr); + printf("null string:\t\"%s\"\n", (char *)NULL); + printf("limited string:\t\"%.22s\"\n", longstr); + + printf("e-style >= 1:\t\"%e\"\n", 12.34); + printf("e-style >= .1:\t\"%e\"\n", 0.1234); + printf("e-style < .1:\t\"%e\"\n", 0.001234); + printf("e-style big:\t\"%.60e\"\n", 1e20); + printf ("e-style == .1:\t\"%e\"\n", 0.1); + printf("f-style >= 1:\t\"%f\"\n", 12.34); + printf("f-style >= .1:\t\"%f\"\n", 0.1234); + printf("f-style < .1:\t\"%f\"\n", 0.001234); + printf("g-style >= 1:\t\"%g\"\n", 12.34); + printf("g-style >= .1:\t\"%g\"\n", 0.1234); + printf("g-style < .1:\t\"%g\"\n", 0.001234); + printf("g-style big:\t\"%.60g\"\n", 1e20); + + printf (" %6.5f\n", .099999999860301614); + printf (" %6.5f\n", .1); + printf ("x%5.4fx\n", .5); + + printf ("%#03x\n", 1); + + { + double d = FLT_MIN; + int niter = 17; + + while (niter-- != 0) + printf ("%.17e\n", d / 2); + fflush (stdout); + } + + printf ("%15.5e\n", 4.9406564584124654e-324); + +#define FORMAT "|%12.4f|%12.4e|%12.4g|\n" + printf (FORMAT, 0.0, 0.0, 0.0); + printf (FORMAT, 1.0, 1.0, 1.0); + printf (FORMAT, -1.0, -1.0, -1.0); + printf (FORMAT, 100.0, 100.0, 100.0); + printf (FORMAT, 1000.0, 1000.0, 1000.0); + printf (FORMAT, 10000.0, 10000.0, 10000.0); + printf (FORMAT, 12345.0, 12345.0, 12345.0); + printf (FORMAT, 100000.0, 100000.0, 100000.0); + printf (FORMAT, 123456.0, 123456.0, 123456.0); +#undef FORMAT + + { + char buf[20]; + printf ("sprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n", + sprintf (buf, "%30s", "foo"), sizeof (buf), buf); + } + + fp_test (); + + printf ("%e should be 1.234568e+06\n", 1234567.8); + printf ("%f should be 1234567.800000\n", 1234567.8); + printf ("%g should be 1.23457e+06\n", 1234567.8); + printf ("%g should be 123.456\n", 123.456); + printf ("%g should be 1e+06\n", 1000000.0); + printf ("%g should be 10\n", 10.0); + printf ("%g should be 0.02\n", 0.02); + + { + double x=1.0; + printf("%.17f\n",(1.0/x/10.0+1.0)*x-x); + } + + puts ("--- Should be no further output. ---"); + rfg1 (); + rfg2 (); + + { + char buf[200]; + int result; + + sprintf(buf,"%*s%*s%*s",-1,"one",-20,"two",-30,"three"); + + result = strcmp (buf, + "onetwo three "); + + puts (result != 0 ? "Test failed!" : "Test ok."); + return result != 0; + } +} + +void +rfg1 (void) +{ + char buf[100]; + + sprintf (buf, "%5.s", "xyz"); + if (strcmp (buf, " ") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " "); + sprintf (buf, "%5.f", 33.3); + if (strcmp (buf, " 33") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 33"); + sprintf (buf, "%8.e", 33.3e7); + if (strcmp (buf, " 3e+08") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3e+08"); + sprintf (buf, "%8.E", 33.3e7); + if (strcmp (buf, " 3E+08") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3E+08"); + sprintf (buf, "%.g", 33.3); + if (strcmp (buf, "3e+01") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3e+01"); + sprintf (buf, "%.G", 33.3); + if (strcmp (buf, "3E+01") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3E+01"); +} + +void +rfg2 (void) +{ + int prec; + char buf[100]; + + prec = 0; + sprintf (buf, "%.*g", prec, 3.3); + if (strcmp (buf, "3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3"); + prec = 0; + sprintf (buf, "%.*G", prec, 3.3); + if (strcmp (buf, "3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, "3"); + prec = 0; + sprintf (buf, "%7.*G", prec, 3.33); + if (strcmp (buf, " 3") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 3"); + prec = 3; + sprintf (buf, "%04.*o", prec, 33); + if (strcmp (buf, " 041") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 041"); + prec = 7; + sprintf (buf, "%09.*u", prec, 33); + if (strcmp (buf, " 0000033") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 0000033"); + prec = 3; + sprintf (buf, "%04.*x", prec, 33); + if (strcmp (buf, " 021") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 021"); + prec = 3; + sprintf (buf, "%04.*X", prec, 33); + if (strcmp (buf, " 021") != 0) + printf ("got: '%s', expected: '%s'\n", buf, " 021"); +} diff --git a/apps/tests/test_old/tstdiomisc.c b/apps/tests/test_old/tstdiomisc.c new file mode 100644 index 0000000..1affac5 --- /dev/null +++ b/apps/tests/test_old/tstdiomisc.c @@ -0,0 +1,56 @@ +#include + +int +t1 (void) +{ + int n = -1; + sscanf ("abc ", "abc %n", &n); + printf ("t1: count=%d\n", n); + + return n != 5; +} + +int +t2 (void) +{ + int result = 0; + int n; + long N; + int retval; +#define SCAN(INPUT, FORMAT, VAR, EXP_RES, EXP_VAL) \ + VAR = -1; \ + retval = sscanf (INPUT, FORMAT, &VAR); \ + printf ("sscanf (\"%s\", \"%s\", &x) => %d, x = %ld\n", \ + INPUT, FORMAT, retval, (long int) VAR); \ + result |= retval != EXP_RES || VAR != EXP_VAL + + SCAN ("12345", "%ld", N, 1, 12345); + SCAN ("12345", "%llllld", N, 0, -1); + SCAN ("12345", "%LLLLLd", N, 0, -1); + SCAN ("test ", "%*s%n", n, 0, 4); + SCAN ("test ", "%2*s%n", n, 0, -1); + SCAN ("12 ", "%l2d", n, 0, -1); + SCAN ("12 ", "%2ld", N, 1, 12); + + n = -1; + N = -1; + retval = sscanf ("1 1", "%d %Z", &n, &N); + printf ("sscanf (\"1 1\", \"%%d %%Z\", &n, &N) => %d, n = %d, N = %ld\n", \ + retval, n, N); \ + result |= retval != 1 || n != 1 || N != -1; + + return result; +} + +int +main (int argc, char *argv[]) +{ + int result = 0; + + result |= t1 (); + result |= t2 (); + + result |= fflush (stdout) == EOF; + + return result; +} diff --git a/apps/tests/tests/GetSysMetrics/GetSysMetrics.c b/apps/tests/tests/GetSysMetrics/GetSysMetrics.c new file mode 100644 index 0000000..918dc7c --- /dev/null +++ b/apps/tests/tests/GetSysMetrics/GetSysMetrics.c @@ -0,0 +1,102 @@ +/* + * Simple program to display the Windows System Metrics. + * + * This source code is in the PUBLIC DOMAIN and has NO WARRANTY. + * + * Robert Dickenson , July 11, 2002. + */ +#include +#include + + +int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) +{ + fprintf(stderr,"Windows System Metric:\t Value\n"); + + fprintf(stderr," SM_ARRANGE:\t\t %d\n", GetSystemMetrics(SM_ARRANGE)); + fprintf(stderr," SM_CLEANBOOT:\t %d\n", GetSystemMetrics(SM_CLEANBOOT)); +// fprintf(stderr," SM_CMONITORS:\t %d\n", GetSystemMetrics(SM_CMONITORS)); + fprintf(stderr," SM_CMOUSEBUTTONS:\t %d\n", GetSystemMetrics(SM_CMOUSEBUTTONS)); + fprintf(stderr," SM_CXBORDER:\t %d\n", GetSystemMetrics(SM_CXBORDER)); + fprintf(stderr," SM_CYBORDER:\t %d\n", GetSystemMetrics(SM_CYBORDER)); + fprintf(stderr," SM_CXCURSOR:\t %d\n", GetSystemMetrics(SM_CXCURSOR)); + fprintf(stderr," SM_CYCURSOR:\t %d\n", GetSystemMetrics(SM_CYCURSOR)); + fprintf(stderr," SM_CXDLGFRAME:\t %d\n", GetSystemMetrics(SM_CXDLGFRAME)); + fprintf(stderr," SM_CYDLGFRAME:\t %d\n", GetSystemMetrics(SM_CYDLGFRAME)); + fprintf(stderr," SM_CXDOUBLECLK:\t %d\n", GetSystemMetrics(SM_CXDOUBLECLK)); + fprintf(stderr," SM_CYDOUBLECLK:\t %d\n", GetSystemMetrics(SM_CYDOUBLECLK)); + fprintf(stderr," SM_CXDRAG:\t\t %d\n", GetSystemMetrics(SM_CXDRAG)); + fprintf(stderr," SM_CYDRAG:\t\t %d\n", GetSystemMetrics(SM_CYDRAG)); + fprintf(stderr," SM_CXEDGE:\t\t %d\n", GetSystemMetrics(SM_CXEDGE)); + fprintf(stderr," SM_CYEDGE:\t\t %d\n", GetSystemMetrics(SM_CYEDGE)); + fprintf(stderr," SM_CXFIXEDFRAME:\t %d\n", GetSystemMetrics(SM_CXFIXEDFRAME)); + fprintf(stderr," SM_CYFIXEDFRAME:\t %d\n", GetSystemMetrics(SM_CYFIXEDFRAME)); + fprintf(stderr," SM_CXFRAME:\t\t %d\n", GetSystemMetrics(SM_CXFRAME)); + fprintf(stderr," SM_CYFRAME:\t\t %d\n", GetSystemMetrics(SM_CYFRAME)); + fprintf(stderr," SM_CXFULLSCREEN:\t %d\n", GetSystemMetrics(SM_CXFULLSCREEN)); + fprintf(stderr," SM_CYFULLSCREEN:\t %d\n", GetSystemMetrics(SM_CYFULLSCREEN)); + fprintf(stderr," SM_CXHSCROLL:\t %d\n", GetSystemMetrics(SM_CXHSCROLL)); + fprintf(stderr," SM_CYHSCROLL:\t %d\n", GetSystemMetrics(SM_CYHSCROLL)); + fprintf(stderr," SM_CXHTHUMB:\t %d\n", GetSystemMetrics(SM_CXHTHUMB)); + fprintf(stderr," SM_CXICON:\t\t %d\n", GetSystemMetrics(SM_CXICON)); + fprintf(stderr," SM_CYICON:\t\t %d\n", GetSystemMetrics(SM_CYICON)); + fprintf(stderr," SM_CXICONSPACING:\t %d\n", GetSystemMetrics(SM_CXICONSPACING)); + fprintf(stderr," SM_CYICONSPACING:\t %d\n", GetSystemMetrics(SM_CYICONSPACING)); + fprintf(stderr," SM_CXMAXIMIZED:\t %d\n", GetSystemMetrics(SM_CXMAXIMIZED)); + fprintf(stderr," SM_CYMAXIMIZED:\t %d\n", GetSystemMetrics(SM_CYMAXIMIZED)); + fprintf(stderr," SM_CXMAXTRACK:\t %d\n", GetSystemMetrics(SM_CXMAXTRACK)); + fprintf(stderr," SM_CYMAXTRACK:\t %d\n", GetSystemMetrics(SM_CYMAXTRACK)); + fprintf(stderr," SM_CXMENUCHECK:\t %d\n", GetSystemMetrics(SM_CXMENUCHECK)); + fprintf(stderr," SM_CYMENUCHECK:\t %d\n", GetSystemMetrics(SM_CYMENUCHECK)); + fprintf(stderr," SM_CXMENUSIZE:\t %d\n", GetSystemMetrics(SM_CXMENUSIZE)); + fprintf(stderr," SM_CYMENUSIZE:\t %d\n", GetSystemMetrics(SM_CYMENUSIZE)); + fprintf(stderr," SM_CXMIN:\t\t %d\n", GetSystemMetrics(SM_CXMIN)); + fprintf(stderr," SM_CYMIN:\t\t %d\n", GetSystemMetrics(SM_CYMIN)); + fprintf(stderr," SM_CXMINIMIZED:\t %d\n", GetSystemMetrics(SM_CXMINIMIZED)); + fprintf(stderr," SM_CYMINIMIZED:\t %d\n", GetSystemMetrics(SM_CYMINIMIZED)); + fprintf(stderr," SM_CXMINSPACING:\t %d\n", GetSystemMetrics(SM_CXMINSPACING)); + fprintf(stderr," SM_CYMINSPACING:\t %d\n", GetSystemMetrics(SM_CYMINSPACING)); + fprintf(stderr," SM_CXMINTRACK:\t %d\n", GetSystemMetrics(SM_CXMINTRACK)); + fprintf(stderr," SM_CYMINTRACK:\t %d\n", GetSystemMetrics(SM_CYMINTRACK)); + fprintf(stderr," SM_CXSCREEN:\t %d\n", GetSystemMetrics(SM_CXSCREEN)); + fprintf(stderr," SM_CYSCREEN:\t %d\n", GetSystemMetrics(SM_CYSCREEN)); + fprintf(stderr," SM_CXSIZE:\t\t %d\n", GetSystemMetrics(SM_CXSIZE)); + fprintf(stderr," SM_CYSIZE:\t\t %d\n", GetSystemMetrics(SM_CYSIZE)); + fprintf(stderr," SM_CXSIZEFRAME:\t %d\n", GetSystemMetrics(SM_CXSIZEFRAME)); + fprintf(stderr," SM_CYSIZEFRAME:\t %d\n", GetSystemMetrics(SM_CYSIZEFRAME)); + + fprintf(stderr," SM_CXSMICON:\t %d\n", GetSystemMetrics(SM_CXSMICON)); + fprintf(stderr," SM_CYSMICON:\t %d\n", GetSystemMetrics(SM_CYSMICON)); + fprintf(stderr," SM_CXSMSIZE:\t %d\n", GetSystemMetrics(SM_CXSMSIZE)); + fprintf(stderr," SM_CYSMSIZE:\t %d\n", GetSystemMetrics(SM_CYSMSIZE)); +// fprintf(stderr," SM_CXVIRTUALSCREEN:\t %d\n", GetSystemMetrics(SM_CXVIRTUALSCREEN)); +// fprintf(stderr," SM_CYVIRTUALSCREEN:\t %d\n", GetSystemMetrics(SM_CYVIRTUALSCREEN)); + fprintf(stderr," SM_CXVSCROLL:\t %d\n", GetSystemMetrics(SM_CXVSCROLL)); + fprintf(stderr," SM_CYVSCROLL:\t %d\n", GetSystemMetrics(SM_CYVSCROLL)); + fprintf(stderr," SM_CYCAPTION:\t %d\n", GetSystemMetrics(SM_CYCAPTION)); + fprintf(stderr," SM_CYKANJIWINDOW:\t %d\n", GetSystemMetrics(SM_CYKANJIWINDOW)); + fprintf(stderr," SM_CYMENU:\t\t %d\n", GetSystemMetrics(SM_CYMENU)); + fprintf(stderr," SM_CYSMCAPTION:\t %d\n", GetSystemMetrics(SM_CYSMCAPTION)); + fprintf(stderr," SM_CYVTHUMB:\t %d\n", GetSystemMetrics(SM_CYVTHUMB)); + fprintf(stderr," SM_DBCSENABLED:\t %d\n", GetSystemMetrics(SM_DBCSENABLED)); + fprintf(stderr," SM_DEBUG:\t\t %d\n", GetSystemMetrics(SM_DEBUG)); +// fprintf(stderr," SM_IMMENABLED:\t %d\n", GetSystemMetrics(SM_IMMENABLED)); + + fprintf(stderr," SM_MENUDROPALIGNMENT: %d\n", GetSystemMetrics(SM_MENUDROPALIGNMENT)); + fprintf(stderr," SM_MIDEASTENABLED:\t %d\n", GetSystemMetrics(SM_MIDEASTENABLED)); + fprintf(stderr," SM_MOUSEPRESENT:\t %d\n", GetSystemMetrics(SM_MOUSEPRESENT)); +#ifndef _MSC_VER + fprintf(stderr," SM_MOUSEWHEELPRESENT: %d\n", GetSystemMetrics(SM_MOUSEWHEELPRESENT)); +#endif + fprintf(stderr," SM_NETWORK:\t\t %d\n", GetSystemMetrics(SM_NETWORK)); + fprintf(stderr," SM_PENWINDOWS:\t %d\n", GetSystemMetrics(SM_PENWINDOWS)); +// fprintf(stderr," SM_REMOTESESSION:\t %d\n", GetSystemMetrics(SM_REMOTESESSION)); + fprintf(stderr," SM_SECURE:\t\t %d\n", GetSystemMetrics(SM_SECURE)); +// fprintf(stderr," SM_SAMEDISPLAYFORMAT: %d\n", GetSystemMetrics(SM_SAMEDISPLAYFORMAT)); + fprintf(stderr," SM_SHOWSOUNDS:\t %d\n", GetSystemMetrics(SM_SHOWSOUNDS)); + fprintf(stderr," SM_SLOWMACHINE:\t %d\n", GetSystemMetrics(SM_SLOWMACHINE)); + fprintf(stderr," SM_SWAPBUTTON:\t %d\n", GetSystemMetrics(SM_SWAPBUTTON)); +// fprintf(stderr," SM_XVIRTUALSCREEN: %d\n", GetSystemMetrics(SM_XVIRTUALSCREEN)); +// fprintf(stderr," SM_YVIRTUALSCREEN: %d\n", GetSystemMetrics(SM_YVIRTUALSCREEN)); + return 0; +} diff --git a/apps/tests/tests/GetSysMetrics/Makefile b/apps/tests/tests/GetSysMetrics/Makefile new file mode 100644 index 0000000..942eb80 --- /dev/null +++ b/apps/tests/tests/GetSysMetrics/Makefile @@ -0,0 +1,20 @@ + +PATH_TO_TOP = ../../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = GetSysMetrics + +TARGET_SDKLIBS = user32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/tests/GetSystemInfo/GetSystemInfo.c b/apps/tests/tests/GetSystemInfo/GetSystemInfo.c new file mode 100644 index 0000000..c3cbf37 --- /dev/null +++ b/apps/tests/tests/GetSystemInfo/GetSystemInfo.c @@ -0,0 +1,37 @@ +/* + * This example demonstrates dynamical loading of (internal) Win32 DLLS. + * I dont know why this was called hello5 in the wine tree - sedwards + */ +#include +#include + +int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) +{ + SYSTEM_INFO si; + void CALLBACK (*fnGetSystemInfo)(LPSYSTEM_INFO si); + HMODULE kernel32; + + kernel32 = LoadLibrary("KERNEL32"); + if (kernel32<32) { + fprintf(stderr,"FATAL: could not load KERNEL32!\n"); + return 0; + } + fnGetSystemInfo = (void*)GetProcAddress(kernel32,"GetSystemInfo"); + if (!fnGetSystemInfo) { + fprintf(stderr,"FATAL: could not find GetSystemInfo!\n"); + return 0; + } + fnGetSystemInfo(&si); + fprintf(stderr,"QuerySystemInfo returns:\n"); + fprintf(stderr," wProcessorArchitecture: %d\n",si.u.s.wProcessorArchitecture); + fprintf(stderr," dwPageSize: %ld\n",si.dwPageSize); + fprintf(stderr," lpMinimumApplicationAddress: %p\n",si.lpMinimumApplicationAddress); + fprintf(stderr," lpMaximumApplicationAddress: %p\n",si.lpMaximumApplicationAddress); + fprintf(stderr," dwActiveProcessorMask: %ld\n",si.dwActiveProcessorMask); + fprintf(stderr," dwNumberOfProcessors: %ld\n",si.dwNumberOfProcessors); + fprintf(stderr," dwProcessorType: %ld\n",si.dwProcessorType); + fprintf(stderr," dwAllocationGranularity: %ld\n",si.dwAllocationGranularity); + fprintf(stderr," wProcessorLevel: %d\n",si.wProcessorLevel); + fprintf(stderr," wProcessorRevision: %d\n",si.wProcessorRevision); + return 0; +} diff --git a/apps/tests/tests/GetSystemInfo/Makefile b/apps/tests/tests/GetSystemInfo/Makefile new file mode 100644 index 0000000..5c0d019 --- /dev/null +++ b/apps/tests/tests/GetSystemInfo/Makefile @@ -0,0 +1,26 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = GetSystemInfo + +OBJECTS = GetSystemInfo.o + +LIBS = +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.coff *.exe *.sym + +.phony: clean + +GetSystemInfo.exe: $(OBJECTS) + $(CC) $(CFLAGS) $(OBJECTS) $(LIBS) -o GetSystemInfo.exe + $(NM) --numeric-sort GetSystemInfo.exe > GetSystemInfo.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/Mutex/Makefile b/apps/tests/tests/Mutex/Makefile new file mode 100644 index 0000000..be53e57 --- /dev/null +++ b/apps/tests/tests/Mutex/Makefile @@ -0,0 +1,26 @@ +# 10-11-01 Steven Edwards +# Mutex Benchmarks from the Wineserver Linux Kernel Module +# + +PATH_TO_TOP = ../../../.. + +PROGS = fivemutex rapidmutex + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.exe *.sym + +.phony: clean + +fivemutex.exe: fivemutex.c + $(CC) fivemutex.c -lkernel32 -o fivemutex.exe + $(NM) --numeric-sort fivemutex.exe > fivemutex.sym + +rapidmutex.exe: rapidmutex.c + $(CC) rapidmutex.c -lkernel32 -o rapidmutex.exe + $(NM) --numeric-sort rapidmutex.exe > rapidmutex.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/Mutex/fivemutex.c b/apps/tests/tests/Mutex/fivemutex.c new file mode 100644 index 0000000..cde45b7 --- /dev/null +++ b/apps/tests/tests/Mutex/fivemutex.c @@ -0,0 +1,124 @@ +/* fivemutex.c: hungry philosophers problem + * + * (c) Copyright D.W.Howells 2000. + * All rights reserved + */ +#include +#include +#include + +#define ERR(X,Y) do { if (X) { perror(""Y""); return 1; } } while(0) +#define RUNLENGTH 4 + +int count[5]; + +const char *names[] = { + "five/1", "five/2", "five/3", "five/4", "five/5" +}; + +DWORD WINAPI child(LPVOID tparam) +{ + HANDLE left, right, first, second; + const char *lname, *rname; + int pid = (int) tparam; + int wt; + + lname = names[pid%5]; + rname = names[(pid+1)%5]; + + /* create a mutex */ + left = CreateMutex(NULL,0,lname); ERR(!left,"create left"); + right = CreateMutex(NULL,0,rname); ERR(!left,"create right"); + + printf("[%d] left: %p [%s]\n",pid,left,lname); + printf("[%d] right: %p [%s]\n",pid,right,rname); + + /* pick the forks up in numerical order, else risk starvation */ + if (pid%5 < (pid+1)%5) { + first = left; + second = right; + } + else { + first = right; + second = left; + } + + for (;;) { + /* grab the left mutex */ + wt = WaitForMultipleObjects(1,&first,0,INFINITE); + if (wt!=WAIT_OBJECT_0) + goto wait_failed; + + /* grab the right mutex */ + wt = WaitForMultipleObjects(1,&second,0,INFINITE); + if (wt!=WAIT_OBJECT_0) + goto wait_failed; + + /* got it */ + count[pid]++; + + /* pass the mutexes */ + ERR(!ReleaseMutex(left),"release left"); + ERR(!ReleaseMutex(right),"release right"); + continue; + + wait_failed: + switch (wt) { + case WAIT_OBJECT_0+1: + printf("[%d] obtained mutex __1__\n",pid); + exit(1); + case WAIT_ABANDONED_0: + case WAIT_ABANDONED_0+1: + printf("[%d] abandoned wait\n",pid); + continue; + case WAIT_TIMEOUT: + printf("[%d] wait timed out\n",pid); + exit(1); + default: + ERR(1,"WaitForMultipleObjects"); + } + + return 1; + } + + /* close the handles */ + ERR(!CloseHandle(left),"close left"); + ERR(!CloseHandle(right),"close right"); + + return 0; + +} + +int main() +{ + HANDLE hThread[5]; + DWORD tid; + int loop; + + for (loop=0; loop<5; loop++) { + + hThread[loop] = CreateThread(NULL, /* thread attributes */ + 0, /* stack size */ + child, /* start address */ + (void*)loop, /* parameter */ + 0, /* creation flags */ + &tid /* thread ID */ + ); + if (!hThread[loop]) + { + ERR(1,"CreateThread"); + } + } + + WaitForMultipleObjects(5,hThread,0,RUNLENGTH*1000); + + for (loop=0; loop<5; loop++) + TerminateThread(hThread[loop],0); + + for (loop=0; loop<5; loop++) + printf("[%d] ate %d times (%d times per second)\n", + loop,count[loop],count[loop]/RUNLENGTH + ); + + return 0; +} diff --git a/apps/tests/tests/Mutex/rapidmutex.c b/apps/tests/tests/Mutex/rapidmutex.c new file mode 100644 index 0000000..5796996 --- /dev/null +++ b/apps/tests/tests/Mutex/rapidmutex.c @@ -0,0 +1,89 @@ +/* rapidmutex.c: rapid mutex passing test client [Win32 threaded] + * + * (c) Copyright D.W.Howells 2000. + * All rights reserved + */ +#include +#include +#include + +#define ERR(X,Y) do { if (X) { perror(Y); return 1; } } while(0) +#define RUNLENGTH 4 + +int count[5]; + +DWORD WINAPI child(LPVOID tparam) +{ + HANDLE mymutex; + int pid = (int) tparam; + + /* create a mutex */ + mymutex = CreateMutex(NULL,0,"wibble"); + ERR(!mymutex,"create mutex"); + printf("[%d] Handle: %p\n",pid,mymutex); + + for (;;) { + /* grab the mutex */ + switch (WaitForMultipleObjects(1,&mymutex,0,INFINITE)) + { + case WAIT_OBJECT_0: + /* got it */ + count[pid]++; + + /* pass the mutex */ + ERR(!ReleaseMutex(mymutex),"release mutex"); + break; + + case WAIT_OBJECT_0+1: + printf("[%d] obtained mutex __1__\n",pid); + exit(0); + case WAIT_ABANDONED_0: + case WAIT_ABANDONED_0+1: + printf("[%d] abandoned wait\n",pid); + exit(0); + case WAIT_TIMEOUT: + printf("[%d] wait timed out\n",pid); + exit(0); + default: + ERR(1,"WaitForMultipleObjects"); + } + } + + return 0; +} + +int main() +{ + HANDLE hThread[5]; + DWORD tid; + int loop; + + for (loop=0; loop<5; loop++) { + + hThread[loop] = + CreateThread(NULL, /* thread attributes */ + 0, /* stack size */ + child, /* start address */ + (void*)loop, /* parameter */ + 0, /* creation flags */ + &tid /* thread ID */ + ); + if (!hThread[loop]) + { + ERR(1,"CreateThread"); + } + } + + WaitForMultipleObjects(5,hThread,0,RUNLENGTH*1000); + + for (loop=0; loop<5; loop++) + TerminateThread(hThread[loop],0); + + for (loop=0; loop<5; loop++) + printf("[%d] obtained the mutex %d times" + " (%d times per second)\n", + loop,count[loop],count[loop]/RUNLENGTH + ); + + return 0; +} diff --git a/apps/tests/tests/Parent_Child/Makefile b/apps/tests/tests/Parent_Child/Makefile new file mode 100644 index 0000000..a84da11 --- /dev/null +++ b/apps/tests/tests/Parent_Child/Makefile @@ -0,0 +1,26 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = Parent_Child + +OBJECTS = Parent_Child.o + +LIBS = $(PATH_TO_TOP)/dk/w32/lib/gdi32.a +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.coff *.exe *.sym + +.phony: clean + +Parent_Child.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o Parent_Child.exe + $(NM) --numeric-sort Parent_Child.exe > Parent_Child.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/Parent_Child/Parent_Child.c b/apps/tests/tests/Parent_Child/Parent_Child.c new file mode 100644 index 0000000..6b9df21 --- /dev/null +++ b/apps/tests/tests/Parent_Child/Parent_Child.c @@ -0,0 +1,151 @@ +#include +#include +/* Win32 counterpart for CalcChildScroll16 is not implemented */ +/* even in MS Visual C++ */ +// #include "windef.h" +// #include "wingdi.h" +/*#include */ + +void Write (HDC dc, int x, int y, char *s) +{ + SetBkMode(dc, TRANSPARENT); + TextOut (dc, x, y, s, strlen (s)); +} + +LRESULT CALLBACK WndProc (HWND wnd, UINT msg, WPARAM w, LPARAM l) +{ + static short xChar, yChar; + static RECT rectHola; + static char* strHola = "Hola"; + HDC dc; + PAINTSTRUCT ps; + TEXTMETRIC tm; + + switch (msg){ + case WM_CREATE: + dc = GetDC (wnd); + GetTextMetrics (dc, &tm); + xChar = tm.tmAveCharWidth; + yChar = tm.tmHeight; + GetTextExtentPoint32( dc, strHola, strlen(strHola), ((LPSIZE)&rectHola) + 1 ); + OffsetRect( &rectHola, xChar, yChar ); + ReleaseDC (wnd, dc); + break; + + case WM_HSCROLL: + case WM_VSCROLL: + InvalidateRect(wnd, &rectHola, TRUE ); +// ScrollChildren(wnd, msg, w, l); + return 0; + + case WM_PAINT: + dc = BeginPaint (wnd, &ps); + Write (dc, xChar, yChar, strHola); + EndPaint (wnd, &ps); + break; + + case WM_DESTROY: + PostQuitMessage (0); + break; + + default: + return DefWindowProc (wnd, msg, w, l); + } + return 0l; +} + +LRESULT CALLBACK WndProc2 (HWND wnd, UINT msg, WPARAM w, LPARAM l) +{ + static short xChar, yChar; + static RECT rectInfo; + char buf[128]; + HDC dc; + PAINTSTRUCT ps; + TEXTMETRIC tm; + + switch (msg){ + case WM_CREATE: + dc = GetDC (wnd); + GetTextMetrics (dc, &tm); + xChar = tm.tmAveCharWidth; + yChar = tm.tmHeight; + ReleaseDC (wnd, dc); + break; + + case WM_PAINT: + dc = BeginPaint (wnd, &ps); + sprintf(buf,"ps.rcPaint = {left = %d, top = %d, right = %d, bottom = %d}", + ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.rcPaint.bottom); + rectInfo.left = rectInfo.top = 0; + GetTextExtentPoint32 (dc, buf, strlen(buf), ((LPSIZE)&rectInfo) + 1 ); + OffsetRect (&rectInfo, xChar, yChar ); + Write (dc, xChar, yChar, buf); + EndPaint (wnd, &ps); + break; + + case WM_MOVE: + case WM_SIZE: + InvalidateRect( wnd, &rectInfo, TRUE ); + /*CalcChildScroll16( (UINT16)GetParent(wnd), SB_BOTH );*/ + break; + + case WM_DESTROY: + PostQuitMessage (0); + break; + + default: + return DefWindowProc (wnd, msg, w, l); + } + return 0l; +} + +int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) +{ + HWND wnd,wnd2; + MSG msg; + WNDCLASS class; + char className[] = "class"; /* To make sure className >= 0x10000 */ + char class2Name[] = "class2"; + char winName[] = "Test app"; + + if (!prev){ + class.style = CS_HREDRAW | CS_VREDRAW; + class.lpfnWndProc = WndProc; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = inst; + class.hIcon = LoadIcon (0, IDI_APPLICATION); + class.hCursor = LoadCursor (0, IDC_ARROW); + class.hbrBackground = GetStockObject (WHITE_BRUSH); + class.lpszMenuName = NULL; + class.lpszClassName = className; + if (!RegisterClass (&class)) + return FALSE; + } + + wnd = CreateWindow (className, winName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, + 0, inst, 0); + + if (!prev){ + class.lpfnWndProc = WndProc2; + class.lpszClassName = class2Name; + class.hbrBackground = GetStockObject(GRAY_BRUSH); + if (!RegisterClass (&class)) + return FALSE; + } + + wnd2= CreateWindow (class2Name,"Child window", WS_CAPTION | WS_CHILD | WS_THICKFRAME, + 50, 50, 350, 100, wnd, 0, inst, 0); + + ShowWindow (wnd, show); + UpdateWindow (wnd); + ShowWindow (wnd2, show); + UpdateWindow (wnd2); + + while (GetMessage (&msg, 0, 0, 0)){ + TranslateMessage (&msg); + DispatchMessage (&msg); + } + return 0; +} diff --git a/apps/tests/tests/guitest/Makefile b/apps/tests/tests/guitest/Makefile new file mode 100644 index 0000000..9461982 --- /dev/null +++ b/apps/tests/tests/guitest/Makefile @@ -0,0 +1,36 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = guitest + +OBJECTS = guitest.o + +LIBS = $(PATH_TO_TOP)/dk/w32/lib/gdi32.a +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.exe *.sym + +.phony: clean + +install: $(PROGS:%=$(FLOPPY_DIR)/apps/tests/%.exe) + +$(PROGS:%=$(FLOPPY_DIR)/apps/tests/%.exe): $(FLOPPY_DIR)/apps/tests/%.exe: %.exe + $(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe + +dist: $(PROGS:%=../../$(DIST_DIR)/apps/tests/%.exe) + +$(PROGS:%=../../$(DIST_DIR)/apps/tests/%.exe): ../../$(DIST_DIR)/apps/tests/%.exe: %.exe + $(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe + +guitest.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o guitest.exe + $(NM) --numeric-sort guitest.exe > guitest.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/guitest/guitest.c b/apps/tests/tests/guitest/guitest.c new file mode 100644 index 0000000..73c742a --- /dev/null +++ b/apps/tests/tests/guitest/guitest.c @@ -0,0 +1,751 @@ +/* Windows GUI Behaviour Tester */ +/* by Ove Kåven */ + +#include +#include +#include +#include + +#include "guitest.rc" + +/* checks to include */ +#define LOGGING /* can be undefined under Wine and use -debugmsg +message instead */ +#define MAIN_STYLE WS_OVERLAPPEDWINDOW|WS_HSCROLL +#define MAIN_EXSTYLE 0 +#undef TEST_DESTROY_MAIN +#define SHOW_SUB +#undef TEST_DIALOG +#define RESIZE_DIALOG +#undef TEST_SUBDIALOG +#undef TEST_COMMCTL + +/************************/ +/*** GLOBAL VARIABLES ***/ +/************************/ + +HINSTANCE hInst; +DWORD StartTime; +HWND hListBox,hMainWnd,hSubWnd; +HWND hButton[4]={0,0,0,0}; +HWND hDialog=0,hGroup=0,hSubDlg=0; +WNDPROC wndButton[4],wndDialog,wndGroup,wndSubDlg; +BOOL Clicked=0,Ready=0; +int State=0,Rec=0; +#define STATE_CREATE 0 +#define STATE_DESTROY 1 +#define STATE_SHOW 2 +#define STATE_UPDATE 3 +#define STATE_DIALOG 4 +#define STATE_TEST 5 +#define STATE_DIRECT 6 +#define STATE_DISPATCH 7 +#define STATE_RECURS 8 +char*StateName[]={ + "Creat", + "Destr", + "Show ", + "Updat", + "Dialg", + "Test ", + "Call ", + "Disp ", + "RCall" +}; + +static char wclassname[] = "GUITestClass"; +static char wcclassname[] = "GUITestChildClass"; +static char winname[] = "GUITest"; + +/**************************/ +/*** LOGGING FACILITIES ***/ +/**************************/ + +struct MSGNAMES { + int msg; + char*name; +} MsgNames[]={ +#define MSG(x) {x,#x}, +#define MSG2(x,y) {y,#x}, +#define ENDMSG {0} + +/* we get these in CreateWindow */ +MSG(WM_GETMINMAXINFO) +MSG(WM_NCCREATE) +MSG(WM_NCCALCSIZE) +MSG(WM_CREATE) +MSG(WM_PARENTNOTIFY) + +/* we get these in ShowWindow */ +MSG(WM_SHOWWINDOW) +MSG(WM_WINDOWPOSCHANGING) +MSG(WM_QUERYNEWPALETTE) +MSG(WM_ACTIVATEAPP) +MSG(WM_NCACTIVATE) +MSG(WM_GETTEXT) +MSG(WM_ACTIVATE) +MSG(WM_SETFOCUS) +MSG(WM_NCPAINT) +MSG(WM_ERASEBKGND) +MSG(WM_WINDOWPOSCHANGED) +MSG(WM_SIZE) +MSG(WM_MOVE) + +/* we get these in DestroyWindow */ +MSG(WM_KILLFOCUS) +MSG(WM_DESTROY) +MSG(WM_NCDESTROY) + +/* we get these directly sent */ +MSG(WM_NCHITTEST) +MSG(WM_SETCURSOR) +MSG(WM_MOUSEACTIVATE) +MSG(WM_CHILDACTIVATE) +MSG(WM_COMMAND) +MSG(WM_SYSCOMMAND) + +/* posted events */ +MSG(WM_MOUSEMOVE) +MSG(WM_NCMOUSEMOVE) +MSG(WM_PAINT) +MSG(WM_LBUTTONDOWN) +MSG(WM_LBUTTONUP) +MSG(WM_LBUTTONDBLCLK) +MSG(WM_NCLBUTTONDOWN) +MSG(WM_NCLBUTTONUP) +MSG(WM_NCLBUTTONDBLCLK) + +MSG(WM_KEYDOWN) +MSG(WM_KEYUP) +MSG(WM_CHAR) + +#ifdef WIN32 +MSG(WM_CTLCOLORBTN) +MSG(WM_CTLCOLORDLG) +MSG(WM_CTLCOLORSTATIC) +#else +MSG(WM_CTLCOLOR) +#endif + +/* moving and sizing */ +MSG2(WM_ENTERSIZEMOVE,0x0231) +MSG2(WM_EXITSIZEMOVE,0x0232) +#ifdef WIN32 +MSG(WM_SIZING) +#endif + +/* menus/dialog boxes */ +MSG(WM_CANCELMODE) +MSG(WM_ENABLE) +MSG(WM_SETFONT) +MSG(WM_INITDIALOG) +MSG(WM_GETDLGCODE) +MSG(WM_ENTERIDLE) + +/* scroll bars */ +MSG(WM_HSCROLL) +MSG(WM_VSCROLL) + +/* getting these from Wine but not from Windows */ +MSG2(WM_SETVISIBLE,0x0009) /* unheard of in BC++ 4.52 */ +#ifdef WIN32 +MSG(WM_CAPTURECHANGED) +#endif + +ENDMSG}; + +struct MSGNAMES ButMsgs[]={ +MSG(BM_SETSTATE) +MSG(BM_SETSTYLE) + +ENDMSG}; + +char*MsgName(UINT msg,HWND hWnd) +{ + int i; + static char buffer[64],wclass[64]; + GetClassName(hWnd,wclass,sizeof(wclass)); + +#define MSGSEARCH(msgs) { \ + for (i=0; msgs[i].name&&msgs[i].msg!=msg; i++); \ + if (msgs[i].name) return msgs[i].name; \ + } + + if (!stricmp(wclass,"Button")) MSGSEARCH(ButMsgs); + MSGSEARCH(MsgNames); + /* WM_USER */ + if (msg>=WM_USER) { + sprintf(buffer,"WM_USER+%04x{%s}",msg-WM_USER,wclass); + return buffer; + } + /* message not found */ + sprintf(buffer,"%04x{%s}",msg,wclass); + return buffer; +} + +char*WndName(HWND hWnd,int state) +{ + static char buffer[16]; + if (!hWnd) return "0000"; + if (hWnd==hMainWnd || (state==STATE_CREATE && !hMainWnd)) return "main"; + if (hWnd==hSubWnd || (state==STATE_CREATE && !hSubWnd)) return "chld"; + if (hWnd==hDialog || (state==STATE_DIALOG && !hDialog)) return "tdlg"; + if (hWnd==hGroup) return "tgrp"; + if (hWnd==hButton[0]) return "but1"; + if (hWnd==hButton[1]) return "but2"; + if (hWnd==hButton[2]) return "but3"; + if (hWnd==hButton[3]) return "but4"; + if (hWnd==hSubDlg || (state==STATE_CREATE && !hSubDlg)) return "sdlg"; + if (hDialog) { + int id=GetDlgCtrlID(hWnd); + if (id) { + sprintf(buffer,"dlgitem(%d)",id); + return buffer; + } + } + sprintf(buffer,"%04x",hWnd); + return buffer; +} + +void Log(const char*fmt) +{ +#ifdef LOGGING + if (!Clicked) SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)fmt); +#endif +} + +void Logf(const char*fmt,...) +{ + va_list par; + static char buffer[256]; + + va_start(par,fmt); + vsprintf(buffer,fmt,par); + va_end(par); + Log(buffer); +} + +void LogChildOrder(HWND hWnd) +{ + HWND hWndChild = GetWindow(hWnd,GW_CHILD); + static char buffer[256]; + + strcpy(buffer,"child list:"); + while (hWndChild) { + strcat(strcat(buffer," "),WndName(hWndChild,State)); + hWndChild=GetWindow(hWndChild,GW_HWNDNEXT); + } + Log(buffer); +} + +void LogMessage(int state,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam,char*name) +{ + static char buffer[256]; + DWORD tick=GetTickCount()-StartTime; + char*msgname=MsgName(msg,hWnd); + if (!name) name=WndName(hWnd,state); + switch (msg) { + case WM_SETFOCUS: + case WM_KILLFOCUS: + case WM_SETCURSOR: + Logf("%04d[%s(%d):%s]%s(%s,%08x)",tick,StateName[state],Rec, + name,msgname,WndName((HWND)wParam,State),lParam); + break; +#ifdef WIN32 + case WM_ENTERIDLE: + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + Logf("%04d[%s(%d):%s]%s(%08x,%s)",tick,StateName[state],Rec, + name,msgname,wParam,WndName((HWND)lParam,State)); + break; +#else + case WM_ENTERIDLE: + case WM_CTLCOLOR: + Logf("%04d[%s(%d):%s]%s(%08x,%04x:%s)",tick,StateName[state],Rec, + name,msgname,wParam,HIWORD(lParam),WndName((HWND)LOWORD(lParam),State)); + break; +#endif + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS*pos=(WINDOWPOS*)lParam; +#ifdef WIN32 + Logf("%04d[%s(%d):%s]%s(%08x,%p)",tick,StateName[state],Rec, + name,msgname,wParam,pos); +#else + Logf("%04d[%s(%d):%s]%s(%04x,%p)",tick,StateName[state],Rec, + name,msgname,wParam,pos); +#endif + strcpy(buffer,"FLAGS:"); + if (pos->flags&SWP_DRAWFRAME) strcat(buffer," DRAWFRAME"); + if (pos->flags&SWP_HIDEWINDOW) strcat(buffer," HIDEWINDOW"); + if (pos->flags&SWP_NOACTIVATE) strcat(buffer," NOACTIVATE"); + if (pos->flags&SWP_NOCOPYBITS) strcat(buffer," NOCOPYBITS"); + if (pos->flags&SWP_NOMOVE) strcat(buffer," NOMOVE"); + if (pos->flags&SWP_NOOWNERZORDER) strcat(buffer," NOOWNERZORDER"); + if (pos->flags&SWP_NOSIZE) strcat(buffer," NOSIZE"); + if (pos->flags&SWP_NOREDRAW) strcat(buffer," NOREDRAW"); + if (pos->flags&SWP_NOZORDER) strcat(buffer," NOZORDER"); + if (pos->flags&SWP_SHOWWINDOW) strcat(buffer," SHOWWINDOW"); + Log(buffer); + } + break; + case WM_SYSCOMMAND: + { + char*cmd=NULL; + switch (wParam&0xFFF0) { +#define CASE(x) case SC_##x: cmd=#x; break; + CASE(CLOSE) + CASE(DEFAULT) + CASE(HOTKEY) + CASE(HSCROLL) + CASE(KEYMENU) + CASE(MAXIMIZE) + CASE(MINIMIZE) + CASE(MOUSEMENU) + CASE(MOVE) + CASE(NEXTWINDOW) + CASE(PREVWINDOW) + CASE(RESTORE) + CASE(SCREENSAVE) + CASE(SIZE) + CASE(TASKLIST) + CASE(VSCROLL) +#undef CASE + } + if (cmd) { + Logf("%04d[%s(%d):%s]%s(%s+%x,%08x)",tick,StateName[state],Rec, + name,msgname,cmd,wParam&0xF,lParam); + } else goto GENERIC_MSG; + } + break; + case WM_HSCROLL: + case WM_VSCROLL: + { + char*cmd=NULL; + switch (LOWORD(wParam)) { +#define CASE(x) case SB_##x: cmd=#x; break; +#define CASE2(h,v) case SB_##h: if (msg==WM_HSCROLL) cmd=#h; else cmd=#v; break; + CASE(BOTTOM) + CASE(ENDSCROLL) + CASE2(LINELEFT,LINEUP) + CASE2(LINERIGHT,LINEDOWN) + CASE2(PAGELEFT,PAGEUP) + CASE2(PAGERIGHT,PAGEDOWN) + CASE(THUMBPOSITION) + CASE(THUMBTRACK) + CASE(TOP) +#undef CASE + } + if (cmd) { +#ifdef WIN32 + Logf("%04d[%s(%d):%s]%s(%s,%04x,%s)",tick,StateName[state],Rec, + name,msgname,cmd,HIWORD(wParam),WndName((HWND)lParam,State)); +#else + Logf("%04d[%s(%d):%s]%s(%04x,%04x,%s)",tick,StateName[state],Rec, + name,msgname,cmd,LOWORD(lParam),WndName((HWND)HIWORD(lParam),State)); +#endif + } else goto GENERIC_MSG; + } + break; + default: +GENERIC_MSG: +#ifdef WIN32 + Logf("%04d[%s(%d):%s]%s(%08x,%08x)",tick,StateName[state],Rec, + name,msgname,wParam,lParam); +#else + Logf("%04d[%s(%d):%s]%s(%04x,%08x)",tick,StateName[state],Rec, + name,msgname,wParam,lParam); +#endif + } +} + +/***************************/ +/*** GRAPHICS FACILITIES ***/ +/***************************/ + +void Paint(HWND hWnd) +{ + HDC dc; + PAINTSTRUCT ps; + dc=BeginPaint(hWnd,&ps); + EndPaint(hWnd,&ps); +} + +void FillPattern(HWND hWnd,HDC pdc) +{ + HDC dc=pdc?pdc:GetDC(hWnd); + HBRUSH oldbrush; + RECT rect; + if (!dc) { + Logf("failed to acquire DC for window %s",WndName(hWnd,State)); + return; + } else { + Logf("acquired DC for %s window %s, painting", + IsWindowVisible(hWnd)?"visible":"invisible",WndName(hWnd,State)); + } + GetClientRect(hWnd,&rect); + oldbrush=SelectObject(dc,GetStockObject(LTGRAY_BRUSH)); + PatBlt(dc,0,0,rect.right,rect.bottom,PATCOPY); + SelectObject(dc,oldbrush); + if (!pdc) ReleaseDC(hWnd,dc); +} + +void PaintPattern(HWND hWnd) +{ + HDC dc; + PAINTSTRUCT ps; + dc=BeginPaint(hWnd,&ps); + FillPattern(hWnd,dc); + EndPaint(hWnd,&ps); +} + +/*************************/ +/*** WINDOW PROCEDURES ***/ +/*************************/ + +/* MAIN WINDOW */ +LRESULT FAR CALLBACK _export MainWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult=0; + RECT rect; + int OldState=State; + + State=STATE_RECURS; Rec++; + if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL); + switch (msg) { + case WM_NCHITTEST: + lResult=DefWindowProc(hWnd,msg,wParam,lParam); + break; + case WM_LBUTTONDOWN: + case WM_CHAR: + if (!Clicked) { + SetParent(hListBox,hWnd); + GetClientRect(hWnd,&rect); + MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE); + ShowWindow(hListBox,SW_SHOW); + SetFocus(hListBox); + Clicked=TRUE; + } + break; + case WM_SIZE: + GetClientRect(hWnd,&rect); + if (Clicked) { + MoveWindow(hListBox,0,0,rect.right,rect.bottom,TRUE); + } + MoveWindow(hSubWnd,0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),TRUE); + break; + case WM_PAINT: + Paint(hWnd); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + lResult=DefWindowProc(hWnd,msg,wParam,lParam); + } + State=OldState; Rec--; + return lResult; +} + +/* CHILD WINDOW */ +LRESULT FAR CALLBACK _export SubWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult=0; + RECT rect; + int OldState=State; + + State=STATE_RECURS; Rec++; + if (!Clicked) LogMessage(OldState,hWnd,msg,wParam,lParam,NULL); + switch (msg) { + case WM_PAINT: + Paint(hWnd); + break; + default: + lResult=DefWindowProc(hWnd,msg,wParam,lParam); + } + State=OldState; Rec--; + return lResult; +} + +BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +/* SUBCLASSED CONTROLS */ +LRESULT FAR CALLBACK _export SubClassWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult=0; + RECT rect; + int OldState=State; + int But=-1; + + if (hWnd==hButton[0]) But=0; else + if (hWnd==hButton[1]) But=1; else + if (hWnd==hButton[2]) But=2; else + if (hWnd==hButton[3]) But=3; + + State=STATE_RECURS; Rec++; + if (!Clicked) { + LogMessage(OldState,hWnd,msg,wParam,lParam,NULL); + if (But!=-1) { + lResult=CallWindowProc((FARPROC)wndButton[But],hWnd,msg,wParam,lParam); + if (msg==WM_LBUTTONUP) { + LogChildOrder(GetParent(hWnd)); + } + } + else if (hWnd==hDialog) { + lResult=CallWindowProc((FARPROC)wndDialog,hWnd,msg,wParam,lParam); + } + else if (hWnd==hSubDlg) { + lResult=CallWindowProc((FARPROC)wndSubDlg,hWnd,msg,wParam,lParam); + } + else if (hWnd==hGroup) { + lResult=CallWindowProc((FARPROC)wndGroup,hWnd,msg,wParam,lParam); + if (msg==WM_SETFOCUS) { + /* create subdialog */ + if (hSubDlg) { +#if 0 + SetRect(&rect,0,0,1,1); + InvalidateRect(hWnd,&rect,FALSE); +#endif + } else { +#ifdef TEST_SUBDIALOG + State=STATE_CREATE; + hSubDlg=CreateDialog(hInst,MAKEINTRESOURCE(2),hWnd,(FARPROC)SubDialogProc); + State=STATE_RECURS; +#else +#ifdef RESIZE_DIALOG + GetWindowRect(GetParent(hWnd),&rect); + rect.right++; + SetWindowPos(GetParent(hWnd),0,0,0, + rect.right-rect.left,rect.bottom-rect.top, + SWP_NOMOVE|SWP_NOZORDER); +#endif +#endif + } + } + } + } + State=OldState; Rec--; + return lResult; +} + +/* MAIN DIALOG PROCEDURE */ +BOOL FAR CALLBACK _export TestDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL bResult=0; + RECT rect; + int OldState=State; + int But=-1; + + State=STATE_RECURS; Rec++; + if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,"dlgp"); + switch (msg) { + case WM_INITDIALOG: + hDialog = hWndDlg; + /* subclass dialog window proc */ + wndDialog = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc); + Logf("dialog visible=%s",IsWindowVisible(hWndDlg)?"TRUE":"FALSE"); + /* subclass OK button */ + hButton[3] = GetDlgItem(hWndDlg,IDOK); + wndButton[3] = (WNDPROC)SetWindowLong(hButton[3],GWL_WNDPROC,(LONG)SubClassWindowProc); + /* subclass group box */ + hGroup = GetDlgItem(hWndDlg,IDC_GROUPBOX1); + wndGroup = (WNDPROC)SetWindowLong(hGroup,GWL_WNDPROC,(LONG)SubClassWindowProc); + +#ifdef RESIZE_DIALOG + GetWindowRect(hWndDlg,&rect); + rect.right--; + SetWindowPos(hWndDlg,0,0,0, + rect.right-rect.left,rect.bottom-rect.top, + SWP_NOMOVE|SWP_NOZORDER); +// ShowWindow(GetDlgItem(hWndDlg,IDCANCEL),SW_HIDE); +#endif + + bResult=TRUE; /* we don't do SetFocus */ + break; + case WM_PAINT: + PaintPattern(hWndDlg); + bResult=TRUE; + break; + case WM_COMMAND: + EndDialog(hWndDlg,LOWORD(wParam)); + bResult=TRUE; + break; + case WM_CLOSE: + EndDialog(hWndDlg,IDCANCEL); + bResult=TRUE; + break; + case WM_NCDESTROY: + hDialog = 0; + break; + } + State=OldState; Rec--; + return bResult; +} + +/* SUBDIALOG PROCEDURE */ +BOOL FAR CALLBACK _export SubDialogProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL bResult=0; + RECT rect; + int OldState=State; + int But=-1; + + State=STATE_RECURS; Rec++; + if (!Clicked) LogMessage(OldState,hWndDlg,msg,wParam,lParam,NULL); + switch (msg) { + case WM_INITDIALOG: + hSubDlg = hWndDlg; + /* subclass dialog window proc */ + wndSubDlg = (WNDPROC)SetWindowLong(hDialog,GWL_WNDPROC,(LONG)SubClassWindowProc); + + bResult=TRUE; /* we don't do SetFocus */ + break; + case WM_NCDESTROY: + hSubDlg = 0; + break; + } + State=OldState; Rec--; + return bResult; +} + +/********************/ +/*** MAIN PROGRAM ***/ +/********************/ + +BOOL AppInit(void) +{ + WNDCLASS wclass; + + wclass.style = CS_HREDRAW|CS_VREDRAW; + wclass.lpfnWndProc = MainWindowProc; + wclass.cbClsExtra = 0; + wclass.cbWndExtra = 0; + wclass.hInstance = hInst; + wclass.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(1)); + wclass.hCursor = LoadCursor(0,IDC_ARROW); + wclass.hbrBackground = GetStockObject(WHITE_BRUSH); + wclass.lpszMenuName = NULL; + wclass.lpszClassName = wclassname; + if (!RegisterClass(&wclass)) return FALSE; + wclass.lpfnWndProc = SubWindowProc; + wclass.lpszClassName = wcclassname; + if (!RegisterClass(&wclass)) return FALSE; + return TRUE; +} + +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, int nCmdShow) +{ + MSG msg; + RECT rect; + + hInst = hInstance; + if (!hPrevInstance) + if (!AppInit()) + return 0; + + StartTime=GetTickCount(); + hListBox = CreateWindow("LISTBOX","Messages",WS_BORDER|WS_VSCROLL|WS_CHILD| + LBS_HASSTRINGS|LBS_NOTIFY|LBS_WANTKEYBOARDINPUT, + 0,0,0,0,GetDesktopWindow(),0,hInst,0); + if (!hListBox) { + MessageBox(0,"Could not create list box","Error",MB_OK); + } + + State=STATE_CREATE; + hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE, + CW_USEDEFAULT,0,400,300,0,0,hInst,0); + if (!hMainWnd) return 0; + State=STATE_SHOW; + ShowWindow(hMainWnd,nCmdShow); +#ifdef TEST_DESTROY_MAIN + State=STATE_DESTROY; + DestroyWindow(hMainWnd); + State=STATE_DIRECT; + while (GetMessage(&msg,0,0,0)) { + TranslateMessage(&msg); + State=STATE_DISPATCH; + DispatchMessage(&msg); + State=STATE_DIRECT; + } + State=STATE_CREATE; + hMainWnd = CreateWindowEx(MAIN_EXSTYLE,wclassname,winname,MAIN_STYLE, + CW_USEDEFAULT,0,400,300,0,0,hInst,0); + if (!hMainWnd) return 0; + State=STATE_SHOW; + ShowWindow(hMainWnd,nCmdShow); +#endif +/* update, so no WM_PAINTs are pending */ + State=STATE_UPDATE; +// UpdateWindow(hMainWnd); + Ready=TRUE; +/* fill client area with a pattern */ + FillPattern(hMainWnd,0); +/* create subwindow */ + State=STATE_CREATE; + GetClientRect(hMainWnd,&rect); + hSubWnd = CreateWindow(wcclassname,winname,WS_CHILD|WS_BORDER|WS_CLIPSIBLINGS, + 0,rect.bottom/2,rect.right,rect.bottom-(rect.bottom/2),hMainWnd,0,hInst,0); + if (!hSubWnd) return 0; +/* create buttons */ + hButton[0] = CreateWindow("BUTTON","1",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE, + 8,8,48,20,hMainWnd,0,hInst,0); + hButton[1] = CreateWindow("BUTTON","2",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE, + 32,12,48,20,hMainWnd,0,hInst,0); + hButton[2] = CreateWindow("BUTTON","3",WS_CHILD|WS_CLIPSIBLINGS|WS_VISIBLE, + 56,16,48,20,hMainWnd,0,hInst,0); +/* subclass them */ + wndButton[0] = (WNDPROC)SetWindowLong(hButton[0],GWL_WNDPROC,(LONG)SubClassWindowProc); + wndButton[1] = (WNDPROC)SetWindowLong(hButton[1],GWL_WNDPROC,(LONG)SubClassWindowProc); + wndButton[2] = (WNDPROC)SetWindowLong(hButton[2],GWL_WNDPROC,(LONG)SubClassWindowProc); +/* show them */ + State=STATE_UPDATE; + UpdateWindow(hButton[0]); + LogChildOrder(hMainWnd); + Logf("but1 visible=%d",IsWindowVisible(hButton[0])); + +/* now reparent the button to our (invisible) subwindow */ + State=STATE_TEST; + /* in different order, seeing who gets topmost */ + SetParent(hButton[0],hSubWnd); + SetParent(hButton[2],hSubWnd); + SetParent(hButton[1],hSubWnd); + LogChildOrder(hSubWnd); +/* the button should now be invisible */ + Logf("but1 visible=%d",IsWindowVisible(hButton[0])); +/* see if we can draw on them */ + FillPattern(hButton[0],0); + +#ifdef SHOW_SUB + State=STATE_SHOW; + ShowWindow(hSubWnd,SW_SHOWNORMAL); + State=STATE_UPDATE; + UpdateWindow(hSubWnd); + FillPattern(hSubWnd,0); +// InvalidateRect(hMainWnd,NULL,TRUE); + Logf("but1 visible=%d",IsWindowVisible(hButton[0])); +#endif + +#ifdef TEST_DIALOG + State=STATE_DIALOG; + DialogBox(hInst,MAKEINTRESOURCE(1),hMainWnd,(FARPROC)TestDialogProc); +#endif +#ifdef TEST_COMMCTL + { + DWORD arr[16]; + CHOOSECOLOR cc={sizeof(cc),0,hInst,0,arr,0}; + ChooseColor(&cc); + } +#endif + + State=STATE_DIRECT; + while (GetMessage(&msg,0,0,0)) { + TranslateMessage(&msg); + State=STATE_DISPATCH; + DispatchMessage(&msg); + State=STATE_DIRECT; + } + return 0; +} + + diff --git a/apps/tests/tests/guitest/guitest.rc b/apps/tests/tests/guitest/guitest.rc new file mode 100644 index 0000000..a151c74 --- /dev/null +++ b/apps/tests/tests/guitest/guitest.rc @@ -0,0 +1,17 @@ +/**************************************************************************** + + +guitest.rh + +produced by Borland Resource Workshop + + +*****************************************************************************/ + +#define IDC_CHECKBOX1 104 +#define IDC_CHECKBOX2 105 +#define IDC_CHECKBOX3 106 +#define DIALOG_2 2 +#define IDC_GROUPBOX1 10 +#define DIALOG_1 1 +#define ICON_1 1 diff --git a/apps/tests/tests/hello/Makefile b/apps/tests/tests/hello/Makefile new file mode 100644 index 0000000..8052c7f --- /dev/null +++ b/apps/tests/tests/hello/Makefile @@ -0,0 +1,26 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = hello + +OBJECTS = hello.o + +LIBS = $(PATH_TO_TOP)/dk/w32/lib/gdi32.a +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.coff *.exe *.sym + +.phony: clean + +hello.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o hello.exe + $(NM) --numeric-sort hello.exe > hello.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/hello/hello.c b/apps/tests/tests/hello/hello.c new file mode 100644 index 0000000..41036cb --- /dev/null +++ b/apps/tests/tests/hello/hello.c @@ -0,0 +1,83 @@ +#include + +char szAppName[] = "Hello"; + +long FAR PASCAL WndProc(HWND, UINT, WPARAM, LPARAM); + +int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszCmdLine, + int nCmdShow) +{ + HWND hwnd; + MSG msg; + WNDCLASS wndclass; + + if(!hPrevInst) { + + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = szAppName; + + RegisterClass(&wndclass); + + + } + + hwnd = CreateWindow(szAppName, szAppName, + WS_HSCROLL | WS_VSCROLL | WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 600, + 400, NULL, NULL, hInstance, NULL); + + ShowWindow(hwnd, nCmdShow); + UpdateWindow(hwnd); + + + while(GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; +} + + + +long FAR PASCAL WndProc(HWND hwnd, UINT message, WPARAM wParam, + LPARAM lParam) +{ + HDC hdc; + RECT rect; + SIZE size; + PAINTSTRUCT ps; + + switch(message) { + + case WM_PAINT: + hdc = BeginPaint(hwnd, &ps); + GetClientRect(hwnd, &rect); + InflateRect(&rect, -10, -10); + if( !IsRectEmpty( &rect ) ) + { + GetTextExtentPoint32(hdc, szAppName, strlen(szAppName), &size); + SelectObject(hdc, GetStockObject(LTGRAY_BRUSH)); + Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom); + rect.left = (rect.right + rect.left - size.cx) / 2; + rect.top = (rect.bottom + rect.top - size.cy) / 2; + SetBkMode(hdc, TRANSPARENT); + TextOut(hdc, rect.left, rect.top, szAppName, strlen(szAppName) ); + } + EndPaint(hwnd, &ps); + return 0; + + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hwnd, message, wParam, lParam); +} + diff --git a/apps/tests/tests/hello2/Makefile b/apps/tests/tests/hello2/Makefile new file mode 100644 index 0000000..6929eaa --- /dev/null +++ b/apps/tests/tests/hello2/Makefile @@ -0,0 +1,26 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = hello2 + +OBJECTS = hello2.o + +LIBS = # gdi32.a +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.coff *.exe *.sym + +.phony: clean + +hello2.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o hello2.exe + $(NM) --numeric-sort hello2.exe > hello2.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/hello2/hello2.c b/apps/tests/tests/hello2/hello2.c new file mode 100644 index 0000000..166eec4 --- /dev/null +++ b/apps/tests/tests/hello2/hello2.c @@ -0,0 +1,9 @@ +#include "windows.h" + +int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) +{ + return MessageBox((HWND)0, + (LPSTR)"Hello, hello!", + (LPSTR)"Hello Wine Application", + (MB_OK | MB_ICONEXCLAMATION)); +} diff --git a/apps/tests/tests/make_install.bat b/apps/tests/tests/make_install.bat new file mode 100644 index 0000000..057e6c0 --- /dev/null +++ b/apps/tests/tests/make_install.bat @@ -0,0 +1,51 @@ +echo off +REM +REM - This is kinda dirty, I might fix it up later. - SE +REM + +REM - Make System + +cd GetSysMetrics +make +cd .. +cd GetSystemInfo +make +cd .. +cd guitest +make +cd .. +cd hello +make +cd .. +cd hello2 +make +cd .. +cd Mutex +make +cd .. +cd new +make +cd .. +cd Parent_Child +make +cd .. +cd rolex +make +cd .. +cd volinfo +make +cd .. + +REM - installs + +mkdir C:\reactos\bin\tests +copy GetSystemInfo\GetSystemInfo.exe C:\reactos\bin\tests +copy guitest\guitest.exe C:\reactos\bin\tests +copy hello\hello.exe C:\reactos\bin\tests +copy hello2\hello2.exe C:\reactos\bin\tests +copy Mutex\fivemutex.exe C:\reactos\bin\tests +copy Mutex\rapidmutex.exe C:\reactos\bin\tests +copy Parent_Child\Parent_Child.exe C:\reactos\bin\tests +copy rolex\rolex.exe C:\reactos\bin\tests +copy volinfo\volinfo.exe C:\reactos\bin\tests + diff --git a/apps/tests/tests/new/Makefile b/apps/tests/tests/new/Makefile new file mode 100644 index 0000000..f1efe38 --- /dev/null +++ b/apps/tests/tests/new/Makefile @@ -0,0 +1,26 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = new + +OBJECTS = new.o + +LIBS = $(PATH_TO_TOP)/dk/w32/lib/gdi32.a +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.coff *.exe *.sym + +.phony: clean + +new.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o new.exe + $(NM) --numeric-sort new.exe > new.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/new/new.c b/apps/tests/tests/new/new.c new file mode 100644 index 0000000..dc0b507 --- /dev/null +++ b/apps/tests/tests/new/new.c @@ -0,0 +1,154 @@ +#include + +HANDLE ghInstance; + + +LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK ChildProc (HWND, UINT, WPARAM, LPARAM); + +int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpszCmdParam, int nCmdShow) + { + char szAppName[] = "ClassLook" ; + HWND hwnd ; + MSG msg ; + WNDCLASS wndclass ; + + ghInstance = hInstance; + if (!hPrevInstance) + { + wndclass.style = CS_HREDRAW | CS_VREDRAW ; + wndclass.lpfnWndProc = WndProc ; + wndclass.cbClsExtra = 0 ; + wndclass.cbWndExtra = 0 ; + wndclass.hInstance = hInstance ; + wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; + wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ; + wndclass.lpszMenuName = NULL ; + wndclass.lpszClassName = szAppName ; + + RegisterClass (&wndclass) ; + } + + hwnd = CreateWindow (szAppName, /* window class name */ + szAppName, /* window caption */ + WS_OVERLAPPEDWINDOW, /* window style */ + CW_USEDEFAULT, /* initial x position */ + CW_USEDEFAULT, /* initial y position */ + 600, /* initial x size */ + 400, /* initial y size */ + NULL, /* parent window handle */ + NULL, /* window menu handle */ + hInstance, /* program instance handle */ + NULL) ; /* creation parameters */ + + ShowWindow (hwnd, nCmdShow) ; + UpdateWindow (hwnd) ; + + while (GetMessage (&msg, NULL, 0, 0)) + { + TranslateMessage (&msg) ; + DispatchMessage (&msg) ; + } + return msg.wParam ; + } + +LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) + { + HDC hdc ; + PAINTSTRUCT ps ; + RECT rect ; + WNDCLASS wndclass ; + char clsName[] = "SecondClass"; + + static HWND hChild; + + switch (message) + { + case WM_CREATE : + wndclass.style = CS_PARENTDC | CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = ChildProc ; + wndclass.cbClsExtra = 0 ; + wndclass.cbWndExtra = 0 ; + wndclass.hInstance = ghInstance ; + wndclass.hIcon = NULL ; + wndclass.hCursor = LoadCursor (NULL, IDC_CROSS) ; + wndclass.hbrBackground = GetStockObject (LTGRAY_BRUSH) ; + wndclass.lpszMenuName = NULL ; + wndclass.lpszClassName = clsName; + + RegisterClass (&wndclass); + + hChild = CreateWindow(clsName,"Child Window", + WS_CHILD | WS_VISIBLE | WS_BORDER, + 10, 10, 580, 380, hwnd, NULL, ghInstance, NULL); + ShowWindow(hChild, SW_SHOW); + case WM_PAINT : + hdc = BeginPaint (hwnd, &ps) ; + + GetClientRect (hwnd, &rect) ; + + DrawText (hdc, "Hello, Windows!", -1, &rect, + DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; + + EndPaint (hwnd, &ps); + return 0 ; + + case WM_DESTROY : + PostQuitMessage (0) ; + return 0 ; + } + return DefWindowProc (hwnd, message, wParam, lParam) ; + } + +LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hDC; + PAINTSTRUCT ps; + WNDCLASS wndClass; + char *classes[]={"EDIT","BUTTON","LISTBOX","STATIC","SCROLLBAR","COMBOBOX","COMBOLBOX", NULL}; + char** curr; + char buf[256]; + RECT rect ; + int i; + + switch (message) { + case WM_PAINT: + curr = classes; + i=0; + hDC = BeginPaint(hwnd, &ps); + SelectObject(hDC,GetStockObject(ANSI_FIXED_FONT)); + while (*curr) { + wsprintf(buf,"%12s:",*curr); + GetClassInfo(NULL, *curr, &wndClass); + if(wndClass.style&CS_VREDRAW) lstrcat(buf," | CS_VREDRAW"); + if(wndClass.style&CS_HREDRAW) lstrcat(buf," | CS_HREDRAW" ); + if(wndClass.style&CS_KEYCVTWINDOW) lstrcat(buf," | CS_KEYCVTWINDOW" ); + if(wndClass.style&CS_DBLCLKS) lstrcat(buf," | CS_DBLCLKS" ); + if(wndClass.style&CS_OWNDC) lstrcat(buf," | CS_OWNDC" ); + if(wndClass.style&CS_CLASSDC) lstrcat(buf," | CS_CLASSDC" ); + if(wndClass.style&CS_PARENTDC) lstrcat(buf," | CS_PARENTDC" ); + if(wndClass.style&CS_NOKEYCVT) lstrcat(buf," | CS_NOKEYCVT" ); + if(wndClass.style&CS_NOCLOSE) lstrcat(buf," | CS_NOCLOSE" ); + if(wndClass.style&CS_SAVEBITS) lstrcat(buf," | CS_SAVEBITS" ); + if(wndClass.style&CS_GLOBALCLASS) lstrcat(buf," | CS_GLOBALCLASS"); + GetClientRect (hwnd, &rect) ; + TextOut (hDC, 5,20+i,buf,lstrlen(buf)) ; + i += 15; + curr++; + } +/* EndPaint(hwnd, &ps); + break; + hDC = BeginPaint(hwnd, &ps); +*/ + MoveToEx(hDC, 0, 0, NULL); + LineTo(hDC, 500, 500); + EndPaint(hwnd, &ps); + break; + default: + return DefWindowProc (hwnd, message, wParam, lParam) ; + } + return (0L); +} + diff --git a/apps/tests/tests/readme.txt b/apps/tests/tests/readme.txt new file mode 100644 index 0000000..2da5f58 --- /dev/null +++ b/apps/tests/tests/readme.txt @@ -0,0 +1,31 @@ +This is a collection of simple tests apps I have ported to the +ros build system from wine and other places. Most if not all +work great under Win9x,NT,2k and XP. I've fixed and renamed a few +of these because the old names didn't really describe them. + +If you feel like messing with this just type make_install and +everything will be installed to C:\reactos\bin\tests + +TESTS - +GetSystemInfo: Reads from kernel32.dll + +guitest: simple win32 gui test + +hello: another win32 hello window test + +hello2: yet another win32 hello window test + +Mutex: Mutex benchmarks from the wineserver kernel module + +new: example of create new window + +Parent_Child: example of child windows inside of parents + +rolex: a clock program worth $30,000 + +volinfo - This gets the volume info for all local and network drives +AVOID THIS ON 9X, it works but its very slow. + + + + diff --git a/apps/tests/tests/rolex/Makefile b/apps/tests/tests/rolex/Makefile new file mode 100644 index 0000000..7cbb5a0 --- /dev/null +++ b/apps/tests/tests/rolex/Makefile @@ -0,0 +1,39 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = rolex + +OBJECTS = rolex.o + +LIBS = $(PATH_TO_TOP)/dk/w32/lib/gdi32.a +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.coff *.exe *.sym + +.phony: clean + +install: $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe) + +$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe + $(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe + +dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe) + +$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe + $(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe + +rolex.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o rolex.exe + $(NM) --numeric-sort rolex.exe > rolex.sym + +#%.coff: %.rc +# $(RC) $(RCINC) $< -o $@ + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/rolex/rolex.c b/apps/tests/tests/rolex/rolex.c new file mode 100644 index 0000000..4881600 --- /dev/null +++ b/apps/tests/tests/rolex/rolex.c @@ -0,0 +1,254 @@ +/********************************************************************* + * * + * rolex.c: Windows clock application for WINE (by Jim Peterson) * + * * + * This is a translation of a Turbo Pascal OWL application I made * + * once, so it's a little flaky (tons of globals, functions that * + * could have been in-lined, etc.). The source code should easily * + * compile with a standard Win32 C compiler. * + * * + * To try it out, type 'make rolex'. * + * * + *********************************************************************/ + +#include +#include +#include "windows.h" + +char AppName[] = "Rolex"; +char WindowName[] = "Rolex"; +int WindowWidth = 100; +int WindowHeight = 121; +COLORREF FaceColor = RGB(192,192,192); +COLORREF HandColor = RGB(0,0,0); +COLORREF EtchColor = RGB(0,0,0); + +float Pi=3.1415926; + +typedef struct +{ + int StartX,StartY,EndX,EndY; +} HandData; + +int MaxX,MaxY; +HandData OldSecond,OldHour,OldMinute; + +HWND HWindow; + +void DrawFace(HDC dc) +{ + int MidX, MidY, t; + + MidX=MaxX/2; + MidY=MaxY/2; + SelectObject(dc,CreateSolidBrush(FaceColor)); + SelectObject(dc,CreatePen(PS_SOLID,1,EtchColor)); + Ellipse(dc,0,0,MaxX,MaxY); + + for(t=0; t<12; t++) + { + MoveToEx(dc,MidX+sin(t*Pi/6)*0.9*MidX,MidY-cos(t*Pi/6)*0.9*MidY,NULL); + LineTo(dc,MidX+sin(t*Pi/6)*0.8*MidX,MidY-cos(t*Pi/6)*0.8*MidY); + } + if(MaxX>64 && MaxY>64) + for(t=0; t<60; t++) + SetPixel(dc,MidX+sin(t*Pi/30)*0.9*MidX,MidY-cos(t*Pi/30)*0.9*MidY + ,EtchColor); + DeleteObject(SelectObject(dc,GetStockObject(NULL_BRUSH))); + DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN))); + memset(&OldSecond,0,sizeof(OldSecond)); + memset(&OldMinute,0,sizeof(OldMinute)); + memset(&OldHour,0,sizeof(OldHour)); +} + +void DrawHourHand(HDC dc) +{ + MoveToEx(dc, OldHour.StartX, OldHour.StartY, NULL); + LineTo(dc, OldHour.EndX, OldHour.EndY); +} + +void DrawMinuteHand(HDC dc) +{ + MoveToEx(dc, OldMinute.StartX, OldMinute.StartY, NULL); + LineTo(dc, OldMinute.EndX, OldMinute.EndY); +} + +void DrawSecondHand(HDC dc) +{ + MoveToEx(dc, OldSecond.StartX, OldSecond.StartY, NULL); + LineTo(dc, OldSecond.EndX, OldSecond.EndY); +} + +BOOL UpdateHourHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos) +{ + int Sx, Sy, Ex, Ey; + BOOL rv; + + rv = FALSE; + Sx = MidX; Sy = MidY; + Ex = MidX+sin(Pos*Pi/6000)*XExt; + Ey = MidY-cos(Pos*Pi/6000)*YExt; + rv = ( Sx!=OldHour.StartX || Ex!=OldHour.EndX || + Sy!=OldHour.StartY || Ey!=OldHour.EndY ); + if(rv)DrawHourHand(dc); + OldHour.StartX = Sx; OldHour.EndX = Ex; + OldHour.StartY = Sy; OldHour.EndY = Ey; + return rv; +} + +BOOL UpdateMinuteHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos) +{ + int Sx, Sy, Ex, Ey; + BOOL rv; + + rv = FALSE; + Sx = MidX; Sy = MidY; + Ex = MidX+sin(Pos*Pi/30000)*XExt; + Ey = MidY-cos(Pos*Pi/30000)*YExt; + rv = ( Sx!=OldMinute.StartX || Ex!=OldMinute.EndX || + Sy!=OldMinute.StartY || Ey!=OldMinute.EndY ); + if(rv)DrawMinuteHand(dc); + OldMinute.StartX = Sx; OldMinute.EndX = Ex; + OldMinute.StartY = Sy; OldMinute.EndY = Ey; + return rv; +} + +BOOL UpdateSecondHand(HDC dc,int MidX,int MidY,int XExt,int YExt,WORD Pos) +{ + int Sx, Sy, Ex, Ey; + BOOL rv; + + rv = FALSE; + Sx = MidX; Sy = MidY; + Ex = MidX+sin(Pos*Pi/3000)*XExt; + Ey = MidY-cos(Pos*Pi/3000)*YExt; + rv = ( Sx!=OldSecond.StartX || Ex!=OldSecond.EndX || + Sy!=OldSecond.StartY || Ey!=OldSecond.EndY ); + if(rv)DrawSecondHand(dc); + OldSecond.StartX = Sx; OldSecond.EndX = Ex; + OldSecond.StartY = Sy; OldSecond.EndY = Ey; + return rv; +} + +void Idle(HDC idc) +{ + SYSTEMTIME st; + WORD H, M, S, F; + int MidX, MidY; + HDC dc; + BOOL Redraw; + + if(idc) + dc=idc; + else + dc=GetDC(HWindow); + if(!dc)return; + + GetLocalTime(&st); + H = st.wHour; + M = st.wMinute; + S = st.wSecond; + F = st.wMilliseconds / 10; + F = F + S*100; + M = M*1000+F/6; + H = H*1000+M/60; + MidX = MaxX/2; + MidY = MaxY/2; + SelectObject(dc,CreatePen(PS_SOLID,1,FaceColor)); + Redraw = FALSE; + if(UpdateHourHand(dc,MidX,MidY,MidX*0.5,MidY*0.5,H)) Redraw = TRUE; + if(UpdateMinuteHand(dc,MidX,MidY,MidX*0.65,MidY*0.65,M)) Redraw = TRUE; + if(UpdateSecondHand(dc,MidX,MidY,MidX*0.79,MidY*0.79,F)) Redraw = TRUE; + DeleteObject(SelectObject(dc,CreatePen(PS_SOLID,1,HandColor))); + if(Redraw) + { + DrawSecondHand(dc); + DrawMinuteHand(dc); + DrawHourHand(dc); + } + DeleteObject(SelectObject(dc,GetStockObject(NULL_PEN))); + if(!idc) ReleaseDC(HWindow,dc); +} + +LRESULT CALLBACK ProcessAppMsg(HWND wnd,UINT msg,WPARAM w,LPARAM l) +{ + PAINTSTRUCT PaintInfo; + HDC dc; + + switch(msg) + { + case WM_PAINT: + if(GetUpdateRect(wnd,NULL,FALSE)) + { + dc=BeginPaint(wnd,&PaintInfo); + DrawFace(dc); + Idle(dc); + EndPaint(wnd,&PaintInfo); + } + break; + + case WM_SIZE: + MaxX = LOWORD(l); + MaxY = HIWORD(l); + break; + + case WM_DESTROY: + PostQuitMessage (0); + break; + + default: + return DefWindowProc (wnd, msg, w, l); + } + return 0l; +} + +WPARAM MessageLoop() +{ + MSG msg; + + while(1) + { + Sleep(1); /* sleep 1 millisecond */ + if(PeekMessage(&msg,0,0,0,PM_REMOVE)) + { + if(msg.message == WM_QUIT) return msg.wParam; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + Idle(NULL); + } +} + +int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) +{ + WNDCLASS class; + if(!prev) + { + class.style = CS_HREDRAW | CS_VREDRAW; + class.lpfnWndProc = ProcessAppMsg; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = inst; + class.hIcon = 0; /* Draw my own icon */ + class.hCursor = LoadCursor (0, IDC_ARROW); + class.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); + class.lpszMenuName = 0; + class.lpszClassName = AppName; + } + if (!RegisterClass (&class)) return -1; + + HWindow=CreateWindowEx(WS_EX_TOPMOST,AppName,WindowName,WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT,CW_USEDEFAULT,WindowWidth,WindowHeight, + 0,0,inst,0); + memset(&OldSecond,0,sizeof(OldSecond)); + memset(&OldMinute,0,sizeof(OldMinute)); + memset(&OldHour,0,sizeof(OldHour)); + MaxX = WindowWidth; + MaxY = WindowHeight; + + ShowWindow (HWindow, show); + UpdateWindow (HWindow); + + return MessageLoop(); +} diff --git a/apps/tests/tests/rolex/rolex.spec b/apps/tests/tests/rolex/rolex.spec new file mode 100644 index 0000000..00d6fce --- /dev/null +++ b/apps/tests/tests/rolex/rolex.spec @@ -0,0 +1,8 @@ +name rolex +mode guiexe +type win32 + +import user32.dll +import gdi32.dll +import kernel32.dll +import ntdll.dll diff --git a/apps/tests/tests/volinfo/Makefile b/apps/tests/tests/volinfo/Makefile new file mode 100644 index 0000000..3a37271 --- /dev/null +++ b/apps/tests/tests/volinfo/Makefile @@ -0,0 +1,36 @@ +# +# +# +PATH_TO_TOP = ../../../.. + +PROGS = volinfo + +OBJECTS = volinfo.o + +LIBS = +CFLAGS = + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: + - $(RM) *.o *.exe *.sym + +.phony: clean + +install: $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe) + +$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe + $(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe + +dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe) + +$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe + $(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe + +volinfo.exe: $(OBJECTS) + $(CC) $(CFLAGS) -Wl,--subsystem,windows $(OBJECTS) $(LIBS) -o volinfo.exe + $(NM) --numeric-sort volinfo.exe > volinfo.sym + +include $(PATH_TO_TOP)/rules.mak diff --git a/apps/tests/tests/volinfo/volinfo.c b/apps/tests/tests/volinfo/volinfo.c new file mode 100644 index 0000000..bc639d1 --- /dev/null +++ b/apps/tests/tests/volinfo/volinfo.c @@ -0,0 +1,29 @@ +/* + * This test program was copied from the former file documentation/cdrom-label + */ +#include +#include +#include /* for strcat() */ + +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, int nCmdShow) +{ + char drive, root[]="C:\\", label[1002], fsname[1002]; + DWORD serial, flags, filenamelen, labellen = 1000, fsnamelen = 1000; + + printf("Drive Serial Flags Filename-Length " + "Label Fsname\n"); + for (drive = 'A'; drive <= 'Z'; drive++) + { + root[0] = drive; + if (GetVolumeInformation(root,label,labellen,&serial, + &filenamelen,&flags,fsname,fsnamelen)) + { + strcat(label,"\""); strcat (fsname,"\""); + printf("%c:\\ 0x%08lx 0x%08lx %15ld \"%-20s \"%-20s\n", + drive, (long) serial, (long) flags, (long) filenamelen, + label, fsname); + } + } + return 0; +} diff --git a/apps/tests/thread/makefile b/apps/tests/thread/makefile new file mode 100644 index 0000000..a199c44 --- /dev/null +++ b/apps/tests/thread/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = thread + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/thread/thread.c b/apps/tests/thread/thread.c new file mode 100644 index 0000000..4a49d0f --- /dev/null +++ b/apps/tests/thread/thread.c @@ -0,0 +1,89 @@ +/* $Id$ + * + * + * + * + */ + +#include +#include +#include + +#define NR_THREADS (10) + +ULONG nr; + +DWORD WINAPI thread_main1(LPVOID param) +{ + ULONG s; + + printf("Thread %ld running\n", (DWORD)param); + s = nr = ((nr * 1103515245) + 12345) & 0x7fffffff; + s = s % 10; + printf("s %ld\n", s); + Sleep(s); + printf("Thread %ld finished\n", (DWORD)param); + return 0; +} + +// Shows the help on how to use these program to the user +void showHelp(void) +{ + +printf("\nReactOS threads test program (built on %s).\n\n", __DATE__); +printf("syntax:\tthread.exe \n"); +printf("\twhere is an integer number\n"); +printf("\texample: thread.exe 100\n"); + + +} + +int main (int argc, char* argv[]) +{ + HANDLE hThread; + DWORD i=0; + DWORD id; + ULONG nr; + HANDLE ThreadHandle[NR_THREADS]; + + // The user must supply one argument (the seed). if he/she doesn't + // then we show the help. + // if(argc < 2) { + // showHelp(); + // return 1; + // } + + // nr = atoi(argv[1]); + nr = 500; + printf("Seed %ld\n", nr); + + printf("Creating %d threads...\n",NR_THREADS*2); + for (i=0;i + +#define INCLUDE_THE_DDK_HEADERS +#ifdef INCLUDE_THE_DDK_HEADERS +#include +#define ROS_ACE_HEADER ACE_HEADER +#define ROS_ACE ACE + +// +// Allocate the System Luid. The first 1000 LUIDs are reserved. +// Use #999 here (0x3E7 = 999) +// + +#define SYSTEM_LUID { 0x3E7, 0x0 } +#define ANONYMOUS_LOGON_LUID { 0x3e6, 0x0 } +#define LOCALSERVICE_LUID { 0x3e5, 0x0 } +#define NETWORKSERVICE_LUID { 0x3e4, 0x0 } + +#else +typedef LONG NTSTATUS, *PNTSTATUS; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR + PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE +} OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; + +typedef struct _ROS_ACE_HEADER +{ + CHAR AceType; + CHAR AceFlags; + USHORT AceSize; +} ROS_ACE_HEADER, *PROS_ACE_HEADER; + +typedef struct +{ + ACE_HEADER Header; + ACCESS_MASK AccessMask; +} ROS_ACE, *PROS_ACE; + +NTSYSAPI +NTSTATUS +NTAPI +RtlConvertSidToUnicodeString ( + IN OUT PUNICODE_STRING String, + IN PSID Sid, + IN BOOLEAN AllocateString + ); + +NTSYSAPI +NTSTATUS +NTAPI +RtlCreateAcl( + PACL Acl, + ULONG AclSize, + ULONG AclRevision); + +NTSYSAPI +NTSTATUS +NTAPI +RtlAddAccessAllowedAce ( + PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid + ); + +NTSYSAPI +NTSTATUS +NTAPI +RtlGetAce ( + PACL Acl, + ULONG AceIndex, + PROS_ACE *Ace + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwAllocateLocallyUniqueId( + OUT PLUID Luid + ); + +NTSYSAPI +NTSTATUS +NTAPI +ZwCreateToken( + OUT PHANDLE TokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER TokenUser, + IN PTOKEN_GROUPS TokenGroups, + IN PTOKEN_PRIVILEGES TokenPrivileges, + IN PTOKEN_OWNER TokenOwner, + IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, + IN PTOKEN_DEFAULT_DACL TokenDefaultDacl, + IN PTOKEN_SOURCE TokenSource + ); +#define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0) +#endif +#include + +#define INITIAL_PRIV_ENABLED SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED +#define INITIAL_PRIV_DISABLED 0 +LUID_AND_ATTRIBUTES InitialPrivilegeSet[] = +{ + { { 0x00000007, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeTcbPrivilege + { { 0x00000002, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeCreateTokenPrivilege + { { 0x00000009, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeTakeOwnershipPrivilege + { { 0x0000000f, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeCreatePagefilePrivilege + { { 0x00000004, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeLockMemoryPrivilege + { { 0x00000003, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeAssignPrimaryTokenPrivilege + { { 0x00000005, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeIncreaseQuotaPrivilege + { { 0x0000000e, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeIncreaseBasePriorityPrivilege + { { 0x00000010, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeCreatePermanentPrivilege + { { 0x00000014, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeDebugPrivilege + { { 0x00000015, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeAuditPrivilege + { { 0x00000008, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSecurityPrivilege + { { 0x00000016, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSystemEnvironmentPrivilege + { { 0x00000017, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeChangeNotifyPrivilege + { { 0x00000011, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeBackupPrivilege + { { 0x00000012, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeRestorePrivilege + { { 0x00000013, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeShutdownPrivilege + { { 0x0000000a, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeLoadDriverPrivilege + { { 0x0000000d, 0x00000000 }, INITIAL_PRIV_ENABLED }, // SeProfileSingleProcessPrivilege + { { 0x0000000c, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeSystemtimePrivilege + { { 0x00000019, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeUndockPrivilege + { { 0x0000001c, 0x00000000 }, INITIAL_PRIV_DISABLED }, // SeManageVolumePrivilege +}; + +typedef struct _SID_2 +{ + UCHAR Revision; + UCHAR SubAuthorityCount; + SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + ULONG SubAuthority[2]; +} SID_2; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +PrintSid(SID_AND_ATTRIBUTES* pSid, TOKEN_OWNER* pOwner, TOKEN_PRIMARY_GROUP* pPrimary) +{ + UNICODE_STRING scSid; + + RtlConvertSidToUnicodeString(&scSid, pSid->Sid, TRUE); + printf("%wZ [", &scSid); + LocalFree(scSid.Buffer); + + if ( EqualSid(pSid->Sid, pOwner->Owner) ) + printf("owner,"); + + if ( EqualSid(pSid->Sid, pPrimary->PrimaryGroup) ) + printf("primary,"); + + if ( pSid->Attributes & SE_GROUP_ENABLED ) + { + if ( pSid->Attributes & SE_GROUP_ENABLED_BY_DEFAULT ) + printf("enabled-default,"); + else + printf("enabled,"); + } + + if ( pSid->Attributes & SE_GROUP_LOGON_ID ) + printf("logon,"); + + + if ( pSid->Attributes & SE_GROUP_MANDATORY ) + printf("mandatory,"); + + printf("]\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayTokenSids(TOKEN_USER* pUser, + TOKEN_GROUPS* pGroups, + TOKEN_OWNER* pOwner, + TOKEN_PRIMARY_GROUP* pPrimary) +{ + DWORD i; + + printf("\nSids:\n"); + PrintSid(&pUser->User, pOwner, pPrimary); + printf("\nGroups:\n"); + for (i = 0; i < pGroups->GroupCount; i++) + PrintSid(&pGroups->Groups[i], pOwner, pPrimary); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayTokenPrivileges(TOKEN_PRIVILEGES* pPriv) +{ + WCHAR buffer[256]; + DWORD i; + + printf("\nprivileges:\n"); + for (i = 0; i < pPriv->PrivilegeCount; i++) + { + DWORD cbName = sizeof(buffer) / sizeof(buffer[0]); + LookupPrivilegeName(0, &pPriv->Privileges[i].Luid, buffer, &cbName); + + printf("%S{0x%08x, 0x%08x} [", buffer, pPriv->Privileges[i].Luid.HighPart, pPriv->Privileges[i].Luid.LowPart); + + if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED ) + printf("enabled,"); + if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT ) + printf("default,"); + if ( pPriv->Privileges[i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS ) + printf("used"); + + printf("]\n"); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayDacl(PACL pAcl) +{ + DWORD i; + NTSTATUS status; + + if ( ! pAcl ) + { + printf("\nNo Default Dacl.\n"); + return; + } + + printf("\nDacl:\n"); + for (i = 0; i < pAcl->AceCount; i++) + { + UNICODE_STRING scSid; + ROS_ACE* pAce; + LPWSTR wszType = 0; + PSID pSid; + + status = RtlGetAce(pAcl, i, (ROS_ACE**) &pAce); + if ( ! NT_SUCCESS(status) ) + { + printf("RtlGetAce(): status = 0x%08x\n", status); + break; + } + + pSid = (PSID) (pAce + 1); + if ( pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE ) + wszType = L"allow"; + if ( pAce->Header.AceType == ACCESS_DENIED_ACE_TYPE ) + wszType = L"deny "; + + status = RtlConvertSidToUnicodeString(&scSid, pSid, TRUE); + if ( ! NT_SUCCESS(status) ) + { + printf("RtlConvertSidToUnicodeString(): status = 0x%08x\n", status); + break; + } + + printf("%d.) %S %wZ 0x%08x\n", i, wszType, &scSid, pAce->AccessMask); + LocalFree(scSid.Buffer); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +PVOID +GetFromToken(HANDLE hToken, TOKEN_INFORMATION_CLASS tic) +{ + BOOL bResult; + DWORD n; + PBYTE p = 0; + + bResult = GetTokenInformation(hToken, tic, 0, 0, &n); + if ( ! bResult && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return 0; + + p = (PBYTE) malloc(n); + if ( ! GetTokenInformation(hToken, tic, p, n, &n) ) + { + printf("GetFromToken() failed for TOKEN_INFORMATION_CLASS(%d): %d\n", tic, GetLastError()); + free(p); + return 0; + } + + return p; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void +DisplayToken(HANDLE hTokenSource) +{ + TOKEN_USER* pTokenUser = (PTOKEN_USER) GetFromToken(hTokenSource, TokenUser); + TOKEN_GROUPS* pTokenGroups = (PTOKEN_GROUPS) GetFromToken(hTokenSource, TokenGroups); + TOKEN_OWNER* pTokenOwner = (PTOKEN_OWNER) GetFromToken(hTokenSource, TokenOwner); + TOKEN_PRIMARY_GROUP* pTokenPrimaryGroup = (PTOKEN_PRIMARY_GROUP) GetFromToken(hTokenSource, TokenPrimaryGroup); + TOKEN_PRIVILEGES* pTokenPrivileges = (PTOKEN_PRIVILEGES) GetFromToken(hTokenSource, TokenPrivileges); + TOKEN_DEFAULT_DACL* pTokenDefaultDacl = (PTOKEN_DEFAULT_DACL) GetFromToken(hTokenSource, TokenDefaultDacl); + + DisplayTokenSids(pTokenUser, pTokenGroups, pTokenOwner, pTokenPrimaryGroup); + // DisplayTokenPrivileges(pTokenPrivileges); + DisplayDacl(pTokenDefaultDacl->DefaultDacl); + + free(pTokenUser); + free(pTokenGroups); + free(pTokenOwner); + free(pTokenPrimaryGroup); + free(pTokenPrivileges); + free(pTokenDefaultDacl); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +BOOL +EnablePrivilege(LPWSTR wszName) +{ + HANDLE hToken; + TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}}; + BOOL bResult; + + LookupPrivilegeValue(0, wszName, &priv.Privileges[0].Luid); + + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); + + AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0); + bResult = GetLastError() == ERROR_SUCCESS; + + CloseHandle(hToken); + return bResult; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +NTSTATUS +CreateInitialSystemToken(HANDLE* phSystemToken) +{ + static SID sidSystem = { 1, 1, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID }; + static SID sidEveryone = { 1, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID }; + static SID sidAuthenticatedUser = { 1, 1, SECURITY_NT_AUTHORITY, SECURITY_AUTHENTICATED_USER_RID }; + static SID_2 sidAdministrators = { 1, 2, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS }; + static const int nGroupCount = 3; + + NTSTATUS status; + ULONG uSize; + DWORD i; + + TOKEN_USER tkUser; + TOKEN_OWNER tkDefaultOwner; + TOKEN_PRIMARY_GROUP tkPrimaryGroup; + + TOKEN_GROUPS* ptkGroups = 0; + TOKEN_PRIVILEGES* ptkPrivileges = 0; + TOKEN_DEFAULT_DACL tkDefaultDacl = { 0 }; + + LARGE_INTEGER tkExpiration; + + LUID authId = SYSTEM_LUID; + + TOKEN_SOURCE source = + { + { '*', '*', 'A', 'N', 'O', 'N', '*', '*' }, + {0, 0} + }; + + SECURITY_QUALITY_OF_SERVICE sqos = + { + sizeof(sqos), + SecurityAnonymous, + SECURITY_STATIC_TRACKING, + FALSE + }; + + OBJECT_ATTRIBUTES oa = + { + sizeof(oa), + 0, + 0, + 0, + 0, + &sqos + }; + + tkExpiration.QuadPart = -1; + status = ZwAllocateLocallyUniqueId(&source.SourceIdentifier); + if ( status != 0 ) + return status; + + tkUser.User.Sid = &sidSystem; + tkUser.User.Attributes = 0; + + // Under WinXP (the only MS OS I've tested) ZwCreateToken() + // squawks if we use sidAdministrators here -- though running + // a progrem under AT and using the DisplayToken() function + // shows that the system token does default ownership to + // Administrator. + + // For now, default ownership to system, since that works + tkDefaultOwner.Owner = &sidSystem; + tkPrimaryGroup.PrimaryGroup = &sidSystem; + + uSize = sizeof(TOKEN_GROUPS) - sizeof(ptkGroups->Groups); + uSize += sizeof(SID_AND_ATTRIBUTES) * nGroupCount; + + ptkGroups = (TOKEN_GROUPS*) malloc(uSize); + ptkGroups->GroupCount = nGroupCount; + + ptkGroups->Groups[0].Sid = (SID*) &sidAdministrators; + ptkGroups->Groups[0].Attributes = SE_GROUP_ENABLED; + + ptkGroups->Groups[1].Sid = &sidEveryone; + ptkGroups->Groups[1].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY; + + ptkGroups->Groups[2].Sid = &sidAuthenticatedUser; + ptkGroups->Groups[2].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY; + + uSize = sizeof(TOKEN_PRIVILEGES) - sizeof(ptkPrivileges->Privileges); + uSize += sizeof(LUID_AND_ATTRIBUTES) * sizeof(InitialPrivilegeSet) / sizeof(InitialPrivilegeSet[0]); + ptkPrivileges = (TOKEN_PRIVILEGES*) malloc(uSize); + ptkPrivileges->PrivilegeCount = sizeof(InitialPrivilegeSet) / sizeof(InitialPrivilegeSet[0]); + for (i = 0; i < ptkPrivileges->PrivilegeCount; i++) + { + ptkPrivileges->Privileges[i].Luid.HighPart = InitialPrivilegeSet[i].Luid.HighPart; + ptkPrivileges->Privileges[i].Luid.LowPart = InitialPrivilegeSet[i].Luid.LowPart; + ptkPrivileges->Privileges[i].Attributes = InitialPrivilegeSet[i].Attributes; + } + + // Calculate the length needed for the ACL + uSize = sizeof(ACL); + uSize += sizeof(ACE) + sizeof(sidSystem); + uSize += sizeof(ACE) + sizeof(sidAdministrators); + uSize = (uSize & (~3)) + 8; + tkDefaultDacl.DefaultDacl = (PACL) malloc(uSize); + + status = RtlCreateAcl(tkDefaultDacl.DefaultDacl, uSize, ACL_REVISION); + if ( ! NT_SUCCESS(status) ) + printf("RtlCreateAcl() failed: 0x%08x\n", status); + + status = RtlAddAccessAllowedAce(tkDefaultDacl.DefaultDacl, ACL_REVISION, GENERIC_ALL, &sidSystem); + if ( ! NT_SUCCESS(status) ) + printf("RtlAddAccessAllowedAce() failed: 0x%08x\n", status); + + status = RtlAddAccessAllowedAce(tkDefaultDacl.DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, (PSID) &sidAdministrators); + if ( ! NT_SUCCESS(status) ) + printf("RtlAddAccessAllowedAce() failed: 0x%08x\n", status); + + printf("Parameters being passed into ZwCreateToken:\n\n"); + DisplayTokenSids(&tkUser, ptkGroups, &tkDefaultOwner, &tkPrimaryGroup); + DisplayDacl(tkDefaultDacl.DefaultDacl); + + printf("Calling ZwCreateToken()...\n"); + status = ZwCreateToken(phSystemToken, + TOKEN_ALL_ACCESS, + &oa, + TokenPrimary, + &authId, + &tkExpiration, + &tkUser, + ptkGroups, + ptkPrivileges, + &tkDefaultOwner, + &tkPrimaryGroup, + &tkDefaultDacl, + &source); + + // Cleanup + free(ptkGroups); + free(ptkPrivileges); + free(tkDefaultDacl.DefaultDacl); + + return status; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +int +main(int argc, char** argv[]) +{ + NTSTATUS Status; + HANDLE hSystemToken; + CHAR buffer[512]; + HANDLE hOurToken; + + printf("Current process Token:\n"); + + Status=ZwOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_QUERY_SOURCE, &hOurToken); + if ( NT_SUCCESS(Status) ) + { + DisplayToken(hOurToken); + CloseHandle(hOurToken); + } + else + { + printf("ZwOpenProcessToken() failed: 0x%08x\n", Status); + } + +//#define ENABLE_PRIVILEGE +#ifdef ENABLE_PRIVILEGE + EnablePrivilege(SE_CREATE_TOKEN_NAME); +#endif + + // Now do the other one + Status = CreateInitialSystemToken(&hSystemToken); + if ( NT_SUCCESS(Status) ) + { + printf("System Token: 0x%08x\n", hSystemToken); + DisplayToken(hSystemToken); + CloseHandle(hSystemToken); + } + else + { + printf("CreateInitialSystemToken() return: 0x%08x\n", Status); + } + + printf("press return"); + gets(buffer); + + return 0; +} diff --git a/apps/tests/vmtest/Makefile b/apps/tests/vmtest/Makefile new file mode 100644 index 0000000..228c069 --- /dev/null +++ b/apps/tests/vmtest/Makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = vmtest + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/vmtest/vmtest.c b/apps/tests/vmtest/vmtest.c new file mode 100644 index 0000000..d68ebbb --- /dev/null +++ b/apps/tests/vmtest/vmtest.c @@ -0,0 +1,54 @@ +#include +#include + +int main() +{ + PVOID Base; + PVOID Ret; + + Base = VirtualAlloc(NULL, + 1048576, + MEM_RESERVE, + PAGE_READWRITE); + if (Base == NULL) + { + printf("VirtualAlloc failed 1\n"); + } + + Ret = VirtualAlloc(Base + 4096, + 4096, + MEM_COMMIT, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 2\n"); + } + + Ret = VirtualAlloc(Base + 12288, + 4096, + MEM_COMMIT, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 3\n"); + } + + Ret = VirtualAlloc(Base + 20480, + 4096, + MEM_COMMIT, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 4\n"); + } + + Ret = VirtualAlloc(Base + 4096, + 28672, + MEM_RESERVE, + PAGE_READWRITE); + if (Ret == NULL) + { + printf("VirtualAlloc failed 5\n"); + } +} + diff --git a/apps/tests/winhello/makefile b/apps/tests/winhello/makefile new file mode 100644 index 0000000..902cc9b --- /dev/null +++ b/apps/tests/winhello/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = windows + +TARGET_NAME = winhello + +TARGET_SDKLIBS = kernel32.a gdi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/tests/winhello/winhello.c b/apps/tests/winhello/winhello.c new file mode 100644 index 0000000..fc34a6e --- /dev/null +++ b/apps/tests/winhello/winhello.c @@ -0,0 +1,107 @@ +#include +#include + +HFONT tf; +LRESULT WINAPI MainWndProc(HWND, UINT, WPARAM, LPARAM); + +int WINAPI +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + WNDCLASS wc; + MSG msg; + HWND hWnd; + + wc.lpszClassName = "HelloClass"; + wc.lpfnWndProc = MainWndProc; + wc.style = CS_VREDRAW | CS_HREDRAW; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); + wc.lpszMenuName = NULL; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + if (RegisterClass(&wc) == 0) + { + fprintf(stderr, "RegisterClass failed (last error 0x%X)\n", + GetLastError()); + return(1); + } + + hWnd = CreateWindow("HelloClass", + "Hello World", + WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL, + 0, + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL); + if (hWnd == NULL) + { + fprintf(stderr, "CreateWindow failed (last error 0x%X)\n", + GetLastError()); + return(1); + } + + tf = CreateFontA(14, 0, 0, TA_BASELINE, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "Timmons"); + + ShowWindow(hWnd, nCmdShow); + + while(GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + DeleteObject(tf); + + return msg.wParam; +} + +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + HDC hDC; + + switch(msg) + { + case WM_LBUTTONUP: + { + ULONG x, y; + RECT Rect; + hDC = GetDC(hWnd); + x = LOWORD(lParam); + y = HIWORD(lParam); + Rect.left = x - 5; + Rect.top = y - 5; + Rect.right = x + 5; + Rect.bottom = y + 5; + FillRect(hDC, &Rect, CreateSolidBrush(RGB(0xFF, 0x00, 0x00))); + ReleaseDC(hWnd, hDC); + break; + } + + case WM_PAINT: + hDC = BeginPaint(hWnd, &ps); + SelectObject(hDC, tf); + TextOut(hDC, 10, 10, "Hello World from ReactOS!", strlen("Hello World from ReactOS!")); + EndPaint(hWnd, &ps); + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; +} diff --git a/apps/utils/cabman/cabinet.cpp b/apps/utils/cabman/cabinet.cpp new file mode 100644 index 0000000..c22cfe5 --- /dev/null +++ b/apps/utils/cabman/cabinet.cpp @@ -0,0 +1,2652 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/cabinet.cpp + * PURPOSE: Cabinet routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: Define CAB_READ_ONLY for read only version + * REVISIONS: + * CSH 21/03-2001 Created + * TODO: + * - Checksum of datablocks should be calculated + * - EXTRACT.EXE complains if a disk is created manually + * - Folders that are created manually and span disks will result in a damaged cabinet + */ +#include +#include +#include +#include "cabinet.h" +#include "raw.h" +#include "mszip.h" + + +#ifndef CAB_READ_ONLY + +#ifdef DBG + +VOID DumpBuffer(PVOID Buffer, DWORD Size) +{ + HANDLE FileHandle; + DWORD BytesWritten; + + /* Create file, overwrite if it already exists */ + FileHandle = CreateFile("dump.bin", // Create this file + GENERIC_WRITE, // Open for writing + 0, // No sharing + NULL, // No security + CREATE_ALWAYS, // Create or overwrite + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (FileHandle == INVALID_HANDLE_VALUE) { + DPRINT(MID_TRACE, ("ERROR OPENING '%d'.\n", (UINT)GetLastError())); + return; + } + + if (!WriteFile(FileHandle, Buffer, Size, &BytesWritten, NULL)) { + DPRINT(MID_TRACE, ("ERROR WRITING '%d'.\n", (UINT)GetLastError())); + } + + CloseHandle(FileHandle); +} + +#endif /* DBG */ + + +/* CCFDATAStorage */ + +CCFDATAStorage::CCFDATAStorage() +/* + * FUNCTION: Default constructor + */ +{ + FileCreated = FALSE; +} + + +CCFDATAStorage::~CCFDATAStorage() +/* + * FUNCTION: Default destructor + */ +{ + ASSERT(!FileCreated); +} + + +ULONG CCFDATAStorage::Create(LPTSTR FileName) +/* + * FUNCTION: Creates the file + * ARGUMENTS: + * FileName = Pointer to name of file + * RETURNS: + * Status of operation + */ +{ + TCHAR FullName[MAX_PATH]; + + ASSERT(!FileCreated); + + if (GetTempPath(MAX_PATH, FullName) == 0) + return CAB_STATUS_CANNOT_CREATE; + + lstrcat(FullName, FileName); + + /* Create file, overwrite if it already exists */ + FileHandle = CreateFile(FullName, // Create this file + GENERIC_READ | GENERIC_WRITE, // Open for reading/writing + 0, // No sharing + NULL, // No security + CREATE_ALWAYS, // Create or overwrite + FILE_FLAG_SEQUENTIAL_SCAN | // Optimize for sequential scans + FILE_FLAG_DELETE_ON_CLOSE | // Delete file when closed + FILE_ATTRIBUTE_TEMPORARY, // Temporary file + NULL); // No attribute template + if (FileHandle == INVALID_HANDLE_VALUE) { + DPRINT(MID_TRACE, ("ERROR '%d'.\n", (UINT)GetLastError())); + return CAB_STATUS_CANNOT_CREATE; + } + + FileCreated = TRUE; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCFDATAStorage::Destroy() +/* + * FUNCTION: Destroys the file + * RETURNS: + * Status of operation + */ +{ + ASSERT(FileCreated); + + CloseHandle(FileHandle); + + FileCreated = FALSE; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCFDATAStorage::Truncate() +/* + * FUNCTION: Truncate the scratch file to zero bytes + * RETURNS: + * Status of operation + */ +{ + if (!SetFilePointer(FileHandle, 0, NULL, FILE_BEGIN)) + return CAB_STATUS_FAILURE; + if (!SetEndOfFile(FileHandle)) + return CAB_STATUS_FAILURE; + return CAB_STATUS_SUCCESS; +} + + +ULONG CCFDATAStorage::Position() +/* + * FUNCTION: Returns current position in file + * RETURNS: + * Current position + */ +{ + return SetFilePointer(FileHandle, 0, NULL, FILE_CURRENT); +} + + +ULONG CCFDATAStorage::Seek(LONG Position) +/* + * FUNCTION: Seeks to an absolute position + * ARGUMENTS: + * Position = Absolute position to seek to + * RETURNS: + * Status of operation + */ +{ + if (SetFilePointer(FileHandle, + Position, + NULL, + FILE_BEGIN) == 0xFFFFFFFF) + return CAB_STATUS_FAILURE; + else + return CAB_STATUS_SUCCESS; +} + + +ULONG CCFDATAStorage::ReadBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesRead) +/* + * FUNCTION: Reads a CFDATA block from the file + * ARGUMENTS: + * Data = Pointer to CFDATA block for the buffer + * Buffer = Pointer to buffer to store data read + * BytesWritten = Pointer to buffer to write number of bytes read + * RETURNS: + * Status of operation + */ +{ + if (!ReadFile(FileHandle, Buffer, Data->CompSize, BytesRead, NULL)) + return CAB_STATUS_CANNOT_READ; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCFDATAStorage::WriteBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesWritten) +/* + * FUNCTION: Writes a CFDATA block to the file + * ARGUMENTS: + * Data = Pointer to CFDATA block for the buffer + * Buffer = Pointer to buffer with data to write + * BytesWritten = Pointer to buffer to write number of bytes written + * RETURNS: + * Status of operation + */ +{ + if (!WriteFile(FileHandle, Buffer, Data->CompSize, BytesWritten, NULL)) + return CAB_STATUS_CANNOT_WRITE; + + return CAB_STATUS_SUCCESS; +} + +#endif /* CAB_READ_ONLY */ + + +/* CCabinet */ + +CCabinet::CCabinet() +/* + * FUNCTION: Default constructor + */ +{ + FileOpen = FALSE; + lstrcpy(DestPath, ""); + + FolderListHead = NULL; + FolderListTail = NULL; + FileListHead = NULL; + FileListTail = NULL; + + Codec = new CRawCodec(); + CodecId = CAB_CODEC_RAW; + CodecSelected = TRUE; + + OutputBuffer = NULL; + InputBuffer = NULL; + MaxDiskSize = 0; + BlockIsSplit = FALSE; + ScratchFile = NULL; + + FolderUncompSize = 0; + BytesLeftInBlock = 0; + ReuseBlock = FALSE; + CurrentDataNode = NULL; +} + + +CCabinet::~CCabinet() +/* + * FUNCTION: Default destructor + */ +{ + if (CodecSelected) + delete Codec; +} + + +LPTSTR CCabinet::GetFileName(LPTSTR Path) +/* + * FUNCTION: Returns a pointer to file name + * ARGUMENTS: + * Path = Pointer to string with pathname + * RETURNS: + * Pointer to filename + */ +{ + DWORD i, j; + + j = i = (Path[0] ? (Path[1] == ':' ? 2 : 0) : 0); + + while (Path [i++]) { + if (Path [i - 1] == '\\') j = i; + } + return Path + j; +} + + +VOID CCabinet::RemoveFileName(LPTSTR Path) +/* + * FUNCTION: Removes a file name from a path + * ARGUMENTS: + * Path = Pointer to string with path + */ +{ + LPTSTR FileName; + DWORD i; + + i = (Path [0] ? (Path[1] == ':' ? 2 : 0) : 0); + FileName = GetFileName(Path + i); + + if ((FileName != (Path + i)) && (FileName [-1] == '\\')) + FileName--; + if ((FileName == (Path + i)) && (FileName [0] == '\\')) + FileName++; + FileName[0] = 0; +} + + +BOOL CCabinet::NormalizePath(LPTSTR Path, + DWORD Length) +/* + * FUNCTION: Normalizes a path + * ARGUMENTS: + * Path = Pointer to string with pathname + * Length = Number of bytes in Path + * RETURNS: + * TRUE if there was enough room in Path, or FALSE + */ +{ + DWORD n; + BOOL OK = TRUE; + + if ((n = lstrlen(Path)) && + (Path[n - 1] != '\\') && + (OK = ((n + 1) < Length))) { + Path[n] = '\\'; + Path[n + 1] = 0; + } + return OK; +} + + +LPTSTR CCabinet::GetCabinetName() +/* + * FUNCTION: Returns pointer to cabinet file name + * RETURNS: + * Pointer to string with name of cabinet + */ +{ + return CabinetName; +} + + +VOID CCabinet::SetCabinetName(LPTSTR FileName) +/* + * FUNCTION: Sets cabinet file name + * ARGUMENTS: + * FileName = Pointer to string with name of cabinet + */ +{ + lstrcpy(CabinetName, FileName); +} + + +VOID CCabinet::SetDestinationPath(LPTSTR DestinationPath) +/* + * FUNCTION: Sets destination path + * ARGUMENTS: + * DestinationPath = Pointer to string with name of destination path + */ +{ + lstrcpy(DestPath, DestinationPath); + if (lstrlen(DestPath) > 0) + NormalizePath(DestPath, MAX_PATH); +} + + +LPTSTR CCabinet::GetDestinationPath() +/* + * FUNCTION: Returns destination path + * RETURNS: + * Pointer to string with name of destination path + */ +{ + return DestPath; +} + + +DWORD CCabinet::GetCurrentDiskNumber() +/* + * FUNCTION: Returns current disk number + * RETURNS: + * Current disk number + */ +{ + return CurrentDiskNumber; +} + + +ULONG CCabinet::Open() +/* + * FUNCTION: Opens a cabinet file + * RETURNS: + * Status of operation + */ +{ + PCFFOLDER_NODE FolderNode; + ULONG Status; + DWORD Index; + + if (!FileOpen) { + DWORD BytesRead; + DWORD Size; + + OutputBuffer = HeapAlloc(GetProcessHeap(), + 0, CAB_BLOCKSIZE + 12); // This should be enough + if (!OutputBuffer) + return CAB_STATUS_NOMEMORY; + + FileHandle = CreateFile(CabinetName, // Open this file + GENERIC_READ, // Open for reading + FILE_SHARE_READ, // Share for reading + NULL, // No security + OPEN_EXISTING, // Existing file only + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + + if (FileHandle == INVALID_HANDLE_VALUE) { + DPRINT(MID_TRACE, ("Cannot open file.\n")); + return CAB_STATUS_CANNOT_OPEN; + } + + FileOpen = TRUE; + + /* Load CAB header */ + if ((Status = ReadBlock(&CABHeader, sizeof(CFHEADER), &BytesRead)) + != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + /* Check header */ + if ((BytesRead != sizeof(CFHEADER)) || + (CABHeader.Signature != CAB_SIGNATURE ) || + (CABHeader.Version != CAB_VERSION ) || + (CABHeader.FolderCount == 0 ) || + (CABHeader.FileCount == 0 ) || + (CABHeader.FileTableOffset < sizeof(CFHEADER))) { + CloseCabinet(); + DPRINT(MID_TRACE, ("File has invalid header.\n")); + return CAB_STATUS_INVALID_CAB; + } + + Size = 0; + + /* Read/skip any reserved bytes */ + if (CABHeader.Flags & CAB_FLAG_RESERVE) { + if ((Status = ReadBlock(&Size, sizeof(DWORD), &BytesRead)) + != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + CabinetReserved = Size & 0xFFFF; + FolderReserved = (Size >> 16) & 0xFF; + DataReserved = (Size >> 24) & 0xFF; + + SetFilePointer(FileHandle, CabinetReserved, NULL, FILE_CURRENT); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_NOMEMORY; + } + } + + if ((CABHeader.Flags & CAB_FLAG_HASPREV) > 0) { + /* Read name of previous cabinet */ + Status = ReadString(CabinetPrev, 256); + if (Status != CAB_STATUS_SUCCESS) + return Status; + /* Read label of previous disk */ + Status = ReadString(DiskPrev, 256); + if (Status != CAB_STATUS_SUCCESS) + return Status; + } else { + lstrcpy(CabinetPrev, ""); + lstrcpy(DiskPrev, ""); + } + + if ((CABHeader.Flags & CAB_FLAG_HASNEXT) > 0) { + /* Read name of next cabinet */ + Status = ReadString(CabinetNext, 256); + if (Status != CAB_STATUS_SUCCESS) + return Status; + /* Read label of next disk */ + Status = ReadString(DiskNext, 256); + if (Status != CAB_STATUS_SUCCESS) + return Status; + } else { + lstrcpy(CabinetNext, ""); + lstrcpy(DiskNext, ""); + } + + /* Read all folders */ + for (Index = 0; Index < CABHeader.FolderCount; Index++) { + FolderNode = NewFolderNode(); + if (!FolderNode) { + DPRINT(MIN_TRACE, ("Insufficient resources.\n")); + return CAB_STATUS_NOMEMORY; + } + + if (Index == 0) + FolderNode->UncompOffset = FolderUncompSize; + + FolderNode->Index = Index; + + if ((Status = ReadBlock(&FolderNode->Folder, + sizeof(CFFOLDER), &BytesRead)) != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + } + + /* Read file entries */ + Status = ReadFileTable(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("ReadFileTable() failed (%d).\n", (UINT)Status)); + return Status; + } + + /* Read data blocks for all folders */ + FolderNode = FolderListHead; + while (FolderNode != NULL) { + Status = ReadDataBlocks(FolderNode); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("ReadDataBlocks() failed (%d).\n", (UINT)Status)); + return Status; + } + FolderNode = FolderNode->Next; + } + } + return CAB_STATUS_SUCCESS; +} + + +VOID CCabinet::Close() +/* + * FUNCTION: Closes the cabinet file + */ +{ + if (FileOpen) { + CloseHandle(FileHandle); + FileOpen = FALSE; + } +} + + +ULONG CCabinet::FindFirst(LPTSTR FileName, + PCAB_SEARCH Search) +/* + * FUNCTION: Finds the first file in the cabinet that matches a search criteria + * ARGUMENTS: + * FileName = Pointer to search criteria + * Search = Pointer to search structure + * RETURNS: + * Status of operation + */ +{ + RestartSearch = FALSE; + strncpy(Search->Search, FileName, MAX_PATH); + Search->Next = FileListHead; + return FindNext(Search); +} + + +ULONG CCabinet::FindNext(PCAB_SEARCH Search) +/* + * FUNCTION: Finds next file in the cabinet that matches a search criteria + * ARGUMENTS: + * Search = Pointer to search structure + * RETURNS: + * Status of operation + */ +{ + ULONG Status; + + if (RestartSearch) { + Search->Next = FileListHead; + + /* Skip split files already extracted */ + while ((Search->Next) && + (Search->Next->File.FileControlID > CAB_FILE_MAX_FOLDER) && + (Search->Next->File.FileOffset <= LastFileOffset)) { + DPRINT(MAX_TRACE, ("Skipping file (%s) FileOffset (0x%X) LastFileOffset (0x%X).\n", + Search->Next->FileName, Search->Next->File.FileOffset, LastFileOffset)); + Search->Next = Search->Next->Next; + } + + RestartSearch = FALSE; + } + + /* FIXME: Check search criteria */ + + if (!Search->Next) { + if (lstrlen(DiskNext) > 0) { + CloseCabinet(); + + SetCabinetName(CabinetNext); + + OnDiskChange(CabinetNext, DiskNext); + + Status = Open(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + + Search->Next = FileListHead; + if (!Search->Next) + return CAB_STATUS_NOFILE; + } else + return CAB_STATUS_NOFILE; + } + + Search->File = &Search->Next->File; + Search->FileName = Search->Next->FileName; + Search->Next = Search->Next->Next; + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::ExtractFile(LPTSTR FileName) +/* + * FUNCTION: Extracts a file from the cabinet + * ARGUMENTS: + * FileName = Pointer to buffer with name of file + * RETURNS + * Status of operation + */ +{ + DWORD Size; + DWORD Offset; + DWORD BytesRead; + DWORD BytesToRead; + DWORD BytesWritten; + DWORD BytesSkipped; + DWORD BytesToWrite; + DWORD TotalBytesRead; + DWORD CurrentOffset; + PUCHAR Buffer; + PUCHAR CurrentBuffer; + HANDLE DestFile; + PCFFILE_NODE File; + CFDATA CFData; + ULONG Status; + BOOL Skip; + FILETIME FileTime; + TCHAR DestName[MAX_PATH]; + TCHAR TempName[MAX_PATH]; + + Status = LocateFile(FileName, &File); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MID_TRACE, ("Cannot locate file (%d).\n", (UINT)Status)); + return Status; + } + + LastFileOffset = File->File.FileOffset; + + switch (CurrentFolderNode->Folder.CompressionType & CAB_COMP_MASK) { + case CAB_COMP_NONE: + SelectCodec(CAB_CODEC_RAW); + break; + case CAB_COMP_MSZIP: + SelectCodec(CAB_CODEC_MSZIP); + break; + default: + return CAB_STATUS_UNSUPPCOMP; + } + + DPRINT(MAX_TRACE, ("Extracting file at uncompressed offset (0x%X) Size (%d bytes) AO (0x%X) UO (0x%X).\n", + (UINT)File->File.FileOffset, + (UINT)File->File.FileSize, + (UINT)File->DataBlock->AbsoluteOffset, + (UINT)File->DataBlock->UncompOffset)); + + lstrcpy(DestName, DestPath); + lstrcat(DestName, FileName); + + /* Create destination file, fail if it already exists */ + DestFile = CreateFile(DestName, // Create this file + GENERIC_WRITE, // Open for writing + 0, // No sharing + NULL, // No security + CREATE_NEW, // New file only + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (DestFile == INVALID_HANDLE_VALUE) { + /* If file exists, ask to overwrite file */ + if (((Status = GetLastError()) == ERROR_FILE_EXISTS) && + (OnOverwrite(&File->File, FileName))) { + /* Create destination file, overwrite if it already exists */ + DestFile = CreateFile(DestName, // Create this file + GENERIC_WRITE, // Open for writing + 0, // No sharing + NULL, // No security + TRUNCATE_EXISTING, // Truncate the file + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (DestFile == INVALID_HANDLE_VALUE) + return CAB_STATUS_CANNOT_CREATE; + } else { + if (Status == ERROR_FILE_EXISTS) + return CAB_STATUS_FILE_EXISTS; + else + return CAB_STATUS_CANNOT_CREATE; + } + } + + if (!DosDateTimeToFileTime(File->File.FileDate, File->File.FileTime, &FileTime)) { + CloseHandle(DestFile); + DPRINT(MIN_TRACE, ("DosDateTimeToFileTime() failed (%d).\n", GetLastError())); + return CAB_STATUS_CANNOT_WRITE; + } + + SetFileTime(DestFile, NULL, &FileTime, NULL); + + SetAttributesOnFile(File); + + Buffer = (PUCHAR)HeapAlloc(GetProcessHeap(), + 0, CAB_BLOCKSIZE + 12); // This should be enough + if (!Buffer) { + CloseHandle(DestFile); + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + /* Call OnExtract event handler */ + OnExtract(&File->File, FileName); + + /* Search to start of file */ + Offset = SetFilePointer(FileHandle, + File->DataBlock->AbsoluteOffset, + NULL, + FILE_BEGIN); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_INVALID_CAB; + } + + Size = File->File.FileSize; + Offset = File->File.FileOffset; + CurrentOffset = File->DataBlock->UncompOffset; + + Skip = TRUE; + + ReuseBlock = (CurrentDataNode == File->DataBlock); + if (Size > 0) { + do { + DPRINT(MAX_TRACE, ("CO (0x%X) ReuseBlock (%d) Offset (0x%X) Size (%d) BytesLeftInBlock (%d)\n", + File->DataBlock->UncompOffset, (UINT)ReuseBlock, Offset, Size, + BytesLeftInBlock)); + + if (/*(CurrentDataNode != File->DataBlock) &&*/ (!ReuseBlock) || (BytesLeftInBlock <= 0)) { + + DPRINT(MAX_TRACE, ("Filling buffer. ReuseBlock (%d)\n", (UINT)ReuseBlock)); + + CurrentBuffer = Buffer; + TotalBytesRead = 0; + do { + DPRINT(MAX_TRACE, ("Size (%d bytes).\n", Size)); + + if (((Status = ReadBlock(&CFData, sizeof(CFDATA), &BytesRead)) != + CAB_STATUS_SUCCESS) || (BytesRead != sizeof(CFDATA))) { + CloseHandle(DestFile); + HeapFree(GetProcessHeap(), 0, Buffer); + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + DPRINT(MAX_TRACE, ("Data block: Checksum (0x%X) CompSize (%d bytes) UncompSize (%d bytes) Offset (0x%X).\n", + (UINT)CFData.Checksum, + (UINT)CFData.CompSize, + (UINT)CFData.UncompSize, + (UINT)SetFilePointer(FileHandle, 0, NULL, FILE_CURRENT))); + + ASSERT(CFData.CompSize <= CAB_BLOCKSIZE + 12); + + BytesToRead = CFData.CompSize; + + DPRINT(MAX_TRACE, ("Read: (0x%X,0x%X).\n", + CurrentBuffer, Buffer)); + + if (((Status = ReadBlock(CurrentBuffer, BytesToRead, &BytesRead)) != + CAB_STATUS_SUCCESS) || (BytesToRead != BytesRead)) { + CloseHandle(DestFile); + HeapFree(GetProcessHeap(), 0, Buffer); + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + /* FIXME: Does not work with files generated by makecab.exe */ +/* + if (CFData.Checksum != 0) { + DWORD Checksum = ComputeChecksum(CurrentBuffer, BytesRead, 0); + if (Checksum != CFData.Checksum) { + CloseHandle(DestFile); + HeapFree(GetProcessHeap(), 0, Buffer); + DPRINT(MIN_TRACE, ("Bad checksum (is 0x%X, should be 0x%X).\n", + Checksum, CFData.Checksum)); + return CAB_STATUS_INVALID_CAB; + } + } +*/ + TotalBytesRead += BytesRead; + + CurrentBuffer += BytesRead; + + if (CFData.UncompSize == 0) { + if (lstrlen(DiskNext) == 0) + return CAB_STATUS_NOFILE; + + /* CloseCabinet() will destroy all file entries so in case + FileName refers to the FileName field of a CFFOLDER_NODE + structure, we have to save a copy of the filename */ + lstrcpy(TempName, FileName); + + CloseCabinet(); + + SetCabinetName(CabinetNext); + + OnDiskChange(CabinetNext, DiskNext); + + Status = Open(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + + /* The first data block of the file will not be + found as it is located in the previous file */ + Status = LocateFile(TempName, &File); + if (Status == CAB_STATUS_NOFILE) { + DPRINT(MID_TRACE, ("Cannot locate file (%d).\n", (UINT)Status)); + return Status; + } + + /* The file is continued in the first data block in the folder */ + File->DataBlock = CurrentFolderNode->DataListHead; + + /* Search to start of file */ + SetFilePointer(FileHandle, + File->DataBlock->AbsoluteOffset, + NULL, + FILE_BEGIN); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_INVALID_CAB; + } + + DPRINT(MAX_TRACE, ("Continuing extraction of file at uncompressed offset (0x%X) Size (%d bytes) AO (0x%X) UO (0x%X).\n", + (UINT)File->File.FileOffset, + (UINT)File->File.FileSize, + (UINT)File->DataBlock->AbsoluteOffset, + (UINT)File->DataBlock->UncompOffset)); + + CurrentDataNode = File->DataBlock; + ReuseBlock = TRUE; + + RestartSearch = TRUE; + } + } while (CFData.UncompSize == 0); + + DPRINT(MAX_TRACE, ("TotalBytesRead (%d).\n", TotalBytesRead)); + + Status = Codec->Uncompress(OutputBuffer, Buffer, TotalBytesRead, &BytesToWrite); + if (Status != CS_SUCCESS) { + CloseHandle(DestFile); + HeapFree(GetProcessHeap(), 0, Buffer); + DPRINT(MID_TRACE, ("Cannot uncompress block.\n")); + if (Status == CS_NOMEMORY) + return CAB_STATUS_NOMEMORY; + return CAB_STATUS_INVALID_CAB; + } + + if (BytesToWrite != CFData.UncompSize) { + DPRINT(MID_TRACE, ("BytesToWrite (%d) != CFData.UncompSize (%d)\n", + BytesToWrite, CFData.UncompSize)); + return CAB_STATUS_INVALID_CAB; + } + + BytesLeftInBlock = BytesToWrite; + } else { + DPRINT(MAX_TRACE, ("Using same buffer. ReuseBlock (%d)\n", (UINT)ReuseBlock)); + + BytesToWrite = BytesLeftInBlock; + + DPRINT(MAX_TRACE, ("Seeking to absolute offset 0x%X.\n", + CurrentDataNode->AbsoluteOffset + sizeof(CFDATA) + + CurrentDataNode->Data.CompSize)); + + if (((Status = ReadBlock(&CFData, sizeof(CFDATA), &BytesRead)) != + CAB_STATUS_SUCCESS) || (BytesRead != sizeof(CFDATA))) { + CloseHandle(DestFile); + HeapFree(GetProcessHeap(), 0, Buffer); + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + DPRINT(MAX_TRACE, ("CFData.CompSize 0x%X CFData.UncompSize 0x%X.\n", + CFData.CompSize, CFData.UncompSize)); + + /* Go to next data block */ + SetFilePointer(FileHandle, + CurrentDataNode->AbsoluteOffset + sizeof(CFDATA) + + CurrentDataNode->Data.CompSize, + NULL, + FILE_BEGIN); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_INVALID_CAB; + } + + ReuseBlock = FALSE; + } + + if (Skip) + BytesSkipped = (Offset - CurrentOffset); + else + BytesSkipped = 0; + + BytesToWrite -= BytesSkipped; + + if (Size < BytesToWrite) + BytesToWrite = Size; + + DPRINT(MAX_TRACE, ("Offset (0x%X) CurrentOffset (0x%X) ToWrite (%d) Skipped (%d)(%d) Size (%d).\n", + (UINT)Offset, + (UINT)CurrentOffset, + (UINT)BytesToWrite, + (UINT)BytesSkipped, (UINT)Skip, + (UINT)Size)); + + if (!WriteFile(DestFile, (PVOID)((ULONG)OutputBuffer + BytesSkipped), + BytesToWrite, &BytesWritten, NULL) || + (BytesToWrite != BytesWritten)) { + + DPRINT(MIN_TRACE, ("Status 0x%X.\n", GetLastError())); + + CloseHandle(DestFile); + HeapFree(GetProcessHeap(), 0, Buffer); + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + Size -= BytesToWrite; + + CurrentOffset += BytesToWrite; + + /* Don't skip any more bytes */ + Skip = FALSE; + } while (Size > 0); + } + + CloseHandle(DestFile); + + HeapFree(GetProcessHeap(), 0, Buffer); + + return CAB_STATUS_SUCCESS; +} + + +VOID CCabinet::SelectCodec(ULONG Id) +/* + * FUNCTION: Selects codec engine to use + * ARGUMENTS: + * Id = Codec identifier + */ +{ + if (CodecSelected) { + if (Id == CodecId) + return; + + CodecSelected = FALSE; + delete Codec; + } + + switch (Id) { + case CAB_CODEC_RAW: + Codec = new CRawCodec(); + break; + case CAB_CODEC_MSZIP: + Codec = new CMSZipCodec(); + break; + default: + return; + } + + CodecId = Id; + CodecSelected = TRUE; +} + + +#ifndef CAB_READ_ONLY + +/* CAB write methods */ + +ULONG CCabinet::NewCabinet() +/* + * FUNCTION: Creates a new cabinet + * RETURNS: + * Status of operation + */ +{ + ULONG Status; + + CurrentDiskNumber = 0; + + OutputBuffer = HeapAlloc(GetProcessHeap(), 0, CAB_BLOCKSIZE + 12); // This should be enough + InputBuffer = HeapAlloc(GetProcessHeap(), 0, CAB_BLOCKSIZE + 12); // This should be enough + if ((!OutputBuffer) || (!InputBuffer)) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + CurrentIBuffer = InputBuffer; + CurrentIBufferSize = 0; + + CABHeader.Signature = CAB_SIGNATURE; + CABHeader.Reserved1 = 0; // Not used + CABHeader.CabinetSize = 0; // Not yet known + CABHeader.Reserved2 = 0; // Not used + CABHeader.Reserved3 = 0; // Not used + CABHeader.Version = CAB_VERSION; + CABHeader.FolderCount = 0; // Not yet known + CABHeader.FileCount = 0; // Not yet known + CABHeader.Flags = 0; // Not yet known + // FIXME: Should be random + CABHeader.SetID = 0x534F; + CABHeader.CabinetNumber = 0; + + + TotalFolderSize = 0; + TotalFileSize = 0; + + DiskSize = sizeof(CFHEADER); + + InitCabinetHeader(); + + // NextFolderNumber is 0-based + NextFolderNumber = 0; + + CurrentFolderNode = NULL; + Status = NewFolder(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + + CurrentFolderNode->Folder.DataOffset = DiskSize - TotalHeaderSize; + + ScratchFile = new CCFDATAStorage; + if (!ScratchFile) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + Status = ScratchFile->Create("~CAB.tmp"); + + CreateNewFolder = FALSE; + + CreateNewDisk = FALSE; + + PrevCabinetNumber = 0; + + return Status; +} + + +ULONG CCabinet::NewDisk() +/* + * FUNCTION: Forces a new disk to be created + * RETURNS: + * Status of operation + */ +{ + // NextFolderNumber is 0-based + NextFolderNumber = 1; + + CreateNewDisk = FALSE; + + DiskSize = sizeof(CFHEADER) + TotalFolderSize + TotalFileSize; + + InitCabinetHeader(); + + CurrentFolderNode->TotalFolderSize = 0; + + CurrentFolderNode->Folder.DataBlockCount = 0; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::NewFolder() +/* + * FUNCTION: Forces a new folder to be created + * RETURNS: + * Status of operation + */ +{ + DPRINT(MAX_TRACE, ("Creating new folder.\n")); + + CurrentFolderNode = NewFolderNode(); + if (!CurrentFolderNode) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + switch (CodecId) { + case CAB_CODEC_RAW: + CurrentFolderNode->Folder.CompressionType = CAB_COMP_NONE; + break; + case CAB_CODEC_MSZIP: + CurrentFolderNode->Folder.CompressionType = CAB_COMP_MSZIP; + break; + default: + return CAB_STATUS_UNSUPPCOMP; + } + + /* FIXME: This won't work if no files are added to the new folder */ + + DiskSize += sizeof(CFFOLDER); + + TotalFolderSize += sizeof(CFFOLDER); + + NextFolderNumber++; + + CABHeader.FolderCount++; + + LastBlockStart = 0; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::WriteFileToScratchStorage(PCFFILE_NODE FileNode) +/* + * FUNCTION: Writes a file to the scratch file + * ARGUMENTS: + * FileNode = Pointer to file node + * RETURNS: + * Status of operation + */ +{ + DWORD BytesToRead; + DWORD BytesRead; + ULONG Status; + DWORD Size; + + if (!ContinueFile) { + /* Try to open file */ + SourceFile = CreateFile( + FileNode->FileName, // Open this file + GENERIC_READ, // Open for reading + FILE_SHARE_READ, // Share for reading + NULL, // No security + OPEN_EXISTING, // File must exist + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (SourceFile == INVALID_HANDLE_VALUE) { + DPRINT(MID_TRACE, ("File not found (%s).\n", FileNode->FileName)); + return CAB_STATUS_NOFILE; + } + + if (CreateNewFolder) { + /* There is always a new folder after + a split file is completely stored */ + Status = NewFolder(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + CreateNewFolder = FALSE; + } + + /* Call OnAdd event handler */ + OnAdd(&FileNode->File, FileNode->FileName); + + TotalBytesLeft = FileNode->File.FileSize; + + FileNode->File.FileOffset = CurrentFolderNode->UncompOffset; + CurrentFolderNode->UncompOffset += TotalBytesLeft; + FileNode->File.FileControlID = NextFolderNumber - 1; + CurrentFolderNode->Commit = TRUE; + PrevCabinetNumber = CurrentDiskNumber; + + Size = sizeof(CFFILE) + lstrlen(GetFileName(FileNode->FileName)) + 1; + CABHeader.FileTableOffset += Size; + TotalFileSize += Size; + DiskSize += Size; + } + + FileNode->Commit = TRUE; + + if (TotalBytesLeft > 0) { + do { + if (TotalBytesLeft > (DWORD)CAB_BLOCKSIZE - CurrentIBufferSize) + BytesToRead = CAB_BLOCKSIZE - CurrentIBufferSize; + else + BytesToRead = TotalBytesLeft; + + if ((!ReadFile(SourceFile, CurrentIBuffer, BytesToRead, &BytesRead, NULL) + != CAB_STATUS_SUCCESS) || (BytesToRead != BytesRead)) { + DPRINT(MIN_TRACE, ("Cannot read from file. BytesToRead (%d) BytesRead (%d) CurrentIBufferSize (%d).\n", + BytesToRead, BytesRead, CurrentIBufferSize)); + return CAB_STATUS_INVALID_CAB; + } + + (PUCHAR)CurrentIBuffer += BytesRead; + + CurrentIBufferSize += (WORD)BytesRead; + + if (CurrentIBufferSize == CAB_BLOCKSIZE) { + Status = WriteDataBlock(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + } + TotalBytesLeft -= BytesRead; + } while ((TotalBytesLeft > 0) && (!CreateNewDisk)); + } + + if (TotalBytesLeft == 0) { + CloseHandle(SourceFile); + FileNode->Delete = TRUE; + + if (FileNode->File.FileControlID > CAB_FILE_MAX_FOLDER) { + FileNode->File.FileControlID = CAB_FILE_CONTINUED; + CurrentFolderNode->Delete = TRUE; + + if ((CurrentIBufferSize > 0) || (CurrentOBufferSize > 0)) { + Status = WriteDataBlock(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + } + + CreateNewFolder = TRUE; + } + } else { + if (FileNode->File.FileControlID <= CAB_FILE_MAX_FOLDER) + FileNode->File.FileControlID = CAB_FILE_SPLIT; + else + FileNode->File.FileControlID = CAB_FILE_PREV_NEXT; + } + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::WriteDisk(DWORD MoreDisks) +/* + * FUNCTION: Forces the current disk to be written + * ARGUMENTS: + * MoreDisks = TRUE if there is one or more disks after this disk + * RETURNS: + * Status of operation + */ +{ + PCFFILE_NODE FileNode; + ULONG Status; + + ContinueFile = FALSE; + FileNode = FileListHead; + while (FileNode != NULL) { + + Status = WriteFileToScratchStorage(FileNode); + if (Status != CAB_STATUS_SUCCESS) + return Status; + if (CreateNewDisk) { + /* A data block could span more than two + disks if MaxDiskSize is very small */ + while (CreateNewDisk) { + DPRINT(MAX_TRACE, ("Creating new disk.\n")); + CommitDisk(TRUE); + CloseDisk(); + NewDisk(); + + ContinueFile = TRUE; + CreateNewDisk = FALSE; + + DPRINT(MAX_TRACE, ("First on new disk. CurrentIBufferSize (%d) CurrentOBufferSize (%d).\n", + CurrentIBufferSize, CurrentOBufferSize)); + + if ((CurrentIBufferSize > 0) || (CurrentOBufferSize > 0)) { + Status = WriteDataBlock(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + } + } + } else { + ContinueFile = FALSE; + FileNode = FileNode->Next; + } + } + + if ((CurrentIBufferSize > 0) || (CurrentOBufferSize > 0)) { + /* A data block could span more than two + disks if MaxDiskSize is very small */ + + ASSERT(CreateNewDisk == FALSE); + + do { + if (CreateNewDisk) { + DPRINT(MID_TRACE, ("Creating new disk 2.\n")); + CommitDisk(TRUE); + CloseDisk(); + NewDisk(); + CreateNewDisk = FALSE; + + ASSERT(FileNode == FileListHead); + } + + if ((CurrentIBufferSize > 0) || (CurrentOBufferSize > 0)) { + Status = WriteDataBlock(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + } + } while (CreateNewDisk); + } + CommitDisk(MoreDisks); + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::CommitDisk(DWORD MoreDisks) +/* + * FUNCTION: Commits the current disk + * ARGUMENTS: + * MoreDisks = TRUE if there is one or more disks after this disk + * RETURNS: + * Status of operation + */ +{ + PCFFOLDER_NODE FolderNode; + ULONG Status; + + OnCabinetName(CurrentDiskNumber, CabinetName); + + /* Create file, fail if it already exists */ + FileHandle = CreateFile(CabinetName, // Create this file + GENERIC_WRITE, // Open for writing + 0, // No sharing + NULL, // No security + CREATE_NEW, // New file only + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (FileHandle == INVALID_HANDLE_VALUE) { + DWORD Status; + /* If file exists, ask to overwrite file */ + if (((Status = GetLastError()) == ERROR_FILE_EXISTS) && + (OnOverwrite(NULL, CabinetName))) { + + /* Create cabinet file, overwrite if it already exists */ + FileHandle = CreateFile(CabinetName, // Create this file + GENERIC_WRITE, // Open for writing + 0, // No sharing + NULL, // No security + TRUNCATE_EXISTING, // Truncate the file + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (FileHandle == INVALID_HANDLE_VALUE) + return CAB_STATUS_CANNOT_CREATE; + } else { + if (Status == ERROR_FILE_EXISTS) + return CAB_STATUS_FILE_EXISTS; + else + return CAB_STATUS_CANNOT_CREATE; + } + } + + WriteCabinetHeader(MoreDisks); + + Status = WriteFolderEntries(); + if (Status != CAB_STATUS_SUCCESS) + return Status; + + /* Write file entries */ + WriteFileEntries(); + + /* Write data blocks */ + FolderNode = FolderListHead; + while (FolderNode != NULL) { + if (FolderNode->Commit) { + Status = CommitDataBlocks(FolderNode); + if (Status != CAB_STATUS_SUCCESS) + return Status; + /* Remove data blocks for folder */ + DestroyDataNodes(FolderNode); + } + FolderNode = FolderNode->Next; + } + + CloseHandle(FileHandle); + + ScratchFile->Truncate(); + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::CloseDisk() +/* + * FUNCTION: Closes the current disk + * RETURNS: + * Status of operation + */ +{ + DestroyDeletedFileNodes(); + + /* Destroy folder nodes that are completely stored */ + DestroyDeletedFolderNodes(); + + CurrentDiskNumber++; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::CloseCabinet() +/* + * FUNCTION: Closes the current cabinet + * RETURNS: + * Status of operation + */ +{ + PCFFOLDER_NODE PrevNode; + PCFFOLDER_NODE NextNode; + ULONG Status; + + DestroyFileNodes(); + + DestroyFolderNodes(); + + if (InputBuffer) { + HeapFree(GetProcessHeap(), 0, InputBuffer); + InputBuffer = NULL; + } + + if (OutputBuffer) { + HeapFree(GetProcessHeap(), 0, OutputBuffer); + OutputBuffer = NULL; + } + + Close(); + + if (ScratchFile) { + Status = ScratchFile->Destroy(); + delete ScratchFile; + return Status; + } + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::AddFile(LPTSTR FileName) +/* + * FUNCTION: Adds a file to the current disk + * ARGUMENTS: + * FileName = Pointer to string with file name (full path) + * RETURNS: + * Status of operation + */ +{ + HANDLE SrcFile; + FILETIME FileTime; + PCFFILE_NODE FileNode; + + FileNode = NewFileNode(); + if (!FileNode) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + FileNode->FolderNode = CurrentFolderNode; + + FileNode->FileName = (LPTSTR)HeapAlloc(GetProcessHeap(), + 0, lstrlen(FileName) + 1); + lstrcpy(FileNode->FileName, FileName); + + /* Try to open file */ + SrcFile = CreateFile( + FileNode->FileName, // Open this file + GENERIC_READ, // Open for reading + FILE_SHARE_READ, // Share for reading + NULL, // No security + OPEN_EXISTING, // File must exist + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (SrcFile == INVALID_HANDLE_VALUE) { + DPRINT(MID_TRACE, ("File not found (%s).\n", FileNode->FileName)); + return CAB_STATUS_CANNOT_OPEN; + } + + /* FIXME: Check for and handle large files (>= 2GB) */ + FileNode->File.FileSize = GetFileSize(SrcFile, NULL); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("Cannot read from file.\n")); + return CAB_STATUS_CANNOT_READ; + } + + if (GetFileTime(SrcFile, NULL, &FileTime, NULL)) + FileTimeToDosDateTime(&FileTime, + &FileNode->File.FileDate, + &FileNode->File.FileTime); + + GetAttributesOnFile(FileNode); + + CloseHandle(SrcFile); + + return CAB_STATUS_SUCCESS; +} + + +VOID CCabinet::SetMaxDiskSize(DWORD Size) +/* + * FUNCTION: Sets the maximum size of the current disk + * ARGUMENTS: + * Size = Maximum size of current disk (0 means no maximum size) + */ +{ + MaxDiskSize = Size; +} + +#endif /* CAB_READ_ONLY */ + + +/* Default event handlers */ + +BOOL CCabinet::OnOverwrite(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called when extracting a file and it already exists + * ARGUMENTS: + * File = Pointer to CFFILE for file being extracted + * FileName = Pointer to buffer with name of file (full path) + * RETURNS + * TRUE if the file should be overwritten, FALSE if not + */ +{ + return FALSE; +} + + +VOID CCabinet::OnExtract(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called just before extracting a file + * ARGUMENTS: + * File = Pointer to CFFILE for file being extracted + * FileName = Pointer to buffer with name of file (full path) + */ +{ +} + + +VOID CCabinet::OnDiskChange(LPTSTR CabinetName, + LPTSTR DiskLabel) +/* + * FUNCTION: Called when a new disk is to be processed + * ARGUMENTS: + * CabinetName = Pointer to buffer with name of cabinet + * DiskLabel = Pointer to buffer with label of disk + */ +{ +} + + +#ifndef CAB_READ_ONLY + +VOID CCabinet::OnAdd(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called just before adding a file to a cabinet + * ARGUMENTS: + * File = Pointer to CFFILE for file being added + * FileName = Pointer to buffer with name of file (full path) + */ +{ +} + + +BOOL CCabinet::OnDiskLabel(ULONG Number, LPTSTR Label) +/* + * FUNCTION: Called when a disk needs a label + * ARGUMENTS: + * Number = Cabinet number that needs a label + * Label = Pointer to buffer to place label of disk + * RETURNS: + * TRUE if a disk label was returned, FALSE if not + */ +{ + return FALSE; +} + + +BOOL CCabinet::OnCabinetName(ULONG Number, LPTSTR Name) +/* + * FUNCTION: Called when a cabinet needs a name + * ARGUMENTS: + * Number = Disk number that needs a name + * Name = Pointer to buffer to place name of cabinet + * RETURNS: + * TRUE if a cabinet name was returned, FALSE if not + */ +{ + return FALSE; +} + +#endif /* CAB_READ_ONLY */ + +PCFFOLDER_NODE CCabinet::LocateFolderNode(DWORD Index) +/* + * FUNCTION: Locates a folder node + * ARGUMENTS: + * Index = Folder index + * RETURNS: + * Pointer to folder node or NULL if the folder node was not found + */ +{ + PCFFOLDER_NODE Node; + + switch (Index) { + case CAB_FILE_SPLIT: + return FolderListTail; + + case CAB_FILE_CONTINUED: + case CAB_FILE_PREV_NEXT: + return FolderListHead; + } + + Node = FolderListHead; + while (Node != NULL) { + if (Node->Index == Index) + return Node; + Node = Node->Next; + } + return NULL; +} + + +ULONG CCabinet::GetAbsoluteOffset(PCFFILE_NODE File) +/* + * FUNCTION: Returns the absolute offset of a file + * ARGUMENTS: + * File = Pointer to CFFILE_NODE structure for file + * RETURNS: + * Status of operation + */ +{ + PCFDATA_NODE Node; + + DPRINT(MAX_TRACE, ("FileName '%s' FileOffset (0x%X) FileSize (%d).\n", + (LPTSTR)File->FileName, + (UINT)File->File.FileOffset, + (UINT)File->File.FileSize)); + + Node = CurrentFolderNode->DataListHead; + while (Node != NULL) { + + DPRINT(MAX_TRACE, ("GetAbsoluteOffset(): Comparing (0x%X, 0x%X) (%d).\n", + (UINT)Node->UncompOffset, + (UINT)Node->UncompOffset + Node->Data.UncompSize, + (UINT)Node->Data.UncompSize)); + + /* Node->Data.UncompSize will be 0 if the block is split + (ie. it is the last block in this cabinet) */ + if ((Node->Data.UncompSize == 0) || + ((File->File.FileOffset >= Node->UncompOffset) && + (File->File.FileOffset < Node->UncompOffset + + Node->Data.UncompSize))) { + File->DataBlock = Node; + return CAB_STATUS_SUCCESS; + } + + Node = Node->Next; + } + return CAB_STATUS_INVALID_CAB; +} + + +ULONG CCabinet::LocateFile(LPTSTR FileName, + PCFFILE_NODE *File) +/* + * FUNCTION: Locates a file in the cabinet + * ARGUMENTS: + * FileName = Pointer to string with name of file to locate + * File = Address of pointer to CFFILE_NODE structure to fill + * RETURNS: + * Status of operation + * NOTES: + * Current folder is set to the folder of the file + */ +{ + PCFFILE_NODE Node; + ULONG Status; + + DPRINT(MAX_TRACE, ("FileName '%s'\n", FileName)); + + Node = FileListHead; + while (Node != NULL) { + if (lstrcmpi(FileName, Node->FileName) == 0) { + + CurrentFolderNode = LocateFolderNode(Node->File.FileControlID); + if (!CurrentFolderNode) { + DPRINT(MID_TRACE, ("Folder with index number (%d) not found.\n", + (UINT)Node->File.FileControlID)); + return CAB_STATUS_INVALID_CAB; + } + + if (Node->DataBlock == NULL) { + Status = GetAbsoluteOffset(Node); + } else + Status = CAB_STATUS_SUCCESS; + *File = Node; + return Status; + } + Node = Node->Next; + } + return CAB_STATUS_NOFILE; +} + + +ULONG CCabinet::ReadString(LPTSTR String, DWORD MaxLength) +/* + * FUNCTION: Reads a NULL-terminated string from the cabinet + * ARGUMENTS: + * String = Pointer to buffer to place string + * MaxLength = Maximum length of string + * RETURNS: + * Status of operation + */ +{ + DWORD BytesRead; + DWORD Offset; + ULONG Status; + DWORD Size; + BOOL Found; + + Offset = 0; + Found = FALSE; + do { + Size = ((Offset + 32) <= MaxLength)? 32 : MaxLength - Offset; + + if (Size == 0) { + DPRINT(MIN_TRACE, ("Too long a filename.\n")); + return CAB_STATUS_INVALID_CAB; + } + + Status = ReadBlock(&String[Offset], Size, &BytesRead); + if ((Status != CAB_STATUS_SUCCESS) || (BytesRead != Size)) { + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + for (Size = Offset; Size < Offset + BytesRead; Size++) { + if (String[Size] == '\0') { + Found = TRUE; + break; + } + } + + Offset += BytesRead; + + } while (!Found); + + /* Back up some bytes */ + Size = (BytesRead - Size) - 1; + SetFilePointer(FileHandle, -(LONG)Size, NULL, FILE_CURRENT); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_INVALID_CAB; + } + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::ReadFileTable() +/* + * FUNCTION: Reads the file table from the cabinet file + * RETURNS: + * Status of operation + */ +{ + ULONG i; + ULONG Status; + DWORD BytesRead; + PCFFILE_NODE File; + + DPRINT(MAX_TRACE, ("Reading file table at absolute offset (0x%X).\n", + CABHeader.FileTableOffset)); + + /* Seek to file table */ + SetFilePointer(FileHandle, CABHeader.FileTableOffset, NULL, FILE_BEGIN); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_INVALID_CAB; + } + + for (i = 0; i < CABHeader.FileCount; i++) { + File = NewFileNode(); + if (!File) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + if ((Status = ReadBlock(&File->File, sizeof(CFFILE), + &BytesRead)) != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + File->FileName = (LPTSTR)HeapAlloc(GetProcessHeap(), 0, MAX_PATH); + if (!File->FileName) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + /* Read file name */ + Status = ReadString(File->FileName, MAX_PATH); + if (Status != CAB_STATUS_SUCCESS) + return Status; + + DPRINT(MAX_TRACE, ("Found file '%s' at uncompressed offset (0x%X). Size (%d bytes) ControlId (0x%X).\n", + (LPTSTR)File->FileName, + (UINT)File->File.FileOffset, + (UINT)File->File.FileSize, + (UINT)File->File.FileControlID)); + + } + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::ReadDataBlocks(PCFFOLDER_NODE FolderNode) +/* + * FUNCTION: Reads all CFDATA blocks for a folder from the cabinet file + * ARGUMENTS: + * FolderNode = Pointer to CFFOLDER_NODE structure for folder + * RETURNS: + * Status of operation + */ +{ + DWORD AbsoluteOffset; + DWORD UncompOffset; + PCFDATA_NODE Node; + DWORD BytesRead; + ULONG Status; + ULONG i; + + DPRINT(MAX_TRACE, ("Reading data blocks for folder (%d) at absolute offset (0x%X).\n", + FolderNode->Index, FolderNode->Folder.DataOffset)); + + AbsoluteOffset = FolderNode->Folder.DataOffset; + UncompOffset = FolderNode->UncompOffset; + + for (i = 0; i < FolderNode->Folder.DataBlockCount; i++) { + Node = NewDataNode(FolderNode); + if (!Node) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + /* Seek to data block */ + SetFilePointer(FileHandle, AbsoluteOffset, NULL, FILE_BEGIN); + if (GetLastError() != NO_ERROR) { + DPRINT(MIN_TRACE, ("SetFilePointer() failed.\n")); + return CAB_STATUS_INVALID_CAB; + } + + if ((Status = ReadBlock(&Node->Data, sizeof(CFDATA), + &BytesRead)) != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot read from file (%d).\n", (UINT)Status)); + return CAB_STATUS_INVALID_CAB; + } + + DPRINT(MAX_TRACE, ("AbsOffset (0x%X) UncompOffset (0x%X) Checksum (0x%X) CompSize (%d) UncompSize (%d).\n", + (UINT)AbsoluteOffset, + (UINT)UncompOffset, + (UINT)Node->Data.Checksum, + (UINT)Node->Data.CompSize, + (UINT)Node->Data.UncompSize)); + + Node->AbsoluteOffset = AbsoluteOffset; + Node->UncompOffset = UncompOffset; + + AbsoluteOffset += sizeof(CFDATA) + Node->Data.CompSize; + UncompOffset += Node->Data.UncompSize; + } + + FolderUncompSize = UncompOffset; + + return CAB_STATUS_SUCCESS; +} + + +PCFFOLDER_NODE CCabinet::NewFolderNode() +/* + * FUNCTION: Creates a new folder node + * RETURNS: + * Pointer to node if there was enough free memory available, otherwise NULL + */ +{ + PCFFOLDER_NODE Node; + + Node = (PCFFOLDER_NODE)HeapAlloc(GetProcessHeap(), + 0, sizeof(CFFOLDER_NODE)); + if (!Node) + return NULL; + + ZeroMemory(Node, sizeof(CFFOLDER_NODE)); + + Node->Folder.CompressionType = CAB_COMP_NONE; + + Node->Prev = FolderListTail; + + if (FolderListTail != NULL) { + FolderListTail->Next = Node; + } else { + FolderListHead = Node; + } + FolderListTail = Node; + + return Node; +} + + +PCFFILE_NODE CCabinet::NewFileNode() +/* + * FUNCTION: Creates a new file node + * ARGUMENTS: + * FolderNode = Pointer to folder node to bind file to + * RETURNS: + * Pointer to node if there was enough free memory available, otherwise NULL + */ +{ + PCFFILE_NODE Node; + + Node = (PCFFILE_NODE)HeapAlloc(GetProcessHeap(), + 0, sizeof(CFFILE_NODE)); + if (!Node) + return NULL; + + ZeroMemory(Node, sizeof(CFFILE_NODE)); + + Node->Prev = FileListTail; + + if (FileListTail != NULL) { + FileListTail->Next = Node; + } else { + FileListHead = Node; + } + FileListTail = Node; + + return Node; +} + + +PCFDATA_NODE CCabinet::NewDataNode(PCFFOLDER_NODE FolderNode) +/* + * FUNCTION: Creates a new data block node + * ARGUMENTS: + * FolderNode = Pointer to folder node to bind data block to + * RETURNS: + * Pointer to node if there was enough free memory available, otherwise NULL + */ +{ + PCFDATA_NODE Node; + + Node = (PCFDATA_NODE)HeapAlloc(GetProcessHeap(), + 0, sizeof(CFDATA_NODE)); + if (!Node) + return NULL; + + ZeroMemory(Node, sizeof(CFDATA_NODE)); + + Node->Prev = FolderNode->DataListTail; + + if (FolderNode->DataListTail != NULL) { + FolderNode->DataListTail->Next = Node; + } else { + FolderNode->DataListHead = Node; + } + FolderNode->DataListTail = Node; + + return Node; +} + + +VOID CCabinet::DestroyDataNodes(PCFFOLDER_NODE FolderNode) +/* + * FUNCTION: Destroys data block nodes bound to a folder node + * ARGUMENTS: + * FolderNode = Pointer to folder node + */ +{ + PCFDATA_NODE PrevNode; + PCFDATA_NODE NextNode; + + NextNode = FolderNode->DataListHead; + while (NextNode != NULL) { + PrevNode = NextNode->Next; + HeapFree(GetProcessHeap(), 0, NextNode); + NextNode = PrevNode; + } + FolderNode->DataListHead = NULL; + FolderNode->DataListTail = NULL; +} + + +VOID CCabinet::DestroyFileNodes() +/* + * FUNCTION: Destroys file nodes + * ARGUMENTS: + * FolderNode = Pointer to folder node + */ +{ + PCFFILE_NODE PrevNode; + PCFFILE_NODE NextNode; + + NextNode = FileListHead; + while (NextNode != NULL) { + PrevNode = NextNode->Next; + if (NextNode->FileName) + HeapFree(GetProcessHeap(), 0, NextNode->FileName); + HeapFree(GetProcessHeap(), 0, NextNode); + NextNode = PrevNode; + } + FileListHead = NULL; + FileListTail = NULL; +} + + +VOID CCabinet::DestroyDeletedFileNodes() +/* + * FUNCTION: Destroys file nodes that are marked for deletion + */ +{ + PCFFILE_NODE CurNode; + PCFFILE_NODE NextNode; + + CurNode = FileListHead; + while (CurNode != NULL) { + NextNode = CurNode->Next; + + if (CurNode->Delete) { + if (CurNode->Prev != NULL) { + CurNode->Prev->Next = CurNode->Next; + } else { + FileListHead = CurNode->Next; + if (FileListHead) + FileListHead->Prev = NULL; + } + + if (CurNode->Next != NULL) { + CurNode->Next->Prev = CurNode->Prev; + } else { + FileListTail = CurNode->Prev; + if (FileListTail) + FileListTail->Next = NULL; + } + + DPRINT(MAX_TRACE, ("Deleting file: '%s'\n", CurNode->FileName)); + + TotalFileSize -= (sizeof(CFFILE) + lstrlen(GetFileName(CurNode->FileName)) + 1); + + if (CurNode->FileName) + HeapFree(GetProcessHeap(), 0, CurNode->FileName); + HeapFree(GetProcessHeap(), 0, CurNode); + } + CurNode = NextNode; + } +} + + +VOID CCabinet::DestroyFolderNodes() +/* + * FUNCTION: Destroys folder nodes + */ +{ + PCFFOLDER_NODE PrevNode; + PCFFOLDER_NODE NextNode; + + NextNode = FolderListHead; + while (NextNode != NULL) { + PrevNode = NextNode->Next; + DestroyDataNodes(NextNode); + HeapFree(GetProcessHeap(), 0, NextNode); + NextNode = PrevNode; + } + FolderListHead = NULL; + FolderListTail = NULL; +} + + +VOID CCabinet::DestroyDeletedFolderNodes() +/* + * FUNCTION: Destroys folder nodes that are marked for deletion + */ +{ + PCFFOLDER_NODE CurNode; + PCFFOLDER_NODE NextNode; + + CurNode = FolderListHead; + while (CurNode != NULL) { + NextNode = CurNode->Next; + + if (CurNode->Delete) { + if (CurNode->Prev != NULL) { + CurNode->Prev->Next = CurNode->Next; + } else { + FolderListHead = CurNode->Next; + if (FolderListHead) + FolderListHead->Prev = NULL; + } + + if (CurNode->Next != NULL) { + CurNode->Next->Prev = CurNode->Prev; + } else { + FolderListTail = CurNode->Prev; + if (FolderListTail) + FolderListTail->Next = NULL; + } + + DestroyDataNodes(CurNode); + HeapFree(GetProcessHeap(), 0, CurNode); + + TotalFolderSize -= sizeof(CFFOLDER); + } + CurNode = NextNode; + } +} + + +ULONG CCabinet::ComputeChecksum(PVOID Buffer, + UINT Size, + ULONG Seed) +/* + * FUNCTION: Computes checksum for data block + * ARGUMENTS: + * Buffer = Pointer to data buffer + * Size = Length of data buffer + * Seed = Previously computed checksum + * RETURNS: + * Checksum of buffer + */ +{ + INT UlongCount; // Number of ULONGs in block + ULONG Checksum; // Checksum accumulator + PBYTE pb; + ULONG ul; + + /* FIXME: Doesn't seem to be correct. EXTRACT.EXE + won't accept checksums computed by this routine */ + + DPRINT(MIN_TRACE, ("Checksumming buffer (0x%X) Size (%d)\n", (UINT)Buffer, Size)); + + UlongCount = Size / 4; // Number of ULONGs + Checksum = Seed; // Init checksum + pb = (PBYTE)Buffer; // Start at front of data block + + /* Checksum integral multiple of ULONGs */ + while (UlongCount-- > 0) { + /* NOTE: Build ULONG in big/little-endian independent manner */ + ul = *pb++; // Get low-order byte + ul |= (((ULONG)(*pb++)) << 8); // Add 2nd byte + ul |= (((ULONG)(*pb++)) << 16); // Add 3nd byte + ul |= (((ULONG)(*pb++)) << 24); // Add 4th byte + + Checksum ^= ul; // Update checksum + } + + /* Checksum remainder bytes */ + ul = 0; + switch (Size % 4) { + case 3: + ul |= (((ULONG)(*pb++)) << 16); // Add 3rd byte + case 2: + ul |= (((ULONG)(*pb++)) << 8); // Add 2nd byte + case 1: + ul |= *pb++; // Get low-order byte + default: + break; + } + Checksum ^= ul; // Update checksum + + /* Return computed checksum */ + return Checksum; +} + + +ULONG CCabinet::ReadBlock(PVOID Buffer, + DWORD Size, + PDWORD BytesRead) +/* + * FUNCTION: Read a block of data from file + * ARGUMENTS: + * Buffer = Pointer to data buffer + * Size = Length of data buffer + * BytesRead = Pointer to DWORD that on return will contain + * number of bytes read + * RETURNS: + * Status of operation + */ +{ + if (!ReadFile(FileHandle, Buffer, Size, BytesRead, NULL)) + return CAB_STATUS_INVALID_CAB; + return CAB_STATUS_SUCCESS; +} + +#ifndef CAB_READ_ONLY + +ULONG CCabinet::InitCabinetHeader() +/* + * FUNCTION: Initializes cabinet header and optional fields + * RETURNS: + * Status of operation + */ +{ + PCFFOLDER_NODE FolderNode; + PCFFILE_NODE FileNode; + DWORD TotalSize; + DWORD Size; + + CABHeader.FileTableOffset = 0; // Not known yet + CABHeader.FolderCount = 0; // Not known yet + CABHeader.FileCount = 0; // Not known yet + CABHeader.Flags = 0; // Not known yet + + CABHeader.CabinetNumber = CurrentDiskNumber; + + if ((CurrentDiskNumber > 0) && (OnCabinetName(PrevCabinetNumber, CabinetPrev))) { + CABHeader.Flags |= CAB_FLAG_HASPREV; + if (!OnDiskLabel(PrevCabinetNumber, DiskPrev)) + lstrcpy(CabinetPrev, ""); + } + + if (OnCabinetName(CurrentDiskNumber + 1, CabinetNext)) { + CABHeader.Flags |= CAB_FLAG_HASNEXT; + if (!OnDiskLabel(CurrentDiskNumber + 1, DiskNext)) + lstrcpy(DiskNext, ""); + } + + TotalSize = 0; + + if ((CABHeader.Flags & CAB_FLAG_HASPREV) > 0) { + + DPRINT(MAX_TRACE, ("CabinetPrev '%s'.\n", CabinetPrev)); + + /* Calculate size of name of previous cabinet */ + TotalSize += lstrlen(CabinetPrev) + 1; + + /* Calculate size of label of previous disk */ + TotalSize += lstrlen(DiskPrev) + 1; + } + + if ((CABHeader.Flags & CAB_FLAG_HASNEXT) > 0) { + + DPRINT(MAX_TRACE, ("CabinetNext '%s'.\n", CabinetNext)); + + /* Calculate size of name of next cabinet */ + Size = lstrlen(CabinetNext) + 1; + TotalSize += Size; + NextFieldsSize = Size; + + /* Calculate size of label of next disk */ + Size = lstrlen(DiskNext) + 1; + TotalSize += Size; + NextFieldsSize += Size; + } else + NextFieldsSize = 0; + + DiskSize += TotalSize; + + /* FIXME: Add cabinet reserved area size */ + TotalHeaderSize = sizeof(CFHEADER) + TotalSize; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::WriteCabinetHeader(BOOL MoreDisks) +/* + * FUNCTION: Writes the cabinet header and optional fields + * ARGUMENTS: + * MoreDisks = TRUE if next cabinet name should be included + * RETURNS: + * Status of operation + */ +{ + PCFFOLDER_NODE FolderNode; + PCFFILE_NODE FileNode; + DWORD BytesWritten; + DWORD Size; + + if (MoreDisks) { + CABHeader.Flags |= CAB_FLAG_HASNEXT; + Size = TotalHeaderSize; + } else { + CABHeader.Flags &= ~CAB_FLAG_HASNEXT; + DiskSize -= NextFieldsSize; + Size = TotalHeaderSize - NextFieldsSize; + } + + /* Set absolute folder offsets */ + BytesWritten = Size + TotalFolderSize + TotalFileSize; + CABHeader.FolderCount = 0; + FolderNode = FolderListHead; + while (FolderNode != NULL) { + FolderNode->Folder.DataOffset = BytesWritten; + + BytesWritten += FolderNode->TotalFolderSize; + + CABHeader.FolderCount++; + + FolderNode = FolderNode->Next; + } + + /* Set absolute offset of file table */ + CABHeader.FileTableOffset = Size + TotalFolderSize; + + /* Count number of files to be committed */ + CABHeader.FileCount = 0; + FileNode = FileListHead; + while (FileNode != NULL) { + if (FileNode->Commit) + CABHeader.FileCount++; + FileNode = FileNode->Next; + } + + CABHeader.CabinetSize = DiskSize; + + /* Write header */ + if (!WriteFile(FileHandle, &CABHeader, sizeof(CFHEADER), &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + + if ((CABHeader.Flags & CAB_FLAG_HASPREV) > 0) { + + DPRINT(MAX_TRACE, ("CabinetPrev '%s'.\n", CabinetPrev)); + + /* Write name of previous cabinet */ + Size = lstrlen(CabinetPrev) + 1; + if (!WriteFile(FileHandle, CabinetPrev, Size, &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + + DPRINT(MAX_TRACE, ("DiskPrev '%s'.\n", DiskPrev)); + + /* Write label of previous disk */ + Size = lstrlen(DiskPrev) + 1; + if (!WriteFile(FileHandle, DiskPrev, Size, &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + } + + if ((CABHeader.Flags & CAB_FLAG_HASNEXT) > 0) { + + DPRINT(MAX_TRACE, ("CabinetNext '%s'.\n", CabinetNext)); + + /* Write name of next cabinet */ + Size = lstrlen(CabinetNext) + 1; + if (!WriteFile(FileHandle, CabinetNext, Size, &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + + DPRINT(MAX_TRACE, ("DiskNext '%s'.\n", DiskNext)); + + /* Write label of next disk */ + Size = lstrlen(DiskNext) + 1; + if (!WriteFile(FileHandle, DiskNext, Size, &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + } + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::WriteFolderEntries() +/* + * FUNCTION: Writes folder entries + * RETURNS: + * Status of operation + */ +{ + PCFFOLDER_NODE FolderNode; + DWORD BytesWritten; + + DPRINT(MAX_TRACE, ("Writing folder table.\n")); + + FolderNode = FolderListHead; + while (FolderNode != NULL) { + if (FolderNode->Commit) { + + DPRINT(MAX_TRACE, ("Writing folder entry. CompressionType (0x%X) DataBlockCount (%d) DataOffset (0x%X).\n", + FolderNode->Folder.CompressionType, FolderNode->Folder.DataBlockCount, FolderNode->Folder.DataOffset)); + + if (!WriteFile(FileHandle, + &FolderNode->Folder, + sizeof(CFFOLDER), + &BytesWritten, + NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + } + FolderNode = FolderNode->Next; + } + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::WriteFileEntries() +/* + * FUNCTION: Writes file entries for all files + * RETURNS: + * Status of operation + */ +{ + PCFFILE_NODE File; + DWORD BytesWritten; + BOOL SetCont; + + DPRINT(MAX_TRACE, ("Writing file table.\n")); + + File = FileListHead; + while (File != NULL) { + if (File->Commit) { + /* Remove any continued files that ends in this disk */ + if (File->File.FileControlID == CAB_FILE_CONTINUED) + File->Delete = TRUE; + + /* The file could end in the last (split) block and should therefore + appear in the next disk too */ + + if ((File->File.FileOffset + File->File.FileSize >= LastBlockStart) && + (File->File.FileControlID <= CAB_FILE_MAX_FOLDER) && (BlockIsSplit)) { + File->File.FileControlID = CAB_FILE_SPLIT; + File->Delete = FALSE; + SetCont = TRUE; + } + + DPRINT(MAX_TRACE, ("Writing file entry. FileControlID (0x%X) FileOffset (0x%X) FileSize (%d) FileName (%s).\n", + File->File.FileControlID, File->File.FileOffset, File->File.FileSize, File->FileName)); + + if (!WriteFile(FileHandle, + &File->File, + sizeof(CFFILE), + &BytesWritten, + NULL)) + return CAB_STATUS_CANNOT_WRITE; + + if (!WriteFile(FileHandle, + GetFileName(File->FileName), + lstrlen(GetFileName(File->FileName)) + 1, &BytesWritten, NULL)) + return CAB_STATUS_CANNOT_WRITE; + + if (SetCont) { + File->File.FileControlID = CAB_FILE_CONTINUED; + SetCont = FALSE; + } + } + + File = File->Next; + } + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::CommitDataBlocks(PCFFOLDER_NODE FolderNode) +/* + * FUNCTION: Writes data blocks to the cabinet + * ARGUMENTS: + * FolderNode = Pointer to folder node containing the data blocks + * RETURNS: + * Status of operation + */ +{ + PCFDATA_NODE DataNode; + DWORD BytesWritten; + DWORD BytesRead; + ULONG Status; + + DataNode = FolderNode->DataListHead; + if (DataNode != NULL) + Status = ScratchFile->Seek(DataNode->ScratchFilePosition); + + while (DataNode != NULL) { + DPRINT(MAX_TRACE, ("Reading block at (0x%X) CompSize (%d) UncompSize (%d).\n", + DataNode->ScratchFilePosition, + DataNode->Data.CompSize, + DataNode->Data.UncompSize)); + + /* InputBuffer is free for us to use here, so we use it and avoid a + memory allocation. OutputBuffer can't be used here because it may + still contain valid data (if a data block spans two or more disks) */ + Status = ScratchFile->ReadBlock(&DataNode->Data, InputBuffer, &BytesRead); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot read from scratch file (%d).\n", (UINT)Status)); + return Status; + } + + if (!WriteFile(FileHandle, &DataNode->Data, + sizeof(CFDATA), &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + + if (!WriteFile(FileHandle, InputBuffer, + DataNode->Data.CompSize, &BytesWritten, NULL)) { + DPRINT(MIN_TRACE, ("Cannot write to file.\n")); + return CAB_STATUS_CANNOT_WRITE; + } + + DataNode = DataNode->Next; + } + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::WriteDataBlock() +/* + * FUNCTION: Writes the current data block to the scratch file + * RETURNS: + * Status of operation + */ +{ + ULONG Status; + DWORD BytesWritten; + PCFDATA_NODE DataNode; + + if (!BlockIsSplit) { + Status = Codec->Compress(OutputBuffer, + InputBuffer, + CurrentIBufferSize, + &TotalCompSize); + + DPRINT(MAX_TRACE, ("Block compressed. CurrentIBufferSize (%d) TotalCompSize(%d).\n", + CurrentIBufferSize, TotalCompSize)); + + CurrentOBuffer = OutputBuffer; + CurrentOBufferSize = TotalCompSize; + } + + DataNode = NewDataNode(CurrentFolderNode); + if (!DataNode) { + DPRINT(MIN_TRACE, ("Insufficient memory.\n")); + return CAB_STATUS_NOMEMORY; + } + + DiskSize += sizeof(CFDATA); + + if (MaxDiskSize > 0) + /* Disk size is limited */ + BlockIsSplit = (DiskSize + CurrentOBufferSize > MaxDiskSize); + else + BlockIsSplit = FALSE; + + if (BlockIsSplit) { + DataNode->Data.CompSize = (WORD)(MaxDiskSize - DiskSize); + DataNode->Data.UncompSize = 0; + CreateNewDisk = TRUE; + } else { + DataNode->Data.CompSize = (WORD)CurrentOBufferSize; + DataNode->Data.UncompSize = (WORD)CurrentIBufferSize; + } + + DataNode->Data.Checksum = 0; + DataNode->ScratchFilePosition = ScratchFile->Position(); + + // FIXME: MAKECAB.EXE does not like this checksum algorithm + //DataNode->Data.Checksum = ComputeChecksum(CurrentOBuffer, DataNode->Data.CompSize, 0); + + DPRINT(MAX_TRACE, ("Writing block. Checksum (0x%X) CompSize (%d) UncompSize (%d).\n", + (UINT)DataNode->Data.Checksum, + (UINT)DataNode->Data.CompSize, + (UINT)DataNode->Data.UncompSize)); + + Status = ScratchFile->WriteBlock(&DataNode->Data, + CurrentOBuffer, &BytesWritten); + if (Status != CAB_STATUS_SUCCESS) + return Status; + + DiskSize += BytesWritten; + + CurrentFolderNode->TotalFolderSize += (BytesWritten + sizeof(CFDATA)); + CurrentFolderNode->Folder.DataBlockCount++; + + (PUCHAR)CurrentOBuffer += DataNode->Data.CompSize; + CurrentOBufferSize -= DataNode->Data.CompSize; + + LastBlockStart += DataNode->Data.UncompSize; + + if (!BlockIsSplit) { + CurrentIBufferSize = 0; + CurrentIBuffer = InputBuffer; + } + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::GetAttributesOnFile(PCFFILE_NODE File) +/* + * FUNCTION: Returns attributes on a file + * ARGUMENTS: + * File = Pointer to CFFILE node for file + * RETURNS: + * Status of operation + */ +{ + DWORD Attributes; + + Attributes = GetFileAttributes(File->FileName); + if (Attributes == -1) + return CAB_STATUS_CANNOT_READ; + + if (Attributes & FILE_ATTRIBUTE_READONLY) + File->File.Attributes |= CAB_ATTRIB_READONLY; + + if (Attributes & FILE_ATTRIBUTE_HIDDEN) + File->File.Attributes |= CAB_ATTRIB_HIDDEN; + + if (Attributes & FILE_ATTRIBUTE_SYSTEM) + File->File.Attributes |= CAB_ATTRIB_SYSTEM; + + if (Attributes & FILE_ATTRIBUTE_DIRECTORY) + File->File.Attributes |= CAB_ATTRIB_DIRECTORY; + + if (Attributes & FILE_ATTRIBUTE_ARCHIVE) + File->File.Attributes |= CAB_ATTRIB_ARCHIVE; + + return CAB_STATUS_SUCCESS; +} + + +ULONG CCabinet::SetAttributesOnFile(PCFFILE_NODE File) +/* + * FUNCTION: Sets attributes on a file + * ARGUMENTS: + * File = Pointer to CFFILE node for file + * RETURNS: + * Status of operation + */ +{ + DWORD Attributes = 0; + + if (File->File.Attributes & CAB_ATTRIB_READONLY) + Attributes |= FILE_ATTRIBUTE_READONLY; + + if (File->File.Attributes & CAB_ATTRIB_HIDDEN) + Attributes |= FILE_ATTRIBUTE_HIDDEN; + + if (File->File.Attributes & CAB_ATTRIB_SYSTEM) + Attributes |= FILE_ATTRIBUTE_SYSTEM; + + if (File->File.Attributes & CAB_ATTRIB_DIRECTORY) + Attributes |= FILE_ATTRIBUTE_DIRECTORY; + + if (File->File.Attributes & CAB_ATTRIB_ARCHIVE) + Attributes |= FILE_ATTRIBUTE_ARCHIVE; + + SetFileAttributes(File->FileName, Attributes); + + return CAB_STATUS_SUCCESS; +} + +#endif /* CAB_READ_ONLY */ + +/* EOF */ diff --git a/apps/utils/cabman/cabinet.h b/apps/utils/cabman/cabinet.h new file mode 100644 index 0000000..2011bd8 --- /dev/null +++ b/apps/utils/cabman/cabinet.h @@ -0,0 +1,431 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/cabinet.h + * PURPOSE: Cabinet definitions + */ +#ifndef __CABINET_H +#define __CABINET_H + +#include + +/* Debugging */ + +#define DBG + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_MEMORY 0x00000100 + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define DPRINT(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + printf("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + printf _x_ ; \ + } + +#define ASSERT(_b_) { \ + if (!(_b_)) { \ + printf("(%s:%d)(%s) ASSERTION: ", __FILE__, __LINE__, __FUNCTION__); \ + printf(#_b_); \ + ExitProcess(0); \ + } \ +} + +#else /* DBG */ + +#define DPRINT(_t_, _x_) + +#define ASSERT(_x_) + +#endif /* DBG */ + + +/* Macros */ + +#ifndef CopyMemory +#define CopyMemory(destination, source, length) memcpy(destination, source, length) +#endif /* CopyMemory */ + +/* Cabinet constants */ + +#define CAB_SIGNATURE 0x4643534D // "MSCF" +#define CAB_VERSION 0x0103 +#define CAB_BLOCKSIZE 32768 + +#define CAB_COMP_MASK 0x00FF +#define CAB_COMP_NONE 0x0000 +#define CAB_COMP_MSZIP 0x0001 +#define CAB_COMP_QUANTUM 0x0002 +#define CAB_COMP_LZX 0x0003 + +#define CAB_FLAG_HASPREV 0x0001 +#define CAB_FLAG_HASNEXT 0x0002 +#define CAB_FLAG_RESERVE 0x0004 + +#define CAB_ATTRIB_READONLY 0x0001 +#define CAB_ATTRIB_HIDDEN 0x0002 +#define CAB_ATTRIB_SYSTEM 0x0004 +#define CAB_ATTRIB_VOLUME 0x0008 +#define CAB_ATTRIB_DIRECTORY 0x0010 +#define CAB_ATTRIB_ARCHIVE 0x0020 +#define CAB_ATTRIB_EXECUTE 0x0040 +#define CAB_ATTRIB_UTF_NAME 0x0080 + +#define CAB_FILE_MAX_FOLDER 0xFFFC +#define CAB_FILE_CONTINUED 0xFFFD +#define CAB_FILE_SPLIT 0xFFFE +#define CAB_FILE_PREV_NEXT 0xFFFF + + +/* Cabinet structures */ + +typedef struct _CFHEADER +{ + DWORD Signature; // File signature 'MSCF' (CAB_SIGNATURE) + DWORD Reserved1; // Reserved field + DWORD CabinetSize; // Cabinet file size + DWORD Reserved2; // Reserved field + DWORD FileTableOffset; // Offset of first CFFILE + DWORD Reserved3; // Reserved field + WORD Version; // Cabinet version (CAB_VERSION) + WORD FolderCount; // Number of folders + WORD FileCount; // Number of files + WORD Flags; // Cabinet flags (CAB_FLAG_*) + WORD SetID; // Cabinet set id + WORD CabinetNumber; // Zero-based cabinet number +/* Optional fields (depends on Flags) + WORD CabinetResSize // Per-cabinet reserved area size + CHAR FolderResSize // Per-folder reserved area size + CHAR FileResSize // Per-file reserved area size + CHAR CabinetReserved[] // Per-cabinet reserved area + CHAR CabinetPrev[] // Name of previous cabinet file + CHAR DiskPrev[] // Name of previous disk + CHAR CabinetNext[] // Name of next cabinet file + CHAR DiskNext[] // Name of next disk + */ +} CFHEADER, *PCFHEADER; + + +typedef struct _CFFOLDER +{ + DWORD DataOffset; // Absolute offset of first CFDATA block in this folder + WORD DataBlockCount; // Number of CFDATA blocks in this folder in this cabinet + WORD CompressionType; // Type of compression used for all CFDATA blocks in this folder +/* Optional fields (depends on Flags) + CHAR FolderReserved[] // Per-folder reserved area + */ +} CFFOLDER, *PCFFOLDER; + + +typedef struct _CFFILE +{ + DWORD FileSize; // Uncompressed file size in bytes + DWORD FileOffset; // Uncompressed offset of file in the folder + WORD FileControlID; // File control ID (CAB_FILE_*) + WORD FileDate; // File date stamp, as used by DOS + WORD FileTime; // File time stamp, as used by DOS + WORD Attributes; // File attributes (CAB_ATTRIB_*) + /* After this is the NULL terminated filename */ +} CFFILE, *PCFFILE; + + +typedef struct _CFDATA +{ + DWORD Checksum; // Checksum of CFDATA entry + WORD CompSize; // Number of compressed bytes in this block + WORD UncompSize; // Number of uncompressed bytes in this block +/* Optional fields (depends on Flags) + CHAR DataReserved[] // Per-datablock reserved area + */ +} CFDATA, *PCFDATA; + +typedef struct _CFDATA_NODE +{ + struct _CFDATA_NODE *Next; + struct _CFDATA_NODE *Prev; + DWORD ScratchFilePosition; // Absolute offset in scratch file + DWORD AbsoluteOffset; // Absolute offset in cabinet + DWORD UncompOffset; // Uncompressed offset in folder + CFDATA Data; +} CFDATA_NODE, *PCFDATA_NODE; + +typedef struct _CFFOLDER_NODE +{ + struct _CFFOLDER_NODE *Next; + struct _CFFOLDER_NODE *Prev; + DWORD UncompOffset; // File size accumulator + DWORD AbsoluteOffset; + DWORD TotalFolderSize; // Total size of folder in current disk + PCFDATA_NODE DataListHead; + PCFDATA_NODE DataListTail; + DWORD Index; + BOOL Commit; // TRUE if the folder should be committed + BOOL Delete; // TRUE if marked for deletion + CFFOLDER Folder; +} CFFOLDER_NODE, *PCFFOLDER_NODE; + +typedef struct _CFFILE_NODE +{ + struct _CFFILE_NODE *Next; + struct _CFFILE_NODE *Prev; + CFFILE File; + LPTSTR FileName; + PCFDATA_NODE DataBlock; // First data block of file. NULL if not known + BOOL Commit; // TRUE if the file data should be committed + BOOL Delete; // TRUE if marked for deletion + PCFFOLDER_NODE FolderNode; // Folder this file belong to +} CFFILE_NODE, *PCFFILE_NODE; + + +typedef struct _CAB_SEARCH +{ + TCHAR Search[MAX_PATH]; // Search criteria + PCFFILE_NODE Next; // Pointer to next node + PCFFILE File; // Pointer to current CFFILE + LPTSTR FileName; // Current filename +} CAB_SEARCH, *PCAB_SEARCH; + + +/* Constants */ + +/* Status codes */ +#define CAB_STATUS_SUCCESS 0x00000000 +#define CAB_STATUS_FAILURE 0x00000001 +#define CAB_STATUS_NOMEMORY 0x00000002 +#define CAB_STATUS_CANNOT_OPEN 0x00000003 +#define CAB_STATUS_CANNOT_CREATE 0x00000004 +#define CAB_STATUS_CANNOT_READ 0x00000005 +#define CAB_STATUS_CANNOT_WRITE 0x00000006 +#define CAB_STATUS_FILE_EXISTS 0x00000007 +#define CAB_STATUS_INVALID_CAB 0x00000008 +#define CAB_STATUS_NOFILE 0x00000009 +#define CAB_STATUS_UNSUPPCOMP 0x0000000A + + + +/* Codecs */ + +class CCABCodec { +public: + /* Default constructor */ + CCABCodec() {}; + /* Default destructor */ + virtual ~CCABCodec() {}; + /* Compresses a data block */ + virtual ULONG Compress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength) = 0; + /* Uncompresses a data block */ + virtual ULONG Uncompress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength) = 0; +}; + + +/* Codec status codes */ +#define CS_SUCCESS 0x0000 /* All data consumed */ +#define CS_NOMEMORY 0x0001 /* Not enough free memory */ +#define CS_BADSTREAM 0x0002 /* Bad data stream */ + + +/* Codec indentifiers */ +#define CAB_CODEC_RAW 0x00 +#define CAB_CODEC_LZX 0x01 +#define CAB_CODEC_MSZIP 0x02 + + + +/* Classes */ + +#ifndef CAB_READ_ONLY + +class CCFDATAStorage { +public: + /* Default constructor */ + CCFDATAStorage(); + /* Default destructor */ + virtual ~CCFDATAStorage(); + ULONG Create(LPTSTR FileName); + ULONG Destroy(); + ULONG Truncate(); + ULONG Position(); + ULONG Seek(LONG Position); + ULONG ReadBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesRead); + ULONG WriteBlock(PCFDATA Data, PVOID Buffer, PDWORD BytesWritten); +private: + BOOL FileCreated; + HANDLE FileHandle; +}; + +#endif /* CAB_READ_ONLY */ + +class CCabinet { +public: + /* Default constructor */ + CCabinet(); + /* Default destructor */ + virtual ~CCabinet(); + /* Returns a pointer to the filename part of a fully qualified filename */ + LPTSTR GetFileName(LPTSTR Path); + /* Removes a filename from a fully qualified filename */ + VOID RemoveFileName(LPTSTR Path); + /* Normalizes a path */ + BOOL NormalizePath(LPTSTR Path, DWORD Length); + /* Returns name of cabinet file */ + LPTSTR GetCabinetName(); + /* Sets the name of the cabinet file */ + VOID SetCabinetName(LPTSTR FileName); + /* Sets destination path for extracted files */ + VOID SetDestinationPath(LPTSTR DestinationPath); + /* Returns destination path */ + LPTSTR GetDestinationPath(); + /* Returns zero-based current disk number */ + DWORD GetCurrentDiskNumber(); + /* Opens the current cabinet file */ + ULONG Open(); + /* Closes the current open cabinet file */ + VOID Close(); + /* Locates the first file in the current cabinet file that matches a search criteria */ + ULONG FindFirst(LPTSTR FileName, PCAB_SEARCH Search); + /* Locates the next file in the current cabinet file */ + ULONG FindNext(PCAB_SEARCH Search); + /* Extracts a file from the current cabinet file */ + ULONG ExtractFile(LPTSTR FileName); + /* Select codec engine to use */ + VOID SelectCodec(ULONG Id); +#ifndef CAB_READ_ONLY + /* Creates a new cabinet file */ + ULONG NewCabinet(); + /* Forces a new disk to be created */ + ULONG NewDisk(); + /* Forces a new folder to be created */ + ULONG NewFolder(); + /* Writes a file to scratch storage */ + ULONG WriteFileToScratchStorage(PCFFILE_NODE FileNode); + /* Forces the current disk to be written */ + ULONG WriteDisk(DWORD MoreDisks); + /* Commits the current disk */ + ULONG CommitDisk(DWORD MoreDisks); + /* Closes the current disk */ + ULONG CloseDisk(); + /* Closes the current cabinet */ + ULONG CloseCabinet(); + /* Adds a file to the current disk */ + ULONG AddFile(LPTSTR FileName); + /* Sets the maximum size of the current disk */ + VOID SetMaxDiskSize(DWORD Size); +#endif /* CAB_READ_ONLY */ + + /* Default event handlers */ + + /* Handler called when a file is about to be overridden */ + virtual BOOL OnOverwrite(PCFFILE Entry, LPTSTR FileName); + /* Handler called when a file is about to be extracted */ + virtual VOID OnExtract(PCFFILE Entry, LPTSTR FileName); + /* Handler called when a new disk is to be processed */ + virtual VOID OnDiskChange(LPTSTR CabinetName, LPTSTR DiskLabel); +#ifndef CAB_READ_ONLY + /* Handler called when a file is about to be added */ + virtual VOID OnAdd(PCFFILE Entry, LPTSTR FileName); + /* Handler called when a cabinet need a name */ + virtual BOOL OnCabinetName(ULONG Number, LPTSTR Name); + /* Handler called when a disk needs a label */ + virtual BOOL OnDiskLabel(ULONG Number, LPTSTR Label); +#endif /* CAB_READ_ONLY */ +private: + PCFFOLDER_NODE LocateFolderNode(DWORD Index); + ULONG GetAbsoluteOffset(PCFFILE_NODE File); + ULONG LocateFile(LPTSTR FileName, PCFFILE_NODE *File); + ULONG ReadString(LPTSTR String, DWORD MaxLength); + ULONG ReadFileTable(); + ULONG ReadDataBlocks(PCFFOLDER_NODE FolderNode); + PCFFOLDER_NODE NewFolderNode(); + PCFFILE_NODE NewFileNode(); + PCFDATA_NODE NewDataNode(PCFFOLDER_NODE FolderNode); + VOID DestroyDataNodes(PCFFOLDER_NODE FolderNode); + VOID DestroyFileNodes(); + VOID DestroyDeletedFileNodes(); + VOID DestroyFolderNodes(); + VOID DestroyDeletedFolderNodes(); + ULONG ComputeChecksum(PVOID Buffer, UINT Size, ULONG Seed); + ULONG ReadBlock(PVOID Buffer, DWORD Size, PDWORD BytesRead); +#ifndef CAB_READ_ONLY + ULONG InitCabinetHeader(); + ULONG WriteCabinetHeader(BOOL MoreDisks); + ULONG WriteFolderEntries(); + ULONG WriteFileEntries(); + ULONG CommitDataBlocks(PCFFOLDER_NODE FolderNode); + ULONG WriteDataBlock(); + ULONG GetAttributesOnFile(PCFFILE_NODE File); + ULONG SetAttributesOnFile(PCFFILE_NODE File); +#endif /* CAB_READ_ONLY */ + DWORD CurrentDiskNumber; // Zero based disk number + TCHAR CabinetName[256]; // Filename of current cabinet + TCHAR CabinetPrev[256]; // Filename of previous cabinet + TCHAR DiskPrev[256]; // Label of cabinet in file CabinetPrev + TCHAR CabinetNext[256]; // Filename of next cabinet + TCHAR DiskNext[256]; // Label of cabinet in file CabinetNext + DWORD TotalHeaderSize; // Size of header and optional fields + DWORD NextFieldsSize; // Size of next cabinet name and next disk label + DWORD TotalFolderSize; // Size of all folder entries + DWORD TotalFileSize; // Size of all file entries + DWORD FolderUncompSize; // Uncompressed size of folder + DWORD BytesLeftInBlock; // Number of bytes left in current block + BOOL ReuseBlock; + TCHAR DestPath[MAX_PATH]; + HANDLE FileHandle; + BOOL FileOpen; + CFHEADER CABHeader; + ULONG CabinetReserved; + ULONG FolderReserved; + ULONG DataReserved; + PCFFOLDER_NODE FolderListHead; + PCFFOLDER_NODE FolderListTail; + PCFFOLDER_NODE CurrentFolderNode; + PCFDATA_NODE CurrentDataNode; + PCFFILE_NODE FileListHead; + PCFFILE_NODE FileListTail; + CCABCodec *Codec; + ULONG CodecId; + BOOL CodecSelected; + PVOID InputBuffer; + PVOID CurrentIBuffer; // Current offset in input buffer + DWORD CurrentIBufferSize; // Bytes left in input buffer + PVOID OutputBuffer; + DWORD TotalCompSize; // Total size of current CFDATA block + PVOID CurrentOBuffer; // Current offset in output buffer + DWORD CurrentOBufferSize; // Bytes left in output buffer + DWORD BytesLeftInCabinet; + BOOL RestartSearch; + DWORD LastFileOffset; // Uncompressed offset of last extracted file +#ifndef CAB_READ_ONLY + DWORD LastBlockStart; // Uncompressed offset of last block in folder + DWORD MaxDiskSize; + DWORD DiskSize; + DWORD PrevCabinetNumber; // Previous cabinet number (where split file starts) + BOOL CreateNewDisk; + BOOL CreateNewFolder; + + CCFDATAStorage *ScratchFile; + HANDLE SourceFile; + BOOL ContinueFile; + DWORD TotalBytesLeft; + BOOL BlockIsSplit; // TRUE if current data block is split + ULONG NextFolderNumber; // Zero based folder number +#endif /* CAB_READ_ONLY */ +}; + +#endif /* __CABINET_H */ + +/* EOF */ diff --git a/apps/utils/cabman/cabman.h b/apps/utils/cabman/cabman.h new file mode 100644 index 0000000..01348bf --- /dev/null +++ b/apps/utils/cabman/cabman.h @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/cabman.h + * PURPOSE: Cabinet manager header + */ +#ifndef __CABMAN_H +#define __CABMAN_H + +#include "cabinet.h" +#include "dfp.h" + +/* Cabinet manager modes */ +#define CM_MODE_CREATE 0 +#define CM_MODE_DISPLAY 1 +#define CM_MODE_EXTRACT 2 + + +/* Classes */ + +class CCABManager : public CDFParser { +public: + CCABManager(); + virtual ~CCABManager(); + BOOL ParseCmdline(INT argc, PCHAR argv[]); + VOID Run(); +private: + VOID Usage(); + VOID CreateCabinet(); + VOID DisplayCabinet(); + VOID ExtractFromCabinet(); + /* Event handlers */ + virtual BOOL OnOverwrite(PCFFILE File, LPTSTR FileName); + virtual VOID OnExtract(PCFFILE File, LPTSTR FileName); + virtual VOID OnDiskChange(LPTSTR CabinetName, LPTSTR DiskLabel); + virtual VOID OnAdd(PCFFILE Entry, LPTSTR FileName); + /* Configuration */ + BOOL ProcessAll; + DWORD Mode; + BOOL PromptOnOverwrite; + TCHAR Location[MAX_PATH]; + TCHAR FileName[MAX_PATH]; +}; + +#endif /* __CABMAN_H */ + +/* EOF */ diff --git a/apps/utils/cabman/dff.txt b/apps/utils/cabman/dff.txt new file mode 100644 index 0000000..cea6981 --- /dev/null +++ b/apps/utils/cabman/dff.txt @@ -0,0 +1,55 @@ +Directive File Format for ReactOS Cabinet Manager +------------------------------------------------- + +Directives begin with a period ("."), and are followed by a command +name, and possibly blank delimited arguments. Commands and variable names are +case insensitive. + +Syntax Description +------------------------------------------------------------------------------- +; Anything on a line after this is a comment + [destination] File copy command +.Define variable=[value] Define variable to be equal to value (*) +.Delete variable Delete a variable definition (*) +.New Disk|Cabinet|Folder Start a new disk, cabinet or folder (* -- new disk will work) +.Set variable=[value] Set variable to be equal to value (*) +%variable% Substitute value of variable (*) + Blank lines are ignored +------------------------------------------------------------------------------- + + +Standard variable Description +------------------------------------------------------------------------------- +Cabinet=ON|OFF Turns cabinet mode on or off (* -- currently always on) +CabinetFileCountThreshold=count Threshold count of files per cabinet (*) +CabinetNamen=filename Cabinet file name for cabinet number n +CabinetNameTemplate=template Cabinet file name template + * is replaced by cabinet number +Compress=ON|OFF Turns compression on or off (* -- currently always on) +CompressionType=NONE|MSZIP Compression engine to use (* -- currently always mszip) +DiskLabeln=label Printed disk label name for disk n +DiskLabelTemplate=template Printed disk label name template + * is replaced by disk number +FolderFileCountThreshold=count Threshold count of files per folder (*) +FolderSizeThreshold=size Threshold folder size for current folder (*) +MaxDiskFileCount=count Maximum count of files per disk (*) +MaxDiskSize[n]=size Maximum disk size (for disk n) +ReservePerCabinetSize=size Amount of space to reserve in each cabinet (*) +ReservePerDataBlockSize=size Amount of space to reserve in each data block (*) +ReservePerFolderSize=size Amount of space to reserve in each folder (*) +SourceDir=path Default path for source files (*) +------------------------------------------------------------------------------- +(*) = not implemented + + +MaxDiskSize +----------- +0 means disk size is unlimited. Standard sizes available are: + + 2.88M + 1.44M + 1.25M + 1.2M + 720K + 360K + CDROM diff --git a/apps/utils/cabman/dfp.cpp b/apps/utils/cabman/dfp.cpp new file mode 100644 index 0000000..be84349 --- /dev/null +++ b/apps/utils/cabman/dfp.cpp @@ -0,0 +1,992 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/dfp.cpp + * PURPOSE: Directive file parser + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: The directive file format is similar to the + * directive file format used by Microsoft's MAKECAB + * REVISIONS: + * CSH 21/03-2001 Created + */ +#include +#include +#include +#include "cabinet.h" +#include "dfp.h" + + +/* CDFParser */ + +CDFParser::CDFParser() +/* + * FUNCTION: Default constructor + */ +{ + FileBuffer = NULL; + FileLoaded = FALSE; + CurrentOffset = 0; + CurrentLine = 0; + CabinetCreated = FALSE; + DiskCreated = FALSE; + FolderCreated = FALSE; + CabinetName = NULL; + DiskLabel = NULL; + MaxDiskSize = NULL; + + MaxDiskSizeAllSet = FALSE; + CabinetNameTemplateSet = FALSE; + DiskLabelTemplateSet = FALSE; +} + + +CDFParser::~CDFParser() +/* + * FUNCTION: Default destructor + */ +{ + PCABINET_NAME CNPrev; + PCABINET_NAME CNNext; + PDISK_NUMBER DNPrev; + PDISK_NUMBER DNNext; + + if (FileBuffer) + HeapFree(GetProcessHeap(), 0, FileBuffer); + CNNext = CabinetName; + while (CNNext != NULL) { + CNPrev = CNNext->Next; + HeapFree(GetProcessHeap(), 0, CNNext); + CNNext = CNPrev; + } + CNNext = DiskLabel; + while (CNNext != NULL) { + CNPrev = CNNext->Next; + HeapFree(GetProcessHeap(), 0, CNNext); + CNNext = CNPrev; + } + DNNext = MaxDiskSize; + while (DNNext != NULL) { + DNPrev = DNNext->Next; + HeapFree(GetProcessHeap(), 0, DNNext); + DNNext = DNPrev; + } +} + + +ULONG CDFParser::Load(LPTSTR FileName) +/* + * FUNCTION: Loads a directive file into memory + * ARGUMENTS: + * FileName = Pointer to name of directive file + * RETURNS: + * Status of operation + */ +{ + DWORD BytesRead; + LONG FileSize; + + if (FileLoaded) + return CAB_STATUS_SUCCESS; + + /* Create cabinet file, overwrite if it already exists */ + FileHandle = CreateFile(FileName, // Create this file + GENERIC_READ, // Open for reading + 0, // No sharing + NULL, // No security + OPEN_EXISTING, // Open the file + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (FileHandle == INVALID_HANDLE_VALUE) + return CAB_STATUS_CANNOT_OPEN; + + FileSize = GetFileSize(FileHandle, NULL); + if (FileSize < 0) { + CloseHandle(FileHandle); + return CAB_STATUS_CANNOT_OPEN; + } + + FileBufferSize = (ULONG)FileSize; + + FileBuffer = (PCHAR)HeapAlloc(GetProcessHeap(), 0, FileBufferSize); + if (!FileBuffer) { + CloseHandle(FileHandle); + return CAB_STATUS_NOMEMORY; + } + + if (!ReadFile(FileHandle, FileBuffer, FileBufferSize, &BytesRead, NULL)) { + CloseHandle(FileHandle); + HeapFree(GetProcessHeap(), 0, FileBuffer); + FileBuffer = NULL; + return CAB_STATUS_CANNOT_READ; + } + + CloseHandle(FileHandle); + + FileLoaded = TRUE; + + DPRINT(MAX_TRACE, ("File (%d bytes)\n", FileBufferSize)); + + return CAB_STATUS_SUCCESS; +} + + +ULONG CDFParser::Parse() +/* + * FUNCTION: Parses a loaded directive file + * RETURNS: + * Status of operation + */ +{ + BOOL Command; + ULONG Status; + + if (!FileLoaded) + return CAB_STATUS_NOFILE; + + while (ReadLine()) { + Command = FALSE; + + while (CurrentToken != TokenEnd) { + switch (CurrentToken) { + case TokenInteger: + itoa(CurrentInteger, (LPTSTR)&CurrentString, 10); + case TokenIdentifier: + if (Command) { + /* Command */ + Status = PerformCommand(); + + if (Status == CAB_STATUS_FAILURE) { + printf("Directive file contains errors at line %d.\n", (UINT)CurrentLine); + DPRINT(MID_TRACE, ("Error while executing command.\n")); + } + + if (Status != CAB_STATUS_SUCCESS) + return Status; + } else { + /* File copy */ + Status = PerformFileCopy(); + + if (Status == CAB_STATUS_FAILURE) { + printf("Directive file contains errors at line %d.\n", (UINT)CurrentLine); + DPRINT(MID_TRACE, ("Error while copying file.\n")); + } + + if (Status != CAB_STATUS_SUCCESS) + return Status; + } + break; + case TokenSpace: + break; + case TokenSemi: + CurrentToken = TokenEnd; + continue; + case TokenPeriod: + Command = TRUE; + break; + default: + printf("Directive file contains errors at line %d.\n", (UINT)CurrentLine); + DPRINT(MIN_TRACE, ("Token is (%d).\n", (UINT)CurrentToken)); + return CAB_STATUS_SUCCESS; + } + NextToken(); + } + } + + printf("\nWriting cabinet. This may take a while...\n\n"); + + if (DiskCreated) { + Status = WriteDisk(FALSE); + if (Status == CAB_STATUS_SUCCESS) + Status = CloseDisk(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (UINT)Status)); + return Status; + } + } + + if (CabinetCreated) { + Status = CloseCabinet(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot close cabinet (%d).\n", (UINT)Status)); + return Status; + } + } + + printf("\nDone.\n"); + + return CAB_STATUS_SUCCESS; +} + + +BOOL CDFParser::OnDiskLabel(ULONG Number, LPTSTR Label) +/* + * FUNCTION: Called when a disk needs a label + * ARGUMENTS: + * Number = Cabinet number that needs a label + * Label = Pointer to buffer to place label of disk + * RETURNS: + * TRUE if a disk label was returned, FALSE if not + */ +{ + TCHAR Buffer[20]; + INT i, j; + TCHAR ch; + + Number += 1; + + DPRINT(MID_TRACE, ("Giving disk (%d) a label...\n", (UINT)Number)); + + if (GetDiskName(&DiskLabel, Number, Label)) + return TRUE; + + if (DiskLabelTemplateSet) { + j = 0; + lstrcpy(Label, ""); + for (i = 0; i < lstrlen(DiskLabelTemplate); i++) { + ch = DiskLabelTemplate[i]; + if (ch == '*') { + lstrcat(Label, itoa(Number, Buffer, 10)); + j += lstrlen(Buffer); + } else { + Label[j] = ch; + j++; + } + Label[j] = '\0'; + } + + DPRINT(MID_TRACE, ("Giving disk (%s) as a label...\n", Label)); + + return TRUE; + } else + return FALSE; +} + + +BOOL CDFParser::OnCabinetName(ULONG Number, LPTSTR Name) +/* + * FUNCTION: Called when a cabinet needs a name + * ARGUMENTS: + * Number = Disk number that needs a name + * Name = Pointer to buffer to place name of cabinet + * RETURNS: + * TRUE if a cabinet name was returned, FALSE if not + */ +{ + TCHAR Buffer[20]; + INT i, j; + TCHAR ch; + + Number += 1; + + DPRINT(MID_TRACE, ("Giving cabinet (%d) a name...\n", (UINT)Number)); + + if (GetDiskName(&CabinetName, Number, Name)) + return TRUE; + + if (CabinetNameTemplateSet) { + j = 0; + lstrcpy(Name, ""); + for (i = 0; i < lstrlen(CabinetNameTemplate); i++) { + ch = CabinetNameTemplate[i]; + if (ch == '*') { + lstrcat(Name, itoa(Number, Buffer, 10)); + j += lstrlen(Buffer); + } else { + Name[j] = ch; + j++; + } + Name[j] = '\0'; + } + + DPRINT(MID_TRACE, ("Giving cabinet (%s) as a name...\n", Name)); + + return TRUE; + } else + return FALSE; +} + + +BOOL CDFParser::SetDiskName(PCABINET_NAME *List, ULONG Number, LPTSTR String) +/* + * FUNCTION: Sets an entry in a list + * ARGUMENTS: + * List = Address of pointer to list + * Number = Disk number + * String = Pointer to string + * RETURNS: + * FALSE if there was not enough free memory available + */ +{ + PCABINET_NAME CN; + + CN = *List; + while (CN != NULL) { + if (CN->DiskNumber == Number) { + lstrcpy(CN->Name, String); + return TRUE; + } + CN = CN->Next; + } + + CN = (PCABINET_NAME)HeapAlloc(GetProcessHeap(), 0, sizeof(CABINET_NAME)); + if (!CN) + return FALSE; + + CN->DiskNumber = Number; + lstrcpy(CN->Name, String); + + CN->Next = *List; + *List = CN; + + return TRUE; +} + + +BOOL CDFParser::GetDiskName(PCABINET_NAME *List, ULONG Number, LPTSTR String) +/* + * FUNCTION: Returns an entry in a list + * ARGUMENTS: + * List = Address of pointer to list + * Number = Disk number + * String = Address of buffer to copy string to + * RETURNS: + * FALSE if there was not enough free memory available + */ +{ + PCABINET_NAME CN; + + CN = *List; + while (CN != NULL) { + if (CN->DiskNumber == Number) { + lstrcpy(String, CN->Name); + return TRUE; + } + CN = CN->Next; + } + + return FALSE; +} + + +BOOL CDFParser::SetDiskNumber(PDISK_NUMBER *List, ULONG Number, ULONG Value) +/* + * FUNCTION: Sets an entry in a list + * ARGUMENTS: + * List = Address of pointer to list + * Number = Disk number + * Value = Value to set + * RETURNS: + * FALSE if there was not enough free memory available + */ +{ + PDISK_NUMBER DN; + + DN = *List; + while (DN != NULL) { + if (DN->DiskNumber == Number) { + DN->Number = Value; + return TRUE; + } + DN = DN->Next; + } + + DN = (PDISK_NUMBER)HeapAlloc(GetProcessHeap(), 0, sizeof(DISK_NUMBER)); + if (!DN) + return FALSE; + + DN->DiskNumber = Number; + DN->Number = Value; + + DN->Next = *List; + *List = DN; + + return TRUE; +} + + +BOOL CDFParser::GetDiskNumber(PDISK_NUMBER *List, ULONG Number, PULONG Value) +/* + * FUNCTION: Returns an entry in a list + * ARGUMENTS: + * List = Address of pointer to list + * Number = Disk number + * Value = Address of buffer to place value + * RETURNS: + * TRUE if the entry was found + */ +{ + PDISK_NUMBER DN; + + DN = *List; + while (DN != NULL) { + if (DN->DiskNumber == Number) { + *Value = DN->Number; + return TRUE; + } + DN = DN->Next; + } + + return FALSE; +} + + +BOOL CDFParser::DoDiskLabel(ULONG Number, LPTSTR Label) +/* + * FUNCTION: Sets the label of a disk + * ARGUMENTS: + * Number = Disk number + * Label = Pointer to label of disk + * RETURNS: + * FALSE if there was not enough free memory available + */ +{ + DPRINT(MID_TRACE, ("Setting label of disk (%d) to '%s'\n", (UINT)Number, Label)); + + return SetDiskName(&DiskLabel, Number, Label); +} + + +VOID CDFParser::DoDiskLabelTemplate(LPTSTR Template) +/* + * FUNCTION: Sets a disk label template to use + * ARGUMENTS: + * Template = Pointer to disk label template + */ +{ + DPRINT(MID_TRACE, ("Setting disk label template to '%s'\n", Template)); + + lstrcpy(DiskLabelTemplate, Template); + DiskLabelTemplateSet = TRUE; +} + + +BOOL CDFParser::DoCabinetName(ULONG Number, LPTSTR Name) +/* + * FUNCTION: Sets the name of a cabinet + * ARGUMENTS: + * Number = Disk number + * Name = Pointer to name of cabinet + * RETURNS: + * FALSE if there was not enough free memory available + */ +{ + DPRINT(MID_TRACE, ("Setting name of cabinet (%d) to '%s'\n", (UINT)Number, Name)); + + return SetDiskName(&CabinetName, Number, Name); +} + + +VOID CDFParser::DoCabinetNameTemplate(LPTSTR Template) +/* + * FUNCTION: Sets a cabinet name template to use + * ARGUMENTS: + * Template = Pointer to cabinet name template + */ +{ + DPRINT(MID_TRACE, ("Setting cabinet name template to '%s'\n", Template)); + + lstrcpy(CabinetNameTemplate, Template); + CabinetNameTemplateSet = TRUE; +} + + +ULONG CDFParser::DoMaxDiskSize(BOOL NumberValid, ULONG Number) +/* + * FUNCTION: Sets the maximum disk size + * ARGUMENTS: + * NumberValid = TRUE if disk number is valid + * Number = Disk number + * RETURNS: + * Status of operation + * NOTES: + * Standard sizes are 2.88M, 1.44M, 1.25M, 1.2M, 720K, 360K, and CDROM + */ +{ + ULONG A, B, Value; + + if (IsNextToken(TokenInteger, TRUE)) { + + A = CurrentInteger; + + if (IsNextToken(TokenPeriod, FALSE)) { + if (!IsNextToken(TokenInteger, FALSE)) + return CAB_STATUS_FAILURE; + + B = CurrentInteger; + + } else + B = 0; + + if (CurrentToken == TokenIdentifier) { + switch (CurrentString[0]) { + case 'K': + if (B != 0) + return CAB_STATUS_FAILURE; + + if (A == 720) + /* 720K disk */ + Value = 730112; + else if (A == 360) + /* 360K disk */ + Value = 362496; + else + return CAB_STATUS_FAILURE; + break; + case 'M': + if (A == 1) { + if (B == 44) + /* 1.44M disk */ + Value = 1457664; + else if (B == 25) + /* 1.25M disk */ + Value = 1300000; // FIXME: Value? + else if (B == 2) + /* 1.2M disk */ + Value = 1213952; + else + return CAB_STATUS_FAILURE; + } else if (A == 2) { + if (B == 88) + /* 2.88M disk */ + Value = 2915328; + else + return CAB_STATUS_FAILURE; + } else + return CAB_STATUS_FAILURE; + break; + default: + DPRINT(MID_TRACE, ("Bad suffix (%c)\n", CurrentString[0])); + return CAB_STATUS_FAILURE; + } + } else + Value = A; + } else { + if ((CurrentToken != TokenString) && + (strcmpi(CurrentString, "CDROM") != 0)) + return CAB_STATUS_FAILURE; + /* CDROM */ + Value = 640*1024*1024; // FIXME: Correct size for CDROM? + } + + if (NumberValid) + return (SetDiskNumber(&MaxDiskSize, Number, Value)? + CAB_STATUS_SUCCESS : CAB_STATUS_FAILURE); + + MaxDiskSizeAll = Value; + MaxDiskSizeAllSet = TRUE; + + SetMaxDiskSize(Value); + + return CAB_STATUS_SUCCESS; +} + + +ULONG CDFParser::SetupNewDisk() +/* + * FUNCTION: Sets up parameters for a new disk + * RETURNS: + * Status of operation + */ +{ + ULONG Value; + + if (!GetDiskNumber(&MaxDiskSize, GetCurrentDiskNumber(), &Value)) { + if (MaxDiskSizeAllSet) + Value = MaxDiskSizeAll; + else + Value = 0; + } + SetMaxDiskSize(Value); + + return CAB_STATUS_SUCCESS; +} + + +ULONG CDFParser::PerformSetCommand() +/* + * FUNCTION: Performs a set variable command + * RETURNS: + * Status of operation + */ +{ + SETTYPE SetType; + BOOL NumberValid = FALSE; + ULONG Number = 0; + + if (!IsNextToken(TokenIdentifier, TRUE)) + return CAB_STATUS_FAILURE; + + if (strcmpi(CurrentString, "DiskLabel") == 0) + SetType = stDiskLabel; + else if (strcmpi(CurrentString, "DiskLabelTemplate") == 0) + SetType = stDiskLabelTemplate; + else if (strcmpi(CurrentString, "CabinetName") == 0) + SetType = stCabinetName; + else if (strcmpi(CurrentString, "CabinetNameTemplate") == 0) + SetType = stCabinetNameTemplate; + else if (strcmpi(CurrentString, "MaxDiskSize") == 0) + SetType = stMaxDiskSize; + else + return CAB_STATUS_FAILURE; + + if ((SetType == stDiskLabel) || (SetType == stCabinetName)) { + if (!IsNextToken(TokenInteger, FALSE)) + return CAB_STATUS_FAILURE; + Number = CurrentInteger; + + if (!IsNextToken(TokenEqual, TRUE)) + return CAB_STATUS_FAILURE; + } else if (SetType == stMaxDiskSize) { + if (IsNextToken(TokenInteger, FALSE)) { + NumberValid = TRUE; + Number = CurrentInteger; + } else { + NumberValid = FALSE; + while (CurrentToken == TokenSpace) + NextToken(); + if (CurrentToken != TokenEqual) + return CAB_STATUS_FAILURE; + } + } else if (!IsNextToken(TokenEqual, TRUE)) + return CAB_STATUS_FAILURE; + + if (SetType != stMaxDiskSize) { + if (!IsNextToken(TokenString, TRUE)) + return CAB_STATUS_FAILURE; + } + + switch (SetType) { + case stDiskLabel: + if (!DoDiskLabel(Number, CurrentString)) + DPRINT(MIN_TRACE, ("Not enough available free memory.\n")); + return CAB_STATUS_SUCCESS; + case stCabinetName: + if (!DoCabinetName(Number, CurrentString)) + DPRINT(MIN_TRACE, ("Not enough available free memory.\n")); + return CAB_STATUS_SUCCESS; + case stDiskLabelTemplate: + DoDiskLabelTemplate(CurrentString); + return CAB_STATUS_SUCCESS; + case stCabinetNameTemplate: + DoCabinetNameTemplate(CurrentString); + return CAB_STATUS_SUCCESS; + case stMaxDiskSize: + return DoMaxDiskSize(NumberValid, Number); + default: + return CAB_STATUS_FAILURE; + } +} + + +ULONG CDFParser::PerformNewCommand() +/* + * FUNCTION: Performs a new disk|cabinet|folder command + * RETURNS: + * Status of operation + */ +{ + NEWTYPE NewType; + ULONG Status; + + if (!IsNextToken(TokenIdentifier, TRUE)) + return CAB_STATUS_FAILURE; + + if (strcmpi(CurrentString, "Disk") == 0) + NewType = ntDisk; + else if (strcmpi(CurrentString, "Cabinet") == 0) + NewType = ntCabinet; + else if (strcmpi(CurrentString, "Folder") == 0) + NewType = ntFolder; + else + return CAB_STATUS_FAILURE; + + switch (NewType) { + case ntDisk: + if (DiskCreated) { + Status = WriteDisk(TRUE); + if (Status == CAB_STATUS_SUCCESS) + Status = CloseDisk(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (UINT)Status)); + return CAB_STATUS_SUCCESS; + } + DiskCreated = FALSE; + } + + Status = NewDisk(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot create disk (%d).\n", (UINT)Status)); + return CAB_STATUS_SUCCESS; + } + DiskCreated = TRUE; + SetupNewDisk(); + return CAB_STATUS_SUCCESS; + case ntCabinet: + if (DiskCreated) { + Status = WriteDisk(TRUE); + if (Status == CAB_STATUS_SUCCESS) + Status = CloseDisk(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (UINT)Status)); + return CAB_STATUS_SUCCESS; + } + DiskCreated = FALSE; + } + + Status = NewCabinet(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (UINT)Status)); + return CAB_STATUS_SUCCESS; + } + DiskCreated = TRUE; + SetupNewDisk(); + return CAB_STATUS_SUCCESS; + case ntFolder: + Status = NewFolder(); + ASSERT(Status == CAB_STATUS_SUCCESS); + return CAB_STATUS_SUCCESS; + default: + return CAB_STATUS_FAILURE; + } +} + + +ULONG CDFParser::PerformCommand() +/* + * FUNCTION: Performs a command + * RETURNS: + * Status of operation + */ +{ + if (strcmpi(CurrentString, "Set") == 0) + return PerformSetCommand(); + if (strcmpi(CurrentString, "New") == 0) + return PerformNewCommand(); + + return CAB_STATUS_FAILURE; +} + + +ULONG CDFParser::PerformFileCopy() +/* + * FUNCTION: Performs a file copy + * RETURNS: + * Status of operation + */ +{ + ULONG Status; + ULONG i, j; + TCHAR ch; + TCHAR SrcName[MAX_PATH]; + TCHAR DstName[MAX_PATH]; + + lstrcpy(SrcName, ""); + lstrcpy(DstName, ""); + + i = lstrlen(CurrentString); + while ((i < LineLength) && + ((ch = Line[i]) != ' ') && + (ch != 0x09) && + (ch != ';')) { + CurrentString[i] = ch; + i++; + } + CurrentString[i] = '\0'; + CurrentToken = TokenString; + CurrentChar = i + 1; + lstrcpy(SrcName, CurrentString); + + SkipSpaces(); + + if (CurrentToken != TokenEnd) { + j = lstrlen(CurrentString); i = 0; + while ((CurrentChar + i < LineLength) && + ((ch = Line[CurrentChar + i]) != ' ') && + (ch != 0x09) && + (ch != ';')) { + CurrentString[j + i] = ch; + i++; + } + CurrentString[j + i] = '\0'; + CurrentToken = TokenString; + CurrentChar += i + 1; + lstrcpy(DstName, CurrentString); + } + + if (!CabinetCreated) { + + DPRINT(MID_TRACE, ("Creating cabinet.\n")); + + Status = NewCabinet(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (UINT)Status)); + printf("Cannot create cabinet.\n"); + return CAB_STATUS_FAILURE; + } + CabinetCreated = TRUE; + + DPRINT(MID_TRACE, ("Creating disk.\n")); + + Status = NewDisk(); + if (Status != CAB_STATUS_SUCCESS) { + DPRINT(MIN_TRACE, ("Cannot create disk (%d).\n", (UINT)Status)); + printf("Cannot create disk.\n"); + return CAB_STATUS_FAILURE; + } + DiskCreated = TRUE; + SetupNewDisk(); + } + + DPRINT(MID_TRACE, ("Adding file: '%s' destination: '%s'.\n", SrcName, DstName)); + + Status = AddFile(SrcName); + if (Status != CAB_STATUS_SUCCESS) { + if (Status == CAB_STATUS_CANNOT_OPEN) + printf("File does not exist: %s.\n", SrcName); + else if (Status == CAB_STATUS_NOMEMORY) + printf("Insufficient memory to add file: %s.\n", SrcName); + else + printf("Cannot add file: %s (%d).\n", SrcName, Status); + return Status; + } + + return CAB_STATUS_SUCCESS; +} + + +VOID CDFParser::SkipSpaces() +/* + * FUNCTION: Skips any spaces in the current line + */ +{ + NextToken(); + while (CurrentToken == TokenSpace) + NextToken(); +} + + +BOOL CDFParser::IsNextToken(TOKEN Token, BOOL NoSpaces) +/* + * FUNCTION: Checks if next token equals Token + * ARGUMENTS: + * Token = Token to compare with + * SkipSp = TRUE if spaces should be skipped + * RETURNS: + * FALSE if next token is diffrent from Token + */ +{ + if (NoSpaces) + SkipSpaces(); + else + NextToken(); + return (CurrentToken == Token); +} + + +BOOL CDFParser::ReadLine() +/* + * FUNCTION: Reads the next line into the line buffer + * RETURNS: + * TRUE if there is a new line, FALSE if not + */ +{ + ULONG i, j; + TCHAR ch; + + if (CurrentOffset >= FileBufferSize) + return FALSE; + + i = 0; + while (((j = CurrentOffset + i) < FileBufferSize) && (i < 127) && + ((ch = FileBuffer[j]) != 0x0D)) { + Line[i] = ch; + i++; + } + + Line[i] = '\0'; + LineLength = i; + + if (FileBuffer[CurrentOffset + i + 1] == 0x0A) + CurrentOffset++; + + CurrentOffset += i + 1; + + CurrentChar = 0; + + CurrentLine++; + + NextToken(); + + return TRUE; +} + + +VOID CDFParser::NextToken() +/* + * FUNCTION: Reads the next token from the current line + */ +{ + ULONG i; + TCHAR ch = ' '; + + if (CurrentChar >= LineLength) { + CurrentToken = TokenEnd; + return; + } + + switch (Line[CurrentChar]) { + case ' ': + case 0x09: CurrentToken = TokenSpace; + break; + case ';': CurrentToken = TokenSemi; + break; + case '=': CurrentToken = TokenEqual; + break; + case '.': CurrentToken = TokenPeriod; + break; + case '\\': CurrentToken = TokenBackslash; + break; + case '"': + i = 0; + while ((CurrentChar + i + 1 < LineLength) && + ((ch = Line[CurrentChar + i + 1]) != '"')) { + CurrentString[i] = ch; + i++; + } + CurrentString[i] = '\0'; + CurrentToken = TokenString; + CurrentChar += i + 2; + return; + default: + i = 0; + while ((CurrentChar + i < LineLength) && + ((ch = Line[CurrentChar + i]) >= '0') && (ch <= '9')) { + CurrentString[i] = ch; + i++; + } + if (i > 0) { + CurrentString[i] = '\0'; + CurrentInteger = atoi((PCHAR)CurrentString); + CurrentToken = TokenInteger; + CurrentChar += i; + return; + } + i = 0; + while (((CurrentChar + i < LineLength) && + (((ch = Line[CurrentChar + i]) >= 'a') && (ch <= 'z')) || + ((ch >= 'A') && (ch <= 'Z')) || (ch == '_'))) { + CurrentString[i] = ch; + i++; + } + if (i > 0) { + CurrentString[i] = '\0'; + CurrentToken = TokenIdentifier; + CurrentChar += i; + return; + } + CurrentToken = TokenUnknown; + } + CurrentChar++; +} + +/* EOF */ diff --git a/apps/utils/cabman/dfp.h b/apps/utils/cabman/dfp.h new file mode 100644 index 0000000..559348d --- /dev/null +++ b/apps/utils/cabman/dfp.h @@ -0,0 +1,130 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/dfp.h + * PURPOSE: Directive file parser header + */ +#ifndef __DFP_H +#define __DFP_H + +#include "cabinet.h" + +typedef struct _CABINET_NAME { + struct _CABINET_NAME *Next; + ULONG DiskNumber; + TCHAR Name[128]; +} CABINET_NAME, *PCABINET_NAME; + +typedef struct _DISK_NUMBER { + struct _DISK_NUMBER *Next; + ULONG DiskNumber; + ULONG Number; +} DISK_NUMBER, *PDISK_NUMBER; + +typedef enum { + TokenUnknown, + TokenInteger, + TokenIdentifier, + TokenString, + TokenSpace, + TokenSemi, + TokenEqual, + TokenPeriod, + TokenBackslash, + TokenEnd, +} TOKEN; + + +typedef enum { + stCabinetName, + stCabinetNameTemplate, + stDiskLabel, + stDiskLabelTemplate, + stMaxDiskSize +} SETTYPE; + + +typedef enum { + ntDisk, + ntCabinet, + ntFolder, +} NEWTYPE; + + +/* Classes */ + +class CDFParser : public CCabinet { +public: + CDFParser(); + virtual ~CDFParser(); + ULONG Load(LPTSTR FileName); + ULONG Parse(); +private: + /* Event handlers */ + virtual BOOL OnDiskLabel(ULONG Number, LPTSTR Label); + virtual BOOL OnCabinetName(ULONG Number, LPTSTR Name); + + BOOL SetDiskName(PCABINET_NAME *List, ULONG Number, LPTSTR String); + BOOL GetDiskName(PCABINET_NAME *List, ULONG Number, LPTSTR String); + BOOL SetDiskNumber(PDISK_NUMBER *List, ULONG Number, ULONG Value); + BOOL GetDiskNumber(PDISK_NUMBER *List, ULONG Number, PULONG Value); + BOOL DoDiskLabel(ULONG Number, LPTSTR Label); + VOID DoDiskLabelTemplate(LPTSTR Template); + BOOL DoCabinetName(ULONG Number, LPTSTR Name); + VOID DoCabinetNameTemplate(LPTSTR Template); + ULONG DoMaxDiskSize(BOOL NumberValid, ULONG Number); + ULONG SetupNewDisk(); + ULONG PerformSetCommand(); + ULONG PerformNewCommand(); + ULONG PerformCommand(); + ULONG PerformFileCopy(); + VOID SkipSpaces(); + BOOL IsNextToken(TOKEN Token, BOOL NoSpaces); + BOOL ReadLine(); + VOID NextToken(); + /* Parsing */ + BOOL FileLoaded; + HANDLE FileHandle; + PCHAR FileBuffer; + DWORD FileBufferSize; + ULONG CurrentOffset; + TCHAR Line[128]; + ULONG LineLength; + ULONG CurrentLine; + ULONG CurrentChar; + /* Token */ + TOKEN CurrentToken; + ULONG CurrentInteger; + TCHAR CurrentString[256]; + + /* State */ + BOOL CabinetCreated; + BOOL DiskCreated; + BOOL FolderCreated; + /* Standard directive variable */ + BOOL Cabinet; + ULONG CabinetFileCountThreshold; + PCABINET_NAME CabinetName; + BOOL CabinetNameTemplateSet; + TCHAR CabinetNameTemplate[128]; + BOOL Compress; + ULONG CompressionType; + PCABINET_NAME DiskLabel; + BOOL DiskLabelTemplateSet; + TCHAR DiskLabelTemplate[128]; + ULONG FolderFileCountThreshold; + ULONG FolderSizeThreshold; + ULONG MaxCabinetSize; + ULONG MaxDiskFileCount; + PDISK_NUMBER MaxDiskSize; + BOOL MaxDiskSizeAllSet; + ULONG MaxDiskSizeAll; + ULONG ReservePerCabinetSize; + ULONG ReservePerDataBlockSize; + ULONG ReservePerFolderSize; + TCHAR SourceDir[256]; +}; + +#endif /* __DFP_H */ + +/* EOF */ diff --git a/apps/utils/cabman/main.cpp b/apps/utils/cabman/main.cpp new file mode 100644 index 0000000..d269f62 --- /dev/null +++ b/apps/utils/cabman/main.cpp @@ -0,0 +1,493 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/main.cpp + * PURPOSE: Main program + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 21/03-2001 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include "cabman.h" + + +#ifdef DBG + +DWORD DebugTraceLevel = MIN_TRACE; +//DWORD DebugTraceLevel = MID_TRACE; +//DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + + +#define CM_VERSION KERNEL_VERSION_STR + + +LPTSTR Pad(LPTSTR Str, CHAR PadChar, UINT Length) +/* + * FUNCTION: Pads a string with a character to make a given length + * ARGUMENTS: + * Str = Pointer to string to pad + * PadChar = Character to pad with + * Length = Disired length of string + * RETURNS: + * Pointer to string + * NOTES: + * Str must be at least Length + 1 bytes + */ +{ + UINT Len; + + Len = lstrlen(Str); + + if (Len < Length) { + memcpy(&Str[Length - Len], Str, Len + 1); + memset(Str, PadChar, Length - Len); + } + return Str; +} + + +LPTSTR Date2Str(LPTSTR Str, WORD Date) +/* + * FUNCTION: Converts a DOS style date to a string + * ARGUMENTS: + * Str = Pointer to destination string + * Date = DOS style date + * RETURNS: + * Pointer to string + */ +{ + DWORD dw; + + /* Month */ + Str[0] = (CHAR)('0' + ((Date & 0x01E0) >> 5) / 10); + Str[1] = (CHAR)('0' + ((Date & 0x01E0) >> 5) % 10); + Str[2] = '-'; + /* Day */ + Str[3] = (CHAR)('0' + (Date & 0x001F) / 10); + Str[4] = (CHAR)('0' + (Date & 0x001F) % 10); + Str[5] = '-'; + /* Year */ + dw = 1980 + ((Date & 0xFE00) >> 9); + Str[6] = (CHAR)('0' + dw / 1000); dw %= 1000; + Str[7] = (CHAR)('0' + dw / 100); dw %= 100; + Str[8] = (CHAR)('0' + dw / 10); dw %= 10; + Str[9] = (CHAR)('0' + dw % 10); + Str[10] = '\0'; + return Str; +} + + +LPTSTR Time2Str(LPTSTR Str, WORD Time) +/* + * FUNCTION: Converts a DOS style time to a string + * ARGUMENTS: + * Str = Pointer to destination string + * Time = DOS style time + * RETURNS: + * Pointer to string + */ +{ + BOOL PM; + DWORD Hour; + DWORD dw; + + Hour = ((Time & 0xF800) >> 11); + PM = (Hour >= 12); + Hour %= 12; + if (Hour == 0) + Hour = 12; + + if (Hour >= 10) + Str[0] = (CHAR)('0' + Hour / 10); + else Str[0] = ' '; + Str[1] = (CHAR)('0' + Hour % 10); + Str[2] = ':'; + /* Minute */ + Str[3] = (CHAR)('0' + ((Time & 0x07E0) >> 5) / 10); + Str[4] = (CHAR)('0' + ((Time & 0x07E0) >> 5) % 10); + Str[5] = ':'; + /* Second */ + dw = 2 * (Time & 0x001F); + Str[6] = (CHAR)('0' + dw / 10); + Str[7] = (CHAR)('0' + dw % 10); + + Str[8] = PM? 'p' : 'a'; + Str[9] = '\0'; + return Str; +} + + +LPTSTR Attr2Str(LPTSTR Str, WORD Attr) +/* + * FUNCTION: Converts attributes to a string + * ARGUMENTS: + * Str = Pointer to destination string + * Attr = Attributes + * RETURNS: + * Pointer to string + */ +{ + /* Archive */ + if (Attr & CAB_ATTRIB_ARCHIVE) + Str[0] = 'A'; + else + Str[0] = '-'; + + /* Hidden */ + if (Attr & CAB_ATTRIB_HIDDEN) + Str[1] = 'H'; + else + Str[1] = '-'; + + /* Read only */ + if (Attr & CAB_ATTRIB_READONLY) + Str[2] = 'R'; + else + Str[2] = '-'; + + /* System */ + if (Attr & CAB_ATTRIB_SYSTEM) + Str[3] = 'S'; + else + Str[3] = '-'; + + Str[4] = '\0'; + return Str; +} + + +/* CCABManager */ + +CCABManager::CCABManager() +/* + * FUNCTION: Default constructor + */ +{ + ProcessAll = FALSE; + Mode = CM_MODE_DISPLAY; + PromptOnOverwrite = TRUE; +} + + +CCABManager::~CCABManager() +/* + * FUNCTION: Default destructor + */ +{ +} + + +VOID CCABManager::Usage() +/* + * FUNCTION: Display usage information on screen + */ +{ + printf("ReactOS Cabinet Manager - Version %s\n\n", CM_VERSION); + printf("CABMAN [/D | /E] [/A] [/L dir] [/Y] cabinet [filename ...]\n"); + printf("CABMAN /C dirfile\n"); + printf(" cabinet Cabinet file.\n"); + printf(" filename Name of the file to extract from the cabinet.\n"); + printf(" Wild cards and multiple filenames\n"); + printf(" (separated by blanks) may be used.\n\n"); + printf(" dirfile Name of the directive file to use.\n\n"); + + + printf(" /A Process ALL cabinets. Follows cabinet chain\n"); + printf(" starting in first cabinet mentioned.\n"); + printf(" /C Create cabinet.\n"); + printf(" /D Display cabinet directory.\n"); + printf(" /E Extract files from cabinet.\n"); + printf(" /L dir Location to place extracted files\n"); + printf(" (default is current directory).\n"); + printf(" /Y Do not prompt before overwriting an existing file.\n\n"); +} + + +BOOL CCABManager::ParseCmdline(INT argc, PCHAR argv[]) +/* + * FUNCTION: Parse command line arguments + * ARGUMENTS: + * argc = Number of arguments on command line + * argv = Pointer to list of command line arguments + * RETURNS: + * TRUE if command line arguments was successfully parsed, false if not + */ +{ + INT i; + BOOL ShowUsage; + BOOL FoundCabinet = FALSE; + + ShowUsage = (argc < 2); + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '/') { + switch (argv[i][1]) { + case 'a': + case 'A': ProcessAll = TRUE; break; + case 'c': + case 'C': Mode = CM_MODE_CREATE; break; + case 'd': + case 'D': Mode = CM_MODE_DISPLAY; break; + case 'e': + case 'E': Mode = CM_MODE_EXTRACT; break; + case 'l': + case 'L': + if (argv[i][2] == ' ') { + i++; + SetDestinationPath((LPTSTR)&argv[i][0]); + } else + SetDestinationPath((LPTSTR)&argv[i][1]); + break; + case 'y': + case 'Y': PromptOnOverwrite = FALSE; break; + default: + printf("Bad parameter %s.\n", argv[i]); + return FALSE; + } + } else { + if ((FoundCabinet) || (Mode == CM_MODE_CREATE)) { + /* FIXME: There may be many of these if Mode != CM_MODE_CREATE */ + lstrcpy((LPTSTR)FileName, argv[i]); + } else { + SetCabinetName(argv[i]); + FoundCabinet = TRUE; + } + } + } + + if (ShowUsage) { + Usage(); + return FALSE; + } + + /* FIXME */ + SelectCodec(CAB_CODEC_MSZIP); + + return TRUE; +} + + +VOID CCABManager::CreateCabinet() +/* + * FUNCTION: Create cabinet + */ +{ + ULONG Status; + + Status = Load((LPTSTR)&FileName); + if (Status != CAB_STATUS_SUCCESS) { + printf("Specified directive file could not be found: %s.\n", (LPTSTR)&FileName); + return; + } + + Parse(); +} + + +VOID CCABManager::DisplayCabinet() +/* + * FUNCTION: Display cabinet contents + */ +{ + CAB_SEARCH Search; + TCHAR Str[20]; + DWORD FileCount = 0; + DWORD ByteCount = 0; + + if (Open() == CAB_STATUS_SUCCESS) { + printf("Cabinet %s\n\n", GetCabinetName()); + + if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) { + do { + if (Search.File->FileControlID != CAB_FILE_CONTINUED) { + printf("%s ", Date2Str((LPTSTR)&Str, Search.File->FileDate)); + printf("%s ", Time2Str((LPTSTR)&Str, Search.File->FileTime)); + printf("%s ", Attr2Str((LPTSTR)&Str, Search.File->Attributes)); + printf("%s ", Pad(itoa(Search.File->FileSize, (LPTSTR)&Str, 10), ' ', 13)); + printf("%s\n", Search.FileName); + + FileCount++; + ByteCount += Search.File->FileSize; + } + } while (FindNext(&Search) == CAB_STATUS_SUCCESS); + } + + if (FileCount > 0) { + if (FileCount == 1) + printf(" 1 file "); + else + printf(" %s files ", + Pad(itoa(FileCount, (LPTSTR)&Str, 10), ' ', 12)); + + if (ByteCount == 1) + printf(" 1 byte\n"); + else + printf("%s bytes\n", + Pad(itoa(ByteCount, (LPTSTR)&Str, 10), ' ', 12)); + } else { + /* There should be at least one file in a cabinet */ + printf("No files in cabinet."); + } + } else + printf("Cannot not open file: %s\n", GetCabinetName()); +} + + +VOID CCABManager::ExtractFromCabinet() +/* + * FUNCTION: Extract file(s) from cabinet + */ +{ + CAB_SEARCH Search; + ULONG Status; + + if (Open() == CAB_STATUS_SUCCESS) { + printf("Cabinet %s\n\n", GetCabinetName()); + + if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) { + do { + switch (Status = ExtractFile(Search.FileName)) { + case CAB_STATUS_SUCCESS: + break; + case CAB_STATUS_INVALID_CAB: + printf("Cabinet contains errors.\n"); + return; + case CAB_STATUS_UNSUPPCOMP: + printf("Cabinet uses unsupported compression type.\n"); + return; + case CAB_STATUS_CANNOT_WRITE: + printf("You've run out of free space on the destination volume or the volume is damaged.\n"); + return; + default: + printf("Unspecified error code (%d).\n", (UINT)Status); + return; + } + } while (FindNext(&Search) == CAB_STATUS_SUCCESS); + } + } else + printf("Cannot not open file: %s.\n", GetCabinetName()); +} + + +VOID CCABManager::Run() +/* + * FUNCTION: Process cabinet + */ +{ + printf("ReactOS Cabinet Manager - Version %s\n\n", CM_VERSION); + + switch (Mode) { + case CM_MODE_CREATE: CreateCabinet(); break; + case CM_MODE_DISPLAY: DisplayCabinet(); break; + case CM_MODE_EXTRACT: ExtractFromCabinet(); break; + default: + break; + } + printf("\n"); +} + + +/* Event handlers */ + +BOOL CCABManager::OnOverwrite(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called when extracting a file and it already exists + * ARGUMENTS: + * File = Pointer to CFFILE for file being extracted + * Filename = Pointer to buffer with name of file (full path) + * RETURNS + * TRUE if the file should be overwritten, FALSE if not + */ +{ + TCHAR ch; + + if (Mode == CM_MODE_CREATE) + return TRUE; + + /* Should we prompt on overwrite? */ + if (!PromptOnOverwrite) + return TRUE; + + /* Ask if file should be overwritten */ + printf("Overwrite %s (Yes/No/All)? ", GetFileName(FileName)); + + for (;;) { + ch = _getch(); + switch (ch) { + case 'Y': + case 'y': printf("%c\n", ch); return TRUE; + case 'N': + case 'n': printf("%c\n", ch); return FALSE; + case 'A': + case 'a': printf("%c\n", ch); PromptOnOverwrite = FALSE; return TRUE; + } + } +} + + +VOID CCABManager::OnExtract(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called just before extracting a file + * ARGUMENTS: + * File = Pointer to CFFILE for file being extracted + * FileName = Pointer to buffer with name of file (full path) + */ +{ + printf("Extracting %s\n", GetFileName(FileName)); +} + + + +VOID CCABManager::OnDiskChange(LPTSTR CabinetName, + LPTSTR DiskLabel) +/* + * FUNCTION: Called when a new disk is to be processed + * ARGUMENTS: + * CabinetName = Pointer to buffer with name of cabinet + * DiskLabel = Pointer to buffer with label of disk + */ +{ + printf("\nChanging to cabinet %s - %s\n\n", CabinetName, DiskLabel); +} + + +VOID CCABManager::OnAdd(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called just before adding a file to a cabinet + * ARGUMENTS: + * File = Pointer to CFFILE for file being added + * FileName = Pointer to buffer with name of file (full path) + */ +{ + printf("Adding %s\n", GetFileName(FileName)); +} + + +INT main(INT argc, PCHAR argv[]) +/* + * FUNCTION: Main entry point + * ARGUMENTS: + * argc = Number of arguments on command line + * argv = Pointer to list of command line arguments + */ +{ + CCABManager CABMgr; + + if (CABMgr.ParseCmdline(argc, argv)) + CABMgr.Run(); + + return 0; +} + +/* EOF */ diff --git a/apps/utils/cabman/makefile b/apps/utils/cabman/makefile new file mode 100644 index 0000000..2d3a1ab --- /dev/null +++ b/apps/utils/cabman/makefile @@ -0,0 +1,64 @@ +# +# Makefile for ReactOS Cabinet Manager +# +PATH_TO_TOP = ../../.. + +#FIXME: why doesn't this work? +#ZLIB_OBJECTS = $(PATH_TO_TOP)/lib/zlib/zlib.a +ZLIB_PATH = $(PATH_TO_TOP)/lib/zlib + +ZLIB_OBJECTS = $(ZLIB_PATH)/adler32.o $(ZLIB_PATH)/deflate.o \ + $(ZLIB_PATH)/infblock.o $(ZLIB_PATH)/infcodes.o \ + $(ZLIB_PATH)/inflate.o $(ZLIB_PATH)/inftrees.o \ + $(ZLIB_PATH)/infutil.o $(ZLIB_PATH)/inffast.o \ + $(ZLIB_PATH)/trees.o $(ZLIB_PATH)/zutil.o +ENGINE_OBJECTS = $(ZLIB_OBJECTS) cabinet.o mszip.o raw.o +TEST_OBJECTS = $(ENGINE_OBJECTS) test.o +OBJECTS = $(ENGINE_OBJECTS) main.o dfp.o +TARGET = cabman +PROGS = $(TARGET).exe test.exe + +#FIXME: zlib should be compiled and installed in the SDK by the master makefile +CFLAGS += -O3 -I$(ZLIB_PATH) + +CLEAN_FILES = *.o $(TARGET).exe $(TARGET).sym test.exe test.sym + +all: $(PROGS) + +clean: + - $(RM) $(CLEAN_FILES) + +.phony: clean + +install: $(PROGS:%=$(FLOPPY_DIR)/apps/%) + +$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: % +ifeq ($(DOSCLI),yes) + $(CP) $* $(FLOPPY_DIR)\apps\$* +else + $(CP) $* $(FLOPPY_DIR)/apps/$* +endif + +dist: $(PROGS:%=../../$(DIST_DIR)/apps/%) + +$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: % +ifeq ($(DOSCLI),yes) + $(CP) $* ..\..\$(DIST_DIR)\apps\$* +else + $(CP) $* ../../$(DIST_DIR)/apps/$* +endif + +#FIXME: zlib should be compiled and installed in the SDK by the master makefile +$(ZLIB_PATH)/zlib.a: + make -C $(ZLIB_PATH) -f makefile.reactos + +$(TARGET).exe: $(OBJECTS) $(ZLIB_PATH)/zlib.a + $(CC) $(OBJECTS) -o $(TARGET).exe + $(NM) --numeric-sort $(TARGET).exe > $(TARGET).sym + +test.exe: $(TEST_OBJECTS) + $(CC) $(TEST_OBJECTS) -o test.exe + $(NM) --numeric-sort test.exe > test.sym + +include ../../rules.mak + diff --git a/apps/utils/cabman/mszip.cpp b/apps/utils/cabman/mszip.cpp new file mode 100644 index 0000000..ec35e92 --- /dev/null +++ b/apps/utils/cabman/mszip.cpp @@ -0,0 +1,172 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/mszip.cpp + * PURPOSE: CAB codec for MSZIP compressed data + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: The ZLIB does the real work. Get the full version + * from http://www.cdrom.com/pub/infozip/zlib/ + * REVISIONS: + * CSH 21/03-2001 Created + */ +#include +#include +#include "mszip.h" + + +/* Memory functions */ + +voidpf MSZipAlloc(voidpf opaque, uInt items, uInt size) +{ + DPRINT(DEBUG_MEMORY, ("items = (%d) size = (%d)\n", items, size)); + return HeapAlloc(GetProcessHeap(), 0, items * size); +} + +void MSZipFree (voidpf opaque, voidpf address) +{ + DPRINT(DEBUG_MEMORY, ("\n")); + HeapFree(GetProcessHeap(), 0, address); +} + + +/* CMSZipCodec */ + +CMSZipCodec::CMSZipCodec() +/* + * FUNCTION: Default constructor + */ +{ + ZStream.zalloc = MSZipAlloc; + ZStream.zfree = MSZipFree; + ZStream.opaque = (voidpf)0; +} + + +CMSZipCodec::~CMSZipCodec() +/* + * FUNCTION: Default destructor + */ +{ +} + + +ULONG CMSZipCodec::Compress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength) +/* + * FUNCTION: Compresses data in a buffer + * ARGUMENTS: + * OutputBuffer = Pointer to buffer to place compressed data + * InputBuffer = Pointer to buffer with data to be compressed + * InputLength = Length of input buffer + * OutputLength = Address of buffer to place size of compressed data + */ +{ + PUSHORT Magic; + + DPRINT(MAX_TRACE, ("InputLength (%d).\n", InputLength)); + + Magic = (PUSHORT)OutputBuffer; + *Magic = MSZIP_MAGIC; + + ZStream.next_in = (PUCHAR)InputBuffer; + ZStream.avail_in = InputLength; + ZStream.next_out = (PUCHAR)((ULONG)OutputBuffer + 2); + ZStream.avail_out = CAB_BLOCKSIZE + 12; + + /* WindowBits is passed < 0 to tell that there is no zlib header */ + Status = deflateInit2(&ZStream, + Z_BEST_COMPRESSION, + Z_DEFLATED, + -MAX_WBITS, + 8, /* memLevel */ + Z_DEFAULT_STRATEGY); + if (Status != Z_OK) { + DPRINT(MIN_TRACE, ("deflateInit() returned (%d).\n", Status)); + return CS_NOMEMORY; + } + + Status = deflate(&ZStream, Z_FINISH); + if ((Status != Z_OK) && (Status != Z_STREAM_END)) { + DPRINT(MIN_TRACE, ("deflate() returned (%d) (%s).\n", Status, ZStream.msg)); + if (Status == Z_MEM_ERROR) + return CS_NOMEMORY; + return CS_BADSTREAM; + } + + *OutputLength = ZStream.total_out + 2; + + Status = deflateEnd(&ZStream); + if (Status != Z_OK) { + DPRINT(MIN_TRACE, ("deflateEnd() returned (%d).\n", Status)); + return CS_BADSTREAM; + } + + return CS_SUCCESS; +} + + +ULONG CMSZipCodec::Uncompress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength) +/* + * FUNCTION: Uncompresses data in a buffer + * ARGUMENTS: + * OutputBuffer = Pointer to buffer to place uncompressed data + * InputBuffer = Pointer to buffer with data to be uncompressed + * InputLength = Length of input buffer + * OutputLength = Address of buffer to place size of uncompressed data + */ +{ + USHORT Magic; + + DPRINT(MAX_TRACE, ("InputLength (%d).\n", InputLength)); + + Magic = *((PUSHORT)InputBuffer); + + if (Magic != MSZIP_MAGIC) { + DPRINT(MID_TRACE, ("Bad MSZIP block header magic (0x%X)\n", Magic)); + return CS_BADSTREAM; + } + + ZStream.next_in = (PUCHAR)((ULONG)InputBuffer + 2); + ZStream.avail_in = InputLength - 2; + ZStream.next_out = (PUCHAR)OutputBuffer; + ZStream.avail_out = CAB_BLOCKSIZE + 12; + + /* WindowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + */ + Status = inflateInit2(&ZStream, -MAX_WBITS); + if (Status != Z_OK) { + DPRINT(MIN_TRACE, ("inflateInit2() returned (%d).\n", Status)); + return CS_BADSTREAM; + } + + while ((ZStream.total_out < CAB_BLOCKSIZE + 12) && + (ZStream.total_in < InputLength - 2)) { + Status = inflate(&ZStream, Z_NO_FLUSH); + if (Status == Z_STREAM_END) break; + if (Status != Z_OK) { + DPRINT(MIN_TRACE, ("inflate() returned (%d) (%s).\n", Status, ZStream.msg)); + if (Status == Z_MEM_ERROR) + return CS_NOMEMORY; + return CS_BADSTREAM; + } + } + + *OutputLength = ZStream.total_out; + + Status = inflateEnd(&ZStream); + if (Status != Z_OK) { + DPRINT(MIN_TRACE, ("inflateEnd() returned (%d).\n", Status)); + return CS_BADSTREAM; + } + return CS_SUCCESS; +} + +/* EOF */ diff --git a/apps/utils/cabman/mszip.h b/apps/utils/cabman/mszip.h new file mode 100644 index 0000000..4d787c7 --- /dev/null +++ b/apps/utils/cabman/mszip.h @@ -0,0 +1,41 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/mszip.h + * PURPOSE: CAB codec for MSZIP compressed data + */ +#ifndef __MSZIP_H +#define __MSZIP_H + +#include "cabinet.h" +#include + +#define MSZIP_MAGIC 0x4B43 + + +/* Classes */ + +class CMSZipCodec : public CCABCodec { +public: + /* Default constructor */ + CMSZipCodec(); + /* Default destructor */ + virtual ~CMSZipCodec(); + /* Compresses a data block */ + virtual ULONG Compress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength); + /* Uncompresses a data block */ + virtual ULONG Uncompress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength); +private: + INT Status; + z_stream ZStream; /* Zlib stream */ +}; + +#endif /* __MSZIP_H */ + +/* EOF */ diff --git a/apps/utils/cabman/raw.cpp b/apps/utils/cabman/raw.cpp new file mode 100644 index 0000000..9014b16 --- /dev/null +++ b/apps/utils/cabman/raw.cpp @@ -0,0 +1,69 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/raw.cpp + * PURPOSE: CAB codec for uncompressed "raw" data + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 21/03-2001 Created + */ +#include +#include "raw.h" + + +/* CRawCodec */ + +CRawCodec::CRawCodec() +/* + * FUNCTION: Default constructor + */ +{ +} + + +CRawCodec::~CRawCodec() +/* + * FUNCTION: Default destructor + */ +{ +} + + +ULONG CRawCodec::Compress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength) +/* + * FUNCTION: Compresses data in a buffer + * ARGUMENTS: + * OutputBuffer = Pointer to buffer to place compressed data + * InputBuffer = Pointer to buffer with data to be compressed + * InputLength = Length of input buffer + * OutputLength = Address of buffer to place size of compressed data + */ +{ + CopyMemory(OutputBuffer, InputBuffer, InputLength); + *OutputLength = InputLength; + return CS_SUCCESS; +} + + +ULONG CRawCodec::Uncompress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength) +/* + * FUNCTION: Uncompresses data in a buffer + * ARGUMENTS: + * OutputBuffer = Pointer to buffer to place uncompressed data + * InputBuffer = Pointer to buffer with data to be uncompressed + * InputLength = Length of input buffer + * OutputLength = Address of buffer to place size of uncompressed data + */ +{ + CopyMemory(OutputBuffer, InputBuffer, InputLength); + *OutputLength = InputLength; + return CS_SUCCESS; +} + +/* EOF */ diff --git a/apps/utils/cabman/raw.h b/apps/utils/cabman/raw.h new file mode 100644 index 0000000..35848a0 --- /dev/null +++ b/apps/utils/cabman/raw.h @@ -0,0 +1,35 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS cabinet manager + * FILE: apps/cabman/raw.h + * PURPOSE: CAB codec for uncompressed data + */ +#ifndef __RAW_H +#define __RAW_H + +#include "cabinet.h" + + +/* Classes */ + +class CRawCodec : public CCABCodec { +public: + /* Default constructor */ + CRawCodec(); + /* Default destructor */ + virtual ~CRawCodec(); + /* Compresses a data block */ + virtual ULONG Compress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength); + /* Uncompresses a data block */ + virtual ULONG Uncompress(PVOID OutputBuffer, + PVOID InputBuffer, + DWORD InputLength, + PDWORD OutputLength); +}; + +#endif /* __RAW_H */ + +/* EOF */ diff --git a/apps/utils/cabman/test.cpp b/apps/utils/cabman/test.cpp new file mode 100644 index 0000000..0354ec1 --- /dev/null +++ b/apps/utils/cabman/test.cpp @@ -0,0 +1,164 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Test program for cabinet classes + * FILE: apps/cabman/test.cpp + * PURPOSE: Test program + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 21/03-2001 Created + */ +#include +#include +#include +#include +#include +#include +#include "test.h" + + +#ifdef DBG + +DWORD DebugTraceLevel = MIN_TRACE; +//DWORD DebugTraceLevel = MID_TRACE; +//DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + + +/* CCABManager */ + +CCABTest::CCABTest() +/* + * FUNCTION: Default constructor + */ +{ + PromptOnOverwrite = FALSE; +} + + +CCABTest::~CCABTest() +/* + * FUNCTION: Default destructor + */ +{ +} + + +VOID CCABTest::ExtractFromCabinet() +/* + * FUNCTION: Extract file(s) from cabinet + */ +{ + CAB_SEARCH Search; + ULONG Status; + + if (Open() == CAB_STATUS_SUCCESS) { + printf("Cabinet %s\n\n", GetCabinetName()); + + if (FindFirst("", &Search) == CAB_STATUS_SUCCESS) { + do { + switch (Status = ExtractFile(Search.FileName)) { + case CAB_STATUS_SUCCESS: + break; + case CAB_STATUS_INVALID_CAB: + printf("Cabinet contains errors.\n"); + return; + case CAB_STATUS_UNSUPPCOMP: + printf("Cabinet uses unsupported compression type.\n"); + return; + case CAB_STATUS_CANNOT_WRITE: + printf("You've run out of free space on the destination volume or the volume is damaged.\n"); + return; + default: + printf("Unspecified error code (%d).\n", (UINT)Status); + return; + } + } while (FindNext(&Search) == CAB_STATUS_SUCCESS); + } + } else { + printf("Cannot not open file: %s.\n", GetCabinetName()); + } +} + + +/* Event handlers */ + +BOOL CCABTest::OnOverwrite(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called when extracting a file and it already exists + * ARGUMENTS: + * File = Pointer to CFFILE for file being extracted + * Filename = Pointer to buffer with name of file (full path) + * RETURNS + * TRUE if the file should be overwritten, FALSE if not + */ +{ + TCHAR ch; + + /* Should we prompt on overwrite? */ + if (!PromptOnOverwrite) + return TRUE; + + /* Ask if file should be overwritten */ + printf("Overwrite %s (Yes/No/All)? ", GetFileName(FileName)); + + for (;;) { + ch = _getch(); + switch (ch) { + case 'Y': + case 'y': printf("%c\n", ch); return TRUE; + case 'N': + case 'n': printf("%c\n", ch); return FALSE; + case 'A': + case 'a': printf("%c\n", ch); PromptOnOverwrite = FALSE; return TRUE; + } + } +} + + +VOID CCABTest::OnExtract(PCFFILE File, + LPTSTR FileName) +/* + * FUNCTION: Called just before extracting a file + * ARGUMENTS: + * File = Pointer to CFFILE for file being extracted + * FileName = Pointer to buffer with name of file (full path) + */ +{ + printf("Extracting %s\n", GetFileName(FileName)); +} + + + +VOID CCABTest::OnDiskChange(LPTSTR CabinetName, + LPTSTR DiskLabel) +/* + * FUNCTION: Called when a new disk is to be processed + * ARGUMENTS: + * CabinetName = Pointer to buffer with name of cabinet + * DiskLabel = Pointer to buffer with label of disk + */ +{ + printf("\nChanging to cabinet %s - %s\n\n", CabinetName, DiskLabel); +} + + +INT main(INT argc, PCHAR argv[]) +/* + * FUNCTION: Main entry point + * ARGUMENTS: + * argc = Number of arguments on command line + * argv = Pointer to list of command line arguments + */ +{ + CCABTest CABTest; + + // Specify your cabinet filename here + CABTest.SetCabinetName("ros1.cab"); + CABTest.ExtractFromCabinet(); + + return 0; +} + +/* EOF */ diff --git a/apps/utils/cabman/test.h b/apps/utils/cabman/test.h new file mode 100644 index 0000000..ad9a18b --- /dev/null +++ b/apps/utils/cabman/test.h @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Test program for cabinet classes + * FILE: apps/cabman/test.h + * PURPOSE: Test program header + */ +#ifndef __TEST_H +#define __TEST_H + +#define CAB_READ_ONLY // Define for smaller read only version +#include "cabinet.h" + + +/* Classes */ + +class CCABTest : public CCabinet { +public: + CCABTest(); + virtual ~CCABTest(); + VOID ExtractFromCabinet(); + /* Event handlers */ + virtual BOOL OnOverwrite(PCFFILE File, LPTSTR FileName); + virtual VOID OnExtract(PCFFILE File, LPTSTR FileName); + virtual VOID OnDiskChange(LPTSTR CabinetName, LPTSTR DiskLabel); +private: + /* Configuration */ + BOOL PromptOnOverwrite; +}; + +#endif /* __CABMAN_H */ + +/* EOF */ diff --git a/apps/utils/cat/cat.c b/apps/utils/cat/cat.c new file mode 100644 index 0000000..ff1b630 --- /dev/null +++ b/apps/utils/cat/cat.c @@ -0,0 +1,26 @@ +#include +#include + +int main(int argc, char* argv[]) +{ + int i; + FILE* in; + char ch; + + for (i=1; i +#include + +// **************************** CListNode **************************** + +HANDLE CListNode::hHeap = NULL; +INT CListNode::nRef = 0; + +// Default constructor +CListNode::CListNode() +{ + Element = NULL; + Next = NULL; + Prev = NULL; +} + +// Constructor with element and next as starter values +CListNode::CListNode(PVOID element, CListNode *next, CListNode *prev) +{ + Element = element; + Next = next; + Prev = prev; +} + +void* CListNode::operator new(/*size_t*/ UINT size) +{ + PVOID p; + if (hHeap == NULL) { + SYSTEM_INFO inf; + GetSystemInfo(&inf); + hHeap = HeapCreate(0, inf.dwAllocationGranularity, 0); + } + if ((p = HeapAlloc(hHeap, 0, size)) != NULL) + nRef++; + return p; +} + +VOID CListNode::operator delete(void* p) +{ + if (HeapFree(hHeap, 0, p) != FALSE) + nRef--; + if (nRef == 0) { + HeapDestroy(hHeap); + hHeap = NULL; + } +} + +// Set element +VOID CListNode::SetElement(PVOID element) +{ + Element = element; +} + +// Set pointer to next node in list +VOID CListNode::SetNext(CListNode *next) +{ + Next = next; +} + +// Set pointer to previous node in list +VOID CListNode::SetPrev(CListNode *prev) +{ + Prev = prev; +} + +// Get element of node +PVOID CListNode::GetElement() +{ + return Element; +} + +// Get pointer to next node in list +CListNode *CListNode::GetNext() +{ + return Next; +} + +// Get pointer to previous node in list +CListNode *CListNode::GetPrev() +{ + return Prev; +} diff --git a/apps/utils/net/roshttpd/common/roshttpd.rc b/apps/utils/net/roshttpd/common/roshttpd.rc new file mode 100644 index 0000000..6c72702 --- /dev/null +++ b/apps/utils/net/roshttpd/common/roshttpd.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS HTTP Win32 Server\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "roshttpd\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalCopyright", "Casper S. Hornstrup (chorns@users.sourceforge.net)\0" + VALUE "OriginalFilename", "roshttpd.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/apps/utils/net/roshttpd/common/socket.cpp b/apps/utils/net/roshttpd/common/socket.cpp new file mode 100644 index 0000000..3c8dd34 --- /dev/null +++ b/apps/utils/net/roshttpd/common/socket.cpp @@ -0,0 +1,343 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: socket.cpp + * PURPOSE: Socket classes + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + */ +#include +#include +#include + +// ***************************** CSocket ***************************** + +// Default constructor +CSocket::CSocket() +{ + Active = FALSE; + Event = WSA_INVALID_EVENT; + Events = 0; + Socket = INVALID_SOCKET; + + // INET address family + SockAddrIn.sin_family = AF_INET; + + // Any address will do + SockAddrIn.sin_addr.s_addr = INADDR_ANY; + + // Convert to network ordering + SockAddrIn.sin_port = htons(0); +} + +// Default destructor +CSocket::~CSocket() +{ +} + +// Return winsock socket handle +SOCKET CSocket::GetSocket() +{ + return Socket; +} + +// Set winsock socket handle +VOID CSocket::SetSocket(SOCKET socket) +{ + Socket = socket; +} + + +// Return socket address +SOCKADDR_IN CSocket::GetSockAddrIn() +{ + return SockAddrIn; +} + +// Set socket address +VOID CSocket::SetSockAddrIn(SOCKADDR_IN sockaddrin) +{ + SockAddrIn = sockaddrin; +} + +// Associate winsock events with socket +VOID CSocket::SetEvents(LONG lEvents) +{ + if (Event == WSA_INVALID_EVENT) { + // Create socket event + Event = WSACreateEvent(); + if (Event == WSA_INVALID_EVENT) + throw ESocketOpen(TS("Unable to create event.")); + } + + if (lEvents != Events) { + // Associate network events with socket + if (WSAEventSelect(Socket, Event, lEvents) == SOCKET_ERROR) + throw ESocketOpen(TS("Unable to select socket events.")); + Events = lEvents; + } +} + +// Return associated winsock events +LONG CSocket::GetEvents() +{ + return Events; +} + +// Open socket +VOID CSocket::Open() +{ +} + +// Close socket +VOID CSocket::Close() +{ +} + + +// *********************** CServerClientSocket *********************** + +// Constructor with serversocket as parameter +CServerClientSocket::CServerClientSocket(LPCServerSocket lpServerSocket) +{ + ServerSocket = lpServerSocket; +} + +// Transmit data to socket +INT CServerClientSocket::Transmit( LPSTR lpsBuffer, UINT nLength) +{ + return send(Socket, lpsBuffer, nLength, 0); +} + +// Send a string to socket +INT CServerClientSocket::SendText( LPSTR lpsText) +{ + static CHAR crlf[3] = {0x0D, 0x0A, 0x00}; + INT nCount; + + nCount = Transmit(lpsText, strlen(lpsText)); + nCount += Transmit(crlf, strlen(crlf)); + return nCount; +} + +// Receive data from socket +INT CServerClientSocket::Receive(LPSTR lpsBuffer, UINT nLength) +{ + return recv(Socket, lpsBuffer, nLength, 0); +} + +// Process winsock messages if any +VOID CServerClientSocket::MessageLoop() +{ + UINT nStatus; + WSANETWORKEVENTS NetworkEvents; + + nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE); + if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) { + if ((NetworkEvents.lNetworkEvents & FD_READ) != 0) { + OnRead(); + } + if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) { + OnClose(); + } + } +} + +// Return server socket that own this socket +LPCServerSocket CServerClientSocket::GetServerSocket() +{ + return ServerSocket; +} + + +// *********************** CServerClientThread *********************** + +CServerClientThread::CServerClientThread(LPCServerClientSocket lpSocket) +{ + ClientSocket = lpSocket; +} + +CServerClientThread::~CServerClientThread() +{ + ClientSocket->GetServerSocket()->RemoveClient((LPCServerClientThread) this); +} + + +// ************************** CServerSocket ************************** + +// Default constructor +CServerSocket::CServerSocket() +{ +} + +// Default destructor +CServerSocket::~CServerSocket() +{ + if (Active) + Close(); +} + +// Open server socket so clients can connect +VOID CServerSocket::Open() +{ + assert(!Active); + + // Convert to network ordering + SockAddrIn.sin_port = htons(Port); + + if (Socket == INVALID_SOCKET) { + // Create socket + Socket = socket(AF_INET, SOCK_STREAM, 0); + if (Socket == INVALID_SOCKET) + throw ESocketOpen(TS("Unable to allocate a socket.")); + } + + // Associate an address with server socket + if (bind(Socket, (struct sockaddr FAR *) &SockAddrIn, sizeof(SockAddrIn)) == SOCKET_ERROR) + throw ESocketOpen(TS("Unable to associate address with socket.")); + + // Listen for incoming connections + if (listen(Socket, MAX_PENDING_CONNECTS) != 0) + throw ESocketOpen(TS("Unable to listen on socket.")); + + // Associate network events with socket + SetEvents(FD_ACCEPT | FD_CONNECT | FD_CLOSE); + + Active = TRUE; +} + +// Close server socket and all current connections +VOID CServerSocket::Close() +{ + assert(Active); + + if (Event != WSA_INVALID_EVENT) { + // Tell winsock not to notify us about any events + if (WSAEventSelect(Socket, Event, 0) == SOCKET_ERROR) + throw ESocketClose(TS("Unable to select socket events.")); + + if (!WSACloseEvent(Event)) + throw ESocketClose(TS("Unable to close socket event.")); + Event = WSA_INVALID_EVENT; + } + + CIterator *i = Connections.CreateIterator(); + + // Terminate and free all client threads + for (i->First(); !i->IsDone(); i->Next()) { + //i->CurrentItem()->Terminate(); + delete i->CurrentItem(); + } + delete i; + Connections.RemoveAll(); + + closesocket(Socket); + Socket = INVALID_SOCKET; + + Active = FALSE; +} + +// Set port number to listen on +VOID CServerSocket::SetPort(UINT nPort) +{ + assert(!Active); + + Port = nPort; +} + +// Process messages from winsock if any +VOID CServerSocket::MessageLoop() +{ + UINT nStatus; + INT nAddrLen; + SOCKET ClientSocket; + SOCKADDR_IN SockAddrIn; + WSANETWORKEVENTS NetworkEvents; + LPCServerClientSocket lpClient; + LPCServerClientThread lpThread; + + nStatus = WSAWaitForMultipleEvents(1, &Event, FALSE, 0, FALSE); + if ((nStatus == 0) && (WSAEnumNetworkEvents(Socket, Event, &NetworkEvents) != SOCKET_ERROR)) { + if ((NetworkEvents.lNetworkEvents & FD_ACCEPT) != 0) { + lpClient = OnGetSocket(this); + nAddrLen = sizeof(SockAddrIn); + ClientSocket = accept(Socket, (SOCKADDR *) &SockAddrIn, &nAddrLen); + if (ClientSocket != INVALID_SOCKET) { + // Set socket handle + lpClient->SetSocket(ClientSocket); + // Set socket address + lpClient->SetSockAddrIn(SockAddrIn); + // Set winsock events + lpClient->SetEvents(FD_READ | FD_CLOSE); + // Create client connection thread + lpThread = OnGetThread(lpClient); + // Add client thread to connection list + InsertClient(lpThread); + // Call OnAccept event handler + OnAccept(lpThread); + } else { + delete lpClient; + lpClient = NULL; + throw ESocketOpen(TS("No more sockets available.")); + } + } + /*if ((NetworkEvents.lNetworkEvents & FD_CONNECT) != 0) { + } + if ((NetworkEvents.lNetworkEvents & FD_CLOSE) != 0) { + }*/ + } +} + +// Insert client into connection list +VOID CServerSocket::InsertClient(LPCServerClientThread lpClient) +{ + Connections.Insert(lpClient); +} + +// Remove client from connection list +VOID CServerSocket::RemoveClient(LPCServerClientThread lpClient) +{ + Connections.Remove(lpClient); +} + +// OnGetSocket event handler +LPCServerClientSocket CServerSocket::OnGetSocket(LPCServerSocket lpServerSocket) +{ + return NULL; +} + +// OnGetThread event handler +LPCServerClientThread CServerSocket::OnGetThread(LPCServerClientSocket lpSocket) +{ + return NULL; +} + + +// Initialize WinSock DLL +VOID InitWinsock() +{ + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + + if (WSAStartup(wVersionRequested, &wsaData) != 0) + // Return FALSE as we couldn't find a usable WinSock DLL + throw ESocketWinsock(TS("Unable to initialize winsock dll.")); + + /* Confirm that the WinSock DLL supports 2.0 */ + + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { + // We couldn't find a usable winsock dll + WSACleanup(); + throw ESocketDll(TS("Winsock dll version is not 2.0 or higher.")); + } +} + +// Deinitialize WinSock DLL +VOID DeinitWinsock() +{ + if (WSACleanup() != 0) + throw ESocketWinsock(TS("Unable to deinitialize winsock dll.")); +} diff --git a/apps/utils/net/roshttpd/common/thread.cpp b/apps/utils/net/roshttpd/common/thread.cpp new file mode 100644 index 0000000..bedea34 --- /dev/null +++ b/apps/utils/net/roshttpd/common/thread.cpp @@ -0,0 +1,80 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: thread.cpp + * PURPOSE: Generic thread class + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + */ +#include +#include +#include +#include + +// This is the thread entry code +DWORD WINAPI ThreadEntry(LPVOID parameter) +{ + ThreadData *p = (ThreadData*) parameter; + + p->ClassPtr->Execute(); + + SetEvent(p->hFinished); + return 0; +} + +// Default constructor +CThread::CThread() +{ + bTerminated = FALSE; + // Points to the class that is executed within thread + Data.ClassPtr = this; + // Create synchronization event + Data.hFinished = CreateEvent(NULL, TRUE, FALSE, NULL); + + // FIXME: Do some error handling + assert(Data.hFinished != NULL); + + // Create thread + hThread = CreateThread(NULL, 0, ThreadEntry, &Data, 0, &dwThreadId); + + // FIXME: Do some error handling + assert(hThread != NULL); +} + +// Default destructor +CThread::~CThread() +{ + if ((hThread != NULL) && (Data.hFinished != NULL)) { + if (!bTerminated) + Terminate(); + WaitForSingleObject(Data.hFinished, INFINITE); + CloseHandle(Data.hFinished); + CloseHandle(hThread); + hThread = NULL; + } +} + +// Execute thread code +void CThread::Execute() +{ + while (!bTerminated) Sleep(0); +} + +// Post a message to the thread's message queue +BOOL CThread::PostMessage(UINT Msg, WPARAM wParam, LPARAM lParam) +{ + return PostThreadMessage(dwThreadId, Msg, wParam, lParam); +} + +// Gracefully terminate thread +void CThread::Terminate() +{ + bTerminated = TRUE; +} + +// Returns TRUE if thread is terminated, FALSE if not +BOOL CThread::Terminated() +{ + return bTerminated; +} diff --git a/apps/utils/net/roshttpd/config.cpp b/apps/utils/net/roshttpd/config.cpp new file mode 100644 index 0000000..f928d34 --- /dev/null +++ b/apps/utils/net/roshttpd/config.cpp @@ -0,0 +1,130 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: config.cpp + * PURPOSE: Daemon configuration + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + */ +#include +#include +#include +#include + +using namespace std; + +LPCConfig pConfiguration; +LPCHttpDaemonThread pDaemonThread; + +// Default constructor +CConfig::CConfig() +{ + Reset(); +} + +// Default destructor +CConfig::~CConfig() +{ + Clear(); +} + +// Clear configuration +void CConfig::Reset() +{ + MainBase = NULL; + HttpBase = NULL; + DefaultResources.RemoveAll(); +} + +// Create default configuration. Can throw bad_alloc +void CConfig::Default() +{ + Clear(); + MainBase = (LPWSTR)_wcsdup(dcfgMainBase); + HttpBase = _strdup(dcfgHttpBase); + + LPSTR lpsStr; + try { + lpsStr = _strdup(dcfgDefaultResource); + DefaultResources.Insert(lpsStr); + } catch (bad_alloc e) { + free((void *)lpsStr); + Clear(); + throw; + } + + Port = dcfgDefaultPort; +} + +// Clear configuration +void CConfig::Clear() +{ + if (MainBase != NULL) + free((void *)MainBase); + if (HttpBase != NULL) + free((void *)HttpBase); + + // Free memory for all strings + CIterator *i = DefaultResources.CreateIterator(); + for (i->First(); !i->IsDone(); i->Next()) + free((void *)i->CurrentItem()); + delete i; + + Reset(); +} + +// Load configuration +BOOL CConfig::Load() +{ + Default(); + return TRUE; +} + +// Save configuration +BOOL CConfig::Save() +{ + return TRUE; +} + +// Return MainBase +LPWSTR CConfig::GetMainBase() +{ + return MainBase; +} + +// Set MainBase +void CConfig::SetMainBase(LPWSTR lpwsMainBase) +{ + MainBase = lpwsMainBase; +} + +// Return HttpBase +LPSTR CConfig::GetHttpBase() +{ + return HttpBase; +} + +// Set HttpBase +void CConfig::SetHttpBase(LPSTR lpsHttpBase) +{ + HttpBase = lpsHttpBase; +} + +// Return DefaultResources +CList* CConfig::GetDefaultResources() +{ + return &DefaultResources; +} + +// Return bound port +USHORT CConfig::GetPort() +{ + return Port; +} + +// Set port +VOID CConfig::SetPort(USHORT wPort) +{ + Port = wPort; +} diff --git a/apps/utils/net/roshttpd/error.cpp b/apps/utils/net/roshttpd/error.cpp new file mode 100644 index 0000000..5915b2a --- /dev/null +++ b/apps/utils/net/roshttpd/error.cpp @@ -0,0 +1,16 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: error.cpp + * PURPOSE: Error reporting + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + */ +#include +#include + +void ReportErrorStr(LPTSTR lpsText) +{ + wprintf((__wchar_t*)lpsText); +} diff --git a/apps/utils/net/roshttpd/http.cpp b/apps/utils/net/roshttpd/http.cpp new file mode 100644 index 0000000..07250ea --- /dev/null +++ b/apps/utils/net/roshttpd/http.cpp @@ -0,0 +1,380 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: http.cpp + * PURPOSE: HTTP 1.1 parser engine + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + * TODO: - Implement message-body + * - Implement more generel-header entries + * - Implement more request-header entries + * - Implement more entity-header entries + */ +#include +#include +#include +#include + +CHAR MethodTable[NUMMETHODS][8] = {"OPTIONS", "GET", "HEAD", "POST", "PUT", + "DELETE", "TRACE"}; + +CHAR GenerelTable[NUMGENERELS][18] = {"Cache-Control", "Connection", "Date", "Pragma", + "Transfer-Encoding", "Upgrade", "Via"}; + +CHAR RequestTable[NUMREQUESTS][20] = {"Accept", "Accept-Charset", "Accept-Encoding", + "Accept-Language", "Authorization", "From", "Host", "If-Modified-Since", "If-Match", + "If-None-Match", "If-Range", "If-Unmodified-Since", "Max-Forwards", + "Proxy-Authorization", "Range", "Referer", "User-Agent"}; + +CHAR EntityTable[NUMENTITIES][17] = {"Allow", "Content-Base", "Content-Encoding", + "Content-Language", "Content-Length", "Content-Location", "Content-MD5", + "Content-Range", "Content-Type", "ETag", "Expires", "Last-Modified"}; + +// *************************** CHttpParser *************************** + +// Default constructor +CHttpParser::CHttpParser() +{ + nHead = 0; + nTail = 0; +} + +// Default destructor +CHttpParser::~CHttpParser() +{ +} + +// Returns TRUE if a complete HTTP message is in buffer +BOOL CHttpParser::Complete() +{ + UINT nTmp; + + /*DPRINT("--1:-%d---\n", sBuffer[nHead-2]); + DPRINT("--2:-%d---\n", sBuffer[nHead-1]); + + sBuffer[nHead] = '!'; + sBuffer[nHead+1] = 0; + DPRINT("Examining buffer: (Head: %d, Tail: %d)\n", nHead, nTail); + DPRINT("%s\n", (LPSTR)&sBuffer[nTail]);*/ + + nTmp = nTail; + if (!Parse()) { + if (!bUnknownMethod) + nTail = nTmp; + return FALSE; + } else + return TRUE; +} + + +// Read a character from buffer +BOOL CHttpParser::ReadChar(LPSTR lpsStr) +{ + if (nTail <= nHead) { + if (nTail != nHead) { + lpsStr[0] = sBuffer[nTail]; + nTail++; + return TRUE; + } else { + lpsStr[0] = 0; + return FALSE; + } + } else { + if (nTail == sizeof(sBuffer)) + nTail = 0; + if (nTail != nHead) { + lpsStr[0] = sBuffer[nTail]; + nTail++; + return TRUE; + } else { + lpsStr[0] = 0; + return FALSE; + } + } +} + +// Peek at a character in the buffer +BOOL CHttpParser::PeekChar(LPSTR lpsStr) +{ + UINT nFakeTail; + + if (nTail == sizeof(sBuffer)) + nFakeTail = 0; + else + nFakeTail = nTail; + if (nFakeTail != nHead) { + lpsStr[0] = sBuffer[nFakeTail]; + return TRUE; + } else { + lpsStr[0] = 0; + return FALSE; + } +} + +// Read a string from buffer. Only A-Z, a-z, 0-9 and '-' are valid characters +BOOL CHttpParser::ReadString(LPSTR lpsStr, UINT nLength) +{ + UINT i = 0; + CHAR sTmp; + + while (PeekChar(&sTmp)) { + if (((sTmp >= 'A') && (sTmp <= 'Z')) || ((sTmp >= 'a') && (sTmp <= 'z')) || + ((sTmp >= '0') && (sTmp <= '9')) || (sTmp == '-')) { + if (i >= (nLength - 1)) { + lpsStr[0] = 0; + return FALSE; + } + ReadChar(&sTmp); + lpsStr[i] = sTmp; + i++; + } else { + lpsStr[i] = 0; + return TRUE; + } + } + lpsStr[0] = 0; + return FALSE; +} + +// Read a string from buffer. Stop if SP or CR is found or when there are no more +// characters +BOOL CHttpParser::ReadSpecial(LPSTR lpsStr, UINT nLength) +{ + UINT i = 0; + CHAR sTmp; + + while (PeekChar(&sTmp) && (sTmp != ' ') && (sTmp != 13)) { + if (i >= (nLength - 1)) { + lpsStr[nLength - 1] = 0; + return FALSE; + } + ReadChar(&sTmp); + lpsStr[i] = sTmp; + i++; + } + lpsStr[i] = 0; + return TRUE; +} + +// Skip until "sCh" is found +VOID CHttpParser::Skip(CHAR sCh) +{ + CHAR sTmp; + + while (PeekChar(&sTmp) && (sTmp != sCh)) + ReadChar(&sTmp); +} + +// Return TRUE if sCh is the next character +BOOL CHttpParser::Expect(CHAR sCh) +{ + CHAR sTmp; + + if (PeekChar(&sTmp)) { + if (sTmp == sCh) { + ReadChar(&sTmp); + return TRUE; + } + } + return FALSE; +} + +// Return TRUE if CRLF are the next characters +BOOL CHttpParser::ExpectCRLF() +{ + return (Expect(13) && Expect(10)); +} + +// Request = RequestLine | *( GenerelHeader | RequestHeader | EntityHeader ) +// CRLF [ MessageBody ] +BOOL CHttpParser::Parse() +{ + BOOL bStatus; + + + CHAR ch; + + if (RequestLine()) { + do { + if (!ReadString(sHeader, sizeof(sHeader))) + break; + bStatus = (GenerelHeader()); + bStatus = (RequestHeader() || bStatus); + bStatus = (EntityHeader() || bStatus); + } while (bStatus); + // CRLF + if (!ExpectCRLF()) + return FALSE; + MessageBody(); + return TRUE; + } + return FALSE; +} + +// RequestLine = Method SP RequestURI SP HTTP-Version CRLF +BOOL CHttpParser::RequestLine() +{ + CHAR sCh; + UINT i; + + bUnknownMethod = FALSE; + + // RFC 2068 states that servers SHOULD ignore any empty nine(s) received where a + // Request-Line is expected + while (PeekChar(&sCh) && ((sCh == 13) || (sCh == 10))); + + if (!ReadString(sMethod, sizeof(sMethod))) + return FALSE; + + for (i = 0; i < NUMMETHODS; i++) { + if (strcmp(MethodTable[i], sMethod) == 0) { + nMethodNo = i; + if (!Expect(' ')) + return FALSE; + // URI (ie. host/directory/resource) + if (!ReadSpecial(sUri, sizeof(sUri))) + return FALSE; + if (!Expect(' ')) + return FALSE; + // HTTP version (eg. HTTP/1.1) + if (!ReadSpecial(sVersion, sizeof(sVersion))) + return FALSE; + // CRLF + if (!ExpectCRLF()) + return FALSE; + + return TRUE; + } + } + bUnknownMethod = TRUE; + return FALSE; +} + +// GenerelHeader = Cache-Control | Connection | Date | Pragma | Transfer-Encoding | +// Upgrade | Via +BOOL CHttpParser::GenerelHeader() +{ + INT i; + + for (i = 0; i < NUMGENERELS; i++) { + if (strcmp(GenerelTable[i], sHeader) == 0) { + switch (i) { + case 1: { + //Connection + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + break; + } + default: { + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + } + } + return TRUE; + } + } + return FALSE; +} + +// RequestHeader = Accept | Accept-Charset | Accept-Encoding | Accept-Language | +// Authorization | From | Host | If-Modified-Since | If-Match | +// If-None-Match | If-Range | If-Unmodified-Since | Max-Forwards | +// Proxy-Authorization | Range | Referer | User-Agent +BOOL CHttpParser::RequestHeader() +{ + INT i; + + for (i = 0; i < NUMREQUESTS; i++) { + if (strcmp(RequestTable[i], sHeader) == 0) { + switch (i) { + case 0: { + //Accept + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + break; + } + case 2: { + //Accept-Encoding + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + break; + } + case 3: { + //Accept-Language + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + break; + } + case 6: { + //Host + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + break; + } + case 16: { + //User-Agent + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + break; + } + default: { + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + return TRUE; + } + } + return TRUE; + } + } + return FALSE; +} + +// EntityHeader = Allow | Content-Base | Content-Encoding | Content-Language | +// Content-Length | Content-Location | Content-MD5 | +// Content-Range | Content-Type | ETag | Expires | +// Last-Modified | extension-header +BOOL CHttpParser::EntityHeader() +{ + INT i; + + for (i = 0; i < NUMENTITIES; i++) { + if (strcmp(EntityTable[i], sHeader) == 0) { + switch (i) { + case 0: + default: { + //cout << ": #" << i << endl; + Expect(':'); + Expect(' '); + Skip(13); + ExpectCRLF(); + return TRUE; + } + } + return FALSE; + } + } + return FALSE; +} + +// MessageBody = *OCTET +BOOL CHttpParser::MessageBody() +{ + return FALSE; +} diff --git a/apps/utils/net/roshttpd/httpd.cpp b/apps/utils/net/roshttpd/httpd.cpp new file mode 100644 index 0000000..2ab38c8 --- /dev/null +++ b/apps/utils/net/roshttpd/httpd.cpp @@ -0,0 +1,492 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: httpd.cpp + * PURPOSE: HTTP daemon + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +CHAR HttpMsg400[] = "400 Bad Request\n\r

400 Bad Request

\n\rThe request had bad syntax.
\n\r\n\r\n\r"; +CHAR HttpMsg404[] = "404 Not Found\n\r

404 Not Found

\n\rThe requested URL was not found on this server.
\n\r\n\r\n\r"; +CHAR HttpMsg405[] = "405 Method Not Allowed\n\r

405 Method Not Allowed

\n\rThe requested method is not supported on this server.
\n\r\n\r\n\r"; +CHAR HttpMsg500[] = "500 Internal Server Error\n\r

500 Internal Server Error

\n\rAn internal error occurred.
\n\r\n\r\n\r"; +CHAR HttpMsg501[] = "501 Not Implemented\n\r

501 Not Implemented

\n\rThe feature is not implemented.
\n\r\n\r\n\r"; + + +// *************************** CHttpClient *************************** + +// Default constructor +CHttpClient::CHttpClient() +{ +} + +// Constructor with server socket as starter value +CHttpClient::CHttpClient(CServerSocket *serversocket) +{ + ServerSocket = serversocket; +} + +// Split URIs into its parts (ie. |http://|www.host.com|/resource|?parameters|) +VOID CHttpClient::SplitUri(LPSTR lpsUri, LPSTR lpsHost, LPSTR lpsResource, LPSTR lpsParams) +{ + LPSTR lpsPos; + LPSTR lpsStr; + UINT i; + + strcpy(lpsHost, ""); + strcpy(lpsResource, ""); + strcpy(lpsParams, ""); + + lpsPos = strstr(lpsUri, "://"); + if (lpsPos != NULL) + lpsStr = &lpsPos[3]; + else + lpsStr = lpsUri; + + lpsPos = strstr(lpsStr, "/"); + if (lpsPos != NULL) { + strncat(lpsHost, lpsPos, lpsPos - lpsStr); + lpsStr = &lpsPos[1]; + + lpsPos = strstr(lpsStr, "?"); + if (lpsPos != NULL) { + strncat(lpsResource, lpsStr, lpsPos - lpsStr); + strcpy(lpsParams, &lpsPos[1]); + } else { + strcpy(lpsResource, lpsStr); + strcpy(lpsParams, ""); + } + + // Replace "/" with "\" + for (i = 0; i < strlen(lpsResource); i++) { + if (lpsResource[i] == '/') + lpsResource[i] = '\\'; + } + } +} + +// Split resource into its parts (ie. |/path/|filename|.extension|) +VOID CHttpClient::SplitResource(LPSTR lpsResource, LPSTR lpsPath, LPSTR lpsFilename, LPSTR lpsExtension) +{ + INT i,len,fileptr,extptr; + + strcpy(lpsPath, ""); + strcpy(lpsFilename, ""); + strcpy(lpsExtension, ""); + + len = strlen(lpsResource); + if (len != 0) { + if (lpsResource[len - 1] == '/') { + // There is only a path + strcpy(lpsPath, lpsResource); + } else { + // Find extension + i = len - 1; + while ((i >= 0) && (lpsResource[i] != '.')) i--; + extptr = i; + while ((i >= 0) && (lpsResource[i] != '/')) i--; + if (i > 0) { + // There is at least one directory in the path (besides root directory) + fileptr = i + 1; + strncat(lpsPath, lpsResource, fileptr); + } else + fileptr = 1; + + // Get filename and possibly extension + if (extptr != 0) { + strncat(lpsFilename, &lpsResource[fileptr], extptr - fileptr); + // Get extension + strncat(lpsExtension, &lpsResource[extptr + 1], len - extptr - 1); + } else + strncat(lpsFilename, &lpsResource[fileptr], len - fileptr); + } + } +} + +// Process HTTP request +VOID CHttpClient::ProcessRequest() +{ + CHAR sStr[255]; + CHAR sHost[255]; + CHAR sResource[255]; + CHAR sParams[255]; + + // Which method? + switch (Parser.nMethodNo) { + case hmGET: { + SplitUri(Parser.sUri, sHost, sResource, sParams); + + // Default resource? + if (strlen(sResource) == 0) { + CIterator *i = pConfiguration->GetDefaultResources()->CreateIterator(); + + // FIXME: All default resources should be tried + // Iterate through all strings + //for (i->First(); !i->IsDone(); i->Next()) + i->First(); + if (!i->IsDone()) { + strcat(sResource, i->CurrentItem()); + delete i; + } else { + // File not found + Report("404 Not Found", HttpMsg404); + break; + } + } + strcpy(sStr, pConfiguration->GetHttpBase()); + strcat(sStr, sResource); + SendFile(sStr); + break; + } + default: { + // Method is not implemented + Report("501 Not Implemented", HttpMsg501); + } + } +} + +// Send a file to socket +VOID CHttpClient::SendFile(LPSTR lpsFilename) +{ + CHAR str[255]; + CHAR str2[32]; + union BigNum { + // unsigned __int64 Big; + unsigned long long Big; + struct { + DWORD Low; + DWORD High; + } u; + } nTotalBytes; + DWORD nBytesToRead; + DWORD nBytesRead; + BOOL bStatus; + + // Try to open file + hFile = CreateFileA(lpsFilename, + GENERIC_READ, // Open for reading + FILE_SHARE_READ, // Share for reading + NULL, // No security + OPEN_EXISTING, // Existing file only + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attr. template + if (hFile == INVALID_HANDLE_VALUE) { + // File not found + Report("404 Not Found", HttpMsg404); + return; + } + // Get file size + nTotalBytes.u.Low = GetFileSize(hFile, &nTotalBytes.u.High); + if ((nTotalBytes.u.Low == 0xFFFFFFFF) && ((GetLastError()) != NO_ERROR)) { + // Internal server error + Report("500 Internal Server Error", HttpMsg500); + // Close file + CloseHandle(hFile); + return; + } + + // Determine buffer size + if (nTotalBytes.Big < 65536) + nBufferSize = 1024; + else + nBufferSize = 32768; + // Allocate memory on heap + lpsBuffer = (PCHAR) malloc(nBufferSize); + + if (lpsBuffer == NULL) { + // Internal server error + Report("500 Internal Server Error", HttpMsg500); + // Close file + CloseHandle(hFile); + return; + } + + SendText("HTTP/1.1 200 OK"); + SendText("Server: ROSHTTPD"); + SendText("MIME-version: 1.0"); + SendText("Content-Type: text/plain"); + SendText("Accept-Ranges: bytes"); + strcpy(str, "Content-Length: "); + _itoa(nTotalBytes.u.Low, str2, 10); + strcat(str, str2); + SendText(str); + SendText(""); + // Read and transmit file + nTotalRead = 0; + nFileSize = nTotalBytes.Big; + bStop = FALSE; + + fd_set wfds; + FD_ZERO(&wfds); + FD_SET(Socket, &wfds); + do { + MessageLoop(); + + if (nTotalRead + nBufferSize < nFileSize) + nBytesToRead = nBufferSize; + else nBytesToRead = nFileSize - nTotalRead; + + bStatus = ReadFile(hFile, lpsBuffer, nBytesToRead, &nBytesRead, NULL); + if (bStatus) { + select(0, NULL, &wfds, NULL, NULL); + bStatus = (Transmit(lpsBuffer, nBytesRead) == (INT)nBytesRead); + nTotalRead += nBytesRead; + } + } while ((!bStop) && (bStatus) && (nTotalRead < nFileSize)); + + if (bStatus) + SendText(""); + else + // We can't send an error message here as we are in the process of sending a file. + // We have to terminate the connection instead + Close(); + + // Free allocated memory + free(lpsBuffer); + + // Close file + CloseHandle(hFile); +} + +// Report something to client +VOID CHttpClient::Report(LPSTR lpsCode, LPSTR lpsStr) +{ + CHAR sTmp[128]; + CHAR sTmp2[16]; + + strcpy(sTmp, "HTTP/1.1 "); + strcat(sTmp, lpsCode); + SendText(sTmp); + SendText("Server: ROSHTTPD"); + SendText("MIME-version: 1.0"); + SendText("Content-Type: text/html"); + SendText("Accept-Ranges: bytes"); + strcpy(sTmp, "Content-Length: "); + if (lpsStr != NULL) { + _itoa(strlen(lpsStr), sTmp2, 10); + strcat(sTmp, sTmp2); + } else + strcat(sTmp, "0"); + SendText(sTmp); + SendText(""); + if (lpsStr != NULL) + SendText(lpsStr); + SendText(""); +} + +// OnRead event handler +VOID CHttpClient::OnRead() +{ + LONG nCount; + + nCount = Receive((LPSTR) &Parser.sBuffer[Parser.nHead], + sizeof(Parser.sBuffer) - Parser.nHead); + + Parser.nHead += nCount; + if (Parser.nHead >= sizeof(Parser.sBuffer)) + Parser.nHead = 0; + + if (Parser.Complete()) { + ProcessRequest(); + } + + if (Parser.bUnknownMethod) { + // Method Not Allowed + Report("405 Method Not Allowed", HttpMsg405); + // Terminate connection + Close(); + } +} +/* +// OnWrite event handler +VOID CHttpClient::OnWrite() +{ + DWORD nBytesToRead; + DWORD nBytesRead; + + OutputDebugString(_T("Can write\n")); + + if (bSendingFile) { + if (nTotalRead + nBufferSize < nFileSize) + nBytesToRead = nBufferSize; + else nBytesToRead = nFileSize - nTotalRead; + + bError = ReadFile(hFile, Buffer, nBytesToRead, &nBytesRead, NULL); + if (!bError) { + Transmit(Buffer, nBytesRead); + nTotalRead += nBytesRead; + } + } +} +*/ +// OnClose event handler +VOID CHttpClient::OnClose() +{ + // Stop sending file if we are doing that now + bStop = TRUE; +} + + +// ************************ CHttpClientThread ************************ + +// Constructor with client socket as starter value +CHttpClientThread::CHttpClientThread(LPCServerClientSocket lpSocket) +{ + ClientSocket = lpSocket; +} + +// Execute client thread code +VOID CHttpClientThread::Execute() +{ + MSG Msg; + + while (!Terminated()) { + (( CHttpClient *) ClientSocket)->MessageLoop(); + if (PeekMessage(&Msg, 0, 0, 0, PM_REMOVE) != 0) { + switch (Msg.message) { + case HTTPD_START: { + // TODO: Start thread + break; + } + case HTTPD_STOP: { + // TODO: Stop thread + break; + } + default: + DispatchMessage(&Msg); + } + + } + } + + if (ClientSocket != NULL) { + delete ClientSocket; + ClientSocket = NULL; + } +} + + +// *************************** CHttpDaemon *************************** + +// Default constructor +CHttpDaemon::CHttpDaemon() +{ + State = hsStopped; + Start(); +} + +// Default destructor +CHttpDaemon::~CHttpDaemon() +{ + if (State==hsRunning) + Stop(); +} + +// Return daemon state +HTTPdState CHttpDaemon::GetState() const +{ + return State; +} + +// Start HTTP daemon +BOOL CHttpDaemon::Start() +{ + assert(State==hsStopped); + + SetPort(pConfiguration->GetPort()); + + Open(); + + State = hsRunning; + + return TRUE; +} + +// Stop HTTP daemon +BOOL CHttpDaemon::Stop() +{ + assert(State==hsRunning); + + Close(); + + State = hsStopped; + + return TRUE; +} + +// OnGetSocket event handler +LPCServerClientSocket CHttpDaemon::OnGetSocket(LPCServerSocket lpServerSocket) +{ + return new CHttpClient(lpServerSocket); +} + +// OnGetThread event handler +LPCServerClientThread CHttpDaemon::OnGetThread(LPCServerClientSocket lpSocket) +{ + return new CHttpClientThread(lpSocket); +} + +// OnAccept event handler +VOID CHttpDaemon::OnAccept(LPCServerClientThread lpThread) +{ +} + + +// ************************ CHttpDaemonThread ************************ + +// Execute daemon thread code +VOID CHttpDaemonThread::Execute() +{ + MSG Msg; + + try { + Daemon = NULL; + Daemon = new CHttpDaemon; + + while (!Terminated()) { + Daemon->MessageLoop(); + if (PeekMessage(&Msg, 0, 0, 0, PM_REMOVE) != 0) { + switch (Msg.message) { + case HTTPD_START: { + if (Daemon->GetState() == hsStopped) + Daemon->Start(); + break; + } + case HTTPD_STOP: { + if (Daemon->GetState() == hsRunning) + Daemon->Stop(); + break; + } + case HTTPD_SUSPEND: { + if (Daemon->GetState() == hsRunning){} + // FIXME: Suspend service + break; + } + case HTTPD_RESUME: { + if (Daemon->GetState() != hsSuspended){} + // FIXME: Resume service + break; + } + default: + DispatchMessage(&Msg); + } + } + } + delete Daemon; + } catch (ESocket e) { + ReportErrorStr(e.what()); + } catch (bad_alloc e) { + ReportErrorStr(TS("Insufficient resources.")); + } +} diff --git a/apps/utils/net/roshttpd/include/config.h b/apps/utils/net/roshttpd/include/config.h new file mode 100644 index 0000000..2479308 --- /dev/null +++ b/apps/utils/net/roshttpd/include/config.h @@ -0,0 +1,49 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/config.h + */ +#ifndef __CONFIG_H +#define __CONFIG_H + +#include +#include + +// General constants +#define APP_DESCRIPTION _T("ReactOS HTTP Daemon") + +// Default configuration +#define dcfgDescription _T("Default configuration") +#define dcfgMainBase _T("C:\\roshttpd\\") +#define dcfgHttpBase "C:\\roshttpd\\HttpBase\\" +#define dcfgDefaultResource "index.html" +#define dcfgDefaultPort 80 + +class CConfig { +public: + CConfig(); + ~CConfig(); + VOID Default(); + VOID Clear(); + BOOL Load(); + BOOL Save(); + LPWSTR GetMainBase(); + VOID SetMainBase(LPWSTR lpwsMainBase); + LPSTR GetHttpBase(); + VOID SetHttpBase(LPSTR lpsHttpBase); + CList* GetDefaultResources(); + USHORT GetPort(); + VOID SetPort(USHORT wPort); +private: + VOID Reset(); + LPWSTR MainBase; + LPSTR HttpBase; + CList DefaultResources; + USHORT Port; +}; +typedef CConfig* LPCConfig; + +extern LPCConfig pConfiguration; +extern LPCHttpDaemonThread pDaemonThread; + +#endif /* __CONFIG_H */ diff --git a/apps/utils/net/roshttpd/include/debug.h b/apps/utils/net/roshttpd/include/debug.h new file mode 100644 index 0000000..2c09275 --- /dev/null +++ b/apps/utils/net/roshttpd/include/debug.h @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/debug.h + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#include + +#ifdef DBG +#define DPRINT(x...) printf(x) +#else +#define DPRINT(x...) +#endif + +#endif /* __DEBUG_H */ diff --git a/apps/utils/net/roshttpd/include/error.h b/apps/utils/net/roshttpd/include/error.h new file mode 100644 index 0000000..33cf9c4 --- /dev/null +++ b/apps/utils/net/roshttpd/include/error.h @@ -0,0 +1,15 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/error.h + */ +#ifndef __ERROR_H +#define __ERROR_H + +#include + +#define TS(x) (LPTSTR)_T(x) + +void ReportErrorStr(LPTSTR lpsText); + +#endif /* __ERROR_H */ diff --git a/apps/utils/net/roshttpd/include/http.h b/apps/utils/net/roshttpd/include/http.h new file mode 100644 index 0000000..7d97eb5 --- /dev/null +++ b/apps/utils/net/roshttpd/include/http.h @@ -0,0 +1,57 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/http.h + */ +#ifndef __HTTP_H +#define __HTTP_H + +#include + +// Generel HTTP related constants +#define NUMMETHODS 7 +#define NUMGENERELS 7 +#define NUMREQUESTS 17 +#define NUMENTITIES 12 + +// HTTP method constants +#define hmOPTIONS 0 +#define hmGET 1 +#define hmHEAD 2 +#define hmPOST 3 +#define hmPUT 4 +#define hmDELETE 5 +#define hmTRACE 6 + +class CHttpParser { +public: + CHAR sBuffer[2048]; + UINT nHead; + UINT nTail; + CHAR sUri[255]; + CHAR sVersion[15]; + CHAR sHeader[63]; + CHAR sMethod[63]; + UINT nMethodNo; + BOOL bUnknownMethod; + BOOL bBadRequest; + CHttpParser(); + ~CHttpParser(); + BOOL Complete(); + BOOL Parse(); +private: + BOOL ReadChar(LPSTR lpsStr); + BOOL PeekChar(LPSTR lpsStr); + BOOL ReadString(LPSTR lpsStr, UINT nLength); + BOOL ReadSpecial(LPSTR lpStr, UINT nLength); + VOID Skip(CHAR sStr); + BOOL Expect(CHAR sStr); + BOOL ExpectCRLF(); + BOOL RequestLine(); + BOOL GenerelHeader(); + BOOL RequestHeader(); + BOOL EntityHeader(); + BOOL MessageBody(); +}; + +#endif /* __HTTP_H */ diff --git a/apps/utils/net/roshttpd/include/httpd.h b/apps/utils/net/roshttpd/include/httpd.h new file mode 100644 index 0000000..d281c0c --- /dev/null +++ b/apps/utils/net/roshttpd/include/httpd.h @@ -0,0 +1,85 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/httpd.h + */ +#ifndef __HTTPD_H +#define __HTTPD_H + +#include +#include +#include + +#define HTTPD_START WM_USER + 1 +#define HTTPD_STOP WM_USER + 2 +#define HTTPD_SUSPEND WM_USER + 3 +#define HTTPD_RESUME WM_USER + 4 + +enum HTTPdState { + hsStopped = 0, + hsRunning, + hsSuspended +}; + +class CHttpDaemon; + +class CHttpClient : public CServerClientSocket { +public: + CHttpClient(); + CHttpClient(LPCServerSocket lpServerSocket); + virtual void OnRead(); + //virtual void OnWrite(); + virtual void OnClose(); + HANDLE ThreadHandle; + DWORD ThreadId; + CHttpParser Parser; + void SplitUri(const LPSTR lpsUri, LPSTR lpsHost, LPSTR lpsResource, LPSTR lpsParams); + void SplitResource(const LPSTR lpsResource, LPSTR lpsPath, LPSTR lpsFilename, LPSTR lpsExtension); + void ProcessRequest(); + void SendFile(const LPSTR lpsFilename); + void Report(const LPSTR lpsCode, const LPSTR lpsStr); +private: + BOOL bStop; + LPSTR lpsBuffer; + LONG nBufferSize; + // unsigned __int64 nTotalRead; + unsigned long long nTotalRead; + // unsigned __int64 nFileSize; + unsigned long long nFileSize; + HANDLE hFile; +}; +typedef CHttpClient* LPCHttpClient; + +class CHttpClientThread : public CServerClientThread { +public: + CHttpClientThread() {}; + CHttpClientThread(LPCServerClientSocket Socket); + virtual void Execute(); +}; +typedef CHttpClientThread* LPCHttpClientThread; + +class CHttpDaemon : public CServerSocket { +public: + CHttpDaemon(); + virtual ~CHttpDaemon(); + HTTPdState GetState() const; + virtual BOOL Start(); + virtual BOOL Stop(); + virtual LPCServerClientSocket OnGetSocket(LPCServerSocket lpServerSocket); + virtual LPCServerClientThread OnGetThread(LPCServerClientSocket Socket); + virtual void OnAccept(const LPCServerClientThread lpThread); +private: + HTTPdState State; +}; +typedef CHttpDaemon* LPCHttpDaemon; + +class CHttpDaemonThread : public CThread { +public: + CHttpDaemonThread() {}; + virtual void Execute(); +private: + CHttpDaemon *Daemon; +}; +typedef CHttpDaemonThread* LPCHttpDaemonThread; + +#endif /* __HTTPD_H */ diff --git a/apps/utils/net/roshttpd/include/iterator.h b/apps/utils/net/roshttpd/include/iterator.h new file mode 100644 index 0000000..a7aa66f --- /dev/null +++ b/apps/utils/net/roshttpd/include/iterator.h @@ -0,0 +1,20 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/iterator.h + */ +#ifndef __ITERATOR_H +#define __ITERATOR_H + +#include + +template +class CIterator { +public: + virtual VOID First() = 0; + virtual VOID Next() = 0; + virtual BOOL IsDone() const = 0; + virtual Item CurrentItem() const = 0; +}; + +#endif /* __ITERATOR_H */ diff --git a/apps/utils/net/roshttpd/include/list.h b/apps/utils/net/roshttpd/include/list.h new file mode 100644 index 0000000..5f261f9 --- /dev/null +++ b/apps/utils/net/roshttpd/include/list.h @@ -0,0 +1,233 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/list.h + */ +#ifndef __LIST_H +#define __LIST_H + +#include +#include + +class CListNode { +public: + CListNode(); + CListNode(VOID *element, CListNode *next, CListNode *prev); + ~CListNode() {}; + void* operator new(/*size_t s*/ UINT s); + VOID operator delete(void* p); + + VOID SetElement(PVOID element); + VOID SetNext(CListNode *next); + VOID SetPrev(CListNode *prev); + PVOID GetElement(); + CListNode *GetNext(); + CListNode *GetPrev(); +private: + PVOID Element; + CListNode *Next; + CListNode *Prev; + static HANDLE hHeap; + static INT nRef; +}; + +template class CList { +public: + //CList(CList&); + CList(); + ~CList(); + CList& operator=(CList&); + + CIterator *CreateIterator() const; + LONG Count() const; + Item& Get(const LONG index) const; + // Can throw bad_alloc + VOID Insert(Item& element); + VOID Remove(Item& element); + VOID RemoveAll(); + CListNode *GetHeader() const; + CListNode *GetTrailer() const; +private: + CListNode *Search(Item& element) const; + LONG NodeCount; + CListNode *Header; + CListNode *Trailer; +}; + +template class CListIterator : public CIterator { +public: + CListIterator(const CList *list); + virtual VOID First(); + virtual VOID Next(); + virtual BOOL IsDone() const; + virtual Item CurrentItem() const; +private: + const CList *List; + CListNode *Current; +}; + +// ****************************** CList ****************************** + +// Default constructor +template +CList::CList() +{ + // Create dummy nodes + Trailer = new CListNode; + Header = new CListNode; + Header->SetNext(Trailer); + Trailer->SetPrev(Header); +} + +// Default destructor +template +CList::~CList() +{ + RemoveAll(); + delete Trailer; + delete Header; +} + +// Create an iterator for the list +template +CIterator *CList::CreateIterator() const +{ + return new CListIterator((CList *) this); +} + +// Return number of elements in list +template +LONG CList::Count() const +{ + return NodeCount; +} + +// Return element at index +template +Item& CList::Get(const LONG index) const +{ + CListNode *node; + + if ((index < 0) || (index >= NodeCount)) + return NULL; + + node = Header; + for (i = 0; i <= index; i++) + node = node->GetNext(); + + return (Item *) node->GetElement(); +} + +// Insert an element into the list +template +VOID CList::Insert(Item& element) +{ + CListNode *node; + + node = new CListNode((PVOID)element, Trailer, Trailer->GetPrev()); + Trailer->GetPrev()->SetNext(node); + Trailer->SetPrev(node); + NodeCount++; +} + +// Remove an element from the list +template +VOID CList::Remove(Item& element) +{ + CListNode *node; + + node = Search(element); + if (node != NULL) { + node->GetPrev()->SetNext(node->GetNext()); + node->GetNext()->SetPrev(node->GetPrev()); + NodeCount--; + delete node; + } +} + +// Remove all elements in list +template +VOID CList::RemoveAll() +{ + CListNode *node; + CListNode *tmp; + + node = Header->GetNext(); + while (node != Trailer) { + tmp = node->GetNext(); + delete node; + node = tmp; + } + Header->SetNext(Trailer); + Trailer->SetPrev(Header); + NodeCount = 0; +} + +// Return header node +template +CListNode *CList::GetHeader() const +{ + return Header; +} + +// Return trailer node +template +CListNode *CList::GetTrailer() const +{ + return Trailer; +} + +// Searches for a node that contains the element. Returns NULL if element is not found +template +CListNode *CList::Search(Item& element) const +{ + CListNode *node; + + node = Header; + while (((node = node->GetNext()) != Trailer) && (node->GetElement() != element)); + if (node != Trailer) + return node; + else + return NULL; +} + + +// ************************** CListIterator ************************** + +// Default constructor +template +CListIterator::CListIterator(const CList *list) : List(list) +{ + First(); +} + +// Go to first element in list +template +VOID CListIterator::First() +{ + Current = List->GetHeader()->GetNext(); +} + +// Go to next element in list +template +VOID CListIterator::Next() +{ + if (!IsDone()) + Current = Current->GetNext(); +} + +// Return FALSE when there are more elements in list and TRUE when there are no more +template +BOOL CListIterator::IsDone() const +{ + return (Current == List->GetTrailer()); +} + +// Return current element +template +Item CListIterator::CurrentItem() const +{ + return IsDone()? NULL : (Item) Current->GetElement(); +} + +#endif /* __LIST_H */ diff --git a/apps/utils/net/roshttpd/include/socket.h b/apps/utils/net/roshttpd/include/socket.h new file mode 100644 index 0000000..af80807 --- /dev/null +++ b/apps/utils/net/roshttpd/include/socket.h @@ -0,0 +1,141 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/socket.h + */ +#ifndef __SOCKET_H +#define __SOCKET_H +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PENDING_CONNECTS 4 // The backlog allowed for listen() + +VOID InitWinsock(); +VOID DeinitWinsock(); + +class CSocket; +class CClientSocket; +class CServerClientSocket; +class CServerClientThread; +class CServerSocket; + +typedef CSocket* LPCSocket; +typedef CClientSocket* LPCClientSocket; +typedef CServerClientSocket* LPCServerClientSocket; +typedef CServerClientThread* LPCServerClientThread; +typedef CServerSocket* LPCServerSocket; + +class ESocket { +public: + ESocket() { Description = NULL; } + ESocket(LPTSTR description) { Description = description; } + LPTSTR what() { return Description; } +protected: + LPTSTR Description; +}; + +class ESocketWinsock : public ESocket { +public: + ESocketWinsock(LPTSTR description) { Description = description; } +}; + +class ESocketDll : public ESocket { +public: + ESocketDll(LPTSTR description) { Description = description; } +}; + +class ESocketOpen : public ESocket { +public: + ESocketOpen(LPTSTR description) { Description = description; } +}; + +class ESocketClose : public ESocket { +public: + ESocketClose(LPTSTR description) { Description = description; } +}; + +class ESocketSend : public ESocket { +public: + ESocketSend(LPTSTR description) { Description = description; } +}; + +class ESocketReceive : public ESocket { +public: + ESocketReceive(LPTSTR description) { Description = description; } +}; + + +class CSocket { +public: + CSocket(); + virtual ~CSocket(); + virtual SOCKET GetSocket(); + virtual VOID SetSocket(SOCKET socket); + virtual SOCKADDR_IN GetSockAddrIn(); + virtual VOID SetSockAddrIn(SOCKADDR_IN sockaddrin); + virtual VOID SetEvents(LONG lEvents); + virtual LONG GetEvents(); + virtual VOID SetPort( UINT nPort) {}; + virtual VOID Open(); + virtual VOID Close(); + virtual INT Transmit( LPSTR lpsBuffer, UINT nLength) { return 0; }; + virtual INT Receive(LPSTR lpsBuffer, UINT nLength) { return 0; }; + virtual INT SendText( LPSTR lpsStr) { return 0; }; +protected: + SOCKET Socket; + SOCKADDR_IN SockAddrIn; + WSAEVENT Event; + UINT Port; + BOOL Active; +private: + LONG Events; +}; + +class CServerClientSocket : public CSocket { +public: + CServerClientSocket() {}; + CServerClientSocket(LPCServerSocket lpServerSocket); + CServerSocket *GetServerSocket(); + virtual INT Transmit( LPSTR lpsBuffer, UINT nLength); + virtual INT Receive(LPSTR lpsBuffer, UINT nLength); + virtual INT SendText( LPSTR lpsText); + virtual VOID MessageLoop(); + virtual VOID OnRead() {}; + //virtual VOID OnWrite() {}; + virtual VOID OnClose() {}; +protected: + LPCServerSocket ServerSocket; +}; + +class CServerClientThread : public CThread { +public: + CServerClientThread() {}; + CServerClientThread(CServerClientSocket *socket); + virtual ~CServerClientThread(); +protected: + CServerClientSocket *ClientSocket; +}; + +class CServerSocket : public CSocket { +public: + CServerSocket(); + virtual ~CServerSocket(); + virtual VOID SetPort( UINT nPort); + virtual VOID Open(); + virtual VOID Close(); + virtual LPCServerClientSocket OnGetSocket(LPCServerSocket lpServerSocket); + virtual LPCServerClientThread OnGetThread(LPCServerClientSocket lpSocket); + virtual VOID OnAccept( LPCServerClientThread lpThread) {}; + virtual VOID MessageLoop(); + VOID InsertClient(LPCServerClientThread lpClient); + VOID RemoveClient(LPCServerClientThread lpClient); +protected: + CList Connections; +}; + +#endif /* __SOCKET_H */ diff --git a/apps/utils/net/roshttpd/include/thread.h b/apps/utils/net/roshttpd/include/thread.h new file mode 100644 index 0000000..0b311d4 --- /dev/null +++ b/apps/utils/net/roshttpd/include/thread.h @@ -0,0 +1,34 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: include/thread.h + */ +#ifndef __THREAD_H +#define __THREAD_H + +#include + +class CThread; + +struct ThreadData { + CThread *ClassPtr; + HANDLE hFinished; +}; + +class CThread { +public: + CThread(); + virtual ~CThread(); + BOOL PostMessage(UINT Msg, WPARAM wParam, LPARAM lParam); + virtual void Execute(); + virtual void Terminate(); + BOOL Terminated(); +protected: + BOOL bTerminated; + DWORD dwThreadId; + HANDLE hThread; + ThreadData Data; +}; +typedef CThread *LPCThread; + +#endif /* __THREAD_H */ diff --git a/apps/utils/net/roshttpd/makefile b/apps/utils/net/roshttpd/makefile new file mode 100644 index 0000000..6cc64e2 --- /dev/null +++ b/apps/utils/net/roshttpd/makefile @@ -0,0 +1,29 @@ +# $Id$ + +PATH_TO_TOP = ../../../.. + +TARGET_PATH = common + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = roshttpd + +TARGET_CPPFLAGS = -I./include -DUNICODE -D_UNICODE -DDBG + +TARGET_SDKLIBS = kernel32.a ws2_32.a user32.a + +MAIN_OBJECTS = roshttpd.o config.o error.o http.o httpd.o + +COMMON_OBJECTS = common/list.o common/socket.o common/thread.o + +TARGET_OBJECTS = $(MAIN_OBJECTS) $(COMMON_OBJECTS) + +TARGET_CLEAN = common/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/utils/net/roshttpd/roshttpd.cpp b/apps/utils/net/roshttpd/roshttpd.cpp new file mode 100644 index 0000000..89af9bf --- /dev/null +++ b/apps/utils/net/roshttpd/roshttpd.cpp @@ -0,0 +1,66 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS HTTP Daemon + * FILE: roshttpd.cpp + * PURPOSE: Main program + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09/2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + + +VOID Run() +{ + InitWinsock(); + + pDaemonThread = NULL; + pConfiguration = NULL; + + try { + // Create configuration object + pConfiguration = new CConfig; + pConfiguration->Default(); + + // Create daemon object + pDaemonThread = new CHttpDaemonThread; + + MSG Msg; + BOOL bQuit = FALSE; + while ((!bQuit) && (!pDaemonThread->Terminated())) { + bQuit = PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE); + if (!bQuit) + DispatchMessage(&Msg); + } + + delete pDaemonThread; + + if (pConfiguration != NULL) + delete pConfiguration; + } catch (bad_alloc e) { + if (pConfiguration != NULL) + delete pConfiguration; + ReportErrorStr(TS("Insufficient resources.")); + } + + DeinitWinsock(); +} + +/* Program entry point */ +int main(int argc, char* argv[]) +{ + printf("ReactOS HTTP Daemon\n"); + printf("Type Control-C to stop.\n"); + + Run(); + + printf("Daemon stopped.\n"); +} diff --git a/apps/utils/net/telnet/Makefile b/apps/utils/net/telnet/Makefile new file mode 100644 index 0000000..729b9ae --- /dev/null +++ b/apps/utils/net/telnet/Makefile @@ -0,0 +1,26 @@ +# $Id$ + +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = telnet + +TARGET_SDKLIBS = kernel32.a ws2_32.a + +TARGET_OBJECTS = \ + ansi.o \ + console.o \ + helpsock.o \ + main.o \ + nvt.o \ + telnet.o \ + vm.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/utils/net/telnet/ansi.cpp b/apps/utils/net/telnet/ansi.cpp new file mode 100644 index 0000000..7cc5e9e --- /dev/null +++ b/apps/utils/net/telnet/ansi.cpp @@ -0,0 +1,307 @@ +/* $Id$ + * + * FILE : ansi.cpp + * AUTHOR : unknown (sources found on www.telnet.org) + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea Modified to compile under 0.0.16 src tree + */ +#include +#include + +#include "telnet.h" + +// Need to implement a Keymapper. +// here are some example key maps + +// vt100 f1 - \eOP +// vt100 f2 - \eOQ + +// ansi f5 - \e[17~ +// f6 - \e[18~ +// f7 - \e[20~ +// f10- \e[[V + +enum _ansi_state +{ + as_normal, + as_esc, + as_esc1 +}; + +//SetConsoleMode + +/////////////////////////////////////////////////////////////////////////////// +// SET SCREEN ATTRIBUTE +/* +ESC [ Ps..Ps m Ps refers to selective parameter. Multiple parameters are + separated by the semicolon character (073 octal). The param- + eters are executed in order and have the following meaning: + + 0 or none All attributes off + 1 Bold on + 4 Underscore on + 5 Blink on + 7 Reverse video on + + 3x set foreground color to x + nx set background color to x + + Any other parameters are ignored. +*/ +static int sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + +void ansi_set_screen_attribute(char* buffer) +{ + while(*buffer) + { + switch(*buffer++) + { + case '0': //Normal + sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + break; + case '1': //Hign Intensity + sa |= FOREGROUND_INTENSITY; + break; + case '4': //Underscore + break; + case '5': //Blink. + sa |= BACKGROUND_INTENSITY; + break; + case '7': + sa = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; + break; + case '8': + sa = 0; + break; + case '3': + sa = sa & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY) | + (*buffer & 1)?FOREGROUND_RED:0 | + (*buffer & 2)?FOREGROUND_GREEN:0 | + (*buffer & 4)?FOREGROUND_BLUE:0; + if(*buffer) + buffer++; + break; + case '6': + sa = sa & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY) | + (*buffer & 1)?BACKGROUND_RED:0 | + (*buffer & 2)?BACKGROUND_GREEN:0 | + (*buffer & 4)?BACKGROUND_BLUE:0; + if(*buffer) + buffer++; + break; + } + if(*buffer && *buffer == ';') + buffer++; + } + SetConsoleTextAttribute(StandardOutput,sa); +} + +/////////////////////////////////////////////////////////////////////////////// +// ERASE LINE +/* +ESC [ 0K Same *default* +ESC [ 1K Erase from beginning of line to cursor +ESC [ 2K Erase line containing cursor +*/ + +void ansi_erase_line(char* buffer) +{ + int act = 0; + while(*buffer) + { + act = (*buffer++) - '0'; + } + + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(StandardOutput,&csbi); + + COORD pos; + DWORD n; + + switch(act) + { + case 0: //erase to end of line + pos.X = csbi.dwCursorPosition.X; + pos.Y = csbi.dwCursorPosition.Y; + n = csbi.dwSize.X - csbi.dwCursorPosition.X; + break; + case 1: //erase from beginning + pos.X = 0; + pos.Y = csbi.dwCursorPosition.Y; + n = csbi.dwCursorPosition.X; + break; + case 2: // erase whole line + pos.X = 0; + pos.Y = csbi.dwCursorPosition.Y; + n = csbi.dwSize.X; + break; + } + + DWORD w; + FillConsoleOutputCharacter(StandardOutput,' ',n,pos,&w); +} + + +/////////////////////////////////////////////////////////////////////////////// +// SET POSITION +// ESC [ Pl;PcH Direct cursor addressing, where Pl is line#, Pc is column# +// default = (1,1) + +void ansi_set_position(char* buffer) +{ + COORD pos = {0,0}; + + // Grab line + while(*buffer && *buffer != ';') + pos.Y = pos.Y*10 + *buffer++ - '0'; + + if(*buffer) + buffer++; + + // Grab y + while(*buffer && *buffer != ';') + pos.X = pos.X*10 + *buffer++ - '0'; + + (pos.X)?pos.X--:0; + (pos.Y)?pos.Y--:0; + + SetConsoleCursorPosition(StandardOutput,pos); + +} + +/////////////////////////////////////////////////////////////////////////////// +// ERASE SCREEN +/* +ESC [ 0J Same *default* +ESC [ 2J Erase entire screen +*/ + +void ansi_erase_screen(char* buffer) +{ + int act = 0; + while(*buffer) + { + act = (*buffer++) - '0'; + } + + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(StandardOutput,&csbi); + + COORD pos; + DWORD n; + + switch(act) + { + case 0: + pos.X = csbi.dwCursorPosition.X; + pos.Y = csbi.dwCursorPosition.Y; + n = csbi.dwSize.X*csbi.dwSize.Y; + break; + case 2: + pos.X = 0; + pos.Y = 0; + n = csbi.dwSize.X*csbi.dwSize.Y; + break; + } + + DWORD w; + FillConsoleOutputCharacter(StandardOutput,' ',n,pos,&w); + SetConsoleCursorPosition(StandardOutput,pos); +} + +/////////////////////////////////////////////////////////////////////////////// +// MOVE UP +// ESC [ Pn A Cursor up Pn lines (Pn default=1) + +void ansi_move_up(char* buffer) +{ + int cnt = *buffer?0:1; + while(*buffer) + { + cnt = cnt*10 + (*buffer++) - '0'; + } + + COORD pos; + + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(StandardOutput,&csbi); + + pos.X = csbi.dwCursorPosition.X; + pos.Y = ((csbi.dwCursorPosition.Y-cnt)>=0)?(csbi.dwCursorPosition.Y-cnt):0; + + SetConsoleCursorPosition(StandardOutput,pos); +} + +/////////////////////////////////////////////////////////////////////////////// +char codebuf[256]; +unsigned char codeptr; + +#define NUM_CODEC 6 + +typedef void (*LPCODEPROC)(char*); + +struct +{ + unsigned char cmd; + LPCODEPROC proc; +} codec[NUM_CODEC] = { + {'m',ansi_set_screen_attribute}, + {'H',ansi_set_position}, + {'K',ansi_erase_line}, + {'J',ansi_erase_screen}, + {'A',ansi_move_up}, + {0,0} +}; + +void ansi(SOCKET server,unsigned char data) +{ + static _ansi_state state = as_normal; + DWORD z; + switch( state) + { + case as_normal: + switch(data) + { + case 0: //eat null codes. + break; + case 27: //ANSI esc. + state = as_esc; + break; + default: //Send all else to the console. + WriteConsole(StandardOutput,&data,1,&z,NULL); + break; + } + break; + case as_esc: + state = as_esc1; + codeptr=0; + codebuf[codeptr] = 0; + break; + case as_esc1: + if(data > 64) + { + int i = 0; + codebuf[codeptr] = 0; + for(i=0; codec[i].cmd && codec[i].cmd != data; i++); + if(codec[i].proc) + codec[i].proc(codebuf); +#ifdef _DEBUG + else + { + char buf[256]; + wsprintf(buf,"Unknown Ansi code:'%c' (%s)\n",data,codebuf); + OutputDebugString(buf); + } +#endif + state = as_normal; + } + else + codebuf[codeptr++] = data; + break; + } +} + +/* EOF */ diff --git a/apps/utils/net/telnet/console.cpp b/apps/utils/net/telnet/console.cpp new file mode 100644 index 0000000..377ef1a --- /dev/null +++ b/apps/utils/net/telnet/console.cpp @@ -0,0 +1,43 @@ +/* $Id$ + * + * FILE : console.cpp + * AUTHOR : E.Aliberti + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea added to group console-related methods + */ +#include + +const char * title = "telnet - "; + +// Set console's title +void console_title_connecting ( + char const* pszHostName, + const int nPort + ) +{ + char t[256]; + wsprintf(t,"%sconnecting to %s:%i", title, pszHostName, nPort); + SetConsoleTitle(t); +} + +void console_title_connected ( + char const* pszHostName, + const int nPort + ) +{ + char t[256]; + wsprintf(t,"%sconnected to %s:%i", title, pszHostName, nPort); + SetConsoleTitle(t); +} + +void console_title_not_connected (void) +{ + char t[256]; + wsprintf(t,"%snot connected", title); + SetConsoleTitle(t); +} + +/* EOF */ diff --git a/apps/utils/net/telnet/console.h b/apps/utils/net/telnet/console.h new file mode 100644 index 0000000..0846f38 --- /dev/null +++ b/apps/utils/net/telnet/console.h @@ -0,0 +1,12 @@ +#ifndef _APPS_NET_TELNET_CONSOLE_H +#define _APPS_NET_TELNET_CONSOLE_H +void console_title_connecting ( + char const* pszHostName, + const int nPort + ); +void console_title_connected ( + char const* pszHostName, + const int nPort + ); +void console_title_not_connected (void); +#endif /* _APPS_NET_TELNET_CONSOLE_H */ diff --git a/apps/utils/net/telnet/helpsock.cpp b/apps/utils/net/telnet/helpsock.cpp new file mode 100644 index 0000000..72939b3 --- /dev/null +++ b/apps/utils/net/telnet/helpsock.cpp @@ -0,0 +1,40 @@ +/* $Id$ + * + * FILE : helpsock.cpp + * AUTHOR : unknown (sources found on www.telnet.org) + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea Modified to compile under 0.0.16 src tree + */ +#include +#include +#include + +#include "telnet.h" + +char const* sockmsg(int ecode) +{ + switch(ecode) + { +// programming errors +// (should never occour in release code?) + case WSASYSNOTREADY: return "tcp/ip network not ready"; + case WSAEINVAL: return "invalid winsock version"; + case WSAVERNOTSUPPORTED: return "wrong winsock version"; + case WSANOTINITIALISED: return "winsock not initialized"; + case WSAEINTR: "The call was canceled"; + case WSAEINPROGRESS: "A blocking winsock operation is in progress"; + default: return "unknown winsock error"; +// general TCP problems + case WSAENETDOWN: return "winsock has detected that the network subsystem has failed"; +// GetXbyY related errors: + case WSAHOST_NOT_FOUND: return "Authoritative Answer Host not found"; + case WSATRY_AGAIN: return "Non-Authoritative Host not found, or SERVERFAIL"; + case WSANO_RECOVERY: "Nonrecoverable errors: FORMERR, REFUSED, NOTIMP"; + case WSANO_DATA: "Valid name, no data record of requested type"; + } +} + +/* EOF */ diff --git a/apps/utils/net/telnet/main.cpp b/apps/utils/net/telnet/main.cpp new file mode 100644 index 0000000..3ecffbf --- /dev/null +++ b/apps/utils/net/telnet/main.cpp @@ -0,0 +1,180 @@ +/* $Id$ + * + * FILE : main.cpp + * AUTHOR : unknown (sources found on www.telnet.org) + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea Modified to compile under 0.0.16 src tree + * 2001-02-27 ea If run with no argument, it asks for a hostname. + */ +/////////////////////////////////////////////////////////////////////////////// +// +// File: +// main.cpp +// +// Purpose: +// This file provdes the main entry point for the project, and all the +// global scope support routines. +// +// Notes: +// This file expects to be linked without the C-Runtime. If compiling, +// please force the entry point symbol to be "main", and do not link in +// the default librarys. +// This means that no c-runtime functions can be used anywhere in the +// project. I expect this will also exclude any MFC based additions. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "telnet.h" + +/////////////////////////////////////////////////////////////////////////////// + +// +// Our simple replacement for the c-runtime includes getting the StandardInput, +// StandardOutput & StandardError handles, and providing new and delete operators, that work +// with the win32 heap functions. +// + +// +// standard handles needed for CRT emulation +// +HANDLE hHeap; +HANDLE StandardInput; +HANDLE StandardOutput; +HANDLE StandardError; + +// +// new will use the win32 heap functions. +// +void* operator new(unsigned int nSize) +{ + return HeapAlloc(hHeap,0,nSize); +} + +// +// delete operator provides all memory de-allocation. +// HeapFree doesn't accept NULL. +// +void operator delete(void* pMem) +{ + if(pMem) HeapFree(hHeap,0,pMem); +} + + + +void err(char const* s, ...) +{ + char buf [1024]; + DWORD nout; + + wvsprintf (buf, s, (char*)(s + sizeof(int))); + WriteFile (StandardError,"Error: ", 7, & nout, NULL); + WriteFile (StandardError, buf, lstrlen(buf), & nout, NULL); + WriteFile (StandardError, "\r\n\r\n", 4, & nout, NULL); +#ifdef _DEBUG + OutputDebugString(buf); + OutputDebugString("\n"); +#endif + ExitProcess (ERROR_SUCCESS); +} + + +int main(int argc, char * argv[]) +{ + WSADATA wd; + int errn; + char name [256] = {'\0'}; + short port = IPPORT_TELNET; /* default tcp port */ + + /////////////////////////////////////// + // CRT emulation init + // Get the IO handles + StandardInput = GetStdHandle(STD_INPUT_HANDLE); + StandardOutput = GetStdHandle(STD_OUTPUT_HANDLE); + StandardError = GetStdHandle(STD_ERROR_HANDLE); + + // Get the heap + hHeap = GetProcessHeap(); + + // Explicitly force the console into a good mode (actually all we are doing is turning + // mouse input off. + SetConsoleMode ( + StandardInput, + (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT) + ); + + /////////////////////////////////////// + // Init winsock + + if (errn = WSAStartup (0x0101, & wd)) + { + err(sockmsg(errn)); + } + + /* hostname */ + if (1 < argc) + { + lstrcpy (name, argv [1]); + } + /* + * Default port is IPPORT_TELNET. + * User may hand one. + */ + if (3 == argc) + { + port = atoi (argv[2]); + if (port <= 0) + { + struct servent * service = NULL; + + service = getservbyname (argv[2], "tcp"); + if (NULL == service) + { + err("Invalid service name specified"); + } + port = service->s_port; + } + else + { + err("Invalid port specified"); + } + } + /* Too many arguments */ + if (3 < argc) + { + err("Usage: telnet []"); + } + /* No argument */ + if (1 == argc) + { + DWORD Count; + char *c; + + WriteFile (StandardError,"host: ", 6, & Count, NULL); + ReadFile (StandardInput, name, sizeof name, & Count, NULL); + c = name; + while (*c > ' ') ++ c; + *c = '\0'; + } + + // guess what this does. + telnet (name, port); + + //Bye bye... + WSACleanup (); + + // Exit process terminates any waiting threads. + // (Its the CRT that makes a process close when the main thread exits. + // The WinAPI will leave the process as is for as long as it has a + // thread any thread. + ExitProcess (EXIT_SUCCESS); +} + +/* EOF */ diff --git a/apps/utils/net/telnet/nvt.cpp b/apps/utils/net/telnet/nvt.cpp new file mode 100644 index 0000000..ce8d92b --- /dev/null +++ b/apps/utils/net/telnet/nvt.cpp @@ -0,0 +1,296 @@ +/* $Id$ + * + * FILE : nvt.cpp + * AUTHOR : unknown (sources found on www.telnet.org) + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea Modified to compile under 0.0.16 src tree + */ +/////////////////////////////////////////////////////////////////////////////// +// +// file: nvt.cpp +// +// purpose: Provides the "bare bones" telnet "Network Virtual Terminal" +// that is our default. We only se a more capable terminal, if +// properly requested via the telnet option. +// +// refrence: The following excerpt from rfc 854 +// +/////////////////////////////////////////////////////////////////////////////// +/* +THE NETWORK VIRTUAL TERMINAL + + The Network Virtual Terminal (NVT) is a bi-directional character + device. The NVT has a printer and a keyboard. The printer responds + to incoming data and the keyboard produces outgoing data which is + sent over the TELNET connection and, if "echoes" are desired, to the + NVT's printer as well. "Echoes" will not be expected to traverse the + network (although options exist to enable a "remote" echoing mode of + operation, no host is required to implement this option). The code + set is seven-bit USASCII in an eight-bit field, except as modified + herein. Any code conversion and timing considerations are local + problems and do not affect the NVT. + + TRANSMISSION OF DATA + + Although a TELNET connection through the network is intrinsically + full duplex, the NVT is to be viewed as a half-duplex device + operating in a line-buffered mode. That is, unless and until + options are negotiated to the contrary, the following default + conditions pertain to the transmission of data over the TELNET + connection: + + 1) Insofar as the availability of local buffer space permits, + data should be accumulated in the host where it is generated + until a complete line of data is ready for transmission, or + until some locally-defined explicit signal to transmit occurs. + This signal could be generated either by a process or by a + human user. + + The motivation for this rule is the high cost, to some hosts, + of processing network input interrupts, coupled with the + default NVT specification that "echoes" do not traverse the + network. Thus, it is reasonable to buffer some amount of data + at its source. Many systems take some processing action at the + end of each input line (even line printers or card punches + frequently tend to work this way), so the transmission should + be triggered at the end of a line. On the other hand, a user + or process may sometimes find it necessary or desirable to + provide data which does not terminate at the end of a line; + therefore implementers are cautioned to provide methods of + locally signaling that all buffered data should be transmitted + immediately. + + 2) When a process has completed sending data to an NVT printer + and has no queued input from the NVT keyboard for further + processing (i.e., when a process at one end of a TELNET + connection cannot proceed without input from the other end), + the process must transmit the TELNET Go Ahead (GA) command. + + This rule is not intended to require that the TELNET GA command + be sent from a terminal at the end of each line, since server + hosts do not normally require a special signal (in addition to + end-of-line or other locally-defined characters) in order to + commence processing. Rather, the TELNET GA is designed to help + a user's local host operate a physically half duplex terminal + which has a "lockable" keyboard such as the IBM 2741. A + description of this type of terminal may help to explain the + proper use of the GA command. + + The terminal-computer connection is always under control of + either the user or the computer. Neither can unilaterally + seize control from the other; rather the controlling end must + relinguish its control explicitly. At the terminal end, the + hardware is constructed so as to relinquish control each time + that a "line" is terminated (i.e., when the "New Line" key is + typed by the user). When this occurs, the attached (local) + computer processes the input data, decides if output should be + generated, and if not returns control to the terminal. If + output should be generated, control is retained by the computer + until all output has been transmitted. + + The difficulties of using this type of terminal through the + network should be obvious. The "local" computer is no longer + able to decide whether to retain control after seeing an + end-of-line signal or not; this decision can only be made by + the "remote" computer which is processing the data. Therefore, + the TELNET GA command provides a mechanism whereby the "remote" + (server) computer can signal the "local" (user) computer that + it is time to pass control to the user of the terminal. It + should be transmitted at those times, and only at those times, + when the user should be given control of the terminal. Note + that premature transmission of the GA command may result in the + blocking of output, since the user is likely to assume that the + transmitting system has paused, and therefore he will fail to + turn the line around manually. + + The foregoing, of course, does not apply to the user-to-server + direction of communication. In this direction, GAs may be sent at + any time, but need not ever be sent. Also, if the TELNET + connection is being used for process-to-process communication, GAs + need not be sent in either direction. Finally, for + terminal-to-terminal communication, GAs may be required in + neither, one, or both directions. If a host plans to support + terminal-to-terminal communication it is suggested that the host + provide the user with a means of manually signaling that it is + time for a GA to be sent over the TELNET connection; this, + however, is not a requirement on the implementer of a TELNET + process. + + Note that the symmetry of the TELNET model requires that there is + an NVT at each end of the TELNET connection, at least + conceptually. +*//* + + THE NVT PRINTER AND KEYBOARD + + The NVT printer has an unspecified carriage width and page length + and can produce representations of all 95 USASCII graphics (codes + 32 through 126). Of the 33 USASCII control codes (0 through 31 + and 127), and the 128 uncovered codes (128 through 255), the + following have specified meaning to the NVT printer: + + NAME CODE MEANING + + NULL (NUL) 0 No Operation + Line Feed (LF) 10 Moves the printer to the + next print line, keeping the + same horizontal position. + Carriage Return (CR) 13 Moves the printer to the left + margin of the current line. + + In addition, the following codes shall have defined, but not + required, effects on the NVT printer. Neither end of a TELNET + connection may assume that the other party will take, or will + have taken, any particular action upon receipt or transmission + of these: + + BELL (BEL) 7 Produces an audible or + visible signal (which does + NOT move the print head). + Back Space (BS) 8 Moves the print head one + character position towards + the left margin. + Horizontal Tab (HT) 9 Moves the printer to the + next horizontal tab stop. + It remains unspecified how + either party determines or + establishes where such tab + stops are located. + Vertical Tab (VT) 11 Moves the printer to the + next vertical tab stop. It + remains unspecified how + either party determines or + establishes where such tab + stops are located. + Form Feed (FF) 12 Moves the printer to the top + of the next page, keeping + the same horizontal position. + + All remaining codes do not cause the NVT printer to take any + action. + + The sequence "CR LF", as defined, will cause the NVT to be + positioned at the left margin of the next print line (as would, + for example, the sequence "LF CR"). However, many systems and + terminals do not treat CR and LF independently, and will have to + go to some effort to simulate their effect. (For example, some + terminals do not have a CR independent of the LF, but on such + terminals it may be possible to simulate a CR by backspacing.) + Therefore, the sequence "CR LF" must be treated as a single "new + line" character and used whenever their combined action is + intended; the sequence "CR NUL" must be used where a carriage + return alone is actually desired; and the CR character must be + avoided in other contexts. This rule gives assurance to systems + which must decide whether to perform a "new line" function or a + multiple-backspace that the TELNET stream contains a character + following a CR that will allow a rational decision. + + Note that "CR LF" or "CR NUL" is required in both directions + (in the default ASCII mode), to preserve the symmetry of the + NVT model. Even though it may be known in some situations + (e.g., with remote echo and suppress go ahead options in + effect) that characters are not being sent to an actual + printer, nonetheless, for the sake of consistency, the protocol + requires that a NUL be inserted following a CR not followed by + a LF in the data stream. The converse of this is that a NUL + received in the data stream after a CR (in the absence of + options negotiations which explicitly specify otherwise) should + be stripped out prior to applying the NVT to local character + set mapping. + + The NVT keyboard has keys, or key combinations, or key sequences, + for generating all 128 USASCII codes. Note that although many + have no effect on the NVT printer, the NVT keyboard is capable of + generating them. + + In addition to these codes, the NVT keyboard shall be capable of + generating the following additional codes which, except as noted, + have defined, but not reguired, meanings. The actual code + assignments for these "characters" are in the TELNET Command + section, because they are viewed as being, in some sense, generic + and should be available even when the data stream is interpreted + as being some other character set. + + Synch + + This key allows the user to clear his data path to the other + party. The activation of this key causes a DM (see command + section) to be sent in the data stream and a TCP Urgent + notification is associated with it. The pair DM-Urgent is to + have required meaning as defined previously. + + Break (BRK) + + This code is provided because it is a signal outside the + USASCII set which is currently given local meaning within many + systems. It is intended to indicate that the Break Key or the + Attention Key was hit. Note, however, that this is intended to + provide a 129th code for systems which require it, not as a + synonym for the IP standard representation. + + Interrupt Process (IP) + + Suspend, interrupt, abort or terminate the process to which the + NVT is connected. Also, part of the out-of-band signal for + other protocols which use TELNET. + + Abort Output (AO) + + Allow the current process to (appear to) run to completion, but + do not send its output to the user. Also, send a Synch to the + user. + + Are You There (AYT) + + Send back to the NVT some visible (i.e., printable) evidence + that the AYT was received. + + Erase Character (EC) + + The recipient should delete the last preceding undeleted + character or "print position" from the data stream. + + Erase Line (EL) + + The recipient should delete characters from the data stream + back to, but not including, the last "CR LF" sequence sent over + the TELNET connection. + + The spirit of these "extra" keys, and also the printer format + effectors, is that they should represent a natural extension of + the mapping that already must be done from "NVT" into "local". + Just as the NVT data byte 68 (104 octal) should be mapped into + whatever the local code for "uppercase D" is, so the EC character + should be mapped into whatever the local "Erase Character" + function is. Further, just as the mapping for 124 (174 octal) is + somewhat arbitrary in an environment that has no "vertical bar" + character, the EL character may have a somewhat arbitrary mapping + (or none at all) if there is no local "Erase Line" facility. + Similarly for format effectors: if the terminal actually does + have a "Vertical Tab", then the mapping for VT is obvious, and + only when the terminal does not have a vertical tab should the + +*/ + +#include +#include + +#include "telnet.h" + +void nvt(SOCKET server,unsigned char data) +{ + DWORD z; + switch(data) + { + case 0: //eat null codes. + break; + default: //Send all else to the console. + WriteConsole(StandardOutput, & data, 1, & z, NULL); + break; + } +} + +/* EOF */ diff --git a/apps/utils/net/telnet/telnet.cpp b/apps/utils/net/telnet/telnet.cpp new file mode 100644 index 0000000..7f6b846 --- /dev/null +++ b/apps/utils/net/telnet/telnet.cpp @@ -0,0 +1,130 @@ +/* $Id$ + * + * FILE : telnet.cpp + * AUTHOR : unknown (sources found on www.telnet.org) + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea Modified to compile under 0.0.16 src tree + */ +#include +#include + +#include "telnet.h" +#include "console.h" + + +// +// sock_loop is the thread dedicatd to reading socket input. +// It waits for data from the socket, and then gives it one byte at a time +// to the telnet vm to process. +// + +DWORD sock_loop(SOCKET server) +{ + char buf[256]; + unsigned long read; + char* scan; + + while( (read = recv(server,buf,sizeof(buf),0)) && read != SOCKET_ERROR ) + { + scan = buf; + while(read--) + vm(server,*scan++); + } + int x = WSAGetLastError(); + return 0; +} + +DWORD input_loop(SOCKET server) +{ + char buf[256]; + DWORD read; + + do + { + WaitForSingleObject(StandardInput, INFINITE); + ReadFile(StandardInput, buf, sizeof buf, & read, NULL); + } + while(SOCKET_ERROR != send(server, buf, read, 0)); + + return 0; + +} + +void telnet(SOCKET server) +{ + DWORD dwThreadIdsock; + DWORD dwThreadIdinput; + HANDLE threads[2]; + + + threads[0] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) sock_loop, /* thread function */ + (LPVOID)server, /* argument to thread function */ + 0, /* use default creation flags */ + &dwThreadIdsock); /* returns the thread identifier */ + + //wait for the other thread to complete any setup negotiation... + //Sleep(500); //- this is not the problem - its just bloody stuffing up! + + threads[1] = CreateThread( + NULL, /* no security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE) input_loop, /* thread function */ + (LPVOID)server, /* argument to thread function */ + 0, /* use default creation flags */ + &dwThreadIdinput); /* returns the thread identifier */ + + + WaitForMultipleObjects(2,threads,FALSE,INFINITE); +} + + +// +// connect to the hostname,port +// +void telnet( + char const* pszHostName, + const short nPort) +{ + unsigned long ip; + if((*pszHostName <= '9') && (*pszHostName >= '0')) + { + if((ip = inet_addr(pszHostName)) == INADDR_NONE) + err("invalid host IP address given"); + } + else + { + hostent* ent = gethostbyname(pszHostName); + if(!ent) + err(sockmsg(WSAGetLastError())); + ip = *(unsigned long*)(ent->h_addr); + } + + sockaddr_in name; + name.sin_family = AF_INET; + name.sin_port = htons(nPort); + name.sin_addr = *(in_addr*)&ip; + + console_title_connecting (pszHostName, nPort); + + SOCKET server; + + if((server = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET) + err(sockmsg(WSAGetLastError())); + + if(SOCKET_ERROR == connect(server,(sockaddr*)&name,sizeof(sockaddr))) + err(sockmsg(WSAGetLastError())); + + console_title_connected (pszHostName, nPort); + + telnet(server); + + closesocket(server); +} + +/* EOF */ diff --git a/apps/utils/net/telnet/telnet.h b/apps/utils/net/telnet/telnet.h new file mode 100644 index 0000000..c84d9c4 --- /dev/null +++ b/apps/utils/net/telnet/telnet.h @@ -0,0 +1,24 @@ +#ifndef _APPS_NET_TELNET_H +#define _APPS_NET_TELNET_H +//Global Handles +extern HANDLE StandardInput; +extern HANDLE StandardOutput; +extern HANDLE StandardError; + +extern char const* sockmsg(int ecode); +extern void err(char const* s,...); + +extern void telnet(char const* pszHostName,const short nPort); +extern void vm(SOCKET,unsigned char); + +// terminal handlers: +void ansi(SOCKET server,unsigned char data); +void nvt(SOCKET server,unsigned char data); + +// helpsock +char const* sockmsg(int ecode); + +// command shell +int shell(char const* pszHostName,const int nPort); + +#endif /* ndef _APPS_NET_TELNET_H */ diff --git a/apps/utils/net/telnet/telnet.rc b/apps/utils/net/telnet/telnet.rc new file mode 100644 index 0000000..420454f --- /dev/null +++ b/apps/utils/net/telnet/telnet.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Telnet Win32 Client\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "telnet\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalCopyright", "Anonymous sources found at http://www.telnet.org/\0" + VALUE "OriginalFilename", "telnet.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/apps/utils/net/telnet/vm.cpp b/apps/utils/net/telnet/vm.cpp new file mode 100644 index 0000000..3a0d6ca --- /dev/null +++ b/apps/utils/net/telnet/vm.cpp @@ -0,0 +1,424 @@ +/* $Id$ + * + * FILE : vm.cpp + * AUTHOR : unknown (sources found on www.telnet.org) + * PROJECT : ReactOS Operating System + * DESCRIPTION: telnet client for the W32 subsystem + * DATE : 2001-01-21 + * REVISIONS + * 2001-02-21 ea Modified to compile under 0.0.16 src tree + */ +#include +#include + +#include "telnet.h" + +// NAME CODE MEANING +// NVT codes +#define NUL 0 // No Operation +#define BEL 7 // BELL +#define BS 8 // Back Space +#define HT 9 // Horizontal Tab +#define LF 10 // Line Feed +#define VT 11 // Vertical Tab +#define FF 12 // Form Feed +#define CR 13 // Carriage Return + +// telnet command codes +#define SE 240 // End of subnegotiation parameters. +#define NOP 241 // No operation. +#define DM 242 // Data Mark +#define BRK 243 // Break +#define IP 244 // Interrupt Process +#define AO 245 // Abort output +#define AYT 246 // Are You There +#define EC 247 // Erase character +#define EL 248 // Erase Line +#define GA 249 // Go ahead +#define SB 250 // SuBnegotiate +#define WILL 251 // +#define WONT 252 // +#define DO 253 // +#define DONT 254 // +#define IAC 255 // Interpret As Command + +//Telnet options: +// 0x00 - binary mode +// 0x01 - Local Echo +// 0x03 - Suppress GA (char at a time) +// 0x05 - status +// 0x06 - Timing Mark +// +// do 0x25 - zub? +// +// 0xff - Extended Options List + +enum _option +{ + TOPT_BIN = 0, // Binary Transmission + TOPT_ECHO = 1, // Echo + TOPT_RECN = 2, // Reconnection + TOPT_SUPP = 3, // Suppress Go Ahead + TOPT_APRX = 4, // Approx Message Size Negotiation + TOPT_STAT = 5, // Status + TOPT_TIM = 6, // Timing Mark + TOPT_REM = 7, // Remote Controlled Trans and Echo + TOPT_OLW = 8, // Output Line Width + TOPT_OPS = 9, // Output Page Size + TOPT_OCRD = 10, // Output Carriage-Return Disposition + TOPT_OHT = 11, // Output Horizontal Tabstops + TOPT_OHTD = 12, // Output Horizontal Tab Disposition + TOPT_OFD = 13, // Output Formfeed Disposition + TOPT_OVT = 14, // Output Vertical Tabstops + TOPT_OVTD = 15, // Output Vertical Tab Disposition + TOPT_OLD = 16, // Output Linefeed Disposition + TOPT_EXT = 17, // Extended ASCII + TOPT_LOGO = 18, // Logout + TOPT_BYTE = 19, // Byte Macro + TOPT_DATA = 20, // Data Entry Terminal + TOPT_SUP = 21, // SUPDUP + TOPT_SUPO = 22, // SUPDUP Output + TOPT_SNDL = 23, // Send Location + TOPT_TERM = 24, // Terminal Type + TOPT_EOR = 25, // End of Record + TOPT_TACACS = 26, // TACACS User Identification + TOPT_OM = 27, // Output Marking + TOPT_TLN = 28, // Terminal Location Number + TOPT_3270 = 29, // Telnet 3270 Regime + TOPT_X3 = 30, // X.3 PAD + TOPT_NAWS = 31, // Negotiate About Window Size + TOPT_TS = 32, // Terminal Speed + TOPT_RFC = 33, // Remote Flow Control + TOPT_LINE = 34, // Linemode + TOPT_XDL = 35, // X Display Location + TOPT_ENVIR = 36,// Telnet Environment Option + TOPT_AUTH = 37, // Telnet Authentication Option + TOPT_NENVIR = 39,// Telnet Environment Option + TOPT_EXTOP = 255, // Extended-Options-List + TOPT_ERROR = 256 // Magic number +}; + +// Wanted by linux box: +// 37 - TOPT_AUTH +// 24 - TOPT_TERM + +enum _verb +{ + verb_sb = 250, + verb_will = 251, + verb_wont = 252, + verb_do = 253, + verb_dont = 254 +}; + +enum _state +{ + state_data, //we expect a data byte + state_code, //we expect a code + state_option //we expect an option +}; + +int option_error(_verb,_option,int,SOCKET); + +typedef void(*LPOPTIONPROC)(SOCKET,_verb,_option); +typedef void(*LPDATAPROC)(SOCKET,unsigned char data); + +/////////////////////////////////////////////////////////////////////////////// + +inline void yesreply(SOCKET server, _verb verb,_option option) +{ + unsigned char buf[3]; + buf[0] = IAC; + buf[1] = (verb==verb_do)?WILL:(verb==verb_dont)?WONT:(verb==verb_will)?DO:DONT; + buf[2] = (unsigned char)option; + send(server,(char*)buf,3,0); +} + +inline void noreply(SOCKET server, _verb verb,_option option) +{ + unsigned char buf[3]; + buf[0] = IAC; + buf[1] = (verb==verb_do)?WONT:(verb==verb_dont)?WILL:(verb==verb_will)?DONT:DO; + buf[2] = (unsigned char)option; + send(server,(char*)buf,3,0); +} + +inline void askfor(SOCKET server, _verb verb,_option option) +{ + unsigned char buf[3]; + buf[0] = IAC; + buf[1] = (unsigned char)verb; + buf[2] = (unsigned char)option; + send(server,(char*)buf,3,0); +} + + +void ddww_error(SOCKET server,_verb verb,_option option) +{ +#ifdef _DEBUG + char tmp[256]; + wsprintf(tmp,"Unknown Option Code: %s, %i\n",(verb==verb_do)?"DO":(verb==verb_dont)?"DON'T":(verb==verb_will)?"WILL":"WONT",(int)option); + OutputDebugString(tmp); +#endif + + switch(verb) + { + case verb_will: // server wants to support something + noreply(server,verb,option); // I don't want that. + break; + case verb_wont: // server waants to disable support + return; // don't confirm - already disabled. + case verb_do: // server wants me to support something + noreply(server,verb,option); //I won't do that + break; + case verb_dont: // server wants me to disable something + return; // don't worry, we don't do that anyway (I hope :) + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Option ECHO & SUPPRESS GA +// +// These options are curiously intertwined... +// The Win32 console doesn't support ECHO_INPUT (echo) if +// LINE_INPUT (==GA) isn't set. +// I can't see how to code this negotiation without using +// some form of Lock-Step algorythm +// ie: if("WILL ECHO") +// Send "DO SUPP" +// if("WILL SUPP") +// Send "DO ECHO" +// else +// Send "DONT ECHO" + + +void ddww_echo(SOCKET server,_verb verb, _option option) +{ + DWORD mode; + GetConsoleMode(StandardInput, & mode); // ENABLE_ECHO_INPUT + + int set = !(mode & ENABLE_ECHO_INPUT); + + switch(verb) + { + case verb_will: // server wants to echo stuff + if(set) return; //don't confirm - already set. + SetConsoleMode(StandardInput,mode & (~ENABLE_ECHO_INPUT)); + break; + case verb_wont: // server don't want to echo + if(!set) return; //don't confirm - already unset. + SetConsoleMode(StandardInput,mode | ENABLE_ECHO_INPUT); + break; + case verb_do: // server wants me to loopback + noreply(server,verb,option); + return; + case verb_dont: // server doesn't want me to echo + break; // don't bother to reply - I don't + } + yesreply(server,verb,option); +} + + +void ddww_supp(SOCKET server,_verb verb,_option option) //Suppress GA +{ + DWORD mode; + GetConsoleMode(StandardInput,&mode); // ENABLE_LINE_INPUT + + int set = !(mode & ENABLE_LINE_INPUT); + + switch(verb) + { + case verb_will: // server wants to suppress GA's + if(set) break; //don't confirm - already set. + SetConsoleMode(StandardInput,mode & (~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))); + askfor(server,verb_do,TOPT_SUPP); + askfor(server,verb_will,TOPT_SUPP); + askfor(server,verb_do,TOPT_ECHO); + break; + case verb_wont: // server wants to send GA's + if(!set) break; //don't confirm - already unset. + SetConsoleMode(StandardInput,mode | ENABLE_LINE_INPUT); + askfor(server,verb_dont,TOPT_SUPP); + askfor(server,verb_wont,TOPT_SUPP); + break; + case verb_do: // server wants me to suppress GA's + if(set) break; + askfor(server,verb_do,TOPT_SUPP); + break; + case verb_dont: // server wants me to send GA's + if(!set) break; + askfor(server,verb_dont,TOPT_SUPP); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Option TERMINAL-TYPE + +void ddww_term(SOCKET server,_verb verb,_option option) //Subnegotiate terminal type +{ + switch(verb) + { + case verb_will: + noreply(server,verb,option); // I don't want terminal info + break; + case verb_wont: + //dat be cool - its not going to send. no need to confirm + break; + case verb_do: + yesreply(server,verb,option); //I'll send it when asked + break; + case verb_dont://Ok - I won't + break; + } +} + +// TERMINAL TYPE subnegotation +enum +{ + SB_TERM_IS = 0, + SB_TERM_SEND = 1 +}; + +#define NUM_TERMINALS 2 + +struct +{ + char* name; + LPDATAPROC termproc; + //pre requsites. +} terminal[NUM_TERMINALS] = { + { "NVT", nvt }, + { "ANSI", ansi } +}; + +int term_index = 0; + +void sbproc_term(SOCKET server,unsigned char data) +{ + + if(data == SB_TERM_SEND) + { + if(term_index == NUM_TERMINALS) + term_index = 0; + else + term_index++; + char buf[16]; //pls limit + buf[0] = IAC; + buf[1] = SB; + buf[2] = TOPT_TERM; + buf[3] = SB_TERM_IS; + lstrcpy(&buf[4],terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].name); + int nlen = lstrlen(&buf[4]); + buf[4+nlen] = IAC; + buf[5+nlen] = SE; + send(server,buf,4+nlen+2,0); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +struct +{ + _option option; + LPOPTIONPROC OptionProc; + LPDATAPROC DataProc; +} ol[] = { + {TOPT_ECHO, ddww_echo, NULL}, + {TOPT_SUPP, ddww_supp, NULL}, + {TOPT_TERM, ddww_term, sbproc_term}, + {TOPT_ERROR, ddww_error, NULL} +}; + + +void vm(SOCKET server,unsigned char code) +{ +//These vars are the finite state + static int state = state_data; + static _verb verb = verb_sb; + static LPDATAPROC DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc; +// for index + int i=0; + +//Decide what to do (state based) + switch(state) + { + case state_data: + switch(code) + { + case IAC: state = state_code; break; + default: DataProc(server,code); + } + break; + case state_code: + state = state_data; + switch(code) + { + // State transition back to data + case IAC: + DataProc(server,code); + break; + // Code state transitions back to data + case SE: + DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc; + break; + case NOP: + break; + case DM: + break; + case BRK: + break; + case IP: + break; + case AO: + break; + case AYT: + break; + case EC: + break; + case EL: + break; + case GA: + break; + // Transitions to option state + case SB: + verb = verb_sb; + state = state_option; + break; + case WILL: + verb = verb_will; + state = state_option; + break; + case WONT: + verb = verb_wont; + state = state_option; + break; + case DO: + verb = verb_do; + state = state_option; + break; + case DONT: + verb = verb_dont; + state = state_option; + break; + } + break; + case state_option: + state = state_data; + + //Find the option entry + for( + i = 0; + ol[i].option != TOPT_ERROR && ol[i].option != code; + i++); + + //Do some verb specific stuff + if(verb == verb_sb) + DataProc = ol[i].DataProc; + else + ol[i].OptionProc(server,verb,(_option)code); + break; + } +} + +/* EOF */ diff --git a/apps/utils/objdir/makefile b/apps/utils/objdir/makefile new file mode 100644 index 0000000..510f900 --- /dev/null +++ b/apps/utils/objdir/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = objdir + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/utils/objdir/objdir.c b/apps/utils/objdir/objdir.c new file mode 100644 index 0000000..e88cb9a --- /dev/null +++ b/apps/utils/objdir/objdir.c @@ -0,0 +1,369 @@ +/* $Id$ + * + * DESCRIPTION: Object Manager Simple Explorer + * PROGRAMMER: David Welch + * REVISIONS + * 2000-04-30 (ea) + * Added directory enumeration. + * (tested under nt4sp4/x86) + * 2000-08-11 (ea) + * Added symbolic link expansion. + * (tested under nt4sp4/x86) + * 2001-05-01 (ea) + * Fixed entries counter. Added more + * error codes check. Removed wprintf, + * because it does not work in .17. + * 2001-05-02 (ea) + * Added -r option. + */ + +#include +#include +#include +#include +#include + +#define MAX_DIR_ENTRY 256 + + +static +PCHAR +STDCALL +RawUszAsz ( + PWCHAR szU, + PCHAR szA + ) +{ + register PCHAR a = szA; + + while (*szU) {*szA++ = (CHAR) (0x00ff & * szU++);} + *szA = '\0'; + return a; +} + + +static +PWCHAR +STDCALL +RawAszUsz ( + PCHAR szA, + PWCHAR szW + ) +{ + register PWCHAR w = szW; + + while (*szA) {*szW++ = (WCHAR) *szA++;} + *szW = L'\0'; + return w; +} + + +static +const char * +STDCALL +StatusToName (NTSTATUS Status) +{ + static char RawValue [16]; + + switch (Status) + { + case STATUS_BUFFER_TOO_SMALL: + return "STATUS_BUFFER_TOO_SMALL"; + case STATUS_INVALID_PARAMETER: + return "STATUS_INVALID_PARAMETER"; + case STATUS_OBJECT_NAME_INVALID: + return "STATUS_OBJECT_NAME_INVALID"; + case STATUS_OBJECT_NAME_NOT_FOUND: + return "STATUS_OBJECT_NAME_NOT_FOUND"; + case STATUS_PATH_SYNTAX_BAD: + return "STATUS_PATH_SYNTAX_BAD"; + case STATUS_NO_MORE_ENTRIES: + return "STATUS_NO_MORE_ENTRIES"; + case STATUS_UNSUCCESSFUL: + return "STATUS_UNSUCCESSFUL"; + } + sprintf (RawValue, "0x%08lx", Status); + return (const char *) RawValue; +} + + +BOOL +STDCALL +ExpandSymbolicLink ( + IN PUNICODE_STRING DirectoryName, + IN PUNICODE_STRING SymbolicLinkName, + IN OUT PUNICODE_STRING TargetObjectName + ) +{ + NTSTATUS Status; + HANDLE hSymbolicLink; + OBJECT_ATTRIBUTES oa; + UNICODE_STRING Path; + WCHAR PathBuffer [MAX_PATH]; + ULONG DataWritten = 0; + + + Path.Buffer = PathBuffer; + Path.Length = 0; + Path.MaximumLength = sizeof PathBuffer; + + RtlCopyUnicodeString (& Path, DirectoryName); + if (L'\\' != Path.Buffer [(Path.Length / sizeof Path.Buffer[0]) - 1]) + { + RtlAppendUnicodeToString (& Path, L"\\"); + } + RtlAppendUnicodeStringToString (& Path, SymbolicLinkName); + + oa.Length = sizeof (OBJECT_ATTRIBUTES); + oa.ObjectName = & Path; + oa.Attributes = 0; /* OBJ_CASE_INSENSITIVE; */ + oa.RootDirectory = NULL; + oa.SecurityDescriptor = NULL; + oa.SecurityQualityOfService = NULL; + + Status = NtOpenSymbolicLinkObject( + & hSymbolicLink, + SYMBOLIC_LINK_QUERY, /* 0x20001 */ + & oa + ); + + if (!NT_SUCCESS(Status)) + { + printf ( + "Failed to open SymbolicLink object (Status: %s)\n", + StatusToName (Status) + ); + return FALSE; + } + TargetObjectName->Length = TargetObjectName->MaximumLength; + memset ( + TargetObjectName->Buffer, + 0, + TargetObjectName->MaximumLength + ); + Status = NtQuerySymbolicLinkObject( + hSymbolicLink, + TargetObjectName, + & DataWritten + ); + if (!NT_SUCCESS(Status)) + { + printf ( + "Failed to query SymbolicLink object (Status: %s)\n", + StatusToName (Status) + ); + NtClose (hSymbolicLink); + return FALSE; + } + NtClose (hSymbolicLink); + return TRUE; +} + + +BOOL +STDCALL +ListDirectory ( + IN PUNICODE_STRING DirectoryNameW, + IN BOOL Recurse + ) +{ + CHAR DirectoryNameA [MAX_PATH]; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE DirectoryHandle; + BYTE DirectoryEntry [MAX_DIR_ENTRY * sizeof(OBJDIR_INFORMATION)]; + POBJDIR_INFORMATION pDirectoryEntry = (POBJDIR_INFORMATION) DirectoryEntry; + ULONG Context = 0; + ULONG ReturnLength = 0; + ULONG EntryCount = 0; + + /* For expanding symbolic links */ + WCHAR TargetName [2 * MAX_PATH]; + UNICODE_STRING TargetObjectName = { + sizeof TargetName, + sizeof TargetName, + TargetName + }; + + /* Convert to ANSI the directory's name */ + RawUszAsz (DirectoryNameW->Buffer, DirectoryNameA); + /* + * Prepare parameters for next call. + */ + InitializeObjectAttributes ( + & ObjectAttributes, + DirectoryNameW, + 0, + NULL, + NULL + ); + /* + * Try opening the directory. + */ + Status = NtOpenDirectoryObject ( + & DirectoryHandle, + DIRECTORY_QUERY, + & ObjectAttributes + ); + if (!NT_SUCCESS(Status)) + { + printf ( + "Failed to open directory object \"%s\" (Status: %s)\n", + DirectoryNameA, + StatusToName (Status) + ); + return (FALSE); + } + printf ("\n Directory of %s\n\n", DirectoryNameA); + /* + * Enumerate each item in the directory. + */ + Status = NtQueryDirectoryObject ( + DirectoryHandle, + pDirectoryEntry, + sizeof DirectoryEntry, + FALSE,/* ReturnSingleEntry */ + TRUE, /* RestartScan */ + & Context, + & ReturnLength + ); + if (!NT_SUCCESS(Status)) + { + if (STATUS_NO_MORE_ENTRIES == Status) + { + NtClose (DirectoryHandle); + return TRUE; + } + printf ( + "Failed to query directory object (Status: %s)\n", + StatusToName (Status) + ); + NtClose (DirectoryHandle); + return (FALSE); + } + while (0 != pDirectoryEntry->ObjectTypeName.Length) + { + CHAR ObjectNameA [MAX_PATH]; + CHAR TypeNameA [MAX_PATH]; + CHAR TargetNameA [MAX_PATH]; + + if (0 == wcscmp (L"SymbolicLink", pDirectoryEntry->ObjectTypeName.Buffer)) + { + if (TRUE == ExpandSymbolicLink ( + DirectoryNameW, + & pDirectoryEntry->ObjectName, + & TargetObjectName + ) + ) + { + + printf ( + "%-16s %s -> %s\n", + RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA), + RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA), + RawUszAsz (TargetObjectName.Buffer, TargetNameA) + ); + } + else + { + printf ( + "%-16s %s -> (error!)\n", + RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA), + RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA) + ); + } + } + else + { + printf ( + "%-16s %s\n", + RawUszAsz (pDirectoryEntry->ObjectTypeName.Buffer, TypeNameA), + RawUszAsz (pDirectoryEntry->ObjectName.Buffer, ObjectNameA) + ); + } + ++ EntryCount; + ++ pDirectoryEntry; + } + printf ("\n\t%d object(s)\n", EntryCount); + /* + * Free any resource. + */ + NtClose (DirectoryHandle); + /* + * Recurse into, if required so. + */ + if (FALSE != Recurse) + { + pDirectoryEntry = (POBJDIR_INFORMATION) DirectoryEntry; + while (0 != pDirectoryEntry->ObjectTypeName.Length) + { + if (0 == wcscmp (L"Directory", pDirectoryEntry->ObjectTypeName.Buffer)) + { + WCHAR CurrentName [MAX_PATH]; + UNICODE_STRING CurrentDirectory; + + CurrentName [0] = L'\0'; + wcscpy (CurrentName, DirectoryNameW->Buffer); + if (wcslen (CurrentName) > 1) + { + wcscat (CurrentName, L"\\"); + } + wcscat (CurrentName, pDirectoryEntry->ObjectName.Buffer); + RtlInitUnicodeString (& CurrentDirectory, CurrentName); + ListDirectory (& CurrentDirectory, Recurse); + } + ++ pDirectoryEntry; + } + } + return (TRUE); +} + + +int main(int argc, char* argv[]) +{ + WCHAR DirectoryNameW [MAX_PATH]; + UNICODE_STRING DirectoryName; + BOOL Recurse = FALSE; + + /* + * Check user arguments. + */ + switch (argc) + { + case 2: + RawAszUsz (argv[1], DirectoryNameW); + break; + case 3: + if (strcmp (argv[1], "-r")) + { + fprintf ( + stderr, + "%s: unknown option '%s'.\n", + argv [0], argv[1] + ); + return EXIT_FAILURE; + } + RawAszUsz (argv[2], DirectoryNameW); + Recurse = TRUE; + break; + default: + fprintf ( + stderr, + "\nUsage: %s [-r] directory\n\n" + " -r recurse\n" + " directory a directory name in the system namespace\n\n", + argv [0] + ); + return EXIT_FAILURE; + } + /* + * List the directory. + */ + RtlInitUnicodeString (& DirectoryName, DirectoryNameW); + return (FALSE == ListDirectory (& DirectoryName, Recurse)) + ? EXIT_FAILURE + : EXIT_SUCCESS; +} + + +/* EOF */ diff --git a/apps/utils/partinfo/makefile b/apps/utils/partinfo/makefile new file mode 100644 index 0000000..72b6c4b --- /dev/null +++ b/apps/utils/partinfo/makefile @@ -0,0 +1,23 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = partinfo + +#TARGET_CFLAGS = -fnative_struct + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/utils/partinfo/partinfo.c b/apps/utils/partinfo/partinfo.c new file mode 100644 index 0000000..56dbd48 --- /dev/null +++ b/apps/utils/partinfo/partinfo.c @@ -0,0 +1,212 @@ +/* + * partinfo - partition info program + */ + +#include +//#include +#include +#include + +//#define DUMP_DATA +#define DUMP_SIZE_INFO + + +#ifdef DUMP_DATA +void HexDump(char *buffer, ULONG size) +{ + ULONG offset = 0; + unsigned char *ptr; + + while (offset < (size & ~15)) + { + ptr = (unsigned char*)((ULONG)buffer + offset); + printf("%08lx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx-%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx\n", + offset, + ptr[0], + ptr[1], + ptr[2], + ptr[3], + ptr[4], + ptr[5], + ptr[6], + ptr[7], + ptr[8], + ptr[9], + ptr[10], + ptr[11], + ptr[12], + ptr[13], + ptr[14], + ptr[15]); + offset += 16; + } + + ptr = (unsigned char*)((ULONG)buffer + offset); + printf("%08lx ", offset); + while (offset < size) + { + printf(" %02hx", *ptr); + offset++; + ptr++; + } + + printf("\n\n\n"); +} +#endif + + +void Usage(void) +{ + puts("Usage: partinfo "); +} + + +int main (int argc, char *argv[]) +{ + HANDLE hDisk; + DWORD dwRead; + DWORD i; + char *Buffer; + DRIVE_LAYOUT_INFORMATION *LayoutBuffer; + DISK_GEOMETRY DiskGeometry; + ULONG ulDrive; + CHAR DriveName[40]; + SYSTEM_DEVICE_INFORMATION DeviceInfo; + NTSTATUS Status; + + if (argc != 2) + { + Usage(); + return(0); + } + + ulDrive = strtoul(argv[1], NULL, 10); + if (errno != 0) + { + printf("Error: Malformed drive number\n", errno); + return(0); + } + + /* Check drive number */ + Status = NtQuerySystemInformation(SystemDeviceInformation, + &DeviceInfo, + sizeof(SYSTEM_DEVICE_INFORMATION), + &i); + if (!NT_SUCCESS(Status)) + { + printf("NtQuerySystemInformation() failed (Status %lx)\n", Status); + return(0); + } + + if (DeviceInfo.NumberOfDisks == 0) + { + printf("No disk drive installed!\n"); + return(0); + } + + if (ulDrive >= DeviceInfo.NumberOfDisks) + { + printf("Invalid disk drive number! Valid drive numbers [0-%lu]\n", + DeviceInfo.NumberOfDisks-1); + return(0); + } + + /* Build full drive name */ + sprintf(DriveName, "\\\\.\\PHYSICALDRIVE%lu", ulDrive); + + /* Open drive */ + hDisk = CreateFile(DriveName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (hDisk == INVALID_HANDLE_VALUE) + { + printf("Invalid disk handle!"); + return 0; + } + + /* Get drive geometry */ + if (!DeviceIoControl(hDisk, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY), + &dwRead, + NULL)) + { + CloseHandle(hDisk); + printf("DeviceIoControl failed! Error: %u\n", + GetLastError()); + free(Buffer); + return 0; + } + +#ifdef DUMP_DATA + HexDump((char*)&DiskGeometry, dwRead); +#endif + printf("Drive number: %lu\n", ulDrive); + printf("Cylinders: %I64u\nMediaType: %lx\nTracksPerCylinder: %lu\n" + "SectorsPerTrack: %lu\nBytesPerSector: %lu\n\n", + DiskGeometry.Cylinders.QuadPart, + DiskGeometry.MediaType, + DiskGeometry.TracksPerCylinder, + DiskGeometry.SectorsPerTrack, + DiskGeometry.BytesPerSector); + + + Buffer = (char*)malloc(8192); + if (Buffer == NULL) + { + CloseHandle(hDisk); + printf("Out of memory!"); + return 0; + } + memset(Buffer, 0, 8192); + + if (!DeviceIoControl(hDisk, + IOCTL_DISK_GET_DRIVE_LAYOUT, + NULL, + 0, + Buffer, + 8192, + &dwRead, + NULL)) + { + CloseHandle(hDisk); + printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT) failed! Error: %u\n", + GetLastError()); + free(Buffer); + return 0; + } + + CloseHandle(hDisk); + +#ifdef DUMP_DATA + HexDump(Buffer, dwRead); +#endif + + LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)Buffer; + + printf("Partitions %u Signature %x\n", + LayoutBuffer->PartitionCount, + LayoutBuffer->Signature); + + for (i = 0; i < LayoutBuffer->PartitionCount; i++) + { + printf(" %d: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n", + i, + LayoutBuffer->PartitionEntry[i].PartitionNumber, + LayoutBuffer->PartitionEntry[i].BootIndicator, + LayoutBuffer->PartitionEntry[i].PartitionType, + LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart, + LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart); + } + + free(Buffer); + + return 0; +} diff --git a/apps/utils/pice/loader/main.c b/apps/utils/pice/loader/main.c new file mode 100644 index 0000000..309ee03 --- /dev/null +++ b/apps/utils/pice/loader/main.c @@ -0,0 +1,1001 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + main.c + +Abstract: + + loader/translator for pIce LINUX + +Environment: + + User mode only + +Author: + + Klaus P. Gerlicher + Reactos Port by Eugene Ingerman + +Revision History: + + 04-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +/////////////////////////////////////////////////////////////////////////////////// +// includes +#include "stdinc.h" +#include + +/////////////////////////////////////////////////////////////////////////////////// +// constant defines + + +/////////////////////////////////////////////////////////////////////////////////// +// global variables +char SrcFileNames[2048][2048]; +ULONG ulCurrentSrcFile = 0; + +HANDLE debugger_file; + +ULONG ulGlobalVerbose = 0; + + +/////////////////////////////////////////////////////////////////////////////////// +// process_stabs() +// +/////////////////////////////////////////////////////////////////////////////////// +void process_stabs( + char* pExeName, // name of exe + HANDLE fileout, // symbol file handle + PIMAGE_SECTION_HEADER section, //Elf32_Shdr* pSHdr, + int sectionHeadersSize, //int nSHdrSize, + void* p, // ptr to memory where whole exe was read + PSTAB_ENTRY pStab, // ptr to stabs + int nStabLen, // size of stabs + char* pStr, // ptr to stabs strings + int nStrLen, // sizeof stabs strings + char* pGlobals, // ptr to global symbols + int nGlobalLen, // sizeof of globals + char* pGlobalsStr, // ptr to global strings + int nGlobalStrLen) // size of global strings +{ + unsigned i,strLen; + int nOffset=0,nNextOffset=0; + PSTAB_ENTRY pStabCopy = pStab; + char* pName,szCurrentPath[2048]; + PICE_SYMBOLFILE_HEADER SymbolFileHeader; + LPSTR pSlash,pDot; + char temp[2048]; + char* pCopyExeName = temp; + WCHAR tempstr[64]; + DWORD wrote; + + //printf("LOADER: enter process_stabs()\n"); + + //get the name of the executable file + memset((void*)&SymbolFileHeader,0,sizeof(SymbolFileHeader)); + SymbolFileHeader.magic = PICE_MAGIC; + strcpy(temp,pExeName); + pSlash = strrchr(temp,'\\'); + pDot = strchr(temp,'.'); + if(pDot) + { + *pDot = 0; + } + if(pSlash) + { + pCopyExeName = pSlash+1; + } + strLen = MultiByteToWideChar(CP_ACP, NULL, pCopyExeName, -1, tempstr, 64 ); + if( !strLen ) + printf("Cannot convert string to multibyte: %s\n", pCopyExeName ); + wcscpy(SymbolFileHeader.name,tempstr); + + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + pName = &pStr[pStabCopy->n_strx + nOffset]; + +#if 0 + //printf("LOADER: \n%.8x %.2x %.2x %.4x %.8x %s\n", + pStabCopy->n_strx, + pStabCopy->n_type, + pStabCopy->n_other, + pStabCopy->n_desc, + pStabCopy->n_value, + pName + ); +#endif + switch(pStabCopy->n_type) + { + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStabCopy->n_value; + //printf("LOADER: changing string offset %x %x\n",nOffset,nNextOffset); + break; + case N_SO: + if((strLen = strlen(pName))) + { + if(pName[strLen-1]!='/') + { + if(strlen(szCurrentPath)) + { + //printf("LOADER: ###########################################################################\n"); + strcat(szCurrentPath,pName); + //printf("LOADER: changing source file %s\n",szCurrentPath); + strcpy(SrcFileNames[ulCurrentSrcFile++],szCurrentPath); + szCurrentPath[0]=0; + } + else + { + //printf("LOADER: ###########################################################################\n"); + //printf("LOADER: changing source file %s\n",pName); + strcpy(SrcFileNames[ulCurrentSrcFile++],pName); + } + } + else + strcpy(szCurrentPath,pName); + } + else + { + //printf("LOADER: END source file\n"); + //printf("LOADER: ###########################################################################\n"); + } + break; +/* case N_SLINE: + //printf("LOADER: code source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value); + break; + case N_DSLINE: + //printf("LOADER: data source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value); + break; + case N_BSLINE: + //printf("LOADER: BSS source line number #%u for addr. %x\n",pStabCopy->n_desc,pStabCopy->n_value); + break; + case N_GSYM: + //printf("LOADER: global symbol %s @ addr. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_BINCL: + //printf("LOADER: include file %s\n",pName); + break; + case N_EINCL: + break; + case N_FUN: + if(strlen(pName)) + //printf("LOADER: function %s @ addr. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + else + //printf("LOADER: text segment %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_PSYM: + //printf("LOADER: parameter %s @ [EBP%+d] (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_RSYM: + //printf("LOADER: register variable %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_LBRAC: + //printf("LOADER: lexical block %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_RBRAC: + //printf("LOADER: END of lexical block %s @ reg. %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_STSYM: + //printf("LOADER: static variable %s @ %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_LCSYM: + //printf("LOADER: BSS variable %s @ %x (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + break; + case N_LSYM: + if(pStabCopy->n_value) + { + //printf("LOADER: stack variable %s @ [EBP%+d] (%x)\n",pName,pStabCopy->n_value,pStabCopy->n_desc); + } + else + { + //printf("LOADER: global variable %s \n",pName); + } + break; +*/ + } + + pStabCopy++; + } + + //printf("LOADER: SymbolFileHeader.ulSizeOfHeader= %x (%x)\n",nSHdrSize,(LPSTR)pSHdr-(LPSTR)p); + //printf("LOADER: SymbolFileHeader.ulSizeOfGlobals = %x (%x)\n",nGlobalLen,(LPSTR)pGlobals-(LPSTR)p); + //printf("LOADER: SymbolFileHeader.ulSizeOfGlobalsStrings = %x (%x)\n",nGlobalStrLen,(LPSTR)pGlobalsStr-(LPSTR)p); + //printf("LOADER: SymbolFileHeader.ulSizeOfStabs = %x (%x)\n",nStabLen,(LPSTR)pStab-(LPSTR)p); + //printf("LOADER: SymbolFileHeader.ulSizeOfStabsStrings = %x (%x)\n",nStrLen,(LPSTR)pStr-(LPSTR)p); + + SymbolFileHeader.ulOffsetToHeaders = sizeof(PICE_SYMBOLFILE_HEADER); + SymbolFileHeader.ulSizeOfHeader = sectionHeadersSize; + SymbolFileHeader.ulOffsetToGlobals = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize; + SymbolFileHeader.ulSizeOfGlobals = nGlobalLen; + SymbolFileHeader.ulOffsetToGlobalsStrings = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen; + SymbolFileHeader.ulSizeOfGlobalsStrings = nGlobalStrLen; + SymbolFileHeader.ulOffsetToStabs = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen; + SymbolFileHeader.ulSizeOfStabs = nStabLen; + SymbolFileHeader.ulOffsetToStabsStrings = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen+nStabLen; + SymbolFileHeader.ulSizeOfStabsStrings = nStrLen; + SymbolFileHeader.ulOffsetToSrcFiles = sizeof(PICE_SYMBOLFILE_HEADER)+sectionHeadersSize+nGlobalLen+nGlobalStrLen+nStabLen+nStrLen; + SymbolFileHeader.ulNumberOfSrcFiles = ulCurrentSrcFile; + + printf("sectionHeaderSize: %ld, nGlobalLen: %ld, nGlobalStrLen: %ld, nStabLen: %ld, " + "nStrLen: %ld, ulCurrentSrcFile: %ld, ulOffsetToStabs: %ld\n", + sectionHeadersSize, nGlobalLen, nGlobalStrLen, + nStabLen, nStrLen, ulCurrentSrcFile, SymbolFileHeader.ulOffsetToStabs); + + WriteFile(fileout,&SymbolFileHeader,sizeof(PICE_SYMBOLFILE_HEADER),&wrote, NULL); + WriteFile(fileout,section,sectionHeadersSize,&wrote, NULL); + WriteFile(fileout,pGlobals,nGlobalLen,&wrote, NULL); + WriteFile(fileout,pGlobalsStr,nGlobalStrLen,&wrote, NULL); + WriteFile(fileout,pStab,nStabLen,&wrote, NULL); + WriteFile(fileout,pStr,nStrLen,&wrote, NULL); + + for(i=0;iName,".stab") == 0) + { + *ppStab = (PSTAB_ENTRY)((int)p + section->PointerToRawData); + *pLen = section->SizeOfRawData; + printf("LOADER: .stab @ %x (offset %x) len = %x\n",*ppStab,section->PointerToRawData,section->SizeOfRawData); + } + else if(strncmp(section->Name,".stabstr",strlen(".stabstr")) == 0) + { + *ppStr = (char*)((int)p + section->PointerToRawData); + *pnStabStrLen = section->SizeOfRawData; + printf("LOADER: .stabstr @ %x (offset %x) len = %x\n",*ppStab,section->PointerToRawData,section->SizeOfRawData); + } + } + + //printf("LOADER: leave find_stab_sections()\n"); +} + +/////////////////////////////////////////////////////////////////////////////////// +// process_pe() +// +/////////////////////////////////////////////////////////////////////////////////// +int process_pe(char* filename,int file,void* p,int len) +{ + + PIMAGE_DOS_HEADER pDosHeader; + PIMAGE_NT_HEADERS pNTHeaders; + + char* pStr; + PSTAB_ENTRY pStab; + DWORD nStabLen,nSym; + char* pStrTab; + char* pSymTab; + + char szSymName[2048]; + HANDLE fileout; + int nSymStrLen,nStabStrLen; + int iRetVal = 0; + + pDosHeader = (PIMAGE_DOS_HEADER)p; + pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD)p + pDosHeader->e_lfanew); + + if ((pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) + && (pDosHeader->e_lfanew != 0L) + && (pNTHeaders->Signature == IMAGE_NT_SIGNATURE)) + { + if( pNTHeaders->FileHeader.PointerToSymbolTable ){ + + pSymTab = (char*)((DWORD)p + pNTHeaders->FileHeader.PointerToSymbolTable); + nSym = pNTHeaders->FileHeader.NumberOfSymbols; + //string table follows immediately after symbol table. first 4 bytes give the length of the table + //references to string table include the first 4 bytes. + pStrTab = (char*)((PIMAGE_SYMBOL)pSymTab + nSym); + nSymStrLen = *((DWORD*)pStrTab); + find_stab_sections(p,IMAGE_FIRST_SECTION(pNTHeaders),pNTHeaders->FileHeader.NumberOfSections, + &pStab,&nStabLen,&pStr,&nStabStrLen); + + if(pStab && nStabLen && pStr && nStabStrLen) + { + LPSTR pDot; + + strcpy(szSymName,filename); + //printf("LOADER: file name = %s\n",szSymName); + if((pDot = strchr(szSymName,'.'))) + { + *pDot = 0; + strcat(pDot,".dbg"); + } + else + { + strcat(szSymName,".dbg"); + } + //printf("LOADER: symbol file name = %s\n",szSymName); + printf("LOADER: creating symbol file %s for %s\n",szSymName,filename); + + fileout = CreateFile(szSymName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + 0, + 0); + + if(fileout != INVALID_HANDLE_VALUE) + { + printf("NumberOfSections: %d, size: %d\n", pNTHeaders->FileHeader.NumberOfSections,sizeof(IMAGE_SECTION_HEADER)); + process_stabs(szSymName, + fileout, + IMAGE_FIRST_SECTION(pNTHeaders), + pNTHeaders->FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER), + p, + pStab, + nStabLen, + pStr, + nStabStrLen, + (char*)pSymTab, + nSym*sizeof(IMAGE_SYMBOL), + pStrTab, + nSymStrLen); + + CloseHandle(fileout); + } + else + { + printf("LOADER: creation of symbol file %s failed\n",szSymName); + iRetVal = 2; + } + + } + else + { + printf("LOADER: file %s has no data inside symbol tables\n",filename); + if( ulGlobalVerbose ) + { + if( !pStab || !nStabLen ) + printf("LOADER: - symbol table is empty or not present\n"); + if( !pStr || !nStabStrLen ) + printf("LOADER: - string table is empty or not present\n"); + } + iRetVal = 2; + } + } + else{ + printf("LOADER: file %s does not have a symbol table\n",filename); + iRetVal = 2; + } + } + else + { + printf("LOADER: file %s is not an ELF binary\n",filename); + iRetVal = 1; + } + + //printf("LOADER: leave process_pe()\n"); + return iRetVal; +} + +/////////////////////////////////////////////////////////////////////////////////// +// process_file() +// +/////////////////////////////////////////////////////////////////////////////////// +int process_file(char* filename) +{ + int file; + void* p; + off_t len; + int iRetVal=0; + + //printf("LOADER: enter process_file()\n"); + file = _open(filename,O_RDONLY|_O_BINARY); + if(file>0) + { + //printf("LOADER: opened %s as FD %x\n",filename,file); + + len = _lseek(file,0,SEEK_END); + printf("LOADER: file %s is %u bytes\n",filename,(int)len); + + _lseek(file,0,SEEK_SET); + + p = malloc(len+16); + if(p) + { + long count; + //printf("LOADER: malloc'd @ %x\n",p); + memset(p,0,len+16); + if(len == (count = _read(file,p,len))) + { + //printf("LOADER: trying ELF format\n"); + iRetVal = process_pe(filename,file,p,len); + } + } + _close(file); + } + else + { + printf("LOADER: file %s could not be opened\n",filename); + iRetVal = 1; + } + + //printf("LOADER: leave process_file()\n"); + return iRetVal; +} + +/////////////////////////////////////////////////////////////////////////////////// +// open_debugger() +// +/////////////////////////////////////////////////////////////////////////////////// +HANDLE open_debugger(void) +{ + debugger_file = CreateFile("\\Device\\Pice",GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL); + if(debugger_file == INVALID_HANDLE_VALUE) + { + printf("LOADER: debugger is not loaded. Last Error: %ld\n", GetLastError()); + } + + return debugger_file; +} + +/////////////////////////////////////////////////////////////////////////////////// +// close_debugger() +// +/////////////////////////////////////////////////////////////////////////////////// +void close_debugger(void) +{ + if( !CloseHandle(debugger_file) ){ + printf("Error closing debugger handle: %ld\n", GetLastError()); + } +} + +int ioctl( HANDLE device, DWORD ioctrlcode, PDEBUGGER_STATUS_BLOCK psb) +{ + DEBUGGER_STATUS_BLOCK tsb; + DWORD bytesreturned; + if( !DeviceIoControl( device, ioctrlcode, psb, sizeof(DEBUGGER_STATUS_BLOCK), + &tsb, sizeof(DEBUGGER_STATUS_BLOCK),&bytesreturned, NULL) ){ + printf("Error in DeviceIoControl: %ld\n", GetLastError()); + return -EINVAL; + } + else{ + memcpy( psb, &tsb, sizeof(DEBUGGER_STATUS_BLOCK) ); + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////// +// banner() +// +/////////////////////////////////////////////////////////////////////////////////// +void banner(void) +{ + printf("#########################################################\n"); + printf("#### Symbols LOADER/TRANSLATOR for PICE ####\n"); + printf("#########################################################\n"); +} + +#define ACTION_NONE 0 +#define ACTION_LOAD 1 +#define ACTION_UNLOAD 2 +#define ACTION_TRANS 3 +#define ACTION_RELOAD 4 +#define ACTION_INSTALL 5 +#define ACTION_UNINSTALL 6 +#define ACTION_STATUS 7 +#define ACTION_BREAK 8 +#define ACTION_TERMINAL 9 + +/////////////////////////////////////////////////////////////////////////////////// +// change_symbols() +// +/////////////////////////////////////////////////////////////////////////////////// +void change_symbols(int action,char* pfilename) +{ + int iRetVal = 0; + DEBUGGER_STATUS_BLOCK sb; + + strcpy(sb.filename, pfilename); + + switch(action) + { + case ACTION_LOAD: + printf("LOADER: loading symbols from %s\n",pfilename); + if(open_debugger() != INVALID_HANDLE_VALUE) + { + iRetVal = ioctl(debugger_file,PICE_IOCTL_LOAD,&sb); + close_debugger(); + } + break; + case ACTION_UNLOAD: + printf("LOADER: unloading symbols from %s\n",pfilename); + if(open_debugger() != INVALID_HANDLE_VALUE) + { + iRetVal = ioctl(debugger_file,PICE_IOCTL_UNLOAD,&sb); + close_debugger(); + } + break; + case ACTION_RELOAD: + printf("LOADER: reloading all symbols\n"); + if(open_debugger() != INVALID_HANDLE_VALUE) + { + ioctl(debugger_file,PICE_IOCTL_RELOAD,NULL); + close_debugger(); + printf("LOADER: reloading DONE!\n"); + } + break; + default : + printf("LOADER: an internal error has occurred at change_symbols\n"); + } + + switch( iRetVal ) + { + case -EINVAL : + printf("LOADER: debugger return value = -EINVAL, operation has failed\n"); + break; + case 0 : + // success - silently proceed + break; + default : + printf("LOADER: debugger return value = %i, operation possibly failed\n",iRetVal); + } +} + +// Dynamic install to be added later +#if 0 +/////////////////////////////////////////////////////////////////////////////////// +// tryinstall() +// +/////////////////////////////////////////////////////////////////////////////////// +int tryinstall(void) +{ + char *argv[]={"/sbin/insmod","pice.o",NULL}; + int err = 0; + int pid,status; + + banner(); + printf("LOADER: trying to install debugger...\n"); + + if( open_debugger() != INVALID_HANDLE_VALUE ) + { + printf("LOADER: debugger already installed...\n"); + close_debugger(); + return 0; + } + + // create a separate thread + pid = fork(); + switch(pid) + { + case -1: + // error when forking, i.e. out E_NOMEM + err = errno; + printf("LOADER: fork failed for execution of '%s' (errno = %u).\n",argv[0],err); + break; + case 0: + // child process handler + execve(argv[0],argv,NULL); + // returns only on error, with return value -1, errno is set + printf("LOADER: couldn't execute '%s' (errno = %u)\n",argv[0],errno); + exit(255); + break; + default: + // parent process handler + printf("LOADER: waiting for debugger to load...\n"); + pid = waitpid(pid, &status, 0); // suspend until child is done + if( (pid>0) && WIFEXITED(status) && (WEXITSTATUS(status) == 0) ) + printf("LOADER: debugger loaded!\n"); + else if( pid<=0 ) + { + printf("LOADER: Error on loading debugger! (waitpid() = %i)\n",pid); + err = -1; + } + else if( !WIFEXITED(status) ) + { + printf("LOADER: Error on loading debugger! (ifexited = %i)\n",WIFEXITED(status)); + err = -1; + } + else + { + printf("LOADER: Error on loading debugger! (exitstatus = %u)\n",WEXITSTATUS(status)); + err = WEXITSTATUS(status); + } + break; + } + + return err; +} + +/////////////////////////////////////////////////////////////////////////////////// +// tryuninstall() +// +/////////////////////////////////////////////////////////////////////////////////// +int tryuninstall(void) +{ + char *argv[]={"/sbin/rmmod","pice",NULL}; + int err = 0; + int pid,status; + + banner(); + printf("LOADER: trying to remove debugger...\n"); + + // check for loaded debugger + if(open_debugger() == INVALID_HANDLE_VALUE) + { + return -1; + } + // don't to close, else we'll have a reference count != 0 + close_debugger(); + + // create a separate thread + pid = fork(); + switch(pid) + { + case -1: + // error when forking, i.e. out E_NOMEM + err = errno; + printf("LOADER: fork failed for execution of '%s' (errno=%u).\n",argv[0],err); + break; + case 0: + // child process handler + execve(argv[0],argv,NULL); + // returns only on error, with return value -1, errno is set + printf("LOADER: couldn't execute '%s' (errno = %u)\n",argv[0],errno); + exit(255); + break; + default: + // parent process handler + printf("LOADER: waiting for debugger to unload...\n"); + pid = waitpid(pid, &status, 0); // suspend until child is done + + if( (pid>0) && WIFEXITED(status) && (WEXITSTATUS(status) == 0) ) + printf("LOADER: debugger removed!\n"); + else if( pid<=0 ) + { + printf("LOADER: Error on removing debugger! (waitpid() = %i)\n",pid); + err = -1; + } + else if( !WIFEXITED(status) ) + { + printf("LOADER: Error on removing debugger! (ifexited = %i)\n",WIFEXITED(status)); + err = -1; + } + else + { + printf("LOADER: Error on removing debugger! (exitstatus = %u)\n",WEXITSTATUS(status)); + err = WEXITSTATUS(status); + } + break; + } + return err; +} +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// showstatus() +// +/////////////////////////////////////////////////////////////////////////////////// +void showstatus(void) +{ + DEBUGGER_STATUS_BLOCK sb; + int iRetVal; + + if(open_debugger() != INVALID_HANDLE_VALUE) + { + iRetVal = ioctl(debugger_file,PICE_IOCTL_STATUS,&sb); + + //printf("LOADER: Test = %X\n",sb.Test); + close_debugger(); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// dobreak() +// +/////////////////////////////////////////////////////////////////////////////////// +void dobreak(void) +{ + int iRetVal; + + if(open_debugger() != INVALID_HANDLE_VALUE) + { + iRetVal = ioctl(debugger_file,PICE_IOCTL_BREAK,NULL); + close_debugger(); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// doterminal() +// +/////////////////////////////////////////////////////////////////////////////////// +#if 0 +void doterminal(void) +{ + if(SetupSerial(2,B115200)) + { + DebuggerShell(); + CloseSerial(); + } +} +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// process_switches() +// +// returns !=0 in case of a commandline error +// +/////////////////////////////////////////////////////////////////////////////////// +int process_switches(int argc,char* argv[]) +{ + int i; + char* parg,*pfilename = NULL; + int action = ACTION_NONE; + int error = 0; + + // parse commandline arguments + for(i=1;i ulGlobalVerbose ) + ulGlobalVerbose++; + } + else if(strcmp(parg,"install")==0 || strcmp(parg,"i")==0) + { + new_action = ACTION_INSTALL; + } + else if(strcmp(parg,"uninstall")==0 || strcmp(parg,"x")==0) + { + new_action = ACTION_UNINSTALL; + } + else if(strcmp(parg,"status")==0 || strcmp(parg,"s")==0) + { + new_action = ACTION_STATUS; + } + else if(strcmp(parg,"break")==0 || strcmp(parg,"b")==0) + { + new_action = ACTION_BREAK; + } + else if(strcmp(parg,"serial")==0 || strcmp(parg,"ser")==0) + { + new_action = ACTION_TERMINAL; + } + else + { + printf("LOADER: error: unknown switch %s", argv[i]); + error = 1; + } + + if( new_action != ACTION_NONE ) + { + if( action == ACTION_NONE ) + action = new_action; + else + if( action == new_action ) + { + // identical, just ignore + } + else + { + printf("LOADER: error: conflicting switch %s", argv[i]); + error = 1; + } + } + } + else + { + if( pfilename ) + { + printf("LOADER: error: additional filename %s", parg); + error = 1; + } + pfilename = parg; + } + } + + // check number of required parameters + switch( action ) + { + case ACTION_TRANS : + case ACTION_LOAD : + case ACTION_UNLOAD : + if( !pfilename ) + { + printf("LOADER: error: missing filename\n"); + error = 1; + } + break; + case ACTION_RELOAD : + /* filename parameter is optional */ + break; +#if 0 + case ACTION_UNINSTALL: + close_debugger(); + tryuninstall(); + break; + case ACTION_INSTALL: + tryinstall(); + break; +#endif + case ACTION_STATUS: + showstatus(); + break; + case ACTION_BREAK: + dobreak(); + break; +#if 0 + case ACTION_TERMINAL: + doterminal(); + break; +#endif + case ACTION_NONE : + printf("LOADER: no action specified specifed on commandline\n"); + error = 1; + + break; + default : + printf("LOADER: an internal error has occurred at commandline parsing\n"); + error = 1; + } + + if( !error ) // commandline was fine, now start processing + { + switch( action ) + { + case ACTION_TRANS : + printf("LOADER: trying to translate file %s...\n",pfilename); + if( process_file(pfilename)==0 ) + printf("LOADER: file %s has been translated\n",pfilename); + else + printf("LOADER: error while translating file %s\n",pfilename); + break; + case ACTION_LOAD : + case ACTION_UNLOAD : + case ACTION_RELOAD : + change_symbols(action,pfilename); + break; + } + } + + return error; +} + + +/////////////////////////////////////////////////////////////////////////////////// +// showhelp() +// +/////////////////////////////////////////////////////////////////////////////////// +void showhelp(void) +{ + banner(); + printf("LOADER: Syntax:\n"); + printf("LOADER: loader [switches] [executable/object file path]\n"); + printf("LOADER: Switches:\n"); + printf("LOADER: -trans (-t): translate from exe to sym\n"); + printf("LOADER: -load (-l): load symbols\n"); + printf("LOADER: -unload (-u): unload symbols\n"); + printf("LOADER: -reload (-r): reload some/all symbols\n"); + printf("LOADER: -verbose (-v): be a bit more verbose\n"); + printf("LOADER: -install (-i): install pICE debugger\n"); + printf("LOADER: -uninstall (-x): uninstall pICE debugger\n"); + printf("LOADER: -break (-b): break into debugger\n"); + printf("LOADER: -serial (-ser): start serial line terminal\n"); +} + +/////////////////////////////////////////////////////////////////////////////////// +// showpermission() +// +/////////////////////////////////////////////////////////////////////////////////// +void showpermission(void) +{ + banner(); + printf("LOADER: You must be superuser!\n"); +} + +/////////////////////////////////////////////////////////////////////////////////// +// main() +// +/////////////////////////////////////////////////////////////////////////////////// +int main(int argc,char* argv[]) +{ + if(argc==1 || argc>3) + { + showhelp(); + + return 1; + } + + return process_switches(argc,argv); +} diff --git a/apps/utils/pice/loader/makefile b/apps/utils/pice/loader/makefile new file mode 100644 index 0000000..2aab129 --- /dev/null +++ b/apps/utils/pice/loader/makefile @@ -0,0 +1,37 @@ +#CC = gcc +#CFLAGS := -g -Wall -fomit-frame-pointer -O2 +#LDFLAGS := -dynamic +#-lncurses + +#OBJS = main.o terminal.o +# + +#loader: $(OBJS) +# $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ + +#clean: +# @echo deleting all intermediate files +# @rm $(OBJS) loader -f +# make + + +PATH_TO_TOP = ../../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = loader + +TARGET_CFLAGS = -g -fomit-frame-pointer + +TARGET_SDKLIBS = + +TARGET_OBJECTS = main.o terminal.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + diff --git a/apps/utils/pice/loader/retypes.h b/apps/utils/pice/loader/retypes.h new file mode 100644 index 0000000..7dceba3 --- /dev/null +++ b/apps/utils/pice/loader/retypes.h @@ -0,0 +1,15 @@ +typedef unsigned int ULONG,*PULONG; +typedef unsigned short USHORT,*PUSHORT; +typedef unsigned char UCHAR,*PUCHAR; + +typedef signed int LONG,*PLONG; +typedef signed short SHORT,*PSHORT; +typedef signed char CHAR,*PCHAR,*LPSTR,*PSTR; + +typedef void VOID,*PVOID; + +typedef char BOOLEAN,*PBOOLEAN; + +#define FALSE (0==1) +#define TRUE (1==1) + diff --git a/apps/utils/pice/loader/stab.def b/apps/utils/pice/loader/stab.def new file mode 100644 index 0000000..b927edd --- /dev/null +++ b/apps/utils/pice/loader/stab.def @@ -0,0 +1,264 @@ +/* Table of DBX symbol codes for the GNU system. + Copyright (C) 1988, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files + overlaps the N_UNDF used for ordinary symbols. In ELF files, the + debug information is in a different file section, so there is no conflict. + This symbol's n_value gives the size of the string section associated + with this file. The symbol's n_strx (relative to the just-updated + string section start address) gives the name of the source file, + e.g. "foo.c", without any path information. The symbol's n_desc gives + the count of upcoming symbols associated with this file (not including + this one). */ +__define_stab (N_UNDF, 0x00, "UNDF") + +/* Global variable. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_GSYM, 0x20, "GSYM") + +/* Function name for BSD Fortran. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_FNAME, 0x22, "FNAME") + +/* Function name or text-segment variable for C. Value is its address. + Desc is supposedly starting line number, but GCC doesn't set it + and DBX seems not to miss it. */ +__define_stab (N_FUN, 0x24, "FUN") + +/* Data-segment variable with internal linkage. Value is its address. + "Static Sym". */ +__define_stab (N_STSYM, 0x26, "STSYM") + +/* BSS-segment variable with internal linkage. Value is its address. */ +__define_stab (N_LCSYM, 0x28, "LCSYM") + +/* Name of main routine. Only the name is significant. */ +__define_stab (N_MAIN, 0x2a, "MAIN") + +/* Solaris2: Read-only data symbols. */ +__define_stab (N_ROSYM, 0x2c, "ROSYM") + +/* Global symbol in Pascal. + Supposedly the value is its line number; I'm skeptical. */ +__define_stab (N_PC, 0x30, "PC") + +/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ +__define_stab (N_NSYMS, 0x32, "NSYMS") + +/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ +__define_stab (N_NOMAP, 0x34, "NOMAP") + +/* New stab from Solaris 2. Like N_SO, but for the object file. Two in + a row provide the build directory and the relative path of the .o from it. + Solaris2 uses this to avoid putting the stabs info into the linked + executable; this stab goes into the ".stab.index" section, and the debugger + reads the real stabs directly from the .o files instead. */ +__define_stab (N_OBJ, 0x38, "OBJ") + +/* New stab from Solaris 2. Options for the debugger, related to the + source language for this module. E.g. whether to use ANSI + integral promotions or traditional integral promotions. */ +__define_stab (N_OPT, 0x3c, "OPT") + +/* Register variable. Value is number of register. */ +__define_stab (N_RSYM, 0x40, "RSYM") + +/* Modula-2 compilation unit. Can someone say what info it contains? */ +__define_stab (N_M2C, 0x42, "M2C") + +/* Line number in text segment. Desc is the line number; + value is corresponding address. On Solaris2, the line number is + relative to the start of the current function. */ +__define_stab (N_SLINE, 0x44, "SLINE") + +/* Similar, for data segment. */ +__define_stab (N_DSLINE, 0x46, "DSLINE") + +/* Similar, for bss segment. */ +__define_stab (N_BSLINE, 0x48, "BSLINE") + +/* Sun's source-code browser stabs. ?? Don't know what the fields are. + Supposedly the field is "path to associated .cb file". THIS VALUE + OVERLAPS WITH N_BSLINE! */ +__define_stab_duplicate (N_BROWS, 0x48, "BROWS") + +/* GNU Modula-2 definition module dependency. Value is the modification time + of the definition file. Other is non-zero if it is imported with the + GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there + are enough empty fields? */ +__define_stab(N_DEFD, 0x4a, "DEFD") + +/* New in Solaris2. Function start/body/end line numbers. */ +__define_stab(N_FLINE, 0x4C, "FLINE") + +/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 + and one is for C++. Still,... */ +/* GNU C++ exception variable. Name is variable name. */ +__define_stab (N_EHDECL, 0x50, "EHDECL") +/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ +__define_stab_duplicate (N_MOD2, 0x50, "MOD2") + +/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if + this entry is immediately followed by a CAUGHT stab saying what exception + was caught. Multiple CAUGHT stabs means that multiple exceptions + can be caught here. If Desc is 0, it means all exceptions are caught + here. */ +__define_stab (N_CATCH, 0x54, "CATCH") + +/* Structure or union element. Value is offset in the structure. */ +__define_stab (N_SSYM, 0x60, "SSYM") + +/* Solaris2: Last stab emitted for module. */ +__define_stab (N_ENDM, 0x62, "ENDM") + +/* Name of main source file. + Value is starting text address of the compilation. + If multiple N_SO's appear, the first to contain a trailing / is the + compilation directory. The first to not contain a trailing / is the + source file name, relative to the compilation directory. Others (perhaps + resulting from cfront) are ignored. + On Solaris2, value is undefined, but desc is a source-language code. */ + +__define_stab (N_SO, 0x64, "SO") + +/* Automatic variable in the stack. Value is offset from frame pointer. + Also used for type descriptions. */ +__define_stab (N_LSYM, 0x80, "LSYM") + +/* Beginning of an include file. Only Sun uses this. + In an object file, only the name is significant. + The Sun linker puts data into some of the other fields. */ +__define_stab (N_BINCL, 0x82, "BINCL") + +/* Name of sub-source file (#include file). + Value is starting text address of the compilation. */ +__define_stab (N_SOL, 0x84, "SOL") + +/* Parameter variable. Value is offset from argument pointer. + (On most machines the argument pointer is the same as the frame pointer. */ +__define_stab (N_PSYM, 0xa0, "PSYM") + +/* End of an include file. No name. + This and N_BINCL act as brackets around the file's output. + In an object file, there is no significant data in this entry. + The Sun linker puts data into some of the fields. */ +__define_stab (N_EINCL, 0xa2, "EINCL") + +/* Alternate entry point. Value is its address. */ +__define_stab (N_ENTRY, 0xa4, "ENTRY") + +/* Beginning of lexical block. + The desc is the nesting level in lexical blocks. + The value is the address of the start of the text for the block. + The variables declared inside the block *precede* the N_LBRAC symbol. + On Solaris2, the value is relative to the start of the current function. */ +__define_stab (N_LBRAC, 0xc0, "LBRAC") + +/* Place holder for deleted include file. Replaces a N_BINCL and everything + up to the corresponding N_EINCL. The Sun linker generates these when + it finds multiple identical copies of the symbols from an include file. + This appears only in output from the Sun linker. */ +__define_stab (N_EXCL, 0xc2, "EXCL") + +/* Modula-2 scope information. Can someone say what info it contains? */ +__define_stab (N_SCOPE, 0xc4, "SCOPE") + +/* End of a lexical block. Desc matches the N_LBRAC's desc. + The value is the address of the end of the text for the block. + On Solaris2, the value is relative to the start of the current function. */ +__define_stab (N_RBRAC, 0xe0, "RBRAC") + +/* Begin named common block. Only the name is significant. */ +__define_stab (N_BCOMM, 0xe2, "BCOMM") + +/* End named common block. Only the name is significant + (and it should match the N_BCOMM). */ +__define_stab (N_ECOMM, 0xe4, "ECOMM") + +/* Member of a common block; value is offset within the common block. + This should occur within a BCOMM/ECOMM pair. */ +__define_stab (N_ECOML, 0xe8, "ECOML") + +/* Solaris2: Pascal "with" statement: type,,0,0,offset */ +__define_stab (N_WITH, 0xea, "WITH") + +/* These STAB's are used on Gould systems for Non-Base register symbols + or something like that. FIXME. I have assigned the values at random + since I don't have a Gould here. Fixups from Gould folk welcome... */ +__define_stab (N_NBTEXT, 0xF0, "NBTEXT") +__define_stab (N_NBDATA, 0xF2, "NBDATA") +__define_stab (N_NBBSS, 0xF4, "NBBSS") +__define_stab (N_NBSTS, 0xF6, "NBSTS") +__define_stab (N_NBLCS, 0xF8, "NBLCS") + +/* Second symbol entry containing a length-value for the preceding entry. + The value is the length. */ +__define_stab (N_LENG, 0xfe, "LENG") + +/* The above information, in matrix format. + + STAB MATRIX + _________________________________________________ + | 00 - 1F are not dbx stab symbols | + | In most cases, the low bit is the EXTernal bit| + + | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | + | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | + + | 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA | + | 09 |EXT | 0B | 0D WEAKU | 0F WEAKT | + + | 10 WEAKD | 12 COMM | 14 SETA | 16 SETT | + | 11 WEAKB | 13 | 15 | 17 | + + | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| + | 19 | 1B | 1D | 1F FN | + + |_______________________________________________| + | Debug entries with bit 01 set are unused. | + | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | + | 28 LCSYM | 2A MAIN | 2C ROSYM | 2E | + | 30 PC | 32 NSYMS | 34 NOMAP | 36 | + | 38 OBJ | 3A | 3C OPT | 3E | + | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | + | 48 BSLINE*| 4A DEFD | 4C FLINE | 4E | + | 50 EHDECL*| 52 | 54 CATCH | 56 | + | 58 | 5A | 5C | 5E | + | 60 SSYM | 62 ENDM | 64 SO | 66 | + | 68 | 6A | 6C | 6E | + | 70 | 72 | 74 | 76 | + | 78 | 7A | 7C | 7E | + | 80 LSYM | 82 BINCL | 84 SOL | 86 | + | 88 | 8A | 8C | 8E | + | 90 | 92 | 94 | 96 | + | 98 | 9A | 9C | 9E | + | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | + | A8 | AA | AC | AE | + | B0 | B2 | B4 | B6 | + | B8 | BA | BC | BE | + | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | + | C8 | CA | CC | CE | + | D0 | D2 | D4 | D6 | + | D8 | DA | DC | DE | + | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | + | E8 ECOML | EA WITH | EC | EE | + | F0 | F2 | F4 | F6 | + | F8 | FA | FC | FE LENG | + +-----------------------------------------------+ + * 50 EHDECL is also MOD2. + * 48 BSLINE is also BROWS. + */ diff --git a/apps/utils/pice/loader/stab_gnu.h b/apps/utils/pice/loader/stab_gnu.h new file mode 100644 index 0000000..e73eb99 --- /dev/null +++ b/apps/utils/pice/loader/stab_gnu.h @@ -0,0 +1,37 @@ +#ifndef __GNU_STAB__ + +/* Indicate the GNU stab.h is in use. */ + +#define __GNU_STAB__ + +#define __define_stab(NAME, CODE, STRING) NAME=CODE, +#define __define_stab_duplicate(NAME, CODE, STRING) NAME=CODE, + +enum __stab_debug_code +{ +#include "stab.def" +LAST_UNUSED_STAB_CODE +}; + +#undef __define_stab + +/* Definitions of "desc" field for N_SO stabs in Solaris2. */ + +#define N_SO_AS 1 +#define N_SO_C 2 +#define N_SO_ANSI_C 3 +#define N_SO_CC 4 /* C++ */ +#define N_SO_FORTRAN 5 +#define N_SO_PASCAL 6 + +/* Solaris2: Floating point type values in basic types. */ + +#define NF_NONE 0 +#define NF_SINGLE 1 /* IEEE 32-bit */ +#define NF_DOUBLE 2 /* IEEE 64-bit */ +#define NF_COMPLEX 3 /* Fortran complex */ +#define NF_COMPLEX16 4 /* Fortran double complex */ +#define NF_COMPLEX32 5 /* Fortran complex*16 */ +#define NF_LDOUBLE 6 /* Long double (whatever that is) */ + +#endif /* __GNU_STAB_ */ diff --git a/apps/utils/pice/loader/stdinc.h b/apps/utils/pice/loader/stdinc.h new file mode 100644 index 0000000..34cfe0c --- /dev/null +++ b/apps/utils/pice/loader/stdinc.h @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +//#include +#include +#include + +//#include +#include +//#include +//#include +//#include +#include +#include +#include +//#include +//#include + +#include "../../../../include/pe.h" +#include "stab_gnu.h" +//#include "retypes.h" +//#include "terminal.h" +//#include +#include "../shared/shared.h" + + diff --git a/apps/utils/pice/loader/terminal.c b/apps/utils/pice/loader/terminal.c new file mode 100644 index 0000000..2776451 --- /dev/null +++ b/apps/utils/pice/loader/terminal.c @@ -0,0 +1,430 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + termínal.c + +Abstract: + + serial terminal for pICE headless mode + +Environment: + + User mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 23-Jan-2001: created + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#if 0 //ei not ready +#include "stdinc.h" +#include + + +#define CONSOLE_WIDTH (80) +#define CONSOLE_HEIGHT (25) + +USHORT major_version=0xFFFF,minor_version=0xFFFF,build_number=0xFFFF; + +USHORT g_attr = 0; + +USHORT usCurX,usCurY,xSize,ySize; + +USHORT foreground_color_map[]= +{ +}; + +USHORT background_color_map[]= +{ +}; + + +int fd_comm; +struct termios oldtio; + +//************************************************************************ +// CheckSum() +// +//************************************************************************ +UCHAR CheckSum(LPSTR p,ULONG Len) +{ + UCHAR ucCheckSum = 0; + ULONG i; + for(i=0;i 0); +} + +///************************************************************************ +// SendByte() +// +///************************************************************************ +BOOLEAN SendByte(UCHAR c) +{ + return (write(fd_comm,&c,1) > 0); +} + + +///************************************************************************ +// ReadPacket() +// +///************************************************************************ +PSERIAL_PACKET ReadPacket(void) +{ + ULONG i; + PSERIAL_PACKET p; + SERIAL_PACKET_HEADER header; + PUCHAR pHeaderRaw,pData; + char temp[256]; + ULONG ulCheckSum; + + // read a packet header + pHeaderRaw = (PUCHAR)&header; + for(i=0;iheader.packet_size; + + switch(pData->type) + { + case PACKET_TYPE_CONNECT: + { + PSERIAL_DATA_PACKET_CONNECT pDataConnect = (PSERIAL_DATA_PACKET_CONNECT)pData; + UCHAR i; + + for(i=0;ixsize,pDataConnect->ysize); + xSize = pDataConnect->xsize; + ySize = pDataConnect->ysize; + } + break; + case PACKET_TYPE_CLRLINE: + { + PSERIAL_DATA_PACKET_CLRLINE pDataClrLine = (PSERIAL_DATA_PACKET_CLRLINE)pData; + + ClrLine(pDataClrLine->line); + } + break; + case PACKET_TYPE_INVERTLINE: + { + PSERIAL_DATA_PACKET_INVERTLINE pDataInvertLine = (PSERIAL_DATA_PACKET_INVERTLINE)pData; + + InvertLine(pDataInvertLine->line); + } + break; + case PACKET_TYPE_PRINT: + { + PSERIAL_DATA_PACKET_PRINT pDataPrint = (PSERIAL_DATA_PACKET_PRINT)pData; + + Print(pDataPrint->string,pDataPrint->x,pDataPrint->y); + } + break; + case PACKET_TYPE_CURSOR: + { + PSERIAL_DATA_PACKET_CURSOR pDataCursor = (PSERIAL_DATA_PACKET_CURSOR)pData; + + SetCursorPosition(pDataCursor->x,pDataCursor->y); + SetCursorState(pDataCursor->state); + } + break; + case PACKET_TYPE_POLL: + { + PSERIAL_DATA_PACKET_POLL pDataPoll= (PSERIAL_DATA_PACKET_POLL)pData; + + if( (major_version != pDataPoll->major_version) || + (minor_version != pDataPoll->minor_version) || + (build_number != pDataPoll->build_number) ) + { + major_version = pDataPoll->major_version; + minor_version = pDataPoll->minor_version; + build_number = pDataPoll->build_number; + +// SetAppTitle(); + } + + } + break; + default: + //printf("UNHANDLED\n"); + break; + } +} + +//************************************************************************ +// DebuggerShell() +// +//************************************************************************ +void DebuggerShell(void) +{ + PSERIAL_PACKET p; + + //printf("DebuggerShell()\n"); + for(;;) + { + p = ReadPacket(); + if(p) + { + ProcessPacket(p); + DeletePacket(p); + } + else + { + usleep(100*1000); + } + } +} +#endif diff --git a/apps/utils/pice/loader/terminal.h b/apps/utils/pice/loader/terminal.h new file mode 100644 index 0000000..ad37c9a --- /dev/null +++ b/apps/utils/pice/loader/terminal.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + termínal.h + +Abstract: + + HEADER for terminal.c + +Environment: + + User mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 23-Jan-2001: created + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +BOOLEAN SetupSerial(ULONG port,ULONG baudrate); +void CloseSerial(void); + + +void DebuggerShell(void); diff --git a/apps/utils/pice/makefile b/apps/utils/pice/makefile new file mode 100644 index 0000000..d46559d --- /dev/null +++ b/apps/utils/pice/makefile @@ -0,0 +1,21 @@ +# $Id$ + +all: + make -C loader + make -C module + +implib: + make -C loader implib + make -C module implib + +clean: + make -C loader clean + make -C module clean + +dist: + make -C loader dist + make -C module dist + +install: + make -C loader install + make -C module install diff --git a/apps/utils/pice/module/animation.h b/apps/utils/pice/module/animation.h new file mode 100644 index 0000000..6b5212f --- /dev/null +++ b/apps/utils/pice/module/animation.h @@ -0,0 +1,2116 @@ +// this file is dynamically generated: DON'T TOUCH + +UCHAR cAnimation[192*11]={ +0x00, // 1 +0x00, // 2 +0x00, // 3 +0x00, // 4 +0x00, // 5 +0x00, // 6 +0x00, // 7 +0x00, // 8 +0x00, // 9 +0x00, // 10 +0x00, // 11 +0x00, // 12 +0x00, // 13 +0x00, // 14 +0x00, // 15 +0x00, // 16 +0x00, // 17 +0x00, // 18 +0x00, // 19 +0x00, // 20 +0x00, // 21 +0x00, // 22 +0x00, // 23 +0x00, // 24 +0x00, // 25 +0x00, // 26 +0x00, // 27 +0x00, // 28 +0x00, // 29 +0x00, // 30 +0x00, // 31 +0x00, // 32 +0x00, // 33 +0x00, // 34 +0x00, // 35 +0x00, // 36 +0x00, // 37 +0x00, // 38 +0x00, // 39 +0x00, // 40 +0x00, // 41 +0x00, // 42 +0x00, // 43 +0x00, // 44 +0x00, // 45 +0x00, // 46 +0x00, // 47 +0x00, // 48 +0x00, // 49 +0x00, // 50 +0x00, // 51 +0x00, // 52 +0x00, // 53 +0x00, // 54 +0x00, // 55 +0x00, // 56 +0x00, // 57 +0x00, // 58 +0x00, // 59 +0x00, // 60 +0x00, // 61 +0x00, // 62 +0x00, // 63 +0x00, // 64 +0x00, // 65 +0x00, // 66 +0x00, // 67 +0x80, // 68 +0x00, // 69 +0x00, // 70 +0x00, // 71 +0x00, // 72 +0x00, // 73 +0x00, // 74 +0x00, // 75 +0xc0, // 76 +0x00, // 77 +0x00, // 78 +0x00, // 79 +0x00, // 80 +0x00, // 81 +0x00, // 82 +0x03, // 83 +0x60, // 84 +0x00, // 85 +0x00, // 86 +0x00, // 87 +0x00, // 88 +0x00, // 89 +0x00, // 90 +0x01, // 91 +0xb8, // 92 +0x00, // 93 +0x00, // 94 +0x00, // 95 +0x00, // 96 +0x00, // 97 +0x00, // 98 +0x00, // 99 +0xfe, // 100 +0x00, // 101 +0x00, // 102 +0x00, // 103 +0x00, // 104 +0x00, // 105 +0x00, // 106 +0x00, // 107 +0x42, // 108 +0x00, // 109 +0x00, // 110 +0x00, // 111 +0x00, // 112 +0x00, // 113 +0x00, // 114 +0x00, // 115 +0x43, // 116 +0x80, // 117 +0x00, // 118 +0x00, // 119 +0x00, // 120 +0x00, // 121 +0x00, // 122 +0x00, // 123 +0x76, // 124 +0xc0, // 125 +0x00, // 126 +0x00, // 127 +0x00, // 128 +0x00, // 129 +0x00, // 130 +0x02, // 131 +0x3c, // 132 +0x60, // 133 +0x00, // 134 +0x00, // 135 +0x00, // 136 +0x00, // 137 +0x00, // 138 +0x03, // 139 +0xf0, // 140 +0x20, // 141 +0x00, // 142 +0x00, // 143 +0x00, // 144 +0x00, // 145 +0x00, // 146 +0x00, // 147 +0x10, // 148 +0x20, // 149 +0x00, // 150 +0x00, // 151 +0x00, // 152 +0x00, // 153 +0x00, // 154 +0x00, // 155 +0xf8, // 156 +0x20, // 157 +0x00, // 158 +0x00, // 159 +0x00, // 160 +0x00, // 161 +0x00, // 162 +0x00, // 163 +0x1c, // 164 +0x20, // 165 +0x00, // 166 +0x00, // 167 +0x00, // 168 +0x00, // 169 +0x00, // 170 +0x00, // 171 +0x07, // 172 +0xe0, // 173 +0x00, // 174 +0x00, // 175 +0x00, // 176 +0x00, // 177 +0x00, // 178 +0x00, // 179 +0x01, // 180 +0x80, // 181 +0x00, // 182 +0x00, // 183 +0x00, // 184 +0x00, // 185 +0x00, // 186 +0x00, // 187 +0x07, // 188 +0x80, // 189 +0x00, // 190 +0x00, // 191 +0x00, // 192 +0x00, // 2 +0x00, // 4 +0x00, // 6 +0x00, // 8 +0x00, // 10 +0x00, // 12 +0x00, // 14 +0x00, // 16 +0x00, // 18 +0x00, // 20 +0x00, // 22 +0x00, // 24 +0x00, // 26 +0x00, // 28 +0x00, // 30 +0x00, // 32 +0x00, // 34 +0x00, // 36 +0x00, // 38 +0x00, // 40 +0x00, // 42 +0x00, // 44 +0x00, // 46 +0x00, // 48 +0x00, // 50 +0x00, // 52 +0x00, // 54 +0x00, // 56 +0x00, // 58 +0x00, // 60 +0x00, // 62 +0x00, // 64 +0x00, // 66 +0x00, // 68 +0x00, // 70 +0x00, // 72 +0x00, // 74 +0x00, // 76 +0x00, // 78 +0x00, // 80 +0x00, // 82 +0x00, // 84 +0x00, // 86 +0x00, // 88 +0x00, // 90 +0x00, // 92 +0x00, // 94 +0x00, // 96 +0x00, // 98 +0x00, // 100 +0x00, // 102 +0x00, // 104 +0x00, // 106 +0x00, // 108 +0x00, // 110 +0x00, // 112 +0x00, // 114 +0x00, // 116 +0x00, // 118 +0x00, // 120 +0x00, // 122 +0x00, // 124 +0x00, // 126 +0x00, // 128 +0x00, // 130 +0x00, // 132 +0x01, // 134 +0x10, // 136 +0x00, // 138 +0x00, // 140 +0x00, // 142 +0x00, // 144 +0x00, // 146 +0x00, // 148 +0x01, // 150 +0x90, // 152 +0x00, // 154 +0x00, // 156 +0x00, // 158 +0x00, // 160 +0x00, // 162 +0x00, // 164 +0x00, // 166 +0x90, // 168 +0x00, // 170 +0x00, // 172 +0x00, // 174 +0x00, // 176 +0x00, // 178 +0x00, // 180 +0x00, // 182 +0x90, // 184 +0x00, // 186 +0x00, // 188 +0x00, // 190 +0x00, // 192 +0x00, // 194 +0x00, // 196 +0x00, // 198 +0xfe, // 200 +0x00, // 202 +0x00, // 204 +0x00, // 206 +0x00, // 208 +0x00, // 210 +0x00, // 212 +0x00, // 214 +0x42, // 216 +0x40, // 218 +0x00, // 220 +0x00, // 222 +0x00, // 224 +0x00, // 226 +0x00, // 228 +0x00, // 230 +0x43, // 232 +0xc0, // 234 +0x00, // 236 +0x00, // 238 +0x00, // 240 +0x00, // 242 +0x00, // 244 +0x00, // 246 +0x76, // 248 +0xc8, // 250 +0x00, // 252 +0x00, // 254 +0x00, // 256 +0x00, // 258 +0x00, // 260 +0x00, // 262 +0x3c, // 264 +0x78, // 266 +0x00, // 268 +0x00, // 270 +0x00, // 272 +0x00, // 274 +0x00, // 276 +0x01, // 278 +0xf0, // 280 +0x20, // 282 +0x00, // 284 +0x00, // 286 +0x00, // 288 +0x00, // 290 +0x00, // 292 +0x00, // 294 +0x10, // 296 +0x20, // 298 +0x00, // 300 +0x00, // 302 +0x00, // 304 +0x00, // 306 +0x00, // 308 +0x01, // 310 +0xf8, // 312 +0x20, // 314 +0x00, // 316 +0x00, // 318 +0x00, // 320 +0x00, // 322 +0x00, // 324 +0x03, // 326 +0x1c, // 328 +0x20, // 330 +0x00, // 332 +0x00, // 334 +0x00, // 336 +0x00, // 338 +0x00, // 340 +0x00, // 342 +0x07, // 344 +0xe0, // 346 +0x00, // 348 +0x00, // 350 +0x00, // 352 +0x00, // 354 +0x00, // 356 +0x00, // 358 +0x01, // 360 +0x80, // 362 +0x00, // 364 +0x00, // 366 +0x00, // 368 +0x00, // 370 +0x00, // 372 +0x00, // 374 +0x07, // 376 +0x80, // 378 +0x00, // 380 +0x00, // 382 +0x00, // 384 +0x00, // 3 +0x00, // 6 +0x00, // 9 +0x00, // 12 +0x00, // 15 +0x00, // 18 +0x00, // 21 +0x00, // 24 +0x00, // 27 +0x00, // 30 +0x00, // 33 +0x00, // 36 +0x00, // 39 +0x00, // 42 +0x00, // 45 +0x00, // 48 +0x00, // 51 +0x00, // 54 +0x00, // 57 +0x00, // 60 +0x00, // 63 +0x00, // 66 +0x00, // 69 +0x00, // 72 +0x00, // 75 +0x00, // 78 +0x00, // 81 +0x00, // 84 +0x00, // 87 +0x00, // 90 +0x00, // 93 +0x00, // 96 +0x00, // 99 +0x00, // 102 +0x00, // 105 +0x00, // 108 +0x00, // 111 +0x00, // 114 +0x00, // 117 +0x00, // 120 +0x00, // 123 +0x00, // 126 +0x00, // 129 +0x00, // 132 +0x00, // 135 +0x00, // 138 +0x00, // 141 +0x00, // 144 +0x00, // 147 +0x00, // 150 +0x00, // 153 +0x00, // 156 +0x00, // 159 +0x00, // 162 +0x00, // 165 +0x00, // 168 +0x00, // 171 +0x00, // 174 +0x00, // 177 +0x08, // 180 +0x00, // 183 +0x00, // 186 +0x00, // 189 +0x00, // 192 +0x00, // 195 +0x00, // 198 +0x00, // 201 +0x08, // 204 +0x00, // 207 +0x00, // 210 +0x00, // 213 +0x00, // 216 +0x00, // 219 +0x00, // 222 +0x00, // 225 +0x88, // 228 +0x00, // 231 +0x00, // 234 +0x00, // 237 +0x00, // 240 +0x00, // 243 +0x00, // 246 +0x00, // 249 +0x88, // 252 +0x00, // 255 +0x00, // 258 +0x00, // 261 +0x00, // 264 +0x00, // 267 +0x00, // 270 +0x00, // 273 +0x8e, // 276 +0x00, // 279 +0x00, // 282 +0x00, // 285 +0x00, // 288 +0x00, // 291 +0x00, // 294 +0x00, // 297 +0xdb, // 300 +0x00, // 303 +0x00, // 306 +0x00, // 309 +0x00, // 312 +0x00, // 315 +0x00, // 318 +0x00, // 321 +0x71, // 324 +0x10, // 327 +0x00, // 330 +0x00, // 333 +0x00, // 336 +0x00, // 339 +0x00, // 342 +0x00, // 345 +0x23, // 348 +0xb0, // 351 +0x00, // 354 +0x00, // 357 +0x00, // 360 +0x00, // 363 +0x00, // 366 +0x00, // 369 +0x36, // 372 +0xc0, // 375 +0x00, // 378 +0x00, // 381 +0x00, // 384 +0x00, // 387 +0x00, // 390 +0x00, // 393 +0x3c, // 396 +0x6c, // 399 +0x00, // 402 +0x00, // 405 +0x00, // 408 +0x00, // 411 +0x00, // 414 +0x01, // 417 +0xf0, // 420 +0x38, // 423 +0x00, // 426 +0x00, // 429 +0x00, // 432 +0x00, // 435 +0x00, // 438 +0x03, // 441 +0x10, // 444 +0x30, // 447 +0x00, // 450 +0x00, // 453 +0x00, // 456 +0x00, // 459 +0x00, // 462 +0x06, // 465 +0x38, // 468 +0x10, // 471 +0x00, // 474 +0x00, // 477 +0x00, // 480 +0x00, // 483 +0x00, // 486 +0x04, // 489 +0x7c, // 492 +0x30, // 495 +0x00, // 498 +0x00, // 501 +0x00, // 504 +0x00, // 507 +0x00, // 510 +0x00, // 513 +0x46, // 516 +0x20, // 519 +0x00, // 522 +0x00, // 525 +0x00, // 528 +0x00, // 531 +0x00, // 534 +0x00, // 537 +0x01, // 540 +0xe0, // 543 +0x00, // 546 +0x00, // 549 +0x00, // 552 +0x00, // 555 +0x00, // 558 +0x00, // 561 +0x07, // 564 +0x80, // 567 +0x00, // 570 +0x00, // 573 +0x00, // 576 +0x00, // 4 +0x00, // 8 +0x00, // 12 +0x00, // 16 +0x00, // 20 +0x00, // 24 +0x00, // 28 +0x00, // 32 +0x00, // 36 +0x00, // 40 +0x00, // 44 +0x00, // 48 +0x00, // 52 +0x00, // 56 +0x00, // 60 +0x00, // 64 +0x00, // 68 +0x00, // 72 +0x00, // 76 +0x00, // 80 +0x00, // 84 +0x00, // 88 +0x00, // 92 +0x00, // 96 +0x00, // 100 +0x00, // 104 +0x00, // 108 +0x00, // 112 +0x00, // 116 +0x00, // 120 +0x00, // 124 +0x00, // 128 +0x00, // 132 +0x00, // 136 +0x00, // 140 +0x00, // 144 +0x00, // 148 +0x00, // 152 +0x00, // 156 +0x00, // 160 +0x00, // 164 +0x00, // 168 +0x00, // 172 +0x00, // 176 +0x00, // 180 +0x00, // 184 +0x00, // 188 +0x00, // 192 +0x00, // 196 +0x00, // 200 +0x00, // 204 +0x00, // 208 +0x00, // 212 +0x00, // 216 +0x00, // 220 +0x00, // 224 +0x00, // 228 +0x00, // 232 +0x00, // 236 +0x00, // 240 +0x00, // 244 +0x00, // 248 +0x00, // 252 +0x00, // 256 +0x00, // 260 +0x00, // 264 +0x01, // 268 +0x10, // 272 +0x00, // 276 +0x00, // 280 +0x00, // 284 +0x00, // 288 +0x00, // 292 +0x00, // 296 +0x01, // 300 +0x90, // 304 +0x00, // 308 +0x00, // 312 +0x00, // 316 +0x00, // 320 +0x00, // 324 +0x00, // 328 +0x00, // 332 +0x90, // 336 +0x00, // 340 +0x00, // 344 +0x00, // 348 +0x00, // 352 +0x00, // 356 +0x00, // 360 +0x00, // 364 +0x90, // 368 +0x00, // 372 +0x00, // 376 +0x00, // 380 +0x00, // 384 +0x00, // 388 +0x00, // 392 +0x00, // 396 +0xfe, // 400 +0x00, // 404 +0x00, // 408 +0x00, // 412 +0x00, // 416 +0x00, // 420 +0x00, // 424 +0x00, // 428 +0x42, // 432 +0x40, // 436 +0x00, // 440 +0x00, // 444 +0x00, // 448 +0x00, // 452 +0x00, // 456 +0x00, // 460 +0x43, // 464 +0xc0, // 468 +0x00, // 472 +0x00, // 476 +0x00, // 480 +0x00, // 484 +0x00, // 488 +0x00, // 492 +0x76, // 496 +0xc8, // 500 +0x00, // 504 +0x00, // 508 +0x00, // 512 +0x00, // 516 +0x00, // 520 +0x00, // 524 +0x3c, // 528 +0x78, // 532 +0x00, // 536 +0x00, // 540 +0x00, // 544 +0x00, // 548 +0x00, // 552 +0x01, // 556 +0xf0, // 560 +0x20, // 564 +0x00, // 568 +0x00, // 572 +0x00, // 576 +0x00, // 580 +0x00, // 584 +0x00, // 588 +0x10, // 592 +0x20, // 596 +0x00, // 600 +0x00, // 604 +0x00, // 608 +0x00, // 612 +0x00, // 616 +0x01, // 620 +0xf8, // 624 +0x20, // 628 +0x00, // 632 +0x00, // 636 +0x00, // 640 +0x00, // 644 +0x00, // 648 +0x03, // 652 +0x1c, // 656 +0x20, // 660 +0x00, // 664 +0x00, // 668 +0x00, // 672 +0x00, // 676 +0x00, // 680 +0x00, // 684 +0x07, // 688 +0xe0, // 692 +0x00, // 696 +0x00, // 700 +0x00, // 704 +0x00, // 708 +0x00, // 712 +0x00, // 716 +0x01, // 720 +0x80, // 724 +0x00, // 728 +0x00, // 732 +0x00, // 736 +0x00, // 740 +0x00, // 744 +0x00, // 748 +0x07, // 752 +0x80, // 756 +0x00, // 760 +0x00, // 764 +0x00, // 768 +0x00, // 5 +0x00, // 10 +0x00, // 15 +0x00, // 20 +0x00, // 25 +0x00, // 30 +0x00, // 35 +0x00, // 40 +0x00, // 45 +0x00, // 50 +0x00, // 55 +0x00, // 60 +0x00, // 65 +0x00, // 70 +0x00, // 75 +0x00, // 80 +0x00, // 85 +0x00, // 90 +0x00, // 95 +0x00, // 100 +0x00, // 105 +0x00, // 110 +0x00, // 115 +0x00, // 120 +0x00, // 125 +0x00, // 130 +0x00, // 135 +0x00, // 140 +0x00, // 145 +0x00, // 150 +0x00, // 155 +0x00, // 160 +0x00, // 165 +0x00, // 170 +0x00, // 175 +0x00, // 180 +0x00, // 185 +0x00, // 190 +0x00, // 195 +0x00, // 200 +0x00, // 205 +0x00, // 210 +0x00, // 215 +0x00, // 220 +0x00, // 225 +0x00, // 230 +0x00, // 235 +0x00, // 240 +0x00, // 245 +0x00, // 250 +0x00, // 255 +0x00, // 260 +0x00, // 265 +0x00, // 270 +0x00, // 275 +0x00, // 280 +0x00, // 285 +0x00, // 290 +0x00, // 295 +0x00, // 300 +0x00, // 305 +0x00, // 310 +0x00, // 315 +0x00, // 320 +0x00, // 325 +0x00, // 330 +0x00, // 335 +0x80, // 340 +0x00, // 345 +0x00, // 350 +0x00, // 355 +0x00, // 360 +0x00, // 365 +0x00, // 370 +0x00, // 375 +0xc0, // 380 +0x00, // 385 +0x00, // 390 +0x00, // 395 +0x00, // 400 +0x00, // 405 +0x00, // 410 +0x03, // 415 +0x60, // 420 +0x00, // 425 +0x00, // 430 +0x00, // 435 +0x00, // 440 +0x00, // 445 +0x00, // 450 +0x01, // 455 +0xb8, // 460 +0x00, // 465 +0x00, // 470 +0x00, // 475 +0x00, // 480 +0x00, // 485 +0x00, // 490 +0x00, // 495 +0xfe, // 500 +0x00, // 505 +0x00, // 510 +0x00, // 515 +0x00, // 520 +0x00, // 525 +0x00, // 530 +0x00, // 535 +0x42, // 540 +0x00, // 545 +0x00, // 550 +0x00, // 555 +0x00, // 560 +0x00, // 565 +0x00, // 570 +0x00, // 575 +0x43, // 580 +0x80, // 585 +0x00, // 590 +0x00, // 595 +0x00, // 600 +0x00, // 605 +0x00, // 610 +0x00, // 615 +0x76, // 620 +0xc0, // 625 +0x00, // 630 +0x00, // 635 +0x00, // 640 +0x00, // 645 +0x00, // 650 +0x02, // 655 +0x3c, // 660 +0x60, // 665 +0x00, // 670 +0x00, // 675 +0x00, // 680 +0x00, // 685 +0x00, // 690 +0x03, // 695 +0xf0, // 700 +0x20, // 705 +0x00, // 710 +0x00, // 715 +0x00, // 720 +0x00, // 725 +0x00, // 730 +0x00, // 735 +0x10, // 740 +0x20, // 745 +0x00, // 750 +0x00, // 755 +0x00, // 760 +0x00, // 765 +0x00, // 770 +0x00, // 775 +0xf8, // 780 +0x20, // 785 +0x00, // 790 +0x00, // 795 +0x00, // 800 +0x00, // 805 +0x00, // 810 +0x00, // 815 +0x1c, // 820 +0x20, // 825 +0x00, // 830 +0x00, // 835 +0x00, // 840 +0x00, // 845 +0x00, // 850 +0x00, // 855 +0x07, // 860 +0xe0, // 865 +0x00, // 870 +0x00, // 875 +0x00, // 880 +0x00, // 885 +0x00, // 890 +0x00, // 895 +0x01, // 900 +0x80, // 905 +0x00, // 910 +0x00, // 915 +0x00, // 920 +0x00, // 925 +0x00, // 930 +0x00, // 935 +0x07, // 940 +0x80, // 945 +0x00, // 950 +0x00, // 955 +0x00, // 960 +0x00, // 6 +0x00, // 12 +0x00, // 18 +0x00, // 24 +0x00, // 30 +0x00, // 36 +0x00, // 42 +0x00, // 48 +0x00, // 54 +0x00, // 60 +0x00, // 66 +0x00, // 72 +0x00, // 78 +0x00, // 84 +0x00, // 90 +0x00, // 96 +0x00, // 102 +0x00, // 108 +0x00, // 114 +0x00, // 120 +0x00, // 126 +0x00, // 132 +0x00, // 138 +0x00, // 144 +0x00, // 150 +0x00, // 156 +0x00, // 162 +0x00, // 168 +0x00, // 174 +0x00, // 180 +0x00, // 186 +0x00, // 192 +0x00, // 198 +0x00, // 204 +0x00, // 210 +0x00, // 216 +0x00, // 222 +0x00, // 228 +0x00, // 234 +0x00, // 240 +0x00, // 246 +0x00, // 252 +0x00, // 258 +0x00, // 264 +0x00, // 270 +0x00, // 276 +0x00, // 282 +0x00, // 288 +0x00, // 294 +0x00, // 300 +0x00, // 306 +0x00, // 312 +0x00, // 318 +0x00, // 324 +0x00, // 330 +0x00, // 336 +0x00, // 342 +0x00, // 348 +0x00, // 354 +0x08, // 360 +0x00, // 366 +0x00, // 372 +0x00, // 378 +0x00, // 384 +0x00, // 390 +0x00, // 396 +0x00, // 402 +0x08, // 408 +0x00, // 414 +0x00, // 420 +0x00, // 426 +0x00, // 432 +0x00, // 438 +0x00, // 444 +0x00, // 450 +0x88, // 456 +0x00, // 462 +0x00, // 468 +0x00, // 474 +0x00, // 480 +0x00, // 486 +0x00, // 492 +0x00, // 498 +0x88, // 504 +0x00, // 510 +0x00, // 516 +0x00, // 522 +0x00, // 528 +0x00, // 534 +0x00, // 540 +0x00, // 546 +0x8e, // 552 +0x00, // 558 +0x00, // 564 +0x00, // 570 +0x00, // 576 +0x00, // 582 +0x00, // 588 +0x00, // 594 +0xdb, // 600 +0x00, // 606 +0x00, // 612 +0x00, // 618 +0x00, // 624 +0x00, // 630 +0x00, // 636 +0x00, // 642 +0x71, // 648 +0x10, // 654 +0x00, // 660 +0x00, // 666 +0x00, // 672 +0x00, // 678 +0x00, // 684 +0x00, // 690 +0x23, // 696 +0xb0, // 702 +0x00, // 708 +0x00, // 714 +0x00, // 720 +0x00, // 726 +0x00, // 732 +0x00, // 738 +0x36, // 744 +0xc0, // 750 +0x00, // 756 +0x00, // 762 +0x00, // 768 +0x00, // 774 +0x00, // 780 +0x00, // 786 +0x3c, // 792 +0x6c, // 798 +0x00, // 804 +0x00, // 810 +0x00, // 816 +0x00, // 822 +0x00, // 828 +0x01, // 834 +0xf0, // 840 +0x38, // 846 +0x00, // 852 +0x00, // 858 +0x00, // 864 +0x00, // 870 +0x00, // 876 +0x03, // 882 +0x10, // 888 +0x30, // 894 +0x00, // 900 +0x00, // 906 +0x00, // 912 +0x00, // 918 +0x00, // 924 +0x06, // 930 +0x38, // 936 +0x10, // 942 +0x00, // 948 +0x00, // 954 +0x00, // 960 +0x00, // 966 +0x00, // 972 +0x04, // 978 +0x7c, // 984 +0x30, // 990 +0x00, // 996 +0x00, // 1002 +0x00, // 1008 +0x00, // 1014 +0x00, // 1020 +0x00, // 1026 +0x46, // 1032 +0x20, // 1038 +0x00, // 1044 +0x00, // 1050 +0x00, // 1056 +0x00, // 1062 +0x00, // 1068 +0x00, // 1074 +0x01, // 1080 +0xe0, // 1086 +0x00, // 1092 +0x00, // 1098 +0x00, // 1104 +0x00, // 1110 +0x00, // 1116 +0x00, // 1122 +0x07, // 1128 +0x80, // 1134 +0x00, // 1140 +0x00, // 1146 +0x00, // 1152 +0x00, // 7 +0x00, // 14 +0x00, // 21 +0x00, // 28 +0x00, // 35 +0x00, // 42 +0x00, // 49 +0x00, // 56 +0x00, // 63 +0x00, // 70 +0x00, // 77 +0x00, // 84 +0x00, // 91 +0x00, // 98 +0x00, // 105 +0x00, // 112 +0x00, // 119 +0x00, // 126 +0x00, // 133 +0x00, // 140 +0x00, // 147 +0x00, // 154 +0x00, // 161 +0x00, // 168 +0x00, // 175 +0x00, // 182 +0x00, // 189 +0x00, // 196 +0x00, // 203 +0x00, // 210 +0x00, // 217 +0x00, // 224 +0x00, // 231 +0x00, // 238 +0x00, // 245 +0x00, // 252 +0x00, // 259 +0x00, // 266 +0x00, // 273 +0x00, // 280 +0x00, // 287 +0x00, // 294 +0x00, // 301 +0x01, // 308 +0x00, // 315 +0x00, // 322 +0x00, // 329 +0x00, // 336 +0x00, // 343 +0x00, // 350 +0x00, // 357 +0x21, // 364 +0x00, // 371 +0x00, // 378 +0x00, // 385 +0x00, // 392 +0x00, // 399 +0x00, // 406 +0x00, // 413 +0x23, // 420 +0x00, // 427 +0x00, // 434 +0x00, // 441 +0x00, // 448 +0x00, // 455 +0x00, // 462 +0x00, // 469 +0x22, // 476 +0x00, // 483 +0x00, // 490 +0x00, // 497 +0x00, // 504 +0x00, // 511 +0x00, // 518 +0x00, // 525 +0x22, // 532 +0x00, // 539 +0x00, // 546 +0x00, // 553 +0x00, // 560 +0x00, // 567 +0x00, // 574 +0x00, // 581 +0x33, // 588 +0x00, // 595 +0x00, // 602 +0x00, // 609 +0x00, // 616 +0x00, // 623 +0x00, // 630 +0x00, // 637 +0x1f, // 644 +0x80, // 651 +0x00, // 658 +0x00, // 665 +0x00, // 672 +0x00, // 679 +0x00, // 686 +0x00, // 693 +0x08, // 700 +0x80, // 707 +0x00, // 714 +0x00, // 721 +0x00, // 728 +0x00, // 735 +0x00, // 742 +0x00, // 749 +0x08, // 756 +0x88, // 763 +0x00, // 770 +0x00, // 777 +0x00, // 784 +0x00, // 791 +0x00, // 798 +0x00, // 805 +0x09, // 812 +0x98, // 819 +0x00, // 826 +0x00, // 833 +0x00, // 840 +0x00, // 847 +0x00, // 854 +0x00, // 861 +0x0f, // 868 +0xf0, // 875 +0x00, // 882 +0x00, // 889 +0x00, // 896 +0x00, // 903 +0x00, // 910 +0x00, // 917 +0x0c, // 924 +0x20, // 931 +0x00, // 938 +0x00, // 945 +0x00, // 952 +0x00, // 959 +0x00, // 966 +0x0f, // 973 +0xf8, // 980 +0x30, // 987 +0x00, // 994 +0x00, // 1001 +0x00, // 1008 +0x00, // 1015 +0x00, // 1022 +0x00, // 1029 +0x08, // 1036 +0x1f, // 1043 +0x80, // 1050 +0x00, // 1057 +0x00, // 1064 +0x00, // 1071 +0x00, // 1078 +0x00, // 1085 +0x1c, // 1092 +0x10, // 1099 +0x00, // 1106 +0x00, // 1113 +0x00, // 1120 +0x00, // 1127 +0x00, // 1134 +0x00, // 1141 +0xf6, // 1148 +0x30, // 1155 +0x00, // 1162 +0x00, // 1169 +0x00, // 1176 +0x00, // 1183 +0x00, // 1190 +0x00, // 1197 +0x83, // 1204 +0x60, // 1211 +0x00, // 1218 +0x00, // 1225 +0x00, // 1232 +0x00, // 1239 +0x00, // 1246 +0x00, // 1253 +0x01, // 1260 +0xc0, // 1267 +0x00, // 1274 +0x00, // 1281 +0x00, // 1288 +0x00, // 1295 +0x00, // 1302 +0x00, // 1309 +0x03, // 1316 +0xe0, // 1323 +0x00, // 1330 +0x00, // 1337 +0x00, // 1344 +0x00, // 8 +0x00, // 16 +0x00, // 24 +0x00, // 32 +0x00, // 40 +0x00, // 48 +0x00, // 56 +0x00, // 64 +0x00, // 72 +0x00, // 80 +0x00, // 88 +0x00, // 96 +0x00, // 104 +0x00, // 112 +0x00, // 120 +0x00, // 128 +0x00, // 136 +0x00, // 144 +0x00, // 152 +0x00, // 160 +0x00, // 168 +0x00, // 176 +0x00, // 184 +0x00, // 192 +0x00, // 200 +0x00, // 208 +0x00, // 216 +0x00, // 224 +0x00, // 232 +0x00, // 240 +0x00, // 248 +0x00, // 256 +0x00, // 264 +0x00, // 272 +0x00, // 280 +0x00, // 288 +0x00, // 296 +0x00, // 304 +0x00, // 312 +0x00, // 320 +0x00, // 328 +0x00, // 336 +0x00, // 344 +0x00, // 352 +0x00, // 360 +0x00, // 368 +0x00, // 376 +0x00, // 384 +0x00, // 392 +0x00, // 400 +0x00, // 408 +0x00, // 416 +0x00, // 424 +0x00, // 432 +0x00, // 440 +0x00, // 448 +0x00, // 456 +0x00, // 464 +0x00, // 472 +0x00, // 480 +0x00, // 488 +0x00, // 496 +0x00, // 504 +0x00, // 512 +0x00, // 520 +0x00, // 528 +0x00, // 536 +0x00, // 544 +0x0c, // 552 +0x00, // 560 +0x00, // 568 +0x00, // 576 +0x00, // 584 +0x00, // 592 +0x00, // 600 +0x06, // 608 +0x18, // 616 +0x00, // 624 +0x00, // 632 +0x00, // 640 +0x00, // 648 +0x00, // 656 +0x00, // 664 +0x03, // 672 +0x30, // 680 +0x00, // 688 +0x00, // 696 +0x00, // 704 +0x00, // 712 +0x00, // 720 +0x00, // 728 +0x01, // 736 +0xe0, // 744 +0x00, // 752 +0x00, // 760 +0x00, // 768 +0x00, // 776 +0x00, // 784 +0x00, // 792 +0x01, // 800 +0x20, // 808 +0x00, // 816 +0x00, // 824 +0x00, // 832 +0x00, // 840 +0x00, // 848 +0x00, // 856 +0x01, // 864 +0x20, // 872 +0x00, // 880 +0x00, // 888 +0x00, // 896 +0x00, // 904 +0x00, // 912 +0x00, // 920 +0x01, // 928 +0xe0, // 936 +0x00, // 944 +0x00, // 952 +0x00, // 960 +0x00, // 968 +0x00, // 976 +0x00, // 984 +0x3d, // 992 +0xb9, // 1000 +0x80, // 1008 +0x00, // 1016 +0x00, // 1024 +0x00, // 1032 +0x00, // 1040 +0x00, // 1048 +0x07, // 1056 +0x0f, // 1064 +0x00, // 1072 +0x00, // 1080 +0x00, // 1088 +0x00, // 1096 +0x00, // 1104 +0x00, // 1112 +0x02, // 1120 +0x08, // 1128 +0x00, // 1136 +0x00, // 1144 +0x00, // 1152 +0x00, // 1160 +0x00, // 1168 +0x00, // 1176 +0x02, // 1184 +0x0b, // 1192 +0x80, // 1200 +0x00, // 1208 +0x00, // 1216 +0x00, // 1224 +0x00, // 1232 +0x00, // 1240 +0x3f, // 1248 +0x1e, // 1256 +0x00, // 1264 +0x00, // 1272 +0x00, // 1280 +0x00, // 1288 +0x00, // 1296 +0x00, // 1304 +0x01, // 1312 +0x10, // 1320 +0x00, // 1328 +0x00, // 1336 +0x00, // 1344 +0x00, // 1352 +0x00, // 1360 +0x00, // 1368 +0x01, // 1376 +0xe0, // 1384 +0x00, // 1392 +0x00, // 1400 +0x00, // 1408 +0x00, // 1416 +0x00, // 1424 +0x00, // 1432 +0x00, // 1440 +0xf0, // 1448 +0x00, // 1456 +0x00, // 1464 +0x00, // 1472 +0x00, // 1480 +0x00, // 1488 +0x00, // 1496 +0x01, // 1504 +0x98, // 1512 +0x00, // 1520 +0x00, // 1528 +0x00, // 1536 +0x00, // 9 +0x00, // 18 +0x00, // 27 +0x01, // 36 +0xff, // 45 +0xc0, // 54 +0x00, // 63 +0x00, // 72 +0x00, // 81 +0x00, // 90 +0x00, // 99 +0x00, // 108 +0xff, // 117 +0x80, // 126 +0x00, // 135 +0x00, // 144 +0x00, // 153 +0x00, // 162 +0x00, // 171 +0x00, // 180 +0x3f, // 189 +0x80, // 198 +0x00, // 207 +0x00, // 216 +0x00, // 225 +0x00, // 234 +0x00, // 243 +0x00, // 252 +0x01, // 261 +0x80, // 270 +0x00, // 279 +0x00, // 288 +0x00, // 297 +0x00, // 306 +0x00, // 315 +0x00, // 324 +0x00, // 333 +0x00, // 342 +0x00, // 351 +0x00, // 360 +0x00, // 369 +0x00, // 378 +0x00, // 387 +0x00, // 396 +0x00, // 405 +0x00, // 414 +0x00, // 423 +0x00, // 432 +0x00, // 441 +0x00, // 450 +0x00, // 459 +0x00, // 468 +0x00, // 477 +0x00, // 486 +0x00, // 495 +0x00, // 504 +0x00, // 513 +0x00, // 522 +0x00, // 531 +0x00, // 540 +0x00, // 549 +0x00, // 558 +0x00, // 567 +0x00, // 576 +0x00, // 585 +0x00, // 594 +0x00, // 603 +0x00, // 612 +0x0c, // 621 +0x00, // 630 +0x00, // 639 +0x00, // 648 +0x00, // 657 +0x00, // 666 +0x00, // 675 +0x06, // 684 +0x18, // 693 +0x00, // 702 +0x00, // 711 +0x00, // 720 +0x00, // 729 +0x00, // 738 +0x00, // 747 +0x03, // 756 +0x30, // 765 +0x00, // 774 +0x00, // 783 +0x00, // 792 +0x00, // 801 +0x00, // 810 +0x00, // 819 +0x01, // 828 +0xe0, // 837 +0x00, // 846 +0x00, // 855 +0x00, // 864 +0x00, // 873 +0x00, // 882 +0x00, // 891 +0x01, // 900 +0x20, // 909 +0x00, // 918 +0x00, // 927 +0x00, // 936 +0x00, // 945 +0x00, // 954 +0x00, // 963 +0x01, // 972 +0x20, // 981 +0x00, // 990 +0x00, // 999 +0x00, // 1008 +0x00, // 1017 +0x00, // 1026 +0x00, // 1035 +0x01, // 1044 +0xe0, // 1053 +0x00, // 1062 +0x00, // 1071 +0x00, // 1080 +0x00, // 1089 +0x00, // 1098 +0x00, // 1107 +0x3d, // 1116 +0xb9, // 1125 +0x80, // 1134 +0x00, // 1143 +0x00, // 1152 +0x00, // 1161 +0x00, // 1170 +0x00, // 1179 +0x07, // 1188 +0x0f, // 1197 +0x00, // 1206 +0x00, // 1215 +0x00, // 1224 +0x00, // 1233 +0x00, // 1242 +0x00, // 1251 +0x02, // 1260 +0x08, // 1269 +0x00, // 1278 +0x00, // 1287 +0x00, // 1296 +0x00, // 1305 +0x00, // 1314 +0x00, // 1323 +0x02, // 1332 +0x0b, // 1341 +0x80, // 1350 +0x00, // 1359 +0x00, // 1368 +0x00, // 1377 +0x00, // 1386 +0x00, // 1395 +0x3f, // 1404 +0x1e, // 1413 +0x00, // 1422 +0x00, // 1431 +0x00, // 1440 +0x00, // 1449 +0x00, // 1458 +0x00, // 1467 +0x01, // 1476 +0x10, // 1485 +0x00, // 1494 +0x00, // 1503 +0x00, // 1512 +0x00, // 1521 +0x00, // 1530 +0x00, // 1539 +0x01, // 1548 +0xe0, // 1557 +0x00, // 1566 +0x00, // 1575 +0x00, // 1584 +0x00, // 1593 +0x00, // 1602 +0x00, // 1611 +0x00, // 1620 +0xf0, // 1629 +0x00, // 1638 +0x00, // 1647 +0x00, // 1656 +0x00, // 1665 +0x00, // 1674 +0x00, // 1683 +0x01, // 1692 +0x98, // 1701 +0x00, // 1710 +0x00, // 1719 +0x00, // 1728 +0x00, // 10 +0x00, // 20 +0x00, // 30 +0x0f, // 40 +0xfe, // 50 +0x00, // 60 +0x00, // 70 +0x00, // 80 +0x00, // 90 +0x00, // 100 +0x00, // 110 +0x0f, // 120 +0xff, // 130 +0xc0, // 140 +0x00, // 150 +0x00, // 160 +0x00, // 170 +0x00, // 180 +0x00, // 190 +0x1f, // 200 +0xff, // 210 +0xc0, // 220 +0x00, // 230 +0x00, // 240 +0x00, // 250 +0x00, // 260 +0x00, // 270 +0x1f, // 280 +0xff, // 290 +0x80, // 300 +0x00, // 310 +0x00, // 320 +0x00, // 330 +0x00, // 340 +0x00, // 350 +0x1f, // 360 +0xff, // 370 +0x80, // 380 +0x00, // 390 +0x00, // 400 +0x00, // 410 +0x00, // 420 +0x00, // 430 +0x1f, // 440 +0xff, // 450 +0x80, // 460 +0x00, // 470 +0x00, // 480 +0x00, // 490 +0x00, // 500 +0x00, // 510 +0x3f, // 520 +0xff, // 530 +0x80, // 540 +0x00, // 550 +0x00, // 560 +0x00, // 570 +0x00, // 580 +0x00, // 590 +0x3f, // 600 +0xff, // 610 +0xff, // 620 +0xff, // 630 +0xf8, // 640 +0x00, // 650 +0x00, // 660 +0x00, // 670 +0x3f, // 680 +0xff, // 690 +0x80, // 700 +0x00, // 710 +0x08, // 720 +0x00, // 730 +0x00, // 740 +0x00, // 750 +0x3f, // 760 +0xff, // 770 +0x80, // 780 +0x00, // 790 +0x08, // 800 +0x00, // 810 +0x00, // 820 +0x00, // 830 +0x3f, // 840 +0xff, // 850 +0x80, // 860 +0x7f, // 870 +0xf8, // 880 +0x00, // 890 +0x00, // 900 +0x00, // 910 +0x3f, // 920 +0xff, // 930 +0xff, // 940 +0xc0, // 950 +0x00, // 960 +0x00, // 970 +0x00, // 980 +0x00, // 990 +0x3f, // 1000 +0xff, // 1010 +0x80, // 1020 +0x00, // 1030 +0x00, // 1040 +0x00, // 1050 +0x00, // 1060 +0x00, // 1070 +0x3f, // 1080 +0xff, // 1090 +0x80, // 1100 +0x00, // 1110 +0x00, // 1120 +0x00, // 1130 +0x00, // 1140 +0x00, // 1150 +0x3f, // 1160 +0xff, // 1170 +0x80, // 1180 +0x00, // 1190 +0x00, // 1200 +0x00, // 1210 +0x00, // 1220 +0x00, // 1230 +0x3f, // 1240 +0xff, // 1250 +0x80, // 1260 +0x00, // 1270 +0x00, // 1280 +0x00, // 1290 +0x00, // 1300 +0x00, // 1310 +0x3f, // 1320 +0xff, // 1330 +0x80, // 1340 +0x00, // 1350 +0x00, // 1360 +0x00, // 1370 +0x00, // 1380 +0x00, // 1390 +0x3f, // 1400 +0xff, // 1410 +0x80, // 1420 +0x00, // 1430 +0x00, // 1440 +0x00, // 1450 +0x00, // 1460 +0x00, // 1470 +0x03, // 1480 +0xfb, // 1490 +0x80, // 1500 +0x00, // 1510 +0x00, // 1520 +0x00, // 1530 +0x00, // 1540 +0x00, // 1550 +0x3f, // 1560 +0x1e, // 1570 +0x00, // 1580 +0x00, // 1590 +0x00, // 1600 +0x00, // 1610 +0x00, // 1620 +0x1c, // 1630 +0x01, // 1640 +0x10, // 1650 +0x7c, // 1660 +0x00, // 1670 +0x00, // 1680 +0x00, // 1690 +0x00, // 1700 +0x10, // 1710 +0x01, // 1720 +0xe0, // 1730 +0x0c, // 1740 +0x00, // 1750 +0x00, // 1760 +0x00, // 1770 +0x00, // 1780 +0x00, // 1790 +0x00, // 1800 +0xf0, // 1810 +0x00, // 1820 +0x80, // 1830 +0x00, // 1840 +0x00, // 1850 +0x00, // 1860 +0x00, // 1870 +0x01, // 1880 +0x98, // 1890 +0x00, // 1900 +0x00, // 1910 +0x00, // 1920 +0x00, // 11 +0x00, // 22 +0x00, // 33 +0x07, // 44 +0xfe, // 55 +0x00, // 66 +0x00, // 77 +0x00, // 88 +0x00, // 99 +0x00, // 110 +0x00, // 121 +0x3f, // 132 +0xff, // 143 +0x80, // 154 +0x00, // 165 +0x00, // 176 +0x00, // 187 +0x00, // 198 +0x00, // 209 +0x3f, // 220 +0xff, // 231 +0xc0, // 242 +0x00, // 253 +0x00, // 264 +0x00, // 275 +0x00, // 286 +0x00, // 297 +0x3f, // 308 +0xff, // 319 +0xc0, // 330 +0x00, // 341 +0x00, // 352 +0x00, // 363 +0x00, // 374 +0x00, // 385 +0x3f, // 396 +0xff, // 407 +0xc0, // 418 +0x00, // 429 +0x00, // 440 +0x00, // 451 +0x00, // 462 +0x00, // 473 +0x3f, // 484 +0xff, // 495 +0xc0, // 506 +0x00, // 517 +0x00, // 528 +0x00, // 539 +0x00, // 550 +0x00, // 561 +0x7f, // 572 +0xff, // 583 +0xc0, // 594 +0x00, // 605 +0x00, // 616 +0x00, // 627 +0x00, // 638 +0x00, // 649 +0x7f, // 660 +0xff, // 671 +0xc0, // 682 +0x01, // 693 +0xf8, // 704 +0x00, // 715 +0x00, // 726 +0x00, // 737 +0x7f, // 748 +0xff, // 759 +0xc0, // 770 +0x1f, // 781 +0x0c, // 792 +0x00, // 803 +0x00, // 814 +0x00, // 825 +0x7f, // 836 +0xff, // 847 +0xc0, // 858 +0xf0, // 869 +0x0c, // 880 +0x00, // 891 +0x00, // 902 +0x00, // 913 +0x7f, // 924 +0xff, // 935 +0xff, // 946 +0x00, // 957 +0x38, // 968 +0x00, // 979 +0x00, // 990 +0x00, // 1001 +0x7f, // 1012 +0xff, // 1023 +0xe0, // 1034 +0x01, // 1045 +0xc0, // 1056 +0x00, // 1067 +0x00, // 1078 +0x00, // 1089 +0x3f, // 1100 +0xff, // 1111 +0xc0, // 1122 +0xff, // 1133 +0x00, // 1144 +0x00, // 1155 +0x00, // 1166 +0x00, // 1177 +0x3f, // 1188 +0xff, // 1199 +0xc7, // 1210 +0x80, // 1221 +0x00, // 1232 +0x00, // 1243 +0x00, // 1254 +0x00, // 1265 +0x3f, // 1276 +0xff, // 1287 +0xfc, // 1298 +0x00, // 1309 +0x00, // 1320 +0x00, // 1331 +0x00, // 1342 +0x00, // 1353 +0x3f, // 1364 +0xff, // 1375 +0xe0, // 1386 +0x00, // 1397 +0x00, // 1408 +0x00, // 1419 +0x00, // 1430 +0x00, // 1441 +0x3f, // 1452 +0xff, // 1463 +0xc0, // 1474 +0x00, // 1485 +0x00, // 1496 +0x00, // 1507 +0x00, // 1518 +0x00, // 1529 +0x3f, // 1540 +0xff, // 1551 +0x80, // 1562 +0x00, // 1573 +0x00, // 1584 +0x00, // 1595 +0x00, // 1606 +0x00, // 1617 +0x3f, // 1628 +0xff, // 1639 +0x80, // 1650 +0x00, // 1661 +0x00, // 1672 +0x00, // 1683 +0x00, // 1694 +0x00, // 1705 +0x3f, // 1716 +0xff, // 1727 +0x80, // 1738 +0x00, // 1749 +0x00, // 1760 +0x00, // 1771 +0x00, // 1782 +0x00, // 1793 +0x1f, // 1804 +0xff, // 1815 +0x80, // 1826 +0x00, // 1837 +0x00, // 1848 +0x00, // 1859 +0x00, // 1870 +0x00, // 1881 +0x1f, // 1892 +0xff, // 1903 +0x80, // 1914 +0x00, // 1925 +0x00, // 1936 +0x00, // 1947 +0x00, // 1958 +0x00, // 1969 +0x1f, // 1980 +0xff, // 1991 +0x80, // 2002 +0x00, // 2013 +0x00, // 2024 +0x00, // 2035 +0x00, // 2046 +0x5f, // 2057 +0x9f, // 2068 +0xff, // 2079 +0x9f, // 2090 +0x10, // 2101 +0x00, // 2112 +}; diff --git a/apps/utils/pice/module/bp.c b/apps/utils/pice/module/bp.c new file mode 100644 index 0000000..7b71296 --- /dev/null +++ b/apps/utils/pice/module/bp.c @@ -0,0 +1,752 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + bp.c + +Abstract: + + setting, listing and removing breakpoints + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 13-Nov-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//////////////////////////////////////////////////// +// GLOBALS +//// +char tempBp[1024]; + +ULONG OldInt3Handler=0; + +SW_BP aSwBreakpoints[64]={{0,0,0,0},}; + +//************************************************************************* +// FindSwBp() +// +//************************************************************************* +PSW_BP FindSwBp(ULONG ulAddress) +{ + ULONG i; + + for(i=0;ibUsed == TRUE && + p->bVirtual == TRUE && + PICE_strcmpi(p->szModName,ModName)==0 && + PICE_strcmpi(p->szFunctionName,szFunctionName)==0) + { + return p; + } + } + + return NULL; +} + +//************************************************************************* +// IsSwBpAtAddressInstalled() +// +//************************************************************************* +BOOLEAN IsSwBpAtAddressInstalled(ULONG ulAddress) +{ + ULONG i; + + for(i=0;ibUsed == TRUE && p->bInstalled == FALSE && p->ulAddress==ulAddress && p->bVirtual==FALSE) + { + if(IsAddressValid(p->ulAddress)) + { + DPRINT((0,"NeedToReInstallSWBreakpoint(): [1] found BP\n")); + bResult = TRUE; + break; + } + } + } + else + { + if(p->bUsed == TRUE && p->bInstalled == FALSE && p->bVirtual == FALSE) + { + if(IsAddressValid(p->ulAddress)) + { + DPRINT((0,"NeedToReInstallSWBreakpoint(): [2] found BP\n")); + bResult = TRUE; + break; + } + } + } + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// ReInstallSWBreakpoint() +// +//************************************************************************* +BOOLEAN ReInstallSWBreakpoint(ULONG ulAddress) +{ + PSW_BP p; + BOOLEAN bResult = FALSE; + ULONG i; + + ENTER_FUNC(); + DPRINT((0,"ReInstallSWBreakpoint()\n")); + + for(i=0;i<(sizeof(aSwBreakpoints)/sizeof(SW_BP));i++) + { + p = &aSwBreakpoints[i]; + if(p->bUsed == TRUE && p->bInstalled == FALSE && p->ulAddress == ulAddress && p->bVirtual == FALSE) + { + if(IsAddressValid(p->ulAddress)) + { + BOOLEAN isWriteable; + + if( !( isWriteable = IsAddressWriteable(p->ulAddress) ) ) + SetAddressWriteable(p->ulAddress,TRUE); + *(PUCHAR)(p->ulAddress) = 0xCC; + if( !isWriteable ) + SetAddressWriteable(p->ulAddress,FALSE); + p->bInstalled = TRUE; + bResult = TRUE; + } + } + } + + LEAVE_FUNC(); + + return bResult; +} + + +//************************************************************************* +// InstallSWBreakpoint() +// +//************************************************************************* +BOOLEAN InstallSWBreakpoint(ULONG ulAddress,BOOLEAN bPermanent,void (*SWBreakpointCallback)(void)) +{ + PSW_BP p; + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + DPRINT((0,"InstallSWBreakpoint()\n")); + + // check if page is present + // TODO: must also check if it's a writable page + if(IsAddressValid(ulAddress) ) + { + DPRINT((0,"InstallSWBreakpoint(): %.8X is valid, writable? %d\n",ulAddress,IsAddressWriteable(ulAddress))); + DPRINT((0,"pde: %x, pte: %x\n", *(ADDR_TO_PDE(ulAddress)), *(ADDR_TO_PTE(ulAddress)))); + if((p = FindSwBp(ulAddress))==NULL) + { + DPRINT((0,"InstallSWBreakpoint(): %.8X is free\n",ulAddress)); + if( (p=FindEmptySwBpSlot()) ) + { + BOOLEAN isWriteable; + DPRINT((0,"InstallSWBreakpoint(): found empty slot\n")); + DPRINT((0,"InstallSWBreakpoint(): %x value: %x", ulAddress, *(PUCHAR)ulAddress)); + p->ucOriginalOpcode = *(PUCHAR)ulAddress; + //allow writing to page + if( !( isWriteable = IsAddressWriteable(ulAddress) ) ) + SetAddressWriteable(ulAddress,TRUE); + DPRINT((0,"writing breakpoint\n")); + *(PUCHAR)ulAddress = 0xCC; + DPRINT((0,"restoring page access\n")); + if( !isWriteable ) + SetAddressWriteable(ulAddress,FALSE); + p->bUsed = TRUE; + p->bInstalled = TRUE; + // find next address + p->ulAddress = ulAddress; + Disasm(&ulAddress,(PUCHAR)&tempBp); + p->ulNextInstr = ulAddress; + p->bPermanent = bPermanent; + if(bPermanent) + p->Callback = SWBreakpointCallback; + else + p->Callback = NULL; + bResult = TRUE; + } + } + else + { + DPRINT((0,"InstallSWBreakpoint(): %.8X is already used\n",ulAddress)); + if(p->bPermanent) + { + DPRINT((0,"InstallSWBreakpoint(): %.8X is a permanent breakpoint\n",ulAddress)); + } + } + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// InstallVirtualSWBreakpoint() +// +//************************************************************************* +BOOLEAN InstallVirtualSWBreakpoint(LPSTR ModName,LPSTR FunctionName) +{ + PSW_BP p; + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + DPRINT((0,"InstallVirtualSWBreakpoint(%s!%s)\n",ModName,FunctionName)); + + if( (p=FindEmptySwBpSlot()) ) + { + DPRINT((0,"InstallVirtualSWBreakpoint(): found empty slot\n")); + + p->bUsed = TRUE; + p->bInstalled = TRUE; + p->bVirtual = TRUE; + p->Callback = NULL; + PICE_strcpy(p->szModName,ModName); + PICE_strcpy(p->szFunctionName,FunctionName); + + bResult = TRUE; + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// TryToInstallVirtualSWBreakpoints() +// +//************************************************************************* +void TryToInstallVirtualSWBreakpoints(void) +{ + ULONG i,ulAddress; + PDEBUG_MODULE pMod; + PSW_BP p; + + DPRINT((0,"TryToInstallVirtualSWBreakpoints()\n")); + + for(i=0;i<(sizeof(aSwBreakpoints)/sizeof(SW_BP));i++) + { + p = &aSwBreakpoints[i]; + if(p->bUsed == TRUE && p->bVirtual) + { + if((pMod = IsModuleLoaded(p->szModName))) + { + if((ulAddress = FindFunctionInModuleByName(p->szFunctionName,pMod))) + { + if((p = FindVirtualSwBp(p->szModName,p->szFunctionName))) + { + ULONG ulAddressWithOffset = ulAddress+p->ulAddress; + DPRINT((0,"TryToInstallVirtualSWBreakpoints(): ulAddressWithOffset = %x (offset = %x)\n",ulAddressWithOffset,p->ulAddress)); + + if(IsAddressValid(ulAddressWithOffset)) + { + BOOLEAN isWriteable; + DPRINT((0,"TryToInstallVirtualSWBreakpoints(): installing...\n")); + p->ucOriginalOpcode = *(PUCHAR)ulAddressWithOffset; + //allow writing to page + if( !( isWriteable = IsAddressWriteable(ulAddressWithOffset) ) ) + SetAddressWriteable(ulAddressWithOffset,TRUE); + *(PUCHAR)ulAddressWithOffset = 0xCC; + if( !isWriteable ) + SetAddressWriteable(ulAddressWithOffset,FALSE); + p->bUsed = TRUE; + p->bInstalled = TRUE; + p->bVirtual = FALSE; + // find next address + p->ulAddress = ulAddressWithOffset; + Disasm(&ulAddressWithOffset,(PUCHAR)&tempBp); + p->ulNextInstr = ulAddressWithOffset; + p->bPermanent = FALSE; + p->Callback = NULL; + } + else + { + DPRINT((0,"TryToInstallVirtualSWBreakpoints(): not valid address\n")); + PICE_memset(p,0,sizeof(*p)); + } + } + + } + } + } + } +} + +//************************************************************************* +// RemoveSWBreakpoint() +// +// removes breakpoint from breakpoint list +//************************************************************************* +BOOLEAN RemoveSWBreakpoint(ULONG ulAddress) +{ + PSW_BP p; + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + DPRINT((0,"RemoveSWBreakpoint()\n")); + + if( (p = FindSwBp(ulAddress)) ) + { + if(IsAddressValid(ulAddress) && p->bInstalled == TRUE && p->bVirtual==FALSE) + { + BOOLEAN isWriteable; + if( !( isWriteable = IsAddressWriteable(ulAddress) ) ) + SetAddressWriteable(ulAddress,TRUE); + // restore original opcode + *(PUCHAR)(p->ulAddress) = p->ucOriginalOpcode; + if( !isWriteable ) + SetAddressWriteable(ulAddress,FALSE); + } + + PICE_memset(p,0,sizeof(*p)); + + bResult = TRUE; + } + + LEAVE_FUNC(); + + return bResult; +} + + +//************************************************************************* +// DeInstallSWBreakpoint() +// +//************************************************************************* +BOOLEAN DeInstallSWBreakpoint(ULONG ulAddress) +{ + PSW_BP p; + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + DPRINT((0,"DeInstallSWBreakpoint()\n")); + + if( (p = FindSwBp(ulAddress)) ) + { + if(IsAddressValid(ulAddress) && p->bInstalled == TRUE && p->bVirtual==FALSE) + { + BOOLEAN isWriteable; + if( !( isWriteable = IsAddressWriteable(ulAddress) ) ) + SetAddressWriteable(ulAddress,TRUE); + // restore original opcode + *(PUCHAR)(p->ulAddress) = p->ucOriginalOpcode; + if( !isWriteable ) + SetAddressWriteable(ulAddress,FALSE); + } + + p->bInstalled = FALSE; + + bResult = TRUE; + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// RemoveAllSWBreakpoints() +// +//************************************************************************* +BOOLEAN RemoveAllSWBreakpoints(BOOLEAN bEvenPermanents) +{ + PSW_BP p; + BOOLEAN bResult = FALSE; + ULONG i; + + ENTER_FUNC(); + DPRINT((0,"RemoveAllSWBreakpoint()\n")); + + for(i=0;i<(sizeof(aSwBreakpoints)/sizeof(SW_BP));i++) + { + p = &aSwBreakpoints[i]; + if(p->bUsed == TRUE) + { + if(bEvenPermanents) + { + if(IsAddressValid(p->ulAddress) && p->bVirtual==FALSE) + { + BOOLEAN isWriteable; + if( !( isWriteable = IsAddressWriteable(p->ulAddress) ) ) + SetAddressWriteable(p->ulAddress,TRUE); + *(PUCHAR)(p->ulAddress) = p->ucOriginalOpcode; + if( !isWriteable ) + SetAddressWriteable(p->ulAddress,FALSE); + bResult = TRUE; + } + PICE_memset(p,0,sizeof(*p)); + } + else + { + if(!p->bPermanent) + { + if(IsAddressValid(p->ulAddress) && p->bVirtual==FALSE) + { + BOOLEAN isWriteable; + if( !( isWriteable = IsAddressWriteable(p->ulAddress) ) ) + SetAddressWriteable(p->ulAddress,TRUE); + *(PUCHAR)(p->ulAddress) = p->ucOriginalOpcode; + if( !isWriteable ) + SetAddressWriteable(p->ulAddress,FALSE); + bResult = TRUE; + } + PICE_memset(p,0,sizeof(*p)); + } + } + } + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// IsPermanentSWBreakpoint() +// +//************************************************************************* +PSW_BP IsPermanentSWBreakpoint(ULONG ulAddress) +{ + PSW_BP p; + ULONG i; + + ENTER_FUNC(); + DPRINT((0,"IsPermanentSWBreakpoint(%.8X)\n",ulAddress)); + + for(i=0;i<(sizeof(aSwBreakpoints)/sizeof(aSwBreakpoints[0]));i++) + { + p = &aSwBreakpoints[i]; + if(p->ulAddress == ulAddress && + p->bUsed == TRUE && + p->bPermanent == TRUE) + { + LEAVE_FUNC(); + return p; + } + } + + LEAVE_FUNC(); + + return NULL; +} + +//************************************************************************* +// ListSWBreakpoints() +// +//************************************************************************* +void ListSWBreakpoints(void) +{ + PSW_BP p; + ULONG i; + LPSTR pSymbolName; + PDEBUG_MODULE pMod; + + ENTER_FUNC(); + DPRINT((0,"ListSWBreakpoints()\n")); + + for(i=0;i<(sizeof(aSwBreakpoints)/sizeof(SW_BP));i++) + { + p = &aSwBreakpoints[i]; + if(p->bUsed == TRUE && p->bVirtual == FALSE) + { + if((pSymbolName = FindFunctionByAddress(p->ulAddress,NULL,NULL)) ) + { + pMod = FindModuleFromAddress(p->ulAddress); + PICE_sprintf(tempBp,"[%u] %.8X (%S!%s) %s\n",i,p->ulAddress,pMod->name,pSymbolName,p->bPermanent?"PERMANENT":""); + } + else + { + if(ScanExportsByAddress(&pSymbolName,p->ulAddress)) + PICE_sprintf(tempBp,"[%u] %.8X (%s) %s\n",i,p->ulAddress,pSymbolName,p->bPermanent?"PERMANENT":""); + else + PICE_sprintf(tempBp,"[%u] %.8X (no symbol) %s\n",i,p->ulAddress,p->bPermanent?"PERMANENT":""); + } + Print(OUTPUT_WINDOW,tempBp); + } + else if(p->bUsed == TRUE) + { + PICE_sprintf(tempBp,"[%u] xxxxxxxx (%s!%s) VIRTUAL\n",i,p->szModName,p->szFunctionName); + Print(OUTPUT_WINDOW,tempBp); + } + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// RevirtualizeBreakpointsForModule() +// +//************************************************************************* +void RevirtualizeBreakpointsForModule(PDEBUG_MODULE pMod) +{ + ULONG i,start,end; + PSW_BP p; + char temp[DEBUG_MODULE_NAME_LEN]; + + DPRINT((0,"RevirtualizeBreakpointsForModule(%x)\n",(ULONG)pMod)); + + if(IsRangeValid((ULONG)pMod,sizeof(DEBUG_MODULE)) ) + { + start = (ULONG)pMod->BaseAddress; + end = (ULONG)pMod->BaseAddress+pMod->size; + + DPRINT((0,"RevirtualizeBreakpointsForModule(): module %x (%x-%x)\n",(ULONG)pMod,start,end)); + // go through all breakpoints + for(i=0;i<(sizeof(aSwBreakpoints)/sizeof(SW_BP));i++) + { + p = &aSwBreakpoints[i]; + // if it's used and installed and not virtual + if(p->bUsed && p->bInstalled && p->bVirtual == FALSE) + { + // make sure we're in module's bound + if(p->ulAddress>=start && p->ulAddressulAddress)) + { + // from now on it's virtual again + p->bVirtual = TRUE; + if(IsAddressValid(p->ulAddress) ) + { + BOOLEAN isWriteable; + if( !( isWriteable = IsAddressWriteable(p->ulAddress) ) ) + SetAddressWriteable(p->ulAddress,TRUE); + DPRINT((0,"RevirtualizeBreakpointsForModule(): restoring original opcode @ %x\n",p->ulAddress)); + *(PUCHAR)(p->ulAddress) = p->ucOriginalOpcode; + if( !isWriteable ) + SetAddressWriteable(p->ulAddress,FALSE); + } + else + { + DPRINT((0,"RevirtualizeBreakpointsForModule(): could not restore original opcode @ %x\n",p->ulAddress)); + } + // skip past the module separator + while(*pFind!='!')pFind++; + pFind++; + // remember the function and the module for reinstallation + CopyWideToAnsi(temp,pMod->name); + PICE_strcpy(p->szModName,temp); + PICE_strcpy(p->szFunctionName,pFind); + DPRINT((0,"RevirtualizeBreakpointsForModule(): %s!%s\n",p->szModName,p->szFunctionName)); + // if function name contains a '+' it's an offset + pFind = p->szFunctionName; + while(*pFind!=0) + { + DPRINT((0,"RevirtualizeBreakpointsForModule(): [1] %s\n",pFind)); + // found any offset to function + if(*pFind=='+') + { + *pFind=0; + break; + } + pFind++; + } + + DPRINT((0,"RevirtualizeBreakpointsForModule(): [2] %s\n",p->szFunctionName)); + if(ScanExports(p->szFunctionName,&ulFunctionAddress)) + { + p->ulAddress -= ulFunctionAddress; + DPRINT((0,"RevirtualizeBreakpointsForModule(): [1] function @ %x offset = %x\n",ulFunctionAddress,p->ulAddress)); + } + else + { + if((ulFunctionAddress = FindFunctionInModuleByName(p->szFunctionName,pMod)) ) + { + p->ulAddress -= ulFunctionAddress; + DPRINT((0,"RevirtualizeBreakpointsForModule(): [2] function @ %x offset = %x\n",ulFunctionAddress,p->ulAddress)); + } + else + { + DPRINT((0,"RevirtualizeBreakpointsForModule(): Breakpoint %u could not be virtualized properly!\n",i)); + PICE_sprintf(tempBp,"Breakpoint %u could not be virtualized properly!\n",i); + Print(OUTPUT_WINDOW,tempBp); + } + } + } + else + { + DPRINT((0,"RevirtualizeBreakpointsForModule(): function for %x not found!\n",p->ulAddress)); + PICE_memset(p,0,sizeof(*p)); + } + } + } + } + } +} + +//************************************************************************* +// NewInt3Handler() +// +//************************************************************************* +__asm__ ("\n\t \ +NewInt3Handler:\n\t \ + pushl $" STR(REASON_INT3) "\n\t \ + // call debugger loop\n\t \ + jmp NewInt31Handler\n\t \ +"); + + +//************************************************************************* +// InstallInt3Hook() +// +//************************************************************************* +void InstallInt3Hook(void) +{ + ULONG LocalInt3Handler; + + ENTER_FUNC(); + DPRINT((0,"enter InstallInt3Hook()...\n")); + + MaskIrqs(); + if(!OldInt3Handler) + { + PICE_memset(aSwBreakpoints,0,sizeof(aSwBreakpoints)); + __asm__("mov $NewInt3Handler,%0" + :"=r" (LocalInt3Handler) + : + :"eax"); + OldInt3Handler=SetGlobalInt(0x03,(ULONG)LocalInt3Handler); + } + UnmaskIrqs(); + + DPRINT((0,"leave InstallInt3Hook()...\n")); + LEAVE_FUNC(); +} + +//************************************************************************* +// DeInstallInt3Hook() +// +//************************************************************************* +void DeInstallInt3Hook(void) +{ + ENTER_FUNC(); + DPRINT((0,"enter DeInstallInt3Hook()...\n")); + + MaskIrqs(); + if(OldInt3Handler) + { + RemoveAllSWBreakpoints(TRUE); + SetGlobalInt(0x03,(ULONG)OldInt3Handler); + OldInt3Handler=0; + } + UnmaskIrqs(); + + DPRINT((0,"leave DeInstallInt3Hook()...\n")); + LEAVE_FUNC(); +} diff --git a/apps/utils/pice/module/bp.h b/apps/utils/pice/module/bp.h new file mode 100644 index 0000000..29cf59d --- /dev/null +++ b/apps/utils/pice/module/bp.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + bp.h + +Abstract: + + HEADER for bp.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +typedef struct _SW_BP +{ + ULONG ulAddress; + ULONG ulNextInstr; + UCHAR ucOriginalOpcode; + BOOLEAN bUsed; + BOOLEAN bInstalled; + BOOLEAN bPermanent; + BOOLEAN bVirtual; + char szModName[128]; + char szFunctionName[128]; + void (*Callback)(void); +}SW_BP,*PSW_BP; + +BOOLEAN InstallSWBreakpoint(ULONG ulAddress,BOOLEAN bPermanent,void (*SWBreakpointCallback)(void)); +BOOLEAN InstallVirtualSWBreakpoint(LPSTR ModName,LPSTR Function); +void TryToInstallVirtualSWBreakpoints(void); +BOOLEAN DeInstallSWBreakpoint(ULONG ulAddress); +BOOLEAN RemoveSWBreakpoint(ULONG ulAddress); +BOOLEAN NeedToReInstallSWBreakpoints(ULONG ulAddress,BOOLEAN bUseAddress); +BOOLEAN ReInstallSWBreakpoint(ULONG ulAddress); +BOOLEAN RemoveAllSWBreakpoints(BOOLEAN bEvenPermanents); +PSW_BP IsPermanentSWBreakpoint(ULONG ulAddress); +void ListSWBreakpoints(void); +PSW_BP FindSwBp(ULONG ulAddress); +BOOLEAN IsSwBpAtAddress(ULONG ulAddress); +BOOLEAN IsSwBpAtAddressInstalled(ULONG ulAddress); +void RevirtualizeBreakpointsForModule(PDEBUG_MODULE pMod); + +void InstallInt3Hook(void); +void DeInstallInt3Hook(void); + diff --git a/apps/utils/pice/module/charset.h b/apps/utils/pice/module/charset.h new file mode 100644 index 0000000..4b276a9 --- /dev/null +++ b/apps/utils/pice/module/charset.h @@ -0,0 +1,2564 @@ +// this file is dynamically generated: DON'T TOUCH + +UCHAR cGraphTable[8*256]= +{ + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + + /* 2 0x02 '^B' */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + + /* 3 0x03 '^C' */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 6 0x06 '^F' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x0f, /* 00001111 */ + 0x07, /* 00000111 */ + 0x0f, /* 00001111 */ + 0x7d, /* 01111101 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + + /* 12 0x0c '^L' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + + /* 13 0x0d '^M' */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + + /* 14 0x0e '^N' */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + + /* 15 0x0f '^O' */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + + /* 16 0x10 '^P' */ + 0x80, /* 10000000 */ + 0xe0, /* 11100000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xe0, /* 11100000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x02, /* 00000010 */ + 0x0e, /* 00001110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x0e, /* 00001110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + + /* 19 0x13 '^S' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x3e, /* 00111110 */ + 0x61, /* 01100001 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x86, /* 10000110 */ + 0x7c, /* 01111100 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + + /* 24 0x18 '^X' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x24, /* 00100100 */ + 0x66, /* 01100110 */ + 0xff, /* 11111111 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x60, /* 01100000 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 60 0x3c '<' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xc0, /* 11000000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xce, /* 11001110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xce, /* 11001110 */ + 0x7c, /* 01111100 */ + 0x0e, /* 00001110 */ + + /* 82 0x52 'R' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x8c, /* 10001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0xc0, /* 11000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + + /* 96 0x60 '`' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0xf8, /* 11111000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + + /* 104 0x68 'h' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + + /* 107 0x6b 'k' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x4c, /* 01001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '€' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + + /* 129 0x81 '' */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '‚' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 131 0x83 'ƒ' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '„' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '…' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '†' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '‡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x0c, /* 00001100 */ + 0x38, /* 00111000 */ + + /* 136 0x88 'ˆ' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '‰' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 138 0x8a 'Š' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '‹' */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 140 0x8c 'Œ' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 142 0x8e 'Ž' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xf8, /* 11111000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '‘' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '’' */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '“' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '”' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '•' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '–' */ + 0x78, /* 01111000 */ + 0x84, /* 10000100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '—' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '˜' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 153 0x99 '™' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a 'š' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '›' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 156 0x9c 'œ' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 158 0x9e 'ž' */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfa, /* 11111010 */ + 0xc6, /* 11000110 */ + 0xcf, /* 11001111 */ + 0xc6, /* 11000110 */ + 0xc7, /* 11000111 */ + + /* 159 0x9f 'Ÿ' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 ' ' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '¡' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '¢' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '£' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '¤' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '¥' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '¦' */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '§' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¨' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x63, /* 01100011 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '©' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '«' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7e, /* 01111110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x0f, /* 00001111 */ + + /* 172 0xac '¬' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7a, /* 01111010 */ + 0x36, /* 00110110 */ + 0x6a, /* 01101010 */ + 0xdf, /* 11011111 */ + 0x06, /* 00000110 */ + + /* 173 0xad '­' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '®' */ + 0x00, /* 00000000 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '¯' */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '°' */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + + /* 177 0xb1 '±' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '²' */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + + /* 179 0xb3 '³' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '´' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 'µ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '¶' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '¸' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '¹' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba 'º' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '¼' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '½' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '¾' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 'À' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 'Á' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 'Â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 'Ã' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 'Ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 'Å' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 'Æ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 'Ç' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 'È' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 'É' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca 'Ê' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb 'Ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc 'Ì' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd 'Í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce 'Î' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf 'Ï' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 'Ð' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 'Ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 'Ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 'Ó' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 'Ô' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 'Õ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 'Ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '×' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 'Ø' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 'Ù' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda 'Ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb 'Û' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc 'Ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd 'Ý' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde 'Þ' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf 'ß' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'à' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xc8, /* 11001000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'á' */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'â' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'ã' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'ä' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'å' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0xc0, /* 11000000 */ + + /* 231 0xe7 'ç' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'è' */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + + /* 233 0xe9 'é' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'ê' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'ë' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 236 0xec 'ì' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'í' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + + /* 238 0xee 'î' */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 239 0xef 'ï' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 'ð' */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 'ñ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 'ò' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 'ó' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 'ô' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 'õ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + + /* 246 0xf6 'ö' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '÷' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 'ø' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 'ù' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa 'ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb 'û' */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + + /* 252 0xfc 'ü' */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd 'ý' */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe 'þ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff 'ÿ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ +}; diff --git a/apps/utils/pice/module/dblflt.c b/apps/utils/pice/module/dblflt.c new file mode 100644 index 0000000..1535c6b --- /dev/null +++ b/apps/utils/pice/module/dblflt.c @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + dblflt.c + +Abstract: + + handle double faults on x86 + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 13-Nov-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//////////////////////////////////////////////////// +// GLOBALS +//// +ULONG OldDblFltHandler = 0; + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// HandleDoubleFault() +// +//************************************************************************* +void HandleDoubleFault(FRAME* ptr) +{ + DPRINT((0,"HandleDoubleFault(): ptr = %x\n",ptr)); +} + + +//************************************************************************* +// NewDblFltHandler() +// +//************************************************************************* +__asm__ (" \ +NewDblFltHandler:\n\t \ + pushfl\n\t \ + cli;\n\t \ + cld;\n\t \ + pushal;\n\t \ + pushl %ds;\n\t \ +\n\t \ + // setup default data selectors\n\t \ + movw %ss,%ax\n\t \ + movw %ax,%ds\n\t \ +\n\t \ + // get frame ptr\n\t \ + lea 40(%esp),%eax\n\t \ + pushl %eax\n\t \ + call _HandleDoubleFault\n\t \ + addl $4,%esp\n\t \ +\n\t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ + // remove error code from stack and replace with reason code\n\t \ + movl $" STR(REASON_DOUBLE_FAULT) ",(%esp)\n\t \ + // call debugger loop\n\t \ + jmp NewInt31Handler\n\t"); + + +//************************************************************************* +// InstallDblFltHook() +// +//************************************************************************* +void InstallDblFltHook(void) +{ + ULONG LocalDblFltHandler; + + ENTER_FUNC(); + + MaskIrqs(); + if(!OldDblFltHandler) + { + __asm__("mov $NewDblFltHandler,%0" + :"=r" (LocalDblFltHandler) + : + :"eax"); + OldDblFltHandler=SetGlobalInt(0x08,(ULONG)LocalDblFltHandler); + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} + +//************************************************************************* +// DeInstallDblFltHook() +// +//************************************************************************* +void DeInstallDblFltHook(void) +{ + ENTER_FUNC(); + + MaskIrqs(); + if(OldDblFltHandler) + { + RemoveAllSWBreakpoints(TRUE); + SetGlobalInt(0x08,(ULONG)OldDblFltHandler); + OldDblFltHandler=0; + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} + +// EOF diff --git a/apps/utils/pice/module/dblflt.h b/apps/utils/pice/module/dblflt.h new file mode 100644 index 0000000..a30f38e --- /dev/null +++ b/apps/utils/pice/module/dblflt.h @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + dblflt.h + +Abstract: + + HEADER for dblflt.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void InstallDblFltHook(void); +void DeInstallDblFltHook(void); diff --git a/apps/utils/pice/module/debug.c b/apps/utils/pice/module/debug.c new file mode 100644 index 0000000..44529af --- /dev/null +++ b/apps/utils/pice/module/debug.c @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + debug.c + +Abstract: + + debug output + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 04-Feb-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#ifdef DEBUG +#include "remods.h" + +#include "precomp.h" +#include +#include "serial.h" +#include "serial_port.h" + +#define STANDARD_DEBUG_PREFIX "pICE: " + +//////////////////////////////////////////////////// +// GLOBALS +//// +LONG lDebugLevel = 10; +ULONG ulDebugFlags; +char tempDebug[2048]; +USHORT usDebugPortBase; + +extern BOOLEAN bIsPrintkPatched; +//////////////////////////////////////////////////// +// FUNCTIONS +//// +void DebugSendString(LPSTR s); + + +//************************************************************************* +// Pice_dprintf() +// +// internal debug print +//************************************************************************* +VOID Pice_dprintf(ULONG DebugLevel, PCHAR DebugMessage, ...) +{ + va_list ap; + + va_start(ap, DebugMessage); + if (/*DebugLevel <= lDebugLevel*/ DebugLevel == 2) + { + save_flags(ulDebugFlags); + cli(); + PICE_vsprintf(tempDebug, DebugMessage, ap); + //ei DebugSendString(tempDebug); + Print(OUTPUT_WINDOW, tempDebug); + //DbgPrint("%s", tempDebug); + restore_flags(ulDebugFlags); + } + va_end(ap); +} + +//************************************************************************ +// SendByte() +// +// Output a character to the serial port +//************************************************************************ +BOOLEAN DebugSendByte(UCHAR x) +{ + ULONG timeout; + + timeout = 0x00FFFFL; + + // Wait for transmitter to clear + while ((inportb((USHORT)(usDebugPortBase + LSR)) & XMTRDY) == 0) + if (!(--timeout)) + { + return FALSE; + } + + outportb((USHORT)(usDebugPortBase + TXR), x); + + return TRUE; +} + +///************************************************************************ +// DebugSetSpeed() +// +///************************************************************************ +void DebugSendString(LPSTR s) +{ + ULONG len = PICE_strlen(s),i; + + for(i=0;i> 8) & 0x00FF)); + outportb((USHORT)(usDebugPortBase + LCR), c); // Reset DLAB + +} + +///************************************************************************ +// DebugSetOthers() +// +// Set other communications parameters +//************************************************************************ +void DebugSetOthers(ULONG Parity, ULONG Bits, ULONG StopBit) +{ + ULONG setting; + UCHAR c; + + if (usDebugPortBase == 0) return ; + if (Bits < 5 || Bits > 8) return ; + if (StopBit != 1 && StopBit != 2) return ; + if (Parity != NO_PARITY && Parity != ODD_PARITY && Parity != EVEN_PARITY) + return; + + setting = Bits-5; + setting |= ((StopBit == 1) ? 0x00 : 0x04); + setting |= Parity; + + c = inportb((USHORT)(usDebugPortBase + LCR)); + outportb((USHORT)(usDebugPortBase + LCR), (UCHAR)(c & ~0x80)); // Reset DLAB + + // no ints + outportb((USHORT)(usDebugPortBase + IER), (UCHAR)0); + + outportb((USHORT)(usDebugPortBase + FCR), (UCHAR)0); + + outportb((USHORT)(usDebugPortBase + LCR), (UCHAR)setting); + + outportb((USHORT)(usDebugPortBase + MCR), DTR | RTS); + + + return ; +} + +///************************************************************************ +// DebugSetupSerial() +// +///************************************************************************ +void DebugSetupSerial(ULONG port,ULONG baudrate) +{ + USHORT ports[]={COM1BASE,COM2BASE}; +#if 0 //ei temporary + usDebugPortBase = ports[port-1]; + DebugSetOthers(NO_PARITY,8,1); + DebugSetSpeed(baudrate); +#endif +} +#endif // DEBUG + +// EOF diff --git a/apps/utils/pice/module/debug.h b/apps/utils/pice/module/debug.h new file mode 100644 index 0000000..ab4d27e --- /dev/null +++ b/apps/utils/pice/module/debug.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + debug.h + +Abstract: + + HEADER for debug.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#ifdef DEBUG + +#define ENTER_FUNC() DPRINT((0,"enter "__FUNCTION__"()\n")) + +#define LEAVE_FUNC() DPRINT((0,"leave "__FUNCTION__"()\n")) + +VOID Pice_dprintf(ULONG DebugLevel, PCHAR DebugMessage, ...); +#define DPRINT(arg) Pice_dprintf arg + +#else // DEBUG + +#define ENTER_FUNC() +#define LEAVE_FUNC() + +#define DPRINT(arg) + +#endif // DEBUG diff --git a/apps/utils/pice/module/disassembler.c b/apps/utils/pice/module/disassembler.c new file mode 100644 index 0000000..c268dba --- /dev/null +++ b/apps/utils/pice/module/disassembler.c @@ -0,0 +1,716 @@ +/*++ + +Copyright (c) 2000-2001 Goran Devic +Modified (c) 2001 Klaus P. Gerlicher + +Module Name: + + disassembler.c + +Abstract: + + line disassembler + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Goran Devic + +Revision History: + + 17-Mar-2000: Original (Goran Devic) + 26-Apr-2000: Major rewrite, added coprocessor instructions (Goran Devic) + 04-Nov-2000: Modified for LinIce (Goran Devic) + 05-Jan-2001: Modified for pICE (Klaus P. Gerlicher) + + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +/******************************************************************************* +* Include Files * +******************************************************************************/ +#include "remods.h" +#include "precomp.h" + +#include "disassemblerdata.h" // Include its own data + +/****************************************************************************** +* +* This structure is used to pass parameters and options to the +* line disassembler. +* +******************************************************************************/ +typedef struct +{ + ULONG dwFlags; // Generic flags (described below) + USHORT wSel; // Selector to use to fetch code + UCHAR *bpTarget; // Target pointer to disassemble + UCHAR *szDisasm; // String where to put ascii result + UCHAR Codes[20]; // Buffer where to store code UCHARs + + UCHAR bAsciiLen; // Length of the ascii result + UCHAR bInstrLen; // Instruction lenght in UCHARs + + int nDisplacement; // Scanner: possible constant displacement + int nScanEnum; // Scanner: specific flags SCAN_* + +} TDisassembler; + +// dwFlags contains a set of boolean flags with the following functionality + +#define DIS_DATA32 0x0001 // Data size 16/32 bits (0/1) +#define DIS_GETDATASIZE(flags) ((flags)&DIS_DATA32) +#define DIS_ADDRESS32 0x0002 // Address size 16/32 bits (0/1) +#define DIS_GETADDRSIZE(flags) (((flags)&DIS_ADDRESS32)?1:0) + +#define DIS_SEGOVERRIDE 0x0004 // Default segment has been overriden + +#define DIS_REP 0x0100 // Return: REP prefix found (followed by..) +#define DIS_REPNE 0x0200 // Return: REPNE prefix found +#define DIS_GETREPENUM(flags) (((flags)>>8)&3) +#define DIS_ILLEGALOP 0x8000 // Return: illegal opcode + + +/****************************************************************************** +* * +* Global Variables * +* * +******************************************************************************/ + + +/****************************************************************************** +* * +* External functions (optional) * +* * +******************************************************************************/ + +/****************************************************************************** +* * +* Local Defines, Variables and Macros * +* * +******************************************************************************/ +UCHAR GetUCHAR(ULONG addr) +{ + if(IsAddressValid(addr)) + return *(PUCHAR)addr; + else + return 0x82; // INVALID OPCODE +} + +static UCHAR GetNextUCHAR(USHORT sel, UCHAR *offset, UCHAR *pCode) +{ + pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF; + + return( pCode[0] ); +} + +static USHORT GetNextUSHORT(USHORT sel, UCHAR *offset, UCHAR *pCode) +{ + pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF; + pCode[1] = GetUCHAR((ULONG) offset + 1) & 0xFF; + + return( *(USHORT *) pCode ); +} + +static ULONG GetNextULONG(USHORT sel, UCHAR *offset, UCHAR *pCode) +{ + pCode[0] = GetUCHAR((ULONG) offset + 0) & 0xFF; + pCode[1] = GetUCHAR((ULONG) offset + 1) & 0xFF; + pCode[2] = GetUCHAR((ULONG) offset + 2) & 0xFF; + pCode[3] = GetUCHAR((ULONG) offset + 3) & 0xFF; + + return( *(ULONG *) pCode ); +} + + +#define NEXTUCHAR GetNextUCHAR( pDis->wSel, bpTarget, bpCode); bpCode += 1; bpTarget += 1; bInstrLen += 1 + +#define NEXTUSHORT GetNextUSHORT( pDis->wSel, bpTarget, bpCode); bpCode += 2; bpTarget += 2; bInstrLen += 2 + +#define NEXTULONG GetNextULONG(pDis->wSel, bpTarget, bpCode); bpCode += 4; bpTarget += 4; bInstrLen += 4 + + +/****************************************************************************** +* * +* Functions * +* * +******************************************************************************/ + +/****************************************************************************** +* * +* UCHAR Disassembler( TDisassembler *pDis ); * +* * +******************************************************************************* +* +* This is a generic Intel line disassembler. +* +* Where: +* TDisassembler: +* bpTarget is the address of instruction to disassemble +* szDisasm is the address of the buffer to print a line into +* dwFlags contains the default operand and address bits +* pCode is the address to store code UCHARs (up to 16) +* +* Disassembled instruction is stored as an ASCIIZ string pointed by +* szDisasm pointer (from the pDis structure). +* +* Returns: +* TDisassembler: +* *szDisasm contains the disassembled instruction string +* bAsciiLen is set to the length of the printed string +* bInstrLen is set to instruction length in UCHARs +* dwFlags - has operand and address size flags adjusted +* - DIS_ILLEGALOP set if that was illegal instruction +* UCHAR - instruction length in UCHARs +* +******************************************************************************/ +UCHAR Disassembler( TDisassembler *pDis ) +{ + TOpcodeData *p; // Pointer to a current instruction record + UCHAR *bpTarget; // Pointer to the target code to be disassembled + UCHAR *bpCode; // Pointer to code UCHARs + ULONG arg; // Argument counter + char *sPtr; // Message selection pointer + int nPos; // Printing position in the output string + UCHAR *pArg; // Pointer to record where instruction arguments are + ULONG dwULONG; // Temporary ULONG storage + USHORT wUSHORT; // Temporary USHORT storage + UCHAR bUCHAR; // Temporary UCHAR storage + UCHAR bInstrLen; // Current instruction lenght in UCHARs + UCHAR bOpcode; // Current opcode that is being disassembled + UCHAR bSegOverride; // 0 default segment. >0, segment index + UCHAR bMod=0; // Mod field of the instruction + UCHAR bReg=0; // Register field of the instruction + UCHAR bRm=0; // R/M field of the instruction + UCHAR bW; // Width bit for the register selection + + UCHAR bSib; // S-I-B UCHAR for the instruction + UCHAR bSs; // SS field of the s-i-b UCHAR + UCHAR bIndex; // Index field of the s-i-b UCHAR + UCHAR bBase; // Base field of the s-i-b UCHAR + LPSTR pSymbolName; // used to symbolic name of value + + bInstrLen = 0; // Reset instruction lenght to zero + bSegOverride = 0; // Set default segment (no override) + nPos = 0; // Reset printing position + sPtr = NULL; // Points to no message by default + bpTarget = pDis->bpTarget; // Set internal pointer to a target address + bpCode = pDis->Codes; // Set internal pointer to code UCHARs + + do + { + bOpcode = NEXTUCHAR; // Get the first opcode UCHAR from the target address + p = &Op1[bOpcode]; // Get the address of the instruction record + + if( p->flags & DIS_SPECIAL ) + { + // Opcode is one of the special ones, so do what needs to be done there + + switch( p->name ) + { + case _EscD8: + case _EscD9: + case _EscDA: + case _EscDB: + case _EscDC: + case _EscDD: + case _EscDE: + case _EscDF: // Coprocessor escape: UCHARs D8 - DF + bOpcode = NEXTUCHAR; // Get the modRM UCHAR of the instruction + + if( bOpcode < 0xC0 ) + { + // Opcodes 00-BF use Coproc1 table + + bReg = (bOpcode >> 3) & 7; + p = &Coproc1[ p->name - _EscD8 ][ bReg ]; + + goto StartInstructionParseMODRM; + } + // Opcodes C0-FF use Coproc2 table + + p = &Coproc2[ p->name - _EscD8 ][ bOpcode - 0xC0 ]; + + goto StartInstructionNoMODRM; + + case _S_ES: // Segment override + case _S_CS: + case _S_SS: + case _S_DS: + case _S_FS: + case _S_GS: + bSegOverride = p->name - _S_ES + 1; + continue; + + case _OPSIZ: // Operand size override - toggle + pDis->dwFlags ^= DIS_DATA32; + continue; + + case _ADSIZ: // Address size override - toggle + pDis->dwFlags ^= DIS_ADDRESS32; + continue; + + case _REPNE: // REPNE/REPNZ prefix + pDis->dwFlags |= DIS_REPNE; + continue; + + case _REP: // REP/REPE/REPZ prefix + pDis->dwFlags |= DIS_REP; + continue; + + case _2BESC: // 2 UCHAR escape code 0x0F + bOpcode = NEXTUCHAR; // Get the second UCHAR of the instruction + p = &Op2[bOpcode]; // Get the address of the instruction record + + if( !(p->flags & DIS_SPECIAL) ) goto StartInstruction; + if( p->name < _GRP6 ) goto IllegalOpcode; + + case _GRP1a: // Additional groups of instructions + case _GRP1b: + case _GRP1c: + case _GRP2a: + case _GRP2b: + case _GRP2c: + case _GRP2d: + case _GRP2e: + case _GRP2f: + case _GRP3a: + case _GRP3b: + case _GRP4: + case _GRP5: + case _GRP6: + case _GRP7: + case _GRP8: + case _GRP9: + + bOpcode = NEXTUCHAR; // Get the Mod R/M UCHAR whose... + // bits 3,4,5 select instruction + + bReg = (bOpcode >> 3) & 7; + p = &Groups[p->name - _GRP1a][ bReg ]; + + if( !(p->flags & DIS_SPECIAL) ) goto StartInstructionParseMODRM; + + case _NDEF : // Not defined or illegal opcode + goto IllegalOpcode; + + default :; // Should not happen + } + } + else + goto StartInstruction; + } + while( bInstrLen < 15 ); + +IllegalOpcode: + + nPos += PICE_sprintf( pDis->szDisasm+nPos, "invalid"); + pDis->dwFlags |= DIS_ILLEGALOP; + + goto DisEnd; + +StartInstruction: + + // If this instruction needs additional Mod R/M UCHAR, fetch it + + if( p->flags & DIS_MODRM ) + { + // Get the next UCHAR (modR/M bit field) + bOpcode = NEXTUCHAR; + + bReg = (bOpcode >> 3) & 7; + +StartInstructionParseMODRM: + + // Parse that UCHAR and get mod, reg and rm fields + bMod = bOpcode >> 6; + bRm = bOpcode & 7; + } + +StartInstructionNoMODRM: + + // Print the possible repeat prefix followed by the instruction + + if( p->flags & DIS_COPROC ) + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%-6s ", sCoprocNames[ p->name ]); + else + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%-6s ", + sRep[DIS_GETREPENUM(pDis->dwFlags)], + sNames[ p->name + (DIS_GETNAMEFLAG(p->flags) & DIS_GETDATASIZE(pDis->dwFlags)) ] ); + + // Do instruction argument processing, up to 3 times + + pArg = &p->dest; + + for( arg=p->args; arg!=0; arg--, pArg++, arg? nPos += PICE_sprintf( pDis->szDisasm+nPos,", ") : 0 ) + { + switch( *pArg ) + { + case _Eb : // modR/M used - bW = 0 + bW = 0; + goto _E; + + case _Ev : // modR/M used - bW = 1 + bW = 1; + goto _E; + + case _Ew : // always USHORT size + pDis->dwFlags &= ~DIS_DATA32; + bW = 1; + goto _E; + + case _Ms : // fword ptr (sgdt,sidt,lgdt,lidt) + sPtr = sFwordPtr; + goto _E1; + + case _Mq : // qword ptr (cmpxchg8b) + sPtr = sQwordPtr; + goto _E1; + + case _Mp : // 32 or 48 bit pointer (les,lds,lfs,lss,lgs) + case _Ep : // Always a memory pointer (call, jmp) + if( pDis->dwFlags & DIS_DATA32 ) + sPtr = sFwordPtr; + else + sPtr = sDwordPtr; + goto _E1; + + _E: + // Do registers first so that the rest may be done together + if( bMod == 3 ) + { + // Registers depending on the w field and data size + nPos+=PICE_sprintf(pDis->szDisasm+nPos, "%s", sRegs1[DIS_GETDATASIZE(pDis->dwFlags)][bW][bRm] ); + + break; + } + + if( bW==0 ) + sPtr = sBytePtr; + else + if( pDis->dwFlags & DIS_DATA32 ) + sPtr = sDwordPtr; + else + sPtr = sWordPtr; + + case _M : // Pure memory pointer (lea,invlpg,floats) + if( bMod == 3 ) goto IllegalOpcode; + + _E1: + + if( sPtr ) + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sPtr ); + + case _Ma : // Used by bound instruction, skip the pointer info + + // Print the segment if it is overriden + // + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sSegOverride[ bSegOverride ] ); + + // + // Special case when sib UCHAR is present in 32 address encoding + // + if( (bRm==4) && (pDis->dwFlags & DIS_ADDRESS32) ) + { + // + // Get the s-i-b UCHAR and parse it + // + bSib = NEXTUCHAR; + + bSs = bSib >> 6; + bIndex = (bSib >> 3) & 7; + bBase = bSib & 7; + + // Special case for base=5 && mod==0 -> fetch 32 bit offset + if( (bBase==5) && (bMod==0) ) + { + dwULONG = NEXTULONG; + if(ScanExportsByAddress(&pSymbolName,dwULONG)) + { + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", pSymbolName ); + } + else + { + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%08X", (unsigned int) dwULONG ); + } + } + else + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", sGenReg16_32[ 1 ][ bBase ] ); + + // Scaled index, no index if bIndex is 4 + if( bIndex != 4 ) + nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%s%s", sScale[ bSs ], sGenReg16_32[ 1 ][ bIndex ] ); + else + if(bSs != 0) + nPos += PICE_sprintf( pDis->szDisasm+nPos,"" ); + + // Offset 8 bit or 32 bit + if( bMod == 1 ) + { + bUCHAR = NEXTUCHAR; + if( (signed char)bUCHAR < 0 ) + nPos += PICE_sprintf( pDis->szDisasm+nPos,"-%02X", 0-(signed char)bUCHAR ); + else + nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%02X", bUCHAR ); + } + + if( bMod == 2 ) + { + dwULONG = NEXTULONG; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%08X", (unsigned int) dwULONG ); + } + + // Wrap up the instruction + nPos += PICE_sprintf( pDis->szDisasm+nPos,"]" ); + break; + } + + // + // 16 or 32 address bit cases with mod zero, one or two + // + // Special cases when r/m is 5 and mod is 0, immediate d16 or d32 + if( bMod==0 && ((bRm==6 && !(pDis->dwFlags & DIS_ADDRESS32)) || (bRm==5 && (pDis->dwFlags & DIS_ADDRESS32))) ) + { + if( pDis->dwFlags & DIS_ADDRESS32 ) + { + dwULONG = NEXTULONG; + if(ScanExportsByAddress(&pSymbolName,dwULONG)) + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s]", pSymbolName ); + else + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%08X]", (unsigned int) dwULONG ); + } + else + { + wUSHORT = NEXTUSHORT; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%04X]", wUSHORT ); + } + + break; + } + + // Print the start of the line + nPos += PICE_sprintf( pDis->szDisasm+nPos,"[%s", sAdr1[DIS_GETADDRSIZE(pDis->dwFlags)][ bRm ] ); + + // Offset (8 or 16) or (8 or 32) bit - 16, 32 bits are unsigned + if( bMod==1 ) + { + bUCHAR = NEXTUCHAR; + if( (signed char)bUCHAR < 0 ) + nPos += PICE_sprintf( pDis->szDisasm+nPos,"-%02X", 0-(signed char)bUCHAR ); + else + nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%02X", bUCHAR ); + } + + if( bMod==2 ) + { + if( pDis->dwFlags & DIS_ADDRESS32 ) + { + dwULONG = NEXTULONG; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%08X", (unsigned int) dwULONG ); + } + else + { + wUSHORT = NEXTUSHORT; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"+%04X", wUSHORT ); + } + } + + // Wrap up the instruction + nPos += PICE_sprintf( pDis->szDisasm+nPos,"]" ); + + break; + + case _Gb : // general, UCHAR register + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sRegs1[0][0][ bReg ] ); + break; + + case _Gv : // general, (d)USHORT register + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[DIS_GETDATASIZE(pDis->dwFlags)][ bReg ] ); + break; + + case _Yb : // ES:(E)DI pointer + case _Yv : + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%s", sSegOverrideDefaultES[ bSegOverride ], sYptr[DIS_GETADDRSIZE(pDis->dwFlags)] ); + break; + + case _Xb : // DS:(E)SI pointer + case _Xv : + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s%s", sSegOverrideDefaultDS[ bSegOverride ], sXptr[DIS_GETADDRSIZE(pDis->dwFlags)] ); + break; + + case _Rd : // general register double USHORT + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[ 1 ][ bRm ] ); + break; + + case _Rw : // register USHORT + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[ 0 ][ bMod ] ); + break; + + case _Sw : // segment register + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sSeg[ bReg ] ); + break; + + case _Cd : // control register + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sControl[ bReg ] ); + break; + + case _Dd : // debug register + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sDebug[ bReg ] ); + break; + + case _Td : // test register + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sTest[ bReg ] ); + break; + + + case _Jb : // immediate UCHAR, relative offset + bUCHAR = NEXTUCHAR; + nPos += PICE_sprintf( pDis->szDisasm+nPos, "short %08X", (unsigned int)(pDis->bpTarget + (signed char)bUCHAR + bInstrLen) ); + break; + + case _Jv : // immediate USHORT or ULONG, relative offset + if( pDis->dwFlags & DIS_DATA32 ) + { + dwULONG = NEXTULONG; + if(ScanExportsByAddress(&pSymbolName,(unsigned int)(pDis->bpTarget + (signed long)dwULONG + bInstrLen))) + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", pSymbolName ); + else + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int)(pDis->bpTarget + (signed long)dwULONG + bInstrLen) ); + } + else + { + wUSHORT = NEXTUSHORT; + if(ScanExportsByAddress(&pSymbolName,(unsigned int)(pDis->bpTarget + (signed short)wUSHORT + bInstrLen))) + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", pSymbolName ); + else + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int)(pDis->bpTarget + (signed short)wUSHORT + bInstrLen) ); + } + break; + + case _O : // Simple USHORT or ULONG offset + if( pDis->dwFlags & DIS_ADDRESS32 ) // depending on the address size + { + dwULONG = NEXTULONG; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s[%08X]", sSegOverride[ bSegOverride ], (unsigned int) dwULONG ); + } + else + { + wUSHORT = NEXTUSHORT; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s[%04X]", sSegOverride[ bSegOverride ], wUSHORT ); + } + break; + + case _Ib : // immediate UCHAR + bUCHAR = NEXTUCHAR; + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%02X", bUCHAR ); + break; + + case _Iv : // immediate USHORT or ULONG + if( pDis->dwFlags & DIS_DATA32 ) + { + dwULONG = NEXTULONG; + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int) dwULONG ); + } + else + { + wUSHORT = NEXTUSHORT; + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X", wUSHORT ); + } + break; + + case _Iw : // Immediate USHORT + wUSHORT = NEXTUSHORT; + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X", wUSHORT ); + break; + + case _Ap : // 32 bit or 48 bit pointer (call far, jump far) + if( pDis->dwFlags & DIS_DATA32 ) + { + dwULONG = NEXTULONG; + wUSHORT = NEXTUSHORT; + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%04X:%08X", wUSHORT, (unsigned int) dwULONG ); + } + else + { + dwULONG = NEXTULONG; + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%08X", (unsigned int) dwULONG ); + } + break; + + case _1 : // numerical 1 + nPos += PICE_sprintf( pDis->szDisasm+nPos,"1" ); + break; + + case _3 : // numerical 3 + nPos += PICE_sprintf( pDis->szDisasm+nPos,"3" ); + break; + + // Hard coded registers + case _DX: case _AL: case _AH: case _BL: case _BH: case _CL: case _CH: + case _DL: case _DH: case _CS: case _DS: case _ES: case _SS: case _FS: + case _GS: + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sRegs2[ *pArg - _DX ] ); + break; + + case _eAX: case _eBX: case _eCX: case _eDX: + case _eSP: case _eBP: case _eSI: case _eDI: + nPos += PICE_sprintf( pDis->szDisasm+nPos, "%s", sGenReg16_32[DIS_GETDATASIZE(pDis->dwFlags)][ *pArg - _eAX ]); + break; + + case _ST: // Coprocessor ST + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sST[9] ); + break; + + case _ST0: // Coprocessor ST(0) - ST(7) + case _ST1: + case _ST2: + case _ST3: + case _ST4: + case _ST5: + case _ST6: + case _ST7: + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sST[ *pArg - _ST0 ] ); + break; + + case _AX: // Coprocessor AX + nPos += PICE_sprintf( pDis->szDisasm+nPos,"%s", sGenReg16_32[0][0] ); + break; + } + } + +DisEnd: + + // Set the returning values and return with the bInstrLen field + + pDis->bAsciiLen = (UCHAR) nPos; + pDis->bInstrLen = bInstrLen; + + return bInstrLen; +} + +/****************************************************************************** +* * +* BOOLEAN Disasm(PULONG pOffset,PUCHAR pchDst) * +* * +* entry point for disassembly from other modules * +******************************************************************************/ +BOOLEAN Disasm(PULONG pOffset,PUCHAR pchDst) +{ + TDisassembler dis; + + dis.dwFlags = DIS_DATA32 | DIS_ADDRESS32; + dis.bpTarget = (UCHAR*)*pOffset; + dis.szDisasm = pchDst; + dis.wSel = CurrentCS; + + *pOffset += (ULONG)Disassembler( &dis); + return TRUE; +} \ No newline at end of file diff --git a/apps/utils/pice/module/disassembler.h b/apps/utils/pice/module/disassembler.h new file mode 100644 index 0000000..de50369 --- /dev/null +++ b/apps/utils/pice/module/disassembler.h @@ -0,0 +1,159 @@ + /* Operand and instruction types */ +#define OP_REG 0x100 /* register */ +#define OP_IMM 0x200 /* immediate value */ +#define OP_IND 0x300 /* indirect memory reference */ +#define OP_BPTR 0x400 /* BYTE Pointer */ +#define OP_WPTR 0x500 /* WORD Pointer */ +#define OP_DPTR 0x600 /* DWORD Pointer */ +#define OP_UNK 0x900 +//#define INS_INVALID 0x00 /* Not a valid instruction */ + /* Branch Instruction types */ +#define INS_BRANCH 0x01 /* Unconditional branch */ +#define INS_COND 0x02 /* Conditional branch */ +#define INS_SUB 0x04 /* Jump to subroutine */ +#define INS_RET 0x08 /* Return from subroutine */ + /* modify ( 'w' ) instructions */ +#define INS_ARITH 0x10 /* Arithmetic inst */ +#define INS_LOGIC 0x20 /* logical inst */ +#define INS_FPU 0x40 /* Floating Point inst */ +#define INS_FLAG 0x80 /* Modify flags */ + /* misc Instruction Types */ +#define INS_MOVE 0x0100 +#define INS_ARRAY 0x0200 /* String and XLAT ops */ +#define INS_PTR 0x0400 /* Load EA/pointer */ +#define INS_STACK 0x1000 /* PUSH, POP, etc */ +#define INS_FRAME 0x2000 /* ENTER, LEAVE, etc */ +#define INS_SYSTEM 0x4000 /* CPUID, WBINVD, etc */ + +/* Other info */ +#define BIG_ENDIAN_ORDER 0 +#define LITTLE_ENDIAN_ORDER 1 + +struct code { /* size 100 */ + unsigned long rva; + unsigned short flags; + char mnemonic[16]; + char dest[32]; + char src[32]; + char aux[32]; + int mnemType; + int destType; + int srcType; + int auxType; +}; + +/* struct used in Init routine */ +struct CPU_TYPE{ + char vendor; + char model[12]; +}; + +#define cpu_80386 0x01 +#define cpu_80486 0x02 +#define cpu_PENTIUM 0x04 +#define cpu_PENTMMX 0x08 +#define cpu_PENTPRO 0x10 +#define cpu_PENTIUM2 0x20 +#define cpu_PENTIUM3 0x40 +#define cpu_PENTIUM4 0x80 + +#define FLAGS_MODRM 0x00001 //contains mod r/m byte +#define FLAGS_8BIT 0x00002 //force 8-bit arguments +#define FLAGS_16BIT 0x00004 //force 16-bit arguments +#define FLAGS_32BIT 0x00008 //force 32-bit arguments +#define FLAGS_REAL 0x00010 //real mode only +#define FLAGS_PMODE 0x00020 //protected mode only +#define FLAGS_PREFIX 0x00040 //for lock and rep prefix +#define FLAGS_MMX 0x00080 //mmx instruction/registers +#define FLAGS_FPU 0x00100 //fpu instruction/registers +#define FLAGS_CJMP 0x00200 //codeflow - conditional jump +#define FLAGS_JMP 0x00400 //codeflow - jump +#define FLAGS_IJMP 0x00800 //codeflow - indexed jump +#define FLAGS_CALL 0x01000 //codeflow - call +#define FLAGS_ICALL 0x02000 //codeflow - indexed call +#define FLAGS_RET 0x04000 //codeflow - return +#define FLAGS_SEGPREFIX 0x08000 //segment prefix +#define FLAGS_OPERPREFIX 0x10000 //operand prefix +#define FLAGS_ADDRPREFIX 0x20000 //address prefix +#define FLAGS_OMODE16 0x40000 //16-bit operand mode only +#define FLAGS_OMODE32 0x80000 //32-bit operand mode only + +enum argtype { + ARG_REG=1,ARG_IMM,ARG_NONE,ARG_MODRM,ARG_REG_AX, + ARG_REG_ES,ARG_REG_CS,ARG_REG_SS,ARG_REG_DS,ARG_REG_FS,ARG_REG_GS,ARG_REG_BX, + ARG_REG_CX,ARG_REG_DX, + ARG_REG_SP,ARG_REG_BP,ARG_REG_SI,ARG_REG_DI,ARG_IMM8,ARG_RELIMM8,ARG_FADDR,ARG_REG_AL, + ARG_MEMLOC,ARG_SREG,ARG_RELIMM,ARG_16REG_DX,ARG_REG_CL,ARG_REG_DL,ARG_REG_BL,ARG_REG_AH, + ARG_REG_CH,ARG_REG_DH,ARG_REG_BH,ARG_MODREG,ARG_CREG,ARG_DREG,ARG_TREG_67,ARG_TREG, + ARG_MREG,ARG_MMXMODRM,ARG_MODRM8,ARG_IMM_1,ARG_MODRM_FPTR,ARG_MODRM_S,ARG_MODRMM512, + ARG_MODRMQ,ARG_MODRM_SREAL,ARG_REG_ST0,ARG_FREG,ARG_MODRM_PTR,ARG_MODRM_WORD,ARG_MODRM_SINT, + ARG_MODRM_EREAL,ARG_MODRM_DREAL,ARG_MODRM_WINT,ARG_MODRM_LINT,ARG_REG_BC,ARG_REG_DE, + ARG_REG_HL,ARG_REG_DE_IND,ARG_REG_HL_IND,ARG_REG_BC_IND,ARG_REG_SP_IND,ARG_REG_A, + ARG_REG_B,ARG_REG_C,ARG_REG_D,ARG_REG_E,ARG_REG_H,ARG_REG_L,ARG_IMM16,ARG_REG_AF, + ARG_REG_AF2,ARG_MEMLOC16,ARG_IMM8_IND,ARG_BIT,ARG_REG_IX,ARG_REG_IX_IND,ARG_REG_IY, + ARG_REG_IY_IND,ARG_REG_C_IND,ARG_REG_I,ARG_REG_R,ARG_IMM16_A,ARG_MODRM16,ARG_SIMM8, + ARG_IMM32,ARG_STRING,ARG_MODRM_BCD,ARG_PSTRING,ARG_DOSSTRING,ARG_CUNICODESTRING, + ARG_PUNICODESTRING,ARG_NONEBYTE,ARG_XREG,ARG_XMMMODRM}; + +typedef struct x86_inst { + int flags; + int destType, srcType, auxType; + int cpu_type; + int inst_type; + char *mnem; + char *dest, *src, *aux; +} instr; + + +#define GENREG_8 0x0001 +#define GENREG_16 0x0002 +#define GENREG_32 0x0004 +#define SEGREG 0x0008 +#define MMXREG 0x0010 +#define SIMDREG 0x0020 +#define DEBUGREG 0x0040 +#define CONTROLREG 0x0080 +#define TESTREG 0x0100 + +#define NO_REG 0x100 +#define DIRECT_REG 0x200 +#define NO_BASE 0x400 +#define NO_INDEX 0x800 +#define DISP8 0x1000 +#define DISP32 0x2000 +#define HAS_SIB 0x4000 +#define HAS_MODRM 0x8000 + +struct OPERAND { //arg1, arg2, arg3 + char * str; //temporary buffer for building arg text + int type; //argument type + int * flag; //pointer to CODE arg flags + char * text; //pointer to CODE arg text +}; + +struct EA { //effective address [SIB/disp] + int mode, flags; + int mod, rm, reg; + long disp; + char sib[32]; +}; + +struct modRM_byte { + unsigned int mod : 2; + unsigned int reg : 3; + unsigned int rm : 3; +}; + +struct SIB_byte { + unsigned int scale : 2; + unsigned int index : 3; + unsigned int base : 3; +}; + +typedef struct x86_table { //Assembly instruction tables + instr *table; //Pointer to table of instruction encodings + char divisor; // number to divide by for look up + char mask; // bit mask for look up + char minlim,maxlim; // limits on min/max entries. + char modrmpos; // modrm byte position plus +} asmtable; diff --git a/apps/utils/pice/module/disassemblerdata.h b/apps/utils/pice/module/disassemblerdata.h new file mode 100644 index 0000000..1aa46a3 --- /dev/null +++ b/apps/utils/pice/module/disassemblerdata.h @@ -0,0 +1,1802 @@ +/*++ + +Copyright (c) 2000-2001 Goran Devic +Modified (c) 2001 Klaus P. Gerlicher + +Module Name: + + disassembler.h + +Abstract: + + header for disassembler.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Goran Devic + +Revision History: + + 17-Mar-2000: Original (Goran Devic) + 05-Jan-2001: Modified for pICE (Klaus P. Gerlicher) + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +BUGS: + There is no segment override for _Ap (look the code) +--*/ + + +/****************************************************************************** +* * +* Include Files * +* * +******************************************************************************/ + +#include "disassemblerdefines.h" // Include its own defines + +/****************************************************************************** +* * +* Define opcode names as ASCIIZ strings * +* * +******************************************************************************/ +char* sNames[] = { +"", /* 0X000 */ +"AAA", /* 0X001 */ +"AAD", /* 0X002 */ +"AAM", /* 0X003 */ +"AAS", /* 0X004 */ +"ADC", /* 0X005 */ +"ADD", /* 0X006 */ +"AND", /* 0X007 */ +"ARPL", /* 0X008 */ +"BOUND", /* 0X009 */ +"BSF", /* 0X00A */ +"BSR", /* 0X00B */ +"BT", /* 0X00C */ +"BTC", /* 0X00D */ +"BTR", /* 0X00E */ +"BTS", /* 0X00F */ +"CALL", /* 0X010 */ +"CBW", /* 0X011 */ +"CWDE", /* 0X012 */ +"CLC", /* 0X013 */ +"CLD", /* 0X014 */ +"CLI", /* 0X015 */ +"CLTS", /* 0X016 */ +"CMC", /* 0X017 */ +"CMP", /* 0X018 */ +"CMPS", /* 0X019 */ +"CMPSB", /* 0X01A */ +"CMPSW", /* 0X01B */ +"CMPSD", /* 0X01C */ +"CWD", /* 0X01D */ +"CDQ", /* 0X01E */ +"DAA", /* 0X01F */ +"DAS", /* 0X020 */ +"DEC", /* 0X021 */ +"DIV", /* 0X022 */ +"ENTER", /* 0X023 */ +"HLT", /* 0X024 */ +"IDIV", /* 0X025 */ +"IMUL", /* 0X026 */ +"IN", /* 0X027 */ +"INC", /* 0X028 */ +"INS", /* 0X029 */ +"INSB", /* 0X02A */ +"INSW", /* 0X02B */ +"INSD", /* 0X02C */ +"INT", /* 0X02D */ +"INTO", /* 0X02E */ +"IRET", /* 0X02F */ +"IRETD", /* 0X030 */ +"JO", /* 0X031 */ +"JNO", /* 0X032 */ +"JB", /* 0X033 */ +"JNB", /* 0X034 */ +"JZ", /* 0X035 */ +"JNZ", /* 0X036 */ +"JBE", /* 0X037 */ +"JNBE", /* 0X038 */ +"JS", /* 0X039 */ +"JNS", /* 0X03A */ +"JP", /* 0X03B */ +"JNP", /* 0X03C */ +"JL", /* 0X03D */ +"JNL", /* 0X03E */ +"JLE", /* 0X03F */ +"JNLE", /* 0X040 */ +"JMP", /* 0X041 */ +"LAHF", /* 0X042 */ +"LAR", /* 0X043 */ +"LEA", /* 0X044 */ +"LEAVE", /* 0X045 */ +"LGDT", /* 0X046 */ +"LIDT", /* 0X047 */ +"LGS", /* 0X048 */ +"LSS", /* 0X049 */ +"LDS", /* 0X04A */ +"LES", /* 0X04B */ +"LFS", /* 0X04C */ +"LLDT", /* 0X04D */ +"LMSW", /* 0X04E */ +"LOCK", /* 0X04F */ +"LODS", /* 0X050 */ +"LODSB", /* 0X051 */ +"LODSW", /* 0X052 */ +"LODSD", /* 0X053 */ +"LOOP", /* 0X054 */ +"LOOPE", /* 0X055 */ +"LOOPZ", /* 0X056 */ +"LOOPNE", /* 0X057 */ +"LOOPNZ", /* 0X058 */ +"LSL", /* 0X059 */ +"LTR", /* 0X05A */ +"MOV", /* 0X05B */ +"MOVS", /* 0X05C */ +"MOVSB", /* 0X05D */ +"MOVSW", /* 0X05E */ +"MOVSD", /* 0X05F */ +"MOVSX", /* 0X060 */ +"MOVZX", /* 0X061 */ +"MUL", /* 0X062 */ +"NEG", /* 0X063 */ +"NOP", /* 0X064 */ +"NOT", /* 0X065 */ +"OR", /* 0X066 */ +"OUT", /* 0X067 */ +"OUTS", /* 0X068 */ +"OUTSB", /* 0X069 */ +"OUTSW", /* 0X06A */ +"OUTSD", /* 0X06B */ +"POP", /* 0X06C */ +"POPA", /* 0X06D */ +"POPAD", /* 0X06E */ +"POPF", /* 0X06F */ +"POPFD", /* 0X070 */ +"PUSH", /* 0X071 */ +"PUSHA", /* 0X072 */ +"PUSHAD", /* 0X073 */ +"PUSHF", /* 0X074 */ +"PUSHFD", /* 0X075 */ +"RCL", /* 0X076 */ +"RCR", /* 0X077 */ +"ROL", /* 0X078 */ +"ROR", /* 0X079 */ +"REP", /* 0X07A */ +"REPE", /* 0X07B */ +"REPZ", /* 0X07C */ +"REPNE", /* 0X07D */ +"REPNZ", /* 0X07E */ +"RET", /* 0X07F */ +"SAHF", /* 0X080 */ +"SAL", /* 0X081 */ +"SAR", /* 0X082 */ +"SHL", /* 0X083 */ +"SHR", /* 0X084 */ +"SBB", /* 0X085 */ +"SCAS", /* 0X086 */ +"SCASB", /* 0X087 */ +"SCASW", /* 0X088 */ +"SCASD", /* 0X089 */ +"SET", /* 0X08A */ +"SGDT", /* 0X08B */ +"SIDT", /* 0X08C */ +"SHLD", /* 0X08D */ +"SHRD", /* 0X08E */ +"SLDT", /* 0X08F */ +"SMSW", /* 0X090 */ +"STC", /* 0X091 */ +"STD", /* 0X092 */ +"STI", /* 0X093 */ +"STOS", /* 0X094 */ +"STOSB", /* 0X095 */ +"STOSW", /* 0X096 */ +"STOSD", /* 0X097 */ +"STR", /* 0X098 */ +"SUB", /* 0X099 */ +"TEST", /* 0X09A */ +"VERR", /* 0X09B */ +"VERW", /* 0X09C */ +"WAIT", /* 0X09D */ +"XCHG", /* 0X09E */ +"XLAT", /* 0X09F */ +"XLATB", /* 0X0A0 */ +"XOR", /* 0X0A1 */ +"JCXZ", /* 0X0A2 */ +"LOADALL", /* 0X0A3 */ +"INVD", /* 0X0A4 */ +"WBINVD", /* 0X0A5 */ +"SETO", /* 0X0A6 */ +"SETNO", /* 0X0A7 */ +"SETB", /* 0X0A8 */ +"SETNB", /* 0X0A9 */ +"SETZ", /* 0X0AA */ +"SETNZ", /* 0X0AB */ +"SETBE", /* 0X0AC */ +"SETNBE", /* 0X0AD */ +"SETS", /* 0X0AE */ +"SETNS", /* 0X0AF */ +"SETP", /* 0X0B0 */ +"SETNP", /* 0X0B1 */ +"SETL", /* 0X0B2 */ +"SETNL", /* 0X0B3 */ +"SETLE", /* 0X0B4 */ +"SETNLE", /* 0X0B5 */ +"WRMSR", /* 0X0B6 */ +"RDTSC", /* 0X0B7 */ +"RDMSR", /* 0X0B8 */ +"CPUID", /* 0X0B9 */ +"RSM", /* 0X0BA */ +"CMPXCHG", /* 0X0BB */ +"XADD", /* 0X0BC */ +"BSWAP", /* 0X0BD */ +"INVLPG", /* 0X0BE */ +"CMPXCHG8B", /* 0X0BF */ +"JMP FAR", /* 0X0C0 */ +"RETF", /* 0X0C1 */ +"RDPMC" /* 0X0C2 */ +}; + + +char* sCoprocNames[] = { +"", /* 0X000 */ +"F2XM1", /* 0X001 */ +"FABS", /* 0X002 */ +"FADD", /* 0X003 */ +"FADDP", /* 0X004 */ +"FBLD", /* 0X005 */ +"FBSTP", /* 0X006 */ +"FCHS", /* 0X007 */ +"FCLEX", /* 0X008 */ +"FCOM", /* 0X009 */ +"FCOMP", /* 0X00A */ +"FCOMPP", /* 0X00B */ +"FCOS", /* 0X00C */ +"FDECSTP", /* 0X00D */ +"FDIV", /* 0X00E */ +"FDIVP", /* 0X00F */ +"FDIVR", /* 0X010 */ +"FDIVRP", /* 0X011 */ +"FFREE", /* 0X012 */ +"FIADD", /* 0X013 */ +"FICOM", /* 0X014 */ +"FICOMP", /* 0X015 */ +"FIDIV", /* 0X016 */ +"FIDIVR", /* 0X017 */ +"FILD", /* 0X018 */ +"FIMUL", /* 0X019 */ +"FINCSTP", /* 0X01A */ +"FINIT", /* 0X01B */ +"FIST", /* 0X01C */ +"FISTP", /* 0X01D */ +"FISUB", /* 0X01E */ +"FISUBR", /* 0X01F */ +"FLD", /* 0X020 */ +"FLD1", /* 0X021 */ +"FLDCW", /* 0X022 */ +"FLDENV", /* 0X023 */ +"FLDL2E", /* 0X024 */ +"FLDL2T", /* 0X025 */ +"FLDLG2", /* 0X026 */ +"FLDLN2", /* 0X027 */ +"FLDPI", /* 0X028 */ +"FLDZ", /* 0X029 */ +"FMUL", /* 0X02A */ +"FMULP", /* 0X02B */ +"FNOP", /* 0X02C */ +"FPATAN", /* 0X02D */ +"FPREM", /* 0X02E */ +"FPREM1", /* 0X02F */ +"FPTAN", /* 0X030 */ +"FRNDINT", /* 0X031 */ +"FRSTOR", /* 0X032 */ +"FSAVE", /* 0X033 */ +"FSCALE", /* 0X034 */ +"FSIN", /* 0X035 */ +"FSINCOS", /* 0X036 */ +"FSQRT", /* 0X037 */ +"FST", /* 0X038 */ +"FSTCW", /* 0X039 */ +"FSTENV", /* 0X03A */ +"FSTP", /* 0X03B */ +"FSTSW", /* 0X03C */ +"FSUB", /* 0X03D */ +"FSUBP", /* 0X03E */ +"FSUBR", /* 0X03F */ +"FSUBRP", /* 0X040 */ +"FTST", /* 0X041 */ +"FUCOM", /* 0X042 */ +"FUCOMP", /* 0X043 */ +"FUCOMPP", /* 0X044 */ +"FXAM", /* 0X045 */ +"FXCH", /* 0X046 */ +"FXTRACT", /* 0X047 */ +"FYL2X", /* 0X048 */ +"FYL2XP1" /* 0X049 */ +}; + + +/****************************************************************************** +* +* Table of the first byte of an instruction +* +******************************************************************************/ +TOpcodeData Op1[ 256 ] = { +{ /* 00 */ _add ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 01 */ _add ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 02 */ _add ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 03 */ _add ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 04 */ _add ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 05 */ _add ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 06 */ _push ,1 ,_ES ,0 ,0 ,0 ,0, 0 }, +{ /* 07 */ _pop ,1 ,_ES ,0 ,0 ,0 ,0, 0 }, +{ /* 08 */ _or ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 09 */ _or ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0A */ _or ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 0B */ _or ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 0C */ _or ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 0D */ _or ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 0E */ _push ,1 ,_CS ,0 ,0 ,0 ,0, 0 }, +{ /* 0F */ _2BESC ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 10 */ _adc ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 11 */ _adc ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 12 */ _adc ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 13 */ _adc ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 14 */ _adc ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 15 */ _adc ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 16 */ _push ,1 ,_SS ,0 ,0 ,0 ,0, 0 }, +{ /* 17 */ _pop ,1 ,_SS ,0 ,0 ,0 ,0, 0 }, +{ /* 18 */ _sbb ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 19 */ _sbb ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 1A */ _sbb ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 1B */ _sbb ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 1C */ _sbb ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 1D */ _sbb ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 1E */ _push ,1 ,_DS ,0 ,0 ,0 ,0, 0 }, +{ /* 1F */ _pop ,1 ,_DS ,0 ,0 ,0 ,0, 0 }, + +{ /* 20 */ _and ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 21 */ _and ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 22 */ _and ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 23 */ _and ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 24 */ _and ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 25 */ _and ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 26 */ _S_ES ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 27 */ _daa ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 28 */ _sub ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 29 */ _sub ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 2A */ _sub ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 2B */ _sub ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 2C */ _sub ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 2D */ _sub ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 2E */ _S_CS ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 2F */ _das ,0 ,0 ,0 ,0 ,0 ,0, 0 }, + +{ /* 30 */ _xor ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 31 */ _xor ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 32 */ _xor ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 33 */ _xor ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 34 */ _xor ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 35 */ _xor ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 36 */ _S_SS ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 37 */ _aaa ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 38 */ _cmp ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 39 */ _cmp ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 3A */ _cmp ,2 ,_Gb ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 3B */ _cmp ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 3C */ _cmp ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* 3D */ _cmp ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* 3E */ _S_DS ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 3F */ _aas ,0 ,0 ,0 ,0 ,0 ,0, 0 }, + +{ /* 40 */ _inc ,1 ,_eAX,0 ,0 ,0 ,0, 0 }, +{ /* 41 */ _inc ,1 ,_eCX,0 ,0 ,0 ,0, 0 }, +{ /* 42 */ _inc ,1 ,_eDX,0 ,0 ,0 ,0, 0 }, +{ /* 43 */ _inc ,1 ,_eBX,0 ,0 ,0 ,0, 0 }, +{ /* 44 */ _inc ,1 ,_eSP,0 ,0 ,0 ,0, 0 }, +{ /* 45 */ _inc ,1 ,_eBP,0 ,0 ,0 ,0, 0 }, +{ /* 46 */ _inc ,1 ,_eSI,0 ,0 ,0 ,0, 0 }, +{ /* 47 */ _inc ,1 ,_eDI,0 ,0 ,0 ,0, 0 }, +{ /* 48 */ _dec ,1 ,_eAX,0 ,0 ,0 ,0, 0 }, +{ /* 49 */ _dec ,1 ,_eCX,0 ,0 ,0 ,0, 0 }, +{ /* 4A */ _dec ,1 ,_eDX,0 ,0 ,0 ,0, 0 }, +{ /* 4B */ _dec ,1 ,_eBX,0 ,0 ,0 ,0, 0 }, +{ /* 4C */ _dec ,1 ,_eSP,0 ,0 ,0 ,0, 0 }, +{ /* 4D */ _dec ,1 ,_eBP,0 ,0 ,0 ,0, 0 }, +{ /* 4E */ _dec ,1 ,_eSI,0 ,0 ,0 ,0, 0 }, +{ /* 4F */ _dec ,1 ,_eDI,0 ,0 ,0 ,0, 0 }, + +{ /* 50 */ _push ,1 ,_eAX,0 ,0 ,0 ,0, 0 }, +{ /* 51 */ _push ,1 ,_eCX,0 ,0 ,0 ,0, 0 }, +{ /* 52 */ _push ,1 ,_eDX,0 ,0 ,0 ,0, 0 }, +{ /* 53 */ _push ,1 ,_eBX,0 ,0 ,0 ,0, 0 }, +{ /* 54 */ _push ,1 ,_eSP,0 ,0 ,0 ,0, 0 }, +{ /* 55 */ _push ,1 ,_eBP,0 ,0 ,0 ,0, 0 }, +{ /* 56 */ _push ,1 ,_eSI,0 ,0 ,0 ,0, 0 }, +{ /* 57 */ _push ,1 ,_eDI,0 ,0 ,0 ,0, 0 }, +{ /* 58 */ _pop ,1 ,_eAX,0 ,0 ,0 ,0, 0 }, +{ /* 59 */ _pop ,1 ,_eCX,0 ,0 ,0 ,0, 0 }, +{ /* 5A */ _pop ,1 ,_eDX,0 ,0 ,0 ,0, 0 }, +{ /* 5B */ _pop ,1 ,_eBX,0 ,0 ,0 ,0, 0 }, +{ /* 5C */ _pop ,1 ,_eSP,0 ,0 ,0 ,0, 0 }, +{ /* 5D */ _pop ,1 ,_eBP,0 ,0 ,0 ,0, 0 }, +{ /* 5E */ _pop ,1 ,_eSI,0 ,0 ,0 ,0, 0 }, +{ /* 5F */ _pop ,1 ,_eDI,0 ,0 ,0 ,0, 0 }, + +{ /* 60 */ _pusha ,0 ,0 ,0 ,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* 61 */ _popa ,0 ,0 ,0 ,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* 62 */ _bound ,2 ,_Gv ,_Ma ,0 ,0 ,0, DIS_MODRM }, +{ /* 63 */ _arpl ,2 ,_Ew ,_Rw ,0 ,0 ,0, DIS_MODRM }, +{ /* 64 */ _S_FS ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 65 */ _S_GS ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 66 */ _OPSIZ ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 67 */ _ADSIZ ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 68 */ _push ,1 ,_Iv ,0 ,0 ,0 ,0, 0 }, +{ /* 69 */ _imul ,2 ,_Gv ,_Ev ,_Iv ,0 ,0, DIS_MODRM }, +{ /* 6A */ _push ,1 ,_Ib ,0 ,0 ,0 ,0, 0 }, +{ /* 6B */ _imul ,3 ,_Gv ,_Ev ,_Ib ,0 ,0, DIS_MODRM }, +{ /* 6C */ _insb ,2 ,_Yb ,_DX ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 6D */ _insw ,2 ,_Yv ,_DX ,0 ,0 ,0, SCAN_TERMINATING | DIS_NAME_FLAG }, +{ /* 6E */ _outsb ,2 ,_DX ,_Xb ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 6F */ _outsw ,2 ,_DX ,_Xv ,0 ,0 ,0, SCAN_TERMINATING | DIS_NAME_FLAG }, + +{ /* 70 */ _jo ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 71 */ _jno ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 72 */ _jb ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 73 */ _jnb ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 74 */ _jz ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 75 */ _jnz ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 76 */ _jbe ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 77 */ _jnbe ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 78 */ _js ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 79 */ _jns ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 7A */ _jp ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 7B */ _jnp ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 7C */ _jl ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 7D */ _jnl ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 7E */ _jle ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 7F */ _jnle ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, + +{ /* 80 */ _GRP1a ,2 ,_Eb ,_Ib ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 81 */ _GRP1b ,2 ,_Ev ,_Iv ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 82 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 83 */ _GRP1c ,2 ,_Ev ,_Ib ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 84 */ _test ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 85 */ _test ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 86 */ _xchg ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 87 */ _xchg ,2 ,_Ev ,_Gv ,0 ,0 ,INSTR_READ_WRITE | INSTR_WORD_DWORD, DIS_MODRM }, +{ /* 88 */ _mov ,2 ,_Eb ,_Gb ,0 ,0 ,INSTR_WRITE | INSTR_BYTE, DIS_MODRM }, +{ /* 89 */ _mov ,2 ,_Ev ,_Gv ,0 ,0 ,INSTR_WRITE | INSTR_WORD, DIS_MODRM }, +{ /* 8A */ _mov ,2 ,_Gb ,_Eb ,0 ,0 ,INSTR_READ | INSTR_BYTE, DIS_MODRM }, +{ /* 8B */ _mov ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 8C */ _mov ,2 ,_Ew ,_Sw ,0 ,0 ,0, DIS_MODRM }, +{ /* 8D */ _lea ,2 ,_Gv ,_M ,0 ,0 ,0, DIS_MODRM }, +{ /* 8E */ _mov ,2 ,_Sw ,_Ew ,0 ,0 ,0, SCAN_TERM_PMODE | DIS_MODRM }, +{ /* 8F */ _pop ,1 ,_Ev ,0 ,0 ,0 ,0, DIS_MODRM }, + +{ /* 90 */ _nop ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 91 */ _xchg ,2 ,_eCX,_eAX,0 ,0 ,0, 0 }, +{ /* 92 */ _xchg ,2 ,_eDX,_eAX,0 ,0 ,0, 0 }, +{ /* 93 */ _xchg ,2 ,_eBX,_eAX,0 ,0 ,0, 0 }, +{ /* 94 */ _xchg ,2 ,_eSP,_eAX,0 ,0 ,0, 0 }, +{ /* 95 */ _xchg ,2 ,_eBP,_eAX,0 ,0 ,0, 0 }, +{ /* 96 */ _xchg ,2 ,_eSI,_eAX,0 ,0 ,0, 0 }, +{ /* 97 */ _xchg ,2 ,_eDI,_eAX,0 ,0 ,0, 0 }, +{ /* 98 */ _cbw ,0 ,0 ,0 ,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* 99 */ _cwd ,0 ,0 ,0 ,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* 9A */ _call ,1 ,_Ap ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, +{ /* 9B */ _wait ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 9C */ _pushf ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING | DIS_NAME_FLAG }, +{ /* 9D */ _popf ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING | DIS_NAME_FLAG }, +{ /* 9E */ _sahf ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 9F */ _lahf ,0 ,0 ,0 ,0 ,0 ,0, 0 }, + +{ /* A0 */ _mov ,2 ,_AL ,_O ,0 ,0 ,0, 0 }, +{ /* A1 */ _mov ,2 ,_eAX,_O ,0 ,0 ,INSTR_READ | INSTR_WORD_DWORD, 0 }, +{ /* A2 */ _mov ,2 ,_O ,_AL ,0 ,0 ,0, 0 }, +{ /* A3 */ _mov ,2 ,_O ,_eAX,0 ,0 ,INSTR_WRITE | INSTR_WORD_DWORD, 0 }, +{ /* A4 */ _movsb ,2 ,_Yb ,_Xb ,0 ,0 ,0, 0 }, +{ /* A5 */ _movsw ,2 ,_Yv ,_Xv ,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* A6 */ _cmpsb ,2 ,_Xb ,_Yb ,0 ,0 ,0, 0 }, +{ /* A7 */ _cmpsw ,2 ,_Xv ,_Yv ,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* A8 */ _test ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* A9 */ _test ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* AA */ _stosb ,2 ,_Yb ,_AL ,0 ,0 ,0, 0 }, +{ /* AB */ _stosw ,2 ,_Yb ,_eAX,0 ,0 ,0, DIS_NAME_FLAG }, +{ /* AC */ _lodsb ,2 ,_AL ,_Xb ,0 ,0 ,INSTR_READ | INSTR_BYTE, 0 }, +{ /* AD */ _lodsw ,2 ,_eAX,_Xv ,0 ,0 ,INSTR_READ | INSTR_WORD_DWORD, DIS_NAME_FLAG }, +{ /* AE */ _scasb ,2 ,_AL ,_Xb ,0 ,0 ,0, 0 }, +{ /* AF */ _scasw ,2 ,_eAX,_Xv ,0 ,0 ,0, DIS_NAME_FLAG }, + +{ /* B0 */ _mov ,2 ,_AL ,_Ib ,0 ,0 ,0, 0 }, +{ /* B1 */ _mov ,2 ,_CL ,_Ib ,0 ,0 ,0, 0 }, +{ /* B2 */ _mov ,2 ,_DL ,_Ib ,0 ,0 ,0, 0 }, +{ /* B3 */ _mov ,2 ,_BL ,_Ib ,0 ,0 ,0, 0 }, +{ /* B4 */ _mov ,2 ,_AH ,_Ib ,0 ,0 ,0, 0 }, +{ /* B5 */ _mov ,2 ,_CH ,_Ib ,0 ,0 ,0, 0 }, +{ /* B6 */ _mov ,2 ,_DH ,_Ib ,0 ,0 ,0, 0 }, +{ /* B7 */ _mov ,2 ,_BH ,_Ib ,0 ,0 ,0, 0 }, +{ /* B8 */ _mov ,2 ,_eAX,_Iv ,0 ,0 ,0, 0 }, +{ /* B9 */ _mov ,2 ,_eCX,_Iv ,0 ,0 ,0, 0 }, +{ /* BA */ _mov ,2 ,_eDX,_Iv ,0 ,0 ,0, 0 }, +{ /* BB */ _mov ,2 ,_eBX,_Iv ,0 ,0 ,0, 0 }, +{ /* BC */ _mov ,2 ,_eSP,_Iv ,0 ,0 ,0, 0 }, +{ /* BD */ _mov ,2 ,_eBP,_Iv ,0 ,0 ,0, 0 }, +{ /* BE */ _mov ,2 ,_eSI,_Iv ,0 ,0 ,0, 0 }, +{ /* BF */ _mov ,2 ,_eDI,_Iv ,0 ,0 ,0, 0 }, + +{ /* C0 */ _GRP2a ,2 ,_Eb ,_Ib ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* C1 */ _GRP2b ,2 ,_Ev ,_Ib ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* C2 */ _ret ,1 ,_Iw ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, +{ /* C3 */ _ret ,0 ,0 ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, +{ /* C4 */ _les ,2 ,_Gv ,_Mp ,0 ,0 ,0, SCAN_TERM_PMODE | DIS_MODRM }, +{ /* C5 */ _lds ,2 ,_Gv ,_Mp ,0 ,0 ,0, SCAN_TERM_PMODE | DIS_MODRM }, +{ /* C6 */ _mov ,2 ,_Eb ,_Ib ,0 ,0 ,0, DIS_MODRM }, +{ /* C7 */ _mov ,2 ,_Ev ,_Iv ,0 ,0 ,0, DIS_MODRM }, +{ /* C8 */ _enter ,2 ,_Iw ,_Ib ,0 ,0 ,0, 0 }, +{ /* C9 */ _leave ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* CA */ _retf ,1 ,_Iw ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, +{ /* CB */ _retf ,0 ,0 ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, +{ /* CC */ _int ,1 ,_3 ,0 ,0 ,0 ,0, 0 }, +{ /* CD */ _int ,1 ,_Ib ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* CE */ _into ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* CF */ _iret ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + +{ /* D0 */ _GRP2c ,2 ,_Eb ,_1 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* D1 */ _GRP2d ,2 ,_Ev ,_1 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* D2 */ _GRP2e ,2 ,_Eb ,_CL ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* D3 */ _GRP2f ,2 ,_Ev ,_CL ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* D4 */ _aam ,1 ,_Ib ,0 ,0 ,0 ,0, 0 }, +{ /* D5 */ _aad ,1 ,_Ib ,0 ,0 ,0 ,0, 0 }, +{ /* D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D7 */ _xlat ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* D8 */ _EscD8 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 */ _EscD9 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA */ _EscDA ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB */ _EscDB ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC */ _EscDC ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD */ _EscDD ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE */ _EscDE ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF */ _EscDF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* E0 */ _loopne ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* E1 */ _loope ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* E2 */ _loop ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* E3 */ _jcxz ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* E4 */ _in ,2 ,_AL ,_Ib ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* E5 */ _in ,2 ,_eAX,_Ib ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* E6 */ _out ,2 ,_Ib ,_AL ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* E7 */ _out ,2 ,_Ib ,_eAX,0 ,0 ,0, SCAN_TERMINATING }, +{ /* E8 */ _call ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* E9 */ _jmp ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_JUMP }, +{ /* EA */ _jmpf ,1 ,_Ap ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* EB */ _jmp ,1 ,_Jb ,0 ,0 ,0 ,0, SCAN_JUMP }, +{ /* EC */ _in ,2 ,_AL ,_DX ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* ED */ _in ,2 ,_eAX,_DX ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* EE */ _out ,2 ,_DX ,_AL ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* EF */ _out ,2 ,_DX ,_eAX,0 ,0 ,0, SCAN_TERMINATING }, + +{ /* F0 */ _lock ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* F1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* F2 */ _REPNE ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* F3 */ _REP ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* F4 */ _hlt ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* F5 */ _cmc ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* F6 */ _GRP3a ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* F7 */ _GRP3b ,1 ,_Ev ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* F8 */ _clc ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* F9 */ _stc ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* FA */ _cli ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* FB */ _sti ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* FC */ _cld ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* FD */ _std ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* FE */ _GRP4 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* FF */ _GRP5 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM } +}; + + +/****************************************************************************** +* +* Table of the second byte of an instruction where the first byte was FF, +* the 2-byte escape code +* +******************************************************************************/ +TOpcodeData Op2[ 256 ] = { +{ /* 0F 00 */ _GRP6 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 0F 01 */ _GRP7 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 0F 02 */ _lar ,2 ,_Gv ,_Ew ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 03 */ _lsl ,2 ,_Gv ,_Ew ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 04 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 05 */ _loadall ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 0F 06 */ _clts ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 07 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 08 */ _invd ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 09 */ _wbinv ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 0A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 0B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 0C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 0D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 0E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 0F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 10 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 11 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 12 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 13 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 14 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 15 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 16 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 17 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 18 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 19 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 1A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 1B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 1C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 1D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 1E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 1F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 20 */ _mov ,2 ,_Rd ,_Cd ,0 ,0 ,0, SCAN_TERMINATING | DIS_MODRM }, +{ /* 0F 21 */ _mov ,2 ,_Rd ,_Dd ,0 ,0 ,0, SCAN_TERMINATING | DIS_MODRM }, +{ /* 0F 22 */ _mov ,2 ,_Cd ,_Rd ,0 ,0 ,0, SCAN_TERMINATING | DIS_MODRM }, +{ /* 0F 23 */ _mov ,2 ,_Dd ,_Rd ,0 ,0 ,0, SCAN_TERMINATING | DIS_MODRM }, +{ /* 0F 24 */ _mov ,2 ,_Rd ,_Td ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 25 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 26 */ _mov ,2 ,_Td ,_Rd ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 27 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 28 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 29 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 2A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 2B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 2C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 2D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 2E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 2F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 30 */ _wrmsr ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 31 */ _rdtsc ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 32 */ _rdmsr ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 33 */ _rdpmc ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F 34 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 35 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 36 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 37 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 38 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 39 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 3A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 3B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 3C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 3D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 3E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 3F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 40 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 41 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 42 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 43 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 44 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 45 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 46 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 47 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 48 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 49 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 4A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 4B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 4C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 4D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 4E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 4F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 50 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 51 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 52 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 53 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 54 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 55 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 56 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 57 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 58 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 59 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 5A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 5B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 5C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 5D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 5E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 5F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 60 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 61 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 62 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 63 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 64 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 65 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 66 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 67 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 68 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 69 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 6A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 6B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 6C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 6D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 6E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 6F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 70 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 71 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 72 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 73 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 74 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 75 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 76 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 77 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 78 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 79 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 7A */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 7B */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 7C */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 7D */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 7E */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F 7F */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F 80 */ _jo ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 81 */ _jno ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 82 */ _jb ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 83 */ _jnb ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 84 */ _jz ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 85 */ _jnz ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 86 */ _jbe ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 87 */ _jnbe ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 88 */ _js ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 89 */ _jns ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 8A */ _jp ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 8B */ _jnp ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 8C */ _jl ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 8D */ _jnl ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 8E */ _jle ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, +{ /* 0F 8F */ _jnle ,1 ,_Jv ,0 ,0 ,0 ,0, SCAN_COND_JUMP }, + +{ /* 0F 90 */ _seto ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 91 */ _setno ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 92 */ _setb ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 93 */ _setnb ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 94 */ _setz ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 95 */ _setnz ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 96 */ _setbe ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 97 */ _setnbe ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 98 */ _sets ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 99 */ _setns ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 9A */ _setp ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 9B */ _setnp ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 9C */ _setl ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 9D */ _setnl ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 9E */ _setle ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F 9F */ _setnle ,1 ,_Eb ,0 ,0 ,0 ,0, DIS_MODRM }, + +{ /* 0F A0 */ _push ,1 ,_FS ,0 ,0 ,0 ,0, 0 }, +{ /* 0F A1 */ _pop ,1 ,_FS ,0 ,0 ,0 ,0, 0 }, +{ /* 0F A2 */ _cpuid ,0 ,0 ,0 ,0 ,0 ,0, SCAN_TERMINATING }, +{ /* 0F A3 */ _bt ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F A4 */ _shld ,3 ,_Ev ,_Gv ,_Ib ,0 ,0, DIS_MODRM }, +{ /* 0F A5 */ _shld ,3 ,_Ev ,_Gv ,_CL ,0 ,0, DIS_MODRM }, +{ /* 0F A6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F A7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F A8 */ _push ,1 ,_GS ,0 ,0 ,0 ,0, 0 }, +{ /* 0F A9 */ _pop ,1 ,_GS ,0 ,0 ,0 ,0, 0 }, +{ /* 0F AA */ _rsm ,0 ,0 ,0 ,0 ,0 ,0, 0 }, +{ /* 0F AB */ _bts ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F AC */ _shrd ,3 ,_Ev ,_Gv ,_Ib ,0 ,0, DIS_MODRM }, +{ /* 0F AD */ _shrd ,3 ,_Ev ,_Gv ,_CL ,0 ,0, DIS_MODRM }, +{ /* 0F AE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F AF */ _imul ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, + +{ /* 0F B0 */ _cmpx ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F B1 */ _cmpx ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F B2 */ _lss ,2 ,_Gv ,_Mp ,0 ,0 ,0, SCAN_TERM_PMODE | DIS_MODRM }, +{ /* 0F B3 */ _btr ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F B4 */ _lfs ,2 ,_Gv ,_Mp ,0 ,0 ,0, SCAN_TERM_PMODE | DIS_MODRM }, +{ /* 0F B5 */ _lgs ,2 ,_Gv ,_Mp ,0 ,0 ,0, SCAN_TERM_PMODE | DIS_MODRM }, +{ /* 0F B6 */ _movzx ,2 ,_Gv ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F B7 */ _movzx ,2 ,_Gv ,_Ew ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F B8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F B9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F BA */ _GRP8 ,2 ,_Ev ,_Ib ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 0F BB */ _btc ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F BC */ _bsf ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F BD */ _bsr ,2 ,_Gv ,_Ev ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F BE */ _movsx ,2 ,_Gv ,_Eb ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F BF */ _movsx ,2 ,_Gv ,_Ew ,0 ,0 ,0, DIS_MODRM }, + +{ /* 0F C0 */ _xadd ,2 ,_Eb ,_Gb ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F C1 */ _xadd ,2 ,_Ev ,_Gv ,0 ,0 ,0, DIS_MODRM }, +{ /* 0F C2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F C3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F C4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F C5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F C6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F C7 */ _GRP9 ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL | DIS_MODRM }, +{ /* 0F C8 */ _bswap ,1 ,_eAX,0 ,0 ,0 ,0, 0 }, +{ /* 0F C9 */ _bswap ,1 ,_eCX,0 ,0 ,0 ,0, 0 }, +{ /* 0F CA */ _bswap ,1 ,_eDX,0 ,0 ,0 ,0, 0 }, +{ /* 0F CB */ _bswap ,1 ,_eBX,0 ,0 ,0 ,0, 0 }, +{ /* 0F CC */ _bswap ,1 ,_eSP,0 ,0 ,0 ,0, 0 }, +{ /* 0F CD */ _bswap ,1 ,_eBP,0 ,0 ,0 ,0, 0 }, +{ /* 0F CE */ _bswap ,1 ,_eSI,0 ,0 ,0 ,0, 0 }, +{ /* 0F CF */ _bswap ,1 ,_eDI,0 ,0 ,0 ,0, 0 }, + +{ /* 0F D0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F D9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F E0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F E9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F EA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F EB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F EC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F ED */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F EE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F EF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* 0F F0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F F9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F FA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F FB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F FC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F FD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F FE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* 0F FF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL } +}; + + +/****************************************************************************** +* +* Table for Groups codes; groups 1 - 9 +* +* (These records have DIS_MODRM implied) +* +******************************************************************************/ +TOpcodeData Groups[ 17 ][ 8 ] = { +{{ /* Group 1a */ _add ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 001 */ _or ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 010 */ _adc ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 011 */ _sbb ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 100 */ _and ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 101 */ _sub ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 110 */ _xor ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 111 */ _cmp ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }}, + +{{ /* Group 1b */ _add ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 001 */ _or ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 010 */ _adc ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 011 */ _sbb ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 100 */ _and ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 101 */ _sub ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 110 */ _xor ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 111 */ _cmp ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }}, + +{{ /* Group 1c */ _add ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 001 */ _or ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 010 */ _adc ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 011 */ _sbb ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 100 */ _and ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 101 */ _sub ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 110 */ _xor ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 111 */ _cmp ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }}, + +{{ /* Group 2a */ _rol ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 001 */ _ror ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 010 */ _rcl ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 011 */ _rcr ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 100 */ _sal ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 101 */ _shr ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 110 */ _shl ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 111 */ _sar ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }}, + +{{ /* Group 2b */ _rol ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 001 */ _ror ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 010 */ _rcl ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 011 */ _rcr ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 100 */ _sal ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 101 */ _shr ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 110 */ _shl ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 111 */ _sar ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }}, + +{{ /* Group 2c */ _rol ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 001 */ _ror ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 010 */ _rcl ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 011 */ _rcr ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 100 */ _sal ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 101 */ _shr ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 110 */ _shl ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }, + { /* 111 */ _sar ,2 ,_Eb ,_1 ,0 ,0 ,0, 0 }}, + +{{ /* Group 2d */ _rol ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 001 */ _ror ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 010 */ _rcl ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 011 */ _rcr ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 100 */ _sal ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 101 */ _shr ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 110 */ _shl ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }, + { /* 111 */ _sar ,2 ,_Ev ,_1 ,0 ,0 ,0, 0 }}, + +{{ /* Group 2e */ _rol ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 001 */ _ror ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 010 */ _rcl ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 011 */ _rcr ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 100 */ _sal ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 101 */ _shr ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 110 */ _shl ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }, + { /* 111 */ _sar ,2 ,_Eb ,_CL ,0 ,0 ,0, 0 }}, + +{{ /* Group 2f */ _rol ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 001 */ _ror ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 010 */ _rcl ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 011 */ _rcr ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 100 */ _sal ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 101 */ _shr ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 110 */ _shl ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }, + { /* 111 */ _sar ,2 ,_Ev ,_CL ,0 ,0 ,0, 0 }}, + +{{ /* Group 3a */ _test ,2 ,_Eb ,_Ib ,0 ,0 ,0, 0 }, + { /* 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 010 */ _not ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 011 */ _neg ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 100 */ _mul ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 101 */ _imul ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 110 */ _div ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 111 */ _idiv ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }}, + +{{ /* Group 3b */ _test ,2 ,_Ev ,_Iv ,0 ,0 ,0, 0 }, + { /* 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 010 */ _not ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 011 */ _neg ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 100 */ _mul ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 101 */ _imul ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 110 */ _div ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 111 */ _idiv ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }}, + +{{ /* Group 4 */ _inc ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 001 */ _dec ,1 ,_Eb ,0 ,0 ,0 ,0, 0 }, + { /* 010 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 011 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 100 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 101 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 110 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 111 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }}, + +{{ /* Group 5 */ _inc ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 001 */ _dec ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 010 */ _call ,1 ,_Ev ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, + { /* 011 */ _call ,1 ,_Ep ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, + { /* 100 */ _jmp ,1 ,_Ev ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, + { /* 101 */ _jmp ,1 ,_Ep ,0 ,0 ,0 ,0, SCAN_SINGLE_STEP }, + { /* 110 */ _push ,1 ,_Ev ,0 ,0 ,0 ,0, 0 }, + { /* 111 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }}, + +{{ /* Group 6 */ _sldt ,1 ,_Ew ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 001 */ _str ,1 ,_Ew ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 010 */ _lldt ,1 ,_Ew ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 011 */ _ltr ,1 ,_Ew ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 100 */ _verr ,1 ,_Ew ,0 ,0 ,0 ,0, 0 }, + { /* 101 */ _verw ,1 ,_Ew ,0 ,0 ,0 ,0, 0 }, + { /* 110 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 111 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }}, + +{{ /* Group 7 */ _sgdt ,1 ,_Ms ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 001 */ _sidt ,1 ,_Ms ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 010 */ _lgdt ,1 ,_Ms ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 011 */ _lidt ,1 ,_Ms ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 100 */ _smsw ,1 ,_Ew ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 101 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 110 */ _lmsw ,1 ,_Ew ,0 ,0 ,0 ,0, SCAN_TERMINATING }, + { /* 111 */ _invpg ,1 ,_M ,0 ,0 ,0 ,0, SCAN_TERMINATING }}, + +{{ /* Group 8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 010 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 011 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 100 */ _bt ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 101 */ _bts ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 110 */ _btr ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }, + { /* 111 */ _btc ,2 ,_Ev ,_Ib ,0 ,0 ,0, 0 }}, + +{{ /* Group 9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 001 */ _cmpx8 ,1 ,_Mq ,0 ,0 ,0 ,0, 0 }, + { /* 010 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 011 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 100 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 101 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 110 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + { /* 111 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }} +}; + + +/****************************************************************************** +* +* Coprocessor instructions have the prefix byte of D8-DF. +* The Coproc1 table defines instructions that have the second byte in the +* range 00-BF +* +******************************************************************************/ +TOpcodeData Coproc1[ 8 ][ 8 ] = { +{{ /* D8 000 */ _fadd ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 001 */ _fmul ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 010 */ _fcom ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 011 */ _fcomp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 100 */ _fsub ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 101 */ _fsubr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 110 */ _fdiv ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D8 111 */ _fdivr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* D9 000 */ _fld ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 010 */ _fst ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 011 */ _fstp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 100 */ _fldenv ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 101 */ _fldcw ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 110 */ _fstenv ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 111 */ _fstcw ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* DA 000 */ _fiadd ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 001 */ _fimul ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 010 */ _ficom ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 011 */ _ficomp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 100 */ _fisub ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 101 */ _fisubr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 110 */ _fidiv ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA 111 */ _fidivr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* DB 000 */ _fild ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DB 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB 010 */ _fist ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DB 011 */ _fistp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DB 100 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB 101 */ _fld ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DB 110 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB 111 */ _fstp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* DC 000 */ _fadd ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 001 */ _fmul ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 010 */ _fcom ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 011 */ _fcomp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 100 */ _fsub ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 101 */ _fsubr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 110 */ _fdiv ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DC 111 */ _fdivr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* DD 000 */ _fld ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD 010 */ _fst ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD 011 */ _fstp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD 100 */ _frstor ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD 101 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD 110 */ _fsave ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD 111 */ _fstsw ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* DE 000 */ _fiadd ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 001 */ _fimul ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 010 */ _ficom ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 011 */ _ficomp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 100 */ _fisub ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 101 */ _fisubr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 110 */ _fidiv ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE 111 */ _fidivr ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }}, + +{{ /* DF 000 */ _fild ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF 001 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF 010 */ _fist ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF 011 */ _fistp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF 100 */ _fbld ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF 101 */ _fild ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF 110 */ _fbstp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF 111 */ _fistp ,1 ,_M ,0 ,0 ,0 ,0, DIS_COPROC }} +}; + + +/****************************************************************************** +* +* The Coproc2 table defines coprocessor instructions that have the second +* byte in the range C0-FF +* +******************************************************************************/ +TOpcodeData Coproc2[ 8 ][ 16 * 4 ] = { +{{ /* D8 C0 */ _fadd ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C1 */ _fadd ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C2 */ _fadd ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C3 */ _fadd ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C4 */ _fadd ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C5 */ _fadd ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C6 */ _fadd ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C7 */ _fadd ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 C8 */ _fmul ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 C9 */ _fmul ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 CA */ _fmul ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 CB */ _fmul ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 CC */ _fmul ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 CD */ _fmul ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 CE */ _fmul ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 CF */ _fmul ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 D0 */ _fcom ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D1 */ _fcom ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D2 */ _fcom ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D3 */ _fcom ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D4 */ _fcom ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D5 */ _fcom ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D6 */ _fcom ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D7 */ _fcom ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 D8 */ _fcomp ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 D9 */ _fcomp ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 DA */ _fcomp ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 DB */ _fcomp ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 DC */ _fcomp ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 DD */ _fcomp ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 DE */ _fcomp ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 DF */ _fcomp ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 E0 */ _fsub ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E1 */ _fsub ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E2 */ _fsub ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E3 */ _fsub ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E4 */ _fsub ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E5 */ _fsub ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E6 */ _fsub ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E7 */ _fsub ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 E8 */ _fsubr ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 E9 */ _fsubr ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 EA */ _fsubr ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 EB */ _fsubr ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 EC */ _fsubr ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 ED */ _fsubr ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 EE */ _fsubr ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 EF */ _fsubr ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 F0 */ _fdiv ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F1 */ _fdiv ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F2 */ _fdiv ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F3 */ _fdiv ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F4 */ _fdiv ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F5 */ _fdiv ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F6 */ _fdiv ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F7 */ _fdiv ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D8 F8 */ _fdivr ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D8 F9 */ _fdivr ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D8 FA */ _fdivr ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D8 FB */ _fdivr ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D8 FC */ _fdivr ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D8 FD */ _fdivr ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D8 FE */ _fdivr ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D8 FF */ _fdivr ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }}, +/*----------------------------------------------------*/ +{{ /* D9 C0 */ _fld ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C1 */ _fld ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C2 */ _fld ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C3 */ _fld ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C4 */ _fld ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C5 */ _fld ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C6 */ _fld ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C7 */ _fld ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D9 C8 */ _fxch ,2 ,_ST ,_ST0,0 ,0 ,0, DIS_COPROC }, +{ /* D9 C9 */ _fxch ,2 ,_ST ,_ST1,0 ,0 ,0, DIS_COPROC }, +{ /* D9 CA */ _fxch ,2 ,_ST ,_ST2,0 ,0 ,0, DIS_COPROC }, +{ /* D9 CB */ _fxch ,2 ,_ST ,_ST3,0 ,0 ,0, DIS_COPROC }, +{ /* D9 CC */ _fxch ,2 ,_ST ,_ST4,0 ,0 ,0, DIS_COPROC }, +{ /* D9 CD */ _fxch ,2 ,_ST ,_ST5,0 ,0 ,0, DIS_COPROC }, +{ /* D9 CE */ _fxch ,2 ,_ST ,_ST6,0 ,0 ,0, DIS_COPROC }, +{ /* D9 CF */ _fxch ,2 ,_ST ,_ST7,0 ,0 ,0, DIS_COPROC }, + +{ /* D9 D0 */ _fnop ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* D9 D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 D9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* D9 E0 */ _fchs ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 E1 */ _fabs ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 E2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 E3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 E4 */ _ftst ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 E5 */ _fxam ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 E6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* D9 E7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* D9 E8 */ _fld1 ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 E9 */ _fldl2t ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 EA */ _fldl2e ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 EB */ _fldpi ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 EC */ _fldlg2 ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 ED */ _fldln2 ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 EE */ _fldz ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 EF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* D9 F0 */ _f2xm1 ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F1 */ _fyl2x ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F2 */ _fptan ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F3 */ _fpatan ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F4 */ _fxtract ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F5 */ _fprem1 ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F6 */ _fdecstp ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F7 */ _fincstp ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, + +{ /* D9 F8 */ _fprem ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 F9 */ _fyl2xp1 ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 FA */ _fsqrt ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 FB */ _fsincos ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 FC */ _frndint ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 FD */ _fscale ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 FE */ _fsin ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* D9 FF */ _fcos ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }}, +/*----------------------------------------------------*/ +{{ /* DA C0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA C8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA C9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA CA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA CB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA CC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA CD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA CE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA CF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA D0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA D9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA E0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA E8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA E9 */ _fucompp ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DA EA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA EB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA EC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA ED */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA EE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA EF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA F0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DA F8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA F9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA FA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA FB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA FC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA FD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA FE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DA FF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }}, +/*----------------------------------------------------*/ +{{ /* DB C0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB C8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB C9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB CA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB CB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB CC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB CD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB CE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB CF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB D0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB D9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB E0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB E1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB E2 */ _fclex ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DB E3 */ _finit ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DB E4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB E5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB E6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB E7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB E8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB E9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB EA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB EB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB EC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB ED */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB EE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB EF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB F0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DB F8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB F9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB FA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB FB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB FC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB FD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB FE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DB FF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }}, +/*----------------------------------------------------*/ +{{ /* DC C0 */ _fadd ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C1 */ _fadd ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C2 */ _fadd ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C3 */ _fadd ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C4 */ _fadd ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C5 */ _fadd ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C6 */ _fadd ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C7 */ _fadd ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DC C8 */ _fmul ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC C9 */ _fmul ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC CA */ _fmul ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC CB */ _fmul ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC CC */ _fmul ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC CD */ _fmul ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC CE */ _fmul ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC CF */ _fmul ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DC D0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DC D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC D9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DC DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DC E0 */ _fsubr ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E1 */ _fsubr ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E2 */ _fsubr ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E3 */ _fsubr ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E4 */ _fsubr ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E5 */ _fsubr ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E6 */ _fsubr ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E7 */ _fsubr ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DC E8 */ _fsub ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC E9 */ _fsub ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC EA */ _fsub ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC EB */ _fsub ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC EC */ _fsub ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC ED */ _fsub ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC EE */ _fsub ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC EF */ _fsub ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DC F0 */ _fdivr ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F1 */ _fdivr ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F2 */ _fdivr ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F3 */ _fdivr ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F4 */ _fdivr ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F5 */ _fdivr ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F6 */ _fdivr ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F7 */ _fdivr ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DC F8 */ _fdiv ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC F9 */ _fdiv ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC FA */ _fdiv ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC FB */ _fdiv ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC FC */ _fdiv ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC FD */ _fdiv ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC FE */ _fdiv ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DC FF */ _fdiv ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }}, +/*----------------------------------------------------*/ +{{ /* DD C0 */ _ffree ,1 ,_ST0,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C1 */ _ffree ,1 ,_ST1,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C2 */ _ffree ,1 ,_ST2,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C3 */ _ffree ,1 ,_ST3,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C4 */ _ffree ,1 ,_ST4,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C5 */ _ffree ,1 ,_ST5,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C6 */ _ffree ,1 ,_ST6,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD C7 */ _ffree ,1 ,_ST7,0 ,0 ,0 ,0, DIS_COPROC }, + +{ /* DD C8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD C9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD CA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD CB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD CC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD CD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD CE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD CF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DD D0 */ _fst ,1 ,_ST0,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D1 */ _fst ,1 ,_ST1,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D2 */ _fst ,1 ,_ST2,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D3 */ _fst ,1 ,_ST3,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D4 */ _fst ,1 ,_ST4,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D5 */ _fst ,1 ,_ST5,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D6 */ _fst ,1 ,_ST6,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D7 */ _fst ,1 ,_ST7,0 ,0 ,0 ,0, DIS_COPROC }, + +{ /* DD D8 */ _fstp ,1 ,_ST0,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD D9 */ _fstp ,1 ,_ST1,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD DA */ _fstp ,1 ,_ST2,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD DB */ _fstp ,1 ,_ST3,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD DC */ _fstp ,1 ,_ST4,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD DD */ _fstp ,1 ,_ST5,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD DE */ _fstp ,1 ,_ST6,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD DF */ _fstp ,1 ,_ST7,0 ,0 ,0 ,0, DIS_COPROC }, + +{ /* DD E0 */ _fucom ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E1 */ _fucom ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E2 */ _fucom ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E3 */ _fucom ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E4 */ _fucom ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E5 */ _fucom ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E6 */ _fucom ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E7 */ _fucom ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DD E8 */ _fucomp ,1 ,_ST0,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD E9 */ _fucomp ,1 ,_ST1,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD EA */ _fucomp ,1 ,_ST2,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD EB */ _fucomp ,1 ,_ST3,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD EC */ _fucomp ,1 ,_ST4,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD ED */ _fucomp ,1 ,_ST5,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD EE */ _fucomp ,1 ,_ST6,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DD EF */ _fucomp ,1 ,_ST7,0 ,0 ,0 ,0, DIS_COPROC }, + +{ /* DD F0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DD F8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD F9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD FA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD FB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD FC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD FD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD FE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DD FF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }}, +/*----------------------------------------------------*/ +{{ /* DE C0 */ _faddp ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C1 */ _faddp ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C2 */ _faddp ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C3 */ _faddp ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C4 */ _faddp ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C5 */ _faddp ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C6 */ _faddp ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C7 */ _faddp ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DE C8 */ _fmulp ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE C9 */ _fmulp ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE CA */ _fmulp ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE CB */ _fmulp ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE CC */ _fmulp ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE CD */ _fmulp ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE CE */ _fmulp ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE CF */ _fmulp ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DE D0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DE D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE D9 */ _fcompp ,0 ,0 ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DE DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DE DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DE E0 */ _fsubrp ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E1 */ _fsubrp ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E2 */ _fsubrp ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E3 */ _fsubrp ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E4 */ _fsubrp ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E5 */ _fsubrp ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E6 */ _fsubrp ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E7 */ _fsubrp ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DE E8 */ _fsubp ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE E9 */ _fsubp ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE EA */ _fsubp ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE EB */ _fsubp ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE EC */ _fsubp ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE ED */ _fsubp ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE EE */ _fsubp ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE EF */ _fsubp ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DE F0 */ _fdivrp ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F1 */ _fdivrp ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F2 */ _fdivrp ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F3 */ _fdivrp ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F4 */ _fdivrp ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F5 */ _fdivrp ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F6 */ _fdivrp ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F7 */ _fdivrp ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }, + +{ /* DE F8 */ _fdivp ,2 ,_ST0,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE F9 */ _fdivp ,2 ,_ST1,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE FA */ _fdivp ,2 ,_ST2,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE FB */ _fdivp ,2 ,_ST3,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE FC */ _fdivp ,2 ,_ST4,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE FD */ _fdivp ,2 ,_ST5,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE FE */ _fdivp ,2 ,_ST6,_ST ,0 ,0 ,0, DIS_COPROC }, +{ /* DE FF */ _fdivp ,2 ,_ST7,_ST ,0 ,0 ,0, DIS_COPROC }}, +/*----------------------------------------------------*/ +{{ /* DF C0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF C8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF C9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF CA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF CB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF CC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF CD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF CE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF CF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF D0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF D8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF D9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF DA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF DB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF DC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF DD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF DE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF DF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF E0 */ _fstsw ,1 ,_AX ,0 ,0 ,0 ,0, DIS_COPROC }, +{ /* DF E1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF E8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF E9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF EA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF EB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF EC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF ED */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF EE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF EF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF F0 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F1 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F2 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F3 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F4 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F5 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F6 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F7 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, + +{ /* DF F8 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF F9 */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF FA */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF FB */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF FC */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF FD */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF FE */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }, +{ /* DF FF */ _NDEF ,0 ,0 ,0 ,0 ,0 ,0, DIS_SPECIAL }} +}; + +/****************************************************************************** +* +* Generic messages used by the disassembler +* +******************************************************************************/ +char *sBytePtr = "BYTE PTR "; +char *sWordPtr = "WORD PTR "; +char *sDwordPtr = "DWORD PTR "; +char *sFwordPtr = "FWORD PTR "; +char *sQwordPtr = "QWORD PTR "; + +/****************************************************************************** +* +* Different register messages used by the disassembler +* +******************************************************************************/ +char *sGenReg16_32[ 2 ][ 8 ] = { +{ "AX","CX","DX","BX","SP","BP","SI","DI" }, +{ "EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI" } +}; + +char *sSeg[ 8 ] = { +"ES","CS","SS","DS","FS","GS","?","?" +}; + +char *sSegOverride[ 8 ] = { +"", "ES:","CS:","SS:","DS:","FS:","GS:","?:" +}; + +char *sSegOverrideDefaultES[ 8 ] = { +"ES:", "ES:","CS:","SS:","DS:","FS:","GS:","?:" +}; + +char *sSegOverrideDefaultDS[ 8 ] = { +"DS:", "ES:","CS:","SS:","DS:","FS:","GS:","?:" +}; + +char *sScale[ 4 ] = { +"", "2*", "4*", "8*" +}; + +char *sAdr1[ 2 ][ 8 ] = { +{ "BX+SI","BX+DI","BP+SI","BP+DI","SI","DI","BP","BX" }, +{ "EAX","ECX","EDX","EBX","?","EBP","ESI","EDI" } +}; + +char *sRegs1[ 2 ][ 2 ][ 8 ] = { +{{ "AL","CL","DL","BL","AH","CH","DH","BH" }, + { "AX","CX","DX","BX","SP","BP","SI","DI" } }, +{{ "AL","CL","DL","BL","AH","CH","DH","BH" }, + { "EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI" } } +}; + +char *sRegs2[] = { +"DX", "AL", "AH", "BL", "BH", "CL", "CH", "DL", "DH", "CS", "DS", "ES", "SS", "FS", "GS" +}; + +char *sControl[ 8 ] = { +"CR0","CR1","CR2","CR3","CR4","?","?","?" +}; + +char *sDebug[ 8 ] = { +"DR0","DR1","DR2","DR3","DR4","DR5","DR6","DR7" +}; + +char *sTest[ 8 ] = { +"?","?","?","?","?","?","TR6","TR7" +}; + +char *sYptr[ 2 ] = { +"[DI]", "[EDI]" +}; + +char *sXptr[ 2 ] = { +"[SI]", "[ESI]" +}; + +char *sRep[ 4 ] = { +"", "REP ", "REPNZ ", "?" +}; + +char *sST[ 9 ] = { +"ST(0)","ST(1)","ST(2)","ST(3)","ST(4)","ST(5)","ST(6)","ST(7)","ST" +}; + + diff --git a/apps/utils/pice/module/disassemblerdefines.h b/apps/utils/pice/module/disassemblerdefines.h new file mode 100644 index 0000000..dc52a99 --- /dev/null +++ b/apps/utils/pice/module/disassemblerdefines.h @@ -0,0 +1,515 @@ +/****************************************************************************** +* * +* Module: disassemblerdefines.h * +* * +* Revision: 1.00 * +* * +* Date: 3/17/2000 * +* * +* Copyright (c) 2000 Goran Devic * +* * +* Author: Goran Devic * +* * +******************************************************************************* + + Module Description: + + This is a header file containing the disassembler defines that are + used in DisassemblerData.h + +******************************************************************************* +* * +* Changes: * +* * +* DATE DESCRIPTION OF CHANGES AUTHOR * +* -------- --------------------------------------------------- ----------- * +* 4/28/2000 Original Goran Devic * +* 11/4/2000 Modified for LinIce Goran Devic * +* -------- --------------------------------------------------- ----------- * +******************************************************************************* +* Important Defines * +******************************************************************************/ +#ifndef _DDEF_H_ +#define _DDEF_H_ + +/****************************************************************************** +* +* Groups and special codes in place of name index +* +******************************************************************************/ +#define _NDEF 0x00 // Udefined/reserved opcode +#define _2BESC 0x01 // 2 byte escape code +#define _S_ES 0x02 // Segment ES override | these defines +#define _S_CS 0x03 // Segment CS override | must have +#define _S_SS 0x04 // Segment SS override | consecutive +#define _S_DS 0x05 // Segment DS override | enumeration +#define _S_FS 0x06 // Segment FS override | numbers. +#define _S_GS 0x07 // Segment GS override | +#define _OPSIZ 0x08 // Operand size override +#define _ADSIZ 0x09 // Address size override +#define _REPNE 0x0A // REPNE/REPNZ prefix +#define _REP 0x0B // REP/REPE/REPZ prefix +#define _EscD8 0x0C // Escape to coprocessor set: prefix D8 +#define _EscD9 0x0D // Escape to coprocessor set: prefix D9 +#define _EscDA 0x0E // Escape to coprocessor set: prefix DA +#define _EscDB 0x0F // Escape to coprocessor set: prefix DB +#define _EscDC 0x10 // Escape to coprocessor set: prefix DC +#define _EscDD 0x11 // Escape to coprocessor set: prefix DD +#define _EscDE 0x12 // Escape to coprocessor set: prefix DE +#define _EscDF 0x13 // Escape to coprocessor set: prefix DF +#define _GRP1a 0x14 // Group 1a extended opcode +#define _GRP1b 0x15 // Group 1b extended opcode +#define _GRP1c 0x16 // Group 1c extended opcode +#define _GRP2a 0x17 // Group 2a extended opcode +#define _GRP2b 0x18 // Group 2b extended opcode +#define _GRP2c 0x19 // Group 2c extended opcode +#define _GRP2d 0x1A // Group 2d extended opcode +#define _GRP2e 0x1B // Group 2e extended opcode +#define _GRP2f 0x1C // Group 2f extended opcode +#define _GRP3a 0x1D // Group 3a extended opcode +#define _GRP3b 0x1E // Group 3b extended opcode +#define _GRP4 0x1F // Group 4 extended opcode +#define _GRP5 0x20 // Group 5 extended opcode +#define _GRP6 0x21 // Group 6 extended opcode +#define _GRP7 0x22 // Group 7 extended opcode +#define _GRP8 0x23 // Group 8 extended opcode +#define _GRP9 0x24 // Group 9 extended opcode + +/****************************************************************************** +* +* Addressing modes argument definiton for the opcodes in a table +* +******************************************************************************/ +#define _O 0x01 + +#define _Ib 0x03 +#define _Iv 0x04 +#define _Iw 0x05 +#define _Yb 0x06 +#define _Yv 0x07 +#define _Xb 0x08 +#define _Xv 0x09 +#define _Jb 0x0A +#define _Jv 0x0B +#define _Ap 0x0C +#define _1 0x10 +#define _3 0x11 +#define _DX 0x12 +#define _AL 0x13 +#define _AH 0x14 +#define _BL 0x15 +#define _BH 0x16 +#define _CL 0x17 +#define _CH 0x18 +#define _DL 0x19 +#define _DH 0x1A +#define _CS 0x1B +#define _DS 0x1C +#define _ES 0x1D +#define _SS 0x1E +#define _FS 0x1F +#define _GS 0x20 +#define _eAX 0x21 +#define _eCX 0x22 +#define _eDX 0x23 +#define _eBX 0x24 +#define _eSP 0x25 +#define _eBP 0x26 +#define _eSI 0x27 +#define _eDI 0x28 +#define _Eb 0x2F +#define _Ev 0x30 +#define _Ew 0x31 +#define _Ep 0x32 +#define _Gb 0x33 +#define _Gv 0x34 +#define _M 0x35 +#define _Ma 0x36 +#define _Mp 0x37 +#define _Ms 0x38 +#define _Mq 0x39 +#define _Rd 0x3A +#define _Rw 0x3B +#define _Sw 0x3C +#define _Cd 0x3D +#define _Dd 0x3E +#define _Td 0x3F +#define _ST 0x40 +#define _ST0 0x41 +#define _ST1 0x42 +#define _ST2 0x43 +#define _ST3 0x44 +#define _ST4 0x45 +#define _ST5 0x46 +#define _ST6 0x47 +#define _ST7 0x48 +#define _AX 0x49 + +/****************************************************************************** +* +* Define holding structure for opcode +* +******************************************************************************/ + +typedef struct +{ + UCHAR name; // Index into the opcode name table + UCHAR args; // Number of addressing codes that follow + UCHAR dest; // Destination operand addressing code + UCHAR src; // Source operand addressing code + UCHAR thrid; // Third operand addressing code + UCHAR v_instruction; // Virtual instruction index + UCHAR access; // Instruction data access type + UCHAR flags; // Miscellaneous flags +} TOpcodeData; + +// `access' field: +// Data access flags are used with memory access instructions + +#define INSTR_READ 0x80 // Faulting instruction reads memory +#define INSTR_WRITE 0x40 // Faulting instruction writes to memory +#define INSTR_READ_WRITE 0x20 // Faulting instruction is read-modify-write + +// Low nibble contains the data length code - do not change these values as +// they represent the data width value as well + +#define INSTR_BYTE 0x01 // Byte access instruction +#define INSTR_WORD 0x02 // Word access instruction +#define INSTR_WORD_DWORD 0x03 // Word or dword, depending on operand size +#define INSTR_DWORD 0x04 // Dword access instruction + +// `flags' field: +// Disassembler flags; bottom 4 bits are used by the scanner flags + +#define DIS_SPECIAL 0x80 // Special opcode +#define DIS_NAME_FLAG 0x40 // Name changes +#define DIS_GETNAMEFLAG(flags) (((flags)>>6)&1) +#define DIS_COPROC 0x20 // Coprocessor instruction +#define DIS_MODRM 0x10 // Use additional Mod R/M byte + +// Scanner enums: 4 bits wide + +#define SCAN_NATIVE 0x0 // Native instruction are default 0 +#define SCAN_JUMP 0x1 // Evaluate new path +#define SCAN_COND_JUMP 0x2 // Evaluate both paths +#define SCAN_TERMINATING 0x3 // Terminating instruction needs virtualization +#define SCAN_TERM_PMODE 0x4 // Terminating instruction in protected mode only +#define SCAN_SINGLE_STEP 0x5 // Single-step instruction + +// Define values stored in meta pages (bits [7:4]) + +#define META_NATIVE 0x0 // Native instruction are default 0 +#define META_UNDEF 0x1 // Undefined/illegal instruction +#define META_TERMINATING 0x2 // Terminating instruction +#define META_SINGLE_STEP 0x3 // Execute natively single step + +/****************************************************************************** +* * +* Define opcode values for the main table * +* * +******************************************************************************/ +#define _aaa 0x001 +#define _aad 0x002 +#define _aam 0x003 +#define _aas 0x004 +#define _adc 0x005 +#define _add 0x006 +#define _and 0x007 +#define _arpl 0x008 +#define _bound 0x009 +#define _bsf 0x00a +#define _bsr 0x00b +#define _bt 0x00c +#define _btc 0x00d +#define _btr 0x00e +#define _bts 0x00f +#define _call 0x010 +#define _cbw 0x011 +#define _cwde 0x012 +#define _clc 0x013 +#define _cld 0x014 +#define _cli 0x015 +#define _clts 0x016 +#define _cmc 0x017 +#define _cmp 0x018 +#define _cmps 0x019 +#define _cmpsb 0x01a +#define _cmpsw 0x01b +#define _cmpsd 0x01c +#define _cwd 0x01d +#define _cdq 0x01e +#define _daa 0x01f +#define _das 0x020 +#define _dec 0x021 +#define _div 0x022 +#define _enter 0x023 +#define _hlt 0x024 +#define _idiv 0x025 +#define _imul 0x026 +#define _in 0x027 +#define _inc 0x028 +#define _ins 0x029 +#define _insb 0x02a +#define _insw 0x02b +#define _insd 0x02c +#define _int 0x02d +#define _into 0x02e +#define _iret 0x02f +#define _iretd 0x030 +#define _jo 0x031 +#define _jno 0x032 +#define _jb 0x033 +#define _jnb 0x034 +#define _jz 0x035 +#define _jnz 0x036 +#define _jbe 0x037 +#define _jnbe 0x038 +#define _js 0x039 +#define _jns 0x03a +#define _jp 0x03b +#define _jnp 0x03c +#define _jl 0x03d +#define _jnl 0x03e +#define _jle 0x03f +#define _jnle 0x040 +#define _jmp 0x041 +#define _lahf 0x042 +#define _lar 0x043 +#define _lea 0x044 +#define _leave 0x045 +#define _lgdt 0x046 +#define _lidt 0x047 +#define _lgs 0x048 +#define _lss 0x049 +#define _lds 0x04a +#define _les 0x04b +#define _lfs 0x04c +#define _lldt 0x04d +#define _lmsw 0x04e +#define _lock 0x04f +#define _lods 0x050 +#define _lodsb 0x051 +#define _lodsw 0x052 +#define _lodsd 0x053 +#define _loop 0x054 +#define _loope 0x055 +#define _loopz 0x056 +#define _loopne 0x057 +#define _loopnz 0x058 +#define _lsl 0x059 +#define _ltr 0x05a +#define _mov 0x05b +#define _movs 0x05c +#define _movsb 0x05d +#define _movsw 0x05e +#define _movsd 0x05f +#define _movsx 0x060 +#define _movzx 0x061 +#define _mul 0x062 +#define _neg 0x063 +#define _nop 0x064 +#define _not 0x065 +#define _or 0x066 +#define _out 0x067 +#define _outs 0x068 +#define _outsb 0x069 +#define _outsw 0x06a +#define _outsd 0x06b +#define _pop 0x06c +#define _popa 0x06d +#define _popad 0x06e +#define _popf 0x06f +#define _popfd 0x070 +#define _push 0x071 +#define _pusha 0x072 +#define _pushad 0x073 +#define _pushf 0x074 +#define _pushfd 0x075 +#define _rcl 0x076 +#define _rcr 0x077 +#define _rol 0x078 +#define _ror 0x079 +#define _rep 0x07a +#define _repe 0x07b +#define _repz 0x07c +#define _repne 0x07d +#define _repnz 0x07e +#define _ret 0x07f +#define _sahf 0x080 +#define _sal 0x081 +#define _sar 0x082 +#define _shl 0x083 +#define _shr 0x084 +#define _sbb 0x085 +#define _scas 0x086 +#define _scasb 0x087 +#define _scasw 0x088 +#define _scasd 0x089 +#define _set 0x08a +#define _sgdt 0x08b +#define _sidt 0x08c +#define _shld 0x08d +#define _shrd 0x08e +#define _sldt 0x08f +#define _smsw 0x090 +#define _stc 0x091 +#define _std 0x092 +#define _sti 0x093 +#define _stos 0x094 +#define _stosb 0x095 +#define _stosw 0x096 +#define _stosd 0x097 +#define _str 0x098 +#define _sub 0x099 +#define _test 0x09a +#define _verr 0x09b +#define _verw 0x09c +#define _wait 0x09d +#define _xchg 0x09e +#define _xlat 0x09f +#define _xlatb 0x0a0 +#define _xor 0x0a1 +#define _jcxz 0x0a2 +#define _loadall 0x0a3 +#define _invd 0x0a4 +#define _wbinv 0x0a5 +#define _seto 0x0a6 +#define _setno 0x0a7 +#define _setb 0x0a8 +#define _setnb 0x0a9 +#define _setz 0x0aa +#define _setnz 0x0ab +#define _setbe 0x0ac +#define _setnbe 0x0ad +#define _sets 0x0ae +#define _setns 0x0af +#define _setp 0x0b0 +#define _setnp 0x0b1 +#define _setl 0x0b2 +#define _setnl 0x0b3 +#define _setle 0x0b4 +#define _setnle 0x0b5 +#define _wrmsr 0x0b6 +#define _rdtsc 0x0b7 +#define _rdmsr 0x0b8 +#define _cpuid 0x0b9 +#define _rsm 0x0ba +#define _cmpx 0x0bb +#define _xadd 0x0bc +#define _bswap 0x0bd +#define _invpg 0x0be +#define _cmpx8 0x0bf +#define _jmpf 0x0c0 +#define _retf 0x0c1 +#define _rdpmc 0x0c2 + +#define _f2xm1 0x001 +#define _fabs 0x002 +#define _fadd 0x003 +#define _faddp 0x004 +#define _fbld 0x005 +#define _fbstp 0x006 +#define _fchs 0x007 +#define _fclex 0x008 +#define _fcom 0x009 +#define _fcomp 0x00a +#define _fcompp 0x00b +#define _fcos 0x00c +#define _fdecstp 0x00d +#define _fdiv 0x00e +#define _fdivp 0x00f +#define _fdivr 0x010 +#define _fdivrp 0x011 +#define _ffree 0x012 +#define _fiadd 0x013 +#define _ficom 0x014 +#define _ficomp 0x015 +#define _fidiv 0x016 +#define _fidivr 0x017 +#define _fild 0x018 +#define _fimul 0x019 +#define _fincstp 0x01a +#define _finit 0x01b +#define _fist 0x01c +#define _fistp 0x01d +#define _fisub 0x01e +#define _fisubr 0x01f +#define _fld 0x020 +#define _fld1 0x021 +#define _fldcw 0x022 +#define _fldenv 0x023 +#define _fldl2e 0x024 +#define _fldl2t 0x025 +#define _fldlg2 0x026 +#define _fldln2 0x027 +#define _fldpi 0x028 +#define _fldz 0x029 +#define _fmul 0x02a +#define _fmulp 0x02b +#define _fnop 0x02c +#define _fpatan 0x02d +#define _fprem 0x02e +#define _fprem1 0x02f +#define _fptan 0x030 +#define _frndint 0x031 +#define _frstor 0x032 +#define _fsave 0x033 +#define _fscale 0x034 +#define _fsin 0x035 +#define _fsincos 0x036 +#define _fsqrt 0x037 +#define _fst 0x038 +#define _fstcw 0x039 +#define _fstenv 0x03a +#define _fstp 0x03b +#define _fstsw 0x03c +#define _fsub 0x03d +#define _fsubp 0x03e +#define _fsubr 0x03f +#define _fsubrp 0x040 +#define _ftst 0x041 +#define _fucom 0x042 +#define _fucomp 0x043 +#define _fucompp 0x044 +#define _fxam 0x045 +#define _fxch 0x046 +#define _fxtract 0x047 +#define _fyl2x 0x048 +#define _fyl2xp1 0x049 + +/****************************************************************************** +* +* External data and strings +* +******************************************************************************/ +extern char* sNames[]; +extern char* sCoprocNames[]; +extern TOpcodeData Op1[ 256 ]; +extern TOpcodeData Op2[ 256 ]; +extern TOpcodeData Groups[ 17 ][ 8 ]; +extern TOpcodeData Coproc1[ 8 ][ 8 ]; +extern TOpcodeData Coproc2[ 8 ][ 16 * 4 ]; +extern char *sBytePtr; +extern char *sWordPtr; +extern char *sDwordPtr; +extern char *sFwordPtr; +extern char *sQwordPtr; +extern char *sGenReg16_32[ 2 ][ 8 ]; +extern char *sSeg[ 8 ]; +extern char *sSegOverride[ 8 ]; +extern char *sSegOverrideDefaultES[ 8 ]; +extern char *sSegOverrideDefaultDS[ 8 ]; +extern char *sScale[ 4 ]; +extern char *sAdr1[ 2 ][ 8 ]; +extern char *sRegs1[ 2 ][ 2 ][ 8 ]; +extern char *sRegs2[]; +extern char *sControl[ 8 ]; +extern char *sDebug[ 8 ]; +extern char *sTest[ 8 ]; +extern char *sYptr[ 2 ]; +extern char *sXptr[ 2 ]; +extern char *sRep[ 4 ]; +extern char *sST[ 9 ]; + + +#endif // _DDEF_H_ diff --git a/apps/utils/pice/module/gpfault.c b/apps/utils/pice/module/gpfault.c new file mode 100644 index 0000000..914dd60 --- /dev/null +++ b/apps/utils/pice/module/gpfault.c @@ -0,0 +1,142 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + GPFault.c + +Abstract: + + handle general protection faults on x86 + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 13-Nov-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//////////////////////////////////////////////////// +// GLOBALS +//// +ULONG OldGPFaultHandler = 0; + +char tempGP[1024]; + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// NewGPFaultHandler() +// +//************************************************************************* +void HandleGPFault(FRAME* ptr) +{ + DPRINT((0,"HandleGPFault(): ptr = %x at eip: %x\n",ptr, ptr->eip)); +} + +//************************************************************************* +// NewGPFaultHandler() +// +//************************************************************************* +__asm__ ("\n\t \ +NewGPFaultHandler:\n\t \ + pushfl\n\t \ + cli\n\t \ + cld\n\t \ + pushal\n\t \ + pushl %ds\n\t \ +\n\t \ + // test for v86 mode. + testl $0x20000,40(%esp)\n\t \ + jnz notv86\n\t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ + .byte 0x2e\n\t \ + jmp *_OldGPFaultHandler\n\t \ +notv86:\n\t \ + // setup default data selectors\n\t \ + movw %ss,%ax\n\t \ + movw %ax,%ds\n\t \ +\n\t \ + // get frame ptr\n\t \ + lea 40(%esp),%eax\n\t \ + pushl %eax\n\t \ + call _HandleGPFault\n\t \ + addl $4,%esp\n\t \ +\n \t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ + // remove error code from stack and replace with reason code\n\t \ + movl $" STR(REASON_GP_FAULT) ",(%esp)\n\t \ + // call debugger loop\n\t \ + jmp NewInt31Handler\n\t \ + "); + +//************************************************************************* +// InstallGPFaultHook() +// +//************************************************************************* +void InstallGPFaultHook(void) +{ + ULONG LocalGPFaultHandler; + + ENTER_FUNC(); + + MaskIrqs(); + if(!OldGPFaultHandler) + { + __asm__("mov $NewGPFaultHandler,%0" + :"=r" (LocalGPFaultHandler) + : + :"eax"); + OldGPFaultHandler=SetGlobalInt(0x0D,(ULONG)LocalGPFaultHandler); + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} + +//************************************************************************* +// DeInstallGPFaultHook() +// +//************************************************************************* +void DeInstallGPFaultHook(void) +{ + ENTER_FUNC(); + + MaskIrqs(); + if(OldGPFaultHandler) + { + RemoveAllSWBreakpoints(TRUE); + SetGlobalInt(0x0D,(ULONG)OldGPFaultHandler); + OldGPFaultHandler=0; + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} + +// EOF diff --git a/apps/utils/pice/module/gpfault.h b/apps/utils/pice/module/gpfault.h new file mode 100644 index 0000000..2830e57 --- /dev/null +++ b/apps/utils/pice/module/gpfault.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + gpfault.h + +Abstract: + + HEADER for gpfault.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void InstallGPFaultHook(void); +void DeInstallGPFaultHook(void); + +extern ULONG OldGPFaultHandler; diff --git a/apps/utils/pice/module/hardware.c b/apps/utils/pice/module/hardware.c new file mode 100644 index 0000000..0a067fd --- /dev/null +++ b/apps/utils/pice/module/hardware.c @@ -0,0 +1,1042 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + hardware.c + +Abstract: + + output to console + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 04-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//////////////////////////////////////////////////// +// PROTOTYPES +//// + +//////////////////////////////////////////////////// +// DEFINES +//// + +//////////////////////////////////////////////////// +// GLOBALS +//// + +// flagging stuff +BOOLEAN bCursorEnabled = FALSE; +BOOLEAN bConsoleIsInitialized = FALSE; + + +// terminal emulation +ETERMINALMODE eTerminalMode = TERMINAL_MODE_NONE; + +// window stuff +WINDOW wWindow[4]; + +// screen parameter +ULONG GLOBAL_SCREEN_WIDTH,GLOBAL_SCREEN_HEIGHT; + +// jump table to real output functions +OUTPUT_HANDLERS ohandlers; +INPUT_HANDLERS ihandlers; + +// ring buffer stuff +ULONG ulInPos = 0,ulLastPos = 0; +ULONG ulOldInPos = 0,ulOldDelta = 0; +BOOLEAN bSuspendPrintRingBuffer = FALSE; + +char aBuffers[LINES_IN_BUFFER][1024]; + +// output lock +ULONG ulOutputLock; + +// color of windows pane separation bars +USHORT usCaptionColor = BLUE; +USHORT usCaptionText = WHITE; +USHORT usForegroundColor = LTGRAY; +USHORT usBackgroundColor = BLACK; +USHORT usHiLiteColor = WHITE; + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// SuspendPrintRingBuffer() +// +//************************************************************************* +void SuspendPrintRingBuffer(BOOLEAN bSuspend) +{ + ENTER_FUNC(); + bSuspendPrintRingBuffer = bSuspend; + LEAVE_FUNC(); +} + +//************************************************************************* +// EmptyRingBuffer() +// +//************************************************************************* +void EmptyRingBuffer(void) +{ + //ENTER_FUNC(); + ulLastPos = ulInPos = ulOldInPos = ulOldDelta = 0; + PICE_memset(aBuffers,0,sizeof(aBuffers)); + //LEAVE_FUNC(); +} + +//************************************************************************* +// LinesInRingBuffer() +// +//************************************************************************* +ULONG LinesInRingBuffer(void) +{ + ULONG ulResult; + +// ENTER_FUNC(); + + ulResult = (ulInPos-ulLastPos)%LINES_IN_BUFFER; + +// LEAVE_FUNC(); + + return ulResult; +} + +//************************************************************************* +// CheckRingBuffer() +// +//************************************************************************* +void CheckRingBuffer(void) +{ +// ENTER_FUNC(); + + Acquire_Output_Lock(); + + if(ulInPos != ulOldInPos ) + { + ulOldInPos = ulInPos; + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + } + + Release_Output_Lock(); + +// LEAVE_FUNC(); +} + +//************************************************************************* +// AddToRingBuffer() +// +//************************************************************************* +BOOLEAN AddToRingBuffer(LPSTR p) +{ + ULONG i,j,len; + BOOLEAN bHadReturn = FALSE; + char temp[sizeof(aBuffers[0])]; + +// ENTER_FUNC(); + + // size of current string + j=PICE_strlen(aBuffers[ulInPos]); + + // start with ':' and current has ':' in front + if(aBuffers[ulInPos][0]==':' && *p==':') + { + if(j==1) + { + //LEAVE_FUNC(); + return FALSE; + } + aBuffers[ulInPos][j++]='\n'; + aBuffers[ulInPos][j]=0; + ulInPos = (ulInPos+1)%LINES_IN_BUFFER; + // wrap around + if(ulInPos == ulLastPos) + { + ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + } + // reset to start of buffer + j = 0; + } + // it's an internal print ("pICE: ...") + else if(aBuffers[ulInPos][0]==':' && PICE_strncmpi(p,"pICE:",5)==0) + { + if(j==1) + { + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + } + else + { + aBuffers[ulInPos][j++]='\n'; + aBuffers[ulInPos][j]=0; + ulInPos = (ulInPos+1)%LINES_IN_BUFFER; + // wrap around + if(ulInPos == ulLastPos) + { + ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + } + } + // reset to start of buffer + j = 0; + } + // it's a debug print and the current line is starting with ':' + else if(aBuffers[ulInPos][0]==':' && + ( (*p=='<' && PICE_isdigit(*(p+1)) && *(p+2)=='>') || bIsDebugPrint) ) + { + if(j==1) + { + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + } + else + { + aBuffers[ulInPos][j++]='\n'; + aBuffers[ulInPos][j]=0; + ulInPos = (ulInPos+1)%LINES_IN_BUFFER; + // wrap around + if(ulInPos == ulLastPos) + { + ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + } + } + // reset to start of buffer + j = 0; + } + // it's a debug print + else if(( (*p=='<' && PICE_isdigit(*(p+1)) && *(p+2)=='>') || bIsDebugPrint) ) + { + p += 3; + } + + // size of new string + len=PICE_strlen(p); + + // if combined string length too big + // reduce to maximum + if( (len+j) > sizeof(aBuffers[0])-2 ) + { + PICE_memcpy(temp,p,sizeof(aBuffers[0])-2); + p = temp; + // assume we end in NEWLINE + p[sizeof(aBuffers[0])-2]='\n'; + p[sizeof(aBuffers[0])-1]=0; + } + + for(i=0;p[i]!=0;i++) + { + // newline + if(p[i]=='\n') + { + aBuffers[ulInPos][j++]='\n'; + aBuffers[ulInPos][j]=0; + ulInPos = (ulInPos+1)%LINES_IN_BUFFER; + // wrap around + if(ulInPos == ulLastPos) + { + ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + } + // reset to start of buffer + j = 0; + // notify that we had a NEWLINE + bHadReturn = TRUE; + } + // backspace + else if(p[i]=='\b') + { + if(j!=0) + { + j--; + aBuffers[ulInPos][j] = 0; + } + } + // TAB + else if(p[i]=='\t') + { + // copy TAB + aBuffers[ulInPos][j++] = p[i]; + } + else + { + if((UCHAR)p[i]<0x20 && (UCHAR)p[i]>0x7f) + p[i]=0x20; + + aBuffers[ulInPos][j++] = p[i]; + } + } +// LEAVE_FUNC(); + + return bHadReturn; +} + +//************************************************************************* +// ReplaceRingBufferCurrent() +// +//************************************************************************* +void ReplaceRingBufferCurrent(LPSTR s) +{ +// ENTER_FUNC(); + + PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); + PICE_strcpy(aBuffers[ulInPos],s); + +// LEAVE_FUNC(); +} + +//************************************************************************* +// PrintRingBuffer() +// +//************************************************************************* +void PrintRingBuffer(ULONG ulLines) +{ + ULONG ulDelta = LinesInRingBuffer(); + ULONG ulOutPos,i=0; + +// ENTER_FUNC(); + + if(bSuspendPrintRingBuffer) + { + DPRINT((0,"PrintRingBuffer(): suspended\n")); + LEAVE_FUNC(); + return; + } + + if(!ulDelta) + { + DPRINT((0,"PrintRingBuffer(): no lines in ring buffer\n")); + LEAVE_FUNC(); + return; + } + + if(ulDelta=0x20 && (UCHAR)p[i]<0x80) + { + PrintGraf(x+i,y,p[i]); + } + } + + Flush(); + + Release_Output_Lock(); + +// LEAVE_FUNC(); +} + +//************************************************************************* +// CopyLineTo() +// +// copy a line from src to dest +//************************************************************************* +void CopyLineTo(USHORT dest,USHORT src) +{ + ohandlers.CopyLineTo(dest,src); +} + +//************************************************************************* +// InvertLine() +// +// invert a line on the screen +//************************************************************************* +void InvertLine(ULONG line) +{ + ohandlers.InvertLine(line); +} + +//************************************************************************* +// HatchLine() +// +// hatches a line on the screen +//************************************************************************* +void HatchLine(ULONG line) +{ + ohandlers.HatchLine(line); +} + +//************************************************************************* +// ClrLine() +// +// clear a line on the screen +//************************************************************************* +void ClrLine(ULONG line) +{ + ohandlers.ClrLine(line); +} + +//************************************************************************* +// ScrollUp() +// +// Scroll a specific window up one line +//************************************************************************* +void ScrollUp(USHORT Window) +{ + USHORT i; + + return; + + if(!wWindow[Window].bScrollDisabled) + { + for(i=1;i (GLOBAL_SCREEN_WIDTH-1)) + bOutput = FALSE; + + // newline + if(p[i]=='\n') + { + wWindow[Window].usCurX = 0; + wWindow[Window].usCurY++; + if(wWindow[Window].usCurY>=wWindow[Window].cy) + { + wWindow[Window].usCurY=wWindow[Window].cy-1; + ScrollUp(Window); + } + if(wWindow[Window].bScrollDisabled==TRUE)break; + } + // backspace + else if(p[i]=='\b') + { + if(wWindow[Window].usCurX>0) + { + wWindow[Window].usCurX--; + if(bOutput) + PrintGraf(wWindow[Window].usCurX,wWindow[Window].y+wWindow[Window].usCurY,0x20); + } + + } + // TAB + else if(p[i]=='\t') + { + if((wWindow[Window].usCurX + 4) < (GLOBAL_SCREEN_WIDTH-1)) + { + wWindow[Window].usCurX += 4; + } + } + else + { + if((UCHAR)p[i]<0x20 && (UCHAR)p[i]>0x7f) + p[i]=0x20; + + if(bOutput) + PrintGraf(wWindow[Window].usCurX,wWindow[Window].y+wWindow[Window].usCurY,p[i]); + + wWindow[Window].usCurX++; + } + } + + // flush + Flush(); + } + //LEAVE_FUNC(); +} + + +//************************************************************************* +// SaveGraphicsState() +// +//************************************************************************* +void SaveGraphicsState(void) +{ + ohandlers.SaveGraphicsState(); +} + +//************************************************************************* +// RestoreGraphicsState() +// +//************************************************************************* +void RestoreGraphicsState(void) +{ + ohandlers.RestoreGraphicsState(); +} + +//************************************************************************* +// SetWindowGeometry() +// +//************************************************************************* +void SetWindowGeometry(PVOID pWindow) +{ + PICE_memcpy(wWindow,pWindow,sizeof(wWindow)); +} + +// INPUT handlers + +//************************************************************************* +// GetKeyPolled() +// +//************************************************************************* +UCHAR GetKeyPolled(void) +{ + return ihandlers.GetKeyPolled(); +} + +//************************************************************************* +// FlushKeyboardQueue() +// +//************************************************************************* +void FlushKeyboardQueue(void) +{ + ihandlers.FlushKeyboardQueue(); +} + + +//************************************************************************* +// ConsoleInit() +// +// init terminal screen +//************************************************************************* +BOOLEAN ConsoleInit(void) +{ + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + + // preset ohandlers and ihandler to NULL + PICE_memset((void*)&ohandlers,0,sizeof(ohandlers)); + PICE_memset((void*)&ihandlers,0,sizeof(ihandlers)); + + switch(eTerminalMode) + { + case TERMINAL_MODE_HERCULES_GRAPHICS: + bResult = ConsoleInitHercules(); + break; + case TERMINAL_MODE_HERCULES_TEXT: + break; + case TERMINAL_MODE_VGA_TEXT: + bResult = ConsoleInitVga(); + break; + case TERMINAL_MODE_SERIAL: + bResult = ConsoleInitSerial(); + break; + case TERMINAL_MODE_NONE: + default: + // fail + break; + } + + // check that outputhandlers have all been set + // ohandlers.Flush may be zero on return + if( !ohandlers.ClrLine || + !ohandlers.CopyLineTo || + !ohandlers.HatchLine || + !ohandlers.HideCursor || + !ohandlers.InvertLine || + !ohandlers.PrintCursor || + !ohandlers.PrintGraf || + !ohandlers.PrintLogo || + !ohandlers.RestoreGraphicsState || + !ohandlers.SaveGraphicsState || + !ohandlers.SetBackgroundColor || + !ohandlers.SetForegroundColor || + !ohandlers.ShowCursor) + { + bResult = FALSE; + } + + // check that inputhandlers were installed + if( !ihandlers.GetKeyPolled || + !ihandlers.FlushKeyboardQueue) + { + bResult = FALSE; + } + + LEAVE_FUNC(); + + bConsoleIsInitialized = bResult; + + return bResult; +} + +//************************************************************************* +// ConsoleShutdown() +// +// exit terminal screen +//************************************************************************* +void ConsoleShutdown(void) +{ + ENTER_FUNC(); + + // sleep for a few seconds + KeStallExecutionProcessor(1000*5000); + + switch(eTerminalMode) + { + case TERMINAL_MODE_HERCULES_GRAPHICS: + ConsoleShutdownHercules(); + break; + case TERMINAL_MODE_HERCULES_TEXT: + break; + case TERMINAL_MODE_VGA_TEXT: + ConsoleShutdownVga(); + break; + case TERMINAL_MODE_SERIAL: + ConsoleShutdownSerial(); + break; + case TERMINAL_MODE_NONE: + default: + // fail + break; + } + + LEAVE_FUNC(); +} + +// EOF diff --git a/apps/utils/pice/module/hardware.h b/apps/utils/pice/module/hardware.h new file mode 100644 index 0000000..e2e1b3f --- /dev/null +++ b/apps/utils/pice/module/hardware.h @@ -0,0 +1,166 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + hardwar.h + +Abstract: + + HEADER for hardware.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +typedef struct tagWindow +{ + USHORT y,cy; + USHORT usCurX,usCurY; + BOOLEAN bScrollDisabled; +}WINDOW,*PWINDOW; + +// pointer indirection table for output functions +typedef struct _OUTPUT_HANDLERS +{ + void (*CopyLineTo) (USHORT dest,USHORT src); + void (*PrintGraf) (ULONG x,ULONG y,UCHAR c); + void (*Flush) (void); + void (*ClrLine) (ULONG line); + void (*InvertLine) (ULONG line); + void (*HatchLine) (ULONG line); + void (*PrintLogo) (BOOLEAN bShow); + void (*PrintCursor) (BOOLEAN bForce); + void (*SaveGraphicsState) (void); + void (*RestoreGraphicsState) (void); + void (*ShowCursor) (void); + void (*HideCursor) (void); + void (*SetForegroundColor) (ECOLORS); + void (*SetBackgroundColor) (ECOLORS); +}OUTPUT_HANDLERS,*POUTPUT_HANDLERS; + +// pointer indirection table for input functions +typedef struct _INPUT_HANDLERS +{ + UCHAR (*GetKeyPolled) (void); + void (*FlushKeyboardQueue) (void); +}INPUT_HANDLERS,*PINPUT_HANDLERS; + +extern OUTPUT_HANDLERS ohandlers; +extern INPUT_HANDLERS ihandlers; + +enum +{ + REGISTER_WINDOW = 0 , + DATA_WINDOW , + SOURCE_WINDOW , + OUTPUT_WINDOW , + OUTPUT_WINDOW_UNBUFFERED +}; + +typedef enum _ETERMINALMODE +{ + TERMINAL_MODE_HERCULES_GRAPHICS = 0 , + TERMINAL_MODE_HERCULES_TEXT, + TERMINAL_MODE_VGA_TEXT, + TERMINAL_MODE_SERIAL, + TERMINAL_MODE_NONE +}ETERMINALMODE; + +extern ETERMINALMODE eTerminalMode; + +extern WINDOW wWindow[]; +extern BOOLEAN bRev; +extern BOOLEAN bGrayed; +extern BOOLEAN bCursorEnabled; + +// install and remove handler +BOOLEAN ConsoleInit(void); +void ConsoleShutdown(void); + +// OUTPUT handler +void Print(USHORT Window,LPSTR p); +void SetBackgroundColor(ECOLORS c); +void SetForegroundColor(ECOLORS c); +void Clear(USHORT window); +void PutChar(LPSTR p,ULONG x,ULONG y); +void ClrLine(ULONG line); +void ShowCursor(void); +void HideCursor(void); +void EnableScroll(USHORT Window); +void DisableScroll(USHORT Window); +void CopyLineTo(USHORT dest,USHORT src); +void PrintLogo(BOOLEAN bShow); +void PrintCursor(BOOLEAN bForce); +void PrintGraf(ULONG x,ULONG y,UCHAR c); +void ScrollUp(USHORT Window); +void Home(USHORT Window); +void InvertLine(ULONG line); +void FillLine(ULONG line,UCHAR c); +void PrintTemplate(void); +void PrintCaption(void); +void ClrLineToEnd(USHORT Window,ULONG line,ULONG x); +void SuspendPrintRingBuffer(BOOLEAN bSuspend); +void HatchLine(ULONG line); +void SaveGraphicsState(void); +void RestoreGraphicsState(void); +void SetWindowGeometry(PVOID pWindow); + +// INPUT handler +UCHAR GetKeyPolled(void); +void FlushKeyboardQueue(void); + + +BOOLEAN PrintRingBufferOffset(ULONG ulLines,ULONG ulOffset); +BOOLEAN PrintRingBufferHome(ULONG ulLines); +void PrintRingBuffer(ULONG ulLines); +ULONG LinesInRingBuffer(void); +void ReplaceRingBufferCurrent(LPSTR s); +void EmptyRingBuffer(void); +void CheckRingBuffer(void); +BOOLEAN AddToRingBuffer(LPSTR p); +void ResetColor(void); + +extern ULONG GLOBAL_SCREEN_WIDTH; +extern ULONG GLOBAL_SCREEN_HEIGHT; + +extern ULONG ulOutputLock; + +#define Acquire_Output_Lock() \ +{ \ + save_flags(ulOutputLock); \ + cli(); \ +} + +#define Release_Output_Lock() \ + restore_flags(ulOutputLock); + +#define NOT_IMPLEMENTED() + +extern USHORT usCaptionColor; +#define COLOR_CAPTION usCaptionColor +extern USHORT usCaptionText; +#define COLOR_TEXT usCaptionText +extern USHORT usForegroundColor; +#define COLOR_FOREGROUND usForegroundColor +extern USHORT usBackgroundColor; + +#undef COLOR_BACKGROUND +#define COLOR_BACKGROUND usBackgroundColor +extern USHORT usHiLiteColor; +#define COLOR_HILITE usHiLiteColor diff --git a/apps/utils/pice/module/hercules.c b/apps/utils/pice/module/hercules.c new file mode 100644 index 0000000..b65c1ca --- /dev/null +++ b/apps/utils/pice/module/hercules.c @@ -0,0 +1,486 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + hercules.c + +Abstract: + + HW dependent draw routines + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 04-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +#include "charset.h" +#include "logo.h" + +//////////////////////////////////////////////////// +// PROTOTYPES +//// + +//////////////////////////////////////////////////// +// DEFINES +//// + +//////////////////////////////////////////////////// +// GLOBALS +//// +// cursor state +BOOLEAN bRev=FALSE; + +// HERCULES graphics adapter stuff +// 43 line graphics mode +UCHAR MGATable43[]={53,45,46, 7,96, 2,91,91, 2, 3, 0, 0, 0, 0, 0, 0}; + +PUCHAR pVgaOffset[4]; +// END of HERCULES graphics adapter stuff + +// used for HERCULES graphics mode +WINDOW wWindowHercGraph[4]= +{ + {1,3,1,0,FALSE}, + {5,6,1,0,FALSE}, + {12,19,1,0,FALSE}, + {32,12,1,0,FALSE} +}; +// used for HERCUELS text and VGA text mode +WINDOW wWindowHerc[4]= +{ + {1,3,1,0,FALSE}, + {5,4,1,0,FALSE}, + {10,9,1,0,FALSE}, + {20,4,1,0,FALSE} +}; + +PUCHAR pScreenBufferHercules; + +struct _attr +{ + union + { + struct + { + + UCHAR fgcol : 4; + UCHAR bkcol : 3; + UCHAR blink : 1; + }bits; + UCHAR Asuchar; + }u; +}attr; + +//************************************************************************* +// SetForegroundColorVga() +// +//************************************************************************* +void SetForegroundColorHercules(ECOLORS col) +{ + attr.u.bits.fgcol = col; + attr.u.bits.blink = 0; +} + +//************************************************************************* +// SetBackgroundColorVga() +// +//************************************************************************* +void SetBackgroundColorHercules(ECOLORS col) +{ + attr.u.bits.bkcol = col; + attr.u.bits.blink = 0; +} + +//************************************************************************* +// PrintGrafHercules() +// +//************************************************************************* +void PrintGrafHercules(ULONG x,ULONG y,UCHAR c) +{ + ULONG i; + PUCHAR p; + ULONG _line = y<<3; + + if(!pScreenBufferHercules) + return; + + p=&cGraphTable[(ULONG)c<<3]; + + if((attr.u.bits.bkcol == COLOR_FOREGROUND && attr.u.bits.fgcol == COLOR_BACKGROUND) || + (attr.u.bits.bkcol == COLOR_CAPTION && attr.u.bits.fgcol == COLOR_TEXT) ) + for(i=0 ;i<8 ;i++,_line++) + { + *(PUCHAR)(pVgaOffset[_line & 0x3] + ( 90* (_line >> 2) ) + x) = ~*p++; + } + else + for(i=0 ;i<8 ;i++,_line++) + { + *(PUCHAR)(pVgaOffset[_line & 0x3] + ( 90* (_line >> 2) ) + x) = *p++; + } +} + + +//************************************************************************* +// FlushHercules() +// +//************************************************************************* +void FlushHercules(void) +{ +} + +//************************************************************************* +// ShowCursor() +// +// show hardware cursor +//************************************************************************* +void ShowCursorHercules(void) +{ + ENTER_FUNC(); + + bCursorEnabled=TRUE; + + LEAVE_FUNC(); +} + +//************************************************************************* +// HideCursorHercules() +// +// hide hardware cursor +//************************************************************************* +void HideCursorHercules(void) +{ + ENTER_FUNC(); + + bCursorEnabled=FALSE; + + LEAVE_FUNC(); +} + +//************************************************************************* +// CopyLineTo() +// +// copy a line from src to dest +//************************************************************************* +void CopyLineToHercules(USHORT dest,USHORT src) +{ + USHORT i,j; + PULONG pDest,pSrc; + + ENTER_FUNC(); + + dest <<= 3; + src <<= 3; + for(i=0;i<8;i++) + { + (PUCHAR)pDest = (PUCHAR)pScreenBufferHercules + ( ( ( dest+i )&3) <<13 )+ 90 * ((dest+i) >> 2); + (PUCHAR)pSrc = (PUCHAR)pScreenBufferHercules + ( ( ( src+i )&3) <<13 )+ 90 * ((src+i) >> 2); + for(j=0;j<(GLOBAL_SCREEN_WIDTH>>2);j++) + { + *pDest++=*pSrc++; + } + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// InvertLineHercules() +// +// invert a line on the screen +//************************************************************************* +void InvertLineHercules(ULONG line) +{ + ULONG i,j; + ULONG _line = line<<3; + PUSHORT p; + + //ENTER_FUNC(); + + for(j=0;j<8;j++) + { + p=(PUSHORT)( pVgaOffset[_line&3] + (90*(_line>>2)) ); + for(i=0;i<(GLOBAL_SCREEN_WIDTH>>1);i++) + { + p[i]=~p[i]; + } + _line++; + } + + //LEAVE_FUNC(); +} + +//************************************************************************* +// HatchLineHercules() +// +// hatches a line on the screen +//************************************************************************* +void HatchLineHercules(ULONG line) +{ + USHORT cc; + ULONG i,j; + ULONG _line = (line<<3) ; + PUSHORT p; + USHORT mask_odd[]={0x8888,0x2222}; + USHORT mask_even[]={0xaaaa,0x5555}; + PUSHORT pmask; + + ENTER_FUNC(); + + pmask = (line&1)?mask_odd:mask_even; + + for(j=0;j<8;j++,_line++) + { + p=(PUSHORT)( pVgaOffset[_line&3] + (90*(_line>>2)) ); + for(i=0;i<(GLOBAL_SCREEN_WIDTH/sizeof(USHORT));i++) + { + cc = p[i]; + + p[i]=(p[i]^pmask[j&1])|cc; + } + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// ClrLineHercules() +// +// clear a line on the screen +//************************************************************************* +void ClrLineHercules(ULONG line) +{ + ULONG j; + BOOLEAN bTemplateLine=( (USHORT)line==wWindow[DATA_WINDOW].y-1 || + (USHORT)line==wWindow[SOURCE_WINDOW].y-1 || + (USHORT)line==wWindow[OUTPUT_WINDOW].y-1 || + 0); + ULONG _line = line<<3; + ULONG cc=0; + PUCHAR p; + +// ENTER_FUNC(); + + if(line > GLOBAL_SCREEN_HEIGHT ) + { + DPRINT((0,"ClrLineHercules(): line %u is out of screen\n",line)); + //LEAVE_FUNC(); + return; + } + + if(attr.u.bits.bkcol == COLOR_CAPTION && attr.u.bits.fgcol == COLOR_TEXT ) + cc=~cc; + + if(bTemplateLine) + { + for(j=0;j<8;j++,_line++) + { + p = (PUCHAR)(pVgaOffset[_line&3] + (90*(_line>>2)) ); + +/* + if(j==2 || j==5)cc=0xFF; + else if(j==3)cc=0xaa; + else if(j==4)cc=0x55; + else cc = 0;*/ + if(j==2 || j==5)cc=0xFF; + else cc = 0; + + PICE_memset(p,(UCHAR)cc,GLOBAL_SCREEN_WIDTH); + } + } + else + { + for(j=0;j<8;j++,_line++) + { + p = (PUCHAR)(pVgaOffset[_line&3] + (90*(_line>>2)) ); + + PICE_memset(p,(UCHAR)cc,GLOBAL_SCREEN_WIDTH); + } + } + //LEAVE_FUNC(); +} + +//************************************************************************* +// PrintLogoHercules() +// +//************************************************************************* +void PrintLogoHercules(BOOLEAN bShow) +{ + LONG x,y; + PUCHAR p; + + p=(PUCHAR)pScreenBufferHercules; + for(y=0;y<24;y++) + { + for(x=0;x<8;x++) + { + p[ ( 0x2000* (( y + 8 ) & 0x3) )+ + ( 90* ( (y + 8 ) >> 2) )+ + (81+x)] = cLogo[y*8+x]; + } + } +} + +//************************************************************************* +// PrintCursorHercules() +// +// emulate a blinking cursor block +//************************************************************************* +void PrintCursorHercules(BOOLEAN bForce) +{ + static ULONG count=0; + + if( (bForce) || ((count++>100) && bCursorEnabled) ) + { + ULONG i; + ULONG x,y; + ULONG _line; + + x=wWindow[OUTPUT_WINDOW].usCurX; + y=wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].usCurY; + + _line = y<<3; + for(i=0;i<8;i++,_line++) + { + *(PUCHAR)(pVgaOffset[_line & 0x3] + ( 90* (_line >> 2) ) + x) ^= 0xFF ; + } + bRev=!bRev; + count=0; + } + + KeStallExecutionProcessor(2500); +} + +//************************************************************************* +// SaveGraphicsHercules() +// +//************************************************************************* +void SaveGraphicsStateHercules(void) +{ + // not implemented +} + +//************************************************************************* +// RestoreGraphicsStateHercules() +// +//************************************************************************* +void RestoreGraphicsStateHercules(void) +{ + // not implemented +} + +//************************************************************************* +// ConsoleInitHercules() +// +// init terminal screen +//************************************************************************* +BOOLEAN ConsoleInitHercules(void) +{ + BOOLEAN bResult = FALSE; + PUCHAR pMGATable = MGATable43; + UCHAR i,reg,data; + PHYSICAL_ADDRESS FrameBuffer; + + ENTER_FUNC(); + + ohandlers.CopyLineTo = CopyLineToHercules; + ohandlers.PrintGraf = PrintGrafHercules; + ohandlers.Flush = FlushHercules; + ohandlers.ClrLine = ClrLineHercules; + ohandlers.InvertLine = InvertLineHercules; + ohandlers.HatchLine = HatchLineHercules; + ohandlers.PrintLogo = PrintLogoHercules; + ohandlers.PrintCursor = PrintCursorHercules; + ohandlers.SaveGraphicsState = SaveGraphicsStateHercules; + ohandlers.RestoreGraphicsState = RestoreGraphicsStateHercules; + ohandlers.ShowCursor = ShowCursorHercules; + ohandlers.HideCursor = HideCursorHercules; + ohandlers.SetForegroundColor = SetForegroundColorHercules; + ohandlers.SetBackgroundColor = SetBackgroundColorHercules; + + ihandlers.GetKeyPolled = KeyboardGetKeyPolled; + ihandlers.FlushKeyboardQueue = KeyboardFlushKeyboardQueue; + + // init HERCULES adapter + outb_p(0,0x3b8); + outb_p(0x03,0x3bf); + for(i=0;i>16)&0x0000FFFF)))+dwInt; + + oldidt=*pidt; + + // set new handler address + pidt->HiOffset=(USHORT)(((ULONG)NewIntHandler)>>16); + pidt->LoOffset=(USHORT)(((ULONG)NewIntHandler)&0x0000FFFF); + + DPRINT((0,"new INT(%0.2x) handler = %0.4x:%x\n",dwInt,pidt->SegSel,(pidt->HiOffset<<16)|(pidt->LoOffset&0x0000FFFF))); + + OldIntHandler=(oldidt.HiOffset<<16)|(oldidt.LoOffset&0x0000FFFF); + + DPRINT((0,"old INT(%0.2x) handler = %0.4x:%x\n",dwInt,pidt->SegSel,OldIntHandler)); + + LEAVE_FUNC(); + + return OldIntHandler; +} + +//************************************************************************* +// TakeIdtSnapshot() +// +//************************************************************************* +void TakeIdtSnapshot(void) +{ + ULONG idt[2],i; + struct IdtEntry* pidt; + + __asm__("sidt %0":"=m" (idt)); + + // get pointer to idte for int 3 + pidt=((struct IdtEntry*)((idt[1]<<16)|((idt[0]>>16)&0x0000FFFF))); + + for(i=0;i<256;i++) + { + DPRINT((11,"TakeIdtSnapShot(): saving vector %u\n",i)); + if(IsRangeValid((ULONG)pidt,sizeof(*pidt)) ) + { + DPRINT((11,"TakeIdtSnapShot(): vector %u valid\n",i)); + idt_snapshot[i] = *pidt++; + } + } +} + +//************************************************************************* +// RestoreIdt() +// +//************************************************************************* +void RestoreIdt(void) +{ + ULONG idt[2],i; + struct IdtEntry* pidt; + + __asm__("sidt %0":"=m" (idt)); + + // get pointer to idte for int 3 + pidt=((struct IdtEntry*)((idt[1]<<16)|((idt[0]>>16)&0x0000FFFF))); + + for(i=0;i<256;i++) + { + DPRINT((11,"TakeIdtSnapShot(): restoring vector %u\n",i)); + if(IsRangeValid((ULONG)pidt,sizeof(*pidt)) ) + { + DPRINT((11,"TakeIdtSnapShot(): vector %u valid\n",i)); + *pidt++ = idt_snapshot[i]; + } + } +} + +// EOF diff --git a/apps/utils/pice/module/hooks.h b/apps/utils/pice/module/hooks.h new file mode 100644 index 0000000..ab9969a --- /dev/null +++ b/apps/utils/pice/module/hooks.h @@ -0,0 +1,49 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + hooks.h + +Abstract: + + HEADER for hooks.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void DeinstallHooks(void); +//ULONG HookInt(ULONG dwInt,ULONG NewIntHandler); +//void UnhookInt(ULONG dwInt); +void MaskIrqs(void); +void UnmaskIrqs(void); +ULONG SetGlobalInt(ULONG dwInt,ULONG NewIntHandler); +ULONG GetIRQVector(ULONG dwInt); +void TakeIdtSnapshot(void); +void RestoreIdt(void); + +// structure of an IDT entry +typedef struct IdtEntry +{ + USHORT LoOffset; + USHORT SegSel; + USHORT Flags; + USHORT HiOffset; +}IDTENTRY,*PIDTENTRY; + diff --git a/apps/utils/pice/module/init.c b/apps/utils/pice/module/init.c new file mode 100644 index 0000000..f3ba200 --- /dev/null +++ b/apps/utils/pice/module/init.c @@ -0,0 +1,379 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + init.c + +Abstract: + + initialisation and cleanup of debugger kernel module + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 25-Jan-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//////////////////////////////////////////////////// +// GLOBALS +ULONG ulDoInitialBreak=1; +char szBootParams[1024]=""; +char tempInit[256]; + +PDIRECTORY_OBJECT *pNameSpaceRoot = NULL; +PDEBUG_MODULE pdebug_module_tail = NULL; +PDEBUG_MODULE pdebug_module_head = NULL; +PMADDRESS_SPACE mm_init_mm; +extern LIST_ENTRY *pModuleListHead; + +ULONG KeyboardIRQL; + +extern void NewInt31Handler(void); +//************************************************************************* +// InitPICE() +// +//************************************************************************* +BOOLEAN InitPICE(void) +{ + ULONG ulHandleScancode=0,ulHandleKbdEvent=0; + ARGS Args; + KIRQL Dirql; + KAFFINITY Affinity; + ULONG ulAddr; + + ENTER_FUNC(); + + DPRINT((0,"InitPICE(): trace step 0.5\n")); + KeyboardIRQL = HalGetInterruptVector(Internal, + 0, + 0, + KEYBOARD_IRQ, + &Dirql, + &Affinity); + DPRINT((0,"KeyboardIRQL: %x\n", KeyboardIRQL)); + + DPRINT((0,"InitPICE(): trace step 1\n")); + // enable monochrome passthrough on BX type chipset + EnablePassThrough(); + + DPRINT((0,"InitPICE(): trace step 2\n")); + // now load all symbol files described in /etc/pice.conf + if(!LoadSymbolsFromConfig(FALSE)) + { + DPRINT((0,"InitPICE: LoadSymbolsFromConfig() failed\n")); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 3\n")); + // init the output console + // this might be one of the following depending setup + // a) monochrome card + // b) serial terminal (TODO) + if(!ConsoleInit()) + { + DPRINT((0,"InitPICE: ConsoleInit() failed\n")); + UnloadSymbols(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 4\n")); + // print the initial screen template + PrintTemplate(); +/* + DPRINT((0,"InitPICE(): trace step 5\n")); + // ask the user if he wants to abort the debugger load + if(!CheckLoadAbort()) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (abort by user)\n"); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } +*/ + + DPRINT((0,"InitPICE(): trace step 6\n")); + // load the file /boot/System.map. + // !!! It must be consistent with the current kernel at all cost!!! + if(!LoadExports()) + { + Print(OUTPUT_WINDOW,"pICE: failed to load exports\n"); + Print(OUTPUT_WINDOW,"press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 7\n")); + ScanExports("_KernelAddressSpace", &ulAddr); + my_init_mm = (PMADDRESS_SPACE) ulAddr; + DPRINT((0,"init_mm %x @ %x\n",&my_init_mm,my_init_mm)); + if(!my_init_mm) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (initial memory map not found)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + DbgPrint("pICE: ABORT (initial memory map not found)\n"); + DbgPrint("pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 7.1\n")); + ScanExports("_ModuleListHead",&ulAddr); + pModuleListHead = (LIST_ENTRY*)ulAddr; + DPRINT((0,"pModuleListHead @ %X\n",pModuleListHead)); + if(!pModuleListHead) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (pModuleListHead not found)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 7.2\n")); + ScanExports("_PsProcessListHead",&ulAddr); + pPsProcessListHead = (LIST_ENTRY*)ulAddr; + DPRINT((0,"pPsProcessListHead @ %X\n",pPsProcessListHead)); + if(!pPsProcessListHead) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (PsProcessListHead not found)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 8\n")); + // end of the kernel + /* + ScanExports("_end",(PULONG)&kernel_end); + if(!kernel_end) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (kernel size is unknown)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadExports(); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + */ + + DPRINT((0,"InitPICE(): trace step 9\n")); + + // the loaded module list + ScanExports("_NameSpaceRoot", &ulAddr); + pNameSpaceRoot = (PDIRECTORY_OBJECT *)ulAddr; + DPRINT((0,"pNameSpaceRoot @ %X\n",pNameSpaceRoot)); + if(!pNameSpaceRoot) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (couldn't retreive name space root)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadExports(); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 10\n")); + // setup a linked list for use in module parsing routines. + if(!InitModuleList(&pdebug_module_head, 100)) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (couldn't initialize kernel module list)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + FreeModuleList( pdebug_module_head ); + while(!GetKeyPolled()); + UnloadExports(); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + pdebug_module_tail = pdebug_module_head; + + DPRINT((0,"InitPICE(): trace step 11\n")); + // do a sanity check on exports + if(!SanityCheckExports()) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (exports are conflicting with kernel symbols)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadExports(); + UnloadSymbols(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 12\n")); + + + DPRINT((0,"InitPICE(): trace step 13\n")); + // patch the keyboard driver + + if(!PatchKeyboardDriver()) + { + Print(OUTPUT_WINDOW,"pICE: ABORT (couldn't patch keyboard driver)\n"); + Print(OUTPUT_WINDOW,"pICE: press any key to continue...\n"); + while(!GetKeyPolled()); + UnloadSymbols(); + UnloadExports(); + ConsoleShutdown(); + LEAVE_FUNC(); + return FALSE; + } + + DPRINT((0,"InitPICE(): trace step 14\n")); + // partial init of shadow registers + CurrentCS = GLOBAL_CODE_SEGMENT; + CurrentEIP = (ULONG)RealIsr; + + CurrentDS = CurrentSS = GLOBAL_DATA_SEGMENT; + __asm__("\n\t \ + mov %%esp,%%eax\n\t \ + mov %%eax,_CurrentESP\n\t \ + ":::"eax"); + + + // display version and symbol information + Ver(NULL); + + // disable HW breakpoints + __asm__("\n\t \ + xorl %%eax,%%eax\n\t \ + mov %%eax,%%dr6\n\t \ + mov %%eax,%%dr7\n\t \ + mov %%dr0,%%eax\n\t \ + mov %%dr1,%%eax\n\t \ + mov %%dr2,%%eax\n\t \ + mov %%dr3,%%eax" + :::"eax" + ); + + DPRINT((0,"InitPICE(): trace step 15\n")); + TakeIdtSnapshot(); + + DPRINT((0,"InitPICE(): trace step 16\n")); + // install all hooks + InstallTraceHook(); + InstallGlobalKeyboardHook(); + InstallSyscallHook(); + InstallInt3Hook(); + InstallDblFltHook(); + InstallGPFaultHook(); + InstallIntEHook(); + InstallPrintkHook(); + + DPRINT((0,"InitPICE(): trace step 16\n")); + if(ulDoInitialBreak) + { + DPRINT((0,"about to do initial break...\n")); + + // simulate an initial break + __asm__("\n\t \ + pushfl\n\t \ + pushl %cs\n\t \ + pushl $initialreturnpoint\n\t \ + pushl $" STR(REASON_CTRLF) "\n\t \ + jmp NewInt31Handler\n\t \ +initialreturnpoint:"); + } + else + { + // display register contents + DisplayRegs(); + + // display data window + Args.Value[0]=CurrentDS; + Args.Value[1]=CurrentEIP; + Args.Count=2; + DisplayMemory(&Args); + + // disassembly from current address + Args.Value[0]=CurrentCS; + Args.Value[1]=CurrentEIP; + Args.Count=2; + Unassemble(&Args); + } + + DPRINT((0,"InitPICE(): trace step 17\n")); + InitPiceRunningTimer(); + + LEAVE_FUNC(); + return TRUE; +} + +//************************************************************************* +// CleanUpPICE() +// +//************************************************************************* +void CleanUpPICE(void) +{ + DPRINT((0,"CleanUpPICE(): trace step 1\n")); + RemovePiceRunningTimer(); + + DPRINT((0,"CleanUpPICE(): trace step 2\n")); + // de-install all hooks + DeInstallGlobalKeyboardHook(); + DeInstallSyscallHook(); + DeInstallInt3Hook(); + DeInstallPrintkHook(); + DeInstallDblFltHook(); + DeInstallGPFaultHook(); + DeInstallIntEHook(); + DeInstallTraceHook(); + + DPRINT((0,"CleanUpPICE(): trace step 3\n")); + RestoreIdt(); + + DPRINT((0,"CleanUpPICE(): trace step 4\n")); + UnloadExports(); // don't use ScanExports() after this + UnloadSymbols(); + + DPRINT((0,"CleanUpPICE(): trace step 5\n")); + // restore patch of keyboard driver + RestoreKeyboardDriver(); + + DPRINT((0,"CleanUpPICE(): trace step 6\n")); + Print(OUTPUT_WINDOW,"pICE: shutting down...\n"); + + DPRINT((0,"CleanUpPICE(): trace step 7\n")); + // cleanup the console + ConsoleShutdown(); +} diff --git a/apps/utils/pice/module/init.h b/apps/utils/pice/module/init.h new file mode 100644 index 0000000..e63332a --- /dev/null +++ b/apps/utils/pice/module/init.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + init.h + +Abstract: + + HEADER for init.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +BOOLEAN InitPICE(void); +void CleanUpPICE(void); + +extern char szBootParams[1024]; diff --git a/apps/utils/pice/module/ldrsym.h b/apps/utils/pice/module/ldrsym.h new file mode 100644 index 0000000..817ccb3 --- /dev/null +++ b/apps/utils/pice/module/ldrsym.h @@ -0,0 +1,38 @@ +// start of +// structure of symbol file +/////////////////////////////////////////////////// +typedef struct tagLoaderSymbolHeader +{ + ULONG dwMagic,dwSize; + char Copyright[256]; + char ModuleName[256]; + ULONG NumberOfSymbols; + ULONG Reserved; // for future extension +}LOADERSYMBOLHEADER,*PLOADERSYMBOLHEADER; + +typedef struct tagLoaderSymbolRecord +{ + ULONG ModuleNameLength; + ULONG NameLength; + ULONG Address; + ULONG Type; + ULONG Class; +}LOADERSYMBOLRECORD,*PLOADERSYMBOLRECORD; + +typedef struct tagLoaderSymbolFile +{ + LOADERSYMBOLHEADER LoaderSymbolHeader; // file header + LOADERSYMBOLRECORD LoaderSymbolRecord[1]; // symbol records (symbol + source file) +}LOADERSYMBOLFILE,*PLOADERSYMBOLFILE; + +typedef struct tagLoaderSymbolPool +{ + ULONG NumberOfFiles; + ULONG SizeOfThisHeap; + LOADERSYMBOLHEADER LoaderSymbolHeader; // file header + LOADERSYMBOLRECORD LoaderSymbolRecord[1]; // symbol records (symbol + source file) +}LOADERSYMBOLPOOL,*PLOADERSYMBOLPOOL; + +// end of +// structure of symbol file +/////////////////////////////////////////////////// diff --git a/apps/utils/pice/module/logo.h b/apps/utils/pice/module/logo.h new file mode 100644 index 0000000..3dea529 --- /dev/null +++ b/apps/utils/pice/module/logo.h @@ -0,0 +1,100 @@ +// this file is dynamically generated: DON'T TOUCH + +UCHAR cLogo[96]={ +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xab, +0xeb, +0xfb, +0xaf, +0xbf, +0xbf, +0xab, +0xab, +0x81, +0xe0, +0x78, +0x37, +0x9c, +0x1c, +0x03, +0x01, +0x88, +0xe2, +0x3c, +0x63, +0x9e, +0x3f, +0x8f, +0x1f, +0x9c, +0x67, +0x1c, +0x71, +0x1c, +0x1f, +0x1f, +0x1f, +0x98, +0xe2, +0x3c, +0x73, +0x3c, +0x9f, +0x9f, +0x03, +0x81, +0xe0, +0x7c, +0x71, +0x3d, +0xdf, +0x1f, +0x17, +0x83, +0xe0, +0x7c, +0x78, +0x38, +0x0f, +0x9f, +0x3f, +0x9f, +0xe7, +0x3c, +0x7c, +0x70, +0x07, +0x1f, +0x1f, +0x8f, +0xe3, +0x38, +0x38, +0x79, +0xcf, +0x9f, +0x03, +0x9f, +0xe7, +0x18, +0x3c, +0x71, +0xc7, +0x1f, +0x01, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +}; diff --git a/apps/utils/pice/module/makefile b/apps/utils/pice/module/makefile new file mode 100644 index 0000000..85ff43f --- /dev/null +++ b/apps/utils/pice/module/makefile @@ -0,0 +1,35 @@ +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = pice +TARGET_CFLAGS := -g -I../../../../ntoskrnl/include -DDEBUG +TARGET_SDK_LIBS := + +TARGET_OBJECTS = \ + hardware.o \ + dblflt.o \ + debug.o \ + disassembler.o \ + gpfault.o \ + bp.o \ + hercules.o \ + hooks.o \ + init.o \ + output.o \ + parse.o \ + patch.o \ + pgflt.o \ + privateice.o \ + serial.o \ + shell.o \ + symbols.o \ + syscall.o \ + trace.o \ + vga.o \ + vga_utils.o \ + utils.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/apps/utils/pice/module/output.c b/apps/utils/pice/module/output.c new file mode 100644 index 0000000..60ed830 --- /dev/null +++ b/apps/utils/pice/module/output.c @@ -0,0 +1,290 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + output.c + +Abstract: + + catch debugging outputs + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 14-Nov-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" +/* +#include +#include +#include +#include +#include +#include +#include +#include +*/ + +char tempOutput[1024],tempOutput2[1024]; + +//ULONG ulPrintk=0; + +ULONG (*ulPrintk) (PANSI_STRING String); + +BOOLEAN bInPrintk = FALSE; +BOOLEAN bIsDebugPrint = FALSE; +BOOLEAN bIsPrintkPatched = FALSE; + +ULONG ulCountTimerEvents = 0; + +#ifdef __cplusplus +#define CPP_ASMLINKAGE extern "C" +#else +#define CPP_ASMLINKAGE +#endif +#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) + +asmlinkage int printk(const char *fmt, ...); + +//EXPORT_SYMBOL(printk); + +//************************************************************************* +// printk() +// +// this function overrides printk() in the kernel +//************************************************************************* +asmlinkage int printk(const char *fmt, ...) +{ + ULONG len,ulRingBufferLock; + static LONGLONG ulOldJiffies = 0; + LARGE_INTEGER jiffies; + + va_list args; + va_start(args, fmt); + + if((len = PICE_strlen((LPSTR)fmt)) ) + { + save_flags(ulRingBufferLock); + cli(); + + PICE_vsprintf(tempOutput, fmt, args); + bIsDebugPrint = TRUE; + // if the last debug print was longer than 50 ms ago + // directly print it, else just add it to the ring buffer + // and let the timer process it. + KeQuerySystemTime(&jiffies); + if( (jiffies.QuadPart-ulOldJiffies) > 10000*(1*wWindow[OUTPUT_WINDOW].cy)/2) + { + ulOldJiffies = jiffies.QuadPart; + Print(OUTPUT_WINDOW,tempOutput); + } + else + { + AddToRingBuffer(tempOutput); + } + + bIsDebugPrint = FALSE; + restore_flags(ulRingBufferLock); + } + va_end(args); + + return 0; +} + +//************************************************************************* +// CountArgs() +// +// count occurrence of '%' in format string (except %%) +// validity of whole format string must have been enforced +//************************************************************************* +ULONG CountArgs(LPSTR fmt) +{ + ULONG count=0; + + while(*fmt) + { + if(*fmt=='%' && *(fmt+1)!='%') + count++; + fmt++; + } + return count; +} + +//*********************************************************************************** +// Our replacement of kernel function. +// Must not make any calls to KdpPrintString (e.g. by calling DbgPrint). +//*********************************************************************************** +ULONG PICE_KdpPrintString(PANSI_STRING String) +{ + ULONG ulRingBufferLock; + + save_flags(ulRingBufferLock); + cli(); + + /* CH: What is bIsDebugPrint used for? */ + bIsDebugPrint = FALSE; + + DPRINT((0,"PICE_KdpPrintString\n\n\n")); + AddToRingBuffer(String->Buffer); + restore_flags(ulRingBufferLock); +} +//************************************************************************* +// PrintkCallback() +// +// called from RealIsr() when processing INT3 placed +// Must not make any calls to KdpPrintString (e.g. by calling DbgPrint). +//************************************************************************* +void PrintkCallback(void) +{ + LPSTR fmt,args; + ULONG ulAddress; + ULONG countArgs,i,len; + PANSI_STRING temp; + CHAR buf[128]; + + DPRINT((0,"In PrintkCallback\n")); + + bInPrintk = TRUE; + + // get the linear address of stack where string resides + ulAddress = GetLinearAddress(CurrentSS,CurrentESP); + if(ulAddress) + { + DPRINT((0,"In PrintkCallback: ulAddress: %x\n", ulAddress)); + if(IsAddressValid(ulAddress+sizeof(char *)) ) + { + //KdpPrintString has PANSI_STRING as a parameter + temp = (PANSI_STRING)*(PULONG)(ulAddress+sizeof(char *)); + DPRINT((0,"PrintkCallback: %s\n", temp->Buffer)); + /* Call our version of KdpPrintString() */ + CurrentEIP = (ULONG_PTR)PICE_KdpPrintString; + } + } + bInPrintk = FALSE; +} + +//************************************************************************* +// PiceRunningTimer() +// +//************************************************************************* + +KTIMER PiceTimer; +KDPC PiceTimerDPC; + +// do I need it here? Have to keep DPC memory resident #pragma code_seg() +VOID PiceRunningTimer(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + CheckRingBuffer(); + + if(ulCountTimerEvents++ > 10) + { + LARGE_INTEGER jiffies; + + ulCountTimerEvents = 0; + + KeQuerySystemTime(&jiffies); + SetForegroundColor(COLOR_TEXT); + SetBackgroundColor(COLOR_CAPTION); + PICE_sprintf(tempOutput,"jiffies = %.8X\n",jiffies.u.LowPart); + PutChar(tempOutput,GLOBAL_SCREEN_WIDTH-strlen(tempOutput),GLOBAL_SCREEN_HEIGHT-1); + ResetColor(); + } +} + +//************************************************************************* +// InitPiceRunningTimer() +// +//************************************************************************* +void InitPiceRunningTimer(void) +{ + LARGE_INTEGER Interval; + + ENTER_FUNC(); +#if 0 //won't work. we have to intercept timer interrupt so dpc will never fire while we are in pice + KeInitializeTimer( &PiceTimer ); + KeInitializeDpc( &PiceTimerDPC, PiceRunningTimer, NULL ); + + Interval.QuadPart=-1000000L; // 100 millisec. (unit is 100 nanosec.) + + KeSetTimerEx(&PiceTimer, + Interval, 1000000L, + &PiceTimerDpc); +#endif + LEAVE_FUNC(); +} + +//************************************************************************* +// RemovePiceRunningTimer() +// +//************************************************************************* +void RemovePiceRunningTimer(void) +{ + KeCancelTimer( &PiceTimer ); +} + +//************************************************************************* +// InstallPrintkHook() +// +//************************************************************************* +void InstallPrintkHook(void) +{ + + ENTER_FUNC(); + + if( bIsPrintkPatched ) + return; + + DPRINT((0,"installing PrintString hook\n")); + ScanExports("_KdpPrintString",(PULONG)&ulPrintk); + + DPRINT((0,"_KdpPrintString @ %x\n", ulPrintk)); + ASSERT( ulPrintk ); // temporary + if(ulPrintk) + { + bIsPrintkPatched = InstallSWBreakpoint(ulPrintk,TRUE,PrintkCallback); + DPRINT((0,"KdpPrintStringTest breakpoint installed? %d\n", bIsPrintkPatched)); + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// DeInstallPrintkHook() +// +//************************************************************************* +void DeInstallPrintkHook(void) +{ + ENTER_FUNC(); + + DPRINT((0,"enter DeInstallPrintkHook()\n")); + if(bIsPrintkPatched && ulPrintk) + { + // will be done on exit debugger + if (DeInstallSWBreakpoint(ulPrintk)) + bIsPrintkPatched = FALSE; + } + LEAVE_FUNC(); +} diff --git a/apps/utils/pice/module/output.h b/apps/utils/pice/module/output.h new file mode 100644 index 0000000..023635d --- /dev/null +++ b/apps/utils/pice/module/output.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + output.h + +Abstract: + + HEADER for output.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void InstallPrintkHook(void); +void DeInstallPrintkHook(void); + +//extern ULONG ulPrintk; + +extern ULONG (*ulPrintk) (PANSI_STRING String); + +extern BOOLEAN bInPrintk; +extern BOOLEAN bIsDebugPrint; + +void InitPiceRunningTimer(void); +void RemovePiceRunningTimer(void); diff --git a/apps/utils/pice/module/parse.c b/apps/utils/pice/module/parse.c new file mode 100644 index 0000000..e568739 --- /dev/null +++ b/apps/utils/pice/module/parse.c @@ -0,0 +1,4099 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + parse.c + +Abstract: + + execution of debugger commands + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 19-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" +#include "pci_ids.h" + +/////////////////////////////////////////////////// +// GLOBALS + +ULONG ValueTrue=1,ValueFalse=0; +ULONG ulLastDisassStartAddress=0,ulLastDisassEndAddress=0,ulLastInvertedAddress=0; +USHORT gCurrentSelector=0; +ULONG gCurrentOffset=0; +LONG ulCurrentlyDisplayedLineNumber=0; +USHORT usOldDisasmSegment = 0; +ULONG ulOldDisasmOffset = 0; +static ULONG ulCountForWaitKey = 0; + +extern PDEBUG_MODULE pdebug_module_head; +extern PDEBUG_MODULE pdebug_module_tail; + +//extern unsigned long sys_call_table[]; + +BOOLEAN (*DisplayMemory)(PARGS) = DisplayMemoryDword; + +char szCurrentFile[256]=""; +PDEBUG_MODULE pCurrentMod=NULL; +PICE_SYMBOLFILE_HEADER* pCurrentSymbols=NULL; + +// suppresses passing on of function keys while stepping code +BOOLEAN bStepping = FALSE; +BOOLEAN bInt3Here = TRUE; +BOOLEAN bInt1Here = TRUE; + +KEYWORDS RegKeyWords[]={ + {"eax",&CurrentEAX,sizeof(ULONG)}, + {"ebx",&CurrentEBX,sizeof(ULONG)}, + {"ecx",&CurrentECX,sizeof(ULONG)}, + {"edx",&CurrentEDX,sizeof(ULONG)}, + {"edi",&CurrentEDI,sizeof(ULONG)}, + {"esi",&CurrentESI,sizeof(ULONG)}, + {"ebp",&CurrentEBP,sizeof(ULONG)}, + {"esp",&CurrentESP,sizeof(ULONG)}, + {"eip",&CurrentEIP,sizeof(ULONG)}, + {NULL,0,0} +}; + +KEYWORDS SelectorRegKeyWords[]={ + {"cs",&CurrentCS,sizeof(USHORT)}, + {"ds",&CurrentDS,sizeof(USHORT)}, + {"es",&CurrentES,sizeof(USHORT)}, + {"fs",&CurrentFS,sizeof(USHORT)}, + {"gs",&CurrentGS,sizeof(USHORT)}, + {"ss",&CurrentSS,sizeof(USHORT)}, + {NULL,0,0} +}; + +KEYWORDS OnOffKeyWords[]={ + {"on",&ValueTrue,sizeof(ULONG)}, + {"off",&ValueFalse,sizeof(ULONG)}, + {NULL,0,0} +}; + +KEYWORDS SpecialKeyWords[]={ + {"process",&CurrentProcess,sizeof(ULONG)}, + {NULL,0,0} +}; + +LPSTR LocalVarRegs[]= +{ + "EAX", + "ECX", + "EDX", + "EBX", + "ESP", + "EBP", + "ESI", + "EDI", + "EIP", + "EFL", + "CS", + "SS", + "DS", + "ES", + "FS", + "GS" +}; + + +#define COMMAND_HAS_NO_PARAMS (0) +#define COMMAND_HAS_PARAMS (1<<0) +#define COMMAND_HAS_SWITCHES (1<<1) +// +#define PARAM_CAN_BE_SYMBOLIC (1<<0) +#define PARAM_CAN_BE_SEG_OFFSET (1<<1) +#define PARAM_CAN_BE_MODULE (1<<2) +#define PARAM_CAN_BE_PRNAME (1<<3) +#define PARAM_CAN_BE_PID (1<<4) +#define PARAM_CAN_BE_SRC_FILE (1<<5) +#define PARAM_CAN_BE_NUMERIC (1<<6) +#define PARAM_CAN_BE_REG_KEYWORD (1<<7) +#define PARAM_CAN_BE_ONOFF_KEYWORD (1<<8) +#define PARAM_CAN_BE_SPECIAL_KEYWORD (1<<9) +#define PARAM_CAN_BE_ASTERISK (1<<10) +#define PARAM_CAN_BE_ONOFF (1<<11) +#define PARAM_CAN_BE_VIRTUAL_SYMBOLIC (1<<12) +#define PARAM_CAN_BE_SRCLINE (1<<13) +#define PARAM_CAN_BE_PARTIAL_SYM_NAME (1<<14) +#define PARAM_CAN_BE_ANY_STRING (1<<15) +#define PARAM_CAN_BE_DECIMAL (1<<16) +#define PARAM_CAN_BE_SIZE_DESC (1<<17) +#define PARAM_CAN_BE_LETTER (1<<18) +// +#define COMMAND_GROUP_HELP (0) +#define COMMAND_GROUP_FLOW (1) +#define COMMAND_GROUP_STRUCT (2) +#define COMMAND_GROUP_OS (3) +#define COMMAND_GROUP_MEM (4) +#define COMMAND_GROUP_BREAKPOINT (5) +#define COMMAND_GROUP_WINDOW (6) +#define COMMAND_GROUP_DEBUG (7) +#define COMMAND_GROUP_INFO (8) +#define COMMAND_GROUP_STATE (9) +#define COMMAND_GROUP_HELP_ONLY (10) +#define COMMAND_GROUP_LAST (11) + +LPSTR CommandGroups[]= +{ + "HELP", + "FLOW CONTROL", + "STRUCTURES", + "OS SPECIFIC", + "MEMORY", + "BREAKPOINTS", + "WINDOW", + "DEBUGGING", + "INFORMATION", + "STATE", + "EDITOR", + NULL +}; +// table of command handlers +CMDTABLE CmdTable[]={ + {"gdt",ShowGdt,"display current global descriptor table" ,0,{0,0,0,0,0},"",COMMAND_GROUP_STRUCT}, + {"idt",ShowIdt,"display current interrupt descriptor table" ,0,{0,0,0,0,0},"",COMMAND_GROUP_STRUCT}, + {"x",LeaveIce,"return to Reactos" ,0,{0,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"t",SingleStep,"single step one instruction" ,0,{0,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"vma",ShowVirtualMemory,"displays VMAs" ,0,{0,0,0,0,0},"",COMMAND_GROUP_OS}, + {"h",ShowHelp,"list help on commands" ,0,{0,0,0,0,0},"",COMMAND_GROUP_HELP}, + {"page",ShowPageDirs,"dump page directories" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC|PARAM_CAN_BE_REG_KEYWORD,0,0,0,0},"",COMMAND_GROUP_STRUCT}, + {"proc",ShowProcesses,"list all processes" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_PRNAME|PARAM_CAN_BE_PID,0,0,0,0},"",COMMAND_GROUP_OS}, + {"dd",DisplayMemoryDword,"display dword memory" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC|PARAM_CAN_BE_SYMBOLIC|PARAM_CAN_BE_REG_KEYWORD,0,0,0,0},"",COMMAND_GROUP_MEM}, + {"db",DisplayMemoryByte,"display byte memory " ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC|PARAM_CAN_BE_SYMBOLIC|PARAM_CAN_BE_REG_KEYWORD,0,0,0,0},"",COMMAND_GROUP_MEM}, + {"dpd",DisplayPhysMemDword,"display dword physical memory" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC,0,0,0,0},"",COMMAND_GROUP_MEM}, + {"u",Unassemble,"disassemble at address" ,COMMAND_HAS_PARAMS|COMMAND_HAS_SWITCHES,{PARAM_CAN_BE_NUMERIC|PARAM_CAN_BE_SYMBOLIC|PARAM_CAN_BE_REG_KEYWORD|PARAM_CAN_BE_SRCLINE,0,0,0,0},"f",COMMAND_GROUP_MEM}, + {"mod",ShowModules,"displays all modules" ,0,{0,0,0,0,0},"",COMMAND_GROUP_OS}, + {"bpx",SetBreakpoint,"set code breakpoint" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC|PARAM_CAN_BE_VIRTUAL_SYMBOLIC|PARAM_CAN_BE_SYMBOLIC|PARAM_CAN_BE_SRCLINE|PARAM_CAN_BE_REG_KEYWORD,0,0,0,0},"",COMMAND_GROUP_BREAKPOINT}, + {"bl",ListBreakpoints,"list breakpoints" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC,0,0,0,0},"",COMMAND_GROUP_BREAKPOINT}, + {"bc",ClearBreakpoints,"clear breakpoints" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC|PARAM_CAN_BE_ASTERISK,0,0,0,0},"",COMMAND_GROUP_BREAKPOINT}, + {"ver",Ver,"display pICE version and state information" ,0,{0,0,0,0,0},"",COMMAND_GROUP_INFO}, + {"hboot",Hboot,"hard boot the system" ,0,{0,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"code",SetCodeDisplay,"toggle code display" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_ONOFF,0,0,0,0},"",COMMAND_GROUP_STATE}, + {"cpu",ShowCPU,"display CPU special registers" ,0,{0,0,0,0,0},"",COMMAND_GROUP_STRUCT}, + {"stack",WalkStack,"display call stack" ,0,{0,0,0,0,0},"",COMMAND_GROUP_STRUCT}, + {"peek",PeekMemory,"peek at physical memory" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_SIZE_DESC,PARAM_CAN_BE_NUMERIC,0,0,0},"",COMMAND_GROUP_MEM}, + {"poke",PokeMemory,"poke to physical memory" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_SIZE_DESC,PARAM_CAN_BE_NUMERIC,PARAM_CAN_BE_NUMERIC,0,0},"",COMMAND_GROUP_MEM}, + {".",UnassembleAtCurrentEip,"unassemble at current instruction" ,0,{0,0,0,0,0},"",COMMAND_GROUP_MEM}, + {"p",StepOver,"single step over call" ,0,{0,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"i",StepInto,"single step into call" ,0,{0,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"locals",ShowLocals,"display local symbols" ,0,{0,0,0,0,0},"",COMMAND_GROUP_MEM}, + {"table",SwitchTables,"display loaded symbol tables" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_MODULE,0,0,0,0},"",COMMAND_GROUP_DEBUG}, + {"file",SwitchFiles,"display source files in symbol table" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_SRC_FILE,0,0,0,0},"",COMMAND_GROUP_DEBUG}, + {"sym",ShowSymbols,"list known symbol information" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_PARTIAL_SYM_NAME,0,0,0,0},"",COMMAND_GROUP_DEBUG}, + {"?",EvaluateExpression,"evaluate an expression" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_ANY_STRING,0,0,0,0},"",COMMAND_GROUP_DEBUG}, + {"src",SetSrcDisplay,"sets disassembly mode" ,0,{0,0,0,0,0},"",COMMAND_GROUP_DEBUG}, + {"wc",SizeCodeWindow,"change size of code window" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_DECIMAL,0,0,0,0},"",COMMAND_GROUP_WINDOW}, + {"wd",SizeDataWindow,"change size of data window" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_DECIMAL,0,0,0,0},"",COMMAND_GROUP_WINDOW}, + {"r",SetGetRegisters,"sets or displays registers" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_REG_KEYWORD,PARAM_CAN_BE_NUMERIC,0,0,0},"",COMMAND_GROUP_STRUCT}, + {"cls",ClearScreen,"clear output window" ,0,{0,0,0,0,0},"",COMMAND_GROUP_WINDOW}, + {"phys",ShowMappings,"show all mappings for linear address" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_NUMERIC,0,0,0,0},"",COMMAND_GROUP_MEM}, + {"timers",ShowTimers,"show all active timers" ,0,{0,0,0,0,0},"",COMMAND_GROUP_OS}, + {"pci",ShowPCI,"show PCI devices" ,COMMAND_HAS_PARAMS|COMMAND_HAS_SWITCHES,{PARAM_CAN_BE_DECIMAL,PARAM_CAN_BE_DECIMAL,0,0,0},"a",COMMAND_GROUP_INFO}, + {"next",NextInstr,"advance EIP to next instruction" ,0,{0,0,0,0,0},""}, + {"i3here",I3here,"catch INT 3s" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_ONOFF,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"layout",SetKeyboardLayout,"sets keyboard layout" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_ANY_STRING,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"syscall",ShowSysCallTable,"displays syscall (table)" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_DECIMAL,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"altkey",SetAltKey,"set alternate break key" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_LETTER,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"addr",ShowContext,"show/set address contexts" ,COMMAND_HAS_PARAMS,{PARAM_CAN_BE_PRNAME,0,0,0,0},"",COMMAND_GROUP_FLOW}, + {"arrow up",NULL,"" ,0,{0,0,0,0,0},"",COMMAND_GROUP_HELP_ONLY}, + {NULL,0,NULL} +}; + +char tempCmd[1024]; + +char HexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + +CPUINFO CPUInfo[]={ + {"DR0",&CurrentDR0}, + {"DR1",&CurrentDR1}, + {"DR2",&CurrentDR2}, + {"DR3",&CurrentDR3}, + {"DR6",&CurrentDR6}, + {"DR7",&CurrentDR7}, + {"EFLAGS",&CurrentEFL}, + {"CR0",&CurrentCR0}, + {"CR2",&CurrentCR2}, + {"CR3",&CurrentCR3}, + {"",NULL}, +}; + +BP Bp[4]={ + {0,0,0,FALSE,FALSE,FALSE,"",""}, + {0,0,0,FALSE,FALSE,FALSE,"",""}, + {0,0,0,FALSE,FALSE,FALSE,"",""}, + {0,0,0,FALSE,FALSE,FALSE,"",""} +}; + +BOOLEAN bShowSrc = TRUE; +BOOLEAN bCodeOn = FALSE; +BOOLEAN bNeedToFillBuffer = TRUE; + +char *NonSystemSegmentTypes[]= +{ + "Data RO", + "Data RO accessed", + "Data RW", + "Data RW accessed", + "Data RO expand-dwon", + "Data RO expand-down, accessed", + "Data RW expand-dwon", + "Data RW expand-down, accessed", + "Code EO", + "Code EO accessed", + "Code ER", + "Code ER accessed", + "Code EO conforming", + "Code EO conforming, accessed", + "Code ER conforming", + "Code ER conforming, accessed" +}; + +char *SystemSegmentTypes[]= +{ + "reserved0", + "16-bit TSS (available)", + "LDT", + "16-bit TSS (busy)", + "16-bit call gate", + "task gate", + "16-bit interrupt gate", + "16-bit trap gate", + "reserved1", + "32-bit TSS (available)", + "reserved2", + "32-bit TSS (busy)", + "32-bit call gate", + "reserved3", + "32-bit interrupt gate", + "32-bit trap gate" +}; + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// RepaintSource() +// +//************************************************************************* +void RepaintSource(void) +{ + ARGS Args; + + ENTER_FUNC(); + + // disassembly from current address + PICE_memset(&Args,0,sizeof(ARGS)); + // make unassembler refresh all again + ulLastDisassStartAddress=ulLastDisassEndAddress=0; + Args.Count=0; + Unassemble(&Args); + + LEAVE_FUNC(); +} + +//************************************************************************* +// RepaintDesktop() +// +//************************************************************************* +void RepaintDesktop(void) +{ + ARGS Args; + + ENTER_FUNC(); + + PrintTemplate(); + + DisplayRegs(); + + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + + // disassembly from current address + PICE_memset(&Args,0,sizeof(ARGS)); + // make unassembler refresh all again + ulLastDisassStartAddress=ulLastDisassEndAddress=0; + Args.Count=0; + Unassemble(&Args); + + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + Print(OUTPUT_WINDOW,""); + + ShowStoppedMsg(); + ShowStatusLine(); + + LEAVE_FUNC(); +} + +//************************************************************************* +// PutStatusText() +// +//************************************************************************* +void PutStatusText(LPSTR p) +{ + ENTER_FUNC(); + + ClrLine(wWindow[OUTPUT_WINDOW].y-1); + PutChar(p,1,wWindow[OUTPUT_WINDOW].y-1); + + LEAVE_FUNC(); +} + +//************************************************************************* +// WaitForKey() +// +//************************************************************************* +BOOLEAN WaitForKey(void) +{ + BOOLEAN result=TRUE; + + if(ulCountForWaitKey == 0) + SuspendPrintRingBuffer(TRUE); + + ulCountForWaitKey++; + + if(ulCountForWaitKey == (wWindow[OUTPUT_WINDOW].cy-1)) + { + SuspendPrintRingBuffer(FALSE); + + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + + ulCountForWaitKey = 0; + + SetBackgroundColor(WHITE); + ClrLine(wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + PutChar(" Press any key to continue listing or press ESC to stop... ",1,wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + ucKeyPressedWhileIdle=0; + while(!(ucKeyPressedWhileIdle=GetKeyPolled())) + { + PrintCursor(FALSE); + } + SetBackgroundColor(BLACK); + // if ESCAPE then indicate retreat + if(ucKeyPressedWhileIdle==SCANCODE_ESC) + { + result=FALSE; + } + ucKeyPressedWhileIdle=0; + } + + + return result; +} + +///////////////////////////////////////////////////////////// +// command handlers +///////////////////////////////////////////////////////////// + +//************************************************************************* +// SingleStep() +// +//************************************************************************* +COMMAND_PROTOTYPE(SingleStep) +{ + ULONG ulLineNumber; + LPSTR pSrcStart,pSrcEnd,pFilename; + + ENTER_FUNC(); + + if(FindSourceLineForAddress(GetLinearAddress(CurrentCS,CurrentEIP),&ulLineNumber,&pSrcStart,&pSrcEnd,&pFilename)) + { + DPRINT((0,"SingleStep(): stepping into source\n")); + StepInto(NULL); + } + else + { + // modify trace flag + CurrentEFL|=0x100; // set trace flag (TF) + + bSingleStep=TRUE; + bNotifyToExit=TRUE; + } + + bStepping = TRUE; + + LEAVE_FUNC(); + + return TRUE; +} + + +//************************************************************************* +// StepOver() +// +// step over calls +//************************************************************************* +COMMAND_PROTOTYPE(StepOver) +{ + char tempDisasm[256]; + ULONG dwBreakAddress; + ULONG ulLineNumber; + LPSTR pSrcStart,pSrcEnd,pFilename; + + ENTER_FUNC(); + + DPRINT((0,"StepOver():\n")); + + // only no arguments supplied + // when we have source and current disassembly mod is SOURCE + // we have to analyse the code block for the source line + if(FindSourceLineForAddress(GetLinearAddress(CurrentCS,CurrentEIP),&ulLineNumber,&pSrcStart,&pSrcEnd,&pFilename)) + { + DPRINT((0,"StepOver(): we have source here!\n")); + DPRINT((0,"StepOver(): line #%u in file = %s!\n",ulLineNumber,pFilename)); + + g_ulLineNumberStart = ulLineNumber; + bStepThroughSource = TRUE; + + // deinstall the INT3 in kernel's printk() + DeInstallPrintkHook(); + + goto proceed_as_normal; + } + else + { + DPRINT((0,"StepOver(): no source here!\n")); + +proceed_as_normal: + // if there is some form of call instruction at EIP we need to find + // the return address + if(IsCallInstrAtEIP()) + { + // get address of next instruction + dwBreakAddress=GetLinearAddress(CurrentCS,CurrentEIP); + + Disasm(&dwBreakAddress,tempDisasm); + + DPRINT((0,"address of break = %.4X:%.8X\n",CurrentCS,dwBreakAddress)); + + dwBreakAddress=GetLinearAddress(CurrentCS,dwBreakAddress); + + DPRINT((0,"linear address of break = %.8X\n",dwBreakAddress)); + + DPRINT((0,"setting DR0=%.8X\n",dwBreakAddress)); + + SetHardwareBreakPoint(dwBreakAddress,0); + + bSingleStep = FALSE; + bNotifyToExit = TRUE; + } + else + { + DPRINT((0,"no call at breakpoint\n")); + // modify trace flag + CurrentEFL|=0x100; // set trace flag (TF) + + bSingleStep=TRUE; + bNotifyToExit=TRUE; + } + } + + bStepInto = FALSE; + + bStepping = TRUE; + + LEAVE_FUNC(); + + return TRUE; +} + +//************************************************************************* +// StepInto() +// +// step into calls +//************************************************************************* +COMMAND_PROTOTYPE(StepInto) +{ + ULONG ulLineNumber; + LPSTR pSrcStart,pSrcEnd,pFilename; + + ENTER_FUNC(); + + // only no arguments supplied + // when we have source and current disassembly mod is SOURCE + // we have to analyse the code block for the source line + if(FindSourceLineForAddress(GetLinearAddress(CurrentCS,CurrentEIP),&ulLineNumber,&pSrcStart,&pSrcEnd,&pFilename)) + { + DPRINT((0,"StepOver(): we have source here!\n")); + DPRINT((0,"StepOver(): line #%u in file = %s!\n",ulLineNumber,pFilename)); + + g_ulLineNumberStart = ulLineNumber; + bStepThroughSource = TRUE; + + // deinstall the INT3 in kernel's printk() + DeInstallPrintkHook(); + + goto proceed_as_normal_into; + } + else + { + DPRINT((0,"StepInto(): no source here!\n")); + +proceed_as_normal_into: + + // modify trace flag + CurrentEFL|=0x100; // set trace flag (TF) + + bSingleStep=TRUE; + bNotifyToExit=TRUE; + } + + bStepInto = TRUE; + + bStepping = TRUE; + + LEAVE_FUNC(); + + return TRUE; +} + +//************************************************************************* +// SetBreakpoint() +// +//************************************************************************* +COMMAND_PROTOTYPE(SetBreakpoint) +{ + ULONG addr,addrorg; + USHORT segment; + + if(pArgs->Count<=2) + { + if(pArgs->bNotTranslated[0]==FALSE) + { + if(gCurrentSelector) + { + addr=pArgs->Value[0]; + addrorg=gCurrentOffset; + segment=gCurrentSelector; + } + else + { + addrorg=addr=pArgs->Value[0]; + segment=CurrentCS; + } + + if(InstallSWBreakpoint(GetLinearAddress(segment,addr),FALSE,NULL) ) + { + PICE_sprintf(tempCmd,"BP #%u set to %.4X:%.8X\n",0,segment,addr); + } + else + { + PICE_sprintf(tempCmd,"BP #%u NOT set (either page not valid OR already used)\n",0); + } + Print(OUTPUT_WINDOW,tempCmd); + } + else + { + if(InstallVirtualSWBreakpoint((LPSTR)pArgs->Value[0],(LPSTR)pArgs->Value[1]) ) + { + PICE_sprintf(tempCmd,"BP #%u virtually set to %s!%s\n",0,(LPSTR)pArgs->Value[0],(LPSTR)pArgs->Value[1]); + } + else + { + PICE_sprintf(tempCmd,"BP #%u NOT set (maybe no symbols loaded)\n",0); + } + Print(OUTPUT_WINDOW,tempCmd); + } + + RepaintSource(); + + } + return TRUE; +} + +//************************************************************************* +// ListBreakpoints() +// +//************************************************************************* +COMMAND_PROTOTYPE(ListBreakpoints) +{ + ULONG i; + + ListSWBreakpoints(); + + for(i=0;i<4;i++) + { + if(Bp[i].Used) + { + PICE_sprintf(tempCmd,"(%u) %s %.4X:%.8X(linear %.8X)\n",i,Bp[i].Active?"*":" ",Bp[i].Segment,Bp[i].Offset,Bp[i].LinearAddress); + Print(OUTPUT_WINDOW,tempCmd); + } + } + return TRUE; +} + +//************************************************************************* +// ClearBreakpoints() +// +//************************************************************************* +COMMAND_PROTOTYPE(ClearBreakpoints) +{ + if(pArgs->Count) + { + if(pArgs->Value[0]<4) + { + Bp[pArgs->Value[0]].Used=Bp[pArgs->Value[0]].Active=FALSE; + } + RepaintSource(); + } + else + { + ULONG i; + + RemoveAllSWBreakpoints(FALSE); + + for(i=0;i<4;i++)Bp[i].Used=Bp[i].Active=FALSE; + RepaintSource(); + } + return TRUE; +} + +//************************************************************************* +// LeaveIce() +// +//************************************************************************* +COMMAND_PROTOTYPE(LeaveIce) +{ + // SetHardwareBreakPoints(); + + bSingleStep=FALSE; + bNotifyToExit=TRUE; + return TRUE; +} + +//************************************************************************* +// ShowGdt() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowGdt) +{ + ULONG gdtr[2]; + USHORT i; + PGDT pGdt; + static ULONG addr=0; + LPSTR pVerbose; + + // get GDT register + __asm__ ("sgdt %0\n" + :"=m" (gdtr)); + + // info out + PICE_sprintf(tempCmd,"Address=%.8X Limit=%.4X\n",(gdtr[1]<<16)|(gdtr[0]>>16),gdtr[0]&0xFFFF); + Print(OUTPUT_WINDOW,tempCmd); + WaitForKey(); + + // make pointer to GDT + pGdt=(PGDT)(((ULONG)(gdtr[1]<<16))|((ULONG)(gdtr[0]>>16))); + if(pArgs->Count==1) + { + ULONG limit=((pGdt[addr].Limit_19_16<<16)|pGdt[addr].Limit_15_0); + + addr=pArgs->Value[0]; + addr&=(~0x7); + if(pGdt[addr>>3].Gran)limit=(limit*4096)|0xfff; + + if(!pGdt[addr>>3].DescType) + pVerbose = SystemSegmentTypes[pGdt[addr>>3].SegType]; + else + pVerbose = NonSystemSegmentTypes[pGdt[addr>>3].SegType]; + + PICE_sprintf(tempCmd,"%.4X %.8X %.8X %s %u %s\n", + addr, + (pGdt[addr>>3].Base_31_24<<24)|(pGdt[addr>>3].Base_23_16<<16)|(pGdt[addr>>3].Base_15_0), + limit, + pGdt[addr>>3].Present?" P":"NP", + pGdt[addr>>3].Dpl, + pVerbose); + Print(OUTPUT_WINDOW,tempCmd); + } + else if(pArgs->Count==0) + { + for(i=0;i<((gdtr[0]&0xFFFF)>>3);i++) + { + ULONG limit=((pGdt[i].Limit_19_16<<16)|pGdt[i].Limit_15_0); + + if(!pGdt[i].DescType) + pVerbose = SystemSegmentTypes[pGdt[i].SegType]; + else + pVerbose = NonSystemSegmentTypes[pGdt[i].SegType]; + + if(pGdt[i].Gran)limit=(limit*4096)|0xfff; + + PICE_sprintf(tempCmd,"%.4X %.8X %.8X %s %u %s\n", + i<<3, + (pGdt[i].Base_31_24<<24)|(pGdt[i].Base_23_16<<16)|(pGdt[i].Base_15_0), + limit, + pGdt[i].Present?" P":"NP", + pGdt[i].Dpl, + pVerbose); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + } + return TRUE; +} + +//************************************************************************* +// OutputIdtEntry() +// +//************************************************************************* +void OutputIdtEntry(PIDT pIdt,ULONG i) +{ + USHORT seg; + ULONG offset; + LPSTR pSym; + + seg = (USHORT)pIdt[i].Selector; + offset = (pIdt[i].Offset_31_16<<16)|(pIdt[i].Offset_15_0); + + switch(pIdt[i].DescType) + { + // task gate + case 0x5: + PICE_sprintf(tempCmd,"(%0.4X) %0.4X:%0.8X %u [task]\n",i, + seg, + GetLinearAddress((USHORT)seg,0), + pIdt[i].Dpl); + break; + // interrupt gate + case 0x6: + case 0xE: + if(ScanExportsByAddress(&pSym,GetLinearAddress((USHORT)seg,offset))) + { + PICE_sprintf(tempCmd,"(%0.4X) %0.4X:%0.8X %u [int] (%s)\n",i, + seg, + offset, + pIdt[i].Dpl, + pSym); + } + else + { + PICE_sprintf(tempCmd,"(%0.4X) %0.4X:%0.8X %u [int]\n",i, + seg, + offset, + pIdt[i].Dpl); + } + break; + // trap gate + case 0x7: + case 0xF: + if(ScanExportsByAddress(&pSym,GetLinearAddress((USHORT)seg,offset))) + { + PICE_sprintf(tempCmd,"(%0.4X) %0.4X:%0.8X %u [trap] (%s)\n",i, + seg, + offset, + pIdt[i].Dpl, + pSym); + } + else + { + PICE_sprintf(tempCmd,"(%0.4X) %0.4X:%0.8X %u [trap]\n",i, + seg, + offset, + pIdt[i].Dpl); + } + break; + default: + PICE_sprintf(tempCmd,"(%0.4X) INVALID\n",i); + break; + } + Print(OUTPUT_WINDOW,tempCmd); +} + +//************************************************************************* +// ShowIdt() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowIdt) +{ + ULONG idtr[2]; + USHORT i; + PIDT pIdt; + ULONG addr=0; + + ENTER_FUNC(); + + // get GDT register + __asm__ ("sidt %0\n" + :"=m" (idtr)); + // info out + PICE_sprintf(tempCmd,"Address=%.8X Limit=%.4X\n",(idtr[1]<<16)|(idtr[0]>>16),idtr[0]&0xFFFF); + Print(OUTPUT_WINDOW,tempCmd); + WaitForKey(); + // make pointer to GDT + pIdt=(PIDT)(((ULONG)(idtr[1]<<16))|((ULONG)(idtr[0]>>16))); + if(pArgs->Count==1) + { + addr=pArgs->Value[0]; + addr&=(~0x7); + + } + else if(pArgs->Count==0) + { + for(i=0;i<((idtr[0]&0xFFFF)>>3);i++) + { + OutputIdtEntry(pIdt,i); + if(WaitForKey()==FALSE)break; + } + } + LEAVE_FUNC(); + return TRUE; +} + +//************************************************************************* +// ShowHelp() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowHelp) +{ + ULONG i,j; + + PutStatusText("COMMAND KEYWORD DESCRIPTION"); + for(j=0;j show all page directories + if(!pArgs->Count) + { + PutStatusText("Linear Physical Attributes"); + // there are 1024 page directories each mapping 1024*4k of address space + for(i=0;i<1024;i++) + { + ULONG ulAddress = i<<22; + // from the mm_struct get pointer to page directory for this address + pPGD = ADDR_TO_PDE(ulAddress); + // create a structurized pointer from PGD + pPageDir = (PPAGEDIR)pPGD; + + if(pPageDir->PTBase) + { + + PICE_sprintf(tempCmd,"%.8X-%.8X %.8X %s %s %s\n", + ulAddress, ulAddress + 0x400000, + (pPageDir->PTBase<<12), + pPageDir->P?"P ":"NP", + pPageDir->RW?"RW":"R ", + pPageDir->US?"U":"S"); + Print(OUTPUT_WINDOW,tempCmd); + + if(WaitForKey()==FALSE)break; + } + } + } + + // one arg supplied -> show individual page + else if(pArgs->Count == 1) + { + pPGD = ADDR_TO_PDE((ULONG)pArgs->Value[0]); + + DPRINT((0,"ShowPageDirs(): VA = %.8X\n",pArgs->Value[0])); + DPRINT((0,"ShowPageDirs(): pPGD = %.8X\n",(ULONG)pPGD)); + + if(pPGD && ((*pPGD)&_PAGE_PRESENT)) + { + // 4M page + if((*pPGD)&_PAGE_4M) + { + PPAGEDIR pPage = (PPAGEDIR)pPGD; + + PutStatusText("Linear Physical Attributes"); + + PICE_sprintf(tempCmd,"%.8X %.8X %s %s %s (LARGE PAGE PTE @ %.8X)\n", + pArgs->Value[0], + (pPage->PTBase<<12)|(pArgs->Value[0]&0x7FFFFF), + pPage->P?"P ":"NP", + pPage->RW?"RW":"R ", + pPage->US?"U":"S", + (ULONG)pPGD); + } + else + { + pPTE = ADDR_TO_PTE(pArgs->Value[0]); + DPRINT((0,"ShowPageDirs(): pPTE = %.8X\n",(ULONG)pPTE)); + if(pPTE) + { + PPAGEDIR pPage = (PPAGEDIR)pPTE; + DPRINT((0,"ShowPageDirs(): pPage->PTBase = %.8X\n",(ULONG)pPage->PTBase)); + + PutStatusText("Linear Physical Attributes"); + + PICE_sprintf(tempCmd,"%.8X %.8X %s %s %s (PTE @ %.8X)\n", + pArgs->Value[0], + (pPage->PTBase<<12)|(pArgs->Value[0]&(_PAGE_SIZE-1)), + (pPage->P==1)?"P ":"NP", + pPage->RW?"RW":"R ", + pPage->US?"U":"S", + (ULONG)pPTE); + } + + } + Print(OUTPUT_WINDOW,tempCmd); + } + else + { + PICE_sprintf(tempCmd,"page at %.8X not present.\n",pArgs->Value[0]); + Print(OUTPUT_WINDOW,tempCmd); + } + + } + } + return TRUE; +} + +//************************************************************************* +// ShowProcesses() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowProcesses) +{ + PEPROCESS my_current = IoGetCurrentProcess(); + PLIST_ENTRY current_entry; + PEPROCESS currentps; + + ENTER_FUNC(); + + current_entry = pPsProcessListHead->Flink; + + if( current_entry ){ + + PutStatusText("NAME TASK PID"); + + while( current_entry != pPsProcessListHead ){ + currentps = CONTAINING_RECORD(current_entry, + EPROCESS, + ProcessListEntry); + DPRINT((0,"currentps = %x\n",currentps)); + //ei would be nice to mark current process! + PICE_sprintf(tempCmd,"%-16.16s %-12x %x\n",currentps->ImageFileName, + (ULONG)currentps,currentps->UniqueProcessId); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE) + break; + current_entry = current_entry->Flink; + } + } + LEAVE_FUNC(); + return TRUE; +} + +//************************************************************************* +// DisplayMemoryDword() +// +//************************************************************************* +COMMAND_PROTOTYPE(DisplayMemoryDword) +{ + ULONG i,j,k; + static ULONG addr=0,addrorg; + static USHORT segment; + char temp[8]; + LPSTR pSymbolName; + + ENTER_FUNC(); + DPRINT((0,"DisplayMemoryDword()\n")); + if(pArgs->Count==2) + { + segment=(USHORT)pArgs->Value[0]; + if(!segment)segment=GLOBAL_DATA_SEGMENT; + addr=pArgs->Value[1]; + OldSelector = segment; + OldOffset = addr; + addrorg=addr; + addr=GetLinearAddress(segment,addr); + } + else if(pArgs->Count==1) + { + segment=CurrentDS; + addr=pArgs->Value[0]; + OldOffset = addr; + addrorg=addr; + addr=GetLinearAddress(segment,addr); + } + else if(pArgs->Count==0) + { + addr += sizeof(ULONG)*4*4; + OldOffset = addr; + } + + if(ScanExportsByAddress(&pSymbolName,addr)) + { + PICE_sprintf(tempCmd," %s ",pSymbolName); + SetForegroundColor(COLOR_TEXT); + SetBackgroundColor(COLOR_CAPTION); + PutChar(tempCmd,GLOBAL_SCREEN_WIDTH-1-PICE_strlen(tempCmd),wWindow[DATA_WINDOW].y-1); + ResetColor(); + } + + DisableScroll(DATA_WINDOW); + + if(DisplayMemory != DisplayMemoryDword) + { + Clear(DATA_WINDOW); + DisplayMemory = DisplayMemoryDword; + } + else + Home(DATA_WINDOW); + + for(k=0;kCount==2) + { + segment=(USHORT)pArgs->Value[0]; + if(!segment)segment=GLOBAL_DATA_SEGMENT; + addr=pArgs->Value[1]; + OldSelector = segment; + OldOffset = addr; + addrorg=addr; + addr=GetLinearAddress(segment,addr); + } + else if(pArgs->Count==1) + { + segment=CurrentDS; + addr=pArgs->Value[0]; + OldOffset = addr; + addrorg=addr; + addr=GetLinearAddress(segment,addr); + } + else if(pArgs->Count==0) + { + addr += sizeof(ULONG)*4*4; + OldOffset = addr; + } + + if(DisplayMemory != DisplayMemoryByte) + { + Clear(DATA_WINDOW); + DisplayMemory = DisplayMemoryByte; + } + else + Home(DATA_WINDOW); + + if(ScanExportsByAddress(&pSymbolName,addr)) + { + PICE_sprintf(tempCmd," %s ",pSymbolName); + SetForegroundColor(COLOR_TEXT); + SetBackgroundColor(COLOR_CAPTION); + PutChar(tempCmd,GLOBAL_SCREEN_WIDTH-1-PICE_strlen(tempCmd),wWindow[DATA_WINDOW].y-1); + ResetColor(); + } + + DisableScroll(DATA_WINDOW); + for(k=0;kCount==1) + { + segment=CurrentDS; + addr=pArgs->Value[0]; + OldOffset = addr; + addrorg=addr; + addr=GetLinearAddress(segment,addr); + } + else if(pArgs->Count==0) + { + addr += sizeof(ULONG)*4*4; + OldOffset = addr; + } + + DisableScroll(DATA_WINDOW); + + if(DisplayMemory != DisplayPhysMemDword) + { + Clear(DATA_WINDOW); + DisplayMemory = DisplayPhysMemDword; + } + else + Home(DATA_WINDOW); + + for(k=0;kGLOBAL_SCREEN_WIDTH-1) + { + tempCmd[GLOBAL_SCREEN_WIDTH-2]='\n'; + tempCmd[GLOBAL_SCREEN_WIDTH-1]=0; + } + + if( (ulLineNumberToInvert!=-1) && + ((int)(ulLineNumberToInvert-ulLineNumber)>=0) && + ((ulLineNumberToInvert-ulLineNumber)=0) && + ((ulLineNumberToInvert-ulLineNumber)CountSwitches, pArgs->Count)); + if(pArgs->CountSwitches>1) + return TRUE; + + if(pArgs->CountSwitches==1) + { + if(pArgs->Switch[0] == 'f') + bForceDisassembly = TRUE; + } + + // we have args + if(pArgs->Count==2) + { + addr=pArgs->Value[1]; + segment=(USHORT)pArgs->Value[0]; + addrorg=addrstart=addr; + addr=GetLinearAddress(segment,addr); + + usOldDisasmSegment = segment; + ulOldDisasmOffset = addr; + } + else if(pArgs->Count==1) + { + addr=pArgs->Value[0]; + segment=CurrentCS; + addrorg=addrstart=addr; + addr=GetLinearAddress(segment,addr); + + usOldDisasmSegment = segment; + ulOldDisasmOffset = addr; + } + else if(pArgs->Count==0) + { + segment = usOldDisasmSegment; + addrorg=addrstart=addr; + addr = GetLinearAddress(usOldDisasmSegment,ulOldDisasmOffset); + } + else + return TRUE; + + + DPRINT((0,"Unassemble(%0.4X:%0.8X), lastst: %x, lastend:%x\n",segment,addr,ulLastDisassStartAddress,ulLastDisassEndAddress)); + + // + // unassemble + // + DisableScroll(SOURCE_WINDOW); + + // if we're inside last disassembly range we only need to move to highlight + if(ulLastDisassStartAddress && ulLastDisassEndAddress && addr>=ulLastDisassStartAddress && + addrname = %S\n",pCurrentMod->name)); + mod_addr = (ULONG)pCurrentMod->BaseAddress; + + pCurrentSymbols = FindModuleSymbols(mod_addr); + DPRINT((0,"Unassemble(): pCurrentSymbols = %x\n",(ULONG)pCurrentSymbols)); + } + DPRINT((0,"Unassemble(): pCurrentMod = %x, showsrc: %d\n",pCurrentMod, bShowSrc)); + + ulCurrentlyDisplayedLineNumber = 0; + + if(bShowSrc && bForceDisassembly == FALSE && (pSrc = FindSourceLineForAddress(addr,&ulLineNumber,&pSrcStart,&pSrcEnd,&pFilename)) ) + { + DPRINT((0,"FoundSourceLineForAddress: file: %s line: %d\n", pFilename, ulLineNumber)); + PICE_strcpy(szCurrentFile,pFilename); + + ulCurrentlyDisplayedLineNumber = ulLineNumber; + + Clear(SOURCE_WINDOW); + + // display file name + SetForegroundColor(COLOR_TEXT); + SetBackgroundColor(COLOR_CAPTION); + + if(PICE_strlen(pFilename)(wWindow[SOURCE_WINDOW].cy/2) ) + { + DisplaySourceFile(pSrcStart,pSrcEnd,ulLineNumber-(wWindow[SOURCE_WINDOW].cy/2),ulLineNumber); + } + else + { + DisplaySourceFile(pSrcStart,pSrcEnd,ulLineNumber,ulLineNumber); + } + } + else + { + *szCurrentFile = 0; + DPRINT((0,"Couldn't find source for file\n")); + Home(SOURCE_WINDOW); + // for each line in the disassembly window + for(i=0;i>4)]; + tempCmd[j*2+1]=HexDigit[((*(PUCHAR)(addrbefore+j)&0xF))]; + } + else + { + tempCmd[j*2]='?'; + tempCmd[j*2+1]='?'; + } + } + else + { + tempCmd[j*2]=' '; + tempCmd[j*2+1]=' '; + } + } + } + PICE_strcat(tempCmd,"\n"); + + if(ulWindowOffset) + { + LONG len = PICE_strlen(tempCmd); + if(ulWindowOffset < len) + PICE_memcpy(tempCmd,&tempCmd[ulWindowOffset],len-ulWindowOffset); + else + tempCmd[0]='\n'; + } + + Print(SOURCE_WINDOW,tempCmd); + + if(addrbefore==CurrentEIP) + { + ResetColor(); + } + + // if potential SW breakpoint, undo marked text + if(IsSwBpAtAddress(addrbefore)) + { + HatchLine(wWindow[SOURCE_WINDOW].y+i); + } + + // if breakpoint was installed before disassembly, put it back + if(bSWBpAtAddr) + { + ReInstallSWBreakpoint(addrbefore); + } + + } + + if(ulLastDisassStartAddress==0 && ulLastDisassEndAddress==0) + { + ulLastDisassStartAddress=addrstart; + ulLastDisassEndAddress=addr; + } + + if(!IsAddressValid(addrstart)) + { + ulLastDisassStartAddress=0; + ulLastDisassEndAddress=0; + } + + } + + EnableScroll(SOURCE_WINDOW); + + return TRUE; +} + +//************************************************************************* +// ShowModules() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowModules) +{ + PDEBUG_MODULE pMod; + DPRINT((0,"ShowModules()\n")); + + if(BuildModuleList()) + { + pMod = pdebug_module_head; + do + { + if(pMod->size) + { + if(pMod == pCurrentMod) + { + PICE_sprintf(tempCmd,"%.8X - %.8X *%-32S\n", + (unsigned int)pMod->BaseAddress, + (unsigned int) ((unsigned int)pMod->BaseAddress+pMod->size),pMod->name); + } + else + { + PICE_sprintf(tempCmd,"%.8X - %.8X %-32S\n", + (unsigned int)pMod->BaseAddress, + (unsigned int) ((unsigned int)pMod->BaseAddress+pMod->size), + pMod->name); + } + } + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE) + break; + }while((pMod = pMod->next)!=pdebug_module_tail); + } + return TRUE; +} + +//************************************************************************* +// DecodeVmFlags() +// +//************************************************************************* +//ei FIX THIS!!!!!!!!!!!!!!!!!! +LPSTR DecodeVmFlags(ULONG flags) +{ + ULONG i; +/* +#define VM_READ 0x0001 +#define VM_WRITE 0x0002 +#define VM_EXEC 0x0004 +#define VM_SHARED 0x0008 + +#define VM_MAYREAD 0x0010 +#define VM_MAYWRITE 0x0020 +#define VM_MAYEXEC 0x0040 +#define VM_MAYSHARE 0x0080 + +#define VM_GROWSDOWN 0x0100 +#define VM_GROWSUP 0x0200 +#define VM_SHM 0x0400 +#define VM_DENYWRITE 0x0800 + +#define VM_EXECUTABLE 0x1000 +#define VM_LOCKED 0x2000 +#define VM_IO 0x4000 + +#define VM_STACK_FLAGS 0x0177 +*/ + static LPSTR flags_syms_on[]={"R","W","X","S","MR","MW","MX","MS","GD","GU","SHM","exe","LOCK","IO",""}; + static char temp[256]; + + // terminate string + *temp = 0; +//ei fix fix fix +#if 0 + + if(flags == VM_STACK_FLAGS) + { + PICE_strcpy(temp," (STACK)"); + } + else + { + for(i=0;i<15;i++) + { + if(flags&0x1) + { + PICE_strcat(temp," "); + PICE_strcat(temp,flags_syms_on[i]); + } + flags >>= 1; + } + } +#endif + return temp; +} + +//************************************************************************* +// ShowVirtualMemory() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowVirtualMemory) +{ + PEPROCESS my_current = IoGetCurrentProcess(); + PLIST_ENTRY current_entry; + PMADDRESS_SPACE vma = NULL; + MEMORY_AREA* current; + char filename[64]; + + DPRINT((0,"ShowVirtualMemory()\n")); + if( my_current ) + vma = &(my_current->AddressSpace); + if( !vma ) + vma = my_init_mm; + while( vma ) + { + if(pArgs->Count == 0) + { + PutStatusText("START END LENGTH VMA TYPE ATTR"); + current_entry = vma->MAreaListHead.Flink; + while (current_entry != &vma->MAreaListHead) + { + *filename = 0; + + current = CONTAINING_RECORD(current_entry, + MEMORY_AREA, + Entry); + // find the filename + if(((current->Type == MEMORY_AREA_SECTION_VIEW) ) && + current->Data.SectionData.Section->FileObject) + { + if(IsAddressValid((ULONG)current->Data.SectionData.Section->FileObject->FileName.Buffer) ) + PICE_sprintf(filename,"%.64S",current->Data.SectionData.Section->FileObject->FileName.Buffer); + } + + PICE_sprintf(tempCmd,"%.8X %.8X %.8X %.8X %x %x %s\n", + (ULONG)current->BaseAddress, + (ULONG)current->BaseAddress+current->Length, + current->Length, + (ULONG)current, + current->Type, current->Attributes,//DecodeVmFlags(current->Type, current->Attributes), + filename); + Print(OUTPUT_WINDOW,tempCmd); + + if(WaitForKey()==FALSE) + break; + current_entry = current_entry->Flink; + } + } + if( vma == &(my_current->AddressSpace) ) + vma = my_init_mm; // switch to kernel memory area + else vma = 0; // if we already did kernel, end loop + } + return TRUE; +} + +//************************************************************************* +// Ver() +// +//************************************************************************* +COMMAND_PROTOTYPE(Ver) +{ + //ei add kernel version info??!! + PICE_sprintf(tempCmd,"pICE: version %u.%u (build %u) for Reactos\n", + PICE_MAJOR_VERSION, + PICE_MINOR_VERSION, + PICE_BUILD); + + Print(OUTPUT_WINDOW,tempCmd); + +/* PICE_sprintf(tempCmd,"pICE: loaded on %s kernel release %s\n", + system_utsname.sysname, + system_utsname.release); + */ + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,"pICE: written by Klaus P. Gerlicher and Goran Devic.\n"); + Print(OUTPUT_WINDOW,"pICE: ported to Reactos by Eugene Ingerman.\n"); + + return TRUE; +} + +//************************************************************************* +// Hboot() +// +//************************************************************************* +COMMAND_PROTOTYPE(Hboot) +{ + // nudge the reset line through keyboard controller + __asm__("\n\t \ + movb $0xFE,%al\n\t \ + outb %al,$0x64"); + // never gets here + return TRUE; +} + +//************************************************************************* +// SetSrcDisplay() +// +//************************************************************************* +COMMAND_PROTOTYPE(SetSrcDisplay) +{ + ARGS Args; + + if(pArgs->Count==0) + { + bShowSrc=bShowSrc?FALSE:TRUE; + PICE_memset(&Args,0,sizeof(ARGS)); + // make unassembler refresh all again + ulLastDisassStartAddress=ulLastDisassEndAddress=0; + Args.Count=0; + Unassemble(&Args); + } + return TRUE; +} + +//************************************************************************* +// I3here() +// +//************************************************************************* +COMMAND_PROTOTYPE(I3here) +{ + if(pArgs->Count==1) + { + if(pArgs->Value[0]==1) + { + if(!bInt3Here) + { + bInt3Here=TRUE; + Print(OUTPUT_WINDOW,"I3HERE is now ON\n"); + } + else + Print(OUTPUT_WINDOW,"I3HERE is already ON\n"); + } + else if(pArgs->Value[0]==0) + { + if(bInt3Here) + { + bInt3Here=FALSE; + Print(OUTPUT_WINDOW,"I3HERE is now OFF\n"); + } + else + Print(OUTPUT_WINDOW,"I3HERE is already OFF\n"); + } + } + else if(pArgs->Count==0) + { + if(bInt3Here) + { + Print(OUTPUT_WINDOW,"I3HERE is ON\n"); + } + else + { + Print(OUTPUT_WINDOW,"I3HERE is OFF\n"); + } + } + // never gets here + return TRUE; +} + +COMMAND_PROTOTYPE(I1here) +{ + if(pArgs->Count==1) + { + if(pArgs->Value[0]==1) + { + if(!bInt1Here) + { + bInt1Here=TRUE; + Print(OUTPUT_WINDOW,"I1HERE is now ON\n"); + } + else + Print(OUTPUT_WINDOW,"I1HERE is already ON\n"); + } + else if(pArgs->Value[0]==0) + { + if(bInt1Here) + { + bInt1Here=FALSE; + Print(OUTPUT_WINDOW,"I1HERE is now OFF\n"); + } + else + Print(OUTPUT_WINDOW,"I1HERE is already OFF\n"); + } + } + else if(pArgs->Count==0) + { + if(bInt1Here) + { + Print(OUTPUT_WINDOW,"I1HERE is ON\n"); + } + else + { + Print(OUTPUT_WINDOW,"I1HERE is OFF\n"); + } + } + // never gets here + return TRUE; +} + +COMMAND_PROTOTYPE(NextInstr) +{ + static char tempDisasm[256]; + ULONG addr,addrbefore; + + bNeedToFillBuffer=FALSE; + + if(!pArgs->Count) + { + addr=addrbefore=GetLinearAddress(CurrentCS,CurrentEIP); + DPRINT((0,"addr before %.8X\n",addrbefore)); + Disasm(&addr,tempDisasm); + DPRINT((0,"addr after %.8X\n",addr)); + CurrentEIP=CurrentEIP+(addr-addrbefore); + // display register contents + DisplayRegs(); + // unassemble + DPRINT((0,"new CS:EIP %04.x:%.8X\n",CurrentCS,CurrentEIP)); + PICE_memset(pArgs,0,sizeof(ARGS)); + // make unassembler refresh all again + ulLastDisassStartAddress=ulLastDisassEndAddress=0; + pArgs->Count=2; + pArgs->Value[0]=(ULONG)CurrentCS; + pArgs->Value[1]=CurrentEIP; + Unassemble(pArgs); + } + bNeedToFillBuffer=TRUE; + return TRUE; +} + +COMMAND_PROTOTYPE(SetGetRegisters) +{ + ULONG i; + + if(pArgs->Count==0) + { + // display whole set + for(i=0;RegKeyWords[i].pValue!=0;i++) + { + switch(RegKeyWords[i].ulSize) + { + case 1: + PICE_sprintf(tempCmd,"%s = %.8X\n",RegKeyWords[i].KeyWord,*(PUCHAR)(RegKeyWords[i].pValue)); + break; + case 2: + PICE_sprintf(tempCmd,"%s = %.8X\n",RegKeyWords[i].KeyWord,*(PUSHORT)(RegKeyWords[i].pValue)); + break; + case 4: + PICE_sprintf(tempCmd,"%s = %.8X\n",RegKeyWords[i].KeyWord,*(PULONG)(RegKeyWords[i].pValue)); + break; + } + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + } + else if(pArgs->Count==1) + { + // display selected register + for(i=0;RegKeyWords[i].pValue!=0;i++) + { + if(PICE_strcmpi(pArgs->pToken[0],RegKeyWords[i].KeyWord)==0) + { + switch(RegKeyWords[i].ulSize) + { + case 1: + PICE_sprintf(tempCmd,"%s = %.2X\n",RegKeyWords[i].KeyWord,*(PUCHAR)(RegKeyWords[i].pValue)); + break; + case 2: + PICE_sprintf(tempCmd,"%s = %.4X\n",RegKeyWords[i].KeyWord,*(PUSHORT)(RegKeyWords[i].pValue)); + break; + case 4: + PICE_sprintf(tempCmd,"%s = %.8X\n",RegKeyWords[i].KeyWord,*(PULONG)(RegKeyWords[i].pValue)); + break; + } + Print(OUTPUT_WINDOW,tempCmd); + break; + } + } + } + else if(pArgs->Count==2) + { + // set selected register to value + for(i=0;RegKeyWords[i].pValue!=0;i++) + { + if(PICE_strcmpi(pArgs->pToken[0],RegKeyWords[i].KeyWord)==0) + { + switch(RegKeyWords[i].ulSize) + { + case 1: + *(PUCHAR)(RegKeyWords[i].pValue)=(UCHAR)pArgs->Value[1]; + break; + case 2: + *(PUSHORT)(RegKeyWords[i].pValue)=(USHORT)pArgs->Value[1]; + break; + case 4: + *(PULONG)(RegKeyWords[i].pValue)=(ULONG)pArgs->Value[1]; + break; + } + DisplayRegs(); + RepaintSource(); + break; + } + } + } + return TRUE; +} + +//************************************************************************* +// SetCodeDisplay() +// +//************************************************************************* +COMMAND_PROTOTYPE(SetCodeDisplay) +{ + ARGS Args; + + if(pArgs->Count==0) + { + bCodeOn=bCodeOn?FALSE:TRUE; + + PICE_memset(&Args,0,sizeof(ARGS)); + Args.Count=0; + // make unassembler refresh all again + ulLastDisassStartAddress=ulLastDisassEndAddress=0; + Unassemble(&Args); + } + else if(pArgs->Count==1) + { + bCodeOn=(pArgs->Value[0]==0)?FALSE:TRUE; + + PICE_memset(&Args,0,sizeof(ARGS)); + Args.Count=0; + // make unassembler refresh all again + ulLastDisassStartAddress=ulLastDisassEndAddress=0; + Unassemble(&Args); + } + return TRUE; +} + +//************************************************************************* +// ShowCPU() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowCPU) +{ +ULONG i; + + for(i=0;CPUInfo[i].pValue!=NULL;i++) + { + PICE_sprintf(tempCmd,"%s = %.8X\n",CPUInfo[i].Name,*(CPUInfo[i].pValue)); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + return TRUE; +} + +//************************************************************************* +// WalkStack() +// +//************************************************************************* +COMMAND_PROTOTYPE(WalkStack) +{ + if(!pArgs->Count) + { + IntelStackWalk(CurrentEIP,CurrentEBP,CurrentESP); + } + + return TRUE; +} + +//************************************************************************* +// PokeDword() +// +//************************************************************************* +COMMAND_PROTOTYPE(PokeDword) +{ + ULONG ulData; + + // read old data + ulData = ReadPhysMem(pArgs->Value[1],sizeof(ULONG)); + PICE_sprintf(tempCmd,"value @ %.8X was %.8X\n",pArgs->Value[1],ulData); + Print(OUTPUT_WINDOW,tempCmd); + + // write new data + WritePhysMem(pArgs->Value[1],pArgs->Value[2],sizeof(ULONG)); + + // read check + ulData = ReadPhysMem(pArgs->Value[1],sizeof(ULONG)); + PICE_sprintf(tempCmd,"value @ %.8X = %.8X\n",pArgs->Value[1],ulData); + Print(OUTPUT_WINDOW,tempCmd); + + return TRUE; +} + +//************************************************************************* +// PokeMemory() +// +//************************************************************************* +COMMAND_PROTOTYPE(PokeMemory) +{ + DPRINT((0,"PokeMemory()\n")); + DPRINT((0,"PokeMemory(): value[0] = %.8X value[1] = %.8X value[3] = %.8X count = %.8X\n",pArgs->Value[0],pArgs->Value[1],pArgs->Value[2],pArgs->Count)); + + // must be three parameters + if(pArgs->Count == 3) + { + switch(pArgs->Value[0]) + { + case 4: + return PokeDword(pArgs); + default: + case 1: + case 2: + break; + } + } + else + { + Print(OUTPUT_WINDOW,"you need to supply a physical address and datum to write!\n"); + } + + return TRUE; +} + + +//************************************************************************* +// PeekDword() +// +//************************************************************************* +COMMAND_PROTOTYPE(PeekDword) +{ + ULONG ulData; + + ulData = ReadPhysMem(pArgs->Value[1],sizeof(ULONG)); + PICE_sprintf(tempCmd,"%.8X\n",ulData); + Print(OUTPUT_WINDOW,tempCmd); + + return TRUE; +} + +//************************************************************************* +// PeekWord() +// +//************************************************************************* +COMMAND_PROTOTYPE(PeekWord) +{ + USHORT usData; + + usData = (USHORT)ReadPhysMem(pArgs->Value[1],sizeof(USHORT)); + PICE_sprintf(tempCmd,"%.4X\n",usData); + Print(OUTPUT_WINDOW,tempCmd); + + return TRUE; +} + +//************************************************************************* +// PeekByte() +// +//************************************************************************* +COMMAND_PROTOTYPE(PeekByte) +{ + UCHAR ucData; + + ucData = (UCHAR)ReadPhysMem(pArgs->Value[1],sizeof(UCHAR)); + PICE_sprintf(tempCmd,"%.2X\n",ucData); + Print(OUTPUT_WINDOW,tempCmd); + + return TRUE; +} + +//************************************************************************* +// PeekMemory() +// +//************************************************************************* +COMMAND_PROTOTYPE(PeekMemory) +{ + DPRINT((0,"PeekMemory()\n")); + DPRINT((0,"PeekMemory(): value[0] = %.8X value[1] = %.8X count = %.8X\n",pArgs->Value[0],pArgs->Value[1],pArgs->Count)); + + if(pArgs->Count == 2) + { + switch(pArgs->Value[0]) + { + case 1: + return PeekByte(pArgs); + case 2: + return PeekWord(pArgs); + case 4: + return PeekDword(pArgs); + default: + break; + } + } + + return TRUE; +} + +//************************************************************************* +// UnassembleAtCurrentEip() +// +//************************************************************************* +COMMAND_PROTOTYPE(UnassembleAtCurrentEip) +{ + PICE_memset(pArgs,0,sizeof(ARGS)); + pArgs->Count = 2; + pArgs->Value[0] = CurrentCS; + pArgs->Value[1] = CurrentEIP; + Unassemble(pArgs); + return TRUE; +} + +//************************************************************************* +// SwitchTables() +// +//************************************************************************* +COMMAND_PROTOTYPE(SwitchTables) +{ + ULONG i; + + DPRINT((0,"SwitchTables()\n")); + + // no arguments -> display load symbol tables + if(!pArgs->Count) + { + for(i=0;iname,(ULONG)apSymbols[i],apSymbols[i]->ulNumberOfSrcFiles); + else + PICE_sprintf(tempCmd," %-32S @ %.8X (%5u source files)\n",apSymbols[i]->name,(ULONG)apSymbols[i],apSymbols[i]->ulNumberOfSrcFiles); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + } + } + // 1 argument -> set new current symbols + else if(pArgs->Count == 1) + { + PDEBUG_MODULE pTempMod; + char temp[DEBUG_MODULE_NAME_LEN]; + + pCurrentSymbols = (PICE_SYMBOLFILE_HEADER*)pArgs->Value[0]; + CopyWideToAnsi( temp, pCurrentSymbols->name ); + + DPRINT((0,"TableSwitchSym: pCurrentSymbols: %x, Name: %s\n", pCurrentSymbols, temp)); + + pTempMod = IsModuleLoaded(temp); + if( pTempMod ) + pCurrentMod = pTempMod; + } + + return TRUE; +} + +//************************************************************************* +// SwitchFiles() +// +//************************************************************************* +COMMAND_PROTOTYPE(SwitchFiles) +{ + PICE_SYMBOLFILE_SOURCE* pSrc; + ULONG i; + LPSTR p; + + DPRINT((0,"SwitchFiles()\n")); + // no arguments -> show files for current symbols + if(!pArgs->Count) + { + if(pCurrentSymbols && pCurrentSymbols->ulNumberOfSrcFiles) + { + LPSTR pCurrentFile=NULL; + + // find out the current file name + if(*szCurrentFile!=0) + { + if((pCurrentFile = strrchr(szCurrentFile,'/')) ) + { + pCurrentFile++; + } + else + { + pCurrentFile = szCurrentFile; + } + } + + pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pCurrentSymbols + pCurrentSymbols->ulOffsetToSrcFiles); + + for(i=0;iulNumberOfSrcFiles;i++) + { + if(pCurrentFile) + { + if((p = strrchr(pSrc->filename,'/')) ) + { + if(PICE_strcmpi(p+1,pCurrentFile)==0) + PICE_sprintf(tempCmd,"*%-32s @ %.8X\n",p+1,(ULONG)pSrc); + else + PICE_sprintf(tempCmd," %-32s @ %.8X\n",p+1,(ULONG)pSrc); + } + else + { + if(PICE_strcmpi(pSrc->filename,pCurrentFile)==0) + PICE_sprintf(tempCmd,"*%-32s @ %.8X\n",pSrc->filename,(ULONG)pSrc); + else + PICE_sprintf(tempCmd," %-32s @ %.8X\n",pSrc->filename,(ULONG)pSrc); + } + } + else + { + if((p = strrchr(pSrc->filename,'/')) ) + { + PICE_sprintf(tempCmd,"%-32s @ %.8X\n",p+1,(ULONG)pSrc); + } + else + { + PICE_sprintf(tempCmd,"%-32s @ %.8X\n",pSrc->filename,(ULONG)pSrc); + } + } + Print(OUTPUT_WINDOW,tempCmd); + + if(WaitForKey()==FALSE)break; + (LPSTR)pSrc += pSrc->ulOffsetToNext; + } + } + else + Print(OUTPUT_WINDOW,"No source files available!\n"); + } + // 1 argument -> argument is pointer PICE_SYMBOLFILE_SOURCE struct -> + // set current file and show it + else if(pArgs->Count == 1) + { + PICE_SYMBOLFILE_SOURCE* pSrc = (PICE_SYMBOLFILE_SOURCE*)pArgs->Value[0]; + LPSTR pFilename = pSrc->filename; + + ClrLine(wWindow[SOURCE_WINDOW].y-1); + + if(PICE_strlen(pFilename)ulOffsetToNext, + 1, + -1); + } + + return TRUE; +} + +//************************************************************************* +// ShowLocals() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowLocals) +{ + PLOCAL_VARIABLE p; + + if(pArgs->Count==0) + { + p = FindLocalsByAddress(GetLinearAddress(CurrentCS,CurrentEIP)); + DPRINT((0,"ShowLocals: %x\n", p)); + if(p) + { + DPRINT((0,"ShowLocals: name %s, type_name %s\n", p->name, p->type_name)); + while(PICE_strlen(p->name)) + { + if(!p->bRegister) + { + PICE_sprintf(tempCmd,"[EBP%.4d / #%u] %x %s %s \n",p->offset,p->line,p->value,p->type_name,p->name); + } + else + { + PICE_sprintf(tempCmd,"[%-8s / #%u] %x %s %s #%u\n",LocalVarRegs[p->offset],p->line,p->value,p->type_name,p->name); + } + Print(OUTPUT_WINDOW,tempCmd); + p++; + } + } + } + return TRUE; +} + +//************************************************************************* +// ShowSymbols() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowSymbols) +{ + PICE_SYMBOLFILE_HEADER* pSymbols; + ULONG index,addr; + LPSTR pSearchString,pName,pFind; + + // no args -> list full symbols for current module + if(!pArgs->Count) + { + // have current module ? + if(pCurrentMod) + { + DPRINT((0,"ShowSymbols(): full listing of symbols for %S\n",pCurrentMod->name)); + addr = (ULONG)pCurrentMod->BaseAddress; + + if((pSymbols = FindModuleSymbols(addr)) ) + { + PICE_sprintf(tempCmd,"symbols for module \"%S\"\n",pCurrentMod->name); + Print(OUTPUT_WINDOW,tempCmd); + + index = 0; + while((index = ListSymbolStartingAt(pCurrentMod,pSymbols,index,tempCmd))) + { + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + } + } + } + // partial name + else if(pArgs->Count == 1) + { + if(pCurrentMod) + { + addr = (ULONG)pCurrentMod->BaseAddress; + + if((pSymbols = FindModuleSymbols(addr))) + { + pSearchString = (LPSTR)pArgs->Value[0]; + + PICE_sprintf(tempCmd,"symbols for module \"%S\" (searching for \"%s\")\n",pCurrentMod->name,pSearchString); + Print(OUTPUT_WINDOW,tempCmd); + + if(pSearchString) + { + if(*pSearchString=='*' && pSearchString[PICE_strlen(pSearchString)-1]=='*') + { + pSearchString[PICE_strlen(pSearchString)-1] = 0; + pSearchString++; + index = 0; + while((index = ListSymbolStartingAt(pCurrentMod,pSymbols,index,tempCmd))) + { + pName = strrchr(tempCmd,' '); + pName++; + pFind = strstr(pName,pSearchString); + if(pFind) + { + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + } + // TODO + } + else if(pSearchString[PICE_strlen(pSearchString)-1]=='*') + { + pSearchString[PICE_strlen(pSearchString)-1] = 0; + index = 0; + + index = ListSymbolStartingAt(pCurrentMod,pSymbols,index,tempCmd); + if(index) + { + do + { + pName = strrchr(tempCmd,' '); + pName++; + pFind = strstr(pName,pSearchString); + if(pFind && (((ULONG)pName-(ULONG)pFind)==0) ) + { + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)break; + } + }while((index = ListSymbolStartingAt(pCurrentMod,pSymbols,index,tempCmd))); + } + } + } + } + } + } + + return TRUE; +} + +//************************************************************************* +// EvaluateExpression() +// +//************************************************************************* +COMMAND_PROTOTYPE(EvaluateExpression) +{ + PICE_SYMBOLFILE_HEADER* pSymbols; + ULONG addr; + + if(pArgs->Count == 1) + { + if(pCurrentMod) + { + addr = (ULONG)pCurrentMod->BaseAddress; + + if( (pSymbols = FindModuleSymbols(addr) ) ) + { + DPRINT((0,"EvaluateExpression: %s\n", (LPSTR)pArgs->Value[0])); + Evaluate(pSymbols,(LPSTR)pArgs->Value[0]); + } + } + } + return TRUE; +} + +//************************************************************************* +// SizeCodeWindow() +// +//************************************************************************* +COMMAND_PROTOTYPE(SizeCodeWindow) +{ + ULONG NewHeight,TotalHeight; + + if(pArgs->Count == 1) + { + NewHeight = pArgs->Value[0]; + + TotalHeight = wWindow[SOURCE_WINDOW].cy + + wWindow[OUTPUT_WINDOW].cy; + + if(NewHeight < TotalHeight) + { + if(wWindow[SOURCE_WINDOW].cy != NewHeight) + { + wWindow[SOURCE_WINDOW].cy = NewHeight; + wWindow[OUTPUT_WINDOW].y = wWindow[SOURCE_WINDOW].y + wWindow[SOURCE_WINDOW].cy + 1; + wWindow[OUTPUT_WINDOW].cy = TotalHeight - NewHeight; + + RepaintDesktop(); + } + } + } + else + { + PICE_sprintf(tempCmd,"code window at position %u has %u lines \n",wWindow[SOURCE_WINDOW].y,wWindow[SOURCE_WINDOW].cy); + Print(OUTPUT_WINDOW,tempCmd); + } + + return TRUE; +} + +//************************************************************************* +// SizeDataWindow() +// +//************************************************************************* +COMMAND_PROTOTYPE(SizeDataWindow) +{ + ULONG NewHeight,TotalHeight; + + if(pArgs->Count) + { + NewHeight = pArgs->Value[0]; + + TotalHeight = wWindow[DATA_WINDOW].cy + + wWindow[SOURCE_WINDOW].cy; + + if(NewHeight < TotalHeight) + { + if(wWindow[DATA_WINDOW].cy != NewHeight) + { + wWindow[DATA_WINDOW].cy = NewHeight; + wWindow[SOURCE_WINDOW].y = wWindow[DATA_WINDOW].y + wWindow[DATA_WINDOW].cy + 1; + wWindow[SOURCE_WINDOW].cy = TotalHeight - NewHeight; + + RepaintDesktop(); + } + } + } + else + { + PICE_sprintf(tempCmd,"data window has %u lines \n",wWindow[DATA_WINDOW].cy); + Print(OUTPUT_WINDOW,tempCmd); + } + + return TRUE; +} + +//************************************************************************* +// ClearScreen() +// +//************************************************************************* +COMMAND_PROTOTYPE(ClearScreen) +{ + EmptyRingBuffer(); + + Clear(OUTPUT_WINDOW); + CheckRingBuffer(); + + return TRUE; +} + +//************************************************************************* +// ShowMappings() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowMappings) +{ +#if 0 + ULONG ulPageDir; + ULONG ulPageTable; + ULONG address; + ULONG phys_addr; + pgd_t * pPGD; + pmd_t * pPMD; + pte_t * pPTE; + struct mm_struct* p = NULL; + struct task_struct* my_current = (struct task_struct*)0xFFFFE000; + + DPRINT((0,"ShowMappings()\n")); + + if(pArgs->Count == 1) + { + // We're in DebuggerShell(), so we live on a different stack + (ULONG)my_current &= ulRealStackPtr; + + // in case we have a user context we use it's mm_struct + if(my_current->mm) + { + p = my_current->mm; + } + // no user context -> use kernel's context + else + { + p = my_init_mm; + } + + // get the requested address from arguments + phys_addr = pArgs->Value[0]; + + DPRINT((0,"ShowMappings(): p = %X phys_addr = %X\n",(ULONG)p,phys_addr)); + + // for every page directory + for(ulPageDir=0;ulPageDir<1024;ulPageDir++) + { + address = (ulPageDir<<22); + + // get the page directory for the address + pPGD = pgd_offset(p,address); + // if page dir present + if(pPGD && pgd_val(*pPGD)&_PAGE_PRESENT) + { + DPRINT((0,"ShowMappings(): page directory present for %x\n",address)); + // not large page + if(!(pgd_val(*pPGD)&_PAGE_4M)) + { + DPRINT((0,"ShowMappings(): page directory for 4k pages\n")); + for(ulPageTable=0;ulPageTable<1024;ulPageTable++) + { + address = (ulPageDir<<22)|(ulPageTable<<12); + + pPMD = pmd_offset(pPGD,address); + if(pPMD) + { + pPTE = pte_offset(pPMD,address); + if(pPTE) + { + if(*(PULONG)pPTE & _PAGE_PRESENT) + { + ULONG ulPte = *(PULONG)pPTE & 0xFFFFF000; + + if(ulPte == (phys_addr & 0xFFFFF000)) + { + PICE_sprintf(tempCmd,"%.8X\n",address+(phys_addr&0xFFF)); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)return TRUE; + } + } + } + } + } + } + // large page + else + { + address = (ulPageDir<<22); + if((pgd_val(*pPGD)&0xFFC00000) == (phys_addr & 0xFFC00000) ) + { + if( ((address|(phys_addr&0x7FFFFF))&~TASK_SIZE) == phys_addr) + PICE_sprintf(tempCmd,"%.8X (identity map %.8X+%.8X)\n",address|(phys_addr&0x7FFFFF),TASK_SIZE,phys_addr); + else + PICE_sprintf(tempCmd,"%.8X\n",address|(phys_addr&0x7FFFFF)); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)return TRUE; + } + } + } + } + } +#endif + PICE_sprintf(tempCmd,"Not implemented yet!\n"); + Print(OUTPUT_WINDOW,tempCmd); + return TRUE; +} + +//************************************************************************* +// ShowTimers() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowTimers) +{ + + return TRUE; +} + +//************************************************************************* +// FindPCIVendorName() +// +//************************************************************************* +LPSTR FindPCIVendorName(USHORT vendorid) +{ + ULONG i; + + for(i=0;iCountSwitches>1) + return TRUE; + + if(pArgs->CountSwitches==1) + { + if(pArgs->Switch[0] == 'a') + bShowAll = TRUE; + } + + if(pArgs->Count < 3) + { + if(pArgs->Count > 0) + { + bUseBus = FALSE; + bus_req = pArgs->Value[0]; + } + if(pArgs->Count > 1) + { + bUseDev = FALSE; + dev_req = pArgs->Value[1]; + } + + // save old config space selector + oldCF8 = inl((PULONG)0xcf8); + + for(bus=0;bus<256;bus++) + { + for(dev=0;dev<32;dev++) + { + if(!((bUseDev || dev == dev_req) && + (bUseBus || bus == bus_req) )) + continue; + + pciNumber.u.AsUlong = 0; + pciNumber.u.bits.dev = dev; + pciNumber.u.bits.bus = bus; + pciNumber.u.bits.func = 0; + pciNumber.u.bits.ce = 1; + outl(pciNumber.u.AsUlong,(PULONG)0xcf8); + data = inl((PULONG)0xcfc); + + if(data != 0xFFFFFFFF) // valid device + { + if((pVendorName = FindPCIVendorName((USHORT)data)) ) + { + PICE_sprintf(tempCmd,"Bus%-8uDev%-8u === %.4X %.4X %s ====\n",bus,dev,(USHORT)data,(USHORT)(data>>16),pVendorName); + } + else + { + PICE_sprintf(tempCmd,"Bus%-8uDev%-8u === %.4X %.4X N/A ====\n",bus,dev,(USHORT)data,(USHORT)(data>>16)); + } + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE)goto CommonShowPCIExit; + + p = (PULONG)&pciConfig; + for(reg=0;regCount == 1) + { + } + + return TRUE; +} + +//************************************************************************* +// SetKeyboardLayout() +// +//************************************************************************* +COMMAND_PROTOTYPE(SetKeyboardLayout) +{ + PKEYBOARD_LAYOUT layout; + + ENTER_FUNC(); + + layout = GetKeyboardLayout(); + + switch(pArgs->Count) + { + case 0: + PICE_sprintf(tempCmd,"current layout = %s\n", layout->name); + Print(OUTPUT_WINDOW,tempCmd); + break; + case 1: + layout = SetKeyboardLayoutByName((LPSTR)pArgs->Value[0]); + PICE_sprintf(tempCmd,"current layout = %s\n", layout->name); + Print(OUTPUT_WINDOW,tempCmd); + break; + } + + LEAVE_FUNC(); + + return TRUE; +} + +//************************************************************************* +// ShowSysCallTable() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowSysCallTable) +{ +#if 0 + LPSTR pName; + ULONG i; + + ENTER_FUNC(); + + if(pArgs->Count == 0) + { + PICE_sprintf(tempCmd,"%u system calls\n",190); + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()!=FALSE) + for(i=0;i<190;i++) + { + if((pName = FindFunctionByAddress(sys_call_table[i],NULL,NULL)) ) + { + PICE_sprintf(tempCmd,"%-.3u: %.8X (%s)\n",i,sys_call_table[i],pName); + } + else + { + PICE_sprintf(tempCmd,"%-.3u: %.8X (%s)\n",i,sys_call_table[i],pName); + } + Print(OUTPUT_WINDOW,tempCmd); + if(WaitForKey()==FALSE) + break; + } + } + else if(pArgs->Count == 1) + { + i = pArgs->Value[0]; + if(i<190) + { + if((pName = FindFunctionByAddress(sys_call_table[i],NULL,NULL)) ) + { + PICE_sprintf(tempCmd,"%-.3u: %.8X (%s)\n",i,sys_call_table[i],pName); + } + else + { + PICE_sprintf(tempCmd,"%-.3u: %.8X (%s)\n",i,sys_call_table[i],pName); + } + Print(OUTPUT_WINDOW,tempCmd); + } + } + + LEAVE_FUNC(); +#endif + PICE_sprintf(tempCmd,"Not implemented yet!\n"); + Print(OUTPUT_WINDOW,tempCmd); + return TRUE; +} + +//************************************************************************* +// SetAltKey() +// +//************************************************************************* +COMMAND_PROTOTYPE(SetAltKey) +{ + if(pArgs->Count == 1) + { + ucBreakKey = (UCHAR)pArgs->Value[0]; + + PICE_sprintf(tempCmd,"new break key is CTRL-%c\n",ucBreakKey); + Print(OUTPUT_WINDOW,tempCmd); + } + else if(pArgs->Count == 0) + { + PICE_sprintf(tempCmd,"current break key is CTRL-%c\n",ucBreakKey); + Print(OUTPUT_WINDOW,tempCmd); + } + + + COMMAND_RET; +} + +//************************************************************************* +// ShowContext() +// +//************************************************************************* +COMMAND_PROTOTYPE(ShowContext) +{ + COMMAND_RET; +} + +//************************************************************************* +// +// utility functions for parsing +// +//************************************************************************* + + +//************************************************************************* +// FindCommand() +// +//************************************************************************* +LPSTR FindCommand(LPSTR p) +{ + ULONG i,j,k=0; + LPSTR result=NULL; + + tempCmd[0]=0; + for(j=0,i=0;CmdTable[i].Cmd!=NULL;i++) + { + if(PICE_strncmpi(CmdTable[i].Cmd,p,PICE_strlen(p)) == 0 && + CmdTable[i].CommandGroup != COMMAND_GROUP_HELP_ONLY) + { + if(PICE_strlen(tempCmd)) + PICE_strcat(tempCmd,", "); + PICE_strcat(tempCmd,CmdTable[i].Cmd); + j++; + k=i; + } + } + if(PICE_strlen(tempCmd)) + { + SetBackgroundColor(COLOR_CAPTION); + SetForegroundColor(COLOR_TEXT); + ClrLine(wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + PutChar(tempCmd,1,wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + if(j==1) + { + PICE_sprintf(tempCmd,"%s",CmdTable[k].Help); + PutChar(tempCmd,40,wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + result=CmdTable[k].Cmd; + } + ResetColor(); + } + return result; +} + + +//************************************************************************* +// CompactString() +// +//************************************************************************* +void CompactString(LPSTR p) +{ +ULONG i; + + for(i=1;i='0' && p[i]<='9') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'0'); + } + else if(p[i]>='A' && p[i]<='F') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'A'+10); + } + else if(p[i]>='a' && p[i]<='f') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'a'+10); + } + else + return FALSE; + } + p+=(i+1); + if(p[i]==':') + { + ULONG ulSelector=result; + if(ulSelector>0xFFFF) + return FALSE; + for(i=0;i<8 && p[i]!=0 && p[i]!=' ' && p[i]!=':';i++) + { + if(p[i]>='0' && p[i]<='9') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'0'); + } + else if(p[i]>='A' && p[i]<='F') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'A'+10); + } + else if(p[i]>='a' && p[i]<='f') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'a'+10); + } + else + return FALSE; + } + gCurrentSelector=(USHORT)ulSelector; + gCurrentOffset=result; + result = GetLinearAddress((USHORT)ulSelector,result); + } + *pValue=result; + return TRUE; +} + +//************************************************************************* +// ConvertTokenToDec() +// +//************************************************************************* +BOOLEAN ConvertTokenToDec(LPSTR p,PULONG pValue) +{ + ULONG result=0; + char c; + + while((c = *p)) + { + if(c >= '0' && c <= '9') + { + result *= 10; + result += (ULONG)(c - '0'); + } + else + return FALSE; + + p++; + } + *pValue = result; + return TRUE; +} + +//************************************************************************* +// ConvertTokenToSymbol() +// +//************************************************************************* +BOOLEAN ConvertTokenToSymbol(LPSTR pToken,PULONG pValue) +{ + LPSTR pEx; + char temp[64]; + LPSTR p; + PDEBUG_MODULE pModFound; + + DPRINT((0,"ConvertTokenToSymbol()\n")); + + PICE_strcpy(temp,pToken); + p = temp; + + // test for module!symbol string + pEx = PICE_strchr(p,'!'); + if(pEx) + { + DPRINT((0,"ConvertTokenToSymbol(): module!symbol syntax detected\n")); + // terminate module name + *pEx = 0; + // now we have two pointers + pEx++; + DPRINT((0,"ConvertTokenToSymbol(): module = %s symbol = %s\n",p,pEx)); + + if( pModFound=IsModuleLoaded(p) ) + { + if((*pValue = FindFunctionInModuleByName(pEx,pModFound))) + return TRUE; + } + } + else + { + if(pCurrentMod) + { + if((*pValue = FindFunctionInModuleByName(p,pCurrentMod))) + return TRUE; + } + return ScanExports(p,pValue); + } + return FALSE; +} + +//************************************************************************* +// ConvertTokenToModuleAndName() +// +//************************************************************************* +BOOLEAN ConvertTokenToModuleAndName(LPSTR pToken,PULONG pulModuleName,PULONG pulFunctionName) +{ + LPSTR pEx; + char temp[64]; + LPSTR p; + static char module_name[128]; + static char function_name[128]; + + // test for module!symbol string + PICE_strcpy(temp,pToken); + p = temp; + + DPRINT((0,"ConvertTokenToModuleAndName(%s)\n",p)); + + pEx = PICE_strchr(p,'!'); + if(pEx) + { + DPRINT((0,"ConvertTokenToModuleAndName(): module!symbol syntax detected\n")); + // terminate module name + *pEx = 0; + // now we have two pointers + pEx++; + DPRINT((0,"ConvertTokenToModuleAndName(): module = %s symbol = %s\n",p,pEx)); + PICE_strcpy(module_name,p); + PICE_strcpy(function_name,pEx); + *pulModuleName = (ULONG)module_name; + *pulFunctionName = (ULONG)function_name; + return TRUE; + + } + return FALSE; +} + +//************************************************************************* +// ConvertTokenToModule() +// +// convert an argument module name to a pointer to the module's symbols +//************************************************************************* +BOOLEAN ConvertTokenToModule(LPSTR p,PULONG pValue) +{ + ULONG i; + char temp[DEBUG_MODULE_NAME_LEN]; + + for(i=0;iname); + if(PICE_strcmpi(p,temp)==0) + { + *pValue = (ULONG)apSymbols[i]; + return TRUE; + } + } + } + + for(i=0;iname); + if(PICE_strncmpi(temp,p,PICE_strlen(p))==0) + { + *pValue = (ULONG)apSymbols[i]; + return TRUE; + } + } + } + + return FALSE; +} + +//************************************************************************* +// ConvertTokenToProcess() +// +//************************************************************************* +BOOLEAN ConvertTokenToProcess(LPSTR p,PULONG pValue) +{ + return FALSE; +} + +//************************************************************************* +// ReplaceKeywordWithValue() +// +//************************************************************************* +BOOLEAN ReplaceKeywordWithValue(LPSTR p,PULONG pValue,KEYWORDS* pKeyWords) +{ + ULONG i; + + for(i=0;pKeyWords[i].KeyWord!=NULL;i++) + { + if(PICE_strcmpi(p,pKeyWords[i].KeyWord)==0) + { + switch(pKeyWords[i].ulSize) + { + case sizeof(USHORT): + *pValue=(ULONG)*(PUSHORT)(pKeyWords[i].pValue); + break; + case sizeof(ULONG): + *pValue=*(PULONG)(pKeyWords[i].pValue); + break; + } + return TRUE; + } + } + return FALSE; +} + +//************************************************************************* +// ConvertTokenToKeyword() +// +//************************************************************************* +BOOLEAN ConvertTokenToKeyword(LPSTR p,PULONG pValue) +{ + char Name[256]; + ULONG count; + + DPRINT((0,"ConvertTokenToKeyword()\n")); + count=StrLenUpToWhiteChar(p," "); + PICE_strncpy(Name,p,count); + Name[count]=0; + if(ReplaceKeywordWithValue(Name,pValue,RegKeyWords)) + { + DPRINT((0,"ConvertTokenToKeyword(): success\n")); + return TRUE; + } + return FALSE; +} + +//************************************************************************* +// ConvertTokenToSpecialKeyword() +// +//************************************************************************* +BOOLEAN ConvertTokenToSpecialKeyword(LPSTR p,PULONG pValue) +{ + char Name[256]; + ULONG count; + + count=StrLenUpToWhiteChar(p," "); + PICE_strncpy(Name,p,count); + Name[count]=0; + if(ReplaceKeywordWithValue(Name,pValue,SpecialKeyWords)) + { + return TRUE; + } + return FALSE; +} + +//************************************************************************* +// ConvertTokenToOnOff() +// +//************************************************************************* +BOOLEAN ConvertTokenToOnOff(LPSTR p,PULONG pValue) +{ + char Name[256]; + ULONG count; + + count=StrLenUpToWhiteChar(p," "); + PICE_strncpy(Name,p,count); + Name[count]=0; + if(ReplaceKeywordWithValue(Name,pValue,OnOffKeyWords)) + { + return TRUE; + } + return FALSE; +} + +//************************************************************************* +// ConvertSizeToKeyword() +// +//************************************************************************* +BOOLEAN ConvertSizeToKeyword(LPSTR p,PULONG pValue) +{ + ULONG count; + + count=StrLenUpToWhiteChar(p," "); + if(count > 1) + return FALSE; + + switch(*p) + { + // BYTE + case 'b': + case 'B': + *pValue = 1; + break; + // WORD + case 'w': + case 'W': + *pValue = 2; + break; + // DWORD + case 'd': + case 'D': + *pValue = 4; + break; + // QWORD + case 'q': + case 'Q': + *pValue = 4; + break; + default: + return FALSE; + } + + return TRUE; +} + + +//************************************************************************* +// ConvertTokenToSrcFile() +// +//************************************************************************* +BOOLEAN ConvertTokenToSrcFile(LPSTR p,PULONG pValue) +{ + PICE_SYMBOLFILE_SOURCE* pSrc; + LPSTR pFilename,pFilenameSrc; + ULONG i; + + DPRINT((0,"ConvertTokenToSrcFile(%s)\n",p)); + + if(pCurrentSymbols && pCurrentSymbols->ulNumberOfSrcFiles) + { + DPRINT((0,"ConvertTokenToSrcFile(): current symbols for %S\n",pCurrentSymbols->name)); + + pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pCurrentSymbols + pCurrentSymbols->ulOffsetToSrcFiles); + + for(i=0;iulNumberOfSrcFiles;i++) + { + pFilename = strrchr(pSrc->filename,'/'); + if(!pFilename) + pFilename = pSrc->filename; + else + pFilename++; + + pFilenameSrc = strrchr(p,'/'); + if(!pFilenameSrc ) + pFilenameSrc = p; + else + pFilenameSrc++; + + DPRINT((0,"ConvertTokenToSrcFile(): %s\n",pFilename)); + + if(PICE_strcmpi(pFilename,pFilenameSrc) == 0) + { + DPRINT((0,"ConvertTokenToSrcFile(): found %s\n",pFilename)); + + *pValue = (ULONG)pSrc; + return TRUE; + } + + // go to next file + (LPSTR)pSrc += pSrc->ulOffsetToNext; + } + + pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pCurrentSymbols + pCurrentSymbols->ulOffsetToSrcFiles); + + // if not found now do a lookup for partials + for(i=0;iulNumberOfSrcFiles;i++) + { + pFilename = strrchr(pSrc->filename,'/'); + if(!pFilename) + pFilename = pSrc->filename; + else + pFilename++; + + DPRINT((0,"ConvertTokenToSrcFile(): %s\n",pFilename)); + + if(PICE_strncmpi(pFilename,p,PICE_strlen(p)) == 0) + { + DPRINT((0,"ConvertTokenToSrcFile(): found %s\n",pFilename)); + + *pValue = (ULONG)pSrc; + return TRUE; + } + + // go to next file + (LPSTR)pSrc += pSrc->ulOffsetToNext; + } + + } + return FALSE; +} + +//************************************************************************* +// ConvertTokenToLineNumber() +// +//************************************************************************* +BOOLEAN ConvertTokenToLineNumber(LPSTR p,PULONG pValue) +{ + ULONG ulDecimal; + + DPRINT((0,"ConvertTokenToLineNumber()\n")); + if(*p++ == '.') + { + ulDecimal = ExtractNumber(p); + DPRINT((0,"ConvertTokenToLineNumber(): ulDecimal = %u\n",ulDecimal)); + if(ulDecimal) + { + DPRINT((0,"ConvertTokenToLineNumber(): current file = %s\n",szCurrentFile)); + if(pCurrentMod && PICE_strlen(szCurrentFile)) + { + DPRINT((0,"ConvertTokenToLineNumber(): current file %S\n",pCurrentMod->name)); + if(FindAddressForSourceLine(ulDecimal,szCurrentFile,pCurrentMod,pValue)) + { + DPRINT((0,"ConvertTokenToLineNumber(): value = %x\n",*pValue)); + return TRUE; + } + } + } + } + + return FALSE; +} + + +//************************************************************************* +// IsWhiteChar() +// +//************************************************************************* +BOOLEAN IsWhiteChar(char c,LPSTR WhiteChars) +{ + USHORT lenWhiteChar = PICE_strlen(WhiteChars); + USHORT i; + for(i=0;iFlags & COMMAND_HAS_SWITCHES) + { + // token starts with '-' and is 2 chars long + // must be a switch + if(PICE_strchr(pCurrentCommand->pszRecognizedSwitches,*(pToken+1)) ) + { + DPRINT((0,"is a switch!\n")); + Arguments.Switch[j++]=*(pToken+1); + continue; + } + // not a valid switch + else + { + PICE_sprintf(tempCmd," <-- %s is not a valid switch\n",pToken); + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,":"); + goto CommonParseReturnPoint; + } + } + else + { + PICE_sprintf(tempCmd," <-- %s can't have any switches\n",pCurrentCommand->Cmd); + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,":"); + goto CommonParseReturnPoint; + } + } + + if(pCurrentCommand->Flags & COMMAND_HAS_PARAMS) + { + if(!pCurrentCommand->ParamFlags[i]) + { + PICE_sprintf(tempCmd," <-- %s can't have more than %u parameters\n",pCurrentCommand->Cmd,i); + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,":"); + goto CommonParseReturnPoint; + } + DPRINT((0,"Parse(): PARAM_CAN_BE_SRCLINE\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_SRCLINE) + { + if(ConvertTokenToLineNumber(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + if(*pToken == '.') + { + PICE_sprintf(tempCmd," <-- no line number %s found\n",pToken); + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,":"); + goto CommonParseReturnPoint; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_NUMERIC\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_NUMERIC) + { + if(ConvertTokenToHex(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_DECIMAL\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_DECIMAL) + { + if(ConvertTokenToDec(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_REG_KEYWORD\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_REG_KEYWORD) + { + if(ConvertTokenToKeyword(pToken,&Arguments.Value[i])) + { + Arguments.pToken[i] = pToken; + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_SYMBOLIC\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_SYMBOLIC) + { + if(ConvertTokenToSymbol(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_VIRTUAL_SYMBOLIC\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_VIRTUAL_SYMBOLIC) + { + DPRINT((0,"might be a virtual modname!symbol syntax!\n")); + if(ConvertTokenToModuleAndName(pToken,&Arguments.Value[i],&Arguments.Value[i+1])) + { + Arguments.bNotTranslated[i]=TRUE; + Arguments.bNotTranslated[i+1]=TRUE; + i+=2; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_MODULE\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_MODULE) + { + if(ConvertTokenToModule(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_PRNAME\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_PRNAME) + { + if(ConvertTokenToProcess(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_SRC_FILE\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_SRC_FILE) + { + if(ConvertTokenToSrcFile(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_ASTERISK\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_ASTERISK) + { + if(PICE_strlen(pToken)==1 && pToken[0]=='*') + { + Arguments.Value[i]=-1; + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_LETTER\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_LETTER) + { + if(PICE_strlen(pToken)==1 && PICE_isprint(pToken[0])) + { + Arguments.Value[i]=(ULONG)pToken[0]; + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_ONOFF\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_ONOFF) + { + if(ConvertTokenToOnOff(pToken,&Arguments.Value[i])) + { + i++; + continue; + } + } + DPRINT((0,"Parse(): PARAM_CAN_BE_PARTIAL_SYM_NAME\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_PARTIAL_SYM_NAME) + { + Arguments.Value[i] = (ULONG)pToken; + i++; + continue; + } + DPRINT((0,"Parse(): PARAM_CAN_BE_ANY_STRING\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_ANY_STRING) + { + Arguments.Value[i] = (ULONG)pToken; + i++; + continue; + } + DPRINT((0,"Parse(): PARAM_CAN_BE_SIZE_DESC\n")); + if(pCurrentCommand->ParamFlags[i] & PARAM_CAN_BE_SIZE_DESC) + { + if(ConvertSizeToKeyword(pToken,&Arguments.Value[i])) + { + Arguments.pToken[i] = pToken; + i++; + continue; + } + } + PICE_sprintf(tempCmd," <-- syntax error in parameter %u!\n",i); + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,":"); + goto CommonParseReturnPoint; + } + else + { + PICE_sprintf(tempCmd," <-- %s has no parameters\n",pCurrentCommand->Cmd); + Print(OUTPUT_WINDOW,tempCmd); + Print(OUTPUT_WINDOW,":"); + goto CommonParseReturnPoint; + } + // next token + i++; + } + }while(pToken && iCmd,Arguments.CountSwitches)); + + if(!bInvokedByFkey) + { + DPRINT((0,"Parse(): adding new line\n")); + Print(OUTPUT_WINDOW,"\n"); + } + + // call the command handler + result=pCurrentCommand->Handler(&Arguments); + + if(result && !bInvokedByFkey && pCurrentCommand->Handler!=LeaveIce && pCurrentCommand->Handler!=SingleStep ) + { + DPRINT((0,"Parse(): adding colon\n")); + Print(OUTPUT_WINDOW,":"); + } + } + +CommonParseReturnPoint: + SuspendPrintRingBuffer(FALSE); + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + + ShowStatusLine(); +} diff --git a/apps/utils/pice/module/parse.h b/apps/utils/pice/module/parse.h new file mode 100644 index 0000000..0f291a8 --- /dev/null +++ b/apps/utils/pice/module/parse.h @@ -0,0 +1,181 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + parse.h + +Abstract: + + HEADER for parse.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +typedef struct TagArgs +{ + ULONG Value[16]; + ULONG Count; + UCHAR Switch[16]; + ULONG CountSwitches; + BOOLEAN bNotTranslated[16]; + LPSTR pToken[16]; +}ARGS,*PARGS; + +typedef struct tagCPUInfo +{ + char *Name; + PULONG pValue; +}CPUINFO; + +typedef BOOLEAN (*PFN)(PARGS); + +#define MAX_ARGS (5) + +typedef struct _CMDTABLE +{ + char * Cmd; + PFN Handler; + char * Help; + ULONG Flags; + ULONG ParamFlags[MAX_ARGS]; + LPSTR pszRecognizedSwitches; + ULONG CommandGroup; +}CMDTABLE,*PCMDTABLE; + +typedef struct tagKeyWords +{ + char* KeyWord; + PVOID pValue; + ULONG ulSize; +}KEYWORDS; + +typedef struct tagSETGETREGS +{ + char *RegName; + PULONG RegAddr; +}SETGETREGS; + +typedef struct tag_BP +{ + ULONG LinearAddress; + ULONG Segment,Offset; + BOOLEAN Used; + BOOLEAN Active; + BOOLEAN Virtual; + char ModName[256]; + char SymName[256]; +}BP; + +extern BOOLEAN bNeedToFillBuffer; + +extern BOOLEAN bCodeOn; +extern BOOLEAN bShowSrc; +extern BP Bp[]; +extern BOOLEAN bInt3Here; +extern BOOLEAN bInt1Here; + +extern BOOLEAN bStepping; + +extern char szCurrentFile[256]; +extern PDEBUG_MODULE pCurrentMod; +extern PICE_SYMBOLFILE_HEADER* pCurrentSymbols; +extern LONG ulCurrentlyDisplayedLineNumber; +extern LIST_ENTRY* pPsProcessListHead; + +BOOLEAN AsciiToHex(LPSTR p,PULONG pValue); +void Parse(LPSTR pCmdLine,BOOLEAN bInvokedByFkey); +LPSTR FindCommand(LPSTR p); +ULONG StrLenUpToWhiteChar(LPSTR p,LPSTR lpszWhiteChars); +BOOLEAN WaitForKey(void); +BOOLEAN ConvertTokenToHex(LPSTR p,PULONG pValue); +void DisplaySourceFile(LPSTR pSrcLine,LPSTR pSrcEnd,ULONG ulLineNumber,ULONG ulLineNumberToInvert); +BOOLEAN ConvertTokenToSrcFile(LPSTR p,PULONG pValue); +void RepaintDesktop(void); +void PutStatusText(LPSTR p); +void UnassembleOneLineDown(void); +void UnassembleOnePageDown(ULONG page); +void UnassembleOneLineUp(void); +void UnassembleOnePageUp(ULONG page); + +extern BOOLEAN (*DisplayMemory)(PARGS pArgs); + +#define COMMAND_PROTOTYPE(arg) BOOLEAN arg(PARGS pArgs) +#define COMMAND_RET return TRUE + +// available commands +COMMAND_PROTOTYPE(ShowGdt); +COMMAND_PROTOTYPE(LeaveIce); +COMMAND_PROTOTYPE(SingleStep); +COMMAND_PROTOTYPE(ShowHelp); +COMMAND_PROTOTYPE(ShowPageDirs); +COMMAND_PROTOTYPE(ShowProcesses); +COMMAND_PROTOTYPE(DisplayMemoryDword); +COMMAND_PROTOTYPE(DisplayMemoryByte); +COMMAND_PROTOTYPE(DisplayPhysMemDword); +COMMAND_PROTOTYPE(Unassemble); +COMMAND_PROTOTYPE(ShowSymbols); +COMMAND_PROTOTYPE(ShowModules); +COMMAND_PROTOTYPE(SetBreakpoint); +COMMAND_PROTOTYPE(ListBreakpoints); +COMMAND_PROTOTYPE(ClearBreakpoints); +COMMAND_PROTOTYPE(Ver); +COMMAND_PROTOTYPE(Hboot); +COMMAND_PROTOTYPE(I3here); +COMMAND_PROTOTYPE(I1here); +COMMAND_PROTOTYPE(SetSrcDisplay); +COMMAND_PROTOTYPE(ShowIdt); +COMMAND_PROTOTYPE(StepOver); +COMMAND_PROTOTYPE(StepInto); +COMMAND_PROTOTYPE(SetGetRegisters); +COMMAND_PROTOTYPE(SetCodeDisplay); +COMMAND_PROTOTYPE(NextInstr); +COMMAND_PROTOTYPE(ShowCPU); +COMMAND_PROTOTYPE(ShowTables); +COMMAND_PROTOTYPE(WalkStack); +COMMAND_PROTOTYPE(ShowVirtualMemory); +COMMAND_PROTOTYPE(UnassembleAtCurrentEip); +COMMAND_PROTOTYPE(PokeMemory); +COMMAND_PROTOTYPE(PeekMemory); +COMMAND_PROTOTYPE(ShowLocals); +COMMAND_PROTOTYPE(SwitchTables); +COMMAND_PROTOTYPE(SwitchFiles); +COMMAND_PROTOTYPE(EvaluateExpression); +COMMAND_PROTOTYPE(SizeCodeWindow); +COMMAND_PROTOTYPE(SizeDataWindow); +COMMAND_PROTOTYPE(ClearScreen); +COMMAND_PROTOTYPE(ShowMappings); +COMMAND_PROTOTYPE(ShowTimers); +COMMAND_PROTOTYPE(ShowPCI); +COMMAND_PROTOTYPE(SetKeyboardLayout); +COMMAND_PROTOTYPE(ShowSysCallTable); +COMMAND_PROTOTYPE(SetAltKey); +COMMAND_PROTOTYPE(ShowContext); + +//ei make sure the following correspond to ntoskrnl/mm/i386/page.c +#define PAGETABLE_MAP (0xf0000000) +#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024))) +#define PAGE_SHIFT 12 +#define PTRS_PER_PTE 1024 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024)) +#define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \ + (((ULONG)v / (1024 * 1024))&(~0x3))) +#define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3))) +#define ADDR_TO_PDE_OFFSET(v) (((ULONG)v / (4 * 1024 * 1024))) diff --git a/apps/utils/pice/module/patch.c b/apps/utils/pice/module/patch.c new file mode 100644 index 0000000..5d51f33 --- /dev/null +++ b/apps/utils/pice/module/patch.c @@ -0,0 +1,234 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + patch.c + +Abstract: + + hooking of kernel internal keyboard interrupt handler + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + Reactos Port: Eugene Ingerman + +Revision History: + + 10-Jul-1999: created + 15-Nov-2000: general cleanup of source files + 12/1/2001 reactos port + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//#include + +#include +#include + +//////////////////////////////////////////////////// +// GLOBALS +//// + +static PUCHAR pPatchAddress; +static ULONG ulOldOffset = 0; +static ULONG ulKeyPatchFlags; + +void (*old_handle_scancode)(UCHAR,int); +char tempPatch[256]; +UCHAR ucBreakKey = 'd'; // key that will break into debugger in combination with CTRL + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//*********************************************************************************** +// PiceKbdIsr - keyboard isr hook routine. +// IsrContext - context that we passed to keyboard driver in internal iocontrol +// pCurrentInput, pCurrentOutput - not implemented yet +// StatusByte - keyboard status register +// pByte - pointer to the byte read from keyboard data port. can be changed. +// pContinueProcessing - should keyboard driver continue processing this byte. +//*********************************************************************************** +BOOLEAN PiceKbdIsr ( + PVOID IsrContext, + PKEYBOARD_INPUT_DATA pCurrentInput, + POUTPUT_PACKET pCurrentOutput, + UCHAR StatusByte, + PUCHAR pByte, + PBOOLEAN pContinueProcessing, + PKEYBOARD_SCAN_STATE pScanState + ) +{ + static BOOLEAN bControl = FALSE; + BOOLEAN bForward=TRUE; // should we let keyboard driver process this keystroke + BOOLEAN isDown=!(*pByte & 0x80); + UCHAR ucKey = *pByte & 0x7f; + + ENTER_FUNC(); + + // BUG?? should protect with spinlock since bControl is static. + DPRINT((0,"PiceKbdIsr(pByte: %x, val: %x,%u)\n",pByte,*pByte,isDown)); + DPRINT((0,"PiceKbdIsr(1): bControl = %u bForward = %u bEnterNow = %u\n",bControl,bForward,bEnterNow)); + + if(isDown) + { + DPRINT((0,"bControl: %x, ucKey: %x, breakkey: %x\n", bControl, ucKey, AsciiToScan(ucBreakKey))); + // CTRL pressed + if(ucKey==0x1d) + { + bControl=TRUE; + } + else if(bControl==TRUE && ucKey==AsciiToScan(ucBreakKey)) // CTRL-D + { + // fake a CTRL-D release call + bEnterNow=TRUE; + bControl=FALSE; + // simulate an initial break + __asm__("\n\t \ + pushfl\n\t \ + pushl %cs\n\t \ + pushl $returnpoint\n\t \ + pushl $" STR(REASON_CTRLF) "\n\t \ + jmp NewInt31Handler\n\t \ + returnpoint:"); + *pByte = 0x1d | 0x80 | 0x7f; + bForward=TRUE; + } + else if((ucKey == 66|| ucKey == 68) && bStepping) + { + bForward=FALSE; + } + + } + else + { + // CTRL released + if(ucKey==0x1d) + { + bControl=FALSE; + } + else if((ucKey == 66|| ucKey == 68) && bStepping) + { + bForward=FALSE; + } + } + *pContinueProcessing = bForward; + DPRINT((5,"*pContinueProcessing: %d\n", *pContinueProcessing)); + LEAVE_FUNC(); + return TRUE; +} + +//*********************************************************************************** +// PiceSendIoctl - send internal_io_control to the driver +// Target - Device Object that receives control request +// Ioctl - request +// InputBuffer - Type3Buffer will be pointing here +// InputBufferLength - length of inputbuffer +//*********************************************************************************** +NTSTATUS PiceSendIoctl(PDEVICE_OBJECT Target, ULONG Ioctl, + PVOID InputBuffer, ULONG InputBufferLength) +{ + KEVENT event; + NTSTATUS status = STATUS_SUCCESS; + IO_STATUS_BLOCK iosb; + PIRP irp; + + KeInitializeEvent(&event, + NotificationEvent, + FALSE + ); + + if (NULL == (irp = IoBuildDeviceIoControlRequest(Ioctl, + Target, + InputBuffer, + InputBufferLength, + 0, + 0, + TRUE, + &event, + &iosb))) { + DPRINT((0,"PiceSendIoctl: STATUS_INSUFFICIENT_RESOURCES\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + status = IoCallDriver(Target, irp); + + if (STATUS_PENDING == status) { + + status = KeWaitForSingleObject(&event, + Executive, + KernelMode, + FALSE, + NULL); + + ASSERT(STATUS_SUCCESS == status); + status = iosb.Status; + } + DPRINT((0,"PiceSendIoctl: status: %d\n",NT_SUCCESS(status))); + return status; +} + +//************************************************** +// PatchKeyboardDriver - set keyboard driver hook. +// We use interface supported by standard keyboard drivers. +//************************************************** +BOOLEAN PatchKeyboardDriver(void) +{ + PINTERNAL_I8042_HOOK_KEYBOARD phkData; + //When we have i8042 driver this should be changed!!!!!!! + UNICODE_STRING DevName = UNICODE_STRING_INITIALIZER(L"\\Device\\Keyboard"); + PDEVICE_OBJECT kbdDevice = NULL; + PFILE_OBJECT FO = NULL; + NTSTATUS status; + + ENTER_FUNC(); + + //Get pointer to keyboard device + if( !NT_SUCCESS( status = IoGetDeviceObjectPointer( &DevName, FILE_READ_ACCESS, &FO, &kbdDevice ) ) ) + { + DPRINT((0,"PatchKeyboardDriver: IoGetDeviceObjectPointer status: %x\n", status)); + return FALSE; + } + phkData = ExAllocatePool( PagedPool, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) ); + RtlZeroMemory( phkData, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) ); + + phkData->IsrRoutine = (PI8042_KEYBOARD_ISR) PiceKbdIsr; + phkData->Context = (PVOID) NULL; //DeviceObject; + + //call keyboard device internal io control to hook keyboard input stream + status = PiceSendIoctl( kbdDevice, IOCTL_INTERNAL_I8042_HOOK_KEYBOARD, + phkData, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) ); + DPRINT((0,"PatchKeyboardDriver: PiceSendIoctl status: %x\n", status)); + + + ObDereferenceObject(FO); + ExFreePool(phkData); + + LEAVE_FUNC(); + + return NT_SUCCESS(status); +} + +void RestoreKeyboardDriver(void) +{ + ENTER_FUNC(); + DbgPrint("RestoreKeyboardDriver: Not Implemented yet!!!\n"); + LEAVE_FUNC(); +} diff --git a/apps/utils/pice/module/patch.h b/apps/utils/pice/module/patch.h new file mode 100644 index 0000000..cdb2653 --- /dev/null +++ b/apps/utils/pice/module/patch.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + patch.h + +Abstract: + + HEADER for patch.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +BOOLEAN PatchKeyboardDriver(void); +void RestoreKeyboardDriver(void); + +extern UCHAR ucBreakKey; diff --git a/apps/utils/pice/module/pci_ids.h b/apps/utils/pice/module/pci_ids.h new file mode 100644 index 0000000..d4e9c83 --- /dev/null +++ b/apps/utils/pice/module/pci_ids.h @@ -0,0 +1,905 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + pci_ids.h + +Abstract: + + HEADER, PCI vendor IDs + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +struct _PCI_VENDOR_IDS +{ + USHORT vendorid; + char* vendor_name; +}PCIVendorIDs[]= +{ + {0x0033 ,"PARADYNE CORP."}, + {0x003D ,"REAL 3D"}, + {0x0100 ,"NCIPHER CORP. LTD"}, + {0x0A89 ,"BREA TECHNOLOGIES INC"}, + {0x0E11 ,"COMPAQ COMPUTER CORP."}, + {0x1000 ,"SYMBIOS LOGIC INC/LSI LOGIC"}, + {0x1001 ,"KOLTER ELECTRONIC"}, + {0x1002 ,"ATI TECHNOLOGIES INC"}, + {0x1004 ,"VLSI TECHNOLOGY INC"}, + {0x100B ,"NATIONAL SEMICONDUCTOR CORPORATION"}, + {0x1010 ,"VIDEO LOGIC LTD"}, + {0x1014 ,"IBM"}, + {0x1018 ,"UNISYS CORPORATION"}, + {0x1019 ,"ELITEGROUP COMPUTER SYS"}, + {0x101A ,"NCR"}, + {0x101E ,"AMERICAN MEGATRENDS"}, + {0x1020 ,"HITACHI COMPUTER PRODUCTS"}, + {0x1021 ,"OKI ELECTRIC INDUSTRY CO. LTD."}, + {0x1022 ,"ADVANCED MICRO DEVICES"}, + {0x1023 ,"TRIDENT MICROSYSTEMS"}, + {0x1028 ,"DELL COMPUTER CORPORATION"}, + {0x102A ,"LSI LOGIC CORPORATION"}, + {0x102B ,"MATROX GRAPHICS, INC."}, + {0x102F ,"TOSHIBA AMERICA, ELEC. COMPANY"}, + {0x1033 ,"NEC CORPORATION"}, + {0x1038 ,"AMP, INC"}, + {0x1039 ,"SILICON INTEGRATED SYSTEMS"}, + {0x103C ,"HEWLETT PACKARD"}, + {0x103F ,"SYNOPSYS/LOGIC MODELING GROUP"}, + {0x1042 ,"MICRON ELECTRONICS, INC."}, + {0x1043 ,"ASUSTEK COMPUTER, INC."}, + {0x1044 ,"DISTRIBUTED PROCESSING TECHNOLOGY"}, + {0x1045 ,"OPTI INC."}, + {0x1048 ,"ELSA AG"}, + {0x1049 ,"FOUNTAIN TECHNOLOGIES, INC."}, + {0x104C ,"TEXAS INSTRUMENTS"}, + {0x104D ,"SONY CORPORATION"}, + {0x1050 ,"WINBOND ELECTRONICS CORP"}, + {0x1054 ,"HITACHI, LTD"}, + {0x1055 ,"STANDARD MICROSYSTEMS CORP."}, + {0x1057 ,"MOTOROLA"}, + {0x1058 ,"ETRI"}, + {0x1059 ,"TEKNOR INDUSTRIAL COMPUTERS INC"}, + {0x105A ,"PROMISE TECHNOLOGY, INC."}, + {0x105B ,"FOXCONN INTERNATIONAL INC"}, + {0x105D ,"NUMBER 9 VISUAL TECHNOLOGY"}, + {0x105F ,"INFOTRONIC AMERICA INC"}, + {0x1063 ,"OCEAN MANUFACTURING LTD"}, + {0x1064 ,"ALCATEL"}, + {0x1067 ,"MITSUBISHI ELECTRIC AMERICA"}, + {0x1068 ,"DIVERSIFIED TECHNOLOGY"}, + {0x1069 ,"MYLEX CORPORATION"}, + {0x106B ,"APPLE COMPUTER INC."}, + {0x106D ,"SEQUENT COMPUTER SYSTEMS"}, + {0x1070 ,"DAEWOO TELECOM LTD"}, + {0x1071 ,"MITAC"}, + {0x1073 ,"YAMAHA CORPORATION"}, + {0x1077 ,"QLOGIC"}, + {0x1079 ,"I-BUS"}, + {0x107B ,"GATEWAY 2000"}, + {0x107E ,"INTERPHASE CORPORATION"}, + {0x108D ,"OLICOM"}, + {0x1095 ,"CMD TECHNOLOGY INC"}, + {0x1096 ,"ALACRON"}, + {0x1097 ,"APPIAN/ETMA"}, + {0x109A ,"PACKARD BELL NEC"}, + {0x109E ,"BROOKTREE CORPORATION"}, + {0x109F ,"TRIGEM COMPUTER INC."}, + {0x10A0 ,"MEIDENSHA CORPORATION"}, + {0x10A2 ,"QUANTUM EFFECT DESIGN"}, + {0x10A9 ,"SILICON GRAPHICS"}, + {0x10AC ,"HONEYWELL IAC"}, + {0x10AF ,"MICRO COMPUTER SYSTEMS INC"}, + {0x10B5 ,"PLX TECHNOLOGY, INC."}, + {0x10B6 ,"MADGE NETWORKS"}, + {0x10B7 ,"3COM CORPORATION"}, + {0x10B9 ,"ACER LABS INC."}, + {0x10BA ,"MITSUBISHI ELECTRIC CORP."}, + {0x10C2 ,"AUSPEX SYSTEMS INC."}, + {0x10C8 ,"NEOMAGIC CORPORATION"}, + {0x10CA ,"FUJITSU MICROELECTRONIC., INC."}, + {0x10CB ,"OMRON CORPORATION"}, + {0x10CD ,"ADVANCED SYSTEM PRODUCTS, INC"}, + {0x10CF ,"FUJITSU LIMITED"}, + {0x10D1 ,"FUTUREPLUS SYSTEMS CORP."}, + {0x10D2 ,"MOLEX INCORPORATED"}, + {0x10DB ,"ROHM LSI SYSTEMS"}, + {0x10DD ,"EVANS & SUTHERLAND"}, + {0x10DE ,"NVIDIA CORPORATION"}, + {0x10DF ,"EMULEX CORPORATION"}, + {0x10E1 ,"TEKRAM TECHNOLOGY CO.,LTD."}, + {0x10E3 ,"TUNDRA SEMICONDUCTOR CORP."}, + {0x10E5 ,"MICRO INDUSTRIES CORPORATION"}, + {0x10EC ,"REALTEK SEMICONDUCTOR CORP."}, + {0x10EE ,"XILINX, INC."}, + {0x10F1 ,"TYAN COMPUTER"}, + {0x10F5 ,"NKK CORPORATION"}, + {0x10F6 ,"CREATIVE ELECTRONIC SYSTEMS SA"}, + {0x10FC ,"I-O DATA DEVICE, INC."}, + {0x10FE ,"FAST MULTIMEDIA AG"}, + {0x1101 ,"INITIO CORPORATION"}, + {0x1102 ,"CREATIVE LABS"}, + {0x1105 ,"SIGMA DESIGNS, INC"}, + {0x1106 ,"VIA TECHNOLOGIES, INC."}, + {0x1107 ,"ASCEND COMMUNICATIONS, INC."}, + {0x1109 ,"ADAPTEC/COGENT DATA TECHNOLOGIES INC"}, + {0x110A ,"SIEMENS PC SYSTEME GMBH"}, + {0x1111 ,"SANTA CRUZ OPERATION"}, + {0x1113 ,"ACCTON TECHNOLOGY CORPORATION"}, + {0x1116 ,"MEDIA 100, INC"}, + {0x1117 ,"DATACUBE, INC"}, + {0x1118 ,"FCI ELECTRONICS"}, + {0x1119 ,"ICP-VORTEX COMPUTERSYSTEM GMBH"}, + {0x111A ,"EFFICIENT NETWORKS, INC"}, + {0x111D ,"INTEGRATED DEVICE TECH"}, + {0x1120 ,"EMC CORPORATION"}, + {0x1127 ,"FORE SYSTEMS INC"}, + {0x112A ,"HERMES ELECTRONICS COMPANY, LTD."}, + {0x112F ,"IMAGING TECHNOLOGY, INC"}, + {0x1131 ,"PHILIPS SEMICONDUCTORS"}, + {0x1132 ,"MITEL CORP."}, + {0x1133 ,"EICON TECHNOLOGY CORPORATION"}, + {0x1134 ,"MERCURY COMPUTER SYSTEMS"}, + {0x1135 ,"FUJI XEROX CO LTD"}, + {0x1136 ,"MOMENTUM DATA SYSTEMS"}, + {0x1137 ,"CISCO SYSTEMS INC"}, + {0x1138 ,"ZIATECH CORPORATION"}, + {0x113C ,"CYCLONE MICROSYSTEMS, INC."}, + {0x113E ,"SANYO ELECTRIC CO - INFORMATION SYSTEMS DIVISION"}, + {0x1141 ,"CREST MICROSYSTEM INC."}, + {0x1145 ,"WORKBIT CORPORATION"}, + {0x1146 ,"FORCE COMPUTERS GMBH"}, + {0x1148 ,"SYSKONNECT"}, + {0x114C ,"ANNABOOKS"}, + {0x114F ,"DIGI INTERNATIONAL"}, + {0x1154 ,"MELCO INC"}, + {0x115C ,"PHOTRON LTD."}, + {0x115D ,"XIRCOM"}, + {0x1161 ,"PFU LIMITED"}, + {0x1163 ,"RENDITION, A DIVISION OF MICRON"}, + {0x1166 ,"RELIANCE COMPUTER"}, + {0x116E ,"ELECTRONICS FOR IMAGING"}, + {0x1170 ,"INVENTEC CORPORATION"}, + {0x1171 ,"BLUE WAVE SYSTEMS"}, + {0x1172 ,"ALTERA CORPORATION"}, + {0x1179 ,"TOSHIBA AMERICA INFO SYSTEMS"}, + {0x1180 ,"RICOH CO LTD"}, + {0x1186 ,"D-LINK SYSTEM INC"}, + {0x1187 ,"ADVANCED TECHNOLOGY LABORATORIES, INC."}, + {0x1189 ,"MATSUSHITA ELECTIC INDUSTRIAL CO LTD"}, + {0x118B ,"PLATYPUS TECHNOLOGY PTY LTD"}, + {0x118C ,"COROLLARY, INC"}, + {0x1191 ,"ACARD TECHNOLOGY CORP"}, + {0x1195 ,"RATOC SYSTEMS INC"}, + {0x119A ,"MINDSHARE, INC."}, + {0x119D ,"BUG, INC."}, + {0x119E ,"FUJITSU MICROELECTRONICS LTD."}, + {0x119F ,"BULL HN INFORMATION SYSTEMS"}, + {0x11A1 ,"HAMAMATSU PHOTONICS K.K."}, + {0x11A9 ,"INNOSYS"}, + {0x11AA ,"ACTEL"}, + {0x11AB ,"GALILEO TECHNOLOGY LTD."}, + {0x11AD ,"LITE-ON COMMUNICATIONS INC"}, + {0x11AE ,"SCITEX CORPORATION"}, + {0x11AF ,"AVID TECHNOLOGY INC"}, + {0x11B0 ,"V3 SEMICONDUCTOR INC."}, + {0x11B2 ,"EASTMAN KODAK"}, + {0x11B3 ,"BARR SYSTEMS INC."}, + {0x11BF ,"ASTRODESIGN, INC."}, + {0x11C6 ,"DAINIPPON SCREEN MFG. CO. LTD"}, + {0x11C8 ,"DOLPHIN INTERCONNECT SOLUTIONS AS"}, + {0x11C9 ,"MAGMA"}, + {0x11CA ,"LSI SYSTEMS, INC"}, + {0x11CB ,"SPECIALIX INTERNATIONAL LTD"}, + {0x11CE ,"NETACCESS"}, + {0x11D0 ,"LOCKHEED MARTIN - ELECTRONISS & COMMUNICATIONS"}, + {0x11D1 ,"AURAVISION"}, + {0x11D2 ,"INTERCOM INC."}, + {0x11D4 ,"ANALOG DEVICES"}, + {0x11D5 ,"IKON CORPORATION"}, + {0x11D9 ,"TOSHIBA TEC CORPORATION"}, + {0x11DA ,"NOVELL"}, + {0x11DF ,"NEW WAVE PDG"}, + {0x11E3 ,"QUICKLOGIC CORPORATION"}, + {0x11EC ,"CORECO INC"}, + {0x11EE ,"DOME IMAGING SYSTEMS INC"}, + {0x11F8 ,"PMC-SIERRA INC"}, + {0x1203 ,"AGFA CORPORATION"}, + {0x1206 ,"AMDAHL CORPORATION"}, + {0x120F ,"ESSENTIAL COMMUNICATIONS"}, + {0x1214 ,"PERFORMANCE TECHNOLOGIES, INC."}, + {0x1216 ,"PURUP - ESKOFOT A/S"}, + {0x1217 ,"O2MICRO, INC."}, + {0x121A ,"3DFX INTERACTIVE, INC."}, + {0x121B ,"VIRATA LTD"}, + {0x1221 ,"CONTEC CO., LTD"}, + {0x1223 ,"ARTESYN COMMUNICATIONS PRODUCTS INC"}, + {0x1227 ,"TECH-SOURCE"}, + {0x122C ,"SICAN GMBH"}, + {0x1232 ,"MARCONI COMMUNICATIONS LTD"}, + {0x123C ,"CENTURY SYSTEMS, INC."}, + {0x123D ,"ENGINEERING DESIGN TEAM, INC."}, + {0x123F ,"C-CUBE MICROSYSTEMS"}, + {0x1242 ,"JAYCOR NETWORKS INC."}, + {0x1244 ,"AVM AUDIOVISUELLES MKTG & COMPUTER SYSTEM GMBH"}, + {0x124B ,"SBS TECHNOLOGIES"}, + {0x1250 ,"HITACHI ULSI SYSTEMS CO LTD"}, + {0x1253 ,"GUZIK TECHNICAL ENTERPRISES"}, + {0x1255 ,"OPTIBASE LTD"}, + {0x1259 ,"ALLIED TELESYN INTERNATIONAL"}, + {0x125C ,"AURORA TECHNOLOGIES, INC."}, + {0x125F ,"CONCURRENT TECHNOLOGIES"}, + {0x1260 ,"INTERSIL CORP"}, + {0x1261 ,"MATSUSHITA-KOTOBUKI ELECTRONICS INDUSTRIES, LTD."}, + {0x1264 ,"AVAL NAGASAKI CORPORATION"}, + {0x1268 ,"TEKTRONIX"}, + {0x126C ,"NORTEL NETWORKS"}, + {0x126D ,"SPLASH TECHNOLOGY, INC."}, + {0x126E ,"SUMITOMO METAL INDUSTRIES, LTD."}, + {0x126F ,"SILICON MOTION, INC."}, + {0x1270 ,"OLYMPUS OPTICAL CO., LTD."}, + {0x1274 ,"CREATIVE LABS, INC. MALVERN"}, + {0x1275 ,"NETWORK APPLIANCE CORPORATION"}, + {0x1278 ,"TRANSTECH DSP LTD"}, + {0x1279 ,"TRANSMETA CORPORATION"}, + {0x127D ,"VELA RESEARCH LP"}, + {0x127F ,"FUJIFILM"}, + {0x1281 ,"YOKOGAWA ELECTRIC CORPORATION"}, + {0x1283 ,"INTEGRATED TECHNOLOGY EXPRESS, INC."}, + {0x1286 ,"MAZET GMBH"}, + {0x128B ,"TRANSWITCH CORPORATION"}, + {0x128D ,"G2 NETWORKS, INC."}, + {0x128F ,"TATENO DENNOU, INC."}, + {0x1290 ,"TOSHIBA PERSONAL COMPUTER SYSTEM CORP."}, + {0x1291 ,"NCS COMPUTER ITALIA SRL"}, + {0x1292 ,"TRITECH MICROELECTRONICS INC"}, + {0x1297 ,"SHUTTLE COMPUTER"}, + {0x1299 ,"KNOWLEDGE TECHNOLOGY LAB."}, + {0x129A ,"VMETRO, INC."}, + {0x129E ,"VICTOR COMPANY OF JAPAN, LTD."}, + {0x12A0 ,"ALLEN- BRADLEY COMPANY"}, + {0x12A3 ,"LUCENT TECHNOLOGIES"}, + {0x12A7 ,"AMO GMBH"}, + {0x12A9 ,"XIOTECH CORPORATION"}, + {0x12AB ,"YUAN YUAN ENTERPRISE CO., LTD."}, + {0x12AE ,"ALTEON WEBSYSTEMS INC"}, + {0x12B6 ,"NATURAL MICROSYSTEMS"}, + {0x12B7 ,"COGNEX MODULAR VISION SYSTEMS DIV. - ACUMEN INC."}, + {0x12B9 ,"3COM CORP."}, + {0x12BC ,"ARRAY MICROSYSTEMS"}, + {0x12BE ,"ANCHOR CHIPS INC."}, + {0x12BF ,"FUJIFILM MICRODEVICES"}, + {0x12C0 ,"INFIMED"}, + {0x12C3 ,"HOLTEK SEMICONDUCTOR INC"}, + {0x12C4 ,"CONNECT TECH INC"}, + {0x12C6 ,"MITAN CORPORATION"}, + {0x12C7 ,"DIALOGIC CORP"}, + {0x12CA ,"INTEGRATED COMPUTING ENGINES"}, + {0x12CD ,"AIMS LAB"}, + {0x12D3 ,"GE VINGMED ULTRASOUND AS"}, + {0x12D4 ,"COMVERSE NETWORKS SYSTEM & ULTICOM, INC."}, + {0x12D5 ,"EQUATOR TECHNOLOGIES"}, + {0x12D6 ,"ANALOGIC CORP"}, + {0x12D8 ,"PERICOM SEMICONDUCTOR"}, + {0x12D9 ,"ACULAB PLC"}, + {0x12DA ,"TRUE TIME INC."}, + {0x12DE ,"RAINBOW TECHNOLOGIES"}, + {0x12DF ,"SBS TECHNOLOGIES INC"}, + {0x12E0 ,"CHASE RESEARCH"}, + {0x12E2 ,"DATUM INC. BANCOMM-TIMING DIVISION"}, + {0x12E4 ,"BROOKTROUT TECHNOLOGY INC"}, + {0x12E7 ,"SEBRING SYSTEMS, INC"}, + {0x12EA ,"REAL VISION, INC"}, + {0x12EB ,"AUREAL INC."}, + {0x12EC ,"3A INTERNATIONAL, INC."}, + {0x12F0 ,"PENTEK"}, + {0x12F7 ,"COGNEX INC."}, + {0x12FB ,"SPECTRUM SIGNAL PROCESSING"}, + {0x12FC ,"CAPITAL EQUIPMENT CORP"}, + {0x12FE ,"ESD ELECTRONIC SYSTEM DESIGN GMBH"}, + {0x1304 ,"JUNIPER NETWORKS INC."}, + {0x1307 ,"COMPUTER BOARDS"}, + {0x1308 ,"LEVEL ONE COMMUNICATIONS INC"}, + {0x130A ,"MITSUBISHI ELECTRIC MICROCOMPUTER"}, + {0x130B ,"COLORGRAPHIC COMMUNICATIONS CORP"}, + {0x130F ,"ADVANET INC"}, + {0x1310 ,"GESPAC"}, + {0x1313 ,"YASKAWA ELECTRIC CO."}, + {0x1316 ,"TERADYNE INC."}, + {0x1317 ,"ADMTEK INC"}, + {0x1318 ,"PACKET ENGINES INC."}, + {0x1319 ,"FORTEMEDIA, INC"}, + {0x131F ,"SIIG INC"}, + {0x1325 ,"SALIX TECHNOLOGIES INC"}, + {0x1326 ,"SEACHANGE INTERNATIONAL"}, + {0x1331 ,"RADISYS CORP."}, + {0x133D ,"PRISA NETWORKS"}, + {0x133F ,"SCM MICROSYSTEMS"}, + {0x1342 ,"PROMAX SYSTEMS INC"}, + {0x1344 ,"MICRON TECHNOLOGY INC"}, + {0x134B ,"ARK RESEARCH CORP."}, + {0x134C ,"CHORI JOHO SYSTEM CO. LTD"}, + {0x134D ,"PC-TEL INC"}, + {0x135A ,"BRAIN BOXES LIMITED"}, + {0x135C ,"QUATECH INC"}, + {0x135E ,"SEALEVEL SYSTEMS INC"}, + {0x135F ,"I-DATA INTERNATIONAL A-S"}, + {0x1360 ,"MEINBERG FUNKUHREN"}, + {0x1361 ,"SOLITON SYSTEMS K.K."}, + {0x1363 ,"PHOENIX TECHNOLOGIES LTD"}, + {0x1367 ,"HITACHI ZOSEN CORPORATION"}, + {0x1368 ,"SKYWARE CORPORATION"}, + {0x1369 ,"DIGIGRAM"}, + {0x136B ,"KAWASAKI STEEL CORPORATION"}, + {0x136C ,"ADTEK SYSTEM SCIENCE CO LTD"}, + {0x1375 ,"BOEING - SUNNYVALE"}, + {0x1377 ,"ELECTRONIC EQUIPMENT PRODUUTION & DISTRIBUTION GMBH"}, + {0x137A ,"MARK OF THE UNICORN INC"}, + {0x137B ,"PPT VISION"}, + {0x137C ,"IWATSU ELECTRIC CO LTD"}, + {0x137D ,"DYNACHIP CORPORATION"}, + {0x1380 ,"SANRITZ AUTOMATION CO LTC"}, + {0x1381 ,"BRAINS CO. LTD"}, + {0x1383 ,"CONTROLNET INC"}, + {0x1384 ,"STELLAR SEMICONDUCTOR INC"}, + {0x1385 ,"NETGEAR"}, + {0x1387 ,"SYSTRAN CORP"}, + {0x1388 ,"HITACHI INFORMATION TECHNOLOGY CO LTD"}, + {0x1389 ,"APPLICOM INTERNATIONAL"}, + {0x138A ,"SITERA"}, + {0x138B ,"TOKIMEC INC"}, + {0x138E ,"BASLER GMBH"}, + {0x138F ,"PATAPSCO DESIGNS INC"}, + {0x1393 ,"MOXA TECHNOLOGIES CO LTD"}, + {0x1394 ,"LEVEL ONE COMMUNICATIONS"}, + {0x1395 ,"AMBICOM INC"}, + {0x1396 ,"CIPHER SYSTEMS INC"}, + {0x1397 ,"COLOGNE CHIP DESIGNS GMBH"}, + {0x1398 ,"CLARION CO. LTD"}, + {0x1399 ,"RIOS SYSTEMS CO LTD"}, + {0x139A ,"ALACRITECH INC"}, + {0x139C ,"QUANTUM 3D INC"}, + {0x139D ,"XSTREAMS PLC/ EPL LIMITED"}, + {0x139E ,"ECHOSTAR DATA NETWORKS"}, + {0x139F ,"AETHRA S.R.L."}, + {0x13A0 ,"CRYSTAL GROUP INC"}, + {0x13A1 ,"KAWASAKI HEAVY INDUSTRIES LTD"}, + {0x13A2 ,"OSITECH COMMUNICATIONS INC"}, + {0x13A4 ,"RASCOM INC"}, + {0x13A7 ,"TELES AG"}, + {0x13A8 ,"EXAR CORP."}, + {0x13A9 ,"SIEMENS MEDICAL SYSTEMS, ULTRASOUND GROUP"}, + {0x13AA ,"NORTEL NETWORKS - BWA DIVISION"}, + {0x13AF ,"T.SQWARE"}, + {0x13B1 ,"TAMURA CORPORATION"}, + {0x13B4 ,"WELLBEAN CO INC"}, + {0x13B5 ,"ARM LTD"}, + {0x13B6 ,"DLOG GMBH"}, + {0x13B8 ,"NOKIA TELECOMMUNICATIONS OY"}, + {0x13BD ,"SHARP CORPORATION"}, + {0x13BF ,"SHAREWAVE INC"}, + {0x13C1 ,"3WARE INC"}, + {0x13C2 ,"TECHNOTREND SYSTEMTECHNIK GMBH"}, + {0x13C3 ,"JANZ COMPUTER AG"}, + {0x13C6 ,"CONDOR ENGINEERING INC"}, + {0x13C7 ,"BLUE CHIP TECHNOLOGY LTD"}, + {0x13CA ,"IOMEGA CORPORATION"}, + {0x13CC ,"METHEUS CORPORATION"}, + {0x13CF ,"STUDIO AUDIO & VIDEO LTD"}, + {0x13D0 ,"B2C2, INC"}, + {0x13D1 ,"ABOCOM SYSTEMS INC"}, + {0x13D2 ,"SHARK MULTIMEDIA INC"}, + {0x13D3 ,"IMC NETWORKS"}, + {0x13D4 ,"GRAPHICS MICROSYSTEMS INC"}, + {0x13D6 ,"K.I. TECHNOLOGY CO LTD"}, + {0x13D7 ,"TOSHIBA ENGINEERING CORPORATION"}, + {0x13D8 ,"PHOBOS CORPORATION"}, + {0x13D9 ,"APEX INC"}, + {0x13DC ,"NETBOOST CORPORATION"}, + {0x13DE ,"ABB ROBOTICS PRODUCTS AB"}, + {0x13DF ,"E-TECH INC"}, + {0x13E0 ,"GVC CORPORATION"}, + {0x13E3 ,"NEST INC"}, + {0x13E4 ,"CALCULEX INC"}, + {0x13E5 ,"TELESOFT DESIGN LTD"}, + {0x13E9 ,"INTRASERVER TECHNOLOGY INC"}, + {0x13EA ,"DALLAS SEMICONDUCTOR"}, + {0x13F0 ,"SUNDANCE TECHNOLOGY INC"}, + {0x13F1 ,"OCE' - TECHNOLOGIES B.V."}, + {0x13F2 ,"FORD MICROELECTRONICS INC"}, + {0x13F4 ,"TROIKA NETWORKS INC"}, + {0x13F6 ,"C-MEDIA ELECTRONICS INC"}, + {0x13F9 ,"NTT ADVANCED TECHNOLOGY CORP."}, + {0x13FB ,"AYDIN CORP"}, + {0x13FD ,"MICRO SCIENCE INC"}, + {0x1400 ,"ARTX INC"}, + {0x1402 ,"MEILHAUS ELECTRONIC GMBH"}, + {0x1404 ,"FUNDAMENTAL SOFTWARE INC"}, + {0x1406 ,"OCE' PRINTING SYSTEMS GMBH"}, + {0x1407 ,"LAVA COMPUTER MFG INC"}, + {0x1408 ,"ALOKA CO. LTD"}, + {0x140A ,"DSP RESEARCH INC"}, + {0x140B ,"RAMIX INC"}, + {0x140D ,"MATSUSHITA ELECTRIC WORKS LTD"}, + {0x1413 ,"ADDONICS"}, + {0x1415 ,"OXFORD SEMICONDUCTOR LTD"}, + {0x1418 ,"KYUSHU ELECTRONICS SYSTEMS INC"}, + {0x1419 ,"EXCEL SWITCHING CORP"}, + {0x141B ,"ZOOM TELEPHONICS INC"}, + {0x141E ,"FANUC LTD"}, + {0x1420 ,"PSION DACOM PLC"}, + {0x1428 ,"EDEC CO LTD"}, + {0x1429 ,"UNEX TECHNOLOGY CORP."}, + {0x142A ,"KINGMAX TECHNOLOGY INC"}, + {0x142B ,"RADIOLAN"}, + {0x142C ,"MINTON OPTIC INDUSTRY CO LTD"}, + {0x142D ,"PIXSTREAM INC"}, + {0x1430 ,"ITT AEROSPACE/COMMUNICATIONS DIVISION"}, + {0x1433 ,"ELTEC ELEKTRONIK GMBH"}, + {0x1436 ,"CIS TECHNOLOGY INC"}, + {0x1437 ,"NISSIN INC CO"}, + {0x1438 ,"ATMEL-DREAM"}, + {0x143F ,"LIGHTWELL CO LTD - ZAX DIVISION"}, + {0x1441 ,"AGIE SA."}, + {0x1445 ,"LOGICAL CO LTD"}, + {0x1446 ,"GRAPHIN CO. LTD"}, + {0x1447 ,"AIM GMBH"}, + {0x144A ,"ADLINK TECHNOLOGY"}, + {0x144B ,"LORONIX INFORMATION SYSTEMS INC"}, + {0x144D ,"SAMSUNG ELECTRONICS CO LTD"}, + {0x1450 ,"OCTAVE COMMUNICATIONS IND."}, + {0x1451 ,"SP3D CHIP DESIGN GMBH"}, + {0x1453 ,"MYCOM INC"}, + {0x1455 ,"LOGIC PLUS PLUS INC"}, + {0x1458 ,"GIGA-BYTE TECHNOLOGY"}, + {0x145C ,"CRYPTEK"}, + {0x145F ,"BALDOR ELECTRIC COMPANY"}, + {0x1460 ,"DYNARC INC"}, + {0x1462 ,"MICRO-STAR INTERNATIONAL CO LTD"}, + {0x1463 ,"FAST CORPORATION"}, + {0x1464 ,"INTERACTIVE CIRCUITS & SYSTEMS LTD"}, + {0x1465 ,"GN NETTEST TELECOM DIV."}, + {0x1468 ,"AMBIT MICROSYSTEMS CORP."}, + {0x1469 ,"CLEVELAND MOTION CONTROLS"}, + {0x146C ,"RUBY TECH CORP."}, + {0x146D ,"TACHYON, INC."}, + {0x146E ,"WILLIAMS ELECTRONICS GAMES, INC."}, + {0x1471 ,"INTEGRATED TELECOM EXPRESS INC"}, + {0x1473 ,"ZAPEX TECHNOLOGIES INC"}, + {0x1474 ,"DOUG CARSON & ASSOCIATES"}, + {0x1477 ,"NET INSIGHT"}, + {0x1478 ,"DIATREND CORPORATION"}, + {0x147B ,"ABIT COMPUTER CORP."}, + {0x147F ,"NIHON UNISYS, LTD."}, + {0x1482 ,"ISYTEC - INTEGRIERTE SYSTEMTECHNIK GMBH"}, + {0x1483 ,"LABWAY COPORATION"}, + {0x1485 ,"ERMA - ELECTRONIC GMBH"}, + {0x1489 ,"KYE SYSTEMS CORPORATION"}, + {0x148A ,"OPTO 22"}, + {0x148B ,"INNOMEDIALOGIC INC."}, + {0x148E ,"OSI PLUS CORPORATION"}, + {0x148F ,"PLANT EQUIPMENT, INC."}, + {0x1490 ,"TC LABS PTY LTD."}, + {0x1493 ,"MAKER COMMUNICATIONS"}, + {0x1495 ,"TOKAI COMMUNICATIONS INDUSTRY CO. LTD"}, + {0x1496 ,"JOYTECH COMPUTER CO., LTD."}, + {0x1497 ,"SMA REGELSYSTEME GMBH"}, + {0x1499 ,"EMTEC CO., LTD"}, + {0x149A ,"ANDOR TECHNOLOGY LTD"}, + {0x149B ,"SEIKO INSTRUMENTS INC"}, + {0x149C ,"OVISLINK CORP."}, + {0x149D ,"NEWTEK INC"}, + {0x149E ,"MAPLETREE NETWORKS INC."}, + {0x149F ,"LECTRON CO LTD"}, + {0x14A0 ,"SOFTING GMBH"}, + {0x14A1 ,"SYSTEMBASE CO LTD"}, + {0x14A2 ,"MILLENNIUM ENGINEERING INC"}, + {0x14A3 ,"MAVERICK NETWORKS"}, + {0x14A4 ,"GVC/BCM ADVANCED RESEARCH"}, + {0x14A5 ,"XIONICS DOCUMENT TECHNOLOGIES INC."}, + {0x14A6 ,"INOVA COMPUTERS GMBH & CO KG"}, + {0x14A8 ,"FEATRON TECHNOLOGIES CORPORATION"}, + {0x14A9 ,"HIVERTEC INC."}, + {0x14AB ,"MENTOR GRAPHICS CORP."}, + {0x14AC ,"NOVAWEB TECHNOLOGIES INC"}, + {0x14AD ,"TIME SPACE RADIO AB"}, + {0x14AE ,"CTI PET SYSTEMS, INC"}, + {0x14AF ,"GUILLEMOT CORPORATION"}, + {0x14B0 ,"BST COMMUNICATION TECHNOLOGY LTD"}, + {0x14B1 ,"NEXTCOM K.K."}, + {0x14B2 ,"ENNOVATE NETWORKS INC"}, + {0x14B3 ,"XPEED INC."}, + {0x14B4 ,"PHILIPS BUSINESS ELECTRONICS B.V."}, + {0x14B5 ,"CREAMWARE GMBH"}, + {0x14B6 ,"QUANTUM DATA CORP."}, + {0x14B7 ,"PROXIM INC"}, + {0x14B8 ,"TECHSOFT TECHNOLOGY CO LTD"}, + {0x14B9 ,"AIRONET WIRELESS COMMUNICATIONS"}, + {0x14BA ,"INTERNIX INC."}, + {0x14BB ,"SEMTECH CORPORATION"}, + {0x14BC ,"GLOBESPAN SEMICONDUCTOR INC."}, + {0x14BD ,"CARDIO CONTROL N.V."}, + {0x14BE ,"L3 COMMUNICATIONS"}, + {0x14BF ,"SPIDER COMMUNICATIONS INC."}, + {0x14C0 ,"COMPAL ELECTRONICS INC"}, + {0x14C1 ,"MYRICOM INC."}, + {0x14C2 ,"DTK COMPUTER"}, + {0x14C3 ,"MEDIATEK CORP."}, + {0x14C4 ,"IWASAKI INFORMATION SYSTEMS CO LTD"}, + {0x14C5 ,"ABB AUTOMATION PRODUCTS AB"}, + {0x14C6 ,"DATA RACE INC"}, + {0x14C7 ,"MODULAR TECHNOLOY HOLDINGS LTD"}, + {0x14C8 ,"TURBOCOMM TECH. INC."}, + {0x14C9 ,"ODIN TELESYSTEMS INC"}, + {0x14CA ,"PE LOGIC CORP."}, + {0x14CB ,"BILLIONTON SYSTEMS INC./CADMUS MICRO INC."}, + {0x14CC ,"NAKAYO TELECOMMUNICATIONS INC"}, + {0x14CD ,"UNIVERSAL SCIENTIFIC IND."}, + {0x14CE ,"WHISTLE COMMUNICATIONS"}, + {0x14CF ,"TEK MICROSYSTEMS INC."}, + {0x14D0 ,"ERICSSON AXE R & D"}, + {0x14D1 ,"COMPUTER HI-TECH CO LTD"}, + {0x14D2 ,"TITAN ELECTRONICS INC"}, + {0x14D3 ,"CIRTECH (UK) LTD"}, + {0x14D4 ,"PANACOM TECHNOLOGY CORP"}, + {0x14D5 ,"NITSUKO CORPORATION"}, + {0x14D6 ,"ACCUSYS INC"}, + {0x14D7 ,"HIRAKAWA HEWTECH CORP"}, + {0x14D8 ,"HOPF ELEKTRONIK GMBH"}, + {0x14D9 ,"ALPHA PROCESSOR INC"}, + {0x14DA ,"NATIONAL AEROSPACE LABORATORIES"}, + {0x14DB ,"AVLAB TECHNOLOGY INC"}, + {0x14DC ,"AMPLICON LIVELINE LTD"}, + {0x14DD ,"IMODL INC."}, + {0x14DE ,"APPLIED INTEGRATION CORPORATION"}, + {0x14DF ,"BASIS COMMUNICATIONS CORP"}, + {0x14E1 ,"INVERTEX"}, + {0x14E2 ,"INFOLIBRIA"}, + {0x14E3 ,"AMTELCO"}, + {0x14E4 ,"BROADCOM CORPORATION"}, + {0x14E5 ,"PIXELFUSION LTD"}, + {0x14E6 ,"SHINING TECHNOLOGY INC"}, + {0x14E7 ,"3CX"}, + {0x14E8 ,"RAYCER INC"}, + {0x14E9 ,"GARNETS SYSTEM CO LTD"}, + {0x14EA ,"PLANEX COMMUNICATIONS INC"}, + {0x14EB ,"SEIKO EPSON CORPORATION"}, + {0x14EC ,"ACQIRIS"}, + {0x14ED ,"DATAKINETICS LTD"}, + {0x14EE ,"MASPRO KENKOH CORP"}, + {0x14EF ,"CARRY COMPUTER ENG. CO LTD"}, + {0x14F0 ,"CANON RESEACH CENTRE FRANCE"}, + {0x14F1 ,"CONEXANT"}, + {0x14F2 ,"MOBILITY ELECTRONICS"}, + {0x14F3 ,"BROADLOGIC"}, + {0x14F4 ,"TOKYO ELECTRONIC INDUSTRY CO LTD"}, + {0x14F5 ,"SOPAC LTD"}, + {0x14F6 ,"COYOTE TECHNOLOGIES LLC"}, + {0x14F7 ,"WOLF TECHNOLOGY INC"}, + {0x14F8 ,"AUDIOCODES INC"}, + {0x14F9 ,"AG COMMUNICATIONS"}, + {0x14FA ,"WAVETEK WANDEL & GOLTERMANN"}, + {0x14FB ,"TRANSAS MARINE (UK) LTD"}, + {0x14FC ,"QUADRICS SUPERCOMPUTERS WORLD"}, + {0x14FD ,"JAPAN COMPUTER INDUSTRY INC."}, + {0x14FE ,"ARCHTEK TELECOM CORP."}, + {0x14FF ,"TWINHEAD INTERNATIONAL CORP."}, + {0x1500 ,"LANTECH COMPUTER COMPANY"}, + {0x1501 ,"BANKSOFT CANADA LTD"}, + {0x1502 ,"MITSUBISHI ELECTRIC LOGISTICS SUPPORT CO LTD"}, + {0x1503 ,"KAWASAKI LSI USA INC"}, + {0x1504 ,"KAISER ELECTRONICS"}, + {0x1505 ,"ITA INGENIEURBURO FUR TESTAUFGABEN GMBH"}, + {0x1506 ,"CHAMELEON SYSTEMS INC"}, + {0x1507 ,"HTEC LTD"}, + {0x1508 ,"HONDA CONNECTORS/MHOTRONICS INC"}, + {0x1509 ,"FIRST INTERNATIONAL COMPUTER INC"}, + {0x150A ,"FORVUS RESEARCH INC"}, + {0x150B ,"YAMASHITA SYSTEMS CORP"}, + {0x150C ,"KYOPAL CO LTD"}, + {0x150D ,"WARPSPPED INC"}, + {0x150E ,"C-PORT CORPORATION"}, + {0x150F ,"INTEC GMBH"}, + {0x1510 ,"BEHAVIOR TECH COMPUTER CORP"}, + {0x1511 ,"CENTILLIUM TECHNOLOGY CORP"}, + {0x1512 ,"ROSUN TECHNOLOGIES INC"}, + {0x1513 ,"RAYCHEM"}, + {0x1514 ,"TFL LAN INC"}, + {0x1515 ,"ICS ADVENT"}, + {0x1516 ,"MYSON TECHNOLOGY INC"}, + {0x1517 ,"ECHOTEK CORPORATION"}, + {0x1518 ,"PEP MODULAR COMPUTERS GMBH"}, + {0x1519 ,"TELEFON AKTIEBOLAGET LM ERICSSON"}, + {0x151A ,"GLOBETEK INC"}, + {0x151B ,"COMBOX LTD"}, + {0x151C ,"DIGITAL AUDIO LABS INC"}, + {0x151D ,"FUJITSU COMPUTER PRODUCTS OF AMERICA"}, + {0x151E ,"MATRIX CORP."}, + {0x151F ,"TOPIC SEMICONDUCTOR CORP"}, + {0x1520 ,"CHAPLET SYSTEM INC"}, + {0x1521 ,"BELL CORPORATION"}, + {0x1522 ,"MAINPINE LIMITED"}, + {0x1523 ,"MUSIC SEMICONDUCTORS"}, + {0x1524 ,"ENE TECHNOLOGY INC"}, + {0x1525 ,"IMPACT TECHNOLOGIES"}, + {0x1526 ,"ISS, INC"}, + {0x1527 ,"SOLECTRON"}, + {0x1528 ,"ACKSYS"}, + {0x1529 ,"AMERICAN MICROSYSTEMS INC"}, + {0x152A ,"QUICKTURN DESIGN SYSTEMS"}, + {0x152B ,"FLYTECH TECHNOLOGY CO LTD"}, + {0x152C ,"MACRAIGOR SYSTEMS LLC"}, + {0x152D ,"QUANTA COMPUTER INC"}, + {0x152E ,"MELEC INC"}, + {0x152F ,"PHILIPS - CRYPTO"}, + {0x1530 ,"ACQIS TECHNOLOGY INC"}, + {0x1531 ,"CHRYON CORP."}, + {0x1532 ,"ECHELON CORPORATION"}, + {0x1533 ,"BALTIMORE"}, + {0x1534 ,"ROAD CORPORATION"}, + {0x1535 ,"EVERGREEN TECHNOLOGIES INC"}, + {0x1537 ,"DATALEX COMMUNCATIONS"}, + {0x1538 ,"ARALION INC."}, + {0x1539 ,"ATELIER INFORMATIQUES ET ELECTRONIQUE ETUDES S.A."}, + {0x153A ,"ONO SOKKI"}, + {0x153B ,"TERRATEC ELECTRONIC GMBH"}, + {0x153C ,"ANTAL ELECTRONIC"}, + {0x153D ,"FILANET CORPORATION"}, + {0x153E ,"TECHWELL INC"}, + {0x153F ,"MIPS DENMARK"}, + {0x1540 ,"PROVIDEO MULTIMEDIA CO LTD"}, + {0x1541 ,"TELOSITY INC."}, + {0x1542 ,"VIVID TECHNOLOGY INC"}, + {0x1543 ,"SILICON LABORATORIES"}, + {0x1544 ,"DCM DATA SYSTEMS"}, + {0x1545 ,"VISIONTEK"}, + {0x1546 ,"IOI TECHNOLOGY CORP."}, + {0x1547 ,"MITUTOYO CORPORATION"}, + {0x1548 ,"JET PROPULSION LABORATORY"}, + {0x1549 ,"INTERCONNECT SYSTEMS SOLUTIONS"}, + {0x154A ,"MAX TECHNOLOGIES INC."}, + {0x154B ,"COMPUTEX CO LTD"}, + {0x154C ,"VISUAL TECHNOLOGY INC."}, + {0x154D ,"PAN INTERNATIONAL INDUSTRIAL CORP"}, + {0x154E ,"SERVOTEST LTD"}, + {0x154F ,"STRATABEAM TECHNOLOGY"}, + {0x1550 ,"OPEN NETWORK CO LTD"}, + {0x1551 ,"SMART ELECTRONIC DEVELOPMENT GMBH"}, + {0x1552 ,"RACAL AIRTECH LTD"}, + {0x1553 ,"CHICONY ELECTRONICS CO LTD"}, + {0x1554 ,"PROLINK MICROSYSTEMS CORP."}, + {0x1555 ,"GESYTEC GMBH"}, + {0x1556 ,"PLD APPLICATIONS"}, + {0x1557 ,"MEDIASTAR CO. LTD"}, + {0x1558 ,"CLEVO/KAPOK COMPUTER"}, + {0x1559 ,"SI LOGIC LTD"}, + {0x155A ,"INNOMEDIA INC"}, + {0x155B ,"PROTAC INTERNATIONAL CORP"}, + {0x155C ,"CEMAX-ICON INC"}, + {0x155D ,"MAC SYSTEM CO LTD"}, + {0x155E ,"LP ELEKTRONIK GMBH"}, + {0x155F ,"PERLE SYSTEMS LIMITED"}, + {0x1560 ,"TERAYON COMMUNICATIONS SYSTEMS"}, + {0x1561 ,"VIEWGRAPHICS INC"}, + {0x1562 ,"SYMBOL TECHNOLOGIES"}, + {0x1563 ,"A-TREND TECHNOLOGY CO LTD"}, + {0x1564 ,"YAMAKATSU ELECTRONICS INDUSTRY CO LTD"}, + {0x1565 ,"BIOSTAR MICROTECH INT'L CORP"}, + {0x1566 ,"ARDENT TECHNOLOGIES INC"}, + {0x1567 ,"JUNGSOFT"}, + {0x1568 ,"DDK ELECTRONICS INC"}, + {0x1569 ,"PALIT MICROSYSTEMS INC"}, + {0x156A ,"AVTEC SYSTEMS"}, + {0x156B ,"2WIRE, INC"}, + {0x156C ,"VIDAC ELECTRONICS GMBH"}, + {0x156D ,"ALPHA-TOP CORP"}, + {0x156E ,"ALFA INC."}, + {0x156F ,"M-SYSTEMS FLASH DISK PIONEERS LTD"}, + {0x1570 ,"LECROY CORPORATION"}, + {0x1571 ,"CONTEMPORARY CONTROLS"}, + {0x1572 ,"OTIS ELEVATOR COMPANY"}, + {0x1573 ,"LATTICE - VANTIS"}, + {0x1574 ,"FAIRCHILD SEMICONDUCTOR"}, + {0x1575 ,"VOLTAIRE ADVANCED DATA SECURITY LTD"}, + {0x1576 ,"VIEWCAST COM"}, + {0x1578 ,"HITT"}, + {0x1579 ,"DUAL TECHNOLOGY CORPORATION"}, + {0x157A ,"JAPAN ELECRONICS IND. INC"}, + {0x157B ,"STAR MULTIMEDIA CORP."}, + {0x157C ,"EUROSOFT (UK) LTD"}, + {0x157D ,"GEMFLEX NETWORKS"}, + {0x157E ,"TRANSITION NETWORKS"}, + {0x157F ,"PX INSTRUMENTS TECHNOLOGY LTD"}, + {0x1580 ,"PRIMEX AEROSPACE CO."}, + {0x1581 ,"SEH COMPUTERTECHNIK GMBH"}, + {0x1582 ,"CYTEC CORPORATION"}, + {0x1583 ,"INET TECHNOLOGIES INC"}, + {0x1584 ,"UNIWILL COMPUTER CORP."}, + {0x1585 ,"LOGITRON"}, + {0x1586 ,"LANCAST INC"}, + {0x1587 ,"KONICA CORPORATION"}, + {0x1588 ,"SOLIDUM SYSTEMS CORP"}, + {0x1589 ,"ATLANTEK MICROSYSTEMS PTY LTD"}, + {0x158A ,"DIGALOG SYSTEMS INC"}, + {0x158B ,"ALLIED DATA TECHNOLOGIES"}, + {0x158C ,"HITACHI SEMICONDUCTOR & DEVICES SALES CO LTD"}, + {0x158D ,"POINT MULTIMEDIA SYSTEMS"}, + {0x158E ,"LARA TECHNOLOGY INC"}, + {0x158F ,"DITECT COOP"}, + {0x1590 ,"3PARDATA INC."}, + {0x1591 ,"ARN"}, + {0x1592 ,"SYBA TECH LIMITED"}, + {0x1593 ,"BOPS INC"}, + {0x1594 ,"NETGAME LTD"}, + {0x1595 ,"DIVA SYSTEMS CORP."}, + {0x1596 ,"FOLSOM RESEARCH INC"}, + {0x1597 ,"MEMEC DESIGN SERVICES"}, + {0x1598 ,"GRANITE MICROSYSTEMS"}, + {0x1599 ,"DELTA ELECTRONICS INC"}, + {0x159A ,"GENERAL INSTRUMENT"}, + {0x159B ,"FARADAY TECHNOLOGY CORP"}, + {0x159C ,"STRATUS COMPUTER SYSTEMS"}, + {0x159D ,"NINGBO HARRISON ELECTRONICS CO LTD"}, + {0x159E ,"A-MAX TECHNOLOGY CO LTD"}, + {0x159F ,"GALEA NETWORK SECURITY"}, + {0x15A0 ,"COMPUMASTER SRL"}, + {0x15A1 ,"GEOCAST NETWORK SYSTEMS INC"}, + {0x15A2 ,"CATALYST ENTERPRISES INC"}, + {0x15A3 ,"ITALTEL"}, + {0x15A4 ,"X-NET OY"}, + {0x15A5 ,"TOYOTA MACS INC"}, + {0x15A6 ,"SUNLIGHT ULTRASOUND TECHNOLOGIES LTD"}, + {0x15A7 ,"SSE TELECOM INC"}, + {0x15A8 ,"SHANGHAI COMMUNICATIONS TECHNOLOGIES CENTER"}, + {0x15AA ,"MORETON BAY"}, + {0x15AB ,"BLUESTEEL NETWORKS INC"}, + {0x15AC ,"NORTH ATLANTIC INSTRUMENTS"}, + {0x15AD ,"VMWARE"}, + {0x15AE ,"AMERSHAM PHARMACIA BIOTECH"}, + {0x15B0 ,"ZOLTRIX INTERNATIONAL LIMITED"}, + {0x15B1 ,"SOURCE TECHNOLOGY INC"}, + {0x15B2 ,"MOSAID TECHNOLOGIES INC."}, + {0x15B3 ,"MELLANOX TECHNOLOGY"}, + {0x15B4 ,"CCI/TRIAD"}, + {0x15B5 ,"CIMETRICS INC"}, + {0x15B6 ,"TEXAS MEMORY SYSTEMS INC"}, + {0x15B7 ,"SANDISK CORP."}, + {0x15B8 ,"ADDI-DATA GMBH"}, + {0x15B9 ,"MAESTRO DIGITAL COMMUNICATIONS"}, + {0x15BA ,"IMPACCT TECHNOLOGY CORP"}, + {0x15BB ,"PORTWELL INC"}, + {0x15BC ,"AGILENT TECHNOLOGIES"}, + {0x15BD ,"DFI INC."}, + {0x15BE ,"SOLA ELECTRONICS"}, + {0x15BF ,"HIGH TECH COMPUTER CORP (HTC)"}, + {0x15C0 ,"BVM LIMITED"}, + {0x15C1 ,"QUANTEL"}, + {0x15C2 ,"NEWER TECHNOLOGY INC"}, + {0x15C3 ,"TAIWAN MYCOMP CO LTD"}, + {0x15C4 ,"EVSX, INC"}, + {0x15C5 ,"PROCOMP INFORMATICS LTD"}, + {0x15C6 ,"TECHNICAL UNIVERSITY OF BUDAPEST"}, + {0x15C7 ,"TATEYAMA SYSTEM LABORATORY CO LTD"}, + {0x15C8 ,"PENTA MEDIA CO. LTD"}, + {0x15C9 ,"SEROME TECHNOLOGY INC"}, + {0x15CA ,"BITBOYS OY"}, + {0x15CB ,"AG ELECTRONICS LTD"}, + {0x15CC ,"HOTRAIL INC."}, + {0x15CD ,"DREAMTECH CO LTD"}, + {0x15CE ,"GENRAD INC."}, + {0x15CF ,"HILSCHER GMBH"}, + {0x15D1 ,"INFINEON TECHNOLOGIES AG"}, + {0x15D2 ,"FIC (FIRST INTERNATIONAL COMPUTER INC)"}, + {0x15D3 ,"NDS TECHNOLOGIES ISRAEL LTD"}, + {0x15D4 ,"IWILL CORPORATION"}, + {0x15D5 ,"TATUNG CO."}, + {0x15D6 ,"ENTRIDIA CORPORATION"}, + {0x15D7 ,"ROCKWELL-COLLINS, INC"}, + {0x15D8 ,"CYBERNETICS TECHNOLOGY CO LTD"}, + {0x15D9 ,"SUPER MICRO COMPUTER INC"}, + {0x15DA ,"CYBERFIRM INC."}, + {0x15DB ,"APPLIED COMPUTING SYSTEMS INC."}, + {0x15DC ,"LITRONIC INC"}, + {0x15DD ,"SIGMATEL INC."}, + {0x15DE ,"MALLEABLE TECHNOLOGIES INC"}, + {0x15DF ,"INFINILINK CORP."}, + {0x15E0 ,"CACHEFLOW INC"}, + {0x15E1 ,"VOICE TECHNOLOGIES GROUP INC."}, + {0x15E2 ,"QUICKNET TECHNOLOGIES INC"}, + {0x15E3 ,"NETWORTH TECHNOLOGIES INC"}, + {0x15E4 ,"VSN SYSTEMEN BV"}, + {0x15E5 ,"VALLEY TECHNOLOGIES INC"}, + {0x15E6 ,"AGERE INC."}, + {0x15E7 ,"GET ENGINEERING CORP."}, + {0x15E8 ,"NATIONAL DATACOMM CORP."}, + {0x15E9 ,"PACIFIC DIGITAL CORP."}, + {0x15EA ,"TOKYO DENSHI SEKEI K.K."}, + {0x15EB ,"DRSEARCH GMBH"}, + {0x15EC ,"BECKHOFF GMBH"}, + {0x15ED ,"MACROLINK INC"}, + {0x15EE ,"IN WIN DEVELOPMENT INC."}, + {0x15EF ,"INTELLIGENT PARADIGM INC"}, + {0x15F0 ,"B-TREE SYSTEMS INC"}, + {0x15F1 ,"TIMES N SYSTEMS INC"}, + {0x15F2 ,"DIAGNOSTIC INSTRUMENTS INC"}, + {0x15F3 ,"DIGITMEDIA CORP."}, + {0x15F4 ,"VALUESOFT"}, + {0x15F5 ,"POWER MICRO RESEARCH"}, + {0x15F6 ,"EXTREME PACKET DEVICE INC"}, + {0x15F7 ,"BANCTEC"}, + {0x15F8 ,"KOGA ELECTRONICS CO"}, + {0x15F9 ,"ZENITH ELECTRONICS CORPORATION"}, + {0x15FA ,"J.P. AXZAM CORPORATION"}, + {0x15FB ,"ZILOG INC."}, + {0x15FC ,"TECHSAN ELECTRONICS CO LTD"}, + {0x15FD ,"N-CUBED.NET"}, + {0x15FE ,"KINPO ELECTRONICS INC"}, + {0x15FF ,"FASTPOINT TECHNOLOGIES INC."}, + {0x1600 ,"NORTHROP GRUMMAN - CANADA LTD"}, + {0x1601 ,"TENTA TECHNOLOGY"}, + {0x1602 ,"PROSYS-TEC INC."}, + {0x1603 ,"NOKIA WIRELESS BUSINESS COMMUNICATIONS"}, + {0x1604 ,"CENTRAL SYSTEM RESEARCH CO LTD"}, + {0x1605 ,"PAIRGAIN TECHNOLOGIES"}, + {0x1606 ,"EUROPOP AG"}, + {0x1607 ,"LAVA SEMICONDUCTOR MANUFACTURING INC."}, + {0x1608 ,"AUTOMATED WAGERING INTERNATIONAL"}, + {0x1609 ,"SCIEMETRIC INSTRUMENTS INC"}, + {0x1813 ,"AMBIENT TECHNOLOGIES INC"}, + {0x1B13 ,"JATON CORP"}, + {0x2001 ,"TEMPORAL RESEARCH LTD"}, + {0x270F ,"CHAINTECH COMPUTER CO. LTD"}, + {0x3388 ,"HINT CORP"}, + {0x3411 ,"QUANTUM DESIGNS (H.K.) INC."}, + {0x4005 ,"AVANCE LOGIC INC"}, + {0x4033 ,"DELTA NETWORKS INC"}, + {0x416C ,"ALADDIN KNOWLEDGE SYSTEMS"}, + {0x4444 ,"ICOMPRESION INC."}, + {0x4943 ,"GROWTH NETWORKS"}, + {0x4CA1 ,"SEANIX TECHNOLOGY INC"}, + {0x4D51 ,"MEDIAQ INC."}, + {0x4D54 ,"MICROTECHNICA CO LTD"}, + {0x5136 ,"S S TECHNOLOGIES"}, + {0x5333 ,"S3 INC."}, + {0x544C ,"TERALOGIC INC"}, + {0x5555 ,"GENROCO INC"}, + {0x6409 ,"LOGITEC CORP."}, + {0x6666 ,"DECISION COMPUTER INTERNATIONAL CO."}, + {0x8086 ,"INTEL CORP."}, + {0x8888 ,"SILICON MAGIC CORP."}, + {0x8E0E ,"COMPUTONE CORPORATION"}, + {0x9004 ,"ADAPTEC"}, + {0x919A ,"GIGAPIXEL CORP"}, + {0x9699 ,"OMNI MEDIA TECHNOLOGY INC."}, + {0xA0A0 ,"AOPEN INC."}, + {0xA0F1 ,"UNISYS CORPORATION"}, + {0xA259 ,"HEWLETT PACKARD"}, + {0xAC1E ,"DIGITAL RECEIVER TECHNOLOGY INC"}, + {0xC0DE ,"MOTOROLA"}, + {0xC0FE ,"MOTION ENGINEERING, INC."}, + {0xCA50 ,"VARIAN AUSTRIALIA PTY LTD"}, + {0xCAFE ,"CHRYSALIS-ITS"}, + {0xCCCC ,"CATAPULT COMMUNICATIONS"}, + {0xD4D4 ,"DY4 SYSTEMS INC"}, + {0xE4BF ,"EKF ELEKTRONIK GMBH"}, + {0xEA01 ,"EAGLE TECHNOLOGY"}, + {0xFA57 ,"FAST SEARCH & TRANSFER ASA"}, + {0xFEDA ,"EPIGRAM INC"} +}; \ No newline at end of file diff --git a/apps/utils/pice/module/pgflt.c b/apps/utils/pice/module/pgflt.c new file mode 100644 index 0000000..6306f4b --- /dev/null +++ b/apps/utils/pice/module/pgflt.c @@ -0,0 +1,402 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + pgflt.c + +Abstract: + + page fault handling on x86 + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 25-Nov-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" + +#include "precomp.h" + +//////////////////////////////////////////////////// +// GLOBALS +//// + +char tempPageFault[1024]; +extern void NewInt31Handler(void); + +ULONG OldIntEHandler=0; +ULONG error_code; +BOOLEAN bInPageFaultHandler = FALSE; +static ULONG PCR_SEL = PCR_SELECTOR; +static ULONG OLD_PCR; + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// HandleInDebuggerFault() +// +//************************************************************************* +ULONG HandleInDebuggerFault(FRAME* ptr,ULONG address) +{ + PEPROCESS tsk; + + ENTER_FUNC(); + + DPRINT((0,"HandleInDebuggerFault(): ###### page fault @ %.8X while inside debugger, eip: %x\n",address, ptr->eip)); + + // fault in this page fault handler + if(bInPageFaultHandler) + { + DPRINT((0,"HandleInDebuggerFault(): ###### page fault @ %.8X while in page fault handler\n",address)); + + DPRINT((0,"!!! machine is halted !!!\n")); + __asm__ __volatile__ ("hlt"); + + LEAVE_FUNC(); + return 0; + } + + bInPageFaultHandler = TRUE; + + // when we come here from DebuggerShell() we live on a different stack + // so the current task is different as well + tsk = IoGetCurrentProcess(); + + DPRINT((0,"%.8X (%.4X:%.8X %.8X %s %s %s task=%.8X )\n", + address, + ptr->cs, + ptr->eip, + ptr->eflags, + (ptr->error_code&1)?"PLP":"NP", + (ptr->error_code&2)?"WRITE":"READ", + (ptr->error_code&4)?"USER-MODE":"KERNEL-MODE", + (ULONG)tsk)); + + if(!bInPrintk) + { + DPRINT((0,"HandleInDebuggerFault(): unexpected pagefault in command handler!\n",address)); + } + else + { + DPRINT((0,"HandleInDebuggerFault(): unexpected pagefault in command handler while in PrintkCallback()!\n",address)); + } + + if(tsk) + { + PULONG pPGD; + PULONG pPTE; + + pPGD = ADDR_TO_PDE(address); + + DPRINT((0,"PGD for %.8X @ %.8X = %.8X\n",address,(ULONG)pPGD,(ULONG)(*pPGD) )); + + if(pPGD && (*pPGD)&_PAGE_PRESENT) + { + // not large page + if(!((*pPGD)&_PAGE_4M)) + { + pPTE = ADDR_TO_PTE(address); + if(pPTE) + { + DPRINT((0,"PTE for %.8X @ %.8X = %.8X\n",address,(ULONG)pPTE,(ULONG)(*pPTE) )); + } + } + } + } + + IntelStackWalk(ptr->eip,CurrentEBP,ulRealStackPtr); + + DPRINT((0,"!!! machine is halted !!!\n")); + __asm__ __volatile__ ("hlt"); + + LEAVE_FUNC(); + + return 2; +} + +//************************************************************************* +// HandlePageFault() +// +// returns: +// 0 = let the system handle it +// 1 = call DebuggerShell() +// 2 = FATAL error inside debugger +//************************************************************************* +ULONG HandlePageFault(FRAME* ptr) +{ + PVOID address; + PEPROCESS tsk, tsk1; + PMADDRESS_SPACE vma; + PLIST_ENTRY current_entry; + MEMORY_AREA* current; + ULONG value; + PKTHREAD CurrentThread; + PETHREAD CurrentEThread; + + // get linear address of page fault + __asm__ __volatile__("movl %%cr2,%0" + :"=r" (address)); + + DPRINT((0,"\nPageFault: bInDebShell: %d, error: %d, addr: %x\n", bInDebuggerShell, ptr->error_code, address)); + + // there's something terribly wrong if we get a fault in our command handler + if(bInDebuggerShell) + { + DPRINT((0,"return handleindebuggerfault\n")); + return HandleInDebuggerFault(ptr,(ULONG)address); + } + + ASSERT(IsAddressValid((ULONG)ptr)); + // remember error code so we can push it back on the stack + error_code = ptr->error_code; + + //ei Check IRQL here!!! +/* + if(in_interrupt()) + { + Print(OUTPUT_WINDOW,"pICE: system is currently processing an interrupt!\n"); + return 1; + } +*/ + // current process + tsk = IoGetCurrentProcess(); + DPRINT((0,"tsk: %x\t", tsk)); + if( !tsk || !(IsAddressValid((ULONG)tsk))){ + DPRINT((0,"tsk address not valid: tsk: %x\n", tsk)); + return 0; + } + + // lookup VMA for this address + if( (ULONG)address > KERNEL_BASE ) + vma = my_init_mm; // use kernel mem area for kernel addresses + else vma = &(tsk->AddressSpace); // otherwise, use user memory area + + if( !vma ){ + DPRINT((0,"vma not valid: vma: %x\n", vma)); + return 0; + } + + current_entry = vma->MAreaListHead.Flink; + ASSERT(current_entry); + DPRINT((0,"vma: %x, current_entry: %x, kernel arena: %x\n", vma, current_entry, my_init_mm)); + while(current_entry != &vma->MAreaListHead) + { + ASSERT(current_entry); + ASSERT(IsAddressValid((ULONG)current_entry)); + current = CONTAINING_RECORD(current_entry, + MEMORY_AREA, + Entry); + + + if( (address >= current->BaseAddress) && (address <= current->BaseAddress + current->Length )) + { + DPRINT((0,"address: %x %x - %x Attrib: %x, Type: %x\n", address, current->BaseAddress, current->BaseAddress + current->Length, current->Attributes, current->Type)); + //page not present + if( !(error_code & 1) ){ + //check it is in pageable area + if( current->Type == MEMORY_AREA_SECTION_VIEW || + current->Type == MEMORY_AREA_VIRTUAL_MEMORY || + current->Type == MEMORY_AREA_PAGED_POOL || + current->Type == MEMORY_AREA_SHARED_DATA + ){ + //ei too much output Print(OUTPUT_WINDOW,"pICE: VMA Pageable Section.\n"); + //ei DPRINT((0,"return 0 1\n")); + return 0; //let the system handle this + } + Print(OUTPUT_WINDOW,"pICE: VMA Page not present in non-pageable Section!\n"); + //ei DPRINT((0,"Type: currenttype: %x return 1 2\n", current->Type)); + return 0; + } + else{ //access violation + + if( error_code & 4 ) + { //user mode + if( (ULONG)address >= KERNEL_BASE ) + { + Print(OUTPUT_WINDOW,"pICE: User mode program trying to access kernel memory!\n"); + //DPRINT((0,"return 0 3\n")); + return 1; + } + //DPRINT((0,"return 0 4\n")); + return 0; + } + /* + if(error_code & 2) + { + //on write + if(!(current->Attributes & PAGE_READONLY)) + { + Print(OUTPUT_WINDOW,"pICE: virtual memory arena is not writeable!\n"); + return 1; + } + } + // READ ACCESS + else + { + // test EXT bit in error code + if (error_code & 1) + { + Print(OUTPUT_WINDOW,"pICE: page-level protection fault!\n"); + return 1; + } + // + */ + /* + if (!(current->Attributes & PAGE_EXECUTE_READ)) + { + Print(OUTPUT_WINDOW,"pICE: VMA is not readable!\n"); + return 1; + } + */ + + // let the system handle it + //DPRINT((0,"return 0 5\n")); + return 0; + } + } + current_entry = current_entry->Flink; + } + + Print(OUTPUT_WINDOW,"pICE: no virtual memory arena at this address!\n"); + DPRINT((0,"return 0 6\n")); + return 1; + + // let the system handle it +// return 0; +} + +//************************************************************************* +// NewIntEHandler() +// +//************************************************************************* +__asm__ ("\n\t \ +NewIntEHandler:\n\t \ + pushfl\n\t \ + cli\n\t \ + cld\n\t \ + pushal\n\t \ + pushl %ds\n\t \ +\n\t \ + // setup default data selectors\n\t \ + movw %ss,%ax\n\t \ + movw %ax,%ds\n\t \ +\n\t \ + /*\n\t \ + * Load the PCR selector.\n\t \ + */\n\t \ + movl %fs, %eax\n\t \ + movl %eax, _OLD_PCR\n\t \ + movl _PCR_SEL, %eax\n\t \ + movl %eax, %fs\n\t \ +\n\t \ + // get frame ptr\n\t \ + lea 40(%esp),%eax\n\t \ + pushl %eax\n\t \ + call _HandlePageFault\n\t \ + addl $4,%esp\n\t \ +\n\t \ + pushl %eax\n\t \ + movl _OLD_PCR, %eax\n\t \ + movl %eax, %fs\n\t \ + popl %eax\n\t \ +\n\t \ + cmpl $0,%eax\n\t \ + je call_old_inte_handler\n\t \ +\n\t \ + cmpl $2,%eax\n\t \ + je call_handler_unknown_reason\n\t \ +\n\t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ + // remove error code. will be restored later when we call\n\t \ + // original handler again.\n\t \ + addl $4,%esp\n\t \ + // call debugger loop\n\t \ + pushl $" STR(REASON_PAGEFAULT) "\n\t \ + jmp NewInt31Handler\n\t \ +\n\t \ +call_old_inte_handler:\n\t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ + // chain to old handler\n\t \ + .byte 0x2e\n\t \ + jmp *_OldIntEHandler\n\t \ +\n\t \ +call_handler_unknown_reason:\n\t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ + // remove error code. will be restored later when we call\n\t \ + // original handler again.\n\t \ + addl $4,%esp\n\t \ + // call debugger loop\n\t \ + pushl $" STR(REASON_INTERNAL_ERROR) "\n\t \ + jmp NewInt31Handler\n\t \ + "); + + +//************************************************************************* +// InstallIntEHook() +// +//************************************************************************* +void InstallIntEHook(void) +{ + ULONG LocalIntEHandler; + + ENTER_FUNC(); + + MaskIrqs(); + if(!OldIntEHandler) + { + __asm__ __volatile__("mov $NewIntEHandler,%0" + :"=r" (LocalIntEHandler) + : + :"eax"); + OldIntEHandler=SetGlobalInt(0x0E,(ULONG)LocalIntEHandler); + } + UnmaskIrqs(); + DPRINT((0,"OldIntE @ %x\n", OldIntEHandler)); + LEAVE_FUNC(); +} + +//************************************************************************* +// DeInstallIntEHook() +// +//************************************************************************* +void DeInstallIntEHook(void) +{ + ENTER_FUNC(); + + MaskIrqs(); + if(OldIntEHandler) + { + SetGlobalInt(0x0E,(ULONG)OldIntEHandler); + OldIntEHandler=0; + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} diff --git a/apps/utils/pice/module/pgflt.h b/apps/utils/pice/module/pgflt.h new file mode 100644 index 0000000..170a3ef --- /dev/null +++ b/apps/utils/pice/module/pgflt.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + pgflt.h + +Abstract: + + HEADER for pgflt.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void InstallIntEHook(void); +void DeInstallIntEHook(void); + +extern ULONG error_code; diff --git a/apps/utils/pice/module/pice.rc b/apps/utils/pice/module/pice.rc new file mode 100644 index 0000000..f6d88eb --- /dev/null +++ b/apps/utils/pice/module/pice.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "PICE Debugger\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "pice\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "pice.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/apps/utils/pice/module/pice_ver.h b/apps/utils/pice/module/pice_ver.h new file mode 100644 index 0000000..f015033 --- /dev/null +++ b/apps/utils/pice/module/pice_ver.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + pice_ver.h + +Abstract: + + HEADER , pICE debugger version + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +// versions below 1.0 are BETA +#define PICE_MAJOR_VERSION (0) +#define PICE_MINOR_VERSION (99) +// reset this on major or minor version change +// increment this on every release build +#define PICE_BUILD (0007) \ No newline at end of file diff --git a/apps/utils/pice/module/precomp.h b/apps/utils/pice/module/precomp.h new file mode 100644 index 0000000..90d3757 --- /dev/null +++ b/apps/utils/pice/module/precomp.h @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + precomp.h + +Abstract: + + precompiled headers + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#define FRAMEBUFFER_SIZE (0x8000) +#define LINES_IN_BUFFER (2048) + +#include +#include +#include +#include +#include +#include +#include + +#include "retypes.h" +//#include +#include "../shared/shared.h" +#include "debug.h" +#include "hardware.h" +#include "utils.h" +#include "init.h" +#include "shell.h" +#include "trace.h" +#include "hooks.h" +#include "patch.h" // patch the keyboard driver +#include "symbols.h" +#include "parse.h" +#include "syscall.h" +#include "bp.h" +#include "scancodes.h" +#include "output.h" +#include "dblflt.h" +#include "pgflt.h" +#include "gpfault.h" +#include "serial.h" +#include "hercules.h" +#include "vga.h" +#include "pice_ver.h" diff --git a/apps/utils/pice/module/privateice.c b/apps/utils/pice/module/privateice.c new file mode 100644 index 0000000..2ea94f0 --- /dev/null +++ b/apps/utils/pice/module/privateice.c @@ -0,0 +1,202 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + privateice.c + +Abstract: + +Environment: + +Author: + + Klaus P. Gerlicher + + reactos port by: + Eugene Ingerman + +Revision History: + + 16-Jul-1998: created + 15-Nov-2000: general cleanup of source files + 19-Jan-2001: renamed to privateice.c + + 10/20/2001: porting to reactos begins + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +/* +#include +#include +#include +#include +#include +#include +#include +#include +*/ + +#include +#include + +#include "precomp.h" +#include "serial.h" + +//////////////////////////////////////////////////// +// GLOBALS +//// + +BOOLEAN bDeviceAlreadyOpen = FALSE; + +char tempPICE[1024]; + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// pice_open() +// +//************************************************************************* + +NTSTATUS STDCALL pice_open(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT((0,"pice_open\n")); + + /* We don't want to talk to two processes at the + * same time */ + if (bDeviceAlreadyOpen){ + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return STATUS_UNSUCCESSFUL; /* is there a more descriptive status code for this case? */ + } + + bDeviceAlreadyOpen = TRUE; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +//************************************************************************* +// pice_close() +// +//************************************************************************* +NTSTATUS STDCALL pice_close(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT((0,"pice_close\n")); + + CleanUpPICE(); // used to be in cleanup_module + + /* We're now ready for our next caller */ + bDeviceAlreadyOpen = FALSE; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + + +//************************************************************************* +// pice_ioctl() +// +//************************************************************************* + +NTSTATUS STDCALL pice_ioctl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ +// char* pFilename = (char*) ioctl_param; + + PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation( Irp ); + + ULONG Code = IoStack->Parameters.DeviceIoControl.IoControlCode; + + switch(Code) + { + case PICE_IOCTL_LOAD: + break; + case PICE_IOCTL_RELOAD: + if(!ReloadSymbols()) + { + PICE_sprintf(tempPICE,"pICE: not able to reload symbols\n"); + Print(OUTPUT_WINDOW,tempPICE); + } + break; + case PICE_IOCTL_UNLOAD: + UnloadSymbols(); + break; + case PICE_IOCTL_BREAK: + PICE_sprintf(tempPICE,"pICE: forcible break\n"); + Print(OUTPUT_WINDOW,tempPICE); + __asm__ __volatile("int $3"); + break; + case PICE_IOCTL_STATUS: + { + PDEBUGGER_STATUS_BLOCK ustatus_block_p; + DEBUGGER_STATUS_BLOCK kstatus_block; + + ULONG OutLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + if( OutLength < sizeof( DEBUGGER_STATUS_BLOCK ) ){ + return STATUS_INVALID_PARAMETER; + } + + ustatus_block_p = (PDEBUGGER_STATUS_BLOCK)Irp->AssociatedIrp.SystemBuffer; + + //kstatus_block.Test = 0x12345678; + RtlCopyMemory(ustatus_block_p, &kstatus_block, sizeof(DEBUGGER_STATUS_BLOCK) ); + } + break; + default: + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return STATUS_INVALID_PARAMETER; + } + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Module entry point + */ +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName; + UNICODE_STRING SymlinkName; + + DPRINT((0,"PICE Debugger\n")); + +#if 0 // don't enable before completely ported +#ifdef DEBUG + // first we enable output of debug strings to COM port + DebugSetupSerial(1,115200); +#endif // DEBUG +#endif + + if(InitPICE()){ + DriverObject->MajorFunction[IRP_MJ_CREATE] = pice_open; + //ei unimplemented DriverObject->MajorFunction[IRP_MJ_CLOSE] = pice_close; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = pice_ioctl; + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\Pice"); + IoCreateDevice(DriverObject, + 0, + &DeviceName, + PICE_DEVICE_DEBUGGER, + 0, + TRUE, + &DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; + + RtlInitUnicodeStringFromLiteral(&SymlinkName, L"\\??\\Pice"); + IoCreateSymbolicLink(&SymlinkName, &DeviceName); + + return(STATUS_SUCCESS); + } +} + diff --git a/apps/utils/pice/module/regs.h b/apps/utils/pice/module/regs.h new file mode 100644 index 0000000..43e99ae --- /dev/null +++ b/apps/utils/pice/module/regs.h @@ -0,0 +1,122 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + regs.h + +Abstract: + + HEADER for disasm.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +#define REGGS 0 +#define REGFS 1 +#define REGES 2 +#define REGDS 3 +#define REGEDI 4 +#define REGESI 5 +#define REGEBX 6 +#define REGEDX 7 +#define REGECX 8 +#define REGEAX 9 +#define REGEBP 10 +#define REGEIP 11 +#define REGCS 12 +#define REGEFL 13 +#define REGESP 14 +#define REGSS 15 + +#ifdef KERNEL +#define REGCR0 16 +#define REGCR2 17 +#define REGCR3 18 +#define REGCR4 19 +#endif + +#define REGDR0 20 +#define REGDR1 21 +#define REGDR2 22 +#define REGDR3 23 +#define REGDR6 24 +#define REGDR7 25 + +#ifdef KERNEL +#define REGGDTR 26 +#define REGGDTL 27 +#define REGIDTR 28 +#define REGIDTL 29 +#define REGTR 30 +#define REGLDTR 31 +#endif + +// Pseudo-registers: +#define PREGEA 40 +#define PREGBASE PREGEA +#define PREGEXP 41 +#define PREGRA 42 +#define PREGP 43 +#define PREGU0 44 +#define PREGU1 45 +#define PREGU2 46 +#define PREGU3 47 +#define PREGU4 48 +#define PREGU5 49 +#define PREGU6 50 +#define PREGU7 51 +#define PREGU8 52 +#define PREGU9 53 + +#define FLAGBASE 100 +#define REGDI 100 +#define REGSI 101 +#define REGBX 102 +#define REGDX 103 +#define REGCX 104 +#define REGAX 105 +#define REGBP 106 +#define REGIP 107 +#define REGFL 108 +#define REGSP 109 +#define REGBL 110 +#define REGDL 111 +#define REGCL 112 +#define REGAL 113 +#define REGBH 114 +#define REGDH 115 +#define REGCH 116 +#define REGAH 117 +#define FLAGIOPL 118 +#define FLAGOF 119 +#define FLAGDF 120 +#define FLAGIF 121 +#define FLAGTF 122 +#define FLAGSF 123 +#define FLAGZF 124 +#define FLAGAF 125 +#define FLAGPF 126 +#define FLAGCF 127 +#define FLAGVIP 128 +#define FLAGVIF 129 + + +#define REGFIR REGEIP diff --git a/apps/utils/pice/module/remods.h b/apps/utils/pice/module/remods.h new file mode 100644 index 0000000..6c64d78 --- /dev/null +++ b/apps/utils/pice/module/remods.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + remods.h + +Abstract: + + HEADER for kernel module creation + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + + + diff --git a/apps/utils/pice/module/retypes.h b/apps/utils/pice/module/retypes.h new file mode 100644 index 0000000..8dc77f0 --- /dev/null +++ b/apps/utils/pice/module/retypes.h @@ -0,0 +1,52 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + retypes.h + +Abstract: + + HEADER for type remapping (porting from NT code) + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +//typedef unsigned int ULONG,*PULONG; +//typedef unsigned short USHORT,*PUSHORT; +//typedef unsigned char UCHAR,*PUCHAR,BYTE,*PBYTE; + +//typedef signed int LONG,*PLONG; +//typedef signed short SHORT,*PSHORT; +//typedef signed char CHAR,*PCHAR,*LPSTR,*PSTR; +//typedef unsigned short WCHAR; + +//typedef void VOID,*PVOID; + +//typedef char BOOLEAN,*PBOOLEAN; + +//#define FALSE (0==1) +//#define TRUE (1==1) +#ifndef NULL +#define NULL ((void*)0) +#endif + +// dimension macro +#define DIM(name) (sizeof(name)/sizeof(name[0])) + diff --git a/apps/utils/pice/module/scancodes.h b/apps/utils/pice/module/scancodes.h new file mode 100644 index 0000000..ea76882 --- /dev/null +++ b/apps/utils/pice/module/scancodes.h @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + scancodes.h + +Abstract: + + HEADER, scancodes of IBM keyboard + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +/* +** Scan Code Definitions . . . +*/ +// System Keys +#define SCANCODE_ESC 0x01 +#define SCANCODE_BACKSPACE 0x0E +#define SCANCODE_TAB 0x0F + +#define SCANCODE_ENTER 0x1C +#define SCANCODE_L_CTRL 0x1D +#define SCANCODE_R_CTRL 0x5A +#define SCANCODE_L_SHIFT 0x2A +#define SCANCODE_R_SHIFT 0x36 +#define SCANCODE_L_ALT 0x38 +#define SCANCODE_R_ALT 0x5C + +#define SCANCODE_SPACE 0x39 +#define SCANCODE_CAPS_LOCK 0x3A +#define SCANCODE_NUM_LOCK 0x45 +#define SCANCODE_PRNT_SCRN 0x47 +#define SCANCODE_SCROLL_LOCK 0x57 + +// Function Keys +#define SCANCODE_F1 0x3b +#define SCANCODE_F2 0x3c +#define SCANCODE_F3 0x3d +#define SCANCODE_F4 0x3e +#define SCANCODE_F5 0x3f +#define SCANCODE_F6 0x40 +#define SCANCODE_F7 0x41 +#define SCANCODE_F8 0x42 +#define SCANCODE_F9 0x43 +#define SCANCODE_F10 0x44 +#define SCANCODE_F11 0x57 +#define SCANCODE_F12 0x58 + +// Directional Control Keys +#define SCANCODE_HOME 0x47 +#define SCANCODE_UP 0x48 +#define SCANCODE_PGUP 0x49 +#define SCANCODE_LEFT 0x4b +#define SCANCODE_CENTER 0x4c +#define SCANCODE_RIGHT 0x4d +#define SCANCODE_END 0x4f +#define SCANCODE_DOWN 0x50 +#define SCANCODE_PGDN 0x51 +#define SCANCODE_INS 0x52 +#define SCANCODE_DEL 0x53 + +// Cluster Directional Control Keys +#define SCANCODE_C_ENTER 0x59 +#define SCANCODE_C_HOME 0x5d +#define SCANCODE_C_UP 0x5e +#define SCANCODE_C_PGUP 0x5f +#define SCANCODE_C_LEFT 0x60 +#define SCANCODE_C_RIGHT 0x61 +#define SCANCODE_C_END 0x62 +#define SCANCODE_C_DOWN 0x63 +#define SCANCODE_C_PGDN 0x64 +#define SCANCODE_C_INS 0x65 +#define SCANCODE_C_DEL 0x66 + + +// Alphanumerics +#define SCANCODE_1 0x02 +#define SCANCODE_2 0x03 +#define SCANCODE_3 0x04 +#define SCANCODE_4 0x05 +#define SCANCODE_5 0x06 +#define SCANCODE_6 0x07 +#define SCANCODE_7 0x08 +#define SCANCODE_8 0x09 +#define SCANCODE_9 0x0A +#define SCANCODE_0 0x0B + +#define SCANCODE_EXTENDED 0xE0 \ No newline at end of file diff --git a/apps/utils/pice/module/serial.c b/apps/utils/pice/module/serial.c new file mode 100644 index 0000000..3998492 --- /dev/null +++ b/apps/utils/pice/module/serial.c @@ -0,0 +1,656 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + serial.c + +Abstract: + + serial debugger connection + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 19-Aug-2000: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#include "remods.h" +#include "precomp.h" +#include "serial_port.h" + +BOOLEAN SerialReadByte(PUCHAR px); + + +// used for SERIAL window creation +// NB: at the moment the terminal is 60 lines high. +WINDOW wWindowSerial[4]= +{ + {1,3,1,0,FALSE}, + {5,8,1,0,FALSE}, + {14,26,1,0,FALSE}, + {41,18,1,0,FALSE} +}; + +PUCHAR pScreenBufferSerial; + +USHORT usSerialPortBase; + +UCHAR packet[_PAGE_SIZE]; +UCHAR assemble_packet[_PAGE_SIZE]; + +UCHAR flush_buffer[_PAGE_SIZE],g_x,g_y; +ULONG ulFlushBufferPos = 0; + +UCHAR ucLastKeyRead; +ECOLORS eForegroundColor=WHITE,eBackgroundColor=BLACK; + +///************************************************************************ +// SerialSetSpeed() +// +///************************************************************************ +void SerialSetSpeed(ULONG baudrate) +{ + UCHAR c; + ULONG divisor; + + divisor = (ULONG) (115200L/baudrate); + + c = inportb((USHORT)(usSerialPortBase + LCR)); + outportb((USHORT)(usSerialPortBase + LCR), (UCHAR)(c | 0x80)); // Set DLAB + outportb((USHORT)(usSerialPortBase + DLL), (UCHAR)(divisor & 0x00FF)); + outportb((USHORT)(usSerialPortBase + DLH), (UCHAR)((divisor >> 8) & 0x00FF)); + outportb((USHORT)(usSerialPortBase + LCR), c); // Reset DLAB + +} + +///************************************************************************ +// SerialSetOthers() +// +// Set other communications parameters +//************************************************************************ +void SerialSetOthers(ULONG Parity, ULONG Bits, ULONG StopBit) +{ + ULONG setting; + UCHAR c; + + if (usSerialPortBase == 0) return ; + if (Bits < 5 || Bits > 8) return ; + if (StopBit != 1 && StopBit != 2) return ; + if (Parity != NO_PARITY && Parity != ODD_PARITY && Parity != EVEN_PARITY) + return; + + setting = Bits-5; + setting |= ((StopBit == 1) ? 0x00 : 0x04); + setting |= Parity; + + c = inportb((USHORT)(usSerialPortBase + LCR)); + outportb((USHORT)(usSerialPortBase + LCR), (UCHAR)(c & ~0x80)); // Reset DLAB + + // no ints + outportb((USHORT)(usSerialPortBase + IER), (UCHAR)0); + + // clear FIFO and disable them + outportb((USHORT)(usSerialPortBase + FCR), (UCHAR)0); + + outportb((USHORT)(usSerialPortBase + LCR), (UCHAR)setting); + + outportb((USHORT)(usSerialPortBase + MCR), DTR | RTS); + + + return ; +} + +///************************************************************************ +// FlushSerialBuffer() +// +///************************************************************************ +void FlushSerialBuffer(void) +{ + UCHAR c; + + while(SerialReadByte(&c)); +} + +///************************************************************************ +// SetupSerial() +// +///************************************************************************ +void SetupSerial(ULONG port,ULONG baudrate) +{ + USHORT ports[]={COM1BASE,COM2BASE,COM3BASE,COM4BASE}; + + usSerialPortBase = ports[port-1]; + SerialSetOthers(NO_PARITY,8,1); + SerialSetSpeed(baudrate); + + // clear out received bytes + // else we would think there's a terminal connected + FlushSerialBuffer(); +} + + +///************************************************************************ +// SerialReadByte() +// +// Output a character to the serial port +//************************************************************************ +BOOLEAN SerialReadByte(PUCHAR px) +{ + ULONG timeout; + + timeout = 0x00FFFFL; + + // Wait for transmitter to clear + while ((inportb((USHORT)(usSerialPortBase + LSR)) & RCVRDY) == 0) + if (!(--timeout)) + { + return FALSE; + } + + *px = inportb((USHORT)(usSerialPortBase + RXR)); + + return TRUE; +} + +///************************************************************************ +// SerialSendByte() +// +// Output a character to the serial port +//************************************************************************ +BOOLEAN SerialSendByte(UCHAR x) +{ + ULONG timeout; + + timeout = 0x00FFFFL; + + // Wait for transmitter to clear + while ((inportb((USHORT)(usSerialPortBase + LSR)) & XMTRDY) == 0) + if (!(--timeout)) + { + return FALSE; + } + + outportb((USHORT)(usSerialPortBase + TXR), x); + + return TRUE; +} + +//************************************************************************ +// CheckSum() +// +//************************************************************************ +UCHAR CheckSum(LPSTR p,ULONG Len) +{ + UCHAR ucCheckSum = 0; + ULONG i; + for(i=0;iheader; + ULONG i; + UCHAR c; + ULONG timeout; + + do + { + timeout = 10; + pHeader = (PUCHAR)&p->header; + for(i=0;i<(sizeof(SERIAL_PACKET_HEADER)+p->header.packet_size);i++) + { + if(!SerialSendByte(*pHeader++)) + { + return FALSE; + } + } + + do + { + c = 0; + SerialReadByte(&c); + if(c != ACK) + ucLastKeyRead = c; + }while(c != ACK && timeout--); + + }while(c != ACK); + + return TRUE; +} + +///************************************************************************ +// SendPacketTimeout() +// +///************************************************************************ +BOOLEAN SendPacketTimeout(PSERIAL_PACKET p) +{ + PUCHAR pHeader = (PUCHAR)&p->header; + ULONG i; + UCHAR c; + ULONG timeout = 20; + BOOLEAN bResult = TRUE; + + pHeader = (PUCHAR)&p->header; + for(i=0;i<(sizeof(SERIAL_PACKET_HEADER)+p->header.packet_size);i++) + { + if(!SerialSendByte(*pHeader++)) + { + return FALSE; + } + } + + do + { + c = 0xFF; + SerialReadByte(&c); + }while(c != ACK && timeout--); + + if(c != ACK) + bResult = FALSE; + + return bResult; +} + + +//************************************************************************ +// AssemblePacket() +// +//************************************************************************ +PSERIAL_PACKET AssemblePacket(PUCHAR pData,ULONG ulSize) +{ + PSERIAL_PACKET p; + ULONG ulCheckSum; + + p = (PSERIAL_PACKET)assemble_packet; + + // fill in header + p->header.packet_chksum = CheckSum(pData,ulSize); + p->header.packet_size = ulSize; + p->header.packet_header_chksum = 0; + ulCheckSum = (ULONG)CheckSum((PUCHAR)p,sizeof(SERIAL_PACKET_HEADER)); + p->header.packet_header_chksum = ulCheckSum; + // attach data to packet + PICE_memcpy(p->data,pData,ulSize); + + return p; +} + + +// OUTPUT handlers + +//************************************************************************* +// SetForegroundColorVga() +// +//************************************************************************* +void SetForegroundColorSerial(ECOLORS col) +{ + eForegroundColor = col; +} + +//************************************************************************* +// SetBackgroundColorVga() +// +//************************************************************************* +void SetBackgroundColorSerial(ECOLORS col) +{ + eBackgroundColor = col; +} + + +//************************************************************************* +// PrintGrafSerial() +// +//************************************************************************* +void PrintGrafSerial(ULONG x,ULONG y,UCHAR c) +{ + // put this into memory + pScreenBufferSerial[y*GLOBAL_SCREEN_WIDTH + x] = c; + + // put this into cache + if(ulFlushBufferPos == 0) + { + g_x = x; + g_y = y; + } + + flush_buffer[ulFlushBufferPos++] = c; +} + +//************************************************************************* +// FlushSerial() +// +//************************************************************************* +void FlushSerial(void) +{ + PSERIAL_DATA_PACKET_PRINT pPrint; + PSERIAL_PACKET p; + + pPrint = (PSERIAL_DATA_PACKET_PRINT)packet; + pPrint->type = PACKET_TYPE_PRINT; + pPrint->x = g_x; + pPrint->y = g_y; + pPrint->fgcol = eForegroundColor; + pPrint->bkcol = eBackgroundColor; + flush_buffer[ulFlushBufferPos++] = 0; + PICE_strcpy(pPrint->string,flush_buffer); + ulFlushBufferPos = 0; + + p = AssemblePacket((PUCHAR)pPrint,sizeof(SERIAL_DATA_PACKET_PRINT)+PICE_strlen(flush_buffer)); + SendPacket(p); +} + +//************************************************************************* +// ShowCursorSerial() +// +// show hardware cursor +//************************************************************************* +void ShowCursorSerial(void) +{ + PSERIAL_DATA_PACKET_CURSOR pCursor; + PSERIAL_PACKET p; + + ENTER_FUNC(); + + bCursorEnabled = TRUE; + + pCursor = (PSERIAL_DATA_PACKET_CURSOR)packet; + pCursor->type = PACKET_TYPE_CURSOR; + pCursor->state = (UCHAR)TRUE; + pCursor->x = (UCHAR)wWindow[OUTPUT_WINDOW].usCurX; + pCursor->y = (UCHAR)wWindow[OUTPUT_WINDOW].usCurY; + + p = AssemblePacket((PUCHAR)pCursor,sizeof(SERIAL_DATA_PACKET_CURSOR)); + SendPacket(p); + + LEAVE_FUNC(); +} + +//************************************************************************* +// HideCursorSerial() +// +// hide hardware cursor +//************************************************************************* +void HideCursorSerial(void) +{ + PSERIAL_DATA_PACKET_CURSOR pCursor; + PSERIAL_PACKET p; + + ENTER_FUNC(); + + bCursorEnabled = FALSE; + + pCursor = (PSERIAL_DATA_PACKET_CURSOR)packet; + pCursor->type = PACKET_TYPE_CURSOR; + pCursor->state = (UCHAR)TRUE; + + p = AssemblePacket((PUCHAR)pCursor,sizeof(SERIAL_DATA_PACKET_CURSOR)); + SendPacket(p); + + LEAVE_FUNC(); +} + +//************************************************************************* +// CopyLineToSerial() +// +// copy a line from src to dest +//************************************************************************* +void CopyLineToSerial(USHORT dest,USHORT src) +{ + NOT_IMPLEMENTED(); +} + +//************************************************************************* +// InvertLineSerial() +// +// invert a line on the screen +//************************************************************************* +void InvertLineSerial(ULONG line) +{ + PSERIAL_DATA_PACKET_INVERTLINE pInvertLine; + PSERIAL_PACKET p; + + pInvertLine = (PSERIAL_DATA_PACKET_INVERTLINE)packet; + pInvertLine->type = PACKET_TYPE_INVERTLINE; + pInvertLine->line = line; + + p = AssemblePacket((PUCHAR)pInvertLine,sizeof(SERIAL_DATA_PACKET_INVERTLINE)); + SendPacket(p); +} + +//************************************************************************* +// HatchLineSerial() +// +// hatches a line on the screen +//************************************************************************* +void HatchLineSerial(ULONG line) +{ + NOT_IMPLEMENTED(); +} + +//************************************************************************* +// ClrLineSerial() +// +// clear a line on the screen +//************************************************************************* +void ClrLineSerial(ULONG line) +{ + PSERIAL_DATA_PACKET_CLRLINE pClrLine; + PSERIAL_PACKET p; + + pClrLine = (PSERIAL_DATA_PACKET_CLRLINE)packet; + pClrLine->type = PACKET_TYPE_CLRLINE; + pClrLine->fgcol = eForegroundColor; + pClrLine->bkcol = eBackgroundColor; + pClrLine->line = line; + + p = AssemblePacket((PUCHAR)pClrLine,sizeof(SERIAL_DATA_PACKET_CLRLINE)); + SendPacket(p); +} + +//************************************************************************* +// PrintLogoSerial() +// +//************************************************************************* +void PrintLogoSerial(BOOLEAN bShow) +{ + NOT_IMPLEMENTED(); +} + +//************************************************************************* +// PrintCursorSerial() +// +// emulate a blinking cursor block +//************************************************************************* +void PrintCursorSerial(BOOLEAN bForce) +{ + NOT_IMPLEMENTED(); +} + +//************************************************************************* +// SaveGraphicsStateSerial() +// +//************************************************************************* +void SaveGraphicsStateSerial(void) +{ + // not implemented +} + +//************************************************************************* +// RestoreGraphicsStateSerial() +// +//************************************************************************* +void RestoreGraphicsStateSerial(void) +{ + // not implemented +} + +// INPUT handlers +//************************************************************************* +// GetKeyPolledSerial() +// +//************************************************************************* +UCHAR GetKeyPolledSerial(void) +{ + UCHAR ucResult; + PSERIAL_DATA_PACKET_POLL pPoll; + PSERIAL_PACKET p; + + pPoll = (PSERIAL_DATA_PACKET_POLL)packet; + pPoll->type = PACKET_TYPE_POLL; + pPoll->major_version = PICE_MAJOR_VERSION; + pPoll->minor_version = PICE_MINOR_VERSION; + pPoll->build_number = PICE_BUILD; + + p = AssemblePacket((PUCHAR)pPoll,sizeof(SERIAL_DATA_PACKET_POLL)); + SendPacket(p); + + ucResult = ucLastKeyRead; + + ucLastKeyRead = 0; + + return ucResult; +} + +//************************************************************************* +// FlushKeyboardQueueSerial() +// +//************************************************************************* +void FlushKeyboardQueueSerial(void) +{ + // not implemented +} + +//************************************************************************* +// Connect() +// +//************************************************************************* +BOOLEAN Connect(USHORT xSize,USHORT ySize) +{ + PSERIAL_DATA_PACKET_CONNECT pConnect; + PSERIAL_PACKET p; + + pConnect = (PSERIAL_DATA_PACKET_CONNECT)packet; + pConnect->type = PACKET_TYPE_CONNECT; + pConnect->xsize = xSize; + pConnect->ysize = ySize; + + p = AssemblePacket((PUCHAR)pConnect,sizeof(SERIAL_DATA_PACKET_CONNECT)); + return SendPacketTimeout(p); +} + +//************************************************************************* +// ConsoleInitSerial() +// +// init terminal screen +//************************************************************************* +BOOLEAN ConsoleInitSerial(void) +{ + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + + ohandlers.CopyLineTo = CopyLineToSerial; + ohandlers.PrintGraf = PrintGrafSerial; + ohandlers.Flush = FlushSerial; + ohandlers.ClrLine = ClrLineSerial; + ohandlers.InvertLine = InvertLineSerial; + ohandlers.HatchLine = HatchLineSerial; + ohandlers.PrintLogo = PrintLogoSerial; + ohandlers.PrintCursor = PrintCursorSerial; + ohandlers.SaveGraphicsState = SaveGraphicsStateSerial; + ohandlers.RestoreGraphicsState = RestoreGraphicsStateSerial; + ohandlers.ShowCursor = ShowCursorSerial; + ohandlers.HideCursor = HideCursorSerial; + ohandlers.SetForegroundColor = SetForegroundColorSerial; + ohandlers.SetBackgroundColor = SetBackgroundColorSerial; + + ihandlers.GetKeyPolled = GetKeyPolledSerial; + ihandlers.FlushKeyboardQueue = FlushKeyboardQueueSerial; + + SetWindowGeometry(wWindowSerial); + + GLOBAL_SCREEN_WIDTH = 80; + GLOBAL_SCREEN_HEIGHT = 60; + + pScreenBufferSerial = PICE_malloc(FRAMEBUFFER_SIZE, NONPAGEDPOOL); + + if(pScreenBufferSerial) + { + bResult = TRUE; + + EmptyRingBuffer(); + + SetupSerial(1,115200); + + // connect to terminal, if none's there, we give up + bResult = Connect(GLOBAL_SCREEN_WIDTH,GLOBAL_SCREEN_HEIGHT); + + if(bResult) + { + GetKeyPolledSerial(); + } + } + + LEAVE_FUNC(); + + return bResult; +} + + +//************************************************************************* +// ConsoleShutdownSerial() +// +// exit terminal screen +//************************************************************************* +void ConsoleShutdownSerial(void) +{ + ENTER_FUNC(); + + Connect(80,25); + + FlushSerialBuffer(); + + if(pScreenBufferSerial) + PICE_free(pScreenBufferSerial); + + LEAVE_FUNC(); +} + + + diff --git a/apps/utils/pice/module/serial.h b/apps/utils/pice/module/serial.h new file mode 100644 index 0000000..b77bf98 --- /dev/null +++ b/apps/utils/pice/module/serial.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + serial.h + +Abstract: + + HEADER for serial.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void SendString(LPSTR s); +void SetupSerial(ULONG port,ULONG baudrate); + +BOOLEAN ConsoleInitSerial(void); +void ConsoleShutdownSerial(void); + diff --git a/apps/utils/pice/module/serial_port.h b/apps/utils/pice/module/serial_port.h new file mode 100644 index 0000000..83c367e --- /dev/null +++ b/apps/utils/pice/module/serial_port.h @@ -0,0 +1,173 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + serial_port.h + +Abstract: + + HEADER for serial.c + + serial port HW defines + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#define COM1 1 +#define COM2 2 +#define COM1BASE 0x3F8 /* Base port address for COM1 */ +#define COM2BASE 0x2F8 /* Base port address for COM2 */ + +// FIX these +#define COM3BASE 0x3F8 /* Base port address for COM3 */ +#define COM4BASE 0x2F8 /* Base port address for COM4 */ + +/* + The 8250 UART has 10 registers accessible through 7 port addresses. + Here are their addresses relative to COM1BASE and COM2BASE. Note + that the baud rate registers, (DLL) and (DLH) are active only when + the Divisor-Latch Access-Bit (DLAB) is on. The (DLAB) is bit 7 of + the (LCR). + + o TXR Output data to the serial port. + o RXR Input data from the serial port. + o LCR Initialize the serial port. + o IER Controls interrupt generation. + o IIR Identifies interrupts. + o MCR Send contorl signals to the modem. + o LSR Monitor the status of the serial port. + o MSR Receive status of the modem. + o DLL Low byte of baud rate divisor. + o DHH High byte of baud rate divisor. +*/ +#define TXR 0 /* Transmit register (WRITE) */ +#define RXR 0 /* Receive register (READ) */ +#define IER 1 /* Interrupt Enable */ +#define IIR 2 /* Interrupt ID */ +#define FCR 2 /* FIFO control */ +#define LCR 3 /* Line control */ +#define MCR 4 /* Modem control */ +#define LSR 5 /* Line Status */ +#define MSR 6 /* Modem Status */ +#define DLL 0 /* Divisor Latch Low */ +#define DLH 1 /* Divisor latch High */ + + +/*-------------------------------------------------------------------* + Bit values held in the Line Control Register (LCR). + bit meaning + --- ------- + 0-1 00=5 bits, 01=6 bits, 10=7 bits, 11=8 bits. + 2 Stop bits. + 3 0=parity off, 1=parity on. + 4 0=parity odd, 1=parity even. + 5 Sticky parity. + 6 Set break. + 7 Toggle port addresses. + *-------------------------------------------------------------------*/ +#define NO_PARITY 0x00 +#define EVEN_PARITY 0x18 +#define ODD_PARITY 0x08 + + + +/*-------------------------------------------------------------------* + Bit values held in the Line Status Register (LSR). + bit meaning + --- ------- + 0 Data ready. + 1 Overrun error - Data register overwritten. + 2 Parity error - bad transmission. + 3 Framing error - No stop bit was found. + 4 Break detect - End to transmission requested. + 5 Transmitter holding register is empty. + 6 Transmitter shift register is empty. + 7 Time out - off line. + *-------------------------------------------------------------------*/ +#define RCVRDY 0x01 +#define OVRERR 0x02 +#define PRTYERR 0x04 +#define FRMERR 0x08 +#define BRKERR 0x10 +#define XMTRDY 0x20 +#define XMTRSR 0x40 +#define TIMEOUT 0x80 + +/*-------------------------------------------------------------------* + Bit values held in the Modem Output Control Register (MCR). + bit meaning + --- ------- + 0 Data Terminal Ready. Computer ready to go. + 1 Request To Send. Computer wants to send data. + 2 auxillary output #1. + 3 auxillary output #2.(Note: This bit must be + set to allow the communications card to send + interrupts to the system) + 4 UART ouput looped back as input. + 5-7 not used. + *------------------------------------------------------------------*/ +#define DTR 0x01 +#define RTS 0x02 + + +/*------------------------------------------------------------------* + Bit values held in the Modem Input Status Register (MSR). + bit meaning + --- ------- + 0 delta Clear To Send. + 1 delta Data Set Ready. + 2 delta Ring Indicator. + 3 delta Data Carrier Detect. + 4 Clear To Send. + 5 Data Set Ready. + 6 Ring Indicator. + 7 Data Carrier Detect. + *------------------------------------------------------------------*/ +#define CTS 0x10 +#define DSR 0x20 + + +/*------------------------------------------------------------------* + Bit values held in the Interrupt Enable Register (IER). + bit meaning + --- ------- + 0 Interrupt when data received. + 1 Interrupt when transmitter holding reg. empty. + 2 Interrupt when data reception error. + 3 Interrupt when change in modem status register. + 4-7 Not used. + *------------------------------------------------------------------*/ +#define RX_INT 0x01 + + +/*------------------------------------------------------------------* + Bit values held in the Interrupt Identification Register (IIR). + bit meaning + --- ------- + 0 Interrupt pending + 1-2 Interrupt ID code + 00=Change in modem status register, + 01=Transmitter holding register empty, + 10=Data received, + 11=reception error, or break encountered. + 3-7 Not used. + *------------------------------------------------------------------*/ +#define RX_ID 0x04 +#define RX_MASK 0x07 diff --git a/apps/utils/pice/module/shell.c b/apps/utils/pice/module/shell.c new file mode 100644 index 0000000..555ef2d --- /dev/null +++ b/apps/utils/pice/module/shell.c @@ -0,0 +1,1692 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + shell.c + +Abstract: + + user interface for debugger + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 16-Jul-1998: created + 22-Sep-1998: rewrite of keyboard hooking through patching the original keyboard driver + 29-Sep-1998: started documentation on project + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + + +//////////////////////////////////////////////////// +// DEFINES +//// +#define LINES_IN_COMMAND_BUFFER (64) + +//////////////////////////////////////////////////// +// PROTOTYPES +//// + +//////////////////////////////////////////////////// +// GLOBALS +//// + +ULONG bPreviousCommandWasGo = FALSE; + +// flags to set when we need to pass things to the old INT handlers +ULONG dwCallOldInt1Handler = 0; +ULONG dwCallOldInt3Handler = 0; +ULONG dwCallOldIntEHandler = 0; +ULONG dwCallOldGPFaultHandler = 0; + +ULONG g_ulLineNumberStart=0; +ULONG ulWindowOffset = 0; +BOOLEAN bStepThroughSource=FALSE; +BOOLEAN bStepInto = FALSE; + +// key handling +UCHAR ucConverted; // key converted from scancode to ANSI + +volatile BOOLEAN bControl=FALSE; // TRUE when CTRL key was pressed +volatile BOOLEAN bShift=FALSE; // TRUE when SHIFT key was pressed +volatile BOOLEAN bAlt=FALSE; // TRUE when ALT key was pressed +volatile ULONG OldInt31Handler; // address of old keyboard ISR +volatile ULONG OldGlobalInt31Handler; // address of old global keyboard ISR +volatile BOOLEAN bEnterNow=FALSE; // TRUE if already stopped +volatile BOOLEAN bNotifyToExit=FALSE; // TRUE when debugger should leave +volatile BOOLEAN bSkipMainLoop=FALSE; // TRUE when debugger should skip main loop +volatile UCHAR ucKeyPressedWhileIdle=0; // key pressed when system was stopped +volatile BOOLEAN bInDebuggerShell=FALSE; // TRUE while in DebuggerShell() +BOOLEAN bIrqStateAtBreak; + +ULONG ulRealStackPtr; +static ULONG PCR_SEL = PCR_SELECTOR; +static ULONG OLD_PCR; + +char tempShell[256]; // temporary string container + +// old address of display memory +USHORT OldSelector=0; +ULONG OldOffset=0; + +ULONG ulLastLineDisplayedOffset = 0; + +// functions of function keys +char *szFunctionKeys[10]={ + "mod", // F1 + "proc", // F2 + "src", // F3 + "code", // F4 + "x", // F5 + "vma", // F6 + "", // F7 + "t", // F8 + "", // F9 + "p" // F10 +}; + +// new stack for "deep parsing" +ULONG aulNewStack[0x20000]; +ULONG ulOldStack; + +// registers save area (context) +ULONG CurrentEIP,CurrentEFL; +ULONG CurrentEAX,CurrentEBX,CurrentECX,CurrentEDX; +ULONG CurrentESP,CurrentEBP,CurrentESI,CurrentEDI; +USHORT CurrentCS,CurrentDS=0,CurrentES,CurrentFS,CurrentGS,CurrentSS; +ULONG CurrentDR0,CurrentDR1,CurrentDR2,CurrentDR3,CurrentDR6,CurrentDR7; +ULONG CurrentCR0,CurrentCR2,CurrentCR3; +// previous context +ULONG OldEIP=0,OldEFL; +ULONG OldEAX,OldEBX,OldECX,OldEDX; +ULONG OldESP,OldEBP,OldESI,OldEDI; +USHORT OldCS=0,OldDS,OldES,OldFS,OldGS,OldSS; + +ULONG CurrentProcess; + +UCHAR ucCommandBuffer[256]; +USHORT usCurrentPosInInputBuffer=0; +volatile BOOLEAN bSingleStep=FALSE; + +// the last command lines +char aszCommandLines[LINES_IN_COMMAND_BUFFER][sizeof(ucCommandBuffer)+2]; +ULONG ulCommandInPos=0,ulCommandLastPos=0; +ULONG ulCommandCurrentPos=0; + + +extern ULONG KeyboardIRQL; + +//************************************************************************* +// GetLinesInCommandHistory() +// +//************************************************************************* +ULONG GetLinesInCommandHistory(void) +{ + ULONG ulResult = (ulCommandInPos-ulCommandLastPos)%LINES_IN_COMMAND_BUFFER; + + ENTER_FUNC(); + + DPRINT((0,"GetLinesInCommandHistory() returns %u (ulIn %u ulLast %u)\n",ulResult,ulCommandInPos,ulCommandLastPos)); + + LEAVE_FUNC(); + + return ulResult; +} + +//************************************************************************* +// AddToCommandLineHistory() +// +//************************************************************************* +void AddToCommandLineHistory(LPSTR s) +{ + ULONG i; + + ENTER_FUNC(); + DPRINT((0,"AddToCommandLineHistory(%s)\n",s)); + + if(PICE_strlen(s)) + { + for(i=0;iImageFileName; + if(IsAddressValid((ULONG)pProcessName) ) + { + PICE_sprintf(tempShell, + " PROCESS(%.8X \"%s\") ", + (ULONG)pCurrentProcess,pProcessName); + } + else + { + PICE_sprintf(tempShell, + " PROCESS(%.8X) ", + (ULONG)pCurrentProcess); + } + PutChar(tempShell,1,wWindow[OUTPUT_WINDOW].y-1); + + ResetColor(); + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// ProcessBootParams() +// +//************************************************************************* +void ProcessBootParams(void) +{ + LPSTR p1,p2; + + ENTER_FUNC(); + if(*szBootParams) + { + DPRINT((0,"ProcessBootParams()\n")); + + p1 = szBootParams; + + while(*p1) + { + p2 = ucCommandBuffer; + DPRINT((0,"ProcessBootParams(): boot params = %s\n",p1)); + while(*p1 && *p1!=';') + { + *p2++ = *p1++; + } + *p2=0; + DPRINT((0,"ProcessBootParams(): cmd buf = %s\n",ucCommandBuffer)); + if(*p1 != ';') + { + DPRINT((0,"ProcessBootParams(): error in cmd buf\n")); + break; + } + p1++; + DPRINT((0,"ProcessBootParams(): next cmd buf = %s\n",p1)); + + Parse(ucCommandBuffer,TRUE); + } + PICE_memset(ucCommandBuffer,0,sizeof(ucCommandBuffer)); + *szBootParams = 0; + } + LEAVE_FUNC(); +} + +//************************************************************************* +// bNoCtrlKeys() +// +//************************************************************************* +BOOLEAN inline bNoCtrlKeys(void) +{ + return (!bControl && !bAlt && !bShift); +} + + +//************************************************************************* +// DebuggerShell() +// +// handle user interface when stopped system +//************************************************************************* +void DebuggerShell(void) +{ + ARGS Args; + UCHAR speaker; + PEPROCESS pCurrentProcess; + + ENTER_FUNC(); + + // save the graphics state + SaveGraphicsState(); + + // tell USER we are stopped + ShowStoppedMsg(); + + FlushKeyboardQueue(); + + CheckRingBuffer(); + + // kill the speakers annoying beep + speaker = inb_p((PCHAR)0x61); + speaker &= 0xFC; + outb_p(speaker,(PCHAR)0x61); + + ProcessBootParams(); + + DPRINT((0,"DebuggerShell(): DisplayRegs()\n")); + // display register contents + DisplayRegs(); + + DPRINT((0,"DebuggerShell(): DisplayMemory()\n")); + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + + DPRINT((0,"DebuggerShell(): Unassemble()\n")); + + // disassembly from current address + PICE_memset(&Args,0,sizeof(ARGS)); + Args.Value[0]=CurrentCS; + Args.Value[1]=CurrentEIP; + Args.Count=2; + Unassemble(&Args); + + // try to find current process's name + pCurrentProcess = IoGetCurrentProcess(); + CurrentProcess = (ULONG)pCurrentProcess; + + // display status line + ShowStatusLine(); + + // switch on cursor + ShowCursor(); + + // while we are not told to exit + while(bNotifyToExit==FALSE) + { + // emulate graphics cursor + PrintCursor(FALSE); + + // we have a key press + if((ucKeyPressedWhileIdle = GetKeyPolled())!=0) + { + DPRINT((0,"DebuggerShell(): key = %x control = %u shift = %u\n",ucKeyPressedWhileIdle,bControl,bShift)); + + // if cursor reversed, normalize it again (only graphics) + if(bRev) + { + PrintCursor(TRUE); + } + + // convert key to ANSI, if success add to command buffer and try to + // find a command that fits the already entered letters + ucConverted = AsciiFromScan((UCHAR)(ucKeyPressedWhileIdle&0x7f)); + +#if 0 + PICE_sprintf(tempShell,"%u -> %u",ucKeyPressedWhileIdle, ucConverted); + PutChar(tempShell,GLOBAL_SCREEN_WIDTH-32,wWindow[OUTPUT_WINDOW].y-1); +#endif + + if(!bControl && !bAlt && ucConverted) + { + DPRINT((0,"DebuggerShell(): normal key\n")); + if(!(usCurrentPosInInputBuffer==0 && ucConverted==' ')) + { + // if we have space in the command buffer + // put the character there + if(usCurrentPosInInputBuffer=59 && ucKeyPressedWhileIdle<69) + { + DPRINT((0,"DebuggerShell(): FUNCTION %u\n",ucKeyPressedWhileIdle-59)); + PICE_sprintf(tempShell,":"); + ReplaceRingBufferCurrent(tempShell); + PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer)); + usCurrentPosInInputBuffer=0; + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + PICE_strcpy(ucCommandBuffer,szFunctionKeys[ucKeyPressedWhileIdle-59]); + usCurrentPosInInputBuffer=PICE_strlen(ucCommandBuffer); + if(ucCommandBuffer[0]) + { + ulLastLineDisplayedOffset = 0; + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + + // setup a safe stack for parsing + __asm__ __volatile__("\n\t \ + movl %2,%%eax\n\t \ + movl %%esp,%%ebx\n\t \ + mov %%ebx,%0\n\t \ + leal _aulNewStack,%%ebx\n\t \ + addl $0x1FFF0,%%ebx\n\t \ + movl %%ebx,%%esp\n\t \ + pushl $1\n\t \ + pushl %%eax\n\t \ + call _Parse\n\t \ + movl %0,%%ebx\n\t \ + movl %%ebx,%%esp" + :"=m" (ulOldStack) + :"m" (ulOldStack),"m" (ucCommandBuffer) + :"eax","ebx"); + PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer)); + usCurrentPosInInputBuffer=0; + } + } + else + { + switch(ucKeyPressedWhileIdle) + { + case SCANCODE_ESC: + if(usCurrentPosInInputBuffer) + { + PICE_sprintf(tempShell,":"); + ReplaceRingBufferCurrent(tempShell); + PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer)); + usCurrentPosInInputBuffer=0; + Print(OUTPUT_WINDOW,""); + ShowStoppedMsg(); + } + break; + case SCANCODE_HOME: // home + DPRINT((0,"DebuggerShell(): HOME\n")); + // memory window + if(bAlt) + { + DPRINT((0,"DebuggerShell(): data window home\n")); + OldOffset=0x0; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + // output window + else if(bShift) + { + DPRINT((0,"DebuggerShell(): output window home\n")); + if(ulLastLineDisplayedOffset != LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy) + { + ulLastLineDisplayedOffset = LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy+1; + PrintRingBufferHome(wWindow[OUTPUT_WINDOW].cy-1); + } + } + // source window home + else if(bControl) + { + if(ulCurrentlyDisplayedLineNumber>0) + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber = 1; + + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + 1,-1); + } + } + } + else if(!bShift && !bControl && !bAlt) + { + } + break; + case SCANCODE_END: // end + DPRINT((0,"DebuggerShell(): END\n")); + // memory window + if(bAlt) + { + DPRINT((0,"DebuggerShell(): data window end\n")); + OldOffset=0xFFFFFFFF-0x10*4; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + // output window + else if(bShift) + { + DPRINT((0,"DebuggerShell(): output window end\n")); + if(ulLastLineDisplayedOffset) + { + ulLastLineDisplayedOffset = 0; + + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + } + } + else if(!bShift && !bControl && !bAlt) + { + } + break; + case SCANCODE_UP: // up + DPRINT((0,"DebuggerShell(): UP\n")); + // memory window + if(bAlt) + { + DPRINT((0,"DebuggerShell(): data window up\n")); + OldOffset-=0x10; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + // output window + else if(bShift) + { + DPRINT((0,"DebuggerShell(): output window up ulLastLineDisplayedOffset = %u\n",ulLastLineDisplayedOffset)); + + if(ulLastLineDisplayedOffset+wWindow[OUTPUT_WINDOW].cy < LinesInRingBuffer()) + { + ulLastLineDisplayedOffset += 1; + + PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset); + } + } + // source window up + else if(bControl) + { + if((ulCurrentlyDisplayedLineNumber-1)>0 && PICE_strlen(szCurrentFile) ) + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber--; + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + ulCurrentlyDisplayedLineNumber,-1); + } + } + else + { + UnassembleOneLineUp(); + } + } + // command line history + else if(!bShift && !bControl && !bAlt) + { + LPSTR pCurrentCmd; + ULONG len; + + DPRINT((0,"DebuggerShell(): command line up\n")); + + // only if anything in history + if(GetLinesInCommandHistory()) + { + // go to next entry in history + if(ulCommandCurrentPos) + ulCommandCurrentPos = (ulCommandCurrentPos-1)%GetLinesInCommandHistory(); + else + ulCommandCurrentPos = GetLinesInCommandHistory()-1; + DPRINT((0,"DebuggerShell(): current history pos = %u\n",ulCommandCurrentPos)); + // get this entry + pCurrentCmd = GetFromCommandLineHistory(ulCommandCurrentPos); + // if it has a string attached + if((len = PICE_strlen(pCurrentCmd))) + { + // replace the current command line + PICE_sprintf(tempShell,":"); + ReplaceRingBufferCurrent(tempShell); + PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer)); + PICE_strcpy(ucCommandBuffer,pCurrentCmd); + usCurrentPosInInputBuffer=len; + Print(OUTPUT_WINDOW,pCurrentCmd); + } + } + } + break; + case SCANCODE_DOWN: // down + DPRINT((0,"DebuggerShell(): DOWN\n")); + // memory window + if(bAlt) + { + DPRINT((0,"DebuggerShell(): data window down\n")); + OldOffset+=0x10; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + // output window + else if(bShift) + { + DPRINT((0,"DebuggerShell(): output window down ulLastLineDisplayedOffset = %u\n",ulLastLineDisplayedOffset)); + if(ulLastLineDisplayedOffset) + { + ulLastLineDisplayedOffset -= 1; + + if(!PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset)) + { + ulLastLineDisplayedOffset = 0; + PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); + } + } + } + // source window down + else if(bControl) + { + if(ulCurrentlyDisplayedLineNumber>0 && PICE_strlen(szCurrentFile)) + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber++; + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + ulCurrentlyDisplayedLineNumber,-1); + } + } + else + { + UnassembleOneLineDown(); + } + } + // command line history + else if(!bShift && !bControl && !bAlt) + { + LPSTR pCurrentCmd; + ULONG len; + + DPRINT((0,"DebuggerShell(): command line down\n")); + + // only if anything in history + if(GetLinesInCommandHistory()) + { + // go to next entry in history + ulCommandCurrentPos = (ulCommandCurrentPos+1)%(GetLinesInCommandHistory()); + DPRINT((0,"DebuggerShell(): current history pos = %u\n",ulCommandCurrentPos)); + // get this entry + pCurrentCmd = GetFromCommandLineHistory(ulCommandCurrentPos); + // if it has a string attached + if((len = PICE_strlen(pCurrentCmd))) + { + // replace the current command line + PICE_sprintf(tempShell,":"); + ReplaceRingBufferCurrent(tempShell); + PICE_memset(&ucCommandBuffer,0,sizeof(ucCommandBuffer)); + PICE_strcpy(ucCommandBuffer,pCurrentCmd); + usCurrentPosInInputBuffer=len; + Print(OUTPUT_WINDOW,pCurrentCmd); + } + } + } + break; + case SCANCODE_LEFT: // left + DPRINT((0,"DebuggerShell(): LEFT\n")); + // memory window + if(bAlt) + { + DPRINT((0,"DebuggerShell(): data window left\n")); + + OldOffset-=0x1; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + else if(!bShift && !bControl && !bAlt) + { + } + else if(bControl) + { + if(ulWindowOffset > 0) + ulWindowOffset--; + PICE_memset(&Args,0,sizeof(ARGS)); + Args.Count=0; + Unassemble(&Args); + } + break; + case SCANCODE_RIGHT: // right + // memory window + if(bAlt) + { + DPRINT((0,"DebuggerShell(): data window right\n")); + + OldOffset+=0x1; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + else if(!bShift && !bControl && !bAlt) + { + } + else if(bControl) + { + if(ulWindowOffset < 80) + ulWindowOffset++; + PICE_memset(&Args,0,sizeof(ARGS)); + Args.Count=0; + Unassemble(&Args); + } + break; + case SCANCODE_PGUP: // page up + DPRINT((0,"DebuggerShell(): PAGEUP\n")); + // memory window + if(bAlt) + { + OldOffset-=wWindow[DATA_WINDOW].cy*0x10; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + // output window + else if(bShift) + { + if(ulLastLineDisplayedOffset+2*(wWindow[OUTPUT_WINDOW].cy) < LinesInRingBuffer()) + { + ulLastLineDisplayedOffset += (wWindow[OUTPUT_WINDOW].cy); + + PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset); + } + else + { + if(ulLastLineDisplayedOffset != LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy) + { + ulLastLineDisplayedOffset = LinesInRingBuffer()-wWindow[OUTPUT_WINDOW].cy; + PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset); + } + } + } + // source window page up + else if(bControl) + { + if(PICE_strlen(szCurrentFile)) + { + if((ulCurrentlyDisplayedLineNumber-wWindow[SOURCE_WINDOW].cy)>0) + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber -= wWindow[SOURCE_WINDOW].cy; + + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + ulCurrentlyDisplayedLineNumber ,-1); + } + } + else + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber = 1; + + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + ulCurrentlyDisplayedLineNumber ,-1); + } + } + } + else + { + UnassembleOnePageUp(wWindow[SOURCE_WINDOW].cy); + } + + } + else if(!bShift && !bControl && !bAlt) + { + } + break; + case SCANCODE_PGDN: // page down + DPRINT((0,"DebuggerShell(): PAGEDOWN\n")); + // memory window + if(bAlt) + { + OldOffset+=wWindow[DATA_WINDOW].cy*0x10; + // display data window + Args.Value[0]=OldSelector; + Args.Value[1]=OldOffset; + Args.Count=2; + DisplayMemory(&Args); + } + else if(bShift) + { + if(ulLastLineDisplayedOffset>wWindow[OUTPUT_WINDOW].cy) + { + ulLastLineDisplayedOffset -= (wWindow[OUTPUT_WINDOW].cy); + + PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset); + } + else + { + if(ulLastLineDisplayedOffset) + { + ulLastLineDisplayedOffset = 0; + PrintRingBufferOffset(wWindow[OUTPUT_WINDOW].cy-1,ulLastLineDisplayedOffset); + } + } + } + else if(bControl) + { + if(PICE_strlen(szCurrentFile) ) + { + if((ulCurrentlyDisplayedLineNumber+wWindow[SOURCE_WINDOW].cy)>0) + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber += wWindow[SOURCE_WINDOW].cy; + + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + ulCurrentlyDisplayedLineNumber ,-1); + } + } + else + { + PICE_SYMBOLFILE_SOURCE* pSrc; + + if(ConvertTokenToSrcFile(szCurrentFile,(PULONG)&pSrc) ) + { + ulCurrentlyDisplayedLineNumber = 1; + + DisplaySourceFile((LPSTR)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE), + (LPSTR)pSrc+pSrc->ulOffsetToNext, + ulCurrentlyDisplayedLineNumber ,-1); + } + } + } + else + { + UnassembleOnePageDown(wWindow[SOURCE_WINDOW].cy); + } + } + else if(!bShift && !bControl && !bAlt) + { + } + break; + } + } + } + } + ucKeyPressedWhileIdle=0; + } + } + + SaveOldRegs(); + + PrintLogo(TRUE); + + ShowRunningMsg(); + + if(bRev) + PrintCursor(TRUE); + + // hide the cursor + HideCursor(); + + FlushKeyboardQueue(); + + RestoreGraphicsState(); + + LEAVE_FUNC(); +} + +//************************************************************************* +// RealIsr() +// +//************************************************************************* +void RealIsr(ULONG dwReasonForBreak) +{ + BOOLEAN ReinstallPermanentBp = FALSE; + + DPRINT((0,"reason: %u#################################################################\n", dwReasonForBreak)); + ENTER_FUNC(); + + // in handler + bInDebuggerShell = TRUE; + + bStepping = FALSE; + + // don't assume we must call original handlers yet + dwCallOldInt1Handler = dwCallOldInt3Handler = dwCallOldIntEHandler = dwCallOldGPFaultHandler = 0; + bSkipMainLoop = FALSE; + bEnterNow = FALSE; + + // reset trace flag (TF) on the stack + CurrentEFL&=(~0x100); + + InstallPrintkHook(); + + // control is not depressed + bControl=FALSE; + + bIrqStateAtBreak = ((CurrentEFL&(1<<9))!=0); + + DPRINT((0,"\nbInDebuggerShell %x, dwReasonForBreak: %x, bIrqStateAtBreak: %d\n", bInDebuggerShell, dwReasonForBreak, bIrqStateAtBreak)); + DPRINT((0,"CurrentEIP: %x, CurrentESP: %x\n", CurrentEIP, CurrentESP)); + + // came in because TF flag was set + if(dwReasonForBreak == REASON_SINGLESTEP) + { + ULONG ulAddress,ulAddressCurrent; + + DPRINT((0,"REASON_SINGLESTEP: bSingleStep: %u\n", bSingleStep)); + + if(!bSingleStep) + { + dwCallOldInt1Handler = 1; + DPRINT((0,"no single step requested: %u!\n", dwCallOldInt1Handler)); + goto common_return_point; + } + + ulAddress = GetLinearAddress(OldCS,OldEIP); + ulAddressCurrent = GetLinearAddress(CurrentCS,CurrentEIP); + + // if we came in because we needed to skip past a permanent + // INT3 hook, we need to put the INT3 back in place and + // simply restart the system. + if(NeedToReInstallSWBreakpoints(ulAddress,TRUE) ) + { + DPRINT((0,"reinstalling INT3 @ %.4X:%.8X\n",OldCS,OldEIP)); + + ReInstallSWBreakpoint(ulAddress); + + // previous command was go i.e. we did not single-step over a location + // where a permanent breakpoint was installed (Printk() etc.) we simply restart + // else we must stop the system. + if(bPreviousCommandWasGo) + { + bPreviousCommandWasGo = FALSE; + bInDebuggerShell = FALSE; + + if(bStepThroughSource) + { + // set TF flag + CurrentEFL |= 0x100; + } + + LEAVE_FUNC(); + DPRINT((0,"singlestep-----------------------------------------------------------------\n")); + return; + } + bPreviousCommandWasGo = FALSE; + } + + if(IsSwBpAtAddressInstalled(ulAddressCurrent)) + DeInstallSWBreakpoint(ulAddressCurrent); + + // we came here while stepping through source code block + if(bStepThroughSource) + { + ULONG ulLineNumber; + LPSTR pSrc,pFileName; + + DPRINT((0,"RealIsr(): stepping through source!\n")); + + // look up the corresponding source line + // if there isn't any or the source line number has changed + // we break back into the debugger + if(bShowSrc) + pSrc = FindSourceLineForAddress(ulAddressCurrent,&ulLineNumber,NULL,NULL,&pFileName); + else pSrc = NULL; + + DPRINT((0,"RealIsr(): line #%u pSrc=%x (old line #%u)\n",ulLineNumber,(ULONG)pSrc,g_ulLineNumberStart)); + + // if we have found a source line there + if(pSrc && ulLineNumber==g_ulLineNumberStart) + { + DPRINT((0,"RealIsr(): stepping through line #%u in file = %s!\n",ulLineNumber,pFileName)); + + if(bStepInto) + StepInto(NULL); + else + StepOver(NULL); + + bInDebuggerShell = FALSE; + LEAVE_FUNC(); + DPRINT((0,"singstep-----------------------------------------------------------------\n")); + return; + } + bStepThroughSource = FALSE; + bNotifyToExit = FALSE; + bSkipMainLoop = FALSE; + } + } + // came in because hardware register triggered a breakpoint + else if(dwReasonForBreak == REASON_HARDWARE_BP) + { + ULONG ulReason; + + DPRINT((0,"REASON_HARDWARE_BP\n")); + + // disable HW breakpoints + __asm__("\n\t \ + movl %%dr6,%%eax\n\t \ + movl %%eax,%0\n\t \ + xorl %%eax,%%eax\n\t \ + movl %%eax,%%dr6\n\t \ + movl %%eax,%%dr7" + :"=m" (ulReason) + : + :"eax" + ); + + DPRINT((0,"REASON_HARDWARE_BP: %x\n",(ulReason&0xF))); + + // HW breakpoint DR1 (skip: only used in init_module detection) + if(ulReason&0x2) + { + CurrentEFL |=(1<<16); // set resume flag + + bSkipMainLoop = TRUE; + + TryToInstallVirtualSWBreakpoints(); + } + // HW breakpoint DR0 + else if(ulReason&0x1) + { + ULONG ulAddressCurrent; + + ulAddressCurrent = GetLinearAddress(CurrentCS,CurrentEIP); + + // we came here while stepping through source code block + if(bStepThroughSource) + { + ULONG ulLineNumber; + LPSTR pSrc,pFileName; + + DPRINT((0,"RealIsr(): stepping through source! [2]\n")); + + // look up the corresponding source line + // if there isn't any or the source line number has changed + // we break back into the debugger + if(bShowSrc) + pSrc = FindSourceLineForAddress(ulAddressCurrent,&ulLineNumber,NULL,NULL,&pFileName); + else + pSrc = NULL; + + DPRINT((0,"RealIsr(): line #%u pSrc=%x (old line #%u) [2]\n",ulLineNumber,(ULONG)pSrc,g_ulLineNumberStart)); + + // if we have found a source line there + if(pSrc && ulLineNumber==g_ulLineNumberStart) + { + DPRINT((0,"RealIsr(): stepping through line #%u in file = %s! [2]\n",ulLineNumber,pFileName)); + + if(bStepInto) + StepInto(NULL); + else + StepOver(NULL); + + bInDebuggerShell = FALSE; + LEAVE_FUNC(); + DPRINT((0,"rrr-----------------------------------------------------------------\n")); + return; + } + bNotifyToExit = FALSE; + bSkipMainLoop = FALSE; + bStepThroughSource = FALSE; + } + } + } + else if(dwReasonForBreak==REASON_INT3) + { + ULONG ulAddress; + + DPRINT((0,"REASON_INT3\n")); + + // must subtract one cause INT3s are generated after instructions execution + CurrentEIP--; + + // make a flat address + ulAddress = GetLinearAddress(CurrentCS,CurrentEIP); + + DPRINT((0,"INT3 @ %.8X\n",ulAddress)); + + // if there's a breakpoint installed at current EIP remove it + if(DeInstallSWBreakpoint(ulAddress) ) + { + PSW_BP p; + + DPRINT((0,"INT3 @ %.8X removed\n",ulAddress)); + + // if it's permanent (must be Printk() ) skip the DebuggerShell() and + // do a callback + if( (p = IsPermanentSWBreakpoint(ulAddress)) ) + { + DPRINT((0,"permanent breakpoint\n")); + + ReinstallPermanentBp = TRUE; + + OldCS = CurrentCS; + OldEIP = CurrentEIP; + + bSkipMainLoop = TRUE; + DPRINT((0,"callback at %x\n",p->Callback)); + if(p->Callback) + p->Callback(); + } + else + { + LPSTR pFind; + if(ScanExportsByAddress(&pFind,GetLinearAddress(CurrentCS,CurrentEIP))) + { + PICE_sprintf(tempShell,"pICE: SW Breakpoint at %s (%.4X:%.8X)\n",pFind,CurrentCS,CurrentEIP); + } + else + { + PICE_sprintf(tempShell,"pICE: SW Breakpoint at %.4X:%.8X\n",CurrentCS,CurrentEIP); + } + Print(OUTPUT_WINDOW,tempShell); + } + CurrentEFL &= ~(1<<16); // clear resume flag + } + else + { + LPSTR pFind; + PEPROCESS my_current = IoGetCurrentProcess(); + + DPRINT((0,"can't deinstall, somebody else's breakpoint\n")); + + + // if no other debugger is running on this process and the address is + // above TASK_SIZE we assume this to be a hard embedded INT3 +/* +#if REAL_LINUX_VERSION_CODE < 0x020400 + if(ulAddressflags & PF_PTRACED) ) +#else + if(ulAddressptrace & PT_PTRACED) ) +#endif +*/ + if( ulAddress ) + { + if(ScanExportsByAddress(&pFind,GetLinearAddress(CurrentCS,CurrentEIP))) + { + PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at %s (%.4X:%.8X)\n",pFind,CurrentCS,CurrentEIP); + } + else + { + PICE_sprintf(tempShell,"pICE: break due to embedded INT 3 at user-mode address %.4X:%.8X\n",CurrentCS,CurrentEIP); + } + Print(OUTPUT_WINDOW,tempShell); + CurrentEFL &= ~(1<<16); // clear resume flag + } + // well someone is already debugging this, we must pass the INT3 on to old handler + // but only when it's a user-mode address +/* + else + { + if(ulAddressring0 transition)\n\t \ + // stack is switched if orig. SS is not global kernel code segment\n\t \ + movl 4*4(%esp),%eax\n\t \ + cmpw $" STR(GLOBAL_CODE_SEGMENT) ",%ax\n\t \ + je notswitched\n\t \ +\n\t \ + // switched stack\n\t \ + movl 6*4(%esp),%eax\n\t \ + mov %eax,_CurrentESP\n\t \ + mov 7*4(%esp),%eax\n\t \ + movzwl %ax,%eax\n\t \ + mov %ax,_CurrentSS\n\t \ + jmp afterswitch\n\t \ +\n\t \ +notswitched:\n\t \ + // didn't switch stack\n\t \ + movl %esp,_CurrentESP\n\t \ + addl $24,_CurrentESP\n\t \ + movw %ss,%ax\n\t \ + movzwl %ax,%eax\n\t \ + mov %ax,_CurrentSS\n\t \ +\n\t \ +afterswitch:\n\t \ + // save EIP\n\t \ + mov 3*4(%esp),%eax\n\t \ + mov %eax,_CurrentEIP\n\t \ + //save CS\n\t \ + mov 4*4(%esp),%eax\n\t \ + movzwl %ax,%eax\n\t \ + movw %ax,_CurrentCS\n\t \ + // save flags\n\t \ + movl 5*4(%esp),%eax\n\t \ + andl $0xFFFFFEFF,%eax\n\t \ + movl %eax,_CurrentEFL\n\t \ +\n\t \ + pushal\n\t \ +\n\t \ + // get reason code\n\t \ + mov 0x28(%esp),%ebx\n\t \ +\n\t \ + /*\n\t \ + * Load the PCR selector.\n\t \ + */\n\t \ +\n\t \ + movl %fs, %eax\n\t \ + movl %eax, _OLD_PCR\n\t \ + movl _PCR_SEL, %eax\n\t \ + movl %eax, %fs\n\t \ +\n\t \ + // setup a large work stack\n\t \ + movl %esp,%eax\n\t \ + movl %eax,_ulRealStackPtr\n\t \ +\n\t \ + pushl %ebx\n\t \ + call _RealIsr\n\t \ + addl $4,%esp\n\t \ +\n\t \ + pushl %eax\n\t \ + movl _OLD_PCR, %eax\n\t \ + movl %eax, %fs\n\t \ + popl %eax\n\t \ +\n\t \ + // restore all regs\n\t \ + popal\n\t \ +\n\t \ + // do an EOI to IRQ controller (because we definitely pressed some key)\n\t \ + // TODO: SMP APIC support\n\t \ + movb $0x20,%al\n\t \ + outb %al,$0x20\n\t \ +\n\t \ + popl %ds\n\t \ + popl %eax\n\t \ +\n\t \ + // remove reason code\n\t \ + addl $4,%esp\n\t \ +\n\t \ + // make EAX available\n\t \ + pushl %eax\n\t \ +\n\t \ + // modify or restore EFLAGS\n\t \ + .byte 0x2e\n\t \ + mov _CurrentEFL,%eax\n\t \ + mov %eax,3*4(%esp)\n\t \ + .byte 0x2e\n\t \ + movzwl _CurrentCS,%eax\n\t \ + mov %eax,2*4(%esp)\n\t \ + .byte 0x2e\n\t \ + mov _CurrentEIP,%eax\n\t \ + mov %eax,1*4(%esp)\n\t \ +\n\t \ + // restore EAX\n\t \ + popl %eax\n\t \ +\n\t \ + // do we need to call old INT1 handler\n\t \ + .byte 0x2e\n\t \ + cmp $0,_dwCallOldInt1Handler\n\t \ + je do_iret2\n\t \ +\n\t \ + // call INT3 handler\n\t \ + .byte 0x2e\n\t \ + jmp *_OldInt1Handler\n\t \ +\n\t \ +do_iret2:\n\t \ + // do we need to call old INT3 handler\n\t \ + .byte 0x2e\n\t \ + cmp $0,_dwCallOldInt3Handler\n\t \ + je do_iret1\n\t \ +\n\t \ + // call INT3 handler\n\t \ + .byte 0x2e\n\t \ + jmp *_OldInt3Handler\n\t \ +\n\t \ +do_iret1:\n\t \ + // do we need to call old pagefault handler\n\t \ + .byte 0x2e\n\t \ + cmp $0,_dwCallOldIntEHandler\n\t \ + je do_iret3\n\t \ +\n\t \ + // call old pagefault handler\n\t \ + .byte 0x2e\n\t \ + pushl _error_code\n\t \ + .byte 0x2e\n\t \ + jmp *_OldIntEHandler\n\t \ +\n\t \ +do_iret3:\n\t \ + // do we need to call old general protection fault handler\n\t \ + .byte 0x2e\n\t \ + cmp $0,_dwCallOldGPFaultHandler\n\t \ + je do_iret\n\t \ +\n\t \ + // call old pagefault handler\n\t \ + .byte 0x2e\n\t \ + pushl _error_code\n\t \ + .byte 0x2e\n\t \ + jmp *_OldGPFaultHandler\n\t \ +\n\t \ +do_iret:\n\t \ + //ei\n\t \ + //int3\n\t \ + iretl "); + +// +// stub for entering via CTRL-F +// +// IDTs keyboard IRQ points here +// +__asm__ ("\n\t \ +NewGlobalInt31Handler:\n\t \ + .byte 0x2e\n\t \ + cmpb $0,_bEnterNow\n\t \ + jne dotheenter\n\t \ +\n\t \ + // chain to old handler\n\t \ + .byte 0x2e\n\t \ + jmp *_OldGlobalInt31Handler\n\t \ +\n\t \ +dotheenter:\n\t \ + pushl $" STR(REASON_CTRLF) "\n\t \ + jmp NewInt31Handler " +); + +void InstallGlobalKeyboardHook(void) +{ + ULONG LocalNewGlobalInt31Handler; + + ENTER_FUNC(); + + MaskIrqs(); + if(!OldGlobalInt31Handler) + { + __asm__("mov $NewGlobalInt31Handler,%0" + :"=r" (LocalNewGlobalInt31Handler) + : + :"eax"); + OldGlobalInt31Handler=SetGlobalInt(KeyboardIRQL,(ULONG)LocalNewGlobalInt31Handler); + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} + +void DeInstallGlobalKeyboardHook(void) +{ + ENTER_FUNC(); + + MaskIrqs(); + if(OldGlobalInt31Handler) + { + SetGlobalInt(KeyboardIRQL,(ULONG)OldGlobalInt31Handler); + OldGlobalInt31Handler=0; + } + UnmaskIrqs(); + + LEAVE_FUNC(); +} + + diff --git a/apps/utils/pice/module/shell.h b/apps/utils/pice/module/shell.h new file mode 100644 index 0000000..cac7822 --- /dev/null +++ b/apps/utils/pice/module/shell.h @@ -0,0 +1,91 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + shell.h + +Abstract: + + HEADER for shell.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +//void InstallKeyboardHook(void); +//void DeInstallKeyboardHook(void); +void InstallGlobalKeyboardHook(void); +void DeInstallGlobalKeyboardHook(void); + +void RealIsr(ULONG dwReasonForBreak); +void NewInt31Handler(void); + +extern volatile BOOLEAN bNotifyToExit; +extern volatile BOOLEAN bSingleStep; +extern volatile UCHAR ucKeyPressedWhileIdle; +extern volatile BOOLEAN bInDebuggerShell; + +extern ULONG CurrentEIP,CurrentEFL; +extern ULONG CurrentEAX,CurrentEBX,CurrentECX,CurrentEDX; +extern ULONG CurrentESP,CurrentEBP,CurrentESI,CurrentEDI; +extern ULONG CurrentDR0,CurrentDR1,CurrentDR2,CurrentDR3,CurrentDR6,CurrentDR7; +extern ULONG CurrentCR0,CurrentCR2,CurrentCR3; +extern USHORT CurrentCS,CurrentDS,CurrentES,CurrentFS,CurrentGS,CurrentSS; +extern volatile BOOLEAN bControl; // TRUE when CTRL key was pressed +extern volatile BOOLEAN bShift; // TRUE when SHIFT key was pressed +extern volatile BOOLEAN bAlt; // TRUE when SHIFT key was pressed + +// previous context +extern ULONG OldEIP,OldEFL; +extern ULONG OldEAX,OldEBX,OldECX,OldEDX; +extern ULONG OldESP,OldEBP,OldESI,OldEDI; +extern USHORT OldCS,OldDS,OldES,OldFS,OldGS,OldSS; + +extern ULONG CurrentProcess; + +extern USHORT OldSelector; +extern ULONG OldOffset; + +extern ULONG ulRealStackPtr; // serves as current process pointer too!! + +extern ULONG g_ulLineNumberStart; +extern BOOLEAN bStepThroughSource; +extern BOOLEAN bStepInto; + +#define REASON_INT3 (0) +#define REASON_SINGLESTEP (1) +#define REASON_CTRLF (2) +#define REASON_PAGEFAULT (3) +#define REASON_GP_FAULT (4) +#define REASON_HARDWARE_BP (5) +#define REASON_DOUBLE_FAULT (6) +#define REASON_MODULE_LOAD (7) +#define REASON_INTERNAL_ERROR (8) + +extern volatile BOOLEAN bEnterNow; + +// keyboard controller defines +#define I8042_PHYSICAL_BASE 0x60 +#define I8042_DATA_REGISTER_OFFSET 0 +#define I8042_COMMAND_REGISTER_OFFSET 4 +#define I8042_STATUS_REGISTER_OFFSET 4 + +void ShowStatusLine(void); + +#define KEYBOARD_IRQ 1 diff --git a/apps/utils/pice/module/stab.def b/apps/utils/pice/module/stab.def new file mode 100644 index 0000000..7e2c129 --- /dev/null +++ b/apps/utils/pice/module/stab.def @@ -0,0 +1,265 @@ +/* Table of DBX symbol codes for the GNU system. + Copyright (C) 1988, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files + overlaps the N_UNDF used for ordinary symbols. In ELF files, the + debug information is in a different file section, so there is no conflict. + This symbol's n_value gives the size of the string section associated + with this file. The symbol's n_strx (relative to the just-updated + string section start address) gives the name of the source file, + e.g. "foo.c", without any path information. The symbol's n_desc gives + the count of upcoming symbols associated with this file (not including + this one). */ +__define_stab (N_UNDF, 0x00, "UNDF") + +/* Global variable. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_GSYM, 0x20, "GSYM") + +/* Function name for BSD Fortran. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_FNAME, 0x22, "FNAME") + +/* Function name or text-segment variable for C. Value is its address. + Desc is supposedly starting line number, but GCC doesn't set it + and DBX seems not to miss it. */ +__define_stab (N_FUN, 0x24, "FUN") + +/* Data-segment variable with internal linkage. Value is its address. + "Static Sym". */ +__define_stab (N_STSYM, 0x26, "STSYM") + +/* BSS-segment variable with internal linkage. Value is its address. */ +__define_stab (N_LCSYM, 0x28, "LCSYM") + +/* Name of main routine. Only the name is significant. */ +__define_stab (N_MAIN, 0x2a, "MAIN") + +/* Solaris2: Read-only data symbols. */ +__define_stab (N_ROSYM, 0x2c, "ROSYM") + +/* Global symbol in Pascal. + Supposedly the value is its line number; I'm skeptical. */ +__define_stab (N_PC, 0x30, "PC") + +/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ +__define_stab (N_NSYMS, 0x32, "NSYMS") + +/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ +__define_stab (N_NOMAP, 0x34, "NOMAP") + +/* New stab from Solaris 2. Like N_SO, but for the object file. Two in + a row provide the build directory and the relative path of the .o from it. + Solaris2 uses this to avoid putting the stabs info into the linked + executable; this stab goes into the ".stab.index" section, and the debugger + reads the real stabs directly from the .o files instead. */ +__define_stab (N_OBJ, 0x38, "OBJ") + +/* New stab from Solaris 2. Options for the debugger, related to the + source language for this module. E.g. whether to use ANSI + integral promotions or traditional integral promotions. */ +__define_stab (N_OPT, 0x3c, "OPT") + +/* Register variable. Value is number of register. */ +__define_stab (N_RSYM, 0x40, "RSYM") + +/* Modula-2 compilation unit. Can someone say what info it contains? */ +__define_stab (N_M2C, 0x42, "M2C") + +/* Line number in text segment. Desc is the line number; + value is corresponding address. On Solaris2, the line number is + relative to the start of the current function. */ +__define_stab (N_SLINE, 0x44, "SLINE") + +/* Similar, for data segment. */ +__define_stab (N_DSLINE, 0x46, "DSLINE") + +/* Similar, for bss segment. */ +__define_stab (N_BSLINE, 0x48, "BSLINE") + +/* Sun's source-code browser stabs. ?? Don't know what the fields are. + Supposedly the field is "path to associated .cb file". THIS VALUE + OVERLAPS WITH N_BSLINE! */ +__define_stab_duplicate (N_BROWS, 0x48, "BROWS") + +/* GNU Modula-2 definition module dependency. Value is the modification time + of the definition file. Other is non-zero if it is imported with the + GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there + are enough empty fields? */ +__define_stab(N_DEFD, 0x4a, "DEFD") + +/* New in Solaris2. Function start/body/end line numbers. */ +__define_stab(N_FLINE, 0x4C, "FLINE") + +/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 + and one is for C++. Still,... */ +/* GNU C++ exception variable. Name is variable name. */ +__define_stab (N_EHDECL, 0x50, "EHDECL") +/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ +__define_stab_duplicate (N_MOD2, 0x50, "MOD2") + +/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if + this entry is immediately followed by a CAUGHT stab saying what exception + was caught. Multiple CAUGHT stabs means that multiple exceptions + can be caught here. If Desc is 0, it means all exceptions are caught + here. */ +__define_stab (N_CATCH, 0x54, "CATCH") + +/* Structure or union element. Value is offset in the structure. */ +__define_stab (N_SSYM, 0x60, "SSYM") + +/* Solaris2: Last stab emitted for module. */ +__define_stab (N_ENDM, 0x62, "ENDM") + +/* Name of main source file. + Value is starting text address of the compilation. + If multiple N_SO's appear, the first to contain a trailing / is the + compilation directory. The first to not contain a trailing / is the + source file name, relative to the compilation directory. Others (perhaps + resulting from cfront) are ignored. + On Solaris2, value is undefined, but desc is a source-language code. */ + +__define_stab (N_SO, 0x64, "SO") + +/* Automatic variable in the stack. Value is offset from frame pointer. + Also used for type descriptions. */ +__define_stab (N_LSYM, 0x80, "LSYM") + +/* Beginning of an include file. Only Sun uses this. + In an object file, only the name is significant. + The Sun linker puts data into some of the other fields. */ +__define_stab (N_BINCL, 0x82, "BINCL") + +/* Name of sub-source file (#include file). + Value is starting text address of the compilation. */ +__define_stab (N_SOL, 0x84, "SOL") + +/* Parameter variable. Value is offset from argument pointer. + (On most machines the argument pointer is the same as the frame pointer. */ +__define_stab (N_PSYM, 0xa0, "PSYM") + +/* End of an include file. No name. + This and N_BINCL act as brackets around the file's output. + In an object file, there is no significant data in this entry. + The Sun linker puts data into some of the fields. */ +__define_stab (N_EINCL, 0xa2, "EINCL") + +/* Alternate entry point. Value is its address. */ +__define_stab (N_ENTRY, 0xa4, "ENTRY") + +/* Beginning of lexical block. + The desc is the nesting level in lexical blocks. + The value is the address of the start of the text for the block. + The variables declared inside the block *precede* the N_LBRAC symbol. + On Solaris2, the value is relative to the start of the current function. */ +__define_stab (N_LBRAC, 0xc0, "LBRAC") + +/* Place holder for deleted include file. Replaces a N_BINCL and everything + up to the corresponding N_EINCL. The Sun linker generates these when + it finds multiple identical copies of the symbols from an include file. + This appears only in output from the Sun linker. */ +__define_stab (N_EXCL, 0xc2, "EXCL") + +/* Modula-2 scope information. Can someone say what info it contains? */ +__define_stab (N_SCOPE, 0xc4, "SCOPE") + +/* End of a lexical block. Desc matches the N_LBRAC's desc. + The value is the address of the end of the text for the block. + On Solaris2, the value is relative to the start of the current function. */ +__define_stab (N_RBRAC, 0xe0, "RBRAC") + +/* Begin named common block. Only the name is significant. */ +__define_stab (N_BCOMM, 0xe2, "BCOMM") + +/* End named common block. Only the name is significant + (and it should match the N_BCOMM). */ +__define_stab (N_ECOMM, 0xe4, "ECOMM") + +/* Member of a common block; value is offset within the common block. + This should occur within a BCOMM/ECOMM pair. */ +__define_stab (N_ECOML, 0xe8, "ECOML") + +/* Solaris2: Pascal "with" statement: type,,0,0,offset */ +__define_stab (N_WITH, 0xea, "WITH") + +/* These STAB's are used on Gould systems for Non-Base register symbols + or something like that. FIXME. I have assigned the values at random + since I don't have a Gould here. Fixups from Gould folk welcome... */ +__define_stab (N_NBTEXT, 0xF0, "NBTEXT") +__define_stab (N_NBDATA, 0xF2, "NBDATA") +__define_stab (N_NBBSS, 0xF4, "NBBSS") +__define_stab (N_NBSTS, 0xF6, "NBSTS") +__define_stab (N_NBLCS, 0xF8, "NBLCS") + +/* Second symbol entry containing a length-value for the preceding entry. + The value is the length. */ +__define_stab (N_LENG, 0xfe, "LENG") + +/* The above information, in matrix format. + + STAB MATRIX + _________________________________________________ + | 00 - 1F are not dbx stab symbols | + | In most cases, the low bit is the EXTernal bit| + + | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | + | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | + + | 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA | + | 09 |EXT | 0B | 0D WEAKU | 0F WEAKT | + + | 10 WEAKD | 12 COMM | 14 SETA | 16 SETT | + | 11 WEAKB | 13 | 15 | 17 | + + | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| + | 19 | 1B | 1D | 1F FN | + + |_______________________________________________| + | Debug entries with bit 01 set are unused. | + | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | + | 28 LCSYM | 2A MAIN | 2C ROSYM | 2E | + | 30 PC | 32 NSYMS | 34 NOMAP | 36 | + | 38 OBJ | 3A | 3C OPT | 3E | + | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | + | 48 BSLINE*| 4A DEFD | 4C FLINE | 4E | + | 50 EHDECL*| 52 | 54 CATCH | 56 | + | 58 | 5A | 5C | 5E | + | 60 SSYM | 62 ENDM | 64 SO | 66 | + | 68 | 6A | 6C | 6E | + | 70 | 72 | 74 | 76 | + | 78 | 7A | 7C | 7E | + | 80 LSYM | 82 BINCL | 84 SOL | 86 | + | 88 | 8A | 8C | 8E | + | 90 | 92 | 94 | 96 | + | 98 | 9A | 9C | 9E | + | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | + | A8 | AA | AC | AE | + | B0 | B2 | B4 | B6 | + | B8 | BA | BC | BE | + | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | + | C8 | CA | CC | CE | + | D0 | D2 | D4 | D6 | + | D8 | DA | DC | DE | + | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | + | E8 ECOML | EA WITH | EC | EE | + | F0 | F2 | F4 | F6 | + | F8 | FA | FC | FE LENG | + +-----------------------------------------------+ + * 50 EHDECL is also MOD2. + * 48 BSLINE is also BROWS. + */ diff --git a/apps/utils/pice/module/stab_gnu.h b/apps/utils/pice/module/stab_gnu.h new file mode 100644 index 0000000..dbc65ee --- /dev/null +++ b/apps/utils/pice/module/stab_gnu.h @@ -0,0 +1,67 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + stab_gnu.h + +Abstract: + + HEADER, GNU stabs symbols + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#ifndef __GNU_STAB__ + +/* Indicate the GNU stab.h is in use. */ + +#define __GNU_STAB__ + +#define __define_stab(NAME, CODE, STRING) NAME=CODE, +#define __define_stab_duplicate(NAME, CODE, STRING) NAME=CODE, + +enum __stab_debug_code +{ +#include "stab.def" +LAST_UNUSED_STAB_CODE +}; + +#undef __define_stab + +/* Definitions of "desc" field for N_SO stabs in Solaris2. */ + +#define N_SO_AS 1 +#define N_SO_C 2 +#define N_SO_ANSI_C 3 +#define N_SO_CC 4 /* C++ */ +#define N_SO_FORTRAN 5 +#define N_SO_PASCAL 6 + +/* Solaris2: Floating point type values in basic types. */ + +#define NF_NONE 0 +#define NF_SINGLE 1 /* IEEE 32-bit */ +#define NF_DOUBLE 2 /* IEEE 64-bit */ +#define NF_COMPLEX 3 /* Fortran complex */ +#define NF_COMPLEX16 4 /* Fortran double complex */ +#define NF_COMPLEX32 5 /* Fortran complex*16 */ +#define NF_LDOUBLE 6 /* Long double (whatever that is) */ + +#endif /* __GNU_STAB_ */ diff --git a/apps/utils/pice/module/symbols.c b/apps/utils/pice/module/symbols.c new file mode 100644 index 0000000..76c44d6 --- /dev/null +++ b/apps/utils/pice/module/symbols.c @@ -0,0 +1,2984 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module ModuleName: + + symbols.c + +Abstract: + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + Reactos Port by Eugene Ingerman + +Revision History: + + 19-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" +#include "stab_gnu.h" + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +PVOID pExports=0; +ULONG ulExportLen=0; + +LOCAL_VARIABLE local_vars[512]; + +PICE_SYMBOLFILE_HEADER* apSymbols[32]={NULL,}; +ULONG ulNumSymbolsLoaded=0; + +ULONG kernel_end=0; + +char tempSym[1024]; // temp buffer for output + + +PULONG LocalRegs[]= +{ + &CurrentEAX, + &CurrentECX, + &CurrentEDX, + &CurrentEBX, + &CurrentESP, + &CurrentEBP, + &CurrentESI, + &CurrentEDI, + &CurrentEIP, + &CurrentEFL +}; + +typedef struct _VRET +{ + ULONG value; + ULONG type; + ULONG father_type; + ULONG error; + ULONG file; + ULONG size; + ULONG address; + char name[256]; + char type_name[256]; + BOOLEAN bPtrType; + BOOLEAN bStructType; + BOOLEAN bArrayType; + PICE_SYMBOLFILE_HEADER* pSymbols; +}VRET,*PVRET; + +ULONG ulIndex; +LPSTR pExpression; +VRET vr; +VRET vrStructMembers[1024]; +ULONG ulNumStructMembers; + +BOOLEAN Expression(PVRET pvr); + +LIST_ENTRY *pModuleListHead = NULL; +extern PDIRECTORY_OBJECT *pNameSpaceRoot; +extern PDEBUG_MODULE pdebug_module_tail; +extern PDEBUG_MODULE pdebug_module_head; + + +PVOID HEADER_TO_BODY(POBJECT_HEADER obj) +{ + return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)); +} + +POBJECT_HEADER BODY_TO_HEADER(PVOID body) +{ + PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body; + return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); +} + +/*-----------------12/26/2001 7:59PM---------------- + * FreeModuleList - free list allocated with InitModuleList. Must + * be called at passive irql. + * --------------------------------------------------*/ +VOID FreeModuleList( PDEBUG_MODULE pm ) +{ + PDEBUG_MODULE pNext = pm; + + ENTER_FUNC(); + + while( pNext ){ + pNext = pm->next; + ExFreePool( pm ); + } + LEAVE_FUNC(); +} + +/*-----------------12/26/2001 7:58PM---------------- + * InitModuleList - creates linked list of length len for debugger. Can't be + * called at elevated IRQL + * --------------------------------------------------*/ +BOOLEAN InitModuleList( PDEBUG_MODULE *ppmodule, ULONG len ) +{ + ULONG i; + PDEBUG_MODULE pNext = NULL, pm = *ppmodule; + + ENTER_FUNC(); + + ASSERT(pm==NULL); + + for(i=1;i<=len;i++){ + pm = (PDEBUG_MODULE)ExAllocatePool( NonPagedPool, sizeof( DEBUG_MODULE ) ); + if( !pm ){ + FreeModuleList(pNext); + return FALSE; + } + pm->next = pNext; + pm->size = 0; + pm->BaseAddress = NULL; + //DbgPrint("len1: %d\n", pm->name.Length); + pNext = pm; + } + *ppmodule = pm; + + LEAVE_FUNC(); + + return TRUE; +} + +BOOLEAN ListUserModules( PPEB peb ) +{ + PLIST_ENTRY UserModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + PPEB_LDR_DATA Ldr; + + ENTER_FUNC(); + + Ldr = peb->Ldr; + if( Ldr && IsAddressValid((ULONG)Ldr)){ + UserModuleListHead = &Ldr->InLoadOrderModuleList; + ASSERT(IsAddressValid((ULONG)UserModuleListHead)); + Entry = UserModuleListHead->Flink; + while (Entry != UserModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + //DbgPrint("Module: %x, BaseAddress: %x\n", Module, Module->BaseAddress); + + DPRINT((0,"FullName: %S, BaseName: %S, Length: %ld, EntryPoint: %x, BaseAddress: %x\n", Module->FullDllName.Buffer, + Module->BaseDllName.Buffer, Module->SizeOfImage, Module->EntryPoint, Module->BaseAddress )); + + pdebug_module_tail->size = Module->SizeOfImage; + pdebug_module_tail->BaseAddress = Module->BaseAddress; + pdebug_module_tail->EntryPoint = (PVOID)(Module->EntryPoint); + ASSERT(Module->BaseDllName.Lengthname, Module->BaseDllName.Buffer ); + pdebug_module_tail = pdebug_module_tail->next; + + Entry = Entry->Flink; + } + } + LEAVE_FUNC(); + return TRUE; +} + +POBJECT FindDriverObjectDirectory( void ) +{ + PLIST_ENTRY current; + POBJECT_HEADER current_obj; + PDIRECTORY_OBJECT pd; + + ENTER_FUNC(); + + if( pNameSpaceRoot && *pNameSpaceRoot ){ + current = (*pNameSpaceRoot)->head.Flink; + while (current!=(&((*pNameSpaceRoot)->head))) + { + current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry); + DPRINT((0,"Scanning %S\n",current_obj->Name.Buffer)); + if (_wcsicmp(current_obj->Name.Buffer, L"Modules")==0) + { + pd=HEADER_TO_BODY(current_obj); + DPRINT((0,"Found it %x\n",pd)); + return pd; + } + current = current->Flink; + } + } + LEAVE_FUNC(); + return NULL; +} + +BOOLEAN ListDriverModules( void ) +{ + PLIST_ENTRY current_entry; + PMODULE_OBJECT current; + POBJECT_HEADER current_obj; + + ENTER_FUNC(); + + ASSERT( pModuleListHead ); + + current_entry = pModuleListHead->Flink; + + while (current_entry != (pModuleListHead)){ + + current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry); + + DPRINT((0,"FullName: %S, BaseName: %S, Length: %ld, EntryPoint: %x\n", current->FullName.Buffer, + current->BaseName.Buffer, current->Length, current->EntryPoint )); + + pdebug_module_tail->BaseAddress = current->Base; + pdebug_module_tail->size = current->Length; + PICE_wcscpy( pdebug_module_tail->name, current->BaseName.Buffer); + pdebug_module_tail->EntryPoint = current->EntryPoint; + + pdebug_module_tail = pdebug_module_tail->next; + + if (current && _wcsicmp(current->BaseName.Buffer, L"ntoskrnl")==0) + { + kernel_end = (ULONG)current->Base + current->Length; + } + current_entry = current_entry->Flink; + } + + LEAVE_FUNC(); + return TRUE; +} + +BOOLEAN BuildModuleList( void ) +{ + PPEB peb; + PEPROCESS tsk; + ENTER_FUNC(); + + pdebug_module_tail = pdebug_module_head; + tsk = IoGetCurrentProcess(); + ASSERT(IsAddressValid((ULONG)tsk)); + if( tsk ){ + peb = tsk->Peb; + if( peb ){ + if( !ListUserModules( peb ) ){ + LEAVE_FUNC(); + return FALSE; + } + } + } + if( !ListDriverModules() ){ + LEAVE_FUNC(); + return FALSE; + } + LEAVE_FUNC(); + return TRUE; +} + +//************************************************************************* +// IsModuleLoaded() +// +//************************************************************************* +PDEBUG_MODULE IsModuleLoaded(LPSTR p) +{ + PDEBUG_MODULE pd; + + ENTER_FUNC(); + DPRINT((0,"IsModuleLoaded(%s)\n",p)); + + if(BuildModuleList()) + { + pd = pdebug_module_head; + do + { + char temp[DEBUG_MODULE_NAME_LEN]; + DPRINT((0,"module (%x) %S\n",pd->size,pd->name)); + CopyWideToAnsi(temp,pd->name); + if(pd->size && PICE_strcmpi(p,temp) == 0) + { + DPRINT((0,"module %S is loaded!\n",pd->name)); + LEAVE_FUNC(); + return pd; + } + }while((pd = pd->next)!=pdebug_module_tail); + } + LEAVE_FUNC(); + return NULL; +} + +//************************************************************************* +// ScanExports() +// +//************************************************************************* +BOOLEAN ScanExports(const char *pFind,PULONG pValue) +{ + char temp[256]; + LPSTR pStr=NULL; + LPSTR pExp = pExports; + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + DPRINT((0,"ScanExports pValue: %x\n", pValue)); +nomatch: + if(pExports) + pStr = strstr(pExp,pFind); + + if(pStr) + { + LPSTR p; + ULONG state; + LPSTR pOldStr = pStr; + + for(;(*pStr!=0x0a && *pStr!=0x0d) && (ULONG)pStr>=(ULONG)pExports;pStr--); + pStr++; + p = temp; + for(;(*pStr!=0x0a && *pStr!=0x0d);)*p++=*pStr++; + *p=0; + p = (LPSTR) PICE_strtok(temp," "); + state=0; + while(p) + { + switch(state) + { + case 0: + ConvertTokenToHex(p,pValue); + break; + case 1: + break; + case 2: + if(strcmp(p,pFind)!=0) + { + DPRINT((0,"Not: %s\n", p)); + pExp = pOldStr+1; + goto nomatch; + } + state = -1; + bResult = TRUE; + DPRINT((0,"%s @ %x\n",pFind,*pValue)); + goto exit; + break; + } + state++; + p = (char*) PICE_strtok(NULL," "); + } + } +exit: + DPRINT((0,"%s %x @ %x\n",pFind,pValue,*pValue)); + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// ReadHex() +// +//************************************************************************* +BOOLEAN ReadHex(LPSTR p,PULONG pValue) +{ + ULONG result=0,i; + + for(i=0;i<8 && p[i]!=0 && p[i]!=' ';i++) + { + if(p[i]>='0' && p[i]<='9') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'0'); + } + else if(p[i]>='A' && p[i]<='F') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'A'+10); + } + else if(p[i]>='a' && p[i]<='f') + { + result<<=4; + result|=(ULONG)(UCHAR)(p[i]-'a'+10); + } + else + return FALSE; + } + + *pValue = result; + return TRUE; +} + +//************************************************************************* +// ScanExportLine() +// +//************************************************************************* +BOOLEAN ScanExportLine(LPSTR p,PULONG ulValue,LPSTR* ppPtrToSymbol) +{ + BOOLEAN bResult = FALSE; + + if(ReadHex(p,ulValue)) + { + p += 11; + *ppPtrToSymbol += 11; + bResult = TRUE; + } + + return bResult; +} + +//************************************************************************* +// ValidityCheckSymbols() +// +//************************************************************************* +BOOLEAN ValidityCheckSymbols(PICE_SYMBOLFILE_HEADER* pSymbols) +{ + BOOLEAN bRet; + + DPRINT((0,"ValidityCheckSymbols()\n")); + + bRet = (IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToHeaders,pSymbols->ulSizeOfHeader) && + IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToGlobals,pSymbols->ulSizeOfGlobals) && + IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToGlobalsStrings,pSymbols->ulSizeOfGlobalsStrings) && + IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToStabs,pSymbols->ulSizeOfStabs) && + IsRangeValid((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings,pSymbols->ulSizeOfStabsStrings)); + + DPRINT((0,"ValidityCheckSymbols(): symbols are %s\n",bRet?"VALID":"NOT VALID")); + + return bRet; +} + +//************************************************************************* +// FindModuleSymbols() +// +//************************************************************************* +PICE_SYMBOLFILE_HEADER* FindModuleSymbols(ULONG addr) +{ + ULONG start,end,i; + PDEBUG_MODULE pd = pdebug_module_head; + + DPRINT((0,"FindModuleSymbols(%x)\n",addr)); + if(BuildModuleList()) + { + i=0; + pd = pdebug_module_head; + do + { + DPRINT((0,"pd: %x\n", pd)); + if(pd->size) + { + start = (ULONG)pd->BaseAddress; + end = start + pd->size; + DPRINT((0,"FindModuleSymbols(): %S %x-%x\n",pd->name,start,end)); + if(addr>=start && addrname,start,end)); + for(i=0;iname )); + if(PICE_wcsicmp(pd->name,apSymbols[i]->name) == 0) + { + if(ValidityCheckSymbols(apSymbols[i])) + return apSymbols[i]; + else + return NULL; + } + } + } + } + }while((pd = pd->next) != pdebug_module_tail); + } + + return NULL; +} + +//************************************************************************* +// FindModuleFromAddress() +// +//************************************************************************* +PDEBUG_MODULE FindModuleFromAddress(ULONG addr) +{ + PDEBUG_MODULE pd; + ULONG start,end; + + DPRINT((0,"FindModuleFromAddress()\n")); + if(BuildModuleList()) + { + pd = pdebug_module_head; + do + { + if(pd->size) + { + start = (ULONG)pd->BaseAddress; + end = start + pd->size; + DPRINT((0,"FindModuleFromAddress(): %S %x-%x\n",pd->name,start,end)); + if(addr>=start && addrname)); + return pd; + } + } + }while((pd = pd->next)!=pdebug_module_tail); + } + + return NULL; +} + +//************************************************************************* +// FindModuleByName() +// +//************************************************************************* +PDEBUG_MODULE FindModuleByName(LPSTR modname) +{ + PDEBUG_MODULE pd; + WCHAR tempstr[DEBUG_MODULE_NAME_LEN]; + + DPRINT((0,"FindModuleFromAddress()\n")); + if( !PICE_MultiByteToWideChar(CP_ACP, NULL, modname, -1, tempstr, DEBUG_MODULE_NAME_LEN ) ) + { + DPRINT((0,"Can't convert module name.\n")); + return NULL; + } + + if(BuildModuleList()) + { + pd = pdebug_module_head; + do + { + if(pd->size) + { + if(PICE_wcsicmp(tempstr,pd->name) == 0) + { + DPRINT((0,"FindModuleByName(): found %S\n",pd->name)); + return pd; + } + } + }while((pd = pd->next) != pdebug_module_tail); + } + + return NULL; +} + +//************************************************************************* +// FindModuleSymbolsByModuleName() +// +//************************************************************************* +PICE_SYMBOLFILE_HEADER* FindModuleSymbolsByModuleName(LPSTR modname) +{ + ULONG i; + WCHAR tempstr[DEBUG_MODULE_NAME_LEN]; + + DPRINT((0,"FindModuleSymbols()\n")); + if( !PICE_MultiByteToWideChar(CP_ACP, NULL, modname, -1, tempstr, DEBUG_MODULE_NAME_LEN ) ) + { + DPRINT((0,"Can't convert module name in FindModuleSymbols.\n")); + return NULL; + } + + for(i=0;iname) == 0) + return apSymbols[i]; + } + + return NULL; +} + +//************************************************************************* +// ScanExportsByAddress() +// +//************************************************************************* +BOOLEAN ScanExportsByAddress(LPSTR *pFind,ULONG ulValue) +{ + char temp[256]; + static char temp3[256]; + LPSTR p,pStartOfLine,pSymbolName=NULL; + ULONG ulCurrentValue=0; + BOOLEAN bResult = FALSE; + PDEBUG_MODULE pd; + ULONG ulMinValue = -1; + PIMAGE_SYMBOL pSym,pSymEnd; //running pointer to symbols and end of sym talbe + PIMAGE_SYMBOL pFoundSym = NULL; //current best symbol match + ULONG ulAddr = 0x0; //address of the best match + LPSTR pStr; + PIMAGE_SECTION_HEADER pShdr; + PICE_SYMBOLFILE_HEADER* pSymbols; + ULONG ulSectionSize; + LPSTR pName; + + ENTER_FUNC(); + DPRINT((0,"In ScanExportsByAddress:\n")); + + pSymbols = FindModuleSymbols(ulValue); + DPRINT((0,"pSymbols: %x\n", pSymbols)); + + if(BuildModuleList()){ + if(pSymbols && pdebug_module_head) + { + PDEBUG_MODULE pdTemp; + + DPRINT((0,"looking up symbols\n")); + pd = pdebug_module_head; + do + { + if(pd->size){ + pdTemp = pd; + + if(ulValue>=((ULONG)pdTemp->BaseAddress) && ulValue<((ULONG)pdTemp+pdTemp->size)) + { + if(PICE_wcsicmp(pdTemp->name,pSymbols->name) == 0) + { + DPRINT((0,"ScanExportsByAddress(): found symbols for module %S @ %x \n",pdTemp->name,(ULONG)pSymbols)); + + pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); + pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); + pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); + pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); + + if(!IsRangeValid((ULONG)pSym,sizeof(IMAGE_SYMBOL) ) ) //should we actually check all the symbols here? + { + DPRINT((0,"ScanExportsByAddress(): pSym = %x is not a valid pointer\n",(ULONG)pSym)); + return FALSE; + } + + DPRINT((0,"ScanExportsByAddress(): pSym = %x\n",pSym)); + DPRINT((0,"ScanExportsByAddress(): pStr = %x\n",pStr)); + DPRINT((0,"ScanExportsByAddress(): pShdr = %x\n",pShdr)); + + DPRINT((0,"ScanExportsByAddress(): %S has %u symbols\n",pSymbols->name,pSymbols->ulSizeOfGlobals/sizeof(IMAGE_SYMBOL))); + + /* go through all the global symbols and find the one with + the largest address which is less than ulValue */ + while(pSym < pSymEnd) + { //it seems only 0x0 and 0x20 are used for type and External or Static storage classes + if(((pSym->Type == 0x0) || (pSym->Type == 0x20) ) && + ((pSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) || (pSym->StorageClass==IMAGE_SYM_CLASS_STATIC)) && + (pSym->SectionNumber > 0 )) + { + ULONG ulCurrAddr; + PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); + + + DPRINT((0,"ScanExportsByAddress(): pShdr[%x] = %x\n",pSym->SectionNumber,(ULONG)pShdrThis)); + + if(!IsRangeValid((ULONG)pShdrThis,sizeof(IMAGE_SECTION_HEADER)) ) + { + DPRINT((0,"ScanExportsByAddress(): pElfShdr[%x] = %x is not a valid pointer\n",pSym->SectionNumber,(ULONG)pShdrThis)); + return FALSE; + } + //to get address in the memory we base address of the module and + //add offset of the section and then add offset of the symbol from + //the begining of the section + ulCurrAddr = ((ULONG)pdTemp->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); + DPRINT((0,"ScanExportsByAddress(): CurrAddr [1] = %x\n",ulCurrAddr)); + + if(ulCurrAddr<=ulValue && ulCurrAddr>ulAddr) + { + ulAddr = ulCurrAddr; + pFoundSym = pSym; + } + } + //skip the auxiliary symbols and get the next symbol + pSym += pSym->NumberOfAuxSymbols + 1; + } + *pFind = temp3; + if( pFoundSym->N.Name.Short ){ + pName = pFoundSym->N.ShortName; //name is in the header + PICE_sprintf(temp3,"%S!%.8s",pdTemp->name,pName); //if name is in the header it may be nonzero terminated + } + else{ + ASSERT(pFoundSym->N.Name.Long<=pSymbols->ulSizeOfGlobalsStrings); //sanity check + pName = pStr+pFoundSym->N.Name.Long; + if(!IsAddressValid((ULONG)pName)) + { + DPRINT((0,"ScanExportsByAddress(): pName = %x is not a valid pointer\n",pName)); + return FALSE; + } + PICE_sprintf(temp3,"%S!%s",pdTemp->name,pName); + } + DPRINT((0,"ScanExportsByAddress(): pName = %x\n",(ULONG)pName)); + return TRUE; + } + } + } + }while((pd = pd->next)); + } + } + // if haven't found in the symbols try ntoskrnl exports. (note: check that this is needed since we + // already checked ntoskrnl coff symbol table) + if(pExports && ulValue >= KERNEL_START && ulValue < kernel_end) + { + p = pExports; + // while we bound in System.map + while(p<((LPSTR)pExports+ulExportLen)) + { + // make a temp ptr to the line we can change + pStartOfLine = p; + // will read the hex value and return a pointer to the symbol name + if(ScanExportLine(p,&ulCurrentValue,&pStartOfLine)) + { + if(ulValue>=ulCurrentValue && (ulValue-ulCurrentValue)name,(ULONG)pSymbols)); + if(pSymbols && pdebug_module_head) + { + DPRINT((0,"looking up symbol\n")); + pd = pdebug_module_head; + do + { + ASSERT(pd->size); + pdTemp = pd; + + //initial values for start and end. + start = (ULONG)pdTemp->BaseAddress; + end = start+pdTemp->size; + + DPRINT((0,"FindFunctionByAddress(): ulValue %x\n",ulValue)); + + if(ulValue>=start && ulValuename)); + if(PICE_wcsicmp(pdTemp->name,pSymbols->name) == 0) + { + DPRINT((0,"found symbols for module %S\n",pdTemp->name)); + pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); + pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); + pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); + pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); + + if(!IsRangeValid((ULONG)pSym,sizeof(IMAGE_SYMBOL) ) ) //should we actually check all the symbols here? + { + DPRINT((0,"FindFunctionByAddress(): pSym = %x is not a valid pointer\n",(ULONG)pSym)); + return FALSE; + } + DPRINT((0,"pSym = %x\n",pSym)); + DPRINT((0,"pStr = %x\n",pStr)); + DPRINT((0,"pShdr = %x\n",pShdr)); + + while( pSym < pSymEnd ) + { + //symbol is a function is it's type is 0x20, and section>0 + if(( (pSym->Type == 0x20) && + (pSym->SectionNumber > 0 ))) + { + ULONG ulCurrAddr; + PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); + + DPRINT((0,"FindFunctionByAddress(): pShdr[%x] = %x\n",pSym->SectionNumber,(ULONG)pShdrThis)); + + if(!IsRangeValid((ULONG)pShdrThis,sizeof(IMAGE_SECTION_HEADER)) ) + { + DPRINT((0,"ScanExportsByAddress(): pElfShdr[%x] = %x is not a valid pointer\n",pSym->SectionNumber,(ULONG)pShdrThis)); + return FALSE; + } + //to get address in the memory we base address of the module and + //add offset of the section and then add offset of the symbol from + //the begining of the section + ulCurrAddr = ((ULONG)pdTemp->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); + DPRINT((0,"FindFunctionByAddress(): CurrAddr [1] = %x\n",ulCurrAddr)); + DPRINT((0,"%x ", ulCurrAddr)); + + if(ulCurrAddr<=ulValue && ulCurrAddr>start) + { + start = ulCurrAddr; + pFoundSym = pSym; + //DPRINT((0,"FindFunctionByAddress(): CANDIDATE for start %x\n",start)); + } + else if(ulCurrAddr>=ulValue && ulCurrAddrNumberOfAuxSymbols + 1; + } + //we went through all the symbols for this module + //now start should point to the start of the function and + //end to the start of the next (or end of section) + if(pulstart) + *pulstart = start; + + if(pulend){ + //just in case there is more than one code section + PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pFoundSym->SectionNumber-1); + if( end > (ULONG)pdTemp->BaseAddress+pShdrThis->SizeOfRawData ){ + DPRINT((0,"Hmm: end=%d, end of section: %d\n", end, (ULONG)pdTemp->BaseAddress+pShdrThis->SizeOfRawData)); + end = (ULONG)pdTemp->BaseAddress+pShdrThis->SizeOfRawData; + } + *pulend = end; + } + + if(pFoundSym->N.Name.Short){ + //name is in the header. it's not zero terminated. have to copy. + PICE_sprintf(temp4,"%.8s", pFoundSym->N.ShortName); + pName = temp4; + DPRINT((0,"Function name: %S!%.8s",pdTemp->name,pName)); + } + else{ + ASSERT(pFoundSym->N.Name.Long<=pSymbols->ulSizeOfGlobalsStrings); //sanity check + pName = pStr+pFoundSym->N.Name.Long; + if(!IsAddressValid((ULONG)pName)) + { + DPRINT((0,"FindFunctionByAddress(): pName = %x is not a valid pointer\n",pName)); + return NULL; + } + DPRINT((0,"Function name: %S!%s",pdTemp->name,pName)); + } + return pName; + } + } + }while((pd = pd->next) != pdebug_module_tail); + } + return NULL; +} + +//************************************************************************* +// FindDataSectionOffset() +// +//************************************************************************* +/* ei: never used +ULONG FindDataSectionOffset(Elf32_Shdr* pSHdr) +{ + + DPRINT((0,"FindDataSectionOffset()\n")); + + while(1) + { + DPRINT((0,"FindDataSectionOffset(): sh_offset %.8X sh_addr = %.8X\n",pSHdr->sh_offset,pSHdr->sh_addr)); + if((pSHdr->sh_flags & (SHF_WRITE|SHF_ALLOC) ) == (SHF_WRITE|SHF_ALLOC)) + { + + return pSHdr->sh_offset; + } + pSHdr++; + } + + return 0; +} +*/ + +//************************************************************************* +// FindFunctionInModuleByNameViaKsyms() +// +//************************************************************************* +/* ei: not needed. no Ksyms! +ULONG FindFunctionInModuleByNameViaKsyms(struct module* pMod,LPSTR szFunctionname) +{ + ULONG i; + + ENTER_FUNC(); + + if(pMod->nsyms) + { + DPRINT((0,"FindFunctionInModuleByNameViaKsyms(): %u symbols for module %s\n",pMod->nsyms,pMod->name)); + for(i=0;insyms;i++) + { + DPRINT((0,"FindFunctionInModuleByNameViaKsyms(): %s\n",pMod->syms[i].name)); + if(PICE_strcmpi((LPSTR)pMod->syms[i].name,szFunctionname) == 0) + { + DPRINT((0,"FindFunctionInModuleByName(): symbol was in exports\n")); + LEAVE_FUNC(); + return pMod->syms[i].value; + } + } + } + + DPRINT((0,"FindFunctionInModuleByName(): symbol wasn't in exports\n")); + LEAVE_FUNC(); + return 0; +} +*/ + +//************************************************************************* +// FindFunctionInModuleByName() +// +//************************************************************************* +ULONG FindFunctionInModuleByName(LPSTR szFunctionname, PDEBUG_MODULE pd) +{ + ULONG i,addr; + PICE_SYMBOLFILE_HEADER* pSymbols=NULL; + PIMAGE_SYMBOL pSym, pSymEnd; + LPSTR pStr; + PIMAGE_SECTION_HEADER pShdr; + + ENTER_FUNC(); + DPRINT((0,"FindFunctionInModuleByName(%s)\n",szFunctionname)); + DPRINT((0,"FindFunctionInModuleByName(): mod size = %x\n",pd->size)); + DPRINT((0,"FindFunctionInModuleByName(): module is %S\n",pd->name)); + + addr = (ULONG)pd->BaseAddress; + + pSymbols = FindModuleSymbols(addr); + if(pSymbols) + { + DPRINT((0,"FindFunctionInModuleByName(): found symbol table for %S\n",pSymbols->name)); + pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); + pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); + pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); + pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); + + while( pSym < pSymEnd ) + { + //symbol is a function is it's type is 0x20, storage class is external and section>0 + //if(( (pSym->Type == 0x20) && (pSym->StorageClass==IMAGE_SYM_CLASS_EXTERNAL) && + // (pSym->SectionNumber > 0 ))) + + if(((pSym->Type == 0x0) || (pSym->Type == 0x20) ) && + ((pSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) || (pSym->StorageClass==IMAGE_SYM_CLASS_STATIC)) && + (pSym->SectionNumber > 0 )) + + { + ULONG start; + LPSTR pName; + PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); + + start = ((ULONG)pd->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); + DPRINT((0,"FindFunctionInModuleByName(): %s @ %x\n",szFunctionname,start)); + + if(pSym->N.Name.Short){ //if name is stored in the structure + //name may be not zero terminated but 8 characters max + DPRINT((0,"FindFunctionInModuleByName: %.8s\n", pSym->N.ShortName)); + pName = pSym->N.ShortName; //name is in the header + if((PICE_fnncmp(pName,szFunctionname, 8) == 0) && start) + { + DPRINT((0,"FindFunctionInModuleByName(): symbol was in symbol table, start: %x\n", start)); + LEAVE_FUNC(); + return start; + } + }else{ + pName = pStr+pSym->N.Name.Long; + DPRINT((0,"FindFunctionInModuleByName: %s\n", pName)); + if((PICE_fncmp(pName,szFunctionname) == 0) && start) + { + DPRINT((0,"FindFunctionInModuleByName(): symbol was in string table, start: %x\n", start)); + LEAVE_FUNC(); + return start; + } + } + } + //skip the auxiliary symbols and get the next symbol + pSym += pSym->NumberOfAuxSymbols + 1; + } + } + LEAVE_FUNC(); + return 0; +} + +//************************************************************************* +// ExtractTypeNumber() +// +//************************************************************************* +ULONG ExtractTypeNumber(LPSTR p) +{ + LPSTR pTypeNumber; + ULONG ulTypeNumber = 0; + + DPRINT((0,"ExtractTypeNumber(%s)\n",p)); + + pTypeNumber = PICE_strchr(p,'('); + + if(pTypeNumber) + { + pTypeNumber++; + ulTypeNumber = ExtractNumber(pTypeNumber); + ulTypeNumber <<= 16; + pTypeNumber = PICE_strchr(p,','); + if(pTypeNumber) + { + pTypeNumber++; + ulTypeNumber += ExtractNumber(pTypeNumber); + } + else + { + ulTypeNumber = 0; + } + } + return ulTypeNumber; +} + +//************************************************************************* +// FindTypeDefinitionForCombinedTypes() +// +//************************************************************************* +LPSTR FindTypeDefinitionForCombinedTypes(PICE_SYMBOLFILE_HEADER* pSymbols,ULONG ulTypeNumber,ULONG ulFileNumber) +{ + ULONG i; + PSTAB_ENTRY pStab; + LPSTR pStr,pName,pTypeNumber,pTypeDefIncluded,pNameTemp; + int nStabLen; + int nOffset=0,nNextOffset=0,nLen; + static char szAccumulatedName[2048]; + ULONG ulCurrentTypeNumber,ulCurrentFileNumber=0; + static char szCurrentPath[256]; + + ENTER_FUNC(); + + *szAccumulatedName = 0; + + pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); + nStabLen = pSymbols->ulSizeOfStabs; + pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); + + DPRINT((0,"FindTypeDefinitionForCombinedTypes()\n")); + + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + pName = &pStr[pStab->n_strx + nOffset]; + + switch(pStab->n_type) + { + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStab->n_value; + break; + case N_SO: + if((nLen = PICE_strlen(pName))) + { + if(pName[nLen-1]!='/') + { + ulCurrentFileNumber++; + if(PICE_strlen(szCurrentPath)) + { + PICE_strcat(szCurrentPath,pName); + DPRINT((0,"FindTypeDefinitionForCombinedTypes(): changing source file %s\n",szCurrentPath)); + } + else + { + DPRINT((0,"FindTypeDefinitionForCombinedTypes(): changing source file %s\n",pName)); + } + } + else + PICE_strcpy(szCurrentPath,pName); + } + else + { + szCurrentPath[0]=0; + } + break; + case N_GSYM: + //ei File number count is not reliable + if( 1 /*ulCurrentFileNumber == ulFileNumber*/) + { + DPRINT((0,"FindTypeDefinitionForCombinedTypes(): %s\n",pName)); + + // handle multi-line symbols + if(PICE_strchr(pName,'\\')) + { + if(PICE_strlen(szAccumulatedName)) + { + PICE_strcat(szAccumulatedName,pName); + } + else + { + PICE_strcpy(szAccumulatedName,pName); + } + szAccumulatedName[PICE_strlen(szAccumulatedName)-1]=0; + //DPRINT((0,"accum. %s\n",szAccumulatedName)); + } + else + { + if(PICE_strlen(szAccumulatedName)==0) + { + PICE_strcpy(szAccumulatedName,pName); + } + else + { + PICE_strcat(szAccumulatedName,pName); + } + pNameTemp = szAccumulatedName; + + // symbol-name:type-identifier type-number = + nLen = StrLenUpToWhiteChar(pNameTemp,":"); + if((pTypeDefIncluded = PICE_strchr(pNameTemp,'=')) && pNameTemp[nLen+1]=='G') + { + DPRINT((0,"FindTypeDefinitionForCombinedTypes(): symbol includes type definition (%s)\n",pNameTemp)); + pTypeNumber = pNameTemp+nLen+1; + if((ulCurrentTypeNumber = ExtractTypeNumber(pTypeNumber)) ) + { + DPRINT((0,"FindTypeDefinitionForCombinedTypes(): type-number %x\n",ulCurrentTypeNumber)); + if(ulCurrentTypeNumber == ulTypeNumber) + { + DPRINT((0,"FindTypeDefinitionForCombinedTypes(): typenumber %x matches!\n",ulCurrentTypeNumber)); + return pNameTemp; + } + } + } + *szAccumulatedName = 0; + } + } + break; + } + pStab++; + } + return NULL; +} + +//************************************************************************* +// FindTypeDefinition() +// +//************************************************************************* +LPSTR FindTypeDefinition(PICE_SYMBOLFILE_HEADER* pSymbols,ULONG ulTypeNumber,ULONG ulFileNumber) +{ + ULONG i; + PSTAB_ENTRY pStab; + LPSTR pStr,pName,pTypeString; + int nStabLen; + int nOffset=0,nNextOffset=0,strLen; + static char szAccumulatedName[2048]; + ULONG ulCurrentTypeNumber,ulCurrentFileNumber=0; + LPSTR pTypeSymbol; + static char szCurrentPath[256]; + + ENTER_FUNC(); + DPRINT((0,"FindTypeDefinition(%u,%u)\n",ulTypeNumber,ulFileNumber)); + + *szAccumulatedName = 0; + + pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); + nStabLen = pSymbols->ulSizeOfStabs; + pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); + + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + pName = &pStr[pStab->n_strx + nOffset]; + + switch(pStab->n_type) + { + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStab->n_value; + break; + case N_SO: + if((strLen = PICE_strlen(pName))) + { + if(pName[strLen-1]!='/') + { + ulCurrentFileNumber++; + if(PICE_strlen(szCurrentPath)) + { + PICE_strcat(szCurrentPath,pName); + DPRINT((0,"FindTypeDefinition()1: cha %s, %u\n",szCurrentPath, ulCurrentFileNumber)); + } + else + { + DPRINT((0,"FindTypeDefinition(): cha %s, %u\n",pName, ulCurrentFileNumber)); + } + } + else + PICE_strcpy(szCurrentPath,pName); + } + else + { + szCurrentPath[0]=0; + } + break; + case N_LSYM: + // stab has no value -> must be type definition + //ei File number count is not reliable + if(pStab->n_value == 0 /*&& ulCurrentFileNumber==ulFileNumber*/) + { + DPRINT((0,"FindTypeDefinition(): pre type definition %s\n",pName)); + // handle multi-line symbols + if(strrchr(pName,'\\')) + { + if(PICE_strlen(szAccumulatedName)) + { + PICE_strcat(szAccumulatedName,pName); + DPRINT((0,"FindTypeDefinition(): [1] accum. %s\n",szAccumulatedName)); + } + else + { + PICE_strcpy(szAccumulatedName,pName); + DPRINT((0,"FindTypeDefinition(): [2] accum. %s\n",szAccumulatedName)); + } + szAccumulatedName[PICE_strlen(szAccumulatedName)-1]=0; + } + else + { + DPRINT((0,"FindTypeDefinition(): [3] accum. %s, pname: %s\n",szAccumulatedName, pName)); + if(PICE_strlen(szAccumulatedName)==0) + { + PICE_strcpy(szAccumulatedName,pName); + } + else + { + PICE_strcat(szAccumulatedName,pName); + } + pTypeString = szAccumulatedName; + + pTypeSymbol = PICE_strchr(pTypeString,':'); + if(pTypeSymbol && (*(pTypeSymbol+1)=='t' || *(pTypeSymbol+1)=='T')) + { + // parse it + ulCurrentTypeNumber = ExtractTypeNumber(pTypeString); + DPRINT((0,"FindTypeDefinition(): ulCurrType: %u, LSYM is type %s\n",ulCurrentTypeNumber,pName)); + if(ulCurrentTypeNumber == ulTypeNumber) + { + DPRINT((0,"FindTypeDefinition(): type definition %s\n",pTypeString)); + return pTypeString; + } + } + *szAccumulatedName=0; + } + } + break; + } + pStab++; + } + + return FindTypeDefinitionForCombinedTypes(pSymbols,ulTypeNumber,ulFileNumber); + +} + +//************************************************************************* +// TruncateString() +// +//************************************************************************* +LPSTR TruncateString(LPSTR p,char c) +{ + static char temp[1024]; + LPSTR pTemp; + + pTemp = temp; + + while(*p!=0 && *p!=c) + *pTemp++ = *p++; + + *pTemp = 0; + + return temp; +} + +//************************************************************************* +// FindLocalsByAddress() +// +// find all locals for a given address by first looking up the function +// and then it's locals +//************************************************************************* +PLOCAL_VARIABLE FindLocalsByAddress(ULONG addr) +{ + ULONG i; + PSTAB_ENTRY pStab; + LPSTR pStr,pName; + int nStabLen; + int nOffset=0,nNextOffset=0; + PICE_SYMBOLFILE_HEADER* pSymbols; + static char szCurrentFunction[256]; + static char szCurrentPath[256]; + LPSTR pFunctionName; + ULONG start,end,strLen; + ULONG ulTypeNumber,ulCurrentFileNumber=0; + LPSTR pTypedef; + ULONG ulNumLocalVars=0; + + DPRINT((0,"FindLocalsByAddress()\n")); + + pFunctionName = FindFunctionByAddress(addr,&start,&end); + DPRINT((0,"FindLocalsByAddress(): pFunctionName = %s\n",pFunctionName)); + if(pFunctionName) + { + pSymbols = FindModuleSymbols(addr); + if(pSymbols) + { + pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); + nStabLen = pSymbols->ulSizeOfStabs; + pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); + + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + pName = &pStr[pStab->n_strx + nOffset]; + + DPRINT((0,"FindLocalsByAddress(): %x %x %x %x %x\n", + pStab->n_strx, + pStab->n_type, + pStab->n_other, + pStab->n_desc, + pStab->n_value)); + + switch(pStab->n_type) + { + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStab->n_value; + break; + case N_SO: + if((strLen = PICE_strlen(pName))) + { + if(pName[strLen-1]!='/') + { + ulCurrentFileNumber++; + if(PICE_strlen(szCurrentPath)) + { + PICE_strcat(szCurrentPath,pName); + DPRINT((0,"changing source file1 %s, %u\n",szCurrentPath,ulCurrentFileNumber)); + } + else + { + DPRINT((0,"changing source file %s, %u\n",pName,ulCurrentFileNumber)); + } + } + else + PICE_strcpy(szCurrentPath,pName); + } + else + { + szCurrentPath[0]=0; + } + break; + case N_LSYM: + // if we're in the function we're looking for + if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) + { + DPRINT((0,"local variable1 %.8X %.8X %.8X %.8X %.8X %s\n",pStab->n_strx,pStab->n_type,pStab->n_other,pStab->n_desc,pStab->n_value,pName)); + ulTypeNumber = ExtractTypeNumber(pName); + DPRINT((0,"type number = %u\n",ulTypeNumber)); + if((pTypedef = FindTypeDefinition(pSymbols,ulTypeNumber,ulCurrentFileNumber))) + { + DPRINT((0,"pTypedef: %x\n", pTypedef)); + PICE_strcpy(local_vars[ulNumLocalVars].type_name,TruncateString(pTypedef,':')); + PICE_strcpy(local_vars[ulNumLocalVars].name,TruncateString(pName,':')); + local_vars[ulNumLocalVars].value = (CurrentEBP+pStab->n_value); + local_vars[ulNumLocalVars].offset = pStab->n_value; + local_vars[ulNumLocalVars].line = pStab->n_desc; + local_vars[ulNumLocalVars].bRegister = FALSE; + ulNumLocalVars++; + } + } + break; + case N_PSYM: + // if we're in the function we're looking for + if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) + { + DPRINT((0,"parameter variable %.8X %.8X %.8X %.8X %.8X %s\n",pStab->n_strx,pStab->n_type,pStab->n_other,pStab->n_desc,pStab->n_value,pName)); + ulTypeNumber = ExtractTypeNumber(pName); + DPRINT((0,"type number = %x\n",ulTypeNumber)); + if((pTypedef = FindTypeDefinition(pSymbols,ulTypeNumber,ulCurrentFileNumber))) + { + PICE_strcpy(local_vars[ulNumLocalVars].type_name,TruncateString(pTypedef,':')); + PICE_strcpy(local_vars[ulNumLocalVars].name,TruncateString(pName,':')); + local_vars[ulNumLocalVars].value = (CurrentEBP+pStab->n_value); + local_vars[ulNumLocalVars].offset = pStab->n_value; + ulNumLocalVars++; + } + } + break; + case N_RSYM: + // if we're in the function we're looking for + if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) + { + DPRINT((0,"local variable2 %.8X %.8X %.8X %.8X %.8X %s\n",pStab->n_strx,pStab->n_type,pStab->n_other,pStab->n_desc,pStab->n_value,pName)); + ulTypeNumber = ExtractTypeNumber(pName); + DPRINT((0,"type number = %x\n",ulTypeNumber)); + if((pTypedef = FindTypeDefinition(pSymbols,ulTypeNumber,ulCurrentFileNumber))) + { + PICE_strcpy(local_vars[ulNumLocalVars].type_name,TruncateString(pTypedef,':')); + PICE_strcpy(local_vars[ulNumLocalVars].name,TruncateString(pName,':')); + local_vars[ulNumLocalVars].value = (LocalRegs[pStab->n_value]); + local_vars[ulNumLocalVars].offset = pStab->n_value; + local_vars[ulNumLocalVars].line = pStab->n_desc; + local_vars[ulNumLocalVars].bRegister = TRUE; + ulNumLocalVars++; + } + } + break; + case N_FUN: + if(PICE_strlen(pName)) + { + ULONG len; + + len=StrLenUpToWhiteChar(pName,":"); + PICE_strncpy(szCurrentFunction,pName,len); + szCurrentFunction[len]=0; + DPRINT((0,"function %s\n",szCurrentFunction)); + } + else + { + DPRINT((0,"END of function %s\n",szCurrentFunction)); + szCurrentFunction[0]=0; + if(ulNumLocalVars) + { + *local_vars[ulNumLocalVars].name = 0; + return local_vars; + } + } + break; + } + pStab++; + } + } + } + return NULL; +} + +//************************************************************************* +// FindSourceLineForAddress() +// +//************************************************************************* +LPSTR FindSourceLineForAddress(ULONG addr,PULONG pulLineNumber,LPSTR* ppSrcStart,LPSTR* ppSrcEnd,LPSTR* ppFilename) +{ + ULONG i; // index for walking through STABS + PSTAB_ENTRY pStab; // pointer to STABS + LPSTR pStr,pName; // pointer to STAB strings and current STAB string + int nStabLen; // length of STAB section in bytes + int nOffset=0,nNextOffset=0; // offset and next offset in string table + PICE_SYMBOLFILE_HEADER* pSymbols; // pointer to module's STAB symbol table + static char szCurrentFunction[256]; + static char szCurrentPath[256]; + static char szWantedPath[256]; + LPSTR pFunctionName; // name of function that brackets the current address + ULONG start,end,strLen,ulMinValue=0xFFFFFFFF; + LPSTR pSrcLine=NULL; + BOOLEAN bFirstOccurence = TRUE; + + // lookup the functions name and start-end (external symbols) + pFunctionName = FindFunctionByAddress(addr,&start,&end); + DPRINT((0,"FindSourceLineForAddress: for function: %s\n", pFunctionName)); + + if(pFunctionName) + { + // lookup the modules symbol table (STABS) + pSymbols = FindModuleSymbols(addr); + DPRINT((0,"FindSourceLineForAddress: pSymbols %x\n", pSymbols)); + if(pSymbols) + { + DPRINT((0,"FindSourceLineForAddress: pSymbols->ulNumberOfSrcFiles %x\n", pSymbols->ulNumberOfSrcFiles)); + // no source files so we don't need to lookup anything + if(!pSymbols->ulNumberOfSrcFiles) + return NULL; + + // prepare STABS access + pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); + nStabLen = pSymbols->ulSizeOfStabs; + pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); + + // walk over all STABS + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + // the name string corresponding to the STAB + pName = &pStr[pStab->n_strx + nOffset]; + + // switch STAB type + switch(pStab->n_type) + { + // change offset of name strings + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStab->n_value; + break; + // source file change + case N_SO: + DPRINT((0,"changing source file %s\n",pName)); + // if filename has a length record it + if((strLen = PICE_strlen(pName))) + { + PICE_strcpy(szCurrentPath,pName); + } + // else empty filename + else + { + szCurrentPath[0]=0; + } + break; + // sub-source file change + case N_SOL: + DPRINT((0,"changing sub source file %s\n",pName)); + // if filename has a length record it + if((strLen = PICE_strlen(pName))) + { + PICE_strcpy(szCurrentPath,pName); + } + // else empty filename + else + { + szCurrentPath[0]=0; + } + break; + // a function symbol + case N_FUN: + if(!PICE_strlen(pName)) + {// it's the end of a function + DPRINT((0,"END of function %s\n",szCurrentFunction)); + + szCurrentFunction[0]=0; + + // in case we haven't had a zero delta match we return from here + if(pSrcLine) + return pSrcLine; + + break; + } + else + {// if it has a length it's the start of a function + ULONG len; + // extract the name only, the type string is of no use here + len=StrLenUpToWhiteChar(pName,":"); + PICE_strncpy(szCurrentFunction,pName,len); + szCurrentFunction[len]=0; + + DPRINT((0,"function %s\n",szCurrentFunction)); + } + //intentional fall through + + // line number + case N_SLINE: + // if we're in the function we're looking for + if(szCurrentFunction[0] && PICE_fncmp(szCurrentFunction,pFunctionName)==0) + { + DPRINT((0,"cslnum#%u for addr.%x (fn @ %x) ulMinVal=%x ulDelta=%x\n",pStab->n_desc,start+pStab->n_value,start,ulMinValue,(addr-(start+pStab->n_value)))); + + if(bFirstOccurence) + { + PICE_strcpy(szWantedPath,szCurrentPath); + DPRINT((0,"source file must be %s\n",szWantedPath)); + bFirstOccurence = FALSE; + } + DPRINT((0,"wanted %s, current: %s\n",szWantedPath, szCurrentPath)); + // we might have a match if our address is greater than the one in the STAB + // and we're lower or equal than minimum value + if(addr>=start+pStab->n_value && + (addr-(start+pStab->n_value))<=ulMinValue && + PICE_strcmpi(szWantedPath,szCurrentPath)==0 ) + { + ULONG j; + PICE_SYMBOLFILE_SOURCE* pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pSymbols+pSymbols->ulOffsetToSrcFiles); + + DPRINT((0,"code source line number #%u for addr. %x found!\n",pStab->n_desc,start+pStab->n_value)); + + // compute new minimum + ulMinValue = addr-(start+pStab->n_value); + + // if we have a pointer for storage of line number, store it + if(pulLineNumber) + *pulLineNumber = pStab->n_desc; + + // NB: should put this somewhere else so that it's not done all the time + // if we have source files at all + DPRINT((0,"%u source files @ %x\n",pSymbols->ulNumberOfSrcFiles,pSrc)); + + // for all source files in this module + for(j=0;julNumberOfSrcFiles;j++) + { + LPSTR pSlash; + ULONG currlen, fnamelen; + + currlen = PICE_strlen( szCurrentPath ); + fnamelen = PICE_strlen( pSrc->filename ); + pSlash = pSrc->filename + fnamelen - currlen; + + //DPRINT((0,"pSlash: %s, szCurrentPath: %s\n", pSlash, szCurrentPath)); + // if base name matches current path we have found the correct source file + if(PICE_strcmpi(pSlash,szCurrentPath)==0) + { + // the linenumber + ULONG k = pStab->n_desc; + + DPRINT((0,"found src file %s @ %x\n",pSrc->filename,pSrc)); + + // store the pointer to the filename + if(ppFilename) + *ppFilename = pSrc->filename; + + if(pSrc->ulOffsetToNext > sizeof(PICE_SYMBOLFILE_SOURCE)) + { + // get a pointer to the source file (right after the file header) + pSrcLine = (LPSTR)((ULONG)pSrc+sizeof(PICE_SYMBOLFILE_SOURCE)); + + // store the source start and end address + if(ppSrcStart) + *ppSrcStart = pSrcLine; + if(ppSrcEnd) + *ppSrcEnd = pSrcLine+pSrc->ulOffsetToNext-sizeof(PICE_SYMBOLFILE_SOURCE); + + // goto to the right line + while(--k) + { + while(*pSrcLine!=0 && *pSrcLine!=0x0a && *pSrcLine!=0x0d) + pSrcLine++; + if(!IsAddressValid((ULONG)pSrcLine)) + return NULL; + pSrcLine++; + } + + if(ulMinValue == 0) + return pSrcLine; + } + else + { + DPRINT((0,"src file descriptor found, but contains no source\n")); + } + + break; + } + (ULONG)pSrc += pSrc->ulOffsetToNext; + } + } + } + break; + } + pStab++; + } + } + } + DPRINT((0,"FindSourceLineForAddress: exit 1\n")); + return NULL; +} + +//************************************************************************* +// FindAddressForSourceLine() +// +//************************************************************************* +BOOLEAN FindAddressForSourceLine(ULONG ulLineNumber,LPSTR pFilename,PDEBUG_MODULE pMod,PULONG pValue) +{ + ULONG i; + PSTAB_ENTRY pStab; + LPSTR pStr,pName; + int nStabLen; + int nOffset=0,nNextOffset=0; + PICE_SYMBOLFILE_HEADER* pSymbols; + static char szCurrentFunction[256]; + static char szCurrentPath[256]; + ULONG strLen,addr,ulMinValue=0xFFFFFFFF; + BOOLEAN bFound = FALSE; + + DPRINT((0,"FindAddressForSourceLine(%u,%s,%x)\n",ulLineNumber,pFilename,(ULONG)pMod)); + + addr = (ULONG)pMod->BaseAddress; + + pSymbols = FindModuleSymbols(addr); + if(pSymbols) + { + pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); + nStabLen = pSymbols->ulSizeOfStabs; + pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); + + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + pName = &pStr[pStab->n_strx + nOffset]; + + switch(pStab->n_type) + { + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStab->n_value; + break; + case N_SO: + if((strLen = PICE_strlen(pName))) + { + if(pName[strLen-1]!='/') + { + if(PICE_strlen(szCurrentPath)) + { + PICE_strcat(szCurrentPath,pName); + DPRINT((0,"changing source file %s\n",szCurrentPath)); + } + else + { + DPRINT((0,"changing source file %s\n",pName)); + PICE_strcpy(szCurrentPath,pName); + } + } + else + PICE_strcpy(szCurrentPath,pName); + } + else + { + szCurrentPath[0]=0; + } + break; + case N_SLINE: + // if we're in the function we're looking for + if(PICE_strcmpi(pFilename,szCurrentPath)==0) + { + if(pStab->n_desc>=ulLineNumber && (pStab->n_desc-ulLineNumber)<=ulMinValue) + { + ulMinValue = pStab->n_desc-ulLineNumber; + + DPRINT((0,"code source line number #%u for offset %x in function @ %s)\n",pStab->n_desc,pStab->n_value,szCurrentFunction)); + addr = FindFunctionInModuleByName(szCurrentFunction,pMod); + if(addr) + { + *pValue = addr + pStab->n_value; + bFound = TRUE; + } + } + } + break; + case N_FUN: + if(PICE_strlen(pName)) + { + ULONG len; + + len=StrLenUpToWhiteChar(pName,":"); + PICE_strncpy(szCurrentFunction,pName,len); + szCurrentFunction[len]=0; + DPRINT((0,"function %s\n",szCurrentFunction)); + } + else + { + DPRINT((0,"END of function %s\n",szCurrentFunction)); + szCurrentFunction[0]=0; + } + break; + } + pStab++; + } + } + return bFound; +} + +//************************************************************************* +// ListSymbolStartingAt() +// iterate through the list of module symbols (both functions and variables) +//************************************************************************* +ULONG ListSymbolStartingAt(PDEBUG_MODULE pMod,PICE_SYMBOLFILE_HEADER* pSymbols,ULONG index,LPSTR pOutput) +{ + PIMAGE_SYMBOL pSym, pSymEnd; + LPSTR pStr; + PIMAGE_SECTION_HEADER pShdr; + + DPRINT((0,"ListSymbolStartingAt(%x,%u)\n",(ULONG)pSymbols,index)); + DPRINT((0,"ListSymbolStartingAt(): ulOffsetToGlobals = %x ulSizeofGlobals = %x\n",pSymbols->ulOffsetToGlobals,pSymbols->ulSizeOfGlobals)); + pSym = (PIMAGE_SYMBOL)((ULONG)pSymbols+pSymbols->ulOffsetToGlobals); + pSymEnd = (PIMAGE_SYMBOL)((ULONG)pSym+pSymbols->ulSizeOfGlobals); + pStr = (LPSTR)((ULONG)pSymbols+pSymbols->ulOffsetToGlobalsStrings); + pShdr = (PIMAGE_SECTION_HEADER)((ULONG)pSymbols+pSymbols->ulOffsetToHeaders); + + pSym += index; + + while( pSym < pSymEnd ) + { + LPSTR pName; + + if(((pSym->Type == 0x0) || (pSym->Type == 0x20) ) && + ((pSym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) /*|| (pSym->StorageClass==IMAGE_SYM_CLASS_STATIC)*/) && + (pSym->SectionNumber > 0 )) + { + PIMAGE_SECTION_HEADER pShdrThis = (PIMAGE_SECTION_HEADER)pShdr + (pSym->SectionNumber-1); + ULONG section_flags; + ULONG start; + + DPRINT((0,"ListSymbolStartingAt(): pShdr[%x] = %x\n",pSym->SectionNumber,(ULONG)pShdrThis)); + + if(!IsRangeValid((ULONG)pShdrThis,sizeof(IMAGE_SECTION_HEADER)) ) + { + DPRINT((0,"ListSymbolStartingAt(): pShdr[%x] = %x is not a valid pointer\n",pSym->SectionNumber,(ULONG)pShdrThis)); + return FALSE; + } + section_flags = pShdrThis->Characteristics; + //to get address in the memory we base address of the module and + //add offset of the section and then add offset of the symbol from + //the begining of the section + + start = ((ULONG)pMod->BaseAddress+pShdrThis->VirtualAddress+pSym->Value); + if(pSym->N.Name.Short){ + //name is in the header. it's not zero terminated. have to copy. + PICE_sprintf(pOutput,"%.8X (%s) %.8s\n",start,(section_flags&IMAGE_SCN_CNT_CODE)?"TEXT":"DATA",pSym->N.ShortName); + } + else{ + ASSERT(pSym->N.Name.Long<=pSymbols->ulSizeOfGlobalsStrings); //sanity check + pName = pStr+pSym->N.Name.Long; + if(!IsAddressValid((ULONG)pName)) + { + DPRINT((0,"ListSymbolStartingAt(): pName = %x is not a valid pointer\n",pName)); + return 0; + } + PICE_sprintf(pOutput,"%.8X (%s) %s\n",start,(section_flags&IMAGE_SCN_CNT_CODE)?"TEXT":"DATA",pName); + } + + if((pSym+pSym->NumberOfAuxSymbols+1)<(pSymEnd)) + return (index+pSym->NumberOfAuxSymbols+1); + } + index += pSym->NumberOfAuxSymbols + 1; + pSym += pSym->NumberOfAuxSymbols + 1; + } + return 0; +} + +//************************************************************************* +// SanityCheckExports() +// +//************************************************************************* +BOOLEAN SanityCheckExports(void) +{ + BOOLEAN bResult = FALSE; + ULONG i,ulValue,incr; + + Print(OUTPUT_WINDOW,"pICE: sanity-checking exports...\n"); + return TRUE; + /* fix later!!! do we really need to cross reference two kinds of symbolic info? + if(fake_kernel_module.nsyms && fake_kernel_module.syms) + { + incr = (fake_kernel_module.nsyms/4); + if(!incr)incr = 1; + for(i=0;imagic = %X\n",pSymbols->magic)); + } + //set_fs(oldfs); + + + if(pSymbols->magic == PICE_MAGIC) + { + DPRINT((0,"magic = %X\n",pSymbols->magic)); + DPRINT((0,"name = %S\n",pSymbols->name));; + DPRINT((0,"ulOffsetToHeaders,ulSizeOfHeader = %X,%X\n",pSymbols->ulOffsetToHeaders,pSymbols->ulSizeOfHeader)); + DPRINT((0,"ulOffsetToGlobals,ulSizeOfGlobals = %X,%X\n",pSymbols->ulOffsetToGlobals,pSymbols->ulSizeOfGlobals)); + DPRINT((0,"ulOffsetToGlobalsStrings,ulSizeOfGlobalsStrings = %X,%X\n",pSymbols->ulOffsetToGlobalsStrings,pSymbols->ulSizeOfGlobalsStrings)); + DPRINT((0,"ulOffsetToStabs,ulSizeOfStabs = %X,%X\n",pSymbols->ulOffsetToStabs,pSymbols->ulSizeOfStabs)); + DPRINT((0,"ulOffsetToStabsStrings,ulSizeOfStabsStrings = %X,%X\n",pSymbols->ulOffsetToStabsStrings,pSymbols->ulSizeOfStabsStrings)); + DPRINT((0,"ulOffsetToSrcFiles,ulNumberOfSrcFiles = %X,%X\n",pSymbols->ulOffsetToSrcFiles,pSymbols->ulNumberOfSrcFiles)); + DPRINT((0,"pICE: symbols loaded for module \"%S\" @ %x\n",pSymbols->name,pSymbols)); + apSymbols[ulNumSymbolsLoaded++]=pSymbols; + } + else + { + DPRINT((0,"LoadSymbols(): freeing %x\n",pSymbols)); + DPRINT((0,"pICE: symbols file \"%s\" corrupt\n",filename)); + PICE_free(pSymbols); + } + } + + } + PICE_close(hf); + } + else + { + DPRINT((0,"pICE: could not load symbols for %s...\n",filename)); + } + } + + LEAVE_FUNC(); + + return pSymbols; +} + +//************************************************************************* +// ReloadSymbols() +// +//************************************************************************* +BOOLEAN ReloadSymbols(void) +{ + BOOLEAN bResult; + + ENTER_FUNC(); + + UnloadSymbols(); + + bResult = LoadSymbolsFromConfig(TRUE); + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// UnloadSymbols() +// +//************************************************************************* +void UnloadSymbols() +{ + ULONG i; + + ENTER_FUNC(); + + if(ulNumSymbolsLoaded) + { + for(i=0;i1) + { + if(PICE_strcmpi(temp,"+vga")==0) + { + eTerminalMode = TERMINAL_MODE_VGA_TEXT; + DPRINT((0,"pICE: eTerminalMode = TERMINAL_MODE_VGA_TEXT\n")); + } + else if(PICE_strcmpi(temp,"+hercules")==0) + { + eTerminalMode = TERMINAL_MODE_HERCULES_GRAPHICS; + DPRINT((0,"pICE: eTerminalMode = TERMINAL_MODE_HERCULES_GRAPHICS\n")); + } + else if(PICE_strcmpi(temp,"+serial")==0) + { + eTerminalMode = TERMINAL_MODE_SERIAL; + DPRINT((0,"pICE: eTerminalMode = TERMINAL_MODE_SERIAL\n")); + } + } + else + { + DPRINT((0,"pICE: found option, but no value\n")); + } + } + // comment + else if(*temp == '#') + { + DPRINT((0,"comment out\n")); + } + // symbol file name/path + else + { + DPRINT((0,"Load symbols from file %s\n", temp)); + pSymbols = LoadSymbols(temp); + DPRINT((0,"Load symbols from file %s, pSymbols: %x\n", temp, pSymbols)); + if(pSymbols) + { + PICE_SYMBOLFILE_SOURCE* pSrc; + LPSTR p; + + pSrc = (PICE_SYMBOLFILE_SOURCE*)((ULONG)pSymbols + pSymbols->ulOffsetToSrcFiles); + pCurrentSymbols = pSymbols; + p = strrchr(pSrc->filename,'\\'); + if(p) + { + PICE_strcpy(szCurrentFile,p+1); + } + else + { + PICE_strcpy(szCurrentFile,pSrc->filename); + } + } + } + } + else + { + DPRINT((0,"invalid line [%u] in config!\n",line)); + } + line++; + } + } + else + { + //set_fs(oldfs); + } + } + + PICE_close(hf); + bResult = TRUE; + } + else + { + DPRINT((0,"pICE: config file not found! No symbols loaded.\n")); + DPRINT((0,"pICE: Please make sure to create a file \\systemroot\\symbols\\pice.conf\n")); + DPRINT((0,"pICE: if you want to have symbols for any module loaded.\n")); + } + + LEAVE_FUNC(); + + return bResult; +} + + +//************************************************************************* +// EVALUATION OF EXPRESSIONS +//************************************************************************* + +//************************************************************************* +// SkipSpaces() +// +//************************************************************************* +void SkipSpaces(void) +{ + while(pExpression[ulIndex]==' ') + ulIndex++; +}; + +//************************************************************************* +// FindGlobalStabSymbol() +// +//************************************************************************* +BOOLEAN FindGlobalStabSymbol(LPSTR pExpression,PULONG pValue,PULONG pulTypeNumber,PULONG pulFileNumber) +{ + ULONG i; + PSTAB_ENTRY pStab; + LPSTR pStr,pName; + int nStabLen; + int nOffset=0,nNextOffset=0,nLen,strLen; + PICE_SYMBOLFILE_HEADER* pSymbols; + ULONG ulTypeNumber; + static char SymbolName[1024]; + static char szCurrentPath[256]; + ULONG ulCurrentFileNumber=0; + LPSTR pTypeDefIncluded; + ULONG addr; + + // must have a current module + if(pCurrentMod) + { + // in case we query for the kernel we need to use the fake kernel module + addr = (ULONG)pCurrentMod->BaseAddress; + + // find the symbols for the module + pSymbols = FindModuleSymbols(addr); + if(pSymbols) + { + // prepare table access + pStab = (PSTAB_ENTRY )((ULONG)pSymbols + pSymbols->ulOffsetToStabs); + nStabLen = pSymbols->ulSizeOfStabs; + pStr = (LPSTR)((ULONG)pSymbols + pSymbols->ulOffsetToStabsStrings); + // starting at file 0 + *pulFileNumber = 0; + + // go through stabs + for(i=0;i<(nStabLen/sizeof(STAB_ENTRY));i++) + { + pName = &pStr[pStab->n_strx + nOffset]; + + switch(pStab->n_type) + { + // an N_UNDF symbol marks a change of string table offset + case N_UNDF: + nOffset += nNextOffset; + nNextOffset = pStab->n_value; + break; + // a source file symbol + case N_SO: + if((strLen = PICE_strlen(pName))) + { + if(pName[strLen-1]!='/') + { + ulCurrentFileNumber++; + if(PICE_strlen(szCurrentPath)) + { + PICE_strcat(szCurrentPath,pName); + DPRINT((0,"changing source file %s\n",szCurrentPath)); + } + else + { + DPRINT((0,"changing source file %s\n",pName)); + } + } + else + PICE_strcpy(szCurrentPath,pName); + } + else + { + szCurrentPath[0]=0; + } + break; + case N_GSYM: + case N_LSYM: + case N_PSYM: + // symbol-name:type-identifier type-number = + nLen = StrLenUpToWhiteChar(pName,":"); + PICE_strncpy(SymbolName,pName,nLen); + SymbolName[nLen] = 0; + if(PICE_strcmpi(SymbolName,pExpression)==0) + { + DPRINT((0,"global symbol %s\n",pName)); + // extract type-number from stab + ulTypeNumber = ExtractTypeNumber(pName); + DPRINT((0,"type number = %x, from %s\n",ulTypeNumber, pName)); + *pulTypeNumber = ulTypeNumber; + // look for symbols address in external symbols + if( pStab->n_type == N_LSYM || pStab->n_type == N_PSYM ) + *pValue = CurrentEBP + pStab->n_value; + else *pValue = FindFunctionInModuleByName(SymbolName,pCurrentMod); + + DPRINT((0,"value = %x\n",*pValue)); + *pulFileNumber = ulCurrentFileNumber; + DPRINT((0,"file = %x\n",ulCurrentFileNumber)); + if((pTypeDefIncluded = PICE_strchr(pName,'=')) ) + { + DPRINT((0,"symbol includes type definition (%s)\n",pTypeDefIncluded)); + } + return TRUE; + } + break; + } + pStab++; + } + } + } + return FALSE; +} + +//************************************************************************* +// ExtractToken() +// +//************************************************************************* +void ExtractToken(LPSTR pStringToken) +{ + while(PICE_isalpha(pExpression[ulIndex]) || PICE_isdigit(pExpression[ulIndex]) || pExpression[ulIndex]=='_') + { + *pStringToken++=pExpression[ulIndex++]; + *pStringToken=0; + } +} + +//************************************************************************* +// ExtractTypeName() +// +//************************************************************************* +LPSTR ExtractTypeName(LPSTR p) +{ + static char temp[1024]; + ULONG i; + + DPRINT((1,"ExtractTypeName(%s)\n",p)); + + for(i=0;IsAddressValid((ULONG)p) && *p!=0 && *p!=':';i++,p++) + temp[i] = *p; + + if(!IsAddressValid((ULONG)p) ) + { + DPRINT((1,"hit invalid page %x!\n",(ULONG)p)); + } + + temp[i]=0; + + return temp; +} + +//************************************************************************* +// ExtractNumber() +// +//************************************************************************* +LONG ExtractNumber(LPSTR p) +{ + LONG lMinus = 1,lBase; + ULONG lNumber = 0; + + DPRINT((0,"ExtractNumber(): %s\n",p)); + + if(!IsAddressValid((ULONG)p) ) + { + DPRINT((1,"ExtractNumber(): [1] invalid page %x hit!\n",p)); + return 0; + } + + if(*p == '-') + { + lMinus = -1; + p++; + } + + if(!IsAddressValid((ULONG)p) ) + { + DPRINT((1,"ExtractNumber(): [2] invalid page %x hit!\n",p)); + return 0; + } + + if(*p != '0') // non-octal -> decimal number + lBase = 10; + else + lBase = 8; + + if(!IsAddressValid((ULONG)p) ) + { + DPRINT((1,"ExtractNumber(): [3] invalid page %x hit!\n",p)); + return 0; + } + + while(PICE_isdigit(*p)) + { + lNumber *= lBase; + lNumber += *p-'0'; + p++; + if(!IsAddressValid((ULONG)p) ) + { + DPRINT((1,"ExtractNumber(): [4] invalid page %x hit!\n",p)); + return 0; + } + } + + return (lNumber*lMinus); +} + +//************************************************************************* +// ExtractArray() +// +//************************************************************************* +BOOLEAN ExtractArray(PVRET pvr,LPSTR p) +{ + ULONG index_typenumber,type_number; + ULONG lower_bound,upper_bound; + LPSTR pTypeDef; + + DPRINT((1,"ExtractArray(%s)\n",p)); + + // index-type index-type-number;lower;upper;element-type-number + pvr->bArrayType = TRUE; + p++; + index_typenumber = ExtractTypeNumber(p); + p = PICE_strchr(p,';'); + if(p) + { + p++; + lower_bound = ExtractNumber(p); + p = PICE_strchr(p,';'); + if(p) + { + p++; + + upper_bound = ExtractNumber(p); + p = PICE_strchr(p,';'); + if(p) + { + p++; + + type_number = ExtractTypeNumber(p); + + DPRINT((1,"ExtractArray(): %x %x %x %x\n",index_typenumber,lower_bound,upper_bound,type_number)); + + pTypeDef = FindTypeDefinition(pvr->pSymbols,type_number,pvr->file); + if(pTypeDef) + { + PICE_strcpy(pvr->type_name,ExtractTypeName(pTypeDef)); + pvr->type = type_number; + return TRUE; + } + } + } + } + return FALSE; +} + +//************************************************************************* +// ExtractStructMembers() +// +//************************************************************************* +PVRET ExtractStructMembers(PVRET pvr,LPSTR p) +{ + ULONG len; + static char member_name[128]; + LONG bit_offset,bit_size,type_number,byte_size; + static VRET vr; + LPSTR pTypeDef,pEqual; + + DPRINT((1,"ExtractStructMembers(): %s\n",p)); + + PICE_memset(&vr,0,sizeof(vr)); + + // name:type-number,bit-offset,bit-size + len=StrLenUpToWhiteChar(p,":"); + if(len) + { + // extract member name + PICE_strncpy(member_name,p,len); + member_name[len]=0; + DPRINT((1,"ExtractStructMembers(): member_name = %s\n",member_name)); + + // go to char following ':' + p += (len+1); + if(IsAddressValid((ULONG)p) ) + { + type_number = ExtractTypeNumber(p); + DPRINT((1,"ExtractStructMembers(): type_number = %x\n",type_number)); + + vr.type = type_number; + + pEqual = PICE_strchr(p,')'); + // see if it includes type def + if(pEqual) + { + p = pEqual+1; + if(*p == '=') + { + p++; + if(*p == 'a') + { + DPRINT((1,"ExtractStructMembers(): member is array\n")); + vr.bArrayType = TRUE; + p = PICE_strchr(p,';'); + p = PICE_strchr(p,';'); + p = PICE_strchr(p,';'); + if(p) + p++; + + type_number = ExtractTypeNumber(p); + vr.father_type = type_number; + } + else if(*p == '*') + { + DPRINT((1,"ExtractStructMembers(): member is ptr\n")); + vr.bPtrType = TRUE; + type_number = ExtractTypeNumber(p); + DPRINT((1,"ExtractStructMembers(): type_number = %x\n",type_number)); + vr.father_type = type_number; + } + else if(*p == 'u') + { + DPRINT((1,"ExtractStructMembers(): member is union\n")); + while(*p!=';' && *(p+1)!=';' && *p!=0)p++; + } + } + } + + p = PICE_strchr(p,','); + if(p) + { + p++; + bit_offset = ExtractNumber(p); + DPRINT((1,"ExtractStructMembers(): bit_offset = %x\n",bit_offset)); + p = PICE_strchr(p,','); + if(p) + { + p++; + + bit_size = ExtractNumber(p); + DPRINT((1,"ExtractStructMembers(): bit_size = %x\n",bit_size)); + + vr.address = pvr->value + bit_offset/8; + vr.file = pvr->file; + vr.size = bit_size; + PICE_strcpy(vr.name,member_name); + byte_size = (bit_size+1)/8; + if(!byte_size) + byte_size = 4; + pvr->address = pvr->value; + if(IsRangeValid(vr.address,byte_size)) + { + switch(byte_size) + { + case 1: + vr.value = *(PUCHAR)vr.address; + break; + case 2: + vr.value = *(PUSHORT)vr.address; + break; + case 4: + vr.value = *(PULONG)vr.address; + break; + } + } + + DPRINT((1,"ExtractStructMembers(): member %s type %x bit_offset %x bit_size%x\n",member_name,type_number,bit_offset,bit_size)); + + pTypeDef = FindTypeDefinition(pvr->pSymbols,type_number,pvr->file); + if(pTypeDef) + { + DPRINT((1,"ExtractStructMembers(): pTypedef= %s\n",pTypeDef)); + PICE_strcpy(vr.type_name,ExtractTypeName(pTypeDef)); + pTypeDef = PICE_strchr(pTypeDef,':'); + if(pTypeDef) + { + pTypeDef++; + type_number = ExtractTypeNumber(pTypeDef); + DPRINT((1,"ExtractStructMembers(): type_number = %x\n",type_number)); + vr.father_type = type_number; + } + } + } + } + } + } + + return &vr; +} + +//************************************************************************* +// EvaluateSymbol() +// +//************************************************************************* +BOOLEAN EvaluateSymbol(PVRET pvr,LPSTR pToken) +{ + LPSTR pTypeDef,pTypeName,pTypeBase,pSemiColon,pStructMembers; + BOOLEAN bDone = FALSE; + ULONG ulType,ulBits,ulBytes; + LONG lLowerRange,lUpperRange,lDelta; + static char type_def[2048]; + + DPRINT((1,"EvaluateSymbol(%s)\n",pToken)); + + if(FindGlobalStabSymbol(pToken,&pvr->value,&pvr->type,&pvr->file)) + { + DPRINT((1,"EvaluateSymbol(%s) pvr->value = %x pvr->type = %x\n",pToken,pvr->value,pvr->type)); + while(!bDone) + { + if(!(pTypeDef = FindTypeDefinition(pvr->pSymbols,pvr->type,pvr->file))) + break; + PICE_strcpy(type_def,pTypeDef); + + pTypeDef = type_def; + + pTypeName = ExtractTypeName(pTypeDef); + + DPRINT((1,"%s %s\n",pTypeName,pToken)); + + PICE_strcpy(pvr->type_name,pTypeName); + + pTypeBase = PICE_strchr(pTypeDef,'='); + + if(!pTypeBase) + return FALSE; + + pTypeBase++; + + switch(*pTypeBase) + { + case '(': // type reference + ulType = ExtractTypeNumber(pTypeBase); + DPRINT((1,"%x is a type reference to %x\n",pvr->type,ulType)); + pvr->type = ulType; + break; + case 'r': // subrange + pTypeBase++; + ulType = ExtractTypeNumber(pTypeBase); + DPRINT((1,"%x is sub range of %x\n",pvr->type,ulType)); + if(pvr->type == ulType) + { + DPRINT((1,"%x is a self reference\n",pvr->type)); + pSemiColon = PICE_strchr(pTypeBase,';'); + pSemiColon++; + lLowerRange = ExtractNumber(pSemiColon); + pSemiColon = PICE_strchr(pSemiColon,';'); + pSemiColon++; + lUpperRange = ExtractNumber(pSemiColon); + lDelta = lUpperRange-lLowerRange; + DPRINT((1,"bounds %x-%x range %x\n",lLowerRange,lUpperRange,lDelta)); + ulBits=0; + do + { + ulBits++; + lDelta /= 2; + }while(lDelta); + ulBytes = (ulBits+1)/8; + if(!ulBytes) + ulBytes = 4; + DPRINT((1,"# of bytes = %x\n",ulBytes)); + pvr->address = pvr->value; + if(IsRangeValid(pvr->value,ulBytes)) + { + switch(ulBytes) + { + case 1: + pvr->value = *(PUCHAR)pvr->value; + break; + case 2: + pvr->value = *(PUSHORT)pvr->value; + break; + case 4: + pvr->value = *(PULONG)pvr->value; + break; + } + } + bDone=TRUE; + } + else + pvr->type = ulType; + break; + case 'a': // array type + DPRINT((1,"%x array\n",pvr->type)); + pTypeBase++; + if(!ExtractArray(pvr,pTypeBase)) + { + bDone = TRUE; + pvr->error = 1; + } + break; + case '*': // ptr type + DPRINT((1,"%x is ptr to\n",pvr->type)); + bDone = TRUE; // meanwhile + break; + case 's': // struct type [name:T(#,#)=s#membername1:(#,#),#,#;membername1:(#,#),#,#;;] + // go past 's' + pTypeBase++; + + // extract the the struct size + lLowerRange = ExtractNumber(pTypeBase); + DPRINT((1,"%x struct size = %x\n",pvr->type,lLowerRange)); + + // skip over the digits + while(PICE_isdigit(*pTypeBase)) + pTypeBase++; + + // the structs address is is value + pvr->address = pvr->value; + pvr->bStructType = TRUE; + + // decode the struct members. pStructMembers now points to first member name + pStructMembers = pTypeBase; + + while(pStructMembers && *pStructMembers && *pStructMembers!=';' && ulNumStructMemberstype == vrStructMembers[i].type) + { + PICE_strcpy(pvrThis->type_name,vrStructMembers[i].type_name); + pvrThis->bArrayType = vrStructMembers[i].bArrayType; + pvrThis->bPtrType = vrStructMembers[i].bPtrType; + pvrThis->bStructType = vrStructMembers[i].bStructType; + break; + } + } + } + + DPRINT((1,"EvaluateSymbol(): vr.type_name = %s\n",vrStructMembers[ulNumStructMembers].type_name)); + DPRINT((1,"EvaluateSymbol(): vr.name = %s\n",vrStructMembers[ulNumStructMembers].name)); + DPRINT((1,"EvaluateSymbol(): vr.address = %.8X\n",vrStructMembers[ulNumStructMembers].address)); + DPRINT((1,"EvaluateSymbol(): vr.value = %.8X\n",vrStructMembers[ulNumStructMembers].value)); + DPRINT((1,"EvaluateSymbol(): vr.size = %.8X\n",vrStructMembers[ulNumStructMembers].size)); + DPRINT((1,"EvaluateSymbol(): vr.type = %.8X\n",vrStructMembers[ulNumStructMembers].type)); + + ulNumStructMembers++; + + // skip to next ':' + pStructMembers = PICE_strchr(pStructMembers,';'); + pStructMembers = PICE_strchr(pStructMembers,':'); + if(pStructMembers) + { + DPRINT((1,"EvaluateSymbol(): ptr is now %s\n",pStructMembers)); + // go back to where member name starts + while(*pStructMembers!=';') + pStructMembers--; + // if ';' present, go to next char + if(pStructMembers) + pStructMembers++; + } + } + + bDone = TRUE; // meanwhile + break; + case 'u': // union type + DPRINT((1,"%x union\n",pvr->type)); + bDone = TRUE; // meanwhile + break; + case 'e': // enum type + DPRINT((1,"%x enum\n",pvr->type)); + bDone = TRUE; // meanwhile + break; + default: + DPRINT((1,"DEFAULT %x, base: %c\n",pvr->type, *pTypeBase)); + pvr->address = pvr->value; + if(IsRangeValid(pvr->value,ulBytes)) + { + switch(ulBytes) + { + case 1: + pvr->value = *(PUCHAR)pvr->value; + break; + case 2: + pvr->value = *(PUSHORT)pvr->value; + break; + case 4: + pvr->value = *(PULONG)pvr->value; + break; + } + } + bDone = TRUE; + break; + } + + } + return TRUE; + } + return FALSE; +} + +//************************************************************************* +// Symbol() +// +// Symbol := v +//************************************************************************* +BOOLEAN Symbol(PVRET pvr) +{ + char SymbolToken[128]; + + ExtractToken(SymbolToken); + + DPRINT((1,"SymbolToken = %s\n",SymbolToken)); + + return EvaluateSymbol(pvr,SymbolToken); +} + +//************************************************************************* +// Expression() +// +// Expression := Symbol | Symbol->Symbol +//************************************************************************* +BOOLEAN Expression(PVRET pvr) +{ + if(!Symbol(pvr)) + return FALSE; + + return TRUE; +} + +//************************************************************************* +// Evaluate() +// +//************************************************************************* +void Evaluate(PICE_SYMBOLFILE_HEADER* pSymbols,LPSTR p) +{ + ULONG i; + + PICE_memset(&vr,0,sizeof(vr)); + vr.pSymbols = pSymbols; + + pExpression = p; + ulIndex=0; + ulNumStructMembers=0; + if(Expression(&vr)) + { + DPRINT((1,"\nOK!\n")); + DPRINT((1,"value = %x type = %x\n",vr.value,vr.type)); + if(vr.bStructType) + { + PICE_sprintf(tempSym,"struct %s %s @ %x\n",vr.type_name,p,vr.address); + Print(OUTPUT_WINDOW,tempSym); + for(i=0;i %x (%u)\n", + vrStructMembers[i].address, + vrStructMembers[i].size/8, + vrStructMembers[i].type_name, + vrStructMembers[i].name, + vrStructMembers[i].value, + vrStructMembers[i].value); + } + else + { + PICE_sprintf(tempSym,"[%.8X %.8X] %s %s = %x (%u)\n", + vrStructMembers[i].address, + vrStructMembers[i].size/8, + vrStructMembers[i].type_name, + vrStructMembers[i].name, + vrStructMembers[i].value, + vrStructMembers[i].value); + } + Print(OUTPUT_WINDOW,tempSym); + } + } + else if(vr.bArrayType) + { + Print(OUTPUT_WINDOW,"array\n"); + } + else + { + PICE_sprintf(tempSym,"%s %s @ %x = %x (%u)\n",vr.type_name,p,vr.address,vr.value,vr.value); + Print(OUTPUT_WINDOW,tempSym); + } + } + else + { + DPRINT((1,"\nERROR: code %x\n",vr.error)); + } +} diff --git a/apps/utils/pice/module/symbols.h b/apps/utils/pice/module/symbols.h new file mode 100644 index 0000000..e7d3593 --- /dev/null +++ b/apps/utils/pice/module/symbols.h @@ -0,0 +1,92 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + symbols.h + +Abstract: + + HEADER for symbols.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +// constant defines +#define FIELD_OFFSET(Type,Field) (LONG)(&(((Type *)(0))->Field)) +#define CONTAINING_RECORD(Address,Type,Field) (Type *)(((LONG)Address) - FIELD_OFFSET(Type,Field)) + +typedef struct _LOCAL_VARIABLE +{ + char type_name[64]; + char name[64]; + ULONG value,offset,line; + BOOLEAN bRegister; +}LOCAL_VARIABLE,*PLOCAL_VARIABLE; + + +struct _DEBUG_MODULE_SYMBOL_ +{ + ULONG value; + char* name; +}; + +typedef struct _DEBUG_MODULE_ +{ + struct _DEBUG_MODULE_ *next; + ULONG size; + PVOID BaseAddress; + PVOID EntryPoint; + WCHAR name[DEBUG_MODULE_NAME_LEN]; + struct _DEBUG_MODULE_SYMBOL_ syms; +}DEBUG_MODULE, *PDEBUG_MODULE; + +BOOLEAN InitFakeKernelModule(void); +BOOLEAN LoadExports(void); +BOOLEAN SanityCheckExports(void); +void UnloadExports(void); +BOOLEAN ScanExports(const char *pFind,PULONG pValue); +BOOLEAN ScanExportsByAddress(LPSTR *pFind,ULONG ulValue); +PICE_SYMBOLFILE_HEADER* LoadSymbols(LPSTR filename); +BOOLEAN LoadSymbolsFromConfig(BOOLEAN bIgnoreBootParams); +void UnloadSymbols(void); +BOOLEAN ReloadSymbols(void); +LPSTR FindFunctionByAddress(ULONG ulValue,PULONG pulstart,PULONG pulend); +LPSTR FindSourceLineForAddress(ULONG addr,PULONG pulLineNumber,LPSTR* ppSrcStart,LPSTR* ppSrcEnd,LPSTR* ppFilename); +PLOCAL_VARIABLE FindLocalsByAddress(ULONG addr); +ULONG FindFunctionInModuleByName(LPSTR szFunctionname, PDEBUG_MODULE pMod); +PICE_SYMBOLFILE_HEADER* FindModuleSymbolsByModuleName(LPSTR modname); +BOOLEAN FindAddressForSourceLine(ULONG ulLineNumber,LPSTR pFilename, PDEBUG_MODULE pMod,PULONG pValue); +ULONG ConvertDecimalToUlong(LPSTR p); +PDEBUG_MODULE FindModuleFromAddress(ULONG addr); +PICE_SYMBOLFILE_HEADER* FindModuleSymbols(ULONG addr); +ULONG ListSymbolStartingAt(PDEBUG_MODULE pMod,PICE_SYMBOLFILE_HEADER* pSymbols,ULONG index,LPSTR pOutput); +PDEBUG_MODULE FindModuleByName(LPSTR modname); +void Evaluate(PICE_SYMBOLFILE_HEADER* pSymbols,LPSTR p); +LONG ExtractNumber(LPSTR p); +LPSTR ExtractTypeName(LPSTR p); +PDEBUG_MODULE IsModuleLoaded(LPSTR p); + +//extern ULONG kernel_end; +extern PICE_SYMBOLFILE_HEADER* apSymbols[32]; + +//extern struct module fake_kernel_module; +#define KERNEL_START (0xc0000000) + diff --git a/apps/utils/pice/module/syscall.c b/apps/utils/pice/module/syscall.c new file mode 100644 index 0000000..6236f56 --- /dev/null +++ b/apps/utils/pice/module/syscall.c @@ -0,0 +1,231 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + syscall.c + +Abstract: + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 12-Nov-1999: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +char syscallTemp[1024]; + +typedef struct _FRAME_SYSCALL +{ + ULONG eip; + ULONG cs; + ULONG eflags; +}FRAME_SYSCALL; + +BOOLEAN bReportProcessEvents = TRUE; + +ULONG OldSyscallHandler=0; + +ULONG ulFreeModule=0; + +PDEBUG_MODULE pModJustFreed=NULL; +void (*old_cleanup_module)(void)=NULL; + +void other_module_cleanup_module(void) +{ + DPRINT((0,"other_module_cleanup_module()\n")); + + if(old_cleanup_module) + { + DPRINT((0,"other_module_cleanup_module(): calling %x\n",(ULONG)old_cleanup_module)); + old_cleanup_module(); + } + + if(pModJustFreed) + { + DPRINT((0,"other_module_cleanup_module(): calling RevirtualizeBreakpointsForModule(%x)\n",(ULONG)pModJustFreed)); + RevirtualizeBreakpointsForModule(pModJustFreed); + } +} + +void CSyscallHandler(FRAME_SYSCALL* ptr,ULONG ulSysCall,ULONG ebx) +{ +// DPRINT((0,"CSyscallHandler(): %.4X:%.8X (syscall = %u)\n",ptr->cs,ptr->eip,ulSysCall)); +/* + switch(ulSysCall) + { + case 1: // sys_exit + DPRINT((0,"CSysCallHandler(): 1\n")); + if(bReportProcessEvents) + { + PICE_sprintf(syscallTemp,"pICE: process destroyed \"%s\" PID=%.4X\n",current->comm,current->pid); + AddToRingBuffer(syscallTemp); + } + break; + case 11: // sys_execve + DPRINT((0,"CSysCallHandler(): 11\n")); + if(bReportProcessEvents) + { + if(PICE_strlen((char*)ebx)) + PICE_sprintf(syscallTemp,"pICE: process created \"%s\" PID=%.4X (parent \"%s\")\n",(char *)ebx,current->pid,current->comm); + else + PICE_sprintf(syscallTemp,"pICE: process created PID=%.4X (parent \"%s\")\n",current->pid,current->comm); + AddToRingBuffer(syscallTemp); + } + break; + case 128: // sys_init_module + DPRINT((0,"CSysCallHandler(): 128\n")); + if(PICE_strlen((char *)ebx)) + { + if(pmodule_list) + { + struct module* pMod = *pmodule_list; + do + { + if(PICE_strcmpi((char*)ebx,(LPSTR)pMod->name)==0) + { + ULONG ulInitAddress; + PICE_sprintf(syscallTemp,"pICE: module \"%s\" loaded (%x-%x init @ %x)\n",(char*)ebx,pMod,(ULONG)pMod+pMod->size,pMod->init); + if((ulInitAddress=FindFunctionInModuleByName("init_module",pMod))) + { + DPRINT((0,"setting DR1=%.8x\n",ulInitAddress)); + + SetHardwareBreakPoint(ulInitAddress,1); + } + } + }while((pMod = pMod->next)); + } + else + { + PICE_sprintf(syscallTemp,"pICE: module loaded \"%s\"\n",(char *)ebx); + } + } + else + PICE_sprintf(syscallTemp,"pICE: module loaded\n"); + AddToRingBuffer(syscallTemp); + break; + case 129: // sys_delete_module + DPRINT((0,"CSysCallHandler(): 129\n")); + if(PICE_strlen((char *)ebx)) + { + if(IsModuleLoaded((LPSTR)ebx)!=NULL && PICE_strcmpi((char*)ebx,"pice")!=0 ) + { + PICE_sprintf(syscallTemp,"pICE: module freed \"%s\"\n",(char *)ebx); + Print(OUTPUT_WINDOW,syscallTemp); + if((pModJustFreed = FindModuleByName((char*)ebx)) ) + { + if(pModJustFreed->cleanup) + { + old_cleanup_module = pModJustFreed->cleanup; + pModJustFreed->cleanup = other_module_cleanup_module; + } + else + { + RevirtualizeBreakpointsForModule(pModJustFreed); + } + } + } + } + else + { + PICE_sprintf(syscallTemp,"pICE: module freed\n"); + AddToRingBuffer(syscallTemp); + } + break; + } + */ +} + +__asm__ ("\n\t \ +NewSyscallHandler:\n\t \ + // save used regs\n\t \ + pushfl\n\t \ + cli\n\t \ + cld\n\t \ + pushal\n\t \ + pushl %ds\n\t \ +\n\t \ + // push the syscall number\n\t \ + pushl %ebx\n\t \ + pushl %eax\n\t \ +\n\t \ + // frame ptr\n\t \ + lea 48(%esp),%eax\n\t \ + pushl %eax\n\t \ +\n\t \ + // setup default data selectors\n\t \ + movw %ss,%ax\n\t \ + movw %ax,%ds\n\t \ +\n\t \ + call _CSyscallHandler\n\t \ +\n\t \ + // remove pushed params\n\t \ + add $12,%esp\n\t \ +\n\t \ + // restore used regs\n\t \ + popl %ds\n\t \ + popal\n\t \ + popfl\n\t \ +\n\t \ + // chain to old handler\n\t \ + .byte 0x2e\n\t \ + jmp *_OldSyscallHandler"); + +void InstallSyscallHook(void) +{ + ULONG LocalSyscallHandler; + + ENTER_FUNC(); +/*ei fix later + MaskIrqs(); + if(!OldSyscallHandler) + { + __asm__("mov $NewSyscallHandler,%0" + :"=r" (LocalSyscallHandler) + : + :"eax"); + OldSyscallHandler=SetGlobalInt(0x2e,(ULONG)LocalSyscallHandler); + + ScanExports("free_module",(PULONG)&ulFreeModule); + + DPRINT((0,"InstallSyscallHook(): free_module @ %x\n",ulFreeModule)); + } + UnmaskIrqs(); + */ + LEAVE_FUNC(); +} + +void DeInstallSyscallHook(void) +{ + ENTER_FUNC(); +/*ei + MaskIrqs(); + if(OldSyscallHandler) + { + SetGlobalInt(0x2e,(ULONG)OldSyscallHandler); + (ULONG)OldSyscallHandler=0; + } + UnmaskIrqs(); +*/ + LEAVE_FUNC(); +} diff --git a/apps/utils/pice/module/syscall.h b/apps/utils/pice/module/syscall.h new file mode 100644 index 0000000..f318b20 --- /dev/null +++ b/apps/utils/pice/module/syscall.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + syscall.h + +Abstract: + + HEADER for syscall.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void InstallSyscallHook(void); +void DeInstallSyscallHook(void); + +void CReturnFromSyscallHandler(void); + diff --git a/apps/utils/pice/module/trace.c b/apps/utils/pice/module/trace.c new file mode 100644 index 0000000..89e19a4 --- /dev/null +++ b/apps/utils/pice/module/trace.c @@ -0,0 +1,91 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + trace.c + +Abstract: + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 19-Aug-1998: created + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" + +#include "precomp.h" + +extern void NewInt31Handler(void); + +void DeInstallTraceHook(void); + +volatile ULONG OldInt1Handler=0; + +BOOLEAN InstallTraceHook(void) +{ + ULONG LocalInt1Handler; + + DPRINT((0,"InstallTraceHook(OldInt1Handler=%0.8x)...\n",OldInt1Handler)); + + MaskIrqs(); + if(!OldInt1Handler) + { + __asm__("mov $NewInt1Handler,%0" + :"=r" (LocalInt1Handler) + : + :"eax"); + OldInt1Handler=SetGlobalInt(0x01,(ULONG)LocalInt1Handler); + } + UnmaskIrqs(); + return TRUE; +} + +//this asm function must be at least second in the file. otherwise gcc does not +//generate correct code. +__asm__("\n\t \ +NewInt1Handler:\n\t \ + pushl %eax\n\t \ + movl %dr6,%eax\n\t \ + testl $(1<<14),%eax\n\t \ + jz exceptionnotsinglestep\n\t \ +\n\t \ + popl %eax\n\t \ + pushl $" STR(REASON_SINGLESTEP) "\n\t \ + jmp NewInt31Handler\n\t \ +\n\t \ +exceptionnotsinglestep:\n\t \ + popl %eax\n\t \ + pushl $" STR(REASON_HARDWARE_BP) "\n\t \ + jmp NewInt31Handler\n\t \ +"); + +void DeInstallTraceHook(void) +{ + DPRINT((0,"DeInstallTraceHook(OldInt1Handler=%0.8x)...\n",OldInt1Handler)); + + MaskIrqs(); + if(OldInt1Handler) + { + SetGlobalInt(0x01,(ULONG)OldInt1Handler); + OldInt1Handler = 0; + } + UnmaskIrqs(); +} diff --git a/apps/utils/pice/module/trace.h b/apps/utils/pice/module/trace.h new file mode 100644 index 0000000..28e9369 --- /dev/null +++ b/apps/utils/pice/module/trace.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + trace.h + +Abstract: + + HEADER for trace.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +void DeInstallTraceHook(void); +BOOLEAN InstallTraceHook(void); +void NewInt1Handler(void); + +extern volatile ULONG OldInt1Handler; diff --git a/apps/utils/pice/module/utils.c b/apps/utils/pice/module/utils.c new file mode 100644 index 0000000..7ddc6e5 --- /dev/null +++ b/apps/utils/pice/module/utils.c @@ -0,0 +1,2429 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + util.c + +Abstract: + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 19-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" +#include + + +//////////////////////////////////////////////////// +// GLOBALS +//// +// output string +char tempUtil[1024]; +char tempFlowChanges[256]; + +//PMADDRESS_SPACE my_init_mm=NULL; + +ULONG TwoPagesForPhysMem[2*_PAGE_SIZE]; + +// scancode to ASCII table +SCANTOASCII ucScanToAscii_DE[]= +{ +// German keyboard + {16,'q'},{17,'w'},{18,'e'},{19,'r'},{20,'t'}, + {21,'z'},{22,'u'},{23,'i'},{24,'o'},{25,'p'}, + {30,'a'},{31,'s'},{32,'d'},{33,'f'},{34,'g'}, + {35,'h'},{36,'j'},{37,'k'},{38,'l'}, + {44,'y'},{45,'x'},{46,'c'},{47,'v'},{48,'b'}, + {49,'n'},{50,'m'}, + {2,'1'},{3,'2'},{4,'3'},{ 5,'4'},{ 6,'5'}, + {7,'6'},{8,'7'},{9,'8'},{10,'9'},{11,'0'}, + {12,'ß'}, // 239 = ß + {0x39,' '},{0x35,'-'},{0x34,'.'},{0x1b,'+'}, + {0,0} +}; + +SCANTOASCII ucShiftScanToAscii_DE[]= +{ +// German keyboard SHIFTED + {16,'Q'},{17,'W'},{18,'E'},{19,'R'},{20,'T'}, + {21,'Z'},{22,'U'},{23,'I'},{24,'O'},{25,'P'}, + {30,'A'},{31,'S'},{32,'D'},{33,'F'},{34,'G'}, + {35,'H'},{36,'J'},{37,'K'},{38,'L'}, + {44,'Y'},{45,'X'},{46,'C'},{47,'V'},{48,'B'}, + {49,'N'},{50,'M'}, + {2,'!'},{3,'\"'}, // " // (fixes mc syntax highlighting) + {4,'@'}, // is pragraph sign on keyboard + { 5,'$'},{ 6,'%'}, + {7,'&'},{8,'/'},{9,'('},{10,')'},{11,'='}, + {12,'?'}, + {0x39,' '},{0x35,'_'},{0x34,':'},{0x1b,'*'}, + {0,0} +}; + +SCANTOASCII ucScanToAscii_US[]= +{ +// US keyboard + {16,'q'},{17,'w'},{18,'e'},{19,'r'}, + {20,'t'},{21,'y'},{22,'u'},{23,'i'}, + {24,'o'},{25,'p'},{30,'a'},{31,'s'}, + {32,'d'},{33,'f'},{34,'g'},{35,'h'}, + {36,'j'},{37,'k'},{38,'l'},{44,'z'}, + {45,'x'},{46,'c'},{47,'v'},{48,'b'}, + {49,'n'},{50,'m'},{2,'1'},{3,'2'}, + {4,'3'},{5,'4'},{6,'5'},{7,'6'}, + {8,'7'},{9,'8'},{10,'9'},{11,'0'},{12,'-'}, + {0x39,' '},{0x35,'/'},{0x34,'.'},{0x1b,']'}, + {0x1a,'['},{0x33,','},{0x27,';'},{0x0d,'='}, + {0x2b,'\\'},{0x28,'\''},{0x29,'`'}, + {0,0} +}; + +SCANTOASCII ucShiftScanToAscii_US[]= +{ +// US keyboard SHIFTED + {16,'Q'},{17,'W'},{18,'E'},{19,'R'}, + {20,'T'},{21,'Y'},{22,'U'},{23,'I'}, + {24,'O'},{25,'P'},{30,'A'},{31,'S'}, + {32,'D'},{33,'F'},{34,'G'},{35,'H'}, + {36,'J'},{37,'K'},{38,'L'},{44,'Z'}, + {45,'X'},{46,'C'},{47,'V'},{48,'B'}, + {49,'N'},{50,'M'},{2,'!'},{3,'@'}, + {4,'#'},{5,'$'},{6,'%'},{7,'^'}, + {8,'&'},{9,'*'},{10,'('},{11,')'},{12,'_'}, + {0x39,' '},{0x35,'?'},{0x34,'>'},{0x1b,'}'}, + {0x1a,'{'},{0x33,'<'},{0x27,':'},{0x0d,'+'}, + {0x2b,'|'},{0x28,'\"'},{0x29,'~'}, + {0,0} +}; + + +SCANTOASCII ucScanToAscii_DK[]= +{ +// Danish keyboard + {16,'q'},{17,'w'},{18,'e'},{19,'r'}, + {20,'t'},{21,'y'},{22,'u'},{23,'i'}, + {24,'o'},{25,'p'},{30,'a'},{31,'s'}, + {32,'d'},{33,'f'},{34,'g'},{35,'h'}, + {36,'j'},{37,'k'},{38,'l'},{44,'z'}, + {45,'x'},{46,'c'},{47,'v'},{48,'b'}, + {49,'n'},{50,'m'},{2,'1'},{3,'2'}, + {4,'3'},{5,'4'},{6,'5'},{7,'6'}, + {8,'7'},{9,'8'},{10,'9'},{11,'0'},{12,'+'}, + {0x39,' '},{0x35,'-'},{0x34,'.'},{0x1b,'¨'}, + {0x1a,'å'},{0x33,','},{0x27,'æ'},{0x0d,'´'}, + {0x2b,'\''},{0x28,'ø'},{0x29,' '}, + {0,0} +}; + +SCANTOASCII ucShiftScanToAscii_DK[]= +{ +// Danish keyboard SHIFTED + {16,'Q'},{17,'W'},{18,'E'},{19,'R'}, + {20,'T'},{21,'Y'},{22,'U'},{23,'I'}, + {24,'O'},{25,'P'},{30,'A'},{31,'S'}, + {32,'D'},{33,'F'},{34,'G'},{35,'H'}, + {36,'J'},{37,'K'},{38,'L'},{44,'Z'}, + {45,'X'},{46,'C'},{47,'V'},{48,'B'}, + {49,'N'},{50,'M'},{2,'!'},{3,'"'}, + {4,'#'},{5,'¤'},{6,'%'},{7,'&'}, + {8,'/'},{9,'('},{10,')'},{11,'='},{12,'?'}, + {0x39,' '},{0x35,'_'},{0x34,':'},{0x1b,'^'}, + {0x1a,'Å'},{0x33,';'},{0x27,'Æ'},{0x0d,'`'}, + {0x2b,'*'},{0x28,'Ø'},{0x29,'§'}, + {0,0} +}; + +SCANTOASCII ucAltScanToAscii_DK[]= +{ +// Danish keyboard ALTED + {16,' '},{17,' '},{18,' '},{19,' '}, + {20,' '},{21,' '},{22,' '},{23,' '}, + {24,' '},{25,' '},{30,' '},{31,' '}, + {32,' '},{33,' '},{34,' '},{35,' '}, + {36,' '},{37,' '},{38,' '},{44,' '}, + {45,' '},{46,' '},{47,' '},{48,' '}, + {49,' '},{50,' '},{2,' '},{3,'@'}, + {4,'£'},{5,'$'},{6,'€'},{7,' '}, + {8,'{'},{9,'['},{10,']'},{11,'}'},{12,' '}, + {0x39,' '},{0x35,' '},{0x34,' '},{0x1b,'~'}, + {0x1a,' '},{0x33,' '},{0x27,' '},{0x0d,'|'}, + {0x2b,' '},{0x28,' '},{0x29,' '}, + {0,0} +}; + +KEYBOARD_LAYOUT ucKeyboard[]= +{ + {"de", ucScanToAscii_DE, ucShiftScanToAscii_DE, NULL}, + {"us", ucScanToAscii_US, ucShiftScanToAscii_US, NULL}, + {"dk", ucScanToAscii_DK, ucShiftScanToAscii_DK, ucAltScanToAscii_DK}, + {NULL, NULL, NULL, NULL} +}; + +PKEYBOARD_LAYOUT CurrentKeyboard = NULL; + + +//////////////////////////////////////////////////// +// FUNCTIONS +//// + +//************************************************************************* +// GetKeyboardLayout() +// +//************************************************************************* +PKEYBOARD_LAYOUT GetKeyboardLayout() +{ + if (CurrentKeyboard == NULL) + { + CurrentKeyboard = &ucKeyboard[kbUS]; + } + + return CurrentKeyboard; +} + +//************************************************************************* +// SetKeyboardLayoutByName() +// +//************************************************************************* +PKEYBOARD_LAYOUT SetKeyboardLayoutByName(LPSTR Name) +{ + CHAR tempCmd[256]; + ULONG i; + + for(i=0;ucKeyboard[i].name != NULL;i++) + { + if(PICE_strcmpi(ucKeyboard[i].name, Name) == 0) + { + CurrentKeyboard = &ucKeyboard[i]; + return CurrentKeyboard; + } + } + return GetKeyboardLayout(); +} + +//************************************************************************* +// PICE_memset() +// +//************************************************************************* +void PICE_memset(void* p,unsigned char c,int sz) +{ + unsigned char *p2 = (unsigned char *)p; + while(sz--) + *p2++ = c; +} + +//************************************************************************* +// PICE_memcpy() +// +//************************************************************************* +void PICE_memcpy(void* t,void* s,int sz) +{ + memcpy(t,s,sz); +} + +//************************************************************************* +// PICE_isprint() +// +//************************************************************************* +BOOLEAN PICE_isprint(char c) +{ + BOOLEAN bResult = FALSE; + + if((ULONG)c>=0x20 && (ULONG)c<=0x7f) + bResult = TRUE; + + return bResult; +} + +//************************************************************************* +// PICE_strchr() +// +//************************************************************************* +char* PICE_strchr(char* s,char c) +{ + while(IsAddressValid((ULONG)s) && *s) + { + if(*s == c) + return s; + s++; + } +#ifdef DEBUG + if(!IsAddressValid((ULONG)s) ) + { + DPRINT((0,"PICE_strchr(): ********************\n")); + DPRINT((0,"PICE_strchr(): EXCEPTION @ %.8X\n",(ULONG)s)); + DPRINT((0,"PICE_strchr(): ********************\n")); + } +#endif + + return NULL; +} + +//************************************************************************* +// PICE_strncpy() +// +//************************************************************************* +char* PICE_strncpy(char* s1,char* s2,int len) +{ + ULONG len2 = PICE_strlen(s2); + + if(len='a' && c<='z') + c = (c-'a')+'A'; + + return c; +} + +int PICE_isdigit( int c ) +{ + return ((c>=0x30) && (c<=0x39)); +} + +int PICE_isxdigit( int c ) +{ + return (PICE_isdigit(c) || ((c>=0x41) && (c<=0x46)) || ((c>=0x61) && (c<=0x66))); +} + +int PICE_islower( int c ) +{ + return ((c>=0x61) && (c<=0x7a)); +} + +int PICE_isalpha( int c ) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +} + +//************************************************************************* +// PICE_strncmpi() +// +// my version of strncmpi() +//************************************************************************* +ULONG PICE_strncmpi(char* s1,char* s2,ULONG len) +{ +ULONG result=1; + + while(len && + IsAddressValid((ULONG)s1) && *s1 && // not end of string + IsAddressValid((ULONG)s2) && *s2 && // not end of string + PICE_toupper(*s1)==PICE_toupper(*s2) ) // char are the same except case + { + s1++; + s2++; + len--; + } + // strings same length + if(len==0) + result=0; + + return result; +} + +//************************************************************************* +// PICE_strcmpi() +// +// my version of strcmp() +//************************************************************************* +ULONG PICE_strcmpi(char* s1,char* s2) +{ +ULONG result=1; + + while(IsAddressValid((ULONG)s1) && *s1 && // not end of string + IsAddressValid((ULONG)s2) && *s2 && // not end of string + PICE_toupper(*s1)==PICE_toupper(*s2) ) // char are the same except case + { + s1++; + s2++; + } + // strings same length + if(*s1==0 && *s2==0) + result=0; + + return result; +} + +//************************************************************************* +// PICE_strcmp() +// +// my version of strcmp() +//************************************************************************* +ULONG PICE_strcmp(char* s1,char* s2) +{ + ULONG result=1; + + while(IsAddressValid((ULONG)s1) && *s1 && // not end of string + IsAddressValid((ULONG)s2) && *s2 && // not end of string + (*s1)==(*s2) ) + { + s1++; + s2++; + } + // strings same length + if(*s1==0 && *s2==0) + result=0; + + return result; +} + +//************************************************************************* +// PICE_fncmp() +// +// compare function names ignoring decorations: +// leading '_' or '@" and trailing "@xx" +//************************************************************************* +ULONG PICE_fncmp(char* s1,char* s2) +{ + ULONG result=1; + + if( IsAddressValid((ULONG)s1) && (*s1 == '_' || *s1 == '@')) + s1++; + + if( IsAddressValid((ULONG)s2) && (*s2 == '_' || *s2 == '@')) + s2++; + + while(IsAddressValid((ULONG)s1) && *s1 && // not end of string + IsAddressValid((ULONG)s2) && *s2 ) + { + if( (*s1 != *s2) || *s1=='@' || *s2=='@' ) + break; + s1++; + s2++; + } + // strings same length + if((*s1==0 || *s1=='@') && (*s2==0 || *s2 =='@')){ + result=0; + } + return result; +} + +//************************************************************************* +// PICE_fnncmp() +// +// compare function names ignoring decorations: +// leading '_' or '@" and trailing "@xx" . Decorations are included in total length. +//************************************************************************* +ULONG PICE_fnncmp(char* s1,char* s2, ULONG len) +{ + ULONG result=1; + ULONG len1 = len, len2 = len; + + if( IsAddressValid((ULONG)s1) && (*s1 == '_' || *s1 == '@')){ + s1++; + len1--; + } + + if( IsAddressValid((ULONG)s2) && (*s2 == '_' || *s2 == '@')){ + s2++; + len2--; + } + + while(len1 && len2 && IsAddressValid((ULONG)s1) && *s1 && // not end of string + IsAddressValid((ULONG)s2) && *s2 ) + { + if( (*s1 != *s2) || *s1=='@' || *s2=='@' ) + break; + s1++; + s2++; + len1--; + len2--; + } + // strings are the same length + if((*s1=='\0' || *s1=='@') && (*s2=='\0' || *s2 =='@')){ + result=0; + } + return result; +} + +wchar_t PICE_towlower(wchar_t c) +{ + if ( c>=L'A' && c<=L'Z' ) + return (c - (L'A' - L'a')); + return(c); +} + +ULONG PICE_wcsicmp(WCHAR* s1, WCHAR* s2) +{ + ULONG result=1; + + while(IsAddressValid((ULONG)s1) && *s1 && // not end of string + IsAddressValid((ULONG)s2) && *s2 && // not end of string + PICE_towlower(*s1)==PICE_towlower(*s2) ) // char are the same except case + { + s1++; + s2++; + } + // strings same length + if(*s1==0 && *s2==0) + result=0; + + return result; +} + +//************************************************************************* +// PICE_strrev() +// +// my version of strrev() +//************************************************************************* +char* PICE_strrev(char* s) +{ +ULONG i,j,len=PICE_strlen(s)-1; +char c; + + for(i=0,j=len;i>8)==0) + pAnsi[j]=(char)(pWide[j]); + else + pAnsi[j]=0x20; + } + pAnsi[j]=0; + +} +#endif // LINUX + +//************************************************************************* +// IsAddressValid() +// +//************************************************************************* +BOOLEAN IsAddressValid(ULONG address) +{ + PULONG pPGD; + PULONG pPTE; + BOOLEAN bResult = FALSE; + + address &= (~(_PAGE_SIZE-1)); + + pPGD = ADDR_TO_PDE(address); + if(pPGD && ((*pPGD)&_PAGE_PRESENT)) + { + // not large page + if(!((*pPGD)&_PAGE_4M)) + { + pPTE = ADDR_TO_PTE(address); + if(pPTE) + { + bResult = (*pPTE)&(_PAGE_PRESENT | _PAGE_PSE); + } + } + // large page + else + { + bResult = TRUE; + } + } + + return bResult; +} + + +//************************************************************************* +// IsAddressWriteable() +// +// returns: +// TRUE if adress/page is writeable +// FALSE if adress/page is not writeable +// +//************************************************************************* +BOOLEAN IsAddressWriteable(ULONG address) +{ + PULONG pPGD; + PULONG pPTE; + + //address &= (~(_PAGE_SIZE-1)); + pPGD = ADDR_TO_PDE(address); + if(pPGD && ((*pPGD)&_PAGE_PRESENT)) + { + // not large page + if(!((*pPGD)&_PAGE_4M)) + { + if(!((*pPGD) & _PAGE_RW)) + return FALSE; + + pPTE = ADDR_TO_PTE(address); + if(pPTE) + { + if( ((*pPTE)&(_PAGE_PRESENT | _PAGE_PSE)) && + ((*pPTE) & _PAGE_RW)) + return TRUE; + else + return FALSE; + } + } + // large page + else + return ((*pPGD) & _PAGE_RW); + } + + return FALSE; +} + + +//************************************************************************* +// SetAddressWriteable() +// +//************************************************************************* +BOOLEAN SetAddressWriteable(ULONG address,BOOLEAN bSet) +{ + PULONG pPGD; + PULONG pPTE; + + //address &= (~(_PAGE_SIZE-1)); + + pPGD = ADDR_TO_PDE(address); + if(pPGD && ((*pPGD)&_PAGE_PRESENT)) + { + // not large page + if(!((*pPGD)&_PAGE_4M)) + { + pPTE = ADDR_TO_PTE(address); + if(pPTE) + { + if( (*pPTE)&(_PAGE_PRESENT | _PAGE_PSE) ) + { + if( bSet ){ + *pPTE |= _PAGE_RW; + } + else{ + *pPTE &= ~_PAGE_RW; + } + FLUSH_TLB; + return TRUE; + } + } + } + // large page + else + { + if( bSet ) + *pPGD |= _PAGE_RW; + else + *pPGD &= ~_PAGE_RW; + FLUSH_TLB; + return TRUE; + } + } + return FALSE; +} +//************************************************************************* +// IsRangeValid() +// +// scan range for page present +//************************************************************************* +BOOLEAN IsRangeValid(ULONG Addr,ULONG Length) +{ +ULONG i,NumPages,PageNum; + + // need to only touch one byte per page + // calculate PICE_number of pages to touch + NumPages=(Length+(_PAGE_SIZE-1))>>12; + + // calculate PICE_number of page + PageNum=Addr>>PAGE_SHIFT; + + // touch all pages containing range + for(i=0;i>16))); + + LEAVE_FUNC(); + + return pGdt; +} + +//************************************************************************* +// GetLinearAddress() +// +// return flat address for SEGMENT:OFFSET +//************************************************************************* +ULONG GetLinearAddress(USHORT Segment,ULONG Offset) +{ + PGDT pGdt; + ULONG result=0; + PDESCRIPTOR pSel; + USHORT OriginalSegment=Segment; + + ENTER_FUNC(); + + pSel=(struct tagDESCRIPTOR*)&Segment; + + // get GDT pointer + pGdt=GetGDTPtr(); + DPRINT((0,"GetLinearAddress(): pGDT = %.8X\n",pGdt)); + DPRINT((0,"GetLinearAddress(): original Segment:Offset = %.4X:%.8X\n",Segment,Offset)); + + // see if segment selector is in LDT + if(pSel->Ti) + { + DPRINT((0,"GetLinearAddress(): Segment is in LDT\n")); + // get LDT selector + __asm__("\n\t \ + sldt %%ax\n\t \ + mov %%ax,%0" + :"=m" (Segment)); + if(Segment) + { + DPRINT((0,"GetLinearAddress(): no LDT\n")); + // get LDT selector + pGdt=(PGDT)((pGdt[pSel->Val].Base_31_24<<24)| + (pGdt[pSel->Val].Base_23_16<<16)| + (pGdt[pSel->Val].Base_15_0)); + if(!IsRangeValid((ULONG)pGdt,0x8) ) + pGdt=0; + } + else + { + pGdt=0; + } + } + + if(pGdt && Segment) + { + DPRINT((0,"GetLinearAddress(): Segment:Offset = %.4X:%.8X\n",Segment,Offset)); + result=pGdt[OriginalSegment>>3].Base_15_0| + (pGdt[OriginalSegment>>3].Base_23_16<<16)| + (pGdt[OriginalSegment>>3].Base_31_24<<24); + result+=Offset; + } + DPRINT((0,"GetLinearAddress(%.4X:%.8X)=%.8X\n",OriginalSegment,Offset,result)); + + LEAVE_FUNC(); + + return result; +} + +//************************************************************************* +// ShowRunningMsg() +// +// place RUNNING message +//************************************************************************* +void ShowRunningMsg(void) +{ + ENTER_FUNC(); + + SetForegroundColor(COLOR_TEXT); + SetBackgroundColor(COLOR_CAPTION); + ClrLine(wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + PutChar(" Reactos is running... (Press CTRL-D to stop) ",1,wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + ResetColor(); + + LEAVE_FUNC(); +} + +//************************************************************************* +// ShowStoppedMsg() +// +// place STOPPED message +//************************************************************************* +void ShowStoppedMsg(void) +{ + ENTER_FUNC(); + + SetForegroundColor(COLOR_TEXT); + SetBackgroundColor(COLOR_CAPTION); + ClrLine(wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + PutChar(" Stopped... (Type 'x' to continue) ",1,wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].cy); + ResetColor(); + + LEAVE_FUNC(); +} + +//************************************************************************* +// SetHardwareBreakPoint() +// +//************************************************************************* +void SetHardwareBreakPoint(ULONG ulAddress,ULONG ulReg) +{ + ULONG mask = 0x300; + ULONG enable_mask = 0x3; + + DPRINT((0,"SetHardwareBreakPoint(%x,DR%x)\n",ulAddress,ulReg)); + + enable_mask <<= (ulReg*2); + mask |= enable_mask; + + DPRINT((0,"mask = %x\n",mask)); + + __asm__ __volatile__ + ("\n\t \ + xorl %%eax,%%eax\n\t \ + mov %%eax,%%dr6\n\t \ + mov %%dr7,%%eax\n\t \ + orl %0,%%eax\n\t \ + mov %%eax,%%dr7\n\t \ + " + : + :"m" (mask) + :"eax"); + + switch(ulReg) + { + case 0: + __asm__ __volatile__ + ("\n\t \ + mov %0,%%eax\n\t \ + mov %%eax,%%dr0\n\t \ + " + : + :"m" (ulAddress) + :"eax"); + break; + case 1: + __asm__ __volatile__ + ("\n\t \ + mov %0,%%eax\n\t \ + mov %%eax,%%dr1\n\t \ + " + : + :"m" (ulAddress) + :"eax"); + break; + case 2: + __asm__ __volatile__ + ("\n\t \ + mov %0,%%eax\n\t \ + mov %%eax,%%dr2\n\t \ + " + : + :"m" (ulAddress) + :"eax"); + break; + case 3: + __asm__ __volatile__ + ("\n\t \ + mov %0,%%eax\n\t \ + mov %%eax,%%dr3\n\t \ + " + : + :"m" (ulAddress) + :"eax"); + break; + } +} + +//************************************************************************* +// SetHardwareBreakPoints() +// +// install HW breakpoints +//************************************************************************* +void SetHardwareBreakPoints(void) +{ +ULONG i; +ULONG mask; +ULONG LinAddr0,LinAddr1,LinAddr2,LinAddr3; +PULONG LinAddr[4]={&LinAddr0,&LinAddr1,&LinAddr2,&LinAddr3}; + + ENTER_FUNC(); + + // cancel all debug activity + __asm__("\n\t \ + pushl %eax\n\t \ + xorl %eax,%eax\n\t \ + mov %eax,%dr6\n\t \ + mov %eax,%dr7\n\t \ + popl %eax"); + // build DR7 mask + for(mask=0,i=0;i<4;i++) + { + mask<<=2; + if(Bp[i].Active && Bp[i].Used && !Bp[i].Virtual) + { + mask|=0x03; + *LinAddr[3-i]=Bp[i].LinearAddress; + DPRINT((0,"breakpoint %u at %.8X\n",i,Bp[i].LinearAddress)); + } + } + if(mask) + { + __asm__("\n\t \ + pushl %%eax\n\t \ + movl %0,%%eax\n\t \ + andl $0x000000FF,%%eax\n\t \ + orl $0x300,%%eax\n\t \ + mov %%eax,%%dr7\n\t \ + mov %1,%%eax\n\t \ + mov %%eax,%%dr0\n\t \ + mov %2,%%eax\n\t \ + mov %%eax,%%dr1\n\t \ + mov %3,%%eax\n\t \ + mov %%eax,%%dr2\n\t \ + mov %4,%%eax\n\t \ + mov %%eax,%%dr3\n\t \ + popl %%eax" + : + :"m" (mask),"m" (LinAddr0),"m" (LinAddr1),"m" (LinAddr2),"m" (LinAddr3)); + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// IsCallInstrAtEIP() +// +// check if instruction at CS:EIP changes program flow +//************************************************************************* +BOOLEAN IsCallInstrAtEIP(void) +{ +PUCHAR linear; +BOOLEAN result=FALSE; + + ENTER_FUNC(); + DPRINT((0,"IsCallInstrAtEIP()\n")); + + linear=(PUCHAR)GetLinearAddress(CurrentCS,CurrentEIP); + if(IsRangeValid((ULONG)linear,2)) + { + if(*linear== 0xE8 || // call + (*linear== 0xFF && ( ((*(linear+1)>>3)&0x7)==0x2 || ((*(linear+1)>>3)&0x7)==0x3) ) || // call + *linear== 0x9A || // call + *linear== 0xF2 || // REP + *linear== 0xF3) // REP + result=TRUE; + } + + LEAVE_FUNC(); + + return result; +} + + +//************************************************************************* +// IsRetAtEIP() +// +// check if instruction at CS:EIP is a return instruction +//************************************************************************* +BOOLEAN IsRetAtEIP(void) +{ + PUCHAR linear; + BOOLEAN bResult = FALSE; + + ENTER_FUNC(); + DPRINT((0,"IsRetAtEIP()\n")); + + linear=(PUCHAR)GetLinearAddress(CurrentCS,CurrentEIP); + + switch(*linear) + { + case 0xc2: + case 0xc3: + case 0xca: + case 0xcb: + case 0xcf: // IRET/IRETD + bResult = TRUE; + break; + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// VisualizeFlags() +// +// display CPU EFLAGS as string +//************************************************************************* +LPSTR VisualizeFlags(ULONG EFlags) +{ + static UCHAR FlagNames[]={'c',0,'p',0,'a',0,'z','s','t','i','d','o'}; + ULONG i,j; + static char temp[32]; + + for(j=0,i=0;i>=1; + } + temp[j]=0; + PICE_strrev(temp); + return temp; +} + +//************************************************************************* +// DisplayRegs() +// +// display CPU registers +//************************************************************************* +void DisplayRegs(void) +{ + char tempDisplayRegs[48]; + + ENTER_FUNC(); + +// Clear(REGISTER_WINDOW); + Home(REGISTER_WINDOW); + // EAX + Print(REGISTER_WINDOW,"EAX="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentEAX); + if(OldEAX!=CurrentEAX) + { + SetForegroundColor(WHITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEAX!=CurrentEAX) + { + ResetColor(); + } + + // EBX + Print(REGISTER_WINDOW," EBX="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentEBX); + if(OldEBX!=CurrentEBX) + { + SetForegroundColor(WHITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEBX!=CurrentEBX) + { + ResetColor(); + } + + // ECX + Print(REGISTER_WINDOW," ECX="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentECX); + if(OldECX!=CurrentECX) + { + SetForegroundColor(WHITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldECX!=CurrentECX) + { + ResetColor(); + } + + // EDX + Print(REGISTER_WINDOW," EDX="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentEDX); + if(OldEDX!=CurrentEDX) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEDX!=CurrentEDX) + { + ResetColor(); + } + + // ESI + Print(REGISTER_WINDOW," ESI="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentESI); + if(OldESI!=CurrentESI) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldESI!=CurrentESI) + { + ResetColor(); + } + + // EDI + Print(REGISTER_WINDOW," EDI="); + PICE_sprintf(tempDisplayRegs,"%.8X\n",CurrentEDI); + if(OldEDI!=CurrentEDI) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEDI!=CurrentEDI) + { + ResetColor(); + } + + // EBP + Print(REGISTER_WINDOW,"EBP="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentEBP); + if(OldEBP!=CurrentEBP) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEBP!=CurrentEBP) + { + ResetColor(); + } + + // ESP + Print(REGISTER_WINDOW," ESP="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentESP); + if(OldESP!=CurrentESP) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldESP!=CurrentESP) + { + ResetColor(); + } + + // EIP + Print(REGISTER_WINDOW," EIP="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentEIP); + if(OldEIP!=CurrentEIP) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEIP!=CurrentEIP) + { + ResetColor(); + } + + // EFL + Print(REGISTER_WINDOW," EFLAGS="); + PICE_sprintf(tempDisplayRegs,"%.8X",CurrentEFL); + if(OldEFL!=CurrentEFL) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldEFL!=CurrentEFL) + { + ResetColor(); + } + + // visual flags + PICE_sprintf(tempDisplayRegs," %s\n",VisualizeFlags(CurrentEFL)); + Print(REGISTER_WINDOW,tempDisplayRegs); + + // CS + Print(REGISTER_WINDOW,"CS="); + PICE_sprintf(tempDisplayRegs,"%.4X",CurrentCS); + if(OldCS!=CurrentCS) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldCS!=CurrentCS) + { + ResetColor(); + } + + // DS + Print(REGISTER_WINDOW," DS="); + PICE_sprintf(tempDisplayRegs,"%.4X",CurrentDS); + if(OldDS!=CurrentDS) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldDS!=CurrentDS) + { + ResetColor(); + } + + // ES + Print(REGISTER_WINDOW," ES="); + PICE_sprintf(tempDisplayRegs,"%.4X",CurrentES); + if(OldES!=CurrentES) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldES!=CurrentES) + { + ResetColor(); + } + + // FS + Print(REGISTER_WINDOW," FS="); + PICE_sprintf(tempDisplayRegs,"%.4X",CurrentFS); + if(OldFS!=CurrentFS) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldFS!=CurrentFS) + { + ResetColor(); + } + + // GS + Print(REGISTER_WINDOW," GS="); + PICE_sprintf(tempDisplayRegs,"%.4X",CurrentGS); + if(OldGS!=CurrentGS) + { + ResetColor(); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldGS!=CurrentGS) + { + ResetColor(); + } + + // SS + Print(REGISTER_WINDOW," SS="); + PICE_sprintf(tempDisplayRegs,"%.4X",CurrentSS); + if(OldSS!=CurrentSS) + { + SetForegroundColor(COLOR_HILITE); + } + Print(REGISTER_WINDOW,tempDisplayRegs); + if(OldSS!=CurrentSS) + { + ResetColor(); + } + + LEAVE_FUNC(); +} + +//************************************************************************* +// SaveOldRegs() +// +//************************************************************************* +void SaveOldRegs(void) +{ + + ENTER_FUNC(); + + OldEAX=CurrentEAX; + OldEBX=CurrentEBX; + OldECX=CurrentECX; + OldEDX=CurrentEDX; + OldESI=CurrentESI; + OldEDI=CurrentEDI; + OldEBP=CurrentEBP; + OldESP=CurrentESP; + OldEIP=CurrentEIP; + OldEFL=CurrentEFL; + OldCS=CurrentCS; + OldDS=CurrentDS; + OldES=CurrentES; + OldFS=CurrentFS; + OldGS=CurrentGS; + OldSS=CurrentSS; + + LEAVE_FUNC(); +} + +//************************************************************************* +// GetKeyStatus() +// +//************************************************************************* +UCHAR GetKeyStatus(void) +{ + UCHAR ucRet; + ucRet = inb_p((PUCHAR)(I8042_PHYSICAL_BASE + I8042_STATUS_REGISTER_OFFSET)); + return ucRet; +} + +//************************************************************************* +// GetKeyData() +// +//************************************************************************* +UCHAR GetKeyData(void) +{ + UCHAR ucRet; + ucRet = inb_p((PUCHAR)(I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET)); + return ucRet; +} + +//************************************************************************* +// GetKeyPolled +// +//************************************************************************* +UCHAR KeyboardGetKeyPolled(void) +{ + UCHAR ucKey; + UCHAR ucStatus; + static BOOLEAN bExtended = FALSE; + + while(ucKey=0,(ucStatus=GetKeyStatus())&OUTPUT_BUFFER_FULL) + { + ucKey = 0; + ucKey = GetKeyData(); + + if(ucStatus&MOUSE_OUTPUT_BUFFER_FULL) + continue; + + DPRINT((1,"GetKeyPolled(): key = %x bExtended=%s\n",ucKey,bExtended?"TRUE":"FALSE")); + + if(SCANCODE_EXTENDED == ucKey) + { + DPRINT((1,"extended switched ON\n")); + bExtended = TRUE; + continue; + } + else + { + if(!(ucKey&0x80)) // keypress + { + switch(ucKey&0x7f) + { + case SCANCODE_L_CTRL: + case SCANCODE_R_CTRL: + if(!bExtended) + bControl=TRUE; + break; + case SCANCODE_L_SHIFT: + case SCANCODE_R_SHIFT: + if(!bExtended) + bShift=TRUE; + break; + case SCANCODE_L_ALT: + case SCANCODE_R_ALT: + if(!bExtended) + bAlt=TRUE; + break; + default: + DPRINT((0,"GetKeyPolled(): control = %u shift = %u alt = %u\n",bControl,bShift,bAlt)); + return ucKey; + } + } + else + { + switch(ucKey&0x7f) + { + case SCANCODE_L_CTRL: + case SCANCODE_R_CTRL: + if(!bExtended) + bControl=FALSE; + break; + case SCANCODE_L_SHIFT: + case SCANCODE_R_SHIFT: + if(!bExtended) + bShift=FALSE; + break; + case SCANCODE_L_ALT: + case SCANCODE_R_ALT: + if(!bExtended) + bAlt=FALSE; + break; + } + } + } + bExtended=FALSE; + } + + return ucKey; +} + +//************************************************************************* +// KeyboardFlushKeyboardQueue() +// +//************************************************************************* +void KeyboardFlushKeyboardQueue(void) +{ + //__udelay(10); + KeStallExecutionProcessor(10); + while(GetKeyStatus()&OUTPUT_BUFFER_FULL) + { + GetKeyData(); + //__udelay(10); + KeStallExecutionProcessor(10); + } +} + +//************************************************************************* +// CheckLoadAbort() +// +//************************************************************************* +BOOLEAN CheckLoadAbort(void) +{ +ULONG i; +UCHAR ucKey; + + MaskIrqs(); + + SaveGraphicsState(); + + FlushKeyboardQueue(); + + PrintLogo(TRUE); + + for(i=0;i<5000;i++) + { + if(!(i%1000) ) + { + PICE_sprintf(tempUtil,"\n LOAD WILL CONTINUE IN %u SEC (HIT 'C' TO CONTINUE OR ANY OTHER KEY TO ABORT)\n",5-i/1000); + Clear(REGISTER_WINDOW); + Print(REGISTER_WINDOW,tempUtil); + PrintLogo(TRUE); + } + + ucKey = GetKeyPolled(); + + if(ucKey) + { + if((ucKey&0x7f)!=46) + { + RestoreGraphicsState(); + UnmaskIrqs(); + return FALSE; + } + else + goto load; + } + KeStallExecutionProcessor(1000); + } +load: + Clear(REGISTER_WINDOW); + PrintLogo(TRUE); + + tempUtil[0] = 0; + FlushKeyboardQueue(); + + RestoreGraphicsState(); + + UnmaskIrqs(); + + return TRUE; +} + + + + +//************************************************************************* +// IntelStackWalk() +// +//************************************************************************* +void IntelStackWalk(ULONG pc,ULONG ebp,ULONG esp) +{ + PULONG pFrame, pPrevFrame; + LPSTR pSymbolName; + + DPRINT((0,"IntelStackWalk(): pc = %X ebp = %X esp = %X\n",pc,ebp,esp)); + + pFrame = pPrevFrame = (PULONG)ebp; + + PutStatusText("EIP FRAME NAME\n"); + while(1) + { + DPRINT((0,"IntelStackWalk(): pFrame = %X pPrevFrame = %X pc =%X\n",(ULONG)pFrame,(ULONG)pPrevFrame,pc)); + if ( ( (ULONG)pFrame & 3 ) || + ( (pFrame <= pPrevFrame) ) ) + { + DPRINT((0,"IntelStackWalk(): pFrame is either unaligned or not less than previous\n")); + if( !IsRangeValid((ULONG)pFrame, sizeof(PVOID)*2) ) + { + DPRINT((0,"IntelStackWalk(): pFrame not valid pointer!\n")); + break; + } + } + + if((pSymbolName = FindFunctionByAddress(pc,NULL,NULL)) ) + PICE_sprintf(tempUtil,"%08X %08X %s\n",pc, (ULONG)pFrame,pSymbolName); + else + PICE_sprintf(tempUtil,"%08X %08X\n",pc, (ULONG)pFrame); + Print(OUTPUT_WINDOW,tempUtil); + if(WaitForKey()==FALSE)break; + + pc = pFrame[1]; + + pPrevFrame = pFrame; + + pFrame = (PULONG)pFrame[0]; // proceed to next higher frame on stack + } +} + +//************************************************************************* +// FindPteForLinearAddress() +// +//************************************************************************* +PULONG FindPteForLinearAddress(ULONG address) +{ + PULONG pPGD; + PULONG pPTE; + BOOLEAN bResult = FALSE; + PEPROCESS my_current = IoGetCurrentProcess(); + + ENTER_FUNC(); + + address &= (~(_PAGE_SIZE-1)); + + if(my_current) + { + pPGD = ADDR_TO_PDE(address); + if(pPGD && ((*pPGD)&_PAGE_PRESENT)) + { + // not large page + if(!((*pPGD)&_PAGE_4M)) + { + pPTE = ADDR_TO_PTE(address); + if(pPTE) + { + LEAVE_FUNC(); + return pPTE; + } + } + // large page + else + { + LEAVE_FUNC(); + return NULL; + } + } + } + + LEAVE_FUNC(); + return NULL; +} + +//************************************************************************* +// InvalidateLB() +// +//************************************************************************* +void InvalidateLB(void) +{ + ENTER_FUNC(); + __asm__ __volatile__ + ( + "wbinvd\n\t \ + mov %%cr3,%%ecx\n\t \ + mov %%ecx,%%cr3" + :::"ecx" + ); + LEAVE_FUNC(); +} + +//************************************************************************* +// ReadPhysMem() +// +//************************************************************************* +ULONG ReadPhysMem(ULONG Address,ULONG ulSize) +{ + ULONG Page = ((ULONG)TwoPagesForPhysMem+_PAGE_SIZE)&~(_PAGE_SIZE-1); + PULONG pPTE; + ULONG temp = 0; + ULONG oldPTE; + + ENTER_FUNC(); + DPRINT((0,"ReadPhysMem(%.8X,%u)\n",Address,ulSize)); + DPRINT((0,"ReadPhysMem(): Page = %.8X\n",Page)); + pPTE = (PULONG)FindPteForLinearAddress(Page); + DPRINT((0,"ReadPhysMem(): pPTE = %.8X\n",pPTE)); + if(pPTE) + { + oldPTE = *pPTE; + DPRINT((0,"ReadPhysMem(): oldPTE = %.8X\n",oldPTE)); + temp = (Address & ~(_PAGE_SIZE-1)); + DPRINT((0,"ReadPhysMem(): page-aligned Address = %.8X\n",temp)); + *pPTE = temp|0x1; + DPRINT((0,"ReadPhysMem(): new PTE = %.8X\n",*pPTE)); + InvalidateLB(); + switch(ulSize) + { + case sizeof(UCHAR): // BYTE + temp = *(PUCHAR)(Page + (Address & (_PAGE_SIZE-1))); + temp = (UCHAR)temp; + break; + case sizeof(USHORT): // WORD + temp = *(PUSHORT)(Page + (Address & (_PAGE_SIZE-1))); + temp = (USHORT)temp; + break; + case sizeof(ULONG): // DWORD + temp = *(PULONG)(Page + (Address & (_PAGE_SIZE-1))); + break; + } + *pPTE = oldPTE; + InvalidateLB(); + } + LEAVE_FUNC(); + + return temp; +} + +//************************************************************************* +// WritePhysMem() +// +//************************************************************************* +void WritePhysMem(ULONG Address,ULONG Datum,ULONG ulSize) +{ + ULONG Page = ((ULONG)TwoPagesForPhysMem+_PAGE_SIZE)&~(_PAGE_SIZE-1); + PULONG pPTE; + ULONG temp; + ULONG oldPTE; + + pPTE = (PULONG)FindPteForLinearAddress(Page); + if(pPTE) + { + oldPTE = *pPTE; + temp = (Address & ~(_PAGE_SIZE-1)); + *pPTE = temp | 0x3; // present and writable + InvalidateLB(); + switch(ulSize) + { + case sizeof(UCHAR): // BYTE + *(PUCHAR)(Page + (Address & (_PAGE_SIZE-1))) = (UCHAR)Datum; + break; + case sizeof(USHORT): // WORD + *(PUSHORT)(Page + (Address & (_PAGE_SIZE-1))) = (USHORT)Datum; + break; + case sizeof(ULONG): // DWORD + *(PULONG)(Page + (Address & (_PAGE_SIZE-1))) = Datum; + break; + } + *pPTE = oldPTE; + InvalidateLB(); + } +} + +///////////////////////////////////////////////////////////////////////////// +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && PICE_isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (PICE_isxdigit(*cp) && (value = PICE_isdigit(*cp) ? *cp-'0' : (PICE_islower(*cp) + ? PICE_toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} + +/* we use this so that we can do without the ctype library */ +#define is_digit(c) ((c) >= '0' && (c) <= '9') + +static int skip_atoi(const char **s) +{ + int i=0; + + while (is_digit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +size_t PICE_strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && IsAddressValid((ULONG)sc) && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + + +#define NUM_ZEROPAD 1 /* pad with zero */ +#define NUM_SIGN 2 /* unsigned/signed long */ +#define NUM_PLUS 4 /* show plus */ +#define NUM_SPACE 8 /* space if plus */ +#define NUM_LEFT 16 /* left justified */ +#define NUM_SPECIAL 32 /* 0x */ +#define NUM_LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long) n) % (unsigned) base; \ +n = ((unsigned long) n) / (unsigned) base; \ +__res; }) + +static char * PICE_number(char * str, long num, int base, int size, int precision + ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & NUM_LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & NUM_LEFT) + type &= ~NUM_ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & NUM_ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & NUM_SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & NUM_PLUS) { + sign = '+'; + size--; + } else if (type & NUM_SPACE) { + sign = ' '; + size--; + } + } + if (type & NUM_SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(NUM_ZEROPAD+NUM_LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & NUM_SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & NUM_LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + return str; +} + +/* Forward decl. needed for IP address printing stuff... */ +int PICE_sprintf(char * buf, const char *fmt, ...); + +int PICE_vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + unsigned long num; + int i, base; + char * str; + const char *s; + const wchar_t *sw; + + int flags; /* flags to PICE_number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + PICE_number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= NUM_LEFT; goto repeat; + case '+': flags |= NUM_PLUS; goto repeat; + case ' ': flags |= NUM_SPACE; goto repeat; + case '#': flags |= NUM_SPECIAL; goto repeat; + case '0': flags |= NUM_ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= NUM_LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & NUM_LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + + len = PICE_strnlen(s, precision); + + if (!(flags & NUM_LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = PICE_strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & NUM_LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & NUM_LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = (unsigned char)(*sw++); + while (len < field_width--) + *str++ = ' '; + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= NUM_ZEROPAD; + } + str = PICE_number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + *str++ = '%'; + continue; + + /* integer PICE_number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= NUM_LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= NUM_SIGN; + case 'u': + break; + + default: + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } + if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & NUM_SIGN) + num = (short) num; + } else if (flags & NUM_SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + str = PICE_number(str, num, base, field_width, precision, flags); + } + *str = '\0'; + return str-buf; +} + +int PICE_sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = PICE_vsprintf(buf,fmt,args); + va_end(args); + return i; +} + +//************************************************************************* +// AsciiFromScan() +// +// Convert Scancode to ASCII +//************************************************************************* +UCHAR AsciiFromScan(UCHAR s) +{ + PSCANTOASCII table; + ULONG i; + + ENTER_FUNC(); + + if (bShift) + { + table = GetKeyboardLayout()->shifted; + } + else if(bAlt) + { + table = GetKeyboardLayout()->alted; + } + else + { + table = GetKeyboardLayout()->normal; + } + + + if (table) + { + for(i=0;table[i].s != 0;i++) + { + if(table[i].s==s) + { + LEAVE_FUNC(); + return table[i].a; + } + } + } + + DPRINT((0,"AsciiFromScan(): no translation for key\n")); + LEAVE_FUNC(); + return 0; +} + + +//************************************************************************* +// AsciiToScan() +// +// Convert Scancode to ASCII +//************************************************************************* +UCHAR AsciiToScan(UCHAR s) +{ + PSCANTOASCII table; + ULONG i; + + ENTER_FUNC(); + + if (bShift) + { + table = GetKeyboardLayout()->shifted; + } + else if(bAlt) + { + table = GetKeyboardLayout()->alted; + } + else + { + table = GetKeyboardLayout()->normal; + } + + if (table) + { + for(i=0;table[i].s != 0;i++) + { + if(table[i].a==s) + { + LEAVE_FUNC(); + return table[i].s; + } + } + } + + DPRINT((0,"AsciiToScan(): no translation for ASCII code\n")); + LEAVE_FUNC(); + return 0; +} + +//************************************************************************ +// outportb() +// +//************************************************************************ +void outportb(PUCHAR port,UCHAR data) +{ + WRITE_PORT_UCHAR((PUCHAR)port, data); +} + +void outb_p(UCHAR data, PUCHAR port) +{ + WRITE_PORT_UCHAR((PUCHAR)port, data); +} + +VOID outl(ULONG data, PULONG port) +{ + WRITE_PORT_ULONG(port, data); +} + + +//************************************************************************ +// inportb() +// +//************************************************************************ +UCHAR inportb(PUCHAR port) +{ + return READ_PORT_UCHAR((PUCHAR)port); +} + +UCHAR inb_p(PUCHAR port) +{ + return READ_PORT_UCHAR((PUCHAR)port); +} + +ULONG inl(PULONG port) +{ + return READ_PORT_ULONG(port); +} + +//************************************************************************* +// EnablePassThrough() +// +// enable MDA passthrough on AGP chipset +//************************************************************************* +void EnablePassThrough(void) +{ + ULONG oldCF8,flags; + + save_flags(flags); + cli(); + + oldCF8 = inl((PULONG)0xcf8); + outl(0x80000050,(PULONG)0xcf8); + outl(inl((PULONG)0xcfc)|0x00000020,(PULONG)0xcfc); + outl(oldCF8,(PULONG)0xcf8); + + restore_flags(flags); +} + +//*********************************************************************************** +// Pice_malloc - allocate memory from paged or non-paged pool +//*********************************************************************************** +void * PICE_malloc( size_t numBytes, BOOLEAN fromPaged ) +{ + void* res = ExAllocatePool( (fromPaged)?PagedPool:NonPagedPool, numBytes ); + ASSERT(res); + return res; +} + +//*********************************************************************************** +// PICE_free - free memory allocated by PICE_malloc +//*********************************************************************************** +void PICE_free( void* p ) +{ + ASSERT( p ); + ExFreePool( p ); +} + +long PICE_read(HANDLE hFile, LPVOID lpBuffer, long lBytes) +{ + DWORD NumberOfBytesRead; + IO_STATUS_BLOCK iosb; + + ASSERT( lpBuffer ); + + if (!NT_SUCCESS(NtReadFile( + (HANDLE) hFile, + NULL, NULL, NULL, &iosb, + (LPVOID) lpBuffer, + (DWORD) lBytes, + NULL, + NULL + ))) + { + return -1; + } + NumberOfBytesRead = iosb.Information; + return NumberOfBytesRead; +} + +HANDLE PICE_open (LPCWSTR lpPathName, int iReadWrite) +{ + DWORD dwAccessMask = 0; + DWORD dwShareMode = 0; + UNICODE_STRING TmpFileName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hfile; + NTSTATUS status; + + + DPRINT((0,"PICE_open: %S\n", lpPathName)); + + if ( (iReadWrite & OF_READWRITE ) == OF_READWRITE ) + dwAccessMask = GENERIC_READ | GENERIC_WRITE; + else if ( (iReadWrite & OF_READ ) == OF_READ ) + dwAccessMask = GENERIC_READ; + else if ( (iReadWrite & OF_WRITE ) == OF_WRITE ) + dwAccessMask = GENERIC_WRITE; + + if ((iReadWrite & OF_SHARE_COMPAT) == OF_SHARE_COMPAT ) + dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_DENY_NONE) == OF_SHARE_DENY_NONE) + dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_DENY_READ) == OF_SHARE_DENY_READ) + dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_DENY_WRITE) == OF_SHARE_DENY_WRITE ) + dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_EXCLUSIVE) == OF_SHARE_EXCLUSIVE) + dwShareMode = 0; + + RtlInitUnicodeString (&TmpFileName, lpPathName); + InitializeObjectAttributes(&ObjectAttributes, + &TmpFileName, + 0, + NULL, + NULL); + + status = NtOpenFile( &hfile, + dwAccessMask, + &ObjectAttributes, + NULL, dwShareMode, FILE_NO_INTERMEDIATE_BUFFERING); + //BUG BUG check status!!! + if( !NT_SUCCESS( status ) ){ + DPRINT((0,"PICE_open: NtOpenFile error: %x\n", status)); + return 0; + } + return hfile; +} + +int PICE_close (HANDLE hFile) +{ + if (NT_SUCCESS( ZwClose((HANDLE)hFile))) + { + return 0; + } + DPRINT((0,"ZwClose failed:\n")); + return -1; +} + +size_t PICE_len( HANDLE hFile ) +{ + FILE_STANDARD_INFORMATION fs; + IO_STATUS_BLOCK iosb; + NTSTATUS status; + + status = ZwQueryInformationFile( hFile, &iosb, &fs, sizeof fs, FileStandardInformation ); + if( !NT_SUCCESS( status ) ){ + DPRINT((0,"PICE_len: ZwQueryInformationFile error: %x\n", status)); + return 0; + } + //ASSERT(fs.EndOfFile.u.HighPart == 0); + return (size_t)fs.EndOfFile.u.LowPart; +} + +/* From kernel32 + * NOTE + * A raw converter for now. It assumes lpMultiByteStr is + * NEVER multi-byte (that is each input character is + * 8-bit ASCII) and is ALWAYS NULL terminated. + * FIXME-FIXME-FIXME-FIXME + */ + +INT +STDCALL +PICE_MultiByteToWideChar ( + UINT CodePage, + DWORD dwFlags, + LPCSTR lpMultiByteStr, + int cchMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar + ) +{ + int InStringLength = 0; + BOOL InIsNullTerminated = TRUE; + PCHAR r; + PWCHAR w; + int cchConverted; + + /* + * Check the parameters. + */ + if ( /* --- CODE PAGE --- */ + ( (CP_ACP != CodePage) + && (CP_MACCP != CodePage) + && (CP_OEMCP != CodePage)) + /* --- FLAGS --- */ + /*|| (dwFlags ^ ( MB_PRECOMPOSED + | MB_COMPOSITE + | MB_ERR_INVALID_CHARS + | MB_USEGLYPHCHARS + ) + )*/ + /* --- INPUT BUFFER --- */ + || (NULL == lpMultiByteStr) + ) + { + DPRINT((0,"ERROR_INVALID_PARAMETER\n")); + return 0; + } + /* + * Compute the input buffer length. + */ + if (-1 == cchMultiByte) + { + InStringLength = PICE_strlen(lpMultiByteStr); + } + else + { + InIsNullTerminated = FALSE; + InStringLength = cchMultiByte; + } + /* + * Does caller query for output + * buffer size? + */ + if (0 == cchWideChar) + { + DPRINT((0,"ERROR_SUCCESS\n")); + return InStringLength; + } + /* + * Is space provided for the translated + * string enough? + */ + if (cchWideChar < InStringLength) + { + DPRINT((0,"ERROR_INSUFFICIENT_BUFFER: cchWideChar: %d, InStringLength: %d\n", cchWideChar, InStringLength)); + return 0; + } + /* + * Raw 8- to 16-bit conversion. + */ + for ( cchConverted = 0, + r = (PCHAR) lpMultiByteStr, + w = (PWCHAR) lpWideCharStr; + + ((*r) && (cchConverted < cchWideChar)); + + r++, w++, + cchConverted++ + ) + { + *w = (WCHAR) *r; + } + /* + * Is the input string NULL terminated? + */ + if (TRUE == InIsNullTerminated) + { + *w = L'\0'; + ++cchConverted; + } + /* + * Return how many characters we + * wrote in the output buffer. + */ + return cchConverted; +} + diff --git a/apps/utils/pice/module/utils.h b/apps/utils/pice/module/utils.h new file mode 100644 index 0000000..902d2f5 --- /dev/null +++ b/apps/utils/pice/module/utils.h @@ -0,0 +1,325 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + utils.h + +Abstract: + + HEADER for utils.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +#include +#include "../../../../ntoskrnl/include/internal/ps.h" +#define __STR(x) #x +#define STR(x) __STR(x) + +typedef enum { + kbDE, + kbUS, + kbDK, + kbMaximum +} KeyboardLayout; + +// scancode to ASCII conversion +typedef struct tagSCANTOASCII +{ + UCHAR s; // 0 terminates the table + UCHAR a; +}SCANTOASCII, *PSCANTOASCII; + +typedef struct tagKEYBOARD_LAYOUT +{ + LPSTR name; + PSCANTOASCII normal; + PSCANTOASCII shifted; + PSCANTOASCII alted; +} KEYBOARD_LAYOUT, *PKEYBOARD_LAYOUT; + +extern PKEYBOARD_LAYOUT CurrentKeyboard; + +typedef struct _FRAME +{ + ULONG error_code; + ULONG eip; + ULONG cs; + ULONG eflags; +}FRAME; + +#define SHOW_FIELD_BYTE(ptr,field,wait)\ +{\ + if(wait && WaitForKey()==FALSE)\ + return TRUE;\ + PICE_sprintf(tempCmd,#field" = %.2x\n",ptr->##field);\ + Print(OUTPUT_WINDOW,tempCmd);\ +} + +#define SHOW_FIELD_WORD(ptr,field,wait)\ +{\ + if(wait && WaitForKey()==FALSE)\ + return TRUE;\ + PICE_sprintf(tempCmd,#field" = %.4x\n",ptr->##field);\ + Print(OUTPUT_WINDOW,tempCmd);\ +} + +#define SHOW_FIELD_DWORD(ptr,field,wait)\ +{\ + if(wait && WaitForKey()==FALSE)\ + return TRUE;\ + PICE_sprintf(tempCmd,#field" = %.8x\n",ptr->##field);\ + Print(OUTPUT_WINDOW,tempCmd);\ +} + +#define SHOW_FIELD_SEG_OFS(ptr,field1,field2,wait)\ +{\ + if(wait && WaitForKey()==FALSE)\ + return TRUE;\ + PICE_sprintf(tempCmd,#field1":"#field2" = %.4x:%.8x\n",ptr->##field1,ptr->##field2);\ + Print(OUTPUT_WINDOW,tempCmd);\ +} + +typedef struct _PCI_NUMBER +{ + union { + struct + { + ULONG res2 : 2; + ULONG reg : 6; // 64 regs per function + ULONG func : 3; // 8 functions per device + ULONG dev : 5; // 32 device per bus + ULONG bus : 8; // 256 buses + ULONG res1 : 7; + ULONG ce : 1; // 1 to enable + }bits; + ULONG AsUlong; + }u; +}PCI_NUMBER; +/* +typedef struct _PCI_COMMON_CONFIG { + USHORT VendorID; // (ro) + USHORT DeviceID; // (ro) + USHORT Command; // Device control + USHORT Status; + UCHAR RevisionID; // (ro) + UCHAR ProgIf; // (ro) + UCHAR SubClass; // (ro) + UCHAR BaseClass; // (ro) + UCHAR CacheLineSize; // (ro+) + UCHAR LatencyTimer; // (ro+) + UCHAR HeaderType; // (ro) + UCHAR BIST; // Built in self test + ULONG BaseAddresses[6]; + ULONG CIS; + USHORT SubVendorID; + USHORT SubSystemID; + ULONG ROMBaseAddress; + UCHAR CapabilitiesPtr; + UCHAR Reserved1[3]; + ULONG Reserved2; + UCHAR InterruptLine; // + UCHAR InterruptPin; // (ro) + UCHAR MinimumGrant; // (ro) + UCHAR MaximumLatency; // (ro) +}PCI_COMMON_CONFIG; +*/ + +typedef struct tagPageDir +{ + ULONG P :1; + ULONG RW :1; + ULONG US :1; + ULONG PWT :1; + ULONG PCD :1; + ULONG A :1; + ULONG dummy :1; + ULONG PS :1; + ULONG G :1; + ULONG Avail :3; + ULONG PTBase :20; +}PAGEDIR,*PPAGEDIR; + +typedef struct tagGdt +{ + ULONG Limit_15_0 :16; + ULONG Base_15_0 :16; + ULONG Base_23_16 :8; + ULONG SegType :4; + ULONG DescType :1; + ULONG Dpl :2; + ULONG Present :1; + ULONG Limit_19_16 :4; + ULONG Avl :1; + ULONG Reserved :1; + ULONG DefOp :1; + ULONG Gran :1; + ULONG Base_31_24 :8; +}GDT,*PGDT; + +typedef struct tagIdt +{ + ULONG Offset_15_0 :16; + ULONG Selector :16; + ULONG Reserved :8; + ULONG DescType :5; + ULONG Dpl :2; + ULONG Present :1; + ULONG Offset_31_16 :16; +}IDT,*PIDT; + +typedef struct tagDESCRIPTOR +{ + USHORT Cpl :2; // current privilege level + USHORT Ti :1; // table index (GDT=0 LDT=1) + USHORT Val :13; // index into table +}DESCRIPTOR,*PDESCRIPTOR; + +PKEYBOARD_LAYOUT GetKeyboardLayout(); +PKEYBOARD_LAYOUT SetKeyboardLayoutByName(LPSTR Name); +void PICE_memset(void* p,unsigned char c,int sz); +void PICE_memcpy(void* t,void* s,int sz); +char *PICE_strrev(char *); +ULONG PICE_strcmp(char* s1,char* s2); +ULONG PICE_strcmpi(char* s1,char* s2); +ULONG PICE_strncmpi(char* s1,char* s2,ULONG len); +USHORT PICE_strlen(const char* s); +char* PICE_strcat(char* s1,char* s2); +BOOLEAN PICE_isprint(char c); +char* PICE_strcpy(char* s1,char* s2); +char* PICE_strncpy(char* s1,char* s2,int len); +char* PICE_strchr(char* s,char c); +int PICE_isdigit( int c ); +int PICE_isxdigit( int c ); +int PICE_islower( int c ); +int PICE_isalpha( int c ); + +int PICE_sprintf(char * buf, const char *fmt, ...); +int PICE_vsprintf(char *buf, const char *fmt, va_list args); + +BOOLEAN IsAddressValid(ULONG Addr); +BOOLEAN IsAddressWriteable(ULONG Addr); +BOOLEAN SetAddressWriteable(ULONG address,BOOLEAN bSet); +BOOLEAN IsRangeValid(ULONG addr,ULONG Length); +void IntelStackWalk(ULONG pc,ULONG ebp,ULONG esp); + +ULONG ReadPhysMem(ULONG Address,ULONG ulSize); +void WritePhysMem(ULONG Address,ULONG Datum,ULONG ulSize); + +BOOLEAN IsRetAtEIP(void); +BOOLEAN IsCallInstrAtEIP(void); + +ULONG GetLinearAddress(USHORT Segment,ULONG Offset); + +#define OUTPUT_BUFFER_FULL 0x01 +#define INPUT_BUFFER_FULL 0x02 +#define MOUSE_OUTPUT_BUFFER_FULL 0x20 + +void ShowStoppedMsg(void); +void ShowRunningMsg(void); + +void SetHardwareBreakPoints(void); +void SetHardwareBreakPoint(ULONG ulAddress,ULONG ulReg); + +// this should be in disasm.h but someone misused the header files +BOOLEAN Disasm(PULONG pOffset, PUCHAR pchDst); +////////////////////////////////////////////////////////////////// + +//segments defined in \include\napi\i386\segment.h +#define GLOBAL_CODE_SEGMENT (KERNEL_CS) +#define GLOBAL_DATA_SEGMENT (KERNEL_DS) + +//#define OVR_CS .byte 0x2e +//#define OVR_FS .byte 0x64 + +void DisplayRegs(void); +void SaveOldRegs(void); + +BOOLEAN CheckLoadAbort(void); + +UCHAR KeyboardGetKeyPolled(void); +void KeyboardFlushKeyboardQueue(void); + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PWT 0x008 +#define _PAGE_PCD 0x010 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 +#define _PAGE_PSE 0x080 +#define _PAGE_4M _PAGE_PSE +#define _PAGE_SIZE 0x1000 + + +UCHAR AsciiFromScan(UCHAR s); +UCHAR AsciiToScan(UCHAR s); + +void outportb(PUCHAR port,UCHAR data); +UCHAR inportb(PUCHAR port); + +void outb_p(UCHAR data, PUCHAR port); +UCHAR inb_p(PUCHAR port); + +VOID outl(ULONG l, PULONG port); +ULONG inl(PULONG port); + + +#define save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) +#define restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc") +#define cli() __asm__ __volatile__("cli": : :"memory") +#define sti() __asm__ __volatile__("sti": : :"memory") + +#ifdef NDEBUG +#define ASSERT(x) +#else +#define ASSERT(x) if (!(x)) { DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__); KeBugCheck(0); } +#endif + +//extern unsigned long sys_call_table[]; + +//struct mm_struct *GetInitMm(void); + +PMADDRESS_SPACE my_init_mm; +LIST_ENTRY* pPsProcessListHead; + +void EnablePassThrough(void); + +#define PAGEDPOOL (1) +#define NONPAGEDPOOL (0) + +void * PICE_malloc( size_t numBytes, BOOLEAN fromPaged ); +void PICE_free( void* p ); + +HANDLE PICE_open (LPCWSTR lpPathName, int iReadWrite); +long PICE_read(HANDLE hFile, LPVOID lpBuffer, long lBytes); +int PICE_close (HANDLE hFile); +size_t PICE_len( HANDLE hFile ); +WCHAR * PICE_wcscpy(WCHAR * str1,const WCHAR * str2); +INT +STDCALL +PICE_MultiByteToWideChar ( + UINT CodePage, + DWORD dwFlags, + LPCSTR lpMultiByteStr, + int cchMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar + ); diff --git a/apps/utils/pice/module/vga.c b/apps/utils/pice/module/vga.c new file mode 100644 index 0000000..4e2e8c0 --- /dev/null +++ b/apps/utils/pice/module/vga.c @@ -0,0 +1,572 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + vga.c + +Abstract: + + VGA HW dependent draw routines + +Environment: + + Kernel mode only + +Author: + + Klaus P. Gerlicher + Reactos Port by Eugene Ingerman + +Revision History: + + 04-Aug-1998: created + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//////////////////////////////////////////////////// +// INCLUDES +//// +#include "remods.h" +#include "precomp.h" + +//#include +//#include + + +//////////////////////////////////////////////////// +// PROTOTYPES +//// +extern void pice_save_current_registers(void); +extern void pice_restore_current_registers(void); +extern void pice_set_mode_3_80x50(void); +extern void pice_set_mode_3_80x25(void); + +extern UCHAR cGraphTable[8*256]; + +// storage for original VGA font +UCHAR cGraphTable2[16*256]; + +//////////////////////////////////////////////////// +// DEFINES +//// +#define VGA_EXTENDED // define this for 80x50 console mode + +#ifndef VGA_EXTENDED +#define SCREEN_BUFFER_SIZE (80*25*2) +#else +#define SCREEN_BUFFER_SIZE (80*50*2) +#endif + +/* Port addresses of control regs */ +#define MISCOUTPUT 0x3c2 +#define FEATURECONTROL 0x3da +#define SEQUENCER 0x3c4 +#define CRTC 0x03d4 +#define GRAPHICS 0x3ce +#define ATTRIBS 0x03c0 +#define PELADDRESSWRITE 0x3c8 +#define PELDATAREG 0x3c9 + +/* Number of regs on the various controllers */ + +#define MAXSEQ 5 +#define MAXCRTC 0x19 +#define MAXGRAPH 0x9 +#define MAXATTRIB 0x015 + +//////////////////////////////////////////////////// +// GLOBALS +//// +// used for HERCULES text and VGA text mode +WINDOW wWindowVga[4]= +#ifndef VGA_EXTENDED +{ + {1,3,1,0,FALSE}, + {5,4,1,0,FALSE}, + {10,9,1,0,FALSE}, + {20,4,1,0,FALSE} +}; +#else // VGA_EXTENDED +{ + {1,3,1,0,FALSE}, + {5,4,1,0,FALSE}, + {10,24,1,0,FALSE}, + {35,14,1,0,FALSE} +}; +#endif // VGA_EXTENDED + +PUCHAR pScreenBufferVga; +PUCHAR pScreenBufferSaveVga = NULL; +PUCHAR pScreenBufferTempVga; +PUCHAR pScreenBufferHardwareVga; +PUCHAR pFontBufferVga = NULL; + +UCHAR offset_a = 0; +UCHAR offset_c = 0,offset_d = 0; +UCHAR offset_e = 0,offset_f = 0; + +struct _attr +{ + union + { + struct + { + + UCHAR fgcol : 4; + UCHAR bkcol : 3; + UCHAR blink : 1; + }bits; + UCHAR Asuchar; + }u; +}attr; + +unsigned char oldgraphicsmode; +unsigned char oldgraphicsmisc; +unsigned char oldsqregmapmask; +unsigned char oldsqregmemory; +unsigned char oldgraphicssetresetenable; +unsigned char oldgraphicsreadmapsel; + +unsigned char read_vga_reg(int port, int reg) +{ + outportb(port,reg); + return(inportb(port+1)); +} + +void write_vga_reg(int port, unsigned char reg, unsigned char value) +{ + outportb(port,reg); + outportb(port+1,value); +} + +/* Registers within controllers */ +#define VREND 0x11 +#define GRREGSETRESET 0 +#define GRREGENABLESETRESET 1 +#define GRREGREADMAPSEL 4 +#define SQREGMAPMASK 2 +#define SQREGMEMORY 4 +#define GRREGWRMODE 5 +#define GRREGMISC 6 + +void map_font_memory(void) +{ + oldgraphicssetresetenable = read_vga_reg(GRAPHICS, GRREGENABLESETRESET); + oldgraphicsmode = read_vga_reg(GRAPHICS, GRREGWRMODE); + oldgraphicsmisc = read_vga_reg(GRAPHICS, GRREGMISC); + oldgraphicsreadmapsel = read_vga_reg(GRAPHICS, GRREGREADMAPSEL); + oldsqregmapmask = read_vga_reg(SEQUENCER, SQREGMAPMASK); + oldsqregmemory = read_vga_reg(SEQUENCER, SQREGMEMORY); + + + /* Make sure set/reset enable is off */ + write_vga_reg(GRAPHICS,GRREGENABLESETRESET,0); + /* Select read plane 2 */ + write_vga_reg(GRAPHICS,GRREGREADMAPSEL,0x02); + /* Make sure write and read mode = 0 */ + write_vga_reg(GRAPHICS,GRREGWRMODE,0x00); + /* Set mapping to 64K at a000:0 & turn off odd/even at the graphics reg */ + write_vga_reg(GRAPHICS,GRREGMISC, 0x04); + /* Set sequencer plane to 2 */ + write_vga_reg(SEQUENCER,SQREGMAPMASK, 0x04); + /* Turn off odd/even at the sequencer */ + write_vga_reg(SEQUENCER,SQREGMEMORY, 0x07); +} + +void unmap_font_memory(void) +{ + write_vga_reg(GRAPHICS,GRREGENABLESETRESET,oldgraphicssetresetenable); + write_vga_reg(GRAPHICS,GRREGWRMODE,oldgraphicsmode); + write_vga_reg(GRAPHICS,GRREGREADMAPSEL,oldgraphicsreadmapsel); + write_vga_reg(GRAPHICS,GRREGMISC, oldgraphicsmisc); + write_vga_reg(SEQUENCER,SQREGMAPMASK, oldsqregmapmask); + write_vga_reg(SEQUENCER,SQREGMEMORY, oldsqregmemory); +} + +/* Font and palette constants */ +#define BYTESPERFONT 8 +#define FONTENTRIES 256 +#define FONTBUFFERSIZE 8192 + +void save_font(UCHAR* graph_table) +{ + PUCHAR FontBase = pFontBufferVga; + int i,j; + map_font_memory(); + + for (i=0; i < FONTENTRIES; i++) + for (j=0; j < 16; j++) + graph_table[i*16+j] = FontBase[i*32+j]; + + unmap_font_memory(); +} + +void load_font(UCHAR* graph_table,int bEnter) +{ + PUCHAR FontBase = pFontBufferVga; + int i,j; + map_font_memory(); + + if(bEnter) + { +#ifdef VGA_EXTENDED + for (i=0; i < FONTENTRIES; i++) + for (j=0; j < 8; j++) + FontBase[i*32+j] = graph_table[i*BYTESPERFONT+j]; +#else // VGA_EXTENDED + for (i=0; i < FONTENTRIES; i++) + for (j=0; j < 16; j++) + FontBase[i*32+j] = graph_table[i*BYTESPERFONT+(j/2)] << (j&1); +#endif // VGA_EXTENDED + } + else + { + for (i=0; i < FONTENTRIES; i++) + for (j=0; j < 16; j++) + FontBase[i*32+j] = graph_table[i*16+j]; + } + + unmap_font_memory(); +} + +//************************************************************************* +// SetForegroundColorVga() +// +//************************************************************************* +void SetForegroundColorVga(ECOLORS col) +{ + attr.u.bits.fgcol = col; + attr.u.bits.blink = 0; +} + +//************************************************************************* +// SetBackgroundColorVga() +// +//************************************************************************* +void SetBackgroundColorVga(ECOLORS col) +{ + attr.u.bits.bkcol = col; + attr.u.bits.blink = 0; +} + +//************************************************************************* +// PrintGrafVga() +// +//************************************************************************* +void PrintGrafVga(ULONG x,ULONG y,UCHAR c) +{ + ((PUSHORT)pScreenBufferVga)[y*GLOBAL_SCREEN_WIDTH + x] = (USHORT)((attr.u.Asuchar<<8)|c); +} + +//************************************************************************* +// ShowCursor() +// +// show hardware cursor +//************************************************************************* +void ShowCursorVga(void) +{ + ENTER_FUNC(); + + bCursorEnabled=TRUE; + + outb_p(0x0a,0x3d4); + outb_p(inb_p(0x3d5)&~0x20,0x3d5); + + LEAVE_FUNC(); +} + +//************************************************************************* +// HideCursorVga() +// +// hide hardware cursor +//************************************************************************* +void HideCursorVga(void) +{ + ENTER_FUNC(); + bCursorEnabled=FALSE; + + outb_p(0x0a,0x3d4); + outb_p(inb_p(0x3d5)|0x20,0x3d5); + + LEAVE_FUNC(); +} + +//************************************************************************* +// CopyLineTo() +// +// copy a line from src to dest +//************************************************************************* +void CopyLineToVga(USHORT dest,USHORT src) +{ + PUSHORT p = (PUSHORT)pScreenBufferVga; + + ENTER_FUNC(); + + PICE_memcpy(&p[dest*GLOBAL_SCREEN_WIDTH],&p[src*GLOBAL_SCREEN_WIDTH],GLOBAL_SCREEN_WIDTH*sizeof(USHORT)); + + LEAVE_FUNC(); +} + +//************************************************************************* +// InvertLineVga() +// +// invert a line on the screen +//************************************************************************* +void InvertLineVga(ULONG line) +{ + ULONG i; + PUSHORT p = (PUSHORT)pScreenBufferVga; + USHORT attr; + + if(line < GLOBAL_SCREEN_HEIGHT) + { + attr = p[line*GLOBAL_SCREEN_WIDTH]>>8; + attr = ((attr & 0x07)<<4) | ((attr & 0xF0)>>4); + attr <<= 8; + for(i=0;i250 ) + { + count=0; + + charoffset = (y* GLOBAL_SCREEN_WIDTH + x); + + outb_p(0x0e,0x3d4); + data=(UCHAR)((charoffset>>8)&0xFF); + outb_p(data,0x3d5); + + outb_p(0x0f,0x3d4); + data=(UCHAR)(charoffset & 0xFF); + outb_p(data,0x3d5); + } +} + +//************************************************************************* +// SaveGraphicsVga() +// +//************************************************************************* +void SaveGraphicsStateVga(void) +{ + UCHAR data; + + // save current regs + pice_save_current_registers(); + + // unprotect crtc regs 0-7 + outb_p(0x11,0x3d4); + data = inb_p(0x3d5); + outb_p(data & 0x7F,0x3d5); + + // save current font + save_font(cGraphTable2); + + // restore original regs +#ifdef VGA_EXTENDED + pice_set_mode_3_80x50(); +#else + pice_set_mode_3_80x25(); +#endif + + // load a font + load_font(cGraphTable,1); + + // copy the screen content to temp area + PICE_memcpy(pScreenBufferTempVga,pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE); + // copy the console to the screen + PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferVga,SCREEN_BUFFER_SIZE); + // save original pointer + pScreenBufferSaveVga = pScreenBufferVga; + // pScreenBufferVga now points to screen + pScreenBufferVga = pScreenBufferHardwareVga; +} + +//************************************************************************* +// RestoreGraphicsStateVga() +// +//************************************************************************* +void RestoreGraphicsStateVga(void) +{ + UCHAR data; + + // unprotect crtc regs 0-7 + outb_p(0x11,0x3d4); + data = inb_p(0x3d5); + outb_p(data & 0x7F,0x3d5); + + // restore original regs + pice_restore_current_registers(); + + // load a font + load_font(cGraphTable2,0); + + pScreenBufferVga = pScreenBufferSaveVga; + // copy screen to the console + PICE_memcpy(pScreenBufferVga,pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE); + // copy the temp area to the screen + PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferTempVga,SCREEN_BUFFER_SIZE); +} + +//************************************************************************* +// ConsoleInitVga() +// +// init terminal screen +//************************************************************************* +BOOLEAN ConsoleInitVga(void) +{ + BOOLEAN bResult = FALSE; + PUSHORT p; + PHYSICAL_ADDRESS FrameBuffer; + PHYSICAL_ADDRESS FontBuffer; + + + ENTER_FUNC(); + + ohandlers.CopyLineTo = CopyLineToVga; + ohandlers.PrintGraf = PrintGrafVga; + ohandlers.ClrLine = ClrLineVga; + ohandlers.InvertLine = InvertLineVga; + ohandlers.HatchLine = HatchLineVga; + ohandlers.PrintLogo = PrintLogoVga; + ohandlers.PrintCursor = PrintCursorVga; + ohandlers.SaveGraphicsState = SaveGraphicsStateVga; + ohandlers.RestoreGraphicsState = RestoreGraphicsStateVga; + ohandlers.ShowCursor = ShowCursorVga; + ohandlers.HideCursor = HideCursorVga; + ohandlers.SetForegroundColor = SetForegroundColorVga; + ohandlers.SetBackgroundColor = SetBackgroundColorVga; + + ihandlers.GetKeyPolled = KeyboardGetKeyPolled; + ihandlers.FlushKeyboardQueue = KeyboardFlushKeyboardQueue; + + SetWindowGeometry(wWindowVga); + + GLOBAL_SCREEN_WIDTH = 80; +#ifndef VGA_EXTENDED + GLOBAL_SCREEN_HEIGHT = 25; +#else // VGA_EXTENDED + GLOBAL_SCREEN_HEIGHT = 50; +#endif // VGA_EXTENDED + + attr.u.Asuchar = 0x07; + + // the real framebuffer + FrameBuffer.u.LowPart = 0xB8000; + pScreenBufferHardwareVga = MmMapIoSpace(FrameBuffer,SCREEN_BUFFER_SIZE,FALSE); + + //The real font buffer + FontBuffer.u.LowPart = 0xA0000; + pFontBufferVga = MmMapIoSpace(FontBuffer,FONTBUFFERSIZE,FALSE); + + // the console + pScreenBufferVga = PICE_malloc(SCREEN_BUFFER_SIZE,NONPAGEDPOOL); + // the save area + pScreenBufferTempVga = PICE_malloc(SCREEN_BUFFER_SIZE,NONPAGEDPOOL); + + if(pScreenBufferVga) + { + DPRINT((0,"VGA memory phys. 0x000b0000 mapped to virt. 0x%x\n",pScreenBufferVga)); + + bResult = TRUE; + + p = (PUSHORT)pScreenBufferVga; + + PICE_memset(pScreenBufferVga,0x0,SCREEN_BUFFER_SIZE); + + DPRINT((0,"VGA memory cleared!\n")); + + EmptyRingBuffer(); + + DPRINT((0,"ConsoleInitVga() SUCCESS!\n")); + } + + LEAVE_FUNC(); + + return bResult; +} + +//************************************************************************* +// ConsoleShutdownVga() +// +// exit terminal screen +//************************************************************************* +void ConsoleShutdownVga(void) +{ + ENTER_FUNC(); + + if(pScreenBufferVga) + { + PICE_free(pScreenBufferVga); + PICE_free(pScreenBufferTempVga); + MmUnmapIoSpace(pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE); + MmUnmapIoSpace(pFontBufferVga,FONTBUFFERSIZE); + } + + LEAVE_FUNC(); +} + + diff --git a/apps/utils/pice/module/vga.h b/apps/utils/pice/module/vga.h new file mode 100644 index 0000000..89e0c30 --- /dev/null +++ b/apps/utils/pice/module/vga.h @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + vga.h + +Abstract: + + HEADER for vga.c + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + +Revision History: + + 15-Nov-2000: general cleanup of source files + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ +BOOLEAN ConsoleInitVga(void); +void ConsoleShutdownVga(void); diff --git a/apps/utils/pice/module/vga_utils.asm b/apps/utils/pice/module/vga_utils.asm new file mode 100644 index 0000000..9602817 --- /dev/null +++ b/apps/utils/pice/module/vga_utils.asm @@ -0,0 +1,729 @@ +;/*++ +; +;Copyright (c) 1998-2001 Klaus P. Gerlicher +; +;Module Name: +; +; vga_utils.asm +; +;Abstract: +; +; assembler function for directly programming standard VGA +; +;Environment: +; +; LINUX 2.2.X +; Kernel mode only +; +;Author: +; +; Klaus P. Gerlicher +; Reactos Port by Eugene Ingerman +; +;Revision History: +; +; 30-Oct-2001: created +; +;Copyright notice: +; +; This file may be distributed under the terms of the GNU Public License. +; +;--*/ + +global _pice_save_current_registers +global _pice_restore_current_registers +global _pice_set_mode_3_80x50 +global _pice_set_mode_3_80x25 + +;**************************************************************************** +;* some assign's ************************************************************ +;**************************************************************************** +%assign VGA_CRT_REGISTERS 24 +%assign VGA_ATTRIBUTE_REGISTERS 21 +%assign VGA_GRAPHIC_REGISTERS 9 +%assign VGA_SEQUENCER_REGISTERS 5 +%assign VGA_MISC_REGISTERS 1 + +%assign VGA_IO_BASE 03c0h +%assign VGA_IO_SIZE 020h + +%assign VGA_ATTRIBUTE_INDEX 03c0h +%assign VGA_ATTRIBUTE_DATA_WRITE 03c0h +%assign VGA_ATTRIBUTE_DATA_READ 03c1h +%assign VGA_MISC_DATA_WRITE 03c2h +%assign VGA_SEQUENCER_INDEX 03c4h +%assign VGA_SEQUENCER_DATA 03c5h +%assign VGA_PEL_MASK 03c6h +%assign VGA_PEL_INDEX_READ 03c7h +%assign VGA_PEL_INDEX_WRITE 03c8h +%assign VGA_PEL_DATA 03c9h +%assign VGA_MISC_DATA_READ 03cch +%assign VGA_GRAPHIC_INDEX 03ceh +%assign VGA_GRAPHIC_DATA 03cfh +%assign VGA_CRT_INDEX 03d4h +%assign VGA_CRT_DATA 03d5h +%assign VGA_INPUT_STATUS 03dah + +section .data +pice_mode3_80x50_registers: +; offsets 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 +.crt: db 0x5f,0x4f,0x50,0x82,0x55,0x80,0xbf,0x1f,0x00,0x67,0x06,0x07,0x00,0x00,0x00,0x00,0x9c,0x8f,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff +.attribute db 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x00,0x0f,0x00,0x00 +.graphic: db 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff +.sequencer: db 0x03,0x00,0x03,0x00,0x02 ; 9 bits per char +;.sequencer: db 0x03,0x01,0x03,0x00,0x02 ; 8 bits per char +.misc: db 0x67 + +pice_mode3_80x25_registers: +; offsets 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 +.crt: db 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x30,0xe8,0x9c,0x0e,0x8f,0x28,0x1f,0x96,0xb9,0xa3 +.attribute db 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x0c,0x00,0x0f,0x08,0x00 +.graphic: db 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff +.sequencer: db 0x03,0x00,0x03,0x00,0x02 +.misc: db 0x67 + + + +section .bss +pice_current_registers: +.crt: resb VGA_CRT_REGISTERS +.attribute: resb VGA_ATTRIBUTE_REGISTERS +.graphic: resb VGA_GRAPHIC_REGISTERS +.sequencer: resb VGA_SEQUENCER_REGISTERS +.misc: resb VGA_MISC_REGISTERS + align 4 +.colormap: resd 256 + +;**************************************************************************** +;* pice_save_current_charset ************************************************ +;**************************************************************************** +section .text +pice_address dd 0xc00a0000 +pice_save_current_charset: + xor dword ebx, ebx + call pice_select_read_plane + mov dword ecx, 04000h + mov dword esi, [pice_address] + mov dword edi, pice_charset_saved + cld + rep movsd + mov dword ebx, 00100h + call pice_select_read_plane + mov dword ecx, 04000h + mov dword esi, [pice_address] + mov dword edi, (pice_charset_saved + 010000h) + cld + rep movsd + mov dword ebx, 00200h + call pice_select_read_plane + mov dword ecx, 04000h + mov dword esi, [pice_address] + mov dword edi, (pice_charset_saved + 020000h) + cld + rep movsd + mov dword ebx, 00300h + call pice_select_read_plane + mov dword ecx, 04000h + mov dword esi, [pice_address] + mov dword edi, (pice_charset_saved + 030000h) + cld + rep movsd +.end: ret + + + +;**************************************************************************** +;* pice_restore_current_charset **************************************************** +;**************************************************************************** +section .text +pice_restore_current_charset: + mov dword ebx, 00100h + call pice_select_write_plane + mov dword ecx, 04000h + mov dword esi, pice_charset_saved + mov dword edi, [pice_address] + cld + rep movsd + mov dword ebx, 00200h + call pice_select_write_plane + mov dword ecx, 04000h + mov dword esi, (pice_charset_saved + 010000h) + mov dword edi, [pice_address] + cld + rep movsd + mov dword ebx, 00400h + call pice_select_write_plane + mov dword ecx, 04000h + mov dword esi, (pice_charset_saved + 020000h) + mov dword edi, [pice_address] + cld + rep movsd + mov dword ebx, 00800h + call pice_select_write_plane + mov dword ecx, 04000h + mov dword esi, (pice_charset_saved + 030000h) + mov dword edi, [pice_address] + cld + rep movsd +.end: ret + +;**************************************************************************** +;* pice_get_crt_registers ************************************************** +;**************************************************************************** +;* ebx=> pointer where to store crt registers +;**************************************************************************** +section .text +pice_get_crt_registers: + xor dword ecx, ecx +.loop: mov dword edx, VGA_CRT_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_CRT_DATA + in byte al, dx + mov byte [ebx + ecx], al + inc dword ecx + cmp dword ecx, VGA_CRT_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_get_attribute_registers ******************************************** +;**************************************************************************** +;* ebx=> pointer where to store attribute registers +;**************************************************************************** +section .text +pice_get_attribute_registers: + xor dword ecx, ecx +.loop: mov dword edx, VGA_INPUT_STATUS + in byte al, dx + mov dword edx, VGA_ATTRIBUTE_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_ATTRIBUTE_DATA_READ + in byte al, dx + mov byte [ebx + ecx], al + inc dword ecx + cmp dword ecx, VGA_ATTRIBUTE_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_get_graphic_registers ********************************************** +;**************************************************************************** +;* ebx=> pointer where to store graphics registers +;**************************************************************************** +section .text +pice_get_graphic_registers: + xor dword ecx, ecx +.loop: mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + in byte al, dx + mov byte [ebx + ecx], al + inc dword ecx + cmp dword ecx, VGA_GRAPHIC_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_get_sequencer_registers ******************************************** +;**************************************************************************** +;* ebx=> pointer where to store sequencer registers +;**************************************************************************** +section .text +pice_get_sequencer_registers: + xor dword ecx, ecx +.loop: mov dword edx, VGA_SEQUENCER_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + in byte al, dx + mov byte [ebx + ecx], al + inc dword ecx + cmp dword ecx, VGA_SEQUENCER_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_get_misc_registers ************************************************* +;**************************************************************************** +;* ebx=> pointer where to store misc register +;**************************************************************************** +section .text +pice_get_misc_registers: + mov dword edx, VGA_MISC_DATA_READ + in byte al, dx + mov byte [ebx], al + ret + + + +;**************************************************************************** +;* pice_get_colormap ******************************************************* +;**************************************************************************** +;* ebx=> pointer where to store colormap +;**************************************************************************** +section .text +pice_get_colormap: + xor dword ecx, ecx + xor dword eax, eax + mov dword edx, VGA_PEL_INDEX_READ + out word dx, al + mov dword edx, VGA_PEL_DATA +.loop: in byte al, dx + shl dword eax, 8 + in byte al, dx + shl dword eax, 8 + in byte al, dx + mov dword [ebx + 4 * ecx], eax + inc dword ecx + test byte cl, cl + jnz .loop + ret + + + +;**************************************************************************** +;* pice_set_crt_registers ************************************************** +;**************************************************************************** +;* ebx=> pointer to stored crt registers +;**************************************************************************** +section .text +pice_set_crt_registers: + + ;deprotect CRT registers 0 - 7 + + mov dword edx, VGA_CRT_INDEX + mov byte al, 011h + out word dx, al + mov dword edx, VGA_CRT_DATA + in byte al, dx + and byte al, 07fh + out word dx, al + + ;write to the registers + + xor dword ecx, ecx +.loop: mov dword edx, VGA_CRT_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_CRT_DATA + mov byte al, [ebx + ecx] + out word dx, al + inc dword ecx + cmp dword ecx, VGA_CRT_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_set_attribute_registers ******************************************** +;**************************************************************************** +;* ebx=> pointer to stored attibute registers +;**************************************************************************** +section .text +pice_set_attribute_registers: + xor dword ecx, ecx +.loop: mov dword edx, VGA_INPUT_STATUS + in byte al, dx + mov dword edx, VGA_ATTRIBUTE_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_ATTRIBUTE_DATA_WRITE + mov byte al, [ebx + ecx] + out word dx, al + inc dword ecx + cmp dword ecx, VGA_ATTRIBUTE_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_set_graphic_registers ********************************************** +;**************************************************************************** +;* ebx=> pointer to stored graphic registers +;**************************************************************************** +section .text +pice_set_graphic_registers: + xor dword ecx, ecx +.loop: mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + mov byte al, [ebx + ecx] + out word dx, al + inc dword ecx + cmp dword ecx, VGA_GRAPHIC_REGISTERS + jb .loop + ret + + + +;**************************************************************************** +;* pice_set_sequencer_registers ******************************************** +;**************************************************************************** +;* ebx=> pointer to stored sequencer registers +;**************************************************************************** +section .text +pice_set_sequencer_registers: + + ;synchronous reset on + + mov dword edx, VGA_SEQUENCER_INDEX + xor dword eax, eax + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + inc dword eax + out word dx, al + + ;write to the registers + + mov dword edx, VGA_SEQUENCER_INDEX + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + mov byte al, [ebx + 1] + or byte al, 020h + out word dx, al + mov dword ecx, 2 +.loop: mov dword edx, VGA_SEQUENCER_INDEX + mov byte al, cl + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + mov byte al, [ebx + ecx] + out word dx, al + inc dword ecx + cmp dword ecx, VGA_SEQUENCER_REGISTERS + jb .loop + + ;synchronous reset off + + mov dword edx, VGA_SEQUENCER_INDEX + xor dword eax, eax + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + mov byte al, 3 + out word dx, al + ret + + + +;**************************************************************************** +;* pice_set_misc_registers ************************************************* +;**************************************************************************** +;* ebx=> pointer to stored misc register +;**************************************************************************** +section .text +pice_set_misc_registers: + mov dword edx, VGA_MISC_DATA_WRITE + mov byte al, [ebx] + out word dx, al + ret + + + +;**************************************************************************** +;* pice_set_colormap ******************************************************* +;**************************************************************************** +;* ebx=> pointer to stored colormap +;**************************************************************************** +section .text +pice_set_colormap: + xor dword ecx, ecx + xor dword eax, eax + mov dword edx, VGA_PEL_INDEX_WRITE + out word dx, al + mov dword edx, VGA_PEL_DATA +.loop: mov dword eax, [ebx + 4 * ecx] + rol dword eax, 16 + out word dx, al + rol dword eax, 8 + out word dx, al + rol dword eax, 8 + out word dx, al + inc dword ecx + test byte cl, cl + jnz .loop + ret + + + +;**************************************************************************** +;* pice_screen_on ********************************************************** +;**************************************************************************** +section .text +pice_screen_on: + + ;turn on the screen + + mov dword edx, VGA_SEQUENCER_INDEX + mov byte al, 1 + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + in byte al, dx + and byte al, 0dfh + out word dx, al + + ;enable video output + + mov dword edx, VGA_INPUT_STATUS + in byte al, dx + mov dword edx, VGA_ATTRIBUTE_DATA_WRITE + mov byte al, 020h + out word dx, al + ret + +;**************************************************************************** +;* pice_select_write_plane ************************************************* +;**************************************************************************** +;* bl==> write mode +;* bh==> write plane +;**************************************************************************** +section .text +pice_select_write_plane: + and dword ebx, 00f03h + + ;enable set/reset = 0 + + mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, 1 + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + xor dword eax, eax + out word dx, al + + ;logical operation = none, rotate = 0 + + mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, 3 + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + xor dword eax, eax + out word dx, al + + ;select write mode + + mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, 5 + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + in byte al, dx + and byte al, 0fch + or byte al, bl + out word dx, al + + ;bitmask = 0ffh + + mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, 8 + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + mov byte al, 0ffh + out word dx, al + + ;select write plane + + mov dword edx, VGA_SEQUENCER_INDEX + mov byte al, 2 + out word dx, al + mov dword edx, VGA_SEQUENCER_DATA + mov byte al, bh + out word dx, al + ret + + + +;**************************************************************************** +;* pice_select_read_plane ************************************************** +;**************************************************************************** +;* bl==> read mode +;* bh==> read plane +;**************************************************************************** +section .text +pice_select_read_plane: + and dword ebx, 00301h + shl byte bl, 3 + + ;select read mode + + mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, 5 + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + in byte al, dx + and byte al, 0f7h + or byte al, bl + out word dx, al + + ;select read plane + + mov dword edx, VGA_GRAPHIC_INDEX + mov byte al, 4 + out word dx, al + mov dword edx, VGA_GRAPHIC_DATA + mov byte al, bh + out word dx, al + ret + + + +;**************************************************************************** +;* pice_save_current_registers ********************************************** +;**************************************************************************** +section .text +_pice_save_current_registers: + push esi + push edi + push ebx + +; call pice_save_current_charset + +.crt: mov dword ebx, pice_current_registers.crt + call pice_get_crt_registers + +.attribute: mov dword ebx, pice_current_registers.attribute + call pice_get_attribute_registers + +.graphic: mov dword ebx, pice_current_registers.graphic + call pice_get_graphic_registers + +.sequencer: mov dword ebx, pice_current_registers.sequencer + call pice_get_sequencer_registers + +.misc: mov dword ebx, pice_current_registers.misc + call pice_get_misc_registers + +.colormap: mov dword ebx, pice_current_registers.colormap + call pice_get_colormap + + pop ebx + pop edi + pop esi +.end: ret + +;**************************************************************************** +;* pice_restore_current_registers ******************************************* +;**************************************************************************** +section .text +_pice_restore_current_registers: + push esi + push edi + push ebx + +; call pice_restore_current_charset + +.misc: mov dword ebx, pice_current_registers.misc + call pice_set_misc_registers + +.crt: mov dword ebx, pice_current_registers.crt + call pice_set_crt_registers + +.attribute: mov dword ebx, pice_current_registers.attribute + call pice_set_attribute_registers + +.graphic: mov dword ebx, pice_current_registers.graphic + call pice_set_graphic_registers + +.sequencer: mov dword ebx, pice_current_registers.sequencer + call pice_set_sequencer_registers + +.screen_on: call pice_screen_on + +.colormap: mov dword ebx, pice_current_registers.colormap + call pice_set_colormap + + pop ebx + pop edi + pop esi + +.end: ret + + +;**************************************************************************** +;* pice_set_mode_3_80x50***************************************************** +;**************************************************************************** +section .text +_pice_set_mode_3_80x50: + push esi + push edi + push ebx + +.crt: mov dword ebx, pice_mode3_80x50_registers.crt + call pice_set_crt_registers + +.attribute: mov dword ebx, pice_mode3_80x50_registers.attribute + call pice_set_attribute_registers + +.graphic: mov dword ebx, pice_mode3_80x50_registers.graphic + call pice_set_graphic_registers + +.sequencer: mov dword ebx, pice_mode3_80x50_registers.sequencer + call pice_set_sequencer_registers + +.misc: mov dword ebx, pice_mode3_80x50_registers.misc + call pice_set_misc_registers + +.screen_on: call pice_screen_on + +;.colormap: mov dword ebx, pice_current_registers.colormap +; call pice_set_colormap + + pop ebx + pop edi + pop esi + +.end: ret + +;**************************************************************************** +;* pice_set_mode_3_80x25***************************************************** +;**************************************************************************** +section .text +_pice_set_mode_3_80x25: + push esi + push edi + push ebx + +.crt: mov dword ebx, pice_mode3_80x25_registers.crt + call pice_set_crt_registers + +.attribute: mov dword ebx, pice_mode3_80x25_registers.attribute + call pice_set_attribute_registers + +.graphic: mov dword ebx, pice_mode3_80x25_registers.graphic + call pice_set_graphic_registers + +.sequencer: mov dword ebx, pice_mode3_80x25_registers.sequencer + call pice_set_sequencer_registers + +.misc: mov dword ebx, pice_mode3_80x25_registers.misc + call pice_set_misc_registers + +.screen_on: call pice_screen_on + +;.colormap: mov dword ebx, pice_current_registers.colormap +; call pice_set_colormap + + pop ebx + pop edi + pop esi + +.end: ret + +;**************************************************************************** +;* uninitialized data ******************************************************* +;**************************************************************************** +section .bss + alignb 4 +pice_charset_saved: resb 040000h + + diff --git a/apps/utils/pice/pice.cfg b/apps/utils/pice/pice.cfg new file mode 100644 index 0000000..e15cb50 --- /dev/null +++ b/apps/utils/pice/pice.cfg @@ -0,0 +1,4 @@ +# sample ++vga +\\SystemRoot\symbols\pice.dbg +\\SystemRoot\symbols\ntoskrnl.dbg diff --git a/apps/utils/pice/readme.txt b/apps/utils/pice/readme.txt new file mode 100644 index 0000000..c1d5341 --- /dev/null +++ b/apps/utils/pice/readme.txt @@ -0,0 +1,107 @@ +This is some preliminary information on using PICE. I am planning to write +a detailed manual later. + +BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA + + PICE for Reactos is in early beta stage of development. It still has many bugs. + +BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA-BETA + + +PICE is a kernel debugger that was ported for Reactos (the original Linux +project by Klaus P. Gerlicher and Goran Devic may be found here: +http://pice.sourceforge.net). + +Installation and use: + +1. PICE is loaded like a regular device driver. The only limitation - it must +be loaded after keyboard.sys driver. You should add: + + LdrLoadAutoConfigDriver( L"pice.sys" ); + +in ntoskrnl/ldr/loader.c after the line loading keyboard driver. + +2. You should copy pice.cfg and ntoskrnl.sym to \SystemRoot\symbols directory +of Reactos. + +3. If you want to add symbolic information you should use loader.exe to +create .dbg file from the unstrippped version of exe or driver: +For example: +pice\loader\loader.exe -t ntoskrnl.nostrip.exe + +After that copy .dbg file to \SystemRoot\symbols and add a line to pice.cfg: +\\SystemRoot\symbols\ntoskrnl.dbg. + +Pice will load the symbols during boot. For large .dbg files it may take a +while (ntoskrnl.dbg is ~3Mb). You may find that loading time under bochs is +quite slow, although otherwise performance should be fine. + +Key combination to break into debugger is CTRL-D. +You may need to press CTRL button upon return from the debugger if you get +"funny" symbols when you type. + +List of commands: + +gdt display current global descriptor table +idt display current interrupt descriptor table +x return to Reactos +t single step one instruction +vma displays VMAs +h list help on commands +page dump page directories +proc list all processes +dd display dword memory +db display byte memory +u disassemble at address +mod displays all modules +bpx set code breakpoint +bl list breakpoints +bc clear breakpoints +ver display pICE version and state information +hboot hard boot the system +cpu display CPU special registers +stack display call stack +. unassemble at current instruction +p single step over call +i single step into call +locals display local symbols +table display loaded symbol tables +file display source files in symbol table +sym list known symbol information +? evaluate an expression (global symbols only) +src sets disassembly mode +wc change size of code window +wd change size of data window +r sets or displays registers +cls clear output window +pci show PCI devices +next advance EIP to next instruction +i3here catch INT 3s +layout sets keyboard layout +syscall displays syscall (table) +altkey set alternate break key +addr show/set address contexts + +[CTRL/SHIFT/ALT] arrow up/down +TAB + +Not implemented yet: + +dpd display dword physical memory +code toggle code display +peek peek at physical memory +poke poke to physical memory +phys show all mappings for linear address +timers show all active timers + +TODO: +1. Evaluation of pointers. +2. Virtual breakpoints +3. Unimplemented commands. +4. Video mode switching (to debug gdi applications). + + +Enjoy, +Eugene + + diff --git a/apps/utils/pice/shared/shared.h b/apps/utils/pice/shared/shared.h new file mode 100644 index 0000000..e04db64 --- /dev/null +++ b/apps/utils/pice/shared/shared.h @@ -0,0 +1,204 @@ +/*++ + +Copyright (c) 1998-2001 Klaus P. Gerlicher + +Module Name: + + shared.h + +Abstract: + + shared stuff between module and loader + +Environment: + + LINUX 2.2.X + Kernel mode only + +Author: + + Klaus P. Gerlicher + + reactos port by: + Eugene Ingerman + +Revision History: + + 13-Nov-1999: created + 15-Nov-2000: general cleanup of source files + + 10/20/2001: porting to reactos begins + +Copyright notice: + + This file may be distributed under the terms of the GNU Public License. + +--*/ + +//#include +//#include + +//temporary +#ifndef CTL_CODE +#define CTL_CODE(Dev, Func, Meth, Acc) ( ((Dev)<<16) | ((Acc)<<14) | ((Func)<<2) | (Meth)) +// IOCTL Parameter buffering methods +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +// IOCTL File access type +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS 1 +#define FILE_WRITE_ACCESS 2 +#endif + +// define custom device type +#define PICE_DEVICE_DEBUGGER 64787 + +#define PICE_IOCTL_LOAD CTL_CODE(PICE_DEVICE_DEBUGGER, 2049, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define PICE_IOCTL_UNLOAD CTL_CODE(PICE_DEVICE_DEBUGGER, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define PICE_IOCTL_RELOAD CTL_CODE(PICE_DEVICE_DEBUGGER, 2051, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define PICE_IOCTL_BREAK CTL_CODE(PICE_DEVICE_DEBUGGER, 2052, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define PICE_IOCTL_STATUS CTL_CODE(PICE_DEVICE_DEBUGGER, 2053, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +typedef struct _DEBUGGER_STATUS_BLOCK +{ + char filename[256]; +}DEBUGGER_STATUS_BLOCK,*PDEBUGGER_STATUS_BLOCK; + +#define MAGIC_ULONG( ch0, ch1, ch2, ch3 ) \ + ( (ULONG)(UCHAR)(ch0) | \ + ( (ULONG)(UCHAR)(ch1) << 8 ) | \ + ( (ULONG)(UCHAR)(ch2) << 16 ) | \ + ( (ULONG)(UCHAR)(ch3) << 24 ) ) + +#define PICE_MAGIC MAGIC_ULONG('P','I','C','E') + +#define DEBUG_MODULE_NAME_LEN 32 +typedef struct _PICE_SYMBOLFILE_HEADER +{ + ULONG magic; + WCHAR name[DEBUG_MODULE_NAME_LEN]; + ULONG ulOffsetToHeaders,ulSizeOfHeader; + ULONG ulOffsetToGlobals,ulSizeOfGlobals; + ULONG ulOffsetToGlobalsStrings,ulSizeOfGlobalsStrings; + ULONG ulOffsetToStabs,ulSizeOfStabs; + ULONG ulOffsetToStabsStrings,ulSizeOfStabsStrings; + ULONG ulOffsetToSrcFiles,ulNumberOfSrcFiles; +}PICE_SYMBOLFILE_HEADER; + +typedef struct _STAB_ENTRY +{ + unsigned long n_strx; + unsigned char n_type; + unsigned char n_other; + unsigned short n_desc; + unsigned long n_value; +}STAB_ENTRY,*PSTAB_ENTRY; + +typedef struct _PICE_SYMBOLFILE_SOURCE +{ + char filename[256]; + ULONG ulOffsetToNext; +}PICE_SYMBOLFILE_SOURCE; + + + + + +/////////////////////////////////////////////////////////////////////////////////// +// serial stuff +typedef struct _SERIAL_PACKET_HEADER +{ + ULONG packet_size; + ULONG packet_header_chksum; + ULONG packet_chksum; +}SERIAL_PACKET_HEADER,*PSERIAL_PACKET_HEADER; + +typedef struct _SERIAL_PACKET +{ + SERIAL_PACKET_HEADER header; + UCHAR data[1]; +}SERIAL_PACKET,*PSERIAL_PACKET; + +#define ACK (0) + +typedef enum _ECOLORS +{ + BLACK = 0, + BLUE, + GREEN, + TURK, + RED, + VIOLET, + BROWN, + LTGRAY, + GRAY, + LTBLUE, + LT_GREEN, + LTTURK, + LTRED, + LTVIOLET, + YELLOW, + WHITE +}ECOLORS; + +typedef struct _SERIAL_DATA_PACKET +{ + UCHAR type; + UCHAR data[1]; +}SERIAL_DATA_PACKET,*PSERIAL_DATA_PACKET; + +#define PACKET_TYPE_CLRLINE (0) +typedef struct _SERIAL_DATA_PACKET_CLRLINE +{ + UCHAR type; + ECOLORS fgcol,bkcol; + UCHAR line; +}SERIAL_DATA_PACKET_CLRLINE,*PSERIAL_DATA_PACKET_CLRLINE; + +#define PACKET_TYPE_PRINT (1) +typedef struct _SERIAL_DATA_PACKET_PRINT +{ + UCHAR type; + UCHAR x; + UCHAR y; + ECOLORS fgcol,bkcol; + UCHAR string[1]; +}SERIAL_DATA_PACKET_PRINT,*PSERIAL_DATA_PACKET_PRINT; + +#define PACKET_TYPE_CONNECT (2) +typedef struct _SERIAL_DATA_PACKET_CONNECT +{ + UCHAR type; + UCHAR xsize,ysize; +}SERIAL_DATA_PACKET_CONNECT,*PSERIAL_DATA_PACKET_CONNECT; + +#define PACKET_TYPE_CURSOR (3) +typedef struct _SERIAL_DATA_PACKET_CURSOR +{ + UCHAR type; + UCHAR state,x,y; +}SERIAL_DATA_PACKET_CURSOR,*PSERIAL_DATA_PACKET_CURSOR; + +#define PACKET_TYPE_INVERTLINE (4) +typedef struct _SERIAL_DATA_PACKET_INVERTLINE +{ + UCHAR type; + UCHAR line; +}SERIAL_DATA_PACKET_INVERTLINE,*PSERIAL_DATA_PACKET_INVERTLINE; + +#define PACKET_TYPE_POLL (5) +typedef struct _SERIAL_DATA_PACKET_POLL +{ + UCHAR type; + USHORT major_version,minor_version,build_number; +}SERIAL_DATA_PACKET_POLL,*PSERIAL_DATA_PACKET_POLL; + +// END of serial stuff +/////////////////////////////////////////////////////////////////////////////////// + + +// EOF diff --git a/apps/utils/ps/makefile b/apps/utils/ps/makefile new file mode 100644 index 0000000..6dfc38c --- /dev/null +++ b/apps/utils/ps/makefile @@ -0,0 +1,21 @@ +# + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = ps + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/utils/ps/ps.cpp b/apps/utils/ps/ps.cpp new file mode 100644 index 0000000..568b053 --- /dev/null +++ b/apps/utils/ps/ps.cpp @@ -0,0 +1,42 @@ +#include +#include + +static char* title = " PID PARENT TIME NAME\n"; +char buf[256]; + +void main() +{ + HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE); + + DWORD r; + WriteFile(stdout,title,lstrlen(title),&r,NULL); + + HANDLE pl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); + + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + pe.th32ParentProcessID = 0; + + if(Process32First(pl,&pe)) do + { + HANDLE p =OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,pe.th32ProcessID); + FILETIME cr; + FILETIME ex; + FILETIME kt; + FILETIME ut; + GetProcessTimes(p,&cr,&ex,&kt,&ut); + WORD fatdate; + WORD fattime; + FileTimeToDosDateTime(&cr,&fatdate,&fattime); + int hour = (fattime & 0xf800) >> 11; + int minute = (fattime & 0x07e0) >> 5; + + wsprintf(buf,"%08X %08X %2d:%02d %s\n",pe.th32ProcessID,pe.th32ParentProcessID,hour,minute,pe.szExeFile); + WriteFile(stdout,buf,lstrlen(buf),&r,NULL); + CloseHandle(p); + pe.th32ParentProcessID = 0; + + } while( Process32Next(pl,&pe)); + + CloseHandle(pl); +} \ No newline at end of file diff --git a/apps/utils/stats/Makefile b/apps/utils/stats/Makefile new file mode 100644 index 0000000..da62df0 --- /dev/null +++ b/apps/utils/stats/Makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_NORC = yes + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = stats + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/apps/utils/stats/stats.c b/apps/utils/stats/stats.c new file mode 100644 index 0000000..4566964 --- /dev/null +++ b/apps/utils/stats/stats.c @@ -0,0 +1,459 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS project statistics + * FILE: stats.c + * PURPOSE: Main program file + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/01-2002 Created + */ +#include +#include + + +typedef struct _EXTENSION_INFO +{ + struct _EXTENSION_INFO * Next; + struct _FILE_INFO * StatInfoList; + TCHAR ExtName[16]; + TCHAR Description[256]; + DWORD FileCount; + DWORD LineCount; +} EXTENSION_INFO, *PEXTENSION_INFO; + +typedef struct _FILE_INFO +{ + struct _FILE_INFO * Next; + struct _FILE_INFO * StatInfoListNext; + PEXTENSION_INFO ExtInfo; + TCHAR FileName[256]; + DWORD LineCount; + DWORD FunctionCount; +} FILE_INFO, *PFILE_INFO; + + +DWORD TotalLineCount; +PCHAR FileBuffer; +DWORD FileBufferSize; +CHAR Line[256]; +DWORD CurrentOffset; +DWORD CurrentChar; +DWORD CurrentLine; +DWORD LineLength; +PEXTENSION_INFO ExtInfoList; +PFILE_INFO StatInfoList; + + +VOID +Initialize() +{ + TotalLineCount = 0; + FileBuffer = NULL; + FileBufferSize = 0; + CurrentOffset = 0; + CurrentLine = 0; + LineLength = 0; + ExtInfoList = NULL; + StatInfoList = NULL; +} + + +VOID +Cleanup() +{ + PEXTENSION_INFO ExtInfo; + PEXTENSION_INFO NextExtInfo; + + ExtInfo = ExtInfoList; + while (ExtInfo != NULL) + { + NextExtInfo = ExtInfo->Next; + HeapFree (GetProcessHeap(), 0, ExtInfo); + ExtInfo = NextExtInfo; + } +} + + +PEXTENSION_INFO +AddExtension(LPTSTR ExtName, + LPTSTR Description) +{ + PEXTENSION_INFO ExtInfo; + PEXTENSION_INFO Info; + + ExtInfo = (PEXTENSION_INFO) HeapAlloc (GetProcessHeap(), 0, sizeof (EXTENSION_INFO)); + if (!ExtInfo) + return NULL; + ZeroMemory (ExtInfo, sizeof (EXTENSION_INFO)); + _tcscpy (ExtInfo->ExtName, ExtName); + _tcscpy (ExtInfo->Description, Description); + + if (ExtInfoList) + { + Info = ExtInfoList; + while (Info->Next != NULL) + { + Info = Info->Next; + } + Info->Next = ExtInfo; + } + else + { + ExtInfoList = ExtInfo; + } + + return ExtInfo; +} + + +PFILE_INFO +AddFile(LPTSTR FileName, + PEXTENSION_INFO ExtInfo) +{ + PFILE_INFO StatInfo; + PFILE_INFO Info; + + StatInfo = (PFILE_INFO) HeapAlloc (GetProcessHeap(), 0, sizeof (FILE_INFO)); + if (!StatInfo) + return NULL; + ZeroMemory (StatInfo, sizeof (FILE_INFO)); + _tcscpy (StatInfo->FileName, FileName); + StatInfo->ExtInfo = ExtInfo; + + if (ExtInfo->StatInfoList) + { + Info = ExtInfo->StatInfoList; + while (Info->StatInfoListNext != NULL) + { + Info = Info->StatInfoListNext; + } + Info->StatInfoListNext = StatInfo; + } + else + { + ExtInfo->StatInfoList = StatInfo; + } + + if (StatInfoList) + { + Info = StatInfoList; + while (Info->Next != NULL) + { + Info = Info->Next; + } + Info->Next = StatInfo; + } + else + { + StatInfoList = StatInfo; + } + + return StatInfo; +} + + +VOID +CleanupAfterFile() +{ + if (FileBuffer) + { + HeapFree (GetProcessHeap(), 0, FileBuffer); + FileBuffer = NULL; + } +} + + +BOOL +LoadFile(LPTSTR FileName) +{ + HANDLE FileHandle; + DWORD BytesRead; + LONG FileSize; + + FileHandle = CreateFile (FileName, // Create this file + GENERIC_READ, // Open for reading + 0, // No sharing + NULL, // No security + OPEN_EXISTING, // Open the file + FILE_ATTRIBUTE_NORMAL, // Normal file + NULL); // No attribute template + if (FileHandle == INVALID_HANDLE_VALUE) + return FALSE; + + FileSize = GetFileSize (FileHandle, NULL); + if (FileSize < 0) + { + CloseHandle (FileHandle); + return FALSE; + } + + FileBufferSize = (DWORD) FileSize; + + FileBuffer = (PCHAR) HeapAlloc (GetProcessHeap(), 0, FileBufferSize); + if (!FileBuffer) + { + CloseHandle (FileHandle); + return FALSE; + } + + if (!ReadFile (FileHandle, FileBuffer, FileBufferSize, &BytesRead, NULL)) + { + CloseHandle(FileHandle); + HeapFree (GetProcessHeap(), 0, FileBuffer); + FileBuffer = NULL; + return FALSE; + } + + CloseHandle (FileHandle); + + CurrentOffset = 0; + CurrentLine = 0; + CurrentChar = 0; + + return TRUE; +} + + +BOOL +ReadLine() +/* + * FUNCTION: Reads the next line into the line buffer + * RETURNS: + * TRUE if there is a new line, FALSE if not + */ +{ + ULONG i, j; + TCHAR ch; + + if (CurrentOffset >= FileBufferSize) + return FALSE; + + i = 0; + while (((j = CurrentOffset + i) < FileBufferSize) && (i < sizeof (Line)) && + ((ch = FileBuffer[j]) != 0x0D)) + { + Line[i] = ch; + i++; + } + + Line[i] = '\0'; + LineLength = i; + + if (FileBuffer[CurrentOffset + i + 1] == 0x0A) + CurrentOffset++; + + CurrentOffset += i + 1; + + CurrentChar = 0; + + CurrentLine++; + + return TRUE; +} + + +VOID +DoStatisticsForFile(PFILE_INFO StatInfo) +{ + while (ReadLine()) + { + } + StatInfo->LineCount = CurrentLine; +} + + +VOID +PrintStatistics() +{ + PEXTENSION_INFO Info; + DWORD TotalFileCount; + DWORD TotalLineCount; + DWORD TotalAvgLF; + + TotalFileCount = 0; + TotalLineCount = 0; + Info = ExtInfoList; + + while (Info != NULL) + { + DWORD AvgLF; + + if (Info->FileCount != 0) + { + AvgLF = Info->LineCount / Info->FileCount; + } + else + { + AvgLF = 0; + } + + _tprintf (_T("\n")); + _tprintf (_T("File extension : %s\n"), Info->ExtName); + _tprintf (_T("File ext. description : %s\n"), Info->Description); + _tprintf (_T("Number of files : %d\n"), Info->FileCount); + _tprintf (_T("Number of lines : %d\n"), Info->LineCount); + _tprintf (_T("Average no. lines/file : %d\n"), AvgLF); + + TotalFileCount += Info->FileCount; + TotalLineCount += Info->LineCount; + + Info = Info->Next; + } + + TotalAvgLF = TotalLineCount / TotalFileCount; + + _tprintf (_T("\n")); + _tprintf (_T("Total number of files : %d\n"), TotalFileCount); + _tprintf (_T("Total number of lines : %d\n"), TotalLineCount); + _tprintf (_T("Average no. lines/file : %d\n"), TotalAvgLF); +} + + +BOOL +ProcessFiles(LPTSTR Path) +{ + WIN32_FIND_DATA FindFile; + PEXTENSION_INFO Info; + TCHAR SearchPath[256]; + TCHAR FileName[256]; + HANDLE SearchHandle; + BOOL More; + + Info = ExtInfoList; + while (Info != NULL) + { + ZeroMemory (&FindFile, sizeof (FindFile)); + _tcscpy (SearchPath, Path); + _tcscat (SearchPath, _T("\\*.")); + _tcscat (SearchPath, Info->ExtName); + _tcscpy (FindFile.cFileName, SearchPath); + SearchHandle = FindFirstFile (SearchPath, &FindFile); + if (SearchHandle != INVALID_HANDLE_VALUE) + { + More = TRUE; + while (More) + { + if (!(FindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + _tcscpy (FileName, Path); + _tcscat (FileName, _T("\\")); + _tcscat (FileName, FindFile.cFileName); + + if (LoadFile (FileName)) + { + PFILE_INFO StatInfo; + + StatInfo = AddFile (FindFile.cFileName, Info); + if (!StatInfo) + { + _tprintf (_T("Not enough free memory.\n")); + return FALSE; + } + + DoStatisticsForFile (StatInfo); + + Info->FileCount++; + Info->LineCount += StatInfo->LineCount; + + CleanupAfterFile(); + } + } + More = FindNextFile (SearchHandle, &FindFile); + } + FindClose (SearchHandle); + } + Info = Info->Next; + } + return TRUE; +} + + +BOOL +ProcessDirectories(LPTSTR Path) +{ + WIN32_FIND_DATA FindFile; + TCHAR SearchPath[MAX_PATH]; + HANDLE SearchHandle; + BOOL More; + + _tprintf (_T("Processing directory %s\n"), Path); + + _tcscpy (SearchPath, Path); + _tcscat (SearchPath, _T("\\*.*")); + + SearchHandle = FindFirstFileEx (SearchPath, + FindExInfoStandard, + &FindFile, + FindExSearchLimitToDirectories, + NULL, + 0); + if (SearchHandle != INVALID_HANDLE_VALUE) + { + More = TRUE; + while (More) + { + if ((FindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + && (_tcscmp (FindFile.cFileName, _T(".")) != 0) + && (_tcscmp (FindFile.cFileName, _T("..")) != 0) + && (_tcscmp (FindFile.cFileName, _T("CVS")) != 0)) + { + _tcscpy (SearchPath, Path); + _tcscat (SearchPath, _T("\\")); + _tcscat (SearchPath, FindFile.cFileName); + if (!ProcessDirectories (SearchPath)) + return FALSE; + if (!ProcessFiles (SearchPath)) + return FALSE; + } + More = FindNextFile (SearchHandle, &FindFile); + } + FindClose (SearchHandle); + } + return TRUE; +} + + +VOID +Execute(LPTSTR Path) +{ + if (!ExtInfoList) + { + _tprintf (_T("No extensions specified.\n")); + return; + } + + if (!ProcessDirectories (Path)) + { + _tprintf (_T("Failed to process directories.\n")); + return; + } + + if (!ProcessFiles (Path)) + { + _tprintf (_T("Failed to process files.\n")); + return; + } + + PrintStatistics(); +} + + +int +main (int argc, char * argv []) +{ + _tprintf (_T("\nReactOS project statistics generator.\n\n")); + + if (argc < 2) + { + _tprintf(_T("Usage: stats directory")); + return 1; + } + + Initialize(); + AddExtension (_T("c"), _T("Source files")); + AddExtension (_T("h"), _T("Header files")); + Execute (argv[1]); + Cleanup(); + + return 0; +} diff --git a/baseaddress.cfg b/baseaddress.cfg new file mode 100644 index 0000000..fa86ada --- /dev/null +++ b/baseaddress.cfg @@ -0,0 +1,55 @@ +# Please try to keep this up2date. Please clean up +# after yourself. + +REACTOS + +lib/advapi32 TARGET_BASE=0x77dc0000 +lib/crtdll TARGET_BASE=0x77630000 +lib/fmifs TARGET_BASE=0x76df0000 +lib/gdi32 TARGET_BASE=0x77ed0000 +lib/kernel32 TARGET_BASE=0x77f00000 +lib/msafd TARGET_BASE=0x777a0000 +lib/msvcrt TARGET_BASE=0x78000000 +lib/ntdll TARGET_BASE=0x77f60000 +lib/ole32 TARGET_BASE=0x77a50000 +lib/oleaut32 TARGET_BASE=0x76260000 +lib/secur32 TARGET_BASE=0x10000000 +lib/shell32 TARGET_BASE=0x77260000 +lib/user32 TARGET_BASE=0x77e70000 +lib/version TARGET_BASE=0x77a90000 +lib/ws2_32 TARGET_BASE=0x77780000 +services/dd/vga/display TARGET_BASE=0x70000000 +services/net/wshtcpip TARGET_BASE=0x777c0000 +subsys/psx/lib/psxdll TARGET_BASE=0x68EB0000 +subsys/psx/lib/psxx # TARGET_BASE=0x77dc0000 +subsys/win32k TARGET_BASE=0x0 + + + +WINE + +dlls/comctl32 TARGET_BASE=0x76160000 +dlls/commdlg TARGET_BASE=0x76200000 +dlls/ddraw TARGET_BASE=0x76240000 +dlls/dinput TARGET_BASE=0x76280000 +dlls/dplay TARGET_BASE=0x76320000 +dlls/dplayx TARGET_BASE=0x76310000 +dlls/mapi32 TARGET_BASE=0x76430000 +dlls/ole32 TARGET_BASE=0x76010000 +dlls/oleaut32 TARGET_BASE=0x76040000 +dlls/olecli TARGET_BASE=0x76070000 +dlls/oledlg TARGET_BASE=0x76050000 +dlls/olepro32 TARGET_BASE=0x76060000 +dlls/olesvr TARGET_BASE=0x76080000 +dlls/psapi TARGET_BASE=0x76330000 +dlls/url TARGET_BASE=0x76530000 +dlls/urlmon TARGET_BASE=0x76730000 +dlls/richedit TARGET_BASE=0x76340000 +dlls/rpcrt4 TARGET_BASE=0x76000000 +dlls/serialui TARGET_BASE=0x76370000 +dlls/shdocvw TARGET_BASE=0x76190000 +dlls/shell32 TARGET_BASE=0x76090000 +dlls/shfolder TARGET_BASE=0x76180000 +dlls/shlwapi TARGET_BASE=0x76120000 +dlls/winspool TARGET_BASE=0x76380000 +unicode/wine_unicode TARGET_BASE=0x76590000 #Do not use \ No newline at end of file diff --git a/boot.bat b/boot.bat new file mode 100644 index 0000000..9c497d4 --- /dev/null +++ b/boot.bat @@ -0,0 +1 @@ +loadros system32\ntoskrnl.exe system32\hal.dll /DEBUGPORT=SCREEN bootc.lst diff --git a/boot.hiv b/boot.hiv new file mode 100644 index 0000000..da41d09 --- /dev/null +++ b/boot.hiv @@ -0,0 +1,46 @@ +REGEDIT4 + +[\Registry\Machine\HARDWARE] + +[\Registry\Machine\HARDWARE\DESCRIPTION] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0] +"Component Information"=hex:00,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff +"Identifier"="ISA" +"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\KeyboardController] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\KeyboardController\0] +"Component Information"=hex:28,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff +"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,03,00,00,00,01,\ + 01,01,00,60,00,00,00,00,00,00,00,01,00,00,00,01,01,01,00,64,00,00,00,00,00,\ + 00,00,01,00,00,00,02,00,01,00,01,00,00,00,01,00,00,00,ff,ff,ff,ff + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\KeyboardController\0\KeyboardPeripheral] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\KeyboardController\0\KeyboardPeripheral\0] +"Component Information"=hex:28,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff +"Identifier"="PCAT_ENHANCED" +"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,05,\ + 00,00,00,08,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,04,00,00,00 + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\PointerController] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\PointerController\0] +"Component Information"=hex:20,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff +"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,01,00,00,00,02,\ + 00,01,00,0c,00,00,00,0c,00,00,00,ff,ff,ff,ff + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\PointerController\0\PointerPeripheral] + +[\Registry\Machine\HARDWARE\DESCRIPTION\System\MultifunctionAdapter\0\PointerController\0\PointerPeripheral\0] +"Component Information"=hex:20,00,00,00,00,00,00,00,00,00,00,00,ff,ff,ff,ff +"Identifier"="MICROSOFT PS2 MOUSE" +"Configuration Data"=hex(9):01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 + + diff --git a/bootc.lst b/bootc.lst new file mode 100644 index 0000000..28ae66a --- /dev/null +++ b/bootc.lst @@ -0,0 +1,7 @@ +system32\drivers\scsiport.sys +system32\drivers\atapi.sys +system32\drivers\class2.sys +system32\drivers\disk.sys +system32\drivers\vfatfs.sys +system32\config\system.hiv +* diff --git a/bootcd.bat b/bootcd.bat new file mode 100755 index 0000000..f1e1c30 --- /dev/null +++ b/bootcd.bat @@ -0,0 +1,24 @@ +@echo off +set BOOTCD_DIR=..\bootcd + +md %BOOTCD_DIR% +md %BOOTCD_DIR%\disk +md %BOOTCD_DIR%\disk\bootdisk +md %BOOTCD_DIR%\disk\install +md %BOOTCD_DIR%\disk\reactos +md %BOOTCD_DIR%\disk\reactos\system32 +copy /Y ntoskrnl\ntoskrnl.exe %BOOTCD_DIR%\disk\reactos +copy /Y hal\halx86\hal.dll %BOOTCD_DIR%\disk\reactos +copy /Y drivers\fs\vfat\vfatfs.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\fs\cdfs\cdfs.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\fs\ntfs\ntfs.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\dd\floppy\floppy.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\dd\blue\blue.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\input\keyboard\keyboard.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\storage\atapi\atapi.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\storage\scsiport\scsiport.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\storage\cdrom\cdrom.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\storage\disk\disk.sys %BOOTCD_DIR%\disk\reactos +copy /Y drivers\storage\class2\class2.sys %BOOTCD_DIR%\disk\reactos +copy /Y lib\ntdll\ntdll.dll %BOOTCD_DIR%\disk\reactos\system32 +copy /Y subsys\system\usetup\usetup.exe %BOOTCD_DIR%\disk\reactos\system32\smss.exe diff --git a/bootflop.bat b/bootflop.bat new file mode 100644 index 0000000..5fc711c --- /dev/null +++ b/bootflop.bat @@ -0,0 +1,32 @@ +@ECHO OFF + +: +: copy files to HD... +: +COPY /Y A:\DRIVERS\*.SYS C:\reactos\system32\drivers > NUL: +COPY /Y A:\DLLS\*.DLL C:\reactos\system32 > NUL: +COPY /Y A:\APPS\*.EXE C:\reactos\system32 > NUL: +COPY /Y A:\SUBSYS\*.EXE C:\reactos\system32 > NUL: +COPY /Y A:\SUBSYS\*.DLL C:\reactos\system32 > NUL: +: +: present a menu to the booter... +: +: ECHO 1) IDE,VFatFSD +: ECHO 2) No Drivers +: CHOICE /C:123 /T:1,3 "Select kernel boot config" +: IF ERRORLEVEL 2 GOTO :L2 + +:L1 +CLS +LOADROS NTOSKRNL.EXE DRIVERS\IDE.SYS DRIVERS\VFATFSD.SYS +GOTO :END + +:L2 +CLS +LOADROS NTOSKRNL.EXE +GOTO :END + +:END +EXIT + + diff --git a/config b/config new file mode 100644 index 0000000..a907ccd --- /dev/null +++ b/config @@ -0,0 +1,33 @@ +# +# Architecture to build for +# +# Specify one of: i386 +# Possible values in the future: alpha,i386,m68k,mips,powerpc +ARCH := i386 + +# +# Whether to compile in the kernel debugger +# +KDBG := 0 + +# +# Whether to compile for debugging +# +DBG := 0 + +# +# Whether to compile a multiprocessor or single processor version +# +MP := 0 + +# +# Whether to compile for ACPI compliant systems +# +ACPI := 0 + + +# +# Which version of NDIS do we support up to? +# +#NDISVERSION=NDIS50 + diff --git a/dk/nkm/.cvsignore b/dk/nkm/.cvsignore new file mode 100644 index 0000000..7951405 --- /dev/null +++ b/dk/nkm/.cvsignore @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/dk/nkm/Makefile b/dk/nkm/Makefile new file mode 100644 index 0000000..595d3cb --- /dev/null +++ b/dk/nkm/Makefile @@ -0,0 +1,150 @@ +# $Id$ +# +# PROJECT : ReactOS Operating System +# FILE : reactos/dk/nkm/Makefile +# DESCRIPTION: Build the development kit for kernel mode modules +# DESCRIPTION: and user mode native applications (subsystem 1). +# LICENSE : GNU GPL V2.0 +# +PATH_TO_TOP=../.. + +include $(PATH_TO_TOP)/rules.mak + + +TARGET_FOLDER_LIB=lib +TARGET_FOLDER_INC=include + +DTFLAGS = -k -l $@ + +MODULES_CORE=\ + $(TARGET_FOLDER_LIB)/ntoskrnl.a +# $(TARGET_FOLDER_LIB)/hal.a + +MODULES_DISPLAY=\ + $(TARGET_FOLDER_LIB)/vgaddi.a\ + $(TARGET_FOLDER_LIB)/vidport.a + +MODULES_NET=\ + $(TARGET_FOLDER_LIB)/afd.a\ + $(TARGET_FOLDER_LIB)/ndis.a\ + $(TARGET_FOLDER_LIB)/packet.a\ + $(TARGET_FOLDER_LIB)/tcpip.a + +MODULES_STORAGE=\ + $(TARGET_FOLDER_LIB)/class2.a\ + $(TARGET_FOLDER_LIB)/scsiport.a + +MODULES_NATIVE=\ + $(TARGET_FOLDER_LIB)/ntdll.a\ + $(TARGET_FOLDER_LIB)/fmifs.a + +MODULES =\ + $(MODULES_CORE)\ + $(MODULES_DISPLAY)\ + $(MODULES_NET)\ + $(MODULES_STORAGE)\ + $(MODULES_NATIVE) + + +all: $(MODULES) + +# --- CORE --- + +$(TARGET_FOLDER_LIB)/ntoskrnl.a: $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D ntoskrnl.exe\ + -d $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.def + +$(TARGET_FOLDER_LIB)/hal.a: $(PATH_TO_TOP)/ntoskrnl/hal/x86/hal.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D hal.dll\ + -d $(PATH_TO_TOP)/ntoskrnl/hal/x86/hal.def + +# --- DISPLAY --- + +$(TARGET_FOLDER_LIB)/vgaddi.a: $(PATH_TO_TOP)/drivers/dd/vga/display/vgaddi.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D vgaddi.dll\ + -d $(PATH_TO_TOP)/drivers/dd/vga/display/vgaddi.def + +$(TARGET_FOLDER_LIB)/vidport.a: $(PATH_TO_TOP)/drivers/dd/vidport/vidport.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D vidport.sys\ + -d $(PATH_TO_TOP)/drivers/dd/vidport/vidport.def + +# --- NET --- + +$(TARGET_FOLDER_LIB)/afd.a: $(PATH_TO_TOP)/drivers/net/afd/afd.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D afd.sys\ + -d $(PATH_TO_TOP)/drivers/net/afd/afd.def + +$(TARGET_FOLDER_LIB)/ndis.a: $(PATH_TO_TOP)/drivers/net/ndis/ndis.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D ndis.sys\ + -d $(PATH_TO_TOP)/drivers/net/ndis/ndis.def + +$(TARGET_FOLDER_LIB)/tcpip.a: $(PATH_TO_TOP)/drivers/net/tcpip/tcpip.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D tcpip.sys\ + -d $(PATH_TO_TOP)/drivers/net/tcpip/tcpip.def + +$(TARGET_FOLDER_LIB)/packet.a: $(PATH_TO_TOP)/drivers/net/packet/packet.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D packet.sys\ + -d $(PATH_TO_TOP)/drivers/net/packet/packet.def + +$(TARGET_FOLDER_LIB)/tdi.a: $(PATH_TO_TOP)/drivers/net/tdi/misc/tdi.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D tdi.sys\ + -d $(PATH_TO_TOP)/drivers/net/tdi/misc/tdi.def + +# --- STORAGE --- + +$(TARGET_FOLDER_LIB)/class2.a: $(PATH_TO_TOP)/drivers/storage/class2/class2.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D class2.sys\ + -d $(PATH_TO_TOP)/drivers/storage/class2/class2.def + +$(TARGET_FOLDER_LIB)/scsiport.a: $(PATH_TO_TOP)/drivers/storage/scsiport/scsiport.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D scsiport.sys\ + -d $(PATH_TO_TOP)/drivers/storage/scsiport/scsiport.def + +# --- NATIVE --- + +$(TARGET_FOLDER_LIB)/ntdll.a: $(PATH_TO_TOP)/lib/ntdll/def/ntdll.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D ntdll.dll\ + -d $(PATH_TO_TOP)/lib/ntdll/def/ntdll.def + +$(TARGET_FOLDER_LIB)/fmifs.a: $(PATH_TO_TOP)/lib/fmifs/fmifs.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D fmifs.dll\ + -d $(PATH_TO_TOP)/lib/fmifs/fmifs.def + +# --- Service rules --- + +clean: + - $(RM) $(TARGET_FOLDER_LIB)/*.a + - $(RM) $(TARGET_FOLDER_INC)/*.h + +install: + +dist: + +#EOF + diff --git a/dk/psx/.cvsignore b/dk/psx/.cvsignore new file mode 100644 index 0000000..38a421c --- /dev/null +++ b/dk/psx/.cvsignore @@ -0,0 +1,2 @@ +lib +include \ No newline at end of file diff --git a/dk/psx/Makefile b/dk/psx/Makefile new file mode 100644 index 0000000..25b6989 --- /dev/null +++ b/dk/psx/Makefile @@ -0,0 +1,59 @@ +# $Id$ +# +# PROJECT : ReactOS Operating System +# FILE : reactos/dk/w32/Makefile +# DESCRIPTION: Build the development kit for user mode application +# DESCRIPTION: to be run in the subsystems 6 (POSIX_GUI) +# DESCRIPTION: and 7 (POSIX_CUI). +# LICENSE : GNU GPL V2.0 +# +PATH_TO_TOP=../.. + +PATH_TO_PSX_TOP=$(PATH_TO_TOP)/../posix + +include $(PATH_TO_TOP)/rules.mak + + +TARGET_FOLDER_LIB=$(PATH_TO_TOP)/dk/psx/lib +TARGET_FOLDER_INC=$(PATH_TO_TOP)/dk/psx/include + +DTFLAGS = -k -l $@ + +MODULES_CORE=\ + $(TARGET_FOLDER_LIB)/psxdll.a\ + $(TARGET_FOLDER_LIB)/psxx.a + + +MODULES =\ + $(MODULES_CORE) + +# --- Rules --- + +all: $(MODULES) + +# --- CORE --- + +$(TARGET_FOLDER_LIB)/psxdll.a: $(PATH_TO_PSX_TOP)/lib/psxdll/psxdll.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D psxdll.dll\ + -d $< + +$(TARGET_FOLDER_LIB)/psxx.a: $(PATH_TO_PSX_TOP)/lib/psxx/misc/psxx.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D psxx.dll\ + -d $< + +# --- Service rules --- + +clean: + - $(RM) $(TARGET_FOLDER_LIB)/*.a + - $(RM) $(TARGET_FOLDER_INC)/*.h + +install: + +dist: + +#EOF + diff --git a/dk/readme.txt b/dk/readme.txt new file mode 100644 index 0000000..d8fb0a4 --- /dev/null +++ b/dk/readme.txt @@ -0,0 +1,21 @@ +$Id$ + +Development Kits for ReactOS +---------------------------- + + +DDK - Device Driver Development Kit (dk/nkm) + + Kernel mode modules and native user mode applications. + + +SDK - Software Development Kit (dk/w32) + + User mode Win32(tm) applications. + + +XDK - POSIX+ Development Kit (dk/psx) + + User mode POSIX+ applications. + +EOF diff --git a/dk/w32/.cvsignore b/dk/w32/.cvsignore new file mode 100644 index 0000000..7951405 --- /dev/null +++ b/dk/w32/.cvsignore @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/dk/w32/Makefile b/dk/w32/Makefile new file mode 100644 index 0000000..aa142c7 --- /dev/null +++ b/dk/w32/Makefile @@ -0,0 +1,231 @@ +# $Id$ +# +# PROJECT : ReactOS Operating System +# FILE : reactos/dk/w32/Makefile +# DESCRIPTION: Build the development kit for user mode application +# DESCRIPTION: to be run in the subsystems 2 (WINDOWS_GUI) +# DESCRIPTION: and 3 (WINDOWS_CUI). +# LICENSE : GNU GPL V2.0 +# +PATH_TO_TOP=../.. + +SHELL32_ALIAS = roshel32 +COMCTL32_ALIAS = rosctl32 + + +include $(PATH_TO_TOP)/rules.mak + + +TARGET_FOLDER_LIB=lib +TARGET_FOLDER_INC=include + +DTFLAGS = -k -l $@ + +MODULES_CORE=\ + $(TARGET_FOLDER_LIB)/kernel32.a\ + $(TARGET_FOLDER_LIB)/gdi32.a\ + $(TARGET_FOLDER_LIB)/user32.a + +MODULES_ADVANCED=\ + $(TARGET_FOLDER_LIB)/advapi32.a\ + $(TARGET_FOLDER_LIB)/secur32.a + +MODULES_SHELL=\ + $(TARGET_FOLDER_LIB)/comctl32.a\ + $(TARGET_FOLDER_LIB)/shell32.a\ + $(TARGET_FOLDER_LIB)/$(COMCTL32_ALIAS).a\ + $(TARGET_FOLDER_LIB)/$(SHELL32_ALIAS).a + +MODULES_NET=\ + $(TARGET_FOLDER_LIB)/iphlpapi.a\ + $(TARGET_FOLDER_LIB)/msafd.a\ + $(TARGET_FOLDER_LIB)/snmpapi.a\ + $(TARGET_FOLDER_LIB)/ws2_32.a\ + $(TARGET_FOLDER_LIB)/wshirda.a\ + $(TARGET_FOLDER_LIB)/wsock32.a + +MODULES_COM=\ + $(TARGET_FOLDER_LIB)/ole32.a\ + $(TARGET_FOLDER_LIB)/oleaut32.a +# $(TARGET_FOLDER_LIB)/rpcrt4.a + +MODULES_CRT=\ + $(TARGET_FOLDER_LIB)/crtdll.a\ + $(TARGET_FOLDER_LIB)/msvcrt.a + +MODULES_MISC=\ + $(TARGET_FOLDER_LIB)/version.a + +MODULES =\ + $(MODULES_CORE)\ + $(MODULES_ADVANCED)\ + $(MODULES_SHELL)\ + $(MODULES_NET)\ + $(MODULES_COM)\ + $(MODULES_CRT)\ + $(MODULES_MISC) + +# --- Rules --- + +all: $(MODULES) + +# --- CORE --- + + + +$(TARGET_FOLDER_LIB)/kernel32.a: $(PATH_TO_TOP)/lib/kernel32/kernel32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D kernel32.dll\ + -d $(PATH_TO_TOP)/lib/kernel32/kernel32.def + +$(TARGET_FOLDER_LIB)/gdi32.a: $(PATH_TO_TOP)/lib/gdi32/gdi32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D gdi32.dll\ + -d $(PATH_TO_TOP)/lib/gdi32/gdi32.def + +$(TARGET_FOLDER_LIB)/user32.a: $(PATH_TO_TOP)/lib/user32/user32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D user32.dll\ + -d $(PATH_TO_TOP)/lib/user32/user32.def + +# --- ADVANCED --- + +$(TARGET_FOLDER_LIB)/advapi32.a: $(PATH_TO_TOP)/lib/advapi32/advapi32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D advapi32.dll\ + -d $(PATH_TO_TOP)/lib/advapi32/advapi32.def + +$(TARGET_FOLDER_LIB)/secur32.a: $(PATH_TO_TOP)/lib/secur32/secur32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D secur32.dll\ + -d $(PATH_TO_TOP)/lib/secur32/secur32.def + +# --- SHELL --- + +$(TARGET_FOLDER_LIB)/shell32.a: $(PATH_TO_TOP)/lib/shell32/shell32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D shell32.dll\ + -d $(PATH_TO_TOP)/lib/shell32/shell32.def + +$(TARGET_FOLDER_LIB)/comctl32.a: $(PATH_TO_TOP)/../wine/dlls/comctl32/comctl32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D comctl32.dll\ + -d $(PATH_TO_TOP)/../wine/dlls/comctl32/comctl32.def + + +$(TARGET_FOLDER_LIB)/$(SHELL32_ALIAS).a: $(PATH_TO_TOP)/lib/shell32/shell32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D $(SHELL32_ALIAS).dll\ + -d $(PATH_TO_TOP)/lib/shell32/shell32.def + +$(TARGET_FOLDER_LIB)/$(COMCTL32_ALIAS).a: $(PATH_TO_TOP)/../wine/dlls/comctl32/comctl32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D $(COMCTL32_ALIAS).dll\ + -d $(PATH_TO_TOP)/../wine/dlls/comctl32/comctl32.def + +#$(TARGET_FOLDER_LIB)/$(COMCTL32_ALIAS).a: $(PATH_TO_TOP)/lib/comctl32/comctl32.def +# -d $(PATH_TO_TOP)/lib/comctl32/comctl32.def + +# --- NET --- + +$(TARGET_FOLDER_LIB)/iphlpapi.a: $(PATH_TO_TOP)/lib/iphlpapi/iphlpapi.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D iphlpapi.dll\ + -d $(PATH_TO_TOP)/lib/iphlpapi/iphlpapi.def + +$(TARGET_FOLDER_LIB)/msafd.a: $(PATH_TO_TOP)/lib/msafd/msafd.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D msafd.dll\ + -d $(PATH_TO_TOP)/lib/msafd/msafd.def + +$(TARGET_FOLDER_LIB)/snmpapi.a: $(PATH_TO_TOP)/lib/snmpapi/snmpapi.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D snmpapi.dll\ + -d $(PATH_TO_TOP)/lib/snmpapi/snmpapi.def + +$(TARGET_FOLDER_LIB)/ws2_32.a: $(PATH_TO_TOP)/lib/ws2_32/ws2_32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D ws2_32.dll\ + -d $(PATH_TO_TOP)/lib/ws2_32/ws2_32.def + +$(TARGET_FOLDER_LIB)/wshirda.a: $(PATH_TO_TOP)/lib/wshirda/wshirda.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D wshirda.dll\ + -d $(PATH_TO_TOP)/lib/wshirda/wshirda.def + +$(TARGET_FOLDER_LIB)/wsock32.a: $(PATH_TO_TOP)/lib/wsock32/wsock32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D wsock32.dll\ + -d $(PATH_TO_TOP)/lib/wsock32/wsock32.def + +# --- COM --- + +$(TARGET_FOLDER_LIB)/ole32.a: $(PATH_TO_TOP)/lib/ole32/ole32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D ole32.dll\ + -d $(PATH_TO_TOP)/lib/ole32/ole32.def + +$(TARGET_FOLDER_LIB)/oleaut32.a: $(PATH_TO_TOP)/lib/oleaut32/oleaut32.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D oleaut32.dll\ + -d $(PATH_TO_TOP)/lib/oleaut32/oleaut32.def + +$(TARGET_FOLDER_LIB)/rpcrt4.a: $(PATH_TO_TOP)/lib/rpcrt4/rpcrt4.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D rpcrt4.dll\ + -d $(PATH_TO_TOP)/lib/rpcrt4/rpcrt4.def + +# --- CRT --- + +$(TARGET_FOLDER_LIB)/crtdll.a: $(PATH_TO_TOP)/lib/crtdll/crtdll.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D crtdll.dll\ + -d $(PATH_TO_TOP)/lib/crtdll/crtdll.def + +$(TARGET_FOLDER_LIB)/msvcrt.a: $(PATH_TO_TOP)/lib/msvcrt/msvcrt.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D msvcrt.dll\ + -d $(PATH_TO_TOP)/lib/msvcrt/msvcrt.def + +# --- MISC --- + +$(TARGET_FOLDER_LIB)/version.a: $(PATH_TO_TOP)/lib/version/version.def + $(DLLTOOL) \ + $(DTFLAGS)\ + -D version.dll\ + -d $(PATH_TO_TOP)/lib/version/version.def + +# --- Service rules --- + +clean: + - $(RM) $(TARGET_FOLDER_LIB)/$(MODULES) + +# - $(RM) $(TARGET_FOLDER_LIB)/*.a +# - $(RM) $(TARGET_FOLDER_INC)/*.h + +install: + +dist: + +#EOF + diff --git a/doc/DIRS b/doc/DIRS new file mode 100644 index 0000000..576ac41 --- /dev/null +++ b/doc/DIRS @@ -0,0 +1,24 @@ +DIRECTORIES + +apps : applications (base directory) +apps/net : network applications +apps/system : system applications (required for startup) +doc : documentation +include : win32 headers +include/internal : kernel private header files +include/ntdll : system library private header files +include/kernel32 : system library private header files +include/ddk : header files for modules +lib/advapi32 : advapi32 source +lib/kernel32 : kernel32 source +lib/ntdll : NT dll source +loaders/dos : DOS based loader +loaders/boot : boot loader +ntoskrnl : kernel source +ntoskrnl/hal : hardware abstraction layer source +ntoskrnl/mm : memory managment subsystem source +ntoskrnl/io : IO manager subsystem source +ntoskrnl/ke : kernel source +services : various services (device drivers, filesystems etc) +services/dd : device drivers +services/fs : file systems diff --git a/doc/HACKING b/doc/HACKING new file mode 100644 index 0000000..8c8cf4e --- /dev/null +++ b/doc/HACKING @@ -0,0 +1,130 @@ +* Introduction + +Having successfully built ReactOS and been amazed by what it does, you're +now desperate to fill in some of the omissions, this document shows you how. + +* Prerequisites + +A working knowledge of NT driver development is useful for understanding the +kernel and some of its abstractions. The NT4 ddk is available for free +download from http://www.microsoft.com/hwdev/. The Windows 98 and Windows +2000 DDKs are also available but the NT4 one is the most useful. See +Legal Stuff below however. + +There are a number of books on NT driver development, I would recommend +'Windows NT Device Driver Development' (http://www.osr.com/book/) since OSR +seem to know their stuff. There is only one book on NT filesystem +development 'Windows NT File System Internals'. Please don't buy any of +these books unless you need to, and can afford it. + +These mailing lists and newsgroups are useful for NT internals related +questions, + ntfsd@atria.com, ntdev@atria.com + (subscribe by email to majordomo@atria.com) + comp.os.???? + microsoft.public.???? + +* Style + +There is no coding style used for ReactOS, however the following guidelines +make things easier + + Include information at the top of a module about its purpose, contact + information for its programmer and any useful notes. + + Include a comment by each non-trival function describing its arguments, + purpose and any other notes. + + Update the documentation in this directory + +These guidelines are an ideal, no one manages to implement them all the +time, straightforward working code is probably just as good. + +* Debugging + +Debugging kernel-mode code is tricky, these are some snippets + + DbgPrint writes a message to the console using a printf style format + string. The DPRINT macro (defined in internal/debug.h) expands to + DbgPrint unless NDEBUG is defined, this is useful for having copious + output from a module only when a problem is being debugging. DPRINT + also prefixes the message with the file and line number to make it + easier to see where output is coming from. DbgPrint can be used at any + point including in interrupt handlers. + + There are options in ntoskrnl/kd/kdebug.c for copying DbgPrint output + to a serial device or bochs logging port (parallel support should also + be added). This can be useful if a lot of output is being generated. + + It should be possible to include support for debugging the kernel with + gdb over a serial line. Bochs (a shareware CPU emulator) is also useful + for debugging the kernel, I wrote some patches to allow capture of console + output from within bochs to file and for debugging a kernel running + under bochs with gdb. Contact me (welch@cwcom.net) if you're are + interested. + + If CPU reports an exception not handled by the kernel (any page fault + not part of virtual memory support or any other exception) the kernel + will display output like this and halt + + General Protection Fault Exception: 13(0) + CS:EIP xxxxxxxx:xxxxxxx + DS xxxx ES xxxx FS xxxx GS xxxxx + EAX: xxxx EBX: xxxx + .... + EDI: xxxx EFLAGS: xxxx ESP: xxxx + cr2: xxxx + Stack: xxxx xxxx xxxx ... + .... + Frames: xxxx xxxx xxxx ... + .... + + The fault type will usually be either 'General Protection' or + 'Page Fault', see your Intel manual for the more exotic types. The + 'EIP' number is the address of the faulting instruction. If the 'CS' + number is 0x20 then the exception occured in kernel mode, if it is 0x11 + then the exception occurred in user mode. 'cr2' is the address that the + faulting instruction was trying to access, if the exception was a page + fault. The number printed after 'Frames' are any addresses on the stack + that look like function addresses. + + + If the kernel detects a serious problem that it will bug check, displaying + output like this + + Bug detected (code x, param x x x x) + Frames: xxx xxxx xxxx + .... + + Again the numbers printed after 'Frames' are any addresses on the stack + that look like function addresss. Usually the kernel will also print a + message describing the problem in more detail, the bug check code isn't + very useful at the moment. + +* Contacts + + There is a mailing list for kernel development, + + ros-kernel@reactos.com + + The main developers use a cvs account to coordinate changes, ask + rex (rex@lvcablemodem.com) for an account if you are going to be adding + a lot of code. Smaller patches can go to the mailing list or to the + relevant developer (usually the comment at the top of a module will have + an email address). Regular snapshots are made available for download, + see the mailing list for announcements. + +* Legal stuff + + The ReactOS project is GPL'ed, please make sure any code submitted is + compatible with this. + + The NT4 ddk license agreement allows its usage for developing nt drivers + only. Legally therefore it can not be used to develop ReactOS, neither the + documentation or the sample code. I'm not a lawyer, but I doubt the + effiacy of 'shrinkwrap licenses' particularly on freely downloadable + software. The only precendent I know of, in a Scottish court, didn't + upload this type of license. + + Also the 'fair use' section of copyright law allows the 'quoting' of small + sections from copyrighted documents, e.g. Windows API or DDK documentation diff --git a/doc/INDEX b/doc/INDEX new file mode 100644 index 0000000..2ec8549 --- /dev/null +++ b/doc/INDEX @@ -0,0 +1,6 @@ +HACKING: Some notes for adding code to ReactOS +DIRS: Explanation of directory layout +INTERNALS: Some notes on kernel internals +TODO: Bugs and omissions, big and little things that need to be done +NOTES: Unsorted material, some of it is redundant +BUGLIST: Known bugs, please update when you find one diff --git a/doc/INTERNALS b/doc/INTERNALS new file mode 100644 index 0000000..e294785 --- /dev/null +++ b/doc/INTERNALS @@ -0,0 +1,43 @@ +A collection of articles on kernel internals, please add to this + +------------------------------------------------------------------------------ +IRQ level +------------------------------------------------------------------------------ + +IRQ level (IRQL) is a per-processor state in ReactOS used to coordinate +execution between ISRs and between threads. There are several levels + + PASSIVE_LEVEL, APC_LEVEL: The normal level for user mode and most + kernel mode code. At the moment APC_LEVEL is unused. + + DISPATCH_LEVEL: At this level all irqs are still allowed but thread + rescheduling on the current processor is disabled. This is used by + the spinlock synchronization primitive to implement its uniprocessor + semantics (multiprocessor is more complex). It is also used for some + other forms of synchronization, DPCs for example. Many APIs are + unavailable at this IRQL, usually those that might have to wait. It + is recommended that you don't spend too much time at this IRQL + otherwise system responsiveness will be reduced. + + > DISPATCH_LEVEL: Each irq is assigned a priority (which will be + greater than DISPATCH_LEVEL). At an irq's priority level that irq, + lower priority irqs and thread rescheduling are disabled. Higher + priority irqs can still run. Very few APIs are available at IRQLs + greater than DISPATCH_LEVEL. + + HIGH_LEVEL: All irqs are disabled. + +------------------------------------------------------------------------------- +DPCs +------------------------------------------------------------------------------- + +It is a design goal not to spend too much time in ISRs, for this reason +ISRs should postpone most processing till it can run at a lower IRQL. The +mechanism for this is a Delayed Procedure Call (DPC). When a DPC object is +created, it is associated with a function. The DPC object can then be inserted +in the DPC queue from an ISR. If the IRQL on return from the ISR is less than +DISPATCH_LEVEL the DPC queue will be drained, otherwise this will happen when +the IRQL level drops below DISPATCH_LEVEL or the processor becomes idle. When +the DPC queue is drained each DPC object is removed and the associated +function is called at DISPATCH_LEVEL. A DPC object can only be inserted once, +further insertions before it is removed will have no effect. diff --git a/doc/apc b/doc/apc new file mode 100644 index 0000000..795ae83 --- /dev/null +++ b/doc/apc @@ -0,0 +1,36 @@ + APC + + Asynchronous procedure call + + An APC is a Kernel-defined control object representing a procedure + that is called asynchronously. APCs are thread-context dependent; that + is, they are queued to a particular thread for execution. + + There are three different kinds of APCs in NT: + + User APCs are used by certain asynchronous NT system services to allow + user-mode applications or protected subsystems to synchronize the + execution of a thread with the completion of an operation or the + occurrence of an event such as a timers expiration. User APCs are, by + default, disabled. That is, they are queued to the user-mode thread, + but they are not executed except at well-defined points in the + program. Specifically, they can only be executed when an application + or protected subsystem has called a wait service and has enabled + alerts to occur, or if it has called the test-alert service. + + Kernel APCs are normal kernel-mode APCs. They are much like a normal + user APC except that they are executable by default. That is, they are + enabled except when the thread is already executing a Kernel APC. + (Note that a special Kernel APC always preempts these.) + + Special Kernel APCs cannot be blocked except by running at a raised + IRQL. They are executed at APC_LEVEL IRQL (see IDT), in kernel mode. + These types of APCs are used by the system to force a thread to + execute a procedure in the threads context. An example of this is I/O + completion: the I/O Manager needs to get back into the context of the + original requestor of the I/O operation so that it can copy buffers, + and so forth. In order to do this, the I/O Manager must be able to + access the virtual address space of the thread/process, and the most + efficient way to complete the operation is to be in the calling + threads context. + diff --git a/doc/news1 b/doc/news1 new file mode 100644 index 0000000..04eab36 --- /dev/null +++ b/doc/news1 @@ -0,0 +1,142 @@ + + Correction / addition to Prasad's "Undocumented NT" + + From: dan_ps@my-deja.com + Reply to: dan_ps@my-deja.com + Date: Sun, 23 Apr 2000 10:03:30 GMT + Organization: Deja.com - Before you buy. + Newsgroups: + comp.os.ms-windows.programmer.nt.kernel-mode + Followup to: newsgroup + + + Recently , I had a chanche to borrow "Undocumented NT" by Mr Prasad +Dabak from one of my friends and read it. While reading the chapters +regarding builidng your own interrupt handlers or callgates under NT , +I found that the book glosses over very important topics such as IDT +in SMP enviroments , and a complete wrong presentation of what structure +a interrupt handler is supposed to build on the stack to ensure shamless +OS functionality. Mr's Prasad choice is a straigtforward pushad , +folowed by setting the FS segment to the ring0 PCR selector. This way +to build a trap frame for a interrupt is still used in Windows 95 , +but in Windows NT , the layout of a correct Trap Frame is a little bit +more complex. + The correct layout for a Trap Frame is the folowing: (note that +it consitis from two parts , a stack frame wich is built by the CPU +according to mode in wich was the CPU when the exception or software +interrupt was generated , and a Context Capure frame who has to be built +by the exception handler itself ) + +struc KeTrapFrame + +.DebugEBP resd 1 ; 00 +.DebugEIP resd 1 ; 04 +.DebugArgMark resd 1 ; 08 +.DebugPointer resd 1 ; 0C +.TempCS resd 1 ; 10 +.TempEsp resd 1 ; 14 + +.DR0 resd 1 ; 18 +.DR1 resd 1 ; 1C +.DR2 resd 1 ; 20 +.DR3 resd 1 ; 24 +.DR6 resd 1 ; 28 +.DR7 resd 1 ; 2C +.GS resw 1 ; 30 + resw 1 ; 32 +.ES resw 1 ; 34 + resw 1 ; 36 +.DS resw 1 ; 38 + resw 1 ; 3A +.EDX resd 1 ; 3C +.ECX resd 1 ; 40 +.EAX resd 1 ; 44 +.PreviousMode resd 1 ; 48 +.ExceptionList resd 1 ; 4C +.FS resw 1 ; 50 + resw 1 ; 52 +.EDI resd 1 ; 54 +.ESI resd 1 ; 58 +.EBX resd 1 ; 5C +.EBP resd 1 ; 60 +.Error resd 1 ; 64 +.EIP resd 1 ; 68 +.CS resw 1 ; 6C + resw 1 ; 6E +.EFLAGS resd 1 ; 70 +.ESP resd 1 ; 74 +.SS resw 1 ; 78 + resw 1 ; 7A +.ES_V86 resw 1 ; 7C + resw 1 ; 7E +.DS_V86 resw 1 ; 80 + resw 1 ; 82 +.FS_V86 resw 1 ; 84 + resw 1 ; 86 +.GS_V86 resw 1 ; 88 +endstruc + + Note that this is the complete layout of a TrapFrame structure. +Depending in what mode the CPU was when the exception occured , it may +break earlier than .GS_V86. Also , it seems that fields above .DR0 are +required only to debug builds. The declaration is for NASM , a free X86 +assembler , but this shouldnt have any kind of importance. + + Now why one should build the correct layout for this stack +frame ? The answer is that for shamlees operation of OS , a interrupt +handler HAS to poke into interrupted thread's KTHREAD strucure a +pointer to current TrapFrame existing on stack. This pointer will be +later used by several ntoskrnl API's to gain access to interrupted +thread;s acccess registers , or to gain information about the +interrupted thread's ring3 stack location , or simply to capture all +this information and package it into the form of a CONTEXT structure. +Since ntoskrnl assumes the above layout for a stack frame , using any +other structure size or layout can lead to unforeseen consequences. + + Other things wich one may want to do when building a stack +frame are : (assumes that the handler already set the FS register to +kernel PCR selector ) + + 1. Save old Exception List head , and patch -1 to FS:0 ( thus +overriding any potentialy pre-existing SEH handlers. + + 2. Determine whatever the interrupted thread was runing in +ring0 or in ring3 and save this information in PreviousMode field of +The Trap frame. This is also important , since many internal API's will +check the Provious mode , acting differently in each case. (check CS +image on stack for this ) + + 3. Get a pointer to the top of KeTrapFrame , and patch it into +KTHREAD structure, at KTHREAD->TrapFrame. if ya want the layout of +TrapFrame , there are multiple places where one can get it , but Im +willing to post it here on request. + + 4. In the case that the hardware stack built by CPU does not +contain an error code , fake one ( generaly , aborts always push an +error code on stack , some exceptions do , and traps never push an +error code by deafult. Suplimentary information can be found in intel +arch. reference manual . + + 5. Optionaly enable the interrupts trough a STI . NT uses +usualy interrupt gates , so the CPU will clear IF upon entering an +exception handler. Note that in the case handling the interrupt or +exception trough a trap gate , IF will not be automaticly cleared. + + If you are interesting in the code wich can actualy build such +a structure on the stack , use a kernel debugger and Break on Int +0x2E , and single step the code . + + As last words , I want to ensure Mr Prasad of my respect , and +the thing that the only reason for this posting is my feeling that all +holes must be covered , for the sake of all NT driver writing comunity. + + Later , Dan + + + + + + + +Sent via Deja.com http://www.deja.com/ +Before you buy. diff --git a/doc/news2 b/doc/news2 new file mode 100644 index 0000000..af0d3b8 --- /dev/null +++ b/doc/news2 @@ -0,0 +1,52 @@ + + Re: alternative to SeCaptureSubjectContext for Win2000 sought + + From: "dave porter" + Reply to: "dave porter" + Date: Mon, 26 Jun 2000 10:57:18 -0400 + Newsgroups: + comp.os.ms-windows.programmer.nt.kernel-mode + Followup to: newsgroup + References: + <39520e7f$0$15896@wodc7nh1.news.uu.net> + + <39575985$0$24336@wodc7nh0.news.uu.net> + + +> Under advise, I have tried ZwOpenProcessToken(), but to little avail. +> ZwQueryInformationToken( ..TokenUser ...) doesn't seem to want to do its +job +> either under NT4. + +I could be jumping in the middle here, but in what way doesn't it work? +This code works for me: + + int bufLen = 256; // we suppose this is enough + void* sidBuf = new char[bufLen]; + int sidLen = 0; + + void* pToken = PsReferencePrimaryToken(PsGetCurrentProcess()); + if (!pToken) ... error ... + + NTSTATUS ntstatus = ObOpenObjectByPointer(pToken, 0, 0, TOKEN_QUERY, +0, KernelMode, &handle); + if (!NT_SUCCESS(ntstatus)) ... error ... + + TOKEN_USER* user = static_cast(sidBuf); + ULONG tokenInfoLen; + ntstatus = ZwQueryInformationToken(handle, TokenUser, user, bufLen, +&tokenInfoLen); + if (!NT_SUCCESS(ntstatus)) ... error ... + + assert(tokenInfoLen <= bufLen); // else we would have got an error, +right? + assert(user->User.Sid == user+1); // SID is in buffer just past +TOKEN_USER structure + + sidLen = tokenInfoLen - sizeof (TOKEN_USER); + memmove(sidBuf, user->User.Sid, sidLen); // shuffle down the buffer + +Naturally, this returns the id of the thread that's running it. +If you execute this in DriverEntry, you're running in some +thread in the system process, which is not related to +the thread which executed the Win32 StartService call. diff --git a/doc/notes b/doc/notes new file mode 100644 index 0000000..eaa392e --- /dev/null +++ b/doc/notes @@ -0,0 +1,570 @@ +*** This file contains messages I've culled off the net as well +as previous discussions all of which have useful info on fixes +that need to be added to ReactOS. messages are between five +dashes on a line by themselves. If you implement the fix +reffered to in a message, feel free to delete it from the file. +Rex *** +----- +Subject: [ros-kernel] Inside the Boot Process +Date: Mon, 22 Mar 1999 22:05:47 +0100 +From: Emanuele Aliberti + +For those working on the boot loader: in WinNt Magazine november 1998 +issue (http://www.winntmag.com/) there is a detailed description, by +Mark Russinovich, of the rôle the MBR, NTLDR, boot.ini, ntdetect.com... +play in the boot process ("Inside the Boot Process, Part 1"). +----- +Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because +it needs to synchronize with KeInsertDpcQueue. Also the idle thread +should run at DISPATCH_LEVEL and regularly drain the dpc queue, that +way if an irq happens and the dpc can't be executed immediately it +will be executed as soon as the processor is idle rather than +waiting for the next timer tick +----- +About the console driver, I think it might be quite useful to have a simple +way for apps to print to the screen for debugging. But when the kernel is more +stable, console handling should be moved to user level because console printing +needs to know about windows and so on which can only be done at user level. +----- +Subject: Re: IMSAMP-how to avoid rebooting? +Date: 9 Nov 1998 00:40:32 -0000 +From: Charles Bryant +Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode +References: 1, 2 , 3 , 4 + +In article , David C. wrote: +>The reason it won't unload when something is bound to it is the same +>reason you can't unload any other driver that has an open client. If +>you install any driver, and have a user program (or another driver) open +>a handle to it, and then give the "net stop" command to unload it, +>you'll find that the unload will be delayed until the user program +>closes its handle. + +When developing a driver I found this to be a considerable nuisance. +Frequently a bug would leave an IRP stuck in the driver and I +couldn't unload and reload a fixed version. While reading NTDDK.H I +found a suspicious constant and discovered that the Flags field in +the device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO) +has a bit called DO_UNLOAD_PENDING. By experiment I confirmed that +this bit is set when you do 'net stop', so a driver can check it +periodically (e.g. from a timer DPC every ten seconds) and cancel all +queued IRPs if it is found to be set. + +Since this is not documented anywhere that I can find, it might be +unwise to rely on it for production code, but it is very useful for +debugging. Maybe someone with internals knowledge can comment on the +reliability of it. +----- +Subject: Re: Kernel bugs +Date: Fri, 23 Oct 1998 12:08:36 -0700 +From: rex +To: Jason Filby +References: 1 + +Jason Filby wrote: + +> Hi, +> +> Ok -- here's most of what I get when I press a key: +> +> Page fault detected at address 1fd4 with eip c042f794 +> Recursive page fault detected +> Exception 14(2) +> CS:EIP 20:c042f794 +> +> Rex -- do you know of anyway to find out which function in what file +> is causing the exception? I know that for problems in the kernel, you +> just look in the ntoskrnl\kernel.sym file and find the EIP value which +> matches the one given in the exception debug text. But what about +> modules? How can we track exceptions that occur in functions in modules? +> + +I know this is a little belated, but I thought I'd take astab at answering +this anyway. add an option to the +makefile for the module to generate a listing file with +symbol information. Then, on a boot test, note the +address that the module is loaded at, and subtract +this from the EIP value. add any offset used in the +module link specification (I dont think there currently +is one), and look for the last symbol with a lower +address offset. + +Brian, I have an idea on how to make this exception +dump information a little more useful. We should +have the load information for the load modules +in memory somewhere. Perhaps the exception +dump could check offending addresses to see if +they lie in the kernel or in a module, and if they +lie in a module the proper offset could be subtracted +and this number could be displayed seperately. If +I get a chance today, I'll make this change and send +it to ya. + +Rex. +----- +Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O" +Date: Mon, 16 Nov 1998 11:24:57 -0800 +From: "-Paul" +Organization: Microsoft Corp. +Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode +References: 1 + +Radu, I post the following information occassionally for questions such as +yours. I hope it helps. + +-Paul + +Here is an explanation of buffers and DeviceIoControl. + +First, here are the parameters, + +BOOL DeviceIoControl( + HANDLE hDevice, // handle to device of interest + DWORD dwIoControlCode, // control code of operation to perform + LPVOID lpInBuffer, // pointer to buffer to supply input data + DWORD nInBufferSize, // size of input buffer + LPVOID lpOutBuffer, // pointer to buffer to receive output data + DWORD nOutBufferSize, // size of output buffer + LPDWORD lpBytesReturned, // pointer to variable to receive output byte +count + LPOVERLAPPED lpOverlapped // pointer to overlapped structure for +asynchronous operation + ); + +METHOD_BUFFERED + +user-mode perspective + +lpInBuffer - optional, contains data that is written to the driver +lpOutBuffer - optional, contains data that is read from the driver after +the call has completed + +lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer. +If a shared buffer, lpInBuffer is overwritten by lpOutBuffer. + + +I/O Manager perspective + +examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged +pool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer. +The size of this buffer is equal to the size of the larger of the two +bufferes. This buffer is accessible at any IRQL. + +copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength +copies nOutBufferSize to +irpSp->Parameters.DeviceIoControl.OutputBufferLength +copies contents of lpInBuffer to SystemBuffer allocated above +calls your driver + + + +Device Driver perspective + +you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data +from this buffer and you write output data to the same buffer, overwriting +the input data. + +Before calling IoCompleteRequest, you must +- set IoStatus.Status to an approriate NtStatus +- if IoStatus.Status == STATUS_SUCCESS + set IoStatus.Information to the + number of bytes you want copied + from the SystemBuffer back into + lpOutBuffer. + + +I/O Manager Completion Routine perspective + +looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the +number of bytes specified by IoStatus.Information from +Irp->AssociatedIrp.SystemBuffer into lpOutBuffer +completes the request + + + + + + +METHOD_IN_DIRECT + +user-mode perspective + +lpInBuffer - optional, contains data that is written to the driver. This +buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid +confusion, mentally rename this buffer to lpControlBuffer. This is +typically a small, optional buffer that might contain a control structure +with useful information for the device driver. This buffer is smal and is +double buffered. + +lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by +the driver. To avoid confusion, mentally rename this buffer to +lpDataTransferBuffer. This is physically the same buffer that the device +driver will read from. There is no double buffering. Technically, this +buffer is still optional, but since you are using this buffering method, +what would be the point??? + +I/O Manager perspective + +If lpInBuffer exists, allocates memory from non-paged pool and puts the +address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is +accessible at any IRQL. + +copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength +copies nOutBufferSize to +irpSp->Parameters.DeviceIoControl.OutputBufferLength +copies contents of lpInBuffer to SystemBuffer allocated above +So far this is completely identical to METHOD_BUFFERED. Most likely +lpInBuffer (mentally renamed to lpControlBuffer) is very small in size. + +For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is +allocated. lpOutBuffer is probed and locked into memory. Then, the user +buffer virtual addresses are checked to be sure they are readable in the +caller's access mode. + +The MDL is address is stored in Irp->MdlAddress. +Your driver is called. + + +Device Driver perspective + +The device driver can read the copy of lpOutBuffer via +Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to +this buffer is lost. The I/O Manager does not copy any data back to the +user-mode buffers as it did in the completion routine for METHOD_BUFFERED. +Art Baker's book is wrong in this respect (page 168, "data going from the +driver back to the caller is passed through an intermediate system-space +buffer" and page 177, "When the IOCTL IRP is completed, the contents of the +system buffer will be copied back into the callers original output buffer". + +The device driver accesses the Win32 buffer directly via Irp->MdlAddress. +The driver uses whatever Mdl API's to read the buffer. Usually, this +buffer is to be written to some mass storage media or some similar +operation. Since this is a large data transfer, assume a completion +routine is required. + +mark the Irp pending +queue it +return status pending + + + + +Device Driver Completion Routine perspective + +standard completion routine operations +set IoStatus.Status to an approriate NtStatus +IoStatus.Information is not needed +completete the request + + + + +I/O Manager Completion Routine perspective + +standard I/O Manager completion routine operations +unmap the pages +deallocate the Mdl +complete the request + + + + + +METHOD_OUT_DIRECT + +user-mode perspective + +lpInBuffer - optional, contains data that is written to the driver. This +buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid +confusion, mentally rename this buffer to lpControlBuffer. This is +typically a small, optional buffer that might contain a control structure +with useful information for the device driver. This buffer is smal and is +double buffered. + +lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written +by the driver and read by the wer-mode application when the request is +completed. To avoid confusion, mentally rename this buffer to +lpDataTransferBuffer. This is physically the same buffer that the device +driver will write to. There is no double buffering. Technically, this +buffer is still optional, but since you are using this buffering method, +what would be the point??? + +I/O Manager perspective + +If lpInBuffer exists, allocates memory from non-paged pool and puts the +address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is +accessible at any IRQL. + +copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength +copies nOutBufferSize to +irpSp->Parameters.DeviceIoControl.OutputBufferLength +copies contents of lpInBuffer to SystemBuffer allocated above +So far this is completely identical to METHOD_BUFFERED. Most likely +lpInBuffer (mentally renamed to lpControlBuffer) is very small in size. + +For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is +allocated. lpOutBuffer is probed and locked into memory. Then the user +buffer's addresses are checked to make sure the caller could write to them +in the caller's access mode. + +The MDL is address is stored in Irp->MdlAddress. +Your driver is called. + + +Device Driver perspective + +The device driver can read the copy of lpOutBuffer via +Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to +this buffer is lost. + +The device driver accesses the Win32 buffer directly via Irp->MdlAddress. +The driver uses whatever Mdl API's to write data to the buffer. Usually, +this buffer is to be read from some mass storage media or some similar +operation. Since this is a large data transfer, assume a completion +routine is required. + +mark the Irp pending +queue it +return status pending + + + + +Device Driver Completion Routine perspective + +standard completion routine operations +set IoStatus.Status to an approriate NtStatus +IoStatus.Information is not needed +completete the request + + + + +I/O Manager Completion Routine perspective + +standard I/O Manager completion routine operations +unmap the pages +deallocate the Mdl +complete the request + + + + +METHOD_NEITHER + +I/O Manager perspective + +Irp->UserBuffer = lpOutputBuffer; +IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer; + +No comments here. Don't use METHOD_DIRECT unless you know what you are +doing. Simple rule. + +If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the +fastest path through the I/O Manager that involves an Irp. + + + + +Final Comment + +Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two +major problems can occur. 1 - page fault at high IRQL, or 2 - you write +something to Irp->UserBuffer and the I/O Manager overwrites you in its +completion routine. File systems access Irp->UserBuffer, but FSD writers +know all of the above and know when it is safe to touch Irp->UserBuffer. + + + +Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>... +>Hello, +> +>I have a kernel-mode device driver that accepts a number of IoControl +>commands that use buffered data transfer (METHOD_BUFFERED). +> +>A user mode API provides a higher level access then the DeviceIoControl +>function. +> +>The function is implemented like that +> +>BOOL +Something( +> HANDLE hDevice , +> int param1, +> int param2, +> DWORD * pReturn, +> LPOVERLAPPED pOverlapped) +>{ +> // here a data buffer on the stack sent to asynchronous DeviceIoControl +>call +> int aDataIn[2]; +> aDataIn[0] = param1; +> aDataIn[1] = param2; +> +> return DeviceIoControl( +> hDevice, +> DO_SOMETHING_IO, +> aDataIn, +> sizeof(int)*2, +> pReturn, +> sizeof(DWORD), +> pOverlapped); +>} +> +>The aDataIn buffer will not exist after DeviceIoControl returns (and +>when the I/O operation terminates). I know that for buffered IO the +>input data buffer is copyed by de IOManager to a nonpaged-pool area +>before passing the request to driver dispatch routine (DeviceControl). +>At the point of calling the dispatch routine (DeviceControl) the driver +>runs in the context of the calling thread so DeviceIoControl hasn't +>returned yet (?? or so I think) so aDataI +n will still be valid at the +>time IOManager copyes it to its buffer. So, this apears to work ok (at +>least in my opinion). +> +>Does I/O Manager use the Input buffer from the call to the Win32 +>DeviceIoControl any where else after the first copy ? +> +>Is there any reason why this approach (passing a buffer on the stack to +>a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ? +> +>Allocating buffers from heap and deleting them on IO completion while +>managing asynchronous IO seems too much work ;-) . +> +>Thanks in advance for your opinions +>Radu W. +> +>-- +>Radu Woinaroski +>Scitec +>Sydney, Australia +>Radu.Woinaroski@scitec.com.au +----- +Subject: Re: PCI ISR problem +Date: Fri, 20 Nov 1998 18:04:48 GMT +From: jeh@cmkrnl.com (Jamie Hanrahan) +Organization: Kernel Mode Systems, San Diego, CA +Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode +References: 1 + +On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner + wrote: + +>I'm having problems with NT4 not hooking the interrupt line indicated by +>a PCI device. Here's what I'm doing: +> +>1) Enumerating the PCI buses on the system (using HalGetBusData) until +>I find my device. +>2) Once my device is found, I read the "Interrupt Line Register" in the +>device's PCI config space to determine what interrupt level to pass to +>HalGetInterruptVector. + +Whups! No. Call HalAssignSlotResources and look at the returned +CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for +your device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.) + + +See Knowledge Base article Q152044. + + --- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com) +Drivers, internals, networks, applications, and training for VMS and Windows NT +NT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/ + +Please post replies, followups, questions, etc., in news, not via e-mail. +----- +Subject: Re: IRP canceling +Date: Mon, 23 Nov 1998 09:05:47 -0500 +From: Walter Oney +Organization: Walter Oney Software +Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode +References: 1 + +Seol,Keun Seok wrote: +> But, if the IRP was the CurrentIrp of the Device Object, +> the Driver's Start I/O routine will try to process the IRP. +> In the DDK help, the Start I/O routine MUST check the current IRP's +> Cancel bit. +> If set, Start I/O routine must just return. +> +> But I think that the IRP already completed should not be accessed. + +You're absolutely right. I recommend the following code in a standard +StartIo routine to avoid the problem you point out: + +VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) + { + KIRQL oldirql; + IoAcquireCancelSpinLock(&oldirql); + if (Irp != DeviceObject->CurrentIrp || Irp->Cancel) + { + IoReleaseCancelSpinLock(oldirql); + return; + } + else + { + IoSetCancelRoutine(Irp, NULL); + IoReleaseCancelSpinLock(oldirql); + } + . . . + } + +This dovetails with a standard cancel routine: + +VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) + { + if (DeviceObject->CurrentIrp == Irp) + { + IoReleaseCancelSpinLock(Irp->CancelIrql); + IoStartNextPacket(DeviceObject, TRUE); + } + else + { + KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry); + IoReleaseCancelSpinLock(Irp->CancelIrql); + } + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + +You need to remember that the C language specification requires that +evaluation of boolean operators short circuit when the result is known. +So, if StartIo discovers that the Irp it got as an argument is not the +same as CurrentIrp, it will not attempt to evaulate Irp->Cancel. + +Now, as to why this works: StartIo gets called either by IoStartPacket +or IoStartNextPacket. Each of them will grab the cancel spin lock and +set CurrentIrp, then release the spin lock and call StartIo. If someone +should sneak in on another CPU and cancel this very same IRP, your +cancel routine will immediately release the spin lock and call +IoStartNextPacket. One of two things will then happen. IoStartNextPacket +may succeed in getting the cancel spin lock, whereupon it will nullify +the CurrentIrp pointer. If another IRP is on the queue, it will remove +it from the queue, set CurrentIrp to point to this *new* IRP, release +the spin lock, and call StartIo. [You now have two instances of StartIo +running on two different CPUs for two different IRPs, but it's not a +problem because they won't be able to interfere with each other.] +Meanwhile, your original instance of StartIo gets the cancel spin lock +and sees that CurrentIrp is not equal to the IRP pointer it got as an +argument, so it gives up. + +The second way this could play out is that StartIo gets the cancel lock +before IoStartNextPacket does. In this case, CurrentIrp is still +pointing to the IRP that's in the process of being cancelled and that +StartIo got as an argument. But this IRP hasn't been completed yet (the +CPU that's running your cancel routine is spinning inside +IoStartNextPacket and therefore hasn't gotten to calling +IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp +to make your pointer invalid. + +People may tell you that you should be using your own queues for IRPs so +you can avoid bottlenecking the system on the global cancel spin lock. +That's true enough, but doing it correctly with Plug and Play and Power +management things in the way is gigantically complicated. There's a +sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage +your own queue if you don't worry about PNP and POWER. I hear tell of an +upcoming MSJ article by a Microsoft developer that may solve the +complete problem. +----- +The END. diff --git a/doc/roadmap b/doc/roadmap new file mode 100644 index 0000000..a52e9b8 --- /dev/null +++ b/doc/roadmap @@ -0,0 +1,26 @@ + + ReactOS RoadMap +================= + +This file should give developers and users some hints about where +the project development is heading to. This list is intended to be +a base for discussions and can be changed to reflect the results of +these discussions. Every developer is encouraged to add his/her own +ideas to this list. + + +Version 0.0.19: + - FreeLoader can boot ReactOS from hard-disk + - Registry support for FreeLoader + - ATAPI storage driver stack + +Version 0.0.20: + - CDROM class driver + - CDFS file system driver (iso9660,...) + +Version 0.0.21: + - ReactOS can boot from CDROM + + +List includes personal 'to-do' topics by: + Eric Kohl diff --git a/doc/todo b/doc/todo new file mode 100644 index 0000000..7678acb --- /dev/null +++ b/doc/todo @@ -0,0 +1,37 @@ + +* Critical path tasks + Test and debug Registry routines + Implement file cache + Implement paging + +* These tasks would be nice + Separate HAL into KM DLL + +* Function groups totally or partially unimplemented + + Dma functions (see hal/x86/dma.c) + Shutdown support (see ex/power.c) + Zw(Set/Get)SystemInformation (see ex/sysinfo.c) + Io cancelation support (see io/cancel, et al) + Directory change notification (see io/dir.c) + Error logging (see io/errlog.c) + Io completion ports (see io/iocomp.c) + File locking (see io/lock.c) + Hardware resource management (see io/resource.c) + Exception support (see ke/catch.c) + Mutex support (see nt/mutex.c) + +* Verify implementation + + +* Major areas + + Security support (see se/*.c) + SCSI miniport driver + +* Drivers + NTFS, EXT2 filesystems + Many others (use oem's where possible) + +* For the future + DOS, Win16, POSIX subsystems diff --git a/drivers/bus/acpi/.cvsignore b/drivers/bus/acpi/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/acpi.rc b/drivers/bus/acpi/acpi.rc new file mode 100644 index 0000000..f267c92 --- /dev/null +++ b/drivers/bus/acpi/acpi.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS ACPI Driver\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "acpi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "acpi.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/drivers/bus/acpi/changed.txt b/drivers/bus/acpi/changed.txt new file mode 100644 index 0000000..5717751 --- /dev/null +++ b/drivers/bus/acpi/changed.txt @@ -0,0 +1,21 @@ +Changes to ACPI CA +------------------ + ++ = Added +- = Removed +* = Altered + ++ include/platform/acwin.h ++ include/platform/types.h +- ospm/ac_adapter/* +- ospm/battery/* +- ospm/button/* +- ospm/ec/* +- ospm/include/* (except bm.h) +- ospm/processor/* +- ospm/system/* +- ospm/thermal/* +- ospm/busmgr/bm_module.c +- ospm/busmgr/bm_proc.c +- ospm/busmgr/bm_symbols.c +- ospm/busmgr/Makefile diff --git a/drivers/bus/acpi/dispatcher/.cvsignore b/drivers/bus/acpi/dispatcher/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/dispatcher/dsfield.c b/drivers/bus/acpi/dispatcher/dsfield.c new file mode 100644 index 0000000..ed5e36e --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dsfield.c @@ -0,0 +1,423 @@ +/****************************************************************************** + * + * Module Name: dsfield - Dispatcher field routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dsfield") + + +/* + * Field flags: Bits 00 - 03 : Access_type (Any_acc, Byte_acc, etc.) + * 04 : Lock_rule (1 == Lock) + * 05 - 06 : Update_rule + */ + +#define FIELD_ACCESS_TYPE_MASK 0x0F +#define FIELD_LOCK_RULE_MASK 0x10 +#define FIELD_UPDATE_RULE_MASK 0x60 + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region_node - Object for the containing Operation Region + * + * RETURN: Status + * + * DESCRIPTION: Create a new field in the specified operation region + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_create_field ( + ACPI_PARSE_OBJECT *op, + ACPI_NAMESPACE_NODE *region_node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_AML_ERROR; + ACPI_PARSE_OBJECT *arg; + ACPI_NAMESPACE_NODE *node; + u8 field_flags; + u8 access_attribute = 0; + u32 field_bit_position = 0; + + + /* First arg is the name of the parent Op_region */ + + arg = op->value.arg; + if (!region_node) { + status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, + ACPI_TYPE_REGION, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, + ®ion_node); + + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* Second arg is the field flags */ + + arg = arg->next; + field_flags = (u8) arg->value.integer; + + /* Each remaining arg is a Named Field */ + + arg = arg->next; + while (arg) { + switch (arg->opcode) { + case AML_RESERVEDFIELD_OP: + + field_bit_position += arg->value.size; + break; + + + case AML_ACCESSFIELD_OP: + + /* + * Get a new Access_type and Access_attribute for all + * entries (until end or another Access_as keyword) + */ + + access_attribute = (u8) arg->value.integer; + field_flags = (u8) + ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); + break; + + + case AML_NAMEDFIELD_OP: + + status = acpi_ns_lookup (walk_state->scope_info, + (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, + INTERNAL_TYPE_DEF_FIELD, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &node); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Initialize an object for the new Node that is on + * the object stack + */ + + status = acpi_aml_prep_def_field_value (node, region_node, field_flags, + access_attribute, field_bit_position, arg->value.size); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Keep track of bit position for *next* field */ + + field_bit_position += arg->value.size; + break; + } + + arg = arg->next; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_bank_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region_node - Object for the containing Operation Region + * + * RETURN: Status + * + * DESCRIPTION: Create a new bank field in the specified operation region + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_create_bank_field ( + ACPI_PARSE_OBJECT *op, + ACPI_NAMESPACE_NODE *region_node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_AML_ERROR; + ACPI_PARSE_OBJECT *arg; + ACPI_NAMESPACE_NODE *register_node; + ACPI_NAMESPACE_NODE *node; + u32 bank_value; + u8 field_flags; + u8 access_attribute = 0; + u32 field_bit_position = 0; + + + /* First arg is the name of the parent Op_region */ + + arg = op->value.arg; + if (!region_node) { + status = acpi_ns_lookup (walk_state->scope_info, arg->value.name, + ACPI_TYPE_REGION, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, + ®ion_node); + + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* Second arg is the Bank Register */ + + arg = arg->next; + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_BANK_FIELD_DEFN, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, ®ister_node); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Third arg is the Bank_value */ + + arg = arg->next; + bank_value = arg->value.integer; + + + /* Next arg is the field flags */ + + arg = arg->next; + field_flags = (u8) arg->value.integer; + + /* Each remaining arg is a Named Field */ + + arg = arg->next; + while (arg) { + switch (arg->opcode) { + case AML_RESERVEDFIELD_OP: + + field_bit_position += arg->value.size; + break; + + + case AML_ACCESSFIELD_OP: + + /* + * Get a new Access_type and Access_attribute for + * all entries (until end or another Access_as keyword) + */ + + access_attribute = (u8) arg->value.integer; + field_flags = (u8) + ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); + break; + + + case AML_NAMEDFIELD_OP: + + status = acpi_ns_lookup (walk_state->scope_info, + (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, + INTERNAL_TYPE_DEF_FIELD, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &node); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Initialize an object for the new Node that is on + * the object stack + */ + + status = acpi_aml_prep_bank_field_value (node, region_node, register_node, + bank_value, field_flags, access_attribute, + field_bit_position, arg->value.size); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Keep track of bit position for the *next* field */ + + field_bit_position += arg->value.size; + break; + + } + + arg = arg->next; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_index_field + * + * PARAMETERS: Op - Op containing the Field definition and args + * Region_node - Object for the containing Operation Region + * + * RETURN: Status + * + * DESCRIPTION: Create a new index field in the specified operation region + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_create_index_field ( + ACPI_PARSE_OBJECT *op, + ACPI_HANDLE region_node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_PARSE_OBJECT *arg; + ACPI_NAMESPACE_NODE *node; + ACPI_NAMESPACE_NODE *index_register_node; + ACPI_NAMESPACE_NODE *data_register_node; + u8 field_flags; + u8 access_attribute = 0; + u32 field_bit_position = 0; + + + arg = op->value.arg; + + /* First arg is the name of the Index register */ + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + ACPI_TYPE_ANY, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &index_register_node); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Second arg is the data register */ + + arg = arg->next; + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + INTERNAL_TYPE_INDEX_FIELD_DEFN, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &data_register_node); + + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Next arg is the field flags */ + + arg = arg->next; + field_flags = (u8) arg->value.integer; + + + /* Each remaining arg is a Named Field */ + + arg = arg->next; + while (arg) { + switch (arg->opcode) { + case AML_RESERVEDFIELD_OP: + + field_bit_position += arg->value.size; + break; + + + case AML_ACCESSFIELD_OP: + + /* + * Get a new Access_type and Access_attribute for all + * entries (until end or another Access_as keyword) + */ + + access_attribute = (u8) arg->value.integer; + field_flags = (u8) + ((field_flags & FIELD_ACCESS_TYPE_MASK) || + ((u8) (arg->value.integer >> 8))); + break; + + + case AML_NAMEDFIELD_OP: + + status = acpi_ns_lookup (walk_state->scope_info, + (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)arg)->name, + INTERNAL_TYPE_INDEX_FIELD, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, &node); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Initialize an object for the new Node that is on + * the object stack + */ + + status = acpi_aml_prep_index_field_value (node, index_register_node, data_register_node, + field_flags, access_attribute, + field_bit_position, arg->value.size); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Keep track of bit position for the *next* field */ + + field_bit_position += arg->value.size; + break; + + + default: + + status = AE_AML_ERROR; + break; + } + + arg = arg->next; + } + + return (status); +} + + diff --git a/drivers/bus/acpi/dispatcher/dsmethod.c b/drivers/bus/acpi/dispatcher/dsmethod.c new file mode 100644 index 0000000..2a03ed5 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dsmethod.c @@ -0,0 +1,497 @@ +/****************************************************************************** + * + * Module Name: dsmethod - Parser/Interpreter interface - control method parsing + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dsmethod") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_parse_method + * + * PARAMETERS: Obj_handle - Node of the method + * Level - Current nesting level + * Context - Points to a method counter + * Return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Call the parser and parse the AML that is + * associated with the method. + * + * MUTEX: Assumes parser is locked + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_parse_method ( + ACPI_HANDLE obj_handle) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_PARSE_OBJECT *op; + ACPI_NAMESPACE_NODE *node; + ACPI_OWNER_ID owner_id; + + + /* Parameter Validation */ + + if (!obj_handle) { + return (AE_NULL_ENTRY); + } + + + /* Extract the method object from the method Node */ + + node = (ACPI_NAMESPACE_NODE *) obj_handle; + obj_desc = node->object; + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + /* Create a mutex for the method if there is a concurrency limit */ + + if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && + (!obj_desc->method.semaphore)) { + status = acpi_os_create_semaphore (obj_desc->method.concurrency, + obj_desc->method.concurrency, + &obj_desc->method.semaphore); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Allocate a new parser op to be the root of the parsed + * method tree + */ + op = acpi_ps_alloc_op (AML_METHOD_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Init new op with the method name and pointer back to the Node */ + + acpi_ps_set_name (op, node->name); + op->node = node; + + + /* + * Parse the method, first pass + * + * The first pass load is + * where newly declared named objects are + * added into the namespace. Actual evaluation of + * the named objects (what would be called a "second + * pass") happens during the actual execution of the + * method so that operands to the named objects can + * take on dynamic run-time values. + */ + status = acpi_ps_parse_aml (op, obj_desc->method.pcode, + obj_desc->method.pcode_length, + ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, + node, NULL, NULL, + acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get a new Owner_id for objects created by this method */ + + owner_id = acpi_cm_allocate_owner_id (OWNER_TYPE_METHOD); + obj_desc->method.owning_id = owner_id; + + /* Install the parsed tree in the method object */ + /* TBD: [Restructure] Obsolete field? */ + + acpi_ps_delete_parse_tree (op); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_begin_method_execution + * + * PARAMETERS: Method_node - Node of the method + * Obj_desc - The method object + * Calling_method_node - Caller of this method (if non-null) + * + * RETURN: Status + * + * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, + * increments the thread count, and waits at the method semaphore + * for clearance to execute. + * + * MUTEX: Locks/unlocks parser. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_begin_method_execution ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_NAMESPACE_NODE *calling_method_node) +{ + ACPI_STATUS status = AE_OK; + + + if (!method_node) { + return (AE_NULL_ENTRY); + } + + + /* + * If there is a concurrency limit on this method, we need to + * obtain a unit from the method semaphore. + */ + if (obj_desc->method.semaphore) { + /* + * Allow recursive method calls, up to the reentrancy/concurrency + * limit imposed by the SERIALIZED rule and the Sync_level method + * parameter. + * + * The point of this code is to avoid permanently blocking a + * thread that is making recursive method calls. + */ + if (method_node == calling_method_node) { + if (obj_desc->method.thread_count >= obj_desc->method.concurrency) { + return (AE_AML_METHOD_LIMIT); + } + } + + /* + * Get a unit from the method semaphore. This releases the + * interpreter if we block + */ + status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore, + WAIT_FOREVER); + } + + + /* + * Increment the method parse tree thread count since it has been + * reentered one more time (even if it is the same thread) + */ + obj_desc->method.thread_count++; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_call_control_method + * + * PARAMETERS: Walk_state - Current state of the walk + * Op - Current Op to be walked + * + * RETURN: Status + * + * DESCRIPTION: Transfer execution to a called control method + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_call_control_method ( + ACPI_WALK_LIST *walk_list, + ACPI_WALK_STATE *this_walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *method_node; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_WALK_STATE *next_walk_state; + ACPI_PARSE_STATE *parser_state; + u32 i; + + + /* + * Get the namespace entry for the control method we are about to call + */ + method_node = this_walk_state->method_call_node; + if (!method_node) { + return (AE_NULL_ENTRY); + } + + obj_desc = acpi_ns_get_attached_object (method_node); + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + + /* Init for new method, wait on concurrency semaphore */ + + status = acpi_ds_begin_method_execution (method_node, obj_desc, + this_walk_state->method_node); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Create and initialize a new parser state */ + + parser_state = acpi_ps_create_state (obj_desc->method.pcode, + obj_desc->method.pcode_length); + if (!parser_state) { + return (AE_NO_MEMORY); + } + + acpi_ps_init_scope (parser_state, NULL); + parser_state->start_node = method_node; + + + /* Create a new state for the preempting walk */ + + next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, + NULL, obj_desc, walk_list); + if (!next_walk_state) { + /* TBD: delete parser state */ + + return (AE_NO_MEMORY); + } + + next_walk_state->walk_type = WALK_METHOD; + next_walk_state->method_node = method_node; + next_walk_state->parser_state = parser_state; + next_walk_state->parse_flags = this_walk_state->parse_flags; + next_walk_state->descending_callback = this_walk_state->descending_callback; + next_walk_state->ascending_callback = this_walk_state->ascending_callback; + + /* The Next_op of the Next_walk will be the beginning of the method */ + /* TBD: [Restructure] -- obsolete? */ + + next_walk_state->next_op = NULL; + + /* Open a new scope */ + + status = acpi_ds_scope_stack_push (method_node, + ACPI_TYPE_METHOD, next_walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* + * Initialize the arguments for the method. The resolved + * arguments were put on the previous walk state's operand + * stack. Operands on the previous walk state stack always + * start at index 0. + */ + status = acpi_ds_method_data_init_args (&this_walk_state->operands[0], + this_walk_state->num_operands, + next_walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Create and init a Root Node */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + status = acpi_ps_parse_aml (op, obj_desc->method.pcode, + obj_desc->method.pcode_length, + ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, + method_node, NULL, NULL, + acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + acpi_ps_delete_parse_tree (op); + + + /* + * Delete the operands on the previous walkstate operand stack + * (they were copied to new objects) + */ + for (i = 0; i < obj_desc->method.param_count; i++) { + acpi_cm_remove_reference (this_walk_state->operands [i]); + this_walk_state->operands [i] = NULL; + } + + /* Clear the operand stack */ + + this_walk_state->num_operands = 0; + + + return (AE_OK); + + + /* On error, we must delete the new walk state */ + +cleanup: + acpi_ds_terminate_control_method (next_walk_state); + acpi_ds_delete_walk_state (next_walk_state); + return (status); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_restart_control_method + * + * PARAMETERS: Walk_state - State of the method when it was preempted + * Op - Pointer to new current op + * + * RETURN: Status + * + * DESCRIPTION: Restart a method that was preempted + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_restart_control_method ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT *return_desc) +{ + ACPI_STATUS status; + + + if (return_desc) { + if (walk_state->return_used) { + /* + * Get the return value (if any) from the previous method. + * NULL if no return value + */ + status = acpi_ds_result_push (return_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (return_desc); + return (status); + } + } + + else { + /* + * Delete the return value if it will not be used by the + * calling method + */ + acpi_cm_remove_reference (return_desc); + } + + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_terminate_control_method + * + * PARAMETERS: Walk_state - State of the method + * + * RETURN: Status + * + * DESCRIPTION: Terminate a control method. Delete everything that the method + * created, delete all locals and arguments, and delete the parse + * tree if requested. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_terminate_control_method ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *method_node; + + + /* The method object should be stored in the walk state */ + + obj_desc = walk_state->method_desc; + if (!obj_desc) { + return (AE_OK); + } + + /* Delete all arguments and locals */ + + acpi_ds_method_data_delete_all (walk_state); + + /* + * Lock the parser while we terminate this method. + * If this is the last thread executing the method, + * we have additional cleanup to perform + */ + acpi_cm_acquire_mutex (ACPI_MTX_PARSER); + + + /* Signal completion of the execution of this method if necessary */ + + if (walk_state->method_desc->method.semaphore) { + status = acpi_os_signal_semaphore ( + walk_state->method_desc->method.semaphore, 1); + } + + /* Decrement the thread count on the method parse tree */ + + walk_state->method_desc->method.thread_count--; + if (!walk_state->method_desc->method.thread_count) { + /* + * There are no more threads executing this method. Perform + * additional cleanup. + * + * The method Node is stored in the walk state + */ + method_node = walk_state->method_node; + + /* + * Delete any namespace entries created immediately underneath + * the method + */ + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + if (method_node->child) { + acpi_ns_delete_namespace_subtree (method_node); + } + + /* + * Delete any namespace entries created anywhere else within + * the namespace + */ + acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id); + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + acpi_cm_release_mutex (ACPI_MTX_PARSER); + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/dispatcher/dsmthdat.c b/drivers/bus/acpi/dispatcher/dsmthdat.c new file mode 100644 index 0000000..11de89e --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dsmthdat.c @@ -0,0 +1,693 @@ +/******************************************************************************* + * + * Module Name: dsmthdat - control method arguments and local variables + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dsmthdat") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_init + * + * PARAMETERS: Walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Initialize the data structures that hold the method's arguments + * and locals. The data struct is an array of NTEs for each. + * This allows Ref_of and De_ref_of to work properly for these + * special data types. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_init ( + ACPI_WALK_STATE *walk_state) +{ + u32 i; + + + /* + * Walk_state fields are initialized to zero by the + * Acpi_cm_callocate(). + * + * An Node is assigned to each argument and local so + * that Ref_of() can return a pointer to the Node. + */ + + /* Init the method arguments */ + + for (i = 0; i < MTH_NUM_ARGS; i++) { + MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name, + NAMEOF_ARG_NTE); + walk_state->arguments[i].name |= (i << 24); + walk_state->arguments[i].data_type = ACPI_DESC_TYPE_NAMED; + walk_state->arguments[i].type = ACPI_TYPE_ANY; + walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; + } + + /* Init the method locals */ + + for (i = 0; i < MTH_NUM_LOCALS; i++) { + MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name, + NAMEOF_LOCAL_NTE); + + walk_state->local_variables[i].name |= (i << 24); + walk_state->local_variables[i].data_type = ACPI_DESC_TYPE_NAMED; + walk_state->local_variables[i].type = ACPI_TYPE_ANY; + walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_delete_all + * + * PARAMETERS: Walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Delete method locals and arguments. Arguments are only + * deleted if this method was called from another method. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_delete_all ( + ACPI_WALK_STATE *walk_state) +{ + u32 index; + ACPI_OPERAND_OBJECT *object; + + + /* Delete the locals */ + + for (index = 0; index < MTH_NUM_LOCALS; index++) { + object = walk_state->local_variables[index].object; + if (object) { + /* Remove first */ + + walk_state->local_variables[index].object = NULL; + + /* Was given a ref when stored */ + + acpi_cm_remove_reference (object); + } + } + + + /* Delete the arguments */ + + for (index = 0; index < MTH_NUM_ARGS; index++) { + object = walk_state->arguments[index].object; + if (object) { + /* Remove first */ + + walk_state->arguments[index].object = NULL; + + /* Was given a ref when stored */ + + acpi_cm_remove_reference (object); + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_init_args + * + * PARAMETERS: *Params - Pointer to a parameter list for the method + * Max_param_count - The arg count for this method + * Walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Initialize arguments for a method + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_init_args ( + ACPI_OPERAND_OBJECT **params, + u32 max_param_count, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + u32 mindex; + u32 pindex; + + + if (!params) { + return (AE_OK); + } + + /* Copy passed parameters into the new method stack frame */ + + for (pindex = mindex = 0; + (mindex < MTH_NUM_ARGS) && (pindex < max_param_count); + mindex++) { + if (params[pindex]) { + /* + * A valid parameter. + * Set the current method argument to the + * Params[Pindex++] argument object descriptor + */ + status = acpi_ds_store_object_to_local (AML_ARG_OP, mindex, + params[pindex], walk_state); + if (ACPI_FAILURE (status)) { + break; + } + + pindex++; + } + + else { + break; + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_get_entry + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument to get + * Entry - Pointer to where a pointer to the stack + * entry is returned. + * Walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Get the address of the object entry given by Opcode:Index + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_get_entry ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT ***entry) +{ + + + /* + * Get the requested object. + * The stack "Opcode" is either a Local_variable or an Argument + */ + + switch (opcode) { + + case AML_LOCAL_OP: + + if (index > MTH_MAX_LOCAL) { + return (AE_BAD_PARAMETER); + } + + *entry = (ACPI_OPERAND_OBJECT **) + &walk_state->local_variables[index].object; + break; + + + case AML_ARG_OP: + + if (index > MTH_MAX_ARG) { + return (AE_BAD_PARAMETER); + } + + *entry = (ACPI_OPERAND_OBJECT **) + &walk_state->arguments[index].object; + break; + + + default: + return (AE_BAD_PARAMETER); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_set_entry + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument to get + * Object - Object to be inserted into the stack entry + * Walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_set_entry ( + u16 opcode, + u32 index, + ACPI_OPERAND_OBJECT *object, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT **entry; + + + /* Get a pointer to the stack entry to set */ + + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Increment ref count so object can't be deleted while installed */ + + acpi_cm_add_reference (object); + + /* Install the object into the stack entry */ + + *entry = object; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_get_type + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument whose type + * to get + * Walk_state - Current walk state object + * + * RETURN: Data type of selected Arg or Local + * Used only in Exec_monadic2()/Type_op. + * + ******************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ds_method_data_get_type ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT **entry; + ACPI_OPERAND_OBJECT *object; + + + /* Get a pointer to the requested stack entry */ + + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + if (ACPI_FAILURE (status)) { + return ((ACPI_TYPE_NOT_FOUND)); + } + + /* Get the object from the method stack */ + + object = *entry; + + /* Get the object type */ + + if (!object) { + /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */ + return (ACPI_TYPE_ANY); + } + + return (object->common.type); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_get_node + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument whose type + * to get + * Walk_state - Current walk state object + * + * RETURN: Get the Node associated with a local or arg. + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +acpi_ds_method_data_get_node ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state) +{ + ACPI_NAMESPACE_NODE *node = NULL; + + + switch (opcode) { + + case AML_LOCAL_OP: + + if (index > MTH_MAX_LOCAL) { + return (node); + } + + node = &walk_state->local_variables[index]; + break; + + + case AML_ARG_OP: + + if (index > MTH_MAX_ARG) { + return (node); + } + + node = &walk_state->arguments[index]; + break; + + + default: + break; + } + + + return (node); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_get_value + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument to get + * Walk_state - Current walk state object + * *Dest_desc - Ptr to Descriptor into which selected Arg + * or Local value should be copied + * + * RETURN: Status + * + * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame + * at the current top of the method stack. + * Used only in Acpi_aml_resolve_to_value(). + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_get_value ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **dest_desc) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT **entry; + ACPI_OPERAND_OBJECT *object; + + + /* Validate the object descriptor */ + + if (!dest_desc) { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the requested method stack entry */ + + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get the object from the method stack */ + + object = *entry; + + + /* Examine the returned object, it must be valid. */ + + if (!object) { + /* + * Index points to uninitialized object stack value. + * This means that either 1) The expected argument was + * not passed to the method, or 2) A local variable + * was referenced by the method (via the ASL) + * before it was initialized. Either case is an error. + */ + + switch (opcode) { + case AML_ARG_OP: + + return (AE_AML_UNINITIALIZED_ARG); + break; + + case AML_LOCAL_OP: + + return (AE_AML_UNINITIALIZED_LOCAL); + break; + } + } + + + /* + * Index points to initialized and valid object stack value. + * Return an additional reference to the object + */ + + *dest_desc = object; + acpi_cm_add_reference (object); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_method_data_delete_value + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument to delete + * Walk_state - Current walk state object + * + * RETURN: Status + * + * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts + * a null into the stack slot after the object is deleted. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_method_data_delete_value ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT **entry; + ACPI_OPERAND_OBJECT *object; + + + /* Get a pointer to the requested entry */ + + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get the current entry in this slot k */ + + object = *entry; + + /* + * Undefine the Arg or Local by setting its descriptor + * pointer to NULL. Locals/Args can contain both + * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs + */ + *entry = NULL; + + + if ((object) && + (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) { + /* + * There is a valid object in this slot + * Decrement the reference count by one to balance the + * increment when the object was stored in the slot. + */ + acpi_cm_remove_reference (object); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_store_object_to_local + * + * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP + * Index - Which local_var or argument to set + * Src_desc - Value to be stored + * Walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed + * as the new value for the Arg or Local and the reference count + * for Src_desc is incremented. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_store_object_to_local ( + u16 opcode, + u32 index, + ACPI_OPERAND_OBJECT *src_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT **entry; + + + /* Parameter validation */ + + if (!src_desc) { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the requested method stack entry */ + + status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (*entry == src_desc) { + goto cleanup; + } + + + /* + * If there is an object already in this slot, we either + * have to delete it, or if this is an argument and there + * is an object reference stored there, we have to do + * an indirect store! + */ + + if (*entry) { + /* + * Check for an indirect store if an argument + * contains an object reference (stored as an Node). + * We don't allow this automatic dereferencing for + * locals, since a store to a local should overwrite + * anything there, including an object reference. + * + * If both Arg0 and Local0 contain Ref_of (Local4): + * + * Store (1, Arg0) - Causes indirect store to local4 + * Store (1, Local0) - Stores 1 in local0, overwriting + * the reference to local4 + * Store (1, De_refof (Local0)) - Causes indirect store to local4 + * + * Weird, but true. + */ + + if ((opcode == AML_ARG_OP) && + (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) { + /* Detach an existing object from the Node */ + + acpi_ns_detach_object ((ACPI_NAMESPACE_NODE *) *entry); + + /* + * Store this object into the Node + * (do the indirect store) + */ + status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc, + src_desc->common.type); + return (status); + } + + +#ifdef ACPI_ENABLE_IMPLICIT_CONVERSION + /* + * Perform "Implicit conversion" of the new object to the type of the + * existing object + */ + status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } +#endif + + /* + * Delete the existing object + * before storing the new one + */ + acpi_ds_method_data_delete_value (opcode, index, walk_state); + } + + + /* + * Install the Obj_stack descriptor (*Src_desc) into + * the descriptor for the Arg or Local. + * Install the new object in the stack entry + * (increments the object reference count by one) + */ + status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Normal exit */ + + return (AE_OK); + + + /* Error exit */ + +cleanup: + + return (status); +} + diff --git a/drivers/bus/acpi/dispatcher/dsobject.c b/drivers/bus/acpi/dispatcher/dsobject.c new file mode 100644 index 0000000..e380696 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dsobject.c @@ -0,0 +1,641 @@ +/****************************************************************************** + * + * Module Name: dsobject - Dispatcher object management routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dsobject") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_init_one_object + * + * PARAMETERS: Obj_handle - Node + * Level - Current nesting level + * Context - Points to a init info struct + * Return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Op Regions + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + OBJECT_TYPE_INTERNAL type; + ACPI_STATUS status; + ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; + u8 table_revision; + + + info->object_count++; + table_revision = info->table_desc->pointer->revision; + + /* + * We are only interested in objects owned by the table that + * was just loaded + */ + + if (((ACPI_NAMESPACE_NODE *) obj_handle)->owner_id != + info->table_desc->table_id) { + return (AE_OK); + } + + + /* And even then, we are only interested in a few object types */ + + type = acpi_ns_get_type (obj_handle); + + switch (type) { + + case ACPI_TYPE_REGION: + + acpi_ds_initialize_region (obj_handle); + + info->op_region_count++; + break; + + + case ACPI_TYPE_METHOD: + + info->method_count++; + + + /* + * Set the execution data width (32 or 64) based upon the + * revision number of the parent ACPI table. + */ + + if (table_revision == 1) { + ((ACPI_NAMESPACE_NODE *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32; + } + + /* + * Always parse methods to detect errors, we may delete + * the parse tree below + */ + + status = acpi_ds_parse_method (obj_handle); + + /* TBD: [Errors] what do we do with an error? */ + + if (ACPI_FAILURE (status)) { + break; + } + + /* + * Delete the parse tree. We simple re-parse the method + * for every execution since there isn't much overhead + */ + acpi_ns_delete_namespace_subtree (obj_handle); + break; + + default: + break; + } + + /* + * We ignore errors from above, and always return OK, since + * we don't want to abort the walk on a single error. + */ + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_initialize_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the entire namespace and perform any necessary + * initialization on the objects found therein + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_initialize_objects ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMESPACE_NODE *start_node) +{ + ACPI_STATUS status; + ACPI_INIT_WALK_INFO info; + + + info.method_count = 0; + info.op_region_count = 0; + info.object_count = 0; + info.table_desc = table_desc; + + + /* Walk entire namespace from the supplied root */ + + status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, + ACPI_UINT32_MAX, acpi_ds_init_one_object, + &info, NULL); + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_init_object_from_op + * + * PARAMETERS: Op - Parser op used to init the internal object + * Opcode - AML opcode associated with the object + * Obj_desc - Namespace object to be initialized + * + * RETURN: Status + * + * DESCRIPTION: Initialize a namespace object from a parser Op and its + * associated arguments. The namespace object is a more compact + * representation of the Op and its arguments. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_init_object_from_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + u16 opcode, + ACPI_OPERAND_OBJECT **obj_desc) +{ + ACPI_STATUS status; + ACPI_PARSE_OBJECT *arg; + ACPI_PARSE2_OBJECT *byte_list; + ACPI_OPERAND_OBJECT *arg_desc; + ACPI_OPCODE_INFO *op_info; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + /* Unknown opcode */ + + return (AE_TYPE); + } + + + /* Get and prepare the first argument */ + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_BUFFER: + + /* First arg is a number */ + + acpi_ds_create_operand (walk_state, op->value.arg, 0); + arg_desc = walk_state->operands [walk_state->num_operands - 1]; + acpi_ds_obj_stack_pop (1, walk_state); + + /* Resolve the object (could be an arg or local) */ + + status = acpi_aml_resolve_to_value (&arg_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (arg_desc); + return (status); + } + + /* We are expecting a number */ + + if (arg_desc->common.type != ACPI_TYPE_INTEGER) { + acpi_cm_remove_reference (arg_desc); + return (AE_TYPE); + } + + /* Get the value, delete the internal object */ + + (*obj_desc)->buffer.length = (u32) arg_desc->integer.value; + acpi_cm_remove_reference (arg_desc); + + /* Allocate the buffer */ + + if ((*obj_desc)->buffer.length == 0) { + (*obj_desc)->buffer.pointer = NULL; + REPORT_WARNING (("Buffer created with zero length in AML\n")); + break; + } + + else { + (*obj_desc)->buffer.pointer = + acpi_cm_callocate ((*obj_desc)->buffer.length); + + if (!(*obj_desc)->buffer.pointer) { + return (AE_NO_MEMORY); + } + } + + /* + * Second arg is the buffer data (optional) + * Byte_list can be either individual bytes or a + * string initializer! + */ + + /* skip first arg */ + arg = op->value.arg; + byte_list = (ACPI_PARSE2_OBJECT *) arg->next; + if (byte_list) { + if (byte_list->opcode != AML_BYTELIST_OP) { + return (AE_TYPE); + } + + MEMCPY ((*obj_desc)->buffer.pointer, byte_list->data, + (*obj_desc)->buffer.length); + } + + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * When called, an internal package object has already + * been built and is pointed to by *Obj_desc. + * Acpi_ds_build_internal_object build another internal + * package object, so remove reference to the original + * so that it is deleted. Error checking is done + * within the remove reference function. + */ + acpi_cm_remove_reference(*obj_desc); + + status = acpi_ds_build_internal_object (walk_state, op, obj_desc); + break; + + case ACPI_TYPE_INTEGER: + (*obj_desc)->integer.value = op->value.integer; + break; + + + case ACPI_TYPE_STRING: + (*obj_desc)->string.pointer = op->value.string; + (*obj_desc)->string.length = STRLEN (op->value.string); + break; + + + case ACPI_TYPE_METHOD: + break; + + + case INTERNAL_TYPE_REFERENCE: + + switch (ACPI_GET_OP_CLASS (op_info)) { + case OPTYPE_LOCAL_VARIABLE: + + /* Split the opcode into a base opcode + offset */ + + (*obj_desc)->reference.opcode = AML_LOCAL_OP; + (*obj_desc)->reference.offset = opcode - AML_LOCAL_OP; + break; + + case OPTYPE_METHOD_ARGUMENT: + + /* Split the opcode into a base opcode + offset */ + + (*obj_desc)->reference.opcode = AML_ARG_OP; + (*obj_desc)->reference.offset = opcode - AML_ARG_OP; + break; + + default: /* Constants, Literals, etc.. */ + + if (op->opcode == AML_NAMEPATH_OP) { + /* Node was saved in Op */ + + (*obj_desc)->reference.node = op->node; + } + + (*obj_desc)->reference.opcode = opcode; + break; + } + + break; + + + default: + + break; + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_build_internal_simple_obj + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op object to the equivalent namespace object + * Simple objects are any objects other than a package object! + * + ****************************************************************************/ + +static ACPI_STATUS +acpi_ds_build_internal_simple_obj ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT **obj_desc_ptr) +{ + ACPI_OPERAND_OBJECT *obj_desc; + OBJECT_TYPE_INTERNAL type; + ACPI_STATUS status; + u32 length; + char *name; + + + if (op->opcode == AML_NAMEPATH_OP) { + /* + * This is an object reference. If The name was + * previously looked up in the NS, it is stored in this op. + * Otherwise, go ahead and look it up now + */ + + if (!op->node) { + status = acpi_ns_lookup (walk_state->scope_info, + op->value.string, ACPI_TYPE_ANY, + IMODE_EXECUTE, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + NULL, + (ACPI_NAMESPACE_NODE **)&(op->node)); + + if (ACPI_FAILURE (status)) { + if (status == AE_NOT_FOUND) { + name = NULL; + acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name); + + if (name) { + REPORT_WARNING (("Reference %s at AML %X not found\n", + name, op->aml_offset)); + acpi_cm_free (name); + } + else { + REPORT_WARNING (("Reference %s at AML %X not found\n", + op->value.string, op->aml_offset)); + } + *obj_desc_ptr = NULL; + } + + else { + return (status); + } + } + } + + /* + * The reference will be a Reference + * TBD: [Restructure] unless we really need a separate + * type of INTERNAL_TYPE_REFERENCE change + * Acpi_ds_map_opcode_to_data_type to handle this case + */ + type = INTERNAL_TYPE_REFERENCE; + } + else { + type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL); + } + + + /* Create and init the internal ACPI object */ + + obj_desc = acpi_cm_create_internal_object (type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + status = acpi_ds_init_object_from_op (walk_state, op, + op->opcode, &obj_desc); + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + return (status); + } + + *obj_desc_ptr = obj_desc; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_build_internal_package_obj + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op package object to the equivalent + * namespace object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_build_internal_package_obj ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT **obj_desc_ptr) +{ + ACPI_PARSE_OBJECT *arg; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status = AE_OK; + + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* The first argument must be the package length */ + + arg = op->value.arg; + obj_desc->package.count = arg->value.integer; + + /* + * Allocate the array of pointers (ptrs to the + * individual objects) Add an extra pointer slot so + * that the list is always null terminated. + */ + + obj_desc->package.elements = + acpi_cm_callocate ((obj_desc->package.count + 1) * + sizeof (void *)); + + if (!obj_desc->package.elements) { + /* Package vector allocation failure */ + + REPORT_ERROR (("Ds_build_internal_package_obj: Package vector allocation failure\n")); + + acpi_cm_delete_object_desc (obj_desc); + return (AE_NO_MEMORY); + } + + obj_desc->package.next_element = obj_desc->package.elements; + + /* + * Now init the elements of the package + */ + + arg = arg->next; + while (arg) { + if (arg->opcode == AML_PACKAGE_OP) { + status = acpi_ds_build_internal_package_obj (walk_state, arg, + obj_desc->package.next_element); + } + + else { + status = acpi_ds_build_internal_simple_obj (walk_state, arg, + obj_desc->package.next_element); + } + + obj_desc->package.next_element++; + arg = arg->next; + } + + *obj_desc_ptr = obj_desc; + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_build_internal_object + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Translate a parser Op object to the equivalent namespace + * object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_build_internal_object ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT **obj_desc_ptr) +{ + ACPI_STATUS status; + + + if (op->opcode == AML_PACKAGE_OP) { + status = acpi_ds_build_internal_package_obj (walk_state, op, + obj_desc_ptr); + } + + else { + status = acpi_ds_build_internal_simple_obj (walk_state, op, + obj_desc_ptr); + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_create_node + * + * PARAMETERS: Op - Parser object to be translated + * Obj_desc_ptr - Where the ACPI internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_create_node ( + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE *node, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + + + if (!op->value.arg) { + /* No arguments, there is nothing to do */ + + return (AE_OK); + } + + + /* Build an internal object for the argument(s) */ + + status = acpi_ds_build_internal_object (walk_state, + op->value.arg, &obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Re-type the object according to it's argument */ + + node->type = obj_desc->common.type; + + /* Init obj */ + + status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, + (u8) node->type); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + return (status); + + +cleanup: + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + diff --git a/drivers/bus/acpi/dispatcher/dsopcode.c b/drivers/bus/acpi/dispatcher/dsopcode.c new file mode 100644 index 0000000..08a9bac --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dsopcode.c @@ -0,0 +1,875 @@ +/****************************************************************************** + * + * Module Name: dsopcode - Dispatcher Op Region support and handling of + * "control" opcodes + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" +#include "actables.h" + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dsopcode") + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_field_unit_arguments + * + * PARAMETERS: Obj_desc - A valid Field_unit object + * + * RETURN: Status. + * + * DESCRIPTION: Get Field_unit Buffer and Index. This implements the late + * evaluation of these field attributes. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_get_field_unit_arguments ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_OPERAND_OBJECT *extra_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *op; + ACPI_PARSE_OBJECT *field_op; + ACPI_STATUS status; + ACPI_TABLE_DESC *table_desc; + + + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + return (AE_OK); + } + + + /* Get the AML pointer (method object) and Field_unit node */ + + extra_desc = obj_desc->field_unit.extra; + node = obj_desc->field_unit.node; + + /* + * Allocate a new parser op to be the root of the parsed + * Op_region tree + */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Save the Node for use in Acpi_ps_parse_aml */ + + op->node = acpi_ns_get_parent_object (node); + + /* Get a handle to the parent ACPI table */ + + status = acpi_tb_handle_to_object (node->owner_id, &table_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Pass1: Parse the entire Field_unit declaration */ + + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, 0, + NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + if (ACPI_FAILURE (status)) { + acpi_ps_delete_parse_tree (op); + return (status); + } + + + /* Get and init the actual Fiel_unit_op created above */ + + field_op = op->value.arg; + op->node = node; + + + field_op = op->value.arg; + field_op->node = node; + acpi_ps_delete_parse_tree (op); + + /* Acpi_evaluate the address and length arguments for the Op_region */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + op->node = acpi_ns_get_parent_object (node); + + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, + ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE, + NULL /*Method_desc*/, NULL, NULL, + acpi_ds_exec_begin_op, acpi_ds_exec_end_op); + /* All done with the parse tree, delete it */ + + acpi_ps_delete_parse_tree (op); + + + /* + * The pseudo-method object is no longer needed since the region is + * now initialized + */ + acpi_cm_remove_reference (obj_desc->field_unit.extra); + obj_desc->field_unit.extra = NULL; + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_region_arguments + * + * PARAMETERS: Obj_desc - A valid region object + * + * RETURN: Status. + * + * DESCRIPTION: Get region address and length. This implements the late + * evaluation of these region attributes. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_get_region_arguments ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_OPERAND_OBJECT *extra_desc = NULL; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *op; + ACPI_PARSE_OBJECT *region_op; + ACPI_STATUS status; + ACPI_TABLE_DESC *table_desc; + + + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + return (AE_OK); + } + + + /* Get the AML pointer (method object) and region node */ + + extra_desc = obj_desc->region.extra; + node = obj_desc->region.node; + + /* + * Allocate a new parser op to be the root of the parsed + * Op_region tree + */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Save the Node for use in Acpi_ps_parse_aml */ + + op->node = acpi_ns_get_parent_object (node); + + /* Get a handle to the parent ACPI table */ + + status = acpi_tb_handle_to_object (node->owner_id, &table_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Parse the entire Op_region declaration, creating a parse tree */ + + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, 0, + NULL, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + + if (ACPI_FAILURE (status)) { + acpi_ps_delete_parse_tree (op); + return (status); + } + + + /* Get and init the actual Region_op created above */ + + region_op = op->value.arg; + op->node = node; + + + region_op = op->value.arg; + region_op->node = node; + acpi_ps_delete_parse_tree (op); + + /* Acpi_evaluate the address and length arguments for the Op_region */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + op->node = acpi_ns_get_parent_object (node); + + status = acpi_ps_parse_aml (op, extra_desc->extra.pcode, + extra_desc->extra.pcode_length, + ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE, + NULL /*Method_desc*/, NULL, NULL, + acpi_ds_exec_begin_op, acpi_ds_exec_end_op); + + /* All done with the parse tree, delete it */ + + acpi_ps_delete_parse_tree (op); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_initialize_region + * + * PARAMETERS: Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_initialize_region ( + ACPI_HANDLE obj_handle) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + obj_desc = acpi_ns_get_attached_object (obj_handle); + + /* Namespace is NOT locked */ + + status = acpi_ev_initialize_region (obj_desc, FALSE); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_eval_field_unit_operands + * + * PARAMETERS: Op - A valid Field_unit Op object + * + * RETURN: Status + * + * DESCRIPTION: Get Field_unit Buffer and Index + * Called from Acpi_ds_exec_end_op during Field_unit parse tree walk + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_eval_field_unit_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *field_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *next_op; + u32 offset; + u32 bit_offset; + u16 bit_count; + + + ACPI_OPERAND_OBJECT *res_desc = NULL; + ACPI_OPERAND_OBJECT *cnt_desc = NULL; + ACPI_OPERAND_OBJECT *off_desc = NULL; + ACPI_OPERAND_OBJECT *src_desc = NULL; + u32 num_operands = 3; + + + /* + * This is where we evaluate the address and length fields of the Op_field_unit declaration + */ + + node = op->node; + + /* Next_op points to the op that holds the Buffer */ + next_op = op->value.arg; + + /* Acpi_evaluate/create the address and length operands */ + + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + return (status); + } + + field_desc = acpi_ns_get_attached_object (node); + if (!field_desc) { + return (AE_NOT_EXIST); + } + + + /* Resolve the operands */ + + status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); + + /* Get the operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + if (AML_CREATE_FIELD_OP == op->opcode) { + num_operands = 4; + status |= acpi_ds_obj_stack_pop_object (&cnt_desc, walk_state); + } + + status |= acpi_ds_obj_stack_pop_object (&off_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&src_desc, walk_state); + + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + offset = (u32) off_desc->integer.value; + + + /* + * If Res_desc is a Name, it will be a direct name pointer after + * Acpi_aml_resolve_operands() + */ + + if (!VALID_DESCRIPTOR_TYPE (res_desc, ACPI_DESC_TYPE_NAMED)) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + /* + * Setup the Bit offsets and counts, according to the opcode + */ + + switch (op->opcode) { + + /* Def_create_bit_field */ + + case AML_BIT_FIELD_OP: + + /* Offset is in bits, Field is a bit */ + + bit_offset = offset; + bit_count = 1; + break; + + + /* Def_create_byte_field */ + + case AML_BYTE_FIELD_OP: + + /* Offset is in bytes, field is a byte */ + + bit_offset = 8 * offset; + bit_count = 8; + break; + + + /* Def_create_word_field */ + + case AML_WORD_FIELD_OP: + + /* Offset is in bytes, field is a word */ + + bit_offset = 8 * offset; + bit_count = 16; + break; + + + /* Def_create_dWord_field */ + + case AML_DWORD_FIELD_OP: + + /* Offset is in bytes, field is a dword */ + + bit_offset = 8 * offset; + bit_count = 32; + break; + + + /* Def_create_field */ + + case AML_CREATE_FIELD_OP: + + /* Offset is in bits, count is in bits */ + + bit_offset = offset; + bit_count = (u16) cnt_desc->integer.value; + break; + + + default: + + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Setup field according to the object type + */ + + switch (src_desc->common.type) { + + /* Source_buff := Term_arg=>Buffer */ + + case ACPI_TYPE_BUFFER: + + if (bit_offset + (u32) bit_count > + (8 * (u32) src_desc->buffer.length)) { + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + + /* Construct the remainder of the field object */ + + field_desc->field_unit.access = (u8) ACCESS_ANY_ACC; + field_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; + field_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; + field_desc->field_unit.length = bit_count; + field_desc->field_unit.bit_offset = (u8) (bit_offset % 8); + field_desc->field_unit.offset = DIV_8 (bit_offset); + field_desc->field_unit.container = src_desc; + + /* Reference count for Src_desc inherits Field_desc count */ + + src_desc->common.reference_count = (u16) (src_desc->common.reference_count + + field_desc->common.reference_count); + + break; + + + /* Improper object type */ + + default: + + + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + if (AML_CREATE_FIELD_OP == op->opcode) { + /* Delete object descriptor unique to Create_field */ + + acpi_cm_remove_reference (cnt_desc); + cnt_desc = NULL; + } + + +cleanup: + + /* Always delete the operands */ + + acpi_cm_remove_reference (off_desc); + acpi_cm_remove_reference (src_desc); + + if (AML_CREATE_FIELD_OP == op->opcode) { + acpi_cm_remove_reference (cnt_desc); + } + + /* On failure, delete the result descriptor */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); /* Result descriptor */ + } + + else { + /* Now the address and length are valid for this op_field_unit */ + + field_desc->field_unit.flags |= AOPOBJ_DATA_VALID; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_eval_region_operands + * + * PARAMETERS: Op - A valid region Op object + * + * RETURN: Status + * + * DESCRIPTION: Get region address and length + * Called from Acpi_ds_exec_end_op during Op_region parse tree walk + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_eval_region_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *operand_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *next_op; + + + /* + * This is where we evaluate the address and length fields of the Op_region declaration + */ + + node = op->node; + + /* Next_op points to the op that holds the Space_iD */ + next_op = op->value.arg; + + /* Next_op points to address op */ + next_op = next_op->next; + + /* Acpi_evaluate/create the address and length operands */ + + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Resolve the length and address operands to numbers */ + + status = acpi_aml_resolve_operands (op->opcode, WALK_OPERANDS, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + obj_desc = acpi_ns_get_attached_object (node); + if (!obj_desc) { + return (AE_NOT_EXIST); + } + + /* + * Get the length operand and save it + * (at Top of stack) + */ + operand_desc = walk_state->operands[walk_state->num_operands - 1]; + + obj_desc->region.length = (u32) operand_desc->integer.value; + acpi_cm_remove_reference (operand_desc); + + /* + * Get the address and save it + * (at top of stack - 1) + */ + operand_desc = walk_state->operands[walk_state->num_operands - 2]; + + obj_desc->region.address = (ACPI_PHYSICAL_ADDRESS) operand_desc->integer.value; + acpi_cm_remove_reference (operand_desc); + + + /* Now the address and length are valid for this opregion */ + + obj_desc->region.flags |= AOPOBJ_DATA_VALID; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_exec_begin_control_op + * + * PARAMETERS: Walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_begin_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_STATE *control_state; + + + switch (op->opcode) { + case AML_IF_OP: + case AML_WHILE_OP: + + /* + * IF/WHILE: Create a new control state to manage these + * constructs. We need to manage these as a stack, in order + * to handle nesting. + */ + + control_state = acpi_cm_create_control_state (); + if (!control_state) { + status = AE_NO_MEMORY; + break; + } + + acpi_cm_push_generic_state (&walk_state->control_state, control_state); + + /* + * Save a pointer to the predicate for multiple executions + * of a loop + */ + walk_state->control_state->control.aml_predicate_start = + walk_state->parser_state->aml - 1; + /* TBD: can this be removed? */ + /*Acpi_ps_pkg_length_encoding_size (GET8 (Walk_state->Parser_state->Aml));*/ + break; + + + case AML_ELSE_OP: + + /* Predicate is in the state object */ + /* If predicate is true, the IF was executed, ignore ELSE part */ + + if (walk_state->last_predicate) { + status = AE_CTRL_TRUE; + } + + break; + + + case AML_RETURN_OP: + + break; + + + default: + break; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_exec_end_control_op + * + * PARAMETERS: Walk_list - The list that owns the walk stack + * Op - The control Op + * + * RETURN: Status + * + * DESCRIPTION: Handles all control ops encountered during control method + * execution. + * + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_end_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_STATE *control_state; + + + switch (op->opcode) { + case AML_IF_OP: + + /* + * Save the result of the predicate in case there is an + * ELSE to come + */ + + walk_state->last_predicate = + (u8) walk_state->control_state->common.value; + + /* + * Pop the control state that was created at the start + * of the IF and free it + */ + + control_state = + acpi_cm_pop_generic_state (&walk_state->control_state); + + acpi_cm_delete_generic_state (control_state); + + break; + + + case AML_ELSE_OP: + + break; + + + case AML_WHILE_OP: + + if (walk_state->control_state->common.value) { + /* Predicate was true, go back and evaluate it again! */ + + status = AE_CTRL_PENDING; + } + + + /* Pop this control state and free it */ + + control_state = + acpi_cm_pop_generic_state (&walk_state->control_state); + + walk_state->aml_last_while = control_state->control.aml_predicate_start; + acpi_cm_delete_generic_state (control_state); + + break; + + + case AML_RETURN_OP: + + + /* + * One optional operand -- the return value + * It can be either an immediate operand or a result that + * has been bubbled up the tree + */ + if (op->value.arg) { + /* Return statement has an immediate operand */ + + status = acpi_ds_create_operands (walk_state, op->value.arg); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + */ + status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Get the return value and save as the last result + * value. This is the only place where Walk_state->Return_desc + * is set to anything other than zero! + */ + + walk_state->return_desc = walk_state->operands[0]; + } + + else if ((walk_state->results) && + (walk_state->results->results.num_results > 0)) { + /* + * The return value has come from a previous calculation. + * + * If value being returned is a Reference (such as + * an arg or local), resolve it now because it may + * cease to exist at the end of the method. + * + * Allow references created by the Index operator to return unchanged. + */ + + if (VALID_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc [0], ACPI_DESC_TYPE_INTERNAL) && + ((walk_state->results->results.obj_desc [0])->common.type == INTERNAL_TYPE_REFERENCE) && + ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) { + status = acpi_aml_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + walk_state->return_desc = walk_state->results->results.obj_desc [0]; + } + + else { + /* No return operand */ + + if (walk_state->num_operands) { + acpi_cm_remove_reference (walk_state->operands [0]); + } + + walk_state->operands [0] = NULL; + walk_state->num_operands = 0; + walk_state->return_desc = NULL; + } + + + /* End the control method execution right now */ + status = AE_CTRL_TERMINATE; + break; + + + case AML_NOOP_OP: + + /* Just do nothing! */ + break; + + + case AML_BREAK_POINT_OP: + + /* Call up to the OS dependent layer to handle this */ + + acpi_os_breakpoint (NULL); + + /* If it returns, we are done! */ + + break; + + + case AML_BREAK_OP: + + /* + * As per the ACPI specification: + * "The break operation causes the current package + * execution to complete" + * "Break -- Stop executing the current code package + * at this point" + * + * Returning AE_FALSE here will cause termination of + * the current package, and execution will continue one + * level up, starting with the completion of the parent Op. + */ + + status = AE_CTRL_FALSE; + break; + + + default: + + status = AE_AML_BAD_OPCODE; + break; + } + + + return (status); +} + diff --git a/drivers/bus/acpi/dispatcher/dsutils.c b/drivers/bus/acpi/dispatcher/dsutils.c new file mode 100644 index 0000000..64951a6 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dsutils.c @@ -0,0 +1,750 @@ +/******************************************************************************* + * + * Module Name: dsutils - Dispatcher utilities + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dsutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_is_result_used + * + * PARAMETERS: Op + * Result_obj + * Walk_state + * + * RETURN: Status + * + * DESCRIPTION: Check if a result object will be used by the parent + * + ******************************************************************************/ + +u8 +acpi_ds_is_result_used ( + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPCODE_INFO *parent_info; + + + /* Must have both an Op and a Result Object */ + + if (!op) { + return (TRUE); + } + + + /* + * If there is no parent, the result can't possibly be used! + * (An executing method typically has no parent, since each + * method is parsed separately) However, a method that is + * invoked from another method has a parent. + */ + if (!op->parent) { + return (FALSE); + } + + + /* + * Get info on the parent. The root Op is AML_SCOPE + */ + + parent_info = acpi_ps_get_opcode_info (op->parent->opcode); + if (ACPI_GET_OP_TYPE (parent_info) != ACPI_OP_TYPE_OPCODE) { + return (FALSE); + } + + + /* + * Decide what to do with the result based on the parent. If + * the parent opcode will not use the result, delete the object. + * Otherwise leave it as is, it will be deleted when it is used + * as an operand later. + */ + + switch (ACPI_GET_OP_CLASS (parent_info)) { + /* + * In these cases, the parent will never use the return object + */ + case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */ + + switch (op->parent->opcode) { + case AML_RETURN_OP: + + /* Never delete the return value associated with a return opcode */ + + return (TRUE); + break; + + case AML_IF_OP: + case AML_WHILE_OP: + + /* + * If we are executing the predicate AND this is the predicate op, + * we will use the return value! + */ + + if ((walk_state->control_state->common.state == CONTROL_PREDICATE_EXECUTING) && + (walk_state->control_state->control.predicate_op == op)) { + return (TRUE); + } + + break; + } + + + /* Fall through to not used case below */ + + + case OPTYPE_NAMED_OBJECT: /* Scope, method, etc. */ + + /* + * These opcodes allow Term_arg(s) as operands and therefore + * method calls. The result is used. + */ + if ((op->parent->opcode == AML_REGION_OP) || + (op->parent->opcode == AML_CREATE_FIELD_OP) || + (op->parent->opcode == AML_BIT_FIELD_OP) || + (op->parent->opcode == AML_BYTE_FIELD_OP) || + (op->parent->opcode == AML_WORD_FIELD_OP) || + (op->parent->opcode == AML_DWORD_FIELD_OP) || + (op->parent->opcode == AML_QWORD_FIELD_OP)) { + return (TRUE); + } + + return (FALSE); + break; + + /* + * In all other cases. the parent will actually use the return + * object, so keep it. + */ + default: + break; + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_delete_result_if_not_used + * + * PARAMETERS: Op + * Result_obj + * Walk_state + * + * RETURN: Status + * + * DESCRIPTION: Used after interpretation of an opcode. If there is an internal + * result descriptor, check if the parent opcode will actually use + * this result. If not, delete the result now so that it will + * not become orphaned. + * + ******************************************************************************/ + +void +acpi_ds_delete_result_if_not_used ( + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT *result_obj, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + if (!op) { + return; + } + + if (!result_obj) { + return; + } + + + if (!acpi_ds_is_result_used (op, walk_state)) { + /* + * Must pop the result stack (Obj_desc should be equal + * to Result_obj) + */ + + status = acpi_ds_result_pop (&obj_desc, walk_state); + if (ACPI_SUCCESS (status)) { + acpi_cm_remove_reference (result_obj); + } + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_operand + * + * PARAMETERS: Walk_state + * Arg + * + * RETURN: Status + * + * DESCRIPTION: Translate a parse tree object that is an argument to an AML + * opcode to the equivalent interpreter object. This may include + * looking up a name or entering a new name into the internal + * namespace. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_create_operand ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *arg, + u32 arg_index) +{ + ACPI_STATUS status = AE_OK; + NATIVE_CHAR *name_string; + u32 name_length; + OBJECT_TYPE_INTERNAL data_type; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_PARSE_OBJECT *parent_op; + u16 opcode; + u32 flags; + OPERATING_MODE interpreter_mode; + + + /* A valid name must be looked up in the namespace */ + + if ((arg->opcode == AML_NAMEPATH_OP) && + (arg->value.string)) { + /* Get the entire name string from the AML stream */ + + status = acpi_aml_get_name_string (ACPI_TYPE_ANY, + arg->value.buffer, + &name_string, + &name_length); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * All prefixes have been handled, and the name is + * in Name_string + */ + + /* + * Differentiate between a namespace "create" operation + * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. + * IMODE_EXECUTE) in order to support the creation of + * namespace objects during the execution of control methods. + */ + + parent_op = arg->parent; + if ((acpi_ps_is_node_op (parent_op->opcode)) && + (parent_op->opcode != AML_METHODCALL_OP) && + (parent_op->opcode != AML_REGION_OP) && + (parent_op->opcode != AML_NAMEPATH_OP)) { + /* Enter name into namespace if not found */ + + interpreter_mode = IMODE_LOAD_PASS2; + } + + else { + /* Return a failure if name not found */ + + interpreter_mode = IMODE_EXECUTE; + } + + status = acpi_ns_lookup (walk_state->scope_info, name_string, + ACPI_TYPE_ANY, interpreter_mode, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + walk_state, + (ACPI_NAMESPACE_NODE **) &obj_desc); + + /* Free the namestring created above */ + + acpi_cm_free (name_string); + + /* + * The only case where we pass through (ignore) a NOT_FOUND + * error is for the Cond_ref_of opcode. + */ + + if (status == AE_NOT_FOUND) { + if (parent_op->opcode == AML_COND_REF_OF_OP) { + /* + * For the Conditional Reference op, it's OK if + * the name is not found; We just need a way to + * indicate this to the interpreter, set the + * object to the root + */ + obj_desc = (ACPI_OPERAND_OBJECT *) acpi_gbl_root_node; + status = AE_OK; + } + + else { + /* + * We just plain didn't find it -- which is a + * very serious error at this point + */ + status = AE_AML_NAME_NOT_FOUND; + } + } + + /* Check status from the lookup */ + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Put the resulting object onto the current object stack */ + + status = acpi_ds_obj_stack_push (obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state)); + } + + + else { + /* Check for null name case */ + + if (arg->opcode == AML_NAMEPATH_OP) { + /* + * If the name is null, this means that this is an + * optional result parameter that was not specified + * in the original ASL. Create an Reference for a + * placeholder + */ + opcode = AML_ZERO_OP; /* Has no arguments! */ + + /* + * TBD: [Investigate] anything else needed for the + * zero op lvalue? + */ + } + + else { + opcode = arg->opcode; + } + + + /* Get the data type of the argument */ + + data_type = acpi_ds_map_opcode_to_data_type (opcode, &flags); + if (data_type == INTERNAL_TYPE_INVALID) { + return (AE_NOT_IMPLEMENTED); + } + + if (flags & OP_HAS_RETURN_VALUE) { + DEBUGGER_EXEC (acpi_db_display_argument_object (walk_state->operands [walk_state->num_operands - 1], walk_state)); + + /* + * Use value that was already previously returned + * by the evaluation of this argument + */ + + status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* + * Only error is underflow, and this indicates + * a missing or null operand! + */ + return (status); + } + + } + + else { + /* Create an ACPI_INTERNAL_OBJECT for the argument */ + + obj_desc = acpi_cm_create_internal_object (data_type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Initialize the new object */ + + status = acpi_ds_init_object_from_op (walk_state, arg, + opcode, &obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_delete_object_desc (obj_desc); + return (status); + } + } + + /* Put the operand object on the object stack */ + + status = acpi_ds_obj_stack_push (obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state)); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_operands + * + * PARAMETERS: First_arg - First argument of a parser argument tree + * + * RETURN: Status + * + * DESCRIPTION: Convert an operator's arguments from a parse tree format to + * namespace objects and place those argument object on the object + * stack in preparation for evaluation by the interpreter. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_create_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *first_arg) +{ + ACPI_STATUS status = AE_OK; + ACPI_PARSE_OBJECT *arg; + u32 arg_count = 0; + + + /* For all arguments in the list... */ + + arg = first_arg; + while (arg) { + status = acpi_ds_create_operand (walk_state, arg, arg_count); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Move on to next argument, if any */ + + arg = arg->next; + arg_count++; + } + + return (status); + + +cleanup: + /* + * We must undo everything done above; meaning that we must + * pop everything off of the operand stack and delete those + * objects + */ + + acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_resolve_operands + * + * PARAMETERS: Walk_state - Current walk state with operands on stack + * + * RETURN: Status + * + * DESCRIPTION: Resolve all operands to their values. Used to prepare + * arguments to a control method invocation (a call from one + * method to another.) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_resolve_operands ( + ACPI_WALK_STATE *walk_state) +{ + u32 i; + ACPI_STATUS status = AE_OK; + + + /* + * Attempt to resolve each of the valid operands + * Method arguments are passed by value, not by reference + */ + + /* + * TBD: [Investigate] Note from previous parser: + * Ref_of problem with Acpi_aml_resolve_to_value() conversion. + */ + + for (i = 0; i < walk_state->num_operands; i++) { + status = acpi_aml_resolve_to_value (&walk_state->operands[i], walk_state); + if (ACPI_FAILURE (status)) { + break; + } + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_map_opcode_to_data_type + * + * PARAMETERS: Opcode - AML opcode to map + * Out_flags - Additional info about the opcode + * + * RETURN: The ACPI type associated with the opcode + * + * DESCRIPTION: Convert a raw AML opcode to the associated ACPI data type, + * if any. If the opcode returns a value as part of the + * intepreter execution, a flag is returned in Out_flags. + * + ******************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ds_map_opcode_to_data_type ( + u16 opcode, + u32 *out_flags) +{ + OBJECT_TYPE_INTERNAL data_type = INTERNAL_TYPE_INVALID; + ACPI_OPCODE_INFO *op_info; + u32 flags = 0; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + /* Unknown opcode */ + + return (data_type); + } + + switch (ACPI_GET_OP_CLASS (op_info)) { + + case OPTYPE_LITERAL: + + switch (opcode) { + case AML_BYTE_OP: + case AML_WORD_OP: + case AML_DWORD_OP: + + data_type = ACPI_TYPE_INTEGER; + break; + + + case AML_STRING_OP: + + data_type = ACPI_TYPE_STRING; + break; + + case AML_NAMEPATH_OP: + data_type = INTERNAL_TYPE_REFERENCE; + break; + + default: + break; + } + break; + + + case OPTYPE_DATA_TERM: + + switch (opcode) { + case AML_BUFFER_OP: + + data_type = ACPI_TYPE_BUFFER; + break; + + case AML_PACKAGE_OP: + + data_type = ACPI_TYPE_PACKAGE; + break; + + default: + break; + } + break; + + + case OPTYPE_CONSTANT: + case OPTYPE_METHOD_ARGUMENT: + case OPTYPE_LOCAL_VARIABLE: + + data_type = INTERNAL_TYPE_REFERENCE; + break; + + + case OPTYPE_MONADIC2: + case OPTYPE_MONADIC2_r: + case OPTYPE_DYADIC2: + case OPTYPE_DYADIC2_r: + case OPTYPE_DYADIC2_s: + case OPTYPE_INDEX: + case OPTYPE_MATCH: + case OPTYPE_RETURN: + + flags = OP_HAS_RETURN_VALUE; + data_type = ACPI_TYPE_ANY; + break; + + case OPTYPE_METHOD_CALL: + + flags = OP_HAS_RETURN_VALUE; + data_type = ACPI_TYPE_METHOD; + break; + + + case OPTYPE_NAMED_OBJECT: + + data_type = acpi_ds_map_named_opcode_to_data_type (opcode); + break; + + + case OPTYPE_DYADIC1: + case OPTYPE_CONTROL: + + /* No mapping needed at this time */ + + break; + + + default: + + break; + } + + /* Return flags to caller if requested */ + + if (out_flags) { + *out_flags = flags; + } + + return (data_type); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_map_named_opcode_to_data_type + * + * PARAMETERS: Opcode - The Named AML opcode to map + * + * RETURN: The ACPI type associated with the named opcode + * + * DESCRIPTION: Convert a raw Named AML opcode to the associated data type. + * Named opcodes are a subsystem of the AML opcodes. + * + ******************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ds_map_named_opcode_to_data_type ( + u16 opcode) +{ + OBJECT_TYPE_INTERNAL data_type; + + + /* Decode Opcode */ + + switch (opcode) { + case AML_SCOPE_OP: + data_type = INTERNAL_TYPE_SCOPE; + break; + + case AML_DEVICE_OP: + data_type = ACPI_TYPE_DEVICE; + break; + + case AML_THERMAL_ZONE_OP: + data_type = ACPI_TYPE_THERMAL; + break; + + case AML_METHOD_OP: + data_type = ACPI_TYPE_METHOD; + break; + + case AML_POWER_RES_OP: + data_type = ACPI_TYPE_POWER; + break; + + case AML_PROCESSOR_OP: + data_type = ACPI_TYPE_PROCESSOR; + break; + + case AML_DEF_FIELD_OP: /* Def_field_op */ + data_type = INTERNAL_TYPE_DEF_FIELD_DEFN; + break; + + case AML_INDEX_FIELD_OP: /* Index_field_op */ + data_type = INTERNAL_TYPE_INDEX_FIELD_DEFN; + break; + + case AML_BANK_FIELD_OP: /* Bank_field_op */ + data_type = INTERNAL_TYPE_BANK_FIELD_DEFN; + break; + + case AML_NAMEDFIELD_OP: /* NO CASE IN ORIGINAL */ + data_type = ACPI_TYPE_ANY; + break; + + case AML_NAME_OP: /* Name_op - special code in original */ + case AML_NAMEPATH_OP: + data_type = ACPI_TYPE_ANY; + break; + + case AML_ALIAS_OP: + data_type = INTERNAL_TYPE_ALIAS; + break; + + case AML_MUTEX_OP: + data_type = ACPI_TYPE_MUTEX; + break; + + case AML_EVENT_OP: + data_type = ACPI_TYPE_EVENT; + break; + + case AML_REGION_OP: + data_type = ACPI_TYPE_REGION; + break; + + + default: + data_type = ACPI_TYPE_ANY; + break; + + } + + return (data_type); +} + + diff --git a/drivers/bus/acpi/dispatcher/dswexec.c b/drivers/bus/acpi/dispatcher/dswexec.c new file mode 100644 index 0000000..6d34445 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dswexec.c @@ -0,0 +1,653 @@ +/****************************************************************************** + * + * Module Name: dswexec - Dispatcher method execution callbacks; + * dispatch to interpreter. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dswexec") + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_get_predicate_value + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Get the result of a predicate evaluation + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_get_predicate_value ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + u32 has_result_obj) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *obj_desc; + + + walk_state->control_state->common.state = 0; + + if (has_result_obj) { + status = acpi_ds_result_pop (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + else { + status = acpi_ds_create_operand (walk_state, op, 0); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_aml_resolve_to_value (&walk_state->operands [0], walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + obj_desc = walk_state->operands [0]; + } + + if (!obj_desc) { + return (AE_AML_NO_OPERAND); + } + + + /* + * Result of predicate evaluation currently must + * be a number + */ + + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + + /* Truncate the predicate to 32-bits if necessary */ + + acpi_aml_truncate_for32bit_table (obj_desc, walk_state); + + /* + * Save the result of the predicate evaluation on + * the control stack + */ + + if (obj_desc->integer.value) { + walk_state->control_state->common.value = TRUE; + } + + else { + /* + * Predicate is FALSE, we will just toss the + * rest of the package + */ + + walk_state->control_state->common.value = FALSE; + status = AE_CTRL_FALSE; + } + + +cleanup: + + /* Break to debugger to display result */ + + DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state)); + + /* + * Delete the predicate result object (we know that + * we don't need it anymore) + */ + + acpi_cm_remove_reference (obj_desc); + + walk_state->control_state->common.state = CONTROL_NORMAL; + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_exec_begin_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been reached in the + * walk; Arguments have not been evaluated yet. + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the execution of control + * methods. This is where most operators and operands are + * dispatched to the interpreter. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op) +{ + ACPI_OPCODE_INFO *op_info; + ACPI_STATUS status = AE_OK; + + + if (!op) { + status = acpi_ds_load2_begin_op (opcode, NULL, walk_state, out_op); + if (ACPI_FAILURE (status)) { + return (status); + } + + op = *out_op; + } + + if (op == walk_state->origin) { + if (out_op) { + *out_op = op; + } + + return (AE_OK); + } + + /* + * If the previous opcode was a conditional, this opcode + * must be the beginning of the associated predicate. + * Save this knowledge in the current scope descriptor + */ + + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + CONTROL_CONDITIONAL_EXECUTING)) { + walk_state->control_state->common.state = CONTROL_PREDICATE_EXECUTING; + + /* Save start of predicate */ + + walk_state->control_state->control.predicate_op = op; + } + + + op_info = acpi_ps_get_opcode_info (op->opcode); + + /* We want to send namepaths to the load code */ + + if (op->opcode == AML_NAMEPATH_OP) { + op_info->flags = OPTYPE_NAMED_OBJECT; + } + + + /* + * Handle the opcode based upon the opcode type + */ + + switch (ACPI_GET_OP_CLASS (op_info)) { + case OPTYPE_CONTROL: + + status = acpi_ds_result_stack_push (walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ds_exec_begin_control_op (walk_state, op); + break; + + + case OPTYPE_NAMED_OBJECT: + + if (walk_state->walk_type == WALK_METHOD) { + /* + * Found a named object declaration during method + * execution; we must enter this object into the + * namespace. The created object is temporary and + * will be deleted upon completion of the execution + * of this method. + */ + + status = acpi_ds_load2_begin_op (op->opcode, op, walk_state, NULL); + } + + + if (op->opcode == AML_REGION_OP) { + status = acpi_ds_result_stack_push (walk_state); + } + + break; + + + /* most operators with arguments */ + + case OPTYPE_MONADIC1: + case OPTYPE_DYADIC1: + case OPTYPE_MONADIC2: + case OPTYPE_MONADIC2_r: + case OPTYPE_DYADIC2: + case OPTYPE_DYADIC2_r: + case OPTYPE_DYADIC2_s: + case OPTYPE_RECONFIGURATION: + case OPTYPE_INDEX: + case OPTYPE_MATCH: + case OPTYPE_FATAL: + case OPTYPE_CREATE_FIELD: + + /* Start a new result/operand state */ + + status = acpi_ds_result_stack_push (walk_state); + break; + + + default: + break; + } + + /* Nothing to do here during method execution */ + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ds_exec_end_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been completed in the + * walk; Arguments have now been evaluated. + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the execution of control + * methods. The only thing we really need to do here is to + * notice the beginning of IF, ELSE, and WHILE blocks. + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ds_exec_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status = AE_OK; + u16 opcode; + u8 optype; + ACPI_PARSE_OBJECT *next_op; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *first_arg; + ACPI_OPERAND_OBJECT *result_obj = NULL; + ACPI_OPCODE_INFO *op_info; + u32 operand_index; + + + opcode = (u16) op->opcode; + + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + return (AE_NOT_IMPLEMENTED); + } + + optype = (u8) ACPI_GET_OP_CLASS (op_info); + first_arg = op->value.arg; + + /* Init the walk state */ + + walk_state->num_operands = 0; + walk_state->return_desc = NULL; + walk_state->op_info = op_info; + walk_state->opcode = opcode; + + + /* Call debugger for single step support (DEBUG build only) */ + + DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, optype)); + DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return (status);}); + + + /* Decode the opcode */ + + switch (optype) { + case OPTYPE_UNDEFINED: + + return (AE_NOT_IMPLEMENTED); + break; + + + case OPTYPE_BOGUS: + break; + + case OPTYPE_CONSTANT: /* argument type only */ + case OPTYPE_LITERAL: /* argument type only */ + case OPTYPE_DATA_TERM: /* argument type only */ + case OPTYPE_LOCAL_VARIABLE: /* argument type only */ + case OPTYPE_METHOD_ARGUMENT: /* argument type only */ + break; + + + /* most operators with arguments */ + + case OPTYPE_MONADIC1: + case OPTYPE_DYADIC1: + case OPTYPE_MONADIC2: + case OPTYPE_MONADIC2_r: + case OPTYPE_DYADIC2: + case OPTYPE_DYADIC2_r: + case OPTYPE_DYADIC2_s: + case OPTYPE_RECONFIGURATION: + case OPTYPE_INDEX: + case OPTYPE_MATCH: + case OPTYPE_FATAL: + + + /* Build resolved operand stack */ + + status = acpi_ds_create_operands (walk_state, first_arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + operand_index = walk_state->num_operands - 1; + + + /* Done with this result state (Now that operand stack is built) */ + + status = acpi_ds_result_stack_pop (walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + switch (optype) { + case OPTYPE_MONADIC1: + + /* 1 Operand, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_monadic1 (opcode, walk_state); + break; + + + case OPTYPE_MONADIC2: + + /* 1 Operand, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_monadic2 (opcode, walk_state, &result_obj); + break; + + + case OPTYPE_MONADIC2_r: + + /* 1 Operand, 1 External_result, 1 Internal_result */ + + status = acpi_aml_exec_monadic2_r (opcode, walk_state, &result_obj); + break; + + + case OPTYPE_DYADIC1: + + /* 2 Operands, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_dyadic1 (opcode, walk_state); + break; + + + case OPTYPE_DYADIC2: + + /* 2 Operands, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_dyadic2 (opcode, walk_state, &result_obj); + break; + + + case OPTYPE_DYADIC2_r: + + /* 2 Operands, 1 or 2 External_results, 1 Internal_result */ + + status = acpi_aml_exec_dyadic2_r (opcode, walk_state, &result_obj); + break; + + + case OPTYPE_DYADIC2_s: /* Synchronization Operator */ + + /* 2 Operands, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_dyadic2_s (opcode, walk_state, &result_obj); + break; + + + case OPTYPE_INDEX: /* Type 2 opcode with 3 operands */ + + /* 3 Operands, 1 External_result, 1 Internal_result */ + + status = acpi_aml_exec_index (walk_state, &result_obj); + break; + + + case OPTYPE_MATCH: /* Type 2 opcode with 6 operands */ + + /* 6 Operands, 0 External_result, 1 Internal_result */ + + status = acpi_aml_exec_match (walk_state, &result_obj); + break; + + + case OPTYPE_RECONFIGURATION: + + /* 1 or 2 operands, 0 Internal Result */ + + status = acpi_aml_exec_reconfiguration (opcode, walk_state); + break; + + + case OPTYPE_FATAL: + + /* 3 Operands, 0 External_result, 0 Internal_result */ + + status = acpi_aml_exec_fatal (walk_state); + break; + } + + /* + * If a result object was returned from above, push it on the + * current result stack + */ + if (ACPI_SUCCESS (status) && + result_obj) { + status = acpi_ds_result_push (result_obj, walk_state); + } + + break; + + + case OPTYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ + + /* 1 Operand, 0 External_result, 0 Internal_result */ + + status = acpi_ds_exec_end_control_op (walk_state, op); + + acpi_ds_result_stack_pop (walk_state); + break; + + + case OPTYPE_METHOD_CALL: + + /* + * (AML_METHODCALL) Op->Value->Arg->Node contains + * the method Node pointer + */ + /* Next_op points to the op that holds the method name */ + + next_op = first_arg; + node = next_op->node; + + /* Next_op points to first argument op */ + + next_op = next_op->next; + + /* + * Get the method's arguments and put them on the operand stack + */ + status = acpi_ds_create_operands (walk_state, next_op); + if (ACPI_FAILURE (status)) { + break; + } + + /* + * Since the operands will be passed to another + * control method, we must resolve all local + * references here (Local variables, arguments + * to *this* method, etc.) + */ + + status = acpi_ds_resolve_operands (walk_state); + if (ACPI_FAILURE (status)) { + break; + } + + /* + * Tell the walk loop to preempt this running method and + * execute the new method + */ + status = AE_CTRL_TRANSFER; + + /* + * Return now; we don't want to disturb anything, + * especially the operand count! + */ + return (status); + break; + + + case OPTYPE_CREATE_FIELD: + + status = acpi_ds_load2_end_op (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } + + status = acpi_ds_eval_field_unit_operands (walk_state, op); + break; + + + case OPTYPE_NAMED_OBJECT: + + status = acpi_ds_load2_end_op (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } + + switch (op->opcode) { + case AML_REGION_OP: + + status = acpi_ds_eval_region_operands (walk_state, op); + if (ACPI_FAILURE (status)) { + break; + } + + status = acpi_ds_result_stack_pop (walk_state); + break; + + + case AML_METHOD_OP: + break; + + + case AML_ALIAS_OP: + + /* Alias creation was already handled by call + to psxload above */ + break; + + + default: + /* Nothing needs to be done */ + + status = AE_OK; + break; + } + + break; + + default: + + status = AE_NOT_IMPLEMENTED; + break; + } + + + /* + * ACPI 2.0 support for 64-bit integers: + * Truncate numeric result value if we are executing from a 32-bit ACPI table + */ + acpi_aml_truncate_for32bit_table (result_obj, walk_state); + + /* + * Check if we just completed the evaluation of a + * conditional predicate + */ + + if ((walk_state->control_state) && + (walk_state->control_state->common.state == + CONTROL_PREDICATE_EXECUTING) && + (walk_state->control_state->control.predicate_op == op)) { + status = acpi_ds_get_predicate_value (walk_state, op, (u32) result_obj); + result_obj = NULL; + } + + +cleanup: + if (result_obj) { + /* Break to debugger to display result */ + + DEBUGGER_EXEC (acpi_db_display_result_object (result_obj, walk_state)); + + /* + * Delete the result op if and only if: + * Parent will not use the result -- such as any + * non-nested type2 op in a method (parent will be method) + */ + acpi_ds_delete_result_if_not_used (op, result_obj, walk_state); + } + + /* Always clear the object stack */ + + /* TBD: [Investigate] Clear stack of return value, + but don't delete it */ + walk_state->num_operands = 0; + + return (status); +} + + diff --git a/drivers/bus/acpi/dispatcher/dswload.c b/drivers/bus/acpi/dispatcher/dswload.c new file mode 100644 index 0000000..384ddd6 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dswload.c @@ -0,0 +1,679 @@ +/****************************************************************************** + * + * Module Name: dswload - Dispatcher namespace load callbacks + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dswload") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_load1_begin_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been reached in the + * walk; Arguments have not been evaluated yet. + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_load1_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + OBJECT_TYPE_INTERNAL data_type; + NATIVE_CHAR *path; + + + /* We are only interested in opcodes that have an associated name */ + + if (!acpi_ps_is_named_op (opcode)) { + *out_op = op; + return (AE_OK); + } + + + /* Check if this object has already been installed in the namespace */ + + if (op && op->node) { + *out_op = op; + return (AE_OK); + } + + path = acpi_ps_get_next_namestring (walk_state->parser_state); + + /* Map the raw opcode into an internal object type */ + + data_type = acpi_ds_map_named_opcode_to_data_type (opcode); + + + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that involve + * arguments to the opcode must be created as we go back up the parse tree later. + */ + status = acpi_ns_lookup (walk_state->scope_info, path, + data_type, IMODE_LOAD_PASS1, + NS_NO_UPSEARCH, walk_state, &(node)); + + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!op) { + /* Create a new op */ + + op = acpi_ps_alloc_op (opcode); + if (!op) { + return (AE_NO_MEMORY); + } + } + + /* Initialize */ + + ((ACPI_PARSE2_OBJECT *)op)->name = node->name; + + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->node = node; + + + acpi_ps_append_arg (acpi_ps_get_parent_scope (walk_state->parser_state), op); + + *out_op = op; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_load1_end_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been completed in the + * walk; Arguments have now been evaluated. + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_load1_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + OBJECT_TYPE_INTERNAL data_type; + + + /* We are only interested in opcodes that have an associated name */ + + if (!acpi_ps_is_named_op (op->opcode)) { + return (AE_OK); + } + + + /* Get the type to determine if we should pop the scope */ + + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + if (op->opcode == AML_NAME_OP) { + /* For Name opcode, check the argument */ + + if (op->value.arg) { + data_type = acpi_ds_map_opcode_to_data_type ( + (op->value.arg)->opcode, NULL); + ((ACPI_NAMESPACE_NODE *)op->node)->type = + (u8) data_type; + } + } + + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope (data_type)) { + + acpi_ds_scope_stack_pop (walk_state); + } + + return (AE_OK); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_load2_begin_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been reached in the + * walk; Arguments have not been evaluated yet. + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_load2_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + OBJECT_TYPE_INTERNAL data_type; + NATIVE_CHAR *buffer_ptr; + void *original = NULL; + + + /* We only care about Namespace opcodes here */ + + if (!acpi_ps_is_namespace_op (opcode) && + opcode != AML_NAMEPATH_OP) { + return (AE_OK); + } + + + /* Temp! same code as in psparse */ + + if (!acpi_ps_is_named_op (opcode)) { + return (AE_OK); + } + + if (op) { + /* + * Get the name we are going to enter or lookup in the namespace + */ + if (opcode == AML_NAMEPATH_OP) { + /* For Namepath op, get the path string */ + + buffer_ptr = op->value.string; + if (!buffer_ptr) { + /* No name, just exit */ + + return (AE_OK); + } + } + + else { + /* Get name from the op */ + + buffer_ptr = (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)op)->name; + } + } + + else { + buffer_ptr = acpi_ps_get_next_namestring (walk_state->parser_state); + } + + + /* Map the raw opcode into an internal object type */ + + data_type = acpi_ds_map_named_opcode_to_data_type (opcode); + + + if (opcode == AML_DEF_FIELD_OP || + opcode == AML_BANK_FIELD_OP || + opcode == AML_INDEX_FIELD_OP) { + node = NULL; + status = AE_OK; + } + + else if (opcode == AML_NAMEPATH_OP) { + /* + * The Name_path is an object reference to an existing object. Don't enter the + * name into the namespace, but look it up for use later + */ + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, + data_type, IMODE_EXECUTE, + NS_SEARCH_PARENT, walk_state, + &(node)); + } + + else { + if (op && op->node) { + original = op->node; + node = op->node; + + if (acpi_ns_opens_scope (data_type)) { + status = acpi_ds_scope_stack_push (node, + data_type, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + } + return (AE_OK); + } + + /* + * Enter the named type into the internal namespace. We enter the name + * as we go downward in the parse tree. Any necessary subobjects that involve + * arguments to the opcode must be created as we go back up the parse tree later. + */ + status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, + data_type, IMODE_EXECUTE, + NS_NO_UPSEARCH, walk_state, + &(node)); + } + + if (ACPI_SUCCESS (status)) { + if (!op) { + /* Create a new op */ + + op = acpi_ps_alloc_op (opcode); + if (!op) { + return (AE_NO_MEMORY); + } + + /* Initialize */ + + ((ACPI_PARSE2_OBJECT *)op)->name = node->name; + *out_op = op; + } + + + /* + * Put the Node in the "op" object that the parser uses, so we + * can get it again quickly when this scope is closed + */ + op->node = node; + + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_load2_end_op + * + * PARAMETERS: Walk_state - Current state of the parse tree walk + * Op - Op that has been just been completed in the + * walk; Arguments have now been evaluated. + * + * RETURN: Status + * + * DESCRIPTION: Ascending callback used during the loading of the namespace, + * both control methods and everything else. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_load2_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ + ACPI_STATUS status = AE_OK; + OBJECT_TYPE_INTERNAL data_type; + ACPI_NAMESPACE_NODE *node; + ACPI_PARSE_OBJECT *arg; + ACPI_NAMESPACE_NODE *new_node; + + + if (!acpi_ps_is_namespace_object_op (op->opcode)) { + return (AE_OK); + } + + if (op->opcode == AML_SCOPE_OP) { + if (((ACPI_PARSE2_OBJECT *)op)->name == -1) { + return (AE_OK); + } + } + + + data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); + + /* + * Get the Node/name from the earlier lookup + * (It was saved in the *op structure) + */ + node = op->node; + + /* + * Put the Node on the object stack (Contains the ACPI Name of + * this object) + */ + + walk_state->operands[0] = (void *) node; + walk_state->num_operands = 1; + + /* Pop the scope stack */ + + if (acpi_ns_opens_scope (data_type)) { + + acpi_ds_scope_stack_pop (walk_state); + } + + + /* + * Named operations are as follows: + * + * AML_SCOPE + * AML_DEVICE + * AML_THERMALZONE + * AML_METHOD + * AML_POWERRES + * AML_PROCESSOR + * AML_FIELD + * AML_INDEXFIELD + * AML_BANKFIELD + * AML_NAMEDFIELD + * AML_NAME + * AML_ALIAS + * AML_MUTEX + * AML_EVENT + * AML_OPREGION + * AML_CREATEFIELD + * AML_CREATEBITFIELD + * AML_CREATEBYTEFIELD + * AML_CREATEWORDFIELD + * AML_CREATEDWORDFIELD + * AML_METHODCALL + */ + + + /* Decode the opcode */ + + arg = op->value.arg; + + switch (op->opcode) { + + case AML_CREATE_FIELD_OP: + case AML_BIT_FIELD_OP: + case AML_BYTE_FIELD_OP: + case AML_WORD_FIELD_OP: + case AML_DWORD_FIELD_OP: + + /* + * Create the field object, but the field buffer and index must + * be evaluated later during the execution phase + */ + + /* Get the Name_string argument */ + + if (op->opcode == AML_CREATE_FIELD_OP) { + arg = acpi_ps_get_arg (op, 3); + } + else { + /* Create Bit/Byte/Word/Dword field */ + + arg = acpi_ps_get_arg (op, 2); + } + + /* + * Enter the Name_string into the namespace + */ + + status = acpi_ns_lookup (walk_state->scope_info, + arg->value.string, + INTERNAL_TYPE_DEF_ANY, + IMODE_LOAD_PASS1, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + walk_state, &(new_node)); + + if (ACPI_SUCCESS (status)) { + /* We could put the returned object (Node) on the object stack for later, but + * for now, we will put it in the "op" object that the parser uses, so we + * can get it again at the end of this scope + */ + op->node = new_node; + + /* + * If there is no object attached to the node, this node was just created and + * we need to create the field object. Otherwise, this was a lookup of an + * existing node and we don't want to create the field object again. + */ + if (!new_node->object) { + /* + * The Field definition is not fully parsed at this time. + * (We must save the address of the AML for the buffer and index operands) + */ + status = acpi_aml_exec_create_field (((ACPI_PARSE2_OBJECT *) op)->data, + ((ACPI_PARSE2_OBJECT *) op)->length, + new_node, walk_state); + } + } + + + break; + + + case AML_METHODCALL_OP: + + /* + * Lookup the method name and save the Node + */ + + status = acpi_ns_lookup (walk_state->scope_info, arg->value.string, + ACPI_TYPE_ANY, IMODE_LOAD_PASS2, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, + walk_state, &(new_node)); + + if (ACPI_SUCCESS (status)) { + +/* has name already been resolved by here ??*/ + + /* TBD: [Restructure] Make sure that what we found is indeed a method! */ + /* We didn't search for a method on purpose, to see if the name would resolve! */ + + /* We could put the returned object (Node) on the object stack for later, but + * for now, we will put it in the "op" object that the parser uses, so we + * can get it again at the end of this scope + */ + op->node = new_node; + } + + + break; + + + case AML_PROCESSOR_OP: + + /* Nothing to do other than enter object into namespace */ + + status = acpi_aml_exec_create_processor (op, (ACPI_HANDLE) node); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + break; + + + case AML_POWER_RES_OP: + + /* Nothing to do other than enter object into namespace */ + + status = acpi_aml_exec_create_power_resource (op, (ACPI_HANDLE) node); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + break; + + + case AML_THERMAL_ZONE_OP: + + /* Nothing to do other than enter object into namespace */ + + break; + + + case AML_DEF_FIELD_OP: + + arg = op->value.arg; + + status = acpi_ds_create_field (op, arg->node, walk_state); + break; + + + case AML_INDEX_FIELD_OP: + + arg = op->value.arg; + + status = acpi_ds_create_index_field (op, (ACPI_HANDLE) arg->node, + walk_state); + break; + + + case AML_BANK_FIELD_OP: + + arg = op->value.arg; + status = acpi_ds_create_bank_field (op, arg->node, walk_state); + break; + + + /* + * Method_op Pkg_length Names_string Method_flags Term_list + */ + case AML_METHOD_OP: + + if (!node->object) { + status = acpi_aml_exec_create_method (((ACPI_PARSE2_OBJECT *) op)->data, + ((ACPI_PARSE2_OBJECT *) op)->length, + arg->value.integer, (ACPI_HANDLE) node); + } + + break; + + + case AML_MUTEX_OP: + + status = acpi_ds_create_operands (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_create_mutex (walk_state); + break; + + + case AML_EVENT_OP: + + status = acpi_ds_create_operands (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_create_event (walk_state); + break; + + + case AML_REGION_OP: + + if (node->object) { + break; + } + + + /* + * The Op_region is not fully parsed at this time. Only valid argument is the Space_id. + * (We must save the address of the AML of the address and length operands) + */ + + status = acpi_aml_exec_create_region (((ACPI_PARSE2_OBJECT *) op)->data, + ((ACPI_PARSE2_OBJECT *) op)->length, + (ACPI_ADDRESS_SPACE_TYPE) arg->value.integer, + walk_state); + + break; + + + /* Namespace Modifier Opcodes */ + + case AML_ALIAS_OP: + + status = acpi_ds_create_operands (walk_state, arg); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_create_alias (walk_state); + break; + + + case AML_NAME_OP: + + /* + * Because of the execution pass through the non-control-method + * parts of the table, we can arrive here twice. Only init + * the named object node the first time through + */ + + if (!node->object) { + status = acpi_ds_create_node (walk_state, node, op); + } + + break; + + + case AML_NAMEPATH_OP: + + break; + + + default: + break; + } + + +cleanup: + + /* Remove the Node pushed at the very beginning */ + + acpi_ds_obj_stack_pop (1, walk_state); + return (status); +} + + diff --git a/drivers/bus/acpi/dispatcher/dswscope.c b/drivers/bus/acpi/dispatcher/dswscope.c new file mode 100644 index 0000000..c47ae36 --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dswscope.c @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * Module Name: dswscope - Scope stack manipulation + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dswscope") + + +#define STACK_POP(head) head + + +/**************************************************************************** + * + * FUNCTION: Acpi_ds_scope_stack_clear + * + * PARAMETERS: None + * + * DESCRIPTION: Pop (and free) everything on the scope stack except the + * root scope object (which remains at the stack top.) + * + ***************************************************************************/ + +void +acpi_ds_scope_stack_clear ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *scope_info; + + + while (walk_state->scope_info) { + /* Pop a scope off the stack */ + + scope_info = walk_state->scope_info; + walk_state->scope_info = scope_info->scope.next; + + acpi_cm_delete_generic_state (scope_info); + } +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ds_scope_stack_push + * + * PARAMETERS: *Node, - Name to be made current + * Type, - Type of frame being pushed + * + * DESCRIPTION: Push the current scope on the scope stack, and make the + * passed Node current. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ds_scope_stack_push ( + ACPI_NAMESPACE_NODE *node, + OBJECT_TYPE_INTERNAL type, + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *scope_info; + + + if (!node) { + /* invalid scope */ + + REPORT_ERROR (("Ds_scope_stack_push: null scope passed\n")); + return (AE_BAD_PARAMETER); + } + + /* Make sure object type is valid */ + + if (!acpi_aml_validate_object_type (type)) { + REPORT_WARNING (("Ds_scope_stack_push: type code out of range\n")); + } + + + /* Allocate a new scope object */ + + scope_info = acpi_cm_create_generic_state (); + if (!scope_info) { + return (AE_NO_MEMORY); + } + + /* Init new scope object */ + + scope_info->scope.node = node; + scope_info->common.value = (u16) type; + + /* Push new scope object onto stack */ + + acpi_cm_push_generic_state (&walk_state->scope_info, scope_info); + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ds_scope_stack_pop + * + * PARAMETERS: Type - The type of frame to be found + * + * DESCRIPTION: Pop the scope stack until a frame of the requested type + * is found. + * + * RETURN: Count of frames popped. If no frame of the requested type + * was found, the count is returned as a negative number and + * the scope stack is emptied (which sets the current scope + * to the root). If the scope stack was empty at entry, the + * function is a no-op and returns 0. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ds_scope_stack_pop ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *scope_info; + + + /* + * Pop scope info object off the stack. + */ + + scope_info = acpi_cm_pop_generic_state (&walk_state->scope_info); + if (!scope_info) { + return (AE_STACK_UNDERFLOW); + } + + acpi_cm_delete_generic_state (scope_info); + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/dispatcher/dswstate.c b/drivers/bus/acpi/dispatcher/dswstate.c new file mode 100644 index 0000000..b0e33da --- /dev/null +++ b/drivers/bus/acpi/dispatcher/dswstate.c @@ -0,0 +1,877 @@ +/****************************************************************************** + * + * Module Name: dswstate - Dispatcher parse tree walk management routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_DISPATCHER + MODULE_NAME ("dswstate") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_insert + * + * PARAMETERS: Object - Object to push + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto this walk's result stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_insert ( + void *object, + u32 index, + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + state = walk_state->results; + if (!state) { + return (AE_NOT_EXIST); + } + + if (index >= OBJ_NUM_OPERANDS) { + return (AE_BAD_PARAMETER); + } + + if (!object) { + return (AE_BAD_PARAMETER); + } + + state->results.obj_desc [index] = object; + state->results.num_results++; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_remove + * + * PARAMETERS: Object - Where to return the popped object + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In + * other words, this is a FIFO. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_remove ( + ACPI_OPERAND_OBJECT **object, + u32 index, + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + state = walk_state->results; + if (!state) { + return (AE_NOT_EXIST); + } + + + + /* Check for a valid result object */ + + if (!state->results.obj_desc [index]) { + return (AE_AML_NO_RETURN_VALUE); + } + + /* Remove the object */ + + state->results.num_results--; + + *object = state->results.obj_desc [index]; + state->results.obj_desc [index] = NULL; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_pop + * + * PARAMETERS: Object - Where to return the popped object + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In + * other words, this is a FIFO. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_pop ( + ACPI_OPERAND_OBJECT **object, + ACPI_WALK_STATE *walk_state) +{ + u32 index; + ACPI_GENERIC_STATE *state; + + + state = walk_state->results; + if (!state) { + return (AE_OK); + } + + + if (!state->results.num_results) { + return (AE_AML_NO_RETURN_VALUE); + } + + /* Remove top element */ + + state->results.num_results--; + + for (index = OBJ_NUM_OPERANDS; index; index--) { + /* Check for a valid result object */ + + if (state->results.obj_desc [index -1]) { + *object = state->results.obj_desc [index -1]; + state->results.obj_desc [index -1] = NULL; + + return (AE_OK); + } + } + + + return (AE_AML_NO_RETURN_VALUE); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_pop_from_bottom + * + * PARAMETERS: Object - Where to return the popped object + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In + * other words, this is a FIFO. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_pop_from_bottom ( + ACPI_OPERAND_OBJECT **object, + ACPI_WALK_STATE *walk_state) +{ + u32 index; + ACPI_GENERIC_STATE *state; + + + state = walk_state->results; + if (!state) { + return (AE_NOT_EXIST); + } + + + if (!state->results.num_results) { + return (AE_AML_NO_RETURN_VALUE); + } + + /* Remove Bottom element */ + + *object = state->results.obj_desc [0]; + + + /* Push entire stack down one element */ + + for (index = 0; index < state->results.num_results; index++) { + state->results.obj_desc [index] = state->results.obj_desc [index + 1]; + } + + state->results.num_results--; + + /* Check for a valid result object */ + + if (!*object) { + return (AE_AML_NO_RETURN_VALUE); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_push + * + * PARAMETERS: Object - Where to return the popped object + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto the current result stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_push ( + ACPI_OPERAND_OBJECT *object, + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + state = walk_state->results; + if (!state) { + return (AE_AML_INTERNAL); + } + + if (state->results.num_results == OBJ_NUM_OPERANDS) { + return (AE_STACK_OVERFLOW); + } + + if (!object) { + return (AE_BAD_PARAMETER); + } + + + state->results.obj_desc [state->results.num_results] = object; + state->results.num_results++; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_stack_push + * + * PARAMETERS: Object - Object to push + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_stack_push ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + state = acpi_cm_create_generic_state (); + if (!state) { + return (AE_NO_MEMORY); + } + + acpi_cm_push_generic_state (&walk_state->results, state); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_result_stack_pop + * + * PARAMETERS: Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_result_stack_pop ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + /* Check for stack underflow */ + + if (walk_state->results == NULL) { + return (AE_AML_NO_OPERAND); + } + + + state = acpi_cm_pop_generic_state (&walk_state->results); + + acpi_cm_delete_generic_state (state); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_delete_all + * + * PARAMETERS: Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Clear the object stack by deleting all objects that are on it. + * Should be used with great care, if at all! + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_delete_all ( + ACPI_WALK_STATE *walk_state) +{ + u32 i; + + + /* The stack size is configurable, but fixed */ + + for (i = 0; i < OBJ_NUM_OPERANDS; i++) { + if (walk_state->operands[i]) { + acpi_cm_remove_reference (walk_state->operands[i]); + walk_state->operands[i] = NULL; + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_push + * + * PARAMETERS: Object - Object to push + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Push an object onto this walk's object/operand stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_push ( + void *object, + ACPI_WALK_STATE *walk_state) +{ + + + /* Check for stack overflow */ + + if (walk_state->num_operands >= OBJ_NUM_OPERANDS) { + return (AE_STACK_OVERFLOW); + } + + /* Put the object onto the stack */ + + walk_state->operands [walk_state->num_operands] = object; + walk_state->num_operands++; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_pop_object + * + * PARAMETERS: Pop_count - Number of objects/entries to pop + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * deleted by this routine. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_pop_object ( + ACPI_OPERAND_OBJECT **object, + ACPI_WALK_STATE *walk_state) +{ + + + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + return (AE_AML_NO_OPERAND); + } + + + /* Pop the stack */ + + walk_state->num_operands--; + + /* Check for a valid operand */ + + if (!walk_state->operands [walk_state->num_operands]) { + return (AE_AML_NO_OPERAND); + } + + /* Get operand and set stack entry to null */ + + *object = walk_state->operands [walk_state->num_operands]; + walk_state->operands [walk_state->num_operands] = NULL; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_pop + * + * PARAMETERS: Pop_count - Number of objects/entries to pop + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT + * deleted by this routine. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_pop ( + u32 pop_count, + ACPI_WALK_STATE *walk_state) +{ + u32 i; + + + for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + return (AE_STACK_UNDERFLOW); + } + + /* Just set the stack entry to null */ + + walk_state->num_operands--; + walk_state->operands [walk_state->num_operands] = NULL; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_pop_and_delete + * + * PARAMETERS: Pop_count - Number of objects/entries to pop + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Pop this walk's object stack and delete each object that is + * popped off. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ds_obj_stack_pop_and_delete ( + u32 pop_count, + ACPI_WALK_STATE *walk_state) +{ + u32 i; + ACPI_OPERAND_OBJECT *obj_desc; + + + for (i = 0; i < pop_count; i++) { + /* Check for stack underflow */ + + if (walk_state->num_operands == 0) { + return (AE_STACK_UNDERFLOW); + } + + /* Pop the stack and delete an object if present in this stack entry */ + + walk_state->num_operands--; + obj_desc = walk_state->operands [walk_state->num_operands]; + if (obj_desc) { + acpi_cm_remove_reference (walk_state->operands [walk_state->num_operands]); + walk_state->operands [walk_state->num_operands] = NULL; + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_obj_stack_get_value + * + * PARAMETERS: Index - Stack index whose value is desired. Based + * on the top of the stack (index=0 == top) + * Walk_state - Current Walk state + * + * RETURN: Status + * + * DESCRIPTION: Retrieve an object from this walk's object stack. Index must + * be within the range of the current stack pointer. + * + ******************************************************************************/ + +void * +acpi_ds_obj_stack_get_value ( + u32 index, + ACPI_WALK_STATE *walk_state) +{ + + + /* Can't do it if the stack is empty */ + + if (walk_state->num_operands == 0) { + return (NULL); + } + + /* or if the index is past the top of the stack */ + + if (index > (walk_state->num_operands - (u32) 1)) { + return (NULL); + } + + + return (walk_state->operands[(NATIVE_UINT)(walk_state->num_operands - 1) - + index]); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_get_current_walk_state + * + * PARAMETERS: Walk_list - Get current active state for this walk list + * + * RETURN: Pointer to the current walk state + * + * DESCRIPTION: Get the walk state that is at the head of the list (the "current" + * walk state. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +acpi_ds_get_current_walk_state ( + ACPI_WALK_LIST *walk_list) + +{ + + if (!walk_list) { + return (NULL); + } + + return (walk_list->walk_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_push_walk_state + * + * PARAMETERS: Walk_state - State to push + * Walk_list - The list that owns the walk stack + * + * RETURN: None + * + * DESCRIPTION: Place the Walk_state at the head of the state list. + * + ******************************************************************************/ + +static void +acpi_ds_push_walk_state ( + ACPI_WALK_STATE *walk_state, + ACPI_WALK_LIST *walk_list) +{ + + + walk_state->next = walk_list->walk_state; + walk_list->walk_state = walk_state; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_pop_walk_state + * + * PARAMETERS: Walk_list - The list that owns the walk stack + * + * RETURN: A Walk_state object popped from the stack + * + * DESCRIPTION: Remove and return the walkstate object that is at the head of + * the walk stack for the given walk list. NULL indicates that + * the list is empty. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +acpi_ds_pop_walk_state ( + ACPI_WALK_LIST *walk_list) +{ + ACPI_WALK_STATE *walk_state; + + + walk_state = walk_list->walk_state; + + if (walk_state) { + /* Next walk state becomes the current walk state */ + + walk_list->walk_state = walk_state->next; + + /* + * Don't clear the NEXT field, this serves as an indicator + * that there is a parent WALK STATE + * Walk_state->Next = NULL; + */ + } + + return (walk_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_create_walk_state + * + * PARAMETERS: Origin - Starting point for this walk + * Walk_list - Owning walk list + * + * RETURN: Pointer to the new walk state. + * + * DESCRIPTION: Allocate and initialize a new walk state. The current walk state + * is set to this new state. + * + ******************************************************************************/ + +ACPI_WALK_STATE * +acpi_ds_create_walk_state ( + ACPI_OWNER_ID owner_id, + ACPI_PARSE_OBJECT *origin, + ACPI_OPERAND_OBJECT *mth_desc, + ACPI_WALK_LIST *walk_list) +{ + ACPI_WALK_STATE *walk_state; + ACPI_STATUS status; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_walk_state_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_walk_state_cache) { + /* There is an object available, use it */ + + walk_state = acpi_gbl_walk_state_cache; + acpi_gbl_walk_state_cache = walk_state->next; + + acpi_gbl_walk_state_cache_hits++; + acpi_gbl_walk_state_cache_depth--; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* The cache is empty, create a new object */ + + /* Avoid deadlock with Acpi_cm_callocate */ + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + walk_state = acpi_cm_callocate (sizeof (ACPI_WALK_STATE)); + if (!walk_state) { + return (NULL); + } + } + + walk_state->data_type = ACPI_DESC_TYPE_WALK; + walk_state->owner_id = owner_id; + walk_state->origin = origin; + walk_state->method_desc = mth_desc; + walk_state->walk_list = walk_list; + + /* Init the method args/local */ + +#ifndef _ACPI_ASL_COMPILER + acpi_ds_method_data_init (walk_state); +#endif + + /* Create an initial result stack entry */ + + status = acpi_ds_result_stack_push (walk_state); + if (ACPI_FAILURE (status)) { + return (NULL); + } + + + /* Put the new state at the head of the walk list */ + + acpi_ds_push_walk_state (walk_state, walk_list); + + return (walk_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ds_delete_walk_state + * + * PARAMETERS: Walk_state - State to delete + * + * RETURN: Status + * + * DESCRIPTION: Delete a walk state including all internal data structures + * + ******************************************************************************/ + +void +acpi_ds_delete_walk_state ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_GENERIC_STATE *state; + + + if (!walk_state) { + return; + } + + if (walk_state->data_type != ACPI_DESC_TYPE_WALK) { + return; + } + + + /* Always must free any linked control states */ + + while (walk_state->control_state) { + state = walk_state->control_state; + walk_state->control_state = state->common.next; + + acpi_cm_delete_generic_state (state); + } + + /* Always must free any linked parse states */ + + while (walk_state->scope_info) { + state = walk_state->scope_info; + walk_state->scope_info = state->common.next; + + acpi_cm_delete_generic_state (state); + } + + /* Always must free any stacked result states */ + + while (walk_state->results) { + state = walk_state->results; + walk_state->results = state->common.next; + + acpi_cm_delete_generic_state (state); + } + + + /* If walk cache is full, just free this wallkstate object */ + + if (acpi_gbl_walk_state_cache_depth >= MAX_WALK_CACHE_DEPTH) { + acpi_cm_free (walk_state); + } + + /* Otherwise put this object back into the cache */ + + else { + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the state */ + + MEMSET (walk_state, 0, sizeof (ACPI_WALK_STATE)); + walk_state->data_type = ACPI_DESC_TYPE_WALK; + + /* Put the object at the head of the global cache list */ + + walk_state->next = acpi_gbl_walk_state_cache; + acpi_gbl_walk_state_cache = walk_state; + acpi_gbl_walk_state_cache_depth++; + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ds_delete_walk_state_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_ds_delete_walk_state_cache ( + void) +{ + ACPI_WALK_STATE *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_walk_state_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_walk_state_cache->next; + acpi_cm_free (acpi_gbl_walk_state_cache); + acpi_gbl_walk_state_cache = next; + acpi_gbl_walk_state_cache_depth--; + } + + return; +} + + diff --git a/drivers/bus/acpi/events/.cvsignore b/drivers/bus/acpi/events/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/events/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/events/evevent.c b/drivers/bus/acpi/events/evevent.c new file mode 100644 index 0000000..67a2103 --- /dev/null +++ b/drivers/bus/acpi/events/evevent.c @@ -0,0 +1,769 @@ +/****************************************************************************** + * + * Module Name: evevent - Fixed and General Purpose Acpi_event + * handling and dispatch + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "achware.h" +#include "acevents.h" +#include "acnamesp.h" +#include "accommon.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evevent") + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly + * configured, disables SCI event sources, installs the SCI + * handler + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_initialize ( + void) +{ + ACPI_STATUS status; + + + /* Make sure we have ACPI tables */ + + if (!acpi_gbl_DSDT) { + return (AE_NO_ACPI_TABLES); + } + + + /* Make sure the BIOS supports ACPI mode */ + + if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { + return (AE_ERROR); + } + + + acpi_gbl_original_mode = acpi_hw_get_mode(); + + /* + * Initialize the Fixed and General Purpose Acpi_events prior. This is + * done prior to enabling SCIs to prevent interrupts from occuring + * before handers are installed. + */ + + status = acpi_ev_fixed_event_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_ev_gpe_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the SCI handler */ + + status = acpi_ev_install_sci_handler (); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ + + status = acpi_ev_init_gpe_control_methods (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the handler for the Global Lock */ + + status = acpi_ev_init_global_lock_handler (); + if (ACPI_FAILURE (status)) { + return (status); + } + + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_fixed_event_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the Fixed Acpi_event data structures + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_fixed_event_initialize(void) +{ + int i = 0; + + /* Initialize the structure that keeps track of fixed event handlers */ + + for (i = 0; i < NUM_FIXED_EVENTS; i++) { + acpi_gbl_fixed_event_handlers[i].handler = NULL; + acpi_gbl_fixed_event_handlers[i].context = NULL; + } + + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0); + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0); + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0); + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0); + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_fixed_event_detect + * + * PARAMETERS: None + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Checks the PM status register for fixed events + * + ******************************************************************************/ + +u32 +acpi_ev_fixed_event_detect(void) +{ + u32 int_status = INTERRUPT_NOT_HANDLED; + u32 status_register; + u32 enable_register; + + /* + * Read the fixed feature status and enable registers, as all the cases + * depend on their values. + */ + + status_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS); + enable_register = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN); + + + /* power management timer roll over */ + + if ((status_register & ACPI_STATUS_PMTIMER) && + (enable_register & ACPI_ENABLE_PMTIMER)) { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_PMTIMER); + } + + /* global event (BIOS want's the global lock) */ + + if ((status_register & ACPI_STATUS_GLOBAL) && + (enable_register & ACPI_ENABLE_GLOBAL)) { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_GLOBAL); + } + + /* power button event */ + + if ((status_register & ACPI_STATUS_POWER_BUTTON) && + (enable_register & ACPI_ENABLE_POWER_BUTTON)) { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_POWER_BUTTON); + } + + /* sleep button event */ + + if ((status_register & ACPI_STATUS_SLEEP_BUTTON) && + (enable_register & ACPI_ENABLE_SLEEP_BUTTON)) { + int_status |= acpi_ev_fixed_event_dispatch (ACPI_EVENT_SLEEP_BUTTON); + } + + return (int_status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_fixed_event_dispatch + * + * PARAMETERS: Event - Event type + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Clears the status bit for the requested event, calls the + * handler that previously registered for the event. + * + ******************************************************************************/ + +u32 +acpi_ev_fixed_event_dispatch ( + u32 event) +{ + u32 register_id; + + /* Clear the status bit */ + + switch (event) { + case ACPI_EVENT_PMTIMER: + register_id = TMR_STS; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_STS; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_STS; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_STS; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_STS; + break; + + default: + return 0; + break; + } + + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, register_id, 1); + + /* + * Make sure we've got a handler. If not, report an error. + * The event is disabled to prevent further interrupts. + */ + if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { + register_id = (PM1_EN | REGISTER_BIT_ID(register_id)); + + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, + register_id, 0); + + REPORT_ERROR ( + ("Ev_gpe_dispatch: No installed handler for fixed event [%08X]\n", + event)); + + return (INTERRUPT_NOT_HANDLED); + } + + /* Invoke the handler */ + + return ((acpi_gbl_fixed_event_handlers[event].handler)( + acpi_gbl_fixed_event_handlers[event].context)); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the GPE data structures + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_gpe_initialize (void) +{ + u32 i; + u32 j; + u32 register_index; + u32 gpe_number; + u16 gpe0register_count; + u16 gpe1_register_count; + + + /* + * Set up various GPE counts + * + * You may ask,why are the GPE register block lengths divided by 2? + * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event + * Registers, we have, + * + * "Each register block contains two registers of equal length + * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the + * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN + * The length of the GPE1_STS and GPE1_EN registers is equal to + * half the GPE1_LEN. If a generic register block is not supported + * then its respective block pointer and block length values in the + * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need + * to be the same size." + */ + + gpe0register_count = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len); + gpe1_register_count = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len); + acpi_gbl_gpe_register_count = gpe0register_count + gpe1_register_count; + + if (!acpi_gbl_gpe_register_count) { + REPORT_WARNING (("Zero GPEs are defined in the FADT\n")); + return (AE_OK); + } + + /* + * Allocate the Gpe information block + */ + + acpi_gbl_gpe_registers = acpi_cm_callocate (acpi_gbl_gpe_register_count * + sizeof (ACPI_GPE_REGISTERS)); + if (!acpi_gbl_gpe_registers) { + return (AE_NO_MEMORY); + } + + /* + * Allocate the Gpe dispatch handler block + * There are eight distinct GP events per register. + * Initialization to zeros is sufficient + */ + + acpi_gbl_gpe_info = acpi_cm_callocate (MUL_8 (acpi_gbl_gpe_register_count) * + sizeof (ACPI_GPE_LEVEL_INFO)); + if (!acpi_gbl_gpe_info) { + acpi_cm_free (acpi_gbl_gpe_registers); + return (AE_NO_MEMORY); + } + + /* Set the Gpe validation table to GPE_INVALID */ + + MEMSET (acpi_gbl_gpe_valid, (int) ACPI_GPE_INVALID, NUM_GPE); + + /* + * Initialize the Gpe information and validation blocks. A goal of these + * blocks is to hide the fact that there are two separate GPE register sets + * In a given block, the status registers occupy the first half, and + * the enable registers occupy the second half. + */ + + /* GPE Block 0 */ + + register_index = 0; + + for (i = 0; i < gpe0register_count; i++) { + acpi_gbl_gpe_registers[register_index].status_addr = + (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i); + + acpi_gbl_gpe_registers[register_index].enable_addr = + (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + i + gpe0register_count); + + acpi_gbl_gpe_registers[register_index].gpe_base = (u8) MUL_8 (i); + + for (j = 0; j < 8; j++) { + gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; + acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; + } + + /* + * Clear the status/enable registers. Note that status registers + * are cleared by writing a '1', while enable registers are cleared + * by writing a '0'. + */ + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF); + + register_index++; + } + + /* GPE Block 1 */ + + for (i = 0; i < gpe1_register_count; i++) { + acpi_gbl_gpe_registers[register_index].status_addr = + (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i); + + acpi_gbl_gpe_registers[register_index].enable_addr = + (u16) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + i + gpe1_register_count); + + acpi_gbl_gpe_registers[register_index].gpe_base = + (u8) (acpi_gbl_FADT->gpe1_base + MUL_8 (i)); + + for (j = 0; j < 8; j++) { + gpe_number = acpi_gbl_gpe_registers[register_index].gpe_base + j; + acpi_gbl_gpe_valid[gpe_number] = (u8) register_index; + } + + /* + * Clear the status/enable registers. Note that status registers + * are cleared by writing a '1', while enable registers are cleared + * by writing a '0'. + */ + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, 0x00); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, 0xFF); + + register_index++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_save_method_info + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Called from Acpi_walk_namespace. Expects each object to be a + * control method under the _GPE portion of the namespace. + * Extract the name and GPE type from the object, saving this + * information for quick lookup during GPE dispatch + * + * The name of each GPE control method is of the form: + * "_Lnn" or "_Enn" + * Where: + * L - means that the GPE is level triggered + * E - means that the GPE is edge triggered + * nn - is the GPE number + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ev_save_method_info ( + ACPI_HANDLE obj_handle, + u32 level, + void *obj_desc, + void **return_value) +{ + u32 gpe_number; + NATIVE_CHAR name[ACPI_NAME_SIZE + 1]; + u8 type; + + + /* Extract the name from the object and convert to a string */ + + MOVE_UNALIGNED32_TO_32 (name, &((ACPI_NAMESPACE_NODE *) obj_handle)->name); + name[ACPI_NAME_SIZE] = 0; + + /* + * Edge/Level determination is based on the 2nd s8 of the method name + */ + if (name[1] == 'L') { + type = ACPI_EVENT_LEVEL_TRIGGERED; + } + else if (name[1] == 'E') { + type = ACPI_EVENT_EDGE_TRIGGERED; + } + else { + /* Unknown method type, just ignore it! */ + + return (AE_OK); + } + + /* Convert the last two characters of the name to the Gpe Number */ + + gpe_number = STRTOUL (&name[2], NULL, 16); + if (gpe_number == ACPI_UINT32_MAX) { + /* Conversion failed; invalid method, just ignore it */ + + return (AE_OK); + } + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + /* Not valid, all we can do here is ignore it */ + + return (AE_OK); + } + + /* + * Now we can add this information to the Gpe_info block + * for use during dispatch of this GPE. + */ + + acpi_gbl_gpe_info [gpe_number].type = type; + acpi_gbl_gpe_info [gpe_number].method_handle = obj_handle; + + + /* + * Enable the GPE (SCIs should be disabled at this point) + */ + + acpi_hw_enable_gpe (gpe_number); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_init_gpe_control_methods + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Obtain the control methods associated with the GPEs. + * + * NOTE: Must be called AFTER namespace initialization! + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_init_gpe_control_methods (void) +{ + ACPI_STATUS status; + + + /* Get a permanent handle to the _GPE object */ + + status = acpi_get_handle (NULL, "\\_GPE", &acpi_gbl_gpe_obj_handle); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Traverse the namespace under \_GPE to find all methods there */ + + status = acpi_walk_namespace (ACPI_TYPE_METHOD, acpi_gbl_gpe_obj_handle, + ACPI_UINT32_MAX, acpi_ev_save_method_info, + NULL, NULL); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_detect + * + * PARAMETERS: None + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Detect if any GP events have occurred + * + ******************************************************************************/ + +u32 +acpi_ev_gpe_detect (void) +{ + u32 int_status = INTERRUPT_NOT_HANDLED; + u32 i; + u32 j; + u8 enabled_status_byte; + u8 bit_mask; + + + /* + * Read all of the 8-bit GPE status and enable registers + * in both of the register blocks, saving all of it. + * Find all currently active GP events. + */ + + for (i = 0; i < acpi_gbl_gpe_register_count; i++) { + acpi_gbl_gpe_registers[i].status = + acpi_os_in8 (acpi_gbl_gpe_registers[i].status_addr); + + acpi_gbl_gpe_registers[i].enable = + acpi_os_in8 (acpi_gbl_gpe_registers[i].enable_addr); + + /* First check if there is anything active at all in this register */ + + enabled_status_byte = (u8) (acpi_gbl_gpe_registers[i].status & + acpi_gbl_gpe_registers[i].enable); + + if (!enabled_status_byte) { + /* No active GPEs in this register, move on */ + + continue; + } + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0, bit_mask = 1; j < 8; j++, bit_mask <<= 1) { + /* Examine one GPE bit */ + + if (enabled_status_byte & bit_mask) { + /* + * Found an active GPE. Dispatch the event to a handler + * or method. + */ + int_status |= + acpi_ev_gpe_dispatch (acpi_gbl_gpe_registers[i].gpe_base + j); + } + } + } + + return (int_status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_asynch_execute_gpe_method + * + * PARAMETERS: Gpe_number - The 0-based Gpe number + * + * RETURN: None + * + * DESCRIPTION: Perform the actual execution of a GPE control method. This + * function is called from an invocation of Acpi_os_queue_for_execution + * (and therefore does NOT execute at interrupt level) so that + * the control method itself is not executed in the context of + * the SCI interrupt handler. + * + ******************************************************************************/ + +static void +acpi_ev_asynch_execute_gpe_method ( + void *context) +{ + u32 gpe_number = (u32) context; + ACPI_GPE_LEVEL_INFO gpe_info; + + + /* + * Take a snapshot of the GPE info for this level + */ + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + gpe_info = acpi_gbl_gpe_info [gpe_number]; + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + + /* + * Method Handler (_Lxx, _Exx): + * ---------------------------- + * Evaluate the _Lxx/_Exx control method that corresponds to this GPE. + */ + if (gpe_info.method_handle) { + acpi_ns_evaluate_by_handle (gpe_info.method_handle, NULL, NULL); + } + + /* + * Level-Triggered? + * ---------------- + * If level-triggered we clear the GPE status bit after handling the event. + */ + if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { + acpi_hw_clear_gpe (gpe_number); + } + + /* + * Enable the GPE. + */ + acpi_hw_enable_gpe (gpe_number); + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_gpe_dispatch + * + * PARAMETERS: Gpe_number - The 0-based Gpe number + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Handle and dispatch a General Purpose Acpi_event. + * Clears the status bit for the requested event. + * + * TBD: [Investigate] is this still valid or necessary: + * The Gpe handler differs from the fixed events in that it clears the enable + * bit rather than the status bit to clear the interrupt. This allows + * software outside of interrupt context to determine what caused the SCI and + * dispatch the correct AML. + * + ******************************************************************************/ + +u32 +acpi_ev_gpe_dispatch ( + u32 gpe_number) +{ + ACPI_GPE_LEVEL_INFO gpe_info; + + /* + * Valid GPE number? + */ + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + return (INTERRUPT_NOT_HANDLED); + } + + /* + * Disable the GPE. + */ + acpi_hw_disable_gpe (gpe_number); + + gpe_info = acpi_gbl_gpe_info [gpe_number]; + + /* + * Edge-Triggered? + * --------------- + * If edge-triggered, clear the GPE status bit now. Note that + * level-triggered events are cleared after the GPE is serviced. + */ + if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) { + acpi_hw_clear_gpe (gpe_number); + } + /* + * Function Handler (e.g. EC)? + */ + if (gpe_info.handler) { + /* Invoke function handler (at interrupt level). */ + gpe_info.handler (gpe_info.context); + + /* Level-Triggered? */ + if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { + acpi_hw_clear_gpe (gpe_number); + } + + /* Enable GPE */ + acpi_hw_enable_gpe (gpe_number); + } + /* + * Method Handler (e.g. _Exx/_Lxx)? + */ + else if (gpe_info.method_handle) { + if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE, + acpi_ev_asynch_execute_gpe_method, (void*)(NATIVE_UINT)gpe_number))) { + /* + * Shoudn't occur, but if it does report an error. Note that + * the GPE will remain disabled until the ACPI Core Subsystem + * is restarted, or the handler is removed/reinstalled. + */ + REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number)); + } + } + /* + * No Handler? Report an error and leave the GPE disabled. + */ + else { + REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number)); + + /* Level-Triggered? */ + if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) { + acpi_hw_clear_gpe (gpe_number); + } + } + + return (INTERRUPT_HANDLED); +} diff --git a/drivers/bus/acpi/events/evmisc.c b/drivers/bus/acpi/events/evmisc.c new file mode 100644 index 0000000..01bcd35 --- /dev/null +++ b/drivers/bus/acpi/events/evmisc.c @@ -0,0 +1,443 @@ +/****************************************************************************** + * + * Module Name: evmisc - ACPI device notification handler dispatch + * and ACPI Global Lock support + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "achware.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evmisc") + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_queue_notify_request + * + * PARAMETERS: + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_queue_notify_request ( + ACPI_NAMESPACE_NODE *node, + u32 notify_value) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *handler_obj = NULL; + ACPI_GENERIC_STATE *notify_info; + ACPI_STATUS status = AE_OK; + + + /* + * For value 1 (Ejection Request), some device method may need to be run. + * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run. + * For value 0x80 (Status Change) on the power button or sleep button, + * initiate soft-off or sleep operation? + */ + + switch (notify_value) { + case 0: + break; + + case 1: + break; + + case 2: + break; + + case 0x80: + break; + + default: + break; + } + + + /* + * Get the notify object attached to the device Node + */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + if (obj_desc) { + + /* We have the notify object, Get the right handler */ + + switch (node->type) { + case ACPI_TYPE_DEVICE: + if (notify_value <= MAX_SYS_NOTIFY) { + handler_obj = obj_desc->device.sys_handler; + } + else { + handler_obj = obj_desc->device.drv_handler; + } + break; + + case ACPI_TYPE_THERMAL: + if (notify_value <= MAX_SYS_NOTIFY) { + handler_obj = obj_desc->thermal_zone.sys_handler; + } + else { + handler_obj = obj_desc->thermal_zone.drv_handler; + } + break; + } + } + + + /* If there is any handler to run, schedule the dispatcher */ + + if ((acpi_gbl_sys_notify.handler && (notify_value <= MAX_SYS_NOTIFY)) || + (acpi_gbl_drv_notify.handler && (notify_value > MAX_SYS_NOTIFY)) || + handler_obj) { + + notify_info = acpi_cm_create_generic_state (); + if (!notify_info) { + return (AE_NO_MEMORY); + } + + notify_info->notify.node = node; + notify_info->notify.value = (u16) notify_value; + notify_info->notify.handler_obj = handler_obj; + + status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, + acpi_ev_notify_dispatch, notify_info); + if (ACPI_FAILURE (status)) { + acpi_cm_delete_generic_state (notify_info); + } + } + + if (!handler_obj) { + /* There is no per-device notify handler for this device */ + + } + + + return (status); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_notify_dispatch + * + * PARAMETERS: + * + * RETURN: None. + * + * DESCRIPTION: Dispatch a device notification event to a previously + * installed handler. + * + *************************************************************************/ + +void +acpi_ev_notify_dispatch ( + void *context) +{ + ACPI_GENERIC_STATE *notify_info = (ACPI_GENERIC_STATE *) context; + NOTIFY_HANDLER global_handler = NULL; + void *global_context = NULL; + ACPI_OPERAND_OBJECT *handler_obj; + + + /* + * We will invoke a global notify handler if installed. + * This is done _before_ we invoke the per-device handler attached to the device. + */ + + if (notify_info->notify.value <= MAX_SYS_NOTIFY) { + /* Global system notification handler */ + + if (acpi_gbl_sys_notify.handler) { + global_handler = acpi_gbl_sys_notify.handler; + global_context = acpi_gbl_sys_notify.context; + } + } + + else { + /* Global driver notification handler */ + + if (acpi_gbl_drv_notify.handler) { + global_handler = acpi_gbl_drv_notify.handler; + global_context = acpi_gbl_drv_notify.context; + } + } + + + /* Invoke the system handler first, if present */ + + if (global_handler) { + global_handler (notify_info->notify.node, notify_info->notify.value, global_context); + } + + /* Now invoke the per-device handler, if present */ + + handler_obj = notify_info->notify.handler_obj; + if (handler_obj) { + handler_obj->notify_handler.handler (notify_info->notify.node, notify_info->notify.value, + handler_obj->notify_handler.context); + } + + + /* All done with the info object */ + + acpi_cm_delete_generic_state (notify_info); +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_global_lock_thread + * + * RETURN: None + * + * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the + * Global Lock. Simply signal all threads that are waiting + * for the lock. + * + **************************************************************************/ + +static void +acpi_ev_global_lock_thread ( + void *context) +{ + + /* Signal threads that are waiting for the lock */ + + if (acpi_gbl_global_lock_thread_count) { + /* Send sufficient units to the semaphore */ + + acpi_os_signal_semaphore (acpi_gbl_global_lock_semaphore, + acpi_gbl_global_lock_thread_count); + } +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_global_lock_handler + * + * RETURN: Status + * + * DESCRIPTION: Invoked directly from the SCI handler when a global lock + * release interrupt occurs. Grab the global lock and queue + * the global lock thread for execution + * + **************************************************************************/ + +static u32 +acpi_ev_global_lock_handler ( + void *context) +{ + u8 acquired = FALSE; + void *global_lock; + + + /* + * Attempt to get the lock + * If we don't get it now, it will be marked pending and we will + * take another interrupt when it becomes free. + */ + + global_lock = acpi_gbl_FACS->global_lock; + ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired); + if (acquired) { + /* Got the lock, now wake all threads waiting for it */ + + acpi_gbl_global_lock_acquired = TRUE; + + /* Run the Global Lock thread which will signal all waiting threads */ + + acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_global_lock_thread, + context); + } + + return (INTERRUPT_HANDLED); +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_init_global_lock_handler + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for the global lock release event + * + **************************************************************************/ + +ACPI_STATUS +acpi_ev_init_global_lock_handler (void) +{ + ACPI_STATUS status; + + + acpi_gbl_global_lock_present = TRUE; + status = acpi_install_fixed_event_handler (ACPI_EVENT_GLOBAL, + acpi_ev_global_lock_handler, NULL); + + /* + * If the global lock does not exist on this platform, the attempt + * to enable GBL_STS will fail (the GBL_EN bit will not stick) + * Map to AE_OK, but mark global lock as not present. + * Any attempt to actually use the global lock will be flagged + * with an error. + */ + if (status == AE_NO_HARDWARE_RESPONSE) { + acpi_gbl_global_lock_present = FALSE; + status = AE_OK; + } + + return (status); +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_acquire_global_lock + * + * RETURN: Status + * + * DESCRIPTION: Attempt to gain ownership of the Global Lock. + * + **************************************************************************/ + +ACPI_STATUS +acpi_ev_acquire_global_lock(void) +{ + ACPI_STATUS status = AE_OK; + u8 acquired = FALSE; + void *global_lock; + + + /* Make sure that we actually have a global lock */ + + if (!acpi_gbl_global_lock_present) { + return (AE_NO_GLOBAL_LOCK); + } + + /* One more thread wants the global lock */ + + acpi_gbl_global_lock_thread_count++; + + + /* If we (OS side) have the hardware lock already, we are done */ + + if (acpi_gbl_global_lock_acquired) { + return (AE_OK); + } + + /* Only if the FACS is valid */ + + if (!acpi_gbl_FACS) { + return (AE_OK); + } + + + /* We must acquire the actual hardware lock */ + + global_lock = acpi_gbl_FACS->global_lock; + ACPI_ACQUIRE_GLOBAL_LOCK (global_lock, acquired); + if (acquired) { + /* We got the lock */ + + acpi_gbl_global_lock_acquired = TRUE; + + return (AE_OK); + } + + + /* + * Did not get the lock. The pending bit was set above, and we must now + * wait until we get the global lock released interrupt. + */ + + /* + * Acquire the global lock semaphore first. + * Since this wait will block, we must release the interpreter + */ + + status = acpi_aml_system_wait_semaphore (acpi_gbl_global_lock_semaphore, + ACPI_UINT32_MAX); + + return (status); +} + + +/*************************************************************************** + * + * FUNCTION: Acpi_ev_release_global_lock + * + * DESCRIPTION: Releases ownership of the Global Lock. + * + **************************************************************************/ + +void +acpi_ev_release_global_lock (void) +{ + u8 pending = FALSE; + void *global_lock; + + + if (!acpi_gbl_global_lock_thread_count) { + REPORT_WARNING(("Global Lock has not be acquired, cannot release\n")); + return; + } + + /* One fewer thread has the global lock */ + + acpi_gbl_global_lock_thread_count--; + + /* Have all threads released the lock? */ + + if (!acpi_gbl_global_lock_thread_count) { + /* + * No more threads holding lock, we can do the actual hardware + * release + */ + + global_lock = acpi_gbl_FACS->global_lock; + ACPI_RELEASE_GLOBAL_LOCK (global_lock, pending); + acpi_gbl_global_lock_acquired = FALSE; + + /* + * If the pending bit was set, we must write GBL_RLS to the control + * register + */ + if (pending) { + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, + GBL_RLS, 1); + } + } + + return; +} diff --git a/drivers/bus/acpi/events/evregion.c b/drivers/bus/acpi/events/evregion.c new file mode 100644 index 0000000..b1bf90a --- /dev/null +++ b/drivers/bus/acpi/events/evregion.c @@ -0,0 +1,606 @@ +/****************************************************************************** + * + * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evregion") + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_install_default_address_space_handlers + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: Installs the core subsystem address space handlers. + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_install_default_address_space_handlers ( + void) +{ + ACPI_STATUS status; + + + /* + * All address spaces (PCI Config, EC, SMBus) are scope dependent + * and registration must occur for a specific device. In the case + * system memory and IO address spaces there is currently no device + * associated with the address space. For these we use the root. + * We install the default PCI config space handler at the root so + * that this space is immediately available even though the we have + * not enumerated all the PCI Root Buses yet. This is to conform + * to the ACPI specification which states that the PCI config + * space must be always available -- even though we are nowhere + * near ready to find the PCI root buses at this point. + * + * NOTE: We ignore AE_EXIST because this means that a handler has + * already been installed (via Acpi_install_address_space_handler) + */ + + status = acpi_install_address_space_handler (acpi_gbl_root_node, + ADDRESS_SPACE_SYSTEM_MEMORY, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) { + return (status); + } + + status = acpi_install_address_space_handler (acpi_gbl_root_node, + ADDRESS_SPACE_SYSTEM_IO, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) { + return (status); + } + + status = acpi_install_address_space_handler (acpi_gbl_root_node, + ADDRESS_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) { + return (status); + } + + + return (AE_OK); +} + + +/* TBD: [Restructure] Move elsewhere */ + +/************************************************************************** + * + * FUNCTION: Acpi_ev_execute_reg_method + * + * PARAMETERS: Region_obj - Object structure + * Function - On (1) or Off (0) + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG method for a region + * + *************************************************************************/ + +static ACPI_STATUS +acpi_ev_execute_reg_method ( + ACPI_OPERAND_OBJECT *region_obj, + u32 function) +{ + ACPI_OPERAND_OBJECT *params[3]; + ACPI_OPERAND_OBJECT space_id_desc; + ACPI_OPERAND_OBJECT function_desc; + ACPI_STATUS status; + + + if (region_obj->region.extra->extra.method_REG == NULL) { + return (AE_OK); + } + + /* + * _REG method has two arguments + * Arg0: Integer: Operation region space ID + * Same value as Region_obj->Region.Space_id + * Arg1: Integer: connection status + * 1 for connecting the handler, + * 0 for disconnecting the handler + * Passed as a parameter + */ + + acpi_cm_init_static_object (&space_id_desc); + acpi_cm_init_static_object (&function_desc); + + /* + * Method requires two parameters. + */ + params [0] = &space_id_desc; + params [1] = &function_desc; + params [2] = NULL; + + /* + * Set up the parameter objects + */ + space_id_desc.common.type = ACPI_TYPE_INTEGER; + space_id_desc.integer.value = region_obj->region.space_id; + + function_desc.common.type = ACPI_TYPE_INTEGER; + function_desc.integer.value = function; + + /* + * Execute the method, no return value + */ + status = acpi_ns_evaluate_by_handle (region_obj->region.extra->extra.method_REG, params, NULL); + return (status); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_ev_address_space_dispatch + * + * PARAMETERS: Region_obj - internal region object + * Space_id - ID of the address space (0-255) + * Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * + * RETURN: Status + * + * DESCRIPTION: Dispatch an address space or operation region access to + * a previously installed handler. + * + *************************************************************************/ + +ACPI_STATUS +acpi_ev_address_space_dispatch ( + ACPI_OPERAND_OBJECT *region_obj, + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value) +{ + ACPI_STATUS status; + ADDRESS_SPACE_HANDLER handler; + ADDRESS_SPACE_SETUP region_setup; + ACPI_OPERAND_OBJECT *handler_desc; + void *region_context = NULL; + + + /* + * Ensure that there is a handler associated with this region + */ + handler_desc = region_obj->region.addr_handler; + if (!handler_desc) { + return(AE_NOT_EXIST); + } + + /* + * It may be the case that the region has never been initialized + * Some types of regions require special init code + */ + if (!(region_obj->region.flags & AOPOBJ_INITIALIZED)) { + /* + * This region has not been initialized yet, do it + */ + region_setup = handler_desc->addr_handler.setup; + if (!region_setup) { + /* + * Bad news, no init routine and not init'd + */ + return (AE_UNKNOWN_STATUS); + } + + /* + * We must exit the interpreter because the region setup will potentially + * execute control methods + */ + acpi_aml_exit_interpreter (); + + status = region_setup (region_obj, ACPI_REGION_ACTIVATE, + handler_desc->addr_handler.context, + ®ion_context); + + /* Re-enter the interpreter */ + + acpi_aml_enter_interpreter (); + + /* + * Init routine may fail + */ + if (ACPI_FAILURE (status)) { + return(status); + } + + region_obj->region.flags |= AOPOBJ_INITIALIZED; + + /* + * Save the returned context for use in all accesses to + * this particular region. + */ + region_obj->region.extra->extra.region_context = region_context; + } + + /* + * We have everything we need, begin the process + */ + handler = handler_desc->addr_handler.handler; + + if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the intepreter. + */ + acpi_aml_exit_interpreter(); + } + + /* + * Invoke the handler. + */ + status = handler (function, address, bit_width, value, + handler_desc->addr_handler.context, + region_obj->region.extra->extra.region_context); + + + if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* We just returned from a non-default handler, we must re-enter the + interpreter */ + + acpi_aml_enter_interpreter (); + } + + return (status); +} + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_disassociate_region_from_handler + * + * PARAMETERS: Region_obj - Region Object + * Acpi_ns_is_locked - Namespace Region Already Locked? + * + * RETURN: None + * + * DESCRIPTION: Break the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +void +acpi_ev_disassociate_region_from_handler( + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_is_locked) +{ + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT **last_obj_ptr; + ADDRESS_SPACE_SETUP region_setup; + void *region_context; + ACPI_STATUS status; + + + region_context = region_obj->region.extra->extra.region_context; + + /* + * Get the address handler from the region object + */ + + handler_obj = region_obj->region.addr_handler; + if (!handler_obj) { + /* + * This region has no handler, all done + */ + return; + } + + + /* + * Find this region in the handler's list + */ + + obj_desc = handler_obj->addr_handler.region_list; + last_obj_ptr = &handler_obj->addr_handler.region_list; + + while (obj_desc) { + /* + * See if this is the one + */ + if (obj_desc == region_obj) { + /* + * This is it, remove it from the handler's list + */ + *last_obj_ptr = obj_desc->region.next; + obj_desc->region.next = NULL; /* Must clear field */ + + if (acpi_ns_is_locked) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + /* + * Now stop region accesses by executing the _REG method + */ + acpi_ev_execute_reg_method (region_obj, 0); + + if (acpi_ns_is_locked) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + } + + /* + * Call the setup handler with the deactivate notification + */ + region_setup = handler_obj->addr_handler.setup; + status = region_setup (region_obj, ACPI_REGION_DEACTIVATE, + handler_obj->addr_handler.context, + ®ion_context); + + /* + * Init routine may fail, Just ignore errors + */ + + region_obj->region.flags &= ~(AOPOBJ_INITIALIZED); + + /* + * Remove handler reference in the region + * + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method + * + * If the region is on the handler's list + * this better be the region's handler + */ + ACPI_ASSERT (region_obj->region.addr_handler == handler_obj); + + region_obj->region.addr_handler = NULL; + + return; + + } /* found the right handler */ + + /* + * Move through the linked list of handlers + */ + last_obj_ptr = &obj_desc->region.next; + obj_desc = obj_desc->region.next; + } + + /* + * If we get here, the region was not in the handler's region list + */ + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_associate_region_and_handler + * + * PARAMETERS: Handler_obj - Handler Object + * Region_obj - Region Object + * Acpi_ns_is_locked - Namespace Region Already Locked? + * + * RETURN: None + * + * DESCRIPTION: Create the association between the handler and the region + * this is a two way association. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_associate_region_and_handler ( + ACPI_OPERAND_OBJECT *handler_obj, + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_is_locked) +{ + ACPI_STATUS status; + + + ACPI_ASSERT (region_obj->region.space_id == handler_obj->addr_handler.space_id); + ACPI_ASSERT (region_obj->region.addr_handler == 0); + + /* + * Link this region to the front of the handler's list + */ + + region_obj->region.next = handler_obj->addr_handler.region_list; + handler_obj->addr_handler.region_list = region_obj; + + /* + * set the region's handler + */ + +/* + Handler_obj->Common.Reference_count = + (u16) (Handler_obj->Common.Reference_count + + Region_obj->Common.Reference_count - 1); +*/ + region_obj->region.addr_handler = handler_obj; + + /* + * Last thing, tell all users that this region is usable + */ + if (acpi_ns_is_locked) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + status = acpi_ev_execute_reg_method (region_obj, 1); + + if (acpi_ns_is_locked) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + } + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ev_addr_handler_helper + * + * PARAMETERS: Handle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into Acpi_ns_walk_namespace + * + * DESCRIPTION: This routine checks to see if the object is a Region if it + * is then the address handler is installed in it. + * + * If the Object is a Device, and the device has a handler of + * the same type then the search is terminated in that branch. + * + * This is because the existing handler is closer in proximity + * to any more regions than the one we are trying to install. + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ev_addr_handler_helper ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_OPERAND_OBJECT *tmp_obj; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + + + handler_obj = (ACPI_OPERAND_OBJECT *) context; + + /* Parameter validation */ + + if (!handler_obj) { + return (AE_OK); + } + + /* Convert and validate the device handle */ + + node = acpi_ns_convert_handle_to_entry (obj_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * We only care about regions.and objects + * that can have address handlers + */ + + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_REGION) && + (node != acpi_gbl_root_node)) { + return (AE_OK); + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + if (!obj_desc) { + /* + * The object DNE, we don't care about it + */ + return (AE_OK); + } + + /* + * Devices are handled different than regions + */ + if (IS_THIS_OBJECT_TYPE (obj_desc, ACPI_TYPE_DEVICE)) { + /* + * See if this guy has any handlers + */ + tmp_obj = obj_desc->device.addr_handler; + while (tmp_obj) { + /* + * Now let's see if it's for the same address space. + */ + if (tmp_obj->addr_handler.space_id == handler_obj->addr_handler.space_id) { + /* + * It's for the same address space + */ + /* + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. + */ + return (AE_CTRL_DEPTH); + } + + /* + * Move through the linked list of handlers + */ + tmp_obj = tmp_obj->addr_handler.next; + } + + /* + * As long as the device didn't have a handler for this + * space we don't care about it. We just ignore it and + * proceed. + */ + return (AE_OK); + } + + /* + * Only here if it was a region + */ + ACPI_ASSERT (obj_desc->common.type == ACPI_TYPE_REGION); + + if (obj_desc->region.space_id != handler_obj->addr_handler.space_id) { + /* + * This region is for a different address space + * ignore it + */ + return (AE_OK); + } + + /* + * Now we have a region and it is for the handler's address + * space type. + * + * First disconnect region for any previous handler (if any) + */ + acpi_ev_disassociate_region_from_handler (obj_desc, FALSE); + + /* + * Then connect the region to the new handler + */ + status = acpi_ev_associate_region_and_handler (handler_obj, obj_desc, FALSE); + + return (status); +} + + diff --git a/drivers/bus/acpi/events/evrgnini.c b/drivers/bus/acpi/events/evrgnini.c new file mode 100644 index 0000000..2125cab --- /dev/null +++ b/drivers/bus/acpi/events/evrgnini.c @@ -0,0 +1,417 @@ +/****************************************************************************** + * + * Module Name: evrgnini- ACPI Address_space (Op_region) init + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evrgnini") + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_system_memory_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling, a nop for now + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_system_memory_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context) +{ + + if (function == ACPI_REGION_DEACTIVATE) { + if (*region_context) { + acpi_cm_free (*region_context); + *region_context = NULL; + } + return (AE_OK); + } + + + /* Activate. Create a new context */ + + *region_context = acpi_cm_callocate (sizeof (MEM_HANDLER_CONTEXT)); + if (!(*region_context)) { + return (AE_NO_MEMORY); + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_io_space_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_io_space_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context) +{ + if (function == ACPI_REGION_DEACTIVATE) { + *region_context = NULL; + } + else { + *region_context = handler_context; + } + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_pci_config_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling + * + * MUTEX: Assumes namespace is not locked + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_pci_config_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context) +{ + ACPI_STATUS status = AE_OK; + ACPI_INTEGER temp; + PCI_HANDLER_CONTEXT *pci_context = *region_context; + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_NAMESPACE_NODE *node; + ACPI_OPERAND_OBJECT *region_obj = (ACPI_OPERAND_OBJECT *) handle; + DEVICE_ID object_hID; + + handler_obj = region_obj->region.addr_handler; + + if (!handler_obj) { + /* + * No installed handler. This shouldn't happen because the dispatch + * routine checks before we get here, but we check again just in case. + */ + return(AE_NOT_EXIST); + } + + if (function == ACPI_REGION_DEACTIVATE) { + if (pci_context) { + acpi_cm_free (pci_context); + *region_context = NULL; + } + + return (status); + } + + + /* Create a new context */ + + pci_context = acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT)); + if (!pci_context) { + return (AE_NO_MEMORY); + } + + /* + * For PCI Config space access, we have to pass the segment, bus, + * device and function numbers. This routine must acquire those. + */ + + /* + * First get device and function numbers from the _ADR object + * in the parent's scope. + */ + ACPI_ASSERT(region_obj->region.node); + + node = acpi_ns_get_parent_object (region_obj->region.node); + + + /* Acpi_evaluate the _ADR object */ + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); + /* + * The default is zero, since the allocation above zeroed the data, just + * do nothing on failures. + */ + if (ACPI_SUCCESS (status)) { + /* + * Got it.. + */ + pci_context->dev_func = (u32) temp; + } + + /* + * Get the _SEG and _BBN values from the device upon which the handler + * is installed. + * + * We need to get the _SEG and _BBN objects relative to the PCI BUS device. + * This is the device the handler has been registered to handle. + */ + + /* + * If the Addr_handler.Node is still pointing to the root, we need + * to scan upward for a PCI Root bridge and re-associate the Op_region + * handlers with that device. + */ + if (handler_obj->addr_handler.node == acpi_gbl_root_node) { + /* + * Node is currently the parent object + */ + while (node != acpi_gbl_root_node) { + status = acpi_cm_execute_HID(node, &object_hID); + + if (ACPI_SUCCESS (status)) { + if (!(STRNCMP(object_hID.buffer, PCI_ROOT_HID_STRING, + sizeof (PCI_ROOT_HID_STRING)))) { + acpi_install_address_space_handler(node, + ADDRESS_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + + break; + } + } + + node = acpi_ns_get_parent_object(node); + } + } + else { + node = handler_obj->addr_handler.node; + } + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp); + if (ACPI_SUCCESS (status)) { + /* + * Got it.. + */ + pci_context->seg = (u32) temp; + } + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp); + if (ACPI_SUCCESS (status)) { + /* + * Got it.. + */ + pci_context->bus = (u32) temp; + } + + *region_context = pci_context; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_ev_default_region_setup + * + * PARAMETERS: Region_obj - region we are interested in + * Function - start or stop + * Handler_context - Address space handler context + * Region_context - Region specific context + * + * RETURN: Status + * + * DESCRIPTION: Do any prep work for region handling + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ev_default_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context) +{ + if (function == ACPI_REGION_DEACTIVATE) { + *region_context = NULL; + } + else { + *region_context = handler_context; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_initialize_region + * + * PARAMETERS: Region_obj - Region we are initializing + * + * RETURN: Status + * + * DESCRIPTION: Initializes the region, finds any _REG methods and saves them + * for execution at a later time + * + * Get the appropriate address space handler for a newly + * created region. + * + * This also performs address space specific intialization. For + * example, PCI regions must have an _ADR object that contains + * a PCI address in the scope of the defintion. This address is + * required to perform an access to PCI config space. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_initialize_region ( + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_locked) +{ + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_ADDRESS_SPACE_TYPE space_id; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *method_node; + ACPI_NAME *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG; + + + if (!region_obj) { + return (AE_BAD_PARAMETER); + } + + ACPI_ASSERT(region_obj->region.node); + + node = acpi_ns_get_parent_object (region_obj->region.node); + space_id = region_obj->region.space_id; + + region_obj->region.addr_handler = NULL; + region_obj->region.extra->extra.method_REG = NULL; + region_obj->region.flags &= ~(AOPOBJ_INITIALIZED); + + /* + * Find any "_REG" associated with this region definition + */ + status = acpi_ns_search_node (*reg_name_ptr, node, + ACPI_TYPE_METHOD, &method_node); + if (ACPI_SUCCESS (status)) { + /* + * The _REG method is optional and there can be only one per region + * definition. This will be executed when the handler is attached + * or removed + */ + region_obj->region.extra->extra.method_REG = method_node; + } + + /* + * The following loop depends upon the root Node having no parent + * ie: Acpi_gbl_Root_node->Parent_entry being set to NULL + */ + while (node) { + /* + * Check to see if a handler exists + */ + handler_obj = NULL; + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + if (obj_desc) { + /* + * can only be a handler if the object exists + */ + switch (node->type) { + case ACPI_TYPE_DEVICE: + + handler_obj = obj_desc->device.addr_handler; + break; + + case ACPI_TYPE_PROCESSOR: + + handler_obj = obj_desc->processor.addr_handler; + break; + + case ACPI_TYPE_THERMAL: + + handler_obj = obj_desc->thermal_zone.addr_handler; + break; + } + + while (handler_obj) { + /* + * This guy has at least one address handler + * see if it has the type we want + */ + if (handler_obj->addr_handler.space_id == space_id) { + /* + * Found it! Now update the region and the handler + */ + acpi_ev_associate_region_and_handler (handler_obj, region_obj, acpi_ns_locked); + return (AE_OK); + } + + handler_obj = handler_obj->addr_handler.next; + + } /* while handlerobj */ + } + + /* + * This one does not have the handler we need + * Pop up one level + */ + node = acpi_ns_get_parent_object (node); + + } /* while Node != ROOT */ + + /* + * If we get here, there is no handler for this region + */ + return (AE_NOT_EXIST); +} + diff --git a/drivers/bus/acpi/events/evsci.c b/drivers/bus/acpi/events/evsci.c new file mode 100644 index 0000000..8a4e3ca --- /dev/null +++ b/drivers/bus/acpi/events/evsci.c @@ -0,0 +1,271 @@ +/******************************************************************************* + * + * Module Name: evsci - System Control Interrupt configuration and + * legacy to ACPI mode state transition functions + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evsci") + + +/* + * Elements correspond to counts for TMR, NOT_USED, GBL, PWR_BTN, SLP_BTN, RTC, + * and GENERAL respectively. These counts are modified by the ACPI interrupt + * handler. + * + * TBD: [Investigate] Note that GENERAL should probably be split out into + * one element for each bit in the GPE registers + */ + + +/******************************************************************************* + * + * FUNCTION: Acpi_ev_sci_handler + * + * PARAMETERS: Context - Calling Context + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Interrupt handler that will figure out what function or + * control method to call to deal with a SCI. Installed + * using BU interrupt support. + * + ******************************************************************************/ + +static u32 +acpi_ev_sci_handler (void *context) +{ + u32 interrupt_handled = INTERRUPT_NOT_HANDLED; + + + /* + * Make sure that ACPI is enabled by checking SCI_EN. Note that we are + * required to treat the SCI interrupt as sharable, level, active low. + */ + if (!acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_DO_NOT_LOCK, SCI_EN)) { + /* ACPI is not enabled; this interrupt cannot be for us */ + + return (INTERRUPT_NOT_HANDLED); + } + + /* + * Fixed Acpi_events: + * ------------- + * Check for and dispatch any Fixed Acpi_events that have occurred + */ + interrupt_handled |= acpi_ev_fixed_event_detect (); + + /* + * GPEs: + * ----- + * Check for and dispatch any GPEs that have occurred + */ + interrupt_handled |= acpi_ev_gpe_detect (); + + return (interrupt_handled); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_install_sci_handler + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Installs SCI handler. + * + ******************************************************************************/ + +u32 +acpi_ev_install_sci_handler (void) +{ + u32 except = AE_OK; + + + except = acpi_os_install_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, + acpi_ev_sci_handler, + NULL); + + return (except); +} + + +/****************************************************************************** + + * + * FUNCTION: Acpi_ev_remove_sci_handler + * + * PARAMETERS: none + * + * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not + * installed to begin with + * + * DESCRIPTION: Restores original status of all fixed event enable bits and + * removes SCI handler. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ev_remove_sci_handler (void) +{ +#if 0 + /* TBD:[Investigate] Figure this out!! Disable all events first ??? */ + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (TMR_FIXED_EVENT)) { + acpi_event_disable_event (TMR_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (GBL_FIXED_EVENT)) { + acpi_event_disable_event (GBL_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (PWR_BTN_FIXED_EVENT)) { + acpi_event_disable_event (PWR_BTN_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (SLP_BTN_FIXED_EVENT)) { + acpi_event_disable_event (SLP_BTN_FIXED_EVENT); + } + + if (original_fixed_enable_bit_status ^ 1 << acpi_event_index (RTC_FIXED_EVENT)) { + acpi_event_disable_event (RTC_FIXED_EVENT); + } + + original_fixed_enable_bit_status = 0; + +#endif + + acpi_os_remove_interrupt_handler ((u32) acpi_gbl_FADT->sci_int, + acpi_ev_sci_handler); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ev_restore_acpi_state + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Restore the original ACPI state of the machine + * + ******************************************************************************/ + +void +acpi_ev_restore_acpi_state (void) +{ + u32 index; + + + /* Restore the state of the chipset enable bits. */ + + if (acpi_gbl_restore_acpi_chipset == TRUE) { + /* Restore the fixed events */ + + if (acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN) != + acpi_gbl_pm1_enable_register_save) { + acpi_hw_register_write (ACPI_MTX_LOCK, PM1_EN, + acpi_gbl_pm1_enable_register_save); + } + + + /* Ensure that all status bits are clear */ + + acpi_hw_clear_acpi_status (); + + + /* Now restore the GPEs */ + + for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) { + if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index) != + acpi_gbl_gpe0enable_register_save[index]) { + acpi_hw_register_write (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index, + acpi_gbl_gpe0enable_register_save[index]); + } + } + + /* GPE 1 present? */ + + if (acpi_gbl_FADT->gpe1_blk_len) { + for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) { + if (acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index) != + acpi_gbl_gpe1_enable_register_save[index]) { + acpi_hw_register_write (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index, + acpi_gbl_gpe1_enable_register_save[index]); + } + } + } + + if (acpi_hw_get_mode() != acpi_gbl_original_mode) { + acpi_hw_set_mode (acpi_gbl_original_mode); + } + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ev_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_ev_terminate (void) +{ + + + /* + * Free global tables, etc. + */ + + if (acpi_gbl_gpe_registers) { + acpi_cm_free (acpi_gbl_gpe_registers); + } + + if (acpi_gbl_gpe_info) { + acpi_cm_free (acpi_gbl_gpe_info); + } + + return; +} + + diff --git a/drivers/bus/acpi/events/evxface.c b/drivers/bus/acpi/events/evxface.c new file mode 100644 index 0000000..ed864ee --- /dev/null +++ b/drivers/bus/acpi/events/evxface.c @@ -0,0 +1,609 @@ +/****************************************************************************** + * + * Module Name: evxface - External interfaces for ACPI events + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "acnamesp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evxface") + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_fixed_event_handler + * + * PARAMETERS: Event - Event type to enable. + * Handler - Pointer to the handler function for the + * event + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Saves the pointer to the handler function and then enables the + * event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_fixed_event_handler ( + u32 event, + FIXED_EVENT_HANDLER handler, + void *context) +{ + ACPI_STATUS status; + + + /* Parameter validation */ + + if (event >= NUM_FIXED_EVENTS) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Don't allow two handlers. */ + + if (NULL != acpi_gbl_fixed_event_handlers[event].handler) { + status = AE_EXIST; + goto cleanup; + } + + + /* Install the handler before enabling the event - just in case... */ + + acpi_gbl_fixed_event_handlers[event].handler = handler; + acpi_gbl_fixed_event_handlers[event].context = context; + + status = acpi_enable_event (event, ACPI_EVENT_FIXED); + if (!ACPI_SUCCESS (status)) { + /* Remove the handler */ + + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + } + + + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_remove_fixed_event_handler + * + * PARAMETERS: Event - Event type to disable. + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Disables the event and unregisters the event handler. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_fixed_event_handler ( + u32 event, + FIXED_EVENT_HANDLER handler) +{ + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if (event >= NUM_FIXED_EVENTS) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Disable the event before removing the handler - just in case... */ + + status = acpi_disable_event(event, ACPI_EVENT_FIXED); + + /* Always Remove the handler */ + + acpi_gbl_fixed_event_handlers[event].handler = NULL; + acpi_gbl_fixed_event_handlers[event].context = NULL; + + + + + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_notify_handler + * + * PARAMETERS: Device - The device for which notifies will be handled + * Handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: System_handler (00-7f) + * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff) + * Handler - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for notifies on an ACPI device + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler, + void *context) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *notify_obj; + ACPI_NAMESPACE_NODE *device_node; + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if ((!handler) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + device_node = acpi_ns_convert_handle_to_entry (device); + if (!device_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * Root Object: + * ------------ + * Registering a notify handler on the root object indicates that the + * caller wishes to receive notifications for all objects. Note that + * only one global handler can be regsitered (per notify type). + */ + if (device == ACPI_ROOT_OBJECT) { + /* Make sure the handler is not already installed */ + + if (((handler_type == ACPI_SYSTEM_NOTIFY) && + acpi_gbl_sys_notify.handler) || + ((handler_type == ACPI_DEVICE_NOTIFY) && + acpi_gbl_drv_notify.handler)) { + status = AE_EXIST; + goto unlock_and_exit; + } + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + acpi_gbl_sys_notify.node = device_node; + acpi_gbl_sys_notify.handler = handler; + acpi_gbl_sys_notify.context = context; + } + else /* ACPI_DEVICE_NOTIFY */ { + acpi_gbl_drv_notify.node = device_node; + acpi_gbl_drv_notify.handler = handler; + acpi_gbl_drv_notify.context = context; + } + + /* Global notify handler installed */ + } + + /* + * Other Objects: + * -------------- + * Caller will only receive notifications specific to the target object. + * Note that only certain object types can receive notifications. + */ + else { + /* + * These are the ONLY objects that can receive ACPI notifications + */ + if ((device_node->type != ACPI_TYPE_DEVICE) && + (device_node->type != ACPI_TYPE_PROCESSOR) && + (device_node->type != ACPI_TYPE_POWER) && + (device_node->type != ACPI_TYPE_THERMAL)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node); + if (obj_desc) { + + /* Object exists - make sure there's no handler */ + + if (((handler_type == ACPI_SYSTEM_NOTIFY) && + obj_desc->device.sys_handler) || + ((handler_type == ACPI_DEVICE_NOTIFY) && + obj_desc->device.drv_handler)) { + status = AE_EXIST; + goto unlock_and_exit; + } + } + + else { + /* Create a new object */ + + obj_desc = acpi_cm_create_internal_object (device_node->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Attach new object to the Node */ + + status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + } + + /* Install the handler */ + + notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY); + if (!notify_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + notify_obj->notify_handler.node = device_node; + notify_obj->notify_handler.handler = handler; + notify_obj->notify_handler.context = context; + + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + obj_desc->device.sys_handler = notify_obj; + } + else /* ACPI_DEVICE_NOTIFY */ { + obj_desc->device.drv_handler = notify_obj; + } + } + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_remove_notify_handler + * + * PARAMETERS: Device - The device for which notifies will be handled + * Handler_type - The type of handler: + * ACPI_SYSTEM_NOTIFY: System_handler (00-7f) + * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff) + * Handler - Address of the handler + * RETURN: Status + * + * DESCRIPTION: Remove a handler for notifies on an ACPI device + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler) +{ + ACPI_OPERAND_OBJECT *notify_obj; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *device_node; + ACPI_STATUS status = AE_OK; + + /* Parameter validation */ + + if ((!handler) || + (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + device_node = acpi_ns_convert_handle_to_entry (device); + if (!device_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * Root Object: + * ------------ + */ + if (device == ACPI_ROOT_OBJECT) { + + if (((handler_type == ACPI_SYSTEM_NOTIFY) && + !acpi_gbl_sys_notify.handler) || + ((handler_type == ACPI_DEVICE_NOTIFY) && + !acpi_gbl_drv_notify.handler)) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + acpi_gbl_sys_notify.node = NULL; + acpi_gbl_sys_notify.handler = NULL; + acpi_gbl_sys_notify.context = NULL; + } + else { + acpi_gbl_drv_notify.node = NULL; + acpi_gbl_drv_notify.handler = NULL; + acpi_gbl_drv_notify.context = NULL; + } + } + + /* + * Other Objects: + * -------------- + */ + else { + /* + * These are the ONLY objects that can receive ACPI notifications + */ + if ((device_node->type != ACPI_TYPE_DEVICE) && + (device_node->type != ACPI_TYPE_PROCESSOR) && + (device_node->type != ACPI_TYPE_POWER) && + (device_node->type != ACPI_TYPE_THERMAL)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Check for an existing internal object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node); + if (!obj_desc) { + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* Object exists - make sure there's an existing handler */ + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + notify_obj = obj_desc->device.sys_handler; + } + else { + notify_obj = obj_desc->device.drv_handler; + } + + if ((!notify_obj) || + (notify_obj->notify_handler.handler != handler)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Remove the handler */ + + if (handler_type == ACPI_SYSTEM_NOTIFY) { + obj_desc->device.sys_handler = NULL; + } + else { + obj_desc->device.drv_handler = NULL; + } + + acpi_cm_remove_reference (notify_obj); + } + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_gpe_handler + * + * PARAMETERS: Gpe_number - The GPE number. The numbering scheme is + * bank 0 first, then bank 1. + * Type - Whether this GPE should be treated as an + * edge- or level-triggered interrupt. + * Handler - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a General Purpose Event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_gpe_handler ( + u32 gpe_number, + u32 type, + GPE_HANDLER handler, + void *context) +{ + ACPI_STATUS status = AE_OK; + + /* Parameter validation */ + + if (!handler || (gpe_number > NUM_GPE)) { + return (AE_BAD_PARAMETER); + } + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Make sure that there isn't a handler there already */ + + if (acpi_gbl_gpe_info[gpe_number].handler) { + status = AE_EXIST; + goto cleanup; + } + + /* Install the handler */ + + acpi_gbl_gpe_info[gpe_number].handler = handler; + acpi_gbl_gpe_info[gpe_number].context = context; + acpi_gbl_gpe_info[gpe_number].type = (u8) type; + + /* Clear the GPE (of stale events), the enable it */ + + acpi_hw_clear_gpe (gpe_number); + acpi_hw_enable_gpe (gpe_number); + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_remove_gpe_handler + * + * PARAMETERS: Gpe_number - The event to remove a handler + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a General Purpose Acpi_event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_gpe_handler ( + u32 gpe_number, + GPE_HANDLER handler) +{ + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if (!handler || (gpe_number > NUM_GPE)) { + return (AE_BAD_PARAMETER); + } + + /* Ensure that we have a valid GPE number */ + + if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) { + return (AE_BAD_PARAMETER); + } + + /* Disable the GPE before removing the handler */ + + acpi_hw_disable_gpe (gpe_number); + + acpi_cm_acquire_mutex (ACPI_MTX_EVENTS); + + /* Make sure that the installed handler is the same */ + + if (acpi_gbl_gpe_info[gpe_number].handler != handler) { + acpi_hw_enable_gpe (gpe_number); + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Remove the handler */ + + acpi_gbl_gpe_info[gpe_number].handler = NULL; + acpi_gbl_gpe_info[gpe_number].context = NULL; + +cleanup: + acpi_cm_release_mutex (ACPI_MTX_EVENTS); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_acquire_global_lock + * + * PARAMETERS: Timeout - How long the caller is willing to wait + * Out_handle - A handle to the lock if acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire the ACPI Global Lock + * + ******************************************************************************/ +ACPI_STATUS +acpi_acquire_global_lock ( + void) +{ + ACPI_STATUS status; + + + status = acpi_aml_enter_interpreter (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * TBD: [Restructure] add timeout param to internal interface, and + * perhaps INTERPRETER_LOCKED + */ + + status = acpi_ev_acquire_global_lock (); + acpi_aml_exit_interpreter (); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_release_global_lock + * + * PARAMETERS: Handle - Returned from Acpi_acquire_global_lock + * + * RETURN: Status + * + * DESCRIPTION: Release the ACPI Global Lock + * + ******************************************************************************/ + +ACPI_STATUS +acpi_release_global_lock ( + void) +{ + acpi_ev_release_global_lock (); + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/events/evxfevnt.c b/drivers/bus/acpi/events/evxfevnt.c new file mode 100644 index 0000000..66de392 --- /dev/null +++ b/drivers/bus/acpi/events/evxfevnt.c @@ -0,0 +1,485 @@ +/****************************************************************************** + * + * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "acnamesp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evxfevnt") + + +/************************************************************************** + * + * FUNCTION: Acpi_enable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Transfers the system into ACPI mode. + * + *************************************************************************/ + +ACPI_STATUS +acpi_enable (void) +{ + ACPI_STATUS status; + + + /* Make sure we've got ACPI tables */ + + if (!acpi_gbl_DSDT) { + return (AE_NO_ACPI_TABLES); + } + + /* Make sure the BIOS supports ACPI mode */ + + if (SYS_MODE_LEGACY == acpi_hw_get_mode_capabilities()) { + return (AE_ERROR); + } + + /* Transition to ACPI mode */ + + status = acpi_hw_set_mode (SYS_MODE_ACPI); + if (ACPI_FAILURE (status)) { + return (status); + } + + return (status); +} + + +/************************************************************************** + * + * FUNCTION: Acpi_disable + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Returns the system to original ACPI/legacy mode, and + * uninstalls the SCI interrupt handler. + * + *************************************************************************/ + +ACPI_STATUS +acpi_disable (void) +{ + ACPI_STATUS status; + + + /* Restore original mode */ + + status = acpi_hw_set_mode (acpi_gbl_original_mode); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Unload the SCI interrupt handler */ + + acpi_ev_remove_sci_handler (); + acpi_ev_restore_acpi_state (); + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_enable_event + * + * PARAMETERS: Event - The fixed event or GPE to be enabled + * Type - The type of event + * + * RETURN: Status + * + * DESCRIPTION: Enable an ACPI event (fixed and general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enable_event ( + u32 event, + u32 type) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) { + case ACPI_EVENT_PMTIMER: + register_id = TMR_EN; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_EN; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_EN; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_EN; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_EN; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* + * Enable the requested fixed event (by writing a one to the + * enable register bit) + */ + + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 1); + + if (1 != acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, register_id)) { + return (AE_NO_HARDWARE_RESPONSE); + } + + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + return (AE_BAD_PARAMETER); + } + + + /* Enable the requested GPE number */ + + acpi_hw_enable_gpe (event); + break; + + + default: + + status = AE_BAD_PARAMETER; + } + + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_disable_event + * + * PARAMETERS: Event - The fixed event or GPE to be enabled + * Type - The type of event + * + * RETURN: Status + * + * DESCRIPTION: Disable an ACPI event (fixed and general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_disable_event ( + u32 event, + u32 type) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) { + case ACPI_EVENT_PMTIMER: + register_id = TMR_EN; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_EN; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_EN; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_EN; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_EN; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* + * Disable the requested fixed event (by writing a zero to the + * enable register bit) + */ + + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 0); + + if (0 != acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, register_id)) { + return (AE_NO_HARDWARE_RESPONSE); + } + + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + return (AE_BAD_PARAMETER); + } + + /* Disable the requested GPE number */ + + acpi_hw_disable_gpe (event); + break; + + + default: + status = AE_BAD_PARAMETER; + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_clear_event + * + * PARAMETERS: Event - The fixed event or GPE to be cleared + * Type - The type of event + * + * RETURN: Status + * + * DESCRIPTION: Clear an ACPI event (fixed and general purpose) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_clear_event ( + u32 event, + u32 type) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) { + case ACPI_EVENT_PMTIMER: + register_id = TMR_STS; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_STS; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_STS; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_STS; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_STS; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* + * Clear the requested fixed event (By writing a one to the + * status register bit) + */ + + acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, register_id, 1); + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + return (AE_BAD_PARAMETER); + } + + + acpi_hw_clear_gpe (event); + break; + + + default: + + status = AE_BAD_PARAMETER; + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_event_status + * + * PARAMETERS: Event - The fixed event or GPE + * Type - The type of event + * Status - Where the current status of the event will + * be returned + * + * RETURN: Status + * + * DESCRIPTION: Obtains and returns the current status of the event + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_get_event_status ( + u32 event, + u32 type, + ACPI_EVENT_STATUS *event_status) +{ + ACPI_STATUS status = AE_OK; + u32 register_id; + + + if (!event_status) { + return (AE_BAD_PARAMETER); + } + + + /* The Type must be either Fixed Acpi_event or GPE */ + + switch (type) { + + case ACPI_EVENT_FIXED: + + /* Decode the Fixed Acpi_event */ + + switch (event) { + case ACPI_EVENT_PMTIMER: + register_id = TMR_STS; + break; + + case ACPI_EVENT_GLOBAL: + register_id = GBL_STS; + break; + + case ACPI_EVENT_POWER_BUTTON: + register_id = PWRBTN_STS; + break; + + case ACPI_EVENT_SLEEP_BUTTON: + register_id = SLPBTN_STS; + break; + + case ACPI_EVENT_RTC: + register_id = RTC_STS; + break; + + default: + return (AE_BAD_PARAMETER); + break; + } + + /* Get the status of the requested fixed event */ + + *event_status = acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, register_id); + break; + + + case ACPI_EVENT_GPE: + + /* Ensure that we have a valid GPE number */ + + if ((event >= NUM_GPE) || + (acpi_gbl_gpe_valid[event] == ACPI_GPE_INVALID)) { + return (AE_BAD_PARAMETER); + } + + + /* Obtain status on the requested GPE number */ + + acpi_hw_get_gpe_status (event, event_status); + break; + + + default: + status = AE_BAD_PARAMETER; + } + + + return (status); +} + diff --git a/drivers/bus/acpi/events/evxfregn.c b/drivers/bus/acpi/events/evxfregn.c new file mode 100644 index 0000000..c3bb244 --- /dev/null +++ b/drivers/bus/acpi/events/evxfregn.c @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and + * Address Spaces. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "acnamesp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + MODULE_NAME ("evxfregn") + + +/****************************************************************************** + * + * FUNCTION: Acpi_install_address_space_handler + * + * PARAMETERS: Device - Handle for the device + * Space_id - The address space ID + * Handler - Address of the handler + * Setup - Address of the setup function + * Context - Value passed to the handler on each access + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for all Op_regions of a given Space_id. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_install_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler, + ADDRESS_SPACE_SETUP setup, + void *context) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status = AE_OK; + OBJECT_TYPE_INTERNAL type; + u16 flags = 0; + + + /* Parameter validation */ + + if ((!device) || + ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || + (space_id > ACPI_MAX_ADDRESS_SPACE)) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + node = acpi_ns_convert_handle_to_entry (device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* + * This registration is valid for only the types below + * and the root. This is where the default handlers + * get placed. + */ + + if ((node->type != ACPI_TYPE_DEVICE) && + (node->type != ACPI_TYPE_PROCESSOR) && + (node->type != ACPI_TYPE_THERMAL) && + (node != acpi_gbl_root_node)) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + if (handler == ACPI_DEFAULT_HANDLER) { + flags = ADDR_HANDLER_DEFAULT_INSTALLED; + + switch (space_id) { + case ADDRESS_SPACE_SYSTEM_MEMORY: + handler = acpi_aml_system_memory_space_handler; + setup = acpi_ev_system_memory_region_setup; + break; + + case ADDRESS_SPACE_SYSTEM_IO: + handler = acpi_aml_system_io_space_handler; + setup = acpi_ev_io_space_region_setup; + break; + + case ADDRESS_SPACE_PCI_CONFIG: + handler = acpi_aml_pci_config_space_handler; + setup = acpi_ev_pci_config_region_setup; + break; + + default: + status = AE_NOT_EXIST; + goto unlock_and_exit; + break; + } + } + + /* + * If the caller hasn't specified a setup routine, use the default + */ + if (!setup) { + setup = acpi_ev_default_region_setup; + } + + /* + * Check for an existing internal object + */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + if (obj_desc) { + /* + * The object exists. + * Make sure the handler is not already installed. + */ + + /* check the address handler the user requested */ + + handler_obj = obj_desc->device.addr_handler; + while (handler_obj) { + /* + * We have an Address handler, see if user requested this + * address space. + */ + if(handler_obj->addr_handler.space_id == space_id) { + status = AE_EXIST; + goto unlock_and_exit; + } + + /* + * Move through the linked list of handlers + */ + handler_obj = handler_obj->addr_handler.next; + } + } + + else { + /* Obj_desc does not exist, create one */ + + if (node->type == ACPI_TYPE_ANY) { + type = ACPI_TYPE_DEVICE; + } + + else { + type = node->type; + } + + obj_desc = acpi_cm_create_internal_object (type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Init new descriptor */ + + obj_desc->common.type = (u8) type; + + /* Attach the new object to the Node */ + + status = acpi_ns_attach_object (node, obj_desc, (u8) type); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + goto unlock_and_exit; + } + } + + /* + * Now we can install the handler + * + * At this point we know that there is no existing handler. + * So, we just allocate the object for the handler and link it + * into the list. + */ + handler_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER); + if (!handler_obj) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + handler_obj->addr_handler.space_id = (u8) space_id; + handler_obj->addr_handler.hflags = flags; + handler_obj->addr_handler.next = obj_desc->device.addr_handler; + handler_obj->addr_handler.region_list = NULL; + handler_obj->addr_handler.node = node; + handler_obj->addr_handler.handler = handler; + handler_obj->addr_handler.context = context; + handler_obj->addr_handler.setup = setup; + + /* + * Now walk the namespace finding all of the regions this + * handler will manage. + * + * We start at the device and search the branch toward + * the leaf nodes until either the leaf is encountered or + * a device is detected that has an address handler of the + * same type. + * + * In either case we back up and search down the remainder + * of the branch + */ + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, + ACPI_UINT32_MAX, NS_WALK_UNLOCK, + acpi_ev_addr_handler_helper, + handler_obj, NULL); + + /* + * Place this handler 1st on the list + */ + + handler_obj->common.reference_count = + (u16) (handler_obj->common.reference_count + + obj_desc->common.reference_count - 1); + obj_desc->device.addr_handler = handler_obj; + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_remove_address_space_handler + * + * PARAMETERS: Space_id - The address space ID + * Handler - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for accesses on an Operation Region + * + ******************************************************************************/ + +ACPI_STATUS +acpi_remove_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *handler_obj; + ACPI_OPERAND_OBJECT *region_obj; + ACPI_OPERAND_OBJECT **last_obj_ptr; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status = AE_OK; + + + /* Parameter validation */ + + if ((!device) || + ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) || + (space_id > ACPI_MAX_ADDRESS_SPACE)) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the device handle */ + + node = acpi_ns_convert_handle_to_entry (device); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + + /* Make sure the internal object exists */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + if (!obj_desc) { + /* + * The object DNE. + */ + status = AE_NOT_EXIST; + goto unlock_and_exit; + } + + /* + * find the address handler the user requested + */ + + handler_obj = obj_desc->device.addr_handler; + last_obj_ptr = &obj_desc->device.addr_handler; + while (handler_obj) { + /* + * We have a handler, see if user requested this one + */ + + if(handler_obj->addr_handler.space_id == space_id) { + /* + * Got it, first dereference this in the Regions + */ + region_obj = handler_obj->addr_handler.region_list; + + /* Walk the handler's region list */ + + while (region_obj) { + /* + * First disassociate the handler from the region. + * + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method + */ + acpi_ev_disassociate_region_from_handler(region_obj, FALSE); + + /* + * Walk the list, since we took the first region and it + * was removed from the list by the dissassociate call + * we just get the first item on the list again + */ + region_obj = handler_obj->addr_handler.region_list; + + } + + /* + * Remove this Handler object from the list + */ + *last_obj_ptr = handler_obj->addr_handler.next; + + /* + * Now we can delete the handler object + */ + acpi_cm_remove_reference (handler_obj); + acpi_cm_remove_reference (handler_obj); + + goto unlock_and_exit; + } + + /* + * Move through the linked list of handlers + */ + last_obj_ptr = &handler_obj->addr_handler.next; + handler_obj = handler_obj->addr_handler.next; + } + + + /* + * The handler does not exist + */ + status = AE_NOT_EXIST; + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + diff --git a/drivers/bus/acpi/executer/.cvsignore b/drivers/bus/acpi/executer/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/executer/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/executer/amconfig.c b/drivers/bus/acpi/executer/amconfig.c new file mode 100644 index 0000000..958321e --- /dev/null +++ b/drivers/bus/acpi/executer/amconfig.c @@ -0,0 +1,304 @@ +/****************************************************************************** + * + * Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acevents.h" +#include "actables.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amconfig") + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_load_table + * + * PARAMETERS: Rgn_desc - Op region where the table will be obtained + * Ddb_handle - Where a handle to the table will be returned + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table + * + ****************************************************************************/ + +static ACPI_STATUS +acpi_aml_exec_load_table ( + ACPI_OPERAND_OBJECT *rgn_desc, + ACPI_HANDLE *ddb_handle) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *table_desc = NULL; + u8 *table_ptr; + u8 *table_data_ptr; + ACPI_TABLE_HEADER table_header; + ACPI_TABLE_DESC table_info; + u32 i; + + + /* TBD: [Unhandled] Object can be either a field or an opregion */ + + + /* Get the table header */ + + table_header.length = 0; + for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) { + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, + (ACPI_PHYSICAL_ADDRESS) i, 8, + (u32 *) ((u8 *) &table_header + i)); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* Allocate a buffer for the entire table */ + + table_ptr = acpi_cm_allocate (table_header.length); + if (!table_ptr) { + return (AE_NO_MEMORY); + } + + /* Copy the header to the buffer */ + + MEMCPY (table_ptr, &table_header, sizeof (ACPI_TABLE_HEADER)); + table_data_ptr = table_ptr + sizeof (ACPI_TABLE_HEADER); + + + /* Get the table from the op region */ + + for (i = 0; i < table_header.length; i++) { + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, + (ACPI_PHYSICAL_ADDRESS)i, 8, + (u32 *) (table_data_ptr + i)); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + + + /* Table must be either an SSDT or a PSDT */ + + if ((!STRNCMP (table_header.signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && + (!STRNCMP (table_header.signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, + acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) { + status = AE_BAD_SIGNATURE; + goto cleanup; + } + + /* Create an object to be the table handle */ + + table_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!table_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* Install the new table into the local data structures */ + + table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr; + table_info.length = table_header.length; + table_info.allocation = ACPI_MEM_ALLOCATED; + table_info.base_pointer = table_ptr; + + status = acpi_tb_install_table (NULL, &table_info); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Add the table to the namespace */ + + /* TBD: [Restructure] - change to whatever new interface is appropriate */ +/* + Status = Acpi_load_namespace (); + if (ACPI_FAILURE (Status)) + { +*/ + /* TBD: [Errors] Unload the table on failure ? */ +/* + goto Cleanup; + } +*/ + + + /* TBD: [Investigate] we need a pointer to the table desc */ + + /* Init the table handle */ + + table_desc->reference.opcode = AML_LOAD_OP; + table_desc->reference.object = table_info.installed_desc; + + *ddb_handle = table_desc; + + return (status); + + +cleanup: + + acpi_cm_free (table_desc); + acpi_cm_free (table_ptr); + return (status); + +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_unload_table + * + * PARAMETERS: Ddb_handle - Handle to a previously loaded table + * + * RETURN: Status + * + * DESCRIPTION: Unload an ACPI table + * + ****************************************************************************/ + +static ACPI_STATUS +acpi_aml_exec_unload_table ( + ACPI_HANDLE ddb_handle) +{ + ACPI_STATUS status = AE_NOT_IMPLEMENTED; + ACPI_OPERAND_OBJECT *table_desc = (ACPI_OPERAND_OBJECT *) ddb_handle; + ACPI_TABLE_DESC *table_info; + + + /* Validate the handle */ + /* Although the handle is partially validated in Acpi_aml_exec_reconfiguration(), + * when it calls Acpi_aml_resolve_operands(), the handle is more completely + * validated here. + */ + + if ((!ddb_handle) || + (!VALID_DESCRIPTOR_TYPE (ddb_handle, ACPI_DESC_TYPE_INTERNAL)) || + (((ACPI_OPERAND_OBJECT *)ddb_handle)->common.type != + INTERNAL_TYPE_REFERENCE)) { + return (AE_BAD_PARAMETER); + } + + + /* Get the actual table descriptor from the Ddb_handle */ + + table_info = (ACPI_TABLE_DESC *) table_desc->reference.object; + + /* + * Delete the entire namespace under this table Node + * (Offset contains the Table_id) + */ + + status = acpi_ns_delete_namespace_by_owner (table_info->table_id); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Delete the table itself */ + + acpi_tb_uninstall_table (table_info->installed_desc); + + /* Delete the table descriptor (Ddb_handle) */ + + acpi_cm_remove_reference (table_desc); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_reconfiguration + * + * PARAMETERS: Opcode - The opcode to be executed + * Walk_state - Current state of the parse tree walk + * + * RETURN: Status + * + * DESCRIPTION: Reconfiguration opcodes such as LOAD and UNLOAD + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_reconfiguration ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *region_desc = NULL; + ACPI_HANDLE *ddb_handle; + + + /* Resolve the operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get the table handle, common for both opcodes */ + + status |= acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &ddb_handle, + walk_state); + + switch (opcode) { + + case AML_LOAD_OP: + + /* Get the region or field descriptor */ + + status |= acpi_ds_obj_stack_pop_object (®ion_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (region_desc); + return (status); + } + + status = acpi_aml_exec_load_table (region_desc, ddb_handle); + break; + + + case AML_UNLOAD_OP: + + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_aml_exec_unload_table (ddb_handle); + break; + + + default: + + status = AE_AML_BAD_OPCODE; + break; + } + + + return (status); +} + diff --git a/drivers/bus/acpi/executer/amconvrt.c b/drivers/bus/acpi/executer/amconvrt.c new file mode 100644 index 0000000..dade2fc --- /dev/null +++ b/drivers/bus/acpi/executer/amconvrt.c @@ -0,0 +1,518 @@ +/****************************************************************************** + * + * Module Name: amconvrt - Object conversion routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amconvrt") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_convert_to_integer + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to an integer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_convert_to_integer ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + u32 i; + ACPI_OPERAND_OBJECT *ret_desc; + u32 count; + char *pointer; + ACPI_INTEGER result; + u32 integer_size = sizeof (ACPI_INTEGER); + + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_INTEGER: + return (AE_OK); + + case ACPI_TYPE_STRING: + pointer = (*obj_desc)->string.pointer; + count = (*obj_desc)->string.length; + break; + + case ACPI_TYPE_BUFFER: + pointer = (char *) (*obj_desc)->buffer.pointer; + count = (*obj_desc)->buffer.length; + break; + + default: + return (AE_TYPE); + } + + /* + * Create a new integer + */ + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + + /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ + + if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper 32-bit field + */ + integer_size = sizeof (u32); + } + + + /* + * Convert the buffer/string to an integer. Note that both buffers and + * strings are treated as raw data - we don't convert ascii to hex for + * strings. + * + * There are two terminating conditions for the loop: + * 1) The size of an integer has been reached, or + * 2) The end of the buffer or string has been reached + */ + result = 0; + + /* Transfer no more than an integer's worth of data */ + + if (count > integer_size) { + count = integer_size; + } + + /* + * String conversion is different than Buffer conversion + */ + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_STRING: + + /* TBD: Need to use 64-bit STRTOUL */ + + /* + * Convert string to an integer + * String must be hexadecimal as per the ACPI specification + */ + + result = STRTOUL (pointer, NULL, 16); + break; + + + case ACPI_TYPE_BUFFER: + + /* + * Buffer conversion - we simply grab enough raw data from the + * buffer to fill an integer + */ + for (i = 0; i < count; i++) { + /* + * Get next byte and shift it into the Result. + * Little endian is used, meaning that the first byte of the buffer + * is the LSB of the integer + */ + result |= (((ACPI_INTEGER) pointer[i]) << (i * 8)); + } + + break; + } + + /* Save the Result, delete original descriptor, store new descriptor */ + + ret_desc->integer.value = result; + + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } + + *obj_desc = ret_desc; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_convert_to_buffer + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to an Buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_convert_to_buffer ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *ret_desc; + u32 i; + u32 integer_size = sizeof (ACPI_INTEGER); + u8 *new_buf; + + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_INTEGER: + + /* + * Create a new Buffer + */ + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ + + if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper + * 32-bit field + */ + integer_size = sizeof (u32); + } + + /* Need enough space for one integers */ + + ret_desc->buffer.length = integer_size; + new_buf = acpi_cm_callocate (integer_size); + if (!new_buf) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); + acpi_cm_remove_reference (ret_desc); + return (AE_NO_MEMORY); + } + + /* Copy the integer to the buffer */ + + for (i = 0; i < integer_size; i++) { + new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8)); + } + ret_desc->buffer.pointer = new_buf; + + /* Return the new buffer descriptor */ + + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; + break; + + + case ACPI_TYPE_STRING: + break; + + + case ACPI_TYPE_BUFFER: + break; + + + default: + return (AE_TYPE); + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_convert_to_string + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: Convert an ACPI Object to a string + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_convert_to_string ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *ret_desc; + u32 i; + u32 index; + u32 integer_size = sizeof (ACPI_INTEGER); + u8 *new_buf; + u8 *pointer; + + + switch ((*obj_desc)->common.type) { + case ACPI_TYPE_INTEGER: + + /* + * Create a new String + */ + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ + + if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper + * 32-bit field + */ + integer_size = sizeof (u32); + } + + /* Need enough space for one ASCII integer plus null terminator */ + + ret_desc->string.length = (integer_size * 2) + 1; + new_buf = acpi_cm_callocate (ret_desc->string.length); + if (!new_buf) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); + acpi_cm_remove_reference (ret_desc); + return (AE_NO_MEMORY); + } + + /* Copy the integer to the buffer */ + + for (i = 0; i < (integer_size * 2); i++) { + new_buf[i] = acpi_gbl_hex_to_ascii [((*obj_desc)->integer.value >> (i * 4)) & 0xF]; + } + + /* Null terminate */ + + new_buf [i] = 0; + ret_desc->buffer.pointer = new_buf; + + /* Return the new buffer descriptor */ + + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; + + return (AE_OK); + + + case ACPI_TYPE_BUFFER: + + if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) { + return (AE_AML_STRING_LIMIT); + } + + /* + * Create a new String + */ + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Need enough space for one ASCII integer plus null terminator */ + + ret_desc->string.length = (*obj_desc)->buffer.length * 3; + new_buf = acpi_cm_callocate (ret_desc->string.length + 1); + if (!new_buf) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); + acpi_cm_remove_reference (ret_desc); + return (AE_NO_MEMORY); + } + + /* + * Convert each byte of the buffer to two ASCII characters plus a space. + */ + pointer = (*obj_desc)->buffer.pointer; + index = 0; + for (i = 0; i < (*obj_desc)->buffer.length; i++) { + new_buf[index + 0] = acpi_gbl_hex_to_ascii [pointer[i] & 0x0F]; + new_buf[index + 1] = acpi_gbl_hex_to_ascii [(pointer[i] >> 4) & 0x0F]; + new_buf[index + 2] = ' '; + index += 3; + } + + /* Null terminate */ + + new_buf [index] = 0; + ret_desc->buffer.pointer = new_buf; + + /* Return the new buffer descriptor */ + + if (walk_state->opcode != AML_STORE_OP) { + acpi_cm_remove_reference (*obj_desc); + } + *obj_desc = ret_desc; + break; + + + case ACPI_TYPE_STRING: + break; + + + default: + return (AE_TYPE); + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_convert_to_target_type + * + * PARAMETERS: *Obj_desc - Object to be converted. + * Walk_state - Current method state + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_convert_to_target_type ( + OBJECT_TYPE_INTERNAL destination_type, + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + /* + * If required by the target, + * perform implicit conversion on the source before we store it. + */ + + switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) { + case ARGI_SIMPLE_TARGET: + case ARGI_FIXED_TARGET: + case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ + + switch (destination_type) { + case INTERNAL_TYPE_DEF_FIELD: + /* + * Named field can always handle conversions + */ + break; + + default: + /* No conversion allowed for these types */ + + if (destination_type != (*obj_desc)->common.type) { + status = AE_TYPE; + } + } + break; + + + case ARGI_TARGETREF: + + switch (destination_type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_FIELD_UNIT: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + /* + * These types require an Integer operand. We can convert + * a Buffer or a String to an Integer if necessary. + */ + status = acpi_aml_convert_to_integer (obj_desc, walk_state); + break; + + + case ACPI_TYPE_STRING: + + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = acpi_aml_convert_to_string (obj_desc, walk_state); + break; + + + case ACPI_TYPE_BUFFER: + + /* + * The operand must be a String. We can convert an + * Integer or Buffer if necessary + */ + status = acpi_aml_convert_to_buffer (obj_desc, walk_state); + break; + } + break; + + + case ARGI_REFERENCE: + /* + * Create_xxxx_field cases - we are storing the field object into the name + */ + break; + + + default: + status = AE_AML_INTERNAL; + } + + + /* + * Source-to-Target conversion semantics: + * + * If conversion to the target type cannot be performed, then simply + * overwrite the target with the new object and type. + */ + if (status == AE_TYPE) { + status = AE_OK; + } + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amcreate.c b/drivers/bus/acpi/executer/amcreate.c new file mode 100644 index 0000000..d599a54 --- /dev/null +++ b/drivers/bus/acpi/executer/amcreate.c @@ -0,0 +1,720 @@ +/****************************************************************************** + * + * Module Name: amcreate - Named object creation + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acevents.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amcreate") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_create_field + * + * PARAMETERS: Opcode - The opcode to be executed + * Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Execute Create_field operators: Create_bit_field_op, + * Create_byte_field_op, Create_word_field_op, Create_dWord_field_op, + * Create_field_op (which define fields in buffers) + * + * ALLOCATION: Deletes Create_field_op's count operand descriptor + * + * + * ACPI SPECIFICATION REFERENCES: + * Def_create_bit_field := Create_bit_field_op Src_buf Bit_idx Name_string + * Def_create_byte_field := Create_byte_field_op Src_buf Byte_idx Name_string + * Def_create_dWord_field := Create_dWord_field_op Src_buf Byte_idx Name_string + * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string + * Def_create_word_field := Create_word_field_op Src_buf Byte_idx Name_string + * Bit_index := Term_arg=>Integer + * Byte_index := Term_arg=>Integer + * Num_bits := Term_arg=>Integer + * Source_buff := Term_arg=>Buffer + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_aml_exec_create_field ( + u8 *aml_ptr, + u32 aml_length, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *tmp_desc; + + + /* Create the region descriptor */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_FIELD_UNIT); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Construct the field object */ + + obj_desc->field_unit.access = (u8) ACCESS_ANY_ACC; + obj_desc->field_unit.lock_rule = (u8) GLOCK_NEVER_LOCK; + obj_desc->field_unit.update_rule = (u8) UPDATE_PRESERVE; + + /* + * Allocate a method object for this field unit + */ + + obj_desc->field_unit.extra = acpi_cm_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->field_unit.extra) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of the field unit + * opcode and operands -- since the buffer and index + * operands must be evaluated. + */ + + obj_desc->field_unit.extra->extra.pcode = aml_ptr; + obj_desc->field_unit.extra->extra.pcode_length = aml_length; + obj_desc->field_unit.node = node; + + + /* + * This operation is supposed to cause the destination Name to refer + * to the defined Field_unit -- it must not store the constructed + * Field_unit object (or its current value) in some location that the + * Name may already be pointing to. So, if the Name currently contains + * a reference which would cause Acpi_aml_exec_store() to perform an indirect + * store rather than setting the value of the Name itself, clobber that + * reference before calling Acpi_aml_exec_store(). + */ + + /* Type of Name's existing value */ + + switch (acpi_ns_get_type (node)) { + + case ACPI_TYPE_FIELD_UNIT: + + case INTERNAL_TYPE_ALIAS: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_DEF_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + tmp_desc = acpi_ns_get_attached_object (node); + if (tmp_desc) { + /* + * There is an existing object here; delete it and zero out the + * object field within the Node + */ + + acpi_cm_remove_reference (tmp_desc); + acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) node, NULL, + ACPI_TYPE_ANY); + } + + /* Set the type to ANY (or the store below will fail) */ + + ((ACPI_NAMESPACE_NODE *) node)->type = ACPI_TYPE_ANY; + + break; + + + default: + + break; + } + + + /* Store constructed field descriptor in result location */ + + status = acpi_aml_exec_store (obj_desc, (ACPI_OPERAND_OBJECT *) node, walk_state); + + /* + * If the field descriptor was not physically stored (or if a failure + * above), we must delete it + */ + if (obj_desc->common.reference_count <= 1) { + acpi_cm_remove_reference (obj_desc); + } + + + return (AE_OK); + + +cleanup: + + /* Delete region object and method subobject */ + + if (obj_desc) { + /* Remove deletes both objects! */ + + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_alias + * + * PARAMETERS: Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Create a new named alias + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_alias ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_NAMESPACE_NODE *source_node; + ACPI_NAMESPACE_NODE *alias_node; + ACPI_STATUS status; + + + /* Get the source/alias operands (both NTEs) */ + + status = acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &source_node, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Don't pop it, it gets removed in the calling routine + */ + + alias_node = acpi_ds_obj_stack_get_value (0, walk_state); + + /* Add an additional reference to the object */ + + acpi_cm_add_reference (source_node->object); + + /* + * Attach the original source Node to the new Alias Node. + */ + status = acpi_ns_attach_object (alias_node, source_node->object, + source_node->type); + + + /* + * The new alias assumes the type of the source, but it points + * to the same object. The reference count of the object has two + * additional references to prevent deletion out from under either the + * source or the alias Node + */ + + /* Since both operands are NTEs, we don't need to delete them */ + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_event + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a new event object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_event ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + + + BREAKPOINT3; + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_EVENT); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS semaphore */ + + /* TBD: [Investigate] should be created with 0 or 1 units? */ + + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 1, + &obj_desc->event.semaphore); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + /* Attach object to the Node */ + + status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), + obj_desc, (u8) ACPI_TYPE_EVENT); + if (ACPI_FAILURE (status)) { + acpi_os_delete_semaphore (obj_desc->event.semaphore); + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + +cleanup: + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_mutex + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * Operands - List of operands for the opcode + * + * RETURN: Status + * + * DESCRIPTION: Create a new mutex object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_mutex ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *sync_desc; + ACPI_OPERAND_OBJECT *obj_desc; + + + /* Get the operand */ + + status = acpi_ds_obj_stack_pop_object (&sync_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Attempt to allocate a new object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_MUTEX); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Create the actual OS semaphore */ + + status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + obj_desc->mutex.sync_level = (u8) sync_desc->integer.value; + + /* Obj_desc was on the stack top, and the name is below it */ + + status = acpi_ns_attach_object (acpi_ds_obj_stack_get_value (0, walk_state), + obj_desc, (u8) ACPI_TYPE_MUTEX); + if (ACPI_FAILURE (status)) { + acpi_os_delete_semaphore (obj_desc->mutex.semaphore); + acpi_cm_remove_reference (obj_desc); + goto cleanup; + } + + +cleanup: + + /* Always delete the operand */ + + acpi_cm_remove_reference (sync_desc); + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_region + * + * PARAMETERS: Aml_ptr - Pointer to the region declaration AML + * Aml_length - Max length of the declaration AML + * Operands - List of operands for the opcode + * Interpreter_mode - Load1/Load2/Execute + * + * RETURN: Status + * + * DESCRIPTION: Create a new operation region object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_region ( + u8 *aml_ptr, + u32 aml_length, + u8 region_space, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *node; + + + /* + * Space ID must be one of the predefined IDs, or in the user-defined + * range + */ + if ((region_space >= NUM_REGION_TYPES) && + (region_space < USER_REGION_BEGIN)) { + REPORT_ERROR (("Invalid Address_space type %X\n", region_space)); + return (AE_AML_INVALID_SPACE_ID); + } + + + /* Get the Node from the object stack */ + + node = (ACPI_NAMESPACE_NODE *) acpi_ds_obj_stack_get_value (0, walk_state); + + /* Create the region descriptor */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_REGION); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Allocate a method object for this region. + */ + + obj_desc->region.extra = acpi_cm_create_internal_object ( + INTERNAL_TYPE_EXTRA); + if (!obj_desc->region.extra) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Remember location in AML stream of address & length + * operands since they need to be evaluated at run time. + */ + + obj_desc->region.extra->extra.pcode = aml_ptr; + obj_desc->region.extra->extra.pcode_length = aml_length; + + /* Init the region from the operands */ + + obj_desc->region.space_id = region_space; + obj_desc->region.address = 0; + obj_desc->region.length = 0; + + + /* Install the new region object in the parent Node */ + + obj_desc->region.node = node; + + status = acpi_ns_attach_object (node, obj_desc, + (u8) ACPI_TYPE_REGION); + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * If we have a valid region, initialize it + * Namespace is NOT locked at this point. + */ + + status = acpi_ev_initialize_region (obj_desc, FALSE); + + if (ACPI_FAILURE (status)) { + /* + * If AE_NOT_EXIST is returned, it is not fatal + * because many regions get created before a handler + * is installed for said region. + */ + if (AE_NOT_EXIST == status) { + status = AE_OK; + } + } + +cleanup: + + if (ACPI_FAILURE (status)) { + /* Delete region object and method subobject */ + + if (obj_desc) { + /* Remove deletes both objects! */ + + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_processor + * + * PARAMETERS: Op - Op containing the Processor definition and + * args + * Processor_nTE - Node for the containing Node + * + * RETURN: Status + * + * DESCRIPTION: Create a new processor object and populate the fields + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_processor ( + ACPI_PARSE_OBJECT *op, + ACPI_HANDLE processor_nTE) +{ + ACPI_STATUS status; + ACPI_PARSE_OBJECT *arg; + ACPI_OPERAND_OBJECT *obj_desc; + + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PROCESSOR); + if (!obj_desc) { + status = AE_NO_MEMORY; + return (status); + } + + /* Install the new processor object in the parent Node */ + + status = acpi_ns_attach_object (processor_nTE, obj_desc, + (u8) ACPI_TYPE_PROCESSOR); + if (ACPI_FAILURE (status)) { + return(status); + } + + arg = op->value.arg; + + /* check existence */ + + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* First arg is the Processor ID */ + + obj_desc->processor.proc_id = (u8) arg->value.integer; + + /* Move to next arg and check existence */ + + arg = arg->next; + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* Second arg is the PBlock Address */ + + obj_desc->processor.address = (ACPI_IO_ADDRESS) arg->value.integer; + + /* Move to next arg and check existence */ + + arg = arg->next; + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* Third arg is the PBlock Length */ + + obj_desc->processor.length = (u8) arg->value.integer; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_power_resource + * + * PARAMETERS: Op - Op containing the Power_resource definition + * and args + * Power_res_nTE - Node for the containing Node + * + * RETURN: Status + * + * DESCRIPTION: Create a new Power_resource object and populate the fields + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_power_resource ( + ACPI_PARSE_OBJECT *op, + ACPI_HANDLE power_res_nTE) +{ + ACPI_STATUS status; + ACPI_PARSE_OBJECT *arg; + ACPI_OPERAND_OBJECT *obj_desc; + + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_POWER); + if (!obj_desc) { + status = AE_NO_MEMORY; + return (status); + } + + /* Install the new power resource object in the parent Node */ + + status = acpi_ns_attach_object (power_res_nTE, obj_desc, + (u8) ACPI_TYPE_POWER); + if (ACPI_FAILURE (status)) { + return(status); + } + + arg = op->value.arg; + + /* check existence */ + + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* First arg is the System_level */ + + obj_desc->power_resource.system_level = (u8) arg->value.integer; + + /* Move to next arg and check existence */ + + arg = arg->next; + if (!arg) { + status = AE_AML_NO_OPERAND; + return (status); + } + + /* Second arg is the PBlock Address */ + + obj_desc->power_resource.resource_order = (u16) arg->value.integer; + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_exec_create_method + * + * PARAMETERS: Aml_ptr - First byte of the method's AML + * Aml_length - AML byte count for this method + * Method_flags - AML method flag byte + * Method - Method Node + * + * RETURN: Status + * + * DESCRIPTION: Create a new method object + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_create_method ( + u8 *aml_ptr, + u32 aml_length, + u32 method_flags, + ACPI_HANDLE method) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Create a new method object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_METHOD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Get the method's AML pointer/length from the Op */ + + obj_desc->method.pcode = aml_ptr; + obj_desc->method.pcode_length = aml_length; + + /* + * First argument is the Method Flags (contains parameter count for the + * method) + */ + + obj_desc->method.method_flags = (u8) method_flags; + obj_desc->method.param_count = (u8) (method_flags & + METHOD_FLAGS_ARG_COUNT); + + /* + * Get the concurrency count. If required, a semaphore will be + * created for this method when it is parsed. + */ + if (method_flags & METHOD_FLAGS_SERIALIZED) { + /* + * ACPI 1.0: Concurrency = 1 + * ACPI 2.0: Concurrency = (Sync_level (in method declaration) + 1) + */ + obj_desc->method.concurrency = (u8) + (((method_flags & METHOD_FLAGS_SYNCH_LEVEL) >> 4) + 1); + } + + else { + obj_desc->method.concurrency = INFINITE_CONCURRENCY; + } + + /* Attach the new object to the method Node */ + + status = acpi_ns_attach_object (method, obj_desc, (u8) ACPI_TYPE_METHOD); + if (ACPI_FAILURE (status)) { + acpi_cm_delete_object_desc (obj_desc); + } + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amdump.c b/drivers/bus/acpi/executer/amdump.c new file mode 100644 index 0000000..f0d0bc0 --- /dev/null +++ b/drivers/bus/acpi/executer/amdump.c @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Module Name: amdump - Interpreter debug output routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amdump") + + +/* + * The following routines are used for debug output only + */ + + diff --git a/drivers/bus/acpi/executer/amdyadic.c b/drivers/bus/acpi/executer/amdyadic.c new file mode 100644 index 0000000..84791e0 --- /dev/null +++ b/drivers/bus/acpi/executer/amdyadic.c @@ -0,0 +1,875 @@ +/****************************************************************************** + * + * Module Name: amdyadic - ACPI AML (p-code) execution for dyadic operators + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acevents.h" +#include "amlcode.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amdyadic") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_do_concatenate + * + * PARAMETERS: *Obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * + * RETURN: Status + * + * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_do_concatenate ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *obj_desc2, + ACPI_OPERAND_OBJECT **actual_ret_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + u32 i; + ACPI_INTEGER this_integer; + ACPI_OPERAND_OBJECT *ret_desc; + NATIVE_CHAR *new_buf; + u32 integer_size = sizeof (ACPI_INTEGER); + + + /* + * There are three cases to handle: + * 1) Two Integers concatenated to produce a buffer + * 2) Two Strings concatenated to produce a string + * 3) Two Buffers concatenated to produce a buffer + */ + switch (obj_desc->common.type) { + case ACPI_TYPE_INTEGER: + + /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */ + + if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper + * 32-bit field + */ + integer_size = sizeof (u32); + } + + /* Result of two integers is a buffer */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Need enough space for two integers */ + + ret_desc->buffer.length = integer_size * 2; + new_buf = acpi_cm_callocate (ret_desc->buffer.length); + if (!new_buf) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->buffer.pointer = (u8 *) new_buf; + + /* Convert the first integer */ + + this_integer = obj_desc->integer.value; + for (i = 0; i < integer_size; i++) { + new_buf[i] = (u8) this_integer; + this_integer >>= 8; + } + + /* Convert the second integer */ + + this_integer = obj_desc2->integer.value; + for (; i < (integer_size * 2); i++) { + new_buf[i] = (u8) this_integer; + this_integer >>= 8; + } + + break; + + + case ACPI_TYPE_STRING: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + /* Operand1 is string */ + + new_buf = acpi_cm_allocate (obj_desc->string.length + + obj_desc2->string.length + 1); + if (!new_buf) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + STRCPY (new_buf, obj_desc->string.pointer); + STRCPY (new_buf + obj_desc->string.length, + obj_desc2->string.pointer); + + /* Point the return object to the new string */ + + ret_desc->string.pointer = new_buf; + ret_desc->string.length = obj_desc->string.length += + obj_desc2->string.length; + break; + + + case ACPI_TYPE_BUFFER: + + /* Operand1 is a buffer */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER); + if (!ret_desc) { + return (AE_NO_MEMORY); + } + + new_buf = acpi_cm_allocate (obj_desc->buffer.length + + obj_desc2->buffer.length); + if (!new_buf) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n")); + status = AE_NO_MEMORY; + goto cleanup; + } + + MEMCPY (new_buf, obj_desc->buffer.pointer, + obj_desc->buffer.length); + MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer, + obj_desc2->buffer.length); + + /* + * Point the return object to the new buffer + */ + + ret_desc->buffer.pointer = (u8 *) new_buf; + ret_desc->buffer.length = obj_desc->buffer.length + + obj_desc2->buffer.length; + break; + + default: + status = AE_AML_INTERNAL; + ret_desc = NULL; + } + + + *actual_ret_desc = ret_desc; + return (AE_OK); + + +cleanup: + + acpi_cm_remove_reference (ret_desc); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_dyadic1 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 dyadic operator with numeric operands: + * Notify_op + * + * ALLOCATION: Deletes both operands + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_OPERAND_OBJECT *val_desc = NULL; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status = AE_OK; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get the operands */ + + status |= acpi_ds_obj_stack_pop_object (&val_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Examine the opcode */ + + switch (opcode) { + + /* Def_notify := Notify_op Notify_object Notify_value */ + + case AML_NOTIFY_OP: + + /* The Obj_desc is actually an Node */ + + node = (ACPI_NAMESPACE_NODE *) obj_desc; + obj_desc = NULL; + + /* Object must be a device or thermal zone */ + + if (node && val_desc) { + switch (node->type) { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* + * Dispatch the notify to the appropriate handler + * NOTE: the request is queued for execution after this method + * completes. The notify handlers are NOT invoked synchronously + * from this thread -- because handlers may in turn run other + * control methods. + */ + + status = acpi_ev_queue_notify_request (node, + (u32) val_desc->integer.value); + break; + + default: + status = AE_AML_OPERAND_TYPE; + break; + } + } + break; + + default: + + REPORT_ERROR (("Acpi_aml_exec_dyadic1: Unknown dyadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + } + + +cleanup: + + /* Always delete both operands */ + + acpi_cm_remove_reference (val_desc); + acpi_cm_remove_reference (obj_desc); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_dyadic2_r + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and + * one or two result operands. + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_OPERAND_OBJECT *obj_desc2 = NULL; + ACPI_OPERAND_OBJECT *res_desc = NULL; + ACPI_OPERAND_OBJECT *res_desc2 = NULL; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_OPERAND_OBJECT *ret_desc2 = NULL; + ACPI_STATUS status = AE_OK; + u32 num_operands = 3; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + if (AML_DIVIDE_OP == opcode) { + num_operands = 4; + status |= acpi_ds_obj_stack_pop_object (&res_desc2, walk_state); + } + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Create an internal return object if necessary */ + + switch (opcode) { + case AML_ADD_OP: + case AML_BIT_AND_OP: + case AML_BIT_NAND_OP: + case AML_BIT_OR_OP: + case AML_BIT_NOR_OP: + case AML_BIT_XOR_OP: + case AML_DIVIDE_OP: + case AML_MULTIPLY_OP: + case AML_SHIFT_LEFT_OP: + case AML_SHIFT_RIGHT_OP: + case AML_SUBTRACT_OP: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + break; + } + + + /* + * Execute the opcode + */ + + switch (opcode) { + + /* Def_add := Add_op Operand1 Operand2 Result */ + + case AML_ADD_OP: + + ret_desc->integer.value = obj_desc->integer.value + + obj_desc2->integer.value; + break; + + + /* Def_and := And_op Operand1 Operand2 Result */ + + case AML_BIT_AND_OP: + + ret_desc->integer.value = obj_desc->integer.value & + obj_desc2->integer.value; + break; + + + /* Def_nAnd := NAnd_op Operand1 Operand2 Result */ + + case AML_BIT_NAND_OP: + + ret_desc->integer.value = ~(obj_desc->integer.value & + obj_desc2->integer.value); + break; + + + /* Def_or := Or_op Operand1 Operand2 Result */ + + case AML_BIT_OR_OP: + + ret_desc->integer.value = obj_desc->integer.value | + obj_desc2->integer.value; + break; + + + /* Def_nOr := NOr_op Operand1 Operand2 Result */ + + case AML_BIT_NOR_OP: + + ret_desc->integer.value = ~(obj_desc->integer.value | + obj_desc2->integer.value); + break; + + + /* Def_xOr := XOr_op Operand1 Operand2 Result */ + + case AML_BIT_XOR_OP: + + ret_desc->integer.value = obj_desc->integer.value ^ + obj_desc2->integer.value; + break; + + + /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */ + + case AML_DIVIDE_OP: + + if (!obj_desc2->integer.value) { + REPORT_ERROR + (("Aml_exec_dyadic2_r/Divide_op: Divide by zero\n")); + + status = AE_AML_DIVIDE_BY_ZERO; + goto cleanup; + } + + ret_desc2 = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc2) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Remainder (modulo) */ + + ret_desc->integer.value = ACPI_MODULO (obj_desc->integer.value, + obj_desc2->integer.value); + + /* Result (what we used to call the quotient) */ + + ret_desc2->integer.value = ACPI_DIVIDE (obj_desc->integer.value, + obj_desc2->integer.value); + break; + + + /* Def_multiply := Multiply_op Operand1 Operand2 Result */ + + case AML_MULTIPLY_OP: + + ret_desc->integer.value = obj_desc->integer.value * + obj_desc2->integer.value; + break; + + + /* Def_shift_left := Shift_left_op Operand Shift_count Result */ + + case AML_SHIFT_LEFT_OP: + + ret_desc->integer.value = obj_desc->integer.value << + obj_desc2->integer.value; + break; + + + /* Def_shift_right := Shift_right_op Operand Shift_count Result */ + + case AML_SHIFT_RIGHT_OP: + + ret_desc->integer.value = obj_desc->integer.value >> + obj_desc2->integer.value; + break; + + + /* Def_subtract := Subtract_op Operand1 Operand2 Result */ + + case AML_SUBTRACT_OP: + + ret_desc->integer.value = obj_desc->integer.value - + obj_desc2->integer.value; + break; + + + /* Def_concat := Concat_op Data1 Data2 Result */ + + case AML_CONCAT_OP: + + + /* + * Convert the second operand if necessary. The first operand + * determines the type of the second operand, (See the Data Types + * section of the ACPI specification.) Both object types are + * guaranteed to be either Integer/String/Buffer by the operand + * resolution mechanism above. + */ + + switch (obj_desc->common.type) { + case ACPI_TYPE_INTEGER: + status = acpi_aml_convert_to_integer (&obj_desc2, walk_state); + break; + + case ACPI_TYPE_STRING: + status = acpi_aml_convert_to_string (&obj_desc2, walk_state); + break; + + case ACPI_TYPE_BUFFER: + status = acpi_aml_convert_to_buffer (&obj_desc2, walk_state); + break; + + default: + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* + * Both operands are now known to be the same object type + * (Both are Integer, String, or Buffer), and we can now perform the + * concatenation. + */ + status = acpi_aml_do_concatenate (obj_desc, obj_desc2, &ret_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + break; + + + default: + + REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Store the result of the operation (which is now in Obj_desc) into + * the result descriptor, or the location pointed to by the result + * descriptor (Res_desc). + */ + + status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + if (AML_DIVIDE_OP == opcode) { + status = acpi_aml_exec_store (ret_desc2, res_desc2, walk_state); + + /* + * Since the remainder is not returned, remove a reference to + * the object we created earlier + */ + + acpi_cm_remove_reference (ret_desc2); + } + + +cleanup: + + /* Always delete the operands */ + + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (obj_desc2); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + /* On failure, delete the result ops */ + + acpi_cm_remove_reference (res_desc); + acpi_cm_remove_reference (res_desc2); + + if (ret_desc) { + /* And delete the internal return object */ + + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_dyadic2_s + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic synchronization operator + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic2_s ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *time_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS status; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&time_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* Default return value is FALSE, operation did not time out */ + + ret_desc->integer.value = 0; + + + /* Examine the opcode */ + + switch (opcode) { + + /* Def_acquire := Acquire_op Mutex_object Timeout */ + + case AML_ACQUIRE_OP: + + status = acpi_aml_acquire_mutex (time_desc, obj_desc, walk_state); + break; + + + /* Def_wait := Wait_op Acpi_event_object Timeout */ + + case AML_WAIT_OP: + + status = acpi_aml_system_wait_event (time_desc, obj_desc); + break; + + + default: + + REPORT_ERROR (("Acpi_aml_exec_dyadic2_s: Unknown dyadic synchronization opcode %X\n", opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + /* + * Return a boolean indicating if operation timed out + * (TRUE) or not (FALSE) + */ + + if (status == AE_TIME) { + ret_desc->integer.value = ACPI_INTEGER_MAX; /* TRUE, op timed out */ + status = AE_OK; + } + + +cleanup: + + /* Delete params */ + + acpi_cm_remove_reference (time_desc); + acpi_cm_remove_reference (obj_desc); + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_dyadic2 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and + * no result operands + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * containing result value + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_dyadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *obj_desc2; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS status; + u8 lboolean; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc2, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + /* + * Execute the Opcode + */ + + lboolean = FALSE; + switch (opcode) { + + /* Def_lAnd := LAnd_op Operand1 Operand2 */ + + case AML_LAND_OP: + + lboolean = (u8) (obj_desc->integer.value && + obj_desc2->integer.value); + break; + + + /* Def_lEqual := LEqual_op Operand1 Operand2 */ + + case AML_LEQUAL_OP: + + lboolean = (u8) (obj_desc->integer.value == + obj_desc2->integer.value); + break; + + + /* Def_lGreater := LGreater_op Operand1 Operand2 */ + + case AML_LGREATER_OP: + + lboolean = (u8) (obj_desc->integer.value > + obj_desc2->integer.value); + break; + + + /* Def_lLess := LLess_op Operand1 Operand2 */ + + case AML_LLESS_OP: + + lboolean = (u8) (obj_desc->integer.value < + obj_desc2->integer.value); + break; + + + /* Def_lOr := LOr_op Operand1 Operand2 */ + + case AML_LOR_OP: + + lboolean = (u8) (obj_desc->integer.value || + obj_desc2->integer.value); + break; + + + default: + + REPORT_ERROR (("Acpi_aml_exec_dyadic2: Unknown dyadic opcode %X\n", opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + break; + } + + + /* Set return value to logical TRUE (all ones) or FALSE (zero) */ + + if (lboolean) { + ret_desc->integer.value = ACPI_INTEGER_MAX; + } + else { + ret_desc->integer.value = 0; + } + + +cleanup: + + /* Always delete operands */ + + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (obj_desc2); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amfield.c b/drivers/bus/acpi/executer/amfield.c new file mode 100644 index 0000000..a7b28be --- /dev/null +++ b/drivers/bus/acpi/executer/amfield.c @@ -0,0 +1,279 @@ +/****************************************************************************** + * + * Module Name: amfield - ACPI AML (p-code) execution - field manipulation + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amfield") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_setup_field + * + * PARAMETERS: *Obj_desc - Field to be read or written + * *Rgn_desc - Region containing field + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Common processing for Acpi_aml_read_field and Acpi_aml_write_field + * + * ACPI SPECIFICATION REFERENCES: + * Each of the Type1_opcodes is defined as specified in in-line + * comments below. For each one, use the following definitions. + * + * Def_bit_field := Bit_field_op Src_buf Bit_idx Destination + * Def_byte_field := Byte_field_op Src_buf Byte_idx Destination + * Def_create_field := Create_field_op Src_buf Bit_idx Num_bits Name_string + * Def_dWord_field := DWord_field_op Src_buf Byte_idx Destination + * Def_word_field := Word_field_op Src_buf Byte_idx Destination + * Bit_index := Term_arg=>Integer + * Byte_index := Term_arg=>Integer + * Destination := Name_string + * Num_bits := Term_arg=>Integer + * Source_buf := Term_arg=>Buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_setup_field ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *rgn_desc, + u32 field_bit_width) +{ + ACPI_STATUS status = AE_OK; + u32 field_byte_width; + + + /* Parameter validation */ + + if (!obj_desc || !rgn_desc) { + return (AE_AML_NO_OPERAND); + } + + if (ACPI_TYPE_REGION != rgn_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* + * TBD: [Future] Acpi 2.0 supports Qword fields + * + * Init and validate Field width + * Possible values are 1, 2, 4 + */ + + field_byte_width = DIV_8 (field_bit_width); + + if ((field_bit_width != 8) && + (field_bit_width != 16) && + (field_bit_width != 32)) { + return (AE_AML_OPERAND_VALUE); + } + + + /* + * If the Region Address and Length have not been previously evaluated, + * evaluate them and save the results. + */ + if (!(rgn_desc->region.flags & AOPOBJ_DATA_VALID)) { + + status = acpi_ds_get_region_arguments (rgn_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + if ((obj_desc->common.type == ACPI_TYPE_FIELD_UNIT) && + (!(obj_desc->common.flags & AOPOBJ_DATA_VALID))) { + /* + * Field Buffer and Index have not been previously evaluated, + */ + return (AE_AML_INTERNAL); + } + + if (rgn_desc->region.length < + (obj_desc->field.offset & ~((u32) field_byte_width - 1)) + + field_byte_width) { + /* + * Offset rounded up to next multiple of field width + * exceeds region length, indicate an error + */ + + return (AE_AML_REGION_LIMIT); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_access_named_field + * + * PARAMETERS: Mode - ACPI_READ or ACPI_WRITE + * Named_field - Handle for field to be accessed + * *Buffer - Value(s) to be read or written + * Buffer_length - Number of bytes to transfer + * + * RETURN: Status + * + * DESCRIPTION: Read or write a named field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_access_named_field ( + u32 mode, + ACPI_HANDLE named_field, + void *buffer, + u32 buffer_length) +{ + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_STATUS status = AE_OK; + u8 locked = FALSE; + u32 bit_granularity = 0; + u32 byte_granularity; + u32 datum_length; + u32 actual_byte_length; + u32 byte_field_length; + + + /* Parameter validation */ + + if ((!named_field) || (ACPI_READ == mode && !buffer)) { + return (AE_AML_INTERNAL); + } + + /* Get the attached field object */ + + obj_desc = acpi_ns_get_attached_object (named_field); + if (!obj_desc) { + return (AE_AML_INTERNAL); + } + + /* Check the type */ + + if (INTERNAL_TYPE_DEF_FIELD != acpi_ns_get_type (named_field)) { + return (AE_AML_OPERAND_TYPE); + } + + /* Obj_desc valid and Named_field is a defined field */ + + + /* Double-check that the attached object is also a field */ + + if (INTERNAL_TYPE_DEF_FIELD != obj_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Granularity was decoded from the field access type + * (Any_acc will be the same as Byte_acc) + */ + + bit_granularity = obj_desc->field_unit.granularity; + byte_granularity = DIV_8 (bit_granularity); + + /* + * Check if request is too large for the field, and silently truncate + * if necessary + */ + + /* TBD: [Errors] should an error be returned in this case? */ + + byte_field_length = (u32) DIV_8 (obj_desc->field_unit.length + 7); + + + actual_byte_length = buffer_length; + if (buffer_length > byte_field_length) { + actual_byte_length = byte_field_length; + } + + /* TBD: should these round down to a power of 2? */ + + if (DIV_8 (bit_granularity) > byte_field_length) { + bit_granularity = MUL_8(byte_field_length); + } + + if (byte_granularity > byte_field_length) { + byte_granularity = byte_field_length; + } + + + /* Convert byte count to datum count, round up if necessary */ + + datum_length = (actual_byte_length + (byte_granularity-1)) / byte_granularity; + + + /* Get the global lock if needed */ + + locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); + + + /* Perform the actual read or write of the buffer */ + + switch (mode) { + case ACPI_READ: + + status = acpi_aml_read_field (obj_desc, buffer, buffer_length, + actual_byte_length, datum_length, + bit_granularity, byte_granularity); + break; + + + case ACPI_WRITE: + + status = acpi_aml_write_field (obj_desc, buffer, buffer_length, + actual_byte_length, datum_length, + bit_granularity, byte_granularity); + break; + + + default: + + status = AE_BAD_PARAMETER; + break; + } + + + /* Release global lock if we acquired it earlier */ + + acpi_aml_release_global_lock (locked); + + return (status); +} + diff --git a/drivers/bus/acpi/executer/amfldio.c b/drivers/bus/acpi/executer/amfldio.c new file mode 100644 index 0000000..5529555 --- /dev/null +++ b/drivers/bus/acpi/executer/amfldio.c @@ -0,0 +1,673 @@ +/****************************************************************************** + * + * Module Name: amfldio - Aml Field I/O + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amfldio") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_read_field_data + * + * PARAMETERS: *Obj_desc - Field to be read + * *Value - Where to store value + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_read_field_data ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 field_byte_offset, + u32 field_bit_width, + u32 *value) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *rgn_desc = NULL; + ACPI_PHYSICAL_ADDRESS address; + u32 local_value = 0; + u32 field_byte_width; + + + /* Obj_desc is validated by callers */ + + if (obj_desc) { + rgn_desc = obj_desc->field.container; + } + + + field_byte_width = DIV_8 (field_bit_width); + status = acpi_aml_setup_field (obj_desc, rgn_desc, field_bit_width); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Setup_field validated Rgn_desc and Field_bit_width */ + + if (!value) { + value = &local_value; /* support reads without saving value */ + } + + + /* + * Set offset to next multiple of field width, + * add region base address and offset within the field + */ + address = rgn_desc->region.address + + (obj_desc->field.offset * field_byte_width) + + field_byte_offset; + + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ, + address, field_bit_width, value); + + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_read_field + * + * PARAMETERS: *Obj_desc - Field to be read + * *Value - Where to store value + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value of the given field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_read_field ( + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity) +{ + ACPI_STATUS status; + u32 this_field_byte_offset; + u32 this_field_datum_offset; + u32 previous_raw_datum; + u32 this_raw_datum = 0; + u32 valid_field_bits; + u32 mask; + u32 merged_datum = 0; + + + /* + * Clear the caller's buffer (the whole buffer length as given) + * This is very important, especially in the cases where a byte is read, + * but the buffer is really a u32 (4 bytes). + */ + + MEMSET (buffer, 0, buffer_length); + + /* Read the first raw datum to prime the loop */ + + this_field_byte_offset = 0; + this_field_datum_offset= 0; + + status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, bit_granularity, + &previous_raw_datum); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* We might actually be done if the request fits in one datum */ + + if ((datum_length == 1) && + ((obj_desc->field.bit_offset + obj_desc->field_unit.length) <= + (u16) bit_granularity)) { + merged_datum = previous_raw_datum; + + merged_datum = (merged_datum >> obj_desc->field.bit_offset); + + valid_field_bits = obj_desc->field_unit.length % bit_granularity; + if (valid_field_bits) { + mask = (((u32) 1 << valid_field_bits) - (u32) 1); + merged_datum &= mask; + } + + + /* + * Place the Merged_datum into the proper format and return buffer + * field + */ + + switch (byte_granularity) { + case 1: + ((u8 *) buffer) [this_field_datum_offset] = (u8) merged_datum; + break; + + case 2: + MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer)[this_field_datum_offset]), &merged_datum); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer)[this_field_datum_offset]), &merged_datum); + break; + } + + this_field_byte_offset = 1; + this_field_datum_offset = 1; + } + + else { + /* We need to get more raw data to complete one or more field data */ + + while (this_field_datum_offset < datum_length) { + /* + * If the field is aligned on a byte boundary, we don't want + * to perform a final read, since this would potentially read + * past the end of the region. + * + * TBD: [Investigate] It may make more sense to just split the aligned + * and non-aligned cases since the aligned case is so very simple, + */ + if ((obj_desc->field.bit_offset != 0) || + ((obj_desc->field.bit_offset == 0) && + (this_field_datum_offset < (datum_length -1)))) { + /* + * Get the next raw datum, it contains some or all bits + * of the current field datum + */ + + status = acpi_aml_read_field_data (obj_desc, + this_field_byte_offset + byte_granularity, + bit_granularity, &this_raw_datum); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Before merging the data, make sure the unused bits are clear */ + + switch (byte_granularity) { + case 1: + this_raw_datum &= 0x000000FF; + previous_raw_datum &= 0x000000FF; + break; + + case 2: + this_raw_datum &= 0x0000FFFF; + previous_raw_datum &= 0x0000FFFF; + break; + } + } + + + /* + * Put together bits of the two raw data to make a complete + * field datum + */ + + + if (obj_desc->field.bit_offset != 0) { + merged_datum = + (previous_raw_datum >> obj_desc->field.bit_offset) | + (this_raw_datum << (bit_granularity - obj_desc->field.bit_offset)); + } + + else { + merged_datum = previous_raw_datum; + } + + /* + * Prepare the merged datum for storing into the caller's + * buffer. It is possible to have a 32-bit buffer + * (Byte_granularity == 4), but a Obj_desc->Field.Length + * of 8 or 16, meaning that the upper bytes of merged data + * are undesired. This section fixes that. + */ + switch (obj_desc->field.length) { + case 8: + merged_datum &= 0x000000FF; + break; + + case 16: + merged_datum &= 0x0000FFFF; + break; + } + + /* + * Now store the datum in the caller's buffer, according to + * the data type + */ + switch (byte_granularity) { + case 1: + ((u8 *) buffer) [this_field_datum_offset] = (u8) merged_datum; + break; + + case 2: + MOVE_UNALIGNED16_TO_16 (&(((u16 *) buffer) [this_field_datum_offset]), &merged_datum); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&(((u32 *) buffer) [this_field_datum_offset]), &merged_datum); + break; + } + + /* + * Save the most recent datum since it contains bits of + * the *next* field datum + */ + + previous_raw_datum = this_raw_datum; + + this_field_byte_offset += byte_granularity; + this_field_datum_offset++; + + } /* while */ + } + +cleanup: + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_write_field_data + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Store the value into the given field + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_aml_write_field_data ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 field_byte_offset, + u32 field_bit_width, + u32 value) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *rgn_desc = NULL; + ACPI_PHYSICAL_ADDRESS address; + u32 field_byte_width; + + + /* Obj_desc is validated by callers */ + + if (obj_desc) { + rgn_desc = obj_desc->field.container; + } + + field_byte_width = DIV_8 (field_bit_width); + status = acpi_aml_setup_field (obj_desc, rgn_desc, field_bit_width); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Set offset to next multiple of field width, + * add region base address and offset within the field + */ + address = rgn_desc->region.address + + (obj_desc->field.offset * field_byte_width) + + field_byte_offset; + + /* Invoke the appropriate Address_space/Op_region handler */ + + status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_WRITE, + address, field_bit_width, &value); + + + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_write_field_data_with_update_rule + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Apply the field update rule to a field write + * + ****************************************************************************/ + +static ACPI_STATUS +acpi_aml_write_field_data_with_update_rule ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 mask, + u32 field_value, + u32 this_field_byte_offset, + u32 bit_granularity) +{ + ACPI_STATUS status = AE_OK; + u32 merged_value; + u32 current_value; + + + /* Start with the new bits */ + + merged_value = field_value; + + + /* Decode the update rule */ + + switch (obj_desc->field.update_rule) { + + case UPDATE_PRESERVE: + + /* Check if update rule needs to be applied (not if mask is all ones) */ + + /* The left shift drops the bits we want to ignore. */ + if ((~mask << (sizeof(mask)*8 - bit_granularity)) != 0) { + /* + * Read the current contents of the byte/word/dword containing + * the field, and merge with the new field value. + */ + status = acpi_aml_read_field_data (obj_desc, this_field_byte_offset, + bit_granularity, ¤t_value); + merged_value |= (current_value & ~mask); + } + break; + + + case UPDATE_WRITE_AS_ONES: + + /* Set positions outside the field to all ones */ + + merged_value |= ~mask; + break; + + + case UPDATE_WRITE_AS_ZEROS: + + /* Set positions outside the field to all zeros */ + + merged_value &= mask; + break; + + + default: + status = AE_AML_OPERAND_VALUE; + } + + + /* Write the merged value */ + + if (ACPI_SUCCESS (status)) { + status = acpi_aml_write_field_data (obj_desc, this_field_byte_offset, + bit_granularity, merged_value); + } + + return (status); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_aml_write_field + * + * PARAMETERS: *Obj_desc - Field to be set + * Value - Value to store + * Field_bit_width - Field Width in bits (8, 16, or 32) + * + * RETURN: Status + * + * DESCRIPTION: Store the value into the given field + * + ****************************************************************************/ + +ACPI_STATUS +acpi_aml_write_field ( + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity) +{ + ACPI_STATUS status; + u32 this_field_byte_offset; + u32 this_field_datum_offset; + u32 mask; + u32 merged_datum; + u32 previous_raw_datum; + u32 this_raw_datum; + u32 field_value; + u32 valid_field_bits; + + + /* + * Break the request into up to three parts: + * non-aligned part at start, aligned part in middle, non-aligned part + * at end --- Just like an I/O request --- + */ + + this_field_byte_offset = 0; + this_field_datum_offset= 0; + + /* Get a datum */ + + switch (byte_granularity) { + case 1: + previous_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; + break; + + case 2: + MOVE_UNALIGNED16_TO_32 (&previous_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&previous_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); + break; + + default: + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + + /* + * Write a partial field datum if field does not begin on a datum boundary + * + * Construct Mask with 1 bits where the field is, 0 bits elsewhere + * + * 1) Bits above the field + */ + + mask = (((u32)(-1)) << (u32)obj_desc->field.bit_offset); + + /* 2) Only the bottom 5 bits are valid for a shift operation. */ + + if ((obj_desc->field.bit_offset + obj_desc->field_unit.length) < 32) { + /* Bits above the field */ + + mask &= (~(((u32)(-1)) << ((u32)obj_desc->field.bit_offset + + (u32)obj_desc->field_unit.length))); + } + + /* 3) Shift and mask the value into the field position */ + + field_value = (previous_raw_datum << obj_desc->field.bit_offset) & mask; + + status = acpi_aml_write_field_data_with_update_rule (obj_desc, mask, field_value, + this_field_byte_offset, + bit_granularity); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* If the field fits within one datum, we are done. */ + + if ((datum_length == 1) && + ((obj_desc->field.bit_offset + obj_desc->field_unit.length) <= + (u16) bit_granularity)) { + goto cleanup; + } + + /* + * We don't need to worry about the update rule for these data, because + * all of the bits are part of the field. + * + * Can't write the last datum, however, because it might contain bits that + * are not part of the field -- the update rule must be applied. + */ + + while (this_field_datum_offset < (datum_length - 1)) { + this_field_datum_offset++; + + /* Get the next raw datum, it contains bits of the current field datum... */ + + switch (byte_granularity) { + case 1: + this_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; + break; + + case 2: + MOVE_UNALIGNED16_TO_32 (&this_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&this_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); + break; + + default: + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + /* + * Put together bits of the two raw data to make a complete field + * datum + */ + + if (obj_desc->field.bit_offset != 0) { + merged_datum = + (previous_raw_datum >> (bit_granularity - obj_desc->field.bit_offset)) | + (this_raw_datum << obj_desc->field.bit_offset); + } + + else { + merged_datum = this_raw_datum; + } + + /* Now write the completed datum */ + + + status = acpi_aml_write_field_data (obj_desc, + this_field_byte_offset + byte_granularity, + bit_granularity, merged_datum); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* + * Save the most recent datum since it contains bits of + * the *next* field datum + */ + + previous_raw_datum = this_raw_datum; + + this_field_byte_offset += byte_granularity; + + } /* while */ + + + /* Write a partial field datum if field does not end on a datum boundary */ + + if ((obj_desc->field_unit.length + obj_desc->field_unit.bit_offset) % + bit_granularity) { + switch (byte_granularity) { + case 1: + this_raw_datum = ((u8 *) buffer) [this_field_datum_offset]; + break; + + case 2: + MOVE_UNALIGNED16_TO_32 (&this_raw_datum, &(((u16 *) buffer) [this_field_datum_offset])); + break; + + case 4: + MOVE_UNALIGNED32_TO_32 (&this_raw_datum, &(((u32 *) buffer) [this_field_datum_offset])); + break; + } + + /* Construct Mask with 1 bits where the field is, 0 bits elsewhere */ + + valid_field_bits = ((obj_desc->field_unit.length % bit_granularity) + + obj_desc->field.bit_offset); + + mask = (((u32) 1 << valid_field_bits) - (u32) 1); + + /* Shift and mask the value into the field position */ + + field_value = (previous_raw_datum >> + (bit_granularity - obj_desc->field.bit_offset)) & mask; + + status = acpi_aml_write_field_data_with_update_rule (obj_desc, mask, field_value, + this_field_byte_offset + byte_granularity, + bit_granularity); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + } + + +cleanup: + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/ammisc.c b/drivers/bus/acpi/executer/ammisc.c new file mode 100644 index 0000000..41d27f0 --- /dev/null +++ b/drivers/bus/acpi/executer/ammisc.c @@ -0,0 +1,513 @@ + +/****************************************************************************** + * + * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("ammisc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_fatal + * + * PARAMETERS: none + * + * RETURN: Status. If the OS returns from the OSD call, we just keep + * on going. + * + * DESCRIPTION: Execute Fatal operator + * + * ACPI SPECIFICATION REFERENCES: + * Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg + * Fatal_type := Byte_data + * Fatal_code := DWord_data + * Fatal_arg := Term_arg=>Integer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_fatal ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *type_desc; + ACPI_OPERAND_OBJECT *code_desc; + ACPI_OPERAND_OBJECT *arg_desc; + ACPI_STATUS status; + + + /* Resolve operands */ + + status = acpi_aml_resolve_operands (AML_FATAL_OP, WALK_OPERANDS, walk_state); + /* Get operands */ + + status |= acpi_ds_obj_stack_pop_object (&arg_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&code_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&type_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */ + + + /* + * TBD: [Unhandled] call OSD interface to notify OS of fatal error + * requiring shutdown! + */ + + +cleanup: + + /* Free the operands */ + + acpi_cm_remove_reference (arg_desc); + acpi_cm_remove_reference (code_desc); + acpi_cm_remove_reference (type_desc); + + + /* If we get back from the OS call, we might as well keep going. */ + + REPORT_WARNING (("An AML \"fatal\" Opcode (Fatal_op) was executed\n")); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_index + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Execute Index operator + * + * ALLOCATION: Deletes one operand descriptor -- other remains on stack + * + * ACPI SPECIFICATION REFERENCES: + * Def_index := Index_op Buff_pkg_obj Index_value Result + * Index_value := Term_arg=>Integer + * Name_string := | + * Result := Super_name + * Super_name := Name_string | Arg_obj | Local_obj | Debug_obj | Def_index + * Local4_op | Local5_op | Local6_op | Local7_op + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_index ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *idx_desc; + ACPI_OPERAND_OBJECT *res_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_OPERAND_OBJECT *tmp_desc; + ACPI_STATUS status; + + + /* Resolve operands */ + /* First operand can be either a package or a buffer */ + + status = acpi_aml_resolve_operands (AML_INDEX_OP, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&idx_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + + /* Create the internal return object */ + + ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + + /* + * At this point, the Obj_desc operand is either a Package or a Buffer + */ + + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + /* Object to be indexed is a Package */ + + if (idx_desc->integer.value >= obj_desc->package.count) { + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) && + (res_desc->reference.opcode == AML_ZERO_OP)) { + /* + * There is no actual result descriptor (the Zero_op Result + * descriptor is a placeholder), so just delete the placeholder and + * return a reference to the package element + */ + + acpi_cm_remove_reference (res_desc); + } + + else { + /* + * Each element of the package is an internal object. Get the one + * we are after. + */ + + tmp_desc = obj_desc->package.elements[idx_desc->integer.value]; + ret_desc->reference.opcode = AML_INDEX_OP; + ret_desc->reference.target_type = tmp_desc->common.type; + ret_desc->reference.object = tmp_desc; + + status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); + ret_desc->reference.object = NULL; + } + + /* + * The local return object must always be a reference to the package element, + * not the element itself. + */ + ret_desc->reference.opcode = AML_INDEX_OP; + ret_desc->reference.target_type = ACPI_TYPE_PACKAGE; + ret_desc->reference.where = &obj_desc->package.elements[idx_desc->integer.value]; + } + + else { + /* Object to be indexed is a Buffer */ + + if (idx_desc->integer.value >= obj_desc->buffer.length) { + status = AE_AML_BUFFER_LIMIT; + goto cleanup; + } + + ret_desc->reference.opcode = AML_INDEX_OP; + ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD; + ret_desc->reference.object = obj_desc; + ret_desc->reference.offset = (u32) idx_desc->integer.value; + + status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); + } + + +cleanup: + + /* Always delete operands */ + + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (idx_desc); + + /* Delete return object on error */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); + + if (ret_desc) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_match + * + * PARAMETERS: none + * + * RETURN: Status + * + * DESCRIPTION: Execute Match operator + * + * ACPI SPECIFICATION REFERENCES: + * Def_match := Match_op Search_pkg Opcode1 Operand1 + * Opcode2 Operand2 Start_index + * Opcode1 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT + * Opcode2 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT + * Operand1 := Term_arg=>Integer + * Operand2 := Term_arg=>Integer + * Search_pkg := Term_arg=>Package_object + * Start_index := Term_arg=>Integer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_match ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *pkg_desc; + ACPI_OPERAND_OBJECT *op1_desc; + ACPI_OPERAND_OBJECT *V1_desc; + ACPI_OPERAND_OBJECT *op2_desc; + ACPI_OPERAND_OBJECT *V2_desc; + ACPI_OPERAND_OBJECT *start_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS status; + u32 index; + u32 match_value = (u32) -1; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (AML_MATCH_OP, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&start_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&V2_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&op2_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&V1_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&op1_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&pkg_desc, walk_state); + + if (ACPI_FAILURE (status)) { + /* Invalid parameters on object stack */ + + goto cleanup; + } + + /* Validate match comparison sub-opcodes */ + + if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) || + (op2_desc->integer.value > MAX_MATCH_OPERATOR)) { + status = AE_AML_OPERAND_VALUE; + goto cleanup; + } + + index = (u32) start_desc->integer.value; + if (index >= (u32) pkg_desc->package.count) { + status = AE_AML_PACKAGE_LIMIT; + goto cleanup; + } + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + + } + + /* + * Examine each element until a match is found. Within the loop, + * "continue" signifies that the current element does not match + * and the next should be examined. + * Upon finding a match, the loop will terminate via "break" at + * the bottom. If it terminates "normally", Match_value will be -1 + * (its initial value) indicating that no match was found. When + * returned as a Number, this will produce the Ones value as specified. + */ + + for ( ; index < pkg_desc->package.count; ++index) { + /* + * Treat any NULL or non-numeric elements as non-matching. + * TBD [Unhandled] - if an element is a Name, + * should we examine its value? + */ + if (!pkg_desc->package.elements[index] || + ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type) { + continue; + } + + /* + * Within these switch statements: + * "break" (exit from the switch) signifies a match; + * "continue" (proceed to next iteration of enclosing + * "for" loop) signifies a non-match. + */ + switch (op1_desc->integer.value) { + + case MATCH_MTR: /* always true */ + + break; + + + case MATCH_MEQ: /* true if equal */ + + if (pkg_desc->package.elements[index]->integer.value + != V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLE: /* true if less than or equal */ + + if (pkg_desc->package.elements[index]->integer.value + > V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLT: /* true if less than */ + + if (pkg_desc->package.elements[index]->integer.value + >= V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGE: /* true if greater than or equal */ + + if (pkg_desc->package.elements[index]->integer.value + < V1_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGT: /* true if greater than */ + + if (pkg_desc->package.elements[index]->integer.value + <= V1_desc->integer.value) { + continue; + } + break; + + + default: /* undefined */ + + continue; + } + + + switch(op2_desc->integer.value) { + + case MATCH_MTR: + + break; + + + case MATCH_MEQ: + + if (pkg_desc->package.elements[index]->integer.value + != V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLE: + + if (pkg_desc->package.elements[index]->integer.value + > V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MLT: + + if (pkg_desc->package.elements[index]->integer.value + >= V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGE: + + if (pkg_desc->package.elements[index]->integer.value + < V2_desc->integer.value) { + continue; + } + break; + + + case MATCH_MGT: + + if (pkg_desc->package.elements[index]->integer.value + <= V2_desc->integer.value) { + continue; + } + break; + + + default: + + continue; + } + + /* Match found: exit from loop */ + + match_value = index; + break; + } + + /* Match_value is the return value */ + + ret_desc->integer.value = match_value; + + +cleanup: + + /* Free the operands */ + + acpi_cm_remove_reference (start_desc); + acpi_cm_remove_reference (V2_desc); + acpi_cm_remove_reference (op2_desc); + acpi_cm_remove_reference (V1_desc); + acpi_cm_remove_reference (op1_desc); + acpi_cm_remove_reference (pkg_desc); + + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} diff --git a/drivers/bus/acpi/executer/ammonad.c b/drivers/bus/acpi/executer/ammonad.c new file mode 100644 index 0000000..12a372f --- /dev/null +++ b/drivers/bus/acpi/executer/ammonad.c @@ -0,0 +1,962 @@ + +/****************************************************************************** + * + * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("ammonad") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_object_reference + * + * PARAMETERS: Obj_desc - Create a reference to this object + * Ret_desc - Where to store the reference + * + * RETURN: Status + * + * DESCRIPTION: Obtain and return a "reference" to the target object + * Common code for the Ref_of_op and the Cond_ref_of_op. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_aml_get_object_reference ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT **ret_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) { + *ret_desc = NULL; + status = AE_TYPE; + goto cleanup; + } + + /* + * Not a Name -- an indirect name pointer would have + * been converted to a direct name pointer in Acpi_aml_resolve_operands + */ + switch (obj_desc->reference.opcode) { + case AML_LOCAL_OP: + case AML_ARG_OP: + + *ret_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state); + break; + + default: + + *ret_desc = NULL; + status = AE_AML_INTERNAL; + goto cleanup; + } + + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Must be a named object; Just return the Node */ + + *ret_desc = obj_desc; + } + + else { + *ret_desc = NULL; + status = AE_TYPE; + } + + +cleanup: + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_monadic1 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on + * object stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_monadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Examine the opcode */ + + switch (opcode) { + + /* Def_release := Release_op Mutex_object */ + + case AML_RELEASE_OP: + + status = acpi_aml_release_mutex (obj_desc, walk_state); + break; + + + /* Def_reset := Reset_op Acpi_event_object */ + + case AML_RESET_OP: + + status = acpi_aml_system_reset_event (obj_desc); + break; + + + /* Def_signal := Signal_op Acpi_event_object */ + + case AML_SIGNAL_OP: + + status = acpi_aml_system_signal_event (obj_desc); + break; + + + /* Def_sleep := Sleep_op Msec_time */ + + case AML_SLEEP_OP: + + acpi_aml_system_do_suspend ((u32) obj_desc->integer.value); + break; + + + /* Def_stall := Stall_op Usec_time */ + + case AML_STALL_OP: + + acpi_aml_system_do_stall ((u32) obj_desc->integer.value); + break; + + + /* Unknown opcode */ + + default: + + REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + break; + + } /* switch */ + + +cleanup: + + /* Always delete the operand */ + + acpi_cm_remove_reference (obj_desc); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_monadic2_r + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and + * result operand on operand stack + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_monadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *res_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_OPERAND_OBJECT *ret_desc2 = NULL; + u32 res_val; + ACPI_STATUS status; + u32 i; + u32 j; + ACPI_INTEGER digit; + + + /* Resolve all operands */ + + status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Get all operands */ + + status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state); + status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Create a return object of type NUMBER for most opcodes */ + + switch (opcode) { + case AML_BIT_NOT_OP: + case AML_FIND_SET_LEFT_BIT_OP: + case AML_FIND_SET_RIGHT_BIT_OP: + case AML_FROM_BCD_OP: + case AML_TO_BCD_OP: + case AML_COND_REF_OF_OP: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + break; + } + + + switch (opcode) { + /* Def_not := Not_op Operand Result */ + + case AML_BIT_NOT_OP: + + ret_desc->integer.value = ~obj_desc->integer.value; + break; + + + /* Def_find_set_left_bit := Find_set_left_bit_op Operand Result */ + + case AML_FIND_SET_LEFT_BIT_OP: + + ret_desc->integer.value = obj_desc->integer.value; + + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundry condition is valid. + */ + for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) { + ret_desc->integer.value >>= 1; + } + + ret_desc->integer.value = res_val; + break; + + + /* Def_find_set_right_bit := Find_set_right_bit_op Operand Result */ + + case AML_FIND_SET_RIGHT_BIT_OP: + + ret_desc->integer.value = obj_desc->integer.value; + + /* + * Acpi specification describes Integer type as a little + * endian unsigned value, so this boundry condition is valid. + */ + for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) { + ret_desc->integer.value <<= 1; + } + + /* Since returns must be 1-based, subtract from 33 (65) */ + + ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val; + break; + + + /* Def_from_bDC := From_bCDOp BCDValue Result */ + + case AML_FROM_BCD_OP: + + /* + * The 64-bit ACPI integer can hold 16 4-bit BCD integers + */ + ret_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Get one BCD digit */ + + digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF); + + /* Check the range of the digit */ + + if (digit > 9) { + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + if (digit > 0) { + /* Sum into the result with the appropriate power of 10 */ + + for (j = 0; j < i; j++) { + digit *= 10; + } + + ret_desc->integer.value += digit; + } + } + break; + + + /* Def_to_bDC := To_bCDOp Operand Result */ + + case AML_TO_BCD_OP: + + + if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) { + status = AE_AML_NUMERIC_OVERFLOW; + goto cleanup; + } + + ret_desc->integer.value = 0; + for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) { + /* Divide by nth factor of 10 */ + + digit = obj_desc->integer.value; + for (j = 0; j < i; j++) { + digit /= 10; + } + + /* Create the BCD digit */ + + if (digit > 0) { + ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4)); + } + } + break; + + + /* Def_cond_ref_of := Cond_ref_of_op Source_object Result */ + + case AML_COND_REF_OF_OP: + + /* + * This op is a little strange because the internal return value is + * different than the return value stored in the result descriptor + * (There are really two return values) + */ + + if ((ACPI_NAMESPACE_NODE *) obj_desc == acpi_gbl_root_node) { + /* + * This means that the object does not exist in the namespace, + * return FALSE + */ + + ret_desc->integer.value = 0; + + /* + * Must delete the result descriptor since there is no reference + * being returned + */ + + acpi_cm_remove_reference (res_desc); + goto cleanup; + } + + /* Get the object reference and store it */ + + status = acpi_aml_get_object_reference (obj_desc, &ret_desc2, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + status = acpi_aml_exec_store (ret_desc2, res_desc, walk_state); + + /* The object exists in the namespace, return TRUE */ + + ret_desc->integer.value = ACPI_INTEGER_MAX; + goto cleanup; + break; + + + case AML_STORE_OP: + + /* + * A store operand is typically a number, string, buffer or lvalue + * TBD: [Unhandled] What about a store to a package? + */ + + /* + * Do the store, and be careful about deleting the source object, + * since the object itself may have been stored. + */ + + status = acpi_aml_exec_store (obj_desc, res_desc, walk_state); + if (ACPI_FAILURE (status)) { + /* On failure, just delete the Obj_desc */ + + acpi_cm_remove_reference (obj_desc); + } + + else { + /* + * Normally, we would remove a reference on the Obj_desc parameter; + * But since it is being used as the internal return object + * (meaning we would normally increment it), the two cancel out, + * and we simply don't do anything. + */ + *return_desc = obj_desc; + } + + obj_desc = NULL; + return (status); + + break; + + + case AML_DEBUG_OP: + + /* Reference, returning an Reference */ + + return (AE_OK); + break; + + + /* + * These are obsolete opcodes + */ + + /* Def_shift_left_bit := Shift_left_bit_op Source Bit_num */ + /* Def_shift_right_bit := Shift_right_bit_op Source Bit_num */ + + case AML_SHIFT_LEFT_BIT_OP: + case AML_SHIFT_RIGHT_BIT_OP: + + status = AE_SUPPORT; + goto cleanup; + break; + + + default: + + REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + + status = acpi_aml_exec_store (ret_desc, res_desc, walk_state); + + +cleanup: + /* Always delete the operand object */ + + acpi_cm_remove_reference (obj_desc); + + /* Delete return object(s) on error */ + + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (res_desc); /* Result descriptor */ + if (ret_desc) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + } + + /* Set the return object and exit */ + + *return_desc = ret_desc; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_monadic2 + * + * PARAMETERS: Opcode - The opcode to be executed + * + * RETURN: Status + * + * DESCRIPTION: Execute Type 2 monadic operator with numeric operand: + * Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op, + * Decrement_op, LNot_op, + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_monadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *tmp_desc; + ACPI_OPERAND_OBJECT *ret_desc = NULL; + ACPI_STATUS resolve_status; + ACPI_STATUS status; + u32 type; + ACPI_INTEGER value; + + + /* Attempt to resolve the operands */ + + resolve_status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state); + /* Always get all operands */ + + status = acpi_ds_obj_stack_pop_object (&obj_desc, walk_state); + + + /* Now we can check the status codes */ + + if (ACPI_FAILURE (resolve_status)) { + goto cleanup; + } + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Get the operand and decode the opcode */ + + + switch (opcode) { + + /* Def_lNot := LNot_op Operand */ + + case AML_LNOT_OP: + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->integer.value = !obj_desc->integer.value; + break; + + + /* Def_decrement := Decrement_op Target */ + /* Def_increment := Increment_op Target */ + + case AML_DECREMENT_OP: + case AML_INCREMENT_OP: + + /* + * Since we are expecting an Reference on the top of the stack, it + * can be either an Node or an internal object. + * + * TBD: [Future] This may be the prototype code for all cases where + * an Reference is expected!! 10/99 + */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + ret_desc = obj_desc; + } + + else { + /* + * Duplicate the Reference in a new object so that we can resolve it + * without destroying the original Reference object + */ + + ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->reference.opcode = obj_desc->reference.opcode; + ret_desc->reference.offset = obj_desc->reference.offset; + ret_desc->reference.object = obj_desc->reference.object; + } + + + /* + * Convert the Ret_desc Reference to a Number + * (This deletes the original Ret_desc) + */ + + status = acpi_aml_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* Do the actual increment or decrement */ + + if (AML_INCREMENT_OP == opcode) { + ret_desc->integer.value++; + } + else { + ret_desc->integer.value--; + } + + /* Store the result back in the original descriptor */ + + status = acpi_aml_exec_store (ret_desc, obj_desc, walk_state); + + /* Objdesc was just deleted (because it is an Reference) */ + + obj_desc = NULL; + + break; + + + /* Def_object_type := Object_type_op Source_object */ + + case AML_TYPE_OP: + + if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) { + /* + * Not a Name -- an indirect name pointer would have + * been converted to a direct name pointer in Resolve_operands + */ + switch (obj_desc->reference.opcode) { + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + + /* Constants are of type Number */ + + type = ACPI_TYPE_INTEGER; + break; + + + case AML_DEBUG_OP: + + /* Per 1.0b spec, Debug object is of type Debug_object */ + + type = ACPI_TYPE_DEBUG_OBJECT; + break; + + + case AML_INDEX_OP: + + /* Get the type of this reference (index into another object) */ + + type = obj_desc->reference.target_type; + if (type == ACPI_TYPE_PACKAGE) { + /* + * The main object is a package, we want to get the type + * of the individual package element that is referenced by + * the index. + */ + type = (*(obj_desc->reference.where))->common.type; + } + + break; + + + case AML_LOCAL_OP: + case AML_ARG_OP: + + type = acpi_ds_method_data_get_type (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state); + break; + + + default: + + REPORT_ERROR (("Acpi_aml_exec_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n", + obj_desc->reference.opcode)); + status = AE_AML_INTERNAL; + goto cleanup; + } + } + + else { + /* + * It's not a Reference, so it must be a direct name pointer. + */ + type = acpi_ns_get_type ((ACPI_HANDLE) obj_desc); + } + + /* Allocate a descriptor to hold the type. */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->integer.value = type; + break; + + + /* Def_size_of := Size_of_op Source_object */ + + case AML_SIZE_OF_OP: + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + obj_desc = acpi_ns_get_attached_object (obj_desc); + } + + if (!obj_desc) { + value = 0; + } + + else { + switch (obj_desc->common.type) { + + case ACPI_TYPE_BUFFER: + + value = obj_desc->buffer.length; + break; + + + case ACPI_TYPE_STRING: + + value = obj_desc->string.length; + break; + + + case ACPI_TYPE_PACKAGE: + + value = obj_desc->package.count; + break; + + case INTERNAL_TYPE_REFERENCE: + + value = 4; + break; + + default: + + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + } + + /* + * Now that we have the size of the object, create a result + * object to hold the value + */ + + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + ret_desc->integer.value = value; + break; + + + /* Def_ref_of := Ref_of_op Source_object */ + + case AML_REF_OF_OP: + + status = acpi_aml_get_object_reference (obj_desc, &ret_desc, walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + break; + + + /* Def_deref_of := Deref_of_op Obj_reference */ + + case AML_DEREF_OF_OP: + + + /* Check for a method local or argument */ + + if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* + * Must resolve/dereference the local/arg reference first + */ + switch (obj_desc->reference.opcode) { + /* Set Obj_desc to the value of the local/arg */ + + case AML_LOCAL_OP: + case AML_ARG_OP: + + acpi_ds_method_data_get_value (obj_desc->reference.opcode, + obj_desc->reference.offset, walk_state, &tmp_desc); + + /* + * Delete our reference to the input object and + * point to the object just retrieved + */ + acpi_cm_remove_reference (obj_desc); + obj_desc = tmp_desc; + break; + + default: + + /* Index op - handled below */ + break; + } + } + + + /* Obj_desc may have changed from the code above */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Get the actual object from the Node (This is the dereference) */ + + ret_desc = ((ACPI_NAMESPACE_NODE *) obj_desc)->object; + + /* Returning a pointer to the object, add another reference! */ + + acpi_cm_add_reference (ret_desc); + } + + else { + /* + * This must be a reference object produced by the Index + * ASL operation -- check internal opcode + */ + + if ((obj_desc->reference.opcode != AML_INDEX_OP) && + (obj_desc->reference.opcode != AML_REF_OF_OP)) { + status = AE_TYPE; + goto cleanup; + } + + + switch (obj_desc->reference.opcode) { + case AML_INDEX_OP: + + /* + * Supported target types for the Index operator are + * 1) A Buffer + * 2) A Package + */ + + if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) { + /* + * The target is a buffer, we must create a new object that + * contains one element of the buffer, the element pointed + * to by the index. + * + * NOTE: index into a buffer is NOT a pointer to a + * sub-buffer of the main buffer, it is only a pointer to a + * single element (byte) of the buffer! + */ + ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!ret_desc) { + status = AE_NO_MEMORY; + goto cleanup; + } + + tmp_desc = obj_desc->reference.object; + ret_desc->integer.value = + tmp_desc->buffer.pointer[obj_desc->reference.offset]; + + /* TBD: [Investigate] (see below) Don't add an additional + * ref! + */ + } + + else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) { + /* + * The target is a package, we want to return the referenced + * element of the package. We must add another reference to + * this object, however. + */ + + ret_desc = *(obj_desc->reference.where); + if (!ret_desc) { + /* + * We can't return a NULL dereferenced value. This is + * an uninitialized package element and is thus a + * severe error. + */ + + status = AE_AML_UNINITIALIZED_ELEMENT; + goto cleanup; + } + + acpi_cm_add_reference (ret_desc); + } + + else { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + break; + + + case AML_REF_OF_OP: + + ret_desc = obj_desc->reference.object; + + /* Add another reference to the object! */ + + acpi_cm_add_reference (ret_desc); + break; + } + } + + break; + + + default: + + REPORT_ERROR (("Acpi_aml_exec_monadic2: Unknown monadic opcode %X\n", + opcode)); + status = AE_AML_BAD_OPCODE; + goto cleanup; + } + + +cleanup: + + if (obj_desc) { + acpi_cm_remove_reference (obj_desc); + } + + /* Delete return object on error */ + + if (ACPI_FAILURE (status) && + (ret_desc)) { + acpi_cm_remove_reference (ret_desc); + ret_desc = NULL; + } + + *return_desc = ret_desc; + return (status); +} + diff --git a/drivers/bus/acpi/executer/ammutex.c b/drivers/bus/acpi/executer/ammutex.c new file mode 100644 index 0000000..38caf8a --- /dev/null +++ b/drivers/bus/acpi/executer/ammutex.c @@ -0,0 +1,281 @@ + +/****************************************************************************** + * + * Module Name: ammutex - ASL Mutex Acquire/Release functions + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("ammutex") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_unlink_mutex + * + * PARAMETERS: *Obj_desc - The mutex to be unlinked + * + * RETURN: Status + * + * DESCRIPTION: Remove a mutex from the "Acquired_mutex" list + * + ******************************************************************************/ + +void +acpi_aml_unlink_mutex ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + + if (obj_desc->mutex.next) { + (obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev; + } + if (obj_desc->mutex.prev) { + (obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_link_mutex + * + * PARAMETERS: *Obj_desc - The mutex to be linked + * *List_head - head of the "Acquired_mutex" list + * + * RETURN: Status + * + * DESCRIPTION: Add a mutex to the "Acquired_mutex" list for this walk + * + ******************************************************************************/ + +void +acpi_aml_link_mutex ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *list_head) +{ + + /* This object will be the first object in the list */ + + obj_desc->mutex.prev = list_head; + obj_desc->mutex.next = list_head->mutex.next; + + /* Update old first object to point back to this object */ + + if (list_head->mutex.next) { + (list_head->mutex.next)->mutex.prev = obj_desc; + } + + /* Update list head */ + + list_head->mutex.next = obj_desc; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_acquire_mutex + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_acquire_mutex ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Current Sync must be less than or equal to the sync level of the + * mutex. This mechanism provides some deadlock prevention + */ + if (walk_state->current_sync_level > obj_desc->mutex.sync_level) { + return (AE_AML_MUTEX_ORDER); + } + + /* + * If the mutex is already owned by this thread, + * just increment the acquisition depth + */ + if (obj_desc->mutex.owner == walk_state) { + obj_desc->mutex.acquisition_depth++; + return (AE_OK); + } + + /* Acquire the mutex, wait if necessary */ + + status = acpi_aml_system_acquire_mutex (time_desc, obj_desc); + if (ACPI_FAILURE (status)) { + /* Includes failure from a timeout on Time_desc */ + + return (status); + } + + /* Have the mutex, update mutex and walk info */ + + obj_desc->mutex.owner = walk_state; + obj_desc->mutex.acquisition_depth = 1; + walk_state->current_sync_level = obj_desc->mutex.sync_level; + + /* Link the mutex to the walk state for force-unlock at method exit */ + + acpi_aml_link_mutex (obj_desc, (ACPI_OPERAND_OBJECT *) + &(walk_state->walk_list->acquired_mutex_list)); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_release_mutex + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Release a previously acquired Mutex. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_release_mutex ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* The mutex must have been previously acquired in order to release it */ + + if (!obj_desc->mutex.owner) { + return (AE_AML_MUTEX_NOT_ACQUIRED); + } + + /* The Mutex is owned, but this thread must be the owner */ + + if (obj_desc->mutex.owner != walk_state) { + return (AE_AML_NOT_OWNER); + } + + /* + * The sync level of the mutex must be less than or + * equal to the current sync level + */ + if (obj_desc->mutex.sync_level > walk_state->current_sync_level) { + return (AE_AML_MUTEX_ORDER); + } + + /* + * Match multiple Acquires with multiple Releases + */ + obj_desc->mutex.acquisition_depth--; + if (obj_desc->mutex.acquisition_depth != 0) { + /* Just decrement the depth and return */ + + return (AE_OK); + } + + + /* Release the mutex */ + + status = acpi_aml_system_release_mutex (obj_desc); + + /* Update the mutex and walk state */ + + obj_desc->mutex.owner = NULL; + walk_state->current_sync_level = obj_desc->mutex.sync_level; + + /* Unlink the mutex from the owner's list */ + + acpi_aml_unlink_mutex (obj_desc); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_release_all_mutexes + * + * PARAMETERS: *Mutex_list - Head of the mutex list + * + * RETURN: Status + * + * DESCRIPTION: Release all mutexes in the list + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_release_all_mutexes ( + ACPI_OPERAND_OBJECT *list_head) +{ + ACPI_OPERAND_OBJECT *next = list_head->mutex.next; + ACPI_OPERAND_OBJECT *this; + + + /* + * Traverse the list of owned mutexes, releasing each one. + */ + while (next) { + this = next; + next = this->mutex.next; + + /* Mark mutex un-owned */ + + this->mutex.owner = NULL; + this->mutex.prev = NULL; + this->mutex.next = NULL; + this->mutex.acquisition_depth = 0; + + /* Release the mutex */ + + acpi_aml_system_release_mutex (this); + } + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/executer/amnames.c b/drivers/bus/acpi/executer/amnames.c new file mode 100644 index 0000000..628eb17 --- /dev/null +++ b/drivers/bus/acpi/executer/amnames.c @@ -0,0 +1,389 @@ + +/****************************************************************************** + * + * Module Name: amnames - interpreter/scanner name load/execute + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amnames") + + +/* AML Package Length encodings */ + +#define ACPI_AML_PACKAGE_TYPE1 0x40 +#define ACPI_AML_PACKAGE_TYPE2 0x4000 +#define ACPI_AML_PACKAGE_TYPE3 0x400000 +#define ACPI_AML_PACKAGE_TYPE4 0x40000000 + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_allocate_name_string + * + * PARAMETERS: Prefix_count - Count of parent levels. Special cases: + * (-1) = root, 0 = none + * Num_name_segs - count of 4-character name segments + * + * RETURN: A pointer to the allocated string segment. This segment must + * be deleted by the caller. + * + * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name + * string is long enough, and set up prefix if any. + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_aml_allocate_name_string ( + u32 prefix_count, + u32 num_name_segs) +{ + NATIVE_CHAR *temp_ptr; + NATIVE_CHAR *name_string; + u32 size_needed; + + + /* + * Allow room for all \ and ^ prefixes, all segments, and a Multi_name_prefix. + * Also, one byte for the null terminator. + * This may actually be somewhat longer than needed. + */ + + if (prefix_count == (u32) -1) { + /* Special case for root */ + + size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + else { + size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1; + } + + /* + * Allocate a buffer for the name. + * This buffer must be deleted by the caller! + */ + + name_string = acpi_cm_allocate (size_needed); + if (!name_string) { + REPORT_ERROR (("Aml_allocate_name_string: name allocation failure\n")); + return (NULL); + } + + temp_ptr = name_string; + + /* Set up Root or Parent prefixes if needed */ + + if (prefix_count == (u32) -1) { + *temp_ptr++ = AML_ROOT_PREFIX; + } + + else { + while (prefix_count--) { + *temp_ptr++ = AML_PARENT_PREFIX; + } + } + + + /* Set up Dual or Multi prefixes if needed */ + + if (num_name_segs > 2) { + /* Set up multi prefixes */ + + *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP; + *temp_ptr++ = (char) num_name_segs; + } + + else if (2 == num_name_segs) { + /* Set up dual prefixes */ + + *temp_ptr++ = AML_DUAL_NAME_PREFIX; + } + + /* + * Terminate string following prefixes. Acpi_aml_exec_name_segment() will + * append the segment(s) + */ + + *temp_ptr = 0; + + return (name_string); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_name_segment + * + * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec) + * + * RETURN: Status + * + * DESCRIPTION: Execute a name segment (4 bytes) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_name_segment ( + u8 **in_aml_address, + NATIVE_CHAR *name_string) +{ + u8 *aml_address = *in_aml_address; + ACPI_STATUS status = AE_OK; + u32 index; + NATIVE_CHAR char_buf[5]; + + + /* + * If first character is a digit, then we know that we aren't looking at a + * valid name segment + */ + + char_buf[0] = *aml_address; + + if ('0' <= char_buf[0] && char_buf[0] <= '9') { + return (AE_CTRL_PENDING); + } + + for (index = 4; + (index > 0) && (acpi_cm_valid_acpi_character (*aml_address)); + --index) { + char_buf[4 - index] = *aml_address++; + } + + + /* Valid name segment */ + + if (0 == index) { + /* Found 4 valid characters */ + + char_buf[4] = '\0'; + + if (name_string) { + STRCAT (name_string, char_buf); + } + + } + + else if (4 == index) { + /* + * First character was not a valid name character, + * so we are looking at something other than a name. + */ + status = AE_CTRL_PENDING; + } + + else { + /* Segment started with one or more valid characters, but fewer than 4 */ + + status = AE_AML_BAD_NAME; + } + + *in_aml_address = aml_address; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_name_string + * + * PARAMETERS: Data_type - Data type to be associated with this name + * + * RETURN: Status + * + * DESCRIPTION: Get a name, including any prefixes. + * + ******************************************************************************/ + + +ACPI_STATUS +acpi_aml_get_name_string ( + OBJECT_TYPE_INTERNAL data_type, + u8 *in_aml_address, + NATIVE_CHAR **out_name_string, + u32 *out_name_length) +{ + ACPI_STATUS status = AE_OK; + u8 *aml_address = in_aml_address; + NATIVE_CHAR *name_string = NULL; + u32 num_segments; + u32 prefix_count = 0; + u8 prefix = 0; + u8 has_prefix = FALSE; + + + if (INTERNAL_TYPE_DEF_FIELD == data_type || + INTERNAL_TYPE_BANK_FIELD == data_type || + INTERNAL_TYPE_INDEX_FIELD == data_type) { + /* Disallow prefixes for types associated with field names */ + + name_string = acpi_aml_allocate_name_string (0, 1); + if (!name_string) { + status = AE_NO_MEMORY; + } + else { + status = acpi_aml_exec_name_segment (&aml_address, name_string); + } + } + + else { + /* + * Data_type is not a field name. + * Examine first character of name for root or parent prefix operators + */ + + switch (*aml_address) { + + case AML_ROOT_PREFIX: + + prefix = *aml_address++; + /* + * Remember that we have a Root_prefix -- + * see comment in Acpi_aml_allocate_name_string() + */ + prefix_count = (u32) -1; + has_prefix = TRUE; + break; + + + case AML_PARENT_PREFIX: + + /* Increment past possibly multiple parent prefixes */ + + do { + prefix = *aml_address++; + ++prefix_count; + + } while (*aml_address == AML_PARENT_PREFIX); + has_prefix = TRUE; + break; + + + default: + + break; + } + + + /* Examine first character of name for name segment prefix operator */ + + switch (*aml_address) { + + case AML_DUAL_NAME_PREFIX: + + prefix = *aml_address++; + name_string = acpi_aml_allocate_name_string (prefix_count, 2); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + has_prefix = TRUE; + + status = acpi_aml_exec_name_segment (&aml_address, name_string); + if (ACPI_SUCCESS (status)) { + status = acpi_aml_exec_name_segment (&aml_address, name_string); + } + break; + + + case AML_MULTI_NAME_PREFIX_OP: + + prefix = *aml_address++; + /* Fetch count of segments remaining in name path */ + + num_segments = *aml_address++; + + name_string = acpi_aml_allocate_name_string (prefix_count, num_segments); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + /* Indicate that we processed a prefix */ + has_prefix = TRUE; + + while (num_segments && + (status = acpi_aml_exec_name_segment (&aml_address, name_string)) == AE_OK) { + --num_segments; + } + + break; + + + case 0: + + /* Null_name valid as of 8-12-98 ASL/AML Grammar Update */ + + + /* Consume the NULL byte */ + + aml_address++; + name_string = acpi_aml_allocate_name_string (prefix_count, 0); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + break; + + + default: + + /* Name segment string */ + + name_string = acpi_aml_allocate_name_string (prefix_count, 1); + if (!name_string) { + status = AE_NO_MEMORY; + break; + } + + status = acpi_aml_exec_name_segment (&aml_address, name_string); + break; + + } /* Switch (Peek_op ()) */ + } + + + if (AE_CTRL_PENDING == status && has_prefix) { + /* Ran out of segments after processing a prefix */ + + REPORT_ERROR ( + ("Aml_do_name: Malformed Name at %p\n", name_string)); + status = AE_AML_BAD_NAME; + } + + + *out_name_string = name_string; + *out_name_length = (u32) (aml_address - in_aml_address); + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amprep.c b/drivers/bus/acpi/executer/amprep.c new file mode 100644 index 0000000..bd97f9f --- /dev/null +++ b/drivers/bus/acpi/executer/amprep.c @@ -0,0 +1,404 @@ + +/****************************************************************************** + * + * Module Name: amprep - ACPI AML (p-code) execution - field prep utilities + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acparser.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amprep") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_decode_field_access_type + * + * PARAMETERS: Access - Encoded field access bits + * + * RETURN: Field granularity (8, 16, or 32) + * + * DESCRIPTION: Decode the Access_type bits of a field definition. + * + ******************************************************************************/ + +static u32 +acpi_aml_decode_field_access_type ( + u32 access, + u16 length) +{ + + switch (access) { + case ACCESS_ANY_ACC: + if (length <= 8) { + return (8); + } + else if (length <= 16) { + return (16); + } + else if (length <= 32) { + return (32); + } + else { + return (8); + } + break; + + case ACCESS_BYTE_ACC: + return (8); + break; + + case ACCESS_WORD_ACC: + return (16); + break; + + case ACCESS_DWORD_ACC: + return (32); + break; + + default: + /* Invalid field access type */ + + return (0); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_common_field_objec + * + * PARAMETERS: Obj_desc - The field object + * Field_flags - Access, Lock_rule, or Update_rule. + * The format of a Field_flag is described + * in the ACPI specification + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Initialize the areas of the field object that are common + * to the various types of fields. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_aml_prep_common_field_object ( + ACPI_OPERAND_OBJECT *obj_desc, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + u32 granularity; + + + /* + * Note: the structure being initialized is the + * ACPI_COMMON_FIELD_INFO; Therefore, we can just use the Field union to + * access this common area. No structure fields outside of the common area + * are initialized by this procedure. + */ + + /* Decode the Field_flags */ + + obj_desc->field.access = (u8) ((field_flags & ACCESS_TYPE_MASK) + >> ACCESS_TYPE_SHIFT); + obj_desc->field.lock_rule = (u8) ((field_flags & LOCK_RULE_MASK) + >> LOCK_RULE_SHIFT); + obj_desc->field.update_rule = (u8) ((field_flags & UPDATE_RULE_MASK) + >> UPDATE_RULE_SHIFT); + + /* Other misc fields */ + + obj_desc->field.length = (u16) field_length; + obj_desc->field.access_attribute = field_attribute; + + /* Decode the access type so we can compute offsets */ + + granularity = acpi_aml_decode_field_access_type (obj_desc->field.access, obj_desc->field.length); + if (!granularity) { + return (AE_AML_OPERAND_VALUE); + } + + /* Access granularity based fields */ + + obj_desc->field.granularity = (u8) granularity; + obj_desc->field.bit_offset = (u8) (field_position % granularity); + obj_desc->field.offset = (u32) field_position / granularity; + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_def_field_value + * + * PARAMETERS: Node - Owning Node + * Region - Region in which field is being defined + * Field_flags - Access, Lock_rule, or Update_rule. + * The format of a Field_flag is described + * in the ACPI specification + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Def_field and + * connect it to the parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_def_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE region, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + ACPI_OPERAND_OBJECT *obj_desc; + u32 type; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!region) { + return (AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type (region); + if (type != ACPI_TYPE_REGION) { + return (AE_AML_OPERAND_TYPE); + } + + /* Allocate a new object */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_DEF_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + + /* Obj_desc and Region valid */ + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, + field_position, field_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->field.container = acpi_ns_get_attached_object (region); + + /* An additional reference for the container */ + + acpi_cm_add_reference (obj_desc->field.container); + + + /* Debug info */ + + /* + * Store the constructed descriptor (Obj_desc) into the Named_obj whose + * handle is on TOS, preserving the current type of that Named_obj. + */ + status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, + (u8) acpi_ns_get_type ((ACPI_HANDLE) node)); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_bank_field_value + * + * PARAMETERS: Node - Owning Node + * Region - Region in which field is being defined + * Bank_reg - Bank selection register + * Bank_val - Value to store in selection register + * Field_flags - Access, Lock_rule, or Update_rule + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Bank_field and + * connect it to the parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_bank_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE region, + ACPI_HANDLE bank_reg, + u32 bank_val, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + ACPI_OPERAND_OBJECT *obj_desc; + u32 type; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!region) { + return (AE_AML_NO_OPERAND); + } + + type = acpi_ns_get_type (region); + if (type != ACPI_TYPE_REGION) { + return (AE_AML_OPERAND_TYPE); + } + + /* Allocate a new object */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_BANK_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Obj_desc and Region valid */ + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, + field_position, field_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->bank_field.value = bank_val; + obj_desc->bank_field.container = acpi_ns_get_attached_object (region); + obj_desc->bank_field.bank_select = acpi_ns_get_attached_object (bank_reg); + + /* An additional reference for the container and bank select */ + /* TBD: [Restructure] is "Bank_select" ever a real internal object?? */ + + acpi_cm_add_reference (obj_desc->bank_field.container); + acpi_cm_add_reference (obj_desc->bank_field.bank_select); + + /* Debug info */ + + /* + * Store the constructed descriptor (Obj_desc) into the Named_obj whose + * handle is on TOS, preserving the current type of that Named_obj. + */ + status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, + (u8) acpi_ns_get_type ((ACPI_HANDLE) node)); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_prep_index_field_value + * + * PARAMETERS: Node - Owning Node + * Index_reg - Index register + * Data_reg - Data register + * Field_flags - Access, Lock_rule, or Update_rule + * Field_position - Field position + * Field_length - Field length + * + * RETURN: Status + * + * DESCRIPTION: Construct an ACPI_OPERAND_OBJECT of type Index_field and + * connect it to the parent Node. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_prep_index_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE index_reg, + ACPI_HANDLE data_reg, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!index_reg || !data_reg) { + return (AE_AML_NO_OPERAND); + } + + /* Allocate a new object descriptor */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_INDEX_FIELD); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Initialize areas of the object that are common to all fields */ + + status = acpi_aml_prep_common_field_object (obj_desc, field_flags, field_attribute, + field_position, field_length); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Initialize areas of the object that are specific to this field type */ + + obj_desc->index_field.value = (u32) (field_position / + obj_desc->field.granularity); + obj_desc->index_field.index = index_reg; + obj_desc->index_field.data = data_reg; + + /* Debug info */ + + /* + * Store the constructed descriptor (Obj_desc) into the Named_obj whose + * handle is on TOS, preserving the current type of that Named_obj. + */ + status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc, + (u8) acpi_ns_get_type ((ACPI_HANDLE) node)); + + return (status); +} + diff --git a/drivers/bus/acpi/executer/amregion.c b/drivers/bus/acpi/executer/amregion.c new file mode 100644 index 0000000..28b61d9 --- /dev/null +++ b/drivers/bus/acpi/executer/amregion.c @@ -0,0 +1,409 @@ + +/****************************************************************************** + * + * Module Name: amregion - ACPI default Op_region (address space) handlers + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amregion") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_memory_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System Memory address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_memory_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + void *logical_addr_ptr = NULL; + MEM_HANDLER_CONTEXT *mem_info = region_context; + u32 length; + + + /* Validate and translate the bit width */ + + switch (bit_width) { + case 8: + length = 1; + break; + + case 16: + length = 2; + break; + + case 32: + length = 4; + break; + + default: + return (AE_AML_OPERAND_VALUE); + break; + } + + + /* + * Does the request fit into the cached memory mapping? + * Is 1) Address below the current mapping? OR + * 2) Address beyond the current mapping? + */ + + if ((address < mem_info->mapped_physical_address) || + (((ACPI_INTEGER) address + length) > + ((ACPI_INTEGER) mem_info->mapped_physical_address + mem_info->mapped_length))) { + /* + * The request cannot be resolved by the current memory mapping; + * Delete the existing mapping and create a new one. + */ + + if (mem_info->mapped_length) { + /* Valid mapping, delete it */ + + acpi_os_unmap_memory (mem_info->mapped_logical_address, + mem_info->mapped_length); + } + + mem_info->mapped_length = 0; /* In case of failure below */ + + /* Create a new mapping starting at the address given */ + + status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE, + (void **) &mem_info->mapped_logical_address); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* TBD: should these pointers go to 64-bit in all cases ? */ + + mem_info->mapped_physical_address = address; + mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE; + } + + + /* + * Generate a logical pointer corresponding to the address we want to + * access + */ + + /* TBD: should these pointers go to 64-bit in all cases ? */ + + logical_addr_ptr = mem_info->mapped_logical_address + + ((ACPI_INTEGER) address - (ACPI_INTEGER) mem_info->mapped_physical_address); + + /* Perform the memory read or write */ + + switch (function) { + + case ADDRESS_SPACE_READ: + + switch (bit_width) { + case 8: + *value = (u32)* (u8 *) logical_addr_ptr; + break; + + case 16: + MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr); + break; + + case 32: + MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr); + break; + } + + break; + + + case ADDRESS_SPACE_WRITE: + + switch (bit_width) { + case 8: + *(u8 *) logical_addr_ptr = (u8) *value; + break; + + case 16: + MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value); + break; + + case 32: + MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value); + break; + } + + break; + + + default: + status = AE_BAD_PARAMETER; + break; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_io_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the System IO address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_io_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + + + /* Decode the function parameter */ + + switch (function) { + + case ADDRESS_SPACE_READ: + + switch (bit_width) { + /* I/O Port width */ + + case 8: + *value = (u32) acpi_os_in8 ((ACPI_IO_ADDRESS) address); + break; + + case 16: + *value = (u32) acpi_os_in16 ((ACPI_IO_ADDRESS) address); + break; + + case 32: + *value = acpi_os_in32 ((ACPI_IO_ADDRESS) address); + break; + + default: + status = AE_AML_OPERAND_VALUE; + } + + break; + + + case ADDRESS_SPACE_WRITE: + + switch (bit_width) { + /* I/O Port width */ + case 8: + acpi_os_out8 ((ACPI_IO_ADDRESS) address, (u8) *value); + break; + + case 16: + acpi_os_out16 ((ACPI_IO_ADDRESS) address, (u16) *value); + break; + + case 32: + acpi_os_out32 ((ACPI_IO_ADDRESS) address, *value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + } + + break; + + + default: + status = AE_BAD_PARAMETER; + break; + } + + return (status); +} + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_pci_config_space_handler + * + * PARAMETERS: Function - Read or Write operation + * Address - Where in the space to read or write + * Bit_width - Field width in bits (8, 16, or 32) + * Value - Pointer to in or out value + * Handler_context - Pointer to Handler's context + * Region_context - Pointer to context specific to the + * accessed region + * + * RETURN: Status + * + * DESCRIPTION: Handler for the PCI Config address space (Op Region) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_pci_config_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context) +{ + ACPI_STATUS status = AE_OK; + u32 pci_bus; + u32 dev_func; + u8 pci_reg; + PCI_HANDLER_CONTEXT *PCIcontext; + + + /* + * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are: + * + * Seg_bus - 0xSSSSBBBB - SSSS is the PCI bus segment + * BBBB is the PCI bus number + * + * Dev_func - 0xDDDDFFFF - DDDD is the PCI device number + * FFFF is the PCI device function number + * + * Reg_num - Config space register must be < 40h + * + * Value - input value for write, output for read + * + */ + + PCIcontext = (PCI_HANDLER_CONTEXT *) region_context; + + pci_bus = LOWORD(PCIcontext->seg) << 16; + pci_bus |= LOWORD(PCIcontext->bus); + + dev_func = PCIcontext->dev_func; + + pci_reg = (u8) address; + + switch (function) { + + case ADDRESS_SPACE_READ: + + *value = 0; + + switch (bit_width) { + /* PCI Register width */ + + case 8: + status = acpi_os_read_pci_cfg_byte (pci_bus, dev_func, pci_reg, + (u8 *) value); + break; + + case 16: + status = acpi_os_read_pci_cfg_word (pci_bus, dev_func, pci_reg, + (u16 *) value); + break; + + case 32: + status = acpi_os_read_pci_cfg_dword (pci_bus, dev_func, pci_reg, + value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + + } /* Switch bit_width */ + + break; + + + case ADDRESS_SPACE_WRITE: + + switch (bit_width) { + /* PCI Register width */ + + case 8: + status = acpi_os_write_pci_cfg_byte (pci_bus, dev_func, pci_reg, + *(u8 *) value); + break; + + case 16: + status = acpi_os_write_pci_cfg_word (pci_bus, dev_func, pci_reg, + *(u16 *) value); + break; + + case 32: + status = acpi_os_write_pci_cfg_dword (pci_bus, dev_func, pci_reg, + *value); + break; + + default: + status = AE_AML_OPERAND_VALUE; + + } /* Switch bit_width */ + + break; + + + default: + + status = AE_BAD_PARAMETER; + break; + + } + + return (status); +} + diff --git a/drivers/bus/acpi/executer/amresnte.c b/drivers/bus/acpi/executer/amresnte.c new file mode 100644 index 0000000..4d3e239 --- /dev/null +++ b/drivers/bus/acpi/executer/amresnte.c @@ -0,0 +1,506 @@ + +/****************************************************************************** + * + * Module Name: amresnte - AML Interpreter object resolution + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amresnte") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_node_to_value + * + * PARAMETERS: Stack_ptr - Pointer to a location on a stack that contains + * a pointer to an Node + * + * RETURN: Status + * + * DESCRIPTION: Resolve a ACPI_NAMESPACE_NODE (Node, + * A.K.A. a "direct name pointer") + * + * Note: for some of the data types, the pointer attached to the Node + * can be either a pointer to an actual internal object or a pointer into the + * AML stream itself. These types are currently: + * + * ACPI_TYPE_INTEGER + * ACPI_TYPE_STRING + * ACPI_TYPE_BUFFER + * ACPI_TYPE_MUTEX + * ACPI_TYPE_PACKAGE + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_node_to_value ( + ACPI_NAMESPACE_NODE **stack_ptr, + ACPI_WALK_STATE *walk_state) + +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *val_desc = NULL; + ACPI_OPERAND_OBJECT *obj_desc = NULL; + ACPI_NAMESPACE_NODE *node; + u8 *aml_pointer = NULL; + OBJECT_TYPE_INTERNAL entry_type; + u8 locked; + u8 attached_aml_pointer = FALSE; + u8 aml_opcode = 0; + ACPI_INTEGER temp_val; + OBJECT_TYPE_INTERNAL object_type; + + + node = *stack_ptr; + + + /* + * The stack pointer is a "Direct name ptr", and points to a + * a ACPI_NAMESPACE_NODE (Node). Get the pointer that is attached to + * the Node. + */ + + val_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node); + entry_type = acpi_ns_get_type ((ACPI_HANDLE) node); + + /* + * The Val_desc attached to the Node can be either: + * 1) An internal ACPI object + * 2) A pointer into the AML stream (into one of the ACPI system tables) + */ + + if (acpi_tb_system_table_pointer (val_desc)) { + attached_aml_pointer = TRUE; + aml_opcode = *((u8 *) val_desc); + aml_pointer = ((u8 *) val_desc) + 1; + + } + + + /* + * Several Entry_types do not require further processing, so + * we will return immediately + */ + /* Devices rarely have an attached object, return the Node + * and Method locals and arguments have a pseudo-Node + */ + if (entry_type == ACPI_TYPE_DEVICE || + (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { + return (AE_OK); + } + + if (!val_desc) { + return (AE_AML_NO_OPERAND); + } + + /* + * Action is based on the type of the Node, which indicates the type + * of the attached object or pointer + */ + switch (entry_type) { + + case ACPI_TYPE_PACKAGE: + + if (attached_aml_pointer) { + /* + * This means that the package initialization is not parsed + * -- should not happen + */ + return (AE_NOT_IMPLEMENTED); + } + + /* Val_desc is an internal object in all cases by the time we get here */ + + if (ACPI_TYPE_PACKAGE != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + break; + + + case ACPI_TYPE_BUFFER: + + if (attached_aml_pointer) { + /* + * This means that the buffer initialization is not parsed + * -- should not happen + */ + return (AE_NOT_IMPLEMENTED); + } + + /* Val_desc is an internal object in all cases by the time we get here */ + + if (ACPI_TYPE_BUFFER != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + break; + + + case ACPI_TYPE_STRING: + + if (attached_aml_pointer) { + /* Allocate a new string object */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* Init the internal object */ + + obj_desc->string.pointer = (NATIVE_CHAR *) aml_pointer; + obj_desc->string.length = STRLEN (obj_desc->string.pointer); + } + + else { + if (ACPI_TYPE_STRING != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + } + + break; + + + case ACPI_TYPE_INTEGER: + + /* + * The Node has an attached internal object, make sure that it's a + * number + */ + + if (ACPI_TYPE_INTEGER != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + break; + + + case INTERNAL_TYPE_DEF_FIELD: + + /* + * TBD: [Investigate] Is this the correct solution? + * + * This section was extended to convert to generic buffer if + * the return length is greater than 32 bits, but still allows + * for returning a type Number for smaller values because the + * caller can then apply arithmetic operators on those fields. + * + * XXX - Implementation limitation: Fields are implemented as type + * XXX - Number, but they really are supposed to be type Buffer. + * XXX - The two are interchangeable only for lengths <= 32 bits. + */ + if(val_desc->field.length > 32) { + object_type = ACPI_TYPE_BUFFER; + } + else { + object_type = ACPI_TYPE_INTEGER; + } + + /* + * Create the destination buffer object and the buffer space. + */ + obj_desc = acpi_cm_create_internal_object (object_type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* + * Fill in the object specific details + */ + if (ACPI_TYPE_BUFFER == object_type) { + obj_desc->buffer.pointer = acpi_cm_callocate (val_desc->field.length); + if (!obj_desc->buffer.pointer) { + acpi_cm_remove_reference(obj_desc); + return (AE_NO_MEMORY); + } + + obj_desc->buffer.length = val_desc->field.length; + + status = acpi_aml_access_named_field (ACPI_READ, (ACPI_HANDLE) node, + obj_desc->buffer.pointer, obj_desc->buffer.length); + + if (ACPI_FAILURE (status)) { + return (status); + } + } + else { + status = acpi_aml_access_named_field (ACPI_READ, (ACPI_HANDLE) node, + &temp_val, sizeof (temp_val)); + + if (ACPI_FAILURE (status)) { + return (status); + } + + obj_desc->integer.value = temp_val; + } + + + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + if (attached_aml_pointer) { + return (AE_AML_OPERAND_TYPE); + } + + if (INTERNAL_TYPE_BANK_FIELD != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* Get the global lock if needed */ + + obj_desc = (ACPI_OPERAND_OBJECT *) *stack_ptr; + locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); + + /* Set Index value to select proper Data register */ + /* perform the update */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + val_desc->bank_field.bank_select, &val_desc->bank_field.value, + sizeof (val_desc->bank_field.value)); + + acpi_aml_release_global_lock (locked); + + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Read Data value */ + + status = acpi_aml_access_named_field (ACPI_READ, + (ACPI_HANDLE) val_desc->bank_field.container, + &temp_val, sizeof (temp_val)); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Create an object for the result */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->integer.value = temp_val; + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + if (attached_aml_pointer) { + return (AE_AML_OPERAND_TYPE); + } + + if (INTERNAL_TYPE_INDEX_FIELD != val_desc->common.type) { + return (AE_AML_OPERAND_TYPE); + } + + + /* Set Index value to select proper Data register */ + /* Get the global lock if needed */ + + obj_desc = (ACPI_OPERAND_OBJECT *) *stack_ptr; + locked = acpi_aml_acquire_global_lock (obj_desc->field_unit.lock_rule); + + /* Perform the update */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + val_desc->index_field.index, &val_desc->index_field.value, + sizeof (val_desc->index_field.value)); + + acpi_aml_release_global_lock (locked); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Read Data value */ + + status = acpi_aml_access_named_field (ACPI_READ, val_desc->index_field.data, + &temp_val, sizeof (temp_val)); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Create an object for the result */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->integer.value = temp_val; + break; + + + case ACPI_TYPE_FIELD_UNIT: + + if (attached_aml_pointer) { + return (AE_AML_OPERAND_TYPE); + } + + if (val_desc->common.type != (u8) entry_type) { + return (AE_AML_OPERAND_TYPE); + break; + } + + /* Create object for result */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + status = acpi_aml_get_field_unit_value (val_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + return (status); + } + + break; + + + /* + * For these objects, just return the object attached to the Node + */ + + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_METHOD: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + + /* Return an additional reference to the object */ + + obj_desc = val_desc; + acpi_cm_add_reference (obj_desc); + break; + + + /* TYPE_Any is untyped, and thus there is no object associated with it */ + + case ACPI_TYPE_ANY: + + return (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ + break; + + + /* + * The only named references allowed are named constants + * + * e.g. Name (\OSFL, Ones) + */ + case INTERNAL_TYPE_REFERENCE: + + switch (val_desc->reference.opcode) { + + case AML_ZERO_OP: + + temp_val = 0; + break; + + + case AML_ONE_OP: + + temp_val = 1; + break; + + + case AML_ONES_OP: + + temp_val = ACPI_INTEGER_MAX; + break; + + + default: + + return (AE_AML_BAD_OPCODE); + } + + /* Create object for result */ + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + obj_desc->integer.value = temp_val; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_aml_truncate_for32bit_table (obj_desc, walk_state); + break; + + + /* Default case is for unknown types */ + + default: + + return (AE_AML_OPERAND_TYPE); + + } /* switch (Entry_type) */ + + + /* Put the object descriptor on the stack */ + + *stack_ptr = (void *) obj_desc; + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amresolv.c b/drivers/bus/acpi/executer/amresolv.c new file mode 100644 index 0000000..66d0ef6 --- /dev/null +++ b/drivers/bus/acpi/executer/amresolv.c @@ -0,0 +1,426 @@ + +/****************************************************************************** + * + * Module Name: amresolv - AML Interpreter object resolution + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amresolv") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_get_field_unit_value + * + * PARAMETERS: *Field_desc - Pointer to a Field_unit + * *Result_desc - Pointer to an empty descriptor + * which will become a Number + * containing the field's value. + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from a Field_unit + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_get_field_unit_value ( + ACPI_OPERAND_OBJECT *field_desc, + ACPI_OPERAND_OBJECT *result_desc) +{ + ACPI_STATUS status = AE_OK; + u32 mask; + u8 *location = NULL; + u8 locked = FALSE; + + + if (!field_desc) { + status = AE_AML_NO_OPERAND; + } + + if (!(field_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_field_unit_arguments (field_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + if (!field_desc->field_unit.container) { + status = AE_AML_INTERNAL; + } + + else if (ACPI_TYPE_BUFFER != field_desc->field_unit.container->common.type) { + status = AE_AML_OPERAND_TYPE; + } + + else if (!result_desc) { + status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Get the global lock if needed */ + + locked = acpi_aml_acquire_global_lock (field_desc->field_unit.lock_rule); + + /* Field location is (base of buffer) + (byte offset) */ + + location = field_desc->field_unit.container->buffer.pointer + + field_desc->field_unit.offset; + + /* + * Construct Mask with as many 1 bits as the field width + * + * NOTE: Only the bottom 5 bits are valid for a shift operation, so + * special care must be taken for any shift greater than 31 bits. + * + * TBD: [Unhandled] Fields greater than 32-bits will not work. + */ + + if (field_desc->field_unit.length < 32) { + mask = ((u32) 1 << field_desc->field_unit.length) - (u32) 1; + } + else { + mask = ACPI_UINT32_MAX; + } + + result_desc->integer.type = (u8) ACPI_TYPE_INTEGER; + + /* Get the 32 bit value at the location */ + + MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location); + + /* + * Shift the 32-bit word containing the field, and mask off the + * resulting value + */ + + result_desc->integer.value = + (result_desc->integer.value >> field_desc->field_unit.bit_offset) & mask; + + /* Release global lock if we acquired it earlier */ + + acpi_aml_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_to_value + * + * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can + * be either an (ACPI_OPERAND_OBJECT *) + * or an ACPI_HANDLE. + * + * RETURN: Status + * + * DESCRIPTION: Convert Reference objects to values + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_to_value ( + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + if (!stack_ptr || !*stack_ptr) { + return (AE_AML_NO_OPERAND); + } + + + /* + * The entity pointed to by the Stack_ptr can be either + * 1) A valid ACPI_OPERAND_OBJECT, or + * 2) A ACPI_NAMESPACE_NODE (Named_obj) + */ + + if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) { + + status = acpi_aml_resolve_object_to_value (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Object on the stack may have changed if Acpi_aml_resolve_object_to_value() + * was called (i.e., we can't use an _else_ here.) + */ + + if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) { + status = acpi_aml_resolve_node_to_value ((ACPI_NAMESPACE_NODE **) stack_ptr, walk_state); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_object_to_value + * + * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a + * ptr to an internal object. + * + * RETURN: Status + * + * DESCRIPTION: Retrieve the value from an internal object. The Reference type + * uses the associated AML opcode to determine the value. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_object_to_value ( + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *stack_desc; + ACPI_STATUS status = AE_OK; + ACPI_HANDLE temp_handle = NULL; + ACPI_OPERAND_OBJECT *obj_desc = NULL; + u32 index = 0; + u16 opcode; + + + stack_desc = *stack_ptr; + + /* This is an ACPI_OPERAND_OBJECT */ + + switch (stack_desc->common.type) { + + case INTERNAL_TYPE_REFERENCE: + + opcode = stack_desc->reference.opcode; + + switch (opcode) { + + case AML_NAME_OP: + + /* + * Convert indirect name ptr to a direct name ptr. + * Then, Acpi_aml_resolve_node_to_value can be used to get the value + */ + + temp_handle = stack_desc->reference.object; + + /* Delete the Reference Object */ + + acpi_cm_remove_reference (stack_desc); + + /* Put direct name pointer onto stack and exit */ + + (*stack_ptr) = temp_handle; + status = AE_OK; + break; + + + case AML_LOCAL_OP: + case AML_ARG_OP: + + index = stack_desc->reference.offset; + + /* + * Get the local from the method's state info + * Note: this increments the local's object reference count + */ + + status = acpi_ds_method_data_get_value (opcode, index, + walk_state, &obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Now we can delete the original Reference Object and + * replace it with the resolve value + */ + + acpi_cm_remove_reference (stack_desc); + *stack_ptr = obj_desc; + + break; + + + /* + * TBD: [Restructure] These next three opcodes change the type of + * the object, which is actually a no-no. + */ + + case AML_ZERO_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; + stack_desc->integer.value = 0; + break; + + + case AML_ONE_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; + stack_desc->integer.value = 1; + break; + + + case AML_ONES_OP: + + stack_desc->common.type = (u8) ACPI_TYPE_INTEGER; + stack_desc->integer.value = ACPI_INTEGER_MAX; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_aml_truncate_for32bit_table (stack_desc, walk_state); + break; + + + case AML_INDEX_OP: + + switch (stack_desc->reference.target_type) { + case ACPI_TYPE_BUFFER_FIELD: + + /* Just return - leave the Reference on the stack */ + break; + + + case ACPI_TYPE_PACKAGE: + obj_desc = *stack_desc->reference.where; + if (obj_desc) { + /* + * Valid obj descriptor, copy pointer to return value + * (i.e., dereference the package index) + * Delete the ref object, increment the returned object + */ + acpi_cm_remove_reference (stack_desc); + acpi_cm_add_reference (obj_desc); + *stack_ptr = obj_desc; + } + + else { + /* + * A NULL object descriptor means an unitialized element of + * the package, can't deref it + */ + + status = AE_AML_UNINITIALIZED_ELEMENT; + } + break; + + default: + /* Invalid reference OBJ*/ + + status = AE_AML_INTERNAL; + break; + } + + break; + + + case AML_DEBUG_OP: + + /* Just leave the object as-is */ + break; + + + default: + + status = AE_AML_INTERNAL; + + } /* switch (Opcode) */ + + + if (ACPI_FAILURE (status)) { + return (status); + } + + break; /* case INTERNAL_TYPE_REFERENCE */ + + + case ACPI_TYPE_FIELD_UNIT: + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + /* Descriptor allocation failure */ + + return (AE_NO_MEMORY); + } + + status = acpi_aml_get_field_unit_value (stack_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + + *stack_ptr = (void *) obj_desc; + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY); + if (!obj_desc) { + /* Descriptor allocation failure */ + + return (AE_NO_MEMORY); + } + + status = acpi_aml_get_field_unit_value (stack_desc, obj_desc); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + } + + *stack_ptr = (void *) obj_desc; + break; + + + /* TBD: [Future] - may need to handle Index_field, and Def_field someday */ + + default: + + break; + + } /* switch (Stack_desc->Common.Type) */ + + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amresop.c b/drivers/bus/acpi/executer/amresop.c new file mode 100644 index 0000000..e9e3b3e --- /dev/null +++ b/drivers/bus/acpi/executer/amresop.c @@ -0,0 +1,481 @@ + +/****************************************************************************** + * + * Module Name: amresop - AML Interpreter operand/object resolution + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amresop") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_check_object_type + * + * PARAMETERS: Type_needed Object type needed + * This_type Actual object type + * Object Object pointer + * + * RETURN: Status + * + * DESCRIPTION: Check required type against actual type + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_check_object_type ( + ACPI_OBJECT_TYPE type_needed, + ACPI_OBJECT_TYPE this_type, + void *object) +{ + + + if (type_needed == ACPI_TYPE_ANY) { + /* All types OK, so we don't perform any typechecks */ + + return (AE_OK); + } + + + if (type_needed != this_type) { + return (AE_AML_OPERAND_TYPE); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_operands + * + * PARAMETERS: Opcode Opcode being interpreted + * Stack_ptr Top of operand stack + * + * RETURN: Status + * + * DESCRIPTION: Convert stack entries to required types + * + * Each nibble in Arg_types represents one required operand + * and indicates the required Type: + * + * The corresponding stack entry will be converted to the + * required type if possible, else return an exception + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_operands ( + u16 opcode, + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status = AE_OK; + u8 object_type; + ACPI_HANDLE temp_handle; + u32 arg_types; + ACPI_OPCODE_INFO *op_info; + u32 this_arg_type; + ACPI_OBJECT_TYPE type_needed; + + + op_info = acpi_ps_get_opcode_info (opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + return (AE_AML_BAD_OPCODE); + } + + + arg_types = op_info->runtime_args; + if (arg_types == ARGI_INVALID_OPCODE) { + return (AE_AML_INTERNAL); + } + + + /* + * Normal exit is with *Types == '\0' at end of string. + * Function will return an exception from within the loop upon + * finding an entry which is not, and cannot be converted + * to, the required type; if stack underflows; or upon + * finding a NULL stack entry (which "should never happen"). + */ + + while (GET_CURRENT_ARG_TYPE (arg_types)) { + if (!stack_ptr || !*stack_ptr) { + return (AE_AML_INTERNAL); + } + + /* Extract useful items */ + + obj_desc = *stack_ptr; + + /* Decode the descriptor type */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { + /* Node */ + + object_type = ((ACPI_NAMESPACE_NODE *) obj_desc)->type; + } + + else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { + /* ACPI internal object */ + + object_type = obj_desc->common.type; + + /* Check for bad ACPI_OBJECT_TYPE */ + + if (!acpi_aml_validate_object_type (object_type)) { + return (AE_AML_OPERAND_TYPE); + } + + if (object_type == (u8) INTERNAL_TYPE_REFERENCE) { + /* + * Decode the Reference + */ + + op_info = acpi_ps_get_opcode_info (opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + return (AE_AML_BAD_OPCODE); + } + + + switch (obj_desc->reference.opcode) { + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + case AML_DEBUG_OP: + case AML_NAME_OP: + case AML_INDEX_OP: + case AML_ARG_OP: + case AML_LOCAL_OP: + + break; + + default: + return (AE_AML_OPERAND_TYPE); + break; + } + } + } + + else { + /* Invalid descriptor */ + + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Get one argument type, point to the next + */ + + this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); + INCREMENT_ARG_LIST (arg_types); + + + /* + * Handle cases where the object does not need to be + * resolved to a value + */ + + switch (this_arg_type) { + + case ARGI_REFERENCE: /* References */ + case ARGI_INTEGER_REF: + case ARGI_OBJECT_REF: + case ARGI_DEVICE_REF: + case ARGI_TARGETREF: /* TBD: must implement implicit conversion rules before store */ + case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ + case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ + + /* Need an operand of type INTERNAL_TYPE_REFERENCE */ + + if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { + goto next_operand; + } + + status = acpi_aml_check_object_type (INTERNAL_TYPE_REFERENCE, + object_type, obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + + if (AML_NAME_OP == obj_desc->reference.opcode) { + /* + * Convert an indirect name ptr to direct name ptr and put + * it on the stack + */ + + temp_handle = obj_desc->reference.object; + acpi_cm_remove_reference (obj_desc); + (*stack_ptr) = temp_handle; + } + + goto next_operand; + break; + + + case ARGI_ANYTYPE: + + /* + * We don't want to resolve Index_op reference objects during + * a store because this would be an implicit De_ref_of operation. + * Instead, we just want to store the reference object. + * -- All others must be resolved below. + */ + + if ((opcode == AML_STORE_OP) && + ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) && + ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) { + goto next_operand; + } + break; + } + + + /* + * Resolve this object to a value + */ + + status = acpi_aml_resolve_to_value (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Check the resulting object (value) type + */ + switch (this_arg_type) { + /* + * For the simple cases, only one type of resolved object + * is allowed + */ + case ARGI_MUTEX: + + /* Need an operand of type ACPI_TYPE_MUTEX */ + + type_needed = ACPI_TYPE_MUTEX; + break; + + case ARGI_EVENT: + + /* Need an operand of type ACPI_TYPE_EVENT */ + + type_needed = ACPI_TYPE_EVENT; + break; + + case ARGI_REGION: + + /* Need an operand of type ACPI_TYPE_REGION */ + + type_needed = ACPI_TYPE_REGION; + break; + + case ARGI_IF: /* If */ + + /* Need an operand of type INTERNAL_TYPE_IF */ + + type_needed = INTERNAL_TYPE_IF; + break; + + case ARGI_PACKAGE: /* Package */ + + /* Need an operand of type ACPI_TYPE_PACKAGE */ + + type_needed = ACPI_TYPE_PACKAGE; + break; + + case ARGI_ANYTYPE: + + /* Any operand type will do */ + + type_needed = ACPI_TYPE_ANY; + break; + + + /* + * The more complex cases allow multiple resolved object types + */ + + case ARGI_INTEGER: /* Number */ + + /* + * Need an operand of type ACPI_TYPE_INTEGER, + * But we can implicitly convert from a STRING or BUFFER + */ + status = acpi_aml_convert_to_integer (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + if (status == AE_TYPE) { + return (AE_AML_OPERAND_TYPE); + } + + return (status); + } + + goto next_operand; + break; + + + case ARGI_BUFFER: + + /* + * Need an operand of type ACPI_TYPE_BUFFER, + * But we can implicitly convert from a STRING or INTEGER + */ + status = acpi_aml_convert_to_buffer (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + if (status == AE_TYPE) { + return (AE_AML_OPERAND_TYPE); + } + + return (status); + } + + goto next_operand; + break; + + + case ARGI_STRING: + + /* + * Need an operand of type ACPI_TYPE_STRING, + * But we can implicitly convert from a BUFFER or INTEGER + */ + status = acpi_aml_convert_to_string (stack_ptr, walk_state); + if (ACPI_FAILURE (status)) { + if (status == AE_TYPE) { + return (AE_AML_OPERAND_TYPE); + } + + return (status); + } + + goto next_operand; + break; + + + case ARGI_COMPUTEDATA: + + /* Need an operand of type INTEGER, STRING or BUFFER */ + + if ((ACPI_TYPE_INTEGER != (*stack_ptr)->common.type) && + (ACPI_TYPE_STRING != (*stack_ptr)->common.type) && + (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) { + return (AE_AML_OPERAND_TYPE); + } + goto next_operand; + break; + + + case ARGI_DATAOBJECT: + /* + * ARGI_DATAOBJECT is only used by the Size_of operator. + * + * The ACPI specification allows Size_of to return the size of + * a Buffer, String or Package. However, the MS ACPI.SYS AML + * Interpreter also allows an Node reference to return without + * error with a size of 4. + */ + + /* Need a buffer, string, package or Node reference */ + + if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && + ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && + ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && + ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) { + return (AE_AML_OPERAND_TYPE); + } + + /* + * If this is a reference, only allow a reference to an Node. + */ + if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { + if (!(*stack_ptr)->reference.node) { + return (AE_AML_OPERAND_TYPE); + } + } + goto next_operand; + break; + + + case ARGI_COMPLEXOBJ: + + /* Need a buffer or package */ + + if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && + ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) { + return (AE_AML_OPERAND_TYPE); + } + goto next_operand; + break; + + + default: + + /* Unknown type */ + + return (AE_BAD_PARAMETER); + } + + + /* + * Make sure that the original object was resolved to the + * required object type (Simple cases only). + */ + status = acpi_aml_check_object_type (type_needed, + (*stack_ptr)->common.type, *stack_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + +next_operand: + /* + * If more operands needed, decrement Stack_ptr to point + * to next operand on stack + */ + if (GET_CURRENT_ARG_TYPE (arg_types)) { + stack_ptr--; + } + + } /* while (*Types) */ + + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amstore.c b/drivers/bus/acpi/executer/amstore.c new file mode 100644 index 0000000..90258a5 --- /dev/null +++ b/drivers/bus/acpi/executer/amstore.c @@ -0,0 +1,569 @@ + +/****************************************************************************** + * + * Module Name: amstore - AML Interpreter object store support + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amstore") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exec_store + * + * PARAMETERS: *Val_desc - Value to be stored + * *Dest_desc - Where to store it 0 Must be (ACPI_HANDLE) + * or an ACPI_OPERAND_OBJECT of type + * Reference; if the latter the descriptor + * will be either reused or deleted. + * + * RETURN: Status + * + * DESCRIPTION: Store the value described by Val_desc into the location + * described by Dest_desc. Called by various interpreter + * functions to store the result of an operation into + * the destination operand. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_exec_store ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *ref_desc = dest_desc; + + + /* Validate parameters */ + + if (!val_desc || !dest_desc) { + return (AE_AML_NO_OPERAND); + } + + /* Dest_desc can be either a namespace node or an ACPI object */ + + if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) { + /* + * Dest is a namespace node, + * Storing an object into a Name "container" + */ + status = acpi_aml_store_object_to_node (val_desc, + (ACPI_NAMESPACE_NODE *) dest_desc, walk_state); + + /* All done, that's it */ + + return (status); + } + + + /* Destination object must be an object of type Reference */ + + if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) { + /* Destination is not an Reference */ + + return (AE_AML_OPERAND_TYPE); + } + + + /* + * Examine the Reference opcode. These cases are handled: + * + * 1) Store to Name (Change the object associated with a name) + * 2) Store to an indexed area of a Buffer or Package + * 3) Store to a Method Local or Arg + * 4) Store to the debug object + * 5) Store to a constant -- a noop + */ + + switch (ref_desc->reference.opcode) { + + case AML_NAME_OP: + + /* Storing an object into a Name "container" */ + + status = acpi_aml_store_object_to_node (val_desc, ref_desc->reference.object, + walk_state); + break; + + + case AML_INDEX_OP: + + /* Storing to an Index (pointer into a packager or buffer) */ + + status = acpi_aml_store_object_to_index (val_desc, ref_desc, walk_state); + break; + + + case AML_LOCAL_OP: + case AML_ARG_OP: + + /* Store to a method local/arg */ + + status = acpi_ds_store_object_to_local (ref_desc->reference.opcode, + ref_desc->reference.offset, val_desc, walk_state); + break; + + + case AML_DEBUG_OP: + + /* + * Storing to the Debug object causes the value stored to be + * displayed and otherwise has no effect -- see ACPI Specification + * + * TBD: print known object types "prettier". + */ + + break; + + + case AML_ZERO_OP: + case AML_ONE_OP: + case AML_ONES_OP: + + /* + * Storing to a constant is a no-op -- see ACPI Specification + * Delete the reference descriptor, however + */ + break; + + + default: + + /* TBD: [Restructure] use object dump routine !! */ + + status = AE_AML_INTERNAL; + break; + + } /* switch (Ref_desc->Reference.Opcode) */ + + + /* Always delete the reference descriptor object */ + + if (ref_desc) { + acpi_cm_remove_reference (ref_desc); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_index + * + * PARAMETERS: *Val_desc - Value to be stored + * *Node - Named object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_index ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *obj_desc; + u32 length; + u32 i; + u8 value = 0; + + + /* + * Destination must be a reference pointer, and + * must point to either a buffer or a package + */ + + switch (dest_desc->reference.target_type) { + case ACPI_TYPE_PACKAGE: + /* + * Storing to a package element is not simple. The source must be + * evaluated and converted to the type of the destination and then the + * source is copied into the destination - we can't just point to the + * source object. + */ + if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) { + /* + * The object at *(Dest_desc->Reference.Where) is the + * element within the package that is to be modified. + */ + obj_desc = *(dest_desc->reference.where); + if (obj_desc) { + /* + * If the Destination element is a package, we will delete + * that object and construct a new one. + * + * TBD: [Investigate] Should both the src and dest be required + * to be packages? + * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE) + */ + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + /* + * Take away the reference for being part of a package and + * delete + */ + acpi_cm_remove_reference (obj_desc); + acpi_cm_remove_reference (obj_desc); + + obj_desc = NULL; + } + } + + if (!obj_desc) { + /* + * If the Obj_desc is NULL, it means that an uninitialized package + * element has been used as a destination (this is OK), therefore, + * we must create the destination element to match the type of the + * source element NOTE: Val_desc can be of any type. + */ + obj_desc = acpi_cm_create_internal_object (val_desc->common.type); + if (!obj_desc) { + return (AE_NO_MEMORY); + } + + /* + * If the source is a package, copy the source to the new dest + */ + if (ACPI_TYPE_PACKAGE == obj_desc->common.type) { + status = acpi_cm_copy_ipackage_to_ipackage (val_desc, obj_desc, walk_state); + if (ACPI_FAILURE (status)) { + acpi_cm_remove_reference (obj_desc); + return (status); + } + } + + /* + * Install the new descriptor into the package and add a + * reference to the newly created descriptor for now being + * part of the parent package + */ + + *(dest_desc->reference.where) = obj_desc; + acpi_cm_add_reference (obj_desc); + } + + if (ACPI_TYPE_PACKAGE != obj_desc->common.type) { + /* + * The destination element is not a package, so we need to + * convert the contents of the source (Val_desc) and copy into + * the destination (Obj_desc) + */ + status = acpi_aml_store_object_to_object (val_desc, obj_desc, + walk_state); + if (ACPI_FAILURE (status)) { + /* + * An error occurrered when copying the internal object + * so delete the reference. + */ + return (AE_AML_OPERAND_TYPE); + } + } + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + /* + * Storing into a buffer at a location defined by an Index. + * + * Each 8-bit element of the source object is written to the + * 8-bit Buffer Field of the Index destination object. + */ + + /* + * Set the Obj_desc to the destination object and type check. + */ + obj_desc = dest_desc->reference.object; + if (obj_desc->common.type != ACPI_TYPE_BUFFER) { + return (AE_AML_OPERAND_TYPE); + } + + /* + * The assignment of the individual elements will be slightly + * different for each source type. + */ + + switch (val_desc->common.type) { + /* + * If the type is Integer, assign bytewise + * This loop to assign each of the elements is somewhat + * backward because of the Big Endian-ness of IA-64 + */ + case ACPI_TYPE_INTEGER: + length = sizeof (ACPI_INTEGER); + for (i = length; i != 0; i--) { + value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1))); + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + /* + * If the type is Buffer, the Length is in the structure. + * Just loop through the elements and assign each one in turn. + */ + case ACPI_TYPE_BUFFER: + length = val_desc->buffer.length; + for (i = 0; i < length; i++) { + value = *(val_desc->buffer.pointer + i); + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + /* + * If the type is String, the Length is in the structure. + * Just loop through the elements and assign each one in turn. + */ + case ACPI_TYPE_STRING: + length = val_desc->string.length; + for (i = 0; i < length; i++) { + value = *(val_desc->string.pointer + i); + obj_desc->buffer.pointer[dest_desc->reference.offset] = value; + } + break; + + /* + * If source is not a valid type so return an error. + */ + default: + status = AE_AML_OPERAND_TYPE; + break; + } + break; + + + default: + status = AE_AML_OPERAND_TYPE; + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_node + * + * PARAMETERS: *Source_desc - Value to be stored + * *Node - Named object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store the object to the named object. + * + * The Assignment of an object to a named object is handled here + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * NOTE: the global lock is acquired early. This will result + * in the global lock being held a bit longer. Also, if the + * function fails during set up we may get the lock when we + * don't really need it. I don't think we care. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_node ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *target_desc; + OBJECT_TYPE_INTERNAL target_type = ACPI_TYPE_ANY; + + + /* + * Assuming the parameters were already validated + */ + ACPI_ASSERT((node) && (source_desc)); + + + /* + * Get current type of the node, and object attached to Node + */ + target_type = acpi_ns_get_type (node); + target_desc = acpi_ns_get_attached_object (node); + + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_aml_resolve_object (&source_desc, target_type, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Do the actual store operation + */ + switch (target_type) { + case INTERNAL_TYPE_DEF_FIELD: + + /* Raw data copy for target types Integer/String/Buffer */ + + status = acpi_aml_copy_data_to_named_field (source_desc, node); + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + case ACPI_TYPE_FIELD_UNIT: + + /* + * These target types are all of type Integer/String/Buffer, and + * therefore support implicit conversion before the store. + * + * Copy and/or convert the source object to a new target object + */ + status = acpi_aml_store_object (source_desc, target_type, &target_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Store the new Target_desc as the new value of the Name, and set + * the Name's type to that of the value being stored in it. + * Source_desc reference count is incremented by Attach_object. + */ + status = acpi_ns_attach_object (node, target_desc, target_type); + break; + + + default: + + /* No conversions for all other types. Just attach the source object */ + + status = acpi_ns_attach_object (node, source_desc, source_desc->common.type); + + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object_to_object + * + * PARAMETERS: *Source_desc - Value to be stored + * *Dest_desc - Object to receive the value + * + * RETURN: Status + * + * DESCRIPTION: Store an object to another object. + * + * The Assignment of an object to another (not named) object + * is handled here. + * The val passed in will replace the current value (if any) + * with the input value. + * + * When storing into an object the data is converted to the + * target object type then stored in the object. This means + * that the target object type (for an initialized target) will + * not be changed by a store operation. + * + * This module allows destination types of Number, String, + * and Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object_to_object ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type; + + + /* + * Assuming the parameters are valid! + */ + ACPI_ASSERT((dest_desc) && (source_desc)); + + + /* + * From this interface, we only support Integers/Strings/Buffers + */ + switch (destination_type) { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + break; + + default: + return (AE_NOT_IMPLEMENTED); + } + + + /* + * Resolve the source object to an actual value + * (If it is a reference object) + */ + status = acpi_aml_resolve_object (&source_desc, destination_type, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Copy and/or convert the source object to the destination object + */ + status = acpi_aml_store_object (source_desc, destination_type, &dest_desc, walk_state); + + + return (status); +} + diff --git a/drivers/bus/acpi/executer/amstoren.c b/drivers/bus/acpi/executer/amstoren.c new file mode 100644 index 0000000..4423ab7 --- /dev/null +++ b/drivers/bus/acpi/executer/amstoren.c @@ -0,0 +1,257 @@ + +/****************************************************************************** + * + * Module Name: amstoren - AML Interpreter object store support, + * Store to Node (namespace object) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amstoren") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_resolve_object + * + * PARAMETERS: Source_desc_ptr - Pointer to the source object + * Target_type - Current type of the target + * Walk_state - Current walk state + * + * RETURN: Status, resolved object in Source_desc_ptr. + * + * DESCRIPTION: Resolve an object. If the object is a reference, dereference + * it and return the actual object in the Source_desc_ptr. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_resolve_object ( + ACPI_OPERAND_OBJECT **source_desc_ptr, + OBJECT_TYPE_INTERNAL target_type, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *source_desc = *source_desc_ptr; + ACPI_STATUS status = AE_OK; + + + /* + * Ensure we have a Source that can be stored in the target + */ + switch (target_type) { + + /* This case handles the "interchangeable" types Integer, String, and Buffer. */ + + /* + * These cases all require only Integers or values that + * can be converted to Integers (Strings or Buffers) + */ + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_FIELD_UNIT: + case INTERNAL_TYPE_BANK_FIELD: + case INTERNAL_TYPE_INDEX_FIELD: + + /* + * Stores into a Field/Region or into a Buffer/String + * are all essentially the same. + */ + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case INTERNAL_TYPE_DEF_FIELD: + + /* + * If Source_desc is not a valid type, try to resolve it to one. + */ + if ((source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING)) { + /* + * Initially not a valid type, convert + */ + status = acpi_aml_resolve_to_value (source_desc_ptr, walk_state); + if (ACPI_SUCCESS (status) && + (source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING)) { + /* + * Conversion successful but still not a valid type + */ + status = AE_AML_OPERAND_TYPE; + } + } + break; + + + case INTERNAL_TYPE_ALIAS: + + /* + * Aliases are resolved by Acpi_aml_prep_operands + */ + status = AE_AML_INTERNAL; + break; + + + case ACPI_TYPE_PACKAGE: + default: + + /* + * All other types than Alias and the various Fields come here, + * including the untyped case - ACPI_TYPE_ANY. + */ + break; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_store_object + * + * PARAMETERS: Source_desc - Object to store + * Target_type - Current type of the target + * Target_desc_ptr - Pointer to the target + * Walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object to another object. This may include + * converting the source type to the target type (implicit + * conversion), and a copy of the value of the source to + * the target. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_store_object ( + ACPI_OPERAND_OBJECT *source_desc, + OBJECT_TYPE_INTERNAL target_type, + ACPI_OPERAND_OBJECT **target_desc_ptr, + ACPI_WALK_STATE *walk_state) +{ + ACPI_OPERAND_OBJECT *target_desc = *target_desc_ptr; + ACPI_STATUS status = AE_OK; + + + /* + * Perform the "implicit conversion" of the source to the current type + * of the target - As per the ACPI specification. + * + * If no conversion performed, Source_desc is left alone, otherwise it + * is updated with a new object. + */ + status = acpi_aml_convert_to_target_type (target_type, &source_desc, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * We now have two objects of identical types, and we can perform a + * copy of the *value* of the source object. + */ + switch (target_type) { + case ACPI_TYPE_ANY: + case INTERNAL_TYPE_DEF_ANY: + + /* + * The target namespace node is uninitialized (has no target object), + * and will take on the type of the source object + */ + + *target_desc_ptr = source_desc; + break; + + + case ACPI_TYPE_INTEGER: + + target_desc->integer.value = source_desc->integer.value; + + /* Truncate value if we are executing from a 32-bit ACPI table */ + + acpi_aml_truncate_for32bit_table (target_desc, walk_state); + break; + + + case ACPI_TYPE_FIELD_UNIT: + + status = acpi_aml_copy_integer_to_field_unit (source_desc, target_desc); + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + status = acpi_aml_copy_integer_to_bank_field (source_desc, target_desc); + break; + + + case INTERNAL_TYPE_INDEX_FIELD: + + status = acpi_aml_copy_integer_to_index_field (source_desc, target_desc); + break; + + + case ACPI_TYPE_STRING: + + status = acpi_aml_copy_string_to_string (source_desc, target_desc); + break; + + + case ACPI_TYPE_BUFFER: + + status = acpi_aml_copy_buffer_to_buffer (source_desc, target_desc); + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * TBD: [Unhandled] Not real sure what to do here + */ + status = AE_NOT_IMPLEMENTED; + break; + + + default: + + /* + * All other types come here. + */ + status = AE_NOT_IMPLEMENTED; + break; + } + + + return (status); +} + + diff --git a/drivers/bus/acpi/executer/amstorob.c b/drivers/bus/acpi/executer/amstorob.c new file mode 100644 index 0000000..5e5d045 --- /dev/null +++ b/drivers/bus/acpi/executer/amstorob.c @@ -0,0 +1,433 @@ + +/****************************************************************************** + * + * Module Name: amstorob - AML Interpreter object store support, store to object + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amstorob") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_buffer_to_buffer + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a buffer object to another buffer object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_buffer_to_buffer ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + u32 length; + u8 *buffer; + + + /* + * We know that Source_desc is a buffer by now + */ + buffer = (u8 *) source_desc->buffer.pointer; + length = source_desc->buffer.length; + + /* + * If target is a buffer of length zero, allocate a new + * buffer of the proper length + */ + if (target_desc->buffer.length == 0) { + target_desc->buffer.pointer = acpi_cm_allocate (length); + if (!target_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } + + target_desc->buffer.length = length; + } + + /* + * Buffer is a static allocation, + * only place what will fit in the buffer. + */ + if (length <= target_desc->buffer.length) { + /* Clear existing buffer and copy in the new one */ + + MEMSET(target_desc->buffer.pointer, 0, target_desc->buffer.length); + MEMCPY(target_desc->buffer.pointer, buffer, length); + } + + else { + /* + * Truncate the source, copy only what will fit + */ + MEMCPY(target_desc->buffer.pointer, buffer, target_desc->buffer.length); + + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_string_to_string + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Copy a String object to another String object + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_string_to_string ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + u32 length; + u8 *buffer; + + + /* + * We know that Source_desc is a string by now. + */ + buffer = (u8 *) source_desc->string.pointer; + length = source_desc->string.length; + + /* + * Setting a string value replaces the old string + */ + if (length < target_desc->string.length) { + /* Clear old string and copy in the new one */ + + MEMSET(target_desc->string.pointer, 0, target_desc->string.length); + MEMCPY(target_desc->string.pointer, buffer, length); + } + + else { + /* + * Free the current buffer, then allocate a buffer + * large enough to hold the value + */ + if (target_desc->string.pointer && + !acpi_tb_system_table_pointer (target_desc->string.pointer)) { + /* + * Only free if not a pointer into the DSDT + */ + acpi_cm_free(target_desc->string.pointer); + } + + target_desc->string.pointer = acpi_cm_allocate (length + 1); + if (!target_desc->string.pointer) { + return (AE_NO_MEMORY); + } + target_desc->string.length = length; + + + MEMCPY(target_desc->string.pointer, buffer, length); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_integer_to_index_field + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Write an Integer to an Index Field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_integer_to_index_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + ACPI_STATUS status; + u8 locked; + + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule); + + /* + * Set Index value to select proper Data register + * perform the update (Set index) + */ + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->index_field.index, + &target_desc->index_field.value, + sizeof (target_desc->index_field.value)); + if (ACPI_SUCCESS (status)) { + /* Set_index was successful, next set Data value */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->index_field.data, + &source_desc->integer.value, + sizeof (source_desc->integer.value)); + + } + + + + /* + * Release global lock if we acquired it earlier + */ + acpi_aml_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_integer_to_bank_field + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Write an Integer to a Bank Field + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_integer_to_bank_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + ACPI_STATUS status; + u8 locked; + + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (target_desc->index_field.lock_rule); + + + /* + * Set Bank value to select proper Bank + * Perform the update (Set Bank Select) + */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->bank_field.bank_select, + &target_desc->bank_field.value, + sizeof (target_desc->bank_field.value)); + if (ACPI_SUCCESS (status)) { + /* Set bank select successful, set data value */ + + status = acpi_aml_access_named_field (ACPI_WRITE, + target_desc->bank_field.bank_select, + &source_desc->bank_field.value, + sizeof (source_desc->bank_field.value)); + } + + + + /* + * Release global lock if we acquired it earlier + */ + acpi_aml_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_data_to_named_field + * + * PARAMETERS: Source_desc - Source object to copy + * Node - Destination Namespace node + * + * RETURN: Status + * + * DESCRIPTION: Copy raw data to a Named Field. No implicit conversion + * is performed on the source object + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_data_to_named_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node) +{ + ACPI_STATUS status; + u8 locked; + u32 length; + u8 *buffer; + + + /* + * Named fields (Create_xxx_field) - We don't perform any conversions on the + * source operand, just use the raw data + */ + switch (source_desc->common.type) { + case ACPI_TYPE_INTEGER: + buffer = (u8 *) &source_desc->integer.value; + length = sizeof (source_desc->integer.value); + break; + + case ACPI_TYPE_BUFFER: + buffer = (u8 *) source_desc->buffer.pointer; + length = source_desc->buffer.length; + break; + + case ACPI_TYPE_STRING: + buffer = (u8 *) source_desc->string.pointer; + length = source_desc->string.length; + break; + + default: + return (AE_TYPE); + } + + /* + * Get the global lock if needed before the update + * TBD: not needed! + */ + locked = acpi_aml_acquire_global_lock (source_desc->field.lock_rule); + + status = acpi_aml_access_named_field (ACPI_WRITE, + node, buffer, length); + + acpi_aml_release_global_lock (locked); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_copy_integer_to_field_unit + * + * PARAMETERS: Source_desc - Source object to copy + * Target_desc - Destination object of the copy + * + * RETURN: Status + * + * DESCRIPTION: Write an Integer to a Field Unit. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_copy_integer_to_field_unit ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc) +{ + ACPI_STATUS status = AE_OK; + u8 *location = NULL; + u32 mask; + u32 new_value; + u8 locked = FALSE; + + + /* + * If the Field Buffer and Index have not been previously evaluated, + * evaluate them and save the results. + */ + if (!(target_desc->common.flags & AOPOBJ_DATA_VALID)) { + status = acpi_ds_get_field_unit_arguments (target_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + if ((!target_desc->field_unit.container || + ACPI_TYPE_BUFFER != target_desc->field_unit.container->common.type)) { + return (AE_AML_INTERNAL); + } + + /* + * Get the global lock if needed + */ + locked = acpi_aml_acquire_global_lock (target_desc->field_unit.lock_rule); + + /* + * TBD: [Unhandled] REMOVE this limitation + * Make sure the operation is within the limits of our implementation + * this is not a Spec limitation!! + */ + if (target_desc->field_unit.length + target_desc->field_unit.bit_offset > 32) { + return (AE_NOT_IMPLEMENTED); + } + + /* Field location is (base of buffer) + (byte offset) */ + + location = target_desc->field_unit.container->buffer.pointer + + target_desc->field_unit.offset; + + /* + * Construct Mask with 1 bits where the field is, + * 0 bits elsewhere + */ + mask = ((u32) 1 << target_desc->field_unit.length) - ((u32)1 + << target_desc->field_unit.bit_offset); + + /* Zero out the field in the buffer */ + + MOVE_UNALIGNED32_TO_32 (&new_value, location); + new_value &= ~mask; + + /* + * Shift and mask the new value into position, + * and or it into the buffer. + */ + new_value |= (source_desc->integer.value << target_desc->field_unit.bit_offset) & + mask; + + /* Store back the value */ + + MOVE_UNALIGNED32_TO_32 (location, &new_value); + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/executer/amsystem.c b/drivers/bus/acpi/executer/amsystem.c new file mode 100644 index 0000000..f0d9196 --- /dev/null +++ b/drivers/bus/acpi/executer/amsystem.c @@ -0,0 +1,326 @@ + +/****************************************************************************** + * + * Module Name: amsystem - Interface to OS services + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "achware.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amsystem") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_wait_semaphore + * + * PARAMETERS: Semaphore - OSD semaphore to wait on + * Timeout - Max time to wait + * + * RETURN: Status + * + * DESCRIPTION: Implements a semaphore wait with a check to see if the + * semaphore is available immediately. If it is not, the + * interpreter is released. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_wait_semaphore ( + ACPI_HANDLE semaphore, + u32 timeout) +{ + ACPI_STATUS status; + + + status = acpi_os_wait_semaphore (semaphore, 1, 0); + if (ACPI_SUCCESS (status)) { + return (status); + } + + if (status == AE_TIME) { + /* We must wait, so unlock the interpreter */ + + acpi_aml_exit_interpreter (); + + status = acpi_os_wait_semaphore (semaphore, 1, timeout); + + /* Reacquire the interpreter */ + + status = acpi_aml_enter_interpreter (); + if (ACPI_SUCCESS (status)) { + /* Restore the timeout exception */ + + status = AE_TIME; + } + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_do_stall + * + * PARAMETERS: How_long - The amount of time to stall + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +void +acpi_aml_system_do_stall ( + u32 how_long) +{ + + if (how_long > 1000) /* 1 millisecond */ { + /* Since this thread will sleep, we must release the interpreter */ + + acpi_aml_exit_interpreter (); + + acpi_os_sleep_usec (how_long); + + /* And now we must get the interpreter again */ + + acpi_aml_enter_interpreter (); + } + + else { + acpi_os_sleep_usec (how_long); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_do_suspend + * + * PARAMETERS: How_long - The amount of time to suspend + * + * RETURN: None + * + * DESCRIPTION: Suspend running thread for specified amount of time. + * + ******************************************************************************/ + +void +acpi_aml_system_do_suspend ( + u32 how_long) +{ + /* Since this thread will sleep, we must release the interpreter */ + + acpi_aml_exit_interpreter (); + + acpi_os_sleep ((u16) (how_long / (u32) 1000), + (u16) (how_long % (u32) 1000)); + + /* And now we must get the interpreter again */ + + acpi_aml_enter_interpreter (); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_acquire_mutex + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This function will cause a lock to be generated + * for the Mutex pointed to by Obj_desc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_acquire_mutex ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Support for the _GL_ Mutex object -- go get the global lock + */ + + if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { + status = acpi_ev_acquire_global_lock (); + return (status); + } + + status = acpi_aml_system_wait_semaphore (obj_desc->mutex.semaphore, + (u32) time_desc->integer.value); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_release_mutex + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to release a + * previously acquired Mutex. If the Mutex variable is set then + * it will be decremented. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_release_mutex ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (!obj_desc) { + return (AE_BAD_PARAMETER); + } + + /* + * Support for the _GL_ Mutex object -- release the global lock + */ + if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { + acpi_ev_release_global_lock (); + return (AE_OK); + } + + status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_signal_event + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: AE_OK + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_signal_event ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (obj_desc) { + status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_wait_event + * + * PARAMETERS: *Time_desc - The 'time to delay' object descriptor + * *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Provides an access point to perform synchronization operations + * within the AML. This operation is a request to wait for an + * event. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_wait_event ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + + + if (obj_desc) { + status = acpi_aml_system_wait_semaphore (obj_desc->event.semaphore, + (u32) time_desc->integer.value); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_system_reset_event + * + * PARAMETERS: *Obj_desc - The object descriptor for this op + * + * RETURN: Status + * + * DESCRIPTION: Reset an event to a known state. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_system_reset_event ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + ACPI_STATUS status = AE_OK; + void *temp_semaphore; + + + /* + * We are going to simply delete the existing semaphore and + * create a new one! + */ + + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore); + if (ACPI_SUCCESS (status)) { + acpi_os_delete_semaphore (obj_desc->event.semaphore); + obj_desc->event.semaphore = temp_semaphore; + } + + return (status); +} + diff --git a/drivers/bus/acpi/executer/amutils.c b/drivers/bus/acpi/executer/amutils.c new file mode 100644 index 0000000..c91e78a --- /dev/null +++ b/drivers/bus/acpi/executer/amutils.c @@ -0,0 +1,363 @@ + +/****************************************************************************** + * + * Module Name: amutils - interpreter/scanner utilities + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_enter_interpreter + * + * PARAMETERS: None + * + * DESCRIPTION: Enter the interpreter execution region + * TBD: should be a macro + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_enter_interpreter (void) +{ + ACPI_STATUS status; + + + status = acpi_cm_acquire_mutex (ACPI_MTX_EXECUTE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_exit_interpreter + * + * PARAMETERS: None + * + * DESCRIPTION: Exit the interpreter execution region + * + * Cases where the interpreter is unlocked: + * 1) Completion of the execution of a control method + * 2) Method blocked on a Sleep() AML opcode + * 3) Method blocked on an Acquire() AML opcode + * 4) Method blocked on a Wait() AML opcode + * 5) Method blocked to acquire the global lock + * 6) Method blocked to execute a serialized control method that is + * already executing + * 7) About to invoke a user-installed opregion handler + * + * TBD: should be a macro + * + ******************************************************************************/ + +void +acpi_aml_exit_interpreter (void) +{ + + acpi_cm_release_mutex (ACPI_MTX_EXECUTE); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_validate_object_type + * + * PARAMETERS: Type Object type to validate + * + * DESCRIPTION: Determine if a type is a valid ACPI object type + * + ******************************************************************************/ + +u8 +acpi_aml_validate_object_type ( + ACPI_OBJECT_TYPE type) +{ + + if ((type > ACPI_TYPE_MAX && type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) { + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_truncate_for32bit_table + * + * PARAMETERS: Obj_desc - Object to be truncated + * Walk_state - Current walk state + * (A method must be executing) + * + * RETURN: none + * + * DESCRIPTION: Truncate a number to 32-bits if the currently executing method + * belongs to a 32-bit ACPI table. + * + ******************************************************************************/ + +void +acpi_aml_truncate_for32bit_table ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state) +{ + + /* + * Object must be a valid number and we must be executing + * a control method + */ + + if ((!obj_desc) || + (obj_desc->common.type != ACPI_TYPE_INTEGER) || + (!walk_state->method_node)) { + return; + } + + if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) { + /* + * We are running a method that exists in a 32-bit ACPI table. + * Truncate the value to 32 bits by zeroing out the upper 32-bit field + */ + obj_desc->integer.value &= (ACPI_INTEGER) ACPI_UINT32_MAX; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_acquire_global_lock + * + * PARAMETERS: Rule - Lock rule: Always_lock, Never_lock + * + * RETURN: TRUE/FALSE indicating whether the lock was actually acquired + * + * DESCRIPTION: Obtain the global lock and keep track of this fact via two + * methods. A global variable keeps the state of the lock, and + * the state is returned to the caller. + * + ******************************************************************************/ + +u8 +acpi_aml_acquire_global_lock ( + u32 rule) +{ + u8 locked = FALSE; + ACPI_STATUS status; + + + /* Only attempt lock if the Rule says so */ + + if (rule == (u32) GLOCK_ALWAYS_LOCK) { + /* We should attempt to get the lock */ + + status = acpi_ev_acquire_global_lock (); + if (ACPI_SUCCESS (status)) { + locked = TRUE; + } + + } + + return (locked); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_release_global_lock + * + * PARAMETERS: Locked_by_me - Return value from corresponding call to + * Acquire_global_lock. + * + * RETURN: Status + * + * DESCRIPTION: Release the global lock if it is locked. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_release_global_lock ( + u8 locked_by_me) +{ + + + /* Only attempt unlock if the caller locked it */ + + if (locked_by_me) { + /* OK, now release the lock */ + + acpi_ev_release_global_lock (); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_digits_needed + * + * PARAMETERS: val - Value to be represented + * base - Base of representation + * + * RETURN: the number of digits needed to represent val in base + * + ******************************************************************************/ + +u32 +acpi_aml_digits_needed ( + ACPI_INTEGER val, + u32 base) +{ + u32 num_digits = 0; + + + if (base < 1) { + REPORT_ERROR (("Aml_digits_needed: Internal error - Invalid base\n")); + } + + else { + for (num_digits = 1 + (val < 0); (val = ACPI_DIVIDE (val,base)); ++num_digits) { ; } + } + + return (num_digits); +} + + +/******************************************************************************* + * + * FUNCTION: ntohl + * + * PARAMETERS: Value - Value to be converted + * + * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) + * + ******************************************************************************/ + +static u32 +_ntohl ( + u32 value) +{ + union { + u32 value; + u8 bytes[4]; + } out; + + union { + u32 value; + u8 bytes[4]; + } in; + + + in.value = value; + + out.bytes[0] = in.bytes[3]; + out.bytes[1] = in.bytes[2]; + out.bytes[2] = in.bytes[1]; + out.bytes[3] = in.bytes[0]; + + return (out.value); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_eisa_id_to_string + * + * PARAMETERS: Numeric_id - EISA ID to be converted + * Out_string - Where to put the converted string (8 bytes) + * + * DESCRIPTION: Convert a numeric EISA ID to string representation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_eisa_id_to_string ( + u32 numeric_id, + NATIVE_CHAR *out_string) +{ + u32 id; + + /* swap to big-endian to get contiguous bits */ + + id = _ntohl (numeric_id); + + out_string[0] = (char) ('@' + ((id >> 26) & 0x1f)); + out_string[1] = (char) ('@' + ((id >> 21) & 0x1f)); + out_string[2] = (char) ('@' + ((id >> 16) & 0x1f)); + out_string[3] = acpi_gbl_hex_to_ascii[(id >> 12) & 0xf]; + out_string[4] = acpi_gbl_hex_to_ascii[(id >> 8) & 0xf]; + out_string[5] = acpi_gbl_hex_to_ascii[(id >> 4) & 0xf]; + out_string[6] = acpi_gbl_hex_to_ascii[id & 0xf]; + out_string[7] = 0; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_unsigned_integer_to_string + * + * PARAMETERS: Value - Value to be converted + * Out_string - Where to put the converted string (8 bytes) + * + * RETURN: Convert a number to string representation + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_unsigned_integer_to_string ( + ACPI_INTEGER value, + NATIVE_CHAR *out_string) +{ + u32 count; + u32 digits_needed; + + + digits_needed = acpi_aml_digits_needed (value, 10); + + out_string[digits_needed] = '\0'; + + for (count = digits_needed; count > 0; count--) { + out_string[count-1] = (NATIVE_CHAR) ('0' + (ACPI_MODULO (value, 10))); + value = ACPI_DIVIDE (value, 10); + } + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/executer/amxface.c b/drivers/bus/acpi/executer/amxface.c new file mode 100644 index 0000000..6cf0259 --- /dev/null +++ b/drivers/bus/acpi/executer/amxface.c @@ -0,0 +1,98 @@ + +/****************************************************************************** + * + * Module Name: amxface - External interpreter interfaces + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + MODULE_NAME ("amxface") + + +/* + * DEFINE_AML_GLOBALS is tested in amlcode.h + * to determine whether certain global names should be "defined" or only + * "declared" in the current compilation. This enhances maintainability + * by enabling a single header file to embody all knowledge of the names + * in question. + * + * Exactly one module of any executable should #define DEFINE_GLOBALS + * before #including the header files which use this convention. The + * names in question will be defined and initialized in that module, + * and declared as extern in all other modules which #include those + * header files. + */ + +#define DEFINE_AML_GLOBALS +#include "amlcode.h" +#include "acparser.h" +#include "acnamesp.h" + + +/******************************************************************************* + * + * FUNCTION: Acpi_aml_execute_method + * + * PARAMETERS: Pcode - Pointer to the pcode stream + * Pcode_length - Length of pcode that comprises the method + * **Params - List of parameters to pass to method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ******************************************************************************/ + +ACPI_STATUS +acpi_aml_execute_method ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc) +{ + ACPI_STATUS status; + + + /* + * The point here is to lock the interpreter and call the low + * level execute. + */ + + status = acpi_aml_enter_interpreter (); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_psx_execute (method_node, params, return_obj_desc); + + acpi_aml_exit_interpreter (); + + return (status); +} + + diff --git a/drivers/bus/acpi/hardware/.cvsignore b/drivers/bus/acpi/hardware/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/hardware/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/hardware/hwacpi.c b/drivers/bus/acpi/hardware/hwacpi.c new file mode 100644 index 0000000..173f687 --- /dev/null +++ b/drivers/bus/acpi/hardware/hwacpi.c @@ -0,0 +1,305 @@ + +/****************************************************************************** + * + * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" + + +#define _COMPONENT ACPI_HARDWARE + MODULE_NAME ("hwacpi") + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and validate various ACPI registers + * + ******************************************************************************/ + +ACPI_STATUS +acpi_hw_initialize ( + void) +{ + ACPI_STATUS status = AE_OK; + u32 index; + + + /* We must have the ACPI tables by the time we get here */ + + if (!acpi_gbl_FADT) { + acpi_gbl_restore_acpi_chipset = FALSE; + + return (AE_NO_ACPI_TABLES); + } + + /* Must support *some* mode! */ +/* + if (!(System_flags & SYS_MODES_MASK)) + { + Restore_acpi_chipset = FALSE; + + return (AE_ERROR); + } + +*/ + + + switch (acpi_gbl_system_flags & SYS_MODES_MASK) { + /* Identify current ACPI/legacy mode */ + + case (SYS_MODE_ACPI): + + acpi_gbl_original_mode = SYS_MODE_ACPI; + break; + + + case (SYS_MODE_LEGACY): + + acpi_gbl_original_mode = SYS_MODE_LEGACY; + break; + + + case (SYS_MODE_ACPI | SYS_MODE_LEGACY): + + if (acpi_hw_get_mode () == SYS_MODE_ACPI) { + acpi_gbl_original_mode = SYS_MODE_ACPI; + } + else { + acpi_gbl_original_mode = SYS_MODE_LEGACY; + } + + break; + } + + + if (acpi_gbl_system_flags & SYS_MODE_ACPI) { + /* Target system supports ACPI mode */ + + /* + * The purpose of this code is to save the initial state + * of the ACPI event enable registers. An exit function will be + * registered which will restore this state when the application + * exits. The exit function will also clear all of the ACPI event + * status bits prior to restoring the original mode. + * + * The location of the PM1a_evt_blk enable registers is defined as the + * base of PM1a_evt_blk + DIV_2(PM1a_evt_blk_length). Since the spec further + * fully defines the PM1a_evt_blk to be a total of 4 bytes, the offset + * for the enable registers is always 2 from the base. It is hard + * coded here. If this changes in the spec, this code will need to + * be modified. The PM1b_evt_blk behaves as expected. + */ + + acpi_gbl_pm1_enable_register_save = (u16) acpi_hw_register_read (ACPI_MTX_LOCK, PM1_EN); + + + /* + * The GPEs behave similarly, except that the length of the register + * block is not fixed, so the buffer must be allocated with malloc + */ + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && + acpi_gbl_FADT->gpe0blk_len) { + /* GPE0 specified in FADT */ + + acpi_gbl_gpe0enable_register_save = + acpi_cm_allocate (DIV_2 (acpi_gbl_FADT->gpe0blk_len)); + if (!acpi_gbl_gpe0enable_register_save) { + return (AE_NO_MEMORY); + } + + /* Save state of GPE0 enable bits */ + + for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe0blk_len); index++) { + acpi_gbl_gpe0enable_register_save[index] = + (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE0_EN_BLOCK | index); + } + } + + else { + acpi_gbl_gpe0enable_register_save = NULL; + } + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && + acpi_gbl_FADT->gpe1_blk_len) { + /* GPE1 defined */ + + acpi_gbl_gpe1_enable_register_save = + acpi_cm_allocate (DIV_2 (acpi_gbl_FADT->gpe1_blk_len)); + if (!acpi_gbl_gpe1_enable_register_save) { + return (AE_NO_MEMORY); + } + + /* save state of GPE1 enable bits */ + + for (index = 0; index < DIV_2 (acpi_gbl_FADT->gpe1_blk_len); index++) { + acpi_gbl_gpe1_enable_register_save[index] = + (u8) acpi_hw_register_read (ACPI_MTX_LOCK, GPE1_EN_BLOCK | index); + } + } + + else { + acpi_gbl_gpe1_enable_register_save = NULL; + } + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_set_mode + * + * PARAMETERS: Mode - SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * RETURN: Status + * + * DESCRIPTION: Transitions the system into the requested mode or does nothing + * if the system is already in that mode. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_hw_set_mode ( + u32 mode) +{ + + ACPI_STATUS status = AE_NO_HARDWARE_RESPONSE; + + + if (mode == SYS_MODE_ACPI) { + /* BIOS should have disabled ALL fixed and GP events */ + + acpi_os_out8 (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_enable); + } + + else if (mode == SYS_MODE_LEGACY) { + /* + * BIOS should clear all fixed status bits and restore fixed event + * enable bits to default + */ + + acpi_os_out8 (acpi_gbl_FADT->smi_cmd, acpi_gbl_FADT->acpi_disable); + } + + if (acpi_hw_get_mode () == mode) { + status = AE_OK; + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_mode + * + * PARAMETERS: none + * + * RETURN: SYS_MODE_ACPI or SYS_MODE_LEGACY + * + * DESCRIPTION: Return current operating state of system. Determined by + * querying the SCI_EN bit. + * + ******************************************************************************/ + +u32 +acpi_hw_get_mode (void) +{ + + + if (acpi_hw_register_bit_access (ACPI_READ, ACPI_MTX_LOCK, SCI_EN)) { + return (SYS_MODE_ACPI); + } + else { + return (SYS_MODE_LEGACY); + } +} + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_mode_capabilities + * + * PARAMETERS: none + * + * RETURN: logical OR of SYS_MODE_ACPI and SYS_MODE_LEGACY determined at initial + * system state. + * + * DESCRIPTION: Returns capablities of system + * + ******************************************************************************/ + +u32 +acpi_hw_get_mode_capabilities (void) +{ + + + if (!(acpi_gbl_system_flags & SYS_MODES_MASK)) { + if (acpi_hw_get_mode () == SYS_MODE_LEGACY) { + /* + * Assume that if this call is being made, Acpi_init has been called + * and ACPI support has been established by the presence of the + * tables. Therefore since we're in SYS_MODE_LEGACY, the system + * must support both modes + */ + + acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY); + } + + else { + /* TBD: [Investigate] !!! this may be unsafe... */ + /* + * system is is ACPI mode, so try to switch back to LEGACY to see if + * it is supported + */ + acpi_hw_set_mode (SYS_MODE_LEGACY); + + if (acpi_hw_get_mode () == SYS_MODE_LEGACY) { + /* Now in SYS_MODE_LEGACY, so both are supported */ + + acpi_gbl_system_flags |= (SYS_MODE_ACPI | SYS_MODE_LEGACY); + acpi_hw_set_mode (SYS_MODE_ACPI); + } + + else { + /* Still in SYS_MODE_ACPI so this must be an ACPI only system */ + + acpi_gbl_system_flags |= SYS_MODE_ACPI; + } + } + } + + return (acpi_gbl_system_flags & SYS_MODES_MASK); +} + + diff --git a/drivers/bus/acpi/hardware/hwgpe.c b/drivers/bus/acpi/hardware/hwgpe.c new file mode 100644 index 0000000..d1ec150 --- /dev/null +++ b/drivers/bus/acpi/hardware/hwgpe.c @@ -0,0 +1,207 @@ + +/****************************************************************************** + * + * Module Name: hwgpe - Low level GPE enable/disable/clear functions + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "achware.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_HARDWARE + MODULE_NAME ("hwgpe") + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_enable_gpe + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Enable a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_enable_gpe ( + u32 gpe_number) +{ + u8 in_byte; + u32 register_index; + u8 bit_mask; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Read the current value of the register, set the appropriate bit + * to enable the GPE, and write out the new register. + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].enable_addr); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, + (u8)(in_byte | bit_mask)); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_disable_gpe + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Disable a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_disable_gpe ( + u32 gpe_number) +{ + u8 in_byte; + u32 register_index; + u8 bit_mask; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Read the current value of the register, clear the appropriate bit, + * and write out the new register value to disable the GPE. + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].enable_addr); + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].enable_addr, + (u8)(in_byte & ~bit_mask)); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_clear_gpe + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Clear a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_clear_gpe ( + u32 gpe_number) +{ + u32 register_index; + u8 bit_mask; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Write a one to the appropriate bit in the status register to + * clear this GPE. + */ + acpi_os_out8 (acpi_gbl_gpe_registers[register_index].status_addr, bit_mask); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_get_gpe_status + * + * PARAMETERS: Gpe_number - The GPE + * + * RETURN: None + * + * DESCRIPTION: Return the status of a single GPE. + * + ******************************************************************************/ + +void +acpi_hw_get_gpe_status ( + u32 gpe_number, + ACPI_EVENT_STATUS *event_status) +{ + u8 in_byte = 0; + u32 register_index = 0; + u8 bit_mask = 0; + + if (!event_status) { + return; + } + + (*event_status) = 0; + + /* + * Translate GPE number to index into global registers array. + */ + register_index = acpi_gbl_gpe_valid[gpe_number]; + + /* + * Figure out the bit offset for this GPE within the target register. + */ + bit_mask = acpi_gbl_decode_to8bit [MOD_8 (gpe_number)]; + + /* + * Enabled?: + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].enable_addr); + + if (bit_mask & in_byte) { + (*event_status) |= ACPI_EVENT_FLAG_ENABLED; + } + + /* + * Set? + */ + in_byte = acpi_os_in8 (acpi_gbl_gpe_registers[register_index].status_addr); + + if (bit_mask & in_byte) { + (*event_status) |= ACPI_EVENT_FLAG_SET; + } +} diff --git a/drivers/bus/acpi/hardware/hwregs.c b/drivers/bus/acpi/hardware/hwregs.c new file mode 100644 index 0000000..36e5d9c --- /dev/null +++ b/drivers/bus/acpi/hardware/hwregs.c @@ -0,0 +1,966 @@ + +/******************************************************************************* + * + * Module Name: hwregs - Read/write access functions for the various ACPI + * control and status registers. + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_HARDWARE + MODULE_NAME ("hwregs") + + +/* This matches the #defines in actypes.h. */ + +NATIVE_CHAR *sleep_state_table[] = {"\\_S0_","\\_S1_","\\_S2_","\\_S3_", + "\\_S4_","\\_S5_","\\_S4_b"}; + + +/******************************************************************************* + * + * FUNCTION: Acpi_hw_get_bit_shift + * + * PARAMETERS: Mask - Input mask to determine bit shift from. + * Must have at least 1 bit set. + * + * RETURN: Bit location of the lsb of the mask + * + * DESCRIPTION: Returns the bit number for the low order bit that's set. + * + ******************************************************************************/ + +u32 +acpi_hw_get_bit_shift ( + u32 mask) { + u32 shift; + + + for (shift = 0; ((mask >> shift) & 1) == 0; shift++) { ; } + + return (shift); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_hw_clear_acpi_status + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Clears all fixed and general purpose status bits + * + ******************************************************************************/ + +void +acpi_hw_clear_acpi_status (void) +{ + u16 gpe_length; + u16 index; + + + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, ALL_FIXED_STS_BITS); + + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address)) { + acpi_os_out16 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm1b_evt_blk.address), + (u16) ALL_FIXED_STS_BITS); + } + + /* now clear the GPE Bits */ + + if (acpi_gbl_FADT->gpe0blk_len) { + gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe0blk_len); + + for (index = 0; index < gpe_length; index++) { + acpi_os_out8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) + index), + (u8) 0xff); + } + } + + if (acpi_gbl_FADT->gpe1_blk_len) { + gpe_length = (u16) DIV_2 (acpi_gbl_FADT->gpe1_blk_len); + + for (index = 0; index < gpe_length; index++) { + acpi_os_out8 ((ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) + index), + (u8) 0xff); + } + } + + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_hw_obtain_sleep_type_register_data + * + * PARAMETERS: Sleep_state - Numeric state requested + * *Slp_Typ_a - Pointer to byte to receive SLP_TYPa value + * *Slp_Typ_b - Pointer to byte to receive SLP_TYPb value + * + * RETURN: Status - ACPI status + * + * DESCRIPTION: Acpi_hw_obtain_sleep_type_register_data() obtains the SLP_TYP and + * SLP_TYPb values for the sleep state requested. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_hw_obtain_sleep_type_register_data ( + u8 sleep_state, + u8 *slp_typ_a, + u8 *slp_typ_b) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *obj_desc; + + + /* + * Validate parameters + */ + + if ((sleep_state > ACPI_S_STATES_MAX) || + !slp_typ_a || !slp_typ_b) { + return (AE_BAD_PARAMETER); + } + + /* + * Acpi_evaluate the namespace object containing the values for this state + */ + + status = acpi_ns_evaluate_by_name (sleep_state_table[sleep_state], NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!obj_desc) { + REPORT_ERROR (("Missing Sleep State object\n")); + return (AE_NOT_EXIST); + } + + /* + * We got something, now ensure it is correct. The object must + * be a package and must have at least 2 numeric values as the + * two elements + */ + + /* Even though Acpi_evaluate_object resolves package references, + * Ns_evaluate dpesn't. So, we do it here. + */ + status = acpi_cm_resolve_package_references(obj_desc); + + if (obj_desc->package.count < 2) { + /* Must have at least two elements */ + + REPORT_ERROR (("Sleep State package does not have at least two elements\n")); + status = AE_ERROR; + } + + else if (((obj_desc->package.elements[0])->common.type != + ACPI_TYPE_INTEGER) || + ((obj_desc->package.elements[1])->common.type != + ACPI_TYPE_INTEGER)) { + /* Must have two */ + + REPORT_ERROR (("Sleep State package elements are not both of type Number\n")); + status = AE_ERROR; + } + + else { + /* + * Valid _Sx_ package size, type, and value + */ + *slp_typ_a = (u8) (obj_desc->package.elements[0])->integer.value; + + *slp_typ_b = (u8) (obj_desc->package.elements[1])->integer.value; + } + + + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_hw_register_bit_access + * + * PARAMETERS: Read_write - Either ACPI_READ or ACPI_WRITE. + * Use_lock - Lock the hardware + * Register_id - index of ACPI Register to access + * Value - (only used on write) value to write to the + * Register. Shifted all the way right. + * + * RETURN: Value written to or read from specified Register. This value + * is shifted all the way right. + * + * DESCRIPTION: Generic ACPI Register read/write function. + * + ******************************************************************************/ + +u32 +acpi_hw_register_bit_access ( + NATIVE_UINT read_write, + u8 use_lock, + u32 register_id, + ...) /* Value (only used on write) */ +{ + u32 register_value = 0; + u32 mask = 0; + u32 value = 0; + + + if (read_write == ACPI_WRITE) { + va_list marker; + + va_start (marker, register_id); + value = va_arg (marker, u32); + va_end (marker); + } + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + /* + * Decode the Register ID + * Register id = Register block id | bit id + * + * Check bit id to fine locate Register offset. + * check Mask to determine Register offset, and then read-write. + */ + + switch (REGISTER_BLOCK_ID(register_id)) { + case PM1_STS: + + switch (register_id) { + case TMR_STS: + mask = TMR_STS_MASK; + break; + + case BM_STS: + mask = BM_STS_MASK; + break; + + case GBL_STS: + mask = GBL_STS_MASK; + break; + + case PWRBTN_STS: + mask = PWRBTN_STS_MASK; + break; + + case SLPBTN_STS: + mask = SLPBTN_STS_MASK; + break; + + case RTC_STS: + mask = RTC_STS_MASK; + break; + + case WAK_STS: + mask = WAK_STS_MASK; + break; + + default: + mask = 0; + break; + } + + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_STS); + + if (read_write == ACPI_WRITE) { + /* + * Status Registers are different from the rest. Clear by + * writing 1, writing 0 has no effect. So, the only relevent + * information is the single bit we're interested in, all + * others should be written as 0 so they will be left + * unchanged + */ + + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + + if (value) { + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_STS, (u16) value); + + register_value = 0; + } + } + + break; + + + case PM1_EN: + + switch (register_id) { + case TMR_EN: + mask = TMR_EN_MASK; + break; + + case GBL_EN: + mask = GBL_EN_MASK; + break; + + case PWRBTN_EN: + mask = PWRBTN_EN_MASK; + break; + + case SLPBTN_EN: + mask = SLPBTN_EN_MASK; + break; + + case RTC_EN: + mask = RTC_EN_MASK; + break; + + default: + mask = 0; + break; + } + + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_EN); + + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, PM1_EN, (u16) register_value); + } + + break; + + + case PM1_CONTROL: + + switch (register_id) { + case SCI_EN: + mask = SCI_EN_MASK; + break; + + case BM_RLD: + mask = BM_RLD_MASK; + break; + + case GBL_RLS: + mask = GBL_RLS_MASK; + break; + + case SLP_TYPE_A: + case SLP_TYPE_B: + mask = SLP_TYPE_X_MASK; + break; + + case SLP_EN: + mask = SLP_EN_MASK; + break; + + default: + mask = 0; + break; + } + + + /* + * Read the PM1 Control register. + * Note that at this level, the fact that there are actually TWO + * registers (A and B) and that B may not exist, are abstracted. + */ + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM1_CONTROL); + + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + /* + * SLP_TYPE_x Registers are written differently + * than any other control Registers with + * respect to A and B Registers. The value + * for A may be different than the value for B + * + * Therefore, pass the Register_id, not just generic PM1_CONTROL, + * because we need to do different things. Yuck. + */ + + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + register_id, (u16) register_value); + } + break; + + + case PM2_CONTROL: + + switch (register_id) { + case ARB_DIS: + mask = ARB_DIS_MASK; + break; + + default: + mask = 0; + break; + } + + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, PM2_CONTROL); + + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + PM2_CONTROL, (u8) (register_value)); + } + break; + + + case PM_TIMER: + + mask = TMR_VAL_MASK; + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, + PM_TIMER); + break; + + + case GPE1_EN_BLOCK: + case GPE1_STS_BLOCK: + case GPE0_EN_BLOCK: + case GPE0_STS_BLOCK: + + /* Determine the bit to be accessed + * + * (u32) Register_id: + * 31 24 16 8 0 + * +--------+--------+--------+--------+ + * | gpe_block_id | gpe_bit_number | + * +--------+--------+--------+--------+ + * + * gpe_block_id is one of GPE[01]_EN_BLOCK and GPE[01]_STS_BLOCK + * gpe_bit_number is relative from the gpe_block (0x00~0xFF) + */ + + mask = REGISTER_BIT_ID(register_id); /* gpe_bit_number */ + register_id = REGISTER_BLOCK_ID(register_id) | (mask >> 3); + mask = acpi_gbl_decode_to8bit [mask % 8]; + + /* + * The base address of the GPE 0 Register Block + * Plus 1/2 the length of the GPE 0 Register Block + * The enable Register is the Register following the Status Register + * and each Register is defined as 1/2 of the total Register Block + */ + + /* + * This sets the bit within Enable_bit that needs to be written to + * the Register indicated in Mask to a 1, all others are 0 + */ + + /* Now get the current Enable Bits in the selected Reg */ + + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id); + if (read_write == ACPI_WRITE) { + register_value &= ~mask; + value <<= acpi_hw_get_bit_shift (mask); + value &= mask; + register_value |= value; + + /* This write will put the Action state into the General Purpose */ + /* Enable Register indexed by the value in Mask */ + + acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + register_id, (u8) register_value); + register_value = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK, register_id); + } + break; + + + case SMI_CMD_BLOCK: + case PROCESSOR_BLOCK: + /* not used */ + default: + + mask = 0; + break; + } + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + + + register_value &= mask; + register_value >>= acpi_hw_get_bit_shift (mask); + + return (register_value); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_register_read + * + * PARAMETERS: Use_lock - Mutex hw access. + * Register_id - Register_iD + Offset. + * + * RETURN: Value read or written. + * + * DESCRIPTION: Acpi register read function. Registers are read at the + * given offset. + * + ******************************************************************************/ + +u32 +acpi_hw_register_read ( + u8 use_lock, + u32 register_id) +{ + u32 value = 0; + u32 bank_offset; + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + + switch (REGISTER_BLOCK_ID(register_id)) { + case PM1_STS: /* 16-bit access */ + + value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); + value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + break; + + + case PM1_EN: /* 16-bit access*/ + + bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len); + value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); + value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); + break; + + + case PM1_CONTROL: /* 16-bit access */ + + value = acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + value |= acpi_hw_low_level_read (16, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + break; + + + case PM2_CONTROL: /* 8-bit access */ + + value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); + break; + + + case PM_TIMER: /* 32-bit access */ + + value = acpi_hw_low_level_read (32, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + break; + + + case GPE0_STS_BLOCK: /* 8-bit access */ + + value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, 0); + break; + + + case GPE0_EN_BLOCK: /* 8-bit access */ + + bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len); + value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe0blk, bank_offset); + break; + + + case GPE1_STS_BLOCK: /* 8-bit access */ + + value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, 0); + break; + + + case GPE1_EN_BLOCK: /* 8-bit access */ + + bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len); + value = acpi_hw_low_level_read (8, &acpi_gbl_FADT->Xgpe1_blk, bank_offset); + break; + + + case SMI_CMD_BLOCK: /* 8bit */ + + value = (u32) acpi_os_in8 (acpi_gbl_FADT->smi_cmd); + break; + + + default: + value = 0; + break; + } + + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + + return (value); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_register_write + * + * PARAMETERS: Use_lock - Mutex hw access. + * Register_id - Register_iD + Offset. + * + * RETURN: Value read or written. + * + * DESCRIPTION: Acpi register Write function. Registers are written at the + * given offset. + * + ******************************************************************************/ + +void +acpi_hw_register_write ( + u8 use_lock, + u32 register_id, + u32 value) +{ + u32 bank_offset; + + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_acquire_mutex (ACPI_MTX_HARDWARE); + } + + + switch (REGISTER_BLOCK_ID (register_id)) { + case PM1_STS: /* 16-bit access */ + + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, 0); + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, 0); + break; + + + case PM1_EN: /* 16-bit access*/ + + bank_offset = DIV_2 (acpi_gbl_FADT->pm1_evt_len); + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_evt_blk, bank_offset); + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_evt_blk, bank_offset); + break; + + + case PM1_CONTROL: /* 16-bit access */ + + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + break; + + + case PM1_a_CONTROL: /* 16-bit access */ + + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1a_cnt_blk, 0); + break; + + + case PM1_b_CONTROL: /* 16-bit access */ + + acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->Xpm1b_cnt_blk, 0); + break; + + + case PM2_CONTROL: /* 8-bit access */ + + acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xpm2_cnt_blk, 0); + break; + + + case PM_TIMER: /* 32-bit access */ + + acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->Xpm_tmr_blk, 0); + break; + + + case GPE0_STS_BLOCK: /* 8-bit access */ + + acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, 0); + break; + + + case GPE0_EN_BLOCK: /* 8-bit access */ + + bank_offset = DIV_2 (acpi_gbl_FADT->gpe0blk_len); + acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe0blk, bank_offset); + break; + + + case GPE1_STS_BLOCK: /* 8-bit access */ + + acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, 0); + break; + + + case GPE1_EN_BLOCK: /* 8-bit access */ + + bank_offset = DIV_2 (acpi_gbl_FADT->gpe1_blk_len); + acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->Xgpe1_blk, bank_offset); + break; + + + case SMI_CMD_BLOCK: /* 8bit */ + + /* For 2.0, SMI_CMD is always in IO space */ + /* TBD: what about 1.0? 0.71? */ + + acpi_os_out8 (acpi_gbl_FADT->smi_cmd, (u8) value); + break; + + + default: + value = 0; + break; + } + + + if (ACPI_MTX_LOCK == use_lock) { + acpi_cm_release_mutex (ACPI_MTX_HARDWARE); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_low_level_read + * + * PARAMETERS: Register - GAS register structure + * Offset - Offset from the base address in the GAS + * Width - 8, 16, or 32 + * + * RETURN: Value read + * + * DESCRIPTION: Read from either memory, IO, or PCI config space. + * + ******************************************************************************/ + +u32 +acpi_hw_low_level_read ( + u32 width, + ACPI_GAS *reg, + u32 offset) +{ + u32 value = 0; + ACPI_PHYSICAL_ADDRESS mem_address; + ACPI_IO_ADDRESS io_address; + u32 pci_register; + u32 pci_dev_func; + + + /* + * Must have a valid pointer to a GAS structure, and + * a non-zero address within + */ + if ((!reg) || + (!ACPI_VALID_ADDRESS (reg->address))) { + return 0; + } + + + /* + * Three address spaces supported: + * Memory, Io, or PCI config. + */ + + switch (reg->address_space_id) { + case ADDRESS_SPACE_SYSTEM_MEMORY: + + mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + + switch (width) { + case 8: + value = acpi_os_mem_in8 (mem_address); + break; + case 16: + value = acpi_os_mem_in16 (mem_address); + break; + case 32: + value = acpi_os_mem_in32 (mem_address); + break; + } + break; + + + case ADDRESS_SPACE_SYSTEM_IO: + + io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + + switch (width) { + case 8: + value = acpi_os_in8 (io_address); + break; + case 16: + value = acpi_os_in16 (io_address); + break; + case 32: + value = acpi_os_in32 (io_address); + break; + } + break; + + + case ADDRESS_SPACE_PCI_CONFIG: + + pci_dev_func = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (reg->address)); + pci_register = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset; + + switch (width) { + case 8: + acpi_os_read_pci_cfg_byte (0, pci_dev_func, pci_register, (u8 *) &value); + break; + case 16: + acpi_os_read_pci_cfg_word (0, pci_dev_func, pci_register, (u16 *) &value); + break; + case 32: + acpi_os_read_pci_cfg_dword (0, pci_dev_func, pci_register, (u32 *) &value); + break; + } + break; + } + + return value; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_hw_low_level_write + * + * PARAMETERS: Width - 8, 16, or 32 + * Value - To be written + * Register - GAS register structure + * Offset - Offset from the base address in the GAS + * + * + * RETURN: Value read + * + * DESCRIPTION: Read from either memory, IO, or PCI config space. + * + ******************************************************************************/ + +void +acpi_hw_low_level_write ( + u32 width, + u32 value, + ACPI_GAS *reg, + u32 offset) +{ + ACPI_PHYSICAL_ADDRESS mem_address; + ACPI_IO_ADDRESS io_address; + u32 pci_register; + u32 pci_dev_func; + + + /* + * Must have a valid pointer to a GAS structure, and + * a non-zero address within + */ + if ((!reg) || + (!ACPI_VALID_ADDRESS (reg->address))) { + return; + } + + + /* + * Three address spaces supported: + * Memory, Io, or PCI config. + */ + + switch (reg->address_space_id) { + case ADDRESS_SPACE_SYSTEM_MEMORY: + + mem_address = (ACPI_PHYSICAL_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + + switch (width) { + case 8: + acpi_os_mem_out8 (mem_address, (u8) value); + break; + case 16: + acpi_os_mem_out16 (mem_address, (u16) value); + break; + case 32: + acpi_os_mem_out32 (mem_address, (u32) value); + break; + } + break; + + + case ADDRESS_SPACE_SYSTEM_IO: + + io_address = (ACPI_IO_ADDRESS) (ACPI_GET_ADDRESS (reg->address) + offset); + + switch (width) { + case 8: + acpi_os_out8 (io_address, (u8) value); + break; + case 16: + acpi_os_out16 (io_address, (u16) value); + break; + case 32: + acpi_os_out32 (io_address, (u32) value); + break; + } + break; + + + case ADDRESS_SPACE_PCI_CONFIG: + + pci_dev_func = ACPI_PCI_DEVFUN (ACPI_GET_ADDRESS (reg->address)); + pci_register = ACPI_PCI_REGISTER (ACPI_GET_ADDRESS (reg->address)) + offset; + + switch (width) { + case 8: + acpi_os_write_pci_cfg_byte (0, pci_dev_func, pci_register, (u8) value); + break; + case 16: + acpi_os_write_pci_cfg_word (0, pci_dev_func, pci_register, (u16) value); + break; + case 32: + acpi_os_write_pci_cfg_dword (0, pci_dev_func, pci_register, (u32) value); + break; + } + break; + } +} diff --git a/drivers/bus/acpi/hardware/hwsleep.c b/drivers/bus/acpi/hardware/hwsleep.c new file mode 100644 index 0000000..46c0d1f --- /dev/null +++ b/drivers/bus/acpi/hardware/hwsleep.c @@ -0,0 +1,188 @@ + +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "acnamesp.h" +#include "achware.h" + +#define _COMPONENT ACPI_HARDWARE + MODULE_NAME ("hwsleep") + + +/****************************************************************************** + * + * FUNCTION: Acpi_set_firmware_waking_vector + * + * PARAMETERS: Physical_address - Physical address of ACPI real mode + * entry point. + * + * RETURN: AE_OK or AE_ERROR + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_set_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS physical_address) +{ + + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Set the vector */ + + if (acpi_gbl_FACS->vector_width == 32) { + * (u32 *) acpi_gbl_FACS->firmware_waking_vector = (u32) physical_address; + } + else { + *acpi_gbl_FACS->firmware_waking_vector = physical_address; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_firmware_waking_vector + * + * PARAMETERS: *Physical_address - Output buffer where contents of + * the Firmware_waking_vector field of + * the FACS will be stored. + * + * RETURN: Status + * + * DESCRIPTION: Access function for d_firmware_waking_vector field in FACS + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS *physical_address) +{ + + + if (!physical_address) { + return (AE_BAD_PARAMETER); + } + + /* Make sure that we have an FACS */ + + if (!acpi_gbl_FACS) { + return (AE_NO_ACPI_TABLES); + } + + /* Get the vector */ + + if (acpi_gbl_FACS->vector_width == 32) { + *physical_address = * (u32 *) acpi_gbl_FACS->firmware_waking_vector; + } + else { + *physical_address = *acpi_gbl_FACS->firmware_waking_vector; + } + + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: Acpi_enter_sleep_state + * + * PARAMETERS: Sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enter_sleep_state ( + u8 sleep_state) +{ + ACPI_STATUS status; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg; + u8 type_a; + u8 type_b; + u16 PM1_acontrol; + u16 PM1_bcontrol; + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + + status = acpi_hw_obtain_sleep_type_register_data(sleep_state, &type_a, &type_b); + + if (!ACPI_SUCCESS(status)) { + return status; + } + + /* run the _PTS and _GTS methods */ + MEMSET(&arg_list, 0, sizeof(arg_list)); + arg_list.count = 1; + arg_list.pointer = &arg; + + MEMSET(&arg, 0, sizeof(arg)); + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + acpi_evaluate_object(NULL, "\\_PTS", &arg_list, NULL); + acpi_evaluate_object(NULL, "\\_GTS", &arg_list, NULL); + + /* clear wake status */ + acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, WAK_STS, 1); + + PM1_acontrol = (u16) acpi_hw_register_read(ACPI_MTX_LOCK, PM1_CONTROL); + + /* mask off SLP_EN and SLP_TYP fields */ + PM1_acontrol &= 0xC3FF; + + /* mask in SLP_EN */ + PM1_acontrol |= (1 << acpi_hw_get_bit_shift (SLP_EN_MASK)); + + PM1_bcontrol = PM1_acontrol; + + /* mask in SLP_TYP */ + PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK)); + + disable(); + + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol); + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol); + acpi_hw_register_write(ACPI_MTX_LOCK, PM1_CONTROL, + (1 << acpi_hw_get_bit_shift (SLP_EN_MASK))); + + enable(); + + return (AE_OK); +} diff --git a/drivers/bus/acpi/hardware/hwtimer.c b/drivers/bus/acpi/hardware/hwtimer.c new file mode 100644 index 0000000..84a4710 --- /dev/null +++ b/drivers/bus/acpi/hardware/hwtimer.c @@ -0,0 +1,200 @@ + +/****************************************************************************** + * + * Name: hwtimer.c - ACPI Power Management Timer Interface + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "acpi.h" +#include "achware.h" + +#define _COMPONENT ACPI_HARDWARE + MODULE_NAME ("hwtimer") + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer_resolution + * + * PARAMETERS: none + * + * RETURN: Number of bits of resolution in the PM Timer (24 or 32). + * + * DESCRIPTION: Obtains resolution of the ACPI PM Timer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer_resolution ( + u32 *resolution) +{ + if (!resolution) { + return (AE_BAD_PARAMETER); + } + + if (0 == acpi_gbl_FADT->tmr_val_ext) { + *resolution = 24; + } + else { + *resolution = 32; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer + * + * PARAMETERS: none + * + * RETURN: Current value of the ACPI PM Timer (in ticks). + * + * DESCRIPTION: Obtains current value of ACPI PM Timer. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer ( + u32 *ticks) +{ + if (!ticks) { + return (AE_BAD_PARAMETER); + } + + *ticks = acpi_os_in32 ((ACPI_IO_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_timer_duration + * + * PARAMETERS: Start_ticks + * End_ticks + * Time_elapsed + * + * RETURN: Time_elapsed + * + * DESCRIPTION: Computes the time elapsed (in microseconds) between two + * PM Timer time stamps, taking into account the possibility of + * rollovers, the timer resolution, and timer frequency. + * + * The PM Timer's clock ticks at roughly 3.6 times per + * _microsecond_, and its clock continues through Cx state + * transitions (unlike many CPU timestamp counters) -- making it + * a versatile and accurate timer. + * + * Note that this function accomodates only a single timer + * rollover. Thus for 24-bit timers, this function should only + * be used for calculating durations less than ~4.6 seconds + * (~20 hours for 32-bit timers). + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_timer_duration ( + u32 start_ticks, + u32 end_ticks, + u32 *time_elapsed) +{ + u32 delta_ticks = 0; + u32 seconds = 0; + u32 milliseconds = 0; + u32 microseconds = 0; + u32 remainder = 0; + + if (!time_elapsed) { + return (AE_BAD_PARAMETER); + } + + /* + * Compute Tick Delta: + * ------------------- + * Handle (max one) timer rollovers on 24- versus 32-bit timers. + */ + if (start_ticks < end_ticks) { + delta_ticks = end_ticks - start_ticks; + } + else if (start_ticks > end_ticks) { + /* 24-bit Timer */ + if (0 == acpi_gbl_FADT->tmr_val_ext) { + delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF); + } + /* 32-bit Timer */ + else { + delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks; + } + } + else { + *time_elapsed = 0; + return (AE_OK); + } + + /* + * Compute Duration: + * ----------------- + * Since certain compilers (gcc/Linux, argh!) don't support 64-bit + * divides in kernel-space we have to do some trickery to preserve + * accuracy while using 32-bit math. + * + * TODO: Change to use 64-bit math when supported. + * + * The process is as follows: + * 1. Compute the number of seconds by dividing Delta Ticks by + * the timer frequency. + * 2. Compute the number of milliseconds in the remainder from step #1 + * by multiplying by 1000 and then dividing by the timer frequency. + * 3. Compute the number of microseconds in the remainder from step #2 + * by multiplying by 1000 and then dividing by the timer frequency. + * 4. Add the results from steps 1, 2, and 3 to get the total duration. + * + * Example: The time elapsed for Delta_ticks = 0xFFFFFFFF should be + * 1199864031 microseconds. This is computed as follows: + * Step #1: Seconds = 1199; Remainder = 3092840 + * Step #2: Milliseconds = 864; Remainder = 113120 + * Step #3: Microseconds = 31; Remainder = + */ + + /* Step #1 */ + seconds = delta_ticks / PM_TIMER_FREQUENCY; + remainder = delta_ticks % PM_TIMER_FREQUENCY; + + /* Step #2 */ + milliseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; + remainder = (remainder * 1000) % PM_TIMER_FREQUENCY; + + /* Step #3 */ + microseconds = (remainder * 1000) / PM_TIMER_FREQUENCY; + + /* Step #4 */ + *time_elapsed = seconds * 1000000; + *time_elapsed += milliseconds * 1000; + *time_elapsed += microseconds; + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/include/accommon.h b/drivers/bus/acpi/include/accommon.h new file mode 100644 index 0000000..ab26834 --- /dev/null +++ b/drivers/bus/acpi/include/accommon.h @@ -0,0 +1,725 @@ +/****************************************************************************** + * + * Name: accommon.h -- prototypes for the common (subsystem-wide) procedures + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACCOMMON_H +#define _ACCOMMON_H + + +typedef +ACPI_STATUS (*ACPI_PKG_CALLBACK) ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context); + + +ACPI_STATUS +acpi_cm_walk_package_tree ( + ACPI_OPERAND_OBJECT *source_object, + void *target_object, + ACPI_PKG_CALLBACK walk_callback, + void *context); + + +typedef struct acpi_pkg_info +{ + u8 *free_space; + u32 length; + u32 object_space; + u32 num_packages; +} ACPI_PKG_INFO; + +#define REF_INCREMENT (u16) 0 +#define REF_DECREMENT (u16) 1 +#define REF_FORCE_DELETE (u16) 2 + +/* Acpi_cm_dump_buffer */ + +#define DB_BYTE_DISPLAY 1 +#define DB_WORD_DISPLAY 2 +#define DB_DWORD_DISPLAY 4 +#define DB_QWORD_DISPLAY 8 + + +/* Global initialization interfaces */ + +void +acpi_cm_init_globals ( + void); + +void +acpi_cm_terminate ( + void); + + +/* + * Cm_init - miscellaneous initialization and shutdown + */ + +ACPI_STATUS +acpi_cm_hardware_initialize ( + void); + +ACPI_STATUS +acpi_cm_subsystem_shutdown ( + void); + +ACPI_STATUS +acpi_cm_validate_fadt ( + void); + +/* + * Cm_global - Global data structures and procedures + */ + +#ifdef ACPI_DEBUG + +NATIVE_CHAR * +acpi_cm_get_mutex_name ( + u32 mutex_id); + +NATIVE_CHAR * +acpi_cm_get_type_name ( + u32 type); + +NATIVE_CHAR * +acpi_cm_get_region_name ( + u8 space_id); + +#endif + + +u8 +acpi_cm_valid_object_type ( + u32 type); + +ACPI_OWNER_ID +acpi_cm_allocate_owner_id ( + u32 id_type); + + +/* + * Cm_clib - Local implementations of C library functions + */ + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +u32 +acpi_cm_strlen ( + const NATIVE_CHAR *string); + +NATIVE_CHAR * +acpi_cm_strcpy ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string); + +NATIVE_CHAR * +acpi_cm_strncpy ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string, + NATIVE_UINT count); + +u32 +acpi_cm_strncmp ( + const NATIVE_CHAR *string1, + const NATIVE_CHAR *string2, + NATIVE_UINT count); + +u32 +acpi_cm_strcmp ( + const NATIVE_CHAR *string1, + const NATIVE_CHAR *string2); + +NATIVE_CHAR * +acpi_cm_strcat ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string); + +NATIVE_CHAR * +acpi_cm_strncat ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string, + NATIVE_UINT count); + +NATIVE_UINT +acpi_cm_strtoul ( + const NATIVE_CHAR *string, + NATIVE_CHAR **terminator, + NATIVE_UINT base); + +NATIVE_CHAR * +acpi_cm_strstr ( + NATIVE_CHAR *string1, + NATIVE_CHAR *string2); + +NATIVE_CHAR * +acpi_cm_strupr ( + NATIVE_CHAR *src_string); + +void * +acpi_cm_memcpy ( + void *dest, + const void *src, + NATIVE_UINT count); + +void * +acpi_cm_memset ( + void *dest, + NATIVE_UINT value, + NATIVE_UINT count); + +u32 +acpi_cm_to_upper ( + u32 c); + +u32 +acpi_cm_to_lower ( + u32 c); + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + +/* + * Cm_copy - Object construction and conversion interfaces + */ + +ACPI_STATUS +acpi_cm_build_simple_object( + ACPI_OPERAND_OBJECT *obj, + ACPI_OBJECT *user_obj, + u8 *data_space, + u32 *buffer_space_used); + +ACPI_STATUS +acpi_cm_build_package_object ( + ACPI_OPERAND_OBJECT *obj, + u8 *buffer, + u32 *space_used); + +ACPI_STATUS +acpi_cm_copy_iobject_to_eobject ( + ACPI_OPERAND_OBJECT *obj, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_cm_copy_esimple_to_isimple( + ACPI_OBJECT *user_obj, + ACPI_OPERAND_OBJECT *obj); + +ACPI_STATUS +acpi_cm_copy_eobject_to_iobject ( + ACPI_OBJECT *obj, + ACPI_OPERAND_OBJECT *internal_obj); + +ACPI_STATUS +acpi_cm_copy_isimple_to_isimple ( + ACPI_OPERAND_OBJECT *source_obj, + ACPI_OPERAND_OBJECT *dest_obj); + +ACPI_STATUS +acpi_cm_copy_ipackage_to_ipackage ( + ACPI_OPERAND_OBJECT *source_obj, + ACPI_OPERAND_OBJECT *dest_obj, + ACPI_WALK_STATE *walk_state); + + +/* + * Cm_create - Object creation + */ + +ACPI_STATUS +acpi_cm_update_object_reference ( + ACPI_OPERAND_OBJECT *object, + u16 action); + +ACPI_OPERAND_OBJECT * +_cm_create_internal_object ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + OBJECT_TYPE_INTERNAL type); + + +/* + * Cm_debug - Debug interfaces + */ + +u32 +get_debug_level ( + void); + +void +set_debug_level ( + u32 level); + +void +function_trace ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name); + +void +function_trace_ptr ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + void *pointer); + +void +function_trace_u32 ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u32 integer); + +void +function_trace_str ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + NATIVE_CHAR *string); + +void +function_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name); + +void +function_status_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_STATUS status); + +void +function_value_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_INTEGER value); + +void +function_ptr_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u8 *ptr); + +void +debug_print_prefix ( + NATIVE_CHAR *module_name, + u32 line_number); + +void +debug_print ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + u32 print_level, + NATIVE_CHAR *format, ...); + +void +debug_print_raw ( + NATIVE_CHAR *format, ...); + +void +_report_info ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +void +_report_error ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +void +_report_warning ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +void +acpi_cm_dump_buffer ( + u8 *buffer, + u32 count, + u32 display, + u32 component_id); + + +/* + * Cm_delete - Object deletion + */ + +void +acpi_cm_delete_internal_obj ( + ACPI_OPERAND_OBJECT *object); + +void +acpi_cm_delete_internal_package_object ( + ACPI_OPERAND_OBJECT *object); + +void +acpi_cm_delete_internal_simple_object ( + ACPI_OPERAND_OBJECT *object); + +ACPI_STATUS +acpi_cm_delete_internal_object_list ( + ACPI_OPERAND_OBJECT **obj_list); + + +/* + * Cm_eval - object evaluation + */ + +/* Method name strings */ + +#define METHOD_NAME__HID "_HID" +#define METHOD_NAME__UID "_UID" +#define METHOD_NAME__ADR "_ADR" +#define METHOD_NAME__STA "_STA" +#define METHOD_NAME__REG "_REG" +#define METHOD_NAME__SEG "_SEG" +#define METHOD_NAME__BBN "_BBN" + + +ACPI_STATUS +acpi_cm_evaluate_numeric_object ( + NATIVE_CHAR *object_name, + ACPI_NAMESPACE_NODE *device_node, + ACPI_INTEGER *address); + +ACPI_STATUS +acpi_cm_execute_HID ( + ACPI_NAMESPACE_NODE *device_node, + DEVICE_ID *hid); + +ACPI_STATUS +acpi_cm_execute_STA ( + ACPI_NAMESPACE_NODE *device_node, + u32 *status_flags); + +ACPI_STATUS +acpi_cm_execute_UID ( + ACPI_NAMESPACE_NODE *device_node, + DEVICE_ID *uid); + + +/* + * Cm_error - exception interfaces + */ + +NATIVE_CHAR * +acpi_cm_format_exception ( + ACPI_STATUS status); + + +/* + * Cm_mutex - mutual exclusion interfaces + */ + +ACPI_STATUS +acpi_cm_mutex_initialize ( + void); + +void +acpi_cm_mutex_terminate ( + void); + +ACPI_STATUS +acpi_cm_create_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_cm_delete_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_cm_acquire_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + +ACPI_STATUS +acpi_cm_release_mutex ( + ACPI_MUTEX_HANDLE mutex_id); + + +/* + * Cm_object - internal object create/delete/cache routines + */ + +void * +_cm_allocate_object_desc ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id); + +#define acpi_cm_create_internal_object(t) _cm_create_internal_object(_THIS_MODULE,__LINE__,_COMPONENT,t) +#define acpi_cm_allocate_object_desc() _cm_allocate_object_desc(_THIS_MODULE,__LINE__,_COMPONENT) + +void +acpi_cm_delete_object_desc ( + ACPI_OPERAND_OBJECT *object); + +u8 +acpi_cm_valid_internal_object ( + void *object); + + +/* + * Cm_ref_cnt - Object reference count management + */ + +void +acpi_cm_add_reference ( + ACPI_OPERAND_OBJECT *object); + +void +acpi_cm_remove_reference ( + ACPI_OPERAND_OBJECT *object); + +/* + * Cm_size - Object size routines + */ + +ACPI_STATUS +acpi_cm_get_simple_object_size ( + ACPI_OPERAND_OBJECT *obj, + u32 *obj_length); + +ACPI_STATUS +acpi_cm_get_package_object_size ( + ACPI_OPERAND_OBJECT *obj, + u32 *obj_length); + +ACPI_STATUS +acpi_cm_get_object_size( + ACPI_OPERAND_OBJECT *obj, + u32 *obj_length); + + +/* + * Cm_state - Generic state creation/cache routines + */ + +void +acpi_cm_push_generic_state ( + ACPI_GENERIC_STATE **list_head, + ACPI_GENERIC_STATE *state); + +ACPI_GENERIC_STATE * +acpi_cm_pop_generic_state ( + ACPI_GENERIC_STATE **list_head); + + +ACPI_GENERIC_STATE * +acpi_cm_create_generic_state ( + void); + +ACPI_GENERIC_STATE * +acpi_cm_create_update_state ( + ACPI_OPERAND_OBJECT *object, + u16 action); + +ACPI_GENERIC_STATE * +acpi_cm_create_pkg_state ( + void *internal_object, + void *external_object, + u16 index); + +ACPI_STATUS +acpi_cm_create_update_state_and_push ( + ACPI_OPERAND_OBJECT *object, + u16 action, + ACPI_GENERIC_STATE **state_list); + +ACPI_STATUS +acpi_cm_create_pkg_state_and_push ( + void *internal_object, + void *external_object, + u16 index, + ACPI_GENERIC_STATE **state_list); + +ACPI_GENERIC_STATE * +acpi_cm_create_control_state ( + void); + +void +acpi_cm_delete_generic_state ( + ACPI_GENERIC_STATE *state); + +void +acpi_cm_delete_generic_state_cache ( + void); + +void +acpi_cm_delete_object_cache ( + void); + +/* + * Cmutils + */ + +u8 +acpi_cm_valid_acpi_name ( + u32 name); + +u8 +acpi_cm_valid_acpi_character ( + NATIVE_CHAR character); + +ACPI_STATUS +acpi_cm_resolve_package_references ( + ACPI_OPERAND_OBJECT *obj_desc); + +#ifdef ACPI_DEBUG + +void +acpi_cm_display_init_pathname ( + ACPI_HANDLE obj_handle, + char *path); + +#endif + + +/* + * Memory allocation functions and related macros. + * Macros that expand to include filename and line number + */ + +void * +_cm_allocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line); + +void * +_cm_callocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line); + +void +_cm_free ( + void *address, + u32 component, + NATIVE_CHAR *module, + u32 line); + +void +acpi_cm_init_static_object ( + ACPI_OPERAND_OBJECT *obj_desc); + +#define acpi_cm_allocate(a) _cm_allocate(a,_COMPONENT,_THIS_MODULE,__LINE__) +#define acpi_cm_callocate(a) _cm_callocate(a, _COMPONENT,_THIS_MODULE,__LINE__) +#define acpi_cm_free(a) _cm_free(a,_COMPONENT,_THIS_MODULE,__LINE__) + +#ifndef ACPI_DEBUG_TRACK_ALLOCATIONS + +#define acpi_cm_add_element_to_alloc_list(a,b,c,d,e,f) +#define acpi_cm_delete_element_from_alloc_list(a,b,c,d) +#define acpi_cm_dump_current_allocations(a,b) +#define acpi_cm_dump_allocation_info() + +#define DECREMENT_OBJECT_METRICS(a) +#define INCREMENT_OBJECT_METRICS(a) +#define INITIALIZE_ALLOCATION_METRICS() +#define DECREMENT_NAME_TABLE_METRICS(a) +#define INCREMENT_NAME_TABLE_METRICS(a) + +#else + +#define INITIALIZE_ALLOCATION_METRICS() \ + acpi_gbl_current_object_count = 0; \ + acpi_gbl_current_object_size = 0; \ + acpi_gbl_running_object_count = 0; \ + acpi_gbl_running_object_size = 0; \ + acpi_gbl_max_concurrent_object_count = 0; \ + acpi_gbl_max_concurrent_object_size = 0; \ + acpi_gbl_current_alloc_size = 0; \ + acpi_gbl_current_alloc_count = 0; \ + acpi_gbl_running_alloc_size = 0; \ + acpi_gbl_running_alloc_count = 0; \ + acpi_gbl_max_concurrent_alloc_size = 0; \ + acpi_gbl_max_concurrent_alloc_count = 0; \ + acpi_gbl_current_node_count = 0; \ + acpi_gbl_current_node_size = 0; \ + acpi_gbl_max_concurrent_node_count = 0 + + +#define DECREMENT_OBJECT_METRICS(a) \ + acpi_gbl_current_object_count--; \ + acpi_gbl_current_object_size -= a + +#define INCREMENT_OBJECT_METRICS(a) \ + acpi_gbl_current_object_count++; \ + acpi_gbl_running_object_count++; \ + if (acpi_gbl_max_concurrent_object_count < acpi_gbl_current_object_count) \ + { \ + acpi_gbl_max_concurrent_object_count = acpi_gbl_current_object_count; \ + } \ + acpi_gbl_running_object_size += a; \ + acpi_gbl_current_object_size += a; \ + if (acpi_gbl_max_concurrent_object_size < acpi_gbl_current_object_size) \ + { \ + acpi_gbl_max_concurrent_object_size = acpi_gbl_current_object_size; \ + } + +#define DECREMENT_NAME_TABLE_METRICS(a) \ + acpi_gbl_current_node_count--; \ + acpi_gbl_current_node_size -= (a) + +#define INCREMENT_NAME_TABLE_METRICS(a) \ + acpi_gbl_current_node_count++; \ + acpi_gbl_current_node_size+= (a); \ + if (acpi_gbl_max_concurrent_node_count < acpi_gbl_current_node_count) \ + { \ + acpi_gbl_max_concurrent_node_count = acpi_gbl_current_node_count; \ + } \ + + +void +acpi_cm_dump_allocation_info ( + void); + +void +acpi_cm_dump_current_allocations ( + u32 component, + NATIVE_CHAR *module); + +#endif + + +#endif /* _ACCOMMON_H */ diff --git a/drivers/bus/acpi/include/acconfig.h b/drivers/bus/acpi/include/acconfig.h new file mode 100644 index 0000000..435ae48 --- /dev/null +++ b/drivers/bus/acpi/include/acconfig.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * Name: acconfig.h - Global configuration constants + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACCONFIG_H +#define _ACCONFIG_H + + +/****************************************************************************** + * + * Compile-time options + * + *****************************************************************************/ + +/* + * ACPI_DEBUG - This switch enables all the debug facilities of the ACPI + * subsystem. This includes the DEBUG_PRINT output statements + * When disabled, all DEBUG_PRINT statements are compiled out. + * + * ACPI_APPLICATION - Use this switch if the subsystem is going to be run + * at the application level. + * + */ + + +/****************************************************************************** + * + * Subsystem Constants + * + *****************************************************************************/ + + +/* Version string */ + +#define ACPI_CA_VERSION 0x20010313 + + +/* Maximum objects in the various object caches */ + +#define MAX_STATE_CACHE_DEPTH 64 /* State objects for stacks */ +#define MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */ +#define MAX_EXTPARSE_CACHE_DEPTH 64 /* Parse tree objects */ +#define MAX_OBJECT_CACHE_DEPTH 64 /* Interpreter operand objects */ +#define MAX_WALK_CACHE_DEPTH 2 /* Objects for parse tree walks (method execution) */ + + +/* String size constants */ + +#define MAX_STRING_LENGTH 512 +#define PATHNAME_MAX 256 /* A full namespace pathname */ + + +/* Maximum count for a semaphore object */ + +#define MAX_SEMAPHORE_COUNT 256 + + +/* Max reference count (for debug only) */ + +#define MAX_REFERENCE_COUNT 0x200 + + +/* Size of cached memory mapping for system memory operation region */ + +#define SYSMEM_REGION_WINDOW_SIZE 4096 + + +/* + * Debugger threading model + * Use single threaded if the entire subsystem is contained in an application + * Use multiple threaded when the subsystem is running in the kernel. + * + * By default the model is single threaded if ACPI_APPLICATION is set, + * multi-threaded if ACPI_APPLICATION is not set. + */ + +#define DEBUGGER_SINGLE_THREADED 0 +#define DEBUGGER_MULTI_THREADED 1 + +#ifdef ACPI_APPLICATION +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED + +#else +#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED +#endif + + +/****************************************************************************** + * + * ACPI Specification constants (Do not change unless the specification changes) + * + *****************************************************************************/ + +/* + * Method info (in WALK_STATE), containing local variables and argumetns + */ + +#define MTH_NUM_LOCALS 8 +#define MTH_MAX_LOCAL 7 + +#define MTH_NUM_ARGS 7 +#define MTH_MAX_ARG 6 + +/* Maximum length of resulting string when converting from a buffer */ + +#define ACPI_MAX_STRING_CONVERSION 200 + +/* + * Operand Stack (in WALK_STATE), Must be large enough to contain MTH_MAX_ARG + */ + +#define OBJ_NUM_OPERANDS 8 +#define OBJ_MAX_OPERAND 7 + +/* Names within the namespace are 4 bytes long */ + +#define ACPI_NAME_SIZE 4 +#define PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 s8 for separator */ +#define PATH_SEPARATOR '.' + + +/* Constants used in searching for the RSDP in low memory */ + +#define LO_RSDP_WINDOW_BASE 0 /* Physical Address */ +#define HI_RSDP_WINDOW_BASE 0xE0000 /* Physical Address */ +#define LO_RSDP_WINDOW_SIZE 0x400 +#define HI_RSDP_WINDOW_SIZE 0x20000 +#define RSDP_SCAN_STEP 16 + + +#endif /* _ACCONFIG_H */ + diff --git a/drivers/bus/acpi/include/acdebug.h b/drivers/bus/acpi/include/acdebug.h new file mode 100644 index 0000000..c5e0568 --- /dev/null +++ b/drivers/bus/acpi/include/acdebug.h @@ -0,0 +1,411 @@ +/****************************************************************************** + * + * Name: acdebug.h - ACPI/AML debugger + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACDEBUG_H__ +#define __ACDEBUG_H__ + + +#define DB_MAX_ARGS 8 /* Must be max method args + 1 */ + +#define DB_COMMAND_PROMPT '-' +#define DB_EXECUTE_PROMPT '%' + + +extern int optind; +extern NATIVE_CHAR *optarg; +extern u8 *aml_ptr; +extern u32 acpi_aml_length; + +extern u8 opt_tables; +extern u8 opt_disasm; +extern u8 opt_stats; +extern u8 opt_parse_jit; +extern u8 opt_verbose; +extern u8 opt_ini_methods; + + +extern NATIVE_CHAR *args[DB_MAX_ARGS]; +extern NATIVE_CHAR line_buf[80]; +extern NATIVE_CHAR scope_buf[40]; +extern NATIVE_CHAR debug_filename[40]; +extern u8 output_to_file; +extern NATIVE_CHAR *buffer; +extern NATIVE_CHAR *filename; +extern NATIVE_CHAR *INDENT_STRING; +extern u8 acpi_gbl_db_output_flags; +extern u32 acpi_gbl_db_debug_level; +extern u32 acpi_gbl_db_console_debug_level; + +extern u32 num_names; +extern u32 num_methods; +extern u32 num_regions; +extern u32 num_packages; +extern u32 num_aliases; +extern u32 num_devices; +extern u32 num_field_defs; +extern u32 num_thermal_zones; +extern u32 num_nodes; +extern u32 num_grammar_elements; +extern u32 num_method_elements ; +extern u32 num_mutexes; +extern u32 num_power_resources; +extern u32 num_bank_fields ; +extern u32 num_index_fields; +extern u32 num_events; + +extern u32 size_of_parse_tree; +extern u32 size_of_method_trees; +extern u32 size_of_nTes; +extern u32 size_of_acpi_objects; + + +#define BUFFER_SIZE 4196 + +#define DB_REDIRECTABLE_OUTPUT 0x01 +#define DB_CONSOLE_OUTPUT 0x02 +#define DB_DUPLICATE_OUTPUT 0x03 + + +typedef struct command_info +{ + NATIVE_CHAR *name; /* Command Name */ + u8 min_args; /* Minimum arguments required */ + +} COMMAND_INFO; + + +typedef struct argument_info +{ + NATIVE_CHAR *name; /* Argument Name */ + +} ARGUMENT_INFO; + + +#define PARAM_LIST(pl) pl + +#define DBTEST_OUTPUT_LEVEL(lvl) if (opt_verbose) + +#define VERBOSE_PRINT(fp) DBTEST_OUTPUT_LEVEL(lvl) {\ + acpi_os_printf PARAM_LIST(fp);} + +#define EX_NO_SINGLE_STEP 1 +#define EX_SINGLE_STEP 2 + + +/* Prototypes */ + + +/* + * dbapi - external debugger interfaces + */ + +int +acpi_db_initialize ( + void); + +ACPI_STATUS +acpi_db_single_step ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + u8 op_type); + + +/* + * dbcmds - debug commands and output routines + */ + + +void +acpi_db_display_table_info ( + NATIVE_CHAR *table_arg); + +void +acpi_db_unload_acpi_table ( + NATIVE_CHAR *table_arg, + NATIVE_CHAR *instance_arg); + +void +acpi_db_set_method_breakpoint ( + NATIVE_CHAR *location, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +void +acpi_db_set_method_call_breakpoint ( + ACPI_PARSE_OBJECT *op); + +void +acpi_db_disassemble_aml ( + NATIVE_CHAR *statements, + ACPI_PARSE_OBJECT *op); + +void +acpi_db_dump_namespace ( + NATIVE_CHAR *start_arg, + NATIVE_CHAR *depth_arg); + +void +acpi_db_dump_namespace_by_owner ( + NATIVE_CHAR *owner_arg, + NATIVE_CHAR *depth_arg); + +void +acpi_db_send_notify ( + NATIVE_CHAR *name, + u32 value); + +void +acpi_db_set_method_data ( + NATIVE_CHAR *type_arg, + NATIVE_CHAR *index_arg, + NATIVE_CHAR *value_arg); + +ACPI_STATUS +acpi_db_display_objects ( + NATIVE_CHAR *obj_type_arg, + NATIVE_CHAR *display_count_arg); + +ACPI_STATUS +acpi_db_find_name_in_namespace ( + NATIVE_CHAR *name_arg); + +void +acpi_db_set_scope ( + NATIVE_CHAR *name); + +void +acpi_db_find_references ( + NATIVE_CHAR *object_arg); + +void +acpi_db_display_locks (void); + + +void +acpi_db_display_resources ( + NATIVE_CHAR *object_arg); + + +/* + * dbdisasm - AML disassembler + */ + +void +acpi_db_display_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *origin, + u32 num_opcodes); + +void +acpi_db_display_namestring ( + NATIVE_CHAR *name); + +void +acpi_db_display_path ( + ACPI_PARSE_OBJECT *op); + +void +acpi_db_display_opcode ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +void +acpi_db_decode_internal_object ( + ACPI_OPERAND_OBJECT *obj_desc); + + +/* + * dbdisply - debug display commands + */ + + +void +acpi_db_display_method_info ( + ACPI_PARSE_OBJECT *op); + +void +acpi_db_decode_and_display_object ( + NATIVE_CHAR *target, + NATIVE_CHAR *output_type); + +void +acpi_db_display_result_object ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_db_display_all_methods ( + NATIVE_CHAR *display_count_arg); + +void +acpi_db_display_internal_object ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +void +acpi_db_display_arguments ( + void); + +void +acpi_db_display_locals ( + void); + +void +acpi_db_display_results ( + void); + +void +acpi_db_display_calling_tree ( + void); + +void +acpi_db_display_argument_object ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + + +/* + * dbexec - debugger control method execution + */ + +void +acpi_db_execute ( + NATIVE_CHAR *name, + NATIVE_CHAR **args, + u32 flags); + +void +acpi_db_create_execution_threads ( + NATIVE_CHAR *num_threads_arg, + NATIVE_CHAR *num_loops_arg, + NATIVE_CHAR *method_name_arg); + + +/* + * dbfileio - Debugger file I/O commands + */ + +OBJECT_TYPE_INTERNAL +acpi_db_match_argument ( + NATIVE_CHAR *user_argument, + ARGUMENT_INFO *arguments); + + +void +acpi_db_close_debug_file ( + void); + +void +acpi_db_open_debug_file ( + NATIVE_CHAR *name); + +ACPI_STATUS +acpi_db_load_acpi_table ( + NATIVE_CHAR *filename); + + +/* + * dbhistry - debugger HISTORY command + */ + +void +acpi_db_add_to_history ( + NATIVE_CHAR *command_line); + +void +acpi_db_display_history (void); + +NATIVE_CHAR * +acpi_db_get_from_history ( + NATIVE_CHAR *command_num_arg); + + +/* + * dbinput - user front-end to the AML debugger + */ + +ACPI_STATUS +acpi_db_command_dispatch ( + NATIVE_CHAR *input_buffer, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +void +acpi_db_execute_thread ( + void *context); + +ACPI_STATUS +acpi_db_user_commands ( + NATIVE_CHAR prompt, + ACPI_PARSE_OBJECT *op); + + +/* + * dbstats - Generation and display of ACPI table statistics + */ + +void +acpi_db_generate_statistics ( + ACPI_PARSE_OBJECT *root, + u8 is_method); + + +ACPI_STATUS +acpi_db_display_statistics ( + NATIVE_CHAR *type_arg); + + +/* + * dbutils - AML debugger utilities + */ + +void +acpi_db_set_output_destination ( + u32 where); + +void +acpi_db_dump_buffer ( + u32 address); + +void +acpi_db_dump_object ( + ACPI_OBJECT *obj_desc, + u32 level); + +void +acpi_db_prep_namestring ( + NATIVE_CHAR *name); + + +ACPI_STATUS +acpi_db_second_pass_parse ( + ACPI_PARSE_OBJECT *root); + +ACPI_NAMESPACE_NODE * +acpi_db_local_ns_lookup ( + NATIVE_CHAR *name); + + +#endif /* __ACDEBUG_H__ */ diff --git a/drivers/bus/acpi/include/acdispat.h b/drivers/bus/acpi/include/acdispat.h new file mode 100644 index 0000000..db8da3f --- /dev/null +++ b/drivers/bus/acpi/include/acdispat.h @@ -0,0 +1,450 @@ +/****************************************************************************** + * + * Name: acdispat.h - dispatcher (parser to interpreter interface) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _ACDISPAT_H_ +#define _ACDISPAT_H_ + + +#define NAMEOF_LOCAL_NTE "__L0" +#define NAMEOF_ARG_NTE "__A0" + + +/* Common interfaces */ + +ACPI_STATUS +acpi_ds_obj_stack_push ( + void *object, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_obj_stack_pop ( + u32 pop_count, + ACPI_WALK_STATE *walk_state); + +void * +acpi_ds_obj_stack_get_value ( + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_obj_stack_pop_object ( + ACPI_OPERAND_OBJECT **object, + ACPI_WALK_STATE *walk_state); + + +/* dsopcode - support for late evaluation */ + +ACPI_STATUS +acpi_ds_get_field_unit_arguments ( + ACPI_OPERAND_OBJECT *obj_desc); + +ACPI_STATUS +acpi_ds_get_region_arguments ( + ACPI_OPERAND_OBJECT *rgn_desc); + + +/* dsctrl - Parser/Interpreter interface, control stack routines */ + + +ACPI_STATUS +acpi_ds_exec_begin_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +ACPI_STATUS +acpi_ds_exec_end_control_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + + +/* dsexec - Parser/Interpreter interface, method execution callbacks */ + + +ACPI_STATUS +acpi_ds_get_predicate_value ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + u32 has_result_obj); + +ACPI_STATUS +acpi_ds_exec_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op); + +ACPI_STATUS +acpi_ds_exec_end_op ( + ACPI_WALK_STATE *state, + ACPI_PARSE_OBJECT *op); + + +/* dsfield - Parser/Interpreter interface for AML fields */ + + +ACPI_STATUS +acpi_ds_create_field ( + ACPI_PARSE_OBJECT *op, + ACPI_NAMESPACE_NODE *region_node, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_create_bank_field ( + ACPI_PARSE_OBJECT *op, + ACPI_NAMESPACE_NODE *region_node, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_create_index_field ( + ACPI_PARSE_OBJECT *op, + ACPI_HANDLE region_node, + ACPI_WALK_STATE *walk_state); + + +/* dsload - Parser/Interpreter interface, namespace load callbacks */ + +ACPI_STATUS +acpi_ds_load1_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op); + +ACPI_STATUS +acpi_ds_load1_end_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +ACPI_STATUS +acpi_ds_load2_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op); + +ACPI_STATUS +acpi_ds_load2_end_op ( + ACPI_WALK_STATE *state, + ACPI_PARSE_OBJECT *op); + +ACPI_STATUS +acpi_ds_load3_begin_op ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op); + +ACPI_STATUS +acpi_ds_load3_end_op ( + ACPI_WALK_STATE *state, + ACPI_PARSE_OBJECT *op); + + +/* dsmthdat - method data (locals/args) */ + + +ACPI_STATUS +acpi_ds_store_object_to_local ( + u16 opcode, + u32 index, + ACPI_OPERAND_OBJECT *src_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_method_data_get_entry ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT ***node); + +ACPI_STATUS +acpi_ds_method_data_delete_all ( + ACPI_WALK_STATE *walk_state); + +u8 +acpi_ds_is_method_value ( + ACPI_OPERAND_OBJECT *obj_desc); + +OBJECT_TYPE_INTERNAL +acpi_ds_method_data_get_type ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_method_data_get_value ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **dest_desc); + +ACPI_STATUS +acpi_ds_method_data_delete_value ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_method_data_init_args ( + ACPI_OPERAND_OBJECT **params, + u32 max_param_count, + ACPI_WALK_STATE *walk_state); + +ACPI_NAMESPACE_NODE * +acpi_ds_method_data_get_node ( + u16 opcode, + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_method_data_init ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_method_data_set_entry ( + u16 opcode, + u32 index, + ACPI_OPERAND_OBJECT *object, + ACPI_WALK_STATE *walk_state); + + +/* dsmethod - Parser/Interpreter interface - control method parsing */ + +ACPI_STATUS +acpi_ds_parse_method ( + ACPI_HANDLE obj_handle); + +ACPI_STATUS +acpi_ds_call_control_method ( + ACPI_WALK_LIST *walk_list, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +ACPI_STATUS +acpi_ds_restart_control_method ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT *return_desc); + +ACPI_STATUS +acpi_ds_terminate_control_method ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_begin_method_execution ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_NAMESPACE_NODE *calling_method_node); + + +/* dsobj - Parser/Interpreter interface - object initialization and conversion */ + +ACPI_STATUS +acpi_ds_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + +ACPI_STATUS +acpi_ds_initialize_objects ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMESPACE_NODE *start_node); + +ACPI_STATUS +acpi_ds_build_internal_package_obj ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT **obj_desc); + +ACPI_STATUS +acpi_ds_build_internal_object ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT **obj_desc_ptr); + +ACPI_STATUS +acpi_ds_init_object_from_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + u16 opcode, + ACPI_OPERAND_OBJECT **obj_desc); + +ACPI_STATUS +acpi_ds_create_node ( + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE *node, + ACPI_PARSE_OBJECT *op); + + +/* dsregn - Parser/Interpreter interface - Op Region parsing */ + +ACPI_STATUS +acpi_ds_eval_field_unit_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +ACPI_STATUS +acpi_ds_eval_region_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op); + +ACPI_STATUS +acpi_ds_initialize_region ( + ACPI_HANDLE obj_handle); + + +/* dsutils - Parser/Interpreter interface utility routines */ + +u8 +acpi_ds_is_result_used ( + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state); + +void +acpi_ds_delete_result_if_not_used ( + ACPI_PARSE_OBJECT *op, + ACPI_OPERAND_OBJECT *result_obj, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_create_operand ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *arg, + u32 args_remaining); + +ACPI_STATUS +acpi_ds_create_operands ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *first_arg); + +ACPI_STATUS +acpi_ds_resolve_operands ( + ACPI_WALK_STATE *walk_state); + +OBJECT_TYPE_INTERNAL +acpi_ds_map_opcode_to_data_type ( + u16 opcode, + u32 *out_flags); + +OBJECT_TYPE_INTERNAL +acpi_ds_map_named_opcode_to_data_type ( + u16 opcode); + + +/* + * dswscope - Scope Stack manipulation + */ + +ACPI_STATUS +acpi_ds_scope_stack_push ( + ACPI_NAMESPACE_NODE *node, + OBJECT_TYPE_INTERNAL type, + ACPI_WALK_STATE *walk_state); + + +ACPI_STATUS +acpi_ds_scope_stack_pop ( + ACPI_WALK_STATE *walk_state); + +void +acpi_ds_scope_stack_clear ( + ACPI_WALK_STATE *walk_state); + + +/* Acpi_dswstate - parser WALK_STATE management routines */ + +ACPI_WALK_STATE * +acpi_ds_create_walk_state ( + ACPI_OWNER_ID owner_id, + ACPI_PARSE_OBJECT *origin, + ACPI_OPERAND_OBJECT *mth_desc, + ACPI_WALK_LIST *walk_list); + +ACPI_STATUS +acpi_ds_obj_stack_delete_all ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_obj_stack_pop_and_delete ( + u32 pop_count, + ACPI_WALK_STATE *walk_state); + +void +acpi_ds_delete_walk_state ( + ACPI_WALK_STATE *walk_state); + +ACPI_WALK_STATE * +acpi_ds_pop_walk_state ( + ACPI_WALK_LIST *walk_list); + +ACPI_STATUS +acpi_ds_result_stack_pop ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_stack_push ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_stack_clear ( + ACPI_WALK_STATE *walk_state); + +ACPI_WALK_STATE * +acpi_ds_get_current_walk_state ( + ACPI_WALK_LIST *walk_list); + +void +acpi_ds_delete_walk_state_cache ( + void); + +ACPI_STATUS +acpi_ds_result_insert ( + void *object, + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_remove ( + ACPI_OPERAND_OBJECT **object, + u32 index, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_pop ( + ACPI_OPERAND_OBJECT **object, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_push ( + ACPI_OPERAND_OBJECT *object, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ds_result_pop_from_bottom ( + ACPI_OPERAND_OBJECT **object, + ACPI_WALK_STATE *walk_state); + +#endif /* _ACDISPAT_H_ */ diff --git a/drivers/bus/acpi/include/acevents.h b/drivers/bus/acpi/include/acevents.h new file mode 100644 index 0000000..bf91f3a --- /dev/null +++ b/drivers/bus/acpi/include/acevents.h @@ -0,0 +1,203 @@ +/****************************************************************************** + * + * Name: acevents.h - Event subcomponent prototypes and defines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACEVENTS_H__ +#define __ACEVENTS_H__ + + +ACPI_STATUS +acpi_ev_initialize ( + void); + + +/* + * Acpi_evfixed - Fixed event handling + */ + +ACPI_STATUS +acpi_ev_fixed_event_initialize ( + void); + +u32 +acpi_ev_fixed_event_detect ( + void); + +u32 +acpi_ev_fixed_event_dispatch ( + u32 acpi_event); + + +/* + * Acpi_evglock - Global Lock support + */ + +ACPI_STATUS +acpi_ev_acquire_global_lock( + void); + +void +acpi_ev_release_global_lock( + void); + +ACPI_STATUS +acpi_ev_init_global_lock_handler ( + void); + + +/* + * Acpi_evgpe - GPE handling and dispatch + */ + +ACPI_STATUS +acpi_ev_gpe_initialize ( + void); + +ACPI_STATUS +acpi_ev_init_gpe_control_methods ( + void); + +u32 +acpi_ev_gpe_dispatch ( + u32 gpe_number); + +u32 +acpi_ev_gpe_detect ( + void); + + +/* + * Acpi_evnotify - Device Notify handling and dispatch + */ + +ACPI_STATUS +acpi_ev_queue_notify_request ( + ACPI_NAMESPACE_NODE *node, + u32 notify_value); + +void +acpi_ev_notify_dispatch ( + void *context); + +/* + * Acpi_evregion - Address Space handling + */ + +ACPI_STATUS +acpi_ev_install_default_address_space_handlers ( + void); + +ACPI_STATUS +acpi_ev_address_space_dispatch ( + ACPI_OPERAND_OBJECT *region_obj, + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value); + + +ACPI_STATUS +acpi_ev_addr_handler_helper ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + +void +acpi_ev_disassociate_region_from_handler( + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_is_locked); + + +ACPI_STATUS +acpi_ev_associate_region_and_handler ( + ACPI_OPERAND_OBJECT *handler_obj, + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_is_locked); + + +/* + * Acpi_evregini - Region initialization and setup + */ + +ACPI_STATUS +acpi_ev_system_memory_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context); + +ACPI_STATUS +acpi_ev_io_space_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context); + +ACPI_STATUS +acpi_ev_pci_config_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context); + +ACPI_STATUS +acpi_ev_default_region_setup ( + ACPI_HANDLE handle, + u32 function, + void *handler_context, + void **region_context); + +ACPI_STATUS +acpi_ev_initialize_region ( + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_locked); + + +/* + * Evsci - SCI (System Control Interrupt) handling/dispatch + */ + +u32 +acpi_ev_install_sci_handler ( + void); + +ACPI_STATUS +acpi_ev_remove_sci_handler ( + void); + +u32 +acpi_ev_initialize_sCI ( + u32 program_sCI); + +void +acpi_ev_restore_acpi_state ( + void); + +void +acpi_ev_terminate ( + void); + + +#endif /* __ACEVENTS_H__ */ diff --git a/drivers/bus/acpi/include/acexcep.h b/drivers/bus/acpi/include/acexcep.h new file mode 100644 index 0000000..92e2ac6 --- /dev/null +++ b/drivers/bus/acpi/include/acexcep.h @@ -0,0 +1,247 @@ +/****************************************************************************** + * + * Name: acexcep.h - Exception codes returned by the ACPI subsystem + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACEXCEP_H__ +#define __ACEXCEP_H__ + + +/* + * Exceptions returned by external ACPI interfaces + */ + +#define AE_CODE_ENVIRONMENTAL 0x0000 +#define AE_CODE_PROGRAMMER 0x1000 +#define AE_CODE_ACPI_TABLES 0x2000 +#define AE_CODE_AML 0x3000 +#define AE_CODE_CONTROL 0x4000 +#define AE_CODE_MASK 0xF000 + + +#define ACPI_SUCCESS(a) (!(a)) +#define ACPI_FAILURE(a) (a) + + +#define AE_OK (ACPI_STATUS) 0x0000 + +/* + * Environmental exceptions + */ +#define AE_ERROR (ACPI_STATUS) (0x0001 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_ACPI_TABLES (ACPI_STATUS) (0x0002 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_NAMESPACE (ACPI_STATUS) (0x0003 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_MEMORY (ACPI_STATUS) (0x0004 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_FOUND (ACPI_STATUS) (0x0005 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_EXIST (ACPI_STATUS) (0x0006 | AE_CODE_ENVIRONMENTAL) +#define AE_EXIST (ACPI_STATUS) (0x0007 | AE_CODE_ENVIRONMENTAL) +#define AE_TYPE (ACPI_STATUS) (0x0008 | AE_CODE_ENVIRONMENTAL) +#define AE_NULL_OBJECT (ACPI_STATUS) (0x0009 | AE_CODE_ENVIRONMENTAL) +#define AE_NULL_ENTRY (ACPI_STATUS) (0x000A | AE_CODE_ENVIRONMENTAL) +#define AE_BUFFER_OVERFLOW (ACPI_STATUS) (0x000B | AE_CODE_ENVIRONMENTAL) +#define AE_STACK_OVERFLOW (ACPI_STATUS) (0x000C | AE_CODE_ENVIRONMENTAL) +#define AE_STACK_UNDERFLOW (ACPI_STATUS) (0x000D | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_IMPLEMENTED (ACPI_STATUS) (0x000E | AE_CODE_ENVIRONMENTAL) +#define AE_VERSION_MISMATCH (ACPI_STATUS) (0x000F | AE_CODE_ENVIRONMENTAL) +#define AE_SUPPORT (ACPI_STATUS) (0x0010 | AE_CODE_ENVIRONMENTAL) +#define AE_SHARE (ACPI_STATUS) (0x0011 | AE_CODE_ENVIRONMENTAL) +#define AE_LIMIT (ACPI_STATUS) (0x0012 | AE_CODE_ENVIRONMENTAL) +#define AE_TIME (ACPI_STATUS) (0x0013 | AE_CODE_ENVIRONMENTAL) +#define AE_UNKNOWN_STATUS (ACPI_STATUS) (0x0014 | AE_CODE_ENVIRONMENTAL) +#define AE_ACQUIRE_DEADLOCK (ACPI_STATUS) (0x0015 | AE_CODE_ENVIRONMENTAL) +#define AE_RELEASE_DEADLOCK (ACPI_STATUS) (0x0016 | AE_CODE_ENVIRONMENTAL) +#define AE_NOT_ACQUIRED (ACPI_STATUS) (0x0017 | AE_CODE_ENVIRONMENTAL) +#define AE_ALREADY_ACQUIRED (ACPI_STATUS) (0x0018 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_HARDWARE_RESPONSE (ACPI_STATUS) (0x0019 | AE_CODE_ENVIRONMENTAL) +#define AE_NO_GLOBAL_LOCK (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) + +#define AE_CODE_ENV_MAX 0x001A + +/* + * Programmer exceptions + */ +#define AE_BAD_PARAMETER (ACPI_STATUS) (0x0001 | AE_CODE_PROGRAMMER) +#define AE_BAD_CHARACTER (ACPI_STATUS) (0x0002 | AE_CODE_PROGRAMMER) +#define AE_BAD_PATHNAME (ACPI_STATUS) (0x0003 | AE_CODE_PROGRAMMER) +#define AE_BAD_DATA (ACPI_STATUS) (0x0004 | AE_CODE_PROGRAMMER) +#define AE_BAD_ADDRESS (ACPI_STATUS) (0x0005 | AE_CODE_PROGRAMMER) + +#define AE_CODE_PGM_MAX 0x0005 + + +/* + * Acpi table exceptions + */ +#define AE_BAD_SIGNATURE (ACPI_STATUS) (0x0001 | AE_CODE_ACPI_TABLES) +#define AE_BAD_HEADER (ACPI_STATUS) (0x0002 | AE_CODE_ACPI_TABLES) +#define AE_BAD_CHECKSUM (ACPI_STATUS) (0x0003 | AE_CODE_ACPI_TABLES) +#define AE_BAD_VALUE (ACPI_STATUS) (0x0004 | AE_CODE_ACPI_TABLES) + +#define AE_CODE_TBL_MAX 0x0003 + + +/* + * AML exceptions. These are caused by problems with + * the actual AML byte stream + */ +#define AE_AML_ERROR (ACPI_STATUS) (0x0001 | AE_CODE_AML) +#define AE_AML_PARSE (ACPI_STATUS) (0x0002 | AE_CODE_AML) +#define AE_AML_BAD_OPCODE (ACPI_STATUS) (0x0003 | AE_CODE_AML) +#define AE_AML_NO_OPERAND (ACPI_STATUS) (0x0004 | AE_CODE_AML) +#define AE_AML_OPERAND_TYPE (ACPI_STATUS) (0x0005 | AE_CODE_AML) +#define AE_AML_OPERAND_VALUE (ACPI_STATUS) (0x0006 | AE_CODE_AML) +#define AE_AML_UNINITIALIZED_LOCAL (ACPI_STATUS) (0x0007 | AE_CODE_AML) +#define AE_AML_UNINITIALIZED_ARG (ACPI_STATUS) (0x0008 | AE_CODE_AML) +#define AE_AML_UNINITIALIZED_ELEMENT (ACPI_STATUS) (0x0009 | AE_CODE_AML) +#define AE_AML_NUMERIC_OVERFLOW (ACPI_STATUS) (0x000A | AE_CODE_AML) +#define AE_AML_REGION_LIMIT (ACPI_STATUS) (0x000B | AE_CODE_AML) +#define AE_AML_BUFFER_LIMIT (ACPI_STATUS) (0x000C | AE_CODE_AML) +#define AE_AML_PACKAGE_LIMIT (ACPI_STATUS) (0x000D | AE_CODE_AML) +#define AE_AML_DIVIDE_BY_ZERO (ACPI_STATUS) (0x000E | AE_CODE_AML) +#define AE_AML_BAD_NAME (ACPI_STATUS) (0x000F | AE_CODE_AML) +#define AE_AML_NAME_NOT_FOUND (ACPI_STATUS) (0x0010 | AE_CODE_AML) +#define AE_AML_INTERNAL (ACPI_STATUS) (0x0011 | AE_CODE_AML) +#define AE_AML_INVALID_SPACE_ID (ACPI_STATUS) (0x0012 | AE_CODE_AML) +#define AE_AML_STRING_LIMIT (ACPI_STATUS) (0x0013 | AE_CODE_AML) +#define AE_AML_NO_RETURN_VALUE (ACPI_STATUS) (0x0014 | AE_CODE_AML) +#define AE_AML_METHOD_LIMIT (ACPI_STATUS) (0x0015 | AE_CODE_AML) +#define AE_AML_NOT_OWNER (ACPI_STATUS) (0x0016 | AE_CODE_AML) +#define AE_AML_MUTEX_ORDER (ACPI_STATUS) (0x0017 | AE_CODE_AML) +#define AE_AML_MUTEX_NOT_ACQUIRED (ACPI_STATUS) (0x0018 | AE_CODE_AML) + +#define AE_CODE_AML_MAX 0x0018 + +/* + * Internal exceptions used for control + */ +#define AE_CTRL_RETURN_VALUE (ACPI_STATUS) (0x0001 | AE_CODE_CONTROL) +#define AE_CTRL_PENDING (ACPI_STATUS) (0x0002 | AE_CODE_CONTROL) +#define AE_CTRL_TERMINATE (ACPI_STATUS) (0x0003 | AE_CODE_CONTROL) +#define AE_CTRL_TRUE (ACPI_STATUS) (0x0004 | AE_CODE_CONTROL) +#define AE_CTRL_FALSE (ACPI_STATUS) (0x0005 | AE_CODE_CONTROL) +#define AE_CTRL_DEPTH (ACPI_STATUS) (0x0006 | AE_CODE_CONTROL) +#define AE_CTRL_END (ACPI_STATUS) (0x0007 | AE_CODE_CONTROL) +#define AE_CTRL_TRANSFER (ACPI_STATUS) (0x0008 | AE_CODE_CONTROL) + +#define AE_CODE_CTRL_MAX 0x0008 + + +#ifdef DEFINE_ACPI_GLOBALS + +/* + * String versions of the exception codes above + * These strings must match the corresponding defines exactly + */ +static NATIVE_CHAR *acpi_gbl_exception_names_env[] = +{ + "AE_OK", + "AE_ERROR", + "AE_NO_ACPI_TABLES", + "AE_NO_NAMESPACE", + "AE_NO_MEMORY", + "AE_NOT_FOUND", + "AE_NOT_EXIST", + "AE_EXIST", + "AE_TYPE", + "AE_NULL_OBJECT", + "AE_NULL_ENTRY", + "AE_BUFFER_OVERFLOW", + "AE_STACK_OVERFLOW", + "AE_STACK_UNDERFLOW", + "AE_NOT_IMPLEMENTED", + "AE_VERSION_MISMATCH", + "AE_SUPPORT", + "AE_SHARE", + "AE_LIMIT", + "AE_TIME", + "AE_UNKNOWN_STATUS", + "AE_ACQUIRE_DEADLOCK", + "AE_RELEASE_DEADLOCK", + "AE_NOT_ACQUIRED", + "AE_ALREADY_ACQUIRED", + "AE_NO_HARDWARE_RESPONSE", + "AE_NO_GLOBAL_LOCK", +}; + +static NATIVE_CHAR *acpi_gbl_exception_names_pgm[] = +{ + "AE_BAD_PARAMETER", + "AE_BAD_CHARACTER", + "AE_BAD_PATHNAME", + "AE_BAD_DATA", + "AE_BAD_ADDRESS", +}; + +static NATIVE_CHAR *acpi_gbl_exception_names_tbl[] = +{ + "AE_BAD_SIGNATURE", + "AE_BAD_HEADER", + "AE_BAD_CHECKSUM", + "AE_BAD_VALUE", +}; + +static NATIVE_CHAR *acpi_gbl_exception_names_aml[] = +{ + "AE_AML_ERROR", + "AE_AML_PARSE", + "AE_AML_BAD_OPCODE", + "AE_AML_NO_OPERAND", + "AE_AML_OPERAND_TYPE", + "AE_AML_OPERAND_VALUE", + "AE_AML_UNINITIALIZED_LOCAL", + "AE_AML_UNINITIALIZED_ARG", + "AE_AML_UNINITIALIZED_ELEMENT", + "AE_AML_NUMERIC_OVERFLOW", + "AE_AML_REGION_LIMIT", + "AE_AML_BUFFER_LIMIT", + "AE_AML_PACKAGE_LIMIT", + "AE_AML_DIVIDE_BY_ZERO", + "AE_AML_BAD_NAME", + "AE_AML_NAME_NOT_FOUND", + "AE_AML_INTERNAL", + "AE_AML_INVALID_SPACE_ID", + "AE_AML_STRING_LIMIT", + "AE_AML_NO_RETURN_VALUE", + "AE_AML_METHOD_LIMIT", + "AE_AML_NOT_OWNER", + "AE_AML_MUTEX_ORDER", + "AE_AML_MUTEX_NOT_ACQUIRED", +}; + +static NATIVE_CHAR *acpi_gbl_exception_names_ctrl[] = +{ + "AE_CTRL_RETURN_VALUE", + "AE_CTRL_PENDING", + "AE_CTRL_TERMINATE", + "AE_CTRL_TRUE", + "AE_CTRL_FALSE", + "AE_CTRL_DEPTH", + "AE_CTRL_END", + "AE_CTRL_TRANSFER", +}; + + +#endif /* DEFINE_ACPI_GLOBALS */ + + +#endif /* __ACEXCEP_H__ */ diff --git a/drivers/bus/acpi/include/acglobal.h b/drivers/bus/acpi/include/acglobal.h new file mode 100644 index 0000000..6229558 --- /dev/null +++ b/drivers/bus/acpi/include/acglobal.h @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * Name: acglobal.h - Declarations for global variables + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACGLOBAL_H__ +#define __ACGLOBAL_H__ + + +/* + * Ensure that the globals are actually defined only once. + * + * The use of these defines allows a single list of globals (here) in order + * to simplify maintenance of the code. + */ +#ifdef DEFINE_ACPI_GLOBALS +#define ACPI_EXTERN +#else +#define ACPI_EXTERN extern +#endif + + +extern NATIVE_CHAR *msg_acpi_error_break; + +/***************************************************************************** + * + * Debug support + * + ****************************************************************************/ + +/* Runtime configuration of debug print levels */ + +extern u32 acpi_dbg_level; +extern u32 acpi_dbg_layer; + + +/* Procedure nesting level for debug output */ + +extern u32 acpi_gbl_nesting_level; + + +/***************************************************************************** + * + * ACPI Table globals + * + ****************************************************************************/ + +/* + * Table pointers. + * Although these pointers are somewhat redundant with the global Acpi_table, + * they are convenient because they are typed pointers. + * + * These tables are single-table only; meaning that there can be at most one + * of each in the system. Each global points to the actual table. + * + */ +ACPI_EXTERN RSDP_DESCRIPTOR *acpi_gbl_RSDP; +ACPI_EXTERN XSDT_DESCRIPTOR *acpi_gbl_XSDT; +ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT; +ACPI_EXTERN ACPI_TABLE_HEADER *acpi_gbl_DSDT; +ACPI_EXTERN ACPI_COMMON_FACS *acpi_gbl_FACS; + +/* + * Since there may be multiple SSDTs and PSDTS, a single pointer is not + * sufficient; Therefore, there isn't one! + */ + + +/* + * ACPI Table info arrays + */ +extern ACPI_TABLE_DESC acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; +extern ACPI_TABLE_SUPPORT acpi_gbl_acpi_table_data[NUM_ACPI_TABLES]; + +/* + * Predefined mutex objects. This array contains the + * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. + * (The table maps local handles to the real OS handles) + */ +ACPI_EXTERN ACPI_MUTEX_INFO acpi_gbl_acpi_mutex_info [NUM_MTX]; + + +/***************************************************************************** + * + * Miscellaneous globals + * + ****************************************************************************/ + + +ACPI_EXTERN u8 *acpi_gbl_gpe0enable_register_save; +ACPI_EXTERN u8 *acpi_gbl_gpe1_enable_register_save; +ACPI_EXTERN ACPI_WALK_STATE *acpi_gbl_breakpoint_walk; +ACPI_EXTERN ACPI_GENERIC_STATE *acpi_gbl_generic_state_cache; +ACPI_EXTERN ACPI_PARSE_OBJECT *acpi_gbl_parse_cache; +ACPI_EXTERN ACPI_PARSE2_OBJECT *acpi_gbl_ext_parse_cache; +ACPI_EXTERN ACPI_OPERAND_OBJECT *acpi_gbl_object_cache; +ACPI_EXTERN ACPI_WALK_STATE *acpi_gbl_walk_state_cache; +ACPI_EXTERN ACPI_HANDLE acpi_gbl_global_lock_semaphore; + + +ACPI_EXTERN u32 acpi_gbl_global_lock_thread_count; +ACPI_EXTERN u32 acpi_gbl_restore_acpi_chipset; +ACPI_EXTERN u32 acpi_gbl_original_mode; +ACPI_EXTERN u32 acpi_gbl_edge_level_save; +ACPI_EXTERN u32 acpi_gbl_irq_enable_save; +ACPI_EXTERN u32 acpi_gbl_rsdp_original_location; + +ACPI_EXTERN u32 acpi_gbl_state_cache_requests; +ACPI_EXTERN u32 acpi_gbl_state_cache_hits; +ACPI_EXTERN u32 acpi_gbl_parse_cache_requests; +ACPI_EXTERN u32 acpi_gbl_parse_cache_hits; +ACPI_EXTERN u32 acpi_gbl_ext_parse_cache_requests; +ACPI_EXTERN u32 acpi_gbl_ext_parse_cache_hits; +ACPI_EXTERN u32 acpi_gbl_object_cache_requests; +ACPI_EXTERN u32 acpi_gbl_object_cache_hits; +ACPI_EXTERN u32 acpi_gbl_walk_state_cache_requests; +ACPI_EXTERN u32 acpi_gbl_walk_state_cache_hits; +ACPI_EXTERN u32 acpi_gbl_ns_lookup_count; +ACPI_EXTERN u32 acpi_gbl_ps_find_count; + + +ACPI_EXTERN u16 acpi_gbl_generic_state_cache_depth; +ACPI_EXTERN u16 acpi_gbl_parse_cache_depth; +ACPI_EXTERN u16 acpi_gbl_ext_parse_cache_depth; +ACPI_EXTERN u16 acpi_gbl_object_cache_depth; +ACPI_EXTERN u16 acpi_gbl_walk_state_cache_depth; +ACPI_EXTERN u16 acpi_gbl_pm1_enable_register_save; +ACPI_EXTERN u16 acpi_gbl_next_table_owner_id; +ACPI_EXTERN u16 acpi_gbl_next_method_owner_id; + +ACPI_EXTERN u8 acpi_gbl_debugger_configuration; +ACPI_EXTERN u8 acpi_gbl_global_lock_acquired; +ACPI_EXTERN u8 acpi_gbl_step_to_next_call; +ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; +ACPI_EXTERN u8 acpi_gbl_global_lock_present; + +ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_drv_notify; +ACPI_EXTERN ACPI_OBJECT_NOTIFY_HANDLER acpi_gbl_sys_notify; + + +extern u8 acpi_gbl_shutdown; +extern u32 acpi_gbl_system_flags; +extern u32 acpi_gbl_startup_flags; +extern u8 acpi_gbl_decode_to8bit[8]; +extern NATIVE_CHAR acpi_gbl_hex_to_ascii[16]; + + +/***************************************************************************** + * + * Namespace globals + * + ****************************************************************************/ + +#define NUM_NS_TYPES INTERNAL_TYPE_INVALID+1 +#define NUM_PREDEFINED_NAMES 9 + + +ACPI_EXTERN ACPI_NAMESPACE_NODE acpi_gbl_root_node_struct; +ACPI_EXTERN ACPI_NAMESPACE_NODE *acpi_gbl_root_node; + +extern u8 acpi_gbl_ns_properties[NUM_NS_TYPES]; +extern PREDEFINED_NAMES acpi_gbl_pre_defined_names [NUM_PREDEFINED_NAMES]; + + +/* Used to detect memory leaks (DEBUG ONLY) */ + +#ifdef ACPI_DEBUG +ACPI_EXTERN ALLOCATION_INFO *acpi_gbl_head_alloc_ptr; +ACPI_EXTERN ALLOCATION_INFO *acpi_gbl_tail_alloc_ptr; +#endif + + +/***************************************************************************** + * + * Interpreter globals + * + ****************************************************************************/ + + +ACPI_EXTERN ACPI_WALK_LIST *acpi_gbl_current_walk_list; + +/* + * Handle to the last method found - used during pass1 of load + */ +ACPI_EXTERN ACPI_HANDLE acpi_gbl_last_method; + +/* + * Table of Address Space handlers + */ + +ACPI_EXTERN ACPI_ADDRESS_SPACE_INFO acpi_gbl_address_spaces[ACPI_NUM_ADDRESS_SPACES]; + + +/* Control method single step flag */ + +ACPI_EXTERN u8 acpi_gbl_cm_single_step; + + +/***************************************************************************** + * + * Parser globals + * + ****************************************************************************/ + +ACPI_EXTERN ACPI_PARSE_OBJECT *acpi_gbl_parsed_namespace_root; + +/***************************************************************************** + * + * Hardware globals + * + ****************************************************************************/ + +extern ACPI_C_STATE_HANDLER acpi_hw_cx_handlers[MAX_CX_STATES]; +extern u32 acpi_hw_active_cx_state; + + +/***************************************************************************** + * + * Event globals + * + ****************************************************************************/ + +ACPI_EXTERN ACPI_FIXED_EVENT_INFO acpi_gbl_fixed_event_handlers[NUM_FIXED_EVENTS]; + +ACPI_EXTERN ACPI_HANDLE acpi_gbl_gpe_obj_handle; +ACPI_EXTERN u32 acpi_gbl_gpe_register_count; +ACPI_EXTERN ACPI_GPE_REGISTERS *acpi_gbl_gpe_registers; +ACPI_EXTERN ACPI_GPE_LEVEL_INFO *acpi_gbl_gpe_info; + +/* + * Gpe validation and translation table + * Indexed by the GPE number, returns GPE_INVALID if the GPE is not supported. + * Otherwise, returns a valid index into the global GPE table. + * + * This table is needed because the GPE numbers supported by block 1 do not + * have to be contiguous with the GPE numbers supported by block 0. + */ +ACPI_EXTERN u8 acpi_gbl_gpe_valid [NUM_GPE]; + +/* Acpi_event counter for debug only */ + +#ifdef ACPI_DEBUG +ACPI_EXTERN u32 acpi_gbl_event_count[NUM_FIXED_EVENTS]; +#endif + + +/***************************************************************************** + * + * Debugger globals + * + ****************************************************************************/ + +#ifdef ENABLE_DEBUGGER +ACPI_EXTERN u8 acpi_gbl_method_executing; +ACPI_EXTERN u8 acpi_gbl_db_terminate_threads; +#endif + +/* Memory allocation metrics - Debug Only! */ + +#ifdef ACPI_DEBUG + +ACPI_EXTERN u32 acpi_gbl_current_alloc_size; +ACPI_EXTERN u32 acpi_gbl_current_alloc_count; +ACPI_EXTERN u32 acpi_gbl_running_alloc_size; +ACPI_EXTERN u32 acpi_gbl_running_alloc_count; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_alloc_size; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_alloc_count; +ACPI_EXTERN u32 acpi_gbl_current_object_count; +ACPI_EXTERN u32 acpi_gbl_current_object_size; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_object_count; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_object_size; +ACPI_EXTERN u32 acpi_gbl_running_object_count; +ACPI_EXTERN u32 acpi_gbl_running_object_size; +ACPI_EXTERN u32 acpi_gbl_current_node_count; +ACPI_EXTERN u32 acpi_gbl_current_node_size; +ACPI_EXTERN u32 acpi_gbl_max_concurrent_node_count; + +#endif + + +#endif /* __ACGLOBAL_H__ */ diff --git a/drivers/bus/acpi/include/achware.h b/drivers/bus/acpi/include/achware.h new file mode 100644 index 0000000..cc2d628 --- /dev/null +++ b/drivers/bus/acpi/include/achware.h @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Name: achware.h -- hardware specific interfaces + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACHWARE_H__ +#define __ACHWARE_H__ + + +/* PM Timer ticks per second (HZ) */ +#define PM_TIMER_FREQUENCY 3579545 + + +/* Prototypes */ + + +ACPI_STATUS +acpi_hw_initialize ( + void); + +ACPI_STATUS +acpi_hw_shutdown ( + void); + +ACPI_STATUS +acpi_hw_initialize_system_info ( + void); + +ACPI_STATUS +acpi_hw_set_mode ( + u32 mode); + +u32 +acpi_hw_get_mode ( + void); + +u32 +acpi_hw_get_mode_capabilities ( + void); + +/* Register I/O Prototypes */ + + +u32 +acpi_hw_register_bit_access ( + NATIVE_UINT read_write, + u8 use_lock, + u32 register_id, + ... /* DWORD Write Value */); + +u32 +acpi_hw_register_read ( + u8 use_lock, + u32 register_id); + +void +acpi_hw_register_write ( + u8 use_lock, + u32 register_id, + u32 value); + +u32 +acpi_hw_low_level_read ( + u32 width, + ACPI_GAS *reg, + u32 offset); + +void +acpi_hw_low_level_write ( + u32 width, + u32 value, + ACPI_GAS *reg, + u32 offset); + +void +acpi_hw_clear_acpi_status ( + void); + +u32 +acpi_hw_get_bit_shift ( + u32 mask); + + +/* GPE support */ + +void +acpi_hw_enable_gpe ( + u32 gpe_index); + +void +acpi_hw_disable_gpe ( + u32 gpe_index); + +void +acpi_hw_clear_gpe ( + u32 gpe_index); + +void +acpi_hw_get_gpe_status ( + u32 gpe_number, + ACPI_EVENT_STATUS *event_status); + +/* Sleep Prototypes */ + +ACPI_STATUS +acpi_hw_obtain_sleep_type_register_data ( + u8 sleep_state, + u8 *slp_typ_a, + u8 *slp_typ_b); + + +/* ACPI Timer prototypes */ + +ACPI_STATUS +acpi_get_timer_resolution ( + u32 *resolution); + +ACPI_STATUS +acpi_get_timer ( + u32 *ticks); + +ACPI_STATUS +acpi_get_timer_duration ( + u32 start_ticks, + u32 end_ticks, + u32 *time_elapsed); + + +#endif /* __ACHWARE_H__ */ diff --git a/drivers/bus/acpi/include/acinterp.h b/drivers/bus/acpi/include/acinterp.h new file mode 100644 index 0000000..396ad67 --- /dev/null +++ b/drivers/bus/acpi/include/acinterp.h @@ -0,0 +1,632 @@ +/****************************************************************************** + * + * Name: acinterp.h - Interpreter subcomponent prototypes and defines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACINTERP_H__ +#define __ACINTERP_H__ + + +#define WALK_OPERANDS &(walk_state->operands [walk_state->num_operands -1]) + + +/* Interpreter constants */ + +#define AML_END_OF_BLOCK -1 +#define PUSH_PKG_LENGTH 1 +#define DO_NOT_PUSH_PKG_LENGTH 0 + + +#define STACK_TOP 0 +#define STACK_BOTTOM (u32) -1 + +/* Constants for global "When_to_parse_methods" */ + +#define METHOD_PARSE_AT_INIT 0x0 +#define METHOD_PARSE_JUST_IN_TIME 0x1 +#define METHOD_DELETE_AT_COMPLETION 0x2 + + +ACPI_STATUS +acpi_aml_resolve_operands ( + u16 opcode, + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state); + + +/* + * amxface - External interpreter interfaces + */ + +ACPI_STATUS +acpi_aml_load_table ( + ACPI_TABLE_TYPE table_id); + +ACPI_STATUS +acpi_aml_execute_method ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc); + + +/* + * amconvrt - object conversion + */ + +ACPI_STATUS +acpi_aml_convert_to_integer ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_convert_to_buffer ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_convert_to_string ( + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_convert_to_target_type ( + OBJECT_TYPE_INTERNAL destination_type, + ACPI_OPERAND_OBJECT **obj_desc, + ACPI_WALK_STATE *walk_state); + + +/* + * amfield - ACPI AML (p-code) execution - field manipulation + */ + +ACPI_STATUS +acpi_aml_read_field ( + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity); + +ACPI_STATUS +acpi_aml_write_field ( + ACPI_OPERAND_OBJECT *obj_desc, + void *buffer, + u32 buffer_length, + u32 byte_length, + u32 datum_length, + u32 bit_granularity, + u32 byte_granularity); + +ACPI_STATUS +acpi_aml_setup_field ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_OPERAND_OBJECT *rgn_desc, + u32 field_bit_width); + +ACPI_STATUS +acpi_aml_read_field_data ( + ACPI_OPERAND_OBJECT *obj_desc, + u32 field_byte_offset, + u32 field_bit_width, + u32 *value); + +ACPI_STATUS +acpi_aml_access_named_field ( + u32 mode, + ACPI_HANDLE named_field, + void *buffer, + u32 length); + +/* + * ammisc - ACPI AML (p-code) execution - specific opcodes + */ + +ACPI_STATUS +acpi_aml_exec_create_field ( + u8 *aml_ptr, + u32 aml_length, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_reconfiguration ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_fatal ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_index ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + +ACPI_STATUS +acpi_aml_exec_match ( + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + +ACPI_STATUS +acpi_aml_exec_create_mutex ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_processor ( + ACPI_PARSE_OBJECT *op, + ACPI_HANDLE processor_nTE); + +ACPI_STATUS +acpi_aml_exec_create_power_resource ( + ACPI_PARSE_OBJECT *op, + ACPI_HANDLE processor_nTE); + +ACPI_STATUS +acpi_aml_exec_create_region ( + u8 *aml_ptr, + u32 acpi_aml_length, + u8 region_space, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_event ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_alias ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_create_method ( + u8 *aml_ptr, + u32 acpi_aml_length, + u32 method_flags, + ACPI_HANDLE method); + + +/* + * ammutex - mutex support + */ + +ACPI_STATUS +acpi_aml_acquire_mutex ( + ACPI_OPERAND_OBJECT *time_desc, + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_release_mutex ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_release_all_mutexes ( + ACPI_OPERAND_OBJECT *mutex_list); + +void +acpi_aml_unlink_mutex ( + ACPI_OPERAND_OBJECT *obj_desc); + + +/* + * amprep - ACPI AML (p-code) execution - prep utilities + */ + +ACPI_STATUS +acpi_aml_prep_def_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE region, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length); + +ACPI_STATUS +acpi_aml_prep_bank_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE region, + ACPI_HANDLE bank_reg, + u32 bank_val, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length); + +ACPI_STATUS +acpi_aml_prep_index_field_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_HANDLE index_reg, + ACPI_HANDLE data_reg, + u8 field_flags, + u8 field_attribute, + u32 field_position, + u32 field_length); + + +/* + * amsystem - Interface to OS services + */ + +ACPI_STATUS +acpi_aml_system_do_notify_op ( + ACPI_OPERAND_OBJECT *value, + ACPI_OPERAND_OBJECT *obj_desc); + +void +acpi_aml_system_do_suspend( + u32 time); + +void +acpi_aml_system_do_stall ( + u32 time); + +ACPI_STATUS +acpi_aml_system_acquire_mutex( + ACPI_OPERAND_OBJECT *time, + ACPI_OPERAND_OBJECT *obj_desc); + +ACPI_STATUS +acpi_aml_system_release_mutex( + ACPI_OPERAND_OBJECT *obj_desc); + +ACPI_STATUS +acpi_aml_system_signal_event( + ACPI_OPERAND_OBJECT *obj_desc); + +ACPI_STATUS +acpi_aml_system_wait_event( + ACPI_OPERAND_OBJECT *time, + ACPI_OPERAND_OBJECT *obj_desc); + +ACPI_STATUS +acpi_aml_system_reset_event( + ACPI_OPERAND_OBJECT *obj_desc); + +ACPI_STATUS +acpi_aml_system_wait_semaphore ( + ACPI_HANDLE semaphore, + u32 timeout); + + +/* + * ammonadic - ACPI AML (p-code) execution, monadic operators + */ + +ACPI_STATUS +acpi_aml_exec_monadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_monadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + +ACPI_STATUS +acpi_aml_exec_monadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + + +/* + * amdyadic - ACPI AML (p-code) execution, dyadic operators + */ + +ACPI_STATUS +acpi_aml_exec_dyadic1 ( + u16 opcode, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_exec_dyadic2 ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + +ACPI_STATUS +acpi_aml_exec_dyadic2_r ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + +ACPI_STATUS +acpi_aml_exec_dyadic2_s ( + u16 opcode, + ACPI_WALK_STATE *walk_state, + ACPI_OPERAND_OBJECT **return_desc); + + +/* + * amresolv - Object resolution and get value functions + */ + +ACPI_STATUS +acpi_aml_resolve_to_value ( + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_resolve_node_to_value ( + ACPI_NAMESPACE_NODE **stack_ptr, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_resolve_object_to_value ( + ACPI_OPERAND_OBJECT **stack_ptr, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_get_field_unit_value ( + ACPI_OPERAND_OBJECT *field_desc, + ACPI_OPERAND_OBJECT *result_desc); + + +/* + * amdump - Scanner debug output routines + */ + +void +acpi_aml_show_hex_value ( + u32 byte_count, + u8 *aml_ptr, + u32 lead_space); + + +ACPI_STATUS +acpi_aml_dump_operand ( + ACPI_OPERAND_OBJECT *entry_desc); + +void +acpi_aml_dump_operands ( + ACPI_OPERAND_OBJECT **operands, + OPERATING_MODE interpreter_mode, + NATIVE_CHAR *ident, + u32 num_levels, + NATIVE_CHAR *note, + NATIVE_CHAR *module_name, + u32 line_number); + +void +acpi_aml_dump_object_descriptor ( + ACPI_OPERAND_OBJECT *object, + u32 flags); + + +void +acpi_aml_dump_node ( + ACPI_NAMESPACE_NODE *node, + u32 flags); + + +/* + * amnames - interpreter/scanner name load/execute + */ + +NATIVE_CHAR * +acpi_aml_allocate_name_string ( + u32 prefix_count, + u32 num_name_segs); + +u32 +acpi_aml_good_char ( + u32 character); + +ACPI_STATUS +acpi_aml_exec_name_segment ( + u8 **in_aml_address, + NATIVE_CHAR *name_string); + +ACPI_STATUS +acpi_aml_get_name_string ( + OBJECT_TYPE_INTERNAL data_type, + u8 *in_aml_address, + NATIVE_CHAR **out_name_string, + u32 *out_name_length); + +ACPI_STATUS +acpi_aml_do_name ( + ACPI_OBJECT_TYPE data_type, + OPERATING_MODE load_exec_mode); + + +/* + * amstore - Object store support + */ + +ACPI_STATUS +acpi_aml_exec_store ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_store_object_to_index ( + ACPI_OPERAND_OBJECT *val_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_store_object_to_node ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_store_object_to_object ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *dest_desc, + ACPI_WALK_STATE *walk_state); + + +/* + * + */ + +ACPI_STATUS +acpi_aml_resolve_object ( + ACPI_OPERAND_OBJECT **source_desc_ptr, + OBJECT_TYPE_INTERNAL target_type, + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_aml_store_object ( + ACPI_OPERAND_OBJECT *source_desc, + OBJECT_TYPE_INTERNAL target_type, + ACPI_OPERAND_OBJECT **target_desc_ptr, + ACPI_WALK_STATE *walk_state); + + +/* + * amcopy - object copy + */ + +ACPI_STATUS +acpi_aml_copy_buffer_to_buffer ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_string_to_string ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_integer_to_index_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_integer_to_bank_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +ACPI_STATUS +acpi_aml_copy_data_to_named_field ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_NAMESPACE_NODE *node); + +ACPI_STATUS +acpi_aml_copy_integer_to_field_unit ( + ACPI_OPERAND_OBJECT *source_desc, + ACPI_OPERAND_OBJECT *target_desc); + +/* + * amutils - interpreter/scanner utilities + */ + +ACPI_STATUS +acpi_aml_enter_interpreter ( + void); + +void +acpi_aml_exit_interpreter ( + void); + +void +acpi_aml_truncate_for32bit_table ( + ACPI_OPERAND_OBJECT *obj_desc, + ACPI_WALK_STATE *walk_state); + +u8 +acpi_aml_validate_object_type ( + ACPI_OBJECT_TYPE type); + +u8 +acpi_aml_acquire_global_lock ( + u32 rule); + +ACPI_STATUS +acpi_aml_release_global_lock ( + u8 locked); + +u32 +acpi_aml_digits_needed ( + ACPI_INTEGER value, + u32 base); + +ACPI_STATUS +acpi_aml_eisa_id_to_string ( + u32 numeric_id, + NATIVE_CHAR *out_string); + +ACPI_STATUS +acpi_aml_unsigned_integer_to_string ( + ACPI_INTEGER value, + NATIVE_CHAR *out_string); + + +/* + * amregion - default Op_region handlers + */ + +ACPI_STATUS +acpi_aml_system_memory_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context); + +ACPI_STATUS +acpi_aml_system_io_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context); + +ACPI_STATUS +acpi_aml_pci_config_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context); + +ACPI_STATUS +acpi_aml_embedded_controller_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context); + +ACPI_STATUS +acpi_aml_sm_bus_space_handler ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context); + + +#endif /* __INTERP_H__ */ diff --git a/drivers/bus/acpi/include/aclocal.h b/drivers/bus/acpi/include/aclocal.h new file mode 100644 index 0000000..d8c3a28 --- /dev/null +++ b/drivers/bus/acpi/include/aclocal.h @@ -0,0 +1,832 @@ +/****************************************************************************** + * + * Name: aclocal.h - Internal data types used across the ACPI subsystem + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACLOCAL_H__ +#define __ACLOCAL_H__ + + +#define WAIT_FOREVER ((u32) -1) + +typedef void* ACPI_MUTEX; +typedef u32 ACPI_MUTEX_HANDLE; + + +/* Object descriptor types */ + +#define ACPI_CACHED_OBJECT 0x11 /* ORed in when object is cached */ +#define ACPI_DESC_TYPE_STATE 0x22 +#define ACPI_DESC_TYPE_WALK 0x44 +#define ACPI_DESC_TYPE_PARSER 0x66 +#define ACPI_DESC_TYPE_INTERNAL 0x88 +#define ACPI_DESC_TYPE_NAMED 0xAA + + +/***************************************************************************** + * + * Mutex typedefs and structs + * + ****************************************************************************/ + + +/* + * Predefined handles for the mutex objects used within the subsystem + * All mutex objects are automatically created by Acpi_cm_mutex_initialize. + * + * The acquire/release ordering protocol is implied via this list. Mutexes + * with a lower value must be acquired before mutexes with a higher value. + * + * NOTE: any changes here must be reflected in the Acpi_gbl_Mutex_names table also! + */ + +#define ACPI_MTX_EXECUTE 0 +#define ACPI_MTX_INTERPRETER 1 +#define ACPI_MTX_PARSER 2 +#define ACPI_MTX_DISPATCHER 3 +#define ACPI_MTX_TABLES 4 +#define ACPI_MTX_OP_REGIONS 5 +#define ACPI_MTX_NAMESPACE 6 +#define ACPI_MTX_EVENTS 7 +#define ACPI_MTX_HARDWARE 8 +#define ACPI_MTX_CACHES 9 +#define ACPI_MTX_MEMORY 10 +#define ACPI_MTX_DEBUG_CMD_COMPLETE 11 +#define ACPI_MTX_DEBUG_CMD_READY 12 + +#define MAX_MTX 12 +#define NUM_MTX MAX_MTX+1 + + +#if defined(ACPI_DEBUG) || defined(ENABLE_DEBUGGER) +#ifdef DEFINE_ACPI_GLOBALS + +/* Names for the mutexes used in the subsystem */ + +static NATIVE_CHAR *acpi_gbl_mutex_names[] = +{ + "ACPI_MTX_Execute", + "ACPI_MTX_Interpreter", + "ACPI_MTX_Parser", + "ACPI_MTX_Dispatcher", + "ACPI_MTX_Tables", + "ACPI_MTX_Op_regions", + "ACPI_MTX_Namespace", + "ACPI_MTX_Events", + "ACPI_MTX_Hardware", + "ACPI_MTX_Caches", + "ACPI_MTX_Memory", + "ACPI_MTX_Debug_cmd_complete" + "ACPI_MTX_Debug_cmd_ready", +}; + +#endif +#endif + + +/* Table for the global mutexes */ + +typedef struct acpi_mutex_info +{ + ACPI_MUTEX mutex; + u32 use_count; + u32 owner_id; + u8 locked; + +} ACPI_MUTEX_INFO; + + +/* Lock flag parameter for various interfaces */ + +#define ACPI_MTX_DO_NOT_LOCK 0 +#define ACPI_MTX_LOCK 1 + + +typedef u16 ACPI_OWNER_ID; +#define OWNER_TYPE_TABLE 0x0 +#define OWNER_TYPE_METHOD 0x1 +#define FIRST_METHOD_ID 0x0000 +#define FIRST_TABLE_ID 0x8000 + +/* TBD: [Restructure] get rid of the need for this! */ + +#define TABLE_ID_DSDT (ACPI_OWNER_ID) 0x8000 + + +/***************************************************************************** + * + * Namespace typedefs and structs + * + ****************************************************************************/ + + +/* Operational modes of the AML interpreter/scanner */ + +typedef enum +{ + IMODE_LOAD_PASS1 = 0x01, + IMODE_LOAD_PASS2 = 0x02, + IMODE_EXECUTE = 0x0E + +} OPERATING_MODE; + + +/* + * The Node describes a named object that appears in the AML + * An Acpi_node is used to store Nodes. + * + * Data_type is used to differentiate between internal descriptors, and MUST + * be the first byte in this structure. + */ + +typedef struct acpi_node +{ + u8 data_type; + u8 type; /* Type associated with this name */ + u16 owner_id; + u32 name; /* ACPI Name, always 4 chars per ACPI spec */ + + + void *object; /* Pointer to attached ACPI object (optional) */ + struct acpi_node *child; /* first child */ + struct acpi_node *peer; /* Next peer*/ + u16 reference_count; /* Current count of references and children */ + u8 flags; + +} ACPI_NAMESPACE_NODE; + + +#define ENTRY_NOT_FOUND NULL + + +/* Node flags */ + +#define ANOBJ_AML_ATTACHMENT 0x01 +#define ANOBJ_END_OF_PEER_LIST 0x02 +#define ANOBJ_DATA_WIDTH_32 0x04 /* Parent table is 64-bits */ +#define ANOBJ_METHOD_ARG 0x08 +#define ANOBJ_METHOD_LOCAL 0x10 +#define ANOBJ_METHOD_NO_RETVAL 0x20 +#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40 + + +/* + * ACPI Table Descriptor. One per ACPI table + */ +typedef struct acpi_table_desc +{ + struct acpi_table_desc *prev; + struct acpi_table_desc *next; + struct acpi_table_desc *installed_desc; + ACPI_TABLE_HEADER *pointer; + void *base_pointer; + u8 *aml_pointer; + UINT64 physical_address; + u32 aml_length; + u32 length; + u32 count; + ACPI_OWNER_ID table_id; + u8 type; + u8 allocation; + u8 loaded_into_namespace; + +} ACPI_TABLE_DESC; + + +typedef struct +{ + NATIVE_CHAR *search_for; + ACPI_HANDLE *list; + u32 *count; + +} FIND_CONTEXT; + + +typedef struct +{ + ACPI_NAMESPACE_NODE *node; +} NS_SEARCH_DATA; + + +/* + * Predefined Namespace items + */ +#define ACPI_MAX_ADDRESS_SPACE 255 +#define ACPI_NUM_ADDRESS_SPACES 256 + + +typedef struct +{ + NATIVE_CHAR *name; + ACPI_OBJECT_TYPE type; + NATIVE_CHAR *val; + +} PREDEFINED_NAMES; + + +/* Object types used during package copies */ + + +#define ACPI_COPY_TYPE_SIMPLE 0 +#define ACPI_COPY_TYPE_PACKAGE 1 + + +/***************************************************************************** + * + * Event typedefs and structs + * + ****************************************************************************/ + + +/* Status bits. */ + +#define ACPI_STATUS_PMTIMER 0x0001 +#define ACPI_STATUS_GLOBAL 0x0020 +#define ACPI_STATUS_POWER_BUTTON 0x0100 +#define ACPI_STATUS_SLEEP_BUTTON 0x0200 +#define ACPI_STATUS_RTC_ALARM 0x0400 + +/* Enable bits. */ + +#define ACPI_ENABLE_PMTIMER 0x0001 +#define ACPI_ENABLE_GLOBAL 0x0020 +#define ACPI_ENABLE_POWER_BUTTON 0x0100 +#define ACPI_ENABLE_SLEEP_BUTTON 0x0200 +#define ACPI_ENABLE_RTC_ALARM 0x0400 + + +/* + * Entry in the Address_space (AKA Operation Region) table + */ + +typedef struct +{ + ADDRESS_SPACE_HANDLER handler; + void *context; + +} ACPI_ADDRESS_SPACE_INFO; + + +/* Values and addresses of the GPE registers (both banks) */ + +typedef struct +{ + u8 status; /* Current value of status reg */ + u8 enable; /* Current value of enable reg */ + u16 status_addr; /* Address of status reg */ + u16 enable_addr; /* Address of enable reg */ + u8 gpe_base; /* Base GPE number */ + +} ACPI_GPE_REGISTERS; + + +#define ACPI_GPE_LEVEL_TRIGGERED 1 +#define ACPI_GPE_EDGE_TRIGGERED 2 + + +/* Information about each particular GPE level */ + +typedef struct +{ + u8 type; /* Level or Edge */ + + ACPI_HANDLE method_handle; /* Method handle for direct (fast) execution */ + GPE_HANDLER handler; /* Address of handler, if any */ + void *context; /* Context to be passed to handler */ + +} ACPI_GPE_LEVEL_INFO; + + +/* Information about each particular fixed event */ + +typedef struct +{ + FIXED_EVENT_HANDLER handler; /* Address of handler. */ + void *context; /* Context to be passed to handler */ + +} ACPI_FIXED_EVENT_INFO; + + +/* Information used during field processing */ + +typedef struct +{ + u8 skip_field; + u8 field_flag; + u32 pkg_length; + +} ACPI_FIELD_INFO; + + +/***************************************************************************** + * + * Generic "state" object for stacks + * + ****************************************************************************/ + + +#define CONTROL_NORMAL 0xC0 +#define CONTROL_CONDITIONAL_EXECUTING 0xC1 +#define CONTROL_PREDICATE_EXECUTING 0xC2 +#define CONTROL_PREDICATE_FALSE 0xC3 +#define CONTROL_PREDICATE_TRUE 0xC4 + + +/* Forward declarations */ +struct acpi_walk_state; +struct acpi_walk_list; +struct acpi_parse_obj; +struct acpi_obj_mutex; + + +#define ACPI_STATE_COMMON /* Two 32-bit fields and a pointer */\ + u8 data_type; /* To differentiate various internal objs */\ + u8 flags; \ + u16 value; \ + u16 state; \ + u16 acpi_eval; \ + void *next; \ + +typedef struct acpi_common_state +{ + ACPI_STATE_COMMON +} ACPI_COMMON_STATE; + + +/* + * Update state - used to traverse complex objects such as packages + */ +typedef struct acpi_update_state +{ + ACPI_STATE_COMMON + union acpi_operand_obj *object; + +} ACPI_UPDATE_STATE; + + +/* + * Pkg state - used to traverse nested package structures + */ +typedef struct acpi_pkg_state +{ + ACPI_STATE_COMMON + union acpi_operand_obj *source_object; + union acpi_operand_obj *dest_object; + struct acpi_walk_state *walk_state; + void *this_target_obj; + u32 num_packages; + u16 index; + +} ACPI_PKG_STATE; + + +/* + * Control state - one per if/else and while constructs. + * Allows nesting of these constructs + */ +typedef struct acpi_control_state +{ + ACPI_STATE_COMMON + struct acpi_parse_obj *predicate_op; + u8 *aml_predicate_start; /* Start of if/while predicate */ + +} ACPI_CONTROL_STATE; + + +/* + * Scope state - current scope during namespace lookups + */ + +typedef struct acpi_scope_state +{ + ACPI_STATE_COMMON + ACPI_NAMESPACE_NODE *node; + +} ACPI_SCOPE_STATE; + + +typedef struct acpi_pscope_state +{ + ACPI_STATE_COMMON + struct acpi_parse_obj *op; /* current op being parsed */ + u8 *arg_end; /* current argument end */ + u8 *pkg_end; /* current package end */ + u32 arg_list; /* next argument to parse */ + u32 arg_count; /* Number of fixed arguments */ + +} ACPI_PSCOPE_STATE; + + +/* + * Result values - used to accumulate the results of nested + * AML arguments + */ +typedef struct acpi_result_values +{ + ACPI_STATE_COMMON + union acpi_operand_obj *obj_desc [OBJ_NUM_OPERANDS]; + u8 num_results; + u8 last_insert; + +} ACPI_RESULT_VALUES; + + +/* + * Notify info - used to pass info to the deferred notify + * handler/dispatcher. + */ + +typedef struct acpi_notify_info +{ + ACPI_STATE_COMMON + ACPI_NAMESPACE_NODE *node; + union acpi_operand_obj *handler_obj; + +} ACPI_NOTIFY_INFO; + + +/* Generic state is union of structs above */ + +typedef union acpi_gen_state +{ + ACPI_COMMON_STATE common; + ACPI_CONTROL_STATE control; + ACPI_UPDATE_STATE update; + ACPI_SCOPE_STATE scope; + ACPI_PSCOPE_STATE parse_scope; + ACPI_PKG_STATE pkg; + ACPI_RESULT_VALUES results; + ACPI_NOTIFY_INFO notify; + +} ACPI_GENERIC_STATE; + + +typedef +ACPI_STATUS (*ACPI_PARSE_DOWNWARDS) ( + u16 opcode, + struct acpi_parse_obj *op, + struct acpi_walk_state *walk_state, + struct acpi_parse_obj **out_op); + +typedef +ACPI_STATUS (*ACPI_PARSE_UPWARDS) ( + struct acpi_walk_state *walk_state, + struct acpi_parse_obj *op); + + +/***************************************************************************** + * + * Parser typedefs and structs + * + ****************************************************************************/ + + +#define ACPI_OP_CLASS_MASK 0x1F +#define ACPI_OP_ARGS_MASK 0x20 +#define ACPI_OP_TYPE_MASK 0xC0 + +#define ACPI_OP_TYPE_OPCODE 0x00 +#define ACPI_OP_TYPE_ASCII 0x40 +#define ACPI_OP_TYPE_PREFIX 0x80 +#define ACPI_OP_TYPE_UNKNOWN 0xC0 + +#define ACPI_GET_OP_CLASS(a) ((a)->flags & ACPI_OP_CLASS_MASK) +#define ACPI_GET_OP_ARGS(a) ((a)->flags & ACPI_OP_ARGS_MASK) +#define ACPI_GET_OP_TYPE(a) ((a)->flags & ACPI_OP_TYPE_MASK) + + +/* + * AML opcode, name, and argument layout + */ +typedef struct acpi_opcode_info +{ + u8 flags; /* Opcode type, Has_args flag */ + u32 parse_args; /* Grammar/Parse time arguments */ + u32 runtime_args; /* Interpret time arguments */ + +#ifdef _OPCODE_NAMES + NATIVE_CHAR *name; /* op name (debug only) */ +#endif + +} ACPI_OPCODE_INFO; + + +typedef union acpi_parse_val +{ + u32 integer; /* integer constant */ + u32 size; /* bytelist or field size */ + NATIVE_CHAR *string; /* NULL terminated string */ + u8 *buffer; /* buffer or string */ + NATIVE_CHAR *name; /* NULL terminated string */ + struct acpi_parse_obj *arg; /* arguments and contained ops */ + +} ACPI_PARSE_VALUE; + + +#define ACPI_PARSE_COMMON \ + u8 data_type; /* To differentiate various internal objs */\ + u8 flags; /* Type of Op */\ + u16 opcode; /* AML opcode */\ + u32 aml_offset; /* offset of declaration in AML */\ + struct acpi_parse_obj *parent; /* parent op */\ + struct acpi_parse_obj *next; /* next op */\ + DEBUG_ONLY_MEMBERS (\ + NATIVE_CHAR op_name[16]) /* op name (debug only) */\ + /* NON-DEBUG members below: */\ + ACPI_NAMESPACE_NODE *node; /* for use by interpreter */\ + ACPI_PARSE_VALUE value; /* Value or args associated with the opcode */\ + + +/* + * generic operation (eg. If, While, Store) + */ +typedef struct acpi_parse_obj +{ + ACPI_PARSE_COMMON +} ACPI_PARSE_OBJECT; + + +/* + * Extended Op for named ops (Scope, Method, etc.), deferred ops (Methods and Op_regions), + * and bytelists. + */ +typedef struct acpi_parse2_obj +{ + ACPI_PARSE_COMMON + u8 *data; /* AML body or bytelist data */ + u32 length; /* AML length */ + u32 name; /* 4-byte name or zero if no name */ + +} ACPI_PARSE2_OBJECT; + + +/* + * Parse state - one state per parser invocation and each control + * method. + */ + +typedef struct acpi_parse_state +{ + u8 *aml_start; /* first AML byte */ + u8 *aml; /* next AML byte */ + u8 *aml_end; /* (last + 1) AML byte */ + u8 *pkg_start; /* current package begin */ + u8 *pkg_end; /* current package end */ + ACPI_PARSE_OBJECT *start_op; /* root of parse tree */ + struct acpi_node *start_node; + ACPI_GENERIC_STATE *scope; /* current scope */ + struct acpi_parse_state *next; + +} ACPI_PARSE_STATE; + + +/***************************************************************************** + * + * Hardware and PNP + * + ****************************************************************************/ + + +/* PCI */ + +#define PCI_ROOT_HID_STRING "PNP0A03" +#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ + + +/* Sleep states */ + +#define SLWA_DEBUG_LEVEL 4 +#define GTS_CALL 0 +#define GTS_WAKE 1 + +/* Cx States */ + +#define MAX_CX_STATE_LATENCY 0xFFFFFFFF +#define MAX_CX_STATES 4 + + +/* + * The #define's and enum below establish an abstract way of identifying what + * register block and register is to be accessed. Do not change any of the + * values as they are used in switch statements and offset calculations. + */ + +#define REGISTER_BLOCK_MASK 0xFF00 /* Register Block Id */ +#define BIT_IN_REGISTER_MASK 0x00FF /* Bit Id in the Register Block Id */ +#define BYTE_IN_REGISTER_MASK 0x00FF /* Register Offset in the Register Block */ + +#define REGISTER_BLOCK_ID(reg_id) (reg_id & REGISTER_BLOCK_MASK) +#define REGISTER_BIT_ID(reg_id) (reg_id & BIT_IN_REGISTER_MASK) +#define REGISTER_OFFSET(reg_id) (reg_id & BYTE_IN_REGISTER_MASK) + +/* + * Access Rule + * To access a Register Bit: + * -> Use Bit Name (= Register Block Id | Bit Id) defined in the enum. + * + * To access a Register: + * -> Use Register Id (= Register Block Id | Register Offset) + */ + + +/* + * Register Block Id + */ +#define PM1_STS 0x0100 +#define PM1_EN 0x0200 +#define PM1_CONTROL 0x0300 +#define PM1_a_CONTROL 0x0400 +#define PM1_b_CONTROL 0x0500 +#define PM2_CONTROL 0x0600 +#define PM_TIMER 0x0700 +#define PROCESSOR_BLOCK 0x0800 +#define GPE0_STS_BLOCK 0x0900 +#define GPE0_EN_BLOCK 0x0A00 +#define GPE1_STS_BLOCK 0x0B00 +#define GPE1_EN_BLOCK 0x0C00 +#define SMI_CMD_BLOCK 0x0D00 + +/* + * Address space bitmasks for mmio or io spaces + */ + +#define SMI_CMD_ADDRESS_SPACE 0x01 +#define PM1_BLK_ADDRESS_SPACE 0x02 +#define PM2_CNT_BLK_ADDRESS_SPACE 0x04 +#define PM_TMR_BLK_ADDRESS_SPACE 0x08 +#define GPE0_BLK_ADDRESS_SPACE 0x10 +#define GPE1_BLK_ADDRESS_SPACE 0x20 + +/* + * Control bit definitions + */ +#define TMR_STS (PM1_STS | 0x01) +#define BM_STS (PM1_STS | 0x02) +#define GBL_STS (PM1_STS | 0x03) +#define PWRBTN_STS (PM1_STS | 0x04) +#define SLPBTN_STS (PM1_STS | 0x05) +#define RTC_STS (PM1_STS | 0x06) +#define WAK_STS (PM1_STS | 0x07) + +#define TMR_EN (PM1_EN | 0x01) + /* no BM_EN */ +#define GBL_EN (PM1_EN | 0x03) +#define PWRBTN_EN (PM1_EN | 0x04) +#define SLPBTN_EN (PM1_EN | 0x05) +#define RTC_EN (PM1_EN | 0x06) +#define WAK_EN (PM1_EN | 0x07) + +#define SCI_EN (PM1_CONTROL | 0x01) +#define BM_RLD (PM1_CONTROL | 0x02) +#define GBL_RLS (PM1_CONTROL | 0x03) +#define SLP_TYPE_A (PM1_CONTROL | 0x04) +#define SLP_TYPE_B (PM1_CONTROL | 0x05) +#define SLP_EN (PM1_CONTROL | 0x06) + +#define ARB_DIS (PM2_CONTROL | 0x01) + +#define TMR_VAL (PM_TIMER | 0x01) + +#define GPE0_STS (GPE0_STS_BLOCK | 0x01) +#define GPE0_EN (GPE0_EN_BLOCK | 0x01) + +#define GPE1_STS (GPE1_STS_BLOCK | 0x01) +#define GPE1_EN (GPE1_EN_BLOCK | 0x01) + + +#define TMR_STS_MASK 0x0001 +#define BM_STS_MASK 0x0010 +#define GBL_STS_MASK 0x0020 +#define PWRBTN_STS_MASK 0x0100 +#define SLPBTN_STS_MASK 0x0200 +#define RTC_STS_MASK 0x0400 +#define WAK_STS_MASK 0x8000 + +#define ALL_FIXED_STS_BITS (TMR_STS_MASK | BM_STS_MASK | GBL_STS_MASK \ + | PWRBTN_STS_MASK | SLPBTN_STS_MASK \ + | RTC_STS_MASK | WAK_STS_MASK) + +#define TMR_EN_MASK 0x0001 +#define GBL_EN_MASK 0x0020 +#define PWRBTN_EN_MASK 0x0100 +#define SLPBTN_EN_MASK 0x0200 +#define RTC_EN_MASK 0x0400 + +#define SCI_EN_MASK 0x0001 +#define BM_RLD_MASK 0x0002 +#define GBL_RLS_MASK 0x0004 +#define SLP_TYPE_X_MASK 0x1C00 +#define SLP_EN_MASK 0x2000 + +#define ARB_DIS_MASK 0x0001 +#define TMR_VAL_MASK 0xFFFFFFFF + +#define GPE0_STS_MASK +#define GPE0_EN_MASK + +#define GPE1_STS_MASK +#define GPE1_EN_MASK + + +#define ACPI_READ 1 +#define ACPI_WRITE 2 + + +/* Plug and play */ + +/* Pnp and ACPI data */ + +#define VERSION_NO 0x01 +#define LOGICAL_DEVICE_ID 0x02 +#define COMPATIBLE_DEVICE_ID 0x03 +#define IRQ_FORMAT 0x04 +#define DMA_FORMAT 0x05 +#define START_DEPENDENT_TAG 0x06 +#define END_DEPENDENT_TAG 0x07 +#define IO_PORT_DESCRIPTOR 0x08 +#define FIXED_LOCATION_IO_DESCRIPTOR 0x09 +#define RESERVED_TYPE0 0x0A +#define RESERVED_TYPE1 0x0B +#define RESERVED_TYPE2 0x0C +#define RESERVED_TYPE3 0x0D +#define SMALL_VENDOR_DEFINED 0x0E +#define END_TAG 0x0F + +/* Pnp and ACPI data */ + +#define MEMORY_RANGE_24 0x81 +#define ISA_MEMORY_RANGE 0x81 +#define LARGE_VENDOR_DEFINED 0x84 +#define EISA_MEMORY_RANGE 0x85 +#define MEMORY_RANGE_32 0x85 +#define FIXED_EISA_MEMORY_RANGE 0x86 +#define FIXED_MEMORY_RANGE_32 0x86 + +/* ACPI only data */ + +#define DWORD_ADDRESS_SPACE 0x87 +#define WORD_ADDRESS_SPACE 0x88 +#define EXTENDED_IRQ 0x89 + +/* MUST HAVES */ + +#define DEVICE_ID_LENGTH 0x09 + +typedef struct +{ + NATIVE_CHAR buffer[DEVICE_ID_LENGTH]; + +} DEVICE_ID; + + +/***************************************************************************** + * + * Debug + * + ****************************************************************************/ + + +/* Entry for a memory allocation (debug only) */ + +#ifdef ACPI_DEBUG + +#define MEM_MALLOC 0 +#define MEM_CALLOC 1 +#define MAX_MODULE_NAME 16 + +typedef struct allocation_info +{ + struct allocation_info *previous; + struct allocation_info *next; + void *address; + u32 size; + u32 component; + u32 line; + NATIVE_CHAR module[MAX_MODULE_NAME]; + u8 alloc_type; + +} ALLOCATION_INFO; + +#endif + +#endif /* __ACLOCAL_H__ */ diff --git a/drivers/bus/acpi/include/acmacros.h b/drivers/bus/acpi/include/acmacros.h new file mode 100644 index 0000000..5cc5023 --- /dev/null +++ b/drivers/bus/acpi/include/acmacros.h @@ -0,0 +1,501 @@ +/****************************************************************************** + * + * Name: acmacros.h - C macros for the entire subsystem. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACMACROS_H__ +#define __ACMACROS_H__ + +/* + * Data manipulation macros + */ + +#ifndef LODWORD +#define LODWORD(l) ((u32)(UINT64)(l)) +#endif + +#ifndef HIDWORD +#define HIDWORD(l) ((u32)((((UINT64)(l)) >> 32) & 0xFFFFFFFF)) +#endif + +#ifndef LOWORD +#define LOWORD(l) ((u16)(NATIVE_UINT)(l)) +#endif + +#ifndef HIWORD +#define HIWORD(l) ((u16)((((NATIVE_UINT)(l)) >> 16) & 0xFFFF)) +#endif + +#ifndef LOBYTE +#define LOBYTE(l) ((u8)(u16)(l)) +#endif + +#ifndef HIBYTE +#define HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF)) +#endif + +#define BIT0(x) ((((x) & 0x01) > 0) ? 1 : 0) +#define BIT1(x) ((((x) & 0x02) > 0) ? 1 : 0) +#define BIT2(x) ((((x) & 0x04) > 0) ? 1 : 0) + +#define BIT3(x) ((((x) & 0x08) > 0) ? 1 : 0) +#define BIT4(x) ((((x) & 0x10) > 0) ? 1 : 0) +#define BIT5(x) ((((x) & 0x20) > 0) ? 1 : 0) +#define BIT6(x) ((((x) & 0x40) > 0) ? 1 : 0) +#define BIT7(x) ((((x) & 0x80) > 0) ? 1 : 0) + +#define LOW_BASE(w) ((u16) ((w) & 0x0000FFFF)) +#define MID_BASE(b) ((u8) (((b) & 0x00FF0000) >> 16)) +#define HI_BASE(b) ((u8) (((b) & 0xFF000000) >> 24)) +#define LOW_LIMIT(w) ((u16) ((w) & 0x0000FFFF)) +#define HI_LIMIT(b) ((u8) (((b) & 0x00FF0000) >> 16)) + + +#ifdef _IA16 +/* + * For 16-bit addresses, we have to assume that the upper 32 bits + * are zero. + */ +#define ACPI_GET_ADDRESS(a) ((a).lo) +#define ACPI_STORE_ADDRESS(a,b) {(a).hi=0;(a).lo=(b);} +#define ACPI_VALID_ADDRESS(a) ((a).hi | (a).lo) + +#else +/* + * Full 64-bit address on 32-bit and 64-bit platforms + */ +#define ACPI_GET_ADDRESS(a) (a) +#define ACPI_STORE_ADDRESS(a,b) ((a)=(b)) +#define ACPI_VALID_ADDRESS(a) (a) +#endif + /* + * Extract a byte of data using a pointer. Any more than a byte and we + * get into potential aligment issues -- see the STORE macros below + */ +#define GET8(addr) (*(u8*)(addr)) + + +/* + * Macros for moving data around to/from buffers that are possibly unaligned. + * If the hardware supports the transfer of unaligned data, just do the store. + * Otherwise, we have to move one byte at a time. + */ + +#ifdef _HW_ALIGNMENT_SUPPORT + +/* The hardware supports unaligned transfers, just do the move */ + +#define MOVE_UNALIGNED16_TO_16(d,s) *(u16*)(d) = *(u16*)(s) +#define MOVE_UNALIGNED32_TO_32(d,s) *(u32*)(d) = *(u32*)(s) +#define MOVE_UNALIGNED16_TO_32(d,s) *(u32*)(d) = *(u16*)(s) + +#else +/* + * The hardware does not support unaligned transfers. We must move the + * data one byte at a time. These macros work whether the source or + * the destination (or both) is/are unaligned. + */ + +#define MOVE_UNALIGNED16_TO_16(d,s) {((u8 *)(d))[0] = ((u8 *)(s))[0];\ + ((u8 *)(d))[1] = ((u8 *)(s))[1];} + +#define MOVE_UNALIGNED32_TO_32(d,s) {((u8 *)(d))[0] = ((u8 *)(s))[0];\ + ((u8 *)(d))[1] = ((u8 *)(s))[1];\ + ((u8 *)(d))[2] = ((u8 *)(s))[2];\ + ((u8 *)(d))[3] = ((u8 *)(s))[3];} + +#define MOVE_UNALIGNED16_TO_32(d,s) {(*(u32*)(d)) = 0; MOVE_UNALIGNED16_TO_16(d,s);} + +#endif + + +/* + * Fast power-of-two math macros for non-optimized compilers + */ + +#define _DIV(value,power_of2) ((u32) ((value) >> (power_of2))) +#define _MUL(value,power_of2) ((u32) ((value) << (power_of2))) +#define _MOD(value,divisor) ((u32) ((value) & ((divisor) -1))) + +#define DIV_2(a) _DIV(a,1) +#define MUL_2(a) _MUL(a,1) +#define MOD_2(a) _MOD(a,2) + +#define DIV_4(a) _DIV(a,2) +#define MUL_4(a) _MUL(a,2) +#define MOD_4(a) _MOD(a,4) + +#define DIV_8(a) _DIV(a,3) +#define MUL_8(a) _MUL(a,3) +#define MOD_8(a) _MOD(a,8) + +#define DIV_16(a) _DIV(a,4) +#define MUL_16(a) _MUL(a,4) +#define MOD_16(a) _MOD(a,16) + +/* + * Divide and Modulo + */ +#define ACPI_DIVIDE(n,d) ((n) / (d)) +#define ACPI_MODULO(n,d) ((n) % (d)) + +/* + * Rounding macros (Power of two boundaries only) + */ + +#define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1))) +#define ROUND_UP(value,boundary) (((value) + ((boundary)-1)) & (~((boundary)-1))) + +#define ROUND_DOWN_TO_32_BITS(a) ROUND_DOWN(a,4) +#define ROUND_DOWN_TO_64_BITS(a) ROUND_DOWN(a,8) +#define ROUND_DOWN_TO_NATIVE_WORD(a) ROUND_DOWN(a,ALIGNED_ADDRESS_BOUNDARY) + +#define ROUND_UP_TO_32_bITS(a) ROUND_UP(a,4) +#define ROUND_UP_TO_64_bITS(a) ROUND_UP(a,8) +#define ROUND_UP_TO_NATIVE_WORD(a) ROUND_UP(a,ALIGNED_ADDRESS_BOUNDARY) + +#define ROUND_PTR_UP_TO_4(a,b) ((b *)(((NATIVE_UINT)(a) + 3) & ~3)) +#define ROUND_PTR_UP_TO_8(a,b) ((b *)(((NATIVE_UINT)(a) + 7) & ~7)) + +#define ROUND_UP_TO_1_k(a) (((a) + 1023) >> 10) + +#ifdef DEBUG_ASSERT +#undef DEBUG_ASSERT +#endif + + +/* Macros for GAS addressing */ + +#define ACPI_PCI_DEVICE_MASK (UINT64) 0x0000FFFF00000000 +#define ACPI_PCI_FUNCTION_MASK (UINT64) 0x00000000FFFF0000 +#define ACPI_PCI_REGISTER_MASK (UINT64) 0x000000000000FFFF + +#define ACPI_PCI_FUNCTION(a) (u32) ((((a) & ACPI_PCI_FUNCTION_MASK) >> 16)) +#define ACPI_PCI_DEVICE(a) (u32) ((((a) & ACPI_PCI_DEVICE_MASK) >> 32)) + +#ifndef _IA16 +#define ACPI_PCI_REGISTER(a) (u32) (((a) & ACPI_PCI_REGISTER_MASK)) +#define ACPI_PCI_DEVFUN(a) (u32) ((ACPI_PCI_DEVICE(a) << 16) | ACPI_PCI_FUNCTION(a)) + +#else +#define ACPI_PCI_REGISTER(a) (u32) (((a) & 0x0000FFFF)) +#define ACPI_PCI_DEVFUN(a) (u32) ((((a) & 0xFFFF0000) >> 16)) + +#endif + +/* + * An ACPI_HANDLE (which is actually an ACPI_NAMESPACE_NODE *) can appear in some contexts, + * such as on ap_obj_stack, where a pointer to an ACPI_OPERAND_OBJECT can also + * appear. This macro is used to distinguish them. + * + * The Data_type field is the first field in both structures. + */ + +#define VALID_DESCRIPTOR_TYPE(d,t) (((ACPI_NAMESPACE_NODE *)d)->data_type == t) + + +/* Macro to test the object type */ + +#define IS_THIS_OBJECT_TYPE(d,t) (((ACPI_OPERAND_OBJECT *)d)->common.type == (u8)t) + +/* Macro to check the table flags for SINGLE or MULTIPLE tables are allowed */ + +#define IS_SINGLE_TABLE(x) (((x) & 0x01) == ACPI_TABLE_SINGLE ? 1 : 0) + +/* + * Macro to check if a pointer is within an ACPI table. + * Parameter (a) is the pointer to check. Parameter (b) must be defined + * as a pointer to an ACPI_TABLE_HEADER. (b+1) then points past the header, + * and ((u8 *)b+b->Length) points one byte past the end of the table. + */ + +#ifndef _IA16 +#define IS_IN_ACPI_TABLE(a,b) (((u8 *)(a) >= (u8 *)(b + 1)) &&\ + ((u8 *)(a) < ((u8 *)b + b->length))) + +#else +#define IS_IN_ACPI_TABLE(a,b) (_segment)(a) == (_segment)(b) &&\ + (((u8 *)(a) >= (u8 *)(b + 1)) &&\ + ((u8 *)(a) < ((u8 *)b + b->length))) +#endif + +/* + * Macros for the master AML opcode table + */ + +#ifdef ACPI_DEBUG +#define OP_INFO_ENTRY(flags,name,Pargs,Iargs) {flags,Pargs,Iargs,name} +#else +#define OP_INFO_ENTRY(flags,name,Pargs,Iargs) {flags,Pargs,Iargs} +#endif + +#define ARG_TYPE_WIDTH 5 +#define ARG_1(x) ((u32)(x)) +#define ARG_2(x) ((u32)(x) << (1 * ARG_TYPE_WIDTH)) +#define ARG_3(x) ((u32)(x) << (2 * ARG_TYPE_WIDTH)) +#define ARG_4(x) ((u32)(x) << (3 * ARG_TYPE_WIDTH)) +#define ARG_5(x) ((u32)(x) << (4 * ARG_TYPE_WIDTH)) +#define ARG_6(x) ((u32)(x) << (5 * ARG_TYPE_WIDTH)) + +#define ARGI_LIST1(a) (ARG_1(a)) +#define ARGI_LIST2(a,b) (ARG_1(b)|ARG_2(a)) +#define ARGI_LIST3(a,b,c) (ARG_1(c)|ARG_2(b)|ARG_3(a)) +#define ARGI_LIST4(a,b,c,d) (ARG_1(d)|ARG_2(c)|ARG_3(b)|ARG_4(a)) +#define ARGI_LIST5(a,b,c,d,e) (ARG_1(e)|ARG_2(d)|ARG_3(c)|ARG_4(b)|ARG_5(a)) +#define ARGI_LIST6(a,b,c,d,e,f) (ARG_1(f)|ARG_2(e)|ARG_3(d)|ARG_4(c)|ARG_5(b)|ARG_6(a)) + +#define ARGP_LIST1(a) (ARG_1(a)) +#define ARGP_LIST2(a,b) (ARG_1(a)|ARG_2(b)) +#define ARGP_LIST3(a,b,c) (ARG_1(a)|ARG_2(b)|ARG_3(c)) +#define ARGP_LIST4(a,b,c,d) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)) +#define ARGP_LIST5(a,b,c,d,e) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)) +#define ARGP_LIST6(a,b,c,d,e,f) (ARG_1(a)|ARG_2(b)|ARG_3(c)|ARG_4(d)|ARG_5(e)|ARG_6(f)) + +#define GET_CURRENT_ARG_TYPE(list) (list & ((u32) 0x1F)) +#define INCREMENT_ARG_LIST(list) (list >>= ((u32) ARG_TYPE_WIDTH)) + + +/* + * Reporting macros that are never compiled out + */ + +#define PARAM_LIST(pl) pl + +/* + * Error reporting. These versions add callers module and line#. Since + * _THIS_MODULE gets compiled out when ACPI_DEBUG isn't defined, only + * use it in debug mode. + */ + +#ifdef ACPI_DEBUG + +#define REPORT_INFO(fp) {_report_info(_THIS_MODULE,__LINE__,_COMPONENT); \ + debug_print_raw PARAM_LIST(fp);} +#define REPORT_ERROR(fp) {_report_error(_THIS_MODULE,__LINE__,_COMPONENT); \ + debug_print_raw PARAM_LIST(fp);} +#define REPORT_WARNING(fp) {_report_warning(_THIS_MODULE,__LINE__,_COMPONENT); \ + debug_print_raw PARAM_LIST(fp);} + +#else + +#define REPORT_INFO(fp) {_report_info("ACPI",__LINE__,_COMPONENT); \ + debug_print_raw PARAM_LIST(fp);} +#define REPORT_ERROR(fp) {_report_error("ACPI",__LINE__,_COMPONENT); \ + debug_print_raw PARAM_LIST(fp);} +#define REPORT_WARNING(fp) {_report_warning("ACPI",__LINE__,_COMPONENT); \ + debug_print_raw PARAM_LIST(fp);} + +#endif + +/* Error reporting. These versions pass thru the module and line# */ + +#define _REPORT_INFO(a,b,c,fp) {_report_info(a,b,c); \ + debug_print_raw PARAM_LIST(fp);} +#define _REPORT_ERROR(a,b,c,fp) {_report_error(a,b,c); \ + debug_print_raw PARAM_LIST(fp);} +#define _REPORT_WARNING(a,b,c,fp) {_report_warning(a,b,c); \ + debug_print_raw PARAM_LIST(fp);} + +/* Buffer dump macros */ + +#define DUMP_BUFFER(a,b) acpi_cm_dump_buffer((u8 *)a,b,DB_BYTE_DISPLAY,_COMPONENT) + +/* + * Debug macros that are conditionally compiled + */ + +#ifdef ACPI_DEBUG + +#define MODULE_NAME(name) static char *_THIS_MODULE = name; + +/* + * Function entry tracing. + * The first parameter should be the procedure name as a quoted string. This is declared + * as a local string ("_Proc_name) so that it can be also used by the function exit macros below. + */ + +#define FUNCTION_TRACE(a) char * _proc_name = a;\ + function_trace(_THIS_MODULE,__LINE__,_COMPONENT,a) +#define FUNCTION_TRACE_PTR(a,b) char * _proc_name = a;\ + function_trace_ptr(_THIS_MODULE,__LINE__,_COMPONENT,a,(void *)b) +#define FUNCTION_TRACE_U32(a,b) char * _proc_name = a;\ + function_trace_u32(_THIS_MODULE,__LINE__,_COMPONENT,a,(u32)b) +#define FUNCTION_TRACE_STR(a,b) char * _proc_name = a;\ + function_trace_str(_THIS_MODULE,__LINE__,_COMPONENT,a,(NATIVE_CHAR *)b) +/* + * Function exit tracing. + * WARNING: These macros include a return statement. This is usually considered + * bad form, but having a separate exit macro is very ugly and difficult to maintain. + * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros + * so that "_Proc_name" is defined. + */ +#define return_VOID {function_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name);return;} +#define return_ACPI_STATUS(s) {function_status_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,s);return(s);} +#define return_VALUE(s) {function_value_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(ACPI_INTEGER)s);return(s);} +#define return_PTR(s) {function_ptr_exit(_THIS_MODULE,__LINE__,_COMPONENT,_proc_name,(u8 *)s);return(s);} + + +/* Conditional execution */ + +#define DEBUG_EXEC(a) a +#define NORMAL_EXEC(a) + +#define DEBUG_DEFINE(a) a; +#define DEBUG_ONLY_MEMBERS(a) a; +#define _OPCODE_NAMES +#define _VERBOSE_STRUCTURES + + +/* Stack and buffer dumping */ + +#define DUMP_STACK_ENTRY(a) acpi_aml_dump_operand(a) +#define DUMP_OPERANDS(a,b,c,d,e) acpi_aml_dump_operands(a,b,c,d,e,_THIS_MODULE,__LINE__) + + +#define DUMP_ENTRY(a,b) acpi_ns_dump_entry (a,b) +#define DUMP_TABLES(a,b) acpi_ns_dump_tables(a,b) +#define DUMP_PATHNAME(a,b,c,d) acpi_ns_dump_pathname(a,b,c,d) +#define DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a) +#define BREAK_MSG(a) acpi_os_breakpoint (a) + +/* + * Generate INT3 on ACPI_ERROR (Debug only!) + */ + +#define ERROR_BREAK +#ifdef ERROR_BREAK +#define BREAK_ON_ERROR(lvl) if ((lvl)&ACPI_ERROR) acpi_os_breakpoint("Fatal error encountered\n") +#else +#define BREAK_ON_ERROR(lvl) +#endif + +/* + * Master debug print macros + * Print iff: + * 1) Debug print for the current component is enabled + * 2) Debug error level or trace level for the print statement is enabled + * + */ + +#define TEST_DEBUG_SWITCH(lvl) if (((lvl) & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer)) + +#define DEBUG_PRINT(lvl,fp) TEST_DEBUG_SWITCH(lvl) {\ + debug_print_prefix (_THIS_MODULE,__LINE__);\ + debug_print_raw PARAM_LIST(fp);\ + BREAK_ON_ERROR(lvl);} + +#define DEBUG_PRINT_RAW(lvl,fp) TEST_DEBUG_SWITCH(lvl) {\ + debug_print_raw PARAM_LIST(fp);} + + +/* Assert macros */ + +#define ACPI_ASSERT(exp) if(!(exp)) \ + acpi_os_dbg_assert(#exp, __FILE__, __LINE__, "Failed Assertion") + +#define DEBUG_ASSERT(msg, exp) if(!(exp)) \ + acpi_os_dbg_assert(#exp, __FILE__, __LINE__, msg) + + +#else +/* + * This is the non-debug case -- make everything go away, + * leaving no executable debug code! + */ + +#define MODULE_NAME(name) +#define _THIS_MODULE "" + +#define DEBUG_EXEC(a) +#define NORMAL_EXEC(a) a; + +#define DEBUG_DEFINE(a) +#define DEBUG_ONLY_MEMBERS(a) +#define FUNCTION_TRACE(a) +#define FUNCTION_TRACE_PTR(a,b) +#define FUNCTION_TRACE_U32(a,b) +#define FUNCTION_TRACE_STR(a,b) +#define FUNCTION_EXIT +#define FUNCTION_STATUS_EXIT(s) +#define FUNCTION_VALUE_EXIT(s) +#define DUMP_STACK_ENTRY(a) +#define DUMP_OPERANDS(a,b,c,d,e) +#define DUMP_ENTRY(a,b) +#define DUMP_TABLES(a,b) +#define DUMP_PATHNAME(a,b,c,d) +#define DUMP_RESOURCE_LIST(a) +#define DEBUG_PRINT(l,f) +#define DEBUG_PRINT_RAW(l,f) +#define BREAK_MSG(a) + +#define return_VOID return +#define return_ACPI_STATUS(s) return(s) +#define return_VALUE(s) return(s) +#define return_PTR(s) return(s) + +#define ACPI_ASSERT(exp) +#define DEBUG_ASSERT(msg, exp) + +#endif + +/* + * Some code only gets executed when the debugger is built in. + * Note that this is entirely independent of whether the + * DEBUG_PRINT stuff (set by ACPI_DEBUG) is on, or not. + */ +#ifdef ENABLE_DEBUGGER +#define DEBUGGER_EXEC(a) a +#else +#define DEBUGGER_EXEC(a) +#endif + + +/* + * For 16-bit code, we want to shrink some things even though + * we are using ACPI_DEBUG to get the debug output + */ +#ifdef _IA16 +#undef DEBUG_ONLY_MEMBERS +#undef _VERBOSE_STRUCTURES +#define DEBUG_ONLY_MEMBERS(a) +#endif + + +#ifdef ACPI_DEBUG + +/* + * 1) Set name to blanks + * 2) Copy the object name + */ + +#define ADD_OBJECT_NAME(a,b) MEMSET (a->common.name, ' ', sizeof (a->common.name));\ + STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name)) + +#else + +#define ADD_OBJECT_NAME(a,b) + +#endif + + +#endif /* ACMACROS_H */ diff --git a/drivers/bus/acpi/include/acnamesp.h b/drivers/bus/acpi/include/acnamesp.h new file mode 100644 index 0000000..c1c706b --- /dev/null +++ b/drivers/bus/acpi/include/acnamesp.h @@ -0,0 +1,430 @@ +/****************************************************************************** + * + * Name: acnamesp.h - Namespace subcomponent prototypes and defines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACNAMESP_H__ +#define __ACNAMESP_H__ + + +/* To search the entire name space, pass this as Search_base */ + +#define NS_ALL ((ACPI_HANDLE)0) + +/* + * Elements of Acpi_ns_properties are bit significant + * and should be one-to-one with values of ACPI_OBJECT_TYPE + */ +#define NSP_NORMAL 0 +#define NSP_NEWSCOPE 1 /* a definition of this type opens a name scope */ +#define NSP_LOCAL 2 /* suppress search of enclosing scopes */ + + +/* Definitions of the predefined namespace names */ + +#define ACPI_UNKNOWN_NAME (u32) 0x3F3F3F3F /* Unknown name is "????" */ +#define ACPI_ROOT_NAME (u32) 0x2F202020 /* Root name is "/ " */ +#define ACPI_SYS_BUS_NAME (u32) 0x5F53425F /* Sys bus name is "_SB_" */ + +#define NS_ROOT_PATH "/" +#define NS_SYSTEM_BUS "_SB_" + + +/* Flags for Acpi_ns_lookup, Acpi_ns_search_and_enter */ + +#define NS_NO_UPSEARCH 0 +#define NS_SEARCH_PARENT 0x01 +#define NS_DONT_OPEN_SCOPE 0x02 +#define NS_NO_PEER_SEARCH 0x04 +#define NS_ERROR_IF_FOUND 0x08 + +#define NS_WALK_UNLOCK TRUE +#define NS_WALK_NO_UNLOCK FALSE + + +ACPI_STATUS +acpi_ns_load_namespace ( + void); + +ACPI_STATUS +acpi_ns_initialize_objects ( + void); + +ACPI_STATUS +acpi_ns_initialize_devices ( + void); + + +/* Namespace init - nsxfinit */ + +ACPI_STATUS +acpi_ns_init_one_device ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value); + +ACPI_STATUS +acpi_ns_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + + +ACPI_STATUS +acpi_ns_walk_namespace ( + OBJECT_TYPE_INTERNAL type, + ACPI_HANDLE start_object, + u32 max_depth, + u8 unlock_before_callback, + WALK_CALLBACK user_function, + void *context, + void **return_value); + + +ACPI_NAMESPACE_NODE * +acpi_ns_get_next_object ( + OBJECT_TYPE_INTERNAL type, + ACPI_NAMESPACE_NODE *parent, + ACPI_NAMESPACE_NODE *child); + + +ACPI_STATUS +acpi_ns_delete_namespace_by_owner ( + u16 table_id); + + +/* Namespace loading - nsload */ + +ACPI_STATUS +acpi_ns_one_complete_parse ( + u32 pass_number, + ACPI_TABLE_DESC *table_desc); + +ACPI_STATUS +acpi_ns_parse_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMESPACE_NODE *scope); + +ACPI_STATUS +acpi_ns_load_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMESPACE_NODE *node); + +ACPI_STATUS +acpi_ns_load_table_by_type ( + ACPI_TABLE_TYPE table_type); + + +/* + * Top-level namespace access - nsaccess + */ + + +ACPI_STATUS +acpi_ns_root_initialize ( + void); + +ACPI_STATUS +acpi_ns_lookup ( + ACPI_GENERIC_STATE *scope_info, + NATIVE_CHAR *name, + OBJECT_TYPE_INTERNAL type, + OPERATING_MODE interpreter_mode, + u32 flags, + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE **ret_node); + + +/* + * Named object allocation/deallocation - nsalloc + */ + + +ACPI_NAMESPACE_NODE * +acpi_ns_create_node ( + u32 acpi_name); + +void +acpi_ns_delete_node ( + ACPI_NAMESPACE_NODE *node); + +ACPI_STATUS +acpi_ns_delete_namespace_subtree ( + ACPI_NAMESPACE_NODE *parent_handle); + +void +acpi_ns_detach_object ( + ACPI_NAMESPACE_NODE *node); + +void +acpi_ns_delete_children ( + ACPI_NAMESPACE_NODE *parent); + + +/* + * Namespace modification - nsmodify + */ + +ACPI_STATUS +acpi_ns_unload_namespace ( + ACPI_HANDLE handle); + +ACPI_STATUS +acpi_ns_delete_subtree ( + ACPI_HANDLE start_handle); + + +/* + * Namespace dump/print utilities - nsdump + */ + +void +acpi_ns_dump_tables ( + ACPI_HANDLE search_base, + u32 max_depth); + +void +acpi_ns_dump_entry ( + ACPI_HANDLE handle, + u32 debug_level); + +ACPI_STATUS +acpi_ns_dump_pathname ( + ACPI_HANDLE handle, + NATIVE_CHAR *msg, + u32 level, + u32 component); + +void +acpi_ns_dump_root_devices ( + void); + +void +acpi_ns_dump_objects ( + OBJECT_TYPE_INTERNAL type, + u32 max_depth, + u32 ownder_id, + ACPI_HANDLE start_handle); + + +/* + * Namespace evaluation functions - nseval + */ + +ACPI_STATUS +acpi_ns_evaluate_by_handle ( + ACPI_NAMESPACE_NODE *prefix_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_object); + +ACPI_STATUS +acpi_ns_evaluate_by_name ( + NATIVE_CHAR *pathname, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_object); + +ACPI_STATUS +acpi_ns_evaluate_relative ( + ACPI_NAMESPACE_NODE *prefix_node, + NATIVE_CHAR *pathname, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_object); + +ACPI_STATUS +acpi_ns_execute_control_method ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc); + +ACPI_STATUS +acpi_ns_get_object_value ( + ACPI_NAMESPACE_NODE *object_node, + ACPI_OPERAND_OBJECT **return_obj_desc); + + +/* + * Parent/Child/Peer utility functions - nsfamily + */ + +ACPI_NAME +acpi_ns_find_parent_name ( + ACPI_NAMESPACE_NODE *node_to_search); + +u8 +acpi_ns_exist_downstream_sibling ( + ACPI_NAMESPACE_NODE *this_node); + + +/* + * Scope manipulation - nsscope + */ + +u32 +acpi_ns_opens_scope ( + OBJECT_TYPE_INTERNAL type); + +NATIVE_CHAR * +acpi_ns_get_table_pathname ( + ACPI_NAMESPACE_NODE *node); + +NATIVE_CHAR * +acpi_ns_name_of_current_scope ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ns_handle_to_pathname ( + ACPI_HANDLE obj_handle, + u32 *buf_size, + NATIVE_CHAR *user_buffer); + +u8 +acpi_ns_pattern_match ( + ACPI_NAMESPACE_NODE *obj_node, + NATIVE_CHAR *search_for); + +ACPI_STATUS +acpi_ns_name_compare ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value); + +ACPI_STATUS +acpi_ns_get_node ( + NATIVE_CHAR *pathname, + ACPI_NAMESPACE_NODE *in_prefix_node, + ACPI_NAMESPACE_NODE **out_node); + +u32 +acpi_ns_get_pathname_length ( + ACPI_NAMESPACE_NODE *node); + + +/* + * Object management for NTEs - nsobject + */ + +ACPI_STATUS +acpi_ns_attach_object ( + ACPI_NAMESPACE_NODE *node, + ACPI_OPERAND_OBJECT *object, + OBJECT_TYPE_INTERNAL type); + + +void * +acpi_ns_compare_value ( + ACPI_HANDLE obj_handle, + u32 level, + void *obj_desc); + + +/* + * Namespace searching and entry - nssearch + */ + +ACPI_STATUS +acpi_ns_search_and_enter ( + u32 entry_name, + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE *node, + OPERATING_MODE interpreter_mode, + OBJECT_TYPE_INTERNAL type, + u32 flags, + ACPI_NAMESPACE_NODE **ret_node); + +ACPI_STATUS +acpi_ns_search_node ( + u32 entry_name, + ACPI_NAMESPACE_NODE *node, + OBJECT_TYPE_INTERNAL type, + ACPI_NAMESPACE_NODE **ret_node); + +void +acpi_ns_install_node ( + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE *parent_node, /* Parent */ + ACPI_NAMESPACE_NODE *node, /* New Child*/ + OBJECT_TYPE_INTERNAL type); + + +/* + * Utility functions - nsutils + */ + +u8 +acpi_ns_valid_root_prefix ( + NATIVE_CHAR prefix); + +u8 +acpi_ns_valid_path_separator ( + NATIVE_CHAR sep); + +OBJECT_TYPE_INTERNAL +acpi_ns_get_type ( + ACPI_HANDLE obj_handle); + +void * +acpi_ns_get_attached_object ( + ACPI_HANDLE obj_handle); + +u32 +acpi_ns_local ( + OBJECT_TYPE_INTERNAL type); + +ACPI_STATUS +acpi_ns_internalize_name ( + NATIVE_CHAR *dotted_name, + NATIVE_CHAR **converted_name); + +ACPI_STATUS +acpi_ns_externalize_name ( + u32 internal_name_length, + NATIVE_CHAR *internal_name, + u32 *converted_name_length, + NATIVE_CHAR **converted_name); + +ACPI_NAMESPACE_NODE * +acpi_ns_convert_handle_to_entry ( + ACPI_HANDLE handle); + +ACPI_HANDLE +acpi_ns_convert_entry_to_handle( + ACPI_NAMESPACE_NODE *node); + +void +acpi_ns_terminate ( + void); + +ACPI_NAMESPACE_NODE * +acpi_ns_get_parent_object ( + ACPI_NAMESPACE_NODE *node); + + +ACPI_NAMESPACE_NODE * +acpi_ns_get_next_valid_object ( + ACPI_NAMESPACE_NODE *node); + + +#endif /* __ACNAMESP_H__ */ diff --git a/drivers/bus/acpi/include/acobject.h b/drivers/bus/acpi/include/acobject.h new file mode 100644 index 0000000..d85ce64 --- /dev/null +++ b/drivers/bus/acpi/include/acobject.h @@ -0,0 +1,425 @@ + +/****************************************************************************** + * + * Name: acobject.h - Definition of ACPI_OPERAND_OBJECT (Internal object only) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ACOBJECT_H +#define _ACOBJECT_H + + +/* + * The ACPI_OPERAND_OBJECT is used to pass AML operands from the dispatcher + * to the interpreter, and to keep track of the various handlers such as + * address space handlers and notify handlers. The object is a constant + * size in order to allow them to be cached and reused. + * + * All variants of the ACPI_OPERAND_OBJECT are defined with the same + * sequence of field types, with fields that are not used in a particular + * variant being named "Reserved". This is not strictly necessary, but + * may in some circumstances simplify understanding if these structures + * need to be displayed in a debugger having limited (or no) support for + * union types. It also simplifies some debug code in Dump_table() which + * dumps multi-level values: fetching Buffer.Pointer suffices to pick up + * the value or next level for any of several types. + */ + +/****************************************************************************** + * + * Common Descriptors + * + *****************************************************************************/ + +/* + * Common area for all objects. + * + * Data_type is used to differentiate between internal descriptors, and MUST + * be the first byte in this structure. + */ + + +#define ACPI_OBJECT_COMMON_HEADER /* 32-bits plus 8-bit flag */\ + u8 data_type; /* To differentiate various internal objs */\ + u8 type; /* ACPI_OBJECT_TYPE */\ + u16 reference_count; /* For object deletion management */\ + u8 flags; \ + +/* Defines for flag byte above */ + +#define AOPOBJ_STATIC_ALLOCATION 0x1 +#define AOPOBJ_DATA_VALID 0x2 +#define AOPOBJ_INITIALIZED 0x4 + + +/* + * Common bitfield for the field objects + */ +#define ACPI_COMMON_FIELD_INFO /* Three 32-bit values plus 8*/\ + u8 granularity;\ + u16 length; \ + u32 offset; /* Byte offset within containing object */\ + u8 bit_offset; /* Bit offset within min read/write data unit */\ + u8 access; /* Access_type */\ + u8 lock_rule;\ + u8 update_rule;\ + u8 access_attribute; + + +/****************************************************************************** + * + * Individual Object Descriptors + * + *****************************************************************************/ + + +typedef struct /* COMMON */ +{ + ACPI_OBJECT_COMMON_HEADER + +} ACPI_OBJECT_COMMON; + + +typedef struct /* CACHE_LIST */ +{ + ACPI_OBJECT_COMMON_HEADER + union acpi_operand_obj *next; /* Link for object cache and internal lists*/ + +} ACPI_OBJECT_CACHE_LIST; + + +typedef struct /* NUMBER - has value */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_INTEGER value; + +} ACPI_OBJECT_INTEGER; + + +typedef struct /* STRING - has length and pointer - Null terminated, ASCII characters only */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 length; + NATIVE_CHAR *pointer; /* String value in AML stream or in allocated space */ + +} ACPI_OBJECT_STRING; + + +typedef struct /* BUFFER - has length and pointer - not null terminated */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 length; + u8 *pointer; /* points to the buffer in allocated space */ + +} ACPI_OBJECT_BUFFER; + + +typedef struct /* PACKAGE - has count, elements, next element */ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 count; /* # of elements in package */ + + union acpi_operand_obj **elements; /* Array of pointers to Acpi_objects */ + union acpi_operand_obj **next_element; /* used only while initializing */ + +} ACPI_OBJECT_PACKAGE; + + +typedef struct /* FIELD UNIT */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + + union acpi_operand_obj *extra; /* Pointer to executable AML (in field definition) */ + ACPI_NAMESPACE_NODE *node; /* containing object */ + union acpi_operand_obj *container; /* Containing object (Buffer) */ + +} ACPI_OBJECT_FIELD_UNIT; + + +typedef struct /* DEVICE - has handle and notification handler/context */ +{ + ACPI_OBJECT_COMMON_HEADER + + union acpi_operand_obj *sys_handler; /* Handler for system notifies */ + union acpi_operand_obj *drv_handler; /* Handler for driver notifies */ + union acpi_operand_obj *addr_handler; /* Handler for Address space */ + +} ACPI_OBJECT_DEVICE; + + +typedef struct /* EVENT */ +{ + ACPI_OBJECT_COMMON_HEADER + void *semaphore; + +} ACPI_OBJECT_EVENT; + + +#define INFINITE_CONCURRENCY 0xFF + +typedef struct /* METHOD */ +{ + ACPI_OBJECT_COMMON_HEADER + u8 method_flags; + u8 param_count; + + u32 pcode_length; + + void *semaphore; + u8 *pcode; + + u8 concurrency; + u8 thread_count; + ACPI_OWNER_ID owning_id; + +} ACPI_OBJECT_METHOD; + + +typedef struct acpi_obj_mutex /* MUTEX */ +{ + ACPI_OBJECT_COMMON_HEADER + u16 sync_level; + u16 acquisition_depth; + + void *semaphore; + void *owner; + union acpi_operand_obj *prev; /* Link for list of acquired mutexes */ + union acpi_operand_obj *next; /* Link for list of acquired mutexes */ + +} ACPI_OBJECT_MUTEX; + + +typedef struct /* REGION */ +{ + ACPI_OBJECT_COMMON_HEADER + + u8 space_id; + u32 length; + ACPI_PHYSICAL_ADDRESS address; + union acpi_operand_obj *extra; /* Pointer to executable AML (in region definition) */ + + union acpi_operand_obj *addr_handler; /* Handler for system notifies */ + ACPI_NAMESPACE_NODE *node; /* containing object */ + union acpi_operand_obj *next; + +} ACPI_OBJECT_REGION; + + +typedef struct /* POWER RESOURCE - has Handle and notification handler/context*/ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 system_level; + u32 resource_order; + + union acpi_operand_obj *sys_handler; /* Handler for system notifies */ + union acpi_operand_obj *drv_handler; /* Handler for driver notifies */ + +} ACPI_OBJECT_POWER_RESOURCE; + + +typedef struct /* PROCESSOR - has Handle and notification handler/context*/ +{ + ACPI_OBJECT_COMMON_HEADER + + u32 proc_id; + u32 length; + ACPI_IO_ADDRESS address; + + union acpi_operand_obj *sys_handler; /* Handler for system notifies */ + union acpi_operand_obj *drv_handler; /* Handler for driver notifies */ + union acpi_operand_obj *addr_handler; /* Handler for Address space */ + +} ACPI_OBJECT_PROCESSOR; + + +typedef struct /* THERMAL ZONE - has Handle and Handler/Context */ +{ + ACPI_OBJECT_COMMON_HEADER + + union acpi_operand_obj *sys_handler; /* Handler for system notifies */ + union acpi_operand_obj *drv_handler; /* Handler for driver notifies */ + union acpi_operand_obj *addr_handler; /* Handler for Address space */ + +} ACPI_OBJECT_THERMAL_ZONE; + + +/* + * Internal types + */ + + +typedef struct /* FIELD */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + + union acpi_operand_obj *container; /* Containing object */ + +} ACPI_OBJECT_FIELD; + + +typedef struct /* BANK FIELD */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + u32 value; /* Value to store into Bank_select */ + + ACPI_HANDLE bank_select; /* Bank select register */ + union acpi_operand_obj *container; /* Containing object */ + +} ACPI_OBJECT_BANK_FIELD; + + +typedef struct /* INDEX FIELD */ +{ + /* + * No container pointer needed since the index and data register definitions + * will define how to access the respective registers + */ + ACPI_OBJECT_COMMON_HEADER + + ACPI_COMMON_FIELD_INFO + u32 value; /* Value to store into Index register */ + + ACPI_HANDLE index; /* Index register */ + ACPI_HANDLE data; /* Data register */ + +} ACPI_OBJECT_INDEX_FIELD; + + +typedef struct /* NOTIFY HANDLER */ +{ + ACPI_OBJECT_COMMON_HEADER + + ACPI_NAMESPACE_NODE *node; /* Parent device */ + NOTIFY_HANDLER handler; + void *context; + +} ACPI_OBJECT_NOTIFY_HANDLER; + + +/* Flags for address handler */ + +#define ADDR_HANDLER_DEFAULT_INSTALLED 0x1 + + +typedef struct /* ADDRESS HANDLER */ +{ + ACPI_OBJECT_COMMON_HEADER + + u8 space_id; + u16 hflags; + ADDRESS_SPACE_HANDLER handler; + + ACPI_NAMESPACE_NODE *node; /* Parent device */ + void *context; + ADDRESS_SPACE_SETUP setup; + union acpi_operand_obj *region_list; /* regions using this handler */ + union acpi_operand_obj *next; + +} ACPI_OBJECT_ADDR_HANDLER; + + +/* + * The Reference object type is used for these opcodes: + * Arg[0-6], Local[0-7], Index_op, Name_op, Zero_op, One_op, Ones_op, Debug_op + */ + +typedef struct /* Reference - Local object type */ +{ + ACPI_OBJECT_COMMON_HEADER + + u8 target_type; /* Used for Index_op */ + u16 opcode; + u32 offset; /* Used for Arg_op, Local_op, and Index_op */ + + void *object; /* Name_op=>HANDLE to obj, Index_op=>ACPI_OPERAND_OBJECT */ + ACPI_NAMESPACE_NODE *node; + union acpi_operand_obj **where; + +} ACPI_OBJECT_REFERENCE; + + +/* + * Extra object is used as additional storage for types that + * have AML code in their declarations (Term_args) that must be + * evaluated at run time. + * + * Currently: Region and Field_unit types + */ + +typedef struct /* EXTRA */ +{ + ACPI_OBJECT_COMMON_HEADER + u8 byte_fill1; + u16 word_fill1; + u32 pcode_length; + u8 *pcode; + ACPI_NAMESPACE_NODE *method_REG; /* _REG method for this region (if any) */ + void *region_context; /* Region-specific data */ + +} ACPI_OBJECT_EXTRA; + + +/****************************************************************************** + * + * ACPI_OPERAND_OBJECT Descriptor - a giant union of all of the above + * + *****************************************************************************/ + +typedef union acpi_operand_obj +{ + ACPI_OBJECT_COMMON common; + ACPI_OBJECT_CACHE_LIST cache; + ACPI_OBJECT_INTEGER integer; + ACPI_OBJECT_STRING string; + ACPI_OBJECT_BUFFER buffer; + ACPI_OBJECT_PACKAGE package; + ACPI_OBJECT_FIELD_UNIT field_unit; + ACPI_OBJECT_DEVICE device; + ACPI_OBJECT_EVENT event; + ACPI_OBJECT_METHOD method; + ACPI_OBJECT_MUTEX mutex; + ACPI_OBJECT_REGION region; + ACPI_OBJECT_POWER_RESOURCE power_resource; + ACPI_OBJECT_PROCESSOR processor; + ACPI_OBJECT_THERMAL_ZONE thermal_zone; + ACPI_OBJECT_FIELD field; + ACPI_OBJECT_BANK_FIELD bank_field; + ACPI_OBJECT_INDEX_FIELD index_field; + ACPI_OBJECT_REFERENCE reference; + ACPI_OBJECT_NOTIFY_HANDLER notify_handler; + ACPI_OBJECT_ADDR_HANDLER addr_handler; + ACPI_OBJECT_EXTRA extra; + +} ACPI_OPERAND_OBJECT; + +#endif /* _ACOBJECT_H */ diff --git a/drivers/bus/acpi/include/acoutput.h b/drivers/bus/acpi/include/acoutput.h new file mode 100644 index 0000000..c416e02 --- /dev/null +++ b/drivers/bus/acpi/include/acoutput.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * + * Name: acoutput.h -- debug output + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACOUTPUT_H__ +#define __ACOUTPUT_H__ + +/* + * Debug levels and component IDs. These are used to control the + * granularity of the output of the DEBUG_PRINT macro -- on a per- + * component basis and a per-exception-type basis. + */ + +/* Component IDs -- used in the global "Debug_layer" */ + +#define ACPI_UTILITIES 0x00000001 +#define ACPI_HARDWARE 0x00000002 +#define ACPI_EVENTS 0x00000003 +#define ACPI_TABLES 0x00000008 +#define ACPI_NAMESPACE 0x00000010 +#define ACPI_PARSER 0x00000020 +#define ACPI_DISPATCHER 0x00000040 +#define ACPI_EXECUTER 0x00000080 +#define ACPI_RESOURCES 0x00000100 +#define ACPI_DEVICES 0x00000200 +#define ACPI_POWER 0x00000400 + + +#define ACPI_BUS_MANAGER 0x00001000 +#define ACPI_POWER_CONTROL 0x00002000 +#define ACPI_EMBEDDED_CONTROLLER 0x00004000 +#define ACPI_PROCESSOR_CONTROL 0x00008000 +#define ACPI_AC_ADAPTER 0x00010000 +#define ACPI_BATTERY 0x00020000 +#define ACPI_BUTTON 0x00040000 +#define ACPI_SYSTEM 0x00080000 +#define ACPI_THERMAL_ZONE 0x00100000 + +#define ACPI_DEBUGGER 0x01000000 +#define ACPI_OS_SERVICES 0x02000000 +#define ACPI_ALL_COMPONENTS 0x01FFFFFF + +#define ACPI_COMPONENT_DEFAULT (ACPI_ALL_COMPONENTS) + + +#define ACPI_COMPILER 0x10000000 +#define ACPI_TOOLS 0x20000000 + + +/* Exception level -- used in the global "Debug_level" */ + +#define ACPI_OK 0x00000001 +#define ACPI_INFO 0x00000002 +#define ACPI_WARN 0x00000004 +#define ACPI_ERROR 0x00000008 +#define ACPI_FATAL 0x00000010 +#define ACPI_DEBUG_OBJECT 0x00000020 +#define ACPI_ALL 0x0000003F + + +/* Trace level -- also used in the global "Debug_level" */ + +#define TRACE_PARSE 0x00000100 +#define TRACE_DISPATCH 0x00000200 +#define TRACE_LOAD 0x00000400 +#define TRACE_EXEC 0x00000800 +#define TRACE_NAMES 0x00001000 +#define TRACE_OPREGION 0x00002000 +#define TRACE_BFIELD 0x00004000 +#define TRACE_TRASH 0x00008000 +#define TRACE_TABLES 0x00010000 +#define TRACE_FUNCTIONS 0x00020000 +#define TRACE_VALUES 0x00040000 +#define TRACE_OBJECTS 0x00080000 +#define TRACE_ALLOCATIONS 0x00100000 +#define TRACE_RESOURCES 0x00200000 +#define TRACE_IO 0x00400000 +#define TRACE_INTERRUPTS 0x00800000 +#define TRACE_USER_REQUESTS 0x01000000 +#define TRACE_PACKAGE 0x02000000 +#define TRACE_MUTEX 0x04000000 +#define TRACE_INIT 0x08000000 + +#define TRACE_ALL 0x0FFFFF00 + + +/* Exceptionally verbose output -- also used in the global "Debug_level" */ + +#define VERBOSE_AML_DISASSEMBLE 0x10000000 +#define VERBOSE_INFO 0x20000000 +#define VERBOSE_TABLES 0x40000000 +#define VERBOSE_EVENTS 0x80000000 + +#define VERBOSE_ALL 0xF0000000 + + +/* Defaults for Debug_level, debug and normal */ + +#define DEBUG_DEFAULT (ACPI_OK | ACPI_WARN | ACPI_ERROR | ACPI_DEBUG_OBJECT) +#define NORMAL_DEFAULT (ACPI_OK | ACPI_WARN | ACPI_ERROR | ACPI_DEBUG_OBJECT) +#define DEBUG_ALL (VERBOSE_AML_DISASSEMBLE | TRACE_ALL | ACPI_ALL) + +/* Misc defines */ + +#define HEX 0x01 +#define ASCII 0x02 +#define FULL_ADDRESS 0x04 +#define CHARS_PER_LINE 16 /* used in Dump_buf function */ + + +#endif /* __ACOUTPUT_H__ */ diff --git a/drivers/bus/acpi/include/acparser.h b/drivers/bus/acpi/include/acparser.h new file mode 100644 index 0000000..421d515 --- /dev/null +++ b/drivers/bus/acpi/include/acparser.h @@ -0,0 +1,346 @@ +/****************************************************************************** + * + * Module Name: acparser.h - AML Parser subcomponent prototypes and defines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __ACPARSER_H__ +#define __ACPARSER_H__ + + +#define OP_HAS_RETURN_VALUE 1 + +/* variable # arguments */ + +#define ACPI_VAR_ARGS ACPI_UINT32_MAX + +/* maximum virtual address */ + +#define ACPI_MAX_AML ((u8 *)(~0UL)) + + +#define ACPI_PARSE_DELETE_TREE 0x0001 +#define ACPI_PARSE_NO_TREE_DELETE 0x0000 +#define ACPI_PARSE_TREE_MASK 0x0001 + +#define ACPI_PARSE_LOAD_PASS1 0x0010 +#define ACPI_PARSE_LOAD_PASS2 0x0020 +#define ACPI_PARSE_EXECUTE 0x0030 +#define ACPI_PARSE_MODE_MASK 0x0030 + +/* psapi - Parser external interfaces */ + +ACPI_STATUS +acpi_psx_load_table ( + u8 *pcode_addr, + u32 pcode_length); + +ACPI_STATUS +acpi_psx_execute ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc); + + +u8 +acpi_ps_is_namespace_object_op ( + u16 opcode); +u8 +acpi_ps_is_namespace_op ( + u16 opcode); + + +/****************************************************************************** + * + * Parser interfaces + * + *****************************************************************************/ + + +/* psargs - Parse AML opcode arguments */ + +u8 * +acpi_ps_get_next_package_end ( + ACPI_PARSE_STATE *parser_state); + +u32 +acpi_ps_get_next_package_length ( + ACPI_PARSE_STATE *parser_state); + +NATIVE_CHAR * +acpi_ps_get_next_namestring ( + ACPI_PARSE_STATE *parser_state); + +void +acpi_ps_get_next_simple_arg ( + ACPI_PARSE_STATE *parser_state, + u32 arg_type, /* type of argument */ + ACPI_PARSE_OBJECT *arg); /* (OUT) argument data */ + +void +acpi_ps_get_next_namepath ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *arg, + u32 *arg_count, + u8 method_call); + +ACPI_PARSE_OBJECT * +acpi_ps_get_next_field ( + ACPI_PARSE_STATE *parser_state); + +ACPI_PARSE_OBJECT * +acpi_ps_get_next_arg ( + ACPI_PARSE_STATE *parser_state, + u32 arg_type, + u32 *arg_count); + + +/* psopcode - AML Opcode information */ + +ACPI_OPCODE_INFO * +acpi_ps_get_opcode_info ( + u16 opcode); + +NATIVE_CHAR * +acpi_ps_get_opcode_name ( + u16 opcode); + + +/* psparse - top level parsing routines */ + +ACPI_STATUS +acpi_ps_find_object ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op); + +void +acpi_ps_delete_parse_tree ( + ACPI_PARSE_OBJECT *root); + +ACPI_STATUS +acpi_ps_parse_loop ( + ACPI_WALK_STATE *walk_state); + +ACPI_STATUS +acpi_ps_parse_aml ( + ACPI_PARSE_OBJECT *start_scope, + u8 *aml, + u32 aml_size, + u32 parse_flags, + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **caller_return_desc, + ACPI_PARSE_DOWNWARDS descending_callback, + ACPI_PARSE_UPWARDS ascending_callback); + +ACPI_STATUS +acpi_ps_parse_table ( + u8 *aml, + u32 aml_size, + ACPI_PARSE_DOWNWARDS descending_callback, + ACPI_PARSE_UPWARDS ascending_callback, + ACPI_PARSE_OBJECT **root_object); + +u16 +acpi_ps_peek_opcode ( + ACPI_PARSE_STATE *state); + + +/* psscope - Scope stack management routines */ + + +ACPI_STATUS +acpi_ps_init_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *root); + +ACPI_PARSE_OBJECT * +acpi_ps_get_parent_scope ( + ACPI_PARSE_STATE *state); + +u8 +acpi_ps_has_completed_scope ( + ACPI_PARSE_STATE *parser_state); + +void +acpi_ps_pop_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT **op, + u32 *arg_list, + u32 *arg_count); + +ACPI_STATUS +acpi_ps_push_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *op, + u32 remaining_args, + u32 arg_count); + +void +acpi_ps_cleanup_scope ( + ACPI_PARSE_STATE *state); + + +/* pstree - parse tree manipulation routines */ + +void +acpi_ps_append_arg( + ACPI_PARSE_OBJECT *op, + ACPI_PARSE_OBJECT *arg); + +ACPI_PARSE_OBJECT* +acpi_ps_find ( + ACPI_PARSE_OBJECT *scope, + NATIVE_CHAR *path, + u16 opcode, + u32 create); + +ACPI_PARSE_OBJECT * +acpi_ps_get_arg( + ACPI_PARSE_OBJECT *op, + u32 argn); + +ACPI_PARSE_OBJECT * +acpi_ps_get_child ( + ACPI_PARSE_OBJECT *op); + +ACPI_PARSE_OBJECT * +acpi_ps_get_depth_next ( + ACPI_PARSE_OBJECT *origin, + ACPI_PARSE_OBJECT *op); + + +/* pswalk - parse tree walk routines */ + +ACPI_STATUS +acpi_ps_walk_parsed_aml ( + ACPI_PARSE_OBJECT *start_op, + ACPI_PARSE_OBJECT *end_op, + ACPI_OPERAND_OBJECT *mth_desc, + ACPI_NAMESPACE_NODE *start_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **caller_return_desc, + ACPI_OWNER_ID owner_id, + ACPI_PARSE_DOWNWARDS descending_callback, + ACPI_PARSE_UPWARDS ascending_callback); + +ACPI_STATUS +acpi_ps_get_next_walk_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_PARSE_UPWARDS ascending_callback); + + +/* psutils - parser utilities */ + + +ACPI_PARSE_STATE * +acpi_ps_create_state ( + u8 *aml, + u32 aml_size); + +void +acpi_ps_init_op ( + ACPI_PARSE_OBJECT *op, + u16 opcode); + +ACPI_PARSE_OBJECT * +acpi_ps_alloc_op ( + u16 opcode); + +void +acpi_ps_free_op ( + ACPI_PARSE_OBJECT *op); + +void +acpi_ps_delete_parse_cache ( + void); + +u8 +acpi_ps_is_leading_char ( + u32 c); + +u8 +acpi_ps_is_prefix_char ( + u32 c); + +u8 +acpi_ps_is_named_op ( + u16 opcode); + +u8 +acpi_ps_is_node_op ( + u16 opcode); + +u8 +acpi_ps_is_deferred_op ( + u16 opcode); + +u8 +acpi_ps_is_bytelist_op( + u16 opcode); + +u8 +acpi_ps_is_field_op( + u16 opcode); + +u8 +acpi_ps_is_create_field_op ( + u16 opcode); + +ACPI_PARSE2_OBJECT* +acpi_ps_to_extended_op( + ACPI_PARSE_OBJECT *op); + +u32 +acpi_ps_get_name( + ACPI_PARSE_OBJECT *op); + +void +acpi_ps_set_name( + ACPI_PARSE_OBJECT *op, + u32 name); + + +/* psdump - display parser tree */ + +u32 +acpi_ps_sprint_path ( + NATIVE_CHAR *buffer_start, + u32 buffer_size, + ACPI_PARSE_OBJECT *op); + +u32 +acpi_ps_sprint_op ( + NATIVE_CHAR *buffer_start, + u32 buffer_size, + ACPI_PARSE_OBJECT *op); + +void +acpi_ps_show ( + ACPI_PARSE_OBJECT *op); + + +#endif /* __ACPARSER_H__ */ diff --git a/drivers/bus/acpi/include/acpi.h b/drivers/bus/acpi/include/acpi.h new file mode 100644 index 0000000..59514c4 --- /dev/null +++ b/drivers/bus/acpi/include/acpi.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * + * Name: acpi.h - Master include file, Publics and external data. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACPI_H__ +#define __ACPI_H__ + +/* + * Common includes for all ACPI driver files + * We put them here because we don't want to duplicate them + * in the rest of the source code again and again. + */ +#include "acconfig.h" /* Configuration constants */ +#include "platform/acenv.h" /* Target environment specific items */ +#include "actypes.h" /* Fundamental common data types */ +#include "acexcep.h" /* ACPI exception codes */ +#include "acmacros.h" /* C macros */ +#include "actbl.h" /* ACPI table definitions */ +#include "aclocal.h" /* Internal data types */ +#include "acoutput.h" /* Error output and Debug macros */ +#include "acpiosxf.h" /* Interfaces to the ACPI-to-OS layer*/ +#include "acpixf.h" /* ACPI core subsystem external interfaces */ +#include "acobject.h" /* ACPI internal object */ +#include "acstruct.h" /* Common structures */ +#include "acglobal.h" /* All global variables */ +#include "achware.h" /* Hardware defines and interfaces */ +#include "accommon.h" /* Common interfaces */ + + +#endif /* __ACPI_H__ */ diff --git a/drivers/bus/acpi/include/acpiosxf.h b/drivers/bus/acpi/include/acpiosxf.h new file mode 100644 index 0000000..f65e038 --- /dev/null +++ b/drivers/bus/acpi/include/acpiosxf.h @@ -0,0 +1,341 @@ + +/****************************************************************************** + * + * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These + * interfaces must be implemented by OSL to interface the + * ACPI components to the host operating system. + * + *****************************************************************************/ + + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACPIOSXF_H__ +#define __ACPIOSXF_H__ + +#include "platform/acenv.h" +#include "actypes.h" + + +/* Priorities for Acpi_os_queue_for_execution */ + +#define OSD_PRIORITY_GPE 1 +#define OSD_PRIORITY_HIGH 2 +#define OSD_PRIORITY_MED 3 +#define OSD_PRIORITY_LO 4 + +#define ACPI_NO_UNIT_LIMIT ((u32) -1) +#define ACPI_MUTEX_SEM 1 + + +/* + * Types specific to the OS service interfaces + */ + +typedef +u32 (*OSD_HANDLER) ( + void *context); + +typedef +void (*OSD_EXECUTION_CALLBACK) ( + void *context); + + +/* + * OSL Initialization and shutdown primitives + */ + +ACPI_STATUS +acpi_os_initialize ( + void); + +ACPI_STATUS +acpi_os_terminate ( + void); + + +/* + * Synchronization primitives + */ + +ACPI_STATUS +acpi_os_create_semaphore ( + u32 max_units, + u32 initial_units, + ACPI_HANDLE *out_handle); + +ACPI_STATUS +acpi_os_delete_semaphore ( + ACPI_HANDLE handle); + +ACPI_STATUS +acpi_os_wait_semaphore ( + ACPI_HANDLE handle, + u32 units, + u32 timeout); + +ACPI_STATUS +acpi_os_signal_semaphore ( + ACPI_HANDLE handle, + u32 units); + + +/* + * Memory allocation and mapping + */ + +void * +acpi_os_allocate ( + u32 size); + +void * +acpi_os_callocate ( + u32 size); + +void +acpi_os_free ( + void * memory); + +ACPI_STATUS +acpi_os_map_memory ( + ACPI_PHYSICAL_ADDRESS physical_address, + u32 length, + void **logical_address); + +void +acpi_os_unmap_memory ( + void *logical_address, + u32 length); + +ACPI_STATUS +acpi_os_get_physical_address ( + void *logical_address, + ACPI_PHYSICAL_ADDRESS *physical_address); + + +/* + * Interrupt handlers + */ + +ACPI_STATUS +acpi_os_install_interrupt_handler ( + u32 interrupt_number, + OSD_HANDLER service_routine, + void *context); + +ACPI_STATUS +acpi_os_remove_interrupt_handler ( + u32 interrupt_number, + OSD_HANDLER service_routine); + + +/* + * Threads and Scheduling + */ + +u32 +acpi_os_get_thread_id ( + void); + +ACPI_STATUS +acpi_os_queue_for_execution ( + u32 priority, + OSD_EXECUTION_CALLBACK function, + void *context); + +void +acpi_os_sleep ( + u32 seconds, + u32 milliseconds); + +void +acpi_os_sleep_usec ( + u32 microseconds); + + +/* + * Platform/Hardware independent I/O interfaces + */ + +u8 +acpi_os_in8 ( + ACPI_IO_ADDRESS in_port); + + +u16 +acpi_os_in16 ( + ACPI_IO_ADDRESS in_port); + +u32 +acpi_os_in32 ( + ACPI_IO_ADDRESS in_port); + +void +acpi_os_out8 ( + ACPI_IO_ADDRESS out_port, + u8 value); + +void +acpi_os_out16 ( + ACPI_IO_ADDRESS out_port, + u16 value); + +void +acpi_os_out32 ( + ACPI_IO_ADDRESS out_port, + u32 value); + + +/* + * Platform/Hardware independent physical memory interfaces + */ + +u8 +acpi_os_mem_in8 ( + ACPI_PHYSICAL_ADDRESS in_addr); + +u16 +acpi_os_mem_in16 ( + ACPI_PHYSICAL_ADDRESS in_addr); + +u32 +acpi_os_mem_in32 ( + ACPI_PHYSICAL_ADDRESS in_addr); + +void +acpi_os_mem_out8 ( + ACPI_PHYSICAL_ADDRESS out_addr, + u8 value); + +void +acpi_os_mem_out16 ( + ACPI_PHYSICAL_ADDRESS out_addr, + u16 value); + +void +acpi_os_mem_out32 ( + ACPI_PHYSICAL_ADDRESS out_addr, + u32 value); + + +/* + * Standard access to PCI configuration space + */ + +ACPI_STATUS +acpi_os_read_pci_cfg_byte ( + u32 bus, + u32 device_function, + u32 register, + u8 *value); + +ACPI_STATUS +acpi_os_read_pci_cfg_word ( + u32 bus, + u32 device_function, + u32 register, + u16 *value); + +ACPI_STATUS +acpi_os_read_pci_cfg_dword ( + u32 bus, + u32 device_function, + u32 register, + u32 *value); + +ACPI_STATUS +acpi_os_write_pci_cfg_byte ( + u32 bus, + u32 device_function, + u32 register, + u8 value); + +ACPI_STATUS +acpi_os_write_pci_cfg_word ( + u32 bus, + u32 device_function, + u32 register, + u16 value); + + +ACPI_STATUS +acpi_os_write_pci_cfg_dword ( + u32 bus, + u32 device_function, + u32 register, + u32 value); + + +/* + * Miscellaneous + */ + +ACPI_STATUS +acpi_os_breakpoint ( + NATIVE_CHAR *message); + +u8 +acpi_os_readable ( + void *pointer, + u32 length); + + +u8 +acpi_os_writable ( + void *pointer, + u32 length); + + +/* + * Debug print routines + */ + +s32 +acpi_os_printf ( + const NATIVE_CHAR *format, + ...); + +s32 +acpi_os_vprintf ( + const NATIVE_CHAR *format, + va_list args); + + +/* + * Debug input + */ + +u32 +acpi_os_get_line ( + NATIVE_CHAR *buffer); + + +/* + * Debug + */ + +void +acpi_os_dbg_assert( + void *failed_assertion, + void *file_name, + u32 line_number, + NATIVE_CHAR *message); + + +#endif /* __ACPIOSXF_H__ */ diff --git a/drivers/bus/acpi/include/acpixf.h b/drivers/bus/acpi/include/acpixf.h new file mode 100644 index 0000000..ef4b1dc --- /dev/null +++ b/drivers/bus/acpi/include/acpixf.h @@ -0,0 +1,340 @@ + +/****************************************************************************** + * + * Name: acpixf.h - External interfaces to the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __ACXFACE_H__ +#define __ACXFACE_H__ + +#include "actypes.h" +#include "actbl.h" + + +/* + * Global interfaces + */ + +ACPI_STATUS +acpi_initialize_subsystem ( + void); + +ACPI_STATUS +acpi_enable_subsystem ( + u32 flags); + +ACPI_STATUS +acpi_terminate ( + void); + +ACPI_STATUS +acpi_enable ( + void); + +ACPI_STATUS +acpi_disable ( + void); + +ACPI_STATUS +acpi_get_system_info( + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_format_exception ( + ACPI_STATUS exception, + ACPI_BUFFER *out_buffer); + + +/* + * ACPI Memory manager + */ + +void * +acpi_allocate ( + u32 size); + +void * +acpi_callocate ( + u32 size); + +void +acpi_free ( + void *address); + + +/* + * ACPI table manipulation interfaces + */ + +ACPI_STATUS +acpi_find_root_pointer ( + ACPI_PHYSICAL_ADDRESS *rsdp_physical_address); + +ACPI_STATUS +acpi_load_tables ( + ACPI_PHYSICAL_ADDRESS rsdp_physical_address); + +ACPI_STATUS +acpi_load_table ( + ACPI_TABLE_HEADER *table_ptr); + +ACPI_STATUS +acpi_unload_table ( + ACPI_TABLE_TYPE table_type); + +ACPI_STATUS +acpi_get_table_header ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER *out_table_header); + +ACPI_STATUS +acpi_get_table ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_BUFFER *ret_buffer); + + +/* + * Namespace and name interfaces + */ + +ACPI_STATUS +acpi_walk_namespace ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE start_object, + u32 max_depth, + WALK_CALLBACK user_function, + void *context, + void * *return_value); + +ACPI_STATUS +acpi_get_devices ( + NATIVE_CHAR *HID, + WALK_CALLBACK user_function, + void *context, + void **return_value); + +ACPI_STATUS +acpi_get_name ( + ACPI_HANDLE handle, + u32 name_type, + ACPI_BUFFER *ret_path_ptr); + +ACPI_STATUS +acpi_get_handle ( + ACPI_HANDLE parent, + ACPI_STRING pathname, + ACPI_HANDLE *ret_handle); + + +/* + * Object manipulation and enumeration + */ + +ACPI_STATUS +acpi_evaluate_object ( + ACPI_HANDLE object, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *parameter_objects, + ACPI_BUFFER *return_object_buffer); + +ACPI_STATUS +acpi_get_object_info ( + ACPI_HANDLE device, + ACPI_DEVICE_INFO *info); + +ACPI_STATUS +acpi_get_next_object ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE parent, + ACPI_HANDLE child, + ACPI_HANDLE *out_handle); + +ACPI_STATUS +acpi_get_type ( + ACPI_HANDLE object, + ACPI_OBJECT_TYPE *out_type); + +ACPI_STATUS +acpi_get_parent ( + ACPI_HANDLE object, + ACPI_HANDLE *out_handle); + + +/* + * Event handler interfaces + */ + +ACPI_STATUS +acpi_install_fixed_event_handler ( + u32 acpi_event, + FIXED_EVENT_HANDLER handler, + void *context); + +ACPI_STATUS +acpi_remove_fixed_event_handler ( + u32 acpi_event, + FIXED_EVENT_HANDLER handler); + +ACPI_STATUS +acpi_install_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler, + void *context); + +ACPI_STATUS +acpi_remove_notify_handler ( + ACPI_HANDLE device, + u32 handler_type, + NOTIFY_HANDLER handler); + +ACPI_STATUS +acpi_install_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler, + ADDRESS_SPACE_SETUP setup, + void *context); + +ACPI_STATUS +acpi_remove_address_space_handler ( + ACPI_HANDLE device, + ACPI_ADDRESS_SPACE_TYPE space_id, + ADDRESS_SPACE_HANDLER handler); + +ACPI_STATUS +acpi_install_gpe_handler ( + u32 gpe_number, + u32 type, + GPE_HANDLER handler, + void *context); + +ACPI_STATUS +acpi_acquire_global_lock ( + void); + +ACPI_STATUS +acpi_release_global_lock ( + void); + +ACPI_STATUS +acpi_remove_gpe_handler ( + u32 gpe_number, + GPE_HANDLER handler); + +ACPI_STATUS +acpi_enable_event ( + u32 acpi_event, + u32 type); + +ACPI_STATUS +acpi_disable_event ( + u32 acpi_event, + u32 type); + +ACPI_STATUS +acpi_clear_event ( + u32 acpi_event, + u32 type); + +ACPI_STATUS +acpi_get_event_status ( + u32 acpi_event, + u32 type, + ACPI_EVENT_STATUS *event_status); + +/* + * Resource interfaces + */ + +ACPI_STATUS +acpi_get_current_resources( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_get_possible_resources( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_set_current_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *in_buffer); + +ACPI_STATUS +acpi_get_irq_routing_table ( + ACPI_HANDLE bus_device_handle, + ACPI_BUFFER *ret_buffer); + + +/* + * Hardware (ACPI device) interfaces + */ + +ACPI_STATUS +acpi_set_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS physical_address); + +ACPI_STATUS +acpi_get_firmware_waking_vector ( + ACPI_PHYSICAL_ADDRESS *physical_address); + +ACPI_STATUS +acpi_enter_sleep_state ( + u8 sleep_state); + +ACPI_STATUS +acpi_get_processor_throttling_info ( + ACPI_HANDLE processor_handle, + ACPI_BUFFER *user_buffer); + +ACPI_STATUS +acpi_set_processor_throttling_state ( + ACPI_HANDLE processor_handle, + u32 throttle_state); + +ACPI_STATUS +acpi_get_processor_throttling_state ( + ACPI_HANDLE processor_handle, + u32 *throttle_state); + +ACPI_STATUS +acpi_get_processor_cx_info ( + ACPI_HANDLE processor_handle, + ACPI_BUFFER *user_buffer); + +ACPI_STATUS +acpi_set_processor_sleep_state ( + ACPI_HANDLE processor_handle, + u32 cx_state); + +ACPI_STATUS +acpi_processor_sleep ( + ACPI_HANDLE processor_handle, + u32 *pm_timer_ticks); + + +#endif /* __ACXFACE_H__ */ diff --git a/drivers/bus/acpi/include/acresrc.h b/drivers/bus/acpi/include/acresrc.h new file mode 100644 index 0000000..1da8751 --- /dev/null +++ b/drivers/bus/acpi/include/acresrc.h @@ -0,0 +1,304 @@ +/****************************************************************************** + * + * Name: acresrc.h - Resource Manager function prototypes + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACRESRC_H__ +#define __ACRESRC_H__ + + +/* + * Function prototypes called from Acpi* APIs + */ + +ACPI_STATUS +acpi_rs_get_prt_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + + +ACPI_STATUS +acpi_rs_get_crs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_rs_get_prs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_rs_set_srs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer); + +ACPI_STATUS +acpi_rs_create_resource_list ( + ACPI_OPERAND_OBJECT *byte_stream_buffer, + u8 *output_buffer, + u32 *output_buffer_length); + +ACPI_STATUS +acpi_rs_create_byte_stream ( + RESOURCE *linked_list_buffer, + u8 *output_buffer, + u32 *output_buffer_length); + +ACPI_STATUS +acpi_rs_create_pci_routing_table ( + ACPI_OPERAND_OBJECT *method_return_object, + u8 *output_buffer, + u32 *output_buffer_length); + + +/* + *Function prototypes called from Acpi_rs_create*APIs + */ + +void +acpi_rs_dump_resource_list ( + RESOURCE *resource); + +void +acpi_rs_dump_irq_list ( + u8 *route_table); + +ACPI_STATUS +acpi_rs_get_byte_stream_start ( + u8 *byte_stream_buffer, + u8 **byte_stream_start, + u32 *size); + +ACPI_STATUS +acpi_rs_calculate_list_length ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u32 *size_needed); + +ACPI_STATUS +acpi_rs_calculate_byte_stream_length ( + RESOURCE *linked_list_buffer, + u32 *size_needed); + +ACPI_STATUS +acpi_rs_calculate_pci_routing_table_length ( + ACPI_OPERAND_OBJECT *package_object, + u32 *buffer_size_needed); + +ACPI_STATUS +acpi_rs_byte_stream_to_list ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u8 **output_buffer); + +ACPI_STATUS +acpi_rs_list_to_byte_stream ( + RESOURCE *linked_list, + u32 byte_stream_size_needed, + u8 **output_buffer); + +ACPI_STATUS +acpi_rs_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_fixed_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_fixed_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_dma_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_dma_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_address16_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_address16_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_address32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_address32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_start_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_end_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_start_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_end_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_memory24_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_memory24_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_memory32_range_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size +); + +ACPI_STATUS +acpi_rs_fixed_memory32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_memory32_range_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_fixed_memory32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_extended_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_extended_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_end_tag_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_end_tag_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + +ACPI_STATUS +acpi_rs_vendor_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size); + +ACPI_STATUS +acpi_rs_vendor_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed); + + +#endif /* __ACRESRC_H__ */ diff --git a/drivers/bus/acpi/include/acstruct.h b/drivers/bus/acpi/include/acstruct.h new file mode 100644 index 0000000..1e9b375 --- /dev/null +++ b/drivers/bus/acpi/include/acstruct.h @@ -0,0 +1,157 @@ +/****************************************************************************** + * + * Name: acstruct.h - Internal structs + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACSTRUCT_H__ +#define __ACSTRUCT_H__ + + +/***************************************************************************** + * + * Tree walking typedefs and structs + * + ****************************************************************************/ + + +/* + * Walk state - current state of a parse tree walk. Used for both a leisurely stroll through + * the tree (for whatever reason), and for control method execution. + */ + +#define NEXT_OP_DOWNWARD 1 +#define NEXT_OP_UPWARD 2 + +#define WALK_NON_METHOD 0 +#define WALK_METHOD 1 +#define WALK_METHOD_RESTART 2 + +typedef struct acpi_walk_state +{ + u8 data_type; /* To differentiate various internal objs */\ + ACPI_OWNER_ID owner_id; /* Owner of objects created during the walk */ + u8 last_predicate; /* Result of last predicate */ + u8 next_op_info; /* Info about Next_op */ + u8 num_operands; /* Stack pointer for Operands[] array */ + u8 current_result; /* */ + + struct acpi_walk_state *next; /* Next Walk_state in list */ + ACPI_PARSE_OBJECT *origin; /* Start of walk [Obsolete] */ + +/* TBD: Obsolete with removal of WALK procedure ? */ + ACPI_PARSE_OBJECT *prev_op; /* Last op that was processed */ + ACPI_PARSE_OBJECT *next_op; /* next op to be processed */ + + + ACPI_GENERIC_STATE *results; /* Stack of accumulated results */ + ACPI_GENERIC_STATE *control_state; /* List of control states (nested IFs) */ + ACPI_GENERIC_STATE *scope_info; /* Stack of nested scopes */ + ACPI_PARSE_STATE *parser_state; /* Current state of parser */ + u8 *aml_last_while; + ACPI_OPCODE_INFO *op_info; /* Info on current opcode */ + ACPI_PARSE_DOWNWARDS descending_callback; + ACPI_PARSE_UPWARDS ascending_callback; + + union acpi_operand_obj *return_desc; /* Return object, if any */ + union acpi_operand_obj *method_desc; /* Method descriptor if running a method */ + struct acpi_node *method_node; /* Method Node if running a method */ + ACPI_PARSE_OBJECT *method_call_op; /* Method_call Op if running a method */ + struct acpi_node *method_call_node; /* Called method Node*/ + union acpi_operand_obj *operands[OBJ_NUM_OPERANDS]; /* Operands passed to the interpreter */ + struct acpi_node arguments[MTH_NUM_ARGS]; /* Control method arguments */ + struct acpi_node local_variables[MTH_NUM_LOCALS]; /* Control method locals */ + struct acpi_walk_list *walk_list; + u32 parse_flags; + u8 walk_type; + u8 return_used; + u16 opcode; /* Current AML opcode */ + u32 prev_arg_types; + u16 current_sync_level; /* Mutex Sync (nested acquire) level */ + + /* Debug support */ + + u32 method_breakpoint; + + +} ACPI_WALK_STATE; + + +/* + * Walk list - head of a tree of walk states. Multiple walk states are created when there + * are nested control methods executing. + */ +typedef struct acpi_walk_list +{ + + ACPI_WALK_STATE *walk_state; + ACPI_OBJECT_MUTEX acquired_mutex_list; /* List of all currently acquired mutexes */ + +} ACPI_WALK_LIST; + + +/* Info used by Acpi_ps_init_objects */ + +typedef struct acpi_init_walk_info +{ + u16 method_count; + u16 op_region_count; + u16 field_count; + u16 op_region_init; + u16 field_init; + u16 object_count; + ACPI_TABLE_DESC *table_desc; + +} ACPI_INIT_WALK_INFO; + + +/* Info used by TBD */ + +typedef struct acpi_device_walk_info +{ + u16 device_count; + u16 num_STA; + u16 num_INI; + ACPI_TABLE_DESC *table_desc; + +} ACPI_DEVICE_WALK_INFO; + + +/* TBD: [Restructure] Merge with struct above */ + +typedef struct acpi_walk_info +{ + u32 debug_level; + u32 owner_id; + +} ACPI_WALK_INFO; + +typedef struct acpi_get_devices_info +{ + WALK_CALLBACK user_function; + void *context; + NATIVE_CHAR *hid; + +} ACPI_GET_DEVICES_INFO; + + +#endif diff --git a/drivers/bus/acpi/include/actables.h b/drivers/bus/acpi/include/actables.h new file mode 100644 index 0000000..9a22d78 --- /dev/null +++ b/drivers/bus/acpi/include/actables.h @@ -0,0 +1,185 @@ +/****************************************************************************** + * + * Name: actables.h - ACPI table management + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTABLES_H__ +#define __ACTABLES_H__ + + +/* Used in Acpi_tb_map_acpi_table for size parameter if table header is to be used */ + +#define SIZE_IN_HEADER 0 + + +ACPI_STATUS +acpi_tb_handle_to_object ( + u16 table_id, + ACPI_TABLE_DESC **table_desc); + +/* + * tbconvrt - Table conversion routines + */ + +ACPI_STATUS +acpi_tb_convert_to_xsdt ( + ACPI_TABLE_DESC *table_info, + u32 *number_of_tables); + +ACPI_STATUS +acpi_tb_convert_table_fadt ( + void); + +ACPI_STATUS +acpi_tb_build_common_facs ( + ACPI_TABLE_DESC *table_info); + + +/* + * tbget - Table "get" routines + */ + +ACPI_STATUS +acpi_tb_get_table_ptr ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER **table_ptr_loc); + +ACPI_STATUS +acpi_tb_get_table ( + ACPI_PHYSICAL_ADDRESS physical_address, + ACPI_TABLE_HEADER *buffer_ptr, + ACPI_TABLE_DESC *table_info); + +ACPI_STATUS +acpi_tb_verify_rsdp ( + ACPI_PHYSICAL_ADDRESS RSDP_physical_address); + +ACPI_STATUS +acpi_tb_get_table_facs ( + ACPI_TABLE_HEADER *buffer_ptr, + ACPI_TABLE_DESC *table_info); + + +/* + * tbgetall - Get all firmware ACPI tables + */ + +ACPI_STATUS +acpi_tb_get_all_tables ( + u32 number_of_tables, + ACPI_TABLE_HEADER *buffer_ptr); + + +/* + * tbinstall - Table installation + */ + +ACPI_STATUS +acpi_tb_install_table ( + ACPI_TABLE_HEADER *table_ptr, + ACPI_TABLE_DESC *table_info); + +ACPI_STATUS +acpi_tb_recognize_table ( + ACPI_TABLE_HEADER *table_ptr, + ACPI_TABLE_DESC *table_info); + +ACPI_STATUS +acpi_tb_init_table_descriptor ( + ACPI_TABLE_TYPE table_type, + ACPI_TABLE_DESC *table_info); + + +/* + * tbremove - Table removal and deletion + */ + +void +acpi_tb_delete_acpi_tables ( + void); + +void +acpi_tb_delete_acpi_table ( + ACPI_TABLE_TYPE type); + +void +acpi_tb_delete_single_table ( + ACPI_TABLE_DESC *table_desc); + +ACPI_TABLE_DESC * +acpi_tb_uninstall_table ( + ACPI_TABLE_DESC *table_desc); + +void +acpi_tb_free_acpi_tables_of_type ( + ACPI_TABLE_DESC *table_info); + + +/* + * tbrsd - RSDP, RSDT utilities + */ + +ACPI_STATUS +acpi_tb_get_table_rsdt ( + u32 *number_of_tables); + +u8 * +acpi_tb_scan_memory_for_rsdp ( + u8 *start_address, + u32 length); + +ACPI_STATUS +acpi_tb_find_rsdp ( + ACPI_TABLE_DESC *table_info); + + +/* + * tbutils - common table utilities + */ + +u8 +acpi_tb_system_table_pointer ( + void *where); + +ACPI_STATUS +acpi_tb_map_acpi_table ( + ACPI_PHYSICAL_ADDRESS physical_address, + u32 *size, + void **logical_address); + +ACPI_STATUS +acpi_tb_verify_table_checksum ( + ACPI_TABLE_HEADER *table_header); + +u8 +acpi_tb_checksum ( + void *buffer, + u32 length); + +ACPI_STATUS +acpi_tb_validate_table_header ( + ACPI_TABLE_HEADER *table_header); + + +#endif /* __ACTABLES_H__ */ diff --git a/drivers/bus/acpi/include/actbl.h b/drivers/bus/acpi/include/actbl.h new file mode 100644 index 0000000..9dcfa3f --- /dev/null +++ b/drivers/bus/acpi/include/actbl.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * Name: actbl.h - Table data structures defined in ACPI specification + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTBL_H__ +#define __ACTBL_H__ + + +/* + * Values for description table header signatures + */ + +#define RSDP_NAME "RSDP" +#define RSDP_SIG "RSD PTR " /* RSDT Pointer signature */ +#define APIC_SIG "APIC" /* Multiple APIC Description Table */ +#define DSDT_SIG "DSDT" /* Differentiated System Description Table */ +#define FADT_SIG "FACP" /* Fixed ACPI Description Table */ +#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */ +#define PSDT_SIG "PSDT" /* Persistent System Description Table */ +#define RSDT_SIG "RSDT" /* Root System Description Table */ +#define XSDT_SIG "XSDT" /* Extended System Description Table */ +#define SSDT_SIG "SSDT" /* Secondary System Description Table */ +#define SBST_SIG "SBST" /* Smart Battery Specification Table */ +#define SPIC_SIG "SPIC" /* iosapic table */ +#define BOOT_SIG "BOOT" /* Boot table */ + + +#define GL_OWNED 0x02 /* Ownership of global lock is bit 1 */ + +/* values of Mapic.Model */ + +#define DUAL_PIC 0 +#define MULTIPLE_APIC 1 + +/* values of Type in APIC_HEADER */ + +#define APIC_PROC 0 +#define APIC_IO 1 + + +/* + * Common table types. The base code can remain + * constant if the underlying tables are changed + */ +#define RSDT_DESCRIPTOR RSDT_DESCRIPTOR_REV2 +#define XSDT_DESCRIPTOR XSDT_DESCRIPTOR_REV2 +#define FACS_DESCRIPTOR FACS_DESCRIPTOR_REV2 +#define FADT_DESCRIPTOR FADT_DESCRIPTOR_REV2 + + +#pragma pack(1) + +/* + * Architecture-independent tables + * The architecture dependent tables are in separate files + */ + +typedef struct /* Root System Descriptor Pointer */ +{ + NATIVE_CHAR signature [8]; /* contains "RSD PTR " */ + u8 checksum; /* to make sum of struct == 0 */ + NATIVE_CHAR oem_id [6]; /* OEM identification */ + u8 revision; /* Must be 0 for 1.0, 2 for 2.0 */ + u32 rsdt_physical_address; /* 32-bit physical address of RSDT */ + u32 length; /* XSDT Length in bytes including hdr */ + UINT64 xsdt_physical_address; /* 64-bit physical address of XSDT */ + u8 extended_checksum; /* Checksum of entire table */ + NATIVE_CHAR reserved [3]; /* reserved field must be 0 */ + +} RSDP_DESCRIPTOR; + + +typedef struct /* ACPI common table header */ +{ + NATIVE_CHAR signature [4]; /* identifies type of table */ + u32 length; /* length of table, in bytes, + * including header */ + u8 revision; /* specification minor version # */ + u8 checksum; /* to make sum of entire table == 0 */ + NATIVE_CHAR oem_id [6]; /* OEM identification */ + NATIVE_CHAR oem_table_id [8]; /* OEM table identification */ + u32 oem_revision; /* OEM revision number */ + NATIVE_CHAR asl_compiler_id [4]; /* ASL compiler vendor ID */ + u32 asl_compiler_revision; /* ASL compiler revision number */ + +} ACPI_TABLE_HEADER; + + +typedef struct /* Common FACS for internal use */ +{ + u32 *global_lock; + UINT64 *firmware_waking_vector; + u8 vector_width; + +} ACPI_COMMON_FACS; + + +typedef struct /* APIC Table */ +{ + ACPI_TABLE_HEADER header; /* table header */ + u32 local_apic_address; /* Physical address for accessing local APICs */ + u32 PCATcompat : 1; /* a one indicates system also has dual 8259s */ + u32 reserved1 : 31; + +} APIC_TABLE; + + +typedef struct /* APIC Header */ +{ + u8 type; /* APIC type. Either APIC_PROC or APIC_IO */ + u8 length; /* Length of APIC structure */ + +} APIC_HEADER; + + +typedef struct /* Processor APIC */ +{ + APIC_HEADER header; + u8 processor_apic_id; /* ACPI processor id */ + u8 local_apic_id; /* processor's local APIC id */ + u32 processor_enabled: 1; /* Processor is usable if set */ + u32 reserved1 : 32; + +} PROCESSOR_APIC; + + +typedef struct /* IO APIC */ +{ + APIC_HEADER header; + u8 io_apic_id; /* I/O APIC ID */ + u8 reserved; /* reserved - must be zero */ + u32 io_apic_address; /* APIC's physical address */ + u32 vector; /* interrupt vector index where INTI + * lines start */ +} IO_APIC; + + +/* +** IA64 TODO: Add SAPIC Tables +*/ + +/* +** IA64 TODO: Modify Smart Battery Description to comply with ACPI IA64 +** extensions. +*/ +typedef struct /* Smart Battery Description Table */ +{ + ACPI_TABLE_HEADER header; + u32 warning_level; + u32 low_level; + u32 critical_level; + +} SMART_BATTERY_DESCRIPTION_TABLE; + + +#pragma pack() + + +/* + * ACPI Table information. We save the table address, length, + * and type of memory allocation (mapped or allocated) for each + * table for 1) when we exit, and 2) if a new table is installed + */ + +#define ACPI_MEM_NOT_ALLOCATED 0 +#define ACPI_MEM_ALLOCATED 1 +#define ACPI_MEM_MAPPED 2 + +/* Definitions for the Flags bitfield member of ACPI_TABLE_SUPPORT */ + +#define ACPI_TABLE_SINGLE 0 +#define ACPI_TABLE_MULTIPLE 1 + + +/* Data about each known table type */ + +typedef struct _acpi_table_support +{ + NATIVE_CHAR *name; + NATIVE_CHAR *signature; + u8 sig_length; + u8 flags; + u16 status; + void **global_ptr; + +} ACPI_TABLE_SUPPORT; + +/* + * Get the architecture-specific tables + */ + +#include "actbl1.h" /* Acpi 1.0 table defintions */ +#include "actbl71.h" /* Acpi 0.71 IA-64 Extension table defintions */ +#include "actbl2.h" /* Acpi 2.0 table definitions */ + +#endif /* __ACTBL_H__ */ diff --git a/drivers/bus/acpi/include/actbl1.h b/drivers/bus/acpi/include/actbl1.h new file mode 100644 index 0000000..1968a4d --- /dev/null +++ b/drivers/bus/acpi/include/actbl1.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * + * Name: actbl1.h - ACPI 1.0 tables + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTBL1_H__ +#define __ACTBL1_H__ + +#pragma pack(1) + +/*************************************/ +/* ACPI Specification Rev 1.0 for */ +/* the Root System Description Table */ +/*************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* Table header */ + u32 table_offset_entry [1]; /* Array of pointers to other */ + /* ACPI tables */ +} RSDT_DESCRIPTOR_REV1; + + +/***************************************/ +/* ACPI Specification Rev 1.0 for */ +/* the Firmware ACPI Control Structure */ +/***************************************/ +typedef struct +{ + NATIVE_CHAR signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 firmware_waking_vector; /* ACPI OS waking vector */ + u32 global_lock; /* Global Lock */ + u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ + u32 reserved1 : 31; /* must be 0 */ + u8 resverved3 [40]; /* reserved - must be zero */ + +} FACS_DESCRIPTOR_REV1; + + +/************************************/ +/* ACPI Specification Rev 1.0 for */ +/* the Fixed ACPI Description Table */ +/************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* table header */ + u32 firmware_ctrl; /* Physical address of FACS */ + u32 dsdt; /* Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 reserved1; /* reserved */ + u16 sci_int; /* System vector of SCI interrupt */ + u32 smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ + u8 reserved2; /* reserved - must be zero */ + u32 pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ + u32 pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ + u32 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u32 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u32 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u32 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u32 gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ + u32 gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 reserved3; /* reserved */ + u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* Size of area read to flush caches */ + u16 flush_stride; /* Stride used in flushing caches */ + u8 duty_offset; /* bit location of duty cycle field in p_cnt reg */ + u8 duty_width; /* bit width of duty cycle field in p_cnt reg */ + u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* index to century in RTC CMOS RAM */ + u8 reserved4; /* reserved */ + u8 reserved4a; /* reserved */ + u8 reserved4b; /* reserved */ + u32 wb_invd : 1; /* wbinvd instruction works properly */ + u32 wb_invd_flush : 1; /* wbinvd flushes but does not invalidate */ + u32 proc_c1 : 1; /* all processors support C1 state */ + u32 plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ + u32 reserved5 : 23; /* reserved - must be zero */ + +} FADT_DESCRIPTOR_REV1; + +#pragma pack() + +#endif /* __ACTBL1_H__ */ + + diff --git a/drivers/bus/acpi/include/actbl2.h b/drivers/bus/acpi/include/actbl2.h new file mode 100644 index 0000000..5d9ae55 --- /dev/null +++ b/drivers/bus/acpi/include/actbl2.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * Name: actbl2.h - ACPI Specification Revision 2.0 Tables + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTBL2_H__ +#define __ACTBL2_H__ + +/**************************************/ +/* Prefered Power Management Profiles */ +/**************************************/ +#define PM_UNSPECIFIED 0 +#define PM_DESKTOP 1 +#define PM_MOBILE 2 +#define PM_WORKSTATION 3 +#define PM_ENTERPRISE_SERVER 4 +#define PM_SOHO_SERVER 5 +#define PM_APPLIANCE_PC 6 + +/*********************************************/ +/* ACPI Boot Arch Flags, See spec Table 5-10 */ +/*********************************************/ +#define BAF_LEGACY_DEVICES 0x0001 +#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 + +#define FADT2_REVISION_ID 3 + +#pragma pack(1) + +/*************************************/ +/* ACPI Specification Rev 2.0 for */ +/* the Root System Description Table */ +/*************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* Table header */ + u32 table_offset_entry [1]; /* Array of pointers to */ + /* other tables' headers */ +} RSDT_DESCRIPTOR_REV2; + + +/********************************************/ +/* ACPI Specification Rev 2.0 for the */ +/* Extended System Description Table (XSDT) */ +/********************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* Table header */ + UINT64 table_offset_entry [1]; /* Array of pointers to */ + /* other tables' headers */ +} XSDT_DESCRIPTOR_REV2; + +/***************************************/ +/* ACPI Specification Rev 2.0 for */ +/* the Firmware ACPI Control Structure */ +/***************************************/ +typedef struct +{ + NATIVE_CHAR signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 firmware_waking_vector; /* 32bit physical address of the Firmware Waking Vector. */ + u32 global_lock; /* Global Lock used to synchronize access to shared hardware resources */ + u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ + u32 reserved1 : 31; /* must be 0 */ + UINT64 Xfirmware_waking_vector; /* 64bit physical address of the Firmware Waking Vector. */ + u8 version; /* Version of this table */ + u8 reserved3 [31]; /* reserved - must be zero */ + +} FACS_DESCRIPTOR_REV2; + + +/***************************************/ +/* ACPI Specification Rev 2.0 for */ +/* the Generic Address Structure (GAS) */ +/***************************************/ +typedef struct +{ + u8 address_space_id; /* Address space where struct or register exists. */ + u8 register_bit_width; /* Size in bits of given register */ + u8 register_bit_offset; /* Bit offset within the register */ + u8 reserved; /* Must be 0 */ + UINT64 address; /* 64-bit address of struct or register */ + +} ACPI_GAS; + + +/************************************/ +/* ACPI Specification Rev 2.0 for */ +/* the Fixed ACPI Description Table */ +/************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* table header */ + u32 V1_firmware_ctrl; /* 32-bit physical address of FACS */ + u32 V1_dsdt; /* 32-bit physical address of DSDT */ + u8 reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ + u8 prefer_PM_profile; /* Conveys preferred power management profile to OSPM. */ + u16 sci_int; /* System vector of SCI interrupt */ + u32 smi_cmd; /* Port address of SMI command port */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ + u8 pstate_cnt; /* processor performance state control*/ + u32 V1_pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ + u32 V1_pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ + u32 V1_pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + u32 V1_pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + u32 V1_pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + u32 V1_pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + u32 V1_gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ + u32 V1_gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 cst_cnt; /* Support for the _CST object and C States change notification.*/ + u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + u16 flush_size; /* number of flush strides that need to be read */ + u16 flush_stride; /* Processor's memory cache line width, in bytes */ + u8 duty_offset; /* Processor_’s duty cycle index in processor's P_CNT reg*/ + u8 duty_width; /* Processor_’s duty cycle value bit width in P_CNT register.*/ + u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* index to century in RTC CMOS RAM */ + u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ + u8 reserved2; /* reserved */ + u32 wb_invd : 1; /* wbinvd instruction works properly */ + u32 wb_invd_flush : 1; /* wbinvd flushes but does not invalidate */ + u32 proc_c1 : 1; /* all processors support C1 state */ + u32 plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ + u32 dock_cap : 1; /* Supports Docking */ + u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/ + u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */ + u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/ + u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */ + /* must be executed after writing the SLP_TYPx register. */ + u32 reserved6 : 18; /* reserved - must be zero */ + + ACPI_GAS reset_register; /* Reset register address in GAS format */ + u8 reset_value; /* Value to write to the Reset_register port to reset the system. */ + u8 reserved7[3]; /* These three bytes must be zero */ + UINT64 Xfirmware_ctrl; /* 64-bit physical address of FACS */ + UINT64 Xdsdt; /* 64-bit physical address of DSDT */ + ACPI_GAS Xpm1a_evt_blk; /* Extended Power Mgt 1a Acpi_event Reg Blk address */ + ACPI_GAS Xpm1b_evt_blk; /* Extended Power Mgt 1b Acpi_event Reg Blk address */ + ACPI_GAS Xpm1a_cnt_blk; /* Extended Power Mgt 1a Control Reg Blk address */ + ACPI_GAS Xpm1b_cnt_blk; /* Extended Power Mgt 1b Control Reg Blk address */ + ACPI_GAS Xpm2_cnt_blk; /* Extended Power Mgt 2 Control Reg Blk address */ + ACPI_GAS Xpm_tmr_blk; /* Extended Power Mgt Timer Ctrl Reg Blk address */ + ACPI_GAS Xgpe0blk; /* Extended General Purpose Acpi_event 0 Reg Blk address */ + ACPI_GAS Xgpe1_blk; /* Extended General Purpose Acpi_event 1 Reg Blk address */ + +} FADT_DESCRIPTOR_REV2; + + +#pragma pack() + +#endif /* __ACTBL2_H__ */ + diff --git a/drivers/bus/acpi/include/actbl71.h b/drivers/bus/acpi/include/actbl71.h new file mode 100644 index 0000000..fe91ddb --- /dev/null +++ b/drivers/bus/acpi/include/actbl71.h @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * Name: actbl71.h - IA-64 Extensions to the ACPI Spec Rev. 0.71 + * This file includes tables specific to this + * specification revision. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTBL71_H__ +#define __ACTBL71_H__ + +/* 0.71 FADT Address_space data item bitmasks defines */ +/* If the associated bit is zero then it is in memory space else in io space */ +#define SMI_CMD_ADDRESS_SPACE 0x01 +#define PM1_BLK_ADDRESS_SPACE 0x02 +#define PM2_CNT_BLK_ADDRESS_SPACE 0x04 +#define PM_TMR_BLK_ADDRESS_SPACE 0x08 +#define GPE0_BLK_ADDRESS_SPACE 0x10 +#define GPE1_BLK_ADDRESS_SPACE 0x20 + +/* Only for clarity in declarations */ +typedef UINT64 IO_ADDRESS; + +#pragma pack(1) + +typedef struct /* Root System Descriptor Pointer */ +{ + NATIVE_CHAR signature [8]; /* contains "RSD PTR " */ + u8 checksum; /* to make sum of struct == 0 */ + NATIVE_CHAR oem_id [6]; /* OEM identification */ + u8 reserved; /* Must be 0 for 1.0, 2 for 2.0 */ + UINT64 rsdt_physical_address; /* 64-bit physical address of RSDT */ +} RSDP_DESCRIPTOR_REV071; + + +/*****************************************/ +/* IA64 Extensions to ACPI Spec Rev 0.71 */ +/* for the Root System Description Table */ +/*****************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* Table header */ + u32 reserved_pad; /* IA64 alignment, must be 0 */ + UINT64 table_offset_entry [1]; /* Array of pointers to other */ + /* tables' headers */ +} RSDT_DESCRIPTOR_REV071; + + +/*******************************************/ +/* IA64 Extensions to ACPI Spec Rev 0.71 */ +/* for the Firmware ACPI Control Structure */ +/*******************************************/ +typedef struct +{ + NATIVE_CHAR signature[4]; /* signature "FACS" */ + u32 length; /* length of structure, in bytes */ + u32 hardware_signature; /* hardware configuration signature */ + u32 reserved4; /* must be 0 */ + UINT64 firmware_waking_vector; /* ACPI OS waking vector */ + UINT64 global_lock; /* Global Lock */ + u32 S4_bios_f : 1; /* Indicates if S4_bIOS support is present */ + u32 reserved1 : 31; /* must be 0 */ + u8 reserved3 [28]; /* reserved - must be zero */ + +} FACS_DESCRIPTOR_REV071; + + +/******************************************/ +/* IA64 Extensions to ACPI Spec Rev 0.71 */ +/* for the Fixed ACPI Description Table */ +/******************************************/ +typedef struct +{ + ACPI_TABLE_HEADER header; /* table header */ + u32 reserved_pad; /* IA64 alignment, must be 0 */ + UINT64 firmware_ctrl; /* 64-bit Physical address of FACS */ + UINT64 dsdt; /* 64-bit Physical address of DSDT */ + u8 model; /* System Interrupt Model */ + u8 address_space; /* Address Space Bitmask */ + u16 sci_int; /* System vector of SCI interrupt */ + u8 acpi_enable; /* value to write to smi_cmd to enable ACPI */ + u8 acpi_disable; /* value to write to smi_cmd to disable ACPI */ + u8 S4_bios_req; /* Value to write to SMI CMD to enter S4_bIOS state */ + u8 reserved2; /* reserved - must be zero */ + UINT64 smi_cmd; /* Port address of SMI command port */ + UINT64 pm1a_evt_blk; /* Port address of Power Mgt 1a Acpi_event Reg Blk */ + UINT64 pm1b_evt_blk; /* Port address of Power Mgt 1b Acpi_event Reg Blk */ + UINT64 pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ + UINT64 pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ + UINT64 pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ + UINT64 pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ + UINT64 gpe0blk; /* Port addr of General Purpose Acpi_event 0 Reg Blk */ + UINT64 gpe1_blk; /* Port addr of General Purpose Acpi_event 1 Reg Blk */ + u8 pm1_evt_len; /* Byte Length of ports at pm1_x_evt_blk */ + u8 pm1_cnt_len; /* Byte Length of ports at pm1_x_cnt_blk */ + u8 pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ + u8 pm_tm_len; /* Byte Length of ports at pm_tm_blk */ + u8 gpe0blk_len; /* Byte Length of ports at gpe0_blk */ + u8 gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ + u8 gpe1_base; /* offset in gpe model where gpe1 events start */ + u8 reserved3; /* reserved */ + u16 plvl2_lat; /* worst case HW latency to enter/exit C2 state */ + u16 plvl3_lat; /* worst case HW latency to enter/exit C3 state */ + u8 day_alrm; /* index to day-of-month alarm in RTC CMOS RAM */ + u8 mon_alrm; /* index to month-of-year alarm in RTC CMOS RAM */ + u8 century; /* index to century in RTC CMOS RAM */ + u8 reserved4; /* reserved */ + u32 flush_cash : 1; /* PAL_FLUSH_CACHE is correctly supported */ + u32 reserved5 : 1; /* reserved - must be zero */ + u32 proc_c1 : 1; /* all processors support C1 state */ + u32 plvl2_up : 1; /* C2 state works on MP system */ + u32 pwr_button : 1; /* Power button is handled as a generic feature */ + u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ + u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ + u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ + u32 tmr_val_ext : 1; /* tmr_val is 32 bits */ + u32 dock_cap : 1; /* Supports Docking */ + u32 reserved6 : 22; /* reserved - must be zero */ + +} FADT_DESCRIPTOR_REV071; + +#pragma pack() + +#endif /* __ACTBL71_H__ */ + diff --git a/drivers/bus/acpi/include/actypes.h b/drivers/bus/acpi/include/actypes.h new file mode 100644 index 0000000..fbb49ef --- /dev/null +++ b/drivers/bus/acpi/include/actypes.h @@ -0,0 +1,1060 @@ +/****************************************************************************** + * + * Name: actypes.h - Common data types for the entire ACPI subsystem + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACTYPES_H__ +#define __ACTYPES_H__ + +/*! [Begin] no source code translation (keep the typedefs) */ + +/* + * Data types - Fixed across all compilation models + * + * BOOLEAN Logical Boolean. + * 1 byte value containing a 0 for FALSE or a 1 for TRUE. + * Other values are undefined. + * + * INT8 8-bit (1 byte) signed value + * UINT8 8-bit (1 byte) unsigned value + * INT16 16-bit (2 byte) signed value + * UINT16 16-bit (2 byte) unsigned value + * INT32 32-bit (4 byte) signed value + * UINT32 32-bit (4 byte) unsigned value + * INT64 64-bit (8 byte) signed value + * UINT64 64-bit (8 byte) unsigned value + * NATIVE_INT 32-bit on IA-32, 64-bit on IA-64 signed value + * NATIVE_UINT 32-bit on IA-32, 64-bit on IA-64 unsigned value + * UCHAR Character. 1 byte unsigned value. + */ + + +#ifdef _IA64 +/* + * 64-bit type definitions + */ +typedef unsigned char UINT8; +typedef unsigned char BOOLEAN; +typedef unsigned char UCHAR; +typedef unsigned short UINT16; +typedef int INT32; +typedef unsigned int UINT32; +typedef COMPILER_DEPENDENT_UINT64 UINT64; + +typedef UINT64 NATIVE_UINT; +typedef INT64 NATIVE_INT; + +typedef NATIVE_UINT ACPI_TBLPTR; +typedef UINT64 ACPI_IO_ADDRESS; +typedef UINT64 ACPI_PHYSICAL_ADDRESS; + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000008 + +/* (No hardware alignment support in IA64) */ + + +#elif _IA16 +/* + * 16-bit type definitions + */ +typedef unsigned char UINT8; +typedef unsigned char BOOLEAN; +typedef unsigned char UCHAR; +typedef unsigned int UINT16; +typedef long INT32; +typedef int INT16; +typedef unsigned long UINT32; + +typedef struct +{ + UINT32 Lo; + UINT32 Hi; + +} UINT64; + +typedef UINT16 NATIVE_UINT; +typedef INT16 NATIVE_INT; + +typedef UINT32 ACPI_TBLPTR; +typedef UINT32 ACPI_IO_ADDRESS; +typedef char *ACPI_PHYSICAL_ADDRESS; + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000002 +#define _HW_ALIGNMENT_SUPPORT + +/* + * (16-bit only) internal integers must be 32-bits, so + * 64-bit integers cannot be supported + */ +#define ACPI_NO_INTEGER64_SUPPORT + + +#else +/* + * 32-bit type definitions (default) + */ +typedef unsigned char UINT8; +typedef unsigned char BOOLEAN; +typedef unsigned char UCHAR; +typedef unsigned short UINT16; +typedef int INT32; +typedef unsigned int UINT32; +typedef COMPILER_DEPENDENT_UINT64 UINT64; + +typedef UINT32 NATIVE_UINT; +typedef INT32 NATIVE_INT; + +typedef NATIVE_UINT ACPI_TBLPTR; +typedef UINT32 ACPI_IO_ADDRESS; +typedef UINT64 ACPI_PHYSICAL_ADDRESS; + +#define ALIGNED_ADDRESS_BOUNDARY 0x00000004 +#define _HW_ALIGNMENT_SUPPORT +#endif + + + +/* + * Miscellaneous common types + */ + +typedef UINT32 UINT32_BIT; +typedef NATIVE_UINT ACPI_PTRDIFF; +typedef char NATIVE_CHAR; + + +/* + * Data type ranges + */ + +#define ACPI_UINT8_MAX (UINT8) 0xFF +#define ACPI_UINT16_MAX (UINT16) 0xFFFF +#define ACPI_UINT32_MAX (UINT32) 0xFFFFFFFF +#define ACPI_UINT64_MAX (UINT64) 0xFFFFFFFFFFFFFFFF + + +#ifdef DEFINE_ALTERNATE_TYPES +/* + * Types used only in translated source + */ +typedef INT32 s32; +typedef UINT8 u8; +typedef UINT16 u16; +typedef UINT32 u32; +typedef UINT64 u64; +#endif +/*! [End] no source code translation !*/ + + +/* + * Useful defines + */ + +#ifdef FALSE +#undef FALSE +#endif +#define FALSE (1 == 0) + +#ifdef TRUE +#undef TRUE +#endif +#define TRUE (1 == 1) + +#ifndef NULL +#define NULL (void *) 0 +#endif + + +/* + * Local datatypes + */ + +typedef u32 ACPI_STATUS; /* All ACPI Exceptions */ +typedef u32 ACPI_NAME; /* 4-s8 ACPI name */ +typedef char* ACPI_STRING; /* Null terminated ASCII string */ +typedef void* ACPI_HANDLE; /* Actually a ptr to an Node */ + + +/* + * Acpi integer width. In ACPI version 1, integers are + * 32 bits. In ACPI version 2, integers are 64 bits. + * Note that this pertains to the ACPI integer type only, not + * other integers used in the implementation of the ACPI CA + * subsystem. + */ +#ifdef ACPI_NO_INTEGER64_SUPPORT + +/* 32-bit integers only, no 64-bit support */ + +typedef u32 ACPI_INTEGER; +#define ACPI_INTEGER_MAX ACPI_UINT32_MAX +#define ACPI_INTEGER_BIT_SIZE 32 +#define ACPI_MAX_BCD_VALUE 99999999 +#define ACPI_MAX_BCD_DIGITS 8 + +#else + +/* 64-bit integers */ + +typedef UINT64 ACPI_INTEGER; +#define ACPI_INTEGER_MAX ACPI_UINT64_MAX +#define ACPI_INTEGER_BIT_SIZE 64 +#define ACPI_MAX_BCD_VALUE 9999999999999999 +#define ACPI_MAX_BCD_DIGITS 16 + +#endif + + +/* + * Constants with special meanings + */ + +#define ACPI_ROOT_OBJECT (ACPI_HANDLE)(-1) + +#define ACPI_FULL_INITIALIZATION 0x00 +#define ACPI_NO_ADDRESS_SPACE_INIT 0x01 +#define ACPI_NO_HARDWARE_INIT 0x02 +#define ACPI_NO_EVENT_INIT 0x04 +#define ACPI_NO_ACPI_ENABLE 0x08 +#define ACPI_NO_DEVICE_INIT 0x10 +#define ACPI_NO_OBJECT_INIT 0x20 + + +/* + * System states + */ +#define ACPI_STATE_S0 (u8) 0 +#define ACPI_STATE_S1 (u8) 1 +#define ACPI_STATE_S2 (u8) 2 +#define ACPI_STATE_S3 (u8) 3 +#define ACPI_STATE_S4 (u8) 4 +#define ACPI_STATE_S5 (u8) 5 +/* let's pretend S4_bIOS didn't exist for now. ASG */ +#define ACPI_STATE_S4_bIOS (u8) 6 +#define ACPI_S_STATES_MAX ACPI_STATE_S5 +#define ACPI_S_STATE_COUNT 6 + +/* + * Device power states + */ +#define ACPI_STATE_D0 (u8) 0 +#define ACPI_STATE_D1 (u8) 1 +#define ACPI_STATE_D2 (u8) 2 +#define ACPI_STATE_D3 (u8) 3 +#define ACPI_D_STATES_MAX ACPI_STATE_D3 +#define ACPI_D_STATE_COUNT 4 + +#define ACPI_STATE_UNKNOWN (u8) 0xFF + + +/* + * Table types. These values are passed to the table related APIs + */ + +typedef u32 ACPI_TABLE_TYPE; + +#define ACPI_TABLE_RSDP (ACPI_TABLE_TYPE) 0 +#define ACPI_TABLE_DSDT (ACPI_TABLE_TYPE) 1 +#define ACPI_TABLE_FADT (ACPI_TABLE_TYPE) 2 +#define ACPI_TABLE_FACS (ACPI_TABLE_TYPE) 3 +#define ACPI_TABLE_PSDT (ACPI_TABLE_TYPE) 4 +#define ACPI_TABLE_SSDT (ACPI_TABLE_TYPE) 5 +#define ACPI_TABLE_XSDT (ACPI_TABLE_TYPE) 6 +#define ACPI_TABLE_MAX 6 +#define NUM_ACPI_TABLES (ACPI_TABLE_MAX+1) + + +/* + * Types associated with names. The first group of + * values correspond to the definition of the ACPI + * Object_type operator (See the ACPI Spec). Therefore, + * only add to the first group if the spec changes! + * + * Types must be kept in sync with the Acpi_ns_properties + * and Acpi_ns_type_names arrays + */ + +typedef u32 ACPI_OBJECT_TYPE; +typedef u8 OBJECT_TYPE_INTERNAL; + +#define ACPI_BTYPE_ANY 0x00000000 +#define ACPI_BTYPE_INTEGER 0x00000001 +#define ACPI_BTYPE_STRING 0x00000002 +#define ACPI_BTYPE_BUFFER 0x00000004 +#define ACPI_BTYPE_PACKAGE 0x00000008 +#define ACPI_BTYPE_FIELD_UNIT 0x00000010 +#define ACPI_BTYPE_DEVICE 0x00000020 +#define ACPI_BTYPE_EVENT 0x00000040 +#define ACPI_BTYPE_METHOD 0x00000080 +#define ACPI_BTYPE_MUTEX 0x00000100 +#define ACPI_BTYPE_REGION 0x00000200 +#define ACPI_BTYPE_POWER 0x00000400 +#define ACPI_BTYPE_PROCESSOR 0x00000800 +#define ACPI_BTYPE_THERMAL 0x00001000 +#define ACPI_BTYPE_BUFFER_FIELD 0x00002000 +#define ACPI_BTYPE_DDB_HANDLE 0x00004000 +#define ACPI_BTYPE_DEBUG_OBJECT 0x00008000 +#define ACPI_BTYPE_REFERENCE 0x00010000 +#define ACPI_BTYPE_RESOURCE 0x00020000 + +#define ACPI_BTYPE_COMPUTE_DATA (ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER) + +#define ACPI_BTYPE_DATA (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_PACKAGE) +#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE) +#define ACPI_BTYPE_DEVICE_OBJECTS (ACPI_BTYPE_DEVICE | ACPI_BTYPE_THERMAL | ACPI_BTYPE_PROCESSOR) +#define ACPI_BTYPE_OBJECTS_AND_REFS 0x00017FFF /* ARG or LOCAL */ +#define ACPI_BTYPE_ALL_OBJECTS 0x00007FFF + + +#define ACPI_TYPE_ANY 0 /* 0x00 */ +#define ACPI_TYPE_INTEGER 1 /* 0x01 Byte/Word/Dword/Zero/One/Ones */ +#define ACPI_TYPE_STRING 2 /* 0x02 */ +#define ACPI_TYPE_BUFFER 3 /* 0x03 */ +#define ACPI_TYPE_PACKAGE 4 /* 0x04 Byte_const, multiple Data_term/Constant/Super_name */ +#define ACPI_TYPE_FIELD_UNIT 5 /* 0x05 */ +#define ACPI_TYPE_DEVICE 6 /* 0x06 Name, multiple Node */ +#define ACPI_TYPE_EVENT 7 /* 0x07 */ +#define ACPI_TYPE_METHOD 8 /* 0x08 Name, Byte_const, multiple Code */ +#define ACPI_TYPE_MUTEX 9 /* 0x09 */ +#define ACPI_TYPE_REGION 10 /* 0x0A */ +#define ACPI_TYPE_POWER 11 /* 0x0B Name,Byte_const,Word_const,multi Node */ +#define ACPI_TYPE_PROCESSOR 12 /* 0x0C Name,Byte_const,DWord_const,Byte_const,multi Nm_o */ +#define ACPI_TYPE_THERMAL 13 /* 0x0D Name, multiple Node */ +#define ACPI_TYPE_BUFFER_FIELD 14 /* 0x0E */ +#define ACPI_TYPE_DDB_HANDLE 15 /* 0x0F */ +#define ACPI_TYPE_DEBUG_OBJECT 16 /* 0x10 */ + +#define ACPI_TYPE_MAX 16 + +/* + * This section contains object types that do not relate to the ACPI Object_type operator. + * They are used for various internal purposes only. If new predefined ACPI_TYPEs are + * added (via the ACPI specification), these internal types must move upwards. + * Also, values exceeding the largest official ACPI Object_type must not overlap with + * defined AML opcodes. + */ +#define INTERNAL_TYPE_BEGIN 17 + +#define INTERNAL_TYPE_DEF_FIELD 17 /* 0x11 */ +#define INTERNAL_TYPE_BANK_FIELD 18 /* 0x12 */ +#define INTERNAL_TYPE_INDEX_FIELD 19 /* 0x13 */ +#define INTERNAL_TYPE_REFERENCE 20 /* 0x14 Arg#, Local#, Name, Debug; used only in descriptors */ +#define INTERNAL_TYPE_ALIAS 21 /* 0x15 */ +#define INTERNAL_TYPE_NOTIFY 22 /* 0x16 */ +#define INTERNAL_TYPE_ADDRESS_HANDLER 23 /* 0x17 */ +#define INTERNAL_TYPE_RESOURCE 24 /* 0x18 */ + + +#define INTERNAL_TYPE_NODE_MAX 24 + +/* These are pseudo-types because there are never any namespace nodes with these types */ + +#define INTERNAL_TYPE_DEF_FIELD_DEFN 25 /* 0x19 Name, Byte_const, multiple Field_element */ +#define INTERNAL_TYPE_BANK_FIELD_DEFN 26 /* 0x1A 2 Name,DWord_const,Byte_const,multi Field_element */ +#define INTERNAL_TYPE_INDEX_FIELD_DEFN 27 /* 0x1B 2 Name, Byte_const, multiple Field_element */ +#define INTERNAL_TYPE_IF 28 /* 0x1C */ +#define INTERNAL_TYPE_ELSE 29 /* 0x1D */ +#define INTERNAL_TYPE_WHILE 30 /* 0x1E */ +#define INTERNAL_TYPE_SCOPE 31 /* 0x1F Name, multiple Node */ +#define INTERNAL_TYPE_DEF_ANY 32 /* 0x20 type is Any, suppress search of enclosing scopes */ +#define INTERNAL_TYPE_EXTRA 33 /* 0x21 */ + +#define INTERNAL_TYPE_MAX 33 + +#define INTERNAL_TYPE_INVALID 34 +#define ACPI_TYPE_NOT_FOUND 0xFF + +/* + * Acpi_event Types: + * ------------ + * Fixed & general purpose... + */ + +typedef u32 ACPI_EVENT_TYPE; + +#define ACPI_EVENT_FIXED (ACPI_EVENT_TYPE) 0 +#define ACPI_EVENT_GPE (ACPI_EVENT_TYPE) 1 + +/* + * Fixed events + */ + +#define ACPI_EVENT_PMTIMER (ACPI_EVENT_TYPE) 0 + /* + * There's no bus master event so index 1 is used for IRQ's that are not + * handled by the SCI handler + */ +#define ACPI_EVENT_NOT_USED (ACPI_EVENT_TYPE) 1 +#define ACPI_EVENT_GLOBAL (ACPI_EVENT_TYPE) 2 +#define ACPI_EVENT_POWER_BUTTON (ACPI_EVENT_TYPE) 3 +#define ACPI_EVENT_SLEEP_BUTTON (ACPI_EVENT_TYPE) 4 +#define ACPI_EVENT_RTC (ACPI_EVENT_TYPE) 5 +#define ACPI_EVENT_GENERAL (ACPI_EVENT_TYPE) 6 +#define ACPI_EVENT_MAX 6 +#define NUM_FIXED_EVENTS (ACPI_EVENT_TYPE) 7 + +#define ACPI_GPE_INVALID 0xFF +#define ACPI_GPE_MAX 0xFF +#define NUM_GPE 256 + +#define ACPI_EVENT_LEVEL_TRIGGERED (ACPI_EVENT_TYPE) 1 +#define ACPI_EVENT_EDGE_TRIGGERED (ACPI_EVENT_TYPE) 2 + +/* + * Acpi_event Status: + * ------------- + * The encoding of ACPI_EVENT_STATUS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the event is enabled). + * +---------------+-+-+ + * | Bits 31:2 |1|0| + * +---------------+-+-+ + * | | | + * | | +- Enabled? + * | +--- Set? + * +----------- + */ +typedef u32 ACPI_EVENT_STATUS; + +#define ACPI_EVENT_FLAG_DISABLED (ACPI_EVENT_STATUS) 0x00 +#define ACPI_EVENT_FLAG_ENABLED (ACPI_EVENT_STATUS) 0x01 +#define ACPI_EVENT_FLAG_SET (ACPI_EVENT_STATUS) 0x02 + + +/* Notify types */ + +#define ACPI_SYSTEM_NOTIFY 0 +#define ACPI_DEVICE_NOTIFY 1 +#define ACPI_MAX_NOTIFY_HANDLER_TYPE 1 + +#define MAX_SYS_NOTIFY 0x7f + + +/* Address Space (Operation Region) Types */ + +typedef u8 ACPI_ADDRESS_SPACE_TYPE; + +#define ADDRESS_SPACE_SYSTEM_MEMORY (ACPI_ADDRESS_SPACE_TYPE) 0 +#define ADDRESS_SPACE_SYSTEM_IO (ACPI_ADDRESS_SPACE_TYPE) 1 +#define ADDRESS_SPACE_PCI_CONFIG (ACPI_ADDRESS_SPACE_TYPE) 2 +#define ADDRESS_SPACE_EC (ACPI_ADDRESS_SPACE_TYPE) 3 +#define ADDRESS_SPACE_SMBUS (ACPI_ADDRESS_SPACE_TYPE) 4 +#define ADDRESS_SPACE_CMOS (ACPI_ADDRESS_SPACE_TYPE) 5 +#define ADDRESS_SPACE_PCI_BAR_TARGET (ACPI_ADDRESS_SPACE_TYPE) 6 + + +/* + * External ACPI object definition + */ + +typedef union acpi_obj +{ + ACPI_OBJECT_TYPE type; /* See definition of Acpi_ns_type for values */ + struct + { + ACPI_OBJECT_TYPE type; + ACPI_INTEGER value; /* The actual number */ + } integer; + + struct + { + ACPI_OBJECT_TYPE type; + u32 length; /* # of bytes in string, excluding trailing null */ + NATIVE_CHAR *pointer; /* points to the string value */ + } string; + + struct + { + ACPI_OBJECT_TYPE type; + u32 length; /* # of bytes in buffer */ + u8 *pointer; /* points to the buffer */ + } buffer; + + struct + { + ACPI_OBJECT_TYPE type; + u32 fill1; + ACPI_HANDLE handle; /* object reference */ + } reference; + + struct + { + ACPI_OBJECT_TYPE type; + u32 count; /* # of elements in package */ + union acpi_obj *elements; /* Pointer to an array of ACPI_OBJECTs */ + } package; + + struct + { + ACPI_OBJECT_TYPE type; + u32 proc_id; + ACPI_IO_ADDRESS pblk_address; + u32 pblk_length; + } processor; + + struct + { + ACPI_OBJECT_TYPE type; + u32 system_level; + u32 resource_order; + } power_resource; + +} ACPI_OBJECT, *PACPI_OBJECT; + + +/* + * List of objects, used as a parameter list for control method evaluation + */ + +typedef struct acpi_obj_list +{ + u32 count; + ACPI_OBJECT *pointer; + +} ACPI_OBJECT_LIST, *PACPI_OBJECT_LIST; + + +/* + * Miscellaneous common Data Structures used by the interfaces + */ + +typedef struct +{ + u32 length; /* Length in bytes of the buffer */ + void *pointer; /* pointer to buffer */ + +} ACPI_BUFFER; + + +/* + * Name_type for Acpi_get_name + */ + +#define ACPI_FULL_PATHNAME 0 +#define ACPI_SINGLE_NAME 1 +#define ACPI_NAME_TYPE_MAX 1 + + +/* + * Structure and flags for Acpi_get_system_info + */ + +#define SYS_MODE_UNKNOWN 0x0000 +#define SYS_MODE_ACPI 0x0001 +#define SYS_MODE_LEGACY 0x0002 +#define SYS_MODES_MASK 0x0003 + +/* + * ACPI CPU Cx state handler + */ +typedef +ACPI_STATUS (*ACPI_SET_C_STATE_HANDLER) ( + NATIVE_UINT pblk_address); + +/* + * ACPI Cx State info + */ +typedef struct +{ + u32 state_number; + u32 latency; +} ACPI_CX_STATE; + +/* + * ACPI CPU throttling info + */ +typedef struct +{ + u32 state_number; + u32 percent_of_clock; +} ACPI_CPU_THROTTLING_STATE; + +/* + * ACPI Table Info. One per ACPI table _type_ + */ +typedef struct acpi_table_info +{ + u32 count; + +} ACPI_TABLE_INFO; + + +/* + * System info returned by Acpi_get_system_info() + */ + +typedef struct _acpi_sys_info +{ + u32 acpi_ca_version; + u32 flags; + u32 timer_resolution; + u32 reserved1; + u32 reserved2; + u32 debug_level; + u32 debug_layer; + u32 num_table_types; + ACPI_TABLE_INFO table_info [NUM_ACPI_TABLES]; + +} ACPI_SYSTEM_INFO; + + +/* + * System Initiailization data. This data is passed to ACPIInitialize + * copyied to global data and retained by ACPI CA + */ + +typedef struct _acpi_init_data +{ + void *RSDP_physical_address; /* Address of RSDP, needed it it is */ + /* not found in the IA32 manner */ +} ACPI_INIT_DATA; + +/* + * Various handlers and callback procedures + */ + +typedef +u32 (*FIXED_EVENT_HANDLER) ( + void *context); + +typedef +void (*GPE_HANDLER) ( + void *context); + +typedef +void (*NOTIFY_HANDLER) ( + ACPI_HANDLE device, + u32 value, + void *context); + +#define ADDRESS_SPACE_READ 1 +#define ADDRESS_SPACE_WRITE 2 + +typedef +ACPI_STATUS (*ADDRESS_SPACE_HANDLER) ( + u32 function, + ACPI_PHYSICAL_ADDRESS address, + u32 bit_width, + u32 *value, + void *handler_context, + void *region_context); + +#define ACPI_DEFAULT_HANDLER ((ADDRESS_SPACE_HANDLER) NULL) + + +typedef +ACPI_STATUS (*ADDRESS_SPACE_SETUP) ( + ACPI_HANDLE region_handle, + u32 function, + void *handler_context, + void **region_context); + +#define ACPI_REGION_ACTIVATE 0 +#define ACPI_REGION_DEACTIVATE 1 + +typedef +ACPI_STATUS (*WALK_CALLBACK) ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value); + + +/* Interrupt handler return values */ + +#define INTERRUPT_NOT_HANDLED 0x00 +#define INTERRUPT_HANDLED 0x01 + + +/* Structure and flags for Acpi_get_device_info */ + +#define ACPI_VALID_HID 0x1 +#define ACPI_VALID_UID 0x2 +#define ACPI_VALID_ADR 0x4 +#define ACPI_VALID_STA 0x8 + + +#define ACPI_COMMON_OBJ_INFO \ + ACPI_OBJECT_TYPE type; /* ACPI object type */ \ + ACPI_NAME name /* ACPI object Name */ + + +typedef struct +{ + ACPI_COMMON_OBJ_INFO; +} ACPI_OBJ_INFO_HEADER; + + +typedef struct +{ + ACPI_COMMON_OBJ_INFO; + + u32 valid; /* Are the next bits legit? */ + NATIVE_CHAR hardware_id [9]; /* _HID value if any */ + NATIVE_CHAR unique_id[9]; /* _UID value if any */ + ACPI_INTEGER address; /* _ADR value if any */ + u32 current_status; /* _STA value */ +} ACPI_DEVICE_INFO; + + +/* Context structs for address space handlers */ + +typedef struct +{ + u32 seg; + u32 bus; + u32 dev_func; +} PCI_HANDLER_CONTEXT; + + +typedef struct +{ + ACPI_PHYSICAL_ADDRESS mapped_physical_address; + u8 *mapped_logical_address; + u32 mapped_length; +} MEM_HANDLER_CONTEXT; + + +/* + * C-state handler + */ + +typedef ACPI_STATUS (*ACPI_C_STATE_HANDLER) (ACPI_IO_ADDRESS, u32*); + + +/* + * Definitions for Resource Attributes + */ + +/* + * Memory Attributes + */ +#define READ_ONLY_MEMORY (u8) 0x00 +#define READ_WRITE_MEMORY (u8) 0x01 + +#define NON_CACHEABLE_MEMORY (u8) 0x00 +#define CACHABLE_MEMORY (u8) 0x01 +#define WRITE_COMBINING_MEMORY (u8) 0x02 +#define PREFETCHABLE_MEMORY (u8) 0x03 + +/* + * IO Attributes + * The ISA IO ranges are: n000-n0FFh, n400-n4_fFh, n800-n8_fFh, n_c00-n_cFFh. + * The non-ISA IO ranges are: n100-n3_fFh, n500-n7_fFh, n900-n_bFFh, n_cD0-n_fFFh. + */ +#define NON_ISA_ONLY_RANGES (u8) 0x01 +#define ISA_ONLY_RANGES (u8) 0x02 +#define ENTIRE_RANGE (NON_ISA_ONLY_RANGES | ISA_ONLY_RANGES) + +/* + * IO Port Descriptor Decode + */ +#define DECODE_10 (u8) 0x00 /* 10-bit IO address decode */ +#define DECODE_16 (u8) 0x01 /* 16-bit IO address decode */ + +/* + * IRQ Attributes + */ +#define EDGE_SENSITIVE (u8) 0x00 +#define LEVEL_SENSITIVE (u8) 0x01 + +#define ACTIVE_HIGH (u8) 0x00 +#define ACTIVE_LOW (u8) 0x01 + +#define EXCLUSIVE (u8) 0x00 +#define SHARED (u8) 0x01 + +/* + * DMA Attributes + */ +#define COMPATIBILITY (u8) 0x00 +#define TYPE_A (u8) 0x01 +#define TYPE_B (u8) 0x02 +#define TYPE_F (u8) 0x03 + +#define NOT_BUS_MASTER (u8) 0x00 +#define BUS_MASTER (u8) 0x01 + +#define TRANSFER_8 (u8) 0x00 +#define TRANSFER_8_16 (u8) 0x01 +#define TRANSFER_16 (u8) 0x02 + +/* + * Start Dependent Functions Priority definitions + */ +#define GOOD_CONFIGURATION (u8) 0x00 +#define ACCEPTABLE_CONFIGURATION (u8) 0x01 +#define SUB_OPTIMAL_CONFIGURATION (u8) 0x02 + +/* + * 16, 32 and 64-bit Address Descriptor resource types + */ +#define MEMORY_RANGE (u8) 0x00 +#define IO_RANGE (u8) 0x01 +#define BUS_NUMBER_RANGE (u8) 0x02 + +#define ADDRESS_NOT_FIXED (u8) 0x00 +#define ADDRESS_FIXED (u8) 0x01 + +#define POS_DECODE (u8) 0x00 +#define SUB_DECODE (u8) 0x01 + +#define PRODUCER (u8) 0x00 +#define CONSUMER (u8) 0x01 + + +/* + * Structures used to describe device resources + */ +typedef struct +{ + u32 edge_level; + u32 active_high_low; + u32 shared_exclusive; + u32 number_of_interrupts; + u32 interrupts[1]; + +} IRQ_RESOURCE; + +typedef struct +{ + u32 type; + u32 bus_master; + u32 transfer; + u32 number_of_channels; + u32 channels[1]; + +} DMA_RESOURCE; + +typedef struct +{ + u32 compatibility_priority; + u32 performance_robustness; + +} START_DEPENDENT_FUNCTIONS_RESOURCE; + +/* + * END_DEPENDENT_FUNCTIONS_RESOURCE struct is not + * needed because it has no fields + */ + +typedef struct +{ + u32 io_decode; + u32 min_base_address; + u32 max_base_address; + u32 alignment; + u32 range_length; + +} IO_RESOURCE; + +typedef struct +{ + u32 base_address; + u32 range_length; + +} FIXED_IO_RESOURCE; + +typedef struct +{ + u32 length; + u8 reserved[1]; + +} VENDOR_RESOURCE; + +typedef struct +{ + u32 read_write_attribute; + u32 min_base_address; + u32 max_base_address; + u32 alignment; + u32 range_length; + +} MEMORY24_RESOURCE; + +typedef struct +{ + u32 read_write_attribute; + u32 min_base_address; + u32 max_base_address; + u32 alignment; + u32 range_length; + +} MEMORY32_RESOURCE; + +typedef struct +{ + u32 read_write_attribute; + u32 range_base_address; + u32 range_length; + +} FIXED_MEMORY32_RESOURCE; + +typedef struct +{ + u16 cache_attribute; + u16 read_write_attribute; + +} MEMORY_ATTRIBUTE; + +typedef struct +{ + u16 range_attribute; + u16 reserved; + +} IO_ATTRIBUTE; + +typedef struct +{ + u16 reserved1; + u16 reserved2; + +} BUS_ATTRIBUTE; + +typedef union +{ + MEMORY_ATTRIBUTE memory; + IO_ATTRIBUTE io; + BUS_ATTRIBUTE bus; + +} ATTRIBUTE_DATA; + +typedef struct +{ + u32 resource_type; + u32 producer_consumer; + u32 decode; + u32 min_address_fixed; + u32 max_address_fixed; + ATTRIBUTE_DATA attribute; + u32 granularity; + u32 min_address_range; + u32 max_address_range; + u32 address_translation_offset; + u32 address_length; + u32 resource_source_index; + u32 resource_source_string_length; + NATIVE_CHAR resource_source[1]; + +} ADDRESS16_RESOURCE; + +typedef struct +{ + u32 resource_type; + u32 producer_consumer; + u32 decode; + u32 min_address_fixed; + u32 max_address_fixed; + ATTRIBUTE_DATA attribute; + u32 granularity; + u32 min_address_range; + u32 max_address_range; + u32 address_translation_offset; + u32 address_length; + u32 resource_source_index; + u32 resource_source_string_length; + NATIVE_CHAR resource_source[1]; + +} ADDRESS32_RESOURCE; + +typedef struct +{ + u32 producer_consumer; + u32 edge_level; + u32 active_high_low; + u32 shared_exclusive; + u32 number_of_interrupts; + u32 interrupts[1]; + u32 resource_source_index; + u32 resource_source_string_length; + NATIVE_CHAR resource_source[1]; + +} EXTENDED_IRQ_RESOURCE; + +typedef enum +{ + irq, + dma, + start_dependent_functions, + end_dependent_functions, + io, + fixed_io, + vendor_specific, + end_tag, + memory24, + memory32, + fixed_memory32, + address16, + address32, + extended_irq +} RESOURCE_TYPE; + +typedef union +{ + IRQ_RESOURCE irq; + DMA_RESOURCE dma; + START_DEPENDENT_FUNCTIONS_RESOURCE start_dependent_functions; + IO_RESOURCE io; + FIXED_IO_RESOURCE fixed_io; + VENDOR_RESOURCE vendor_specific; + MEMORY24_RESOURCE memory24; + MEMORY32_RESOURCE memory32; + FIXED_MEMORY32_RESOURCE fixed_memory32; + ADDRESS16_RESOURCE address16; + ADDRESS32_RESOURCE address32; + EXTENDED_IRQ_RESOURCE extended_irq; +} RESOURCE_DATA; + +typedef struct _resource_tag +{ + RESOURCE_TYPE id; + u32 length; + RESOURCE_DATA data; +} RESOURCE; + +#define RESOURCE_LENGTH 12 +#define RESOURCE_LENGTH_NO_DATA 8 + +#define NEXT_RESOURCE(res) (RESOURCE*)((u8*) res + res->length) + +/* + * END: Definitions for Resource Attributes + */ + + +typedef struct pci_routing_table +{ + u32 length; + u32 pin; + ACPI_INTEGER address; /* here for 64-bit alignment */ + u32 source_index; + NATIVE_CHAR source[4]; /* pad to 64 bits so sizeof() works in all cases */ + +} PCI_ROUTING_TABLE; + + +/* + * END: Definitions for PCI Routing tables + */ + +#endif /* __ACTYPES_H__ */ diff --git a/drivers/bus/acpi/include/amlcode.h b/drivers/bus/acpi/include/amlcode.h new file mode 100644 index 0000000..a1c3b23 --- /dev/null +++ b/drivers/bus/acpi/include/amlcode.h @@ -0,0 +1,420 @@ +/****************************************************************************** + * + * Name: amlcode.h - Definitions for AML, as included in "definition blocks" + * Declarations and definitions contained herein are derived + * directly from the ACPI specification. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __AMLCODE_H__ +#define __AMLCODE_H__ + + +/* primary opcodes */ + +#define AML_NULL_CHAR (u16) 0x00 + +#define AML_ZERO_OP (u16) 0x00 +#define AML_ONE_OP (u16) 0x01 +#define AML_UNASSIGNED (u16) 0x02 +#define AML_ALIAS_OP (u16) 0x06 +#define AML_NAME_OP (u16) 0x08 +#define AML_BYTE_OP (u16) 0x0a +#define AML_WORD_OP (u16) 0x0b +#define AML_DWORD_OP (u16) 0x0c +#define AML_STRING_OP (u16) 0x0d +#define AML_QWORD_OP (u16) 0x0e /* ACPI 2.0 */ +#define AML_SCOPE_OP (u16) 0x10 +#define AML_BUFFER_OP (u16) 0x11 +#define AML_PACKAGE_OP (u16) 0x12 +#define AML_VAR_PACKAGE_OP (u16) 0x13 /* ACPI 2.0 */ +#define AML_METHOD_OP (u16) 0x14 +#define AML_DUAL_NAME_PREFIX (u16) 0x2e +#define AML_MULTI_NAME_PREFIX_OP (u16) 0x2f +#define AML_NAME_CHAR_SUBSEQ (u16) 0x30 +#define AML_NAME_CHAR_FIRST (u16) 0x41 +#define AML_OP_PREFIX (u16) 0x5b +#define AML_ROOT_PREFIX (u16) 0x5c +#define AML_PARENT_PREFIX (u16) 0x5e +#define AML_LOCAL_OP (u16) 0x60 +#define AML_LOCAL0 (u16) 0x60 +#define AML_LOCAL1 (u16) 0x61 +#define AML_LOCAL2 (u16) 0x62 +#define AML_LOCAL3 (u16) 0x63 +#define AML_LOCAL4 (u16) 0x64 +#define AML_LOCAL5 (u16) 0x65 +#define AML_LOCAL6 (u16) 0x66 +#define AML_LOCAL7 (u16) 0x67 +#define AML_ARG_OP (u16) 0x68 +#define AML_ARG0 (u16) 0x68 +#define AML_ARG1 (u16) 0x69 +#define AML_ARG2 (u16) 0x6a +#define AML_ARG3 (u16) 0x6b +#define AML_ARG4 (u16) 0x6c +#define AML_ARG5 (u16) 0x6d +#define AML_ARG6 (u16) 0x6e +#define AML_STORE_OP (u16) 0x70 +#define AML_REF_OF_OP (u16) 0x71 +#define AML_ADD_OP (u16) 0x72 +#define AML_CONCAT_OP (u16) 0x73 +#define AML_SUBTRACT_OP (u16) 0x74 +#define AML_INCREMENT_OP (u16) 0x75 +#define AML_DECREMENT_OP (u16) 0x76 +#define AML_MULTIPLY_OP (u16) 0x77 +#define AML_DIVIDE_OP (u16) 0x78 +#define AML_SHIFT_LEFT_OP (u16) 0x79 +#define AML_SHIFT_RIGHT_OP (u16) 0x7a +#define AML_BIT_AND_OP (u16) 0x7b +#define AML_BIT_NAND_OP (u16) 0x7c +#define AML_BIT_OR_OP (u16) 0x7d +#define AML_BIT_NOR_OP (u16) 0x7e +#define AML_BIT_XOR_OP (u16) 0x7f +#define AML_BIT_NOT_OP (u16) 0x80 +#define AML_FIND_SET_LEFT_BIT_OP (u16) 0x81 +#define AML_FIND_SET_RIGHT_BIT_OP (u16) 0x82 +#define AML_DEREF_OF_OP (u16) 0x83 +#define AML_CONCAT_RES_OP (u16) 0x84 /* ACPI 2.0 */ +#define AML_MOD_OP (u16) 0x85 /* ACPI 2.0 */ +#define AML_NOTIFY_OP (u16) 0x86 +#define AML_SIZE_OF_OP (u16) 0x87 +#define AML_INDEX_OP (u16) 0x88 +#define AML_MATCH_OP (u16) 0x89 +#define AML_DWORD_FIELD_OP (u16) 0x8a +#define AML_WORD_FIELD_OP (u16) 0x8b +#define AML_BYTE_FIELD_OP (u16) 0x8c +#define AML_BIT_FIELD_OP (u16) 0x8d +#define AML_TYPE_OP (u16) 0x8e +#define AML_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */ +#define AML_LAND_OP (u16) 0x90 +#define AML_LOR_OP (u16) 0x91 +#define AML_LNOT_OP (u16) 0x92 +#define AML_LEQUAL_OP (u16) 0x93 +#define AML_LGREATER_OP (u16) 0x94 +#define AML_LLESS_OP (u16) 0x95 +#define AML_TO_BUFFER_OP (u16) 0x96 /* ACPI 2.0 */ +#define AML_TO_DECSTRING_OP (u16) 0x97 /* ACPI 2.0 */ +#define AML_TO_HEXSTRING_OP (u16) 0x98 /* ACPI 2.0 */ +#define AML_TO_INTEGER_OP (u16) 0x99 /* ACPI 2.0 */ +#define AML_TO_STRING_OP (u16) 0x9c /* ACPI 2.0 */ +#define AML_COPY_OP (u16) 0x9d /* ACPI 2.0 */ +#define AML_MID_OP (u16) 0x9e /* ACPI 2.0 */ +#define AML_CONTINUE_OP (u16) 0x9f /* ACPI 2.0 */ +#define AML_IF_OP (u16) 0xa0 +#define AML_ELSE_OP (u16) 0xa1 +#define AML_WHILE_OP (u16) 0xa2 +#define AML_NOOP_OP (u16) 0xa3 +#define AML_RETURN_OP (u16) 0xa4 +#define AML_BREAK_OP (u16) 0xa5 +#define AML_BREAK_POINT_OP (u16) 0xcc +#define AML_ONES_OP (u16) 0xff + +/* prefixed opcodes */ + +#define AML_EXTOP (u16) 0x005b + + +#define AML_MUTEX_OP (u16) 0x5b01 +#define AML_EVENT_OP (u16) 0x5b02 +#define AML_SHIFT_RIGHT_BIT_OP (u16) 0x5b10 +#define AML_SHIFT_LEFT_BIT_OP (u16) 0x5b11 +#define AML_COND_REF_OF_OP (u16) 0x5b12 +#define AML_CREATE_FIELD_OP (u16) 0x5b13 +#define AML_LOAD_TABLE_OP (u16) 0x5b1f /* ACPI 2.0 */ +#define AML_LOAD_OP (u16) 0x5b20 +#define AML_STALL_OP (u16) 0x5b21 +#define AML_SLEEP_OP (u16) 0x5b22 +#define AML_ACQUIRE_OP (u16) 0x5b23 +#define AML_SIGNAL_OP (u16) 0x5b24 +#define AML_WAIT_OP (u16) 0x5b25 +#define AML_RESET_OP (u16) 0x5b26 +#define AML_RELEASE_OP (u16) 0x5b27 +#define AML_FROM_BCD_OP (u16) 0x5b28 +#define AML_TO_BCD_OP (u16) 0x5b29 +#define AML_UNLOAD_OP (u16) 0x5b2a +#define AML_REVISION_OP (u16) 0x5b30 +#define AML_DEBUG_OP (u16) 0x5b31 +#define AML_FATAL_OP (u16) 0x5b32 +#define AML_REGION_OP (u16) 0x5b80 +#define AML_DEF_FIELD_OP (u16) 0x5b81 +#define AML_DEVICE_OP (u16) 0x5b82 +#define AML_PROCESSOR_OP (u16) 0x5b83 +#define AML_POWER_RES_OP (u16) 0x5b84 +#define AML_THERMAL_ZONE_OP (u16) 0x5b85 +#define AML_INDEX_FIELD_OP (u16) 0x5b86 +#define AML_BANK_FIELD_OP (u16) 0x5b87 +#define AML_DATA_REGION_OP (u16) 0x5b88 /* ACPI 2.0 */ + + +/* Bogus opcodes (they are actually two separate opcodes) */ + +#define AML_LGREATEREQUAL_OP (u16) 0x9295 +#define AML_LLESSEQUAL_OP (u16) 0x9294 +#define AML_LNOTEQUAL_OP (u16) 0x9293 + + +/* + * Internal opcodes + * Use only "Unknown" AML opcodes, don't attempt to use + * any valid ACPI ASCII values (A-Z, 0-9, '-') + */ + +#define AML_NAMEPATH_OP (u16) 0x002d +#define AML_NAMEDFIELD_OP (u16) 0x0030 +#define AML_RESERVEDFIELD_OP (u16) 0x0031 +#define AML_ACCESSFIELD_OP (u16) 0x0032 +#define AML_BYTELIST_OP (u16) 0x0033 +#define AML_STATICSTRING_OP (u16) 0x0034 +#define AML_METHODCALL_OP (u16) 0x0035 +#define AML_RETURN_VALUE_OP (u16) 0x0036 + + +#define ARG_NONE 0x0 + +/* + * Argument types for the AML Parser + * Each field in the Arg_types u32 is 5 bits, allowing for a maximum of 6 arguments. + * There can be up to 31 unique argument types + */ + +#define ARGP_BYTEDATA 0x01 +#define ARGP_BYTELIST 0x02 +#define ARGP_CHARLIST 0x03 +#define ARGP_DATAOBJ 0x04 +#define ARGP_DATAOBJLIST 0x05 +#define ARGP_DWORDDATA 0x06 +#define ARGP_FIELDLIST 0x07 +#define ARGP_NAME 0x08 +#define ARGP_NAMESTRING 0x09 +#define ARGP_OBJLIST 0x0A +#define ARGP_PKGLENGTH 0x0B +#define ARGP_SUPERNAME 0x0C +#define ARGP_TARGET 0x0D +#define ARGP_TERMARG 0x0E +#define ARGP_TERMLIST 0x0F +#define ARGP_WORDDATA 0x10 +#define ARGP_QWORDDATA 0x11 +#define ARGP_SIMPLENAME 0x12 + +/* + * Resolved argument types for the AML Interpreter + * Each field in the Arg_types u32 is 5 bits, allowing for a maximum of 6 arguments. + * There can be up to 31 unique argument types (0 is end-of-arg-list indicator) + */ + +/* "Standard" ACPI types are 1-15 (0x0F) */ + +#define ARGI_INTEGER ACPI_TYPE_INTEGER /* 1 */ +#define ARGI_STRING ACPI_TYPE_STRING /* 2 */ +#define ARGI_BUFFER ACPI_TYPE_BUFFER /* 3 */ +#define ARGI_PACKAGE ACPI_TYPE_PACKAGE /* 4 */ +#define ARGI_EVENT ACPI_TYPE_EVENT +#define ARGI_MUTEX ACPI_TYPE_MUTEX +#define ARGI_REGION ACPI_TYPE_REGION +#define ARGI_DDBHANDLE ACPI_TYPE_DDB_HANDLE + +/* Custom types are 0x10 through 0x1F */ + +#define ARGI_IF 0x10 +#define ARGI_ANYOBJECT 0x11 +#define ARGI_ANYTYPE 0x12 +#define ARGI_COMPUTEDATA 0x13 /* Buffer, String, or Integer */ +#define ARGI_DATAOBJECT 0x14 /* Buffer, string, package or reference to a Node - Used only by Size_of operator*/ +#define ARGI_COMPLEXOBJ 0x15 /* Buffer or package */ +#define ARGI_INTEGER_REF 0x16 +#define ARGI_OBJECT_REF 0x17 +#define ARGI_DEVICE_REF 0x18 +#define ARGI_REFERENCE 0x19 +#define ARGI_TARGETREF 0x1A /* Target, subject to implicit conversion */ +#define ARGI_FIXED_TARGET 0x1B /* Target, no implicit conversion */ +#define ARGI_SIMPLE_TARGET 0x1C /* Name, Local, Arg -- no implicit conversion */ +#define ARGI_BUFFERSTRING 0x1D + +#define ARGI_INVALID_OPCODE 0xFFFFFFFF + + +/* + * hash offsets + */ +#define AML_EXTOP_HASH_OFFSET 22 +#define AML_LNOT_HASH_OFFSET 19 + + +/* + * opcode groups and types + */ + +#define OPGRP_NAMED 0x01 +#define OPGRP_FIELD 0x02 +#define OPGRP_BYTELIST 0x04 + +#define OPTYPE_UNDEFINED 0 + + +#define OPTYPE_LITERAL 1 +#define OPTYPE_CONSTANT 2 +#define OPTYPE_METHOD_ARGUMENT 3 +#define OPTYPE_LOCAL_VARIABLE 4 +#define OPTYPE_DATA_TERM 5 + +/* Type 1 opcodes */ + +#define OPTYPE_MONADIC1 6 +#define OPTYPE_DYADIC1 7 + + +/* Type 2 opcodes */ + +#define OPTYPE_MONADIC2 8 +#define OPTYPE_MONADIC2_r 9 +#define OPTYPE_DYADIC2 10 +#define OPTYPE_DYADIC2_r 11 +#define OPTYPE_DYADIC2_s 12 +#define OPTYPE_INDEX 13 +#define OPTYPE_MATCH 14 + +/* Generic for an op that returns a value */ + +#define OPTYPE_METHOD_CALL 15 + + +/* Misc */ + +#define OPTYPE_CREATE_FIELD 16 +#define OPTYPE_FATAL 17 +#define OPTYPE_CONTROL 18 +#define OPTYPE_RECONFIGURATION 19 +#define OPTYPE_NAMED_OBJECT 20 +#define OPTYPE_RETURN 21 + +#define OPTYPE_BOGUS 22 + + +/* Predefined Operation Region Space_iDs */ + +typedef enum +{ + REGION_MEMORY = 0, + REGION_IO, + REGION_PCI_CONFIG, + REGION_EC, + REGION_SMBUS, + REGION_CMOS, + REGION_PCI_BAR + +} AML_REGION_TYPES; + + +/* Comparison operation codes for Match_op operator */ + +typedef enum +{ + MATCH_MTR = 0, + MATCH_MEQ = 1, + MATCH_MLE = 2, + MATCH_MLT = 3, + MATCH_MGE = 4, + MATCH_MGT = 5 + +} AML_MATCH_OPERATOR; + +#define MAX_MATCH_OPERATOR 5 + + +/* Field Access Types */ + +#define ACCESS_TYPE_MASK 0x0f +#define ACCESS_TYPE_SHIFT 0 + +typedef enum +{ + ACCESS_ANY_ACC = 0, + ACCESS_BYTE_ACC = 1, + ACCESS_WORD_ACC = 2, + ACCESS_DWORD_ACC = 3, + ACCESS_BLOCK_ACC = 4, + ACCESS_SMBSEND_RECV_ACC = 5, + ACCESS_SMBQUICK_ACC = 6 + +} AML_ACCESS_TYPE; + + +/* Field Lock Rules */ + +#define LOCK_RULE_MASK 0x10 +#define LOCK_RULE_SHIFT 4 + +typedef enum +{ + GLOCK_NEVER_LOCK = 0, + GLOCK_ALWAYS_LOCK = 1 + +} AML_LOCK_RULE; + + +/* Field Update Rules */ + +#define UPDATE_RULE_MASK 0x060 +#define UPDATE_RULE_SHIFT 5 + +typedef enum +{ + UPDATE_PRESERVE = 0, + UPDATE_WRITE_AS_ONES = 1, + UPDATE_WRITE_AS_ZEROS = 2 + +} AML_UPDATE_RULE; + + +/* bit fields in Method_flags byte */ + +#define METHOD_FLAGS_ARG_COUNT 0x07 +#define METHOD_FLAGS_SERIALIZED 0x08 +#define METHOD_FLAGS_SYNCH_LEVEL 0xF0 + + +/* Array sizes. Used for range checking also */ + +#define NUM_REGION_TYPES 7 +#define NUM_ACCESS_TYPES 7 +#define NUM_UPDATE_RULES 3 +#define NUM_MATCH_OPS 7 +#define NUM_OPCODES 256 +#define NUM_FIELD_NAMES 2 + + +#define USER_REGION_BEGIN 0x80 + +/* + * AML tables + */ + +#ifdef DEFINE_AML_GLOBALS + +/* External declarations of the AML tables */ + +extern u8 acpi_gbl_aml [NUM_OPCODES]; +extern u16 acpi_gbl_pfx [NUM_OPCODES]; + + +#endif /* DEFINE_AML_GLOBALS */ + +#endif /* __AMLCODE_H__ */ diff --git a/drivers/bus/acpi/include/platform/acenv.h b/drivers/bus/acpi/include/platform/acenv.h new file mode 100644 index 0000000..bd062ab --- /dev/null +++ b/drivers/bus/acpi/include/platform/acenv.h @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * Name: acenv.h - Generation environment specific items + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACENV_H__ +#define __ACENV_H__ + + +/* + * Configuration for ACPI tools and utilities + */ + +#ifdef _ACPI_DUMP_APP +#define ACPI_DEBUG +#define ACPI_APPLICATION +#define ENABLE_DEBUGGER +#define ACPI_USE_SYSTEM_CLIBRARY +#define PARSER_ONLY +#endif + +#ifdef _ACPI_EXEC_APP +#undef DEBUGGER_THREADING +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED +#define ACPI_DEBUG +#define ACPI_APPLICATION +#define ENABLE_DEBUGGER +#define ACPI_USE_SYSTEM_CLIBRARY +#endif + +#ifdef _ACPI_ASL_COMPILER +#define ACPI_DEBUG +#define ACPI_APPLICATION +#define ENABLE_DEBUGGER +#define ACPI_USE_SYSTEM_CLIBRARY +#endif + +/* + * Memory allocation tracking. Used only if + * 1) This is the debug version + * 2) This is NOT a 16-bit version of the code (not enough real-mode memory) + */ +#ifdef ACPI_DEBUG +#ifndef _IA16 +#define ACPI_DEBUG_TRACK_ALLOCATIONS +#endif +#endif + +/* + * Environment configuration. The purpose of this file is to interface to the + * local generation environment. + * + * 1) ACPI_USE_SYSTEM_CLIBRARY - Define this if linking to an actual C library. + * Otherwise, local versions of string/memory functions will be used. + * 2) ACPI_USE_STANDARD_HEADERS - Define this if linking to a C library and + * the standard header files may be used. + * + * The ACPI subsystem only uses low level C library functions that do not call + * operating system services and may therefore be inlined in the code. + * + * It may be necessary to tailor these include files to the target + * generation environment. + * + * + * Functions and constants used from each header: + * + * string.h: memcpy + * memset + * strcat + * strcmp + * strcpy + * strlen + * strncmp + * strncat + * strncpy + * + * stdlib.h: strtoul + * + * stdarg.h: va_list + * va_arg + * va_start + * va_end + * + */ + +/*! [Begin] no source code translation */ + +#ifdef _LINUX +#include "aclinux.h" + +#elif _AED_EFI +#include "acefi.h" + +#elif WIN32 +#include "acwin.h" + +#elif __FreeBSD__ +#include "acfreebsd.h" + +#else + +/* All other environments */ + +#define ACPI_USE_STANDARD_HEADERS + +/* Name of host operating system (returned by the _OS_ namespace object) */ + +#define ACPI_OS_NAME "Intel ACPI/CA Core Subsystem" + +#endif + + +/*! [End] no source code translation !*/ + +/****************************************************************************** + * + * C library configuration + * + *****************************************************************************/ + +#ifdef ACPI_USE_SYSTEM_CLIBRARY +/* + * Use the standard C library headers. + * We want to keep these to a minimum. + * + */ + +#ifdef ACPI_USE_STANDARD_HEADERS +/* + * Use the standard headers from the standard locations + */ +#include +#include +#include +#include + +#endif /* ACPI_USE_STANDARD_HEADERS */ + +/* + * We will be linking to the standard Clib functions + */ + +#define STRSTR(s1,s2) strstr((s1), (s2)) +#define STRUPR(s) strupr((s)) +#define STRLEN(s) (u32) strlen((s)) +#define STRCPY(d,s) strcpy((d), (s)) +#define STRNCPY(d,s,n) strncpy((d), (s), (NATIVE_INT)(n)) +#define STRNCMP(d,s,n) strncmp((d), (s), (NATIVE_INT)(n)) +#define STRCMP(d,s) strcmp((d), (s)) +#define STRCAT(d,s) strcat((d), (s)) +#define STRNCAT(d,s,n) strncat((d), (s), (NATIVE_INT)(n)) +#define STRTOUL(d,s,n) strtoul((d), (s), (NATIVE_INT)(n)) +#define MEMCPY(d,s,n) memcpy((d), (s), (NATIVE_INT)(n)) +#define MEMSET(d,s,n) memset((d), (s), (NATIVE_INT)(n)) +#define TOUPPER toupper +#define TOLOWER tolower +#define IS_XDIGIT isxdigit + +/****************************************************************************** + * + * Not using native C library, use local implementations + * + *****************************************************************************/ +#else + +/* + * Use local definitions of C library macros and functions + * NOTE: The function implementations may not be as efficient + * as an inline or assembly code implementation provided by a + * native C library. + */ + +#ifndef va_arg + +#ifndef _VALIST +#define _VALIST +typedef char *va_list; +#endif /* _VALIST */ + +/* + * Storage alignment properties + */ + +#define _AUPBND (sizeof (NATIVE_INT) - 1) +#define _ADNBND (sizeof (NATIVE_INT) - 1) + +/* + * Variable argument list macro definitions + */ + +#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) +#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) +#define va_end(ap) (void) 0 +#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) + +#endif /* va_arg */ + + +#define STRSTR(s1,s2) acpi_cm_strstr ((s1), (s2)) +#define STRUPR(s) acpi_cm_strupr ((s)) +#define STRLEN(s) acpi_cm_strlen ((s)) +#define STRCPY(d,s) acpi_cm_strcpy ((d), (s)) +#define STRNCPY(d,s,n) acpi_cm_strncpy ((d), (s), (n)) +#define STRNCMP(d,s,n) acpi_cm_strncmp ((d), (s), (n)) +#define STRCMP(d,s) acpi_cm_strcmp ((d), (s)) +#define STRCAT(d,s) acpi_cm_strcat ((d), (s)) +#define STRNCAT(d,s,n) acpi_cm_strncat ((d), (s), (n)) +#define STRTOUL(d,s,n) acpi_cm_strtoul ((d), (s),(n)) +#define MEMCPY(d,s,n) acpi_cm_memcpy ((d), (s), (n)) +#define MEMSET(d,v,n) acpi_cm_memset ((d), (v), (n)) +#define TOUPPER acpi_cm_to_upper +#define TOLOWER acpi_cm_to_lower + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + + +/****************************************************************************** + * + * Assembly code macros + * + *****************************************************************************/ + +/* + * Handle platform- and compiler-specific assembly language differences. + * These should already have been defined by the platform includes above. + * + * Notes: + * 1) Interrupt 3 is used to break into a debugger + * 2) Interrupts are turned off during ACPI register setup + */ + +/* Unrecognized compiler, use defaults */ +#ifndef ACPI_ASM_MACROS + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() +#define enable() +#define halt() +#define ACPI_ACQUIRE_GLOBAL_LOCK(Glptr, acq) +#define ACPI_RELEASE_GLOBAL_LOCK(Glptr, acq) + +#endif /* ACPI_ASM_MACROS */ + + +#ifdef ACPI_APPLICATION + +/* Don't want software interrupts within a ring3 application */ + +#undef causeinterrupt +#undef BREAKPOINT3 +#define causeinterrupt(level) +#define BREAKPOINT3 +#endif + + +/****************************************************************************** + * + * Compiler-specific + * + *****************************************************************************/ + +/* this has been moved to compiler-specific headers, which are included from the + platform header. */ + + +#endif /* __ACENV_H__ */ diff --git a/drivers/bus/acpi/include/platform/acgcc.h b/drivers/bus/acpi/include/platform/acgcc.h new file mode 100644 index 0000000..34b0ebb --- /dev/null +++ b/drivers/bus/acpi/include/platform/acgcc.h @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Name: acgcc.h - GCC specific defines, etc. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACGCC_H__ +#define __ACGCC_H__ + + +#ifdef __ia64__ +#define _IA64 + +#define COMPILER_DEPENDENT_UINT64 unsigned long +/* Single threaded */ +#define ACPI_APPLICATION + +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() __cli() +#define enable() __sti() +#define wbinvd() + +/*! [Begin] no source code translation */ + +#include + +#define halt() ia64_pal_halt_light() /* PAL_HALT[_LIGHT] */ +#define safe_halt() ia64_pal_halt(1) /* PAL_HALT */ + + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + __asm__ volatile ("1: ld4 r29=%1\n" \ + ";;\n" \ + "mov ar.ccv=r29\n" \ + "mov r2=r29\n" \ + "shr.u r30=r29,1\n" \ + "and r29=-4,r29\n" \ + ";;\n" \ + "add r29=2,r29\n" \ + "and r30=1,r30\n" \ + ";;\n" \ + "add r29=r29,r30\n" \ + ";;\n" \ + "cmpxchg4.acq r30=%1,r29,ar.ccv\n" \ + ";;\n" \ + "cmp.eq p6,p7=r2,r30\n" \ + "(p7) br.dpnt.few 1b\n" \ + "cmp.gt p8,p9=3,r29\n" \ + ";;\n" \ + "(p8) mov %0=-1\n" \ + "(p9) mov %0=r0\n" \ + :"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \ + } while (0) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + __asm__ volatile ("1: ld4 r29=%1\n" \ + ";;\n" \ + "mov ar.ccv=r29\n" \ + "mov r2=r29\n" \ + "and r29=-4,r29\n" \ + ";;\n" \ + "cmpxchg4.acq r30=%1,r29,ar.ccv\n" \ + ";;\n" \ + "cmp.eq p6,p7=r2,r30\n" \ + "(p7) br.dpnt.few 1b\n" \ + "and %0=1,r2\n" \ + ";;\n" \ + :"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \ + } while (0) +/*! [End] no source code translation !*/ + + +#else /* DO IA32 */ +#define COMPILER_DEPENDENT_UINT64 unsigned long long +#define ACPI_ASM_MACROS +#define causeinterrupt(level) +#define BREAKPOINT3 +#define disable() __cli() +#define enable() __sti() +#define halt() __asm__ __volatile__ ("sti; hlt":::"memory") +#define wbinvd() + +/*! [Begin] no source code translation + * + * A brief explanation as GNU inline assembly is a bit hairy + * %0 is the output parameter in EAX ("=a") + * %1 and %2 are the input parameters in ECX ("c") + * and an immediate value ("i") respectively + * All actual register references are preceded with "%%" as in "%%edx" + * Immediate values in the assembly are preceded by "$" as in "$0x1" + * The final asm parameter are the operation altered non-output registers. + */ +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + int dummy; \ + asm("1: movl (%1),%%eax;" \ + "movl %%eax,%%edx;" \ + "andl %2,%%edx;" \ + "btsl $0x1,%%edx;" \ + "adcl $0x0,%%edx;" \ + "lock; cmpxchgl %%edx,(%1);" \ + "jnz 1b;" \ + "cmpb $0x3,%%dl;" \ + "sbbl %%eax,%%eax" \ + :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~1L):"dx"); \ + } while(0) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + do { \ + int dummy; \ + asm("1: movl (%1),%%eax;" \ + "movl %%eax,%%edx;" \ + "andl %2,%%edx;" \ + "lock; cmpxchgl %%edx,(%1);" \ + "jnz 1b;" \ + "andl $0x1,%%eax" \ + :"=a"(Acq),"=c"(dummy):"c"(GLptr),"i"(~3L):"dx"); \ + } while(0) + +/*! [End] no source code translation !*/ + +#endif /* IA 32 */ + +#endif /* __ACGCC_H__ */ diff --git a/drivers/bus/acpi/include/platform/aclinux.h b/drivers/bus/acpi/include/platform/aclinux.h new file mode 100644 index 0000000..9e6857e --- /dev/null +++ b/drivers/bus/acpi/include/platform/aclinux.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Name: aclinux.h - OS specific defines, etc. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACLINUX_H__ +#define __ACLINUX_H__ + +#define ACPI_OS_NAME "Linux" + +#undef ACPI_USE_SYSTEM_CLIBRARY + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#else + +#include + +#endif + +/* Linux uses GCC */ + +#include "acgcc.h" + +#undef DEBUGGER_THREADING +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED + +#ifndef _IA64 +/* Linux ia32 can't do int64 well */ +#define ACPI_NO_INTEGER64_SUPPORT +/* And the ia32 kernel doesn't include 64-bit divide support */ +#define ACPI_DIV64(dividend, divisor) do_div(dividend, divisor) +#else +#define ACPI_DIV64(dividend, divisor) ACPI_DIVIDE(dividend, divisor) +#endif + + +#endif /* __ACLINUX_H__ */ diff --git a/drivers/bus/acpi/include/platform/acwin.h b/drivers/bus/acpi/include/platform/acwin.h new file mode 100644 index 0000000..55025c7 --- /dev/null +++ b/drivers/bus/acpi/include/platform/acwin.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Name: aclinux.h - OS specific defines, etc. + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ACWIN_H__ +#define __ACWIN_H__ + +#define ACPI_OS_NAME "ReactOS" +#define DEFINE_ALTERNATE_TYPES + +#undef ACPI_USE_SYSTEM_CLIBRARY + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#else + +#include + +#endif + +/* ReactOS uses GCC */ + +#include "acgcc.h" + +#undef disable +#define disable() __asm__("cli\n\t"); +#undef enable +#define enable() __asm__("sti\n\t"); + +#undef DEBUGGER_THREADING +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED + +#ifndef _IA64 +/* Linux ia32 can't do int64 well */ +#define ACPI_NO_INTEGER64_SUPPORT +/* And the ia32 kernel doesn't include 64-bit divide support */ +#define ACPI_DIV64(dividend, divisor) do_div(dividend, divisor) +#else +#define ACPI_DIV64(dividend, divisor) ACPI_DIVIDE(dividend, divisor) +#endif + +#endif /* __ACWIN_H__ */ diff --git a/drivers/bus/acpi/include/platform/types.h b/drivers/bus/acpi/include/platform/types.h new file mode 100644 index 0000000..6326448 --- /dev/null +++ b/drivers/bus/acpi/include/platform/types.h @@ -0,0 +1,796 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/types.h + * PURPOSE: Types used by all the parts of the system + * PROGRAMMER: David Welch + * DEFINES: _WIN64: 64-bit architecture + * _WIN32: 32-bit architecture (default) + * UPDATE HISTORY: + * 27/06/00: Created + * 01/05/01: Portabillity changes + */ + +#ifndef __INCLUDE_ACPI_TYPES_H +#define __INCLUDE_ACPI_TYPES_H + +/* Fixed precision types */ +typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +#if 0 +typedef signed int INT32, *PINT32; +#endif +typedef signed long long INT64, *PINT64; +#if 0 +typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32; +typedef unsigned long long UINT64, *PUINT64; +#endif + +typedef signed long int LONG32, *PLONG32; +typedef unsigned long int ULONG32, *PULONG32; +typedef unsigned long int DWORD32, *PDWORD32; + + +#ifdef _WIN64 + +/* 64-bit architecture */ + +typedef INT64 INT, *PINT; +typedef LONG64 LONG, *PLONG; +typedef DWORD64 DWORD, *PDWORD; +typedef UINT64 UINT, *PUINT; +typedef ULONG64 ULONG, *PULONG; + +/* Pointer precision types */ +typedef long long INT_PTR, *PINT_PTR; +typedef unsigned long long UINT_PTR, *PUINT_PTR; +typedef long long LONG_PTR, *PLONG_PTR; +typedef unsigned long long ULONG_PTR, *PULONG_PTR; +typedef unsigned long long HANDLE_PTR; +typedef unsigned int UHALF_PTR, *PUHALF_PTR; +typedef int HALF_PTR, *PHALF_PTR; + +#else /* _WIN64 */ + +/* 32-bit architecture */ + +typedef INT32 INT, *PINT; +typedef LONG32 LONG, *PLONG; +typedef DWORD32 DWORD, *PDWORD; +typedef UINT32 UINT, *PUINT; +typedef ULONG32 ULONG, *PULONG; + + +/* Pointer precision types */ +typedef int INT_PTR, *PINT_PTR; +typedef unsigned int UINT_PTR, *PUINT_PTR; +typedef long LONG_PTR, *PLONG_PTR; +typedef unsigned long ULONG_PTR, *PULONG_PTR; +typedef unsigned short UHALF_PTR, *PUHALF_PTR; +typedef short HALF_PTR, *PHALF_PTR; +typedef unsigned long HANDLE_PTR; + +#endif /* _WIN64 */ + +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; + +typedef long long LONG64, *PLONG64; + +typedef unsigned long long ULONG64, *PULONG64; +typedef unsigned long long DWORD64, *PDWORD64; + + +#if 0 +typedef unsigned char UCHAR; +#endif +typedef unsigned short USHORT; +typedef unsigned short WCHAR; +typedef unsigned short WORD; +typedef int BOOL; +#if 0 +typedef unsigned char BOOLEAN; +#endif +typedef BOOLEAN* PBOOLEAN; +typedef unsigned short *LPWSTR; +typedef unsigned short *PWSTR; +typedef unsigned char *PUCHAR; +typedef unsigned short *PUSHORT; +typedef void *PVOID; +typedef unsigned char BYTE; +typedef void *LPVOID; +typedef float *PFLOAT; +typedef unsigned short *PWCH; +typedef unsigned short *PWORD; + +typedef long long LONGLONG; +typedef unsigned long long ULONGLONG; +typedef long long *PLONGLONG; +typedef unsigned long long *PULONGLONG; + +/* Check VOID before defining CHAR, SHORT */ +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef short SHORT; +#endif + +typedef CHAR *PCHAR; +typedef CHAR *PCH; +typedef void *HANDLE; +typedef char CCHAR; +typedef CCHAR *PCCHAR; + +#if 0 +#define FALSE 0 +#define TRUE 1 +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void*)0) +#endif /* __cplusplus */ +#endif /* NULL */ + +typedef const unsigned short *PCWSTR; + +typedef char* PCSZ; + +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + } u; +#ifdef ANONYMOUSUNIONS + struct + { + DWORD LowPart; + LONG HighPart; + }; +#endif /* ANONYMOUSUNIONS */ + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER +{ + struct + { + DWORD LowPart; + DWORD HighPart; + } u; +#ifdef ANONYMOUSUNIONS + struct + { + DWORD LowPart; + DWORD HighPart; + }; +#endif /* ANONYMOUSUNIONS */ + ULONGLONG QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME, *LPFILETIME, *PFILETIME; + +#define CONST const + +#ifdef i386 +#define STDCALL __attribute__ ((stdcall)) +#define CDECL __attribute((cdecl)) +#define CALLBACK WINAPI +#define PASCAL WINAPI +#else +#define STDCALL +#define CDECL +#define CALLBACK +#define PASCAL +#endif + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _SINGLE_LIST_ENTRY { + struct _SINGLE_LIST_ENTRY *Next; +} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; + +typedef DWORD STDCALL (*PTHREAD_START_ROUTINE) (LPVOID); +typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; + +typedef unsigned short *PWCHAR; + +#ifdef __PPC__ +#define CONTEXT_CONTROL 1L +#define CONTEXT_FLOATING_POINT 2L +#define CONTEXT_INTEGER 4L +#define CONTEXT_DEBUG_REGISTERS 8L + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +#define CONTEXT_DEBUGGER (CONTEXT_FULL) + +#else /* x86 */ +/* The doc refered me to winnt.h, so I had to look... */ +#define SIZE_OF_80387_REGISTERS 80 + +/* Values for contextflags */ +#define CONTEXT_i386 0x10000 +#define CONTEXT_CONTROL (CONTEXT_i386 | 1) +#define CONTEXT_INTEGER (CONTEXT_i386 | 2) +#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4) +#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10) +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) + +/* our own invention */ +#define FLAG_TRACE_BIT 0x100 +#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT) + +#endif + +#ifdef __i386__ + +typedef struct _FLOATING_SAVE_AREA { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + BYTE RegisterArea[80]; + DWORD Cr0NpxState; +} FLOATING_SAVE_AREA; + +typedef struct _CONTEXT { + DWORD ContextFlags; + + DWORD Dr0; + DWORD Dr1; + DWORD Dr2; + DWORD Dr3; + DWORD Dr6; + DWORD Dr7; + + FLOATING_SAVE_AREA FloatSave; + + DWORD SegGs; + DWORD SegFs; + DWORD SegEs; + DWORD SegDs; + + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Edx; + DWORD Ecx; + DWORD Eax; + + DWORD Ebp; + DWORD Eip; + DWORD SegCs; + DWORD EFlags; + DWORD Esp; + DWORD SegSs; +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +#else /* __ppc__ */ + +typedef struct + { + /* Floating point registers returned when CONTEXT_FLOATING_POINT is set */ + double Fpr0; + double Fpr1; + double Fpr2; + double Fpr3; + double Fpr4; + double Fpr5; + double Fpr6; + double Fpr7; + double Fpr8; + double Fpr9; + double Fpr10; + double Fpr11; + double Fpr12; + double Fpr13; + double Fpr14; + double Fpr15; + double Fpr16; + double Fpr17; + double Fpr18; + double Fpr19; + double Fpr20; + double Fpr21; + double Fpr22; + double Fpr23; + double Fpr24; + double Fpr25; + double Fpr26; + double Fpr27; + double Fpr28; + double Fpr29; + double Fpr30; + double Fpr31; + double Fpscr; + + /* Integer registers returned when CONTEXT_INTEGER is set. */ + DWORD Gpr0; + DWORD Gpr1; + DWORD Gpr2; + DWORD Gpr3; + DWORD Gpr4; + DWORD Gpr5; + DWORD Gpr6; + DWORD Gpr7; + DWORD Gpr8; + DWORD Gpr9; + DWORD Gpr10; + DWORD Gpr11; + DWORD Gpr12; + DWORD Gpr13; + DWORD Gpr14; + DWORD Gpr15; + DWORD Gpr16; + DWORD Gpr17; + DWORD Gpr18; + DWORD Gpr19; + DWORD Gpr20; + DWORD Gpr21; + DWORD Gpr22; + DWORD Gpr23; + DWORD Gpr24; + DWORD Gpr25; + DWORD Gpr26; + DWORD Gpr27; + DWORD Gpr28; + DWORD Gpr29; + DWORD Gpr30; + DWORD Gpr31; + + DWORD Cr; /* Condition register */ + DWORD Xer; /* Fixed point exception register */ + + /* The following are set when CONTEXT_CONTROL is set. */ + DWORD Msr; /* Machine status register */ + DWORD Iar; /* Instruction address register */ + DWORD Lr; /* Link register */ + DWORD Ctr; /* Control register */ + + /* Control which context values are returned */ + DWORD ContextFlags; + DWORD Fill[3]; + + /* Registers returned if CONTEXT_DEBUG_REGISTERS is set. */ + DWORD Dr0; /* Breakpoint Register 1 */ + DWORD Dr1; /* Breakpoint Register 2 */ + DWORD Dr2; /* Breakpoint Register 3 */ + DWORD Dr3; /* Breakpoint Register 4 */ + DWORD Dr4; /* Breakpoint Register 5 */ + DWORD Dr5; /* Breakpoint Register 6 */ + DWORD Dr6; /* Debug Status Register */ + DWORD Dr7; /* Debug Control Register */ +} CONTEXT, *PCONTEXT, *LPCONTEXT; +#endif + +typedef HANDLE *PHANDLE; + +typedef struct value_ent { + LPWSTR ve_valuename; + DWORD ve_valuelen; + DWORD ve_valueptr; + DWORD ve_type; +} WVALENT, *PWVALENT; + + +typedef const void *LPCVOID; +typedef BYTE *LPBYTE, *PBYTE; + +typedef BOOL *PBOOL; + +typedef DWORD LCID; +typedef DWORD *PLCID; + +typedef const char *LPCSTR; + +typedef char *LPSTR; + +typedef const unsigned short *LPCWSTR; + +typedef unsigned short RTL_ATOM; +typedef unsigned short *PRTL_ATOM; +typedef WORD ATOM; + +typedef struct _COORD { + SHORT X; + SHORT Y; +} COORD; + +typedef struct _SMALL_RECT { + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; +} SMALL_RECT, *PSMALL_RECT; + + +typedef +VOID +(*PTIMERAPCROUTINE)( + LPVOID lpArgToCompletionRoutine, + DWORD dwTimerLowValue, + DWORD dwTimerHighValue + ); + +#include + +#endif /* __INCLUDE_ACPI_TYPES_H */ + + + +#if 0 + + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/types.h + * PURPOSE: Types used by all the parts of the system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + +#ifndef __INCLUDE_ACPI_TYPES_H +#define __INCLUDE_ACPI_TYPES_H +#if 0 +typedef unsigned char UCHAR; +#endif +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef unsigned short USHORT; +typedef unsigned short WCHAR; +typedef unsigned short WORD; +typedef int BOOL; +#if 0 +typedef unsigned char BOOLEAN; +#endif +typedef BOOLEAN* PBOOLEAN; +typedef unsigned int DWORD; /* was unsigned long */ +typedef unsigned short *LPWSTR; +typedef unsigned short *PWSTR; +typedef unsigned char *PUCHAR; +typedef unsigned int *PUINT; +typedef unsigned long *PULONG; +typedef unsigned short *PUSHORT; +typedef void *PVOID; +typedef unsigned char BYTE; +typedef void *LPVOID; +typedef DWORD *PDWORD; +typedef float *PFLOAT; +typedef unsigned short *PWCH; +typedef unsigned short *PWORD; + +typedef long long LONGLONG; +typedef unsigned long long ULONGLONG; +typedef long long *PLONGLONG; +typedef unsigned long long *PULONGLONG; + +/* Check VOID before defining CHAR, SHORT, and LONG */ +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef short SHORT; +typedef long LONG; +#endif + +typedef CHAR *PCHAR; +typedef CHAR *PCH; +typedef void *HANDLE; +typedef char CCHAR; + +#if 0 +#define FALSE 0 +#define TRUE 1 +#endif + +typedef const unsigned short *PCWSTR; + +typedef char* PCSZ; + +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + } u; +#ifdef ANONYMOUSUNIONS + struct + { + DWORD LowPart; + LONG HighPart; + }; +#endif /* ANONYMOUSUNIONS */ + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER +{ + struct + { + DWORD LowPart; + DWORD HighPart; + } u; +#ifdef ANONYMOUSUNIONS + struct + { + DWORD LowPart; + DWORD HighPart; + }; +#endif /* ANONYMOUSUNIONS */ + ULONGLONG QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +#define CONST const + +#ifdef i386 +#define STDCALL __attribute__ ((stdcall)) +#define CDECL __attribute((cdecl)) +#define CALLBACK WINAPI +#define PASCAL WINAPI +#else +#define STDCALL +#define CDECL +#define CALLBACK +#define PASCAL +#endif + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _SINGLE_LIST_ENTRY { + struct _SINGLE_LIST_ENTRY *Next; +} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; + +typedef DWORD STDCALL (*PTHREAD_START_ROUTINE) (LPVOID); +typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; + +typedef unsigned short *PWCHAR; + +#ifdef __PPC__ +#define CONTEXT_CONTROL 1L +#define CONTEXT_FLOATING_POINT 2L +#define CONTEXT_INTEGER 4L +#define CONTEXT_DEBUG_REGISTERS 8L + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +#define CONTEXT_DEBUGGER (CONTEXT_FULL) + +#else /* x86 */ +/* The doc refered me to winnt.h, so I had to look... */ +#define SIZE_OF_80387_REGISTERS 80 + +/* Values for contextflags */ +#define CONTEXT_i386 0x10000 +#define CONTEXT_CONTROL (CONTEXT_i386 | 1) +#define CONTEXT_INTEGER (CONTEXT_i386 | 2) +#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4) +#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10) +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) + +/* our own invention */ +#define FLAG_TRACE_BIT 0x100 +#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT) + +#endif + +#ifdef __i386__ + +typedef struct _FLOATING_SAVE_AREA { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + BYTE RegisterArea[80]; + DWORD Cr0NpxState; +} FLOATING_SAVE_AREA; + +typedef struct _CONTEXT { + DWORD ContextFlags; + + DWORD Dr0; + DWORD Dr1; + DWORD Dr2; + DWORD Dr3; + DWORD Dr6; + DWORD Dr7; + + FLOATING_SAVE_AREA FloatSave; + + DWORD SegGs; + DWORD SegFs; + DWORD SegEs; + DWORD SegDs; + + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Edx; + DWORD Ecx; + DWORD Eax; + + DWORD Ebp; + DWORD Eip; + DWORD SegCs; + DWORD EFlags; + DWORD Esp; + DWORD SegSs; +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +#else /* __ppc__ */ + +typedef struct + { + /* Floating point registers returned when CONTEXT_FLOATING_POINT is set */ + double Fpr0; + double Fpr1; + double Fpr2; + double Fpr3; + double Fpr4; + double Fpr5; + double Fpr6; + double Fpr7; + double Fpr8; + double Fpr9; + double Fpr10; + double Fpr11; + double Fpr12; + double Fpr13; + double Fpr14; + double Fpr15; + double Fpr16; + double Fpr17; + double Fpr18; + double Fpr19; + double Fpr20; + double Fpr21; + double Fpr22; + double Fpr23; + double Fpr24; + double Fpr25; + double Fpr26; + double Fpr27; + double Fpr28; + double Fpr29; + double Fpr30; + double Fpr31; + double Fpscr; + + /* Integer registers returned when CONTEXT_INTEGER is set. */ + DWORD Gpr0; + DWORD Gpr1; + DWORD Gpr2; + DWORD Gpr3; + DWORD Gpr4; + DWORD Gpr5; + DWORD Gpr6; + DWORD Gpr7; + DWORD Gpr8; + DWORD Gpr9; + DWORD Gpr10; + DWORD Gpr11; + DWORD Gpr12; + DWORD Gpr13; + DWORD Gpr14; + DWORD Gpr15; + DWORD Gpr16; + DWORD Gpr17; + DWORD Gpr18; + DWORD Gpr19; + DWORD Gpr20; + DWORD Gpr21; + DWORD Gpr22; + DWORD Gpr23; + DWORD Gpr24; + DWORD Gpr25; + DWORD Gpr26; + DWORD Gpr27; + DWORD Gpr28; + DWORD Gpr29; + DWORD Gpr30; + DWORD Gpr31; + + DWORD Cr; /* Condition register */ + DWORD Xer; /* Fixed point exception register */ + + /* The following are set when CONTEXT_CONTROL is set. */ + DWORD Msr; /* Machine status register */ + DWORD Iar; /* Instruction address register */ + DWORD Lr; /* Link register */ + DWORD Ctr; /* Control register */ + + /* Control which context values are returned */ + DWORD ContextFlags; + DWORD Fill[3]; + + /* Registers returned if CONTEXT_DEBUG_REGISTERS is set. */ + DWORD Dr0; /* Breakpoint Register 1 */ + DWORD Dr1; /* Breakpoint Register 2 */ + DWORD Dr2; /* Breakpoint Register 3 */ + DWORD Dr3; /* Breakpoint Register 4 */ + DWORD Dr4; /* Breakpoint Register 5 */ + DWORD Dr5; /* Breakpoint Register 6 */ + DWORD Dr6; /* Debug Status Register */ + DWORD Dr7; /* Debug Control Register */ +} CONTEXT, *PCONTEXT, *LPCONTEXT; +#endif + +typedef HANDLE *PHANDLE; + +typedef struct value_ent { + LPWSTR ve_valuename; + DWORD ve_valuelen; + DWORD ve_valueptr; + DWORD ve_type; +} WVALENT, *PWVALENT; + +typedef long *PLONG; + +typedef const void *LPCVOID; +typedef BYTE *LPBYTE; + +typedef BYTE *PBYTE; + +typedef DWORD LCID; +typedef DWORD *PLCID; + +typedef const char *LPCSTR; + +typedef char *LPSTR; + +typedef const unsigned short *LPCWSTR; + +typedef unsigned short RTL_ATOM; +typedef unsigned short *PRTL_ATOM; +typedef WORD ATOM; + +typedef struct _COORD { + SHORT X; + SHORT Y; +} COORD; + +typedef struct _SMALL_RECT { + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; +} SMALL_RECT, *PSMALL_RECT; + + +typedef +VOID +(*PTIMERAPCROUTINE)( + LPVOID lpArgToCompletionRoutine, + DWORD dwTimerLowValue, + DWORD dwTimerHighValue + ); + +#include + +#endif /* __INCLUDE_ACPI_TYPES_H */ + +#endif + diff --git a/drivers/bus/acpi/makefile b/drivers/bus/acpi/makefile new file mode 100644 index 0000000..49cfea6 --- /dev/null +++ b/drivers/bus/acpi/makefile @@ -0,0 +1,246 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = acpi + +TARGET_CFLAGS = -I./include -I./ospm/include + +OBJECTS_PATH = objects + +TARGET_OBJECTS = $(OBJECTS_PATH)/$(TARGET_NAME).o + +TARGET_CLEAN = \ + $(OBJECTS_PATH)/*.o \ + dispatcher/*.o \ + events/*.o \ + executer/*.o \ + hardware/*.o \ + namespace/*.o \ + ospm/*.o \ + ospm/busmgr/*.o \ + parser/*.o \ + resource/*.o \ + tables/*.o \ + utils/*.o + + +OBJECTS_OSPM_BUSMGR = \ + ospm/busmgr/bm.o \ + ospm/busmgr/bmnotify.o \ + ospm/busmgr/bmpm.o \ + ospm/busmgr/bmpower.o \ + ospm/busmgr/bmrequest.o \ + ospm/busmgr/bmsearch.o \ + ospm/busmgr/bmutils.o \ + ospm/busmgr/bmxface.o + +OBJECTS_OSPM = \ + $(OBJECTS_OSPM_BUSMGR) \ + ospm/acpienum.o \ + ospm/acpisys.o \ + ospm/bn.o \ + ospm/fdo.o \ + ospm/osl.o \ + ospm/pdo.o + +OBJECTS_DISPATCHER = \ + dispatcher/dsfield.o \ + dispatcher/dsmethod.o \ + dispatcher/dsmthdat.o \ + dispatcher/dsobject.o \ + dispatcher/dsopcode.o \ + dispatcher/dsutils.o \ + dispatcher/dswexec.o \ + dispatcher/dswload.o \ + dispatcher/dswscope.o \ + dispatcher/dswstate.o + +OBJECTS_EVENTS = \ + events/evevent.o \ + events/evmisc.o \ + events/evregion.o \ + events/evrgnini.o \ + events/evsci.o \ + events/evxface.o \ + events/evxfevnt.o \ + events/evxfregn.o + +OBJECTS_EXECUTER = \ + executer/amconfig.o \ + executer/amconvrt.o \ + executer/amcreate.o \ + executer/amdump.o \ + executer/amdyadic.o \ + executer/amfield.o \ + executer/amfldio.o \ + executer/ammisc.o \ + executer/ammonad.o \ + executer/ammutex.o \ + executer/amnames.o \ + executer/amprep.o \ + executer/amregion.o \ + executer/amresnte.o \ + executer/amresolv.o \ + executer/amresop.o \ + executer/amstore.o \ + executer/amstoren.o \ + executer/amstorob.o \ + executer/amsystem.o \ + executer/amutils.o \ + executer/amxface.o + +OBJECTS_HARDWARE = \ + hardware/hwacpi.o \ + hardware/hwgpe.o \ + hardware/hwregs.o \ + hardware/hwsleep.o \ + hardware/hwtimer.o + +OBJECTS_NAMESPACE = \ + namespace/nsaccess.o \ + namespace/nsalloc.o \ + namespace/nseval.o \ + namespace/nsinit.o \ + namespace/nsload.o \ + namespace/nsnames.o \ + namespace/nsobject.o \ + namespace/nssearch.o \ + namespace/nsutils.o \ + namespace/nswalk.o \ + namespace/nsxfname.o \ + namespace/nsxfobj.o + +OBJECTS_PARSER = \ + parser/psargs.o \ + parser/psopcode.o \ + parser/psparse.o \ + parser/psscope.o \ + parser/pstree.o \ + parser/psutils.o \ + parser/pswalk.o \ + parser/psxface.o + +OBJECTS_RESOURCE = \ + resource/rsaddr.o \ + resource/rscalc.o \ + resource/rscreate.o \ + resource/rsdump.o \ + resource/rsio.o \ + resource/rsirq.o \ + resource/rslist.o \ + resource/rsmemory.o \ + resource/rsmisc.o \ + resource/rsutils.o \ + resource/rsxface.o + +OBJECTS_TABLES = \ + tables/tbconvrt.o \ + tables/tbget.o \ + tables/tbinstal.o \ + tables/tbutils.o \ + tables/tbxface.o \ + tables/tbxfroot.o + +OBJECTS_UTILS = \ + utils/cmalloc.o \ + utils/cmclib.o \ + utils/cmcopy.o \ + utils/cmdebug.o \ + utils/cmdelete.o \ + utils/cmeval.o \ + utils/cmglobal.o \ + utils/cminit.o \ + utils/cmobject.o \ + utils/cmutils.o \ + utils/cmxface.o + + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + + +# +# Build intermediate objects +# +$(OBJECTS_PATH)/ospm.o: $(OBJECTS_OSPM) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/ospm.o \ + $(OBJECTS_OSPM) + +$(OBJECTS_PATH)/dispatcher.o: $(OBJECTS_DISPATCHER) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/dispatcher.o \ + $(OBJECTS_DISPATCHER) + +$(OBJECTS_PATH)/events.o: $(OBJECTS_EVENTS) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/events.o \ + $(OBJECTS_EVENTS) + +$(OBJECTS_PATH)/executer.o: $(OBJECTS_EXECUTER) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/executer.o \ + $(OBJECTS_EXECUTER) + +$(OBJECTS_PATH)/hardware.o: $(OBJECTS_HARDWARE) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/hardware.o \ + $(OBJECTS_HARDWARE) + +$(OBJECTS_PATH)/namespace.o: $(OBJECTS_NAMESPACE) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/namespace.o \ + $(OBJECTS_NAMESPACE) + +$(OBJECTS_PATH)/parser.o: $(OBJECTS_PARSER) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/parser.o \ + $(OBJECTS_PARSER) + +$(OBJECTS_PATH)/resource.o: $(OBJECTS_RESOURCE) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/resource.o \ + $(OBJECTS_RESOURCE) + +$(OBJECTS_PATH)/tables.o: $(OBJECTS_TABLES) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/tables.o \ + $(OBJECTS_TABLES) + +$(OBJECTS_PATH)/utils.o: $(OBJECTS_UTILS) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/utils.o \ + $(OBJECTS_UTILS) + + +OBJECTS = \ + $(OBJECTS_PATH)/ospm.o \ + $(OBJECTS_PATH)/dispatcher.o \ + $(OBJECTS_PATH)/events.o \ + $(OBJECTS_PATH)/executer.o \ + $(OBJECTS_PATH)/hardware.o \ + $(OBJECTS_PATH)/namespace.o \ + $(OBJECTS_PATH)/parser.o \ + $(OBJECTS_PATH)/resource.o \ + $(OBJECTS_PATH)/tables.o \ + $(OBJECTS_PATH)/utils.o + +$(OBJECTS_PATH)/$(TARGET_NAME).o: $(OBJECTS_PATH) $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(OBJECTS_PATH)/$(TARGET_NAME).o + +$(OBJECTS_PATH): + mkdir $(OBJECTS_PATH) diff --git a/drivers/bus/acpi/namespace/.cvsignore b/drivers/bus/acpi/namespace/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/namespace/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/namespace/nsaccess.c b/drivers/bus/acpi/namespace/nsaccess.c new file mode 100644 index 0000000..413dd0d --- /dev/null +++ b/drivers/bus/acpi/namespace/nsaccess.c @@ -0,0 +1,551 @@ +/******************************************************************************* + * + * Module Name: nsaccess - Top-level functions for accessing ACPI namespace + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsaccess") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_root_initialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Allocate and initialize the default root named objects + * + * MUTEX: Locks namespace for entire execution + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_root_initialize (void) +{ + ACPI_STATUS status = AE_OK; + PREDEFINED_NAMES *init_val = NULL; + ACPI_NAMESPACE_NODE *new_node; + ACPI_OPERAND_OBJECT *obj_desc; + + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* + * The global root ptr is initially NULL, so a non-NULL value indicates + * that Acpi_ns_root_initialize() has already been called; just return. + */ + + if (acpi_gbl_root_node) { + status = AE_OK; + goto unlock_and_exit; + } + + + /* + * Tell the rest of the subsystem that the root is initialized + * (This is OK because the namespace is locked) + */ + + acpi_gbl_root_node = &acpi_gbl_root_node_struct; + + + /* Enter the pre-defined names in the name table */ + + for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { + status = acpi_ns_lookup (NULL, init_val->name, + (OBJECT_TYPE_INTERNAL) init_val->type, + IMODE_LOAD_PASS2, NS_NO_UPSEARCH, + NULL, &new_node); + + + /* + * Name entered successfully. + * If entry in Pre_defined_names[] specifies an + * initial value, create the initial value. + */ + + if (init_val->val) { + /* + * Entry requests an initial value, allocate a + * descriptor for it. + */ + + obj_desc = acpi_cm_create_internal_object ( + (OBJECT_TYPE_INTERNAL) init_val->type); + + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* + * Convert value string from table entry to + * internal representation. Only types actually + * used for initial values are implemented here. + */ + + switch (init_val->type) { + + case ACPI_TYPE_INTEGER: + + obj_desc->integer.value = + (ACPI_INTEGER) STRTOUL (init_val->val, NULL, 10); + break; + + + case ACPI_TYPE_STRING: + + obj_desc->string.length = STRLEN (init_val->val); + + /* + * Allocate a buffer for the string. All + * String.Pointers must be allocated buffers! + * (makes deletion simpler) + */ + obj_desc->string.pointer = acpi_cm_allocate ( + (obj_desc->string.length + 1)); + if (!obj_desc->string.pointer) { + acpi_cm_remove_reference (obj_desc); + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + STRCPY (obj_desc->string.pointer, init_val->val); + break; + + + case ACPI_TYPE_MUTEX: + + obj_desc->mutex.sync_level = + (u16) STRTOUL (init_val->val, NULL, 10); + + if (STRCMP (init_val->name, "_GL_") == 0) { + /* + * Create a counting semaphore for the + * global lock + */ + status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, + 1, &obj_desc->mutex.semaphore); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + /* + * We just created the mutex for the + * global lock, save it + */ + + acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore; + } + + else { + /* Create a mutex */ + + status = acpi_os_create_semaphore (1, 1, + &obj_desc->mutex.semaphore); + + if (ACPI_FAILURE (status)) { + goto unlock_and_exit; + } + } + break; + + + default: + REPORT_ERROR (("Unsupported initial type value %X\n", + init_val->type)); + acpi_cm_remove_reference (obj_desc); + obj_desc = NULL; + continue; + } + + /* Store pointer to value descriptor in the Node */ + + acpi_ns_attach_object (new_node, obj_desc, obj_desc->common.type); + } + } + + +unlock_and_exit: + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_lookup + * + * PARAMETERS: Prefix_node - Search scope if name is not fully qualified + * Pathname - Search pathname, in internal format + * (as represented in the AML stream) + * Type - Type associated with name + * Interpreter_mode - IMODE_LOAD_PASS2 => add name if not found + * Flags - Flags describing the search restrictions + * Walk_state - Current state of the walk + * Return_node - Where the Node is placed (if found + * or created successfully) + * + * RETURN: Status + * + * DESCRIPTION: Find or enter the passed name in the name space. + * Log an error if name not found in Exec mode. + * + * MUTEX: Assumes namespace is locked. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_lookup ( + ACPI_GENERIC_STATE *scope_info, + NATIVE_CHAR *pathname, + OBJECT_TYPE_INTERNAL type, + OPERATING_MODE interpreter_mode, + u32 flags, + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE **return_node) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *prefix_node; + ACPI_NAMESPACE_NODE *current_node = NULL; + ACPI_NAMESPACE_NODE *scope_to_push = NULL; + ACPI_NAMESPACE_NODE *this_node = NULL; + u32 num_segments; + ACPI_NAME simple_name; + u8 null_name_path = FALSE; + OBJECT_TYPE_INTERNAL type_to_check_for; + OBJECT_TYPE_INTERNAL this_search_type; + u32 local_flags = flags & ~NS_ERROR_IF_FOUND; + + + if (!return_node) { + return (AE_BAD_PARAMETER); + } + + + acpi_gbl_ns_lookup_count++; + + *return_node = ENTRY_NOT_FOUND; + + + if (!acpi_gbl_root_node) { + return (AE_NO_NAMESPACE); + } + + /* + * Get the prefix scope. + * A null scope means use the root scope + */ + + if ((!scope_info) || + (!scope_info->scope.node)) { + prefix_node = acpi_gbl_root_node; + } + else { + prefix_node = scope_info->scope.node; + } + + + /* + * This check is explicitly split provide relax the Type_to_check_for + * conditions for Bank_field_defn. Originally, both Bank_field_defn and + * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION, + * but the Bank_field_defn may also check for a Field definition as well + * as an Operation_region. + */ + + if (INTERNAL_TYPE_DEF_FIELD_DEFN == type) { + /* Def_field_defn defines fields in a Region */ + + type_to_check_for = ACPI_TYPE_REGION; + } + + else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) { + /* Bank_field_defn defines data fields in a Field Object */ + + type_to_check_for = ACPI_TYPE_ANY; + } + + else { + type_to_check_for = type; + } + + + /* TBD: [Restructure] - Move the pathname stuff into a new procedure */ + + /* Examine the name pointer */ + + if (!pathname) { + /* 8-12-98 ASL Grammar Update supports null Name_path */ + + null_name_path = TRUE; + num_segments = 0; + this_node = acpi_gbl_root_node; + + } + + else { + /* + * Valid name pointer (Internal name format) + * + * Check for prefixes. As represented in the AML stream, a + * Pathname consists of an optional scope prefix followed by + * a segment part. + * + * If present, the scope prefix is either a Root_prefix (in + * which case the name is fully qualified), or zero or more + * Parent_prefixes (in which case the name's scope is relative + * to the current scope). + * + * The segment part consists of either: + * - A single 4-byte name segment, or + * - A Dual_name_prefix followed by two 4-byte name segments, or + * - A Multi_name_prefix_op, followed by a byte indicating the + * number of segments and the segments themselves. + */ + + if (*pathname == AML_ROOT_PREFIX) { + /* Pathname is fully qualified, look in root name table */ + + current_node = acpi_gbl_root_node; + + /* point to segment part */ + + pathname++; + + /* Direct reference to root, "\" */ + + if (!(*pathname)) { + this_node = acpi_gbl_root_node; + goto check_for_new_scope_and_exit; + } + } + + else { + /* Pathname is relative to current scope, start there */ + + current_node = prefix_node; + + /* + * Handle up-prefix (carat). More than one prefix + * is supported + */ + + while (*pathname == AML_PARENT_PREFIX) { + /* Point to segment part or next Parent_prefix */ + + pathname++; + + /* Backup to the parent's scope */ + + this_node = acpi_ns_get_parent_object (current_node); + if (!this_node) { + /* Current scope has no parent scope */ + + REPORT_ERROR ( + ("Too many parent prefixes (^) - reached root\n")); + return (AE_NOT_FOUND); + } + + current_node = this_node; + } + } + + + /* + * Examine the name prefix opcode, if any, + * to determine the number of segments + */ + + if (*pathname == AML_DUAL_NAME_PREFIX) { + num_segments = 2; + + /* point to first segment */ + + pathname++; + + } + + else if (*pathname == AML_MULTI_NAME_PREFIX_OP) { + num_segments = (u32)* (u8 *) ++pathname; + + /* point to first segment */ + + pathname++; + + } + + else { + /* + * No Dual or Multi prefix, hence there is only one + * segment and Pathname is already pointing to it. + */ + num_segments = 1; + + } + + } + + + /* + * Search namespace for each segment of the name. + * Loop through and verify/add each name segment. + */ + + + while (num_segments-- && current_node) { + /* + * Search for the current name segment under the current + * named object. The Type is significant only at the last (topmost) + * level. (We don't care about the types along the path, only + * the type of the final target object.) + */ + this_search_type = ACPI_TYPE_ANY; + if (!num_segments) { + this_search_type = type; + local_flags = flags; + } + + /* Pluck one ACPI name from the front of the pathname */ + + MOVE_UNALIGNED32_TO_32 (&simple_name, pathname); + + /* Try to find the ACPI name */ + + status = acpi_ns_search_and_enter (simple_name, walk_state, + current_node, interpreter_mode, + this_search_type, local_flags, + &this_node); + + if (ACPI_FAILURE (status)) { + if (status == AE_NOT_FOUND) { + /* Name not found in ACPI namespace */ + + } + + return (status); + } + + + /* + * If 1) This is the last segment (Num_segments == 0) + * 2) and looking for a specific type + * (Not checking for TYPE_ANY) + * 3) Which is not an alias + * 4) which is not a local type (TYPE_DEF_ANY) + * 5) which is not a local type (TYPE_SCOPE) + * 6) which is not a local type (TYPE_INDEX_FIELD_DEFN) + * 7) and type of object is known (not TYPE_ANY) + * 8) and object does not match request + * + * Then we have a type mismatch. Just warn and ignore it. + */ + if ((num_segments == 0) && + (type_to_check_for != ACPI_TYPE_ANY) && + (type_to_check_for != INTERNAL_TYPE_ALIAS) && + (type_to_check_for != INTERNAL_TYPE_DEF_ANY) && + (type_to_check_for != INTERNAL_TYPE_SCOPE) && + (type_to_check_for != INTERNAL_TYPE_INDEX_FIELD_DEFN) && + (this_node->type != ACPI_TYPE_ANY) && + (this_node->type != type_to_check_for)) { + /* Complain about a type mismatch */ + + REPORT_WARNING ( + ("Ns_lookup: %4.4s, type %X, checking for type %X\n", + &simple_name, this_node->type, type_to_check_for)); + } + + /* + * If this is the last name segment and we are not looking for a + * specific type, but the type of found object is known, use that type + * to see if it opens a scope. + */ + + if ((0 == num_segments) && (ACPI_TYPE_ANY == type)) { + type = this_node->type; + } + + if ((num_segments || acpi_ns_opens_scope (type)) && + (this_node->child == NULL)) { + /* + * More segments or the type implies enclosed scope, + * and the next scope has not been allocated. + */ + + } + + current_node = this_node; + + /* point to next name segment */ + + pathname += ACPI_NAME_SIZE; + } + + + /* + * Always check if we need to open a new scope + */ + +check_for_new_scope_and_exit: + + if (!(flags & NS_DONT_OPEN_SCOPE) && (walk_state)) { + /* + * If entry is a type which opens a scope, + * push the new scope on the scope stack. + */ + + if (acpi_ns_opens_scope (type_to_check_for)) { + /* 8-12-98 ASL Grammar Update supports null Name_path */ + + if (null_name_path) { + /* TBD: [Investigate] - is this the correct thing to do? */ + + scope_to_push = NULL; + } + else { + scope_to_push = this_node; + } + + status = acpi_ds_scope_stack_push (scope_to_push, type, + walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + } + } + + *return_node = this_node; + return (AE_OK); +} + diff --git a/drivers/bus/acpi/namespace/nsalloc.c b/drivers/bus/acpi/namespace/nsalloc.c new file mode 100644 index 0000000..4f21495 --- /dev/null +++ b/drivers/bus/acpi/namespace/nsalloc.c @@ -0,0 +1,566 @@ +/******************************************************************************* + * + * Module Name: nsalloc - Namespace allocation and deletion utilities + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsalloc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_create_node + * + * PARAMETERS: + * + * RETURN: None + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_NAMESPACE_NODE * +acpi_ns_create_node ( + u32 acpi_name) +{ + ACPI_NAMESPACE_NODE *node; + + + node = acpi_cm_callocate (sizeof (ACPI_NAMESPACE_NODE)); + if (!node) { + return (NULL); + } + + INCREMENT_NAME_TABLE_METRICS (sizeof (ACPI_NAMESPACE_NODE)); + + node->data_type = ACPI_DESC_TYPE_NAMED; + node->name = acpi_name; + node->reference_count = 1; + + return (node); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_delete_node + * + * PARAMETERS: + * + * RETURN: None + * + * DESCRIPTION: + * + ******************************************************************************/ + +void +acpi_ns_delete_node ( + ACPI_NAMESPACE_NODE *node) +{ + ACPI_NAMESPACE_NODE *parent_node; + ACPI_NAMESPACE_NODE *prev_node; + ACPI_NAMESPACE_NODE *next_node; + + + parent_node = acpi_ns_get_parent_object (node); + + prev_node = NULL; + next_node = parent_node->child; + + while (next_node != node) { + prev_node = next_node; + next_node = prev_node->peer; + } + + if (prev_node) { + prev_node->peer = next_node->peer; + if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + prev_node->flags |= ANOBJ_END_OF_PEER_LIST; + } + } + else { + parent_node->child = next_node->peer; + } + + + DECREMENT_NAME_TABLE_METRICS (sizeof (ACPI_NAMESPACE_NODE)); + + /* + * Detach an object if there is one + */ + + if (node->object) { + acpi_ns_detach_object (node); + } + + acpi_cm_free (node); + + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_install_node + * + * PARAMETERS: Walk_state - Current state of the walk + * Parent_node - The parent of the new Node + * Node - The new Node to install + * Type - ACPI object type of the new Node + * + * RETURN: None + * + * DESCRIPTION: Initialize a new entry within a namespace table. + * + ******************************************************************************/ + +void +acpi_ns_install_node ( + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE *parent_node, /* Parent */ + ACPI_NAMESPACE_NODE *node, /* New Child*/ + OBJECT_TYPE_INTERNAL type) +{ + u16 owner_id = TABLE_ID_DSDT; + ACPI_NAMESPACE_NODE *child_node; + + + /* + * Get the owner ID from the Walk state + * The owner ID is used to track table deletion and + * deletion of objects created by methods + */ + if (walk_state) { + owner_id = walk_state->owner_id; + } + + + /* link the new entry into the parent and existing children */ + + /* TBD: Could be first, last, or alphabetic */ + + child_node = parent_node->child; + if (!child_node) { + parent_node->child = node; + } + + else { + while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { + child_node = child_node->peer; + } + + child_node->peer = node; + + /* Clear end-of-list flag */ + + child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; + } + + /* Init the new entry */ + + node->owner_id = owner_id; + node->flags |= ANOBJ_END_OF_PEER_LIST; + node->peer = parent_node; + + + /* + * If adding a name with unknown type, or having to + * add the region in order to define fields in it, we + * have a forward reference. + */ + + if ((ACPI_TYPE_ANY == type) || + (INTERNAL_TYPE_DEF_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) { + /* + * We don't want to abort here, however! + * We will fill in the actual type when the + * real definition is found later. + */ + + } + + /* + * The Def_field_defn and Bank_field_defn cases are actually + * looking up the Region in which the field will be defined + */ + + if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) { + type = ACPI_TYPE_REGION; + } + + /* + * Scope, Def_any, and Index_field_defn are bogus "types" which do + * not actually have anything to do with the type of the name + * being looked up. Save any other value of Type as the type of + * the entry. + */ + + if ((type != INTERNAL_TYPE_SCOPE) && + (type != INTERNAL_TYPE_DEF_ANY) && + (type != INTERNAL_TYPE_INDEX_FIELD_DEFN)) { + node->type = (u8) type; + } + + /* + * Increment the reference count(s) of all parents up to + * the root! + */ + + while ((node = acpi_ns_get_parent_object (node)) != NULL) { + node->reference_count++; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_delete_children + * + * PARAMETERS: Parent_node - Delete this objects children + * + * RETURN: None. + * + * DESCRIPTION: Delete all children of the parent object. Deletes a + * "scope". + * + ******************************************************************************/ + +void +acpi_ns_delete_children ( + ACPI_NAMESPACE_NODE *parent_node) +{ + ACPI_NAMESPACE_NODE *child_node; + ACPI_NAMESPACE_NODE *next_node; + u8 flags; + + + if (!parent_node) { + return; + } + + /* If no children, all done! */ + + child_node = parent_node->child; + if (!child_node) { + return; + } + + /* + * Deallocate all children at this level + */ + do { + /* Get the things we need */ + + next_node = child_node->peer; + flags = child_node->flags; + + /* Grandchildren should have all been deleted already */ + + + /* Now we can free this child object */ + + DECREMENT_NAME_TABLE_METRICS (sizeof (ACPI_NAMESPACE_NODE)); + + /* + * Detach an object if there is one + */ + + if (child_node->object) { + acpi_ns_detach_object (child_node); + } + + acpi_cm_free (child_node); + + /* And move on to the next child in the list */ + + child_node = next_node; + + } while (!(flags & ANOBJ_END_OF_PEER_LIST)); + + + /* Clear the parent's child pointer */ + + parent_node->child = NULL; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_delete_namespace_subtree + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects + * stored within the subtree. Scope tables are deleted also + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_delete_namespace_subtree ( + ACPI_NAMESPACE_NODE *parent_node) +{ + ACPI_NAMESPACE_NODE *child_node; + ACPI_OPERAND_OBJECT *obj_desc; + u32 level; + + + if (!parent_node) { + return (AE_OK); + } + + + child_node = 0; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + + while (level > 0) { + /* + * Get the next typed object in this scope. + * Null returned if not found + */ + + child_node = acpi_ns_get_next_object (ACPI_TYPE_ANY, parent_node, + child_node); + if (child_node) { + /* + * Found an object - delete the object within + * the Value field + */ + + obj_desc = acpi_ns_get_attached_object (child_node); + if (obj_desc) { + acpi_ns_detach_object (child_node); + acpi_cm_remove_reference (obj_desc); + } + + + /* Check if this object has any children */ + + if (acpi_ns_get_next_object (ACPI_TYPE_ANY, child_node, 0)) { + /* + * There is at least one child of this object, + * visit the object + */ + + level++; + parent_node = child_node; + child_node = 0; + } + } + + else { + /* + * No more children in this object. + * We will move up to the grandparent. + */ + level--; + + /* + * Now delete all of the children of this parent + * all at the same time. + */ + acpi_ns_delete_children (parent_node); + + /* New "last child" is this parent object */ + + child_node = parent_node; + + /* Now we can move up the tree to the grandparent */ + + parent_node = acpi_ns_get_parent_object (parent_node); + } + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_remove_reference + * + * PARAMETERS: Node - Named object whose reference count is to be + * decremented + * + * RETURN: None. + * + * DESCRIPTION: Remove a Node reference. Decrements the reference count + * of all parent Nodes up to the root. Any object along + * the way that reaches zero references is freed. + * + ******************************************************************************/ + +static void +acpi_ns_remove_reference ( + ACPI_NAMESPACE_NODE *node) +{ + ACPI_NAMESPACE_NODE *next_node; + + + /* + * Decrement the reference count(s) of this object and all + * objects up to the root, Delete anything with zero remaining references. + */ + next_node = node; + while (next_node) { + /* Decrement the reference count on this object*/ + + next_node->reference_count--; + + /* Delete the object if no more references */ + + if (!next_node->reference_count) { + /* Delete all children and delete the object */ + + acpi_ns_delete_children (next_node); + acpi_ns_delete_node (next_node); + } + + /* Move up to parent */ + + next_node = acpi_ns_get_parent_object (next_node); + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_delete_namespace_by_owner + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete entries within the namespace that are owned by a + * specific ID. Used to delete entire ACPI tables. All + * reference counts are updated. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_delete_namespace_by_owner ( + u16 owner_id) +{ + ACPI_NAMESPACE_NODE *child_node; + u32 level; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *parent_node; + + + parent_node = acpi_gbl_root_node; + child_node = 0; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + + while (level > 0) { + /* + * Get the next typed object in this scope. + * Null returned if not found + */ + + child_node = acpi_ns_get_next_object (ACPI_TYPE_ANY, parent_node, + child_node); + + if (child_node) { + if (child_node->owner_id == owner_id) { + /* + * Found an object - delete the object within + * the Value field + */ + + obj_desc = acpi_ns_get_attached_object (child_node); + if (obj_desc) { + acpi_ns_detach_object (child_node); + acpi_cm_remove_reference (obj_desc); + } + } + + /* Check if this object has any children */ + + if (acpi_ns_get_next_object (ACPI_TYPE_ANY, child_node, 0)) { + /* + * There is at least one child of this object, + * visit the object + */ + + level++; + parent_node = child_node; + child_node = 0; + } + + else if (child_node->owner_id == owner_id) { + acpi_ns_remove_reference (child_node); + } + } + + else { + /* + * No more children in this object. Move up to grandparent. + */ + level--; + + if (level != 0) { + if (parent_node->owner_id == owner_id) { + acpi_ns_remove_reference (parent_node); + } + } + + /* New "last child" is this parent object */ + + child_node = parent_node; + + /* Now we can move up the tree to the grandparent */ + + parent_node = acpi_ns_get_parent_object (parent_node); + } + } + + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/namespace/nseval.c b/drivers/bus/acpi/namespace/nseval.c new file mode 100644 index 0000000..7b4bf53 --- /dev/null +++ b/drivers/bus/acpi/namespace/nseval.c @@ -0,0 +1,506 @@ +/******************************************************************************* + * + * Module Name: nseval - Object evaluation interfaces -- includes control + * method lookup and execution. + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acparser.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nseval") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_evaluate_relative + * + * PARAMETERS: Handle - The relative containing object + * *Pathname - Name of method to execute, If NULL, the + * handle is the object to execute + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and execute the requested method using the handle as a + * scope + * + * MUTEX: Locks Namespace + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_evaluate_relative ( + ACPI_NAMESPACE_NODE *handle, + NATIVE_CHAR *pathname, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_object) +{ + ACPI_NAMESPACE_NODE *prefix_node; + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node = NULL; + NATIVE_CHAR *internal_path = NULL; + ACPI_GENERIC_STATE scope_info; + + + /* + * Must have a valid object handle + */ + if (!handle) { + return (AE_BAD_PARAMETER); + } + + /* Build an internal name string for the method */ + + status = acpi_ns_internalize_name (pathname, &internal_path); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Get the prefix handle and Node */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + prefix_node = acpi_ns_convert_handle_to_entry (handle); + if (!prefix_node) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + status = AE_BAD_PARAMETER; + goto cleanup; + } + + /* Lookup the name in the namespace */ + + scope_info.scope.node = prefix_node; + status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY, + IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, + &node); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * Now that we have a handle to the object, we can attempt + * to evaluate it. + */ + + status = acpi_ns_evaluate_by_handle (node, params, return_object); + +cleanup: + + /* Cleanup */ + + acpi_cm_free (internal_path); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_evaluate_by_name + * + * PARAMETERS: Pathname - Fully qualified pathname to the object + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * + * RETURN: Status + * + * DESCRIPTION: Find and execute the requested method passing the given + * parameters + * + * MUTEX: Locks Namespace + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_evaluate_by_name ( + NATIVE_CHAR *pathname, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_object) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node = NULL; + NATIVE_CHAR *internal_path = NULL; + + + /* Build an internal name string for the method */ + + status = acpi_ns_internalize_name (pathname, &internal_path); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Lookup the name in the namespace */ + + status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, + IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, + &node); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * Now that we have a handle to the object, we can attempt + * to evaluate it. + */ + + status = acpi_ns_evaluate_by_handle (node, params, return_object); + + +cleanup: + + /* Cleanup */ + + if (internal_path) { + acpi_cm_free (internal_path); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_evaluate_by_handle + * + * PARAMETERS: Handle - Method Node to execute + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Execute the requested method passing the given parameters + * + * MUTEX: Locks Namespace + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_evaluate_by_handle ( + ACPI_NAMESPACE_NODE *handle, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_object) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *local_return_object; + + + /* Check if namespace has been initialized */ + + if (!acpi_gbl_root_node) { + return (AE_NO_NAMESPACE); + } + + /* Parameter Validation */ + + if (!handle) { + return (AE_BAD_PARAMETER); + } + + if (return_object) { + /* Initialize the return value to an invalid object */ + + *return_object = NULL; + } + + /* Get the prefix handle and Node */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + node = acpi_ns_convert_handle_to_entry (handle); + if (!node) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + + /* + * Two major cases here: + * 1) The object is an actual control method -- execute it. + * 2) The object is not a method -- just return it's current + * value + * + * In both cases, the namespace is unlocked by the + * Acpi_ns* procedure + */ + if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) { + /* + * Case 1) We have an actual control method to execute + */ + status = acpi_ns_execute_control_method (node, params, + &local_return_object); + } + + else { + /* + * Case 2) Object is NOT a method, just return its + * current value + */ + status = acpi_ns_get_object_value (node, &local_return_object); + } + + + /* + * Check if there is a return value on the stack that must + * be dealt with + */ + if (status == AE_CTRL_RETURN_VALUE) { + /* + * If the Method returned a value and the caller + * provided a place to store a returned value, Copy + * the returned value to the object descriptor provided + * by the caller. + */ + if (return_object) { + /* + * Valid return object, copy the pointer to + * the returned object + */ + *return_object = local_return_object; + } + + + /* Map AE_RETURN_VALUE to AE_OK, we are done with it */ + + if (status == AE_CTRL_RETURN_VALUE) { + status = AE_OK; + } + } + + /* + * Namespace was unlocked by the handling Acpi_ns* function, + * so we just return + */ + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_execute_control_method + * + * PARAMETERS: Method_node - The object/method + * **Params - List of parameters to pass to the method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * **Return_obj_desc - List of result objects to be returned + * from the method. + * + * RETURN: Status + * + * DESCRIPTION: Execute the requested method passing the given parameters + * + * MUTEX: Assumes namespace is locked + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_execute_control_method ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + + + /* Verify that there is a method associated with this object */ + + obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node); + if (!obj_desc) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_ERROR); + } + + + /* + * Unlock the namespace before execution. This allows namespace access + * via the external Acpi* interfaces while a method is being executed. + * However, any namespace deletion must acquire both the namespace and + * interpreter locks to ensure that no thread is using the portion of the + * namespace that is being deleted. + */ + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* + * Execute the method via the interpreter + */ + status = acpi_aml_execute_method (method_node, params, return_obj_desc); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_get_object_value + * + * PARAMETERS: Node - The object + * + * RETURN: Status + * + * DESCRIPTION: Return the current value of the object + * + * MUTEX: Assumes namespace is locked + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_get_object_value ( + ACPI_NAMESPACE_NODE *node, + ACPI_OPERAND_OBJECT **return_obj_desc) +{ + ACPI_STATUS status = AE_OK; + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *val_desc; + + + /* + * We take the value from certain objects directly + */ + + if ((node->type == ACPI_TYPE_PROCESSOR) || + (node->type == ACPI_TYPE_POWER)) { + /* + * Create a Reference object to contain the object + */ + obj_desc = acpi_cm_create_internal_object (node->type); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* + * Get the attached object + */ + + val_desc = acpi_ns_get_attached_object (node); + if (!val_desc) { + status = AE_NULL_OBJECT; + goto unlock_and_exit; + } + + /* + * Just copy from the original to the return object + * + * TBD: [Future] - need a low-level object copy that handles + * the reference count automatically. (Don't want to copy it) + */ + + MEMCPY (obj_desc, val_desc, sizeof (ACPI_OPERAND_OBJECT)); + obj_desc->common.reference_count = 1; + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + + /* + * Other objects require a reference object wrapper which we + * then attempt to resolve. + */ + else { + /* Create an Reference object to contain the object */ + + obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE); + if (!obj_desc) { + status = AE_NO_MEMORY; + goto unlock_and_exit; + } + + /* Construct a descriptor pointing to the name */ + + obj_desc->reference.opcode = (u8) AML_NAME_OP; + obj_desc->reference.object = (void *) node; + + /* + * Use Resolve_to_value() to get the associated value. This call + * always deletes Obj_desc (allocated above). + * + * NOTE: we can get away with passing in NULL for a walk state + * because Obj_desc is guaranteed to not be a reference to either + * a method local or a method argument + * + * Even though we do not directly invoke the interpreter + * for this, we must enter it because we could access an opregion. + * The opregion access code assumes that the interpreter + * is locked. + * + * We must release the namespace lock before entering the + * intepreter. + */ + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + status = acpi_aml_enter_interpreter (); + if (ACPI_SUCCESS (status)) { + status = acpi_aml_resolve_to_value (&obj_desc, NULL); + + acpi_aml_exit_interpreter (); + } + } + + /* + * If Acpi_aml_resolve_to_value() succeeded, the return value was + * placed in Obj_desc. + */ + + if (ACPI_SUCCESS (status)) { + status = AE_CTRL_RETURN_VALUE; + + *return_obj_desc = obj_desc; + } + + /* Namespace is unlocked */ + + return (status); + + +unlock_and_exit: + + /* Unlock the namespace */ + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} diff --git a/drivers/bus/acpi/namespace/nsinit.c b/drivers/bus/acpi/namespace/nsinit.c new file mode 100644 index 0000000..7259ef4 --- /dev/null +++ b/drivers/bus/acpi/namespace/nsinit.c @@ -0,0 +1,278 @@ +/****************************************************************************** + * + * Module Name: nsinit - namespace initialization + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acdispat.h" + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsinit") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_initialize_objects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Walk the entire namespace and perform any necessary + * initialization on the objects found therein + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_initialize_objects ( + void) +{ + ACPI_STATUS status; + ACPI_INIT_WALK_INFO info; + + + info.field_count = 0; + info.field_init = 0; + info.op_region_count = 0; + info.op_region_init = 0; + info.object_count = 0; + + + /* Walk entire namespace from the supplied root */ + + status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_ns_init_one_object, + &info, NULL); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_initialize_devices + * + * PARAMETERS: None + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices. + * This means running _INI on all present devices. + * + * Note: We install PCI config space handler on region access, + * not here. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_initialize_devices ( + void) +{ + ACPI_STATUS status; + ACPI_DEVICE_WALK_INFO info; + + + info.device_count = 0; + info.num_STA = 0; + info.num_INI = 0; + + + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, FALSE, acpi_ns_init_one_device, &info, NULL); + + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_init_one_object + * + * PARAMETERS: Obj_handle - Node + * Level - Current nesting level + * Context - Points to a init info struct + * Return_value - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object + * within the namespace. + * + * Currently, the only objects that require initialization are: + * 1) Methods + * 2) Op Regions + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_init_one_object ( + ACPI_HANDLE obj_handle, + u32 level, + void *context, + void **return_value) +{ + OBJECT_TYPE_INTERNAL type; + ACPI_STATUS status; + ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context; + ACPI_NAMESPACE_NODE *node = (ACPI_NAMESPACE_NODE *) obj_handle; + ACPI_OPERAND_OBJECT *obj_desc; + + + info->object_count++; + + + /* And even then, we are only interested in a few object types */ + + type = acpi_ns_get_type (obj_handle); + obj_desc = node->object; + if (!obj_desc) { + return (AE_OK); + } + + switch (type) { + + case ACPI_TYPE_REGION: + + info->op_region_count++; + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + break; + } + + info->op_region_init++; + status = acpi_ds_get_region_arguments (obj_desc); + + + break; + + + case ACPI_TYPE_FIELD_UNIT: + + info->field_count++; + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { + break; + } + + info->field_init++; + status = acpi_ds_get_field_unit_arguments (obj_desc); + + + break; + + default: + break; + } + + /* + * We ignore errors from above, and always return OK, since + * we don't want to abort the walk on a single error. + */ + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_init_one_device + * + * PARAMETERS: WALK_CALLBACK + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: This is called once per device soon after ACPI is enabled + * to initialize each device. It determines if the device is + * present, and if so, calls _INI. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_init_one_device ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node; + u32 flags; + ACPI_DEVICE_WALK_INFO *info = (ACPI_DEVICE_WALK_INFO *) context; + + + + info->device_count++; + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + node = acpi_ns_convert_handle_to_entry (obj_handle); + if (!node) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* + * Run _STA to determine if we can run _INI on the device. + */ + + status = acpi_cm_execute_STA (node, &flags); + if (ACPI_FAILURE (status)) { + /* Ignore error and move on to next device */ + + return (AE_OK); + } + + info->num_STA++; + + if (!(flags & 0x01)) { + /* don't look at children of a not present device */ + return(AE_CTRL_DEPTH); + } + + + /* + * The device is present. Run _INI. + */ + + status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL); + if (AE_NOT_FOUND == status) { + /* No _INI means device requires no initialization */ + status = AE_OK; + } + + else if (ACPI_FAILURE (status)) { + /* Ignore error and move on to next device */ + + } + + else { + /* Count of successful INIs */ + + info->num_INI++; + } + + return (AE_OK); +} diff --git a/drivers/bus/acpi/namespace/nsload.c b/drivers/bus/acpi/namespace/nsload.c new file mode 100644 index 0000000..396020f --- /dev/null +++ b/drivers/bus/acpi/namespace/nsload.c @@ -0,0 +1,528 @@ +/****************************************************************************** + * + * Module Name: nsload - namespace loading/expanding/contracting procedures + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsload") + + +/******************************************************************************* + * + * FUNCTION: Acpi_load_namespace + * + * PARAMETERS: Display_aml_during_load + * + * RETURN: Status + * + * DESCRIPTION: Load the name space from what ever is pointed to by DSDT. + * (DSDT points to either the BIOS or a buffer.) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_load_namespace ( + void) +{ + ACPI_STATUS status; + + + /* There must be at least a DSDT installed */ + + if (acpi_gbl_DSDT == NULL) { + return (AE_NO_ACPI_TABLES); + } + + + /* + * Load the namespace. The DSDT is required, + * but the SSDT and PSDT tables are optional. + */ + + status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Ignore exceptions from these */ + + acpi_ns_load_table_by_type (ACPI_TABLE_SSDT); + acpi_ns_load_table_by_type (ACPI_TABLE_PSDT); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_one_parse_pass + * + * PARAMETERS: + * + * RETURN: Status + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_one_complete_parse ( + u32 pass_number, + ACPI_TABLE_DESC *table_desc) +{ + ACPI_PARSE_DOWNWARDS descending_callback; + ACPI_PARSE_UPWARDS ascending_callback; + ACPI_PARSE_OBJECT *parse_root; + ACPI_STATUS status; + + + switch (pass_number) { + case 1: + descending_callback = acpi_ds_load1_begin_op; + ascending_callback = acpi_ds_load1_end_op; + break; + + case 2: + descending_callback = acpi_ds_load2_begin_op; + ascending_callback = acpi_ds_load2_end_op; + break; + + case 3: + descending_callback = acpi_ds_exec_begin_op; + ascending_callback = acpi_ds_exec_end_op; + break; + + default: + return (AE_BAD_PARAMETER); + } + + /* Create and init a Root Node */ + + parse_root = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!parse_root) { + return (AE_NO_MEMORY); + } + + ((ACPI_PARSE2_OBJECT *) parse_root)->name = ACPI_ROOT_NAME; + + + /* Pass 1: Parse everything except control method bodies */ + + status = acpi_ps_parse_aml (parse_root, table_desc->aml_pointer, + table_desc->aml_length, + ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, + NULL, NULL, NULL, descending_callback, + ascending_callback); + + acpi_ps_delete_parse_tree (parse_root); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_parse_table + * + * PARAMETERS: Table_desc - An ACPI table descriptor for table to parse + * Start_node - Where to enter the table into the namespace + * + * RETURN: Status + * + * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_parse_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMESPACE_NODE *start_node) +{ + ACPI_STATUS status; + + + /* + * AML Parse, pass 1 + * + * In this pass, we load most of the namespace. Control methods + * are not parsed until later. A parse tree is not created. Instead, + * each Parser Op subtree is deleted when it is finished. This saves + * a great deal of memory, and allows a small cache of parse objects + * to service the entire parse. The second pass of the parse then + * performs another complete parse of the AML.. + */ + + status = acpi_ns_one_complete_parse (1, table_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * AML Parse, pass 2 + * + * In this pass, we resolve forward references and other things + * that could not be completed during the first pass. + * Another complete parse of the AML is performed, but the + * overhead of this is compensated for by the fact that the + * parse objects are all cached. + */ + + status = acpi_ns_one_complete_parse (2, table_desc); + if (ACPI_FAILURE (status)) { + return (status); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_load_table + * + * PARAMETERS: *Pcode_addr - Address of pcode block + * Pcode_length - Length of pcode block + * + * RETURN: Status + * + * DESCRIPTION: Load one ACPI table into the namespace + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_load_table ( + ACPI_TABLE_DESC *table_desc, + ACPI_NAMESPACE_NODE *node) +{ + ACPI_STATUS status; + + + if (!table_desc->aml_pointer) { + return (AE_BAD_PARAMETER); + } + + + if (!table_desc->aml_length) { + return (AE_BAD_PARAMETER); + } + + + /* + * Parse the table and load the namespace with all named + * objects found within. Control methods are NOT parsed + * at this time. In fact, the control methods cannot be + * parsed until the entire namespace is loaded, because + * if a control method makes a forward reference (call) + * to another control method, we can't continue parsing + * because we don't know how many arguments to parse next! + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ns_parse_table (table_desc, node->child); + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Now we can parse the control methods. We always parse + * them here for a sanity check, and if configured for + * just-in-time parsing, we delete the control method + * parse trees. + */ + + status = acpi_ds_initialize_objects (table_desc, node); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_load_table_by_type + * + * PARAMETERS: Table_type - Id of the table type to load + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables + * of the given type are loaded. The mechanism allows this + * routine to be called repeatedly. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_load_table_by_type ( + ACPI_TABLE_TYPE table_type) +{ + u32 i; + ACPI_STATUS status = AE_OK; + ACPI_TABLE_HEADER *table_ptr; + ACPI_TABLE_DESC *table_desc; + + + acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + + + /* + * Table types supported are: + * DSDT (one), SSDT/PSDT (multiple) + */ + + switch (table_type) { + + case ACPI_TABLE_DSDT: + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT]; + + /* If table already loaded into namespace, just return */ + + if (table_desc->loaded_into_namespace) { + goto unlock_and_exit; + } + + table_desc->table_id = TABLE_ID_DSDT; + + /* Now load the single DSDT */ + + status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); + if (ACPI_SUCCESS (status)) { + table_desc->loaded_into_namespace = TRUE; + } + + break; + + + case ACPI_TABLE_SSDT: + + /* + * Traverse list of SSDT tables + */ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { + table_ptr = table_desc->pointer; + + /* + * Only attempt to load table if it is not + * already loaded! + */ + + if (!table_desc->loaded_into_namespace) { + status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); + if (ACPI_FAILURE (status)) { + break; + } + + table_desc->loaded_into_namespace = TRUE; + } + + table_desc = table_desc->next; + } + break; + + + case ACPI_TABLE_PSDT: + + /* + * Traverse list of PSDT tables + */ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; + + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { + table_ptr = table_desc->pointer; + + /* Only attempt to load table if it is not already loaded! */ + + if (!table_desc->loaded_into_namespace) { + status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); + if (ACPI_FAILURE (status)) { + break; + } + + table_desc->loaded_into_namespace = TRUE; + } + + table_desc = table_desc->next; + } + + break; + + + default: + status = AE_SUPPORT; + break; + } + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_TABLES); + + return (status); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_delete_subtree + * + * PARAMETERS: Start_handle - Handle in namespace where search begins + * + * RETURNS Status + * + * DESCRIPTION: Walks the namespace starting at the given handle and deletes + * all objects, entries, and scopes in the entire subtree. + * + * TBD: [Investigate] What if any part of this subtree is in use? + * (i.e. on one of the object stacks?) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_delete_subtree ( + ACPI_HANDLE start_handle) +{ + ACPI_STATUS status; + ACPI_HANDLE child_handle; + ACPI_HANDLE parent_handle; + ACPI_HANDLE next_child_handle; + ACPI_HANDLE dummy; + u32 level; + + + parent_handle = start_handle; + child_handle = 0; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up + * to where we started. + */ + + while (level > 0) { + /* Attempt to get the next object in this scope */ + + status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle, + child_handle, &next_child_handle); + + child_handle = next_child_handle; + + + /* Did we get a new object? */ + + if (ACPI_SUCCESS (status)) { + /* Check if this object has any children */ + + if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle, + 0, &dummy))) { + /* + * There is at least one child of this object, + * visit the object + */ + + level++; + parent_handle = child_handle; + child_handle = 0; + } + } + + else { + /* + * No more children in this object, go back up to + * the object's parent + */ + level--; + + /* Delete all children now */ + + acpi_ns_delete_children (child_handle); + + child_handle = parent_handle; + acpi_get_parent (parent_handle, &parent_handle); + } + } + + /* Now delete the starting object, and we are done */ + + acpi_ns_delete_node (child_handle); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_unload_name_space + * + * PARAMETERS: Handle - Root of namespace subtree to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Shrinks the namespace, typically in response to an undocking + * event. Deletes an entire subtree starting from (and + * including) the given handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_unload_namespace ( + ACPI_HANDLE handle) +{ + ACPI_STATUS status; + + + /* Parameter validation */ + + if (!acpi_gbl_root_node) { + return (AE_NO_NAMESPACE); + } + + if (!handle) { + return (AE_BAD_PARAMETER); + } + + + /* This function does the real work */ + + status = acpi_ns_delete_subtree (handle); + + return (status); +} + + diff --git a/drivers/bus/acpi/namespace/nsnames.c b/drivers/bus/acpi/namespace/nsnames.c new file mode 100644 index 0000000..b19c2d2 --- /dev/null +++ b/drivers/bus/acpi/namespace/nsnames.c @@ -0,0 +1,249 @@ +/******************************************************************************* + * + * Module Name: nsnames - Name manipulation and search + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsnames") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_get_table_pathname + * + * PARAMETERS: Node - Scope whose name is needed + * + * RETURN: Pointer to storage containing the fully qualified name of + * the scope, in Label format (all segments strung together + * with no separators) + * + * DESCRIPTION: Used for debug printing in Acpi_ns_search_table(). + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_ns_get_table_pathname ( + ACPI_NAMESPACE_NODE *node) +{ + NATIVE_CHAR *name_buffer; + u32 size; + ACPI_NAME name; + ACPI_NAMESPACE_NODE *child_node; + ACPI_NAMESPACE_NODE *parent_node; + + + if (!acpi_gbl_root_node || !node) { + /* + * If the name space has not been initialized, + * this function should not have been called. + */ + return (NULL); + } + + child_node = node->child; + + + /* Calculate required buffer size based on depth below root */ + + size = 1; + parent_node = child_node; + while (parent_node) { + parent_node = acpi_ns_get_parent_object (parent_node); + if (parent_node) { + size += ACPI_NAME_SIZE; + } + } + + + /* Allocate a buffer to be returned to caller */ + + name_buffer = acpi_cm_callocate (size + 1); + if (!name_buffer) { + REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n")); + return (NULL); + } + + + /* Store terminator byte, then build name backwards */ + + name_buffer[size] = '\0'; + while ((size > ACPI_NAME_SIZE) && + acpi_ns_get_parent_object (child_node)) { + size -= ACPI_NAME_SIZE; + name = acpi_ns_find_parent_name (child_node); + + /* Put the name into the buffer */ + + MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name); + child_node = acpi_ns_get_parent_object (child_node); + } + + name_buffer[--size] = AML_ROOT_PREFIX; + + + return (name_buffer); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_get_pathname_length + * + * PARAMETERS: Node - Namespace node + * + * RETURN: Length of path, including prefix + * + * DESCRIPTION: Get the length of the pathname string for this node + * + ******************************************************************************/ + +u32 +acpi_ns_get_pathname_length ( + ACPI_NAMESPACE_NODE *node) +{ + u32 size; + ACPI_NAMESPACE_NODE *next_node; + + /* + * Compute length of pathname as 5 * number of name segments. + * Go back up the parent tree to the root + */ + for (size = 0, next_node = node; + acpi_ns_get_parent_object (next_node); + next_node = acpi_ns_get_parent_object (next_node)) { + size += PATH_SEGMENT_LENGTH; + } + + /* Special case for size still 0 - no parent for "special" nodes */ + + if (!size) { + size = PATH_SEGMENT_LENGTH; + } + + return (size + 1); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_handle_to_pathname + * + * PARAMETERS: Target_handle - Handle of named object whose name is + * to be found + * Buf_size - Size of the buffer provided + * User_buffer - Where the pathname is returned + * + * RETURN: Status, Buffer is filled with pathname if status is AE_OK + * + * DESCRIPTION: Build and return a full namespace pathname + * + * MUTEX: Locks Namespace + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_handle_to_pathname ( + ACPI_HANDLE target_handle, + u32 *buf_size, + NATIVE_CHAR *user_buffer) +{ + ACPI_STATUS status = AE_OK; + ACPI_NAMESPACE_NODE *node; + u32 path_length; + u32 user_buf_size; + ACPI_NAME name; + u32 size; + + + if (!acpi_gbl_root_node || !target_handle) { + /* + * If the name space has not been initialized, + * this function should not have been called. + */ + + return (AE_NO_NAMESPACE); + } + + node = acpi_ns_convert_handle_to_entry (target_handle); + if (!node) { + return (AE_BAD_PARAMETER); + } + + + /* Set return length to the required path length */ + + path_length = acpi_ns_get_pathname_length (node); + size = path_length - 1; + + user_buf_size = *buf_size; + *buf_size = path_length; + + /* Check if the user buffer is sufficiently large */ + + if (path_length > user_buf_size) { + status = AE_BUFFER_OVERFLOW; + goto exit; + } + + /* Store null terminator */ + + user_buffer[size] = 0; + size -= ACPI_NAME_SIZE; + + /* Put the original ACPI name at the end of the path */ + + MOVE_UNALIGNED32_TO_32 ((user_buffer + size), + &node->name); + + user_buffer[--size] = PATH_SEPARATOR; + + /* Build name backwards, putting "." between segments */ + + while ((size > ACPI_NAME_SIZE) && node) { + size -= ACPI_NAME_SIZE; + name = acpi_ns_find_parent_name (node); + MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name); + + user_buffer[--size] = PATH_SEPARATOR; + node = acpi_ns_get_parent_object (node); + } + + /* + * Overlay the "." preceding the first segment with + * the root name "\" + */ + + user_buffer[size] = '\\'; + +exit: + return (status); +} + + diff --git a/drivers/bus/acpi/namespace/nsobject.c b/drivers/bus/acpi/namespace/nsobject.c new file mode 100644 index 0000000..2e65f5e --- /dev/null +++ b/drivers/bus/acpi/namespace/nsobject.c @@ -0,0 +1,361 @@ +/******************************************************************************* + * + * Module Name: nsobject - Utilities for objects attached to namespace + * table entries + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsobject") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_attach_object + * + * PARAMETERS: Node - Parent Node + * Object - Object to be attached + * Type - Type of object, or ACPI_TYPE_ANY if not + * known + * + * DESCRIPTION: Record the given object as the value associated with the + * name whose ACPI_HANDLE is passed. If Object is NULL + * and Type is ACPI_TYPE_ANY, set the name as having no value. + * + * MUTEX: Assumes namespace is locked + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_attach_object ( + ACPI_NAMESPACE_NODE *node, + ACPI_OPERAND_OBJECT *object, + OBJECT_TYPE_INTERNAL type) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_OPERAND_OBJECT *previous_obj_desc; + OBJECT_TYPE_INTERNAL obj_type = ACPI_TYPE_ANY; + u8 flags; + u16 opcode; + + + /* + * Parameter validation + */ + + if (!acpi_gbl_root_node) { + /* Name space not initialized */ + + REPORT_ERROR (("Ns_attach_object: Namespace not initialized\n")); + return (AE_NO_NAMESPACE); + } + + if (!node) { + /* Invalid handle */ + + REPORT_ERROR (("Ns_attach_object: Null Named_obj handle\n")); + return (AE_BAD_PARAMETER); + } + + if (!object && (ACPI_TYPE_ANY != type)) { + /* Null object */ + + REPORT_ERROR (("Ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n")); + return (AE_BAD_PARAMETER); + } + + if (!VALID_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED)) { + /* Not a name handle */ + + REPORT_ERROR (("Ns_attach_object: Invalid handle\n")); + return (AE_BAD_PARAMETER); + } + + /* Check if this object is already attached */ + + if (node->object == object) { + return (AE_OK); + } + + + /* Get the current flags field of the Node */ + + flags = node->flags; + flags &= ~ANOBJ_AML_ATTACHMENT; + + + /* If null object, we will just install it */ + + if (!object) { + obj_desc = NULL; + obj_type = ACPI_TYPE_ANY; + } + + /* + * If the object is an Node with an attached object, + * we will use that (attached) object + */ + + else if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED) && + ((ACPI_NAMESPACE_NODE *) object)->object) { + /* + * Value passed is a name handle and that name has a + * non-null value. Use that name's value and type. + */ + + obj_desc = ((ACPI_NAMESPACE_NODE *) object)->object; + obj_type = ((ACPI_NAMESPACE_NODE *) object)->type; + + /* + * Copy appropriate flags + */ + + if (((ACPI_NAMESPACE_NODE *) object)->flags & ANOBJ_AML_ATTACHMENT) { + flags |= ANOBJ_AML_ATTACHMENT; + } + } + + + /* + * Otherwise, we will use the parameter object, but we must type + * it first + */ + + else { + obj_desc = (ACPI_OPERAND_OBJECT *) object; + + + /* If a valid type (non-ANY) was given, just use it */ + + if (ACPI_TYPE_ANY != type) { + obj_type = type; + } + + + /* + * Type is TYPE_Any, we must try to determinte the + * actual type of the object + */ + + /* + * Check if value points into the AML code + */ + else if (acpi_tb_system_table_pointer (object)) { + /* + * Object points into the AML stream. + * Set a flag bit in the Node to indicate this + */ + + flags |= ANOBJ_AML_ATTACHMENT; + + /* + * The next byte (perhaps the next two bytes) + * will be the AML opcode + */ + + MOVE_UNALIGNED16_TO_16 (&opcode, object); + + /* Check for a recognized Opcode */ + + switch ((u8) opcode) { + + case AML_OP_PREFIX: + + if (opcode != AML_REVISION_OP) { + /* + * Op_prefix is unrecognized unless part + * of Revision_op + */ + + break; + } + + /* Else fall through to set type as Number */ + + + case AML_ZERO_OP: case AML_ONES_OP: case AML_ONE_OP: + case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: + + obj_type = ACPI_TYPE_INTEGER; + break; + + + case AML_STRING_OP: + + obj_type = ACPI_TYPE_STRING; + break; + + + case AML_BUFFER_OP: + + obj_type = ACPI_TYPE_BUFFER; + break; + + + case AML_MUTEX_OP: + + obj_type = ACPI_TYPE_MUTEX; + break; + + + case AML_PACKAGE_OP: + + obj_type = ACPI_TYPE_PACKAGE; + break; + + + default: + + return (AE_TYPE); + break; + } + } + + else { + /* + * Cannot figure out the type -- set to Def_any which + * will print as an error in the name table dump + */ + + + obj_type = INTERNAL_TYPE_DEF_ANY; + } + } + + + /* + * Must increment the new value's reference count + * (if it is an internal object) + */ + + acpi_cm_add_reference (obj_desc); + + /* Save the existing object (if any) for deletion later */ + + previous_obj_desc = node->object; + + /* Install the object and set the type, flags */ + + node->object = obj_desc; + node->type = (u8) obj_type; + node->flags |= flags; + + + /* + * Delete an existing attached object. + */ + + if (previous_obj_desc) { + /* One for the attach to the Node */ + + acpi_cm_remove_reference (previous_obj_desc); + + /* Now delete */ + + acpi_cm_remove_reference (previous_obj_desc); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_detach_object + * + * PARAMETERS: Node - An object whose Value will be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete the Value associated with a namespace object. If the + * Value is an allocated object, it is freed. Otherwise, the + * field is simply cleared. + * + ******************************************************************************/ + +void +acpi_ns_detach_object ( + ACPI_NAMESPACE_NODE *node) +{ + ACPI_OPERAND_OBJECT *obj_desc; + + + obj_desc = node->object; + if (!obj_desc) { + return; + } + + /* Clear the entry in all cases */ + + node->object = NULL; + + /* Found a valid value */ + + /* + * Not every value is an object allocated via Acpi_cm_callocate, + * - must check + */ + + if (!acpi_tb_system_table_pointer (obj_desc)) { + /* Attempt to delete the object (and all subobjects) */ + + acpi_cm_remove_reference (obj_desc); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_get_attached_object + * + * PARAMETERS: Handle - Parent Node to be examined + * + * RETURN: Current value of the object field from the Node whose + * handle is passed + * + ******************************************************************************/ + +void * +acpi_ns_get_attached_object ( + ACPI_HANDLE handle) +{ + + if (!handle) { + /* handle invalid */ + + return (NULL); + } + + return (((ACPI_NAMESPACE_NODE *) handle)->object); +} + + diff --git a/drivers/bus/acpi/namespace/nssearch.c b/drivers/bus/acpi/namespace/nssearch.c new file mode 100644 index 0000000..8bba2e4 --- /dev/null +++ b/drivers/bus/acpi/namespace/nssearch.c @@ -0,0 +1,346 @@ +/******************************************************************************* + * + * Module Name: nssearch - Namespace search + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nssearch") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_search_node + * + * PARAMETERS: *Target_name - Ascii ACPI name to search for + * *Node - Starting table where search will begin + * Type - Object type to match + * **Return_node - Where the matched Named obj is returned + * + * RETURN: Status + * + * DESCRIPTION: Search a single namespace table. Performs a simple search, + * does not add entries or search parents. + * + * + * Named object lists are built (and subsequently dumped) in the + * order in which the names are encountered during the namespace load; + * + * All namespace searching is linear in this implementation, but + * could be easily modified to support any improved search + * algorithm. However, the linear search was chosen for simplicity + * and because the trees are small and the other interpreter + * execution overhead is relatively high. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_search_node ( + u32 target_name, + ACPI_NAMESPACE_NODE *node, + OBJECT_TYPE_INTERNAL type, + ACPI_NAMESPACE_NODE **return_node) +{ + ACPI_NAMESPACE_NODE *next_node; + + + /* + * Search for name in this table, which is to say that we must search + * for the name among the children of this object + */ + + next_node = node->child; + while (next_node) { + /* Check for match against the name */ + + if (next_node->name == target_name) { + /* + * Found matching entry. Capture the type if appropriate, before + * returning the entry. + * + * The Def_field_defn and Bank_field_defn cases are actually looking up + * the Region in which the field will be defined + */ + + if ((INTERNAL_TYPE_DEF_FIELD_DEFN == type) || + (INTERNAL_TYPE_BANK_FIELD_DEFN == type)) { + type = ACPI_TYPE_REGION; + } + + /* + * Scope, Def_any, and Index_field_defn are bogus "types" which do not + * actually have anything to do with the type of the name being + * looked up. For any other value of Type, if the type stored in + * the entry is Any (i.e. unknown), save the actual type. + */ + + if (type != INTERNAL_TYPE_SCOPE && + type != INTERNAL_TYPE_DEF_ANY && + type != INTERNAL_TYPE_INDEX_FIELD_DEFN && + next_node->type == ACPI_TYPE_ANY) { + next_node->type = (u8) type; + } + + *return_node = next_node; + return (AE_OK); + } + + + /* + * The last entry in the list points back to the parent, + * so a flag is used to indicate the end-of-list + */ + if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + /* Searched entire list, we are done */ + + break; + } + + /* Didn't match name, move on to the next peer object */ + + next_node = next_node->peer; + } + + + /* Searched entire table, not found */ + + + return (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_search_parent_tree + * + * PARAMETERS: *Target_name - Ascii ACPI name to search for + * *Node - Starting table where search will begin + * Type - Object type to match + * **Return_node - Where the matched Named Obj is returned + * + * RETURN: Status + * + * DESCRIPTION: Called when a name has not been found in the current namespace + * table. Before adding it or giving up, ACPI scope rules require + * searching enclosing scopes in cases identified by Acpi_ns_local(). + * + * "A name is located by finding the matching name in the current + * name space, and then in the parent name space. If the parent + * name space does not contain the name, the search continues + * recursively until either the name is found or the name space + * does not have a parent (the root of the name space). This + * indicates that the name is not found" (From ACPI Specification, + * section 5.3) + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ns_search_parent_tree ( + u32 target_name, + ACPI_NAMESPACE_NODE *node, + OBJECT_TYPE_INTERNAL type, + ACPI_NAMESPACE_NODE **return_node) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *parent_node; + + + parent_node = acpi_ns_get_parent_object (node); + + /* + * If there is no parent (at the root) or type is "local", we won't be + * searching the parent tree. + */ + if ((acpi_ns_local (type)) || + (!parent_node)) { + + + return (AE_NOT_FOUND); + } + + + /* Search the parent tree */ + + /* + * Search parents until found the target or we have backed up to + * the root + */ + + while (parent_node) { + /* Search parent scope */ + /* TBD: [Investigate] Why ACPI_TYPE_ANY? */ + + status = acpi_ns_search_node (target_name, parent_node, + ACPI_TYPE_ANY, return_node); + + if (ACPI_SUCCESS (status)) { + return (status); + } + + /* + * Not found here, go up another level + * (until we reach the root) + */ + + parent_node = acpi_ns_get_parent_object (parent_node); + } + + + /* Not found in parent tree */ + + return (AE_NOT_FOUND); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_search_and_enter + * + * PARAMETERS: Target_name - Ascii ACPI name to search for (4 chars) + * Walk_state - Current state of the walk + * *Node - Starting table where search will begin + * Interpreter_mode - Add names only in MODE_Load_pass_x. + * Otherwise,search only. + * Type - Object type to match + * Flags - Flags describing the search restrictions + * **Return_node - Where the Node is returned + * + * RETURN: Status + * + * DESCRIPTION: Search for a name segment in a single name table, + * optionally adding it if it is not found. If the passed + * Type is not Any and the type previously stored in the + * entry was Any (i.e. unknown), update the stored type. + * + * In IMODE_EXECUTE, search only. + * In other modes, search and add if not found. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_search_and_enter ( + u32 target_name, + ACPI_WALK_STATE *walk_state, + ACPI_NAMESPACE_NODE *node, + OPERATING_MODE interpreter_mode, + OBJECT_TYPE_INTERNAL type, + u32 flags, + ACPI_NAMESPACE_NODE **return_node) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *new_node; + + + /* Parameter validation */ + + if (!node || !target_name || !return_node) { + REPORT_ERROR (("Ns_search_and_enter: bad (null) parameter\n")); + return (AE_BAD_PARAMETER); + } + + + /* Name must consist of printable characters */ + + if (!acpi_cm_valid_acpi_name (target_name)) { + REPORT_ERROR (("Ns_search_and_enter: Bad character in ACPI Name\n")); + return (AE_BAD_CHARACTER); + } + + + /* Try to find the name in the table specified by the caller */ + + *return_node = ENTRY_NOT_FOUND; + status = acpi_ns_search_node (target_name, node, + type, return_node); + if (status != AE_NOT_FOUND) { + /* + * If we found it AND the request specifies that a find is an error, + * return the error + */ + if ((status == AE_OK) && + (flags & NS_ERROR_IF_FOUND)) { + status = AE_EXIST; + } + + /* + * Either found it or there was an error + * -- finished either way + */ + return (status); + } + + + /* + * Not found in the table. If we are NOT performing the + * first pass (name entry) of loading the namespace, search + * the parent tree (all the way to the root if necessary.) + * We don't want to perform the parent search when the + * namespace is actually being loaded. We want to perform + * the search when namespace references are being resolved + * (load pass 2) and during the execution phase. + */ + + if ((interpreter_mode != IMODE_LOAD_PASS1) && + (flags & NS_SEARCH_PARENT)) { + /* + * Not found in table - search parent tree according + * to ACPI specification + */ + + status = acpi_ns_search_parent_tree (target_name, node, + type, return_node); + if (ACPI_SUCCESS (status)) { + return (status); + } + } + + + /* + * In execute mode, just search, never add names. Exit now. + */ + if (interpreter_mode == IMODE_EXECUTE) { + return (AE_NOT_FOUND); + } + + + /* Create the new named object */ + + new_node = acpi_ns_create_node (target_name); + if (!new_node) { + return (AE_NO_MEMORY); + } + + /* Install the new object into the parent's list of children */ + + acpi_ns_install_node (walk_state, node, new_node, type); + *return_node = new_node; + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/namespace/nsutils.c b/drivers/bus/acpi/namespace/nsutils.c new file mode 100644 index 0000000..2dbbc60 --- /dev/null +++ b/drivers/bus/acpi/namespace/nsutils.c @@ -0,0 +1,815 @@ +/****************************************************************************** + * + * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing + * parents and siblings and Scope manipulation + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" +#include "actables.h" + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsutils") + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_valid_root_prefix + * + * PARAMETERS: Prefix - Character to be checked + * + * RETURN: TRUE if a valid prefix + * + * DESCRIPTION: Check if a character is a valid ACPI Root prefix + * + ***************************************************************************/ + +u8 +acpi_ns_valid_root_prefix ( + NATIVE_CHAR prefix) +{ + + return ((u8) (prefix == '\\')); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_valid_path_separator + * + * PARAMETERS: Sep - Character to be checked + * + * RETURN: TRUE if a valid path separator + * + * DESCRIPTION: Check if a character is a valid ACPI path separator + * + ***************************************************************************/ + +u8 +acpi_ns_valid_path_separator ( + NATIVE_CHAR sep) +{ + + return ((u8) (sep == '.')); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_type + * + * PARAMETERS: Handle - Parent Node to be examined + * + * RETURN: Type field from Node whose handle is passed + * + ***************************************************************************/ + +OBJECT_TYPE_INTERNAL +acpi_ns_get_type ( + ACPI_HANDLE handle) +{ + + if (!handle) { + REPORT_WARNING (("Ns_get_type: Null handle\n")); + return (ACPI_TYPE_ANY); + } + + return (((ACPI_NAMESPACE_NODE *) handle)->type); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_local + * + * PARAMETERS: Type - A namespace object type + * + * RETURN: LOCAL if names must be found locally in objects of the + * passed type, 0 if enclosing scopes should be searched + * + ***************************************************************************/ + +u32 +acpi_ns_local ( + OBJECT_TYPE_INTERNAL type) +{ + + if (!acpi_cm_valid_object_type (type)) { + /* Type code out of range */ + + REPORT_WARNING (("Ns_local: Invalid Object Type\n")); + return (NSP_NORMAL); + } + + return ((u32) acpi_gbl_ns_properties[type] & NSP_LOCAL); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_internalize_name + * + * PARAMETERS: *External_name - External representation of name + * **Converted Name - Where to return the resulting + * internal represention of the name + * + * RETURN: Status + * + * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") + * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_internalize_name ( + NATIVE_CHAR *external_name, + NATIVE_CHAR **converted_name) +{ + NATIVE_CHAR *result = NULL; + NATIVE_CHAR *internal_name; + u32 num_segments = 0; + u8 fully_qualified = FALSE; + u32 i; + u32 num_carats = 0; + + + if ((!external_name) || + (*external_name == 0) || + (!converted_name)) { + return (AE_BAD_PARAMETER); + } + + + /* + * For the internal name, the required length is 4 bytes + * per segment, plus 1 each for Root_prefix, Multi_name_prefix_op, + * segment count, trailing null (which is not really needed, + * but no there's harm in putting it there) + * + * strlen() + 1 covers the first Name_seg, which has no + * path separator + */ + + if (acpi_ns_valid_root_prefix (external_name[0])) { + fully_qualified = TRUE; + external_name++; + } + + else { + /* + * Handle Carat prefixes + */ + + while (*external_name == '^') { + num_carats++; + external_name++; + } + } + + /* + * Determine the number of ACPI name "segments" by counting + * the number of path separators within the string. Start + * with one segment since the segment count is (# separators) + * + 1, and zero separators is ok. + */ + + if (*external_name) { + num_segments = 1; + for (i = 0; external_name[i]; i++) { + if (acpi_ns_valid_path_separator (external_name[i])) { + num_segments++; + } + } + } + + + /* We need a segment to store the internal version of the name */ + + internal_name = acpi_cm_callocate ((ACPI_NAME_SIZE * num_segments) + 4 + num_carats); + if (!internal_name) { + return (AE_NO_MEMORY); + } + + + /* Setup the correct prefixes, counts, and pointers */ + + if (fully_qualified) { + internal_name[0] = '\\'; + + if (num_segments <= 1) { + result = &internal_name[1]; + } + else if (num_segments == 2) { + internal_name[1] = AML_DUAL_NAME_PREFIX; + result = &internal_name[2]; + } + else { + internal_name[1] = AML_MULTI_NAME_PREFIX_OP; + internal_name[2] = (char) num_segments; + result = &internal_name[3]; + } + + } + + else { + /* + * Not fully qualified. + * Handle Carats first, then append the name segments + */ + + i = 0; + if (num_carats) { + for (i = 0; i < num_carats; i++) { + internal_name[i] = '^'; + } + } + + if (num_segments == 1) { + result = &internal_name[i]; + } + + else if (num_segments == 2) { + internal_name[i] = AML_DUAL_NAME_PREFIX; + result = &internal_name[i+1]; + } + + else { + internal_name[i] = AML_MULTI_NAME_PREFIX_OP; + internal_name[i+1] = (char) num_segments; + result = &internal_name[i+2]; + } + } + + + /* Build the name (minus path separators) */ + + for (; num_segments; num_segments--) { + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (acpi_ns_valid_path_separator (*external_name) || + (*external_name == 0)) { + /* + * Pad the segment with underscore(s) if + * segment is short + */ + + result[i] = '_'; + } + + else { + /* Convert s8 to uppercase and save it */ + + result[i] = (char) TOUPPER (*external_name); + external_name++; + } + + } + + /* Now we must have a path separator, or the pathname is bad */ + + if (!acpi_ns_valid_path_separator (*external_name) && + (*external_name != 0)) { + acpi_cm_free (internal_name); + return (AE_BAD_PARAMETER); + } + + /* Move on the next segment */ + + external_name++; + result += ACPI_NAME_SIZE; + } + + + /* Return the completed name */ + + /* Terminate the string! */ + *result = 0; + *converted_name = internal_name; + + + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_externalize_name + * + * PARAMETERS: *Internal_name - Internal representation of name + * **Converted_name - Where to return the resulting + * external representation of name + * + * RETURN: Status + * + * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) + * to its external form (e.g. "\_PR_.CPU0") + * + ****************************************************************************/ + +ACPI_STATUS +acpi_ns_externalize_name ( + u32 internal_name_length, + char *internal_name, + u32 *converted_name_length, + char **converted_name) +{ + u32 prefix_length = 0; + u32 names_index = 0; + u32 names_count = 0; + u32 i = 0; + u32 j = 0; + + + if (!internal_name_length || + !internal_name || + !converted_name_length || + !converted_name) { + return (AE_BAD_PARAMETER); + } + + + /* + * Check for a prefix (one '\' | one or more '^'). + */ + switch (internal_name[0]) { + case '\\': + prefix_length = 1; + break; + + case '^': + for (i = 0; i < internal_name_length; i++) { + if (internal_name[i] != '^') { + prefix_length = i + 1; + } + } + + if (i == internal_name_length) { + prefix_length = i; + } + + break; + } + + /* + * Check for object names. Note that there could be 0-255 of these + * 4-byte elements. + */ + if (prefix_length < internal_name_length) { + switch (internal_name[prefix_length]) { + + /* 4-byte names */ + + case AML_MULTI_NAME_PREFIX_OP: + names_index = prefix_length + 2; + names_count = (u32) internal_name[prefix_length + 1]; + break; + + + /* two 4-byte names */ + + case AML_DUAL_NAME_PREFIX: + names_index = prefix_length + 1; + names_count = 2; + break; + + + /* Null_name */ + + case 0: + names_index = 0; + names_count = 0; + break; + + + /* one 4-byte name */ + + default: + names_index = prefix_length; + names_count = 1; + break; + } + } + + /* + * Calculate the length of Converted_name, which equals the length + * of the prefix, length of all object names, length of any required + * punctuation ('.') between object names, plus the NULL terminator. + */ + *converted_name_length = prefix_length + (4 * names_count) + + ((names_count > 0) ? (names_count - 1) : 0) + 1; + + /* + * Check to see if we're still in bounds. If not, there's a problem + * with Internal_name (invalid format). + */ + if (*converted_name_length > internal_name_length) { + REPORT_ERROR (("Ns_externalize_name: Invalid internal name\n")); + return (AE_BAD_PATHNAME); + } + + /* + * Build Converted_name... + */ + + (*converted_name) = acpi_cm_callocate (*converted_name_length); + if (!(*converted_name)) { + return (AE_NO_MEMORY); + } + + j = 0; + + for (i = 0; i < prefix_length; i++) { + (*converted_name)[j++] = internal_name[i]; + } + + if (names_count > 0) { + for (i = 0; i < names_count; i++) { + if (i > 0) { + (*converted_name)[j++] = '.'; + } + + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + (*converted_name)[j++] = internal_name[names_index++]; + } + } + + return (AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_convert_handle_to_entry + * + * PARAMETERS: Handle - Handle to be converted to an Node + * + * RETURN: A Name table entry pointer + * + * DESCRIPTION: Convert a namespace handle to a real Node + * + ****************************************************************************/ + +ACPI_NAMESPACE_NODE * +acpi_ns_convert_handle_to_entry ( + ACPI_HANDLE handle) +{ + + /* + * Simple implementation for now; + * TBD: [Future] Real integer handles allow for more verification + * and keep all pointers within this subsystem! + */ + + if (!handle) { + return (NULL); + } + + if (handle == ACPI_ROOT_OBJECT) { + return (acpi_gbl_root_node); + } + + + /* We can at least attempt to verify the handle */ + + if (!VALID_DESCRIPTOR_TYPE (handle, ACPI_DESC_TYPE_NAMED)) { + return (NULL); + } + + return ((ACPI_NAMESPACE_NODE *) handle); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_convert_entry_to_handle + * + * PARAMETERS: Node - Node to be converted to a Handle + * + * RETURN: An USER ACPI_HANDLE + * + * DESCRIPTION: Convert a real Node to a namespace handle + * + ****************************************************************************/ + +ACPI_HANDLE +acpi_ns_convert_entry_to_handle ( + ACPI_NAMESPACE_NODE *node) +{ + + + /* + * Simple implementation for now; + * TBD: [Future] Real integer handles allow for more verification + * and keep all pointers within this subsystem! + */ + + return ((ACPI_HANDLE) node); + + +/* --------------------------------------------------- + + if (!Node) + { + return (NULL); + } + + if (Node == Acpi_gbl_Root_node) + { + return (ACPI_ROOT_OBJECT); + } + + + return ((ACPI_HANDLE) Node); +------------------------------------------------------*/ +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_ns_terminate (void) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_NAMESPACE_NODE *this_node; + + + this_node = acpi_gbl_root_node; + + /* + * 1) Free the entire namespace -- all objects, tables, and stacks + */ + /* + * Delete all objects linked to the root + * (additional table descriptors) + */ + + acpi_ns_delete_namespace_subtree (this_node); + + /* Detach any object(s) attached to the root */ + + obj_desc = acpi_ns_get_attached_object (this_node); + if (obj_desc) { + acpi_ns_detach_object (this_node); + acpi_cm_remove_reference (obj_desc); + } + + acpi_ns_delete_children (this_node); + + + /* + * 2) Now we can delete the ACPI tables + */ + + acpi_tb_delete_acpi_tables (); + + return; +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_opens_scope + * + * PARAMETERS: Type - A valid namespace type + * + * RETURN: NEWSCOPE if the passed type "opens a name scope" according + * to the ACPI specification, else 0 + * + ***************************************************************************/ + +u32 +acpi_ns_opens_scope ( + OBJECT_TYPE_INTERNAL type) +{ + + if (!acpi_cm_valid_object_type (type)) { + /* type code out of range */ + + REPORT_WARNING (("Ns_opens_scope: Invalid Object Type\n")); + return (NSP_NORMAL); + } + + return (((u32) acpi_gbl_ns_properties[type]) & NSP_NEWSCOPE); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_node + * + * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The + * \ (backslash) and ^ (carat) prefixes, and the + * . (period) to separate segments are supported. + * Start_node - Root of subtree to be searched, or NS_ALL for the + * root of the name space. If Name is fully + * qualified (first s8 is '\'), the passed value + * of Scope will not be accessed. + * Return_node - Where the Node is returned + * + * DESCRIPTION: Look up a name relative to a given scope and return the + * corresponding Node. NOTE: Scope can be null. + * + * MUTEX: Locks namespace + * + ***************************************************************************/ + +ACPI_STATUS +acpi_ns_get_node ( + NATIVE_CHAR *pathname, + ACPI_NAMESPACE_NODE *start_node, + ACPI_NAMESPACE_NODE **return_node) +{ + ACPI_GENERIC_STATE scope_info; + ACPI_STATUS status; + NATIVE_CHAR *internal_path = NULL; + + + /* Ensure that the namespace has been initialized */ + + if (!acpi_gbl_root_node) { + return (AE_NO_NAMESPACE); + } + + if (!pathname) { + return (AE_BAD_PARAMETER); + } + + + /* Convert path to internal representation */ + + status = acpi_ns_internalize_name (pathname, &internal_path); + if (ACPI_FAILURE (status)) { + return (status); + } + + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Setup lookup scope (search starting point) */ + + scope_info.scope.node = start_node; + + /* Lookup the name in the namespace */ + + status = acpi_ns_lookup (&scope_info, internal_path, + ACPI_TYPE_ANY, IMODE_EXECUTE, + NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE, + NULL, return_node); + + + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* Cleanup */ + + acpi_cm_free (internal_path); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_find_parent_name + * + * PARAMETERS: *Child_node - Named Obj whose name is to be found + * + * RETURN: The ACPI name + * + * DESCRIPTION: Search for the given obj in its parent scope and return the + * name segment, or "????" if the parent name can't be found + * (which "should not happen"). + * + ***************************************************************************/ + +ACPI_NAME +acpi_ns_find_parent_name ( + ACPI_NAMESPACE_NODE *child_node) +{ + ACPI_NAMESPACE_NODE *parent_node; + + + if (child_node) { + /* Valid entry. Get the parent Node */ + + parent_node = acpi_ns_get_parent_object (child_node); + if (parent_node) { + if (parent_node->name) { + return (parent_node->name); + } + } + + } + + + return (ACPI_UNKNOWN_NAME); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_parent_object + * + * PARAMETERS: Node - Current table entry + * + * RETURN: Parent entry of the given entry + * + * DESCRIPTION: Obtain the parent entry for a given entry in the namespace. + * + ***************************************************************************/ + + +ACPI_NAMESPACE_NODE * +acpi_ns_get_parent_object ( + ACPI_NAMESPACE_NODE *node) +{ + + + if (!node) { + return (NULL); + } + + /* + * Walk to the end of this peer list. + * The last entry is marked with a flag and the peer + * pointer is really a pointer back to the parent. + * This saves putting a parent back pointer in each and + * every named object! + */ + + while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) { + node = node->peer; + } + + + return (node->peer); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_ns_get_next_valid_object + * + * PARAMETERS: Node - Current table entry + * + * RETURN: Next valid object in the table. NULL if no more valid + * objects + * + * DESCRIPTION: Find the next valid object within a name table. + * Useful for implementing NULL-end-of-list loops. + * + ***************************************************************************/ + + +ACPI_NAMESPACE_NODE * +acpi_ns_get_next_valid_object ( + ACPI_NAMESPACE_NODE *node) +{ + + /* If we are at the end of this peer list, return NULL */ + + if (node->flags & ANOBJ_END_OF_PEER_LIST) { + return NULL; + } + + /* Otherwise just return the next peer */ + + return (node->peer); +} + + diff --git a/drivers/bus/acpi/namespace/nswalk.c b/drivers/bus/acpi/namespace/nswalk.c new file mode 100644 index 0000000..ed3007e --- /dev/null +++ b/drivers/bus/acpi/namespace/nswalk.c @@ -0,0 +1,272 @@ +/****************************************************************************** + * + * Module Name: nswalk - Functions for walking the APCI namespace + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nswalk") + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_next_object + * + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are + * getting + * Last_child - Previous child that was found. + * The NEXT child will be returned + * + * RETURN: ACPI_NAMESPACE_NODE - Pointer to the NEXT child or NULL if + * none is found. + * + * DESCRIPTION: Return the next peer object within the namespace. If Handle + * is valid, Scope is ignored. Otherwise, the first object + * within Scope is returned. + * + ****************************************************************************/ + +ACPI_NAMESPACE_NODE * +acpi_ns_get_next_object ( + OBJECT_TYPE_INTERNAL type, + ACPI_NAMESPACE_NODE *parent_node, + ACPI_NAMESPACE_NODE *child_node) +{ + ACPI_NAMESPACE_NODE *next_node = NULL; + + + if (!child_node) { + + /* It's really the parent's _scope_ that we want */ + + if (parent_node->child) { + next_node = parent_node->child; + } + } + + else { + /* Start search at the NEXT object */ + + next_node = acpi_ns_get_next_valid_object (child_node); + } + + + /* If any type is OK, we are done */ + + if (type == ACPI_TYPE_ANY) { + /* Next_node is NULL if we are at the end-of-list */ + + return (next_node); + } + + + /* Must search for the object -- but within this scope only */ + + while (next_node) { + /* If type matches, we are done */ + + if (next_node->type == type) { + return (next_node); + } + + /* Otherwise, move on to the next object */ + + next_node = acpi_ns_get_next_valid_object (next_node); + } + + + /* Not found */ + + return (NULL); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_ns_walk_namespace + * + * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for + * Start_node - Handle in namespace where search begins + * Max_depth - Depth to which search is to reach + * Unlock_before_callback- Whether to unlock the NS before invoking + * the callback routine + * User_function - Called when an object of "Type" is found + * Context - Passed to user function + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ns_walk_namespace ( + OBJECT_TYPE_INTERNAL type, + ACPI_HANDLE start_node, + u32 max_depth, + u8 unlock_before_callback, + WALK_CALLBACK user_function, + void *context, + void **return_value) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *child_node; + ACPI_NAMESPACE_NODE *parent_node; + OBJECT_TYPE_INTERNAL child_type; + u32 level; + + + /* Special case for the namespace Root Node */ + + if (start_node == ACPI_ROOT_OBJECT) { + start_node = acpi_gbl_root_node; + } + + + /* Null child means "get first object" */ + + parent_node = start_node; + child_node = 0; + child_type = ACPI_TYPE_ANY; + level = 1; + + /* + * Traverse the tree of objects until we bubble back up to where we + * started. When Level is zero, the loop is done because we have + * bubbled up to (and passed) the original parent handle (Start_entry) + */ + + while (level > 0) { + /* + * Get the next typed object in this scope. Null returned + * if not found + */ + + status = AE_OK; + child_node = acpi_ns_get_next_object (ACPI_TYPE_ANY, + parent_node, + child_node); + + if (child_node) { + /* + * Found an object, Get the type if we are not + * searching for ANY + */ + + if (type != ACPI_TYPE_ANY) { + child_type = child_node->type; + } + + if (child_type == type) { + /* + * Found a matching object, invoke the user + * callback function + */ + + if (unlock_before_callback) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + status = user_function (child_node, level, + context, return_value); + + if (unlock_before_callback) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + } + + switch (status) { + case AE_OK: + case AE_CTRL_DEPTH: + /* Just keep going */ + break; + + case AE_CTRL_TERMINATE: + /* Exit now, with OK status */ + return (AE_OK); + break; + + default: + /* All others are valid exceptions */ + return (status); + break; + } + } + + /* + * Depth first search: + * Attempt to go down another level in the namespace + * if we are allowed to. Don't go any further if we + * have reached the caller specified maximum depth + * or if the user function has specified that the + * maximum depth has been reached. + */ + + if ((level < max_depth) && (status != AE_CTRL_DEPTH)) { + if (acpi_ns_get_next_object (ACPI_TYPE_ANY, + child_node, 0)) { + /* + * There is at least one child of this + * object, visit the object + */ + level++; + parent_node = child_node; + child_node = 0; + } + } + } + + else { + /* + * No more children in this object (Acpi_ns_get_next_object + * failed), go back upwards in the namespace tree to + * the object's parent. + */ + level--; + child_node = parent_node; + parent_node = acpi_ns_get_parent_object (parent_node); + } + } + + /* Complete walk, not terminated by user function */ + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/namespace/nsxfname.c b/drivers/bus/acpi/namespace/nsxfname.c new file mode 100644 index 0000000..d9923d6 --- /dev/null +++ b/drivers/bus/acpi/namespace/nsxfname.c @@ -0,0 +1,300 @@ +/****************************************************************************** + * + * Module Name: nsxfname - Public interfaces to the ACPI subsystem + * ACPI Namespace oriented interfaces + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsxfname") + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_handle + * + * PARAMETERS: Parent - Object to search under (search scope). + * Path_name - Pointer to an asciiz string containing the + * name + * Ret_handle - Where the return handle is placed + * + * RETURN: Status + * + * DESCRIPTION: This routine will search for a caller specified name in the + * name space. The caller can restrict the search region by + * specifying a non NULL parent. The parent value is itself a + * namespace handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_handle ( + ACPI_HANDLE parent, + ACPI_STRING pathname, + ACPI_HANDLE *ret_handle) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node = NULL; + ACPI_NAMESPACE_NODE *prefix_node = NULL; + + + if (!ret_handle || !pathname) { + return (AE_BAD_PARAMETER); + } + + /* Convert a parent handle to a prefix node */ + + if (parent) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + prefix_node = acpi_ns_convert_handle_to_entry (parent); + if (!prefix_node) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + + /* Special case for root, since we can't search for it */ + + if (STRCMP (pathname, NS_ROOT_PATH) == 0) { + *ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_node); + return (AE_OK); + } + + /* + * Find the Node and convert to a handle + */ + status = acpi_ns_get_node (pathname, prefix_node, &node); + + *ret_handle = NULL; + if (ACPI_SUCCESS (status)) { + *ret_handle = acpi_ns_convert_entry_to_handle (node); + } + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_pathname + * + * PARAMETERS: Handle - Handle to be converted to a pathname + * Name_type - Full pathname or single segment + * Ret_path_ptr - Buffer for returned path + * + * RETURN: Pointer to a string containing the fully qualified Name. + * + * DESCRIPTION: This routine returns the fully qualified name associated with + * the Handle parameter. This and the Acpi_pathname_to_handle are + * complementary functions. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_name ( + ACPI_HANDLE handle, + u32 name_type, + ACPI_BUFFER *ret_path_ptr) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node; + + + /* Buffer pointer must be valid always */ + + if (!ret_path_ptr || (name_type > ACPI_NAME_TYPE_MAX)) { + return (AE_BAD_PARAMETER); + } + + /* Allow length to be zero and ignore the pointer */ + + if ((ret_path_ptr->length) && + (!ret_path_ptr->pointer)) { + return (AE_BAD_PARAMETER); + } + + if (name_type == ACPI_FULL_PATHNAME) { + /* Get the full pathname (From the namespace root) */ + + status = acpi_ns_handle_to_pathname (handle, &ret_path_ptr->length, + ret_path_ptr->pointer); + return (status); + } + + /* + * Wants the single segment ACPI name. + * Validate handle and convert to an Node + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + node = acpi_ns_convert_handle_to_entry (handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + /* Check if name will fit in buffer */ + + if (ret_path_ptr->length < PATH_SEGMENT_LENGTH) { + ret_path_ptr->length = PATH_SEGMENT_LENGTH; + status = AE_BUFFER_OVERFLOW; + goto unlock_and_exit; + } + + /* Just copy the ACPI name from the Node and zero terminate it */ + + STRNCPY (ret_path_ptr->pointer, (NATIVE_CHAR *) &node->name, + ACPI_NAME_SIZE); + ((NATIVE_CHAR *) ret_path_ptr->pointer) [ACPI_NAME_SIZE] = 0; + status = AE_OK; + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_get_object_info + * + * PARAMETERS: Handle - Object Handle + * Info - Where the info is returned + * + * RETURN: Status + * + * DESCRIPTION: Returns information about an object as gleaned from the + * namespace node and possibly by running several standard + * control methods (Such as in the case of a device.) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_object_info ( + ACPI_HANDLE handle, + ACPI_DEVICE_INFO *info) +{ + DEVICE_ID hid; + DEVICE_ID uid; + ACPI_STATUS status; + u32 device_status = 0; + ACPI_INTEGER address = 0; + ACPI_NAMESPACE_NODE *node; + + + /* Parameter validation */ + + if (!handle || !info) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + node = acpi_ns_convert_handle_to_entry (handle); + if (!node) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + info->type = node->type; + info->name = node->name; + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + /* + * If not a device, we are all done. + */ + if (info->type != ACPI_TYPE_DEVICE) { + return (AE_OK); + } + + + /* + * Get extra info for ACPI devices only. Run the + * _HID, _UID, _STA, and _ADR methods. Note: none + * of these methods are required, so they may or may + * not be present. The Info->Valid bits are used + * to indicate which methods ran successfully. + */ + + info->valid = 0; + + /* Execute the _HID method and save the result */ + + status = acpi_cm_execute_HID (node, &hid); + if (ACPI_SUCCESS (status)) { + STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id)); + + info->valid |= ACPI_VALID_HID; + } + + /* Execute the _UID method and save the result */ + + status = acpi_cm_execute_UID (node, &uid); + if (ACPI_SUCCESS (status)) { + STRCPY (info->unique_id, uid.buffer); + + info->valid |= ACPI_VALID_UID; + } + + /* + * Execute the _STA method and save the result + * _STA is not always present + */ + + status = acpi_cm_execute_STA (node, &device_status); + if (ACPI_SUCCESS (status)) { + info->current_status = device_status; + info->valid |= ACPI_VALID_STA; + } + + /* + * Execute the _ADR method and save result if successful + * _ADR is not always present + */ + + status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, + node, &address); + + if (ACPI_SUCCESS (status)) { + info->address = address; + info->valid |= ACPI_VALID_ADR; + } + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/namespace/nsxfobj.c b/drivers/bus/acpi/namespace/nsxfobj.c new file mode 100644 index 0000000..2e0f4ec --- /dev/null +++ b/drivers/bus/acpi/namespace/nsxfobj.c @@ -0,0 +1,694 @@ +/******************************************************************************* + * + * Module Name: nsxfobj - Public interfaces to the ACPI subsystem + * ACPI Object oriented interfaces + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdispat.h" + + +#define _COMPONENT ACPI_NAMESPACE + MODULE_NAME ("nsxfobj") + + +/******************************************************************************* + * + * FUNCTION: Acpi_evaluate_object + * + * PARAMETERS: Handle - Object handle (optional) + * *Pathname - Object pathname (optional) + * **Params - List of parameters to pass to + * method, terminated by NULL. + * Params itself may be NULL + * if no parameters are being + * passed. + * *Return_object - Where to put method's return value (if + * any). If NULL, no value is returned. + * + * RETURN: Status + * + * DESCRIPTION: Find and evaluate the given object, passing the given + * parameters if necessary. One of "Handle" or "Pathname" must + * be valid (non-null) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_evaluate_object ( + ACPI_HANDLE handle, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *param_objects, + ACPI_BUFFER *return_buffer) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT **param_ptr = NULL; + ACPI_OPERAND_OBJECT *return_obj = NULL; + ACPI_OPERAND_OBJECT *object_ptr = NULL; + u32 buffer_space_needed; + u32 user_buffer_length; + u32 count; + u32 i; + u32 param_length; + u32 object_length; + + + /* + * If there are parameters to be passed to the object + * (which must be a control method), the external objects + * must be converted to internal objects + */ + + if (param_objects && param_objects->count) { + /* + * Allocate a new parameter block for the internal objects + * Add 1 to count to allow for null terminated internal list + */ + + count = param_objects->count; + param_length = (count + 1) * sizeof (void *); + object_length = count * sizeof (ACPI_OPERAND_OBJECT); + + param_ptr = acpi_cm_callocate (param_length + /* Parameter List part */ + object_length); /* Actual objects */ + if (!param_ptr) { + return (AE_NO_MEMORY); + } + + object_ptr = (ACPI_OPERAND_OBJECT *) ((u8 *) param_ptr + + param_length); + + /* + * Init the param array of pointers and NULL terminate + * the list + */ + + for (i = 0; i < count; i++) { + param_ptr[i] = &object_ptr[i]; + acpi_cm_init_static_object (&object_ptr[i]); + } + param_ptr[count] = NULL; + + /* + * Convert each external object in the list to an + * internal object + */ + for (i = 0; i < count; i++) { + status = acpi_cm_copy_eobject_to_iobject (¶m_objects->pointer[i], + param_ptr[i]); + + if (ACPI_FAILURE (status)) { + acpi_cm_delete_internal_object_list (param_ptr); + return (status); + } + } + } + + + /* + * Three major cases: + * 1) Fully qualified pathname + * 2) No handle, not fully qualified pathname (error) + * 3) Valid handle + */ + + if ((pathname) && + (acpi_ns_valid_root_prefix (pathname[0]))) { + /* + * The path is fully qualified, just evaluate by name + */ + status = acpi_ns_evaluate_by_name (pathname, param_ptr, &return_obj); + } + + else if (!handle) { + /* + * A handle is optional iff a fully qualified pathname + * is specified. Since we've already handled fully + * qualified names above, this is an error + */ + + + + status = AE_BAD_PARAMETER; + } + + else { + /* + * We get here if we have a handle -- and if we have a + * pathname it is relative. The handle will be validated + * in the lower procedures + */ + + if (!pathname) { + /* + * The null pathname case means the handle is for + * the actual object to be evaluated + */ + status = acpi_ns_evaluate_by_handle (handle, param_ptr, &return_obj); + } + + else { + /* + * Both a Handle and a relative Pathname + */ + status = acpi_ns_evaluate_relative (handle, pathname, param_ptr, + &return_obj); + } + } + + + /* + * If we are expecting a return value, and all went well above, + * copy the return value to an external object. + */ + + if (return_buffer) { + user_buffer_length = return_buffer->length; + return_buffer->length = 0; + + if (return_obj) { + if (VALID_DESCRIPTOR_TYPE (return_obj, ACPI_DESC_TYPE_NAMED)) { + /* + * If we got an Node as a return object, + * this means the object we are evaluating + * has nothing interesting to return (such + * as a mutex, etc.) We return an error + * because these types are essentially + * unsupported by this interface. We + * don't check up front because this makes + * it easier to add support for various + * types at a later date if necessary. + */ + status = AE_TYPE; + return_obj = NULL; /* No need to delete an Node */ + } + + if (ACPI_SUCCESS (status)) { + /* + * Find out how large a buffer is needed + * to contain the returned object + */ + status = acpi_cm_get_object_size (return_obj, + &buffer_space_needed); + if (ACPI_SUCCESS (status)) { + /* + * Check if there is enough room in the + * caller's buffer + */ + + if (user_buffer_length < buffer_space_needed) { + /* + * Caller's buffer is too small, can't + * give him partial results fail the call + * but return the buffer size needed + */ + + return_buffer->length = buffer_space_needed; + status = AE_BUFFER_OVERFLOW; + } + + else { + /* + * We have enough space for the object, build it + */ + status = acpi_cm_copy_iobject_to_eobject (return_obj, + return_buffer); + return_buffer->length = buffer_space_needed; + } + } + } + } + } + + + /* Delete the return and parameter objects */ + + if (return_obj) { + /* + * Delete the internal return object. (Or at least + * decrement the reference count by one) + */ + acpi_cm_remove_reference (return_obj); + } + + /* + * Free the input parameter list (if we created one), + */ + + if (param_ptr) { + /* Free the allocated parameter block */ + + acpi_cm_delete_internal_object_list (param_ptr); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_next_object + * + * PARAMETERS: Type - Type of object to be searched for + * Parent - Parent object whose children we are getting + * Last_child - Previous child that was found. + * The NEXT child will be returned + * Ret_handle - Where handle to the next object is placed + * + * RETURN: Status + * + * DESCRIPTION: Return the next peer object within the namespace. If Handle is + * valid, Scope is ignored. Otherwise, the first object within + * Scope is returned. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_next_object ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE parent, + ACPI_HANDLE child, + ACPI_HANDLE *ret_handle) +{ + ACPI_STATUS status = AE_OK; + ACPI_NAMESPACE_NODE *node; + ACPI_NAMESPACE_NODE *parent_node = NULL; + ACPI_NAMESPACE_NODE *child_node = NULL; + + + /* Parameter validation */ + + if (type > ACPI_TYPE_MAX) { + return (AE_BAD_PARAMETER); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* If null handle, use the parent */ + + if (!child) { + /* Start search at the beginning of the specified scope */ + + parent_node = acpi_ns_convert_handle_to_entry (parent); + if (!parent_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + /* Non-null handle, ignore the parent */ + + else { + /* Convert and validate the handle */ + + child_node = acpi_ns_convert_handle_to_entry (child); + if (!child_node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + } + + + /* Internal function does the real work */ + + node = acpi_ns_get_next_object ((OBJECT_TYPE_INTERNAL) type, + parent_node, child_node); + if (!node) { + status = AE_NOT_FOUND; + goto unlock_and_exit; + } + + if (ret_handle) { + *ret_handle = acpi_ns_convert_entry_to_handle (node); + } + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_type + * + * PARAMETERS: Handle - Handle of object whose type is desired + * *Ret_type - Where the type will be placed + * + * RETURN: Status + * + * DESCRIPTION: This routine returns the type associatd with a particular handle + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_type ( + ACPI_HANDLE handle, + ACPI_OBJECT_TYPE *ret_type) +{ + ACPI_NAMESPACE_NODE *node; + + + /* Parameter Validation */ + + if (!ret_type) { + return (AE_BAD_PARAMETER); + } + + /* + * Special case for the predefined Root Node + * (return type ANY) + */ + if (handle == ACPI_ROOT_OBJECT) { + *ret_type = ACPI_TYPE_ANY; + return (AE_OK); + } + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the handle */ + + node = acpi_ns_convert_handle_to_entry (handle); + if (!node) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_BAD_PARAMETER); + } + + *ret_type = node->type; + + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_parent + * + * PARAMETERS: Handle - Handle of object whose parent is desired + * Ret_handle - Where the parent handle will be placed + * + * RETURN: Status + * + * DESCRIPTION: Returns a handle to the parent of the object represented by + * Handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_parent ( + ACPI_HANDLE handle, + ACPI_HANDLE *ret_handle) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status = AE_OK; + + + /* No trace macro, too verbose */ + + + if (!ret_handle) { + return (AE_BAD_PARAMETER); + } + + /* Special case for the predefined Root Node (no parent) */ + + if (handle == ACPI_ROOT_OBJECT) { + return (AE_NULL_ENTRY); + } + + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + /* Convert and validate the handle */ + + node = acpi_ns_convert_handle_to_entry (handle); + if (!node) { + status = AE_BAD_PARAMETER; + goto unlock_and_exit; + } + + + /* Get the parent entry */ + + *ret_handle = + acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_object (node)); + + /* Return exeption if parent is null */ + + if (!acpi_ns_get_parent_object (node)) { + status = AE_NULL_ENTRY; + } + + +unlock_and_exit: + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_walk_namespace + * + * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for + * Start_object - Handle in namespace where search begins + * Max_depth - Depth to which search is to reach + * User_function - Called when an object of "Type" is found + * Context - Passed to user function + * Return_value - Location where return value of + * User_function is put if terminated early + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * The point of this procedure is to provide a generic namespace + * walk routine that can be called from multiple places to + * provide multiple services; the User Function can be tailored + * to each task, whether it is a print function, a compare + * function, etc. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_walk_namespace ( + ACPI_OBJECT_TYPE type, + ACPI_HANDLE start_object, + u32 max_depth, + WALK_CALLBACK user_function, + void *context, + void **return_value) +{ + ACPI_STATUS status; + + + /* Parameter validation */ + + if ((type > ACPI_TYPE_MAX) || + (!max_depth) || + (!user_function)) { + return (AE_BAD_PARAMETER); + } + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ns_walk_namespace ((OBJECT_TYPE_INTERNAL) type, + start_object, max_depth, + NS_WALK_UNLOCK, + user_function, context, + return_value); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ns_get_device_callback + * + * PARAMETERS: Callback from Acpi_get_device + * + * RETURN: Status + * + * DESCRIPTION: Takes callbacks from Walk_namespace and filters out all non- + * present devices, or if they specified a HID, it filters based + * on that. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ns_get_device_callback ( + ACPI_HANDLE obj_handle, + u32 nesting_level, + void *context, + void **return_value) +{ + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node; + u32 flags; + DEVICE_ID device_id; + ACPI_GET_DEVICES_INFO *info; + + + info = context; + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + + node = acpi_ns_convert_handle_to_entry (obj_handle); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + if (!node) { + return (AE_BAD_PARAMETER); + } + + /* + * Run _STA to determine if device is present + */ + + status = acpi_cm_execute_STA (node, &flags); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!(flags & 0x01)) { + /* don't return at the device or children of the device if not there */ + + return (AE_CTRL_DEPTH); + } + + /* + * Filter based on device HID + */ + if (info->hid != NULL) { + status = acpi_cm_execute_HID (node, &device_id); + + if (status == AE_NOT_FOUND) { + return (AE_OK); + } + + else if (ACPI_FAILURE (status)) { + return (status); + } + + if (STRNCMP (device_id.buffer, info->hid, sizeof (device_id.buffer)) != 0) { + return (AE_OK); + } + } + + info->user_function (obj_handle, nesting_level, info->context, return_value); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_devices + * + * PARAMETERS: HID - HID to search for. Can be NULL. + * User_function - Called when a matching object is found + * Context - Passed to user function + * Return_value - Location where return value of + * User_function is put if terminated early + * + * RETURNS Return value from the User_function if terminated early. + * Otherwise, returns NULL. + * + * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, + * starting (and ending) at the object specified by Start_handle. + * The User_function is called whenever an object that matches + * the type parameter is found. If the user function returns + * a non-zero value, the search is terminated immediately and this + * value is returned to the caller. + * + * This is a wrapper for Walk_namespace, but the callback performs + * additional filtering. Please see Acpi_get_device_callback. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_devices ( + NATIVE_CHAR *HID, + WALK_CALLBACK user_function, + void *context, + void **return_value) +{ + ACPI_STATUS status; + ACPI_GET_DEVICES_INFO info; + + + /* Parameter validation */ + + if (!user_function) { + return (AE_BAD_PARAMETER); + } + + /* + * We're going to call their callback from OUR callback, so we need + * to know what it is, and their context parameter. + */ + info.context = context; + info.user_function = user_function; + info.hid = HID; + + /* + * Lock the namespace around the walk. + * The namespace will be unlocked/locked around each call + * to the user function - since this function + * must be allowed to make Acpi calls itself. + */ + + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, + ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + NS_WALK_UNLOCK, + acpi_ns_get_device_callback, &info, + return_value); + + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + + return (status); +} diff --git a/drivers/bus/acpi/ospm/.cvsignore b/drivers/bus/acpi/ospm/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/ospm/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/ospm/acpienum.c b/drivers/bus/acpi/ospm/acpienum.c new file mode 100644 index 0000000..052816d --- /dev/null +++ b/drivers/bus/acpi/ospm/acpienum.c @@ -0,0 +1,235 @@ +/* $Id$ + * + * PROJECT: ReactOS ACPI bus driver + * FILE: acpi/ospm/acpienum.c + * PURPOSE: ACPI namespace enumerator + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 01-05-2001 CSH Created + */ +#include +#include + +#define NDEBUG +#include + + +void +bm_print1 ( + BM_NODE *node, + u32 flags) +{ + ACPI_BUFFER buffer; + BM_DEVICE *device = NULL; + char *type_string = NULL; + + if (!node) { + return; + } + + device = &(node->device); + + if (flags & BM_PRINT_PRESENT) { + if (!BM_DEVICE_PRESENT(device)) { + return; + } + } + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + acpi_get_name(device->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + + switch(device->id.type) { + case BM_TYPE_SYSTEM: + type_string = "System"; + break; + case BM_TYPE_SCOPE: + type_string = "Scope"; + break; + case BM_TYPE_PROCESSOR: + type_string = "Processor"; + break; + case BM_TYPE_THERMAL_ZONE: + type_string = "ThermalZone"; + break; + case BM_TYPE_POWER_RESOURCE: + type_string = "PowerResource"; + break; + case BM_TYPE_FIXED_BUTTON: + type_string = "Button"; + break; + case BM_TYPE_DEVICE: + type_string = "Device"; + break; + default: + type_string = "Unknown"; + break; + } + + if (!(flags & BM_PRINT_GROUP)) { + DbgPrint("+------------------------------------------------------------\n"); + } + + DbgPrint("%s[0x%02x] hid[%s] %s\n", type_string, device->handle, device->id.hid, buffer.pointer); + DbgPrint(" acpi_handle[0x%08x] flags[0x%02x] status[0x%02x]\n", device->acpi_handle, device->flags, device->status); + + if (flags & BM_PRINT_IDENTIFICATION) { + DbgPrint(" identification: uid[%s] adr[0x%08x]\n", device->id.uid, device->id.adr); + } + + if (flags & BM_PRINT_LINKAGE) { + DbgPrint(" linkage: this[%p] parent[%p] next[%p]\n", node, node->parent, node->next); + DbgPrint(" scope.head[%p] scope.tail[%p]\n", node->scope.head, node->scope.tail); + } + + if (flags & BM_PRINT_POWER) { + DbgPrint(" power: state[D%d] flags[0x%08X]\n", device->power.state, device->power.flags); + DbgPrint(" S0[0x%02x] S1[0x%02x] S2[0x%02x]\n", device->power.dx_supported[0], device->power.dx_supported[1], device->power.dx_supported[2]); + DbgPrint(" S3[0x%02x] S4[0x%02x] S5[0x%02x]\n", device->power.dx_supported[3], device->power.dx_supported[4], device->power.dx_supported[5]); + } + + if (!(flags & BM_PRINT_GROUP)) { + DbgPrint("+------------------------------------------------------------\n"); + } + + acpi_os_free(buffer.pointer); + + return; +} + + +NTSTATUS +ACPIEnumerateRootBusses( + PFDO_DEVICE_EXTENSION DeviceExtension) +{ + BM_HANDLE_LIST HandleList; + PACPI_DEVICE AcpiDevice; + ACPI_STATUS AcpiStatus; + BM_HANDLE DeviceHandle; + BM_DEVICE_ID Criteria; + KIRQL OldIrql; + ULONG i; + + BM_NODE *Node; + ULONG j; + + DPRINT("Called\n"); + + RtlZeroMemory(&Criteria, sizeof(BM_DEVICE_ID)); + RtlMoveMemory(&Criteria.hid, PCI_ROOT_HID_STRING, sizeof(PCI_ROOT_HID_STRING)); + + AcpiStatus = bm_search(BM_HANDLE_ROOT, &Criteria, &HandleList); + + if (ACPI_SUCCESS(AcpiStatus)) { + DPRINT("Got %d devices\n", HandleList.count); + + for (i = 0; i < HandleList.count; i++) { + AcpiStatus = bm_get_node(HandleList.handles[i], 0, &Node); + if (ACPI_SUCCESS(AcpiStatus)) { + DPRINT("Got BM node information: (Node 0x%X)\n", Node); + bm_print1(Node, BM_PRINT_ALL - BM_PRINT_PRESENT); +#if 1 + for (j=0; j < 4*1000;j++) + KeStallExecutionProcessor(1000); +#endif + } else { + DPRINT("Could not get BM node\n"); + } + + AcpiDevice = (PACPI_DEVICE)ExAllocatePool( + NonPagedPool, sizeof(ACPI_DEVICE)); + if (!AcpiDevice) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(AcpiDevice, sizeof(ACPI_DEVICE)); + + AcpiDevice->Pdo = NULL; + AcpiDevice->BmHandle = HandleList.handles[i]; + + KeAcquireSpinLock(&DeviceExtension->DeviceListLock, &OldIrql); + InsertHeadList(&DeviceExtension->DeviceListHead, + &AcpiDevice->DeviceListEntry); + DeviceExtension->DeviceListCount++; + KeReleaseSpinLock(&DeviceExtension->DeviceListLock, OldIrql); + } + } else { + DPRINT("Got no devices (Status 0x%X)\n", AcpiStatus); + } + for (j=0; j < 4*10*1000;j++) + KeStallExecutionProcessor(1000); + + return STATUS_SUCCESS; +} + + +NTSTATUS +ACPIEnumerateNamespace( + PFDO_DEVICE_EXTENSION DeviceExtension) +{ + BM_HANDLE_LIST HandleList; + PACPI_DEVICE AcpiDevice; + ACPI_STATUS AcpiStatus; + BM_HANDLE DeviceHandle; + BM_DEVICE_ID Criteria; + BM_NODE *Node; + KIRQL OldIrql; + ULONG i; + + DPRINT("Called\n"); + + RtlZeroMemory(&Criteria, sizeof(BM_DEVICE_ID)); + + DbgPrint("Listing ACPI namespace\n"); + Criteria.type = BM_TYPE_ALL; + + AcpiStatus = bm_search(BM_HANDLE_ROOT, &Criteria, &HandleList); + if (ACPI_SUCCESS(AcpiStatus)) { + DPRINT("Got %d devices\n", HandleList.count); + + for (i = 0; i < HandleList.count; i++) { + AcpiStatus = bm_get_node(HandleList.handles[i], 0, &Node); + if (ACPI_SUCCESS(AcpiStatus)) { + DPRINT("Got BM node information: (Node 0x%X)\n", Node); +#if 0 + { + ULONG j; + + bm_print1(Node, BM_PRINT_ALL - BM_PRINT_PRESENT); + for (j=0; j < 4*1000;j++) + KeStallExecutionProcessor(1000); + } +#endif + } else { + DPRINT("Could not get BM node\n"); + } + + AcpiDevice = (PACPI_DEVICE)ExAllocatePool( + NonPagedPool, sizeof(ACPI_DEVICE)); + if (!AcpiDevice) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(AcpiDevice, sizeof(ACPI_DEVICE)); + + AcpiDevice->Pdo = NULL; + AcpiDevice->BmHandle = HandleList.handles[i]; + + KeAcquireSpinLock(&DeviceExtension->DeviceListLock, &OldIrql); + InsertHeadList(&DeviceExtension->DeviceListHead, + &AcpiDevice->DeviceListEntry); + DeviceExtension->DeviceListCount++; + KeReleaseSpinLock(&DeviceExtension->DeviceListLock, OldIrql); + } + } else { + DPRINT("Got no devices (Status 0x%X)\n", AcpiStatus); + } + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/bus/acpi/ospm/acpisys.c b/drivers/bus/acpi/ospm/acpisys.c new file mode 100644 index 0000000..6a07427 --- /dev/null +++ b/drivers/bus/acpi/ospm/acpisys.c @@ -0,0 +1,168 @@ +/* $Id$ + * + * PROJECT: ReactOS ACPI bus driver + * FILE: acpi/ospm/acpisys.c + * PURPOSE: Driver entry + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 01-05-2001 CSH Created + */ +#include +#include +#include + +#define NDEBUG +#include + +#ifdef ALLOC_PRAGMA + +// Make the initialization routines discardable, so that they +// don't waste space + +#pragma alloc_text(init, DriverEntry) + +#endif /* ALLOC_PRAGMA */ + + +NTSTATUS +STDCALL +ACPIDispatchDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called. IRP is at (0x%X)\n", Irp); + + Irp->IoStatus.Information = 0; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + + DPRINT("Completing IRP at 0x%X\n", Irp); + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +ACPIPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PCOMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->IsFDO) { + Status = FdoPnpControl(DeviceObject, Irp); + } else { + Status = FdoPnpControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +ACPIPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PCOMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->IsFDO) { + Status = FdoPowerControl(DeviceObject, Irp); + } else { + Status = PdoPowerControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +ACPIAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT Fdo; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), + NULL, FILE_DEVICE_ACPI, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + return Status; + } + + DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; + + DeviceExtension->Pdo = PhysicalDeviceObject; + + DeviceExtension->Common.Ldo = + IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject); + + DeviceExtension->State = dsStopped; + + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + DPRINT("Done AddDevice\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DbgPrint("Advanced Configuration and Power Interface Bus Driver\n"); + + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH) ACPIDispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) ACPIPnpControl; + DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) ACPIPowerControl; + DriverObject->DriverExtension->AddDevice = ACPIAddDevice; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/bus/acpi/ospm/bn.c b/drivers/bus/acpi/ospm/bn.c new file mode 100644 index 0000000..07cd18e --- /dev/null +++ b/drivers/bus/acpi/ospm/bn.c @@ -0,0 +1,598 @@ +/***************************************************************************** + * + * Module Name: bn.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Plxxe, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "bn.h" + + +#define _COMPONENT ACPI_BUTTON + MODULE_NAME ("bn") + + +static struct proc_dir_entry *bn_proc_root = NULL; + + +/***************************************************************************** + * Internal Functions + *****************************************************************************/ + +/***************************************************************************** + * + * FUNCTION: bn_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Prints out information on a specific button. + * + ****************************************************************************/ + +void +bn_print ( + BN_CONTEXT *button) +{ +#ifdef ACPI_DEBUG + ACPI_BUFFER buffer; +#endif /*ACPI_DEBUG*/ + + if (!button) { + return; + } + + switch (button->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + acpi_os_printf("Power Button: found\n"); + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + acpi_os_printf("Sleep Button: found\n"); + break; + + case BN_TYPE_LID_SWITCH: + acpi_os_printf("Lid Switch: found\n"); + break; + } + +#ifdef ACPI_DEBUG + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + /* + * Get the full pathname for this ACPI object. + */ + acpi_get_name(button->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + + /* + * Print out basic button information. + */ + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + switch (button->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + DEBUG_PRINT(ACPI_INFO, ("| PowerButton[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer)); + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + DEBUG_PRINT(ACPI_INFO, ("| SleepButton[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer)); + break; + + case BN_TYPE_LID_SWITCH: + DEBUG_PRINT(ACPI_INFO, ("| LidSwitch[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer)); + break; + } + + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + acpi_os_free(buffer.pointer); +#endif /*ACPI_DEBUG*/ + + return; +} + + +/**************************************************************************** + * + * FUNCTION: bn_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_add_device( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BN_CONTEXT *button = NULL; + + FUNCTION_TRACE("bn_add_device"); + + DEBUG_PRINT(ACPI_INFO, ("Adding button device [0x%02x].\n", device_handle)); + + if (!context || *context) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid context.\n")); + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Get information on this device. + */ + status = bm_get_device_info( device_handle, &device ); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Allocate a new BN_CONTEXT structure. + */ + button = acpi_os_callocate(sizeof(BN_CONTEXT)); + if (!button) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + button->device_handle = device->handle; + button->acpi_handle = device->acpi_handle; + + /* + * Power Button? + * ------------- + * Either fixed-feature or generic (namespace) types. + */ + if (strncmp(device->id.hid, BN_HID_POWER_BUTTON, + sizeof(BM_DEVICE_HID)) == 0) { + + if (device->id.type == BM_TYPE_FIXED_BUTTON) { + + button->type = BN_TYPE_POWER_BUTTON_FIXED; + + /* Register for fixed-feature events. */ + status = acpi_install_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, bn_notify_fixed, + (void*)button); + } + else { + button->type = BN_TYPE_POWER_BUTTON; + } + + //proc_mkdir(BN_PROC_POWER_BUTTON, bn_proc_root); + + } + + /* + * Sleep Button? + * ------------- + * Either fixed-feature or generic (namespace) types. + */ + else if (strncmp( device->id.hid, BN_HID_SLEEP_BUTTON, + sizeof(BM_DEVICE_HID)) == 0) { + + if (device->id.type == BM_TYPE_FIXED_BUTTON) { + + button->type = BN_TYPE_SLEEP_BUTTON_FIXED; + + /* Register for fixed-feature events. */ + status = acpi_install_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed, + (void*)button); + } + else { + button->type = BN_TYPE_SLEEP_BUTTON; + } + + //proc_mkdir(BN_PROC_SLEEP_BUTTON, bn_proc_root); + } + + /* + * LID Switch? + * ----------- + */ + else if (strncmp( device->id.hid, BN_HID_LID_SWITCH, + sizeof(BM_DEVICE_HID)) == 0) { + + button->type = BN_TYPE_LID_SWITCH; + + //proc_mkdir(BN_PROC_LID_SWITCH, bn_proc_root); + } + + *context = button; + + bn_print(button); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_remove_device( + void **context) +{ + ACPI_STATUS status = AE_OK; + BN_CONTEXT *button = NULL; + + FUNCTION_TRACE("bn_remove_device"); + + if (!context || !*context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + button = (BN_CONTEXT*)*context; + + DEBUG_PRINT(ACPI_INFO, ("Removing button device [0x%02x].\n", button->device_handle)); + + /* + * Remove the /proc entry for this button. + */ + switch (button->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + /* Unregister for fixed-feature events. */ + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_POWER_BUTTON, bn_notify_fixed); + //remove_proc_entry(BN_PROC_POWER_BUTTON, bn_proc_root); + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + /* Unregister for fixed-feature events. */ + status = acpi_remove_fixed_event_handler( + ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed); + //remove_proc_entry(BN_PROC_SLEEP_BUTTON, bn_proc_root); + break; + + case BN_TYPE_LID_SWITCH: + //remove_proc_entry(BN_PROC_LID_SWITCH, bn_proc_root); + break; + } + + acpi_os_free(button); + + *context = NULL; + + return_ACPI_STATUS(status); +} + + +/***************************************************************************** + * External Functions + *****************************************************************************/ + +/***************************************************************************** + * + * FUNCTION: bn_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + + ****************************************************************************/ + +ACPI_STATUS +bn_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + FUNCTION_TRACE("bn_initialize"); + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + driver.notify = &bn_notify; + driver.request = &bn_request; + + /* + * Create button's root /proc entry. + */ + //bn_proc_root = proc_mkdir(BN_PROC_ROOT, bm_proc_root); + //if (!bn_proc_root) { +// return_ACPI_STATUS(AE_ERROR); +// } + + /* + * Register for power buttons. + */ + MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON)); + status = bm_register_driver(&criteria, &driver); + + /* + * Register for sleep buttons. + */ + MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON)); + status = bm_register_driver(&criteria, &driver); + + /* + * Register for LID switches. + */ + MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH)); + status = bm_register_driver(&criteria, &driver); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + FUNCTION_TRACE("bn_terminate"); + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + driver.notify = &bn_notify; + driver.request = &bn_request; + + /* + * Unregister for power buttons. + */ + MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON)); + status = bm_unregister_driver(&criteria, &driver); + + /* + * Unregister for sleep buttons. + */ + MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON)); + status = bm_unregister_driver(&criteria, &driver); + + /* + * Unregister for LID switches. + */ + MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH)); + status = bm_unregister_driver(&criteria, &driver); + + /* + * Remove button's root /proc entry. + */ + if (bn_proc_root) { + //remove_proc_entry(BN_PROC_ROOT, bm_proc_root); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_notify_fixed + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_notify_fixed ( + void *context) +{ + ACPI_STATUS status = AE_OK; + BN_CONTEXT *button = NULL; + + FUNCTION_TRACE("bn_notify_fixed"); + + if (!context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + button = (BN_CONTEXT*)context; + + DbgPrint("Fixed button status change event detected.\n"); + + switch (button->type) { + + case BN_TYPE_POWER_BUTTON_FIXED: + DEBUG_PRINT(ACPI_INFO, ("Fixed-feature button status change event detected.\n")); + /*bm_generate_event(button->device_handle, BN_PROC_ROOT, + BN_PROC_POWER_BUTTON, BN_NOTIFY_STATUS_CHANGE, 0);*/ + break; + + case BN_TYPE_SLEEP_BUTTON_FIXED: + DEBUG_PRINT(ACPI_INFO, ("Fixed-feature button status change event detected.\n")); + /*bm_generate_event(button->device_handle, BN_PROC_ROOT, + BN_PROC_SLEEP_BUTTON, BN_NOTIFY_STATUS_CHANGE, 0);*/ + break; + + default: + DEBUG_PRINT(ACPI_INFO, ("Unsupported fixed-feature event detected.\n")); + status = AE_SUPPORT; + break; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bn_notify"); + + if (!context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + switch (notify_type) { + case BM_NOTIFY_DEVICE_ADDED: + status = bn_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = bn_remove_device(context); + break; + + case BN_NOTIFY_STATUS_CHANGE: + DEBUG_PRINT(ACPI_INFO, ("Button status change event detected.\n")); + + DbgPrint("Button status change event detected.\n"); + + if (!context || !*context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + switch(((BN_CONTEXT*)*context)->type) { + + case BN_TYPE_POWER_BUTTON: + case BN_TYPE_POWER_BUTTON_FIXED: + /*bm_generate_event(device_handle, BN_PROC_ROOT, + BN_PROC_POWER_BUTTON, notify_type, 0);*/ + break; + + case BN_TYPE_SLEEP_BUTTON: + case BN_TYPE_SLEEP_BUTTON_FIXED: + /*bm_generate_event(device_handle, BN_PROC_ROOT, + BN_PROC_SLEEP_BUTTON, notify_type, 0);*/ + break; + + case BN_TYPE_LID_SWITCH: + /*bm_generate_event(device_handle, BN_PROC_ROOT, + BN_PROC_LID_SWITCH, notify_type, 0);*/ + break; + + default: + status = AE_SUPPORT; + break; + } + + break; + + default: + status = AE_SUPPORT; + break; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bn_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bn_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bn_request"); + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Handle Request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return_ACPI_STATUS(status); +} diff --git a/drivers/bus/acpi/ospm/busmgr/bm.c b/drivers/bus/acpi/ospm/busmgr/bm.c new file mode 100644 index 0000000..1f39e65 --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bm.c @@ -0,0 +1,1047 @@ +/****************************************************************************** + * + * Module Name: bm.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bm") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern FADT_DESCRIPTOR_REV2 acpi_fadt; +/* TODO: Make dynamically sizeable. */ +static BM_NODE_LIST node_list; + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print ( + BM_NODE *node, + u32 flags) +{ + ACPI_BUFFER buffer; + BM_DEVICE *device = NULL; + char *type_string = NULL; + + if (!node) { + return; + } + + device = &(node->device); + + if (flags & BM_PRINT_PRESENT) { + if (!BM_DEVICE_PRESENT(device)) { + return; + } + } + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + acpi_get_name(device->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + + switch(device->id.type) { + case BM_TYPE_SYSTEM: + type_string = "System"; + break; + case BM_TYPE_SCOPE: + type_string = "Scope"; + break; + case BM_TYPE_PROCESSOR: + type_string = "Processor"; + break; + case BM_TYPE_THERMAL_ZONE: + type_string = "ThermalZone"; + break; + case BM_TYPE_POWER_RESOURCE: + type_string = "PowerResource"; + break; + case BM_TYPE_FIXED_BUTTON: + type_string = "Button"; + break; + case BM_TYPE_DEVICE: + type_string = "Device"; + break; + default: + type_string = "Unknown"; + break; + } + + if (!(flags & BM_PRINT_GROUP)) { + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + } + + DEBUG_PRINT(ACPI_INFO, ("%s[0x%02x] hid[%s] %s\n", type_string, device->handle, device->id.hid, buffer.pointer)); + DEBUG_PRINT(ACPI_INFO, (" acpi_handle[0x%08x] flags[0x%02x] status[0x%02x]\n", device->acpi_handle, device->flags, device->status)); + + if (flags & BM_PRINT_IDENTIFICATION) { + DEBUG_PRINT(ACPI_INFO, (" identification: uid[%s] adr[0x%08x]\n", device->id.uid, device->id.adr)); + } + + if (flags & BM_PRINT_LINKAGE) { + DEBUG_PRINT(ACPI_INFO, (" linkage: this[%p] parent[%p] next[%p]\n", node, node->parent, node->next)); + DEBUG_PRINT(ACPI_INFO, (" scope.head[%p] scope.tail[%p]\n", node->scope.head, node->scope.tail)); + } + + if (flags & BM_PRINT_POWER) { + DEBUG_PRINT(ACPI_INFO, (" power: state[D%d] flags[0x%08X]\n", device->power.state, device->power.flags)); + DEBUG_PRINT(ACPI_INFO, (" S0[0x%02x] S1[0x%02x] S2[0x%02x]\n", device->power.dx_supported[0], device->power.dx_supported[1], device->power.dx_supported[2])); + DEBUG_PRINT(ACPI_INFO, (" S3[0x%02x] S4[0x%02x] S5[0x%02x]\n", device->power.dx_supported[3], device->power.dx_supported[4], device->power.dx_supported[5])); + } + + if (!(flags & BM_PRINT_GROUP)) { + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + } + + acpi_os_free(buffer.pointer); + + return; +} + + +/**************************************************************************** + * + * FUNCTION: bm_print_hierarchy + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_hierarchy (void) +{ + u32 i = 0; + + FUNCTION_TRACE("bm_print_hierarchy"); + + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + for (i = 0; i < node_list.count; i++) { + bm_print(node_list.nodes[i], BM_PRINT_GROUP | BM_PRINT_PRESENT); + } + + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + return_VOID; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_status + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_status ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + + if (!device) { + return AE_BAD_PARAMETER; + } + + device->status = BM_STATUS_UNKNOWN; + + /* + * Dynamic Status? + * --------------- + * If _STA isn't present we just return the default status. + */ + if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) { + device->status = BM_STATUS_DEFAULT; + return AE_OK; + } + + /* + * Evaluate _STA: + * -------------- + */ + status = bm_evaluate_simple_integer(device->acpi_handle, "_STA", + &(device->status)); + + return status; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_identification + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_identification ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + ACPI_DEVICE_INFO info; + + if (!device) { + return AE_BAD_PARAMETER; + } + + if (!(device->flags & BM_FLAGS_IDENTIFIABLE)) { + return AE_OK; + } + + MEMSET(&(device->id.uid), 0, sizeof(device->id.uid)); + MEMSET(&(device->id.hid), 0, sizeof(device->id.hid)); + device->id.adr = BM_ADDRESS_UNKNOWN; + + /* + * Get Object Info: + * ---------------- + * Evalute _UID, _HID, _ADR, and _STA... + */ + status = acpi_get_object_info(device->acpi_handle, &info); + if (ACPI_FAILURE(status)) { + return status; + } + + if (info.valid & ACPI_VALID_UID) { + MEMCPY((void*)device->id.uid, (void*)info.unique_id, + sizeof(BM_DEVICE_UID)); + } + + if (info.valid & ACPI_VALID_HID) { + MEMCPY((void*)device->id.hid, (void*)info.hardware_id, + sizeof(BM_DEVICE_HID)); + } + + if (info.valid & ACPI_VALID_ADR) { + device->id.adr = info.address; + } + + return status; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_flags + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_flags ( + BM_DEVICE *device) +{ + ACPI_HANDLE acpi_handle = NULL; + + if (!device) { + return AE_BAD_PARAMETER; + } + + device->flags = BM_FLAGS_UNKNOWN; + + switch (device->id.type) { + + case BM_TYPE_DEVICE: + + /* + * Presence of _DCK indicates a docking station. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_DCK", &acpi_handle))) { + device->flags |= BM_FLAGS_DOCKING_STATION; + } + + /* + * Presence of _EJD and/or _EJx indicates 'ejectable'. + * TODO: _EJx... + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_EJD", &acpi_handle))) { + device->flags |= BM_FLAGS_EJECTABLE; + } + + /* + * Presence of _PR0 or _PS0 indicates 'power manageable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_PR0", &acpi_handle)) || + ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_PS0", &acpi_handle))) { + device->flags |= BM_FLAGS_POWER_CONTROL; + } + + /* + * Presence of _CRS indicates 'configurable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_CRS", &acpi_handle))) { + device->flags |= BM_FLAGS_CONFIGURABLE; + } + + /* Fall through to next case statement. */ + + case BM_TYPE_PROCESSOR: + case BM_TYPE_THERMAL_ZONE: + case BM_TYPE_POWER_RESOURCE: + /* + * Presence of _HID or _ADR indicates 'identifiable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_HID", &acpi_handle)) || + ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_ADR", &acpi_handle))) { + device->flags |= BM_FLAGS_IDENTIFIABLE; + } + + /* + * Presence of _STA indicates 'dynamic status'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_STA", &acpi_handle))) { + device->flags |= BM_FLAGS_DYNAMIC_STATUS; + } + + break; + } + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: bm_add_namespace_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_add_namespace_device ( + ACPI_HANDLE acpi_handle, + ACPI_OBJECT_TYPE acpi_type, + BM_NODE *parent, + BM_NODE **child) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_add_namespace_device"); + + if (!parent || !child) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node_list.count > BM_HANDLES_MAX) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + (*child) = NULL; + + /* + * Create Node: + * ------------ + */ + node = acpi_os_callocate(sizeof(BM_NODE)); + if (!node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + node->parent = parent; + node->next = NULL; + + device = &(node->device); + + device->handle = node_list.count; + device->acpi_handle = acpi_handle; + + /* + * Device Type: + * ------------ + */ + switch (acpi_type) { + case INTERNAL_TYPE_SCOPE: + device->id.type = BM_TYPE_SCOPE; + break; + case ACPI_TYPE_PROCESSOR: + device->id.type = BM_TYPE_PROCESSOR; + break; + case ACPI_TYPE_THERMAL: + device->id.type = BM_TYPE_THERMAL_ZONE; + break; + case ACPI_TYPE_POWER: + device->id.type = BM_TYPE_POWER_RESOURCE; + break; + case ACPI_TYPE_DEVICE: + device->id.type = BM_TYPE_DEVICE; + break; + } + + /* + * Get Other Device Info: + * ---------------------- + * But only if this device's parent is present (which implies + * this device MAY be present). + */ + if (BM_NODE_PRESENT(node->parent)) { + /* + * Device Flags + */ + status = bm_get_flags(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Device Identification + */ + status = bm_get_identification(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Device Status + */ + status = bm_get_status(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Power Management: + * ----------------- + * If this node doesn't provide direct power control + * then we inherit PM capabilities from its parent. + * + * TODO: Inherit! + */ + if (device->flags & BM_FLAGS_POWER_CONTROL) { + status = bm_get_pm_capabilities(node); + if (ACPI_FAILURE(status)) { + goto end; + } + } + } + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(node); + } + else { + /* + * Add to the node_list. + */ + node_list.nodes[node_list.count++] = node; + + /* + * Formulate Hierarchy: + * -------------------- + * Arrange within the namespace by assigning the parent and + * adding to the parent device's list of children (scope). + */ + if (!parent->scope.head) { + parent->scope.head = node; + } + else { + if (!parent->scope.tail) { + (parent->scope.head)->next = node; + } + else { + (parent->scope.tail)->next = node; + } + } + parent->scope.tail = node; + + (*child) = node; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_enumerate_namespace + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_enumerate_namespace (void) +{ + ACPI_STATUS status = AE_OK; + ACPI_HANDLE parent_handle = ACPI_ROOT_OBJECT; + ACPI_HANDLE child_handle = NULL; + BM_NODE *parent = NULL; + BM_NODE *child = NULL; + ACPI_OBJECT_TYPE acpi_type = 0; + u32 level = 1; + + FUNCTION_TRACE("bm_enumerate_namespace"); + + parent = node_list.nodes[0]; + + /* + * Enumerate ACPI Namespace: + * ------------------------- + * Parse through the ACPI namespace, identify all 'devices', + * and create a new entry for each in our collection. + */ + while (level > 0) { + + /* + * Get the next object at this level. + */ + status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle); + if (ACPI_SUCCESS(status)) { + + /* + * TODO: This is a hack to get around the problem + * identifying scope objects. Scopes + * somehow need to be uniquely identified. + */ + status = acpi_get_type(child_handle, &acpi_type); + if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); + if (ACPI_SUCCESS(status)) { + acpi_type = INTERNAL_TYPE_SCOPE; + } + } + + /* + * Device? + * ------- + * If this object is a 'device', insert into the + * ACPI Bus Manager's local hierarchy and search + * the object's scope for any child devices (a + * depth-first search). + */ + switch (acpi_type) { + case INTERNAL_TYPE_SCOPE: + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_POWER: + status = bm_add_namespace_device(child_handle, acpi_type, parent, &child); + if (ACPI_SUCCESS(status)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + parent_handle = child_handle; + child_handle = 0; + parent = child; + } + } + break; + } + } + + /* + * Scope Exhausted: + * ---------------- + * No more children in this object's scope, Go back up + * in the namespace tree to the object's parent. + */ + else { + level--; + child_handle = parent_handle; + acpi_get_parent(parent_handle, + &parent_handle); + + if (parent) { + parent = parent->parent; + } + else { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_add_fixed_feature_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_add_fixed_feature_device ( + BM_NODE *parent, + BM_DEVICE_TYPE device_type, + char *device_hid) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_add_fixed_feature_device"); + + if (!parent) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node_list.count > BM_HANDLES_MAX) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Allocate the new device and add to the device array. + */ + node = acpi_os_callocate(sizeof(BM_NODE)); + if (!node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Get device info. + */ + node->device.handle = node_list.count; + node->device.acpi_handle = ACPI_ROOT_OBJECT; + node->device.id.type = BM_TYPE_FIXED_BUTTON; + if (device_hid) { + MEMCPY((void*)node->device.id.hid, device_hid, + sizeof(node->device.id.hid)); + } + node->device.flags = BM_FLAGS_FIXED_FEATURE; + node->device.status = BM_STATUS_DEFAULT; + /* TODO: Device PM capabilities */ + + /* + * Add to the node_list. + */ + node_list.nodes[node_list.count++] = node; + + /* + * Formulate Hierarchy: + * -------------------- + * Arrange within the namespace by assigning the parent and + * adding to the parent device's list of children (scope). + */ + node->parent = parent; + node->next = NULL; + + if (parent) { + if (!parent->scope.head) { + parent->scope.head = node; + } + else { + if (!parent->scope.tail) { + (parent->scope.head)->next = node; + } + else { + (parent->scope.tail)->next = node; + } + } + parent->scope.tail = node; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_enumerate_fixed_features + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_enumerate_fixed_features (void) +{ + FUNCTION_TRACE("bm_enumerate_fixed_features"); + + /* + * Root Object: + * ------------ + * Fabricate the root object, which happens to always get a + * device_handle of zero. + */ + node_list.nodes[0] = acpi_os_callocate(sizeof(BM_NODE)); + if (NULL == (node_list.nodes[0])) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + node_list.nodes[0]->device.handle = BM_HANDLE_ROOT; + node_list.nodes[0]->device.acpi_handle = ACPI_ROOT_OBJECT; + node_list.nodes[0]->device.flags = BM_FLAGS_UNKNOWN; + node_list.nodes[0]->device.status = BM_STATUS_DEFAULT; + node_list.nodes[0]->device.id.type = BM_TYPE_SYSTEM; + /* TODO: Get system PM capabilities (Sx states?) */ + + node_list.count++; + + /* + * Fixed Features: + * --------------- + * Enumerate fixed-feature devices (e.g. power and sleep buttons). + */ + if (acpi_fadt.pwr_button == 0) { + bm_add_fixed_feature_device(node_list.nodes[0], + BM_TYPE_FIXED_BUTTON, BM_HID_POWER_BUTTON); + } + + if (acpi_fadt.sleep_button == 0) { + bm_add_fixed_feature_device(node_list.nodes[0], + BM_TYPE_FIXED_BUTTON, BM_HID_SLEEP_BUTTON); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_handle + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_handle ( + ACPI_HANDLE acpi_handle, + BM_HANDLE *device_handle) +{ + ACPI_STATUS status = AE_OK; + u32 i = 0; + + FUNCTION_TRACE("bm_get_handle"); + + if (!device_handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *device_handle = BM_HANDLE_UNKNOWN; + + /* + * Search all devices for a match on the ACPI handle. + */ + for (i=0; idevice.acpi_handle == acpi_handle) { + *device_handle = node_list.nodes[i]->device.handle; + break; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_node + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_node ( + BM_HANDLE device_handle, + ACPI_HANDLE acpi_handle, + BM_NODE **node) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_get_node"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * If no device handle, resolve acpi handle to device handle. + */ + if (!device_handle && acpi_handle) { + status = bm_get_handle(acpi_handle, &device_handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + } + + /* + * Valid device handle? + */ + if (device_handle > BM_HANDLES_MAX) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid node handle [0x%02x] detected.\n", device_handle)); + return_ACPI_STATUS(AE_ERROR); + } + + *node = node_list.nodes[device_handle]; + + /* + * Valid node? + */ + if (!(*node)) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [0x%02x] detected.\n", device_handle)); + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_initialize + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_initialize (void) +{ + ACPI_STATUS status = AE_OK; + u32 start = 0; + u32 stop = 0; + u32 elapsed = 0; + + FUNCTION_TRACE("bm_initialize"); + + MEMSET(&node_list, 0, sizeof(BM_HANDLE_LIST)); + + acpi_get_timer(&start); + + DEBUG_PRINT(ACPI_INFO, ("Building device hierarchy.\n")); + + /* + * Enumerate ACPI fixed-feature devices. + */ + status = bm_enumerate_fixed_features(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Enumerate the ACPI namespace. + */ + status = bm_enumerate_namespace(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_get_timer(&stop); + acpi_get_timer_duration(start, stop, &elapsed); + + DEBUG_PRINT(ACPI_INFO, ("Device heirarchy build took [%d] microseconds.\n", elapsed)); + + /* + * Display hierarchy. + */ +#ifdef ACPI_DEBUG + bm_print_hierarchy(); +#endif /*ACPI_DEBUG*/ + + /* + * Register for all standard and device-specific notifications. + */ + DEBUG_PRINT(ACPI_INFO, ("Registering for all device notifications.\n")); + + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &bm_notify, NULL); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to register for standard notifications.\n")); + return_ACPI_STATUS(status); + } + + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, + ACPI_DEVICE_NOTIFY, &bm_notify, NULL); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to register for device-specific notifications.\n")); + return_ACPI_STATUS(status); + } + + /* + * Initialize /proc interface. + */ + //DEBUG_PRINT(ACPI_INFO, ("Initializing /proc interface.\n")); + //status = bm_proc_initialize(); + + DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager enabled.\n")); + + /* + * Initialize built-in power resource driver. + */ + bm_pr_initialize(); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_terminate + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_terminate (void) +{ + ACPI_STATUS status = AE_OK; + u32 i = 0; + + FUNCTION_TRACE("bm_terminate"); + + /* + * Terminate built-in power resource driver. + */ + bm_pr_terminate(); + + /* + * Remove the /proc interface. + */ + //DEBUG_PRINT(ACPI_INFO, ("Removing /proc interface.\n")); + //status = bm_proc_terminate(); + + + /* + * Unregister for all notifications. + */ + + DEBUG_PRINT(ACPI_INFO, ("Unregistering for device notifications.\n")); + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &bm_notify); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for standard notifications.\n")); + } + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_DEVICE_NOTIFY, &bm_notify); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for device-specific notifications.\n")); + } + + /* + * Parse through the device array, freeing all entries. + */ + DEBUG_PRINT(ACPI_INFO, ("Removing device hierarchy.\n")); + for (i = 0; i < node_list.count; i++) { + if (node_list.nodes[i]) { + acpi_os_free(node_list.nodes[i]); + } + } + + DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager disabled.\n")); + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/bus/acpi/ospm/busmgr/bmnotify.c b/drivers/bus/acpi/ospm/busmgr/bmnotify.c new file mode 100644 index 0000000..2d9f136 --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmnotify.c @@ -0,0 +1,310 @@ +/***************************************************************************** + * + * Module Name: bmnotify.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmnotify") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_generate_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_generate_notify ( + BM_NODE *node, + u32 notify_type) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_generate_notify"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + DEBUG_PRINT(ACPI_INFO, ("Sending notify [0x%02x] to device [0x%02x].\n", notify_type, node->device.handle)); + + if (!(node->device.flags & BM_FLAGS_DRIVER_CONTROL) || + !(node->driver.notify)) { + DEBUG_PRINT(ACPI_WARN, ("No driver installed for device [0x%02x].\n", node->device.handle)); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + status = node->driver.notify(notify_type, node->device.handle, + &(node->driver.context)); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_device_check + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_device_check ( + BM_NODE *node, + u32 *status_change) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BM_DEVICE_STATUS old_status = BM_STATUS_UNKNOWN; + + FUNCTION_TRACE("bm_device_check"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + + if (status_change) { + *status_change = FALSE; + } + + old_status = device->status; + + /* + * Parent Present? + * --------------- + * Only check this device if its parent is present (which implies + * this device MAY be present). + */ + if (!BM_NODE_PRESENT(node->parent)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Get Status: + * ----------- + * And see if the status has changed. + */ + status = bm_get_status(device); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (old_status == node->device.status) { + return_ACPI_STATUS(AE_OK); + } + + if (status_change) { + *status_change = TRUE; + } + + /* + * Device Insertion? + * ----------------- + */ + if ((device->status & BM_STATUS_PRESENT) && + !(old_status & BM_STATUS_PRESENT)) { + /* TODO: Make sure driver is loaded, and if not, load. */ + status = bm_generate_notify(node, BM_NOTIFY_DEVICE_ADDED); + } + + /* + * Device Removal? + * --------------- + */ + else if (!(device->status & BM_STATUS_PRESENT) && + (old_status & BM_STATUS_PRESENT)) { + /* TODO: Unload driver if last device instance. */ + status = bm_generate_notify(node, BM_NOTIFY_DEVICE_REMOVED); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_bus_check + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_bus_check ( + BM_NODE *parent_node) +{ + ACPI_STATUS status = AE_OK; + u32 status_change = FALSE; + + FUNCTION_TRACE("bm_bus_check"); + + if (!parent_node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Status Change? + * -------------- + */ + status = bm_device_check(parent_node, &status_change); + if (ACPI_FAILURE(status) || !status_change) { + return_ACPI_STATUS(status); + } + + /* + * Enumerate Scope: + * ---------------- + * TODO: Enumerate child devices within this device's scope and + * run bm_device_check()'s on them... + */ + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_notify ( + ACPI_HANDLE acpi_handle, + u32 notify_value, + void *context) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_notify"); + + /* + * Resolve the ACPI handle. + */ + status = bm_get_node(0, acpi_handle, &node); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_INFO, ("Recieved notify [0x%02x] for unknown device [%p].\n", notify_value, acpi_handle)); + return_VOID; + } + + /* + * Device-Specific or Standard? + * ---------------------------- + * Device-specific notifies are forwarded to the control module's + * notify() function for processing. Standard notifies are handled + * internally. + */ + if (notify_value > 0x7F) { + status = bm_generate_notify(node, notify_value); + } + else { + switch (notify_value) { + + case BM_NOTIFY_BUS_CHECK: + DEBUG_PRINT(ACPI_INFO, ("Received BUS CHECK notification.\n")); + status = bm_bus_check(node); + break; + + case BM_NOTIFY_DEVICE_CHECK: + DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK notification.\n")); + status = bm_device_check(node, NULL); + break; + + case BM_NOTIFY_DEVICE_WAKE: + DEBUG_PRINT(ACPI_INFO, ("Received DEVICE WAKE notification.\n")); + /* TODO */ + break; + + case BM_NOTIFY_EJECT_REQUEST: + DEBUG_PRINT(ACPI_INFO, ("Received EJECT REQUEST notification.\n")); + /* TODO */ + break; + + case BM_NOTIFY_DEVICE_CHECK_LIGHT: + DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK LIGHT notification.\n")); + /* TODO: Exactly what does the 'light' mean? */ + status = bm_device_check(node, NULL); + break; + + case BM_NOTIFY_FREQUENCY_MISMATCH: + DEBUG_PRINT(ACPI_INFO, ("Received FREQUENCY MISMATCH notification.\n")); + /* TODO */ + break; + + case BM_NOTIFY_BUS_MODE_MISMATCH: + DEBUG_PRINT(ACPI_INFO, ("Received BUS MODE MISMATCH notification.\n")); + /* TODO */ + break; + + case BM_NOTIFY_POWER_FAULT: + DEBUG_PRINT(ACPI_INFO, ("Received POWER FAULT notification.\n")); + /* TODO */ + break; + + default: + DEBUG_PRINT(ACPI_INFO, ("Received unknown/unsupported notification.\n")); + break; + } + } + + return_VOID; +} + + diff --git a/drivers/bus/acpi/ospm/busmgr/bmpm.c b/drivers/bus/acpi/ospm/busmgr/bmpm.c new file mode 100644 index 0000000..75676dc --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmpm.c @@ -0,0 +1,397 @@ +/***************************************************************************** + * + * Module Name: bmpm.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" +#include "bmpower.h" + + +#define _COMPONENT ACPI_POWER_CONTROL + MODULE_NAME ("bmpm") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_inferred_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_inferred_power_state ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + BM_HANDLE_LIST pr_list; + BM_POWER_STATE list_state = ACPI_STATE_UNKNOWN; + char object_name[5] = {'_','P','R','0','\0'}; + u32 i = 0; + + FUNCTION_TRACE("bm_get_inferred_power_state"); + + if (!device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&pr_list, 0, sizeof(BM_HANDLE_LIST)); + + device->power.state = ACPI_STATE_D3; + + /* + * Calculate Power State: + * ---------------------- + * Try to infer the devices's power state by checking the state of + * the devices's power resources. We start by evaluating _PR0 + * (resource requirements at D0) and work through _PR1 and _PR2. + * We know the current devices power state when all resources (for + * a give Dx state) are ON. If no power resources are on then the + * device is assumed to be off (D3). + */ + for (i=ACPI_STATE_D0; iacpi_handle, + object_name, &pr_list); + + if (ACPI_SUCCESS(status)) { + + status = bm_pr_list_get_state(&pr_list, + &list_state); + + if (ACPI_SUCCESS(status)) { + + if (list_state == ACPI_STATE_D0) { + device->power.state = i; + break; + } + } + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_power_state ( + BM_NODE *node) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_get_power_state"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + + device->power.state = ACPI_STATE_UNKNOWN; + + if (device->flags & BM_FLAGS_POWER_STATE) { + status = bm_evaluate_simple_integer(device->acpi_handle, + "_PSC", &(device->power.state)); + } + else { + status = bm_get_inferred_power_state(device); + } + + if (ACPI_SUCCESS(status)) { + DEBUG_PRINT(ACPI_INFO, ("Device [0x%02x] is at power state [D%d].\n", device->handle, device->power.state)); + } + else { + DEBUG_PRINT(ACPI_INFO, ("Error getting power state for device [0x%02x]\n", device->handle)); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_set_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_set_power_state ( + BM_NODE *node, + BM_POWER_STATE state) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BM_DEVICE *parent_device = NULL; + BM_HANDLE_LIST current_list; + BM_HANDLE_LIST target_list; + char object_name[5] = {'_','P','R','0','\0'}; + + FUNCTION_TRACE("bm_set_power_state"); + + if (!node || !node->parent || (state > ACPI_STATE_D3)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(¤t_list, 0, sizeof(BM_HANDLE_LIST)); + MEMSET(&target_list, 0, sizeof(BM_HANDLE_LIST)); + + device = &(node->device); + parent_device = &(node->parent->device); + + /* + * Check Parent's Power State: + * --------------------------- + * Can't be in a higher power state (lower Dx value) than parent. + */ + if (state < parent_device->power.state) { + DEBUG_PRINT(ACPI_WARN, ("Cannot set device [0x%02x] to a higher-powered state than parent_device.\n", device->handle)); + return_ACPI_STATUS(AE_ERROR); + } + + /* + * Get Resources: + * -------------- + * Get the power resources associated with the device's current + * and target power states. + */ + if (device->power.state != ACPI_STATE_UNKNOWN) { + object_name[3] = '0' + device->power.state; + bm_evaluate_reference_list(device->acpi_handle, + object_name, ¤t_list); + } + + object_name[3] = '0' + state; + bm_evaluate_reference_list(device->acpi_handle, object_name, + &target_list); + + /* + * Transition Resources: + * --------------------- + * Transition all power resources referenced by this device to + * the correct power state (taking into consideration sequencing + * and dependencies to other devices). + */ + if (current_list.count || target_list.count) { + status = bm_pr_list_transition(¤t_list, &target_list); + } + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Execute _PSx: + * ------------- + * Execute the _PSx method corresponding to the target Dx state, + * if it exists. + */ + object_name[2] = 'S'; + object_name[3] = '0' + state; + bm_evaluate_object(device->acpi_handle, object_name, NULL, NULL); + + if (ACPI_SUCCESS(status)) { + DEBUG_PRINT(ACPI_INFO, ("Device [0x%02x] is now at [D%d].\n", device->handle, state)); + device->power.state = state; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_pm_capabilities + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_pm_capabilities ( + BM_NODE *node) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE *device = NULL; + BM_DEVICE *parent_device = NULL; + ACPI_HANDLE acpi_handle = NULL; + BM_POWER_STATE dx_supported = ACPI_STATE_UNKNOWN; + char object_name[5] = {'_','S','0','D','\0'}; + u32 i = 0; + + FUNCTION_TRACE("bm_get_pm_capabilities"); + + if (!node || !node->parent) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + device = &(node->device); + parent_device = &(node->parent->device); + + /* + * Power Management Flags: + * ----------------------- + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PSC", + &acpi_handle))) { + device->power.flags |= BM_FLAGS_POWER_STATE; + } + + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_IRC", + &acpi_handle))) { + device->power.flags |= BM_FLAGS_INRUSH_CURRENT; + } + + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PRW", + &acpi_handle))) { + device->power.flags |= BM_FLAGS_WAKE_CAPABLE; + } + + /* + * Device Power State: + * ------------------- + * Note that we can't get the device's power state until we've + * initialized all power resources, so for now we just set to + * unknown. + */ + device->power.state = ACPI_STATE_UNKNOWN; + + /* + * Dx Supported in S0: + * ------------------- + * Figure out which Dx states are supported by this device for the + * S0 (working) state. Note that D0 and D3 are required (assumed). + */ + device->power.dx_supported[ACPI_STATE_S0] = BM_FLAGS_D0_SUPPORT | + BM_FLAGS_D3_SUPPORT; + + if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR1", + &acpi_handle))) || + (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS1", + &acpi_handle)))) { + device->power.dx_supported[ACPI_STATE_S0] |= + BM_FLAGS_D1_SUPPORT; + } + + if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR2", + &acpi_handle))) || + (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS2", + &acpi_handle)))) { + device->power.dx_supported[ACPI_STATE_S0] |= + BM_FLAGS_D2_SUPPORT; + } + + /* + * Dx Supported in S1-S5: + * ---------------------- + * Figure out which Dx states are supported by this device for + * all other Sx states. + */ + for (i = ACPI_STATE_S1; i <= ACPI_STATE_S5; i++) { + + /* + * D3 support is assumed (off is always possible!). + */ + device->power.dx_supported[i] = BM_FLAGS_D3_SUPPORT; + + /* + * Evalute _SxD: + * ------------- + * Which returns the highest (power) Dx state supported in + * this system (Sx) state. We convert this value to a bit + * mask of supported states (conceptually simpler). + */ + status = bm_evaluate_simple_integer(device->acpi_handle, + object_name, &dx_supported); + if (ACPI_SUCCESS(status)) { + switch (dx_supported) { + case 0: + device->power.dx_supported[i] |= + BM_FLAGS_D0_SUPPORT; + /* fall through */ + case 1: + device->power.dx_supported[i] |= + BM_FLAGS_D1_SUPPORT; + /* fall through */ + case 2: + device->power.dx_supported[i] |= + BM_FLAGS_D2_SUPPORT; + /* fall through */ + case 3: + device->power.dx_supported[i] |= + BM_FLAGS_D3_SUPPORT; + break; + } + + /* + * Validate: + * --------- + * Mask of any states that _Sx_d falsely advertises + * (e.g.claims D1 support but neither _PR2 or _PS2 + * exist). In other words, S1-S5 can't offer a Dx + * state that isn't supported by S0. + */ + device->power.dx_supported[i] &= + device->power.dx_supported[ACPI_STATE_S0]; + } + + object_name[2]++; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/bus/acpi/ospm/busmgr/bmpower.c b/drivers/bus/acpi/ospm/busmgr/bmpower.c new file mode 100644 index 0000000..8d0d6a8 --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmpower.c @@ -0,0 +1,669 @@ +/**************************************************************************** + * + * Module Name: bmpower.c - Driver for ACPI Power Resource 'devices' + * $Revision$ + * + ****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * TODO: + * ----- + * 1. Sequencing of power resource list transitions. + * 2. Global serialization of power resource transtions (see ACPI + * spec section 7.1.2/7.1.3). + * 3. Better error handling. + */ + + +#include +#include "bm.h" +#include "bmpower.h" + + +#define _COMPONENT ACPI_POWER_CONTROL + MODULE_NAME ("bmpower") + + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +ACPI_STATUS +bm_pr_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context); + +ACPI_STATUS +bm_pr_request ( + BM_REQUEST *request, + void *context); + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_pr_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_print ( + BM_POWER_RESOURCE *pr) +{ + ACPI_BUFFER buffer; + + if (!pr) { + return(AE_BAD_PARAMETER); + } + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return(AE_NO_MEMORY); + } + + acpi_get_name(pr->acpi_handle, ACPI_FULL_PATHNAME, &buffer); + + acpi_os_printf("Power Resource: found\n"); + + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + DEBUG_PRINT(ACPI_INFO, ("PowerResource[0x%02X]|[0x%08X] %s\n", pr->device_handle, pr->acpi_handle, buffer.pointer)); + DEBUG_PRINT(ACPI_INFO, (" system_level[S%d] resource_order[%d]\n", pr->system_level, pr->resource_order)); + DEBUG_PRINT(ACPI_INFO, (" state[D%d] reference_count[%d]\n", pr->state, pr->reference_count)); + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + acpi_os_free(buffer.pointer); + + return(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_get_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_get_state ( + BM_POWER_RESOURCE *pr) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_STATUS device_status = BM_STATUS_UNKNOWN; + + FUNCTION_TRACE("bm_pr_get_state"); + + if (!pr) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + pr->state = ACPI_STATE_UNKNOWN; + + /* + * Evaluate _STA: + * -------------- + * Evalute _STA to determine whether the power resource is ON or OFF. + * Note that if the power resource isn't present we'll get AE_OK but + * an unknown status. + */ + status = bm_get_device_status(pr->device_handle, &device_status); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Error reading status for power resource [0x%02x].\n", pr->device_handle)); + return_ACPI_STATUS(status); + } + if (device_status == BM_STATUS_UNKNOWN) { + DEBUG_PRINT(ACPI_ERROR, ("Error reading status for power resource [0x%02x].\n", pr->device_handle)); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* + * Mask off all bits but the first as some systems return non-standard + * values (e.g. 0x51). + */ + switch (device_status & 0x01) { + case 0: + DEBUG_PRINT(ACPI_INFO, ("Power resource [0x%02x] is OFF.\n", pr->device_handle)); + pr->state = ACPI_STATE_D3; + break; + case 1: + DEBUG_PRINT(ACPI_INFO, ("Power resource [0x%02x] is ON.\n", pr->device_handle)); + pr->state = ACPI_STATE_D0; + break; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_set_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_set_state ( + BM_POWER_RESOURCE *pr, + BM_POWER_STATE target_state) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_pr_set_state"); + + if (!pr) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + status = bm_pr_get_state(pr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (target_state == pr->state) { + DEBUG_PRINT(ACPI_INFO, ("Power resource [0x%02X] already at target power state [D%d].\n", pr->device_handle, pr->state)); + return_ACPI_STATUS(AE_OK); + } + + switch (target_state) { + + case ACPI_STATE_D0: + DEBUG_PRINT(ACPI_INFO, ("Turning power resource [0x%02X] ON.\n", pr->device_handle)); + status = bm_evaluate_object(pr->acpi_handle, "_ON", NULL, NULL); + break; + + case ACPI_STATE_D3: + DEBUG_PRINT(ACPI_INFO, ("Turning power resource [0x%02X] OFF.\n", pr->device_handle)); + status = bm_evaluate_object(pr->acpi_handle, "_OFF", NULL, NULL); + break; + + default: + status = AE_BAD_PARAMETER; + break; + } + + status = bm_pr_get_state(pr); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_list_get_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_list_get_state ( + BM_HANDLE_LIST *pr_list, + BM_POWER_STATE *power_state) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_pr_list_get_state"); + + if (!pr_list || !power_state) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (pr_list->count < 1) { + pr->state = ACPI_STATE_UNKNOWN; + return_ACPI_STATUS(AE_ERROR); + } + + (*power_state) = ACPI_STATE_D0; + + /* + * Calculate Current power_state: + * ----------------------------- + * The current state of a list of power resources is ON if all + * power resources are currently in the ON state. In other words, + * if any power resource in the list is OFF then the collection + * isn't fully ON. + */ + for (i = 0; i < pr_list->count; i++) { + + status = bm_get_device_context(pr_list->handles[i], + (BM_DRIVER_CONTEXT*)(&pr)); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [0x%02X].\n", pr_list->handles[i])); + (*power_state) = ACPI_STATE_UNKNOWN; + break; + } + + status = bm_pr_get_state(pr); + if (ACPI_FAILURE(status)) { + (*power_state) = ACPI_STATE_UNKNOWN; + break; + } + + if (pr->state != ACPI_STATE_D0) { + (*power_state) = pr->state; + break; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_list_transition + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_list_transition ( + BM_HANDLE_LIST *current_list, + BM_HANDLE_LIST *target_list) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_pr_list_transition"); + + if (!current_list || !target_list) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Reference Target: + * ----------------- + * Reference all resources for the target power state first (so + * the device doesn't get turned off while transitioning). Power + * resources that aren't on (new reference count of 1) are turned on. + */ + for (i = 0; i < target_list->count; i++) { + + status = bm_get_device_context(target_list->handles[i], + (BM_DRIVER_CONTEXT*)(&pr)); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [0x%02X].\n", target_list->handles[i])); + continue; + } + + if (++pr->reference_count == 1) { + /* TODO: Need ordering based upon resource_order */ + status = bm_pr_set_state(pr, ACPI_STATE_D0); + if (ACPI_FAILURE(status)) { + /* TODO: How do we handle this? */ + DEBUG_PRINT(ACPI_WARN, ("Unable to change power state for power resource [0x%02X].\n", target_list->handles[i])); + } + } + } + + /* + * Dereference Current: + * -------------------- + * Dereference all resources for the current power state. Power + * resources no longer referenced (new reference count of 0) are + * turned off. + */ + for (i = 0; i < current_list->count; i++) { + + status = bm_get_device_context(current_list->handles[i], + (BM_DRIVER_CONTEXT*)(&pr)); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [0x%02X].\n", target_list->handles[i])); + continue; + } + + if (--pr->reference_count == 0) { + /* TODO: Need ordering based upon resource_order */ + status = bm_pr_set_state(pr, ACPI_STATE_D3); + if (ACPI_FAILURE(status)) { + /* TODO: How do we handle this? */ + DEBUG_PRINT(ACPI_ERROR, ("Unable to change power state for power resource [0x%02X].\n", current_list->handles[i])); + } + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_add_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_add_device ( + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + BM_DEVICE *device = NULL; + ACPI_BUFFER buffer; + ACPI_OBJECT acpi_object; + + FUNCTION_TRACE("bm_pr_add_device"); + + DEBUG_PRINT(ACPI_INFO, ("Adding power resource [0x%02X].\n", device_handle)); + + if (!context || *context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + buffer.length = sizeof(ACPI_OBJECT); + buffer.pointer = &acpi_object; + + /* + * Get information on this device. + */ + status = bm_get_device_info(device_handle, &device); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Allocate a new BM_POWER_RESOURCE structure. + */ + pr = acpi_os_callocate(sizeof(BM_POWER_RESOURCE)); + if (!pr) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + pr->device_handle = device->handle; + pr->acpi_handle = device->acpi_handle; + + /* + * Get information on this power resource. + */ + status = acpi_evaluate_object(pr->acpi_handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + pr->system_level = acpi_object.power_resource.system_level; + pr->resource_order = acpi_object.power_resource.resource_order; + pr->state = ACPI_STATE_UNKNOWN; + pr->reference_count = 0; + + /* + * Get the power resource's current state (ON|OFF). + */ + status = bm_pr_get_state(pr); + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(pr); + } + else { + *context = pr; + bm_pr_print(pr); + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_remove_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_remove_device ( + void **context) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + + FUNCTION_TRACE("bm_pr_remove_device"); + + if (!context || !*context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + pr = (BM_POWER_RESOURCE*)*context; + + DEBUG_PRINT(ACPI_INFO, ("Removing power resource [0x%02X].\n", pr->device_handle)); + + acpi_os_free(pr); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_pr_initialize + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_initialize (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + FUNCTION_TRACE("bm_pr_initialize"); + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + criteria.type = BM_TYPE_POWER_RESOURCE; + + driver.notify = &bm_pr_notify; + driver.request = &bm_pr_request; + + status = bm_register_driver(&criteria, &driver); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_terminate + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_terminate (void) +{ + ACPI_STATUS status = AE_OK; + BM_DEVICE_ID criteria; + BM_DRIVER driver; + + FUNCTION_TRACE("bm_pr_terminate"); + + MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID)); + MEMSET(&driver, 0, sizeof(BM_DRIVER)); + + criteria.type = BM_TYPE_POWER_RESOURCE; + + driver.notify = &bm_pr_notify; + driver.request = &bm_pr_request; + + status = bm_unregister_driver(&criteria, &driver); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_notify ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + void **context) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_pr_notify"); + + switch (notify_type) { + + case BM_NOTIFY_DEVICE_ADDED: + status = bm_pr_add_device(device_handle, context); + break; + + case BM_NOTIFY_DEVICE_REMOVED: + status = bm_pr_remove_device(context); + break; + + default: + status = AE_SUPPORT; + break; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_pr_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_pr_request ( + BM_REQUEST *request, + void *context) +{ + ACPI_STATUS status = AE_OK; + BM_POWER_RESOURCE *pr = NULL; + + FUNCTION_TRACE("bm_pr_request"); + + /* + * Must have a valid request structure and context. + */ + if (!request || !context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * context contains information specific to this power resource. + */ + pr = (BM_POWER_RESOURCE*)context; + + /* + * Handle request: + * --------------- + */ + switch (request->command) { + + default: + status = AE_SUPPORT; + break; + } + + request->status = status; + + return_ACPI_STATUS(status); +} + + + diff --git a/drivers/bus/acpi/ospm/busmgr/bmrequest.c b/drivers/bus/acpi/ospm/busmgr/bmrequest.c new file mode 100644 index 0000000..e46ac36 --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmrequest.c @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * Module Name: bmrequest.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmrequest") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_generate_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_generate_request ( + BM_NODE *node, + BM_REQUEST *request) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_generate_request"); + + if (!node || !request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + DEBUG_PRINT(ACPI_INFO, ("Sending request [0x%02x] to device [0x%02x].\n", request->command, node->device.handle)); + + if (!(node->device.flags & BM_FLAGS_DRIVER_CONTROL) || + !(node->driver.request)) { + DEBUG_PRINT(ACPI_WARN, ("No driver installed for device [0x%02x].\n", node->device.handle)); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + status = node->driver.request(request, node->driver.context); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_request ( + BM_REQUEST *request) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_request"); + + /* + * Must have a valid request structure. + */ + if (!request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + DEBUG_PRINT(ACPI_INFO, ("Received request for device [0x%02x] command [0x%08x].\n", request->handle, request->command)); + + /* + * Resolve the node. + */ + status = bm_get_node(request->handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + device = &(node->device); + + /* + * Device-Specific Request? + * ------------------------ + * If a device-specific command (>=0x80) forward this request to + * the appropriate driver. + */ + if (request->command & BM_COMMAND_DEVICE_SPECIFIC) { + status = bm_generate_request(node, request); + return_ACPI_STATUS(status); + } + + /* + * Bus-Specific Requests: + * ---------------------- + */ + switch (request->command) { + + case BM_COMMAND_GET_POWER_STATE: + status = bm_get_power_state(node); + if (ACPI_FAILURE(status)) { + break; + } + status = bm_copy_to_buffer(&(request->buffer), + &(device->power.state), sizeof(BM_POWER_STATE)); + break; + + case BM_COMMAND_SET_POWER_STATE: + { + BM_POWER_STATE *power_state = NULL; + + status = bm_cast_buffer(&(request->buffer), + (void**)&power_state, sizeof(BM_POWER_STATE)); + if (ACPI_FAILURE(status)) { + break; + } + status = bm_set_power_state(node, *power_state); + } + break; + + default: + status = AE_SUPPORT; + request->status = AE_SUPPORT; + break; + } + + return_ACPI_STATUS(status); +} diff --git a/drivers/bus/acpi/ospm/busmgr/bmsearch.c b/drivers/bus/acpi/ospm/busmgr/bmsearch.c new file mode 100644 index 0000000..97756dd --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmsearch.c @@ -0,0 +1,191 @@ +/****************************************************************************** + * + * Module Name: bmsearch.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmsearch") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_compare + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_compare ( + BM_DEVICE *device, + BM_DEVICE_ID *criteria) +{ + if (!device || !criteria) { + return AE_BAD_PARAMETER; + } + + /* + * Present? + * -------- + * We're only going to match on devices that are present. + * TODO: Optimize in bm_search (don't have to call here). + */ + if (!BM_DEVICE_PRESENT(device)) { + return AE_NOT_FOUND; + } + + /* + * type? + */ + if (criteria->type && !(criteria->type & device->id.type)) { + return AE_NOT_FOUND; + } + + /* + * hid? + */ + if ((criteria->hid[0]) && (0 != STRNCMP(criteria->hid, + device->id.hid, sizeof(BM_DEVICE_HID)))) { + return AE_NOT_FOUND; + } + + /* + * adr? + */ + if ((criteria->adr) && (criteria->adr != device->id.adr)) { + return AE_NOT_FOUND; + } + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: bm_search + * + * PARAMETERS: + * + * RETURN: AE_BAD_PARAMETER- invalid input parameter + * AE_NOT_EXIST - start_device_handle doesn't exist + * AE_NOT_FOUND - no matches to Search_info.criteria found + * AE_OK - success + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_search( + BM_HANDLE device_handle, + BM_DEVICE_ID *criteria, + BM_HANDLE_LIST *results) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_search"); + + if (!criteria || !results) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + results->count = 0; + + /* + * Locate Starting Point: + * ---------------------- + * Locate the node in the hierarchy where we'll begin our search. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Parse Hierarchy: + * ---------------- + * Parse through the node hierarchy looking for matches. + */ + while (node && (results->count<=BM_HANDLES_MAX)) { + /* + * Depth-first: + * ------------ + * Searches are always performed depth-first. + */ + if (node->scope.head) { + status = bm_compare(&(node->device), criteria); + if (ACPI_SUCCESS(status)) { + results->handles[results->count++] = + node->device.handle; + } + node = node->scope.head; + } + + /* + * Now Breadth: + * ------------ + * Search all peers until scope is exhausted. + */ + else { + status = bm_compare(&(node->device), criteria); + if (ACPI_SUCCESS(status)) { + results->handles[results->count++] = + node->device.handle; + } + + /* + * Locate Next Device: + * ------------------- + * The next node is either a peer at this level + * (node->next is valid), or we work are way back + * up the tree until we either find a non-parsed + * peer or hit the top (node->parent is NULL). + */ + while (!node->next && node->parent) { + node = node->parent; + } + node = node->next; + } + } + + if (results->count == 0) { + return_ACPI_STATUS(AE_NOT_FOUND); + } + else { + return_ACPI_STATUS(AE_OK); + } +} diff --git a/drivers/bus/acpi/ospm/busmgr/bmutils.c b/drivers/bus/acpi/ospm/busmgr/bmutils.c new file mode 100644 index 0000000..5935b57 --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmutils.c @@ -0,0 +1,606 @@ +/***************************************************************************** + * + * Module Name: bmutils.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmutils") + + +#ifdef ACPI_DEBUG +#define DEBUG_EVAL_ERROR(l,h,p,s) bm_print_eval_error(l,h,p,s) +#else +#define DEBUG_EVAL_ERROR(l,h,p,s) +#endif + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_print_eval_error + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_eval_error ( + u32 debug_level, + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + ACPI_STATUS status) +{ + ACPI_BUFFER buffer; + ACPI_STRING status_string = NULL; + + buffer.length = 256; + buffer.pointer = acpi_os_callocate(buffer.length); + if (!buffer.pointer) { + return; + } + + status_string = acpi_cm_format_exception(status); + + status = acpi_get_name(acpi_handle, ACPI_FULL_PATHNAME, &buffer); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(debug_level, ("Evaluate object [0x%08x], %s\n", acpi_handle, status_string)); + return; + } + + if (pathname) { + DEBUG_PRINT(ACPI_INFO, ("Evaluate object [%s.%s], %s\n", buffer.pointer, pathname, status_string)); + } + else { + DEBUG_PRINT(ACPI_INFO, ("Evaluate object [%s], %s\n", buffer.pointer, status_string)); + } + + acpi_os_free(buffer.pointer); +} + + +/**************************************************************************** + * + * FUNCTION: bm_copy_to_buffer + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_copy_to_buffer ( + ACPI_BUFFER *buffer, + void *data, + u32 length) +{ + FUNCTION_TRACE("bm_copy_to_buffer"); + + if (!buffer || (!buffer->pointer) || !data || (length == 0)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (length > buffer->length) { + buffer->length = length; + return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + } + + buffer->length = length; + MEMCPY(buffer->pointer, data, length); + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_cast_buffer + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_cast_buffer ( + ACPI_BUFFER *buffer, + void **pointer, + u32 length) +{ + FUNCTION_TRACE("bm_cast_buffer"); + + if (!buffer || !buffer->pointer || !pointer || length == 0) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (length > buffer->length) { + return_ACPI_STATUS(AE_BAD_DATA); + } + + *pointer = buffer->pointer; + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_extract_package_data + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +/* + TODO: Don't assume numbers (in ASL) are 32-bit values!!!! (IA64) + TODO: Issue with 'assumed' types coming out of interpreter... + (e.g. toshiba _BIF) +*/ + +ACPI_STATUS +bm_extract_package_data ( + ACPI_OBJECT *package, + ACPI_BUFFER *package_format, + ACPI_BUFFER *buffer) +{ + ACPI_STATUS status = AE_OK; + u8 *head = NULL; + u8 *tail = NULL; + u8 **pointer = NULL; + u32 tail_offset = 0; + ACPI_OBJECT *element = NULL; + u32 size_required = 0; + char* format = NULL; + u32 format_count = 0; + u32 i = 0; + + FUNCTION_TRACE("bm_extract_package_data"); + + if (!package || (package->type != ACPI_TYPE_PACKAGE) || + (package->package.count == 0) || !package_format || + (package_format->length < 1) || + (!package_format->pointer) || !buffer) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + format_count = package_format->length - 1; + + if (format_count > package->package.count) { + DEBUG_PRINT(ACPI_WARN, ("Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count)); + return_ACPI_STATUS(AE_BAD_DATA); + } + + format = (char*)package_format->pointer; + + /* + * Calculate size_required. + */ + for (i=0; ipackage.elements[i]); + + switch (element->type) { + + case ACPI_TYPE_INTEGER: + switch (format[i]) { + case 'N': + size_required += sizeof(ACPI_INTEGER); + tail_offset += sizeof(ACPI_INTEGER); + break; + case 'S': + size_required += sizeof(u8*) + + sizeof(ACPI_INTEGER) + 1; + tail_offset += sizeof(ACPI_INTEGER); + break; + default: + DEBUG_PRINT(ACPI_WARN, ("Invalid package element [%d]: got number, expecing [%c].\n", i, format[i])); + return_ACPI_STATUS(AE_BAD_DATA); + break; + } + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + switch (format[i]) { + case 'S': + size_required += sizeof(u8*) + + element->string.length + 1; + tail_offset += sizeof(u8*); + break; + case 'B': + size_required += sizeof(u8*) + + element->buffer.length; + tail_offset += sizeof(u8*); + break; + default: + DEBUG_PRINT(ACPI_WARN, ("Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format[i])); + return_ACPI_STATUS(AE_BAD_DATA); + break; + } + break; + + case ACPI_TYPE_PACKAGE: + default: + /* TODO: handle nested packages... */ + return_ACPI_STATUS(AE_SUPPORT); + break; + } + } + + if (size_required > buffer->length) { + buffer->length = size_required; + return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + } + + buffer->length = size_required; + + if (!buffer->pointer) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + head = buffer->pointer; + tail = buffer->pointer + tail_offset; + + /* + * Extract package data: + */ + for (i=0; ipackage.elements[i]); + + switch (element->type) { + + case ACPI_TYPE_INTEGER: + switch (format[i]) { + case 'N': + *((ACPI_INTEGER*)head) = + element->integer.value; + head += sizeof(ACPI_INTEGER); + break; + case 'S': + pointer = (u8**)head; + *pointer = tail; + *((ACPI_INTEGER*)tail) = + element->integer.value; + head += sizeof(ACPI_INTEGER*); + tail += sizeof(ACPI_INTEGER); + /* NULL terminate string */ + *tail = 0; + tail++; + break; + default: + /* Should never get here */ + break; + } + break; + + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + switch (format[i]) { + case 'S': + pointer = (u8**)head; + *pointer = tail; + memcpy(tail, element->string.pointer, + element->string.length); + head += sizeof(u8*); + tail += element->string.length; + /* NULL terminate string */ + *tail = 0; + tail++; + break; + case 'B': + pointer = (u8**)head; + *pointer = tail; + memcpy(tail, element->buffer.pointer, + element->buffer.length); + head += sizeof(u8*); + tail += element->buffer.length; + break; + default: + /* Should never get here */ + break; + } + break; + + case ACPI_TYPE_PACKAGE: + /* TODO: handle nested packages... */ + default: + /* Should never get here */ + break; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_evaluate_object + * + * PARAMETERS: + * + * RETURN: AE_OK + * AE_BUFFER_OVERFLOW Evaluated object returned data, but + * caller did not provide buffer. + * + * DESCRIPTION: Helper for acpi_evaluate_object that handles buffer + * allocation. Note that the caller is responsible for + * freeing buffer->pointer! + * + ****************************************************************************/ + +ACPI_STATUS +bm_evaluate_object ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *arguments, + ACPI_BUFFER *buffer) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_evaluate_object"); + + /* If caller provided a buffer it must be unallocated/zero'd. */ + if ((buffer) && (buffer->length != 0 || buffer->pointer)) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Evalute Object: + * --------------- + * The first attempt is just to get the size of the object data + * (that is unless there's no return data, e.g. _INI); the second + * gets the data. + */ + status = acpi_evaluate_object(acpi_handle, pathname, arguments, buffer); + if (ACPI_SUCCESS(status)) { + return_ACPI_STATUS(status); + } + + else if ((buffer) && (status == AE_BUFFER_OVERFLOW)) { + + /* Gotta allocate -- CALLER MUST FREE! */ + buffer->pointer = acpi_os_callocate(buffer->length); + if (!buffer->pointer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Re-evaluate -- this time it should work */ + status = acpi_evaluate_object(acpi_handle, pathname, + arguments, buffer); + } + + if (ACPI_FAILURE(status)) { + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + if (buffer && buffer->pointer) { + acpi_os_free(buffer->pointer); + buffer->pointer = NULL; + buffer->length = 0; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_evaluate_simple_integer + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_evaluate_simple_integer ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + u32 *data) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT *element = NULL; + ACPI_BUFFER buffer; + + FUNCTION_TRACE("bm_evaluate_simple_integer"); + + if (!data) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&buffer, 0, sizeof(ACPI_BUFFER)); + + /* + * Evaluate Object: + * ---------------- + */ + status = bm_evaluate_object(acpi_handle, pathname, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Validate Data: + * -------------- + */ + status = bm_cast_buffer(&buffer, (void**)&element, + sizeof(ACPI_OBJECT)); + if (ACPI_FAILURE(status)) { + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + if (element->type != ACPI_TYPE_INTEGER) { + status = AE_BAD_DATA; + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + *data = element->integer.value; + +end: + acpi_os_free(buffer.pointer); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_evaluate_reference_list + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_evaluate_reference_list ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + BM_HANDLE_LIST *reference_list) +{ + ACPI_STATUS status = AE_OK; + ACPI_OBJECT *package = NULL; + ACPI_OBJECT *element = NULL; + ACPI_HANDLE reference_handle = NULL; + ACPI_BUFFER buffer; + u32 i = 0; + + FUNCTION_TRACE("bm_evaluate_reference_list"); + + if (!reference_list) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&buffer, 0, sizeof(ACPI_BUFFER)); + + /* + * Evaluate Object: + * ---------------- + */ + status = bm_evaluate_object(acpi_handle, pathname, NULL, &buffer); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Validate Package: + * ----------------- + */ + status = bm_cast_buffer(&buffer, (void**)&package, + sizeof(ACPI_OBJECT)); + if (ACPI_FAILURE(status)) { + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + if (package->type != ACPI_TYPE_PACKAGE) { + status = AE_BAD_DATA; + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + goto end; + } + + if (package->package.count > BM_HANDLES_MAX) { + package->package.count = BM_HANDLES_MAX; + } + + /* + * Parse Package Data: + * ------------------- + */ + for (i = 0; i < package->package.count; i++) { + + element = &(package->package.elements[i]); + + if (!element || (element->type != ACPI_TYPE_STRING)) { + status = AE_BAD_DATA; + DEBUG_PRINT(ACPI_WARN, ("Invalid element in package (not a device reference).\n")); + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + break; + } + + /* + * Resolve reference string (e.g. "\_PR_.CPU_") to an + * ACPI_HANDLE. + */ + status = acpi_get_handle(acpi_handle, + element->string.pointer, &reference_handle); + if (ACPI_FAILURE(status)) { + status = AE_BAD_DATA; + DEBUG_PRINT(ACPI_WARN, ("Unable to resolve device reference [%s].\n", element->string.pointer)); + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + break; + } + + /* + * Resolve ACPI_HANDLE to BM_HANDLE. + */ + status = bm_get_handle(reference_handle, + &(reference_list->handles[i])); + if (ACPI_FAILURE(status)) { + status = AE_BAD_DATA; + DEBUG_PRINT(ACPI_WARN, ("Unable to resolve device reference for [0x%08x].\n", reference_handle)); + DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status); + break; + } + + DEBUG_PRINT(ACPI_INFO, ("Resolved reference [%s]->[0x%08x]->[0x%02x]\n", element->string.pointer, reference_handle, reference_list->handles[i])); + + (reference_list->count)++; + } + +end: + acpi_os_free(buffer.pointer); + + return_ACPI_STATUS(status); +} + + diff --git a/drivers/bus/acpi/ospm/busmgr/bmxface.c b/drivers/bus/acpi/ospm/busmgr/bmxface.c new file mode 100644 index 0000000..0b5cfbe --- /dev/null +++ b/drivers/bus/acpi/ospm/busmgr/bmxface.c @@ -0,0 +1,331 @@ +/***************************************************************************** + * + * Module Name: bmxface.c + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include +#include "bm.h" + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmxface") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_device_status + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +ACPI_STATUS +bm_get_device_status ( + BM_HANDLE device_handle, + BM_DEVICE_STATUS *device_status) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_status"); + + if (!device_status) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *device_status = BM_STATUS_UNKNOWN; + + /* + * Resolve device handle to node. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Parent Present? + * --------------- + * If the parent isn't present we can't evalute _STA on the child. + * Return an unknown status. + */ + if (!BM_NODE_PRESENT(node->parent)) { + return_ACPI_STATUS(AE_OK); + } + + /* + * Dynamic Status? + * --------------- + * If _STA isn't present we just return the default status. + */ + if (!(node->device.flags & BM_FLAGS_DYNAMIC_STATUS)) { + *device_status = BM_STATUS_DEFAULT; + return_ACPI_STATUS(AE_OK); + } + + /* + * Evaluate _STA: + * -------------- + */ + status = bm_evaluate_simple_integer(node->device.acpi_handle, "_STA", + &(node->device.status)); + if (ACPI_SUCCESS(status)) { + *device_status = node->device.status; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_device_info + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +ACPI_STATUS +bm_get_device_info ( + BM_HANDLE device_handle, + BM_DEVICE **device) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_info"); + + if (!device) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * Resolve device handle to internal device. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + *device = &(node->device); + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_device_context + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +ACPI_STATUS +bm_get_device_context ( + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_get_device_context"); + + if (!context) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *context = NULL; + + /* + * Resolve device handle to internal device. + */ + status = bm_get_node(device_handle, 0, &node); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (!node->driver.context) { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + *context = node->driver.context; + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_register_driver + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_register_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver) +{ + ACPI_STATUS status = AE_NOT_FOUND; + BM_HANDLE_LIST device_list; + BM_NODE *node = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_register_driver"); + + if (!criteria || !driver || !driver->notify || !driver->request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST)); + + /* + * Find Matches: + * ------------- + * Search through the entire device hierarchy for matches against + * the given device criteria. + */ + status = bm_search(BM_HANDLE_ROOT, criteria, &device_list); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Install driver: + * ---------------- + * For each match, record the driver information and execute the + * driver's Notify() funciton (if present) to notify the driver + * of the device's presence. + */ + for (i = 0; i < device_list.count; i++) { + + /* Resolve the device handle. */ + status = bm_get_node(device_list.handles[i], 0, &node); + if (ACPI_FAILURE(status)) { + continue; + } + + DEBUG_PRINT(ACPI_INFO, ("Registering driver for device [0x%02x].\n", node->device.handle)); + + /* Notify driver of new device. */ + status = driver->notify(BM_NOTIFY_DEVICE_ADDED, + node->device.handle, &(node->driver.context)); + if (ACPI_SUCCESS(status)) { + node->driver.notify = driver->notify; + node->driver.request = driver->request; + node->device.flags |= BM_FLAGS_DRIVER_CONTROL; + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_unregister_driver + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_unregister_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver) +{ + ACPI_STATUS status = AE_NOT_FOUND; + BM_HANDLE_LIST device_list; + BM_NODE *node = NULL; + u32 i = 0; + + FUNCTION_TRACE("bm_unregister_driver"); + + if (!criteria || !driver || !driver->notify || !driver->request) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST)); + + /* + * Find Matches: + * ------------- + * Search through the entire device hierarchy for matches against + * the given device criteria. + */ + status = bm_search(BM_HANDLE_ROOT, criteria, &device_list); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Remove driver: + * --------------- + * For each match, execute the driver's Notify() function to allow + * the driver to cleanup each device instance. + */ + for (i = 0; i < device_list.count; i++) { + /* + * Resolve the device handle. + */ + status = bm_get_node(device_list.handles[i], 0, &node); + if (ACPI_FAILURE(status)) { + continue; + } + + DEBUG_PRINT(ACPI_INFO, ("Unregistering driver for device [0x%02x].\n", node->device.handle)); + + /* Notify driver of device removal. */ + status = node->driver.notify(BM_NOTIFY_DEVICE_REMOVED, + node->device.handle, &(node->driver.context)); + + node->device.flags &= ~BM_FLAGS_DRIVER_CONTROL; + + MEMSET(&(node->driver), 0, sizeof(BM_DRIVER)); + } + + return_ACPI_STATUS(AE_OK); +} diff --git a/drivers/bus/acpi/ospm/fdo.c b/drivers/bus/acpi/ospm/fdo.c new file mode 100644 index 0000000..6f1e2e5 --- /dev/null +++ b/drivers/bus/acpi/ospm/fdo.c @@ -0,0 +1,512 @@ +/* $Id$ + * + * PROJECT: ReactOS ACPI bus driver + * FILE: acpi/ospm/fdo.c + * PURPOSE: ACPI device object dispatch routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 08-08-2001 CSH Created + */ +#include +#include +#include + +#define NDEBUG +#include + +/*** PRIVATE *****************************************************************/ + +FADT_DESCRIPTOR_REV2 acpi_fadt; + +NTSTATUS +FdoQueryBusRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPDO_DEVICE_EXTENSION PdoDeviceExtension; + PFDO_DEVICE_EXTENSION DeviceExtension; + PDEVICE_RELATIONS Relations; + PLIST_ENTRY CurrentEntry; + ANSI_STRING AnsiString; + ACPI_STATUS AcpiStatus; + PACPI_DEVICE Device; + NTSTATUS Status; + BM_NODE *Node; + ULONG Size; + ULONG i; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) * + (DeviceExtension->DeviceListCount - 1); + Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); + if (!Relations) + return STATUS_INSUFFICIENT_RESOURCES; + + Relations->Count = DeviceExtension->DeviceListCount; + + i = 0; + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) { + Device = CONTAINING_RECORD(CurrentEntry, ACPI_DEVICE, DeviceListEntry); + + /* FIXME: For ACPI namespace devices on the motherboard create filter DOs + and attach them just above the ACPI bus device object (PDO) */ + + /* FIXME: For other devices in ACPI namespace, but not on motherboard, + create PDOs */ + + if (!Device->Pdo) { + /* Create a physical device object for the + device as it does not already have one */ + Status = IoCreateDevice(DeviceObject->DriverObject, 0, + NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &Device->Pdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + /* FIXME: Cleanup all new PDOs created in this call */ + ExFreePool(Relations); + return Status; + } + + PdoDeviceExtension = ExAllocatePool( + NonPagedPool, + sizeof(PDO_DEVICE_EXTENSION)); + if (!PdoDeviceExtension) { + /* FIXME: Cleanup all new PDOs created in this call */ + ExFreePool(Relations); + } + + RtlZeroMemory( + PdoDeviceExtension, + sizeof(PDO_DEVICE_EXTENSION)); + + Device->Pdo->DeviceExtension = PdoDeviceExtension; + + Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + + PdoDeviceExtension->Common.DeviceObject = Device->Pdo; + + PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0; + + PdoDeviceExtension->Common.Ldo = IoAttachDeviceToDeviceStack( + DeviceObject, + Device->Pdo); + + RtlInitUnicodeString(&PdoDeviceExtension->HardwareIDs, NULL); + RtlInitUnicodeString(&PdoDeviceExtension->CompatibleIDs, NULL); + + AcpiStatus = bm_get_node(Device->BmHandle, 0, &Node); + if (ACPI_SUCCESS(AcpiStatus)) { + if (Node->device.flags & BM_FLAGS_HAS_A_HID) { + RtlInitAnsiString(&AnsiString, Node->device.id.hid); + Status = RtlAnsiStringToUnicodeString( + &PdoDeviceExtension->HardwareIDs, + &AnsiString, + TRUE); + assert(NT_SUCCESS(Status)); + } + + if (Node->device.flags & BM_FLAGS_HAS_A_CID) { + RtlInitAnsiString(&AnsiString, Node->device.id.cid); + Status = RtlAnsiStringToUnicodeString( + &PdoDeviceExtension->CompatibleIDs, + &AnsiString, + TRUE); + assert(NT_SUCCESS(Status)); + } + } + } + + /* Reference the physical device object. The PnP manager + will dereference it again when it is no longer needed */ + ObReferenceObject(Device->Pdo); + + Relations->Objects[i] = Device->Pdo; + + i++; + + CurrentEntry = CurrentEntry->Flink; + } + + Irp->IoStatus.Information = (ULONG)Relations; + + return Status; +} + + +VOID ACPIPrintInfo( + PFDO_DEVICE_EXTENSION DeviceExtension) +{ + DbgPrint("ACPI: System firmware supports:\n"); + + /* + * Print out basic system information + */ + DbgPrint("+------------------------------------------------------------\n"); + DbgPrint("| Sx states: %cS0 %cS1 %cS2 %cS3 %cS4 %cS5\n", + (DeviceExtension->SystemStates[0]?'+':'-'), + (DeviceExtension->SystemStates[1]?'+':'-'), + (DeviceExtension->SystemStates[2]?'+':'-'), + (DeviceExtension->SystemStates[3]?'+':'-'), + (DeviceExtension->SystemStates[4]?'+':'-'), + (DeviceExtension->SystemStates[5]?'+':'-')); + DbgPrint("+------------------------------------------------------------\n"); +} + +NTSTATUS +ACPIInitializeInternalDriver( + PFDO_DEVICE_EXTENSION DeviceExtension, + ACPI_DRIVER_FUNCTION Initialize, + ACPI_DRIVER_FUNCTION Terminate) +{ + ACPI_STATUS AcpiStatus; + PACPI_DEVICE AcpiDevice; + + AcpiStatus = Initialize(); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("BN init status 0x%X\n", AcpiStatus); + return STATUS_UNSUCCESSFUL; + } +#if 0 + AcpiDevice = (PACPI_DEVICE)ExAllocatePool( + NonPagedPool, sizeof(ACPI_DEVICE)); + if (!AcpiDevice) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + AcpiDevice->Initialize = Initialize; + AcpiDevice->Terminate = Terminate; + + /* FIXME: Create PDO */ + + AcpiDevice->Pdo = NULL; + //AcpiDevice->BmHandle = HandleList.handles[i]; + + ExInterlockedInsertHeadList(&DeviceExtension->DeviceListHead, + &AcpiDevice->ListEntry, &DeviceExtension->DeviceListLock); +#endif + return STATUS_SUCCESS; +} + + +NTSTATUS +ACPIInitializeInternalDrivers( + PFDO_DEVICE_EXTENSION DeviceExtension) +{ + NTSTATUS Status; + + ULONG j; + + Status = ACPIInitializeInternalDriver(DeviceExtension, + bn_initialize, bn_terminate); + + return STATUS_SUCCESS; +} + + +NTSTATUS +FdoStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + ACPI_PHYSICAL_ADDRESS rsdp; + ACPI_SYSTEM_INFO SysInfo; + ACPI_STATUS AcpiStatus; + ACPI_BUFFER Buffer; + UCHAR TypeA, TypeB; + ULONG i; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + assert(DeviceExtension->State == dsStopped); + + AcpiStatus = acpi_initialize_subsystem(); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("acpi_initialize_subsystem() failed with status 0x%X\n", AcpiStatus); + return STATUS_UNSUCCESSFUL; + } + + AcpiStatus = acpi_find_root_pointer(&rsdp); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("acpi_find_root_pointer() failed with status 0x%X\n", AcpiStatus); + return STATUS_UNSUCCESSFUL; + } + + /* From this point on, on error we must call acpi_terminate() */ + + AcpiStatus = acpi_load_tables(rsdp); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("acpi_load_tables() failed with status 0x%X\n", AcpiStatus); + acpi_terminate(); + return STATUS_UNSUCCESSFUL; + } + + Buffer.length = sizeof(SysInfo); + Buffer.pointer = &SysInfo; + + AcpiStatus = acpi_get_system_info(&Buffer); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("acpi_get_system_info() failed with status 0x%X\n", AcpiStatus); + acpi_terminate(); + return STATUS_UNSUCCESSFUL; + } + + DPRINT("ACPI CA Core Subsystem version 0x%X\n", SysInfo.acpi_ca_version); + + assert(SysInfo.num_table_types > ACPI_TABLE_FADT); + + RtlMoveMemory(&acpi_fadt, + &SysInfo.table_info[ACPI_TABLE_FADT], + sizeof(FADT_DESCRIPTOR_REV2)); + + AcpiStatus = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("acpi_enable_subsystem() failed with status 0x%X\n", AcpiStatus); + acpi_terminate(); + return STATUS_UNSUCCESSFUL; + } + + DPRINT("ACPI CA Core Subsystem enabled\n"); + + /* + * Sx States: + * ---------- + * Figure out which Sx states are supported + */ + for (i=0; i<=ACPI_S_STATES_MAX; i++) { + AcpiStatus = acpi_hw_obtain_sleep_type_register_data( + i, + &TypeA, + &TypeB); + DPRINT("acpi_hw_obtain_sleep_type_register_data (%d) status 0x%X\n", + i, AcpiStatus); + if (ACPI_SUCCESS(AcpiStatus)) { + DeviceExtension->SystemStates[i] = TRUE; + } + } + + ACPIPrintInfo(DeviceExtension); + + /* Initialize ACPI bus manager */ + AcpiStatus = bm_initialize(); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("bm_initialize() failed with status 0x%X\n", AcpiStatus); + acpi_terminate(); + return STATUS_UNSUCCESSFUL; + } + + InitializeListHead(&DeviceExtension->DeviceListHead); + KeInitializeSpinLock(&DeviceExtension->DeviceListLock); + DeviceExtension->DeviceListCount = 0; + + ACPIEnumerateNamespace(DeviceExtension); + + //ACPIEnumerateRootBusses(DeviceExtension); + + ACPIInitializeInternalDrivers(DeviceExtension); + + DeviceExtension->State = dsStarted; + + return STATUS_SUCCESS; +} + + +NTSTATUS +FdoSetPower( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + ACPI_STATUS AcpiStatus; + NTSTATUS Status; + ULONG AcpiState; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (IrpSp->Parameters.Power.Type == SystemPowerState) { + Status = STATUS_SUCCESS; + switch (IrpSp->Parameters.Power.State.SystemState) { + case PowerSystemSleeping1: + AcpiState = ACPI_STATE_S1; + break; + case PowerSystemSleeping2: + AcpiState = ACPI_STATE_S2; + break; + case PowerSystemSleeping3: + AcpiState = ACPI_STATE_S3; + break; + case PowerSystemHibernate: + AcpiState = ACPI_STATE_S4; + break; + case PowerSystemShutdown: + AcpiState = ACPI_STATE_S5; + break; + default: + Status = STATUS_UNSUCCESSFUL; + } + if (!DeviceExtension->SystemStates[AcpiState]) { + DPRINT("System sleep state S%d is not supported by hardware\n", AcpiState); + Status = STATUS_UNSUCCESSFUL; + } + + if (NT_SUCCESS(Status)) { + DPRINT("Trying to enter sleep state %d\n", AcpiState); + + AcpiStatus = acpi_enter_sleep_state(AcpiState); + if (!ACPI_SUCCESS(AcpiStatus)) { + DPRINT("Failed to enter sleep state %d (Status 0x%X)\n", + AcpiState, AcpiStatus); + Status = STATUS_UNSUCCESSFUL; + } + } + } else { + Status = STATUS_UNSUCCESSFUL; + } + + return Status; +} + + +/*** PUBLIC ******************************************************************/ + +NTSTATUS +STDCALL +FdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the ACPI device + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the ACPI driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + switch (IrpSp->MinorFunction) { + case IRP_MN_CANCEL_REMOVE_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp); + break; + + case IRP_MN_QUERY_PNP_DEVICE_STATE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_QUERY_STOP_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_REMOVE_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_START_DEVICE: + DPRINT("IRP_MN_START_DEVICE received\n"); + Status = FdoStartDevice(DeviceObject, Irp); + break; + + case IRP_MN_STOP_DEVICE: + /* Currently not supported */ + //bm_terminate(); + Status = STATUS_UNSUCCESSFUL; + break; + + case IRP_MN_SURPRISE_REMOVAL: + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +FdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the ACPI device + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the ACPI driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + case IRP_MN_SET_POWER: + Status = FdoSetPower(DeviceObject, Irp, IrpSp); + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +/* EOF */ diff --git a/drivers/bus/acpi/ospm/include/acpisys.h b/drivers/bus/acpi/ospm/include/acpisys.h new file mode 100644 index 0000000..e8f4f85 --- /dev/null +++ b/drivers/bus/acpi/ospm/include/acpisys.h @@ -0,0 +1,124 @@ +/* + * PROJECT: ReactOS ACPI bus driver + * FILE: acpi/ospm/include/acpisys.h + * PURPOSE: ACPI bus driver definitions + */ +#define ACPI_DEBUG +#include +#define __INCLUDE_TYPES_H +#include +#undef ROUND_UP +#include +#include + +typedef ACPI_STATUS (*ACPI_DRIVER_FUNCTION)(VOID); + + +typedef enum { + dsStopped, + dsStarted, + dsPaused, + dsRemoved, + dsSurpriseRemoved +} ACPI_DEVICE_STATE; + + +typedef struct _COMMON_DEVICE_EXTENSION +{ + // Pointer to device object, this device extension is associated with + PDEVICE_OBJECT DeviceObject; + // Wether this device extension is for an FDO or PDO + BOOLEAN IsFDO; + // Wether the device is removed + BOOLEAN Removed; + // Current device power state for the device + DEVICE_POWER_STATE DevicePowerState; + // Lower device object + PDEVICE_OBJECT Ldo; +} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; + +/* Physical Device Object device extension for a child device */ +typedef struct _PDO_DEVICE_EXTENSION +{ + // Common device data + COMMON_DEVICE_EXTENSION Common; + // Hardware IDs + UNICODE_STRING HardwareIDs; + // Compatible IDs + UNICODE_STRING CompatibleIDs; +} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION; + +typedef struct _FDO_DEVICE_EXTENSION +{ + // Common device data + COMMON_DEVICE_EXTENSION Common; + // Physical Device Object + PDEVICE_OBJECT Pdo; + // Current state of the driver + ACPI_DEVICE_STATE State; + // Supported system states + BOOLEAN SystemStates[ACPI_S_STATE_COUNT]; + // Namespace device list + LIST_ENTRY DeviceListHead; + // Number of devices in device list + ULONG DeviceListCount; + // Lock for namespace device list + KSPIN_LOCK DeviceListLock; +} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; + + +typedef struct _ACPI_DEVICE +{ + // Entry on device list + LIST_ENTRY DeviceListEntry; + // Bus manager handle + BM_HANDLE BmHandle; + // Physical Device Object + PDEVICE_OBJECT Pdo; + // Initialization function + ACPI_DRIVER_FUNCTION Initialize; + // Cleanup function + ACPI_DRIVER_FUNCTION Terminate; +} ACPI_DEVICE, *PACPI_DEVICE; + + +/* acpienum.c */ + +NTSTATUS +ACPIEnumerateRootBusses( + PFDO_DEVICE_EXTENSION DeviceExtension); + +NTSTATUS +ACPIEnumerateNamespace( + PFDO_DEVICE_EXTENSION DeviceExtension); + + +/* fdo.c */ + +NTSTATUS +STDCALL +FdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +STDCALL +FdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* pdo.c */ + +NTSTATUS +STDCALL +PdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +STDCALL +PdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* EOF */ diff --git a/drivers/bus/acpi/ospm/include/bm.h b/drivers/bus/acpi/ospm/include/bm.h new file mode 100644 index 0000000..bf4590a --- /dev/null +++ b/drivers/bus/acpi/ospm/include/bm.h @@ -0,0 +1,624 @@ +/***************************************************************************** + * + * Module name: bm.h + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BM_H__ +#define __BM_H__ + +#include +#include + + +/***************************************************************************** + * Types & Defines + *****************************************************************************/ + +/* + * Output Flags (Debug): + * --------------------- + */ +#define BM_PRINT_ALL (0x00000000) +#define BM_PRINT_GROUP (0x00000001) +#define BM_PRINT_LINKAGE (0x00000002) +#define BM_PRINT_IDENTIFICATION (0x00000004) +#define BM_PRINT_POWER (0x00000008) +#define BM_PRINT_PRESENT (0x00000010) + + +/* + * /proc Interface: + * ---------------- + */ +#define BM_PROC_ROOT "acpi" +#define BM_PROC_EVENT "event" + +extern struct proc_dir_entry *bm_proc_root; + + +/* + * BM_COMMAND: + * ----------- + */ +typedef u32 BM_COMMAND; + +#define BM_COMMAND_UNKNOWN ((BM_COMMAND) 0x00) + +#define BM_COMMAND_GET_POWER_STATE ((BM_COMMAND) 0x01) +#define BM_COMMAND_SET_POWER_STATE ((BM_COMMAND) 0x02) + +#define BM_COMMAND_DEVICE_SPECIFIC ((BM_COMMAND) 0x80) + +/* + * BM_NOTIFY: + * ---------- + * Standard ACPI notification values, from section 5.6.3 of the ACPI 2.0 + * specification. Note that the Bus Manager internally handles all + * standard ACPI notifications -- driver modules are never sent these + * values (see "Bus Manager Notifications", below). + */ +typedef u32 BM_NOTIFY; + +#define BM_NOTIFY_BUS_CHECK ((BM_NOTIFY) 0x00) +#define BM_NOTIFY_DEVICE_CHECK ((BM_NOTIFY) 0x01) +#define BM_NOTIFY_DEVICE_WAKE ((BM_NOTIFY) 0x02) +#define BM_NOTIFY_EJECT_REQUEST ((BM_NOTIFY) 0x03) +#define BM_NOTIFY_DEVICE_CHECK_LIGHT ((BM_NOTIFY) 0x04) +#define BM_NOTIFY_FREQUENCY_MISMATCH ((BM_NOTIFY) 0x05) +#define BM_NOTIFY_BUS_MODE_MISMATCH ((BM_NOTIFY) 0x06) +#define BM_NOTIFY_POWER_FAULT ((BM_NOTIFY) 0x07) + +/* + * These are a higher-level abstraction of ACPI notifications, intended + * for consumption by driver modules to facilitate PnP. + */ +#define BM_NOTIFY_UNKNOWN ((BM_NOTIFY) 0x00) +#define BM_NOTIFY_DEVICE_ADDED ((BM_NOTIFY) 0x01) +#define BM_NOTIFY_DEVICE_REMOVED ((BM_NOTIFY) 0x02) + + +/* + * BM_HANDLE: + * ---------- + */ +typedef u32 BM_HANDLE; + +#define BM_HANDLE_UNKNOWN ((BM_HANDLE) 0x00) +#define BM_HANDLE_ROOT ((BM_HANDLE) 0x00) +#define BM_HANDLES_MAX 256 + + + +/* + * BM_HANDLE_LIST: + * --------------- + */ +typedef struct +{ + u32 count; + BM_HANDLE handles[BM_HANDLES_MAX]; +} BM_HANDLE_LIST; + + +/* + * BM_DEVICE_TYPE: + * --------------- + */ +typedef u32 BM_DEVICE_TYPE; + +#define BM_TYPE_UNKNOWN ((BM_DEVICE_TYPE) 0x00000000) + +#define BM_TYPE_SCOPE ((BM_DEVICE_TYPE) 0x00000001) +#define BM_TYPE_PROCESSOR ((BM_DEVICE_TYPE) 0x00000002) +#define BM_TYPE_THERMAL_ZONE ((BM_DEVICE_TYPE) 0x00000004) +#define BM_TYPE_POWER_RESOURCE ((BM_DEVICE_TYPE) 0x00000008) +#define BM_TYPE_DEVICE ((BM_DEVICE_TYPE) 0x00000010) +#define BM_TYPE_FIXED_BUTTON ((BM_DEVICE_TYPE) 0x00000020) +#define BM_TYPE_SYSTEM ((BM_DEVICE_TYPE) 0x80000000) +#define BM_TYPE_ALL ((BM_DEVICE_TYPE) 0xFFFFFFFF) + + +/* + * BM_DEVICE_UID: + * -------------- + */ +typedef char BM_DEVICE_UID[9]; + +#define BM_UID_UNKNOWN '0' + + +/* + * BM_DEVICE_HID: + * -------------- + */ +typedef char BM_DEVICE_HID[9]; + +#define BM_HID_UNKNOWN '\0' +#define BM_HID_POWER_BUTTON "PNP0C0C" +#define BM_HID_SLEEP_BUTTON "PNP0C0E" + +/* + * BM_DEVICE_CID: + * The compatibility ID can be a string with 44 characters + * The extra pad is in case there is a change. It also + * provides 8 byte alignment for the BM_DEVICE_ID structure. + * ------------------------------------------------------------- + */ +typedef char BM_DEVICE_CID[46]; + + +/* + * BM_DEVICE_ADR: + * -------------- + */ +typedef u32 BM_DEVICE_ADR; + +#define BM_ADDRESS_UNKNOWN 0 + + +/* + * BM_DEVICE_FLAGS: + * ---------------- + * The encoding of BM_DEVICE_FLAGS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the device has dynamic status). + * +--+------------+-+-+-+-+-+-+-+ + * |31| Bits 31:11 |6|5|4|3|2|1|0| + * +--+------------+-+-+-+-+-+-+-+ + * | | | | | | | | | + * | | | | | | | | +- Dynamic status? + * | | | | | | | +--- Identifiable? + * | | | | | | +----- Configurable? + * | | | | | +------- Power Manageable? + * | | | | +--------- Ejectable? + * | | | +----------- Docking Station? + * | | +------------- Fixed-Feature? + * | +-------------------- + * +---------------------------- Driver Control? + * + * Dynamic status: Device has a _STA object. + * Identifiable: Device has a _HID and/or _ADR and possibly other + * identification objects defined. + * Configurable: Device has a _CRS and possibly other configuration + * objects defined. + * Power Control: Device has a _PR0 and/or _PS0 and possibly other + * power management objects defined. + * Ejectable: Device has an _EJD and/or _EJx and possibly other + * dynamic insertion/removal objects defined. + * Docking Station: Device has a _DCK object defined. + * Fixed-Feature: Device does not exist in the namespace; was + * enumerated as a fixed-feature (e.g. power button). + * Power Manageable:Can change device's power consumption behavior. + * Has a HID: In the BIOS ASL this device has a hardware ID as + * defined in section 6.1.4 of ACPI Spec 2.0 + * Has a CID: In the BIOS ASL this device has a compatible ID as + * defined in section 6.1.2 of ACPI Spec 2.0 + * Has a ADR: In the BIOS ASL this device has an address ID as + * defined in section 6.1.1 of ACPI Spec 2.0 + * Is a bridge: This device is recognized as a bridge to another bus. + * Is on PCI bus: This device is on a PCI bus or within PCI configuration + * address space. + * Is on USB bus: This device is on or within USB address space. + * Is on SCSI bus: This device is on or within SCSI address space. + * Driver Control: A driver has been installed for this device. + */ +typedef u32 BM_DEVICE_FLAGS; + +#define BM_FLAGS_UNKNOWN ((BM_DEVICE_FLAGS) 0x00000000) + +#define BM_FLAGS_DYNAMIC_STATUS ((BM_DEVICE_FLAGS) 0x00000001) +#define BM_FLAGS_IDENTIFIABLE ((BM_DEVICE_FLAGS) 0x00000002) +#define BM_FLAGS_CONFIGURABLE ((BM_DEVICE_FLAGS) 0x00000004) +#define BM_FLAGS_POWER_CONTROL ((BM_DEVICE_FLAGS) 0x00000008) +#define BM_FLAGS_EJECTABLE ((BM_DEVICE_FLAGS) 0x00000010) +#define BM_FLAGS_DOCKING_STATION ((BM_DEVICE_FLAGS) 0x00000020) +#define BM_FLAGS_FIXED_FEATURE ((BM_DEVICE_FLAGS) 0x00000040) +#define BM_FLAGS_IS_POWER_MANAGEABLE ((BM_DEVICE_FLAGS) 0x00000080) +#define BM_FLAGS_HAS_A_HID ((BM_DEVICE_FLAGS) 0x00000100) +#define BM_FLAGS_HAS_A_CID ((BM_DEVICE_FLAGS) 0x00000200) +#define BM_FLAGS_HAS_A_ADR ((BM_DEVICE_FLAGS) 0x00000400) +#define BM_FLAGS_IS_A_BRIDGE ((BM_DEVICE_FLAGS) 0x00000800) +#define BM_FLAGS_IS_ON_PCI_BUS ((BM_DEVICE_FLAGS) 0x00001000) +#define BM_FLAGS_IS_ON_USB_BUS ((BM_DEVICE_FLAGS) 0x00002000) +#define BM_FLAGS_IS_ON_SCSI_BUS ((BM_DEVICE_FLAGS) 0x00004000) +#define BM_FLAGS_DRIVER_CONTROL ((BM_DEVICE_FLAGS) 0x80000000) + +/* + * Device PM Flags: + * ---------------- + * +-----------+-+-+-+-+-+-+-+ + * | Bits 31:7 |6|5|4|3|2|1|0| + * +-----------+-+-+-+-+-+-+-+ + * | | | | | | | | + * | | | | | | | +- D0 Support? + * | | | | | | +--- D1 Support? + * | | | | | +----- D2 Support? + * | | | | +------- D3 Support? + * | | | +--------- Power State Queriable? + * | | +----------- Inrush Current? + * | +------------- Wake Capable? + * +-------------------- + * + * D0-D3 Support: Device supports corresponding Dx state. + * Power State: Device has a _PSC (current power state) object defined. + * Inrush Current: Device has an _IRC (inrush current) object defined. + * Wake Capable: Device has a _PRW (wake-capable) object defined. + */ +#define BM_FLAGS_D0_SUPPORT ((BM_DEVICE_FLAGS) 0x00000001) +#define BM_FLAGS_D1_SUPPORT ((BM_DEVICE_FLAGS) 0x00000002) +#define BM_FLAGS_D2_SUPPORT ((BM_DEVICE_FLAGS) 0x00000004) +#define BM_FLAGS_D3_SUPPORT ((BM_DEVICE_FLAGS) 0x00000008) +#define BM_FLAGS_POWER_STATE ((BM_DEVICE_FLAGS) 0x00000010) +#define BM_FLAGS_INRUSH_CURRENT ((BM_DEVICE_FLAGS) 0x00000020) +#define BM_FLAGS_WAKE_CAPABLE ((BM_DEVICE_FLAGS) 0x00000040) + + +/* + * BM_DEVICE_STATUS: + * ----------------- + * The encoding of BM_DEVICE_STATUS is illustrated below. + * Note that a set bit (1) indicates the property is TRUE + * (e.g. if bit 0 is set then the device is present). + * +-----------+-+-+-+-+-+ + * | Bits 31:4 |4|3|2|1|0| + * +-----------+-+-+-+-+-+ + * | | | | | | + * | | | | | +- Present? + * | | | | +--- Enabled? + * | | | +----- Show in UI? + * | | +------- Functioning? + * | +--------- Battery Present? + * +---------------- + */ +typedef u32 BM_DEVICE_STATUS; + +#define BM_STATUS_UNKNOWN ((BM_DEVICE_STATUS) 0x00000000) +#define BM_STATUS_PRESENT ((BM_DEVICE_STATUS) 0x00000001) +#define BM_STATUS_ENABLED ((BM_DEVICE_STATUS) 0x00000002) +#define BM_STATUS_SHOW_UI ((BM_DEVICE_STATUS) 0x00000004) +#define BM_STATUS_FUNCTIONING ((BM_DEVICE_STATUS) 0x00000008) +#define BM_STATUS_BATTERY_PRESENT ((BM_DEVICE_STATUS) 0x00000010) +#define BM_STATUS_DEFAULT ((BM_DEVICE_STATUS) 0x0000000F) + + +typedef u32 BM_POWER_STATE; + +typedef u8 BM_PCI_BUS_NUM; +typedef u8 BM_PCI_DEVICE_NUM; +typedef u8 BM_PCI_FUNCTION_NUM; +typedef u8 BM_U8_RESERVED; +typedef u8 BM_PCI_DEVICE_CLASS_ID; +typedef u8 BM_PCI_DEVICE_SUBCLASS_ID; +typedef u8 BM_PCI_DEVICE_PROG_IF; +typedef u8 BM_PCI_DEVICE_REVISION; +typedef u16 BM_PCI_VENDOR_ID; +typedef u16 BM_PCI_DEVICE_ID; +typedef u32 BM_U32_RESERVED; + + +/* + * BM_DEVICE_ID: + * This structure, when filled in for a device, provides + * an "association" between hardware space and ACPI. + * ----------------------------------------------------------- + */ +typedef struct +{ + BM_DEVICE_CID cid; + BM_DEVICE_HID hid; + BM_DEVICE_UID uid; + BM_DEVICE_TYPE type; + BM_DEVICE_ADR adr; + BM_PCI_BUS_NUM pci_bus_num; + BM_PCI_DEVICE_NUM pci_device_num; + BM_PCI_FUNCTION_NUM pci_func_num; + BM_U8_RESERVED u8_reserved; + BM_PCI_DEVICE_CLASS_ID pci_device_class_id; + BM_PCI_DEVICE_SUBCLASS_ID pci_device_subclass_id; + BM_PCI_DEVICE_PROG_IF pci_device_prog_if; + BM_PCI_DEVICE_REVISION pci_device_rev_num; + BM_PCI_VENDOR_ID pci_vendor_id; + BM_PCI_DEVICE_ID pci_device_id; + BM_U32_RESERVED u32_reserved; +} BM_DEVICE_ID; + + +/* + * BM_DEVICE_POWER: + * ---------------- + * Structure containing basic device power management information. + */ +typedef struct +{ + BM_DEVICE_FLAGS flags; + BM_POWER_STATE state; + BM_DEVICE_FLAGS dx_supported[ACPI_S_STATE_COUNT]; +} BM_DEVICE_POWER; + + +/* + * BM_DEVICE: + * ---------- + */ +typedef struct +{ + BM_HANDLE handle; + ACPI_HANDLE acpi_handle; + BM_DEVICE_FLAGS flags; + BM_DEVICE_STATUS status; + BM_DEVICE_ID id; + BM_DEVICE_POWER power; +} BM_DEVICE; + + +/* + * BM_SEARCH: + * ---------- + * Structure used for searching the ACPI Bus Manager's device hierarchy. + */ +typedef struct +{ + BM_DEVICE_ID criteria; + BM_HANDLE_LIST results; +} BM_SEARCH; + + +/* + * BM_REQUEST: + * ----------- + * Structure used for sending requests to/through the ACPI Bus Manager. + */ +typedef struct +{ + ACPI_STATUS status; + BM_COMMAND command; + BM_HANDLE handle; + ACPI_BUFFER buffer; +} BM_REQUEST; + + +/* + * Driver Registration: + * -------------------- + */ + +/* Driver Context */ +typedef void * BM_DRIVER_CONTEXT; + +/* Notification Callback Function */ +typedef +ACPI_STATUS (*BM_DRIVER_NOTIFY) ( + BM_NOTIFY notify_type, + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context); + +/* Request Callback Function */ +typedef +ACPI_STATUS (*BM_DRIVER_REQUEST) ( + BM_REQUEST *request, + BM_DRIVER_CONTEXT context); + +/* Driver Registration */ +typedef struct +{ + BM_DRIVER_NOTIFY notify; + BM_DRIVER_REQUEST request; + BM_DRIVER_CONTEXT context; +} BM_DRIVER; + + +/* + * BM_NODE: + * -------- + * Structure used to maintain the device hierarchy. + */ +typedef struct _BM_NODE +{ + BM_DEVICE device; + BM_DRIVER driver; + struct _BM_NODE *parent; + struct _BM_NODE *next; + struct + { + struct _BM_NODE *head; + struct _BM_NODE *tail; + } scope; +} BM_NODE; + + +/* + * BM_NODE_LIST: + * ------------- + * Structure used to maintain an array of node pointers. + */ +typedef struct +{ + u32 count; + BM_NODE *nodes[BM_HANDLES_MAX]; +} BM_NODE_LIST; + + +/***************************************************************************** + * Macros + *****************************************************************************/ + +#define BM_DEVICE_PRESENT(d) (d->status & BM_STATUS_PRESENT) +#define BM_NODE_PRESENT(n) (n->device.status & BM_STATUS_PRESENT) + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* bm.c */ + +ACPI_STATUS +bm_initialize (void); + +ACPI_STATUS +bm_terminate (void); + +ACPI_STATUS +bm_get_status ( + BM_DEVICE *device); + +ACPI_STATUS +bm_get_handle ( + ACPI_HANDLE acpi_handle, + BM_HANDLE *device_handle); + +ACPI_STATUS +bm_get_node ( + BM_HANDLE device_handle, + ACPI_HANDLE acpi_handle, + BM_NODE **node); + +/* bmsearch.c */ + +ACPI_STATUS +bm_search( + BM_HANDLE device_handle, + BM_DEVICE_ID *criteria, + BM_HANDLE_LIST *results); + +/* bmnotify.c */ + +void +bm_notify ( + ACPI_HANDLE acpi_handle, + u32 notify_value, + void *context); + +/* bm_request.c */ + +ACPI_STATUS +bm_request ( + BM_REQUEST *request_info); + +/* bmxface.c */ + +ACPI_STATUS +bm_get_device_status ( + BM_HANDLE device_handle, + BM_DEVICE_STATUS *device_status); + +ACPI_STATUS +bm_get_device_info ( + BM_HANDLE device_handle, + BM_DEVICE **device_info); + +ACPI_STATUS +bm_get_device_context ( + BM_HANDLE device_handle, + BM_DRIVER_CONTEXT *context); + +ACPI_STATUS +bm_register_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver); + +ACPI_STATUS +bm_unregister_driver ( + BM_DEVICE_ID *criteria, + BM_DRIVER *driver); + +/* bmpm.c */ + +ACPI_STATUS +bm_get_pm_capabilities ( + BM_NODE *node); + +ACPI_STATUS +bm_get_power_state ( + BM_NODE *node); + +ACPI_STATUS +bm_set_power_state ( + BM_NODE *node, + BM_POWER_STATE target_state); + +/* bmpower.c */ + +ACPI_STATUS +bm_pr_initialize (void); + +ACPI_STATUS +bm_pr_terminate (void); + +/* bmutils.c */ + +ACPI_STATUS +bm_cast_buffer ( + ACPI_BUFFER *buffer, + void **pointer, + u32 length); + +ACPI_STATUS +bm_copy_to_buffer ( + ACPI_BUFFER *buffer, + void *data, + u32 length); + +ACPI_STATUS +bm_extract_package_data ( + ACPI_OBJECT *package, + ACPI_BUFFER *format, + ACPI_BUFFER *buffer); + +ACPI_STATUS +bm_evaluate_object ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + ACPI_OBJECT_LIST *arguments, + ACPI_BUFFER *buffer); + +ACPI_STATUS +bm_evaluate_simple_integer ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + u32 *data); + +ACPI_STATUS +bm_evaluate_reference_list ( + ACPI_HANDLE acpi_handle, + ACPI_STRING pathname, + BM_HANDLE_LIST *reference_list); + +/* bm_proc.c */ + +ACPI_STATUS +bm_proc_initialize (void); + +ACPI_STATUS +bm_proc_terminate (void); + +ACPI_STATUS +bm_generate_event ( + BM_HANDLE device_handle, + char *device_type, + char *device_instance, + u32 event_type, + u32 event_data); + + +#endif /* __BM_H__ */ diff --git a/drivers/bus/acpi/ospm/include/bmpower.h b/drivers/bus/acpi/ospm/include/bmpower.h new file mode 100644 index 0000000..1041c2b --- /dev/null +++ b/drivers/bus/acpi/ospm/include/bmpower.h @@ -0,0 +1,75 @@ +/***************************************************************************** + * + * Module name: bmpower.h + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BMPOWER_H__ +#define __BMPOWER_H__ + +#include "bm.h" + + +/***************************************************************************** + * Types & Defines + *****************************************************************************/ + + +/* + * BM_POWER_RESOURCE: + * ------------------ + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + BM_POWER_STATE system_level; + u32 resource_order; + BM_POWER_STATE state; + u32 reference_count; +} BM_POWER_RESOURCE; + + +/***************************************************************************** + * Function Prototypes + *****************************************************************************/ + +/* bmpower.c */ + +ACPI_STATUS +bm_pr_initialize (void); + +ACPI_STATUS +bm_pr_terminate (void); + +ACPI_STATUS +bm_pr_list_get_state ( + BM_HANDLE_LIST *resource_list, + BM_POWER_STATE *power_state); + +ACPI_STATUS +bm_pr_list_transition ( + BM_HANDLE_LIST *current_list, + BM_HANDLE_LIST *target_list); + + +#endif /* __BMPOWER_H__ */ diff --git a/drivers/bus/acpi/ospm/include/bn.h b/drivers/bus/acpi/ospm/include/bn.h new file mode 100644 index 0000000..4da62a9 --- /dev/null +++ b/drivers/bus/acpi/ospm/include/bn.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * + * Module Name: bn.h + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef __BN_H__ +#define __BN_H__ + +#include +#include +#include + + +/***************************************************************************** + * Types & Other Defines + *****************************************************************************/ + +/* + * Notifications: + * --------------------- + */ +#define BN_NOTIFY_STATUS_CHANGE ((BM_NOTIFY) 0x80) + +/* + * Types: + * ------ + */ +#define BN_TYPE_POWER_BUTTON (0x01) +#define BN_TYPE_POWER_BUTTON_FIXED (0x02) +#define BN_TYPE_SLEEP_BUTTON (0x03) +#define BN_TYPE_SLEEP_BUTTON_FIXED (0x04) +#define BN_TYPE_LID_SWITCH (0x05) + +/* + * Hardware IDs: + * ------------- + * TODO: Power and Sleep button HIDs also exist in . Should all + * HIDs (ACPI well-known devices) exist in one place (e.g. + * acpi_hid.h)? + */ +#define BN_HID_POWER_BUTTON "PNP0C0C" +#define BN_HID_SLEEP_BUTTON "PNP0C0E" +#define BN_HID_LID_SWITCH "PNP0C0D" + +/* + * /proc Entries: + * -------------- + */ +#define BN_PROC_ROOT "button" +#define BN_PROC_POWER_BUTTON "power" +#define BN_PROC_SLEEP_BUTTON "sleep" +#define BN_PROC_LID_SWITCH "lid" + +/* + * Device Context: + * --------------- + */ +typedef struct +{ + BM_HANDLE device_handle; + ACPI_HANDLE acpi_handle; + u32 type; +} BN_CONTEXT; + + +/****************************************************************************** + * Function Prototypes + *****************************************************************************/ + +ACPI_STATUS +bn_initialize (void); + +ACPI_STATUS +bn_terminate (void); + +ACPI_STATUS +bn_notify_fixed ( + void *context); + +ACPI_STATUS +bn_notify ( + u32 notify_type, + u32 device, + void **context); + +ACPI_STATUS +bn_request( + BM_REQUEST *request_info, + void *context); + + +#endif /* __BN_H__ */ diff --git a/drivers/bus/acpi/ospm/osl.c b/drivers/bus/acpi/ospm/osl.c new file mode 100644 index 0000000..f46fd17 --- /dev/null +++ b/drivers/bus/acpi/ospm/osl.c @@ -0,0 +1,613 @@ +/******************************************************************************* +* * +* ACPI Component Architecture Operating System Layer (OSL) for ReactOS * +* * +*******************************************************************************/ + +/* + * Copyright (C) 2000 Andrew Henroid + * Copyright (C) 2001 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include + +#define NDEBUG +#include + +static PKINTERRUPT AcpiInterrupt; +static BOOLEAN AcpiInterruptHandlerRegistered = FALSE; +static OSD_HANDLER AcpiIrqHandler = NULL; +static PVOID AcpiIrqContext = NULL; +static ULONG AcpiIrqNumber = 0; +static KDPC AcpiDpc; +static PVOID IVTVirtualAddress = NULL; +static PVOID BDAVirtualAddress = NULL; + + +VOID STDCALL +OslDpcStub( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + OSD_EXECUTION_CALLBACK Routine = (OSD_EXECUTION_CALLBACK)SystemArgument1; + + DPRINT("OslDpcStub()\n"); + + DPRINT("Calling [%p]([%p])\n", Routine, SystemArgument2); + + (*Routine)(SystemArgument2); +} + + +ACPI_STATUS +acpi_os_remove_interrupt_handler( + u32 irq, + OSD_HANDLER handler); + + +ACPI_STATUS +acpi_os_initialize(void) +{ + DPRINT("acpi_os_initialize()\n"); + + KeInitializeDpc(&AcpiDpc, OslDpcStub, NULL); + + return AE_OK; +} + +ACPI_STATUS +acpi_os_terminate(void) +{ + DPRINT("acpi_os_terminate()\n"); + + if (AcpiInterruptHandlerRegistered) { + acpi_os_remove_interrupt_handler(AcpiIrqNumber, AcpiIrqHandler); + } + + return AE_OK; +} + +s32 +acpi_os_printf(const NATIVE_CHAR *fmt,...) +{ + LONG Size; + va_list args; + va_start(args, fmt); + Size = acpi_os_vprintf(fmt, args); + va_end(args); + return Size; +} + +s32 +acpi_os_vprintf(const NATIVE_CHAR *fmt, va_list args) +{ + static char Buffer[512]; + LONG Size = vsprintf(Buffer, fmt, args); + + DbgPrint("%s", Buffer); + return Size; +} + +void * +acpi_os_allocate(u32 size) +{ + return ExAllocatePool(NonPagedPool, size); +} + +void * +acpi_os_callocate(u32 size) +{ + PVOID ptr = ExAllocatePool(NonPagedPool, size); + if (ptr) + memset(ptr, 0, size); + return ptr; +} + +void +acpi_os_free(void *ptr) +{ + if (ptr) { + /* FIXME: There is at least one bug somewhere that + results in an attempt to release a null pointer */ + ExFreePool(ptr); + } +} + +ACPI_STATUS +acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, u32 size, void **virt) +{ + PHYSICAL_ADDRESS Address; + PVOID Virtual; + + DPRINT("acpi_os_map_memory(phys 0x%X size 0x%X)\n", (ULONG)phys, size); + + if (phys == 0x0) { + /* Real mode Interrupt Vector Table */ + Virtual = ExAllocatePool(NonPagedPool, size); + if (NT_SUCCESS(NtVdmControl(0, Virtual))) { + IVTVirtualAddress = Virtual; + *virt = Virtual; + return AE_OK; + } else { + return AE_ERROR; + } + } + + if ((ULONG)phys >= 0x100000) { + Address.QuadPart = (ULONG)phys; + *virt = MmMapIoSpace(Address, size, FALSE); + if (!*virt) + return AE_ERROR; + } else { + *virt = (PVOID)((ULONG)phys); + } + + return AE_OK; +} + +void +acpi_os_unmap_memory(void *virt, u32 size) +{ + DPRINT("acpi_os_unmap_memory()\n"); + + if (virt == IVTVirtualAddress) { + /* Real mode Interrupt Vector Table */ + ExFreePool(IVTVirtualAddress); + IVTVirtualAddress = NULL; + return; + } + /* FIXME: Causes "Memory area is NULL" bugcheck in marea.c */ + //if ((ULONG)virt >= 0x100000) + //MmUnmapIoSpace(virt, size); +} + +ACPI_STATUS +acpi_os_get_physical_address(void *virt, ACPI_PHYSICAL_ADDRESS *phys) +{ + PHYSICAL_ADDRESS Address; + + DPRINT("acpi_os_get_physical_address()\n"); + + if (!phys || !virt) + return AE_BAD_PARAMETER; + + Address = MmGetPhysicalAddress(virt); + + *phys = (ULONG)Address.QuadPart; + + return AE_OK; +} + +BOOLEAN STDCALL +OslIsrStub( + PKINTERRUPT Interrupt, + PVOID ServiceContext) +{ + INT32 Status; + + Status = (*AcpiIrqHandler)(AcpiIrqContext); + + if (Status == INTERRUPT_HANDLED) + return TRUE; + else + return FALSE; +} + +ACPI_STATUS +acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) +{ + ULONG Vector; + KIRQL DIrql; + KAFFINITY Affinity; + NTSTATUS Status; + + DPRINT("acpi_os_install_interrupt_handler()\n"); + + Vector = HalGetInterruptVector( + Internal, + 0, + 0, + irq, + &DIrql, + &Affinity); + + Status = IoConnectInterrupt( + &AcpiInterrupt, + OslIsrStub, + NULL, + NULL, + Vector, + DIrql, + DIrql, + LevelSensitive, /* FIXME: LevelSensitive or Latched? */ + FALSE, + Affinity, + FALSE); + if (!NT_SUCCESS(Status)) { + DPRINT("Could not connect to interrupt %d\n", Vector); + return AE_ERROR; + } + + AcpiIrqNumber = irq; + AcpiIrqHandler = handler; + AcpiIrqContext = context; + AcpiInterruptHandlerRegistered = TRUE; + + return AE_OK; +} + +ACPI_STATUS +acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler) +{ + DPRINT("acpi_os_remove_interrupt_handler()\n"); + + if (AcpiInterruptHandlerRegistered) { + IoDisconnectInterrupt(AcpiInterrupt); + AcpiInterrupt = NULL; + AcpiInterruptHandlerRegistered = FALSE; + } + + return AE_OK; +} + +void +acpi_os_sleep(u32 sec, u32 ms) +{ + /* FIXME: Wait */ +} + +void +acpi_os_sleep_usec(u32 us) +{ + KeStallExecutionProcessor(us); +} + +u8 +acpi_os_in8(ACPI_IO_ADDRESS port) +{ + return READ_PORT_UCHAR((PUCHAR)port); +} + +u16 +acpi_os_in16(ACPI_IO_ADDRESS port) +{ + return READ_PORT_USHORT((PUSHORT)port); +} + +u32 +acpi_os_in32(ACPI_IO_ADDRESS port) +{ + return READ_PORT_ULONG((PULONG)port); +} + +void +acpi_os_out8(ACPI_IO_ADDRESS port, u8 val) +{ + WRITE_PORT_UCHAR((PUCHAR)port, val); +} + +void +acpi_os_out16(ACPI_IO_ADDRESS port, u16 val) +{ + WRITE_PORT_USHORT((PUSHORT)port, val); +} + +void +acpi_os_out32(ACPI_IO_ADDRESS port, u32 val) +{ + WRITE_PORT_ULONG((PULONG)port, val); +} + +UINT8 +acpi_os_mem_in8 (ACPI_PHYSICAL_ADDRESS phys_addr) +{ + return (*(PUCHAR)(ULONG)phys_addr); +} + +UINT16 +acpi_os_mem_in16 (ACPI_PHYSICAL_ADDRESS phys_addr) +{ + return (*(PUSHORT)(ULONG)phys_addr); +} + +UINT32 +acpi_os_mem_in32 (ACPI_PHYSICAL_ADDRESS phys_addr) +{ + return (*(PULONG)(ULONG)phys_addr); +} + +void +acpi_os_mem_out8 (ACPI_PHYSICAL_ADDRESS phys_addr, UINT8 value) +{ + *(PUCHAR)(ULONG)phys_addr = value; +} + +void +acpi_os_mem_out16 (ACPI_PHYSICAL_ADDRESS phys_addr, UINT16 value) +{ + *(PUSHORT)(ULONG)phys_addr = value; +} + +void +acpi_os_mem_out32 (ACPI_PHYSICAL_ADDRESS phys_addr, UINT32 value) +{ + *(PULONG)(ULONG)phys_addr = value; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_byte( + u32 bus, + u32 func, + u32 addr, + u8 * val) +{ + /* FIXME: What do we do here? */ + + DPRINT("acpi_os_read_pci_cfg_byte is not implemented"); + + return AE_ERROR; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_word( + u32 bus, + u32 func, + u32 addr, + u16 * val) +{ + /* FIXME: What do we do here? */ + + DPRINT("acpi_os_read_pci_cfg_word is not implemented"); + + return AE_ERROR; +} + +ACPI_STATUS +acpi_os_read_pci_cfg_dword( + u32 bus, + u32 func, + u32 addr, + u32 * val) +{ + /* FIXME: What do we do here? */ + + DPRINT("acpi_os_read_pci_cfg_dword is not implemented"); + + return AE_ERROR; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_byte( + u32 bus, + u32 func, + u32 addr, + u8 val) +{ + /* FIXME: What do we do here? */ + + DPRINT("acpi_os_write_pci_cfg_byte is not implemented"); + + return AE_ERROR; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_word( + u32 bus, + u32 func, + u32 addr, + u16 val) +{ + /* FIXME: What do we do here? */ + + DPRINT("acpi_os_write_pci_cfg_word is not implemented"); + + return AE_ERROR; +} + +ACPI_STATUS +acpi_os_write_pci_cfg_dword( + u32 bus, + u32 func, + u32 addr, + u32 val) +{ + /* FIXME: What do we do here? */ + + DPRINT("acpi_os_write_pci_cfg_dword is not implemented"); + + return AE_ERROR; +} + +ACPI_STATUS +acpi_os_load_module ( + char *module_name) +{ + DPRINT("acpi_os_load_module()\n"); + + if (!module_name) + return AE_BAD_PARAMETER; + + return AE_OK; +} + +ACPI_STATUS +acpi_os_unload_module ( + char *module_name) +{ + DPRINT("acpi_os_unload_module()\n"); + + if (!module_name) + return AE_BAD_PARAMETER; + + return AE_OK; +} + +ACPI_STATUS +acpi_os_queue_for_execution( + u32 priority, + OSD_EXECUTION_CALLBACK function, + void *context) +{ + ACPI_STATUS Status = AE_OK; + + DPRINT("acpi_os_queue_for_execution()\n"); + + if (!function) + return AE_BAD_PARAMETER; + + DPRINT("Scheduling task [%p](%p) for execution.\n", function, context); + +#if 0 + switch (priority) { + case OSD_PRIORITY_MED: + KeSetImportanceDpc(&AcpiDpc, MediumImportance); + case OSD_PRIORITY_LO: + KeSetImportanceDpc(&AcpiDpc, LowImportance); + case OSD_PRIORITY_HIGH: + default: + KeSetImportanceDpc(&AcpiDpc, HighImportance); + } +#endif + + KeInsertQueueDpc(&AcpiDpc, (PVOID)function, (PVOID)context); + + return Status; +} + +ACPI_STATUS +acpi_os_create_semaphore( + u32 max_units, + u32 initial_units, + ACPI_HANDLE *handle) +{ + PFAST_MUTEX Mutex; + + Mutex = ExAllocatePool(NonPagedPool, sizeof(FAST_MUTEX)); + if (!Mutex) + return AE_NO_MEMORY; + + DPRINT("acpi_os_create_semaphore() at 0x%X\n", Mutex); + + ExInitializeFastMutex(Mutex); + + *handle = Mutex; + return AE_OK; +} + +ACPI_STATUS +acpi_os_delete_semaphore( + ACPI_HANDLE handle) +{ + PFAST_MUTEX Mutex = (PFAST_MUTEX)handle; + + DPRINT("acpi_os_delete_semaphore(handle 0x%X)\n", handle); + + if (!Mutex) + return AE_BAD_PARAMETER; + + ExFreePool(Mutex); + + return AE_OK; +} + +ACPI_STATUS +acpi_os_wait_semaphore( + ACPI_HANDLE handle, + u32 units, + u32 timeout) +{ + ACPI_STATUS Status = AE_OK; + PFAST_MUTEX Mutex = (PFAST_MUTEX)handle; + + if (!Mutex || (units < 1)) { + DPRINT("acpi_os_wait_semaphore(handle 0x%X, units %d) Bad parameters\n", + handle, units); + return AE_BAD_PARAMETER; + } + + DPRINT("Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout); + + //ExAcquireFastMutex(Mutex); + + return AE_OK; +} + +ACPI_STATUS +acpi_os_signal_semaphore( + ACPI_HANDLE handle, + u32 units) +{ + PFAST_MUTEX Mutex = (PFAST_MUTEX)handle; + + if (!Mutex || (units < 1)) { + DPRINT("acpi_os_signal_semaphore(handle 0x%X) Bad parameter\n", handle); + return AE_BAD_PARAMETER; + } + + DPRINT("Signaling semaphore[%p|%d]\n", handle, units); + + //ExReleaseFastMutex(Mutex); + + return AE_OK; +} + +ACPI_STATUS +acpi_os_breakpoint(NATIVE_CHAR *msg) +{ + DPRINT1("BREAKPOINT: %s", msg); + return AE_OK; +} + +void +acpi_os_dbg_trap(char *msg) + +{ + DPRINT1("TRAP: %s", msg); +} + +void +acpi_os_dbg_assert(void *failure, void *file, u32 line, NATIVE_CHAR *msg) +{ + DPRINT1("ASSERT: %s\n", msg); +} + +u32 +acpi_os_get_line(NATIVE_CHAR *buffer) +{ + return 0; +} + +BOOLEAN +acpi_os_readable(void *ptr, u32 len) +{ + /* Always readable */ + return TRUE; +} + +BOOLEAN +acpi_os_writable(void *ptr, u32 len) +{ + /* Always writable */ + return TRUE; +} + +u32 +acpi_os_get_thread_id (void) +{ + return (ULONG)PsGetCurrentThreadId(); +} diff --git a/drivers/bus/acpi/ospm/pdo.c b/drivers/bus/acpi/ospm/pdo.c new file mode 100644 index 0000000..0388e3d --- /dev/null +++ b/drivers/bus/acpi/ospm/pdo.c @@ -0,0 +1,221 @@ +/* $Id$ + * + * PROJECT: ReactOS ACPI bus driver + * FILE: acpi/ospm/pdo.c + * PURPOSE: Child device object dispatch routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 08-08-2001 CSH Created + */ +#include +#include +#include + +#define NDEBUG +#include + +/*** PRIVATE *****************************************************************/ + +NTSTATUS +PdoQueryId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPDO_DEVICE_EXTENSION DeviceExtension; + ACPI_STATUS AcpiStatus; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + +// Irp->IoStatus.Information = 0; + + switch (IrpSp->Parameters.QueryId.IdType) { + case BusQueryDeviceID: + break; + + case BusQueryHardwareIDs: + case BusQueryCompatibleIDs: + case BusQueryInstanceID: + case BusQueryDeviceSerialNumber: + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; +} + + +NTSTATUS +PdoSetPower( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPDO_DEVICE_EXTENSION DeviceExtension; + ACPI_STATUS AcpiStatus; + NTSTATUS Status; + ULONG AcpiState; + + DPRINT("Called\n"); + + DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (IrpSp->Parameters.Power.Type == DevicePowerState) { + Status = STATUS_SUCCESS; + switch (IrpSp->Parameters.Power.State.SystemState) { + default: + Status = STATUS_UNSUCCESSFUL; + } + } else { + Status = STATUS_UNSUCCESSFUL; + } + + return Status; +} + + +/*** PUBLIC ******************************************************************/ + +NTSTATUS +STDCALL +PdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + case IRP_MN_CANCEL_REMOVE_DEVICE: + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + break; + + case IRP_MN_EJECT: + break; + + case IRP_MN_QUERY_BUS_INFORMATION: + break; + + case IRP_MN_QUERY_CAPABILITIES: + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + /* FIXME: Possibly handle for RemovalRelations */ + break; + + case IRP_MN_QUERY_DEVICE_TEXT: + break; + + case IRP_MN_QUERY_ID: + break; + + case IRP_MN_QUERY_PNP_DEVICE_STATE: + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + break; + + case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: + break; + + case IRP_MN_QUERY_RESOURCES: + break; + + case IRP_MN_QUERY_STOP_DEVICE: + break; + + case IRP_MN_REMOVE_DEVICE: + break; + + case IRP_MN_SET_LOCK: + break; + + case IRP_MN_START_DEVICE: + break; + + case IRP_MN_STOP_DEVICE: + break; + + case IRP_MN_SURPRISE_REMOVAL: + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +NTSTATUS +STDCALL +PdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + case IRP_MN_SET_POWER: + Status = PdoSetPower(DeviceObject, Irp, IrpSp); + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +/* EOF */ diff --git a/drivers/bus/acpi/parser/.cvsignore b/drivers/bus/acpi/parser/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/parser/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/parser/psargs.c b/drivers/bus/acpi/parser/psargs.c new file mode 100644 index 0000000..9c99410 --- /dev/null +++ b/drivers/bus/acpi/parser/psargs.c @@ -0,0 +1,733 @@ +/****************************************************************************** + * + * Module Name: psargs - Parse AML opcode arguments + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psargs") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_package_length + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Decoded package length. On completion, the AML pointer points + * past the length byte or bytes. + * + * DESCRIPTION: Decode and return a package length field + * + ******************************************************************************/ + +u32 +acpi_ps_get_next_package_length ( + ACPI_PARSE_STATE *parser_state) +{ + u32 encoded_length; + u32 length = 0; + + + encoded_length = (u32) GET8 (parser_state->aml); + parser_state->aml++; + + + switch (encoded_length >> 6) /* bits 6-7 contain encoding scheme */ { + case 0: /* 1-byte encoding (bits 0-5) */ + + length = (encoded_length & 0x3F); + break; + + + case 1: /* 2-byte encoding (next byte + bits 0-3) */ + + length = ((GET8 (parser_state->aml) << 04) | + (encoded_length & 0x0F)); + parser_state->aml++; + break; + + + case 2: /* 3-byte encoding (next 2 bytes + bits 0-3) */ + + length = ((GET8 (parser_state->aml + 1) << 12) | + (GET8 (parser_state->aml) << 04) | + (encoded_length & 0x0F)); + parser_state->aml += 2; + break; + + + case 3: /* 4-byte encoding (next 3 bytes + bits 0-3) */ + + length = ((GET8 (parser_state->aml + 2) << 20) | + (GET8 (parser_state->aml + 1) << 12) | + (GET8 (parser_state->aml) << 04) | + (encoded_length & 0x0F)); + parser_state->aml += 3; + break; + } + + return (length); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_package_end + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Pointer to end-of-package +1 + * + * DESCRIPTION: Get next package length and return a pointer past the end of + * the package. Consumes the package length field + * + ******************************************************************************/ + +u8 * +acpi_ps_get_next_package_end ( + ACPI_PARSE_STATE *parser_state) +{ + u8 *start = parser_state->aml; + NATIVE_UINT length; + + + length = (NATIVE_UINT) acpi_ps_get_next_package_length (parser_state); + + return (start + length); /* end of package */ +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_namestring + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Pointer to the start of the name string (pointer points into + * the AML. + * + * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name + * prefix characters. Set parser state to point past the string. + * (Name is consumed from the AML.) + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_ps_get_next_namestring ( + ACPI_PARSE_STATE *parser_state) +{ + u8 *start = parser_state->aml; + u8 *end = parser_state->aml; + u32 length; + + + /* Handle multiple prefix characters */ + + while (acpi_ps_is_prefix_char (GET8 (end))) { + /* include prefix '\\' or '^' */ + + end++; + } + + /* Decode the path */ + + switch (GET8 (end)) { + case 0: + + /* Null_name */ + + if (end == start) { + start = NULL; + } + end++; + break; + + + case AML_DUAL_NAME_PREFIX: + + /* two name segments */ + + end += 9; + break; + + + case AML_MULTI_NAME_PREFIX_OP: + + /* multiple name segments */ + + length = (u32) GET8 (end + 1) * 4; + end += 2 + length; + break; + + + default: + + /* single name segment */ + /* assert (Acpi_ps_is_lead (GET8 (End))); */ + + end += 4; + break; + } + + parser_state->aml = (u8*) end; + + return ((NATIVE_CHAR *) start); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_namepath + * + * PARAMETERS: Parser_state - Current parser state object + * Arg - Where the namepath will be stored + * Arg_count - If the namepath points to a control method + * the method's argument is returned here. + * Method_call - Whether the namepath can be the start + * of a method call + * + * RETURN: None + * + * DESCRIPTION: Get next name (if method call, push appropriate # args). Names + * are looked up in either the parsed or internal namespace to + * determine if the name represents a control method. If a method + * is found, the number of arguments to the method is returned. + * This information is critical for parsing to continue correctly. + * + ******************************************************************************/ + + +#ifdef PARSER_ONLY + +void +acpi_ps_get_next_namepath ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *arg, + u32 *arg_count, + u8 method_call) +{ + NATIVE_CHAR *path; + ACPI_PARSE_OBJECT *name_op; + ACPI_PARSE_OBJECT *op; + ACPI_PARSE_OBJECT *count; + + + path = acpi_ps_get_next_namestring (parser_state); + if (!path || !method_call) { + /* Null name case, create a null namepath object */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + return; + } + + + if (acpi_gbl_parsed_namespace_root) { + /* + * Lookup the name in the parsed namespace + */ + + op = NULL; + if (method_call) { + op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state), + path, AML_METHOD_OP, 0); + } + + if (op) { + if (op->opcode == AML_METHOD_OP) { + /* + * The name refers to a control method, so this namepath is a + * method invocation. We need to 1) Get the number of arguments + * associated with this method, and 2) Change the NAMEPATH + * object into a METHODCALL object. + */ + + count = acpi_ps_get_arg (op, 0); + if (count && count->opcode == AML_BYTE_OP) { + name_op = acpi_ps_alloc_op (AML_NAMEPATH_OP); + if (name_op) { + /* Change arg into a METHOD CALL and attach the name */ + + acpi_ps_init_op (arg, AML_METHODCALL_OP); + + name_op->value.name = path; + + /* Point METHODCALL/NAME to the METHOD Node */ + + name_op->node = (ACPI_NAMESPACE_NODE *) op; + acpi_ps_append_arg (arg, name_op); + + *arg_count = count->value.integer & + METHOD_FLAGS_ARG_COUNT; + } + } + + return; + } + + /* + * Else this is normal named object reference. + * Just init the NAMEPATH object with the pathname. + * (See code below) + */ + } + } + + + /* + * Either we didn't find the object in the namespace, or the object is + * something other than a control method. Just initialize the Op with the + * pathname + */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + + + return; +} + + +#else + + +void +acpi_ps_get_next_namepath ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *arg, + u32 *arg_count, + u8 method_call) +{ + NATIVE_CHAR *path; + ACPI_PARSE_OBJECT *name_op; + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *method_node = NULL; + ACPI_NAMESPACE_NODE *node; + ACPI_GENERIC_STATE scope_info; + + + path = acpi_ps_get_next_namestring (parser_state); + if (!path || !method_call) { + /* Null name case, create a null namepath object */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + return; + } + + + if (method_call) { + /* + * Lookup the name in the internal namespace + */ + scope_info.scope.node = NULL; + node = parser_state->start_node; + if (node) { + scope_info.scope.node = node; + } + + /* + * Lookup object. We don't want to add anything new to the namespace + * here, however. So we use MODE_EXECUTE. Allow searching of the + * parent tree, but don't open a new scope -- we just want to lookup the + * object (MUST BE mode EXECUTE to perform upsearch) + */ + + status = acpi_ns_lookup (&scope_info, path, ACPI_TYPE_ANY, IMODE_EXECUTE, + NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE, NULL, + &node); + if (ACPI_SUCCESS (status)) { + if (node->type == ACPI_TYPE_METHOD) { + method_node = node; + name_op = acpi_ps_alloc_op (AML_NAMEPATH_OP); + if (name_op) { + /* Change arg into a METHOD CALL and attach name to it */ + + acpi_ps_init_op (arg, AML_METHODCALL_OP); + + name_op->value.name = path; + + /* Point METHODCALL/NAME to the METHOD Node */ + + name_op->node = method_node; + acpi_ps_append_arg (arg, name_op); + + if (!(ACPI_OPERAND_OBJECT *) method_node->object) { + return; + } + + *arg_count = ((ACPI_OPERAND_OBJECT *) method_node->object)->method.param_count; + } + + return; + } + + /* + * Else this is normal named object reference. + * Just init the NAMEPATH object with the pathname. + * (See code below) + */ + } + } + + /* + * Either we didn't find the object in the namespace, or the object is + * something other than a control method. Just initialize the Op with the + * pathname. + */ + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = path; + + + return; +} + +#endif + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_simple_arg + * + * PARAMETERS: Parser_state - Current parser state object + * Arg_type - The argument type (AML_*_ARG) + * Arg - Where the argument is returned + * + * RETURN: None + * + * DESCRIPTION: Get the next simple argument (constant, string, or namestring) + * + ******************************************************************************/ + +void +acpi_ps_get_next_simple_arg ( + ACPI_PARSE_STATE *parser_state, + u32 arg_type, + ACPI_PARSE_OBJECT *arg) +{ + + + switch (arg_type) { + + case ARGP_BYTEDATA: + + acpi_ps_init_op (arg, AML_BYTE_OP); + arg->value.integer = (u32) GET8 (parser_state->aml); + parser_state->aml++; + break; + + + case ARGP_WORDDATA: + + acpi_ps_init_op (arg, AML_WORD_OP); + + /* Get 2 bytes from the AML stream */ + + MOVE_UNALIGNED16_TO_32 (&arg->value.integer, parser_state->aml); + parser_state->aml += 2; + break; + + + case ARGP_DWORDDATA: + + acpi_ps_init_op (arg, AML_DWORD_OP); + + /* Get 4 bytes from the AML stream */ + + MOVE_UNALIGNED32_TO_32 (&arg->value.integer, parser_state->aml); + parser_state->aml += 4; + break; + + + case ARGP_CHARLIST: + + acpi_ps_init_op (arg, AML_STRING_OP); + arg->value.string = (char*) parser_state->aml; + + while (GET8 (parser_state->aml) != '\0') { + parser_state->aml++; + } + parser_state->aml++; + break; + + + case ARGP_NAME: + case ARGP_NAMESTRING: + + acpi_ps_init_op (arg, AML_NAMEPATH_OP); + arg->value.name = acpi_ps_get_next_namestring (parser_state); + break; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_field + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: A newly allocated FIELD op + * + * DESCRIPTION: Get next field (Named_field, Reserved_field, or Access_field) + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +acpi_ps_get_next_field ( + ACPI_PARSE_STATE *parser_state) +{ + ACPI_PTRDIFF aml_offset = parser_state->aml - + parser_state->aml_start; + ACPI_PARSE_OBJECT *field; + u16 opcode; + u32 name; + + + /* determine field type */ + + switch (GET8 (parser_state->aml)) { + + default: + + opcode = AML_NAMEDFIELD_OP; + break; + + + case 0x00: + + opcode = AML_RESERVEDFIELD_OP; + parser_state->aml++; + break; + + + case 0x01: + + opcode = AML_ACCESSFIELD_OP; + parser_state->aml++; + break; + } + + + /* Allocate a new field op */ + + field = acpi_ps_alloc_op (opcode); + if (field) { + field->aml_offset = aml_offset; + + /* Decode the field type */ + + switch (opcode) { + case AML_NAMEDFIELD_OP: + + /* Get the 4-character name */ + + MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml); + acpi_ps_set_name (field, name); + parser_state->aml += 4; + + /* Get the length which is encoded as a package length */ + + field->value.size = acpi_ps_get_next_package_length (parser_state); + break; + + + case AML_RESERVEDFIELD_OP: + + /* Get the length which is encoded as a package length */ + + field->value.size = acpi_ps_get_next_package_length (parser_state); + break; + + + case AML_ACCESSFIELD_OP: + + /* Get Access_type and Access_atrib and merge into the field Op */ + + field->value.integer = ((GET8 (parser_state->aml) << 8) | + GET8 (parser_state->aml)); + parser_state->aml += 2; + break; + } + } + + return (field); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_arg + * + * PARAMETERS: Parser_state - Current parser state object + * Arg_type - The argument type (AML_*_ARG) + * Arg_count - If the argument points to a control method + * the method's argument is returned here. + * + * RETURN: An op object containing the next argument. + * + * DESCRIPTION: Get next argument (including complex list arguments that require + * pushing the parser stack) + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +acpi_ps_get_next_arg ( + ACPI_PARSE_STATE *parser_state, + u32 arg_type, + u32 *arg_count) +{ + ACPI_PARSE_OBJECT *arg = NULL; + ACPI_PARSE_OBJECT *prev = NULL; + ACPI_PARSE_OBJECT *field; + u32 subop; + + + switch (arg_type) { + case ARGP_BYTEDATA: + case ARGP_WORDDATA: + case ARGP_DWORDDATA: + case ARGP_CHARLIST: + case ARGP_NAME: + case ARGP_NAMESTRING: + + /* constants, strings, and namestrings are all the same size */ + + arg = acpi_ps_alloc_op (AML_BYTE_OP); + if (arg) { + acpi_ps_get_next_simple_arg (parser_state, arg_type, arg); + } + break; + + + case ARGP_PKGLENGTH: + + /* package length, nothing returned */ + + parser_state->pkg_end = acpi_ps_get_next_package_end (parser_state); + break; + + + case ARGP_FIELDLIST: + + if (parser_state->aml < parser_state->pkg_end) { + /* non-empty list */ + + while (parser_state->aml < parser_state->pkg_end) { + field = acpi_ps_get_next_field (parser_state); + if (!field) { + break; + } + + if (prev) { + prev->next = field; + } + + else { + arg = field; + } + + prev = field; + } + + /* skip to End of byte data */ + + parser_state->aml = parser_state->pkg_end; + } + break; + + + case ARGP_BYTELIST: + + if (parser_state->aml < parser_state->pkg_end) { + /* non-empty list */ + + arg = acpi_ps_alloc_op (AML_BYTELIST_OP); + if (arg) { + /* fill in bytelist data */ + + arg->value.size = (parser_state->pkg_end - parser_state->aml); + ((ACPI_PARSE2_OBJECT *) arg)->data = parser_state->aml; + } + + /* skip to End of byte data */ + + parser_state->aml = parser_state->pkg_end; + } + break; + + + case ARGP_TARGET: + case ARGP_SUPERNAME: { + subop = acpi_ps_peek_opcode (parser_state); + if (subop == 0 || + acpi_ps_is_leading_char (subop) || + acpi_ps_is_prefix_char (subop)) { + /* Null_name or Name_string */ + + arg = acpi_ps_alloc_op (AML_NAMEPATH_OP); + if (arg) { + acpi_ps_get_next_namepath (parser_state, arg, arg_count, 0); + } + } + + else { + /* single complex argument, nothing returned */ + + *arg_count = 1; + } + } + break; + + + case ARGP_DATAOBJ: + case ARGP_TERMARG: + + /* single complex argument, nothing returned */ + + *arg_count = 1; + break; + + + case ARGP_DATAOBJLIST: + case ARGP_TERMLIST: + case ARGP_OBJLIST: + + if (parser_state->aml < parser_state->pkg_end) { + /* non-empty list of variable arguments, nothing returned */ + + *arg_count = ACPI_VAR_ARGS; + } + break; + } + + return (arg); +} diff --git a/drivers/bus/acpi/parser/psopcode.c b/drivers/bus/acpi/parser/psopcode.c new file mode 100644 index 0000000..7e3f7cf --- /dev/null +++ b/drivers/bus/acpi/parser/psopcode.c @@ -0,0 +1,650 @@ +/****************************************************************************** + * + * Module Name: psopcode - Parser opcode information table + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psopcode") + + +#define _UNK 0x6B +/* + * Reserved ASCII characters. Do not use any of these for + * internal opcodes, since they are used to differentiate + * name strings from AML opcodes + */ +#define _ASC 0x6C +#define _NAM 0x6C +#define _PFX 0x6D +#define _UNKNOWN_OPCODE 0x02 /* An example unknown opcode */ + +#define MAX_EXTENDED_OPCODE 0x88 +#define NUM_EXTENDED_OPCODE MAX_EXTENDED_OPCODE + 1 +#define MAX_INTERNAL_OPCODE +#define NUM_INTERNAL_OPCODE MAX_INTERNAL_OPCODE + 1 + + +/******************************************************************************* + * + * NAME: Acpi_gbl_Aml_op_info + * + * DESCRIPTION: Opcode table. Each entry contains + * The name is a simple ascii string, the operand specifier is an + * ascii string with one letter per operand. The letter specifies + * the operand type. + * + ******************************************************************************/ + + +/* + * Flags byte: 0-4 (5 bits) = Opcode Type + * 5 (1 bit) = Has arguments flag + * 6-7 (2 bits) = Reserved + */ +#define AML_NO_ARGS 0 +#define AML_HAS_ARGS ACPI_OP_ARGS_MASK + +/* + * All AML opcodes and the parse-time arguments for each. Used by the AML parser Each list is compressed + * into a 32-bit number and stored in the master opcode table at the end of this file. + */ + +#define ARGP_ZERO_OP ARG_NONE +#define ARGP_ONE_OP ARG_NONE +#define ARGP_ALIAS_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_NAME) +#define ARGP_NAME_OP ARGP_LIST2 (ARGP_NAME, ARGP_DATAOBJ) +#define ARGP_BYTE_OP ARGP_LIST1 (ARGP_BYTEDATA) +#define ARGP_WORD_OP ARGP_LIST1 (ARGP_WORDDATA) +#define ARGP_DWORD_OP ARGP_LIST1 (ARGP_DWORDDATA) +#define ARGP_STRING_OP ARGP_LIST1 (ARGP_CHARLIST) +#define ARGP_QWORD_OP ARGP_LIST1 (ARGP_QWORDDATA) +#define ARGP_SCOPE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_TERMLIST) +#define ARGP_BUFFER_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_BYTELIST) +#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST) +#define ARGP_VAR_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST) +#define ARGP_METHOD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMLIST) +#define ARGP_LOCAL0 ARG_NONE +#define ARGP_LOCAL1 ARG_NONE +#define ARGP_LOCAL2 ARG_NONE +#define ARGP_LOCAL3 ARG_NONE +#define ARGP_LOCAL4 ARG_NONE +#define ARGP_LOCAL5 ARG_NONE +#define ARGP_LOCAL6 ARG_NONE +#define ARGP_LOCAL7 ARG_NONE +#define ARGP_ARG0 ARG_NONE +#define ARGP_ARG1 ARG_NONE +#define ARGP_ARG2 ARG_NONE +#define ARGP_ARG3 ARG_NONE +#define ARGP_ARG4 ARG_NONE +#define ARGP_ARG5 ARG_NONE +#define ARGP_ARG6 ARG_NONE +#define ARGP_STORE_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SUPERNAME) +#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_ADD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_SUBTRACT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_INCREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_DECREMENT_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_MULTIPLY_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_DIVIDE_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET, ARGP_TARGET) +#define ARGP_SHIFT_LEFT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_SHIFT_RIGHT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_AND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NAND_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_OR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_XOR_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_BIT_NOT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_FIND_SET_LEFT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_FIND_SET_RIGHT_BIT_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_DEREF_OF_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_MOD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG) +#define ARGP_SIZE_OF_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_INDEX_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_MATCH_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_DWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_WORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_BYTE_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_BIT_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_QWORD_FIELD_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_LAND_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LOR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LNOT_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_LEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LGREATER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LLESS_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_TO_BUFFER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_DEC_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_HEX_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_INTEGER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_STRING_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_COPY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SIMPLENAME) +#define ARGP_MID_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET) +#define ARGP_CONTINUE_OP ARG_NONE +#define ARGP_IF_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST) +#define ARGP_ELSE_OP ARGP_LIST2 (ARGP_PKGLENGTH, ARGP_TERMLIST) +#define ARGP_WHILE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_TERMLIST) +#define ARGP_NOOP_OP ARG_NONE +#define ARGP_RETURN_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_BREAK_OP ARG_NONE +#define ARGP_BREAK_POINT_OP ARG_NONE +#define ARGP_ONES_OP ARG_NONE +#define ARGP_MUTEX_OP ARGP_LIST2 (ARGP_NAME, ARGP_BYTEDATA) +#define ARGP_EVENT_OP ARGP_LIST1 (ARGP_NAME) +#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME) +#define ARGP_CREATE_FIELD_OP ARGP_LIST4 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_NAME) +#define ARGP_LOAD_TABLE_OP ARGP_LIST6 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LOAD_OP ARGP_LIST2 (ARGP_NAMESTRING, ARGP_SUPERNAME) +#define ARGP_STALL_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_SLEEP_OP ARGP_LIST1 (ARGP_TERMARG) +#define ARGP_ACQUIRE_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_WORDDATA) +#define ARGP_SIGNAL_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_WAIT_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG) +#define ARGP_RESET_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_RELEASE_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_FROM_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_TO_BCD_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET) +#define ARGP_UNLOAD_OP ARGP_LIST1 (ARGP_SUPERNAME) +#define ARGP_REVISION_OP ARG_NONE +#define ARGP_DEBUG_OP ARG_NONE +#define ARGP_FATAL_OP ARGP_LIST3 (ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_TERMARG) +#define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_DEF_FIELD_OP ARGP_LIST4 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_DEVICE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST) +#define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST) +#define ARGP_THERMAL_ZONE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_OBJLIST) +#define ARGP_INDEX_FIELD_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_BANK_FIELD_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAMESTRING, ARGP_NAMESTRING,ARGP_TERMARG, ARGP_BYTEDATA, ARGP_FIELDLIST) +#define ARGP_DATA_REGION_OP ARGP_LIST4 (ARGP_NAMESTRING, ARGP_TERMARG, ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LNOTEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LLESSEQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_LGREATEREQUAL_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TERMARG) +#define ARGP_NAMEPATH_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_METHODCALL_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_BYTELIST_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_RESERVEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_NAMEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_ACCESSFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING) +#define ARGP_STATICSTRING_OP ARGP_LIST1 (ARGP_NAMESTRING) + + +/* + * All AML opcodes and the runtime arguments for each. Used by the AML interpreter Each list is compressed + * into a 32-bit number and stored in the master opcode table at the end of this file. + * + * (Used by Acpi_aml_prep_operands procedure and the ASL Compiler) + */ + +#define ARGI_ZERO_OP ARG_NONE +#define ARGI_ONE_OP ARG_NONE +#define ARGI_ALIAS_OP ARGI_INVALID_OPCODE +#define ARGI_NAME_OP ARGI_INVALID_OPCODE +#define ARGI_BYTE_OP ARGI_INVALID_OPCODE +#define ARGI_WORD_OP ARGI_INVALID_OPCODE +#define ARGI_DWORD_OP ARGI_INVALID_OPCODE +#define ARGI_STRING_OP ARGI_INVALID_OPCODE +#define ARGI_QWORD_OP ARGI_INVALID_OPCODE +#define ARGI_SCOPE_OP ARGI_INVALID_OPCODE +#define ARGI_BUFFER_OP ARGI_INVALID_OPCODE +#define ARGI_PACKAGE_OP ARGI_INVALID_OPCODE +#define ARGI_VAR_PACKAGE_OP ARGI_INVALID_OPCODE +#define ARGI_METHOD_OP ARGI_INVALID_OPCODE +#define ARGI_LOCAL0 ARG_NONE +#define ARGI_LOCAL1 ARG_NONE +#define ARGI_LOCAL2 ARG_NONE +#define ARGI_LOCAL3 ARG_NONE +#define ARGI_LOCAL4 ARG_NONE +#define ARGI_LOCAL5 ARG_NONE +#define ARGI_LOCAL6 ARG_NONE +#define ARGI_LOCAL7 ARG_NONE +#define ARGI_ARG0 ARG_NONE +#define ARGI_ARG1 ARG_NONE +#define ARGI_ARG2 ARG_NONE +#define ARGI_ARG3 ARG_NONE +#define ARGI_ARG4 ARG_NONE +#define ARGI_ARG5 ARG_NONE +#define ARGI_ARG6 ARG_NONE +#define ARGI_STORE_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_TARGETREF) +#define ARGI_REF_OF_OP ARGI_LIST1 (ARGI_OBJECT_REF) +#define ARGI_ADD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF) +#define ARGI_SUBTRACT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_INCREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) +#define ARGI_DECREMENT_OP ARGI_LIST1 (ARGI_INTEGER_REF) +#define ARGI_MULTIPLY_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_DIVIDE_OP ARGI_LIST4 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF, ARGI_TARGETREF) +#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_AND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_NAND_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_OR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_NOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_XOR_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_BIT_NOT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_FIND_SET_LEFT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_FIND_SET_RIGHT_BIT_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_DEREF_OF_OP ARGI_LIST1 (ARGI_REFERENCE) +#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF) +#define ARGI_MOD_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER) +#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT) +#define ARGI_INDEX_OP ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_DWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_WORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_BYTE_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_BIT_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE) +#define ARGI_QWORD_FIELD_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_LAND_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LNOT_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_LEQUAL_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LGREATER_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_LLESS_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_TO_BUFFER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_DEC_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET) +#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET) +#define ARGI_COPY_OP ARGI_LIST2 (ARGI_ANYTYPE, ARGI_SIMPLE_TARGET) +#define ARGI_MID_OP ARGI_LIST4 (ARGI_BUFFERSTRING,ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_CONTINUE_OP ARGI_INVALID_OPCODE +#define ARGI_IF_OP ARGI_INVALID_OPCODE +#define ARGI_ELSE_OP ARGI_INVALID_OPCODE +#define ARGI_WHILE_OP ARGI_INVALID_OPCODE +#define ARGI_NOOP_OP ARG_NONE +#define ARGI_RETURN_OP ARGI_INVALID_OPCODE +#define ARGI_BREAK_OP ARG_NONE +#define ARGI_BREAK_POINT_OP ARG_NONE +#define ARGI_ONES_OP ARG_NONE +#define ARGI_MUTEX_OP ARGI_INVALID_OPCODE +#define ARGI_EVENT_OP ARGI_INVALID_OPCODE +#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF) +#define ARGI_CREATE_FIELD_OP ARGI_LIST4 (ARGI_BUFFER, ARGI_INTEGER, ARGI_INTEGER, ARGI_REFERENCE) +#define ARGI_LOAD_TABLE_OP ARGI_LIST6 (ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_STRING, ARGI_TARGETREF) +#define ARGI_LOAD_OP ARGI_LIST2 (ARGI_REGION, ARGI_TARGETREF) +#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER) +#define ARGI_ACQUIRE_OP ARGI_LIST2 (ARGI_MUTEX, ARGI_INTEGER) +#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT) +#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER) +#define ARGI_RESET_OP ARGI_LIST1 (ARGI_EVENT) +#define ARGI_RELEASE_OP ARGI_LIST1 (ARGI_MUTEX) +#define ARGI_FROM_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_TARGETREF) +#define ARGI_TO_BCD_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_FIXED_TARGET) +#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE) +#define ARGI_REVISION_OP ARG_NONE +#define ARGI_DEBUG_OP ARG_NONE +#define ARGI_FATAL_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_REGION_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER) +#define ARGI_DEF_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_DEVICE_OP ARGI_INVALID_OPCODE +#define ARGI_PROCESSOR_OP ARGI_INVALID_OPCODE +#define ARGI_POWER_RES_OP ARGI_INVALID_OPCODE +#define ARGI_THERMAL_ZONE_OP ARGI_INVALID_OPCODE +#define ARGI_INDEX_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_BANK_FIELD_OP ARGI_INVALID_OPCODE +#define ARGI_DATA_REGION_OP ARGI_LIST3 (ARGI_STRING, ARGI_STRING, ARGI_STRING) +#define ARGI_LNOTEQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LLESSEQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_LGREATEREQUAL_OP ARGI_INVALID_OPCODE +#define ARGI_NAMEPATH_OP ARGI_INVALID_OPCODE +#define ARGI_METHODCALL_OP ARGI_INVALID_OPCODE +#define ARGI_BYTELIST_OP ARGI_INVALID_OPCODE +#define ARGI_RESERVEDFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_NAMEDFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_ACCESSFIELD_OP ARGI_INVALID_OPCODE +#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE + + +/* + * Master Opcode information table. A summary of everything we know about each opcode, all in one place. + */ + + +static ACPI_OPCODE_INFO aml_op_info[] = +{ +/* Index Opcode Type Class Has Arguments? Name Parser Args Interpreter Args */ + +/* 00 */ /* AML_ZERO_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Zero", ARGP_ZERO_OP, ARGI_ZERO_OP), +/* 01 */ /* AML_ONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "One", ARGP_ONE_OP, ARGI_ONE_OP), +/* 02 */ /* AML_ALIAS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP), +/* 03 */ /* AML_NAME_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Name", ARGP_NAME_OP, ARGI_NAME_OP), +/* 04 */ /* AML_BYTE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_const", ARGP_BYTE_OP, ARGI_BYTE_OP), +/* 05 */ /* AML_WORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Word_const", ARGP_WORD_OP, ARGI_WORD_OP), +/* 06 */ /* AML_DWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Dword_const", ARGP_DWORD_OP, ARGI_DWORD_OP), +/* 07 */ /* AML_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "String", ARGP_STRING_OP, ARGI_STRING_OP), +/* 08 */ /* AML_SCOPE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP), +/* 09 */ /* AML_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP), +/* 0A */ /* AML_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP), +/* 0B */ /* AML_METHOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Method", ARGP_METHOD_OP, ARGI_METHOD_OP), +/* 0C */ /* AML_LOCAL0 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local0", ARGP_LOCAL0, ARGI_LOCAL0), +/* 0D */ /* AML_LOCAL1 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local1", ARGP_LOCAL1, ARGI_LOCAL1), +/* 0E */ /* AML_LOCAL2 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local2", ARGP_LOCAL2, ARGI_LOCAL2), +/* 0F */ /* AML_LOCAL3 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local3", ARGP_LOCAL3, ARGI_LOCAL3), +/* 10 */ /* AML_LOCAL4 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local4", ARGP_LOCAL4, ARGI_LOCAL4), +/* 11 */ /* AML_LOCAL5 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local5", ARGP_LOCAL5, ARGI_LOCAL5), +/* 12 */ /* AML_LOCAL6 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local6", ARGP_LOCAL6, ARGI_LOCAL6), +/* 13 */ /* AML_LOCAL7 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LOCAL_VARIABLE| AML_NO_ARGS, "Local7", ARGP_LOCAL7, ARGI_LOCAL7), +/* 14 */ /* AML_ARG0 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg0", ARGP_ARG0, ARGI_ARG0), +/* 15 */ /* AML_ARG1 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg1", ARGP_ARG1, ARGI_ARG1), +/* 16 */ /* AML_ARG2 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg2", ARGP_ARG2, ARGI_ARG2), +/* 17 */ /* AML_ARG3 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg3", ARGP_ARG3, ARGI_ARG3), +/* 18 */ /* AML_ARG4 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg4", ARGP_ARG4, ARGI_ARG4), +/* 19 */ /* AML_ARG5 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg5", ARGP_ARG5, ARGI_ARG5), +/* 1_a */ /* AML_ARG6 */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_ARGUMENT| AML_NO_ARGS, "Arg6", ARGP_ARG6, ARGI_ARG6), +/* 1_b */ /* AML_STORE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Store", ARGP_STORE_OP, ARGI_STORE_OP), +/* 1_c */ /* AML_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Ref_of", ARGP_REF_OF_OP, ARGI_REF_OF_OP), +/* 1_d */ /* AML_ADD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Add", ARGP_ADD_OP, ARGI_ADD_OP), +/* 1_e */ /* AML_CONCAT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP), +/* 1_f */ /* AML_SUBTRACT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP), +/* 20 */ /* AML_INCREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP), +/* 21 */ /* AML_DECREMENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP), +/* 22 */ /* AML_MULTIPLY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP), +/* 23 */ /* AML_DIVIDE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP), +/* 24 */ /* AML_SHIFT_LEFT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Shift_left", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP), +/* 25 */ /* AML_SHIFT_RIGHT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Shift_right", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP), +/* 26 */ /* AML_BIT_AND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP), +/* 27 */ /* AML_BIT_NAND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP), +/* 28 */ /* AML_BIT_OR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP), +/* 29 */ /* AML_BIT_NOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP), +/* 2_a */ /* AML_BIT_XOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP), +/* 2_b */ /* AML_BIT_NOT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP), +/* 2_c */ /* AML_FIND_SET_LEFT_BIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Find_set_left_bit", ARGP_FIND_SET_LEFT_BIT_OP, ARGI_FIND_SET_LEFT_BIT_OP), +/* 2_d */ /* AML_FIND_SET_RIGHT_BIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Find_set_right_bit", ARGP_FIND_SET_RIGHT_BIT_OP, ARGI_FIND_SET_RIGHT_BIT_OP), +/* 2_e */ /* AML_DEREF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Deref_of", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP), +/* 2_f */ /* AML_NOTIFY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC1| AML_HAS_ARGS, "Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP), +/* 30 */ /* AML_SIZE_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Size_of", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP), +/* 31 */ /* AML_INDEX_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_INDEX| AML_HAS_ARGS, "Index", ARGP_INDEX_OP, ARGI_INDEX_OP), +/* 32 */ /* AML_MATCH_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MATCH| AML_HAS_ARGS, "Match", ARGP_MATCH_OP, ARGI_MATCH_OP), +/* 33 */ /* AML_DWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_dWord_field", ARGP_DWORD_FIELD_OP, ARGI_DWORD_FIELD_OP), +/* 34 */ /* AML_WORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_word_field", ARGP_WORD_FIELD_OP, ARGI_WORD_FIELD_OP), +/* 35 */ /* AML_BYTE_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_byte_field", ARGP_BYTE_FIELD_OP, ARGI_BYTE_FIELD_OP), +/* 36 */ /* AML_BIT_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_bit_field", ARGP_BIT_FIELD_OP, ARGI_BIT_FIELD_OP), +/* 37 */ /* AML_TYPE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "Object_type", ARGP_TYPE_OP, ARGI_TYPE_OP), +/* 38 */ /* AML_LAND_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LAnd", ARGP_LAND_OP, ARGI_LAND_OP), +/* 39 */ /* AML_LOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LOr", ARGP_LOR_OP, ARGI_LOR_OP), +/* 3_a */ /* AML_LNOT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2| AML_HAS_ARGS, "LNot", ARGP_LNOT_OP, ARGI_LNOT_OP), +/* 3_b */ /* AML_LEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP), +/* 3_c */ /* AML_LGREATER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP), +/* 3_d */ /* AML_LLESS_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2| AML_HAS_ARGS, "LLess", ARGP_LLESS_OP, ARGI_LLESS_OP), +/* 3_e */ /* AML_IF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "If", ARGP_IF_OP, ARGI_IF_OP), +/* 3_f */ /* AML_ELSE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Else", ARGP_ELSE_OP, ARGI_ELSE_OP), +/* 40 */ /* AML_WHILE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "While", ARGP_WHILE_OP, ARGI_WHILE_OP), +/* 41 */ /* AML_NOOP_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Noop", ARGP_NOOP_OP, ARGI_NOOP_OP), +/* 42 */ /* AML_RETURN_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_HAS_ARGS, "Return", ARGP_RETURN_OP, ARGI_RETURN_OP), +/* 43 */ /* AML_BREAK_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break", ARGP_BREAK_OP, ARGI_BREAK_OP), +/* 44 */ /* AML_BREAK_POINT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Break_point", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP), +/* 45 */ /* AML_ONES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Ones", ARGP_ONES_OP, ARGI_ONES_OP), + +/* Prefixed opcodes (Two-byte opcodes with a prefix op) */ + +/* 46 */ /* AML_MUTEX_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP), +/* 47 */ /* AML_EVENT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_NO_ARGS, "Event", ARGP_EVENT_OP, ARGI_EVENT_OP), +/* 48 */ /* AML_COND_REF_OF_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Cond_ref_of", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP), +/* 49 */ /* AML_CREATE_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_field", ARGP_CREATE_FIELD_OP, ARGI_CREATE_FIELD_OP), +/* 4_a */ /* AML_LOAD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RECONFIGURATION| AML_HAS_ARGS, "Load", ARGP_LOAD_OP, ARGI_LOAD_OP), +/* 4_b */ /* AML_STALL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Stall", ARGP_STALL_OP, ARGI_STALL_OP), +/* 4_c */ /* AML_SLEEP_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP), +/* 4_d */ /* AML_ACQUIRE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_s| AML_HAS_ARGS, "Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP), +/* 4_e */ /* AML_SIGNAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP), +/* 4_f */ /* AML_WAIT_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_s| AML_HAS_ARGS, "Wait", ARGP_WAIT_OP, ARGI_WAIT_OP), +/* 50 */ /* AML_RESET_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Reset", ARGP_RESET_OP, ARGI_RESET_OP), +/* 51 */ /* AML_RELEASE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC1| AML_HAS_ARGS, "Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP), +/* 52 */ /* AML_FROM_BCD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "From_bCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP), +/* 53 */ /* AML_TO_BCD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_bCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP), +/* 54 */ /* AML_UNLOAD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RECONFIGURATION| AML_HAS_ARGS, "Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP), +/* 55 */ /* AML_REVISION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Revision", ARGP_REVISION_OP, ARGI_REVISION_OP), +/* 56 */ /* AML_DEBUG_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONSTANT| AML_NO_ARGS, "Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP), +/* 57 */ /* AML_FATAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_FATAL| AML_HAS_ARGS, "Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP), +/* 58 */ /* AML_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Op_region", ARGP_REGION_OP, ARGI_REGION_OP), +/* 59 */ /* AML_DEF_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Field", ARGP_DEF_FIELD_OP, ARGI_DEF_FIELD_OP), +/* 5_a */ /* AML_DEVICE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP), +/* 5_b */ /* AML_PROCESSOR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP), +/* 5_c */ /* AML_POWER_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Power_resource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP), +/* 5_d */ /* AML_THERMAL_ZONE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Thermal_zone", ARGP_THERMAL_ZONE_OP, ARGI_THERMAL_ZONE_OP), +/* 5_e */ /* AML_INDEX_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Index_field", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP), +/* 5_f */ /* AML_BANK_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_NAMED_OBJECT| AML_HAS_ARGS, "Bank_field", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP), + +/* Internal opcodes that map to invalid AML opcodes */ + +/* 60 */ /* AML_LNOTEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LNot_equal", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP), +/* 61 */ /* AML_LLESSEQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LLess_equal", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP), +/* 62 */ /* AML_LGREATEREQUAL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_HAS_ARGS, "LGreater_equal", ARGP_LGREATEREQUAL_OP, ARGI_LGREATEREQUAL_OP), +/* 63 */ /* AML_NAMEPATH_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Name_path", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP), +/* 64 */ /* AML_METHODCALL_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_METHOD_CALL| AML_HAS_ARGS, "Method_call", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP), +/* 65 */ /* AML_BYTELIST_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Byte_list", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP), +/* 66 */ /* AML_RESERVEDFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Reserved_field", ARGP_RESERVEDFIELD_OP, ARGI_RESERVEDFIELD_OP), +/* 67 */ /* AML_NAMEDFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Named_field", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP), +/* 68 */ /* AML_ACCESSFIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Access_field", ARGP_ACCESSFIELD_OP, ARGI_ACCESSFIELD_OP), +/* 69 */ /* AML_STATICSTRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_BOGUS| AML_NO_ARGS, "Static_string", ARGP_STATICSTRING_OP, ARGI_STATICSTRING_OP), +/* 6_a */ /* AML_RETURN_VALUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_RETURN| AML_HAS_ARGS, "[Return Value]", ARG_NONE, ARG_NONE), +/* 6_b */ /* UNKNOWN OPCODES */ OP_INFO_ENTRY (ACPI_OP_TYPE_UNKNOWN | OPTYPE_BOGUS| AML_HAS_ARGS, "UNKNOWN_OP!", ARG_NONE, ARG_NONE), +/* 6_c */ /* ASCII CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_ASCII | OPTYPE_BOGUS| AML_HAS_ARGS, "ASCII_ONLY!", ARG_NONE, ARG_NONE), +/* 6_d */ /* PREFIX CHARACTERS */ OP_INFO_ENTRY (ACPI_OP_TYPE_PREFIX | OPTYPE_BOGUS| AML_HAS_ARGS, "PREFIX_ONLY!", ARG_NONE, ARG_NONE), + + +/* ACPI 2.0 (new) opcodes */ + +/* 6_e */ /* AML_QWORD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_LITERAL| AML_NO_ARGS, "Qword_const", ARGP_QWORD_OP, ARGI_QWORD_OP), +/* 6_f */ /* AML_VAR_PACKAGE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DATA_TERM| AML_HAS_ARGS, "Var_package", ARGP_VAR_PACKAGE_OP, ARGI_VAR_PACKAGE_OP), +/* 70 */ /* AML_CONCAT_RES_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Concat_res", ARGP_CONCAT_RES_OP, ARGI_CONCAT_RES_OP), +/* 71 */ /* AML_MOD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_DYADIC2_r| AML_HAS_ARGS, "Mod", ARGP_MOD_OP, ARGI_MOD_OP), +/* 72 */ /* AML_QWORD_FIELD_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CREATE_FIELD| AML_HAS_ARGS, "Create_qWord_field", ARGP_QWORD_FIELD_OP, ARGI_QWORD_FIELD_OP), +/* 73 */ /* AML_TO_BUFFER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_buffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP), +/* 74 */ /* AML_TO_DEC_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_dec_string", ARGP_TO_DEC_STR_OP, ARGI_TO_DEC_STR_OP), +/* 75 */ /* AML_TO_HEX_STR_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_hex_string", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP), +/* 76 */ /* AML_TO_INTEGER_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_integer", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP), +/* 77 */ /* AML_TO_STRING_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "To_string", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP), +/* 78 */ /* AML_COPY_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Copy", ARGP_COPY_OP, ARGI_COPY_OP), +/* 79 */ /* AML_MID_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Mid", ARGP_MID_OP, ARGI_MID_OP), +/* 7_a */ /* AML_CONTINUE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_CONTROL| AML_NO_ARGS, "Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP), +/* 7_b */ /* AML_LOAD_TABLE_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Load_table", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP), +/* 7_c */ /* AML_DATA_REGION_OP */ OP_INFO_ENTRY (ACPI_OP_TYPE_OPCODE | OPTYPE_MONADIC2_r| AML_HAS_ARGS, "Data_op_region", ARGP_DATA_REGION_OP, ARGI_DATA_REGION_OP), + +}; + +/* + * This table is directly indexed by the opcodes, and returns an + * index into the table above + */ + +static u8 aml_short_op_info_index[256] = +{ +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ 0x00, 0x01, _UNK, _UNK, _UNK, _UNK, 0x02, _UNK, +/* 0x08 */ 0x03, _UNK, 0x04, 0x05, 0x06, 0x07, 0x6E, _UNK, +/* 0x10 */ 0x08, 0x09, 0x0a, 0x6F, 0x0b, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x20 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x28 */ _UNK, _UNK, _UNK, _UNK, _UNK, 0x63, _PFX, _PFX, +/* 0x30 */ 0x67, 0x66, 0x68, 0x65, 0x69, 0x64, 0x6A, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x48 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x50 */ _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, _ASC, +/* 0x58 */ _ASC, _ASC, _ASC, _UNK, _PFX, _UNK, _PFX, _ASC, +/* 0x60 */ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, +/* 0x68 */ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, _UNK, +/* 0x70 */ 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, +/* 0x78 */ 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, +/* 0x80 */ 0x2b, 0x2c, 0x2d, 0x2e, 0x70, 0x71, 0x2f, 0x30, +/* 0x88 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x72, +/* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74, +/* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A, +/* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, +/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xC8 */ _UNK, _UNK, _UNK, _UNK, 0x44, _UNK, _UNK, _UNK, +/* 0xD0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xD8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xE8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0xF8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x45, +}; + + +static u8 aml_long_op_info_index[NUM_EXTENDED_OPCODE] = +{ +/* 0 1 2 3 4 5 6 7 */ +/* 8 9 A B C D E F */ +/* 0x00 */ _UNK, 0x46, 0x47, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x08 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x10 */ _UNK, _UNK, 0x48, 0x49, _UNK, _UNK, _UNK, _UNK, +/* 0x18 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, 0x7B, +/* 0x20 */ 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, +/* 0x28 */ 0x52, 0x53, 0x54, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x30 */ 0x55, 0x56, 0x57, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x38 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x40 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x48 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x50 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x58 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x60 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x68 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x70 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x78 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, +/* 0x80 */ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, +/* 0x88 */ 0x7C, +}; + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_opcode_info + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the info about the opcode. NULL if the opcode was + * not found in the table. + * + * DESCRIPTION: Find AML opcode description based on the opcode. + * NOTE: This procedure must ALWAYS return a valid pointer! + * + ******************************************************************************/ + +ACPI_OPCODE_INFO * +acpi_ps_get_opcode_info ( + u16 opcode) +{ + ACPI_OPCODE_INFO *op_info; + u8 upper_opcode; + u8 lower_opcode; + + + /* Split the 16-bit opcode into separate bytes */ + + upper_opcode = (u8) (opcode >> 8); + lower_opcode = (u8) opcode; + + /* Default is "unknown opcode" */ + + op_info = &aml_op_info [_UNK]; + + + /* + * Detect normal 8-bit opcode or extended 16-bit opcode + */ + + switch (upper_opcode) { + case 0: + + /* Simple (8-bit) opcode: 0-255, can't index beyond table */ + + op_info = &aml_op_info [aml_short_op_info_index [lower_opcode]]; + break; + + + case AML_EXTOP: + + /* Extended (16-bit, prefix+opcode) opcode */ + + if (lower_opcode <= MAX_EXTENDED_OPCODE) { + op_info = &aml_op_info [aml_long_op_info_index [lower_opcode]]; + } + break; + + + case AML_LNOT_OP: + + /* This case is for the bogus opcodes LNOTEQUAL, LLESSEQUAL, LGREATEREQUAL */ + /* TBD: [Investigate] remove this case? */ + + break; + + + default: + + break; + } + + + /* Get the Op info pointer for this opcode */ + + return (op_info); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_opcode_name + * + * PARAMETERS: Opcode - The AML opcode + * + * RETURN: A pointer to the name of the opcode (ASCII String) + * Note: Never returns NULL. + * + * DESCRIPTION: Translate an opcode into a human-readable string + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_ps_get_opcode_name ( + u16 opcode) +{ + ACPI_OPCODE_INFO *op; + + + op = acpi_ps_get_opcode_info (opcode); + + /* Always guaranteed to return a valid pointer */ + + return ("AE_NOT_CONFIGURED"); +} + + diff --git a/drivers/bus/acpi/parser/psparse.c b/drivers/bus/acpi/parser/psparse.c new file mode 100644 index 0000000..9d032fb --- /dev/null +++ b/drivers/bus/acpi/parser/psparse.c @@ -0,0 +1,1229 @@ +/****************************************************************************** + * + * Module Name: psparse - Parser top level AML parse routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * Parse the AML and build an operation tree as most interpreters, + * like Perl, do. Parsing is done by hand rather than with a YACC + * generated parser to tightly constrain stack and dynamic memory + * usage. At the same time, parsing is kept flexible and the code + * fairly compact by parsing based on a list of AML opcode + * templates in Aml_op_info[] + */ + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psparse") + + +u32 acpi_gbl_depth = 0; +extern u32 acpi_gbl_scope_depth; + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_peek_opcode + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) + * + ******************************************************************************/ + +static u32 +acpi_ps_get_opcode_size ( + u32 opcode) +{ + + /* Extended (2-byte) opcode if > 255 */ + + if (opcode > 0x00FF) { + return (2); + } + + /* Otherwise, just a single byte opcode */ + + return (1); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_peek_opcode + * + * PARAMETERS: Parser_state - A parser state object + * + * RETURN: Status + * + * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) + * + ******************************************************************************/ + +u16 +acpi_ps_peek_opcode ( + ACPI_PARSE_STATE *parser_state) +{ + u8 *aml; + u16 opcode; + + + aml = parser_state->aml; + opcode = (u16) GET8 (aml); + + aml++; + + + /* + * Original code special cased LNOTEQUAL, LLESSEQUAL, LGREATEREQUAL. + * These opcodes are no longer recognized. Instead, they are broken into + * two opcodes. + * + * + * if (Opcode == AML_EXTOP + * || (Opcode == AML_LNOT + * && (GET8 (Acpi_aml) == AML_LEQUAL + * || GET8 (Acpi_aml) == AML_LGREATER + * || GET8 (Acpi_aml) == AML_LLESS))) + * + * extended Opcode, !=, <=, or >= + */ + + if (opcode == AML_EXTOP) { + /* Extended opcode */ + + opcode = (u16) ((opcode << 8) | GET8 (aml)); + aml++; + } + + /* don't convert bare name to a namepath */ + + return (opcode); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_create_state + * + * PARAMETERS: Acpi_aml - Acpi_aml code pointer + * Acpi_aml_size - Length of AML code + * + * RETURN: A new parser state object + * + * DESCRIPTION: Create and initialize a new parser state object + * + ******************************************************************************/ + +ACPI_PARSE_STATE * +acpi_ps_create_state ( + u8 *aml, + u32 aml_size) +{ + ACPI_PARSE_STATE *parser_state; + + + parser_state = acpi_cm_callocate (sizeof (ACPI_PARSE_STATE)); + if (!parser_state) { + return (NULL); + } + + parser_state->aml = aml; + parser_state->aml_end = aml + aml_size; + parser_state->pkg_end = parser_state->aml_end; + parser_state->aml_start = aml; + + + return (parser_state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_find_object + * + * PARAMETERS: Opcode - Current opcode + * Parser_state - Current state + * Walk_state - Current state + * *Op - Where found/new op is returned + * + * RETURN: Status + * + * DESCRIPTION: Find a named object. Two versions - one to search the parse + * tree (for parser-only applications such as acpidump), another + * to search the ACPI internal namespace (the parse tree may no + * longer exist) + * + ******************************************************************************/ + +#ifdef PARSER_ONLY + +ACPI_STATUS +acpi_ps_find_object ( + u16 opcode, + ACPI_PARSE_OBJECT *op, + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT **out_op) +{ + NATIVE_CHAR *path; + + + /* We are only interested in opcodes that have an associated name */ + + if (!acpi_ps_is_named_op (opcode)) { + *out_op = op; + return (AE_OK); + } + + /* Find the name in the parse tree */ + + path = acpi_ps_get_next_namestring (walk_state->parser_state); + + *out_op = acpi_ps_find (acpi_ps_get_parent_scope (walk_state->parser_state), + path, opcode, 1); + + if (!(*out_op)) { + return (AE_NOT_FOUND); + } + + return (AE_OK); +} + +#endif + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_complete_this_op + * + * PARAMETERS: Walk_state - Current State + * Op - Op to complete + * + * RETURN: TRUE if Op and subtree was deleted + * + * DESCRIPTION: Perform any cleanup at the completion of an Op. + * + ******************************************************************************/ + +static u8 +acpi_ps_complete_this_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op) +{ +#ifndef PARSER_ONLY + ACPI_PARSE_OBJECT *prev; + ACPI_PARSE_OBJECT *next; + ACPI_OPCODE_INFO *op_info; + ACPI_OPCODE_INFO *parent_info; + u32 opcode_class; + ACPI_PARSE_OBJECT *replacement_op = NULL; + + + op_info = acpi_ps_get_opcode_info (op->opcode); + opcode_class = ACPI_GET_OP_CLASS (op_info); + + + /* Delete this op and the subtree below it if asked to */ + + if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) && + (opcode_class != OPTYPE_CONSTANT) && + (opcode_class != OPTYPE_LITERAL) && + (opcode_class != OPTYPE_LOCAL_VARIABLE) && + (opcode_class != OPTYPE_METHOD_ARGUMENT) && + (opcode_class != OPTYPE_DATA_TERM) && + (op->opcode != AML_NAMEPATH_OP)) { + /* Make sure that we only delete this subtree */ + + if (op->parent) { + /* + * Check if we need to replace the operator and its subtree + * with a return value op (placeholder op) + */ + + parent_info = acpi_ps_get_opcode_info (op->parent->opcode); + + switch (ACPI_GET_OP_CLASS (parent_info)) { + case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */ + break; + + case OPTYPE_NAMED_OBJECT: /* Scope, method, etc. */ + + /* + * These opcodes contain Term_arg operands. The current + * op must be replace by a placeholder return op + */ + + if ((op->parent->opcode == AML_REGION_OP) || + (op->parent->opcode == AML_CREATE_FIELD_OP) || + (op->parent->opcode == AML_BIT_FIELD_OP) || + (op->parent->opcode == AML_BYTE_FIELD_OP) || + (op->parent->opcode == AML_WORD_FIELD_OP) || + (op->parent->opcode == AML_DWORD_FIELD_OP) || + (op->parent->opcode == AML_QWORD_FIELD_OP)) { + replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP); + if (!replacement_op) { + return (FALSE); + } + } + + break; + + default: + replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP); + if (!replacement_op) { + return (FALSE); + } + } + + /* We must unlink this op from the parent tree */ + + prev = op->parent->value.arg; + if (prev == op) { + /* This op is the first in the list */ + + if (replacement_op) { + replacement_op->parent = op->parent; + replacement_op->value.arg = NULL; + op->parent->value.arg = replacement_op; + replacement_op->next = op->next; + } + else { + op->parent->value.arg = op->next; + } + } + + /* Search the parent list */ + + else while (prev) { + /* Traverse all siblings in the parent's argument list */ + + next = prev->next; + if (next == op) { + if (replacement_op) { + replacement_op->parent = op->parent; + replacement_op->value.arg = NULL; + prev->next = replacement_op; + replacement_op->next = op->next; + next = NULL; + } + else { + prev->next = op->next; + next = NULL; + } + } + + prev = next; + } + + } + + /* Now we can actually delete the subtree rooted at op */ + + acpi_ps_delete_parse_tree (op); + + return (TRUE); + } + + return (FALSE); + +#else + return (FALSE); +#endif +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_next_parse_state + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: + * + * DESCRIPTION: + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ps_next_parse_state ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_STATUS callback_status) +{ + ACPI_PARSE_STATE *parser_state = walk_state->parser_state; + ACPI_STATUS status = AE_CTRL_PENDING; + u8 *start; + u32 package_length; + + + switch (callback_status) { + case AE_CTRL_TERMINATE: + + /* + * A control method was terminated via a RETURN statement. + * The walk of this method is complete. + */ + + parser_state->aml = parser_state->aml_end; + status = AE_CTRL_TERMINATE; + break; + + + case AE_CTRL_PENDING: + + /* + * Predicate of a WHILE was true and the loop just completed an + * execution. Go back to the start of the loop and reevaluate the + * predicate. + */ +/* Walk_state->Control_state->Common.State = + CONTROL_PREDICATE_EXECUTING;*/ + + /* TBD: How to handle a break within a while. */ + /* This code attempts it */ + + parser_state->aml = walk_state->aml_last_while; + break; + + + case AE_CTRL_TRUE: + /* + * Predicate of an IF was true, and we are at the matching ELSE. + * Just close out this package + * + * Note: Parser_state->Aml is modified by the package length procedure + * TBD: [Investigate] perhaps it shouldn't, too much trouble + */ + start = parser_state->aml; + package_length = acpi_ps_get_next_package_length (parser_state); + parser_state->aml = start + package_length; + break; + + + case AE_CTRL_FALSE: + + /* + * Either an IF/WHILE Predicate was false or we encountered a BREAK + * opcode. In both cases, we do not execute the rest of the + * package; We simply close out the parent (finishing the walk of + * this branch of the tree) and continue execution at the parent + * level. + */ + + parser_state->aml = parser_state->scope->parse_scope.pkg_end; + + /* In the case of a BREAK, just force a predicate (if any) to FALSE */ + + walk_state->control_state->common.value = FALSE; + status = AE_CTRL_END; + break; + + + case AE_CTRL_TRANSFER: + + /* + * A method call (invocation) -- transfer control + */ + status = AE_CTRL_TRANSFER; + walk_state->prev_op = op; + walk_state->method_call_op = op; + walk_state->method_call_node = (op->value.arg)->node; + + /* Will return value (if any) be used by the caller? */ + + walk_state->return_used = acpi_ds_is_result_used (op, walk_state); + break; + + + default: + status = callback_status; + if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) { + status = AE_OK; + } + break; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_parse_loop + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Status + * + * DESCRIPTION: Parse AML (pointed to by the current parser state) and return + * a tree of ops. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_parse_loop ( + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + ACPI_PARSE_OBJECT *op = NULL; /* current op */ + ACPI_OPCODE_INFO *op_info; + ACPI_PARSE_OBJECT *arg = NULL; + ACPI_PARSE2_OBJECT *deferred_op; + u32 arg_count; /* push for fixed or var args */ + u32 arg_types = 0; + ACPI_PTRDIFF aml_offset; + u16 opcode; + ACPI_PARSE_OBJECT pre_op; + ACPI_PARSE_STATE *parser_state; + u8 *aml_op_start; + + + parser_state = walk_state->parser_state; + +#ifndef PARSER_ONLY + if (walk_state->walk_type & WALK_METHOD_RESTART) { + /* We are restarting a preempted control method */ + + if (acpi_ps_has_completed_scope (parser_state)) { + /* + * We must check if a predicate to an IF or WHILE statement + * was just completed + */ + if ((parser_state->scope->parse_scope.op) && + ((parser_state->scope->parse_scope.op->opcode == AML_IF_OP) || + (parser_state->scope->parse_scope.op->opcode == AML_WHILE_OP)) && + (walk_state->control_state) && + (walk_state->control_state->common.state == + CONTROL_PREDICATE_EXECUTING)) { + + /* + * A predicate was just completed, get the value of the + * predicate and branch based on that value + */ + + status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE); + if (ACPI_FAILURE (status) && + ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { + return (status); + } + + status = acpi_ps_next_parse_state (walk_state, op, status); + } + + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + } + + else if (walk_state->prev_op) { + /* We were in the middle of an op */ + + op = walk_state->prev_op; + arg_types = walk_state->prev_arg_types; + } + } +#endif + + /* + * Iterative parsing loop, while there is more aml to process: + */ + while ((parser_state->aml < parser_state->aml_end) || (op)) { + if (!op) { + /* Get the next opcode from the AML stream */ + + aml_op_start = parser_state->aml; + aml_offset = parser_state->aml - parser_state->aml_start; + opcode = acpi_ps_peek_opcode (parser_state); + + /* + * First cut to determine what we have found: + * 1) A valid AML opcode + * 2) A name string + * 3) An unknown/invalid opcode + */ + + op_info = acpi_ps_get_opcode_info (opcode); + switch (ACPI_GET_OP_TYPE (op_info)) { + case ACPI_OP_TYPE_OPCODE: + + /* Found opcode info, this is a normal opcode */ + + parser_state->aml += acpi_ps_get_opcode_size (opcode); + arg_types = op_info->parse_args; + break; + + case ACPI_OP_TYPE_ASCII: + case ACPI_OP_TYPE_PREFIX: + /* + * Starts with a valid prefix or ASCII char, this is a name + * string. Convert the bare name string to a namepath. + */ + + opcode = AML_NAMEPATH_OP; + arg_types = ARGP_NAMESTRING; + break; + + case ACPI_OP_TYPE_UNKNOWN: + + /* The opcode is unrecognized. Just skip unknown opcodes */ + + /* Assume one-byte bad opcode */ + + parser_state->aml++; + continue; + } + + + /* Create Op structure and append to parent's argument list */ + + if (acpi_ps_is_named_op (opcode)) { + pre_op.value.arg = NULL; + pre_op.opcode = opcode; + + while (GET_CURRENT_ARG_TYPE (arg_types) != ARGP_NAME) { + arg = acpi_ps_get_next_arg (parser_state, + GET_CURRENT_ARG_TYPE (arg_types), + &arg_count); + acpi_ps_append_arg (&pre_op, arg); + INCREMENT_ARG_LIST (arg_types); + } + + + /* We know that this arg is a name, move to next arg */ + + INCREMENT_ARG_LIST (arg_types); + + if (walk_state->descending_callback != NULL) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + status = walk_state->descending_callback (opcode, NULL, walk_state, &op); + if (op == NULL) { + continue; + } + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + } + + acpi_ps_append_arg (op, pre_op.value.arg); + acpi_gbl_depth++; + + + if (op->opcode == AML_REGION_OP) { + deferred_op = acpi_ps_to_extended_op (op); + if (deferred_op) { + /* + * Defer final parsing of an Operation_region body, + * because we don't have enough info in the first pass + * to parse it correctly (i.e., there may be method + * calls within the Term_arg elements of the body. + * + * However, we must continue parsing because + * the opregion is not a standalone package -- + * we don't know where the end is at this point. + * + * (Length is unknown until parse of the body complete) + */ + + deferred_op->data = aml_op_start; + deferred_op->length = 0; + } + } + } + + + else { + /* Not a named opcode, just allocate Op and append to parent */ + + op = acpi_ps_alloc_op (opcode); + if (!op) { + return (AE_NO_MEMORY); + } + + + if ((op->opcode == AML_CREATE_FIELD_OP) || + (op->opcode == AML_BIT_FIELD_OP) || + (op->opcode == AML_BYTE_FIELD_OP) || + (op->opcode == AML_WORD_FIELD_OP) || + (op->opcode == AML_DWORD_FIELD_OP)) { + /* + * Backup to beginning of Create_xXXfield declaration + * Body_length is unknown until we parse the body + */ + deferred_op = (ACPI_PARSE2_OBJECT *) op; + + deferred_op->data = aml_op_start; + deferred_op->length = 0; + } + + acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op); + + if ((walk_state->descending_callback != NULL)) { + /* + * Find the object. This will either insert the object into + * the namespace or simply look it up + */ + status = walk_state->descending_callback (opcode, op, walk_state, &op); + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (ACPI_FAILURE (status)) { + goto close_this_op; + } + } + } + + op->aml_offset = aml_offset; + + } + + + /* Start Arg_count at zero because we don't know if there are any args yet */ + + arg_count = 0; + + + if (arg_types) /* Are there any arguments that must be processed? */ { + /* get arguments */ + + switch (op->opcode) { + case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ + case AML_WORD_OP: /* AML_WORDDATA_ARG */ + case AML_DWORD_OP: /* AML_DWORDATA_ARG */ + case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ + + /* fill in constant or string argument directly */ + + acpi_ps_get_next_simple_arg (parser_state, + GET_CURRENT_ARG_TYPE (arg_types), op); + break; + + case AML_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ + + acpi_ps_get_next_namepath (parser_state, op, &arg_count, 1); + arg_types = 0; + break; + + + default: + + /* Op is not a constant or string, append each argument */ + + while (GET_CURRENT_ARG_TYPE (arg_types) && !arg_count) { + aml_offset = parser_state->aml - parser_state->aml_start; + arg = acpi_ps_get_next_arg (parser_state, + GET_CURRENT_ARG_TYPE (arg_types), + &arg_count); + if (arg) { + arg->aml_offset = aml_offset; + acpi_ps_append_arg (op, arg); + } + + INCREMENT_ARG_LIST (arg_types); + } + + + /* For a method, save the length and address of the body */ + + if (op->opcode == AML_METHOD_OP) { + deferred_op = acpi_ps_to_extended_op (op); + if (deferred_op) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + */ + + deferred_op->data = parser_state->aml; + deferred_op->length = parser_state->pkg_end - + parser_state->aml; + + /* + * Skip body of method. For Op_regions, we must continue + * parsing because the opregion is not a standalone + * package (We don't know where the end is). + */ + parser_state->aml = parser_state->pkg_end; + arg_count = 0; + } + } + + break; + } + } + + + /* + * Zero Arg_count means that all arguments for this op have been processed + */ + if (!arg_count) { + /* completed Op, prepare for next */ + + if (acpi_ps_is_named_op (op->opcode)) { + if (acpi_gbl_depth) { + acpi_gbl_depth--; + } + + if (op->opcode == AML_REGION_OP) { + deferred_op = acpi_ps_to_extended_op (op); + if (deferred_op) { + /* + * Skip parsing of control method or opregion body, + * because we don't have enough info in the first pass + * to parse them correctly. + * + * Completed parsing an Op_region declaration, we now + * know the length. + */ + + deferred_op->length = parser_state->aml - + deferred_op->data; + } + } + } + + if ((op->opcode == AML_CREATE_FIELD_OP) || + (op->opcode == AML_BIT_FIELD_OP) || + (op->opcode == AML_BYTE_FIELD_OP) || + (op->opcode == AML_WORD_FIELD_OP) || + (op->opcode == AML_DWORD_FIELD_OP) || + (op->opcode == AML_QWORD_FIELD_OP)) { + /* + * Backup to beginning of Create_xXXfield declaration (1 for + * Opcode) + * + * Body_length is unknown until we parse the body + */ + deferred_op = (ACPI_PARSE2_OBJECT *) op; + deferred_op->length = parser_state->aml - deferred_op->data; + } + + /* This op complete, notify the dispatcher */ + + if (walk_state->ascending_callback != NULL) { + status = walk_state->ascending_callback (walk_state, op); + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + } + + +close_this_op: + + /* + * Finished one argument of the containing scope + */ + parser_state->scope->parse_scope.arg_count--; + + /* Close this Op (may result in parse subtree deletion) */ + + if (acpi_ps_complete_this_op (walk_state, op)) { + op = NULL; + } + + + switch (status) { + case AE_OK: + break; + + + case AE_CTRL_TRANSFER: + + /* + * We are about to transfer to a called method. + */ + walk_state->prev_op = op; + walk_state->prev_arg_types = arg_types; + return (status); + break; + + + case AE_CTRL_END: + + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + + status = walk_state->ascending_callback (walk_state, op); + status = acpi_ps_next_parse_state (walk_state, op, status); + + acpi_ps_complete_this_op (walk_state, op); + op = NULL; + status = AE_OK; + break; + + + case AE_CTRL_TERMINATE: + + status = AE_OK; + + /* Clean up */ + do { + if (op) { + acpi_ps_complete_this_op (walk_state, op); + } + + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + } while (op); + + return (status); + break; + + + default: /* All other non-AE_OK status */ + + if (op == NULL) { + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + } + walk_state->prev_op = op; + walk_state->prev_arg_types = arg_types; + + /* + * TEMP: + */ + + return (status); + break; + } + + + /* This scope complete? */ + + if (acpi_ps_has_completed_scope (parser_state)) { + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + } + + else { + op = NULL; + } + + } + + + /* Arg_count is non-zero */ + + else { + /* complex argument, push Op and prepare for argument */ + + acpi_ps_push_scope (parser_state, op, arg_types, arg_count); + op = NULL; + } + + } /* while Parser_state->Aml */ + + + /* + * Complete the last Op (if not completed), and clear the scope stack. + * It is easily possible to end an AML "package" with an unbounded number + * of open scopes (such as when several AML blocks are closed with + * sequential closing braces). We want to terminate each one cleanly. + */ + + do { + if (op) { + if (walk_state->ascending_callback != NULL) { + status = walk_state->ascending_callback (walk_state, op); + status = acpi_ps_next_parse_state (walk_state, op, status); + if (status == AE_CTRL_PENDING) { + status = AE_OK; + goto close_this_op; + } + + if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + + /* Clean up */ + do { + if (op) { + acpi_ps_complete_this_op (walk_state, op); + } + + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + + } while (op); + + return (status); + } + + else if (ACPI_FAILURE (status)) { + acpi_ps_complete_this_op (walk_state, op); + return (status); + } + } + + acpi_ps_complete_this_op (walk_state, op); + } + + acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count); + + } while (op); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_parse_aml + * + * PARAMETERS: Start_scope - The starting point of the parse. Becomes the + * root of the parsed op tree. + * Aml - Pointer to the raw AML code to parse + * Aml_size - Length of the AML to parse + * + * RETURN: Status + * + * DESCRIPTION: Parse raw AML and return a tree of ops + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_parse_aml ( + ACPI_PARSE_OBJECT *start_scope, + u8 *aml, + u32 aml_size, + u32 parse_flags, + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **caller_return_desc, + ACPI_PARSE_DOWNWARDS descending_callback, + ACPI_PARSE_UPWARDS ascending_callback) +{ + ACPI_STATUS status; + ACPI_PARSE_STATE *parser_state; + ACPI_WALK_STATE *walk_state; + ACPI_WALK_LIST walk_list; + ACPI_NAMESPACE_NODE *node = NULL; + ACPI_WALK_LIST *prev_walk_list = acpi_gbl_current_walk_list; + ACPI_OPERAND_OBJECT *return_desc; + ACPI_OPERAND_OBJECT *mth_desc = NULL; + + + /* Create and initialize a new parser state */ + + parser_state = acpi_ps_create_state (aml, aml_size); + if (!parser_state) { + return (AE_NO_MEMORY); + } + + acpi_ps_init_scope (parser_state, start_scope); + + if (method_node) { + mth_desc = acpi_ns_get_attached_object (method_node); + } + + /* Create and initialize a new walk list */ + + walk_list.walk_state = NULL; + walk_list.acquired_mutex_list.prev = NULL; + walk_list.acquired_mutex_list.next = NULL; + + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, parser_state->start_op, mth_desc, &walk_list); + if (!walk_state) { + status = AE_NO_MEMORY; + goto cleanup; + } + + walk_state->method_node = method_node; + walk_state->parser_state = parser_state; + walk_state->parse_flags = parse_flags; + walk_state->descending_callback = descending_callback; + walk_state->ascending_callback = ascending_callback; + + /* TBD: [Restructure] TEMP until we pass Walk_state to the interpreter + */ + acpi_gbl_current_walk_list = &walk_list; + + + if (method_node) { + parser_state->start_node = method_node; + walk_state->walk_type = WALK_METHOD; + + /* Push start scope on scope stack and make it current */ + + status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Init arguments if this is a control method */ + /* TBD: [Restructure] add walkstate as a param */ + + acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state); + } + + else { + /* Setup the current scope */ + + node = parser_state->start_op->node; + parser_state->start_node = node; + + if (node) { + /* Push start scope on scope stack and make it current */ + + status = acpi_ds_scope_stack_push (node, node->type, + walk_state); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + } + } + + + status = AE_OK; + + /* + * Execute the walk loop as long as there is a valid Walk State. This + * handles nested control method invocations without recursion. + */ + + while (walk_state) { + if (ACPI_SUCCESS (status)) { + status = acpi_ps_parse_loop (walk_state); + } + + if (status == AE_CTRL_TRANSFER) { + /* + * A method call was detected. + * Transfer control to the called control method + */ + + status = acpi_ds_call_control_method (&walk_list, walk_state, NULL); + + /* + * If the transfer to the new method method call worked, a new walk + * state was created -- get it + */ + + walk_state = acpi_ds_get_current_walk_state (&walk_list); + continue; + } + + else if (status == AE_CTRL_TERMINATE) { + status = AE_OK; + } + + /* We are done with this walk, move on to the parent if any */ + + + walk_state = acpi_ds_pop_walk_state (&walk_list); + + /* Extract return value before we delete Walk_state */ + + return_desc = walk_state->return_desc; + + /* Reset the current scope to the beginning of scope stack */ + + acpi_ds_scope_stack_clear (walk_state); + + /* + * If we just returned from the execution of a control method, + * there's lots of cleanup to do + */ + + if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) { + acpi_ds_terminate_control_method (walk_state); + } + + /* Delete this walk state and all linked control states */ + + acpi_ps_cleanup_scope (walk_state->parser_state); + acpi_cm_free (walk_state->parser_state); + acpi_ds_delete_walk_state (walk_state); + + /* Check if we have restarted a preempted walk */ + + walk_state = acpi_ds_get_current_walk_state (&walk_list); + if (walk_state && + ACPI_SUCCESS (status)) { + /* There is another walk state, restart it */ + + /* + * If the method returned value is not used by the parent, + * The object is deleted + */ + + acpi_ds_restart_control_method (walk_state, return_desc); + walk_state->walk_type |= WALK_METHOD_RESTART; + } + + /* + * Just completed a 1st-level method, save the final internal return + * value (if any) + */ + + else if (caller_return_desc) { + *caller_return_desc = return_desc; /* NULL if no return value */ + } + + else if (return_desc) { + /* Caller doesn't want it, must delete it */ + + acpi_cm_remove_reference (return_desc); + } + } + + + /* Normal exit */ + + acpi_aml_release_all_mutexes ((ACPI_OPERAND_OBJECT *) &walk_list.acquired_mutex_list); + acpi_gbl_current_walk_list = prev_walk_list; + return (status); + + +cleanup: + + /* Cleanup */ + + acpi_ds_delete_walk_state (walk_state); + acpi_ps_cleanup_scope (parser_state); + acpi_cm_free (parser_state); + + acpi_aml_release_all_mutexes ((ACPI_OPERAND_OBJECT *)&walk_list.acquired_mutex_list); + acpi_gbl_current_walk_list = prev_walk_list; + + return (status); +} + + diff --git a/drivers/bus/acpi/parser/psscope.c b/drivers/bus/acpi/parser/psscope.c new file mode 100644 index 0000000..0347b94 --- /dev/null +++ b/drivers/bus/acpi/parser/psscope.c @@ -0,0 +1,264 @@ +/****************************************************************************** + * + * Module Name: psscope - Parser scope stack management routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psscope") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_parent_scope + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Pointer to an Op object + * + * DESCRIPTION: Get parent of current op being parsed + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +acpi_ps_get_parent_scope ( + ACPI_PARSE_STATE *parser_state) +{ + return (parser_state->scope->parse_scope.op); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_has_completed_scope + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Boolean, TRUE = scope completed. + * + * DESCRIPTION: Is parsing of current argument complete? Determined by + * 1) AML pointer is at or beyond the end of the scope + * 2) The scope argument count has reached zero. + * + ******************************************************************************/ + +u8 +acpi_ps_has_completed_scope ( + ACPI_PARSE_STATE *parser_state) +{ + return ((u8) ((parser_state->aml >= parser_state->scope->parse_scope.arg_end || + !parser_state->scope->parse_scope.arg_count))); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_init_scope + * + * PARAMETERS: Parser_state - Current parser state object + * Root - the Root Node of this new scope + * + * RETURN: Status + * + * DESCRIPTION: Allocate and init a new scope object + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_init_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *root_op) +{ + ACPI_GENERIC_STATE *scope; + + + scope = acpi_cm_create_generic_state (); + if (!scope) { + return (AE_NO_MEMORY); + } + + scope->parse_scope.op = root_op; + scope->parse_scope.arg_count = ACPI_VAR_ARGS; + scope->parse_scope.arg_end = parser_state->aml_end; + scope->parse_scope.pkg_end = parser_state->aml_end; + + parser_state->scope = scope; + parser_state->start_op = root_op; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_push_scope + * + * PARAMETERS: Parser_state - Current parser state object + * Op - Current op to be pushed + * Remaining_args - List of args remaining + * Arg_count - Fixed or variable number of args + * + * RETURN: Status + * + * DESCRIPTION: Push current op to begin parsing its argument + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_push_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT *op, + u32 remaining_args, + u32 arg_count) +{ + ACPI_GENERIC_STATE *scope; + + + scope = acpi_cm_create_generic_state (); + if (!scope) { + return (AE_NO_MEMORY); + } + + + scope->parse_scope.op = op; + scope->parse_scope.arg_list = remaining_args; + scope->parse_scope.arg_count = arg_count; + scope->parse_scope.pkg_end = parser_state->pkg_end; + + /* Push onto scope stack */ + + acpi_cm_push_generic_state (&parser_state->scope, scope); + + + if (arg_count == ACPI_VAR_ARGS) { + /* multiple arguments */ + + scope->parse_scope.arg_end = parser_state->pkg_end; + } + + else { + /* single argument */ + + scope->parse_scope.arg_end = ACPI_MAX_AML; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_pop_scope + * + * PARAMETERS: Parser_state - Current parser state object + * Op - Where the popped op is returned + * Arg_list - Where the popped "next argument" is + * returned + * Arg_count - Count of objects in Arg_list + * + * RETURN: Status + * + * DESCRIPTION: Return to parsing a previous op + * + ******************************************************************************/ + +void +acpi_ps_pop_scope ( + ACPI_PARSE_STATE *parser_state, + ACPI_PARSE_OBJECT **op, + u32 *arg_list, + u32 *arg_count) +{ + ACPI_GENERIC_STATE *scope = parser_state->scope; + + + /* + * Only pop the scope if there is in fact a next scope + */ + if (scope->common.next) { + scope = acpi_cm_pop_generic_state (&parser_state->scope); + + + /* return to parsing previous op */ + + *op = scope->parse_scope.op; + *arg_list = scope->parse_scope.arg_list; + *arg_count = scope->parse_scope.arg_count; + parser_state->pkg_end = scope->parse_scope.pkg_end; + + /* All done with this scope state structure */ + + acpi_cm_delete_generic_state (scope); + } + + else { + /* empty parse stack, prepare to fetch next opcode */ + + *op = NULL; + *arg_list = 0; + *arg_count = 0; + } + + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_cleanup_scope + * + * PARAMETERS: Parser_state - Current parser state object + * + * RETURN: Status + * + * DESCRIPTION: Destroy available list, remaining stack levels, and return + * root scope + * + ******************************************************************************/ + +void +acpi_ps_cleanup_scope ( + ACPI_PARSE_STATE *parser_state) +{ + ACPI_GENERIC_STATE *scope; + + + if (!parser_state) { + return; + } + + + /* Delete anything on the scope stack */ + + while (parser_state->scope) { + scope = acpi_cm_pop_generic_state (&parser_state->scope); + acpi_cm_delete_generic_state (scope); + } + + return; +} + diff --git a/drivers/bus/acpi/parser/pstree.c b/drivers/bus/acpi/parser/pstree.c new file mode 100644 index 0000000..5bee5d8 --- /dev/null +++ b/drivers/bus/acpi/parser/pstree.c @@ -0,0 +1,288 @@ +/****************************************************************************** + * + * Module Name: pstree - Parser op tree manipulation/traversal/search + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("pstree") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_arg + * + * PARAMETERS: Op - Get an argument for this op + * Argn - Nth argument to get + * + * RETURN: The argument (as an Op object). NULL if argument does not exist + * + * DESCRIPTION: Get the specified op's argument. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +acpi_ps_get_arg ( + ACPI_PARSE_OBJECT *op, + u32 argn) +{ + ACPI_PARSE_OBJECT *arg = NULL; + ACPI_OPCODE_INFO *op_info; + + + /* Get the info structure for this opcode */ + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + /* Invalid opcode or ASCII character */ + + return (NULL); + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(ACPI_GET_OP_ARGS (op_info))) { + /* Has no linked argument objects */ + + return (NULL); + } + + /* Get the requested argument object */ + + arg = op->value.arg; + while (arg && argn) { + argn--; + arg = arg->next; + } + + return (arg); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_append_arg + * + * PARAMETERS: Op - Append an argument to this Op. + * Arg - Argument Op to append + * + * RETURN: None. + * + * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) + * + ******************************************************************************/ + +void +acpi_ps_append_arg ( + ACPI_PARSE_OBJECT *op, + ACPI_PARSE_OBJECT *arg) +{ + ACPI_PARSE_OBJECT *prev_arg; + ACPI_OPCODE_INFO *op_info; + + + if (!op) { + return; + } + + /* Get the info structure for this opcode */ + + op_info = acpi_ps_get_opcode_info (op->opcode); + if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { + /* Invalid opcode */ + + return; + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(ACPI_GET_OP_ARGS (op_info))) { + /* Has no linked argument objects */ + + return; + } + + + /* Append the argument to the linked argument list */ + + if (op->value.arg) { + /* Append to existing argument list */ + + prev_arg = op->value.arg; + while (prev_arg->next) { + prev_arg = prev_arg->next; + } + prev_arg->next = arg; + } + + else { + /* No argument list, this will be the first argument */ + + op->value.arg = arg; + } + + + /* Set the parent in this arg and any args linked after it */ + + while (arg) { + arg->parent = op; + arg = arg->next; + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_child + * + * PARAMETERS: Op - Get the child of this Op + * + * RETURN: Child Op, Null if none is found. + * + * DESCRIPTION: Get op's children or NULL if none + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +acpi_ps_get_child ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_PARSE_OBJECT *child = NULL; + + + switch (op->opcode) { + case AML_SCOPE_OP: + case AML_ELSE_OP: + case AML_DEVICE_OP: + case AML_THERMAL_ZONE_OP: + case AML_METHODCALL_OP: + + child = acpi_ps_get_arg (op, 0); + break; + + + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_METHOD_OP: + case AML_IF_OP: + case AML_WHILE_OP: + case AML_DEF_FIELD_OP: + + child = acpi_ps_get_arg (op, 1); + break; + + + case AML_POWER_RES_OP: + case AML_INDEX_FIELD_OP: + + child = acpi_ps_get_arg (op, 2); + break; + + + case AML_PROCESSOR_OP: + case AML_BANK_FIELD_OP: + + child = acpi_ps_get_arg (op, 3); + break; + + } + + return (child); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_depth_next + * + * PARAMETERS: Origin - Root of subtree to search + * Op - Last (previous) Op that was found + * + * RETURN: Next Op found in the search. + * + * DESCRIPTION: Get next op in tree (walking the tree in depth-first order) + * Return NULL when reaching "origin" or when walking up from root + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT * +acpi_ps_get_depth_next ( + ACPI_PARSE_OBJECT *origin, + ACPI_PARSE_OBJECT *op) +{ + ACPI_PARSE_OBJECT *next = NULL; + ACPI_PARSE_OBJECT *parent; + ACPI_PARSE_OBJECT *arg; + + + if (!op) { + return (NULL); + } + + /* look for an argument or child */ + + next = acpi_ps_get_arg (op, 0); + if (next) { + return (next); + } + + /* look for a sibling */ + + next = op->next; + if (next) { + return (next); + } + + /* look for a sibling of parent */ + + parent = op->parent; + + while (parent) { + arg = acpi_ps_get_arg (parent, 0); + while (arg && (arg != origin) && (arg != op)) { + arg = arg->next; + } + + if (arg == origin) { + /* reached parent of origin, end search */ + + return (NULL); + } + + if (parent->next) { + /* found sibling of parent */ + return (parent->next); + } + + op = parent; + parent = parent->parent; + } + + return (next); +} + + diff --git a/drivers/bus/acpi/parser/psutils.c b/drivers/bus/acpi/parser/psutils.c new file mode 100644 index 0000000..303754c --- /dev/null +++ b/drivers/bus/acpi/parser/psutils.c @@ -0,0 +1,556 @@ +/****************************************************************************** + * + * Module Name: psutils - Parser miscellaneous utilities (Parser only) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psutils") + + +#define PARSEOP_GENERIC 0x01 +#define PARSEOP_NAMED 0x02 +#define PARSEOP_DEFERRED 0x03 +#define PARSEOP_BYTELIST 0x04 +#define PARSEOP_IN_CACHE 0x80 + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_init_op + * + * PARAMETERS: Op - A newly allocated Op object + * Opcode - Opcode to store in the Op + * + * RETURN: Status + * + * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on + * opcode + * + ******************************************************************************/ + +void +acpi_ps_init_op ( + ACPI_PARSE_OBJECT *op, + u16 opcode) +{ + ACPI_OPCODE_INFO *aml_op; + + + op->data_type = ACPI_DESC_TYPE_PARSER; + op->opcode = opcode; + + aml_op = acpi_ps_get_opcode_info (opcode); + + DEBUG_ONLY_MEMBERS (STRNCPY (op->op_name, aml_op->name, + sizeof (op->op_name))); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_alloc_op + * + * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * + * RETURN: Pointer to the new Op. + * + * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on + * opcode. A cache of opcodes is available for the pure + * GENERIC_OP, since this is by far the most commonly used. + * + ******************************************************************************/ + +ACPI_PARSE_OBJECT* +acpi_ps_alloc_op ( + u16 opcode) +{ + ACPI_PARSE_OBJECT *op = NULL; + u32 size; + u8 flags; + + + /* Allocate the minimum required size object */ + + if (acpi_ps_is_deferred_op (opcode)) { + size = sizeof (ACPI_PARSE2_OBJECT); + flags = PARSEOP_DEFERRED; + } + + else if (acpi_ps_is_named_op (opcode)) { + size = sizeof (ACPI_PARSE2_OBJECT); + flags = PARSEOP_NAMED; + } + + else if (acpi_ps_is_bytelist_op (opcode)) { + size = sizeof (ACPI_PARSE2_OBJECT); + flags = PARSEOP_BYTELIST; + } + + else { + size = sizeof (ACPI_PARSE_OBJECT); + flags = PARSEOP_GENERIC; + } + + + if (size == sizeof (ACPI_PARSE_OBJECT)) { + /* + * The generic op is by far the most common (16 to 1), and therefore + * the op cache is implemented with this type. + * + * Check if there is an Op already available in the cache + */ + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_parse_cache_requests++; + if (acpi_gbl_parse_cache) { + /* Extract an op from the front of the cache list */ + + acpi_gbl_parse_cache_depth--; + acpi_gbl_parse_cache_hits++; + + op = acpi_gbl_parse_cache; + acpi_gbl_parse_cache = op->next; + + + /* Clear the previously used Op */ + + MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT)); + + } + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* + * The generic op is by far the most common (16 to 1), and therefore + * the op cache is implemented with this type. + * + * Check if there is an Op already available in the cache + */ + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_ext_parse_cache_requests++; + if (acpi_gbl_ext_parse_cache) { + /* Extract an op from the front of the cache list */ + + acpi_gbl_ext_parse_cache_depth--; + acpi_gbl_ext_parse_cache_hits++; + + op = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache; + acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op->next; + + + /* Clear the previously used Op */ + + MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT)); + + } + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + + /* Allocate a new Op if necessary */ + + if (!op) { + op = acpi_cm_callocate (size); + } + + /* Initialize the Op */ + if (op) { + acpi_ps_init_op (op, opcode); + op->flags = flags; + } + + return (op); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_free_op + * + * PARAMETERS: Op - Op to be freed + * + * RETURN: None. + * + * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list + * or actually free it. + * + ******************************************************************************/ + +void +acpi_ps_free_op ( + ACPI_PARSE_OBJECT *op) +{ + + + + if (op->flags == PARSEOP_GENERIC) { + /* Is the cache full? */ + + if (acpi_gbl_parse_cache_depth < MAX_PARSE_CACHE_DEPTH) { + /* Put a GENERIC_OP back into the cache */ + + /* Clear the previously used Op */ + + MEMSET (op, 0, sizeof (ACPI_PARSE_OBJECT)); + op->flags = PARSEOP_IN_CACHE; + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_parse_cache_depth++; + + op->next = acpi_gbl_parse_cache; + acpi_gbl_parse_cache = op; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + return; + } + } + + else { + /* Is the cache full? */ + + if (acpi_gbl_ext_parse_cache_depth < MAX_EXTPARSE_CACHE_DEPTH) { + /* Put a GENERIC_OP back into the cache */ + + /* Clear the previously used Op */ + + MEMSET (op, 0, sizeof (ACPI_PARSE2_OBJECT)); + op->flags = PARSEOP_IN_CACHE; + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + acpi_gbl_ext_parse_cache_depth++; + + op->next = (ACPI_PARSE_OBJECT *) acpi_gbl_ext_parse_cache; + acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) op; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + return; + } + } + + + /* + * Not a GENERIC OP, or the cache is full, just free the Op + */ + + acpi_cm_free (op); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_delete_parse_cache + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Free all objects that are on the parse cache list. + * + ******************************************************************************/ + +void +acpi_ps_delete_parse_cache ( + void) +{ + ACPI_PARSE_OBJECT *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_parse_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_parse_cache->next; + acpi_cm_free (acpi_gbl_parse_cache); + acpi_gbl_parse_cache = next; + acpi_gbl_parse_cache_depth--; + } + + /* Traverse the global cache list */ + + while (acpi_gbl_ext_parse_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_ext_parse_cache->next; + acpi_cm_free (acpi_gbl_ext_parse_cache); + acpi_gbl_ext_parse_cache = (ACPI_PARSE2_OBJECT *) next; + acpi_gbl_ext_parse_cache_depth--; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Utility functions + * + * DESCRIPTION: Low level functions + * + * TBD: [Restructure] + * 1) Some of these functions should be macros + * 2) Some can be simplified + * + ******************************************************************************/ + + +/* + * Is "c" a namestring lead character? + */ + + +u8 +acpi_ps_is_leading_char ( + u32 c) +{ + return ((u8) (c == '_' || (c >= 'A' && c <= 'Z'))); +} + + +/* + * Is "c" a namestring prefix character? + */ +u8 +acpi_ps_is_prefix_char ( + u32 c) +{ + return ((u8) (c == '\\' || c == '^')); +} + + +u8 +acpi_ps_is_namespace_object_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_DEF_FIELD_OP || + opcode == AML_INDEX_FIELD_OP || + opcode == AML_BANK_FIELD_OP || + opcode == AML_NAMEDFIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP || + opcode == AML_METHODCALL_OP || + opcode == AML_NAMEPATH_OP)); +} + +u8 +acpi_ps_is_namespace_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_DEF_FIELD_OP || + opcode == AML_INDEX_FIELD_OP || + opcode == AML_BANK_FIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_NAMEDFIELD_OP)); +} + + +/* + * Is opcode for a named object Op? + * (Includes all named object opcodes) + * + * TBD: [Restructure] Need a better way than this brute force approach! + */ +u8 +acpi_ps_is_node_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_NAMEDFIELD_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + + + opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP || + opcode == AML_METHODCALL_OP || + opcode == AML_NAMEPATH_OP)); +} + + +/* + * Is opcode for a named Op? + */ +u8 +acpi_ps_is_named_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_SCOPE_OP || + opcode == AML_DEVICE_OP || + opcode == AML_THERMAL_ZONE_OP || + opcode == AML_METHOD_OP || + opcode == AML_POWER_RES_OP || + opcode == AML_PROCESSOR_OP || + opcode == AML_NAME_OP || + opcode == AML_ALIAS_OP || + opcode == AML_MUTEX_OP || + opcode == AML_EVENT_OP || + opcode == AML_REGION_OP || + opcode == AML_NAMEDFIELD_OP)); +} + + +u8 +acpi_ps_is_deferred_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_METHOD_OP || + opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP || + opcode == AML_REGION_OP)); +} + + +/* + * Is opcode for a bytelist? + */ +u8 +acpi_ps_is_bytelist_op ( + u16 opcode) +{ + return ((u8) (opcode == AML_BYTELIST_OP)); +} + + +/* + * Is opcode for a Field, Index_field, or Bank_field + */ +u8 +acpi_ps_is_field_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_CREATE_FIELD_OP + || opcode == AML_DEF_FIELD_OP + || opcode == AML_INDEX_FIELD_OP + || opcode == AML_BANK_FIELD_OP)); +} + + +/* + * Is field creation op + */ +u8 +acpi_ps_is_create_field_op ( + u16 opcode) +{ + return ((u8) + (opcode == AML_CREATE_FIELD_OP || + opcode == AML_BIT_FIELD_OP || + opcode == AML_BYTE_FIELD_OP || + opcode == AML_WORD_FIELD_OP || + opcode == AML_DWORD_FIELD_OP)); +} + + +/* + * Cast an acpi_op to an acpi_extended_op if possible + */ + +/* TBD: This is very inefficient, fix */ +ACPI_PARSE2_OBJECT * +acpi_ps_to_extended_op ( + ACPI_PARSE_OBJECT *op) +{ + return ((acpi_ps_is_deferred_op (op->opcode) || acpi_ps_is_named_op (op->opcode) || acpi_ps_is_bytelist_op (op->opcode)) + ? ( (ACPI_PARSE2_OBJECT *) op) : NULL); +} + + +/* + * Get op's name (4-byte name segment) or 0 if unnamed + */ +u32 +acpi_ps_get_name ( + ACPI_PARSE_OBJECT *op) +{ + ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op); + + return (named ? named->name : 0); +} + + +/* + * Set op's name + */ +void +acpi_ps_set_name ( + ACPI_PARSE_OBJECT *op, + u32 name) +{ + ACPI_PARSE2_OBJECT *named = acpi_ps_to_extended_op (op); + + if (named) { + named->name = name; + } +} + diff --git a/drivers/bus/acpi/parser/pswalk.c b/drivers/bus/acpi/parser/pswalk.c new file mode 100644 index 0000000..d56e282 --- /dev/null +++ b/drivers/bus/acpi/parser/pswalk.c @@ -0,0 +1,283 @@ +/****************************************************************************** + * + * Module Name: pswalk - Parser routines to walk parsed op tree(s) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "amlcode.h" +#include "acparser.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("pswalk") + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_get_next_walk_op + * + * PARAMETERS: Walk_state - Current state of the walk + * Op - Current Op to be walked + * Ascending_callback - Procedure called when Op is complete + * + * RETURN: Status + * + * DESCRIPTION: Get the next Op in a walk of the parse tree. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_ps_get_next_walk_op ( + ACPI_WALK_STATE *walk_state, + ACPI_PARSE_OBJECT *op, + ACPI_PARSE_UPWARDS ascending_callback) +{ + ACPI_PARSE_OBJECT *next; + ACPI_PARSE_OBJECT *parent; + ACPI_PARSE_OBJECT *grand_parent; + ACPI_STATUS status; + + + /* Check for a argument only if we are descending in the tree */ + + if (walk_state->next_op_info != NEXT_OP_UPWARD) { + /* Look for an argument or child of the current op */ + + next = acpi_ps_get_arg (op, 0); + if (next) { + /* Still going downward in tree (Op is not completed yet) */ + + walk_state->prev_op = op; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + return (AE_OK); + } + + + /* + * No more children, this Op is complete. Save Next and Parent + * in case the Op object gets deleted by the callback routine + */ + + next = op->next; + parent = op->parent; + + status = ascending_callback (walk_state, op); + + /* + * If we are back to the starting point, the walk is complete. + */ + if (op == walk_state->origin) { + /* Reached the point of origin, the walk is complete */ + + walk_state->prev_op = op; + walk_state->next_op = NULL; + + return (status); + } + + /* + * Check for a sibling to the current op. A sibling means + * we are still going "downward" in the tree. + */ + + if (next) { + /* There is a sibling, it will be next */ + + walk_state->prev_op = op; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + /* Continue downward */ + + return (status); + } + + + /* + * Drop into the loop below because we are moving upwards in + * the tree + */ + } + + else { + /* + * We are resuming a walk, and we were (are) going upward in the tree. + * So, we want to drop into the parent loop below. + */ + + parent = op; + } + + + /* + * Look for a sibling of the current Op's parent + * Continue moving up the tree until we find a node that has not been + * visited, or we get back to where we started. + */ + while (parent) { + /* We are moving up the tree, therefore this parent Op is complete */ + + grand_parent = parent->parent; + next = parent->next; + + status = ascending_callback (walk_state, parent); + + /* + * If we are back to the starting point, the walk is complete. + */ + if (parent == walk_state->origin) { + /* Reached the point of origin, the walk is complete */ + + walk_state->prev_op = parent; + walk_state->next_op = NULL; + + return (status); + } + + /* + * If there is a sibling to this parent (it is not the starting point + * Op), then we will visit it. + */ + if (next) { + /* found sibling of parent */ + + walk_state->prev_op = parent; + walk_state->next_op = next; + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + return (status); + } + + /* No siblings, no errors, just move up one more level in the tree */ + + op = parent; + parent = grand_parent; + walk_state->prev_op = op; + } + + + /* Got all the way to the top of the tree, we must be done! */ + /* However, the code should have terminated in the loop above */ + + walk_state->next_op = NULL; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_delete_completed_op + * + * PARAMETERS: State - Walk state + * Op - Completed op + * + * RETURN: AE_OK + * + * DESCRIPTION: Callback function for Acpi_ps_get_next_walk_op(). Used during + * Acpi_ps_delete_parse tree to delete Op objects when all sub-objects + * have been visited (and deleted.) + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_ps_delete_completed_op ( + ACPI_WALK_STATE *state, + ACPI_PARSE_OBJECT *op) +{ + + acpi_ps_free_op (op); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_ps_delete_parse_tree + * + * PARAMETERS: Subtree_root - Root of tree (or subtree) to delete + * + * RETURN: None + * + * DESCRIPTION: Delete a portion of or an entire parse tree. + * + ******************************************************************************/ + +void +acpi_ps_delete_parse_tree ( + ACPI_PARSE_OBJECT *subtree_root) +{ + ACPI_WALK_STATE *walk_state; + ACPI_WALK_LIST walk_list; + + + if (!subtree_root) { + return; + } + + /* Create and initialize a new walk list */ + + walk_list.walk_state = NULL; + walk_list.acquired_mutex_list.prev = NULL; + walk_list.acquired_mutex_list.next = NULL; + + walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, &walk_list); + if (!walk_state) { + return; + } + + walk_state->parser_state = NULL; + walk_state->parse_flags = 0; + walk_state->descending_callback = NULL; + walk_state->ascending_callback = NULL; + + + walk_state->origin = subtree_root; + walk_state->next_op = subtree_root; + + + /* Head downward in the tree */ + + walk_state->next_op_info = NEXT_OP_DOWNWARD; + + /* Visit all nodes in the subtree */ + + while (walk_state->next_op) { + acpi_ps_get_next_walk_op (walk_state, walk_state->next_op, + acpi_ps_delete_completed_op); + } + + /* We are done with this walk */ + + acpi_aml_release_all_mutexes ((ACPI_OPERAND_OBJECT *) &walk_list.acquired_mutex_list); + acpi_ds_delete_walk_state (walk_state); + + return; +} + + diff --git a/drivers/bus/acpi/parser/psxface.c b/drivers/bus/acpi/parser/psxface.c new file mode 100644 index 0000000..4307a79 --- /dev/null +++ b/drivers/bus/acpi/parser/psxface.c @@ -0,0 +1,163 @@ +/****************************************************************************** + * + * Module Name: psxface - Parser external interfaces + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_PARSER + MODULE_NAME ("psxface") + + +/***************************************************************************** + * + * FUNCTION: Acpi_psx_execute + * + * PARAMETERS: Method_node - A method object containing both the AML + * address and length. + * **Params - List of parameters to pass to method, + * terminated by NULL. Params itself may be + * NULL if no parameters are being passed. + * **Return_obj_desc - Return object from execution of the + * method. + * + * RETURN: Status + * + * DESCRIPTION: Execute a control method + * + ****************************************************************************/ + +ACPI_STATUS +acpi_psx_execute ( + ACPI_NAMESPACE_NODE *method_node, + ACPI_OPERAND_OBJECT **params, + ACPI_OPERAND_OBJECT **return_obj_desc) +{ + ACPI_STATUS status; + ACPI_OPERAND_OBJECT *obj_desc; + u32 i; + ACPI_PARSE_OBJECT *op; + + + /* Validate the Node and get the attached object */ + + if (!method_node) { + return (AE_NULL_ENTRY); + } + + obj_desc = acpi_ns_get_attached_object (method_node); + if (!obj_desc) { + return (AE_NULL_OBJECT); + } + + /* Init for new method, wait on concurrency semaphore */ + + status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (params) { + /* + * The caller "owns" the parameters, so give each one an extra + * reference + */ + + for (i = 0; params[i]; i++) { + acpi_cm_add_reference (params[i]); + } + } + + /* + * Perform the first pass parse of the method to enter any + * named objects that it creates into the namespace + */ + + /* Create and init a Root Node */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + status = acpi_ps_parse_aml (op, obj_desc->method.pcode, + obj_desc->method.pcode_length, + ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, + method_node, params, return_obj_desc, + acpi_ds_load1_begin_op, acpi_ds_load1_end_op); + acpi_ps_delete_parse_tree (op); + + /* Create and init a Root Node */ + + op = acpi_ps_alloc_op (AML_SCOPE_OP); + if (!op) { + return (AE_NO_MEMORY); + } + + + /* Init new op with the method name and pointer back to the NS node */ + + acpi_ps_set_name (op, method_node->name); + op->node = method_node; + + /* + * The walk of the parse tree is where we actually execute the method + */ + status = acpi_ps_parse_aml (op, obj_desc->method.pcode, + obj_desc->method.pcode_length, + ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE, + method_node, params, return_obj_desc, + acpi_ds_exec_begin_op, acpi_ds_exec_end_op); + acpi_ps_delete_parse_tree (op); + + if (params) { + /* Take away the extra reference that we gave the parameters above */ + + for (i = 0; params[i]; i++) { + acpi_cm_update_object_reference (params[i], REF_DECREMENT); + } + } + + + /* + * Normal exit is with Status == AE_RETURN_VALUE when a Return_op has been + * executed, or with Status == AE_PENDING at end of AML block (end of + * Method code) + */ + + if (*return_obj_desc) { + status = AE_CTRL_RETURN_VALUE; + } + + + return (status); +} + + diff --git a/drivers/bus/acpi/resource/rsaddr.c b/drivers/bus/acpi/resource/rsaddr.c new file mode 100644 index 0000000..7b5028c --- /dev/null +++ b/drivers/bus/acpi/resource/rsaddr.c @@ -0,0 +1,801 @@ +/******************************************************************************* + * + * Module Name: rsaddr - Acpi_rs_address16_resource + * Acpi_rs_address16_stream + * Acpi_rs_address32_resource + * Acpi_rs_address32_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsaddr") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_address16_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_address16_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16; + u8 temp8; + u32 index; + u32 struct_size = sizeof(ADDRESS16_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + *bytes_consumed = temp16 + 3; + + output_struct->id = address16; + + output_struct->length = struct_size; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 are valid */ + if (temp8 > 2) { + return (AE_AML_ERROR); + } + + output_struct->data.address16.resource_type = temp8 & 0x03; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address16.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address16.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address16.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address16.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (MEMORY_RANGE == output_struct->data.address16.resource_type) { + output_struct->data.address16.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + output_struct->data.address16.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x0F); + } + + else { + if (IO_RANGE == output_struct->data.address16.resource_type) { + output_struct->data.address16.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + } + + else { + /* BUS_NUMBER_RANGE == Address32_data->Resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-7) + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.granularity, + buffer); + + /* + * Get Min_address_range (Bytes 8-9) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 (&output_struct->data.address16.min_address_range, + buffer); + + /* + * Get Max_address_range (Bytes 10-11) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 + (&output_struct->data.address16.max_address_range, + buffer); + + /* + * Get Address_translation_offset (Bytes 12-13) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 + (&output_struct->data.address16.address_translation_offset, + buffer); + + /* + * Get Address_length (Bytes 14-15) + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 + (&output_struct->data.address16.address_length, + buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 2; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > 16) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address16.resource_source_index = + (u32) temp8; + + /* Point to the String */ + + buffer += 1; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + output_struct->data.address16.resource_source[index] = + *buffer; + + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + output_struct->data.address16.resource_source[index] = 0x00; + + output_struct->data.address16.resource_source_string_length = + index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundry. + */ + temp8 = (u8) (index + 1); + struct_size += ROUND_UP_TO_32_bITS (temp8); + output_struct->length = struct_size; + } + else { + output_struct->data.address16.resource_source_index = 0x00; + output_struct->data.address16.resource_source_string_length = 0; + output_struct->data.address16.resource_source[0] = 0x00; + } + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_address16_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_address16_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 *length_field; + u8 temp8; + NATIVE_CHAR *temp_pointer = NULL; + u32 actual_bytes; + + + /* + * The descriptor field is static + */ + *buffer = 0x88; + buffer += 1; + + /* + * Save a pointer to the Length field - to be filled in later + */ + length_field = buffer; + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, Bus_number) + */ + temp8 = (u8) (linked_list->data.address16.resource_type & 0x03); + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address16.producer_consumer & 0x01); + + temp8 |= (linked_list->data.address16.decode & 0x01) << 1; + temp8 |= (linked_list->data.address16.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address16.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if (MEMORY_RANGE == linked_list->data.address16.resource_type) { + temp8 = (u8) + (linked_list->data.address16.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address16.attribute.memory.cache_attribute & + 0x0F) << 1; + } + + else if (IO_RANGE == linked_list->data.address16.resource_type) { + temp8 = (u8) + (linked_list->data.address16.attribute.io.range_attribute & + 0x03); + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.granularity); + buffer += 2; + + /* + * Set the address range minimum + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.min_address_range); + buffer += 2; + + /* + * Set the address range maximum + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.max_address_range); + buffer += 2; + + /* + * Set the address translation offset + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.address_translation_offset); + buffer += 2; + + /* + * Set the address length + */ + MOVE_UNALIGNED16_TO_16 (buffer, + &linked_list->data.address16.address_length); + buffer += 2; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address16.resource_source_string_length) { + temp8 = (u8) linked_list->data.address16.resource_source_index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = (NATIVE_CHAR *) buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.address16.resource_source); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.address16.resource_source) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + actual_bytes = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + *bytes_consumed = actual_bytes; + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + actual_bytes -= 3; + MOVE_UNALIGNED16_TO_16 (length_field, &actual_bytes); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_address32_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_address32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer; + RESOURCE *output_struct; + u16 temp16; + u8 temp8; + u32 struct_size; + u32 index; + + + buffer = byte_stream_buffer; + + output_struct = (RESOURCE *) *output_buffer; + + struct_size = sizeof (ADDRESS32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + *bytes_consumed = temp16 + 3; + + output_struct->id = address32; + + /* + * Get the Resource Type (Byte3) + */ + buffer += 2; + temp8 = *buffer; + + /* Values 0-2 are valid */ + if(temp8 > 2) { + return (AE_AML_ERROR); + } + + output_struct->data.address32.resource_type = temp8 & 0x03; + + /* + * Get the General Flags (Byte4) + */ + buffer += 1; + temp8 = *buffer; + + /* + * Producer / Consumer + */ + output_struct->data.address32.producer_consumer = temp8 & 0x01; + + /* + * Decode + */ + output_struct->data.address32.decode = (temp8 >> 1) & 0x01; + + /* + * Min Address Fixed + */ + output_struct->data.address32.min_address_fixed = (temp8 >> 2) & 0x01; + + /* + * Max Address Fixed + */ + output_struct->data.address32.max_address_fixed = (temp8 >> 3) & 0x01; + + /* + * Get the Type Specific Flags (Byte5) + */ + buffer += 1; + temp8 = *buffer; + + if (MEMORY_RANGE == output_struct->data.address32.resource_type) { + output_struct->data.address32.attribute.memory.read_write_attribute = + (u16) (temp8 & 0x01); + + output_struct->data.address32.attribute.memory.cache_attribute = + (u16) ((temp8 >> 1) & 0x0F); + } + + else { + if (IO_RANGE == output_struct->data.address32.resource_type) { + output_struct->data.address32.attribute.io.range_attribute = + (u16) (temp8 & 0x03); + } + + else { + /* BUS_NUMBER_RANGE == Output_struct->Data.Address32.Resource_type */ + /* Nothing needs to be filled in */ + } + } + + /* + * Get Granularity (Bytes 6-9) + */ + buffer += 1; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.granularity, + buffer); + + /* + * Get Min_address_range (Bytes 10-13) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.min_address_range, + buffer); + + /* + * Get Max_address_range (Bytes 14-17) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.max_address_range, + buffer); + + /* + * Get Address_translation_offset (Bytes 18-21) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 + (&output_struct->data.address32.address_translation_offset, + buffer); + + /* + * Get Address_length (Bytes 22-25) + */ + buffer += 4; + MOVE_UNALIGNED32_TO_32 (&output_struct->data.address32.address_length, + buffer); + + /* + * Resource Source Index (if present) + */ + buffer += 4; + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > 26) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.address32.resource_source_index = (u32)temp8; + + /* Point to the String */ + + buffer += 1; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + output_struct->data.address32.resource_source[index] = *buffer; + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + output_struct->data.address32.resource_source[index] = 0x00; + + output_struct->data.address32.resource_source_string_length = index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundry. + */ + temp8 = (u8) (index + 1); + struct_size += ROUND_UP_TO_32_bITS (temp8); + } + + else { + output_struct->data.address32.resource_source_index = 0x00; + output_struct->data.address32.resource_source_string_length = 0; + output_struct->data.address32.resource_source[0] = 0x00; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_address32_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_address32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer; + u16 *length_field; + u8 temp8; + NATIVE_CHAR *temp_pointer; + + + buffer = *output_buffer; + + /* + * The descriptor field is static + */ + *buffer = 0x87; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + + length_field = (u16 *)buffer; + buffer += 2; + + /* + * Set the Resource Type (Memory, Io, Bus_number) + */ + temp8 = (u8) (linked_list->data.address32.resource_type & 0x03); + + *buffer = temp8; + buffer += 1; + + /* + * Set the general flags + */ + temp8 = (u8) (linked_list->data.address32.producer_consumer & 0x01); + temp8 |= (linked_list->data.address32.decode & 0x01) << 1; + temp8 |= (linked_list->data.address32.min_address_fixed & 0x01) << 2; + temp8 |= (linked_list->data.address32.max_address_fixed & 0x01) << 3; + + *buffer = temp8; + buffer += 1; + + /* + * Set the type specific flags + */ + temp8 = 0; + + if(MEMORY_RANGE == linked_list->data.address32.resource_type) { + temp8 = (u8) + (linked_list->data.address32.attribute.memory.read_write_attribute & + 0x01); + + temp8 |= + (linked_list->data.address32.attribute.memory.cache_attribute & + 0x0F) << 1; + } + + else if (IO_RANGE == linked_list->data.address32.resource_type) { + temp8 = (u8) + (linked_list->data.address32.attribute.io.range_attribute & + 0x03); + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the address space granularity + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.granularity); + buffer += 4; + + /* + * Set the address range minimum + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.min_address_range); + buffer += 4; + + /* + * Set the address range maximum + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.max_address_range); + buffer += 4; + + /* + * Set the address translation offset + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.address_translation_offset); + buffer += 4; + + /* + * Set the address length + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.address32.address_length); + buffer += 4; + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.address32.resource_source_string_length) { + temp8 = (u8) linked_list->data.address32.resource_source_index; + + *buffer = temp8; + buffer += 1; + + temp_pointer = (NATIVE_CHAR *) buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.address32.resource_source); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.address32.resource_source) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rscalc.c b/drivers/bus/acpi/resource/rscalc.c new file mode 100644 index 0000000..0023b6c --- /dev/null +++ b/drivers/bus/acpi/resource/rscalc.c @@ -0,0 +1,868 @@ +/******************************************************************************* + * + * Module Name: rscalc - Acpi_rs_calculate_byte_stream_length + * Acpi_rs_calculate_list_length + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" +#include "amlcode.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rscalc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_calculate_byte_stream_length + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Size_needed - u32 pointer of the size buffer needed + * to properly return the parsed data + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource byte stream and parses it once, calculating + * the size buffer needed to hold the linked list that conveys + * the resource data. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_calculate_byte_stream_length ( + RESOURCE *linked_list, + u32 *size_needed) +{ + u32 byte_stream_size_needed = 0; + u32 segment_size; + EXTENDED_IRQ_RESOURCE *ex_irq = NULL; + u8 done = FALSE; + + + while (!done) { + + /* + * Init the variable that will hold the size to add to the + * total. + */ + segment_size = 0; + + switch (linked_list->id) { + case irq: + /* + * IRQ Resource + */ + /* + * For an IRQ Resource, Byte 3, although optional, will + * always be created - it holds IRQ information. + */ + segment_size = 4; + break; + + case dma: + /* + * DMA Resource + */ + /* + * For this resource the size is static + */ + segment_size = 3; + break; + + case start_dependent_functions: + /* + * Start Dependent Functions Resource + */ + /* + * For a Start_dependent_functions Resource, Byte 1, + * although optional, will always be created. + */ + segment_size = 2; + break; + + case end_dependent_functions: + /* + * End Dependent Functions Resource + */ + /* + * For this resource the size is static + */ + segment_size = 1; + break; + + case io: + /* + * IO Port Resource + */ + /* + * For this resource the size is static + */ + segment_size = 8; + break; + + case fixed_io: + /* + * Fixed IO Port Resource + */ + /* + * For this resource the size is static + */ + segment_size = 4; + break; + + case vendor_specific: + /* + * Vendor Defined Resource + */ + /* + * For a Vendor Specific resource, if the Length is + * between 1 and 7 it will be created as a Small + * Resource data type, otherwise it is a Large + * Resource data type. + */ + if(linked_list->data.vendor_specific.length > 7) { + segment_size = 3; + } + else { + segment_size = 1; + } + segment_size += + linked_list->data.vendor_specific.length; + break; + + case end_tag: + /* + * End Tag + */ + /* + * For this resource the size is static + */ + segment_size = 2; + done = TRUE; + break; + + case memory24: + /* + * 24-Bit Memory Resource + */ + /* + * For this resource the size is static + */ + segment_size = 12; + break; + + case memory32: + /* + * 32-Bit Memory Range Resource + */ + /* + * For this resource the size is static + */ + segment_size = 20; + break; + + case fixed_memory32: + /* + * 32-Bit Fixed Memory Resource + */ + /* + * For this resource the size is static + */ + segment_size = 12; + break; + + case address16: + /* + * 16-Bit Address Resource + */ + /* + * The base size of this byte stream is 16. If a + * Resource Source string is not NULL, add 1 for + * the Index + the length of the null terminated + * string Resource Source + 1 for the null. + */ + segment_size = 16; + + if(NULL != linked_list->data.address16.resource_source) { + segment_size += (1 + + linked_list->data.address16.resource_source_string_length); + } + break; + + case address32: + /* + * 32-Bit Address Resource + */ + /* + * The base size of this byte stream is 26. If a Resource + * Source string is not NULL, add 1 for the Index + the + * length of the null terminated string Resource Source + + * 1 for the null. + */ + segment_size = 26; + + if(NULL != linked_list->data.address16.resource_source) { + segment_size += (1 + + linked_list->data.address16.resource_source_string_length); + } + break; + + case extended_irq: + /* + * Extended IRQ Resource + */ + /* + * The base size of this byte stream is 9. This is for an + * Interrupt table length of 1. For each additional + * interrupt, add 4. + * If a Resource Source string is not NULL, add 1 for the + * Index + the length of the null terminated string + * Resource Source + 1 for the null. + */ + segment_size = 9; + + segment_size += + (linked_list->data.extended_irq.number_of_interrupts - + 1) * 4; + + if(NULL != ex_irq->resource_source) { + segment_size += (1 + + linked_list->data.extended_irq.resource_source_string_length); + } + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_AML_ERROR); + break; + + } /* switch (Linked_list->Id) */ + + /* + * Update the total + */ + byte_stream_size_needed += segment_size; + + /* + * Point to the next object + */ + linked_list = (RESOURCE *) ((NATIVE_UINT) linked_list + + (NATIVE_UINT) linked_list->length); + } + + /* + * This is the data the caller needs + */ + *size_needed = byte_stream_size_needed; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_calculate_list_length + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream + * Byte_stream_buffer_length - Size of Byte_stream_buffer + * Size_needed - u32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource byte stream and parses it once, calculating + * the size buffer needed to hold the linked list that conveys + * the resource data. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_calculate_list_length ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u32 *size_needed) +{ + u32 buffer_size = 0; + u32 bytes_parsed = 0; + u8 number_of_interrupts = 0; + u8 number_of_channels = 0; + u8 resource_type; + u32 structure_size; + u32 bytes_consumed; + u8 *buffer; + u8 temp8; + u16 temp16; + u8 index; + u8 additional_bytes; + + + while (bytes_parsed < byte_stream_buffer_length) { + /* + * Look at the next byte in the stream + */ + resource_type = *byte_stream_buffer; + + /* + * See if this is a small or large resource + */ + if(resource_type & 0x80) { + /* + * Large Resource Type + */ + switch (resource_type) { + case MEMORY_RANGE_24: + /* + * 24-Bit Memory Resource + */ + bytes_consumed = 12; + + structure_size = sizeof (MEMORY24_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + case LARGE_VENDOR_DEFINED: + /* + * Vendor Defined Resource + */ + buffer = byte_stream_buffer; + ++buffer; + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + bytes_consumed = temp16 + 3; + + /* + * Ensure a 32-bit boundary for the structure + */ + temp16 = (u16) ROUND_UP_TO_32_bITS (temp16); + + structure_size = sizeof (VENDOR_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp16 * sizeof (u8)); + break; + + case MEMORY_RANGE_32: + /* + * 32-Bit Memory Range Resource + */ + + bytes_consumed = 20; + + structure_size = sizeof (MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + case FIXED_MEMORY_RANGE_32: + /* + * 32-Bit Fixed Memory Resource + */ + bytes_consumed = 12; + + structure_size = sizeof(FIXED_MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + case DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 23, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (23 < temp16) { + temp8 = (u8) (temp16 - 24); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundary for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (ADDRESS32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp8 * sizeof (u8)); + break; + + case WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + buffer = byte_stream_buffer; + + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 13, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (13 < temp16) { + temp8 = (u8) (temp16 - 14); + } + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundry for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (ADDRESS16_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp8 * sizeof (u8)); + break; + + case EXTENDED_IRQ: + /* + * Extended IRQ + */ + buffer = byte_stream_buffer; + + ++buffer; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + bytes_consumed = temp16 + 3; + + /* + * Point past the length field and the + * Interrupt vector flags to save off the + * Interrupt table length to the Temp8 variable. + */ + buffer += 3; + temp8 = *buffer; + + /* + * To compensate for multiple interrupt numbers, + * Add 4 bytes for each additional interrupts + * greater than 1 + */ + additional_bytes = (u8) ((temp8 - 1) * 4); + + /* + * Resource Source Index and Resource Source are + * optional elements. Check the length of the + * Bytestream. If it is greater than 9, that + * means that an Index exists and is followed by + * a null termininated string. Therefore, set + * the temp variable to the length minus the minimum + * byte stream length plus the byte for the Index to + * determine the size of the NULL terminiated string. + */ + if (9 + additional_bytes < temp16) { + temp8 = (u8) (temp16 - (9 + additional_bytes)); + } + + else { + temp8 = 0; + } + + /* + * Ensure a 32-bit boundry for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + + structure_size = sizeof (EXTENDED_IRQ_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (additional_bytes * sizeof (u8)) + + (temp8 * sizeof (u8)); + + break; + +/* TBD: [Future] 64-bit not currently supported */ +/* + case 0x8A: + break; +*/ + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_AML_ERROR); + break; + } + } + + else { + /* + * Small Resource Type + * Only bits 7:3 are valid + */ + resource_type >>= 3; + + switch (resource_type) { + case IRQ_FORMAT: + /* + * IRQ Resource + */ + /* + * Determine if it there are two or three + * trailing bytes + */ + buffer = byte_stream_buffer; + temp8 = *buffer; + + if(temp8 & 0x01) { + bytes_consumed = 4; + } + + else { + bytes_consumed = 3; + } + + /* + * Point past the descriptor + */ + ++buffer; + + /* + * Look at the number of bits set + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + for (index = 0; index < 16; index++) { + if (temp16 & 0x1) { + ++number_of_interrupts; + } + + temp16 >>= 1; + } + + structure_size = sizeof (IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (number_of_interrupts * sizeof (u32)); + break; + + + case DMA_FORMAT: + + /* + * DMA Resource + */ + buffer = byte_stream_buffer; + + bytes_consumed = 3; + + /* + * Point past the descriptor + */ + ++buffer; + + /* + * Look at the number of bits set + */ + temp8 = *buffer; + + for(index = 0; index < 8; index++) { + if(temp8 & 0x1) { + ++number_of_channels; + } + + temp8 >>= 1; + } + + structure_size = sizeof (DMA_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (number_of_channels * sizeof (u32)); + break; + + + case START_DEPENDENT_TAG: + + /* + * Start Dependent Functions Resource + */ + /* + * Determine if it there are two or three trailing bytes + */ + buffer = byte_stream_buffer; + temp8 = *buffer; + + if(temp8 & 0x01) { + bytes_consumed = 2; + } + else { + bytes_consumed = 1; + } + + + structure_size = + sizeof (START_DEPENDENT_FUNCTIONS_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + + case END_DEPENDENT_TAG: + + /* + * End Dependent Functions Resource + */ + bytes_consumed = 1; + structure_size = RESOURCE_LENGTH; + break; + + + case IO_PORT_DESCRIPTOR: + /* + * IO Port Resource + */ + bytes_consumed = 8; + structure_size = sizeof (IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + + case FIXED_LOCATION_IO_DESCRIPTOR: + + /* + * Fixed IO Port Resource + */ + bytes_consumed = 4; + structure_size = sizeof (FIXED_IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + break; + + + case SMALL_VENDOR_DEFINED: + + /* + * Vendor Specific Resource + */ + buffer = byte_stream_buffer; + + temp8 = *buffer; + temp8 = (u8) (temp8 & 0x7); + bytes_consumed = temp8 + 1; + + /* + * Ensure a 32-bit boundry for the structure + */ + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + structure_size = sizeof (VENDOR_RESOURCE) + + RESOURCE_LENGTH_NO_DATA + + (temp8 * sizeof (u8)); + break; + + + case END_TAG: + + /* + * End Tag + */ + bytes_consumed = 2; + structure_size = RESOURCE_LENGTH; + byte_stream_buffer_length = bytes_parsed; + break; + + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_AML_ERROR); + break; + + } /* switch */ + + } /* if(Resource_type & 0x80) */ + + /* + * Update the return value and counter + */ + buffer_size += structure_size; + bytes_parsed += bytes_consumed; + + /* + * Set the byte stream to point to the next resource + */ + byte_stream_buffer += bytes_consumed; + + } + + /* + * This is the data the caller needs + */ + *size_needed = buffer_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_calculate_pci_routing_table_length + * + * PARAMETERS: Package_object - Pointer to the package object + * Buffer_size_needed - u32 pointer of the size buffer + * needed to properly return the + * parsed data + * + * RETURN: Status AE_OK + * + * DESCRIPTION: Given a package representing a PCI routing table, this + * calculates the size of the corresponding linked list of + * descriptions. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_calculate_pci_routing_table_length ( + ACPI_OPERAND_OBJECT *package_object, + u32 *buffer_size_needed) +{ + u32 number_of_elements; + u32 temp_size_needed = 0; + ACPI_OPERAND_OBJECT **top_object_list; + u32 index; + ACPI_OPERAND_OBJECT *package_element; + ACPI_OPERAND_OBJECT **sub_object_list; + u8 name_found; + u32 table_index; + + + number_of_elements = package_object->package.count; + + /* + * Calculate the size of the return buffer. + * The base size is the number of elements * the sizes of the + * structures. Additional space for the strings is added below. + * The minus one is to subtract the size of the u8 Source[1] + * member because it is added below. + */ + + /* + * But each PRT_ENTRY structure has a pointer to a string and + * the size of that string must be found. + */ + top_object_list = package_object->package.elements; + + for (index = 0; index < number_of_elements; index++) { + /* + * Dereference the sub-package + */ + package_element = *top_object_list; + + /* + * The Sub_object_list will now point to an array of the + * four IRQ elements: Address, Pin, Source and Source_index + */ + sub_object_list = package_element->package.elements; + + /* + * Scan the Irq_table_elements for the Source Name String + */ + name_found = FALSE; + + for (table_index = 0; table_index < 4 && !name_found; table_index++) { + if ((ACPI_TYPE_STRING == (*sub_object_list)->common.type) || + ((INTERNAL_TYPE_REFERENCE == (*sub_object_list)->common.type) && + ((*sub_object_list)->reference.opcode == AML_NAMEPATH_OP))) { + name_found = TRUE; + } + + else { + /* + * Look at the next element + */ + sub_object_list++; + } + } + + temp_size_needed += (sizeof (PCI_ROUTING_TABLE) - 4); + + /* + * Was a String type found? + */ + if (TRUE == name_found) { + if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) { + /* + * The length String.Length field includes the + * terminating NULL + */ + temp_size_needed += (*sub_object_list)->string.length; + } + else { + temp_size_needed += acpi_ns_get_pathname_length ((*sub_object_list)->reference.node); + } + } + + else { + /* + * If no name was found, then this is a NULL, which is + * translated as a u32 zero. + */ + temp_size_needed += sizeof(u32); + } + + + /* Round up the size since each element must be aligned */ + + temp_size_needed = ROUND_UP_TO_64_bITS (temp_size_needed); + + /* + * Point to the next ACPI_OPERAND_OBJECT + */ + top_object_list++; + } + + + /* + * Adding an extra element to the end of the list, essentially a NULL terminator + */ + *buffer_size_needed = temp_size_needed + sizeof (PCI_ROUTING_TABLE); + + return (AE_OK); +} diff --git a/drivers/bus/acpi/resource/rscreate.c b/drivers/bus/acpi/resource/rscreate.c new file mode 100644 index 0000000..0a428f4 --- /dev/null +++ b/drivers/bus/acpi/resource/rscreate.c @@ -0,0 +1,421 @@ +/******************************************************************************* + * + * Module Name: rscreate - Acpi_rs_create_resource_list + * Acpi_rs_create_pci_routing_table + * Acpi_rs_create_byte_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" +#include "amlcode.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rscreate") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_create_resource_list + * + * PARAMETERS: + * Byte_stream_buffer - Pointer to the resource byte stream + * Output_buffer - Pointer to the user's buffer + * Output_buffer_length - Pointer to the size of Output_buffer + * + * RETURN: Status - AE_OK if okay, else a valid ACPI_STATUS code + * If Output_buffer is not large enough, Output_buffer_length + * indicates how large Output_buffer should be, else it + * indicates how may u8 elements of Output_buffer are valid. + * + * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method + * execution and parses the stream to create a linked list + * of device resources. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_create_resource_list ( + ACPI_OPERAND_OBJECT *byte_stream_buffer, + u8 *output_buffer, + u32 *output_buffer_length) +{ + + ACPI_STATUS status; + u8 *byte_stream_start = NULL; + u32 list_size_needed = 0; + u32 byte_stream_buffer_length = 0; + + + /* + * Params already validated, so we don't re-validate here + */ + + byte_stream_buffer_length = byte_stream_buffer->buffer.length; + byte_stream_start = byte_stream_buffer->buffer.pointer; + + /* + * Pass the Byte_stream_buffer into a module that can calculate + * the buffer size needed for the linked list + */ + status = acpi_rs_calculate_list_length (byte_stream_start, + byte_stream_buffer_length, + &list_size_needed); + + /* + * Exit with the error passed back + */ + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * If the linked list will fit into the available buffer + * call to fill in the list + */ + + if (list_size_needed <= *output_buffer_length) { + /* + * Zero out the return buffer before proceeding + */ + MEMSET (output_buffer, 0x00, *output_buffer_length); + + status = acpi_rs_byte_stream_to_list (byte_stream_start, + byte_stream_buffer_length, + &output_buffer); + + /* + * Exit with the error passed back + */ + if (ACPI_FAILURE (status)) { + return (status); + } + + } + + else { + *output_buffer_length = list_size_needed; + return (AE_BUFFER_OVERFLOW); + } + + *output_buffer_length = list_size_needed; + return (AE_OK); + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_create_pci_routing_table + * + * PARAMETERS: + * Package_object - Pointer to an ACPI_OPERAND_OBJECT + * package + * Output_buffer - Pointer to the user's buffer + * Output_buffer_length - Size of Output_buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the Output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and Output_buffer_length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the ACPI_OPERAND_OBJECT package and creates a + * linked list of PCI interrupt descriptions + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_create_pci_routing_table ( + ACPI_OPERAND_OBJECT *package_object, + u8 *output_buffer, + u32 *output_buffer_length) +{ + u8 *buffer = output_buffer; + ACPI_OPERAND_OBJECT **top_object_list = NULL; + ACPI_OPERAND_OBJECT **sub_object_list = NULL; + ACPI_OPERAND_OBJECT *package_element = NULL; + u32 buffer_size_needed = 0; + u32 number_of_elements = 0; + u32 index = 0; + PCI_ROUTING_TABLE *user_prt = NULL; + ACPI_NAMESPACE_NODE *node; + ACPI_STATUS status; + + + /* + * Params already validated, so we don't re-validate here + */ + + status = acpi_rs_calculate_pci_routing_table_length(package_object, + &buffer_size_needed); + + /* + * If the data will fit into the available buffer + * call to fill in the list + */ + if (buffer_size_needed <= *output_buffer_length) { + /* + * Zero out the return buffer before proceeding + */ + MEMSET (output_buffer, 0x00, *output_buffer_length); + + /* + * Loop through the ACPI_INTERNAL_OBJECTS - Each object should + * contain a u32 Address, a u8 Pin, a Name and a u8 + * Source_index. + */ + top_object_list = package_object->package.elements; + number_of_elements = package_object->package.count; + user_prt = (PCI_ROUTING_TABLE *) buffer; + + + buffer = ROUND_PTR_UP_TO_8 (buffer, u8); + + for (index = 0; index < number_of_elements; index++) { + /* + * Point User_prt past this current structure + * + * NOTE: On the first iteration, User_prt->Length will + * be zero because we cleared the return buffer earlier + */ + buffer += user_prt->length; + user_prt = (PCI_ROUTING_TABLE *) buffer; + + + /* + * Fill in the Length field with the information we + * have at this point. + * The minus four is to subtract the size of the + * u8 Source[4] member because it is added below. + */ + user_prt->length = (sizeof (PCI_ROUTING_TABLE) -4); + + /* + * Dereference the sub-package + */ + package_element = *top_object_list; + + /* + * The Sub_object_list will now point to an array of + * the four IRQ elements: Address, Pin, Source and + * Source_index + */ + sub_object_list = package_element->package.elements; + + /* + * 1) First subobject: Dereference the Address + */ + if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) { + user_prt->address = (*sub_object_list)->integer.value; + } + + else { + return (AE_BAD_DATA); + } + + /* + * 2) Second subobject: Dereference the Pin + */ + sub_object_list++; + + if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) { + user_prt->pin = + (u32) (*sub_object_list)->integer.value; + } + + else { + return (AE_BAD_DATA); + } + + /* + * 3) Third subobject: Dereference the Source Name + */ + sub_object_list++; + + switch ((*sub_object_list)->common.type) { + case INTERNAL_TYPE_REFERENCE: + if ((*sub_object_list)->reference.opcode != AML_NAMEPATH_OP) { + return (AE_BAD_DATA); + } + + node = (*sub_object_list)->reference.node; + + /* TBD: use *remaining* length of the buffer! */ + + status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) node, + output_buffer_length, user_prt->source); + + user_prt->length += STRLEN (user_prt->source) + 1; /* include null terminator */ + break; + + + case ACPI_TYPE_STRING: + + STRCPY (user_prt->source, + (*sub_object_list)->string.pointer); + + /* + * Add to the Length field the length of the string + */ + user_prt->length += (*sub_object_list)->string.length; + break; + + + case ACPI_TYPE_INTEGER: + /* + * If this is a number, then the Source Name + * is NULL, since the entire buffer was zeroed + * out, we can leave this alone. + */ + /* + * Add to the Length field the length of + * the u32 NULL + */ + user_prt->length += sizeof (u32); + break; + + + default: + return (AE_BAD_DATA); + break; + } + + /* Now align the current length */ + + user_prt->length = ROUND_UP_TO_64_bITS (user_prt->length); + + /* + * 4) Fourth subobject: Dereference the Source Index + */ + sub_object_list++; + + if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) { + user_prt->source_index = + (u32) (*sub_object_list)->integer.value; + } + + else { + return (AE_BAD_DATA); + } + + /* + * Point to the next ACPI_OPERAND_OBJECT + */ + top_object_list++; + } + + } + + else { + *output_buffer_length = buffer_size_needed; + + return (AE_BUFFER_OVERFLOW); + } + + /* + * Report the amount of buffer used + */ + *output_buffer_length = buffer_size_needed; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_create_byte_stream + * + * PARAMETERS: + * Linked_list_buffer - Pointer to the resource linked list + * Output_buffer - Pointer to the user's buffer + * Output_buffer_length - Size of Output_buffer + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code. + * If the Output_buffer is too small, the error will be + * AE_BUFFER_OVERFLOW and Output_buffer_length will point + * to the size buffer needed. + * + * DESCRIPTION: Takes the linked list of device resources and + * creates a bytestream to be used as input for the + * _SRS control method. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_create_byte_stream ( + RESOURCE *linked_list_buffer, + u8 *output_buffer, + u32 *output_buffer_length) +{ + ACPI_STATUS status; + u32 byte_stream_size_needed = 0; + + + /* + * Params already validated, so we don't re-validate here + * + * Pass the Linked_list_buffer into a module that can calculate + * the buffer size needed for the byte stream. + */ + status = acpi_rs_calculate_byte_stream_length (linked_list_buffer, + &byte_stream_size_needed); + + /* + * Exit with the error passed back + */ + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * If the linked list will fit into the available buffer + * call to fill in the list + */ + + if (byte_stream_size_needed <= *output_buffer_length) { + /* + * Zero out the return buffer before proceeding + */ + MEMSET (output_buffer, 0x00, *output_buffer_length); + + status = acpi_rs_list_to_byte_stream (linked_list_buffer, + byte_stream_size_needed, + &output_buffer); + + /* + * Exit with the error passed back + */ + if (ACPI_FAILURE (status)) { + return (status); + } + + } + else { + *output_buffer_length = byte_stream_size_needed; + return (AE_BUFFER_OVERFLOW); + } + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rsdump.c b/drivers/bus/acpi/resource/rsdump.c new file mode 100644 index 0000000..e463c92 --- /dev/null +++ b/drivers/bus/acpi/resource/rsdump.c @@ -0,0 +1,929 @@ +/******************************************************************************* + * + * Module Name: rsdump - Functions do dump out the resource structures. + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsdump") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_irq + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_irq ( + RESOURCE_DATA *data) +{ + IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) data; + u8 index = 0; + + + acpi_os_printf ("\t_iRQ Resource\n"); + + acpi_os_printf ("\t\t%s Triggered\n", + LEVEL_SENSITIVE == irq_data->edge_level ? + "Level" : "Edge"); + + acpi_os_printf ("\t\t_active %s\n", + ACTIVE_LOW == irq_data->active_high_low ? + "Low" : "High"); + + acpi_os_printf ("\t\t%s\n", + SHARED == irq_data->shared_exclusive ? + "Shared" : "Exclusive"); + + acpi_os_printf ("\t\t%X Interrupts ( ", + irq_data->number_of_interrupts); + + for (index = 0; index < irq_data->number_of_interrupts; index++) { + acpi_os_printf ("%X ", irq_data->interrupts[index]); + } + + acpi_os_printf (")\n"); + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_dma + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_dma ( + RESOURCE_DATA *data) +{ + DMA_RESOURCE *dma_data = (DMA_RESOURCE*) data; + u8 index = 0; + + + acpi_os_printf ("\t_dMA Resource\n"); + + switch (dma_data->type) { + case COMPATIBILITY: + acpi_os_printf ("\t\t_compatibility mode\n"); + break; + + case TYPE_A: + acpi_os_printf ("\t\t_type A\n"); + break; + + case TYPE_B: + acpi_os_printf ("\t\t_type B\n"); + break; + + case TYPE_F: + acpi_os_printf ("\t\t_type F\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid DMA type\n"); + break; + } + + acpi_os_printf ("\t\t%sBus Master\n", + BUS_MASTER == dma_data->bus_master ? + "" : "Not a "); + + switch (dma_data->transfer) { + case TRANSFER_8: + acpi_os_printf ("\t\t8-bit only transfer\n"); + break; + + case TRANSFER_8_16: + acpi_os_printf ("\t\t8 and 16-bit transfer\n"); + break; + + case TRANSFER_16: + acpi_os_printf ("\t\t16 bit only transfer\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid transfer preference\n"); + break; + } + + acpi_os_printf ("\t\t_number of Channels: %X ( ", + dma_data->number_of_channels); + + for (index = 0; index < dma_data->number_of_channels; index++) { + acpi_os_printf ("%X ", dma_data->channels[index]); + } + + acpi_os_printf (")\n"); + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_start_dependent_functions + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_start_dependent_functions ( + RESOURCE_DATA *data) +{ + START_DEPENDENT_FUNCTIONS_RESOURCE *sdf_data = + (START_DEPENDENT_FUNCTIONS_RESOURCE*) data; + + + acpi_os_printf ("\t_start Dependent Functions Resource\n"); + + switch (sdf_data->compatibility_priority) { + case GOOD_CONFIGURATION: + acpi_os_printf ("\t\t_good configuration\n"); + break; + + case ACCEPTABLE_CONFIGURATION: + acpi_os_printf ("\t\t_acceptable configuration\n"); + break; + + case SUB_OPTIMAL_CONFIGURATION: + acpi_os_printf ("\t\t_sub-optimal configuration\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid compatibility priority\n"); + break; + } + + switch(sdf_data->performance_robustness) { + case GOOD_CONFIGURATION: + acpi_os_printf ("\t\t_good configuration\n"); + break; + + case ACCEPTABLE_CONFIGURATION: + acpi_os_printf ("\t\t_acceptable configuration\n"); + break; + + case SUB_OPTIMAL_CONFIGURATION: + acpi_os_printf ("\t\t_sub-optimal configuration\n"); + break; + + default: + acpi_os_printf ("\t\t_invalid performance " + "robustness preference\n"); + break; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_io + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_io ( + RESOURCE_DATA *data) +{ + IO_RESOURCE *io_data = (IO_RESOURCE*) data; + + + acpi_os_printf ("\t_io Resource\n"); + + acpi_os_printf ("\t\t%d bit decode\n", + DECODE_16 == io_data->io_decode ? 16 : 10); + + acpi_os_printf ("\t\t_range minimum base: %08X\n", + io_data->min_base_address); + + acpi_os_printf ("\t\t_range maximum base: %08X\n", + io_data->max_base_address); + + acpi_os_printf ("\t\t_alignment: %08X\n", + io_data->alignment); + + acpi_os_printf ("\t\t_range Length: %08X\n", + io_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_fixed_io + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_fixed_io ( + RESOURCE_DATA *data) +{ + FIXED_IO_RESOURCE *fixed_io_data = (FIXED_IO_RESOURCE*) data; + + + acpi_os_printf ("\t_fixed Io Resource\n"); + acpi_os_printf ("\t\t_range base address: %08X", + fixed_io_data->base_address); + + acpi_os_printf ("\t\t_range length: %08X", + fixed_io_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_vendor_specific + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_vendor_specific ( + RESOURCE_DATA *data) +{ + VENDOR_RESOURCE *vendor_data = (VENDOR_RESOURCE*) data; + u16 index = 0; + + + acpi_os_printf ("\t_vendor Specific Resource\n"); + + acpi_os_printf ("\t\t_length: %08X\n", vendor_data->length); + + for (index = 0; index < vendor_data->length; index++) { + acpi_os_printf ("\t\t_byte %X: %08X\n", + index, vendor_data->reserved[index]); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_memory24 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_memory24 ( + RESOURCE_DATA *data) +{ + MEMORY24_RESOURCE *memory24_data = (MEMORY24_RESOURCE*) data; + + + acpi_os_printf ("\t24-Bit Memory Range Resource\n"); + + acpi_os_printf ("\t\t_read%s\n", + READ_WRITE_MEMORY == + memory24_data->read_write_attribute ? + "/Write" : " only"); + + acpi_os_printf ("\t\t_range minimum base: %08X\n", + memory24_data->min_base_address); + + acpi_os_printf ("\t\t_range maximum base: %08X\n", + memory24_data->max_base_address); + + acpi_os_printf ("\t\t_alignment: %08X\n", + memory24_data->alignment); + + acpi_os_printf ("\t\t_range length: %08X\n", + memory24_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_memory32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_memory32 ( + RESOURCE_DATA *data) +{ + MEMORY32_RESOURCE *memory32_data = (MEMORY32_RESOURCE*) data; + + + acpi_os_printf ("\t32-Bit Memory Range Resource\n"); + + acpi_os_printf ("\t\t_read%s\n", + READ_WRITE_MEMORY == + memory32_data->read_write_attribute ? + "/Write" : " only"); + + acpi_os_printf ("\t\t_range minimum base: %08X\n", + memory32_data->min_base_address); + + acpi_os_printf ("\t\t_range maximum base: %08X\n", + memory32_data->max_base_address); + + acpi_os_printf ("\t\t_alignment: %08X\n", + memory32_data->alignment); + + acpi_os_printf ("\t\t_range length: %08X\n", + memory32_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_fixed_memory32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_fixed_memory32 ( + RESOURCE_DATA *data) +{ + FIXED_MEMORY32_RESOURCE *fixed_memory32_data = (FIXED_MEMORY32_RESOURCE*) data; + + + acpi_os_printf ("\t32-Bit Fixed Location Memory Range Resource\n"); + + acpi_os_printf ("\t\t_read%s\n", + READ_WRITE_MEMORY == + fixed_memory32_data->read_write_attribute ? + "/Write" : " Only"); + + acpi_os_printf ("\t\t_range base address: %08X\n", + fixed_memory32_data->range_base_address); + + acpi_os_printf ("\t\t_range length: %08X\n", + fixed_memory32_data->range_length); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_address16 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address16 ( + RESOURCE_DATA *data) +{ + ADDRESS16_RESOURCE *address16_data = (ADDRESS16_RESOURCE*) data; + + + acpi_os_printf ("\t16-Bit Address Space Resource\n"); + acpi_os_printf ("\t\t_resource Type: "); + + switch (address16_data->resource_type) { + case MEMORY_RANGE: + + acpi_os_printf ("Memory Range\n"); + + switch (address16_data->attribute.memory.cache_attribute) { + case NON_CACHEABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Noncacheable memory\n"); + break; + + case CACHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Cacheable memory\n"); + break; + + case WRITE_COMBINING_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Write-combining memory\n"); + break; + + case PREFETCHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf ("\t\t_type Specific: Read%s\n", + READ_WRITE_MEMORY == + address16_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case IO_RANGE: + + acpi_os_printf ("I/O Range\n"); + + switch (address16_data->attribute.io.range_attribute) { + case NON_ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "ISA Io Addresses\n"); + break; + + case ENTIRE_RANGE: + acpi_os_printf ("\t\t_type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid range attribute\n"); + break; + } + break; + + case BUS_NUMBER_RANGE: + + acpi_os_printf ("Bus Number Range\n"); + break; + + default: + + acpi_os_printf ("Invalid resource type. Exiting.\n"); + return; + } + + acpi_os_printf ("\t\t_resource %s\n", + CONSUMER == address16_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf ("\t\t%s decode\n", + SUB_DECODE == address16_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf ("\t\t_min address is %s fixed\n", + ADDRESS_FIXED == address16_data->min_address_fixed ? + "" : "not"); + + acpi_os_printf ("\t\t_max address is %s fixed\n", + ADDRESS_FIXED == address16_data->max_address_fixed ? + "" : "not"); + + acpi_os_printf ("\t\t_granularity: %08X\n", + address16_data->granularity); + + acpi_os_printf ("\t\t_address range min: %08X\n", + address16_data->min_address_range); + + acpi_os_printf ("\t\t_address range max: %08X\n", + address16_data->max_address_range); + + acpi_os_printf ("\t\t_address translation offset: %08X\n", + address16_data->address_translation_offset); + + acpi_os_printf ("\t\t_address Length: %08X\n", + address16_data->address_length); + + if (0xFF != address16_data->resource_source_index) { + acpi_os_printf ("\t\t_resource Source Index: %X\n", + address16_data->resource_source_index); + acpi_os_printf ("\t\t_resource Source: %s\n", + address16_data->resource_source); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_address32 + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_address32 ( + RESOURCE_DATA *data) +{ + ADDRESS32_RESOURCE *address32_data = (ADDRESS32_RESOURCE*) data; + + + acpi_os_printf ("\t32-Bit Address Space Resource\n"); + + switch (address32_data->resource_type) { + case MEMORY_RANGE: + + acpi_os_printf ("\t\t_resource Type: Memory Range\n"); + + switch (address32_data->attribute.memory.cache_attribute) { + case NON_CACHEABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Noncacheable memory\n"); + break; + + case CACHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Cacheable memory\n"); + break; + + case WRITE_COMBINING_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Write-combining memory\n"); + break; + + case PREFETCHABLE_MEMORY: + acpi_os_printf ("\t\t_type Specific: " + "Prefetchable memory\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid cache attribute\n"); + break; + } + + acpi_os_printf ("\t\t_type Specific: Read%s\n", + READ_WRITE_MEMORY == + address32_data->attribute.memory.read_write_attribute ? + "/Write" : " Only"); + break; + + case IO_RANGE: + + acpi_os_printf ("\t\t_resource Type: Io Range\n"); + + switch (address32_data->attribute.io.range_attribute) { + case NON_ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "Non-ISA Io Addresses\n"); + break; + + case ISA_ONLY_RANGES: + acpi_os_printf ("\t\t_type Specific: " + "ISA Io Addresses\n"); + break; + + case ENTIRE_RANGE: + acpi_os_printf ("\t\t_type Specific: " + "ISA and non-ISA Io Addresses\n"); + break; + + default: + acpi_os_printf ("\t\t_type Specific: " + "Invalid Range attribute"); + break; + } + break; + + case BUS_NUMBER_RANGE: + + acpi_os_printf ("\t\t_resource Type: Bus Number Range\n"); + break; + + default: + + acpi_os_printf ("\t\t_invalid Resource Type..exiting.\n"); + return; + } + + acpi_os_printf ("\t\t_resource %s\n", + CONSUMER == address32_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf ("\t\t%s decode\n", + SUB_DECODE == address32_data->decode ? + "Subtractive" : "Positive"); + + acpi_os_printf ("\t\t_min address is %s fixed\n", + ADDRESS_FIXED == address32_data->min_address_fixed ? + "" : "not "); + + acpi_os_printf ("\t\t_max address is %s fixed\n", + ADDRESS_FIXED == address32_data->max_address_fixed ? + "" : "not "); + + acpi_os_printf ("\t\t_granularity: %08X\n", + address32_data->granularity); + + acpi_os_printf ("\t\t_address range min: %08X\n", + address32_data->min_address_range); + + acpi_os_printf ("\t\t_address range max: %08X\n", + address32_data->max_address_range); + + acpi_os_printf ("\t\t_address translation offset: %08X\n", + address32_data->address_translation_offset); + + acpi_os_printf ("\t\t_address Length: %08X\n", + address32_data->address_length); + + if(0xFF != address32_data->resource_source_index) { + acpi_os_printf ("\t\t_resource Source Index: %X\n", + address32_data->resource_source_index); + acpi_os_printf ("\t\t_resource Source: %s\n", + address32_data->resource_source); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_extended_irq + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Prints out the various members of the Data structure type. + * + ******************************************************************************/ + +void +acpi_rs_dump_extended_irq ( + RESOURCE_DATA *data) +{ + EXTENDED_IRQ_RESOURCE *ext_irq_data = (EXTENDED_IRQ_RESOURCE*) data; + u8 index = 0; + + + acpi_os_printf ("\t_extended IRQ Resource\n"); + + acpi_os_printf ("\t\t_resource %s\n", + CONSUMER == ext_irq_data->producer_consumer ? + "Consumer" : "Producer"); + + acpi_os_printf ("\t\t%s\n", + LEVEL_SENSITIVE == ext_irq_data->edge_level ? + "Level" : "Edge"); + + acpi_os_printf ("\t\t_active %s\n", + ACTIVE_LOW == ext_irq_data->active_high_low ? + "low" : "high"); + + acpi_os_printf ("\t\t%s\n", + SHARED == ext_irq_data->shared_exclusive ? + "Shared" : "Exclusive"); + + acpi_os_printf ("\t\t_interrupts : %X ( ", + ext_irq_data->number_of_interrupts); + + for (index = 0; index < ext_irq_data->number_of_interrupts; index++) { + acpi_os_printf ("%X ", ext_irq_data->interrupts[index]); + } + + acpi_os_printf (")\n"); + + if(0xFF != ext_irq_data->resource_source_index) { + acpi_os_printf ("\t\t_resource Source Index: %X", + ext_irq_data->resource_source_index); + acpi_os_printf ("\t\t_resource Source: %s", + ext_irq_data->resource_source); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_resource_list + * + * PARAMETERS: Data - pointer to the resource structure to dump. + * + * RETURN: + * + * DESCRIPTION: Dispatches the structure to the correct dump routine. + * + ******************************************************************************/ + +void +acpi_rs_dump_resource_list ( + RESOURCE *resource) +{ + u8 count = 0; + u8 done = FALSE; + + + if (acpi_dbg_level & TRACE_RESOURCES && _COMPONENT & acpi_dbg_layer) { + while (!done) { + acpi_os_printf ("\t_resource structure %x.\n", count++); + + switch (resource->id) { + case irq: + acpi_rs_dump_irq (&resource->data); + break; + + case dma: + acpi_rs_dump_dma (&resource->data); + break; + + case start_dependent_functions: + acpi_rs_dump_start_dependent_functions (&resource->data); + break; + + case end_dependent_functions: + acpi_os_printf ("\t_end_dependent_functions Resource\n"); + /* Acpi_rs_dump_end_dependent_functions (Resource->Data);*/ + break; + + case io: + acpi_rs_dump_io (&resource->data); + break; + + case fixed_io: + acpi_rs_dump_fixed_io (&resource->data); + break; + + case vendor_specific: + acpi_rs_dump_vendor_specific (&resource->data); + break; + + case end_tag: + /*Rs_dump_end_tag (Resource->Data);*/ + acpi_os_printf ("\t_end_tag Resource\n"); + done = TRUE; + break; + + case memory24: + acpi_rs_dump_memory24 (&resource->data); + break; + + case memory32: + acpi_rs_dump_memory32 (&resource->data); + break; + + case fixed_memory32: + acpi_rs_dump_fixed_memory32 (&resource->data); + break; + + case address16: + acpi_rs_dump_address16 (&resource->data); + break; + + case address32: + acpi_rs_dump_address32 (&resource->data); + break; + + case extended_irq: + acpi_rs_dump_extended_irq (&resource->data); + break; + + default: + acpi_os_printf ("Invalid resource type\n"); + break; + + } + + resource = (RESOURCE *) ((NATIVE_UINT) resource + + (NATIVE_UINT) resource->length); + } + } + + return; +} + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dump_irq_list + * + * PARAMETERS: Data - pointer to the routing table to dump. + * + * RETURN: + * + * DESCRIPTION: Dispatches the structures to the correct dump routine. + * + ******************************************************************************/ + +void +acpi_rs_dump_irq_list ( + u8 *route_table) +{ + u8 *buffer = route_table; + u8 count = 0; + u8 done = FALSE; + PCI_ROUTING_TABLE *prt_element; + + + if (acpi_dbg_level & TRACE_RESOURCES && _COMPONENT & acpi_dbg_layer) { + prt_element = (PCI_ROUTING_TABLE *) buffer; + + while (!done) { + acpi_os_printf ("\t_pCI IRQ Routing Table structure %X.\n", count++); + + acpi_os_printf ("\t\t_address: %X\n", + prt_element->address); + + acpi_os_printf ("\t\t_pin: %X\n", prt_element->pin); + + acpi_os_printf ("\t\t_source: %s\n", prt_element->source); + + acpi_os_printf ("\t\t_source_index: %X\n", + prt_element->source_index); + + buffer += prt_element->length; + + prt_element = (PCI_ROUTING_TABLE *) buffer; + + if(0 == prt_element->length) { + done = TRUE; + } + } + } + + return; +} + diff --git a/drivers/bus/acpi/resource/rsio.c b/drivers/bus/acpi/resource/rsio.c new file mode 100644 index 0000000..37cf462 --- /dev/null +++ b/drivers/bus/acpi/resource/rsio.c @@ -0,0 +1,528 @@ +/******************************************************************************* + * + * Module Name: rsio - Acpi_rs_io_resource + * Acpi_rs_fixed_io_resource + * Acpi_rs_io_stream + * Acpi_rs_fixed_io_stream + * Acpi_rs_dma_resource + * Acpi_rs_dma_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsio") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_io_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 8; + + output_struct->id = io; + + /* + * Check Decode + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.io.io_decode = temp8 & 0x01; + + /* + * Check Min_base Address + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + output_struct->data.io.min_base_address = temp16; + + /* + * Check Max_base Address + */ + buffer += 2; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + output_struct->data.io.max_base_address = temp16; + + /* + * Check Base alignment + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.io.alignment = temp8; + + /* + * Check Range_length + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.io.range_length = temp8; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_fixed_io_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_io_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (FIXED_IO_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 4; + + output_struct->id = fixed_io; + + /* + * Check Range Base Address + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + output_struct->data.fixed_io.base_address = temp16; + + /* + * Check Range_length + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.fixed_io.range_length = temp8; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_io_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x47; + buffer += 1; + + /* + * Io Information Byte + */ + temp8 = (u8) (linked_list->data.io.io_decode & 0x01); + + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + temp16 = (u16) linked_list->data.io.min_base_address; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Range maximum base address + */ + temp16 = (u16) linked_list->data.io.max_base_address; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the base alignment + */ + temp8 = (u8) linked_list->data.io.alignment; + + *buffer = temp8; + buffer += 1; + + /* + * Set the range length + */ + temp8 = (u8) linked_list->data.io.range_length; + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_fixed_io_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_io_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x4B; + + buffer += 1; + + /* + * Set the Range base address + */ + temp16 = (u16) linked_list->data.fixed_io.base_address; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the range length + */ + temp8 = (u8) linked_list->data.fixed_io.range_length; + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dma_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_dma_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u8 temp8 = 0; + u8 index; + u8 i; + u32 struct_size = sizeof(DMA_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are Constant + */ + *bytes_consumed = 3; + output_struct->id = dma; + + /* + * Point to the 8-bits of Byte 1 + */ + buffer += 1; + temp8 = *buffer; + + /* Decode the IRQ bits */ + + for (i = 0, index = 0; index < 8; index++) { + if ((temp8 >> index) & 0x01) { + output_struct->data.dma.channels[i] = index; + i++; + } + } + output_struct->data.dma.number_of_channels = i; + + + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += (output_struct->data.dma.number_of_channels - 1) * 4; + + /* + * Point to Byte 2 + */ + buffer += 1; + temp8 = *buffer; + + /* + * Check for transfer preference (Bits[1:0]) + */ + output_struct->data.dma.transfer = temp8 & 0x03; + + if (0x03 == output_struct->data.dma.transfer) { + return (AE_BAD_DATA); + } + + /* + * Get bus master preference (Bit[2]) + */ + output_struct->data.dma.bus_master = (temp8 >> 2) & 0x01; + + /* + * Get channel speed support (Bits[6:5]) + */ + output_struct->data.dma.type = (temp8 >> 5) & 0x03; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_dma_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_dma_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + + + /* + * The descriptor field is static + */ + *buffer = 0x2A; + buffer += 1; + temp8 = 0; + + /* + * Loop through all of the Channels and set the mask bits + */ + for (index = 0; + index < linked_list->data.dma.number_of_channels; + index++) { + temp16 = (u16) linked_list->data.dma.channels[index]; + temp8 |= 0x1 << temp16; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the DMA Info + */ + temp8 = (u8) ((linked_list->data.dma.type & 0x03) << 5); + temp8 |= ((linked_list->data.dma.bus_master & 0x01) << 2); + temp8 |= (linked_list->data.dma.transfer & 0x03); + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rsirq.c b/drivers/bus/acpi/resource/rsirq.c new file mode 100644 index 0000000..34335ef --- /dev/null +++ b/drivers/bus/acpi/resource/rsirq.c @@ -0,0 +1,556 @@ +/******************************************************************************* + * + * Module Name: rsirq - Acpi_rs_irq_resource, + * Acpi_rs_irq_stream + * Acpi_rs_extended_irq_resource + * Acpi_rs_extended_irq_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsirq") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_irq_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u8 i; + u32 struct_size = sizeof (IRQ_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are contained in the descriptor + * (Bits:0-1) + */ + temp8 = *buffer; + *bytes_consumed = (temp8 & 0x03) + 1; + output_struct->id = irq; + + /* + * Point to the 16-bits of Bytes 1 and 2 + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + output_struct->data.irq.number_of_interrupts = 0; + + /* Decode the IRQ bits */ + + for (i = 0, index = 0; index < 16; index++) { + if((temp16 >> index) & 0x01) { + output_struct->data.irq.interrupts[i] = index; + i++; + } + } + output_struct->data.irq.number_of_interrupts = i; + + /* + * Calculate the structure size based upon the number of interrupts + */ + struct_size += (output_struct->data.irq.number_of_interrupts - 1) * 4; + + /* + * Point to Byte 3 if it is used + */ + if (4 == *bytes_consumed) { + buffer += 2; + temp8 = *buffer; + + /* + * Check for HE, LL or HL + */ + if (temp8 & 0x01) { + output_struct->data.irq.edge_level = EDGE_SENSITIVE; + output_struct->data.irq.active_high_low = ACTIVE_HIGH; + } + + else { + if (temp8 & 0x8) { + output_struct->data.irq.edge_level = LEVEL_SENSITIVE; + output_struct->data.irq.active_high_low = ACTIVE_LOW; + } + + else { + /* + * Only _LL and _HE polarity/trigger interrupts + * are allowed (ACPI spec v1.0b ection 6.4.2.1), + * so an error will occur if we reach this point + */ + return (AE_BAD_DATA); + } + } + + /* + * Check for sharable + */ + output_struct->data.irq.shared_exclusive = (temp8 >> 3) & 0x01; + } + + else { + /* + * Assume Edge Sensitive, Active High, Non-Sharable + * per ACPI Specification + */ + output_struct->data.irq.edge_level = EDGE_SENSITIVE; + output_struct->data.irq.active_high_low = ACTIVE_HIGH; + output_struct->data.irq.shared_exclusive = EXCLUSIVE; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_irq_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u8 IRQinfo_byte_needed; + + + /* + * The descriptor field is set based upon whether a third byte is + * needed to contain the IRQ Information. + */ + if (EDGE_SENSITIVE == linked_list->data.irq.edge_level && + ACTIVE_HIGH == linked_list->data.irq.active_high_low && + EXCLUSIVE == linked_list->data.irq.shared_exclusive) { + *buffer = 0x22; + IRQinfo_byte_needed = FALSE; + } + else { + *buffer = 0x23; + IRQinfo_byte_needed = TRUE; + } + + buffer += 1; + temp16 = 0; + + /* + * Loop through all of the interrupts and set the mask bits + */ + for(index = 0; + index < linked_list->data.irq.number_of_interrupts; + index++) { + temp8 = (u8) linked_list->data.irq.interrupts[index]; + temp16 |= 0x1 << temp8; + } + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the IRQ Info byte if needed. + */ + if (IRQinfo_byte_needed) { + temp8 = 0; + temp8 = (u8) ((linked_list->data.irq.shared_exclusive & + 0x01) << 4); + + if (LEVEL_SENSITIVE == linked_list->data.irq.edge_level && + ACTIVE_LOW == linked_list->data.irq.active_high_low) { + temp8 |= 0x08; + } + + else { + temp8 |= 0x01; + } + + *buffer = temp8; + buffer += 1; + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_extended_irq_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_extended_irq_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u32 struct_size = sizeof (EXTENDED_IRQ_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + *bytes_consumed = temp16 + 3; + output_struct->id = extended_irq; + + /* + * Point to the Byte3 + */ + buffer += 2; + temp8 = *buffer; + + output_struct->data.extended_irq.producer_consumer = temp8 & 0x01; + + /* + * Check for HE, LL or HL + */ + if(temp8 & 0x02) { + output_struct->data.extended_irq.edge_level = EDGE_SENSITIVE; + output_struct->data.extended_irq.active_high_low = ACTIVE_HIGH; + } + + else { + if(temp8 & 0x4) { + output_struct->data.extended_irq.edge_level = LEVEL_SENSITIVE; + output_struct->data.extended_irq.active_high_low = ACTIVE_LOW; + } + + else { + /* + * Only _LL and _HE polarity/trigger interrupts + * are allowed (ACPI spec v1.0b ection 6.4.2.1), + * so an error will occur if we reach this point + */ + return (AE_BAD_DATA); + } + } + + /* + * Check for sharable + */ + output_struct->data.extended_irq.shared_exclusive = + (temp8 >> 3) & 0x01; + + /* + * Point to Byte4 (IRQ Table length) + */ + buffer += 1; + temp8 = *buffer; + + output_struct->data.extended_irq.number_of_interrupts = temp8; + + /* + * Add any additional structure size to properly calculate + * the next pointer at the end of this function + */ + struct_size += (temp8 - 1) * 4; + + /* + * Point to Byte5 (First IRQ Number) + */ + buffer += 1; + + /* + * Cycle through every IRQ in the table + */ + for (index = 0; index < temp8; index++) { + output_struct->data.extended_irq.interrupts[index] = + (u32)*buffer; + + /* Point to the next IRQ */ + + buffer += 4; + } + + /* + * This will leave us pointing to the Resource Source Index + * If it is present, then save it off and calculate the + * pointer to where the null terminated string goes: + * Each Interrupt takes 32-bits + the 5 bytes of the + * stream that are default. + */ + if (*bytes_consumed > + (u32)(output_struct->data.extended_irq.number_of_interrupts * + 4) + 5) { + /* Dereference the Index */ + + temp8 = *buffer; + output_struct->data.extended_irq.resource_source_index = + (u32)temp8; + + /* Point to the String */ + + buffer += 1; + + /* Copy the string into the buffer */ + + index = 0; + + while (0x00 != *buffer) { + output_struct->data.extended_irq.resource_source[index] = + *buffer; + + buffer += 1; + index += 1; + } + + /* + * Add the terminating null + */ + output_struct->data.extended_irq.resource_source[index] = 0x00; + output_struct->data.extended_irq.resource_source_string_length = + index + 1; + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the string and expand the + * Struct_size to the next 32-bit boundry. + */ + temp8 = (u8) (index + 1); + temp8 = (u8) ROUND_UP_TO_32_bITS (temp8); + } + + else { + output_struct->data.extended_irq.resource_source_index = 0x00; + output_struct->data.extended_irq.resource_source_string_length = 0; + output_struct->data.extended_irq.resource_source[0] = 0x00; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_extended_irq_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_extended_irq_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 *length_field; + u8 temp8 = 0; + u8 index; + NATIVE_CHAR *temp_pointer = NULL; + + + /* + * The descriptor field is static + */ + *buffer = 0x89; + buffer += 1; + + /* + * Set a pointer to the Length field - to be filled in later + */ + + length_field = (u16 *)buffer; + buffer += 2; + + /* + * Set the Interrupt vector flags + */ + temp8 = (u8)(linked_list->data.extended_irq.producer_consumer & 0x01); + + temp8 |= ((linked_list->data.extended_irq.shared_exclusive & 0x01) << 3); + + if (LEVEL_SENSITIVE == linked_list->data.extended_irq.edge_level && + ACTIVE_LOW == linked_list->data.extended_irq.active_high_low) { + temp8 |= 0x04; + } + else { + temp8 |= 0x02; + } + + *buffer = temp8; + buffer += 1; + + /* + * Set the Interrupt table length + */ + temp8 = (u8) linked_list->data.extended_irq.number_of_interrupts; + + *buffer = temp8; + buffer += 1; + + for (index = 0; + index < linked_list->data.extended_irq.number_of_interrupts; + index++) { + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.extended_irq.interrupts[index]); + buffer += 4; + } + + /* + * Resource Source Index and Resource Source are optional + */ + if (0 != linked_list->data.extended_irq.resource_source_string_length) { + *buffer = (u8) linked_list->data.extended_irq.resource_source_index; + buffer += 1; + + temp_pointer = (NATIVE_CHAR *) buffer; + + /* + * Copy the string + */ + STRCPY (temp_pointer, linked_list->data.extended_irq.resource_source); + + /* + * Buffer needs to be set to the length of the sting + one for the + * terminating null + */ + buffer += (STRLEN (linked_list->data.extended_irq.resource_source) + 1); + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + /* + * Set the length field to the number of bytes consumed + * minus the header size (3 bytes) + */ + *length_field = (u16) (*bytes_consumed - 3); + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rslist.c b/drivers/bus/acpi/resource/rslist.c new file mode 100644 index 0000000..576dcc6 --- /dev/null +++ b/drivers/bus/acpi/resource/rslist.c @@ -0,0 +1,500 @@ +/******************************************************************************* + * + * Module Name: rslist - Acpi_rs_byte_stream_to_list + * Acpi_list_to_byte_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rslist") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_byte_stream_to_list + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource byte stream + * Byte_stream_buffer_length - Length of Byte_stream_buffer + * Output_buffer - Pointer to the buffer that will + * contain the output structures + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource byte stream and parses it, creating a + * linked list of resources in the caller's output buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_byte_stream_to_list ( + u8 *byte_stream_buffer, + u32 byte_stream_buffer_length, + u8 **output_buffer) +{ + ACPI_STATUS status; + u32 bytes_parsed = 0; + u8 resource_type = 0; + u32 bytes_consumed = 0; + u8 **buffer = output_buffer; + u32 structure_size = 0; + u8 end_tag_processed = FALSE; + + + while (bytes_parsed < byte_stream_buffer_length && + FALSE == end_tag_processed) { + /* + * Look at the next byte in the stream + */ + resource_type = *byte_stream_buffer; + + /* + * See if this is a small or large resource + */ + if(resource_type & 0x80) { + /* + * Large Resource Type + */ + switch (resource_type) { + case MEMORY_RANGE_24: + /* + * 24-Bit Memory Resource + */ + status = acpi_rs_memory24_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case LARGE_VENDOR_DEFINED: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case MEMORY_RANGE_32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case FIXED_MEMORY_RANGE_32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case DWORD_ADDRESS_SPACE: + /* + * 32-Bit Address Resource + */ + status = acpi_rs_address32_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case WORD_ADDRESS_SPACE: + /* + * 16-Bit Address Resource + */ + status = acpi_rs_address16_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case EXTENDED_IRQ: + /* + * Extended IRQ + */ + status = acpi_rs_extended_irq_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + +/* TBD: [Future] 64-bit not currently supported */ +/* + case 0x8A: + break; +*/ + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_AML_ERROR); + break; + } + } + + else { + /* + * Small Resource Type + * Only bits 7:3 are valid + */ + resource_type >>= 3; + + switch(resource_type) { + case IRQ_FORMAT: + /* + * IRQ Resource + */ + status = acpi_rs_irq_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case DMA_FORMAT: + /* + * DMA Resource + */ + status = acpi_rs_dma_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case START_DEPENDENT_TAG: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_dependent_functions_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case END_DEPENDENT_TAG: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_dependent_functions_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case IO_PORT_DESCRIPTOR: + /* + * IO Port Resource + */ + status = acpi_rs_io_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case FIXED_LOCATION_IO_DESCRIPTOR: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case SMALL_VENDOR_DEFINED: + /* + * Vendor Specific Resource + */ + status = acpi_rs_vendor_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + + break; + + case END_TAG: + /* + * End Tag + */ + status = acpi_rs_end_tag_resource(byte_stream_buffer, + &bytes_consumed, + buffer, + &structure_size); + end_tag_processed = TRUE; + + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_AML_ERROR); + break; + + } /* switch */ + } /* end else */ + + /* + * Update the return value and counter + */ + bytes_parsed += bytes_consumed; + + /* + * Set the byte stream to point to the next resource + */ + byte_stream_buffer += bytes_consumed; + + /* + * Set the Buffer to the next structure + */ + *buffer += structure_size; + + } /* end while */ + + /* + * Check the reason for exiting the while loop + */ + if (TRUE != end_tag_processed) { + return (AE_AML_ERROR); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_list_to_byte_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Byte_steam_size_needed - Calculated size of the byte stream + * needed from calling + * Acpi_rs_calculate_byte_stream_length() + * The size of the Output_buffer is + * guaranteed to be >= + * Byte_stream_size_needed + * Output_buffer - Pointer to the buffer that will + * contain the byte stream + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Takes the resource linked list and parses it, creating a + * byte stream of resources in the caller's output buffer + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_list_to_byte_stream ( + RESOURCE *linked_list, + u32 byte_stream_size_needed, + u8 **output_buffer) +{ + ACPI_STATUS status; + u8 *buffer = *output_buffer; + u32 bytes_consumed = 0; + u8 done = FALSE; + + + while (!done) { + switch (linked_list->id) { + case irq: + /* + * IRQ Resource + */ + status = acpi_rs_irq_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case dma: + /* + * DMA Resource + */ + status = acpi_rs_dma_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case start_dependent_functions: + /* + * Start Dependent Functions Resource + */ + status = acpi_rs_start_dependent_functions_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case end_dependent_functions: + /* + * End Dependent Functions Resource + */ + status = acpi_rs_end_dependent_functions_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case io: + /* + * IO Port Resource + */ + status = acpi_rs_io_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case fixed_io: + /* + * Fixed IO Port Resource + */ + status = acpi_rs_fixed_io_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case vendor_specific: + /* + * Vendor Defined Resource + */ + status = acpi_rs_vendor_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case end_tag: + /* + * End Tag + */ + status = acpi_rs_end_tag_stream (linked_list, + &buffer, + &bytes_consumed); + + /* + * An End Tag indicates the end of the Resource Template + */ + done = TRUE; + break; + + case memory24: + /* + * 24-Bit Memory Resource + */ + status = acpi_rs_memory24_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case memory32: + /* + * 32-Bit Memory Range Resource + */ + status = acpi_rs_memory32_range_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case fixed_memory32: + /* + * 32-Bit Fixed Memory Resource + */ + status = acpi_rs_fixed_memory32_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case address16: + /* + * 16-Bit Address Descriptor Resource + */ + status = acpi_rs_address16_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case address32: + /* + * 32-Bit Address Descriptor Resource + */ + status = acpi_rs_address32_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + case extended_irq: + /* + * Extended IRQ Resource + */ + status = acpi_rs_extended_irq_stream (linked_list, + &buffer, + &bytes_consumed); + break; + + default: + /* + * If we get here, everything is out of sync, + * so exit with an error + */ + return (AE_BAD_DATA); + break; + + } /* switch (Linked_list->Id) */ + + /* + * Set the Buffer to point to the open byte + */ + buffer += bytes_consumed; + + /* + * Point to the next object + */ + linked_list = (RESOURCE *) ((NATIVE_UINT) linked_list + + (NATIVE_UINT) linked_list->length); + } + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rsmemory.c b/drivers/bus/acpi/resource/rsmemory.c new file mode 100644 index 0000000..5534c0f --- /dev/null +++ b/drivers/bus/acpi/resource/rsmemory.c @@ -0,0 +1,557 @@ +/******************************************************************************* + * + * Module Name: rsmem24 - Acpi_rs_memory24_resource + * Acpi_rs_memory24_stream + * Acpi_rs_memory32_range_resource + * Acpi_rs_fixed_memory32_resource + * Acpi_rs_memory32_range_stream + * Acpi_rs_fixed_memory32_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsmemory") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_memory24_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_memory24_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (MEMORY24_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + buffer += 2; + *bytes_consumed = temp16 + 3; + output_struct->id = memory24; + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + output_struct->data.memory24.read_write_attribute = temp8 & 0x01; + + /* + * Get Min_base_address (Bytes 4-5) + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + buffer += 2; + output_struct->data.memory24.min_base_address = temp16; + + /* + * Get Max_base_address (Bytes 6-7) + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + buffer += 2; + output_struct->data.memory24.max_base_address = temp16; + + /* + * Get Alignment (Bytes 8-9) + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + buffer += 2; + output_struct->data.memory24.alignment = temp16; + + /* + * Get Range_length (Bytes 10-11) + */ + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + output_struct->data.memory24.range_length = temp16; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_memory24_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_memory24_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x81; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x09; + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.memory24.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.min_base_address); + buffer += 2; + + /* + * Set the Range maximum base address + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.max_base_address); + buffer += 2; + + /* + * Set the base alignment + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.alignment); + buffer += 2; + + /* + * Set the range length + */ + MOVE_UNALIGNED16_TO_16 (buffer, &linked_list->data.memory24.range_length); + buffer += 2; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_memory32_range_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_memory32_range_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + buffer += 2; + *bytes_consumed = temp16 + 3; + + output_struct->id = memory32; + + /* + * Point to the place in the output buffer where the data portion will + * begin. + * 1. Set the RESOURCE_DATA * Data to point to it's own address, then + * 2. Set the pointer to the next address. + * + * NOTE: Output_struct->Data is cast to u8, otherwise, this addition adds + * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8) + */ + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + + output_struct->data.memory32.read_write_attribute = temp8 & 0x01; + + /* + * Get Min_base_address (Bytes 4-7) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.min_base_address, + buffer); + buffer += 4; + + /* + * Get Max_base_address (Bytes 8-11) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.max_base_address, + buffer); + buffer += 4; + + /* + * Get Alignment (Bytes 12-15) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.alignment, buffer); + buffer += 4; + + /* + * Get Range_length (Bytes 16-19) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.memory32.range_length, buffer); + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_fixed_memory32_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_memory32_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u32 struct_size = sizeof (FIXED_MEMORY32_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Point past the Descriptor to get the number of bytes consumed + */ + buffer += 1; + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + buffer += 2; + *bytes_consumed = temp16 + 3; + + output_struct->id = fixed_memory32; + + /* + * Check Byte 3 the Read/Write bit + */ + temp8 = *buffer; + buffer += 1; + output_struct->data.fixed_memory32.read_write_attribute = temp8 & 0x01; + + /* + * Get Range_base_address (Bytes 4-7) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.fixed_memory32.range_base_address, + buffer); + buffer += 4; + + /* + * Get Range_length (Bytes 8-11) + */ + MOVE_UNALIGNED32_TO_32 (&output_struct->data.fixed_memory32.range_length, + buffer); + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_memory32_range_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_memory32_range_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x85; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x11; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range minimum base address + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.min_base_address); + buffer += 4; + + /* + * Set the Range maximum base address + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.max_base_address); + buffer += 4; + + /* + * Set the base alignment + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.alignment); + buffer += 4; + + /* + * Set the range length + */ + MOVE_UNALIGNED32_TO_32 (buffer, &linked_list->data.memory32.range_length); + buffer += 4; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_fixed_memory32_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_fixed_memory32_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x86; + buffer += 1; + + /* + * The length field is static + */ + temp16 = 0x09; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + + /* + * Set the Information Byte + */ + temp8 = (u8) (linked_list->data.fixed_memory32.read_write_attribute & 0x01); + *buffer = temp8; + buffer += 1; + + /* + * Set the Range base address + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.fixed_memory32.range_base_address); + buffer += 4; + + /* + * Set the range length + */ + MOVE_UNALIGNED32_TO_32 (buffer, + &linked_list->data.fixed_memory32.range_length); + buffer += 4; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rsmisc.c b/drivers/bus/acpi/resource/rsmisc.c new file mode 100644 index 0000000..2697a75 --- /dev/null +++ b/drivers/bus/acpi/resource/rsmisc.c @@ -0,0 +1,606 @@ +/******************************************************************************* + * + * Module Name: rsmisc - Acpi_rs_end_tag_resource + * Acpi_rs_end_tag_stream + * Acpi_rs_vendor_resource + * Acpi_rs_vendor_stream + * Acpi_rs_start_dependent_functions_resource + * Acpi_rs_end_dependent_functions_resource + * Acpi_rs_start_dependent_functions_stream + * Acpi_rs_end_dependent_functions_stream + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsmisc") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_end_tag_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_end_tag_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u32 struct_size = RESOURCE_LENGTH; + + + /* + * The number of bytes consumed is static + */ + *bytes_consumed = 2; + + /* + * Fill out the structure + */ + output_struct->id = end_tag; + + /* + * Set the Length parameter + */ + output_struct->length = 0; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_end_tag_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_end_tag_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 temp8 = 0; + + + /* + * The descriptor field is static + */ + *buffer = 0x79; + buffer += 1; + + /* + * Set the Checksum - zero means that the resource data is treated as if + * the checksum operation succeeded (ACPI Spec 1.0b Section 6.4.2.8) + */ + temp8 = 0; + + *buffer = temp8; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_vendor_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_vendor_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + u32 struct_size = sizeof (VENDOR_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * Dereference the Descriptor to find if this is a large or small item. + */ + temp8 = *buffer; + + if (temp8 & 0x80) { + /* + * Large Item + */ + /* Point to the length field */ + + buffer += 1; + + /* Dereference */ + + MOVE_UNALIGNED16_TO_16 (&temp16, buffer); + + /* Calculate bytes consumed */ + + *bytes_consumed = temp16 + 3; + + /* Point to the first vendor byte */ + + buffer += 2; + } + + else { + /* + * Small Item + */ + + /* Dereference the size */ + + temp16 = (u8)(*buffer & 0x07); + + /* Calculate bytes consumed */ + + *bytes_consumed = temp16 + 1; + + /* Point to the first vendor byte */ + + buffer += 1; + } + + output_struct->id = vendor_specific; + output_struct->data.vendor_specific.length = temp16; + + for (index = 0; index < temp16; index++) { + output_struct->data.vendor_specific.reserved[index] = *buffer; + buffer += 1; + } + + /* + * In order for the Struct_size to fall on a 32-bit boundry, + * calculate the length of the vendor string and expand the + * Struct_size to the next 32-bit boundry. + */ + struct_size += ROUND_UP_TO_32_bITS (temp16); + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_vendor_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_vendor_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u16 temp16 = 0; + u8 temp8 = 0; + u8 index; + + + /* + * Dereference the length to find if this is a large or small item. + */ + + if(linked_list->data.vendor_specific.length > 7) { + /* + * Large Item + */ + /* + * Set the descriptor field and length bytes + */ + *buffer = 0x84; + buffer += 1; + + temp16 = (u16) linked_list->data.vendor_specific.length; + + MOVE_UNALIGNED16_TO_16 (buffer, &temp16); + buffer += 2; + } + + else { + /* + * Small Item + */ + + /* + * Set the descriptor field + */ + temp8 = 0x70; + temp8 |= linked_list->data.vendor_specific.length; + + *buffer = temp8; + buffer += 1; + } + + /* + * Loop through all of the Vendor Specific fields + */ + for (index = 0; index < linked_list->data.vendor_specific.length; index++) { + temp8 = linked_list->data.vendor_specific.reserved[index]; + + *buffer = temp8; + buffer += 1; + } + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_start_dependent_functions_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_start_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + u8 *buffer = byte_stream_buffer; + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u8 temp8 = 0; + u32 struct_size = + sizeof(START_DEPENDENT_FUNCTIONS_RESOURCE) + + RESOURCE_LENGTH_NO_DATA; + + + /* + * The number of bytes consumed are contained in the descriptor (Bits:0-1) + */ + temp8 = *buffer; + + *bytes_consumed = (temp8 & 0x01) + 1; + + output_struct->id = start_dependent_functions; + + /* + * Point to Byte 1 if it is used + */ + if (2 == *bytes_consumed) { + buffer += 1; + temp8 = *buffer; + + /* + * Check Compatibility priority + */ + output_struct->data.start_dependent_functions.compatibility_priority = + temp8 & 0x03; + + if (3 == output_struct->data.start_dependent_functions.compatibility_priority) { + return (AE_AML_ERROR); + } + + /* + * Check Performance/Robustness preference + */ + output_struct->data.start_dependent_functions.performance_robustness = + (temp8 >> 2) & 0x03; + + if (3 == output_struct->data.start_dependent_functions.performance_robustness) { + return (AE_AML_ERROR); + } + } + + else { + output_struct->data.start_dependent_functions.compatibility_priority = + ACCEPTABLE_CONFIGURATION; + + output_struct->data.start_dependent_functions.performance_robustness = + ACCEPTABLE_CONFIGURATION; + } + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_end_dependent_functions_resource + * + * PARAMETERS: Byte_stream_buffer - Pointer to the resource input byte + * stream + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes consumed from + * the Byte_stream_buffer + * Output_buffer - Pointer to the user's return buffer + * Structure_size - u32 pointer that is filled with + * the number of bytes in the filled + * in structure + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the resource byte stream and fill out the appropriate + * structure pointed to by the Output_buffer. Return the + * number of bytes consumed from the byte stream. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_end_dependent_functions_resource ( + u8 *byte_stream_buffer, + u32 *bytes_consumed, + u8 **output_buffer, + u32 *structure_size) +{ + RESOURCE *output_struct = (RESOURCE *) * output_buffer; + u32 struct_size = RESOURCE_LENGTH; + + + /* + * The number of bytes consumed is static + */ + *bytes_consumed = 1; + + /* + * Fill out the structure + */ + output_struct->id = end_dependent_functions; + + /* + * Set the Length parameter + */ + output_struct->length = struct_size; + + /* + * Return the final size of the structure + */ + *structure_size = struct_size; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_start_dependent_functions_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_start_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed) +{ + u8 *buffer = *output_buffer; + u8 temp8 = 0; + + + /* + * The descriptor field is set based upon whether a byte is needed + * to contain Priority data. + */ + if (ACCEPTABLE_CONFIGURATION == + linked_list->data.start_dependent_functions.compatibility_priority && + ACCEPTABLE_CONFIGURATION == + linked_list->data.start_dependent_functions.performance_robustness) { + *buffer = 0x30; + } + else { + *buffer = 0x31; + buffer += 1; + + /* + * Set the Priority Byte Definition + */ + temp8 = 0; + temp8 = (u8) + ((linked_list->data.start_dependent_functions.performance_robustness & + 0x03) << 2); + temp8 |= + (linked_list->data.start_dependent_functions.compatibility_priority & + 0x03); + + *buffer = temp8; + } + + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_end_dependent_functions_stream + * + * PARAMETERS: Linked_list - Pointer to the resource linked list + * Output_buffer - Pointer to the user's return buffer + * Bytes_consumed - u32 pointer that is filled with + * the number of bytes of the + * Output_buffer used + * + * RETURN: Status AE_OK if okay, else a valid ACPI_STATUS code + * + * DESCRIPTION: Take the linked list resource structure and fills in the + * the appropriate bytes in a byte stream + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_end_dependent_functions_stream ( + RESOURCE *linked_list, + u8 **output_buffer, + u32 *bytes_consumed + ) +{ + u8 *buffer = *output_buffer; + + + /* + * The descriptor field is static + */ + *buffer = 0x38; + buffer += 1; + + /* + * Return the number of bytes consumed in this operation + */ + *bytes_consumed = (u32) ((NATIVE_UINT) buffer - + (NATIVE_UINT) *output_buffer); + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/resource/rsutils.c b/drivers/bus/acpi/resource/rsutils.c new file mode 100644 index 0000000..e7cef04 --- /dev/null +++ b/drivers/bus/acpi/resource/rsutils.c @@ -0,0 +1,387 @@ +/******************************************************************************* + * + * Module Name: rsutils - Utilities for the resource manager + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acresrc.h" + + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_get_prt_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * Ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the _PRT value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_get_prt_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_OPERAND_OBJECT *ret_obj; + ACPI_STATUS status; + u32 buffer_space_needed; + + + /* already validated params, so we won't repeat here */ + + buffer_space_needed = ret_buffer->length; + + /* + * Execute the method, no parameters + */ + status = acpi_ns_evaluate_relative (handle, "_PRT", NULL, &ret_obj); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!ret_obj) { + /* Return object is required */ + + return (AE_TYPE); + } + + + /* + * The return object will be a package, so check the + * parameters. If the return object is not a package, + * then the underlying AML code is corrupt or improperly + * written. + */ + if (ACPI_TYPE_PACKAGE != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_pci_routing_table (ret_obj, + ret_buffer->pointer, + &buffer_space_needed); + + /* + * Tell the user how much of the buffer we have used or is needed + * and return the final status. + */ + ret_buffer->length = buffer_space_needed; + + + /* On exit, we must delete the object returned by evaluate_object */ + +cleanup: + + acpi_cm_remove_reference (ret_obj); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_get_crs_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * Ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the _CRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_get_crs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_OPERAND_OBJECT *ret_obj; + ACPI_STATUS status; + u32 buffer_space_needed = ret_buffer->length; + + + /* already validated params, so we won't repeat here */ + + /* + * Execute the method, no parameters + */ + status = acpi_ns_evaluate_relative (handle, "_CRS", NULL, &ret_obj); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!ret_obj) { + /* Return object is required */ + + return (AE_TYPE); + } + + /* + * The return object will be a buffer, but check the + * parameters. If the return object is not a buffer, + * then the underlying AML code is corrupt or improperly + * written. + */ + if (ACPI_TYPE_BUFFER != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list (ret_obj, + ret_buffer->pointer, + &buffer_space_needed); + + + + /* + * Tell the user how much of the buffer we have used or is needed + * and return the final status. + */ + ret_buffer->length = buffer_space_needed; + + + /* On exit, we must delete the object returned by evaluate_object */ + +cleanup: + + acpi_cm_remove_reference (ret_obj); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_get_prs_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * Ret_buffer - a pointer to a buffer structure for the + * results + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the _PRS value of an object + * contained in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_get_prs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_OPERAND_OBJECT *ret_obj; + ACPI_STATUS status; + u32 buffer_space_needed = ret_buffer->length; + + + /* already validated params, so we won't repeat here */ + + /* + * Execute the method, no parameters + */ + status = acpi_ns_evaluate_relative (handle, "_PRS", NULL, &ret_obj); + if (ACPI_FAILURE (status)) { + return (status); + } + + if (!ret_obj) { + /* Return object is required */ + + return (AE_TYPE); + } + + /* + * The return object will be a buffer, but check the + * parameters. If the return object is not a buffer, + * then the underlying AML code is corrupt or improperly + * written.. + */ + if (ACPI_TYPE_BUFFER != ret_obj->common.type) { + status = AE_AML_OPERAND_TYPE; + goto cleanup; + } + + /* + * Make the call to create a resource linked list from the + * byte stream buffer that comes back from the _CRS method + * execution. + */ + status = acpi_rs_create_resource_list (ret_obj, + ret_buffer->pointer, + &buffer_space_needed); + + /* + * Tell the user how much of the buffer we have used or is needed + * and return the final status. + */ + ret_buffer->length = buffer_space_needed; + + + /* On exit, we must delete the object returned by evaluate_object */ + +cleanup: + + acpi_cm_remove_reference (ret_obj); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_rs_set_srs_method_data + * + * PARAMETERS: Handle - a handle to the containing object + * In_buffer - a pointer to a buffer structure of the + * parameter + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to set the _SRS of an object contained + * in an object specified by the handle passed in + * + * If the function fails an appropriate status will be returned + * and the contents of the callers buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_rs_set_srs_method_data ( + ACPI_HANDLE handle, + ACPI_BUFFER *in_buffer) +{ + ACPI_OPERAND_OBJECT *params[2]; + ACPI_OPERAND_OBJECT param_obj; + ACPI_STATUS status; + u8 *byte_stream = NULL; + u32 buffer_size_needed = 0; + + + /* already validated params, so we won't repeat here */ + + /* + * The In_buffer parameter will point to a linked list of + * resource parameters. It needs to be formatted into a + * byte stream to be sent in as an input parameter. + */ + buffer_size_needed = 0; + + /* + * First call is to get the buffer size needed + */ + status = acpi_rs_create_byte_stream (in_buffer->pointer, + byte_stream, + &buffer_size_needed); + /* + * We expect a return of AE_BUFFER_OVERFLOW + * if not, exit with the error + */ + if (AE_BUFFER_OVERFLOW != status) { + return (status); + } + + /* + * Allocate the buffer needed + */ + byte_stream = acpi_cm_callocate(buffer_size_needed); + if (NULL == byte_stream) { + return (AE_NO_MEMORY); + } + + /* + * Now call to convert the linked list into a byte stream + */ + status = acpi_rs_create_byte_stream (in_buffer->pointer, + byte_stream, + &buffer_size_needed); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + /* + * Init the param object + */ + acpi_cm_init_static_object (¶m_obj); + + /* + * Method requires one parameter. Set it up + */ + params [0] = ¶m_obj; + params [1] = NULL; + + /* + * Set up the parameter object + */ + param_obj.common.type = ACPI_TYPE_BUFFER; + param_obj.buffer.length = buffer_size_needed; + param_obj.buffer.pointer = byte_stream; + + /* + * Execute the method, no return value + */ + status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL); + + /* + * Clean up and return the status from Acpi_ns_evaluate_relative + */ + +cleanup: + + acpi_cm_free (byte_stream); + return (status); +} + diff --git a/drivers/bus/acpi/resource/rsxface.c b/drivers/bus/acpi/resource/rsxface.c new file mode 100644 index 0000000..c968842 --- /dev/null +++ b/drivers/bus/acpi/resource/rsxface.c @@ -0,0 +1,221 @@ +/******************************************************************************* + * + * Module Name: rsxface - Public interfaces to the ACPI subsystem + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + MODULE_NAME ("rsxface") + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_irq_routing_table + * + * PARAMETERS: Device_handle - a handle to the Bus device we are querying + * Ret_buffer - a pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the IRQ routing table for a + * specific bus. The caller must first acquire a handle for the + * desired bus. The routine table is placed in the buffer pointed + * to by the Ret_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of Ret_buffer is undefined. + * + * This function attempts to execute the _PRT method contained in + * the object indicated by the passed Device_handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_irq_routing_table ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. + */ + if ((!device_handle) || + (!ret_buffer) || + ((!ret_buffer->pointer) && (ret_buffer->length))) { + return (AE_BAD_PARAMETER); + } + + status = acpi_rs_get_prt_method_data (device_handle, ret_buffer); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_current_resources + * + * PARAMETERS: Device_handle - a handle to the device object for the + * device we are querying + * Ret_buffer - a pointer to a buffer to receive the + * current resources for the device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is placed in the buffer + * pointed to by the Ret_buffer variable parameter. + * + * If the function fails an appropriate status will be returned + * and the value of Ret_buffer is undefined. + * + * This function attempts to execute the _CRS method contained in + * the object indicated by the passed Device_handle. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_current_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. + */ + if ((!device_handle) || + (!ret_buffer) || + ((ret_buffer->length) && (!ret_buffer->pointer))) { + return (AE_BAD_PARAMETER); + } + + status = acpi_rs_get_crs_method_data (device_handle, ret_buffer); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_possible_resources + * + * PARAMETERS: Device_handle - a handle to the device object for the + * device we are querying + * Ret_buffer - a pointer to a buffer to receive the + * resources for the device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get a list of the possible resources + * for a specific device. The caller must first acquire a handle + * for the desired device. The resource data is placed in the + * buffer pointed to by the Ret_buffer variable. + * + * If the function fails an appropriate status will be returned + * and the value of Ret_buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_possible_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + /* + * Must have a valid handle and buffer, So we have to have a handle + * and a return buffer structure, and if there is a non-zero buffer length + * we also need a valid pointer in the buffer. If it's a zero buffer length, + * we'll be returning the needed buffer size, so keep going. + */ + if ((!device_handle) || + (!ret_buffer) || + ((ret_buffer->length) && (!ret_buffer->pointer))) { + return (AE_BAD_PARAMETER); + } + + status = acpi_rs_get_prs_method_data (device_handle, ret_buffer); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_set_current_resources + * + * PARAMETERS: Device_handle - a handle to the device object for the + * device we are changing the resources of + * In_buffer - a pointer to a buffer containing the + * resources to be set for the device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to set the current resources for a + * specific device. The caller must first acquire a handle for + * the desired device. The resource data is passed to the routine + * the buffer pointed to by the In_buffer variable. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_set_current_resources ( + ACPI_HANDLE device_handle, + ACPI_BUFFER *in_buffer) +{ + ACPI_STATUS status; + + + /* + * Must have a valid handle and buffer + */ + if ((!device_handle) || + (!in_buffer) || + (!in_buffer->pointer) || + (!in_buffer->length)) { + return (AE_BAD_PARAMETER); + } + + status = acpi_rs_set_srs_method_data (device_handle, in_buffer); + + return (status); +} diff --git a/drivers/bus/acpi/tables/.cvsignore b/drivers/bus/acpi/tables/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/tables/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/tables/tbconvrt.c b/drivers/bus/acpi/tables/tbconvrt.c new file mode 100644 index 0000000..b890698 --- /dev/null +++ b/drivers/bus/acpi/tables/tbconvrt.c @@ -0,0 +1,551 @@ +/****************************************************************************** + * + * Module Name: tbconvrt - ACPI Table conversion utilities + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "actables.h" +#include "actbl.h" + + +#define _COMPONENT ACPI_TABLES + MODULE_NAME ("tbconvrt") + + +/* + * Build a GAS structure from earlier ACPI table entries (V1.0 and 0.71 extensions) + * + * 1) Address space + * 2) Length in bytes -- convert to length in bits + * 3) Bit offset is zero + * 4) Reserved field is zero + * 5) Expand address to 64 bits + */ +#define ASL_BUILD_GAS_FROM_ENTRY(a,b,c,d) {a.address_space_id = (u8) d;\ + a.register_bit_width = (u8) MUL_8 (b);\ + a.register_bit_offset = 0;\ + a.reserved = 0;\ + ACPI_STORE_ADDRESS (a.address,c);} + + +/* ACPI V1.0 entries -- address space is always I/O */ + +#define ASL_BUILD_GAS_FROM_V1_ENTRY(a,b,c) ASL_BUILD_GAS_FROM_ENTRY(a,b,c,ADDRESS_SPACE_SYSTEM_IO) + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_convert_to_xsdt + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_convert_to_xsdt ( + ACPI_TABLE_DESC *table_info, + u32 *number_of_tables) { + u32 table_size; + u32 pointer_size; + u32 i; + XSDT_DESCRIPTOR *new_table; + + +#ifndef _IA64 + + if (acpi_gbl_RSDP->revision < 2) { + pointer_size = sizeof (u32); + } + + else +#endif + { + pointer_size = sizeof (UINT64); + } + + /* + * Determine the number of tables pointed to by the RSDT/XSDT. + * This is defined by the ACPI Specification to be the number of + * pointers contained within the RSDT/XSDT. The size of the pointers + * is architecture-dependent. + */ + + table_size = table_info->pointer->length; + *number_of_tables = (table_size - + sizeof (ACPI_TABLE_HEADER)) / pointer_size; + + /* Compute size of the converted XSDT */ + + table_size = (*number_of_tables * sizeof (UINT64)) + sizeof (ACPI_TABLE_HEADER); + + + /* Allocate an XSDT */ + + new_table = acpi_cm_callocate (table_size); + if (!new_table) { + return (AE_NO_MEMORY); + } + + /* Copy the header and set the length */ + + MEMCPY (new_table, table_info->pointer, sizeof (ACPI_TABLE_HEADER)); + new_table->header.length = table_size; + + /* Copy the table pointers */ + + for (i = 0; i < *number_of_tables; i++) { + if (acpi_gbl_RSDP->revision < 2) { +#ifdef _IA64 + new_table->table_offset_entry[i] = + ((RSDT_DESCRIPTOR_REV071 *) table_info->pointer)->table_offset_entry[i]; +#else + ACPI_STORE_ADDRESS (new_table->table_offset_entry[i], + ((RSDT_DESCRIPTOR_REV1 *) table_info->pointer)->table_offset_entry[i]); +#endif + } + else { + new_table->table_offset_entry[i] = + ((XSDT_DESCRIPTOR *) table_info->pointer)->table_offset_entry[i]; + } + } + + + /* Delete the original table (either mapped or in a buffer) */ + + acpi_tb_delete_single_table (table_info); + + + /* Point the table descriptor to the new table */ + + table_info->pointer = (ACPI_TABLE_HEADER *) new_table; + table_info->base_pointer = (ACPI_TABLE_HEADER *) new_table; + table_info->length = table_size; + table_info->allocation = ACPI_MEM_ALLOCATED; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_convert_table_fadt + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * Converts BIOS supplied 1.0 and 0.71 ACPI FADT to an intermediate + * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply + * copied to the intermediate FADT. The ACPI CA software uses this + * intermediate FADT. Thus a significant amount of special #ifdef + * type codeing is saved. This intermediate FADT will need to be + * freed at some point. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_convert_table_fadt (void) +{ + +#ifdef _IA64 + FADT_DESCRIPTOR_REV071 *FADT71; + u8 pm1_address_space; + u8 pm2_address_space; + u8 pm_timer_address_space; + u8 gpe0address_space; + u8 gpe1_address_space; +#else + FADT_DESCRIPTOR_REV1 *FADT1; +#endif + + FADT_DESCRIPTOR_REV2 *FADT2; + ACPI_TABLE_DESC *table_desc; + + + /* Acpi_gbl_FADT is valid */ + /* Allocate and zero the 2.0 buffer */ + + FADT2 = acpi_cm_callocate (sizeof (FADT_DESCRIPTOR_REV2)); + if (FADT2 == NULL) { + return (AE_NO_MEMORY); + } + + + /* The ACPI FADT revision number is FADT2_REVISION_ID=3 */ + /* So, if the current table revision is less than 3 it is type 1.0 or 0.71 */ + + if (acpi_gbl_FADT->header.revision >= FADT2_REVISION_ID) { + /* We have an ACPI 2.0 FADT but we must copy it to our local buffer */ + + *FADT2 = *((FADT_DESCRIPTOR_REV2*) acpi_gbl_FADT); + + } + + else { + +#ifdef _IA64 + /* + * For the 64-bit case only, a revision ID less than V2.0 means the + * tables are the 0.71 extensions + */ + + /* The BIOS stored FADT should agree with Revision 0.71 */ + + FADT71 = (FADT_DESCRIPTOR_REV071 *) acpi_gbl_FADT; + + /* Copy the table header*/ + + FADT2->header = FADT71->header; + + /* Copy the common fields */ + + FADT2->sci_int = FADT71->sci_int; + FADT2->acpi_enable = FADT71->acpi_enable; + FADT2->acpi_disable = FADT71->acpi_disable; + FADT2->S4_bios_req = FADT71->S4_bios_req; + FADT2->plvl2_lat = FADT71->plvl2_lat; + FADT2->plvl3_lat = FADT71->plvl3_lat; + FADT2->day_alrm = FADT71->day_alrm; + FADT2->mon_alrm = FADT71->mon_alrm; + FADT2->century = FADT71->century; + FADT2->gpe1_base = FADT71->gpe1_base; + + /* + * We still use the block length registers even though + * the GAS structure should obsolete them. This is because + * these registers are byte lengths versus the GAS which + * contains a bit width + */ + FADT2->pm1_evt_len = FADT71->pm1_evt_len; + FADT2->pm1_cnt_len = FADT71->pm1_cnt_len; + FADT2->pm2_cnt_len = FADT71->pm2_cnt_len; + FADT2->pm_tm_len = FADT71->pm_tm_len; + FADT2->gpe0blk_len = FADT71->gpe0blk_len; + FADT2->gpe1_blk_len = FADT71->gpe1_blk_len; + FADT2->gpe1_base = FADT71->gpe1_base; + + /* Copy the existing 0.71 flags to 2.0. The other bits are zero.*/ + + FADT2->wb_invd = FADT71->flush_cash; + FADT2->proc_c1 = FADT71->proc_c1; + FADT2->plvl2_up = FADT71->plvl2_up; + FADT2->pwr_button = FADT71->pwr_button; + FADT2->sleep_button = FADT71->sleep_button; + FADT2->fixed_rTC = FADT71->fixed_rTC; + FADT2->rtcs4 = FADT71->rtcs4; + FADT2->tmr_val_ext = FADT71->tmr_val_ext; + FADT2->dock_cap = FADT71->dock_cap; + + + /* We should not use these next two addresses */ + /* Since our buffer is pre-zeroed nothing to do for */ + /* the next three data items in the structure */ + /* FADT2->Firmware_ctrl = 0; */ + /* FADT2->Dsdt = 0; */ + + /* System Interrupt Model isn't used in ACPI 2.0*/ + /* FADT2->Reserved1 = 0; */ + + /* This field is set by the OEM to convey the preferred */ + /* power management profile to OSPM. It doesn't have any*/ + /* 0.71 equivalence. Since we don't know what kind of */ + /* 64-bit system this is, we will pick unspecified. */ + + FADT2->prefer_PM_profile = PM_UNSPECIFIED; + + + /* Port address of SMI command port */ + /* We shouldn't use this port because IA64 doesn't */ + /* have or use SMI. It has PMI. */ + + FADT2->smi_cmd = (u32)(FADT71->smi_cmd & 0xFFFFFFFF); + + + /* processor performance state control*/ + /* The value OSPM writes to the SMI_CMD register to assume */ + /* processor performance state control responsibility. */ + /* There isn't any equivalence in 0.71 */ + /* Again this should be meaningless for IA64 */ + /* FADT2->Pstate_cnt = 0; */ + + /* The 32-bit Power management and GPE registers are */ + /* not valid in IA-64 and we are not going to use them */ + /* so leaving them pre-zeroed. */ + + /* Support for the _CST object and C States change notification.*/ + /* This data item hasn't any 0.71 equivalence so leaving it zero.*/ + /* FADT2->Cst_cnt = 0; */ + + /* number of flush strides that need to be read */ + /* No 0.71 equivalence. Leave pre-zeroed. */ + /* FADT2->Flush_size = 0; */ + + /* Processor's memory cache line width, in bytes */ + /* No 0.71 equivalence. Leave pre-zeroed. */ + /* FADT2->Flush_stride = 0; */ + + /* Processor's duty cycle index in processor's P_CNT reg*/ + /* No 0.71 equivalence. Leave pre-zeroed. */ + /* FADT2->Duty_offset = 0; */ + + /* Processor's duty cycle value bit width in P_CNT register.*/ + /* No 0.71 equivalence. Leave pre-zeroed. */ + /* FADT2->Duty_width = 0; */ + + + /* Since there isn't any equivalence in 0.71 */ + /* and since Big_sur had to support legacy */ + + FADT2->iapc_boot_arch = BAF_LEGACY_DEVICES; + + /* Copy to ACPI 2.0 64-BIT Extended Addresses */ + + FADT2->Xfirmware_ctrl = FADT71->firmware_ctrl; + FADT2->Xdsdt = FADT71->dsdt; + + + /* Extract the address space IDs */ + + pm1_address_space = (u8)((FADT71->address_space & PM1_BLK_ADDRESS_SPACE) >> 1); + pm2_address_space = (u8)((FADT71->address_space & PM2_CNT_BLK_ADDRESS_SPACE) >> 2); + pm_timer_address_space = (u8)((FADT71->address_space & PM_TMR_BLK_ADDRESS_SPACE) >> 3); + gpe0address_space = (u8)((FADT71->address_space & GPE0_BLK_ADDRESS_SPACE) >> 4); + gpe1_address_space = (u8)((FADT71->address_space & GPE1_BLK_ADDRESS_SPACE) >> 5); + + /* + * Convert the 0.71 (non-GAS style) Block addresses to V2.0 GAS structures, + * in this order: + * + * PM 1_a Events + * PM 1_b Events + * PM 1_a Control + * PM 1_b Control + * PM 2 Control + * PM Timer Control + * GPE Block 0 + * GPE Block 1 + */ + + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1a_evt_blk, FADT71->pm1_evt_len, FADT71->pm1a_evt_blk, pm1_address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1b_evt_blk, FADT71->pm1_evt_len, FADT71->pm1b_evt_blk, pm1_address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1a_cnt_blk, FADT71->pm1_cnt_len, FADT71->pm1a_cnt_blk, pm1_address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm1b_cnt_blk, FADT71->pm1_cnt_len, FADT71->pm1b_cnt_blk, pm1_address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm2_cnt_blk, FADT71->pm2_cnt_len, FADT71->pm2_cnt_blk, pm2_address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xpm_tmr_blk, FADT71->pm_tm_len, FADT71->pm_tmr_blk, pm_timer_address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xgpe0blk, FADT71->gpe0blk_len, FADT71->gpe0blk, gpe0address_space); + ASL_BUILD_GAS_FROM_ENTRY (FADT2->Xgpe1_blk, FADT71->gpe1_blk_len, FADT71->gpe1_blk, gpe1_address_space); + +#else + + /* ACPI 1.0 FACS */ + + + /* The BIOS stored FADT should agree with Revision 1.0 */ + + FADT1 = (FADT_DESCRIPTOR_REV1*) acpi_gbl_FADT; + + /* + * Copy the table header and the common part of the tables + * The 2.0 table is an extension of the 1.0 table, so the + * entire 1.0 table can be copied first, then expand some + * fields to 64 bits. + */ + + MEMCPY (FADT2, FADT1, sizeof (FADT_DESCRIPTOR_REV1)); + + + /* Convert table pointers to 64-bit fields */ + + ACPI_STORE_ADDRESS (FADT2->Xfirmware_ctrl, FADT1->firmware_ctrl); + ACPI_STORE_ADDRESS (FADT2->Xdsdt, FADT1->dsdt); + + /* System Interrupt Model isn't used in ACPI 2.0*/ + /* FADT2->Reserved1 = 0; */ + + /* This field is set by the OEM to convey the preferred */ + /* power management profile to OSPM. It doesn't have any*/ + /* 1.0 equivalence. Since we don't know what kind of */ + /* 32-bit system this is, we will pick unspecified. */ + + FADT2->prefer_PM_profile = PM_UNSPECIFIED; + + + /* Processor Performance State Control. This is the value */ + /* OSPM writes to the SMI_CMD register to assume processor */ + /* performance state control responsibility. There isn't */ + /* any equivalence in 1.0. So leave it zeroed. */ + + FADT2->pstate_cnt = 0; + + + /* Support for the _CST object and C States change notification.*/ + /* This data item hasn't any 1.0 equivalence so leaving it zero.*/ + + FADT2->cst_cnt = 0; + + + /* Since there isn't any equivalence in 1.0 and since it */ + /* is highly likely that a 1.0 system has legacy support. */ + + FADT2->iapc_boot_arch = BAF_LEGACY_DEVICES; + + + /* + * Convert the V1.0 Block addresses to V2.0 GAS structures + * in this order: + * + * PM 1_a Events + * PM 1_b Events + * PM 1_a Control + * PM 1_b Control + * PM 2 Control + * PM Timer Control + * GPE Block 0 + * GPE Block 1 + */ + + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1a_evt_blk, FADT1->pm1_evt_len, FADT1->pm1a_evt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1b_evt_blk, FADT1->pm1_evt_len, FADT1->pm1b_evt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1a_cnt_blk, FADT1->pm1_cnt_len, FADT1->pm1a_cnt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm1b_cnt_blk, FADT1->pm1_cnt_len, FADT1->pm1b_cnt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm2_cnt_blk, FADT1->pm2_cnt_len, FADT1->pm2_cnt_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xpm_tmr_blk, FADT1->pm_tm_len, FADT1->pm_tmr_blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xgpe0blk, FADT1->gpe0blk_len, FADT1->gpe0blk); + ASL_BUILD_GAS_FROM_V1_ENTRY (FADT2->Xgpe1_blk, FADT1->gpe1_blk_len, FADT1->gpe1_blk); +#endif + } + + + /* + * Global FADT pointer will point to the common V2.0 FADT + */ + acpi_gbl_FADT = FADT2; + acpi_gbl_FADT->header.length = sizeof (FADT_DESCRIPTOR); + + + /* Free the original table */ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_FADT]; + acpi_tb_delete_single_table (table_desc); + + + /* Install the new table */ + + table_desc->pointer = (ACPI_TABLE_HEADER *) acpi_gbl_FADT; + table_desc->base_pointer = acpi_gbl_FADT; + table_desc->allocation = ACPI_MEM_ALLOCATED; + table_desc->length = sizeof (FADT_DESCRIPTOR_REV2); + + + /* Dump the entire FADT */ + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_convert_table_facs + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_build_common_facs ( + ACPI_TABLE_DESC *table_info) +{ + ACPI_COMMON_FACS *common_facs; + +#ifdef _IA64 + FACS_DESCRIPTOR_REV071 *FACS71; +#else + FACS_DESCRIPTOR_REV1 *FACS1; +#endif + + FACS_DESCRIPTOR_REV2 *FACS2; + + + /* Allocate a common FACS */ + + common_facs = acpi_cm_callocate (sizeof (ACPI_COMMON_FACS)); + if (!common_facs) { + return (AE_NO_MEMORY); + } + + + /* Copy fields to the new FACS */ + + if (acpi_gbl_RSDP->revision < 2) { +#ifdef _IA64 + /* 0.71 FACS */ + + FACS71 = (FACS_DESCRIPTOR_REV071 *) acpi_gbl_FACS; + + common_facs->global_lock = (u32 *) &(FACS71->global_lock); + common_facs->firmware_waking_vector = &FACS71->firmware_waking_vector; + common_facs->vector_width = 64; +#else + /* ACPI 1.0 FACS */ + + FACS1 = (FACS_DESCRIPTOR_REV1 *) acpi_gbl_FACS; + + common_facs->global_lock = &(FACS1->global_lock); + common_facs->firmware_waking_vector = (UINT64 *) &FACS1->firmware_waking_vector; + common_facs->vector_width = 32; + +#endif + } + + else { + /* ACPI 2.0 FACS */ + + FACS2 = (FACS_DESCRIPTOR_REV2 *) acpi_gbl_FACS; + + common_facs->global_lock = &(FACS2->global_lock); + common_facs->firmware_waking_vector = &FACS2->Xfirmware_waking_vector; + common_facs->vector_width = 64; + } + + + /* Set the global FACS pointer to point to the common FACS */ + + + acpi_gbl_FACS = common_facs; + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/tables/tbget.c b/drivers/bus/acpi/tables/tbget.c new file mode 100644 index 0000000..1c7ea10 --- /dev/null +++ b/drivers/bus/acpi/tables/tbget.c @@ -0,0 +1,611 @@ +/****************************************************************************** + * + * Module Name: tbget - ACPI Table get* routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + MODULE_NAME ("tbget") + +#define RSDP_CHECKSUM_LENGTH 20 + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_ptr + * + * PARAMETERS: Table_type - one of the defined table types + * Instance - Which table of this type + * Table_ptr_loc - pointer to location to place the pointer for + * return + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get the pointer to an ACPI table. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_ptr ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER **table_ptr_loc) +{ + ACPI_TABLE_DESC *table_desc; + u32 i; + + + if (!acpi_gbl_DSDT) { + return (AE_NO_ACPI_TABLES); + } + + if (table_type > ACPI_TABLE_MAX) { + return (AE_BAD_PARAMETER); + } + + + /* + * For all table types (Single/Multiple), the first + * instance is always in the list head. + */ + + if (instance == 1) { + /* + * Just pluck the pointer out of the global table! + * Will be null if no table is present + */ + + *table_ptr_loc = acpi_gbl_acpi_tables[table_type].pointer; + return (AE_OK); + } + + + /* + * Check for instance out of range + */ + if (instance > acpi_gbl_acpi_tables[table_type].count) { + return (AE_NOT_EXIST); + } + + /* Walk the list to get the desired table + * Since the if (Instance == 1) check above checked for the + * first table, setting Table_desc equal to the .Next member + * is actually pointing to the second table. Therefore, we + * need to walk from the 2nd table until we reach the Instance + * that the user is looking for and return its table pointer. + */ + table_desc = acpi_gbl_acpi_tables[table_type].next; + for (i = 2; i < instance; i++) { + table_desc = table_desc->next; + } + + /* We are now pointing to the requested table's descriptor */ + + *table_ptr_loc = table_desc->pointer; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table + * + * PARAMETERS: Physical_address - Physical address of table to retrieve + * *Buffer_ptr - If Buffer_ptr is valid, read data from + * buffer rather than searching memory + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Maps the physical address of table into a logical address + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table ( + ACPI_PHYSICAL_ADDRESS physical_address, + ACPI_TABLE_HEADER *buffer_ptr, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_HEADER *table_header = NULL; + ACPI_TABLE_HEADER *full_table = NULL; + u32 size; + u8 allocation; + ACPI_STATUS status = AE_OK; + + + if (!table_info) { + return (AE_BAD_PARAMETER); + } + + + if (buffer_ptr) { + /* + * Getting data from a buffer, not BIOS tables + */ + + table_header = buffer_ptr; + status = acpi_tb_validate_table_header (table_header); + if (ACPI_FAILURE (status)) { + /* Table failed verification, map all errors to BAD_DATA */ + + return (AE_BAD_DATA); + } + + /* Allocate buffer for the entire table */ + + full_table = acpi_cm_allocate (table_header->length); + if (!full_table) { + return (AE_NO_MEMORY); + } + + /* Copy the entire table (including header) to the local buffer */ + + size = table_header->length; + MEMCPY (full_table, buffer_ptr, size); + + /* Save allocation type */ + + allocation = ACPI_MEM_ALLOCATED; + } + + + /* + * Not reading from a buffer, just map the table's physical memory + * into our address space. + */ + else { + size = SIZE_IN_HEADER; + + status = acpi_tb_map_acpi_table (physical_address, &size, + (void **) &full_table); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Save allocation type */ + + allocation = ACPI_MEM_MAPPED; + } + + + /* Return values */ + + table_info->pointer = full_table; + table_info->length = size; + table_info->allocation = allocation; + table_info->base_pointer = full_table; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_all_tables + * + * PARAMETERS: Number_of_tables - Number of tables to get + * Table_ptr - Input buffer pointer, optional + * + * RETURN: Status + * + * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must + * already be loaded and validated. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_all_tables ( + u32 number_of_tables, + ACPI_TABLE_HEADER *table_ptr) +{ + ACPI_STATUS status = AE_OK; + u32 index; + ACPI_TABLE_DESC table_info; + + + /* + * Loop through all table pointers found in RSDT. + * This will NOT include the FACS and DSDT - we must get + * them after the loop + */ + + for (index = 0; index < number_of_tables; index++) { + /* Clear the Table_info each time */ + + MEMSET (&table_info, 0, sizeof (ACPI_TABLE_DESC)); + + /* Get the table via the XSDT */ + + status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) + ACPI_GET_ADDRESS (acpi_gbl_XSDT->table_offset_entry[index]), + table_ptr, &table_info); + + /* Ignore a table that failed verification */ + + if (status == AE_BAD_DATA) { + continue; + } + + /* However, abort on serious errors */ + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Recognize and install the table */ + + status = acpi_tb_install_table (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + /* + * Unrecognized or unsupported table, delete it and ignore the + * error. Just get as many tables as we can, later we will + * determine if there are enough tables to continue. + */ + + acpi_tb_uninstall_table (&table_info); + } + } + + + /* + * Convert the FADT to a common format. This allows earlier revisions of the + * table to coexist with newer versions, using common access code. + */ + status = acpi_tb_convert_table_fadt (); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Get the minimum set of ACPI tables, namely: + * + * 1) FADT (via RSDT in loop above) + * 2) FACS + * 3) DSDT + * + */ + + + /* + * Get the FACS (must have the FADT first, from loop above) + * Acpi_tb_get_table_facs will fail if FADT pointer is not valid + */ + + status = acpi_tb_get_table_facs (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Install the FACS */ + + status = acpi_tb_install_table (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Create the common FACS pointer table + * (Contains pointers to the original table) + */ + + status = acpi_tb_build_common_facs (&table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* + * Get the DSDT (We know that the FADT is valid now) + */ + + status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xdsdt), + table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the DSDT */ + + status = acpi_tb_install_table (table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Dump the DSDT Header */ + + /* Dump the entire DSDT */ + + /* + * Initialize the capabilities flags. + * Assumes that platform supports ACPI_MODE since we have tables! + */ + acpi_gbl_system_flags |= acpi_hw_get_mode_capabilities (); + + + /* Always delete the RSDP mapping, we are done with it */ + + acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_verify_rsdp + * + * PARAMETERS: Number_of_tables - Where the table count is placed + * + * RETURN: Status + * + * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_verify_rsdp ( + ACPI_PHYSICAL_ADDRESS rsdp_physical_address) +{ + ACPI_TABLE_DESC table_info; + ACPI_STATUS status; + u8 *table_ptr; + + + /* + * Obtain access to the RSDP structure + */ + status = acpi_os_map_memory (rsdp_physical_address, + sizeof (RSDP_DESCRIPTOR), + (void **) &table_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * The signature and checksum must both be correct + */ + if (STRNCMP ((NATIVE_CHAR *) table_ptr, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { + /* Nope, BAD Signature */ + + status = AE_BAD_SIGNATURE; + goto cleanup; + } + + if (acpi_tb_checksum (table_ptr, RSDP_CHECKSUM_LENGTH) != 0) { + /* Nope, BAD Checksum */ + + status = AE_BAD_CHECKSUM; + goto cleanup; + } + + /* TBD: Check extended checksum if table version >= 2 */ + + /* The RSDP supplied is OK */ + + table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr; + table_info.length = sizeof (RSDP_DESCRIPTOR); + table_info.allocation = ACPI_MEM_MAPPED; + table_info.base_pointer = table_ptr; + + /* Save the table pointers and allocation info */ + + status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info); + if (ACPI_FAILURE (status)) { + goto cleanup; + } + + + /* Save the RSDP in a global for easy access */ + + acpi_gbl_RSDP = (RSDP_DESCRIPTOR *) table_info.pointer; + return (status); + + + /* Error exit */ +cleanup: + + acpi_os_unmap_memory (table_ptr, sizeof (RSDP_DESCRIPTOR)); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_get_table_rsdt + * + * PARAMETERS: Number_of_tables - Where the table count is placed + * + * RETURN: Status + * + * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_rsdt ( + u32 *number_of_tables) +{ + ACPI_TABLE_DESC table_info; + ACPI_STATUS status = AE_OK; + ACPI_PHYSICAL_ADDRESS physical_address; + u32 signature_length; + char *table_signature; + + + /* + * Get the RSDT from the RSDP + */ + + /* + * For RSDP revision 0 or 1, we use the RSDT. + * For RSDP revision 2 (and above), we use the XSDT + */ + if (acpi_gbl_RSDP->revision < 2) { +#ifdef _IA64 + /* 0.71 RSDP has 64bit Rsdt address field */ + physical_address = ((RSDP_DESCRIPTOR_REV071 *)acpi_gbl_RSDP)->rsdt_physical_address; +#else + physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->rsdt_physical_address; +#endif + table_signature = RSDT_SIG; + signature_length = sizeof (RSDT_SIG) -1; + } + else { + physical_address = (ACPI_PHYSICAL_ADDRESS) + ACPI_GET_ADDRESS (acpi_gbl_RSDP->xsdt_physical_address); + table_signature = XSDT_SIG; + signature_length = sizeof (XSDT_SIG) -1; + } + + + /* Get the RSDT/XSDT */ + + status = acpi_tb_get_table (physical_address, NULL, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + + /* Check the RSDT or XSDT signature */ + + if (STRNCMP ((char *) table_info.pointer, table_signature, + signature_length)) { + /* Invalid RSDT or XSDT signature */ + + REPORT_ERROR (("Invalid signature where RSDP indicates %s should be located\n", + table_signature)); + + return (status); + } + + + /* Valid RSDT signature, verify the checksum */ + + status = acpi_tb_verify_table_checksum (table_info.pointer); + + + /* Convert and/or copy to an XSDT structure */ + + status = acpi_tb_convert_to_xsdt (&table_info, number_of_tables); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Save the table pointers and allocation info */ + + status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_gbl_XSDT = (XSDT_DESCRIPTOR *) table_info.pointer; + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_tb_get_table_facs + * + * PARAMETERS: *Buffer_ptr - If Buffer_ptr is valid, read data from + * buffer rather than searching memory + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Returns a pointer to the FACS as defined in FADT. This + * function assumes the global variable FADT has been + * correctly initialized. The value of FADT->Firmware_ctrl + * into a far pointer which is returned. + * + *****************************************************************************/ + +ACPI_STATUS +acpi_tb_get_table_facs ( + ACPI_TABLE_HEADER *buffer_ptr, + ACPI_TABLE_DESC *table_info) +{ + void *table_ptr = NULL; + u32 size; + u8 allocation; + ACPI_STATUS status = AE_OK; + + + /* Must have a valid FADT pointer */ + + if (!acpi_gbl_FADT) { + return (AE_NO_ACPI_TABLES); + } + + size = sizeof (FACS_DESCRIPTOR); + if (buffer_ptr) { + /* + * Getting table from a file -- allocate a buffer and + * read the table. + */ + table_ptr = acpi_cm_allocate (size); + if(!table_ptr) { + return (AE_NO_MEMORY); + } + + MEMCPY (table_ptr, buffer_ptr, size); + + /* Save allocation type */ + + allocation = ACPI_MEM_ALLOCATED; + } + + else { + /* Just map the physical memory to our address space */ + + status = acpi_tb_map_acpi_table ((ACPI_PHYSICAL_ADDRESS) ACPI_GET_ADDRESS (acpi_gbl_FADT->Xfirmware_ctrl), + &size, &table_ptr); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Save allocation type */ + + allocation = ACPI_MEM_MAPPED; + } + + + /* Return values */ + + table_info->pointer = table_ptr; + table_info->length = size; + table_info->allocation = allocation; + table_info->base_pointer = table_ptr; + + return (status); +} + diff --git a/drivers/bus/acpi/tables/tbinstal.c b/drivers/bus/acpi/tables/tbinstal.c new file mode 100644 index 0000000..2b89e3f --- /dev/null +++ b/drivers/bus/acpi/tables/tbinstal.c @@ -0,0 +1,534 @@ +/****************************************************************************** + * + * Module Name: tbinstal - ACPI table installation and removal + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + MODULE_NAME ("tbinstal") + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_install_table + * + * PARAMETERS: Table_ptr - Input buffer pointer, optional + * Table_info - Return value from Acpi_tb_get_table + * + * RETURN: Status + * + * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must + * already be loaded and validated. + * Install the table into the global data structs. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_install_table ( + ACPI_TABLE_HEADER *table_ptr, + ACPI_TABLE_DESC *table_info) +{ + ACPI_STATUS status; + + + /* + * Check the table signature and make sure it is recognized + * Also checks the header checksum + */ + + status = acpi_tb_recognize_table (table_ptr, table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Lock tables while installing */ + + acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + + /* Install the table into the global data structure */ + + status = acpi_tb_init_table_descriptor (table_info->type, table_info); + + acpi_cm_release_mutex (ACPI_MTX_TABLES); + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_recognize_table + * + * PARAMETERS: Table_ptr - Input buffer pointer, optional + * Table_info - Return value from Acpi_tb_get_table + * + * RETURN: Status + * + * DESCRIPTION: Check a table signature for a match against known table types + * + * NOTE: All table pointers are validated as follows: + * 1) Table pointer must point to valid physical memory + * 2) Signature must be 4 ASCII chars, even if we don't recognize the + * name + * 3) Table must be readable for length specified in the header + * 4) Table checksum must be valid (with the exception of the FACS + * which has no checksum for some odd reason) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_recognize_table ( + ACPI_TABLE_HEADER *table_ptr, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_HEADER *table_header; + ACPI_STATUS status; + ACPI_TABLE_TYPE table_type = 0; + u32 i; + + + /* Ensure that we have a valid table pointer */ + + table_header = (ACPI_TABLE_HEADER *) table_info->pointer; + if (!table_header) { + return (AE_BAD_PARAMETER); + } + + /* + * Search for a signature match among the known table types + * Start at index one -> Skip the RSDP + */ + + status = AE_SUPPORT; + for (i = 1; i < NUM_ACPI_TABLES; i++) { + if (!STRNCMP (table_header->signature, + acpi_gbl_acpi_table_data[i].signature, + acpi_gbl_acpi_table_data[i].sig_length)) { + /* + * Found a signature match, get the pertinent info from the + * Table_data structure + */ + + table_type = i; + status = acpi_gbl_acpi_table_data[i].status; + + break; + } + } + + /* Return the table type and length via the info struct */ + + table_info->type = (u8) table_type; + table_info->length = table_header->length; + + + /* + * Validate checksum for _most_ tables, + * even the ones whose signature we don't recognize + */ + + if (table_type != ACPI_TABLE_FACS) { + /* But don't abort if the checksum is wrong */ + /* TBD: [Future] make this a configuration option? */ + + acpi_tb_verify_table_checksum (table_header); + } + + /* + * An AE_SUPPORT means that the table was not recognized. + * We basically ignore this; just print a debug message + */ + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_init_table_descriptor + * + * PARAMETERS: Table_type - The type of the table + * Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Install a table into the global data structs. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_init_table_descriptor ( + ACPI_TABLE_TYPE table_type, + ACPI_TABLE_DESC *table_info) +{ + ACPI_TABLE_DESC *list_head; + ACPI_TABLE_DESC *table_desc; + + + /* + * Install the table into the global data structure + */ + + list_head = &acpi_gbl_acpi_tables[table_type]; + table_desc = list_head; + + + /* + * Two major types of tables: 1) Only one instance is allowed. This + * includes most ACPI tables such as the DSDT. 2) Multiple instances of + * the table are allowed. This includes SSDT and PSDTs. + */ + + if (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags)) { + /* + * Only one table allowed, and a table has alread been installed + * at this location, so return an error. + */ + + if (list_head->pointer) { + return (AE_EXIST); + } + + table_desc->count = 1; + } + + + else { + /* + * Multiple tables allowed for this table type, we must link + * the new table in to the list of tables of this type. + */ + + if (list_head->pointer) { + table_desc = acpi_cm_callocate (sizeof (ACPI_TABLE_DESC)); + if (!table_desc) { + return (AE_NO_MEMORY); + } + + list_head->count++; + + /* Update the original previous */ + + list_head->prev->next = table_desc; + + /* Update new entry */ + + table_desc->prev = list_head->prev; + table_desc->next = list_head; + + /* Update list head */ + + list_head->prev = table_desc; + } + + else { + table_desc->count = 1; + } + } + + + /* Common initialization of the table descriptor */ + + table_desc->pointer = table_info->pointer; + table_desc->base_pointer = table_info->base_pointer; + table_desc->length = table_info->length; + table_desc->allocation = table_info->allocation; + table_desc->aml_pointer = (u8 *) (table_desc->pointer + 1), + table_desc->aml_length = (u32) (table_desc->length - + (u32) sizeof (ACPI_TABLE_HEADER)); + table_desc->table_id = acpi_cm_allocate_owner_id (OWNER_TYPE_TABLE); + table_desc->loaded_into_namespace = FALSE; + + /* + * Set the appropriate global pointer (if there is one) to point to the + * newly installed table + */ + + if (acpi_gbl_acpi_table_data[table_type].global_ptr) { + *(acpi_gbl_acpi_table_data[table_type].global_ptr) = table_info->pointer; + } + + + /* Return Data */ + + table_info->table_id = table_desc->table_id; + table_info->installed_desc = table_desc; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_delete_acpi_tables + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all internal ACPI tables + * + ******************************************************************************/ + +void +acpi_tb_delete_acpi_tables (void) +{ + ACPI_TABLE_TYPE type; + + + /* + * Free memory allocated for ACPI tables + * Memory can either be mapped or allocated + */ + + for (type = 0; type < NUM_ACPI_TABLES; type++) { + acpi_tb_delete_acpi_table (type); + } + +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_delete_acpi_table + * + * PARAMETERS: Type - The table type to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Delete an internal ACPI table + * Locks the ACPI table mutex + * + ******************************************************************************/ + +void +acpi_tb_delete_acpi_table ( + ACPI_TABLE_TYPE type) +{ + + if (type > ACPI_TABLE_MAX) { + return; + } + + + acpi_cm_acquire_mutex (ACPI_MTX_TABLES); + + /* Free the table */ + + acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]); + + + /* Clear the appropriate "typed" global table pointer */ + + switch (type) { + case ACPI_TABLE_RSDP: + acpi_gbl_RSDP = NULL; + break; + + case ACPI_TABLE_DSDT: + acpi_gbl_DSDT = NULL; + break; + + case ACPI_TABLE_FADT: + acpi_gbl_FADT = NULL; + break; + + case ACPI_TABLE_FACS: + acpi_gbl_FACS = NULL; + break; + + case ACPI_TABLE_XSDT: + acpi_gbl_XSDT = NULL; + break; + + case ACPI_TABLE_SSDT: + case ACPI_TABLE_PSDT: + default: + break; + } + + acpi_cm_release_mutex (ACPI_MTX_TABLES); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_free_acpi_tables_of_type + * + * PARAMETERS: Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Free the memory associated with an internal ACPI table + * Table mutex should be locked. + * + ******************************************************************************/ + +void +acpi_tb_free_acpi_tables_of_type ( + ACPI_TABLE_DESC *list_head) +{ + ACPI_TABLE_DESC *table_desc; + u32 count; + u32 i; + + + /* Get the head of the list */ + + table_desc = list_head; + count = list_head->count; + + /* + * Walk the entire list, deleting both the allocated tables + * and the table descriptors + */ + + for (i = 0; i < count; i++) { + table_desc = acpi_tb_uninstall_table (table_desc); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_delete_single_table + * + * PARAMETERS: Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where + * the table was allocated a buffer or was mapped. + * + ******************************************************************************/ + +void +acpi_tb_delete_single_table ( + ACPI_TABLE_DESC *table_desc) +{ + + if (!table_desc) { + return; + } + + if (table_desc->pointer) { + /* Valid table, determine type of memory allocation */ + + switch (table_desc->allocation) { + + case ACPI_MEM_NOT_ALLOCATED: + break; + + + case ACPI_MEM_ALLOCATED: + + acpi_cm_free (table_desc->base_pointer); + break; + + + case ACPI_MEM_MAPPED: + + acpi_os_unmap_memory (table_desc->base_pointer, table_desc->length); + break; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_uninstall_table + * + * PARAMETERS: Table_info - A table info struct + * + * RETURN: None. + * + * DESCRIPTION: Free the memory associated with an internal ACPI table that + * is either installed or has never been installed. + * Table mutex should be locked. + * + ******************************************************************************/ + +ACPI_TABLE_DESC * +acpi_tb_uninstall_table ( + ACPI_TABLE_DESC *table_desc) +{ + ACPI_TABLE_DESC *next_desc; + + + if (!table_desc) { + return (NULL); + } + + + /* Unlink the descriptor */ + + if (table_desc->prev) { + table_desc->prev->next = table_desc->next; + } + + if (table_desc->next) { + table_desc->next->prev = table_desc->prev; + } + + + /* Free the memory allocated for the table itself */ + + acpi_tb_delete_single_table (table_desc); + + + /* Free the table descriptor (Don't delete the list head, tho) */ + + if ((table_desc->prev) == (table_desc->next)) { + + next_desc = NULL; + + /* Clear the list head */ + + table_desc->pointer = NULL; + table_desc->length = 0; + table_desc->count = 0; + + } + + else { + /* Free the table descriptor */ + + next_desc = table_desc->next; + acpi_cm_free (table_desc); + } + + + return (next_desc); +} + + diff --git a/drivers/bus/acpi/tables/tbutils.c b/drivers/bus/acpi/tables/tbutils.c new file mode 100644 index 0000000..b3a0275 --- /dev/null +++ b/drivers/bus/acpi/tables/tbutils.c @@ -0,0 +1,355 @@ +/****************************************************************************** + * + * Module Name: tbutils - Table manipulation utilities + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "actables.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_TABLES + MODULE_NAME ("tbutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_handle_to_object + * + * PARAMETERS: Table_id - Id for which the function is searching + * Table_desc - Pointer to return the matching table + * descriptor. + * + * RETURN: Search the tables to find one with a matching Table_id and + * return a pointer to that table descriptor. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_handle_to_object ( + u16 table_id, + ACPI_TABLE_DESC **table_desc) +{ + u32 i; + ACPI_TABLE_DESC *list_head; + + + for (i = 0; i < ACPI_TABLE_MAX; i++) { + list_head = &acpi_gbl_acpi_tables[i]; + do { + if (list_head->table_id == table_id) { + *table_desc = list_head; + return (AE_OK); + } + + list_head = list_head->next; + + } while (list_head != &acpi_gbl_acpi_tables[i]); + } + + + return (AE_BAD_PARAMETER); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_system_table_pointer + * + * PARAMETERS: *Where - Pointer to be examined + * + * RETURN: TRUE if Where is within the AML stream (in one of the ACPI + * system tables such as the DSDT or an SSDT.) + * FALSE otherwise + * + ******************************************************************************/ + +u8 +acpi_tb_system_table_pointer ( + void *where) +{ + u32 i; + ACPI_TABLE_DESC *table_desc; + ACPI_TABLE_HEADER *table; + + + /* No function trace, called too often! */ + + + /* Ignore null pointer */ + + if (!where) { + return (FALSE); + } + + + /* Check for a pointer within the DSDT */ + + if ((acpi_gbl_DSDT) && + (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT))) { + return (TRUE); + } + + + /* Check each of the loaded SSDTs (if any)*/ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; + + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { + table = table_desc->pointer; + + if (IS_IN_ACPI_TABLE (where, table)) { + return (TRUE); + } + + table_desc = table_desc->next; + } + + + /* Check each of the loaded PSDTs (if any)*/ + + table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; + + for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { + table = table_desc->pointer; + + if (IS_IN_ACPI_TABLE (where, table)) { + return (TRUE); + } + + table_desc = table_desc->next; + } + + + /* Pointer does not point into any system table */ + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_validate_table_header + * + * PARAMETERS: Table_header - Logical pointer to the table + * + * RETURN: Status + * + * DESCRIPTION: Check an ACPI table header for validity + * + * NOTE: Table pointers are validated as follows: + * 1) Table pointer must point to valid physical memory + * 2) Signature must be 4 ASCII chars, even if we don't recognize the + * name + * 3) Table must be readable for length specified in the header + * 4) Table checksum must be valid (with the exception of the FACS + * which has no checksum for some odd reason) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_validate_table_header ( + ACPI_TABLE_HEADER *table_header) +{ + ACPI_NAME signature; + + + /* Verify that this is a valid address */ + + if (!acpi_os_readable (table_header, sizeof (ACPI_TABLE_HEADER))) { + return (AE_BAD_ADDRESS); + } + + + /* Ensure that the signature is 4 ASCII characters */ + + MOVE_UNALIGNED32_TO_32 (&signature, &table_header->signature); + if (!acpi_cm_valid_acpi_name (signature)) { + REPORT_WARNING (("Invalid table signature found\n")); + return (AE_BAD_SIGNATURE); + } + + + /* Validate the table length */ + + if (table_header->length < sizeof (ACPI_TABLE_HEADER)) { + REPORT_WARNING (("Invalid table header length found\n")); + return (AE_BAD_HEADER); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_map_acpi_table + * + * PARAMETERS: Physical_address - Physical address of table to map + * *Size - Size of the table. If zero, the size + * from the table header is used. + * Actual size is returned here. + * **Logical_address - Logical address of mapped table + * + * RETURN: Logical address of the mapped table. + * + * DESCRIPTION: Maps the physical address of table into a logical address + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_map_acpi_table ( + ACPI_PHYSICAL_ADDRESS physical_address, + u32 *size, + void **logical_address) +{ + ACPI_TABLE_HEADER *table; + u32 table_size = *size; + ACPI_STATUS status = AE_OK; + + + /* If size is zero, look at the table header to get the actual size */ + + if ((*size) == 0) { + /* Get the table header so we can extract the table length */ + + status = acpi_os_map_memory (physical_address, sizeof (ACPI_TABLE_HEADER), + (void **) &table); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Extract the full table length before we delete the mapping */ + + table_size = table->length; + + /* + * Validate the header and delete the mapping. + * We will create a mapping for the full table below. + */ + + status = acpi_tb_validate_table_header (table); + + /* Always unmap the memory for the header */ + + acpi_os_unmap_memory (table, sizeof (ACPI_TABLE_HEADER)); + + /* Exit if header invalid */ + + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* Map the physical memory for the correct length */ + + status = acpi_os_map_memory (physical_address, table_size, (void **) &table); + if (ACPI_FAILURE (status)) { + return (status); + } + + *size = table_size; + *logical_address = table; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_verify_table_checksum + * + * PARAMETERS: *Table_header - ACPI table to verify + * + * RETURN: 8 bit checksum of table + * + * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct + * table should have a checksum of 0. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_verify_table_checksum ( + ACPI_TABLE_HEADER *table_header) +{ + u8 checksum; + ACPI_STATUS status = AE_OK; + + + /* Compute the checksum on the table */ + + checksum = acpi_tb_checksum (table_header, table_header->length); + + /* Return the appropriate exception */ + + if (checksum) { + REPORT_WARNING (("Invalid checksum (%X) in table %4.4s\n", + checksum, &table_header->signature)); + + status = AE_BAD_CHECKSUM; + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_checksum + * + * PARAMETERS: Buffer - Buffer to checksum + * Length - Size of the buffer + * + * RETURNS 8 bit checksum of buffer + * + * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it. + * + ******************************************************************************/ + +u8 +acpi_tb_checksum ( + void *buffer, + u32 length) +{ + u8 *limit; + u8 *rover; + u8 sum = 0; + + + if (buffer && length) { + /* Buffer and Length are valid */ + + limit = (u8 *) buffer + length; + + for (rover = buffer; rover < limit; rover++) { + sum = (u8) (sum + *rover); + } + } + + return (sum); +} + + diff --git a/drivers/bus/acpi/tables/tbxface.c b/drivers/bus/acpi/tables/tbxface.c new file mode 100644 index 0000000..64e653a --- /dev/null +++ b/drivers/bus/acpi/tables/tbxface.c @@ -0,0 +1,387 @@ +/****************************************************************************** + * + * Module Name: tbxface - Public interfaces to the ACPI subsystem + * ACPI table oriented interfaces + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + MODULE_NAME ("tbxface") + + +/******************************************************************************* + * + * FUNCTION: Acpi_load_tables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load the ACPI tables from the + * provided RSDT + * + ******************************************************************************/ + +ACPI_STATUS +acpi_load_tables ( + ACPI_PHYSICAL_ADDRESS rsdp_physical_address) +{ + ACPI_STATUS status = AE_OK; + u32 number_of_tables = 0; + + + /* Map and validate the RSDP */ + + status = acpi_tb_verify_rsdp (rsdp_physical_address); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Acpi_load_tables: RSDP Failed validation: %s\n", + acpi_cm_format_exception (status))); + goto error_exit; + } + + /* Get the RSDT via the RSDP */ + + status = acpi_tb_get_table_rsdt (&number_of_tables); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Acpi_load_tables: Could not load RSDT: %s\n", + acpi_cm_format_exception (status))); + goto error_exit; + } + + /* Now get the rest of the tables */ + + status = acpi_tb_get_all_tables (number_of_tables, NULL); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", + acpi_cm_format_exception (status))); + goto error_exit; + } + + + /* Load the namespace from the tables */ + + status = acpi_ns_load_namespace (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Acpi_load_tables: Could not load namespace: %s\n", + acpi_cm_format_exception (status))); + goto error_exit; + } + + return (AE_OK); + + +error_exit: + REPORT_ERROR (("Acpi_load_tables: Could not load tables: %s\n", + acpi_cm_format_exception (status))); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_load_table + * + * PARAMETERS: Table_ptr - pointer to a buffer containing the entire + * table to be loaded + * + * RETURN: Status + * + * DESCRIPTION: This function is called to load a table from the caller's + * buffer. The buffer must contain an entire ACPI Table including + * a valid header. The header fields will be verified, and if it + * is determined that the table is invalid, the call will fail. + * + * If the call fails an appropriate status will be returned. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_load_table ( + ACPI_TABLE_HEADER *table_ptr) +{ + ACPI_STATUS status; + ACPI_TABLE_DESC table_info; + + + if (!table_ptr) { + return (AE_BAD_PARAMETER); + } + + /* Copy the table to a local buffer */ + + status = acpi_tb_get_table (0, table_ptr, &table_info); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* Install the new table into the local data structures */ + + status = acpi_tb_install_table (NULL, &table_info); + if (ACPI_FAILURE (status)) { + /* Free table allocated by Acpi_tb_get_table */ + + acpi_tb_delete_single_table (&table_info); + return (status); + } + + + status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); + if (ACPI_FAILURE (status)) { + /* Uninstall table and free the buffer */ + + acpi_tb_uninstall_table (table_info.installed_desc); + return (status); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_unload_table + * + * PARAMETERS: Table_type - Type of table to be unloaded + * + * RETURN: Status + * + * DESCRIPTION: This routine is used to force the unload of a table + * + ******************************************************************************/ + +ACPI_STATUS +acpi_unload_table ( + ACPI_TABLE_TYPE table_type) +{ + ACPI_TABLE_DESC *list_head; + + + /* Parameter validation */ + + if (table_type > ACPI_TABLE_MAX) { + return (AE_BAD_PARAMETER); + } + + + /* Find all tables of the requested type */ + + list_head = &acpi_gbl_acpi_tables[table_type]; + do { + /* + * Delete all namespace entries owned by this table. Note that these + * entries can appear anywhere in the namespace by virtue of the AML + * "Scope" operator. Thus, we need to track ownership by an ID, not + * simply a position within the hierarchy + */ + + acpi_ns_delete_namespace_by_owner (list_head->table_id); + + /* Delete (or unmap) the actual table */ + + acpi_tb_delete_acpi_table (table_type); + + } while (list_head != &acpi_gbl_acpi_tables[table_type]); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_table_header + * + * PARAMETERS: Table_type - one of the defined table types + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * see Acpi_gbl_Acpi_table_flag + * Out_table_header - pointer to the ACPI_TABLE_HEADER if successful + * + * DESCRIPTION: This function is called to get an ACPI table header. The caller + * supplies an pointer to a data area sufficient to contain an ACPI + * ACPI_TABLE_HEADER structure. + * + * The header contains a length field that can be used to determine + * the size of the buffer needed to contain the entire table. This + * function is not valid for the RSD PTR table since it does not + * have a standard header and is fixed length. + * + * If the operation fails for any reason an appropriate status will + * be returned and the contents of Out_table_header are undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_table_header ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_TABLE_HEADER *out_table_header) +{ + ACPI_TABLE_HEADER *tbl_ptr; + ACPI_STATUS status; + + + if ((instance == 0) || + (table_type == ACPI_TABLE_RSDP) || + (!out_table_header)) { + return (AE_BAD_PARAMETER); + } + + /* Check the table type and instance */ + + if ((table_type > ACPI_TABLE_MAX) || + (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && + instance > 1)) { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the entire table */ + + status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * The function will return a NULL pointer if the table is not loaded + */ + if (tbl_ptr == NULL) { + return (AE_NOT_EXIST); + } + + /* + * Copy the header to the caller's buffer + */ + MEMCPY ((void *) out_table_header, (void *) tbl_ptr, + sizeof (ACPI_TABLE_HEADER)); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_get_table + * + * PARAMETERS: Table_type - one of the defined table types + * Instance - the non zero instance of the table, allows + * support for multiple tables of the same type + * see Acpi_gbl_Acpi_table_flag + * Ret_buffer - pointer to a structure containing a buffer to + * receive the table + * + * RETURN: Status + * + * DESCRIPTION: This function is called to get an ACPI table. The caller + * supplies an Out_buffer large enough to contain the entire ACPI + * table. The caller should call the Acpi_get_table_header function + * first to determine the buffer size needed. Upon completion + * the Out_buffer->Length field will indicate the number of bytes + * copied into the Out_buffer->Buf_ptr buffer. This table will be + * a complete table including the header. + * + * If the operation fails an appropriate status will be returned + * and the contents of Out_buffer are undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_table ( + ACPI_TABLE_TYPE table_type, + u32 instance, + ACPI_BUFFER *ret_buffer) +{ + ACPI_TABLE_HEADER *tbl_ptr; + ACPI_STATUS status; + u32 ret_buf_len; + + + /* + * If we have a buffer, we must have a length too + */ + if ((instance == 0) || + (!ret_buffer) || + ((!ret_buffer->pointer) && (ret_buffer->length))) { + return (AE_BAD_PARAMETER); + } + + /* Check the table type and instance */ + + if ((table_type > ACPI_TABLE_MAX) || + (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && + instance > 1)) { + return (AE_BAD_PARAMETER); + } + + + /* Get a pointer to the entire table */ + + status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Acpi_tb_get_table_ptr will return a NULL pointer if the + * table is not loaded. + */ + if (tbl_ptr == NULL) { + return (AE_NOT_EXIST); + } + + /* + * Got a table ptr, assume it's ok and copy it to the user's buffer + */ + if (table_type == ACPI_TABLE_RSDP) { + /* + * RSD PTR is the only "table" without a header + */ + ret_buf_len = sizeof (RSDP_DESCRIPTOR); + } + else { + ret_buf_len = tbl_ptr->length; + } + + /* + * Verify we have space in the caller's buffer for the table + */ + if (ret_buffer->length < ret_buf_len) { + ret_buffer->length = ret_buf_len; + return (AE_BUFFER_OVERFLOW); + } + + ret_buffer->length = ret_buf_len; + + MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, ret_buf_len); + + return (AE_OK); +} + diff --git a/drivers/bus/acpi/tables/tbxfroot.c b/drivers/bus/acpi/tables/tbxfroot.c new file mode 100644 index 0000000..58dfd10 --- /dev/null +++ b/drivers/bus/acpi/tables/tbxfroot.c @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * Module Name: tbxfroot - Find the root ACPI table (RSDT) + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + MODULE_NAME ("tbxfroot") + +#define RSDP_CHECKSUM_LENGTH 20 + + +/******************************************************************************* + * + * FUNCTION: Acpi_find_root_pointer + * + * PARAMETERS: **Rsdp_physical_address - Where to place the RSDP address + * + * RETURN: Status, Physical address of the RSDP + * + * DESCRIPTION: Find the RSDP + * + ******************************************************************************/ + +ACPI_STATUS +acpi_find_root_pointer ( + ACPI_PHYSICAL_ADDRESS *rsdp_physical_address) +{ + ACPI_TABLE_DESC table_info; + ACPI_STATUS status; + + + /* Get the RSDP */ + + status = acpi_tb_find_rsdp (&table_info); + if (ACPI_FAILURE (status)) { + return (AE_NO_ACPI_TABLES); + } + + *rsdp_physical_address = table_info.physical_address; + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_scan_memory_for_rsdp + * + * PARAMETERS: Start_address - Starting pointer for search + * Length - Maximum length to search + * + * RETURN: Pointer to the RSDP if found, otherwise NULL. + * + * DESCRIPTION: Search a block of memory for the RSDP signature + * + ******************************************************************************/ + +u8 * +acpi_tb_scan_memory_for_rsdp ( + u8 *start_address, + u32 length) +{ + u32 offset; + u8 *mem_rover; + + + /* Search from given start addr for the requested length */ + + for (offset = 0, mem_rover = start_address; + offset < length; + offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP) { + + /* The signature and checksum must both be correct */ + + if (STRNCMP ((NATIVE_CHAR *) mem_rover, + RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 && + acpi_tb_checksum (mem_rover, RSDP_CHECKSUM_LENGTH) == 0) { + /* If so, we have found the RSDP */ + + return (mem_rover); + } + } + + /* Searched entire block, no RSDP was found */ + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_tb_find_rsdp + * + * PARAMETERS: *Buffer_ptr - If == NULL, read data from buffer + * rather than searching memory + * *Table_info - Where the table info is returned + * + * RETURN: Status + * + * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor + * pointer structure. If it is found, set *RSDP to point to it. + * + * NOTE: The RSDP must be either in the first 1_k of the Extended + * BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section + * 5.2.2; assertion #421). + * + ******************************************************************************/ + +ACPI_STATUS +acpi_tb_find_rsdp ( + ACPI_TABLE_DESC *table_info) +{ + u8 *table_ptr; + u8 *mem_rover; + UINT64 phys_addr; + ACPI_STATUS status = AE_OK; + + + /* + * Search memory for RSDP. First map low physical memory. + */ + + status = acpi_os_map_memory (LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE, + (void **)&table_ptr); + + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * 1) Search EBDA (low memory) paragraphs + */ + + mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, LO_RSDP_WINDOW_SIZE); + + /* This mapping is no longer needed */ + + acpi_os_unmap_memory (table_ptr, LO_RSDP_WINDOW_SIZE); + + if (mem_rover) { + /* Found it, return the physical address */ + + phys_addr = LO_RSDP_WINDOW_BASE; + phys_addr += (mem_rover - table_ptr); + + table_info->physical_address = phys_addr; + + return (AE_OK); + } + + + /* + * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h + */ + + status = acpi_os_map_memory (HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE, + (void **)&table_ptr); + + if (ACPI_FAILURE (status)) { + return (status); + } + + mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, HI_RSDP_WINDOW_SIZE); + + /* This mapping is no longer needed */ + + acpi_os_unmap_memory (table_ptr, HI_RSDP_WINDOW_SIZE); + + if (mem_rover) { + /* Found it, return the physical address */ + + phys_addr = HI_RSDP_WINDOW_BASE; + phys_addr += (mem_rover - table_ptr); + + table_info->physical_address = phys_addr; + + return (AE_OK); + } + + + /* RSDP signature was not found */ + + return (AE_NOT_FOUND); +} + + diff --git a/drivers/bus/acpi/utils/.cvsignore b/drivers/bus/acpi/utils/.cvsignore new file mode 100644 index 0000000..dfa5ac2 --- /dev/null +++ b/drivers/bus/acpi/utils/.cvsignore @@ -0,0 +1,5 @@ +acpi.coff +objects +*.d +*.o +*.sym diff --git a/drivers/bus/acpi/utils/cmalloc.c b/drivers/bus/acpi/utils/cmalloc.c new file mode 100644 index 0000000..da34361 --- /dev/null +++ b/drivers/bus/acpi/utils/cmalloc.c @@ -0,0 +1,170 @@ +/****************************************************************************** + * + * Module Name: cmalloc - local memory allocation routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acparser.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acglobal.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmalloc") + + +/***************************************************************************** + * + * FUNCTION: _Cm_allocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ****************************************************************************/ + +void * +_cm_allocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line) +{ + void *address = NULL; + + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + _REPORT_ERROR (module, line, component, + ("Cm_allocate: Attempt to allocate zero bytes\n")); + size = 1; + } + + address = acpi_os_allocate (size); + if (!address) { + /* Report allocation error */ + + _REPORT_ERROR (module, line, component, + ("Cm_allocate: Could not allocate size %X\n", size)); + + return (NULL); + } + + + return (address); +} + + +/***************************************************************************** + * + * FUNCTION: _Cm_callocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ****************************************************************************/ + +void * +_cm_callocate ( + u32 size, + u32 component, + NATIVE_CHAR *module, + u32 line) +{ + void *address = NULL; + + + /* Check for an inadvertent size of zero bytes */ + + if (!size) { + _REPORT_ERROR (module, line, component, + ("Cm_callocate: Attempt to allocate zero bytes\n")); + return (NULL); + } + + + address = acpi_os_callocate (size); + + if (!address) { + /* Report allocation error */ + + _REPORT_ERROR (module, line, component, + ("Cm_callocate: Could not allocate size %X\n", size)); + return (NULL); + } + + + return (address); +} + + +/***************************************************************************** + * + * FUNCTION: _Cm_free + * + * PARAMETERS: Address - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Address + * + ****************************************************************************/ + +void +_cm_free ( + void *address, + u32 component, + NATIVE_CHAR *module, + u32 line) +{ + + if (NULL == address) { + _REPORT_ERROR (module, line, component, + ("_Cm_free: Trying to delete a NULL address\n")); + + return; + } + + + acpi_os_free (address); + + return; +} + + diff --git a/drivers/bus/acpi/utils/cmclib.c b/drivers/bus/acpi/utils/cmclib.c new file mode 100644 index 0000000..b8d531f --- /dev/null +++ b/drivers/bus/acpi/utils/cmclib.c @@ -0,0 +1,815 @@ +/****************************************************************************** + * + * Module Name: cmclib - Local implementation of C library functions + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acevents.h" +#include "achware.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" + +/* + * These implementations of standard C Library routines can optionally be + * used if a C library is not available. In general, they are less efficient + * than an inline or assembly implementation + */ + +#define _COMPONENT MISCELLANEOUS + MODULE_NAME ("cmclib") + + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +/******************************************************************************* + * + * FUNCTION: strlen + * + * PARAMETERS: String - Null terminated string + * + * RETURN: Length + * + * DESCRIPTION: Returns the length of the input string + * + ******************************************************************************/ + + +u32 +acpi_cm_strlen ( + const NATIVE_CHAR *string) +{ + u32 length = 0; + + + /* Count the string until a null is encountered */ + + while (*string) { + length++; + string++; + } + + return (length); +} + + +/******************************************************************************* + * + * FUNCTION: strcpy + * + * PARAMETERS: Dst_string - Target of the copy + * Src_string - The source string to copy + * + * RETURN: Dst_string + * + * DESCRIPTION: Copy a null terminated string + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_cm_strcpy ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string) +{ + NATIVE_CHAR *string = dst_string; + + + /* Move bytes brute force */ + + while (*src_string) { + *string = *src_string; + + string++; + src_string++; + } + + /* Null terminate */ + + *string = 0; + + return (dst_string); +} + + +/******************************************************************************* + * + * FUNCTION: strncpy + * + * PARAMETERS: Dst_string - Target of the copy + * Src_string - The source string to copy + * Count - Maximum # of bytes to copy + * + * RETURN: Dst_string + * + * DESCRIPTION: Copy a null terminated string, with a maximum length + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_cm_strncpy ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string, + NATIVE_UINT count) +{ + NATIVE_CHAR *string = dst_string; + + + /* Copy the string */ + + for (string = dst_string; + count && (count--, (*string++ = *src_string++)); ) {;} + + /* Pad with nulls if necessary */ + + while (count--) { + *string = 0; + string++; + } + + /* Return original pointer */ + + return (dst_string); +} + + +/******************************************************************************* + * + * FUNCTION: strcmp + * + * PARAMETERS: String1 - First string + * String2 - Second string + * + * RETURN: Index where strings mismatched, or 0 if strings matched + * + * DESCRIPTION: Compare two null terminated strings + * + ******************************************************************************/ + +u32 +acpi_cm_strcmp ( + const NATIVE_CHAR *string1, + const NATIVE_CHAR *string2) +{ + + + for ( ; (*string1 == *string2); string2++) { + if (!*string1++) { + return (0); + } + } + + + return ((unsigned char) *string1 - (unsigned char) *string2); +} + + +/******************************************************************************* + * + * FUNCTION: strncmp + * + * PARAMETERS: String1 - First string + * String2 - Second string + * Count - Maximum # of bytes to compare + * + * RETURN: Index where strings mismatched, or 0 if strings matched + * + * DESCRIPTION: Compare two null terminated strings, with a maximum length + * + ******************************************************************************/ + +u32 +acpi_cm_strncmp ( + const NATIVE_CHAR *string1, + const NATIVE_CHAR *string2, + NATIVE_UINT count) +{ + + + for ( ; count-- && (*string1 == *string2); string2++) { + if (!*string1++) { + return (0); + } + } + + return ((count == -1) ? 0 : ((unsigned char) *string1 - + (unsigned char) *string2)); +} + + +/******************************************************************************* + * + * FUNCTION: Strcat + * + * PARAMETERS: Dst_string - Target of the copy + * Src_string - The source string to copy + * + * RETURN: Dst_string + * + * DESCRIPTION: Append a null terminated string to a null terminated string + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_cm_strcat ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string) +{ + NATIVE_CHAR *string; + + + /* Find end of the destination string */ + + for (string = dst_string; *string++; ) { ; } + + /* Concatinate the string */ + + for (--string; (*string++ = *src_string++); ) { ; } + + return (dst_string); +} + + +/******************************************************************************* + * + * FUNCTION: strncat + * + * PARAMETERS: Dst_string - Target of the copy + * Src_string - The source string to copy + * Count - Maximum # of bytes to copy + * + * RETURN: Dst_string + * + * DESCRIPTION: Append a null terminated string to a null terminated string, + * with a maximum count. + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_cm_strncat ( + NATIVE_CHAR *dst_string, + const NATIVE_CHAR *src_string, + NATIVE_UINT count) +{ + NATIVE_CHAR *string; + + + if (count) { + /* Find end of the destination string */ + + for (string = dst_string; *string++; ) { ; } + + /* Concatinate the string */ + + for (--string; (*string++ = *src_string++) && --count; ) { ; } + + /* Null terminate if necessary */ + + if (!count) { + *string = 0; + } + } + + return (dst_string); +} + + +/******************************************************************************* + * + * FUNCTION: memcpy + * + * PARAMETERS: Dest - Target of the copy + * Src - Source buffer to copy + * Count - Number of bytes to copy + * + * RETURN: Dest + * + * DESCRIPTION: Copy arbitrary bytes of memory + * + ******************************************************************************/ + +void * +acpi_cm_memcpy ( + void *dest, + const void *src, + NATIVE_UINT count) +{ + NATIVE_CHAR *new = (NATIVE_CHAR *) dest; + NATIVE_CHAR *old = (NATIVE_CHAR *) src; + + + while (count) { + *new = *old; + new++; + old++; + count--; + } + + return (dest); +} + + +/******************************************************************************* + * + * FUNCTION: memset + * + * PARAMETERS: Dest - Buffer to set + * Value - Value to set each byte of memory + * Count - Number of bytes to set + * + * RETURN: Dest + * + * DESCRIPTION: Initialize a buffer to a known value. + * + ******************************************************************************/ + +void * +acpi_cm_memset ( + void *dest, + NATIVE_UINT value, + NATIVE_UINT count) +{ + NATIVE_CHAR *new = (NATIVE_CHAR *) dest; + + + while (count) { + *new = (char) value; + new++; + count--; + } + + return (dest); +} + + +#define NEGATIVE 1 +#define POSITIVE 0 + + +#define _ACPI_XA 0x00 /* extra alphabetic - not supported */ +#define _ACPI_XS 0x40 /* extra space */ +#define _ACPI_BB 0x00 /* BEL, BS, etc. - not supported */ +#define _ACPI_CN 0x20 /* CR, FF, HT, NL, VT */ +#define _ACPI_DI 0x04 /* '0'-'9' */ +#define _ACPI_LO 0x02 /* 'a'-'z' */ +#define _ACPI_PU 0x10 /* punctuation */ +#define _ACPI_SP 0x08 /* space */ +#define _ACPI_UP 0x01 /* 'A'-'Z' */ +#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ + +static const u8 _acpi_ctype[257] = { + _ACPI_CN, /* 0x0 0. */ + _ACPI_CN, /* 0x1 1. */ + _ACPI_CN, /* 0x2 2. */ + _ACPI_CN, /* 0x3 3. */ + _ACPI_CN, /* 0x4 4. */ + _ACPI_CN, /* 0x5 5. */ + _ACPI_CN, /* 0x6 6. */ + _ACPI_CN, /* 0x7 7. */ + _ACPI_CN, /* 0x8 8. */ + _ACPI_CN|_ACPI_SP, /* 0x9 9. */ + _ACPI_CN|_ACPI_SP, /* 0xA 10. */ + _ACPI_CN|_ACPI_SP, /* 0xB 11. */ + _ACPI_CN|_ACPI_SP, /* 0xC 12. */ + _ACPI_CN|_ACPI_SP, /* 0xD 13. */ + _ACPI_CN, /* 0xE 14. */ + _ACPI_CN, /* 0xF 15. */ + _ACPI_CN, /* 0x10 16. */ + _ACPI_CN, /* 0x11 17. */ + _ACPI_CN, /* 0x12 18. */ + _ACPI_CN, /* 0x13 19. */ + _ACPI_CN, /* 0x14 20. */ + _ACPI_CN, /* 0x15 21. */ + _ACPI_CN, /* 0x16 22. */ + _ACPI_CN, /* 0x17 23. */ + _ACPI_CN, /* 0x18 24. */ + _ACPI_CN, /* 0x19 25. */ + _ACPI_CN, /* 0x1A 26. */ + _ACPI_CN, /* 0x1B 27. */ + _ACPI_CN, /* 0x1C 28. */ + _ACPI_CN, /* 0x1D 29. */ + _ACPI_CN, /* 0x1E 30. */ + _ACPI_CN, /* 0x1F 31. */ + _ACPI_XS|_ACPI_SP, /* 0x20 32. ' ' */ + _ACPI_PU, /* 0x21 33. '!' */ + _ACPI_PU, /* 0x22 34. '"' */ + _ACPI_PU, /* 0x23 35. '#' */ + _ACPI_PU, /* 0x24 36. '$' */ + _ACPI_PU, /* 0x25 37. '%' */ + _ACPI_PU, /* 0x26 38. '&' */ + _ACPI_PU, /* 0x27 39. ''' */ + _ACPI_PU, /* 0x28 40. '(' */ + _ACPI_PU, /* 0x29 41. ')' */ + _ACPI_PU, /* 0x2A 42. '*' */ + _ACPI_PU, /* 0x2B 43. '+' */ + _ACPI_PU, /* 0x2C 44. ',' */ + _ACPI_PU, /* 0x2D 45. '-' */ + _ACPI_PU, /* 0x2E 46. '.' */ + _ACPI_PU, /* 0x2F 47. '/' */ + _ACPI_XD|_ACPI_DI, /* 0x30 48. '0' */ + _ACPI_XD|_ACPI_DI, /* 0x31 49. '1' */ + _ACPI_XD|_ACPI_DI, /* 0x32 50. '2' */ + _ACPI_XD|_ACPI_DI, /* 0x33 51. '3' */ + _ACPI_XD|_ACPI_DI, /* 0x34 52. '4' */ + _ACPI_XD|_ACPI_DI, /* 0x35 53. '5' */ + _ACPI_XD|_ACPI_DI, /* 0x36 54. '6' */ + _ACPI_XD|_ACPI_DI, /* 0x37 55. '7' */ + _ACPI_XD|_ACPI_DI, /* 0x38 56. '8' */ + _ACPI_XD|_ACPI_DI, /* 0x39 57. '9' */ + _ACPI_PU, /* 0x3A 58. ':' */ + _ACPI_PU, /* 0x3B 59. ';' */ + _ACPI_PU, /* 0x3C 60. '<' */ + _ACPI_PU, /* 0x3D 61. '=' */ + _ACPI_PU, /* 0x3E 62. '>' */ + _ACPI_PU, /* 0x3F 63. '?' */ + _ACPI_PU, /* 0x40 64. '@' */ + _ACPI_XD|_ACPI_UP, /* 0x41 65. 'A' */ + _ACPI_XD|_ACPI_UP, /* 0x42 66. 'B' */ + _ACPI_XD|_ACPI_UP, /* 0x43 67. 'C' */ + _ACPI_XD|_ACPI_UP, /* 0x44 68. 'D' */ + _ACPI_XD|_ACPI_UP, /* 0x45 69. 'E' */ + _ACPI_XD|_ACPI_UP, /* 0x46 70. 'F' */ + _ACPI_UP, /* 0x47 71. 'G' */ + _ACPI_UP, /* 0x48 72. 'H' */ + _ACPI_UP, /* 0x49 73. 'I' */ + _ACPI_UP, /* 0x4A 74. 'J' */ + _ACPI_UP, /* 0x4B 75. 'K' */ + _ACPI_UP, /* 0x4C 76. 'L' */ + _ACPI_UP, /* 0x4D 77. 'M' */ + _ACPI_UP, /* 0x4E 78. 'N' */ + _ACPI_UP, /* 0x4F 79. 'O' */ + _ACPI_UP, /* 0x50 80. 'P' */ + _ACPI_UP, /* 0x51 81. 'Q' */ + _ACPI_UP, /* 0x52 82. 'R' */ + _ACPI_UP, /* 0x53 83. 'S' */ + _ACPI_UP, /* 0x54 84. 'T' */ + _ACPI_UP, /* 0x55 85. 'U' */ + _ACPI_UP, /* 0x56 86. 'V' */ + _ACPI_UP, /* 0x57 87. 'W' */ + _ACPI_UP, /* 0x58 88. 'X' */ + _ACPI_UP, /* 0x59 89. 'Y' */ + _ACPI_UP, /* 0x5A 90. 'Z' */ + _ACPI_PU, /* 0x5B 91. '[' */ + _ACPI_PU, /* 0x5C 92. '\' */ + _ACPI_PU, /* 0x5D 93. ']' */ + _ACPI_PU, /* 0x5E 94. '^' */ + _ACPI_PU, /* 0x5F 95. '_' */ + _ACPI_PU, /* 0x60 96. '`' */ + _ACPI_XD|_ACPI_LO, /* 0x61 97. 'a' */ + _ACPI_XD|_ACPI_LO, /* 0x62 98. 'b' */ + _ACPI_XD|_ACPI_LO, /* 0x63 99. 'c' */ + _ACPI_XD|_ACPI_LO, /* 0x64 100. 'd' */ + _ACPI_XD|_ACPI_LO, /* 0x65 101. 'e' */ + _ACPI_XD|_ACPI_LO, /* 0x66 102. 'f' */ + _ACPI_LO, /* 0x67 103. 'g' */ + _ACPI_LO, /* 0x68 104. 'h' */ + _ACPI_LO, /* 0x69 105. 'i' */ + _ACPI_LO, /* 0x6A 106. 'j' */ + _ACPI_LO, /* 0x6B 107. 'k' */ + _ACPI_LO, /* 0x6C 108. 'l' */ + _ACPI_LO, /* 0x6D 109. 'm' */ + _ACPI_LO, /* 0x6E 110. 'n' */ + _ACPI_LO, /* 0x6F 111. 'o' */ + _ACPI_LO, /* 0x70 112. 'p' */ + _ACPI_LO, /* 0x71 113. 'q' */ + _ACPI_LO, /* 0x72 114. 'r' */ + _ACPI_LO, /* 0x73 115. 's' */ + _ACPI_LO, /* 0x74 116. 't' */ + _ACPI_LO, /* 0x75 117. 'u' */ + _ACPI_LO, /* 0x76 118. 'v' */ + _ACPI_LO, /* 0x77 119. 'w' */ + _ACPI_LO, /* 0x78 120. 'x' */ + _ACPI_LO, /* 0x79 121. 'y' */ + _ACPI_LO, /* 0x7A 122. 'z' */ + _ACPI_PU, /* 0x7B 123. '{' */ + _ACPI_PU, /* 0x7C 124. '|' */ + _ACPI_PU, /* 0x7D 125. '}' */ + _ACPI_PU, /* 0x7E 126. '~' */ + _ACPI_CN, /* 0x7F 127. */ + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 to 0x8F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90 to 0x9F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA0 to 0xAF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB0 to 0xBF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC0 to 0xCF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD0 to 0xDF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE0 to 0xEF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100 */ +}; + +#define IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) +#define IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) +#define IS_DIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI)) +#define IS_SPACE(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP)) +#define IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_to_upper + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Convert character to uppercase + * + ******************************************************************************/ + +u32 +acpi_cm_to_upper ( + u32 c) +{ + + return (IS_LOWER(c) ? ((c)-0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_to_lower + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: Convert character to lowercase + * + ******************************************************************************/ + +u32 +acpi_cm_to_lower ( + u32 c) +{ + + return (IS_UPPER(c) ? ((c)+0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: strupr + * + * PARAMETERS: Src_string - The source string to convert to + * + * RETURN: Src_string + * + * DESCRIPTION: Convert string to uppercase + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_cm_strupr ( + NATIVE_CHAR *src_string) +{ + NATIVE_CHAR *string; + + + /* Walk entire string, uppercasing the letters */ + + for (string = src_string; *string; ) { + *string = (char) acpi_cm_to_upper (*string); + string++; + } + + + return (src_string); +} + + +/******************************************************************************* + * + * FUNCTION: strstr + * + * PARAMETERS: String1 - + * String2 + * + * RETURN: + * + * DESCRIPTION: Checks if String2 occurs in String1. This is not really a + * full implementation of strstr, only sufficient for command + * matching + * + ******************************************************************************/ + +NATIVE_CHAR * +acpi_cm_strstr ( + NATIVE_CHAR *string1, + NATIVE_CHAR *string2) +{ + NATIVE_CHAR *string; + + + if (acpi_cm_strlen (string2) > acpi_cm_strlen (string1)) { + return (NULL); + } + + /* Walk entire string, comparing the letters */ + + for (string = string1; *string2; ) { + if (*string2 != *string) { + return (NULL); + } + + string2++; + string++; + } + + + return (string1); +} + + +/******************************************************************************* + * + * FUNCTION: strtoul + * + * PARAMETERS: String - Null terminated string + * Terminater - Where a pointer to the terminating byte is returned + * Base - Radix of the string + * + * RETURN: Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. + * + ******************************************************************************/ + +NATIVE_UINT +acpi_cm_strtoul ( + const NATIVE_CHAR *string, + NATIVE_CHAR **terminator, + NATIVE_UINT base) +{ + u32 converted = 0; + u32 index; + u32 sign; + const NATIVE_CHAR *string_start; + NATIVE_UINT return_value = 0; + ACPI_STATUS status = AE_OK; + + + /* + * Save the value of the pointer to the buffer's first + * character, save the current errno value, and then + * skip over any white space in the buffer: + */ + string_start = string; + while (IS_SPACE (*string) || *string == '\t') { + ++string; + } + + /* + * The buffer may contain an optional plus or minus sign. + * If it does, then skip over it but remember what is was: + */ + if (*string == '-') { + sign = NEGATIVE; + ++string; + } + + else if (*string == '+') { + ++string; + sign = POSITIVE; + } + + else { + sign = POSITIVE; + } + + /* + * If the input parameter Base is zero, then we need to + * determine if it is octal, decimal, or hexadecimal: + */ + if (base == 0) { + if (*string == '0') { + if (acpi_cm_to_lower (*(++string)) == 'x') { + base = 16; + ++string; + } + + else { + base = 8; + } + } + + else { + base = 10; + } + } + + else if (base < 2 || base > 36) { + /* + * The specified Base parameter is not in the domain of + * this function: + */ + goto done; + } + + /* + * For octal and hexadecimal bases, skip over the leading + * 0 or 0x, if they are present. + */ + if (base == 8 && *string == '0') { + string++; + } + + if (base == 16 && + *string == '0' && + acpi_cm_to_lower (*(++string)) == 'x') { + string++; + } + + + /* + * Main loop: convert the string to an unsigned long: + */ + while (*string) { + if (IS_DIGIT (*string)) { + index = *string - '0'; + } + + else { + index = acpi_cm_to_upper (*string); + if (IS_UPPER (index)) { + index = index - 'A' + 10; + } + + else { + goto done; + } + } + + if (index >= base) { + goto done; + } + + /* + * Check to see if value is out of range: + */ + + if (return_value > ((ACPI_UINT32_MAX - (u32) index) / + (u32) base)) { + status = AE_ERROR; + return_value = 0L; /* reset */ + } + + else { + return_value *= base; + return_value += index; + converted = 1; + } + + ++string; + } + +done: + /* + * If appropriate, update the caller's pointer to the next + * unconverted character in the buffer. + */ + if (terminator) { + if (converted == 0 && return_value == 0L && string != NULL) { + *terminator = (NATIVE_CHAR *) string_start; + } + + else { + *terminator = (NATIVE_CHAR *) string; + } + } + + if (status == AE_ERROR) { + return_value = ACPI_UINT32_MAX; + } + + /* + * If a minus sign was present, then "the conversion is negated": + */ + if (sign == NEGATIVE) { + return_value = (ACPI_UINT32_MAX - return_value) + 1; + } + + return (return_value); +} + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + diff --git a/drivers/bus/acpi/utils/cmcopy.c b/drivers/bus/acpi/utils/cmcopy.c new file mode 100644 index 0000000..6cbe8d7 --- /dev/null +++ b/drivers/bus/acpi/utils/cmcopy.c @@ -0,0 +1,707 @@ +/****************************************************************************** + * + * Module Name: cmcopy - Internal to external object translation utilities + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmcopy") + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_isimple_to_esimple + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Buffer - Where the object is returned + * *Space_used - Where the data length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a simple object in a user + * buffer. + * + * The buffer is assumed to have sufficient space for the object. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_cm_copy_isimple_to_esimple ( + ACPI_OPERAND_OBJECT *internal_object, + ACPI_OBJECT *external_object, + u8 *data_space, + u32 *buffer_space_used) +{ + u32 length = 0; + ACPI_STATUS status = AE_OK; + + + /* + * Check for NULL object case (could be an uninitialized + * package element + */ + + if (!internal_object) { + *buffer_space_used = 0; + return (AE_OK); + } + + /* Always clear the external object */ + + MEMSET (external_object, 0, sizeof (ACPI_OBJECT)); + + /* + * In general, the external object will be the same type as + * the internal object + */ + + external_object->type = internal_object->common.type; + + /* However, only a limited number of external types are supported */ + + switch (internal_object->common.type) { + + case ACPI_TYPE_STRING: + + length = internal_object->string.length + 1; + external_object->string.length = internal_object->string.length; + external_object->string.pointer = (NATIVE_CHAR *) data_space; + MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, length); + break; + + + case ACPI_TYPE_BUFFER: + + length = internal_object->buffer.length; + external_object->buffer.length = internal_object->buffer.length; + external_object->buffer.pointer = data_space; + MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer, length); + break; + + + case ACPI_TYPE_INTEGER: + + external_object->integer.value= internal_object->integer.value; + break; + + + case INTERNAL_TYPE_REFERENCE: + + /* + * This is an object reference. Attempt to dereference it. + */ + + switch (internal_object->reference.opcode) { + case AML_ZERO_OP: + external_object->type = ACPI_TYPE_INTEGER; + external_object->integer.value = 0; + break; + + case AML_ONE_OP: + external_object->type = ACPI_TYPE_INTEGER; + external_object->integer.value = 1; + break; + + case AML_ONES_OP: + external_object->type = ACPI_TYPE_INTEGER; + external_object->integer.value = ACPI_INTEGER_MAX; + break; + + case AML_NAMEPATH_OP: + /* + * This is a named reference, get the string. We already know that + * we have room for it, use max length + */ + length = MAX_STRING_LENGTH; + external_object->type = ACPI_TYPE_STRING; + external_object->string.pointer = (NATIVE_CHAR *) data_space; + status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) internal_object->reference.node, + &length, (char *) data_space); + + /* Converted (external) string length is returned from above */ + + external_object->string.length = length; + break; + + default: + /* + * Use the object type of "Any" to indicate a reference + * to object containing a handle to an ACPI named object. + */ + external_object->type = ACPI_TYPE_ANY; + external_object->reference.handle = internal_object->reference.node; + break; + } + break; + + + case ACPI_TYPE_PROCESSOR: + + external_object->processor.proc_id = internal_object->processor.proc_id; + external_object->processor.pblk_address = internal_object->processor.address; + external_object->processor.pblk_length = internal_object->processor.length; + break; + + + case ACPI_TYPE_POWER: + + external_object->power_resource.system_level = + internal_object->power_resource.system_level; + + external_object->power_resource.resource_order = + internal_object->power_resource.resource_order; + break; + + + default: + /* + * There is no corresponding external object type + */ + return (AE_SUPPORT); + break; + } + + + *buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_ielement_to_eelement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_copy_ielement_to_eelement ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context; + u32 object_space; + u32 this_index; + ACPI_OBJECT *target_object; + + + this_index = state->pkg.index; + target_object = (ACPI_OBJECT *) + &((ACPI_OBJECT *)(state->pkg.dest_object))->package.elements[this_index]; + + + switch (object_type) { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * This is a simple or null object -- get the size + */ + + status = acpi_cm_copy_isimple_to_esimple (source_object, + target_object, info->free_space, &object_space); + if (ACPI_FAILURE (status)) { + return (status); + } + + break; + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * Build the package object + */ + target_object->type = ACPI_TYPE_PACKAGE; + target_object->package.count = source_object->package.count; + target_object->package.elements = (ACPI_OBJECT *) info->free_space; + + /* + * Pass the new package object back to the package walk routine + */ + state->pkg.this_target_obj = target_object; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + object_space = (u32) ROUND_UP_TO_NATIVE_WORD ( + target_object->package.count * sizeof (ACPI_OBJECT)); + break; + + default: + return (AE_BAD_PARAMETER); + } + + + info->free_space += object_space; + info->length += object_space; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_ipackage_to_epackage + * + * PARAMETERS: *Internal_object - Pointer to the object we are returning + * *Buffer - Where the object is returned + * *Space_used - Where the object length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * Acpi_cm_get_object_size function before calling this function. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_cm_copy_ipackage_to_epackage ( + ACPI_OPERAND_OBJECT *internal_object, + u8 *buffer, + u32 *space_used) +{ + ACPI_OBJECT *external_object; + ACPI_STATUS status; + ACPI_PKG_INFO info; + + + /* + * First package at head of the buffer + */ + external_object = (ACPI_OBJECT *) buffer; + + /* + * Free space begins right after the first package + */ + info.length = 0; + info.object_space = 0; + info.num_packages = 1; + info.free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + + external_object->type = internal_object->common.type; + external_object->package.count = internal_object->package.count; + external_object->package.elements = (ACPI_OBJECT *) info.free_space; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + info.free_space += external_object->package.count * + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + + status = acpi_cm_walk_package_tree (internal_object, external_object, + acpi_cm_copy_ielement_to_eelement, &info); + + *space_used = info.length; + + return (status); + +} + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_iobject_to_eobject + * + * PARAMETERS: *Internal_object - The internal object to be converted + * *Buffer_ptr - Where the object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to build an API object to be returned to + * the caller. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_copy_iobject_to_eobject ( + ACPI_OPERAND_OBJECT *internal_object, + ACPI_BUFFER *ret_buffer) +{ + ACPI_STATUS status; + + + if (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)) { + /* + * Package object: Copy all subobjects (including + * nested packages) + */ + status = acpi_cm_copy_ipackage_to_epackage (internal_object, + ret_buffer->pointer, &ret_buffer->length); + } + + else { + /* + * Build a simple object (no nested objects) + */ + status = acpi_cm_copy_isimple_to_esimple (internal_object, + (ACPI_OBJECT *) ret_buffer->pointer, + ((u8 *) ret_buffer->pointer + + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))), + &ret_buffer->length); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + ret_buffer->length += sizeof (ACPI_OBJECT); + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_esimple_to_isimple + * + * PARAMETERS: *External_object - The external object to be converted + * *Internal_object - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function copies an external object to an internal one. + * NOTE: Pointers can be copied, we don't need to copy data. + * (The pointers have to be valid in our address space no matter + * what we do with them!) + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_copy_esimple_to_isimple ( + ACPI_OBJECT *external_object, + ACPI_OPERAND_OBJECT *internal_object) +{ + + + internal_object->common.type = (u8) external_object->type; + + switch (external_object->type) { + + case ACPI_TYPE_STRING: + + internal_object->string.length = external_object->string.length; + internal_object->string.pointer = external_object->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + internal_object->buffer.length = external_object->buffer.length; + internal_object->buffer.pointer = external_object->buffer.pointer; + break; + + + case ACPI_TYPE_INTEGER: + /* + * Number is included in the object itself + */ + internal_object->integer.value = external_object->integer.value; + break; + + + default: + return (AE_CTRL_RETURN_VALUE); + break; + } + + + return (AE_OK); +} + + +#ifdef ACPI_FUTURE_IMPLEMENTATION + +/* Code to convert packages that are parameters to control methods */ + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_epackage_to_ipackage + * + * PARAMETERS: *Internal_object - Pointer to the object we are returning + * *Buffer - Where the object is returned + * *Space_used - Where the length of the object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using the + * Acpi_cm_get_object_size function before calling this function. + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_cm_copy_epackage_to_ipackage ( + ACPI_OPERAND_OBJECT *internal_object, + u8 *buffer, + u32 *space_used) +{ + u8 *free_space; + ACPI_OBJECT *external_object; + u32 length = 0; + u32 this_index; + u32 object_space = 0; + ACPI_OPERAND_OBJECT *this_internal_obj; + ACPI_OBJECT *this_external_obj; + + + /* + * First package at head of the buffer + */ + external_object = (ACPI_OBJECT *)buffer; + + /* + * Free space begins right after the first package + */ + free_space = buffer + sizeof(ACPI_OBJECT); + + + external_object->type = internal_object->common.type; + external_object->package.count = internal_object->package.count; + external_object->package.elements = (ACPI_OBJECT *)free_space; + + + /* + * Build an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + + free_space += external_object->package.count * sizeof(ACPI_OBJECT); + + + /* Call Walk_package */ + +} + +#endif /* Future implementation */ + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_eobject_to_iobject + * + * PARAMETERS: *Internal_object - The external object to be converted + * *Buffer_ptr - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Converts an external object to an internal object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_copy_eobject_to_iobject ( + ACPI_OBJECT *external_object, + ACPI_OPERAND_OBJECT *internal_object) +{ + ACPI_STATUS status; + + + if (external_object->type == ACPI_TYPE_PACKAGE) { + /* + * Package objects contain other objects (which can be objects) + * buildpackage does it all + * + * TBD: Package conversion must be completed and tested + * NOTE: this code converts packages as input parameters to + * control methods only. This is a very, very rare case. + */ +/* + Status = Acpi_cm_copy_epackage_to_ipackage(Internal_object, + Ret_buffer->Pointer, + &Ret_buffer->Length); +*/ + return (AE_NOT_IMPLEMENTED); + } + + else { + /* + * Build a simple object (no nested objects) + */ + status = acpi_cm_copy_esimple_to_isimple (external_object, internal_object); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_ielement_to_ielement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_copy_ielement_to_ielement ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context) +{ + ACPI_STATUS status = AE_OK; + u32 this_index; + ACPI_OPERAND_OBJECT **this_target_ptr; + ACPI_OPERAND_OBJECT *target_object; + + + this_index = state->pkg.index; + this_target_ptr = (ACPI_OPERAND_OBJECT **) + &state->pkg.dest_object->package.elements[this_index]; + + switch (object_type) { + case 0: + + /* + * This is a simple object, just copy it + */ + target_object = acpi_cm_create_internal_object (source_object->common.type); + if (!target_object) { + return (AE_NO_MEMORY); + } + + status = acpi_aml_store_object_to_object (source_object, target_object, + (ACPI_WALK_STATE *) context); + if (ACPI_FAILURE (status)) { + return (status); + } + + *this_target_ptr = target_object; + break; + + + case 1: + /* + * This object is a package - go down another nesting level + * Create and build the package object + */ + target_object = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE); + if (!target_object) { + /* TBD: must delete package created up to this point */ + + return (AE_NO_MEMORY); + } + + target_object->package.count = source_object->package.count; + + /* + * Pass the new package object back to the package walk routine + */ + state->pkg.this_target_obj = target_object; + + /* + * Store the object pointer in the parent package object + */ + *this_target_ptr = target_object; + break; + + default: + return (AE_BAD_PARAMETER); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_copy_ipackage_to_ipackage + * + * PARAMETERS: *Source_obj - Pointer to the source package object + * *Dest_obj - Where the internal object is returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to copy an internal package object + * into another internal package object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_copy_ipackage_to_ipackage ( + ACPI_OPERAND_OBJECT *source_obj, + ACPI_OPERAND_OBJECT *dest_obj, + ACPI_WALK_STATE *walk_state) +{ + ACPI_STATUS status = AE_OK; + + + dest_obj->common.type = source_obj->common.type; + dest_obj->package.count = source_obj->package.count; + + + /* + * Create the object array and walk the source package tree + */ + + dest_obj->package.elements = acpi_cm_callocate ((source_obj->package.count + 1) * + sizeof (void *)); + dest_obj->package.next_element = dest_obj->package.elements; + + if (!dest_obj->package.elements) { + REPORT_ERROR ( + ("Aml_build_copy_internal_package_object: Package allocation failure\n")); + return (AE_NO_MEMORY); + } + + + status = acpi_cm_walk_package_tree (source_obj, dest_obj, + acpi_cm_copy_ielement_to_ielement, walk_state); + + return (status); +} + diff --git a/drivers/bus/acpi/utils/cmdebug.c b/drivers/bus/acpi/utils/cmdebug.c new file mode 100644 index 0000000..8f2df33 --- /dev/null +++ b/drivers/bus/acpi/utils/cmdebug.c @@ -0,0 +1,555 @@ +/****************************************************************************** + * + * Module Name: cmdebug - Debug print routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmdebug") + + +/***************************************************************************** + * + * FUNCTION: Get/Set debug level + * + * DESCRIPTION: Get or set value of the debug flag + * + * These are used to allow user's to get/set the debug level + * + ****************************************************************************/ + + +u32 +get_debug_level (void) +{ + + return (acpi_dbg_level); +} + +void +set_debug_level ( + u32 new_debug_level) +{ + + acpi_dbg_level = new_debug_level; +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name) +{ + + acpi_gbl_nesting_level++; + + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s\n", + acpi_gbl_nesting_level, function_name); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_ptr + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Pointer - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_ptr ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + void *pointer) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %p\n", + acpi_gbl_nesting_level, function_name, pointer); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_str + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * String - Additional string to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_str ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + NATIVE_CHAR *string) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %s\n", + acpi_gbl_nesting_level, function_name, string); +} + + +/***************************************************************************** + * + * FUNCTION: Function_trace_u32 + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Integer - Integer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_trace_u32 ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u32 integer) +{ + + acpi_gbl_nesting_level++; + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Entered Function: %s, %lX\n", + acpi_gbl_nesting_level, function_name, integer); +} + + +/***************************************************************************** + * + * FUNCTION: Function_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level + * + ****************************************************************************/ + +void +function_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s\n", + acpi_gbl_nesting_level, function_name); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_status_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Status - Exit status code + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit status also. + * + ****************************************************************************/ + +void +function_status_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_STATUS status) +{ + + debug_print (module_name, line_number, component_id, + TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %s\n", + acpi_gbl_nesting_level, + function_name, + acpi_cm_format_exception (status)); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_value_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit value also. + * + ****************************************************************************/ + +void +function_value_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + ACPI_INTEGER value) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %X\n", + acpi_gbl_nesting_level, function_name, value); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Function_ptr_exit + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Function_name - Name of Caller's function + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in Debug_level. Prints exit value also. + * + ****************************************************************************/ + +void +function_ptr_exit ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + NATIVE_CHAR *function_name, + u8 *ptr) +{ + + debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS, + " %2.2ld Exiting Function: %s, %p\n", + acpi_gbl_nesting_level, function_name, ptr); + + acpi_gbl_nesting_level--; +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Print_level - Requested debug print level + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message with prefix consisting of the module name, + * line number, and component ID. + * + ****************************************************************************/ + +void +debug_print ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + u32 print_level, + NATIVE_CHAR *format, + ...) +{ + va_list args; + + + /* Both the level and the component must be enabled */ + + if ((print_level & acpi_dbg_level) && + (component_id & acpi_dbg_layer)) { + va_start (args, format); + + acpi_os_printf ("%8s-%04d: ", module_name, line_number); + acpi_os_vprintf (format, args); + } +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print_prefix + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * + * RETURN: None + * + * DESCRIPTION: Print the prefix part of an error message, consisting of the + * module name, and line number + * + ****************************************************************************/ + +void +debug_print_prefix ( + NATIVE_CHAR *module_name, + u32 line_number) +{ + + + acpi_os_printf ("%8s-%04d: ", module_name, line_number); +} + + +/***************************************************************************** + * + * FUNCTION: Debug_print_raw + * + * PARAMETERS: Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message -- without module/line indentifiers + * + ****************************************************************************/ + +void +debug_print_raw ( + NATIVE_CHAR *format, + ...) +{ + va_list args; + + + va_start (args, format); + + acpi_os_vprintf (format, args); + + va_end (args); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_dump_buffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Component_iD - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ****************************************************************************/ + +void +acpi_cm_dump_buffer ( + u8 *buffer, + u32 count, + u32 display, + u32 component_id) +{ + u32 i = 0; + u32 j; + u32 temp32; + u8 buf_char; + + + /* Only dump the buffer if tracing is enabled */ + + if (!((TRACE_TABLES & acpi_dbg_level) && + (component_id & acpi_dbg_layer))) { + return; + } + + + /* + * Nasty little dump buffer routine! + */ + while (i < count) { + /* Print current offset */ + + acpi_os_printf ("%05X ", i); + + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) { + if (i + j >= count) { + acpi_os_printf ("\n"); + return; + } + + /* Make sure that the s8 doesn't get sign-extended! */ + + switch (display) { + /* Default is BYTE display */ + + default: + + acpi_os_printf ("%02X ", + *((u8 *) &buffer[i + j])); + j += 1; + break; + + + case DB_WORD_DISPLAY: + + MOVE_UNALIGNED16_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%04X ", temp32); + j += 2; + break; + + + case DB_DWORD_DISPLAY: + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%08X ", temp32); + j += 4; + break; + + + case DB_QWORD_DISPLAY: + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j]); + acpi_os_printf ("%08X", temp32); + + MOVE_UNALIGNED32_TO_32 (&temp32, + &buffer[i + j + 4]); + acpi_os_printf ("%08X ", temp32); + j += 8; + break; + } + } + + + /* + * Print the ASCII equivalent characters + * But watch out for the bad unprintable ones... + */ + + for (j = 0; j < 16; j++) { + if (i + j >= count) { + acpi_os_printf ("\n"); + return; + } + + buf_char = buffer[i + j]; + if ((buf_char > 0x1F && buf_char < 0x2E) || + (buf_char > 0x2F && buf_char < 0x61) || + (buf_char > 0x60 && buf_char < 0x7F)) { + acpi_os_printf ("%c", buf_char); + } + else { + acpi_os_printf ("."); + } + } + + /* Done with that line. */ + + acpi_os_printf ("\n"); + i += 16; + } + + return; +} + + diff --git a/drivers/bus/acpi/utils/cmdelete.c b/drivers/bus/acpi/utils/cmdelete.c new file mode 100644 index 0000000..ebd5cc5 --- /dev/null +++ b/drivers/bus/acpi/utils/cmdelete.c @@ -0,0 +1,589 @@ +/******************************************************************************* + * + * Module Name: cmdelete - object deletion and reference count utilities + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acparser.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmdelete") + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_internal_obj + * + * PARAMETERS: *Object - Pointer to the list to be deleted + * + * RETURN: None + * + * DESCRIPTION: Low level object deletion, after reference counts have been + * updated (All reference counts, including sub-objects!) + * + ******************************************************************************/ + +void +acpi_cm_delete_internal_obj ( + ACPI_OPERAND_OBJECT *object) +{ + void *obj_pointer = NULL; + ACPI_OPERAND_OBJECT *handler_desc; + + + if (!object) { + return; + } + + /* + * Must delete or free any pointers within the object that are not + * actual ACPI objects (for example, a raw buffer pointer). + */ + + switch (object->common.type) { + + case ACPI_TYPE_STRING: + + /* Free the actual string buffer */ + + obj_pointer = object->string.pointer; + break; + + + case ACPI_TYPE_BUFFER: + + /* Free the actual buffer */ + + obj_pointer = object->buffer.pointer; + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * Elements of the package are not handled here, they are deleted + * separately + */ + + /* Free the (variable length) element pointer array */ + + obj_pointer = object->package.elements; + break; + + + case ACPI_TYPE_MUTEX: + + acpi_aml_unlink_mutex (object); + acpi_os_delete_semaphore (object->mutex.semaphore); + break; + + + case ACPI_TYPE_EVENT: + + acpi_os_delete_semaphore (object->event.semaphore); + object->event.semaphore = NULL; + break; + + + case ACPI_TYPE_METHOD: + + /* Delete the method semaphore if it exists */ + + if (object->method.semaphore) { + acpi_os_delete_semaphore (object->method.semaphore); + object->method.semaphore = NULL; + } + + break; + + + case ACPI_TYPE_REGION: + + + if (object->region.extra) { + /* + * Free the Region_context if and only if the handler is one of the + * default handlers -- and therefore, we created the context object + * locally, it was not created by an external caller. + */ + handler_desc = object->region.addr_handler; + if ((handler_desc) && + (handler_desc->addr_handler.hflags == ADDR_HANDLER_DEFAULT_INSTALLED)) { + obj_pointer = object->region.extra->extra.region_context; + } + + /* Now we can free the Extra object */ + + acpi_cm_delete_object_desc (object->region.extra); + } + break; + + + case ACPI_TYPE_FIELD_UNIT: + + if (object->field_unit.extra) { + acpi_cm_delete_object_desc (object->field_unit.extra); + } + break; + + default: + break; + } + + + /* + * Delete any allocated memory found above + */ + + if (obj_pointer) { + if (!acpi_tb_system_table_pointer (obj_pointer)) { + acpi_cm_free (obj_pointer); + } + } + + + /* Only delete the object if it was dynamically allocated */ + + + if (!(object->common.flags & AOPOBJ_STATIC_ALLOCATION)) { + acpi_cm_delete_object_desc (object); + + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_internal_object_list + * + * PARAMETERS: *Obj_list - Pointer to the list to be deleted + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function deletes an internal object list, including both + * simple objects and package objects + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_delete_internal_object_list ( + ACPI_OPERAND_OBJECT **obj_list) +{ + ACPI_OPERAND_OBJECT **internal_obj; + + + /* Walk the null-terminated internal list */ + + for (internal_obj = obj_list; *internal_obj; internal_obj++) { + /* + * Check for a package + * Simple objects are simply stored in the array and do not + * need to be deleted separately. + */ + + if (IS_THIS_OBJECT_TYPE ((*internal_obj), ACPI_TYPE_PACKAGE)) { + /* Delete the package */ + + /* + * TBD: [Investigate] This might not be the right thing to do, + * depending on how the internal package object was allocated!!! + */ + acpi_cm_delete_internal_obj (*internal_obj); + } + + } + + /* Free the combined parameter pointer list and object array */ + + acpi_cm_free (obj_list); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_update_ref_count + * + * PARAMETERS: *Object - Object whose ref count is to be updated + * Action - What to do + * + * RETURN: New ref count + * + * DESCRIPTION: Modify the ref count and return it. + * + ******************************************************************************/ + +static void +acpi_cm_update_ref_count ( + ACPI_OPERAND_OBJECT *object, + u32 action) +{ + u16 count; + u16 new_count; + + + if (!object) { + return; + } + + + count = object->common.reference_count; + new_count = count; + + /* + * Reference count action (increment, decrement, or force delete) + */ + + switch (action) { + + case REF_INCREMENT: + + new_count++; + object->common.reference_count = new_count; + + break; + + + case REF_DECREMENT: + + if (count < 1) { + new_count = 0; + } + + else { + new_count--; + + } + + + object->common.reference_count = new_count; + if (new_count == 0) { + acpi_cm_delete_internal_obj (object); + } + + break; + + + case REF_FORCE_DELETE: + + new_count = 0; + object->common.reference_count = new_count; + acpi_cm_delete_internal_obj (object); + break; + + + default: + + break; + } + + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_update_object_reference + * + * PARAMETERS: *Object - Increment ref count for this object + * and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT or + * REF_FORCE_DELETE + * + * RETURN: Status + * + * DESCRIPTION: Increment the object reference count + * + * Object references are incremented when: + * 1) An object is attached to a Node (namespace object) + * 2) An object is copied (all subobjects must be incremented) + * + * Object references are decremented when: + * 1) An object is detached from an Node + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_update_object_reference ( + ACPI_OPERAND_OBJECT *object, + u16 action) +{ + ACPI_STATUS status; + u32 i; + ACPI_OPERAND_OBJECT *next; + ACPI_OPERAND_OBJECT *new; + ACPI_GENERIC_STATE *state_list = NULL; + ACPI_GENERIC_STATE *state; + + + /* Ignore a null object ptr */ + + if (!object) { + return (AE_OK); + } + + + /* + * Make sure that this isn't a namespace handle or an AML pointer + */ + + if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) { + return (AE_OK); + } + + if (acpi_tb_system_table_pointer (object)) { + return (AE_OK); + } + + + state = acpi_cm_create_update_state (object, action); + + while (state) { + + object = state->update.object; + action = state->update.value; + acpi_cm_delete_generic_state (state); + + /* + * All sub-objects must have their reference count incremented also. + * Different object types have different subobjects. + */ + switch (object->common.type) { + + case ACPI_TYPE_DEVICE: + + status = acpi_cm_create_update_state_and_push (object->device.addr_handler, + action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + acpi_cm_update_ref_count (object->device.sys_handler, action); + acpi_cm_update_ref_count (object->device.drv_handler, action); + break; + + + case INTERNAL_TYPE_ADDRESS_HANDLER: + + /* Must walk list of address handlers */ + + next = object->addr_handler.next; + while (next) { + new = next->addr_handler.next; + acpi_cm_update_ref_count (next, action); + + next = new; + } + break; + + + case ACPI_TYPE_PACKAGE: + + /* + * We must update all the sub-objects of the package + * (Each of whom may have their own sub-objects, etc. + */ + for (i = 0; i < object->package.count; i++) { + /* + * Push each element onto the stack for later processing. + * Note: There can be null elements within the package, + * these are simply ignored + */ + + status = acpi_cm_create_update_state_and_push ( + object->package.elements[i], action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + } + break; + + + case ACPI_TYPE_FIELD_UNIT: + + status = acpi_cm_create_update_state_and_push ( + object->field_unit.container, action, &state_list); + + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_DEF_FIELD: + + status = acpi_cm_create_update_state_and_push ( + object->field.container, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case INTERNAL_TYPE_BANK_FIELD: + + status = acpi_cm_create_update_state_and_push ( + object->bank_field.bank_select, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + + status = acpi_cm_create_update_state_and_push ( + object->bank_field.container, action, &state_list); + if (ACPI_FAILURE (status)) { + return (status); + } + break; + + + case ACPI_TYPE_REGION: + + /* TBD: [Investigate] + Acpi_cm_update_ref_count (Object->Region.Addr_handler, Action); + */ +/* + Status = + Acpi_cm_create_update_state_and_push (Object->Region.Addr_handler, + Action, &State_list); + if (ACPI_FAILURE (Status)) + { + return (Status); + } +*/ + break; + + + case INTERNAL_TYPE_REFERENCE: + + break; + } + + + /* + * Now we can update the count in the main object. This can only + * happen after we update the sub-objects in case this causes the + * main object to be deleted. + */ + + acpi_cm_update_ref_count (object, action); + + + /* Move on to the next object to be updated */ + + state = acpi_cm_pop_generic_state (&state_list); + } + + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_add_reference + * + * PARAMETERS: *Object - Object whose reference count is to be + * incremented + * + * RETURN: None + * + * DESCRIPTION: Add one reference to an ACPI object + * + ******************************************************************************/ + +void +acpi_cm_add_reference ( + ACPI_OPERAND_OBJECT *object) +{ + + + /* + * Ensure that we have a valid object + */ + + if (!acpi_cm_valid_internal_object (object)) { + return; + } + + /* + * We have a valid ACPI internal object, now increment the reference count + */ + + acpi_cm_update_object_reference (object, REF_INCREMENT); + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_remove_reference + * + * PARAMETERS: *Object - Object whose ref count will be decremented + * + * RETURN: None + * + * DESCRIPTION: Decrement the reference count of an ACPI internal object + * + ******************************************************************************/ + +void +acpi_cm_remove_reference ( + ACPI_OPERAND_OBJECT *object) +{ + + + /* + * Ensure that we have a valid object + */ + + if (!acpi_cm_valid_internal_object (object)) { + return; + } + + /* + * Decrement the reference count, and only actually delete the object + * if the reference count becomes 0. (Must also decrement the ref count + * of all subobjects!) + */ + + acpi_cm_update_object_reference (object, REF_DECREMENT); + + return; +} + + diff --git a/drivers/bus/acpi/utils/cmeval.c b/drivers/bus/acpi/utils/cmeval.c new file mode 100644 index 0000000..d2c4ac7 --- /dev/null +++ b/drivers/bus/acpi/utils/cmeval.c @@ -0,0 +1,306 @@ +/****************************************************************************** + * + * Module Name: cmeval - Object evaluation + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acnamesp.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmeval") + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_evaluate_numeric_object + * + * PARAMETERS: *Object_name - Object name to be evaluated + * Device_node - Node for the device + * *Address - Where the value is returned + * + * RETURN: Status + * + * DESCRIPTION: evaluates a numeric namespace object for a selected device + * and stores results in *Address. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_evaluate_numeric_object ( + NATIVE_CHAR *object_name, + ACPI_NAMESPACE_NODE *device_node, + ACPI_INTEGER *address) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, object_name, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + return (status); + } + + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* Is the return object of the correct type? */ + + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + status = AE_TYPE; + } + else { + /* + * Since the structure is a union, setting any field will set all + * of the variables in the union + */ + *address = obj_desc->integer.value; + } + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_execute_HID + * + * PARAMETERS: Device_node - Node for the device + * *Hid - Where the HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_execute_HID ( + ACPI_NAMESPACE_NODE *device_node, + DEVICE_ID *hid) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, + METHOD_NAME__HID, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* + * A _HID can return either a Number (32 bit compressed EISA ID) or + * a string + */ + + if ((obj_desc->common.type != ACPI_TYPE_INTEGER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) { + status = AE_TYPE; + } + + else { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { + /* Convert the Numeric HID to string */ + + acpi_aml_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer); + } + + else { + /* Copy the String HID from the returned object */ + + STRNCPY(hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer)); + } + } + + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_execute_UID + * + * PARAMETERS: Device_node - Node for the device + * *Uid - Where the UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_execute_UID ( + ACPI_NAMESPACE_NODE *device_node, + DEVICE_ID *uid) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, + METHOD_NAME__UID, NULL, &obj_desc); + if (ACPI_FAILURE (status)) { + + + return (status); + } + + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* + * A _UID can return either a Number (32 bit compressed EISA ID) or + * a string + */ + + if ((obj_desc->common.type != ACPI_TYPE_INTEGER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) { + status = AE_TYPE; + } + + else { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { + /* Convert the Numeric UID to string */ + + acpi_aml_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer); + } + + else { + /* Copy the String UID from the returned object */ + + STRNCPY(uid->buffer, obj_desc->string.pointer, sizeof(uid->buffer)); + } + } + + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + + return (status); +} + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_execute_STA + * + * PARAMETERS: Device_node - Node for the device + * *Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ***************************************************************************/ + +ACPI_STATUS +acpi_cm_execute_STA ( + ACPI_NAMESPACE_NODE *device_node, + u32 *flags) +{ + ACPI_OPERAND_OBJECT *obj_desc; + ACPI_STATUS status; + + + /* Execute the method */ + + status = acpi_ns_evaluate_relative (device_node, + METHOD_NAME__STA, NULL, &obj_desc); + if (AE_NOT_FOUND == status) { + *flags = 0x0F; + status = AE_OK; + } + + + else /* success */ { + /* Did we get a return object? */ + + if (!obj_desc) { + return (AE_TYPE); + } + + /* Is the return object of the correct type? */ + + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { + status = AE_TYPE; + } + + else { + /* Extract the status flags */ + + *flags = (u32) obj_desc->integer.value; + } + + /* On exit, we must delete the return object */ + + acpi_cm_remove_reference (obj_desc); + } + + return (status); +} diff --git a/drivers/bus/acpi/utils/cmglobal.c b/drivers/bus/acpi/utils/cmglobal.c new file mode 100644 index 0000000..12d1684 --- /dev/null +++ b/drivers/bus/acpi/utils/cmglobal.c @@ -0,0 +1,482 @@ +/****************************************************************************** + * + * Module Name: cmglobal - Global variables for the ACPI subsystem + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define DEFINE_ACPI_GLOBALS + +#include "acpi.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmglobal") + + +/****************************************************************************** + * + * Static global variable initialization. + * + ******************************************************************************/ + +/* + * We want the debug switches statically initialized so they + * are already set when the debugger is entered. + */ + +/* Debug switch - level and trace mask */ + +u32 acpi_dbg_level = NORMAL_DEFAULT; + +/* Debug switch - layer (component) mask */ + +u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT; +u32 acpi_gbl_nesting_level = 0; + + +/* Debugger globals */ + +u8 acpi_gbl_db_terminate_threads = FALSE; +u8 acpi_gbl_method_executing = FALSE; + +/* System flags */ + +u32 acpi_gbl_system_flags = 0; +u32 acpi_gbl_startup_flags = 0; + +/* System starts unitialized! */ +u8 acpi_gbl_shutdown = TRUE; + + +u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128}; + + +/****************************************************************************** + * + * Namespace globals + * + ******************************************************************************/ + + +/* + * Names built-in to the interpreter + * + * Initial values are currently supported only for types String and Number. + * To avoid type punning, both are specified as strings in this table. + * + * NOTES: + * 1) _SB_ is defined to be a device to allow _SB_/_INI to be run + * during the initialization sequence. + */ + +PREDEFINED_NAMES acpi_gbl_pre_defined_names[] = +{ {"_GPE", INTERNAL_TYPE_DEF_ANY}, + {"_PR_", INTERNAL_TYPE_DEF_ANY}, + {"_SB_", ACPI_TYPE_DEVICE}, + {"_SI_", INTERNAL_TYPE_DEF_ANY}, + {"_TZ_", INTERNAL_TYPE_DEF_ANY}, + {"_REV", ACPI_TYPE_INTEGER, "2"}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, "0"}, + {NULL, ACPI_TYPE_ANY} /* Table terminator */ +}; + + +/* + * Properties of the ACPI Object Types, both internal and external. + * + * Elements of Acpi_ns_properties are bit significant + * and the table is indexed by values of ACPI_OBJECT_TYPE + */ + +u8 acpi_gbl_ns_properties[] = +{ + NSP_NORMAL, /* 00 Any */ + NSP_NORMAL, /* 01 Number */ + NSP_NORMAL, /* 02 String */ + NSP_NORMAL, /* 03 Buffer */ + NSP_LOCAL, /* 04 Package */ + NSP_NORMAL, /* 05 Field_unit */ + NSP_NEWSCOPE | NSP_LOCAL, /* 06 Device */ + NSP_LOCAL, /* 07 Acpi_event */ + NSP_NEWSCOPE | NSP_LOCAL, /* 08 Method */ + NSP_LOCAL, /* 09 Mutex */ + NSP_LOCAL, /* 10 Region */ + NSP_NEWSCOPE | NSP_LOCAL, /* 11 Power */ + NSP_NEWSCOPE | NSP_LOCAL, /* 12 Processor */ + NSP_NEWSCOPE | NSP_LOCAL, /* 13 Thermal */ + NSP_NORMAL, /* 14 Buffer_field */ + NSP_NORMAL, /* 15 Ddb_handle */ + NSP_NORMAL, /* 16 Debug Object */ + NSP_NORMAL, /* 17 Def_field */ + NSP_NORMAL, /* 18 Bank_field */ + NSP_NORMAL, /* 19 Index_field */ + NSP_NORMAL, /* 20 Reference */ + NSP_NORMAL, /* 21 Alias */ + NSP_NORMAL, /* 22 Notify */ + NSP_NORMAL, /* 23 Address Handler */ + NSP_NEWSCOPE | NSP_LOCAL, /* 24 Resource */ + NSP_NORMAL, /* 25 Def_field_defn */ + NSP_NORMAL, /* 26 Bank_field_defn */ + NSP_NORMAL, /* 27 Index_field_defn */ + NSP_NORMAL, /* 28 If */ + NSP_NORMAL, /* 29 Else */ + NSP_NORMAL, /* 30 While */ + NSP_NEWSCOPE, /* 31 Scope */ + NSP_LOCAL, /* 32 Def_any */ + NSP_NORMAL, /* 33 Extra */ + NSP_NORMAL /* 34 Invalid */ +}; + + +/* Hex to ASCII conversion table */ + +NATIVE_CHAR acpi_gbl_hex_to_ascii[] = + {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + + +/****************************************************************************** + * + * Table globals + * + * NOTE: This table includes ONLY the ACPI tables that the subsystem consumes. + * it is NOT an exhaustive list of all possible ACPI tables. All ACPI tables + * that are not used by the subsystem are simply ignored. + * + ******************************************************************************/ + + +ACPI_TABLE_DESC acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; + + +ACPI_TABLE_SUPPORT acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] = +{ + /*********** Name, Signature, Signature size, How many allowed?, Supported? Global typed pointer */ + + /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, sizeof (RSDP_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, + /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, sizeof (DSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_DSDT}, + /* FADT 2 */ {FADT_SIG, FADT_SIG, sizeof (FADT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FADT}, + /* FACS 3 */ {FACS_SIG, FACS_SIG, sizeof (FACS_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, (void **) &acpi_gbl_FACS}, + /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, sizeof (PSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, sizeof (SSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK, NULL}, + /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, sizeof (RSDT_SIG)-1, ACPI_TABLE_SINGLE, AE_OK, NULL}, +}; + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_valid_object_type + * + * PARAMETERS: None. + * + * RETURN: TRUE if valid object type + * + * DESCRIPTION: Validate an object type + * + ****************************************************************************/ + +u8 +acpi_cm_valid_object_type ( + u32 type) +{ + + if (type > ACPI_TYPE_MAX) + { + if ((type < INTERNAL_TYPE_BEGIN) || + (type > INTERNAL_TYPE_MAX)) + { + return (FALSE); + } + } + + return (TRUE); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_cm_format_exception + * + * PARAMETERS: Status - Acpi status to be formatted + * + * RETURN: Formatted status string + * + * DESCRIPTION: Convert an ACPI exception to a string + * + ****************************************************************************/ + +NATIVE_CHAR * +acpi_cm_format_exception ( + ACPI_STATUS status) +{ + NATIVE_CHAR *exception = "UNKNOWN_STATUS"; + ACPI_STATUS sub_status; + + + sub_status = (status & ~AE_CODE_MASK); + + + switch (status & AE_CODE_MASK) + { + case AE_CODE_ENVIRONMENTAL: + + if (sub_status <= AE_CODE_ENV_MAX) + { + exception = acpi_gbl_exception_names_env [sub_status]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (sub_status <= AE_CODE_PGM_MAX) + { + exception = acpi_gbl_exception_names_pgm [sub_status -1]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (sub_status <= AE_CODE_TBL_MAX) + { + exception = acpi_gbl_exception_names_tbl [sub_status -1]; + } + break; + + case AE_CODE_AML: + + if (sub_status <= AE_CODE_AML_MAX) + { + exception = acpi_gbl_exception_names_aml [sub_status -1]; + } + break; + + case AE_CODE_CONTROL: + + if (sub_status <= AE_CODE_CTRL_MAX) + { + exception = acpi_gbl_exception_names_ctrl [sub_status -1]; + } + break; + + default: + break; + } + + + return (exception); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_allocate_owner_id + * + * PARAMETERS: Id_type - Type of ID (method or table) + * + * DESCRIPTION: Allocate a table or method owner id + * + ***************************************************************************/ + +ACPI_OWNER_ID +acpi_cm_allocate_owner_id ( + u32 id_type) +{ + ACPI_OWNER_ID owner_id = 0xFFFF; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + switch (id_type) + { + case OWNER_TYPE_TABLE: + + owner_id = acpi_gbl_next_table_owner_id; + acpi_gbl_next_table_owner_id++; + + if (acpi_gbl_next_table_owner_id == FIRST_METHOD_ID) + { + acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; + } + break; + + + case OWNER_TYPE_METHOD: + + owner_id = acpi_gbl_next_method_owner_id; + acpi_gbl_next_method_owner_id++; + + if (acpi_gbl_next_method_owner_id == FIRST_TABLE_ID) + { + acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; + } + break; + } + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + return (owner_id); +} + + +/**************************************************************************** + * + * FUNCTION: Acpi_cm_init_globals + * + * PARAMETERS: none + * + * DESCRIPTION: Init library globals. All globals that require specific + * initialization should be initialized here! + * + ***************************************************************************/ + +void +acpi_cm_init_globals ( + void) +{ + u32 i; + + + /* ACPI table structure */ + + for (i = 0; i < NUM_ACPI_TABLES; i++) + { + acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; + acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; + acpi_gbl_acpi_tables[i].pointer = NULL; + acpi_gbl_acpi_tables[i].length = 0; + acpi_gbl_acpi_tables[i].allocation = ACPI_MEM_NOT_ALLOCATED; + acpi_gbl_acpi_tables[i].count = 0; + } + + + /* Address Space handler array */ + + for (i = 0; i < ACPI_NUM_ADDRESS_SPACES; i++) + { + acpi_gbl_address_spaces[i].handler = NULL; + acpi_gbl_address_spaces[i].context = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < NUM_MTX; i++) + { + acpi_gbl_acpi_mutex_info[i].mutex = NULL; + acpi_gbl_acpi_mutex_info[i].locked = FALSE; + acpi_gbl_acpi_mutex_info[i].use_count = 0; + } + + /* Global notify handlers */ + + acpi_gbl_sys_notify.handler = NULL; + acpi_gbl_drv_notify.handler = NULL; + + /* Global "typed" ACPI table pointers */ + + acpi_gbl_RSDP = NULL; + acpi_gbl_XSDT = NULL; + acpi_gbl_FACS = NULL; + acpi_gbl_FADT = NULL; + acpi_gbl_DSDT = NULL; + + + /* Global Lock support */ + + acpi_gbl_global_lock_acquired = FALSE; + acpi_gbl_global_lock_thread_count = 0; + + /* Miscellaneous variables */ + + acpi_gbl_system_flags = 0; + acpi_gbl_startup_flags = 0; + acpi_gbl_rsdp_original_location = 0; + acpi_gbl_cm_single_step = FALSE; + acpi_gbl_db_terminate_threads = FALSE; + acpi_gbl_shutdown = FALSE; + acpi_gbl_ns_lookup_count = 0; + acpi_gbl_ps_find_count = 0; + acpi_gbl_acpi_hardware_present = TRUE; + acpi_gbl_next_table_owner_id = FIRST_TABLE_ID; + acpi_gbl_next_method_owner_id = FIRST_METHOD_ID; + acpi_gbl_debugger_configuration = DEBUGGER_THREADING; + + /* Cache of small "state" objects */ + + acpi_gbl_generic_state_cache = NULL; + acpi_gbl_generic_state_cache_depth = 0; + acpi_gbl_state_cache_requests = 0; + acpi_gbl_state_cache_hits = 0; + + acpi_gbl_parse_cache = NULL; + acpi_gbl_parse_cache_depth = 0; + acpi_gbl_parse_cache_requests = 0; + acpi_gbl_parse_cache_hits = 0; + + acpi_gbl_ext_parse_cache = NULL; + acpi_gbl_ext_parse_cache_depth = 0; + acpi_gbl_ext_parse_cache_requests = 0; + acpi_gbl_ext_parse_cache_hits = 0; + + acpi_gbl_object_cache = NULL; + acpi_gbl_object_cache_depth = 0; + acpi_gbl_object_cache_requests = 0; + acpi_gbl_object_cache_hits = 0; + + acpi_gbl_walk_state_cache = NULL; + acpi_gbl_walk_state_cache_depth = 0; + acpi_gbl_walk_state_cache_requests = 0; + acpi_gbl_walk_state_cache_hits = 0; + + /* Hardware oriented */ + + acpi_gbl_gpe0enable_register_save = NULL; + acpi_gbl_gpe1_enable_register_save = NULL; + acpi_gbl_original_mode = SYS_MODE_UNKNOWN; /* original ACPI/legacy mode */ + acpi_gbl_gpe_registers = NULL; + acpi_gbl_gpe_info = NULL; + + /* Namespace */ + + acpi_gbl_root_node = NULL; + + acpi_gbl_root_node_struct.name = ACPI_ROOT_NAME; + acpi_gbl_root_node_struct.data_type = ACPI_DESC_TYPE_NAMED; + acpi_gbl_root_node_struct.type = ACPI_TYPE_ANY; + acpi_gbl_root_node_struct.child = NULL; + acpi_gbl_root_node_struct.peer = NULL; + acpi_gbl_root_node_struct.object = NULL; + acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; + + /* Memory allocation metrics - compiled out in non-debug mode. */ + + INITIALIZE_ALLOCATION_METRICS(); + + return; +} + + diff --git a/drivers/bus/acpi/utils/cminit.c b/drivers/bus/acpi/utils/cminit.c new file mode 100644 index 0000000..47f60c7 --- /dev/null +++ b/drivers/bus/acpi/utils/cminit.c @@ -0,0 +1,247 @@ +/****************************************************************************** + * + * Module Name: cminit - Common ACPI subsystem initialization + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "achware.h" +#include "acnamesp.h" +#include "acevents.h" +#include "acparser.h" +#include "acdispat.h" + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cminit") + + +#define ACPI_OFFSET(d,o) ((u32) &(((d *)0)->o)) +#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o) + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_fadt_register_error + * + * PARAMETERS: *Register_name - Pointer to string identifying register + * Value - Actual register contents value + * Acpi_test_spec_section - TDS section containing assertion + * Acpi_assertion - Assertion number being tested + * + * RETURN: AE_BAD_VALUE + * + * DESCRIPTION: Display failure message and link failure to TDS assertion + * + ******************************************************************************/ + +static ACPI_STATUS +acpi_cm_fadt_register_error ( + NATIVE_CHAR *register_name, + u32 value, + u32 offset) +{ + + REPORT_ERROR ( + ("Invalid FADT value %s=%lX at offset %lX FADT=%p\n", + register_name, value, offset, acpi_gbl_FADT)); + + + return (AE_BAD_VALUE); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_validate_fadt + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Validate various ACPI registers in the FADT + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_validate_fadt ( + void) +{ + ACPI_STATUS status = AE_OK; + + + /* + * Verify Fixed ACPI Description Table fields, + * but don't abort on any problems, just display error + */ + + if (acpi_gbl_FADT->pm1_evt_len < 4) { + status = acpi_cm_fadt_register_error ("PM1_EVT_LEN", + (u32) acpi_gbl_FADT->pm1_evt_len, + ACPI_FADT_OFFSET (pm1_evt_len)); + } + + if (!acpi_gbl_FADT->pm1_cnt_len) { + status = acpi_cm_fadt_register_error ("PM1_CNT_LEN", 0, + ACPI_FADT_OFFSET (pm1_cnt_len)); + } + + if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)) { + status = acpi_cm_fadt_register_error ("X_PM1a_EVT_BLK", 0, + ACPI_FADT_OFFSET (Xpm1a_evt_blk.address)); + } + + if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_cnt_blk.address)) { + status = acpi_cm_fadt_register_error ("X_PM1a_CNT_BLK", 0, + ACPI_FADT_OFFSET (Xpm1a_cnt_blk.address)); + } + + if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)) { + status = acpi_cm_fadt_register_error ("X_PM_TMR_BLK", 0, + ACPI_FADT_OFFSET (Xpm_tmr_blk.address)); + } + + if ((ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address) && + !acpi_gbl_FADT->pm2_cnt_len)) { + status = acpi_cm_fadt_register_error ("PM2_CNT_LEN", + (u32) acpi_gbl_FADT->pm2_cnt_len, + ACPI_FADT_OFFSET (pm2_cnt_len)); + } + + if (acpi_gbl_FADT->pm_tm_len < 4) { + status = acpi_cm_fadt_register_error ("PM_TM_LEN", + (u32) acpi_gbl_FADT->pm_tm_len, + ACPI_FADT_OFFSET (pm_tm_len)); + } + + /* length of GPE blocks must be a multiple of 2 */ + + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) && + (acpi_gbl_FADT->gpe0blk_len & 1)) { + status = acpi_cm_fadt_register_error ("(x)GPE0_BLK_LEN", + (u32) acpi_gbl_FADT->gpe0blk_len, + ACPI_FADT_OFFSET (gpe0blk_len)); + } + + if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) && + (acpi_gbl_FADT->gpe1_blk_len & 1)) { + status = acpi_cm_fadt_register_error ("(x)GPE1_BLK_LEN", + (u32) acpi_gbl_FADT->gpe1_blk_len, + ACPI_FADT_OFFSET (gpe1_blk_len)); + } + + return (status); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_terminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: free memory allocated for table storage. + * + ******************************************************************************/ + +void +acpi_cm_terminate (void) +{ + + + /* Free global tables, etc. */ + + if (acpi_gbl_gpe0enable_register_save) { + acpi_cm_free (acpi_gbl_gpe0enable_register_save); + } + + if (acpi_gbl_gpe1_enable_register_save) { + acpi_cm_free (acpi_gbl_gpe1_enable_register_save); + } + + + return; +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_cm_subsystem_shutdown + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex + * objects here -- because the AML debugger may be still running. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_subsystem_shutdown (void) +{ + + /* Just exit if subsystem is already shutdown */ + + if (acpi_gbl_shutdown) { + return (AE_OK); + } + + /* Subsystem appears active, go ahead and shut it down */ + + acpi_gbl_shutdown = TRUE; + + /* Close the Namespace */ + + acpi_ns_terminate (); + + /* Close the Acpi_event Handling */ + + acpi_ev_terminate (); + + /* Close the globals */ + + acpi_cm_terminate (); + + /* Flush the local cache(s) */ + + acpi_cm_delete_generic_state_cache (); + acpi_cm_delete_object_cache (); + acpi_ds_delete_walk_state_cache (); + + /* Close the Parser */ + + /* TBD: [Restructure] Acpi_ps_terminate () */ + + acpi_ps_delete_parse_cache (); + + /* Debug only - display leftover memory allocation, if any */ +#ifdef ENABLE_DEBUGGER + acpi_cm_dump_current_allocations (ACPI_UINT32_MAX, NULL); +#endif + + return (AE_OK); +} + + diff --git a/drivers/bus/acpi/utils/cmobject.c b/drivers/bus/acpi/utils/cmobject.c new file mode 100644 index 0000000..e005045 --- /dev/null +++ b/drivers/bus/acpi/utils/cmobject.c @@ -0,0 +1,622 @@ +/****************************************************************************** + * + * Module Name: cmobject - ACPI object create/delete/size/cache routines + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmobject") + + +/******************************************************************************* + * + * FUNCTION: _Cm_create_internal_object + * + * PARAMETERS: Address - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * Type - ACPI Type of the new object + * + * RETURN: Object - The new object. Null on failure + * + * DESCRIPTION: Create and initialize a new internal object. + * + * NOTE: We always allocate the worst-case object descriptor because + * these objects are cached, and we want them to be + * one-size-satisifies-any-request. This in itself may not be + * the most memory efficient, but the efficiency of the object + * cache should more than make up for this! + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +_cm_create_internal_object ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id, + OBJECT_TYPE_INTERNAL type) +{ + ACPI_OPERAND_OBJECT *object; + + + /* Allocate the raw object descriptor */ + + object = _cm_allocate_object_desc (module_name, line_number, component_id); + if (!object) { + /* Allocation failure */ + + return (NULL); + } + + /* Save the object type in the object descriptor */ + + object->common.type = type; + + /* Init the reference count */ + + object->common.reference_count = 1; + + /* Any per-type initialization should go here */ + + + return (object); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_valid_internal_object + * + * PARAMETERS: Operand - Object to be validated + * + * RETURN: Validate a pointer to be an ACPI_OPERAND_OBJECT + * + ******************************************************************************/ + +u8 +acpi_cm_valid_internal_object ( + void *object) +{ + + /* Check for a null pointer */ + + if (!object) { + return (FALSE); + } + + /* Check for a pointer within one of the ACPI tables */ + + if (acpi_tb_system_table_pointer (object)) { + return (FALSE); + } + + /* Check the descriptor type field */ + + if (!VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL)) { + /* Not an ACPI internal object, do some further checking */ + + + + + return (FALSE); + } + + + /* The object appears to be a valid ACPI_OPERAND_OBJECT */ + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: _Cm_allocate_object_desc + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: Pointer to newly allocated object descriptor. Null on error + * + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * error conditions. + * + ******************************************************************************/ + +void * +_cm_allocate_object_desc ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + ACPI_OPERAND_OBJECT *object; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + acpi_gbl_object_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_object_cache) { + /* There is an object available, use it */ + + object = acpi_gbl_object_cache; + acpi_gbl_object_cache = object->cache.next; + object->cache.next = NULL; + + acpi_gbl_object_cache_hits++; + acpi_gbl_object_cache_depth--; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + + else { + /* The cache is empty, create a new object */ + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + /* Attempt to allocate new descriptor */ + + object = _cm_callocate (sizeof (ACPI_OPERAND_OBJECT), component_id, + module_name, line_number); + if (!object) { + /* Allocation failed */ + + _REPORT_ERROR (module_name, line_number, component_id, + ("Could not allocate an object descriptor\n")); + + return (NULL); + } + + /* Memory allocation metrics - compiled out in non debug mode. */ + + INCREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); + } + + /* Mark the descriptor type */ + + object->common.data_type = ACPI_DESC_TYPE_INTERNAL; + + return (object); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_object_desc + * + * PARAMETERS: Object - Acpi internal object to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache + * + ******************************************************************************/ + +void +acpi_cm_delete_object_desc ( + ACPI_OPERAND_OBJECT *object) +{ + + + /* Make sure that the object isn't already in the cache */ + + if (object->common.data_type == (ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT)) { + return; + } + + /* Object must be an ACPI_OPERAND_OBJECT */ + + if (object->common.data_type != ACPI_DESC_TYPE_INTERNAL) { + return; + } + + + /* If cache is full, just free this object */ + + if (acpi_gbl_object_cache_depth >= MAX_OBJECT_CACHE_DEPTH) { + /* + * Memory allocation metrics. Call the macro here since we only + * care about dynamically allocated objects. + */ + DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); + + acpi_cm_free (object); + return; + } + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the entire object. This is important! */ + + MEMSET (object, 0, sizeof (ACPI_OPERAND_OBJECT)); + object->common.data_type = ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT; + + /* Put the object at the head of the global cache list */ + + object->cache.next = acpi_gbl_object_cache; + acpi_gbl_object_cache = object; + acpi_gbl_object_cache_depth++; + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_object_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_cm_delete_object_cache ( + void) +{ + ACPI_OPERAND_OBJECT *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_object_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_object_cache->cache.next; + acpi_gbl_object_cache->cache.next = NULL; + + /* + * Memory allocation metrics. Call the macro here since we only + * care about dynamically allocated objects. + */ + DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT)); + + acpi_cm_free (acpi_gbl_object_cache); + acpi_gbl_object_cache = next; + acpi_gbl_object_cache_depth--; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_init_static_object + * + * PARAMETERS: Obj_desc - Pointer to a "static" object - on stack + * or in the data segment. + * + * RETURN: None. + * + * DESCRIPTION: Initialize a static object. Sets flags to disallow dynamic + * deletion of the object. + * + ******************************************************************************/ + +void +acpi_cm_init_static_object ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + + + if (!obj_desc) { + return; + } + + + /* + * Clear the entire descriptor + */ + MEMSET ((void *) obj_desc, 0, sizeof (ACPI_OPERAND_OBJECT)); + + + /* + * Initialize the header fields + * 1) This is an ACPI_OPERAND_OBJECT descriptor + * 2) The size is the full object (worst case) + * 3) The flags field indicates static allocation + * 4) Reference count starts at one (not really necessary since the + * object can't be deleted, but keeps everything sane) + */ + + obj_desc->common.data_type = ACPI_DESC_TYPE_INTERNAL; + obj_desc->common.flags = AOPOBJ_STATIC_ALLOCATION; + obj_desc->common.reference_count = 1; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_get_simple_object_size + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Ret_length - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a simple object for return to an API user. + * + * The length includes the object structure plus any additional + * needed space. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_simple_object_size ( + ACPI_OPERAND_OBJECT *internal_object, + u32 *obj_length) +{ + u32 length; + ACPI_STATUS status = AE_OK; + + + /* Handle a null object (Could be a uninitialized package element -- which is legal) */ + + if (!internal_object) { + *obj_length = 0; + return (AE_OK); + } + + + /* Start with the length of the Acpi object */ + + length = sizeof (ACPI_OBJECT); + + if (VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_NAMED)) { + /* Object is a named object (reference), just return the length */ + + *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); + return (status); + } + + + /* + * The final length depends on the object type + * Strings and Buffers are packed right up against the parent object and + * must be accessed bytewise or there may be alignment problems on + * certain processors + */ + + switch (internal_object->common.type) { + + case ACPI_TYPE_STRING: + + length += internal_object->string.length + 1; + break; + + + case ACPI_TYPE_BUFFER: + + length += internal_object->buffer.length; + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + /* + * No extra data for these types + */ + break; + + + case INTERNAL_TYPE_REFERENCE: + + /* + * The only type that should be here is opcode AML_NAMEPATH_OP -- since + * this means an object reference + */ + if (internal_object->reference.opcode != AML_NAMEPATH_OP) { + status = AE_TYPE; + } + + else { + /* + * Get the actual length of the full pathname to this object. + * The reference will be converted to the pathname to the object + */ + length += ROUND_UP_TO_NATIVE_WORD (acpi_ns_get_pathname_length (internal_object->reference.node)); + } + break; + + + default: + + status = AE_TYPE; + break; + } + + + /* + * Account for the space required by the object rounded up to the next + * multiple of the machine word size. This keeps each object aligned + * on a machine word boundary. (preventing alignment faults on some + * machines.) + */ + *obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_get_element_length + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Get the length of one package element. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_element_length ( + u8 object_type, + ACPI_OPERAND_OBJECT *source_object, + ACPI_GENERIC_STATE *state, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context; + u32 object_space; + + + switch (object_type) { + case 0: + + /* + * Simple object - just get the size (Null object/entry is handled + * here also) and sum it into the running package length + */ + status = acpi_cm_get_simple_object_size (source_object, &object_space); + if (ACPI_FAILURE (status)) { + return (status); + } + + info->length += object_space; + break; + + + case 1: + /* Package - nothing much to do here, let the walk handle it */ + + info->num_packages++; + state->pkg.this_target_obj = NULL; + break; + + default: + return (AE_BAD_PARAMETER); + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_get_package_object_size + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Ret_length - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a package object for return to an API user. + * + * This is moderately complex since a package contains other + * objects including packages. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_package_object_size ( + ACPI_OPERAND_OBJECT *internal_object, + u32 *obj_length) +{ + ACPI_STATUS status; + ACPI_PKG_INFO info; + + + info.length = 0; + info.object_space = 0; + info.num_packages = 1; + + status = acpi_cm_walk_package_tree (internal_object, NULL, + acpi_cm_get_element_length, &info); + + /* + * We have handled all of the objects in all levels of the package. + * just add the length of the package objects themselves. + * Round up to the next machine word. + */ + info.length += ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) * + info.num_packages; + + /* Return the total package length */ + + *obj_length = info.length; + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_get_object_size + * + * PARAMETERS: *Internal_object - Pointer to the object we are examining + * *Ret_length - Where the length will be returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain an object for return to an API user. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_get_object_size( + ACPI_OPERAND_OBJECT *internal_object, + u32 *obj_length) +{ + ACPI_STATUS status; + + + if ((VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_INTERNAL)) && + (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE))) { + status = acpi_cm_get_package_object_size (internal_object, obj_length); + } + + else { + status = acpi_cm_get_simple_object_size (internal_object, obj_length); + } + + return (status); +} + + diff --git a/drivers/bus/acpi/utils/cmutils.c b/drivers/bus/acpi/utils/cmutils.c new file mode 100644 index 0000000..f363523 --- /dev/null +++ b/drivers/bus/acpi/utils/cmutils.c @@ -0,0 +1,1006 @@ +/******************************************************************************* + * + * Module Name: cmutils - common utility procedures + * $Revision$ + * + ******************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acevents.h" +#include "achware.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmutils") + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_valid_acpi_name + * + * PARAMETERS: Character - The character to be examined + * + * RETURN: 1 if Character may appear in a name, else 0 + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +u8 +acpi_cm_valid_acpi_name ( + u32 name) +{ + NATIVE_CHAR *name_ptr = (NATIVE_CHAR *) &name; + u32 i; + + + for (i = 0; i < ACPI_NAME_SIZE; i++) { + if (!((name_ptr[i] == '_') || + (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') || + (name_ptr[i] >= '0' && name_ptr[i] <= '9'))) { + return (FALSE); + } + } + + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_valid_acpi_character + * + * PARAMETERS: Character - The character to be examined + * + * RETURN: 1 if Character may appear in a name, else 0 + * + * DESCRIPTION: Check for a printable character + * + ******************************************************************************/ + +u8 +acpi_cm_valid_acpi_character ( + NATIVE_CHAR character) +{ + + return ((u8) ((character == '_') || + (character >= 'A' && character <= 'Z') || + (character >= '0' && character <= '9'))); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_mutex_initialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_mutex_initialize ( + void) +{ + u32 i; + ACPI_STATUS status; + + + /* + * Create each of the predefined mutex objects + */ + for (i = 0; i < NUM_MTX; i++) { + status = acpi_cm_create_mutex (i); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_mutex_terminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. + * + ******************************************************************************/ + +void +acpi_cm_mutex_terminate ( + void) +{ + u32 i; + + + /* + * Delete each predefined mutex object + */ + for (i = 0; i < NUM_MTX; i++) { + acpi_cm_delete_mutex (i); + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_create_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status = AE_OK; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { + status = acpi_os_create_semaphore (1, 1, + &acpi_gbl_acpi_mutex_info[mutex_id].mutex); + acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; + acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_delete_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); + + acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_acquire_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_acquire_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + u32 i; + u32 this_thread_id; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + this_thread_id = acpi_os_get_thread_id (); + + /* + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = mutex_id; i < MAX_MTX; i++) { + if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + if (i == mutex_id) { + return (AE_ALREADY_ACQUIRED); + } + + return (AE_ACQUIRE_DEADLOCK); + } + } + + + status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, + 1, WAIT_FOREVER); + + if (ACPI_SUCCESS (status)) { + acpi_gbl_acpi_mutex_info[mutex_id].locked = TRUE; + acpi_gbl_acpi_mutex_info[mutex_id].use_count++; + acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id; + } + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_release_mutex + * + * PARAMETERS: Mutex_iD - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_release_mutex ( + ACPI_MUTEX_HANDLE mutex_id) +{ + ACPI_STATUS status; + u32 i; + u32 this_thread_id; + + + if (mutex_id > MAX_MTX) { + return (AE_BAD_PARAMETER); + } + + + /* + * Mutex must be acquired in order to release it! + */ + if (!acpi_gbl_acpi_mutex_info[mutex_id].locked) { + return (AE_NOT_ACQUIRED); + } + + + /* + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + this_thread_id = acpi_os_get_thread_id (); + for (i = mutex_id; i < MAX_MTX; i++) { + if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + if (i == mutex_id) { + continue; + } + + return (AE_RELEASE_DEADLOCK); + } + } + + acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; /* Mark before unlocking */ + acpi_gbl_acpi_mutex_info[mutex_id].owner_id = 0; + + status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_update_state_and_push + * + * PARAMETERS: *Object - Object to be added to the new state + * Action - Increment/Decrement + * State_list - List the state will be added to + * + * RETURN: None + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_create_update_state_and_push ( + ACPI_OPERAND_OBJECT *object, + u16 action, + ACPI_GENERIC_STATE **state_list) +{ + ACPI_GENERIC_STATE *state; + + + /* Ignore null objects; these are expected */ + + if (!object) { + return (AE_OK); + } + + state = acpi_cm_create_update_state (object, action); + if (!state) { + return (AE_NO_MEMORY); + } + + + acpi_cm_push_generic_state (state_list, state); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_pkg_state_and_push + * + * PARAMETERS: *Object - Object to be added to the new state + * Action - Increment/Decrement + * State_list - List the state will be added to + * + * RETURN: None + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_create_pkg_state_and_push ( + void *internal_object, + void *external_object, + u16 index, + ACPI_GENERIC_STATE **state_list) +{ + ACPI_GENERIC_STATE *state; + + + state = acpi_cm_create_pkg_state (internal_object, external_object, index); + if (!state) { + return (AE_NO_MEMORY); + } + + + acpi_cm_push_generic_state (state_list, state); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_push_generic_state + * + * PARAMETERS: List_head - Head of the state stack + * State - State object to push + * + * RETURN: Status + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +acpi_cm_push_generic_state ( + ACPI_GENERIC_STATE **list_head, + ACPI_GENERIC_STATE *state) +{ + /* Push the state object onto the front of the list (stack) */ + + state->common.next = *list_head; + *list_head = state; + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_pop_generic_state + * + * PARAMETERS: List_head - Head of the state stack + * + * RETURN: Status + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_pop_generic_state ( + ACPI_GENERIC_STATE **list_head) +{ + ACPI_GENERIC_STATE *state; + + + /* Remove the state object at the head of the list (stack) */ + + state = *list_head; + if (state) { + /* Update the list head */ + + *list_head = state->common.next; + } + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_generic_state + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_generic_state (void) +{ + ACPI_GENERIC_STATE *state; + + + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + acpi_gbl_state_cache_requests++; + + /* Check the cache first */ + + if (acpi_gbl_generic_state_cache) { + /* There is an object available, use it */ + + state = acpi_gbl_generic_state_cache; + acpi_gbl_generic_state_cache = state->common.next; + state->common.next = NULL; + + acpi_gbl_state_cache_hits++; + acpi_gbl_generic_state_cache_depth--; + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + } + + else { + /* The cache is empty, create a new object */ + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + + state = acpi_cm_callocate (sizeof (ACPI_GENERIC_STATE)); + } + + /* Initialize */ + + if (state) { + /* Always zero out the object before init */ + + MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); + + state->common.data_type = ACPI_DESC_TYPE_STATE; + } + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_update_state + * + * PARAMETERS: Object - Initial Object to be installed in the + * state + * Action - Update action to be performed + * + * RETURN: Status + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_update_state ( + ACPI_OPERAND_OBJECT *object, + u16 action) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_cm_create_generic_state (); + if (!state) { + return (NULL); + } + + /* Init fields specific to the update struct */ + + state->update.object = object; + state->update.value = action; + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_pkg_state + * + * PARAMETERS: Object - Initial Object to be installed in the + * state + * Action - Update action to be performed + * + * RETURN: Status + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_pkg_state ( + void *internal_object, + void *external_object, + u16 index) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_cm_create_generic_state (); + if (!state) { + return (NULL); + } + + /* Init fields specific to the update struct */ + + state->pkg.source_object = (ACPI_OPERAND_OBJECT *) internal_object; + state->pkg.dest_object = external_object; + state->pkg.index = index; + state->pkg.num_packages = 1; + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_create_control_state + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +acpi_cm_create_control_state ( + void) +{ + ACPI_GENERIC_STATE *state; + + + /* Create the generic state object */ + + state = acpi_cm_create_generic_state (); + if (!state) { + return (NULL); + } + + + /* Init fields specific to the control struct */ + + state->common.state = CONTROL_CONDITIONAL_EXECUTING; + + return (state); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_generic_state + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Put a state object back into the global state cache. The object + * is not actually freed at this time. + * + ******************************************************************************/ + +void +acpi_cm_delete_generic_state ( + ACPI_GENERIC_STATE *state) +{ + + /* If cache is full, just free this state object */ + + if (acpi_gbl_generic_state_cache_depth >= MAX_STATE_CACHE_DEPTH) { + acpi_cm_free (state); + } + + /* Otherwise put this object back into the cache */ + + else { + acpi_cm_acquire_mutex (ACPI_MTX_CACHES); + + /* Clear the state */ + + MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE)); + state->common.data_type = ACPI_DESC_TYPE_STATE; + + /* Put the object at the head of the global cache list */ + + state->common.next = acpi_gbl_generic_state_cache; + acpi_gbl_generic_state_cache = state; + acpi_gbl_generic_state_cache_depth++; + + + acpi_cm_release_mutex (ACPI_MTX_CACHES); + } + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_delete_generic_state_cache + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge the global state object cache. Used during subsystem + * termination. + * + ******************************************************************************/ + +void +acpi_cm_delete_generic_state_cache ( + void) +{ + ACPI_GENERIC_STATE *next; + + + /* Traverse the global cache list */ + + while (acpi_gbl_generic_state_cache) { + /* Delete one cached state object */ + + next = acpi_gbl_generic_state_cache->common.next; + acpi_cm_free (acpi_gbl_generic_state_cache); + acpi_gbl_generic_state_cache = next; + acpi_gbl_generic_state_cache_depth--; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_resolve_package_references + * + * PARAMETERS: Obj_desc - The Package object on which to resolve refs + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package and turn internal references into values + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_resolve_package_references ( + ACPI_OPERAND_OBJECT *obj_desc) +{ + u32 count; + ACPI_OPERAND_OBJECT *sub_object; + + + if (obj_desc->common.type != ACPI_TYPE_PACKAGE) { + /* The object must be a package */ + + REPORT_ERROR (("Must resolve Package Refs on a Package\n")); + return(AE_ERROR); + } + + /* + * TBD: what about nested packages? */ + + for (count = 0; count < obj_desc->package.count; count++) { + sub_object = obj_desc->package.elements[count]; + + if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) { + if (sub_object->reference.opcode == AML_ZERO_OP) { + sub_object->common.type = ACPI_TYPE_INTEGER; + sub_object->integer.value = 0; + } + + else if (sub_object->reference.opcode == AML_ONE_OP) { + sub_object->common.type = ACPI_TYPE_INTEGER; + sub_object->integer.value = 1; + } + + else if (sub_object->reference.opcode == AML_ONES_OP) { + sub_object->common.type = ACPI_TYPE_INTEGER; + sub_object->integer.value = ACPI_INTEGER_MAX; + } + } + } + + return(AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_cm_walk_package_tree + * + * PARAMETERS: Obj_desc - The Package object on which to resolve refs + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package + * + ******************************************************************************/ + +ACPI_STATUS +acpi_cm_walk_package_tree ( + ACPI_OPERAND_OBJECT *source_object, + void *target_object, + ACPI_PKG_CALLBACK walk_callback, + void *context) +{ + ACPI_STATUS status = AE_OK; + ACPI_GENERIC_STATE *state_list = NULL; + ACPI_GENERIC_STATE *state; + u32 this_index; + ACPI_OPERAND_OBJECT *this_source_obj; + + + state = acpi_cm_create_pkg_state (source_object, target_object, 0); + if (!state) { + return (AE_NO_MEMORY); + } + + while (state) { + this_index = state->pkg.index; + this_source_obj = (ACPI_OPERAND_OBJECT *) + state->pkg.source_object->package.elements[this_index]; + + /* + * Check for + * 1) An uninitialized package element. It is completely + * legal to declare a package and leave it uninitialized + * 2) Not an internal object - can be a namespace node instead + * 3) Any type other than a package. Packages are handled in else + * case below. + */ + if ((!this_source_obj) || + (!VALID_DESCRIPTOR_TYPE ( + this_source_obj, ACPI_DESC_TYPE_INTERNAL)) || + (!IS_THIS_OBJECT_TYPE ( + this_source_obj, ACPI_TYPE_PACKAGE))) { + + status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj, + state, context); + if (ACPI_FAILURE (status)) { + /* TBD: must delete package created up to this point */ + + return (status); + } + + state->pkg.index++; + while (state->pkg.index >= state->pkg.source_object->package.count) { + /* + * We've handled all of the objects at this level, This means + * that we have just completed a package. That package may + * have contained one or more packages itself. + * + * Delete this state and pop the previous state (package). + */ + acpi_cm_delete_generic_state (state); + state = acpi_cm_pop_generic_state (&state_list); + + + /* Finished when there are no more states */ + + if (!state) { + /* + * We have handled all of the objects in the top level + * package just add the length of the package objects + * and exit + */ + return (AE_OK); + } + + /* + * Go back up a level and move the index past the just + * completed package object. + */ + state->pkg.index++; + } + } + + else { + /* This is a sub-object of type package */ + + status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj, + state, context); + if (ACPI_FAILURE (status)) { + /* TBD: must delete package created up to this point */ + + return (status); + } + + + /* + * The callback above returned a new target package object. + */ + + /* + * Push the current state and create a new one + */ + acpi_cm_push_generic_state (&state_list, state); + state = acpi_cm_create_pkg_state (this_source_obj, + state->pkg.this_target_obj, 0); + if (!state) { + /* TBD: must delete package created up to this point */ + + return (AE_NO_MEMORY); + } + } + } + + /* We should never get here */ + + return (AE_AML_INTERNAL); + +} + + +/******************************************************************************* + * + * FUNCTION: _Report_error + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print error message + * + ******************************************************************************/ + +void +_report_error ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + + + acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number); +} + + +/******************************************************************************* + * + * FUNCTION: _Report_warning + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print warning message + * + ******************************************************************************/ + +void +_report_warning ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + + acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number); +} + + +/******************************************************************************* + * + * FUNCTION: _Report_info + * + * PARAMETERS: Module_name - Caller's module name (for error output) + * Line_number - Caller's line number (for error output) + * Component_id - Caller's component ID (for error output) + * Message - Error message to use on failure + * + * RETURN: None + * + * DESCRIPTION: Print information message + * + ******************************************************************************/ + +void +_report_info ( + NATIVE_CHAR *module_name, + u32 line_number, + u32 component_id) +{ + + acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number); +} + + diff --git a/drivers/bus/acpi/utils/cmxface.c b/drivers/bus/acpi/utils/cmxface.c new file mode 100644 index 0000000..6832aef --- /dev/null +++ b/drivers/bus/acpi/utils/cmxface.c @@ -0,0 +1,459 @@ +/****************************************************************************** + * + * Module Name: cmxface - External interfaces for "global" ACPI functions + * $Revision$ + * + *****************************************************************************/ + +/* + * Copyright (C) 2000, 2001 R. Byron Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "acpi.h" +#include "acevents.h" +#include "achware.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_UTILITIES + MODULE_NAME ("cmxface") + + +/******************************************************************************* + * + * FUNCTION: Acpi_initialize_subsystem + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_initialize_subsystem ( + void) +{ + ACPI_STATUS status; + + + /* Initialize all globals used by the subsystem */ + + acpi_cm_init_globals (); + + /* Initialize the OS-Dependent layer */ + + status = acpi_os_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("OSD failed to initialize, %s\n", + acpi_cm_format_exception (status))); + return (status); + } + + /* Create the default mutex objects */ + + status = acpi_cm_mutex_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Global mutex creation failure, %s\n", + acpi_cm_format_exception (status))); + return (status); + } + + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + + status = acpi_ns_root_initialize (); + if (ACPI_FAILURE (status)) { + REPORT_ERROR (("Namespace initialization failure, %s\n", + acpi_cm_format_exception (status))); + return (status); + } + + + /* If configured, initialize the AML debugger */ + + DEBUGGER_EXEC (acpi_db_initialize ()); + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_enable_subsystem + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_enable_subsystem ( + u32 flags) +{ + ACPI_STATUS status = AE_OK; + + + /* Sanity check the FADT for valid values */ + + status = acpi_cm_validate_fadt (); + if (ACPI_FAILURE (status)) { + return (status); + } + + /* + * Install the default Op_region handlers. These are + * installed unless other handlers have already been + * installed via the Install_address_space_handler interface + */ + + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + status = acpi_ev_install_default_address_space_handlers (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * We must initialize the hardware before we can enable ACPI. + */ + + if (!(flags & ACPI_NO_HARDWARE_INIT)) { + status = acpi_hw_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Enable ACPI on this platform + */ + + if (!(flags & ACPI_NO_ACPI_ENABLE)) { + status = acpi_enable (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + /* + * Note: + * We must have the hardware AND events initialized before we can execute + * ANY control methods SAFELY. Any control method can require ACPI hardware + * support, so the hardware MUST be initialized before execution! + */ + + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_initialize (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* + * Initialize all device objects in the namespace + * This runs the _STA and _INI methods. + */ + + if (!(flags & ACPI_NO_DEVICE_INIT)) { + status = acpi_ns_initialize_devices (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + /* + * Initialize the objects that remain uninitialized. This + * runs the executable AML that is part of the declaration of Op_regions + * and Fields. + */ + + if (!(flags & ACPI_NO_OBJECT_INIT)) { + status = acpi_ns_initialize_objects (); + if (ACPI_FAILURE (status)) { + return (status); + } + } + + + return (status); +} + + +/******************************************************************************* + * + * FUNCTION: Acpi_terminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_terminate (void) +{ + + /* Terminate the AML Debuger if present */ + + DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); + + /* TBD: [Investigate] This is no longer needed?*/ +/* Acpi_cm_release_mutex (ACPI_MTX_DEBUG_CMD_READY); */ + + + /* Shutdown and free all resources */ + + acpi_cm_subsystem_shutdown (); + + + /* Free the mutex objects */ + + acpi_cm_mutex_terminate (); + + + /* Now we can shutdown the OS-dependent layer */ + + acpi_os_terminate (); + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_get_system_info + * + * PARAMETERS: Out_buffer - a pointer to a buffer to receive the + * resources for the device + * Buffer_length - the number of bytes available in the buffer + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get information about the current + * state of the ACPI subsystem. It will return system information + * in the Out_buffer. + * + * If the function fails an appropriate status will be returned + * and the value of Out_buffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_get_system_info ( + ACPI_BUFFER *out_buffer) +{ + ACPI_SYSTEM_INFO *info_ptr; + u32 i; + + + /* + * Must have a valid buffer + */ + if ((!out_buffer) || + (!out_buffer->pointer)) { + return (AE_BAD_PARAMETER); + } + + if (out_buffer->length < sizeof (ACPI_SYSTEM_INFO)) { + /* + * Caller's buffer is too small + */ + out_buffer->length = sizeof (ACPI_SYSTEM_INFO); + + return (AE_BUFFER_OVERFLOW); + } + + + /* + * Set return length and get data + */ + out_buffer->length = sizeof (ACPI_SYSTEM_INFO); + info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer; + + info_ptr->acpi_ca_version = ACPI_CA_VERSION; + + /* System flags (ACPI capabilities) */ + + info_ptr->flags = acpi_gbl_system_flags; + + /* Timer resolution - 24 or 32 bits */ + if (!acpi_gbl_FADT) { + info_ptr->timer_resolution = 0; + } + else if (acpi_gbl_FADT->tmr_val_ext == 0) { + info_ptr->timer_resolution = 24; + } + else { + info_ptr->timer_resolution = 32; + } + + /* Clear the reserved fields */ + + info_ptr->reserved1 = 0; + info_ptr->reserved2 = 0; + + /* Current debug levels */ + + info_ptr->debug_layer = acpi_dbg_layer; + info_ptr->debug_level = acpi_dbg_level; + + /* Current status of the ACPI tables, per table type */ + + info_ptr->num_table_types = NUM_ACPI_TABLES; + for (i = 0; i < NUM_ACPI_TABLES; i++) { + info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: Acpi_format_exception + * + * PARAMETERS: Out_buffer - a pointer to a buffer to receive the + * exception name + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string. + * + ******************************************************************************/ + +ACPI_STATUS +acpi_format_exception ( + ACPI_STATUS exception, + ACPI_BUFFER *out_buffer) +{ + u32 length; + NATIVE_CHAR *formatted_exception; + + + /* + * Must have a valid buffer + */ + if ((!out_buffer) || + (!out_buffer->pointer)) { + return (AE_BAD_PARAMETER); + } + + + /* Convert the exception code (Handles bad exception codes) */ + + formatted_exception = acpi_cm_format_exception (exception); + + /* + * Get length of string and check if it will fit in caller's buffer + */ + + length = STRLEN (formatted_exception); + if (out_buffer->length < length) { + out_buffer->length = length; + return (AE_BUFFER_OVERFLOW); + } + + + /* Copy the string, all done */ + + STRCPY (out_buffer->pointer, formatted_exception); + + return (AE_OK); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_allocate + * + * PARAMETERS: Size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * External front-end to the Cm* memory manager + * + ****************************************************************************/ + +void * +acpi_allocate ( + u32 size) +{ + + return (acpi_cm_allocate (size)); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_callocate + * + * PARAMETERS: Size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of calloc. + * External front-end to the Cm* memory manager + * + ****************************************************************************/ + +void * +acpi_callocate ( + u32 size) +{ + + return (acpi_cm_callocate (size)); +} + + +/***************************************************************************** + * + * FUNCTION: Acpi_free + * + * PARAMETERS: Address - Address of the memory to deallocate + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Address + * External front-end to the Cm* memory manager + * + ****************************************************************************/ + +void +acpi_free ( + void *address) +{ + + acpi_cm_free (address); +} diff --git a/drivers/bus/isapnp/.cvsignore b/drivers/bus/isapnp/.cvsignore new file mode 100644 index 0000000..3481446 --- /dev/null +++ b/drivers/bus/isapnp/.cvsignore @@ -0,0 +1,8 @@ +base.tmp +junk.tmp +temp.exp +isapnp.coff +isapnp.sys.unstripped +*.d +*.o +*.sym diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c new file mode 100644 index 0000000..ae6569d --- /dev/null +++ b/drivers/bus/isapnp/isapnp.c @@ -0,0 +1,1718 @@ +/* $Id$ + * + * PROJECT: ReactOS ISA PnP Bus driver + * FILE: isapnp.c + * PURPOSE: Driver entry + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTE: Parts adapted from linux ISA PnP driver + * UPDATE HISTORY: + * 01-05-2001 CSH Created + */ +#include +#include + +#define NDEBUG +#include + + +#ifdef ALLOC_PRAGMA + +// Make the initialization routines discardable, so that they +// don't waste space + +#pragma alloc_text(init, DriverEntry) + +// Make the PASSIVE_LEVEL routines pageable, so that they don't +// waste nonpaged memory + +#pragma alloc_text(page, ACPIDispatchOpenClose) +#pragma alloc_text(page, ACPIDispatchRead) +#pragma alloc_text(page, ACPIDispatchWrite) + +#endif /* ALLOC_PRAGMA */ + + +PUCHAR IsaPnPReadPort; + + +#define UCHAR2USHORT(v0, v1) \ + ((v1 << 8) | v0) + +#define UCHAR2ULONG(v0, v1, v2, v3) \ + ((UCHAR2USHORT(v2, v3) << 16) | UCHAR2USHORT(v0, v1)) + + +#ifndef NDEBUG + +struct +{ + PCH Name; +} SmallTags[] = { + {"Unknown Small Tag"}, + {"ISAPNP_SRIN_VERSION"}, + {"ISAPNP_SRIN_LDEVICE_ID"}, + {"ISAPNP_SRIN_CDEVICE_ID"}, + {"ISAPNP_SRIN_IRQ_FORMAT"}, + {"ISAPNP_SRIN_DMA_FORMAT"}, + {"ISAPNP_SRIN_START_DFUNCTION"}, + {"ISAPNP_SRIN_END_DFUNCTION"}, + {"ISAPNP_SRIN_IO_DESCRIPTOR"}, + {"ISAPNP_SRIN_FL_IO_DESCRIPOTOR"}, + {"Reserved Small Tag"}, + {"Reserved Small Tag"}, + {"Reserved Small Tag"}, + {"Reserved Small Tag"}, + {"ISAPNP_SRIN_VENDOR_DEFINED"}, + {"ISAPNP_SRIN_END_TAG"} +}; + +struct +{ + PCH Name; +} LargeTags[] = { + {"Unknown Large Tag"}, + {"ISAPNP_LRIN_MEMORY_RANGE"}, + {"ISAPNP_LRIN_ID_STRING_ANSI"}, + {"ISAPNP_LRIN_ID_STRING_UNICODE"}, + {"ISAPNP_LRIN_VENDOR_DEFINED"}, + {"ISAPNP_LRIN_MEMORY_RANGE32"}, + {"ISAPNP_LRIN_FL_MEMORY_RANGE32"} +}; + +PCSZ TagName(ULONG Tag, BOOLEAN Small) +{ + if (Small && (Tag <= ISAPNP_SRIN_END_TAG)) { + return SmallTags[Tag].Name; + } else if (Tag <= ISAPNP_LRIN_FL_MEMORY_RANGE32){ + return LargeTags[Tag].Name; + } + + return NULL; +} + +#endif + +static inline VOID WriteData(UCHAR Value) +{ + WRITE_PORT_UCHAR((PUCHAR)ISAPNP_WRITE_PORT, Value); +} + +static inline VOID WriteAddress(UCHAR Value) +{ + WRITE_PORT_UCHAR((PUCHAR)ISAPNP_ADDRESS_PORT, Value); + KeStallExecutionProcessor(20); +} + +static inline UCHAR ReadData(VOID) +{ + return READ_PORT_UCHAR(IsaPnPReadPort); +} + +UCHAR ReadUchar(UCHAR Index) +{ + WriteAddress(Index); + return ReadData(); +} + +USHORT ReadUshort(UCHAR Index) +{ + USHORT Value; + + Value = ReadUchar(Index); + Value = (Value << 8) + ReadUchar(Index + 1); + return Value; +} + +ULONG ReadUlong(UCHAR Index) +{ + ULONG Value; + + Value = ReadUchar(Index); + Value = (Value << 8) + ReadUchar(Index + 1); + Value = (Value << 8) + ReadUchar(Index + 2); + Value = (Value << 8) + ReadUchar(Index + 3); + return Value; +} + +VOID WriteUchar(UCHAR Index, UCHAR Value) +{ + WriteAddress(Index); + WriteData(Value); +} + +VOID WriteUshort(UCHAR Index, USHORT Value) +{ + WriteUchar(Index, Value >> 8); + WriteUchar(Index + 1, Value); +} + +VOID WriteUlong(UCHAR Index, ULONG Value) +{ + WriteUchar(Index, Value >> 24); + WriteUchar(Index + 1, Value >> 16); + WriteUchar(Index + 2, Value >> 8); + WriteUchar(Index + 3, Value); +} + +static inline VOID SetReadDataPort(ULONG Port) +{ + IsaPnPReadPort = (PUCHAR)Port; + WriteUchar(0x00, Port >> 2); + KeStallExecutionProcessor(100); +} + +static VOID SendKey(VOID) +{ + ULONG i; + UCHAR msb; + UCHAR code; + + /* FIXME: Is there something better? */ + KeStallExecutionProcessor(1000); + WriteAddress(0x00); + WriteAddress(0x00); + + code = 0x6a; + WriteAddress(code); + for (i = 1; i < 32; i++) { + msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7; + code = (code >> 1) | msb; + WriteAddress(code); + } +} + +/* Place all PnP cards in wait-for-key state */ +static VOID SendWait(VOID) +{ + WriteUchar(0x02, 0x02); +} + +VOID SendWake(UCHAR csn) +{ + WriteUchar(ISAPNP_CARD_WAKECSN, csn); +} + +VOID SelectLogicalDevice(UCHAR LogicalDevice) +{ + WriteUchar(ISAPNP_CARD_LOG_DEVICE_NUM, LogicalDevice); +} + +VOID ActivateLogicalDevice(UCHAR LogicalDevice) +{ + SelectLogicalDevice(LogicalDevice); + WriteUchar(ISAPNP_CONTROL_ACTIVATE, 0x1); + KeStallExecutionProcessor(250); +} + +VOID DeactivateLogicalDevice(UCHAR LogicalDevice) +{ + SelectLogicalDevice(LogicalDevice); + WriteUchar(ISAPNP_CONTROL_ACTIVATE, 0x0); + KeStallExecutionProcessor(500); +} + +#define READ_DATA_PORT_STEP 32 /* Minimum is 4 */ + +static ULONG FindNextReadPort(VOID) +{ + ULONG Port; + + Port = (ULONG)IsaPnPReadPort; + while (Port <= ISAPNP_MAX_READ_PORT) { + /* + * We cannot use NE2000 probe spaces for + * ISAPnP or we will lock up machines + */ + if ((Port < 0x280) || (Port > 0x380)) + { + return Port; + } + Port += READ_DATA_PORT_STEP; + } + return 0; +} + +static BOOLEAN IsolateReadDataPortSelect(VOID) +{ + ULONG Port; + + SendWait(); + SendKey(); + + /* Control: reset CSN and conditionally everything else too */ + WriteUchar(0x02, 0x05); + KeStallExecutionProcessor(2000); + + SendWait(); + SendKey(); + SendWake(0x00); + + Port = FindNextReadPort(); + if (Port == 0) { + SendWait(); + return FALSE; + } + + SetReadDataPort(Port); + KeStallExecutionProcessor(1000); + WriteAddress(0x01); + KeStallExecutionProcessor(1000); + return TRUE; +} + +/* + * Isolate (assign uniqued CSN) to all ISA PnP devices + */ +static ULONG IsolatePnPCards(VOID) +{ + UCHAR checksum = 0x6a; + UCHAR chksum = 0x00; + UCHAR bit = 0x00; + ULONG data; + ULONG csn = 0; + ULONG i; + ULONG iteration = 1; + + DPRINT("Called\n"); + + IsaPnPReadPort = (PUCHAR)ISAPNP_MIN_READ_PORT; + if (!IsolateReadDataPortSelect()) { + DPRINT("Could not set read data port\n"); + return 0; + } + + while (TRUE) { + for (i = 1; i <= 64; i++) { + data = ReadData() << 8; + KeStallExecutionProcessor(250); + data = data | ReadData(); + KeStallExecutionProcessor(250); + if (data == 0x55aa) + bit = 0x01; + checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1); + bit = 0x00; + } + for (i = 65; i <= 72; i++) { + data = ReadData() << 8; + KeStallExecutionProcessor(250); + data = data | ReadData(); + KeStallExecutionProcessor(250); + if (data == 0x55aa) + chksum |= (1 << (i - 65)); + } + if ((checksum != 0x00) && (checksum == chksum)) { + csn++; + + WriteUchar(0x06, csn); + KeStallExecutionProcessor(250); + iteration++; + SendWake(0x00); + SetReadDataPort((ULONG)IsaPnPReadPort); + KeStallExecutionProcessor(1000); + WriteAddress(0x01); + KeStallExecutionProcessor(1000); + goto next; + } + if (iteration == 1) { + IsaPnPReadPort += READ_DATA_PORT_STEP; + if (!IsolateReadDataPortSelect()) { + DPRINT("Could not set read data port\n"); + return 0; + } + } else if (iteration > 1) { + break; + } +next: + checksum = 0x6a; + chksum = 0x00; + bit = 0x00; + } + SendWait(); + return csn; +} + + +VOID Peek(PUCHAR Data, ULONG Count) +{ + ULONG i, j; + UCHAR d = 0; + + for (i = 1; i <= Count; i++) { + for (j = 0; j < 20; j++) { + d = ReadUchar(0x05); + if (d & 0x1) + break; + KeStallExecutionProcessor(100); + } + if (!(d & 0x1)) { + if (Data != NULL) + *Data++ = 0xff; + continue; + } + d = ReadUchar(0x04); /* PRESDI */ + if (Data != NULL) + *Data++ = d; + } +} + + +/* + * Skip specified number of bytes from stream + */ +static VOID Skip(ULONG Count) +{ + Peek(NULL, Count); +} + + +/* + * Read one tag from stream + */ +static BOOLEAN ReadTag(PUCHAR Type, + PUSHORT Size, + PBOOLEAN Small) +{ + UCHAR tag, tmp[2]; + + Peek(&tag, 1); + if (tag == 0) { + /* Invalid tag */ + DPRINT("Invalid tag with value 0\n"); +#ifndef NDEBUG + for (;;); +#endif + return FALSE; + } + + if (tag & ISAPNP_RESOURCE_ITEM_TYPE) { + /* Large resource item */ + *Type = (tag & 0x7f); + Peek(tmp, 2); + *Size = UCHAR2USHORT(tmp[0], tmp[1]); + *Small = FALSE; +#ifndef NDEBUG + if (*Type > ISAPNP_LRIN_FL_MEMORY_RANGE32) { + DPRINT("Invalid large tag with value 0x%X\n", *Type); + for (;;); + } +#endif + } else { + /* Small resource item */ + *Type = (tag >> 3) & 0x0f; + *Size = tag & 0x07; + *Small = TRUE; +#ifndef NDEBUG + if (*Type > ISAPNP_SRIN_END_TAG) { + DPRINT("Invalid small tag with value 0x%X\n", *Type); + for (;;); + } +#endif + } + + DPRINT("Tag = 0x%X, Type = 0x%X, Size = %d (%s)\n", + tag, *Type, *Size, TagName(*Type, *Small)); + + /* Probably invalid data */ + if ((*Type == 0xff) && (*Size == 0xffff)) { + DPRINT("Invalid data (Type 0x%X Size 0x%X)\n", *Type, *Size); + for (;;); + return FALSE; + } + + return TRUE; +} + + +/* + * Parse ANSI name for ISA PnP logical device + */ +static NTSTATUS ParseAnsiName(PUNICODE_STRING Name, PUSHORT Size) +{ + ANSI_STRING AnsiString; + UCHAR Buffer[256]; + USHORT size1; + + size1 = (*Size >= sizeof(Buffer)) ? (sizeof(Buffer) - 1) : *Size; + + Peek(Buffer, size1); + Buffer[size1] = '\0'; + *Size -= size1; + + /* Clean whitespace from end of string */ + while ((size1 > 0) && (Buffer[--size1] == ' ')) + Buffer[size1] = '\0'; + + DPRINT("ANSI name: %s\n", Buffer); + + RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer); + return RtlAnsiStringToUnicodeString(Name, &AnsiString, TRUE); +} + + +/* + * Add a resource list to the + * resource lists of a logical device + */ +static NTSTATUS AddResourceList( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Priority, + PISAPNP_CONFIGURATION_LIST *NewList) +{ + PISAPNP_CONFIGURATION_LIST List; + NTSTATUS Status; + + DPRINT("Adding resource list for logical device %d on card %d (Priority %d)\n", + LogicalDevice->Number, + LogicalDevice->Card->CardId, + Priority); + + List = (PISAPNP_CONFIGURATION_LIST) + ExAllocatePool(PagedPool, sizeof(ISAPNP_CONFIGURATION_LIST)); + if (!List) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(List, sizeof(ISAPNP_CONFIGURATION_LIST)); + + List->Priority = Priority; + + InitializeListHead(&List->ListHead); + + InsertTailList(&LogicalDevice->Configuration, &List->ListEntry); + + *NewList = List; + + return STATUS_SUCCESS; +} + + +/* + * Add a resource entry to the + * resource list of a logical device + */ +static NTSTATUS AddResourceDescriptor( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Priority, + ULONG Option, + PISAPNP_DESCRIPTOR *Descriptor) +{ + PLIST_ENTRY CurrentEntry; + PISAPNP_CONFIGURATION_LIST List; + PISAPNP_DESCRIPTOR d; + NTSTATUS Status; + + DPRINT("Adding resource descriptor for logical device %d on card %d (%d of %d)\n", + LogicalDevice->Number, + LogicalDevice->Card->CardId, + LogicalDevice->CurrentDescriptorCount, + LogicalDevice->DescriptorCount); + + d = (PISAPNP_DESCRIPTOR) + ExAllocatePool(PagedPool, sizeof(ISAPNP_DESCRIPTOR)); + if (!d) + return Status; + + RtlZeroMemory(d, sizeof(ISAPNP_DESCRIPTOR)); + + d->Descriptor.Option = Option; + + *Descriptor = d; + + CurrentEntry = LogicalDevice->Configuration.Flink; + while (CurrentEntry != &LogicalDevice->Configuration) { + List = CONTAINING_RECORD( + CurrentEntry, ISAPNP_CONFIGURATION_LIST, ListEntry); + + if (List->Priority == Priority) { + + LogicalDevice->ConfigurationSize += sizeof(IO_RESOURCE_DESCRIPTOR); + InsertTailList(&List->ListHead, &d->ListEntry); + LogicalDevice->CurrentDescriptorCount++; + if (LogicalDevice->DescriptorCount < + LogicalDevice->CurrentDescriptorCount) { + LogicalDevice->DescriptorCount = + LogicalDevice->CurrentDescriptorCount; + } + + return STATUS_SUCCESS; + } + CurrentEntry = CurrentEntry->Flink; + } + + Status = AddResourceList(LogicalDevice, Priority, &List); + if (NT_SUCCESS(Status)) { + LogicalDevice->ConfigurationSize += sizeof(IO_RESOURCE_LIST); + LogicalDevice->CurrentDescriptorCount = 0; + InsertTailList(&List->ListHead, &d->ListEntry); + } + + return Status; +} + + +/* + * Add IRQ resource to resources list + */ +static NTSTATUS AddIrqResource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[3]; + ULONG irq, i, last; + BOOLEAN found; + NTSTATUS Status; + + Peek(tmp, Size); + + irq = UCHAR2USHORT(tmp[0], tmp[0]); + + DPRINT("IRQ bitmask: 0x%X\n", irq); + + found = FALSE; + for (i = 0; i < 16; i++) { + if (!found && (irq & (1 << i))) { + last = i; + found = TRUE; + } + + if ((found && !(irq & (1 << i))) || (irq & (1 << i) && (i == 15))) { + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypeInterrupt; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Interrupt.MinimumVector = last; + + if ((irq & (1 << i)) && (i == 15)) + Descriptor->Descriptor.u.Interrupt.MaximumVector = i; + else + Descriptor->Descriptor.u.Interrupt.MaximumVector = i - 1; + + DPRINT("Found IRQ range %d - %d for logical device %d on card %d\n", + Descriptor->Descriptor.u.Interrupt.MinimumVector, + Descriptor->Descriptor.u.Interrupt.MaximumVector, + LogicalDevice->Number, + LogicalDevice->Card->CardId); + + found = FALSE; + } + } + + return STATUS_SUCCESS; +} + +/* + * Add DMA resource to resources list + */ +static NTSTATUS AddDmaResource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[2]; + ULONG dma, flags, i, last; + BOOLEAN found; + NTSTATUS Status; + + Peek(tmp, Size); + + dma = tmp[0]; + flags = tmp[1]; + + DPRINT("DMA bitmask: 0x%X\n", dma); + + found = FALSE; + for (i = 0; i < 8; i++) { + if (!found && (dma & (1 << i))) { + last = i; + found = TRUE; + } + + if ((found && !(dma & (1 << i))) || (dma & (1 << i) && (i == 15))) { + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypeDma; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Dma.MinimumChannel = last; + + if ((dma & (1 << i)) && (i == 15)) + Descriptor->Descriptor.u.Dma.MaximumChannel = i; + else + Descriptor->Descriptor.u.Dma.MaximumChannel = i - 1; + + /* FIXME: Parse flags */ + + DPRINT("Found DMA range %d - %d for logical device %d on card %d\n", + Descriptor->Descriptor.u.Dma.MinimumChannel, + Descriptor->Descriptor.u.Dma.MaximumChannel, + LogicalDevice->Number, + LogicalDevice->Card->CardId); + + found = FALSE; + } + } + + return STATUS_SUCCESS; +} + +/* + * Add port resource to resources list + */ +static NTSTATUS AddIOPortResource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ +#if 0 + DPRINT("I/O port: size 0x%X\n", Size); + Skip(Size); +#else + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[7]; + NTSTATUS Status; + + Peek(tmp, Size); + + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypePort; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Port.Length = tmp[6]; + /* FIXME: Parse flags */ + Descriptor->Descriptor.u.Port.Alignment = 0; + Descriptor->Descriptor.u.Port.MinimumAddress.QuadPart = UCHAR2USHORT(tmp[1], tmp[2]); + Descriptor->Descriptor.u.Port.MaximumAddress.QuadPart = UCHAR2USHORT(tmp[4], tmp[4]); + + DPRINT("Found I/O port range 0x%X - 0x%X for logical device %d on card %d\n", + Descriptor->Descriptor.u.Port.MinimumAddress, + Descriptor->Descriptor.u.Port.MaximumAddress, + LogicalDevice->Number, + LogicalDevice->Card->CardId); +#endif + return STATUS_SUCCESS; +} + +/* + * Add fixed port resource to resources list + */ +static NTSTATUS AddFixedIOPortResource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ +#if 0 + DPRINT("Fixed I/O port: size 0x%X\n", Size); + Skip(Size); +#else + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[3]; + NTSTATUS Status; + + Peek(tmp, Size); + + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypePort; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Port.Length = tmp[2]; + Descriptor->Descriptor.u.Port.Alignment = 0; + Descriptor->Descriptor.u.Port.MinimumAddress.QuadPart = UCHAR2USHORT(tmp[0], tmp[1]); + Descriptor->Descriptor.u.Port.MaximumAddress.QuadPart = UCHAR2USHORT(tmp[0], tmp[1]); + + DPRINT("Found fixed I/O port range 0x%X - 0x%X for logical device %d on card %d\n", + Descriptor->Descriptor.u.Port.MinimumAddress, + Descriptor->Descriptor.u.Port.MaximumAddress, + LogicalDevice->Number, + LogicalDevice->Card->CardId); +#endif + return STATUS_SUCCESS; +} + +/* + * Add memory resource to resources list + */ +static NTSTATUS AddMemoryResource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ +#if 0 + DPRINT("Memory range: size 0x%X\n", Size); + Skip(Size); +#else + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[9]; + NTSTATUS Status; + + Peek(tmp, Size); + + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypeMemory; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Memory.Length = UCHAR2USHORT(tmp[7], tmp[8]) << 8; + Descriptor->Descriptor.u.Memory.Alignment = UCHAR2USHORT(tmp[5], tmp[6]); + Descriptor->Descriptor.u.Memory.MinimumAddress.QuadPart = UCHAR2USHORT(tmp[1], tmp[2]) << 8; + Descriptor->Descriptor.u.Memory.MaximumAddress.QuadPart = UCHAR2USHORT(tmp[3], tmp[4]) << 8; + + DPRINT("Found memory range 0x%X - 0x%X for logical device %d on card %d\n", + Descriptor->Descriptor.u.Memory.MinimumAddress, + Descriptor->Descriptor.u.Memory.MaximumAddress, + LogicalDevice->Number, + LogicalDevice->Card->CardId); +#endif + return STATUS_SUCCESS; +} + +/* + * Add 32-bit memory resource to resources list + */ +static NTSTATUS AddMemory32Resource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ +#if 0 + DPRINT("Memory32 range: size 0x%X\n", Size); + Skip(Size); +#else + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[17]; + NTSTATUS Status; + + Peek(tmp, Size); + + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypeMemory; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Memory.Length = + UCHAR2ULONG(tmp[13], tmp[14], tmp[15], tmp[16]); + Descriptor->Descriptor.u.Memory.Alignment = + UCHAR2ULONG(tmp[9], tmp[10], tmp[11], tmp[12]); + Descriptor->Descriptor.u.Memory.MinimumAddress.QuadPart = + UCHAR2ULONG(tmp[1], tmp[2], tmp[3], tmp[4]); + Descriptor->Descriptor.u.Memory.MaximumAddress.QuadPart = + UCHAR2ULONG(tmp[5], tmp[6], tmp[7], tmp[8]); + + DPRINT("Found memory32 range 0x%X - 0x%X for logical device %d on card %d\n", + Descriptor->Descriptor.u.Memory.MinimumAddress, + Descriptor->Descriptor.u.Memory.MaximumAddress, + LogicalDevice->Number, + LogicalDevice->Card->CardId); +#endif + return STATUS_SUCCESS; +} + +/* + * Add 32-bit fixed memory resource to resources list + */ +static NTSTATUS AddFixedMemory32Resource( + PISAPNP_LOGICAL_DEVICE LogicalDevice, + ULONG Size, + ULONG Priority, + ULONG Option) +{ +#if 0 + DPRINT("Memory32 range: size 0x%X\n", Size); + Skip(Size); +#else + PISAPNP_DESCRIPTOR Descriptor; + UCHAR tmp[17]; + NTSTATUS Status; + + Peek(tmp, Size); + + Status = AddResourceDescriptor(LogicalDevice, + Priority, Option, &Descriptor); + if (!NT_SUCCESS(Status)) + return Status; + Descriptor->Descriptor.Type = CmResourceTypeMemory; + Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Descriptor.u.Memory.Length = + UCHAR2ULONG(tmp[9], tmp[10], tmp[11], tmp[12]); + Descriptor->Descriptor.u.Memory.Alignment = + UCHAR2ULONG(tmp[5], tmp[6], tmp[7], tmp[8]); + Descriptor->Descriptor.u.Memory.MinimumAddress.QuadPart = + UCHAR2ULONG(tmp[1], tmp[2], tmp[3], tmp[4]); + Descriptor->Descriptor.u.Memory.MaximumAddress.QuadPart = + UCHAR2ULONG(tmp[1], tmp[2], tmp[3], tmp[4]); + + DPRINT("Found fixed memory32 range 0x%X - 0x%X for logical device %d on card %d\n", + Descriptor->Descriptor.u.Memory.MinimumAddress, + Descriptor->Descriptor.u.Memory.MaximumAddress, + LogicalDevice->Number, + LogicalDevice->Card->CardId); +#endif + return STATUS_SUCCESS; +} + + +/* + * Parse logical device tag + */ +static PISAPNP_LOGICAL_DEVICE ParseLogicalDevice( + PISAPNP_DEVICE_EXTENSION DeviceExtension, + PISAPNP_CARD Card, + ULONG Size, + USHORT Number) +{ + UCHAR tmp[6]; + PISAPNP_LOGICAL_DEVICE LogicalDevice; + + DPRINT("Card %d Number %d\n", Card->CardId, Number); + + Peek(tmp, Size); + + LogicalDevice = (PISAPNP_LOGICAL_DEVICE)ExAllocatePool( + PagedPool, sizeof(ISAPNP_LOGICAL_DEVICE)); + if (!LogicalDevice) + return NULL; + + RtlZeroMemory(LogicalDevice, sizeof(ISAPNP_LOGICAL_DEVICE)); + + LogicalDevice->Number = Number; + LogicalDevice->VendorId = UCHAR2USHORT(tmp[0], tmp[1]); + LogicalDevice->DeviceId = UCHAR2USHORT(tmp[2], tmp[3]); + LogicalDevice->Regs = tmp[4]; + LogicalDevice->Card = Card; + if (Size > 5) + LogicalDevice->Regs |= tmp[5] << 8; + + InitializeListHead(&LogicalDevice->Configuration); + + ExInterlockedInsertTailList(&Card->LogicalDevices, + &LogicalDevice->CardListEntry, + &Card->LogicalDevicesLock); + + ExInterlockedInsertTailList(&DeviceExtension->DeviceListHead, + &LogicalDevice->DeviceListEntry, + &DeviceExtension->GlobalListLock); + + DeviceExtension->DeviceListCount++; + + return LogicalDevice; +} + + +/* + * Parse resource map for logical device + */ +static BOOLEAN CreateLogicalDevice(PISAPNP_DEVICE_EXTENSION DeviceExtension, + PISAPNP_CARD Card, USHORT Size) +{ + ULONG number = 0, skip = 0, compat = 0; + UCHAR type, tmp[17]; + PISAPNP_LOGICAL_DEVICE LogicalDevice; + BOOLEAN Small; + ULONG Priority = 0; + ULONG Option = IO_RESOURCE_REQUIRED; + + DPRINT("Card %d Size %d\n", Card->CardId, Size); + + LogicalDevice = ParseLogicalDevice(DeviceExtension, Card, Size, number++); + if (!LogicalDevice) + return FALSE; + + while (TRUE) { + if (!ReadTag(&type, &Size, &Small)) + return FALSE; + + if (skip && !(Small && (type == ISAPNP_SRIN_LDEVICE_ID) + || (type == ISAPNP_SRIN_END_TAG))) + goto skip; + + if (Small) { + switch (type) { + case ISAPNP_SRIN_LDEVICE_ID: + if ((Size >= 5) && (Size <= 6)) { + LogicalDevice = ParseLogicalDevice( + DeviceExtension, Card, Size, number++); + if (!LogicalDevice) + return FALSE; + Size = 0; + skip = 0; + } else { + skip = 1; + } + Priority = 0; + Option = IO_RESOURCE_REQUIRED; + compat = 0; + break; + + case ISAPNP_SRIN_CDEVICE_ID: + if ((Size == 4) && (compat < MAX_COMPATIBLE_ID)) { + Peek(tmp, 4); + LogicalDevice->CVendorId[compat] = UCHAR2USHORT(tmp[0], tmp[1]); + LogicalDevice->CDeviceId[compat] = UCHAR2USHORT(tmp[2], tmp[3]); + compat++; + Size = 0; + } + break; + + case ISAPNP_SRIN_IRQ_FORMAT: + if ((Size < 2) || (Size > 3)) + goto skip; + AddIrqResource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + case ISAPNP_SRIN_DMA_FORMAT: + if (Size != 2) + goto skip; + AddDmaResource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + case ISAPNP_SRIN_START_DFUNCTION: + if (Size > 1) + goto skip; + + if (Size > 0) { + Peek(tmp, Size); + Priority = tmp[0]; + Size = 0; + /* FIXME: Maybe use IO_RESOURCE_PREFERRED for some */ + Option = IO_RESOURCE_ALTERNATIVE; + } else { + Priority = 0; + Option = IO_RESOURCE_ALTERNATIVE; + } + + DPRINT(" Start priority %d \n", Priority); + + LogicalDevice->CurrentDescriptorCount = 0; + + break; + + case ISAPNP_SRIN_END_DFUNCTION: + + DPRINT(" End priority %d \n", Priority); + + if (Size != 0) + goto skip; + Priority = 0; + Option = IO_RESOURCE_REQUIRED; + LogicalDevice->CurrentDescriptorCount = 0; + break; + + case ISAPNP_SRIN_IO_DESCRIPTOR: + if (Size != 7) + goto skip; + AddIOPortResource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + case ISAPNP_SRIN_FL_IO_DESCRIPOTOR: + if (Size != 3) + goto skip; + AddFixedIOPortResource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + case ISAPNP_SRIN_VENDOR_DEFINED: + break; + + case ISAPNP_SRIN_END_TAG: + if (Size > 0) + Skip(Size); + return FALSE; + + default: + DPRINT("Ignoring small tag of type 0x%X for logical device %d on card %d\n", + type, LogicalDevice->Number, Card->CardId); + } + } else { + switch (type) { + case ISAPNP_LRIN_MEMORY_RANGE: + if (Size != 9) + goto skip; + AddMemoryResource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + case ISAPNP_LRIN_ID_STRING_ANSI: + ParseAnsiName(&LogicalDevice->Name, &Size); + break; + + case ISAPNP_LRIN_ID_STRING_UNICODE: + break; + + case ISAPNP_LRIN_VENDOR_DEFINED: + break; + + case ISAPNP_LRIN_MEMORY_RANGE32: + if (Size != 17) + goto skip; + AddMemory32Resource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + case ISAPNP_LRIN_FL_MEMORY_RANGE32: + if (Size != 17) + goto skip; + AddFixedMemory32Resource(LogicalDevice, Size, Priority, Option); + Size = 0; + break; + + default: + DPRINT("Ignoring large tag of type 0x%X for logical device %d on card %d\n", + type, LogicalDevice->Number, Card->CardId); + } + } +skip: + if (Size > 0) + Skip(Size); + } + + return TRUE; +} + + +/* + * Parse resource map for ISA PnP card + */ +static BOOLEAN ParseResourceMap(PISAPNP_DEVICE_EXTENSION DeviceExtension, + PISAPNP_CARD Card) +{ + UCHAR type, tmp[17]; + USHORT size; + BOOLEAN Small; + + DPRINT("Card %d\n", Card->CardId); + + while (TRUE) { + if (!ReadTag(&type, &size, &Small)) + return FALSE; + + if (Small) { + switch (type) { + case ISAPNP_SRIN_VERSION: + if (size != 2) + goto skip; + Peek(tmp, 2); + Card->PNPVersion = tmp[0]; + Card->ProductVersion = tmp[1]; + size = 0; + break; + + case ISAPNP_SRIN_LDEVICE_ID: + if ((size >= 5) && (size <= 6)) { + if (!CreateLogicalDevice(DeviceExtension, Card, size)) + return FALSE; + size = 0; + } + break; + + case ISAPNP_SRIN_CDEVICE_ID: + /* FIXME: Parse compatible IDs */ + break; + + case ISAPNP_SRIN_END_TAG: + if (size > 0) + Skip(size); + return TRUE; + + default: + DPRINT("Ignoring small tag Type 0x%X for Card %d\n", type, Card->CardId); + } + } else { + switch (type) { + case ISAPNP_LRIN_ID_STRING_ANSI: + ParseAnsiName(&Card->Name, &size); + break; + + default: + DPRINT("Ignoring large tag Type 0x%X for Card %d\n", + type, Card->CardId); + } + } +skip: + if (size > 0) + Skip(size); + } + + return TRUE; +} + + +/* + * Compute ISA PnP checksum for first eight bytes + */ +static UCHAR Checksum(PUCHAR data) +{ + ULONG i, j; + UCHAR checksum = 0x6a, bit, b; + + for (i = 0; i < 8; i++) { + b = data[i]; + for (j = 0; j < 8; j++) { + bit = 0; + if (b & (1 << j)) + bit = 1; + checksum = ((((checksum ^ (checksum >> 1)) & + 0x01) ^ bit) << 7) | (checksum >> 1); + } + } + return checksum; +} + + +/* + * Build a resource list for a logical ISA PnP device + */ +static NTSTATUS BuildResourceList(PISAPNP_LOGICAL_DEVICE LogicalDevice, + PIO_RESOURCE_LIST DestinationList, + ULONG Priority) +{ + PLIST_ENTRY CurrentEntry, Entry; + PISAPNP_CONFIGURATION_LIST List; + PISAPNP_DESCRIPTOR Descriptor; + NTSTATUS Status; + ULONG i; + + if (IsListEmpty(&LogicalDevice->Configuration)) + return STATUS_NOT_FOUND; + + CurrentEntry = LogicalDevice->Configuration.Flink; + while (CurrentEntry != &LogicalDevice->Configuration) { + List = CONTAINING_RECORD( + CurrentEntry, ISAPNP_CONFIGURATION_LIST, ListEntry); + + if (List->Priority == Priority) { + + DPRINT("Logical device %d DestinationList 0x%X\n", + LogicalDevice->Number, + DestinationList); + + DestinationList->Version = 1; + DestinationList->Revision = 1; + DestinationList->Count = LogicalDevice->DescriptorCount; + + i = 0; + Entry = List->ListHead.Flink; + while (Entry != &List->ListHead) { + Descriptor = CONTAINING_RECORD( + Entry, ISAPNP_DESCRIPTOR, ListEntry); + + DPRINT("Logical device %d Destination 0x%X(%d)\n", + LogicalDevice->Number, + &DestinationList->Descriptors[i], + i); + + RtlCopyMemory(&DestinationList->Descriptors[i], + &Descriptor->Descriptor, + sizeof(IO_RESOURCE_DESCRIPTOR)); + + i++; + + Entry = Entry->Flink; + } + + RemoveEntryList(&List->ListEntry); + + ExFreePool(List); + + return STATUS_SUCCESS; + } + + CurrentEntry = CurrentEntry->Flink; + } + + return STATUS_UNSUCCESSFUL; +} + + +/* + * Build resource lists for a logical ISA PnP device + */ +static NTSTATUS BuildResourceLists(PISAPNP_LOGICAL_DEVICE LogicalDevice) +{ + ULONG ListSize; + ULONG Priority; + ULONG SingleListSize; + PIO_RESOURCE_LIST p; + NTSTATUS Status; + + ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + - sizeof(IO_RESOURCE_LIST) + + LogicalDevice->ConfigurationSize; + + DPRINT("Logical device %d ListSize 0x%X ConfigurationSize 0x%X DescriptorCount %d\n", + LogicalDevice->Number, ListSize, + LogicalDevice->ConfigurationSize, + LogicalDevice->DescriptorCount); + + LogicalDevice->ResourceLists = + (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool( + PagedPool, ListSize); + if (!LogicalDevice->ResourceLists) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(LogicalDevice->ResourceLists, ListSize); + + SingleListSize = sizeof(IO_RESOURCE_LIST) + + (LogicalDevice->DescriptorCount - 1) * + sizeof(IO_RESOURCE_DESCRIPTOR); + + DPRINT("SingleListSize %d\n", SingleListSize); + + Priority = 0; + p = &LogicalDevice->ResourceLists->List[0]; + do { + Status = BuildResourceList(LogicalDevice, p, Priority); + if (NT_SUCCESS(Status)) { + p = (PIO_RESOURCE_LIST)((ULONG)p + SingleListSize); + Priority++; + } + } while (Status != STATUS_NOT_FOUND); + + LogicalDevice->ResourceLists->ListSize = ListSize; + LogicalDevice->ResourceLists->AlternativeLists = Priority + 1; + + return STATUS_SUCCESS; +} + + +/* + * Build resource lists for a ISA PnP card + */ +static NTSTATUS BuildResourceListsForCard(PISAPNP_CARD Card) +{ + PISAPNP_LOGICAL_DEVICE LogicalDevice; + PLIST_ENTRY CurrentEntry; + NTSTATUS Status; + + CurrentEntry = Card->LogicalDevices.Flink; + while (CurrentEntry != &Card->LogicalDevices) { + LogicalDevice = CONTAINING_RECORD( + CurrentEntry, ISAPNP_LOGICAL_DEVICE, CardListEntry); + Status = BuildResourceLists(LogicalDevice); + if (!NT_SUCCESS(Status)) + return Status; + CurrentEntry = CurrentEntry->Flink; + } + + return STATUS_SUCCESS; +} + + +/* + * Build resource lists for all present ISA PnP cards + */ +static NTSTATUS BuildResourceListsForAll( + PISAPNP_DEVICE_EXTENSION DeviceExtension) +{ + PLIST_ENTRY CurrentEntry; + PISAPNP_CARD Card; + NTSTATUS Status; + + CurrentEntry = DeviceExtension->CardListHead.Flink; + while (CurrentEntry != &DeviceExtension->CardListHead) { + Card = CONTAINING_RECORD( + CurrentEntry, ISAPNP_CARD, ListEntry); + Status = BuildResourceListsForCard(Card); + if (!NT_SUCCESS(Status)) + return Status; + CurrentEntry = CurrentEntry->Flink; + } + + return STATUS_SUCCESS; +} + + +/* + * Build device list for all present ISA PnP cards + */ +static NTSTATUS BuildDeviceList(PISAPNP_DEVICE_EXTENSION DeviceExtension) +{ + ULONG csn; + UCHAR header[9], checksum; + PISAPNP_CARD Card; + NTSTATUS Status; + + DPRINT("Called\n"); + + SendWait(); + SendKey(); + for (csn = 1; csn <= 10; csn++) { + SendWake(csn); + Peek(header, 9); + checksum = Checksum(header); + + if (checksum == 0x00 || checksum != header[8]) /* Invalid CSN */ + continue; + + DPRINT("VENDOR: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + header[0], header[1], header[2], header[3], + header[4], header[5], header[6], header[7], header[8]); + + Card = (PISAPNP_CARD)ExAllocatePool( + PagedPool, sizeof(ISAPNP_CARD)); + if (!Card) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(Card, sizeof(ISAPNP_CARD)); + + Card->CardId = csn; + Card->VendorId = (header[1] << 8) | header[0]; + Card->DeviceId = (header[3] << 8) | header[2]; + Card->Serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4]; + + InitializeListHead(&Card->LogicalDevices); + KeInitializeSpinLock(&Card->LogicalDevicesLock); + + ParseResourceMap(DeviceExtension, Card); + + ExInterlockedInsertTailList(&DeviceExtension->CardListHead, + &Card->ListEntry, + &DeviceExtension->GlobalListLock); + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +ISAPNPQueryBusRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PISAPNP_DEVICE_EXTENSION DeviceExtension; + PISAPNP_LOGICAL_DEVICE LogicalDevice; + PDEVICE_RELATIONS Relations; + PLIST_ENTRY CurrentEntry; + NTSTATUS Status; + ULONG Size; + ULONG i; + + DPRINT("Called\n"); + + DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (Irp->IoStatus.Information) { + /* FIXME: Another bus driver has already created a DEVICE_RELATIONS + structure so we must merge this structure with our own */ + } + + Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) * + (DeviceExtension->DeviceListCount - 1); + Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); + if (!Relations) + return STATUS_INSUFFICIENT_RESOURCES; + + Relations->Count = DeviceExtension->DeviceListCount; + + i = 0; + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) { + LogicalDevice = CONTAINING_RECORD( + CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceListEntry); + + if (!LogicalDevice->Pdo) { + /* Create a physical device object for the + device as it does not already have one */ + Status = IoCreateDevice(DeviceObject->DriverObject, 0, + NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &LogicalDevice->Pdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + ExFreePool(Relations); + return Status; + } + + LogicalDevice->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + } + + /* Reference the physical device object. The PnP manager + will dereference it again when it is no longer needed */ + ObReferenceObject(LogicalDevice->Pdo); + + Relations->Objects[i] = LogicalDevice->Pdo; + + i++; + + CurrentEntry = CurrentEntry->Flink; + } + + Irp->IoStatus.Information = (ULONG)Relations; + + return Status; +} + + +NTSTATUS +ISAPNPQueryDeviceRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PISAPNP_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->State == dsStopped) + return STATUS_UNSUCCESSFUL; + + switch (IrpSp->Parameters.QueryDeviceRelations.Type) { + case BusRelations: + Status = ISAPNPQueryBusRelations(DeviceObject, Irp, IrpSp); + break; + + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; +} + + +NTSTATUS +ISAPNPStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PISAPNP_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + ULONG NumCards; + + DPRINT("Called\n"); + + DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->State == dsStarted) + return STATUS_SUCCESS; + + NumCards = IsolatePnPCards(); + + DPRINT("Number of ISA PnP cards found: %d\n", NumCards); + + Status = BuildDeviceList(DeviceExtension); + if (!NT_SUCCESS(Status)) { + DPRINT("BuildDeviceList() failed with status 0x%X\n", Status); + return Status; + } + + Status = BuildResourceListsForAll(DeviceExtension); + if (!NT_SUCCESS(Status)) { + DPRINT("BuildResourceListsForAll() failed with status 0x%X\n", Status); + return Status; + } + + DeviceExtension->State = dsStarted; + + return STATUS_SUCCESS; +} + + +NTSTATUS +ISAPNPStopDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PISAPNP_DEVICE_EXTENSION DeviceExtension; + + DPRINT("Called\n"); + + DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->State != dsStopped) { + /* FIXME: Stop device */ + DeviceExtension->State = dsStopped; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +ISAPNPDispatchOpenClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("Called\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +ISAPNPDispatchReadWrite( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PIRP Irp) +{ + DPRINT("Called\n"); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_UNSUCCESSFUL; +} + + +NTSTATUS +STDCALL +ISAPNPDispatchDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Irp->IoStatus.Information = 0; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +ISAPNPControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + switch (IrpSp->MinorFunction) { + case IRP_MN_QUERY_DEVICE_RELATIONS: + Status = ISAPNPQueryDeviceRelations(DeviceObject, Irp, IrpSp); + break; + + case IRP_MN_START_DEVICE: + Status = ISAPNPStartDevice(DeviceObject, Irp, IrpSp); + break; + + case IRP_MN_STOP_DEVICE: + Status = ISAPNPStopDevice(DeviceObject, Irp, IrpSp); + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +ISAPNPAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + PISAPNP_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT Fdo; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = IoCreateDevice(DriverObject, sizeof(ISAPNP_DEVICE_EXTENSION), + NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + return Status; + } + + DeviceExtension = (PISAPNP_DEVICE_EXTENSION)Fdo->DeviceExtension; + + DeviceExtension->Pdo = PhysicalDeviceObject; + + DeviceExtension->Ldo = + IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject); + + InitializeListHead(&DeviceExtension->CardListHead); + InitializeListHead(&DeviceExtension->DeviceListHead); + DeviceExtension->DeviceListCount = 0; + KeInitializeSpinLock(&DeviceExtension->GlobalListLock); + + DeviceExtension->State = dsStopped; + + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + DPRINT("Done AddDevice\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DbgPrint("ISA Plug and Play Bus Driver\n"); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = ISAPNPDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = ISAPNPDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_READ] = ISAPNPDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = ISAPNPDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ISAPNPDispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_PNP] = ISAPNPControl; + DriverObject->DriverExtension->AddDevice = ISAPNPAddDevice; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h new file mode 100644 index 0000000..2844fd1 --- /dev/null +++ b/drivers/bus/isapnp/isapnp.h @@ -0,0 +1,329 @@ +#ifndef __ISAPNP_H +#define __ISAPNP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ISAPNP_ADDRESS_PORT 0x0279 // ADDRESS (W) +#define ISAPNP_WRITE_PORT 0x0A79 // WRITE_DATA (W) +#define ISAPNP_MIN_READ_PORT 0x0203 // READ_DATA (R) +#define ISAPNP_MAX_READ_PORT 0x03FF // READ_DATA (R) + +// Card control registers +#define ISAPNP_CARD_READ_DATA_PORT 0x00 // Set READ_DATA port +#define ISAPNP_CARD_ISOLATION 0x01 // Isolation +#define ISAPNP_CARD_CONFIG_COTROL 0x02 // Configuration control +#define ISAPNP_CARD_WAKECSN 0x03 // Wake[CSN] +#define ISAPNP_CARD_RESOUCE_DATA 0x04 // Resource data port +#define ISAPNP_CARD_STATUS 0x05 // Status port +#define ISAPNP_CARD_CSN 0x06 // Card Select Number port +#define ISAPNP_CARD_LOG_DEVICE_NUM 0x07 // Logical Device Number +#define ISAPNP_CARD_RESERVED 0x08 // Card level reserved +#define ISAPNP_CARD_VENDOR_DEFINED 0x20 // Vendor defined + +// Logical device control registers +#define ISAPNP_CONTROL_ACTIVATE 0x30 // Activate logical device +#define ISAPNP_CONTROL_IO_RANGE_CHECK 0x31 // I/O range conflict check +#define ISAPNP_CONTROL_LDC_RESERVED 0x32 // Logical Device Control reserved +#define ISAPNP_CONTROL_LDCV_RESERVED 0x38 // Logical Device Control Vendor reserved + +// Logical device configuration registers +#define ISAPNP_CONFIG_MEMORY_BASE2 0x00 // Memory base address bits 23-16 +#define ISAPNP_CONFIG_MEMORY_BASE1 0x01 // Memory base address bits 15-8 +#define ISAPNP_CONFIG_MEMORY_CONTROL 0x02 // Memory control +#define ISAPNP_CONFIG_MEMORY_LIMIT2 0x03 // Memory limit bits 23-16 +#define ISAPNP_CONFIG_MEMORY_LIMIT1 0x04 // Memory limit bits 15-8 + +#define ISAPNP_CONFIG_MEMORY_DESC0 0x40 // Memory descriptor 0 +#define ISAPNP_CONFIG_MEMORY_DESC1 0x48 // Memory descriptor 1 +#define ISAPNP_CONFIG_MEMORY_DESC2 0x50 // Memory descriptor 2 +#define ISAPNP_CONFIG_MEMORY_DESC3 0x58 // Memory descriptor 3 + +#define ISAPNP_CONFIG_MEMORY32_BASE3 0x00 // 32-bit memory base address bits 31-24 +#define ISAPNP_CONFIG_MEMORY32_BASE2 0x01 // 32-bit memory base address bits 23-16 +#define ISAPNP_CONFIG_MEMORY32_BASE1 0x01 // 32-bit memory base address bits 15-8 +#define ISAPNP_CONFIG_MEMORY32_CONTROL 0x02 // 32-bit memory control +#define ISAPNP_CONFIG_MEMORY32_LIMIT3 0x03 // 32-bit memory limit bits 31-24 +#define ISAPNP_CONFIG_MEMORY32_LIMIT2 0x04 // 32-bit memory limit bits 23-16 +#define ISAPNP_CONFIG_MEMORY32_LIMIT1 0x05 // 32-bit memory limit bits 15-8 + +#define ISAPNP_CONFIG_MEMORY32_DESC0 0x76 // 32-bit memory descriptor 0 +#define ISAPNP_CONFIG_MEMORY32_DESC1 0x80 // 32-bit memory descriptor 1 +#define ISAPNP_CONFIG_MEMORY32_DESC2 0x90 // 32-bit memory descriptor 2 +#define ISAPNP_CONFIG_MEMORY32_DESC3 0xA0 // 32-bit memory descriptor 3 + +#define ISAPNP_CONFIG_IO_BASE1 0x00 // I/O port base address bits 15-8 +#define ISAPNP_CONFIG_IO_BASE0 0x01 // I/O port base address bits 7-0 + +#define ISAPNP_CONFIG_IO_DESC0 0x60 // I/O port descriptor 0 +#define ISAPNP_CONFIG_IO_DESC1 0x62 // I/O port descriptor 1 +#define ISAPNP_CONFIG_IO_DESC2 0x64 // I/O port descriptor 2 +#define ISAPNP_CONFIG_IO_DESC3 0x66 // I/O port descriptor 3 +#define ISAPNP_CONFIG_IO_DESC4 0x68 // I/O port descriptor 4 +#define ISAPNP_CONFIG_IO_DESC5 0x6A // I/O port descriptor 5 +#define ISAPNP_CONFIG_IO_DESC6 0x6C // I/O port descriptor 6 +#define ISAPNP_CONFIG_IO_DESC7 0x6E // I/O port descriptor 7 + +#define ISAPNP_CONFIG_IRQ_LEVEL0 0x70 // Interupt level for descriptor 0 +#define ISAPNP_CONFIG_IRQ_TYPE0 0x71 // Type level for descriptor 0 +#define ISAPNP_CONFIG_IRQ_LEVEL1 0x72 // Interupt level for descriptor 1 +#define ISAPNP_CONFIG_IRQ_TYPE1 0x73 // Type level for descriptor 1 + +#define ISAPNP_CONFIG_DMA_CHANNEL0 0x74 // DMA channel for descriptor 0 +#define ISAPNP_CONFIG_DMA_CHANNEL1 0x75 // DMA channel for descriptor 1 + + +typedef struct _PNPISA_SERIAL_ID +{ + UCHAR VendorId[4]; // Vendor Identifier + UCHAR SerialId[4]; // Serial number + UCHAR Checksum; // Checksum +} PNPISA_SERIAL_ID, *PPNPISA_SERIAL_ID; + + +#define ISAPNP_RES_PRIORITY_PREFERRED 0 +#define ISAPNP_RES_PRIORITY_ACCEPTABLE 1 +#define ISAPNP_RES_PRIORITY_FUNCTIONAL 2 +#define ISAPNP_RES_PRIORITY_INVALID 65535 + + +#define ISAPNP_RESOURCE_ITEM_TYPE 0x80 // 0 = small, 1 = large + +// Small Resource Item Names (SRINs) +#define ISAPNP_SRIN_VERSION 0x1 // PnP version number +#define ISAPNP_SRIN_LDEVICE_ID 0x2 // Logical device id +#define ISAPNP_SRIN_CDEVICE_ID 0x3 // Compatible device id +#define ISAPNP_SRIN_IRQ_FORMAT 0x4 // IRQ format +#define ISAPNP_SRIN_DMA_FORMAT 0x5 // DMA format +#define ISAPNP_SRIN_START_DFUNCTION 0x6 // Start dependant function +#define ISAPNP_SRIN_END_DFUNCTION 0x7 // End dependant function +#define ISAPNP_SRIN_IO_DESCRIPTOR 0x8 // I/O port descriptor +#define ISAPNP_SRIN_FL_IO_DESCRIPOTOR 0x9 // Fixed location I/O port descriptor +#define ISAPNP_SRIN_VENDOR_DEFINED 0xE // Vendor defined +#define ISAPNP_SRIN_END_TAG 0xF // End tag + +typedef struct _ISAPNP_SRI_VERSION +{ + UCHAR Header; + UCHAR Version; // Packed BCD format version number + UCHAR VendorVersion; // Vendor specific version number +} ISAPNP_SRI_VERSION, *PISAPNP_SRI_VERSION; + +typedef struct _ISAPNP_SRI_LDEVICE_ID +{ + UCHAR Header; + USHORT DeviceId; // Logical device id + USHORT VendorId; // Manufacturer id + UCHAR Flags; // Flags +} ISAPNP_SRI_LDEVICE_ID, *PISAPNP_SRI_LDEVICE_ID; + +typedef struct _ISAPNP_SRI_CDEVICE_ID +{ + UCHAR Header; + USHORT DeviceId; // Logical device id + USHORT VendorId; // Manufacturer id +} ISAPNP_SRI_CDEVICE_ID, *PISAPNP_SRI_CDEVICE_ID; + +typedef struct _ISAPNP_SRI_IRQ_FORMAT +{ + UCHAR Header; + USHORT Mask; // IRQ mask (bit 0 = irq 0, etc.) + UCHAR Information; // IRQ information +} ISAPNP_SRI_IRQ_FORMAT, *PISAPNP_SRI_IRQ_FORMAT; + +typedef struct _ISAPNP_SRI_DMA_FORMAT +{ + UCHAR Header; + USHORT Mask; // DMA channel mask (bit 0 = channel 0, etc.) + UCHAR Information; // DMA information +} ISAPNP_SRI_DMA_FORMAT, *PISAPNP_SRI_DMA_FORMAT; + +typedef struct _ISAPNP_SRI_START_DFUNCTION +{ + UCHAR Header; +} ISAPNP_SRI_START_DFUNCTION, *PISAPNP_SRI_START_DFUNCTION; + +typedef struct _ISAPNP_SRI_END_DFUNCTION +{ + UCHAR Header; +} ISAPNP_SRI_END_DFUNCTION, *PISAPNP_SRI_END_DFUNCTION; + +typedef struct _ISAPNP_SRI_IO_DESCRIPTOR +{ + UCHAR Header; + UCHAR Information; // Information + USHORT RangeMinBase; // Minimum base address + USHORT RangeMaxBase; // Maximum base address + UCHAR Alignment; // Base alignment + UCHAR RangeLength; // Length of range +} ISAPNP_SRI_IO_DESCRIPTOR, *PISAPNP_SRI_IO_DESCRIPTOR; + +typedef struct _ISAPNP_SRI_FL_IO_DESCRIPTOR +{ + UCHAR Header; + USHORT RangeBase; // Range base address + UCHAR RangeLength; // Length of range +} ISAPNP_SRI_FL_IO_DESCRIPTOR, *PISAPNP_SRI_FL_IO_DESCRIPTOR; + +typedef struct _PISAPNP_SRI_VENDOR_DEFINED +{ + UCHAR Header; + UCHAR Reserved[0]; // Vendor defined +} ISAPNP_SRI_VENDOR_DEFINED, *PISAPNP_SRI_VENDOR_DEFINED; + +typedef struct _ISAPNP_SRI_END_TAG +{ + UCHAR Header; + UCHAR Checksum; // Checksum +} ISAPNP_SRI_END_TAG, *PISAPNP_SRI_END_TAG; + + +typedef struct _ISAPNP_LRI +{ + UCHAR Header; + USHORT Length; // Length of data items +} ISAPNP_LRI, *PISAPNP_LRI; + +// Large Resource Item Names (LRINs) +#define ISAPNP_LRIN_MEMORY_RANGE 0x1 // Memory range descriptor +#define ISAPNP_LRIN_ID_STRING_ANSI 0x2 // Identifier string (ANSI) +#define ISAPNP_LRIN_ID_STRING_UNICODE 0x3 // Identifier string (UNICODE) +#define ISAPNP_LRIN_VENDOR_DEFINED 0x4 // Vendor defined +#define ISAPNP_LRIN_MEMORY_RANGE32 0x5 // 32-bit memory range descriptor +#define ISAPNP_LRIN_FL_MEMORY_RANGE32 0x6 // 32-bit fixed location memory range descriptor + +typedef struct _ISAPNP_LRI_MEMORY_RANGE +{ + UCHAR Header; + USHORT Length; // Length of data items + UCHAR Information; // Information + USHORT RangeMinBase; // Minimum base address + USHORT RangeMaxBase; // Maximum base address + USHORT Alignment; // Base alignment + USHORT RangeLength; // Length of range +} ISAPNP_LRI_MEMORY_RANGE, *PISAPNP_LRI_MEMORY_RANGE; + +typedef struct _ISAPNP_LRI_ID_STRING_ANSI +{ + UCHAR Header; + USHORT Length; // Length of data items + UCHAR String[0]; // Identifier string +} ISAPNP_LRI_ID_STRING_ANSI, *PISAPNP_LRI_ID_STRING_ANSI; + +typedef struct _ISAPNP_LRI_ID_STRING_UNICODE +{ + UCHAR Header; + USHORT Length; // Length of data items + USHORT CountryId; // Country identifier + USHORT String[0]; // Identifier string +} ISAPNP_LRI_ID_STRING_UNICODE, *PISAPNP_LRI_ID_STRING_UNICODE; + +typedef struct _PISAPNP_LRI_VENDOR_DEFINED +{ + UCHAR Header; + USHORT Length; // Length of data items + UCHAR Reserved[0]; // Vendor defined +} ISAPNP_LRI_VENDOR_DEFINED, *PISAPNP_LRI_VENDOR_DEFINED; + +typedef struct _ISAPNP_LRI_MEMORY_RANGE32 +{ + UCHAR Header; + USHORT Length; // Length of data items + UCHAR Information; // Information + ULONG RangeMinBase; // Minimum base address + ULONG RangeMaxBase; // Maximum base address + ULONG Alignment; // Base alignment + ULONG RangeLength; // Length of range +} ISAPNP_LRI_MEMORY_RANGE32, *PISAPNP_LRI_MEMORY_RANGE32; + +typedef struct _ISAPNP_LRI_FL_MEMORY_RANGE32 +{ + UCHAR Header; + USHORT Length; // Length of data items + UCHAR Information; // Information + ULONG RangeMinBase; // Minimum base address + ULONG RangeMaxBase; // Maximum base address + ULONG RangeLength; // Length of range +} ISAPNP_LRI_FL_MEMORY_RANGE32, *PISAPNP_LRI_FL_MEMORY_RANGE32; + +typedef struct _ISAPNP_CARD +{ + LIST_ENTRY ListEntry; + USHORT CardId; + USHORT VendorId; + USHORT DeviceId; + ULONG Serial; + UCHAR PNPVersion; + UCHAR ProductVersion; + UNICODE_STRING Name; + LIST_ENTRY LogicalDevices; + KSPIN_LOCK LogicalDevicesLock; +} ISAPNP_CARD, *PISAPNP_CARD; + + +typedef struct _ISAPNP_DESCRIPTOR +{ + LIST_ENTRY ListEntry; + IO_RESOURCE_DESCRIPTOR Descriptor; +} ISAPNP_DESCRIPTOR, *PISAPNP_DESCRIPTOR; + +typedef struct _ISAPNP_CONFIGURATION_LIST +{ + LIST_ENTRY ListEntry; + ULONG Priority; + LIST_ENTRY ListHead; +} ISAPNP_CONFIGURATION_LIST, *PISAPNP_CONFIGURATION_LIST; + + +#define MAX_COMPATIBLE_ID 32 + +typedef struct _ISAPNP_LOGICAL_DEVICE +{ + LIST_ENTRY CardListEntry; + LIST_ENTRY DeviceListEntry; + USHORT Number; + USHORT VendorId; + USHORT DeviceId; + USHORT CVendorId[MAX_COMPATIBLE_ID]; + USHORT CDeviceId[MAX_COMPATIBLE_ID]; + USHORT Regs; + PISAPNP_CARD Card; + UNICODE_STRING Name; + PDEVICE_OBJECT Pdo; + PIO_RESOURCE_REQUIREMENTS_LIST ResourceLists; + LIST_ENTRY Configuration; + ULONG ConfigurationSize; + ULONG DescriptorCount; + ULONG CurrentDescriptorCount; +} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; + + +typedef enum { + dsStopped, + dsStarted +} ISAPNP_DEVICE_STATE; + +typedef struct _ISAPNP_DEVICE_EXTENSION +{ + // Physical Device Object + PDEVICE_OBJECT Pdo; + // Lower device object + PDEVICE_OBJECT Ldo; + // List of ISA PnP cards managed by this driver + LIST_ENTRY CardListHead; + // List of devices managed by this driver + LIST_ENTRY DeviceListHead; + // Number of devices managed by this driver + ULONG DeviceListCount; + // Spinlock for the linked lists + KSPIN_LOCK GlobalListLock; + // Current state of the driver + ISAPNP_DEVICE_STATE State; +} ISAPNP_DEVICE_EXTENSION, *PISAPNP_DEVICE_EXTENSION; + +#ifdef __cplusplus +} +#endif + +#endif /* __ISAPNP_H */ diff --git a/drivers/bus/isapnp/isapnp.rc b/drivers/bus/isapnp/isapnp.rc new file mode 100644 index 0000000..205420a --- /dev/null +++ b/drivers/bus/isapnp/isapnp.rc @@ -0,0 +1,38 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ISA Plug And Play Bus Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "isapnp\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "isapnp.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/drivers/bus/isapnp/makefile b/drivers/bus/isapnp/makefile new file mode 100644 index 0000000..de06ba7 --- /dev/null +++ b/drivers/bus/isapnp/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = isapnp + +TARGET_OBJECTS = isapnp.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/bus/pci/.cvsignore b/drivers/bus/pci/.cvsignore new file mode 100644 index 0000000..9ce3594 --- /dev/null +++ b/drivers/bus/pci/.cvsignore @@ -0,0 +1,4 @@ +pci.coff +*.d +*.o +*.sym diff --git a/drivers/bus/pci/fdo.c b/drivers/bus/pci/fdo.c new file mode 100644 index 0000000..b52ac70 --- /dev/null +++ b/drivers/bus/pci/fdo.c @@ -0,0 +1,458 @@ +/* $Id$ + * + * PROJECT: ReactOS PCI bus driver + * FILE: fdo.c + * PURPOSE: PCI device object dispatch routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 10-09-2001 CSH Created + */ +#include + +#define NDEBUG +#include + +/*** PRIVATE *****************************************************************/ + +NTSTATUS +FdoLocateChildDevice( + PPCI_DEVICE *Device, + PFDO_DEVICE_EXTENSION DeviceExtension, + PPCI_COMMON_CONFIG PciConfig) +{ + PLIST_ENTRY CurrentEntry; + PPCI_DEVICE CurrentDevice; + + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) { + CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry); + + /* If both vendor ID and device ID match, it is the same device */ + if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) && + (PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID)) { + *Device = CurrentDevice; + return STATUS_SUCCESS; + } + + CurrentEntry = CurrentEntry->Flink; + } + + *Device = NULL; + return STATUS_UNSUCCESSFUL; +} + + +NTSTATUS +FdoEnumerateDevices( + PDEVICE_OBJECT DeviceObject) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + PCI_COMMON_CONFIG PciConfig; + PLIST_ENTRY CurrentEntry; + PPCI_DEVICE Device; + NTSTATUS Status; + ULONG Slot; + ULONG Size; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* Mark all devices to be removed. If we don't discover them again during + enumeration, assume that they have been surprise removed */ + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) { + Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry); + Device->RemovePending = TRUE; + CurrentEntry = CurrentEntry->Flink; + } + + DeviceExtension->DeviceListCount = 0; + + /* Enumerate devices on the PCI bus */ + for (Slot = 0; Slot < 256; Slot++) + { + Size = PciGetBusData( + DeviceExtension->BusNumber, + Slot, + &PciConfig, + 0, + sizeof(PCI_COMMON_CONFIG)); + if (Size != 0) + { + DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n", + DeviceExtension->BusNumber, + Slot>>3, + Slot & 0x07, + PciConfig.VendorID, + PciConfig.DeviceID); + + Status = FdoLocateChildDevice(&Device, DeviceExtension, &PciConfig); + if (!NT_SUCCESS(Status)) { + Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE)); + if (!Device) + { + /* FIXME: Cleanup resources for already discovered devices */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(Device, sizeof(PCI_DEVICE)); + + RtlMoveMemory(&Device->PciConfig, &PciConfig, sizeof(PCI_COMMON_CONFIG)); + + ExInterlockedInsertTailList( + &DeviceExtension->DeviceListHead, + &Device->ListEntry, + &DeviceExtension->DeviceListLock); + } + + /* Don't remove this device */ + Device->RemovePending = FALSE; + + DeviceExtension->DeviceListCount++; + } + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +FdoQueryBusRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPDO_DEVICE_EXTENSION PdoDeviceExtension; + PFDO_DEVICE_EXTENSION DeviceExtension; + PDEVICE_RELATIONS Relations; + PLIST_ENTRY CurrentEntry; + PPCI_DEVICE Device; + NTSTATUS Status; + BOOLEAN ErrorOccurred; + NTSTATUS ErrorStatus; + WCHAR Buffer[MAX_PATH]; + ULONG Size; + ULONG i; + + DPRINT("Called\n"); + + ErrorStatus = STATUS_INSUFFICIENT_RESOURCES; + + Status = STATUS_SUCCESS; + + ErrorOccurred = FALSE; + + FdoEnumerateDevices(DeviceObject); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (Irp->IoStatus.Information) { + /* FIXME: Another bus driver has already created a DEVICE_RELATIONS + structure so we must merge this structure with our own */ + } + + Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) * + (DeviceExtension->DeviceListCount - 1); + Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); + if (!Relations) + return STATUS_INSUFFICIENT_RESOURCES; + + Relations->Count = DeviceExtension->DeviceListCount; + + i = 0; + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) { + Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry); + + PdoDeviceExtension = NULL; + + if (!Device->Pdo) { + /* Create a physical device object for the + device as it does not already have one */ + Status = IoCreateDevice( + DeviceObject->DriverObject, + sizeof(PDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Device->Pdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + ErrorStatus = Status; + ErrorOccurred = TRUE; + break; + } + + Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + + Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; + + //Device->Pdo->Flags |= DO_POWER_PAGABLE; + + PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; + + RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); + + PdoDeviceExtension->Common.IsFDO = FALSE; + + PdoDeviceExtension->Common.DeviceObject = Device->Pdo; + + PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0; + + /* FIXME: Get device properties (Hardware IDs, etc.) */ + + swprintf( + Buffer, + L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", + Device->PciConfig.VendorID, + Device->PciConfig.DeviceID, + Device->PciConfig.u.type0.SubSystemID, + Device->PciConfig.RevisionID); + + if (!PciCreateUnicodeString( + &PdoDeviceExtension->DeviceID, + Buffer, + PagedPool)) { + ErrorOccurred = TRUE; + break; + } + + DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceID.Buffer); + } + + if (!Device->RemovePending) { + /* Reference the physical device object. The PnP manager + will dereference it again when it is no longer needed */ + ObReferenceObject(Device->Pdo); + + Relations->Objects[i] = Device->Pdo; + + i++; + } + + CurrentEntry = CurrentEntry->Flink; + } + + if (ErrorOccurred) { + /* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */ + /* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */ + if (PdoDeviceExtension) { + RtlFreeUnicodeString(&PdoDeviceExtension->DeviceID); + ExFreePool(PdoDeviceExtension); + } + + ExFreePool(Relations); + return ErrorStatus; + } + + Irp->IoStatus.Information = (ULONG_PTR)Relations; + + return Status; +} + + +NTSTATUS +FdoStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + assert(DeviceExtension->State == dsStopped); + + InitializeListHead(&DeviceExtension->DeviceListHead); + KeInitializeSpinLock(&DeviceExtension->DeviceListLock); + DeviceExtension->DeviceListCount = 0; + + PciBusConfigType = PciGetBusConfigType(); + + DPRINT("Bus configuration is %d\n", PciBusConfigType); + + if (PciBusConfigType != pbtUnknown) { + /* At least one PCI bus is found */ + } + + /* FIXME: Find a way to get this information */ + DeviceExtension->BusNumber = 0; + + DeviceExtension->State = dsStarted; + + //Irp->IoStatus.Information = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +FdoSetPower( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (IrpSp->Parameters.Power.Type == DevicePowerState) { + /* FIXME: Set device power state for the device */ + Status = STATUS_UNSUCCESSFUL; + } else { + Status = STATUS_UNSUCCESSFUL; + } + + return Status; +} + + +/*** PUBLIC ******************************************************************/ + +NTSTATUS +FdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the PCI device object + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the PCI driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + switch (IrpSp->MinorFunction) { +#if 0 + case IRP_MN_CANCEL_REMOVE_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: + Status = STATUS_NOT_IMPLEMENTED; + break; +#endif + case IRP_MN_QUERY_DEVICE_RELATIONS: + Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp); + break; +#if 0 + case IRP_MN_QUERY_PNP_DEVICE_STATE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_QUERY_STOP_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case IRP_MN_REMOVE_DEVICE: + Status = STATUS_NOT_IMPLEMENTED; + break; +#endif + case IRP_MN_START_DEVICE: + DPRINT("IRP_MN_START_DEVICE received\n"); + Status = FdoStartDevice(DeviceObject, Irp); + break; + case IRP_MN_STOP_DEVICE: + /* Currently not supported */ + Status = STATUS_UNSUCCESSFUL; + break; +#if 0 + case IRP_MN_SURPRISE_REMOVAL: + Status = STATUS_NOT_IMPLEMENTED; + break; +#endif + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + + /* + * Do NOT complete the IRP as it will be processed by the lower + * device object, which will complete the IRP + */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->Ldo, Irp); + return Status; + break; + } + + + if (Status != STATUS_PENDING) { + if (Status != STATUS_NOT_IMPLEMENTED) + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +FdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the PCI device object + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the PCI driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + case IRP_MN_SET_POWER: + Status = FdoSetPower(DeviceObject, Irp, IrpSp); + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +/* EOF */ diff --git a/drivers/bus/pci/makefile b/drivers/bus/pci/makefile new file mode 100644 index 0000000..af38cc1 --- /dev/null +++ b/drivers/bus/pci/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = pci + +TARGET_OBJECTS = fdo.o pci.o pdo.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/bus/pci/pci.c b/drivers/bus/pci/pci.c new file mode 100644 index 0000000..88f01c0 --- /dev/null +++ b/drivers/bus/pci/pci.c @@ -0,0 +1,613 @@ +/* $Id$ + * + * PROJECT: ReactOS PCI Bus driver + * FILE: pci.c + * PURPOSE: Driver entry + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 10-09-2001 CSH Created + */ +#include + +#define NDEBUG +#include + + +#ifdef ALLOC_PRAGMA + +// Make the initialization routines discardable, so that they +// don't waste space + +#pragma alloc_text(init, DriverEntry) + +#endif /* ALLOC_PRAGMA */ + +/*** PUBLIC ******************************************************************/ + +PCI_BUS_TYPE PciBusConfigType = pbtUnknown; + + +/*** PRIVATE *****************************************************************/ + +static NTSTATUS +PciReadConfigUchar(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PUCHAR Value) +{ + switch (PciBusConfigType) + { + case pbtType1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3)); + return STATUS_SUCCESS; + + case pbtType2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +PciReadConfigUshort(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PUSHORT Value) +{ + if ((Offset & 1) != 0) + { + return STATUS_INVALID_PARAMETER; + } + + switch (PciBusConfigType) + { + case pbtType1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1)); + return STATUS_SUCCESS; + + case pbtType2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +PciReadConfigUlong(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PULONG Value) +{ + if ((Offset & 3) != 0) + { + return STATUS_INVALID_PARAMETER; + } + + switch (PciBusConfigType) + { + case pbtType1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_ULONG((PULONG)0xCFC); + return STATUS_SUCCESS; + + case pbtType2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +PciWriteConfigUchar(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + UCHAR Value) +{ + switch (PciBusConfigType) + { + case pbtType1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value); + return STATUS_SUCCESS; + + case pbtType2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +PciWriteConfigUshort(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + USHORT Value) +{ + if ((Offset & 1) != 0) + { + return STATUS_INVALID_PARAMETER; + } + + switch (PciBusConfigType) + { + case pbtType1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value); + return STATUS_SUCCESS; + + case pbtType2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +PciWriteConfigUlong(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + ULONG Value) +{ + if ((Offset & 3) != 0) + { + return STATUS_INVALID_PARAMETER; + } + + switch (PciBusConfigType) + { + case pbtType1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_ULONG((PULONG)0xCFC, Value); + return STATUS_SUCCESS; + + case pbtType2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +ULONG +PciGetBusData(ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PVOID Ptr = Buffer; + ULONG Address = Offset; + ULONG Len = Length; + ULONG Vendor; + UCHAR HeaderType; + +#if 0 + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); +#endif + + if ((Length == 0) || (PciBusConfigType == 0)) + return 0; + + /* 0E=PCI_HEADER_TYPE */ + PciReadConfigUchar(BusNumber, + SlotNumber & 0xF8, + 0x0E, + &HeaderType); + if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0)) + return 0; + + PciReadConfigUlong(BusNumber, + SlotNumber, + 0x00, + &Vendor); + /* some broken boards return 0 if a slot is empty: */ + if (Vendor == 0xFFFFFFFF || Vendor == 0) + return 0; + + if ((Address & 1) && (Len >= 1)) + { + PciReadConfigUchar(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + if ((Address & 2) && (Len >= 2)) + { + PciReadConfigUshort(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + while (Len >= 4) + { + PciReadConfigUlong(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 4; + Address += 4; + Len -= 4; + } + + if (Len >= 2) + { + PciReadConfigUshort(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + if (Len >= 1) + { + PciReadConfigUchar(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + return Length - Len; +} + + +ULONG +PciSetBusData(ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PVOID Ptr = Buffer; + ULONG Address = Offset; + ULONG Len = Length; + ULONG Vendor; + UCHAR HeaderType; + +#if 0 + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); +#endif + + if ((Length == 0) || (PciBusConfigType == 0)) + return 0; + + /* 0E=PCI_HEADER_TYPE */ + PciReadConfigUchar(BusNumber, + SlotNumber & 0xF8, + 0x0E, + &HeaderType); + if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0)) + return 0; + + PciReadConfigUlong(BusNumber, + SlotNumber, + 0x00, + &Vendor); + /* some broken boards return 0 if a slot is empty: */ + if (Vendor == 0xFFFFFFFF || Vendor == 0) + return 0; + + if ((Address & 1) && (Len >= 1)) + { + PciWriteConfigUchar(BusNumber, + SlotNumber, + Address, + *(PUCHAR)Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + if ((Address & 2) && (Len >= 2)) + { + PciWriteConfigUshort(BusNumber, + SlotNumber, + Address, + *(PUSHORT)Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + while (Len >= 4) + { + PciWriteConfigUlong(BusNumber, + SlotNumber, + Address, + *(PULONG)Ptr); + Ptr = Ptr + 4; + Address += 4; + Len -= 4; + } + + if (Len >= 2) + { + PciWriteConfigUshort(BusNumber, + SlotNumber, + Address, + *(PUSHORT)Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + if (Len >= 1) + { + PciWriteConfigUchar(BusNumber, + SlotNumber, + Address, + *(PUCHAR)Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + return Length - Len; +} + + +PCI_BUS_TYPE +PciGetBusConfigType(VOID) +{ + ULONG Value; + + DPRINT("Called\n"); + + DPRINT("Checking configuration type 1:\n"); + WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01); + Value = READ_PORT_ULONG((PULONG)0xCF8); + WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000); + if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000) + { + WRITE_PORT_ULONG((PULONG)0xCF8, Value); + DPRINT(" Success!\n"); + return pbtType1; + } + WRITE_PORT_ULONG((PULONG)0xCF8, Value); + DPRINT(" Unsuccessful!\n"); + + DPRINT("Checking configuration type 2:\n"); + WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00); + if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 && + READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00) + { + DPRINT(" Success!\n"); + return pbtType2; + } + DPRINT(" Unsuccessful!\n"); + + DPRINT("No pci bus found!\n"); + return pbtUnknown; +} + + +NTSTATUS +STDCALL +PciDispatchDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called. IRP is at (0x%X)\n", Irp); + + Irp->IoStatus.Information = 0; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + + DPRINT("Completing IRP at 0x%X\n", Irp); + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +PciPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PCOMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + DPRINT("IsFDO %d\n", DeviceExtension->IsFDO); + + if (DeviceExtension->IsFDO) { + Status = FdoPnpControl(DeviceObject, Irp); + } else { + Status = PdoPnpControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +PciPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle power management IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PCOMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->IsFDO) { + Status = FdoPowerControl(DeviceObject, Irp); + } else { + Status = PdoPowerControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +PciAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT Fdo; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), + NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + return Status; + } + + DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; + + RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION)); + + DeviceExtension->Common.IsFDO = TRUE; + + DeviceExtension->Ldo = + IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject); + + DeviceExtension->State = dsStopped; + + Fdo->Flags &= ~DO_DEVICE_INITIALIZING; + + //Fdo->Flags |= DO_POWER_PAGABLE; + + DPRINT("Done AddDevice\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DbgPrint("Peripheral Component Interconnect Bus Driver\n"); + + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH) PciDispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PciPnpControl; + DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PciPowerControl; + DriverObject->DriverExtension->AddDevice = PciAddDevice; + + return STATUS_SUCCESS; +} + + +BOOLEAN +PciCreateUnicodeString( + PUNICODE_STRING Destination, + PWSTR Source, + POOL_TYPE PoolType) +{ + ULONG Length; + + if (!Source) + { + RtlInitUnicodeString(Destination, NULL); + return TRUE; + } + + Length = (wcslen(Source) + 1) * sizeof(WCHAR); + + Destination->Buffer = ExAllocatePool(PoolType, Length); + + if (Destination->Buffer == NULL) + { + return FALSE; + } + + RtlCopyMemory(Destination->Buffer, Source, Length); + + Destination->MaximumLength = Length; + + Destination->Length = Length - sizeof(WCHAR); + + return TRUE; +} + +/* EOF */ diff --git a/drivers/bus/pci/pci.h b/drivers/bus/pci/pci.h new file mode 100644 index 0000000..20bc2a6 --- /dev/null +++ b/drivers/bus/pci/pci.h @@ -0,0 +1,129 @@ +/* $Id$ */ + +#ifndef __PCI_H +#define __PCI_H + +#include +#include + + +typedef enum { + pbtUnknown = 0, + pbtType1, + pbtType2, +} PCI_BUS_TYPE; + + +typedef struct _PCI_DEVICE +{ + // Entry on device list + LIST_ENTRY ListEntry; + // Physical Device Object of device + PDEVICE_OBJECT Pdo; + // PCI configuration data + PCI_COMMON_CONFIG PciConfig; + // Flag used during enumeration to locate removed devices + BOOLEAN RemovePending; +} PCI_DEVICE, *PPCI_DEVICE; + + +typedef enum { + dsStopped, + dsStarted, + dsPaused, + dsRemoved, + dsSurpriseRemoved +} PCI_DEVICE_STATE; + + +typedef struct _COMMON_DEVICE_EXTENSION +{ + // Pointer to device object, this device extension is associated with + PDEVICE_OBJECT DeviceObject; + // Wether this device extension is for an FDO or PDO + BOOLEAN IsFDO; + // Wether the device is removed + BOOLEAN Removed; + // Current device power state for the device + DEVICE_POWER_STATE DevicePowerState; +} __attribute((packed)) COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; + +/* Physical Device Object device extension for a child device */ +typedef struct _PDO_DEVICE_EXTENSION +{ + // Common device data + COMMON_DEVICE_EXTENSION Common; + // Device ID + UNICODE_STRING DeviceID; + // Instance ID + UNICODE_STRING InstanceID; + // Hardware IDs + UNICODE_STRING HardwareIDs; + // Compatible IDs + UNICODE_STRING CompatibleIDs; + // Textual description of device + UNICODE_STRING DeviceText; + // Textual description of device + UNICODE_STRING DeviceTextLocation; +} __attribute((packed)) PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION; + +/* Functional Device Object device extension for the PCI driver device object */ +typedef struct _FDO_DEVICE_EXTENSION +{ + // Common device data + COMMON_DEVICE_EXTENSION Common; + // Physical Device Object + PDEVICE_OBJECT Pdo; + // Current state of the driver + PCI_DEVICE_STATE State; + // Namespace device list + LIST_ENTRY DeviceListHead; + // Number of (not removed) devices in device list + ULONG DeviceListCount; + // Lock for namespace device list + KSPIN_LOCK DeviceListLock; + // PCI bus number + ULONG BusNumber; + // Lower device object + PDEVICE_OBJECT Ldo; +} __attribute((packed)) FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; + + +/* fdo.c */ + +NTSTATUS +FdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +FdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* pci.c */ + +extern PCI_BUS_TYPE PciBusConfigType; + +PCI_BUS_TYPE +PciGetBusConfigType(VOID); + +BOOLEAN +PciCreateUnicodeString( + PUNICODE_STRING Destination, + PWSTR Source, + POOL_TYPE PoolType); + +/* pdo.c */ + +NTSTATUS +PdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +PdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +#endif /* __PCI_H */ diff --git a/drivers/bus/pci/pci.rc b/drivers/bus/pci/pci.rc new file mode 100644 index 0000000..e21a994 --- /dev/null +++ b/drivers/bus/pci/pci.rc @@ -0,0 +1,38 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "PCI Bus Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "pci\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "pci.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/drivers/bus/pci/pcidef.h b/drivers/bus/pci/pcidef.h new file mode 100644 index 0000000..51134fb --- /dev/null +++ b/drivers/bus/pci/pcidef.h @@ -0,0 +1,315 @@ +/* + * $Id$ + * + * PCI defines and function prototypes + * Copyright 1994, Drew Eckhardt + * Copyright 1997--1999 Martin Mares + * + * For more information, please consult the following manuals (look at + * http://www.pcisig.com/ for how to get them): + * + * PCI BIOS Specification + * PCI Local Bus Specification + * PCI to PCI Bridge Specification + * PCI System Design Guide + * + * Ported from linux pci.h to ReactOS by: + * Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +#ifndef _PCIDEF_H +#define _PCIDEF_H + +/* + * Under PCI, each device has 256 bytes of configuration address space, + * of which the first 64 bytes are standardized as follows: + */ +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ +#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ +#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ +#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ +#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ +#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ +#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ +#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ + +#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ +#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ +#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ +#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ +#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ +#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ +#define PCI_STATUS_DEVSEL_FAST 0x000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x200 +#define PCI_STATUS_DEVSEL_SLOW 0x400 +#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ +#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ +#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ +#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ +#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + +#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 + revision */ +#define PCI_REVISION_ID 0x08 /* Revision ID */ +#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ + +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_HEADER_TYPE_NORMAL 0 +#define PCI_HEADER_TYPE_BRIDGE 1 +#define PCI_HEADER_TYPE_CARDBUS 2 + +#define PCI_BIST 0x0f /* 8 bits */ +#define PCI_BIST_CODE_MASK 0x0f /* Return result */ +#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ +#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ + +/* + * Base addresses specify locations in memory or I/O space. + * Decoded size can be determined by writing a value of + * 0xffffffff to the register, and reading it back. Only + * 1 bits are decoded. + */ +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ +#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ +#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ +#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ +#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ +#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ +#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ +#define PCI_BASE_ADDRESS_SPACE_IO 0x01 +#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 +#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 +#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ +#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ +#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ +#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ +#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) +#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) +/* bit 1 is reserved if address_space = 1 */ + +/* Header type 0 (normal devices) */ +#define PCI_CARDBUS_CIS 0x28 +#define PCI_SUBSYSTEM_VENDOR_ID 0x2c +#define PCI_SUBSYSTEM_ID 0x2e +#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 +#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) + +#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ + +/* 0x35-0x3b are reserved */ +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +/* Header type 1 (PCI-to-PCI bridges) */ +#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ +#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ +#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ +#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ +#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ +#define PCI_IO_LIMIT 0x1d +#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */ +#define PCI_IO_RANGE_TYPE_16 0x00 +#define PCI_IO_RANGE_TYPE_32 0x01 +#define PCI_IO_RANGE_MASK ~0x0f +#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ +#define PCI_MEMORY_BASE 0x20 /* Memory range behind */ +#define PCI_MEMORY_LIMIT 0x22 +#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f +#define PCI_MEMORY_RANGE_MASK ~0x0f +#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ +#define PCI_PREF_MEMORY_LIMIT 0x26 +#define PCI_PREF_RANGE_TYPE_MASK 0x0f +#define PCI_PREF_RANGE_TYPE_32 0x00 +#define PCI_PREF_RANGE_TYPE_64 0x01 +#define PCI_PREF_RANGE_MASK ~0x0f +#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ +#define PCI_PREF_LIMIT_UPPER32 0x2c +#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ +#define PCI_IO_LIMIT_UPPER16 0x32 +/* 0x34 same as for htype 0 */ +/* 0x35-0x3b is reserved */ +#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ +/* 0x3c-0x3d are same as for htype 0 */ +#define PCI_BRIDGE_CONTROL 0x3e +#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */ +#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ +#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */ +#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ +#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ +#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ +#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ + +/* Header type 2 (CardBus bridges) */ +#define PCI_CB_CAPABILITY_LIST 0x14 +/* 0x15 reserved */ +#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */ +#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */ +#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */ +#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */ +#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ +#define PCI_CB_MEMORY_BASE_0 0x1c +#define PCI_CB_MEMORY_LIMIT_0 0x20 +#define PCI_CB_MEMORY_BASE_1 0x24 +#define PCI_CB_MEMORY_LIMIT_1 0x28 +#define PCI_CB_IO_BASE_0 0x2c +#define PCI_CB_IO_BASE_0_HI 0x2e +#define PCI_CB_IO_LIMIT_0 0x30 +#define PCI_CB_IO_LIMIT_0_HI 0x32 +#define PCI_CB_IO_BASE_1 0x34 +#define PCI_CB_IO_BASE_1_HI 0x36 +#define PCI_CB_IO_LIMIT_1 0x38 +#define PCI_CB_IO_LIMIT_1_HI 0x3a +#define PCI_CB_IO_RANGE_MASK ~0x03 +/* 0x3c-0x3d are same as for htype 0 */ +#define PCI_CB_BRIDGE_CONTROL 0x3e +#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */ +#define PCI_CB_BRIDGE_CTL_SERR 0x02 +#define PCI_CB_BRIDGE_CTL_ISA 0x04 +#define PCI_CB_BRIDGE_CTL_VGA 0x08 +#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20 +#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ +#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 +#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 +#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 +#define PCI_CB_SUBSYSTEM_ID 0x42 +#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ +/* 0x48-0x7f reserved */ + +/* Capability lists */ + +#define PCI_CAP_LIST_ID 0 /* Capability ID */ +#define PCI_CAP_ID_PM 0x01 /* Power Management */ +#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ +#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */ +#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ +#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ +#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ +#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ +#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ +#define PCI_CAP_SIZEOF 4 + +/* Power Management Registers */ + +#define PCI_PM_PMC 2 /* PM Capabilities Register */ +#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */ +#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ +#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ +#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ +#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */ +#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ +#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ +#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ +#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */ +#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */ +#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */ +#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */ +#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */ +#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */ +#define PCI_PM_CTRL 4 /* PM control and status register */ +#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ +#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ +#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ +#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ +#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ +#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ +#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ +#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */ +#define PCI_PM_DATA_REGISTER 7 /* (??) */ +#define PCI_PM_SIZEOF 8 + +/* AGP registers */ + +#define PCI_AGP_VERSION 2 /* BCD version number */ +#define PCI_AGP_RFU 3 /* Rest of capability flags */ +#define PCI_AGP_STATUS 4 /* Status register */ +#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */ +#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */ +#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */ +#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */ +#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */ +#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */ +#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */ +#define PCI_AGP_COMMAND 8 /* Control register */ +#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ +#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ +#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ +#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */ +#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */ +#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */ +#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 4x rate */ +#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 4x rate */ +#define PCI_AGP_SIZEOF 12 + +/* Slot Identification */ + +#define PCI_SID_ESR 2 /* Expansion Slot Register */ +#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */ +#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ +#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ + +/* Message Signalled Interrupts registers */ + +#define PCI_MSI_FLAGS 2 /* Various flags */ +#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ +#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ +#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ +#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ +#define PCI_MSI_RFU 3 /* Rest of capability flags */ +#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ +#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ +#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ +#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ + +/* + * The PCI interface treats multi-function devices as independent + * devices. The slot/function address of each device is encoded + * in a single byte as follows: + * + * 7:3 = slot + * 2:0 = function + */ +#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) +#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define PCI_FUNC(devfn) ((devfn) & 0x07) + + +/* + * For PCI devices, the region numbers are assigned this way: + * + * 0-5 standard PCI regions + * 6 expansion ROM + * 7-10 bridges: address space assigned to buses behind the bridge + */ + +#define PCI_ROM_RESOURCE 6 +#define PCI_BRIDGE_RESOURCES 7 +#define PCI_NUM_RESOURCES 11 + +#define PCI_REGION_FLAG_MASK 0x0f /* These bits of resource flags tell us the PCI region flags */ + + + +#define CONFIG_CMD(bus, device_fn, where) \ + (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) + +#define IOADDR(devfn, where) \ + ((0xC000 | ((devfn & 0x78) << 5)) + where) + +#define FUNC(devfn) \ + (((devfn & 7) << 1) | 0xf0) + +#endif /* _PCIDEF_H */ diff --git a/drivers/bus/pci/pdo.c b/drivers/bus/pci/pdo.c new file mode 100644 index 0000000..99b604f --- /dev/null +++ b/drivers/bus/pci/pdo.c @@ -0,0 +1,242 @@ +/* $Id$ + * + * PROJECT: ReactOS PCI bus driver + * FILE: pdo.c + * PURPOSE: Child device object dispatch routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 10-09-2001 CSH Created + */ +#include + +#define NDEBUG +#include + +/*** PRIVATE *****************************************************************/ + +NTSTATUS +PdoQueryId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPDO_DEVICE_EXTENSION DeviceExtension; + UNICODE_STRING String; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + +// Irp->IoStatus.Information = 0; + + Status = STATUS_SUCCESS; + + RtlInitUnicodeString(&String, NULL); + + switch (IrpSp->Parameters.QueryId.IdType) { + case BusQueryDeviceID: + Status = PciCreateUnicodeString( + &String, + DeviceExtension->DeviceID.Buffer, + PagedPool); + + DPRINT("DeviceID: %S\n", String.Buffer); + + Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; + break; + + case BusQueryHardwareIDs: + case BusQueryCompatibleIDs: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case BusQueryInstanceID: + Status = PciCreateUnicodeString( + &String, + L"0000", + PagedPool); + + DPRINT("InstanceID: %S\n", String.Buffer); + + Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; + break; + + case BusQueryDeviceSerialNumber: + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; +} + + +NTSTATUS +PdoSetPower( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPDO_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (IrpSp->Parameters.Power.Type == DevicePowerState) { + Status = STATUS_SUCCESS; + switch (IrpSp->Parameters.Power.State.SystemState) { + default: + Status = STATUS_UNSUCCESSFUL; + } + } else { + Status = STATUS_UNSUCCESSFUL; + } + + return Status; +} + + +/*** PUBLIC ******************************************************************/ + +NTSTATUS +PdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { +#if 0 + case IRP_MN_CANCEL_REMOVE_DEVICE: + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + break; + + case IRP_MN_EJECT: + break; + + case IRP_MN_QUERY_BUS_INFORMATION: + break; + + case IRP_MN_QUERY_CAPABILITIES: + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + /* FIXME: Possibly handle for RemovalRelations */ + break; + + case IRP_MN_QUERY_DEVICE_TEXT: + break; +#endif + case IRP_MN_QUERY_ID: + Status = PdoQueryId(DeviceObject, Irp, IrpSp); + break; +#if 0 + case IRP_MN_QUERY_PNP_DEVICE_STATE: + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + break; + + case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: + break; + + case IRP_MN_QUERY_RESOURCES: + break; + + case IRP_MN_QUERY_STOP_DEVICE: + break; + + case IRP_MN_REMOVE_DEVICE: + break; + + case IRP_MN_SET_LOCK: + break; + + case IRP_MN_START_DEVICE: + break; + + case IRP_MN_STOP_DEVICE: + break; + + case IRP_MN_SURPRISE_REMOVAL: + break; +#endif + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +NTSTATUS +PdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + case IRP_MN_SET_POWER: + Status = PdoSetPower(DeviceObject, Irp, IrpSp); + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +/* EOF */ diff --git a/drivers/dd/beep/.cvsignore b/drivers/dd/beep/.cvsignore new file mode 100644 index 0000000..ca1cbcf --- /dev/null +++ b/drivers/dd/beep/.cvsignore @@ -0,0 +1,4 @@ +base.tmp +junk.tmp +temp.exp +beep.coff diff --git a/drivers/dd/beep/beep.c b/drivers/dd/beep/beep.c new file mode 100644 index 0000000..81ef515 --- /dev/null +++ b/drivers/dd/beep/beep.c @@ -0,0 +1,285 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/dd/beep/beep.c + * PURPOSE: BEEP device driver + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 30/01/99 Created + * 16/10/99 Minor fixes + */ + +/* INCLUDES ****************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* TYEPEDEFS ***************************************************************/ + +typedef struct _BEEP_DEVICE_EXTENSION +{ + KDPC Dpc; + KTIMER Timer; + KEVENT Event; + BOOLEAN BeepOn; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + + +/* FUNCTIONS ***************************************************************/ + +static VOID STDCALL +BeepDPC(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PDEVICE_EXTENSION DeviceExtension = DeferredContext; + + DPRINT("BeepDPC() called!\n"); + + HalMakeBeep(0); + DeviceExtension->BeepOn = FALSE; + KeSetEvent(&DeviceExtension->Event, + 0, + FALSE); + + DPRINT("BeepDPC() finished!\n"); +} + + +static NTSTATUS STDCALL +BeepCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + DPRINT("BeepCreate() called!\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +BeepClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + PDEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("BeepClose() called!\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + if (DeviceExtension->BeepOn == TRUE) + { + HalMakeBeep(0); + DeviceExtension->BeepOn = FALSE; + KeCancelTimer(&DeviceExtension->Timer); + } + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + + +static NTSTATUS STDCALL +BeepCleanup(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + DPRINT("BeepCleanup() called!\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +BeepDeviceControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + PIO_STACK_LOCATION Stack; + PDEVICE_EXTENSION DeviceExtension; + PBEEP_SET_PARAMETERS BeepParam; + LARGE_INTEGER DueTime; + + DPRINT("BeepDeviceControl() called!\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer; + + Irp->IoStatus.Information = 0; + + if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET) + { + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_NOT_IMPLEMENTED); + } + + if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS)) + || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM) + || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM)) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_INVALID_PARAMETER); + } + + DueTime.QuadPart = 0; + + /* do the beep!! */ + DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n", + pbsp->Frequency, + pbsp->Duration); + + if (BeepParam->Duration >= 0) + { + DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000; + + KeSetTimer(&DeviceExtension->Timer, + DueTime, + &DeviceExtension->Dpc); + + HalMakeBeep(BeepParam->Frequency); + DeviceExtension->BeepOn = TRUE; + KeWaitForSingleObject(&DeviceExtension->Event, + Executive, + KernelMode, + FALSE, + NULL); + } + else if (BeepParam->Duration == (DWORD)-1) + { + if (DeviceExtension->BeepOn == TRUE) + { + HalMakeBeep(0); + DeviceExtension->BeepOn = FALSE; + } + else + { + HalMakeBeep(BeepParam->Frequency); + DeviceExtension->BeepOn = TRUE; + } + } + + DPRINT("Did the beep!\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +BeepUnload(PDRIVER_OBJECT DriverObject) +{ + DPRINT("BeepUnload() called!\n"); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Beep"); + UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\Beep"); + NTSTATUS Status; + + DPRINT("Beep Device Driver 0.0.3\n"); + + DriverObject->Flags = 0; + DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl; + DriverObject->DriverUnload = BeepUnload; + + Status = IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_BEEP, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + return Status; + + /* set up device extension */ + DeviceExtension = DeviceObject->DeviceExtension; + DeviceExtension->BeepOn = FALSE; + + KeInitializeDpc(&DeviceExtension->Dpc, + BeepDPC, + DeviceExtension); + KeInitializeTimer(&DeviceExtension->Timer); + KeInitializeEvent(&DeviceExtension->Event, + SynchronizationEvent, + FALSE); + + /* Create the dos device link */ + IoCreateSymbolicLink(&SymlinkName, + &DeviceName); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/dd/beep/beep.rc b/drivers/dd/beep/beep.rc new file mode 100644 index 0000000..c48ff21 --- /dev/null +++ b/drivers/dd/beep/beep.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "PC Speaker Device Driver\0" + VALUE "FileVersion", "0.0.3\0" + VALUE "InternalName", "beep\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "beep.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/beep/makefile b/drivers/dd/beep/makefile new file mode 100644 index 0000000..79b1139 --- /dev/null +++ b/drivers/dd/beep/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = beep + +TARGET_OBJECTS = beep.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/blue/.cvsignore b/drivers/dd/blue/.cvsignore new file mode 100644 index 0000000..ae9bad6 --- /dev/null +++ b/drivers/dd/blue/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +blue.coff +blue.sys.unstripped \ No newline at end of file diff --git a/drivers/dd/blue/blue.c b/drivers/dd/blue/blue.c new file mode 100644 index 0000000..058d819 --- /dev/null +++ b/drivers/dd/blue/blue.c @@ -0,0 +1,634 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/dd/blue/blue.c + * PURPOSE: Console (blue screen) device driver + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * ??? Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* DEFINITIONS ***************************************************************/ + +#define VIDMEM_BASE 0xb8000 +#define VIDMEM_SIZE 0x2000 + +#define CRTC_COMMAND ((PUCHAR)0x3d4) +#define CRTC_DATA ((PUCHAR)0x3d5) + +#define CRTC_COLUMNS 0x01 +#define CRTC_OVERFLOW 0x07 +#define CRTC_ROWS 0x12 +#define CRTC_SCANLINES 0x09 +#define CRTC_CURSORSTART 0x0a +#define CRTC_CURSOREND 0x0b +#define CRTC_CURSORPOSHI 0x0e +#define CRTC_CURSORPOSLO 0x0f + +#define ATTRC_WRITEREG ((PUCHAR)0x3c0) +#define ATTRC_READREG ((PUCHAR)0x3c1) +#define ATTRC_INPST1 ((PUCHAR)0x3da) + +#define TAB_WIDTH 8 + + +/* NOTES ******************************************************************/ +/* + * [[character][attribute]][[character][attribute]].... + */ + + +/* TYPEDEFS ***************************************************************/ + +typedef struct _DEVICE_EXTENSION +{ + PBYTE VideoMemory; /* Pointer to video memory */ + DWORD CursorSize; + BOOL CursorVisible; + WORD CharAttribute; + DWORD Mode; + BYTE ScanLines; /* Height of a text line */ + WORD Rows; /* Number of rows */ + WORD Columns; /* Number of columns */ +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + + +/* FUNCTIONS **************************************************************/ + +NTSTATUS STDCALL +ScrCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PHYSICAL_ADDRESS BaseAddress; + NTSTATUS Status; + unsigned int offset; + BYTE data, value; + + DeviceExtension = DeviceObject->DeviceExtension; + + /* get pointer to video memory */ + BaseAddress.QuadPart = VIDMEM_BASE; + DeviceExtension->VideoMemory = + (PBYTE)MmMapIoSpace (BaseAddress, VIDMEM_SIZE, FALSE); + + /* disable interrupts */ + __asm__("cli\n\t"); + + /* get current output position */ + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + offset = READ_PORT_UCHAR (CRTC_DATA); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); + + /* switch blinking characters off */ + READ_PORT_UCHAR (ATTRC_INPST1); + value = READ_PORT_UCHAR (ATTRC_WRITEREG); + WRITE_PORT_UCHAR (ATTRC_WRITEREG, 0x10); + data = READ_PORT_UCHAR (ATTRC_READREG); + data = data & ~0x08; + WRITE_PORT_UCHAR (ATTRC_WRITEREG, data); + WRITE_PORT_UCHAR (ATTRC_WRITEREG, value); + READ_PORT_UCHAR (ATTRC_INPST1); + + /* read screen information from crt controller */ + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_COLUMNS); + DeviceExtension->Columns = READ_PORT_UCHAR (CRTC_DATA) + 1; + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_ROWS); + DeviceExtension->Rows = READ_PORT_UCHAR (CRTC_DATA); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_OVERFLOW); + data = READ_PORT_UCHAR (CRTC_DATA); + DeviceExtension->Rows |= (((data & 0x02) << 7) | ((data & 0x40) << 3)); + DeviceExtension->Rows++; + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_SCANLINES); + DeviceExtension->ScanLines = (READ_PORT_UCHAR (CRTC_DATA) & 0x1F) + 1; + + /* enable interrupts */ + __asm__("sti\n\t"); + + /* calculate number of text rows */ + DeviceExtension->Rows = + DeviceExtension->Rows / DeviceExtension->ScanLines; +#ifdef BOCHS_30ROWS + DeviceExtension->Rows = 30; +#endif + + DPRINT ("%d Columns %d Rows %d Scanlines\n", + DeviceExtension->Columns, + DeviceExtension->Rows, + DeviceExtension->ScanLines); + + DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */ + DeviceExtension->CursorVisible = TRUE; + + /* more initialization */ + DeviceExtension->CharAttribute = 0x17; /* light grey on blue */ + DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT | + ENABLE_WRAP_AT_EOL_OUTPUT; + + /* show blinking cursor */ + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); + WRITE_PORT_UCHAR (CRTC_DATA, (DeviceExtension->ScanLines - 1) & 0x1F); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); + data = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; + WRITE_PORT_UCHAR (CRTC_DATA, + data | ((DeviceExtension->ScanLines - 1) & 0x1F)); + __asm__("sti\n\t"); + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return (Status); +} + + +NTSTATUS STDCALL +ScrWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + char *pch = Irp->UserBuffer; + char *vidmem; + int i, j, offset; + int cursorx, cursory; + int rows, columns; + int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT; + + vidmem = DeviceExtension->VideoMemory; + rows = DeviceExtension->Rows; + columns = DeviceExtension->Columns; + + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + offset = READ_PORT_UCHAR (CRTC_DATA)<<8; + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + offset += READ_PORT_UCHAR (CRTC_DATA); + + cursory = offset / columns; + cursorx = offset % columns; + if( processed == 0 ) + { + /* raw output mode */ + memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length ); + offset += (stk->Parameters.Write.Length / 2); + } + else { + for (i = 0; i < stk->Parameters.Write.Length; i++, pch++) + { + switch (*pch) + { + case '\b': + if (cursorx > 0) + { + cursorx--; + } + else if (cursory > 0) + { + cursorx = columns - 1; + cursory--; + } + vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' '; + vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute; + break; + + case '\n': + cursory++; + cursorx = 0; + break; + + case '\r': + cursorx = 0; + break; + + case '\t': + offset = TAB_WIDTH - (cursorx % TAB_WIDTH); + for (j = 0; j < offset; j++) + { + vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' '; + cursorx++; + + if (cursorx >= columns) + { + cursory++; + cursorx = 0; + } + } + break; + + default: + vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch; + vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute; + cursorx++; + if (cursorx >= columns) + { + cursory++; + cursorx = 0; + } + break; + } + if (cursory >= rows) + { + unsigned short *LinePtr; + + memcpy (vidmem, + &vidmem[columns * 2], + columns * (rows - 1) * 2); + + LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2]; + + for (j = 0; j < columns; j++) + { + LinePtr[j] = DeviceExtension->CharAttribute << 8; + } + cursory = rows - 1; + for (j = 0; j < columns; j++) + { + vidmem[(j * 2) + (cursory * columns * 2)] = ' '; + vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute; + } + } + } + + /* Set the cursor position */ + offset = (cursory * columns) + cursorx; + } + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + WRITE_PORT_UCHAR (CRTC_DATA, offset); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + offset >>= 8; + WRITE_PORT_UCHAR (CRTC_DATA, offset); + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return (Status); +} + + +NTSTATUS STDCALL +ScrIoControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); + PDEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + DeviceExtension = DeviceObject->DeviceExtension; + switch (stk->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO: + { + PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; + int rows = DeviceExtension->Rows; + int columns = DeviceExtension->Columns; + unsigned int offset; + + /* read cursor position from crtc */ + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + offset = READ_PORT_UCHAR (CRTC_DATA); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); + __asm__("sti\n\t"); + + pcsbi->dwSize.X = columns; + pcsbi->dwSize.Y = rows; + + pcsbi->dwCursorPosition.X = (SHORT)(offset % columns); + pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns); + + pcsbi->wAttributes = DeviceExtension->CharAttribute; + + pcsbi->srWindow.Left = 0; + pcsbi->srWindow.Right = columns - 1; + pcsbi->srWindow.Top = 0; + pcsbi->srWindow.Bottom = rows - 1; + + pcsbi->dwMaximumWindowSize.X = columns; + pcsbi->dwMaximumWindowSize.Y = rows; + + Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO: + { + PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; + unsigned int offset; + + DeviceExtension->CharAttribute = pcsbi->wAttributes; + offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) + + pcsbi->dwCursorPosition.X; + + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + WRITE_PORT_UCHAR (CRTC_DATA, offset); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + WRITE_PORT_UCHAR (CRTC_DATA, offset>>8); + __asm__("sti\n\t"); + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_GET_CURSOR_INFO: + { + PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; + + pcci->dwSize = DeviceExtension->CursorSize; + pcci->bVisible = DeviceExtension->CursorVisible; + + Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_CURSOR_INFO: + { + PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; + BYTE data, value; + DWORD size, height; + + DeviceExtension->CursorSize = pcci->dwSize; + DeviceExtension->CursorVisible = pcci->bVisible; + height = DeviceExtension->ScanLines; + data = (pcci->bVisible) ? 0x40 : 0x20; + + size = (pcci->dwSize * height) / 100; + if (size < 1) + size = 1; + + data |= (BYTE)(height - size); + + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); + WRITE_PORT_UCHAR (CRTC_DATA, data); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); + value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; + WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1)); + + __asm__("sti\n\t"); + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_GET_MODE: + { + PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; + + pcm->dwMode = DeviceExtension->Mode; + + Irp->IoStatus.Information = sizeof(CONSOLE_MODE); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_MODE: + { + PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; + + DeviceExtension->Mode = pcm->dwMode; + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE: + { + POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2) + 1; + + for (dwCount = 0; dwCount < Buf->nLength; dwCount++) + { + vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute; + } + + Buf->dwTransfered = Buf->nLength; + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE: + { + POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; + PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress); + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2) + 1; + + for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pAttr++) + { + (char) *pAttr = vidmem[offset + (dwCount * 2)]; + } + + Buf->dwTransfered = dwCount; + + Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE: + { + COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); + CHAR *pAttr = (CHAR *)(pCoord + 1); + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (pCoord->Y * DeviceExtension->Columns * 2) + + (pCoord->X * 2) + 1; + + for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pAttr++) + { + vidmem[offset + (dwCount * 2)] = *pAttr; + } + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE: + DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer; + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + break; + + + case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER: + { + POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2); + + CHECKPOINT + + for (dwCount = 0; dwCount < Buf->nLength; dwCount++) + { + vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter; + } + + Buf->dwTransfered = Buf->nLength; + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER: + { + POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; + LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress); + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2); + + for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pChar++) + { + *pChar = vidmem[offset + (dwCount * 2)]; + } + + Buf->dwTransfered = dwCount; + + Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER: + { + COORD *pCoord; + LPSTR pChar; + char *vidmem; + int offset; + DWORD dwCount; + pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); + pChar = (CHAR *)(pCoord + 1); + vidmem = DeviceExtension->VideoMemory; + offset = (pCoord->Y * DeviceExtension->Columns * 2) + + (pCoord->X * 2); + + for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pChar++) + { + vidmem[offset + (dwCount * 2)] = *pChar; + } + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return (Status); +} + + +NTSTATUS STDCALL +ScrDispatch(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + + switch (stk->MajorFunction) + { + case IRP_MJ_CLOSE: + Status = STATUS_SUCCESS; + break; + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return (Status); +} + + +/* + * Module entry point + */ +NTSTATUS STDCALL +DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\BlueScreen"); + UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\BlueScreen"); + + DPRINT ("Screen Driver 0.0.6\n"); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch; + DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl; + + IoCreateDevice (DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_SCREEN, + 0, + TRUE, + &DeviceObject); + + IoCreateSymbolicLink (&SymlinkName, &DeviceName); + + return (STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/dd/blue/blue.rc b/drivers/dd/blue/blue.rc new file mode 100644 index 0000000..dafbe1f --- /dev/null +++ b/drivers/dd/blue/blue.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "HAL Console Device Driver\0" + VALUE "FileVersion", "0.0.6\0" + VALUE "InternalName", "blue\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "blue.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/blue/makefile b/drivers/dd/blue/makefile new file mode 100644 index 0000000..ebc9e15 --- /dev/null +++ b/drivers/dd/blue/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = blue + +TARGET_OBJECTS = blue.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/floppy/.cvsignore b/drivers/dd/floppy/.cvsignore new file mode 100644 index 0000000..8bfa9ae --- /dev/null +++ b/drivers/dd/floppy/.cvsignore @@ -0,0 +1,2 @@ +floppy.sys.unstripped +floppy.coff diff --git a/drivers/dd/floppy/Makefile b/drivers/dd/floppy/Makefile new file mode 100644 index 0000000..ab1bd9a --- /dev/null +++ b/drivers/dd/floppy/Makefile @@ -0,0 +1,16 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = floppy + +TARGET_OBJECTS = \ + dpc.o \ + floppy.o \ + isr.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/floppy/dpc.c b/drivers/dd/floppy/dpc.c new file mode 100644 index 0000000..d36847b --- /dev/null +++ b/drivers/dd/floppy/dpc.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * Defered procedure calls for floppy disk driver, reactos project, created * + * by Phillip Susi on 2/25/2001. This software is published under the GNU * + * general public license, see the README file for more details * + ***************************************************************************/ + +#include +#define NDEBUG +#include +#include "floppy.h" + + +VOID STDCALL +FloppyDpc(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + ControllerExtension->DpcState( Dpc, + DeviceObject, + Irp, + Context ); +} + + +VOID STDCALL +FloppyDpcDetect(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + KeSetEvent( &ControllerExtension->Event, 0, FALSE ); +} + +VOID STDCALL +FloppyDpcFailIrp(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; + CHECKPOINT; + IoCompleteRequest( Irp, 0 ); +} + +VOID STDCALL +FloppyMotorSpindownDpc(PKDPC Dpc, + PVOID Context, + PVOID Arg1, + PVOID Arg2 ) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension; + + // queue call to turn off motor + IoAllocateController( Controller, + ControllerExtension->Device, + FloppyExecuteSpindown, + ControllerExtension ); +} + +VOID STDCALL +FloppyMotorSpinupDpc(PKDPC Dpc, + PVOID Context, + PVOID Arg1, + PVOID Arg2) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension; + LARGE_INTEGER Timeout; + + Timeout.QuadPart = FLOPPY_MOTOR_SPINDOWN_TIME; + // Motor has had time to spin up, mark motor as spun up and restart IRP + // don't forget to set the spindown timer + KeSetTimer( &ControllerExtension->SpinupTimer, + Timeout, + &ControllerExtension->MotorSpindownDpc ); + DPRINT( "Motor spun up, retrying operation\n" ); + ControllerExtension->MotorOn = DeviceExtension->DriveSelect; + IoFreeController( Controller ); + IoAllocateController( Controller, + ControllerExtension->Device, + FloppyExecuteReadWrite, + ControllerExtension->Irp ); +} + +VOID STDCALL +FloppySeekDpc(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension; + + // if the seek failed, fail the IRP + if( ControllerExtension->St0 & FLOPPY_ST0_GDMASK ) + { + ControllerExtension->Irp->IoStatus.Status = STATUS_DISK_CORRUPT_ERROR; + ControllerExtension->Irp->IoStatus.Information = 0; + DPRINT( "Failing IRP: St0 = %2x, St1 = %2x, St2 = %2x\n", + ControllerExtension->St0, + ControllerExtension->St1, + ControllerExtension->St2 ); + for(;;); + IoCompleteRequest( ControllerExtension->Irp, 0 ); + IoFreeController( DeviceExtension->Controller ); + return; + } + KeStallExecutionProcessor( 10000 ); + DPRINT( "Seek completed, now on cyl %2x\n", DeviceExtension->Cyl ); + // now that we are on the right cyl, restart the read + if( FloppyExecuteReadWrite( DeviceObject, + ControllerExtension->Irp, + ControllerExtension->MapRegisterBase, + ControllerExtension->Irp ) == DeallocateObject ) + IoFreeController( DeviceExtension->Controller ); +} + +VOID STDCALL +FloppyDpcReadWrite(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension; + DWORD SectorSize = 128 << ControllerExtension->SectorSizeCode; + PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( ControllerExtension->Irp ); + BOOLEAN WriteToDevice = Stk->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE; + + Irp = ControllerExtension->Irp; + // if the IO failed, fail the IRP + if( ControllerExtension->St0 & FLOPPY_ST0_GDMASK ) + { + Irp->IoStatus.Status = STATUS_DISK_CORRUPT_ERROR; + Irp->IoStatus.Information = 0; + DPRINT( "Failing IRP: St0 = %2x, St1 = %2x, St2 = %2x\n", + ControllerExtension->St0, + ControllerExtension->St1, + ControllerExtension->St2 ); + for(;;); + IoCompleteRequest( Irp, 0 ); + IoFreeController( Controller ); + return; + } + // don't forget to flush the buffers + IoFlushAdapterBuffers( ControllerExtension->AdapterObject, + ControllerExtension->Irp->MdlAddress, + ControllerExtension->MapRegisterBase, + ControllerExtension->Irp->Tail.Overlay.DriverContext[0], + ControllerExtension->TransferLength, + WriteToDevice ); + DPRINT( "St0 = %2x, St1 %2x, St2 = %2x\n", + ControllerExtension->St0, + ControllerExtension->St1, + ControllerExtension->St2 ); + // update buffer info + Stk->Parameters.Read.ByteOffset.u.LowPart += ControllerExtension->TransferLength; + Stk->Parameters.Read.Length -= ControllerExtension->TransferLength; + // drivercontext used for current va + (DWORD)ControllerExtension->Irp->Tail.Overlay.DriverContext[0] += ControllerExtension->TransferLength; + + DPRINT( "First dword: %x\n", *((DWORD *)ControllerExtension->MapRegisterBase) ) + + // if there is more IO to be done, restart execute routine to issue next read + if( Stk->Parameters.Read.Length ) + { + if( FloppyExecuteReadWrite( DeviceObject, + Irp, + ControllerExtension->MapRegisterBase, + Irp ) == DeallocateObject ) + IoFreeController( Controller ); + } + else { + IoFreeController( Controller ); + // otherwise, complete the Irp + IoCompleteRequest( Irp, 0 ); + } +} + +VOID STDCALL +FloppyDpcDetectMedia(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + // If the read ID failed, fail the irp + if( ControllerExtension->St1 != 0 ) + { + DPRINT1( "Read ID failed: ST1 = %2x\n", ControllerExtension->St1 ); + Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; + IoCompleteRequest( Irp, 0 ); + return; + } + // set media type, and restart the IRP from the beginning + ((PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension)->MediaType = 0; + DPRINT( "Media detected, restarting IRP\n" ); + // don't forget to free the controller so that the now queued routine may execute + IoFreeController( Controller ); + + IoAllocateController( Controller, + DeviceObject, + FloppyExecuteReadWrite, + Irp ); +} diff --git a/drivers/dd/floppy/floppy.c b/drivers/dd/floppy/floppy.c new file mode 100644 index 0000000..e5e54e4 --- /dev/null +++ b/drivers/dd/floppy/floppy.c @@ -0,0 +1,556 @@ +/* + * FLOPPY.C - NEC-765/8272A floppy device driver + * written by Rex Jolliff + * with help from various other sources, including but not limited to: + * Art Baker's NT Device Driver Book, Linux Source, and the internet. + * + * Modification History: + * 08/19/98 RJJ Created. + * 01/31/01 PJS Heavy rewrite, most of code thrown out + * + * To do: + * FIXME: get it working + * FIXME: add support for DMA hardware + * FIXME: should add support for floppy tape/zip devices + */ + +#include + +#include "floppy.h" +#define NDEBUG +#include + + +FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] = +{ + {0x03f0, 6, 6, 2, 6, LevelSensitive, 0xffff} + // {0x0370, 6, 6, 6, LevelSensitive, 0xffff}, +}; + +const FLOPPY_MEDIA_TYPE MediaTypes[] = { + { 0x02, 80, 2, 18, 512 }, + { 0, 0, 0, 0, 0 } }; + + +static BOOLEAN +FloppyCreateController(PDRIVER_OBJECT DriverObject, + PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters, + int Index) +{ + PCONTROLLER_OBJECT ControllerObject; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension; + PFLOPPY_DEVICE_EXTENSION DeviceExtension; + UNICODE_STRING DeviceName; + NTSTATUS Status; + PDEVICE_OBJECT DeviceObject; + PCONFIGURATION_INFORMATION ConfigInfo; + LARGE_INTEGER Timeout; + BYTE Byte; + int c; + PCONFIGURATION_INFORMATION Config; + DEVICE_DESCRIPTION DeviceDescription; + ULONG MaxMapRegs; + + /* FIXME: Register port ranges and interrupts with HAL */ + + /* Create controller object for FDC */ + ControllerObject = IoCreateController(sizeof(FLOPPY_CONTROLLER_EXTENSION)); + if (ControllerObject == NULL) + { + DPRINT("Could not create controller object for controller %d\n", + Index); + return FALSE; + } + + /* FIXME: fill out controller data */ + ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION) + ControllerObject->ControllerExtension; + ControllerExtension->Number = Index; + ControllerExtension->PortBase = ControllerParameters->PortBase; + ControllerExtension->Vector = ControllerParameters->Vector; + KeInitializeEvent( &ControllerExtension->Event, SynchronizationEvent, FALSE ); + ControllerExtension->Device = 0; // no active device + ControllerExtension->Irp = 0; // no active IRP + /* Initialize the spin lock in the controller extension */ + KeInitializeSpinLock(&ControllerExtension->SpinLock); + ControllerExtension->IsrState = FloppyIsrDetect; + ControllerExtension->DpcState = FloppyDpcDetect; + + /* Register an interrupt handler for this controller */ + Status = IoConnectInterrupt(&ControllerExtension->Interrupt, + FloppyIsr, + ControllerObject, + &ControllerExtension->SpinLock, + ControllerExtension->Vector, + ControllerParameters->IrqL, + ControllerParameters->SynchronizeIrqL, + ControllerParameters->InterruptMode, + FALSE, + ControllerParameters->Affinity, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not Connect Interrupt %d\n", + ControllerExtension->Vector); + goto controllercleanup; + } + + + /* setup DMA stuff for controller */ + DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; + DeviceDescription.Master = FALSE; + DeviceDescription.ScatterGather = FALSE; + DeviceDescription.AutoInitialize = FALSE; + DeviceDescription.Dma32BitAddress = FALSE; + DeviceDescription.DmaChannel = ControllerParameters->DmaChannel; + DeviceDescription.InterfaceType = Isa; + // DeviceDescription.DmaWidth = Width8Bits; + ControllerExtension->AdapterObject = HalGetAdapter( &DeviceDescription, &MaxMapRegs ); + if( ControllerExtension->AdapterObject == NULL ) + { + DPRINT1( "Could not get adapter object\n" ); + goto interruptcleanup; + } + +#if 0 + /* Check for each possible drive and create devices for them */ + for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++) + { + /* FIXME: try to identify the drive */ + /* FIXME: create a device if it's there */ + } +#endif + + /* FIXME: Let's assume one drive and one controller for the moment */ + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\Floppy0"); + Status = IoCreateDevice(DriverObject, + sizeof(FLOPPY_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_DISK, + FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + goto interruptcleanup; + } + DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + DeviceExtension->DriveSelect = 0; + DeviceExtension->Controller = ControllerObject; + DeviceExtension->MediaType = ~0; + ControllerExtension->MotorOn = ~0; + // set up DPC + ControllerExtension->Device = DeviceObject; + KeInitializeDpc( &ControllerExtension->MotorSpinupDpc, + FloppyMotorSpinupDpc, + ControllerObject ); + KeInitializeDpc( &ControllerExtension->MotorSpindownDpc, + FloppyMotorSpindownDpc, + ControllerObject ); + KeInitializeTimer( &ControllerExtension->SpinupTimer ); + IoInitializeDpcRequest( DeviceObject, FloppyDpc ); + // reset controller and wait for interrupt + DPRINT( "Controller Off\n" ); + FloppyWriteDOR( ControllerExtension->PortBase, 0 ); + // let controller reset for at least FLOPPY_RESET_TIME + KeStallExecutionProcessor( FLOPPY_RESET_TIME ); + DPRINT( "Controller On\n" ); + FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA ); + // wait for interrupt now + Timeout.QuadPart = -10000000; + Status = KeWaitForSingleObject( &ControllerExtension->Event, + Executive, + KernelMode, + FALSE, + &Timeout ); + if( Status != STATUS_WAIT_0 ) + { + DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status ); + goto devicecleanup; + } + // set for high speed mode + // FloppyWriteCCNTL( ControllerExtension->PortBase, FLOPPY_CCNTL_1MBIT ); + + // ok, so we have an FDC, now check for drives + // aparently the sense drive status command does not work on any FDC I can find + // so instead we will just have to assume a 1.44 meg 3.5 inch floppy. At some + // point we should get the bios disk parameters passed in to the kernel at boot + // and stored in the HARDWARE registry key for us to pick up here. + + // turn on motor, wait for spinup time, and recalibrate the drive + FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DRIVE0_ON ); + Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME; + KeDelayExecutionThread( KernelMode, FALSE, &Timeout ); + DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) ); + FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL ); + DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) ); + KeStallExecutionProcessor( 10000 ); + FloppyWriteDATA( ControllerExtension->PortBase, 0 ); // drive select + Timeout.QuadPart = FLOPPY_RECAL_TIMEOUT; + Status = KeWaitForSingleObject( &ControllerExtension->Event, + Executive, + KernelMode, + FALSE, + &Timeout ); + if( Status != STATUS_WAIT_0 ) + { + DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status ); + goto devicecleanup; + } + if( ControllerExtension->St0 != FLOPPY_ST0_SEEKGD ) + { + DbgPrint( "Floppy: error recalibrating drive, ST0: %2x\n", (DWORD)ControllerExtension->St0 ); + goto interruptcleanup; + } + DeviceExtension->Cyl = 0; + // drive is good, and it is now on track 0, turn off the motor + FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA ); + /* Initialize the device */ + DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; + DeviceObject->AlignmentRequirement = FILE_512_BYTE_ALIGNMENT; + // change state machine, no interrupt expected + ControllerExtension->IsrState = FloppyIsrUnexpected; + Config = IoGetConfigurationInformation(); + Config->FloppyCount++; + // call IoAllocateAdapterChannel, and wait for execution routine to be given the channel + CHECKPOINT; + Status = IoAllocateAdapterChannel( ControllerExtension->AdapterObject, + DeviceObject, + 0x3000/PAGE_SIZE, // max track size is 12k + FloppyAdapterControl, + ControllerExtension ); + if( !NT_SUCCESS( Status ) ) + { + DPRINT1( "Error: IoAllocateAdapterChannel returned %x\n", Status ); + goto interruptcleanup; + } + CHECKPOINT; + Status = KeWaitForSingleObject( &ControllerExtension->Event, + Executive, + KernelMode, + FALSE, + &Timeout ); + CHECKPOINT; + if( Status != STATUS_WAIT_0 ) + { + DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status ); + goto interruptcleanup; + } + // Ok, we own the adapter object, from now on we can just IoMapTransfer, and not + // bother releasing the adapter ever. + + DPRINT( "Floppy drive initialized\n" ); + return TRUE; + + devicecleanup: + IoDeleteDevice( DeviceObject ); + interruptcleanup: + IoDisconnectInterrupt(ControllerExtension->Interrupt); + controllercleanup: + // turn off controller + FloppyWriteDOR( ControllerExtension->PortBase, 0 ); + IoDeleteController(ControllerObject); + for(;;); + return FALSE; +} + +IO_ALLOCATION_ACTION STDCALL +FloppyExecuteSpindown(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterbase, + PVOID Context) +{ + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension= (PFLOPPY_CONTROLLER_EXTENSION)Context; + + // turn off motor, and return + DPRINT( "Spinning down motor\n" ); + ControllerExtension->MotorOn = ~0; + FloppyWriteDOR( ControllerExtension->PortBase, + FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA ); + return DeallocateObject; +} + +IO_ALLOCATION_ACTION STDCALL +FloppyExecuteReadWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterbase, + PVOID Context) +{ + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension; + LARGE_INTEGER Timeout; + BOOLEAN WriteToDevice; + DWORD Cyl, Sector, Head; + PIO_STACK_LOCATION Stk; + DWORD Length; + + ControllerExtension->Irp = Irp = (PIRP)Context; + Stk = IoGetCurrentIrpStackLocation( Irp ); + ControllerExtension->Device = DeviceObject; + Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME; + DPRINT( "FloppyExecuteReadWrite()\n" ); + CHECKPOINT; + WriteToDevice = Stk->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE; + // verify drive is spun up and selected + if( ControllerExtension->MotorOn != DeviceExtension->DriveSelect ) + { + // turn on and select drive, and allow it to spin up + // FloppyMotorSpinupDpc will restart this operation once motor is spun up + DPRINT( "Motor not on, turning it on now\n" ); + FloppyWriteDOR( ControllerExtension->PortBase, + DeviceExtension->DriveSelect ? FLOPPY_DRIVE1_ON : FLOPPY_DRIVE0_ON ); + // cancel possible spindown timer first + KeCancelTimer( &ControllerExtension->SpinupTimer ); + KeSetTimerEx( &ControllerExtension->SpinupTimer, + Timeout, + 0, + &ControllerExtension->MotorSpinupDpc ); + return KeepObject; + } + else { + Timeout.QuadPart = FLOPPY_MOTOR_SPINDOWN_TIME; + // motor is already spinning, so reset the spindown timer + KeCancelTimer( &ControllerExtension->SpinupTimer ); + KeSetTimer( &ControllerExtension->SpinupTimer, + Timeout, + &ControllerExtension->MotorSpindownDpc ); + } + // verify media content + if( FloppyReadDIR( ControllerExtension->PortBase ) & FLOPPY_DI_DSKCHNG ) + { + // No disk is in the drive + DPRINT( "No disk is in the drive\n" ); + Irp->IoStatus.Status = STATUS_NO_MEDIA; + Irp->IoStatus.Information = 0; + IoCompleteRequest( Irp, 0 ); + return DeallocateObject; + } + if( DeviceExtension->MediaType == ~0 ) + { + // media is in disk, but we have not yet detected what kind it is, + // so detect it now + // First, we need to recalibrate the drive though + ControllerExtension->IsrState = FloppyIsrRecal; + DPRINT( "Recalibrating drive\n" ); + KeStallExecutionProcessor( 1000 ); + FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL ); + KeStallExecutionProcessor( 1000 ); + FloppyWriteDATA( ControllerExtension->PortBase, DeviceExtension->DriveSelect ); + return KeepObject; + } + // looks like we have media in the drive.... do the read + // first, calculate geometry for read + Sector = Stk->Parameters.Read.ByteOffset.u.LowPart / MediaTypes[DeviceExtension->MediaType].BytesPerSector; + // absolute sector right now + Cyl = Sector / MediaTypes[DeviceExtension->MediaType].SectorsPerTrack; + DPRINT( "Sector = %x, Offset = %x, Cyl = %x, Heads = %x MediaType = %x\n", Sector, Stk->Parameters.Read.ByteOffset.u.LowPart, (DWORD)Cyl, (DWORD)MediaTypes[DeviceExtension->MediaType].Heads, (DWORD)DeviceExtension->MediaType ); + Head = Cyl % MediaTypes[DeviceExtension->MediaType].Heads; + DPRINT( "Head = %2x\n", Head ); + // convert absolute cyl to relative + Cyl /= MediaTypes[DeviceExtension->MediaType].Heads; + // convert absolute sector to relative + Sector %= MediaTypes[DeviceExtension->MediaType].SectorsPerTrack; + Sector++; // track relative sector numbers are 1 based, not 0 based + DPRINT( "Cyl = %2x, Head = %2x, Sector = %2x\n", Cyl, Head, Sector ); + + // seek if we need to seek + if( DeviceExtension->Cyl != Cyl ) + { + DPRINT( "Seeking...\n" ); + ControllerExtension->IsrState = FloppyIsrDetect; + ControllerExtension->DpcState = FloppySeekDpc; + FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SEEK ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, DeviceExtension->DriveSelect ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Cyl ); + return KeepObject; + } + //set up DMA and issue read command + Length = MediaTypes[DeviceExtension->MediaType].SectorsPerTrack - Sector + 1; + // number of sectors untill end of track + Length *= 512; // convert to bytes + if( Length > Stk->Parameters.Read.Length ) + Length = Stk->Parameters.Read.Length; + DPRINT( "Sector: %d, Length: %d\n", Sector, Length ); + ControllerExtension->TransferLength = Length; + IoMapTransfer( ControllerExtension->AdapterObject, + Irp->MdlAddress, + ControllerExtension->MapRegisterBase, + Irp->Tail.Overlay.DriverContext[0], // current va + &Length, + WriteToDevice ); + ControllerExtension->IsrState = FloppyIsrReadWrite; + ControllerExtension->DpcState = FloppyDpcReadWrite; + CHECKPOINT; + FloppyWriteDATA( ControllerExtension->PortBase, WriteToDevice ? FLOPPY_CMD_WRITE : FLOPPY_CMD_READ ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, ( Head << 2 ) | DeviceExtension->DriveSelect ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Cyl ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Head ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Sector ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorSizeCode ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorsPerTrack ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, 0 ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, 0xFF ); + CHECKPOINT; + // eventually, the FDC will interrupt and we will read results then + return KeepObject; +} + +NTSTATUS STDCALL +FloppyDispatchOpenClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("FloppyDispatchOpenClose\n"); + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension; + PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( Irp ); + KIRQL oldlvl; + + if( Stk->Parameters.Read.ByteOffset.u.HighPart ) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + IoCompleteRequest( Irp, 1 ); + return STATUS_INVALID_PARAMETER; + } + // store currentva in drivercontext + Irp->Tail.Overlay.DriverContext[0] = MmGetMdlVirtualAddress( Irp->MdlAddress ); + DPRINT( "FloppyDispatchReadWrite: offset = %x, length = %x, va = %x\n", + Stk->Parameters.Read.ByteOffset.u.LowPart, + Stk->Parameters.Read.Length, + Irp->Tail.Overlay.DriverContext[0] ); + // Queue IRP + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Stk->Parameters.Read.Length; + IoMarkIrpPending( Irp ); + KeRaiseIrql( DISPATCH_LEVEL, &oldlvl ); + IoAllocateController( ((PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Controller, + DeviceObject, + FloppyExecuteReadWrite, + Irp ); + KeLowerIrql( oldlvl ); + DPRINT( "oldlvl = %x\n", oldlvl ); + return STATUS_PENDING; +} + +IO_ALLOCATION_ACTION STDCALL +FloppyAdapterControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterBase, + PVOID Context) +{ + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Context; + + // just set the event, and return KeepObject + CHECKPOINT; + ControllerExtension->MapRegisterBase = MapRegisterBase; + KeSetEvent( &ControllerExtension->Event, 0, FALSE ); + return KeepObject; +} + +NTSTATUS STDCALL +FloppyDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + ULONG ControlCode, InputLength, OutputLength; + NTSTATUS Status; + + DPRINT("FloppyDispatchDeviceControl\n"); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + switch (ControlCode) + { + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + if (OutputLength < sizeof(DISK_GEOMETRY)) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PDISK_GEOMETRY Geometry = Irp->AssociatedIrp.SystemBuffer; + // FIXME: read the first sector of the diskette + Geometry->MediaType = F3_1Pt44_512; + Geometry->Cylinders.QuadPart = 80; + Geometry->TracksPerCylinder = 2 * 18; + Geometry->SectorsPerTrack = 18; + Geometry->BytesPerSector = 512; + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); + } + break; + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + return Status; +} + +/* ModuleEntry + * + * DESCRIPTION: + * This function initializes the driver, locates and claims + * hardware resources, and creates various NT objects needed + * to process I/O requests. + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * IN PDRIVER_OBJECT DriverObject System allocated Driver Object + * for this driver + * IN PUNICODE_STRING RegistryPath Name of registry driver service + * key + * + * RETURNS: + * NTSTATUS + */ +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT("Floppy driver\n"); + + /* Export other driver entry points... */ + DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = FloppyDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = + FloppyDispatchDeviceControl; + + /* Try to detect controller and abort if it fails */ + if (!FloppyCreateController(DriverObject, + &ControllerParameters[0], + 0)) + { + DPRINT("Could not find floppy controller\n"); + return STATUS_NO_SUCH_DEVICE; + } + + return STATUS_SUCCESS; +} + +/* EOF */ + diff --git a/drivers/dd/floppy/floppy.h b/drivers/dd/floppy/floppy.h new file mode 100644 index 0000000..4568c47 --- /dev/null +++ b/drivers/dd/floppy/floppy.h @@ -0,0 +1,260 @@ +// +// Floppy register definitions +// + +#define FLOPPY_REG_DOR 0x0002 +#define FLOPPY_DOR_ENABLE 0x04 +#define FLOPPY_DOR_DMA 0x08 +#define FLOPPY_DOR_MOTOR0 0x10 +#define FLOPPY_DOR_MOTOR1 0x20 +#define FLOPPY_DRIVE0_ON ( FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA | FLOPPY_DOR_MOTOR0 ) +#define FLOPPY_DRIVE1_ON ( FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA | FLOPPY_DOR_MOTOR1 | 1 ) +#define FLOPPY_REG_MSTAT 0x0004 +#define FLOPPY_MS_DRV0BUSY 0x01 +#define FLOPPY_MS_DRV1BUSY 0x02 +#define FLOPPY_MS_DRV2BUSY 0x04 +#define FLOPPY_MS_DRV3BUSY 0x08 +#define FLOPPY_MS_FDCBUSY 0x10 +#define FLOPPY_MS_DMAMODE 0x20 +#define FLOPPY_MS_DATADIR 0x40 +#define FLOPPY_MS_RDYMASK 0xF0 +#define FLOPPY_MS_DATARDYW 0x80 +#define FLOPPY_MS_DATARDYR 0xC0 +#define FLOPPY_REG_DATA 0x0005 +#define FLOPPY_REG_DIR 0x0007 /* READ ONLY */ +#define FLOPPY_DI_DSKCHNG 0x80 +#define FLOPPY_REG_CCNTL 0x0007 /* WRITE ONLY */ +#define FLOPPY_CCNTL_1MBIT 0x03 + +#define FLOPPY_CMD_RD_TRK 0x02 +#define FLOPPY_CMD_SPEC_CHARS 0x03 +#define FLOPPY_CSC_SRT_SHIFT 4 +#define FLOPPY_CSC_HUT_MASK 0x0f +#define FLOPPY_CSC_HLT_SHIFT 1 +#define FLOPPY_CSC_NON_DMA 0x01 +#define FLOPPY_CMD_SNS_DRV 0x04 +#define FLOPPY_CMD_WRT_DATA 0x05 +#define FLOPPY_CMD_RD_DATA 0x06 +#define FLOPPY_CMD_RECAL 0x07 +#define FLOPPY_CMD_SNS_INTR 0x08 +#define FLOPPY_ST0_SEEKGD 0x20 +#define FLOPPY_ST0_GDMASK 0xd8 +#define FLOPPY_CMD_WRT_DEL 0x09 +#define FLOPPY_CMD_RD_ID 0x0a +#define FLOPPY_CMD_RD_DEL 0x0c +#define FLOPPY_CMD_FMT_TRK 0x0d +#define FLOPPY_CMD_DUMP_FDC 0x0e +#define FLOPPY_CMD_SEEK 0x0f +#define FLOPPY_CMD_VERSION 0x10 +#define FLOPPY_CMD_SCN_EQ 0x11 +#define FLOPPY_CMD_PPND_RW 0x12 +#define FLOPPY_CMD_CFG_FIFO 0x13 +#define FLOPPY_CMD_LCK_FIFO 0x14 +#define FLOPPY_CMD_PARTID 0x18 +#define FLOPPY_CMD_SCN_LE 0x19 +#define FLOPPY_CMD_SCN_GE 0x1d +#define FLOPPY_CMD_CFG_PWR 0x27 +#define FLOPPY_CMD_SAVE_FDC 0x2e +#define FLOPPY_CMD_FMT_ISO 0x33 +#define FLOPPY_CMD_DMA_READ 0x46 +#define FLOPPY_CMD_DMA_WRT 0x4a +#define FLOPPY_CMD_REST_FDC 0x4e +#define FLOPPY_CMD_DRV_SPEC 0x8e +#define FLOPPY_CMD_RSEEK_OUT 0x8f +#define FLOPPY_CMD_ULK_FIFO 0x94 +#define FLOPPY_CMD_RSEEK_IN 0xcf +#define FLOPPY_CMD_FMT_WRT 0xef + +// Command Code modifiers +#define FLOPPY_C0M_SK 0x20 +#define FLOPPY_C0M_MFM 0x40 +#define FLOPPY_C0M_MT 0x80 +#define FLOPPY_C1M_DRVMASK 0x03 +#define FLOPPY_C1M_HEAD1 0x04 + +// Status code values and masks +#define FLOPPY_ST0_INVALID 0x80 + +// useful command defines +#define FLOPPY_CMD_READ (FLOPPY_CMD_RD_DATA | FLOPPY_C0M_SK | FLOPPY_C0M_MFM | FLOPPY_C0M_MT) +#define FLOPPY_CMD_WRITE (FLOPPY_CMD_WRT_DATA | FLOPPY_C0M_MFM | FLOPPY_C0M_MT) +#define FLOPPY_CMD_FORMAT (FLOPPY_CMD_FMT_TRK | FLOPPY_C0M_MFM) + +// +// HAL floppy register access commands +// +#define FloppyWriteDOR(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DOR, (V))) +#define FloppyReadMSTAT(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_MSTAT)) +#define FloppyReadDATA(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DATA)) +#define FloppyWriteDATA(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DATA, (V))) +#define FloppyReadDIR(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DIR)) +#define FloppyWriteCCNTL(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_CCNTL, (V))) + +typedef struct _FLOPPY_ERROR_THRESHOLDS +{ + /* number of errors to be reached before aborting */ + unsigned int Abort; + /* maximal number of errors permitted to read an entire track at once */ + unsigned int ReadTrack; + /* maximal number of errors before a reset is tried */ + unsigned int Reset; + /* maximal number of errors before a recalibrate is tried */ + unsigned int Recal; + /* + * Threshold for reporting FDC errors to the console. + * Setting this to zero may flood your screen when using + * ultra cheap floppies ;-) + */ + unsigned int Reporting; +} FLOPPY_ERROR_THRESHOLDS; + +typedef struct _FLOPPY_MEDIA_TYPE +{ + BYTE SectorSizeCode; + BYTE MaximumTrack; + BYTE Heads; + DWORD SectorsPerTrack; + ULONG BytesPerSector; +} FLOPPY_MEDIA_TYPE; + +extern const FLOPPY_MEDIA_TYPE MediaTypes[]; + +#define FDP_DEBUG 0x02 +#define FDP_SILENT_DCL_CLEAR 0x04 +#define FDP_MSG 0x10 +#define FDP_BROKEN_DCL 0x20 +#define FDP_INVERTED_DCL 0x80 + +// time to hold reset line low +#define FLOPPY_RESET_TIME 50000 +#define FLOPPY_MOTOR_SPINUP_TIME -15000000 +#define FLOPPY_MOTOR_SPINDOWN_TIME -50000000 +#define FLOPPY_RECAL_TIMEOUT -30000000 + +typedef BOOLEAN (*FloppyIsrStateRoutine)( PCONTROLLER_OBJECT Controller ); +typedef PIO_DPC_ROUTINE FloppyDpcStateRoutine; + +typedef struct _FLOPPY_DEVICE_EXTENSION +{ + PCONTROLLER_OBJECT Controller; + CHAR DriveSelect; + CHAR Cyl; // current cylinder + ULONG MediaType; // Media type index +} FLOPPY_DEVICE_EXTENSION, *PFLOPPY_DEVICE_EXTENSION; + +typedef struct _FLOPPY_CONTROLLER_EXTENSION +{ + PKINTERRUPT Interrupt; + KSPIN_LOCK SpinLock; + ULONG Number; + ULONG PortBase; + ULONG Vector; + KEVENT Event; // Event set by ISR/DPC to wake DeviceEntry + PDEVICE_OBJECT Device; // Pointer to the primary device on this controller + PIRP Irp; // Current IRP + CHAR St0; // Status registers + CHAR St1; + CHAR St2; + CHAR SectorSizeCode; + FloppyIsrStateRoutine IsrState; // pointer to state routine handler for ISR + FloppyDpcStateRoutine DpcState; // pointer to state routine handler for DPC + CHAR MotorOn; // drive select for drive with motor on + KDPC MotorSpinupDpc; // DPC for motor spin up time + KTIMER SpinupTimer; // Timer for motor spin up time + KDPC MotorSpindownDpc; // DPC for motor spin down + PADAPTER_OBJECT AdapterObject; // Adapter object for dma + PVOID MapRegisterBase; + DWORD TransferLength; // Length of the transfer +} FLOPPY_CONTROLLER_EXTENSION, *PFLOPPY_CONTROLLER_EXTENSION; + +typedef struct _FLOPPY_CONTROLLER_PARAMETERS +{ + ULONG PortBase; + ULONG Vector; + ULONG IrqL; + ULONG DmaChannel; + ULONG SynchronizeIrqL; + KINTERRUPT_MODE InterruptMode; + KAFFINITY Affinity; +} FLOPPY_CONTROLLER_PARAMETERS, *PFLOPPY_CONTROLLER_PARAMETERS; + +#define FLOPPY_MAX_CONTROLLERS 1 + +VOID STDCALL +FloppyDpcDetectMedia(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); +VOID STDCALL +FloppyDpcFailIrp(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +IO_ALLOCATION_ACTION STDCALL +FloppyExecuteReadWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterbase, + PVOID Context); + +IO_ALLOCATION_ACTION STDCALL +FloppyExecuteSpindown(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterbase, + PVOID Context); + +VOID STDCALL +FloppyMotorSpinupDpc(PKDPC Dpc, + PVOID Context, + PVOID Arg1, + PVOID Arg2); + +VOID STDCALL +FloppySeekDpc(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +VOID STDCALL +FloppyMotorSpindownDpc(PKDPC Dpc, + PVOID Context, + PVOID Arg1, + PVOID Arg2); + +VOID STDCALL +FloppyDpcDetect(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context ); + +VOID STDCALL +FloppyDpcReadWrite(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +VOID STDCALL +FloppyDpc(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +BOOLEAN FloppyIsrDetect( PCONTROLLER_OBJECT Controller ); + +BOOLEAN FloppyIsrReadWrite( PCONTROLLER_OBJECT Controller ); + +BOOLEAN FloppyIsrUnexpected( PCONTROLLER_OBJECT Controller ); + +BOOLEAN FloppyIsrDetectMedia( PCONTROLLER_OBJECT Controller ); + +BOOLEAN FloppyIsrRecal( PCONTROLLER_OBJECT Controller ); + +BOOLEAN STDCALL +FloppyIsr(PKINTERRUPT Interrupt, + PVOID ServiceContext); + +IO_ALLOCATION_ACTION STDCALL +FloppyAdapterControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterBase, + PVOID Context); diff --git a/drivers/dd/floppy/floppy.rc b/drivers/dd/floppy/floppy.rc new file mode 100644 index 0000000..61da49f --- /dev/null +++ b/drivers/dd/floppy/floppy.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Floppy Device Driver\0" + VALUE "FileVersion", "0.1.4\0" + VALUE "InternalName", "floppy\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "floppy.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/floppy/isr.c b/drivers/dd/floppy/isr.c new file mode 100644 index 0000000..615f97b --- /dev/null +++ b/drivers/dd/floppy/isr.c @@ -0,0 +1,182 @@ +/************************************************************************ + * Interrupt handlers for floppy disk driver, reactos project, created * + * by Phillip Susi on 2/25/2001. This software is publised under the * + * GNU General public license. See the README file for more details * + ***********************************************************************/ + +#include +#define NDEBUG +#include +#include "floppy.h" + + +// ISR state machine function called when expecting an interrupt due to reset +// During reset, there is nothing ready to read, just issue sense interrupt status + +BOOLEAN FloppyIsrDetect( PCONTROLLER_OBJECT Controller ) +{ + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension; + // Issue read interrupt status, and store the results + FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SNS_INTR ); + KeStallExecutionProcessor( 100 ); + ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 100 ); + DeviceExtension->Cyl = FloppyReadDATA( ControllerExtension->PortBase ); + // now queue DPC to set the event + IoRequestDpc( ControllerExtension->Device, + 0, + Controller ); + return TRUE; +} + +// ISR state machine handler for unexpected interrupt +BOOLEAN FloppyIsrUnexpected( PCONTROLLER_OBJECT Controller ) +{ + DPRINT( "Unexpected interrupt!\n" ); + return FALSE; +} + +BOOLEAN FloppyIsrDetectMedia( PCONTROLLER_OBJECT Controller ) +{ + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + BYTE SectorSize; + // media detect in progress, read ID command already issued + // first, read result registers + KeStallExecutionProcessor( 1000 ); + ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 1000 ); + ControllerExtension->St1 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 1000 ); + ControllerExtension->St2 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 1000 ); + FloppyReadDATA( ControllerExtension->PortBase ); // ignore cyl + KeStallExecutionProcessor( 1000 ); + FloppyReadDATA( ControllerExtension->PortBase ); // ignore head + KeStallExecutionProcessor( 1000 ); + FloppyReadDATA( ControllerExtension->PortBase ); // ignore sector + KeStallExecutionProcessor( 1000 ); + SectorSize = FloppyReadDATA( ControllerExtension->PortBase ); + DPRINT( "Sector Size Code: %2x\n", SectorSize ); + DPRINT( "St0 = %2x, St1 = %2x, St2 = %2x\n", ControllerExtension->St0, ControllerExtension->St1, ControllerExtension->St2 ); + DPRINT( "ControllerExtension->Device = %x, ControllerExtension->Irp = %x\n", ControllerExtension->Device, ControllerExtension->Irp ); + // queue DPC + ControllerExtension->DpcState = FloppyDpcDetectMedia; + IoRequestDpc( ControllerExtension->Device, + ControllerExtension->Irp, + Controller ); + return TRUE; +} + +BOOLEAN FloppyIsrRecal( PCONTROLLER_OBJECT Controller ) +{ + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + // issue sense interrupt status, and read St0 and cyl + + FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SNS_INTR ); + KeStallExecutionProcessor( 1000 ); + ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 1000 ); + FloppyReadDATA( ControllerExtension->PortBase ); // ignore cyl number + DPRINT( "Recal St0: %2x\n", ControllerExtension->St0 ); + + // If recalibrate worked, issue read ID for each media type untill one works + if( ControllerExtension->St0 != FLOPPY_ST0_SEEKGD ) + { + DPRINT( "Recalibrate failed, ST0 = %2x\n", ControllerExtension->St0 ); + // queue DPC to fail IRP + ControllerExtension->DpcState = FloppyDpcFailIrp; + IoRequestDpc( ControllerExtension->Device, + ControllerExtension->Irp, + Controller ); + } + else { + // issue first read id, FloppyIsrDetectMedia will handle + DPRINT( "Recalibrate worked, issuing read ID mark command\n" ); + ControllerExtension->IsrState = FloppyIsrDetectMedia; + KeStallExecutionProcessor( 1000 ); + FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RD_ID | FLOPPY_C0M_MFM ); + KeStallExecutionProcessor( 1000 ); + FloppyWriteDATA( ControllerExtension->PortBase, ((PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension)->DriveSelect ); + } + + return TRUE; +} + +BOOLEAN FloppyIsrReadWrite( PCONTROLLER_OBJECT Controller ) +{ + // read result registers from read or write command, and queue dpc to start next operation + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + BYTE Cyl, Head, Sector; + PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension; + PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( ControllerExtension->Irp ); + BOOLEAN WriteToDevice = Stk->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE; + + + ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 100 ); + ControllerExtension->St1 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 100 ); + ControllerExtension->St2 = FloppyReadDATA( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 100 ); + Cyl = FloppyReadDATA( ControllerExtension->PortBase ); // cyl + KeStallExecutionProcessor( 100 ); + Head = FloppyReadDATA( ControllerExtension->PortBase ); // head + KeStallExecutionProcessor( 100 ); + Sector = FloppyReadDATA( ControllerExtension->PortBase ); // sector + KeStallExecutionProcessor( 100 ); + ControllerExtension->SectorSizeCode = FloppyReadDATA( ControllerExtension->PortBase ); + // reprogam for next sector if we are not done reading track + /* if( ( ControllerExtension->TransferLength -= ( 128 << ControllerExtension->SectorSizeCode ) ) ) + { + DPRINT1( "ISR reprogramming for next sector: %d\n", Sector ); + Sector++; + FloppyWriteDATA( ControllerExtension->PortBase, WriteToDevice ? FLOPPY_CMD_WRITE : FLOPPY_CMD_READ ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, ( Head << 2 ) | DeviceExtension->DriveSelect ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Cyl ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Head ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, Sector ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, ControllerExtension->SectorSizeCode ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorsPerTrack ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, 0 ); + KeStallExecutionProcessor( 100 ); + FloppyWriteDATA( ControllerExtension->PortBase, 0xFF ); + } + else */IoRequestDpc( ControllerExtension->Device, + ControllerExtension->Irp, + Controller ); + return TRUE; +} + +// actual ISR, passes controll to handler for current state in state machine + +BOOLEAN STDCALL +FloppyIsr(PKINTERRUPT Interrupt, + PVOID ServiceContext) +{ + PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)ServiceContext; + PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension; + BYTE Byte; + + // need to make sure interrupt is for us, and add some delay for the damn FDC + // without the delay, even though the thing has interrupted, it's still not ready + // for us to read the data register. + KeStallExecutionProcessor( 100 ); + Byte = FloppyReadMSTAT( ControllerExtension->PortBase ); + KeStallExecutionProcessor( 100 ); + if( Byte == 0 ) + { + DPRINT( "Ignoring interrupt, MSTAT = 0\n" ); + return TRUE; + } + return ControllerExtension->IsrState( Controller ); +} + + diff --git a/drivers/dd/ide/.cvsignore b/drivers/dd/ide/.cvsignore new file mode 100644 index 0000000..dc98dbc --- /dev/null +++ b/drivers/dd/ide/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +ide.coff +ide.sys.unstripped diff --git a/drivers/dd/ide/ide.c b/drivers/dd/ide/ide.c new file mode 100644 index 0000000..073d30d --- /dev/null +++ b/drivers/dd/ide/ide.c @@ -0,0 +1,2263 @@ +/* $Id$ + * + * IDE.C - IDE Disk driver + * written by Rex Jolliff + * with help from various documentation sources and a few peeks at + * linux and freebsd sources. + * + * This driver supports PCI controllers and up to 4 ISA controllers + * with up to 2 drives each. + * The device names are assigned as follows: + * \Devices\HarddiskX\Partition0 + * for the raw device, and + * \Devices\HarddiskX\PartitionY + * for partitions + * where: + * X is computed by counting the available drives from the following + * sequence: the controller number (0=0x1f0, 1=0x170, 2=0x1e8, + * 3=0x168) * 2 plus the drive number (0,1) + * Y is the partition number + * + * The driver exports the following function: + * + * DriverEntry() - NT device driver initialization routine + * + * And the following functions are exported implicitly: + * + * IDEStartIo() - called to start an I/O request packet + * IDEDispatchOpenClose() - Called to open/close the device. a NOOP + * IDEDispatchReadWrite() - Called to read/write the device. + * IDEDispatchQueryInformation() - Called to get device information + * IDEDispatchSetInformation() - Called to set device information + * IDEDispatchDeviceControl() - Called to execute device control requests + * + * Modification History: + * 05/25/98 RJJ Created. + * 05/30/98 RJJ Removed IRQ handler and inserted busy waits + * just to get something working... + * 07/18/98 RJJ Made drastic changes so that the driver + * resembles a WinNT driver. + * 08/05/98 RJJ Changed to .C extension + * 09/19/98 RJJ First release (run for cover!) + * + * Test List: + * 09/17/98 RJJ Pri/MST: 14.12X19 WDC AC31000H Test Passed + * Pri/SLV: None. + * + * + * To Do: + * FIXME: a timer should be used to watch for device timeouts and errors + * FIXME: errors should be retried + * FIXME: a drive reset/recalibrate should be attempted if errors occur + * FIXME: Use DMA for transfers if drives support it + * FIXME: should we support unloading of this driver??? + * FIXME: the device information should come from AUTODETECT (via registry) + * FIXME: really big devices need to be handled correctly + * FIXME: should get device info from the registry + * FIXME: should report hardware usage to iomgr + * FIXME: finish implementation of QueryInformation + * FIXME: finish implementation of SetInformation + * FIXME: finish implementation of DeviceControl + * FIXME: bring up to ATA-3 spec + * FIXME: add general support for ATAPI devices + * FIXME: add support for ATAPI CDROMs + * FIXME: add support for ATAPI ZIP drives/RHDs + * FIXME: add support for ATAPI tape drives + */ + +// ------------------------------------------------------------------------- + +#include + +#define NDEBUG +#include + +#include "ide.h" +#include "partitio.h" + +#define VERSION "V0.1.5" + +/* uncomment the following line to enable the secondary ide channel */ +//#define ENABLE_SECONDARY_IDE_CHANNEL + +// ------------------------------------------------------- File Static Data + + +typedef struct _IDE_CONTROLLER_PARAMETERS +{ + int CommandPortBase; + int CommandPortSpan; + int ControlPortBase; + int ControlPortSpan; + int Vector; + int IrqL; + int SynchronizeIrqL; + KINTERRUPT_MODE InterruptMode; + KAFFINITY Affinity; +} IDE_CONTROLLER_PARAMETERS, *PIDE_CONTROLLER_PARAMETERS; + +// NOTE: Do not increase max drives above 2 + +#define IDE_MAX_DRIVES 2 + +#define IDE_MAX_CONTROLLERS 2 +IDE_CONTROLLER_PARAMETERS Controllers[IDE_MAX_CONTROLLERS] = +{ + {0x01f0, 8, 0x03f6, 1, 14, 14, 15, LevelSensitive, 0xffff}, + {0x0170, 8, 0x0376, 1, 15, 15, 15, LevelSensitive, 0xffff} +/* {0x01E8, 8, 0x03ee, 1, 11, 11, 15, LevelSensitive, 0xffff}, + {0x0168, 8, 0x036e, 1, 10, 10, 15, LevelSensitive, 0xffff}*/ +}; + +static BOOLEAN IDEInitialized = FALSE; + +// ----------------------------------------------- Discardable Declarations + +#ifdef ALLOC_PRAGMA + +// make the initialization routines discardable, so that they +// don't waste space + +#pragma alloc_text(init, DriverEntry) +#pragma alloc_text(init, IDECreateController) +#pragma alloc_text(init, IDECreateDevices) +#pragma alloc_text(init, IDECreateDevice) +#pragma alloc_text(init, IDEPolledRead) + +// make the PASSIVE_LEVEL routines pageable, so that they don't +// waste nonpaged memory + +#pragma alloc_text(page, IDEShutdown) +#pragma alloc_text(page, IDEDispatchOpenClose) +#pragma alloc_text(page, IDEDispatchRead) +#pragma alloc_text(page, IDEDispatchWrite) + +#endif /* ALLOC_PRAGMA */ + +// ---------------------------------------------------- Forward Declarations + +static NTSTATUS +IdeFindControllers(IN PDRIVER_OBJECT DriverObject); + +static NTSTATUS +IdeCreateController(IN PDRIVER_OBJECT DriverObject, + IN PIDE_CONTROLLER_PARAMETERS ControllerParams, + IN int ControllerIdx); + +static BOOLEAN IDEResetController(IN WORD CommandPort, IN WORD ControlPort); +static BOOLEAN IDECreateDevices(IN PDRIVER_OBJECT DriverObject, + IN PCONTROLLER_OBJECT ControllerObject, + IN PIDE_CONTROLLER_EXTENSION ControllerExtension, + IN int DriveIdx, + IN int HarddiskIdx); +static BOOLEAN IDEGetDriveIdentification(IN int CommandPort, + IN int DriveNum, + OUT PIDE_DRIVE_IDENTIFY DrvParms); +static NTSTATUS IDECreateDiskDevice(IN PDRIVER_OBJECT DriverObject, + OUT PDEVICE_OBJECT *DeviceObject, + IN PCONTROLLER_OBJECT ControllerObject, + IN int UnitNumber, + IN ULONG DiskNumber, + IN PIDE_DRIVE_IDENTIFY DrvParms, + IN ULONG SectorCount); +static NTSTATUS IDECreatePartitionDevice(IN PDRIVER_OBJECT DriverObject, + OUT PDEVICE_OBJECT *DeviceObject, + IN PCONTROLLER_OBJECT ControllerObject, + IN PVOID DiskDeviceExtension, + IN int UnitNumber, + IN ULONG DiskNumber, + IN PIDE_DRIVE_IDENTIFY DrvParms, + IN PPARTITION_INFORMATION PartitionInfo); +static int IDEPolledRead(IN WORD Address, + IN BYTE PreComp, + IN BYTE SectorCnt, + IN BYTE SectorNum, + IN BYTE CylinderLow, + IN BYTE CylinderHigh, + IN BYTE DrvHead, + IN BYTE Command, + OUT BYTE *Buffer); +static NTSTATUS STDCALL IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp); +static NTSTATUS STDCALL IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, IN PIRP Irp); +static NTSTATUS STDCALL IDEDispatchDeviceControl(IN PDEVICE_OBJECT pDO, IN PIRP Irp); +static VOID STDCALL IDEStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +static IO_ALLOCATION_ACTION STDCALL +IDEAllocateController(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Ccontext); +static BOOLEAN STDCALL +IDEStartController(IN OUT PVOID Context); +VOID IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension); +static BOOLEAN STDCALL IDEIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); +static VOID IDEDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext); +static VOID IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension); +static VOID STDCALL IDEIoTimer(PDEVICE_OBJECT DeviceObject, PVOID Context); + +// ---------------------------------------------------------------- Inlines + +void +IDESwapBytePairs(char *Buf, + int Cnt) +{ + char t; + int i; + + for (i = 0; i < Cnt; i += 2) + { + t = Buf[i]; + Buf[i] = Buf[i+1]; + Buf[i+1] = t; + } +} + +// ------------------------------------------------------- Public Interface + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver, locates and claims +// hardware resources, and creates various NT objects needed +// to process I/O requests. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject System allocated Driver Object +// for this driver +// IN PUNICODE_STRING RegistryPath Name of registry driver service +// key +// +// RETURNS: +// NTSTATUS + +STDCALL NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + NTSTATUS Status; + + DPRINT("IDE Driver %s\n", VERSION); + + /* Export other driver entry points... */ + DriverObject->DriverStartIo = IDEStartIo; + DriverObject->MajorFunction[IRP_MJ_CREATE] = IDEDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = IDEDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_READ] = IDEDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = IDEDispatchReadWrite; +// DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = IDEDispatchQueryInformation; +// DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = IDEDispatchSetInformation; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IDEDispatchDeviceControl; + + Status = IdeFindControllers(DriverObject); + if (NT_SUCCESS(Status)) + { + IDEInitialized = TRUE; + } + + return(Status); +} + +// ---------------------------------------------------- Discardable statics + +static NTSTATUS +IdeFindControllers(IN PDRIVER_OBJECT DriverObject) +{ + PCI_COMMON_CONFIG PciConfig; + ULONG Bus; + ULONG Slot; + ULONG Size; + ULONG i; + NTSTATUS ReturnedStatus = STATUS_NO_SUCH_DEVICE; + NTSTATUS Status; + INT ControllerIdx = 0; + PCONFIGURATION_INFORMATION ConfigInfo; + + DPRINT("IdeFindControllers() called!\n"); + + ConfigInfo = IoGetConfigurationInformation(); + + /* Search PCI busses for IDE controllers */ + for (Bus = 0; Bus < 8; Bus++) + { + for (Slot = 0; Slot < 256; Slot++) + { + Size = HalGetBusData(PCIConfiguration, + Bus, + Slot, + &PciConfig, + sizeof(PCI_COMMON_CONFIG)); + if (Size != 0) + { + if ((PciConfig.BaseClass == 0x01) && + (PciConfig.SubClass == 0x01)) + { + DPRINT("IDE controller found!\n"); + + DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n", + Bus, + Slot>>3, + Slot & 0x07, + PciConfig.VendorID, + PciConfig.DeviceID); + if ((PciConfig.HeaderType & 0x7FFFFFFF) == 0) + { + DPRINT(" IPR 0x%X ILR 0x%X\n", + PciConfig.u.type0.InterruptPin, + PciConfig.u.type0.InterruptLine); + } + + if (PciConfig.ProgIf & 0x01) + { + DPRINT("Primary channel: PCI native mode\n"); + } + else + { + DPRINT("Primary channel: Compatibility mode\n"); + if (ConfigInfo->AtDiskPrimaryAddressClaimed == FALSE) + { + Status = IdeCreateController(DriverObject, + &Controllers[0], + ControllerIdx); + if (NT_SUCCESS(Status)) + { + ControllerIdx++; + ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE; + ConfigInfo->ScsiPortCount++; + ReturnedStatus = Status; + } + } + else + { + /* + * FIXME: Switch controller to native pci mode + * if it is programmable. + */ + } + } + if (PciConfig.ProgIf & 0x02) + { + DPRINT("Primary channel: programmable\n"); + } + else + { + DPRINT("Primary channel: not programmable\n"); + } + +#ifdef ENABLE_SECONDARY_IDE_CHANNEL + if (PciConfig.ProgIf & 0x04) + { + DPRINT("Secondary channel: PCI native mode\n"); + } + else + { + DPRINT("Secondary channel: Compatibility mode\n"); + if (ConfigInfo->AtDiskSecondaryAddressClaimed == FALSE) + { + Status = IdeCreateController(DriverObject, + &Controllers[1], + ControllerIdx); + if (NT_SUCCESS(Status)) + { + ControllerIdx++; + ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE; + ConfigInfo->ScsiPortCount++; + ReturnedStatus = Status; + } + } + else + { + /* + * FIXME: Switch controller to native pci mode + * if it is programmable. + */ + } + } + if (PciConfig.ProgIf & 0x08) + { + DPRINT("Secondary channel: programmable\n"); + } + else + { + DPRINT("Secondary channel: not programmable\n"); + } + + if (PciConfig.ProgIf & 0x80) + { + DPRINT("Master IDE device: 1\n"); + } + else + { + DPRINT("Master IDE device: 0\n"); + } + + for (i = 0; i < PCI_TYPE0_ADDRESSES; i++) + { + DPRINT("BaseAddress: 0x%08X\n", PciConfig.u.type0.BaseAddresses[i]); + } +#endif + } + } + } + } + + /* Search for ISA IDE controller if no primary controller was found */ + if (ConfigInfo->AtDiskPrimaryAddressClaimed == FALSE) + { + DPRINT("Searching for primary ISA IDE controller!\n"); + + if (IDEResetController(Controllers[0].CommandPortBase, + Controllers[0].ControlPortBase)) + { + Status = IdeCreateController(DriverObject, + &Controllers[0], + 0); + if (NT_SUCCESS(Status)) + { + DPRINT(" Found primary ISA IDE controller!\n"); + ControllerIdx++; + ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE; + ConfigInfo->ScsiPortCount++; + ReturnedStatus = Status; + } + } + } + + /* Search for ISA IDE controller if no secondary controller was found */ +#ifdef ENABLE_SECONDARY_IDE_CHANNEL + if (ConfigInfo->AtDiskSecondaryAddressClaimed == FALSE) + { + DPRINT("Searching for secondary ISA IDE controller!\n"); + + if (IDEResetController(Controllers[1].CommandPortBase, + Controllers[1].ControlPortBase)) + { + Status = IdeCreateController(DriverObject, + &Controllers[1], + 1); + if (NT_SUCCESS(Status)) + { + DPRINT(" Found secondary ISA IDE controller!\n"); + ControllerIdx++; + ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE; + ConfigInfo->ScsiPortCount++; + ReturnedStatus = Status; + } + } + } +#endif + + DPRINT("IdeFindControllers() done!\n"); + + return(ReturnedStatus); +} + + +// IdeCreateController +// +// DESCRIPTION: +// Creates a controller object and a device object for each valid +// device on the controller +// +// RUN LEVEL: +// PASSIVE LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject The system created driver object +// IN PIDE_CONTROLLER_PARAMETERS The parameter block for this +// ControllerParams controller +// IN int ControllerIdx The index of this controller +// +// RETURNS: +// TRUE Devices where found on this controller +// FALSE The controller does not respond or there are no devices on it +// + +static NTSTATUS +IdeCreateController(IN PDRIVER_OBJECT DriverObject, + IN PIDE_CONTROLLER_PARAMETERS ControllerParams, + IN int ControllerIdx) +{ + BOOLEAN CreatedDevices, ThisDriveExists; + int DriveIdx; + NTSTATUS RC; + PCONTROLLER_OBJECT ControllerObject; + PIDE_CONTROLLER_EXTENSION ControllerExtension; + + ControllerObject = IoCreateController(sizeof(IDE_CONTROLLER_EXTENSION)); + if (ControllerObject == NULL) + { + DbgPrint ("Could not create controller object for controller %d\n", + ControllerIdx); + return STATUS_NO_SUCH_DEVICE; + } + + // Fill out Controller extension data + ControllerExtension = (PIDE_CONTROLLER_EXTENSION) + ControllerObject->ControllerExtension; + ControllerExtension->Number = ControllerIdx; + ControllerExtension->CommandPortBase = ControllerParams->CommandPortBase; + ControllerExtension->ControlPortBase = ControllerParams->ControlPortBase; + ControllerExtension->Vector = ControllerParams->Vector; + ControllerExtension->DMASupported = FALSE; + ControllerExtension->ControllerInterruptBug = FALSE; + ControllerExtension->OperationInProgress = FALSE; + + // Initialize the spin lock in the controller extension + KeInitializeSpinLock(&ControllerExtension->SpinLock); + + // Register an interrupt handler for this controller + RC = IoConnectInterrupt(&ControllerExtension->Interrupt, + IDEIsr, + ControllerExtension, + &ControllerExtension->SpinLock, + ControllerExtension->Vector, + ControllerParams->IrqL, + ControllerParams->SynchronizeIrqL, + ControllerParams->InterruptMode, + FALSE, + ControllerParams->Affinity, + FALSE); + if (!NT_SUCCESS(RC)) + { + DbgPrint ("Could not Connect Interrupt %d\n", + ControllerExtension->Vector); + IoDeleteController (ControllerObject); + return RC; + } + +/* TEST */ + IDEInitialized = TRUE; + + // Create device objects for each raw device (and for partitions) + CreatedDevices = FALSE; + for (DriveIdx = 0; DriveIdx < IDE_MAX_DRIVES; DriveIdx++) + { + ThisDriveExists = IDECreateDevices(DriverObject, + ControllerObject, + ControllerExtension, + DriveIdx, + ControllerIdx * 2 + DriveIdx); + if (ThisDriveExists) + { + CreatedDevices = TRUE; + } + } + + if (!CreatedDevices) + { + DbgPrint ("Did not find any devices for controller %d\n", + ControllerIdx); + IoDisconnectInterrupt (ControllerExtension->Interrupt); + IoDeleteController (ControllerObject); + } + else + { + IDEResetController(ControllerParams->CommandPortBase, + ControllerParams->ControlPortBase); + IoStartTimer(ControllerExtension->TimerDevice); + } + + return((CreatedDevices == TRUE)?STATUS_SUCCESS:STATUS_NO_SUCH_DEVICE); +} + + +// IDEResetController +// +// DESCRIPTION: +// Reset the controller and report completion status +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN WORD CommandPort The address of the command port +// IN WORD ControlPort The address of the control port +// +// RETURNS: +// + +BOOLEAN +IDEResetController(IN WORD CommandPort, + IN WORD ControlPort) +{ + int Retries; + + // Assert drive reset line + IDEWriteDriveControl(ControlPort, IDE_DC_SRST); + + // Wait for min. 25 microseconds + KeStallExecutionProcessor(IDE_RESET_PULSE_LENGTH); + + // Negate drive reset line + IDEWriteDriveControl(ControlPort, 0); + + // Wait for BUSY negation + for (Retries = 0; Retries < IDE_RESET_BUSY_TIMEOUT * 1000; Retries++) + { + if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY)) + { + break; + } + KeStallExecutionProcessor(10); + } + CHECKPOINT; + if (Retries >= IDE_RESET_BUSY_TIMEOUT * 1000) + { + return FALSE; + } + CHECKPOINT; + // return TRUE if controller came back to life. and + // the registers are initialized correctly + return IDEReadError(CommandPort) == 1; +} + + +// IDECreateDevices +// +// DESCRIPTION: +// Create the raw device and any partition devices on this drive +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject The system created driver object +// IN PCONTROLLER_OBJECT ControllerObject +// IN PIDE_CONTROLLER_EXTENSION ControllerExtension +// The IDE controller extension for +// this device +// IN int DriveIdx The index of the drive on this +// controller +// IN int HarddiskIdx The NT device number for this +// drive +// +// RETURNS: +// TRUE Drive exists and devices were created +// FALSE no devices were created for this device +// + +BOOLEAN +IDECreateDevices(IN PDRIVER_OBJECT DriverObject, + IN PCONTROLLER_OBJECT ControllerObject, + IN PIDE_CONTROLLER_EXTENSION ControllerExtension, + IN int DriveIdx, + IN int HarddiskIdx) +{ + WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; + int CommandPort; + NTSTATUS Status; + IDE_DRIVE_IDENTIFY DrvParms; + PDEVICE_OBJECT DiskDeviceObject; + PDEVICE_OBJECT PartitionDeviceObject; + PIDE_DEVICE_EXTENSION DiskDeviceExtension; + UNICODE_STRING UnicodeDeviceDirName; + OBJECT_ATTRIBUTES DeviceDirAttributes; + HANDLE Handle; + ULONG SectorCount = 0; + PDRIVE_LAYOUT_INFORMATION PartitionList = NULL; + PPARTITION_INFORMATION PartitionEntry; + ULONG i; + + /* Copy I/O port offsets for convenience */ + CommandPort = ControllerExtension->CommandPortBase; +// ControlPort = ControllerExtension->ControlPortBase; + DPRINT("probing IDE controller %d Addr %04lx Drive %d\n", + ControllerExtension->Number, + CommandPort, + DriveIdx); + + /* Get the Drive Identification Data */ + if (!IDEGetDriveIdentification(CommandPort, DriveIdx, &DrvParms)) + { + DPRINT("No ATA drive %d found on controller %d...\n", + DriveIdx, + ControllerExtension->Number); + return(FALSE); + } + + DPRINT("Found ATA drive %d on controller %d...\n", + DriveIdx, + ControllerExtension->Number); + + /* Create the harddisk device directory */ + swprintf (NameBuffer, + L"\\Device\\Harddisk%d", + HarddiskIdx); + RtlInitUnicodeString(&UnicodeDeviceDirName, + NameBuffer); + InitializeObjectAttributes(&DeviceDirAttributes, + &UnicodeDeviceDirName, + 0, + NULL, + NULL); + Status = ZwCreateDirectoryObject(&Handle, 0, &DeviceDirAttributes); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not create device dir object\n"); + return(FALSE); + } + + /* Create the disk device */ + if (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED) + { + SectorCount = + (ULONG)((DrvParms.TMSectorCountHi << 16) + DrvParms.TMSectorCountLo); + } + else + { + SectorCount = + (ULONG)(DrvParms.LogicalCyls * DrvParms.LogicalHeads * DrvParms.SectorsPerTrack); + } + DPRINT("SectorCount %lu\n", SectorCount); + + Status = IDECreateDiskDevice(DriverObject, + &DiskDeviceObject, + ControllerObject, + DriveIdx, + HarddiskIdx, + &DrvParms, + SectorCount); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IDECreateDevice call failed for raw device\n"); + return FALSE; + } + + /* Increase number of available physical disk drives */ + IoGetConfigurationInformation()->DiskCount++; + + /* + * Initialize the controller timer here + * (since it has to be tied to a device) + */ + if (DriveIdx == 0) + { + ControllerExtension->TimerState = IDETimerIdle; + ControllerExtension->TimerCount = 0; + ControllerExtension->TimerDevice = DiskDeviceObject; + IoInitializeTimer(DiskDeviceObject, + IDEIoTimer, + ControllerExtension); + } + + DPRINT("DrvParms.BytesPerSector %ld\n",DrvParms.BytesPerSector); + + /* Read partition table */ + Status = IoReadPartitionTable(DiskDeviceObject, + DrvParms.BytesPerSector, + TRUE, + &PartitionList); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoReadPartitionTable() failed\n"); + return FALSE; + } + + DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount); + for (i=0;i < PartitionList->PartitionCount; i++) + { + PartitionEntry = &PartitionList->PartitionEntry[i]; + + DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n", + i, + PartitionEntry->PartitionNumber, + PartitionEntry->BootIndicator, + PartitionEntry->PartitionType, + PartitionEntry->StartingOffset.QuadPart / DrvParms.BytesPerSector, + PartitionEntry->PartitionLength.QuadPart / DrvParms.BytesPerSector); + + /* Create device for partition */ + Status = IDECreatePartitionDevice(DriverObject, + &PartitionDeviceObject, + ControllerObject, + DiskDeviceObject->DeviceExtension, + DriveIdx, + HarddiskIdx, + &DrvParms, + PartitionEntry); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IDECreateDevice() failed\n"); + break; + } + } + + if (PartitionList != NULL) + ExFreePool(PartitionList); + + return TRUE; +} + +// IDEGetDriveIdentification +// +// DESCRIPTION: +// Get the identification block from the drive +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN int CommandPort Address of the command port +// IN int DriveNum The drive index (0,1) +// OUT PIDE_DRIVE_IDENTIFY DrvParms Address to write drive ident block +// +// RETURNS: +// TRUE The drive identification block was retrieved successfully +// + +static BOOLEAN +IDEGetDriveIdentification(IN int CommandPort, + IN int DriveNum, + OUT PIDE_DRIVE_IDENTIFY DrvParms) +{ + + /* Get the Drive Identify block from drive or die */ + if (IDEPolledRead(CommandPort, 0, 1, 0, 0, 0, (DriveNum ? IDE_DH_DRV1 : 0), + IDE_CMD_IDENT_DRV, (BYTE *)DrvParms) != 0) + { + return(FALSE); + } + + /* Report on drive parameters if debug mode */ + IDESwapBytePairs(DrvParms->SerialNumber, 20); + IDESwapBytePairs(DrvParms->FirmwareRev, 8); + IDESwapBytePairs(DrvParms->ModelNumber, 40); + DPRINT("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n", + DrvParms->ConfigBits, + DrvParms->LogicalCyls, + DrvParms->LogicalHeads, + DrvParms->SectorsPerTrack, + DrvParms->InterSectorGap, + DrvParms->InterSectorGapSize); + DPRINT("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n", + DrvParms->BytesInPLO, + DrvParms->VendorUniqueCnt, + DrvParms->SerialNumber); + DPRINT("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n", + DrvParms->ControllerType, + DrvParms->BufferSize * IDE_SECTOR_BUF_SZ, + DrvParms->ECCByteCnt, + DrvParms->FirmwareRev); + DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber); + DPRINT("RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n", + (DrvParms->RWMultImplemented) & 0xff, + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0, + (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0, + DrvParms->MinPIOTransTime, + DrvParms->MinDMATransTime); + DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n", + DrvParms->TMCylinders, + DrvParms->TMHeads, + DrvParms->TMSectorsPerTrk, + (ULONG)(DrvParms->TMCapacityLo + (DrvParms->TMCapacityHi << 16))); + DPRINT("TM:SectorCount: 0x%04x%04x = %lu\n", + DrvParms->TMSectorCountHi, + DrvParms->TMSectorCountLo, + (ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo)); + + /* + * Fix default ATA sector size. + * Attention: Default ATAPI sector size is 2048 bytes!! + */ + DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); + DrvParms->BytesPerSector = 512; + DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); + + return(TRUE); +} + + +// IDECreateDiskDevice +// +// DESCRIPTION: +// Creates the disk device object +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject The system supplied driver object +// OUT PDEVICE_OBJECT *DeviceObject The created device object +// IN PCONTROLLER_OBJECT ControllerObject The Controller for the device +// IN BOOLEAN LBASupported Does the drive support LBA addressing? +// IN BOOLEAN DMASupported Does the drive support DMA? +// IN int SectorsPerLogCyl Sectors per cylinder +// IN int SectorsPerLogTrk Sectors per track +// IN DWORD Offset First valid sector for this device +// IN DWORD Size Count of valid sectors for this device +// +// RETURNS: +// NTSTATUS +// + +NTSTATUS +IDECreateDiskDevice(IN PDRIVER_OBJECT DriverObject, + OUT PDEVICE_OBJECT *DeviceObject, + IN PCONTROLLER_OBJECT ControllerObject, + IN int UnitNumber, + IN ULONG DiskNumber, + IN PIDE_DRIVE_IDENTIFY DrvParms, + IN ULONG SectorCount) +{ + WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; + UNICODE_STRING DeviceName; + NTSTATUS RC; + PIDE_DEVICE_EXTENSION DeviceExtension; + + /* Create a unicode device name */ + swprintf(NameBuffer, + L"\\Device\\Harddisk%d\\Partition0", + DiskNumber); + RtlInitUnicodeString(&DeviceName, + NameBuffer); + + /* Create the device */ + RC = IoCreateDevice(DriverObject, + sizeof(IDE_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_DISK, + 0, + TRUE, + DeviceObject); + if (!NT_SUCCESS(RC)) + { + DbgPrint("IoCreateDevice call failed\n"); + return(RC); + } + + /* Set the buffering strategy here... */ + (*DeviceObject)->Flags |= DO_DIRECT_IO; + (*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT; + + /* Fill out Device extension data */ + DeviceExtension = (PIDE_DEVICE_EXTENSION) (*DeviceObject)->DeviceExtension; + DeviceExtension->DeviceObject = (*DeviceObject); + DeviceExtension->ControllerObject = ControllerObject; + DeviceExtension->DiskDeviceExtension = DeviceExtension; + DeviceExtension->UnitNumber = UnitNumber; + DeviceExtension->LBASupported = + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0; + DeviceExtension->DMASupported = + (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0; + DeviceExtension->BytesPerSector = DrvParms->BytesPerSector; + DeviceExtension->SectorsPerLogCyl = + DrvParms->LogicalHeads * DrvParms->SectorsPerTrack; + DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack; + DeviceExtension->LogicalHeads = DrvParms->LogicalHeads; + DeviceExtension->LogicalCylinders = + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? DrvParms->TMCylinders : DrvParms->LogicalCyls; + + DeviceExtension->StartingOffset.QuadPart = 0; + DeviceExtension->PartitionLength.QuadPart = (ULONGLONG)SectorCount * + (ULONGLONG)DrvParms->BytesPerSector; + DeviceExtension->HiddenSectors = 0; + DeviceExtension->PartitionNumber = 0; + DeviceExtension->PartitionType = 0; + DeviceExtension->BootIndicator = FALSE; + + DPRINT("%wZ: offset %I64d length %I64d\n", + &DeviceName, + DeviceExtension->StartingOffset.QuadPart, + DeviceExtension->PartitionLength.QuadPart); + + /* Initialize the DPC object here */ + IoInitializeDpcRequest(*DeviceObject, + IDEDpcForIsr); + + return RC; +} + + +// IDECreatePartitionDevice +// +// DESCRIPTION: +// Creates a partition device object +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject The system supplied driver object +// OUT PDEVICE_OBJECT *DeviceObject The created device object +// IN PCONTROLLER_OBJECT ControllerObject The Controller for the device +// IN BOOLEAN LBASupported Does the drive support LBA addressing? +// IN BOOLEAN DMASupported Does the drive support DMA? +// IN int SectorsPerLogCyl Sectors per cylinder +// IN int SectorsPerLogTrk Sectors per track +// IN DWORD Offset First valid sector for this device +// IN DWORD Size Count of valid sectors for this device +// +// RETURNS: +// NTSTATUS +// + +NTSTATUS +IDECreatePartitionDevice(IN PDRIVER_OBJECT DriverObject, + OUT PDEVICE_OBJECT *DeviceObject, + IN PCONTROLLER_OBJECT ControllerObject, + IN PVOID DiskDeviceExtension, + IN int UnitNumber, + IN ULONG DiskNumber, + IN PIDE_DRIVE_IDENTIFY DrvParms, + IN PPARTITION_INFORMATION PartitionInfo) +{ + WCHAR NameBuffer[IDE_MAX_NAME_LENGTH]; + UNICODE_STRING DeviceName; + NTSTATUS RC; + PIDE_DEVICE_EXTENSION DeviceExtension; + + /* Create a unicode device name */ + swprintf(NameBuffer, + L"\\Device\\Harddisk%d\\Partition%d", + DiskNumber, + PartitionInfo->PartitionNumber); + RtlInitUnicodeString(&DeviceName, + NameBuffer); + + /* Create the device */ + RC = IoCreateDevice(DriverObject, sizeof(IDE_DEVICE_EXTENSION), + &DeviceName, FILE_DEVICE_DISK, 0, TRUE, DeviceObject); + if (!NT_SUCCESS(RC)) + { + DbgPrint ("IoCreateDevice call failed\n"); + return RC; + } + + /* Set the buffering strategy here... */ + (*DeviceObject)->Flags |= DO_DIRECT_IO; + (*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT; + + /* Fill out Device extension data */ + DeviceExtension = (PIDE_DEVICE_EXTENSION)(*DeviceObject)->DeviceExtension; + DeviceExtension->DeviceObject = (*DeviceObject); + DeviceExtension->ControllerObject = ControllerObject; + DeviceExtension->DiskDeviceExtension = DiskDeviceExtension; + DeviceExtension->UnitNumber = UnitNumber; + DeviceExtension->LBASupported = + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0; + DeviceExtension->DMASupported = + (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0; + DeviceExtension->BytesPerSector = DrvParms->BytesPerSector; + DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads * + DrvParms->SectorsPerTrack; + DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack; + DeviceExtension->LogicalHeads = DrvParms->LogicalHeads; + DeviceExtension->LogicalCylinders = + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? DrvParms->TMCylinders : DrvParms->LogicalCyls; + + DeviceExtension->StartingOffset = PartitionInfo->StartingOffset; + DeviceExtension->PartitionLength = PartitionInfo->PartitionLength; + DeviceExtension->HiddenSectors = PartitionInfo->HiddenSectors; + DeviceExtension->PartitionNumber = PartitionInfo->PartitionNumber; + DeviceExtension->PartitionType = PartitionInfo->PartitionType; + DeviceExtension->BootIndicator = PartitionInfo->BootIndicator; + + DPRINT("%wZ: offset %I64d size %I64d\n", + &DeviceName, + DeviceExtension->StartingOffset.QuadPart, + DeviceExtension->PartitionLength.QuadPart); + + /* Initialize the DPC object here */ + IoInitializeDpcRequest(*DeviceObject, IDEDpcForIsr); + + DPRINT("%wZ %I64dMB\n", + &DeviceName, + DeviceExtension->PartitionLength.QuadPart >> 20); + + return RC; +} + + +// IDEPolledRead +// +// DESCRIPTION: +// Read a sector of data from the drive in a polled fashion. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN WORD Address Address of command port for drive +// IN BYTE PreComp Value to write to precomp register +// IN BYTE SectorCnt Value to write to sectorCnt register +// IN BYTE SectorNum Value to write to sectorNum register +// IN BYTE CylinderLow Value to write to CylinderLow register +// IN BYTE CylinderHigh Value to write to CylinderHigh register +// IN BYTE DrvHead Value to write to Drive/Head register +// IN BYTE Command Value to write to Command register +// OUT BYTE *Buffer Buffer for output data +// +// RETURNS: +// int 0 is success, non 0 is an error code +// + +static int +IDEPolledRead(IN WORD Address, + IN BYTE PreComp, + IN BYTE SectorCnt, + IN BYTE SectorNum, + IN BYTE CylinderLow, + IN BYTE CylinderHigh, + IN BYTE DrvHead, + IN BYTE Command, + OUT BYTE *Buffer) +{ + BYTE Status; + int RetryCount; + BOOLEAN ReadJunk = FALSE; + ULONG SectorCount = 0; + + /* Wait for STATUS.BUSY and STATUS.DRQ to clear */ + for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) + { + Status = IDEReadStatus(Address); + if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ)) + { + break; + } + KeStallExecutionProcessor(10); + } + if (RetryCount == IDE_MAX_BUSY_RETRIES) + { + return IDE_ER_ABRT; + } + + /* Write Drive/Head to select drive */ + IDEWriteDriveHead(Address, IDE_DH_FIXED | DrvHead); + + /* Wait for STATUS.BUSY and STATUS.DRQ to clear */ + for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) + { + Status = IDEReadStatus(Address); + if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ)) + { + break; + } + KeStallExecutionProcessor(10); + } + if (RetryCount == IDE_MAX_BUSY_RETRIES) + { + return IDE_ER_ABRT; + } + + /* Issue command to drive */ + if (DrvHead & IDE_DH_LBA) + { + DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", + DrvHead & IDE_DH_DRV1 ? 1 : 0, + ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum, + SectorCnt, + Command); + } + else + { + DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", + DrvHead & IDE_DH_DRV1 ? 1 : 0, + CylinderHigh, + CylinderLow, + DrvHead & 0x0f, + SectorNum, + SectorCnt, + Command); + } + + /* Setup command parameters */ + IDEWritePrecomp(Address, PreComp); + IDEWriteSectorCount(Address, SectorCnt); + IDEWriteSectorNum(Address, SectorNum); + IDEWriteCylinderHigh(Address, CylinderHigh); + IDEWriteCylinderLow(Address, CylinderLow); + IDEWriteDriveHead(Address, IDE_DH_FIXED | DrvHead); + + /* Issue the command */ + IDEWriteCommand(Address, Command); + KeStallExecutionProcessor(50); + + /* wait for DRQ or error */ + for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++) + { + Status = IDEReadStatus(Address); + if (!(Status & IDE_SR_BUSY)) + { + if (Status & IDE_SR_ERR) + { + DPRINT("IDE_SR_ERR asserted!\n"); + } + if ((Status & IDE_SR_DRQ) && !(Status & IDE_SR_ERR)) + { + break; + } + else + { + return IDE_ER_ABRT; + } + } + KeStallExecutionProcessor(10); + } + if (RetryCount >= IDE_MAX_POLL_RETRIES) + { + return IDE_ER_ABRT; + } + + while (1) + { + /* Read data into buffer */ + if (ReadJunk == TRUE) + { + UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ]; + IDEReadBlock(Address, JunkBuffer, IDE_SECTOR_BUF_SZ); + } + else + { + IDEReadBlock(Address, Buffer, IDE_SECTOR_BUF_SZ); + Buffer += IDE_SECTOR_BUF_SZ; + } + SectorCount++; + + /* Check for more sectors to read */ + for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) + { + Status = IDEReadStatus(Address); + if (!(Status & IDE_SR_BUSY)) + { + if (Status & IDE_SR_ERR) + { + DPRINT("IDE_SR_ERR asserted!\n"); + } + if (Status & IDE_SR_DRQ) + { + if (SectorCount >= SectorCnt) + ReadJunk = TRUE; + break; + } + else + { + return 0; + } + } + } + } +} + +// ------------------------------------------- Nondiscardable statics + +// IDEDispatchOpenClose +// +// DESCRIPTION: +// Answer requests for Open/Close calls: a null operation +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, + IN PIRP Irp) +{ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +// IDEDispatchReadWrite +// +// DESCRIPTION: +// Answer requests for reads and writes +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +IDEDispatchReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + ULONG IrpInsertKey; + LARGE_INTEGER AdjustedOffset, AdjustedExtent, PartitionExtent, InsertKeyLI; + PIO_STACK_LOCATION IrpStack; + PIDE_DEVICE_EXTENSION DeviceExtension; + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = (PIDE_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // Validate operation parameters + AdjustedOffset.QuadPart = DeviceExtension->StartingOffset.QuadPart + + IrpStack->Parameters.Read.ByteOffset.QuadPart; + DPRINT("AdjustedOffset: %I64x\n", AdjustedOffset.QuadPart); + + AdjustedExtent.QuadPart = AdjustedOffset.QuadPart + + (ULONGLONG)IrpStack->Parameters.Read.Length; + DPRINT("AdjustedExtent: %I64x\n", AdjustedExtent.QuadPart); + + PartitionExtent.QuadPart = DeviceExtension->StartingOffset.QuadPart + + DeviceExtension->PartitionLength.QuadPart; + DPRINT("PartitionExtent: %I64x\n", PartitionExtent.QuadPart); + + if ((AdjustedExtent.QuadPart > PartitionExtent.QuadPart) || + (IrpStack->Parameters.Read.Length & (DeviceExtension->BytesPerSector - 1))) + { + DPRINT("Request failed on bad parameters\n",0); + DPRINT("AdjustedExtent=%I64x PartitionExtent=%I64x ReadLength=%lx\n", + AdjustedExtent.QuadPart, + PartitionExtent.QuadPart, + IrpStack->Parameters.Read.Length); + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INVALID_PARAMETER; + } + + // Adjust operation to absolute sector offset + IrpStack->Parameters.Read.ByteOffset = AdjustedOffset; + + // Start the packet and insert the request in order of sector offset + assert(DeviceExtension->BytesPerSector == 512); + InsertKeyLI.QuadPart = IrpStack->Parameters.Read.ByteOffset.QuadPart >> 9; + IrpInsertKey = InsertKeyLI.u.LowPart; + IoStartPacket(DeviceObject, Irp, &IrpInsertKey, NULL); + + DPRINT("Returning STATUS_PENDING\n"); + return STATUS_PENDING; +} + +// IDEDispatchDeviceControl +// +// DESCRIPTION: +// Answer requests for device control calls +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +IDEDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS RC; + ULONG ControlCode, InputLength, OutputLength; + PIO_STACK_LOCATION IrpStack; + PIDE_DEVICE_EXTENSION DeviceExtension; + PIDE_DEVICE_EXTENSION DiskDeviceExtension; + CCHAR Increment; + + RC = STATUS_SUCCESS; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + DiskDeviceExtension = (PIDE_DEVICE_EXTENSION)DeviceExtension->DiskDeviceExtension; + Increment = IO_NO_INCREMENT; + + // A huge switch statement in a Windows program?! who would have thought? + switch (ControlCode) + { + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + } + else + { + PDISK_GEOMETRY Geometry; + + Geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; + + Geometry->MediaType = FixedMedia; + Geometry->Cylinders.QuadPart = DiskDeviceExtension->LogicalCylinders; + Geometry->TracksPerCylinder = DiskDeviceExtension->SectorsPerLogCyl / + DiskDeviceExtension->SectorsPerLogTrk; + Geometry->SectorsPerTrack = DiskDeviceExtension->SectorsPerLogTrk; + Geometry->BytesPerSector = DiskDeviceExtension->BytesPerSector; +DPRINT("DiskDeviceExtension->BytesPerSector %lu\n", DiskDeviceExtension->BytesPerSector); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); + } + break; + + case IOCTL_DISK_GET_PARTITION_INFO: + DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n"); + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(PARTITION_INFORMATION)) + { + Irp->IoStatus.Status = STATUS_INFO_LENGTH_MISMATCH; + } + else if (DeviceExtension->PartitionNumber == 0) + { + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + PPARTITION_INFORMATION PartitionInfo; + + PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + PartitionInfo->PartitionType = DeviceExtension->PartitionType; + PartitionInfo->StartingOffset = DeviceExtension->StartingOffset; + PartitionInfo->PartitionLength = DeviceExtension->PartitionLength; + PartitionInfo->HiddenSectors = DeviceExtension->HiddenSectors; + PartitionInfo->PartitionNumber = DeviceExtension->PartitionNumber; + PartitionInfo->BootIndicator = DeviceExtension->BootIndicator; + PartitionInfo->RewritePartition = FALSE; + PartitionInfo->RecognizedPartition = + IsRecognizedPartition(DeviceExtension->PartitionType); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION); + } + break; + + case IOCTL_DISK_SET_PARTITION_INFO: + RC = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Status = RC; + Irp->IoStatus.Information = 0; + break; + + case IOCTL_DISK_GET_DRIVE_LAYOUT: + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(DRIVE_LAYOUT_INFORMATION)) + { + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + PDRIVE_LAYOUT_INFORMATION PartitionList; + + RC = IoReadPartitionTable(DiskDeviceExtension->DeviceObject, + DiskDeviceExtension->BytesPerSector, + FALSE, + &PartitionList); + if (!NT_SUCCESS(RC)) + { + Irp->IoStatus.Status = RC; + } + else + { + ULONG BufferSize; + + BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, + PartitionEntry[0]); + BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION); + + if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength) + { + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, + PartitionList, + BufferSize); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = BufferSize; + } + ExFreePool(PartitionList); + } + } + Increment = IO_DISK_INCREMENT; + break; + + case IOCTL_DISK_SET_DRIVE_LAYOUT: + case IOCTL_DISK_VERIFY: + case IOCTL_DISK_FORMAT_TRACKS: + case IOCTL_DISK_PERFORMANCE: + case IOCTL_DISK_IS_WRITABLE: + case IOCTL_DISK_LOGGING: + case IOCTL_DISK_FORMAT_TRACKS_EX: + case IOCTL_DISK_HISTOGRAM_STRUCTURE: + case IOCTL_DISK_HISTOGRAM_DATA: + case IOCTL_DISK_HISTOGRAM_RESET: + case IOCTL_DISK_REQUEST_STRUCTURE: + case IOCTL_DISK_REQUEST_DATA: + + // If we get here, something went wrong. inform the requestor + default: + RC = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Status = RC; + Irp->IoStatus.Information = 0; + break; + } + + IoCompleteRequest(Irp, Increment); + + return RC; +} + +// IDEStartIo +// +// DESCRIPTION: +// Get the next requested I/O packet started +// +// RUN LEVEL: +// DISPATCH_LEVEL +// +// ARGUMENTS: +// Dispatch routine standard arguments +// +// RETURNS: +// NTSTATUS +// + +static VOID +STDCALL IDEStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + LARGE_INTEGER SectorLI; + PIO_STACK_LOCATION IrpStack; + PIDE_DEVICE_EXTENSION DeviceExtension; + KIRQL OldIrql; + + DPRINT("IDEStartIo() called!\n"); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + + // FIXME: implement the supported functions + + switch (IrpStack->MajorFunction) + { + case IRP_MJ_READ: + case IRP_MJ_WRITE: + DeviceExtension->Operation = IrpStack->MajorFunction; + DeviceExtension->BytesRequested = IrpStack->Parameters.Read.Length; + assert(DeviceExtension->BytesPerSector == 512); + SectorLI = RtlLargeIntegerShiftRight(IrpStack->Parameters.Read.ByteOffset, 9); + DeviceExtension->StartingSector = SectorLI.u.LowPart; + if (DeviceExtension->BytesRequested > DeviceExtension->BytesPerSector * + IDE_MAX_SECTORS_PER_XFER) + { + DeviceExtension->BytesToTransfer = DeviceExtension->BytesPerSector * + IDE_MAX_SECTORS_PER_XFER; + } + else + { + DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested; + } + DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; + DeviceExtension->SectorsTransferred = 0; + DeviceExtension->TargetAddress = (BYTE *)MmGetSystemAddressForMdl(Irp->MdlAddress); + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + IoAllocateController(DeviceExtension->ControllerObject, + DeviceObject, + IDEAllocateController, + NULL); + KeLowerIrql(OldIrql); + break; + + default: + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + KeBugCheck((ULONG)Irp); + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, FALSE); + break; + } + DPRINT("IDEStartIo() finished!\n"); +} + +// IDEAllocateController + +static IO_ALLOCATION_ACTION STDCALL +IDEAllocateController(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Ccontext) +{ + PIDE_DEVICE_EXTENSION DeviceExtension; + PIDE_CONTROLLER_EXTENSION ControllerExtension; + + DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + ControllerExtension = (PIDE_CONTROLLER_EXTENSION) + DeviceExtension->ControllerObject->ControllerExtension; + ControllerExtension->CurrentIrp = Irp; + ControllerExtension->Retries = 0; + return KeSynchronizeExecution(ControllerExtension->Interrupt, + IDEStartController, + DeviceExtension) ? KeepObject : + DeallocateObject; +} + +// IDEStartController + +BOOLEAN STDCALL +IDEStartController(IN OUT PVOID Context) +{ + BYTE SectorCnt, SectorNum, CylinderLow, CylinderHigh; + BYTE DrvHead, Command; + BYTE Status; + int Retries; + ULONG StartingSector; + PIDE_DEVICE_EXTENSION DeviceExtension; + PIDE_CONTROLLER_EXTENSION ControllerExtension; + PIRP Irp; + + DeviceExtension = (PIDE_DEVICE_EXTENSION) Context; + ControllerExtension = (PIDE_CONTROLLER_EXTENSION) + DeviceExtension->ControllerObject->ControllerExtension; + ControllerExtension->OperationInProgress = TRUE; + ControllerExtension->DeviceForOperation = DeviceExtension; + + // Write controller registers to start opteration + StartingSector = DeviceExtension->StartingSector; + SectorCnt = DeviceExtension->BytesToTransfer / + DeviceExtension->BytesPerSector; + if (DeviceExtension->LBASupported) + { + SectorNum = StartingSector & 0xff; + CylinderLow = (StartingSector >> 8) & 0xff; + CylinderHigh = (StartingSector >> 16) & 0xff; + DrvHead = ((StartingSector >> 24) & 0x0f) | + (DeviceExtension->UnitNumber ? IDE_DH_DRV1 : 0) | + IDE_DH_LBA; + } + else + { + SectorNum = (StartingSector % DeviceExtension->SectorsPerLogTrk) + 1; + StartingSector /= DeviceExtension->SectorsPerLogTrk; + DrvHead = (StartingSector % DeviceExtension->LogicalHeads) | + (DeviceExtension->UnitNumber ? IDE_DH_DRV1 : 0); + StartingSector /= DeviceExtension->LogicalHeads; + CylinderLow = StartingSector & 0xff; + CylinderHigh = StartingSector >> 8; + } + Command = DeviceExtension->Operation == IRP_MJ_READ ? + IDE_CMD_READ : IDE_CMD_WRITE; + if (DrvHead & IDE_DH_LBA) + { + DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", + DeviceExtension->Operation == IRP_MJ_READ ? "READ" : "WRITE", + ControllerExtension->CommandPortBase, + DrvHead & IDE_DH_DRV1 ? 1 : 0, + ((DrvHead & 0x0f) << 24) + + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum, + SectorCnt, + Command); + } + else + { + DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", + DeviceExtension->Operation == IRP_MJ_READ ? "READ" : "WRITE", + ControllerExtension->CommandPortBase, + DrvHead & IDE_DH_DRV1 ? 1 : 0, + CylinderHigh, + CylinderLow, + DrvHead & 0x0f, + SectorNum, + SectorCnt, + Command); + } + + /* wait for BUSY to clear */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(ControllerExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY)) + { + break; + } + KeStallExecutionProcessor(10); + } + DPRINT ("status=%02x\n", Status); + DPRINT ("waited %ld usecs for busy to clear\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT ("Drive is BUSY for too long\n"); + if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES) + { + DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + DPRINT ("Beginning drive reset sequence\n"); + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } + } + + /* Select the desired drive */ + IDEWriteDriveHead(ControllerExtension->CommandPortBase, IDE_DH_FIXED | DrvHead); + + /* wait for BUSY to clear and DRDY to assert */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(ControllerExtension->CommandPortBase); +// if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY)) + if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ)) + { + break; + } + KeStallExecutionProcessor(10); + } + DPRINT ("waited %ld usecs for busy to clear after drive select\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT ("Drive is BUSY for too long after drive select\n"); + if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES) + { + DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + DPRINT ("Beginning drive reset sequence\n"); + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } + } + + /* Setup command parameters */ + IDEWritePrecomp(ControllerExtension->CommandPortBase, 0); + IDEWriteSectorCount(ControllerExtension->CommandPortBase, SectorCnt); + IDEWriteSectorNum(ControllerExtension->CommandPortBase, SectorNum); + IDEWriteCylinderHigh(ControllerExtension->CommandPortBase, CylinderHigh); + IDEWriteCylinderLow(ControllerExtension->CommandPortBase, CylinderLow); + IDEWriteDriveHead(ControllerExtension->CommandPortBase, IDE_DH_FIXED | DrvHead); + + /* Issue command to drive */ + IDEWriteCommand(ControllerExtension->CommandPortBase, Command); + ControllerExtension->TimerState = IDETimerCmdWait; + ControllerExtension->TimerCount = IDE_CMD_TIMEOUT; + + if (DeviceExtension->Operation == IRP_MJ_WRITE) + { + + // Wait for controller ready + for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++) + { + BYTE Status = IDEReadStatus(ControllerExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR)) + { + break; + } + KeStallExecutionProcessor(10); + } + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES) + { + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } + } + + // Load the first sector of data into the controller + IDEWriteBlock(ControllerExtension->CommandPortBase, + DeviceExtension->TargetAddress, + IDE_SECTOR_BUF_SZ); + DeviceExtension->TargetAddress += IDE_SECTOR_BUF_SZ; + DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; + DeviceExtension->SectorsTransferred++; + } + DPRINT ("Command issued to drive, IDEStartController done\n"); + + return TRUE; +} + +// IDEBeginControllerReset + +VOID +IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension) +{ + int Retries; + + DPRINT("Controller Reset initiated on %04x\n", + ControllerExtension->ControlPortBase); + + /* Assert drive reset line */ + DPRINT("Asserting reset line\n"); + IDEWriteDriveControl(ControllerExtension->ControlPortBase, IDE_DC_SRST); + + /* Wait for BSY assertion */ + DPRINT("Waiting for BSY assertion\n"); + for (Retries = 0; Retries < IDE_MAX_RESET_RETRIES; Retries++) + { + BYTE Status = IDEReadStatus(ControllerExtension->CommandPortBase); + if ((Status & IDE_SR_BUSY)) + { + break; + } + KeStallExecutionProcessor(10); + } + if (Retries == IDE_MAX_RESET_RETRIES) + { + DPRINT("Timeout on BSY assertion\n"); + } + + /* Negate drive reset line */ + DPRINT("Negating reset line\n"); + IDEWriteDriveControl(ControllerExtension->ControlPortBase, 0); + + // FIXME: handle case of no device 0 + + /* Set timer to check for end of reset */ + ControllerExtension->TimerState = IDETimerResetWaitForBusyNegate; + ControllerExtension->TimerCount = IDE_RESET_BUSY_TIMEOUT; +} + +// IDEIsr +// +// DESCIPTION: +// Handle interrupts for IDE devices +// +// RUN LEVEL: +// DIRQL +// +// ARGUMENTS: +// IN PKINTERRUPT Interrupt The interrupt level in effect +// IN PVOID ServiceContext The driver supplied context +// (the controller extension) +// RETURNS: +// TRUE This ISR handled the interrupt +// FALSE Another ISR must handle this interrupt + +static BOOLEAN STDCALL +IDEIsr(IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext) +{ + BOOLEAN IsLastBlock, AnErrorOccured, RequestIsComplete; + BYTE *TargetAddress; + int Retries; + NTSTATUS ErrorStatus; + ULONG ErrorInformation; + PIRP Irp; + PIDE_DEVICE_EXTENSION DeviceExtension; + PIDE_CONTROLLER_EXTENSION ControllerExtension; + + if (IDEInitialized == FALSE) + { + return FALSE; + } + DPRINT ("IDEIsr called\n"); + + ControllerExtension = (PIDE_CONTROLLER_EXTENSION) ServiceContext; + + // Read the status port to clear the interrtupt (even if it's not ours). + ControllerExtension->DeviceStatus = IDEReadStatus(ControllerExtension->CommandPortBase); + + // If the interrupt is not ours, get the heck outta dodge. + if (!ControllerExtension->OperationInProgress) + { + return FALSE; + } + + DeviceExtension = ControllerExtension->DeviceForOperation; + IsLastBlock = FALSE; + AnErrorOccured = FALSE; + RequestIsComplete = FALSE; + ErrorStatus = STATUS_SUCCESS; + ErrorInformation = 0; + + // Handle error condition if it exists + if (ControllerExtension->DeviceStatus & IDE_SR_ERR) + { + BYTE ErrorReg, SectorCount, SectorNum, CylinderLow, CylinderHigh; + BYTE DriveHead; + + // Log the error + ErrorReg = IDEReadError(ControllerExtension->CommandPortBase); + CylinderLow = IDEReadCylinderLow(ControllerExtension->CommandPortBase); + CylinderHigh = IDEReadCylinderHigh(ControllerExtension->CommandPortBase); + DriveHead = IDEReadDriveHead(ControllerExtension->CommandPortBase); + SectorCount = IDEReadSectorCount(ControllerExtension->CommandPortBase); + SectorNum = IDEReadSectorNum(ControllerExtension->CommandPortBase); + // FIXME: should use the NT error logging facility + DbgPrint ("IDE Error: OP:%02x STAT:%02x ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n", + DeviceExtension->Operation, + ControllerExtension->DeviceStatus, + ErrorReg, + CylinderLow, + CylinderHigh, + SectorCount, + SectorNum); + + // FIXME: should retry the command and perhaps recalibrate the drive + + // Set error status information + AnErrorOccured = TRUE; + ErrorStatus = STATUS_DISK_OPERATION_FAILED; + ErrorInformation = + (((((((CylinderHigh << 8) + CylinderLow) * + DeviceExtension->LogicalHeads) + + (DriveHead % DeviceExtension->LogicalHeads)) * + DeviceExtension->SectorsPerLogTrk) + SectorNum - 1) - + DeviceExtension->StartingSector) * DeviceExtension->BytesPerSector; + } + else + { + + // Check controller and setup for next transfer + switch (DeviceExtension->Operation) + { + case IRP_MJ_READ: + + // Update controller/device state variables + TargetAddress = DeviceExtension->TargetAddress; + DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector; + DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; + DeviceExtension->SectorsTransferred++; + + // Remember whether DRQ should be low at end (last block read) + IsLastBlock = DeviceExtension->BytesToTransfer == 0; + + // Wait for DRQ assertion + for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES && + !(IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ); + Retries++) + { + KeStallExecutionProcessor(10); + } + + // Copy the block of data + IDEReadBlock(ControllerExtension->CommandPortBase, + TargetAddress, + IDE_SECTOR_BUF_SZ); + + // check DRQ + if (IsLastBlock) + { + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES && + (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY); + Retries++) + { + KeStallExecutionProcessor(10); + } + + // Check for data overrun + if (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ) + { + AnErrorOccured = TRUE; + ErrorStatus = STATUS_DATA_OVERRUN; + ErrorInformation = 0; + } + else + { + + // Setup next transfer or set RequestIsComplete + if (DeviceExtension->BytesRequested > + DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER) + { + DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; + DeviceExtension->SectorsTransferred = 0; + DeviceExtension->BytesToTransfer = + DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER; + DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; + } + else if (DeviceExtension->BytesRequested > 0) + { + DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; + DeviceExtension->SectorsTransferred = 0; + DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested; + DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; + } + else + { + RequestIsComplete = TRUE; + } + } + } + break; + + case IRP_MJ_WRITE: + + // check DRQ + if (DeviceExtension->BytesToTransfer == 0) + { + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES && + (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY); + Retries++) + { + KeStallExecutionProcessor(10); + } + + // Check for data overrun + if (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ) + { + AnErrorOccured = TRUE; + ErrorStatus = STATUS_DATA_OVERRUN; + ErrorInformation = 0; + } + else + { + + // Setup next transfer or set RequestIsComplete + IsLastBlock = TRUE; + if (DeviceExtension->BytesRequested > + DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER) + { + DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; + DeviceExtension->SectorsTransferred = 0; + DeviceExtension->BytesToTransfer = + DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER; + DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; + } + else if (DeviceExtension->BytesRequested > 0) + { + DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred; + DeviceExtension->SectorsTransferred = 0; + DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested; + DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer; + } + else + { + RequestIsComplete = TRUE; + } + } + } + else + { + + // Update controller/device state variables + TargetAddress = DeviceExtension->TargetAddress; + DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector; + DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; + DeviceExtension->SectorsTransferred++; + + // Write block to controller + IDEWriteBlock(ControllerExtension->CommandPortBase, + TargetAddress, + IDE_SECTOR_BUF_SZ); + } + break; + } + } + + // If there was an error or the request is done, complete the packet + if (AnErrorOccured || RequestIsComplete) + { + // Set the return status and info values + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = ErrorStatus; + Irp->IoStatus.Information = ErrorInformation; + + // Clear out controller fields + ControllerExtension->OperationInProgress = FALSE; + ControllerExtension->DeviceStatus = 0; + + // Queue the Dpc to finish up + IoRequestDpc(DeviceExtension->DeviceObject, + Irp, + ControllerExtension); + } + else if (IsLastBlock) + { + // Else more data is needed, setup next device I/O + IDEStartController((PVOID)DeviceExtension); + } + + return TRUE; +} + +// IDEDpcForIsr +// DESCRIPTION: +// +// RUN LEVEL: +// +// ARGUMENTS: +// IN PKDPC Dpc +// IN PDEVICE_OBJECT DpcDeviceObject +// IN PIRP DpcIrp +// IN PVOID DpcContext +// +static VOID +IDEDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext) +{ + DPRINT("IDEDpcForIsr()\n"); + IDEFinishOperation((PIDE_CONTROLLER_EXTENSION) DpcContext); +} + +// IDEFinishOperation + +static VOID +IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension) +{ + PIDE_DEVICE_EXTENSION DeviceExtension; + PIRP Irp; + ULONG Operation; + + DeviceExtension = ControllerExtension->DeviceForOperation; + Irp = ControllerExtension->CurrentIrp; + Operation = DeviceExtension->Operation; + ControllerExtension->OperationInProgress = FALSE; + ControllerExtension->DeviceForOperation = 0; + ControllerExtension->CurrentIrp = 0; + + // Deallocate the controller + IoFreeController(DeviceExtension->ControllerObject); + + // Start the next packet + IoStartNextPacketByKey(DeviceExtension->DeviceObject, + FALSE, + DeviceExtension->StartingSector); + + // Flush cache if necessary + if (Operation == IRP_MJ_READ) + { + KeFlushIoBuffers(Irp->MdlAddress, TRUE, FALSE); + } + // Issue completion of the current packet + // return status information too + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = DeviceExtension->SectorsTransferred * DeviceExtension->BytesPerSector; + IoCompleteRequest(Irp, IO_DISK_INCREMENT); +} + +// IDEIoTimer +// DESCRIPTION: +// This function handles timeouts and other time delayed processing +// +// RUN LEVEL: +// +// ARGUMENTS: +// IN PDEVICE_OBJECT DeviceObject Device object registered with timer +// IN PVOID Context the Controller extension for the +// controller the device is on +// +static VOID STDCALL +IDEIoTimer(PDEVICE_OBJECT DeviceObject, + PVOID Context) +{ + PIDE_CONTROLLER_EXTENSION ControllerExtension; + + // Setup Extension pointer + ControllerExtension = (PIDE_CONTROLLER_EXTENSION) Context; + DPRINT("Timer activated for %04lx\n", ControllerExtension->CommandPortBase); + + // Handle state change if necessary + switch (ControllerExtension->TimerState) + { + case IDETimerResetWaitForBusyNegate: + if (!(IDEReadStatus(ControllerExtension->CommandPortBase) & + IDE_SR_BUSY)) + { + DPRINT("Busy line has negated, waiting for DRDY assert\n"); + ControllerExtension->TimerState = IDETimerResetWaitForDrdyAssert; + ControllerExtension->TimerCount = IDE_RESET_DRDY_TIMEOUT; + return; + } + break; + + case IDETimerResetWaitForDrdyAssert: + if (IDEReadStatus(ControllerExtension->CommandPortBase) & + IDE_SR_DRQ) + { + DPRINT("DRDY has asserted, reset complete\n"); + ControllerExtension->TimerState = IDETimerIdle; + ControllerExtension->TimerCount = 0; + + // FIXME: get diagnostic code from drive 0 + + /* Start current packet command again */ + if (!KeSynchronizeExecution(ControllerExtension->Interrupt, + IDEStartController, + ControllerExtension->DeviceForOperation)) + { + IDEFinishOperation(ControllerExtension); + } + return; + } + break; + + default: + break; + } + + // If we're counting down, then count. + if (ControllerExtension->TimerCount > 0) + { + ControllerExtension->TimerCount--; + + // Else we'll check the state and process if necessary + } + else + { + switch (ControllerExtension->TimerState) + { + case IDETimerIdle: + break; + + case IDETimerCmdWait: + /* Command timed out, reset drive and try again or fail */ + DPRINT("Timeout waiting for command completion\n"); + if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES) + { + if (ControllerExtension->CurrentIrp != NULL) + { + DbgPrint ("Max retries has been reached, IRP finished with error\n"); + ControllerExtension->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT; + ControllerExtension->CurrentIrp->IoStatus.Information = 0; + IDEFinishOperation(ControllerExtension); + } + ControllerExtension->TimerState = IDETimerIdle; + ControllerExtension->TimerCount = 0; + } + else + { + IDEBeginControllerReset(ControllerExtension); + } + break; + + case IDETimerResetWaitForBusyNegate: + case IDETimerResetWaitForDrdyAssert: + if (ControllerExtension->CurrentIrp != NULL) + { + DbgPrint ("Timeout waiting for drive reset, giving up on IRP\n"); + ControllerExtension->CurrentIrp->IoStatus.Status = + STATUS_IO_TIMEOUT; + ControllerExtension->CurrentIrp->IoStatus.Information = 0; + IDEFinishOperation(ControllerExtension); + } + ControllerExtension->TimerState = IDETimerIdle; + ControllerExtension->TimerCount = 0; + break; + } + } +} + + diff --git a/drivers/dd/ide/ide.h b/drivers/dd/ide/ide.h new file mode 100644 index 0000000..9ad89a2 --- /dev/null +++ b/drivers/dd/ide/ide.h @@ -0,0 +1,256 @@ +// +// IDE.H - defines and typedefs for the IDE Driver module. +// + +#ifndef __IDE_H +#define __IDE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define IDE_MAXIMUM_DEVICES 8 + +#define IDE_MAX_NAME_LENGTH 50 + +#define IDE_SECTOR_BUF_SZ 512 +#define IDE_MAX_SECTORS_PER_XFER 256 +#define IDE_MAX_RESET_RETRIES 10000 +#define IDE_MAX_POLL_RETRIES 100000 +#define IDE_MAX_WRITE_RETRIES 1000 +#define IDE_MAX_BUSY_RETRIES 50000 +#define IDE_MAX_DRQ_RETRIES 10000 +//#define IDE_MAX_CMD_RETRIES 1 +#define IDE_MAX_CMD_RETRIES 0 +#define IDE_CMD_TIMEOUT 5 +#define IDE_RESET_PULSE_LENGTH 500 /* maybe a little too long */ +#define IDE_RESET_BUSY_TIMEOUT 120 +#define IDE_RESET_DRDY_TIMEOUT 120 + +// Control Block offsets and masks +#define IDE_REG_ALT_STATUS 0x0000 +#define IDE_REG_DEV_CNTRL 0x0000 /* device control register */ +#define IDE_DC_SRST 0x04 /* drive reset (both drives) */ +#define IDE_DC_nIEN 0x02 /* IRQ enable (active low) */ +#define IDE_REG_DRV_ADDR 0x0001 + +// Command Block offsets and masks +#define IDE_REG_DATA_PORT 0x0000 +#define IDE_REG_ERROR 0x0001 /* error register */ +#define IDE_ER_AMNF 0x01 /* addr mark not found */ +#define IDE_ER_TK0NF 0x02 /* track 0 not found */ +#define IDE_ER_ABRT 0x04 /* command aborted */ +#define IDE_ER_MCR 0x08 /* media change requested */ +#define IDE_ER_IDNF 0x10 /* ID not found */ +#define IDE_ER_MC 0x20 /* Media changed */ +#define IDE_ER_UNC 0x40 /* Uncorrectable data error */ +#define IDE_REG_PRECOMP 0x0001 +#define IDE_REG_SECTOR_CNT 0x0002 +#define IDE_REG_SECTOR_NUM 0x0003 +#define IDE_REG_CYL_LOW 0x0004 +#define IDE_REG_CYL_HIGH 0x0005 +#define IDE_REG_DRV_HEAD 0x0006 +#define IDE_DH_FIXED 0xA0 +#define IDE_DH_LBA 0x40 +#define IDE_DH_HDMASK 0x0F +#define IDE_DH_DRV0 0x00 +#define IDE_DH_DRV1 0x10 +#define IDE_REG_STATUS 0x0007 +#define IDE_SR_BUSY 0x80 +#define IDE_SR_DRDY 0x40 +#define IDE_SR_DRQ 0x08 +#define IDE_SR_ERR 0x01 +#define IDE_REG_COMMAND 0x0007 +#define IDE_CMD_READ 0x20 +#define IDE_CMD_READ_RETRY 0x21 +#define IDE_CMD_WRITE 0x30 +#define IDE_CMD_WRITE_RETRY 0x31 +#define IDE_CMD_IDENT_DRV 0xEC + +// +// Access macros for command registers +// Each macro takes an address of the command port block, and data +// +#define IDEReadError(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR))) +#define IDEWritePrecomp(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data))) +#define IDEReadSectorCount(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT))) +#define IDEWriteSectorCount(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data))) +#define IDEReadSectorNum(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM))) +#define IDEWriteSectorNum(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data))) +#define IDEReadCylinderLow(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW))) +#define IDEWriteCylinderLow(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data))) +#define IDEReadCylinderHigh(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH))) +#define IDEWriteCylinderHigh(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data))) +#define IDEReadDriveHead(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD))) +#define IDEWriteDriveHead(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data))) +#define IDEReadStatus(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS))) +#define IDEWriteCommand(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data))) + + +// +// Data block read and write commands +// +#define IDEReadBlock(Address, Buffer, Count) \ + (READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) +#define IDEWriteBlock(Address, Buffer, Count) \ + (WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) + +// +// Access macros for control registers +// Each macro takes an address of the control port blank and data +// +#define IDEWriteDriveControl(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data))) + +// IDE_DEVICE_EXTENSION +// +// DESCRIPTION: +// Extension to be placed in each device object +// +// ACCESS: +// Allocated from NON-PAGED POOL +// Available at any IRQL +// + +typedef struct _IDE_DEVICE_EXTENSION +{ + PDEVICE_OBJECT DeviceObject; + PCONTROLLER_OBJECT ControllerObject; + PVOID DiskDeviceExtension; + int UnitNumber; + BOOLEAN LBASupported; + BOOLEAN DMASupported; + int BytesPerSector; + int LogicalHeads; + int LogicalCylinders; + int SectorsPerLogCyl; + int SectorsPerLogTrk; + + LARGE_INTEGER StartingOffset; + LARGE_INTEGER PartitionLength; + ULONG HiddenSectors; + ULONG PartitionNumber; + UCHAR PartitionType; + BOOLEAN BootIndicator; + + int Operation; + ULONG BytesRequested; + ULONG BytesToTransfer; + ULONG BytesRemaining; + ULONG StartingSector; + int SectorsTransferred; + BYTE *TargetAddress; + +} IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION; + +// IDE_TIMER_STATES +// +// DESCRIPTION: +// An enumeration containing the states in the timer DFA +// + +typedef enum _IDE_TIMER_STATES { + IDETimerIdle, + IDETimerCmdWait, + IDETimerResetWaitForBusyNegate, + IDETimerResetWaitForDrdyAssert +} IDE_TIMER_STATES; + +// IDE_CONTROLLER_EXTENSION +// +// DESCRIPTION: +// Driver-defined structure used to hold miscellaneous controller information. +// +// ACCESS: +// Allocated from NON-PAGED POOL +// Available at any IRQL +// + +typedef struct _IDE_CONTROLLER_EXTENSION { + KSPIN_LOCK SpinLock; + int Number; + int Vector; + int CommandPortBase; + int ControlPortBase; + BOOLEAN DMASupported; + BOOLEAN ControllerInterruptBug; + PKINTERRUPT Interrupt; + + BOOLEAN OperationInProgress; + BYTE DeviceStatus; + PIDE_DEVICE_EXTENSION DeviceForOperation; + PIRP CurrentIrp; + int Retries; + + IDE_TIMER_STATES TimerState; + LONG TimerCount; + PDEVICE_OBJECT TimerDevice; + +} IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION; + +// IDE_DRIVE_IDENTIFY + +typedef struct _IDE_DRIVE_IDENTIFY { + WORD ConfigBits; /*00*/ + WORD LogicalCyls; /*01*/ + WORD Reserved02; /*02*/ + WORD LogicalHeads; /*03*/ + WORD BytesPerTrack; /*04*/ + WORD BytesPerSector; /*05*/ + WORD SectorsPerTrack; /*06*/ + BYTE InterSectorGap; /*07*/ + BYTE InterSectorGapSize; + BYTE Reserved08H; /*08*/ + BYTE BytesInPLO; + WORD VendorUniqueCnt; /*09*/ + char SerialNumber[20]; /*10*/ + WORD ControllerType; /*20*/ + WORD BufferSize; /*21*/ + WORD ECCByteCnt; /*22*/ + char FirmwareRev[8]; /*23*/ + char ModelNumber[40]; /*27*/ + WORD RWMultImplemented; /*47*/ + WORD Reserved48; /*48*/ + WORD Capabilities; /*49*/ +#define IDE_DRID_STBY_SUPPORTED 0x2000 +#define IDE_DRID_IORDY_SUPPORTED 0x0800 +#define IDE_DRID_IORDY_DISABLE 0x0400 +#define IDE_DRID_LBA_SUPPORTED 0x0200 +#define IDE_DRID_DMA_SUPPORTED 0x0100 + WORD Reserved50; /*50*/ + WORD MinPIOTransTime; /*51*/ + WORD MinDMATransTime; /*52*/ + WORD TMFieldsValid; /*53*/ + WORD TMCylinders; /*54*/ + WORD TMHeads; /*55*/ + WORD TMSectorsPerTrk; /*56*/ + WORD TMCapacityLo; /*57*/ + WORD TMCapacityHi; /*58*/ + WORD Reserved59; /*59*/ + WORD TMSectorCountLo; /*60*/ + WORD TMSectorCountHi; /*61*/ + WORD Reserved62[194]; /*62*/ +} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY; + + +#ifdef __cplusplus +} +#endif + +#endif /* __IDE_H */ + + diff --git a/drivers/dd/ide/ide.rc b/drivers/dd/ide/ide.rc new file mode 100644 index 0000000..5981746 --- /dev/null +++ b/drivers/dd/ide/ide.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "IDE Disk Device Driver\0" + VALUE "FileVersion", "0.1.4\0" + VALUE "InternalName", "ide\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ide.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/ide/makefile b/drivers/dd/ide/makefile new file mode 100644 index 0000000..47b8f74 --- /dev/null +++ b/drivers/dd/ide/makefile @@ -0,0 +1,17 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = ide + +TARGET_OBJECTS = ide.o + +TARGET_HEADERS = *.h + +TARGET_GCCLIBS = gcc + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/ide/partitio.h b/drivers/dd/ide/partitio.h new file mode 100644 index 0000000..06841ee --- /dev/null +++ b/drivers/dd/ide/partitio.h @@ -0,0 +1,41 @@ +/** +*** Partition.h - defines and structs for harddrive partition info +*** +*** 05/30/98 RJJ Created +**/ + +#ifndef __PARTITION_H +#define __PARTITION_H + +#define PARTITION_MAGIC 0xaa55 +#define PART_MAGIC_OFFSET 0x01fe +#define PARTITION_OFFSET 0x01be +#define PARTITION_TBL_SIZE 4 +#define PTCHSToLBA(c, h, s, scnt, hcnt) ((s) & 0x3f) + \ + (scnt) * ( (h) + (hcnt) * ((c) | (((s) & 0xc0) << 2))) +#define PTLBAToCHS(lba, c, h, s, scnt, hcnt) ( \ + (s) = (lba) % (scnt) + 1, \ + (lba) /= (scnt), \ + (h) = (lba) % (hcnt), \ + (lba) /= (heads), \ + (c) = (lba) & 0xff, \ + (s) |= ((lba) >> 2) & 0xc0) + + +typedef struct Partition { + unsigned char BootFlags; + unsigned char StartingHead; + unsigned char StartingSector; + unsigned char StartingCylinder; + unsigned char PartitionType; + unsigned char EndingHead; + unsigned char EndingSector; + unsigned char EndingCylinder; + unsigned int StartingBlock; + unsigned int SectorCount; + +} PARTITION; + +#endif // PARTITION_H + + diff --git a/drivers/dd/mouse/.cvsignore b/drivers/dd/mouse/.cvsignore new file mode 100644 index 0000000..ecc83ad --- /dev/null +++ b/drivers/dd/mouse/.cvsignore @@ -0,0 +1 @@ +base.tmp diff --git a/drivers/dd/mouse/makefile b/drivers/dd/mouse/makefile new file mode 100644 index 0000000..9beb9c9 --- /dev/null +++ b/drivers/dd/mouse/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = mouse + +TARGET_OBJECTS = mouse.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/mouse/mouse.c b/drivers/dd/mouse/mouse.c new file mode 100644 index 0000000..b9da7fb --- /dev/null +++ b/drivers/dd/mouse/mouse.c @@ -0,0 +1,270 @@ +/* + + ** Mouse driver 0.0.3 + ** Written by Jason Filby (jasonfilby@yahoo.com) + ** For ReactOS (www.sid-dis.com/reactos) + + ** Note: The serial.o driver must be loaded before loading this driver + + ** Known Limitations: + ** Only supports mice on COM port 1 + +*/ + +#include +#include +#include +/* #include */ +#include + +#define MOUSE_IRQ_COM1 4 +#define MOUSE_IRQ_COM2 3 + +#define COM1_PORT 0x3f8 +#define COM2_PORT 0x2f8 + +#define max_screen_x 79 +#define max_screen_y 24 + +static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1; +static unsigned int MOUSE_COM=COM1_PORT; + +static unsigned int bytepos=0, coordinate; +static unsigned char mpacket[3]; +static signed int mouse_x=40, mouse_y=12; +static unsigned char mouse_button1, mouse_button2; +static signed int horiz_sensitivity, vert_sensitivity; + +BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext) +{ + unsigned int mbyte=inb(MOUSE_COM); + + // Synchronize + if((mbyte&64)==64) { bytepos=0; }; + + mpacket[bytepos]=mbyte; + bytepos++; + + // Process packet + if(bytepos==3) { + // Retrieve change in x and y from packet + int change_x=((mpacket[0] & 3) << 6) + mpacket[1]; + int change_y=((mpacket[0] & 12) << 4) + mpacket[2]; + + // Some mice need this + if(coordinate==1) { + change_x-=128; + change_y-=128; + }; + + // Change to signed + if(change_x>=128) { change_x=change_x-256; }; + if(change_y>=128) { change_y=change_y-256; }; + + // Adjust mouse position according to sensitivity + mouse_x+=change_x/horiz_sensitivity; + mouse_y+=change_y/vert_sensitivity; + + // Check that mouse is still in screen + if(mouse_x<0) { mouse_x=0; }; + if(mouse_x>max_screen_x) { mouse_x=max_screen_x; }; + if(mouse_y<0) { mouse_y=0; }; + if(mouse_y>max_screen_y) { mouse_y=max_screen_y; }; + + // Retrieve mouse button status from packet + mouse_button1=mpacket[0] & 32; + mouse_button2=mpacket[0] & 16; + + bytepos=0; + }; + +}; + +void InitializeMouseHardware(unsigned int mtype) +{ + char clear_error_bits; + + outb_p(MOUSE_COM+3, 0x80); // set DLAB on + outb_p(MOUSE_COM, 0x60); // speed LO byte + outb_p(MOUSE_COM+1, 0); // speed HI byte + outb_p(MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse + outb_p(MOUSE_COM+1, 0); // set comm and DLAB to 0 + outb_p(MOUSE_COM+4, 1); // DR int enable + + clear_error_bits=inb_p(MOUSE_COM+5); // clear error bits +}; + +int DetMicrosoft(void) +{ + char tmp, ind; + int buttons=0, i; + + outb_p(MOUSE_COM+4, 0x0b); + tmp=inb_p(MOUSE_COM); + + // Check the first for bytes for signs that this is an MS mouse + for(i=0; i<4; i++) { + while((inb_p(MOUSE_COM+5) & 1)==0) ; + ind=inb_p(MOUSE_COM); + if(ind==0x33) buttons=3; + if(ind==0x4d) buttons=2; + }; + + return buttons; +}; + +int CheckMouseType(unsigned int mtype) +{ + unsigned int retval=0; + + InitializeMouseHardware(mtype); + if(mtype==2) retval=DetMicrosoft(); + if(mtype==3) { + outb_p(MOUSE_COM+4, 11); + retval=3; + }; + outb_p(MOUSE_COM+1, 1); + + return retval; +}; + +void ClearMouse(void) +{ + // Waits until the mouse calms down but also quits out after a while + // in case some destructive user wants to keep moving the mouse + // before we're done + + unsigned int restarts=0, i; + for (i=0; i<60000; i++) + { + unsigned temp=inb(MOUSE_COM); + if(temp!=0) { + restarts++; + if(restarts<300000) { + i=0; + } else + { + i=60000; + }; + }; + }; +}; + +void InitializeMouse(void) +{ + int mbuttons=0, gotmouse=0; + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + PKINTERRUPT IrqObject; + + horiz_sensitivity=2; + vert_sensitivity=3; + + // Check for Microsoft mouse (2 buttons) + if(CheckMouseType(2)!=0) + { + gotmouse=1; + DbgPrint("Microsoft Mouse Detected\n"); + ClearMouse(); + coordinate=0; + }; + + // Check for Microsoft Systems mouse (3 buttons) + if(gotmouse==0) { + if(CheckMouseType(3)!=0) + { + gotmouse=1; + DbgPrint("Microsoft Mouse Detected\n"); + ClearMouse(); + coordinate=1; + }; + }; + + if(gotmouse==0) { + DbgPrint("No Mouse Detected!\n"); + } else { + MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, + &Dirql, &Affinity); + + IoConnectInterrupt(&IrqObject, microsoft_mouse_handler, NULL, + NULL, MappedIrq, Dirql, Dirql, 0, FALSE, + Affinity, FALSE); + }; +}; + +// For test purposes only +unsigned char get_text_char(int x, int y) +{ + unsigned char getchar; + char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2))); + getchar=*vidmem; + return getchar; +}; + +// For test purposes only +unsigned char get_text_color(int x, int y) +{ + unsigned char getcolor; + char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2))); + vidmem++; + getcolor=*vidmem; + return getcolor; +}; + +// For test purposes only +void put_text_char(int x, int y, unsigned char putchar[2]) +{ + char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2))); + *vidmem=putchar[0]; + vidmem++; + *vidmem=putchar[1]; +}; + +// For test purposes only +void test_mouse(void) +{ + static int i=0, forcechange=0; + static int old_x=40, old_y=12; + static unsigned char old_cursor[2], new_cursor[2]; + + DbgPrint("Testing mouse..."); + + old_cursor[0]=' '; + old_cursor[1]=7; + new_cursor[0]='Û'; + new_cursor[1]=15; + + old_cursor[0]=get_text_char(mouse_x, mouse_y); + old_cursor[1]=get_text_color(mouse_x, mouse_y); + put_text_char(mouse_x, mouse_y, new_cursor); + + while(i!=1) + { + if(mouse_button1!=0) { new_cursor[1]=10; mouse_button1=0; forcechange=1; }; + if(mouse_button2!=0) { new_cursor[1]=12; mouse_button2=0; forcechange=1; }; + + if((mouse_x!=old_x) || (mouse_y!=old_y) || (forcechange==1)) { + forcechange=0; + + put_text_char(old_x, old_y, old_cursor); + old_cursor[0]=get_text_char(mouse_x, mouse_y); + old_cursor[1]=get_text_color(mouse_x, mouse_y); + put_text_char(mouse_x, mouse_y, new_cursor); + + old_x=mouse_x; + old_y=mouse_y; + }; + }; +}; + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + DbgPrint("Mouse Driver 0.0.3\n"); + InitializeMouse(); + test_mouse(); + + return(STATUS_SUCCESS); +}; + diff --git a/drivers/dd/null/.cvsignore b/drivers/dd/null/.cvsignore new file mode 100644 index 0000000..03978ec --- /dev/null +++ b/drivers/dd/null/.cvsignore @@ -0,0 +1,7 @@ +null.coff +null.sys +null.sys.unstripped +base.tmp +junk.tmp +temp.exp + diff --git a/drivers/dd/null/makefile b/drivers/dd/null/makefile new file mode 100644 index 0000000..daba811 --- /dev/null +++ b/drivers/dd/null/makefile @@ -0,0 +1,15 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = null + +TARGET_OBJECTS = null.o + +#TARGET_LFLAGS = -Wl,--file-alignment,0x20 -Wl,--section-alignment,0x20 + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/null/null.c b/drivers/dd/null/null.c new file mode 100644 index 0000000..7ae1731 --- /dev/null +++ b/drivers/dd/null/null.c @@ -0,0 +1,164 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/null/null.c + * PURPOSE: NULL device driver + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 13/08/1998: Created + * 29/04/2002: Fixed bugs, added zero-stream device + */ + +/* INCLUDES */ +#include +#include "null.h" + +/* OBJECTS */ +static const NULL_EXTENSION nxNull = NullBitBucket; +static const NULL_EXTENSION nxZero = NullZeroStream; + +/* FUNCTIONS */ +NTSTATUS STDCALL +NullDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS nErrCode; + + nErrCode = STATUS_SUCCESS; + + switch(piosStack->MajorFunction) + { + /* opening and closing handles to the device */ + case IRP_MJ_CREATE: + case IRP_MJ_CLOSE: + { + break; + } + + /* write data */ + case IRP_MJ_WRITE: + { + switch(NULL_DEVICE_TYPE(DeviceObject)) + { + case NullBitBucket: + Irp->IoStatus.Information = piosStack->Parameters.Write.Length; + break; + + case NullZeroStream: + default: + Irp->IoStatus.Information = 0; + nErrCode = STATUS_NOT_IMPLEMENTED; + } + + break; + } + + /* read data */ + case IRP_MJ_READ: + { + switch(NULL_DEVICE_TYPE(DeviceObject)) + { + case NullBitBucket: + Irp->IoStatus.Information = 0; + nErrCode = STATUS_END_OF_FILE; + break; + + case NullZeroStream: + RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, piosStack->Parameters.Read.Length); + Irp->IoStatus.Information = piosStack->Parameters.Read.Length; + break; + + default: + Irp->IoStatus.Information = 0; + nErrCode = STATUS_NOT_IMPLEMENTED; + } + + break; + } + + /* unsupported operations */ + default: + { + nErrCode = STATUS_NOT_IMPLEMENTED; + } + } + + Irp->IoStatus.Status = nErrCode; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return (nErrCode); +} + +NTSTATUS STDCALL +NullUnload(PDRIVER_OBJECT DriverObject) +{ + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + PDEVICE_OBJECT pdoNullDevice; + PDEVICE_OBJECT pdoZeroDevice; + UNICODE_STRING wstrDeviceName; + NTSTATUS nErrCode; + + /* register driver routines */ + DriverObject->MajorFunction[IRP_MJ_CLOSE] = NullDispatch; + DriverObject->MajorFunction[IRP_MJ_CREATE] = NullDispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = NullDispatch; + DriverObject->MajorFunction[IRP_MJ_READ] = NullDispatch; + /* DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = NullDispatch; */ + DriverObject->DriverUnload = NullUnload; + + /* create null device */ + RtlInitUnicodeStringFromLiteral(&wstrDeviceName, L"\\Device\\Null"); + + nErrCode = IoCreateDevice + ( + DriverObject, + sizeof(NULL_EXTENSION), + &wstrDeviceName, + FILE_DEVICE_NULL, + 0, + FALSE, + &pdoNullDevice + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) + { + return (nErrCode); + } + + pdoNullDevice->DeviceExtension = (PVOID)&nxNull; + + /* create zero device */ + RtlInitUnicodeStringFromLiteral(&wstrDeviceName, L"\\Device\\Zero"); + + nErrCode = IoCreateDevice + ( + DriverObject, + sizeof(NULL_EXTENSION), + &wstrDeviceName, + FILE_DEVICE_NULL, + FILE_READ_ONLY_DEVICE, /* zero device is read-only */ + FALSE, + &pdoZeroDevice + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) + { + IoDeleteDevice(pdoNullDevice); + return (nErrCode); + } + + pdoZeroDevice->DeviceExtension = (PVOID)&nxZero; + pdoZeroDevice->Flags |= DO_BUFFERED_IO; + + return (nErrCode); +} + +/* EOF */ diff --git a/drivers/dd/null/null.h b/drivers/dd/null/null.h new file mode 100644 index 0000000..48e3c50 --- /dev/null +++ b/drivers/dd/null/null.h @@ -0,0 +1,19 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/dd/null/null.h + * PURPOSE: NULL device driver internal definitions + * PROGRAMMER: KJK::Hyperion + * UPDATE HISTORY: + * 29/04/2002: Created + */ + +typedef enum __tagNULL_EXTENSION{ + NullBitBucket, + NullZeroStream, +} NULL_EXTENSION, *PNULL_EXTENSION; + +#define NULL_DEVICE_TYPE(__DEVICE__) (*((PNULL_EXTENSION)((__DEVICE__)->DeviceExtension))) + +/* EOF */ diff --git a/drivers/dd/null/null.rc b/drivers/dd/null/null.rc new file mode 100644 index 0000000..5a61bc9 --- /dev/null +++ b/drivers/dd/null/null.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Null Device Driver\0" + VALUE "FileVersion", "0.0.2\0" + VALUE "InternalName", "null\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "null.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/parallel/.cvsignore b/drivers/dd/parallel/.cvsignore new file mode 100644 index 0000000..9a3b8eb --- /dev/null +++ b/drivers/dd/parallel/.cvsignore @@ -0,0 +1,7 @@ +base.tmp +junk.tmp +temp.exp +parallel.coff +parallel.sys +parallel.sys.unstripped + diff --git a/drivers/dd/parallel/makefile b/drivers/dd/parallel/makefile new file mode 100644 index 0000000..40afcba --- /dev/null +++ b/drivers/dd/parallel/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = parallel + +TARGET_OBJECTS = parallel.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/parallel/parallel.c b/drivers/dd/parallel/parallel.c new file mode 100644 index 0000000..526399b --- /dev/null +++ b/drivers/dd/parallel/parallel.c @@ -0,0 +1,156 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/parallel/parallel.c + * PURPOSE: Parallel port driver + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * ??/??/??: Created + * 18/06/98: Made more NT like + */ + +/* FUNCTIONS **************************************************************/ + +#include + +#include "parallel.h" + +#define NDEBUG +#include + + +#define LP_B (0x378) +#define LP_S (READ_PORT_UCHAR((PUCHAR)(LP_B+1))) +#define LP_C (LP_B+2) + +static void Parallel_Reset(void) +/* + * FUNCTION: Resets the device attached to the parallel port + */ +{ + int i; + + WRITE_PORT_UCHAR((PUCHAR)LP_C,0); + for (i=0;iMajorFunction) + { + case IRP_MJ_CREATE: + DPRINT("(Parallel Port Driver) Creating\n"); + Parallel_Reset(); + status = STATUS_SUCCESS; + break; + + case IRP_MJ_CLOSE: + status = STATUS_SUCCESS; + break; + + case IRP_MJ_WRITE: + DPRINT("(Parallel Port Driver) Writing %d bytes\n", + Stack->Parameters.Write.Length); + for (i=0;iParameters.Write.Length;i++) + { + Parallel_putchar(((char *)Irp->UserBuffer)[i]); + } + status = STATUS_SUCCESS; + break; + + default: + status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(status); +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Parallel"); + NTSTATUS Status; + + DPRINT("Parallel Port Driver 0.0.1\n"); + + Status = IoCreateDevice(DriverObject, + 0, + &DeviceName, + FILE_DEVICE_PARALLEL_PORT, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DeviceObject->Flags=0; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_CREATE] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch; + DriverObject->DriverUnload = NULL; + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/dd/parallel/parallel.h b/drivers/dd/parallel/parallel.h new file mode 100644 index 0000000..7b45c41 --- /dev/null +++ b/drivers/dd/parallel/parallel.h @@ -0,0 +1,137 @@ +#ifndef _LINUX_LP_H +#define _LINUX_LP_H + +/* + * usr/include/linux/lp.h c.1991-1992 James Wiegand + * many modifications copyright (C) 1992 Michael K. Johnson + * Interrupt support added 1993 Nigel Gamble + */ + +/* + * Per POSIX guidelines, this module reserves the LP and lp prefixes + * These are the lp_table[minor].flags flags... + */ +#define LP_EXIST 0x0001 +#define LP_SELEC 0x0002 +#define LP_BUSY 0x0004 +#define LP_OFFL 0x0008 +#define LP_NOPA 0x0010 +#define LP_ERR 0x0020 +#define LP_ABORT 0x0040 +#define LP_CAREFUL 0x0080 +#define LP_ABORTOPEN 0x0100 + +/* timeout for each character. This is relative to bus cycles -- it + * is the count in a busy loop. THIS IS THE VALUE TO CHANGE if you + * have extremely slow printing, or if the machine seems to slow down + * a lot when you print. If you have slow printing, increase this + * number and recompile, and if your system gets bogged down, decrease + * this number. This can be changed with the tunelp(8) command as well. + */ + +#define LP_INIT_CHAR 1000 + +/* The parallel port specs apparently say that there needs to be + * a .5usec wait before and after the strobe. Since there are wildly + * different computers running linux, I can't come up with a perfect + * value, but since it worked well on most printers before without, + * I'll initialize it to 0. + */ + +#define LP_INIT_WAIT 0 + +/* This is the amount of time that the driver waits for the printer to + * catch up when the printer's buffer appears to be filled. If you + * want to tune this and have a fast printer (i.e. HPIIIP), decrease + * this number, and if you have a slow printer, increase this number. + * This is in hundredths of a second, the default 2 being .05 second. + * Or use the tunelp(8) command, which is especially nice if you want + * change back and forth between character and graphics printing, which + * are wildly different... + */ + +#define LP_INIT_TIME 2 + +/* IOCTL numbers */ +#define LPCHAR 0x0601 /* corresponds to LP_INIT_CHAR */ +#define LPTIME 0x0602 /* corresponds to LP_INIT_TIME */ +#define LPABORT 0x0604 /* call with TRUE arg to abort on error, + FALSE to retry. Default is retry. */ +#define LPSETIRQ 0x0605 /* call with new IRQ number, + or 0 for polling (no IRQ) */ +#define LPGETIRQ 0x0606 /* get the current IRQ number */ +#define LPWAIT 0x0608 /* corresponds to LP_INIT_WAIT */ +#define LPCAREFUL 0x0609 /* call with TRUE arg to require out-of-paper, off- + line, and error indicators good on all writes, + FALSE to ignore them. Default is ignore. */ +#define LPABORTOPEN 0x060a /* call with TRUE arg to abort open() on error, + FALSE to ignore error. Default is ignore. */ +#define LPGETSTATUS 0x060b /* return LP_S(minor) */ +#define LPRESET 0x060c /* reset printer */ + +/* timeout for print'ing a timeout, in jiffies (100ths of a second). + This is also used for re-checking error conditions if LP_ABORT is + not set. This is the default behavior. */ + +#define LP_TIMEOUT_INTERRUPT (60 * HZ) +#define LP_TIMEOUT_POLLED (10 * HZ) + +#if 0 +#define LP_B(minor) lp_table[(minor)].base /* IO address */ +#define LP_F(minor) lp_table[(minor)].flags /* flags for busy, etc. */ +#define LP_S(minor) inb_p(LP_B((minor)) + 1) /* status port */ +#define LP_C(minor) (lp_table[(minor)].base + 2) /* control port */ +#define LP_CHAR(minor) lp_table[(minor)].chars /* busy timeout */ +#define LP_TIME(minor) lp_table[(minor)].time /* wait time */ +#define LP_WAIT(minor) lp_table[(minor)].wait /* strobe wait */ +#define LP_IRQ(minor) lp_table[(minor)].irq /* interrupt # */ + /* 0 means polled */ +#endif + +#define LP_BUFFER_SIZE 256 + + +/* + * The following constants describe the various signals of the printer port + * hardware. Note that the hardware inverts some signals and that some + * signals are active low. An example is LP_STROBE, which must be programmed + * with 1 for being active and 0 for being inactive, because the strobe signal + * gets inverted, but it is also active low. + */ + +/* + * bit defines for 8255 status port + * base + 1 + * accessed with LP_S(minor), which gets the byte... + */ +#define LP_PBUSY 0x80 /* inverted input, active high */ +#define LP_PACK 0x40 /* unchanged input, active low */ +#define LP_POUTPA 0x20 /* unchanged input, active high */ +#define LP_PSELECD 0x10 /* unchanged input, active high */ +#define LP_PERRORP 0x08 /* unchanged input, active low */ + +/* + * defines for 8255 control port + * base + 2 + * accessed with LP_C(minor) + */ +#define LP_PINTEN 0x10 +#define LP_PSELECP 0x08 /* inverted output, active low */ +#define LP_PINITP 0x04 /* unchanged output, active low */ +#define LP_PAUTOLF 0x02 /* inverted output, active low */ +#define LP_PSTROBE 0x01 /* inverted output, active low */ + +/* + * the value written to ports to test existence. PC-style ports will + * return the value written. AT-style ports will return 0. so why not + * make them the same ? + */ +#define LP_DUMMY 0x00 + +/* + * This is the port delay time. Your mileage may vary. + * It is used only in the lp_init() routine. + */ +#define LP_DELAY 150000 + +#endif diff --git a/drivers/dd/parallel/parallel.rc b/drivers/dd/parallel/parallel.rc new file mode 100644 index 0000000..b0e6298 --- /dev/null +++ b/drivers/dd/parallel/parallel.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Parallel Port Device Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "parallel\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "parallel.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/ramdrv/.cvsignore b/drivers/dd/ramdrv/.cvsignore new file mode 100644 index 0000000..b4046bc --- /dev/null +++ b/drivers/dd/ramdrv/.cvsignore @@ -0,0 +1,7 @@ +base.tmp +junk.tmp +temp.exp +ramdrv.coff +ramdrv.sys +ramdrv.sys.unstripped + diff --git a/drivers/dd/ramdrv/makefile b/drivers/dd/ramdrv/makefile new file mode 100644 index 0000000..4093d47 --- /dev/null +++ b/drivers/dd/ramdrv/makefile @@ -0,0 +1,21 @@ +# $Id$ + +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = ramdrv + +TARGET_OBJECTS = ramdrv.o + +TARGET_DDKLIBS = unbzip2.a + +TARGET_NORC = yes + +TARGET_CFLAGS=-I../../../ntoskrnl/include -g + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/ramdrv/ramdrv.c b/drivers/dd/ramdrv/ramdrv.c new file mode 100644 index 0000000..1219ae3 --- /dev/null +++ b/drivers/dd/ramdrv/ramdrv.c @@ -0,0 +1,242 @@ +#include +#include "ramdrv.h" +#include +#include "../../lib/bzip2/bzlib.h" + +NTSTATUS STDCALL RamdrvDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + ULONG ControlCode, InputLength, OutputLength; + NTSTATUS Status; + + DPRINT("RamdrvDispatchDeviceControl\n"); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + switch (ControlCode) + { + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + if (OutputLength < sizeof(DISK_GEOMETRY)) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PDISK_GEOMETRY Geometry = Irp->AssociatedIrp.SystemBuffer; + Geometry->MediaType = F3_1Pt44_512; + Geometry->Cylinders.QuadPart = 80; + Geometry->TracksPerCylinder = 2 * 18; + Geometry->SectorsPerTrack = 18; + Geometry->BytesPerSector = 512; + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); + } + break; + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + return Status; +} + +NTSTATUS STDCALL RamdrvDispatchReadWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PRAMDRV_DEVICE_EXTENSION devext = (PRAMDRV_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( Irp ); + + if( Stk->Parameters.Read.ByteOffset.u.HighPart || + Stk->Parameters.Read.ByteOffset.u.LowPart >= devext->Size ) + { + Irp->IoStatus.Status = STATUS_END_OF_FILE; + Irp->IoStatus.Information = 0; + IoCompleteRequest( Irp, 0 ); + return STATUS_END_OF_FILE; + } + if( (Stk->Parameters.Read.ByteOffset.u.LowPart + Stk->Parameters.Read.Length) > devext->Size ) + Stk->Parameters.Read.Length = devext->Size - Stk->Parameters.Read.ByteOffset.u.LowPart; + if( Stk->MajorFunction == IRP_MJ_READ ) + RtlCopyMemory( MmGetSystemAddressForMdl( Irp->MdlAddress ), + devext->Buffer + Stk->Parameters.Read.ByteOffset.u.LowPart, + Stk->Parameters.Read.Length ); + else RtlCopyMemory( devext->Buffer + Stk->Parameters.Read.ByteOffset.u.LowPart, + MmGetSystemAddressForMdl( Irp->MdlAddress ), + Stk->Parameters.Read.Length ); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Stk->Parameters.Read.Length; + IoCompleteRequest( Irp, 0 ); + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL RamdrvDispatchOpenClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("RamdrvDispatchOpenClose\n"); + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Ramdisk"); + NTSTATUS Status; + PDEVICE_OBJECT DeviceObject; + PRAMDRV_DEVICE_EXTENSION devext; + UNICODE_STRING LinkName; + HANDLE file; + OBJECT_ATTRIBUTES objattr; + IO_STATUS_BLOCK iosb; + LARGE_INTEGER allocsize; + HANDLE event; + void *tbuff; + unsigned int dstlen = 1024 * 1440; + FILE_STANDARD_INFORMATION finfo; + DWORD err; + + DPRINT("Ramdisk driver\n"); + + /* Export other driver entry points... */ + DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdrvDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdrvDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_READ] = RamdrvDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdrvDispatchReadWrite; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdrvDispatchDeviceControl; + + + // create device and symbolic link + Status = IoCreateDevice( DriverObject, + sizeof( RAMDRV_DEVICE_EXTENSION ), + &DeviceName, + FILE_DEVICE_DISK, + 0, + FALSE, + &DeviceObject ); + if( !NT_SUCCESS( Status ) ) + return Status; + DeviceObject->Flags |= DO_DIRECT_IO; + devext = (PRAMDRV_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + devext->Size = 1440 * 1024; + devext->Buffer = ExAllocatePool( PagedPool, devext->Size ); + if( !devext->Buffer ) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleandevice; + } + RtlInitUnicodeStringFromLiteral( &LinkName, L"\\??\\Z:" ); + IoCreateSymbolicLink( &LinkName, &DeviceName ); + + RtlInitUnicodeStringFromLiteral( &LinkName, L"\\Device\\Floppy0\\ramdisk.bz2" ); + InitializeObjectAttributes( &objattr, + &LinkName, + 0, + 0, + 0 ); + allocsize.u.LowPart = allocsize.u.HighPart = 0; + + Status = NtOpenFile( &file, + GENERIC_READ, + &objattr, + &iosb, + FILE_SHARE_READ, + FILE_NO_INTERMEDIATE_BUFFERING ); + + if( !NT_SUCCESS( Status ) ) + { + DPRINT( "Failed to open floppy\n" ); + goto cleanbuffer; + } + + InitializeObjectAttributes( &objattr, + 0, + 0, + 0, + 0 ); + Status = NtCreateEvent( &event, + 0, + &objattr, + TRUE, + FALSE ); + if( !NT_SUCCESS( Status ) ) + { + DPRINT( "Failed to create event\n" ); + goto cleanfile; + } + + Status = NtQueryInformationFile( file, + &iosb, + &finfo, + sizeof( finfo ), + FileStandardInformation ); + + if( !NT_SUCCESS( Status ) ) + { + DPRINT1( "Failed to query file information\n" ); + goto cleanevent; + } + tbuff = ExAllocatePool( PagedPool, finfo.EndOfFile.u.LowPart ); + if( !tbuff ) + { + DPRINT1( "Failed to allocate buffer of size %d\n", finfo.EndOfFile.u.LowPart ); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanevent; + } + + Status = NtReadFile( file, + event, + 0, + 0, + &iosb, + tbuff, + finfo.EndOfFile.u.LowPart, + &allocsize, + 0 ); + + if( !NT_SUCCESS( Status ) ) + { + DPRINT( "Failed to read floppy\n" ); + goto cleantbuff; + } + Status = NtWaitForSingleObject( event, FALSE, 0 ); + if( Status != STATUS_WAIT_0 || !NT_SUCCESS( iosb.Status ) ) + { + DPRINT( "Failed to read floppy\n" ); + goto cleantbuff; + } + DPRINT( "RAMDRV: Read in %d bytes, decompressing now\n", iosb.Information ); + err = BZ2_bzBuffToBuffDecompress( devext->Buffer, + &dstlen, + tbuff, + iosb.Information, + 1, + 0 ); + if( err == 0 ) + { + DPRINT( "RAMDRV: Image Decompressed\n"); + } + else DbgPrint( "RAMDRV: Failed to decomparess image, error: %d\n", err ); + ExFreePool( tbuff ); + NtClose( file ); + NtClose( event ); + return STATUS_SUCCESS; + + cleantbuff: + ExFreePool( tbuff ); + cleanevent: + NtClose( event ); + cleanfile: + NtClose( file ); + cleanbuffer: + ExFreePool( devext->Buffer ); + + cleandevice: + IoDeleteDevice( DeviceObject ); + for(;;); + + return Status; +} + diff --git a/drivers/dd/ramdrv/ramdrv.h b/drivers/dd/ramdrv/ramdrv.h new file mode 100644 index 0000000..554a21e --- /dev/null +++ b/drivers/dd/ramdrv/ramdrv.h @@ -0,0 +1,5 @@ +typedef struct _RAMDRV_DEVICE_EXTENSION { + void *Buffer; + unsigned long Size; +} RAMDRV_DEVICE_EXTENSION, *PRAMDRV_DEVICE_EXTENSION; + diff --git a/drivers/dd/sdisk/makefile b/drivers/dd/sdisk/makefile new file mode 100644 index 0000000..ed9697b --- /dev/null +++ b/drivers/dd/sdisk/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = sdisk + +TARGET_OBJECTS = sdisk.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/sdisk/sdisk.c b/drivers/dd/sdisk/sdisk.c new file mode 100644 index 0000000..c077f2d --- /dev/null +++ b/drivers/dd/sdisk/sdisk.c @@ -0,0 +1,162 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/sdisk/sdisk.c + * PURPOSE: Disk driver for Bochs + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES ****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS **************************************************************/ + +#define PORT (0x3ec) + +static VOID SdWriteOffset(ULONG Offset) +{ + outl_p(PORT,Offset); +} + +NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + int i; + PCH Buffer; + ULONG Length; + ULONG Information = 0; + + switch (Stack->MajorFunction) + { + case IRP_MJ_CREATE: + DPRINT("Creating\n",0); + status = STATUS_SUCCESS; + break; + + case IRP_MJ_CLOSE: + status = STATUS_SUCCESS; + break; + + case IRP_MJ_WRITE: + DPRINT("Writing %d bytes\n", + Stack->Parameters.Write.Length); + Length = Stack->Parameters.Write.Length; + if ((Length%512)>0) + { + Length = Length - (Length%512); + } + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + DPRINT("Buffer %x\n",Buffer); + #if 0 + for (i=0;iParameters.Write.ByteOffset.LowPart+i); + SdWriteOffset(Stack->Parameters.Write.ByteOffset.LowPart+i); + } + outb_p(PORT,Buffer[i]); + DbgPrint("%c",Buffer[i]); + } + #endif + for (i=0;i<(Length/512);i++) + { + DPRINT("Offset %x\n", + Stack->Parameters.Write.ByteOffset.LowPart+i); + SdWriteOffset(Stack->Parameters.Write.ByteOffset.LowPart+i); + outsb(PORT,Buffer,512); + } + status = STATUS_SUCCESS; + Information = Length; + break; + + case IRP_MJ_READ: + DPRINT("Reading %d bytes\n", + Stack->Parameters.Write.Length); + Length = Stack->Parameters.Write.Length; + if ((Length%512)>0) + { + Length = Length - (Length%512); + } + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + for (i=0;iParameters.Write.ByteOffset.LowPart+i); + SdWriteOffset(Stack->Parameters.Write.ByteOffset.LowPart+i); + } + Buffer[i]=inb_p(PORT); + } + status = STATUS_SUCCESS; + break; + + default: + status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = Information; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(status); +} + +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS ret; + ANSI_STRING astr; + UNICODE_STRING ustr; + ANSI_STRING asymlink; + UNICODE_STRING usymlink; + + DbgPrint("Simple Disk Driver 0.0.1\n"); + + RtlInitAnsiString(&astr,"\\Device\\SDisk"); + RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE); + ret = IoCreateDevice(DriverObject,0,&ustr, + FILE_DEVICE_DISK,0,FALSE,&DeviceObject); + if (ret!=STATUS_SUCCESS) + { + return(ret); + } + + RtlInitAnsiString(&asymlink,"\\??\\C:"); + RtlAnsiStringToUnicodeString(&usymlink,&asymlink,TRUE); + IoCreateSymbolicLink(&usymlink,&ustr); + + DeviceObject->Flags=DO_DIRECT_IO; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_CREATE] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_READ] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch; + DriverObject->DriverUnload = NULL; + + return(STATUS_SUCCESS); +} + diff --git a/drivers/dd/serial/.cvsignore b/drivers/dd/serial/.cvsignore new file mode 100644 index 0000000..9948aa6 --- /dev/null +++ b/drivers/dd/serial/.cvsignore @@ -0,0 +1,8 @@ +base.tmp +junk.tmp +temp.exp +*.o +serial.coff +serial.sys +serial.sym +serial.nostrip.sys diff --git a/drivers/dd/serial/makefile b/drivers/dd/serial/makefile new file mode 100644 index 0000000..a61a4e5 --- /dev/null +++ b/drivers/dd/serial/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = serial + +TARGET_OBJECTS = serial.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/serial/serial.c b/drivers/dd/serial/serial.c new file mode 100644 index 0000000..55fac9b --- /dev/null +++ b/drivers/dd/serial/serial.c @@ -0,0 +1,161 @@ +/* $Id$ + * + * Serial driver + * Written by Jason Filby (jasonfilby@yahoo.com) + * For ReactOS (www.reactos.com) + * + */ + +#include +//#include +//#include "../../../ntoskrnl/include/internal/i386/io.h" +//#include "../../../ntoskrnl/include/internal/io.h" + +#define outb_p(a,p) WRITE_PORT_UCHAR((PUCHAR)a,p) +#define outw_p(a,p) WRITE_PORT_USHORT((PUSHORT)a,p) +#define inb_p(p) READ_PORT_UCHAR((PUCHAR)p) + +#define NDEBUG +#include + + +#define COM1 0x3F8 +#define COM2 0x2F8 +#define COM3 0x3E8 +#define COM4 0x2E8 + +#define UART_BAUDRATE 96 // 1200 BPS +#define UART_LCRVAL 0x1b // 0x1b for 8e1 +#define UARY_FCRVAL 0x7 + +int uart_detect(unsigned base) +{ + // Returns 0 if no UART detected + + int olddata=inb_p(base+4); + outb_p(base+4, 0x10); + if ((inb_p(base+6) & 0xf0)) return 0; + return 1; +}; + +int irq_setup(unsigned base) +{ + // Returns -1 if not found -- otherwise returns interrupt level + + char ier, mcr, imrm, imrs, maskm, masks, irqm, irqs; + + __asm("cli"); // disable all CPU interrupts + ier = inb_p(base+1); // read IER + outb_p(base+1,0); // disable all UART ints + while (!(inb_p(base+5)&0x20)); // wait for the THR to be empty + mcr = inb_p(base+4); // read MCR + outb_p(base+4,0x0F); // connect UART to irq line + imrm = inb_p(0x21); // read contents of master ICU mask register + imrs = inb_p(0xA1); // read contents of slave ICU mask register + outb_p(0xA0,0x0A); // next read access to 0xA0 reads out IRR + outb_p(0x20,0x0A); // next read access to 0x20 reads out IRR + outb_p(base+1,2); // let's generate interrupts... + maskm = inb_p(0x20); // this clears all bits except for the one + masks = inb_p(0xA0); // that corresponds to the int + outb_p(base+1,0); // drop the int line + maskm &= ~inb_p(0x20); // this clears all bits except for the one + masks &= ~inb_p(0xA0); // that corresponds to the int + outb_p(base+1,2); // and raise it again just to be sure... + maskm &= inb_p(0x20); // this clears all bits except for the one + masks &= inb_p(0xA0); // that corresponds to the int + outb_p(0xA1,~masks); // now let us unmask this interrupt only + outb_p(0x21,~maskm); + outb_p(0xA0,0x0C); // enter polled mode + outb_p(0x20,0x0C); // that order is important with Pentium/PCI systems + irqs = inb_p(0xA0); // and accept the interrupt + irqm = inb_p(0x20); + inb_p(base+2); // reset transmitter interrupt in UART + outb_p(base+4,mcr); // restore old value of MCR + outb_p(base+1,ier); // restore old value of IER + if (masks) outb_p(0xA0,0x20); // send an EOI to slave + if (maskm) outb_p(0x20,0x20); // send an EOI to master + outb_p(0x21,imrm); // restore old mask register contents + outb_p(0xA1,imrs); + __asm("sti"); + if (irqs&0x80) // slave interrupt occured + return (irqs&0x07)+8; + if (irqm&0x80) // master interrupt occured + return irqm&0x07; + return -1; +}; + +void uart_init(unsigned uart_base) +{ + // Initialize the UART + outb_p(uart_base+3, 0x80); + outw_p(uart_base, UART_BAUDRATE); + outb_p(uart_base+3, UART_LCRVAL); + outb_p(uart_base+4, 0); +}; + +unsigned uart_getchar(unsigned uart_base) +{ + unsigned x; + + x=(inb_p(uart_base+5) & 0x9f) << 8; + if(x & 0x100) x|=((unsigned)inb_p(uart_base)) & 0xff; + return x; +}; + +void InitializeSerial(void) +{ + unsigned comports[4] = { COM1, COM2, COM3, COM4 }; + char *comname[4] = { "COM1", "COM2", "COM3", "COM4" }; + int i, irq_level; + + for (i=0; i<4; i++) + { + if(uart_detect(comports[i])==0) + { + DbgPrint("%s not detected\n", comname[i]); + } else { + uart_init(comports[i]); + irq_level=irq_setup(comports[i]); + if(irq_level==-1) + { + DbgPrint("Warning: IRQ not detected!\n"); + } else { + DbgPrint("%s hooked to interrupt level %d\n", comname[i], irq_level); + }; + }; + }; +}; + +// For testing purposes +void testserial(void) +{ + int i=0; + char testc; + + union { + unsigned val; + char character; + } x; + + DbgPrint("Testing serial input...\n"); + + while(i==0) { + x.val=uart_getchar(COM1); +// if(!x.val) continue; +// if(x.val & 0x100) + + testc=inb_p(COM1); + +// DbgPrint("(%x-%c) %c\n", x.val, x.character, testc); + }; +}; + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + DbgPrint("Serial Driver 0.0.2\n"); +// InitializeSerial(); +// testserial(); + return(STATUS_SUCCESS); +}; + diff --git a/drivers/dd/serial/serial.rc b/drivers/dd/serial/serial.rc new file mode 100644 index 0000000..1b1b9fa --- /dev/null +++ b/drivers/dd/serial/serial.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Serial Port Device Driver\0" + VALUE "FileVersion", "0.0.2\0" + VALUE "InternalName", "serial\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "serial.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/sound/.cvsignore b/drivers/dd/sound/.cvsignore new file mode 100644 index 0000000..ae95121 --- /dev/null +++ b/drivers/dd/sound/.cvsignore @@ -0,0 +1,7 @@ +base.tmp +junk.tmp +temp.exp +sound.coff +sound.sys +sound.sys.unstripped + diff --git a/drivers/dd/sound/dsp.c b/drivers/dd/sound/dsp.c new file mode 100644 index 0000000..f3db1e2 --- /dev/null +++ b/drivers/dd/sound/dsp.c @@ -0,0 +1,77 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/sound/dsp.c + * PURPOSE: Digital Signal Processing ? + * PROGRAMMER: Snatched from ? + * + * UPDATE HISTORY: + * ??/??/??: Created + * 10/23/02: Steven Edwards (Steven_Ed4153@yahoo.com) + * Minor build fix + */ + +#include "dsp.h" +#include "sb16.h" + +/************************************ + * unsigned char read_dsp(void) + * + * Reads the DSP chip + * Arguments: none + * Returns: Byte read + ************************************/ +unsigned char read_dsp(unsigned short base) +{ + while((inb(base+0x0e)&0x80)==0); //Wait until there is something to read + return inb(base+0x0a); +} + +/************************************' + * sb_status detect_dsp(void); + * + * Detects if a SB16 is installed + * Arguments: None + * Returns: Success or failure + ************************************/ +sb_status detect_dsp(SB16* sb16) +{ + for(base=0x200;base<0x280;base+=0x10) //Tries to reset all DSP addresses there is + if(reset_dsp(base)==SB_TRUE) + { + sb16->base=base; + return SB_TRUE; + } + return SB_FALSE; +} + +/************************************** + * sb_status reset_dsp(unsigned short base_address); + * + * Tries to reset a DSP chip + * Arguments: base address + * Returns: Success of failure + **************************************/ +sb_status reset_dsp(unsigned short base_address) +{ + int delay; + + outb(base_address+DSP_RESET_PORT,1); + for(delay=0;delay<0xffff;delay++); + + outb(base_address+DSP_RESET_PORT,0); + for(delay=0;delay<0xffff;delay++); + + if((inb(base_address+DSP_READ_STATUS_PORT)&0x80)==0) return SB_FALSE; + + if(inb(base_address+DSP_READ_DATA_PORT)!=0xAA) return SB_FALSE; + + return SB_TRUE; +} + +void write_dsp(unsigned short base,unsigned char data) +{ + while ((inb(base+DSP_WRITE_PORT) & 0x80) != 0); + outb(base+DSP_WRITE_PORT, data); +} + diff --git a/drivers/dd/sound/dsp.h b/drivers/dd/sound/dsp.h new file mode 100644 index 0000000..8f79320 --- /dev/null +++ b/drivers/dd/sound/dsp.h @@ -0,0 +1,17 @@ +#define SB_TRUE 0 +#define SB_FALSE 1 + +#define DSP_MIXER_ADDRESS_PORT 0x04 +#define DSP_MIXER_DATA_PORT 0x05 +#define DSP_RESET_PORT 0x06 +#define DSP_READ_DATA_PORT 0x0A +#define DSP_WRITE_PORT 0x0C //Same port used for reading status and writing data +#define DSP_READ_STATUS_PORT 0x0E + +typedef unsigned char sb_status; +unsigned short base; +unsigned char irq,dma8,dma16; +unsigned char read_dsp(unsigned short base); +void write_dsp(unsigned short base,unsigned char data); +//sb_status detect_dsp(SB16* sb16); +sb_status reset_dsp(unsigned short base_address); diff --git a/drivers/dd/sound/makefile b/drivers/dd/sound/makefile new file mode 100644 index 0000000..8bae898 --- /dev/null +++ b/drivers/dd/sound/makefile @@ -0,0 +1,33 @@ +# +# +# +PATH_TO_TOP = ../../.. + +TARGET = sound + +OBJECTS = dsp.o mixer.o sb_waveout.o sound.o wave.o + +LIBS = $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.a + +all: $(TARGET).sys $(TARGET).sys.unstripped + +.phony: all + +clean: + - $(RM) *.o *.sym *.coff junk.tmp base.tmp temp.exp $(TARGET).sys $(TARGET).sys.unstripped + +.phony: clean + +install: $(FLOPPY_DIR)/drivers/$(TARGET).sys + +$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys + $(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys + +dist: $(PATH_TO_TOP)/$(DIST_DIR)/drivers/$(TARGET).sys + +$(PATH_TO_TOP)/$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys + $(CP) $(TARGET).sys $(PATH_TO_TOP)/$(DIST_DIR)/drivers/$(TARGET).sys + +$(TARGET).sys $(TARGET).sys.unstripped: $(OBJECTS) $(LIBS) + +include $(PATH_TO_TOP)/rules.mak diff --git a/drivers/dd/sound/mixer.c b/drivers/dd/sound/mixer.c new file mode 100644 index 0000000..a3a249b --- /dev/null +++ b/drivers/dd/sound/mixer.c @@ -0,0 +1,49 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/dd/sound/mixer.c + * PURPOSE: Wave Mixer? + * PROGRAMMER: ? + * + * UPDATE HISTORY: + * ??/??/??: Created + * 10/23/02: Steven Edwards (Steven_Ed4153@yahoo.com) + * Minor build fixes + */ + +#include "dsp.h" +#include "sb16.h" +#include "mixer.h" + +unsigned char read_mixer(unsigned short base,unsigned char reg) +{ + + outb(base+0x04,reg); + return inb(base+0x05); +} + +unsigned char get_irq(SB16* sb16) +{ + unsigned char irq; + irq=(read_mixer(sb16->base,MIXER_INTERRUPT_SETUP_REGISTER)&0x0f); + + if(irq==1) sb16->irq=2; + if(irq==2) sb16->irq=5; + if(irq==4) sb16->irq=7; + if(irq==8) sb16->irq=10; + return 0; +} + +void get_dma(SB16* sb16) +{ + unsigned char hi,lo,result=read_mixer(sb16->base,MIXER_DMA_SETUP_REGISTER); + hi=result&0xE0; + lo=result&0x0B; + if(hi==0x80) sb16->dma16=7; + if(hi==0x40) sb16->dma16=6; + if(hi==0x20) sb16->dma16=5; + + if(lo==0x08) sb16->dma8=3; + if(lo==0x02) sb16->dma8=1; + if(lo==0x01) sb16->dma8=0; +} diff --git a/drivers/dd/sound/mixer.h b/drivers/dd/sound/mixer.h new file mode 100644 index 0000000..564ae35 --- /dev/null +++ b/drivers/dd/sound/mixer.h @@ -0,0 +1,8 @@ +#define MIXER_INTERRUPT_SETUP_REGISTER 0x80 +#define MIXER_DMA_SETUP_REGISTER 0x81 +#define MIXER_INTERRUP_STATUS_REGISTEER 0x82 + +void get_dma(SB16* sb16); +unsigned char read_mixer(unsigned short base,unsigned char reg); +unsigned char get_irq(SB16* sb16); + diff --git a/drivers/dd/sound/sb16.h b/drivers/dd/sound/sb16.h new file mode 100644 index 0000000..822f2d8 --- /dev/null +++ b/drivers/dd/sound/sb16.h @@ -0,0 +1,9 @@ +typedef struct +{ + unsigned short base; + unsigned char irq; + unsigned char dma8; + unsigned char dma16; + unsigned char* buffer; +}SB16; + diff --git a/drivers/dd/sound/sb_waveout.c b/drivers/dd/sound/sb_waveout.c new file mode 100644 index 0000000..826145e --- /dev/null +++ b/drivers/dd/sound/sb_waveout.c @@ -0,0 +1,3 @@ +void write_wave() +{ +} diff --git a/drivers/dd/sound/sound.c b/drivers/dd/sound/sound.c new file mode 100644 index 0000000..cf5befa --- /dev/null +++ b/drivers/dd/sound/sound.c @@ -0,0 +1,124 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: mkernel/modules/sound/sound.c + * PURPOSE: SoundBlaster 16 Driver + * PROGRAMMER: Snatched from David Welch (welch@mcmail.com) + * Modified for Soundblaster by Robert Bergkvist (fragdance@hotmail.com) + * UPDATE HISTORY: + * ??/??/??: Created + * + */ + +/* FUNCTIONS **************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sb16.h" +#include "dsp.h" +#include "mixer.h" +#include "in.h" +#include "wave.h" + + +SB16 sb16; +sb_status sb16_getenvironment(void); + +NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + + switch (Stack->MajorFunction) + { + case IRP_MJ_CREATE: + printk("(SoundBlaster 16 Driver WaveOut) Creating\n"); + reset_dsp(sb16.base); + status = STATUS_SUCCESS; + break; + + case IRP_MJ_CLOSE: + status = STATUS_SUCCESS; + break; + + case IRP_MJ_WRITE: + printk("(SoundBlaster 16 Driver) Writing %d bytes\n",Stack->Parameters.Write.Length); + sb16_play((WAVE_HDR*)Irp->UserBuffer); + status = STATUS_SUCCESS; + break; + + default: + status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(status); +} + +NTSTATUS ModuleEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS ret; + + printk("SoundBlaster 16 Driver 0.0.1\n"); + if(sb16_getenvironment()!=SB_TRUE) + { + printk("Soundblaster 16 not found\n"); + return 0; + } + ret = IoCreateDevice(DriverObject,0,"\\Device\\WaveOut",FILE_DEVICE_WAVE_OUT,0,FALSE,&DeviceObject); + if (ret!=STATUS_SUCCESS) + return(ret); + + DeviceObject->Flags=0; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_CREATE] =Dispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch; + DriverObject->DriverUnload = NULL; + + return(STATUS_SUCCESS); +} + +sb_status sb16_getenvironment(void) +{ + if(detect_dsp(&sb16)!=SB_TRUE) + { + printk("Detect DSP failed!!!\n"); + return SB_FALSE; + } + printk("DSP base address 0x%x\n",sb16.base); + get_irq(&sb16); + printk("IRQ: %d\n",sb16.irq); + get_dma(&sb16); + printk("DMA8: 0x%x DMA16: 0x%x\n",sb16.dma8,sb16.dma16); + return SB_TRUE; +} + +#include "dsp.c" +#include "mixer.c" +#include "wave.c" diff --git a/drivers/dd/sound/wave.c b/drivers/dd/sound/wave.c new file mode 100644 index 0000000..0349be7 --- /dev/null +++ b/drivers/dd/sound/wave.c @@ -0,0 +1,126 @@ +ULONG OldIRQ; +PKINTERRUPT IrqObject; +BOOLEAN DMAOutputISR(PKINTERRUPT Interrupt, PVOID ServiceContext) +{ + printk("interrupt\n"); + return FALSE; +} + +void sb16_play(WAVE_HDR* wave) +{ + unsigned int eflags; + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + PKINTERRUPT IrqObject; + unsigned int mask,newmask; + + unsigned int i; + unsigned int tmp[255]; + i=0; + dump_wav(wave); + do + { + tmp[i++]=get_dma_page(0x0fffff+IDMAP_BASE); + printk("0x%x ",tmp[i-1]); + } + while((tmp[i-1]&0xffff)!=0); + free_page((tmp[0])-IDMAP_BASE,i-1); + sb16.buffer=((unsigned char*)tmp[i-1]); + + /* + * Because this is used by alomost every subsystem including irqs it + * must be atomic. The following code sequence disables interrupts after + * saving the previous state of the interrupt flag + */ + + __asm__("pushf\n\tpop %0\n\tcli\n\t" + : "=m" (eflags) + : ); + + memcpy(sb16.buffer,(&wave->data),wave->dLen); + + + MappedIrq = HalGetInterruptVector(Internal,0,0,8+sb16.irq,&Dirql,&Affinity); + + + + IoConnectInterrupt(&IrqObject,DMAOutputISR,0,NULL,MappedIrq,Dirql,Dirql,0,FALSE,Affinity,FALSE); + + mask=inb(0x21); + newmask=((int)1<dLen); + set_dma_mode(1,DMA_MODE_WRITE); + //outb(0xb,0x49); + //outb(0x3,(wave->dLen)&0xff); + //outb(0x3,((unsigned int)(wave->dLen)>>8)&0xff); + set_dma_addr(sb16.dma8,(unsigned int)sb16.buffer-IDMAP_BASE); + //outb(0x83,(((unsigned int)(sb16.buffer-IDMAP_BASE)>>16))&0xf); + //outb(0x2,((unsigned int)sb16.buffer&0xff)); + //outb(0x2,(((unsigned int)(sb16.buffer-IDMAP_BASE)>>8))&0xff); + enable_dma(sb16.dma8); + //outb(0xa,1); + + write_dsp(sb16.base,0x00D1); + + write_dsp(sb16.base,0x40); + write_dsp(sb16.base,((unsigned char)256-(1000000/wave->nSamplesPerSec))); + + outb(sb16.base + 4, (int) 0xa); + outb(sb16.base + 5, (int) 0x00); + + outb(sb16.base + 4, (int) 4); + outb(sb16.base + 5, (int) 0xFF); + + outb(sb16.base + 4, (int) 0x22); + outb(sb16.base + 5, (int) 0xFF); + + write_dsp(sb16.base,0x14); + write_dsp(sb16.base,(wave->dLen&0x00ff)); + write_dsp(sb16.base,((wave->dLen)&0xff00)>>8); + +// write_dsp(sb16.base,0xc0); +// write_dsp(sb16.base,0x0); +// OldIRQ=HalGetInterruptVector(Internal,0,0,irq+8,&irql,&affinity); +// printk("OldIRQ: 0x%x\n",OldIRQ); + +// status=IoConnectInterrupt(&IrqObject,playRoutine,0,NULL,OldIRQ,irql,irql,0,FALSE,affinity,FALSE); +// if(status!=STATUS_SUCCESS) printk("Couldn't set irq\n"); +// else printk("IRQ set\n"); + +} + +void dump_wav(WAVE_HDR* wave) +{ + printk("wave.rID: %c%c%c%c\n",wave->rID[0],wave->rID[1],wave->rID[2],wave->rID[3]); + printk("wave.rLen: 0x%x\n",wave->rLen); + printk("wave.wID: %c%c%c%c\n",wave->wID[0],wave->wID[1],wave->wID[2],wave->wID[3]); + printk("wave.fID: %c%c%c%c\n",wave->fID[0],wave->fID[1],wave->fID[2],wave->fID[3]); + printk("wave.fLen: 0x%x\n",wave->fLen); + printk("wave.wFormatTag: 0x%x\n",wave->wFormatTag); + printk("wave.nChannels: 0x%x\n",wave->nChannels); + printk("wave.nSamplesPerSec: 0x%x\n",wave->nSamplesPerSec); + printk("wave.nAvgBytesPerSec: 0x%x\n",wave->nAvgBytesPerSec); + printk("wave.nBlockAlign: 0x%x\n",wave->nBlockAlign); + printk("wave.FormatSpecific: 0x%x\n",wave->FormatSpecific); + printk("wave.dID: %c%c%c%c\n",wave->dID[0],wave->dID[1],wave->dID[2],wave->dID[3]); + printk("wave.dLen: 0x%x\n",wave->dLen); +} + +BOOLEAN playRoutine(PKINTERRUPT Interrupt,PVOID ServiceContext) +{ + return FALSE; +} diff --git a/drivers/dd/sound/wave.h b/drivers/dd/sound/wave.h new file mode 100644 index 0000000..e17ddf7 --- /dev/null +++ b/drivers/dd/sound/wave.h @@ -0,0 +1,24 @@ +KIRQL irql; +KAFFINITY affinity; + +typedef struct +{ + unsigned char rID[4] __attribute__((packed)); //4 0 + unsigned int rLen __attribute__((packed)); //4 4 + unsigned char wID[4] __attribute__((packed)); //4 8 + unsigned char fID[4] __attribute__((packed)); //4 12 + unsigned int fLen __attribute__((packed)); //4 16 + unsigned short wFormatTag __attribute__((packed)); //2 18 + unsigned short nChannels __attribute__((packed)); //2 20 + unsigned int nSamplesPerSec __attribute__((packed)); //2 22 + unsigned int nAvgBytesPerSec __attribute__((packed)); //2 24 + unsigned short nBlockAlign __attribute__((packed)); //2 26 + unsigned short FormatSpecific __attribute__((packed)); //2 28 + unsigned char dID[4] __attribute__((packed)); //4 30 + unsigned int dLen __attribute__((packed)); + unsigned char* data; +}WAVE_HDR; + +void sb16_play(WAVE_HDR* wave); +void dump_wav(WAVE_HDR* wave); +BOOLEAN playRoutine(PKINTERRUPT Interrupt,PVOID ServiceContext); diff --git a/drivers/dd/test/.cvsignore b/drivers/dd/test/.cvsignore new file mode 100644 index 0000000..a6f277f --- /dev/null +++ b/drivers/dd/test/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +test.coff +test.sys.unstripped diff --git a/drivers/dd/test/makefile b/drivers/dd/test/makefile new file mode 100644 index 0000000..3fcbdbd --- /dev/null +++ b/drivers/dd/test/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = test + +TARGET_OBJECTS = test.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/test/test.c b/drivers/dd/test/test.c new file mode 100644 index 0000000..85398a1 --- /dev/null +++ b/drivers/dd/test/test.c @@ -0,0 +1,107 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/test/test.c + * PURPOSE: Testing driver + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * ??/??/??: Created + * 18/06/98: Made more NT like + */ + +/* INCLUDES ****************************************************************/ + +#include + +/* FUNCTIONS **************************************************************/ + +#if 0 + +NTSTATUS TestWrite(PIRP Irp, PIO_STACK_LOCATION Stk) +{ + PVOID Address; + + Address = MmGetSystemAddressForMdl(Irp->MdlAddress); + DbgPrint("Asked to write '%s'\n",(PCH)Address); + return(STATUS_SUCCESS); +} + +NTSTATUS TestDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +/* + * FUNCTION: Handles user mode requests + * ARGUMENTS: + * DeviceObject = Device for request + * Irp = I/O request packet describing request + * RETURNS: Success or failure + */ +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + int i; + + switch (Stack->MajorFunction) + { + case IRP_MJ_CREATE: + DbgPrint("(Test Driver) Creating\n"); + status = STATUS_SUCCESS; + break; + + case IRP_MJ_CLOSE: + status = STATUS_SUCCESS; + break; + + case IRP_MJ_WRITE: + DbgPrint("(Test Driver) Writing\n"); + status = TestWrite(Irp,Stack); + break; + + default: + status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(status); +} + +#endif + +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS ret; + ANSI_STRING astr; + UNICODE_STRING ustr; + + DbgPrint("Test Driver 0.0.1\n"); + + #if 0 + RtlInitAnsiString(&astr,"\\Device\\Test"); + RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE); + ret = IoCreateDevice(DriverObject,0,&ustr, + FILE_DEVICE_PARALLEL_PORT,0,FALSE,&DeviceObject); + if (ret!=STATUS_SUCCESS) + { + return(ret); + } + + DeviceObject->Flags=DO_DIRECT_IO; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = TestDispatch; + DriverObject->MajorFunction[IRP_MJ_CREATE] = TestDispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = TestDispatch; + DriverObject->MajorFunction[IRP_MJ_WRITE] = TestDispatch; + DriverObject->DriverUnload = NULL; + #endif + return(STATUS_SUCCESS); +} + diff --git a/drivers/dd/vga/display/.cvsignore b/drivers/dd/vga/display/.cvsignore new file mode 100644 index 0000000..ea9f9c0 --- /dev/null +++ b/drivers/dd/vga/display/.cvsignore @@ -0,0 +1,3 @@ +vgaddi.coff +vgaddi.dll +vgaddi.nostrip.dll \ No newline at end of file diff --git a/drivers/dd/vga/display/main/enable.c b/drivers/dd/vga/display/main/enable.c new file mode 100644 index 0000000..7d7e2d2 --- /dev/null +++ b/drivers/dd/vga/display/main/enable.c @@ -0,0 +1,481 @@ +/* + * entry.c + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include "gdiinfo.h" +#include "../vgavideo/vgavideo.h" +#include + +#define DBG_PREFIX "VGADDI: " + +static BOOL VGAInitialized = FALSE; + +DRVFN FuncList[] = +{ + /* Required Display driver fuctions */ + {INDEX_DrvAssertMode, (PFN) DrvAssertMode}, + {INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV}, + {INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV}, + {INDEX_DrvDisableSurface, (PFN) DrvDisableSurface}, + {INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV}, + {INDEX_DrvEnableSurface, (PFN) DrvEnableSurface}, + {INDEX_DrvGetModes, (PFN) DrvGetModes}, + {INDEX_DrvLineTo, (PFN) DrvLineTo}, + {INDEX_DrvPaint, (PFN) DrvPaint}, + {INDEX_DrvBitBlt, (PFN) DrvBitBlt}, + {INDEX_DrvTransparentBlt, (PFN) DrvTransparentBlt}, + {INDEX_DrvMovePointer, (PFN) DrvMovePointer}, + {INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape}, + +#if 0 + /* Optional Display driver functions */ + {INDEX_, (PFN) }, + {INDEX_DescribePixelFormat, (PFN) VGADDIDescribePixelFormat}, + {INDEX_DrvDitherColor, (PFN) VGADDIDitherColor}, + {INDEX_DrvFillPath, (PFN) VGADDIFillPath}, + {INDEX_DrvGetTrueTypeFile, (PFN) VGADDIGetTrueTypeFile}, + {INDEX_DrvLoadFontFile, (PFN) VGADDILoadFontFile}, + {INDEX_DrvQueryFont, (PFN) VGADDIQueryFont}, + {INDEX_DrvQueryFontCaps, (PFN) VGADDIQueryFontCaps}, + {INDEX_DrvQueryFontData, (PFN) VGADDIQueryFontData}, + {INDEX_DrvQueryFontFile, (PFN) VGADDIQueryFontFile}, + {INDEX_DrvQueryFontTree, (PFN) VGADDIQueryFontTree}, + {INDEX_DrvQueryTrueTypeOutline, (PFN) VGADDIQueryTrueTypeOutline}, + {INDEX_DrvQueryTrueTypeTable, (PFN) VGADDIQueryTrueTypeTable}, + {INDEX_DrvRealizeBrush, (PFN) VGADDIRealizeBrush}, + {INDEX_DrvResetPDEV, (PFN) VGADDIResetPDEV}, + {INDEX_DrvSetPalette, (PFN) VGADDISetPalette}, + {INDEX_DrvSetPixelFormat, (PFN) VGADDISetPixelFormat}, + {INDEX_DrvStretchBlt, (PFN) VGADDIStretchBlt}, + {INDEX_DrvStrokePath, (PFN) VGADDIStrokePath}, + {INDEX_DrvSwapBuffers, (PFN) VGADDISwapBuffers}, + {INDEX_DrvTextOut, (PFN) VGADDITextOut}, + {INDEX_DrvUnloadFontFile, (PFN) VGADDIUnloadFontFile}, +#endif +}; + + +BOOL STDCALL +DrvEnableDriver(IN ULONG EngineVersion, + IN ULONG SizeOfDED, + OUT PDRVENABLEDATA DriveEnableData) +{ + EngDebugPrint("VGADDI", "DrvEnableDriver called...\n", 0); + + vgaPreCalc(); + + // FIXME: Use Vidport to map the memory properly + vidmem = (char *)(0xd0000000 + 0xa0000); + + VGADDI_InitializeOffScreenMem((640 * 480) >> 3, 65536 - ((640 * 480) >> 3)); + + DriveEnableData->pdrvfn = FuncList; + DriveEnableData->c = sizeof(FuncList) / sizeof(DRVFN); + DriveEnableData->iDriverVersion = DDI_DRIVER_VERSION; + + return TRUE; +} + +// DrvDisableDriver +// DESCRIPTION: +// This function is called by the KMGDI at exit. It should cleanup. +// ARGUMENTS: +// NONE +// RETURNS: +// NONE + +VOID STDCALL +DrvDisableDriver(VOID) +{ + return; +} + +// ----------------------------------------------- Driver Implementation + + +// DrvEnablePDEV +// DESCRIPTION: +// This function is called after DrvEnableDriver to get information +// about the mode that is to be used. This function just returns +// information, and should not yet initialize the mode. +// ARGUMENTS: +// IN DEVMODEW * DM Describes the mode requested +// IN LPWSTR LogAddress +// IN ULONG PatternCount number of patterns expected +// OUT HSURF * SurfPatterns array to contain pattern handles +// IN ULONG CapsSize the size of the DevCaps object passed in +// OUT ULONG * DevCaps Device Capabilities object +// IN ULONG DevInfoSize the size of the DevInfo object passed in +// OUT DEVINFO * DI Device Info object +// IN LPWSTR DevDataFile ignore +// IN LPWSTR DeviceName Device name +// IN HANDLE Driver handle to KM driver +// RETURNS: +// DHPDEV a handle to a DPev object + +DHPDEV STDCALL +DrvEnablePDEV(IN DEVMODEW *DM, + IN LPWSTR LogAddress, + IN ULONG PatternCount, + OUT HSURF *SurfPatterns, + IN ULONG CapsSize, + OUT ULONG *DevCaps, + IN ULONG DevInfoSize, + OUT DEVINFO *DI, + IN LPWSTR DevDataFile, + IN LPWSTR DeviceName, + IN HANDLE Driver) +{ + PPDEV PDev; + + PDev = EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV), ALLOC_TAG); + if (PDev == NULL) + { + EngDebugPrint(DBG_PREFIX, "EngAllocMem failed for PDEV\n", 0); + return(NULL); + } + PDev->KMDriver = Driver; + DPRINT( "PDev: %x, Driver: %x\n", PDev, PDev->KMDriver ); + PDev->xyCursor.x = 320; + PDev->xyCursor.y = 240; + PDev->ptlExtent.x = 0; + PDev->ptlExtent.y = 0; + PDev->cExtent = 0; + PDev->flCursor = CURSOR_DOWN; + // FIXME: fill out DevCaps + // FIXME: full out DevInfo + + devinfoVGA.hpalDefault = EngCreatePalette(PAL_INDEXED, 16, (PULONG *)VGApalette.PaletteEntry, 0, 0, 0); +DPRINT("Palette from Driver: %u\n", devinfoVGA.hpalDefault); + *DI = devinfoVGA; +DPRINT("Palette from Driver 2: %u and DI is %08x\n", DI->hpalDefault, DI); + + return(PDev); +} + + +// DrvCompletePDEV +// DESCRIPTION +// Called after initialization of PDEV is complete. Supplies +// a reference to the GDI handle for the PDEV. + +VOID STDCALL +DrvCompletePDEV(IN DHPDEV PDev, + IN HDEV Dev) +{ + ((PPDEV) PDev)->GDIDevHandle = Dev; // Handle to the DC +} + + +BOOL STDCALL +DrvAssertMode(IN DHPDEV DPev, + IN BOOL Enable) +{ + PPDEV ppdev = (PPDEV)DPev; + ULONG returnedDataLength; + + if(Enable==TRUE) + { + // Reenable our graphics mode + + if (!InitPointer(ppdev)) + { + // Failed to set pointer + return FALSE; + } + + if (!VGAInitialized) + { + if (!InitVGA(ppdev, FALSE)) + { + // Failed to initialize the VGA + return FALSE; + } + VGAInitialized = TRUE; + } + } else { + // Go back to last known mode + DPRINT( "ppdev: %x, KMDriver: %x", ppdev, ppdev->KMDriver ); + if (EngDeviceIoControl(ppdev->KMDriver, IOCTL_VIDEO_RESET_DEVICE, NULL, 0, NULL, 0, &returnedDataLength)) + { + // Failed to go back to mode + return FALSE; + } + VGAInitialized = FALSE; + } + +} + + +VOID STDCALL +DrvDisablePDEV(IN DHPDEV PDev) +{ + PPDEV ppdev = (PPDEV)PDev; + + // EngDeletePalette(devinfoVGA.hpalDefault); + if (ppdev->pjPreallocSSBBuffer != NULL) + { + EngFreeMem(ppdev->pjPreallocSSBBuffer); + } + + if (ppdev->pucDIB4ToVGAConvBuffer != NULL) + { + EngFreeMem(ppdev->pucDIB4ToVGAConvBuffer); + } + DPRINT( "Freeing PDEV\n" ); + EngFreeMem(PDev); +} + + +VOID STDCALL +DrvDisableSurface(IN DHPDEV PDev) +{ + PPDEV ppdev = (PPDEV)PDev; + PDEVSURF pdsurf = ppdev->AssociatedSurf; + PSAVED_SCREEN_BITS pSSB, pSSBNext; + CHECKPOINT; + DPRINT( "KMDriver: %x\n", ppdev->KMDriver ); + // EngFreeMem(pdsurf->BankSelectInfo); + CHECKPOINT; + if (pdsurf->BankInfo != NULL) { + EngFreeMem(pdsurf->BankInfo); + } + CHECKPOINT; + if (pdsurf->BankInfo2RW != NULL) { + EngFreeMem(pdsurf->BankInfo2RW); + } + CHECKPOINT; + if (pdsurf->BankBufferPlane0 != NULL) { + EngFreeMem(pdsurf->BankBufferPlane0); + } + CHECKPOINT; + if (ppdev->pPointerAttributes != NULL) { + EngFreeMem(ppdev->pPointerAttributes); + } + CHECKPOINT; + // free any pending saved screen bit blocks +#if 0 + pSSB = pdsurf->ssbList; + while (pSSB != (PSAVED_SCREEN_BITS) NULL) { + + // Point to the next saved screen bits block + pSSBNext = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB; + + // Free the current block + EngFreeMem(pSSB); + pSSB = pSSBNext; + } +#endif + EngDeleteSurface((HSURF) ppdev->SurfHandle); + // EngFreeMem(pdsurf); // free the surface +} + + +static VOID +InitSavedBits(PPDEV ppdev) +{ + if (!(ppdev->fl & DRIVER_OFFSCREEN_REFRESHED)) + { + return; + } + + // set up rect to right of visible screen + ppdev->SavedBitsRight.left = ppdev->sizeSurf.cx; + ppdev->SavedBitsRight.top = 0; + ppdev->SavedBitsRight.right = ppdev->sizeMem.cx-PLANAR_PELS_PER_CPU_ADDRESS; + ppdev->SavedBitsRight.bottom = ppdev->sizeSurf.cy; + + if ((ppdev->SavedBitsRight.right <= ppdev->SavedBitsRight.left) || + (ppdev->SavedBitsRight.bottom <= ppdev->SavedBitsRight.top)) + { + ppdev->SavedBitsRight.left = 0; + ppdev->SavedBitsRight.top = 0; + ppdev->SavedBitsRight.right = 0; + ppdev->SavedBitsRight.bottom = 0; + } + + // set up rect below visible screen + ppdev->SavedBitsBottom.left = 0; + ppdev->SavedBitsBottom.top = ppdev->sizeSurf.cy; + ppdev->SavedBitsBottom.right = ppdev->sizeMem.cx-PLANAR_PELS_PER_CPU_ADDRESS; + ppdev->SavedBitsBottom.bottom = ppdev->sizeMem.cy - ppdev->NumScansUsedByPointer; + + if ((ppdev->SavedBitsBottom.right <= ppdev->SavedBitsBottom.left) || + (ppdev->SavedBitsBottom.bottom <= ppdev->SavedBitsBottom.top)) + { + ppdev->SavedBitsBottom.left = 0; + ppdev->SavedBitsBottom.top = 0; + ppdev->SavedBitsBottom.right = 0; + ppdev->SavedBitsBottom.bottom = 0; + } + + ppdev->BitsSaved = FALSE; + + return; +} + + +HSURF STDCALL +DrvEnableSurface(IN DHPDEV PDev) +{ + PPDEV ppdev = (PPDEV)PDev; + PDEVSURF pdsurf; + DHSURF dhsurf; + HSURF hsurf; + + DPRINT1("DrvEnableSurface() called\n"); + + // Initialize the VGA + if (!VGAInitialized) + { + if (!InitVGA(ppdev, TRUE)) + { + goto error_done; + } + VGAInitialized = TRUE; + } +CHECKPOINT1; + + // dhsurf is of type DEVSURF, which is the drivers specialized surface type + dhsurf = (DHSURF)EngAllocMem(0, sizeof(DEVSURF), ALLOC_TAG); + if (dhsurf == (DHSURF) 0) + { + goto error_done; + } + + pdsurf = (PDEVSURF) dhsurf; + pdsurf->ident = DEVSURF_IDENT; + pdsurf->flSurf = 0; + pdsurf->Format = BMF_PHYSDEVICE; + pdsurf->jReserved1 = 0; + pdsurf->jReserved2 = 0; + pdsurf->ppdev = ppdev; + pdsurf->sizeSurf.cx = ppdev->sizeSurf.cx; + pdsurf->sizeSurf.cy = ppdev->sizeSurf.cy; + pdsurf->NextPlane = 0; + pdsurf->Scan0 = ppdev->fbScreen; + pdsurf->BitmapStart = ppdev->fbScreen; + pdsurf->StartBmp = ppdev->fbScreen; + +/* pdsurf->Conv = &ConvertBuffer[0]; */ + + if (!InitPointer(ppdev)) { + DbgPrint("DrvEnablePDEV failed bInitPointer\n"); + goto error_clean; + } + +/* if (!SetUpBanking(pdsurf, ppdev)) { + DISPDBG((0, "DrvEnablePDEV failed SetUpBanking\n")); + goto error_clean; + } BANKING CODE UNIMPLEMENTED */ + + if ((hsurf = EngCreateDeviceSurface(dhsurf, ppdev->sizeSurf, BMF_4BPP)) == + (HSURF)0) + { + // Call to EngCreateDeviceSurface failed + EngDebugPrint("VGADDI:", "EngCreateDeviceSurface call failed\n", 0); + goto error_clean; + } + + InitSavedBits(ppdev); + + if (EngAssociateSurface(hsurf, ppdev->GDIDevHandle, HOOK_BITBLT | HOOK_PAINT | HOOK_LINETO | HOOK_COPYBITS | + HOOK_TRANSPARENTBLT)) + { + EngDebugPrint("VGADDI:", "Successfully associated surface\n", 0); + ppdev->SurfHandle = hsurf; + ppdev->AssociatedSurf = pdsurf; + + // Set up an empty saved screen block list + pdsurf->ssbList = NULL; + + return(hsurf); + } + DPRINT( "EngAssociateSurface() failed\n" ); + EngDeleteSurface(hsurf); + +error_clean: + EngFreeMem(dhsurf); + +error_done: + return((HSURF)0); +} + + +ULONG STDCALL +DrvGetModes(IN HANDLE Driver, + IN ULONG DataSize, + OUT PDEVMODEW DM) +{ + DWORD NumModes; + DWORD ModeSize; + DWORD OutputSize; + DWORD OutputModes = DataSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + PVIDEO_MODE_INFORMATION VideoModeInformation, VideoTemp; + + NumModes = getAvailableModes(Driver, + (PVIDEO_MODE_INFORMATION *) &VideoModeInformation, + &ModeSize); + + if (NumModes == 0) + { + return 0; + } + + if (DM == NULL) + { + OutputSize = NumModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + } else { + + OutputSize=0; + VideoTemp = VideoModeInformation; + + do + { + if (VideoTemp->Length != 0) + { + if (OutputModes == 0) + { + break; + } + + memset(DM, 0, sizeof(DEVMODEW)); + memcpy(DM->dmDeviceName, DLL_NAME, sizeof(DLL_NAME)); + + DM->dmSpecVersion = DM_SPECVERSION; + DM->dmDriverVersion = DM_SPECVERSION; + DM->dmSize = sizeof(DEVMODEW); + DM->dmDriverExtra = DRIVER_EXTRA_SIZE; + DM->dmBitsPerPel = VideoTemp->NumberOfPlanes * + VideoTemp->BitsPerPlane; + DM->dmPelsWidth = VideoTemp->VisScreenWidth; + DM->dmPelsHeight = VideoTemp->VisScreenHeight; + DM->dmDisplayFrequency = VideoTemp->Frequency; + DM->dmDisplayFlags = 0; + + DM->dmFields = DM_BITSPERPEL | + DM_PELSWIDTH | + DM_PELSHEIGHT | + DM_DISPLAYFREQUENCY | + DM_DISPLAYFLAGS ; + + // next DEVMODE entry + OutputModes--; + + DM = (PDEVMODEW) ( ((ULONG)DM) + sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + + OutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE); + } + + VideoTemp = (PVIDEO_MODE_INFORMATION)(((PUCHAR)VideoTemp) + ModeSize); + + } while (--NumModes); + } +} + +/* EOF */ diff --git a/drivers/dd/vga/display/main/gdiinfo.h b/drivers/dd/vga/display/main/gdiinfo.h new file mode 100644 index 0000000..dc73223 --- /dev/null +++ b/drivers/dd/vga/display/main/gdiinfo.h @@ -0,0 +1,119 @@ +#include "../vgaddi.h" + +GDIINFO gaulCap = { + GDI_DRIVER_VERSION, + DT_RASDISPLAY, // ulTechnology + 0, // ulHorzSize + 0, // ulVertSize + 0, // ulHorzRes (filled in at initialization) + 0, // ulVertRes (filled in at initialization) + 4, // cBitsPixel + 1, // cPlanes + 16, // ulNumColors + 0, // flRaster (DDI reserved field) + + 0, // ulLogPixelsX (filled in at initialization) + 0, // ulLogPixelsY (filled in at initialization) + + TC_RA_ABLE | TC_SCROLLBLT, // flTextCaps + + 6, // ulDACRed + 6, // ulDACGree + 6, // ulDACBlue + + 0x0024, // ulAspectX (one-to-one aspect ratio) + 0x0024, // ulAspectY + 0x0033, // ulAspectXY + + 1, // xStyleStep + 1, // yStyleSte; + 3, // denStyleStep + + { 0, 0 }, // ptlPhysOffset + { 0, 0 }, // szlPhysSize + + 0, // ulNumPalReg (win3.1 16 color drivers say 0 too) + +// These fields are for halftone initialization. + + { // ciDevice, ColorInfo + { 6700, 3300, 0 }, // Red + { 2100, 7100, 0 }, // Green + { 1400, 800, 0 }, // Blue + { 1750, 3950, 0 }, // Cyan + { 4050, 2050, 0 }, // Magenta + { 4400, 5200, 0 }, // Yellow + { 3127, 3290, 0 }, // AlignmentWhite + 20000, // RedGamma + 20000, // GreenGamma + 20000, // BlueGamma + 0, 0, 0, 0, 0, 0 + }, + + 0, // ulDevicePelsDPI + PRIMARY_ORDER_CBA, // ulPrimaryOrder + HT_PATSIZE_4x4_M, // ulHTPatternSize + HT_FORMAT_4BPP_IRGB, // ulHTOutputFormat + HT_FLAG_ADDITIVE_PRIMS, // flHTFlags + + 0, // ulVRefresh + 8, // ulBltAlignment + 0, // ulPanningHorzRes + 0, // ulPanningVertRes +}; + +// Palette for VGA + +typedef struct _VGALOGPALETTE +{ + USHORT ident; + USHORT NumEntries; + PALETTEENTRY PaletteEntry[16]; +} VGALOGPALETTE; + +const VGALOGPALETTE VGApalette = +{ + +0x400, // driver version +16, // num entries +{ + { 0x00, 0x00, 0x00, 0x00 }, // 0 + { 0x80, 0x00, 0x00, 0x00 }, // 1 + { 0x00, 0x80, 0x00, 0x00 }, // 2 + { 0x80, 0x80, 0x00, 0x00 }, // 3 + { 0x00, 0x00, 0x80, 0x00 }, // 4 + { 0x80, 0x00, 0x80, 0x00 }, // 5 + { 0x00, 0x80, 0x80, 0x00 }, // 6 + { 0x80, 0x80, 0x80, 0x00 }, // 7 + { 0xc0, 0xc0, 0xc0, 0x00 }, // 8 + { 0xff, 0x00, 0x00, 0x00 }, // 9 + { 0x00, 0xff, 0x00, 0x00 }, // 10 + { 0xff, 0xff, 0x00, 0x00 }, // 11 + { 0x00, 0x00, 0xff, 0x00 }, // 12 + { 0xff, 0x00, 0xff, 0x00 }, // 13 + { 0x00, 0xff, 0xff, 0x00 }, // 14 + { 0xff, 0xff, 0xff, 0x00 } // 15 +} +}; + +// Devinfo structure passed back to the engine in DrvEnablePDEV + +#define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_DONTCARE, L"System"} +#define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,VARIABLE_PITCH | FF_DONTCARE, L"MS Sans Serif"} +#define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_DONTCARE, L"Courier"} + +DEVINFO devinfoVGA = +{ + (GCAPS_OPAQUERECT | GCAPS_HORIZSTRIKE | GCAPS_ALTERNATEFILL | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER | + GCAPS_WINDINGFILL | GCAPS_DITHERONREALIZE + ), // Graphics capabilities + + SYSTM_LOGFONT, // Default font description + HELVE_LOGFONT, // ANSI variable font description + COURI_LOGFONT, // ANSI fixed font description + 0, // Count of device fonts + BMF_4BPP, // preferred DIB format + 8, // Width of color dither + 8, // Height of color dither + 0 // Default palette to use for this device +}; diff --git a/drivers/dd/vga/display/makefile b/drivers/dd/vga/display/makefile new file mode 100644 index 0000000..8babf88 --- /dev/null +++ b/drivers/dd/vga/display/makefile @@ -0,0 +1,40 @@ +# $Id$ + +PATH_TO_TOP = ../../../.. + +TARGET_BASE = 0x70000000 + +TARGET_TYPE = gdi_driver + +TARGET_NAME = vgaddi + +MAIN_OBJECTS = \ + main/enable.o + +OTHER_OBJECTS = \ + objects/screen.o \ + objects/pointer.o \ + objects/lineto.o \ + objects/paint.o \ + objects/bitblt.o \ + objects/transblt.o \ + objects/offscreen.o + +VGAVIDEO_OBJECTS = \ + vgavideo/vgavideo.o + +TARGET_OBJECTS = \ + $(MAIN_OBJECTS) \ + $(OTHER_OBJECTS) \ + $(VGAVIDEO_OBJECTS) + +TARGET_CLEAN = \ + main/*.o \ + objects/*.o \ + vgavideo/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/dd/vga/display/objects/bitblt.c b/drivers/dd/vga/display/objects/bitblt.c new file mode 100644 index 0000000..963b66b --- /dev/null +++ b/drivers/dd/vga/display/objects/bitblt.c @@ -0,0 +1,382 @@ +#include +#define NDEBUG +#include +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include "brush.h" +#include "bitblt.h" + +typedef BOOL (*PFN_VGABlt)(SURFOBJ*, SURFOBJ*, XLATEOBJ*, RECTL*, POINTL*); + +BOOL +DIBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + LONG i, j, dx, dy, alterx, altery, idxColor, RGBulong = 0, c8; + BYTE *GDIpos, *initial, *tMask, *lMask; + + GDIpos = Source->pvBits; + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + alterx = abs(SourcePoint->x - DestRect->left); + altery = abs(SourcePoint->y - DestRect->top); + + if (ColorTranslation == NULL) + { + DIB_BltToVGA(DestRect->left, DestRect->top, dx, dy, Source->pvBits, + Source->lDelta); + } + else + { + /* Perform color translation */ + for (j = SourcePoint->y; j < SourcePoint->y+dy; j++) + { + initial = GDIpos; + + for (i=SourcePoint->x; ix+dx; i++) + { + idxColor = XLATEOBJ_iXlate(ColorTranslation, *GDIpos); + vgaPutPixel(i+alterx, j+altery, idxColor); + GDIpos+=1; + } + GDIpos = initial + Source->lDelta; + } + } +} + +BOOL +VGAtoDIB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + LONG i, j, dx, dy, RGBulong; + BYTE *GDIpos, *initial, idxColor; + + // Used by the temporary DFB + PDEVSURF TargetSurf; + DEVSURF DestDevSurf; + PSURFOBJ TargetBitmapSurf; + HBITMAP hTargetBitmap; + SIZEL InterSize; + POINTL ZeroPoint; + + // FIXME: Optimize to retrieve entire bytes at a time (see /display/vgavideo/vgavideo.c:vgaGetByte) + + GDIpos = Dest->pvBits /* + (DestRect->top * Dest->lDelta) + (DestRect->left >> 1) */ ; + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if(ColorTranslation == NULL) + { + // Prepare a Dest Dev Target and copy from the DFB to the DIB + DestDevSurf.NextScan = Dest->lDelta; + DestDevSurf.StartBmp = Dest->pvScan0; + + DIB_BltFromVGA(SourcePoint->x, SourcePoint->y, dx, dy, Dest->pvBits, Dest->lDelta); + + } else { + // Color translation + for(j=SourcePoint->y; jy+dy; j++) + { + initial = GDIpos; + for(i=SourcePoint->x; ix+dx; i++) + { + *GDIpos = XLATEOBJ_iXlate(ColorTranslation, vgaGetPixel(i, j)); + GDIpos+=1; + } + GDIpos = initial + Dest->lDelta; + } + } +} + +BOOL +DFBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + // Do DFBs need color translation?? +} + +BOOL +VGAtoDFB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + // Do DFBs need color translation?? +} + +BOOL +VGAtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + // FIXME: Use fast blts instead of get and putpixels + + int i, j, dx, dy, alterx, altery, BltDirection; + + // Calculate deltas + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + alterx = abs(SourcePoint->x - DestRect->left); + altery = abs(SourcePoint->y - DestRect->top); + + // Determine bltting direction + // FIXME: should we perhaps make this an EngXxx function? Determining + // direction is probably used whenever the surfaces are the same (not + // just VGA screen) + if (SourcePoint->y >= DestRect->top) + { + if (SourcePoint->x >= DestRect->left) + { + BltDirection = CD_RIGHTDOWN; + } + else + { + BltDirection = CD_LEFTDOWN; + } + } + else + { + if (SourcePoint->x >= DestRect->left) + { + BltDirection = CD_RIGHTUP; + } + else + { + BltDirection = CD_LEFTUP; + } + } + + // Do the VGA to VGA BitBlt + // FIXME: Right now we're only doing CN_LEFTDOWN and we're using slow + // get and put pixel routines + + for(j=SourcePoint->y; jy+dy; j++) + { + for(i=SourcePoint->x; ix+dx; i++) + { + vgaPutPixel(i+alterx, j+altery, vgaGetPixel(i, j)); + } + } + + return TRUE; +} + +BOOL STDCALL +VGADDI_BltBrush(SURFOBJ* Dest, XLATEOBJ* ColorTranslation, RECTL* DestRect, + BRUSHOBJ* Brush, POINTL* BrushPoint, ROP4 Rop4) +{ + UCHAR SolidColor; + ULONG Left; + ULONG Right; + ULONG Length; + PUCHAR Video; + UCHAR Mask; + ULONG i, j; + + /* Punt brush blts to non-device surfaces. */ + if (Dest->iType != STYPE_DEVICE) + { + return(FALSE); + } + + /* Punt pattern fills. */ + if (Rop4 == PATCOPY && Brush->iSolidColor == 0xFFFFFFFF) + { + return(FALSE); + } + if (Rop4 == PATCOPY) + { + SolidColor = Brush->iSolidColor; + } + else if (Rop4 == WHITENESS) + { + SolidColor = 1; + } + else + { + SolidColor = 0; + } + + /* Fill any pixels on the left which don't fall into a full row of eight. */ + if ((DestRect->left % 8) != 0) + { + /* Disable writes to pixels outside of the destination rectangle. */ + Mask = (1 << (8 - (DestRect->left % 8))) - 1; + if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8))) + { + Mask &= ~((1 << (8 - (DestRect->right % 8))) - 1); + } + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask); + + /* Write the same color to each pixel. */ + Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->left >> 3); + for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80) + { + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SolidColor); + } + } + + /* Enable writes to all pixels. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + + /* Have we finished. */ + if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8))) + { + return(TRUE); + } + + /* Fill any whole rows of eight pixels. */ + Left = (DestRect->left + 7) & ~0x7; + Length = (DestRect->right >> 3) - (Left >> 3); + for (i = DestRect->top; i < DestRect->bottom; i++) + { + Video = (PUCHAR)vidmem + i * 80 + (Left >> 3); + for (j = 0; j < Length; j++, Video++) + { + WRITE_REGISTER_UCHAR(Video, SolidColor); + } + } + + /* Fill any pixels on the right which don't fall into a complete row. */ + if ((DestRect->right % 8) != 0) + { + /* Disable writes to pixels outside the destination rectangle. */ + Mask = ~((1 << (8 - (DestRect->right % 8))) - 1); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask); + + Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->right >> 3); + for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80) + { + /* Read the existing colours for this pixel into the latches. */ + (VOID)READ_REGISTER_UCHAR(Video); + /* Write the new colour for the pixels selected in the mask. */ + WRITE_REGISTER_UCHAR(Video, SolidColor); + } + + /* Restore the default write masks. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + } + return(TRUE); +} + +BOOL STDCALL +VGADDI_BltSrc(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint) +{ + RECT_ENUM RectEnum; + BOOL EnumMore; + PFN_VGABlt BltOperation; + ULONG SourceType; + + SourceType = Source->iType; + + if (SourceType == STYPE_BITMAP && Dest->iType == STYPE_DEVICE) + { + BltOperation = DIBtoVGA; + } + else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_BITMAP) + { + BltOperation = VGAtoDIB; + } + else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVICE) + { + BltOperation = VGAtoVGA; + } + else if (SourceType == STYPE_DEVBITMAP && Dest->iType == STYPE_DEVICE) + { + BltOperation = DFBtoVGA; + } + else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVBITMAP) + { + BltOperation = VGAtoDFB; + } + else + { + /* Punt blts not involving a device or a device-bitmap. */ + return(FALSE); + } + + BltOperation(Dest, Source, ColorTranslation, DestRect, SourcePoint); + return(TRUE); +} + +BOOL STDCALL +VGADDI_BltMask(SURFOBJ *Dest, SURFOBJ *Mask, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush, + POINTL* BrushPoint) +{ + LONG i, j, dx, dy, idxColor, RGBulong = 0, c8; + BYTE *initial, *tMask, *lMask; + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if (ColorTranslation == NULL) + { + if (Mask != NULL) + { + tMask = Mask->pvBits; + for (j=0; jleft + i, DestRect->top + j, Brush->iSolidColor); + } + c8++; + if(c8 == 8) { lMask++; c8=0; } + } + tMask += Mask->lDelta; + } + } + } +} + +BOOL STDCALL +DrvBitBlt(SURFOBJ *Dest, + SURFOBJ *Source, + SURFOBJ *Mask, + CLIPOBJ *Clip, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint, + POINTL *MaskPoint, + BRUSHOBJ *Brush, + POINTL *BrushPoint, + ROP4 rop4) +{ + /* Punt bitblts with complex clipping to the GDI. */ + if (Clip != NULL) + { + return(FALSE); + } + + switch (rop4) + { + case BLACKNESS: + case PATCOPY: + case WHITENESS: + return(VGADDI_BltBrush(Dest, ColorTranslation, DestRect, Brush, + BrushPoint, rop4)); + + case SRCCOPY: + return(VGADDI_BltSrc(Dest, Source, ColorTranslation, DestRect, + SourcePoint)); + + case 0xAACC: + return(VGADDI_BltMask(Dest, Mask, ColorTranslation, DestRect, + MaskPoint, Brush, BrushPoint)); + + default: + return(FALSE); + } +} diff --git a/drivers/dd/vga/display/objects/bitblt.h b/drivers/dd/vga/display/objects/bitblt.h new file mode 100644 index 0000000..2f5d359 --- /dev/null +++ b/drivers/dd/vga/display/objects/bitblt.h @@ -0,0 +1,22 @@ +/// Define the A vector polynomial bits +// Each bit corresponds to one of the terms in the polynomial +// +// Rop(D,S,P) = a + a D + a S + a P + a DS + a DP + a SP + a DSP +// 0 d s p ds dp sp dsp + +#define AVEC_NOT 0x01 +#define AVEC_D 0x02 +#define AVEC_S 0x04 +#define AVEC_P 0x08 +#define AVEC_DS 0x10 +#define AVEC_DP 0x20 +#define AVEC_SP 0x40 +#define AVEC_DSP 0x80 + +#define AVEC_NEED_SOURCE (AVEC_S | AVEC_DS | AVEC_SP | AVEC_DSP) +#define AVEC_NEED_PATTERN (AVEC_P | AVEC_DP | AVEC_SP | AVEC_DSP) + +#define BB_TARGET_SCREEN 0x0001 +#define BB_TARGET_ONLY 0x0002 +#define BB_SOURCE_COPY 0x0004 +#define BB_PATTERN_COPY 0x0008 diff --git a/drivers/dd/vga/display/objects/brush.h b/drivers/dd/vga/display/objects/brush.h new file mode 100644 index 0000000..bbcc826 --- /dev/null +++ b/drivers/dd/vga/display/objects/brush.h @@ -0,0 +1,58 @@ +typedef struct _BRUSHINST +{ + // We need to removed ajC0-3 when color pattern code is complete!!! + // + BYTE ajC0[8]; // Color bits for plane 0 + BYTE ajC1[8]; // Color bits for plane 1 + BYTE ajC2[8]; // Color bits for plane 2 + BYTE ajC3[8]; // Color bits for plane 3 + + BYTE ajPattern[32]; // Color bits for the mask + USHORT usStyle; // Brush style + BYTE fjAccel; // Accelerator flags + BYTE jFgColor; // Current foreground color + BYTE jBkColor; // Current background color + BYTE RealWidth; // + BYTE YShiftValue; // + BYTE jOldBrushRealized; // + DWORD Width; // Width of brush + DWORD Height; + BYTE *pPattern; //Pointer to realized mono pattern +} BRUSHINST; + +#define BRI_SOLID 0 +#define BRI_HOLLOW 1 +#define BRI_HATCHED 2 +#define BRI_PATTERN 3 +#define BRI_MONO_PATTERN 4 +#define BRI_COLOR_PATTERN 5 + +// Definitions for the pcol_C3 byte of the physical color +// +// Some of these definitions have limitations as to when they +// are valid. They are as follows: +// +// C0_BIT color device, phys color, solid brushes if SOLID_COLOR +// C1_BIT color device, phys color, solid brushes if SOLID_COLOR +// C2_BIT color device, phys color, solid brushes if SOLID_COLOR +// C3_BIT color device, phys color, solid brushes if SOLID_COLOR +// MONO_BIT mono device, phys color +// ONES_OR_ZEROS color device, phys color, solid brushes if SOLID_COLOR +// GREY_SCALE color device, dithered solid and hatched brushes +// SOLID_BRUSH color device, solid brush qualifier +// +// There may be brushes where the accelerators could have been set, +// but wasn't. That's life. + +#define C0_BIT 0x01 // C0 color +#define C1_BIT 0x02 // C1 color +#define C2_BIT 0x04 // C2 color +#define C3_BIT 0x08 // C3 color +#define COLOR_BITS 0x0f // All the color bits +#define MONO_BIT 0x10 // Monochrome bit +#define ONES_OR_ZEROS 0x20 // Color is really all 1's or all 0's +#define GREY_SCALE 0x40 // Indicates a real grey scale brush +#define SOLID_BRUSH 0x80 // Indicates a solid color brush + +#define PTRI_INVERT 0x0001 +#define PTRI_ANIMATE 0x0002 diff --git a/drivers/dd/vga/display/objects/lineto.c b/drivers/dd/vga/display/objects/lineto.c new file mode 100644 index 0000000..6345306 --- /dev/null +++ b/drivers/dd/vga/display/objects/lineto.c @@ -0,0 +1,105 @@ +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" + + +BOOL STDCALL +DrvLineTo(SURFOBJ *Surface, + CLIPOBJ *Clip, + BRUSHOBJ *Brush, + LONG x1, + LONG y1, + LONG x2, + LONG y2, + RECTL *RectBounds, + MIX mix) + +// FIXME: Use ClipObj and RectBounds to clip the line where required +// FIXME: Use Mix to perform ROPs + +{ + ULONG x, y, d, i, length, xchange, ychange, error, + iSolidColor, hx, vy; + LONG deltax, deltay; + + iSolidColor = Brush->iSolidColor; // FIXME: Brush Realization... + + // FIXME: Implement clipping + + x=x1; + y=y1; + deltax=x2-x1; + deltay=y2-y1; + + if(deltax<0) + { + xchange=-1; + deltax=-deltax; + hx = x2; + } else + { + xchange=1; + hx = x1; + } + + if(deltay<0) + { + ychange=-1; + deltay=-deltay; + vy = y2; + } else + { + ychange=1; + vy = y1; + }; + + if(y1==y2) + { + return vgaHLine(hx, y1, deltax, iSolidColor); + } + if(x1==x2) + { + return vgaVLine(x1, vy, deltay, iSolidColor); + } + + // Using individual pixels to draw a line neither horizontal or vertical + // Set up the VGA masking for individual pixels + + + error=0; + i=0; + + if(deltaxdeltay) + { + x=x+xchange; + error=error-deltay; + } + i=i+1; + } + } else + { + length=deltax+1; + while(ideltax) + { + y=y+ychange; + error=error-deltax; + } + i=i+1; + } + } + + return TRUE; +} diff --git a/drivers/dd/vga/display/objects/offscreen.c b/drivers/dd/vga/display/objects/offscreen.c new file mode 100644 index 0000000..4c8fba8 --- /dev/null +++ b/drivers/dd/vga/display/objects/offscreen.c @@ -0,0 +1,191 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS VGA16 display driver + * FILE: drivers/dd/vga/display/objects/offscreen.c + * PURPOSE: Manages off-screen video memory. + */ + +/* INCLUDES ******************************************************************/ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include + +/* GLOBALS *******************************************************************/ + +static LIST_ENTRY SavedBitsList; + +/* FUNCTIONS *****************************************************************/ + +VOID +VGADDI_BltFromSavedScreenBits(ULONG DestX, + ULONG DestY, + PSAVED_SCREEN_BITS Src, + ULONG SizeX, + ULONG SizeY) +{ + PUCHAR DestOffset; + PUCHAR SrcOffset; + ULONG i, j; + + /* Select write mode 1. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1); + + SrcOffset = (PUCHAR)vidmem + Src->Offset; + for (i = 0; i < SizeY; i++) + { + DestOffset = (PUCHAR)vidmem + (i + DestY) * 80 + (DestX >> 3); + for (j = 0; j < SizeX; j++, SrcOffset++, DestOffset++) + { + (VOID)READ_REGISTER_UCHAR(SrcOffset); + WRITE_REGISTER_UCHAR(DestOffset, 0); + } + } + + /* Select write mode 2. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2); +} + +VOID +VGADDI_BltToSavedScreenBits(PSAVED_SCREEN_BITS Dest, + ULONG SourceX, + ULONG SourceY, + ULONG SizeX, + ULONG SizeY) +{ + PUCHAR DestOffset; + PUCHAR SrcOffset; + ULONG i, j; + + /* Select write mode 1. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1); + + DestOffset = (PUCHAR)vidmem + Dest->Offset; + + for (i = 0; i < SizeY; i++) + { + SrcOffset = (PUCHAR)vidmem + (SourceY + i) * 80 + (SourceX >> 3); + for (j = 0; j < SizeX; j++, SrcOffset++, DestOffset++) + { + (VOID)READ_REGISTER_UCHAR(SrcOffset); + WRITE_REGISTER_UCHAR(DestOffset, 0); + } + } + + /* Select write mode 2. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2); +} + +VOID +VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits) +{ + SavedBits->Free = TRUE; + + if (SavedBits->ListEntry.Blink != &SavedBitsList) + { + PSAVED_SCREEN_BITS Previous; + + Previous = CONTAINING_RECORD(SavedBits->ListEntry.Blink, + SAVED_SCREEN_BITS, ListEntry); + if (Previous->Free) + { + Previous->Size += SavedBits->Size; + RemoveEntryList(&SavedBits->ListEntry); + EngFreeMem(SavedBits); + SavedBits = Previous; + } + } + if (SavedBits->ListEntry.Flink != &SavedBitsList) + { + PSAVED_SCREEN_BITS Next; + + Next = CONTAINING_RECORD(SavedBits->ListEntry.Flink, SAVED_SCREEN_BITS, + ListEntry); + if (Next->Free) + { + SavedBits->Size += Next->Size; + RemoveEntryList(&SavedBits->ListEntry); + EngFreeMem(SavedBits); + } + } +} + +PSAVED_SCREEN_BITS +VGADDI_AllocSavedScreenBits(ULONG Size) +{ + PSAVED_SCREEN_BITS Current; + PLIST_ENTRY CurrentEntry; + PSAVED_SCREEN_BITS Best; + PSAVED_SCREEN_BITS New; + + Best = NULL; + CurrentEntry = SavedBitsList.Flink; + while (CurrentEntry != &SavedBitsList) + { + Current = CONTAINING_RECORD(CurrentEntry, SAVED_SCREEN_BITS, ListEntry); + + if (Current->Free && Current->Size >= Size && + (Best == NULL || (Current->Size - Size) < (Best->Size - Size))) + { + Best = Current; + } + + CurrentEntry = CurrentEntry->Flink; + } + + if (Best == NULL) + { + return(NULL); + } + if (Best->Size == Size) + { + Best->Free = FALSE; + return(Best); + } + else + { + New = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG); + New->Free = FALSE; + New->Offset = Best->Offset + Size; + New->Size = Size; + Best->Size -= Size; + InsertHeadList(&Best->ListEntry, &New->ListEntry); + return(New); + } +} + +VOID +VGADDI_InitializeOffScreenMem(ULONG Start, ULONG Length) +{ + PSAVED_SCREEN_BITS FreeBits; + + InitializeListHead(&SavedBitsList); + + FreeBits = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG); + FreeBits->Free = TRUE; + FreeBits->Offset = Start; + FreeBits->Size = Length; + InsertHeadList(&SavedBitsList, &FreeBits->ListEntry); +} diff --git a/drivers/dd/vga/display/objects/paint.c b/drivers/dd/vga/display/objects/paint.c new file mode 100644 index 0000000..f50ab17 --- /dev/null +++ b/drivers/dd/vga/display/objects/paint.c @@ -0,0 +1,231 @@ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include "brush.h" + +#include + +BOOL VGADDIFillSolid(SURFOBJ *Surface, RECTL Dimensions, ULONG iColor) +{ + int x, y, x2, y2, w, h; + ULONG offset, i, j, pre1; + ULONG orgpre1, orgx, midpre1, tmppre1; + ULONG ileftpix, imidpix, irightpix; + double leftpix, midpix, rightpix, temp; + UCHAR a; + + DPRINT("VGADDIFillSolid: x:%d, y:%d, w:%d, h:%d\n", x, y, w, h); + + // Swap dimensions so that x, y are at topmost left + if(Dimensions.right < Dimensions.left) { + x = Dimensions.right; + x2 = Dimensions.left; + } else { + x2 = Dimensions.right; + x = Dimensions.left; + } + if(Dimensions.bottom < Dimensions.top) { + y = Dimensions.bottom; + y2 = Dimensions.top; + } else { + y2 = Dimensions.bottom; + y = Dimensions.top; + } + + // Calculate the width and height + w = x2 - x; + h = y2 - y; + + // Calculate the starting offset + offset = xconv[x]+y80[y]; + + // Make a note of original x + orgx=x; + + // If width is less than 8, draw using vertical lines + if(w<8) + { + for (i=x; i0) + { + // Write left pixels + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)0x3cf,startmasks[ileftpix]); + + tmppre1 = pre1; + for (j=y; j0) + { + midpre1=xconv[x]+y80[y]; + + // Set mask to all pixels in byte + WRITE_PORT_UCHAR((PUCHAR)0x3ce, 0x08); + + WRITE_PORT_UCHAR((PUCHAR)0x3cf, 0xff); + + for (j=y; jiMode, ClipRegion->iDComplexity, iColor); + switch(ClipRegion->iMode) { + + case TC_RECTANGLES: + + /* Rectangular clipping can be handled without enumeration. + Note that trivial clipping is not possible, since the clipping + region defines the area to fill */ + + if (ClipRegion->iDComplexity == DC_RECT) + { + DPRINT("VGADDIPaintRgn Rect:%d %d %d %d\n", ClipRegion->rclBounds.left, ClipRegion->rclBounds.top, ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom); + VGADDIFillSolid(Surface, ClipRegion->rclBounds, iColor); + } else { + /* Enumerate all the rectangles and draw them */ + + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, + ENUM_RECT_LIMIT); + + do { + int i; + EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum); + DPRINT("EnumMore: %d, count: %d\n", EnumMore, RectEnum.c); + for( i=0; iiSolidColor; // FIXME: Realizations and the like + + // If the foreground and background Mixes are the same, + // (LATER or if there's no brush mask) + // then see if we can use the solid brush accelerators + + // FIXME: Put in the mix switch below + // Brush color parameter doesn't matter for these rops + return(VGADDIPaintRgn(Surface, ClipRegion, iSolidColor, Mix, NULL, BrushOrigin)); + + if ((Mix & 0xFF) == ((Mix >> 8) & 0xFF)) + { + switch (Mix & 0xFF) + { + case 0: + break; + + // FIXME: Implement all these millions of ROPs + // For now we don't support brushes -- everything is solid + + case R2_MASKNOTPEN: + case R2_NOTCOPYPEN: + case R2_XORPEN: + case R2_MASKPEN: + case R2_NOTXORPEN: + case R2_MERGENOTPEN: + case R2_COPYPEN: + case R2_MERGEPEN: + case R2_NOTMERGEPEN: + case R2_MASKPENNOT: + case R2_NOTMASKPEN: + case R2_MERGEPENNOT: + + // Rops that are implicit solid colors + case R2_NOT: + case R2_WHITE: + case R2_BLACK: + + + // FIXME: The Paint region belongs HERE + + case R2_NOP: + return(TRUE); + + default: + break; + } + } + +doBitBlt: + + // If VGADDIPaint can't do it, VGADDIBitBlt can.. or it might just loop back + // here and we have a nice infinite loop + +/* return( VGADDIBitBlt(Surface, (SURFOBJ *)NULL, (SURFOBJ *)NULL, ClipRegion, + (XLATEOBJ *)NULL, &ClipRegion->rclBounds, + NULL, (POINTL *)NULL, Brush, BrushOrigin, + NULL) ); UNIMPLEMENTED */ +} diff --git a/drivers/dd/vga/display/objects/pointer.c b/drivers/dd/vga/display/objects/pointer.c new file mode 100644 index 0000000..3178ee8 --- /dev/null +++ b/drivers/dd/vga/display/objects/pointer.c @@ -0,0 +1,350 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS VGA16 display driver + * FILE: drivers/dd/vga/display/objects/pointer.c + * PURPOSE: Draws the mouse pointer. + */ + +/* INCLUDES ******************************************************************/ + +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" + +/* GLOBALS *******************************************************************/ + +static ULONG oldx, oldy; +static PSAVED_SCREEN_BITS ImageBehindCursor = NULL; +VOID VGADDI_HideCursor(PPDEV ppdev); +VOID VGADDI_ShowCursor(PPDEV ppdev); + +/* FUNCTIONS *****************************************************************/ + +VOID +VGADDI_BltPointerToVGA(ULONG StartX, ULONG StartY, ULONG SizeX, + ULONG SizeY, PUCHAR MaskBits, ULONG MaskOp) +{ + ULONG EndX, EndY; + UCHAR Mask; + PUCHAR Video; + PUCHAR Src; + ULONG MaskPitch; + UCHAR SrcValue; + ULONG i, j; + ULONG Left; + ULONG Length; + + EndX = StartX + SizeX; + EndY = StartY + SizeY; + MaskPitch = SizeX >> 3; + + /* Set write mode zero. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0); + + /* Select raster op. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, MaskOp); + + if ((StartX % 8) != 0) + { + /* Disable writes to pixels outside of the destination rectangle. */ + Mask = (1 << (8 - (StartX % 8))) - 1; + if ((EndX - StartX) < (8 - (StartX % 8))) + { + Mask &= ~((1 << (8 - (EndX % 8))) - 1); + } + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask); + + /* Write the mask. */ + Video = (PUCHAR)vidmem + StartY * 80 + (StartX >> 3); + Src = MaskBits; + for (i = 0; i < SizeY; i++, Video+=80, Src+=MaskPitch) + { + SrcValue = (*Src) >> (StartX % 8); + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SrcValue); + } + } + + /* Enable writes to all pixels. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + + /* Have we finished. */ + if ((EndX - StartX) < (8 - (StartX % 8))) + { + return; + } + + /* Fill any whole rows of eight pixels. */ + Left = (StartX + 7) & ~0x7; + Length = (EndX >> 3) - (Left >> 3); + for (i = StartY; i < EndY; i++) + { + Video = (PUCHAR)vidmem + i * 80 + (Left >> 3); + Src = MaskBits + (i - StartY) * MaskPitch; + for (j = 0; j < Length; j++, Video++, Src++) + { + if ((StartX % 8) != 0) + { + SrcValue = (Src[0] << (8 - (StartX % 8))); + SrcValue |= (Src[1] >> (StartX % 8)); + } + else + { + SrcValue = Src[0]; + } + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SrcValue); + } + } + + /* Fill any pixels on the right which don't fall into a complete row. */ + if ((EndX % 8) != 0) + { + /* Disable writes to pixels outside the destination rectangle. */ + Mask = ~((1 << (8 - (EndX % 8))) - 1); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask); + + Video = (PUCHAR)vidmem + StartY * 80 + (EndX >> 3); + Src = MaskBits + (SizeX >> 3) - 1; + for (i = StartY; i < EndY; i++, Video+=80, Src+=MaskPitch) + { + SrcValue = (Src[0] << (8 - (StartX % 8))); + (VOID)READ_REGISTER_UCHAR(Video); + WRITE_REGISTER_UCHAR(Video, SrcValue); + } + + /* Restore the default write masks. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF); + } + + /* Set write mode two. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2); + + /* Select raster op replace. */ + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 3); + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0); +} + +BOOL InitPointer(PPDEV ppdev) +{ + ULONG CursorWidth = 32, CursorHeight = 32; + ULONG PointerAttributesSize; + ULONG SavedMemSize; + + /* Determine the size of the pointer attributes */ + PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) + + ((CursorWidth * CursorHeight * 2) >> 3); + + /* Allocate memory for pointer attributes */ + ppdev->pPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG); + + ppdev->pPointerAttributes->Flags = 0; /* FIXME: Do this right */ + ppdev->pPointerAttributes->Width = CursorWidth; + ppdev->pPointerAttributes->Height = CursorHeight; + ppdev->pPointerAttributes->WidthInBytes = CursorWidth >> 3; + ppdev->pPointerAttributes->Enable = 0; + ppdev->pPointerAttributes->Column = 0; + ppdev->pPointerAttributes->Row = 0; + + /* Allocate memory for the pixels behind the cursor */ + SavedMemSize = ((((CursorWidth + 7) & ~0x7) + 16) * CursorHeight) >> 3; + ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize); + + return(TRUE); +} + + +VOID STDCALL +DrvMovePointer(IN PSURFOBJ pso, + IN LONG x, + IN LONG y, + IN PRECTL prcl) +{ + PPDEV ppdev = (PPDEV)pso->dhpdev; + + if (x == -1) + { + /* x == -1 and y == -1 indicates we must hide the cursor */ + VGADDI_HideCursor(ppdev); + return; + } + + ppdev->xyCursor.x = x; + ppdev->xyCursor.y = y; + + VGADDI_ShowCursor(ppdev); + + /* Give feedback on the new cursor rectangle */ + /*if (prcl != NULL) ComputePointerRect(ppdev, prcl);*/ +} + + +ULONG STDCALL +DrvSetPointerShape(PSURFOBJ pso, + PSURFOBJ psoMask, + PSURFOBJ psoColor, + PXLATEOBJ pxlo, + LONG xHot, + LONG yHot, + LONG x, + LONG y, + PRECTL prcl, + ULONG fl) +{ + PPDEV ppdev = (PPDEV)pso->dhpdev; + ULONG NewWidth, NewHeight; + PUCHAR Src, Dest; + ULONG i, j; + + NewWidth = psoMask->lDelta << 3; + NewHeight = (psoMask->cjBits / psoMask->lDelta) / 2; + + /* Hide the cursor */ + if(ppdev->pPointerAttributes->Enable != 0) + { + VGADDI_HideCursor(ppdev); + } + + /* Reallocate the space for the cursor if necessary. */ + if (ppdev->pPointerAttributes->Width != NewWidth || + ppdev->pPointerAttributes->Height != NewHeight) + { + ULONG PointerAttributesSize; + PVIDEO_POINTER_ATTRIBUTES NewPointerAttributes; + ULONG SavedMemSize; + + /* Determine the size of the pointer attributes */ + PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) + + ((NewWidth * NewHeight * 2) >> 3); + + /* Allocate memory for pointer attributes */ + NewPointerAttributes = EngAllocMem(0, PointerAttributesSize, ALLOC_TAG); + *NewPointerAttributes = *ppdev->pPointerAttributes; + NewPointerAttributes->Width = NewWidth; + NewPointerAttributes->Height = NewHeight; + NewPointerAttributes->WidthInBytes = NewWidth >> 3; + EngFreeMem(ppdev->pPointerAttributes); + ppdev->pPointerAttributes = NewPointerAttributes; + + /* Reallocate the space for the saved bits. */ + VGADDI_FreeSavedScreenBits(ImageBehindCursor); + SavedMemSize = ((((NewWidth + 7) & ~0x7) + 16) * NewHeight) >> 3; + ImageBehindCursor = VGADDI_AllocSavedScreenBits(SavedMemSize); + } + + /* Copy the new cursor in. */ + for (i = 0; i < (NewHeight * 2); i++) + { + Src = (PUCHAR)psoMask->pvBits; + Src += (i * (NewWidth >> 3)); + Dest = (PUCHAR)ppdev->pPointerAttributes->Pixels; + if (i >= NewHeight) + { + Dest += (((NewHeight * 3) - i - 1) * (NewWidth >> 3)); + } + else + { + Dest += ((NewHeight - i - 1) * (NewWidth >> 3)); + } + memcpy(Dest, Src, NewWidth >> 3); + } + + /* Set the new cursor position */ + ppdev->xyCursor.x = x; + ppdev->xyCursor.y = y; + + /* Show the cursor */ + VGADDI_ShowCursor(ppdev); +} + +VOID +VGADDI_HideCursor(PPDEV ppdev) +{ + ULONG i, j, cx, cy, bitpos; + ULONG SizeX; + + /* Display what was behind cursor */ + SizeX = ((oldx + ppdev->pPointerAttributes->Width) + 7) & ~0x7; + SizeX -= (oldx & ~0x7); + VGADDI_BltFromSavedScreenBits(oldx & ~0x7, + oldy, + ImageBehindCursor, + SizeX, + ppdev->pPointerAttributes->Height); + + ppdev->pPointerAttributes->Enable = 0; +} + +VOID +VGADDI_ShowCursor(PPDEV ppdev) +{ + ULONG i, j, cx, cy; + PUCHAR AndMask; + ULONG SizeX; + + if (ppdev->pPointerAttributes->Enable != 0) + { + VGADDI_HideCursor(ppdev); + } + + /* Capture pixels behind the cursor */ + cx = ppdev->xyCursor.x; + cy = ppdev->xyCursor.y; + + /* Used to repaint background */ + SizeX = ((cx + ppdev->pPointerAttributes->Width) + 7) & ~0x7; + SizeX -= (cx & ~0x7); + VGADDI_BltToSavedScreenBits(ImageBehindCursor, + cx & ~0x7, + cy, + SizeX, + ppdev->pPointerAttributes->Height); + + /* Display the cursor. */ + AndMask = ppdev->pPointerAttributes->Pixels + + ppdev->pPointerAttributes->WidthInBytes * + ppdev->pPointerAttributes->Height; + VGADDI_BltPointerToVGA(ppdev->xyCursor.x, + ppdev->xyCursor.y, + ppdev->pPointerAttributes->Width, + ppdev->pPointerAttributes->Height, + AndMask, + VGA_AND); + VGADDI_BltPointerToVGA(ppdev->xyCursor.x, + ppdev->xyCursor.y, + ppdev->pPointerAttributes->Width, + ppdev->pPointerAttributes->Height, + ppdev->pPointerAttributes->Pixels, + VGA_XOR); + + /* Save the new cursor location. */ + oldx = ppdev->xyCursor.x; + oldy = ppdev->xyCursor.y; + + /* Mark the cursor as currently displayed. */ + ppdev->pPointerAttributes->Enable = 1; +} diff --git a/drivers/dd/vga/display/objects/screen.c b/drivers/dd/vga/display/objects/screen.c new file mode 100644 index 0000000..f4b7736 --- /dev/null +++ b/drivers/dd/vga/display/objects/screen.c @@ -0,0 +1,170 @@ +#include "../vgaddi.h" + +static WORD PaletteBuffer[] = { + 16, 0, // 16 entries, start with 0 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static BYTE ColorBuffer[] = { + 16, // 16 entries + 0, 0, + 0, // start with 0 + 0x00, 0x00, 0x00, 0x00, // black + 0x2A, 0x00, 0x15, 0x00, // red + 0x00, 0x2A, 0x15, 0x00, // green + 0x2A, 0x2A, 0x15, 0x00, // brown + 0x00, 0x00, 0x2A, 0x00, // blue + 0x2A, 0x15, 0x2A, 0x00, // magenta + 0x15, 0x2A, 0x2A, 0x00, // cyan + 0x21, 0x22, 0x23, 0x00, // dark gray + 0x30, 0x31, 0x32, 0x00, // light gray + 0x3F, 0x00, 0x00, 0x00, // bright red + 0x00, 0x3F, 0x00, 0x00, // bright green + 0x3F, 0x3F, 0x00, 0x00, // bright yellow + 0x00, 0x00, 0x3F, 0x00, // bright blue + 0x3F, 0x00, 0x3F, 0x00, // bright magenta + 0x00, 0x3F, 0x3F, 0x00, // bright cyan + 0x3F, 0x3F, 0x3F, 0x00 // bright white +}; + +DWORD getAvailableModes(HANDLE Driver, + PVIDEO_MODE_INFORMATION *modeInformation, + DWORD *ModeSize) +{ + ULONG Temp; + VIDEO_NUM_MODES modes; + PVIDEO_MODE_INFORMATION VideoTemp; + + // get number of modes supported + if (EngDeviceIoControl(Driver, + IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES, + NULL, + 0, + &modes, + sizeof(VIDEO_NUM_MODES), + &Temp)) + { + // get modes failed + return(0); + } + + *ModeSize = modes.ModeInformationLength; + + // allocate buffer for the mini-port to write the modes in + *modeInformation = (PVIDEO_MODE_INFORMATION) + EngAllocMem(0, modes.NumModes * + modes.ModeInformationLength, ALLOC_TAG); + + if (*modeInformation == (PVIDEO_MODE_INFORMATION) NULL) + { + // couldn't allocate buffer + return 0; + } + + // Ask the mini-port to fill in the available modes. + if (EngDeviceIoControl(Driver, + IOCTL_VIDEO_QUERY_AVAIL_MODES, + NULL, + 0, + *modeInformation, + modes.NumModes * modes.ModeInformationLength, + &Temp)) + { + // failed to query modes + EngFreeMem(*modeInformation); + *modeInformation = (PVIDEO_MODE_INFORMATION) NULL; + + return(0); + } + + // Which modes supported by miniport driver are also suppoted by us, the + // display driver + + Temp = modes.NumModes; + VideoTemp = *modeInformation; + + // Reject mode if it's not 4 planes or not graphic or not 1 bits per pel + while (Temp--) + { + if ((VideoTemp->NumberOfPlanes != 4 ) || + !(VideoTemp->AttributeFlags & VIDEO_MODE_GRAPHICS) || + (VideoTemp->BitsPerPlane != 1) || + BROKEN_RASTERS(VideoTemp->ScreenStride, VideoTemp->VisScreenHeight)) + + { + VideoTemp->Length = 0; + } + + VideoTemp = (PVIDEO_MODE_INFORMATION)(((PUCHAR)VideoTemp) + modes.ModeInformationLength); + } + + return modes.NumModes; +} + +BOOL InitVGA(PPDEV ppdev, BOOL bFirst) +{ + ULONG ReturnedDataLength; + VIDEO_MEMORY VideoMemory; + VIDEO_MEMORY_INFORMATION VideoMemoryInfo; + + char* vidmem; + + ppdev->ModeNum = 12; + + // Set the mode that was requested + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_SET_CURRENT_MODE, + &ppdev->ModeNum, + sizeof(VIDEO_MODE), + NULL, + 0, + &ReturnedDataLength)) { + return(FALSE); + } + + // set up internal palette + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_SET_PALETTE_REGISTERS, + (PVOID) PaletteBuffer, + sizeof (PaletteBuffer), + NULL, + 0, + &ReturnedDataLength)) { + return(FALSE); + } + + // set up the DAC + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_SET_COLOR_REGISTERS, + (PVOID) ColorBuffer, + sizeof (ColorBuffer), + NULL, + 0, + &ReturnedDataLength)) { + return(FALSE); + } + +/* + +gotta fix this up.. it prevents drawing to vidmem right now + + if (bFirst) { + // map video memory into virtual memory + VideoMemory.RequestedVirtualAddress = NULL; + + if (EngDeviceIoControl(ppdev->KMDriver, + IOCTL_VIDEO_MAP_VIDEO_MEMORY, + (PVOID) &VideoMemory, + sizeof (VIDEO_MEMORY), + (PVOID) &VideoMemoryInfo, + sizeof (VideoMemoryInfo), + &ReturnedDataLength)) { + // Failed to map to virtual memory + return (FALSE); + } + + ppdev->fbScreen = VideoMemoryInfo.FrameBufferBase; + } +*/ + return TRUE; +} diff --git a/drivers/dd/vga/display/objects/transblt.c b/drivers/dd/vga/display/objects/transblt.c new file mode 100644 index 0000000..f4f8fd2 --- /dev/null +++ b/drivers/dd/vga/display/objects/transblt.c @@ -0,0 +1,34 @@ +#include +#define NDEBUG +#include +#include "../vgaddi.h" +#include "../vgavideo/vgavideo.h" +#include "brush.h" +#include "bitblt.h" + +BOOL STDCALL +DrvTransparentBlt(PSURFOBJ Dest, + PSURFOBJ Source, + PCLIPOBJ Clip, + PXLATEOBJ ColorTranslation, + PRECTL DestRect, + PRECTL SourceRect, + ULONG TransparentColor, + ULONG Reserved) +{ + LONG dx, dy, sx, sy; + + dx = abs(DestRect->right - DestRect->left); + dy = abs(DestRect->bottom - DestRect->top); + + sx = abs(SourceRect->right - SourceRect->left); + sy = abs(SourceRect->bottom - SourceRect->top); + + if(sxleft, DestRect->top, dx, dy, Source->pvBits, Source->lDelta, TransparentColor); + + return TRUE; +} diff --git a/drivers/dd/vga/display/vgaddi.def b/drivers/dd/vga/display/vgaddi.def new file mode 100644 index 0000000..b520d7c --- /dev/null +++ b/drivers/dd/vga/display/vgaddi.def @@ -0,0 +1,11 @@ +; $Id$ +; +; vgaddi.def +; +; ReactOS Operating System +; +; From Anders Norlander's w32api-0.1.5 vgaddi.def. +; +LIBRARY vgaddi.dll +EXPORTS +DrvEnableDriver@12 diff --git a/drivers/dd/vga/display/vgaddi.edf b/drivers/dd/vga/display/vgaddi.edf new file mode 100644 index 0000000..fb52bdd --- /dev/null +++ b/drivers/dd/vga/display/vgaddi.edf @@ -0,0 +1,11 @@ +; $Id$ +; +; vgaddi.def +; +; ReactOS Operating System +; +; From Anders Norlander's w32api-0.1.5 vgaddi.def. +; +LIBRARY vgaddi.dll +EXPORTS +DrvEnableDriver=DrvEnableDriver@12 diff --git a/drivers/dd/vga/display/vgaddi.h b/drivers/dd/vga/display/vgaddi.h new file mode 100644 index 0000000..64ddc4a --- /dev/null +++ b/drivers/dd/vga/display/vgaddi.h @@ -0,0 +1,235 @@ +#include +#include +#include + +#define DS_SOLIDBRUSH 0x00000001 +#define DS_GREYBRUSH 0x00000002 +#define DS_BRUSH 0x00000004 +#define DS_DIB 0x00000008 + +#define POW2(stride) (!((stride) & ((stride)-1))) // TRUE if stride is power of 2 +#define BROKEN_RASTERS(stride,cy) ((!(POW2(stride))) && ((stride*cy) > 0x10000)) + +#define DM_SPECVERSION 1 // FIXME: What is this really? +#define ENUM_RECT_LIMIT 50 + +typedef struct _RECT_ENUM +{ + ULONG c; + RECTL arcl[ENUM_RECT_LIMIT]; +} RECT_ENUM; + +// Cursor coordinates +typedef struct _XYPAIR +{ + USHORT x; + USHORT y; +} XYPAIR; + +// Cursor states +#define CURSOR_DOWN 0x00000001 +#define CURSOR_COLOR 0x00000004 +#define CURSOR_HW 0x00000010 +#define CURSOR_HW_ACTIVE 0x00000020 +#define CURSOR_ANIMATE 0x00000040 + +typedef struct _PDEV +{ + ULONG fl; // driver flags + + // Handles + HANDLE KMDriver; + HDEV GDIDevHandle; // engine's handle to PDEV + HSURF SurfHandle; // engine's handle to surface + PVOID AssociatedSurf; // associated surface + + // Cursor + XYPAIR xyCursor; // cursor position + POINTL ptlExtent; // cursor extent + ULONG cExtent; // effective cursor extent + ULONG flCursor; // cursor status + + // Pointer + PVIDEO_POINTER_ATTRIBUTES pPointerAttributes; // HW Pointer Attributes + ULONG XorMaskStartOffset; // Start offset of hardware pointer + // XOR mask relative to AND mask for + // passing to HW pointer + DWORD PointerAttributes; // Size of buffer allocated + DWORD flPreallocSSBBufferInUse; // True if preallocated saved screen + // bits buffer is in use + PUCHAR pjPreallocSSBBuffer; // Pointer to preallocated saved screen + // bits buffer, if there is one + ULONG ulPreallocSSBSize; // Size of preallocated saved screen + // bits buffer + VIDEO_POINTER_CAPABILITIES PointerCapabilities; // HW pointer abilities + PUCHAR pucDIB4ToVGAConvBuffer; // DIB4->VGA conversion table buffer + PUCHAR pucDIB4ToVGAConvTables; // Pointer to DIB4->VGA conversion + + // Misc + ULONG ModeNum; // mode index for current VGA mode + + SIZEL sizeSurf; // displayed size of the surface + PBYTE fbScreen; // pointer to the frame buffer + RECTL SavedBitsRight; // invisible part right of screen + RECTL SavedBitsBottom; // invisible part at the bottom of the screen + BOOL BitsSaved; // TRUE if bits are currently saved + SIZEL sizeMem; // actual size (in pixels) of video memory + LONG NumScansUsedByPointer; // # scans of offscreen memory used by + +} PDEV, *PPDEV; + +typedef struct { + RECTL BankBounds; // Pixels addressable in this bank + ULONG BankOffset; // Offset of bank start from bitmap start if linearly addressable +} BANK_INFO, *PBANK_INFO; + +typedef enum { + JustifyTop = 0, + JustifyBottom, +} BANK_JUST; + +// bank control function vector +//typedef VOID (*PFN_BankControl)(PDEVSURF, ULONG, BANK_JUST); +typedef VOID (*PFN_BankControl)(PVOID, ULONG, BANK_JUST); + +#if 0 +// descriptor for a saved screen bits block + +typedef struct _SAVED_SCREEN_BITS +{ + BOOL bFlags; + PBYTE pjBuffer; // pointer to save buffer start + ULONG ulSize; // size of save buffer (per plane; display memory only) + ULONG ulSaveWidthInBytes; // # of bytes across save area (including + // partial edge bytes, if any) + ULONG ulDelta; // # of bytes from end of one saved scan's saved bits to + // start of next (system memory only) + PVOID pvNextSSB; // pointer to next saved screen bits block + // for system memory blocks, saved bits start immediately + // after this structure +} SAVED_SCREEN_BITS, *PSAVED_SCREEN_BITS; +#else +typedef struct _SAVED_SCREEN_BITS +{ + BOOL Free; + DWORD Offset; + ULONG Size; + LIST_ENTRY ListEntry; +} SAVED_SCREEN_BITS, *PSAVED_SCREEN_BITS; +#endif + +// DEVSURF -- definition of a surface as seen and used by the various VGA +// drivers + +typedef struct _DEVSURF +{ + IDENT ident; // Identifier for debugging ease + ULONG flSurf; // DS_ flags as defined below + BYTE Color; // Solid color surface if DS_SOLIDBRUSH + +// If DS_SOLIDBRUSH, the following fields are undefined and not guaranteed to +// have been allocated! + + BYTE Format; // BMF_*, BMF_PHYSDEVICE + BYTE jReserved1; // Reserved + BYTE jReserved2; // Reserved + PPDEV ppdev; // Pointer to associated PDEV + SIZEL sizeSurf; // Size of the surface + ULONG NextScan; // Offset from scan "n" to "n+1" + ULONG NextPlane; // Offset from plane "n" to "n+1" + PVOID Scan0; // Pointer to scan 0 of bitmap + // (actual address of start of bank, for banked VGA surface) + PVOID StartBmp; // Pointer to start of bitmap + PVOID Conv; // Pointer to DIB/Planer conversion buffer + +// Banking variables; used only for banked VGA surfaces + + PVIDEO_BANK_SELECT BankSelectInfo; + ULONG Bank2RWSkip; // Offset from one bank index to next to make two 32K banks appear to be + // one seamless 64K bank + PFN pfnBankSwitchCode; + VIDEO_BANK_TYPE BankingType; + ULONG BitmapSize; // Length of bitmap if there were no banking, in CPU addressable bytes + ULONG PtrBankScan; // Last scan line in pointer work bank + RECTL WindowClip1; // Single-window banking clip rect + RECTL WindowClip2[2]; // Double-window banking clip rects for + // windows 0 & 1 + ULONG WindowBank[2]; // Current banks mapped into windows + // 0 & 1 (used in 2 window mode only) + PBANK_INFO BankInfo; // Pointer to array of bank clip info + ULONG BankInfoLength; // Length of pbiBankInfo, in entries + PBANK_INFO BankInfo2RW; // Same as above, but for 2RW window + ULONG BankInfo2RWLength; // case + PFN_BankControl pfnBankControl; // Pointer to bank control function + PFN_BankControl pfnBankControl2Window; // Pointer to double-window bank + // control function + PVOID BitmapStart; // Single-window bitmap start pointer (adjusted as + // necessary to make window map in at proper offset) + PVOID BitmapStart2Window[2]; // Double-window window 0 and 1 bitmap start + PVOID BankBufferPlane0; // Pointer to temp buffer capable of + // storing one full bank for plane 0 for 1 + // R/W case; capable of storing one full + // bank height of edge bytes for all four + // planes for the 1R/1W case. Also used to + // point to text building buffer in all + // cases. This is the pointer used to + // dealloc bank working storage for all + // four planes + + // The following 3 pointers used by 1 R/W banked devices + PVOID BankBufferPlane1; // Like above, but for plane 1 + PVOID BankBufferPlane2; // Like above, but for plane 2 + PVOID BankBufferPlane3; // Like above, but for plane 3 + ULONG TempBufferSize; // Full size of temp buffer pointed to + // by pvBankBufferPlane0 + + ULONG ajBits[1]; // Bits will start here for device bitmaps + PSAVED_SCREEN_BITS ssbList; // Pointer to start of linked list of + // saved screen bit blocks +} DEVSURF, *PDEVSURF; + +typedef VOID (*PFN_ScreenToScreenBlt)(PDEVSURF, PRECTL, PPOINTL, INT); + +// BMF_PHYSDEVICE format type + +#define BMF_PHYSDEVICE 0xFF +#define BMF_DFB 0xFE + +// Identifiers used in debugging (DEVSURF.ident) + +#define PDEV_IDENT ('V' + ('P' << 8) + ('D' << 16) + ('V' << 24)) +#define DEVSURF_IDENT ('V' + ('S' << 8) + ('R' << 16) + ('F' << 24)) + +BOOL InitVGA(PPDEV ppdev, BOOL bFirst); // screen.c: initialize VGA mode + +#define DRIVER_EXTRA_SIZE 0 +#define ALLOC_TAG TAG('D', 'v', 'g', 'a') // Dvga tag +#define DLL_NAME L"vga" // DLL name in Unicode + +#define MAX_SCAN_WIDTH 2048 // pixels +#define DRIVER_OFFSCREEN_REFRESHED 0x04L // if not set, don't use offscreen memory +#define PLANAR_PELS_PER_CPU_ADDRESS 8 +#define PACKED_PELS_PER_CPU_ADDRESS 2 + +BOOL VGAtoGDI( + SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation, + RECTL *DestRect, POINTL *SourcePoint); + +VOID +VGADDI_BltFromSavedScreenBits(ULONG DestX, + ULONG DestY, + PSAVED_SCREEN_BITS Src, + ULONG SizeX, + ULONG SizeY); +VOID +VGADDI_BltToSavedScreenBits(PSAVED_SCREEN_BITS Dest, + ULONG SourceX, + ULONG SourceY, + ULONG SizeX, + ULONG SizeY); +VOID +VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits); +PSAVED_SCREEN_BITS +VGADDI_AllocSavedScreenBits(ULONG Size); +VOID +VGADDI_InitializeOffScreenMem(ULONG Start, ULONG Length); diff --git a/drivers/dd/vga/display/vgaddi.rc b/drivers/dd/vga/display/vgaddi.rc new file mode 100644 index 0000000..5c34e3d --- /dev/null +++ b/drivers/dd/vga/display/vgaddi.rc @@ -0,0 +1,38 @@ +#include "../../../../include/defines.h" +#include "../../../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "VGA Display Driver\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "vgaddi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vgaddi.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/vga/display/vgavideo/vgavideo.c b/drivers/dd/vga/display/vgavideo/vgavideo.c new file mode 100644 index 0000000..ca644f1 --- /dev/null +++ b/drivers/dd/vga/display/vgavideo/vgavideo.c @@ -0,0 +1,723 @@ +#include +#include +#include +#include +#include "vgavideo.h" + +UCHAR PreCalcReverseByte[256]; +int maskbit[640]; +int y80[480]; +int xconv[640]; +int bit8[640]; +int startmasks[8]; +int endmasks[8]; +char* vidmem; + +static unsigned char saved_SEQ_mask; /* 0x02 */ +static unsigned char saved_GC_eSR; /* 0x01 */ +static unsigned char saved_GC_fun; /* 0x03 */ +static unsigned char saved_GC_rmap; /* 0x04 */ +static unsigned char saved_GC_mode; /* 0x05 */ +static unsigned char saved_GC_mask; /* 0x08 */ +static unsigned char leftMask; +static int byteCounter; +static unsigned char rightMask; + +INT abs(INT nm) +{ + if(nm<0) + { + return nm * -1; + } else + { + return nm; + } +} + +div_t div(int num, int denom) +{ + div_t r; + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} + +int mod(int num, int denom) +{ + div_t dvt = div(num, denom); + return dvt.rem; +} + +BYTE bytesPerPixel(ULONG Format) +{ + // This function is taken from /subsys/win32k/eng/surface.c + // FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the + // pixel size if < 1 byte we expand it to 1 byte for simplicities sake + + if(Format==BMF_1BPP) + { + return 1; + } else + if((Format==BMF_4BPP) || (Format==BMF_4RLE)) + { + return 1; + } else + if((Format==BMF_8BPP) || (Format==BMF_8RLE)) + { + return 1; + } else + if(Format==BMF_16BPP) + { + return 2; + } else + if(Format==BMF_24BPP) + { + return 3; + } else + if(Format==BMF_32BPP) + { + return 4; + } + + return 0; +} + +VOID vgaPreCalc() +{ + ULONG j; + + startmasks[0] = 255; + startmasks[1] = 1; + startmasks[2] = 3; + startmasks[3] = 7; + startmasks[4] = 15; + startmasks[5] = 31; + startmasks[6] = 63; + startmasks[7] = 127; + startmasks[8] = 255; + + endmasks[0] = 128; + endmasks[1] = 192; + endmasks[2] = 224; + endmasks[3] = 240; + endmasks[4] = 248; + endmasks[5] = 252; + endmasks[6] = 254; + endmasks[7] = 255; + endmasks[8] = 255; + + for(j=0; j<80; j++) + { + maskbit[j*8] = 128; + maskbit[j*8+1] = 64; + maskbit[j*8+2] = 32; + maskbit[j*8+3] = 16; + maskbit[j*8+4] = 8; + maskbit[j*8+5] = 4; + maskbit[j*8+6] = 2; + maskbit[j*8+7] = 1; + + bit8[j*8] = 7; + bit8[j*8+1] = 6; + bit8[j*8+2] = 5; + bit8[j*8+3] = 4; + bit8[j*8+4] = 3; + bit8[j*8+5] = 2; + bit8[j*8+6] = 1; + bit8[j*8+7] = 0; + } + for(j=0; j<480; j++) + { + y80[j] = j*80; + } + for(j=0; j<640; j++) + { + xconv[j] = j >> 3; + } + + for (j = 0; j < 256; j++) + { + PreCalcReverseByte[j] = + (((j >> 0) & 0x1) << 7) | + (((j >> 1) & 0x1) << 6) | + (((j >> 2) & 0x1) << 5) | + (((j >> 3) & 0x1) << 4) | + (((j >> 4) & 0x1) << 3) | + (((j >> 5) & 0x1) << 2) | + (((j >> 6) & 0x1) << 1) | + (((j >> 7) & 0x1) << 0); + } +} + +void +get_masks(int x, int w) +{ + register int tmp; + + leftMask = rightMask = 0; + byteCounter = w; + /* right margin */ + tmp = (x+w) & 7; + if (tmp) { + byteCounter -= tmp; + rightMask = (unsigned char)(0xff00 >> tmp); + } + /* left margin */ + tmp = x & 7; + if (tmp) { + byteCounter -= (8 - tmp); + leftMask = (0xff >> tmp); + } + /* too small ? */ + if (byteCounter < 0) { + leftMask &= rightMask; + rightMask = 0; + byteCounter = 0; + } + byteCounter /= 8; +} + +VOID vgaPutPixel(INT x, INT y, UCHAR c) +{ + ULONG offset; + UCHAR a; + + offset = xconv[x]+y80[y]; + + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); + WRITE_PORT_UCHAR((PUCHAR)0x3cf,maskbit[x]); + + a = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_REGISTER_UCHAR(vidmem + offset, c); +} + +VOID vgaPutByte(INT x, INT y, UCHAR c) +{ + ULONG offset; + + offset = xconv[x]+y80[y]; + + // Set the write mode + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); + WRITE_PORT_UCHAR((PUCHAR)0x3cf,0xff); + + WRITE_REGISTER_UCHAR(vidmem + offset, c); +} + +VOID vgaGetByte(ULONG offset, + UCHAR *b, UCHAR *g, + UCHAR *r, UCHAR *i) +{ + WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0304); + *i = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0204); + *r = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0104); + *g = READ_REGISTER_UCHAR(vidmem + offset); + WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0004); + *b = READ_REGISTER_UCHAR(vidmem + offset); +} + +INT vgaGetPixel(INT x, INT y) +{ + UCHAR mask, b, g, r, i; + ULONG offset; + + offset = xconv[x]+y80[y]; + vgaGetByte(offset, &b, &g, &r, &i); + + mask=maskbit[x]; + b=b&mask; + g=g&mask; + r=r&mask; + i=i&mask; + + mask=bit8[x]; + g=g>>mask; + b=b>>mask; + r=r>>mask; + i=i>>mask; + + return(b+2*g+4*r+8*i); +} + +BOOL vgaHLine(INT x, INT y, INT len, UCHAR c) +{ + UCHAR a; + ULONG pre1, i; + ULONG orgpre1, orgx, midpre1; + ULONG ileftpix, imidpix, irightpix; + + orgx=x; + + if(len<8) + { + for (i=x; i0) + { + // Write left pixels + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)0x3cf,startmasks[ileftpix]); + + a = READ_REGISTER_UCHAR(vidmem + pre1); + WRITE_REGISTER_UCHAR(vidmem + pre1, c); + + // Prepare new x for the middle + x=orgx+8; + } + + if(imidpix>0) + { + midpre1=xconv[x]+y80[y]; + + // Set mask to all pixels in byte + WRITE_PORT_UCHAR((PUCHAR)0x3ce, 0x08); + WRITE_PORT_UCHAR((PUCHAR)0x3cf, 0xff); + memset(vidmem+midpre1, c, imidpix); // write middle pixels, no need to read in latch because of the width + } + + x=orgx+len-irightpix; + pre1=xconv[x]+y80[y]; + + // Write right pixels + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask bits + WRITE_PORT_UCHAR((PUCHAR)0x3cf, endmasks[irightpix]); + + a = READ_REGISTER_UCHAR(vidmem + pre1); + WRITE_REGISTER_UCHAR(vidmem + pre1, c); + } + + return TRUE; +} + +BOOL vgaVLine(INT x, INT y, INT len, UCHAR c) +{ + ULONG offset, i; + UCHAR a; + + offset = xconv[x]+y80[y]; + + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask + WRITE_PORT_UCHAR((PUCHAR)0x3cf,maskbit[x]); + + len++; + + for(i=y; ileft = max(prcSrc1->left, prcSrc2->left); + prcDst->right = min(prcSrc1->right, prcSrc2->right); + + if (prcDst->left < prcDst->right) { + prcDst->top = max(prcSrc1->top, prcSrc2->top); + prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); + + if (prcDst->top < prcDst->bottom) + { + return TRUE; + } + } + + *prcDst = rclEmpty; + + return FALSE; +} + +void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta) + +// DIB blt from the VGA. +// For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format. +{ + PBYTE pb = b, opb = b; + BOOLEAN edgePixel = FALSE; + ULONG i, j; + ULONG x2 = x + w; + ULONG y2 = y + h; + BYTE b1, b2; + + // Check if the width is odd + if(mod(w, 2)>0) + { + edgePixel = TRUE; + x2 -= 1; + } + + for (j=y; j0) + { + edgePixel = TRUE; + x2 -= 1; + } + + for (j=y; j> 4; + b2 = *pb & 0x0f; + vgaPutPixel(i, j, b1); + vgaPutPixel(i+1, j, b2); + pb++; + } + + if(edgePixel == TRUE) + { + b1 = *pb; + vgaPutPixel(x2, j, b1); + pb++; + } + + opb += Source_lDelta; + + pb = opb; + + } +} + +void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans) + +// DIB blt to the VGA. +// For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format. +{ + PBYTE pb = b, opb = b; + BOOLEAN edgePixel = FALSE; + ULONG i, j; + ULONG x2 = x + w; + ULONG y2 = y + h; + BYTE b1, b2; + + // Check if the width is odd + if(mod(w, 2)>0) + { + edgePixel = TRUE; + x2 -= 1; + } + + for (j=y; j> 4; + b2 = *pb & 0x0f; + if(b1 != trans) vgaPutPixel(i, j, b1); + if(b2 != trans) vgaPutPixel(i+1, j, b2); + pb++; + } + + if(edgePixel == TRUE) + { + b1 = *pb; + if(b1 != trans) vgaPutPixel(x2, j, b1); + pb++; + } + + opb += Source_lDelta; + pb = opb; // new test code + + } +} + +void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw) + +// This algorithm goes from goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *vp, *vpY, *vpP; + unsigned char data, mask, maskP; + unsigned char *bp, *bpY; + unsigned char plane_mask; + int byte_per_line = SCREEN_X >> 3; + int plane, i, j; + + ASSIGNVP4(x, y, vpP) + ASSIGNMK4(x, y, maskP) + get_masks(x, w); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // read mode 0 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select + + // clear buffer + bp=b; + for (j=h; j>0; j--) { + memset(bp, 0, w); + bp += bw; + } + + for (plane=0, plane_mask=1; plane<4; plane++, plane_mask<<=1) { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select + vpY = vpP; + bpY = b; + for (j=h; j>0; j--) { + vp = vpY; + bp = bpY; + if (leftMask) { + mask = maskP; + data = *vp++; + do { + if (data & mask) *bp |= plane_mask; + bp++; + mask >>= 1; + } while (mask & leftMask); + + } + if (byteCounter) { + for (i=byteCounter; i>0; i--) { + data = *vp++; + if (data & 0x80) *bp |= plane_mask; + bp++; + if (data & 0x40) *bp |= plane_mask; + bp++; + if (data & 0x20) *bp |= plane_mask; + bp++; + if (data & 0x10) *bp |= plane_mask; + bp++; + if (data & 0x08) *bp |= plane_mask; + bp++; + if (data & 0x04) *bp |= plane_mask; + bp++; + if (data & 0x02) *bp |= plane_mask; + bp++; + if (data & 0x01) *bp |= plane_mask; + bp++; + } + } + if (rightMask) { + mask = 0x80; + data = *vp; + do { + if (data & mask) *bp |= plane_mask; + bp++; + mask >>= 1; + } while (mask & rightMask); + } + bpY += bw; + vpY += byte_per_line; + } + } + + // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer) + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); +} + +void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw) + +// This algorithm goes from goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *bp, *bpX; + unsigned char *vp, *vpX; + unsigned char mask; + volatile unsigned char dummy; + int byte_per_line; + int i, j; + + bpX = b; + ASSIGNVP4(x, y, vpX) + ASSIGNMK4(x, y, mask) + byte_per_line = SCREEN_X >> 3; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask + + for (i=w; i>0; i--) { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); + bp = bpX; + vp = vpX; + for (j=h; j>0; j--) { + dummy = *vp; + *vp = *bp; + bp += bw; + vp += byte_per_line; + } + bpX++; + if ((mask >>= 1) == 0) { + vpX++; + mask = 0x80; + } + } +} + +void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans) + +// This algorithm goes from goes from left to right, and inside that loop, top to bottom. +// It also stores each 4BPP pixel in an entire byte. +{ + unsigned char *bp, *bpX; + unsigned char *vp, *vpX; + unsigned char mask; + volatile unsigned char dummy; + int byte_per_line; + int i, j; + + bpX = b; + ASSIGNVP4(x, y, vpX) + ASSIGNMK4(x, y, mask) + byte_per_line = SCREEN_X >> 3; + + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2 + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace + WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00); + WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask + + for (i=w; i>0; i--) { + WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask); + bp = bpX; + vp = vpX; + for (j=h; j>0; j--) { + if (*bp != Trans) + { + dummy = *vp; + *vp = *bp; + } + bp += bw; + vp += byte_per_line; + } + bpX++; + if ((mask >>= 1) == 0) { + vpX++; + mask = 0x80; + } + } +} + +void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) + +// This algorithm converts a DFB into a DIB +// WARNING: This algorithm is buggy +{ + unsigned char *bp, *bpX, *dib, *dibTmp; + int i, j, dib_shift; + + bpX = b; + dib = bdib + y * dibw + (x / 2); + + for (i=w; i>0; i--) { + + // determine the bit shift for the DIB pixel + dib_shift = mod(w-i, 2); + if(dib_shift > 0) dib_shift = 4; + dibTmp = dib; + + bp = bpX; + for (j=h; j>0; j--) { + *dibTmp = *bp << dib_shift | *(bp + 1); + dibTmp += dibw; + bp += bw; + } + bpX++; + if(dib_shift == 0) dib++; + } +} + + +void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw) + +// This algorithm converts a DIB into a DFB +{ + unsigned char *bp, *bpX, *dib, *dibTmp; + int i, j, dib_shift, dib_and; + + bpX = b; + dib = bdib + y * dibw + (x / 2); + + for (i=w; i>0; i--) { + + // determine the bit shift for the DIB pixel + dib_shift = mod(w-i, 2); + if(dib_shift > 0) { + dib_shift = 0; + dib_and = 0x0f; + } else { + dib_shift = 4; + dib_and = 0xf0; + } + + dibTmp = dib; + bp = bpX; + + for (j=h; j>0; j--) { + *bp = (*dibTmp & dib_and) >> dib_shift; + dibTmp += dibw; + bp += bw; + } + + bpX++; + if(dib_shift == 0) dib++; + } +} diff --git a/drivers/dd/vga/display/vgavideo/vgavideo.h b/drivers/dd/vga/display/vgavideo/vgavideo.h new file mode 100644 index 0000000..0a4e97d --- /dev/null +++ b/drivers/dd/vga/display/vgavideo/vgavideo.h @@ -0,0 +1,66 @@ +// FIXME: Make these variables so we can also use modes like 800x600 +#define SCREEN_X 640 +#define SCREEN_Y 480 + +#define VGA_NORMAL 0 +#define VGA_AND 8 +#define VGA_OR 16 +#define VGA_XOR 24 + +//This is in mingw standard headers +//typedef struct { int quot, rem; } div_t; + +extern int maskbit[640]; +extern int y80[480]; +extern int xconv[640]; +extern int bit8[640]; +extern int startmasks[8]; +extern int endmasks[8]; + +extern UCHAR PreCalcReverseByte[256]; + +extern char* vidmem; + +#define MISC 0x3c2 +#define SEQ 0x3c4 +#define CRTC 0x3d4 +#define GRAPHICS 0x3ce +#define FEATURE 0x3da +#define ATTRIB 0x3c0 +#define STATUS 0x3da + +typedef struct _VideoMode { + unsigned short VidSeg; + unsigned char Misc; + unsigned char Feature; + unsigned char Seq[5]; + unsigned char Crtc[25]; + unsigned char Gfx[9]; + unsigned char Attrib[21]; +} VideoMode; + +VOID vgaPreCalc(); +VOID vgaPutPixel(INT x, INT y, UCHAR c); +VOID vgaPutByte(INT x, INT y, UCHAR c); +VOID vgaGetByte(ULONG offset, + UCHAR *b, UCHAR *g, + UCHAR *r, UCHAR *i); +INT vgaGetPixel(INT x, INT y); +BOOL vgaHLine(INT x, INT y, INT len, UCHAR c); +BOOL vgaVLine(INT x, INT y, INT len, UCHAR c); +INT abs(INT nm); +BOOL VGADDIIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2); + +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ + +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ + +#define LowByte(w) (*((unsigned char *)&(w) + 0)) +#define HighByte(w) (*((unsigned char *)&(w) + 1)) + +#define ASSIGNVP4(x, y, vp) vp = vidmem /* VBUF */ + (((x) + (y)*SCREEN_X) >> 3); +#define ASSIGNMK4(x, y, mask) mask = 0x80 >> ((x) & 7); + +void get_masks(int x, int w); diff --git a/drivers/dd/vga/makefile b/drivers/dd/vga/makefile new file mode 100644 index 0000000..ee410cf --- /dev/null +++ b/drivers/dd/vga/makefile @@ -0,0 +1,22 @@ +# $Id$ +# +# +all: + make -C display + make -C miniport + +implib: + make -C display implib + make -C miniport implib + +clean: + make -C display clean + make -C miniport clean + +dist: + make -C display dist + make -C miniport dist + +install: + make -C display install + make -C miniport install diff --git a/drivers/dd/vga/miniport/.cvsignore b/drivers/dd/vga/miniport/.cvsignore new file mode 100644 index 0000000..5e596a5 --- /dev/null +++ b/drivers/dd/vga/miniport/.cvsignore @@ -0,0 +1,6 @@ +junk.tmp +base.tmp +temp.exp +vgamp.coff +vgamp.sys +vgamp.sys.unstripped diff --git a/drivers/dd/vga/miniport/initvga.c b/drivers/dd/vga/miniport/initvga.c new file mode 100644 index 0000000..212efcc --- /dev/null +++ b/drivers/dd/vga/miniport/initvga.c @@ -0,0 +1,128 @@ +#include +#include +#include "vgavideo.h" + +void outxay(PUSHORT ad, UCHAR x, UCHAR y) +{ + USHORT xy = (x << 8) + y; + + VideoPortWritePortUshort(ad, xy); +} + +void setMode(VideoMode mode) +{ + unsigned char x; + unsigned int y, c, a, m, n; + + VideoPortWritePortUchar((PUCHAR)MISC, mode.Misc); + VideoPortWritePortUchar((PUCHAR)STATUS, 0); + VideoPortWritePortUchar((PUCHAR)FEATURE, mode.Feature); + + for(x=0; x<5; x++) + { + outxay((PUSHORT)SEQ, mode.Seq[x], x); + } + + VideoPortWritePortUshort((PUSHORT)CRTC, 0x11); + VideoPortWritePortUshort((PUSHORT)CRTC, (mode.Crtc[0x11] & 0x7f)); + + for(x=0; x<25; x++) + { + outxay((PUSHORT)CRTC, mode.Crtc[x], x); + } + + for(x=0; x<9; x++) + { + outxay((PUSHORT)GRAPHICS, mode.Gfx[x], x); + } + + x=VideoPortReadPortUchar((PUCHAR)FEATURE); + + for(x=0; x<21; x++) + { + VideoPortWritePortUchar((PUCHAR)ATTRIB, x); + VideoPortWritePortUchar((PUCHAR)ATTRIB, mode.Attrib[x]); + } + + x=VideoPortReadPortUchar((PUCHAR)STATUS); + + VideoPortWritePortUchar((PUCHAR)ATTRIB, 0x20); +} + +VideoMode Mode12 = { + 0xa000, 0xe3, 0x00, + + {0x03, 0x01, 0x0f, 0x00, 0x06 }, + + {0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x59, 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff}, + + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff}, + + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x81, 0x00, 0x0f, 0x00, 0x00} +}; + +void InitVGAMode() +{ + int i; + VIDEO_X86_BIOS_ARGUMENTS vxba; + VP_STATUS vps; + + // FIXME: Use Vidport to map the memory properly + vidmem = (char *)(0xd0000000 + 0xa0000); + memset(&vxba, 0, sizeof(vxba)); + vxba.Eax = 0x0012; + vps = VideoPortInt10(NULL, &vxba); + + // Get VGA registers into the correct state (mainly for setting up the palette registers correctly) + setMode(Mode12); + + // Get the VGA into the mode we want to work with + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // Set + WRITE_PORT_UCHAR((PUCHAR)0x3cf,0); // the MASK + WRITE_PORT_USHORT((PUSHORT)0x3ce,0x0205); // write mode = 2 (bits 0,1) read mode = 0 (bit 3) + i = READ_REGISTER_UCHAR(vidmem); // Update bit buffer + WRITE_REGISTER_UCHAR(vidmem, 0); // Write the pixel + WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); + WRITE_PORT_UCHAR((PUCHAR)0x3cf,0xff); + + // Zero out video memory (clear a possibly trashed screen) + RtlZeroMemory(vidmem, 64000); + + vgaPreCalc(); +} + +VOID VGAResetDevice(OUT PSTATUS_BLOCK StatusBlock) +{ + char *vidmem; + HANDLE Event; + OBJECT_ATTRIBUTES Attr; + UNICODE_STRING Name = UNICODE_STRING_INITIALIZER(L"\\TextConsoleRefreshEvent"); + NTSTATUS Status; + VIDEO_X86_BIOS_ARGUMENTS vxba; + VP_STATUS vps; + ULONG ThreadRelease = 1; + + CHECKPOINT; + Event = 0; + + memset(&vxba, 0, sizeof(vxba)); + vxba.Eax = 0x0003; + vps = VideoPortInt10(NULL, &vxba); + memset(&vxba, 0, sizeof(vxba)); + vxba.Eax = 0x1112; + vps = VideoPortInt10(NULL, &vxba); + InitializeObjectAttributes( &Attr, &Name, 0, 0, 0 ); + Status = ZwOpenEvent( &Event, STANDARD_RIGHTS_ALL, &Attr ); + if( !NT_SUCCESS( Status ) ) + DbgPrint( "VGA: Failed to open refresh event\n" ); + else { + ZwSetEvent( Event, &ThreadRelease ); + ZwClose( Event ); + } +} + + + diff --git a/drivers/dd/vga/miniport/makefile b/drivers/dd/vga/miniport/makefile new file mode 100644 index 0000000..7533900 --- /dev/null +++ b/drivers/dd/vga/miniport/makefile @@ -0,0 +1,18 @@ +# $Id$ + +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = vgamp + +TARGET_DDKLIBS = vidport.a + +TARGET_OBJECTS = \ + initvga.o \ + vgamp.o \ + vgavideo.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/vga/miniport/vgamp.c b/drivers/dd/vga/miniport/vgamp.c new file mode 100644 index 0000000..8dd9ba3 --- /dev/null +++ b/drivers/dd/vga/miniport/vgamp.c @@ -0,0 +1,483 @@ +/* + * VGA.C - a generic VGA miniport driver + * + */ + +#include +#include + +#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0) + +#define VERSION "0.0.0" + +// ---------------------------------------------------- Forward Declarations +static VP_STATUS STDCALL +VGAFindAdapter(PVOID DeviceExtension, + PVOID Context, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again); +static BOOLEAN STDCALL +VGAInitialize(PVOID DeviceExtension); +static BOOLEAN STDCALL +VGAStartIO(PVOID DeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket); +/* +static BOOLEAN STDCALL +VGAInterrupt(PVOID DeviceExtension); +static BOOLEAN STDCALL +VGAResetHw(PVOID DeviceExtension, + ULONG Columns, + ULONG Rows); +static VOID STDCALL +VGATimer(PVOID DeviceExtension); +*/ + +/* Mandatory IoControl routines */ +VOID VGAMapVideoMemory(IN PVIDEO_MEMORY RequestedAddress, + OUT PVIDEO_MEMORY_INFORMATION MapInformation, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAQueryAvailModes(OUT PVIDEO_MODE_INFORMATION ReturnedModes, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAQueryCurrentMode(OUT PVIDEO_MODE_INFORMATION CurrentMode, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAQueryNumAvailModes(OUT PVIDEO_NUM_MODES NumberOfModes, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAResetDevice(OUT PSTATUS_BLOCK StatusBlock); +VOID VGASetColorRegisters(IN PVIDEO_CLUT ColorLookUpTable, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGASetPaletteRegisters(IN PWORD PaletteRegisters, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGASetCurrentMode(IN PVIDEO_MODE RequestedMode, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAShareVideoMemory(IN PVIDEO_SHARE_MEMORY RequestedMemory, + OUT PVIDEO_MEMORY_INFORMATION ReturnedMemory, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAUnmapVideoMemory(IN PVIDEO_MEMORY MemoryToUnmap, + OUT PSTATUS_BLOCK StatusBlock); +VOID VGAUnshareVideoMemory(IN PVIDEO_MEMORY MemoryToUnshare, + OUT PSTATUS_BLOCK StatusBlock); + +// ------------------------------------------------------- Public Interface + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PVOID Context1 Context parameter to pass to VidPortInitialize +// IN PVOID Context2 Context parameter to pass to VidPortInitialize +// RETURNS: +// VP_STATUS + +VP_STATUS STDCALL +DriverEntry(IN PVOID Context1, + IN PVOID Context2) +{ + VIDEO_HW_INITIALIZATION_DATA InitData; + + VideoPortZeroMemory(&InitData, sizeof InitData); + + /* FIXME: Fill in InitData members */ + InitData.StartingDeviceNumber = 0; + + /* Export driver entry points... */ + InitData.HwFindAdapter = VGAFindAdapter; + InitData.HwInitialize = VGAInitialize; + InitData.HwStartIO = VGAStartIO; + /* InitData.HwInterrupt = VGAInterrupt; */ + /* InitData.HwResetHw = VGAResetHw; */ + /* InitData.HwTimer = VGATimer; */ + + return VideoPortInitialize(Context1, Context2, &InitData, NULL); +} + +// VGAFindAdapter +// +// DESCRIPTION: +// This routine is called by the videoport driver to find and allocate +// the adapter for a given bus. The miniport driver needs to do the +// following in this routine: +// - Determine if the adapter is present +// - Claim any necessary memory/IO resources for the adapter +// - Map resources into system memory for the adapter +// - fill in relevant information in the VIDEO_PORT_CONFIG_INFO buffer +// - update registry settings for adapter specifics. +// - Set 'Again' based on whether the function should be called again +// another adapter on the same bus. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// PVOID Context +// PWSTR ArgumentString +// PVIDEO_PORT_CONFIG_INFO ConfigInfo +// PUCHAR Again +// RETURNS: +// VP_STATUS + +static VP_STATUS STDCALL +VGAFindAdapter(PVOID DeviceExtension, + PVOID Context, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again) +{ + /* FIXME: Determine if the adapter is present */ + *Again = FALSE; + + return STATUS_SUCCESS; + + /* FIXME: Claim any necessary memory/IO resources for the adapter */ + /* FIXME: Map resources into system memory for the adapter */ + /* FIXME: Fill in relevant information in the VIDEO_PORT_CONFIG_INFO buffer */ + /* FIXME: Update registry settings for adapter specifics. */ +// return NO_ERROR; +} + +// VGAInitialize +// +// DESCRIPTION: +// Perform initialization tasks, but leave the adapter in the same +// user visible state +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// RETURNS: +// BOOLEAN Success or failure +static BOOLEAN STDCALL +VGAInitialize(PVOID DeviceExtension) +{ + return FALSE; +} + +// VGAStartIO +// +// DESCRIPTION: +// This function gets called in responce to GDI EngDeviceIoControl +// calls. Device requests are passed in VRPs. +// Required VRPs: +// IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES +// IOCTL_VIDEO_QUERY_AVAIL_MODES +// IOCTL_VIDEO_QUERY_CURRENT_MODE +// IOCTL_VIDEO_SET_CURRENT_MODE +// IOCTL_VIDEO_RESET_DEVICE +// IOCTL_VIDEO_MAP_VIDEO_MEMORY +// IOCTL_VIDEO_UNMAP_VIDEO_MEMORY +// IOCTL_VIDEO_SHARE_VIDEO_MEMORY +// IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY +// Optional VRPs: +// IOCTL_VIDEO_GET_PUBLIC_ACCESS_RANGES +// IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES +// IOCTL_VIDEO_GET_POWER_MANAGEMENT +// IOCTL_VIDEO_SET_POWER_MANAGEMENT +// IOCTL_QUERY_COLOR_CAPABILITIES +// IOCTL_VIDEO_SET_COLOR_REGISTERS (required if the device has a palette) +// IOCTL_VIDEO_DISABLE_POINTER +// IOCTL_VIDEO_ENABLE_POINTER +// IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES +// IOCTL_VIDEO_QUERY_POINTER_ATTR +// IOCTL_VIDEO_SET_POINTER_ATTR +// IOCTL_VIDEO_QUERY_POINTER_POSITION +// IOCTL_VIDEO_SET_POINTER_POSITION +// IOCTL_VIDEO_SAVE_HARDWARE_STATE +// IOCTL_VIDEO_RESTORE_HARDWARE_STATE +// IOCTL_VIDEO_DISABLE_CURSOR +// IOCTL_VIDEO_ENABLE_CURSOR +// IOCTL_VIDEO_QUERY_CURSOR_ATTR +// IOCTL_VIDEO_SET_CURSOR_ATTR +// IOCTL_VIDEO_QUERY_CURSOR_POSITION +// IOCTL_VIDEO_SET_CURSOR_POSITION +// IOCTL_VIDEO_GET_BANK_SELECT_CODE +// IOCTL_VIDEO_SET_PALETTE_REGISTERS +// IOCTL_VIDEO_LOAD_AND_SET_FONT +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// PVIDEO_REQUEST_PACKET RequestPacket +// RETURNS: +// BOOLEAN This function must return TRUE, and complete the work or +// set an error status in the VRP. + +static BOOLEAN STDCALL +VGAStartIO(PVOID DeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket) +{ + switch (RequestPacket->IoControlCode) + { + case IOCTL_VIDEO_MAP_VIDEO_MEMORY: + VGAMapVideoMemory((PVIDEO_MEMORY) RequestPacket->InputBuffer, + (PVIDEO_MEMORY_INFORMATION) + RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_AVAIL_MODES: + VGAQueryAvailModes((PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_CURRENT_MODE: + VGAQueryCurrentMode((PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: + VGAQueryNumAvailModes((PVIDEO_NUM_MODES) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_RESET_DEVICE: + VGAResetDevice(RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_SET_COLOR_REGISTERS: + VGASetColorRegisters((PVIDEO_CLUT) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_SET_CURRENT_MODE: + VGASetCurrentMode((PVIDEO_MODE) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: + VGAShareVideoMemory((PVIDEO_SHARE_MEMORY) RequestPacket->InputBuffer, + (PVIDEO_MEMORY_INFORMATION) RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: + VGAUnmapVideoMemory((PVIDEO_MEMORY) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: + VGAUnshareVideoMemory((PVIDEO_MEMORY) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + case IOCTL_VIDEO_SET_PALETTE_REGISTERS: + VGASetPaletteRegisters((PWORD) RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + +#if 0 + case IOCTL_VIDEO_DISABLE_CURSOR: + case IOCTL_VIDEO_DISABLE_POINTER: + case IOCTL_VIDEO_ENABLE_CURSOR: + case IOCTL_VIDEO_ENABLE_POINTER: + + case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES: + VGAFreePublicAccessRanges((PVIDEO_PUBLIC_ACCESS_RANGES) + RequestPacket->InputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_GET_BANK_SELECT_CODE: + case IOCTL_VIDEO_GET_POWER_MANAGEMENT: + case IOCTL_VIDEO_LOAD_AND_SET_FONT: + case IOCTL_VIDEO_QUERY_CURSOR_POSITION: + case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES: + case IOCTL_VIDEO_QUERY_CURSOR_ATTR: + case IOCTL_VIDEO_QUERY_POINTER_ATTR: + case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES: + case IOCTL_VIDEO_QUERY_POINTER_POSITION: + + case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES: + VGAQueryPublicAccessRanges((PVIDEO_PUBLIC_ACCESS_RANGES) + RequestPacket->OutputBuffer, + RequestPacket->StatusBlock); + break; + + case IOCTL_VIDEO_RESTORE_HARDWARE_STATE: + case IOCTL_VIDEO_SAVE_HARDWARE_STATE: + case IOCTL_VIDEO_SET_CURSOR_ATTR: + case IOCTL_VIDEO_SET_CURSOR_POSITION: + case IOCTL_VIDEO_SET_POINTER_ATTR: + case IOCTL_VIDEO_SET_POINTER_POSITION: + case IOCTL_VIDEO_SET_POWER_MANAGEMENT: + +#endif + + default: + RequestPacket->StatusBlock->Status = STATUS_NOT_IMPLEMENTED; + break; + } + + return TRUE; +} + +#if 0 +// VGAInterrupt +// +// DESCRIPTION: +// This function will be called upon receipt of a adapter generated +// interrupt when enabled. +// +// RUN LEVEL: +// IRQL +// +// ARGUMENTS: +// PVOID DeviceExtension +// RETURNS: +// BOOLEAN TRUE if the interrupt was handled by the routine + +static BOOLEAN STDCALL +VGAInterrupt(PVOID DeviceExtension) +{ + return(TRUE); +} + +// VGAResetHw +// +// DESCRIPTION: +// This function is called to reset the hardware to a known state +// if calling a BIOS int 10 reset will not achieve this result. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// ULONG Columns Columns and Rows specify the mode parameters +// ULONG Rows to reset to. +// RETURNS: +// BOOLEAN TRUE if no further action is necessary, FALSE if the system +// needs to still do a BOIS int 10 reset. + +static BOOLEAN STDCALL +VGAResetHw(PVOID DeviceExtension, + ULONG Columns, + ULONG Rows) +{ + return(TRUE); +} + +// VGATimer +// +// DESCRIPTION: +// This function will be called once a second when enabled +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// PVOID DeviceExtension +// RETURNS: +// VOID + +static VOID STDCALL +VGATimer(PVOID DeviceExtension) +{ +} + +#endif + +VOID VGAMapVideoMemory(IN PVIDEO_MEMORY RequestedAddress, + OUT PVIDEO_MEMORY_INFORMATION MapInformation, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAQueryAvailModes(OUT PVIDEO_MODE_INFORMATION ReturnedModes, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAQueryCurrentMode(OUT PVIDEO_MODE_INFORMATION CurrentMode, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAQueryNumAvailModes(OUT PVIDEO_NUM_MODES NumberOfModes, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGASetPaletteRegisters(IN PWORD PaletteRegisters, + OUT PSTATUS_BLOCK StatusBlock) +{ + ; + +/* + We don't need the following code because the palette registers are set correctly on VGA initialization. + Still, we may include\test this is in the future. + + int i, j = 2; + char tmp, v; + + tmp = VideoPortReadPortUchar(0x03da); + v = VideoPortReadPortUchar(0x03c0); + + // Set the first 16 palette registers to map to the first 16 palette colors + for (i=PaletteRegisters[1]; iFirstEntry; iNumEntries; i++) + { + VideoPortWritePortUchar((PUCHAR)0x03c8, i); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[i].RgbArray.Red); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[i].RgbArray.Green); + VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[i].RgbArray.Blue); + } +} + +VOID VGASetCurrentMode(IN PVIDEO_MODE RequestedMode, + OUT PSTATUS_BLOCK StatusBlock) +{ + if(RequestedMode->RequestedMode == 12) + { + InitVGAMode(); + } else { + DbgPrint("Unrecognised mode for VGASetCurrentMode\n"); + } +} + +VOID VGAShareVideoMemory(IN PVIDEO_SHARE_MEMORY RequestedMemory, + OUT PVIDEO_MEMORY_INFORMATION ReturnedMemory, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAUnmapVideoMemory(IN PVIDEO_MEMORY MemoryToUnmap, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} + +VOID VGAUnshareVideoMemory(IN PVIDEO_MEMORY MemoryToUnshare, + OUT PSTATUS_BLOCK StatusBlock) +{ + UNIMPLEMENTED; +} diff --git a/drivers/dd/vga/miniport/vgamp.rc b/drivers/dd/vga/miniport/vgamp.rc new file mode 100644 index 0000000..b9c24bd --- /dev/null +++ b/drivers/dd/vga/miniport/vgamp.rc @@ -0,0 +1,38 @@ +#include "../../../../include/defines.h" +#include "../../../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "VGA Miniport Device Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "vgamp\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vgamp.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/dd/vga/miniport/vgavideo.c b/drivers/dd/vga/miniport/vgavideo.c new file mode 100644 index 0000000..faafdbc --- /dev/null +++ b/drivers/dd/vga/miniport/vgavideo.c @@ -0,0 +1,94 @@ +#include "vgavideo.h" + +div_t div(int num, int denom) +{ + div_t r; + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} + +int mod(int num, int denom) +{ + div_t dvt = div(num, denom); + return dvt.rem; +} + +VOID vgaPreCalc() +{ + ULONG j; + + startmasks[1] = 127; + startmasks[2] = 63; + startmasks[3] = 31; + startmasks[4] = 15; + startmasks[5] = 7; + startmasks[6] = 3; + startmasks[7] = 1; + startmasks[8] = 255; + + endmasks[0] = 128; + endmasks[1] = 192; + endmasks[2] = 224; + endmasks[3] = 240; + endmasks[4] = 248; + endmasks[5] = 252; + endmasks[6] = 254; + endmasks[7] = 255; + endmasks[8] = 255; + + for(j=0; j<80; j++) + { + maskbit[j*8] = 128; + maskbit[j*8+1] = 64; + maskbit[j*8+2] = 32; + maskbit[j*8+3] = 16; + maskbit[j*8+4] = 8; + maskbit[j*8+5] = 4; + maskbit[j*8+6] = 2; + maskbit[j*8+7] = 1; + + bit8[j*8] = 7; + bit8[j*8+1] = 6; + bit8[j*8+2] = 5; + bit8[j*8+3] = 4; + bit8[j*8+4] = 3; + bit8[j*8+5] = 2; + bit8[j*8+6] = 1; + bit8[j*8+7] = 0; + } + for(j=0; j<480; j++) + { + y80[j] = j*80; + } + for(j=0; j<640; j++) + { + xconv[j] = j >> 3; + } +} + +void vgaSetWriteMode(char mode) +{ + VideoPortWritePortUchar((PUCHAR)0x03ce, 0x03); + VideoPortWritePortUchar((PUCHAR)0x03cf, mode); +} + +void vgaSetColor(int cindex, int red, int green, int blue) +{ + VideoPortWritePortUchar((PUCHAR)0x03c8, cindex); + VideoPortWritePortUchar((PUCHAR)0x03c9, red); + VideoPortWritePortUchar((PUCHAR)0x03c9, green); + VideoPortWritePortUchar((PUCHAR)0x03c9, blue); +} diff --git a/drivers/dd/vga/miniport/vgavideo.h b/drivers/dd/vga/miniport/vgavideo.h new file mode 100644 index 0000000..9fb566b --- /dev/null +++ b/drivers/dd/vga/miniport/vgavideo.h @@ -0,0 +1,34 @@ +#include +#include + +#define VGA_NORMAL 0 +#define VGA_AND 8 +#define VGA_OR 16 +#define VGA_XOR 24 + +//This is in mingw standard headers +//typedef struct { int quot, rem; } div_t; + +int maskbit[640], y80[480], xconv[640], bit8[640], startmasks[8], endmasks[8]; + +char* vidmem; + +#define MISC 0x3c2 +#define SEQ 0x3c4 +#define CRTC 0x3d4 +#define GRAPHICS 0x3ce +#define FEATURE 0x3da +#define ATTRIB 0x3c0 +#define STATUS 0x3da + +typedef struct _VideoMode { + unsigned short VidSeg; + unsigned char Misc; + unsigned char Feature; + unsigned short Seq[6]; + unsigned short Crtc[25]; + unsigned short Gfx[9]; + unsigned char Attrib[21]; +} VideoMode; + +VOID vgaPreCalc(); diff --git a/drivers/dd/vidport/.cvsignore b/drivers/dd/vidport/.cvsignore new file mode 100644 index 0000000..6469429 --- /dev/null +++ b/drivers/dd/vidport/.cvsignore @@ -0,0 +1,2 @@ +vidport.coff +vidport.sys.unstripped diff --git a/drivers/dd/vidport/makefile b/drivers/dd/vidport/makefile new file mode 100644 index 0000000..224ef06 --- /dev/null +++ b/drivers/dd/vidport/makefile @@ -0,0 +1,15 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = vidport + +TARGET_CFLAGS = + +TARGET_OBJECTS = vidport.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/dd/vidport/vidport.c b/drivers/dd/vidport/vidport.c new file mode 100644 index 0000000..eab93f2 --- /dev/null +++ b/drivers/dd/vidport/vidport.c @@ -0,0 +1,806 @@ +/* $Id$ + * + * VideoPort driver + * Written by Rex Jolliff + */ + +#include +#include + +#include "../../../ntoskrnl/include/internal/v86m.h" + +#include "vidport.h" + +#define NDEBUG +#include + +//#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0) + +#define VERSION "0.0.0" + +static VOID STDCALL VidStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +static NTSTATUS STDCALL VidDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp); +static NTSTATUS STDCALL VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +static BOOLEAN CsrssInitialized = FALSE; +static HANDLE CsrssHandle = 0; +static struct _EPROCESS* Csrss = NULL; + +PBYTE ReturnCsrssAddress(void) +{ + return (PBYTE)Csrss; +} + +// ------------------------------------------------------- Public Interface + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject System allocated Driver Object +// for this driver +// IN PUNICODE_STRING RegistryPath Name of registry driver service +// key +// +// RETURNS: +// NTSTATUS + +STDCALL NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + return(STATUS_SUCCESS); +} + +VOID +VideoPortDebugPrint(IN ULONG DebugPrintLevel, + IN PCHAR DebugMessage, ...) +{ + char Buffer[256]; + va_list ap; + +/* + if (DebugPrintLevel > InternalDebugLevel) + return; +*/ + va_start (ap, DebugMessage); + vsprintf (Buffer, DebugMessage, ap); + va_end (ap); + + DbgPrint (Buffer); +} + +VP_STATUS +STDCALL +VideoPortDisableInterrupt(IN PVOID HwDeviceExtension) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortEnableInterrupt(IN PVOID HwDeviceExtension) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension, + IN PVOID MappedAddress) +{ + UNIMPLEMENTED; +} + +ULONG +STDCALL +VideoPortGetBusData(IN PVOID HwDeviceExtension, + IN BUS_DATA_TYPE BusDataType, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + return HalGetBusDataByOffset(BusDataType, + 0, + SlotNumber, + Buffer, + Offset, + Length); +} + +UCHAR +STDCALL +VideoPortGetCurrentIrql(VOID) +{ + return KeGetCurrentIrql(); +} + +PVOID +STDCALL +VideoPortGetDeviceBase(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfUchars, + IN UCHAR InIoSpace) +{ + if (InIoSpace) + { + return MmMapIoSpace(IoAddress, NumberOfUchars, FALSE); + } + else + { + UNIMPLEMENTED; + return NULL; + } +} + +VP_STATUS +STDCALL +VideoPortGetDeviceData(IN PVOID HwDeviceExtension, + IN VIDEO_DEVICE_DATA_TYPE DeviceDataType, + IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine, + IN PVOID Context) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortGetAccessRanges(IN PVOID HwDeviceExtension, + IN ULONG NumRequestedResources, + IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRanges, + IN PVOID VendorId, + IN PVOID DeviceId, + IN PULONG Slot) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension, + IN PWSTR ParameterName, + IN UCHAR IsParameterFileName, + IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine, + IN PVOID Context) +{ + UNIMPLEMENTED; +} + +ULONG STDCALL +VideoPortInitialize(IN PVOID Context1, + IN PVOID Context2, + IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData, + IN PVOID HwContext) +{ + UCHAR Again; + WCHAR DeviceBuffer[20]; + WCHAR SymlinkBuffer[20]; + NTSTATUS Status; + PDRIVER_OBJECT MPDriverObject = (PDRIVER_OBJECT) Context1; + PDEVICE_OBJECT MPDeviceObject; + VIDEO_PORT_CONFIG_INFO ConfigInfo; + PVIDEOPORT_EXTENSION_DATA ExtensionData; + ULONG DeviceNumber = 0; + UNICODE_STRING DeviceName; + UNICODE_STRING SymlinkName; + CLIENT_ID Cid; + + /* Build Dispatch table from passed data */ + MPDriverObject->DriverStartIo = (PDRIVER_STARTIO) HwInitializationData->HwStartIO; + + /* Create a unicode device name */ + Again = FALSE; + do + { + swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber); + RtlInitUnicodeString(&DeviceName, DeviceBuffer); + + /* Create the device */ + Status = IoCreateDevice(MPDriverObject, + HwInitializationData->HwDeviceExtensionSize + + sizeof(VIDEOPORT_EXTENSION_DATA), + &DeviceName, + FILE_DEVICE_VIDEO, + 0, + TRUE, + &MPDeviceObject); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoCreateDevice call failed\n",0); + return Status; + } + + MPDriverObject->DeviceObject = MPDeviceObject; + + /* initialize the miniport drivers dispatch table */ + MPDriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatchOpenClose; + MPDriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatchOpenClose; + MPDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatchDeviceControl; + + /* create symbolic link "\??\DISPLAYx" */ + swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber+1); + RtlInitUnicodeString (&SymlinkName, + SymlinkBuffer); + IoCreateSymbolicLink (&SymlinkName, + &DeviceName); + + ExtensionData = + (PVIDEOPORT_EXTENSION_DATA) MPDeviceObject->DeviceExtension; + ExtensionData->DeviceObject = MPDeviceObject; + + /* Set the buffering strategy here... */ + /* If you change this, remember to change VidDispatchDeviceControl too */ + MPDeviceObject->Flags |= DO_BUFFERED_IO; + + /* Call HwFindAdapter entry point */ + /* FIXME: Need to figure out what string to pass as param 3 */ + Status = HwInitializationData->HwFindAdapter(VPExtensionToMPExtension(ExtensionData), + Context2, + L"", + &ConfigInfo, + &Again); + if (!NT_SUCCESS(Status)) + { + DbgPrint("HwFindAdapter call failed\n"); + IoDeleteDevice(MPDeviceObject); + + return Status; + } + + /* FIXME: Allocate hardware resources for device */ + + /* Allocate interrupt for device */ + if (HwInitializationData->HwInterrupt != NULL && + !(ConfigInfo.BusInterruptLevel == 0 && + ConfigInfo.BusInterruptVector == 0)) + { +#if 0 + ExtensionData->IRQL = ConfigInfo.BusInterruptLevel; + ExtensionData->InterruptLevel = + HalGetInterruptVector(ConfigInfo.AdapterInterfaceType, + ConfigInfo.SystemIoBusNumber, + ConfigInfo.BusInterruptLevel, + ConfigInfo.BusInterruptVector, + &ExtensionData->IRQL, + &ExtensionData->Affinity); + KeInitializeSpinLock(&ExtensionData->InterruptSpinLock); + Status = IoConnectInterrupt(&ExtensionData->InterruptObject, + (PKSERVICE_ROUTINE) + HwInitializationData->HwInterrupt, + VPExtensionToMPExtension(ExtensionData), + &ExtensionData->InterruptSpinLock, + ExtensionData->InterruptLevel, + ExtensionData->IRQL, + ExtensionData->IRQL, + ConfigInfo.InterruptMode, + FALSE, + ExtensionData->Affinity, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoConnectInterrupt failed\n"); + IoDeleteDevice(MPDeviceObject); + + return Status; + } +#endif + } + DeviceNumber++; + } + while (Again); + + /* FIXME: initialize timer routine for MP Driver */ + if (HwInitializationData->HwTimer != NULL) + { + Status = IoInitializeTimer(MPDeviceObject, + (PIO_TIMER_ROUTINE) + HwInitializationData->HwTimer, + VPExtensionToMPExtension(ExtensionData)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoInitializeTimer failed\n"); + + if (HwInitializationData->HwInterrupt != NULL) + { + IoDisconnectInterrupt(ExtensionData->InterruptObject); + } + IoDeleteDevice(MPDeviceObject); + + return Status; + } + } + + return STATUS_SUCCESS; +} + +VP_STATUS STDCALL +VideoPortInt10(IN PVOID HwDeviceExtension, + IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments) +{ + KV86M_REGISTERS Regs; + NTSTATUS Status; + + KeAttachProcess(Csrss); + + memset(&Regs, 0, sizeof(Regs)); + Regs.Eax = BiosArguments->Eax; + Regs.Ebx = BiosArguments->Ebx; + Regs.Ecx = BiosArguments->Ecx; + Regs.Edx = BiosArguments->Edx; + Regs.Esi = BiosArguments->Esi; + Regs.Edi = BiosArguments->Edi; + Regs.Ebp = BiosArguments->Ebp; + Status = Ke386CallBios(0x10, &Regs); + + KeDetachProcess(); + + return(Status); +} + +VOID +STDCALL +VideoPortLogError(IN PVOID HwDeviceExtension, + IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL, + IN VP_STATUS ErrorCode, + IN ULONG UniqueId) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortMapBankedMemory(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN PULONG Length, + IN PULONG InIoSpace, + OUT PVOID *VirtualAddress, + IN ULONG BankLength, + IN UCHAR ReadWriteBank, + IN PBANKED_SECTION_ROUTINE BankRoutine, + IN PVOID Context) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortMapMemory(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN PULONG Length, + IN PULONG InIoSpace, + OUT PVOID *VirtualAddress) +{ + if (*InIoSpace) + { + *VirtualAddress = MmMapIoSpace(PhysicalAddress, *Length, FALSE); + + return *VirtualAddress != NULL ? STATUS_SUCCESS : + STATUS_INSUFFICIENT_RESOURCES; + } + else + { + UNIMPLEMENTED; + } + + return STATUS_SUCCESS; +} + +UCHAR +STDCALL +VideoPortReadPortUchar(IN PUCHAR Port) +{ + return READ_PORT_UCHAR(Port); +} + +USHORT +STDCALL +VideoPortReadPortUshort(IN PUSHORT Port) +{ + return READ_PORT_USHORT(Port); +} + +ULONG +STDCALL +VideoPortReadPortUlong(IN PULONG Port) +{ + return READ_PORT_ULONG(Port); +} + +VOID +STDCALL +VideoPortReadPortBufferUchar(IN PUCHAR Port, + OUT PUCHAR Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadPortBufferUshort(IN PUSHORT Port, + OUT PUSHORT Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadPortBufferUlong(IN PULONG Port, + OUT PULONG Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +UCHAR +STDCALL +VideoPortReadRegisterUchar(IN PUCHAR Register) +{ + return READ_REGISTER_UCHAR(Register); +} + +USHORT +STDCALL +VideoPortReadRegisterUshort(IN PUSHORT Register) +{ + return READ_REGISTER_USHORT(Register); +} + +ULONG +STDCALL +VideoPortReadRegisterUlong(IN PULONG Register) +{ + return READ_REGISTER_ULONG(Register); +} + +VOID +STDCALL +VideoPortReadRegisterBufferUchar(IN PUCHAR Register, + OUT PUCHAR Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadRegisterBufferUshort(IN PUSHORT Register, + OUT PUSHORT Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID +STDCALL +VideoPortReadRegisterBufferUlong(IN PULONG Register, + OUT PULONG Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +BOOLEAN +STDCALL +VideoPortScanRom(IN PVOID HwDeviceExtension, + IN PUCHAR RomBase, + IN ULONG RomLength, + IN PUCHAR String) +{ + UNIMPLEMENTED; +} + +ULONG +STDCALL +VideoPortSetBusData(IN PVOID HwDeviceExtension, + IN BUS_DATA_TYPE BusDataType, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + return HalSetBusDataByOffset(BusDataType, + 0, + SlotNumber, + Buffer, + Offset, + Length); +} + +VP_STATUS +STDCALL +VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension, + IN PWSTR ValueName, + IN PVOID ValueData, + IN ULONG ValueLength) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRange) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +VideoPortStartTimer(IN PVOID HwDeviceExtension) +{ + PVIDEOPORT_EXTENSION_DATA ExtensionData = + MPExtensionToVPExtension(HwDeviceExtension); + + IoStartTimer(ExtensionData->DeviceObject); +} + +VOID +STDCALL +VideoPortStopTimer(IN PVOID HwDeviceExtension) +{ + PVIDEOPORT_EXTENSION_DATA ExtensionData = + MPExtensionToVPExtension(HwDeviceExtension); + + IoStopTimer(ExtensionData->DeviceObject); +} + +BOOLEAN +STDCALL +VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension, + IN VIDEO_SYNCHRONIZE_PRIORITY Priority, + IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine, + OUT PVOID Context) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortUnmapMemory(IN PVOID HwDeviceExtension, + IN PVOID VirtualAddress, + IN HANDLE ProcessHandle) +{ + UNIMPLEMENTED; +} + +VP_STATUS +STDCALL +VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRanges) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +VideoPortWritePortUchar(IN PUCHAR Port, + IN UCHAR Value) +{ + WRITE_PORT_UCHAR(Port, Value); +} + +VOID +STDCALL +VideoPortWritePortUshort(IN PUSHORT Port, + IN USHORT Value) +{ + WRITE_PORT_USHORT(Port, Value); +} + +VOID +STDCALL +VideoPortWritePortUlong(IN PULONG Port, + IN ULONG Value) +{ + WRITE_PORT_ULONG(Port, Value); +} + +VOID +STDCALL +VideoPortWritePortBufferUchar(IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortWritePortBufferUshort(IN PUSHORT Port, + IN PUSHORT Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortWritePortBufferUlong(IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +VOID +STDCALL +VideoPortWriteRegisterUchar(IN PUCHAR Register, + IN UCHAR Value) +{ + WRITE_REGISTER_UCHAR(Register, Value); +} + +VOID +STDCALL +VideoPortWriteRegisterUshort(IN PUSHORT Register, + IN USHORT Value) +{ + WRITE_REGISTER_USHORT(Register, Value); +} + +VOID +STDCALL +VideoPortWriteRegisterUlong(IN PULONG Register, + IN ULONG Value) +{ + WRITE_REGISTER_ULONG(Register, Value); +} + +VOID +STDCALL +VideoPortWriteRegisterBufferUchar(IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID STDCALL +VideoPortWriteRegisterBufferUshort(IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID STDCALL +VideoPortWriteRegisterBufferUlong(IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +VOID STDCALL +VideoPortZeroDeviceMemory(OUT PVOID Destination, + IN ULONG Length) +{ + UNIMPLEMENTED; +} + + +// ------------------------------------------- Nondiscardable statics + +// VidDispatchOpenClose +// +// DESCRIPTION: +// Answer requests for Open/Close calls: a null operation +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +VidDispatchOpenClose(IN PDEVICE_OBJECT pDO, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + + DPRINT("VidDispatchOpenClose() called\n"); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + if (IrpStack->MajorFunction == IRP_MJ_CREATE && + CsrssInitialized == FALSE) + { + DPRINT("Referencing CSRSS\n"); + Csrss = PsGetCurrentProcess(); + CsrssInitialized = TRUE; + DPRINT("Csrss %p\n", Csrss); + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +// VidStartIo +// +// DESCRIPTION: +// Get the next requested I/O packet started +// +// RUN LEVEL: +// DISPATCH_LEVEL +// +// ARGUMENTS: +// Dispatch routine standard arguments +// +// RETURNS: +// NTSTATUS +// + +static VOID STDCALL +VidStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; +} + +// VidDispatchDeviceControl +// +// DESCRIPTION: +// Answer requests for device control calls +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// Standard dispatch arguments +// +// RETURNS: +// NTSTATUS +// + +static NTSTATUS STDCALL +VidDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IrpStack; + PVIDEO_REQUEST_PACKET vrp; + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + // Translate the IRP to a VRP + vrp = ExAllocatePool(PagedPool, sizeof(VIDEO_REQUEST_PACKET)); + vrp->StatusBlock = ExAllocatePool(PagedPool, sizeof(STATUS_BLOCK)); + vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + + // We're assuming METHOD_BUFFERED + vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer; + vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + vrp->OutputBuffer = Irp->UserBuffer; + vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + // Call the Miniport Driver with the VRP + DeviceObject->DriverObject->DriverStartIo(DeviceObject->DeviceExtension, (PIRP)vrp); + + // Translate the VRP back into the IRP for OutputBuffer + Irp->UserBuffer = vrp->OutputBuffer; + IrpStack->Parameters.DeviceIoControl.OutputBufferLength = vrp->OutputBufferLength; + + // Free the VRP + ExFreePool(vrp->StatusBlock); + ExFreePool(vrp); + + return STATUS_SUCCESS; +} diff --git a/drivers/dd/vidport/vidport.def b/drivers/dd/vidport/vidport.def new file mode 100644 index 0000000..ae1616e --- /dev/null +++ b/drivers/dd/vidport/vidport.def @@ -0,0 +1,60 @@ +; $Id$ +; +; vidport.def - export definition file for ReactOS +; +EXPORTS +ReturnCsrssAddress +VideoPortCompareMemory@12 +VideoPortDebugPrint +VideoPortDisableInterrupt@4 +VideoPortEnableInterrupt@4 +VideoPortFreeDeviceBase@8 +VideoPortGetBusData@24 +VideoPortGetCurrentIrql@0 +VideoPortGetDeviceBase@20 +VideoPortGetDeviceData@16 +VideoPortGetAccessRanges@32 +VideoPortGetRegistryParameters@20 +VideoPortInitialize@16 +VideoPortInt10@8 +VideoPortLogError@16 +VideoPortMapBankedMemory@40 +VideoPortMapMemory@24 +VideoPortMoveMemory@12 +VideoPortReadPortUchar@4 +VideoPortReadPortUshort@4 +VideoPortReadPortUlong@4 +VideoPortReadPortBufferUchar@12 +VideoPortReadPortBufferUshort@12 +VideoPortReadPortBufferUlong@12 +VideoPortReadRegisterUchar@4 +VideoPortReadRegisterUshort@4 +VideoPortReadRegisterUlong@4 +VideoPortReadRegisterBufferUchar@12 +VideoPortReadRegisterBufferUshort@12 +VideoPortReadRegisterBufferUlong@12 +VideoPortScanRom@16 +VideoPortSetBusData@24 +VideoPortSetRegistryParameters@16 +VideoPortSetTrappedEmulatorPorts@12 +VideoPortStallExecution@4 +VideoPortStartTimer@4 +VideoPortStopTimer@4 +VideoPortSynchronizeExecution@16 +VideoPortUnmapMemory@12 +VideoPortVerifyAccessRanges@12 +VideoPortWritePortUchar@8 +VideoPortWritePortUshort@8 +VideoPortWritePortUlong@8 +VideoPortWritePortBufferUchar@12 +VideoPortWritePortBufferUshort@12 +VideoPortWritePortBufferUlong@12 +VideoPortWriteRegisterUchar@8 +VideoPortWriteRegisterUshort@8 +VideoPortWriteRegisterUlong@8 +VideoPortWriteRegisterBufferUchar@12 +VideoPortWriteRegisterBufferUshort@12 +VideoPortWriteRegisterBufferUlong@12 +VideoPortZeroMemory@8 +VideoPortZeroDeviceMemory@8 + diff --git a/drivers/dd/vidport/vidport.edf b/drivers/dd/vidport/vidport.edf new file mode 100644 index 0000000..d343f60 --- /dev/null +++ b/drivers/dd/vidport/vidport.edf @@ -0,0 +1,61 @@ +; $Id$ +; +; vidport.def - export definition file for ReactOS +; +EXPORTS +ReturnCsrssAddress +VideoPortCompareMemory=NTOSKRNL.RtlCompareMemory +VideoPortDebugPrint +VideoPortDisableInterrupt=VideoPortDisableInterrupt@4 +VideoPortEnableInterrupt=VideoPortEnableInterrupt@4 +VideoPortFreeDeviceBase=VideoPortFreeDeviceBase@8 +VideoPortGetBusData=VideoPortGetBusData@24 +VideoPortGetCurrentIrql=VideoPortGetCurrentIrql@0 +VideoPortGetDeviceBase=VideoPortGetDeviceBase@20 +VideoPortGetDeviceData=VideoPortGetDeviceData@16 +VideoPortGetAccessRanges=VideoPortGetAccessRanges@32 +VideoPortGetRegistryParameters=VideoPortGetRegistryParameters@20 +VideoPortInitialize=VideoPortInitialize@16 +VideoPortInt10=VideoPortInt10@8 +VideoPortLogError=VideoPortLogError@16 +VideoPortMapBankedMemory=VideoPortMapBankedMemory@40 +VideoPortMapMemory=VideoPortMapMemory@24 +VideoPortMoveMemory=NTOSKRNL.RtlMoveMemory +VideoPortReadPortUchar=VideoPortReadPortUchar@4 +VideoPortReadPortUshort=VideoPortReadPortUshort@4 +VideoPortReadPortUlong=VideoPortReadPortUlong@4 +VideoPortReadPortBufferUchar=VideoPortReadPortBufferUchar@12 +VideoPortReadPortBufferUshort=VideoPortReadPortBufferUshort@12 +VideoPortReadPortBufferUlong=VideoPortReadPortBufferUlong@12 +VideoPortReadRegisterUchar=VideoPortReadRegisterUchar@4 +VideoPortReadRegisterUshort=VideoPortReadRegisterUshort@4 +VideoPortReadRegisterUlong=VideoPortReadRegisterUlong@4 +VideoPortReadRegisterBufferUchar=VideoPortReadRegisterBufferUchar@12 +VideoPortReadRegisterBufferUshort=VideoPortReadRegisterBufferUshort@12 +VideoPortReadRegisterBufferUlong=VideoPortReadRegisterBufferUlong@12 +VideoPortScanRom=VideoPortScanRom@16 +VideoPortSetBusData=VideoPortSetBusData@24 +VideoPortSetRegistryParameters=VideoPortSetRegistryParameters@16 +VideoPortSetTrappedEmulatorPorts=VideoPortSetTrappedEmulatorPorts@12 +;VideoPortStallExecution=HAL.KeStallExecutionProcessor +VideoPortStallExecution=NTOSKRNL.KeStallExecutionProcessor +VideoPortStartTimer=VideoPortStartTimer@4 +VideoPortStopTimer=VideoPortStopTimer@4 +VideoPortSynchronizeExecution=VideoPortSynchronizeExecution@16 +VideoPortUnmapMemory=VideoPortUnmapMemory@12 +VideoPortVerifyAccessRanges=VideoPortVerifyAccessRanges@12 +VideoPortWritePortUchar=VideoPortWritePortUchar@8 +VideoPortWritePortUshort=VideoPortWritePortUshort@8 +VideoPortWritePortUlong=VideoPortWritePortUlong@8 +VideoPortWritePortBufferUchar=VideoPortWritePortBufferUchar@12 +VideoPortWritePortBufferUshort=VideoPortWritePortBufferUshort@12 +VideoPortWritePortBufferUlong=VideoPortWritePortBufferUlong@12 +VideoPortWriteRegisterUchar=VideoPortWriteRegisterUchar@8 +VideoPortWriteRegisterUshort=VideoPortWriteRegisterUshort@8 +VideoPortWriteRegisterUlong=VideoPortWriteRegisterUlong@8 +VideoPortWriteRegisterBufferUchar=VideoPortWriteRegisterBufferUchar@12 +VideoPortWriteRegisterBufferUshort=VideoPortWriteRegisterBufferUshort@12 +VideoPortWriteRegisterBufferUlong=VideoPortWriteRegisterBufferUlong@12 +VideoPortZeroMemory=NTOSKRNL.RtlZeroMemory +VideoPortZeroDeviceMemory=VideoPortZeroDeviceMemory@8 + diff --git a/drivers/dd/vidport/vidport.h b/drivers/dd/vidport/vidport.h new file mode 100644 index 0000000..ed824e6 --- /dev/null +++ b/drivers/dd/vidport/vidport.h @@ -0,0 +1,16 @@ + +typedef struct _VIDEOPORT_EXTENSTION_DATA +{ + PDEVICE_OBJECT DeviceObject; + PKINTERRUPT InterruptObject; + KSPIN_LOCK InterruptSpinLock; + ULONG InterruptLevel; + KIRQL IRQL; + KAFFINITY Affinity; +} VIDEOPORT_EXTENSION_DATA, *PVIDEOPORT_EXTENSION_DATA; + +#define MPExtensionToVPExtension(MPX) \ + ((PVIDEOPORT_EXTENSION_DATA) ((DWORD) (MPX) - sizeof(VIDEOPORT_EXTENSION_DATA))) +#define VPExtensionToMPExtension(VPX) \ + ((PVOID) ((DWORD) (VPX) + sizeof(VIDEOPORT_EXTENSION_DATA))) + diff --git a/drivers/dd/vidport/vidport.rc b/drivers/dd/vidport/vidport.rc new file mode 100644 index 0000000..92f1908 --- /dev/null +++ b/drivers/dd/vidport/vidport.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Videort Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "vidport\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vidport.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/cdfs/.cvsignore b/drivers/fs/cdfs/.cvsignore new file mode 100644 index 0000000..19a0241 --- /dev/null +++ b/drivers/fs/cdfs/.cvsignore @@ -0,0 +1,6 @@ +base.tmp +junk.tmp +temp.exp +cdfs.coff +cdfs.sys.unstripped +*.d \ No newline at end of file diff --git a/drivers/fs/cdfs/cdfs.c b/drivers/fs/cdfs/cdfs.c new file mode 100644 index 0000000..bc5bf35 --- /dev/null +++ b/drivers/fs/cdfs/cdfs.c @@ -0,0 +1,108 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/cdfs.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* GLOBALS *****************************************************************/ + +PCDFS_GLOBAL_DATA CdfsGlobalData; + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Cdfs"); + + DPRINT("CDFS 0.0.2\n"); + + Status = IoCreateDevice(DriverObject, + sizeof(CDFS_GLOBAL_DATA), + &DeviceName, + FILE_DEVICE_CD_ROM_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* Initialize global data */ + CdfsGlobalData = DeviceObject->DeviceExtension; + RtlZeroMemory(CdfsGlobalData, + sizeof(CDFS_GLOBAL_DATA)); + CdfsGlobalData->DriverObject = DriverObject; + CdfsGlobalData->DeviceObject = DeviceObject; + + /* Initialize driver data */ + DeviceObject->Flags = DO_DIRECT_IO; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = CdfsClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CdfsCleanup; + DriverObject->MajorFunction[IRP_MJ_CREATE] = CdfsCreate; + DriverObject->MajorFunction[IRP_MJ_READ] = CdfsRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = CdfsWrite; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + CdfsFileSystemControl; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = + CdfsDirectoryControl; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + CdfsQueryInformation; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = + CdfsSetInformation; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = + CdfsQueryVolumeInformation; + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = + CdfsSetVolumeInformation; + + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + + return(STATUS_SUCCESS); +} + diff --git a/drivers/fs/cdfs/cdfs.h b/drivers/fs/cdfs/cdfs.h new file mode 100644 index 0000000..ba50f23 --- /dev/null +++ b/drivers/fs/cdfs/cdfs.h @@ -0,0 +1,398 @@ +#ifndef CDFS_H +#define CDFS_H + +#include + +#define CDFS_BASIC_SECTOR 2048 +#define CDFS_PRIMARY_DESCRIPTOR_LOCATION 16 +#define BLOCKSIZE CDFS_BASIC_SECTOR +#define CDFS_MAX_NAME_LEN 256 + + +/* Volume descriptor types (VdType) */ +#define BOOT_VOLUME_DESCRIPTOR_TYPE 0 +#define PRIMARY_VOLUME_DESCRIPTOR_TYPE 1 +#define SUPPLEMENTARY_VOLUME_DESCRIPTOR_TYPE 2 +#define VOLUME_PARTITION_DESCRIPTOR_TYPE 3 +#define VOLUME_DESCRIPTOR_SET_TERMINATOR 255 + +struct _DIR_RECORD +{ + UCHAR RecordLength; // 1 + UCHAR ExtAttrRecordLength; // 2 + ULONG ExtentLocationL; // 3-6 + ULONG ExtentLocationM; // 7-10 + ULONG DataLengthL; // 11-14 + ULONG DataLengthM; // 15-18 + UCHAR Year; // 19 + UCHAR Month; // 20 + UCHAR Day; // 21 + UCHAR Hour; // 22 + UCHAR Minute; // 23 + UCHAR Second; // 24 + UCHAR TimeZone; // 25 + UCHAR FileFlags; // 26 + UCHAR FileUnitSize; // 27 + UCHAR InterleaveGapSize; // 28 + ULONG VolumeSequenceNumber; // 29-32 + UCHAR FileIdLength; // 33 + UCHAR FileId[1]; // 34 +} __attribute__((packed)); + +typedef struct _DIR_RECORD DIR_RECORD, *PDIR_RECORD; + + + + +/* Volume Descriptor header*/ +struct _VD_HEADER +{ + UCHAR VdType; // 1 + UCHAR StandardId[5]; // 2-6 + UCHAR VdVersion; // 7 +} __attribute__((packed)); + +typedef struct _VD_HEADER VD_HEADER, *PVD_HEADER; + + + +/* Primary Volume Descriptor */ +struct _PVD +{ + UCHAR VdType; // 1 + UCHAR StandardId[5]; // 2-6 + UCHAR VdVersion; // 7 + UCHAR unused0; // 8 + UCHAR SystemId[32]; // 9-40 + UCHAR VolumeId[32]; // 41-72 + UCHAR unused1[8]; // 73-80 + ULONG VolumeSpaceSizeL; // 81-84 + ULONG VolumeSpaceSizeM; // 85-88 + UCHAR unused2[32]; // 89-120 + ULONG VolumeSetSize; // 121-124 + ULONG VolumeSequenceNumber; // 125-128 + ULONG LogicalBlockSize; // 129-132 + ULONG PathTableSizeL; // 133-136 + ULONG PathTableSizeM; // 137-140 + ULONG LPathTablePos; // 141-144 + ULONG LOptPathTablePos; // 145-148 + ULONG MPathTablePos; // 149-152 + ULONG MOptPathTablePos; // 153-156 + DIR_RECORD RootDirRecord; // 157-190 + UCHAR VolumeSetIdentifier[128]; // 191-318 + UCHAR PublisherIdentifier[128]; // 319-446 + + /* more data ... */ + +} __attribute__((packed)); + +typedef struct _PVD PVD, *PPVD; + + +/* Supplementary Volume Descriptor */ +struct _SVD +{ + UCHAR VdType; // 1 + UCHAR StandardId[5]; // 2-6 + UCHAR VdVersion; // 7 + UCHAR VolumeFlags; // 8 + UCHAR SystemId[32]; // 9-40 + UCHAR VolumeId[32]; // 41-72 + UCHAR unused1[8]; // 73-80 + ULONG VolumeSpaceSizeL; // 81-84 + ULONG VolumeSpaceSizeM; // 85-88 + UCHAR EscapeSequences[32]; // 89-120 + ULONG VolumeSetSize; // 121-124 + ULONG VolumeSequenceNumber; // 125-128 + ULONG LogicalBlockSize; // 129-132 + ULONG PathTableSizeL; // 133-136 + ULONG PathTableSizeM; // 137-140 + ULONG LPathTablePos; // 141-144 + ULONG LOptPathTablePos; // 145-148 + ULONG MPathTablePos; // 149-152 + ULONG MOptPathTablePos; // 153-156 + DIR_RECORD RootDirRecord; // 157-190 + UCHAR VolumeSetIdentifier[128]; // 191-318 + UCHAR PublisherIdentifier[128]; // 319-446 + + // more data ... +} __attribute__((packed)); + +typedef struct _SVD SVD, *PSVD; + + + + + + + +typedef struct _CDINFO +{ + ULONG VolumeOffset; + ULONG VolumeSpaceSize; + ULONG JolietLevel; + ULONG RootStart; + ULONG RootSize; + WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH]; + ULONG VolumeLabelLength; + ULONG SerialNumber; +} CDINFO, *PCDINFO; + + +typedef struct +{ + ERESOURCE DirResource; +// ERESOURCE FatResource; + + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + + PVPB Vpb; + PDEVICE_OBJECT StorageDevice; + PFILE_OBJECT StreamFileObject; + + CDINFO CdInfo; + + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + + +#define FCB_CACHE_INITIALIZED 0x0001 +#define FCB_IS_VOLUME_STREAM 0x0002 +#define FCB_IS_VOLUME 0x0004 + +typedef struct _FCB +{ + REACTOS_COMMON_FCB_HEADER RFCB; + SECTION_OBJECT_POINTERS SectionObjectPointers; + + PFILE_OBJECT FileObject; + PDEVICE_EXTENSION DevExt; + + WCHAR *ObjectName; /* point on filename (250 chars max) in PathName */ + WCHAR PathName[MAX_PATH]; /* path+filename 260 max */ + WCHAR ShortName[13]; + USHORT ShortNameLength; + +// ERESOURCE PagingIoResource; + ERESOURCE MainResource; + + LIST_ENTRY FcbListEntry; + struct _FCB* ParentFcb; + + ULONG DirIndex; + + LONG RefCount; + ULONG Flags; + + DIR_RECORD Entry; + + +} FCB, *PFCB; + + +typedef struct _CCB +{ + PFCB Fcb; + LIST_ENTRY NextCCB; + PFILE_OBJECT PtrFileObject; + LARGE_INTEGER CurrentByteOffset; + /* for DirectoryControl */ + ULONG Entry; + ULONG Offset; + /* for DirectoryControl */ + PWCHAR DirectorySearchPattern; + ULONG LastCluster; + ULONG LastOffset; +} CCB, *PCCB; + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +#define TAG_CCB TAG('I', 'C', 'C', 'B') + + + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; +} CDFS_GLOBAL_DATA, *PCDFS_GLOBAL_DATA; + +extern PCDFS_GLOBAL_DATA CdfsGlobalData; + + +NTSTATUS +CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer); + +int CdfsStrcmpi( wchar_t *str1, wchar_t *str2 ); +void CdfsWstrcpy( wchar_t *str1, wchar_t *str2, int max ); + +/* cleanup.c */ + +NTSTATUS STDCALL +CdfsCleanup(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* close.c */ + +NTSTATUS STDCALL +CdfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +CdfsCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject); + +/* common.c */ + +NTSTATUS +CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer); + +NTSTATUS +CdfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer); + +NTSTATUS +CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize); + +/* create.c */ + +NTSTATUS STDCALL +CdfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* dirctl.c */ + +NTSTATUS STDCALL +CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* fcb.c */ + +PFCB +CdfsCreateFCB(PWCHAR FileName); + +VOID +CdfsDestroyFCB(PFCB Fcb); + +BOOLEAN +CdfsFCBIsDirectory(PFCB Fcb); + +BOOLEAN +CdfsFCBIsRoot(PFCB Fcb); + +VOID +CdfsGrabFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +VOID +CdfsReleaseFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +VOID +CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +PFCB +CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb, + PWSTR FileName); + +NTSTATUS +CdfsFCBInitializeCache(PVCB Vcb, + PFCB Fcb); + +PFCB +CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb); + +PFCB +CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb); + + + +NTSTATUS +CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, + PFCB Fcb, + PFILE_OBJECT FileObject); + + + + +NTSTATUS +CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb, + PFCB *pParentFCB, + PFCB *pFCB, + const PWSTR pFileName); + + +/* finfo.c */ + +NTSTATUS STDCALL +CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +CdfsSetInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* fsctl.c */ + +NTSTATUS STDCALL +CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* misc.c */ + +BOOLEAN +wstrcmpjoki(PWSTR s1, PWSTR s2); + +VOID +CdfsSwapString(PWCHAR Out, + PUCHAR In, + ULONG Count); + +VOID +CdfsDateTimeToFileTime(PFCB Fcb, + TIME *FileTime); + +VOID +CdfsFileFlagsToAttributes(PFCB Fcb, + PULONG FileAttributes); + +/* rw.c */ + +NTSTATUS STDCALL +CdfsRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +CdfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* volinfo.c */ + +NTSTATUS STDCALL +CdfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +CdfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +#endif //CDFS_H diff --git a/drivers/fs/cdfs/cdfs.rc b/drivers/fs/cdfs/cdfs.rc new file mode 100644 index 0000000..4c9fb19 --- /dev/null +++ b/drivers/fs/cdfs/cdfs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ISO9660 Driver\0" + VALUE "FileVersion", "0.0.6\0" + VALUE "InternalName", "cdfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "cdfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/cdfs/cleanup.c b/drivers/fs/cdfs/cleanup.c new file mode 100644 index 0000000..d989897 --- /dev/null +++ b/drivers/fs/cdfs/cleanup.c @@ -0,0 +1,104 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/cleanup.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Hartmut Birr + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsCleanupFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject) +/* + * FUNCTION: Cleans up after a file has been closed. + */ +{ + PCCB Ccb; + + DPRINT("CdfsCleanupFile(DeviceExt %x, FileObject %x)\n", + DeviceExt, + FileObject); + + + Ccb = (PCCB) (FileObject->FsContext2); + if (Ccb == NULL) + { + return STATUS_SUCCESS; + } + + /* Uninitialize the file cache. */ + CcRosReleaseFileCache (FileObject, Ccb->Fcb->RFCB.Bcb); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +CdfsCleanup(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + + DPRINT("CdfsCleanup() called\n"); + + if (DeviceObject == CdfsGlobalData->DeviceObject) + { + DPRINT("Closing file system\n"); + Status = STATUS_SUCCESS; + goto ByeBye; + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + DeviceExtension = DeviceObject->DeviceExtension; + + ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource, TRUE); + + Status = CdfsCleanupFile(DeviceExtension, FileObject); + + ExReleaseResourceLite(&DeviceExtension->DirResource); + + +ByeBye: + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +/* EOF */ \ No newline at end of file diff --git a/drivers/fs/cdfs/close.c b/drivers/fs/cdfs/close.c new file mode 100644 index 0000000..ec17966 --- /dev/null +++ b/drivers/fs/cdfs/close.c @@ -0,0 +1,115 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/close.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +CdfsCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject) +/* + * FUNCTION: Closes a file + */ +{ + PCCB Ccb; + + DPRINT("CdfsCloseFile(DeviceExt %x, FileObject %x)\n", + DeviceExt, + FileObject); + + Ccb = (PCCB)(FileObject->FsContext2); + + DPRINT("Ccb %x\n", Ccb); + if (Ccb == NULL) + { + return(STATUS_SUCCESS); + } + + FileObject->FsContext2 = NULL; + + if (FileObject->FileName.Buffer) + { + // This a FO, that was created outside from FSD. + // Some FO's are created with IoCreateStreamFileObject() insid from FSD. + // This FO's don't have a FileName. + CdfsReleaseFCB(DeviceExt, + Ccb->Fcb); + } + + if (Ccb->DirectorySearchPattern) + { + ExFreePool(Ccb->DirectorySearchPattern); + } + ExFreePool(Ccb); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +CdfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + + DPRINT("CdfsClose() called\n"); + + if (DeviceObject == CdfsGlobalData->DeviceObject) + { + DPRINT("Closing file system\n"); + Status = STATUS_SUCCESS; + goto ByeBye; + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + DeviceExtension = DeviceObject->DeviceExtension; + + Status = CdfsCloseFile(DeviceExtension,FileObject); + +ByeBye: + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +/* EOF */ \ No newline at end of file diff --git a/drivers/fs/cdfs/common.c b/drivers/fs/cdfs/common.c new file mode 100644 index 0000000..9c65d6a --- /dev/null +++ b/drivers/fs/cdfs/common.c @@ -0,0 +1,257 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/volume.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer) +{ + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER Offset; + ULONG BlockSize; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Offset.u.LowPart = DiskSector << 11; + Offset.u.HighPart = DiskSector >> 21; + + BlockSize = BLOCKSIZE * SectorCount; + + DPRINT("CdfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", + DeviceObject, DiskSector, Buffer); + DPRINT("Offset %I64x BlockSize %ld\n", + Offset.QuadPart, + BlockSize); + + DPRINT("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + Buffer, + BlockSize, + &Offset, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT("Getting IO Status... for %x\n", Irp); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_VERIFY_REQUIRED) + { + PDEVICE_OBJECT DeviceToVerify; + NTSTATUS NewStatus; + + DPRINT1("STATUS_VERIFY_REQUIRED\n"); + DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); + IoSetDeviceToVerify(PsGetCurrentThread(), NULL); + + NewStatus = IoVerifyVolume(DeviceToVerify, FALSE); + DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus); + } + + DPRINT("CdfsReadSectors() failed (Status %x)\n", Status); + DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n", + DeviceObject, DiskSector, Buffer, + Offset.QuadPart); + return(Status); + } + + DPRINT("Block request succeeded for %x\n", Irp); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +CdfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN OUT PUCHAR Buffer) +{ + PIO_STACK_LOCATION Stack; + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER Offset; + ULONG BlockSize; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Offset.u.LowPart = DiskSector << 11; + Offset.u.HighPart = DiskSector >> 21; + + BlockSize = BLOCKSIZE * SectorCount; + + DPRINT("CdfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", + DeviceObject, DiskSector, Buffer); + DPRINT("Offset %I64x BlockSize %ld\n", + Offset.QuadPart, + BlockSize); + + DPRINT("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + Buffer, + BlockSize, + &Offset, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + +// Stack = IoGetCurrentIrpStackLocation(Irp); +// Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT("Getting IO Status... for %x\n", Irp); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS(Status)) + { + DPRINT("CdfsReadSectors() failed (Status %x)\n", Status); + DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n", + DeviceObject, DiskSector, Buffer, + Offset.QuadPart); + return(Status); + } + + DPRINT("Block request succeeded for %x\n", Irp); + + return(STATUS_SUCCESS); +} + +NTSTATUS +CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize) +{ + ULONG OutputBufferSize = 0; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + DPRINT("CdfsDeviceIoControl(DeviceObject %x, CtlCode %x, " + "InputBuffer %x, InputBufferSize %x, OutputBuffer %x, " + "POutputBufferSize %x (%x)\n", DeviceObject, CtlCode, + InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize, + pOutputBufferSize ? *pOutputBufferSize : 0); + + if (pOutputBufferSize) + { + OutputBufferSize = *pOutputBufferSize; + } + + KeInitializeEvent (&Event, NotificationEvent, FALSE); + + DPRINT("Building device I/O control request ...\n"); + Irp = IoBuildDeviceIoControlRequest(CtlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutputBufferSize, + FALSE, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + DPRINT ("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT ("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT ("Operation pending\n"); + KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT ("Getting IO Status... for %x\n", Irp); + + Status = IoStatus.Status; + } + if (OutputBufferSize) + { + *pOutputBufferSize = OutputBufferSize; + } + DPRINT("Returning Status %x\n", Status); + return Status; +} + +/* EOF */ diff --git a/drivers/fs/cdfs/create.c b/drivers/fs/cdfs/create.c new file mode 100644 index 0000000..28c4b1e --- /dev/null +++ b/drivers/fs/cdfs/create.c @@ -0,0 +1,263 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/cdfs.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject, + PWSTR pRelativeFileName, + PWSTR *pAbsoluteFilename) +{ + PWSTR rcName; + PFCB Fcb; + PCCB Ccb; + + DPRINT("try related for %S\n", pRelativeFileName); + Ccb = pFileObject->FsContext2; + assert(Ccb); + Fcb = Ccb->Fcb; + assert(Fcb); + + /* verify related object is a directory and target name + don't start with \. */ + if (Fcb->Entry.FileFlags & 0x02 == 0 || + pRelativeFileName[0] == L'\\') + { + return(STATUS_INVALID_PARAMETER); + } + + /* construct absolute path name */ + assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 + <= MAX_PATH); + rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR)); + if (!rcName) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + wcscpy(rcName, Fcb->PathName); + if (!CdfsFCBIsRoot(Fcb)) + wcscat (rcName, L"\\"); + wcscat (rcName, pRelativeFileName); + *pAbsoluteFilename = rcName; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsOpenFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PWSTR FileName) +/* + * FUNCTION: Opens a file + */ +{ + PFCB ParentFcb; + PFCB Fcb; + NTSTATUS Status; + PWSTR AbsFileName = NULL; + + DPRINT("CdfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName); + + if (FileObject->RelatedFileObject) + { + DPRINT("Converting relative filename to absolute filename\n"); + + Status = CdfsMakeAbsoluteFilename(FileObject->RelatedFileObject, + FileName, + &AbsFileName); + FileName = AbsFileName; + if (!NT_SUCCESS(Status)) + { + return(Status); + } + return(STATUS_UNSUCCESSFUL); + } + + //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators) + + DPRINT("PathName to open: %S\n", FileName); + + /* try first to find an existing FCB in memory */ + DPRINT("Checking for existing FCB in memory\n"); + Fcb = CdfsGrabFCBFromTable(DeviceExt, + FileName); + if (Fcb == NULL) + { + DPRINT("No existing FCB found, making a new one if file exists.\n"); + Status = CdfsGetFCBForFile(DeviceExt, + &ParentFcb, + &Fcb, + FileName); + if (ParentFcb != NULL) + { + CdfsReleaseFCB(DeviceExt, + ParentFcb); + } + + if (!NT_SUCCESS (Status)) + { + DPRINT("Could not make a new FCB, status: %x\n", Status); + + if (AbsFileName) + ExFreePool(AbsFileName); + + return(Status); + } + } + + DPRINT("Attaching FCB to fileObject\n"); + Status = CdfsAttachFCBToFileObject(DeviceExt, + Fcb, + FileObject); + + if (AbsFileName) + ExFreePool (AbsFileName); + + return Status; +} + + + + +static NTSTATUS +CdfsCreateFile(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Opens a file + */ +{ + PDEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + ULONG RequestedDisposition; + ULONG RequestedOptions; + PFCB Fcb; + PCCB Ccb; +// PWSTR FileName; + NTSTATUS Status; + + DPRINT("CdfsCreateFile() called\n"); + + DeviceExt = DeviceObject->DeviceExtension; + assert (DeviceExt); + Stack = IoGetCurrentIrpStackLocation (Irp); + assert (Stack); + + RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff); + RequestedOptions = Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; + DPRINT("RequestedDisposition %x, RequestedOptions %x\n", + RequestedDisposition, RequestedOptions); + + FileObject = Stack->FileObject; + + if (RequestedDisposition == FILE_CREATE || + RequestedDisposition == FILE_OVERWRITE_IF || + RequestedDisposition == FILE_SUPERSEDE) + { + return(STATUS_ACCESS_DENIED); + } + + Status = CdfsOpenFile(DeviceExt, + FileObject, + FileObject->FileName.Buffer); + + if (NT_SUCCESS(Status)) + { + Ccb = FileObject->FsContext2; + Fcb = Ccb->Fcb; + /* + * Check the file has the requested attributes + */ + if (RequestedOptions & FILE_NON_DIRECTORY_FILE && CdfsFCBIsDirectory(Fcb)) + { + CdfsCloseFile (DeviceExt, FileObject); + return STATUS_FILE_IS_A_DIRECTORY; + } + if (RequestedOptions & FILE_DIRECTORY_FILE && !CdfsFCBIsDirectory(Fcb)) + { + CdfsCloseFile (DeviceExt, FileObject); + return STATUS_NOT_A_DIRECTORY; + } + } + + /* + * If the directory containing the file to open doesn't exist then + * fail immediately + */ + Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0; + Irp->IoStatus.Status = Status; + + return(Status); +} + + +NTSTATUS STDCALL +CdfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status; + + if (DeviceObject == CdfsGlobalData->DeviceObject) + { + /* DeviceObject represents FileSystem instead of logical volume */ + DPRINT("Opening file system\n"); + Irp->IoStatus.Information = FILE_OPENED; + Status = STATUS_SUCCESS; + goto ByeBye; + } + + DeviceExt = DeviceObject->DeviceExtension; + + ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, + TRUE); + Status = CdfsCreateFile(DeviceObject, + Irp); + ExReleaseResourceLite(&DeviceExt->DirResource); + +ByeBye: + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, + NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/cdfs/dirctl.c b/drivers/fs/cdfs/dirctl.c new file mode 100644 index 0000000..ce58ca2 --- /dev/null +++ b/drivers/fs/cdfs/dirctl.c @@ -0,0 +1,760 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/dirctl.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * Eric Kohl + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + +/* DEFINES ******************************************************************/ + +#define ROUND_DOWN(N, S) (((N) / (S)) * (S)) + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt, + PVOID *Context, + PVOID *Block, + PLARGE_INTEGER StreamOffset, + ULONG DirLength, + PVOID *Ptr, + PWSTR Name, + PULONG pIndex, + PULONG CurrentOffset) +/* + * FUNCTION: Retrieves the file name, be it in short or long file name format + */ +{ + PDIR_RECORD Record = *Ptr; + ULONG Index; + + if (*CurrentOffset >= DirLength) + return(STATUS_NO_MORE_ENTRIES); + + if (*CurrentOffset == 0) + { + Index = 0; + Record = (PDIR_RECORD)*Block; + while (Index < *pIndex) + { + (*Ptr) += Record->RecordLength; + (*CurrentOffset) += Record->RecordLength; + Record = *Ptr; + if (*Ptr - *Block >= BLOCKSIZE || Record->RecordLength == 0) + { + DPRINT("Map next sector\n"); + CcUnpinData(*Context); + StreamOffset->QuadPart += BLOCKSIZE; + *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE); + if (!CcMapData(DeviceExt->StreamFileObject, + StreamOffset, + BLOCKSIZE, TRUE, + Context, Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + *Ptr = *Block; + Record = (PDIR_RECORD)*Ptr; + } + if (*CurrentOffset >= DirLength) + return(STATUS_NO_MORE_ENTRIES); + + Index++; + } + } + + if (*Ptr - *Block >= BLOCKSIZE || Record->RecordLength == 0) + { + DPRINT("Map next sector\n"); + CcUnpinData(*Context); + StreamOffset->QuadPart += BLOCKSIZE; + *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE); + if (!CcMapData(DeviceExt->StreamFileObject, + StreamOffset, + BLOCKSIZE, TRUE, + Context, Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + *Ptr = *Block; + Record = (PDIR_RECORD)*Ptr; + } + if (*CurrentOffset >= DirLength) + return(STATUS_NO_MORE_ENTRIES); + + DPRINT("Index %lu RecordLength %lu Offset %lu\n", + *pIndex, Record->RecordLength, *CurrentOffset); + + if (Record->FileIdLength == 1 && Record->FileId[0] == 0) + { + wcscpy(Name, L"."); + } + else if (Record->FileIdLength == 1 && Record->FileId[0] == 1) + { + wcscpy(Name, L".."); + } + else + { + if (DeviceExt->CdInfo.JolietLevel == 0) + { + ULONG i; + + for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++) + Name[i] = (WCHAR)Record->FileId[i]; + Name[i] = 0; + } + else + { + CdfsSwapString(Name, Record->FileId, Record->FileIdLength); + } + } + + DPRINT("Name '%S'\n", Name); + + *Ptr = Record; + + return(STATUS_SUCCESS); +} + +static NTSTATUS +CdfsFindFile(PDEVICE_EXTENSION DeviceExt, + PFCB Fcb, + PFCB Parent, + PWSTR FileToFind, + PULONG pDirIndex, + PULONG pOffset) +/* + * FUNCTION: Find a file + */ +{ + WCHAR name[256]; + WCHAR TempStr[2]; + WCHAR ShortNameBuffer[13]; + UNICODE_STRING ShortName; + UNICODE_STRING LongName; + PVOID Block; + NTSTATUS Status; + ULONG len; + ULONG DirIndex; + ULONG Offset = 0; + ULONG Read; + BOOLEAN IsRoot; + PVOID Context = NULL; + ULONG DirSize; + PDIR_RECORD Record; + LARGE_INTEGER StreamOffset; + BOOLEAN HasSpaces; + GENERATE_NAME_CONTEXT NameContext; + + DPRINT("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", + Parent, FileToFind, pDirIndex ? *pDirIndex : 0); + DPRINT("FindFile: old Pathname %x, old Objectname %x)\n", + Fcb->PathName, Fcb->ObjectName); + + IsRoot = FALSE; + DirIndex = 0; + if (wcslen (FileToFind) == 0) + { + CHECKPOINT; + TempStr[0] = (WCHAR) '.'; + TempStr[1] = 0; + FileToFind = (PWSTR)&TempStr; + } + + if (Parent) + { + if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart) + { + IsRoot = TRUE; + } + } + else + { + IsRoot = TRUE; + } + + if (IsRoot == TRUE) + { + StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE; + DirSize = DeviceExt->CdInfo.RootSize; + + + if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0) + || (FileToFind[0] == '.' && FileToFind[1] == 0)) + { + /* it's root : complete essentials fields then return ok */ + RtlZeroMemory(Fcb, sizeof(FCB)); + + Fcb->PathName[0]='\\'; + Fcb->ObjectName = &Fcb->PathName[1]; + Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart; + Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize; + Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY; + + if (pDirIndex) + *pDirIndex = 0; + if (pOffset) + *pOffset = 0; + DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName); + return (STATUS_SUCCESS); + } + } + else + { + StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE; + DirSize = Parent->Entry.DataLengthL; + } + + DPRINT("StreamOffset %I64u DirSize %lu\n", StreamOffset.QuadPart, DirSize); + + if (pDirIndex && (*pDirIndex)) + DirIndex = *pDirIndex; + + if (pOffset && (*pOffset)) + { + Offset = *pOffset; + StreamOffset.QuadPart += ROUND_DOWN(Offset, BLOCKSIZE); + } + + if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset, + BLOCKSIZE, TRUE, &Context, &Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + + Record = (PDIR_RECORD) (Block + Offset % BLOCKSIZE); + if (Offset) + { + Offset += Record->RecordLength; + Record = (PVOID)Record + Record->RecordLength; + } + while(TRUE) + { + DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n", + Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength); + + Status = CdfsGetEntryName(DeviceExt, &Context, &Block, &StreamOffset, + DirSize, (PVOID*)&Record, name, &DirIndex, &Offset); + + if (Status == STATUS_NO_MORE_ENTRIES) + { + break; + } + else if (Status == STATUS_UNSUCCESSFUL) + { + /* Note: the directory cache has already been unpinned */ + return(Status); + } + + DPRINT("Name '%S'\n", name); + + RtlInitUnicodeString(&LongName, name); + ShortName.Length = 0; + ShortName.MaximumLength = 26; + ShortName.Buffer = ShortNameBuffer; + + if ((RtlIsNameLegalDOS8Dot3(&LongName, NULL, &HasSpaces) == FALSE) || + (HasSpaces == TRUE)) + { + /* Build short name */ + RtlGenerate8dot3Name(&LongName, + FALSE, + &NameContext, + &ShortName); + } + else + { + /* copy short name */ + RtlUpcaseUnicodeString(&ShortName, + &LongName, + FALSE); + } + + DPRINT("ShortName '%wZ'\n", &ShortName); + + if (wstrcmpjoki(name, FileToFind) || + wstrcmpjoki(ShortNameBuffer, FileToFind)) + { + if (Parent && Parent->PathName) + { + len = wcslen(Parent->PathName); + memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR)); + Fcb->ObjectName=&Fcb->PathName[len]; + if (len != 1 || Fcb->PathName[0] != '\\') + { + Fcb->ObjectName[0] = '\\'; + Fcb->ObjectName = &Fcb->ObjectName[1]; + } + } + else + { + Fcb->ObjectName=Fcb->PathName; + Fcb->ObjectName[0]='\\'; + Fcb->ObjectName=&Fcb->ObjectName[1]; + } + + DPRINT("PathName '%S' ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName); + + memcpy(&Fcb->Entry, Record, sizeof(DIR_RECORD)); + wcsncpy(Fcb->ObjectName, name, MAX_PATH); + + /* Copy short name */ + Fcb->ShortNameLength = ShortName.Length; + memcpy(Fcb->ShortName, ShortName.Buffer, ShortName.Length); + + if (pDirIndex) + *pDirIndex = DirIndex; + if (pOffset) + *pOffset = Offset; + + DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n", + Fcb->PathName, Fcb->ObjectName, DirIndex); + + CcUnpinData(Context); + + return(STATUS_SUCCESS); + } + + + Offset += Record->RecordLength; + Record = (PVOID)Record + Record->RecordLength; + DirIndex++; + + } + + CcUnpinData(Context); + + if (pDirIndex) + *pDirIndex = DirIndex; + + if (pOffset) + *pOffset = Offset; + + return(STATUS_UNSUCCESSFUL); +} + + +static NTSTATUS +CdfsGetNameInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_NAMES_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetNameInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetDirectoryInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + /* Convert file flags */ + CdfsFileFlagsToAttributes(Fcb, + &Info->FileAttributes); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + +// Info->FileIndex=; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetFullDirectoryInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_FULL_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetFullDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + /* Convert file flags */ + CdfsFileFlagsToAttributes(Fcb, + &Info->FileAttributes); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + +// Info->FileIndex=; + Info->EaSize = 0; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetBothDirectoryInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_BOTH_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetBothDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + /* Convert file flags */ + CdfsFileFlagsToAttributes(Fcb, + &Info->FileAttributes); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + +// Info->FileIndex=; + Info->EaSize = 0; + + /* Copy short name */ + Info->ShortNameLength = Fcb->ShortNameLength; + memcpy(Info->ShortName, Fcb->ShortName, Fcb->ShortNameLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + LONG BufferLength = 0; + PUNICODE_STRING SearchPattern = NULL; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG FileIndex = 0; + PUCHAR Buffer = NULL; + PFILE_NAMES_INFORMATION Buffer0 = NULL; + PFCB Fcb; + PCCB Ccb; + FCB TempFcb; + BOOLEAN First = FALSE; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("CdfsQueryDirectory() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + + Ccb = (PCCB)FileObject->FsContext2; + Fcb = Ccb->Fcb; + + /* Obtain the callers parameters */ + BufferLength = Stack->Parameters.QueryDirectory.Length; + SearchPattern = Stack->Parameters.QueryDirectory.FileName; + FileInformationClass = + Stack->Parameters.QueryDirectory.FileInformationClass; + FileIndex = Stack->Parameters.QueryDirectory.FileIndex; + + + if (SearchPattern != NULL) + { + if (!Ccb->DirectorySearchPattern) + { + First = TRUE; + Ccb->DirectorySearchPattern = + ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR)); + if (!Ccb->DirectorySearchPattern) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + memcpy(Ccb->DirectorySearchPattern, + SearchPattern->Buffer, + SearchPattern->Length); + Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0; + } + } + else if (!Ccb->DirectorySearchPattern) + { + First = TRUE; + Ccb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); + if (!Ccb->DirectorySearchPattern) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + Ccb->DirectorySearchPattern[0] = L'*'; + Ccb->DirectorySearchPattern[1] = 0; + } + DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern); + + /* Determine directory index */ + if (Stack->Flags & SL_INDEX_SPECIFIED) + { + Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart; + Ccb->Offset = 0; + } + else if (First || (Stack->Flags & SL_RESTART_SCAN)) + { + Ccb->Entry = 0; + Ccb->Offset = 0; + } + + /* Determine Buffer for result */ + if (Irp->MdlAddress) + { + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + } + else + { + Buffer = Irp->UserBuffer; + } + DPRINT("Buffer=%x tofind=%S\n", Buffer, Ccb->DirectorySearchPattern); + + TempFcb.ObjectName = TempFcb.PathName; + while (Status == STATUS_SUCCESS && BufferLength > 0) + { + Status = CdfsFindFile(DeviceExtension, + &TempFcb, + Fcb, + Ccb->DirectorySearchPattern, + &Ccb->Entry, + &Ccb->Offset); + DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry); + + if (NT_SUCCESS(Status)) + { + switch (FileInformationClass) + { + case FileNameInformation: + Status = CdfsGetNameInformation(&TempFcb, + DeviceExtension, + (PFILE_NAMES_INFORMATION)Buffer, + BufferLength); + break; + + case FileDirectoryInformation: + Status = CdfsGetDirectoryInformation(&TempFcb, + DeviceExtension, + (PFILE_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + case FileFullDirectoryInformation: + Status = CdfsGetFullDirectoryInformation(&TempFcb, + DeviceExtension, + (PFILE_FULL_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + case FileBothDirectoryInformation: + Status = CdfsGetBothDirectoryInformation(&TempFcb, + DeviceExtension, + (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + + if (Status == STATUS_BUFFER_OVERFLOW) + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + break; + } + } + else + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + + if (First) + { + Status = STATUS_NO_SUCH_FILE; + } + else + { + Status = STATUS_NO_MORE_FILES; + } + break; + } + + Buffer0 = (PFILE_NAMES_INFORMATION)Buffer; + Buffer0->FileIndex = FileIndex++; + Ccb->Entry++; + + if (Stack->Flags & SL_RETURN_SINGLE_ENTRY) + { + break; + } + BufferLength -= Buffer0->NextEntryOffset; + Buffer += Buffer0->NextEntryOffset; + } + + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + + if (FileIndex > 0) + { + Status = STATUS_SUCCESS; + } + + return(Status); +} + + + +NTSTATUS STDCALL +CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("CdfsDirectoryControl() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_QUERY_DIRECTORY: + Status = CdfsQueryDirectory(DeviceObject, + Irp); + break; + + case IRP_MN_NOTIFY_CHANGE_DIRECTORY: + DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/cdfs/fcb.c b/drivers/fs/cdfs/fcb.c new file mode 100644 index 0000000..fa54c38 --- /dev/null +++ b/drivers/fs/cdfs/fcb.c @@ -0,0 +1,707 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/fcb.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* MACROS *******************************************************************/ + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) +#define TAG_FCB TAG('I', 'F', 'C', 'B') + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + + +/* FUNCTIONS ****************************************************************/ + +static PWCHAR +CdfsGetNextPathElement(PWCHAR FileName) +{ + if (*FileName == L'\0') + { + return(NULL); + } + + while (*FileName != L'\0' && *FileName != L'\\') + { + FileName++; + } + + return(FileName); +} + + +static VOID +CdfsWSubString(PWCHAR pTarget, const PWCHAR pSource, size_t pLength) +{ + wcsncpy (pTarget, pSource, pLength); + pTarget [pLength] = L'\0'; +} + + +PFCB +CdfsCreateFCB(PWSTR FileName) +{ + PFCB Fcb; + + Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); + RtlZeroMemory(Fcb, sizeof(FCB)); + + if (FileName) + { + wcscpy(Fcb->PathName, FileName); + if (wcsrchr(Fcb->PathName, '\\') != 0) + { + Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\'); + } + else + { + Fcb->ObjectName = Fcb->PathName; + } + } + + ExInitializeResourceLite(&Fcb->MainResource); + + return(Fcb); +} + + +VOID +CdfsDestroyFCB(PFCB Fcb) +{ + ExDeleteResourceLite(&Fcb->MainResource); + + ExFreePool(Fcb); +} + + +BOOLEAN +CdfsFCBIsDirectory(PFCB Fcb) +{ +// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY); + return(Fcb->Entry.FileFlags & 0x02); +} + + +BOOLEAN +CdfsFCBIsRoot(PFCB Fcb) +{ + return(wcscmp(Fcb->PathName, L"\\") == 0); +} + + +VOID +CdfsGrabFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + DPRINT("grabbing FCB at %x: %S, refCount:%d\n", + Fcb, + Fcb->PathName, + Fcb->RefCount); + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +VOID +CdfsReleaseFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + DPRINT("releasing FCB at %x: %S, refCount:%d\n", + Fcb, + Fcb->PathName, + Fcb->RefCount); + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->RefCount--; + if (Fcb->RefCount <= 0 && !CdfsFCBIsDirectory(Fcb)) + { + RemoveEntryList(&Fcb->FcbListEntry); + CdfsDestroyFCB(Fcb); + } + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +VOID +CdfsAddFCBToTable(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->DevExt = Vcb; + InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry); + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +PFCB +CdfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb, + PWSTR FileName) +{ + KIRQL oldIrql; + PFCB Fcb; + PLIST_ENTRY current_entry; + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + + if (FileName == NULL || *FileName == 0) + { + DPRINT("Return FCB for stream file object\n"); + Fcb = ((PCCB)Vcb->StreamFileObject->FsContext2)->Fcb; + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + return(Fcb); + } + + current_entry = Vcb->FcbListHead.Flink; + while (current_entry != &Vcb->FcbListHead) + { + Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry); + + DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName); + if (_wcsicmp(FileName, Fcb->PathName) == 0) + { + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + return(Fcb); + } + + //FIXME: need to compare against short name in FCB here + + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + + return(NULL); +} + + +NTSTATUS +CdfsFCBInitializeCache(PVCB Vcb, + PFCB Fcb) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + PCCB newCCB; + + FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice); + + newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); + if (newCCB == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + RtlZeroMemory(newCCB, + sizeof(CCB)); + + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = (PVOID) &Fcb->RFCB; + FileObject->FsContext2 = newCCB; + newCCB->Fcb = Fcb; + newCCB->PtrFileObject = FileObject; + Fcb->FileObject = FileObject; + Fcb->DevExt = Vcb; + + Status = CcRosInitializeFileCache(FileObject, + &Fcb->RFCB.Bcb, + PAGE_SIZE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + KeBugCheck(0); + } + + ObDereferenceObject(FileObject); + Fcb->Flags |= FCB_CACHE_INITIALIZED; + + return(Status); +} + + +PFCB +CdfsMakeRootFCB(PDEVICE_EXTENSION Vcb) +{ + PFCB Fcb; + + Fcb = CdfsCreateFCB(L"\\"); + + Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize; + Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart; + Fcb->Entry.FileFlags = 0x02; // FILE_ATTRIBUTE_DIRECTORY; + Fcb->RefCount = 1; + Fcb->DirIndex = 0; + Fcb->RFCB.FileSize.QuadPart = Vcb->CdInfo.RootSize; + Fcb->RFCB.ValidDataLength.QuadPart = Vcb->CdInfo.RootSize; + Fcb->RFCB.AllocationSize.QuadPart = Vcb->CdInfo.RootSize; + + CdfsFCBInitializeCache(Vcb, Fcb); + CdfsAddFCBToTable(Vcb, Fcb); + CdfsGrabFCB(Vcb, Fcb); + + return(Fcb); +} + + +PFCB +CdfsOpenRootFCB(PDEVICE_EXTENSION Vcb) +{ + PFCB Fcb; + + Fcb = CdfsGrabFCBFromTable(Vcb, L"\\"); + if (Fcb == NULL) + { + Fcb = CdfsMakeRootFCB(Vcb); + } + + return(Fcb); +} + + +static VOID +CdfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt, + PDIR_RECORD Record, + PWSTR Name) +/* + * FUNCTION: Retrieves the file name from a directory record. + */ +{ + if (Record->FileIdLength == 1 && Record->FileId[0] == 0) + { + wcscpy(Name, L"."); + } + else if (Record->FileIdLength == 1 && Record->FileId[0] == 1) + { + wcscpy(Name, L".."); + } + else + { + if (DeviceExt->CdInfo.JolietLevel == 0) + { + ULONG i; + + for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++) + Name[i] = (WCHAR)Record->FileId[i]; + Name[i] = 0; + } + else + { + CdfsSwapString(Name, + Record->FileId, + Record->FileIdLength); + } + } + + DPRINT("Name '%S'\n", Name); +} + + +NTSTATUS +CdfsMakeFCBFromDirEntry(PVCB Vcb, + PFCB DirectoryFCB, + PWSTR LongName, + PWSTR ShortName, + PDIR_RECORD Record, + PFCB * fileFCB) +{ + WCHAR pathName[MAX_PATH]; + PFCB rcFCB; + ULONG Size; + + if (LongName [0] != 0 && wcslen (DirectoryFCB->PathName) + + sizeof(WCHAR) + wcslen (LongName) > MAX_PATH) + { + return(STATUS_OBJECT_NAME_INVALID); + } + + wcscpy(pathName, DirectoryFCB->PathName); + if (!CdfsFCBIsRoot(DirectoryFCB)) + { + wcscat(pathName, L"\\"); + } + + if (LongName[0] != 0) + { + wcscat(pathName, LongName); + } + else + { + WCHAR entryName[MAX_PATH]; + + CdfsGetDirEntryName(Vcb, Record, entryName); + wcscat(pathName, entryName); + } + + rcFCB = CdfsCreateFCB(pathName); + memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD)); + + /* Copy short name into FCB */ + rcFCB->ShortNameLength = wcslen(ShortName) * sizeof(WCHAR); + wcscpy(rcFCB->ShortName, ShortName); + + Size = rcFCB->Entry.DataLengthL; + + rcFCB->RFCB.FileSize.QuadPart = Size; + rcFCB->RFCB.ValidDataLength.QuadPart = Size; + rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE); + if (CdfsFCBIsDirectory(rcFCB)) + { + CdfsFCBInitializeCache(Vcb, rcFCB); + } + rcFCB->RefCount++; + CdfsAddFCBToTable(Vcb, rcFCB); + *fileFCB = rcFCB; + + DPRINT("%S %d %I64d\n", LongName, Size, rcFCB->RFCB.AllocationSize.QuadPart); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +CdfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, + PFCB Fcb, + PFILE_OBJECT FileObject) +{ + NTSTATUS Status; + PCCB newCCB; + + newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); + if (newCCB == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + memset(newCCB, 0, sizeof(CCB)); + + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = (PVOID)&Fcb->RFCB; + FileObject->FsContext2 = newCCB; + newCCB->Fcb = Fcb; + newCCB->PtrFileObject = FileObject; + Fcb->DevExt = Vcb; + + if (CdfsFCBIsDirectory(Fcb)) + { + Status = CcRosInitializeFileCache(FileObject, + &Fcb->RFCB.Bcb, + PAGE_SIZE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + KeBugCheck(0); + } + Fcb->Flags |= FCB_CACHE_INITIALIZED; + } + + DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +CdfsDirFindFile(PDEVICE_EXTENSION DeviceExt, + PFCB DirectoryFcb, + PWSTR FileToFind, + PFCB *FoundFCB) +{ + WCHAR TempName[2]; + WCHAR Name[256]; + PVOID Block; + ULONG FirstSector; + ULONG DirSize; + PDIR_RECORD Record; + ULONG Offset; + ULONG BlockOffset; + NTSTATUS Status; + + LARGE_INTEGER StreamOffset; + PVOID Context; + + WCHAR ShortNameBuffer[13]; + UNICODE_STRING ShortName; + UNICODE_STRING LongName; + BOOLEAN HasSpaces; + GENERATE_NAME_CONTEXT NameContext; + + + assert(DeviceExt); + assert(DirectoryFcb); + assert(FileToFind); + + DPRINT("CdfsDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n", + DeviceExt, + DirectoryFcb, + FileToFind); + DPRINT("Dir Path:%S\n", DirectoryFcb->PathName); + + /* default to '.' if no filename specified */ + if (wcslen(FileToFind) == 0) + { + TempName[0] = L'.'; + TempName[1] = 0; + FileToFind = TempName; + } + + DirSize = DirectoryFcb->Entry.DataLengthL; + StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE; + + if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset, + BLOCKSIZE, TRUE, &Context, &Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + + Offset = 0; + BlockOffset = 0; + Record = (PDIR_RECORD)Block; + while(TRUE) + { + if (Record->RecordLength == 0) + { + DPRINT("RecordLength == 0 Stopped!\n"); + break; + } + + DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n", + Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength); + + CdfsGetDirEntryName(DeviceExt, Record, Name); + DPRINT("Name '%S'\n", Name); + + RtlInitUnicodeString(&LongName, Name); + ShortName.Length = 0; + ShortName.MaximumLength = 26; + ShortName.Buffer = ShortNameBuffer; + memset(ShortNameBuffer, 0, 26); + + if ((RtlIsNameLegalDOS8Dot3(&LongName, NULL, &HasSpaces) == FALSE) || + (HasSpaces == TRUE)) + { + /* Build short name */ + RtlGenerate8dot3Name(&LongName, + FALSE, + &NameContext, + &ShortName); + } + else + { + /* copy short name */ + RtlUpcaseUnicodeString(&ShortName, + &LongName, + FALSE); + } + + DPRINT("ShortName '%wZ'\n", &ShortName); + + if (wstrcmpjoki(Name, FileToFind) || wstrcmpjoki(ShortNameBuffer, FileToFind)) + { + DPRINT("Match found, %S\n", Name); + Status = CdfsMakeFCBFromDirEntry(DeviceExt, + DirectoryFcb, + Name, + ShortNameBuffer, + Record, + FoundFCB); + + CcUnpinData(Context); + + return(Status); + } + + Offset += Record->RecordLength; + BlockOffset += Record->RecordLength; + Record = (PDIR_RECORD)(Block + BlockOffset); + if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0) + { + DPRINT("Map next sector\n"); + CcUnpinData(Context); + StreamOffset.QuadPart += BLOCKSIZE; + Offset = ROUND_UP(Offset, BLOCKSIZE); + BlockOffset = 0; + + if (!CcMapData(DeviceExt->StreamFileObject, + &StreamOffset, + BLOCKSIZE, TRUE, + &Context, &Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + Record = (PDIR_RECORD)(Block + BlockOffset); + } + + if (Offset >= DirSize) + break; + } + + CcUnpinData(Context); + + return(STATUS_OBJECT_NAME_NOT_FOUND); +} + + +NTSTATUS +CdfsGetFCBForFile(PDEVICE_EXTENSION Vcb, + PFCB *pParentFCB, + PFCB *pFCB, + const PWSTR pFileName) +{ + NTSTATUS Status; + WCHAR pathName [MAX_PATH]; + WCHAR elementName [MAX_PATH]; + PWCHAR currentElement; + PFCB FCB; + PFCB parentFCB; + + DPRINT("CdfsGetFCBForFile(%x, %x, %x, '%S')\n", + Vcb, + pParentFCB, + pFCB, + pFileName); + + /* Trivial case, open of the root directory on volume */ + if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0) + { + DPRINT("returning root FCB\n"); + + FCB = CdfsOpenRootFCB(Vcb); + *pFCB = FCB; + *pParentFCB = NULL; + + return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND); + } + else + { + currentElement = pFileName + 1; + wcscpy (pathName, L"\\"); + FCB = CdfsOpenRootFCB (Vcb); + } + parentFCB = NULL; + + /* Parse filename and check each path element for existance and access */ + while (CdfsGetNextPathElement(currentElement) != 0) + { + /* Skip blank directory levels */ + if ((CdfsGetNextPathElement(currentElement) - currentElement) == 0) + { + currentElement++; + continue; + } + + DPRINT("Parsing, currentElement:%S\n", currentElement); + DPRINT(" parentFCB:%x FCB:%x\n", parentFCB, FCB); + + /* Descend to next directory level */ + if (parentFCB) + { + CdfsReleaseFCB(Vcb, parentFCB); + parentFCB = NULL; + } + + /* fail if element in FCB is not a directory */ + if (!CdfsFCBIsDirectory(FCB)) + { + DPRINT("Element in requested path is not a directory\n"); + + CdfsReleaseFCB(Vcb, FCB); + FCB = 0; + *pParentFCB = NULL; + *pFCB = NULL; + + return(STATUS_OBJECT_PATH_NOT_FOUND); + } + parentFCB = FCB; + + /* Extract next directory level into dirName */ + CdfsWSubString(pathName, + pFileName, + CdfsGetNextPathElement(currentElement) - pFileName); + DPRINT(" pathName:%S\n", pathName); + + FCB = CdfsGrabFCBFromTable(Vcb, pathName); + if (FCB == NULL) + { + CdfsWSubString(elementName, + currentElement, + CdfsGetNextPathElement(currentElement) - currentElement); + DPRINT(" elementName:%S\n", elementName); + + Status = CdfsDirFindFile(Vcb, parentFCB, elementName, &FCB); + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + *pParentFCB = parentFCB; + *pFCB = NULL; + currentElement = CdfsGetNextPathElement(currentElement); + if (*currentElement == L'\0' || CdfsGetNextPathElement(currentElement + 1) == 0) + { + return(STATUS_OBJECT_NAME_NOT_FOUND); + } + else + { + return(STATUS_OBJECT_PATH_NOT_FOUND); + } + } + else if (!NT_SUCCESS(Status)) + { + CdfsReleaseFCB(Vcb, parentFCB); + *pParentFCB = NULL; + *pFCB = NULL; + + return(Status); + } + } + currentElement = CdfsGetNextPathElement(currentElement); + } + + *pParentFCB = parentFCB; + *pFCB = FCB; + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/cdfs/finfo.c b/drivers/fs/cdfs/finfo.c new file mode 100644 index 0000000..f3d6638 --- /dev/null +++ b/drivers/fs/cdfs/finfo.c @@ -0,0 +1,437 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/finfo.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * Eric Kohl + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsGetStandardInformation(PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_STANDARD_INFORMATION StandardInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the standard file information + */ +{ + DPRINT("CdfsGetStandardInformation() called\n"); + + if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + + /* PRECONDITION */ + assert(StandardInfo != NULL); + assert(Fcb != NULL); + + RtlZeroMemory(StandardInfo, + sizeof(FILE_STANDARD_INFORMATION)); + + StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize; + StandardInfo->EndOfFile = Fcb->RFCB.FileSize; + StandardInfo->NumberOfLinks = 0; + StandardInfo->DeletePending = FALSE; + StandardInfo->Directory = Fcb->Entry.FileFlags & 0x02 ? TRUE : FALSE; + + *BufferLength -= sizeof(FILE_STANDARD_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetPositionInformation(PFILE_OBJECT FileObject, + PFILE_POSITION_INFORMATION PositionInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetPositionInformation() called\n"); + + if (*BufferLength < sizeof(FILE_POSITION_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + + PositionInfo->CurrentByteOffset.QuadPart = + FileObject->CurrentByteOffset.QuadPart; + + DPRINT("Getting position %I64x\n", + PositionInfo->CurrentByteOffset.QuadPart); + + *BufferLength -= sizeof(FILE_POSITION_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetBasicInformation(PFILE_OBJECT FileObject, + PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_BASIC_INFORMATION BasicInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetBasicInformation() called\n"); + + if (*BufferLength < sizeof(FILE_BASIC_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->ChangeTime); + + CdfsFileFlagsToAttributes(Fcb, + &BasicInfo->FileAttributes); + + *BufferLength -= sizeof(FILE_BASIC_INFORMATION); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetNameInformation(PFILE_OBJECT FileObject, + PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_NAME_INFORMATION NameInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the file name information + */ +{ + ULONG NameLength; + + DPRINT("CdfsGetNameInformation() called\n"); + + assert(NameInfo != NULL); + assert(Fcb != NULL); + + NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR); + if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength) + return STATUS_BUFFER_OVERFLOW; + + NameInfo->FileNameLength = NameLength; + RtlCopyMemory(NameInfo->FileName, + Fcb->PathName, + NameLength + sizeof(WCHAR)); + + *BufferLength -= + (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR)); + + return STATUS_SUCCESS; +} + + +static NTSTATUS +CdfsGetInternalInformation(PFCB Fcb, + PFILE_INTERNAL_INFORMATION InternalInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetInternalInformation() called\n"); + + assert(InternalInfo); + assert(Fcb); + + if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + /* FIXME: get a real index, that can be used in a create operation */ + InternalInfo->IndexNumber.QuadPart = 0; + + *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetNetworkOpenInformation(PFCB Fcb, + PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the file network open information + */ +{ + assert(NetworkInfo); + assert(Fcb); + + if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + CdfsDateTimeToFileTime(Fcb, + &NetworkInfo->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &NetworkInfo->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &NetworkInfo->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &NetworkInfo->ChangeTime); + NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize; + NetworkInfo->EndOfFile = Fcb->RFCB.FileSize; + CdfsFileFlagsToAttributes(Fcb, + &NetworkInfo->FileAttributes); + + *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetAllInformation(PFILE_OBJECT FileObject, + PFCB Fcb, + PFILE_ALL_INFORMATION Info, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the all file information + */ +{ + ULONG NameLength; + + assert(Info); + assert(Fcb); + + NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR); + if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength) + return(STATUS_BUFFER_OVERFLOW); + + /* Basic Information */ + CdfsDateTimeToFileTime(Fcb, + &Info->BasicInformation.CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->BasicInformation.LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->BasicInformation.LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->BasicInformation.ChangeTime); + CdfsFileFlagsToAttributes(Fcb, + &Info->BasicInformation.FileAttributes); + + /* Standard Information */ + Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize; + Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize; + Info->StandardInformation.NumberOfLinks = 0; + Info->StandardInformation.DeletePending = FALSE; + Info->StandardInformation.Directory = Fcb->Entry.FileFlags & 0x02 ? TRUE : FALSE; + + /* Internal Information */ + /* FIXME: get a real index, that can be used in a create operation */ + Info->InternalInformation.IndexNumber.QuadPart = 0; + + /* EA Information */ + Info->EaInformation.EaSize = 0; + + /* Access Information */ + /* The IO-Manager adds this information */ + + /* Position Information */ + Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart; + + /* Mode Information */ + /* The IO-Manager adds this information */ + + /* Alignment Information */ + /* The IO-Manager adds this information */ + + /* Name Information */ + Info->NameInformation.FileNameLength = NameLength; + RtlCopyMemory(Info->NameInformation.FileName, + Fcb->PathName, + NameLength + sizeof(WCHAR)); + + *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR)); + + return STATUS_SUCCESS; +} + +static NTSTATUS +CdfsSetPositionInformation(PFILE_OBJECT FileObject, + PFILE_POSITION_INFORMATION PositionInfo) +{ + DPRINT ("CdfsSetPositionInformation()\n"); + + DPRINT ("PositionInfo %x\n", PositionInfo); + DPRINT ("Setting position %d\n", PositionInfo->CurrentByteOffset.u.LowPart); + memcpy (&FileObject->CurrentByteOffset, &PositionInfo->CurrentByteOffset, + sizeof (LARGE_INTEGER)); + + return (STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CdfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Retrieve the specified file information + */ +{ + FILE_INFORMATION_CLASS FileInformationClass; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PFCB Fcb; + PVOID SystemBuffer; + ULONG BufferLength; + + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("CdfsQueryInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; + FileObject = Stack->FileObject; + Fcb = FileObject->FsContext; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = Stack->Parameters.QueryFile.Length; + + switch (FileInformationClass) + { + case FileStandardInformation: + Status = CdfsGetStandardInformation(Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FilePositionInformation: + Status = CdfsGetPositionInformation(FileObject, + SystemBuffer, + &BufferLength); + break; + + case FileBasicInformation: + Status = CdfsGetBasicInformation(FileObject, + Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileNameInformation: + Status = CdfsGetNameInformation(FileObject, + Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileInternalInformation: + Status = CdfsGetInternalInformation(Fcb, + SystemBuffer, + &BufferLength); + break; + + case FileNetworkOpenInformation: + Status = CdfsGetNetworkOpenInformation(Fcb, + SystemBuffer, + &BufferLength); + break; + + case FileAllInformation: + Status = CdfsGetAllInformation(FileObject, + Fcb, + SystemBuffer, + &BufferLength); + break; + + case FileAlternateNameInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + DPRINT("Unimplemented information class %u\n", FileInformationClass); + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryFile.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +NTSTATUS STDCALL +CdfsSetInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Retrieve the specified file information + */ +{ + FILE_INFORMATION_CLASS FileInformationClass; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PFCB Fcb; + PVOID SystemBuffer; + + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT1("CdfsSetInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileInformationClass = Stack->Parameters.SetFile.FileInformationClass; + FileObject = Stack->FileObject; + Fcb = FileObject->FsContext; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + + switch (FileInformationClass) + { + case FilePositionInformation: + Status = CdfsSetPositionInformation(FileObject, + SystemBuffer); + break; + case FileBasicInformation: + case FileRenameInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/cdfs/fsctl.c b/drivers/fs/cdfs/fsctl.c new file mode 100644 index 0000000..2a777f9 --- /dev/null +++ b/drivers/fs/cdfs/fsctl.c @@ -0,0 +1,520 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/fsctl.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "cdfs.h" + +/* FUNCTIONS ****************************************************************/ + +static inline +int msf_to_lba (BYTE m, BYTE s, BYTE f) +{ + return (((m * 60) + s) * 75 + f) - 150; +} + +static VOID +CdfsGetPVDData(PUCHAR Buffer, + PCDINFO CdInfo) +{ + PPVD Pvd; + ULONG i; + PCHAR pc; + PWCHAR pw; + + union + { + ULONG Value; + UCHAR Part[4]; + } Serial; + + Pvd = (PPVD)Buffer; + + /* Calculate the volume serial number */ + Serial.Value = 0; + for (i = 0; i < 2048; i += 4) + { + /* DON'T optimize this to ULONG!!! (breaks overflow) */ + Serial.Part[0] += Buffer[i+3]; + Serial.Part[1] += Buffer[i+2]; + Serial.Part[2] += Buffer[i+1]; + Serial.Part[3] += Buffer[i+0]; + } + CdInfo->SerialNumber = Serial.Value; + + /* Extract the volume label */ + pc = Pvd->VolumeId; + pw = CdInfo->VolumeLabel; + for (i = 0; i < MAXIMUM_VOLUME_LABEL_LENGTH && *pc != ' '; i++) + { + *pw++ = (WCHAR)*pc++; + } + *pw = 0; + CdInfo->VolumeLabelLength = i; + + CdInfo->VolumeSpaceSize = Pvd->VolumeSpaceSizeL; + CdInfo->RootStart = Pvd->RootDirRecord.ExtentLocationL; + CdInfo->RootSize = Pvd->RootDirRecord.DataLengthL; + + DPRINT("VolumeSerial: %08lx\n", CdInfo->SerialNumber); + DPRINT("VolumeLabel: '%S'\n", CdInfo->VolumeLabel); + DPRINT("VolumeLabelLength: %lu\n", CdInfo->VolumeLabelLength); + DPRINT("VolumeSize: %lu\n", Pvd->VolumeSpaceSizeL); + DPRINT("RootStart: %lu\n", Pvd->RootDirRecord.ExtentLocationL); + DPRINT("RootSize: %lu\n", Pvd->RootDirRecord.DataLengthL); + +#if 0 + DbgPrint("******** PVD **********\n"); + DbgPrint("VdType: %d\n", Pvd->VdType); + DbgPrint("StandardId: '%.*s'\n", 5, Pvd->StandardId); + DbgPrint("VdVersion: %d\n", Pvd->VdVersion); + DbgPrint("SystemId: '%.*s'\n", 32, Pvd->SystemId); + DbgPrint("VolumeId: '%.*s'\n", 32, Pvd->VolumeId); + DbgPrint("VolumeSpaceSizeL: %d (%x)\n", Pvd->VolumeSpaceSizeL, Pvd->VolumeSpaceSizeL); + DbgPrint("VolumeSpaceSizeM: %d (%x)\n", Pvd->VolumeSpaceSizeM, Pvd->VolumeSpaceSizeM); + DbgPrint("VolumeSetSize: %d (%x)\n", Pvd->VolumeSequenceNumber, Pvd->VolumeSequenceNumber); + DbgPrint("VolumeSequenceNumber: %d (%x)\n", Pvd->VolumeSequenceNumber, Pvd->VolumeSequenceNumber); + DbgPrint("LogicalBlockSize: %d (%x)\n", Pvd->LogicalBlockSize, Pvd->LogicalBlockSize); + DbgPrint("PathTableSizeL: %d (%x)\n", Pvd->PathTableSizeL, Pvd->PathTableSizeL); + DbgPrint("PathTableSizeM: %d (%x)\n", Pvd->PathTableSizeM, Pvd->PathTableSizeM); + DbgPrint("LPathTablePos: %d (%x)\n", Pvd->LPathTablePos, Pvd->LPathTablePos); + DbgPrint("LOptPathTablePos: %d (%x)\n", Pvd->LOptPathTablePos, Pvd->LOptPathTablePos); + DbgPrint("MPathTablePos: %d (%x)\n", Pvd->MPathTablePos, Pvd->MPathTablePos); + DbgPrint("MOptPathTablePos: %d (%x)\n", Pvd->MOptPathTablePos, Pvd->MOptPathTablePos); + DbgPrint("VolumeSetIdentifier: '%.*s'\n", 128, Pvd->VolumeSetIdentifier); + DbgPrint("PublisherIdentifier: '%.*s'\n", 128, Pvd->PublisherIdentifier); + DbgPrint("******** Root *********\n"); + DbgPrint("RecordLength: %d\n", Pvd->RootDirRecord.RecordLength); + DbgPrint("ExtAttrRecordLength: %d\n", Pvd->RootDirRecord.ExtAttrRecordLength); + DbgPrint("ExtentLocationL: %d\n", Pvd->RootDirRecord.ExtentLocationL); + DbgPrint("DataLengthL: %d\n", Pvd->RootDirRecord.DataLengthL); + DbgPrint("Year: %d\n", Pvd->RootDirRecord.Year); + DbgPrint("Month: %d\n", Pvd->RootDirRecord.Month); + DbgPrint("Day: %d\n", Pvd->RootDirRecord.Day); + DbgPrint("Hour: %d\n", Pvd->RootDirRecord.Hour); + DbgPrint("Minute: %d\n", Pvd->RootDirRecord.Minute); + DbgPrint("Second: %d\n", Pvd->RootDirRecord.Second); + DbgPrint("TimeZone: %d\n", Pvd->RootDirRecord.TimeZone); + DbgPrint("FileFlags: %d\n", Pvd->RootDirRecord.FileFlags); + DbgPrint("FileUnitSize: %d\n", Pvd->RootDirRecord.FileUnitSize); + DbgPrint("InterleaveGapSize: %d\n", Pvd->RootDirRecord.InterleaveGapSize); + DbgPrint("VolumeSequenceNumber: %d\n", Pvd->RootDirRecord.VolumeSequenceNumber); + DbgPrint("FileIdLength: %d\n", Pvd->RootDirRecord.FileIdLength); + DbgPrint("FileId: '%.*s'\n", Pvd->RootDirRecord.FileId); + DbgPrint("***********************\n"); +#endif +} + + +static VOID +CdfsGetSVDData(PUCHAR Buffer, + PCDINFO CdInfo) +{ + PSVD Svd; + ULONG JolietLevel = 0; + + Svd = (PSVD)Buffer; + + DPRINT("EscapeSequences: '%.32s'\n", Svd->EscapeSequences); + + if (strncmp(Svd->EscapeSequences, "%/@", 3) == 0) + { + DPRINT("Joliet extension found (UCS-2 Level 1)\n"); + JolietLevel = 1; + } + else if (strncmp(Svd->EscapeSequences, "%/C", 3) == 0) + { + DPRINT("Joliet extension found (UCS-2 Level 2)\n"); + JolietLevel = 2; + } + else if (strncmp(Svd->EscapeSequences, "%/E", 3) == 0) + { + DPRINT("Joliet extension found (UCS-2 Level 3)\n"); + JolietLevel = 3; + } + + CdInfo->JolietLevel = JolietLevel; + + if (JolietLevel != 0) + { + CdInfo->RootStart = Svd->RootDirRecord.ExtentLocationL; + CdInfo->RootSize = Svd->RootDirRecord.DataLengthL; + + DPRINT("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL); + DPRINT("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL); + } +} + + +static NTSTATUS +CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject, + PCDINFO CdInfo) +{ + PUCHAR Buffer; + NTSTATUS Status; + ULONG Sector; + PVD_HEADER VdHeader; + ULONG Size; + ULONG Offset; + ULONG i; + struct + { + UCHAR Length[2]; + UCHAR FirstSession; + UCHAR LastSession; + TRACK_DATA TrackData; + } + Toc; + + DPRINT("CdfsGetVolumeData\n"); + + Buffer = ExAllocatePool(NonPagedPool, + CDFS_BASIC_SECTOR); + + if (Buffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + Size = sizeof(Toc); + Status = CdfsDeviceIoControl(DeviceObject, + IOCTL_CDROM_GET_LAST_SESSION, + NULL, + 0, + &Toc, + &Size); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Buffer); + return Status; + } + + DPRINT("FirstSession %d, LastSession %d, FirstTrack %d\n", + Toc.FirstSession, Toc.LastSession, Toc.TrackData.TrackNumber); + + Offset = 0; + for (i = 0; i < 4; i++) + { + Offset = (Offset << 8) + Toc.TrackData.Address[i]; + } + CdInfo->VolumeOffset = Offset; + + DPRINT("Offset of first track in last session %d\n", Offset); + + CdInfo->JolietLevel = 0; + VdHeader = (PVD_HEADER)Buffer; + Buffer[0] = 0; + + for (Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; Sector < 100 && Buffer[0] != 255; Sector++) + { + /* Read the Primary Volume Descriptor (PVD) */ + Status = CdfsReadRawSectors(DeviceObject, + Sector + Offset, + 1, + Buffer); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Buffer); + return(Status); + } + + if (Sector == CDFS_PRIMARY_DESCRIPTOR_LOCATION) + { + DPRINT("CD-identifier: [%.5s]\n", Buffer + 1); + + if (Buffer[0] != 1 || Buffer[1] != 'C' || Buffer[2] != 'D' || + Buffer[3] != '0' || Buffer[4] != '0' || Buffer[5] != '1') + { + ExFreePool(Buffer); + return STATUS_UNRECOGNIZED_VOLUME; + } + } + + switch (VdHeader->VdType) + { + case 0: + DPRINT("BootVolumeDescriptor found!\n"); + break; + + case 1: + DPRINT("PrimaryVolumeDescriptor found!\n"); + CdfsGetPVDData(Buffer, CdInfo); + break; + + case 2: + DPRINT("SupplementaryVolumeDescriptor found!\n"); + CdfsGetSVDData(Buffer, CdInfo); + break; + + case 3: + DPRINT("VolumePartitionDescriptor found!\n"); + break; + + case 255: + DPRINT("VolumeDescriptorSetTerminator found!\n"); + break; + + default: + DPRINT1("Unknown volume descriptor type %u found!\n", VdHeader->VdType); + break; + } + + } + + ExFreePool(Buffer); + + return(STATUS_SUCCESS); +} + +static NTSTATUS +CdfsMountVolume(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt = NULL; + PDEVICE_OBJECT NewDeviceObject = NULL; + PDEVICE_OBJECT DeviceToMount; + PIO_STACK_LOCATION Stack; + PFCB Fcb = NULL; + PCCB Ccb = NULL; + PVPB Vpb; + NTSTATUS Status; + CDINFO CdInfo; + + DPRINT("CdfsMountVolume() called\n"); + + if (DeviceObject != CdfsGlobalData->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; + Vpb = Stack->Parameters.MountVolume.Vpb; + + Status = CdfsGetVolumeData(DeviceToMount, &CdInfo); + if (!NT_SUCCESS(Status)) + { + goto ByeBye; + } + + Status = IoCreateDevice(CdfsGlobalData->DriverObject, + sizeof(DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, +// FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &NewDeviceObject); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = (PVOID)NewDeviceObject->DeviceExtension; + RtlZeroMemory(DeviceExt, + sizeof(DEVICE_EXTENSION)); + + Vpb->SerialNumber = CdInfo.SerialNumber; + Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength; + RtlCopyMemory(Vpb->VolumeLabel, CdInfo.VolumeLabel, CdInfo.VolumeLabelLength * sizeof(WCHAR)); + RtlCopyMemory(&DeviceExt->CdInfo, &CdInfo, sizeof(CDINFO)); + + NewDeviceObject->Vpb = DeviceToMount->Vpb; + + DeviceExt->StorageDevice = DeviceToMount; + DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject; + DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; + DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; + DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL, + DeviceExt->StorageDevice); + + Fcb = CdfsCreateFCB(NULL); + if (Fcb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + + Ccb = ExAllocatePoolWithTag(NonPagedPool, + sizeof(CCB), + TAG_CCB); + if (Ccb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + RtlZeroMemory(Ccb, + sizeof(CCB)); + + DeviceExt->StreamFileObject->Flags = DeviceExt->StreamFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; + DeviceExt->StreamFileObject->FsContext = (PVOID)&Fcb->RFCB; + DeviceExt->StreamFileObject->FsContext2 = Ccb; + DeviceExt->StreamFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + DeviceExt->StreamFileObject->PrivateCacheMap = NULL; + DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb; + Ccb->Fcb = Fcb; + Ccb->PtrFileObject = DeviceExt->StreamFileObject; + Fcb->FileObject = DeviceExt->StreamFileObject; + Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; + + Fcb->Flags = FCB_IS_VOLUME_STREAM; + + Fcb->RFCB.FileSize.QuadPart = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE; + Fcb->RFCB.ValidDataLength = Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; + + Fcb->Entry.ExtentLocationL = 0; + Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE; + + Status = CcRosInitializeFileCache(DeviceExt->StreamFileObject, + &Fcb->RFCB.Bcb, + PAGE_SIZE); + if (!NT_SUCCESS (Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + goto ByeBye; + } + + ExInitializeResourceLite(&DeviceExt->DirResource); +// ExInitializeResourceLite(&DeviceExt->FatResource); + + KeInitializeSpinLock(&DeviceExt->FcbListLock); + InitializeListHead(&DeviceExt->FcbListHead); + + Status = STATUS_SUCCESS; + +ByeBye: + if (!NT_SUCCESS(Status)) + { + /* Cleanup */ + if (DeviceExt && DeviceExt->StreamFileObject) + ObDereferenceObject(DeviceExt->StreamFileObject); + if (Fcb) + ExFreePool(Fcb); + if (Ccb) + ExFreePool(Ccb); + if (NewDeviceObject) + IoDeleteDevice(NewDeviceObject); + } + + DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status); + + return(Status); +} + + +static NTSTATUS +CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_OBJECT DeviceToVerify; + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + CDINFO CdInfo; + + DPRINT1("CdfsVerifyVolume() called\n"); + +#if 0 + if (DeviceObject != CdfsGlobalData->DeviceObject) + { + DPRINT1("DeviceObject != CdfsGlobalData->DeviceObject\n"); + return(STATUS_INVALID_DEVICE_REQUEST); + } +#endif + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject; + + DPRINT("Device object %p Device to verify %p\n", DeviceObject, DeviceToVerify); + + CdInfo.SerialNumber = ~DeviceToVerify->Vpb->SerialNumber; + + Status = CdfsGetVolumeData(DeviceToVerify, &CdInfo); + + if (NT_SUCCESS(Status)) + { + DPRINT("Current serial number %08lx Vpb serial number %08lx\n", + CdInfo.SerialNumber, DeviceToVerify->Vpb->SerialNumber); + + if (CdInfo.SerialNumber != DeviceToVerify->Vpb->SerialNumber) + Status = STATUS_WRONG_VOLUME; + } + + return(Status); +} + + +NTSTATUS STDCALL +CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("CdfsFileSystemControl() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_USER_FS_REQUEST: + DPRINT("CDFS: IRP_MN_USER_FS_REQUEST\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + case IRP_MN_MOUNT_VOLUME: + DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n"); + Status = CdfsMountVolume(DeviceObject, Irp); + break; + + case IRP_MN_VERIFY_VOLUME: + DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n"); + Status = CdfsVerifyVolume(DeviceObject, Irp); + break; + + default: + DPRINT("CDFS FSC: MinorFunction %d\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/cdfs/makefile b/drivers/fs/cdfs/makefile new file mode 100644 index 0000000..57a17ef --- /dev/null +++ b/drivers/fs/cdfs/makefile @@ -0,0 +1,16 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = cdfs + +TARGET_OBJECTS = $(TARGET_NAME).o close.o common.o create.o dirctl.o \ + fcb.o finfo.o fsctl.o misc.o rw.o volinfo.o cleanup.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/fs/cdfs/misc.c b/drivers/fs/cdfs/misc.c new file mode 100644 index 0000000..745359d --- /dev/null +++ b/drivers/fs/cdfs/misc.c @@ -0,0 +1,137 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/misc.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + + +BOOLEAN +wstrcmpjoki(PWSTR s1, + PWSTR s2) +/* + * FUNCTION: Compare two wide character strings, s2 with jokers (* or ?) + * return TRUE if s1 like s2 + */ +{ + while ((*s2=='*')||(*s2=='?')||(towlower(*s1)==towlower(*s2))) + { + if ((*s1)==0 && (*s2)==0) + return(TRUE); + + if(*s2=='*') + { + s2++; + while (*s1) + if (wstrcmpjoki(s1,s2)) + return(TRUE); + else + s1++; + } + else + { + s1++; + s2++; + } + } + + if ((*s2)=='.') + { + for (;((*s2)=='.')||((*s2)=='*')||((*s2)=='?');s2++) + ; + } + + if ((*s1)==0 && (*s2)==0) + return(TRUE); + + return(FALSE); +} + + +VOID +CdfsSwapString(PWCHAR Out, + PUCHAR In, + ULONG Count) +{ + PUCHAR t = (PUCHAR)Out; + ULONG i; + + for (i = 0; i < Count; i += 2) + { + t[i] = In[i+1]; + t[i+1] = In[i]; + if (t[i+1] == 0 && t[i] == ';') + break; + } + t[i] = 0; + t[i+1] = 0; +} + + +VOID +CdfsDateTimeToFileTime(PFCB Fcb, + TIME *FileTime) +{ + TIME_FIELDS TimeFields; + + TimeFields.Milliseconds = 0; + TimeFields.Second = Fcb->Entry.Second; + TimeFields.Minute = Fcb->Entry.Minute; + TimeFields.Hour = Fcb->Entry.Hour; + + TimeFields.Day = Fcb->Entry.Day; + TimeFields.Month = Fcb->Entry.Month; + TimeFields.Year = Fcb->Entry.Year + 1900; + + RtlTimeFieldsToTime(&TimeFields, + (PLARGE_INTEGER)FileTime); +} + + +VOID +CdfsFileFlagsToAttributes(PFCB Fcb, + PULONG FileAttributes) +{ + /* FIXME: Fix attributes */ + + *FileAttributes = // FILE_ATTRIBUTE_READONLY | + (Fcb->Entry.FileFlags & 0x01) ? FILE_ATTRIBUTE_HIDDEN : 0 | + (Fcb->Entry.FileFlags & 0x02) ? FILE_ATTRIBUTE_DIRECTORY : 0 | + (Fcb->Entry.FileFlags & 0x04) ? FILE_ATTRIBUTE_SYSTEM : 0 | + (Fcb->Entry.FileFlags & 0x10) ? FILE_ATTRIBUTE_READONLY : 0; +} + +/* EOF */ diff --git a/drivers/fs/cdfs/rw.c b/drivers/fs/cdfs/rw.c new file mode 100644 index 0000000..75eda1b --- /dev/null +++ b/drivers/fs/cdfs/rw.c @@ -0,0 +1,230 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/cdfs/rw.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* GLOBALS *******************************************************************/ + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#define ROUND_DOWN(N, S) ((N) - ((N) % (S))) + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsReadFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PUCHAR Buffer, + ULONG Length, + ULONG ReadOffset, + ULONG IrpFlags, + PULONG LengthRead) +/* + * FUNCTION: Reads data from a file + */ +{ + NTSTATUS Status = STATUS_SUCCESS; + PUCHAR TempBuffer; + ULONG TempLength; + PCCB Ccb; + PFCB Fcb; + + DPRINT("CdfsReadFile(ReadOffset %lu Length %lu)\n", ReadOffset, Length); + + *LengthRead = 0; + + if (Length == 0) + return STATUS_SUCCESS; + + Ccb = (PCCB)FileObject->FsContext2; + Fcb = Ccb->Fcb; + + if (ReadOffset + Length > Fcb->Entry.DataLengthL) + Length = Fcb->Entry.DataLengthL - ReadOffset; + + DPRINT("Reading %d bytes at %d\n", Length, ReadOffset); + + if (Length == 0) + return(STATUS_UNSUCCESSFUL); + + if (!(IrpFlags & (IRP_NOCACHE|IRP_PAGING_IO))) + { + LARGE_INTEGER FileOffset; + IO_STATUS_BLOCK IoStatus; + + if (FileObject->PrivateCacheMap == NULL) + { + CcRosInitializeFileCache(FileObject, &Fcb->RFCB.Bcb, PAGE_SIZE); + } + + FileOffset.QuadPart = (LONGLONG)ReadOffset; + CcCopyRead(FileObject, + &FileOffset, + Length, + TRUE, + Buffer, + &IoStatus); + *LengthRead = IoStatus.Information; + + return(IoStatus.Status); + } + + if ((ReadOffset % BLOCKSIZE) != 0) + { + TempLength = min(Length, BLOCKSIZE - (ReadOffset % BLOCKSIZE)); + TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); + + Status = CdfsReadSectors(DeviceExt->StorageDevice, + Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE), + 1, + TempBuffer); + if (NT_SUCCESS(Status)) + { + memcpy(Buffer, TempBuffer + (ReadOffset % BLOCKSIZE), TempLength); + (*LengthRead) = (*LengthRead) + TempLength; + Length = Length - TempLength; + Buffer = Buffer + TempLength; + ReadOffset = ReadOffset + TempLength; + } + ExFreePool(TempBuffer); + } + + DPRINT("Status %lx\n", Status); + + if ((Length / BLOCKSIZE) != 0 && NT_SUCCESS(Status)) + { + TempLength = ROUND_DOWN(Length, BLOCKSIZE); + Status = CdfsReadSectors(DeviceExt->StorageDevice, + Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE), + TempLength / BLOCKSIZE, + Buffer); + if (NT_SUCCESS(Status)) + { + (*LengthRead) = (*LengthRead) + TempLength; + Length = Length - TempLength; + Buffer = Buffer + TempLength; + ReadOffset = ReadOffset + TempLength; + } + } + + DPRINT("Status %lx\n", Status); + + if (Length > 0 && NT_SUCCESS(Status)) + { + TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); + + Status = CdfsReadSectors(DeviceExt->StorageDevice, + Fcb->Entry.ExtentLocationL + (ReadOffset / BLOCKSIZE), + 1, + TempBuffer); + if (NT_SUCCESS(Status)) + { + memcpy(Buffer, TempBuffer, Length); + (*LengthRead) = (*LengthRead) + Length; + } + ExFreePool(TempBuffer); + } + + return(Status); +} + + +NTSTATUS STDCALL +CdfsRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PVOID Buffer; + ULONG ReadLength; + LARGE_INTEGER ReadOffset; + ULONG ReturnedReadLength = 0; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("CdfsRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + DeviceExt = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + + ReadLength = Stack->Parameters.Read.Length; + ReadOffset = Stack->Parameters.Read.ByteOffset; + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + + Status = CdfsReadFile(DeviceExt, + FileObject, + Buffer, + ReadLength, + ReadOffset.u.LowPart, + Irp->Flags, + &ReturnedReadLength); + +ByeBye: + if (NT_SUCCESS(Status)) + { + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + FileObject->CurrentByteOffset.QuadPart = + ReadOffset.QuadPart + ReturnedReadLength; + } + Irp->IoStatus.Information = ReturnedReadLength; + } + else + { + Irp->IoStatus.Information = 0; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +CdfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("CdfsWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + return(STATUS_NOT_SUPPORTED); +} + +/* EOF */ diff --git a/drivers/fs/cdfs/volinfo.c b/drivers/fs/cdfs/volinfo.c new file mode 100644 index 0000000..ba5aff9 --- /dev/null +++ b/drivers/fs/cdfs/volinfo.c @@ -0,0 +1,243 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/volume.c + * PURPOSE: CDROM (ISO 9660) filesystem driver + * PROGRAMMER: Art Yerkes + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "cdfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +CdfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, + PULONG BufferLength) +{ + ULONG LabelLength; + + DPRINT("CdfsGetFsVolumeInformation() called\n"); + DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + + DPRINT("Vpb %p\n", DeviceObject->Vpb); + LabelLength = DeviceObject->Vpb->VolumeLabelLength; + + DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))); + DPRINT("LabelLength %lu\n", LabelLength); + DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel); + + if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))) + return STATUS_BUFFER_OVERFLOW; + + /* valid entries */ + FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber; + FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR); + wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel); + + /* dummy entries */ + FsVolumeInfo->VolumeCreationTime.QuadPart = 0; + FsVolumeInfo->SupportsObjects = FALSE; + + DPRINT("Finished FsdGetFsVolumeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR)); + + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, + PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetFsAttributeInformation()\n"); + DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)); + + if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)) + return STATUS_BUFFER_OVERFLOW; + + FsAttributeInfo->FileSystemAttributes = + FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK; + FsAttributeInfo->MaximumComponentNameLength = 255; + FsAttributeInfo->FileSystemNameLength = 8; + + memcpy(FsAttributeInfo->FileSystemName, L"CDFS", 8); + + DPRINT("Finished FsdGetFsAttributeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_SIZE_INFORMATION FsSizeInfo, + PULONG BufferLength) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("CdfsGetFsSizeInformation()\n"); + DPRINT("FsSizeInfo = %p\n", FsSizeInfo); + + if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + DeviceExt = DeviceObject->DeviceExtension; + + FsSizeInfo->AvailableAllocationUnits.QuadPart = 0; + FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->CdInfo.VolumeSpaceSize; + FsSizeInfo->SectorsPerAllocationUnit = 1; + FsSizeInfo->BytesPerSector = BLOCKSIZE; + + DPRINT("Finished FsdGetFsSizeInformation()\n"); + if (NT_SUCCESS(Status)) + *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION); + + return(Status); +} + + +static NTSTATUS +CdfsGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, + PULONG BufferLength) +{ + DPRINT("CdfsGetFsDeviceInformation()\n"); + DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION)); + + if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + FsDeviceInfo->DeviceType = FILE_DEVICE_CD_ROM; + FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */ + + DPRINT("FsdGetFsDeviceInformation() finished.\n"); + + *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + + +NTSTATUS STDCALL +CdfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + FS_INFORMATION_CLASS FsInformationClass; + PIO_STACK_LOCATION Stack; + NTSTATUS Status = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + DPRINT("CdfsQueryVolumeInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass; + BufferLength = Stack->Parameters.QueryVolume.Length; + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + + DPRINT("FsInformationClass %d\n", FsInformationClass); + DPRINT("SystemBuffer %x\n", SystemBuffer); + + switch (FsInformationClass) + { + case FileFsVolumeInformation: + Status = CdfsGetFsVolumeInformation(DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsAttributeInformation: + Status = CdfsGetFsAttributeInformation(DeviceObject->DeviceExtension, + SystemBuffer, + &BufferLength); + break; + + case FileFsSizeInformation: + Status = CdfsGetFsSizeInformation(DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsDeviceInformation: + Status = CdfsGetFsDeviceInformation(SystemBuffer, + &BufferLength); + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryVolume.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +CdfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("CdfsSetVolumeInformation() called\n"); + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NOT_SUPPORTED); +} + +/* EOF */ diff --git a/drivers/fs/ext2/attr.c b/drivers/fs/ext2/attr.c new file mode 100644 index 0000000..9992d7a --- /dev/null +++ b/drivers/fs/ext2/attr.c @@ -0,0 +1,136 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/attr.c + * PURPOSE: Set/Get file attributes support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +Ext2SetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("Ext2SetInformation(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +Ext2QueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + NTSTATUS Status; + PIO_STACK_LOCATION Param; + PFILE_OBJECT FileObject; + PDEVICE_EXTENSION DeviceExt; + ULONG Length; + PFILE_BASIC_INFORMATION PFileBasicInformation; + PFILE_STANDARD_INFORMATION PFileStandardInformation; + PFILE_INTERNAL_INFORMATION PFileInternalInformation; + PFILE_EA_INFORMATION PFileEaInformation; + PFILE_ACCESS_INFORMATION PFileAccessInformation; + PFILE_NAME_INFORMATION PFileNameInformation; + PFILE_POSITION_INFORMATION PFilePositionInformation; + PVOID Buffer; + + DPRINT("Ext2QueryInformation(DeviceObject %x Irp %x)\n", DeviceObject, Irp); + + Param = IoGetCurrentIrpStackLocation(Irp); + FileObject = Param->FileObject; + DeviceExt = DeviceObject->DeviceExtension; + Length = Param->Parameters.QueryFile.Length; + Buffer = Irp->AssociatedIrp.SystemBuffer; + + switch (Param->Parameters.QueryFile.FileInformationClass) + { + case FileDirectoryInformation: + case FileFullDirectoryInformation: + case FileBothDirectoryInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FileBasicInformation: + PFileBasicInformation = (PFILE_BASIC_INFORMATION)Buffer; + memset(PFileBasicInformation, 0, sizeof(FILE_BASIC_INFORMATION)); + Status = STATUS_SUCCESS; + break; + + case FileStandardInformation: + PFileStandardInformation = (PFILE_STANDARD_INFORMATION)Buffer; + memset(PFileStandardInformation, 0, sizeof(FILE_STANDARD_INFORMATION)); + Status = STATUS_SUCCESS; + break; + + case FileInternalInformation: + PFileInternalInformation = (PFILE_INTERNAL_INFORMATION)Buffer; + memset(PFileInternalInformation, 0, sizeof(FILE_INTERNAL_INFORMATION)); + Status = STATUS_SUCCESS; + break; + + case FileEaInformation: + PFileEaInformation = (PFILE_EA_INFORMATION)Buffer; + memset(PFileEaInformation, 0, sizeof(FILE_EA_INFORMATION)); + PFileEaInformation->EaSize = 0; + Status = STATUS_SUCCESS; + break; + + case FileAccessInformation: + PFileAccessInformation = (PFILE_ACCESS_INFORMATION)Buffer; + memset(PFileAccessInformation, 0, sizeof(FILE_ACCESS_INFORMATION)); + PFileAccessInformation->AccessFlags = 0; + Status = STATUS_SUCCESS; + break; + + case FileNameInformation: + PFileNameInformation = (PFILE_NAME_INFORMATION)Buffer; + memset(PFileNameInformation, 0, sizeof(FILE_NAME_INFORMATION)); + Status = STATUS_SUCCESS; + break; + + case FilePositionInformation: + PFilePositionInformation = (PFILE_POSITION_INFORMATION)Buffer; + memcpy(PFilePositionInformation, + &FileObject->CurrentByteOffset, + sizeof(FileObject->CurrentByteOffset)); + Status = STATUS_SUCCESS; + break; + + case FileRenameInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + + + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Param->Parameters.QueryFile.Length - Length; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} diff --git a/drivers/fs/ext2/blockdev.c b/drivers/fs/ext2/blockdev.c new file mode 100644 index 0000000..c64ae87 --- /dev/null +++ b/drivers/fs/ext2/blockdev.c @@ -0,0 +1,155 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/blockdev.c + * PURPOSE: Temporary sector reading support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN +Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN PVOID Buffer) +{ + LARGE_INTEGER sectorNumber; + PIRP irp; + IO_STATUS_BLOCK ioStatus; + KEVENT event; + NTSTATUS status; + ULONG sectorSize; + int j; + + DPRINT("VFATReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n", + pDeviceObject,DiskSector,Buffer); + + sectorNumber.u.HighPart = 0; + sectorNumber.u.LowPart = DiskSector * BLOCKSIZE; + + DPRINT("DiskSector:%ld BLKSZ:%ld sectorNumber:%ld:%ld\n", + (unsigned long) DiskSector, + (unsigned long) BLOCKSIZE, + (unsigned long) sectorNumber.u.HighPart, + (unsigned long) sectorNumber.u.LowPart); + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + sectorSize = BLOCKSIZE*SectorCount; + + + DPRINT("Building synchronous FSD Request...\n"); + irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + pDeviceObject, + Buffer, + sectorSize, + §orNumber, + &event, + &ioStatus ); + + if (!irp) + { + DbgPrint("READ failed!!!\n"); + return FALSE; + } + + DPRINT("Calling IO Driver...\n"); + status = IoCallDriver(pDeviceObject, irp); + + DPRINT("Waiting for IO Operation...\n"); + if (status == STATUS_PENDING) + { + KeWaitForSingleObject(&event, + Suspended, + KernelMode, + FALSE, + NULL); + DPRINT("Getting IO Status...\n"); + status = ioStatus.Status; + } + + if (!NT_SUCCESS(status)) + { + DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status); + return FALSE; + } + + return TRUE; +} + +BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN UCHAR* Buffer) +{ + LARGE_INTEGER sectorNumber; + PIRP irp; + IO_STATUS_BLOCK ioStatus; + KEVENT event; + NTSTATUS status; + ULONG sectorSize; + PULONG mbr; + int j; + + DPRINT("VFATWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n", + pDeviceObject,DiskSector,Buffer); + + sectorNumber.u.HighPart = 0; + sectorNumber.u.LowPart = DiskSector * BLOCKSIZE; + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + sectorSize = BLOCKSIZE*SectorCount; + + + DPRINT("Building synchronous FSD Request...\n"); + irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, + pDeviceObject, + Buffer, + sectorSize, + §orNumber, + &event, + &ioStatus ); + + if (!irp) { + DbgPrint("WRITE failed!!!\n"); + return FALSE; + } + + DPRINT("Calling IO Driver...\n"); + status = IoCallDriver(pDeviceObject, + irp); + + DPRINT("Waiting for IO Operation...\n"); + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, + Suspended, + KernelMode, + FALSE, + NULL); + DPRINT("Getting IO Status...\n"); + status = ioStatus.Status; + } + + if (!NT_SUCCESS(status)) { + DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status); + return FALSE; + } + + + ExFreePool(mbr); + DPRINT("Block request succeeded\n"); + return TRUE; +} + diff --git a/drivers/fs/ext2/dir.c b/drivers/fs/ext2/dir.c new file mode 100644 index 0000000..5c8e2ed --- /dev/null +++ b/drivers/fs/ext2/dir.c @@ -0,0 +1,338 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/dir.c + * PURPOSE: ext2 filesystem + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS *****************************************************************/ + + +static VOID Ext2ConvertName(PWSTR Out, PCH In, ULONG Len) +{ + ULONG i; + + for (i=0; iinode, + &inode); + + switch (IoStack->Parameters.QueryDirectory.FileInformationClass) + { + case FileNamesInformation: + FNI = (PFILE_NAMES_INFORMATION)Buffer; + FNI->NextEntryOffset = sizeof(FileDirectoryInformation) + + dir_entry->name_len + 1; + FNI->FileNameLength = dir_entry->name_len; + Ext2ConvertName(FNI->FileName, dir_entry->name, dir_entry->name_len); + Buffer = Buffer + FNI->NextEntryOffset; + break; + + case FileDirectoryInformation: + FDI = (PFILE_DIRECTORY_INFORMATION)Buffer; + FDI->NextEntryOffset = sizeof(FileDirectoryInformation) + + dir_entry->name_len + 1; + FDI->FileIndex = FileIndex; +// FDI->CreationTime = 0; +// FDI->LastAccessTime = 0; +// FDI->LastWriteTime = 0; +// FDI->ChangeTime = 0; + FDI->AllocationSize.QuadPart = FDI->EndOfFile.QuadPart = inode.i_size; + FDI->FileAttributes = 0; + FDI->FileNameLength = dir_entry->name_len; + Ext2ConvertName(FDI->FileName, dir_entry->name, dir_entry->name_len); + Buffer = Buffer + FDI->NextEntryOffset; + break; + + case FileBothDirectoryInformation: + FBI = (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer; + FBI->NextEntryOffset = sizeof(FileBothDirectoryInformation) + + dir_entry->name_len + 1; + FBI->FileIndex = FileIndex; + FBI->AllocationSize.QuadPart = FBI->EndOfFile.QuadPart = inode.i_size; + FBI->FileAttributes = 0; + FBI->FileNameLength = dir_entry->name_len; + Ext2ConvertName(FBI->FileName, dir_entry->name, dir_entry->name_len); + memset(FBI->ShortName, 0, sizeof(FBI->ShortName)); + Buffer = Buffer + FBI->NextEntryOffset; + break; + + default: + UNIMPLEMENTED; + } + return(Buffer); +} + + +NTSTATUS Ext2QueryDirectory(PDEVICE_EXTENSION DeviceExt, + PEXT2_FCB Fcb, + PIRP Irp, + PIO_STACK_LOCATION IoStack) +{ + ULONG Max; + ULONG i; + ULONG StartIndex; + PVOID Buffer = NULL; + struct ext2_dir_entry dir_entry; + + Buffer = Irp->UserBuffer; + DPRINT("Buffer %x\n",Buffer); + DPRINT("IoStack->Flags %x\n",IoStack->Flags); + + if (IoStack->Flags & SL_RETURN_SINGLE_ENTRY) + { + Max = 1; + } + else + { + UNIMPLEMENTED; + } + + DPRINT("Buffer->FileIndex %d\n", + ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex); + if (IoStack->Flags & SL_INDEX_SPECIFIED) + { + StartIndex = ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex; + } + else + { + StartIndex = 0; + } + + if (IoStack->Flags & SL_RESTART_SCAN) + { + StartIndex = 0; + } + + DPRINT("StartIndex %d\n",StartIndex); + + for (i=0; iinode,"*",&dir_entry,&StartIndex)) + { + ((PFILE_DIRECTORY_INFORMATION)Buffer)->NextEntryOffset = 0; + return(STATUS_NO_MORE_FILES); + } + Buffer = Ext2ProcessDirEntry(DeviceExt, + &dir_entry, + IoStack, + Buffer, + StartIndex); + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + PEXT2_FCB Fcb = (PVOID)FileObject->FsContext; + NTSTATUS Status; + PDEVICE_EXTENSION DeviceExt; + + DPRINT("Ext2DirectoryControl(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + DeviceExt = DeviceObject->DeviceExtension; + + switch (Stack->MinorFunction) + { + case IRP_MN_QUERY_DIRECTORY: + Status = Ext2QueryDirectory(DeviceExt, Fcb, Irp, Stack); + break; + + default: + Status = STATUS_UNSUCCESSFUL; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt, + struct ext2_inode* dir, + PCH filename, + struct ext2_dir_entry* ret, + PULONG StartIndex) +{ + ULONG i; + char* buffer; + ULONG offset; + char name[255]; + struct ext2_dir_entry* current; + ULONG block; + BOOL b; + + DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret); + + buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); + + for (i=0; i<((*StartIndex)/BLOCKSIZE); i++); + for (; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++) + { + DPRINT("block %d\n",block); + b = Ext2ReadSectors(DeviceExt->StorageDevice, + block, + 1, + buffer); + if (!b) + { + DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__); + return(FALSE); + } + + offset = (*StartIndex)%BLOCKSIZE; + while (offset < BLOCKSIZE) + { + current = &buffer[offset]; + + strncpy(name,current->name,current->name_len); + name[current->name_len]=0; + + DPRINT("Scanning offset %d inode %d name %s\n", + offset,current->inode,name); + + DPRINT("Comparing %s %s\n",name,filename); + if (strcmp(name,filename)==0 || strcmp(filename,"*")==0) + { + DPRINT("Match found\n"); + *StartIndex = (i*BLOCKSIZE) + offset + current->rec_len; + memcpy(ret,current,sizeof(struct ext2_dir_entry)); + ExFreePool(buffer); + return(TRUE); + } + + offset = offset + current->rec_len; + assert(current->rec_len != 0); + DPRINT("offset %d\n",offset); + } + DPRINT("Onto next block\n"); + } + DPRINT("No match\n"); + ExFreePool(buffer); + return(FALSE); +} + +void unicode_to_ansi(PCH StringA, PWSTR StringW) +{ + while((*StringW)!=0) + { + *StringA = *StringW; + StringA++; + StringW++; + } + *StringA = 0; +} + +NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PWSTR FileName) +/* + * FUNCTION: Opens a file + */ +{ + EXT2_INODE parent_inode; + struct ext2_dir_entry entry; + char name[255]; + ULONG current_inode = 2; + char* current_segment; + PEXT2_FCB Fcb; + ULONG StartIndex = 0; + + DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %S)\n", + DeviceExt,FileObject,FileName); + + Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB)); + + unicode_to_ansi(name,FileName); + DPRINT("name %s\n",name); + DPRINT("strtok %x\n",strtok); + current_segment = strtok(name,"\\"); + DPRINT("current_segment %x\n", current_segment); + while (current_segment!=NULL) + { + Ext2LoadInode(DeviceExt, + current_inode, + &parent_inode); + if (!Ext2ScanDir(DeviceExt, + parent_inode.inode, + current_segment, + &entry, + &StartIndex)) + { + Ext2ReleaseInode(DeviceExt, + &parent_inode); + ExFreePool(Fcb); + return(STATUS_UNSUCCESSFUL); + } + current_inode = entry.inode; + current_segment = strtok(NULL,"\\"); + StartIndex = 0; + Ext2ReleaseInode(DeviceExt, + &parent_inode); + } + DPRINT("Found file\n"); + + Fcb->inode = current_inode; + CcRosInitializeFileCache(FileObject, &Fcb->Bcb, PAGE_SIZE*3); + FileObject->FsContext = Fcb; + + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + NTSTATUS Status; + PDEVICE_EXTENSION DeviceExt; + + DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + DeviceExt = DeviceObject->DeviceExtension; + Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} diff --git a/drivers/fs/ext2/ext2fs.h b/drivers/fs/ext2/ext2fs.h new file mode 100644 index 0000000..9d18ae7 --- /dev/null +++ b/drivers/fs/ext2/ext2fs.h @@ -0,0 +1,289 @@ +#include +#include + +BOOLEAN Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN PVOID Buffer); + +#define BLOCKSIZE (1024) + +struct ext2_super_block { + ULONG s_inodes_count; /* Inodes count */ + ULONG s_blocks_count; /* Blocks count */ + ULONG s_r_blocks_count; /* Reserved blocks count */ + ULONG s_free_blocks_count; /* Free blocks count */ + ULONG s_free_inodes_count; /* Free inodes count */ + ULONG s_first_data_block; /* First Data Block */ + ULONG s_log_block_size; /* Block size */ + LONG s_log_frag_size; /* Fragment size */ + ULONG s_blocks_per_group; /* # Blocks per group */ + ULONG s_frags_per_group; /* # Fragments per group */ + ULONG s_inodes_per_group; /* # Inodes per group */ + ULONG s_mtime; /* Mount time */ + ULONG s_wtime; /* Write time */ + USHORT s_mnt_count; /* Mount count */ + SHORT s_max_mnt_count; /* Maximal mount count */ + USHORT s_magic; /* Magic signature */ + USHORT s_state; /* File system state */ + USHORT s_errors; /* Behaviour when detecting errors */ + USHORT s_minor_rev_level; /* minor revision level */ + ULONG s_lastcheck; /* time of last check */ + ULONG s_checkinterval; /* max. time between checks */ + ULONG s_creator_os; /* OS */ + ULONG s_rev_level; /* Revision level */ + USHORT s_def_resuid; /* Default uid for reserved blocks */ + USHORT s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + ULONG s_first_ino; /* First non-reserved inode */ + USHORT s_inode_size; /* size of inode structure */ + USHORT s_block_group_nr; /* block group # of this superblock */ + ULONG s_feature_compat; /* compatible feature set */ + ULONG s_feature_incompat; /* incompatible feature set */ + ULONG s_feature_ro_compat; /* readonly-compatible feature set */ + ULONG s_reserved[230]; /* Padding to the end of the block */ +}; + +/* + * Codes for operating systems + */ +#define EXT2_OS_LINUX 0 +#define EXT2_OS_HURD 1 +#define EXT2_OS_MASIX 2 +#define EXT2_OS_FREEBSD 3 +#define EXT2_OS_LITES 4 + +/* + * Revision levels + */ +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ + +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV + +/* + * The second extended file system magic number + */ +#define EXT2_SUPER_MAGIC 0xEF53 + +/* + * Constants relative to the data blocks + */ +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + + +/* + * Structure of an inode on the disk + */ +struct ext2_inode { + USHORT i_mode; /* File mode */ + USHORT i_uid; /* Owner Uid */ + ULONG i_size; /* Size in bytes */ + ULONG i_atime; /* Access time */ + ULONG i_ctime; /* Creation time */ + ULONG i_mtime; /* Modification time */ + ULONG i_dtime; /* Deletion Time */ + USHORT i_gid; /* Group Id */ + USHORT i_links_count; /* Links count */ + ULONG i_blocks; /* Blocks count */ + ULONG i_flags; /* File flags */ + union { + struct { + ULONG l_i_reserved1; + } linux1; + struct { + ULONG h_i_translator; + } hurd1; + struct { + ULONG m_i_reserved1; + } masix1; + } osd1; /* OS dependent 1 */ + ULONG i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ + ULONG i_version; /* File version (for NFS) */ + ULONG i_file_acl; /* File ACL */ + ULONG i_dir_acl; /* Directory ACL */ + ULONG i_faddr; /* Fragment address */ + union { + struct { + UCHAR l_i_frag; /* Fragment number */ + UCHAR l_i_fsize; /* Fragment size */ + USHORT i_pad1; + ULONG l_i_reserved2[2]; + } linux2; + struct { + UCHAR h_i_frag; /* Fragment number */ + UCHAR h_i_fsize; /* Fragment size */ + USHORT h_i_mode_high; + USHORT h_i_uid_high; + USHORT h_i_gid_high; + ULONG h_i_author; + } hurd2; + struct { + UCHAR m_i_frag; /* Fragment number */ + UCHAR m_i_fsize; /* Fragment size */ + USHORT m_pad1; + ULONG m_i_reserved2[2]; + } masix2; + } osd2; /* OS dependent 2 */ +}; + +#if defined(__KERNEL__) || defined(__linux__) +#define i_reserved1 osd1.linux1.l_i_reserved1 +#define i_frag osd2.linux2.l_i_frag +#define i_fsize osd2.linux2.l_i_fsize +#define i_reserved2 osd2.linux2.l_i_reserved2 +#endif + +#ifdef __hurd__ +#define i_translator osd1.hurd1.h_i_translator +#define i_frag osd2.hurd2.h_i_frag; +#define i_fsize osd2.hurd2.h_i_fsize; +#define i_uid_high osd2.hurd2.h_i_uid_high +#define i_gid_high osd2.hurd2.h_i_gid_high +#define i_author osd2.hurd2.h_i_author +#endif + +#ifdef __masix__ +#define i_reserved1 osd1.masix1.m_i_reserved1 +#define i_frag osd2.masix2.m_i_frag +#define i_fsize osd2.masix2.m_i_fsize +#define i_reserved2 osd2.masix2.m_i_reserved2 +#endif + +/* + * Constants relative to the data blocks + */ +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + +/* + * Inode flags + */ +#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ +#define EXT2_UNRM_FL 0x00000002 /* Undelete */ +#define EXT2_COMPR_FL 0x00000004 /* Compress file */ +#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ +#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ +#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ +#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ + + +/* + * Structure of a blocks group descriptor + */ +struct ext2_group_desc +{ + ULONG bg_block_bitmap; /* Blocks bitmap block */ + ULONG bg_inode_bitmap; /* Inodes bitmap block */ + ULONG bg_inode_table; /* Inodes table block */ + USHORT bg_free_blocks_count; /* Free blocks count */ + USHORT bg_free_inodes_count; /* Free inodes count */ + USHORT bg_used_dirs_count; /* Directories count */ + USHORT bg_pad; + ULONG bg_reserved[3]; +}; + +#define EXT2_NAME_LEN 255 + +struct ext2_dir_entry { + ULONG inode; /* Inode number */ + USHORT rec_len; /* Directory entry length */ + USHORT name_len; /* Name length */ + char name[EXT2_NAME_LEN]; /* File name */ +}; + +typedef struct +{ + PDEVICE_OBJECT StorageDevice; + struct ext2_super_block* superblock; + PFILE_OBJECT FileObject; + PBCB Bcb; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +typedef struct _EXT2_GROUP_DESC +{ + ERESOURCE Lock; + struct ext2_group_desc* desc; + PCACHE_SEGMENT CacheSeg; + PVOID BaseAddress; +} EXT2_GROUP_DESC, *PEXT2_GROUP_DESC; + +PEXT2_GROUP_DESC Ext2LoadGroup(PDEVICE_EXTENSION DeviceExt, + ULONG BlockGrp); +VOID Ext2ReleaseGroup(PDEVICE_EXTENSION DeviceExt, + PEXT2_GROUP_DESC GrpDesc); + +VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt, + ULONG ino, + struct ext2_inode* inode); +struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt, + ULONG block_group); + +typedef struct _EXT2_INODE +{ + struct ext2_inode* inode; + PVOID BaseAddress; + PCACHE_SEGMENT CacheSeg; +} EXT2_INODE, *PEXT2_INODE; + +typedef struct _EXT2_FCB +{ + ULONG inode; + EXT2_INODE i; + PBCB Bcb; +} EXT2_FCB, *PEXT2_FCB; + +ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt, + struct ext2_inode* inode, + ULONG offset); +NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PWSTR FileName); +NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + LARGE_INTEGER Offset); +NTSTATUS STDCALL Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2QueryQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2SetQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2SetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2QuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2SetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2QueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2Read(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2Write(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2Cleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2FlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL Ext2Shutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS Ext2ReadPage(PDEVICE_EXTENSION DeviceExt, + PEXT2_FCB Fcb, + PVOID Buffer, + ULONG Offset); +VOID Ext2LoadInode(PDEVICE_EXTENSION DeviceExt, + ULONG ino, + PEXT2_INODE Inode); +VOID Ext2ReleaseInode(PDEVICE_EXTENSION DeviceExt, + PEXT2_INODE Inode); + diff --git a/drivers/fs/ext2/ext2fs.rc b/drivers/fs/ext2/ext2fs.rc new file mode 100644 index 0000000..ab3ab66 --- /dev/null +++ b/drivers/fs/ext2/ext2fs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Linux ext2 IFS Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "ext2fs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ext2fs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/ext2/file.c b/drivers/fs/ext2/file.c new file mode 100644 index 0000000..ee35ca3 --- /dev/null +++ b/drivers/fs/ext2/file.c @@ -0,0 +1,61 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/super.c + * PURPOSE: ext2 filesystem + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS ****************************************************************/ + +#define addr_per_block (BLOCKSIZE / sizeof(ULONG)) + +ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt, + struct ext2_inode* inode, + ULONG offset) +{ + ULONG block; + PULONG TempBuffer; + BOOL b; + + DPRINT("Ext2BlockMap(DeviceExt %x, inode %x, offset %d)\n", + DeviceExt,inode,offset); + if (offset < EXT2_NDIR_BLOCKS) + { + block = inode->i_block[offset]; + DPRINT("block %d\n",block); + return(block); + } + offset = offset - EXT2_NDIR_BLOCKS; + if (offset < addr_per_block) + { + block = inode->i_block[EXT2_IND_BLOCK]; + TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); + b = Ext2ReadSectors(DeviceExt->StorageDevice, + block, + 1, + TempBuffer); + if (!b) + { + DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__); + return(0); + } + block = TempBuffer[offset]; + ExFreePool(TempBuffer); + return(block); + } + offset = offset - addr_per_block; + DbgPrint("Failed at %s:%d\n",__FILE__,__LINE__); + for(;;); +} + diff --git a/drivers/fs/ext2/inode.c b/drivers/fs/ext2/inode.c new file mode 100644 index 0000000..cb0e1ee --- /dev/null +++ b/drivers/fs/ext2/inode.c @@ -0,0 +1,148 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/inode.c + * PURPOSE: Manipulating inodes + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 26/12/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS ***************************************************************/ + +struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt, + ULONG block_group) +{ + struct ext2_group_desc* buffer; + ULONG block; + struct ext2_group_desc* gdp; + + buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); + + block = block_group / (BLOCKSIZE / sizeof(struct ext2_group_desc)); + + Ext2ReadSectors(DeviceExt->StorageDevice, + 2 + block, + 1, + buffer); + + gdp = &buffer[block_group % (BLOCKSIZE / sizeof(struct ext2_group_desc))]; + + DPRINT("gdp->bg_free_blocks_count %d\n",gdp->bg_free_blocks_count); + DPRINT("gdp->bg_inode_table %d\n",gdp->bg_inode_table); + + return(gdp); + +} + +#define INODES_PER_PAGE (PAGE_SIZE / sizeof(struct ext2_inode)) +#define INODES_PER_BLOCK (BLOCKSIZE / sizeof(struct ext2_inode)) + +VOID Ext2LoadInode(PDEVICE_EXTENSION DeviceExt, + ULONG ino, + PEXT2_INODE Inode) +{ + ULONG block_group; + struct ext2_group_desc* gdp; + ULONG offset; + ULONG dsec; + BOOLEAN Uptodate; + struct ext2_inode* ibuffer; + + DPRINT("Ext2LoadInode(DeviceExt %x, ino %d, Inode %x)\n", + DeviceExt, ino, Inode); + + block_group = (ino - 1) / DeviceExt->superblock->s_inodes_per_group; + + DPRINT("block_group %d\n",block_group); + + gdp = Ext2LoadGroupDesc(DeviceExt, block_group); + + offset = (ino - 1) % DeviceExt->superblock->s_inodes_per_group; + + DPRINT("offset %d\n", offset); + + dsec = (gdp->bg_inode_table + (offset / INODES_PER_BLOCK)) * BLOCKSIZE; + + DPRINT("dsec %d (dsec/BLOCKSIZE) %d PAGE_ROUND_DOWN(dsec) %d\n", + dsec, (dsec/BLOCKSIZE), PAGE_ROUND_DOWN(dsec)); + + CcRequestCachePage(DeviceExt->Bcb, + PAGE_ROUND_DOWN(dsec), + &Inode->BaseAddress, + &Uptodate, + &Inode->CacheSeg); + DPRINT("PAGE_ROUND_DOWN(dsec)/BLOCKSIZE %d\n", + PAGE_ROUND_DOWN(dsec)/BLOCKSIZE); + if (!Uptodate) + { + Ext2ReadSectors(DeviceExt->StorageDevice, + PAGE_ROUND_DOWN(dsec) / BLOCKSIZE, + 4, + Inode->BaseAddress); + } + ibuffer = ((struct ext2_inode *)Inode->BaseAddress) + + (dsec - PAGE_ROUND_DOWN(dsec)); + DPRINT("Inode->BaseAddress 0x%x ibuffer 0x%x\n", + Inode->BaseAddress, ibuffer); + Inode->inode = &ibuffer[offset % INODES_PER_PAGE]; + + DPRINT("inode->i_uid %d\n",Inode->inode->i_uid); + DPRINT("inode->i_links_count %d\n",Inode->inode->i_links_count); + DPRINT("inode->i_blocks %d\n",Inode->inode->i_blocks); + + DPRINT("Ext2LoadInode() finished\n"); +} + +VOID Ext2ReleaseInode(PDEVICE_EXTENSION DeviceExt, + PEXT2_INODE Inode) +{ + CcReleaseCachePage(DeviceExt->Bcb, + Inode->CacheSeg, + TRUE); + Inode->CacheSeg = NULL; + Inode->BaseAddress = NULL; + Inode->inode = NULL; +} + +VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt, + ULONG ino, + struct ext2_inode* inode) +{ + ULONG block_group; + struct ext2_group_desc* gdp; + ULONG offset; + struct ext2_inode* buffer; + + DPRINT("Ext2ReadInode(DeviceExt %x, ino %d, inode %x)\n", + DeviceExt,ino,inode); + + block_group = (ino - 1) / DeviceExt->superblock->s_inodes_per_group; + + gdp = Ext2LoadGroupDesc(DeviceExt, block_group); + + + + offset = (ino - 1) % DeviceExt->superblock->s_inodes_per_group; + + buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE); + Ext2ReadSectors(DeviceExt->StorageDevice, + gdp->bg_inode_table + (offset / INODES_PER_BLOCK), + 1, + buffer); + memcpy(inode,&buffer[offset % INODES_PER_BLOCK],sizeof(struct ext2_inode)); + + DPRINT("inode->i_uid %d\n",inode->i_uid); + DPRINT("inode->i_links_count %d\n",inode->i_links_count); + DPRINT("inode->i_blocks %d\n",inode->i_blocks); + +} diff --git a/drivers/fs/ext2/makefile b/drivers/fs/ext2/makefile new file mode 100644 index 0000000..6925dba --- /dev/null +++ b/drivers/fs/ext2/makefile @@ -0,0 +1,26 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = ext2fs + +TARGET_CFLAGS = -I./include -DDBG + +TARGET_OBJECTS = \ + attr.o \ + blockdev.o \ + dir.o \ + file.o \ + inode.o \ + rw.o \ + quota.o \ + security.o \ + super.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/fs/ext2/quota.c b/drivers/fs/ext2/quota.c new file mode 100644 index 0000000..d7130c7 --- /dev/null +++ b/drivers/fs/ext2/quota.c @@ -0,0 +1,49 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/quota.c + * PURPOSE: Quota support + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +Ext2QueryQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + NTSTATUS Status; + + Status = STATUS_NOT_IMPLEMENTED; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +NTSTATUS STDCALL +Ext2SetQuota(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + NTSTATUS Status; + + Status = STATUS_NOT_IMPLEMENTED; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} diff --git a/drivers/fs/ext2/rw.c b/drivers/fs/ext2/rw.c new file mode 100644 index 0000000..a2c3b9a --- /dev/null +++ b/drivers/fs/ext2/rw.c @@ -0,0 +1,219 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/super.c + * PURPOSE: ext2 filesystem + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS Ext2ReadPage(PDEVICE_EXTENSION DeviceExt, + PEXT2_FCB Fcb, + PVOID Buffer, + ULONG Offset) +{ + ULONG block, i; + + for (i=0; i<4; i++) + { + block = Ext2BlockMap(DeviceExt, + Fcb->i.inode, + Offset + i); + Ext2ReadSectors(DeviceExt->StorageDevice, + block, + 1, + Buffer + (i*BLOCKSIZE)); + } + return(STATUS_SUCCESS); +} + +NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + LARGE_INTEGER OffsetL) +{ + PVOID BaseAddress; + BOOLEAN Uptodate = FALSE; + PCACHE_SEGMENT CacheSeg; + ULONG Offset = (ULONG)OffsetL.u.LowPart; + PEXT2_FCB Fcb; + ULONG block, i, Delta; + DPRINT("Ext2ReadFile(DeviceExt %x, FileObject %x, Buffer %x, Length %d, \n" + "OffsetL %d)\n",DeviceExt,FileObject,Buffer,Length,(ULONG)OffsetL); + + Fcb = (PEXT2_FCB)FileObject->FsContext; + + Ext2LoadInode(DeviceExt, + Fcb->inode, + &Fcb->i); + + if (Offset >= Fcb->i.inode->i_size) + { + DPRINT("Returning end of file\n"); + return(STATUS_END_OF_FILE); + } + if ((Offset + Length) > Fcb->i.inode->i_size) + { + Length = Fcb->i.inode->i_size - Offset; + } + + Ext2ReleaseInode(DeviceExt, + &Fcb->i); + + if ((Offset % PAGE_SIZE) != 0) + { + Delta = min(PAGE_SIZE - (Offset % PAGE_SIZE),Length); + CcRequestCachePage(Fcb->Bcb, + Offset, + &BaseAddress, + &Uptodate, + &CacheSeg); + if (Uptodate == FALSE) + { + Ext2ReadPage(DeviceExt, + Fcb, + BaseAddress, + Offset / BLOCKSIZE); + } + memcpy(Buffer, BaseAddress + (Offset % PAGE_SIZE), Delta); + CcReleaseCachePage(Fcb->Bcb, + CacheSeg, + TRUE); + Length = Length - Delta; + Offset = Offset + Delta; + Buffer = Buffer + Delta; + } + CHECKPOINT; + for (i=0; i<(Length/PAGE_SIZE); i++) + { + CcRequestCachePage(Fcb->Bcb, + Offset, + &BaseAddress, + &Uptodate, + &CacheSeg); + if (Uptodate == FALSE) + { + Ext2ReadPage(DeviceExt, + Fcb, + BaseAddress, + (Offset / BLOCKSIZE)); + } + memcpy(Buffer, BaseAddress, PAGE_SIZE); + CcReleaseCachePage(Fcb->Bcb, + CacheSeg, + TRUE); + Length = Length - PAGE_SIZE; + Offset = Offset + PAGE_SIZE; + Buffer = Buffer + PAGE_SIZE; + } + CHECKPOINT; + if ((Length % PAGE_SIZE) != 0) + { + CcRequestCachePage(Fcb->Bcb, + Offset, + &BaseAddress, + &Uptodate, + &CacheSeg); + if (Uptodate == FALSE) + { + Ext2ReadPage(DeviceExt, + Fcb, + BaseAddress, + (Offset / BLOCKSIZE)); + } + DPRINT("Copying %x to %x Length %d\n",BaseAddress,Buffer,Length); + memcpy(Buffer,BaseAddress,Length); + CcReleaseCachePage(Fcb->Bcb, + CacheSeg, + TRUE); + } + CHECKPOINT; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +Ext2Write(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("Ext2Write(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +Ext2FlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("Ext2FlushBuffers(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +Ext2Shutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("Ext2Shutdown(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +Ext2Cleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DbgPrint("Ext2Cleanup(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + + DbgPrint("Ext2Cleanup() finished\n"); + + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +Ext2Read(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + ULONG Length; + PVOID Buffer; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; + NTSTATUS Status; + + DPRINT("Ext2Read(DeviceObject %x, FileObject %x, Irp %x)\n", + DeviceObject, FileObject, Irp); + + Length = Stack->Parameters.Read.Length; + CHECKPOINT; + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + CHECKPOINT; + CHECKPOINT; + + Status = Ext2ReadFile(DeviceExt,FileObject,Buffer,Length, + Stack->Parameters.Read.ByteOffset); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + + return(Status); +} diff --git a/drivers/fs/ext2/security.c b/drivers/fs/ext2/security.c new file mode 100644 index 0000000..ab2297b --- /dev/null +++ b/drivers/fs/ext2/security.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/security.c + * PURPOSE: Security support + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +Ext2QuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("Ext2QuerySecurity(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +Ext2SetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("Ext2SetSecurity(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} diff --git a/drivers/fs/ext2/super.c b/drivers/fs/ext2/super.c new file mode 100644 index 0000000..0ddad31 --- /dev/null +++ b/drivers/fs/ext2/super.c @@ -0,0 +1,201 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ext2/super.c + * PURPOSE: ext2 filesystem + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ext2fs.h" + +/* GLOBALS *****************************************************************/ + +static PDRIVER_OBJECT DriverObject; + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +Ext2Close(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PDEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + PEXT2_FCB Fcb; + + DbgPrint("Ext2Close(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + DeviceExtension = DeviceObject->DeviceExtension; + + if (FileObject == DeviceExtension->FileObject) + { + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); + } + + Fcb = (PEXT2_FCB)FileObject->FsContext; + if (Fcb != NULL) + { + if (Fcb->Bcb != NULL) + { + CcRosReleaseFileCache(FileObject, Fcb->Bcb); + } + ExFreePool(Fcb); + FileObject->FsContext = NULL; + } + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +NTSTATUS Ext2Mount(PDEVICE_OBJECT DeviceToMount) +{ + PDEVICE_OBJECT DeviceObject; + PDEVICE_EXTENSION DeviceExt; + PVOID BlockBuffer; + struct ext2_super_block* superblock; + + DPRINT("Ext2Mount(DeviceToMount %x)\n",DeviceToMount); + + BlockBuffer = ExAllocatePool(NonPagedPool,BLOCKSIZE); + Ext2ReadSectors(DeviceToMount, + 1, + 1, + BlockBuffer); + superblock = BlockBuffer; + + if (superblock->s_magic != EXT2_SUPER_MAGIC) + { + ExFreePool(BlockBuffer); + return(STATUS_UNRECOGNIZED_VOLUME); + } + DPRINT("Volume recognized\n"); + DPRINT("s_inodes_count %d\n",superblock->s_inodes_count); + DPRINT("s_blocks_count %d\n",superblock->s_blocks_count); + + IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + DPRINT("DeviceObject %x\n",DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = (PVOID)DeviceObject->DeviceExtension; + DPRINT("DeviceExt %x\n",DeviceExt); + + DeviceExt->StorageDevice = DeviceToMount; + DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject; + DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; + DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; + DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + DPRINT("DeviceExt->StorageDevice %x\n", DeviceExt->StorageDevice); + DeviceExt->FileObject = IoCreateStreamFileObject(NULL, DeviceObject); + DeviceExt->superblock = superblock; + CcRosInitializeFileCache(DeviceExt->FileObject, + &DeviceExt->Bcb, + PAGE_SIZE * 3); + + DPRINT("Ext2Mount() = STATUS_SUCCESS\n"); + + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +Ext2FileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PVPB vpb = Stack->Parameters.Mount.Vpb; + PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject; + NTSTATUS Status; + + Status = Ext2Mount(DeviceToMount); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT _DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS ret; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Ext2Fsd"); + + DbgPrint("Ext2 FSD 0.0.1\n"); + + DriverObject = _DriverObject; + + ret = IoCreateDevice(DriverObject, + 0, + &DeviceName, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (ret!=STATUS_SUCCESS) + { + return(ret); + } + + DeviceObject->Flags=0; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close; + DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create; + DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read; + DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + Ext2FileSystemControl; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = + Ext2DirectoryControl; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + Ext2QueryInformation; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2SetInformation; + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2FlushBuffers; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2Shutdown; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2Cleanup; + DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = Ext2QuerySecurity; + DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = Ext2SetSecurity; + DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = Ext2QueryQuota; + DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = Ext2SetQuota; + + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + + return(STATUS_SUCCESS); +} + diff --git a/drivers/fs/fs_rec/.cvsignore b/drivers/fs/fs_rec/.cvsignore new file mode 100644 index 0000000..43fea5d --- /dev/null +++ b/drivers/fs/fs_rec/.cvsignore @@ -0,0 +1,6 @@ +base.tmp +junk.tmp +temp.exp +fs_rec.coff +fs_rec.sys.unstripped +*.d \ No newline at end of file diff --git a/drivers/fs/fs_rec/blockdev.c b/drivers/fs/fs_rec/blockdev.c new file mode 100644 index 0000000..264fba0 --- /dev/null +++ b/drivers/fs/fs_rec/blockdev.c @@ -0,0 +1,166 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/fs_rec/blockdev.c + * PURPOSE: Filesystem recognizer driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "fs_rec.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +FsRecReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN ULONG SectorSize, + IN OUT PUCHAR Buffer) +{ + PIO_STACK_LOCATION Stack; + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER Offset; + ULONG BlockSize; + PKEVENT Event; + PIRP Irp; + NTSTATUS Status; + + Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); + if (Event == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + KeInitializeEvent(Event, + NotificationEvent, + FALSE); + + Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize; + BlockSize = SectorCount * SectorSize; + + DPRINT("FsrecReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", + DeviceObject, DiskSector, Buffer); + DPRINT("Offset %I64x BlockSize %ld\n", + Offset.QuadPart, + BlockSize); + + DPRINT("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + Buffer, + BlockSize, + &Offset, + Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + ExFreePool(Event); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +FsRecDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, + IN ULONG ControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize) +{ + ULONG BufferSize = 0; + PKEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + if (OutputBufferSize != NULL) + { + BufferSize = *OutputBufferSize; + } + + Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); + if (Event == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + KeInitializeEvent(Event, NotificationEvent, FALSE); + + DPRINT("Building device I/O control request ...\n"); + Irp = IoBuildDeviceIoControlRequest(ControlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + BufferSize, + FALSE, + Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest() failed\n"); + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + if (OutputBufferSize) + { + *OutputBufferSize = BufferSize; + } + + ExFreePool(Event); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/fs_rec/cdfs.c b/drivers/fs/fs_rec/cdfs.c new file mode 100644 index 0000000..f65143d --- /dev/null +++ b/drivers/fs/fs_rec/cdfs.c @@ -0,0 +1,143 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/fs_rec/cdfs.c + * PURPOSE: Filesystem recognizer driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "fs_rec.h" + + +#define CDFS_PVD_SECTOR 16 + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +FsRecIsCdfsVolume(IN PDEVICE_OBJECT DeviceObject) +{ + DISK_GEOMETRY DiskGeometry; + PUCHAR Buffer; + NTSTATUS Status; + ULONG Size; + + Size = sizeof(DISK_GEOMETRY); + Status = FsRecDeviceIoControl(DeviceObject, + IOCTL_CDROM_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("FsRecDeviceIoControl() failed (Status %lx)\n", Status); + return(Status); + } + + DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); + Buffer = ExAllocatePool(NonPagedPool, + DiskGeometry.BytesPerSector); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = FsRecReadSectors(DeviceObject, + CDFS_PVD_SECTOR, + 1, + DiskGeometry.BytesPerSector, + Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT("FsRecReadSectors() failed (Status %lx)\n", Status); + return(Status); + } + + Buffer[6] = 0; + DPRINT("CD-identifier: [%.5s]\n", Buffer + 1); + + Status = (Buffer[0] == 1 && + Buffer[1] == 'C' && + Buffer[2] == 'D' && + Buffer[3] == '0' && + Buffer[4] == '0' && + Buffer[5] == '1') ? STATUS_SUCCESS : STATUS_UNRECOGNIZED_VOLUME; + + ExFreePool(Buffer); + + return(Status); +} + + +NTSTATUS +FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + UNICODE_STRING RegistryPath; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_MOUNT_VOLUME: + DPRINT("Cdfs: IRP_MN_MOUNT_VOLUME\n"); + Status = FsRecIsCdfsVolume(Stack->Parameters.MountVolume.DeviceObject); + if (NT_SUCCESS(Status)) + { + DPRINT("Identified CDFS volume\n"); + Status = STATUS_FS_DRIVER_REQUIRED; + } + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + DPRINT("Cdfs: IRP_MN_LOAD_FILE_SYSTEM\n"); + RtlInitUnicodeStringFromLiteral(&RegistryPath, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Cdfs"); + Status = ZwLoadDriver(&RegistryPath); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwLoadDriver failed (Status %x)\n", Status); + } + else + { + IoUnregisterFileSystem(DeviceObject); + } + break; + + default: + DPRINT("Cdfs: Unknown minor function %lx\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/fs_rec/fat.c b/drivers/fs/fs_rec/fat.c new file mode 100644 index 0000000..5d884c4 --- /dev/null +++ b/drivers/fs/fs_rec/fat.c @@ -0,0 +1,141 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/fs_rec/vfat.c + * PURPOSE: Filesystem recognizer driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "fs_rec.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +FsRecIsFatVolume(IN PDEVICE_OBJECT DeviceObject) +{ + DISK_GEOMETRY DiskGeometry; + PUCHAR Buffer; + ULONG Size; + NTSTATUS Status; + + Size = sizeof(DISK_GEOMETRY); + Status = FsRecDeviceIoControl(DeviceObject, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &Size); + DPRINT("FsRecDeviceIoControl() Status %lx\n", Status); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); + Buffer = ExAllocatePool(NonPagedPool, + DiskGeometry.BytesPerSector); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = FsRecReadSectors(DeviceObject, + 0, /* Partition boot sector */ + 1, + DiskGeometry.BytesPerSector, + Buffer); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if ((strncmp(&Buffer[0x36], "FAT12", 5) == 0) || + (strncmp(&Buffer[0x36], "FAT16", 5) == 0) || + (strncmp(&Buffer[0x52], "FAT32", 5) == 0)) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_UNRECOGNIZED_VOLUME; + } + + ExFreePool(Buffer); + + return(Status); +} + + +NTSTATUS +FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + UNICODE_STRING RegistryPath; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_MOUNT_VOLUME: + DPRINT("FAT: IRP_MN_MOUNT_VOLUME\n"); + Status = FsRecIsFatVolume(Stack->Parameters.MountVolume.DeviceObject); + if (NT_SUCCESS(Status)) + { + DPRINT("Identified FAT volume\n"); + Status = STATUS_FS_DRIVER_REQUIRED; + } + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + DPRINT("FAT: IRP_MN_LOAD_FILE_SYSTEM\n"); + RtlInitUnicodeStringFromLiteral(&RegistryPath, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Vfatfs"); + Status = ZwLoadDriver(&RegistryPath); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwLoadDriver failed (Status %x)\n", Status); + } + else + { + IoUnregisterFileSystem(DeviceObject); + } + break; + + default: + DPRINT("FAT: Unknown minor function %lx\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/fs_rec/fs_rec.c b/drivers/fs/fs_rec/fs_rec.c new file mode 100644 index 0000000..89943d1 --- /dev/null +++ b/drivers/fs/fs_rec/fs_rec.c @@ -0,0 +1,243 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/fs_rec/fs_rec.c + * PURPOSE: Filesystem recognizer driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "fs_rec.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +FsRecCreate(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status; + + + Status = STATUS_SUCCESS; + + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +FsRecClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +FsRecFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status; + + DeviceExt = DeviceObject->DeviceExtension; + switch (DeviceExt->FsType) + { + case FS_TYPE_VFAT: + Status = FsRecVfatFsControl(DeviceObject, Irp); + break; + + case FS_TYPE_CDFS: + Status = FsRecCdfsFsControl(DeviceObject, Irp); + break; + + case FS_TYPE_NTFS: + Status = FsRecNtfsFsControl(DeviceObject, Irp); + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + + +VOID STDCALL +FsRecUnload(IN PDRIVER_OBJECT DriverObject) +{ + PDEVICE_OBJECT NextDevice; + PDEVICE_OBJECT ThisDevice; + + /* Delete all remaining device objects */ + NextDevice = DriverObject->DeviceObject; + while (NextDevice != NULL) + { + ThisDevice = NextDevice; + NextDevice = NextDevice->NextDevice; + IoDeleteDevice(ThisDevice); + } +} + + +static NTSTATUS +FsRecRegisterFs(PDRIVER_OBJECT DriverObject, + PWSTR FsName, + PWSTR RecognizerName, + ULONG DeviceType, + ULONG FsType) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatus; + PDEVICE_EXTENSION DeviceExt; + UNICODE_STRING DeviceName; + UNICODE_STRING FileName; + PDEVICE_OBJECT DeviceObject; + HANDLE FileHandle; + NTSTATUS Status; + + RtlInitUnicodeString(&FileName, + FsName); + + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + OBJ_CASE_INSENSITIVE, + 0, + NULL); + + Status = ZwCreateFile(&FileHandle, + 0x100000, + &ObjectAttributes, + &IoStatus, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + OPEN_EXISTING, + 0, + NULL, + 0); + if (NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + return(STATUS_IMAGE_ALREADY_LOADED); + } + + /* Create recognizer device object */ + RtlInitUnicodeString(&DeviceName, + RecognizerName); + + Status = IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + DeviceType, + 0, + FALSE, + &DeviceObject); + + if (NT_SUCCESS(Status)) + { + DeviceExt = DeviceObject->DeviceExtension; + DeviceExt->FsType = FsType; + IoRegisterFileSystem(DeviceObject); + DPRINT("Created recognizer device '%wZ'\n", &DeviceName); + } + + return(Status); +} + + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + PCONFIGURATION_INFORMATION ConfigInfo; + ULONG DeviceCount; + NTSTATUS Status; + + DPRINT("FileSystem recognizer 0.0.1\n"); + + DeviceCount = 0; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = FsRecCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsRecClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FsRecClose; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsRecFsControl; + DriverObject->DriverUnload = FsRecUnload; + + ConfigInfo = IoGetConfigurationInformation(); + + if (ConfigInfo->CDRomCount > 0) + { + Status = FsRecRegisterFs(DriverObject, + L"\\Cdfs", + L"\\FileSystem\\CdfsRecognizer", + FILE_DEVICE_CD_ROM_FILE_SYSTEM, + FS_TYPE_CDFS); + if (NT_SUCCESS(Status)) + { + DeviceCount++; + } + } + + Status = FsRecRegisterFs(DriverObject, + L"\\Fat", + L"\\FileSystem\\FatRecognizer", + FILE_DEVICE_DISK_FILE_SYSTEM, + FS_TYPE_VFAT); + if (NT_SUCCESS(Status)) + { + DeviceCount++; + } + + Status = FsRecRegisterFs(DriverObject, + L"\\Ntfs", + L"\\FileSystem\\NtfsRecognizer", + FILE_DEVICE_DISK_FILE_SYSTEM, + FS_TYPE_NTFS); + if (NT_SUCCESS(Status)) + { + DeviceCount++; + } + + return((DeviceCount > 0) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); +} + +/* EOF */ diff --git a/drivers/fs/fs_rec/fs_rec.h b/drivers/fs/fs_rec/fs_rec.h new file mode 100644 index 0000000..f3c9a90 --- /dev/null +++ b/drivers/fs/fs_rec/fs_rec.h @@ -0,0 +1,81 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/fs_rec/fs_rec.h + * PURPOSE: Filesystem recognizer driver + * PROGRAMMER: Eric Kohl + */ + + +/* Filesystem types (add new filesystems here)*/ + +#define FS_TYPE_UNUSED 0 +#define FS_TYPE_VFAT 1 +#define FS_TYPE_NTFS 2 +#define FS_TYPE_CDFS 3 + + +typedef struct _DEVICE_EXTENSION +{ + ULONG FsType; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + + +/* blockdev.c */ + +NTSTATUS +FsRecReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN ULONG SectorSize, + IN OUT PUCHAR Buffer); + +NTSTATUS +FsRecDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, + IN ULONG ControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize); + + +/* cdfs.c */ + +NTSTATUS +FsRecCdfsFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +/* fat.c */ + +NTSTATUS +FsRecVfatFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +/* ntfs.c */ + +NTSTATUS +FsRecNtfsFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +/* EOF */ diff --git a/drivers/fs/fs_rec/fs_rec.rc b/drivers/fs/fs_rec/fs_rec.rc new file mode 100644 index 0000000..946e3f9 --- /dev/null +++ b/drivers/fs/fs_rec/fs_rec.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Filesystem recognizer driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "fs_rec\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "fs_rec.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/fs_rec/makefile b/drivers/fs/fs_rec/makefile new file mode 100644 index 0000000..2ab49dc --- /dev/null +++ b/drivers/fs/fs_rec/makefile @@ -0,0 +1,26 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = fs_rec + +TARGET_OBJECTS = \ + blockdev.o \ + fs_rec.o \ + cdfs.o \ + fat.o \ + ntfs.o + +DEP_OBJECTS = $(TARGET_OBJECTS) + +TARGET_CLEAN = $(DEP_FILES) *.o *.sys *.sym + +TARGET_CFLAGS = -g + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/depend.mk diff --git a/drivers/fs/fs_rec/ntfs.c b/drivers/fs/fs_rec/ntfs.c new file mode 100644 index 0000000..01b6190 --- /dev/null +++ b/drivers/fs/fs_rec/ntfs.c @@ -0,0 +1,142 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/fs_rec/ntfs.c + * PURPOSE: Filesystem recognizer driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "fs_rec.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +FsRecIsNtfsVolume(IN PDEVICE_OBJECT DeviceObject) +{ + DISK_GEOMETRY DiskGeometry; + PUCHAR Buffer; + ULONG Size; + NTSTATUS Status; + + Size = sizeof(DISK_GEOMETRY); + Status = FsRecDeviceIoControl(DeviceObject, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("FsRecDeviceIoControl() failed (Status %lx)\n", Status); + return(Status); + } + + DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); + Buffer = ExAllocatePool(NonPagedPool, + DiskGeometry.BytesPerSector); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = FsRecReadSectors(DeviceObject, + 0, /* Partition boot sector */ + 1, + DiskGeometry.BytesPerSector, + Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT("FsRecReadSectors() failed (Status %lx)\n", Status); + return(Status); + } + + DPRINT("NTFS-identifier: [%.8s]\n", &Buffer[3]); + if (strncmp(&Buffer[3], "NTFS ", 8) == 0) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_UNRECOGNIZED_VOLUME; + } + + ExFreePool(Buffer); + + return(Status); +} + + +NTSTATUS +FsRecNtfsFsControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + UNICODE_STRING RegistryPath; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_MOUNT_VOLUME: + DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n"); + + Status = FsRecIsNtfsVolume(Stack->Parameters.MountVolume.DeviceObject); + if (NT_SUCCESS(Status)) + { + DPRINT("Identified NTFS volume\n"); + Status = STATUS_FS_DRIVER_REQUIRED; + } + break; + + case IRP_MN_LOAD_FILE_SYSTEM: + DPRINT("NTFS: IRP_MN_LOAD_FILE_SYSTEM\n"); + RtlInitUnicodeString(&RegistryPath, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ntfs"); + Status = ZwLoadDriver(&RegistryPath); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwLoadDriver failed (Status %x)\n", Status); + } + else + { + IoUnregisterFileSystem(DeviceObject); + } + break; + + default: + DPRINT("NTFS: Unknown minor function %lx\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/minix/.cvsignore b/drivers/fs/minix/.cvsignore new file mode 100644 index 0000000..ea7ede1 --- /dev/null +++ b/drivers/fs/minix/.cvsignore @@ -0,0 +1,2 @@ +minix.coff +minixfs.sys.unstripped \ No newline at end of file diff --git a/drivers/fs/minix/Makefile b/drivers/fs/minix/Makefile new file mode 100644 index 0000000..8612b86 --- /dev/null +++ b/drivers/fs/minix/Makefile @@ -0,0 +1,22 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = minixfs + +TARGET_OBJECTS = \ + bitops.o + block.o \ + blockdev.o \ + cache.o \ + dir.o \ + inode.o \ + minixfs.o + mount.o \ + rw.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/fs/minix/bitops.c b/drivers/fs/minix/bitops.c new file mode 100644 index 0000000..7f2b335 --- /dev/null +++ b/drivers/fs/minix/bitops.c @@ -0,0 +1,203 @@ +/* + * ReactOS kernel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Copyright 1992, Linus Torvalds. + */ +/* + * These have to be done with inline assembly: that way the bit-setting + * is guaranteed to be atomic. All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +#ifdef __SMP__ +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +/* + * Function prototypes to keep gcc -Wall happy + */ +extern void set_bit(int nr, volatile void * addr); +extern void clear_bit(int nr, volatile void * addr); +extern void change_bit(int nr, volatile void * addr); +extern int test_and_set_bit(int nr, volatile void * addr); +extern int test_and_clear_bit(int nr, volatile void * addr); +extern int test_and_change_bit(int nr, volatile void * addr); +extern int __constant_test_bit(int nr, const volatile void * addr); +extern int __test_bit(int nr, volatile void * addr); +extern int find_first_zero_bit(void * addr, unsigned size); +extern int find_next_zero_bit (void * addr, int size, int offset); +extern unsigned long ffz(unsigned long word); + +/* + * Some hacks to defeat gcc over-optimizations.. + */ +struct __dummy { unsigned long a[100]; }; +#define ADDR (*(volatile struct __dummy *) addr) +#define CONST_ADDR (*(volatile const struct __dummy *) addr) + +void set_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +void clear_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btrl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +void change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +int test_and_set_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btsl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +int test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +int test_and_change_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btcl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +/* + * This routine doesn't need to be atomic. + */ +int __constant_test_bit(int nr, const volatile void * addr) +{ + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +int test_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit) + :"m" (ADDR),"Ir" (nr)); + return oldbit; +} + +#if 0 +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + __constant_test_bit((nr),(addr)) : \ + __test_bit((nr),(addr))) +#endif + +/* + * Find-bit routines.. + */ +int find_first_zero_bit(void * addr, unsigned size) +{ + int d0, d1, d2; + int res; + + if (!size) + return 0; + __asm__("cld\n\t" + "movl $-1,%%eax\n\t" + "xorl %%edx,%%edx\n\t" + "repe; scasl\n\t" + "je 1f\n\t" + "xorl -4(%%edi),%%eax\n\t" + "subl $4,%%edi\n\t" + "bsfl %%eax,%%edx\n" + "1:\tsubl %%ebx,%%edi\n\t" + "shll $3,%%edi\n\t" + "addl %%edi,%%edx" + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) + :"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); + return res; +} + +int find_next_zero_bit (void * addr, int size, int offset) +{ + unsigned long * p = ((unsigned long *) addr) + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* + * Look for zero in first byte + */ + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" + : "=r" (set) + : "r" (~(*p >> bit))); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No zero yet, search remaining full bytes for a zero + */ + res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); + return (offset + set + res); +} + +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +unsigned long ffz(unsigned long word) +{ + __asm__("bsfl %1,%0" + :"=r" (word) + :"r" (~word)); + return word; +} diff --git a/drivers/fs/minix/bitops.h b/drivers/fs/minix/bitops.h new file mode 100644 index 0000000..7c0123b --- /dev/null +++ b/drivers/fs/minix/bitops.h @@ -0,0 +1,30 @@ +#ifndef _I386_BITOPS_H +#define _I386_BITOPS_H + +/* + * Copyright 1992, Linus Torvalds. + */ + +/* + * These have to be done with inline assembly: that way the bit-setting + * is guaranteed to be atomic. All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +/* + * Function prototypes to keep gcc -Wall happy + */ +extern void set_bit(int nr, volatile void * addr); +extern void clear_bit(int nr, volatile void * addr); +extern void change_bit(int nr, volatile void * addr); +extern int test_and_set_bit(int nr, volatile void * addr); +extern int test_and_clear_bit(int nr, volatile void * addr); +extern int test_and_change_bit(int nr, volatile void * addr); +extern int test_bit(int nr, volatile void * addr); +extern int find_first_zero_bit(void * addr, unsigned size); +extern int find_next_zero_bit (void * addr, int size, int offset); +extern unsigned long ffz(unsigned long word); + +#endif /* _I386_BITOPS_H */ diff --git a/drivers/fs/minix/block.c b/drivers/fs/minix/block.c new file mode 100644 index 0000000..07b9dfb --- /dev/null +++ b/drivers/fs/minix/block.c @@ -0,0 +1,109 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/minix.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "minix.h" + +/* FUNCTIONS ****************************************************************/ + +static unsigned int MinixGetBlock(PDEVICE_OBJECT DeviceObject, + PMINIX_DEVICE_EXTENSION DeviceExt, + struct minix_inode* inode, + ULONG FileOffset) +{ + int block; + PVOID BaseAddress; + ULONG blk; + + blk = FileOffset / BLOCKSIZE; + + DPRINT("MinixGetBlock(inode %x, blk %d)\n",inode,blk); + + /* + * The first few blocks are available in the inode + */ + if (blk < 7) + { + block = inode->i_zone[blk]; + return(block); + } + blk = blk - 7; + + /* + * Retrieve a single-indirect block + */ + if (blk < 512) + { + block = inode->i_zone[7]; + + BaseAddress = ExAllocatePool(NonPagedPool, 512); + + MinixReadSector(DeviceObject, + block, + BaseAddress); + + block = ((PUSHORT)(BaseAddress))[blk]; + + ExFreePool(BaseAddress); + + return(block); + } + + /* + * Get a double indirect block + */ + blk = blk - 512; + block = inode->i_zone[8]; + + BaseAddress = ExAllocatePool(NonPagedPool, 512); + + MinixReadSector(DeviceObject, + block, + BaseAddress); + + block = ((PUSHORT)BaseAddress)[(blk>>9)&511]; + + ExFreePool(BaseAddress); + + + BaseAddress = ExAllocatePool(NonPagedPool, 512); + + MinixReadSector(DeviceObject, + block, + BaseAddress); + + block = ((PUSHORT)BaseAddress)[blk&512]; + + ExFreePool(BaseAddress); + + return(block); +} + +NTSTATUS MinixReadBlock(PDEVICE_OBJECT DeviceObject, + PMINIX_DEVICE_EXTENSION DeviceExt, + struct minix_inode* inode, + ULONG FileOffset, + PULONG DiskOffset) +{ + unsigned int block; + + DPRINT("MinixReadBlock()\n"); + + block = MinixGetBlock(DeviceObject, DeviceExt,inode, FileOffset); + + (*DiskOffset) = block * BLOCKSIZE; + + return(STATUS_SUCCESS); +} diff --git a/drivers/fs/minix/blockdev.c b/drivers/fs/minix/blockdev.c new file mode 100644 index 0000000..e9f5c36 --- /dev/null +++ b/drivers/fs/minix/blockdev.c @@ -0,0 +1,154 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/minix.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "minix.h" + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN MinixReadPage(PDEVICE_OBJECT DeviceObject, + ULONG Offset, + PVOID Buffer) +{ + ULONG i; + BOOLEAN Result; + + for (i=0; i<4; i++) + { + Result = MinixReadSector(DeviceObject, + (Offset + (i * PAGE_SIZE)) / BLOCKSIZE, + (Buffer + (i * PAGE_SIZE))); + if (!Result) + { + return(Result); + } + } + return(TRUE); +} + +BOOLEAN MinixReadSector(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN PVOID Buffer) +{ + LARGE_INTEGER sectorNumber; + PIRP irp; + IO_STATUS_BLOCK ioStatus; + KEVENT event; + NTSTATUS status; + ULONG sectorSize; + PULONG mbr; + + DPRINT("MinixReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n", + pDeviceObject,DiskSector,Buffer); + + sectorNumber.u.HighPart = 0; + sectorNumber.u.LowPart = DiskSector * BLOCKSIZE; + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + sectorSize = BLOCKSIZE; + + mbr = ExAllocatePool(NonPagedPool, sectorSize); + + if (!mbr) { + return FALSE; + } + + + irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + pDeviceObject, + mbr, + sectorSize, + §orNumber, + &event, + &ioStatus ); + + if (!irp) { + ExFreePool(mbr); + return FALSE; + } + + status = IoCallDriver(pDeviceObject, + irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, + Suspended, + KernelMode, + FALSE, + NULL); + status = ioStatus.Status; + } + + if (!NT_SUCCESS(status)) { + ExFreePool(mbr); + return FALSE; + } + + RtlCopyMemory(Buffer,mbr,sectorSize); + + ExFreePool(mbr); + return TRUE; +} + +BOOLEAN MinixWriteSector(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN PVOID Buffer) +{ + LARGE_INTEGER sectorNumber; + PIRP irp; + IO_STATUS_BLOCK ioStatus; + KEVENT event; + NTSTATUS status; + ULONG sectorSize; + + DPRINT("MinixWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n", + pDeviceObject,DiskSector,Buffer); + + sectorNumber.u.HighPart = 0; + sectorNumber.u.LowPart = DiskSector * BLOCKSIZE; + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + sectorSize = BLOCKSIZE; + + irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, + pDeviceObject, + Buffer, + sectorSize, + §orNumber, + &event, + &ioStatus ); + + + status = IoCallDriver(pDeviceObject, + irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, + Suspended, + KernelMode, + FALSE, + NULL); + status = ioStatus.Status; + } + + if (!NT_SUCCESS(status)) { + return FALSE; + } + + return TRUE; +} diff --git a/drivers/fs/minix/cache.c b/drivers/fs/minix/cache.c new file mode 100644 index 0000000..8ee228d --- /dev/null +++ b/drivers/fs/minix/cache.c @@ -0,0 +1,45 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/cache.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +//#define NDEBUG +#include + +#include "minix.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS MinixRequestCacheBlock(PDEVICE_OBJECT DeviceObject, + PBCB Bcb, + ULONG FileOffset, + PVOID* BaseAddress, + PCACHE_SEGMENT* CacheSeg) +{ + BOOLEAN UptoDate; + + CcRosRequestCacheSegment(Bcb, + FileOffset, + BaseAddress, + &UptoDate, + CacheSeg); + if (!UptoDate) + { + MinixReadPage(DeviceObject, + PAGE_ROUND_DOWN(FileOffset), + BaseAddress); + } + BaseAddress = BaseAddress + (FileOffset % PAGE_SIZE); + + return(STATUS_SUCCESS); +} + diff --git a/drivers/fs/minix/dir.c b/drivers/fs/minix/dir.c new file mode 100644 index 0000000..5ff146d --- /dev/null +++ b/drivers/fs/minix/dir.c @@ -0,0 +1,234 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/minix.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +//#define NDEBUG +#include + +#include "minix.h" + +/* FUNCTIONS ****************************************************************/ + +BOOLEAN MinixCompareUnicodeStringToAnsi(PCH AnsiStr, + PWCHAR UnicodeStr, + ULONG MaxLen) +{ + unsigned int i = 0; + + while (ii_size/MINIX_DIR_ENTRY_SIZE);i++) + { + CHECKPOINT; + offset = i*MINIX_DIR_ENTRY_SIZE; + if ((offset%BLOCKSIZE)==0) + { + MinixReadBlock(DeviceObject, + DeviceExt, + dir, + offset/BLOCKSIZE, + &DiskOffset); + MinixReadSector(DeviceObject, + DiskOffset, + Block); + } + current_entry = (struct minix_dir_entry *) + (Block+offset%BLOCKSIZE); + DPRINT("Inode %x Name %.30s\n",current_entry->inode, + current_entry->name); + if (MinixCompareUnicodeStringToAnsi(current_entry->name, + Name,30)) + { + inode = current_entry->inode; + ExFreePool(Block); + DPRINT("MinixDirLookup() = %d\n",inode); + return(inode); + } + } + CHECKPOINT; + ExFreePool(Block); + DPRINT("MinixDirLookup() = %d\n",0); + return(0); +} + +NTSTATUS MinixOpen(PDEVICE_OBJECT DeviceObject, + MINIX_DEVICE_EXTENSION* DeviceExt, + PFILE_OBJECT FileObject, + PMINIX_FSCONTEXT result, + PULONG Information) +{ + PWSTR current; + PWSTR next; + PWSTR string; + struct minix_inode current_dir; + unsigned int current_ino; + + string = ExAllocatePool(NonPagedPool, + 2*(wcslen(FileObject->FileName.Buffer)+1)); + wcscpy(string, FileObject->FileName.Buffer); + + DbgPrint("MinixOpen(DeviceObject %x, DeviceName %S, result %x)\n", + DeviceObject,string,result); + + + next = &string[0]; + current = next+1; + + current_ino = MINIX_ROOT_INO; + + while (next != NULL && current_ino != 0) + { + MinixReadInode(DeviceObject,DeviceExt,current_ino,¤t_dir); + + DPRINT("current %S next %x\n",current,next); + + *next = '\\'; + current = next+1; + next = wcschr(next+1,'\\'); + if (next!=NULL) + { + *next=0; + } + + current_ino = MinixDirLookup(DeviceExt, + DeviceObject, + ¤t_dir, + current); + } + if (next == NULL && current_ino != 0) + { + MinixReadInode(DeviceObject,DeviceExt,current_ino,¤t_dir); + } + else + { + (*Information) = FILE_DOES_NOT_EXIST; + return(STATUS_UNSUCCESSFUL); + } + + result = ExAllocatePool(NonPagedPool, sizeof(MINIX_FSCONTEXT)); + memcpy(&result->inode,¤t_dir,sizeof(struct minix_inode)); + + DPRINT("MinxOpen() = STATUS_SUCCESS\n",0); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +MinixClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + + DPRINT("MinixClose(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + ExFreePool(FileObject->FsContext); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +MinixDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); +// PFILE_OBJECT FileObject = Stack->FileObject; + + if (Stack->MinorFunction != IRP_MN_QUERY_DIRECTORY) + { + return(STATUS_NOT_IMPLEMENTED); + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +MinixCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + NTSTATUS Status; + PMINIX_FSCONTEXT result; + MINIX_DEVICE_EXTENSION* DeviceExt; + + DPRINT("MinixCreate(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + DPRINT("Opening file %x %S\n",FileObject->FileName.Buffer, + FileObject->FileName.Buffer); + DPRINT("FileObject->FileName.Buffer %x\n", + FileObject->FileName.Buffer); + + DeviceExt = (MINIX_DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + result = ExAllocatePool(NonPagedPool,sizeof(struct minix_inode)); + DPRINT("result %x\n",result); + Status = MinixOpen(DeviceExt->AttachedDevice, + DeviceExt, + FileObject, + result, + &Irp->IoStatus.Information); + + if (NT_SUCCESS(Status)) + { + FileObject->FsContext = result; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + DPRINT("Finished MinixCreate()\n"); + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + diff --git a/drivers/fs/minix/inode.c b/drivers/fs/minix/inode.c new file mode 100644 index 0000000..6f36a49 --- /dev/null +++ b/drivers/fs/minix/inode.c @@ -0,0 +1,136 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/minix.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include "bitops.h" +#include + +#define NDEBUG +#include + +#include "minix.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS MinixDeleteInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt, + ULONG ino) +{ + PULONG Buffer; + ULONG off; + + Buffer = ExAllocatePool(NonPagedPool,BLOCKSIZE); + MinixReadSector(Volume, (ino / 8192)+2, (PVOID)Buffer); + off = ino % 8192; + clear_bit(off%32,&Buffer[off/32]); + MinixWriteSector(Volume, (ino / 8192)+2, (PVOID)Buffer); + return(STATUS_SUCCESS); +} + +static ULONG MinixAllocateInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt) +{ + ULONG i; + PULONG Buffer; + ULONG ino; + + Buffer = ExAllocatePool(NonPagedPool,BLOCKSIZE); + for (i=0; isb->s_imap_blocks; i++) + { + MinixReadSector(Volume,i + 2,Buffer); + ino = find_first_zero_bit(Buffer,8192); + if (ino < 8192) + { + set_bit(ino%32,&Buffer[32]); + MinixWriteSector(Volume,i + 2,Buffer); + ExFreePool(Buffer); + return(ino + (i*8192)); + } + } + ExFreePool(Buffer); + return(0); +} + +ULONG MinixNewInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt, + struct minix_inode* new_inode) +{ + ULONG ino; + + ino = MinixAllocateInode(Volume,DeviceExt); + if (ino == 0) + { + return(0); + } + MinixWriteInode(Volume,DeviceExt,ino,new_inode); + return(ino); +} + +NTSTATUS MinixWriteInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt, + ULONG ino, + struct minix_inode* result) +{ + int block; + char* buffer; + struct minix_inode* inodes; + + DPRINT("MinixWriteInode(ino %x, result %x)\n",ino,result); + + buffer = ExAllocatePool(NonPagedPool,1024); + inodes = (struct minix_inode *)buffer; + + block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks + + ((ino-1) / MINIX_INODES_PER_BLOCK); + MinixReadSector(Volume,block,buffer); + memcpy(&inodes[(ino-1)%MINIX_INODES_PER_BLOCK],result, + sizeof(struct minix_inode)); + MinixWriteSector(Volume,block,buffer); + + ExFreePool(buffer); + return(STATUS_SUCCESS); +} + +NTSTATUS MinixReadInode(PDEVICE_OBJECT DeviceObject, + MINIX_DEVICE_EXTENSION* DeviceExt, + ULONG ino, + struct minix_inode* result) +{ + int block; + struct minix_inode* inodes; + PVOID BaseAddress; + + DPRINT("MinixReadInode(ino %x, result %x)\n",ino,result); + + block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks + + ((ino-1) / MINIX_INODES_PER_BLOCK); + DPRINT("Reading block %x offset %x\n",block,block*BLOCKSIZE); + DPRINT("Index %x\n",(ino-1)%MINIX_INODES_PER_BLOCK); + + BaseAddress = ExAllocatePool(NonPagedPool, PAGE_SIZE); + + MinixReadPage(DeviceObject, + block, + BaseAddress); + + inodes = (struct minix_inode *)(BaseAddress + ((block % 4) * 512)); + + memcpy(result, + &inodes[(ino-1)%MINIX_INODES_PER_BLOCK], + sizeof(struct minix_inode)); + DPRINT("result->i_uid %x\n",result->i_uid); + DPRINT("result->i_size %x\n",result->i_size); + + ExFreePool(BaseAddress); + + return(STATUS_SUCCESS); +} diff --git a/drivers/fs/minix/minix.h b/drivers/fs/minix/minix.h new file mode 100644 index 0000000..7d93320 --- /dev/null +++ b/drivers/fs/minix/minix.h @@ -0,0 +1,133 @@ +#include +#include + +#define MINIX_ROOT_INO 1 + +/* Not the same as the bogus LINK_MAX in . Oh well. */ +#define MINIX_LINK_MAX 250 + +#define MINIX_I_MAP_SLOTS 8 +#define MINIX_Z_MAP_SLOTS 64 +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_VALID_FS 0x0001 /* Clean fs. */ +#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ + +#define MINIX_INODES_PER_BLOCK ((BLOCKSIZE)/(sizeof (struct minix_inode))) +#define MINIX2_INODES_PER_BLOCK ((BLOCKSIZE)/(sizeof (struct minix2_inode))) + +#define MINIX_V1 0x0001 /* original minix fs */ +#define MINIX_V2 0x0002 /* minix V2 fs */ + + +/* + * This is the original minix inode layout on disk. + * Note the 8-bit gid and atime and ctime. + */ +struct minix_inode { + unsigned short int i_mode; + unsigned short int i_uid; + unsigned long i_size; + unsigned long i_time; + unsigned char i_gid; + unsigned char i_nlinks; + unsigned short int i_zone[9]; +}; + +/* + * The new minix inode has all the time entries, as well as + * long block numbers and a third indirect block (7+1+1+1 + * instead of 7+1+1). Also, some previously 8-bit values are + * now 16-bit. The inode is now 64 bytes instead of 32. + */ +struct minix2_inode { + unsigned short int i_mode; + unsigned short int i_nlinks; + unsigned short int i_uid; + unsigned short int i_gid; + unsigned long i_size; + unsigned long i_atime; + unsigned long i_mtime; + unsigned long i_ctime; + unsigned long i_zone[10]; +}; + +/* + * minix super-block data on disk + */ +struct minix_super_block { + unsigned short int s_ninodes; + unsigned short int s_nzones; + unsigned short int s_imap_blocks; + unsigned short int s_zmap_blocks; + unsigned short int s_firstdatazone; + unsigned short int s_log_zone_size; + unsigned long s_max_size; + unsigned short int s_magic; + unsigned short int s_state; + unsigned long s_zones; +}; + +struct minix_dir_entry { + unsigned short int inode; + char name[0]; +}; +#define MINIX_DIR_ENTRY_SIZE (sizeof(struct minix_dir_entry)+30) + +BOOLEAN MinixReadSector(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN PVOID Buffer); +BOOLEAN MinixWriteSector(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN PVOID Buffer); + +#define BLOCKSIZE (1024) + +//extern PDRIVER_OBJECT DriverObject; + +typedef struct +{ + PDEVICE_OBJECT AttachedDevice; + struct minix_inode root_inode; + char superblock_buf[BLOCKSIZE]; + struct minix_super_block* sb; + PFILE_OBJECT FileObject; +} MINIX_DEVICE_EXTENSION, *PMINIX_DEVICE_EXTENSION; + +typedef struct +{ + struct minix_inode inode; +} MINIX_FSCONTEXT, *PMINIX_FSCONTEXT; + +NTSTATUS STDCALL MinixCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MinixClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MinixWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MinixRead(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MinixDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +ULONG MinixNewInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt, + struct minix_inode* new_inode); +NTSTATUS MinixWriteInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt, + ULONG ino, + struct minix_inode* result); +NTSTATUS MinixReadInode(PDEVICE_OBJECT DeviceObject, + MINIX_DEVICE_EXTENSION* DeviceExt, + ULONG ino, + struct minix_inode* result); +NTSTATUS MinixDeleteInode(PDEVICE_OBJECT Volume, + MINIX_DEVICE_EXTENSION* DeviceExt, + ULONG ino); + +NTSTATUS MinixReadBlock(PDEVICE_OBJECT DeviceObject, + PMINIX_DEVICE_EXTENSION DeviceExt, + struct minix_inode* inode, + ULONG FileOffset, + PULONG DiskOffset); + +BOOLEAN MinixReadPage(PDEVICE_OBJECT DeviceObject, + ULONG Offset, + PVOID Buffer); diff --git a/drivers/fs/minix/minix.rc b/drivers/fs/minix/minix.rc new file mode 100644 index 0000000..3708159 --- /dev/null +++ b/drivers/fs/minix/minix.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Minix IFS Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "minixfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "minixfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/minix/minix_fs.h b/drivers/fs/minix/minix_fs.h new file mode 100644 index 0000000..8cfdb90 --- /dev/null +++ b/drivers/fs/minix/minix_fs.h @@ -0,0 +1,80 @@ +#define MINIX_ROOT_INO 1 + +/* Not the same as the bogus LINK_MAX in . Oh well. */ +#define MINIX_LINK_MAX 250 + +#define MINIX_I_MAP_SLOTS 8 +#define MINIX_Z_MAP_SLOTS 64 +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_VALID_FS 0x0001 /* Clean fs. */ +#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ + +#define MINIX_INODES_PER_BLOCK ((BLOCKSIZE)/(sizeof (struct minix_inode))) +#define MINIX2_INODES_PER_BLOCK ((BLOCKSIZE)/(sizeof (struct minix2_inode))) + +#define MINIX_V1 0x0001 /* original minix fs */ +#define MINIX_V2 0x0002 /* minix V2 fs */ + + +/* + * This is the original minix inode layout on disk. + * Note the 8-bit gid and atime and ctime. + */ +struct minix_inode { + unsigned short int i_mode; + unsigned short int i_uid; + unsigned long i_size; + unsigned long i_time; + unsigned char i_gid; + unsigned char i_nlinks; + unsigned short int i_zone[9]; +}; + +/* + * The new minix inode has all the time entries, as well as + * long block numbers and a third indirect block (7+1+1+1 + * instead of 7+1+1). Also, some previously 8-bit values are + * now 16-bit. The inode is now 64 bytes instead of 32. + */ +struct minix2_inode { + unsigned short int i_mode; + unsigned short int i_nlinks; + unsigned short int i_uid; + unsigned short int i_gid; + unsigned long i_size; + unsigned long i_atime; + unsigned long i_mtime; + unsigned long i_ctime; + unsigned long i_zone[10]; +}; + +/* + * minix super-block data on disk + */ +struct minix_super_block { + unsigned short int s_ninodes; + unsigned short int s_nzones; + unsigned short int s_imap_blocks; + unsigned short int s_zmap_blocks; + unsigned short int s_firstdatazone; + unsigned short int s_log_zone_size; + unsigned long s_max_size; + unsigned short int s_magic; + unsigned short int s_state; + unsigned long s_zones; +}; + +struct minix_dir_entry { + unsigned short int inode; + char name[0]; +}; +#define MINIX_DIR_ENTRY_SIZE (sizeof(struct minix_dir_entry)+30) + +BOOLEAN MinixReadSector(IN PDEVICE_OBJECT pDeviceObject, + IN ULONG DiskSector, + IN UCHAR* Buffer); + +#define BLOCKSIZE (1024) diff --git a/drivers/fs/minix/mount.c b/drivers/fs/minix/mount.c new file mode 100644 index 0000000..e78bbf3 --- /dev/null +++ b/drivers/fs/minix/mount.c @@ -0,0 +1,160 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/minix.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +//#define NDEBUG +#include + +#include "minix.h" + +/* GLOBALS *******************************************************************/ + +static PDRIVER_OBJECT DriverObject; + +/* FUNCTIONS ****************************************************************/ + +VOID MinixMount(PDEVICE_OBJECT DeviceToMount) +{ + PDEVICE_OBJECT DeviceObject; + MINIX_DEVICE_EXTENSION* DeviceExt; + + IoCreateDevice(DriverObject, + sizeof(MINIX_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = DeviceObject->DeviceExtension; + + MinixReadSector(DeviceToMount,1,DeviceExt->superblock_buf); + DeviceExt->sb = (struct minix_super_block *)(DeviceExt->superblock_buf); + + DeviceExt->StorageDevice = DeviceToMount; + DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject; + DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; + DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; + DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + DeviceExt->FileObject = IoCreateStreamFileObject(NULL, DeviceObject); +} + +NTSTATUS STDCALL +MinixFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); +// PVPB vpb = Stack->Parameters.Mount.Vpb; + PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject; + NTSTATUS Status; + char* superblock_buf; + struct minix_super_block* sb; + + DbgPrint("MinixFileSystemControl(DeviceObject %x, Irp %x)\n",DeviceObject, + Irp); + DPRINT("DeviceToMount %x\n",DeviceToMount); + + superblock_buf = ExAllocatePool(NonPagedPool,BLOCKSIZE); + + DPRINT("MinixReadSector %x\n",MinixReadSector); + MinixReadSector(DeviceToMount,1,superblock_buf); + sb = (struct minix_super_block *)superblock_buf; + DPRINT("Magic %x\n",sb->s_magic); + DPRINT("Imap blocks %x\n",sb->s_imap_blocks); + DPRINT("Zmap blocks %x\n",sb->s_zmap_blocks); + if (sb->s_magic==MINIX_SUPER_MAGIC2) + { + DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__); + MinixMount(DeviceToMount); + Status = STATUS_SUCCESS; + } + else + { + DPRINT("%s() = STATUS_UNRECOGNIZED_VOLUME\n",__FUNCTION__); + Status = STATUS_UNRECOGNIZED_VOLUME; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT _DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS ret; + UNICODE_STRING DeviceName; + + DbgPrint("Minix FSD 0.0.1\n"); + + DriverObject = _DriverObject; + + RtlInitUnicodeString(&DeviceName, + L"\\Device\\Minix"); + ret = IoCreateDevice(DriverObject, + 0, + &DeviceName, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(ret)) + { + return(ret); + } + + DeviceObject->Flags = 0; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = MinixClose; + DriverObject->MajorFunction[IRP_MJ_CREATE] = MinixCreate; + DriverObject->MajorFunction[IRP_MJ_READ] = MinixRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = MinixWrite; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + MinixFileSystemControl; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = + MinixDirectoryControl; + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + + return(STATUS_SUCCESS); +} + diff --git a/drivers/fs/minix/rw.c b/drivers/fs/minix/rw.c new file mode 100644 index 0000000..61f925c --- /dev/null +++ b/drivers/fs/minix/rw.c @@ -0,0 +1,162 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/minix/rw.c + * PURPOSE: Minix FSD + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +#include "minix.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +MinixWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT("MinixWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +static NTSTATUS MinixReadFilePage(PDEVICE_OBJECT DeviceObject, + PMINIX_DEVICE_EXTENSION DeviceExt, + PMINIX_FSCONTEXT FsContext, + ULONG Offset, + PVOID* Buffer) +{ + NTSTATUS Status; + ULONG i; + ULONG DiskOffset; + + *Buffer = ExAllocatePool(NonPagedPool, 4096); + + for (i=0; i<4; i++) + { + Status = MinixReadBlock(DeviceObject, + DeviceExt, + &FsContext->inode, + Offset + (i * BLOCKSIZE), + &DiskOffset); + MinixReadSector(DeviceObject, + DiskOffset / BLOCKSIZE, + (*Buffer) + (i * BLOCKSIZE)); + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +MinixRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + ULONG Length; + PVOID Buffer; + ULONG Offset; + ULONG CurrentOffset; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + MINIX_DEVICE_EXTENSION* DeviceExt = DeviceObject->DeviceExtension; + PMINIX_FSCONTEXT FsContext = (PMINIX_FSCONTEXT)FileObject->FsContext; + unsigned int i; + PVOID DiskBuffer; + + DPRINT("MinixRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + Length = Stack->Parameters.Read.Length; + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Offset = Stack->Parameters.Read.ByteOffset.u.LowPart; + + DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset); + + CurrentOffset=Offset; + + DPRINT("inode->i_size %d\n",inode->i_size); + + if (Offset > FsContext->inode.i_size) + { + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return(STATUS_UNSUCCESSFUL); + } + if ((Offset+Length) > FsContext->inode.i_size) + { + Length = FsContext->inode.i_size - Offset; + } + + if ((Offset%PAGE_SIZE)!=0) + { + CurrentOffset = Offset - (Offset%PAGE_SIZE); + + MinixReadFilePage(DeviceObject, + DeviceExt, + FsContext, + CurrentOffset, + &DiskBuffer); + + memcpy(Buffer, + DiskBuffer+(Offset%PAGE_SIZE), + min(PAGE_SIZE - (Offset%PAGE_SIZE),Length)); + + ExFreePool(DiskBuffer); + + DPRINT("(BLOCKSIZE - (Offset%BLOCKSIZE)) %d\n", + (BLOCKSIZE - (Offset%BLOCKSIZE))); + DPRINT("Length %d\n",Length); + CurrentOffset = CurrentOffset + PAGE_SIZE; + Buffer = Buffer + PAGE_SIZE - (Offset%PAGE_SIZE); + Length = Length - min(PAGE_SIZE - (Offset%PAGE_SIZE),Length); + DPRINT("CurrentOffset %d Buffer %x Length %d\n",CurrentOffset,Buffer, + Length); + } + for (i=0;i<(Length/PAGE_SIZE);i++) + { + CHECKPOINT; + + DPRINT("Length %d\n",Length); + + MinixReadFilePage(DeviceObject, + DeviceExt, + FsContext, + CurrentOffset, + &DiskBuffer); + memcpy(Buffer, DiskBuffer, PAGE_SIZE); + + ExFreePool(DiskBuffer); + + CurrentOffset = CurrentOffset + PAGE_SIZE; + Buffer = Buffer + PAGE_SIZE; + } + if ((Length%PAGE_SIZE) > 0) + { + CHECKPOINT; + + DPRINT("Length %x Buffer %x\n",(Length%PAGE_SIZE),Buffer); + + MinixReadFilePage(DeviceObject, + DeviceExt, + FsContext, + CurrentOffset, + &DiskBuffer); + + memcpy(Buffer, DiskBuffer, (Length%PAGE_SIZE)); + + ExFreePool(DiskBuffer); + + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Length; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return(STATUS_SUCCESS); +} diff --git a/drivers/fs/ms/.cvsignore b/drivers/fs/ms/.cvsignore new file mode 100644 index 0000000..4742e3b --- /dev/null +++ b/drivers/fs/ms/.cvsignore @@ -0,0 +1,2 @@ +msfs.coff +msfs.sys.unstripped \ No newline at end of file diff --git a/drivers/fs/ms/Makefile b/drivers/fs/ms/Makefile new file mode 100644 index 0000000..c81541d --- /dev/null +++ b/drivers/fs/ms/Makefile @@ -0,0 +1,18 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = msfs + +TARGET_OBJECTS = \ + create.o \ + finfo.o \ + fsctrl.o \ + msfs.o \ + rw.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/fs/ms/create.c b/drivers/fs/ms/create.c new file mode 100644 index 0000000..77e837e --- /dev/null +++ b/drivers/fs/ms/create.c @@ -0,0 +1,310 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ms/create.c + * PURPOSE: Mailslot filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "msfs.h" + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +MsfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PMSFS_DEVICE_EXTENSION DeviceExtension; + PMSFS_MAILSLOT Mailslot; + PMSFS_FCB Fcb; + PMSFS_MAILSLOT current; + PLIST_ENTRY current_entry; + KIRQL oldIrql; + + DPRINT("MsfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + + DPRINT("Mailslot name: %wZ\n", &FileObject->FileName); + + Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB)); + if (Fcb == NULL) + { + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + KeLockMutex(&DeviceExtension->MailslotListLock); + current_entry = DeviceExtension->MailslotListHead.Flink; + while (current_entry != &DeviceExtension->MailslotListHead) + { + current = CONTAINING_RECORD(current_entry, + MSFS_MAILSLOT, + MailslotListEntry); + + if (!RtlCompareUnicodeString(&FileObject->FileName, ¤t->Name, TRUE)) + { + break; + } + + current_entry = current_entry->Flink; + } + + if (current_entry == &DeviceExtension->MailslotListHead) + { + ExFreePool(Fcb); + KeUnlockMutex(&DeviceExtension->MailslotListLock); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_UNSUCCESSFUL); + } + + Mailslot = current; + + KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql); + InsertTailList(&Mailslot->FcbListHead, &Fcb->FcbListEntry); + KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql); + + Mailslot->ReferenceCount++; + + Fcb->Mailslot = Mailslot; + + KeUnlockMutex(&DeviceExtension->MailslotListLock); + + FileObject->FsContext = Fcb; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PMSFS_DEVICE_EXTENSION DeviceExtension; + PMSFS_MAILSLOT Mailslot; + PMSFS_FCB Fcb; + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PMSFS_MAILSLOT current; + PIO_MAILSLOT_CREATE_BUFFER Buffer; + + DPRINT("MsfsCreateMailslot(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + Buffer = (PIO_MAILSLOT_CREATE_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer; + + DPRINT("Mailslot name: %wZ\n", &FileObject->FileName); + + Mailslot = ExAllocatePool(NonPagedPool, sizeof(MSFS_MAILSLOT)); + if (Mailslot == NULL) + { + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + if (!RtlCreateUnicodeString(&Mailslot->Name, FileObject->FileName.Buffer)) + { + ExFreePool(Mailslot); + ExFreePool(Fcb); + + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + Fcb = ExAllocatePool(NonPagedPool, sizeof(MSFS_FCB)); + if (Fcb == NULL) + { + ExFreePool(Mailslot); + + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + Mailslot->ReferenceCount = 0; + InitializeListHead(&Mailslot->FcbListHead); + KeInitializeSpinLock(&Mailslot->FcbListLock); + + Mailslot->MaxMessageSize = Buffer->MaxMessageSize; + Mailslot->MessageCount = 0; + Mailslot->TimeOut = Buffer->TimeOut; + KeInitializeEvent(&Mailslot->MessageEvent, + NotificationEvent, + FALSE); + + InitializeListHead(&Mailslot->MessageListHead); + KeInitializeSpinLock(&Mailslot->MessageListLock); + + KeLockMutex(&DeviceExtension->MailslotListLock); + current_entry = DeviceExtension->MailslotListHead.Flink; + while (current_entry != &DeviceExtension->MailslotListHead) + { + current = CONTAINING_RECORD(current_entry, + MSFS_MAILSLOT, + MailslotListEntry); + + if (!RtlCompareUnicodeString(&Mailslot->Name, ¤t->Name, TRUE)) + { + break; + } + + current_entry = current_entry->Flink; + } + + if (current_entry != &DeviceExtension->MailslotListHead) + { + RtlFreeUnicodeString(&Mailslot->Name); + ExFreePool(Mailslot); + + Mailslot = current; + } + else + { + InsertTailList(&DeviceExtension->MailslotListHead, + &Mailslot->MailslotListEntry); + } + + KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql); + InsertTailList(&Mailslot->FcbListHead, &Fcb->FcbListEntry); + KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql); + + Mailslot->ReferenceCount++; + Mailslot->ServerFcb = Fcb; + Fcb->Mailslot = Mailslot; + + KeUnlockMutex(&DeviceExtension->MailslotListLock); + + FileObject->FsContext = Fcb; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +MsfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PMSFS_DEVICE_EXTENSION DeviceExtension; + PMSFS_MAILSLOT Mailslot; + PMSFS_FCB Fcb; + PMSFS_MESSAGE Message; + KIRQL oldIrql; + + DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + + KeLockMutex(&DeviceExtension->MailslotListLock); + + if (DeviceExtension->MailslotListHead.Flink == &DeviceExtension->MailslotListHead) + { + KeUnlockMutex(&DeviceExtension->MailslotListLock); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); + } + + Fcb = FileObject->FsContext; + Mailslot = Fcb->Mailslot; + + DPRINT("Mailslot name: %wZ\n", &Mailslot->Name); + + Mailslot->ReferenceCount--; + if (Mailslot->ServerFcb == Fcb) + { + /* delete all messages from message-list */ + KeAcquireSpinLock(&Mailslot->MessageListLock, &oldIrql); + + while (Mailslot->MessageListHead.Flink != &Mailslot->MessageListHead) + { + Message = CONTAINING_RECORD(Mailslot->MessageListHead.Flink, + MSFS_MESSAGE, + MessageListEntry); + RemoveEntryList(Mailslot->MessageListHead.Flink); + ExFreePool(Message); + } + Mailslot->MessageCount = 0; + + KeReleaseSpinLock(&Mailslot->MessageListLock, oldIrql); + Mailslot->ServerFcb = NULL; + } + + KeAcquireSpinLock(&Mailslot->FcbListLock, &oldIrql); + RemoveEntryList(&Fcb->FcbListEntry); + KeReleaseSpinLock(&Mailslot->FcbListLock, oldIrql); + ExFreePool(Fcb); + FileObject->FsContext = NULL; + + if (Mailslot->ReferenceCount == 0) + { + DPRINT1("ReferenceCount == 0: Deleting mailslot data\n"); + RtlFreeUnicodeString(&Mailslot->Name); + RemoveEntryList(&Mailslot->MailslotListEntry); + ExFreePool(Mailslot); + } + + KeUnlockMutex(&DeviceExtension->MailslotListLock); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/ms/finfo.c b/drivers/fs/ms/finfo.c new file mode 100644 index 0000000..107439d --- /dev/null +++ b/drivers/fs/ms/finfo.c @@ -0,0 +1,198 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ms/finfo.c + * PURPOSE: Mailslot filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "msfs.h" + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS +MsfsQueryMailslotInformation(PMSFS_FCB Fcb, + PFILE_MAILSLOT_QUERY_INFORMATION Buffer, + PULONG BufferLength) +{ + PMSFS_MAILSLOT Mailslot; + KIRQL oldIrql; + + if (*BufferLength < sizeof(FILE_MAILSLOT_QUERY_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + Mailslot = Fcb->Mailslot; + + Buffer->MaxMessageSize = Mailslot->MaxMessageSize; + Buffer->Timeout = Mailslot->TimeOut; + + KeAcquireSpinLock(&Mailslot->MessageListLock, &oldIrql); + Buffer->MessageCount = Mailslot->MessageCount; + if (Mailslot->MessageCount == 0) + { + Buffer->NextSize = 0; + } + else + { + /* FIXME: read size of first message (head) */ + Buffer->NextSize = 0; + } + KeReleaseSpinLock(&Mailslot->MessageListLock, oldIrql); + + *BufferLength -= sizeof(FILE_MAILSLOT_QUERY_INFORMATION); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +MsfsSetMailslotInformation(PMSFS_FCB Fcb, + PFILE_MAILSLOT_SET_INFORMATION Buffer, + PULONG BufferLength) +{ + if (*BufferLength < sizeof(FILE_MAILSLOT_SET_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + Fcb->Mailslot->TimeOut = Buffer->Timeout; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +MsfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + PMSFS_DEVICE_EXTENSION DeviceExtension; + PMSFS_FCB Fcb; + PMSFS_MAILSLOT Mailslot; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DPRINT("MsfsQueryInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; + DeviceExtension = DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + Fcb = (PMSFS_FCB)FileObject->FsContext; + Mailslot = Fcb->Mailslot; + + DPRINT("Mailslot name: %wZ\n", &Mailslot->Name); + + /* querying information is not permitted on client side */ + if (Fcb->Mailslot->ServerFcb != Fcb) + { + Status = STATUS_ACCESS_DENIED; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); + } + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = IoStack->Parameters.QueryFile.Length; + + switch (FileInformationClass) + { + case FileMailslotQueryInformation: + Status = MsfsQueryMailslotInformation(Fcb, + SystemBuffer, + &BufferLength); + break; + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + IoStack->Parameters.QueryFile.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +MsfsSetInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + PMSFS_FCB Fcb; + PMSFS_MAILSLOT Mailslot; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DPRINT("MsfsSetInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; + FileObject = IoStack->FileObject; + Fcb = (PMSFS_FCB)FileObject->FsContext; + Mailslot = Fcb->Mailslot; + + DPRINT("Mailslot name: %wZ\n", &Mailslot->Name); + + /* setting information is not permitted on client side */ + if (Fcb->Mailslot->ServerFcb != Fcb) + { + Status = STATUS_ACCESS_DENIED; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); + } + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = IoStack->Parameters.QueryFile.Length; + + DPRINT("FileInformationClass %d\n", FileInformationClass); + DPRINT("SystemBuffer %x\n", SystemBuffer); + + switch (FileInformationClass) + { + case FileMailslotSetInformation: + Status = MsfsSetMailslotInformation(Fcb, + SystemBuffer, + &BufferLength); + break; + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ms/fsctrl.c b/drivers/fs/ms/fsctrl.c new file mode 100644 index 0000000..1940ba7 --- /dev/null +++ b/drivers/fs/ms/fsctrl.c @@ -0,0 +1,71 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ms/fsctrl.c + * PURPOSE: Mailslot filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "msfs.h" + +//#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +MsfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PMSFS_MAILSLOT Mailslot; + PMSFS_FCB Fcb; + NTSTATUS Status; + + DPRINT1("MsfsFileSystemControl(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + FileObject = IoStack->FileObject; + Fcb = FileObject->FsContext; + Mailslot = Fcb->Mailslot; + + DPRINT1("Mailslot name: %wZ\n", &Mailslot->Name); + + switch (IoStack->Parameters.FileSystemControl.IoControlCode) + { +#if 0 + case FSCTL_WAIT_PIPE: + break; + + case FSCTL_LISTEN: + break; + + case FSCTL_SET_STATE: + break; + + case FSCTL_GET_STATE: + { + + + break; + } + +#endif + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ms/msfs.c b/drivers/fs/ms/msfs.c new file mode 100644 index 0000000..2e051ac --- /dev/null +++ b/drivers/fs/ms/msfs.c @@ -0,0 +1,79 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ms/msfs.c + * PURPOSE: Mailslot filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "msfs.h" + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + PMSFS_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName; + NTSTATUS Status; + + DbgPrint("Mailslot FSD 0.0.1\n"); + + DriverObject->Flags = 0; + DriverObject->MajorFunction[IRP_MJ_CREATE] = MsfsCreate; + DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = + MsfsCreateMailslot; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = MsfsClose; + DriverObject->MajorFunction[IRP_MJ_READ] = MsfsRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = MsfsWrite; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + MsfsQueryInformation; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = + MsfsSetInformation; +// DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = +// MsfsDirectoryControl; +// DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = MsfsFlushBuffers; +// DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = MsfsShutdown; +// DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = +// MsfsQuerySecurity; +// DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = +// MsfsSetSecurity; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + MsfsFileSystemControl; + + DriverObject->DriverUnload = NULL; + + RtlInitUnicodeString(&DeviceName, + L"\\Device\\MailSlot"); + Status = IoCreateDevice(DriverObject, + sizeof(MSFS_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_MAILSLOT, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* initialize device extension */ + DeviceExtension = DeviceObject->DeviceExtension; + InitializeListHead(&DeviceExtension->MailslotListHead); + KeInitializeMutex(&DeviceExtension->MailslotListLock, + 0); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/ms/msfs.h b/drivers/fs/ms/msfs.h new file mode 100644 index 0000000..4f7da54 --- /dev/null +++ b/drivers/fs/ms/msfs.h @@ -0,0 +1,60 @@ +#ifndef __SERVICES_FS_MS_MSFS_H +#define __SERVICES_FS_MS_MSFS_H + +typedef struct _MSFS_DEVICE_EXTENSION +{ + LIST_ENTRY MailslotListHead; + KMUTEX MailslotListLock; +} MSFS_DEVICE_EXTENSION, *PMSFS_DEVICE_EXTENSION; + +typedef struct _MSFS_MAILSLOT +{ + UNICODE_STRING Name; + LIST_ENTRY MailslotListEntry; + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + struct _MSFS_FCB *ServerFcb; + ULONG ReferenceCount; + LARGE_INTEGER TimeOut; + KEVENT MessageEvent; + ULONG MaxMessageSize; + ULONG MessageCount; + KSPIN_LOCK MessageListLock; + LIST_ENTRY MessageListHead; +} MSFS_MAILSLOT, *PMSFS_MAILSLOT; + +typedef struct _MSFS_FCB +{ + LIST_ENTRY FcbListEntry; + PMSFS_MAILSLOT Mailslot; +} MSFS_FCB, *PMSFS_FCB; + +typedef struct _MSFS_MESSAGE +{ + LIST_ENTRY MessageListEntry; + ULONG Size; + UCHAR Buffer[1]; +} MSFS_MESSAGE, *PMSFS_MESSAGE; + + +#define KeLockMutex(x) KeWaitForSingleObject(x, \ + UserRequest, \ + KernelMode, \ + FALSE, \ + NULL); + +#define KeUnlockMutex(x) KeReleaseMutex(x, FALSE); + +NTSTATUS STDCALL MsfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MsfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL MsfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MsfsSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL MsfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL MsfsWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL MsfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +#endif /* __SERVICES_FS_NP_NPFS_H */ diff --git a/drivers/fs/ms/msfs.rc b/drivers/fs/ms/msfs.rc new file mode 100644 index 0000000..a3a164d --- /dev/null +++ b/drivers/fs/ms/msfs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Mailslot IFS Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "msfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "msfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/ms/rw.c b/drivers/fs/ms/rw.c new file mode 100644 index 0000000..cc34b6b --- /dev/null +++ b/drivers/fs/ms/rw.c @@ -0,0 +1,175 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ms/rw.c + * PURPOSE: Mailslot filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include "msfs.h" + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +MsfsRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PMSFS_MAILSLOT Mailslot; + PMSFS_FCB Fcb; + PMSFS_MESSAGE Message; + KIRQL oldIrql; + ULONG Length; + ULONG LengthRead = 0; + PVOID Buffer; + NTSTATUS Status; + + DPRINT("MsfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileObject = IoStack->FileObject; + Fcb = (PMSFS_FCB)FileObject->FsContext; + Mailslot = Fcb->Mailslot; + + DPRINT("MailslotName: %wZ\n", &Mailslot->Name); + + /* reading is not permitted on client side */ + if (Fcb->Mailslot->ServerFcb != Fcb) + { + Irp->IoStatus.Status = STATUS_ACCESS_DENIED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_ACCESS_DENIED); + } + + Length = IoStack->Parameters.Read.Length; + if (Irp->MdlAddress) + Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress); + else + Buffer = Irp->UserBuffer; + + Status = KeWaitForSingleObject(&Mailslot->MessageEvent, + UserRequest, + KernelMode, + FALSE, + NULL); /* FIXME: handle timeout */ + if ((NT_SUCCESS(Status)) && (Mailslot->MessageCount > 0)) + { + /* copy current message into buffer */ + Message = CONTAINING_RECORD(Mailslot->MessageListHead.Flink, + MSFS_MESSAGE, + MessageListEntry); + memcpy(Buffer, &Message->Buffer, min(Message->Size,Length)); + LengthRead = Message->Size; + + KeAcquireSpinLock(&Mailslot->MessageListLock, &oldIrql); + RemoveHeadList(&Mailslot->MessageListHead); + KeReleaseSpinLock(&Mailslot->MessageListLock, oldIrql); + + ExFreePool(Message); + Mailslot->MessageCount--; + if (Mailslot->MessageCount == 0) + { + KeClearEvent(&Mailslot->MessageEvent); + } + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = LengthRead; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +MsfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PMSFS_MAILSLOT Mailslot; + PMSFS_FCB Fcb; + PMSFS_MESSAGE Message; + KIRQL oldIrql; + ULONG Length; + PVOID Buffer; + + DPRINT("MsfsWrite(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileObject = IoStack->FileObject; + Fcb = (PMSFS_FCB)FileObject->FsContext; + Mailslot = Fcb->Mailslot; + + DPRINT("MailslotName: %wZ\n", &Mailslot->Name); + + /* writing is not permitted on server side */ + if (Fcb->Mailslot->ServerFcb == Fcb) + { + Irp->IoStatus.Status = STATUS_ACCESS_DENIED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_ACCESS_DENIED); + } + + Length = IoStack->Parameters.Write.Length; + if (Irp->MdlAddress) + Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress); + else + Buffer = Irp->UserBuffer; + + DPRINT("Length: %lu Message: %s\n", Length, (PUCHAR)Buffer); + + /* Allocate new message */ + Message = ExAllocatePool(NonPagedPool, + sizeof(MSFS_MESSAGE) + Length); + if (Message == NULL) + { + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + Message->Size = Length; + memcpy(&Message->Buffer, Buffer, Length); + + KeAcquireSpinLock(&Mailslot->MessageListLock, &oldIrql); + InsertTailList(&Mailslot->MessageListHead, &Message->MessageListEntry); + KeReleaseSpinLock(&Mailslot->MessageListLock, oldIrql); + + Mailslot->MessageCount++; + if (Mailslot->MessageCount == 1) + { + KeSetEvent(&Mailslot->MessageEvent, + 0, + FALSE); + } + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Length; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/mup/.cvsignore b/drivers/fs/mup/.cvsignore new file mode 100644 index 0000000..6f7e8c9 --- /dev/null +++ b/drivers/fs/mup/.cvsignore @@ -0,0 +1,6 @@ +base.tmp +junk.tmp +temp.exp +mup.coff +mup.sys.unstripped +*.d \ No newline at end of file diff --git a/drivers/fs/mup/create.c b/drivers/fs/mup/create.c new file mode 100644 index 0000000..ab17971 --- /dev/null +++ b/drivers/fs/mup/create.c @@ -0,0 +1,71 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/fs/mup/create.c + * PURPOSE: Multi UNC Provider + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "mup.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +MupCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + + DPRINT("MupCreate() called\n"); + + DeviceExt = DeviceObject->DeviceExtension; + assert (DeviceExt); + Stack = IoGetCurrentIrpStackLocation (Irp); + assert (Stack); + + FileObject = Stack->FileObject; + + DPRINT("FileName: '%wZ'\n", &FileObject->FileName); + + Status = STATUS_ACCESS_DENIED; + + Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0; + Irp->IoStatus.Status = Status; + + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/mup/makefile b/drivers/fs/mup/makefile new file mode 100644 index 0000000..53a13b6 --- /dev/null +++ b/drivers/fs/mup/makefile @@ -0,0 +1,15 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = mup + +TARGET_OBJECTS = $(TARGET_NAME).o create.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/fs/mup/mup.c b/drivers/fs/mup/mup.c new file mode 100644 index 0000000..824939e --- /dev/null +++ b/drivers/fs/mup/mup.c @@ -0,0 +1,105 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: drivers/fs/mup/mup.c + * PURPOSE: Multi UNC Provider + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "mup.h" + + +/* GLOBALS *****************************************************************/ + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status; + UNICODE_STRING DeviceName; + + DPRINT("MUP 0.0.1\n"); + + RtlInitUnicodeString(&DeviceName, + L"\\Device\\Mup"); + Status = IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_MULTI_UNC_PROVIDER, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* Initialize driver data */ + DeviceObject->Flags = DO_DIRECT_IO; +// DriverObject->MajorFunction[IRP_MJ_CLOSE] = NtfsClose; + DriverObject->MajorFunction[IRP_MJ_CREATE] = MupCreate; + DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = MupCreate; + DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = MupCreate; +// DriverObject->MajorFunction[IRP_MJ_READ] = NtfsRead; +// DriverObject->MajorFunction[IRP_MJ_WRITE] = NtfsWrite; +// DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = +// NtfsFileSystemControl; +// DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = +// NtfsDirectoryControl; +// DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = +// NtfsQueryInformation; +// DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = +// NtfsQueryVolumeInformation; +// DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = +// NtfsSetVolumeInformation; + + DriverObject->DriverUnload = NULL; + + + /* Initialize global data */ +// DeviceExtensionNtfsGlobalData = DeviceObject->DeviceExtension; +// RtlZeroMemory(NtfsGlobalData, +// sizeof(NTFS_GLOBAL_DATA)); +// NtfsGlobalData->DriverObject = DriverObject; +// NtfsGlobalData->DeviceObject = DeviceObject; + + return(STATUS_SUCCESS); +} + diff --git a/drivers/fs/mup/mup.h b/drivers/fs/mup/mup.h new file mode 100644 index 0000000..6178b47 --- /dev/null +++ b/drivers/fs/mup/mup.h @@ -0,0 +1,29 @@ +#ifndef MUP_H +#define MUP_H + +#include + + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + + + +typedef struct +{ + ULONG Dummy; + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + + + +/* create.c */ + +NTSTATUS STDCALL +MupCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + + +#endif /* MUP_H */ diff --git a/drivers/fs/mup/mup.rc b/drivers/fs/mup/mup.rc new file mode 100644 index 0000000..28189c8 --- /dev/null +++ b/drivers/fs/mup/mup.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Multi UNC Provider\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "mup\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "mup.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/np/.cvsignore b/drivers/fs/np/.cvsignore new file mode 100644 index 0000000..c725dab --- /dev/null +++ b/drivers/fs/np/.cvsignore @@ -0,0 +1,6 @@ +base.tmp +junk.tmp +temp.exp +npfs.coff +npfs.sys +npfs.sys.unstripped diff --git a/drivers/fs/np/Makefile b/drivers/fs/np/Makefile new file mode 100644 index 0000000..5793f20 --- /dev/null +++ b/drivers/fs/np/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = npfs + +TARGET_OBJECTS = \ + create.o \ + finfo.o \ + fsctrl.o \ + npfs.o \ + rw.o \ + volume.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/fs/np/create.c b/drivers/fs/np/create.c new file mode 100644 index 0000000..34624e7 --- /dev/null +++ b/drivers/fs/np/create.c @@ -0,0 +1,454 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/np/create.c + * PURPOSE: Named pipe filesystem + * PROGRAMMER: David Welch + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include "npfs.h" + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NpfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PNPFS_PIPE Pipe; + PNPFS_FCB ClientFcb; + PNPFS_FCB ServerFcb; + PNPFS_PIPE current; + PLIST_ENTRY current_entry; + PNPFS_DEVICE_EXTENSION DeviceExt; + KIRQL oldIrql; + ULONG Disposition; + + DPRINT1("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + IoStack = IoGetCurrentIrpStackLocation(Irp); + FileObject = IoStack->FileObject; + Disposition = ((IoStack->Parameters.Create.Options >> 24) & 0xff); + DPRINT("FileObject %p\n", FileObject); + DPRINT("FileName %wZ\n", &FileObject->FileName); + + ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB)); + if (ClientFcb == NULL) + { + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("No memory!\n"); + + return(STATUS_NO_MEMORY); + } + + KeLockMutex(&DeviceExt->PipeListLock); + current_entry = DeviceExt->PipeListHead.Flink; + while (current_entry != &DeviceExt->PipeListHead) + { + current = CONTAINING_RECORD(current_entry, + NPFS_PIPE, + PipeListEntry); + + if (RtlCompareUnicodeString(&FileObject->FileName, + ¤t->PipeName, + TRUE) == 0) + { + break; + } + + current_entry = current_entry->Flink; + } + + if (current_entry == &DeviceExt->PipeListHead) + { + ExFreePool(ClientFcb); + KeUnlockMutex(&DeviceExt->PipeListLock); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("No pipe found!\n"); + + return(STATUS_OBJECT_NAME_NOT_FOUND); + } + + Pipe = current; + + ClientFcb->Pipe = Pipe; + ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END; + ClientFcb->OtherSide = NULL; + ClientFcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + + /* initialize data list */ + InitializeListHead(&ClientFcb->DataListHead); + KeInitializeSpinLock(&ClientFcb->DataListLock); + + KeInitializeEvent(&ClientFcb->ConnectEvent, + SynchronizationEvent, + FALSE); + + KeInitializeEvent(&ClientFcb->ReadEvent, + SynchronizationEvent, + FALSE); + + KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql); + InsertTailList(&Pipe->ClientFcbListHead, &ClientFcb->FcbListEntry); + KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql); + + Pipe->ReferenceCount++; + + KeUnlockMutex(&DeviceExt->PipeListLock); + +#if 0 + if (Disposition == OPEN_EXISTING) + { + /* do not connect to listening servers */ + FileObject->FsContext = ClientFcb; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("Success!\n"); + + return(STATUS_SUCCESS); + } +#endif + + /* search for disconnected or listening server fcb */ + current_entry = Pipe->ServerFcbListHead.Flink; + while (current_entry != &Pipe->ServerFcbListHead) + { + ServerFcb = CONTAINING_RECORD(current_entry, + NPFS_FCB, + FcbListEntry); + if ((ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE) + || (ServerFcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)) + { + DPRINT("Server found! Fcb %p\n", ServerFcb); + break; + } + current_entry = current_entry->Flink; + } + + if (current_entry == &Pipe->ServerFcbListHead) + { + DPRINT("No server fcb found!\n"); + + FileObject->FsContext = ClientFcb; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); + } + + ClientFcb->OtherSide = ServerFcb; + ServerFcb->OtherSide = ClientFcb; + ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE; + ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE; + + /* FIXME: create data queue(s) */ + + /* wake server thread */ + KeSetEvent(&ServerFcb->ConnectEvent, 0, FALSE); + + FileObject->FsContext = ClientFcb; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT("Success!\n"); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PNPFS_DEVICE_EXTENSION DeviceExt; + PNPFS_PIPE Pipe; + PNPFS_FCB Fcb; + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PNPFS_PIPE current; + PIO_PIPE_CREATE_BUFFER Buffer; + + DPRINT1("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + IoStack = IoGetCurrentIrpStackLocation(Irp); + FileObject = IoStack->FileObject; + DPRINT("FileObject %p\n", FileObject); + DPRINT("Pipe name %wZ\n", &FileObject->FileName); + + Buffer = (PIO_PIPE_CREATE_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer; + + Pipe = ExAllocatePool(NonPagedPool, sizeof(NPFS_PIPE)); + if (Pipe == NULL) + { + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB)); + if (Fcb == NULL) + { + ExFreePool(Pipe); + + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + if (RtlCreateUnicodeString(&Pipe->PipeName, FileObject->FileName.Buffer) == 0) + { + ExFreePool(Pipe); + ExFreePool(Fcb); + + Irp->IoStatus.Status = STATUS_NO_MEMORY; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NO_MEMORY); + } + + Pipe->ReferenceCount = 0; + InitializeListHead(&Pipe->ServerFcbListHead); + InitializeListHead(&Pipe->ClientFcbListHead); + KeInitializeSpinLock(&Pipe->FcbListLock); + + Pipe->PipeType = Buffer->WriteModeMessage ? FILE_PIPE_MESSAGE_TYPE : FILE_PIPE_BYTE_STREAM_TYPE; + Pipe->PipeWriteMode = Buffer->WriteModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE; + Pipe->PipeReadMode = Buffer->ReadModeMessage ? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE; + Pipe->PipeBlockMode = Buffer->NonBlocking; + Pipe->PipeConfiguration = IoStack->Parameters.Create.Options & 0x3; + Pipe->MaximumInstances = Buffer->MaxInstances; + Pipe->CurrentInstances = 0; + Pipe->TimeOut = Buffer->TimeOut; + Pipe->InboundQuota = Buffer->InBufferSize; + Pipe->OutboundQuota = Buffer->OutBufferSize; + + KeLockMutex(&DeviceExt->PipeListLock); + current_entry = DeviceExt->PipeListHead.Flink; + while (current_entry != &DeviceExt->PipeListHead) + { + current = CONTAINING_RECORD(current_entry, + NPFS_PIPE, + PipeListEntry); + + if (RtlCompareUnicodeString(&Pipe->PipeName, ¤t->PipeName, TRUE) == 0) + { + break; + } + + current_entry = current_entry->Flink; + } + + if (current_entry != &DeviceExt->PipeListHead) + { + RtlFreeUnicodeString(&Pipe->PipeName); + ExFreePool(Pipe); + + Pipe = current; + } + else + { + InsertTailList(&DeviceExt->PipeListHead, &Pipe->PipeListEntry); + } + Pipe->ReferenceCount++; + Pipe->CurrentInstances++; + + KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql); + InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry); + KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql); + + Fcb->Pipe = Pipe; + Fcb->PipeEnd = FILE_PIPE_SERVER_END; + Fcb->OtherSide = NULL; + Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + Fcb->ReadDataAvailable = 0; + Fcb->WriteQuotaAvailable = 0; + + /* initialize data list */ + InitializeListHead(&Fcb->DataListHead); + KeInitializeSpinLock(&Fcb->DataListLock); + + KeInitializeEvent(&Fcb->ConnectEvent, + SynchronizationEvent, + FALSE); + + KeInitializeEvent(&Fcb->ReadEvent, + SynchronizationEvent, + FALSE); + + + KeUnlockMutex(&DeviceExt->PipeListLock); + + FileObject->FsContext = Fcb; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NpfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PNPFS_DEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PNPFS_FCB Fcb; + PNPFS_PIPE Pipe; + KIRQL oldIrql; + PLIST_ENTRY CurrentEntry; + PNPFS_PIPE_DATA Current; + + + DPRINT1("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + Fcb = FileObject->FsContext; + + if (Fcb == NULL) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); + } + + DPRINT("Fcb %x\n", Fcb); + Pipe = Fcb->Pipe; + + DPRINT("Closing pipe %wZ\n", &Pipe->PipeName); + + KeLockMutex(&DeviceExt->PipeListLock); + + + if (Fcb->PipeEnd == FILE_PIPE_SERVER_END) + { + /* FIXME: Clean up existing connections here ?? */ + DPRINT("Server\n"); + Pipe->CurrentInstances--; + if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + if (Fcb->OtherSide) + { + Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE; + } + Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + } + } + Pipe->ReferenceCount--; + + if (Fcb->PipeEnd == FILE_PIPE_CLIENT_END) + { + DPRINT("Client\n"); + if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + if (Fcb->OtherSide) + { + Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE; + + /* Signaling the read event. If is possible that an other + * thread waits of read data. + */ + KeSetEvent(&Fcb->OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE); + } + Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + } + } + + FileObject->FsContext = NULL; + + if (Pipe->ReferenceCount == 0) + { + KeAcquireSpinLock(&Pipe->FcbListLock, &oldIrql); + if (Fcb->OtherSide) + { + RemoveEntryList(&Fcb->OtherSide->FcbListEntry); + } + RemoveEntryList(&Fcb->FcbListEntry); + KeReleaseSpinLock(&Pipe->FcbListLock, oldIrql); + if (Fcb->OtherSide) + { + KeAcquireSpinLock(&Fcb->OtherSide->DataListLock, &oldIrql); + while (!IsListEmpty(&Fcb->OtherSide->DataListHead)) + { + CurrentEntry = RemoveHeadList(&Fcb->OtherSide->DataListHead); + Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); + + NpfsFreePipeData(Current); + } + KeReleaseSpinLock(&Fcb->OtherSide->DataListLock, oldIrql); + ExFreePool(Fcb->OtherSide); + } + + KeAcquireSpinLock(&Fcb->DataListLock, &oldIrql); + while (!IsListEmpty(&Fcb->DataListHead)) + { + CurrentEntry = RemoveHeadList(&Fcb->DataListHead); + Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); + NpfsFreePipeData(Current); + } + KeReleaseSpinLock(&Fcb->DataListLock, oldIrql); + ExFreePool(Fcb); + RtlFreeUnicodeString(&Pipe->PipeName); + RemoveEntryList(&Pipe->PipeListEntry); + ExFreePool(Pipe); + } + + KeUnlockMutex(&DeviceExt->PipeListLock); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/np/finfo.c b/drivers/fs/np/finfo.c new file mode 100644 index 0000000..727d879 --- /dev/null +++ b/drivers/fs/np/finfo.c @@ -0,0 +1,205 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/np/finfo.c + * PURPOSE: Named pipe filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "npfs.h" + +#define NDEBUG +#include + + + + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS +NpfsQueryPipeInformation(PDEVICE_OBJECT DeviceObject, + PNPFS_FCB Fcb, + PFILE_PIPE_INFORMATION Info, + PULONG BufferLength) +{ + PNPFS_PIPE Pipe; + + DPRINT("NpfsQueryPipeInformation()\n"); + + Pipe = Fcb->Pipe; + + RtlZeroMemory(Info, + sizeof(FILE_PIPE_INFORMATION)); + +// Info->PipeMode = +// Info->CompletionMode = + + *BufferLength -= sizeof(FILE_PIPE_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NpfsQueryLocalPipeInformation(PDEVICE_OBJECT DeviceObject, + PNPFS_FCB Fcb, + PFILE_PIPE_LOCAL_INFORMATION Info, + PULONG BufferLength) +{ + PNPFS_PIPE Pipe; + + DPRINT("NpfsQueryLocalPipeInformation()\n"); + + Pipe = Fcb->Pipe; + + RtlZeroMemory(Info, + sizeof(FILE_PIPE_LOCAL_INFORMATION)); + + Info->NamedPipeType = Pipe->PipeType; + Info->NamedPipeConfiguration = Pipe->PipeConfiguration; + Info->MaximumInstances = Pipe->MaximumInstances; + Info->CurrentInstances = Pipe->CurrentInstances; + Info->InboundQuota = Pipe->InboundQuota; + Info->OutboundQuota = Pipe->OutboundQuota; + Info->NamedPipeState = Fcb->PipeState; + Info->NamedPipeEnd = Fcb->PipeEnd; + + if (Fcb->PipeEnd == FILE_PIPE_SERVER_END) + { + Info->ReadDataAvailable = Fcb->ReadDataAvailable; + Info->WriteQuotaAvailable = Fcb->WriteQuotaAvailable; + } + else if (Fcb->OtherSide != NULL) + { + Info->ReadDataAvailable = Fcb->OtherSide->ReadDataAvailable; + Info->WriteQuotaAvailable = Fcb->OtherSide->WriteQuotaAvailable; + } + + *BufferLength -= sizeof(FILE_PIPE_LOCAL_INFORMATION); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NpfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + PNPFS_DEVICE_EXTENSION DeviceExtension; + PNPFS_FCB Fcb; + PNPFS_PIPE Pipe; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DPRINT("NpfsQueryInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; + DeviceExtension = DeviceObject->DeviceExtension; + FileObject = IoStack->FileObject; + Fcb = (PNPFS_FCB)FileObject->FsContext; + Pipe = Fcb->Pipe; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = IoStack->Parameters.QueryFile.Length; + + DPRINT("Pipe name: %wZ\n", &Pipe->PipeName); + DPRINT("FileInformationClass %d\n", FileInformationClass); + DPRINT("SystemBuffer %p\n", SystemBuffer); + DPRINT("BufferLength %lu\n", BufferLength); + + switch (FileInformationClass) + { + case FilePipeInformation: + Status = NpfsQueryPipeInformation(DeviceObject, + Fcb, + SystemBuffer, + &BufferLength); + break; + + case FilePipeLocalInformation: + Status = NpfsQueryLocalPipeInformation(DeviceObject, + Fcb, + SystemBuffer, + &BufferLength); + break; + + case FilePipeRemoteInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + IoStack->Parameters.QueryFile.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +NpfsSetInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + PNPFS_FCB Fcb; + PNPFS_PIPE Pipe; + PVOID SystemBuffer; + ULONG BufferLength; + NTSTATUS Status; + + DPRINT("NpfsSetInformation(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation (Irp); + FileInformationClass = IoStack->Parameters.QueryFile.FileInformationClass; + FileObject = IoStack->FileObject; + Fcb = (PNPFS_FCB)FileObject->FsContext; + Pipe = Fcb->Pipe; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = IoStack->Parameters.QueryFile.Length; + + DPRINT("Pipe name: %wZ\n", &Pipe->PipeName); + DPRINT("FileInformationClass %d\n", FileInformationClass); + DPRINT("SystemBuffer %p\n", SystemBuffer); + DPRINT("BufferLength %lu\n", BufferLength); + + switch (FileInformationClass) + { + case FilePipeInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + case FilePipeLocalInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + case FilePipeRemoteInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/np/fsctrl.c b/drivers/fs/np/fsctrl.c new file mode 100644 index 0000000..cec08fb --- /dev/null +++ b/drivers/fs/np/fsctrl.c @@ -0,0 +1,513 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/np/fsctrl.c + * PURPOSE: Named pipe filesystem + * PROGRAMMER: David Welch + * Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "npfs.h" + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS +NpfsConnectPipe(PNPFS_FCB Fcb) +{ + PNPFS_PIPE Pipe; + PLIST_ENTRY current_entry; + PNPFS_FCB ClientFcb; + NTSTATUS Status; + + DPRINT("NpfsConnectPipe()\n"); + + if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) + return STATUS_PIPE_CONNECTED; + + if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE) + return STATUS_PIPE_CLOSING; + + /* + * Acceptable states are: FILE_PIPE_DISCONNECTED_STATE and + * FILE_PIPE_LISTENING_STATE + */ + + DPRINT("Waiting for connection...\n"); + + Pipe = Fcb->Pipe; + + Fcb->PipeState = FILE_PIPE_LISTENING_STATE; + + /* search for a listening client fcb */ + + current_entry = Pipe->ClientFcbListHead.Flink; + while (current_entry != &Pipe->ClientFcbListHead) + { + ClientFcb = CONTAINING_RECORD(current_entry, + NPFS_FCB, + FcbListEntry); + + if ((ClientFcb->PipeState == FILE_PIPE_LISTENING_STATE) + || (ClientFcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)) + { + break; + } + + current_entry = current_entry->Flink; + } + + if ((current_entry != &Pipe->ClientFcbListHead) + && (ClientFcb->PipeState == FILE_PIPE_LISTENING_STATE)) + { + /* found a listening client fcb */ + DPRINT("Listening client fcb found -- connecting\n"); + + /* connect client and server fcb's */ + Fcb->OtherSide = ClientFcb; + ClientFcb->OtherSide = Fcb; + + /* set connected state */ + Fcb->PipeState = FILE_PIPE_CONNECTED_STATE; + ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE; + + /* FIXME: create and initialize data queues */ + + /* signal client's connect event */ + KeSetEvent(&ClientFcb->ConnectEvent, IO_NO_INCREMENT, FALSE); + + } + else if ((current_entry != &Pipe->ClientFcbListHead) + && (ClientFcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)) + { + /* found a disconnected client fcb */ + DPRINT("Disconnected client fcb found - notifying client\n"); + + /* signal client's connect event */ + KeSetEvent(&ClientFcb->ConnectEvent, IO_NO_INCREMENT, FALSE); + } + else + { + /* no listening client fcb found */ + DPRINT("No listening client fcb found -- waiting for client\n"); + Status = KeWaitForSingleObject(&Fcb->ConnectEvent, + UserRequest, + KernelMode, + FALSE, + NULL); + + DPRINT("Finished waiting! Status: %x\n", Status); + } + + + DPRINT("Client Fcb: %p\n", Fcb->OtherSide); + + return STATUS_PIPE_CONNECTED; +} + + +static NTSTATUS +NpfsDisconnectPipe(PNPFS_FCB Fcb) +{ + PNPFS_FCB ServerFcb; + + DPRINT("NpfsDisconnectPipe()\n"); + + if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE) + return(STATUS_SUCCESS); + + if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) + { + Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + Fcb->OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE; + + /* FIXME: remove data queue(s) */ + + Fcb->OtherSide->OtherSide = NULL; + Fcb->OtherSide = NULL; + + DPRINT("Pipe disconnected\n"); + return(STATUS_SUCCESS); + } + + if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE) + { + Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; + + /* FIXME: remove data queue(s) */ + + DPRINT("Pipe disconnected\n"); + return(STATUS_SUCCESS); + } + + return(STATUS_UNSUCCESSFUL); +} + + +static NTSTATUS +NpfsWaitPipe(PIRP Irp, + PNPFS_FCB Fcb) +{ + PNPFS_PIPE Pipe; + PLIST_ENTRY current_entry; + PNPFS_FCB ServerFcb; + PNPFS_WAIT_PIPE WaitPipe; + NTSTATUS Status; + + DPRINT("NpfsWaitPipe\n"); + + WaitPipe = (PNPFS_WAIT_PIPE)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; + + /* search for listening server */ + current_entry = Pipe->ServerFcbListHead.Flink; + while (current_entry != &Pipe->ServerFcbListHead) + { + ServerFcb = CONTAINING_RECORD(current_entry, + NPFS_FCB, + FcbListEntry); + + if (ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE) + break; + + current_entry = current_entry->Flink; + } + + if (current_entry != &Pipe->ServerFcbListHead) + { + /* found a listening server fcb */ + DPRINT("Listening server fcb found -- connecting\n"); + + Status = STATUS_SUCCESS; + } + else + { + /* no listening server fcb found -- wait for one */ + Fcb->PipeState = FILE_PIPE_LISTENING_STATE; + + Status = KeWaitForSingleObject(&Fcb->ConnectEvent, + UserRequest, + KernelMode, + FALSE, + &WaitPipe->Timeout); + } + + return(Status); +} + + +static NTSTATUS +NpfsGetState( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Return current state of a pipe + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + ULONG OutputBufferLength; + PNPFS_GET_STATE Reply; + NTSTATUS Status; + PNPFS_PIPE Pipe; + PNPFS_FCB Fcb; + + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if (OutputBufferLength >= sizeof(NPFS_GET_STATE)) + { + Fcb = IrpSp->FileObject->FsContext; + Reply = (PNPFS_GET_STATE)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; + + if (Pipe->PipeWriteMode == FILE_PIPE_MESSAGE_MODE) + { + Reply->WriteModeMessage = TRUE; + } + else + { + Reply->WriteModeMessage = FALSE; + } + + if (Pipe->PipeReadMode == FILE_PIPE_MESSAGE_MODE) + { + Reply->ReadModeMessage = TRUE; + } + else + { + Reply->ReadModeMessage = FALSE; + } + + if (Pipe->PipeBlockMode == FILE_PIPE_QUEUE_OPERATION) + { + Reply->NonBlocking = TRUE; + } + else + { + Reply->NonBlocking = FALSE; + } + + Reply->InBufferSize = Pipe->InboundQuota; + + Reply->OutBufferSize = Pipe->OutboundQuota; + + Reply->Timeout = Pipe->TimeOut; + + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + + DPRINT("Status (0x%X).\n", Status); + + return Status; +} + + +static NTSTATUS +NpfsSetState( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Set state of a pipe + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + ULONG InputBufferLength; + PNPFS_SET_STATE Request; + PNPFS_PIPE Pipe; + NTSTATUS Status; + PNPFS_FCB Fcb; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + /* Validate parameters */ + if (InputBufferLength >= sizeof(NPFS_SET_STATE)) + { + Fcb = IrpSp->FileObject->FsContext; + Request = (PNPFS_SET_STATE)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; + + if (Request->WriteModeMessage) + { + Pipe->PipeWriteMode = FILE_PIPE_MESSAGE_MODE; + } + else + { + Pipe->PipeWriteMode = FILE_PIPE_BYTE_STREAM_MODE; + } + + if (Request->ReadModeMessage) + { + Pipe->PipeReadMode = FILE_PIPE_MESSAGE_MODE; + } + else + { + Pipe->PipeReadMode = FILE_PIPE_BYTE_STREAM_MODE; + } + + if (Request->NonBlocking) + { + Pipe->PipeBlockMode = FILE_PIPE_QUEUE_OPERATION; + } + else + { + Pipe->PipeBlockMode = FILE_PIPE_COMPLETE_OPERATION; + } + + Pipe->InboundQuota = Request->InBufferSize; + + Pipe->OutboundQuota = Request->OutBufferSize; + + Pipe->TimeOut = Request->Timeout; + + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + + DPRINT("Status (0x%X).\n", Status); + + return Status; +} + + +static NTSTATUS +NpfsPeekPipe(PIRP Irp, + PIO_STACK_LOCATION IoStack) +/* + * FUNCTION: Peek at a pipe (get information about messages) + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IoStack = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + ULONG OutputBufferLength; + PNPFS_PIPE Pipe; + PFILE_PIPE_PEEK_BUFFER Reply; + PNPFS_FCB Fcb; + NTSTATUS Status; + + DPRINT("NpfsPeekPipe\n"); + + OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER)) + { + DPRINT("Buffer too small\n"); + return(STATUS_INVALID_PARAMETER); + } + + Fcb = IoStack->FileObject->FsContext; + Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer; + Pipe = Fcb->Pipe; + + Status = STATUS_NOT_IMPLEMENTED; + + return(Status); +} + + + +NTSTATUS STDCALL +NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + PNPFS_DEVICE_EXTENSION DeviceExt; + PNPFS_PIPE Pipe; + PNPFS_FCB Fcb; + + DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + IoStack = IoGetCurrentIrpStackLocation(Irp); + DPRINT("IoStack: %p\n", IoStack); + FileObject = IoStack->FileObject; + DPRINT("FileObject: %p\n", FileObject); + Fcb = FileObject->FsContext; + DPRINT("Fcb: %p\n", Fcb); + Pipe = Fcb->Pipe; + DPRINT("Pipe: %p\n", Pipe); + DPRINT("PipeName: %wZ\n", &Pipe->PipeName); + + switch (IoStack->Parameters.FileSystemControl.IoControlCode) + { + case FSCTL_PIPE_ASSIGN_EVENT: + DPRINT("Assign event\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_DISCONNECT: + DPRINT("Disconnecting pipe %wZ\n", &Pipe->PipeName); + Status = NpfsDisconnectPipe(Fcb); + break; + + case FSCTL_PIPE_LISTEN: + DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName); + Status = NpfsConnectPipe(Fcb); + break; + + case FSCTL_PIPE_PEEK: + DPRINT("Peeking pipe %wZ\n", &Pipe->PipeName); + Status = NpfsPeekPipe(Irp, IoStack); + break; + + case FSCTL_PIPE_QUERY_EVENT: + DPRINT("Query event\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_TRANSCEIVE: + DPRINT("Transceive\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_WAIT: + DPRINT("Waiting for pipe %wZ\n", &Pipe->PipeName); + Status = NpfsWaitPipe(Irp, Fcb); + break; + + case FSCTL_PIPE_IMPERSONATE: + DPRINT("Impersonate\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_SET_CLIENT_PROCESS: + DPRINT("Set client process\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_QUERY_CLIENT_PROCESS: + DPRINT("Query client process\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_GET_STATE: + DPRINT("Get state\n"); + Status = NpfsGetState(Irp, IoStack); + break; + + case FSCTL_PIPE_SET_STATE: + DPRINT("Set state\n"); + Status = NpfsSetState(Irp, IoStack); + break; + + case FSCTL_PIPE_INTERNAL_READ: + DPRINT("Internal read\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_INTERNAL_WRITE: + DPRINT("Internal write\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_INTERNAL_TRANSCEIVE: + DPRINT("Internal transceive\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + case FSCTL_PIPE_INTERNAL_READ_OVFLOW: + DPRINT("Internal read overflow\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + DPRINT("IoControlCode: %x\n", IoStack->Parameters.FileSystemControl.IoControlCode) + Status = STATUS_UNSUCCESSFUL; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/np/npfs.c b/drivers/fs/np/npfs.c new file mode 100644 index 0000000..69f3acd --- /dev/null +++ b/drivers/fs/np/npfs.c @@ -0,0 +1,93 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/np/mount.c + * PURPOSE: Named pipe filesystem + * PROGRAMMER: David Welch + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "npfs.h" + +#define NDEBUG +#include + +NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + PNPFS_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName; + NTSTATUS Status; + + DbgPrint("Named Pipe FSD 0.0.2\n"); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = NpfsCreate; + DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = + NpfsCreateNamedPipe; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = NpfsClose; + DriverObject->MajorFunction[IRP_MJ_READ] = NpfsRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = NpfsWrite; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + NpfsQueryInformation; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = + NpfsSetInformation; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = + NpfsQueryVolumeInformation; +// DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NpfsCleanup; +// DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpfsFlushBuffers; +// DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = +// NpfsDirectoryControl; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + NpfsFileSystemControl; +// DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = +// NpfsQuerySecurity; +// DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = +// NpfsSetSecurity; + + DriverObject->DriverUnload = NULL; + + RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe"); + Status = IoCreateDevice(DriverObject, + sizeof(NPFS_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_NAMED_PIPE, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create named pipe device! (Status %x)\n", Status); + return(Status); + } + + /* initialize the device object */ + DeviceObject->Flags = DO_DIRECT_IO; + + /* initialize the device extension */ + DeviceExtension = DeviceObject->DeviceExtension; + InitializeListHead(&DeviceExtension->PipeListHead); + KeInitializeMutex(&DeviceExtension->PipeListLock, + 0); + + ExInitializeNPagedLookasideList( + &NpfsPipeDataLookasideList, + NULL, + NULL, + 0, + sizeof(NPFS_PIPE_DATA), + TAG('N', 'P', 'D', 'A'), + 0); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/np/npfs.h b/drivers/fs/np/npfs.h new file mode 100644 index 0000000..387a6b5 --- /dev/null +++ b/drivers/fs/np/npfs.h @@ -0,0 +1,96 @@ +/* $Id$ */ + +#ifndef __SERVICES_FS_NP_NPFS_H +#define __SERVICES_FS_NP_NPFS_H + + +typedef struct +{ + LIST_ENTRY PipeListHead; + KMUTEX PipeListLock; +} NPFS_DEVICE_EXTENSION, *PNPFS_DEVICE_EXTENSION; + +typedef struct +{ + LIST_ENTRY ListEntry; + ULONG Size; + PVOID Data; + ULONG Offset; +} NPFS_PIPE_DATA, *PNPFS_PIPE_DATA; + +typedef struct +{ + UNICODE_STRING PipeName; + LIST_ENTRY PipeListEntry; + KSPIN_LOCK FcbListLock; + LIST_ENTRY ServerFcbListHead; + LIST_ENTRY ClientFcbListHead; + ULONG ReferenceCount; + ULONG PipeType; + ULONG PipeReadMode; + ULONG PipeWriteMode; + ULONG PipeBlockMode; + ULONG PipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG OutboundQuota; + LARGE_INTEGER TimeOut; +} NPFS_PIPE, *PNPFS_PIPE; + +typedef struct _NPFS_FCB +{ + LIST_ENTRY FcbListEntry; + struct _NPFS_FCB* OtherSide; + PNPFS_PIPE Pipe; + KEVENT ConnectEvent; + KEVENT ReadEvent; + ULONG PipeEnd; + ULONG PipeState; + ULONG ReadDataAvailable; + ULONG WriteQuotaAvailable; + + LIST_ENTRY DataListHead; /* Data queue */ + KSPIN_LOCK DataListLock; /* Data queue lock */ +} NPFS_FCB, *PNPFS_FCB; + + +extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList; + + +#define KeLockMutex(x) KeWaitForSingleObject(x, \ + UserRequest, \ + KernelMode, \ + FALSE, \ + NULL); + +#define KeUnlockMutex(x) KeReleaseMutex(x, FALSE); + +#define CP DPRINT("\n"); + +static inline VOID +NpfsFreePipeData(PNPFS_PIPE_DATA PipeData) +{ + if (PipeData->Data) + { + ExFreePool(PipeData->Data); + } + ExFreeToNPagedLookasideList(&NpfsPipeDataLookasideList, PipeData); +} + + +NTSTATUS STDCALL NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS STDCALL NpfsSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); + +NTSTATUS STDCALL NpfsQueryVolumeInformation (PDEVICE_OBJECT DeviceObject, PIRP Irp); + +#endif /* __SERVICES_FS_NP_NPFS_H */ diff --git a/drivers/fs/np/npfs.rc b/drivers/fs/np/npfs.rc new file mode 100644 index 0000000..d069799 --- /dev/null +++ b/drivers/fs/np/npfs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Named Pipe IFS Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "npfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "npfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/np/rw.c b/drivers/fs/np/rw.c new file mode 100644 index 0000000..9148b0e --- /dev/null +++ b/drivers/fs/np/rw.c @@ -0,0 +1,308 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/np/rw.c + * PURPOSE: Named pipe filesystem + * PROGRAMMER: David Welch + */ + +/* INCLUDES ******************************************************************/ + +#include +#include "npfs.h" + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +static inline PNPFS_PIPE_DATA +NpfsAllocatePipeData(PVOID Data, + ULONG Size) +{ + PNPFS_PIPE_DATA PipeData; + + PipeData = ExAllocateFromNPagedLookasideList(&NpfsPipeDataLookasideList); + if (!PipeData) + { + return NULL; + } + + PipeData->Data = Data; + PipeData->Size = Size; + PipeData->Offset = 0; + + return PipeData; +} + + +static inline PNPFS_PIPE_DATA +NpfsInitializePipeData( + PVOID Data, + ULONG Size) +{ + PNPFS_PIPE_DATA PipeData; + PVOID Buffer; + + Buffer = ExAllocatePool(NonPagedPool, Size); + if (!Buffer) + { + return NULL; + } + + RtlMoveMemory(Buffer, Data, Size); + + PipeData = NpfsAllocatePipeData(Buffer, Size); + if (!PipeData) + { + ExFreePool(Buffer); + } + + return PipeData; +} + + +NTSTATUS STDCALL +NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + NTSTATUS Status; + PNPFS_DEVICE_EXTENSION DeviceExt; + PWSTR PipeName; + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PNPFS_PIPE_DATA Current; + ULONG Information; + PNPFS_FCB Fcb; + PNPFS_FCB ReadFcb; + PNPFS_PIPE Pipe; + ULONG Length; + PVOID Buffer; + ULONG CopyLength; + + DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + + DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + IoStack = IoGetCurrentIrpStackLocation(Irp); + FileObject = IoStack->FileObject; + Fcb = FileObject->FsContext; + Pipe = Fcb->Pipe; + ReadFcb = Fcb->OtherSide; + + if (ReadFcb == NULL) + { + DPRINT("Pipe is NOT connected!\n"); + Status = STATUS_UNSUCCESSFUL; + Information = 0; + goto done; + } + + if (Irp->MdlAddress == NULL) + { + DPRINT("Irp->MdlAddress == NULL\n"); + Status = STATUS_UNSUCCESSFUL; + Information = 0; + goto done; + } + + Status = STATUS_SUCCESS; + Length = IoStack->Parameters.Read.Length; + Information = 0; + + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + DPRINT("Length %d Buffer %x\n",Length,Buffer); + + KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql); + while (1) + { + /* FIXME: check if in blocking mode */ + if (IsListEmpty(&ReadFcb->DataListHead)) + { + KeResetEvent(&Fcb->ReadEvent); + KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql); + if (Information > 0) + { + Status = STATUS_SUCCESS; + goto done; + } + if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE) + { + Status = STATUS_PIPE_BROKEN; + goto done; + } + /* Wait for ReadEvent to become signaled */ + DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer); + Status = KeWaitForSingleObject(&Fcb->ReadEvent, + UserRequest, + KernelMode, + FALSE, + NULL); + DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status); + KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql); + } + + if (Pipe->PipeReadMode == FILE_PIPE_BYTE_STREAM_MODE) + { + DPRINT("Byte stream mode\n"); + + /* Byte stream mode */ + CurrentEntry = NULL; + while (Length > 0 && !IsListEmpty(&ReadFcb->DataListHead)) + { + CurrentEntry = RemoveHeadList(&ReadFcb->DataListHead); + Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); + + DPRINT("Took pipe data at %p off the queue\n", Current); + + CopyLength = RtlMin(Current->Size, Length); + RtlCopyMemory(Buffer, + ((PVOID)((PVOID)Current->Data + Current->Offset)), + CopyLength); + Buffer += CopyLength; + Length -= CopyLength; + Information += CopyLength; + + /* Update the data buffer */ + Current->Offset += CopyLength; + Current->Size -= CopyLength; + if (Current->Size == 0) + { + NpfsFreePipeData(Current); + CurrentEntry = NULL; + } + } + + if (CurrentEntry && Current->Size > 0) + { + DPRINT("Putting pipe data at %p back in queue\n", Current); + + /* The caller's buffer could not contain the complete message, + so put it back on the queue */ + InsertHeadList(&ReadFcb->DataListHead, &Current->ListEntry); + } + + if (Length == 0) + { + break; + } + } + else + { + DPRINT("Message mode\n"); + + /* Message mode */ + if (!IsListEmpty(&ReadFcb->DataListHead)) + { + CurrentEntry = RemoveHeadList(&ReadFcb->DataListHead); + Current = CONTAINING_RECORD(CurrentEntry, NPFS_PIPE_DATA, ListEntry); + + DPRINT("Took pipe data at %p off the queue\n", Current); + + /* Truncate the message if the receive buffer is too small */ + CopyLength = RtlMin(Current->Size, Length); + RtlCopyMemory(Buffer, Current->Data, CopyLength); + Information = CopyLength; + + Current->Offset += CopyLength; + NpfsFreePipeData(Current); + } + if (Information > 0) + { + break; + } + } + } + /* reset ReaderEvent */ + KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql); + + +done: + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Information; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +NpfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PNPFS_FCB Fcb = NULL; + PNPFS_PIPE Pipe = NULL; + PUCHAR Buffer; + NTSTATUS Status = STATUS_SUCCESS; + ULONG Length; + ULONG Offset; + KIRQL OldIrql; + PNPFS_PIPE_DATA PipeData; + + DPRINT("NpfsWrite()\n"); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + FileObject = IoStack->FileObject; + DPRINT("FileObject %p\n", FileObject); + DPRINT("Pipe name %wZ\n", &FileObject->FileName); + + Fcb = FileObject->FsContext; + Pipe = Fcb->Pipe; + + Length = IoStack->Parameters.Write.Length; + Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart; + + if (Irp->MdlAddress == NULL) + { + DbgPrint ("Irp->MdlAddress == NULL\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + if (Fcb->OtherSide == NULL) + { + DPRINT("Pipe is NOT connected!\n"); + Status = STATUS_UNSUCCESSFUL; + Length = 0; + goto done; + } + + Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress); + DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset); + + PipeData = NpfsInitializePipeData(Buffer, Length); + if (PipeData) + { + DPRINT("Attaching pipe data at %p (%d bytes)\n", PipeData, Length); + + KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql); + InsertTailList(&Fcb->DataListHead, &PipeData->ListEntry); + + /* signal the readers ReadEvent */ + KeSetEvent(&Fcb->OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE); + + KeReleaseSpinLock(&Fcb->DataListLock, OldIrql); + + } + else + { + Length = 0; + Status = STATUS_INSUFFICIENT_RESOURCES; + } + +done: + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/np/volume.c b/drivers/fs/np/volume.c new file mode 100644 index 0000000..1378c8b --- /dev/null +++ b/drivers/fs/np/volume.c @@ -0,0 +1,120 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/npfs/volume.c + * PURPOSE: Named pipe filesystem + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "npfs.h" + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +NpfsQueryFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, + PULONG BufferLength) +{ + DPRINT("NpfsQueryFsDeviceInformation()\n"); + DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); + + if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + FsDeviceInfo->DeviceType = FILE_DEVICE_NAMED_PIPE; + FsDeviceInfo->Characteristics = 0; + + *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); + + DPRINT("NpfsQueryFsDeviceInformation() finished.\n"); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NpfsQueryFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, + PULONG BufferLength) +{ + DPRINT("NpfsQueryFsAttributeInformation() called.\n"); + DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); + + if (*BufferLength < sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8) + return(STATUS_BUFFER_OVERFLOW); + + FsAttributeInfo->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; + FsAttributeInfo->MaximumComponentNameLength = 255; + FsAttributeInfo->FileSystemNameLength = 8; + wcscpy(FsAttributeInfo->FileSystemName, + L"NPFS"); + + DPRINT("NpfsQueryFsAttributeInformation() finished.\n"); + *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NpfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + FS_INFORMATION_CLASS FsInformationClass; + NTSTATUS Status = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + /* PRECONDITION */ + assert(DeviceObject != NULL); + assert(Irp != NULL); + + DPRINT("NpfsQueryVolumeInformation(DeviceObject %x, Irp %x)\n", + DeviceObject, + Irp); + + Stack = IoGetCurrentIrpStackLocation (Irp); + FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass; + BufferLength = Stack->Parameters.QueryVolume.Length; + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + + DPRINT("FsInformationClass %d\n", FsInformationClass); + DPRINT("SystemBuffer %x\n", SystemBuffer); + + switch (FsInformationClass) + { + case FileFsDeviceInformation: + Status = NpfsQueryFsDeviceInformation(SystemBuffer, + &BufferLength); + break; + + case FileFsAttributeInformation: + Status = NpfsQueryFsAttributeInformation(SystemBuffer, + &BufferLength); + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryVolume.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/.cvsignore b/drivers/fs/ntfs/.cvsignore new file mode 100644 index 0000000..56392de --- /dev/null +++ b/drivers/fs/ntfs/.cvsignore @@ -0,0 +1,6 @@ +base.tmp +junk.tmp +temp.exp +ntfs.coff +ntfs.sys.unstripped +*.d \ No newline at end of file diff --git a/drivers/fs/ntfs/attrib.c b/drivers/fs/ntfs/attrib.c new file mode 100644 index 0000000..3d3c062 --- /dev/null +++ b/drivers/fs/ntfs/attrib.c @@ -0,0 +1,217 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/attrib.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +VOID +NtfsDumpAttribute(PATTRIBUTE Attribute) +{ + PNONRESIDENT_ATTRIBUTE NresAttr; + PRESIDENT_ATTRIBUTE ResAttr; + UNICODE_STRING Name; + PUCHAR Ptr; + UCHAR RunHeader; + ULONG RunLength; + ULONG RunStart; + + switch (Attribute->AttributeType) + { + case AttributeStandardInformation: + DbgPrint(" $STANDARD_INFORMATION "); + break; + + case AttributeAttributeList: + DbgPrint(" $ATTRIBUTE_LIST "); + break; + + case AttributeFileName: + DbgPrint(" $FILE_NAME "); + break; + + case AttributeObjectId: + DbgPrint(" $OBJECT_ID "); + break; + + case AttributeSecurityDescriptor: + DbgPrint(" $SECURITY_DESCRIPTOR "); + break; + + case AttributeVolumeName: + DbgPrint(" $VOLUME_NAME "); + break; + + case AttributeVolumeInformation: + DbgPrint(" $VOLUME_INFORMATION "); + break; + + case AttributeData: + DbgPrint(" $DATA "); + break; + + case AttributeIndexRoot: + DbgPrint(" $INDEX_ROOT "); + break; + + case AttributeIndexAllocation: + DbgPrint(" $INDEX_ALLOCATION "); + break; + + case AttributeBitmap: + DbgPrint(" $BITMAP "); + break; + + case AttributeReparsePoint: + DbgPrint(" $REPARSE_POINT "); + break; + + case AttributeEAInformation: + DbgPrint(" $EA_INFORMATION "); + break; + + case AttributeEA: + DbgPrint(" $EA "); + break; + + case AttributePropertySet: + DbgPrint(" $PROPERTY_SET "); + break; + + case AttributeLoggedUtilityStream: + DbgPrint(" $LOGGED_UTILITY_STREAM "); + break; + + default: + DbgPrint(" Attribute %lx ", + Attribute->AttributeType); + break; + } + + if (Attribute->NameLength != 0) + { + Name.Length = Attribute->NameLength * sizeof(WCHAR); + Name.MaximumLength = Name.Length; + Name.Buffer = (PWCHAR)((ULONG)Attribute + Attribute->NameOffset); + + DbgPrint("'%wZ' ", &Name); + } + + DbgPrint("(%s)\n", + Attribute->Nonresident ? "nonresident" : "resident"); + + if (Attribute->Nonresident != 0) + { + NresAttr = (PNONRESIDENT_ATTRIBUTE)Attribute; + Ptr = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset); + while (*Ptr != 0) + { + RunHeader = *Ptr++; + + switch (RunHeader & 0x0F) + { + case 1: + RunLength = (ULONG)*Ptr++; + break; + + case 2: + RunLength = *((PUSHORT)Ptr); + Ptr += 2; + break; + + case 3: + RunLength = *Ptr++; + RunLength += *Ptr++ << 8; + RunLength += *Ptr++ << 16; + break; + + case 4: + RunLength = *((PULONG)Ptr); + Ptr += 4; + break; + + default: + DbgPrint("RunLength size of %hu not implemented!\n", RunHeader & 0x0F); + KeBugCheck(0); + } + + switch (RunHeader >> 4) + { + case 1: + RunStart = (ULONG)*Ptr; + Ptr++; + break; + + case 2: + RunStart = *((PUSHORT)Ptr); + Ptr += 2; + break; + + case 3: + RunStart = *Ptr++; + RunStart += *Ptr++ << 8; + RunStart += *Ptr++ << 16; + break; + + case 4: + RunStart = *((PULONG)Ptr); + Ptr += 4; + break; + + default: + DbgPrint("RunStart size of %hu not implemented!\n", RunHeader >> 4); + KeBugCheck(0); + } + + DbgPrint(" AllocatedSize %I64d DataSize %I64d\n", NresAttr->AllocatedSize, NresAttr->DataSize); +// DbgPrint(" Run: Header %hx Start %lu Length %lu\n", RunHeader, RunStart, RunLength); + if (RunLength == 1) + { + DbgPrint(" logical sector %lu (0x%lx)\n", RunStart, RunStart); + } + else + { + DbgPrint(" logical sectors %lu-%lu (0x%lx-0x%lx)\n", + RunStart, RunStart + RunLength - 1, + RunStart, RunStart + RunLength - 1); + } + } + } + + +} + + +/* EOF */ diff --git a/drivers/fs/ntfs/blockdev.c b/drivers/fs/ntfs/blockdev.c new file mode 100644 index 0000000..d2f3311 --- /dev/null +++ b/drivers/fs/ntfs/blockdev.c @@ -0,0 +1,255 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/blockdev.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN ULONG SectorSize, + IN OUT PUCHAR Buffer) +{ + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER Offset; + ULONG BlockSize; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize; + BlockSize = SectorCount * SectorSize; + + DPRINT("NtfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", + DeviceObject, DiskSector, Buffer); + DPRINT("Offset %I64x BlockSize %ld\n", + Offset.QuadPart, + BlockSize); + + DPRINT("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + Buffer, + BlockSize, + &Offset, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT("Getting IO Status... for %x\n", Irp); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS(Status)) + { + if (Status == STATUS_VERIFY_REQUIRED) + { + PDEVICE_OBJECT DeviceToVerify; + NTSTATUS NewStatus; + + DPRINT1("STATUS_VERIFY_REQUIRED\n"); + DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread()); + IoSetDeviceToVerify(PsGetCurrentThread(), NULL); + + NewStatus = IoVerifyVolume(DeviceToVerify, FALSE); + DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus); + } + + DPRINT("NtfsReadSectors() failed (Status %x)\n", Status); + DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n", + DeviceObject, DiskSector, Buffer, + Offset.QuadPart); + return(Status); + } + + DPRINT("Block request succeeded for %x\n", Irp); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN ULONG SectorSize, + IN OUT PUCHAR Buffer) +{ + PIO_STACK_LOCATION Stack; + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER Offset; + ULONG BlockSize; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize; + BlockSize = SectorCount * SectorSize; + + DPRINT("NtfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n", + DeviceObject, DiskSector, Buffer); + DPRINT("Offset %I64x BlockSize %ld\n", + Offset.QuadPart, + BlockSize); + + DPRINT("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + Buffer, + BlockSize, + &Offset, + &Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + +// Stack = IoGetCurrentIrpStackLocation(Irp); +// Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT("Getting IO Status... for %x\n", Irp); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS(Status)) + { + DPRINT("NtfsReadSectors() failed (Status %x)\n", Status); + DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n", + DeviceObject, DiskSector, Buffer, + Offset.QuadPart); + return(Status); + } + + DPRINT("Block request succeeded for %x\n", Irp); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, + IN ULONG ControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize) +{ + ULONG BufferSize = 0; + PKEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + if (OutputBufferSize != NULL) + { + BufferSize = *OutputBufferSize; + } + + Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); + if (Event == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + KeInitializeEvent(Event, NotificationEvent, FALSE); + + DPRINT("Building device I/O control request ...\n"); + Irp = IoBuildDeviceIoControlRequest(ControlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + BufferSize, + FALSE, + Event, + &IoStatus); + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest() failed\n"); + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + DPRINT("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + if (OutputBufferSize) + { + *OutputBufferSize = BufferSize; + } + + ExFreePool(Event); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/create.c b/drivers/fs/ntfs/create.c new file mode 100644 index 0000000..ade3d61 --- /dev/null +++ b/drivers/fs/ntfs/create.c @@ -0,0 +1,243 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/create.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject, + PWSTR pRelativeFileName, + PWSTR *pAbsoluteFilename) +{ + PWSTR rcName; + PFCB Fcb; + PCCB Ccb; + + DPRINT("try related for %S\n", pRelativeFileName); + Ccb = pFileObject->FsContext2; + assert(Ccb); + Fcb = Ccb->Fcb; + assert(Fcb); + + /* verify related object is a directory and target name + don't start with \. */ + if (NtfsFCBIsDirectory(Fcb) == FALSE || + pRelativeFileName[0] == L'\\') + { + return(STATUS_INVALID_PARAMETER); + } + + /* construct absolute path name */ + assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 + <= MAX_PATH); + rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR)); + if (!rcName) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + wcscpy(rcName, Fcb->PathName); + if (!NtfsFCBIsRoot(Fcb)) + wcscat (rcName, L"\\"); + wcscat (rcName, pRelativeFileName); + *pAbsoluteFilename = rcName; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsOpenFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PWSTR FileName) +/* + * FUNCTION: Opens a file + */ +{ + PFCB ParentFcb; + PFCB Fcb; + NTSTATUS Status; + PWSTR AbsFileName = NULL; + + DPRINT("NtfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName); + + if (FileObject->RelatedFileObject) + { + DPRINT("Converting relative filename to absolute filename\n"); + + Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject, + FileName, + &AbsFileName); + FileName = AbsFileName; + if (!NT_SUCCESS(Status)) + { + return(Status); + } + return(STATUS_UNSUCCESSFUL); + } + + //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators) + + DPRINT("PathName to open: %S\n", FileName); + + /* try first to find an existing FCB in memory */ + DPRINT("Checking for existing FCB in memory\n"); + Fcb = NtfsGrabFCBFromTable(DeviceExt, + FileName); + if (Fcb == NULL) + { + DPRINT("No existing FCB found, making a new one if file exists.\n"); + Status = NtfsGetFCBForFile(DeviceExt, + &ParentFcb, + &Fcb, + FileName); + if (ParentFcb != NULL) + { + NtfsReleaseFCB(DeviceExt, + ParentFcb); + } + + if (!NT_SUCCESS (Status)) + { + DPRINT("Could not make a new FCB, status: %x\n", Status); + + if (AbsFileName) + ExFreePool(AbsFileName); + + return(Status); + } + } + + DPRINT("Attaching FCB to fileObject\n"); + Status = NtfsAttachFCBToFileObject(DeviceExt, + Fcb, + FileObject); + + if (AbsFileName) + ExFreePool (AbsFileName); + + return(Status); +} + + +static NTSTATUS +NtfsCreateFile(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Opens a file + */ +{ + PDEVICE_EXTENSION DeviceExt; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + ULONG RequestedDisposition; + ULONG RequestedOptions; + PFCB Fcb; +// PWSTR FileName; + NTSTATUS Status; + + DPRINT("NtfsCreateFile() called\n"); + + DeviceExt = DeviceObject->DeviceExtension; + assert (DeviceExt); + Stack = IoGetCurrentIrpStackLocation (Irp); + assert (Stack); + + RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff); +// RequestedOptions = +// Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; +// PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE; +// if ((RequestedOptions & FILE_DIRECTORY_FILE) +// && RequestedDisposition == FILE_SUPERSEDE) +// return STATUS_INVALID_PARAMETER; + + FileObject = Stack->FileObject; + + if (RequestedDisposition == FILE_CREATE || + RequestedDisposition == FILE_OVERWRITE_IF || + RequestedDisposition == FILE_SUPERSEDE) + { + return(STATUS_ACCESS_DENIED); + } + + Status = NtfsOpenFile(DeviceExt, + FileObject, + FileObject->FileName.Buffer); + + /* + * If the directory containing the file to open doesn't exist then + * fail immediately + */ + Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0; + Irp->IoStatus.Status = Status; + + return(Status); +} + + +NTSTATUS STDCALL +NtfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status; + + if (DeviceObject == NtfsGlobalData->DeviceObject) + { + /* DeviceObject represents FileSystem instead of logical volume */ + DPRINT("Opening file system\n"); + Irp->IoStatus.Information = FILE_OPENED; + Status = STATUS_SUCCESS; + goto ByeBye; + } + + DeviceExt = DeviceObject->DeviceExtension; + + ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, + TRUE); + Status = NtfsCreateFile(DeviceObject, + Irp); + ExReleaseResourceLite(&DeviceExt->DirResource); + +ByeBye: + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, + NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/dirctl.c b/drivers/fs/ntfs/dirctl.c new file mode 100644 index 0000000..2646066 --- /dev/null +++ b/drivers/fs/ntfs/dirctl.c @@ -0,0 +1,709 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/dirctl.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +#if 0 +static NTSTATUS +CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt, + PVOID *Context, + PVOID *Block, + PLARGE_INTEGER StreamOffset, + ULONG DirLength, + PVOID *Ptr, + PWSTR Name, + PULONG pIndex, + PULONG pIndex2) +/* + * FUNCTION: Retrieves the file name, be it in short or long file name format + */ +{ + PDIR_RECORD Record; + NTSTATUS Status; + ULONG Index = 0; + ULONG Offset = 0; + ULONG BlockOffset = 0; + + Record = (PDIR_RECORD)*Block; + while(Index < *pIndex) + { + BlockOffset += Record->RecordLength; + Offset += Record->RecordLength; + + Record = (PDIR_RECORD)(*Block + BlockOffset); + if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0) + { + DPRINT("Map next sector\n"); + CcUnpinData(*Context); + StreamOffset->QuadPart += BLOCKSIZE; + Offset = ROUND_UP(Offset, BLOCKSIZE); + BlockOffset = 0; + + if (!CcMapData(DeviceExt->StreamFileObject, + StreamOffset, + BLOCKSIZE, TRUE, + Context, Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + Record = (PDIR_RECORD)(*Block + BlockOffset); + } + + if (Offset >= DirLength) + return(STATUS_NO_MORE_ENTRIES); + + Index++; + } + + DPRINT("Index %lu RecordLength %lu Offset %lu\n", + Index, Record->RecordLength, Offset); + + if (Record->FileIdLength == 1 && Record->FileId[0] == 0) + { + wcscpy(Name, L"."); + } + else if (Record->FileIdLength == 1 && Record->FileId[0] == 1) + { + wcscpy(Name, L".."); + } + else + { + if (DeviceExt->CdInfo.JolietLevel == 0) + { + ULONG i; + + for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++) + Name[i] = (WCHAR)Record->FileId[i]; + Name[i] = 0; + } + else + { + CdfsSwapString(Name, Record->FileId, Record->FileIdLength); + } + } + + DPRINT("Name '%S'\n", Name); + + *Ptr = Record; + + *pIndex = Index; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsFindFile(PDEVICE_EXTENSION DeviceExt, + PFCB Fcb, + PFCB Parent, + PWSTR FileToFind, + PULONG pDirIndex, + PULONG pDirIndex2) +/* + * FUNCTION: Find a file + */ +{ + WCHAR name[256]; + WCHAR TempStr[2]; + PVOID Block; + NTSTATUS Status; + ULONG len; + ULONG DirIndex; + ULONG Offset; + ULONG Read; + BOOLEAN IsRoot; + PVOID Context = NULL; + ULONG DirSize; + PUCHAR Ptr; + PDIR_RECORD Record; + LARGE_INTEGER StreamOffset; + + DPRINT("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", + Parent, FileToFind, pDirIndex ? *pDirIndex : 0); + DPRINT("FindFile: old Pathname %x, old Objectname %x)\n", + Fcb->PathName, Fcb->ObjectName); + + IsRoot = FALSE; + DirIndex = 0; + if (wcslen (FileToFind) == 0) + { + CHECKPOINT; + TempStr[0] = (WCHAR) '.'; + TempStr[1] = 0; + FileToFind = (PWSTR)&TempStr; + } + + if (Parent) + { + if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart) + { + IsRoot = TRUE; + } + } + else + { + IsRoot = TRUE; + } + + if (IsRoot == TRUE) + { + StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE; + DirSize = DeviceExt->CdInfo.RootSize; + + + if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0) + || (FileToFind[0] == '.' && FileToFind[1] == 0)) + { + /* it's root : complete essentials fields then return ok */ + RtlZeroMemory(Fcb, sizeof(FCB)); + + Fcb->PathName[0]='\\'; + Fcb->ObjectName = &Fcb->PathName[1]; + Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart; + Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize; + Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY; + + if (pDirIndex) + *pDirIndex = 0; + if (pDirIndex2) + *pDirIndex2 = 0; + DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName); + return (STATUS_SUCCESS); + } + } + else + { + StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE; + DirSize = Parent->Entry.DataLengthL; + } + + DPRINT("StreamOffset %I64u DirSize %lu\n", StreamOffset.QuadPart, DirSize); + + if (pDirIndex && (*pDirIndex)) + DirIndex = *pDirIndex; + + if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset, + BLOCKSIZE, TRUE, &Context, &Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + + Ptr = (PUCHAR)Block; + while(TRUE) + { + Record = (PDIR_RECORD)Ptr; + if (Record->RecordLength == 0) + { + DPRINT1("Stopped!\n"); + break; + } + + DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n", + Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength); + + Status = CdfsGetEntryName(DeviceExt, &Context, &Block, &StreamOffset, + DirSize, (PVOID*)&Ptr, name, &DirIndex, pDirIndex2); + if (Status == STATUS_NO_MORE_ENTRIES) + { + break; + } + else if (Status == STATUS_UNSUCCESSFUL) + { + /* Note: the directory cache has already been unpinned */ + return(Status); + } + + DPRINT("Name '%S'\n", name); + + if (wstrcmpjoki(name, FileToFind)) /* || wstrcmpjoki (name2, FileToFind)) */ + { + if (Parent && Parent->PathName) + { + len = wcslen(Parent->PathName); + memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR)); + Fcb->ObjectName=&Fcb->PathName[len]; + if (len != 1 || Fcb->PathName[0] != '\\') + { + Fcb->ObjectName[0] = '\\'; + Fcb->ObjectName = &Fcb->ObjectName[1]; + } + } + else + { + Fcb->ObjectName=Fcb->PathName; + Fcb->ObjectName[0]='\\'; + Fcb->ObjectName=&Fcb->ObjectName[1]; + } + + DPRINT("PathName '%S' ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName); + + memcpy(&Fcb->Entry, Ptr, sizeof(DIR_RECORD)); + wcsncpy(Fcb->ObjectName, name, MAX_PATH); + if (pDirIndex) + *pDirIndex = DirIndex; + + DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n", + Fcb->PathName, Fcb->ObjectName, DirIndex); + + CcUnpinData(Context); + + return(STATUS_SUCCESS); + } + + + Ptr = Ptr + Record->RecordLength; + DirIndex++; + + if (((ULONG)Ptr - (ULONG)Block) >= DirSize) + { + DPRINT("Stopped!\n"); + break; + } + } + + CcUnpinData(Context); + + if (pDirIndex) + *pDirIndex = DirIndex; + + return(STATUS_UNSUCCESSFUL); +} + + +static NTSTATUS +CdfsGetNameInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_NAMES_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetNameInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetDirectoryInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + /* Convert file flags */ + CdfsFileFlagsToAttributes(Fcb, + &Info->FileAttributes); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + +// Info->FileIndex=; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetFullDirectoryInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_FULL_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetFullDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + /* Convert file flags */ + CdfsFileFlagsToAttributes(Fcb, + &Info->FileAttributes); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + +// Info->FileIndex=; + Info->EaSize = 0; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +CdfsGetBothDirectoryInformation(PFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_BOTH_DIRECTORY_INFORMATION Info, + ULONG BufferLength) +{ + ULONG Length; + + DPRINT("CdfsGetBothDirectoryInformation() called\n"); + + Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return(STATUS_BUFFER_OVERFLOW); + + Info->FileNameLength = Length; + Info->NextEntryOffset = + ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4); + memcpy(Info->FileName, Fcb->ObjectName, Length); + + /* Convert file times */ + CdfsDateTimeToFileTime(Fcb, + &Info->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &Info->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &Info->ChangeTime); + + /* Convert file flags */ + CdfsFileFlagsToAttributes(Fcb, + &Info->FileAttributes); + + Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL; + + /* Make AllocSize a rounded up multiple of the sector size */ + Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE); + +// Info->FileIndex=; + Info->EaSize = 0; + + if (DeviceExt->CdInfo.JolietLevel == 0) + { + /* Standard ISO-9660 format */ + Info->ShortNameLength = Length; + memcpy(Info->ShortName, Fcb->ObjectName, Length); + } + else + { + /* Joliet extension */ + + /* FIXME: Copy or create a short file name */ + + Info->ShortName[0] = 0; + Info->ShortNameLength = 0; + } + + return(STATUS_SUCCESS); +} +#endif + +static NTSTATUS +NtfsQueryDirectory(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + LONG BufferLength = 0; + PUNICODE_STRING SearchPattern = NULL; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG FileIndex = 0; + PUCHAR Buffer = NULL; + PFILE_NAMES_INFORMATION Buffer0 = NULL; + PFCB Fcb; + PCCB Ccb; + FCB TempFcb; + BOOLEAN First = FALSE; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT1("NtfsQueryDirectory() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + FileObject = Stack->FileObject; + + Ccb = (PCCB)FileObject->FsContext2; + Fcb = Ccb->Fcb; + + /* Obtain the callers parameters */ + BufferLength = Stack->Parameters.QueryDirectory.Length; + SearchPattern = Stack->Parameters.QueryDirectory.FileName; + FileInformationClass = + Stack->Parameters.QueryDirectory.FileInformationClass; + FileIndex = Stack->Parameters.QueryDirectory.FileIndex; + + + if (SearchPattern != NULL) + { + if (!Ccb->DirectorySearchPattern) + { + First = TRUE; + Ccb->DirectorySearchPattern = + ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR)); + if (!Ccb->DirectorySearchPattern) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + memcpy(Ccb->DirectorySearchPattern, + SearchPattern->Buffer, + SearchPattern->Length); + Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0; + } + } + else if (!Ccb->DirectorySearchPattern) + { + First = TRUE; + Ccb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); + if (!Ccb->DirectorySearchPattern) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + Ccb->DirectorySearchPattern[0] = L'*'; + Ccb->DirectorySearchPattern[1] = 0; + } + DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern); + + /* Determine directory index */ + if (Stack->Flags & SL_INDEX_SPECIFIED) + { + Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart; + } + else if (First || (Stack->Flags & SL_RESTART_SCAN)) + { + Ccb->Entry = 0; + } + + /* Determine Buffer for result */ + if (Irp->MdlAddress) + { + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + } + else + { + Buffer = Irp->UserBuffer; + } + DPRINT("Buffer=%x tofind=%S\n", Buffer, Ccb->DirectorySearchPattern); +#if 0 + TempFcb.ObjectName = TempFcb.PathName; + while (Status == STATUS_SUCCESS && BufferLength > 0) + { + Status = CdfsFindFile(DeviceExtension, + &TempFcb, + Fcb, + Ccb->DirectorySearchPattern, + &Ccb->Entry, + NULL); + DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry); + + if (NT_SUCCESS(Status)) + { + switch (FileInformationClass) + { + case FileNameInformation: + Status = CdfsGetNameInformation(&TempFcb, + DeviceExtension, + (PFILE_NAMES_INFORMATION)Buffer, + BufferLength); + break; + + case FileDirectoryInformation: + Status = CdfsGetDirectoryInformation(&TempFcb, + DeviceExtension, + (PFILE_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + case FileFullDirectoryInformation: + Status = CdfsGetFullDirectoryInformation(&TempFcb, + DeviceExtension, + (PFILE_FULL_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + case FileBothDirectoryInformation: + Status = NtfsGetBothDirectoryInformation(&TempFcb, + DeviceExtension, + (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer, + BufferLength); + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + + if (Status == STATUS_BUFFER_OVERFLOW) + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + break; + } + } + else + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + + if (First) + { + Status = STATUS_NO_SUCH_FILE; + } + else + { + Status = STATUS_NO_MORE_FILES; + } + break; + } + + Buffer0 = (PFILE_NAMES_INFORMATION)Buffer; + Buffer0->FileIndex = FileIndex++; + Ccb->Entry++; + + if (Stack->Flags & SL_RETURN_SINGLE_ENTRY) + { + break; + } + BufferLength -= Buffer0->NextEntryOffset; + Buffer += Buffer0->NextEntryOffset; + } +#endif + + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + + if (FileIndex > 0) + { + Status = STATUS_SUCCESS; + } + + return(Status); +} + + + +NTSTATUS STDCALL +NtfsDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT1("NtfsDirectoryControl() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_QUERY_DIRECTORY: + Status = NtfsQueryDirectory(DeviceObject, + Irp); + break; + + case IRP_MN_NOTIFY_CHANGE_DIRECTORY: + DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + DPRINT1("NTFS: MinorFunction %d\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/fcb.c b/drivers/fs/ntfs/fcb.c new file mode 100644 index 0000000..45f8861 --- /dev/null +++ b/drivers/fs/ntfs/fcb.c @@ -0,0 +1,674 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/fcb.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "ntfs.h" + + +/* MACROS *******************************************************************/ + +#define TAG_FCB TAG('I', 'F', 'C', 'B') + + + +/* FUNCTIONS ****************************************************************/ + +static PWCHAR +NtfsGetNextPathElement(PWCHAR FileName) +{ + if (*FileName == L'\0') + { + return(NULL); + } + + while (*FileName != L'\0' && *FileName != L'\\') + { + FileName++; + } + + return(FileName); +} + + +static VOID +NtfsWSubString(PWCHAR pTarget, const PWCHAR pSource, size_t pLength) +{ + wcsncpy (pTarget, pSource, pLength); + pTarget [pLength] = L'\0'; +} + + +PFCB +NtfsCreateFCB(PWSTR FileName) +{ + PFCB Fcb; + + Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB); + RtlZeroMemory(Fcb, sizeof(FCB)); + + if (FileName) + { + wcscpy(Fcb->PathName, FileName); + if (wcsrchr(Fcb->PathName, '\\') != 0) + { + Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\'); + } + else + { + Fcb->ObjectName = Fcb->PathName; + } + } + + ExInitializeResourceLite(&Fcb->MainResource); + + return(Fcb); +} + + +VOID +NtfsDestroyFCB(PFCB Fcb) +{ + ExDeleteResourceLite(&Fcb->MainResource); + + ExFreePool(Fcb); +} + + +BOOLEAN +NtfsFCBIsDirectory(PFCB Fcb) +{ +// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY); +// return(Fcb->Entry.FileFlags & 0x02); + return(TRUE); +} + + +BOOLEAN +NtfsFCBIsRoot(PFCB Fcb) +{ + return(wcscmp(Fcb->PathName, L"\\") == 0); +} + + +VOID +NtfsGrabFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + DPRINT("grabbing FCB at %x: %S, refCount:%d\n", + Fcb, + Fcb->PathName, + Fcb->RefCount); + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +VOID +NtfsReleaseFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + DPRINT("releasing FCB at %x: %S, refCount:%d\n", + Fcb, + Fcb->PathName, + Fcb->RefCount); + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->RefCount--; + if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb)) + { + RemoveEntryList(&Fcb->FcbListEntry); + CcRosReleaseFileCache(NULL, Fcb->RFCB.Bcb); + NtfsDestroyFCB(Fcb); + } + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +VOID +NtfsAddFCBToTable(PDEVICE_EXTENSION Vcb, + PFCB Fcb) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + Fcb->DevExt = Vcb; + InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry); + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); +} + + +PFCB +NtfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb, + PWSTR FileName) +{ + KIRQL oldIrql; + PFCB Fcb; + PLIST_ENTRY current_entry; + + KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql); + + if (FileName == NULL || *FileName == 0) + { + DPRINT("Return FCB for stream file object\n"); + Fcb = ((PCCB)Vcb->StreamFileObject->FsContext2)->Fcb; + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + return(Fcb); + } + + current_entry = Vcb->FcbListHead.Flink; + while (current_entry != &Vcb->FcbListHead) + { + Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry); + + DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName); + if (_wcsicmp(FileName, Fcb->PathName) == 0) + { + Fcb->RefCount++; + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + return(Fcb); + } + + //FIXME: need to compare against short name in FCB here + + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql); + + return(NULL); +} + + +NTSTATUS +NtfsFCBInitializeCache(PVCB Vcb, + PFCB Fcb) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + PCCB newCCB; + + FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice); + + newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); + if (newCCB == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + RtlZeroMemory(newCCB, + sizeof(CCB)); + + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = (PVOID) &Fcb->RFCB; + FileObject->FsContext2 = newCCB; + newCCB->Fcb = Fcb; + newCCB->PtrFileObject = FileObject; + Fcb->FileObject = FileObject; + Fcb->DevExt = Vcb; + + Status = CcRosInitializeFileCache(FileObject, + &Fcb->RFCB.Bcb, + CACHEPAGESIZE(Vcb)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + KeBugCheck(0); + } + + ObDereferenceObject(FileObject); + Fcb->Flags |= FCB_CACHE_INITIALIZED; + + return(Status); +} + + +PFCB +NtfsMakeRootFCB(PDEVICE_EXTENSION Vcb) +{ + PFCB Fcb; + + Fcb = NtfsCreateFCB(L"\\"); + +// memset(Fcb->entry.Filename, ' ', 11); + +// Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize; +// Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart; +// Fcb->Entry.FileFlags = 0x02; // FILE_ATTRIBUTE_DIRECTORY; + Fcb->RefCount = 1; + Fcb->DirIndex = 0; + Fcb->RFCB.FileSize.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize; + Fcb->RFCB.ValidDataLength.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize; + Fcb->RFCB.AllocationSize.QuadPart = PAGE_SIZE;//Vcb->CdInfo.RootSize; + + NtfsFCBInitializeCache(Vcb, Fcb); + NtfsAddFCBToTable(Vcb, Fcb); + NtfsGrabFCB(Vcb, Fcb); + + return(Fcb); +} + + +PFCB +NtfsOpenRootFCB(PDEVICE_EXTENSION Vcb) +{ + PFCB Fcb; + + Fcb = NtfsGrabFCBFromTable(Vcb, L"\\"); + if (Fcb == NULL) + { + Fcb = NtfsMakeRootFCB(Vcb); + } + + return(Fcb); +} + + +#if 0 +static VOID +NtfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt, + PDIR_RECORD Record, + PWSTR Name) +/* + * FUNCTION: Retrieves the file name, be it in short or long file name format + */ +{ + if (Record->FileIdLength == 1 && Record->FileId[0] == 0) + { + wcscpy(Name, L"."); + } + else if (Record->FileIdLength == 1 && Record->FileId[0] == 1) + { + wcscpy(Name, L".."); + } + else + { + if (DeviceExt->CdInfo.JolietLevel == 0) + { + ULONG i; + + for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++) + Name[i] = (WCHAR)Record->FileId[i]; + Name[i] = 0; + } + else + { + CdfsSwapString(Name, Record->FileId, Record->FileIdLength); + } + } + + DPRINT("Name '%S'\n", Name); +} + + +NTSTATUS +NtfsMakeFCBFromDirEntry(PVCB Vcb, + PFCB DirectoryFCB, + PWSTR Name, + PDIR_RECORD Record, + PFCB * fileFCB) +{ + WCHAR pathName[MAX_PATH]; + PFCB rcFCB; + ULONG Size; + + if (Name [0] != 0 && wcslen (DirectoryFCB->PathName) + + sizeof(WCHAR) + wcslen (Name) > MAX_PATH) + { + return(STATUS_OBJECT_NAME_INVALID); + } + + wcscpy(pathName, DirectoryFCB->PathName); + if (!CdfsFCBIsRoot(DirectoryFCB)) + { + wcscat(pathName, L"\\"); + } + + if (Name[0] != 0) + { + wcscat(pathName, Name); + } + else + { + WCHAR entryName[MAX_PATH]; + + CdfsGetDirEntryName(Vcb, Record, entryName); + wcscat(pathName, entryName); + } + + rcFCB = CdfsCreateFCB(pathName); + memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD)); + + Size = rcFCB->Entry.DataLengthL; + + rcFCB->RFCB.FileSize.QuadPart = Size; + rcFCB->RFCB.ValidDataLength.QuadPart = Size; + rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE); +// DPRINT1("%S %d %d\n", longName, Size, (ULONG)rcFCB->RFCB.AllocationSize.QuadPart); + CdfsFCBInitializeCache(Vcb, rcFCB); + rcFCB->RefCount++; + CdfsAddFCBToTable(Vcb, rcFCB); + *fileFCB = rcFCB; + + return(STATUS_SUCCESS); +} +#endif + + +NTSTATUS +NtfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, + PFCB Fcb, + PFILE_OBJECT FileObject) +{ + NTSTATUS Status; + PCCB newCCB; + + newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB); + if (newCCB == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + memset(newCCB, 0, sizeof(CCB)); + + FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + FileObject->FsContext = (PVOID)&Fcb->RFCB; + FileObject->FsContext2 = newCCB; + newCCB->Fcb = Fcb; + newCCB->PtrFileObject = FileObject; + Fcb->DevExt = Vcb; + + if (!(Fcb->Flags & FCB_CACHE_INITIALIZED)) + { + Status = CcRosInitializeFileCache(FileObject, + &Fcb->RFCB.Bcb, + CACHEPAGESIZE(Vcb)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CcRosInitializeFileCache failed\n"); + KeBugCheck(0); + } + Fcb->Flags |= FCB_CACHE_INITIALIZED; + } + + DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL); + + return(STATUS_SUCCESS); +} + + +#if 0 +NTSTATUS +NtfsDirFindFile(PDEVICE_EXTENSION DeviceExt, + PFCB DirectoryFcb, + PWSTR FileToFind, + PFCB *FoundFCB) +{ + WCHAR TempName[2]; + WCHAR Name[256]; + PVOID Block; + ULONG FirstSector; + ULONG DirSize; + PDIR_RECORD Record; + ULONG Offset; + ULONG BlockOffset; + NTSTATUS Status; + + LARGE_INTEGER StreamOffset; + PVOID Context; + + assert(DeviceExt); + assert(DirectoryFcb); + assert(FileToFind); + + DPRINT("CdfsDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n", + DeviceExt, + DirectoryFcb, + FileToFind); + DPRINT("Dir Path:%S\n", DirectoryFcb->PathName); + + /* default to '.' if no filename specified */ + if (wcslen(FileToFind) == 0) + { + TempName[0] = L'.'; + TempName[1] = 0; + FileToFind = TempName; + } + + DirSize = DirectoryFcb->Entry.DataLengthL; + StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE; + + if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset, + BLOCKSIZE, TRUE, &Context, &Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + + Offset = 0; + BlockOffset = 0; + Record = (PDIR_RECORD)Block; + while(TRUE) + { + if (Record->RecordLength == 0) + { + DPRINT("RecordLength == 0 Stopped!\n"); + break; + } + + DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n", + Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength); + + CdfsGetDirEntryName(DeviceExt, Record, Name); + DPRINT("Name '%S'\n", Name); + + if (wstrcmpjoki(Name, FileToFind)) + { + DPRINT("Match found, %S\n", Name); + Status = CdfsMakeFCBFromDirEntry(DeviceExt, + DirectoryFcb, + Name, + Record, + FoundFCB); + + CcUnpinData(Context); + + return(Status); + } + + Offset += Record->RecordLength; + BlockOffset += Record->RecordLength; + Record = (PDIR_RECORD)(Block + BlockOffset); + if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0) + { + DPRINT("Map next sector\n"); + CcUnpinData(Context); + StreamOffset.QuadPart += BLOCKSIZE; + Offset = ROUND_UP(Offset, BLOCKSIZE); + BlockOffset = 0; + + if (!CcMapData(DeviceExt->StreamFileObject, + &StreamOffset, + BLOCKSIZE, TRUE, + &Context, &Block)) + { + DPRINT("CcMapData() failed\n"); + return(STATUS_UNSUCCESSFUL); + } + Record = (PDIR_RECORD)(Block + BlockOffset); + } + + if (Offset >= DirSize) + break; + } + + CcUnpinData(Context); + + return(STATUS_OBJECT_NAME_NOT_FOUND); +} +#endif + +NTSTATUS +NtfsGetFCBForFile(PDEVICE_EXTENSION Vcb, + PFCB *pParentFCB, + PFCB *pFCB, + const PWSTR pFileName) +{ + NTSTATUS Status; + WCHAR pathName [MAX_PATH]; + WCHAR elementName [MAX_PATH]; + PWCHAR currentElement; + PFCB FCB; + PFCB parentFCB; + + DPRINT("NtfsGetFCBForFile(%x, %x, %x, '%S')\n", + Vcb, + pParentFCB, + pFCB, + pFileName); + + /* Dummy code */ + FCB = NtfsOpenRootFCB(Vcb); + *pFCB = FCB; + *pParentFCB = NULL; + +#if 0 + /* Trivial case, open of the root directory on volume */ + if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0) + { + DPRINT("returning root FCB\n"); + + FCB = NtfsOpenRootFCB(Vcb); + *pFCB = FCB; + *pParentFCB = NULL; + + return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND); + } + else + { + currentElement = pFileName + 1; + wcscpy (pathName, L"\\"); + FCB = CdfsOpenRootFCB (Vcb); + } + parentFCB = NULL; + + /* Parse filename and check each path element for existance and access */ + while (CdfsGetNextPathElement(currentElement) != 0) + { + /* Skip blank directory levels */ + if ((CdfsGetNextPathElement(currentElement) - currentElement) == 0) + { + currentElement++; + continue; + } + + DPRINT("Parsing, currentElement:%S\n", currentElement); + DPRINT(" parentFCB:%x FCB:%x\n", parentFCB, FCB); + + /* Descend to next directory level */ + if (parentFCB) + { + CdfsReleaseFCB(Vcb, parentFCB); + parentFCB = NULL; + } + + /* fail if element in FCB is not a directory */ + if (!CdfsFCBIsDirectory(FCB)) + { + DPRINT("Element in requested path is not a directory\n"); + + CdfsReleaseFCB(Vcb, FCB); + FCB = 0; + *pParentFCB = NULL; + *pFCB = NULL; + + return(STATUS_OBJECT_PATH_NOT_FOUND); + } + parentFCB = FCB; + + /* Extract next directory level into dirName */ + CdfsWSubString(pathName, + pFileName, + CdfsGetNextPathElement(currentElement) - pFileName); + DPRINT(" pathName:%S\n", pathName); + + FCB = CdfsGrabFCBFromTable(Vcb, pathName); + if (FCB == NULL) + { + CdfsWSubString(elementName, + currentElement, + CdfsGetNextPathElement(currentElement) - currentElement); + DPRINT(" elementName:%S\n", elementName); + + Status = CdfsDirFindFile(Vcb, parentFCB, elementName, &FCB); + if (Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + *pParentFCB = parentFCB; + *pFCB = NULL; + currentElement = CdfsGetNextPathElement(currentElement); + if (*currentElement == L'\0' || CdfsGetNextPathElement(currentElement + 1) == 0) + { + return(STATUS_OBJECT_NAME_NOT_FOUND); + } + else + { + return(STATUS_OBJECT_PATH_NOT_FOUND); + } + } + else if (!NT_SUCCESS(Status)) + { + CdfsReleaseFCB(Vcb, parentFCB); + *pParentFCB = NULL; + *pFCB = NULL; + + return(Status); + } + } + currentElement = CdfsGetNextPathElement(currentElement); + } + + *pParentFCB = parentFCB; + *pFCB = FCB; +#endif + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/finfo.c b/drivers/fs/ntfs/finfo.c new file mode 100644 index 0000000..a5986bc --- /dev/null +++ b/drivers/fs/ntfs/finfo.c @@ -0,0 +1,268 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/dirctl.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +NtfsGetStandardInformation(PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_STANDARD_INFORMATION StandardInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the standard file information + */ +{ + DPRINT("NtfsGetStandardInformation() called\n"); + + if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + /* PRECONDITION */ + assert(StandardInfo != NULL); + assert(Fcb != NULL); + + RtlZeroMemory(StandardInfo, + sizeof(FILE_STANDARD_INFORMATION)); + + StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize; + StandardInfo->EndOfFile = Fcb->RFCB.FileSize; + StandardInfo->NumberOfLinks = 0; + StandardInfo->DeletePending = FALSE; + StandardInfo->Directory = NtfsFCBIsDirectory(Fcb); + + *BufferLength -= sizeof(FILE_STANDARD_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsGetPositionInformation(PFILE_OBJECT FileObject, + PFILE_POSITION_INFORMATION PositionInfo, + PULONG BufferLength) +{ + DPRINT("NtfsGetPositionInformation() called\n"); + + if (*BufferLength < sizeof(FILE_POSITION_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + PositionInfo->CurrentByteOffset.QuadPart = + 0; +// FileObject->CurrentByteOffset.QuadPart; + + DPRINT("Getting position %I64x\n", + PositionInfo->CurrentByteOffset.QuadPart); + + *BufferLength -= sizeof(FILE_POSITION_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsGetBasicInformation(PFILE_OBJECT FileObject, + PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_BASIC_INFORMATION BasicInfo, + PULONG BufferLength) +{ + DPRINT("NtfsGetBasicInformation() called\n"); + + if (*BufferLength < sizeof(FILE_BASIC_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + +#if 0 + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->CreationTime); + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->LastAccessTime); + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->LastWriteTime); + CdfsDateTimeToFileTime(Fcb, + &BasicInfo->ChangeTime); + + CdfsFileFlagsToAttributes(Fcb, + &BasicInfo->FileAttributes); +#endif + + *BufferLength -= sizeof(FILE_BASIC_INFORMATION); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsGetNameInformation(PFILE_OBJECT FileObject, + PFCB Fcb, + PDEVICE_OBJECT DeviceObject, + PFILE_NAME_INFORMATION NameInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the file name information + */ +{ + ULONG NameLength; + + DPRINT("NtfsGetNameInformation() called\n"); + + assert(NameInfo != NULL); + assert(Fcb != NULL); + +// NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR); + NameLength = 2; + if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength) + return(STATUS_BUFFER_OVERFLOW); + + NameInfo->FileNameLength = NameLength; +// memcpy(NameInfo->FileName, +// Fcb->PathName, +// NameLength + sizeof(WCHAR)); + wcscpy(NameInfo->FileName, L"\\"); + + *BufferLength -= + (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR)); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsGetInternalInformation(PFCB Fcb, + PFILE_INTERNAL_INFORMATION InternalInfo, + PULONG BufferLength) +{ + DPRINT("NtfsGetInternalInformation() called\n"); + + assert(InternalInfo); + assert(Fcb); + + if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + /* FIXME: get a real index, that can be used in a create operation */ + InternalInfo->IndexNumber.QuadPart = 0; + + *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Retrieve the specified file information + */ +{ + FILE_INFORMATION_CLASS FileInformationClass; + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + PFCB Fcb; + PVOID SystemBuffer; + ULONG BufferLength; + + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtfsQueryInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; + FileObject = Stack->FileObject; + Fcb = FileObject->FsContext; + + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + BufferLength = Stack->Parameters.QueryFile.Length; + + switch (FileInformationClass) + { + case FileStandardInformation: + Status = NtfsGetStandardInformation(Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FilePositionInformation: + Status = NtfsGetPositionInformation(FileObject, + SystemBuffer, + &BufferLength); + break; + + case FileBasicInformation: + Status = NtfsGetBasicInformation(FileObject, + Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileNameInformation: + Status = NtfsGetNameInformation(FileObject, + Fcb, + DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileInternalInformation: + Status = NtfsGetInternalInformation(Fcb, + SystemBuffer, + &BufferLength); + break; + + case FileAlternateNameInformation: + case FileAllInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + DPRINT("Unimplemented information class %u\n", FileInformationClass); + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryFile.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/fsctl.c b/drivers/fs/ntfs/fsctl.c new file mode 100644 index 0000000..98554d9 --- /dev/null +++ b/drivers/fs/ntfs/fsctl.c @@ -0,0 +1,479 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/fsctl.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "ntfs.h" + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount) +/* + * FUNCTION: Tests if the device contains a filesystem that can be mounted + * by this fsd + */ +{ + PARTITION_INFORMATION PartitionInfo; + DISK_GEOMETRY DiskGeometry; + ULONG Size; + PBOOT_SECTOR BootSector; + NTSTATUS Status; + + DPRINT("NtfsHasFileSystem() called\n"); + + Size = sizeof(DISK_GEOMETRY); + Status = NtfsDeviceIoControl(DeviceToMount, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status); + return(Status); + } + + if (DiskGeometry.MediaType == FixedMedia) + { + /* We have found a hard disk */ + Size = sizeof(PARTITION_INFORMATION); + Status = NtfsDeviceIoControl(DeviceToMount, + IOCTL_DISK_GET_PARTITION_INFO, + NULL, + 0, + &PartitionInfo, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status); + return(Status); + } + + if (PartitionInfo.PartitionType != PARTITION_IFS) + { + return(STATUS_UNRECOGNIZED_VOLUME); + } + } + + DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); + BootSector = ExAllocatePool(NonPagedPool, + DiskGeometry.BytesPerSector); + if (BootSector == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = NtfsReadRawSectors(DeviceToMount, + 0, + 1, + DiskGeometry.BytesPerSector, + (PVOID)BootSector); + if (NT_SUCCESS(Status)) + { + DPRINT("NTFS-identifier: [%.8s]\n", BootSector->OemName); + if (strncmp(BootSector->OemName, "NTFS ", 8) != 0) + { + Status = STATUS_UNRECOGNIZED_VOLUME; + } + } + + ExFreePool(BootSector); + + return(Status); +} + + +static NTSTATUS +NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, + PDEVICE_EXTENSION Vcb) +{ + DISK_GEOMETRY DiskGeometry; +// PUCHAR Buffer; + ULONG Size; + NTSTATUS Status; + PBOOT_SECTOR BootSector; + + DPRINT("NtfsGetVolumeData() called\n"); + + Size = sizeof(DISK_GEOMETRY); + Status = NtfsDeviceIoControl(DeviceObject, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status); + return(Status); + } + + DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector); + BootSector = ExAllocatePool(NonPagedPool, + DiskGeometry.BytesPerSector); + if (BootSector == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = NtfsReadRawSectors(DeviceObject, + 0, /* Partition boot sector */ + 1, + DiskGeometry.BytesPerSector, + (PVOID)BootSector); + if (NT_SUCCESS(Status)) + { + /* Read data from the bootsector */ + Vcb->NtfsInfo.BytesPerSector = BootSector->BytesPerSector; + Vcb->NtfsInfo.SectorsPerCluster = BootSector->SectorsPerCluster; + Vcb->NtfsInfo.BytesPerCluster = BootSector->BytesPerSector * BootSector->SectorsPerCluster; + Vcb->NtfsInfo.SectorCount = BootSector->SectorCount; + + Vcb->NtfsInfo.MftStart.QuadPart = BootSector->MftLocation; + Vcb->NtfsInfo.MftMirrStart.QuadPart = BootSector->MftMirrLocation; + Vcb->NtfsInfo.SerialNumber = BootSector->SerialNumber; + +//#indef NDEBUG + DbgPrint("Boot sector information:\n"); + DbgPrint(" BytesPerSector: %hu\n", BootSector->BytesPerSector); + DbgPrint(" SectorsPerCluster: %hu\n", BootSector->SectorsPerCluster); + + DbgPrint(" SectorCount: %I64u\n", BootSector->SectorCount); + + DbgPrint(" MftStart: %I64u\n", BootSector->MftLocation); + DbgPrint(" MftMirrStart: %I64u\n", BootSector->MftMirrLocation); + + DbgPrint(" ClustersPerMftRecord: %lx\n", BootSector->ClustersPerMftRecord); + DbgPrint(" ClustersPerIndexRecord: %lx\n", BootSector->ClustersPerIndexRecord); + + DbgPrint(" SerialNumber: %I64x\n", BootSector->SerialNumber); +//#endif + + NtfsOpenMft(DeviceObject, Vcb); + + } + + ExFreePool(BootSector); + + return(Status); +} + + + +static NTSTATUS +NtfsMountVolume(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt = NULL; + PDEVICE_OBJECT NewDeviceObject = NULL; + PDEVICE_OBJECT DeviceToMount; + PIO_STACK_LOCATION Stack; + PFCB Fcb = NULL; + PCCB Ccb = NULL; + PVPB Vpb; + NTSTATUS Status; + + DPRINT("NtfsMountVolume() called\n"); + + if (DeviceObject != NtfsGlobalData->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceToMount = Stack->Parameters.MountVolume.DeviceObject; + Vpb = Stack->Parameters.MountVolume.Vpb; + + Status = NtfsHasFileSystem(DeviceToMount); + if (!NT_SUCCESS(Status)) + { + goto ByeBye; + } + + Status = IoCreateDevice(NtfsGlobalData->DriverObject, + sizeof(DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, +// FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &NewDeviceObject); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = (PVOID)NewDeviceObject->DeviceExtension; + RtlZeroMemory(DeviceExt, + sizeof(DEVICE_EXTENSION)); + + Status = NtfsGetVolumeData(DeviceToMount, + DeviceExt); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + NewDeviceObject->Vpb = DeviceToMount->Vpb; + + DeviceExt->StorageDevice = DeviceToMount; + DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject; + DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; + DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; + NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; + NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL, + DeviceExt->StorageDevice); + + + Fcb = NtfsCreateFCB(NULL); + if (Fcb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + + Ccb = ExAllocatePoolWithTag(NonPagedPool, + sizeof(CCB), + TAG_CCB); + if (Ccb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + RtlZeroMemory(Ccb, + sizeof(CCB)); + + DeviceExt->StreamFileObject->Flags = DeviceExt->StreamFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; + DeviceExt->StreamFileObject->FsContext = (PVOID)&Fcb->RFCB; + DeviceExt->StreamFileObject->FsContext2 = Ccb; + DeviceExt->StreamFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + DeviceExt->StreamFileObject->PrivateCacheMap = NULL; + DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb; + Ccb->Fcb = Fcb; + Ccb->PtrFileObject = DeviceExt->StreamFileObject; + Fcb->FileObject = DeviceExt->StreamFileObject; + Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; + + Fcb->Flags = FCB_IS_VOLUME_STREAM; + + Fcb->RFCB.FileSize.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector; + Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector; + Fcb->RFCB.AllocationSize.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector; /* Correct? */ + +// Fcb->Entry.ExtentLocationL = 0; +// Fcb->Entry.DataLengthL = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE; + + Status = CcRosInitializeFileCache(DeviceExt->StreamFileObject, + &Fcb->RFCB.Bcb, + CACHEPAGESIZE(DeviceExt)); + if (!NT_SUCCESS (Status)) + { + DbgPrint("CcRosInitializeFileCache() failed (Status %lx)\n", Status); + goto ByeBye; + } + + ExInitializeResourceLite(&DeviceExt->DirResource); +// ExInitializeResourceLite(&DeviceExt->FatResource); + + KeInitializeSpinLock(&DeviceExt->FcbListLock); + InitializeListHead(&DeviceExt->FcbListHead); + + /* Read serial number */ + NewDeviceObject->Vpb->SerialNumber = DeviceExt->NtfsInfo.SerialNumber; + + /* Read volume label */ +// NtfsReadVolumeLabel(DeviceExt, +// NewDeviceObject->Vpb); + + Status = STATUS_SUCCESS; + +ByeBye: + if (!NT_SUCCESS(Status)) + { + /* Cleanup */ + if (DeviceExt && DeviceExt->StreamFileObject) + ObDereferenceObject(DeviceExt->StreamFileObject); + if (Fcb) + ExFreePool(Fcb); + if (Ccb) + ExFreePool(Ccb); + if (NewDeviceObject) + IoDeleteDevice(NewDeviceObject); + } + + DPRINT("NtfsMountVolume() done (Status: %lx)\n", Status); + + return(Status); +} + + +static NTSTATUS +NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ +#if 0 + PDEVICE_OBJECT DeviceToVerify; + PIO_STACK_LOCATION Stack; + PUCHAR Buffer; + ULONG Sector; + ULONG i; + NTSTATUS Status; + + union + { + ULONG Value; + UCHAR Part[4]; + } Serial; +#endif + + DPRINT1("NtfsVerifyVolume() called\n"); + +#if 0 + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject; + + DPRINT("Device object %p Device to verify %p\n", DeviceObject, DeviceToVerify); + + Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; + + Buffer = ExAllocatePool(NonPagedPool, + CDFS_BASIC_SECTOR); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + do + { + /* Read the Primary Volume Descriptor (PVD) */ + Status = CdfsReadRawSectors(DeviceToVerify, + Sector, + 1, + Buffer); + DPRINT("CdfsReadRawSectors() status %lx\n", Status); + if (!NT_SUCCESS(Status)) + { + goto ByeBye; + } + + if (Buffer[0] == 1 && + Buffer[1] == 'C' && + Buffer[2] == 'D' && + Buffer[3] == '0' && + Buffer[4] == '0' && + Buffer[5] == '1') + { + break; + } + + Sector++; + } + while (Buffer[0] != 255); + + if (Buffer[0] == 255) + goto ByeBye; + + Status = STATUS_WRONG_VOLUME; + + /* Calculate the volume serial number */ + Serial.Value = 0; + for (i = 0; i < 2048; i += 4) + { + /* DON'T optimize this to ULONG!!! (breaks overflow) */ + Serial.Part[0] += Buffer[i+3]; + Serial.Part[1] += Buffer[i+2]; + Serial.Part[2] += Buffer[i+1]; + Serial.Part[3] += Buffer[i+0]; + } + + DPRINT("Current serial number %08lx Vpb serial number %08lx\n", + Serial.Value, DeviceToVerify->Vpb->SerialNumber); + + if (Serial.Value == DeviceToVerify->Vpb->SerialNumber) + Status = STATUS_SUCCESS; + +ByeBye: + ExFreePool(Buffer); + + DPRINT("CdfsVerifyVolume() done (Status: %lx)\n", Status); + + return(Status); +#endif + return(STATUS_UNSUCCESSFUL); +} + + +NTSTATUS STDCALL +NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("NtfsFileSystemControl() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_USER_FS_REQUEST: + DPRINT("NTFS: IRP_MN_USER_FS_REQUEST\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + case IRP_MN_MOUNT_VOLUME: + DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n"); + Status = NtfsMountVolume(DeviceObject, Irp); + break; + + case IRP_MN_VERIFY_VOLUME: + DPRINT1("NTFS: IRP_MN_VERIFY_VOLUME\n"); + Status = NtfsVerifyVolume(DeviceObject, Irp); + break; + + default: + DPRINT("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/ntfs/makefile b/drivers/fs/ntfs/makefile new file mode 100644 index 0000000..28c1929 --- /dev/null +++ b/drivers/fs/ntfs/makefile @@ -0,0 +1,16 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = ntfs + +TARGET_OBJECTS = $(TARGET_NAME).o attrib.o blockdev.o create.o dirctl.o \ + fcb.o finfo.o fsctl.o mft.o volinfo.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/fs/ntfs/mft.c b/drivers/fs/ntfs/mft.c new file mode 100644 index 0000000..9027a07 --- /dev/null +++ b/drivers/fs/ntfs/mft.c @@ -0,0 +1,100 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/mft.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +//#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + + +NTSTATUS +NtfsOpenMft(PDEVICE_OBJECT DeviceObject, + PDEVICE_EXTENSION Vcb) +{ + PVOID Buffer; + PFILE_RECORD_HEADER RecordHeader; + PATTRIBUTE Attribute; + NTSTATUS Status; + + DPRINT1("NtfsOpenMft() called\n"); + + Buffer = ExAllocatePool(NonPagedPool, + Vcb->NtfsInfo.BytesPerCluster); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + + /* read first MFT cluster */ + Status = NtfsReadRawSectors(DeviceObject, + Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster, + Vcb->NtfsInfo.SectorsPerCluster, + Vcb->NtfsInfo.BytesPerSector, + (PVOID)Buffer); + if (NT_SUCCESS(Status)) + { + /* Enumerate MFT records */ + RecordHeader = Buffer; + while (((ULONG)RecordHeader - (ULONG)Buffer) < Vcb->NtfsInfo.BytesPerCluster) + { + DbgPrint("\n"); +// DbgPrint("Magic: %.04s\n", (PCHAR)&RecordHeader->Ntfs.Type); +// DbgPrint("Real size: %lx\n", RecordHeader->RealSize); +// DbgPrint("AllocSize: %lx\n", RecordHeader->AllocSize); + + /* Enumerate attributes */ + Attribute = (PATTRIBUTE)((ULONG)RecordHeader + + RecordHeader->Ntfs.UsnOffset + + RecordHeader->Ntfs.UsnSize * sizeof(USHORT)); + while (Attribute->AttributeType != 0xFFFFFFFF) + { + NtfsDumpAttribute(Attribute); + + Attribute = (PATTRIBUTE)((ULONG)Attribute + Attribute->Length); + } + + + RecordHeader = (PFILE_RECORD_HEADER)((ULONG)RecordHeader + RecordHeader->BytesAllocated); + } + + } + + ExFreePool(Buffer); + + return(Status); +} + + +/* EOF */ diff --git a/drivers/fs/ntfs/ntfs.c b/drivers/fs/ntfs/ntfs.c new file mode 100644 index 0000000..7ce00f8 --- /dev/null +++ b/drivers/fs/ntfs/ntfs.c @@ -0,0 +1,104 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/ntfs.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "ntfs.h" + + +/* GLOBALS *****************************************************************/ + +PNTFS_GLOBAL_DATA NtfsGlobalData; + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Ntfs"); + + DPRINT("NTFS 0.0.1\n"); + + Status = IoCreateDevice(DriverObject, + sizeof(NTFS_GLOBAL_DATA), + &DeviceName, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* Initialize global data */ + NtfsGlobalData = DeviceObject->DeviceExtension; + RtlZeroMemory(NtfsGlobalData, + sizeof(NTFS_GLOBAL_DATA)); + NtfsGlobalData->DriverObject = DriverObject; + NtfsGlobalData->DeviceObject = DeviceObject; + + /* Initialize driver data */ + DeviceObject->Flags = DO_DIRECT_IO; +// DriverObject->MajorFunction[IRP_MJ_CLOSE] = NtfsClose; + DriverObject->MajorFunction[IRP_MJ_CREATE] = NtfsCreate; +// DriverObject->MajorFunction[IRP_MJ_READ] = NtfsRead; +// DriverObject->MajorFunction[IRP_MJ_WRITE] = NtfsWrite; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + NtfsFileSystemControl; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = + NtfsDirectoryControl; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = + NtfsQueryInformation; +// DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = +// NtfsQueryVolumeInformation; +// DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = +// NtfsSetVolumeInformation; + + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + + return(STATUS_SUCCESS); +} + diff --git a/drivers/fs/ntfs/ntfs.h b/drivers/fs/ntfs/ntfs.h new file mode 100644 index 0000000..5998345 --- /dev/null +++ b/drivers/fs/ntfs/ntfs.h @@ -0,0 +1,430 @@ +#ifndef NTFS_H +#define NTFS_H + +#include + + +#define CACHEPAGESIZE(pDeviceExt) \ + ((pDeviceExt)->NtfsInfo.BytesPerCluster > PAGE_SIZE ? \ + (pDeviceExt)->NtfsInfo.BytesPerCluster : PAGE_SIZE) + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + + +typedef struct _BOOT_SECTOR +{ + UCHAR Magic[3]; // 0x00 + UCHAR OemName[8]; // 0x03 + USHORT BytesPerSector; // 0x0B + UCHAR SectorsPerCluster; // 0x0D + UCHAR Unused0[7]; // 0x0E + UCHAR MediaId; // 0x15 + UCHAR Unused1[2]; // 0x16 + USHORT SectorsPerTrack; + USHORT Heads; + UCHAR Unused2[8]; + UCHAR Unknown0[4]; /* always 80 00 80 00 */ + ULONGLONG SectorCount; + ULONGLONG MftLocation; + ULONGLONG MftMirrLocation; + ULONG ClustersPerMftRecord; + ULONG ClustersPerIndexRecord; + ULONGLONG SerialNumber; // 0x48 + UCHAR BootCode[432]; // 0x50 +} __attribute__((packed)) BOOT_SECTOR, *PBOOT_SECTOR; + +//typedef struct _BootSector BootSector; + + + + + +typedef struct _NTFS_INFO +{ + ULONG BytesPerSector; + ULONG SectorsPerCluster; + ULONG BytesPerCluster; + ULONGLONG SectorCount; + ULARGE_INTEGER MftStart; + ULARGE_INTEGER MftMirrStart; + ULONGLONG SerialNumber; + +} NTFS_INFO, *PNTFS_INFO; + + +typedef struct +{ + ERESOURCE DirResource; +// ERESOURCE FatResource; + + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + + PVPB Vpb; + PDEVICE_OBJECT StorageDevice; + PFILE_OBJECT StreamFileObject; + + NTFS_INFO NtfsInfo; + + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + + +#define FCB_CACHE_INITIALIZED 0x0001 +#define FCB_IS_VOLUME_STREAM 0x0002 +#define FCB_IS_VOLUME 0x0004 + +typedef struct _FCB +{ + REACTOS_COMMON_FCB_HEADER RFCB; + SECTION_OBJECT_POINTERS SectionObjectPointers; + + PFILE_OBJECT FileObject; + PDEVICE_EXTENSION DevExt; + + WCHAR *ObjectName; /* point on filename (250 chars max) in PathName */ + WCHAR PathName[MAX_PATH]; /* path+filename 260 max */ + + ERESOURCE PagingIoResource; + ERESOURCE MainResource; + + LIST_ENTRY FcbListEntry; + struct _FCB* ParentFcb; + + ULONG DirIndex; + + LONG RefCount; + ULONG Flags; + +// DIR_RECORD Entry; + + +} FCB, *PFCB; + + +typedef struct _CCB +{ + PFCB Fcb; + LIST_ENTRY NextCCB; + PFILE_OBJECT PtrFileObject; + LARGE_INTEGER CurrentByteOffset; + /* for DirectoryControl */ + ULONG Entry; + /* for DirectoryControl */ + PWCHAR DirectorySearchPattern; + ULONG LastCluster; + ULONG LastOffset; +} CCB, *PCCB; + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +#define TAG_CCB TAG('I', 'C', 'C', 'B') + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; +} NTFS_GLOBAL_DATA, *PNTFS_GLOBAL_DATA; + + +typedef enum +{ + AttributeStandardInformation = 0x10, + AttributeAttributeList = 0x20, + AttributeFileName = 0x30, + AttributeObjectId = 0x40, + AttributeSecurityDescriptor = 0x50, + AttributeVolumeName = 0x60, + AttributeVolumeInformation = 0x70, + AttributeData = 0x80, + AttributeIndexRoot = 0x90, + AttributeIndexAllocation = 0xA0, + AttributeBitmap = 0xB0, + AttributeReparsePoint = 0xC0, + AttributeEAInformation = 0xD0, + AttributeEA = 0xE0, + AttributePropertySet = 0xF0, + AttributeLoggedUtilityStream = 0x100 +} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; + + +typedef struct +{ + ULONG Type; + USHORT UsnOffset; + USHORT UsnSize; + ULONGLONG Usn; +} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER; + +typedef struct +{ + NTFS_RECORD_HEADER Ntfs; + USHORT SequenceNumber; + USHORT LinkCount; + USHORT AttributeOffset; + USHORT Flags; + ULONG BytesInUse; + ULONG BytesAllocated; + ULONGLONG BaseFileRecord; + USHORT NextAttributeNumber; +} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER; + +typedef struct +{ + ATTRIBUTE_TYPE AttributeType; + ULONG Length; + BOOLEAN Nonresident; + UCHAR NameLength; + USHORT NameOffset; + USHORT Flags; + USHORT AttributeNumber; +} ATTRIBUTE, *PATTRIBUTE; + +typedef struct +{ + ATTRIBUTE Attribute; + ULONG ValueLength; + USHORT ValueOffset; + UCHAR Flags; +// UCHAR Padding0; +} RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE; + +typedef struct +{ + ATTRIBUTE Attribute; + ULONGLONG StartVcn; // LowVcn + ULONGLONG LastVcn; // HighVcn + USHORT RunArrayOffset; + USHORT CompressionUnit; + ULONG Padding0; + UCHAR IndexedFlag; + ULONGLONG AllocatedSize; + ULONGLONG DataSize; + ULONGLONG InitializedSize; + ULONGLONG CompressedSize; +} NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE; + + +typedef struct +{ + ULONGLONG CreationTime; + ULONGLONG ChangeTime; + ULONGLONG LastWriteTime; + ULONGLONG LastAccessTime; + ULONG FileAttribute; + ULONG AlignmentOrReserved[3]; +#if 0 + ULONG QuotaId; + ULONG SecurityId; + ULONGLONG QuotaCharge; + USN Usn; +#endif +} STANDARD_INFORMATION, *PSTANDARD_INFORMATION; + + +typedef struct +{ + ATTRIBUTE_TYPE AttributeType; + USHORT Length; + UCHAR NameLength; + UCHAR NameOffset; + ULONGLONG StartVcn; // LowVcn + ULONGLONG FileReferenceNumber; + USHORT AttributeNumber; + USHORT AlignmentOrReserved[3]; +} ATTRIBUTE_LIST, *PATTRIBUTE_LIST; + + +typedef struct +{ + ULONGLONG DirectoryFileReferenceNumber; + ULONGLONG CreationTime; + ULONGLONG ChangeTime; + ULONGLONG LastWriteTime; + ULONGLONG LastAccessTime; + ULONGLONG AllocatedSize; + ULONGLONG DataSize; + ULONG FileAttributes; + ULONG AlignmentOrReserved; + UCHAR NameLength; + UCHAR NameType; + WCHAR Name[1]; +} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE; + + + +extern PNTFS_GLOBAL_DATA NtfsGlobalData; + +//int CdfsStrcmpi( wchar_t *str1, wchar_t *str2 ); +//void CdfsWstrcpy( wchar_t *str1, wchar_t *str2, int max ); + + +/* attrib.c */ + +VOID +NtfsDumpAttribute(PATTRIBUTE Attribute); + + +/* blockdev.c */ + +NTSTATUS +NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN ULONG SectorSize, + IN OUT PUCHAR Buffer); + +NTSTATUS +NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject, + IN ULONG DiskSector, + IN ULONG SectorCount, + IN ULONG SectorSize, + IN OUT PUCHAR Buffer); + +NTSTATUS +NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject, + IN ULONG ControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG OutputBufferSize); + +#if 0 +/* close.c */ + +NTSTATUS STDCALL +CdfsClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +#endif + +/* create.c */ + +NTSTATUS STDCALL +NtfsCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* dirctl.c */ + +NTSTATUS STDCALL +NtfsDirectoryControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* fcb.c */ + +PFCB +NtfsCreateFCB(PWCHAR FileName); + +VOID +NtfsDestroyFCB(PFCB Fcb); + +BOOLEAN +NtfsFCBIsDirectory(PFCB Fcb); + +BOOLEAN +NtfsFCBIsRoot(PFCB Fcb); + +VOID +NtfsGrabFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +VOID +NtfsReleaseFCB(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +VOID +NtfsAddFCBToTable(PDEVICE_EXTENSION Vcb, + PFCB Fcb); + +PFCB +NtfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb, + PWSTR FileName); + +NTSTATUS +NtfsFCBInitializeCache(PVCB Vcb, + PFCB Fcb); + +PFCB +NtfsMakeRootFCB(PDEVICE_EXTENSION Vcb); + +PFCB +NtfsOpenRootFCB(PDEVICE_EXTENSION Vcb); + +NTSTATUS +NtfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb, + PFCB Fcb, + PFILE_OBJECT FileObject); + +NTSTATUS +NtfsGetFCBForFile(PDEVICE_EXTENSION Vcb, + PFCB *pParentFCB, + PFCB *pFCB, + const PWSTR pFileName); + + +/* finfo.c */ + +NTSTATUS STDCALL +NtfsQueryInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* fsctl.c */ + +NTSTATUS STDCALL +NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + + +/* mft.c */ +NTSTATUS +NtfsOpenMft(PDEVICE_OBJECT DeviceObject, + PDEVICE_EXTENSION Vcb); + + +#if 0 +/* misc.c */ + +BOOLEAN +wstrcmpjoki(PWSTR s1, PWSTR s2); + +VOID +CdfsSwapString(PWCHAR Out, + PUCHAR In, + ULONG Count); + +VOID +CdfsDateTimeToFileTime(PFCB Fcb, + TIME *FileTime); + +VOID +CdfsFileFlagsToAttributes(PFCB Fcb, + PULONG FileAttributes); + +/* rw.c */ + +NTSTATUS STDCALL +CdfsRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +CdfsWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +#endif + + +/* volinfo.c */ + +NTSTATUS STDCALL +NtfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL +NtfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +#endif /* NTFS_H */ diff --git a/drivers/fs/ntfs/ntfs.rc b/drivers/fs/ntfs/ntfs.rc new file mode 100644 index 0000000..ab52053 --- /dev/null +++ b/drivers/fs/ntfs/ntfs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "NTFS Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "ntfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ntfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/ntfs/volinfo.c b/drivers/fs/ntfs/volinfo.c new file mode 100644 index 0000000..a5a45bc --- /dev/null +++ b/drivers/fs/ntfs/volinfo.c @@ -0,0 +1,242 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/ntfs/volume.c + * PURPOSE: NTFS filesystem driver + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "ntfs.h" + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, + PULONG BufferLength) +{ + ULONG LabelLength; + + DPRINT("NtfsGetFsVolumeInformation() called\n"); + DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + + DPRINT("Vpb %p\n", DeviceObject->Vpb); + LabelLength = DeviceObject->Vpb->VolumeLabelLength; + + DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))); + DPRINT("LabelLength %lu\n", LabelLength); + DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel); + + if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION)) + return(STATUS_INFO_LENGTH_MISMATCH); + + if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))) + return(STATUS_BUFFER_OVERFLOW); + + /* valid entries */ + FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber; + FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR); + wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel); + + /* dummy entries */ + FsVolumeInfo->VolumeCreationTime.QuadPart = 0; + FsVolumeInfo->SupportsObjects = FALSE; + + *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR)); + + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("NtfsGetFsVolumeInformation() done\n"); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, + PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, + PULONG BufferLength) +{ + DPRINT("NtfsGetFsAttributeInformation()\n"); + DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)); + + if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) + return(STATUS_INFO_LENGTH_MISMATCH); + + if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8)) + return(STATUS_BUFFER_OVERFLOW); + + FsAttributeInfo->FileSystemAttributes = + FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK; + FsAttributeInfo->MaximumComponentNameLength = 255; + FsAttributeInfo->FileSystemNameLength = 8; + + memcpy(FsAttributeInfo->FileSystemName, L"NTFS", 8); + + DPRINT("Finished NtfsGetFsAttributeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +NtfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_SIZE_INFORMATION FsSizeInfo, + PULONG BufferLength) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("NtfsGetFsSizeInformation()\n"); + DPRINT("FsSizeInfo = %p\n", FsSizeInfo); + + if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + DeviceExt = DeviceObject->DeviceExtension; + + FsSizeInfo->AvailableAllocationUnits.QuadPart = 0; + FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->NtfsInfo.SectorCount; /* ?? */ + FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->NtfsInfo.SectorsPerCluster; + FsSizeInfo->BytesPerSector = DeviceExt->NtfsInfo.BytesPerSector; + + DPRINT("Finished NtfsGetFsSizeInformation()\n"); + if (NT_SUCCESS(Status)) + *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION); + + return(Status); +} + + +static NTSTATUS +NtfsGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, + PULONG BufferLength) +{ + DPRINT("NtfsGetFsDeviceInformation()\n"); + DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION)); + + if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + FsDeviceInfo->DeviceType = FILE_DEVICE_DISK; + FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */ + + DPRINT("NtfsGetFsDeviceInformation() finished.\n"); + + *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + + +NTSTATUS STDCALL +NtfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + FS_INFORMATION_CLASS FsInformationClass; + PIO_STACK_LOCATION Stack; + NTSTATUS Status = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + DPRINT("NtfsQueryVolumeInformation() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass; + BufferLength = Stack->Parameters.QueryVolume.Length; + SystemBuffer = Irp->AssociatedIrp.SystemBuffer; + + DPRINT("FsInformationClass %d\n", FsInformationClass); + DPRINT("SystemBuffer %x\n", SystemBuffer); + + switch (FsInformationClass) + { + case FileFsVolumeInformation: + Status = NtfsGetFsVolumeInformation(DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsAttributeInformation: + Status = NtfsGetFsAttributeInformation(DeviceObject->DeviceExtension, + SystemBuffer, + &BufferLength); + break; + + case FileFsSizeInformation: + Status = NtfsGetFsSizeInformation(DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsDeviceInformation: + Status = NtfsGetFsDeviceInformation(SystemBuffer, + &BufferLength); + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + Irp->IoStatus.Status = Status; + if (NT_SUCCESS(Status)) + Irp->IoStatus.Information = + Stack->Parameters.QueryVolume.Length - BufferLength; + else + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +NTSTATUS STDCALL +NtfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("NtfsSetVolumeInformation() called\n"); + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_NOT_SUPPORTED); +} + +/* EOF */ diff --git a/drivers/fs/template/makefile b/drivers/fs/template/makefile new file mode 100644 index 0000000..52a816a --- /dev/null +++ b/drivers/fs/template/makefile @@ -0,0 +1,15 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = template + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/fs/template/template.c b/drivers/fs/template/template.c new file mode 100644 index 0000000..adfe72f --- /dev/null +++ b/drivers/fs/template/template.c @@ -0,0 +1,284 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/template/template.c + * PURPOSE: Bare filesystem template + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +typedef struct +{ + PDEVICE_OBJECT StorageDevice; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +/* GLOBALS ******************************************************************/ + +static PDRIVER_OBJECT DriverObject; + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +FsdCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject) +/* + * FUNCTION: Closes a file + */ +{ + return(STATUS_SUCCESS); +} + + +NTSTATUS +FsdOpenFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PWSTR FileName) +/* + * FUNCTION: Opens a file + */ +{ + return(STATUS_SUCCESS); +} + + +BOOLEAN +FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount) +/* + * FUNCTION: Tests if the device contains a filesystem that can be mounted + * by this fsd + */ +{ + return(TRUE); +} + + +NTSTATUS +FsdMountDevice(PDEVICE_EXTENSION DeviceExt, + PDEVICE_OBJECT DeviceToMount) +/* + * FUNCTION: Mounts the device + */ +{ + return(STATUS_SUCCESS); +} + + +NTSTATUS +FsdReadFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + ULONG Offset) +/* + * FUNCTION: Reads data from a file + */ +{ + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +FsdClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + + Status = FsdCloseFile(DeviceExtension,FileObject); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + + +NTSTATUS STDCALL +FsdCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + NTSTATUS Status; + PDEVICE_EXTENSION DeviceExt; + + DeviceExt = DeviceObject->DeviceExtension; + Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + + +NTSTATUS STDCALL +FsdWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +FsdRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + ULONG Length; + PVOID Buffer; + ULONG Offset; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = Stack->FileObject; + PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; + NTSTATUS Status; + + DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + Length = Stack->Parameters.Read.Length; + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Offset = Stack->Parameters.Read.ByteOffset.LowPart; + + Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + return(Status); +} + + +NTSTATUS +FsdMount(PDEVICE_OBJECT DeviceToMount) +{ + PDEVICE_OBJECT DeviceObject; + PDEVICE_EXTENSION DeviceExt; + + IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = (PVOID)DeviceObject->DeviceExtension; + + FsdMountDevice(DeviceExt, + DeviceToMount); + + DeviceExt->StorageDevice = DeviceToMount; + DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject; + DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; + DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; + DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PVPB vpb = Stack->Parameters.Mount.Vpb; + PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject; + NTSTATUS Status; + + if (FsdHasFileSystem(DeviceToMount)) + { + Status = FsdMount(DeviceToMount); + } + else + { + Status = STATUS_UNRECOGNIZED_VOLUME; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT _DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + NTSTATUS Status; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\BareFsd"); + + DbgPrint("Bare FSD Template 0.0.1\n"); + + DriverObject = _DriverObject; + + Status = IoCreateDevice(DriverObject, + 0, + &DeviceName, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DeviceObject->Flags=0; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose; + DriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate; + DriverObject->MajorFunction[IRP_MJ_READ] = FsdRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = + FsdFileSystemControl; + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/drivers/fs/vfat/.cvsignore b/drivers/fs/vfat/.cvsignore new file mode 100644 index 0000000..4f613ad --- /dev/null +++ b/drivers/fs/vfat/.cvsignore @@ -0,0 +1,6 @@ +base.tmp +junk.tmp +temp.exp +vfatfs.coff +vfatfs.sys.unstripped +*.d \ No newline at end of file diff --git a/drivers/fs/vfat/blockdev.c b/drivers/fs/vfat/blockdev.c new file mode 100644 index 0000000..02b731f --- /dev/null +++ b/drivers/fs/vfat/blockdev.c @@ -0,0 +1,189 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/blockdev.c + * PURPOSE: Temporary sector reading support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS +VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject, + IN PLARGE_INTEGER ReadOffset, + IN ULONG ReadLength, + IN OUT PUCHAR Buffer) +{ + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + KEVENT event; + NTSTATUS Status; + + KeInitializeEvent (&event, NotificationEvent, FALSE); + + DPRINT ("VfatReadSectors(pDeviceObject %x, Offset %I64x, Length %d, Buffer %x)\n", + pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); + + DPRINT ("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest (IRP_MJ_READ, + pDeviceObject, + Buffer, + ReadLength, + ReadOffset, + &event, + &IoStatus); + + if (Irp == NULL) + { + DPRINT("IoBuildSynchronousFsdRequest failed\n"); + return(STATUS_UNSUCCESSFUL); + } + + DPRINT ("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver (pDeviceObject, Irp); + + DPRINT ("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT ("Operation pending\n"); + KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL); + DPRINT ("Getting IO Status... for %x\n", Irp); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS (Status)) + { + DPRINT ("IO failed!!! VfatReadSectors : Error code: %x\n", Status); + DPRINT ("(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x\n", + pDeviceObject, ReadOffset->QuadPart, ReadLength, Buffer); + return (Status); + } + DPRINT ("Block request succeeded for %x\n", Irp); + return (STATUS_SUCCESS); +} + +NTSTATUS +VfatWriteDisk (IN PDEVICE_OBJECT pDeviceObject, + IN PLARGE_INTEGER WriteOffset, + IN ULONG WriteLength, + IN PUCHAR Buffer) +{ + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + KEVENT event; + NTSTATUS Status; + + DPRINT ("VfatWriteSectors(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x)\n", + pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer); + + KeInitializeEvent (&event, NotificationEvent, FALSE); + + DPRINT ("Building synchronous FSD Request...\n"); + Irp = IoBuildSynchronousFsdRequest (IRP_MJ_WRITE, + pDeviceObject, + Buffer, + WriteLength, + WriteOffset, + &event, + &IoStatus); + + if (!Irp) + { + DPRINT ("WRITE failed!!!\n"); + return (STATUS_UNSUCCESSFUL); + } + + DPRINT ("Calling IO Driver...\n"); + Status = IoCallDriver (pDeviceObject, Irp); + + DPRINT ("Waiting for IO Operation...\n"); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL); + DPRINT ("Getting IO Status...\n"); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS (Status)) + { + DPRINT1 ("IO failed!!! VfatWriteSectors : Error code: %x\n", Status); + return (Status); + } + + DPRINT ("Block request succeeded\n"); + return (STATUS_SUCCESS); +} + +NTSTATUS +VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize) +{ + ULONG OutputBufferSize = 0; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + DPRINT("VfatBlockDeviceIoControl(DeviceObject %x, CtlCode %x, " + "InputBuffer %x, InputBufferSize %x, OutputBuffer %x, " + "POutputBufferSize %x (%x)\n", DeviceObject, CtlCode, + InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize, + pOutputBufferSize ? *pOutputBufferSize : 0); + + if (pOutputBufferSize) + { + OutputBufferSize = *pOutputBufferSize; + } + + KeInitializeEvent (&Event, NotificationEvent, FALSE); + + DPRINT("Building device I/O control request ...\n"); + Irp = IoBuildDeviceIoControlRequest(CtlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutputBufferSize, + FALSE, + &Event, + &IoStatus); + + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + DPRINT ("Calling IO Driver... with irp %x\n", Irp); + Status = IoCallDriver(DeviceObject, Irp); + + DPRINT ("Waiting for IO Operation for %x\n", Irp); + if (Status == STATUS_PENDING) + { + DPRINT ("Operation pending\n"); + KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL); + DPRINT ("Getting IO Status... for %x\n", Irp); + + Status = IoStatus.Status; + } + if (OutputBufferSize) + { + *pOutputBufferSize = OutputBufferSize; + } + DPRINT("Returning Status %x\n", Status); + return Status; +} diff --git a/drivers/fs/vfat/cleanup.c b/drivers/fs/vfat/cleanup.c new file mode 100644 index 0000000..7d65a10 --- /dev/null +++ b/drivers/fs/vfat/cleanup.c @@ -0,0 +1,90 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/cleanup.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +VfatCleanupFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject) +/* + * FUNCTION: Cleans up after a file has been closed. + */ +{ + PVFATCCB pCcb; + PVFATFCB pFcb; + + DPRINT("VfatCleanupFile(DeviceExt %x, FileObject %x)\n", + DeviceExt, FileObject); + + /* FIXME: handle file/directory deletion here */ + pCcb = (PVFATCCB) (FileObject->FsContext2); + if (pCcb == NULL) + { + return STATUS_SUCCESS; + } + pFcb = pCcb->pFcb; + + if (FileObject->FileName.Buffer) + { + if (pFcb->Flags & FCB_UPDATE_DIRENTRY) + { + VfatUpdateEntry (DeviceExt, FileObject); + pFcb->Flags &= ~FCB_UPDATE_DIRENTRY; + } + } + + /* Uninitialize the file cache. */ + CcRosReleaseFileCache (FileObject, pFcb->RFCB.Bcb); + + return STATUS_SUCCESS; +} + +NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Cleans up after a file has been closed. + */ +{ + NTSTATUS Status; + + DPRINT("VfatCleanup(DeviceObject %x, Irp %x)\n", DeviceObject, Irp); + + if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) + { + Status = STATUS_SUCCESS; + goto ByeBye; + } + + if (!ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return VfatQueueRequest (IrpContext); + } + + Status = VfatCleanupFile(IrpContext->DeviceExt, IrpContext->FileObject); + + ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource); + +ByeBye: + IrpContext->Irp->IoStatus.Status = Status; + IrpContext->Irp->IoStatus.Information = 0; + + IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + return (Status); +} + +/* EOF */ diff --git a/drivers/fs/vfat/close.c b/drivers/fs/vfat/close.c new file mode 100644 index 0000000..6dffc5c --- /dev/null +++ b/drivers/fs/vfat/close.c @@ -0,0 +1,115 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/close.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +VfatCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject) +/* + * FUNCTION: Closes a file + */ +{ + PVFATFCB pFcb; + PVFATCCB pCcb; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT ("VfatCloseFile(DeviceExt %x, FileObject %x)\n", + DeviceExt, FileObject); + + /* FIXME : update entry in directory? */ + pCcb = (PVFATCCB) (FileObject->FsContext2); + + DPRINT ("pCcb %x\n", pCcb); + if (pCcb == NULL) + { + return STATUS_SUCCESS; + } + pFcb = pCcb->pFcb; + if (pFcb->Flags & FCB_IS_VOLUME) + { + DPRINT1("Volume\n"); + pFcb->RefCount--; + FileObject->FsContext2 = NULL; + } + else if (FileObject->FileName.Buffer) + { + // This a FO, that was created outside from FSD. + // Some FO's are created with IoCreateStreamFileObject() insid from FSD. + // This FO's haven't a FileName. + if (FileObject->DeletePending) + { + if (pFcb->Flags & FCB_DELETE_PENDING) + { + delEntry (DeviceExt, FileObject); + pFcb->Flags &= ~FCB_UPDATE_DIRENTRY; + } + else + Status = STATUS_DELETE_PENDING; + } + if (pFcb->Flags & FCB_UPDATE_DIRENTRY) + { + VfatUpdateEntry (DeviceExt, FileObject); + pFcb->Flags &= ~FCB_UPDATE_DIRENTRY; + } + FileObject->FsContext2 = NULL; + vfatReleaseFCB (DeviceExt, pFcb); + } + else + FileObject->FsContext2 = NULL; + + if (pCcb->DirectorySearchPattern) + ExFreePool(pCcb->DirectorySearchPattern); + ExFreePool (pCcb); + + return Status; +} + +NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Closes a file + */ +{ + NTSTATUS Status; + + DPRINT ("VfatClose(DeviceObject %x, Irp %x)\n", DeviceObject, Irp); + + if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) + { + DPRINT("Closing file system\n"); + Status = STATUS_SUCCESS; + goto ByeBye; + } + + if (!ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return VfatQueueRequest (IrpContext); + } + + Status = VfatCloseFile (IrpContext->DeviceExt, IrpContext->FileObject); + ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource); + +ByeBye: + IrpContext->Irp->IoStatus.Status = Status; + IrpContext->Irp->IoStatus.Information = 0; + IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + + return (Status); +} + +/* EOF */ diff --git a/drivers/fs/vfat/create.c b/drivers/fs/vfat/create.c new file mode 100644 index 0000000..c9be403 --- /dev/null +++ b/drivers/fs/vfat/create.c @@ -0,0 +1,875 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/create.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* GLOBALS *******************************************************************/ + +#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry)) + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +IsLastEntry (PVOID Block, ULONG Offset) +/* + * FUNCTION: Determine if the given directory entry is the last + */ +{ + return (((FATDirEntry *) Block)[Offset].Filename[0] == 0); +} + +BOOLEAN +IsVolEntry (PVOID Block, ULONG Offset) +/* + * FUNCTION: Determine if the given directory entry is a vol entry + */ +{ + if ((((FATDirEntry *) Block)[Offset].Attrib) == 0x28) + return TRUE; + else + return FALSE; +} + +BOOLEAN +IsDeletedEntry (PVOID Block, ULONG Offset) +/* + * FUNCTION: Determines if the given entry is a deleted one + */ +{ + /* Checks special character */ + + return ((((FATDirEntry *) Block)[Offset].Filename[0] == 0xe5) || + (((FATDirEntry *) Block)[Offset].Filename[0] == 0)); +} + +void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName) +{ + int fromIndex, toIndex; + + fromIndex = toIndex = 0; + while (fromIndex < 8 && pBasename [fromIndex] != ' ') + { + pName [toIndex++] = pBasename [fromIndex++]; + } + if (pExtension [0] != ' ') + { + pName [toIndex++] = L'.'; + fromIndex = 0; + while (fromIndex < 3 && pExtension [fromIndex] != ' ') + { + pName [toIndex++] = pExtension [fromIndex++]; + } + } + pName [toIndex] = L'\0'; +} + +static void vfat8Dot3ToVolumeLabel (PCHAR pBasename, PCHAR pExtension, PWSTR pName) +{ + int fromIndex, toIndex; + + fromIndex = toIndex = 0; + while (fromIndex < 8 && pBasename [fromIndex] != ' ') + { + pName [toIndex++] = pBasename [fromIndex++]; + } + if (pExtension [0] != ' ') + { + fromIndex = 0; + while (fromIndex < 3 && pBasename [fromIndex] != ' ') + { + pName [toIndex++] = pExtension [fromIndex++]; + } + } + pName [toIndex] = L'\0'; +} + +NTSTATUS +GetEntryName(PVOID *pContext, + PVOID *Block, + PFILE_OBJECT FileObject, + PWSTR Name, + PULONG pIndex, + PULONG pIndex2) +/* + * FUNCTION: Retrieves the file name, be it in short or long file name format + */ +{ + NTSTATUS Status; + FATDirEntry * test; + slot * test2; + ULONG cpos; + ULONG Offset = *pIndex % ENTRIES_PER_PAGE; + ULONG Read; + LARGE_INTEGER FileOffset; + + *Name = 0; + while (TRUE) + { + test = (FATDirEntry *) *Block; + test2 = (slot *) *Block; + if (vfatIsDirEntryEndMarker(&test[Offset])) + { + return STATUS_NO_MORE_ENTRIES; + } + if (test2[Offset].attr == 0x0f && !vfatIsDirEntryDeleted(&test[Offset])) + { + *Name = 0; + if (pIndex2) + *pIndex2 = *pIndex; // start of dir entry + + DPRINT (" long name entry found at %d\n", *pIndex); + + DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n", + 5, test2 [Offset].name0_4, + 6, test2 [Offset].name5_10, + 2, test2 [Offset].name11_12); + + vfat_initstr (Name, 255); + vfat_wcsncpy (Name, test2[Offset].name0_4, 5); + vfat_wcsncat (Name, test2[Offset].name5_10, 5, 6); + vfat_wcsncat (Name, test2[Offset].name11_12, 11, 2); + + DPRINT (" longName: [%S]\n", Name); + cpos = 0; + while ((test2[Offset].id != 0x41) && (test2[Offset].id != 0x01) && + (test2[Offset].attr > 0)) + { + (*pIndex)++; + Offset++; + + if (Offset == ENTRIES_PER_PAGE) + { + Offset = 0; + CcUnpinData(*pContext); + FileOffset.QuadPart = *pIndex * sizeof(FATDirEntry); + if(!CcMapData(FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, Block)) + { + *pContext = NULL; + return STATUS_NO_MORE_ENTRIES; + } + test2 = (slot *) *Block; + } + DPRINT (" long name entry found at %d\n", *pIndex); + + DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n", + 5, test2 [Offset].name0_4, + 6, test2 [Offset].name5_10, + 2, test2 [Offset].name11_12); + + cpos++; + vfat_movstr (Name, 13, 0, cpos * 13); + vfat_wcsncpy (Name, test2[Offset].name0_4, 5); + vfat_wcsncat (Name, test2[Offset].name5_10, 5, 6); + vfat_wcsncat (Name, test2[Offset].name11_12, 11, 2); + + DPRINT (" longName: [%S]\n", Name); + } + (*pIndex)++; + Offset++; + if (Offset == ENTRIES_PER_PAGE) + { + Offset = 0; + CcUnpinData(*pContext); + FileOffset.QuadPart = *pIndex * sizeof(FATDirEntry); + if(!CcMapData(FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, Block)) + { + *pContext = NULL; + return STATUS_NO_MORE_ENTRIES; + } + test2 = (slot *) *Block; + test = (FATDirEntry*) *Block; + } + } + else + { + if (vfatIsDirEntryEndMarker(&test[Offset])) + return STATUS_NO_MORE_ENTRIES; + if (vfatIsDirEntryDeleted(&test[Offset])) + return STATUS_UNSUCCESSFUL; + if (*Name == 0) + { + vfat8Dot3ToString (test[Offset].Filename, test[Offset].Ext, Name); + if (pIndex2) + *pIndex2 = *pIndex; + } + break; + } + } + return STATUS_SUCCESS; +} + +NTSTATUS +ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb) +/* + * FUNCTION: Read the volume label + */ +{ + PVOID Context = NULL; + ULONG Offset = 0; + ULONG DirIndex = 0; + FATDirEntry* Entry; + PVFATFCB pFcb; + LARGE_INTEGER FileOffset; + + *(Vpb->VolumeLabel) = 0; + Vpb->VolumeLabelLength = 0; + + pFcb = vfatOpenRootFCB (DeviceExt); + + while (TRUE) + { + if (Context == NULL || Offset == ENTRIES_PER_PAGE) + { + if (Offset == ENTRIES_PER_PAGE) + { + Offset = 0; + } + if (Context) + { + CcUnpinData(Context); + } + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = (DirIndex - Offset) * sizeof(FATDirEntry); + if (!CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry)) + { + Context = NULL; + break; + } + } + if (IsVolEntry(Entry, Offset)) + { + /* copy volume label */ + vfat8Dot3ToVolumeLabel (Entry[Offset].Filename, Entry[Offset].Ext, Vpb->VolumeLabel); + Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR); + break; + } + if (IsLastEntry(Entry, Offset)) + { + break; + } + Offset++; + DirIndex++; + } + + if (Context) + { + CcUnpinData(Context); + } + vfatReleaseFCB (DeviceExt, pFcb); + + return STATUS_SUCCESS; +} + +NTSTATUS +FindFile (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + PVFATFCB Parent, + PWSTR FileToFind, + ULONG *pDirIndex, + ULONG *pDirIndex2) +/* + * FUNCTION: Find a file + */ +{ + WCHAR name[256]; + WCHAR name2[14]; + char * block; + WCHAR TempStr[2]; + NTSTATUS Status; + ULONG len; + ULONG DirIndex; + ULONG Offset; + ULONG FirstCluster; + ULONG Read; + BOOL isRoot; + LARGE_INTEGER FileOffset; + PVOID Context = NULL; + + DPRINT ("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", Parent, FileToFind, pDirIndex ? *pDirIndex : 0); + DPRINT ("FindFile: old Pathname %x, old Objectname %x)\n",Fcb->PathName, Fcb->ObjectName); + + isRoot = FALSE; + DirIndex = 0; + if (wcslen (FileToFind) == 0) + { + CHECKPOINT; + TempStr[0] = (WCHAR) '.'; + TempStr[1] = 0; + FileToFind = (PWSTR)&TempStr; + } + if (Parent) + { + FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Parent->entry); + if (DeviceExt->FatInfo.FatType == FAT32) + { + if (FirstCluster == DeviceExt->FatInfo.RootCluster) + isRoot = TRUE; + } + else + { + if (FirstCluster == 1) + isRoot = TRUE; + } + } + else + isRoot = TRUE; + if (isRoot) + { + if (DeviceExt->FatInfo.FatType == FAT32) + FirstCluster = DeviceExt->FatInfo.RootCluster; + else + FirstCluster = 1; + + if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0) + || (FileToFind[0] == '.' && FileToFind[1] == 0)) + { + /* it's root : complete essentials fields then return ok */ + CHECKPOINT; + memset (Fcb, 0, sizeof (VFATFCB)); + memset (Fcb->entry.Filename, ' ', 11); + CHECKPOINT; + Fcb->PathName[0]='\\'; + Fcb->ObjectName = &Fcb->PathName[1]; + Fcb->entry.FileSize = DeviceExt->FatInfo.rootDirectorySectors * DeviceExt->FatInfo.BytesPerSector; + Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY; + if (DeviceExt->FatInfo.FatType == FAT32) + { + Fcb->entry.FirstCluster = ((PUSHORT)FirstCluster)[0]; + Fcb->entry.FirstClusterHigh = ((PUSHORT)FirstCluster)[1]; + } + else + Fcb->entry.FirstCluster = 1; + if (pDirIndex) + *pDirIndex = 0; + if (pDirIndex2) + *pDirIndex2 = 0; + DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName); + return (STATUS_SUCCESS); + } + } + else + { + DPRINT ("Parent->entry.FileSize %x\n", Parent->entry.FileSize); + FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Parent->entry); + } + if (pDirIndex && (*pDirIndex)) + DirIndex = *pDirIndex; + + Offset = DirIndex % ENTRIES_PER_PAGE; + while(TRUE) + { + if (Context == NULL || Offset == ENTRIES_PER_PAGE) + { + if (Offset == ENTRIES_PER_PAGE) + Offset = 0; + if (Context) + { + CcUnpinData(Context); + } + FileOffset.QuadPart = (DirIndex - Offset) * sizeof(FATDirEntry); + if (!CcMapData(Parent->FileObject, &FileOffset, PAGE_SIZE, TRUE, + &Context, (PVOID*)&block)) + { + Context = NULL; + break; + } + } + if (vfatIsDirEntryVolume(&((FATDirEntry*)block)[Offset])) + { + Offset++; + DirIndex++; + continue; + } + Status = GetEntryName (&Context, (PVOID*)&block, Parent->FileObject, name, + &DirIndex, pDirIndex2); + if (Status == STATUS_NO_MORE_ENTRIES) + break; + Offset = DirIndex % ENTRIES_PER_PAGE; + if (NT_SUCCESS(Status)) + { + vfat8Dot3ToString(((FATDirEntry *) block)[Offset].Filename,((FATDirEntry *) block)[Offset].Ext, name2); + if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind)) + { + if (Parent && Parent->PathName) + { + len = wcslen(Parent->PathName); + CHECKPOINT; + memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR)); + Fcb->ObjectName=&Fcb->PathName[len]; + if (len != 1 || Fcb->PathName[0] != '\\') + { + Fcb->ObjectName[0] = '\\'; + Fcb->ObjectName = &Fcb->ObjectName[1]; + } + } + else + { + Fcb->ObjectName=Fcb->PathName; + Fcb->ObjectName[0]='\\'; + Fcb->ObjectName=&Fcb->ObjectName[1]; + } + + memcpy (&Fcb->entry, &((FATDirEntry *) block)[Offset], + sizeof (FATDirEntry)); + vfat_wcsncpy (Fcb->ObjectName, name, MAX_PATH); + if (pDirIndex) + *pDirIndex = DirIndex; + DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb->PathName, Fcb->ObjectName, DirIndex); + if (Context) + CcUnpinData(Context); + return STATUS_SUCCESS; + } + } + Offset++; + DirIndex++; + } + if (pDirIndex) + *pDirIndex = DirIndex; + if (Context) + CcUnpinData(Context); + return (STATUS_UNSUCCESSFUL); +} + +NTSTATUS +vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject, + PWSTR pRelativeFileName, + PWSTR *pAbsoluteFilename) +{ + PWSTR rcName; + PVFATFCB fcb; + PVFATCCB ccb; + + DPRINT ("try related for %S\n", pRelativeFileName); + ccb = pFileObject->FsContext2; + assert (ccb); + fcb = ccb->pFcb; + assert (fcb); + + /* verify related object is a directory and target name + don't start with \. */ + if (!(fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) + || (pRelativeFileName[0] == L'\\')) + { + return STATUS_INVALID_PARAMETER; + } + + /* construct absolute path name */ + assert (wcslen (fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1 + <= MAX_PATH); + rcName = ExAllocatePool (NonPagedPool, MAX_PATH * sizeof(WCHAR)); + if (!rcName) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + wcscpy (rcName, fcb->PathName); + if (!vfatFCBIsRoot(fcb)) + wcscat (rcName, L"\\"); + wcscat (rcName, pRelativeFileName); + *pAbsoluteFilename = rcName; + + return STATUS_SUCCESS; +} + +NTSTATUS +VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PWSTR FileName) +/* + * FUNCTION: Opens a file + */ +{ + PVFATFCB ParentFcb; + PVFATFCB Fcb; + NTSTATUS Status; + PWSTR AbsFileName = NULL; + + DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName); + + if (FileObject->RelatedFileObject) + { + DPRINT ("Converting relative filename to absolute filename\n"); + Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject, + FileName, + &AbsFileName); + FileName = AbsFileName; + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + + //FIXME: Get cannonical path name (remove .'s, ..'s and extra separators) + + DPRINT ("PathName to open: %S\n", FileName); + + /* try first to find an existing FCB in memory */ + DPRINT ("Checking for existing FCB in memory\n"); + Fcb = vfatGrabFCBFromTable (DeviceExt, FileName); + if (Fcb == NULL) + { + DPRINT ("No existing FCB found, making a new one if file exists.\n"); + Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName); + if (ParentFcb != NULL) + { + vfatReleaseFCB (DeviceExt, ParentFcb); + } + if (!NT_SUCCESS (Status)) + { + DPRINT ("Could not make a new FCB, status: %x\n", Status); + + if (AbsFileName) + ExFreePool (AbsFileName); + + return Status; + } + } + if (Fcb->Flags & FCB_DELETE_PENDING) + { + vfatReleaseFCB (DeviceExt, Fcb); + if (AbsFileName) + ExFreePool (AbsFileName); + return STATUS_DELETE_PENDING; + } + DPRINT ("Attaching FCB to fileObject\n"); + Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject); + + if (AbsFileName) + ExFreePool (AbsFileName); + + return Status; +} + +VOID STATIC +VfatPagingFileCreate(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb) +{ + ULONG CurrentCluster, NextCluster, i; + NTSTATUS Status; + + Fcb->Flags |= FCB_IS_PAGE_FILE; + Fcb->FatChainSize = + ((Fcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster); + if (Fcb->FatChainSize) + { + Fcb->FatChain = + ExAllocatePool(NonPagedPool, Fcb->FatChainSize * sizeof(ULONG)); + } + + if (DeviceExt->FatInfo.FatType == FAT32) + { + CurrentCluster = Fcb->entry.FirstCluster + + Fcb->entry.FirstClusterHigh * 65536; + } + else + { + CurrentCluster = Fcb->entry.FirstCluster; + } + + i = 0; + if (Fcb->FatChainSize) + { + while (CurrentCluster != 0xffffffff) + { + Fcb->FatChain[i] = CurrentCluster; + Status = GetNextCluster (DeviceExt, CurrentCluster, + &NextCluster, FALSE); + i++; + CurrentCluster = NextCluster; + } + } +} + +VOID STATIC +VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PVFATFCB Fcb) +{ + ULONG Cluster, NextCluster; + NTSTATUS Status; + + Fcb->entry.FileSize = 0; + if (DeviceExt->FatInfo.FatType == FAT32) + { + Cluster = Fcb->entry.FirstCluster + Fcb->entry.FirstClusterHigh * 65536; + } + else + { + Cluster = Fcb->entry.FirstCluster; + } + Fcb->entry.FirstCluster = 0; + Fcb->entry.FirstClusterHigh = 0; + VfatUpdateEntry (DeviceExt, FileObject); + if (Fcb->RFCB.FileSize.QuadPart > 0) + { + Fcb->RFCB.AllocationSize.QuadPart = 0; + Fcb->RFCB.FileSize.QuadPart = 0; + Fcb->RFCB.ValidDataLength.QuadPart = 0; + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize); + } + while (Cluster != 0xffffffff && Cluster > 1) + { + Status = GetNextCluster (DeviceExt, Cluster, &NextCluster, FALSE); + WriteCluster (DeviceExt, Cluster, 0); + Cluster = NextCluster; + } +} + +NTSTATUS +VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp) +/* + * FUNCTION: Create or open a file + */ +{ + PIO_STACK_LOCATION Stack; + PFILE_OBJECT FileObject; + NTSTATUS Status = STATUS_SUCCESS; + PDEVICE_EXTENSION DeviceExt; + ULONG RequestedDisposition, RequestedOptions; + PVFATCCB pCcb; + PVFATFCB pFcb; + PWCHAR c; + BOOLEAN PagingFileCreate = FALSE; + + /* Unpack the various parameters. */ + Stack = IoGetCurrentIrpStackLocation (Irp); + RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff); + RequestedOptions = + Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; + PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE; + FileObject = Stack->FileObject; + DeviceExt = DeviceObject->DeviceExtension; + + /* Check their validity. */ + if (RequestedOptions & FILE_DIRECTORY_FILE && + RequestedDisposition == FILE_SUPERSEDE) + { + return(STATUS_INVALID_PARAMETER); + } + + /* This a open operation for the volume itself */ + if (FileObject->FileName.Length == 0 && + FileObject->RelatedFileObject == NULL) + { + if (RequestedDisposition == FILE_CREATE || + RequestedDisposition == FILE_OVERWRITE_IF || + RequestedDisposition == FILE_SUPERSEDE) + { + return(STATUS_ACCESS_DENIED); + } + if (RequestedOptions & FILE_DIRECTORY_FILE) + { + return(STATUS_NOT_A_DIRECTORY); + } + pFcb = DeviceExt->VolumeFcb; + pCcb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB); + if (pCcb == NULL) + { + return (STATUS_INSUFFICIENT_RESOURCES); + } + memset(pCcb, 0, sizeof(VFATCCB)); + FileObject->Flags |= FO_FCB_IS_VALID; + FileObject->SectionObjectPointers = &pFcb->SectionObjectPointers; + FileObject->FsContext = (PVOID) &pFcb->RFCB; + FileObject->FsContext2 = pCcb; + pCcb->pFcb = pFcb; + pCcb->PtrFileObject = FileObject; + pFcb->pDevExt = DeviceExt; + pFcb->RefCount++; + + Irp->IoStatus.Information = FILE_OPENED; + return(STATUS_SUCCESS); + } + + /* + * Check for illegal characters in the file name + */ + c = FileObject->FileName.Buffer; + while (*c != 0) + { + if (*c == L'*' || *c == L'?' || (*c == L'\\' && c[1] == L'\\')) + { + return(STATUS_OBJECT_NAME_INVALID); + } + c++; + } + + /* Try opening the file. */ + Status = VfatOpenFile (DeviceExt, FileObject, FileObject->FileName.Buffer); + + /* + * If the directory containing the file to open doesn't exist then + * fail immediately + */ + if (Status == STATUS_OBJECT_PATH_NOT_FOUND || + Status == STATUS_INVALID_PARAMETER || + Status == STATUS_DELETE_PENDING) + { + return(Status); + } + + /* + * If the file open failed then create the required file + */ + if (!NT_SUCCESS (Status)) + { + if (RequestedDisposition == FILE_CREATE || + RequestedDisposition == FILE_OPEN_IF || + RequestedDisposition == FILE_OVERWRITE_IF || + RequestedDisposition == FILE_SUPERSEDE) + { + ULONG Attributes; + Attributes = Stack->Parameters.Create.FileAttributes; + Status = VfatAddEntry (DeviceExt, FileObject, RequestedOptions, + Attributes & FILE_ATTRIBUTE_VALID_FLAGS); + if (NT_SUCCESS (Status)) + { + pCcb = FileObject->FsContext2; + pFcb = pCcb->pFcb; + Irp->IoStatus.Information = FILE_CREATED; + VfatSetAllocationSizeInformation(FileObject, + pFcb, + DeviceExt, + &Irp->Overlay.AllocationSize); + VfatSetExtendedAttributes(FileObject, + Irp->AssociatedIrp.SystemBuffer, + Stack->Parameters.Create.EaLength); + IoSetShareAccess(0 /*DesiredAccess*/, + Stack->Parameters.Create.ShareAccess, + FileObject, + &pFcb->FCBShareAccess); + } + else + { + return(Status); + } + } + else + { + return(Status); + } + } + else + { + /* Otherwise fail if the caller wanted to create a new file */ + if (RequestedDisposition == FILE_CREATE) + { + Irp->IoStatus.Information = FILE_EXISTS; + return(STATUS_OBJECT_NAME_COLLISION); + } + + pCcb = FileObject->FsContext2; + pFcb = pCcb->pFcb; + + /* + * Check the file has the requested attributes + */ + if (RequestedOptions & FILE_NON_DIRECTORY_FILE && + pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) + { + VfatCloseFile (DeviceExt, FileObject); + return(STATUS_FILE_IS_A_DIRECTORY); + } + if (RequestedOptions & FILE_DIRECTORY_FILE && + !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)) + { + VfatCloseFile (DeviceExt, FileObject); + return(STATUS_NOT_A_DIRECTORY); + } + + /* Supersede the file */ + if (RequestedDisposition == FILE_SUPERSEDE) + { + VfatSupersedeFile(DeviceExt, FileObject, pFcb); + Irp->IoStatus.Information = FILE_SUPERSEDED; + } + else + { + Irp->IoStatus.Information = FILE_OPENED; + } + } + + /* + * If this create was for a paging file then make sure all the + * information needed to manipulate it is locked in memory. + */ + if (PagingFileCreate) + { + VfatPagingFileCreate(DeviceExt, pFcb); + } + + /* FIXME : test share access */ + /* FIXME : test write access if requested */ + + return(Status); +} + + +NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Create or open a file + */ +{ + NTSTATUS Status; + + assert (IrpContext); + + if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) + { + /* DeviceObject represents FileSystem instead of logical volume */ + DPRINT ("FsdCreate called with file system\n"); + IrpContext->Irp->IoStatus.Information = FILE_OPENED; + IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest (IrpContext->Irp, IO_DISK_INCREMENT); + VfatFreeIrpContext(IrpContext); + return(STATUS_SUCCESS); + } + + if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return(VfatQueueRequest (IrpContext)); + } + + IrpContext->Irp->IoStatus.Information = 0; + ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE); + Status = VfatCreateFile (IrpContext->DeviceObject, IrpContext->Irp); + ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource); + + IrpContext->Irp->IoStatus.Status = Status; + IoCompleteRequest (IrpContext->Irp, + NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/vfat/dir.c b/drivers/fs/vfat/dir.c new file mode 100644 index 0000000..91dbe1d --- /dev/null +++ b/drivers/fs/vfat/dir.c @@ -0,0 +1,416 @@ +/* + * $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/dir.c + * PURPOSE: VFAT Filesystem : directory control + * UPDATE HISTORY: + 19-12-1998 : created + +*/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + + +// function like DosDateTimeToFileTime +BOOL FsdDosDateTimeToFileTime (WORD wDosDate, WORD wDosTime, TIME * FileTime) +{ + PDOSTIME pdtime = (PDOSTIME) & wDosTime; + PDOSDATE pddate = (PDOSDATE) & wDosDate; + TIME_FIELDS TimeFields; + + if (FileTime == NULL) + return FALSE; + + TimeFields.Milliseconds = 0; + TimeFields.Second = pdtime->Second * 2; + TimeFields.Minute = pdtime->Minute; + TimeFields.Hour = pdtime->Hour; + + TimeFields.Day = pddate->Day; + TimeFields.Month = pddate->Month; + TimeFields.Year = 1980 + pddate->Year; + + RtlTimeFieldsToTime (&TimeFields, (PLARGE_INTEGER) FileTime); + + return TRUE; +} + + +// function like FileTimeToDosDateTime +BOOL +FsdFileTimeToDosDateTime (TIME * FileTime, WORD * pwDosDate, WORD * pwDosTime) +{ + PDOSTIME pdtime = (PDOSTIME) pwDosTime; + PDOSDATE pddate = (PDOSDATE) pwDosDate; + TIME_FIELDS TimeFields; + + if (FileTime == NULL) + return FALSE; + + RtlTimeToTimeFields ((PLARGE_INTEGER) FileTime, &TimeFields); + + if (pdtime) + { + pdtime->Second = TimeFields.Second / 2; + pdtime->Minute = TimeFields.Minute; + pdtime->Hour = TimeFields.Hour; + } + + if (pddate) + { + pddate->Day = TimeFields.Day; + pddate->Month = TimeFields.Month; + pddate->Year = TimeFields.Year - 1980; + } + + return TRUE; +} + + + +unsigned long +vfat_wstrlen (PWSTR s) +{ + WCHAR c = ' '; + unsigned int len = 0; + + while (c != 0) + { + c = *s; + s++; + len++; + }; + s -= len; + + return len - 1; +} + +#define DWORD_ROUND_UP(x) ( (((ULONG)(x))%32) ? ((((ULONG)x)&(~0x1f))+0x20) : ((ULONG)x) ) + +NTSTATUS +VfatGetFileNameInformation (PVFATFCB pFcb, + PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength) +{ + ULONG Length; + Length = vfat_wstrlen (pFcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength) + return STATUS_BUFFER_OVERFLOW; + pInfo->FileNameLength = Length; + pInfo->NextEntryOffset = + DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length); + memcpy (pInfo->FileName, pFcb->ObjectName, Length); + return STATUS_SUCCESS; +} + +NTSTATUS +VfatGetFileDirectoryInformation (PVFATFCB pFcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_DIRECTORY_INFORMATION pInfo, + ULONG BufferLength) +{ + unsigned long long AllocSize; + ULONG Length; + Length = vfat_wstrlen (pFcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength) + return STATUS_BUFFER_OVERFLOW; + pInfo->FileNameLength = Length; + pInfo->NextEntryOffset = + DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length); + memcpy (pInfo->FileName, pFcb->ObjectName, Length); +// pInfo->FileIndex=; + FsdDosDateTimeToFileTime (pFcb->entry.CreationDate, + pFcb->entry.CreationTime, &pInfo->CreationTime); + FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0, + &pInfo->LastAccessTime); + FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, + &pInfo->LastWriteTime); + FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, + &pInfo->ChangeTime); + pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize); + /* Make allocsize a rounded up multiple of BytesPerCluster */ + AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster; + pInfo->AllocationSize.QuadPart = AllocSize; + pInfo->FileAttributes = pFcb->entry.Attrib; + + return STATUS_SUCCESS; +} + +NTSTATUS +VfatGetFileFullDirectoryInformation (PVFATFCB pFcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_FULL_DIRECTORY_INFORMATION pInfo, + ULONG BufferLength) +{ + unsigned long long AllocSize; + ULONG Length; + Length = vfat_wstrlen (pFcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength) + return STATUS_BUFFER_OVERFLOW; + pInfo->FileNameLength = Length; + pInfo->NextEntryOffset = + DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length); + memcpy (pInfo->FileName, pFcb->ObjectName, Length); +// pInfo->FileIndex=; + FsdDosDateTimeToFileTime (pFcb->entry.CreationDate, + pFcb->entry.CreationTime, &pInfo->CreationTime); + FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0, + &pInfo->LastAccessTime); + FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, + &pInfo->LastWriteTime); + FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, + &pInfo->ChangeTime); + pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize); + /* Make allocsize a rounded up multiple of BytesPerCluster */ + AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster; + pInfo->AllocationSize.QuadPart = AllocSize; + pInfo->FileAttributes = pFcb->entry.Attrib; +// pInfo->EaSize=; + return STATUS_SUCCESS; +} + +NTSTATUS +VfatGetFileBothInformation (PVFATFCB pFcb, + PDEVICE_EXTENSION DeviceExt, + PFILE_BOTH_DIRECTORY_INFORMATION pInfo, + ULONG BufferLength) +{ + short i; + unsigned long long AllocSize; + ULONG Length; + Length = vfat_wstrlen (pFcb->ObjectName) * sizeof(WCHAR); + if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength) + return STATUS_BUFFER_OVERFLOW; + pInfo->FileNameLength = Length; + pInfo->NextEntryOffset = + DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length); + memcpy (pInfo->FileName, pFcb->ObjectName, Length); +// pInfo->FileIndex=; + FsdDosDateTimeToFileTime (pFcb->entry.CreationDate, + pFcb->entry.CreationTime, &pInfo->CreationTime); + FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0, + &pInfo->LastAccessTime); + FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, + &pInfo->LastWriteTime); + FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime, + &pInfo->ChangeTime); + pInfo->EndOfFile = RtlConvertUlongToLargeInteger (pFcb->entry.FileSize); + /* Make allocsize a rounded up multiple of BytesPerCluster */ + AllocSize = ((pFcb->entry.FileSize + DeviceExt->FatInfo.BytesPerCluster - 1) / + DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.BytesPerCluster; + pInfo->AllocationSize.QuadPart = AllocSize; + pInfo->FileAttributes = pFcb->entry.Attrib; +// pInfo->EaSize=; + for (i = 0; i < 8 && (pFcb->entry.Filename[i] != ' '); i++) + pInfo->ShortName[i] = pFcb->entry.Filename[i]; + pInfo->ShortNameLength = i; + pInfo->ShortName[i] = '.'; + for (i = 0; i < 3 && (pFcb->entry.Ext[i] != ' '); i++) + pInfo->ShortName[i + 1 + pInfo->ShortNameLength] = pFcb->entry.Ext[i]; + if (i) + pInfo->ShortNameLength += (i + 1); + pInfo->ShortNameLength *= sizeof(WCHAR); + return STATUS_SUCCESS; +} + +NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext) +{ + NTSTATUS RC = STATUS_SUCCESS; + long BufferLength = 0; + PUNICODE_STRING pSearchPattern = NULL; + FILE_INFORMATION_CLASS FileInformationClass; + unsigned long FileIndex = 0; + unsigned char *Buffer = NULL; + PFILE_NAMES_INFORMATION Buffer0 = NULL; + PVFATFCB pFcb; + VFATFCB tmpFcb; + PVFATCCB pCcb; + BOOLEAN First = FALSE; + + pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2; + pFcb = pCcb->pFcb; + + if (!ExAcquireResourceSharedLite(&pFcb->MainResource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return STATUS_PENDING; + } + + // Obtain the callers parameters + BufferLength = IrpContext->Stack->Parameters.QueryDirectory.Length; + pSearchPattern = IrpContext->Stack->Parameters.QueryDirectory.FileName; + FileInformationClass = + IrpContext->Stack->Parameters.QueryDirectory.FileInformationClass; + FileIndex = IrpContext->Stack->Parameters.QueryDirectory.FileIndex; + if (pSearchPattern) + { + if (!pCcb->DirectorySearchPattern) + { + First = TRUE; + pCcb->DirectorySearchPattern = + ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR)); + if (!pCcb->DirectorySearchPattern) + { + ExReleaseResourceLite(&pFcb->MainResource); + return STATUS_INSUFFICIENT_RESOURCES; + } + memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer, + pSearchPattern->Length); + pCcb->DirectorySearchPattern[pSearchPattern->Length / sizeof(WCHAR)] = 0; + } + } + else if (!pCcb->DirectorySearchPattern) + { + First = TRUE; + pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR)); + if (!pCcb->DirectorySearchPattern) + { + ExReleaseResourceLite(&pFcb->MainResource); + return STATUS_INSUFFICIENT_RESOURCES; + } + pCcb->DirectorySearchPattern[0] = L'*'; + pCcb->DirectorySearchPattern[1] = 0; + } + + if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED) + { + pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart; + } + else if (First || (IrpContext->Stack->Flags & SL_RESTART_SCAN)) + { + pCcb->Entry = 0; + } + // determine Buffer for result : + if (IrpContext->Irp->MdlAddress) + { + Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress); + } + else + { + Buffer = IrpContext->Irp->UserBuffer; + } + DPRINT ("Buffer=%x tofind=%S\n", Buffer, pCcb->DirectorySearchPattern); + + tmpFcb.ObjectName = tmpFcb.PathName; + while (RC == STATUS_SUCCESS && BufferLength > 0) + { + RC = FindFile (IrpContext->DeviceExt, &tmpFcb, pFcb, + pCcb->DirectorySearchPattern, &pCcb->Entry, NULL); + DPRINT ("Found %S, RC=%x, entry %x\n", tmpFcb.ObjectName, RC, pCcb->Entry); + if (NT_SUCCESS (RC)) + { + switch (FileInformationClass) + { + case FileNameInformation: + RC = VfatGetFileNameInformation (&tmpFcb, + (PFILE_NAMES_INFORMATION) Buffer, BufferLength); + break; + case FileDirectoryInformation: + RC = VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt, + (PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength); + break; + case FileFullDirectoryInformation: + RC = VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt, + (PFILE_FULL_DIRECTORY_INFORMATION) Buffer, BufferLength); + break; + case FileBothDirectoryInformation: + RC = VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt, + (PFILE_BOTH_DIRECTORY_INFORMATION) Buffer, BufferLength); + break; + default: + RC = STATUS_INVALID_INFO_CLASS; + } + if (RC == STATUS_BUFFER_OVERFLOW) + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + break; + } + } + else + { + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + if (First) + { + RC = STATUS_NO_SUCH_FILE; + } + else + { + RC = STATUS_NO_MORE_FILES; + } + break; + } + Buffer0 = (PFILE_NAMES_INFORMATION) Buffer; + Buffer0->FileIndex = FileIndex++; + pCcb->Entry++; + if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY) + { + break; + } + BufferLength -= Buffer0->NextEntryOffset; + Buffer += Buffer0->NextEntryOffset; + } + if (Buffer0) + { + Buffer0->NextEntryOffset = 0; + } + if (FileIndex > 0) + { + RC = STATUS_SUCCESS; + } + ExReleaseResourceLite(&pFcb->MainResource); + return RC; +} + + +NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: directory control : read/write directory informations + */ +{ + NTSTATUS RC = STATUS_SUCCESS; + CHECKPOINT; + switch (IrpContext->MinorFunction) + { + case IRP_MN_QUERY_DIRECTORY: + RC = DoQuery (IrpContext); + break; + case IRP_MN_NOTIFY_CHANGE_DIRECTORY: + DPRINT (" vfat, dir : change\n"); + RC = STATUS_NOT_IMPLEMENTED; + break; + default: + // error + DbgPrint ("unexpected minor function %x in VFAT driver\n", + IrpContext->MinorFunction); + RC = STATUS_INVALID_DEVICE_REQUEST; + break; + } + if (RC == STATUS_PENDING) + { + RC = VfatQueueRequest(IrpContext); + } + else + { + IrpContext->Irp->IoStatus.Status = RC; + IrpContext->Irp->IoStatus.Information = 0; + IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + } + return RC; +} + + diff --git a/drivers/fs/vfat/direntry.c b/drivers/fs/vfat/direntry.c new file mode 100644 index 0000000..97ca117 --- /dev/null +++ b/drivers/fs/vfat/direntry.c @@ -0,0 +1,206 @@ +/* $Id$ + * + * + * FILE: DirEntry.c + * PURPOSE: Routines to manipulate directory entries. + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * Rex Jolliff (rex@lvcablemodem.com) + */ + +/* ------------------------------------------------------- INCLUDES */ + +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \ + (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE) + +#define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \ + (CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->FatInfo.BytesPerSector))) + + +ULONG +vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, + PFAT_DIR_ENTRY pFatDirEntry) +{ + ULONG cluster; + + if (pDeviceExt->FatInfo.FatType == FAT32) + { + cluster = pFatDirEntry->FirstCluster + + pFatDirEntry->FirstClusterHigh * 65536; + } + else + { + cluster = pFatDirEntry->FirstCluster; + } + + return cluster; +} + +BOOL +vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry) +{ + return pFatDirEntry->Filename [0] == 0xe5; +} + +BOOL +vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry) +{ + return pFatDirEntry->Filename [0] == 0; +} + +BOOL +vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry) +{ + return pFatDirEntry->Attrib == 0x0f; +} + +BOOL +vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry) +{ + return pFatDirEntry->Attrib == 0x28; +} + +void +vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName) +{ + vfat8Dot3ToString (dirEntry->Filename, dirEntry->Ext, entryName); +} + +NTSTATUS +vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt, + PVFATFCB pDirectoryFCB, + ULONG * pDirectoryIndex, + PWSTR pLongFileName, + PFAT_DIR_ENTRY pDirEntry) +{ + ULONG indexInPage = *pDirectoryIndex % ENTRIES_PER_CACHEPAGE(pDeviceExt); + ULONG pageNumber = *pDirectoryIndex / ENTRIES_PER_CACHEPAGE(pDeviceExt); + PVOID currentPage = NULL; + FATDirEntry * fatDirEntry; + slot * longNameEntry; + ULONG cpos; + LARGE_INTEGER FileOffset; + PVOID Context; + + DPRINT ("vfatGetNextDirEntry (%x,%x,%d,%x,%x)\n", + pDeviceExt, + pDirectoryFCB, + *pDirectoryIndex, + pLongFileName, + pDirEntry); + + *pLongFileName = 0; + + FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt); + if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset, + CACHEPAGESIZE(pDeviceExt), TRUE, &Context, ¤tPage)) + { + return STATUS_UNSUCCESSFUL; + } + + while (TRUE) + { + fatDirEntry = (FATDirEntry *) currentPage; + + if (vfatIsDirEntryEndMarker (&fatDirEntry [indexInPage])) + { + DPRINT ("end of directory, returning no more entries\n"); + CcUnpinData(Context); + return STATUS_NO_MORE_ENTRIES; + } + else if (vfatIsDirEntryLongName (&fatDirEntry [indexInPage]) + && !vfatIsDirEntryDeleted (&fatDirEntry [indexInPage])) + { + DPRINT (" long name entry found at %d\n", *pDirectoryIndex); + longNameEntry = (slot *) currentPage; + + DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n", + 5, longNameEntry [indexInPage].name0_4, + 6, longNameEntry [indexInPage].name5_10, + 2, longNameEntry [indexInPage].name11_12); + + vfat_initstr (pLongFileName, 256); + vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5); + vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6); + vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2); + + DPRINT (" longName: [%S]\n", pLongFileName); + + cpos = 0; + while ((longNameEntry [indexInPage].id != 0x41) && + (longNameEntry [indexInPage].id != 0x01) && + (longNameEntry [indexInPage].attr > 0)) + { + (*pDirectoryIndex)++; + indexInPage++; + if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt)) + { + indexInPage = 0; + pageNumber++; + + CcUnpinData(Context); + FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt); + if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset, + CACHEPAGESIZE(pDeviceExt), TRUE, &Context, ¤tPage)) + { + return STATUS_UNSUCCESSFUL; + } + longNameEntry = (slot *) currentPage; + } + DPRINT (" index %d\n", *pDirectoryIndex); + + DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n", + 5, longNameEntry [indexInPage].name0_4, + 6, longNameEntry [indexInPage].name5_10, + 2, longNameEntry [indexInPage].name11_12); + + cpos++; + vfat_movstr (pLongFileName, 13, 0, cpos * 13); + vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5); + vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6); + vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2); + + DPRINT (" longName: [%S]\n", pLongFileName); + + } + (*pDirectoryIndex)++; + indexInPage++; + if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt)) + { + indexInPage = 0; + pageNumber++; + + CcUnpinData(Context); + FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt); + if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset, + CACHEPAGESIZE(pDeviceExt), TRUE, &Context, ¤tPage)) + { + return STATUS_UNSUCCESSFUL; + } + } + } + else + { + memcpy (pDirEntry, &fatDirEntry [indexInPage], sizeof (FAT_DIR_ENTRY)); + (*pDirectoryIndex)++; + break; + } + } + CcUnpinData(Context); + return STATUS_SUCCESS; +} + + + + + diff --git a/drivers/fs/vfat/dirwr.c b/drivers/fs/vfat/dirwr.c new file mode 100644 index 0000000..e78d8d0 --- /dev/null +++ b/drivers/fs/vfat/dirwr.c @@ -0,0 +1,652 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/dirwr.c + * PURPOSE: VFAT Filesystem : write in directory + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +const char *short_illegals=" ;+=[]',\"*\\<>/?:|"; + +static BOOLEAN +vfatIsShortIllegal(char c) +{ + int i; + for (i = 0; short_illegals[i]; i++) + if (c == short_illegals[i]) + return TRUE; + return FALSE; +} + +NTSTATUS +VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) +/* + * update an existing FAT entry + */ +{ + PVOID Context; + PVOID Buffer; + NTSTATUS status; + PVFATFCB pDirFcb = NULL, pFcb = NULL; + LARGE_INTEGER Offset; + + DPRINT ("updEntry PathFileName \'%S\'\n", + ((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName); + status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb, + ((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName); + if (!NT_SUCCESS(status)) + { + if (pDirFcb != NULL) + { + vfatReleaseFCB(DeviceExt, pDirFcb); + } + return status; + } + + Offset.u.HighPart = 0; + Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry); + if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry), + TRUE, &Context, (PVOID*)&Buffer)) + { + memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry)); + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + else + DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName); + vfatReleaseFCB(DeviceExt, pDirFcb); + vfatReleaseFCB(DeviceExt, pFcb); + return STATUS_SUCCESS; +} + +BOOLEAN +findDirSpace(PDEVICE_EXTENSION DeviceExt, + PVFATFCB pDirFcb, + ULONG nbSlots, + PULONG start) +{ +/* + * try to find contiguous entries frees in directory, + * extend a directory if is neccesary + */ + LARGE_INTEGER FileOffset; + ULONG i, count, size, nbFree = 0; + FATDirEntry* pFatEntry; + PVOID Context = NULL; + NTSTATUS Status; + FileOffset.QuadPart = 0; + count = pDirFcb->RFCB.FileSize.u.LowPart / sizeof(FATDirEntry); + size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry); + for (i = 0; i < count; i++, pFatEntry++) + { + if (Context == NULL || (i % size) == 0) + { + if (Context) + { + CcUnpinData(Context); + } + // FIXME: check return value + CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, + TRUE, &Context, (PVOID*)&pFatEntry); + FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster; + } + if (vfatIsDirEntryEndMarker(pFatEntry)) + { + break; + } + if (vfatIsDirEntryDeleted(pFatEntry)) + { + nbFree++; + } + else + { + nbFree = 0; + } + if (nbFree == nbSlots) + { + break; + } + } + if (Context) + { + CcUnpinData(Context); + Context = NULL; + } + if (nbFree == nbSlots) + { + // found enough contiguous free slots + *start = i - nbSlots + 1; + } + else + { + *start = i - nbFree; + if (*start + nbSlots > count) + { + LARGE_INTEGER AllocationSize; + CHECKPOINT; + // extend the directory + if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32) + { + // We can't extend a root directory on a FAT12/FAT16 partition + return FALSE; + } + AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster; + Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb, + DeviceExt, &AllocationSize); + if (!NT_SUCCESS(Status)) + { + return FALSE; + } + // clear the new dir cluster + FileOffset.u.LowPart = pDirFcb->RFCB.FileSize.QuadPart - + DeviceExt->FatInfo.BytesPerCluster; + CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, + TRUE, &Context, (PVOID*)&pFatEntry); + RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster); + } + else if (*start + nbSlots < count) + { + // clear the entry after the last new entry + FileOffset.u.LowPart = (*start + nbSlots) * sizeof(FATDirEntry); + CcMapData (pDirFcb->FileObject, &FileOffset, sizeof(FATDirEntry), + TRUE, &Context, (PVOID*)&pFatEntry); + RtlZeroMemory(pFatEntry, sizeof(FATDirEntry)); + } + if (Context) + { + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + } + DPRINT ("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, *start); + return TRUE; +} + +NTSTATUS +VfatAddEntry (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT pFileObject, + ULONG RequestedOptions, + UCHAR ReqAttr) +/* + create a new FAT entry +*/ +{ + WCHAR DirName[MAX_PATH], *FileName, *PathFileName; + VFATFCB FileFcb; + PVOID Context = NULL; + FATDirEntry *pFatEntry, *pEntry; + slot *pSlots; + short nbSlots = 0, nbFree = 0, j, posCar, NameLen; + PUCHAR Buffer; + BOOLEAN needTilde = FALSE, needLong = FALSE; + PVFATFCB newFCB; + ULONG CurrentCluster; + LARGE_INTEGER SystemTime, LocalTime, FileOffset; + NTSTATUS Status = STATUS_SUCCESS; + PVFATFCB pDirFcb; + ULONG start, size; + long i; + + PathFileName = pFileObject->FileName.Buffer; + DPRINT ("addEntry: Pathname=%S\n", PathFileName); + //find last \ in PathFileName + posCar = -1; + for (i = 0; PathFileName[i]; i++) + { + if (PathFileName[i] == L'\\') + { + posCar = i; + } + } + if (posCar == -1) + { + return STATUS_UNSUCCESSFUL; + } + FileName = &PathFileName[posCar + 1]; + for (NameLen = 0; FileName[NameLen]; NameLen++); + // extract directory name from pathname + if (posCar == 0) + { + // root dir + DirName[0] = L'\\'; + DirName[1] = 0; + } + else + { + memcpy (DirName, PathFileName, posCar * sizeof (WCHAR)); + DirName[posCar] = 0; + } + // open parent directory + pDirFcb = vfatGrabFCBFromTable(DeviceExt, DirName); + if (pDirFcb == NULL) + { + return STATUS_UNSUCCESSFUL; + } + nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry + DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots); + Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry)); + RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry)); + pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry)); + pSlots = (slot *) Buffer; + // create 8.3 name + needTilde = FALSE; + // find last point in name + posCar = j = 0; + for (i = 0; FileName[i]; i++) + { + if (FileName[i] == '.') + { + posCar = i; + if (i == j) + { + j++; + } + } + } + if (!posCar) + { + posCar = i; + } + if (posCar < j) + { + posCar = i; + needTilde = TRUE; + } + if (posCar > 8) + { + needTilde = TRUE; + } + //copy 8 characters max + memset (pEntry, ' ', 11); + for (i = 0, j = 0; j < 8 && i < posCar; i++) + { + if (vfatIsShortIllegal (FileName[i])) + { + needTilde = TRUE; + pEntry->Filename[j++] = '_'; + } + else + { + if (FileName[i] == '.') + { + needTilde = TRUE; + } + else + { + pEntry->Filename[j++] = toupper ((char) FileName[i]); + } + } + } + //copy extension + if (FileName[posCar]) + { + for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++) + { + if (vfatIsShortIllegal(FileName[i])) + { + needTilde = TRUE; + pEntry->Ext[j++] = '_'; + } + else + { + if (FileName[i] == '.') + { + needTilde = TRUE; + } + else + { + pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F)); + } + } + } + } + if (FileName[i]) + { + needTilde = TRUE; + } + //find good value for tilde + if (needTilde) + { + needLong = TRUE; + DPRINT ("searching a good value for tilde\n"); + for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++); + if (posCar == 0) // ?????????????????????? + { + pEntry->Filename[posCar++] = '_'; + } + posCar += 2; + if (posCar > 8) + { + posCar = 8; + } + pEntry->Filename[posCar - 2] = '~'; + pEntry->Filename[posCar - 1] = '1'; + vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName); + //try first with xxxxxx~y.zzz + for (i = 1; i < 10; i++) + { + DirName[posCar-1] = '0' + i; + pEntry->Filename[posCar - 1] = '0' + i; + Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL); + if (!NT_SUCCESS(Status)) + { + break; + } + } + if (i == 10) + { + posCar++; + if (posCar > 8) + { + posCar = 8; + } + pEntry->Filename[posCar - 3] = '~'; + pEntry->Filename[posCar - 2] = '1'; + pEntry->Filename[posCar - 1] = '0'; + vfat8Dot3ToString (pEntry->Filename, pEntry->Ext, DirName); + //try second with xxxxx~yy.zzz + for (i = 10; i < 100; i++) + { + DirName[posCar - 1] = '0' + i % 10; + DirName[posCar - 2] = '0' + i / 10; + pEntry->Filename[posCar - 1] = '0' + i % 10; + pEntry->Filename[posCar - 2] = '0' + i / 10; + Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL); + if (!NT_SUCCESS(Status)) + { + break; + } + } + if (i == 100) //FIXME : what to do after 99 tilde ? + { + vfatReleaseFCB(DeviceExt, pDirFcb); + ExFreePool (Buffer); + return STATUS_UNSUCCESSFUL; + } + } + } + else + { + DPRINT ("check if long name entry needed, needlong=%d\n", needLong); + for (i = 0; i < posCar; i++) + { + if ((USHORT) pEntry->Filename[i] != FileName[i]) + { + DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]); + needLong = TRUE; + } + } + if (FileName[i]) + { + i++; //jump on point char + for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++) + { + if ((USHORT) pEntry->Ext[j++] != FileName[i]) + { + DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Filename[i], + FileName[i]); + needLong = TRUE; + } + } + } + } + if (needLong == FALSE) + { + nbSlots = 1; + memcpy (Buffer, pEntry, sizeof (FATDirEntry)); + memset (pEntry, 0, sizeof (FATDirEntry)); + pEntry = (FATDirEntry *) Buffer; + } + else + { + memset (DirName, 0xff, sizeof (DirName)); + memcpy (DirName, FileName, NameLen * sizeof (WCHAR)); + DirName[NameLen] = 0; + } + DPRINT ("dos name=%11.11s\n", pEntry->Filename); + + /* set attributes */ + pEntry->Attrib = ReqAttr; + if (RequestedOptions & FILE_DIRECTORY_FILE) + { + pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY; + } + /* set dates and times */ + KeQuerySystemTime (&SystemTime); + ExSystemTimeToLocalTime (&SystemTime, &LocalTime); + FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate, + &pEntry->CreationTime); + pEntry->UpdateDate = pEntry->CreationDate; + pEntry->UpdateTime = pEntry->CreationTime; + pEntry->AccessDate = pEntry->CreationDate; + + // calculate checksum for 8.3 name + for (pSlots[0].alias_checksum = i = 0; i < 11; i++) + { + pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7 + | ((pSlots[0].alias_checksum & 0xfe) >> 1)) + + pEntry->Filename[i]); + } + //construct slots and entry + for (i = nbSlots - 2; i >= 0; i--) + { + DPRINT ("construct slot %d\n", i); + pSlots[i].attr = 0xf; + if (i) + { + pSlots[i].id = nbSlots - i - 1; + } + else + { + pSlots[i].id = nbSlots - i - 1 + 0x40; + } + pSlots[i].alias_checksum = pSlots[0].alias_checksum; +//FIXME pSlots[i].start=; + memcpy (pSlots[i].name0_4, DirName + (nbSlots - i - 2) * 13, 10); + memcpy (pSlots[i].name5_10, DirName + (nbSlots - i - 2) * 13 + 5, 12); + memcpy (pSlots[i].name11_12, DirName + (nbSlots - i - 2) * 13 + 11, 4); + } + + //try to find nbSlots contiguous entries frees in directory + if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start)) + { + vfatReleaseFCB(DeviceExt, pDirFcb); + ExFreePool (Buffer); + return STATUS_DISK_FULL; + } + + if (RequestedOptions & FILE_DIRECTORY_FILE) + { + CurrentCluster = 0xffffffff; + Status = NextCluster (DeviceExt, NULL, 0, &CurrentCluster, TRUE); + if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status)) + { + vfatReleaseFCB(DeviceExt, pDirFcb); + ExFreePool (Buffer); + if (!NT_SUCCESS(Status)) + { + return Status; + } + return STATUS_DISK_FULL; + } + if (DeviceExt->FatInfo.FatType == FAT32) + { + pEntry->FirstClusterHigh = CurrentCluster >> 16; + } + pEntry->FirstCluster = CurrentCluster; + } + + size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry); + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = start * sizeof(FATDirEntry); + if (start / size == (start + nbSlots - 1) / size) + { + // one cluster + CHECKPOINT; + CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry), + TRUE, &Context, (PVOID*)&pFatEntry); + memcpy(pFatEntry, Buffer, nbSlots * sizeof(FATDirEntry)); + } + else + { + // two clusters + CHECKPOINT; + size = DeviceExt->FatInfo.BytesPerCluster - + (start * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster; + CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE, + &Context, (PVOID*)&pFatEntry); + memcpy(pFatEntry, Buffer, size); + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + FileOffset.u.LowPart += size; + CcMapData (pDirFcb->FileObject, &FileOffset, + nbSlots * sizeof(FATDirEntry) - size, + TRUE, &Context, (PVOID*)&pFatEntry); + memcpy(pFatEntry, (PVOID)Buffer + size, nbSlots * sizeof(FATDirEntry) - size); + } + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + + // FEXME: check status + vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry, + start + nbSlots - 1, &newFCB); + vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject); + + DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename); + DPRINT ("new : entry=%11.11s\n", pEntry->Filename); + + if (RequestedOptions & FILE_DIRECTORY_FILE) + { + FileOffset.QuadPart = 0; + CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE, + &Context, (PVOID*)&pFatEntry); + // clear the new directory cluster + RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster); + // create '.' and '..' + memcpy (&pFatEntry[0].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11); + memcpy (pFatEntry[0].Filename, ". ", 11); + memcpy (&pFatEntry[1].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11); + memcpy (pFatEntry[1].Filename, ".. ", 11); + pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster; + pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh; + if (DeviceExt->FatInfo.FatType == FAT32) + { + if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) && + pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16)) + { + pFatEntry[1].FirstCluster = 0; + pFatEntry[1].FirstClusterHigh = 0; + } + } + else + { + if (pFatEntry[1].FirstCluster == 1) + { + pFatEntry[1].FirstCluster = 0; + } + } + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + vfatReleaseFCB (DeviceExt, pDirFcb); + ExFreePool (Buffer); + DPRINT ("addentry ok\n"); + return STATUS_SUCCESS; +} + +NTSTATUS +delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject) +/* + * deleting an existing FAT entry + */ +{ + VFATFCB Fcb; + PVFATFCB pFcb = NULL, pDirFcb = NULL; + NTSTATUS status; + PWSTR pName; + ULONG Entry = 0, startEntry, Read, CurrentCluster, NextCluster, i; + FATDirEntry DirEntry; + + DPRINT ("delEntry PathFileName \'%S\'\n", pFileObject->FileName.Buffer); + + status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb, + pFileObject->FileName.Buffer); + if (pFcb != NULL) + { + vfatReleaseFCB(DeviceExt, pFcb); + } + if (!NT_SUCCESS(status)) + { + if (pDirFcb != NULL) + { + vfatReleaseFCB(DeviceExt, pDirFcb); + } + return status; + } + pName = ((PVFATCCB)(pFileObject->FsContext2))->pFcb->ObjectName; + if (*pName == L'\\') + { + pName ++; + } + status = FindFile (DeviceExt, &Fcb, pDirFcb, pName, &Entry, &startEntry); + + if (NT_SUCCESS(status)) + { + PVOID Context = NULL; + LARGE_INTEGER Offset; + FATDirEntry* pDirEntry; + DPRINT ("delete entry: %d to %d\n", startEntry, Entry); + Offset.u.HighPart = 0; + for (i = startEntry; i <= Entry; i++) + { + if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0) + { + if (Context) + { + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE; + CcMapData (pDirFcb->FileObject, &Offset, PAGE_SIZE, TRUE, + &Context, (PVOID*)&pDirEntry); + } + pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5; + if (i == Entry) + { + CurrentCluster = + vfatDirEntryGetFirstCluster (DeviceExt, + &pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))]); + } + } + if (Context) + { + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + } + + while (CurrentCluster && CurrentCluster != 0xffffffff) + { + GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE); + // FIXME: check status + WriteCluster(DeviceExt, CurrentCluster, 0); + CurrentCluster = NextCluster; + } + } + vfatReleaseFCB(DeviceExt, pDirFcb); + return status; +} + +/* EOF */ diff --git a/drivers/fs/vfat/ea.c b/drivers/fs/vfat/ea.c new file mode 100644 index 0000000..23e5eb0 --- /dev/null +++ b/drivers/fs/vfat/ea.c @@ -0,0 +1,47 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/ea.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +VfatSetExtendedAttributes(PFILE_OBJECT FileObject, + PVOID Ea, + ULONG EaLength) +{ + return(STATUS_EAS_NOT_SUPPORTED); +} diff --git a/drivers/fs/vfat/fat.c b/drivers/fs/vfat/fat.c new file mode 100644 index 0000000..499f1a3 --- /dev/null +++ b/drivers/fs/vfat/fat.c @@ -0,0 +1,817 @@ +/* + * $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/fat.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* GLOBALS ******************************************************************/ + +#define ROUND_DOWN(N, S) ((N) - ((N) % (S))) + +#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \ + (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE) + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster) +/* + * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical + * disk read + */ +{ + PVOID BaseAddress; + NTSTATUS Status; + ULONG FATOffset; + ULONG ChunkSize; + PVOID Context; + LARGE_INTEGER Offset; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FATOffset = CurrentCluster * sizeof(ULONG); + Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + CurrentCluster = (*(PULONG)(BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff; + if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff) + CurrentCluster = 0xffffffff; + CcUnpinData(Context); + *NextCluster = CurrentCluster; + return (STATUS_SUCCESS); +} + +NTSTATUS +Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster) +/* + * FUNCTION: Retrieve the next FAT16 cluster from the FAT table + */ +{ + PVOID BaseAddress; + NTSTATUS Status; + ULONG FATOffset; + ULONG ChunkSize; + PVOID Context; + LARGE_INTEGER Offset; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FATOffset = CurrentCluster * 2; + Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + CurrentCluster = *((PUSHORT)(BaseAddress + (FATOffset % ChunkSize))); + if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff) + CurrentCluster = 0xffffffff; + CcUnpinData(Context); + *NextCluster = CurrentCluster; + return (STATUS_SUCCESS); +} + +NTSTATUS +Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster) +/* + * FUNCTION: Retrieve the next FAT12 cluster from the FAT table + */ +{ + PUSHORT CBlock; + ULONG FATOffset; + ULONG Entry; + NTSTATUS Status; + PVOID BaseAddress; + PVOID Context; + LARGE_INTEGER Offset; + + + *NextCluster = 0; + + Offset.QuadPart = 0; + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + CBlock = (PUSHORT)(BaseAddress + (CurrentCluster * 12) / 8); + if ((CurrentCluster % 2) == 0) + { + Entry = *CBlock & 0x0fff; + } + else + { + Entry = *CBlock >> 4; + } +// DPRINT("Entry %x\n",Entry); + if (Entry >= 0xff8 && Entry <= 0xfff) + Entry = 0xffffffff; +// DPRINT("Returning %x\n",Entry); + *NextCluster = Entry; + CcUnpinData(Context); +// return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS; + return STATUS_SUCCESS; +} + +NTSTATUS +FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, + PULONG Cluster) +/* + * FUNCTION: Finds the first available cluster in a FAT16 table + */ +{ + ULONG FatLength; + ULONG StartCluster; + ULONG i, j; + NTSTATUS Status; + PVOID BaseAddress; + ULONG ChunkSize; + PVOID Context = 0; + LARGE_INTEGER Offset; + PUSHORT Block; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2; + *Cluster = 0; + StartCluster = DeviceExt->LastAvailableCluster; + + for (j = 0; j < 2; j++) + { + for (i = StartCluster * 2; i < FatLength; i += 2, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) + { + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if (Context != NULL) + { + CcUnpinData(Context); + } + CHECKPOINT; + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); + return STATUS_UNSUCCESSFUL; + } + CHECKPOINT; + Block = (PUSHORT)(BaseAddress + i % ChunkSize); + } + + if (*Block == 0) + { + DPRINT("Found available cluster 0x%x\n", i / 2); + DeviceExt->LastAvailableCluster = *Cluster = i / 2; + CcUnpinData(Context); + return(STATUS_SUCCESS); + } + } + FatLength = StartCluster * 2; + StartCluster = 2; + if (Context != NULL) + { + CcUnpinData(Context); + Context =NULL; + } + } + return(STATUS_DISK_FULL); +} + +NTSTATUS +FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster) +/* + * FUNCTION: Finds the first available cluster in a FAT12 table + */ +{ + ULONG FatLength; + ULONG FATOffset; + ULONG StartCluster; + ULONG Entry; + PUSHORT CBlock; + ULONG i, j; + PVOID BaseAddress; + NTSTATUS Status; + PVOID Context; + LARGE_INTEGER Offset; + + FatLength = DeviceExt->FatInfo.NumberOfClusters + 2; + *Cluster = 0; + StartCluster = DeviceExt->LastAvailableCluster; + Offset.QuadPart = 0; + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) + { + DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector); + return STATUS_UNSUCCESSFUL; + } + + for (j = 0; j < 2; j++) + { + for (i = StartCluster; i < FatLength; i++) + { + CBlock = (PUSHORT)(BaseAddress + (i * 12) / 8); + if ((i % 2) == 0) + { + Entry = *CBlock & 0xfff; + } + else + { + Entry = *CBlock >> 4; + } + if (Entry == 0) + { + DPRINT("Found available cluster 0x%x\n", i); + DeviceExt->LastAvailableCluster = *Cluster = i; + CcUnpinData(Context); + return(STATUS_SUCCESS); + } + } + FatLength = StartCluster; + StartCluster = 2; + } + CcUnpinData(Context); + return (STATUS_DISK_FULL); +} + +NTSTATUS +FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster) +/* + * FUNCTION: Finds the first available cluster in a FAT32 table + */ +{ + ULONG FatLength; + ULONG StartCluster; + ULONG i, j; + NTSTATUS Status; + PVOID BaseAddress; + ULONG ChunkSize; + PVOID Context = 0; + LARGE_INTEGER Offset; + PULONG Block; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4; + *Cluster = 0; + StartCluster = DeviceExt->LastAvailableCluster; + + for (j = 0; j < 2; j++) + { + for (i = StartCluster * 4; i < FatLength; i += 4, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) + { + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if (Context != NULL) + { + CcUnpinData(Context); + } + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize); + return STATUS_UNSUCCESSFUL; + } + Block = (PULONG)(BaseAddress + i % ChunkSize); + } + + if ((*Block & 0x0fffffff) == 0) + { + DPRINT("Found available cluster 0x%x\n", i / 4); + DeviceExt->LastAvailableCluster = *Cluster = i / 4; + CcUnpinData(Context); + return(STATUS_SUCCESS); + } + } + FatLength = StartCluster * 4; + StartCluster = 2; + if (Context != NULL) + { + CcUnpinData(Context); + Context=NULL; + } + } + return (STATUS_DISK_FULL); +} + + +NTSTATUS +FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) +/* + * FUNCTION: Counts free cluster in a FAT12 table + */ +{ + ULONG FATOffset; + ULONG Entry; + PVOID BaseAddress; + ULONG ulCount = 0; + ULONG i; + NTSTATUS Status; + ULONG numberofclusters; + LARGE_INTEGER Offset; + PVOID Context; + PUSHORT CBlock; + + Offset.QuadPart = 0; + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + + numberofclusters = DeviceExt->FatInfo.NumberOfClusters + 2; + + for (i = 2; i < numberofclusters; i++) + { + CBlock = (PUSHORT)(BaseAddress + (i * 12) / 8); + if ((i % 2) == 0) + { + Entry = *CBlock & 0x0fff; + } + else + { + Entry = *CBlock >> 4; + } + if (Entry == 0) + ulCount++; + } + + CcUnpinData(Context); + DeviceExt->AvailableClusters = ulCount; + DeviceExt->AvailableClustersValid = TRUE; + + return(STATUS_SUCCESS); +} + + +NTSTATUS +FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) +/* + * FUNCTION: Counts free clusters in a FAT16 table + */ +{ + PUSHORT Block; + PVOID BaseAddress = NULL; + ULONG ulCount = 0; + ULONG i; + ULONG ChunkSize; + NTSTATUS Status; + PVOID Context = NULL; + LARGE_INTEGER Offset; + ULONG FatLength; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 2; + + for (i = 4; i< FatLength; i += 2, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) + { + DPRINT("%d\n", i/2); + if (Context) + { + CcUnpinData(Context); + } + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + Block = (PUSHORT)(BaseAddress + i % ChunkSize); + } + if (*Block == 0) + ulCount++; + } + + DeviceExt->AvailableClusters = ulCount; + DeviceExt->AvailableClustersValid = TRUE; + CcUnpinData(Context); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt) +/* + * FUNCTION: Counts free clusters in a FAT32 table + */ +{ + PULONG Block; + PVOID BaseAddress = NULL; + ULONG ulCount = 0; + ULONG i; + ULONG ChunkSize; + NTSTATUS Status; + PVOID Context = NULL; + LARGE_INTEGER Offset; + ULONG FatLength; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4; + + for (i = 8; i< FatLength; i += 4, Block++) + { + if ((i % ChunkSize) == 0 || Context == NULL) + { + if (Context) + { + CcUnpinData(Context); + } + Offset.QuadPart = ROUND_DOWN(i, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + Block = (PULONG)(BaseAddress + i % ChunkSize); + } + if ((*Block & 0x0fffffff) == 0) + ulCount++; + } + + DeviceExt->AvailableClusters = ulCount; + DeviceExt->AvailableClustersValid = TRUE; + CcUnpinData(Context); + + return(STATUS_SUCCESS); +} + +NTSTATUS +CountAvailableClusters(PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER Clusters) +{ + NTSTATUS Status = STATUS_SUCCESS; + ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE); + if (!DeviceExt->AvailableClustersValid) + { + if (DeviceExt->FatInfo.FatType == FAT12) + Status = FAT12CountAvailableClusters(DeviceExt); + else if (DeviceExt->FatInfo.FatType == FAT16) + Status = FAT16CountAvailableClusters(DeviceExt); + else + Status = FAT32CountAvailableClusters(DeviceExt); + } + Clusters->QuadPart = DeviceExt->AvailableClusters; + ExReleaseResourceLite (&DeviceExt->FatResource); + + return Status; +} + + + + + +NTSTATUS +FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue) +/* + * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables + */ +{ + ULONG FATsector; + ULONG FATOffset; + PUCHAR CBlock; + int i; + NTSTATUS Status; + PVOID BaseAddress; + PVOID Context; + LARGE_INTEGER Offset; + + Offset.QuadPart = 0; + if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + CBlock = (PUCHAR)BaseAddress; + + FATOffset = (ClusterToWrite * 12) / 8; + DPRINT("Writing 0x%x for 0x%x at 0x%x\n", + NewValue, ClusterToWrite, FATOffset); + if ((ClusterToWrite % 2) == 0) + { + *OldValue = CBlock[FATOffset] + ((CBlock[FATOffset + 1] & 0x0f) << 8); + CBlock[FATOffset] = NewValue; + CBlock[FATOffset + 1] &= 0xf0; + CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8; + } + else + { + *OldValue = (CBlock[FATOffset] >> 4) + (CBlock[FATOffset + 1] << 4); + CBlock[FATOffset] &= 0x0f; + CBlock[FATOffset] |= (NewValue & 0xf) << 4; + CBlock[FATOffset + 1] = NewValue >> 4; + } + /* Write the changed FAT sector(s) to disk */ + FATsector = FATOffset / DeviceExt->FatInfo.BytesPerSector; + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + return(STATUS_SUCCESS); +} + +NTSTATUS +FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue) +/* + * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables + */ +{ + PVOID BaseAddress; + NTSTATUS Status; + ULONG FATOffset; + ULONG i; + ULONG ChunkSize; + PVOID Context; + LARGE_INTEGER Offset; + PUSHORT Cluster; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + FATOffset = ClusterToWrite * 2; + Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset, + ClusterToWrite); + Cluster = ((PUSHORT)(BaseAddress + (FATOffset % ChunkSize))); + *OldValue = *Cluster; + *Cluster = NewValue; + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + return(STATUS_SUCCESS); +} + +NTSTATUS +FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue, + PULONG OldValue) +/* + * FUNCTION: Writes a cluster to the FAT32 physical tables + */ +{ + PVOID BaseAddress; + NTSTATUS Status; + ULONG FATOffset; + ULONG i; + ULONG ChunkSize; + PVOID Context; + LARGE_INTEGER Offset; + PULONG Cluster; + + ChunkSize = CACHEPAGESIZE(DeviceExt); + + FATOffset = (ClusterToWrite * 4); + Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize); + if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress)) + { + return STATUS_UNSUCCESSFUL; + } + DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset, + ClusterToWrite); + Cluster = ((PULONG)(BaseAddress + (FATOffset % ChunkSize))); + *OldValue = *Cluster & 0x0fffffff; + *Cluster = (*Cluster & 0xf0000000) | (NewValue & 0x0fffffff); + + CcSetDirtyPinnedData(Context, NULL); + CcUnpinData(Context); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +WriteCluster(PDEVICE_EXTENSION DeviceExt, + ULONG ClusterToWrite, + ULONG NewValue) +/* + * FUNCTION: Write a changed FAT entry + */ +{ + NTSTATUS Status; + ULONG OldValue; + ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE); + if (DeviceExt->FatInfo.FatType == FAT16) + { + Status = FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue); + } + else if (DeviceExt->FatInfo.FatType == FAT32) + { + Status = FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue); + } + else + { + Status = FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue); + } + if (DeviceExt->AvailableClustersValid) + { + if (OldValue && NewValue == 0) + InterlockedIncrement(&DeviceExt->AvailableClusters); + else if (OldValue == 0 && NewValue) + InterlockedDecrement(&DeviceExt->AvailableClusters); + } + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); +} + +ULONG +ClusterToSector(PDEVICE_EXTENSION DeviceExt, + ULONG Cluster) +/* + * FUNCTION: Converts the cluster number to a sector number for this physical + * device + */ +{ + return DeviceExt->FatInfo.dataStart + + ((Cluster - 2) * DeviceExt->FatInfo.SectorsPerCluster); +} + +NTSTATUS +GetNextCluster(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster, + BOOLEAN Extend) +/* + * FUNCTION: Retrieve the next cluster depending on the FAT type + */ +{ + NTSTATUS Status; + + DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n", + DeviceExt, CurrentCluster); + + if (!Extend) + { + ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE); + } + else + { + ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE); + } + CHECKPOINT; + /* + * If the file hasn't any clusters allocated then we need special + * handling + */ + if (CurrentCluster == 0 && Extend) + { + ULONG NewCluster; + + if (DeviceExt->FatInfo.FatType == FAT16) + { + CHECKPOINT; + Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster); + CHECKPOINT; + if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); + } + } + else if (DeviceExt->FatInfo.FatType == FAT32) + { + Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster); + if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); + } + } + else + { + Status = FAT12FindAvailableCluster(DeviceExt, &NewCluster); + if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); + } + } + /* Mark the new AU as the EOF */ + WriteCluster (DeviceExt, NewCluster, 0xFFFFFFFF); + *NextCluster = NewCluster; + ExReleaseResourceLite(&DeviceExt->FatResource); + return(STATUS_SUCCESS); + } + else if (CurrentCluster == 0) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(STATUS_UNSUCCESSFUL); + } + + if (DeviceExt->FatInfo.FatType == FAT16) + { + Status = Fat16GetNextCluster(DeviceExt, CurrentCluster, NextCluster); + } + else if (DeviceExt->FatInfo.FatType == FAT32) + { + Status = Fat32GetNextCluster(DeviceExt, CurrentCluster, NextCluster); + } + else + { + Status = Fat12GetNextCluster(DeviceExt, CurrentCluster, NextCluster); + } + if (Extend && (*NextCluster) == 0xFFFFFFFF) + { + ULONG NewCluster; + + /* We are after last existing cluster, we must add one to file */ + /* Firstly, find the next available open allocation unit */ + if (DeviceExt->FatInfo.FatType == FAT16) + { + Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster); + if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); + } + } + else if (DeviceExt->FatInfo.FatType == FAT32) + { + Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster); + if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); + } + } + else + { + Status = FAT12FindAvailableCluster(DeviceExt, &NewCluster); + if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&DeviceExt->FatResource); + return(Status); + } + } + /* Mark the new AU as the EOF */ + WriteCluster(DeviceExt, NewCluster, 0xFFFFFFFF); + /* Now, write the AU of the LastCluster with the value of the newly + found AU */ + WriteCluster(DeviceExt, CurrentCluster, NewCluster); + *NextCluster = NewCluster; + } + + ExReleaseResourceLite(&DeviceExt->FatResource); + + return(Status); +} + + +NTSTATUS +GetNextSector(PDEVICE_EXTENSION DeviceExt, + ULONG CurrentSector, + PULONG NextSector, + BOOLEAN Extend) +/* Some functions don't have access to the cluster they're really reading from. + Maybe this is a dirty solution, but it will allow them to handle fragmentation. */ +{ + NTSTATUS Status; + + DPRINT("GetNextSector(DeviceExt %x, CurrentSector %x)\n", + DeviceExt, + CurrentSector); + if (CurrentSectorFatInfo.dataStart || ((CurrentSector - DeviceExt->FatInfo.dataStart + 1) % DeviceExt->FatInfo.SectorsPerCluster)) + /* Basically, if the next sequential sector would be on a cluster border, then we'll need to check in the FAT */ + { + (*NextSector)=CurrentSector+1; + return (STATUS_SUCCESS); + } + else + { + CurrentSector = (CurrentSector - DeviceExt->FatInfo.dataStart) / DeviceExt->FatInfo.SectorsPerCluster + 2; + + Status = GetNextCluster(DeviceExt, CurrentSector, NextSector, Extend); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if ((*NextSector) == 0 || (*NextSector) == 0xffffffff) + { + /* The caller wants to know a sector. These FAT codes don't correspond to any sector. */ + return(STATUS_UNSUCCESSFUL); + } + + (*NextSector) = ClusterToSector(DeviceExt,(*NextSector)); + return(STATUS_SUCCESS); + } +} + +/* EOF */ diff --git a/drivers/fs/vfat/fcb.c b/drivers/fs/vfat/fcb.c new file mode 100644 index 0000000..bf0a6cb --- /dev/null +++ b/drivers/fs/vfat/fcb.c @@ -0,0 +1,577 @@ +/* $Id$ + * + * + * FILE: fcb.c + * PURPOSE: Routines to manipulate FCBs. + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * Rex Jolliff (rex@lvcablemodem.com) + */ + +/* ------------------------------------------------------- INCLUDES */ + +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* -------------------------------------------------------- DEFINES */ + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) +#define TAG_FCB TAG('V', 'F', 'C', 'B') + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + +/* -------------------------------------------------------- PUBLICS */ + +PVFATFCB +vfatNewFCB(PWCHAR pFileName) +{ + PVFATFCB rcFCB; + + rcFCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATFCB), TAG_FCB); + memset (rcFCB, 0, sizeof (VFATFCB)); + if (pFileName) + { + wcscpy (rcFCB->PathName, pFileName); + if (wcsrchr (rcFCB->PathName, '\\') != 0) + { + rcFCB->ObjectName = wcsrchr (rcFCB->PathName, '\\'); + } + else + { + rcFCB->ObjectName = rcFCB->PathName; + } + } + ExInitializeResourceLite(&rcFCB->PagingIoResource); + ExInitializeResourceLite(&rcFCB->MainResource); + return rcFCB; +} + +VOID +vfatDestroyFCB(PVFATFCB pFCB) +{ + ExDeleteResourceLite(&pFCB->PagingIoResource); + ExDeleteResourceLite(&pFCB->MainResource); + if ((pFCB->Flags & FCB_IS_PAGE_FILE) && pFCB->FatChainSize) + ExFreePool(pFCB->FatChain); + ExFreePool (pFCB); +} + +BOOL +vfatFCBIsDirectory(PDEVICE_EXTENSION pVCB, PVFATFCB FCB) +{ + return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY; +} + +BOOL +vfatFCBIsRoot(PVFATFCB FCB) +{ + return wcscmp (FCB->PathName, L"\\") == 0; +} + +VOID +vfatGrabFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) +{ + KIRQL oldIrql; + + DPRINT ("grabbing FCB at %x: %S, refCount:%d\n", + pFCB, + pFCB->PathName, + pFCB->RefCount); + + KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql); + pFCB->RefCount++; + KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); +} + +VOID +vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) +{ + KIRQL oldIrql; + + DPRINT ("releasing FCB at %x: %S, refCount:%d\n", + pFCB, + pFCB->PathName, + pFCB->RefCount); + + KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql); + pFCB->RefCount--; + if (pFCB->RefCount <= 0 && (!vfatFCBIsDirectory (pVCB, pFCB) || pFCB->Flags & FCB_DELETE_PENDING)) + { + RemoveEntryList (&pFCB->FcbListEntry); + KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); + if (vfatFCBIsDirectory(pVCB, pFCB)) + { + CcRosReleaseFileCache(pFCB->FileObject, pFCB->RFCB.Bcb); + ExFreePool(pFCB->FileObject->FsContext2); + pFCB->FileObject->FsContext2 = NULL; + ObDereferenceObject(pFCB->FileObject); + } + vfatDestroyFCB (pFCB); + } + else + KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); +} + +VOID +vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB) +{ + KIRQL oldIrql; + + KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql); + pFCB->pDevExt = pVCB; + InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry); + KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); +} + +PVFATFCB +vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PWSTR pFileName) +{ + KIRQL oldIrql; + PVFATFCB rcFCB; + PLIST_ENTRY current_entry; + + KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql); + current_entry = pVCB->FcbListHead.Flink; + while (current_entry != &pVCB->FcbListHead) + { + rcFCB = CONTAINING_RECORD (current_entry, VFATFCB, FcbListEntry); + + if (wstrcmpi (pFileName, rcFCB->PathName)) + { + rcFCB->RefCount++; + KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); + return rcFCB; + } + + //FIXME: need to compare against short name in FCB here + + current_entry = current_entry->Flink; + } + KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql); + + return NULL; +} + +NTSTATUS +vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb) +{ + NTSTATUS status; + PFILE_OBJECT fileObject; + ULONG fileCacheQuantum; + PVFATCCB newCCB; + + fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice); + + newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB); + if (newCCB == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + memset (newCCB, 0, sizeof (VFATCCB)); + + fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + fileObject->SectionObjectPointers = &fcb->SectionObjectPointers; + fileObject->FsContext = (PVOID) &fcb->RFCB; + fileObject->FsContext2 = newCCB; + newCCB->pFcb = fcb; + newCCB->PtrFileObject = fileObject; + fcb->FileObject = fileObject; + fcb->pDevExt = vcb; + + + fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGE_SIZE) ? + vcb->FatInfo.BytesPerCluster : PAGE_SIZE; + + status = CcRosInitializeFileCache (fileObject, + &fcb->RFCB.Bcb, + fileCacheQuantum); + if (!NT_SUCCESS (status)) + { + DbgPrint ("CcRosInitializeFileCache failed\n"); + KeBugCheck (0); + } + + fcb->Flags |= FCB_CACHE_INITIALIZED; + + return status; +} + +PVFATFCB +vfatMakeRootFCB(PDEVICE_EXTENSION pVCB) +{ + PVFATFCB FCB; + ULONG FirstCluster, CurrentCluster, Size = 0; + NTSTATUS Status = STATUS_SUCCESS; + + FCB = vfatNewFCB(L"\\"); + memset(FCB->entry.Filename, ' ', 11); + FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; + FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY; + if (pVCB->FatInfo.FatType == FAT32) + { + CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster; + FCB->entry.FirstCluster = FirstCluster & 0xffff; + FCB->entry.FirstClusterHigh = FirstCluster >> 16; + CurrentCluster = FirstCluster; + + while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) + { + Size += pVCB->FatInfo.BytesPerCluster; + Status = NextCluster (pVCB, NULL, FirstCluster, &CurrentCluster, FALSE); + } + } + else + { + FCB->entry.FirstCluster = 1; + Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector; + } + FCB->RefCount = 1; + FCB->dirIndex = 0; + FCB->RFCB.FileSize.QuadPart = Size; + FCB->RFCB.ValidDataLength.QuadPart = Size; + FCB->RFCB.AllocationSize.QuadPart = Size; + + vfatFCBInitializeCacheFromVolume(pVCB, FCB); + vfatAddFCBToTable(pVCB, FCB); + vfatGrabFCB(pVCB, FCB); + + return(FCB); +} + +PVFATFCB +vfatOpenRootFCB(PDEVICE_EXTENSION pVCB) +{ + PVFATFCB FCB; + + FCB = vfatGrabFCBFromTable (pVCB, L"\\"); + if (FCB == NULL) + { + FCB = vfatMakeRootFCB (pVCB); + } + + return FCB; +} + +NTSTATUS +vfatMakeFCBFromDirEntry(PVCB vcb, + PVFATFCB directoryFCB, + PWSTR longName, + PFAT_DIR_ENTRY dirEntry, + ULONG dirIndex, + PVFATFCB* fileFCB) +{ + PVFATFCB rcFCB; + WCHAR pathName [MAX_PATH]; + ULONG Size; + if (longName [0] != 0 && wcslen (directoryFCB->PathName) + + sizeof(WCHAR) + wcslen (longName) > MAX_PATH) + { + return STATUS_OBJECT_NAME_INVALID; + } + wcscpy (pathName, directoryFCB->PathName); + if (!vfatFCBIsRoot (directoryFCB)) + { + wcscat (pathName, L"\\"); + } + if (longName [0] != 0) + { + wcscat (pathName, longName); + } + else + { + WCHAR entryName [MAX_PATH]; + + vfatGetDirEntryName (dirEntry, entryName); + wcscat (pathName, entryName); + } + rcFCB = vfatNewFCB (pathName); + memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY)); + + if (vfatFCBIsDirectory(vcb, rcFCB)) + { + ULONG FirstCluster, CurrentCluster; + NTSTATUS Status; + Size = 0; + FirstCluster = vfatDirEntryGetFirstCluster (vcb, &rcFCB->entry); + if (FirstCluster == 1) + { + Size = vcb->FatInfo.rootDirectorySectors * vcb->FatInfo.BytesPerSector; + } + else + { + CurrentCluster = FirstCluster; + while (CurrentCluster != 0xffffffff) + { + Size += vcb->FatInfo.BytesPerCluster; + Status = NextCluster (vcb, NULL, FirstCluster, &CurrentCluster, FALSE); + } + } + } + else + { + Size = rcFCB->entry.FileSize; + } + rcFCB->dirIndex = dirIndex; + rcFCB->RFCB.FileSize.QuadPart = Size; + rcFCB->RFCB.ValidDataLength.QuadPart = Size; + rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster); + rcFCB->RefCount++; + if (vfatFCBIsDirectory(vcb, rcFCB)) + { + vfatFCBInitializeCacheFromVolume(vcb, rcFCB); + } + vfatAddFCBToTable (vcb, rcFCB); + *fileFCB = rcFCB; + + return STATUS_SUCCESS; +} + +NTSTATUS +vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, + PVFATFCB fcb, + PFILE_OBJECT fileObject) +{ + NTSTATUS status; + PVFATCCB newCCB; + + newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB); + if (newCCB == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + memset (newCCB, 0, sizeof (VFATCCB)); + + fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID | + FO_DIRECT_CACHE_PAGING_READ; + fileObject->SectionObjectPointers = &fcb->SectionObjectPointers; + fileObject->FsContext = (PVOID) &fcb->RFCB; + fileObject->FsContext2 = newCCB; + newCCB->pFcb = fcb; + newCCB->PtrFileObject = fileObject; + fcb->pDevExt = vcb; + DPRINT ("file open: fcb:%x file size: %d\n", fcb, fcb->entry.FileSize); + + return STATUS_SUCCESS; +} + +NTSTATUS +vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt, + PVFATFCB pDirectoryFCB, + PWSTR pFileToFind, + PVFATFCB * pFoundFCB) +{ + BOOL finishedScanningDirectory; + ULONG directoryIndex; + NTSTATUS status; + WCHAR defaultFileName [2]; + WCHAR currentLongName [256]; + FAT_DIR_ENTRY currentDirEntry; + WCHAR currentEntryName [256]; + + assert (pDeviceExt); + assert (pDirectoryFCB); + assert (pFileToFind); + + DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n", + pDeviceExt, + pDirectoryFCB, + pFileToFind); + DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName); + + // default to '.' if no filename specified + if (wcslen (pFileToFind) == 0) + { + defaultFileName [0] = L'.'; + defaultFileName [1] = 0; + pFileToFind = defaultFileName; + } + + directoryIndex = 0; + finishedScanningDirectory = FALSE; + while (!finishedScanningDirectory) + { + status = vfatGetNextDirEntry (pDeviceExt, + pDirectoryFCB, + &directoryIndex, + currentLongName, + ¤tDirEntry); + if (status == STATUS_NO_MORE_ENTRIES) + { + finishedScanningDirectory = TRUE; + continue; + } + else if (!NT_SUCCESS(status)) + { + return status; + } + + DPRINT (" Index:%d longName:%S\n", + directoryIndex, + currentLongName); + + if (!vfatIsDirEntryDeleted (¤tDirEntry) + && !vfatIsDirEntryVolume(¤tDirEntry)) + { + if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind)) + { + DPRINT ("Match found, %S\n", currentLongName); + status = vfatMakeFCBFromDirEntry (pDeviceExt, + pDirectoryFCB, + currentLongName, + ¤tDirEntry, + directoryIndex - 1, + pFoundFCB); + return status; + } + else + { + vfatGetDirEntryName (¤tDirEntry, currentEntryName); + DPRINT (" entryName:%S\n", currentEntryName); + + if (wstrcmpjoki (currentEntryName, pFileToFind)) + { + DPRINT ("Match found, %S\n", currentEntryName); + status = vfatMakeFCBFromDirEntry (pDeviceExt, + pDirectoryFCB, + currentLongName, + ¤tDirEntry, + directoryIndex - 1, + pFoundFCB); + return status; + } + } + } + } + + return STATUS_OBJECT_NAME_NOT_FOUND; +} + +NTSTATUS +vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, + PVFATFCB *pParentFCB, + PVFATFCB *pFCB, + const PWSTR pFileName) +{ + NTSTATUS status; + WCHAR pathName [MAX_PATH]; + WCHAR elementName [MAX_PATH]; + PWCHAR currentElement; + PVFATFCB FCB; + PVFATFCB parentFCB; + + DPRINT ("vfatGetFCBForFile (%x,%x,%x,%S)\n", + pVCB, + pParentFCB, + pFCB, + pFileName); + + // Trivial case, open of the root directory on volume + if (pFileName [0] == L'\0' || wcscmp (pFileName, L"\\") == 0) + { + DPRINT ("returning root FCB\n"); + + FCB = vfatOpenRootFCB (pVCB); + *pFCB = FCB; + *pParentFCB = NULL; + + return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND; + } + else + { + currentElement = pFileName + 1; + wcscpy (pathName, L"\\"); + FCB = vfatOpenRootFCB (pVCB); + } + parentFCB = NULL; + + // Parse filename and check each path element for existance and access + while (vfatGetNextPathElement (currentElement) != 0) + { + // Skip blank directory levels + if ((vfatGetNextPathElement (currentElement) - currentElement) == 0) + { + currentElement++; + continue; + } + + DPRINT ("Parsing, currentElement:%S\n", currentElement); + DPRINT (" parentFCB:%x FCB:%x\n", parentFCB, FCB); + + // descend to next directory level + if (parentFCB) + { + vfatReleaseFCB (pVCB, parentFCB); + parentFCB = 0; + } + // fail if element in FCB is not a directory + if (!vfatFCBIsDirectory (pVCB, FCB)) + { + DPRINT ("Element in requested path is not a directory\n"); + + vfatReleaseFCB (pVCB, FCB); + FCB = 0; + *pParentFCB = NULL; + *pFCB = NULL; + + return STATUS_OBJECT_PATH_NOT_FOUND; + } + parentFCB = FCB; + + // Extract next directory level into dirName + vfatWSubString (pathName, + pFileName, + vfatGetNextPathElement (currentElement) - pFileName); + DPRINT (" pathName:%S\n", pathName); + + FCB = vfatGrabFCBFromTable (pVCB, pathName); + if (FCB == NULL) + { + vfatWSubString (elementName, + currentElement, + vfatGetNextPathElement (currentElement) - currentElement); + DPRINT (" elementName:%S\n", elementName); + + status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB); + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + { + *pParentFCB = parentFCB; + *pFCB = NULL; + currentElement = vfatGetNextPathElement(currentElement); + if (*currentElement == L'\0' || vfatGetNextPathElement(currentElement + 1) == 0) + { + return STATUS_OBJECT_NAME_NOT_FOUND; + } + else + { + return STATUS_OBJECT_PATH_NOT_FOUND; + } + } + else if (!NT_SUCCESS (status)) + { + vfatReleaseFCB (pVCB, parentFCB); + *pParentFCB = NULL; + *pFCB = NULL; + + return status; + } + } + currentElement = vfatGetNextPathElement (currentElement); + } + + *pParentFCB = parentFCB; + *pFCB = FCB; + + return STATUS_SUCCESS; +} + + + + diff --git a/drivers/fs/vfat/finfo.c b/drivers/fs/vfat/finfo.c new file mode 100644 index 0000000..2917a50 --- /dev/null +++ b/drivers/fs/vfat/finfo.c @@ -0,0 +1,666 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/finfo.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +VfatGetStandardInformation(PVFATFCB FCB, + PDEVICE_OBJECT DeviceObject, + PFILE_STANDARD_INFORMATION StandardInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the standard file information + */ +{ + PDEVICE_EXTENSION DeviceExtension; + + if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + + DeviceExtension = DeviceObject->DeviceExtension; + /* PRECONDITION */ + assert (DeviceExtension != NULL); + assert (DeviceExtension->FatInfo.BytesPerCluster != 0); + assert (StandardInfo != NULL); + assert (FCB != NULL); + + RtlZeroMemory(StandardInfo, + sizeof(FILE_STANDARD_INFORMATION)); + + StandardInfo->AllocationSize = FCB->RFCB.AllocationSize; + StandardInfo->EndOfFile = FCB->RFCB.FileSize; + StandardInfo->NumberOfLinks = 0; + StandardInfo->DeletePending = FCB->Flags & FCB_DELETE_PENDING ? TRUE : FALSE; + StandardInfo->Directory = FCB->entry.Attrib & 0x10 ? TRUE : FALSE; + + *BufferLength -= sizeof(FILE_STANDARD_INFORMATION); + return(STATUS_SUCCESS); +} + +static NTSTATUS +VfatSetPositionInformation(PFILE_OBJECT FileObject, + PVFATFCB FCB, + PDEVICE_OBJECT DeviceObject, + PFILE_POSITION_INFORMATION PositionInfo) +{ + DPRINT ("FsdSetPositionInformation()\n"); + + DPRINT ("PositionInfo %x\n", PositionInfo); + DPRINT ("Setting position %d\n", PositionInfo->CurrentByteOffset.u.LowPart); + memcpy (&FileObject->CurrentByteOffset, &PositionInfo->CurrentByteOffset, + sizeof (LARGE_INTEGER)); + + return (STATUS_SUCCESS); +} + +static NTSTATUS +VfatGetPositionInformation(PFILE_OBJECT FileObject, + PVFATFCB FCB, + PDEVICE_OBJECT DeviceObject, + PFILE_POSITION_INFORMATION PositionInfo, + PULONG BufferLength) +{ + DPRINT ("VfatGetPositionInformation()\n"); + + if (*BufferLength < sizeof(FILE_POSITION_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + + PositionInfo->CurrentByteOffset.QuadPart = + FileObject->CurrentByteOffset.QuadPart; + + DPRINT("Getting position %I64x\n", + PositionInfo->CurrentByteOffset.QuadPart); + + *BufferLength -= sizeof(FILE_POSITION_INFORMATION); + return(STATUS_SUCCESS); +} + +static NTSTATUS +VfatGetBasicInformation(PFILE_OBJECT FileObject, + PVFATFCB FCB, + PDEVICE_OBJECT DeviceObject, + PFILE_BASIC_INFORMATION BasicInfo, + PULONG BufferLength) +{ + DPRINT("VfatGetBasicInformation()\n"); + + if (*BufferLength < sizeof(FILE_BASIC_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + + FsdDosDateTimeToFileTime(FCB->entry.CreationDate, + FCB->entry.CreationTime, + &BasicInfo->CreationTime); + FsdDosDateTimeToFileTime(FCB->entry.AccessDate, + 0, + &BasicInfo->LastAccessTime); + FsdDosDateTimeToFileTime(FCB->entry.UpdateDate, + FCB->entry.UpdateTime, + &BasicInfo->LastWriteTime); + FsdDosDateTimeToFileTime(FCB->entry.UpdateDate, + FCB->entry.UpdateTime, + &BasicInfo->ChangeTime); + + BasicInfo->FileAttributes = FCB->entry.Attrib; + DPRINT("Getting attributes %x\n", BasicInfo->FileAttributes); + + *BufferLength -= sizeof(FILE_BASIC_INFORMATION); + return(STATUS_SUCCESS); +} + + +static NTSTATUS +VfatSetDispositionInformation(PFILE_OBJECT FileObject, + PVFATFCB FCB, + PDEVICE_OBJECT DeviceObject, + PFILE_DISPOSITION_INFORMATION DispositionInfo) +{ + KIRQL oldIrql; + VFATFCB tmpFcb; + WCHAR star[2]; + ULONG Index; + NTSTATUS Status = STATUS_SUCCESS; + int count; + + PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; + + DPRINT ("FsdSetDispositionInformation()\n"); + + assert (DeviceExt != NULL); + assert (DeviceExt->FatInfo.BytesPerCluster != 0); + assert (FCB != NULL); + + if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..") + || !wcscmp(FCB->ObjectName, L".")) + { + // we cannot delete a '.', '..' or the root directory + return STATUS_ACCESS_DENIED; + } + if (DispositionInfo->DoDeleteFile) + { + KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql); + count = FCB->RefCount; + if (FCB->RefCount > 1) + Status = STATUS_ACCESS_DENIED; + else + { + FCB->Flags |= FCB_DELETE_PENDING; + FileObject->DeletePending = TRUE; + } + KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql); + DPRINT("RefCount:%d\n", count); + if (NT_SUCCESS(Status) && vfatFCBIsDirectory(DeviceExt, FCB)) + { + memset (&tmpFcb, 0, sizeof(VFATFCB)); + tmpFcb.ObjectName = tmpFcb.PathName; + star[0] = L'*'; + star[1] = 0; + // skip '.' and '..', start by 2 + Index = 2; + Status = FindFile (DeviceExt, &tmpFcb, FCB, star, &Index, NULL); + if (NT_SUCCESS(Status)) + { + DPRINT1("found: \'%S\'\n", tmpFcb.PathName); + Status = STATUS_DIRECTORY_NOT_EMPTY; + FCB->Flags &= ~FCB_DELETE_PENDING; + FileObject->DeletePending = FALSE; + } + else + { + Status = STATUS_SUCCESS; + } + } + } + else + FileObject->DeletePending = FALSE; + return Status; +} + +static NTSTATUS +VfatGetNameInformation(PFILE_OBJECT FileObject, + PVFATFCB FCB, + PDEVICE_OBJECT DeviceObject, + PFILE_NAME_INFORMATION NameInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the file name information + */ +{ + ULONG NameLength; + + assert (NameInfo != NULL); + assert (FCB != NULL); + + NameLength = wcslen(FCB->PathName) * sizeof(WCHAR); + if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength) + return STATUS_BUFFER_OVERFLOW; + + NameInfo->FileNameLength = NameLength; + memcpy(NameInfo->FileName, + FCB->PathName, + NameLength + sizeof(WCHAR)); + + *BufferLength -= + (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR)); + + return STATUS_SUCCESS; +} + +static NTSTATUS +VfatGetInternalInformation(PVFATFCB Fcb, + PFILE_INTERNAL_INFORMATION InternalInfo, + PULONG BufferLength) +{ + assert (InternalInfo); + assert (Fcb); + + if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION)) + return STATUS_BUFFER_OVERFLOW; + // FIXME: get a real index, that can be used in a create operation + InternalInfo->IndexNumber.QuadPart = 0; + *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION); + return STATUS_SUCCESS; +} + + +static NTSTATUS +VfatGetNetworkOpenInformation(PVFATFCB Fcb, + PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the file network open information + */ +{ + assert (NetworkInfo); + assert (Fcb); + + if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + FsdDosDateTimeToFileTime(Fcb->entry.CreationDate, + Fcb->entry.CreationTime, + &NetworkInfo->CreationTime); + FsdDosDateTimeToFileTime(Fcb->entry.AccessDate, + 0, + &NetworkInfo->LastAccessTime); + FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate, + Fcb->entry.UpdateTime, + &NetworkInfo->LastWriteTime); + FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate, + Fcb->entry.UpdateTime, + &NetworkInfo->ChangeTime); + NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize; + NetworkInfo->EndOfFile = Fcb->RFCB.FileSize; + NetworkInfo->FileAttributes = Fcb->entry.Attrib; + + *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION); + return STATUS_SUCCESS; +} + + +static NTSTATUS +VfatGetAllInformation(PFILE_OBJECT FileObject, + PVFATFCB Fcb, + PFILE_ALL_INFORMATION Info, + PULONG BufferLength) +/* + * FUNCTION: Retrieve the all file information + */ +{ + ULONG NameLength; + + assert (Info); + assert (Fcb); + + NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR); + if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength) + return(STATUS_BUFFER_OVERFLOW); + + /* Basic Information */ + FsdDosDateTimeToFileTime(Fcb->entry.CreationDate, + Fcb->entry.CreationTime, + &Info->BasicInformation.CreationTime); + FsdDosDateTimeToFileTime(Fcb->entry.AccessDate, + 0, + &Info->BasicInformation.LastAccessTime); + FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate, + Fcb->entry.UpdateTime, + &Info->BasicInformation.LastWriteTime); + FsdDosDateTimeToFileTime(Fcb->entry.UpdateDate, + Fcb->entry.UpdateTime, + &Info->BasicInformation.ChangeTime); + Info->BasicInformation.FileAttributes = Fcb->entry.Attrib; + + /* Standard Information */ + Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize; + Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize; + Info->StandardInformation.NumberOfLinks = 0; + Info->StandardInformation.DeletePending = Fcb->Flags & FCB_DELETE_PENDING ? TRUE : FALSE; + Info->StandardInformation.Directory = Fcb->entry.Attrib & 0x10 ? TRUE : FALSE; + + /* Internal Information */ + /* FIXME: get a real index, that can be used in a create operation */ + Info->InternalInformation.IndexNumber.QuadPart = 0; + + /* EA Information */ + Info->EaInformation.EaSize = 0; + + /* Access Information */ + /* The IO-Manager adds this information */ + + /* Position Information */ + Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart; + + /* Mode Information */ + /* The IO-Manager adds this information */ + + /* Alignment Information */ + /* The IO-Manager adds this information */ + + /* Name Information */ + Info->NameInformation.FileNameLength = NameLength; + RtlCopyMemory(Info->NameInformation.FileName, + Fcb->PathName, + NameLength + sizeof(WCHAR)); + + *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR)); + + return STATUS_SUCCESS; +} + +NTSTATUS +VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, + PVFATFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER AllocationSize) +{ + ULONG OldSize; + ULONG Cluster, FirstCluster; + ULONG Offset; + NTSTATUS Status; + + ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster; + ULONG NewSize = AllocationSize->u.LowPart; + ULONG NCluster; + + DPRINT("VfatSetAllocationSizeInformation()\n"); + + OldSize = Fcb->entry.FileSize; + if (AllocationSize->u.HighPart > 0) + { + return STATUS_INVALID_PARAMETER; + } + if (OldSize == NewSize) + { + return(STATUS_SUCCESS); + } + + FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry); + + if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart) + { + if (FirstCluster == 0) + { + Status = NextCluster (DeviceExt, Fcb, FirstCluster, &FirstCluster, TRUE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NextCluster failed.\n"); + return Status; + } + if (FirstCluster == 0xffffffff) + { + return STATUS_DISK_FULL; + } + Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, + ROUND_DOWN(NewSize - 1, ClusterSize), + &NCluster, TRUE); + if (NCluster == 0xffffffff) + { + /* disk is full */ + NCluster = Cluster = FirstCluster; + while (Cluster != 0xffffffff) + { + NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE); + WriteCluster (DeviceExt, Cluster, 0); + Cluster = NCluster; + } + return STATUS_DISK_FULL; + } + Fcb->entry.FirstCluster = (FirstCluster & 0x0000FFFF); + Fcb->entry.FirstClusterHigh = (FirstCluster & 0xFFFF0000) >> 16; + } + else + { + Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, + Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize, + &Cluster, FALSE); + /* Cluster points now to the last cluster within the chain */ + Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, + ROUND_DOWN(NewSize - 1, ClusterSize), + &NCluster, TRUE); + if (NCluster == 0xffffffff) + { + /* disk is full */ + NCluster = Cluster; + NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE); + WriteCluster(DeviceExt, Cluster, 0xffffffff); + Cluster = NCluster; + while (Cluster != 0xffffffff) + { + NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE); + WriteCluster (DeviceExt, Cluster, 0); + Cluster = NCluster; + } + return STATUS_DISK_FULL; + } + } + } + else if (NewSize <= Fcb->RFCB.AllocationSize.u.LowPart - ClusterSize) + { + if (NewSize > 0) + { + Status = OffsetToCluster(DeviceExt, Fcb, Cluster, + ROUND_DOWN(NewSize - 1, ClusterSize), + &Cluster, FALSE); + + } + NCluster = Cluster; + Status = NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE); + WriteCluster(DeviceExt, Cluster, 0xffffffff); + Cluster = NCluster; + while (Cluster != 0xffffffff) + { + NextCluster (DeviceExt, Fcb, Cluster, &NCluster, FALSE); + WriteCluster (DeviceExt, Cluster, 0); + Cluster = NCluster; + } + } + if (!vfatFCBIsDirectory(DeviceExt, Fcb)) + { + Fcb->entry.FileSize = NewSize; + } + if (NewSize > 0) + { + Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(NewSize - 1, ClusterSize); + } + else + { + Fcb->RFCB.AllocationSize.QuadPart = 0LL; + Fcb->entry.FirstCluster = 0; + Fcb->entry.FirstClusterHigh = 0; + } + Fcb->RFCB.FileSize.QuadPart = NewSize; + Fcb->RFCB.ValidDataLength.QuadPart = NewSize; + + if (FileObject->SectionObjectPointers->SharedCacheMap != NULL) + { + CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize); + } + /* Update the on-disk directory entry */ + VfatUpdateEntry(DeviceExt, FileObject); + return STATUS_SUCCESS; +} + +NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Retrieve the specified file information + */ +{ + FILE_INFORMATION_CLASS FileInformationClass; + PVFATFCB FCB = NULL; + + NTSTATUS RC = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + /* PRECONDITION */ + assert (IrpContext); + + /* INITIALIZATION */ + FileInformationClass = IrpContext->Stack->Parameters.QueryFile.FileInformationClass; + FCB = ((PVFATCCB) IrpContext->FileObject->FsContext2)->pFcb; + + SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; + BufferLength = IrpContext->Stack->Parameters.QueryFile.Length; + + if (!(FCB->Flags & FCB_IS_PAGE_FILE)) + { + if (!ExAcquireResourceSharedLite(&FCB->MainResource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return VfatQueueRequest (IrpContext); + } + } + + + switch (FileInformationClass) + { + case FileStandardInformation: + RC = VfatGetStandardInformation(FCB, + IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + case FilePositionInformation: + RC = VfatGetPositionInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + case FileBasicInformation: + RC = VfatGetBasicInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + case FileNameInformation: + RC = VfatGetNameInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + case FileInternalInformation: + RC = VfatGetInternalInformation(FCB, + SystemBuffer, + &BufferLength); + break; + case FileNetworkOpenInformation: + RC = VfatGetNetworkOpenInformation(FCB, + SystemBuffer, + &BufferLength); + break; + case FileAllInformation: + RC = VfatGetAllInformation(IrpContext->FileObject, + FCB, + SystemBuffer, + &BufferLength); + break; + + case FileAlternateNameInformation: + RC = STATUS_NOT_IMPLEMENTED; + break; + default: + RC = STATUS_NOT_SUPPORTED; + } + + if (!(FCB->Flags & FCB_IS_PAGE_FILE)) + { + ExReleaseResourceLite(&FCB->MainResource); + } + IrpContext->Irp->IoStatus.Status = RC; + if (NT_SUCCESS(RC)) + IrpContext->Irp->IoStatus.Information = + IrpContext->Stack->Parameters.QueryFile.Length - BufferLength; + else + IrpContext->Irp->IoStatus.Information = 0; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + + return RC; +} + +NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Retrieve the specified file information + */ +{ + FILE_INFORMATION_CLASS FileInformationClass; + PVFATFCB FCB = NULL; + NTSTATUS RC = STATUS_SUCCESS; + PVOID SystemBuffer; + BOOL CanWait = IrpContext->Flags & IRPCONTEXT_CANWAIT; + + /* PRECONDITION */ + assert(IrpContext); + + DPRINT("VfatSetInformation(IrpContext %x)\n", IrpContext); + + /* INITIALIZATION */ + FileInformationClass = + IrpContext->Stack->Parameters.SetFile.FileInformationClass; + FCB = ((PVFATCCB) IrpContext->FileObject->FsContext2)->pFcb; + SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; + + DPRINT("FileInformationClass %d\n", FileInformationClass); + DPRINT("SystemBuffer %x\n", SystemBuffer); + + if (FCB->Flags & FCB_IS_PAGE_FILE) + { + if (!ExAcquireResourceExclusiveLite(&FCB->PagingIoResource, CanWait)) + { + return(VfatQueueRequest (IrpContext)); + } + } + else + { + if (!ExAcquireResourceExclusiveLite(&FCB->MainResource, CanWait)) + { + return(VfatQueueRequest (IrpContext)); + } + } + + switch (FileInformationClass) + { + case FilePositionInformation: + RC = VfatSetPositionInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceObject, + SystemBuffer); + break; + case FileDispositionInformation: + RC = VfatSetDispositionInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceObject, + SystemBuffer); + break; + case FileAllocationInformation: + case FileEndOfFileInformation: + RC = VfatSetAllocationSizeInformation(IrpContext->FileObject, + FCB, + IrpContext->DeviceExt, + (PLARGE_INTEGER)SystemBuffer); + break; + case FileBasicInformation: + case FileRenameInformation: + RC = STATUS_NOT_IMPLEMENTED; + break; + default: + RC = STATUS_NOT_SUPPORTED; + } + + if (FCB->Flags & FCB_IS_PAGE_FILE) + { + ExReleaseResourceLite(&FCB->PagingIoResource); + } + else + { + ExReleaseResourceLite(&FCB->MainResource); + } + + IrpContext->Irp->IoStatus.Status = RC; + IrpContext->Irp->IoStatus.Information = 0; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + + return RC; +} + +/* EOF */ diff --git a/drivers/fs/vfat/fsctl.c b/drivers/fs/vfat/fsctl.c new file mode 100644 index 0000000..244079e --- /dev/null +++ b/drivers/fs/vfat/fsctl.c @@ -0,0 +1,436 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/fsctl.c + * PURPOSE: VFAT Filesystem + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \ + (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE) + + +static NTSTATUS +VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount, + PBOOLEAN RecognizedFS, + PFATINFO pFatInfo) +{ + NTSTATUS Status; + PARTITION_INFORMATION PartitionInfo; + DISK_GEOMETRY DiskGeometry; + FATINFO FatInfo; + ULONG Size; + ULONG Sectors; + LARGE_INTEGER Offset; + struct _BootSector* Boot; + + *RecognizedFS = FALSE; + + Size = sizeof(DISK_GEOMETRY); + Status = VfatBlockDeviceIoControl(DeviceToMount, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status); + return Status; + } + if (DiskGeometry.MediaType == FixedMedia) + { + // We have found a hard disk + Size = sizeof(PARTITION_INFORMATION); + Status = VfatBlockDeviceIoControl(DeviceToMount, + IOCTL_DISK_GET_PARTITION_INFO, + NULL, + 0, + &PartitionInfo, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("VfatBlockDeviceIoControl faild (%x)\n", Status); + return Status; + } +#ifndef NDEBUG + DbgPrint("Partition Information:\n"); + DbgPrint("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart / 512); + DbgPrint("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart / 512); + DbgPrint("HiddenSectors %u\n", PartitionInfo.HiddenSectors); + DbgPrint("PartitionNumber %u\n", PartitionInfo.PartitionNumber); + DbgPrint("PartitionType %u\n", PartitionInfo.PartitionType); + DbgPrint("BootIndicator %u\n", PartitionInfo.BootIndicator); + DbgPrint("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition); + DbgPrint("RewritePartition %u\n", PartitionInfo.RewritePartition); +#endif + if (PartitionInfo.PartitionType == PARTITION_FAT_12 || + PartitionInfo.PartitionType == PARTITION_FAT_16 || + PartitionInfo.PartitionType == PARTITION_HUGE || + PartitionInfo.PartitionType == PARTITION_FAT32 || + PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 || + PartitionInfo.PartitionType == PARTITION_XINT13) + { + *RecognizedFS = TRUE; + } + } + else if (DiskGeometry.MediaType > Unknown && DiskGeometry.MediaType <= RemovableMedia) + { + *RecognizedFS = TRUE; + } + if (*RecognizedFS == FALSE) + { + return STATUS_SUCCESS; + } + + Boot = ExAllocatePool(NonPagedPool, DiskGeometry.BytesPerSector); + if (Boot == NULL) + { + *RecognizedFS=FALSE; + return STATUS_INSUFFICIENT_RESOURCES; + } + Offset.QuadPart = 0; + Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot); + if (NT_SUCCESS(Status)) + { + FatInfo.VolumeID = Boot->VolumeID; + FatInfo.FATStart = Boot->ReservedSectors; + FatInfo.FATCount = Boot->FATCount; + FatInfo.FATSectors = Boot->FATSectors ? Boot->FATSectors : ((struct _BootSector32*) Boot)->FATSectors32; + FatInfo.BytesPerSector = Boot->BytesPerSector; + FatInfo.SectorsPerCluster = Boot->SectorsPerCluster; + FatInfo.BytesPerCluster = FatInfo.BytesPerSector * FatInfo.SectorsPerCluster; + FatInfo.rootDirectorySectors = ((Boot->RootEntries * 32) + Boot->BytesPerSector - 1) / Boot->BytesPerSector; + FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors; + FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors; + FatInfo.Sectors = Sectors = Boot->Sectors ? Boot->Sectors : Boot->SectorsHuge; + Sectors -= Boot->ReservedSectors + FatInfo.FATCount * FatInfo.FATSectors + FatInfo.rootDirectorySectors; + FatInfo.NumberOfClusters = Sectors / Boot->SectorsPerCluster; + if (FatInfo.NumberOfClusters < 4085) + { + DPRINT("FAT12\n"); + FatInfo.FatType = FAT12; + } + else if (FatInfo.NumberOfClusters >= 65525) + { + DPRINT("FAT32\n"); + FatInfo.FatType = FAT32; + FatInfo.RootCluster = ((struct _BootSector32*) Boot)->RootCluster; + FatInfo.rootStart = FatInfo.dataStart + ((FatInfo.RootCluster - 2) * FatInfo.SectorsPerCluster); + FatInfo.VolumeID = ((struct _BootSector32*) Boot)->VolumeID; + } + else + { + DPRINT("FAT16\n"); + FatInfo.FatType = FAT16; + } + if (pFatInfo) + { + *pFatInfo = FatInfo; + } + } + ExFreePool(Boot); + return Status; +} + +static NTSTATUS +VfatMountDevice(PDEVICE_EXTENSION DeviceExt, + PDEVICE_OBJECT DeviceToMount) +/* + * FUNCTION: Mounts the device + */ +{ + NTSTATUS Status; + BOOLEAN RecognizedFS; + + DPRINT("Mounting VFAT device...\n"); + + Status = VfatHasFileSystem(DeviceToMount, &RecognizedFS, &DeviceExt->FatInfo); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (DeviceExt->FatInfo.BytesPerCluster >= PAGE_SIZE && + (DeviceExt->FatInfo.BytesPerCluster % PAGE_SIZE) != 0) + { + DbgPrint("(%s:%d) Invalid cluster size\n", __FILE__, __LINE__); + KeBugCheck(0); + } + else if (DeviceExt->FatInfo.BytesPerCluster < PAGE_SIZE && + (PAGE_SIZE % DeviceExt->FatInfo.BytesPerCluster) != 0) + { + DbgPrint("(%s:%d) Invalid cluster size2\n", __FILE__, __LINE__); + KeBugCheck(0); + } + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +VfatMount (PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Mount the filesystem + */ +{ + PDEVICE_OBJECT DeviceObject = NULL; + PDEVICE_EXTENSION DeviceExt = NULL; + BOOLEAN RecognizedFS; + NTSTATUS Status; + PVFATFCB Fcb = NULL; + PVFATFCB VolumeFcb = NULL; + PVFATCCB Ccb = NULL; + LARGE_INTEGER timeout; + + DPRINT("VfatMount(IrpContext %x)\n", IrpContext); + + assert (IrpContext); + + if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + Status = VfatHasFileSystem (IrpContext->Stack->Parameters.MountVolume.DeviceObject, &RecognizedFS, NULL); + if (!NT_SUCCESS(Status)) + { + goto ByeBye; + } + + if (RecognizedFS == FALSE) + { + DPRINT("VFAT: Unrecognized Volume\n"); + Status = STATUS_UNRECOGNIZED_VOLUME; + goto ByeBye; + } + + DPRINT("VFAT: Recognized volume\n"); + Status = IoCreateDevice(VfatGlobalData->DriverObject, + sizeof (DEVICE_EXTENSION), + NULL, + FILE_DEVICE_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + goto ByeBye; + } + + DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; + DeviceExt = (PVOID) DeviceObject->DeviceExtension; + RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION)); + + /* use same vpb as device disk */ + DeviceObject->Vpb = IrpContext->Stack->Parameters.MountVolume.DeviceObject->Vpb; + Status = VfatMountDevice(DeviceExt, IrpContext->Stack->Parameters.MountVolume.DeviceObject); + if (!NT_SUCCESS(Status)) + { + /* FIXME: delete device object */ + goto ByeBye; + } + +#ifndef NDEBUG + DbgPrint("BytesPerSector: %d\n", DeviceExt->FatInfo.BytesPerSector); + DbgPrint("SectorsPerCluster: %d\n", DeviceExt->FatInfo.SectorsPerCluster); + DbgPrint("FATCount: %d\n", DeviceExt->FatInfo.FATCount); + DbgPrint("FATSectors: %d\n", DeviceExt->FatInfo.FATSectors); + DbgPrint("RootStart: %d\n", DeviceExt->FatInfo.rootStart); + DbgPrint("DataStart: %d\n", DeviceExt->FatInfo.dataStart); + if (DeviceExt->FatInfo.FatType == FAT32) + { + DbgPrint("RootCluster: %d\n", DeviceExt->FatInfo.RootCluster); + } +#endif + + DeviceExt->StorageDevice = IrpContext->Stack->Parameters.MountVolume.DeviceObject; + DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject; + DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice; + DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED; + DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + DPRINT("FsDeviceObject %lx\n", DeviceObject); + + DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice); + Fcb = vfatNewFCB(NULL); + if (Fcb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + Ccb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB); + if (Ccb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + memset(Ccb, 0, sizeof (VFATCCB)); + wcscpy(Fcb->PathName, L"$$Fat$$"); + Fcb->ObjectName = Fcb->PathName; + DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ; + DeviceExt->FATFileObject->FsContext = (PVOID) &Fcb->RFCB; + DeviceExt->FATFileObject->FsContext2 = Ccb; + DeviceExt->FATFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers; + DeviceExt->FATFileObject->PrivateCacheMap = NULL; + DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb; + Ccb->pFcb = Fcb; + Ccb->PtrFileObject = DeviceExt->FATFileObject; + Fcb->FileObject = DeviceExt->FATFileObject; + Fcb->pDevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; + + Fcb->Flags = FCB_IS_FAT; + + Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector; + Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize; + Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize; + + if (DeviceExt->FatInfo.FatType != FAT12) + { + Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt)); + } + else + { + Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, 2 * PAGE_SIZE); + } + if (!NT_SUCCESS (Status)) + { + DbgPrint ("CcRosInitializeFileCache failed\n"); + goto ByeBye; + } + DeviceExt->LastAvailableCluster = 0; + ExInitializeResourceLite(&DeviceExt->DirResource); + ExInitializeResourceLite(&DeviceExt->FatResource); + + KeInitializeSpinLock(&DeviceExt->FcbListLock); + InitializeListHead(&DeviceExt->FcbListHead); + + VolumeFcb = vfatNewFCB(NULL); + if (VolumeFcb == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto ByeBye; + } + wcscpy(VolumeFcb->PathName, L"$$Volume$$"); + VolumeFcb->ObjectName = VolumeFcb->PathName; + VolumeFcb->Flags = FCB_IS_VOLUME; + VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector; + VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize; + VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize; + VolumeFcb->pDevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice; + DeviceExt->VolumeFcb = VolumeFcb; + + /* read serial number */ + DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID; + + /* read volume label */ + ReadVolumeLabel(DeviceExt, DeviceObject->Vpb); + + Status = STATUS_SUCCESS; +ByeBye: + + if (!NT_SUCCESS(Status)) + { + // cleanup + if (DeviceExt && DeviceExt->FATFileObject) + ObDereferenceObject (DeviceExt->FATFileObject); + if (Fcb) + ExFreePool(Fcb); + if (Ccb) + ExFreePool(Ccb); + if (DeviceObject) + IoDeleteDevice(DeviceObject); + if (VolumeFcb) + vfatDestroyFCB(VolumeFcb); + } + return Status; +} + + +static NTSTATUS +VfatVerify (PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Mount the filesystem + */ +{ + DPRINT("VfatVerify(IrpContext %x)\n", IrpContext); + + assert(IrpContext); + + return(STATUS_INVALID_DEVICE_REQUEST); +} + + +NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: File system control + */ +{ + + NTSTATUS Status; + + DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext); + + assert (IrpContext); + + switch (IrpContext->MinorFunction) + { + case IRP_MN_USER_FS_REQUEST: + DPRINT("VFAT FSC: IRP_MN_USER_FS_REQUEST\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + + case IRP_MN_MOUNT_VOLUME: + Status = VfatMount(IrpContext); + break; + + case IRP_MN_VERIFY_VOLUME: + Status = VfatVerify(IrpContext); + break; + + default: + DPRINT("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction); + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + IrpContext->Irp->IoStatus.Status = Status; + IrpContext->Irp->IoStatus.Information = 0; + + IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + return (Status); +} + diff --git a/drivers/fs/vfat/iface.c b/drivers/fs/vfat/iface.c new file mode 100644 index 0000000..9b7aad2 --- /dev/null +++ b/drivers/fs/vfat/iface.c @@ -0,0 +1,96 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/iface.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* GLOBALS *****************************************************************/ + +PVFAT_GLOBAL_DATA VfatGlobalData; + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initalize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Fat"); + NTSTATUS Status; + + Status = IoCreateDevice(DriverObject, + sizeof(VFAT_GLOBAL_DATA), + &DeviceName, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + VfatGlobalData = DeviceObject->DeviceExtension; + RtlZeroMemory (VfatGlobalData, sizeof(VFAT_GLOBAL_DATA)); + VfatGlobalData->DriverObject = DriverObject; + VfatGlobalData->DeviceObject = DeviceObject; + + DeviceObject->Flags = DO_DIRECT_IO; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = + VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = + VfatBuildRequest; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest; + + DriverObject->DriverUnload = NULL; + + IoRegisterFileSystem(DeviceObject); + return(STATUS_SUCCESS); +} + +/* EOF */ + diff --git a/drivers/fs/vfat/makefile b/drivers/fs/vfat/makefile new file mode 100644 index 0000000..ad6160d --- /dev/null +++ b/drivers/fs/vfat/makefile @@ -0,0 +1,42 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = vfatfs + +TARGET_GCCLIBS = gcc + +TARGET_OBJECTS = \ + blockdev.o \ + cleanup.o \ + close.o \ + create.o \ + dir.o \ + direntry.o \ + dirwr.o \ + fat.o \ + fcb.o \ + finfo.o \ + iface.o \ + rw.o \ + shutdown.o \ + string.o \ + volume.o \ + misc.o \ + fsctl.o \ + ea.o + +DEP_OBJECTS = $(TARGET_OBJECTS) + +TARGET_CLEAN = $(DEP_FILES) *.o *.sys *.sym + +TARGET_CFLAGS = -g + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/depend.mk + diff --git a/drivers/fs/vfat/misc.c b/drivers/fs/vfat/misc.c new file mode 100644 index 0000000..dd71eb8 --- /dev/null +++ b/drivers/fs/vfat/misc.c @@ -0,0 +1,196 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/misc.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Hartmut Birr + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +static LONG QueueCount = 0; + +NTSTATUS VfatDispatchRequest ( + IN PVFAT_IRP_CONTEXT IrpContext) +{ + DPRINT ("VfatDispatchRequest (IrpContext %x), MajorFunction %x\n", IrpContext, IrpContext->MajorFunction); + + assert (IrpContext); + + switch (IrpContext->MajorFunction) + { + case IRP_MJ_CLOSE: + return VfatClose (IrpContext); + case IRP_MJ_CREATE: + return VfatCreate (IrpContext); + case IRP_MJ_READ: + return VfatRead (IrpContext); + case IRP_MJ_WRITE: + return VfatWrite (IrpContext); + case IRP_MJ_FILE_SYSTEM_CONTROL: + return VfatFileSystemControl(IrpContext); + case IRP_MJ_QUERY_INFORMATION: + return VfatQueryInformation (IrpContext); + case IRP_MJ_SET_INFORMATION: + return VfatSetInformation (IrpContext); + case IRP_MJ_DIRECTORY_CONTROL: + return VfatDirectoryControl(IrpContext); + case IRP_MJ_QUERY_VOLUME_INFORMATION: + return VfatQueryVolumeInformation(IrpContext); + case IRP_MJ_SET_VOLUME_INFORMATION: + return VfatSetVolumeInformation(IrpContext); + case IRP_MJ_CLEANUP: + return VfatCleanup(IrpContext); + default: + DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction); + IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + return STATUS_DRIVER_INTERNAL_ERROR; + } +} + + +NTSTATUS STDCALL VfatBuildRequest ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status; + PVFAT_IRP_CONTEXT IrpContext; + + DPRINT ("VfatBuildRequest (DeviceObject %x, Irp %x)\n", DeviceObject, Irp); + + assert (DeviceObject); + assert (Irp); + + FsRtlEnterFileSystem(); + IrpContext = VfatAllocateIrpContext(DeviceObject, Irp); + if (IrpContext == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + } + else + { + Status = VfatDispatchRequest (IrpContext); + } + FsRtlExitFileSystem(); + return Status; +} + +VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext) +{ + assert (IrpContext); + ExFreePool(IrpContext); +} + +PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PVFAT_IRP_CONTEXT IrpContext; + PIO_STACK_LOCATION Stack; + UCHAR MajorFunction; + DPRINT ("VfatAllocateIrpContext(DeviceObject %x, Irp %x)\n", DeviceObject, Irp); + + assert (DeviceObject); + assert (Irp); + + IrpContext = ExAllocatePool (NonPagedPool, sizeof(VFAT_IRP_CONTEXT)); + if (IrpContext) + { + RtlZeroMemory(IrpContext, sizeof(IrpContext)); + IrpContext->Irp = Irp; + IrpContext->DeviceObject = DeviceObject; + IrpContext->DeviceExt = DeviceObject->DeviceExtension; + IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp); + assert (IrpContext->Stack); + MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction; + IrpContext->MinorFunction = IrpContext->Stack->MinorFunction; + IrpContext->FileObject = IrpContext->Stack->FileObject; + if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL || + MajorFunction == IRP_MJ_DEVICE_CONTROL || + MajorFunction == IRP_MJ_SHUTDOWN) + { + IrpContext->Flags |= IRPCONTEXT_CANWAIT; + } + else if (MajorFunction != IRP_MJ_CLEANUP && + MajorFunction != IRP_MJ_CLOSE && + IoIsOperationSynchronous(Irp)) + { + IrpContext->Flags |= IRPCONTEXT_CANWAIT; + } + } + return IrpContext; +} + +VOID STDCALL VfatDoRequest (PVOID IrpContext) +{ + ULONG Count = InterlockedDecrement(&QueueCount); + DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, Count); + VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext); + +} + +NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext) +{ + ULONG Count = InterlockedIncrement(&QueueCount); + DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, Count); + + assert (IrpContext != NULL); + assert (IrpContext->Irp != NULL); + + IrpContext->Flags |= IRPCONTEXT_CANWAIT; + IoMarkIrpPending (IrpContext->Irp); + ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext); + ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue); + return STATUS_PENDING; +} + +PVOID VfatGetUserBuffer(IN PIRP Irp) +{ + assert(Irp); + + if (Irp->MdlAddress) + { + return MmGetSystemAddressForMdl(Irp->MdlAddress); + } + else + { + return Irp->UserBuffer; + } +} + +NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation) +{ + assert(Irp); + + if (Irp->MdlAddress) + { + return STATUS_SUCCESS; + } + + IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp); + + if (!Irp->MdlAddress) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation); + + return STATUS_SUCCESS; +} + + diff --git a/drivers/fs/vfat/rw.c b/drivers/fs/vfat/rw.c new file mode 100644 index 0000000..cd63a63 --- /dev/null +++ b/drivers/fs/vfat/rw.c @@ -0,0 +1,1068 @@ + +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/rw.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NextCluster(PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + ULONG FirstCluster, + PULONG CurrentCluster, + BOOLEAN Extend) + /* + * Return the next cluster in a FAT chain, possibly extending the chain if + * necessary + */ +{ + if (Fcb != NULL && Fcb->Flags & FCB_IS_PAGE_FILE) + { + ULONG i; + PULONG FatChain; + NTSTATUS Status; + DPRINT("NextCluster(Fcb %x, FirstCluster %x, Extend %d)\n", Fcb, + FirstCluster, Extend); + if (Fcb->FatChainSize == 0) + { + /* Paging file with zero length. */ + *CurrentCluster = 0xffffffff; + if (Extend) + { + Fcb->FatChain = ExAllocatePool(NonPagedPool, sizeof(ULONG)); + if (Fcb->FatChain == NULL) + { + return(STATUS_NO_MEMORY); + } + Status = GetNextCluster(DeviceExt, 0, CurrentCluster, TRUE); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Fcb->FatChain); + return(Status); + } + Fcb->FatChain[0] = *CurrentCluster; + Fcb->FatChainSize = 1; + return Status; + } + else + { + return STATUS_UNSUCCESSFUL; + } + } + else + { + for (i = 0; i < Fcb->FatChainSize; i++) + { + if (Fcb->FatChain[i] == *CurrentCluster) + break; + } + if (i >= Fcb->FatChainSize) + { + return STATUS_UNSUCCESSFUL; + } + if (i == Fcb->FatChainSize - 1) + { + if (Extend) + { + FatChain = ExAllocatePool(NonPagedPool, + (i + 2) * sizeof(ULONG)); + if (!FatChain) + { + *CurrentCluster = 0xffffffff; + return STATUS_NO_MEMORY; + } + Status = GetNextCluster(DeviceExt, *CurrentCluster, + CurrentCluster, TRUE); + if (NT_SUCCESS(Status) && *CurrentCluster != 0xffffffff) + { + memcpy(FatChain, Fcb->FatChain, (i + 1) * sizeof(ULONG)); + FatChain[i + 1] = *CurrentCluster; + ExFreePool(Fcb->FatChain); + Fcb->FatChain = FatChain; + Fcb->FatChainSize = i + 2; + } + else + { + ExFreePool(FatChain); + } + return Status; + } + else + { + *CurrentCluster = 0xffffffff; + return STATUS_SUCCESS; + } + } + *CurrentCluster = Fcb->FatChain[i + 1]; + return STATUS_SUCCESS; + } + } + if (FirstCluster == 1) + { + (*CurrentCluster) += DeviceExt->FatInfo.SectorsPerCluster; + return(STATUS_SUCCESS); + } + else + { + /* + * CN: FIXME: Real bug here or in dirwr, where CurrentCluster isn't + * initialized when 0 + */ + if (FirstCluster == 0) + { + NTSTATUS Status; + + Status = GetNextCluster(DeviceExt, 0, CurrentCluster, + Extend); + return(Status); + } + else + { + NTSTATUS Status; + + Status = GetNextCluster(DeviceExt, (*CurrentCluster), CurrentCluster, + Extend); + return(Status); + } + } +} + +NTSTATUS +OffsetToCluster(PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + ULONG FirstCluster, + ULONG FileOffset, + PULONG Cluster, + BOOLEAN Extend) + /* + * Return the cluster corresponding to an offset within a file, + * possibly extending the file if necessary + */ +{ + ULONG CurrentCluster; + ULONG i; + NTSTATUS Status; + DPRINT("OffsetToCluster(DeviceExt %x, Fcb %x, FirstCluster %x," + " FileOffset %x, Cluster %x, Extend %d)\n", DeviceExt, + Fcb, FirstCluster, FileOffset, Cluster, Extend); + if (FirstCluster == 0) + { + DbgPrint("OffsetToCluster is called with FirstCluster = 0!\n"); + KeBugCheck(0); + } + + if (Fcb != NULL && Fcb->Flags & FCB_IS_PAGE_FILE) + { + ULONG NCluster; + ULONG Offset = FileOffset / DeviceExt->FatInfo.BytesPerCluster; + PULONG FatChain; + int i; + if (Fcb->FatChainSize == 0) + { + DbgPrint("OffsetToCluster is called with FirstCluster = %x" + " and Fcb->FatChainSize = 0!\n", FirstCluster); + KeBugCheck(0); + } + if (Offset < Fcb->FatChainSize) + { + *Cluster = Fcb->FatChain[Offset]; + return STATUS_SUCCESS; + } + else + { + if (!Extend) + { + *Cluster = 0xffffffff; + return STATUS_UNSUCCESSFUL; + } + else + { + FatChain = ExAllocatePool(NonPagedPool, (Offset + 1) * sizeof(ULONG)); + if (!FatChain) + { + *Cluster = 0xffffffff; + return STATUS_UNSUCCESSFUL; + } + + CurrentCluster = Fcb->FatChain[Fcb->FatChainSize - 1]; + FatChain[Fcb->FatChainSize - 1] = CurrentCluster; + for (i = Fcb->FatChainSize; i < Offset + 1; i++) + { + Status = GetNextCluster(DeviceExt, CurrentCluster, &CurrentCluster, TRUE); + if (!NT_SUCCESS(Status) || CurrentCluster == 0xFFFFFFFF) + { + while (i >= Fcb->FatChainSize) + { + WriteCluster(DeviceExt, FatChain[i - 1], 0xFFFFFFFF); + i--; + } + *Cluster = 0xffffffff; + ExFreePool(FatChain); + if (!NT_SUCCESS(Status)) + return Status; + return STATUS_UNSUCCESSFUL; + } + FatChain[i] = CurrentCluster; + } + memcpy (FatChain, Fcb->FatChain, Fcb->FatChainSize * sizeof(ULONG)); + ExFreePool(Fcb->FatChain); + Fcb->FatChain = FatChain; + Fcb->FatChainSize = Offset + 1; + } + } + *Cluster = CurrentCluster; + return(STATUS_SUCCESS); + } + if (FirstCluster == 1) + { + /* root of FAT16 or FAT12 */ + *Cluster = DeviceExt->FatInfo.rootStart + FileOffset + / (DeviceExt->FatInfo.BytesPerCluster) * DeviceExt->FatInfo.SectorsPerCluster; + return(STATUS_SUCCESS); + } + else + { + CurrentCluster = FirstCluster; + for (i = 0; i < FileOffset / DeviceExt->FatInfo.BytesPerCluster; i++) + { + Status = GetNextCluster (DeviceExt, CurrentCluster, &CurrentCluster, + Extend); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + *Cluster = CurrentCluster; + return(STATUS_SUCCESS); + } +} + +NTSTATUS +VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer, + ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead) +/* + * FUNCTION: Reads data from a file + */ +{ + ULONG CurrentCluster; + ULONG FirstCluster; + ULONG StartCluster; + ULONG ClusterCount; + LARGE_INTEGER StartOffset; + PDEVICE_EXTENSION DeviceExt; + BOOLEAN First = TRUE; + PVFATFCB Fcb; + PVFATCCB Ccb; + NTSTATUS Status; + ULONG BytesDone; + ULONG BytesPerSector; + ULONG BytesPerCluster; + + /* PRECONDITION */ + assert (IrpContext); + DeviceExt = IrpContext->DeviceExt; + assert (DeviceExt); + assert (DeviceExt->FatInfo.BytesPerCluster); + assert (IrpContext->FileObject); + assert (IrpContext->FileObject->FsContext2 != NULL); + + DPRINT("VfatReadFileData(DeviceExt %x, FileObject %x, Buffer %x, " + "Length %d, ReadOffset 0x%I64x)\n", DeviceExt, + IrpContext->FileObject, Buffer, Length, ReadOffset.QuadPart); + + *LengthRead = 0; + + Ccb = (PVFATCCB)IrpContext->FileObject->FsContext2; + Fcb = Ccb->pFcb; + BytesPerSector = DeviceExt->FatInfo.BytesPerSector; + BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster; + + assert(ReadOffset.QuadPart + Length <= ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector)); + assert(ReadOffset.u.LowPart % BytesPerSector == 0); + assert(Length % BytesPerSector == 0); + + /* Is this a read of the FAT? */ + if (Fcb->Flags & FCB_IS_FAT) + { + ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector; + Status = VfatReadDisk(DeviceExt->StorageDevice, &ReadOffset, Length, Buffer); + + if (NT_SUCCESS(Status)) + { + *LengthRead = Length; + } + else + { + DPRINT1("FAT reading failed, Status %x\n", Status); + } + return Status; + } + /* Is this a read of the Volume ? */ + if (Fcb->Flags & FCB_IS_VOLUME) + { + Status = VfatReadDisk(DeviceExt->StorageDevice, &ReadOffset, Length, Buffer); + if (NT_SUCCESS(Status)) + { + *LengthRead = Length; + } + else + { + DPRINT1("Volume reading failed, Status %x\n", Status); + } + return Status; + } + + /* + * Find the first cluster + */ + FirstCluster = CurrentCluster = + vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry); + + if (FirstCluster == 1) + { + // Directory of FAT12/16 needs a special handling + CHECKPOINT; + if (ReadOffset.u.LowPart + Length > DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector) + { + Length = DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector - ReadOffset.u.LowPart; + } + ReadOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector; + + // Fire up the read command + + Status = VfatReadDisk (DeviceExt->StorageDevice, &ReadOffset, Length, Buffer); + if (NT_SUCCESS(Status)) + { + *LengthRead += Length; + } + return Status; + } + /* + * Find the cluster to start the read from + */ + if (Ccb->LastCluster > 0 && ReadOffset.u.LowPart > Ccb->LastOffset) + { + CurrentCluster = Ccb->LastCluster; + } + Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, + ROUND_DOWN(ReadOffset.u.LowPart, BytesPerCluster), + &CurrentCluster, FALSE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Ccb->LastCluster = CurrentCluster; + Ccb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster); + + while (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) + { + StartCluster = CurrentCluster; + StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector; + BytesDone = 0; + ClusterCount = 0; + + do + { + ClusterCount++; + if (First) + { + BytesDone = min (Length, BytesPerCluster - (ReadOffset.u.LowPart % BytesPerCluster)); + StartOffset.QuadPart += ReadOffset.u.LowPart % BytesPerCluster; + First = FALSE; + } + else + { + if (Length - BytesDone > BytesPerCluster) + { + BytesDone += BytesPerCluster; + } + else + { + BytesDone = Length; + } + } + Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, FALSE); + } + while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone); + DPRINT("start %08x, next %08x, count %d\n", + StartCluster, CurrentCluster, ClusterCount); + + Ccb->LastCluster = StartCluster + (ClusterCount - 1); + Ccb->LastOffset = ReadOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster; + + // Fire up the read command + Status = VfatReadDisk (DeviceExt->StorageDevice, &StartOffset, BytesDone, Buffer); + + if (NT_SUCCESS(Status)) + { + *LengthRead += BytesDone; + Buffer += BytesDone; + Length -= BytesDone; + ReadOffset.u.LowPart += BytesDone; + } + } + return Status; +} + +NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, + PVOID Buffer, + ULONG Length, + LARGE_INTEGER WriteOffset) +{ + PDEVICE_EXTENSION DeviceExt; + PVFATFCB Fcb; + PVFATCCB Ccb; + ULONG Count; + ULONG FirstCluster; + ULONG CurrentCluster; + ULONG BytesDone; + ULONG StartCluster; + ULONG ClusterCount; + NTSTATUS Status; + BOOLEAN First = TRUE; + ULONG BytesPerSector; + ULONG BytesPerCluster; + LARGE_INTEGER StartOffset; + + /* PRECONDITION */ + assert (IrpContext); + DeviceExt = IrpContext->DeviceExt; + assert (DeviceExt); + assert (DeviceExt->FatInfo.BytesPerCluster); + assert (IrpContext->FileObject); + assert (IrpContext->FileObject->FsContext2 != NULL); + + Ccb = (PVFATCCB)IrpContext->FileObject->FsContext2; + Fcb = Ccb->pFcb; + BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster; + BytesPerSector = DeviceExt->FatInfo.BytesPerSector; + + DPRINT("VfatWriteFileData(DeviceExt %x, FileObject %x, Buffer %x, " + "Length %d, WriteOffset 0x%I64x), '%S'\n", DeviceExt, + IrpContext->FileObject, Buffer, Length, WriteOffset, + Fcb->PathName); + + assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart); + assert(WriteOffset.u.LowPart % BytesPerSector == 0); + assert(Length % BytesPerSector == 0) + + // Is this a write of the volume ? + if (Fcb->Flags & FCB_IS_VOLUME) + { + Status = VfatWriteDisk(DeviceExt->StorageDevice, &WriteOffset, Length, Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Volume writing failed, Status %x\n", Status); + } + return Status; + } + + // Is this a write to the FAT ? + if (Fcb->Flags & FCB_IS_FAT) + { + WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector; + for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++) + { + Status = VfatWriteDisk(DeviceExt->StorageDevice, &WriteOffset, Length, Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("FAT writing failed, Status %x\n", Status); + } + WriteOffset.u.LowPart += Fcb->RFCB.FileSize.u.LowPart; + } + return Status; + } + + /* + * Find the first cluster + */ + FirstCluster = CurrentCluster = + vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry); + + if (FirstCluster == 1) + { + assert(WriteOffset.u.LowPart + Length <= DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector); + // Directory of FAT12/16 needs a special handling + WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector; + // Fire up the write command + Status = VfatWriteDisk (DeviceExt->StorageDevice, &WriteOffset, Length, Buffer); + return Status; + } + + /* + * Find the cluster to start the write from + */ + if (Ccb->LastCluster > 0 && WriteOffset.u.LowPart > Ccb->LastOffset) + { + CurrentCluster = Ccb->LastCluster; + } + + Status = OffsetToCluster(DeviceExt, Fcb, FirstCluster, + ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster), + &CurrentCluster, FALSE); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Ccb->LastCluster = CurrentCluster; + Ccb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster); + + while (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status)) + { + StartCluster = CurrentCluster; + StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector; + BytesDone = 0; + ClusterCount = 0; + + do + { + ClusterCount++; + if (First) + { + BytesDone = min (Length, BytesPerCluster - (WriteOffset.u.LowPart % BytesPerCluster)); + StartOffset.QuadPart += WriteOffset.u.LowPart % BytesPerCluster; + First = FALSE; + } + else + { + if (Length - BytesDone > BytesPerCluster) + { + BytesDone += BytesPerCluster; + } + else + { + BytesDone = Length; + } + } + Status = NextCluster(DeviceExt, Fcb, FirstCluster, &CurrentCluster, FALSE); + } + while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone); + DPRINT("start %08x, next %08x, count %d\n", + StartCluster, CurrentCluster, ClusterCount); + + Ccb->LastCluster = StartCluster + (ClusterCount - 1); + Ccb->LastOffset = WriteOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster; + + // Fire up the write command + Status = VfatWriteDisk (DeviceExt->StorageDevice, &StartOffset, BytesDone, Buffer); + if (NT_SUCCESS(Status)) + { + Buffer += BytesDone; + Length -= BytesDone; + WriteOffset.u.LowPart += BytesDone; + } + } + return Status; +} + +NTSTATUS +VfatRead(PVFAT_IRP_CONTEXT IrpContext) +{ + NTSTATUS Status; + PVFATFCB Fcb; + PVFATCCB Ccb; + ULONG Length; + ULONG ReturnedLength = 0; + PERESOURCE Resource = NULL; + LARGE_INTEGER ByteOffset; + PVOID Buffer; + PDEVICE_OBJECT DeviceToVerify; + ULONG BytesPerSector; + + assert(IrpContext); + + DPRINT("VfatRead(IrpContext %x)\n", IrpContext); + + assert(IrpContext->DeviceObject); + + // This request is not allowed on the main device object + if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) + { + DPRINT("VfatRead is called with the main device object.\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + assert(IrpContext->DeviceExt); + assert(IrpContext->FileObject); + Ccb = (PVFATCCB) IrpContext->FileObject->FsContext2; + assert(Ccb); + Fcb = Ccb->pFcb; + assert(Fcb); + + DPRINT("<%S>\n", Fcb->PathName); + + ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset; + Length = IrpContext->Stack->Parameters.Read.Length; + BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector; + + /* fail if file is a directory and no paged read */ + if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO)) + { + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + + + DPRINT("'%S', Offset: %d, Length %d\n", Fcb->PathName, ByteOffset.u.LowPart, Length); + + if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME)) + { + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart) + { + IrpContext->Irp->IoStatus.Information = 0; + Status = STATUS_END_OF_FILE; + goto ByeBye; + } + if (IrpContext->Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME)) + { + if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0) + { + DPRINT("%d %d\n", ByteOffset.u.LowPart, Length); + // non chached read must be sector aligned + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + } + if (Length == 0) + { + IrpContext->Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + goto ByeBye; + } + + if (Fcb->Flags & FCB_IS_VOLUME) + { + Resource = &IrpContext->DeviceExt->DirResource; + } + else if (IrpContext->Irp->Flags & IRP_PAGING_IO) + { + Resource = &Fcb->PagingIoResource; + } + else + { + Resource = &Fcb->MainResource; + } + if (!ExAcquireResourceSharedLite(Resource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + Resource = NULL; + Status = STATUS_PENDING; + goto ByeBye; + } + if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) && + !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME))) + { + // cached read + CHECKPOINT; + Status = STATUS_SUCCESS; + if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart) + { + Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart; + Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS; + } + + Buffer = VfatGetUserBuffer(IrpContext->Irp); + if (!Buffer) + { + Status = STATUS_INVALID_USER_BUFFER; + goto ByeBye; + } + + CHECKPOINT; + if (IrpContext->FileObject->PrivateCacheMap == NULL) + { + ULONG CacheSize; + CacheSize = IrpContext->DeviceExt->FatInfo.BytesPerCluster; + if (CacheSize < PAGE_SIZE) + { + CacheSize = PAGE_SIZE; + } + CcRosInitializeFileCache(IrpContext->FileObject, &Fcb->RFCB.Bcb, CacheSize); + } + if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length, + IrpContext->Flags & IRPCONTEXT_CANWAIT, Buffer, + &IrpContext->Irp->IoStatus)) + { + Status = STATUS_PENDING; + goto ByeBye; + } + CHECKPOINT; + if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status)) + { + Status = IrpContext->Irp->IoStatus.Status; + } + } + else + { + // non cached read + CHECKPOINT; + if (ByteOffset.QuadPart + Length > ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector)) + { + Length = ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart; + } + + Buffer = VfatGetUserBuffer(IrpContext->Irp); + if (!Buffer) + { + Status = STATUS_INVALID_USER_BUFFER; + goto ByeBye; + } + + Status = VfatReadFileData(IrpContext, Buffer, Length, ByteOffset, &ReturnedLength); +/* + if (Status == STATUS_VERIFY_REQUIRED) + { + DPRINT("VfatReadFile returned STATUS_VERIFY_REQUIRED\n"); + DeviceToVerify = IoGetDeviceToVerify(KeGetCurrentThread()); + IoSetDeviceToVerify(KeGetCurrentThread(), NULL); + Status = IoVerifyVolume (DeviceToVerify, FALSE); + + if (NT_SUCCESS(Status)) + { + Status = VfatReadFileData(IrpContext, Buffer, Length, + ByteOffset.u.LowPart, &ReturnedLength); + } + } +*/ + if (NT_SUCCESS(Status)) + { + IrpContext->Irp->IoStatus.Information = ReturnedLength; + } + } + +ByeBye: + if (Resource) + { + ExReleaseResourceLite(Resource); + } + + if (Status == STATUS_PENDING) + { + Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess); + if (NT_SUCCESS(Status)) + { + Status = VfatQueueRequest(IrpContext); + } + else + { + IrpContext->Irp->IoStatus.Status = Status; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + } + } + else + { + IrpContext->Irp->IoStatus.Status = Status; + if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO && + !(IrpContext->Irp->Flags & IRP_PAGING_IO) && + (NT_SUCCESS(Status) || Status==STATUS_END_OF_FILE)) + { + IrpContext->FileObject->CurrentByteOffset.QuadPart = + ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information; + } + + IoCompleteRequest(IrpContext->Irp, + NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + } + DPRINT("%x\n", Status); + return Status; +} + +NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext) +{ + PVFATCCB Ccb; + PVFATFCB Fcb; + PERESOURCE Resource = NULL; + LARGE_INTEGER ByteOffset; + LARGE_INTEGER OldFileSize; + NTSTATUS Status = STATUS_SUCCESS; + ULONG Length; + ULONG OldAllocationSize; + PVOID Buffer; + ULONG BytesPerSector; + + assert (IrpContext); + + DPRINT("VfatWrite(IrpContext %x)\n", IrpContext); + + assert(IrpContext->DeviceObject); + + // This request is not allowed on the main device object + if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) + { + DPRINT("VfatWrite is called with the main device object.\n"); + Status = STATUS_INVALID_DEVICE_REQUEST; + goto ByeBye; + } + + assert(IrpContext->DeviceExt); + assert(IrpContext->FileObject); + Ccb = (PVFATCCB) IrpContext->FileObject->FsContext2; + assert(Ccb); + Fcb = Ccb->pFcb; + assert(Fcb); + + DPRINT("<%S>\n", Fcb->PathName); + + /* fail if file is a directory and no paged read */ + if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO)) + { + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + + ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset; + Length = IrpContext->Stack->Parameters.Write.Length; + BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector; + + if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME)) + { + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + + if (Fcb->Flags & (FCB_IS_FAT | FCB_IS_VOLUME) || + 1 == vfatDirEntryGetFirstCluster (IrpContext->DeviceExt, &Fcb->entry)) + { + if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart) + { + // we can't extend the FAT, the volume or the root on FAT12/FAT16 + Status = STATUS_END_OF_FILE; + goto ByeBye; + } + } + + if (IrpContext->Irp->Flags & (IRP_PAGING_IO|IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME)) + { + if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0) + { + // non chached write must be sector aligned + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + } + + if (Length == 0) + { + IrpContext->Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + goto ByeBye; + } + + if (IrpContext->Irp->Flags & IRP_PAGING_IO) + { + if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart) + { + Status = STATUS_INVALID_PARAMETER; + goto ByeBye; + } + if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector)) + { + Length = ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart; + } + } + + if (Fcb->Flags & FCB_IS_VOLUME) + { + Resource = &IrpContext->DeviceExt->DirResource; + } + else if (IrpContext->Irp->Flags & IRP_PAGING_IO) + { + Resource = &Fcb->PagingIoResource; + } + else + { + Resource = &Fcb->MainResource; + } + + if (Fcb->Flags & FCB_IS_PAGE_FILE) + { + if (!ExAcquireResourceSharedLite(Resource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + Resource = NULL; + Status = STATUS_PENDING; + goto ByeBye; + } + } + else + { + if (!ExAcquireResourceExclusiveLite(Resource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + Resource = NULL; + Status = STATUS_PENDING; + goto ByeBye; + } + } + + if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT) && !(Fcb->Flags & FCB_IS_VOLUME)) + { + if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart) + { + Status = STATUS_PENDING; + goto ByeBye; + } + } + + OldFileSize = Fcb->RFCB.FileSize; + OldAllocationSize = Fcb->RFCB.AllocationSize.u.LowPart; + + if (!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)) && + !(IrpContext->Irp->Flags & IRP_PAGING_IO) && + ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart) + { + LARGE_INTEGER AllocationSize; + AllocationSize.QuadPart = ByteOffset.u.LowPart + Length; + Status = VfatSetAllocationSizeInformation(IrpContext->FileObject, Fcb, + IrpContext->DeviceExt, &AllocationSize); + if (!NT_SUCCESS (Status)) + { + CHECKPOINT; + goto ByeBye; + } + } + + if (ByteOffset.QuadPart > OldFileSize.QuadPart) + { + CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE); + } + + if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) && + !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME))) + { + // cached write + CHECKPOINT; + + Buffer = VfatGetUserBuffer(IrpContext->Irp); + if (!Buffer) + { + Status = STATUS_INVALID_USER_BUFFER; + goto ByeBye; + } + CHECKPOINT; + if (IrpContext->FileObject->PrivateCacheMap == NULL) + { + ULONG CacheSize; + CacheSize = IrpContext->DeviceExt->FatInfo.BytesPerCluster; + if (CacheSize < PAGE_SIZE) + { + CacheSize = PAGE_SIZE; + } + CcRosInitializeFileCache(IrpContext->FileObject, &Fcb->RFCB.Bcb, CacheSize); + } + if (CcCopyWrite(IrpContext->FileObject, &ByteOffset, Length, + 1 /*IrpContext->Flags & IRPCONTEXT_CANWAIT*/, Buffer)) + { + IrpContext->Irp->IoStatus.Information = Length; + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_UNSUCCESSFUL; + } + CHECKPOINT; + } + else + { + // non cached write + CHECKPOINT; + + Buffer = VfatGetUserBuffer(IrpContext->Irp); + if (!Buffer) + { + Status = STATUS_INVALID_USER_BUFFER; + goto ByeBye; + } + + Status = VfatWriteFileData(IrpContext, Buffer, Length, ByteOffset); + if (NT_SUCCESS(Status)) + { + IrpContext->Irp->IoStatus.Information = Length; + } + } + + if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) && + !(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME))) + { + if(!(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)) + { + LARGE_INTEGER SystemTime, LocalTime; + // set dates and times + KeQuerySystemTime (&SystemTime); + ExSystemTimeToLocalTime (&SystemTime, &LocalTime); + FsdFileTimeToDosDateTime ((TIME*)&LocalTime, &Fcb->entry.UpdateDate, + &Fcb->entry.UpdateTime); + Fcb->entry.AccessDate = Fcb->entry.UpdateDate; + // update dates/times and length + if (OldAllocationSize != Fcb->RFCB.AllocationSize.u.LowPart) + { + VfatUpdateEntry (IrpContext->DeviceExt, IrpContext->FileObject); + Fcb->Flags &= ~FCB_UPDATE_DIRENTRY; + } + else + Fcb->Flags |= FCB_UPDATE_DIRENTRY; + } + } + +ByeBye: + if (Resource) + { + ExReleaseResourceLite(Resource); + } + + if (Status == STATUS_PENDING) + { + Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess); + if (NT_SUCCESS(Status)) + { + Status = VfatQueueRequest(IrpContext); + } + else + { + IrpContext->Irp->IoStatus.Status = Status; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + } + } + else + { + IrpContext->Irp->IoStatus.Status = Status; + if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO && + !(IrpContext->Irp->Flags & IRP_PAGING_IO) && NT_SUCCESS(Status)) + { + IrpContext->FileObject->CurrentByteOffset.QuadPart = + ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information; + } + + IoCompleteRequest(IrpContext->Irp, + NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + } + DPRINT("%x\n", Status); + return Status; +} + + diff --git a/drivers/fs/vfat/shutdown.c b/drivers/fs/vfat/shutdown.c new file mode 100644 index 0000000..c4be53e --- /dev/null +++ b/drivers/fs/vfat/shutdown.c @@ -0,0 +1,56 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/shutdown.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + NTSTATUS Status; + + DPRINT("VfatShutdown(DeviceObject %x, Irp %x)\n",DeviceObject, Irp); + +#if 0 + /* FIXME: block new mount requests */ + + + /* FIXME: Traverse list of logical volumes. For each volume: */ + { + /* FIXME: acquire vcb resource exclusively */ + + /* FIXME: Flush logical volume */ + + /* FIXME: send IRP_MJ_SHUTDOWN to each volume */ + + /* FIXME: wait for completion of IRP_MJ_SHUTDOWN */ + + /* FIXME: release vcb resource */ + } + +#endif + + Status = STATUS_SUCCESS; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(Status); +} + +/* EOF */ diff --git a/drivers/fs/vfat/string.c b/drivers/fs/vfat/string.c new file mode 100644 index 0000000..9419fdf --- /dev/null +++ b/drivers/fs/vfat/string.c @@ -0,0 +1,192 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/string.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +void vfat_initstr(wchar_t *wstr, ULONG wsize) +/* + * FUNCTION: Initialize a string for use with a long file name + */ +{ + int i; + wchar_t nc=0; + for(i=0; i + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#define ROUND_DOWN(N, S) ((N) - ((N) % (S))) + +struct _BootSector +{ + unsigned char magic0, res0, magic1; + unsigned char OEMName[8]; + unsigned short BytesPerSector; + unsigned char SectorsPerCluster; + unsigned short ReservedSectors; + unsigned char FATCount; + unsigned short RootEntries, Sectors; + unsigned char Media; + unsigned short FATSectors, SectorsPerTrack, Heads; + unsigned long HiddenSectors, SectorsHuge; + unsigned char Drive, Res1, Sig; + unsigned long VolumeID; + unsigned char VolumeLabel[11], SysType[8]; + unsigned char Res2[446]; + unsigned long Signatur1; +} __attribute__((packed)); + +struct _BootSector32 +{ + unsigned char magic0, res0, magic1; // 0 + unsigned char OEMName[8]; // 3 + unsigned short BytesPerSector; // 11 + unsigned char SectorsPerCluster; // 13 + unsigned short ReservedSectors; // 14 + unsigned char FATCount; // 16 + unsigned short RootEntries, Sectors; // 17 + unsigned char Media; // 21 + unsigned short FATSectors, SectorsPerTrack, Heads; // 22 + unsigned long HiddenSectors, SectorsHuge; // 28 + unsigned long FATSectors32; // 36 + unsigned short ExtFlag; // 40 + unsigned short FSVersion; // 42 + unsigned long RootCluster; // 44 + unsigned short FSInfoSector; // 48 + unsigned long BootBackup; // 50 + unsigned char Res3[10]; // 54 + unsigned char Drive; // 64 + unsigned char Res4; // 65 + unsigned char ExtBootSignature; // 66 + unsigned long VolumeID; // 67 + unsigned char VolumeLabel[11], SysType[8]; // 71 + unsigned char Res2[418]; // 90 + unsigned long Signature1; // 508 +} __attribute__((packed)); + +struct _BootBackupSector +{ + unsigned long ExtBootSignature2; // 0 + unsigned char Res6[480]; // 4 + unsigned long FSINFOSignature; // 484 + unsigned long FreeCluster; // 488 + unsigned long NextCluster; // 492 + unsigned char Res7[12]; // 496 + unsigned long Signatur2; // 508 +} __attribute__((packed)); + +typedef struct _BootSector BootSector; + +struct _FATDirEntry +{ + unsigned char Filename[8], Ext[3], Attrib, Res[2]; + unsigned short CreationTime,CreationDate,AccessDate; + unsigned short FirstClusterHigh; // higher + unsigned short UpdateTime; //time create/update + unsigned short UpdateDate; //date create/update + unsigned short FirstCluster; + unsigned long FileSize; +} __attribute__((packed)); + +typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY; + +struct _slot +{ + unsigned char id; // sequence number for slot + WCHAR name0_4[5]; // first 5 characters in name + unsigned char attr; // attribute byte + unsigned char reserved; // always 0 + unsigned char alias_checksum; // checksum for 8.3 alias + WCHAR name5_10[6]; // 6 more characters in name + unsigned char start[2]; // starting cluster number + WCHAR name11_12[2]; // last 2 characters in name +} __attribute__((packed)); + + +typedef struct _slot slot; + +#define BLOCKSIZE 512 + +#define FAT16 (1) +#define FAT12 (2) +#define FAT32 (3) + +#define VCB_VOLUME_LOCKED 0x0001 +#define VCB_DISMOUNT_PENDING 0x0002 + +typedef struct +{ + ULONG VolumeID; + ULONG FATStart; + ULONG FATCount; + ULONG FATSectors; + ULONG rootDirectorySectors; + ULONG rootStart; + ULONG dataStart; + ULONG RootCluster; + ULONG SectorsPerCluster; + ULONG BytesPerSector; + ULONG BytesPerCluster; + ULONG NumberOfClusters; + ULONG FatType; + ULONG Sectors; +} FATINFO, *PFATINFO; + +struct _VFATFCB; + +typedef struct +{ + ERESOURCE DirResource; + ERESOURCE FatResource; + + KSPIN_LOCK FcbListLock; + LIST_ENTRY FcbListHead; + + PDEVICE_OBJECT StorageDevice; + PFILE_OBJECT FATFileObject; + FATINFO FatInfo; + ULONG LastAvailableCluster; + ULONG AvailableClusters; + BOOLEAN AvailableClustersValid; + ULONG Flags; + struct _VFATFCB * VolumeFcb; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB; + +typedef struct +{ + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; +} VFAT_GLOBAL_DATA, *PVFAT_GLOBAL_DATA; + +extern PVFAT_GLOBAL_DATA VfatGlobalData; + +#define FCB_CACHE_INITIALIZED 0x0001 +#define FCB_DELETE_PENDING 0x0002 +#define FCB_IS_FAT 0x0004 +#define FCB_IS_PAGE_FILE 0x0008 +#define FCB_IS_VOLUME 0x0010 +#define FCB_UPDATE_DIRENTRY 0x0020 + +typedef struct _VFATFCB +{ + REACTOS_COMMON_FCB_HEADER RFCB; + SECTION_OBJECT_POINTERS SectionObjectPointers; + FATDirEntry entry; + /* point on filename (250 chars max) in PathName */ + WCHAR *ObjectName; + /* path+filename 260 max */ + WCHAR PathName[MAX_PATH]; + LONG RefCount; + PDEVICE_EXTENSION pDevExt; + LIST_ENTRY FcbListEntry; + struct _VFATFCB* parentFcb; + ULONG Flags; + PFILE_OBJECT FileObject; + ULONG dirIndex; + ERESOURCE PagingIoResource; + ERESOURCE MainResource; + ULONG TimerCount; + SHARE_ACCESS FCBShareAccess; + + /* Structure members used only for paging files. */ + ULONG FatChainSize; + PULONG FatChain; +} VFATFCB, *PVFATFCB; + +typedef struct _VFATCCB +{ + VFATFCB * pFcb; + LIST_ENTRY NextCCB; + PFILE_OBJECT PtrFileObject; + LARGE_INTEGER CurrentByteOffset; + /* for DirectoryControl */ + ULONG Entry; + /* for DirectoryControl */ + PWCHAR DirectorySearchPattern; + ULONG LastCluster; + ULONG LastOffset; + +} VFATCCB, *PVFATCCB; + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +#define TAG_CCB TAG('V', 'C', 'C', 'B') + +#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry)) + +typedef struct __DOSTIME +{ + WORD Second:5; + WORD Minute:6; + WORD Hour:5; +} +DOSTIME, *PDOSTIME; + +typedef struct __DOSDATE +{ + WORD Day:5; + WORD Month:4; + WORD Year:5; +} +DOSDATE, *PDOSDATE; + +#define IRPCONTEXT_CANWAIT 0x0001 + +typedef struct +{ + PIRP Irp; + PDEVICE_OBJECT DeviceObject; + PDEVICE_EXTENSION DeviceExt; + ULONG Flags; + WORK_QUEUE_ITEM WorkQueueItem; + PIO_STACK_LOCATION Stack; + UCHAR MajorFunction; + UCHAR MinorFunction; + PFILE_OBJECT FileObject; +} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; + +/* ------------------------------------------------------ shutdown.c */ + +NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* -------------------------------------------------------- volume.c */ + +NTSTATUS VfatQueryVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetVolumeInformation (PVFAT_IRP_CONTEXT IrpContext); + +/* ------------------------------------------------------ blockdev.c */ + +NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject, + IN PLARGE_INTEGER ReadOffset, + IN ULONG ReadLength, + IN PUCHAR Buffer); + +NTSTATUS VfatWriteDisk(IN PDEVICE_OBJECT pDeviceObject, + IN PLARGE_INTEGER WriteOffset, + IN ULONG WriteLength, + IN PUCHAR Buffer); + +NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, + IN ULONG CtlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + IN OUT PVOID OutputBuffer, + IN OUT PULONG pOutputBufferSize); + +/* ----------------------------------------------------------- dir.c */ + +NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT); + +BOOL FsdDosDateTimeToFileTime (WORD wDosDate, + WORD wDosTime, + TIME *FileTime); + +BOOL FsdFileTimeToDosDateTime (TIME *FileTime, + WORD *pwDosDate, + WORD *pwDosTime); + +/* -------------------------------------------------------- create.c */ + +NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PWSTR FileName); + +NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + PVFATFCB Parent, + PWSTR FileToFind, + PULONG pDirIndex, + PULONG pDirIndex2); + +VOID vfat8Dot3ToString (PCHAR pBasename, + PCHAR pExtension, + PWSTR pName); + +NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, + PVPB Vpb); + +BOOLEAN IsDeletedEntry (PVOID Block, + ULONG Offset); + +BOOLEAN IsLastEntry (PVOID Block, + ULONG Offset); + +/* --------------------------------------------------------- close.c */ + +NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatCloseFile(PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject); + +/* ------------------------------------------------------- cleanup.c */ + +NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- fsctl.c */ + +NTSTATUS VfatFileSystemControl (PVFAT_IRP_CONTEXT IrpContext); + +/* --------------------------------------------------------- finfo.c */ + +NTSTATUS VfatQueryInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatSetInformation (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS +VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject, + PVFATFCB Fcb, + PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER AllocationSize); + +/* --------------------------------------------------------- iface.c */ + +NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath); + +/* --------------------------------------------------------- dirwr.c */ + +NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT pFileObject, + ULONG RequestedOptions,UCHAR ReqAttr); + +NTSTATUS VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT pFileObject); + +NTSTATUS delEntry(PDEVICE_EXTENSION, + PFILE_OBJECT); + +/* -------------------------------------------------------- string.c */ + +VOID vfat_initstr (wchar_t *wstr, + ULONG wsize); + +wchar_t* vfat_wcsncat (wchar_t * dest, + const wchar_t * src, + size_t wstart, + size_t wcount); + +wchar_t* vfat_wcsncpy (wchar_t * dest, + const wchar_t *src, + size_t wcount); + +wchar_t* vfat_movstr (wchar_t *src, + ULONG dpos, + ULONG spos, + ULONG len); + +BOOLEAN wstrcmpi (PWSTR s1, + PWSTR s2); + +BOOLEAN wstrcmpjoki (PWSTR s1, + PWSTR s2); + +PWCHAR vfatGetNextPathElement (PWCHAR pFileName); + +VOID vfatWSubString (PWCHAR pTarget, + const PWCHAR pSource, + size_t pLength); + +BOOL vfatIsFileNameValid (PWCHAR pFileName); + +/* ----------------------------------------------------------- fat.c */ + +NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + ULONG FirstCluster, + ULONG FileOffset, + PULONG Cluster, + BOOLEAN Extend); + +ULONG ClusterToSector (PDEVICE_EXTENSION DeviceExt, + ULONG Cluster); + +NTSTATUS GetNextCluster (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentCluster, + PULONG NextCluster, + BOOLEAN Extend); + +NTSTATUS GetNextSector (PDEVICE_EXTENSION DeviceExt, + ULONG CurrentSector, + PULONG NextSector, + BOOLEAN Extend); + +NTSTATUS CountAvailableClusters (PDEVICE_EXTENSION DeviceExt, + PLARGE_INTEGER Clusters); + +/* ------------------------------------------------------ direntry.c */ + +ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, + PFAT_DIR_ENTRY pDirEntry); + +BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry); + +BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry); + +BOOL vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry); + +VOID vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry, + PWSTR pEntryName); + +NTSTATUS vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt, + PVFATFCB pDirectoryFCB, + ULONG * pDirectoryIndex, + PWSTR pLongFileName, + PFAT_DIR_ENTRY pDirEntry); + +/* ----------------------------------------------------------- fcb.c */ + +PVFATFCB vfatNewFCB (PWCHAR pFileName); + +VOID vfatDestroyFCB (PVFATFCB pFCB); + +VOID vfatGrabFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatReleaseFCB (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB, + PVFATFCB pFCB); + +PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt, + PWSTR pFileName); + +PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB); + +PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB); + +BOOL vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, + PVFATFCB FCB); + +NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb, + PVFATFCB fcb, + PFILE_OBJECT fileObject); + +NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB, + PVFATFCB parentFCB, + PWSTR elementName, + PVFATFCB * fileFCB); + +NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB, + PVFATFCB *pParentFCB, + PVFATFCB *pFCB, + const PWSTR pFileName); + +NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb, + PVFATFCB directoryFCB, + PWSTR longName, + PFAT_DIR_ENTRY dirEntry, + ULONG dirIndex, + PVFATFCB * fileFCB); + +/* ------------------------------------------------------------ rw.c */ + +NTSTATUS VfatRead (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS VfatWriteFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + ULONG WriteOffset, + BOOLEAN NoCache, + BOOLEAN PageIo); + + +NTSTATUS VfatReadFile (PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, ULONG Length, + ULONG ReadOffset, + PULONG LengthRead, + ULONG NoCache); + +NTSTATUS NextCluster(PDEVICE_EXTENSION DeviceExt, + PVFATFCB Fcb, + ULONG FirstCluster, + PULONG CurrentCluster, + BOOLEAN Extend); + +/* ----------------------------------------------------------- misc.c */ + +NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext); + +PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +VOID VfatFreeIrpContext(PVFAT_IRP_CONTEXT IrpContext); + +NTSTATUS STDCALL VfatBuildRequest (PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +PVOID VfatGetUserBuffer(IN PIRP); + +NTSTATUS VfatLockUserBuffer(IN PIRP, IN ULONG, + IN LOCK_OPERATION); + +NTSTATUS +VfatSetExtendedAttributes(PFILE_OBJECT FileObject, + PVOID Ea, + ULONG EaLength); +/* EOF */ diff --git a/drivers/fs/vfat/vfat005.1st b/drivers/fs/vfat/vfat005.1st new file mode 100644 index 0000000..71af436 --- /dev/null +++ b/drivers/fs/vfat/vfat005.1st @@ -0,0 +1,12 @@ +This is VFAT driver release 0.0.5 + +To install : + extract files + delete all object files (*.o) in all subdirectories + (because include file include/ddk/iotypes.h is modified and is used by many files) + recompile reactos + +What's new : + - some bugfixes + - support for IRP_MJ_DIRECTORY_CONTROL + (see reactos/tst/sshell.c for use of ZwQueryDirectoryFile) diff --git a/drivers/fs/vfat/vfat_fr.txt b/drivers/fs/vfat/vfat_fr.txt new file mode 100644 index 0000000..af4e0ed --- /dev/null +++ b/drivers/fs/vfat/vfat_fr.txt @@ -0,0 +1,97 @@ +A Faire : + finir FsdDirectoryControl. + tester les écritures. + FsdCreate doit créer le fichier s'il n'existe pas et que le répertoire parent existe, + et que les options d'appel lee demandent. + + +fichiers sources : + +iface.c +dir.c +blockdev.c +vfat.h + + + +fonctions visibles de l'extérieur (appelées par IoCallDriver): + DriverEntry : iface.c + initialisation du driver + rend visibles les fonctions suivantes : + FsdFileSystemControl + répond aux demandes IRP_MJ_FILE_SYSTEM_CONTROL + monte les filesystems qu'il reconnait + appelle FsdHasFileSystem pour voir si le driver reconnait le filesystem. + puis appelle FsdMount. + NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) + répond aux demandes IRP_MJ_CREATE : + appelle FsdOpenFile, qui remplit IoGetCurrentIrpStackLocation(Irp)->FileObject->Fcb + remplit Irp->IoStatus + appelle IoCompleteRequest + FsdClose + répond aux demandes IRP_MJ_CLOSE + appelle FsdCloseFile, qui ne fait rien actuellement. + remplit Irp->IoStatus + appelle IoCompleteRequest + FsdRead + répond aux demandes IRP_MJ_READ + FsdWrite + répond aux demandes IRP_MJ_WRITE + FsdQueryInformation + répond aux demandes IRP_MJ_QUERY_INFORMATION + FsdDirectoryControl + répond aux demandes IRP_MJ_DIRECTORY_CONTROL + + +fonctions strictement internes dans iface.c : + ULONG Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) + ULONG Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) + ULONG Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) + ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) + ULONG FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt) + void FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, + ULONG NewValue) + void WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, + ULONG NewValue) + ULONG GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) + unsigned long ClusterToSector(PDEVICE_EXTENSION DeviceExt, + unsigned long Cluster) + void RtlAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length) + void vfat_initstr(wchar_t *wstr, ULONG wsize) + wchar_t * vfat_wcsncat(wchar_t * dest, const wchar_t * src,size_t wstart, size_t wcount) + wchar_t * vfat_wcsncpy(wchar_t * dest, const wchar_t *src,size_t wcount) + wchar_t * vfat_movstr(wchar_t * dest, const wchar_t *src, ULONG dpos, + ULONG spos, ULONG len) + BOOLEAN IsLastEntry(PVOID Block, ULONG Offset) + BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset) + BOOLEAN GetEntryName(PVOID Block, PULONG _Offset, PWSTR Name, PULONG _jloop, + PDEVICE_EXTENSION DeviceExt, PULONG _StartingSector) + BOOLEAN wstrcmpi(PWSTR s1, PWSTR s2) + BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2) + NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PFCB Fcb, + PFCB Parent, PWSTR FileToFind) + parcourt le répertoire décrit par Parent pour trouver un fichier dans le filesystem + décrit par DeviceExt.Si Parent==NULL : part de la racine du filesystem. + remplit Fcb si trouve elle le fichier, et renvoie STATUS_SUCCESS. + renvoie STATUS_UNSUCCESSFUL sinon. + NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject) + ne fait rien, renvoie STATUS_SUCCESS. + NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PWSTR FileName) + parcourt l'arborescence pour trouver le fichier(appelle FindFile à chaque niveau) + si trouvé : FileObject->FsContext = Fcb du fichier, renvoie STATUS_SUCCESS + sinon : renvoie STATUS_UNSUCCESSFULL + BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount) + NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt, + PDEVICE_OBJECT DeviceToMount) + void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster) + void VFATWriteCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster) + NTSTATUS FsdReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PVOID Buffer, ULONG Length, ULONG ReadOffset) + lit Length octets d'un fichier + NTSTATUS FsdWriteFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, + PVOID Buffer, ULONG Length, ULONG WriteOffset) + NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount) + NTSTATUS FsdGetStandardInformation(PFCB FCB, PDEVICE_OBJECT DeviceObject, + PFILE_STANDARD_INFORMATION StandardInfo); + diff --git a/drivers/fs/vfat/vfatfs.def b/drivers/fs/vfat/vfatfs.def new file mode 100644 index 0000000..02fcc1c --- /dev/null +++ b/drivers/fs/vfat/vfatfs.def @@ -0,0 +1 @@ +LIBRARY VFATFS.SYS diff --git a/drivers/fs/vfat/vfatfs.rc b/drivers/fs/vfat/vfatfs.rc new file mode 100644 index 0000000..82830c5 --- /dev/null +++ b/drivers/fs/vfat/vfatfs.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "VFAT IFS Driver\0" + VALUE "FileVersion", "0.0.6\0" + VALUE "InternalName", "vfatfs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "vfatfs.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/fs/vfat/volume.c b/drivers/fs/vfat/volume.c new file mode 100644 index 0000000..d20d4fa --- /dev/null +++ b/drivers/fs/vfat/volume.c @@ -0,0 +1,287 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/fs/vfat/volume.c + * PURPOSE: VFAT Filesystem + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#include "vfat.h" + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, + PULONG BufferLength) +{ + ULONG LabelLength; + + DPRINT("FsdGetFsVolumeInformation()\n"); + DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + + LabelLength = DeviceObject->Vpb->VolumeLabelLength; + + DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))); + DPRINT("LabelLength %lu\n", LabelLength); + DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel); + + if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR))) + return STATUS_BUFFER_OVERFLOW; + + /* valid entries */ + FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber; + FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR); + wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel); + + /* dummy entries */ + FsVolumeInfo->VolumeCreationTime.QuadPart = 0; + FsVolumeInfo->SupportsObjects = FALSE; + + DPRINT("Finished FsdGetFsVolumeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR)); + + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, + PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, + PULONG BufferLength) +{ + ULONG Length = DeviceExt->FatInfo.FatType == FAT32 ? 10 : 6; + + DPRINT("FsdGetFsAttributeInformation()\n"); + DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length)); + + if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length)) + return STATUS_BUFFER_OVERFLOW; + + FsAttributeInfo->FileSystemAttributes = + FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK; + FsAttributeInfo->MaximumComponentNameLength = 255; + FsAttributeInfo->FileSystemNameLength = Length; + if (DeviceExt->FatInfo.FatType == FAT32) + { + memcpy(FsAttributeInfo->FileSystemName, L"FAT32", 10); + } + else + { + memcpy(FsAttributeInfo->FileSystemName, L"FAT", 6); + } + + DPRINT("Finished FsdGetFsAttributeInformation()\n"); + + *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_SIZE_INFORMATION FsSizeInfo, + PULONG BufferLength) +{ + PDEVICE_EXTENSION DeviceExt; + NTSTATUS Status; + + DPRINT("FsdGetFsSizeInformation()\n"); + DPRINT("FsSizeInfo = %p\n", FsSizeInfo); + + if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + DeviceExt = DeviceObject->DeviceExtension; + Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits); + + FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters; + FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster; + FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector; + + DPRINT("Finished FsdGetFsSizeInformation()\n"); + if (NT_SUCCESS(Status)) + *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION); + + return(Status); +} + + +static NTSTATUS +FsdGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, + PULONG BufferLength) +{ + DPRINT("FsdGetFsDeviceInformation()\n"); + DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo); + DPRINT("BufferLength %lu\n", *BufferLength); + DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION)); + + if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION)) + return(STATUS_BUFFER_OVERFLOW); + + FsDeviceInfo->DeviceType = FILE_DEVICE_DISK; + FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */ + + DPRINT("FsdGetFsDeviceInformation() finished.\n"); + + *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION); + DPRINT("BufferLength %lu\n", *BufferLength); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject, + PFILE_FS_LABEL_INFORMATION FsLabelInfo) +{ + DPRINT("FsdSetFsLabelInformation()\n"); + + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Retrieve the specified volume information + */ +{ + FS_INFORMATION_CLASS FsInformationClass; + NTSTATUS RC = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + /* PRECONDITION */ + assert(IrpContext); + + DPRINT("VfatQueryVolumeInformation(IrpContext %x)\n", IrpContext); + + if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return VfatQueueRequest (IrpContext); + } + + /* INITIALIZATION */ + FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass; + BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length; + SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; + + + DPRINT ("FsInformationClass %d\n", FsInformationClass); + DPRINT ("SystemBuffer %x\n", SystemBuffer); + + switch (FsInformationClass) + { + case FileFsVolumeInformation: + RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsAttributeInformation: + RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension, + SystemBuffer, + &BufferLength); + break; + + case FileFsSizeInformation: + RC = FsdGetFsSizeInformation(IrpContext->DeviceObject, + SystemBuffer, + &BufferLength); + break; + + case FileFsDeviceInformation: + RC = FsdGetFsDeviceInformation(SystemBuffer, + &BufferLength); + break; + + default: + RC = STATUS_NOT_SUPPORTED; + } + + ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource); + IrpContext->Irp->IoStatus.Status = RC; + if (NT_SUCCESS(RC)) + IrpContext->Irp->IoStatus.Information = + IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength; + else + IrpContext->Irp->IoStatus.Information = 0; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + + return RC; +} + + +NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext) +/* + * FUNCTION: Set the specified volume information + */ +{ + FS_INFORMATION_CLASS FsInformationClass; + NTSTATUS Status = STATUS_SUCCESS; + PVOID SystemBuffer; + ULONG BufferLength; + + /* PRECONDITION */ + assert(IrpContext); + + DPRINT1("VfatSetVolumeInformation(IrpContext %x)\n", IrpContext); + + if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT)) + { + return VfatQueueRequest (IrpContext); + } + + FsInformationClass = IrpContext->Stack->Parameters.SetVolume.FsInformationClass; + BufferLength = IrpContext->Stack->Parameters.SetVolume.Length; + SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer; + + DPRINT1("FsInformationClass %d\n", FsInformationClass); + DPRINT1("BufferLength %d\n", BufferLength); + DPRINT1("SystemBuffer %x\n", SystemBuffer); + + switch(FsInformationClass) + { + case FileFsLabelInformation: + Status = FsdSetFsLabelInformation(IrpContext->DeviceObject, + SystemBuffer); + break; + + default: + Status = STATUS_NOT_SUPPORTED; + } + + ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource); + IrpContext->Irp->IoStatus.Status = Status; + IrpContext->Irp->IoStatus.Information = 0; + IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT); + VfatFreeIrpContext(IrpContext); + + return(Status); +} + +/* EOF */ diff --git a/drivers/input/include/mouse.h b/drivers/input/include/mouse.h new file mode 100644 index 0000000..99440c0 --- /dev/null +++ b/drivers/input/include/mouse.h @@ -0,0 +1,50 @@ +// Mouse definitions common to both mouse class and port drivers + +#define IO_MOUSE_INCREMENT 6 +#define MOUSE_BUFFER_SIZE 32 + +#define IOCTL_INTERNAL_MOUSE_CONNECT CTL_CODE(FILE_DEVICE_MOUSE, 0x0080, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_INTERNAL_MOUSE_DISCONNECT CTL_CODE(FILE_DEVICE_MOUSE, 0x0100, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_INTERNAL_MOUSE_ENABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0200, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_INTERNAL_MOUSE_DISABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0400, METHOD_NEITHER, FILE_ANY_ACCESS) + +typedef struct _MOUSE_INPUT_DATA { + USHORT UnitId; + USHORT Flags; + union { + ULONG Buttons; + struct { + USHORT ButtonFlags; + USHORT ButtonData; + }; + }; + ULONG RawButtons; + LONG LastX; + LONG LastY; + ULONG ExtraInformation; +} MOUSE_INPUT_DATA, *PMOUSE_INPUT_DATA; + +typedef struct _CLASS_INFORMATION { + PDEVICE_OBJECT DeviceObject; + PVOID CallBack; +} CLASS_INFORMATION, *PCLASS_INFORMATION; + +typedef struct _GDI_INFORMATION { + PVOID CallBack; +} GDI_INFORMATION, *PGDI_INFORMATION; + +typedef +VOID +(*PSERVICE_CALLBACK_ROUTINE) ( + IN PVOID NormalContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2, + IN OUT PVOID SystemArgument3 + ); + +typedef +VOID +(*PGDI_SERVICE_CALLBACK_ROUTINE) ( + IN PVOID SystemArgument1, + IN ULONG SystemArgument2 + ); diff --git a/drivers/input/keyboard/.cvsignore b/drivers/input/keyboard/.cvsignore new file mode 100644 index 0000000..8cf6e69 --- /dev/null +++ b/drivers/input/keyboard/.cvsignore @@ -0,0 +1,2 @@ +keyboard.coff +keyboard.sys.unstripped diff --git a/drivers/input/keyboard/keyboard.c b/drivers/input/keyboard/keyboard.c new file mode 100644 index 0000000..4848bd4 --- /dev/null +++ b/drivers/input/keyboard/keyboard.c @@ -0,0 +1,862 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/dd/keyboard/keyboard.c + * PURPOSE: Keyboard driver + * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) + * Jason Filby (jasonfilby@yahoo.com) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#include +#include + +#define NDEBUG +#include + +#include "keyboard.h" + +/* GLOBALS *******************************************************************/ + +/* + * Driver data + */ + +static KEY_EVENT_RECORD kbdBuffer[KBD_BUFFER_SIZE]; +static int bufHead,bufTail; +static int keysInBuffer; +static int extKey; +static BYTE ledStatus; +static BYTE capsDown,numDown,scrollDown; +static DWORD ctrlKeyState; +static PKINTERRUPT KbdInterrupt; +static KDPC KbdDpc; +static BOOLEAN AlreadyOpened = FALSE; + +/* + * PURPOSE: Current irp being processed + */ +static PIRP CurrentIrp; + +/* + * PURPOSE: Number of keys that have been read into the current irp's buffer + */ +static ULONG KeysRead; +static ULONG KeysRequired; + +/* + * Virtual key codes table + * + * Comments: + * * PrtSc = VK_PRINT + * * Alt+PrtSc (SysRq) = VK_EXECUTE + * * Alt = VK_MENU + */ + +static const WORD vkTable[128]= +{ + /* 00 - 07 */ 0, VK_ESCAPE, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6, + /* 08 - 0F */ VK_7, VK_8, VK_9, VK_0, 189, 187, VK_BACK, VK_TAB, + /* 10 - 17 */ VK_Q, VK_W, VK_E, VK_R, VK_T, VK_Y, VK_U, VK_I, + /* 18 - 1F */ VK_O, VK_P, 219, 221, VK_RETURN, VK_CONTROL, VK_A, VK_S, + /* 20 - 27 */ VK_D, VK_F, VK_G, VK_H, VK_J, VK_K, VK_L, 186, + /* 28 - 2F */ 222, 192, VK_SHIFT, 220, VK_Z, VK_X, VK_C, VK_V, + /* 30 - 37 */ VK_B, VK_N, VK_M, 188, 190, 191, VK_SHIFT, VK_MULTIPLY, + /* 38 - 3F */ VK_MENU, VK_SPACE, VK_CAPITAL, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, + /* 40 - 47 */ VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME, + /* 48 - 4F */ VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_ADD, VK_END, + /* 50 - 57 */ VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE, VK_EXECUTE, 0, 0, VK_F11, + /* 58 - 5F */ VK_F12, 0, 0, 91, 92, 93, 0, 0, + /* 60 - 67 */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 68 - 6F */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 70 - 77 */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 78 - 7F */ 0, 0, 0, 0, 0, 0, 0, VK_PAUSE +}; +static const WORD vkKeypadTable[13]= /* 47 - 53 */ +{ + VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT, + VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD, + VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DECIMAL +}; + + +/* + * ASCII translation tables + */ + +static const BYTE asciiTable1[10]= +{ + ')','!','@','#','$','%','^','&','*','(' +}; +static const BYTE asciiTable2[16]= +{ + '0','1','2','3','4','5','6','7','8','9','*','+',0,'-','.','/' +}; +static const BYTE asciiTable3[37]= +{ + ';','=',',','-','.','/','`', 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '[', '\\', ']', '\'' +}; +static const BYTE asciiTable4[37]= +{ + ':','+','<','_','>','?','~', 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '{', '|', '}', '"' +}; + +VOID STDCALL +KdSystemDebugControl(ULONG Code); + +static LONG DoSystemDebug = -1; +static BOOLEAN InSysRq = FALSE; + +/* FUNCTIONS *****************************************************************/ + +static void KbdWrite(int addr,BYTE data) +/* + * FUNCTION: Write data to keyboard + */ +{ + BYTE status; + + do + { + status=READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT); // Wait until input buffer empty + } while(status & KBD_IBF); + WRITE_PORT_UCHAR((PUCHAR)addr,data); +} + +static int KbdReadData(void) +/* + * FUNCTION: Read data from port 0x60 + */ +{ + int i; + BYTE status,data; + + i=500000; + do + { + status=READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT); + if (!(status & KBD_OBF)) // Check if data available + continue; + data=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT); + if (status & (KBD_GTO | KBD_PERR)) // Check for timeout error + continue; + return data; + } while(--i); + return -1; // Timed out +} + + +/* + * Set keyboard LED's + */ + +static void SetKeyboardLEDs(BYTE status) +{ + KbdWrite(KBD_DATA_PORT,0xED); + if (KbdReadData()!=KBD_ACK) // Error + return; + KbdWrite(KBD_DATA_PORT,status); + KbdReadData(); +} + + +/* + * Process scan code + */ + +static void ProcessScanCode(BYTE scanCode,BOOL isDown) +{ + switch(scanCode) + { + case 0x1D: // Ctrl + if (extKey) + { + if (isDown) + ctrlKeyState|=RIGHT_CTRL_PRESSED; + else + ctrlKeyState&=~RIGHT_CTRL_PRESSED; + } + else + { + if (isDown) + ctrlKeyState|=LEFT_CTRL_PRESSED; + else + ctrlKeyState&=~LEFT_CTRL_PRESSED; + } + break; + case 0x2A: // Left shift + case 0x36: // Right shift + if (isDown) + ctrlKeyState|=SHIFT_PRESSED; + else + ctrlKeyState&=~SHIFT_PRESSED; + break; + case 0x38: // Alt + if (extKey) + { + if (isDown) + ctrlKeyState|=RIGHT_ALT_PRESSED; + else + ctrlKeyState&=~RIGHT_ALT_PRESSED; + } + else + { + if (isDown) + ctrlKeyState|=LEFT_ALT_PRESSED; + else + ctrlKeyState&=~LEFT_ALT_PRESSED; + } + break; + case 0x3A: // CapsLock + if (ctrlKeyState & CTRL_PRESSED) + break; + if (isDown) + { + if (!capsDown) + { + capsDown=1; + if (ctrlKeyState & CAPSLOCK_ON) + { + ledStatus&=~KBD_LED_CAPS; + ctrlKeyState&=~CAPSLOCK_ON; + } + else + { + ledStatus|=KBD_LED_CAPS; + ctrlKeyState|=CAPSLOCK_ON; + } + SetKeyboardLEDs(ledStatus); + } + } + else + { + capsDown=0; + } + break; + case 0x45: // NumLock + if (ctrlKeyState & CTRL_PRESSED) + break; + if (isDown) + { + if (!numDown) + { + numDown=1; + if (ctrlKeyState & NUMLOCK_ON) + { + ledStatus&=~KBD_LED_NUM; + ctrlKeyState&=~NUMLOCK_ON; + } + else + { + ledStatus|=KBD_LED_NUM; + ctrlKeyState|=NUMLOCK_ON; + } + SetKeyboardLEDs(ledStatus); + } + } + else + { + numDown=0; + } + break; + case 0x46: // ScrollLock + if (ctrlKeyState & CTRL_PRESSED) + break; + if (isDown) + { + if (!scrollDown) + { + scrollDown=1; + if (ctrlKeyState & SCROLLLOCK_ON) + { + ledStatus&=~KBD_LED_SCROLL; + ctrlKeyState&=~SCROLLLOCK_ON; + } + else + { + ledStatus|=KBD_LED_SCROLL; + ctrlKeyState|=SCROLLLOCK_ON; + } + SetKeyboardLEDs(ledStatus); + } + } + else + { + scrollDown=0; + } + break; + default: + break; + } +} + + +/* + * Translate virtual key code to ASCII + */ + +static BYTE VirtualToAscii(WORD keyCode,BOOL isDown) +{ + if ((ctrlKeyState & ALT_PRESSED)&&(ctrlKeyState & CTRL_PRESSED)) + return 0; // Ctrl+Alt+char always 0 + if ((!isDown)&&(ctrlKeyState & ALT_PRESSED)) + return 0; // Alt+char is 0 when key is released + + if (ctrlKeyState & CTRL_PRESSED) + { + if ((keyCode>=VK_A)&&(keyCode<=VK_Z)) + return keyCode-VK_A+1; + switch(keyCode) + { + case VK_SPACE: + return ' '; + case VK_BACK: + return 127; + case VK_RETURN: + return '\r'; + case 219: /* [ */ + if (ctrlKeyState & SHIFT_PRESSED) + return 0; + return 27; + case 220: /* \ */ + if (ctrlKeyState & SHIFT_PRESSED) + return 0; + return 28; + case 221: /* ] */ + if (ctrlKeyState & SHIFT_PRESSED) + return 0; + return 29; + default: + return 0; + } + } + + if ((keyCode>=VK_A)&&(keyCode<=VK_Z)) + { + if (ctrlKeyState & CAPSLOCK_ON) + if (ctrlKeyState & SHIFT_PRESSED) + return keyCode-VK_A+'a'; + else + return keyCode-VK_A+'A'; + else + if (ctrlKeyState & SHIFT_PRESSED) + return keyCode-VK_A+'A'; + else + return keyCode-VK_A+'a'; + } + + if ((keyCode>=VK_0)&&(keyCode<=VK_9)) + { + if (ctrlKeyState & SHIFT_PRESSED) + return asciiTable1[keyCode-VK_0]; + else + return keyCode-VK_0+'0'; + } + + if ((keyCode>=VK_NUMPAD0)&&(keyCode<=VK_DIVIDE)) + return asciiTable2[keyCode-VK_NUMPAD0]; + + if ((keyCode>=186)&&(keyCode<=222)) + { + if (ctrlKeyState & SHIFT_PRESSED) + return asciiTable4[keyCode-186]; + else + return asciiTable3[keyCode-186]; + } + + switch(keyCode) + { + case VK_SPACE: + return ' '; + case VK_RETURN: + return '\r'; + case VK_BACK: + return 8; + case VK_TAB: + return 9; + } + return 0; +} + + +/* + * Translate scan code to virtual key code + */ + +static WORD ScanToVirtual(BYTE scanCode) +{ + if ((scanCode>=0x47)&&(scanCode<=0x53)&&(ctrlKeyState & NUMLOCK_ON)&& + (!extKey)&&(!(ctrlKeyState & SHIFT_PRESSED))) + return vkKeypadTable[scanCode-0x47]; + if ((scanCode==0x35)&&(extKey)) // Gray divide + return VK_DIVIDE; + if ((scanCode==0x37)&&(extKey)) // Print screen + return VK_PRINT; + return vkTable[scanCode]; +} + + +/* + * Keyboard IRQ handler + */ + +static VOID STDCALL +KbdDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PIRP Irp = (PIRP)SystemArgument2; + PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1; + + if (SystemArgument1 == NULL && DoSystemDebug != -1) + { + KdSystemDebugControl(DoSystemDebug); + DoSystemDebug = -1; + return; + } + + CHECKPOINT; + DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n", + DeviceObject,Irp); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject,FALSE); +} + +static BOOLEAN STDCALL +KeyboardHandler(PKINTERRUPT Interrupt, + PVOID Context) +{ + BYTE thisKey; + BOOL isDown; + static BYTE lastKey; + CHAR Status; + PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context; + PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; + + CHECKPOINT; + + /* + * Check status + */ + Status = READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT); + if (!(Status & KBD_OBF)) + { + return (FALSE); + } + + // Read scan code + thisKey=READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT); + + // Call hook routine. May change scancode value. + if (deviceExtension->IsrHookCallback) { + BOOLEAN cont = FALSE, ret; + //BUG BUG: rewrite to have valid CurrentScanState!!! + ret = (*deviceExtension->IsrHookCallback)( + deviceObject, + NULL,//&deviceExtension->CurrentInput, + NULL,//&deviceExtension->CurrentOutput, + Status, + &thisKey, //&scanCode, + &cont, + NULL //&deviceExtension->CurrentScanState + ); + + if (!cont) { + return ret; + } + } + + + if ((thisKey==0xE0)||(thisKey==0xE1)) // Extended key + { + extKey=1; // Wait for next byte + lastKey=thisKey; + return FALSE; + } + + isDown=!(thisKey & 0x80); + thisKey&=0x7F; + + // The keyboard maintains its own internal caps lock and num lock + // statuses. In caps lock mode E0 AA precedes make code and + // E0 2A follow break code. In num lock mode, E0 2A precedes + // make code and E0 AA follow break code. We maintain our own caps lock + // and num lock statuses, so we will just ignore these. + // Some keyboards have L-Shift/R-Shift modes instead of caps lock + // mode. If right shift pressed, E0 B6 / E0 36 pairs generated. + if (extKey & ((thisKey==0x2A)||(thisKey==0x36))) + { + extKey=0; + return FALSE; + } + + // Check for PAUSE sequence + if (extKey && (lastKey==0xE1)) + { + if (thisKey==0x1D) + lastKey=0xFF; // Sequence is OK + else + extKey=0; + return FALSE; + } + if (extKey && (lastKey==0xFF)) + { + if (thisKey!=0x45) + { + extKey=0; // Bad sequence + return FALSE; + } + thisKey=0x7F; // Pseudo-code for PAUSE + } + + ProcessScanCode(thisKey,isDown); + +// DbgPrint("Key: %c\n",VirtualToAscii(ScanToVirtual(thisKey),isDown)); +// DbgPrint("Key: %x\n",ScanToVirtual(thisKey)); + if (ScanToVirtual(thisKey) == VK_TAB && isDown) + { + InSysRq = TRUE; + } + else if (ScanToVirtual(thisKey) == VK_TAB && !isDown) + { + InSysRq = FALSE; + } + else if (InSysRq == TRUE && ScanToVirtual(thisKey) >= VK_A && + ScanToVirtual(thisKey) <= VK_Z && isDown) + { + DoSystemDebug = ScanToVirtual(thisKey) - VK_A; + KeInsertQueueDpc(&KbdDpc, NULL, NULL); + return(TRUE); + } + + if (CurrentIrp!=NULL) + { + KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *) + CurrentIrp->AssociatedIrp.SystemBuffer; + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(CurrentIrp); + + CHECKPOINT; + + rec[KeysRead].bKeyDown=isDown; + rec[KeysRead].wRepeatCount=1; + rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey); + rec[KeysRead].wVirtualScanCode=thisKey; + rec[KeysRead].uChar.AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown); + rec[KeysRead].dwControlKeyState=ctrlKeyState; + if (extKey) + { + rec[KeysRead].dwControlKeyState|=ENHANCED_KEY; + } + KeysRead++; + DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead); + if (KeysRead==KeysRequired) + { + PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Context; + KeInsertQueueDpc(&KbdDpc,DeviceObject,CurrentIrp); + CurrentIrp=NULL; + } + CHECKPOINT; + return TRUE; + } + + // Buffer is full ? + if (keysInBuffer==KBD_BUFFER_SIZE) // Buffer is full + { + extKey=0; + return(TRUE); + } + kbdBuffer[bufHead].bKeyDown=isDown; + kbdBuffer[bufHead].wRepeatCount=1; + kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey); + kbdBuffer[bufHead].wVirtualScanCode=thisKey; + kbdBuffer[bufHead].uChar.UnicodeChar=0; + // kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey); + kbdBuffer[bufHead].uChar.AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown); + kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState; + if (extKey) + kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY; + bufHead++; + bufHead&=KBD_WRAP_MASK; // Modulo KBD_BUFFER_SIZE + keysInBuffer++; + extKey=0; + return TRUE; +} + + +// +// Initialize keyboard +// +static void KeyboardConnectInterrupt(PDEVICE_OBJECT DeviceObject) +{ + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + NTSTATUS Status; + + MappedIrq = HalGetInterruptVector(Internal, + 0, + 0, + KEYBOARD_IRQ, + &Dirql, + &Affinity); + Status = IoConnectInterrupt(&KbdInterrupt, + KeyboardHandler, + (PVOID)DeviceObject, + NULL, + MappedIrq, + Dirql, + Dirql, + 0, + FALSE, + Affinity, + FALSE); +} + +VOID +KbdClearInput(VOID) +{ + ULONG i; + CHAR Status; + + for (i = 0; i < 100; i++) + { + Status = READ_PORT_UCHAR((PUCHAR)KBD_CTRL_PORT); + if (!(Status & KBD_OBF)) + { + return; + } + (VOID)READ_PORT_UCHAR((PUCHAR)KBD_DATA_PORT); + } +} + +static int InitializeKeyboard(PDEVICE_OBJECT DeviceObject) +{ + // Initialize variables + bufHead=0; + bufTail=0; + keysInBuffer=0; + ledStatus=0; + capsDown=0; + numDown=0; + scrollDown=0; + ctrlKeyState=0; + extKey=0; + + KbdClearInput(); + KeyboardConnectInterrupt(DeviceObject); + KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL); + return 0; +} + +/* + * Read data from keyboard buffer + */ +BOOLEAN STDCALL +KbdSynchronizeRoutine(PVOID Context) +{ + PIRP Irp = (PIRP)Context; + KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)Irp->AssociatedIrp.SystemBuffer; + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD); + int i; + + DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer); + NrToRead = min(NrToRead,keysInBuffer); + + DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n", + NrToRead,stk->Parameters.Read.Length); + DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD)); + for (i=0;iParameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead) + { + return(TRUE); + } + + KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD); + KeysRead=NrToRead; + CurrentIrp=Irp; + + return(FALSE); +} + +VOID STDCALL KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ +#ifndef NDEBUG + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); +#endif + + DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp); + + if (KeSynchronizeExecution(KbdInterrupt, KbdSynchronizeRoutine, Irp)) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, FALSE); + } + + DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length); + DPRINT("KeysRequired %d\n",KeysRequired); +} + +NTSTATUS KbdInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION stk; + PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard; + PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; + NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; + + Irp->IoStatus.Information = 0; + stk = IoGetCurrentIrpStackLocation(Irp); + + switch (stk->Parameters.DeviceIoControl.IoControlCode) + { + /*-----------------11/29/2001 4:12PM---------------- + * This internal ioctrl belongs in i8042 driver. Should be + * moved to the appropriate driver later. + * --------------------------------------------------*/ + case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: + + if (stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(INTERNAL_I8042_HOOK_KEYBOARD)) + { + DPRINT(("Keyboard IOCTL_INTERNAL_I8042_HOOK_KEYBOARD invalid buffer size\n")); + status = STATUS_INVALID_PARAMETER; + } + else { + // + // Copy the values if they are filled in + // + hookKeyboard = (PINTERNAL_I8042_HOOK_KEYBOARD) + stk->Parameters.DeviceIoControl.Type3InputBuffer; + + DevExt->HookContext = hookKeyboard->Context; + if (hookKeyboard->InitializationRoutine) { + DbgPrint("Keyboard: InitializationHookCallback NOT IMPLEMENTED\n"); + DevExt->InitializationHookCallback = + hookKeyboard->InitializationRoutine; + } + + if (hookKeyboard->IsrRoutine) { + DevExt->IsrHookCallback = hookKeyboard->IsrRoutine; + } + + status = STATUS_SUCCESS; + } + break; + default: + status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; +} + +NTSTATUS STDCALL KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + + DPRINT("DeviceObject %x\n",DeviceObject); + DPRINT("Irp %x\n",Irp); + + DPRINT("IRP_MJ_CREATE %d stk->MajorFunction %d\n", + IRP_MJ_CREATE, stk->MajorFunction); + DPRINT("AlreadyOpened %d\n",AlreadyOpened); + + switch (stk->MajorFunction) + { + case IRP_MJ_CREATE: + if (AlreadyOpened == TRUE) + { + CHECKPOINT; +// Status = STATUS_UNSUCCESSFUL; + Status = STATUS_SUCCESS; + } + else + { + CHECKPOINT; + Status = STATUS_SUCCESS; + AlreadyOpened = TRUE; + } + break; + + case IRP_MJ_CLOSE: + Status = STATUS_SUCCESS; + break; + + case IRP_MJ_READ: + DPRINT("Handling Read request\n"); + DPRINT("Queueing packet\n"); + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject,Irp,NULL,NULL); + return(STATUS_PENDING); + + default: + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + DPRINT("Status %d\n",Status); + return(Status); +} + +NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Module entry point + */ +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Keyboard"); + UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\Keyboard"); + + DPRINT("Keyboard Driver 0.0.4\n"); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch; + DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdInternalDeviceControl; + + DriverObject->DriverStartIo = KbdStartIo; + + IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_KEYBOARD, + 0, + TRUE, + &DeviceObject); + + RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION)); + + DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; + InitializeKeyboard( DeviceObject ); + + IoCreateSymbolicLink(&SymlinkName, &DeviceName); + + return(STATUS_SUCCESS); +} diff --git a/drivers/input/keyboard/keyboard.h b/drivers/input/keyboard/keyboard.h new file mode 100644 index 0000000..18885ce --- /dev/null +++ b/drivers/input/keyboard/keyboard.h @@ -0,0 +1,87 @@ +#ifndef _KEYBOARD_H_ +#define _KEYBOARD_H_ +#include +#include + + +/*----------------------------------------------------- + * DeviceExtension + * --------------------------------------------------*/ +typedef struct _DEVICE_EXTENSION +{ + + PI8042_KEYBOARD_INITIALIZATION_ROUTINE InitializationHookCallback; + PI8042_KEYBOARD_ISR IsrHookCallback; + PVOID HookContext; + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +/* + * Some defines + */ + +#define KEYBOARD_IRQ 1 +#define KBD_BUFFER_SIZE 32 +#define KBD_WRAP_MASK 0x1F + +#define disable() __asm__("cli\n\t") +#define enable() __asm__("sti\n\t") + +#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) +#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED) + + +/* + * Keyboard controller ports + */ + +#define KBD_DATA_PORT 0x60 +#define KBD_CTRL_PORT 0x64 + + +/* + * Controller commands + */ + +#define KBD_READ_MODE 0x20 +#define KBD_WRITE_MODE 0x60 +#define KBD_SELF_TEST 0xAA +#define KBD_LINE_TEST 0xAB +#define KBD_CTRL_ENABLE 0xAE + +/* + * Keyboard commands + */ + +#define KBD_ENABLE 0xF4 +#define KBD_DISABLE 0xF5 +#define KBD_RESET 0xFF + + +/* + * Keyboard responces + */ + +#define KBD_ACK 0xFA +#define KBD_BATCC 0xAA + + +/* + * Controller status register bits + */ + +#define KBD_OBF 0x01 +#define KBD_IBF 0x02 +#define KBD_GTO 0x40 +#define KBD_PERR 0x80 + + +/* + * LED bits + */ + +#define KBD_LED_SCROLL 0x01 +#define KBD_LED_NUM 0x02 +#define KBD_LED_CAPS 0x04 + +#endif // _KEYBOARD_H_ diff --git a/drivers/input/keyboard/keyboard.rc b/drivers/input/keyboard/keyboard.rc new file mode 100644 index 0000000..8095fc3 --- /dev/null +++ b/drivers/input/keyboard/keyboard.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Keyboard Device Driver\0" + VALUE "FileVersion", "0.0.4\0" + VALUE "InternalName", "keyboard\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "keyboard.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/input/keyboard/makefile b/drivers/input/keyboard/makefile new file mode 100644 index 0000000..f56c974 --- /dev/null +++ b/drivers/input/keyboard/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = keyboard + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/input/mouclass/.cvsignore b/drivers/input/mouclass/.cvsignore new file mode 100644 index 0000000..438594d --- /dev/null +++ b/drivers/input/mouclass/.cvsignore @@ -0,0 +1,2 @@ +mouclass.coff +mouclass.sys.unstripped diff --git a/drivers/input/mouclass/makefile b/drivers/input/mouclass/makefile new file mode 100644 index 0000000..6daf0e1 --- /dev/null +++ b/drivers/input/mouclass/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = mouclass + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/input/mouclass/mouclass.c b/drivers/input/mouclass/mouclass.c new file mode 100644 index 0000000..a4e65d0 --- /dev/null +++ b/drivers/input/mouclass/mouclass.c @@ -0,0 +1,286 @@ +/* + + ** Mouse class driver 0.0.1 + ** Written by Jason Filby (jasonfilby@yahoo.com) + ** For ReactOS (www.reactos.com) + + ** The class driver between win32k and the various mouse port drivers + + ** TODO: Change interface to win32k to a callback instead of ReadFile IO + Add support for multiple port devices + +*/ + +#include +#include "../include/mouse.h" +#include "mouclass.h" + +BOOLEAN AlreadyOpened = FALSE; + +BOOLEAN MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA MouseDataStart, + PMOUSE_INPUT_DATA MouseDataEnd, PULONG InputCount) +{ + PDEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension; + PIRP Irp; + ULONG ReadSize; + PIO_STACK_LOCATION Stack; + + // In classical NT, you would take the input data and pipe it through the IO system, for the GDI to read. + // In ReactOS, however, we use a GDI callback for increased mouse responsiveness. The reason we don't + // simply call from the port driver is so that our mouse class driver can support NT mouse port drivers. + +/* if(ClassDeviceExtension->ReadIsPending == TRUE) + { + Irp = ClassDeviceObject->CurrentIrp; + ClassDeviceObject->CurrentIrp = NULL; + Stack = IoGetCurrentIrpStackLocation(Irp); + + ReadSize = sizeof(MOUSE_INPUT_DATA) * (*InputCount); + + // A read request is waiting for input, so go straight to it + RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, (PCHAR)MouseDataStart, ReadSize); + + // Go to next packet and complete this request with STATUS_SUCCESS + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = ReadSize; + Stack->Parameters.Read.Length = ReadSize; + + IoStartNextPacket(ClassDeviceObject, FALSE); + IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); + ClassDeviceExtension->ReadIsPending = FALSE; + } */ + + // If we have data from the port driver and a higher service to send the data to + if((*InputCount>0) && (*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack != NULL)) + { + if(ClassDeviceExtension->InputCount + *InputCount > MOUSE_BUFFER_SIZE) + { + ReadSize = MOUSE_BUFFER_SIZE - ClassDeviceExtension->InputCount; + } else { + ReadSize = *InputCount; + } + + // FIXME: If we exceed the buffer, mouse data gets thrown away.. better solution? + + + // Move the mouse input data from the port data queue to our class data queue + RtlMoveMemory(ClassDeviceExtension->PortData, (PCHAR)MouseDataStart, + sizeof(MOUSE_INPUT_DATA) * ReadSize); + + // Move the pointer and counter up + ClassDeviceExtension->PortData += ReadSize; + ClassDeviceExtension->InputCount += ReadSize; + + // Throw data up to GDI callback + if(*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack != NULL) { + (*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack) + (ClassDeviceExtension->PortData - ReadSize, ReadSize); + } + + ClassDeviceExtension->PortData -= ReadSize; + ClassDeviceExtension->InputCount -= ReadSize; + ClassDeviceExtension->ReadIsPending = FALSE; + } + + return TRUE; +} + +NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject) +{ + PDEVICE_OBJECT PortDeviceObject = NULL; + PFILE_OBJECT FileObject = NULL; + NTSTATUS status; + UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(L"\\Device\\Mouse"); + IO_STATUS_BLOCK ioStatus; + KEVENT event; + PIRP irp; + CLASS_INFORMATION ClassInformation; + PDEVICE_EXTENSION DeviceExtension = ClassDeviceObject->DeviceExtension; + + DeviceExtension->GDIInformation.CallBack = NULL; + + // Get the port driver's DeviceObject + // FIXME: The name might change.. find a way to be more dynamic? + + status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject); + + if(status != STATUS_SUCCESS) + { + DbgPrint("MOUCLASS: Could not connect to mouse port driver\n"); + return status; + } + + DeviceExtension->PortDeviceObject = PortDeviceObject; + DeviceExtension->PortData = ExAllocatePool(NonPagedPool, MOUSE_BUFFER_SIZE * sizeof(MOUSE_INPUT_DATA)); + DeviceExtension->InputCount = 0; + DeviceExtension->ReadIsPending = FALSE; + + // Connect our callback to the port driver + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + ClassInformation.DeviceObject = ClassDeviceObject; + ClassInformation.CallBack = MouseClassCallBack; + + irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT, + PortDeviceObject, &ClassInformation, sizeof(CLASS_INFORMATION), NULL, 0, TRUE, &event, &ioStatus); + + status = IoCallDriver(DeviceExtension->PortDeviceObject, irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); + } else { + ioStatus.Status = status; + } + + return ioStatus.Status; +} + +NTSTATUS STDCALL MouseClassDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + + switch (Stack->MajorFunction) + { + case IRP_MJ_CREATE: + if (AlreadyOpened == TRUE) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_SUCCESS; + AlreadyOpened = TRUE; + } + break; + + case IRP_MJ_CLOSE: + Status = STATUS_SUCCESS; + break; + + case IRP_MJ_READ: + + if (Stack->Parameters.Read.Length == 0) { + Status = STATUS_SUCCESS; + } else { + Status = STATUS_PENDING; + } + break; + + default: + DbgPrint("NOT IMPLEMENTED\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + if (Status==STATUS_PENDING) + { + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, Irp, NULL, NULL); + } else { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + return(Status); +} + +VOID MouseClassStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + ULONG ReadSize; + + if(DeviceExtension->InputCount>0) + { + // FIXME: We should not send too much input data.. depends on the max buffer size of the win32k + ReadSize = DeviceExtension->InputCount * sizeof(MOUSE_INPUT_DATA); + + // Bring the PortData back to base so that it can be copied + DeviceExtension->PortData -= DeviceExtension->InputCount; + DeviceExtension->InputCount = 0; + DeviceExtension->ReadIsPending = FALSE; + + RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, (PCHAR)DeviceExtension->PortData, ReadSize); + + // Go to next packet and complete this request with STATUS_SUCCESS + Irp->IoStatus.Status = STATUS_SUCCESS; + + Irp->IoStatus.Information = ReadSize; + Stack->Parameters.Read.Length = ReadSize; + + IoStartNextPacket(DeviceObject, FALSE); + IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); + } else { + DeviceExtension->ReadIsPending = TRUE; + } +} + +NTSTATUS STDCALL MouseClassInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + // Retrieve GDI's callback + + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + + switch(Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_MOUSE_CONNECT: + + DeviceExtension->GDIInformation = + *((PGDI_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer); + + status = STATUS_SUCCESS; + break; + + case IOCTL_INTERNAL_MOUSE_DISCONNECT: + + DeviceExtension->GDIInformation.CallBack = NULL; + + status = STATUS_SUCCESS; + break; + + default: + status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = status; + if (status == STATUS_PENDING) { + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, Irp, NULL, NULL); + } else { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return status; +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\MouseClass"); + UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\MouseClass"); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassDispatch; +// DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassDispatch; +// DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassDispatch; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MouseClassInternalDeviceControl; // to get GDI callback +// DriverObject->DriverStartIo = MouseClassStartIo; + + IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_MOUSE, + 0, + TRUE, + &DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; + + IoCreateSymbolicLink(&SymlinkName, &DeviceName); + + return ConnectMousePortDriver(DeviceObject); +} diff --git a/drivers/input/mouclass/mouclass.h b/drivers/input/mouclass/mouclass.h new file mode 100644 index 0000000..cf77cb7 --- /dev/null +++ b/drivers/input/mouclass/mouclass.h @@ -0,0 +1,7 @@ +typedef struct _DEVICE_EXTENSION { + BOOLEAN ReadIsPending; + ULONG InputCount; + PMOUSE_INPUT_DATA PortData; + PDEVICE_OBJECT PortDeviceObject; // FIXME: Expand this to handle multiple port drivers (make *PortDeviceObject) + GDI_INFORMATION GDIInformation; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; diff --git a/drivers/input/mouclass/mouclass.rc b/drivers/input/mouclass/mouclass.rc new file mode 100644 index 0000000..e080d18 --- /dev/null +++ b/drivers/input/mouclass/mouclass.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Mouse Class Device Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "mouclass\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "mouclass.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/input/psaux/.cvsignore b/drivers/input/psaux/.cvsignore new file mode 100644 index 0000000..f61f1c9 --- /dev/null +++ b/drivers/input/psaux/.cvsignore @@ -0,0 +1,2 @@ +psaux.coff +psaux.sys.unstripped diff --git a/drivers/input/psaux/controller.c b/drivers/input/psaux/controller.c new file mode 100644 index 0000000..408650e --- /dev/null +++ b/drivers/input/psaux/controller.c @@ -0,0 +1,156 @@ +// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/). +// CHAOS is also under the GNU General Public License. + +#include + +#include "controller.h" +#include "keyboard.h" +#include "mouse.h" + +/* This reads the controller status port, and does the appropriate + action. It requires that we hold the keyboard controller spinlock. */ + +unsigned handle_event(void) +{ + unsigned status = controller_read_status(); + unsigned int work; + + for(work = 0; (work < 10000) && ((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0); work++) + { + unsigned scancode; + + scancode = controller_read_input(); + +#if 0 + /* Ignore error bytes. */ + + if((status &(CONTROLLER_STATUS_GENERAL_TIMEOUT | + CONTROLLER_STATUS_PARITY_ERROR)) == 0) +#endif + { + if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0) + { +// mouse_handle_event(scancode); we just use the mouse handler directly.. + } + else + { +// keyboard_handle_event(scancode); + } + } + + status = controller_read_status(); + + } + + if(work == 10000) + { + DbgPrint("PSAUX: Keyboard controller jammed\n"); + } + + return status; +} + +/* Wait for keyboard controller input buffer to drain. + Quote from PS/2 System Reference Manual: + "Address hex 0060 and address hex 0064 should be written only + when the input-buffer-full bit and output-buffer-full bit in the + Controller Status register are set 0." */ + +void controller_wait(void) +{ + unsigned long timeout; + LARGE_INTEGER Millisecond_Timeout; + + Millisecond_Timeout.QuadPart = 1; + + for(timeout = 0; timeout < CONTROLLER_TIMEOUT; timeout++) + { + // "handle_keyboard_event()" will handle any incoming events + // while we wait -- keypresses or mouse movement + + unsigned char status = handle_event(); + + if((status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0) return; + + // Sleep for one millisecond + KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout); + } + + DbgPrint("PSAUX: Keyboard timed out\n"); +} + +/* Wait for input from the keyboard controller. */ + +int controller_wait_for_input(void) +{ + int timeout; + LARGE_INTEGER Millisecond_Timeout; + + Millisecond_Timeout.QuadPart = 1; + + for(timeout = KEYBOARD_INIT_TIMEOUT; timeout > 0; timeout--) + { + int return_value = controller_read_data(); + + if(return_value >= 0) return return_value; + + // Sleep for one millisecond + KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout); + } + + DbgPrint("PSAUX: Timed out on waiting for input from controller\n"); + return -1; +} + +/* Write a command word to the keyboard controller. */ + +void controller_write_command_word(unsigned data) +{ + controller_wait(); + controller_write_command(data); +} + +/* Write an output word to the keyboard controller. */ + +void controller_write_output_word(unsigned data) +{ + controller_wait(); + controller_write_output(data); +} + +/* Empty the keyboard input buffer. */ + +void keyboard_clear_input(void) +{ + int max_read; + + for(max_read = 0; max_read < 100; max_read++) + { + if(controller_read_data() == KEYBOARD_NO_DATA) + { + break; + } + } +} + +/* Read data from the keyboard controller. */ + +int controller_read_data(void) +{ + int return_value = KEYBOARD_NO_DATA; + unsigned status; + + status = controller_read_status(); + if(status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) + { + unsigned data = controller_read_input(); + + return_value = data; + if(status &(CONTROLLER_STATUS_GENERAL_TIMEOUT | + CONTROLLER_STATUS_PARITY_ERROR)) + { + return_value = KEYBOARD_BAD_DATA; + } + } + return return_value; +} diff --git a/drivers/input/psaux/controller.h b/drivers/input/psaux/controller.h new file mode 100644 index 0000000..7269b25 --- /dev/null +++ b/drivers/input/psaux/controller.h @@ -0,0 +1,139 @@ +// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/). +// CHAOS is also under the GNU General Public License. + +/* Keyboard controller registers. */ + +#define CONTROLLER_REGISTER_STATUS 0x64 +#define CONTROLLER_REGISTER_CONTROL 0x64 +#define CONTROLLER_REGISTER_DATA 0x60 + +/* Keyboard controller commands. */ +/* Read mode bits. */ + +#define CONTROLLER_COMMAND_READ_MODE 0x20 + +/* Write mode bits. */ + +#define CONTROLLER_COMMAND_WRITE_MODE 0x60 + +/* Get controller version. */ + +#define CONTROLLER_COMMAND_GET_VERSION 0xA1 + +/* Disable mouse interface. */ + +#define CONTROLLER_COMMAND_MOUSE_DISABLE 0xA7 + +/* Enable mouse interface. */ + +#define CONTROLLER_COMMAND_MOUSE_ENABLE 0xA8 + +/* Mouse interface test. */ + +#define CONTROLLER_COMMAND_TEST_MOUSE 0xA9 + +/* Controller self test. */ + +#define CONTROLLER_COMMAND_SELF_TEST 0xAA + +/* Keyboard interface test. */ + +#define CONTROLLER_COMMAND_KEYBOARD_TEST 0xAB + +/* Keyboard interface disable. */ + +#define CONTROLLER_COMMAND_KEYBOARD_DISABLE 0xAD + +/* Keyboard interface enable. */ + +#define CONTROLLER_COMMAND_KEYBOARD_ENABLE 0xAE + +/* Write to output buffer as if initiated by the auxiliary device. */ + +#define CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER 0xD3 + +/* Write the following byte to the mouse. */ + +#define CONTROLLER_COMMAND_WRITE_MOUSE 0xD4 + +/* Status Register Bits. */ +/* Keyboard output buffer full. */ + +#define CONTROLLER_STATUS_OUTPUT_BUFFER_FULL 0x01 + +/* Keyboard input buffer full. */ + +#define CONTROLLER_STATUS_INPUT_BUFFER_FULL 0x02 + +/* Self test successful. */ + +#define CONTROLLER_STATUS_SELF_TEST 0x04 + +/* Last write was a command write. (0 = data) */ + +#define CONTROLLER_STATUS_COMMAND 0x08 + +/* Zero if keyboard locked. */ + +#define CONTROLLER_STATUS_UNLOCKED 0x10 + +/* Mouse output buffer full. */ + +#define CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL 0x20 + +/* General receive/xmit timeout. */ + +#define CONTROLLER_STATUS_GENERAL_TIMEOUT 0x40 + +/* Parity error. */ + +#define CONTROLLER_STATUS_PARITY_ERROR 0x80 + +#define AUX_STATUS_OUTPUT_BUFFER_FULL (CONTROLLER_STATUS_OUTPUT_BUFFER_FULL | \ + CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) + +/* Controller mode register bits. */ +/* Keyboard data generate IRQ1. */ + +#define CONTROLLER_MODE_KEYBOARD_INTERRUPT 0x01 + +/* Mouse data generate IRQ12. */ + +#define CONTROLLER_MODE_MOUSE_INTERRUPT 0x02 + +/* The system flag. (?) */ + +#define CONTROLLER_MODE_SYS 0x04 + +/* The keylock doesn't affect the keyboard if set. */ + +#define CONTROLLER_MODE_NO_KEYLOCK 0x08 + +/* Disable keyboard interface. */ + +#define CONTROLLER_MODE_DISABLE_KEYBOARD 0x10 + +/* Disable mouse interface. */ + +#define CONTROLLER_MODE_DISABLE_MOUSE 0x20 + +/* Scan code conversion to PC format. */ + +#define CONTROLLER_MODE_KCC 0x40 +#define CONTROLLER_MODE_RFU 0x80 + +/* Timeout in ms for sending to keyboard controller. */ + +#define CONTROLLER_TIMEOUT 250 + +/* Hardware defines. */ + +#define CONTROLLER_PORT_BASE 0x60 +#define CONTROLLER_PORTS 0x10 + +/* Macros for accessing the keyboard controller on this platform. */ + +#define controller_read_input() READ_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_DATA) +#define controller_read_status() READ_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_STATUS) +#define controller_write_output(value) WRITE_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_DATA, value) +#define controller_write_command(value) WRITE_PORT_UCHAR ((PUCHAR)CONTROLLER_REGISTER_CONTROL, value) diff --git a/drivers/input/psaux/keyboard.h b/drivers/input/psaux/keyboard.h new file mode 100644 index 0000000..738b591 --- /dev/null +++ b/drivers/input/psaux/keyboard.h @@ -0,0 +1,51 @@ +// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/). +// CHAOS is also under the GNU General Public License. + +/* Timeout in ms for keyboard command acknowledge. */ + +#define KEYBOARD_TIMEOUT 1000 + +/* Timeout in ms for initializing the keyboard. */ + +#define KEYBOARD_INIT_TIMEOUT 1000 + +/* Keyboard commands. */ + +#define KEYBOARD_COMMAND_SET_LEDS 0xED +#define KEYBOARD_COMMAND_SET_RATE 0xF3 +#define KEYBOARD_COMMAND_ENABLE 0xF4 +#define KEYBOARD_COMMAND_DISABLE 0xF5 +#define KEYBOARD_COMMAND_RESET 0xFF + +/* Keyboard replies. */ +/* Power on reset. */ + +#define KEYBOARD_REPLY_POWER_ON_RESET 0xAA + +/* Acknowledgement of previous command. */ + +#define KEYBOARD_REPLY_ACK 0xFA + +/* Command NACK, send the command again. */ + +#define KEYBOARD_REPLY_RESEND 0xFE + +/* Hardware defines. */ + +#define KEYBOARD_IRQ 1 + +/* Return values from keyboard_read_data (). */ +/* No data. */ + +#define KEYBOARD_NO_DATA (-1) + +/* Parity or other error. */ + +#define KEYBOARD_BAD_DATA (-2) + +/* Common variables. */ + +int mouse_replies_expected; +BOOLEAN has_mouse; +// mailbox_id_type keyboard_target_mailbox_id; +unsigned keyboard_pressed_keys[16]; diff --git a/drivers/input/psaux/makefile b/drivers/input/psaux/makefile new file mode 100644 index 0000000..059f462 --- /dev/null +++ b/drivers/input/psaux/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = psaux + +TARGET_OBJECTS = $(TARGET_NAME).o controller.o mouse.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/input/psaux/mouse.c b/drivers/input/psaux/mouse.c new file mode 100644 index 0000000..47c06ba --- /dev/null +++ b/drivers/input/psaux/mouse.c @@ -0,0 +1,233 @@ +#include +#include "../include/mouse.h" +#include "controller.h" +#include "mouse.h" +#include "psaux.h" + +// Have we got a PS/2 mouse port? +BOOLEAN has_mouse = FALSE; + +// This buffer holds the mouse scan codes. The PS/2 protocol sends three characters for each event. +unsigned mouse_buffer[3]; +int mouse_buffer_position = 0; + +// The number of mouse replies expected +int mouse_replies_expected = 0; + +// Handle a mouse event + +BOOLEAN STDCALL +ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext) +{ + // char tmpstr[100]; + PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext; + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + + int state_dx, state_dy, state_buttons; + unsigned scancode; + unsigned status = controller_read_status(); + scancode = controller_read_input(); + + // Don't handle the mouse event if we aren't connected to the mouse class driver + if(DeviceExtension->ClassInformation.CallBack == NULL) return FALSE; + + if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0) + { + // mouse_handle_event(scancode); proceed to handle it + } + else + { + return FALSE; // keyboard_handle_event(scancode); + } + + if (mouse_replies_expected > 0) + { + if (scancode == MOUSE_ACK) + { + mouse_replies_expected--; + return; + } + + mouse_replies_expected = 0; + } + + /* Add this scancode to the mouse event queue. */ + + mouse_buffer[mouse_buffer_position] = scancode; + mouse_buffer_position++; + + // If the buffer is full, parse this event + if (mouse_buffer_position == 3) + { + mouse_buffer_position = 0; + // system_call_debug_print_simple ("We got a mouse event"); + + state_buttons = (mouse_buffer[0] & 1) * GPM_B_LEFT + + (mouse_buffer[0] & 2) * GPM_B_RIGHT + + (mouse_buffer[0] & 4) * GPM_B_MIDDLE; + + /* Some PS/2 mice send reports with negative bit set in data[0] and zero for movement. I think this is a + bug in the mouse, but working around it only causes artifacts when the actual report is -256; they'll + be treated as zero. This should be rare if the mouse sampling rate is set to a reasonable value; the + default of 100 Hz is plenty. (Stephen Tell) */ + + if (mouse_buffer[1] == 0) + { + state_dx = 0; + } + else + { + state_dx = (mouse_buffer[0] & 0x10) ? + mouse_buffer[1] - 256 : + mouse_buffer[1]; + } + + if (mouse_buffer[2] == 0) + { + state_dy = 0; + } + else + { + state_dy = -((mouse_buffer[0] & 0x20) ? + mouse_buffer[2] - 256 : + mouse_buffer[2]); + } + + if (((state_dx!=0) || (state_dy!=0) || (state_buttons!=0))) + { + // FIXME: Implement button state, see /include/ntddmous.h + + DeviceObject = (PDEVICE_OBJECT)ServiceContext; + DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->InputDataCount == MOUSE_BUFFER_SIZE) + { + return TRUE; + } + + DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].RawButtons = state_buttons; + DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].ButtonData = state_buttons; + DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastX = state_dx; + DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastY = state_dy; + DeviceExtension->InputDataCount++; + + KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL); + + return TRUE; + } + } +} + +/* Write a PS/2 mouse command. */ + +static void mouse_write_command (int command) +{ + controller_wait(); + controller_write_command (CONTROLLER_COMMAND_WRITE_MODE); + controller_wait(); + controller_write_output (command); +} + +/* Send a byte to the PS/2 mouse & handle returned ACK. */ + +static void mouse_write_ack (int value) +{ + controller_wait(); + controller_write_command (CONTROLLER_COMMAND_WRITE_MOUSE); + controller_wait(); + controller_write_output (value); + + /* We expect an ACK in response. */ + + mouse_replies_expected++; + controller_wait (); +} + +/* Check if this is a dual port controller. */ + +BOOLEAN detect_ps2_port(void) +{ + int loops; + BOOLEAN return_value = FALSE; + LARGE_INTEGER Millisecond_Timeout; + + Millisecond_Timeout.QuadPart = 1; + + return TRUE; // The rest of this code fails under BOCHs + + /* Put the value 0x5A in the output buffer using the "WriteAuxiliary Device Output Buffer" command (0xD3). + Poll the Status Register for a while to see if the value really turns up in the Data Register. If the + KEYBOARD_STATUS_MOUSE_OBF bit is also set to 1 in the Status Register, we assume this controller has an + Auxiliary Port (a.k.a. Mouse Port). */ + + controller_wait (); + controller_write_command (CONTROLLER_COMMAND_WRITE_MOUSE_OUTPUT_BUFFER); + controller_wait (); + + // 0x5A is a random dummy value + controller_write_output (0x5A); + + for (loops = 0; loops < 10; loops++) + { + unsigned char status = controller_read_status(); + + if((status & CONTROLLER_STATUS_OUTPUT_BUFFER_FULL) != 0) + { + controller_read_input(); + if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0) + { + return_value = TRUE; + } + break; + } + + KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout); + } + + return return_value; +} + +// Initialize the PS/2 mouse support + +BOOLEAN mouse_init (PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + + if (!detect_ps2_port ()) return FALSE; + + has_mouse = TRUE; + + DeviceExtension->InputDataCount = 0; + DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); + + // Enable the PS/2 mouse port + controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE); + + // 200 samples/sec + mouse_write_ack (MOUSE_SET_SAMPLE_RATE); + mouse_write_ack (200); + + // 8 counts per mm + mouse_write_ack (MOUSE_SET_RESOLUTION); + mouse_write_ack (3); + + // 2:1 scaling + mouse_write_ack (MOUSE_SET_SCALE21); + + // Enable the PS/2 device + mouse_write_ack (MOUSE_ENABLE_DEVICE); + + // Enable controller interrupts + mouse_write_command (MOUSE_INTERRUPTS_ON); + + // Connect the interrupt for the mouse irq + MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, &Dirql, &Affinity); + + IoConnectInterrupt(&DeviceExtension->MouseInterrupt, ps2_mouse_handler, DeviceObject, NULL, MappedIrq, + Dirql, Dirql, 0, FALSE, Affinity, FALSE); + + return TRUE; +} diff --git a/drivers/input/psaux/mouse.h b/drivers/input/psaux/mouse.h new file mode 100644 index 0000000..5ab0f5f --- /dev/null +++ b/drivers/input/psaux/mouse.h @@ -0,0 +1,80 @@ +// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/). +// CHAOS is also under the GNU General Public License. + +/* Mouse commands. */ +/* Set resolution. */ + +#define MOUSE_SET_RESOLUTION 0xE8 + +/* Set 1:1 scaling. */ + +#define MOUSE_SET_SCALE11 0xE6 + +/* Set 2:1 scaling. */ + +#define MOUSE_SET_SCALE21 0xE7 + +/* Get scaling factor. */ + +#define MOUSE_GET_SCALE 0xE9 + +/* Set stream mode. */ + +#define MOUSE_SET_STREAM 0xEA + +/* Set sample rate (number of times the controller will poll the port + per second). */ + +#define MOUSE_SET_SAMPLE_RATE 0xF3 + +/* Enable mouse device. */ + +#define MOUSE_ENABLE_DEVICE 0xF4 + +/* Disable mouse device. */ + +#define MOUSE_DISABLE_DEVICE 0xF5 + +/* Reset aux device. */ + +#define MOUSE_RESET 0xFF + +/* Command byte ACK. */ + +#define MOUSE_ACK 0xFA + +#define MOUSE_INTERRUPTS_OFF (CONTROLLER_MODE_KCC | \ + CONTROLLER_MODE_DISABLE_MOUSE | \ + CONTROLLER_MODE_SYS | \ + CONTROLLER_MODE_KEYBOARD_INTERRUPT) + +#define MOUSE_INTERRUPTS_ON (CONTROLLER_MODE_KCC | \ + CONTROLLER_MODE_SYS | \ + CONTROLLER_MODE_MOUSE_INTERRUPT | \ + CONTROLLER_MODE_KEYBOARD_INTERRUPT) + +/* Used with mouse buttons */ + +#define GPM_B_LEFT 4 +#define GPM_B_MIDDLE 2 +#define GPM_B_RIGHT 1 + +/* Some aux operations take long time. */ + +#define MAX_RETRIES 60 + +/* Hardware defines. */ + +#define MOUSE_IRQ 12 +#define MOUSE_WRAP_MASK 0x1F + +static PIRP CurrentIrp; +static ULONG MouseDataRead; +static ULONG MouseDataRequired; +static BOOLEAN AlreadyOpened = FALSE; +static KDPC MouseDpc; + +static VOID MouseDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2); diff --git a/drivers/input/psaux/psaux.c b/drivers/input/psaux/psaux.c new file mode 100644 index 0000000..e8bd4b0 --- /dev/null +++ b/drivers/input/psaux/psaux.c @@ -0,0 +1,196 @@ +/* + + ** PS/2 driver 0.0.1 + ** Written by Jason Filby (jasonfilby@yahoo.com) + ** For ReactOS (www.reactos.com) + + ** Handles the keyboard and mouse on the PS/2 ports + + ** TODO: Fix detect_ps2_port(void) so that it works under BOCHs + Implement mouse button support + +*/ + +#include +#include "../include/mouse.h" +#include "mouse.h" +#include "psaux.h" + +BOOLEAN STDCALL +MouseSynchronizeRoutine(PVOID Context) +{ + PIRP Irp = (PIRP)Context; + PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA); + int i; + + if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead) + { + return(TRUE); + } + + MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA); + MouseDataRead=NrToRead; + CurrentIrp=Irp; + + return(FALSE); +} + +VOID STDCALL +PS2MouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + + if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp)) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, FALSE); + } +} + +NTSTATUS STDCALL +PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + + switch (stk->MajorFunction) + { + case IRP_MJ_CREATE: + if (AlreadyOpened == TRUE) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_SUCCESS; + AlreadyOpened = TRUE; + } + break; + + case IRP_MJ_CLOSE: + Status = STATUS_SUCCESS; + break; + + default: + DbgPrint("NOT IMPLEMENTED\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status==STATUS_PENDING) + { + IoMarkIrpPending(Irp); + } + else + { + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + } + return(Status); +} + +VOID PS2MouseInitializeDataQueue(PVOID Context) +{ + ; +/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension; + + DeviceExtension->InputDataCount = 0; + DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */ +} + +NTSTATUS STDCALL +PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + + switch(Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_MOUSE_CONNECT: + + DeviceExtension->ClassInformation = + *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer); + + // Reinitialize the port input data queue synchronously + KeSynchronizeExecution(DeviceExtension->MouseInterrupt, + (PKSYNCHRONIZE_ROUTINE)PS2MouseInitializeDataQueue, DeviceExtension); + + status = STATUS_SUCCESS; + break; + + default: + status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = status; + if (status == STATUS_PENDING) { + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, Irp, NULL, NULL); + } else { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return status; +} + +VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + + (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)( + DeviceExtension->ClassInformation.DeviceObject, + DeviceExtension->MouseInputData, + NULL, + &DeviceExtension->InputDataCount); + + DeviceExtension->InputDataCount = 0; +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName; + UNICODE_STRING SymlinkName; + PDEVICE_EXTENSION DeviceExtension; + + if(detect_ps2_port() == TRUE) + { + } else + return STATUS_UNSUCCESSFUL; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = PS2MouseDispatch; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl; + DriverObject->DriverStartIo = PS2MouseStartIo; + + RtlInitUnicodeStringFromLiteral(&DeviceName, + L"\\Device\\Mouse"); // FIXME: find correct device name + IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_SERIAL_MOUSE_PORT, // FIXME: this isn't really a serial mouse port driver + 0, + TRUE, + &DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; + + RtlInitUnicodeStringFromLiteral(&SymlinkName, + L"\\??\\Mouse"); // FIXME: find correct device name + IoCreateSymbolicLink(&SymlinkName, &DeviceName); + + DeviceExtension = DeviceObject->DeviceExtension; + KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject); + KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject); + + mouse_init(DeviceObject); + + return(STATUS_SUCCESS); +} diff --git a/drivers/input/psaux/psaux.h b/drivers/input/psaux/psaux.h new file mode 100644 index 0000000..0dfb620 --- /dev/null +++ b/drivers/input/psaux/psaux.h @@ -0,0 +1,12 @@ +typedef struct _DEVICE_EXTENSION { + + PDEVICE_OBJECT DeviceObject; + ULONG InputDataCount; + PMOUSE_INPUT_DATA MouseInputData; + CLASS_INFORMATION ClassInformation; + + PKINTERRUPT MouseInterrupt; + KDPC IsrDpc; + KDPC IsrDpcRetry; + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; diff --git a/drivers/input/psaux/psaux.rc b/drivers/input/psaux/psaux.rc new file mode 100644 index 0000000..c7383c0 --- /dev/null +++ b/drivers/input/psaux/psaux.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "PS Auxiliary Device Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "psaux\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "psaux.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/input/sermouse/.cvsignore b/drivers/input/sermouse/.cvsignore new file mode 100644 index 0000000..67f8da8 --- /dev/null +++ b/drivers/input/sermouse/.cvsignore @@ -0,0 +1,2 @@ +sermouse.coff +sermouse.sys.unstripped diff --git a/drivers/input/sermouse/makefile b/drivers/input/sermouse/makefile new file mode 100644 index 0000000..fdf0915 --- /dev/null +++ b/drivers/input/sermouse/makefile @@ -0,0 +1,16 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = sermouse + +TARGET_OBJECTS = \ + sermouse.o + +#mouse.o - Old Serial mouse driver + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/input/sermouse/mouse.c b/drivers/input/sermouse/mouse.c new file mode 100644 index 0000000..d402062 --- /dev/null +++ b/drivers/input/sermouse/mouse.c @@ -0,0 +1,272 @@ +/* + + ** Mouse driver 0.0.3 + ** Written by Jason Filby (jasonfilby@yahoo.com) + ** For ReactOS (www.sid-dis.com/reactos) + + ** Note: The serial.o driver must be loaded before loading this driver + + ** Known Limitations: + ** Only supports mice on COM port 1 + + ** Old Driver, We done build it. Just keep for History. (S.E.) + +*/ + +#include +#include +#include +/* #include */ +#include + +#define MOUSE_IRQ_COM1 4 +#define MOUSE_IRQ_COM2 3 + +#define COM1_PORT 0x3f8 +#define COM2_PORT 0x2f8 + +#define max_screen_x 79 +#define max_screen_y 24 + +static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1; +static unsigned int MOUSE_COM=COM1_PORT; + +static unsigned int bytepos=0, coordinate; +static unsigned char mpacket[3]; +static signed int mouse_x=40, mouse_y=12; +static unsigned char mouse_button1, mouse_button2; +static signed int horiz_sensitivity, vert_sensitivity; + +BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext) +{ + unsigned int mbyte=inb(MOUSE_COM); + + // Synchronize + if((mbyte&64)==64) { bytepos=0; }; + + mpacket[bytepos]=mbyte; + bytepos++; + + // Process packet + if(bytepos==3) { + // Retrieve change in x and y from packet + int change_x=((mpacket[0] & 3) << 6) + mpacket[1]; + int change_y=((mpacket[0] & 12) << 4) + mpacket[2]; + + // Some mice need this + if(coordinate==1) { + change_x-=128; + change_y-=128; + }; + + // Change to signed + if(change_x>=128) { change_x=change_x-256; }; + if(change_y>=128) { change_y=change_y-256; }; + + // Adjust mouse position according to sensitivity + mouse_x+=change_x/horiz_sensitivity; + mouse_y+=change_y/vert_sensitivity; + + // Check that mouse is still in screen + if(mouse_x<0) { mouse_x=0; }; + if(mouse_x>max_screen_x) { mouse_x=max_screen_x; }; + if(mouse_y<0) { mouse_y=0; }; + if(mouse_y>max_screen_y) { mouse_y=max_screen_y; }; + + // Retrieve mouse button status from packet + mouse_button1=mpacket[0] & 32; + mouse_button2=mpacket[0] & 16; + + bytepos=0; + }; + +}; + +void InitializeMouseHardware(unsigned int mtype) +{ + char clear_error_bits; + + outb_p(MOUSE_COM+3, 0x80); // set DLAB on + outb_p(MOUSE_COM, 0x60); // speed LO byte + outb_p(MOUSE_COM+1, 0); // speed HI byte + outb_p(MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse + outb_p(MOUSE_COM+1, 0); // set comm and DLAB to 0 + outb_p(MOUSE_COM+4, 1); // DR int enable + + clear_error_bits=inb_p(MOUSE_COM+5); // clear error bits +}; + +int DetMicrosoft(void) +{ + char tmp, ind; + int buttons=0, i; + + outb_p(MOUSE_COM+4, 0x0b); + tmp=inb_p(MOUSE_COM); + + // Check the first for bytes for signs that this is an MS mouse + for(i=0; i<4; i++) { + while((inb_p(MOUSE_COM+5) & 1)==0) ; + ind=inb_p(MOUSE_COM); + if(ind==0x33) buttons=3; + if(ind==0x4d) buttons=2; + }; + + return buttons; +}; + +int CheckMouseType(unsigned int mtype) +{ + unsigned int retval=0; + + InitializeMouseHardware(mtype); + if(mtype==2) retval=DetMicrosoft(); + if(mtype==3) { + outb_p(MOUSE_COM+4, 11); + retval=3; + }; + outb_p(MOUSE_COM+1, 1); + + return retval; +}; + +void ClearMouse(void) +{ + // Waits until the mouse calms down but also quits out after a while + // in case some destructive user wants to keep moving the mouse + // before we're done + + unsigned int restarts=0, i; + for (i=0; i<60000; i++) + { + unsigned temp=inb(MOUSE_COM); + if(temp!=0) { + restarts++; + if(restarts<300000) { + i=0; + } else + { + i=60000; + }; + }; + }; +}; + +void InitializeMouse(void) +{ + int mbuttons=0, gotmouse=0; + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + PKINTERRUPT IrqObject; + + horiz_sensitivity=2; + vert_sensitivity=3; + + // Check for Microsoft mouse (2 buttons) + if(CheckMouseType(2)!=0) + { + gotmouse=1; + DbgPrint("Microsoft Mouse Detected\n"); + ClearMouse(); + coordinate=0; + }; + + // Check for Microsoft Systems mouse (3 buttons) + if(gotmouse==0) { + if(CheckMouseType(3)!=0) + { + gotmouse=1; + DbgPrint("Microsoft Mouse Detected\n"); + ClearMouse(); + coordinate=1; + }; + }; + + if(gotmouse==0) { + DbgPrint("No Mouse Detected!\n"); + } else { + MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, + &Dirql, &Affinity); + + IoConnectInterrupt(&IrqObject, microsoft_mouse_handler, NULL, + NULL, MappedIrq, Dirql, Dirql, 0, FALSE, + Affinity, FALSE); + }; +}; + +// For test purposes only +unsigned char get_text_char(int x, int y) +{ + unsigned char getchar; + char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2))); + getchar=*vidmem; + return getchar; +}; + +// For test purposes only +unsigned char get_text_color(int x, int y) +{ + unsigned char getcolor; + char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2))); + vidmem++; + getcolor=*vidmem; + return getcolor; +}; + +// For test purposes only +void put_text_char(int x, int y, unsigned char putchar[2]) +{ + char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2))); + *vidmem=putchar[0]; + vidmem++; + *vidmem=putchar[1]; +}; + +// For test purposes only +void test_mouse(void) +{ + static int i=0, forcechange=0; + static int old_x=40, old_y=12; + static unsigned char old_cursor[2], new_cursor[2]; + + DbgPrint("Testing mouse..."); + + old_cursor[0]=' '; + old_cursor[1]=7; + new_cursor[0]='Û'; + new_cursor[1]=15; + + old_cursor[0]=get_text_char(mouse_x, mouse_y); + old_cursor[1]=get_text_color(mouse_x, mouse_y); + put_text_char(mouse_x, mouse_y, new_cursor); + + while(i!=1) + { + if(mouse_button1!=0) { new_cursor[1]=10; mouse_button1=0; forcechange=1; }; + if(mouse_button2!=0) { new_cursor[1]=12; mouse_button2=0; forcechange=1; }; + + if((mouse_x!=old_x) || (mouse_y!=old_y) || (forcechange==1)) { + forcechange=0; + + put_text_char(old_x, old_y, old_cursor); + old_cursor[0]=get_text_char(mouse_x, mouse_y); + old_cursor[1]=get_text_color(mouse_x, mouse_y); + put_text_char(mouse_x, mouse_y, new_cursor); + + old_x=mouse_x; + old_y=mouse_y; + }; + }; +}; + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + DbgPrint("Mouse Driver 0.0.3\n"); + InitializeMouse(); + test_mouse(); + + return(STATUS_SUCCESS); +}; + diff --git a/drivers/input/sermouse/mouse.h b/drivers/input/sermouse/mouse.h new file mode 100644 index 0000000..0532f48 --- /dev/null +++ b/drivers/input/sermouse/mouse.h @@ -0,0 +1,12 @@ +typedef struct _DEVICE_EXTENSION { + + PDEVICE_OBJECT DeviceObject; + ULONG InputDataCount; + PMOUSE_INPUT_DATA MouseInputData; + CLASS_INFORMATION ClassInformation; + + PKINTERRUPT MouseInterrupt; + KDPC IsrDpc; + KDPC IsrDpcRetry; + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; \ No newline at end of file diff --git a/drivers/input/sermouse/sermouse.c b/drivers/input/sermouse/sermouse.c new file mode 100644 index 0000000..d625924 --- /dev/null +++ b/drivers/input/sermouse/sermouse.c @@ -0,0 +1,373 @@ +/* + + ** Mouse driver 0.0.4 + ** Written by Jason Filby (jasonfilby@yahoo.com) + ** For ReactOS (www.sid-dis.com/reactos) + + ** Note: The serial.o driver must be loaded before loading this driver + + ** Known Limitations: + ** Only supports mice on COM port 1 + +*/ + +#include +#include "../include/mouse.h" +#include "sermouse.h" +#include "mouse.h" + +#define MOUSE_IRQ_COM1 4 +#define MOUSE_IRQ_COM2 3 + +#define COM1_PORT 0x3f8 +#define COM2_PORT 0x2f8 + +#define max_screen_x 79 +#define max_screen_y 24 + +//static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1; +static unsigned int MOUSE_COM=COM1_PORT; + +static unsigned int bytepos=0, coordinate; +static unsigned char mpacket[3]; +static signed int mouse_x=40, mouse_y=12; +static unsigned char mouse_button1, mouse_button2; +static signed int horiz_sensitivity, vert_sensitivity; + +BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext) +{ + unsigned int mbyte=READ_PORT_UCHAR((PUCHAR)MOUSE_COM); + + // Synchronize + if((mbyte&64)==64) { bytepos=0; } + + mpacket[bytepos]=mbyte; + bytepos++; + + // Process packet + if(bytepos==3) { + // Retrieve change in x and y from packet + int change_x=((mpacket[0] & 3) << 6) + mpacket[1]; + int change_y=((mpacket[0] & 12) << 4) + mpacket[2]; + + // Some mice need this + if(coordinate==1) { + change_x-=128; + change_y-=128; + } + + // Change to signed + if(change_x>=128) { change_x=change_x-256; } + if(change_y>=128) { change_y=change_y-256; } + + // Adjust mouse position according to sensitivity + mouse_x+=change_x/horiz_sensitivity; + mouse_y+=change_y/vert_sensitivity; + + // Check that mouse is still in screen + if(mouse_x<0) { mouse_x=0; } + if(mouse_x>max_screen_x) { mouse_x=max_screen_x; } + if(mouse_y<0) { mouse_y=0; } + if(mouse_y>max_screen_y) { mouse_y=max_screen_y; } + + // Retrieve mouse button status from packet + mouse_button1=mpacket[0] & 32; + mouse_button2=mpacket[0] & 16; + + bytepos=0; + } + +} + +void InitializeMouseHardware(unsigned int mtype) +{ + char clear_error_bits; + + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+3, 0x80); // set DLAB on + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM, 0x60); // speed LO byte + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 0); // speed HI byte + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 0); // set comm and DLAB to 0 + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 1); // DR int enable + + clear_error_bits=READ_PORT_UCHAR((PUCHAR)MOUSE_COM+5); // clear error bits +} + +int DetMicrosoft(void) +{ + char tmp, ind; + int buttons=0, i, timeout=250; + + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 0x0b); + tmp=READ_PORT_UCHAR((PUCHAR)MOUSE_COM); + + // Check the first four bytes for signs that this is an MS mouse + for(i=0; i<4; i++) { + while(((READ_PORT_UCHAR((PUCHAR)MOUSE_COM+5) & 1)==0) && (timeout>0)) + { + KeDelayExecutionThread (KernelMode, FALSE, 1); + timeout--; + } + ind=READ_PORT_UCHAR((PUCHAR)MOUSE_COM); + if(ind==0x33) buttons=3; + if(ind==0x4d) buttons=2; + } + + return buttons; +} + +int CheckMouseType(unsigned int mtype) +{ + unsigned int retval=0; + + InitializeMouseHardware(mtype); + if(mtype==2) retval=DetMicrosoft(); + if(mtype==3) { + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 11); + retval=3; + } + WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 1); + + return retval; +} + +void ClearMouse(void) +{ + // Waits until the mouse calms down but also quits out after a while + // in case some destructive user wants to keep moving the mouse + // before we're done + + unsigned int restarts=0, i; + for (i=0; i<60000; i++) + { + unsigned temp=READ_PORT_UCHAR((PUCHAR)MOUSE_COM); + if(temp!=0) { + restarts++; + if(restarts<300000) { + i=0; + } else + { + i=60000; + } + } + } +} + +BOOLEAN InitializeMouse(PDEVICE_OBJECT DeviceObject) +{ + int mbuttons=0, gotmouse=0; + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; + + horiz_sensitivity=2; + vert_sensitivity=3; + + // Check for Microsoft mouse (2 buttons) + if(CheckMouseType(2)!=0) + { + gotmouse=1; + DbgPrint("Microsoft Mouse Detected\n"); + ClearMouse(); + coordinate=0; + } + + // Check for Microsoft Systems mouse (3 buttons) + if(gotmouse==0) { + if(CheckMouseType(3)!=0) + { + gotmouse=1; + DbgPrint("Microsoft Mouse Detected\n"); + ClearMouse(); + coordinate=1; + } + } + + if(gotmouse==0) return FALSE; + + DeviceExtension->InputDataCount = 0; + DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); + + MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ, + &Dirql, &Affinity); + + IoConnectInterrupt(&DeviceExtension->MouseInterrupt, microsoft_mouse_handler, NULL, + NULL, MappedIrq, Dirql, Dirql, 0, FALSE, + Affinity, FALSE); + + return TRUE; +} + +VOID SerialMouseInitializeDataQueue(PVOID Context) +{ + ; +/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension; + + DeviceExtension->InputDataCount = 0; + DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */ +} + +BOOLEAN MouseSynchronizeRoutine(PVOID Context) +{ + PIRP Irp = (PIRP)Context; + PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA); + int i; + + if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead) + { + return(TRUE); + } + + MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA); + MouseDataRead=NrToRead; + CurrentIrp=Irp; + + return(FALSE); +} + +VOID SerialMouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + + if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp)) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, FALSE); + } +} + +NTSTATUS SerialMouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + + switch(Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_MOUSE_CONNECT: + + DeviceExtension->ClassInformation = + *((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer); + + // Reinitialize the port input data queue synchronously + KeSynchronizeExecution(DeviceExtension->MouseInterrupt, + (PKSYNCHRONIZE_ROUTINE)SerialMouseInitializeDataQueue, DeviceExtension); + + status = STATUS_SUCCESS; + break; + + default: + status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + Irp->IoStatus.Status = status; + if (status == STATUS_PENDING) { + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, Irp, NULL, NULL); + } else { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + return status; +} + +NTSTATUS SerialMouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + + switch (stk->MajorFunction) + { + case IRP_MJ_CREATE: + if (AlreadyOpened == TRUE) + { + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_SUCCESS; + AlreadyOpened = TRUE; + } + break; + + case IRP_MJ_CLOSE: + Status = STATUS_SUCCESS; + break; + + default: + DbgPrint("NOT IMPLEMENTED\n"); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status==STATUS_PENDING) + { + IoMarkIrpPending(Irp); + } + else + { + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp,IO_NO_INCREMENT); + } + return(Status); +} + +VOID SerialMouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) +{ + PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + + (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)( + DeviceExtension->ClassInformation.DeviceObject, + DeviceExtension->MouseInputData, + NULL, + &DeviceExtension->InputDataCount); + + DeviceExtension->InputDataCount = 0; +} + +NTSTATUS STDCALL +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +{ + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName; + UNICODE_STRING SymlinkName; + PDEVICE_EXTENSION DeviceExtension; + + DbgPrint("Serial Mouse Driver 0.0.4\n"); + + if(InitializeMouse(DeviceObject) == FALSE) + return STATUS_UNSUCCESSFUL; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialMouseDispatch; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialMouseDispatch; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SerialMouseInternalDeviceControl; + DriverObject->DriverStartIo = SerialMouseStartIo; + + RtlInitUnicodeStringFromLiteral(&DeviceName, + L"\\Device\\Mouse"); // FIXME: find correct device name + IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_SERIAL_MOUSE_PORT, + 0, + TRUE, + &DeviceObject); + DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; + + RtlInitUnicodeStringFromLiteral(&SymlinkName, + L"\\??\\Mouse"); // FIXME: find correct device name + IoCreateSymbolicLink(&SymlinkName, &DeviceName); + + DeviceExtension = DeviceObject->DeviceExtension; + KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject); + KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject); + + return(STATUS_SUCCESS); +} diff --git a/drivers/input/sermouse/sermouse.h b/drivers/input/sermouse/sermouse.h new file mode 100644 index 0000000..5ab0f5f --- /dev/null +++ b/drivers/input/sermouse/sermouse.h @@ -0,0 +1,80 @@ +// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/). +// CHAOS is also under the GNU General Public License. + +/* Mouse commands. */ +/* Set resolution. */ + +#define MOUSE_SET_RESOLUTION 0xE8 + +/* Set 1:1 scaling. */ + +#define MOUSE_SET_SCALE11 0xE6 + +/* Set 2:1 scaling. */ + +#define MOUSE_SET_SCALE21 0xE7 + +/* Get scaling factor. */ + +#define MOUSE_GET_SCALE 0xE9 + +/* Set stream mode. */ + +#define MOUSE_SET_STREAM 0xEA + +/* Set sample rate (number of times the controller will poll the port + per second). */ + +#define MOUSE_SET_SAMPLE_RATE 0xF3 + +/* Enable mouse device. */ + +#define MOUSE_ENABLE_DEVICE 0xF4 + +/* Disable mouse device. */ + +#define MOUSE_DISABLE_DEVICE 0xF5 + +/* Reset aux device. */ + +#define MOUSE_RESET 0xFF + +/* Command byte ACK. */ + +#define MOUSE_ACK 0xFA + +#define MOUSE_INTERRUPTS_OFF (CONTROLLER_MODE_KCC | \ + CONTROLLER_MODE_DISABLE_MOUSE | \ + CONTROLLER_MODE_SYS | \ + CONTROLLER_MODE_KEYBOARD_INTERRUPT) + +#define MOUSE_INTERRUPTS_ON (CONTROLLER_MODE_KCC | \ + CONTROLLER_MODE_SYS | \ + CONTROLLER_MODE_MOUSE_INTERRUPT | \ + CONTROLLER_MODE_KEYBOARD_INTERRUPT) + +/* Used with mouse buttons */ + +#define GPM_B_LEFT 4 +#define GPM_B_MIDDLE 2 +#define GPM_B_RIGHT 1 + +/* Some aux operations take long time. */ + +#define MAX_RETRIES 60 + +/* Hardware defines. */ + +#define MOUSE_IRQ 12 +#define MOUSE_WRAP_MASK 0x1F + +static PIRP CurrentIrp; +static ULONG MouseDataRead; +static ULONG MouseDataRequired; +static BOOLEAN AlreadyOpened = FALSE; +static KDPC MouseDpc; + +static VOID MouseDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2); diff --git a/drivers/input/sermouse/sermouse.rc b/drivers/input/sermouse/sermouse.rc new file mode 100644 index 0000000..15e98a6 --- /dev/null +++ b/drivers/input/sermouse/sermouse.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Serial Mouse Device Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "sermouse\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "sermouse.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/lib/bzip2/CHANGES b/drivers/lib/bzip2/CHANGES new file mode 100644 index 0000000..ecaf417 --- /dev/null +++ b/drivers/lib/bzip2/CHANGES @@ -0,0 +1,167 @@ + + +0.9.0 +~~~~~ +First version. + + +0.9.0a +~~~~~~ +Removed 'ranlib' from Makefile, since most modern Unix-es +don't need it, or even know about it. + + +0.9.0b +~~~~~~ +Fixed a problem with error reporting in bzip2.c. This does not effect +the library in any way. Problem is: versions 0.9.0 and 0.9.0a (of the +program proper) compress and decompress correctly, but give misleading +error messages (internal panics) when an I/O error occurs, instead of +reporting the problem correctly. This shouldn't give any data loss +(as far as I can see), but is confusing. + +Made the inline declarations disappear for non-GCC compilers. + + +0.9.0c +~~~~~~ +Fixed some problems in the library pertaining to some boundary cases. +This makes the library behave more correctly in those situations. The +fixes apply only to features (calls and parameters) not used by +bzip2.c, so the non-fixedness of them in previous versions has no +effect on reliability of bzip2.c. + +In bzlib.c: + * made zero-length BZ_FLUSH work correctly in bzCompress(). + * fixed bzWrite/bzRead to ignore zero-length requests. + * fixed bzread to correctly handle read requests after EOF. + * wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. + +In compress.c: + * changed setting of nGroups in sendMTFValues() so as to + do a bit better on small files. This _does_ effect + bzip2.c. + + +0.9.5a +~~~~~~ +Major change: add a fallback sorting algorithm (blocksort.c) +to give reasonable behaviour even for very repetitive inputs. +Nuked --repetitive-best and --repetitive-fast since they are +no longer useful. + +Minor changes: mostly a whole bunch of small changes/ +bugfixes in the driver (bzip2.c). Changes pertaining to the +user interface are: + + allow decompression of symlink'd files to stdout + decompress/test files even without .bz2 extension + give more accurate error messages for I/O errors + when compressing/decompressing to stdout, don't catch control-C + read flags from BZIP2 and BZIP environment variables + decline to break hard links to a file unless forced with -f + allow -c flag even with no filenames + preserve file ownerships as far as possible + make -s -1 give the expected block size (100k) + add a flag -q --quiet to suppress nonessential warnings + stop decoding flags after --, so files beginning in - can be handled + resolved inconsistent naming: bzcat or bz2cat ? + bzip2 --help now returns 0 + +Programming-level changes are: + + fixed syntax error in GET_LL4 for Borland C++ 5.02 + let bzBuffToBuffDecompress return BZ_DATA_ERROR{_MAGIC} + fix overshoot of mode-string end in bzopen_or_bzdopen + wrapped bzlib.h in #ifdef __cplusplus ... extern "C" { ... } + close file handles under all error conditions + added minor mods so it compiles with DJGPP out of the box + fixed Makefile so it doesn't give problems with BSD make + fix uninitialised memory reads in dlltest.c + +0.9.5b +~~~~~~ +Open stdin/stdout in binary mode for DJGPP. + +0.9.5c +~~~~~~ +Changed BZ_N_OVERSHOOT to be ... + 2 instead of ... + 1. The + 1 +version could cause the sorted order to be wrong in some extremely +obscure cases. Also changed setting of quadrant in blocksort.c. + +0.9.5d +~~~~~~ +The only functional change is to make bzlibVersion() in the library +return the correct string. This has no effect whatsoever on the +functioning of the bzip2 program or library. Added a couple of casts +so the library compiles without warnings at level 3 in MS Visual +Studio 6.0. Included a Y2K statement in the file Y2K_INFO. All other +changes are minor documentation changes. + +1.0 +~~~ +Several minor bugfixes and enhancements: + +* Large file support. The library uses 64-bit counters to + count the volume of data passing through it. bzip2.c + is now compiled with -D_FILE_OFFSET_BITS=64 to get large + file support from the C library. -v correctly prints out + file sizes greater than 4 gigabytes. All these changes have + been made without assuming a 64-bit platform or a C compiler + which supports 64-bit ints, so, except for the C library + aspect, they are fully portable. + +* Decompression robustness. The library/program should be + robust to any corruption of compressed data, detecting and + handling _all_ corruption, instead of merely relying on + the CRCs. What this means is that the program should + never crash, given corrupted data, and the library should + always return BZ_DATA_ERROR. + +* Fixed an obscure race-condition bug only ever observed on + Solaris, in which, if you were very unlucky and issued + control-C at exactly the wrong time, both input and output + files would be deleted. + +* Don't run out of file handles on test/decompression when + large numbers of files have invalid magic numbers. + +* Avoid library namespace pollution. Prefix all exported + symbols with BZ2_. + +* Minor sorting enhancements from my DCC2000 paper. + +* Advance the version number to 1.0, so as to counteract the + (false-in-this-case) impression some people have that programs + with version numbers less than 1.0 are in someway, experimental, + pre-release versions. + +* Create an initial Makefile-libbz2_so to build a shared library. + Yes, I know I should really use libtool et al ... + +* Make the program exit with 2 instead of 0 when decompression + fails due to a bad magic number (ie, an invalid bzip2 header). + Also exit with 1 (as the manual claims :-) whenever a diagnostic + message would have been printed AND the corresponding operation + is aborted, for example + bzip2: Output file xx already exists. + When a diagnostic message is printed but the operation is not + aborted, for example + bzip2: Can't guess original name for wurble -- using wurble.out + then the exit value 0 is returned, unless some other problem is + also detected. + + I think it corresponds more closely to what the manual claims now. + + +1.0.1 +~~~~~ +* Modified dlltest.c so it uses the new BZ2_ naming scheme. +* Modified makefile-msc to fix minor build probs on Win2k. +* Updated README.COMPILATION.PROBLEMS. + +There are no functionality changes or bug fixes relative to version +1.0.0. This is just a documentation update + a fix for minor Win32 +build problems. For almost everyone, upgrading from 1.0.0 to 1.0.1 is +utterly pointless. Don't bother. diff --git a/drivers/lib/bzip2/LICENSE b/drivers/lib/bzip2/LICENSE new file mode 100644 index 0000000..88fa6d8 --- /dev/null +++ b/drivers/lib/bzip2/LICENSE @@ -0,0 +1,39 @@ + +This program, "bzip2" and associated library "libbzip2", are +copyright (C) 1996-2000 Julian R Seward. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, Cambridge, UK. +jseward@acm.org +bzip2/libbzip2 version 1.0 of 21 March 2000 + diff --git a/drivers/lib/bzip2/Makefile b/drivers/lib/bzip2/Makefile new file mode 100644 index 0000000..c933adb --- /dev/null +++ b/drivers/lib/bzip2/Makefile @@ -0,0 +1,18 @@ +PATH_TO_TOP = ../../.. +TARGET_TYPE = export_driver +TARGET_NAME = unbzip2 +TARGET_NORC = yes + +TARGET_CFLAGS=-Wall -Winline -Os -fomit-frame-pointer -fno-strength-reduce -DBZ_NO_STDIO -DBZ_DECOMPRESS_ONLY $(BIGFILES) -g + +TARGET_OBJECTS = bzlib.o randtable.o crctable.o decompress.o huffman.o dllmain.o + +TARGET_GCCLIBS = gcc + +include $(PATH_TO_TOP)/rules.mak +include $(TOOLS_PATH)/helper.mk + +test.exe: test.o ../../dk/w32/lib/unbzip2.a + $(CC) -s -Os -o test.exe test.o ../../dk/w32/lib/unbzip2.a +test.o: test.c + $(CC) -s -Os -c test.c diff --git a/drivers/lib/bzip2/Makefile-libbz2_so b/drivers/lib/bzip2/Makefile-libbz2_so new file mode 100644 index 0000000..a347c50 --- /dev/null +++ b/drivers/lib/bzip2/Makefile-libbz2_so @@ -0,0 +1,43 @@ + +# This Makefile builds a shared version of the library, +# libbz2.so.1.0.1, with soname libbz2.so.1.0, +# at least on x86-Linux (RedHat 5.2), +# with gcc-2.7.2.3. Please see the README file for some +# important info about building the library like this. + +SHELL=/bin/sh +CC=gcc +BIGFILES=-D_FILE_OFFSET_BITS=64 +CFLAGS=-fpic -fPIC -Wall -Winline -O2 -fomit-frame-pointer -fno-strength-reduce $(BIGFILES) + +OBJS= blocksort.o \ + huffman.o \ + crctable.o \ + randtable.o \ + compress.o \ + decompress.o \ + bzlib.o + +all: $(OBJS) + $(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.1 $(OBJS) + $(CC) $(CFLAGS) -o bzip2-shared bzip2.c libbz2.so.1.0.1 + rm -f libbz2.so.1.0 + ln -s libbz2.so.1.0.1 libbz2.so.1.0 + +clean: + rm -f $(OBJS) bzip2.o libbz2.so.1.0.1 libbz2.so.1.0 bzip2-shared + +blocksort.o: blocksort.c + $(CC) $(CFLAGS) -c blocksort.c +huffman.o: huffman.c + $(CC) $(CFLAGS) -c huffman.c +crctable.o: crctable.c + $(CC) $(CFLAGS) -c crctable.c +randtable.o: randtable.c + $(CC) $(CFLAGS) -c randtable.c +compress.o: compress.c + $(CC) $(CFLAGS) -c compress.c +decompress.o: decompress.c + $(CC) $(CFLAGS) -c decompress.c +bzlib.o: bzlib.c + $(CC) $(CFLAGS) -c bzlib.c diff --git a/drivers/lib/bzip2/README b/drivers/lib/bzip2/README new file mode 100644 index 0000000..22945a2 --- /dev/null +++ b/drivers/lib/bzip2/README @@ -0,0 +1,166 @@ + +This is the README for bzip2, a block-sorting file compressor, version +1.0. This version is fully compatible with the previous public +releases, bzip2-0.1pl2, bzip2-0.9.0 and bzip2-0.9.5. + +bzip2-1.0 is distributed under a BSD-style license. For details, +see the file LICENSE. + +Complete documentation is available in Postscript form (manual.ps) or +html (manual_toc.html). A plain-text version of the manual page is +available as bzip2.txt. A statement about Y2K issues is now included +in the file Y2K_INFO. + + +HOW TO BUILD -- UNIX + +Type `make'. This builds the library libbz2.a and then the +programs bzip2 and bzip2recover. Six self-tests are run. +If the self-tests complete ok, carry on to installation: + +To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type + make install +To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type + make install PREFIX=/xxx/yyy +If you are (justifiably) paranoid and want to see what 'make install' +is going to do, you can first do + make -n install or + make -n install PREFIX=/xxx/yyy respectively. +The -n instructs make to show the commands it would execute, but +not actually execute them. + + +HOW TO BUILD -- UNIX, shared library libbz2.so. + +Do 'make -f Makefile-libbz2_so'. This Makefile seems to work for +Linux-ELF (RedHat 5.2 on an x86 box), with gcc. I make no claims +that it works for any other platform, though I suspect it probably +will work for most platforms employing both ELF and gcc. + +bzip2-shared, a client of the shared library, is also build, but +not self-tested. So I suggest you also build using the normal +Makefile, since that conducts a self-test. + +Important note for people upgrading .so's from 0.9.0/0.9.5 to +version 1.0. All the functions in the library have been renamed, +from (eg) bzCompress to BZ2_bzCompress, to avoid namespace pollution. +Unfortunately this means that the libbz2.so created by +Makefile-libbz2_so will not work with any program which used an +older version of the library. Sorry. I do encourage library +clients to make the effort to upgrade to use version 1.0, since +it is both faster and more robust than previous versions. + + +HOW TO BUILD -- Windows 95, NT, DOS, Mac, etc. + +It's difficult for me to support compilation on all these platforms. +My approach is to collect binaries for these platforms, and put them +on the master web page (http://sourceware.cygnus.com/bzip2). Look +there. However (FWIW), bzip2-1.0 is very standard ANSI C and should +compile unmodified with MS Visual C. For Win32, there is one +important caveat: in bzip2.c, you must set BZ_UNIX to 0 and +BZ_LCCWIN32 to 1 before building. If you have difficulties building, +you might want to read README.COMPILATION.PROBLEMS. + + +VALIDATION + +Correct operation, in the sense that a compressed file can always be +decompressed to reproduce the original, is obviously of paramount +importance. To validate bzip2, I used a modified version of Mark +Nelson's churn program. Churn is an automated test driver which +recursively traverses a directory structure, using bzip2 to compress +and then decompress each file it encounters, and checking that the +decompressed data is the same as the original. There are more details +in Section 4 of the user guide. + + + +Please read and be aware of the following: + +WARNING: + + This program (attempts to) compress data by performing several + non-trivial transformations on it. Unless you are 100% familiar + with *all* the algorithms contained herein, and with the + consequences of modifying them, you should NOT meddle with the + compression or decompression machinery. Incorrect changes can and + very likely *will* lead to disastrous loss of data. + + +DISCLAIMER: + + I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE + USE OF THIS PROGRAM, HOWSOEVER CAUSED. + + Every compression of a file implies an assumption that the + compressed file can be decompressed to reproduce the original. + Great efforts in design, coding and testing have been made to + ensure that this program works correctly. However, the complexity + of the algorithms, and, in particular, the presence of various + special cases in the code which occur with very low but non-zero + probability make it impossible to rule out the possibility of bugs + remaining in the program. DO NOT COMPRESS ANY DATA WITH THIS + PROGRAM UNLESS YOU ARE PREPARED TO ACCEPT THE POSSIBILITY, HOWEVER + SMALL, THAT THE DATA WILL NOT BE RECOVERABLE. + + That is not to say this program is inherently unreliable. Indeed, + I very much hope the opposite is true. bzip2 has been carefully + constructed and extensively tested. + + +PATENTS: + + To the best of my knowledge, bzip2 does not use any patented + algorithms. However, I do not have the resources available to + carry out a full patent search. Therefore I cannot give any + guarantee of the above statement. + +End of legalities. + + +WHAT'S NEW IN 0.9.0 (as compared to 0.1pl2) ? + + * Approx 10% faster compression, 30% faster decompression + * -t (test mode) is a lot quicker + * Can decompress concatenated compressed files + * Programming interface, so programs can directly read/write .bz2 files + * Less restrictive (BSD-style) licensing + * Flag handling more compatible with GNU gzip + * Much more documentation, i.e., a proper user manual + * Hopefully, improved portability (at least of the library) + +WHAT'S NEW IN 0.9.5 ? + + * Compression speed is much less sensitive to the input + data than in previous versions. Specifically, the very + slow performance caused by repetitive data is fixed. + * Many small improvements in file and flag handling. + * A Y2K statement. + +WHAT'S NEW IN 1.0 + + See the CHANGES file. + +I hope you find bzip2 useful. Feel free to contact me at + jseward@acm.org +if you have any suggestions or queries. Many people mailed me with +comments, suggestions and patches after the releases of bzip-0.15, +bzip-0.21, bzip2-0.1pl2 and bzip2-0.9.0, and the changes in bzip2 are +largely a result of this feedback. I thank you for your comments. + +At least for the time being, bzip2's "home" is (or can be reached via) +http://www.muraroa.demon.co.uk. + +Julian Seward +jseward@acm.org + +Cambridge, UK +18 July 1996 (version 0.15) +25 August 1996 (version 0.21) + 7 August 1997 (bzip2, version 0.1) +29 August 1997 (bzip2, version 0.1pl2) +23 August 1998 (bzip2, version 0.9.0) + 8 June 1999 (bzip2, version 0.9.5) + 4 Sept 1999 (bzip2, version 0.9.5d) + 5 May 2000 (bzip2, version 1.0pre8) diff --git a/drivers/lib/bzip2/README.COMPILATION.PROBLEMS b/drivers/lib/bzip2/README.COMPILATION.PROBLEMS new file mode 100644 index 0000000..d621ad5 --- /dev/null +++ b/drivers/lib/bzip2/README.COMPILATION.PROBLEMS @@ -0,0 +1,130 @@ + +bzip2-1.0 should compile without problems on the vast majority of +platforms. Using the supplied Makefile, I've built and tested it +myself for x86-linux, sparc-solaris, alpha-linux, x86-cygwin32 and +alpha-tru64unix. With makefile.msc, Visual C++ 6.0 and nmake, you can +build a native Win32 version too. Large file support seems to work +correctly on at least alpha-tru64unix and x86-cygwin32 (on Windows +2000). + +When I say "large file" I mean a file of size 2,147,483,648 (2^31) +bytes or above. Many older OSs can't handle files above this size, +but many newer ones can. Large files are pretty huge -- most files +you'll encounter are not Large Files. + +Earlier versions of bzip2 (0.1, 0.9.0, 0.9.5) compiled on a wide +variety of platforms without difficulty, and I hope this version will +continue in that tradition. However, in order to support large files, +I've had to include the define -D_FILE_OFFSET_BITS=64 in the Makefile. +This can cause problems. + +The technique of adding -D_FILE_OFFSET_BITS=64 to get large file +support is, as far as I know, the Recommended Way to get correct large +file support. For more details, see the Large File Support +Specification, published by the Large File Summit, at + http://www.sas.com/standard/large.file/ + +As a general comment, if you get compilation errors which you think +are related to large file support, try removing the above define from +the Makefile, ie, delete the line + BIGFILES=-D_FILE_OFFSET_BITS=64 +from the Makefile, and do 'make clean ; make'. This will give you a +version of bzip2 without large file support, which, for most +applications, is probably not a problem. + +Alternatively, try some of the platform-specific hints listed below. + +You can use the spewG.c program to generate huge files to test bzip2's +large file support, if you are feeling paranoid. Be aware though that +any compilation problems which affect bzip2 will also affect spewG.c, +alas. + + +Known problems as of 1.0pre8: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* HP/UX 10.20 and 11.00, using gcc (2.7.2.3 and 2.95.2): A large + number of warnings appear, including the following: + + /usr/include/sys/resource.h: In function `getrlimit': + /usr/include/sys/resource.h:168: + warning: implicit declaration of function `__getrlimit64' + /usr/include/sys/resource.h: In function `setrlimit': + /usr/include/sys/resource.h:170: + warning: implicit declaration of function `__setrlimit64' + + This would appear to be a problem with large file support, header + files and gcc. gcc may or may not give up at this point. If it + fails, you might be able to improve matters by adding + -D__STDC_EXT__=1 + to the BIGFILES variable in the Makefile (ie, change its definition + to + BIGFILES=-D_FILE_OFFSET_BITS=64 -D__STDC_EXT__=1 + + Even if gcc does produce a binary which appears to work (ie passes + its self-tests), you might want to test it to see if it works properly + on large files. + + +* HP/UX 10.20 and 11.00, using HP's cc compiler. + + No specific problems for this combination, except that you'll need to + specify the -Ae flag, and zap the gcc-specific stuff + -Wall -Winline -O2 -fomit-frame-pointer -fno-strength-reduce. + You should retain -D_FILE_OFFSET_BITS=64 in order to get large + file support -- which is reported to work ok for this HP/UX + cc + combination. + + +* SunOS 4.1.X. + + Amazingly, there are still people out there using this venerable old + banger. I shouldn't be too rude -- I started life on SunOS, and + it was a pretty darn good OS, way back then. Anyway: + + SunOS doesn't seem to have strerror(), so you'll have to use + perror(), perhaps by doing adding this (warning: UNTESTED CODE): + + char* strerror ( int errnum ) + { + if (errnum < 0 || errnum >= sys_nerr) + return "Unknown error"; + else + return sys_errlist[errnum]; + } + + Or you could comment out the relevant calls to strerror; they're + not mission-critical. Or you could upgrade to Solaris. Ha ha ha! + (what?? you think I've got Bad Attitude?) + + +* Making a shared library on Solaris. (Not really a compilation + problem, but many people ask ...) + + Firstly, if you have Solaris 8, either you have libbz2.so already + on your system, or you can install it from the Solaris CD. + + Secondly, be aware that there are potential naming conflicts + between the .so file supplied with Solaris 8, and the .so file + which Makefile-libbz2_so will make. Makefile-libbz2_so creates + a .so which has the names which I intend to be "official" as + of version 1.0.0 and onwards. Unfortunately, the .so in + Solaris 8 appeared before I decided on the final names, so + the two libraries are incompatible. We have since communicated + and I hope that the problems will have been solved in the next + version of Solaris, whenever that might appear. + + All that said: you might be able to get somewhere + by finding the line in Makefile-libbz2_so which says + + $(CC) -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.1 $(OBJS) + + and replacing with + + ($CC) -G -shared -o libbz2.so.1.0.1 -h libbz2.so.1.0 $(OBJS) + + If gcc objects to the combination -fpic -fPIC, get rid of + the second one, leaving just "-fpic". + + +That's the end of the currently known compilation problems. diff --git a/drivers/lib/bzip2/README.reactos b/drivers/lib/bzip2/README.reactos new file mode 100644 index 0000000..8d5b127 --- /dev/null +++ b/drivers/lib/bzip2/README.reactos @@ -0,0 +1,8 @@ +2001-10-16: Imported bzip2 code into reactos project to create a decompression +library for use by the ramdisk driver to decompress the ramdisk image into mem +Modified makefile and some source code to build a .dll with only the +decompression code. There are 3 exports: the decompression routine, and two +function pointers that must be initialized to C malloc and free routines. + + - Phillip Susi + diff --git a/drivers/lib/bzip2/Y2K_INFO b/drivers/lib/bzip2/Y2K_INFO new file mode 100644 index 0000000..55fd56a --- /dev/null +++ b/drivers/lib/bzip2/Y2K_INFO @@ -0,0 +1,34 @@ + +Y2K status of bzip2 and libbzip2, versions 0.1, 0.9.0 and 0.9.5 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Informally speaking: + bzip2 is a compression program built on top of libbzip2, + a library which does the real work of compression and + decompression. As far as I am aware, libbzip2 does not have + any date-related code at all. + + bzip2 itself copies dates from source to destination files + when compressing or decompressing, using the 'stat' and 'utime' + UNIX system calls. It doesn't examine, manipulate or store the + dates in any way. So as far as I can see, there shouldn't be any + problem with bzip2 providing 'stat' and 'utime' work correctly + on your system. + + On non-unix platforms (those for which BZ_UNIX in bzip2.c is + not set to 1), bzip2 doesn't even do the date copying. + + Overall, informally speaking, I don't think bzip2 or libbzip2 + have a Y2K problem. + +Formally speaking: + I am not prepared to offer you any assurance whatsoever + regarding Y2K issues in my software. You alone assume the + entire risk of using the software. The disclaimer of liability + in the LICENSE file in the bzip2 source distribution continues + to apply on this issue as with every other issue pertaining + to the software. + +Julian Seward +Cambridge, UK +25 August 1999 diff --git a/drivers/lib/bzip2/blocksort.c b/drivers/lib/bzip2/blocksort.c new file mode 100644 index 0000000..ec42672 --- /dev/null +++ b/drivers/lib/bzip2/blocksort.c @@ -0,0 +1,1134 @@ + +/*-------------------------------------------------------------*/ +/*--- Block sorting machinery ---*/ +/*--- blocksort.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. + + To get some idea how the block sorting algorithms in this file + work, read my paper + On the Performance of BWT Sorting Algorithms + in Proceedings of the IEEE Data Compression Conference 2000, + Snowbird, Utah, USA, 27-30 March 2000. The main sort in this + file implements the algorithm called cache in the paper. +--*/ + + +#include "bzlib_private.h" + +/*---------------------------------------------*/ +/*--- Fallback O(N log(N)^2) sorting ---*/ +/*--- algorithm, for repetitive blocks ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +void fallbackSimpleSort ( UInt32* fmap, + UInt32* eclass, + Int32 lo, + Int32 hi ) +{ + Int32 i, j, tmp; + UInt32 ec_tmp; + + if (lo == hi) return; + + if (hi - lo > 3) { + for ( i = hi-4; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4 ) + fmap[j-4] = fmap[j]; + fmap[j-4] = tmp; + } + } + + for ( i = hi-1; i >= lo; i-- ) { + tmp = fmap[i]; + ec_tmp = eclass[tmp]; + for ( j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++ ) + fmap[j-1] = fmap[j]; + fmap[j-1] = tmp; + } +} + + +/*---------------------------------------------*/ +#define fswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define fvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + fswap(fmap[yyp1], fmap[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + + +#define fmin(a,b) ((a) < (b)) ? (a) : (b) + +#define fpush(lz,hz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + sp++; } + +#define fpop(lz,hz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; } + +#define FALLBACK_QSORT_SMALL_THRESH 10 +#define FALLBACK_QSORT_STACK_SIZE 100 + + +static +void fallbackQSort3 ( UInt32* fmap, + UInt32* eclass, + Int32 loSt, + Int32 hiSt ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m; + Int32 sp, lo, hi; + UInt32 med, r, r3; + Int32 stackLo[FALLBACK_QSORT_STACK_SIZE]; + Int32 stackHi[FALLBACK_QSORT_STACK_SIZE]; + + r = 0; + + sp = 0; + fpush ( loSt, hiSt ); + + while (sp > 0) { + + AssertH ( sp < FALLBACK_QSORT_STACK_SIZE, 1004 ); + + fpop ( lo, hi ); + if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) { + fallbackSimpleSort ( fmap, eclass, lo, hi ); + continue; + } + + /* Random partitioning. Median of 3 sometimes fails to + avoid bad cases. Median of 9 seems to help but + looks rather expensive. This too seems to work but + is cheaper. Guidance for the magic constants + 7621 and 32768 is taken from Sedgewick's algorithms + book, chapter 35. + */ + r = ((r * 7621) + 1) % 32768; + r3 = r % 3; + if (r3 == 0) med = eclass[fmap[lo]]; else + if (r3 == 1) med = eclass[fmap[(lo+hi)>>1]]; else + med = eclass[fmap[hi]]; + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (1) { + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unLo]] - (Int32)med; + if (n == 0) { + fswap(fmap[unLo], fmap[ltLo]); + ltLo++; unLo++; + continue; + }; + if (n > 0) break; + unLo++; + } + while (1) { + if (unLo > unHi) break; + n = (Int32)eclass[fmap[unHi]] - (Int32)med; + if (n == 0) { + fswap(fmap[unHi], fmap[gtHi]); + gtHi--; unHi--; + continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + fswap(fmap[unLo], fmap[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "fallbackQSort3(2)" ); + + if (gtHi < ltLo) continue; + + n = fmin(ltLo-lo, unLo-ltLo); fvswap(lo, unLo-n, n); + m = fmin(hi-gtHi, gtHi-unHi); fvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + if (n - lo > hi - m) { + fpush ( lo, n ); + fpush ( m, hi ); + } else { + fpush ( m, hi ); + fpush ( lo, n ); + } + } +} + +#undef fmin +#undef fpush +#undef fpop +#undef fswap +#undef fvswap +#undef FALLBACK_QSORT_SMALL_THRESH +#undef FALLBACK_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + eclass exists for [0 .. nblock-1] + ((UChar*)eclass) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)eclass) [0 .. nblock-1] holds block + All other areas of eclass destroyed + fmap [0 .. nblock-1] holds sorted order + bhtab [ 0 .. 2+(nblock/32) ] destroyed +*/ + +#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31)) +#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31)) +#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31))) +#define WORD_BH(zz) bhtab[(zz) >> 5] +#define UNALIGNED_BH(zz) ((zz) & 0x01f) + +static +void fallbackSort ( UInt32* fmap, + UInt32* eclass, + UInt32* bhtab, + Int32 nblock, + Int32 verb ) +{ + Int32 ftab[257]; + Int32 ftabCopy[256]; + Int32 H, i, j, k, l, r, cc, cc1; + Int32 nNotDone; + Int32 nBhtab; + UChar* eclass8 = (UChar*)eclass; + + /*-- + Initial 1-char radix sort to generate + initial fmap and initial BH bits. + --*/ + if (verb >= 4) + VPrintf0 ( " bucket sorting ...\n" ); + for (i = 0; i < 257; i++) ftab[i] = 0; + for (i = 0; i < nblock; i++) ftab[eclass8[i]]++; + for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i]; + for (i = 1; i < 257; i++) ftab[i] += ftab[i-1]; + + for (i = 0; i < nblock; i++) { + j = eclass8[i]; + k = ftab[j] - 1; + ftab[j] = k; + fmap[k] = i; + } + + nBhtab = 2 + (nblock / 32); + for (i = 0; i < nBhtab; i++) bhtab[i] = 0; + for (i = 0; i < 256; i++) SET_BH(ftab[i]); + + /*-- + Inductively refine the buckets. Kind-of an + "exponential radix sort" (!), inspired by the + Manber-Myers suffix array construction algorithm. + --*/ + + /*-- set sentinel bits for block-end detection --*/ + for (i = 0; i < 32; i++) { + SET_BH(nblock + 2*i); + CLEAR_BH(nblock + 2*i + 1); + } + + /*-- the log(N) loop --*/ + H = 1; + while (1) { + + if (verb >= 4) + VPrintf1 ( " depth %6d has ", H ); + + j = 0; + for (i = 0; i < nblock; i++) { + if (ISSET_BH(i)) j = i; + k = fmap[i] - H; if (k < 0) k += nblock; + eclass[k] = j; + } + + nNotDone = 0; + r = -1; + while (1) { + + /*-- find the next non-singleton bucket --*/ + k = r + 1; + while (ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (ISSET_BH(k)) { + while (WORD_BH(k) == 0xffffffff) k += 32; + while (ISSET_BH(k)) k++; + } + l = k - 1; + if (l >= nblock) break; + while (!ISSET_BH(k) && UNALIGNED_BH(k)) k++; + if (!ISSET_BH(k)) { + while (WORD_BH(k) == 0x00000000) k += 32; + while (!ISSET_BH(k)) k++; + } + r = k - 1; + if (r >= nblock) break; + + /*-- now [l, r] bracket current bucket --*/ + if (r > l) { + nNotDone += (r - l + 1); + fallbackQSort3 ( fmap, eclass, l, r ); + + /*-- scan bucket and generate header bits-- */ + cc = -1; + for (i = l; i <= r; i++) { + cc1 = eclass[fmap[i]]; + if (cc != cc1) { SET_BH(i); cc = cc1; }; + } + } + } + + if (verb >= 4) + VPrintf1 ( "%6d unresolved strings\n", nNotDone ); + + H *= 2; + if (H > nblock || nNotDone == 0) break; + } + + /*-- + Reconstruct the original block in + eclass8 [0 .. nblock-1], since the + previous phase destroyed it. + --*/ + if (verb >= 4) + VPrintf0 ( " reconstructing block ...\n" ); + j = 0; + for (i = 0; i < nblock; i++) { + while (ftabCopy[j] == 0) j++; + ftabCopy[j]--; + eclass8[fmap[i]] = (UChar)j; + } + AssertH ( j < 256, 1005 ); +} + +#undef SET_BH +#undef CLEAR_BH +#undef ISSET_BH +#undef WORD_BH +#undef UNALIGNED_BH + + +/*---------------------------------------------*/ +/*--- The main, O(N^2 log(N)) sorting ---*/ +/*--- algorithm. Faster for "normal" ---*/ +/*--- non-repetitive blocks. ---*/ +/*---------------------------------------------*/ + +/*---------------------------------------------*/ +static +__inline__ +Bool mainGtU ( UInt32 i1, + UInt32 i2, + UChar* block, + UInt16* quadrant, + UInt32 nblock, + Int32* budget ) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + + AssertD ( i1 != i2, "mainGtU" ); + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 9 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 10 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 11 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + /* 12 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + i1++; i2++; + + k = nblock + 8; + + do { + /* 1 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 2 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 3 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 4 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 5 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 6 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 7 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + /* 8 */ + c1 = block[i1]; c2 = block[i2]; + if (c1 != c2) return (c1 > c2); + s1 = quadrant[i1]; s2 = quadrant[i2]; + if (s1 != s2) return (s1 > s2); + i1++; i2++; + + if (i1 >= nblock) i1 -= nblock; + if (i2 >= nblock) i2 -= nblock; + + k -= 8; + (*budget)--; + } + while (k >= 0); + + return False; +} + + +/*---------------------------------------------*/ +/*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. +--*/ +static +Int32 incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 }; + +static +void mainSimpleSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 lo, + Int32 hi, + Int32 d, + Int32* budget ) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + + bigN = hi - lo + 1; + if (bigN < 2) return; + + hp = 0; + while (incs[hp] < bigN) hp++; + hp--; + + for (; hp >= 0; hp--) { + h = incs[hp]; + + i = lo + h; + while (True) { + + /*-- copy 1 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) break; + v = ptr[i]; + j = i; + while ( mainGtU ( + ptr[j-h]+d, v+d, block, quadrant, nblock, budget + ) ) { + ptr[j] = ptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) break; + } + ptr[j] = v; + i++; + + if (*budget < 0) return; + } + } +} + + +/*---------------------------------------------*/ +/*-- + The following is an implementation of + an elegant 3-way quicksort for strings, + described in a paper "Fast Algorithms for + Sorting and Searching Strings", by Robert + Sedgewick and Jon L. Bentley. +--*/ + +#define mswap(zz1, zz2) \ + { Int32 zztmp = zz1; zz1 = zz2; zz2 = zztmp; } + +#define mvswap(zzp1, zzp2, zzn) \ +{ \ + Int32 yyp1 = (zzp1); \ + Int32 yyp2 = (zzp2); \ + Int32 yyn = (zzn); \ + while (yyn > 0) { \ + mswap(ptr[yyp1], ptr[yyp2]); \ + yyp1++; yyp2++; yyn--; \ + } \ +} + +static +__inline__ +UChar mmed3 ( UChar a, UChar b, UChar c ) +{ + UChar t; + if (a > b) { t = a; a = b; b = t; }; + if (b > c) { + b = c; + if (a > b) b = a; + } + return b; +} + +#define mmin(a,b) ((a) < (b)) ? (a) : (b) + +#define mpush(lz,hz,dz) { stackLo[sp] = lz; \ + stackHi[sp] = hz; \ + stackD [sp] = dz; \ + sp++; } + +#define mpop(lz,hz,dz) { sp--; \ + lz = stackLo[sp]; \ + hz = stackHi[sp]; \ + dz = stackD [sp]; } + + +#define mnextsize(az) (nextHi[az]-nextLo[az]) + +#define mnextswap(az,bz) \ + { Int32 tz; \ + tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \ + tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \ + tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; } + + +#define MAIN_QSORT_SMALL_THRESH 20 +#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT) +#define MAIN_QSORT_STACK_SIZE 100 + +static +void mainQSort3 ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + Int32 nblock, + Int32 loSt, + Int32 hiSt, + Int32 dSt, + Int32* budget ) +{ + Int32 unLo, unHi, ltLo, gtHi, n, m, med; + Int32 sp, lo, hi, d; + + Int32 stackLo[MAIN_QSORT_STACK_SIZE]; + Int32 stackHi[MAIN_QSORT_STACK_SIZE]; + Int32 stackD [MAIN_QSORT_STACK_SIZE]; + + Int32 nextLo[3]; + Int32 nextHi[3]; + Int32 nextD [3]; + + sp = 0; + mpush ( loSt, hiSt, dSt ); + + while (sp > 0) { + + AssertH ( sp < MAIN_QSORT_STACK_SIZE, 1001 ); + + mpop ( lo, hi, d ); + if (hi - lo < MAIN_QSORT_SMALL_THRESH || + d > MAIN_QSORT_DEPTH_THRESH) { + mainSimpleSort ( ptr, block, quadrant, nblock, lo, hi, d, budget ); + if (*budget < 0) return; + continue; + } + + med = (Int32) + mmed3 ( block[ptr[ lo ]+d], + block[ptr[ hi ]+d], + block[ptr[ (lo+hi)>>1 ]+d] ); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (True) { + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unLo]+d]) - med; + if (n == 0) { + mswap(ptr[unLo], ptr[ltLo]); + ltLo++; unLo++; continue; + }; + if (n > 0) break; + unLo++; + } + while (True) { + if (unLo > unHi) break; + n = ((Int32)block[ptr[unHi]+d]) - med; + if (n == 0) { + mswap(ptr[unHi], ptr[gtHi]); + gtHi--; unHi--; continue; + }; + if (n < 0) break; + unHi--; + } + if (unLo > unHi) break; + mswap(ptr[unLo], ptr[unHi]); unLo++; unHi--; + } + + AssertD ( unHi == unLo-1, "mainQSort3(2)" ); + + if (gtHi < ltLo) { + mpush(lo, hi, d+1 ); + continue; + } + + n = mmin(ltLo-lo, unLo-ltLo); mvswap(lo, unLo-n, n); + m = mmin(hi-gtHi, gtHi-unHi); mvswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + nextLo[0] = lo; nextHi[0] = n; nextD[0] = d; + nextLo[1] = m; nextHi[1] = hi; nextD[1] = d; + nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1; + + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + if (mnextsize(1) < mnextsize(2)) mnextswap(1,2); + if (mnextsize(0) < mnextsize(1)) mnextswap(0,1); + + AssertD (mnextsize(0) >= mnextsize(1), "mainQSort3(8)" ); + AssertD (mnextsize(1) >= mnextsize(2), "mainQSort3(9)" ); + + mpush (nextLo[0], nextHi[0], nextD[0]); + mpush (nextLo[1], nextHi[1], nextD[1]); + mpush (nextLo[2], nextHi[2], nextD[2]); + } +} + +#undef mswap +#undef mvswap +#undef mpush +#undef mpop +#undef mmin +#undef mnextsize +#undef mnextswap +#undef MAIN_QSORT_SMALL_THRESH +#undef MAIN_QSORT_DEPTH_THRESH +#undef MAIN_QSORT_STACK_SIZE + + +/*---------------------------------------------*/ +/* Pre: + nblock > N_OVERSHOOT + block32 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)block32) [0 .. nblock-1] holds block + ptr exists for [0 .. nblock-1] + + Post: + ((UChar*)block32) [0 .. nblock-1] holds block + All other areas of block32 destroyed + ftab [0 .. 65536 ] destroyed + ptr [0 .. nblock-1] holds sorted order + if (*budget < 0), sorting was abandoned +*/ + +#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8]) +#define SETMASK (1 << 21) +#define CLEARMASK (~(SETMASK)) + +static +void mainSort ( UInt32* ptr, + UChar* block, + UInt16* quadrant, + UInt32* ftab, + Int32 nblock, + Int32 verb, + Int32* budget ) +{ + Int32 i, j, k, ss, sb; + Int32 runningOrder[256]; + Bool bigDone[256]; + Int32 copyStart[256]; + Int32 copyEnd [256]; + UChar c1; + Int32 numQSorted; + UInt16 s; + if (verb >= 4) VPrintf0 ( " main sort initialise ...\n" ); + + /*-- set up the 2-byte frequency table --*/ + for (i = 65536; i >= 0; i--) ftab[i] = 0; + + j = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + quadrant[i-1] = 0; + j = (j >> 8) | ( ((UInt16)block[i-1]) << 8); + ftab[j]++; + quadrant[i-2] = 0; + j = (j >> 8) | ( ((UInt16)block[i-2]) << 8); + ftab[j]++; + quadrant[i-3] = 0; + j = (j >> 8) | ( ((UInt16)block[i-3]) << 8); + ftab[j]++; + } + for (; i >= 0; i--) { + quadrant[i] = 0; + j = (j >> 8) | ( ((UInt16)block[i]) << 8); + ftab[j]++; + } + + /*-- (emphasises close relationship of block & quadrant) --*/ + for (i = 0; i < BZ_N_OVERSHOOT; i++) { + block [nblock+i] = block[i]; + quadrant[nblock+i] = 0; + } + + if (verb >= 4) VPrintf0 ( " bucket sorting ...\n" ); + + /*-- Complete the initial radix sort --*/ + for (i = 1; i <= 65536; i++) ftab[i] += ftab[i-1]; + + s = block[0] << 8; + i = nblock-1; + for (; i >= 3; i -= 4) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + s = (s >> 8) | (block[i-1] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-1; + s = (s >> 8) | (block[i-2] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-2; + s = (s >> 8) | (block[i-3] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i-3; + } + for (; i >= 0; i--) { + s = (s >> 8) | (block[i] << 8); + j = ftab[s] -1; + ftab[s] = j; + ptr[j] = i; + } + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + for (i = 0; i <= 255; i++) { + bigDone [i] = False; + runningOrder[i] = i; + } + + { + Int32 vv; + Int32 h = 1; + do h = 3 * h + 1; while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ( BIGFREQ(runningOrder[j-h]) > BIGFREQ(vv) ) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) goto zero; + } + zero: + runningOrder[j] = vv; + } + } while (h != 1); + } + + /*-- + The main sorting loop. + --*/ + + numQSorted = 0; + + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + Basically this is a 3-step process in which we call + mainQSort3 to sort the small buckets [ss, j], but + also make a big effort to avoid the calls if we can. + --*/ + ss = runningOrder[i]; + + /*-- + Step 1: + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j], for j != ss. + Hopefully previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + if (j != ss) { + sb = (ss << 8) + j; + if ( ! (ftab[sb] & SETMASK) ) { + Int32 lo = ftab[sb] & CLEARMASK; + Int32 hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + if (verb >= 4) + VPrintf4 ( " qsort [0x%x, 0x%x] " + "done %d this %d\n", + ss, j, numQSorted, hi - lo + 1 ); + mainQSort3 ( + ptr, block, quadrant, nblock, + lo, hi, BZ_N_RADIX, budget + ); + numQSorted += (hi - lo + 1); + if (*budget < 0) return; + } + } + ftab[sb] |= SETMASK; + } + } + + AssertH ( !bigDone[ss], 1006 ); + + /*-- + Step 2: + Now scan this big bucket [ss] so as to synthesise the + sorted order for small buckets [t, ss] for all t, + including, magically, the bucket [ss,ss] too. + This will avoid doing Real Work in subsequent Step 1's. + --*/ + { + for (j = 0; j <= 255; j++) { + copyStart[j] = ftab[(j << 8) + ss] & CLEARMASK; + copyEnd [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1; + } + for (j = ftab[ss << 8] & CLEARMASK; j < copyStart[ss]; j++) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyStart[c1]++ ] = k; + } + for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > copyEnd[ss]; j--) { + k = ptr[j]-1; if (k < 0) k += nblock; + c1 = block[k]; + if (!bigDone[c1]) + ptr[ copyEnd[c1]-- ] = k; + } + } + + AssertH ( copyStart[ss]-1 == copyEnd[ss], 1007 ); + + for (j = 0; j <= 255; j++) ftab[(j << 8) + ss] |= SETMASK; + + /*-- + Step 3: + The [ss] big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + + The quadrant array provides a way to incrementally + cache sort orderings, as they appear, so as to + make subsequent comparisons in fullGtU() complete + faster. For repetitive blocks this makes a big + difference (but not big enough to be able to avoid + the fallback sorting mechanism, exponential radix sort). + + The precise meaning is: at all times: + + for 0 <= i < nblock and 0 <= j <= nblock + + if block[i] != block[j], + + then the relative values of quadrant[i] and + quadrant[j] are meaningless. + + else { + if quadrant[i] < quadrant[j] + then the string starting at i lexicographically + precedes the string starting at j + + else if quadrant[i] > quadrant[j] + then the string starting at j lexicographically + precedes the string starting at i + + else + the relative ordering of the strings starting + at i and j has not yet been determined. + } + --*/ + bigDone[ss] = True; + + if (i < 255) { + Int32 bbStart = ftab[ss << 8] & CLEARMASK; + Int32 bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + Int32 shifts = 0; + + while ((bbSize >> shifts) > 65534) shifts++; + + for (j = bbSize-1; j >= 0; j--) { + Int32 a2update = ptr[bbStart + j]; + UInt16 qVal = (UInt16)(j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZ_N_OVERSHOOT) + quadrant[a2update + nblock] = qVal; + } + AssertH ( ((bbSize-1) >> shifts) <= 65535, 1002 ); + } + + } + + if (verb >= 4) + VPrintf3 ( " %d pointers, %d sorted, %d scanned\n", + nblock, numQSorted, nblock - numQSorted ); +} + +#undef BIGFREQ +#undef SETMASK +#undef CLEARMASK + + +/*---------------------------------------------*/ +/* Pre: + nblock > 0 + arr2 exists for [0 .. nblock-1 +N_OVERSHOOT] + ((UChar*)arr2) [0 .. nblock-1] holds block + arr1 exists for [0 .. nblock-1] + + Post: + ((UChar*)arr2) [0 .. nblock-1] holds block + All other areas of block destroyed + ftab [ 0 .. 65536 ] destroyed + arr1 [0 .. nblock-1] holds sorted order +*/ +void BZ2_blockSort ( EState* s ) +{ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt32* ftab = s->ftab; + Int32 nblock = s->nblock; + Int32 verb = s->verbosity; + Int32 wfact = s->workFactor; + UInt16* quadrant; + Int32 budget; + Int32 budgetInit; + Int32 i; + + if (nblock < 10000) { + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } else { + /* Calculate the location for quadrant, remembering to get + the alignment right. Assumes that &(block[0]) is at least + 2-byte aligned -- this should be ok since block is really + the first section of arr2. + */ + i = nblock+BZ_N_OVERSHOOT; + if (i & 1) i++; + quadrant = (UInt16*)(&(block[i])); + + /* (wfact-1) / 3 puts the default-factor-30 + transition point at very roughly the same place as + with v0.1 and v0.9.0. + Not that it particularly matters any more, since the + resulting compressed stream is now the same regardless + of whether or not we use the main sort or fallback sort. + */ + if (wfact < 1 ) wfact = 1; + if (wfact > 100) wfact = 100; + budgetInit = nblock * ((wfact-1) / 3); + budget = budgetInit; + + mainSort ( ptr, block, quadrant, ftab, nblock, verb, &budget ); + if (verb >= 3) + VPrintf3 ( " %d work, %d block, ratio %5.2f\n", + budgetInit - budget, + nblock, + (float)(budgetInit - budget) / + (float)(nblock==0 ? 1 : nblock) ); + if (budget < 0) { + if (verb >= 2) + VPrintf0 ( " too repetitive; using fallback" + " sorting algorithm\n" ); + fallbackSort ( s->arr1, s->arr2, ftab, nblock, verb ); + } + } + + s->origPtr = -1; + for (i = 0; i < s->nblock; i++) + if (ptr[i] == 0) + { s->origPtr = i; break; }; + + AssertH( s->origPtr != -1, 1003 ); +} + + +/*-------------------------------------------------------------*/ +/*--- end blocksort.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/bzip2.1 b/drivers/lib/bzip2/bzip2.1 new file mode 100644 index 0000000..7de54a0 --- /dev/null +++ b/drivers/lib/bzip2/bzip2.1 @@ -0,0 +1,439 @@ +.PU +.TH bzip2 1 +.SH NAME +bzip2, bunzip2 \- a block-sorting file compressor, v1.0 +.br +bzcat \- decompresses files to stdout +.br +bzip2recover \- recovers data from damaged bzip2 files + +.SH SYNOPSIS +.ll +8 +.B bzip2 +.RB [ " \-cdfkqstvzVL123456789 " ] +[ +.I "filenames \&..." +] +.ll -8 +.br +.B bunzip2 +.RB [ " \-fkvsVL " ] +[ +.I "filenames \&..." +] +.br +.B bzcat +.RB [ " \-s " ] +[ +.I "filenames \&..." +] +.br +.B bzip2recover +.I "filename" + +.SH DESCRIPTION +.I bzip2 +compresses files using the Burrows-Wheeler block sorting +text compression algorithm, and Huffman coding. Compression is +generally considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of the PPM +family of statistical compressors. + +The command-line options are deliberately very similar to +those of +.I GNU gzip, +but they are not identical. + +.I bzip2 +expects a list of file names to accompany the +command-line flags. Each file is replaced by a compressed version of +itself, with the name "original_name.bz2". +Each compressed file +has the same modification date, permissions, and, when possible, +ownership as the corresponding original, so that these properties can +be correctly restored at decompression time. File name handling is +naive in the sense that there is no mechanism for preserving original +file names, permissions, ownerships or dates in filesystems which lack +these concepts, or have serious file name length restrictions, such as +MS-DOS. + +.I bzip2 +and +.I bunzip2 +will by default not overwrite existing +files. If you want this to happen, specify the \-f flag. + +If no file names are specified, +.I bzip2 +compresses from standard +input to standard output. In this case, +.I bzip2 +will decline to +write compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless. + +.I bunzip2 +(or +.I bzip2 \-d) +decompresses all +specified files. Files which were not created by +.I bzip2 +will be detected and ignored, and a warning issued. +.I bzip2 +attempts to guess the filename for the decompressed file +from that of the compressed file as follows: + + filename.bz2 becomes filename + filename.bz becomes filename + filename.tbz2 becomes filename.tar + filename.tbz becomes filename.tar + anyothername becomes anyothername.out + +If the file does not end in one of the recognised endings, +.I .bz2, +.I .bz, +.I .tbz2 +or +.I .tbz, +.I bzip2 +complains that it cannot +guess the name of the original file, and uses the original name +with +.I .out +appended. + +As with compression, supplying no +filenames causes decompression from +standard input to standard output. + +.I bunzip2 +will correctly decompress a file which is the +concatenation of two or more compressed files. The result is the +concatenation of the corresponding uncompressed files. Integrity +testing (\-t) +of concatenated +compressed files is also supported. + +You can also compress or decompress files to the standard output by +giving the \-c flag. Multiple files may be compressed and +decompressed like this. The resulting outputs are fed sequentially to +stdout. Compression of multiple files +in this manner generates a stream +containing multiple compressed file representations. Such a stream +can be decompressed correctly only by +.I bzip2 +version 0.9.0 or +later. Earlier versions of +.I bzip2 +will stop after decompressing +the first file in the stream. + +.I bzcat +(or +.I bzip2 -dc) +decompresses all specified files to +the standard output. + +.I bzip2 +will read arguments from the environment variables +.I BZIP2 +and +.I BZIP, +in that order, and will process them +before any arguments read from the command line. This gives a +convenient way to supply default arguments. + +Compression is always performed, even if the compressed +file is slightly +larger than the original. Files of less than about one hundred bytes +tend to get larger, since the compression mechanism has a constant +overhead in the region of 50 bytes. Random data (including the output +of most file compressors) is coded at about 8.05 bits per byte, giving +an expansion of around 0.5%. + +As a self-check for your protection, +.I +bzip2 +uses 32-bit CRCs to +make sure that the decompressed version of a file is identical to the +original. This guards against corruption of the compressed data, and +against undetected bugs in +.I bzip2 +(hopefully very unlikely). The +chances of data corruption going undetected is microscopic, about one +chance in four billion for each file processed. Be aware, though, that +the check occurs upon decompression, so it can only tell you that +something is wrong. It can't help you +recover the original uncompressed +data. You can use +.I bzip2recover +to try to recover data from +damaged files. + +Return values: 0 for a normal exit, 1 for environmental problems (file +not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt +compressed file, 3 for an internal consistency error (eg, bug) which +caused +.I bzip2 +to panic. + +.SH OPTIONS +.TP +.B \-c --stdout +Compress or decompress to standard output. +.TP +.B \-d --decompress +Force decompression. +.I bzip2, +.I bunzip2 +and +.I bzcat +are +really the same program, and the decision about what actions to take is +done on the basis of which name is used. This flag overrides that +mechanism, and forces +.I bzip2 +to decompress. +.TP +.B \-z --compress +The complement to \-d: forces compression, regardless of the +invokation name. +.TP +.B \-t --test +Check integrity of the specified file(s), but don't decompress them. +This really performs a trial decompression and throws away the result. +.TP +.B \-f --force +Force overwrite of output files. Normally, +.I bzip2 +will not overwrite +existing output files. Also forces +.I bzip2 +to break hard links +to files, which it otherwise wouldn't do. +.TP +.B \-k --keep +Keep (don't delete) input files during compression +or decompression. +.TP +.B \-s --small +Reduce memory usage, for compression, decompression and testing. Files +are decompressed and tested using a modified algorithm which only +requires 2.5 bytes per block byte. This means any file can be +decompressed in 2300k of memory, albeit at about half the normal speed. + +During compression, \-s selects a block size of 200k, which limits +memory use to around the same figure, at the expense of your compression +ratio. In short, if your machine is low on memory (8 megabytes or +less), use \-s for everything. See MEMORY MANAGEMENT below. +.TP +.B \-q --quiet +Suppress non-essential warning messages. Messages pertaining to +I/O errors and other critical events will not be suppressed. +.TP +.B \-v --verbose +Verbose mode -- show the compression ratio for each file processed. +Further \-v's increase the verbosity level, spewing out lots of +information which is primarily of interest for diagnostic purposes. +.TP +.B \-L --license -V --version +Display the software version, license terms and conditions. +.TP +.B \-1 to \-9 +Set the block size to 100 k, 200 k .. 900 k when compressing. Has no +effect when decompressing. See MEMORY MANAGEMENT below. +.TP +.B \-- +Treats all subsequent arguments as file names, even if they start +with a dash. This is so you can handle files with names beginning +with a dash, for example: bzip2 \-- \-myfilename. +.TP +.B \--repetitive-fast --repetitive-best +These flags are redundant in versions 0.9.5 and above. They provided +some coarse control over the behaviour of the sorting algorithm in +earlier versions, which was sometimes useful. 0.9.5 and above have an +improved algorithm which renders these flags irrelevant. + +.SH MEMORY MANAGEMENT +.I bzip2 +compresses large files in blocks. The block size affects +both the compression ratio achieved, and the amount of memory needed for +compression and decompression. The flags \-1 through \-9 +specify the block size to be 100,000 bytes through 900,000 bytes (the +default) respectively. At decompression time, the block size used for +compression is read from the header of the compressed file, and +.I bunzip2 +then allocates itself just enough memory to decompress +the file. Since block sizes are stored in compressed files, it follows +that the flags \-1 to \-9 are irrelevant to and so ignored +during decompression. + +Compression and decompression requirements, +in bytes, can be estimated as: + + Compression: 400k + ( 8 x block size ) + + Decompression: 100k + ( 4 x block size ), or + 100k + ( 2.5 x block size ) + +Larger block sizes give rapidly diminishing marginal returns. Most of +the compression comes from the first two or three hundred k of block +size, a fact worth bearing in mind when using +.I bzip2 +on small machines. +It is also important to appreciate that the decompression memory +requirement is set at compression time by the choice of block size. + +For files compressed with the default 900k block size, +.I bunzip2 +will require about 3700 kbytes to decompress. To support decompression +of any file on a 4 megabyte machine, +.I bunzip2 +has an option to +decompress using approximately half this amount of memory, about 2300 +kbytes. Decompression speed is also halved, so you should use this +option only where necessary. The relevant flag is -s. + +In general, try and use the largest block size memory constraints allow, +since that maximises the compression achieved. Compression and +decompression speed are virtually unaffected by block size. + +Another significant point applies to files which fit in a single block +-- that means most files you'd encounter using a large block size. The +amount of real memory touched is proportional to the size of the file, +since the file is smaller than a block. For example, compressing a file +20,000 bytes long with the flag -9 will cause the compressor to +allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 +kbytes of it. Similarly, the decompressor will allocate 3700k but only +touch 100k + 20000 * 4 = 180 kbytes. + +Here is a table which summarises the maximum memory usage for different +block sizes. Also recorded is the total compressed size for 14 files of +the Calgary Text Compression Corpus totalling 3,141,622 bytes. This +column gives some feel for how compression varies with block size. +These figures tend to understate the advantage of larger block sizes for +larger files, since the Corpus is dominated by smaller files. + + Compress Decompress Decompress Corpus + Flag usage usage -s usage Size + + -1 1200k 500k 350k 914704 + -2 2000k 900k 600k 877703 + -3 2800k 1300k 850k 860338 + -4 3600k 1700k 1100k 846899 + -5 4400k 2100k 1350k 845160 + -6 5200k 2500k 1600k 838626 + -7 6100k 2900k 1850k 834096 + -8 6800k 3300k 2100k 828642 + -9 7600k 3700k 2350k 828642 + +.SH RECOVERING DATA FROM DAMAGED FILES +.I bzip2 +compresses files in blocks, usually 900kbytes long. Each +block is handled independently. If a media or transmission error causes +a multi-block .bz2 +file to become damaged, it may be possible to +recover data from the undamaged blocks in the file. + +The compressed representation of each block is delimited by a 48-bit +pattern, which makes it possible to find the block boundaries with +reasonable certainty. Each block also carries its own 32-bit CRC, so +damaged blocks can be distinguished from undamaged ones. + +.I bzip2recover +is a simple program whose purpose is to search for +blocks in .bz2 files, and write each block out into its own .bz2 +file. You can then use +.I bzip2 +\-t +to test the +integrity of the resulting files, and decompress those which are +undamaged. + +.I bzip2recover +takes a single argument, the name of the damaged file, +and writes a number of files "rec0001file.bz2", +"rec0002file.bz2", etc, containing the extracted blocks. +The output filenames are designed so that the use of +wildcards in subsequent processing -- for example, +"bzip2 -dc rec*file.bz2 > recovered_data" -- lists the files in +the correct order. + +.I bzip2recover +should be of most use dealing with large .bz2 +files, as these will contain many blocks. It is clearly +futile to use it on damaged single-block files, since a +damaged block cannot be recovered. If you wish to minimise +any potential data loss through media or transmission errors, +you might consider compressing with a smaller +block size. + +.SH PERFORMANCE NOTES +The sorting phase of compression gathers together similar strings in the +file. Because of this, files containing very long runs of repeated +symbols, like "aabaabaabaab ..." (repeated several hundred times) may +compress more slowly than normal. Versions 0.9.5 and above fare much +better than previous versions in this respect. The ratio between +worst-case and average-case compression time is in the region of 10:1. +For previous versions, this figure was more like 100:1. You can use the +\-vvvv option to monitor progress in great detail, if you want. + +Decompression speed is unaffected by these phenomena. + +.I bzip2 +usually allocates several megabytes of memory to operate +in, and then charges all over it in a fairly random fashion. This means +that performance, both for compressing and decompressing, is largely +determined by the speed at which your machine can service cache misses. +Because of this, small changes to the code to reduce the miss rate have +been observed to give disproportionately large performance improvements. +I imagine +.I bzip2 +will perform best on machines with very large caches. + +.SH CAVEATS +I/O error messages are not as helpful as they could be. +.I bzip2 +tries hard to detect I/O errors and exit cleanly, but the details of +what the problem is sometimes seem rather misleading. + +This manual page pertains to version 1.0 of +.I bzip2. +Compressed +data created by this version is entirely forwards and backwards +compatible with the previous public releases, versions 0.1pl2, 0.9.0 +and 0.9.5, +but with the following exception: 0.9.0 and above can correctly +decompress multiple concatenated compressed files. 0.1pl2 cannot do +this; it will stop after decompressing just the first file in the +stream. + +.I bzip2recover +uses 32-bit integers to represent bit positions in +compressed files, so it cannot handle compressed files more than 512 +megabytes long. This could easily be fixed. + +.SH AUTHOR +Julian Seward, jseward@acm.org. + +http://sourceware.cygnus.com/bzip2 +http://www.muraroa.demon.co.uk + +The ideas embodied in +.I bzip2 +are due to (at least) the following +people: Michael Burrows and David Wheeler (for the block sorting +transformation), David Wheeler (again, for the Huffman coder), Peter +Fenwick (for the structured coding model in the original +.I bzip, +and many refinements), and Alistair Moffat, Radford Neal and Ian Witten +(for the arithmetic coder in the original +.I bzip). +I am much +indebted for their help, support and advice. See the manual in the +source distribution for pointers to sources of documentation. Christian +von Roques encouraged me to look for faster sorting algorithms, so as to +speed up compression. Bela Lubkin encouraged me to improve the +worst-case compression performance. Many people sent patches, helped +with portability problems, lent machines, gave advice and were generally +helpful. diff --git a/drivers/lib/bzip2/bzip2.1.preformatted b/drivers/lib/bzip2/bzip2.1.preformatted new file mode 100644 index 0000000..9f18339 --- /dev/null +++ b/drivers/lib/bzip2/bzip2.1.preformatted @@ -0,0 +1,462 @@ + + + +bzip2(1) bzip2(1) + + +NNAAMMEE + bzip2, bunzip2 - a block-sorting file compressor, v1.0 + bzcat - decompresses files to stdout + bzip2recover - recovers data from damaged bzip2 files + + +SSYYNNOOPPSSIISS + bbzziipp22 [ --ccddffkkqqssttvvzzVVLL112233445566778899 ] [ _f_i_l_e_n_a_m_e_s _._._. ] + bbuunnzziipp22 [ --ffkkvvssVVLL ] [ _f_i_l_e_n_a_m_e_s _._._. ] + bbzzccaatt [ --ss ] [ _f_i_l_e_n_a_m_e_s _._._. ] + bbzziipp22rreeccoovveerr _f_i_l_e_n_a_m_e + + +DDEESSCCRRIIPPTTIIOONN + _b_z_i_p_2 compresses files using the Burrows-Wheeler block + sorting text compression algorithm, and Huffman coding. + Compression is generally considerably better than that + achieved by more conventional LZ77/LZ78-based compressors, + and approaches the performance of the PPM family of sta- + tistical compressors. + + The command-line options are deliberately very similar to + those of _G_N_U _g_z_i_p_, but they are not identical. + + _b_z_i_p_2 expects a list of file names to accompany the com- + mand-line flags. Each file is replaced by a compressed + version of itself, with the name "original_name.bz2". + Each compressed file has the same modification date, per- + missions, and, when possible, ownership as the correspond- + ing original, so that these properties can be correctly + restored at decompression time. File name handling is + naive in the sense that there is no mechanism for preserv- + ing original file names, permissions, ownerships or dates + in filesystems which lack these concepts, or have serious + file name length restrictions, such as MS-DOS. + + _b_z_i_p_2 and _b_u_n_z_i_p_2 will by default not overwrite existing + files. If you want this to happen, specify the -f flag. + + If no file names are specified, _b_z_i_p_2 compresses from + standard input to standard output. In this case, _b_z_i_p_2 + will decline to write compressed output to a terminal, as + this would be entirely incomprehensible and therefore + pointless. + + _b_u_n_z_i_p_2 (or _b_z_i_p_2 _-_d_) decompresses all specified files. + Files which were not created by _b_z_i_p_2 will be detected and + ignored, and a warning issued. _b_z_i_p_2 attempts to guess + the filename for the decompressed file from that of the + compressed file as follows: + + filename.bz2 becomes filename + filename.bz becomes filename + filename.tbz2 becomes filename.tar + + + + 1 + + + + + +bzip2(1) bzip2(1) + + + filename.tbz becomes filename.tar + anyothername becomes anyothername.out + + If the file does not end in one of the recognised endings, + _._b_z_2_, _._b_z_, _._t_b_z_2 or _._t_b_z_, _b_z_i_p_2 complains that it cannot + guess the name of the original file, and uses the original + name with _._o_u_t appended. + + As with compression, supplying no filenames causes decom- + pression from standard input to standard output. + + _b_u_n_z_i_p_2 will correctly decompress a file which is the con- + catenation of two or more compressed files. The result is + the concatenation of the corresponding uncompressed files. + Integrity testing (-t) of concatenated compressed files is + also supported. + + You can also compress or decompress files to the standard + output by giving the -c flag. Multiple files may be com- + pressed and decompressed like this. The resulting outputs + are fed sequentially to stdout. Compression of multiple + files in this manner generates a stream containing multi- + ple compressed file representations. Such a stream can be + decompressed correctly only by _b_z_i_p_2 version 0.9.0 or + later. Earlier versions of _b_z_i_p_2 will stop after decom- + pressing the first file in the stream. + + _b_z_c_a_t (or _b_z_i_p_2 _-_d_c_) decompresses all specified files to + the standard output. + + _b_z_i_p_2 will read arguments from the environment variables + _B_Z_I_P_2 and _B_Z_I_P_, in that order, and will process them + before any arguments read from the command line. This + gives a convenient way to supply default arguments. + + Compression is always performed, even if the compressed + file is slightly larger than the original. Files of less + than about one hundred bytes tend to get larger, since the + compression mechanism has a constant overhead in the + region of 50 bytes. Random data (including the output of + most file compressors) is coded at about 8.05 bits per + byte, giving an expansion of around 0.5%. + + As a self-check for your protection, _b_z_i_p_2 uses 32-bit + CRCs to make sure that the decompressed version of a file + is identical to the original. This guards against corrup- + tion of the compressed data, and against undetected bugs + in _b_z_i_p_2 (hopefully very unlikely). The chances of data + corruption going undetected is microscopic, about one + chance in four billion for each file processed. Be aware, + though, that the check occurs upon decompression, so it + can only tell you that something is wrong. It can't help + you recover the original uncompressed data. You can use + _b_z_i_p_2_r_e_c_o_v_e_r to try to recover data from damaged files. + + + + 2 + + + + + +bzip2(1) bzip2(1) + + + Return values: 0 for a normal exit, 1 for environmental + problems (file not found, invalid flags, I/O errors, &c), + 2 to indicate a corrupt compressed file, 3 for an internal + consistency error (eg, bug) which caused _b_z_i_p_2 to panic. + + +OOPPTTIIOONNSS + --cc ----ssttddoouutt + Compress or decompress to standard output. + + --dd ----ddeeccoommpprreessss + Force decompression. _b_z_i_p_2_, _b_u_n_z_i_p_2 and _b_z_c_a_t are + really the same program, and the decision about + what actions to take is done on the basis of which + name is used. This flag overrides that mechanism, + and forces _b_z_i_p_2 to decompress. + + --zz ----ccoommpprreessss + The complement to -d: forces compression, regard- + less of the invokation name. + + --tt ----tteesstt + Check integrity of the specified file(s), but don't + decompress them. This really performs a trial + decompression and throws away the result. + + --ff ----ffoorrccee + Force overwrite of output files. Normally, _b_z_i_p_2 + will not overwrite existing output files. Also + forces _b_z_i_p_2 to break hard links to files, which it + otherwise wouldn't do. + + --kk ----kkeeeepp + Keep (don't delete) input files during compression + or decompression. + + --ss ----ssmmaallll + Reduce memory usage, for compression, decompression + and testing. Files are decompressed and tested + using a modified algorithm which only requires 2.5 + bytes per block byte. This means any file can be + decompressed in 2300k of memory, albeit at about + half the normal speed. + + During compression, -s selects a block size of + 200k, which limits memory use to around the same + figure, at the expense of your compression ratio. + In short, if your machine is low on memory (8 + megabytes or less), use -s for everything. See + MEMORY MANAGEMENT below. + + --qq ----qquuiieett + Suppress non-essential warning messages. Messages + pertaining to I/O errors and other critical events + + + + 3 + + + + + +bzip2(1) bzip2(1) + + + will not be suppressed. + + --vv ----vveerrbboossee + Verbose mode -- show the compression ratio for each + file processed. Further -v's increase the ver- + bosity level, spewing out lots of information which + is primarily of interest for diagnostic purposes. + + --LL ----lliicceennssee --VV ----vveerrssiioonn + Display the software version, license terms and + conditions. + + --11 ttoo --99 + Set the block size to 100 k, 200 k .. 900 k when + compressing. Has no effect when decompressing. + See MEMORY MANAGEMENT below. + + ---- Treats all subsequent arguments as file names, even + if they start with a dash. This is so you can han- + dle files with names beginning with a dash, for + example: bzip2 -- -myfilename. + + ----rreeppeettiittiivvee--ffaasstt ----rreeppeettiittiivvee--bbeesstt + These flags are redundant in versions 0.9.5 and + above. They provided some coarse control over the + behaviour of the sorting algorithm in earlier ver- + sions, which was sometimes useful. 0.9.5 and above + have an improved algorithm which renders these + flags irrelevant. + + +MMEEMMOORRYY MMAANNAAGGEEMMEENNTT + _b_z_i_p_2 compresses large files in blocks. The block size + affects both the compression ratio achieved, and the + amount of memory needed for compression and decompression. + The flags -1 through -9 specify the block size to be + 100,000 bytes through 900,000 bytes (the default) respec- + tively. At decompression time, the block size used for + compression is read from the header of the compressed + file, and _b_u_n_z_i_p_2 then allocates itself just enough memory + to decompress the file. Since block sizes are stored in + compressed files, it follows that the flags -1 to -9 are + irrelevant to and so ignored during decompression. + + Compression and decompression requirements, in bytes, can + be estimated as: + + Compression: 400k + ( 8 x block size ) + + Decompression: 100k + ( 4 x block size ), or + 100k + ( 2.5 x block size ) + + Larger block sizes give rapidly diminishing marginal + returns. Most of the compression comes from the first two + + + + 4 + + + + + +bzip2(1) bzip2(1) + + + or three hundred k of block size, a fact worth bearing in + mind when using _b_z_i_p_2 on small machines. It is also + important to appreciate that the decompression memory + requirement is set at compression time by the choice of + block size. + + For files compressed with the default 900k block size, + _b_u_n_z_i_p_2 will require about 3700 kbytes to decompress. To + support decompression of any file on a 4 megabyte machine, + _b_u_n_z_i_p_2 has an option to decompress using approximately + half this amount of memory, about 2300 kbytes. Decompres- + sion speed is also halved, so you should use this option + only where necessary. The relevant flag is -s. + + In general, try and use the largest block size memory con- + straints allow, since that maximises the compression + achieved. Compression and decompression speed are virtu- + ally unaffected by block size. + + Another significant point applies to files which fit in a + single block -- that means most files you'd encounter + using a large block size. The amount of real memory + touched is proportional to the size of the file, since the + file is smaller than a block. For example, compressing a + file 20,000 bytes long with the flag -9 will cause the + compressor to allocate around 7600k of memory, but only + touch 400k + 20000 * 8 = 560 kbytes of it. Similarly, the + decompressor will allocate 3700k but only touch 100k + + 20000 * 4 = 180 kbytes. + + Here is a table which summarises the maximum memory usage + for different block sizes. Also recorded is the total + compressed size for 14 files of the Calgary Text Compres- + sion Corpus totalling 3,141,622 bytes. This column gives + some feel for how compression varies with block size. + These figures tend to understate the advantage of larger + block sizes for larger files, since the Corpus is domi- + nated by smaller files. + + Compress Decompress Decompress Corpus + Flag usage usage -s usage Size + + -1 1200k 500k 350k 914704 + -2 2000k 900k 600k 877703 + -3 2800k 1300k 850k 860338 + -4 3600k 1700k 1100k 846899 + -5 4400k 2100k 1350k 845160 + -6 5200k 2500k 1600k 838626 + -7 6100k 2900k 1850k 834096 + -8 6800k 3300k 2100k 828642 + -9 7600k 3700k 2350k 828642 + + + + + + + 5 + + + + + +bzip2(1) bzip2(1) + + +RREECCOOVVEERRIINNGG DDAATTAA FFRROOMM DDAAMMAAGGEEDD FFIILLEESS + _b_z_i_p_2 compresses files in blocks, usually 900kbytes long. + Each block is handled independently. If a media or trans- + mission error causes a multi-block .bz2 file to become + damaged, it may be possible to recover data from the + undamaged blocks in the file. + + The compressed representation of each block is delimited + by a 48-bit pattern, which makes it possible to find the + block boundaries with reasonable certainty. Each block + also carries its own 32-bit CRC, so damaged blocks can be + distinguished from undamaged ones. + + _b_z_i_p_2_r_e_c_o_v_e_r is a simple program whose purpose is to + search for blocks in .bz2 files, and write each block out + into its own .bz2 file. You can then use _b_z_i_p_2 -t to test + the integrity of the resulting files, and decompress those + which are undamaged. + + _b_z_i_p_2_r_e_c_o_v_e_r takes a single argument, the name of the dam- + aged file, and writes a number of files "rec0001file.bz2", + "rec0002file.bz2", etc, containing the extracted blocks. + The output filenames are designed so that the use of + wildcards in subsequent processing -- for example, "bzip2 + -dc rec*file.bz2 > recovered_data" -- lists the files in + the correct order. + + _b_z_i_p_2_r_e_c_o_v_e_r should be of most use dealing with large .bz2 + files, as these will contain many blocks. It is clearly + futile to use it on damaged single-block files, since a + damaged block cannot be recovered. If you wish to min- + imise any potential data loss through media or transmis- + sion errors, you might consider compressing with a smaller + block size. + + +PPEERRFFOORRMMAANNCCEE NNOOTTEESS + The sorting phase of compression gathers together similar + strings in the file. Because of this, files containing + very long runs of repeated symbols, like "aabaabaabaab + ..." (repeated several hundred times) may compress more + slowly than normal. Versions 0.9.5 and above fare much + better than previous versions in this respect. The ratio + between worst-case and average-case compression time is in + the region of 10:1. For previous versions, this figure + was more like 100:1. You can use the -vvvv option to mon- + itor progress in great detail, if you want. + + Decompression speed is unaffected by these phenomena. + + _b_z_i_p_2 usually allocates several megabytes of memory to + operate in, and then charges all over it in a fairly ran- + dom fashion. This means that performance, both for com- + pressing and decompressing, is largely determined by the + + + + 6 + + + + + +bzip2(1) bzip2(1) + + + speed at which your machine can service cache misses. + Because of this, small changes to the code to reduce the + miss rate have been observed to give disproportionately + large performance improvements. I imagine _b_z_i_p_2 will per- + form best on machines with very large caches. + + +CCAAVVEEAATTSS + I/O error messages are not as helpful as they could be. + _b_z_i_p_2 tries hard to detect I/O errors and exit cleanly, + but the details of what the problem is sometimes seem + rather misleading. + + This manual page pertains to version 1.0 of _b_z_i_p_2_. Com- + pressed data created by this version is entirely forwards + and backwards compatible with the previous public + releases, versions 0.1pl2, 0.9.0 and 0.9.5, but with the + following exception: 0.9.0 and above can correctly decom- + press multiple concatenated compressed files. 0.1pl2 can- + not do this; it will stop after decompressing just the + first file in the stream. + + _b_z_i_p_2_r_e_c_o_v_e_r uses 32-bit integers to represent bit posi- + tions in compressed files, so it cannot handle compressed + files more than 512 megabytes long. This could easily be + fixed. + + +AAUUTTHHOORR + Julian Seward, jseward@acm.org. + + http://sourceware.cygnus.com/bzip2 + http://www.muraroa.demon.co.uk + + The ideas embodied in _b_z_i_p_2 are due to (at least) the fol- + lowing people: Michael Burrows and David Wheeler (for the + block sorting transformation), David Wheeler (again, for + the Huffman coder), Peter Fenwick (for the structured cod- + ing model in the original _b_z_i_p_, and many refinements), and + Alistair Moffat, Radford Neal and Ian Witten (for the + arithmetic coder in the original _b_z_i_p_)_. I am much + indebted for their help, support and advice. See the man- + ual in the source distribution for pointers to sources of + documentation. Christian von Roques encouraged me to look + for faster sorting algorithms, so as to speed up compres- + sion. Bela Lubkin encouraged me to improve the worst-case + compression performance. Many people sent patches, helped + with portability problems, lent machines, gave advice and + were generally helpful. + + + + + + + + + 7 + + diff --git a/drivers/lib/bzip2/bzip2.c b/drivers/lib/bzip2/bzip2.c new file mode 100644 index 0000000..56adfdc --- /dev/null +++ b/drivers/lib/bzip2/bzip2.c @@ -0,0 +1,2044 @@ + +/*-----------------------------------------------------------*/ +/*--- A block-sorting, lossless compressor bzip2.c ---*/ +/*-----------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +/*----------------------------------------------------*/ +/*--- IMPORTANT ---*/ +/*----------------------------------------------------*/ + +/*-- + WARNING: + This program and library (attempts to) compress data by + performing several non-trivial transformations on it. + Unless you are 100% familiar with *all* the algorithms + contained herein, and with the consequences of modifying them, + you should NOT meddle with the compression or decompression + machinery. Incorrect changes can and very likely *will* + lead to disasterous loss of data. + + DISCLAIMER: + I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE + USE OF THIS PROGRAM, HOWSOEVER CAUSED. + + Every compression of a file implies an assumption that the + compressed file can be decompressed to reproduce the original. + Great efforts in design, coding and testing have been made to + ensure that this program works correctly. However, the + complexity of the algorithms, and, in particular, the presence + of various special cases in the code which occur with very low + but non-zero probability make it impossible to rule out the + possibility of bugs remaining in the program. DO NOT COMPRESS + ANY DATA WITH THIS PROGRAM AND/OR LIBRARY UNLESS YOU ARE PREPARED + TO ACCEPT THE POSSIBILITY, HOWEVER SMALL, THAT THE DATA WILL + NOT BE RECOVERABLE. + + That is not to say this program is inherently unreliable. + Indeed, I very much hope the opposite is true. bzip2/libbzip2 + has been carefully constructed and extensively tested. + + PATENTS: + To the best of my knowledge, bzip2/libbzip2 does not use any + patented algorithms. However, I do not have the resources + available to carry out a full patent search. Therefore I cannot + give any guarantee of the above statement. +--*/ + + + +/*----------------------------------------------------*/ +/*--- and now for something much more pleasant :-) ---*/ +/*----------------------------------------------------*/ + +/*---------------------------------------------*/ +/*-- + Place a 1 beside your platform, and 0 elsewhere. +--*/ + +/*-- + Generic 32-bit Unix. + Also works on 64-bit Unix boxes. +--*/ +#define BZ_UNIX 1 + +/*-- + Win32, as seen by Jacob Navia's excellent + port of (Chris Fraser & David Hanson)'s excellent + lcc compiler. +--*/ +#define BZ_LCCWIN32 0 + +#if defined(_WIN32) && !defined(__CYGWIN__) +#undef BZ_LCCWIN32 +#define BZ_LCCWIN32 1 +#undef BZ_UNIX +#define BZ_UNIX 0 +#endif + + +/*---------------------------------------------*/ +/*-- + Some stuff for all platforms. +--*/ + +#include +#include +#include +#include +#include +#include +#include +#include "bzlib.h" + +#define ERROR_IF_EOF(i) { if ((i) == EOF) ioError(); } +#define ERROR_IF_NOT_ZERO(i) { if ((i) != 0) ioError(); } +#define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); } + + +/*---------------------------------------------*/ +/*-- + Platform-specific stuff. +--*/ + +#if BZ_UNIX +# include +# include +# include +# include +# include + +# define PATH_SEP '/' +# define MY_LSTAT lstat +# define MY_S_IFREG S_ISREG +# define MY_STAT stat + +# define APPEND_FILESPEC(root, name) \ + root=snocString((root), (name)) + +# define APPEND_FLAG(root, name) \ + root=snocString((root), (name)) + +# define SET_BINARY_MODE(fd) /**/ + +# ifdef __GNUC__ +# define NORETURN __attribute__ ((noreturn)) +# else +# define NORETURN /**/ +# endif +# ifdef __DJGPP__ +# include +# include +# undef MY_LSTAT +# define MY_LSTAT stat +# undef SET_BINARY_MODE +# define SET_BINARY_MODE(fd) \ + do { \ + int retVal = setmode ( fileno ( fd ), \ + O_BINARY ); \ + ERROR_IF_MINUS_ONE ( retVal ); \ + } while ( 0 ) +# endif +# ifdef __CYGWIN__ +# include +# include +# undef SET_BINARY_MODE +# define SET_BINARY_MODE(fd) \ + do { \ + int retVal = setmode ( fileno ( fd ), \ + O_BINARY ); \ + ERROR_IF_MINUS_ONE ( retVal ); \ + } while ( 0 ) +# endif +#endif + + + +#if BZ_LCCWIN32 +# include +# include +# include + +# define NORETURN /**/ +# define PATH_SEP '\\' +# define MY_LSTAT _stat +# define MY_STAT _stat +# define MY_S_IFREG(x) ((x) & _S_IFREG) + +# define APPEND_FLAG(root, name) \ + root=snocString((root), (name)) + +# if 0 + /*-- lcc-win32 seems to expand wildcards itself --*/ +# define APPEND_FILESPEC(root, spec) \ + do { \ + if ((spec)[0] == '-') { \ + root = snocString((root), (spec)); \ + } else { \ + struct _finddata_t c_file; \ + long hFile; \ + hFile = _findfirst((spec), &c_file); \ + if ( hFile == -1L ) { \ + root = snocString ((root), (spec)); \ + } else { \ + int anInt = 0; \ + while ( anInt == 0 ) { \ + root = snocString((root), \ + &c_file.name[0]); \ + anInt = _findnext(hFile, &c_file); \ + } \ + } \ + } \ + } while ( 0 ) +# else +# define APPEND_FILESPEC(root, name) \ + root = snocString ((root), (name)) +# endif + +# define SET_BINARY_MODE(fd) \ + do { \ + int retVal = setmode ( fileno ( fd ), \ + O_BINARY ); \ + ERROR_IF_MINUS_ONE ( retVal ); \ + } while ( 0 ) + +#endif + + +/*---------------------------------------------*/ +/*-- + Some more stuff for all platforms :-) +--*/ + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +/*-- + IntNative is your platform's `native' int size. + Only here to avoid probs with 64-bit platforms. +--*/ +typedef int IntNative; + + +/*---------------------------------------------------*/ +/*--- Misc (file handling) data decls ---*/ +/*---------------------------------------------------*/ + +Int32 verbosity; +Bool keepInputFiles, smallMode, deleteOutputOnInterrupt; +Bool forceOverwrite, testFailsExist, unzFailsExist, noisy; +Int32 numFileNames, numFilesProcessed, blockSize100k; +Int32 exitValue; + +/*-- source modes; F==file, I==stdin, O==stdout --*/ +#define SM_I2O 1 +#define SM_F2O 2 +#define SM_F2F 3 + +/*-- operation modes --*/ +#define OM_Z 1 +#define OM_UNZ 2 +#define OM_TEST 3 + +Int32 opMode; +Int32 srcMode; + +#define FILE_NAME_LEN 1034 + +Int32 longestFileName; +Char inName [FILE_NAME_LEN]; +Char outName[FILE_NAME_LEN]; +Char tmpName[FILE_NAME_LEN]; +Char *progName; +Char progNameReally[FILE_NAME_LEN]; +FILE *outputHandleJustInCase; +Int32 workFactor; + +static void panic ( Char* ) NORETURN; +static void ioError ( void ) NORETURN; +static void outOfMemory ( void ) NORETURN; +static void configError ( void ) NORETURN; +static void crcError ( void ) NORETURN; +static void cleanUpAndFail ( Int32 ) NORETURN; +static void compressedStreamEOF ( void ) NORETURN; + +static void copyFileName ( Char*, Char* ); +static void* myMalloc ( Int32 ); + + + +/*---------------------------------------------------*/ +/*--- An implementation of 64-bit ints. Sigh. ---*/ +/*--- Roll on widespread deployment of ANSI C9X ! ---*/ +/*---------------------------------------------------*/ + +typedef + struct { UChar b[8]; } + UInt64; + +static +void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 ) +{ + n->b[7] = (UChar)((hi32 >> 24) & 0xFF); + n->b[6] = (UChar)((hi32 >> 16) & 0xFF); + n->b[5] = (UChar)((hi32 >> 8) & 0xFF); + n->b[4] = (UChar) (hi32 & 0xFF); + n->b[3] = (UChar)((lo32 >> 24) & 0xFF); + n->b[2] = (UChar)((lo32 >> 16) & 0xFF); + n->b[1] = (UChar)((lo32 >> 8) & 0xFF); + n->b[0] = (UChar) (lo32 & 0xFF); +} + +static +double uInt64_to_double ( UInt64* n ) +{ + Int32 i; + double base = 1.0; + double sum = 0.0; + for (i = 0; i < 8; i++) { + sum += base * (double)(n->b[i]); + base *= 256.0; + } + return sum; +} + +static +void uInt64_add ( UInt64* src, UInt64* dst ) +{ + Int32 i; + Int32 carry = 0; + for (i = 0; i < 8; i++) { + carry += ( ((Int32)src->b[i]) + ((Int32)dst->b[i]) ); + dst->b[i] = (UChar)(carry & 0xFF); + carry >>= 8; + } +} + +static +void uInt64_sub ( UInt64* src, UInt64* dst ) +{ + Int32 t, i; + Int32 borrow = 0; + for (i = 0; i < 8; i++) { + t = ((Int32)dst->b[i]) - ((Int32)src->b[i]) - borrow; + if (t < 0) { + dst->b[i] = (UChar)(t + 256); + borrow = 1; + } else { + dst->b[i] = (UChar)t; + borrow = 0; + } + } +} + +static +void uInt64_mul ( UInt64* a, UInt64* b, UInt64* r_hi, UInt64* r_lo ) +{ + UChar sum[16]; + Int32 ia, ib, carry; + for (ia = 0; ia < 16; ia++) sum[ia] = 0; + for (ia = 0; ia < 8; ia++) { + carry = 0; + for (ib = 0; ib < 8; ib++) { + carry += ( ((Int32)sum[ia+ib]) + + ((Int32)a->b[ia]) * ((Int32)b->b[ib]) ); + sum[ia+ib] = (UChar)(carry & 0xFF); + carry >>= 8; + } + sum[ia+8] = (UChar)(carry & 0xFF); + if ((carry >>= 8) != 0) panic ( "uInt64_mul" ); + } + + for (ia = 0; ia < 8; ia++) r_hi->b[ia] = sum[ia+8]; + for (ia = 0; ia < 8; ia++) r_lo->b[ia] = sum[ia]; +} + + +static +void uInt64_shr1 ( UInt64* n ) +{ + Int32 i; + for (i = 0; i < 8; i++) { + n->b[i] >>= 1; + if (i < 7 && (n->b[i+1] & 1)) n->b[i] |= 0x80; + } +} + +static +void uInt64_shl1 ( UInt64* n ) +{ + Int32 i; + for (i = 7; i >= 0; i--) { + n->b[i] <<= 1; + if (i > 0 && (n->b[i-1] & 0x80)) n->b[i]++; + } +} + +static +Bool uInt64_isZero ( UInt64* n ) +{ + Int32 i; + for (i = 0; i < 8; i++) + if (n->b[i] != 0) return 0; + return 1; +} + +static +Int32 uInt64_qrm10 ( UInt64* n ) +{ + /* Divide *n by 10, and return the remainder. Long division + is difficult, so we cheat and instead multiply by + 0xCCCC CCCC CCCC CCCD, which is 0.8 (viz, 0.1 << 3). + */ + Int32 i; + UInt64 tmp1, tmp2, n_orig, zero_point_eight; + + zero_point_eight.b[1] = zero_point_eight.b[2] = + zero_point_eight.b[3] = zero_point_eight.b[4] = + zero_point_eight.b[5] = zero_point_eight.b[6] = + zero_point_eight.b[7] = 0xCC; + zero_point_eight.b[0] = 0xCD; + + n_orig = *n; + + /* divide n by 10, + by multiplying by 0.8 and then shifting right 3 times */ + uInt64_mul ( n, &zero_point_eight, &tmp1, &tmp2 ); + uInt64_shr1(&tmp1); uInt64_shr1(&tmp1); uInt64_shr1(&tmp1); + *n = tmp1; + + /* tmp1 = 8*n, tmp2 = 2*n */ + uInt64_shl1(&tmp1); uInt64_shl1(&tmp1); uInt64_shl1(&tmp1); + tmp2 = *n; uInt64_shl1(&tmp2); + + /* tmp1 = 10*n */ + uInt64_add ( &tmp2, &tmp1 ); + + /* n_orig = n_orig - 10*n */ + uInt64_sub ( &tmp1, &n_orig ); + + /* n_orig should now hold quotient, in range 0 .. 9 */ + for (i = 7; i >= 1; i--) + if (n_orig.b[i] != 0) panic ( "uInt64_qrm10(1)" ); + if (n_orig.b[0] > 9) + panic ( "uInt64_qrm10(2)" ); + + return (int)n_orig.b[0]; +} + +/* ... and the Whole Entire Point of all this UInt64 stuff is + so that we can supply the following function. +*/ +static +void uInt64_toAscii ( char* outbuf, UInt64* n ) +{ + Int32 i, q; + UChar buf[32]; + Int32 nBuf = 0; + UInt64 n_copy = *n; + do { + q = uInt64_qrm10 ( &n_copy ); + buf[nBuf] = q + '0'; + nBuf++; + } while (!uInt64_isZero(&n_copy)); + outbuf[nBuf] = 0; + for (i = 0; i < nBuf; i++) outbuf[i] = buf[nBuf-i-1]; +} + + +/*---------------------------------------------------*/ +/*--- Processing of complete files and streams ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +static +Bool myfeof ( FILE* f ) +{ + Int32 c = fgetc ( f ); + if (c == EOF) return True; + ungetc ( c, f ); + return False; +} + + +/*---------------------------------------------*/ +static +void compressStream ( FILE *stream, FILE *zStream ) +{ + BZFILE* bzf = NULL; + UChar ibuf[5000]; + Int32 nIbuf; + UInt32 nbytes_in_lo32, nbytes_in_hi32; + UInt32 nbytes_out_lo32, nbytes_out_hi32; + Int32 bzerr, bzerr_dummy, ret; + + SET_BINARY_MODE(stream); + SET_BINARY_MODE(zStream); + + if (ferror(stream)) goto errhandler_io; + if (ferror(zStream)) goto errhandler_io; + + bzf = BZ2_bzWriteOpen ( &bzerr, zStream, + blockSize100k, verbosity, workFactor ); + if (bzerr != BZ_OK) goto errhandler; + + if (verbosity >= 2) fprintf ( stderr, "\n" ); + + while (True) { + + if (myfeof(stream)) break; + nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream ); + if (ferror(stream)) goto errhandler_io; + if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf ); + if (bzerr != BZ_OK) goto errhandler; + + } + + BZ2_bzWriteClose64 ( &bzerr, bzf, 0, + &nbytes_in_lo32, &nbytes_in_hi32, + &nbytes_out_lo32, &nbytes_out_hi32 ); + if (bzerr != BZ_OK) goto errhandler; + + if (ferror(zStream)) goto errhandler_io; + ret = fflush ( zStream ); + if (ret == EOF) goto errhandler_io; + if (zStream != stdout) { + ret = fclose ( zStream ); + if (ret == EOF) goto errhandler_io; + } + if (ferror(stream)) goto errhandler_io; + ret = fclose ( stream ); + if (ret == EOF) goto errhandler_io; + + if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) + nbytes_in_lo32 = 1; + + if (verbosity >= 1) { + Char buf_nin[32], buf_nout[32]; + UInt64 nbytes_in, nbytes_out; + double nbytes_in_d, nbytes_out_d; + uInt64_from_UInt32s ( &nbytes_in, + nbytes_in_lo32, nbytes_in_hi32 ); + uInt64_from_UInt32s ( &nbytes_out, + nbytes_out_lo32, nbytes_out_hi32 ); + nbytes_in_d = uInt64_to_double ( &nbytes_in ); + nbytes_out_d = uInt64_to_double ( &nbytes_out ); + uInt64_toAscii ( buf_nin, &nbytes_in ); + uInt64_toAscii ( buf_nout, &nbytes_out ); + fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, " + "%5.2f%% saved, %s in, %s out.\n", + nbytes_in_d / nbytes_out_d, + (8.0 * nbytes_out_d) / nbytes_in_d, + 100.0 * (1.0 - nbytes_out_d / nbytes_in_d), + buf_nin, + buf_nout + ); + } + + return; + + errhandler: + BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, + &nbytes_in_lo32, &nbytes_in_hi32, + &nbytes_out_lo32, &nbytes_out_hi32 ); + switch (bzerr) { + case BZ_CONFIG_ERROR: + configError(); break; + case BZ_MEM_ERROR: + outOfMemory (); break; + case BZ_IO_ERROR: + errhandler_io: + ioError(); break; + default: + panic ( "compress:unexpected error" ); + } + + panic ( "compress:end" ); + /*notreached*/ +} + + + +/*---------------------------------------------*/ +static +Bool uncompressStream ( FILE *zStream, FILE *stream ) +{ + BZFILE* bzf = NULL; + Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i; + UChar obuf[5000]; + UChar unused[BZ_MAX_UNUSED]; + Int32 nUnused; + UChar* unusedTmp; + + nUnused = 0; + streamNo = 0; + + SET_BINARY_MODE(stream); + SET_BINARY_MODE(zStream); + + if (ferror(stream)) goto errhandler_io; + if (ferror(zStream)) goto errhandler_io; + + while (True) { + + bzf = BZ2_bzReadOpen ( + &bzerr, zStream, verbosity, + (int)smallMode, unused, nUnused + ); + if (bzf == NULL || bzerr != BZ_OK) goto errhandler; + streamNo++; + + while (bzerr == BZ_OK) { + nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 ); + if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler; + if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0) + fwrite ( obuf, sizeof(UChar), nread, stream ); + if (ferror(stream)) goto errhandler_io; + } + if (bzerr != BZ_STREAM_END) goto errhandler; + + BZ2_bzReadGetUnused ( &bzerr, bzf, (void**)(&unusedTmp), &nUnused ); + if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" ); + + for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i]; + + BZ2_bzReadClose ( &bzerr, bzf ); + if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" ); + + if (nUnused == 0 && myfeof(zStream)) break; + + } + + if (ferror(zStream)) goto errhandler_io; + ret = fclose ( zStream ); + if (ret == EOF) goto errhandler_io; + + if (ferror(stream)) goto errhandler_io; + ret = fflush ( stream ); + if (ret != 0) goto errhandler_io; + if (stream != stdout) { + ret = fclose ( stream ); + if (ret == EOF) goto errhandler_io; + } + if (verbosity >= 2) fprintf ( stderr, "\n " ); + return True; + + errhandler: + BZ2_bzReadClose ( &bzerr_dummy, bzf ); + switch (bzerr) { + case BZ_CONFIG_ERROR: + configError(); break; + case BZ_IO_ERROR: + errhandler_io: + ioError(); break; + case BZ_DATA_ERROR: + crcError(); + case BZ_MEM_ERROR: + outOfMemory(); + case BZ_UNEXPECTED_EOF: + compressedStreamEOF(); + case BZ_DATA_ERROR_MAGIC: + if (zStream != stdin) fclose(zStream); + if (stream != stdout) fclose(stream); + if (streamNo == 1) { + return False; + } else { + if (noisy) + fprintf ( stderr, + "\n%s: %s: trailing garbage after EOF ignored\n", + progName, inName ); + return True; + } + default: + panic ( "decompress:unexpected error" ); + } + + panic ( "decompress:end" ); + return True; /*notreached*/ +} + + +/*---------------------------------------------*/ +static +Bool testStream ( FILE *zStream ) +{ + BZFILE* bzf = NULL; + Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i; + UChar obuf[5000]; + UChar unused[BZ_MAX_UNUSED]; + Int32 nUnused; + UChar* unusedTmp; + + nUnused = 0; + streamNo = 0; + + SET_BINARY_MODE(zStream); + if (ferror(zStream)) goto errhandler_io; + + while (True) { + + bzf = BZ2_bzReadOpen ( + &bzerr, zStream, verbosity, + (int)smallMode, unused, nUnused + ); + if (bzf == NULL || bzerr != BZ_OK) goto errhandler; + streamNo++; + + while (bzerr == BZ_OK) { + nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 ); + if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler; + } + if (bzerr != BZ_STREAM_END) goto errhandler; + + BZ2_bzReadGetUnused ( &bzerr, bzf, (void**)(&unusedTmp), &nUnused ); + if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" ); + + for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i]; + + BZ2_bzReadClose ( &bzerr, bzf ); + if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" ); + if (nUnused == 0 && myfeof(zStream)) break; + + } + + if (ferror(zStream)) goto errhandler_io; + ret = fclose ( zStream ); + if (ret == EOF) goto errhandler_io; + + if (verbosity >= 2) fprintf ( stderr, "\n " ); + return True; + + errhandler: + BZ2_bzReadClose ( &bzerr_dummy, bzf ); + if (verbosity == 0) + fprintf ( stderr, "%s: %s: ", progName, inName ); + switch (bzerr) { + case BZ_CONFIG_ERROR: + configError(); break; + case BZ_IO_ERROR: + errhandler_io: + ioError(); break; + case BZ_DATA_ERROR: + fprintf ( stderr, + "data integrity (CRC) error in data\n" ); + return False; + case BZ_MEM_ERROR: + outOfMemory(); + case BZ_UNEXPECTED_EOF: + fprintf ( stderr, + "file ends unexpectedly\n" ); + return False; + case BZ_DATA_ERROR_MAGIC: + if (zStream != stdin) fclose(zStream); + if (streamNo == 1) { + fprintf ( stderr, + "bad magic number (file not created by bzip2)\n" ); + return False; + } else { + if (noisy) + fprintf ( stderr, + "trailing garbage after EOF ignored\n" ); + return True; + } + default: + panic ( "test:unexpected error" ); + } + + panic ( "test:end" ); + return True; /*notreached*/ +} + + +/*---------------------------------------------------*/ +/*--- Error [non-] handling grunge ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +static +void setExit ( Int32 v ) +{ + if (v > exitValue) exitValue = v; +} + + +/*---------------------------------------------*/ +static +void cadvise ( void ) +{ + if (noisy) + fprintf ( + stderr, + "\nIt is possible that the compressed file(s) have become corrupted.\n" + "You can use the -tvv option to test integrity of such files.\n\n" + "You can use the `bzip2recover' program to *attempt* to recover\n" + "data from undamaged sections of corrupted files.\n\n" + ); +} + + +/*---------------------------------------------*/ +static +void showFileNames ( void ) +{ + if (noisy) + fprintf ( + stderr, + "\tInput file = %s, output file = %s\n", + inName, outName + ); +} + + +/*---------------------------------------------*/ +static +void cleanUpAndFail ( Int32 ec ) +{ + IntNative retVal; + + if ( srcMode == SM_F2F + && opMode != OM_TEST + && deleteOutputOnInterrupt ) { + if (noisy) + fprintf ( stderr, "%s: Deleting output file %s, if it exists.\n", + progName, outName ); + if (outputHandleJustInCase != NULL) + fclose ( outputHandleJustInCase ); + retVal = remove ( outName ); + if (retVal != 0) + fprintf ( stderr, + "%s: WARNING: deletion of output file (apparently) failed.\n", + progName ); + } + if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) { + fprintf ( stderr, + "%s: WARNING: some files have not been processed:\n" + "\t%d specified on command line, %d not processed yet.\n\n", + progName, numFileNames, + numFileNames - numFilesProcessed ); + } + setExit(ec); + exit(exitValue); +} + + +/*---------------------------------------------*/ +static +void panic ( Char* s ) +{ + fprintf ( stderr, + "\n%s: PANIC -- internal consistency error:\n" + "\t%s\n" + "\tThis is a BUG. Please report it to me at:\n" + "\tjseward@acm.org\n", + progName, s ); + showFileNames(); + cleanUpAndFail( 3 ); +} + + +/*---------------------------------------------*/ +static +void crcError ( void ) +{ + fprintf ( stderr, + "\n%s: Data integrity error when decompressing.\n", + progName ); + showFileNames(); + cadvise(); + cleanUpAndFail( 2 ); +} + + +/*---------------------------------------------*/ +static +void compressedStreamEOF ( void ) +{ + fprintf ( stderr, + "\n%s: Compressed file ends unexpectedly;\n\t" + "perhaps it is corrupted? *Possible* reason follows.\n", + progName ); + perror ( progName ); + showFileNames(); + cadvise(); + cleanUpAndFail( 2 ); +} + + +/*---------------------------------------------*/ +static +void ioError ( void ) +{ + fprintf ( stderr, + "\n%s: I/O or other error, bailing out. " + "Possible reason follows.\n", + progName ); + perror ( progName ); + showFileNames(); + cleanUpAndFail( 1 ); +} + + +/*---------------------------------------------*/ +static +void mySignalCatcher ( IntNative n ) +{ + fprintf ( stderr, + "\n%s: Control-C or similar caught, quitting.\n", + progName ); + cleanUpAndFail(1); +} + + +/*---------------------------------------------*/ +static +void mySIGSEGVorSIGBUScatcher ( IntNative n ) +{ + if (opMode == OM_Z) + fprintf ( + stderr, + "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n" + "\n" + " Possible causes are (most likely first):\n" + " (1) This computer has unreliable memory or cache hardware\n" + " (a surprisingly common problem; try a different machine.)\n" + " (2) A bug in the compiler used to create this executable\n" + " (unlikely, if you didn't compile bzip2 yourself.)\n" + " (3) A real bug in bzip2 -- I hope this should never be the case.\n" + " The user's manual, Section 4.3, has more info on (1) and (2).\n" + " \n" + " If you suspect this is a bug in bzip2, or are unsure about (1)\n" + " or (2), feel free to report it to me at: jseward@acm.org.\n" + " Section 4.3 of the user's manual describes the info a useful\n" + " bug report should have. If the manual is available on your\n" + " system, please try and read it before mailing me. If you don't\n" + " have the manual or can't be bothered to read it, mail me anyway.\n" + "\n", + progName ); + else + fprintf ( + stderr, + "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n" + "\n" + " Possible causes are (most likely first):\n" + " (1) The compressed data is corrupted, and bzip2's usual checks\n" + " failed to detect this. Try bzip2 -tvv my_file.bz2.\n" + " (2) This computer has unreliable memory or cache hardware\n" + " (a surprisingly common problem; try a different machine.)\n" + " (3) A bug in the compiler used to create this executable\n" + " (unlikely, if you didn't compile bzip2 yourself.)\n" + " (4) A real bug in bzip2 -- I hope this should never be the case.\n" + " The user's manual, Section 4.3, has more info on (2) and (3).\n" + " \n" + " If you suspect this is a bug in bzip2, or are unsure about (2)\n" + " or (3), feel free to report it to me at: jseward@acm.org.\n" + " Section 4.3 of the user's manual describes the info a useful\n" + " bug report should have. If the manual is available on your\n" + " system, please try and read it before mailing me. If you don't\n" + " have the manual or can't be bothered to read it, mail me anyway.\n" + "\n", + progName ); + + showFileNames(); + if (opMode == OM_Z) + cleanUpAndFail( 3 ); else + { cadvise(); cleanUpAndFail( 2 ); } +} + + +/*---------------------------------------------*/ +static +void outOfMemory ( void ) +{ + fprintf ( stderr, + "\n%s: couldn't allocate enough memory\n", + progName ); + showFileNames(); + cleanUpAndFail(1); +} + + +/*---------------------------------------------*/ +static +void configError ( void ) +{ + fprintf ( stderr, + "bzip2: I'm not configured correctly for this platform!\n" + "\tI require Int32, Int16 and Char to have sizes\n" + "\tof 4, 2 and 1 bytes to run properly, and they don't.\n" + "\tProbably you can fix this by defining them correctly,\n" + "\tand recompiling. Bye!\n" ); + setExit(3); + exit(exitValue); +} + + +/*---------------------------------------------------*/ +/*--- The main driver machinery ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +static +void pad ( Char *s ) +{ + Int32 i; + if ( (Int32)strlen(s) >= longestFileName ) return; + for (i = 1; i <= longestFileName - (Int32)strlen(s); i++) + fprintf ( stderr, " " ); +} + + +/*---------------------------------------------*/ +static +void copyFileName ( Char* to, Char* from ) +{ + if ( strlen(from) > FILE_NAME_LEN-10 ) { + fprintf ( + stderr, + "bzip2: file name\n`%s'\n" + "is suspiciously (more than %d chars) long.\n" + "Try using a reasonable file name instead. Sorry! :-)\n", + from, FILE_NAME_LEN-10 + ); + setExit(1); + exit(exitValue); + } + + strncpy(to,from,FILE_NAME_LEN-10); + to[FILE_NAME_LEN-10]='\0'; +} + + +/*---------------------------------------------*/ +static +Bool fileExists ( Char* name ) +{ + FILE *tmp = fopen ( name, "rb" ); + Bool exists = (tmp != NULL); + if (tmp != NULL) fclose ( tmp ); + return exists; +} + + +/*---------------------------------------------*/ +/*-- + if in doubt, return True +--*/ +static +Bool notAStandardFile ( Char* name ) +{ + IntNative i; + struct MY_STAT statBuf; + + i = MY_LSTAT ( name, &statBuf ); + if (i != 0) return True; + if (MY_S_IFREG(statBuf.st_mode)) return False; + return True; +} + + +/*---------------------------------------------*/ +/*-- + rac 11/21/98 see if file has hard links to it +--*/ +static +Int32 countHardLinks ( Char* name ) +{ + IntNative i; + struct MY_STAT statBuf; + + i = MY_LSTAT ( name, &statBuf ); + if (i != 0) return 0; + return (statBuf.st_nlink - 1); +} + + +/*---------------------------------------------*/ +static +void copyDatePermissionsAndOwner ( Char *srcName, Char *dstName ) +{ +#if BZ_UNIX + IntNative retVal; + struct MY_STAT statBuf; + struct utimbuf uTimBuf; + + retVal = MY_LSTAT ( srcName, &statBuf ); + ERROR_IF_NOT_ZERO ( retVal ); + uTimBuf.actime = statBuf.st_atime; + uTimBuf.modtime = statBuf.st_mtime; + + retVal = chmod ( dstName, statBuf.st_mode ); + ERROR_IF_NOT_ZERO ( retVal ); + + retVal = utime ( dstName, &uTimBuf ); + ERROR_IF_NOT_ZERO ( retVal ); + + retVal = chown ( dstName, statBuf.st_uid, statBuf.st_gid ); + /* chown() will in many cases return with EPERM, which can + be safely ignored. + */ +#endif +} + + +/*---------------------------------------------*/ +static +void setInterimPermissions ( Char *dstName ) +{ +#if BZ_UNIX + IntNative retVal; + retVal = chmod ( dstName, S_IRUSR | S_IWUSR ); + ERROR_IF_NOT_ZERO ( retVal ); +#endif +} + + +/*---------------------------------------------*/ +static +Bool containsDubiousChars ( Char* name ) +{ + Bool cdc = False; + for (; *name != '\0'; name++) + if (*name == '?' || *name == '*') cdc = True; + return cdc; +} + + +/*---------------------------------------------*/ +#define BZ_N_SUFFIX_PAIRS 4 + +Char* zSuffix[BZ_N_SUFFIX_PAIRS] + = { ".bz2", ".bz", ".tbz2", ".tbz" }; +Char* unzSuffix[BZ_N_SUFFIX_PAIRS] + = { "", "", ".tar", ".tar" }; + +static +Bool hasSuffix ( Char* s, Char* suffix ) +{ + Int32 ns = strlen(s); + Int32 nx = strlen(suffix); + if (ns < nx) return False; + if (strcmp(s + ns - nx, suffix) == 0) return True; + return False; +} + +static +Bool mapSuffix ( Char* name, + Char* oldSuffix, Char* newSuffix ) +{ + if (!hasSuffix(name,oldSuffix)) return False; + name[strlen(name)-strlen(oldSuffix)] = 0; + strcat ( name, newSuffix ); + return True; +} + + +/*---------------------------------------------*/ +static +void compress ( Char *name ) +{ + FILE *inStr; + FILE *outStr; + Int32 n, i; + + deleteOutputOnInterrupt = False; + + if (name == NULL && srcMode != SM_I2O) + panic ( "compress: bad modes\n" ); + + switch (srcMode) { + case SM_I2O: + copyFileName ( inName, "(stdin)" ); + copyFileName ( outName, "(stdout)" ); + break; + case SM_F2F: + copyFileName ( inName, name ); + copyFileName ( outName, name ); + strcat ( outName, ".bz2" ); + break; + case SM_F2O: + copyFileName ( inName, name ); + copyFileName ( outName, "(stdout)" ); + break; + } + + if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { + if (noisy) + fprintf ( stderr, "%s: There are no files matching `%s'.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode != SM_I2O && !fileExists ( inName ) ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + } + for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) { + if (hasSuffix(inName, zSuffix[i])) { + if (noisy) + fprintf ( stderr, + "%s: Input file %s already has %s suffix.\n", + progName, inName, zSuffix[i] ); + setExit(1); + return; + } + } + if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) { + if (noisy) + fprintf ( stderr, "%s: Input file %s is not a normal file.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode == SM_F2F && !forceOverwrite && fileExists ( outName ) ) { + fprintf ( stderr, "%s: Output file %s already exists.\n", + progName, outName ); + setExit(1); + return; + } + if ( srcMode == SM_F2F && !forceOverwrite && + (n=countHardLinks ( inName )) > 0) { + fprintf ( stderr, "%s: Input file %s has %d other link%s.\n", + progName, inName, n, n > 1 ? "s" : "" ); + setExit(1); + return; + } + + switch ( srcMode ) { + + case SM_I2O: + inStr = stdin; + outStr = stdout; + if ( isatty ( fileno ( stdout ) ) ) { + fprintf ( stderr, + "%s: I won't write compressed data to a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + setExit(1); + return; + }; + break; + + case SM_F2O: + inStr = fopen ( inName, "rb" ); + outStr = stdout; + if ( isatty ( fileno ( stdout ) ) ) { + fprintf ( stderr, + "%s: I won't write compressed data to a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + }; + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + }; + break; + + case SM_F2F: + inStr = fopen ( inName, "rb" ); + outStr = fopen ( outName, "wb" ); + if ( outStr == NULL) { + fprintf ( stderr, "%s: Can't create output file %s: %s.\n", + progName, outName, strerror(errno) ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + } + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + if ( outStr != NULL ) fclose ( outStr ); + setExit(1); + return; + }; + setInterimPermissions ( outName ); + break; + + default: + panic ( "compress: bad srcMode" ); + break; + } + + if (verbosity >= 1) { + fprintf ( stderr, " %s: ", inName ); + pad ( inName ); + fflush ( stderr ); + } + + /*--- Now the input and output handles are sane. Do the Biz. ---*/ + outputHandleJustInCase = outStr; + deleteOutputOnInterrupt = True; + compressStream ( inStr, outStr ); + outputHandleJustInCase = NULL; + + /*--- If there was an I/O error, we won't get here. ---*/ + if ( srcMode == SM_F2F ) { + copyDatePermissionsAndOwner ( inName, outName ); + deleteOutputOnInterrupt = False; + if ( !keepInputFiles ) { + IntNative retVal = remove ( inName ); + ERROR_IF_NOT_ZERO ( retVal ); + } + } + + deleteOutputOnInterrupt = False; +} + + +/*---------------------------------------------*/ +static +void uncompress ( Char *name ) +{ + FILE *inStr; + FILE *outStr; + Int32 n, i; + Bool magicNumberOK; + Bool cantGuess; + + deleteOutputOnInterrupt = False; + + if (name == NULL && srcMode != SM_I2O) + panic ( "uncompress: bad modes\n" ); + + cantGuess = False; + switch (srcMode) { + case SM_I2O: + copyFileName ( inName, "(stdin)" ); + copyFileName ( outName, "(stdout)" ); + break; + case SM_F2F: + copyFileName ( inName, name ); + copyFileName ( outName, name ); + for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) + if (mapSuffix(outName,zSuffix[i],unzSuffix[i])) + goto zzz; + cantGuess = True; + strcat ( outName, ".out" ); + break; + case SM_F2O: + copyFileName ( inName, name ); + copyFileName ( outName, "(stdout)" ); + break; + } + + zzz: + if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { + if (noisy) + fprintf ( stderr, "%s: There are no files matching `%s'.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode != SM_I2O && !fileExists ( inName ) ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + } + if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) { + if (noisy) + fprintf ( stderr, "%s: Input file %s is not a normal file.\n", + progName, inName ); + setExit(1); + return; + } + if ( /* srcMode == SM_F2F implied && */ cantGuess ) { + if (noisy) + fprintf ( stderr, + "%s: Can't guess original name for %s -- using %s\n", + progName, inName, outName ); + /* just a warning, no return */ + } + if ( srcMode == SM_F2F && !forceOverwrite && fileExists ( outName ) ) { + fprintf ( stderr, "%s: Output file %s already exists.\n", + progName, outName ); + setExit(1); + return; + } + if ( srcMode == SM_F2F && !forceOverwrite && + (n=countHardLinks ( inName ) ) > 0) { + fprintf ( stderr, "%s: Input file %s has %d other link%s.\n", + progName, inName, n, n > 1 ? "s" : "" ); + setExit(1); + return; + } + + switch ( srcMode ) { + + case SM_I2O: + inStr = stdin; + outStr = stdout; + if ( isatty ( fileno ( stdin ) ) ) { + fprintf ( stderr, + "%s: I won't read compressed data from a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + setExit(1); + return; + }; + break; + + case SM_F2O: + inStr = fopen ( inName, "rb" ); + outStr = stdout; + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s:%s.\n", + progName, inName, strerror(errno) ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + }; + break; + + case SM_F2F: + inStr = fopen ( inName, "rb" ); + outStr = fopen ( outName, "wb" ); + if ( outStr == NULL) { + fprintf ( stderr, "%s: Can't create output file %s: %s.\n", + progName, outName, strerror(errno) ); + if ( inStr != NULL ) fclose ( inStr ); + setExit(1); + return; + } + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s: %s.\n", + progName, inName, strerror(errno) ); + if ( outStr != NULL ) fclose ( outStr ); + setExit(1); + return; + }; + setInterimPermissions ( outName ); + break; + + default: + panic ( "uncompress: bad srcMode" ); + break; + } + + if (verbosity >= 1) { + fprintf ( stderr, " %s: ", inName ); + pad ( inName ); + fflush ( stderr ); + } + + /*--- Now the input and output handles are sane. Do the Biz. ---*/ + outputHandleJustInCase = outStr; + deleteOutputOnInterrupt = True; + magicNumberOK = uncompressStream ( inStr, outStr ); + outputHandleJustInCase = NULL; + + /*--- If there was an I/O error, we won't get here. ---*/ + if ( magicNumberOK ) { + if ( srcMode == SM_F2F ) { + copyDatePermissionsAndOwner ( inName, outName ); + deleteOutputOnInterrupt = False; + if ( !keepInputFiles ) { + IntNative retVal = remove ( inName ); + ERROR_IF_NOT_ZERO ( retVal ); + } + } + } else { + unzFailsExist = True; + deleteOutputOnInterrupt = False; + if ( srcMode == SM_F2F ) { + IntNative retVal = remove ( outName ); + ERROR_IF_NOT_ZERO ( retVal ); + } + } + deleteOutputOnInterrupt = False; + + if ( magicNumberOK ) { + if (verbosity >= 1) + fprintf ( stderr, "done\n" ); + } else { + setExit(2); + if (verbosity >= 1) + fprintf ( stderr, "not a bzip2 file.\n" ); else + fprintf ( stderr, + "%s: %s is not a bzip2 file.\n", + progName, inName ); + } + +} + + +/*---------------------------------------------*/ +static +void testf ( Char *name ) +{ + FILE *inStr; + Bool allOK; + + deleteOutputOnInterrupt = False; + + if (name == NULL && srcMode != SM_I2O) + panic ( "testf: bad modes\n" ); + + copyFileName ( outName, "(none)" ); + switch (srcMode) { + case SM_I2O: copyFileName ( inName, "(stdin)" ); break; + case SM_F2F: copyFileName ( inName, name ); break; + case SM_F2O: copyFileName ( inName, name ); break; + } + + if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) { + if (noisy) + fprintf ( stderr, "%s: There are no files matching `%s'.\n", + progName, inName ); + setExit(1); + return; + } + if ( srcMode != SM_I2O && !fileExists ( inName ) ) { + fprintf ( stderr, "%s: Can't open input %s: %s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + } + + switch ( srcMode ) { + + case SM_I2O: + if ( isatty ( fileno ( stdin ) ) ) { + fprintf ( stderr, + "%s: I won't read compressed data from a terminal.\n", + progName ); + fprintf ( stderr, "%s: For help, type: `%s --help'.\n", + progName, progName ); + setExit(1); + return; + }; + inStr = stdin; + break; + + case SM_F2O: case SM_F2F: + inStr = fopen ( inName, "rb" ); + if ( inStr == NULL ) { + fprintf ( stderr, "%s: Can't open input file %s:%s.\n", + progName, inName, strerror(errno) ); + setExit(1); + return; + }; + break; + + default: + panic ( "testf: bad srcMode" ); + break; + } + + if (verbosity >= 1) { + fprintf ( stderr, " %s: ", inName ); + pad ( inName ); + fflush ( stderr ); + } + + /*--- Now the input handle is sane. Do the Biz. ---*/ + allOK = testStream ( inStr ); + + if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" ); + if (!allOK) testFailsExist = True; +} + + +/*---------------------------------------------*/ +static +void license ( void ) +{ + fprintf ( stderr, + + "bzip2, a block-sorting file compressor. " + "Version %s.\n" + " \n" + " Copyright (C) 1996-2000 by Julian Seward.\n" + " \n" + " This program is free software; you can redistribute it and/or modify\n" + " it under the terms set out in the LICENSE file, which is included\n" + " in the bzip2-1.0 source distribution.\n" + " \n" + " This program is distributed in the hope that it will be useful,\n" + " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + " LICENSE file for more details.\n" + " \n", + BZ2_bzlibVersion() + ); +} + + +/*---------------------------------------------*/ +static +void usage ( Char *fullProgName ) +{ + fprintf ( + stderr, + "bzip2, a block-sorting file compressor. " + "Version %s.\n" + "\n usage: %s [flags and input files in any order]\n" + "\n" + " -h --help print this message\n" + " -d --decompress force decompression\n" + " -z --compress force compression\n" + " -k --keep keep (don't delete) input files\n" + " -f --force overwrite existing output files\n" + " -t --test test compressed file integrity\n" + " -c --stdout output to standard out\n" + " -q --quiet suppress noncritical error messages\n" + " -v --verbose be verbose (a 2nd -v gives more)\n" + " -L --license display software version & license\n" + " -V --version display software version & license\n" + " -s --small use less memory (at most 2500k)\n" + " -1 .. -9 set block size to 100k .. 900k\n" + "\n" + " If invoked as `bzip2', default action is to compress.\n" + " as `bunzip2', default action is to decompress.\n" + " as `bzcat', default action is to decompress to stdout.\n" + "\n" + " If no file names are given, bzip2 compresses or decompresses\n" + " from standard input to standard output. You can combine\n" + " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n" +#if BZ_UNIX + "\n" +#endif + , + + BZ2_bzlibVersion(), + fullProgName + ); +} + + +/*---------------------------------------------*/ +static +void redundant ( Char* flag ) +{ + fprintf ( + stderr, + "%s: %s is redundant in versions 0.9.5 and above\n", + progName, flag ); +} + + +/*---------------------------------------------*/ +/*-- + All the garbage from here to main() is purely to + implement a linked list of command-line arguments, + into which main() copies argv[1 .. argc-1]. + + The purpose of this exercise is to facilitate + the expansion of wildcard characters * and ? in + filenames for OSs which don't know how to do it + themselves, like MSDOS, Windows 95 and NT. + + The actual Dirty Work is done by the platform- + specific macro APPEND_FILESPEC. +--*/ + +typedef + struct zzzz { + Char *name; + struct zzzz *link; + } + Cell; + + +/*---------------------------------------------*/ +static +void *myMalloc ( Int32 n ) +{ + void* p; + + p = malloc ( (size_t)n ); + if (p == NULL) outOfMemory (); + return p; +} + + +/*---------------------------------------------*/ +static +Cell *mkCell ( void ) +{ + Cell *c; + + c = (Cell*) myMalloc ( sizeof ( Cell ) ); + c->name = NULL; + c->link = NULL; + return c; +} + + +/*---------------------------------------------*/ +static +Cell *snocString ( Cell *root, Char *name ) +{ + if (root == NULL) { + Cell *tmp = mkCell(); + tmp->name = (Char*) myMalloc ( 5 + strlen(name) ); + strcpy ( tmp->name, name ); + return tmp; + } else { + Cell *tmp = root; + while (tmp->link != NULL) tmp = tmp->link; + tmp->link = snocString ( tmp->link, name ); + return root; + } +} + + +/*---------------------------------------------*/ +static +void addFlagsFromEnvVar ( Cell** argList, Char* varName ) +{ + Int32 i, j, k; + Char *envbase, *p; + + envbase = getenv(varName); + if (envbase != NULL) { + p = envbase; + i = 0; + while (True) { + if (p[i] == 0) break; + p += i; + i = 0; + while (isspace((Int32)(p[0]))) p++; + while (p[i] != 0 && !isspace((Int32)(p[i]))) i++; + if (i > 0) { + k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10; + for (j = 0; j < k; j++) tmpName[j] = p[j]; + tmpName[k] = 0; + APPEND_FLAG(*argList, tmpName); + } + } + } +} + + +/*---------------------------------------------*/ +#define ISFLAG(s) (strcmp(aa->name, (s))==0) + +IntNative main ( IntNative argc, Char *argv[] ) +{ + Int32 i, j; + Char *tmp; + Cell *argList; + Cell *aa; + Bool decode; + + /*-- Be really really really paranoid :-) --*/ + if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 || + sizeof(Int16) != 2 || sizeof(UInt16) != 2 || + sizeof(Char) != 1 || sizeof(UChar) != 1) + configError(); + + /*-- Initialise --*/ + outputHandleJustInCase = NULL; + smallMode = False; + keepInputFiles = False; + forceOverwrite = False; + noisy = True; + verbosity = 0; + blockSize100k = 9; + testFailsExist = False; + unzFailsExist = False; + numFileNames = 0; + numFilesProcessed = 0; + workFactor = 30; + deleteOutputOnInterrupt = False; + exitValue = 0; + i = j = 0; /* avoid bogus warning from egcs-1.1.X */ + + /*-- Set up signal handlers for mem access errors --*/ + signal (SIGSEGV, mySIGSEGVorSIGBUScatcher); +#if BZ_UNIX +#ifndef __DJGPP__ + signal (SIGBUS, mySIGSEGVorSIGBUScatcher); +#endif +#endif + + copyFileName ( inName, "(none)" ); + copyFileName ( outName, "(none)" ); + + copyFileName ( progNameReally, argv[0] ); + progName = &progNameReally[0]; + for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++) + if (*tmp == PATH_SEP) progName = tmp + 1; + + + /*-- Copy flags from env var BZIP2, and + expand filename wildcards in arg list. + --*/ + argList = NULL; + addFlagsFromEnvVar ( &argList, "BZIP2" ); + addFlagsFromEnvVar ( &argList, "BZIP" ); + for (i = 1; i <= argc-1; i++) + APPEND_FILESPEC(argList, argv[i]); + + + /*-- Find the length of the longest filename --*/ + longestFileName = 7; + numFileNames = 0; + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFileNames++; + if (longestFileName < (Int32)strlen(aa->name) ) + longestFileName = (Int32)strlen(aa->name); + } + + + /*-- Determine source modes; flag handling may change this too. --*/ + if (numFileNames == 0) + srcMode = SM_I2O; else srcMode = SM_F2F; + + + /*-- Determine what to do (compress/uncompress/test/cat). --*/ + /*-- Note that subsequent flag handling may change this. --*/ + opMode = OM_Z; + + if ( (strstr ( progName, "unzip" ) != 0) || + (strstr ( progName, "UNZIP" ) != 0) ) + opMode = OM_UNZ; + + if ( (strstr ( progName, "z2cat" ) != 0) || + (strstr ( progName, "Z2CAT" ) != 0) || + (strstr ( progName, "zcat" ) != 0) || + (strstr ( progName, "ZCAT" ) != 0) ) { + opMode = OM_UNZ; + srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O; + } + + + /*-- Look at the flags. --*/ + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) break; + if (aa->name[0] == '-' && aa->name[1] != '-') { + for (j = 1; aa->name[j] != '\0'; j++) { + switch (aa->name[j]) { + case 'c': srcMode = SM_F2O; break; + case 'd': opMode = OM_UNZ; break; + case 'z': opMode = OM_Z; break; + case 'f': forceOverwrite = True; break; + case 't': opMode = OM_TEST; break; + case 'k': keepInputFiles = True; break; + case 's': smallMode = True; break; + case 'q': noisy = False; break; + case '1': blockSize100k = 1; break; + case '2': blockSize100k = 2; break; + case '3': blockSize100k = 3; break; + case '4': blockSize100k = 4; break; + case '5': blockSize100k = 5; break; + case '6': blockSize100k = 6; break; + case '7': blockSize100k = 7; break; + case '8': blockSize100k = 8; break; + case '9': blockSize100k = 9; break; + case 'V': + case 'L': license(); break; + case 'v': verbosity++; break; + case 'h': usage ( progName ); + exit ( 0 ); + break; + default: fprintf ( stderr, "%s: Bad flag `%s'\n", + progName, aa->name ); + usage ( progName ); + exit ( 1 ); + break; + } + } + } + } + + /*-- And again ... --*/ + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) break; + if (ISFLAG("--stdout")) srcMode = SM_F2O; else + if (ISFLAG("--decompress")) opMode = OM_UNZ; else + if (ISFLAG("--compress")) opMode = OM_Z; else + if (ISFLAG("--force")) forceOverwrite = True; else + if (ISFLAG("--test")) opMode = OM_TEST; else + if (ISFLAG("--keep")) keepInputFiles = True; else + if (ISFLAG("--small")) smallMode = True; else + if (ISFLAG("--quiet")) noisy = False; else + if (ISFLAG("--version")) license(); else + if (ISFLAG("--license")) license(); else + if (ISFLAG("--exponential")) workFactor = 1; else + if (ISFLAG("--repetitive-best")) redundant(aa->name); else + if (ISFLAG("--repetitive-fast")) redundant(aa->name); else + if (ISFLAG("--verbose")) verbosity++; else + if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); } + else + if (strncmp ( aa->name, "--", 2) == 0) { + fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name ); + usage ( progName ); + exit ( 1 ); + } + } + + if (verbosity > 4) verbosity = 4; + if (opMode == OM_Z && smallMode && blockSize100k > 2) + blockSize100k = 2; + + if (opMode == OM_TEST && srcMode == SM_F2O) { + fprintf ( stderr, "%s: -c and -t cannot be used together.\n", + progName ); + exit ( 1 ); + } + + if (srcMode == SM_F2O && numFileNames == 0) + srcMode = SM_I2O; + + if (opMode != OM_Z) blockSize100k = 0; + + if (srcMode == SM_F2F) { + signal (SIGINT, mySignalCatcher); + signal (SIGTERM, mySignalCatcher); +# if BZ_UNIX + signal (SIGHUP, mySignalCatcher); +# endif + } + + if (opMode == OM_Z) { + if (srcMode == SM_I2O) { + compress ( NULL ); + } else { + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFilesProcessed++; + compress ( aa->name ); + } + } + } + else + + if (opMode == OM_UNZ) { + unzFailsExist = False; + if (srcMode == SM_I2O) { + uncompress ( NULL ); + } else { + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFilesProcessed++; + uncompress ( aa->name ); + } + } + if (unzFailsExist) { + setExit(2); + exit(exitValue); + } + } + + else { + testFailsExist = False; + if (srcMode == SM_I2O) { + testf ( NULL ); + } else { + decode = True; + for (aa = argList; aa != NULL; aa = aa->link) { + if (ISFLAG("--")) { decode = False; continue; } + if (aa->name[0] == '-' && decode) continue; + numFilesProcessed++; + testf ( aa->name ); + } + } + if (testFailsExist && noisy) { + fprintf ( stderr, + "\n" + "You can use the `bzip2recover' program to attempt to recover\n" + "data from undamaged sections of corrupted files.\n\n" + ); + setExit(2); + exit(exitValue); + } + } + + /* Free the argument list memory to mollify leak detectors + (eg) Purify, Checker. Serves no other useful purpose. + */ + aa = argList; + while (aa != NULL) { + Cell* aa2 = aa->link; + if (aa->name != NULL) free(aa->name); + free(aa); + aa = aa2; + } + + return exitValue; +} + + +/*-----------------------------------------------------------*/ +/*--- end bzip2.c ---*/ +/*-----------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/bzip2.txt b/drivers/lib/bzip2/bzip2.txt new file mode 100644 index 0000000..4f1ae86 --- /dev/null +++ b/drivers/lib/bzip2/bzip2.txt @@ -0,0 +1,376 @@ + + +NAME + bzip2, bunzip2 - a block-sorting file compressor, v1.0 + bzcat - decompresses files to stdout + bzip2recover - recovers data from damaged bzip2 files + + +SYNOPSIS + bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ... ] + bunzip2 [ -fkvsVL ] [ filenames ... ] + bzcat [ -s ] [ filenames ... ] + bzip2recover filename + + +DESCRIPTION + bzip2 compresses files using the Burrows-Wheeler block + sorting text compression algorithm, and Huffman coding. + Compression is generally considerably better than that + achieved by more conventional LZ77/LZ78-based compressors, + and approaches the performance of the PPM family of sta- + tistical compressors. + + The command-line options are deliberately very similar to + those of GNU gzip, but they are not identical. + + bzip2 expects a list of file names to accompany the com- + mand-line flags. Each file is replaced by a compressed + version of itself, with the name "original_name.bz2". + Each compressed file has the same modification date, per- + missions, and, when possible, ownership as the correspond- + ing original, so that these properties can be correctly + restored at decompression time. File name handling is + naive in the sense that there is no mechanism for preserv- + ing original file names, permissions, ownerships or dates + in filesystems which lack these concepts, or have serious + file name length restrictions, such as MS-DOS. + + bzip2 and bunzip2 will by default not overwrite existing + files. If you want this to happen, specify the -f flag. + + If no file names are specified, bzip2 compresses from + standard input to standard output. In this case, bzip2 + will decline to write compressed output to a terminal, as + this would be entirely incomprehensible and therefore + pointless. + + bunzip2 (or bzip2 -d) decompresses all specified files. + Files which were not created by bzip2 will be detected and + ignored, and a warning issued. bzip2 attempts to guess + the filename for the decompressed file from that of the + compressed file as follows: + + filename.bz2 becomes filename + filename.bz becomes filename + filename.tbz2 becomes filename.tar + filename.tbz becomes filename.tar + anyothername becomes anyothername.out + + If the file does not end in one of the recognised endings, + .bz2, .bz, .tbz2 or .tbz, bzip2 complains that it cannot + guess the name of the original file, and uses the original + name with .out appended. + + As with compression, supplying no filenames causes decom- + pression from standard input to standard output. + + bunzip2 will correctly decompress a file which is the con- + catenation of two or more compressed files. The result is + the concatenation of the corresponding uncompressed files. + Integrity testing (-t) of concatenated compressed files is + also supported. + + You can also compress or decompress files to the standard + output by giving the -c flag. Multiple files may be com- + pressed and decompressed like this. The resulting outputs + are fed sequentially to stdout. Compression of multiple + files in this manner generates a stream containing multi- + ple compressed file representations. Such a stream can be + decompressed correctly only by bzip2 version 0.9.0 or + later. Earlier versions of bzip2 will stop after decom- + pressing the first file in the stream. + + bzcat (or bzip2 -dc) decompresses all specified files to + the standard output. + + bzip2 will read arguments from the environment variables + BZIP2 and BZIP, in that order, and will process them + before any arguments read from the command line. This + gives a convenient way to supply default arguments. + + Compression is always performed, even if the compressed + file is slightly larger than the original. Files of less + than about one hundred bytes tend to get larger, since the + compression mechanism has a constant overhead in the + region of 50 bytes. Random data (including the output of + most file compressors) is coded at about 8.05 bits per + byte, giving an expansion of around 0.5%. + + As a self-check for your protection, bzip2 uses 32-bit + CRCs to make sure that the decompressed version of a file + is identical to the original. This guards against corrup- + tion of the compressed data, and against undetected bugs + in bzip2 (hopefully very unlikely). The chances of data + corruption going undetected is microscopic, about one + chance in four billion for each file processed. Be aware, + though, that the check occurs upon decompression, so it + can only tell you that something is wrong. It can't help + you recover the original uncompressed data. You can use + bzip2recover to try to recover data from damaged files. + + Return values: 0 for a normal exit, 1 for environmental + problems (file not found, invalid flags, I/O errors, &c), + 2 to indicate a corrupt compressed file, 3 for an internal + consistency error (eg, bug) which caused bzip2 to panic. + + +OPTIONS + -c --stdout + Compress or decompress to standard output. + + -d --decompress + Force decompression. bzip2, bunzip2 and bzcat are + really the same program, and the decision about + what actions to take is done on the basis of which + name is used. This flag overrides that mechanism, + and forces bzip2 to decompress. + + -z --compress + The complement to -d: forces compression, regard- + less of the invokation name. + + -t --test + Check integrity of the specified file(s), but don't + decompress them. This really performs a trial + decompression and throws away the result. + + -f --force + Force overwrite of output files. Normally, bzip2 + will not overwrite existing output files. Also + forces bzip2 to break hard links to files, which it + otherwise wouldn't do. + + -k --keep + Keep (don't delete) input files during compression + or decompression. + + -s --small + Reduce memory usage, for compression, decompression + and testing. Files are decompressed and tested + using a modified algorithm which only requires 2.5 + bytes per block byte. This means any file can be + decompressed in 2300k of memory, albeit at about + half the normal speed. + + During compression, -s selects a block size of + 200k, which limits memory use to around the same + figure, at the expense of your compression ratio. + In short, if your machine is low on memory (8 + megabytes or less), use -s for everything. See + MEMORY MANAGEMENT below. + + -q --quiet + Suppress non-essential warning messages. Messages + pertaining to I/O errors and other critical events + will not be suppressed. + + -v --verbose + Verbose mode -- show the compression ratio for each + file processed. Further -v's increase the ver- + bosity level, spewing out lots of information which + is primarily of interest for diagnostic purposes. + + -L --license -V --version + Display the software version, license terms and + conditions. + + -1 to -9 + Set the block size to 100 k, 200 k .. 900 k when + compressing. Has no effect when decompressing. + See MEMORY MANAGEMENT below. + + -- Treats all subsequent arguments as file names, even + if they start with a dash. This is so you can han- + dle files with names beginning with a dash, for + example: bzip2 -- -myfilename. + + --repetitive-fast --repetitive-best + These flags are redundant in versions 0.9.5 and + above. They provided some coarse control over the + behaviour of the sorting algorithm in earlier ver- + sions, which was sometimes useful. 0.9.5 and above + have an improved algorithm which renders these + flags irrelevant. + + +MEMORY MANAGEMENT + bzip2 compresses large files in blocks. The block size + affects both the compression ratio achieved, and the + amount of memory needed for compression and decompression. + The flags -1 through -9 specify the block size to be + 100,000 bytes through 900,000 bytes (the default) respec- + tively. At decompression time, the block size used for + compression is read from the header of the compressed + file, and bunzip2 then allocates itself just enough memory + to decompress the file. Since block sizes are stored in + compressed files, it follows that the flags -1 to -9 are + irrelevant to and so ignored during decompression. + + Compression and decompression requirements, in bytes, can + be estimated as: + + Compression: 400k + ( 8 x block size ) + + Decompression: 100k + ( 4 x block size ), or + 100k + ( 2.5 x block size ) + + Larger block sizes give rapidly diminishing marginal + returns. Most of the compression comes from the first two + or three hundred k of block size, a fact worth bearing in + mind when using bzip2 on small machines. It is also + important to appreciate that the decompression memory + requirement is set at compression time by the choice of + block size. + + For files compressed with the default 900k block size, + bunzip2 will require about 3700 kbytes to decompress. To + support decompression of any file on a 4 megabyte machine, + bunzip2 has an option to decompress using approximately + half this amount of memory, about 2300 kbytes. Decompres- + sion speed is also halved, so you should use this option + only where necessary. The relevant flag is -s. + + In general, try and use the largest block size memory con- + straints allow, since that maximises the compression + achieved. Compression and decompression speed are virtu- + ally unaffected by block size. + + Another significant point applies to files which fit in a + single block -- that means most files you'd encounter + using a large block size. The amount of real memory + touched is proportional to the size of the file, since the + file is smaller than a block. For example, compressing a + file 20,000 bytes long with the flag -9 will cause the + compressor to allocate around 7600k of memory, but only + touch 400k + 20000 * 8 = 560 kbytes of it. Similarly, the + decompressor will allocate 3700k but only touch 100k + + 20000 * 4 = 180 kbytes. + + Here is a table which summarises the maximum memory usage + for different block sizes. Also recorded is the total + compressed size for 14 files of the Calgary Text Compres- + sion Corpus totalling 3,141,622 bytes. This column gives + some feel for how compression varies with block size. + These figures tend to understate the advantage of larger + block sizes for larger files, since the Corpus is domi- + nated by smaller files. + + Compress Decompress Decompress Corpus + Flag usage usage -s usage Size + + -1 1200k 500k 350k 914704 + -2 2000k 900k 600k 877703 + -3 2800k 1300k 850k 860338 + -4 3600k 1700k 1100k 846899 + -5 4400k 2100k 1350k 845160 + -6 5200k 2500k 1600k 838626 + -7 6100k 2900k 1850k 834096 + -8 6800k 3300k 2100k 828642 + -9 7600k 3700k 2350k 828642 + + +RECOVERING DATA FROM DAMAGED FILES + bzip2 compresses files in blocks, usually 900kbytes long. + Each block is handled independently. If a media or trans- + mission error causes a multi-block .bz2 file to become + damaged, it may be possible to recover data from the + undamaged blocks in the file. + + The compressed representation of each block is delimited + by a 48-bit pattern, which makes it possible to find the + block boundaries with reasonable certainty. Each block + also carries its own 32-bit CRC, so damaged blocks can be + distinguished from undamaged ones. + + bzip2recover is a simple program whose purpose is to + search for blocks in .bz2 files, and write each block out + into its own .bz2 file. You can then use bzip2 -t to test + the integrity of the resulting files, and decompress those + which are undamaged. + + bzip2recover takes a single argument, the name of the dam- + aged file, and writes a number of files "rec0001file.bz2", + "rec0002file.bz2", etc, containing the extracted blocks. + The output filenames are designed so that the use of + wildcards in subsequent processing -- for example, "bzip2 + -dc rec*file.bz2 > recovered_data" -- lists the files in + the correct order. + + bzip2recover should be of most use dealing with large .bz2 + files, as these will contain many blocks. It is clearly + futile to use it on damaged single-block files, since a + damaged block cannot be recovered. If you wish to min- + imise any potential data loss through media or transmis- + sion errors, you might consider compressing with a smaller + block size. + + +PERFORMANCE NOTES + The sorting phase of compression gathers together similar + strings in the file. Because of this, files containing + very long runs of repeated symbols, like "aabaabaabaab + ..." (repeated several hundred times) may compress more + slowly than normal. Versions 0.9.5 and above fare much + better than previous versions in this respect. The ratio + between worst-case and average-case compression time is in + the region of 10:1. For previous versions, this figure + was more like 100:1. You can use the -vvvv option to mon- + itor progress in great detail, if you want. + + Decompression speed is unaffected by these phenomena. + + bzip2 usually allocates several megabytes of memory to + operate in, and then charges all over it in a fairly ran- + dom fashion. This means that performance, both for com- + pressing and decompressing, is largely determined by the + speed at which your machine can service cache misses. + Because of this, small changes to the code to reduce the + miss rate have been observed to give disproportionately + large performance improvements. I imagine bzip2 will per- + form best on machines with very large caches. + + +CAVEATS + I/O error messages are not as helpful as they could be. + bzip2 tries hard to detect I/O errors and exit cleanly, + but the details of what the problem is sometimes seem + rather misleading. + + This manual page pertains to version 1.0 of bzip2. Com- + pressed data created by this version is entirely forwards + and backwards compatible with the previous public + releases, versions 0.1pl2, 0.9.0 and 0.9.5, but with the + following exception: 0.9.0 and above can correctly decom- + press multiple concatenated compressed files. 0.1pl2 can- + not do this; it will stop after decompressing just the + first file in the stream. + + bzip2recover uses 32-bit integers to represent bit posi- + tions in compressed files, so it cannot handle compressed + files more than 512 megabytes long. This could easily be + fixed. + + +AUTHOR + Julian Seward, jseward@acm.org. + + http://sourceware.cygnus.com/bzip2 + http://www.muraroa.demon.co.uk + + The ideas embodied in bzip2 are due to (at least) the fol- + lowing people: Michael Burrows and David Wheeler (for the + block sorting transformation), David Wheeler (again, for + the Huffman coder), Peter Fenwick (for the structured cod- + ing model in the original bzip, and many refinements), and + Alistair Moffat, Radford Neal and Ian Witten (for the + arithmetic coder in the original bzip). I am much + indebted for their help, support and advice. See the man- + ual in the source distribution for pointers to sources of + documentation. Christian von Roques encouraged me to look + for faster sorting algorithms, so as to speed up compres- + sion. Bela Lubkin encouraged me to improve the worst-case + compression performance. Many people sent patches, helped + with portability problems, lent machines, gave advice and + were generally helpful. + diff --git a/drivers/lib/bzip2/bzip2recover.c b/drivers/lib/bzip2/bzip2recover.c new file mode 100644 index 0000000..ba3d175 --- /dev/null +++ b/drivers/lib/bzip2/bzip2recover.c @@ -0,0 +1,435 @@ + +/*-----------------------------------------------------------*/ +/*--- Block recoverer program for bzip2 ---*/ +/*--- bzip2recover.c ---*/ +/*-----------------------------------------------------------*/ + +/*-- + This program is bzip2recover, a program to attempt data + salvage from damaged files created by the accompanying + bzip2-1.0 program. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 +--*/ + +/*-- + This program is a complete hack and should be rewritten + properly. It isn't very complicated. +--*/ + +#include +#include +#include +#include + +typedef unsigned int UInt32; +typedef int Int32; +typedef unsigned char UChar; +typedef char Char; +typedef unsigned char Bool; +#define True ((Bool)1) +#define False ((Bool)0) + + +Char inFileName[2000]; +Char outFileName[2000]; +Char progName[2000]; + +UInt32 bytesOut = 0; +UInt32 bytesIn = 0; + + +/*---------------------------------------------------*/ +/*--- I/O errors ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------*/ +void readError ( void ) +{ + fprintf ( stderr, + "%s: I/O error reading `%s', possible reason follows.\n", + progName, inFileName ); + perror ( progName ); + fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", + progName ); + exit ( 1 ); +} + + +/*---------------------------------------------*/ +void writeError ( void ) +{ + fprintf ( stderr, + "%s: I/O error reading `%s', possible reason follows.\n", + progName, inFileName ); + perror ( progName ); + fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", + progName ); + exit ( 1 ); +} + + +/*---------------------------------------------*/ +void mallocFail ( Int32 n ) +{ + fprintf ( stderr, + "%s: malloc failed on request for %d bytes.\n", + progName, n ); + fprintf ( stderr, "%s: warning: output file(s) may be incomplete.\n", + progName ); + exit ( 1 ); +} + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +typedef + struct { + FILE* handle; + Int32 buffer; + Int32 buffLive; + Char mode; + } + BitStream; + + +/*---------------------------------------------*/ +BitStream* bsOpenReadStream ( FILE* stream ) +{ + BitStream *bs = malloc ( sizeof(BitStream) ); + if (bs == NULL) mallocFail ( sizeof(BitStream) ); + bs->handle = stream; + bs->buffer = 0; + bs->buffLive = 0; + bs->mode = 'r'; + return bs; +} + + +/*---------------------------------------------*/ +BitStream* bsOpenWriteStream ( FILE* stream ) +{ + BitStream *bs = malloc ( sizeof(BitStream) ); + if (bs == NULL) mallocFail ( sizeof(BitStream) ); + bs->handle = stream; + bs->buffer = 0; + bs->buffLive = 0; + bs->mode = 'w'; + return bs; +} + + +/*---------------------------------------------*/ +void bsPutBit ( BitStream* bs, Int32 bit ) +{ + if (bs->buffLive == 8) { + Int32 retVal = putc ( (UChar) bs->buffer, bs->handle ); + if (retVal == EOF) writeError(); + bytesOut++; + bs->buffLive = 1; + bs->buffer = bit & 0x1; + } else { + bs->buffer = ( (bs->buffer << 1) | (bit & 0x1) ); + bs->buffLive++; + }; +} + + +/*---------------------------------------------*/ +/*-- + Returns 0 or 1, or 2 to indicate EOF. +--*/ +Int32 bsGetBit ( BitStream* bs ) +{ + if (bs->buffLive > 0) { + bs->buffLive --; + return ( ((bs->buffer) >> (bs->buffLive)) & 0x1 ); + } else { + Int32 retVal = getc ( bs->handle ); + if ( retVal == EOF ) { + if (errno != 0) readError(); + return 2; + } + bs->buffLive = 7; + bs->buffer = retVal; + return ( ((bs->buffer) >> 7) & 0x1 ); + } +} + + +/*---------------------------------------------*/ +void bsClose ( BitStream* bs ) +{ + Int32 retVal; + + if ( bs->mode == 'w' ) { + while ( bs->buffLive < 8 ) { + bs->buffLive++; + bs->buffer <<= 1; + }; + retVal = putc ( (UChar) (bs->buffer), bs->handle ); + if (retVal == EOF) writeError(); + bytesOut++; + retVal = fflush ( bs->handle ); + if (retVal == EOF) writeError(); + } + retVal = fclose ( bs->handle ); + if (retVal == EOF) { + if (bs->mode == 'w') writeError(); else readError(); + } + free ( bs ); +} + + +/*---------------------------------------------*/ +void bsPutUChar ( BitStream* bs, UChar c ) +{ + Int32 i; + for (i = 7; i >= 0; i--) + bsPutBit ( bs, (((UInt32) c) >> i) & 0x1 ); +} + + +/*---------------------------------------------*/ +void bsPutUInt32 ( BitStream* bs, UInt32 c ) +{ + Int32 i; + + for (i = 31; i >= 0; i--) + bsPutBit ( bs, (c >> i) & 0x1 ); +} + + +/*---------------------------------------------*/ +Bool endsInBz2 ( Char* name ) +{ + Int32 n = strlen ( name ); + if (n <= 4) return False; + return + (name[n-4] == '.' && + name[n-3] == 'b' && + name[n-2] == 'z' && + name[n-1] == '2'); +} + + +/*---------------------------------------------------*/ +/*--- ---*/ +/*---------------------------------------------------*/ + +#define BLOCK_HEADER_HI 0x00003141UL +#define BLOCK_HEADER_LO 0x59265359UL + +#define BLOCK_ENDMARK_HI 0x00001772UL +#define BLOCK_ENDMARK_LO 0x45385090UL + + +UInt32 bStart[20000]; +UInt32 bEnd[20000]; +UInt32 rbStart[20000]; +UInt32 rbEnd[20000]; + +Int32 main ( Int32 argc, Char** argv ) +{ + FILE* inFile; + FILE* outFile; + BitStream* bsIn, *bsWr; + Int32 currBlock, b, wrBlock; + UInt32 bitsRead; + Int32 rbCtr; + + + UInt32 buffHi, buffLo, blockCRC; + Char* p; + + strcpy ( progName, argv[0] ); + inFileName[0] = outFileName[0] = 0; + + fprintf ( stderr, "bzip2recover 1.0: extracts blocks from damaged .bz2 files.\n" ); + + if (argc != 2) { + fprintf ( stderr, "%s: usage is `%s damaged_file_name'.\n", + progName, progName ); + exit(1); + } + + strcpy ( inFileName, argv[1] ); + + inFile = fopen ( inFileName, "rb" ); + if (inFile == NULL) { + fprintf ( stderr, "%s: can't read `%s'\n", progName, inFileName ); + exit(1); + } + + bsIn = bsOpenReadStream ( inFile ); + fprintf ( stderr, "%s: searching for block boundaries ...\n", progName ); + + bitsRead = 0; + buffHi = buffLo = 0; + currBlock = 0; + bStart[currBlock] = 0; + + rbCtr = 0; + + while (True) { + b = bsGetBit ( bsIn ); + bitsRead++; + if (b == 2) { + if (bitsRead >= bStart[currBlock] && + (bitsRead - bStart[currBlock]) >= 40) { + bEnd[currBlock] = bitsRead-1; + if (currBlock > 0) + fprintf ( stderr, " block %d runs from %d to %d (incomplete)\n", + currBlock, bStart[currBlock], bEnd[currBlock] ); + } else + currBlock--; + break; + } + buffHi = (buffHi << 1) | (buffLo >> 31); + buffLo = (buffLo << 1) | (b & 1); + if ( ( (buffHi & 0x0000ffff) == BLOCK_HEADER_HI + && buffLo == BLOCK_HEADER_LO) + || + ( (buffHi & 0x0000ffff) == BLOCK_ENDMARK_HI + && buffLo == BLOCK_ENDMARK_LO) + ) { + if (bitsRead > 49) + bEnd[currBlock] = bitsRead-49; else + bEnd[currBlock] = 0; + if (currBlock > 0 && + (bEnd[currBlock] - bStart[currBlock]) >= 130) { + fprintf ( stderr, " block %d runs from %d to %d\n", + rbCtr+1, bStart[currBlock], bEnd[currBlock] ); + rbStart[rbCtr] = bStart[currBlock]; + rbEnd[rbCtr] = bEnd[currBlock]; + rbCtr++; + } + currBlock++; + + bStart[currBlock] = bitsRead; + } + } + + bsClose ( bsIn ); + + /*-- identified blocks run from 1 to rbCtr inclusive. --*/ + + if (rbCtr < 1) { + fprintf ( stderr, + "%s: sorry, I couldn't find any block boundaries.\n", + progName ); + exit(1); + }; + + fprintf ( stderr, "%s: splitting into blocks\n", progName ); + + inFile = fopen ( inFileName, "rb" ); + if (inFile == NULL) { + fprintf ( stderr, "%s: can't open `%s'\n", progName, inFileName ); + exit(1); + } + bsIn = bsOpenReadStream ( inFile ); + + /*-- placate gcc's dataflow analyser --*/ + blockCRC = 0; bsWr = 0; + + bitsRead = 0; + outFile = NULL; + wrBlock = 0; + while (True) { + b = bsGetBit(bsIn); + if (b == 2) break; + buffHi = (buffHi << 1) | (buffLo >> 31); + buffLo = (buffLo << 1) | (b & 1); + if (bitsRead == 47+rbStart[wrBlock]) + blockCRC = (buffHi << 16) | (buffLo >> 16); + + if (outFile != NULL && bitsRead >= rbStart[wrBlock] + && bitsRead <= rbEnd[wrBlock]) { + bsPutBit ( bsWr, b ); + } + + bitsRead++; + + if (bitsRead == rbEnd[wrBlock]+1) { + if (outFile != NULL) { + bsPutUChar ( bsWr, 0x17 ); bsPutUChar ( bsWr, 0x72 ); + bsPutUChar ( bsWr, 0x45 ); bsPutUChar ( bsWr, 0x38 ); + bsPutUChar ( bsWr, 0x50 ); bsPutUChar ( bsWr, 0x90 ); + bsPutUInt32 ( bsWr, blockCRC ); + bsClose ( bsWr ); + } + if (wrBlock >= rbCtr) break; + wrBlock++; + } else + if (bitsRead == rbStart[wrBlock]) { + outFileName[0] = 0; + sprintf ( outFileName, "rec%4d", wrBlock+1 ); + for (p = outFileName; *p != 0; p++) if (*p == ' ') *p = '0'; + strcat ( outFileName, inFileName ); + if ( !endsInBz2(outFileName)) strcat ( outFileName, ".bz2" ); + + fprintf ( stderr, " writing block %d to `%s' ...\n", + wrBlock+1, outFileName ); + + outFile = fopen ( outFileName, "wb" ); + if (outFile == NULL) { + fprintf ( stderr, "%s: can't write `%s'\n", + progName, outFileName ); + exit(1); + } + bsWr = bsOpenWriteStream ( outFile ); + bsPutUChar ( bsWr, 'B' ); bsPutUChar ( bsWr, 'Z' ); + bsPutUChar ( bsWr, 'h' ); bsPutUChar ( bsWr, '9' ); + bsPutUChar ( bsWr, 0x31 ); bsPutUChar ( bsWr, 0x41 ); + bsPutUChar ( bsWr, 0x59 ); bsPutUChar ( bsWr, 0x26 ); + bsPutUChar ( bsWr, 0x53 ); bsPutUChar ( bsWr, 0x59 ); + } + } + + fprintf ( stderr, "%s: finished\n", progName ); + return 0; +} + + + +/*-----------------------------------------------------------*/ +/*--- end bzip2recover.c ---*/ +/*-----------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/bzlib.c b/drivers/lib/bzip2/bzlib.c new file mode 100644 index 0000000..e43de27 --- /dev/null +++ b/drivers/lib/bzip2/bzlib.c @@ -0,0 +1,1579 @@ + +/*-------------------------------------------------------------*/ +/*--- Library top-level functions. ---*/ +/*--- bzlib.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + +/*-- + CHANGES + ~~~~~~~ + 0.9.0 -- original version. + + 0.9.0a/b -- no changes in this file. + + 0.9.0c + * made zero-length BZ_FLUSH work correctly in bzCompress(). + * fixed bzWrite/bzRead to ignore zero-length requests. + * fixed bzread to correctly handle read requests after EOF. + * wrong parameter order in call to bzDecompressInit in + bzBuffToBuffDecompress. Fixed. +--*/ + +#ifdef BZ_DECOMPRESS_ONLY +#define __NTDRIVER__ +#include +#include +#endif + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Compression stuff ---*/ +/*---------------------------------------------------*/ + + +/*---------------------------------------------------*/ +#ifndef BZ_NO_STDIO +void BZ2_bz__AssertH__fail ( int errcode ) +{ + fprintf(stderr, + "\n\nbzip2/libbzip2: internal error number %d.\n" + "This is a bug in bzip2/libbzip2, %s.\n" + "Please report it to me at: jseward@acm.org. If this happened\n" + "when you were using some program which uses libbzip2 as a\n" + "component, you should also report this bug to the author(s)\n" + "of that program. Please make an effort to report this bug;\n" + "timely and accurate bug reports eventually lead to higher\n" + "quality software. Thanks. Julian Seward, 21 March 2000.\n\n", + errcode, + BZ2_bzlibVersion() + ); + exit(3); +} +#endif + + +/*---------------------------------------------------*/ +static +int bz_config_ok ( void ) +{ + if (sizeof(int) != 4) return 0; + if (sizeof(short) != 2) return 0; + if (sizeof(char) != 1) return 0; + return 1; +} + +/*---------------------------------------------------*/ +static +void* default_bzalloc ( void* opaque, Int32 items, Int32 size ) +{ + return ExAllocatePool( PagedPool, items * size ); +} + +static +void default_bzfree ( void* opaque, void* addr ) +{ + ExFreePool( addr ); +} + +#ifndef BZ_DECOMPRESS_ONLY + +/*---------------------------------------------------*/ +static +void prepare_new_block ( EState* s ) +{ + Int32 i; + s->nblock = 0; + s->numZ = 0; + s->state_out_pos = 0; + BZ_INITIALISE_CRC ( s->blockCRC ); + for (i = 0; i < 256; i++) s->inUse[i] = False; + s->blockNo++; +} + + +/*---------------------------------------------------*/ +static +void init_RL ( EState* s ) +{ + s->state_in_ch = 256; + s->state_in_len = 0; +} + + +static +Bool isempty_RL ( EState* s ) +{ + if (s->state_in_ch < 256 && s->state_in_len > 0) + return False; else + return True; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressInit) + ( bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 n; + EState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL || + blockSize100k < 1 || blockSize100k > 9 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(EState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + + s->arr1 = NULL; + s->arr2 = NULL; + s->ftab = NULL; + + n = 100000 * blockSize100k; + s->arr1 = BZALLOC( n * sizeof(UInt32) ); + s->arr2 = BZALLOC( (n+BZ_N_OVERSHOOT) * sizeof(UInt32) ); + s->ftab = BZALLOC( 65537 * sizeof(UInt32) ); + + if (s->arr1 == NULL || s->arr2 == NULL || s->ftab == NULL) { + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + if (s != NULL) BZFREE(s); + return BZ_MEM_ERROR; + } + + s->blockNo = 0; + s->state = BZ_S_INPUT; + s->mode = BZ_M_RUNNING; + s->combinedCRC = 0; + s->blockSize100k = blockSize100k; + s->nblockMAX = 100000 * blockSize100k - 19; + s->verbosity = verbosity; + s->workFactor = workFactor; + + s->block = (UChar*)s->arr2; + s->mtfv = (UInt16*)s->arr1; + s->zbits = NULL; + s->ptr = (UInt32*)s->arr1; + + strm->state = s; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + init_RL ( s ); + prepare_new_block ( s ); + return BZ_OK; +} + + +/*---------------------------------------------------*/ +static +void add_pair_to_block ( EState* s ) +{ + Int32 i; + UChar ch = (UChar)(s->state_in_ch); + for (i = 0; i < s->state_in_len; i++) { + BZ_UPDATE_CRC( s->blockCRC, ch ); + } + s->inUse[s->state_in_ch] = True; + switch (s->state_in_len) { + case 1: + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 2: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + case 3: + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + break; + default: + s->inUse[s->state_in_len-4] = True; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = (UChar)ch; s->nblock++; + s->block[s->nblock] = ((UChar)(s->state_in_len-4)); + s->nblock++; + break; + } +} + + +/*---------------------------------------------------*/ +static +void flush_RL ( EState* s ) +{ + if (s->state_in_ch < 256) add_pair_to_block ( s ); + init_RL ( s ); +} + + +/*---------------------------------------------------*/ +#define ADD_CHAR_TO_BLOCK(zs,zchh0) \ +{ \ + UInt32 zchh = (UInt32)(zchh0); \ + /*-- fast track the common case --*/ \ + if (zchh != zs->state_in_ch && \ + zs->state_in_len == 1) { \ + UChar ch = (UChar)(zs->state_in_ch); \ + BZ_UPDATE_CRC( zs->blockCRC, ch ); \ + zs->inUse[zs->state_in_ch] = True; \ + zs->block[zs->nblock] = (UChar)ch; \ + zs->nblock++; \ + zs->state_in_ch = zchh; \ + } \ + else \ + /*-- general, uncommon cases --*/ \ + if (zchh != zs->state_in_ch || \ + zs->state_in_len == 255) { \ + if (zs->state_in_ch < 256) \ + add_pair_to_block ( zs ); \ + zs->state_in_ch = zchh; \ + zs->state_in_len = 1; \ + } else { \ + zs->state_in_len++; \ + } \ +} + + +/*---------------------------------------------------*/ +static +Bool copy_input_until_stop ( EState* s ) +{ + Bool progress_in = False; + + if (s->mode == BZ_M_RUNNING) { + + /*-- fast track the common case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + } + + } else { + + /*-- general, uncommon case --*/ + while (True) { + /*-- block full? --*/ + if (s->nblock >= s->nblockMAX) break; + /*-- no input? --*/ + if (s->strm->avail_in == 0) break; + /*-- flush/finish end? --*/ + if (s->avail_in_expect == 0) break; + progress_in = True; + ADD_CHAR_TO_BLOCK ( s, (UInt32)(*((UChar*)(s->strm->next_in))) ); + s->strm->next_in++; + s->strm->avail_in--; + s->strm->total_in_lo32++; + if (s->strm->total_in_lo32 == 0) s->strm->total_in_hi32++; + s->avail_in_expect--; + } + } + return progress_in; +} + + +/*---------------------------------------------------*/ +static +Bool copy_output_until_stop ( EState* s ) +{ + Bool progress_out = False; + + while (True) { + + /*-- no output space? --*/ + if (s->strm->avail_out == 0) break; + + /*-- block done? --*/ + if (s->state_out_pos >= s->numZ) break; + + progress_out = True; + *(s->strm->next_out) = s->zbits[s->state_out_pos]; + s->state_out_pos++; + s->strm->avail_out--; + s->strm->next_out++; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + return progress_out; +} + + +/*---------------------------------------------------*/ +static +Bool handle_compress ( bz_stream* strm ) +{ + Bool progress_in = False; + Bool progress_out = False; + EState* s = strm->state; + + while (True) { + + if (s->state == BZ_S_OUTPUT) { + progress_out |= copy_output_until_stop ( s ); + if (s->state_out_pos < s->numZ) break; + if (s->mode == BZ_M_FINISHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + prepare_new_block ( s ); + s->state = BZ_S_INPUT; + if (s->mode == BZ_M_FLUSHING && + s->avail_in_expect == 0 && + isempty_RL(s)) break; + } + + if (s->state == BZ_S_INPUT) { + progress_in |= copy_input_until_stop ( s ); + if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) { + flush_RL ( s ); + BZ2_compressBlock ( s, (Bool)(s->mode == BZ_M_FINISHING) ); + s->state = BZ_S_OUTPUT; + } + else + if (s->nblock >= s->nblockMAX) { + BZ2_compressBlock ( s, False ); + s->state = BZ_S_OUTPUT; + } + else + if (s->strm->avail_in == 0) { + break; + } + } + + } + + return progress_in || progress_out; +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompress) ( bz_stream *strm, int action ) +{ + Bool progress; + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + preswitch: + switch (s->mode) { + + case BZ_M_IDLE: + return BZ_SEQUENCE_ERROR; + + case BZ_M_RUNNING: + if (action == BZ_RUN) { + progress = handle_compress ( strm ); + return progress ? BZ_RUN_OK : BZ_PARAM_ERROR; + } + else + if (action == BZ_FLUSH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FLUSHING; + goto preswitch; + } + else + if (action == BZ_FINISH) { + s->avail_in_expect = strm->avail_in; + s->mode = BZ_M_FINISHING; + goto preswitch; + } + else + return BZ_PARAM_ERROR; + + case BZ_M_FLUSHING: + if (action != BZ_FLUSH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FLUSH_OK; + s->mode = BZ_M_RUNNING; + return BZ_RUN_OK; + + case BZ_M_FINISHING: + if (action != BZ_FINISH) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect != s->strm->avail_in) + return BZ_SEQUENCE_ERROR; + progress = handle_compress ( strm ); + if (!progress) return BZ_SEQUENCE_ERROR; + if (s->avail_in_expect > 0 || !isempty_RL(s) || + s->state_out_pos < s->numZ) return BZ_FINISH_OK; + s->mode = BZ_M_IDLE; + return BZ_STREAM_END; + } + return BZ_OK; /*--not reached--*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzCompressEnd) ( bz_stream *strm ) +{ + EState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->arr1 != NULL) BZFREE(s->arr1); + if (s->arr2 != NULL) BZFREE(s->arr2); + if (s->ftab != NULL) BZFREE(s->ftab); + BZFREE(strm->state); + + strm->state = NULL; + + return BZ_OK; +} + +#endif // BZ_DECOMPRESS_ONLY + +/*---------------------------------------------------*/ +/*--- Decompression stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressInit) + ( bz_stream* strm, + int verbosity, + int small ) +{ + DState* s; + + if (!bz_config_ok()) return BZ_CONFIG_ERROR; + + if (strm == NULL) return BZ_PARAM_ERROR; + if (small != 0 && small != 1) return BZ_PARAM_ERROR; + if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR; + + if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc; + if (strm->bzfree == NULL) strm->bzfree = default_bzfree; + + s = BZALLOC( sizeof(DState) ); + if (s == NULL) return BZ_MEM_ERROR; + s->strm = strm; + strm->state = s; + s->state = BZ_X_MAGIC_1; + s->bsLive = 0; + s->bsBuff = 0; + s->calculatedCombinedCRC = 0; + strm->total_in_lo32 = 0; + strm->total_in_hi32 = 0; + strm->total_out_lo32 = 0; + strm->total_out_hi32 = 0; + s->smallDecompress = (Bool)small; + s->ll4 = NULL; + s->ll16 = NULL; + s->tt = NULL; + s->currBlockNo = 0; + s->verbosity = verbosity; + + return BZ_OK; +} + +#ifndef BZ_DECOMPRESS_ONLY + +/*---------------------------------------------------*/ +static +void unRLE_obuf_to_output_FAST ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return; + + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_FAST(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + /* restore */ + UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC; + UChar c_state_out_ch = s->state_out_ch; + Int32 c_state_out_len = s->state_out_len; + Int32 c_nblock_used = s->nblock_used; + Int32 c_k0 = s->k0; + UInt32* c_tt = s->tt; + UInt32 c_tPos = s->tPos; + char* cs_next_out = s->strm->next_out; + unsigned int cs_avail_out = s->strm->avail_out; + /* end restore */ + + UInt32 avail_out_INIT = cs_avail_out; + Int32 s_save_nblockPP = s->save_nblock+1; + unsigned int total_out_lo32_old; + + while (True) { + + /* try to finish existing run */ + if (c_state_out_len > 0) { + while (True) { + if (cs_avail_out == 0) goto return_notr; + if (c_state_out_len == 1) break; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + c_state_out_len--; + cs_next_out++; + cs_avail_out--; + } + s_state_out_len_eq_one: + { + if (cs_avail_out == 0) { + c_state_out_len = 1; goto return_notr; + }; + *( (UChar*)(cs_next_out) ) = c_state_out_ch; + BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); + cs_next_out++; + cs_avail_out--; + } + } + /* can a new run be started? */ + if (c_nblock_used == s_save_nblockPP) { + c_state_out_len = 0; goto return_notr; + }; + c_state_out_ch = c_k0; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (k1 != c_k0) { + c_k0 = k1; goto s_state_out_len_eq_one; + }; + if (c_nblock_used == s_save_nblockPP) + goto s_state_out_len_eq_one; + + c_state_out_len = 2; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + c_state_out_len = 3; + BZ_GET_FAST_C(k1); c_nblock_used++; + if (c_nblock_used == s_save_nblockPP) continue; + if (k1 != c_k0) { c_k0 = k1; continue; }; + + BZ_GET_FAST_C(k1); c_nblock_used++; + c_state_out_len = ((Int32)k1) + 4; + BZ_GET_FAST_C(c_k0); c_nblock_used++; + } + + return_notr: + total_out_lo32_old = s->strm->total_out_lo32; + s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); + if (s->strm->total_out_lo32 < total_out_lo32_old) + s->strm->total_out_hi32++; + + /* save */ + s->calculatedBlockCRC = c_calculatedBlockCRC; + s->state_out_ch = c_state_out_ch; + s->state_out_len = c_state_out_len; + s->nblock_used = c_nblock_used; + s->k0 = c_k0; + s->tt = c_tt; + s->tPos = c_tPos; + s->strm->next_out = cs_next_out; + s->strm->avail_out = cs_avail_out; + /* end save */ + } +} + +#endif // BZ_DECOMPRESS_ONLY + +/*---------------------------------------------------*/ +__inline__ Int32 BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) +{ + Int32 nb, na, mid; + nb = 0; + na = 256; + do { + mid = (nb + na) >> 1; + if (indx >= cftab[mid]) nb = mid; else na = mid; + } + while (na - nb != 1); + return nb; +} + +/*---------------------------------------------------*/ +static +void unRLE_obuf_to_output_SMALL ( DState* s ) +{ + UChar k1; + + if (s->blockRandomised) { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return; + + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK; + k1 ^= BZ_RAND_MASK; s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK; + s->k0 ^= BZ_RAND_MASK; s->nblock_used++; + } + + } else { + + while (True) { + /* try to finish existing run */ + while (True) { + if (s->strm->avail_out == 0) return; + if (s->state_out_len == 0) break; + *( (UChar*)(s->strm->next_out) ) = s->state_out_ch; + BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); + s->state_out_len--; + s->strm->next_out++; + s->strm->avail_out--; + s->strm->total_out_lo32++; + if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; + } + + /* can a new run be started? */ + if (s->nblock_used == s->save_nblock+1) return; + + s->state_out_len = 1; + s->state_out_ch = s->k0; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 2; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + s->state_out_len = 3; + BZ_GET_SMALL(k1); s->nblock_used++; + if (s->nblock_used == s->save_nblock+1) continue; + if (k1 != s->k0) { s->k0 = k1; continue; }; + + BZ_GET_SMALL(k1); s->nblock_used++; + s->state_out_len = ((Int32)k1) + 4; + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } +} + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) +{ + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + while (True) { + if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; + if (s->state == BZ_X_OUTPUT) { +#ifndef BZ_DECOMPRESS_ONLY + if (s->smallDecompress) + unRLE_obuf_to_output_SMALL ( s ); else + unRLE_obuf_to_output_FAST ( s ); +#else + unRLE_obuf_to_output_SMALL ( s ); +#endif + if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { + BZ_FINALISE_CRC ( s->calculatedBlockCRC ); + if (s->verbosity >= 3) + VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC, + s->calculatedBlockCRC ); + if (s->verbosity >= 2) VPrintf0 ( "]" ); + if (s->calculatedBlockCRC != s->storedBlockCRC) + return BZ_DATA_ERROR; + s->calculatedCombinedCRC + = (s->calculatedCombinedCRC << 1) | + (s->calculatedCombinedCRC >> 31); + s->calculatedCombinedCRC ^= s->calculatedBlockCRC; + s->state = BZ_X_BLKHDR_1; + } else { + return BZ_OK; + } + } + if (s->state >= BZ_X_MAGIC_1) { + Int32 r = BZ2_decompress ( s ); + if (r == BZ_STREAM_END) { + if (s->verbosity >= 3) + VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x", + s->storedCombinedCRC, s->calculatedCombinedCRC ); + if (s->calculatedCombinedCRC != s->storedCombinedCRC) + return BZ_DATA_ERROR; + return r; + } + if (s->state != BZ_X_OUTPUT) return r; + } + } + + AssertH ( 0, 6001 ); + + return 0; /*NOTREACHED*/ +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzDecompressEnd) ( bz_stream *strm ) +{ + DState* s; + if (strm == NULL) return BZ_PARAM_ERROR; + s = strm->state; + if (s == NULL) return BZ_PARAM_ERROR; + if (s->strm != strm) return BZ_PARAM_ERROR; + + if (s->tt != NULL) BZFREE(s->tt); + if (s->ll16 != NULL) BZFREE(s->ll16); + if (s->ll4 != NULL) BZFREE(s->ll4); + + BZFREE(strm->state); + strm->state = NULL; + + return BZ_OK; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ +/*--- File I/O stuff ---*/ +/*---------------------------------------------------*/ + +#define BZ_SETERR(eee) \ +{ \ + if (bzerror != NULL) *bzerror = eee; \ + if (bzf != NULL) bzf->lastErr = eee; \ +} + +typedef + struct { + FILE* handle; + Char buf[BZ_MAX_UNUSED]; + Int32 bufN; + Bool writing; + bz_stream strm; + Int32 lastErr; + Bool initialisedOk; + } + bzFile; + + +/*---------------------------------------------*/ +static Bool myfeof ( FILE* f ) +{ + Int32 c = fgetc ( f ); + if (c == EOF) return True; + ungetc ( c, f ); + return False; +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzWriteOpen) + ( int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor ) +{ + Int32 ret; + bzFile* bzf = NULL; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (blockSize100k < 1 || blockSize100k > 9) || + (workFactor < 0 || workFactor > 250) || + (verbosity < 0 || verbosity > 4)) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + bzf->initialisedOk = False; + bzf->bufN = 0; + bzf->handle = f; + bzf->writing = True; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + if (workFactor == 0) workFactor = 30; + ret = BZ2_bzCompressInit ( &(bzf->strm), blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = 0; + bzf->initialisedOk = True; + return bzf; +} + + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWrite) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return; }; + + bzf->strm.avail_in = len; + bzf->strm.next_in = buf; + + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_RUN ); + if (ret != BZ_RUN_OK) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (bzf->strm.avail_in == 0) + { BZ_SETERR(BZ_OK); return; }; + } +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzWriteClose) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out ) +{ + BZ2_bzWriteClose64 ( bzerror, b, abandon, + nbytes_in, NULL, nbytes_out, NULL ); +} + + +void BZ_API(BZ2_bzWriteClose64) + ( int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 ) +{ + Int32 n, n2, ret; + bzFile* bzf = (bzFile*)b; + + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + if (!(bzf->writing)) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + + if (nbytes_in_lo32 != NULL) *nbytes_in_lo32 = 0; + if (nbytes_in_hi32 != NULL) *nbytes_in_hi32 = 0; + if (nbytes_out_lo32 != NULL) *nbytes_out_lo32 = 0; + if (nbytes_out_hi32 != NULL) *nbytes_out_hi32 = 0; + + if ((!abandon) && bzf->lastErr == BZ_OK) { + while (True) { + bzf->strm.avail_out = BZ_MAX_UNUSED; + bzf->strm.next_out = bzf->buf; + ret = BZ2_bzCompress ( &(bzf->strm), BZ_FINISH ); + if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return; }; + + if (bzf->strm.avail_out < BZ_MAX_UNUSED) { + n = BZ_MAX_UNUSED - bzf->strm.avail_out; + n2 = fwrite ( (void*)(bzf->buf), sizeof(UChar), + n, bzf->handle ); + if (n != n2 || ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (ret == BZ_STREAM_END) break; + } + } + + if ( !abandon && !ferror ( bzf->handle ) ) { + fflush ( bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return; }; + } + + if (nbytes_in_lo32 != NULL) + *nbytes_in_lo32 = bzf->strm.total_in_lo32; + if (nbytes_in_hi32 != NULL) + *nbytes_in_hi32 = bzf->strm.total_in_hi32; + if (nbytes_out_lo32 != NULL) + *nbytes_out_lo32 = bzf->strm.total_out_lo32; + if (nbytes_out_hi32 != NULL) + *nbytes_out_hi32 = bzf->strm.total_out_hi32; + + BZ_SETERR(BZ_OK); + BZ2_bzCompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +BZFILE* BZ_API(BZ2_bzReadOpen) + ( int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused ) +{ + bzFile* bzf = NULL; + int ret; + + BZ_SETERR(BZ_OK); + + if (f == NULL || + (small != 0 && small != 1) || + (verbosity < 0 || verbosity > 4) || + (unused == NULL && nUnused != 0) || + (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) + { BZ_SETERR(BZ_PARAM_ERROR); return NULL; }; + + if (ferror(f)) + { BZ_SETERR(BZ_IO_ERROR); return NULL; }; + + bzf = malloc ( sizeof(bzFile) ); + if (bzf == NULL) + { BZ_SETERR(BZ_MEM_ERROR); return NULL; }; + + BZ_SETERR(BZ_OK); + + bzf->initialisedOk = False; + bzf->handle = f; + bzf->bufN = 0; + bzf->writing = False; + bzf->strm.bzalloc = NULL; + bzf->strm.bzfree = NULL; + bzf->strm.opaque = NULL; + + while (nUnused > 0) { + bzf->buf[bzf->bufN] = *((UChar*)(unused)); bzf->bufN++; + unused = ((void*)( 1 + ((UChar*)(unused)) )); + nUnused--; + } + + ret = BZ2_bzDecompressInit ( &(bzf->strm), verbosity, small ); + if (ret != BZ_OK) + { BZ_SETERR(ret); free(bzf); return NULL; }; + + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + + bzf->initialisedOk = True; + return bzf; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadClose) ( int *bzerror, BZFILE *b ) +{ + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + if (bzf == NULL) + { BZ_SETERR(BZ_OK); return; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + + if (bzf->initialisedOk) + (void)BZ2_bzDecompressEnd ( &(bzf->strm) ); + free ( bzf ); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzRead) + ( int* bzerror, + BZFILE* b, + void* buf, + int len ) +{ + Int32 n, ret; + bzFile* bzf = (bzFile*)b; + + BZ_SETERR(BZ_OK); + + if (bzf == NULL || buf == NULL || len < 0) + { BZ_SETERR(BZ_PARAM_ERROR); return 0; }; + + if (bzf->writing) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return 0; }; + + if (len == 0) + { BZ_SETERR(BZ_OK); return 0; }; + + bzf->strm.avail_out = len; + bzf->strm.next_out = buf; + + while (True) { + + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + + if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) { + n = fread ( bzf->buf, sizeof(UChar), + BZ_MAX_UNUSED, bzf->handle ); + if (ferror(bzf->handle)) + { BZ_SETERR(BZ_IO_ERROR); return 0; }; + bzf->bufN = n; + bzf->strm.avail_in = bzf->bufN; + bzf->strm.next_in = bzf->buf; + } + + ret = BZ2_bzDecompress ( &(bzf->strm) ); + + if (ret != BZ_OK && ret != BZ_STREAM_END) + { BZ_SETERR(ret); return 0; }; + + if (ret == BZ_OK && myfeof(bzf->handle) && + bzf->strm.avail_in == 0 && bzf->strm.avail_out > 0) + { BZ_SETERR(BZ_UNEXPECTED_EOF); return 0; }; + + if (ret == BZ_STREAM_END) + { BZ_SETERR(BZ_STREAM_END); + return len - bzf->strm.avail_out; }; + if (bzf->strm.avail_out == 0) + { BZ_SETERR(BZ_OK); return len; }; + + } + + return 0; /*not reached*/ +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzReadGetUnused) + ( int* bzerror, + BZFILE* b, + void** unused, + int* nUnused ) +{ + bzFile* bzf = (bzFile*)b; + if (bzf == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + if (bzf->lastErr != BZ_STREAM_END) + { BZ_SETERR(BZ_SEQUENCE_ERROR); return; }; + if (unused == NULL || nUnused == NULL) + { BZ_SETERR(BZ_PARAM_ERROR); return; }; + + BZ_SETERR(BZ_OK); + *nUnused = bzf->strm.avail_in; + *unused = bzf->strm.next_in; +} +#endif + +#ifndef BZ_DECOMPRESS_ONLY + +/*---------------------------------------------------*/ +/*--- Misc convenience stuff ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffCompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor ) +{ + bz_stream strm; + int ret; + CHECKPOINT; + if (dest == NULL || destLen == NULL || + source == NULL || + blockSize100k < 1 || blockSize100k > 9 || + verbosity < 0 || verbosity > 4 || + workFactor < 0 || workFactor > 250) + return BZ_PARAM_ERROR; + + if (workFactor == 0) workFactor = 30; + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + CHECKPOINT; + ret = BZ2_bzCompressInit ( &strm, blockSize100k, + verbosity, workFactor ); + if (ret != BZ_OK) return ret; + CHECKPOINT; + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzCompress ( &strm, BZ_FINISH ); + if (ret == BZ_FINISH_OK) goto output_overflow; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + CHECKPOINT; + BZ2_bzCompressEnd ( &strm ); + return BZ_OK; + + output_overflow: + CHECKPOINT; + BZ2_bzCompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + + errhandler: + CHECKPOINT; + BZ2_bzCompressEnd ( &strm ); + return ret; +} + +#endif // BZ_DECOMPRESS_0NLY + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzBuffToBuffDecompress) + ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity ) +{ + bz_stream strm; + int ret; + + if (dest == NULL || destLen == NULL || + source == NULL || + (small != 0 && small != 1) || + verbosity < 0 || verbosity > 4) + return BZ_PARAM_ERROR; + + strm.bzalloc = NULL; + strm.bzfree = NULL; + strm.opaque = NULL; + ret = BZ2_bzDecompressInit ( &strm, verbosity, small ); + if (ret != BZ_OK) return ret; + + strm.next_in = source; + strm.next_out = dest; + strm.avail_in = sourceLen; + strm.avail_out = *destLen; + + ret = BZ2_bzDecompress ( &strm ); + if (ret == BZ_OK) goto output_overflow_or_eof; + if (ret != BZ_STREAM_END) goto errhandler; + + /* normal termination */ + *destLen -= strm.avail_out; + BZ2_bzDecompressEnd ( &strm ); + return BZ_OK; + + output_overflow_or_eof: + if (strm.avail_out > 0) { + BZ2_bzDecompressEnd ( &strm ); + return BZ_UNEXPECTED_EOF; + } else { + BZ2_bzDecompressEnd ( &strm ); + return BZ_OUTBUFF_FULL; + }; + + errhandler: + BZ2_bzDecompressEnd ( &strm ); + return ret; +} + + +/*---------------------------------------------------*/ +/*-- + Code contributed by Yoshioka Tsuneo + (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +/*-- + return version like "0.9.0c". +--*/ +const char * BZ_API(BZ2_bzlibVersion)(void) +{ + return BZ_VERSION; +} + + +#ifndef BZ_NO_STDIO +/*---------------------------------------------------*/ + +#if defined(_WIN32) || defined(OS2) || defined(MSDOS) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif +static +BZFILE * bzopen_or_bzdopen + ( const char *path, /* no use when bzdopen */ + int fd, /* no use when bzdopen */ + const char *mode, + int open_mode) /* bzopen: 0, bzdopen:1 */ +{ + int bzerr; + char unused[BZ_MAX_UNUSED]; + int blockSize100k = 9; + int writing = 0; + char mode2[10] = ""; + FILE *fp = NULL; + BZFILE *bzfp = NULL; + int verbosity = 0; + int workFactor = 30; + int smallMode = 0; + int nUnused = 0; + + if (mode == NULL) return NULL; + while (*mode) { + switch (*mode) { + case 'r': + writing = 0; break; + case 'w': + writing = 1; break; + case 's': + smallMode = 1; break; + default: + if (isdigit((int)(*mode))) { + blockSize100k = *mode-'0'; + } + } + mode++; + } + strcat(mode2, writing ? "w" : "r" ); + strcat(mode2,"b"); /* binary mode */ + + if (open_mode==0) { + if (path==NULL || strcmp(path,"")==0) { + fp = (writing ? stdout : stdin); + SET_BINARY_MODE(fp); + } else { + fp = fopen(path,mode2); + } + } else { +#ifdef BZ_STRICT_ANSI + fp = NULL; +#else + fp = fdopen(fd,mode2); +#endif + } + if (fp == NULL) return NULL; + + if (writing) { + /* Guard against total chaos and anarchy -- JRS */ + if (blockSize100k < 1) blockSize100k = 1; + if (blockSize100k > 9) blockSize100k = 9; + bzfp = BZ2_bzWriteOpen(&bzerr,fp,blockSize100k, + verbosity,workFactor); + } else { + bzfp = BZ2_bzReadOpen(&bzerr,fp,verbosity,smallMode, + unused,nUnused); + } + if (bzfp == NULL) { + if (fp != stdin && fp != stdout) fclose(fp); + return NULL; + } + return bzfp; +} + + +/*---------------------------------------------------*/ +/*-- + open file for read or write. + ex) bzopen("file","w9") + case path="" or NULL => use stdin or stdout. +--*/ +BZFILE * BZ_API(BZ2_bzopen) + ( const char *path, + const char *mode ) +{ + return bzopen_or_bzdopen(path,-1,mode,/*bzopen*/0); +} + + +/*---------------------------------------------------*/ +BZFILE * BZ_API(BZ2_bzdopen) + ( int fd, + const char *mode ) +{ + return bzopen_or_bzdopen(NULL,fd,mode,/*bzdopen*/1); +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzread) (BZFILE* b, void* buf, int len ) +{ + int bzerr, nread; + if (((bzFile*)b)->lastErr == BZ_STREAM_END) return 0; + nread = BZ2_bzRead(&bzerr,b,buf,len); + if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) { + return nread; + } else { + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzwrite) (BZFILE* b, void* buf, int len ) +{ + int bzerr; + + BZ2_bzWrite(&bzerr,b,buf,len); + if(bzerr == BZ_OK){ + return len; + }else{ + return -1; + } +} + + +/*---------------------------------------------------*/ +int BZ_API(BZ2_bzflush) (BZFILE *b) +{ + /* do nothing now... */ + return 0; +} + + +/*---------------------------------------------------*/ +void BZ_API(BZ2_bzclose) (BZFILE* b) +{ + int bzerr; + FILE *fp = ((bzFile *)b)->handle; + + if (b==NULL) {return;} + if(((bzFile*)b)->writing){ + BZ2_bzWriteClose(&bzerr,b,0,NULL,NULL); + if(bzerr != BZ_OK){ + BZ2_bzWriteClose(NULL,b,1,NULL,NULL); + } + }else{ + BZ2_bzReadClose(&bzerr,b); + } + if(fp!=stdin && fp!=stdout){ + fclose(fp); + } +} + + +/*---------------------------------------------------*/ +/*-- + return last error code +--*/ +static char *bzerrorstrings[] = { + "OK" + ,"SEQUENCE_ERROR" + ,"PARAM_ERROR" + ,"MEM_ERROR" + ,"DATA_ERROR" + ,"DATA_ERROR_MAGIC" + ,"IO_ERROR" + ,"UNEXPECTED_EOF" + ,"OUTBUFF_FULL" + ,"CONFIG_ERROR" + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ +}; + + +const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) +{ + int err = ((bzFile *)b)->lastErr; + + if(err>0) err = 0; + *errnum = err; + return bzerrorstrings[err*-1]; +} +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/bzlib.h b/drivers/lib/bzip2/bzlib.h new file mode 100644 index 0000000..41a155d --- /dev/null +++ b/drivers/lib/bzip2/bzlib.h @@ -0,0 +1,323 @@ + +/*-------------------------------------------------------------*/ +/*--- Public header file for the library. ---*/ +/*--- bzlib.h ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#ifndef _BZLIB_H +#define _BZLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define BZ_RUN 0 +#define BZ_FLUSH 1 +#define BZ_FINISH 2 + +#define BZ_OK 0 +#define BZ_RUN_OK 1 +#define BZ_FLUSH_OK 2 +#define BZ_FINISH_OK 3 +#define BZ_STREAM_END 4 +#define BZ_SEQUENCE_ERROR (-1) +#define BZ_PARAM_ERROR (-2) +#define BZ_MEM_ERROR (-3) +#define BZ_DATA_ERROR (-4) +#define BZ_DATA_ERROR_MAGIC (-5) +#define BZ_IO_ERROR (-6) +#define BZ_UNEXPECTED_EOF (-7) +#define BZ_OUTBUFF_FULL (-8) +#define BZ_CONFIG_ERROR (-9) + +typedef + struct { + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *,int,int); + void (*bzfree)(void *,void *); + void *opaque; + } + bz_stream; + + +#ifndef BZ_IMPORT +#define BZ_EXPORT +#endif + +#ifdef _WIN32 +# include +# include +# ifdef small + /* windows.h define small to char */ +# undef small +# endif +# ifdef BZ_EXPORT +# define BZ_API(func) WINAPI func +# define BZ_EXTERN extern +# else + /* import windows dll dynamically */ +# define BZ_API(func) (WINAPI * func) +# define BZ_EXTERN +# endif +#else +# define BZ_API(func) func +# define BZ_EXTERN extern +#endif + + +/*-- Core (low-level) library functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzCompressInit) ( + bz_stream* strm, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompress) ( + bz_stream* strm, + int action + ); + +BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) ( + bz_stream *strm, + int verbosity, + int small + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompress) ( + bz_stream* strm + ); + +BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) ( + bz_stream *strm + ); + + + +/*-- High(er) level library functions --*/ + +#ifndef BZ_NO_STDIO +#define BZ_MAX_UNUSED 5000 + +typedef void BZFILE; + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) ( + int* bzerror, + FILE* f, + int verbosity, + int small, + void* unused, + int nUnused + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadClose) ( + int* bzerror, + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) ( + int* bzerror, + BZFILE* b, + void** unused, + int* nUnused + ); + +BZ_EXTERN int BZ_API(BZ2_bzRead) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) ( + int* bzerror, + FILE* f, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN void BZ_API(BZ2_bzWrite) ( + int* bzerror, + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out + ); + +BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) ( + int* bzerror, + BZFILE* b, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 + ); +#endif + + +/*-- Utility functions --*/ + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor + ); + +BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) ( + char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity + ); + + +/*-- + Code contributed by Yoshioka Tsuneo + (QWF00133@niftyserve.or.jp/tsuneo-y@is.aist-nara.ac.jp), + to support better zlib compatibility. + This code is not _officially_ part of libbzip2 (yet); + I haven't tested it, documented it, or considered the + threading-safeness of it. + If this code breaks, please contact both Yoshioka and me. +--*/ + +BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) ( + void + ); + +#ifndef BZ_NO_STDIO +BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) ( + const char *path, + const char *mode + ); + +BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) ( + int fd, + const char *mode + ); + +BZ_EXTERN int BZ_API(BZ2_bzread) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzwrite) ( + BZFILE* b, + void* buf, + int len + ); + +BZ_EXTERN int BZ_API(BZ2_bzflush) ( + BZFILE* b + ); + +BZ_EXTERN void BZ_API(BZ2_bzclose) ( + BZFILE* b + ); + +BZ_EXTERN const char * BZ_API(BZ2_bzerror) ( + BZFILE *b, + int *errnum + ); +#endif + +extern _stdcall void *(*BZ2_malloc)( unsigned long size ); +extern _stdcall void (*BZ2_free)( void *ptr ); +_stdcall void BZ2_set_malloc_free( _stdcall void *(*malloc)(unsigned long size), _stdcall void (*free)(void *ptr) ); + +#ifdef __cplusplus +} +#endif + +#endif + +/*-------------------------------------------------------------*/ +/*--- end bzlib.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/bzlib_private.h b/drivers/lib/bzip2/bzlib_private.h new file mode 100644 index 0000000..fb51c7a --- /dev/null +++ b/drivers/lib/bzip2/bzlib_private.h @@ -0,0 +1,530 @@ + +/*-------------------------------------------------------------*/ +/*--- Private header file for the library. ---*/ +/*--- bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#ifndef _BZLIB_PRIVATE_H +#define _BZLIB_PRIVATE_H + +#include + +#ifndef BZ_NO_STDIO +#include +#include +#include +#endif + +#include "bzlib.h" + + + +/*-- General stuff. --*/ + +#define BZ_VERSION "1.0.1, 23-June-2000" + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +#define True ((Bool)1) +#define False ((Bool)0) + +#ifndef __GNUC__ +#define __inline__ /* */ +#endif + +#ifndef BZ_NO_STDIO +extern void BZ2_bz__AssertH__fail ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); } +#if BZ_DEBUG +#define AssertD(cond,msg) \ + { if (!(cond)) { \ + fprintf ( stderr, \ + "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\ + exit(1); \ + }} +#else +#define AssertD(cond,msg) /* */ +#endif +#define VPrintf0(zf) \ + fprintf(stderr,zf) +#define VPrintf1(zf,za1) \ + fprintf(stderr,zf,za1) +#define VPrintf2(zf,za1,za2) \ + fprintf(stderr,zf,za1,za2) +#define VPrintf3(zf,za1,za2,za3) \ + fprintf(stderr,zf,za1,za2,za3) +#define VPrintf4(zf,za1,za2,za3,za4) \ + fprintf(stderr,zf,za1,za2,za3,za4) +#define VPrintf5(zf,za1,za2,za3,za4,za5) \ + fprintf(stderr,zf,za1,za2,za3,za4,za5) +#else +extern void bz_internal_error ( int errcode ); +#define AssertH(cond,errcode) \ + { if (!(cond)) bz_internal_error ( errcode ); } +#define AssertD(cond,msg) /* */ +#define VPrintf0(zf) /* */ +#define VPrintf1(zf,za1) /* */ +#define VPrintf2(zf,za1,za2) /* */ +#define VPrintf3(zf,za1,za2,za3) /* */ +#define VPrintf4(zf,za1,za2,za3,za4) /* */ +#define VPrintf5(zf,za1,za2,za3,za4,za5) /* */ +#endif + + +#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1) +#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp)) + + +/*-- Constants for the back end. --*/ + +#define BZ_MAX_ALPHA_SIZE 258 +#define BZ_MAX_CODE_LEN 23 + +#define BZ_RUNA 0 +#define BZ_RUNB 1 + +#define BZ_N_GROUPS 6 +#define BZ_G_SIZE 50 +#define BZ_N_ITERS 4 + +#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE)) + + + +/*-- Stuff for randomising repetitive blocks. --*/ + +extern Int32 BZ2_rNums[512]; + +#define BZ_RAND_DECLS \ + Int32 rNToGo; \ + Int32 rTPos \ + +#define BZ_RAND_INIT_MASK \ + s->rNToGo = 0; \ + s->rTPos = 0 \ + +#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0) + +#define BZ_RAND_UPD_MASK \ + if (s->rNToGo == 0) { \ + s->rNToGo = BZ2_rNums[s->rTPos]; \ + s->rTPos++; \ + if (s->rTPos == 512) s->rTPos = 0; \ + } \ + s->rNToGo--; + + + +/*-- Stuff for doing CRCs. --*/ + +extern UInt32 BZ2_crc32Table[256]; + +#define BZ_INITIALISE_CRC(crcVar) \ +{ \ + crcVar = 0xffffffffL; \ +} + +#define BZ_FINALISE_CRC(crcVar) \ +{ \ + crcVar = ~(crcVar); \ +} + +#define BZ_UPDATE_CRC(crcVar,cha) \ +{ \ + crcVar = (crcVar << 8) ^ \ + BZ2_crc32Table[(crcVar >> 24) ^ \ + ((UChar)cha)]; \ +} + + + +/*-- States and modes for compression. --*/ + +#define BZ_M_IDLE 1 +#define BZ_M_RUNNING 2 +#define BZ_M_FLUSHING 3 +#define BZ_M_FINISHING 4 + +#define BZ_S_OUTPUT 1 +#define BZ_S_INPUT 2 + +#define BZ_N_RADIX 2 +#define BZ_N_QSORT 12 +#define BZ_N_SHELL 18 +#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2) + + + + +/*-- Structure holding all the compression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* mode this stream is in, and whether inputting */ + /* or outputting data */ + Int32 mode; + Int32 state; + + /* remembers avail_in when flush/finish requested */ + UInt32 avail_in_expect; + + /* for doing the block sorting */ + UInt32* arr1; + UInt32* arr2; + UInt32* ftab; + Int32 origPtr; + + /* aliases for arr1 and arr2 */ + UInt32* ptr; + UChar* block; + UInt16* mtfv; + UChar* zbits; + + /* for deciding when to use the fallback sorting algorithm */ + Int32 workFactor; + + /* run-length-encoding of the input */ + UInt32 state_in_ch; + Int32 state_in_len; + BZ_RAND_DECLS; + + /* input and output limits and current posns */ + Int32 nblock; + Int32 nblockMAX; + Int32 numZ; + Int32 state_out_pos; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + UChar unseqToSeq[256]; + + /* the buffer for bit stream creation */ + UInt32 bsBuff; + Int32 bsLive; + + /* block and combined CRCs */ + UInt32 blockCRC; + UInt32 combinedCRC; + + /* misc administratium */ + Int32 verbosity; + Int32 blockNo; + Int32 blockSize100k; + + /* stuff for coding the MTF values */ + Int32 nMTF; + Int32 mtfFreq [BZ_MAX_ALPHA_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + /* second dimension: only 3 needed; 4 makes index calculations faster */ + UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4]; + + } + EState; + + + +/*-- externs for compression. --*/ + +extern void +BZ2_blockSort ( EState* ); + +extern void +BZ2_compressBlock ( EState*, Bool ); + +extern void +BZ2_bsInitWrite ( EState* ); + +extern void +BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 ); + +extern void +BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 ); + + + +/*-- states for decompression. --*/ + +#define BZ_X_IDLE 1 +#define BZ_X_OUTPUT 2 + +#define BZ_X_MAGIC_1 10 +#define BZ_X_MAGIC_2 11 +#define BZ_X_MAGIC_3 12 +#define BZ_X_MAGIC_4 13 +#define BZ_X_BLKHDR_1 14 +#define BZ_X_BLKHDR_2 15 +#define BZ_X_BLKHDR_3 16 +#define BZ_X_BLKHDR_4 17 +#define BZ_X_BLKHDR_5 18 +#define BZ_X_BLKHDR_6 19 +#define BZ_X_BCRC_1 20 +#define BZ_X_BCRC_2 21 +#define BZ_X_BCRC_3 22 +#define BZ_X_BCRC_4 23 +#define BZ_X_RANDBIT 24 +#define BZ_X_ORIGPTR_1 25 +#define BZ_X_ORIGPTR_2 26 +#define BZ_X_ORIGPTR_3 27 +#define BZ_X_MAPPING_1 28 +#define BZ_X_MAPPING_2 29 +#define BZ_X_SELECTOR_1 30 +#define BZ_X_SELECTOR_2 31 +#define BZ_X_SELECTOR_3 32 +#define BZ_X_CODING_1 33 +#define BZ_X_CODING_2 34 +#define BZ_X_CODING_3 35 +#define BZ_X_MTF_1 36 +#define BZ_X_MTF_2 37 +#define BZ_X_MTF_3 38 +#define BZ_X_MTF_4 39 +#define BZ_X_MTF_5 40 +#define BZ_X_MTF_6 41 +#define BZ_X_ENDHDR_2 42 +#define BZ_X_ENDHDR_3 43 +#define BZ_X_ENDHDR_4 44 +#define BZ_X_ENDHDR_5 45 +#define BZ_X_ENDHDR_6 46 +#define BZ_X_CCRC_1 47 +#define BZ_X_CCRC_2 48 +#define BZ_X_CCRC_3 49 +#define BZ_X_CCRC_4 50 + + + +/*-- Constants for the fast MTF decoder. --*/ + +#define MTFA_SIZE 4096 +#define MTFL_SIZE 16 + + + +/*-- Structure holding all the decompression-side stuff. --*/ + +typedef + struct { + /* pointer back to the struct bz_stream */ + bz_stream* strm; + + /* state indicator for this stream */ + Int32 state; + + /* for doing the final run-length decoding */ + UChar state_out_ch; + Int32 state_out_len; + Bool blockRandomised; + BZ_RAND_DECLS; + + /* the buffer for bit stream reading */ + UInt32 bsBuff; + Int32 bsLive; + + /* misc administratium */ + Int32 blockSize100k; + Bool smallDecompress; + Int32 currBlockNo; + Int32 verbosity; + + /* for undoing the Burrows-Wheeler transform */ + Int32 origPtr; + UInt32 tPos; + Int32 k0; + Int32 unzftab[256]; + Int32 nblock_used; + Int32 cftab[257]; + Int32 cftabCopy[257]; + + /* for undoing the Burrows-Wheeler transform (FAST) */ + UInt32 *tt; + + /* for undoing the Burrows-Wheeler transform (SMALL) */ + UInt16 *ll16; + UChar *ll4; + + /* stored and calculated CRCs */ + UInt32 storedBlockCRC; + UInt32 storedCombinedCRC; + UInt32 calculatedBlockCRC; + UInt32 calculatedCombinedCRC; + + /* map of bytes used in block */ + Int32 nInUse; + Bool inUse[256]; + Bool inUse16[16]; + UChar seqToUnseq[256]; + + /* for decoding the MTF values */ + UChar mtfa [MTFA_SIZE]; + Int32 mtfbase[256 / MTFL_SIZE]; + UChar selector [BZ_MAX_SELECTORS]; + UChar selectorMtf[BZ_MAX_SELECTORS]; + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + + Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 minLens[BZ_N_GROUPS]; + + /* save area for scalars in the main decompress code */ + Int32 save_i; + Int32 save_j; + Int32 save_t; + Int32 save_alphaSize; + Int32 save_nGroups; + Int32 save_nSelectors; + Int32 save_EOB; + Int32 save_groupNo; + Int32 save_groupPos; + Int32 save_nextSym; + Int32 save_nblockMAX; + Int32 save_nblock; + Int32 save_es; + Int32 save_N; + Int32 save_curr; + Int32 save_zt; + Int32 save_zn; + Int32 save_zvec; + Int32 save_zj; + Int32 save_gSel; + Int32 save_gMinlen; + Int32* save_gLimit; + Int32* save_gBase; + Int32* save_gPerm; + + } + DState; + + + +/*-- Macros for decompression. --*/ + +#define BZ_GET_FAST(cccc) \ + s->tPos = s->tt[s->tPos]; \ + cccc = (UChar)(s->tPos & 0xff); \ + s->tPos >>= 8; + +#define BZ_GET_FAST_C(cccc) \ + c_tPos = c_tt[c_tPos]; \ + cccc = (UChar)(c_tPos & 0xff); \ + c_tPos >>= 8; + +#define SET_LL4(i,n) \ + { if (((i) & 0x1) == 0) \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \ + s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \ + } + +#define GET_LL4(i) \ + ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF) + +#define SET_LL(i,n) \ + { s->ll16[i] = (UInt16)(n & 0x0000ffff); \ + SET_LL4(i, n >> 16); \ + } + +#define GET_LL(i) \ + (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) + +#define BZ_GET_SMALL(cccc) \ + cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ + s->tPos = GET_LL(s->tPos); + + +/*-- externs for decompression. --*/ + +extern Int32 +BZ2_indexIntoF ( Int32, Int32* ); + +extern Int32 +BZ2_decompress ( DState* ); + +extern void +BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*, + Int32, Int32, Int32 ); + + +#endif + + +/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/ + +#ifdef BZ_NO_STDIO +#ifndef NULL +#define NULL 0 +#endif +#endif + + +/*-------------------------------------------------------------*/ +/*--- end bzlib_private.h ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/compress.c b/drivers/lib/bzip2/compress.c new file mode 100644 index 0000000..cc5e31d --- /dev/null +++ b/drivers/lib/bzip2/compress.c @@ -0,0 +1,714 @@ + +/*-------------------------------------------------------------*/ +/*--- Compression machinery (not incl block sorting) ---*/ +/*--- compress.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + +/*-- + CHANGES + ~~~~~~~ + 0.9.0 -- original version. + + 0.9.0a/b -- no changes in this file. + + 0.9.0c + * changed setting of nGroups in sendMTFValues() so as to + do a bit better on small files +--*/ + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +/*--- Bit stream I/O ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +void BZ2_bsInitWrite ( EState* s ) +{ + s->bsLive = 0; + s->bsBuff = 0; +} + + +/*---------------------------------------------------*/ +static +void bsFinishWrite ( EState* s ) +{ + while (s->bsLive > 0) { + s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); + s->numZ++; + s->bsBuff <<= 8; + s->bsLive -= 8; + } +} + + +/*---------------------------------------------------*/ +#define bsNEEDW(nz) \ +{ \ + while (s->bsLive >= 8) { \ + s->zbits[s->numZ] \ + = (UChar)(s->bsBuff >> 24); \ + s->numZ++; \ + s->bsBuff <<= 8; \ + s->bsLive -= 8; \ + } \ +} + + +/*---------------------------------------------------*/ +static +__inline__ +void bsW ( EState* s, Int32 n, UInt32 v ) +{ + bsNEEDW ( n ); + s->bsBuff |= (v << (32 - s->bsLive - n)); + s->bsLive += n; +} + + +/*---------------------------------------------------*/ +static +void bsPutUInt32 ( EState* s, UInt32 u ) +{ + bsW ( s, 8, (u >> 24) & 0xffL ); + bsW ( s, 8, (u >> 16) & 0xffL ); + bsW ( s, 8, (u >> 8) & 0xffL ); + bsW ( s, 8, u & 0xffL ); +} + + +/*---------------------------------------------------*/ +static +void bsPutUChar ( EState* s, UChar c ) +{ + bsW( s, 8, (UInt32)c ); +} + + +/*---------------------------------------------------*/ +/*--- The back end proper ---*/ +/*---------------------------------------------------*/ + +/*---------------------------------------------------*/ +static +void makeMaps_e ( EState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->unseqToSeq[i] = s->nInUse; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +static +void generateMTFValues ( EState* s ) +{ + UChar yy[256]; + Int32 i, j; + Int32 zPend; + Int32 wr; + Int32 EOB; + + /* + After sorting (eg, here), + s->arr1 [ 0 .. s->nblock-1 ] holds sorted order, + and + ((UChar*)s->arr2) [ 0 .. s->nblock-1 ] + holds the original block data. + + The first thing to do is generate the MTF values, + and put them in + ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ]. + Because there are strictly fewer or equal MTF values + than block values, ptr values in this area are overwritten + with MTF values only when they are no longer needed. + + The final compressed bitstream is generated into the + area starting at + (UChar*) (&((UChar*)s->arr2)[s->nblock]) + + These storage aliases are set up in bzCompressInit(), + except for the last one, which is arranged in + compressBlock(). + */ + UInt32* ptr = s->ptr; + UChar* block = s->block; + UInt16* mtfv = s->mtfv; + + makeMaps_e ( s ); + EOB = s->nInUse+1; + + for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0; + + wr = 0; + zPend = 0; + for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i; + + for (i = 0; i < s->nblock; i++) { + UChar ll_i; + AssertD ( wr <= i, "generateMTFValues(1)" ); + j = ptr[i]-1; if (j < 0) j += s->nblock; + ll_i = s->unseqToSeq[block[j]]; + AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" ); + + if (yy[0] == ll_i) { + zPend++; + } else { + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + { + register UChar rtmp; + register UChar* ryy_j; + register UChar rll_i; + rtmp = yy[1]; + yy[1] = yy[0]; + ryy_j = &(yy[1]); + rll_i = ll_i; + while ( rll_i != rtmp ) { + register UChar rtmp2; + ryy_j++; + rtmp2 = rtmp; + rtmp = *ryy_j; + *ryy_j = rtmp2; + }; + yy[0] = rtmp; + j = ryy_j - &(yy[0]); + mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++; + } + + } + } + + if (zPend > 0) { + zPend--; + while (True) { + if (zPend & 1) { + mtfv[wr] = BZ_RUNB; wr++; + s->mtfFreq[BZ_RUNB]++; + } else { + mtfv[wr] = BZ_RUNA; wr++; + s->mtfFreq[BZ_RUNA]++; + } + if (zPend < 2) break; + zPend = (zPend - 2) / 2; + }; + zPend = 0; + } + + mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++; + + s->nMTF = wr; +} + + +/*---------------------------------------------------*/ +#define BZ_LESSER_ICOST 0 +#define BZ_GREATER_ICOST 15 + +static +void sendMTFValues ( EState* s ) +{ + Int32 v, t, i, j, gs, ge, totc, bt, bc, iter; + Int32 nSelectors, alphaSize, minLen, maxLen, selCtr; + Int32 nGroups, nBytes; + + /*-- + UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + is a global since the decoder also needs it. + + Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; + are also globals only used in this proc. + Made global to keep stack frame size small. + --*/ + + + UInt16 cost[BZ_N_GROUPS]; + Int32 fave[BZ_N_GROUPS]; + + UInt16* mtfv = s->mtfv; + + if (s->verbosity >= 3) + VPrintf3( " %d in block, %d after MTF & 1-2 coding, " + "%d+2 syms in use\n", + s->nblock, s->nMTF, s->nInUse ); + + alphaSize = s->nInUse+2; + for (t = 0; t < BZ_N_GROUPS; t++) + for (v = 0; v < alphaSize; v++) + s->len[t][v] = BZ_GREATER_ICOST; + + /*--- Decide how many coding tables to use ---*/ + AssertH ( s->nMTF > 0, 3001 ); + if (s->nMTF < 200) nGroups = 2; else + if (s->nMTF < 600) nGroups = 3; else + if (s->nMTF < 1200) nGroups = 4; else + if (s->nMTF < 2400) nGroups = 5; else + nGroups = 6; + + /*--- Generate an initial set of coding tables ---*/ + { + Int32 nPart, remF, tFreq, aFreq; + + nPart = nGroups; + remF = s->nMTF; + gs = 0; + while (nPart > 0) { + tFreq = remF / nPart; + ge = gs-1; + aFreq = 0; + while (aFreq < tFreq && ge < alphaSize-1) { + ge++; + aFreq += s->mtfFreq[ge]; + } + + if (ge > gs + && nPart != nGroups && nPart != 1 + && ((nGroups-nPart) % 2 == 1)) { + aFreq -= s->mtfFreq[ge]; + ge--; + } + + if (s->verbosity >= 3) + VPrintf5( " initial group %d, [%d .. %d], " + "has %d syms (%4.1f%%)\n", + nPart, gs, ge, aFreq, + (100.0 * (float)aFreq) / (float)(s->nMTF) ); + + for (v = 0; v < alphaSize; v++) + if (v >= gs && v <= ge) + s->len[nPart-1][v] = BZ_LESSER_ICOST; else + s->len[nPart-1][v] = BZ_GREATER_ICOST; + + nPart--; + gs = ge+1; + remF -= aFreq; + } + } + + /*--- + Iterate up to BZ_N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZ_N_ITERS; iter++) { + + for (t = 0; t < nGroups; t++) fave[t] = 0; + + for (t = 0; t < nGroups; t++) + for (v = 0; v < alphaSize; v++) + s->rfreq[t][v] = 0; + + /*--- + Set up an auxiliary length table which is used to fast-track + the common case (nGroups == 6). + ---*/ + if (nGroups == 6) { + for (v = 0; v < alphaSize; v++) { + s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v]; + s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v]; + s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v]; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (True) { + + /*--- Set group start & end marks. --*/ + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (t = 0; t < nGroups; t++) cost[t] = 0; + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + register UInt32 cost01, cost23, cost45; + register UInt16 icv; + cost01 = cost23 = cost45 = 0; + +# define BZ_ITER(nn) \ + icv = mtfv[gs+(nn)]; \ + cost01 += s->len_pack[icv][0]; \ + cost23 += s->len_pack[icv][1]; \ + cost45 += s->len_pack[icv][2]; \ + + BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4); + BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9); + BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14); + BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19); + BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24); + BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29); + BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34); + BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39); + BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44); + BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49); + +# undef BZ_ITER + + cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; + cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; + cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + UInt16 icv = mtfv[i]; + for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv]; + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; bt = -1; + for (t = 0; t < nGroups; t++) + if (cost[t] < bc) { bc = cost[t]; bt = t; }; + totc += bc; + fave[bt]++; + s->selector[nSelectors] = bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + +# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++ + + BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4); + BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9); + BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14); + BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19); + BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24); + BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29); + BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34); + BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39); + BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44); + BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49); + +# undef BZ_ITUR + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) + s->rfreq[bt][ mtfv[i] ]++; + } + + gs = ge+1; + } + if (s->verbosity >= 3) { + VPrintf2 ( " pass %d: size is %d, grp uses are ", + iter+1, totc/8 ); + for (t = 0; t < nGroups; t++) + VPrintf1 ( "%d ", fave[t] ); + VPrintf0 ( "\n" ); + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + for (t = 0; t < nGroups; t++) + BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), + alphaSize, 20 ); + } + + + AssertH( nGroups < 8, 3002 ); + AssertH( nSelectors < 32768 && + nSelectors <= (2 + (900000 / BZ_G_SIZE)), + 3003 ); + + + /*--- Compute MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp; + for (i = 0; i < nGroups; i++) pos[i] = i; + for (i = 0; i < nSelectors; i++) { + ll_i = s->selector[i]; + j = 0; + tmp = pos[j]; + while ( ll_i != tmp ) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + }; + pos[0] = tmp; + s->selectorMtf[i] = j; + } + }; + + /*--- Assign actual codes for the tables. --*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + AssertH ( !(maxLen > 20), 3004 ); + AssertH ( !(minLen < 1), 3005 ); + BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), + minLen, maxLen, alphaSize ); + } + + /*--- Transmit the mapping table. ---*/ + { + Bool inUse16[16]; + for (i = 0; i < 16; i++) { + inUse16[i] = False; + for (j = 0; j < 16; j++) + if (s->inUse[i * 16 + j]) inUse16[i] = True; + } + + nBytes = s->numZ; + for (i = 0; i < 16; i++) + if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0); + + for (i = 0; i < 16; i++) + if (inUse16[i]) + for (j = 0; j < 16; j++) { + if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0); + } + + if (s->verbosity >= 3) + VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes ); + } + + /*--- Now the selectors. ---*/ + nBytes = s->numZ; + bsW ( s, 3, nGroups ); + bsW ( s, 15, nSelectors ); + for (i = 0; i < nSelectors; i++) { + for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1); + bsW(s,1,0); + } + if (s->verbosity >= 3) + VPrintf1( "selectors %d, ", s->numZ-nBytes ); + + /*--- Now the coding tables. ---*/ + nBytes = s->numZ; + + for (t = 0; t < nGroups; t++) { + Int32 curr = s->len[t][0]; + bsW ( s, 5, curr ); + for (i = 0; i < alphaSize; i++) { + while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ }; + while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ }; + bsW ( s, 1, 0 ); + } + } + + if (s->verbosity >= 3) + VPrintf1 ( "code lengths %d, ", s->numZ-nBytes ); + + /*--- And finally, the block data proper ---*/ + nBytes = s->numZ; + selCtr = 0; + gs = 0; + while (True) { + if (gs >= s->nMTF) break; + ge = gs + BZ_G_SIZE - 1; + if (ge >= s->nMTF) ge = s->nMTF-1; + AssertH ( s->selector[selCtr] < nGroups, 3006 ); + + if (nGroups == 6 && 50 == ge-gs+1) { + /*--- fast track the common case ---*/ + UInt16 mtfv_i; + UChar* s_len_sel_selCtr + = &(s->len[s->selector[selCtr]][0]); + Int32* s_code_sel_selCtr + = &(s->code[s->selector[selCtr]][0]); + +# define BZ_ITAH(nn) \ + mtfv_i = mtfv[gs+(nn)]; \ + bsW ( s, \ + s_len_sel_selCtr[mtfv_i], \ + s_code_sel_selCtr[mtfv_i] ) + + BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4); + BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9); + BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14); + BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19); + BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24); + BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29); + BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34); + BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39); + BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44); + BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49); + +# undef BZ_ITAH + + } else { + /*--- slow version which correctly handles all situations ---*/ + for (i = gs; i <= ge; i++) { + bsW ( s, + s->len [s->selector[selCtr]] [mtfv[i]], + s->code [s->selector[selCtr]] [mtfv[i]] ); + } + } + + + gs = ge+1; + selCtr++; + } + AssertH( selCtr == nSelectors, 3007 ); + + if (s->verbosity >= 3) + VPrintf1( "codes %d\n", s->numZ-nBytes ); +} + + +/*---------------------------------------------------*/ +void BZ2_compressBlock ( EState* s, Bool is_last_block ) +{ + if (s->nblock > 0) { + + BZ_FINALISE_CRC ( s->blockCRC ); + s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31); + s->combinedCRC ^= s->blockCRC; + if (s->blockNo > 1) s->numZ = 0; + + if (s->verbosity >= 2) + VPrintf4( " block %d: crc = 0x%8x, " + "combined CRC = 0x%8x, size = %d\n", + s->blockNo, s->blockCRC, s->combinedCRC, s->nblock ); + + BZ2_blockSort ( s ); + } + + s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]); + + /*-- If this is the first block, create the stream header. --*/ + if (s->blockNo == 1) { + BZ2_bsInitWrite ( s ); + bsPutUChar ( s, 'B' ); + bsPutUChar ( s, 'Z' ); + bsPutUChar ( s, 'h' ); + bsPutUChar ( s, (UChar)('0' + s->blockSize100k) ); + } + + if (s->nblock > 0) { + + bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 ); + bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 ); + bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 ); + + /*-- Now the block's CRC, so it is in a known place. --*/ + bsPutUInt32 ( s, s->blockCRC ); + + /*-- + Now a single bit indicating (non-)randomisation. + As of version 0.9.5, we use a better sorting algorithm + which makes randomisation unnecessary. So always set + the randomised bit to 'no'. Of course, the decoder + still needs to be able to handle randomised blocks + so as to maintain backwards compatibility with + older versions of bzip2. + --*/ + bsW(s,1,0); + + bsW ( s, 24, s->origPtr ); + generateMTFValues ( s ); + sendMTFValues ( s ); + } + + + /*-- If this is the last block, add the stream trailer. --*/ + if (is_last_block) { + + bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 ); + bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 ); + bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); + bsPutUInt32 ( s, s->combinedCRC ); + if (s->verbosity >= 2) + VPrintf1( " final combined CRC = 0x%x\n ", s->combinedCRC ); + bsFinishWrite ( s ); + } +} + + +/*-------------------------------------------------------------*/ +/*--- end compress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/crctable.c b/drivers/lib/bzip2/crctable.c new file mode 100644 index 0000000..61c040c --- /dev/null +++ b/drivers/lib/bzip2/crctable.c @@ -0,0 +1,144 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for doing CRCs ---*/ +/*--- crctable.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + +/*-- + I think this is an implementation of the AUTODIN-II, + Ethernet & FDDI 32-bit CRC standard. Vaguely derived + from code by Rob Warnock, in Section 51 of the + comp.compression FAQ. +--*/ + +UInt32 BZ2_crc32Table[256] = { + + /*-- Ugly, innit? --*/ + + 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, + 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, + 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, + 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, + 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, + 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, + 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, + 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, + 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, + 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, + 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, + 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, + 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, + 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, + 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, + 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, + 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, + 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, + 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, + 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, + 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, + 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, + 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, + 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, + 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, + 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, + 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, + 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, + 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, + 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, + 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, + 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, + 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, + 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, + 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, + 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, + 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, + 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, + 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, + 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, + 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, + 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, + 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, + 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, + 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, + 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, + 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, + 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, + 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, + 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, + 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, + 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, + 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, + 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, + 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, + 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, + 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, + 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, + 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, + 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, + 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, + 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, + 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, + 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L +}; + + +/*-------------------------------------------------------------*/ +/*--- end crctable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/decompress.c b/drivers/lib/bzip2/decompress.c new file mode 100644 index 0000000..cdced18 --- /dev/null +++ b/drivers/lib/bzip2/decompress.c @@ -0,0 +1,660 @@ + +/*-------------------------------------------------------------*/ +/*--- Decompression machinery ---*/ +/*--- decompress.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------------*/ +static +void makeMaps_d ( DState* s ) +{ + Int32 i; + s->nInUse = 0; + for (i = 0; i < 256; i++) + if (s->inUse[i]) { + s->seqToUnseq[s->nInUse] = i; + s->nInUse++; + } +} + + +/*---------------------------------------------------*/ +#define RETURN(rrr) \ + { retVal = rrr; goto save_state_and_return; }; + +#define GET_BITS(lll,vvv,nnn) \ + case lll: s->state = lll; \ + while (True) { \ + if (s->bsLive >= nnn) { \ + UInt32 v; \ + v = (s->bsBuff >> \ + (s->bsLive-nnn)) & ((1 << nnn)-1); \ + s->bsLive -= nnn; \ + vvv = v; \ + break; \ + } \ + if (s->strm->avail_in == 0) RETURN(BZ_OK); \ + s->bsBuff \ + = (s->bsBuff << 8) | \ + ((UInt32) \ + (*((UChar*)(s->strm->next_in)))); \ + s->bsLive += 8; \ + s->strm->next_in++; \ + s->strm->avail_in--; \ + s->strm->total_in_lo32++; \ + if (s->strm->total_in_lo32 == 0) \ + s->strm->total_in_hi32++; \ + } + +#define GET_UCHAR(lll,uuu) \ + GET_BITS(lll,uuu,8) + +#define GET_BIT(lll,uuu) \ + GET_BITS(lll,uuu,1) + +/*---------------------------------------------------*/ +#define GET_MTF_VAL(label1,label2,lval) \ +{ \ + if (groupPos == 0) { \ + groupNo++; \ + if (groupNo >= nSelectors) \ + RETURN(BZ_DATA_ERROR); \ + groupPos = BZ_G_SIZE; \ + gSel = s->selector[groupNo]; \ + gMinlen = s->minLens[gSel]; \ + gLimit = &(s->limit[gSel][0]); \ + gPerm = &(s->perm[gSel][0]); \ + gBase = &(s->base[gSel][0]); \ + } \ + groupPos--; \ + zn = gMinlen; \ + GET_BITS(label1, zvec, zn); \ + while (1) { \ + if (zn > 20 /* the longest code */) \ + RETURN(BZ_DATA_ERROR); \ + if (zvec <= gLimit[zn]) break; \ + zn++; \ + GET_BIT(label2, zj); \ + zvec = (zvec << 1) | zj; \ + }; \ + if (zvec - gBase[zn] < 0 \ + || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \ + RETURN(BZ_DATA_ERROR); \ + lval = gPerm[zvec - gBase[zn]]; \ +} + + +/*---------------------------------------------------*/ +Int32 BZ2_decompress ( DState* s ) +{ + UChar uc; + Int32 retVal; + Int32 minLen, maxLen; + bz_stream* strm = s->strm; + + /* stuff that needs to be saved/restored */ + Int32 i; + Int32 j; + Int32 t; + Int32 alphaSize; + Int32 nGroups; + Int32 nSelectors; + Int32 EOB; + Int32 groupNo; + Int32 groupPos; + Int32 nextSym; + Int32 nblockMAX; + Int32 nblock; + Int32 es; + Int32 N; + Int32 curr; + Int32 zt; + Int32 zn; + Int32 zvec; + Int32 zj; + Int32 gSel; + Int32 gMinlen; + Int32* gLimit; + Int32* gBase; + Int32* gPerm; + + if (s->state == BZ_X_MAGIC_1) { + /*initialise the save area*/ + s->save_i = 0; + s->save_j = 0; + s->save_t = 0; + s->save_alphaSize = 0; + s->save_nGroups = 0; + s->save_nSelectors = 0; + s->save_EOB = 0; + s->save_groupNo = 0; + s->save_groupPos = 0; + s->save_nextSym = 0; + s->save_nblockMAX = 0; + s->save_nblock = 0; + s->save_es = 0; + s->save_N = 0; + s->save_curr = 0; + s->save_zt = 0; + s->save_zn = 0; + s->save_zvec = 0; + s->save_zj = 0; + s->save_gSel = 0; + s->save_gMinlen = 0; + s->save_gLimit = NULL; + s->save_gBase = NULL; + s->save_gPerm = NULL; + } + + /*restore from the save area*/ + i = s->save_i; + j = s->save_j; + t = s->save_t; + alphaSize = s->save_alphaSize; + nGroups = s->save_nGroups; + nSelectors = s->save_nSelectors; + EOB = s->save_EOB; + groupNo = s->save_groupNo; + groupPos = s->save_groupPos; + nextSym = s->save_nextSym; + nblockMAX = s->save_nblockMAX; + nblock = s->save_nblock; + es = s->save_es; + N = s->save_N; + curr = s->save_curr; + zt = s->save_zt; + zn = s->save_zn; + zvec = s->save_zvec; + zj = s->save_zj; + gSel = s->save_gSel; + gMinlen = s->save_gMinlen; + gLimit = s->save_gLimit; + gBase = s->save_gBase; + gPerm = s->save_gPerm; + + retVal = BZ_OK; + + switch (s->state) { + + GET_UCHAR(BZ_X_MAGIC_1, uc); + if (uc != 'B') RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_2, uc); + if (uc != 'Z') RETURN(BZ_DATA_ERROR_MAGIC); + + GET_UCHAR(BZ_X_MAGIC_3, uc) + if (uc != 'h') RETURN(BZ_DATA_ERROR_MAGIC); + + GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8) + if (s->blockSize100k < '1' || + s->blockSize100k > '9') RETURN(BZ_DATA_ERROR_MAGIC); + s->blockSize100k -= '0'; + + if (s->smallDecompress) { + s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) ); + s->ll4 = BZALLOC( + ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) + ); + if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR); + } else { + s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) ); + if (s->tt == NULL) RETURN(BZ_MEM_ERROR); + } + + GET_UCHAR(BZ_X_BLKHDR_1, uc); + + if (uc == 0x17) goto endhdr_2; + if (uc != 0x31) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_2, uc); + if (uc != 0x41) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_3, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_4, uc); + if (uc != 0x26) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_5, uc); + if (uc != 0x53) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_BLKHDR_6, uc); + if (uc != 0x59) RETURN(BZ_DATA_ERROR); + + s->currBlockNo++; + if (s->verbosity >= 2) + VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo ); + + s->storedBlockCRC = 0; + GET_UCHAR(BZ_X_BCRC_1, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_2, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_3, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_BCRC_4, uc); + s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc); + + GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1); + + s->origPtr = 0; + GET_UCHAR(BZ_X_ORIGPTR_1, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_2, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + GET_UCHAR(BZ_X_ORIGPTR_3, uc); + s->origPtr = (s->origPtr << 8) | ((Int32)uc); + + if (s->origPtr < 0) + RETURN(BZ_DATA_ERROR); + if (s->origPtr > 10 + 100000*s->blockSize100k) + RETURN(BZ_DATA_ERROR); + + /*--- Receive the mapping table ---*/ + for (i = 0; i < 16; i++) { + GET_BIT(BZ_X_MAPPING_1, uc); + if (uc == 1) + s->inUse16[i] = True; else + s->inUse16[i] = False; + } + + for (i = 0; i < 256; i++) s->inUse[i] = False; + + for (i = 0; i < 16; i++) + if (s->inUse16[i]) + for (j = 0; j < 16; j++) { + GET_BIT(BZ_X_MAPPING_2, uc); + if (uc == 1) s->inUse[i * 16 + j] = True; + } + makeMaps_d ( s ); + if (s->nInUse == 0) RETURN(BZ_DATA_ERROR); + alphaSize = s->nInUse+2; + + /*--- Now the selectors ---*/ + GET_BITS(BZ_X_SELECTOR_1, nGroups, 3); + if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR); + GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15); + if (nSelectors < 1) RETURN(BZ_DATA_ERROR); + for (i = 0; i < nSelectors; i++) { + j = 0; + while (True) { + GET_BIT(BZ_X_SELECTOR_3, uc); + if (uc == 0) break; + j++; + if (j >= nGroups) RETURN(BZ_DATA_ERROR); + } + s->selectorMtf[i] = j; + } + + /*--- Undo the MTF values for the selectors. ---*/ + { + UChar pos[BZ_N_GROUPS], tmp, v; + for (v = 0; v < nGroups; v++) pos[v] = v; + + for (i = 0; i < nSelectors; i++) { + v = s->selectorMtf[i]; + tmp = pos[v]; + while (v > 0) { pos[v] = pos[v-1]; v--; } + pos[0] = tmp; + s->selector[i] = tmp; + } + } + + /*--- Now the coding tables ---*/ + for (t = 0; t < nGroups; t++) { + GET_BITS(BZ_X_CODING_1, curr, 5); + for (i = 0; i < alphaSize; i++) { + while (True) { + if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR); + GET_BIT(BZ_X_CODING_2, uc); + if (uc == 0) break; + GET_BIT(BZ_X_CODING_3, uc); + if (uc == 0) curr++; else curr--; + } + s->len[t][i] = curr; + } + } + + /*--- Create the Huffman decoding tables ---*/ + for (t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (i = 0; i < alphaSize; i++) { + if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; + if (s->len[t][i] < minLen) minLen = s->len[t][i]; + } + BZ2_hbCreateDecodeTables ( + &(s->limit[t][0]), + &(s->base[t][0]), + &(s->perm[t][0]), + &(s->len[t][0]), + minLen, maxLen, alphaSize + ); + s->minLens[t] = minLen; + } + + /*--- Now the MTF values ---*/ + + EOB = s->nInUse+1; + nblockMAX = 100000 * s->blockSize100k; + groupNo = -1; + groupPos = 0; + + for (i = 0; i <= 255; i++) s->unzftab[i] = 0; + + /*-- MTF init --*/ + { + Int32 ii, jj, kk; + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj); + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + /*-- end MTF init --*/ + + nblock = 0; + GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym); + + while (True) { + + if (nextSym == EOB) break; + + if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { + + es = -1; + N = 1; + do { + if (nextSym == BZ_RUNA) es = es + (0+1) * N; else + if (nextSym == BZ_RUNB) es = es + (1+1) * N; + N = N * 2; + GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym); + } + while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); + + es++; + uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; + s->unzftab[uc] += es; + + if (s->smallDecompress) + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->ll16[nblock] = (UInt16)uc; + nblock++; + es--; + } + else + while (es > 0) { + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + s->tt[nblock] = (UInt32)uc; + nblock++; + es--; + }; + + continue; + + } else { + + if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR); + + /*-- uc = MTF ( nextSym-1 ) --*/ + { + Int32 ii, jj, kk, pp, lno, off; + UInt32 nn; + nn = (UInt32)(nextSym - 1); + + if (nn < MTFL_SIZE) { + /* avoid general-case expense */ + pp = s->mtfbase[0]; + uc = s->mtfa[pp+nn]; + while (nn > 3) { + Int32 z = pp+nn; + s->mtfa[(z) ] = s->mtfa[(z)-1]; + s->mtfa[(z)-1] = s->mtfa[(z)-2]; + s->mtfa[(z)-2] = s->mtfa[(z)-3]; + s->mtfa[(z)-3] = s->mtfa[(z)-4]; + nn -= 4; + } + while (nn > 0) { + s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; + }; + s->mtfa[pp] = uc; + } else { + /* general case */ + lno = nn / MTFL_SIZE; + off = nn % MTFL_SIZE; + pp = s->mtfbase[lno] + off; + uc = s->mtfa[pp]; + while (pp > s->mtfbase[lno]) { + s->mtfa[pp] = s->mtfa[pp-1]; pp--; + }; + s->mtfbase[lno]++; + while (lno > 0) { + s->mtfbase[lno]--; + s->mtfa[s->mtfbase[lno]] + = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; + lno--; + } + s->mtfbase[0]--; + s->mtfa[s->mtfbase[0]] = uc; + if (s->mtfbase[0] == 0) { + kk = MTFA_SIZE-1; + for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { + for (jj = MTFL_SIZE-1; jj >= 0; jj--) { + s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; + kk--; + } + s->mtfbase[ii] = kk + 1; + } + } + } + } + /*-- end uc = MTF ( nextSym-1 ) --*/ + + s->unzftab[s->seqToUnseq[uc]]++; + if (s->smallDecompress) + s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else + s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]); + nblock++; + + GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym); + continue; + } + } + + /* Now we know what nblock is, we can do a better sanity + check on s->origPtr. + */ + if (s->origPtr < 0 || s->origPtr >= nblock) + RETURN(BZ_DATA_ERROR); + + s->state_out_len = 0; + s->state_out_ch = 0; + BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); + s->state = BZ_X_OUTPUT; + if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); + + /*-- Set up cftab to facilitate generation of T^(-1) --*/ + s->cftab[0] = 0; + for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; + for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + + if (s->smallDecompress) { + + /*-- Make a copy of cftab, used in generation of T --*/ + for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i]; + + /*-- compute the T vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->ll16[i]); + SET_LL(i, s->cftabCopy[uc]); + s->cftabCopy[uc]++; + } + + /*-- Compute T^(-1) by pointer reversal on T --*/ + i = s->origPtr; + j = GET_LL(i); + do { + Int32 tmp = GET_LL(j); + SET_LL(j, i); + i = j; + j = tmp; + } + while (i != s->origPtr); + + s->tPos = s->origPtr; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_SMALL(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_SMALL(s->k0); s->nblock_used++; + } + + } else { + + /*-- compute the T^(-1) vector --*/ + for (i = 0; i < nblock; i++) { + uc = (UChar)(s->tt[i] & 0xff); + s->tt[s->cftab[uc]] |= (i << 8); + s->cftab[uc]++; + } + + s->tPos = s->tt[s->origPtr] >> 8; + s->nblock_used = 0; + if (s->blockRandomised) { + BZ_RAND_INIT_MASK; + BZ_GET_FAST(s->k0); s->nblock_used++; + BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; + } else { + BZ_GET_FAST(s->k0); s->nblock_used++; + } + + } + + RETURN(BZ_OK); + + + + endhdr_2: + + GET_UCHAR(BZ_X_ENDHDR_2, uc); + if (uc != 0x72) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_3, uc); + if (uc != 0x45) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_4, uc); + if (uc != 0x38) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_5, uc); + if (uc != 0x50) RETURN(BZ_DATA_ERROR); + GET_UCHAR(BZ_X_ENDHDR_6, uc); + if (uc != 0x90) RETURN(BZ_DATA_ERROR); + + s->storedCombinedCRC = 0; + GET_UCHAR(BZ_X_CCRC_1, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_2, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_3, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + GET_UCHAR(BZ_X_CCRC_4, uc); + s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc); + + s->state = BZ_X_IDLE; + RETURN(BZ_STREAM_END); + + default: AssertH ( False, 4001 ); + } + + AssertH ( False, 4002 ); + + save_state_and_return: + + s->save_i = i; + s->save_j = j; + s->save_t = t; + s->save_alphaSize = alphaSize; + s->save_nGroups = nGroups; + s->save_nSelectors = nSelectors; + s->save_EOB = EOB; + s->save_groupNo = groupNo; + s->save_groupPos = groupPos; + s->save_nextSym = nextSym; + s->save_nblockMAX = nblockMAX; + s->save_nblock = nblock; + s->save_es = es; + s->save_N = N; + s->save_curr = curr; + s->save_zt = zt; + s->save_zn = zn; + s->save_zvec = zvec; + s->save_zj = zj; + s->save_gSel = gSel; + s->save_gMinlen = gMinlen; + s->save_gLimit = gLimit; + s->save_gBase = gBase; + s->save_gPerm = gPerm; + + return retVal; +} + + +/*-------------------------------------------------------------*/ +/*--- end decompress.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/dllmain.c b/drivers/lib/bzip2/dllmain.c new file mode 100644 index 0000000..99d048c --- /dev/null +++ b/drivers/lib/bzip2/dllmain.c @@ -0,0 +1,16 @@ +#ifdef BZ_DECOMPRESS_ONLY + +int _stdcall DriverEntry( void *a, void *b ) +{ + return 1; +} +#else +int _stdcall DllMain( unsigned long a, unsigned long b, unsigned long c ) +{ + return 1; +} +#endif +void bz_internal_error ( int errcode ) +{ + return; +} diff --git a/drivers/lib/bzip2/dlltest.c b/drivers/lib/bzip2/dlltest.c new file mode 100644 index 0000000..ade1062 --- /dev/null +++ b/drivers/lib/bzip2/dlltest.c @@ -0,0 +1,176 @@ +/* + minibz2 + libbz2.dll test program. + by Yoshioka Tsuneo(QWF00133@nifty.ne.jp/tsuneo-y@is.aist-nara.ac.jp) + This file is Public Domain. + welcome any email to me. + + usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename] +*/ + +#define BZ_IMPORT +#include +#include +#include "bzlib.h" +#ifdef _WIN32 +#include +#endif + + +#ifdef _WIN32 + +#define BZ2_LIBNAME "libbz2-1.0.0.DLL" + +#include +static int BZ2DLLLoaded = 0; +static HINSTANCE BZ2DLLhLib; +int BZ2DLLLoadLibrary(void) +{ + HINSTANCE hLib; + + if(BZ2DLLLoaded==1){return 0;} + hLib=LoadLibrary(BZ2_LIBNAME); + if(hLib == NULL){ + fprintf(stderr,"Can't load %s\n",BZ2_LIBNAME); + return -1; + } + BZ2_bzlibVersion=GetProcAddress(hLib,"BZ2_bzlibVersion"); + BZ2_bzopen=GetProcAddress(hLib,"BZ2_bzopen"); + BZ2_bzdopen=GetProcAddress(hLib,"BZ2_bzdopen"); + BZ2_bzread=GetProcAddress(hLib,"BZ2_bzread"); + BZ2_bzwrite=GetProcAddress(hLib,"BZ2_bzwrite"); + BZ2_bzflush=GetProcAddress(hLib,"BZ2_bzflush"); + BZ2_bzclose=GetProcAddress(hLib,"BZ2_bzclose"); + BZ2_bzerror=GetProcAddress(hLib,"BZ2_bzerror"); + + if (!BZ2_bzlibVersion || !BZ2_bzopen || !BZ2_bzdopen + || !BZ2_bzread || !BZ2_bzwrite || !BZ2_bzflush + || !BZ2_bzclose || !BZ2_bzerror) { + fprintf(stderr,"GetProcAddress failed.\n"); + return -1; + } + BZ2DLLLoaded=1; + BZ2DLLhLib=hLib; + return 0; + +} +int BZ2DLLFreeLibrary(void) +{ + if(BZ2DLLLoaded==0){return 0;} + FreeLibrary(BZ2DLLhLib); + BZ2DLLLoaded=0; +} +#endif /* WIN32 */ + +void usage(void) +{ + puts("usage: minibz2 [-d] [-{1,2,..9}] [[srcfilename] destfilename]"); +} + +int main(int argc,char *argv[]) +{ + int decompress = 0; + int level = 9; + char *fn_r = NULL; + char *fn_w = NULL; + +#ifdef _WIN32 + if(BZ2DLLLoadLibrary()<0){ + fprintf(stderr,"Loading of %s failed. Giving up.\n", BZ2_LIBNAME); + exit(1); + } + printf("Loading of %s succeeded. Library version is %s.\n", + BZ2_LIBNAME, BZ2_bzlibVersion() ); +#endif + while(++argv,--argc){ + if(**argv =='-' || **argv=='/'){ + char *p; + + for(p=*argv+1;*p;p++){ + if(*p=='d'){ + decompress = 1; + }else if('1'<=*p && *p<='9'){ + level = *p - '0'; + }else{ + usage(); + exit(1); + } + } + }else{ + break; + } + } + if(argc>=1){ + fn_r = *argv; + argc--;argv++; + }else{ + fn_r = NULL; + } + if(argc>=1){ + fn_w = *argv; + argc--;argv++; + }else{ + fn_w = NULL; + } + { + int len; + char buff[0x1000]; + char mode[10]; + + if(decompress){ + BZFILE *BZ2fp_r = NULL; + FILE *fp_w = NULL; + + if(fn_w){ + if((fp_w = fopen(fn_w,"wb"))==NULL){ + printf("can't open [%s]\n",fn_w); + perror("reason:"); + exit(1); + } + }else{ + fp_w = stdout; + } + if((BZ2fp_r == NULL && (BZ2fp_r = BZ2_bzdopen(fileno(stdin),"rb"))==NULL) + || (BZ2fp_r != NULL && (BZ2fp_r = BZ2_bzopen(fn_r,"rb"))==NULL)){ + printf("can't bz2openstream\n"); + exit(1); + } + while((len=BZ2_bzread(BZ2fp_r,buff,0x1000))>0){ + fwrite(buff,1,len,fp_w); + } + BZ2_bzclose(BZ2fp_r); + if(fp_w != stdout) fclose(fp_w); + }else{ + BZFILE *BZ2fp_w = NULL; + FILE *fp_r = NULL; + + if(fn_r){ + if((fp_r = fopen(fn_r,"rb"))==NULL){ + printf("can't open [%s]\n",fn_r); + perror("reason:"); + exit(1); + } + }else{ + fp_r = stdin; + } + mode[0]='w'; + mode[1] = '0' + level; + mode[2] = '\0'; + + if((fn_w == NULL && (BZ2fp_w = BZ2_bzdopen(fileno(stdout),mode))==NULL) + || (fn_w !=NULL && (BZ2fp_w = BZ2_bzopen(fn_w,mode))==NULL)){ + printf("can't bz2openstream\n"); + exit(1); + } + while((len=fread(buff,1,0x1000,fp_r))>0){ + BZ2_bzwrite(BZ2fp_w,buff,len); + } + BZ2_bzclose(BZ2fp_w); + if(fp_r!=stdin)fclose(fp_r); + } + } +#ifdef _WIN32 + BZ2DLLFreeLibrary(); +#endif + return 0; +} diff --git a/drivers/lib/bzip2/dlltest.dsp b/drivers/lib/bzip2/dlltest.dsp new file mode 100644 index 0000000..04819a4 --- /dev/null +++ b/drivers/lib/bzip2/dlltest.dsp @@ -0,0 +1,93 @@ +# Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** •ÒW‚µ‚È‚¢‚Å‚­‚¾‚³‚¢ ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dlltest - Win32 Debug +!MESSAGE ‚±‚ê‚Í—LŒø‚ÈÒ²¸Ì§²Ù‚Å‚Í‚ ‚è‚Ü‚¹‚ñB ‚±‚ÌÌßÛ¼Þª¸Ä‚ðËÞÙÄނ·‚邽‚ß‚É‚Í NMAKE ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢B +!MESSAGE [Ò²¸Ì§²Ù‚Ì´¸½Îß°Ä] ºÏÝÄނðŽg—p‚µ‚ÄŽÀs‚µ‚Ä‚­‚¾‚³‚¢ +!MESSAGE +!MESSAGE NMAKE /f "dlltest.mak". +!MESSAGE +!MESSAGE NMAKE ‚ÌŽÀsŽž‚ɍ\¬‚ðŽw’è‚Å‚«‚Ü‚· +!MESSAGE ºÏÝÄÞ ×²Ýã‚Åϸۂ̐ݒè‚ð’è‹`‚µ‚Ü‚·B—á: +!MESSAGE +!MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug" +!MESSAGE +!MESSAGE ‘I‘ð‰Â”\‚ÈËÞÙÄÞ Ó°ÄÞ: +!MESSAGE +!MESSAGE "dlltest - Win32 Release" ("Win32 (x86) Console Application" —p) +!MESSAGE "dlltest - Win32 Debug" ("Win32 (x86) Console Application" —p) +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dlltest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x411 /d "NDEBUG" +# ADD RSC /l 0x411 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"minibz2.exe" + +!ELSEIF "$(CFG)" == "dlltest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "dlltest_" +# PROP BASE Intermediate_Dir "dlltest_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "dlltest_" +# PROP Intermediate_Dir "dlltest_" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x411 /d "_DEBUG" +# ADD RSC /l 0x411 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"minibz2.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "dlltest - Win32 Release" +# Name "dlltest - Win32 Debug" +# Begin Source File + +SOURCE=.\bzlib.h +# End Source File +# Begin Source File + +SOURCE=.\dlltest.c +# End Source File +# End Target +# End Project diff --git a/drivers/lib/bzip2/huffman.c b/drivers/lib/bzip2/huffman.c new file mode 100644 index 0000000..9b446c4 --- /dev/null +++ b/drivers/lib/bzip2/huffman.c @@ -0,0 +1,228 @@ + +/*-------------------------------------------------------------*/ +/*--- Huffman coding low-level stuff ---*/ +/*--- huffman.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + +/*---------------------------------------------------*/ +#define WEIGHTOF(zz0) ((zz0) & 0xffffff00) +#define DEPTHOF(zz1) ((zz1) & 0x000000ff) +#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3)) + +#define ADDWEIGHTS(zw1,zw2) \ + (WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \ + (1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2))) + +#define UPHEAP(z) \ +{ \ + Int32 zz, tmp; \ + zz = z; tmp = heap[zz]; \ + while (weight[tmp] < weight[heap[zz >> 1]]) { \ + heap[zz] = heap[zz >> 1]; \ + zz >>= 1; \ + } \ + heap[zz] = tmp; \ +} + +#define DOWNHEAP(z) \ +{ \ + Int32 zz, yy, tmp; \ + zz = z; tmp = heap[zz]; \ + while (True) { \ + yy = zz << 1; \ + if (yy > nHeap) break; \ + if (yy < nHeap && \ + weight[heap[yy+1]] < weight[heap[yy]]) \ + yy++; \ + if (weight[tmp] < weight[heap[yy]]) break; \ + heap[zz] = heap[yy]; \ + zz = yy; \ + } \ + heap[zz] = tmp; \ +} + + +/*---------------------------------------------------*/ +void BZ2_hbMakeCodeLengths ( UChar *len, + Int32 *freq, + Int32 alphaSize, + Int32 maxLen ) +{ + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + Int32 nNodes, nHeap, n1, n2, i, j, k; + Bool tooLong; + + Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ]; + Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ]; + Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ]; + + for (i = 0; i < alphaSize; i++) + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + + while (True) { + + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (i = 1; i <= alphaSize; i++) { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + UPHEAP(nHeap); + } + + AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 ); + + while (nHeap > 1) { + n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1); + nNodes++; + parent[n1] = parent[n2] = nNodes; + weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]); + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + UPHEAP(nHeap); + } + + AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 ); + + tooLong = False; + for (i = 1; i <= alphaSize; i++) { + j = 0; + k = i; + while (parent[k] >= 0) { k = parent[k]; j++; } + len[i-1] = j; + if (j > maxLen) tooLong = True; + } + + if (! tooLong) break; + + for (i = 1; i < alphaSize; i++) { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbAssignCodes ( Int32 *code, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 n, vec, i; + + vec = 0; + for (n = minLen; n <= maxLen; n++) { + for (i = 0; i < alphaSize; i++) + if (length[i] == n) { code[i] = vec; vec++; }; + vec <<= 1; + } +} + + +/*---------------------------------------------------*/ +void BZ2_hbCreateDecodeTables ( Int32 *limit, + Int32 *base, + Int32 *perm, + UChar *length, + Int32 minLen, + Int32 maxLen, + Int32 alphaSize ) +{ + Int32 pp, i, j, vec; + + pp = 0; + for (i = minLen; i <= maxLen; i++) + for (j = 0; j < alphaSize; j++) + if (length[j] == i) { perm[pp] = j; pp++; }; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0; + for (i = 0; i < alphaSize; i++) base[length[i]+1]++; + + for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1]; + + for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0; + vec = 0; + + for (i = minLen; i <= maxLen; i++) { + vec += (base[i+1] - base[i]); + limit[i] = vec-1; + vec <<= 1; + } + for (i = minLen + 1; i <= maxLen; i++) + base[i] = ((limit[i-1] + 1) << 1) - base[i]; +} + + +/*-------------------------------------------------------------*/ +/*--- end huffman.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/libbz2.def b/drivers/lib/bzip2/libbz2.def new file mode 100644 index 0000000..4f83fcc --- /dev/null +++ b/drivers/lib/bzip2/libbz2.def @@ -0,0 +1,27 @@ +LIBRARY LIBBZ2 +DESCRIPTION "libbzip2: library for data compression" +EXPORTS + BZ2_bzCompressInit + BZ2_bzCompress + BZ2_bzCompressEnd + BZ2_bzDecompressInit + BZ2_bzDecompress + BZ2_bzDecompressEnd + BZ2_bzReadOpen + BZ2_bzReadClose + BZ2_bzReadGetUnused + BZ2_bzRead + BZ2_bzWriteOpen + BZ2_bzWrite + BZ2_bzWriteClose + BZ2_bzWriteClose64 + BZ2_bzBuffToBuffCompress + BZ2_bzBuffToBuffDecompress + BZ2_bzlibVersion + BZ2_bzopen + BZ2_bzdopen + BZ2_bzread + BZ2_bzwrite + BZ2_bzflush + BZ2_bzclose + BZ2_bzerror diff --git a/drivers/lib/bzip2/libbz2.dsp b/drivers/lib/bzip2/libbz2.dsp new file mode 100644 index 0000000..06c1d37 --- /dev/null +++ b/drivers/lib/bzip2/libbz2.dsp @@ -0,0 +1,130 @@ +# Microsoft Developer Studio Project File - Name="libbz2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** •ÒW‚µ‚È‚¢‚Å‚­‚¾‚³‚¢ ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libbz2 - Win32 Debug +!MESSAGE ‚±‚ê‚Í—LŒø‚ÈÒ²¸Ì§²Ù‚Å‚Í‚ ‚è‚Ü‚¹‚ñB ‚±‚ÌÌßÛ¼Þª¸Ä‚ðËÞÙÄނ·‚邽‚ß‚É‚Í NMAKE ‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢B +!MESSAGE [Ò²¸Ì§²Ù‚Ì´¸½Îß°Ä] ºÏÝÄނðŽg—p‚µ‚ÄŽÀs‚µ‚Ä‚­‚¾‚³‚¢ +!MESSAGE +!MESSAGE NMAKE /f "libbz2.mak". +!MESSAGE +!MESSAGE NMAKE ‚ÌŽÀsŽž‚ɍ\¬‚ðŽw’è‚Å‚«‚Ü‚· +!MESSAGE ºÏÝÄÞ ×²Ýã‚Åϸۂ̐ݒè‚ð’è‹`‚µ‚Ü‚·B—á: +!MESSAGE +!MESSAGE NMAKE /f "libbz2.mak" CFG="libbz2 - Win32 Debug" +!MESSAGE +!MESSAGE ‘I‘ð‰Â”\‚ÈËÞÙÄÞ Ó°ÄÞ: +!MESSAGE +!MESSAGE "libbz2 - Win32 Release" ("Win32 (x86) Dynamic-Link Library" —p) +!MESSAGE "libbz2 - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" —p) +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libbz2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x411 /d "NDEBUG" +# ADD RSC /l 0x411 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"libbz2.dll" + +!ELSEIF "$(CFG)" == "libbz2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x411 /d "_DEBUG" +# ADD RSC /l 0x411 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"libbz2.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "libbz2 - Win32 Release" +# Name "libbz2 - Win32 Debug" +# Begin Source File + +SOURCE=.\blocksort.c +# End Source File +# Begin Source File + +SOURCE=.\bzlib.c +# End Source File +# Begin Source File + +SOURCE=.\bzlib.h +# End Source File +# Begin Source File + +SOURCE=.\bzlib_private.h +# End Source File +# Begin Source File + +SOURCE=.\compress.c +# End Source File +# Begin Source File + +SOURCE=.\crctable.c +# End Source File +# Begin Source File + +SOURCE=.\decompress.c +# End Source File +# Begin Source File + +SOURCE=.\huffman.c +# End Source File +# Begin Source File + +SOURCE=.\libbz2.def +# End Source File +# Begin Source File + +SOURCE=.\randtable.c +# End Source File +# End Target +# End Project diff --git a/drivers/lib/bzip2/makefile.msc b/drivers/lib/bzip2/makefile.msc new file mode 100644 index 0000000..b79c928 --- /dev/null +++ b/drivers/lib/bzip2/makefile.msc @@ -0,0 +1,63 @@ +# Makefile for Microsoft Visual C++ 6.0 +# usage: nmake -f makefile.msc +# K.M. Syring (syring@gsf.de) +# Fixed up by JRS for bzip2-0.9.5d release. + +CC=cl +CFLAGS= -DWIN32 -MD -Ox -D_FILE_OFFSET_BITS=64 + +OBJS= blocksort.obj \ + huffman.obj \ + crctable.obj \ + randtable.obj \ + compress.obj \ + decompress.obj \ + bzlib.obj + +all: lib bzip2 test + +bzip2: lib + $(CC) $(CFLAGS) -o bzip2 bzip2.c libbz2.lib setargv.obj + $(CC) $(CFLAGS) -o bzip2recover bzip2recover.c + +lib: $(OBJS) + lib /out:libbz2.lib $(OBJS) + +test: bzip2 + type words1 + .\\bzip2 -1 < sample1.ref > sample1.rb2 + .\\bzip2 -2 < sample2.ref > sample2.rb2 + .\\bzip2 -3 < sample3.ref > sample3.rb2 + .\\bzip2 -d < sample1.bz2 > sample1.tst + .\\bzip2 -d < sample2.bz2 > sample2.tst + .\\bzip2 -ds < sample3.bz2 > sample3.tst + @echo All six of the fc's should find no differences. + @echo If fc finds an error on sample3.bz2, this could be + @echo because WinZip's 'TAR file smart CR/LF conversion' + @echo is too clever for its own good. Disable this option. + @echo The correct size for sample3.ref is 120,244. If it + @echo is 150,251, WinZip has messed it up. + fc sample1.bz2 sample1.rb2 + fc sample2.bz2 sample2.rb2 + fc sample3.bz2 sample3.rb2 + fc sample1.tst sample1.ref + fc sample2.tst sample2.ref + fc sample3.tst sample3.ref + + + +clean: + del *.obj + del libbz2.lib + del bzip2.exe + del bzip2recover.exe + del sample1.rb2 + del sample2.rb2 + del sample3.rb2 + del sample1.tst + del sample2.tst + del sample3.tst + +.c.obj: + $(CC) $(CFLAGS) -c $*.c -o $*.obj + diff --git a/drivers/lib/bzip2/manual.ps b/drivers/lib/bzip2/manual.ps new file mode 100644 index 0000000..1a7dbac --- /dev/null +++ b/drivers/lib/bzip2/manual.ps @@ -0,0 +1,3808 @@ +%!PS-Adobe-2.0 +%%Creator: dvips(k) 5.78 Copyright 1998 Radical Eye Software (www.radicaleye.com) +%%Title: manual.dvi +%%Pages: 39 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%EndComments +%DVIPSCommandLine: dvips -o manual.ps manual.dvi +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2000.03.23:2343 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin /N{def}def /B{bind def}N /S{exch}N +/X{S N}B /TR{translate}N /isls false N /vsize 11 72 mul N /hsize 8.5 72 +mul N /landplus90{false}def /@rigin{isls{[0 landplus90{1 -1}{-1 1} +ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale +isls{landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div +hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul +TR[matrix currentmatrix{dup dup round sub abs 0.00001 lt{round}if} +forall round exch round exch]setmatrix}N /@landscape{/isls true N}B +/@manualfeed{statusdict /manualfeed true put}B /@copies{/#copies X}B +/FMat[1 0 0 -1 0 0]N /FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{ +/nn 8 dict N nn begin /FontType 3 N /FontMatrix fntrx N /FontBBox FBB N +string /base X array /BitMaps X /BuildChar{CharBuilder}N /Encoding IE N +end dup{/foo setfont}2 array copy cvx N load 0 nn put /ctr 0 N[}B /df{ +/sf 1 N /fntrx FMat N df-tail}B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0] +N df-tail}B /E{pop nn dup definefont setfont}B /ch-width{ch-data dup +length 5 sub get}B /ch-height{ch-data dup length 4 sub get}B /ch-xoff{ +128 ch-data dup length 3 sub get sub}B /ch-yoff{ch-data dup length 2 sub +get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B /ch-image{ch-data +dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0 N /rw 0 N +/rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S dup +/base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx +0 ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff +setcachedevice ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff +.1 sub]/id ch-image N /rw ch-width 7 add 8 idiv string N /rc 0 N /gp 0 N +/cp 0 N{rc 0 ne{rc 1 sub /rc X rw}{G}ifelse}imagemask restore}B /G{{id +gp get /gp gp 1 add N dup 18 mod S 18 idiv pl S get exec}loop}B /adv{cp +add /cp X}B /chg{rw cp id gp 4 index getinterval putinterval dup gp add +/gp X adv}B /nd{/cp 0 N rw exit}B /lsh{rw cp 2 copy get dup 0 eq{pop 1}{ +dup 255 eq{pop 254}{dup dup add 255 and S 1 and or}ifelse}ifelse put 1 +adv}B /rsh{rw cp 2 copy get dup 0 eq{pop 128}{dup 255 eq{pop 127}{dup 2 +idiv S 128 and or}ifelse}ifelse put 1 adv}B /clr{rw cp 2 index string +putinterval adv}B /set{rw cp fillstr 0 4 index getinterval putinterval +adv}B /fillstr 18 string 0 1 17{2 copy 255 put pop}for N /pl[{adv 1 chg} +{adv 1 chg nd}{1 add chg}{1 add chg nd}{adv lsh}{adv lsh nd}{adv rsh}{ +adv rsh nd}{1 add adv}{/rc X nd}{1 add set}{1 add clr}{adv 2 chg}{adv 2 +chg nd}{pop nd}]dup{bind pop}forall N /D{/cc X dup type /stringtype ne{] +}if nn /base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{dup dup +length 1 sub dup 2 index S get sf div put}if put /ctr ctr 1 add N}B /I{ +cc 1 add D}B /bop{userdict /bop-hook known{bop-hook}if /SI save N @rigin +0 0 moveto /V matrix currentmatrix dup 1 get dup mul exch 0 get dup mul +add .99 lt{/QV}{/RV}ifelse load def pop pop}N /eop{SI restore userdict +/eop-hook known{eop-hook}if showpage}N /@start{userdict /start-hook +known{start-hook}if pop /VResolution X /Resolution X 1000 div /DVImag X +/IE 256 array N 2 string 0 1 255{IE S dup 360 add 36 4 index cvrs cvn +put}for pop 65781.76 div /vsize X 65781.76 div /hsize X}N /p{show}N +/RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley +X /rulex X V}B /V{}B /RV statusdict begin /product where{pop false[ +(Display)(NeXT)(LaserWriter 16/600)]{dup length product length le{dup +length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse} +forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale rulex ruley false +RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR rulex ruley scale 1 1 +false RMat{BDot}imagemask grestore}}ifelse B /QV{gsave newpath transform +round exch round exch itransform moveto rulex 0 rlineto 0 ruley neg +rlineto rulex neg 0 rlineto fill grestore}B /a{moveto}B /delta 0 N /tail +{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{S p tail}B /c{-4 M} +B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B /j{3 M}B /k{ +4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w}B /q{ +p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p +a}B /bos{/SS save N}B /eos{SS restore}B end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (manual.dvi) +@start +%DVIPSBitmapFont: Fa cmti10 10.95 1 +/Fa 1 47 df<120FEA3FC0127FA212FFA31380EA7F00123C0A0A77891C>46 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fb cmbxti10 14.4 1 +/Fb 1 47 df<13FCEA03FF000F13804813C05AA25AA2B5FCA31480A214006C5A6C5A6C5A +EA0FE0121271912B>46 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fc cmsl10 10.95 25 +/Fc 25 122 df37 D44 D48 D<157015F014011407143F903803FFE0137FEBFFCFEBF80F1300 +141F15C0A5143F1580A5147F1500A55C5CA513015CA513035CA513075CA5130F5CA3131F +497EB612F8A31D3D78BC2D>I<133C137F5B481380A31400A26C5A137890C7FCB3EA0780 +EA0FE0121F123FA5121FEA0F601200A213E05BA212015B120390C7FC5A1206120E5A5A12 +3012705A5A11397AA619>59 D97 DIIIII<147FEB3FFFA313017FA25CA513015CA51303 +5CA4ED07F80107EB1FFF9139F0781FC09138F1E00F9139F38007E0ECF70002FE14F0495A +5CA25CA24A130F131F4A14E0A4161F133F4A14C0A4163F137F91C71380A4167F5B491500 +A300015D486C491380B5D8F87F13FCA32E3F7DBE33>104 D<1478EB01FE130314FFA25B +14FE130314FCEB00F01400ACEB03F8EA01FF14F0A2EA001F130FA314E0A5131F14C0A513 +3F1480A5137F1400A55B5BA4EA03FF007F13F0A2B5FC183E7DBD1A>I<143FEB1FFF5BA2 +13017FA214FEA5130114FCA5130314F8A5130714F0A5130F14E0A5131F14C0A5133F1480 +A5137F1400A55B5BA4EA03FF007F13F8A2B5FC183F7DBE1A>108 +D<902707F007F8EB03FCD803FFD91FFF90380FFF80913CE0781FC03C0FE09126E1E00FEB +F0073E001FE38007E1C003F090260FE700EBE38002EEDAF70013F802FC14FE02D85C14F8 +4A5CA24A5C011F020F14074A4A14F0A5013F021F140F4A4A14E0A5017F023F141F91C749 +14C0A549027F143F4992C71380A300014B147F486C496DEBFFC0B5D8F87FD9FC3F13FEA3 +47287DA74C>I<903907F007F8D803FFEB1FFF9139E0781FC09138E1E00F3B001FE38007 +E090380FE70002EE14F014FC14D814F85CA24A130F131F4A14E0A4161F133F4A14C0A416 +3F137F91C71380A4167F5B491500A300015D486C491380B5D8F87F13FCA32E287DA733> +II<91387F01FE903A7FFF0FFFC09139FE3E03F09238F801F890 +3A01FFE000FE4B137F6D497F4990C713804A15C04A141FA218E0A20103150F5C18F0A317 +1F010716E05CA3173F18C0130F4A147F1880A2EFFF004C5A011F5D16034C5A6E495AEE1F +C06E495AD93FDC017EC7FC91388F01F8913883FFE0028090C8FC92C9FC137FA291CAFCA4 +5BA25BA31201487EB512F8A3343A81A733>I<903907F01F80D803FFEB7FE09138E1E1F0 +9138E387F839001FE707EB0FE614EE02FC13F002D813E09138F801804AC7FCA25C131FA2 +5CA4133F5CA5137F91C8FCA55B5BA31201487EB512FEA325287EA724>114 +D<9138FF81C0010713E390381F807F90397C003F8049131F4848130F5B00031407A24848 +1400A27FA27F6D90C7FCEBFF8014FC6C13FF6C14C015F06C6C7F011F7F13079038007FFE +1403140100381300157EA2123C153E157E007C147CA2007E147815F8007F495A4A5A486C +485A26F9E01FC7FC38E0FFFC38C01FE0222A7DA824>II<01FE147F00FFEC7FFF4914FEA20007140300031401A34914FCA4 +150312074914F8A41507120F4914F0A4150F121F4914E0A2151FA3153F4914C0157F15FF +EC01DF3A0FC003BFE09138073FFF3803F01E3801FFF826003FE01380282977A733>III<90B539E007FFF05E18E0902707FE000313006D48EB01FC +705A5F01014A5A5F16036E5C0100140794C7FC160E805E805E1678ED8070023F13F05EED +81C015C191381FC38015C793C8FC15EF15EEEC0FFCA25DA26E5AA25DA26E5A5DA24AC9FC +5C140E141E141C5C121C003F5B5A485B495A130300FE5B4848CAFCEA701EEA783CEA3FF0 +EA0FC0343A80A630>121 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fd cmtt12 14.4 10 +/Fd 10 123 df50 D<383FFF805AB57EA37E7EEA003FAEED07FC92383FFF +8092B512E002C314F802CF8002DF8091B7FCDBF80F1380DBC00113C092C713E04A143F4A +EC1FF04A15F84A140F4AEC07FCA217034A15FE1701A318FF83A95F18FEA280170318FC6E +140718F86E140FEF1FF06E143F6EEC7FE06EECFFC0DBC0031380EDF01F92B6120002DF14 +FC02CF5C02C35CD91F8114C090260F807F90C7FC90C7EA0FF8384A7FC83E>98 +D<923803FFF85D4B7FA38181ED0003AEEC1FF0ECFFFE0103EBFF83010F14E34914F3017F +14FB90B7FC48EBF80F48EBC00191C7FC4848143F4848141F5B4848140F491407123F4914 +03127F5BA312FF90C8FCA97F127FA216077F123F6D140FA26C6C141F6D143F000F157F6C +6C14FF01FF5B6C6D5A6CD9F01FEBFFFC6C90B500FB13FE6D02F313FF6D14E3010F14C36D +020113FE010101FC14FC9026003FE0C8FC384A7CC83E>100 D<143E147F4A7E497FA56D +5B6EC8FC143E91C9FCAC003FB57E5A81A47EC7123FB3B3007FB71280B812C0A56C16802A +4A76C93E>105 D<007FB512C0B6FC81A47EC7121FB3B3B3A5007FB712F8B812FCA56C16 +F82E4978C83E>108 D111 +DI<903901FFF00F011F9038 +FE1F8090B612BF000315FF5A5A5A393FFE003F01F01307D87FC0130190C8FC5A48157FA4 +7EEE3F00D87FC091C7FC13F0EA3FFE381FFFF06CEBFFC06C14FE6C6E7EC615E0013F14F8 +010780D9003F7F02007F03071380030013C0003EED3FE0007F151F48150F17F06D1407A3 +7FA26D140F6D15E0161F01FCEC3FC06D14FF9026FFC00F138091B612005E485D013F5C6D +14E0D8FC0714802778007FF8C7FC2C3677B43E>115 D<147C14FC497EAD003FB712FC5A +B87EA36C5EA2260001FEC9FCB3A6173FA2EF7F80A76E14FF6D16006F5A9238C007FE9138 +7FF01F92B55A6E5C6E5C6E5C6E1480020149C7FC9138003FF031437DC13E>I<000FB812 +804817C04817E0A418C001C0C712014C13804C1300EE1FFE4C5AEE7FF06C484A5A4B5BC8 +485B4B90C7FC4B5A4B5A4B5A4B5A4B5A4A5B4A5B4A90C8FC4A5A4A5A4A5A4A5A4A5A495B +495B4990C9FC495A495A4948EC0FC0495A4948EC1FE0485B00075B4890C8FCEA1FFC485A +485A90B8FCB9FCA46C17C07E33337CB23E>122 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fe cmtt12 13.14 31 +/Fe 31 123 df50 D<003FB6FC4815E0B712F882826C816C16802701FC000113C0 +9238007FE0161FEE0FF0A2160717F81603A6160717F0A2160FEE1FE0163FEE7FC0923801 +FF80030F130090B65A5E16F08216FEEEFF8017C001FCC7EA7FE0EE1FF0EE07F8160317FC +EE01FE1600A217FF177FA717FF17FE16011603EE07FC160FEE3FF8EEFFF0003FB7FC4816 +E0B812C01780EEFE006C15F86C15C030437DC238>66 DI<007FB512F8B7FC16C08216F8826C813A03F8001FFF15 +07030113806F13C0167FEE3FE0161FEE0FF0A2EE07F8A2EE03FCA21601A217FE1600A417 +7FAD17FF17FEA4160117FCA2160317F81607A2EE0FF0161FEE3FE0167FEEFFC04B13805D +031F1300007FB65AB75A5E5E16C093C7FC6C14F830437DC238>I<007FB712FCB87EA57E +D801FCC8FCA9177C94C7FCA6ED07C04B7EA590B6FCA79038FC000FA56F5A92C9FCA7EF0F +80EF1FC0AA007FB8FCB9FCA56C178032437DC238>I<91391FF003C091397FFC07E049B5 +FC010714CF4914EF4914FF5B90387FF81F9038FFE00748EB800191C7FC4848147F485A49 +143F485A161F485AA249140F123F5BA2127F90C8EA07C093C7FCA35A5AAA923807FFFC4B +13FE4B13FF7E7E6F13FE6F13FC9238000FE07F003F151FA27F121F7F163F6C7EA26C6C14 +7F7F6C6C14FF6C6C5B6E5A6C6D5A90387FF81F6DB6FC6D14EF6D14CF6D148F0101140F90 +3A007FFC07C0DA1FF0C7FC30457CC338>71 D<007FB612F0B712F8A56C15F0260001FCC7 +FCB3B3B1007FB612F0B712F8A56C15F0254377C238>73 D<90380FFFFE90B612E0000315 +F8488148814881A2273FFE000F138001F01301497F49147F4848EC3FC0A290C8121FA448 +16E0A248150FB3AC6C151FA36C16C0A36D143FA36C6CEC7F806D14FF6D5B01FE130F6CB7 +1200A26C5D6C5D6C5DC615E0010F49C7FC2B457AC338>79 D<003FB512F04814FEB77E16 +E0826C816C813A01FC003FFEED07FF03017F81707E163F161F83160FA7161F5F163F167F +4C5A5D030790C7FCED3FFE90B65A5E5E5EA282829038FC001FED07FC6F7E150115008282 +AA18E0EF01F0EF03F8A31783EE3F87263FFFE0ECC7F0486D14FFB56C7F18E07013C06C49 +6D13806C496D1300CA12FC35447EC238>82 D<003FB8FC481780B9FCA53BFE0007F0003F +A9007CEE1F00C792C7FCB3B3A70107B512F04980A56D5C31437DC238>84 +D<267FFFF090387FFFF0B56C90B512F8A56C496D13F0D801FCC73801FC00B3B3A66D1403 +00005EA36D14076D5D6E130F6D6C495A6E133F6D6C495A6D6C495AECFF076D90B5C7FC6D +5C6D5C6D5C023F13E0020F1380DA03FEC8FC35447FC238>I87 +D<001FB712F04816F85AA417F090C8121F17E0EE3FC0167F1780EEFF00A24B5A4B5A123E +C8485A4B5AA24B5A4B5AA24B5A4BC7FCA24A5A14035D4A5A140F5D4A5A143F5D4A5A14FF +92C8FC495A13035C495AA2495A495AA2495A495A17F849C7EA01FC485AA2485A485AA248 +5A121F5B485A127F90B7FCB8FCA56C16F82E437BC238>90 D<003FB712804816C0B812E0 +A46C16C06C16802B087A7D38>95 D97 DIIIII<14F0497E497E497EA4 +6D5A6D5A6D5A91C8FCAB383FFFFC487FB5FCA37E7EC7FCB3AF007FB612F0B712F816FCA3 +16F86C15F0264476C338>105 D<387FFFFEB6FCA57EC77EB3B3B1007FB7FCB81280A56C +1600294379C238>108 D<023FEB07E03B3FE0FFC01FF8D87FF39038E07FFCD8FFF76D48 +7E90B500F97F15FB6C91B612806C01C1EBF83F00030100EBE01F4902C013C0A24990387F +800FA2491400A349137EB3A73C3FFF03FFE07FFC4801879038F0FFFEB500C76D13FFA36C +01874913FE6C01039038E07FFC383080AF38>IIII114 D<903907FF80F0017FEBF1F848B5 +12FD000714FF5A5A5AEBFC00D87FE0131F0180130F48C71207481403A5007FEC01F001C0 +90C7FCEA3FF013FE381FFFF86CEBFFC0000314F8C614FF013F1480010714E0D9003F13F0 +020013F8ED0FFC1503003CEC01FE007E140000FE15FF167F7EA37F6D14FF16FE01F01303 +6DEB07FC01FF137F91B512F816F016E04815C0D8FC3F1400010F13FCD8780113E0283278 +B038>III<000FB712FC4816FE5AA417 +FC0180C7EA1FF8EE3FF0EE7FE0EEFFC04B13804B13006CC7485AC8485A4B5A4B5A4B5A4B +5A4A5B4A90C7FCEC07FC4A5A4A5A4A5A4A5A49485A4990C8FC495A495A495A495A494814 +7C494814FE485B4890C8FC485A485A485A485A48B7FCB8FCA56C16FC2F2F7DAE38>122 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Ff cmbx12 13.14 53 +/Ff 53 122 df<923807FFE092B512FC020714FF021F81027F9038007FC0902601FFF0EB +0FE04901C0497E4990C7487ED90FFC147F011F824A14FF495AA2137F5CA2715A715A715A +EF078094C8FCA7EF07FCB9FCA526007FF0C7123F171FB3B3A2003FB5D8E00FB512F8A53D +4D7ECC44>12 D45 DI<177817F8EE01FCA21603A2EE07F8A217F016 +0FA217E0161FA2EE3FC0A21780167FA217005EA24B5AA25E1503A24B5AA25E150FA25E15 +1FA24B5AA25E157FA24BC7FCA25D1401A25D1403A24A5AA25D140FA24A5AA25D143FA25D +147FA24AC8FCA25C1301A25C1303A2495AA25C130FA2495AA25C133FA25C137FA249C9FC +A25B1201A2485AA25B1207A25B120FA2485AA25B123FA25B127FA248CAFCA25AA2127CA2 +2E6D79D13D>I<15F014011407141F147FEB03FF137FB6FCA313FC1380C7FCB3B3B2007F +B712E0A52B4777C63D>49 DIIIII<121F7F7F13FE90B812E0A45A18C0188018005F5FA25F485E90C8 +EA07E0007E4B5A5F007C151F4CC7FC167E5E485D15014B5A4B5AC8485A4B5AA24BC8FC15 +7EA25D1401A24A5A1407A24A5AA2141FA24A5AA2147FA314FFA3495BA45BA55BAA6D5BA2 +6D90C9FCEB007C334B79C93D>III65 +D<93261FFF80EB01C00307B500F81303033F02FE13074AB7EAC00F0207EEE03F021F903A +FE007FF87F027F01E0903807FCFF91B5C70001B5FC010301FC6E7E4901F0151F4901C081 +4949814990C97E494882494882485B48197F4A173F5A4A171F5A5C48190FA2485B1A07A2 +5AA297C7FC91CDFCA2B5FCAD7EA280A2F207C07EA36C7FA26C190F6E18807E6E171F6C1A +006E5F6C193E6C6D177E6D6C5F6D6C4C5A6D6D15036D6D4B5A6D01F04B5A6D01FCED3FC0 +010001FFEDFF806E01E0D903FEC7FC021F01FEEB3FFC020790B612F002015EDA003F92C8 +FC030714FCDB001F13804A4D79CB59>67 D +III<93261FFF80EB01C00307B500F8 +1303033F02FE13074AB7EAC00F0207EEE03F021F903AFE007FF87F027F01E0903807FCFF +91B5C70001B5FC010301FC6E7E4901F0151F4901C0814949814990C97E49488249488248 +5B48197F4A173F5A4A171F5A5C48190FA2485B1A07A25AA297C8FC91CEFCA2B5FCAD6C04 +0FB712C0A280A36C93C7001FEBC000A2807EA27E807E807E806C7F7E6D7E6D7E6D7F6D01 +E05D6D6D5D6D13FC010001FF4AB5FC6E01E0EB07F9021F01FFEB3FF0020791B5EAE07F02 +01EEC01FDA003FED0007030702F81301DB001F018090C8FC524D79CB61>III76 DII +II82 DI<003FBB12C0A5DA80019038FC001FD9FC001601D8 +7FF09438007FE001C0183F49181F90C7170FA2007E1907A3007C1903A500FC1AF0481901 +A5C894C7FCB3B3A749B812FCA54C4A7CC955>III89 D97 +DI<91380FFF8091B512F8 +010314FF010F15804948C613C0D97FF8EB1FE0D9FFE0EB3FF04849137F4849EBFFF84890 +C7FCA2485A121FA24848EC7FF0EE3FE0EE1FC0007F92C7FC5BA212FFAC127FA27FA2123F +A26C6C153EA26C6C157E177C6C6D14FC6C6D14F86C6D13036C6DEB07F0D97FFCEB1FE06D +B4EBFFC0010F90B5120001035C010014F0020F13802F347CB237>IIIIII<13FCEA03FF487F487FA2487FA66C5BA26C5B6C90C7FCEA00FC90C8 +FCABEB7FC0B5FCA512037EB3B3A2B61280A5194D7BCC22>I108 D<90287FC001FFC0EC7FF0B5010F01FC0103B5FC033F +6D010F804B6D4980DBFE079026803F817F9126C1F801903AC07E007FF00003D9C3E0DAE0 +F8806C9026C78000D9F1E06D7E02CFC7EBF3C002DEEDF780DD7FFF6E7E02FC93C7FC4A5D +A24A5DA34A5DB3AAB6D8C03FB5D8F00FB512FCA55E327BB167>I<903A7FC001FFC0B501 +0F13F8033F7F4B13FFDBFE077F9138C1F00300039026C3E0017F6CD9C78080ECCF0014DE +02DC6D7F14FC5CA25CA35CB3AAB6D8C07FEBFFE0A53B327BB144>I<913807FF80027F13 +F80103B6FC010F15C090261FFE017F903A7FF0003FF849486D7E480180EB07FE4890C76C +7E4817804980000F17C048486E13E0A2003F17F0A249157F007F17F8A400FF17FCAB007F +17F8A46C6CEDFFF0A2001F17E0A26C6C4A13C0A26C6C4A13806C6D4913006C5E6C01E0EB +1FFC6D6C495A903A3FFE01FFF0010FB612C0010392C7FCD9007F13F80207138036347DB2 +3D>I<90397FC007FFB5017F13E002C1B512FC02C714FF9126CFF80F7F9126DFC0037F00 +0301FFC77F6C496E7E02F8814A6E7E717E4A81831980A28319C0A37113E0AC19C05FA319 +805F19005F606E143F6E5D4D5A6E4A5A02FF495BDBC0075B9126EFF01F5B02E7B548C7FC +02E114F8DAE07F13E0DB0FFEC8FC92CAFCAFB612C0A53B477CB144>I<9039FF803FE0B5 +EBFFF8028113FE02837FDA87E11380EC8F830003D99F0713C06C139E14BCA214F8A24A6C +13806F13006F5A4A90C7FCA45CB3A8B612E0A52A327CB132>114 +D<903907FF8070017FEBF1F048B6FC1207380FFC01391FE0003F4848130F491307127F90 +C71203A2481401A27FA27F01F090C7FC13FCEBFFC06C13FEECFFE06C14FC6C806CECFF80 +6C15C06C15E06C15F06C7E011F14F8010114FCEB000FEC007FED1FFE0078140F00F81407 +15037E1501A27E16FC7E15036D14F86D13076D14F001F8EB1FE001FFEBFFC04890B51280 +486C1400D8F81F13FCD8E00313C027347CB230>I<14F8A51301A41303A21307A2130FA2 +131F133F137F13FF1203000F90B512F0B7FCA426007FF8C7FCB3A7167CAA013F14F880A2 +90391FFE01F0010F1303903907FF87E06DEBFFC06D14806D6C1300EC0FFC26467EC430> +IIII<007FB500C090387FFFE0A5C601F0C73803F8006E5D017F5E6E140701 +3F5E80170F011F5E6E141F6D93C7FC6F5B6D153E6F137E6D157C6F13FCA26D6D5B16016D +5DEDF803027F5CEDFC07023F5CEDFE0F021F5C15FF161F6E91C8FC16BF6E13BE16FE6E5B +A26E5BA36E5BA26F5AA26F5AA26F5AA393C9FC5D153E157E157CD81F8013FC486C5B387F +E001D8FFF05B14035D14074A5A49485A007F133F4948CAFC383F81FE381FFFF86C5B6C13 +C0C648CBFC3B477EB041>121 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fg cmtt12 17.28 6 +/Fg 6 123 df<913803FFC0023F13FC49B67E010715F04981013F15FE498190B812C048 +8348D9FC0180489026E0001F7F480180130391C87F48486F7E49153F4848ED0FFF834848 +178083496F13C012FF8319E07FA2187FA36C5A6C5A6C5ACBFCA218FFA219C05FA219805F +A24D13005F604D5A173F4D5A4D5AA24C5B4C5B4C5B041F90C7FC4C5A4C5A4C5A4B5B4B5B +4B5B031F5B4B90C8FC4B5AEDFFF84A5B4A5B4A5B021F5B4A90C9FCEC7FFC4A5A495B495B +010F5B495B4948CAFC4948ED1F804948ED3FC04849ED7FE0485B000F5B4890C9FC4890B8 +FC5ABAFCA56C18C06C18803B5A79D94A>50 D<383FFFF0487F80B5FCA37EA27EEA000FB0 +EE0FFC93B57E030714E0031F14F84B14FE92B7FC02FD8291B87E85DCE01F7FEE000703FC +01017F4B6D7F03E0143F4B6E7E4B140F8592C87E4A6F1380A34A6F13C0A284A21AE0A219 +7FAA19FFA21AC0A26E5DA24E138080606F1600606F4A5A6F143F6F4A5A6F4A5A6F130303 +FF010F5BDCC03F5B93B65A6102FD93C7FC02FC5D6F5C031F14F0902607F80714C0902603 +F00191C8FC90C8EA3FF043597FD74A>98 D105 D<003FB512FE4880B77EA57E7EC71201B3B3B3 +B0003FB812FC4817FEBAFCA56C17FE6C17FC385877D74A>108 D +112 D<000FB912E04818F04818F8A619F001F0C8000313E04D13C04D13804D13004D5A4D +5A4D5A6C484A5B6C484A5BC9000F5B4C5B4C90C7FC4C5A4C5A4B5B4B5B4B5B4B5B4B5B4B +90C8FC4B5A4B5A4A5B4A5B4A5B4A5B4A5B4A90C9FC4A5A4A5A495B495B495B4949EC07E0 +4949EC0FF04948C8EA1FF8495A495A485B485B485B485B4890C9FC485A48B9FCBAFCA66C +18F06C18E03D3E7BBD4A>122 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fh cmbx12 17.28 28 +/Fh 28 120 df<16F04B7E1507151F153FEC01FF1407147F010FB5FCB7FCA41487EBF007 +C7FCB3B3B3B3007FB91280A6395E74DD51>49 D<913801FFF8021FEBFFC091B612F80103 +15FF010F16C0013F8290267FFC0114F89027FFE0003F7F4890C7000F7F48486E7FD807F8 +6E148048486E14C048486E14E048486F13F001FC17F8486C816D17FC6E80B56C16FE8380 +A219FFA283A36C5BA26C5B6C90C8FCD807FC5DEA01F0CA14FEA34D13FCA219F85F19F04D +13E0A294B512C019804C14004C5B604C5B4C5B604C13804C90C7FC4C5A4C5A4B13F05F4B +13804B90C8FC4B5AED1FF84B5A4B5A4B48143F4A5B4A48C8FC4A5A4A48157E4A5A4A5AEC +7F8092C9FC02FE16FE495A495A4948ED01FCD90FC0150749B8FC5B5B90B9FC5A4818F85A +5A5A5A5ABAFCA219F0A4405E78DD51>I<92B5FC020F14F8023F14FF49B712C04916F001 +0FD9C01F13FC90271FFC00077FD93FE001017F49486D8049C86C7F484883486C6F7F14C0 +486D826E806E82487FA4805CA36C5E4A5E6C5B6C5B6C495E011FC85A90C95CA294B55A61 +4C91C7FC604C5B4C5B4C5B4C5B047F138092260FFFFEC8FC020FB512F817E094C9FC17F8 +17FF91C7003F13E0040713F8040113FE707F717F7113E085717FA2717F85A285831A80A3 +1AC0EA03FCEA0FFF487F487F487FA2B57EA31A80A34D14005C7E4A5E5F6C495E49C8485B +D81FF85F000F5ED807FE92B55A6C6C6C4914806C01F0010791C7FC6C9026FF803F5B6D90 +B65A011F16F0010716C001014BC8FCD9001F14F0020149C9FC426079DD51>II<4DB5ED03C0057F02F0 +14070407B600FE140F047FDBFFC0131F4BB800F0133F030F05FC137F033F9127F8007FFE +13FF92B6C73807FF814A02F0020113C3020702C09138007FE74A91C9001FB5FC023F01FC +16074A01F08291B54882490280824991CB7E49498449498449498449865D49498490B5FC +484A84A2484A84A24891CD127FA25A4A1A3F5AA348491A1FA44899C7FCA25CA3B5FCB07E +A380A27EA2F50FC0A26C7FA37E6E1A1F6C1D80A26C801D3F6C6E1A00A26C6E616D1BFE6D +7F6F4E5A7F6D6D4E5A6D6D4E5A6D6D4E5A6D6E171F6D02E04D5A6E6DEFFF806E01FC4C90 +C7FC020F01FFEE07FE6E02C0ED1FF8020102F8ED7FF06E02FF913803FFE0033F02F8013F +1380030F91B648C8FC030117F86F6C16E004071680DC007F02F8C9FC050191CAFC626677 +E375>67 D72 DI77 +D80 D<001FBEFCA64849C79126E0000F148002E0180091 +C8171F498601F81A0349864986A2491B7FA2491B3F007F1DC090C9181FA4007E1C0FA600 +FE1DE0481C07A5CA95C7FCB3B3B3A3021FBAFCA663617AE070>84 +D<913803FFFE027FEBFFF00103B612FE010F6F7E4916E090273FFE001F7FD97FE001077F +D9FFF801017F486D6D7F717E486D6E7F85717FA2717FA36C496E7FA26C5B6D5AEB1FC090 +C9FCA74BB6FC157F0207B7FC147F49B61207010F14C0013FEBFE004913F048B512C04891 +C7FC485B4813F85A5C485B5A5CA2B55AA45FA25F806C5E806C047D7F6EEB01F96C6DD903 +F1EBFF806C01FED90FE114FF6C9027FFC07FC01580000191B5487E6C6C4B7E011F02FC13 +0F010302F001011400D9001F90CBFC49437CC14E>97 D<903807FF80B6FCA6C6FC7F7FB3 +A8EFFFF8040FEBFF80047F14F00381B612FC038715FF038F010014C0DBBFF0011F7FDBFF +C001077F93C76C7F4B02007F03F8824B6F7E4B6F13804B17C0851BE0A27313F0A21BF8A3 +7313FCA41BFEAE1BFCA44F13F8A31BF0A24F13E0A24F13C06F17804F1300816F4B5A6F4A +5B4AB402075B4A6C6C495B9126F83FE0013F13C09127F00FFC03B55A4A6CB648C7FCDAC0 +0115F84A6C15E091C7001F91C8FC90C8000313E04F657BE35A>I<92380FFFF04AB67E02 +0F15F0023F15FC91B77E01039039FE001FFF4901F8010113804901E0010713C049018049 +13E0017F90C7FC49484A13F0A2485B485B5A5C5A7113E0485B7113C048701380943800FE +0095C7FC485BA4B5FCAE7EA280A27EA2806C18FCA26C6D150119F87E6C6D15036EED07F0 +6C18E06C6D150F6D6DEC1FC06D01E0EC7F806D6DECFF00010701FCEB03FE6D9039FFC03F +FC010091B512F0023F5D020F1580020102FCC7FCDA000F13C03E437BC148>II<92380FFFC0 +4AB512FC020FECFF80023F15E091B712F80103D9FE037F499039F0007FFF011F01C0011F +7F49496D7F4990C76C7F49486E7F48498048844A804884485B727E5A5C48717EA35A5C72 +1380A2B5FCA391B9FCA41A0002C0CBFCA67EA380A27EA27E6E160FF11F806C183F6C7FF1 +7F006C7F6C6D16FE6C17016D6C4B5A6D6D4A5A6D01E04A5A6D6DEC3FE0010301FC49B45A +6D9026FFC01F90C7FC6D6C90B55A021F15F8020715E0020092C8FC030713F041437CC14A +>III<903807FF80B6FCA6C6FC7F7FB3A8EF1FFF94B512F0040714 +FC041F14FF4C8193267FE07F7F922781FE001F7FDB83F86D7FDB87F07FDB8FC0814C7F03 +9FC78015BE03BC8003FC825DA25DA25DA45DB3B2B7D8F007B71280A651647BE35A>II<903807FF80B6 +FCA6C6FC7F7FB3B3B3B3ADB712E0A623647BE32C>108 D<902607FF80D91FFFEEFFF8B6 +91B500F00207EBFF80040702FC023F14E0041F02FF91B612F84C6F488193267FE07F6D48 +01037F922781FE001F9027E00FF0007FC6DA83F86D9026F01FC06D7F6DD987F06D4A487F +6DD98FC0DBF87EC7804C6D027C80039FC76E488203BEEEFDF003BC6E4A8003FC04FF834B +5FA24B5FA24B94C8FCA44B5EB3B2B7D8F007B7D8803FB612FCA67E417BC087>I<902607 +FF80EB1FFFB691B512F0040714FC041F14FF4C8193267FE07F7F922781FE001F7FC6DA83 +F86D7F6DD987F07F6DD98FC0814C7F039FC78015BE03BC8003FC825DA25DA25DA45DB3B2 +B7D8F007B71280A651417BC05A>I<923807FFE092B6FC020715E0021F15F8027F15FE49 +4848C66C6C7E010701F0010F13E04901C001037F49496D7F4990C87F49486F7E49486F7E +48496F13804819C04A814819E048496F13F0A24819F8A348496F13FCA34819FEA4B518FF +AD6C19FEA46C6D4B13FCA36C19F8A26C6D4B13F0A26C19E06C6D4B13C0A26C6D4B13806C +6D4B13006D6C4B5A6D6D495B6D6D495B010701F0010F13E06D01FE017F5B010090B7C7FC +023F15FC020715E0020092C8FC030713E048437CC151>I114 D<913A3FFF8007800107B5EAF81F011FECFE7F017F91B5FC48B8FC48EBE0 +014890C7121FD80FFC1407D81FF0801600485A007F167F49153FA212FF171FA27F7F7F6D +92C7FC13FF14E014FF6C14F8EDFFC06C15FC16FF6C16C06C16F06C826C826C826C82013F +1680010F16C01303D9007F15E0020315F0EC001F1500041F13F81607007C150100FC8117 +7F6C163FA2171F7EA26D16F0A27F173F6D16E06D157F6D16C001FEEDFF806D0203130002 +C0EB0FFE02FCEB7FFC01DFB65A010F5DD8FE0315C026F8007F49C7FC48010F13E035437B +C140>II<90 +2607FFC0ED3FFEB60207B5FCA6C6EE00076D826D82B3B3A260A360A2607F60183E6D6D14 +7E4E7F6D6D4948806D6DD907F0ECFF806D01FFEB3FE06D91B55A6E1500021F5C020314F8 +DA003F018002F0C7FC51427BC05A>I119 D +E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fi cmsy10 10.95 1 +/Fi 1 16 df15 +D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fj cmtt10 10.95 89 +/Fj 89 127 df<121C127FEAFF80B3EA7F00B2123EC7FCA8121C127FA2EAFF80A3EA7F00 +A2121C09396DB830>33 D<00101304007C131F00FEEB3F80A26C137FA248133FB2007E14 +00007C7F003C131E00101304191C75B830>I<903907C007C0A2496C487EA8011F131FA2 +02C05BA3007FB7FCA2B81280A36C16006C5D3A007F807F80A2020090C7FCA9495BA2003F +90B512FE4881B81280A36C1600A22701FC01FCC7FCA300031303A201F85BA76C486C5AA2 +29387DB730>I38 DI<141E147F14FF5BEB03FEEB07FCEB0FF0EB1FE0EB3FC0EB7F80EBFF00 +485A5B12035B485A120F5BA2485AA2123F5BA2127F90C7FCA412FEAD127FA47F123FA27F +121FA26C7EA27F12076C7E7F12017F6C7EEB7F80EB3FC0EB1FE0EB0FF0EB07FCEB03FEEB +01FF7F147F141E184771BE30>I<127812FE7E7F6C7E6C7EEA0FF06C7E6C7E6C7E6C7EEB +7F80133F14C0131FEB0FE014F01307A2EB03F8A214FC1301A214FE1300A4147FAD14FEA4 +130114FCA2130314F8A2EB07F0A2130F14E0EB1FC0133F1480137FEBFF00485A485A485A +485AEA3FE0485A485A90C7FC5A1278184778BE30>I<14E0497E497EA60038EC0380007E +EC0FC0D8FF83EB3FE001C3137F9038F3F9FF267FFBFB13C06CB61280000FECFE00000314 +F86C5C6C6C13C0011F90C7FC017F13C048B512F04880000F14FE003FECFF80267FFBFB13 +C026FFF3F913E09038C3F87F0183133FD87E03EB0FC00038EC0380000091C7FCA66D5A6D +5A23277AAE30>I<143EA2147FAF007FB7FCA2B81280A36C1600A2C76CC8FCAF143EA229 +297DAF30>II<007FB612F0 +A2B712F8A36C15F0A225077B9E30>I<120FEA3FC0EA7FE0A2EAFFF0A4EA7FE0A2EA3FC0 +EA0F000C0C6E8B30>I<16F01501ED03F8A21507A2ED0FF0A2ED1FE0A2ED3FC0A2ED7F80 +A2EDFF00A24A5AA25D1403A24A5AA24A5AA24A5AA24A5AA24A5AA24AC7FCA2495AA25C13 +03A2495AA2495AA2495AA2495AA2495AA249C8FCA2485AA25B1203A2485AA2485AA2485A +A2485AA2485AA248C9FCA25AA2127CA225477BBE30>I<14FE903807FFC0497F013F13F8 +497F90B57E48EB83FF4848C6138049137F4848EB3FC04848EB1FE049130F001F15F04913 +07A24848EB03F8A290C712014815FCA400FEEC00FEAD6C14016C15FCA36D1303003F15F8 +A26D1307001F15F0A26D130F6C6CEB1FE0A26C6CEB3FC06C6CEB7F806D13FF2601FF8313 +006CEBFFFE6D5B6D5B010F13E06D5BD900FEC7FC273A7CB830>IIIII<000FB612804815C05AA316800180C8FCAEEB83FF019F13C0 +90B512F015FC8181D9FE0313809039F0007FC049133F0180EB1FE06CC7120F000E15F0C8 +1207A216F81503A31218127EA2B4FC150716F048140F6C15E06C141F6DEB3FC06D137F3A +3FE001FF80261FFC0F13006CB55A6C5C6C5C6C14E06C6C1380D90FFCC7FC25397BB730> +II<127CB712FC16FEA416FC48C7EA0FF816F0ED1FE0007CEC3FC0C8EA7F80EDFF00 +A24A5A4A5A5D14075D140F5D4A5AA24A5AA24AC7FCA25C5C13015CA213035CA213075CA4 +495AA6131F5CA96D5A6DC8FC273A7CB830>I<49B4FC011F13F0017F13FC90B57E0003EC +FF804815C048010113E03A1FF8003FF049131FD83FC0EB07F8A24848EB03FC90C71201A5 +6D1303003F15F86D13076C6CEB0FF06C6CEB1FE0D807FCEB7FC03A03FF83FF806C90B512 +006C6C13FC011F13F0497F90B512FE48802607FE0013C0D80FF8EB3FE0D81FE0EB0FF048 +48EB07F8491303007F15FC90C712014815FE481400A66C14016C15FC6D1303003F15F86D +1307D81FF0EB1FF06D133F3A0FFF01FFE06C90B512C06C1580C6ECFE006D5B011F13F001 +0190C7FC273A7CB830>I<49B4FC010F13E0013F13F890B57E4880488048010113803A0F +FC007FC0D81FF0EB3FE04848131F49EB0FF048481307A290C7EA03F85A4815FC1501A416 +FEA37E7E6D130315076C7E6C6C130F6D133FD80FFC13FF6CB6FC7E6C14FE6C14F9013FEB +E1FC010F138190380060011400ED03F8A2150716F0150F000F15E0486C131F486CEB3FC0 +157FEDFF804A1300EC07FE391FF01FFC90B55A6C5C6C5C6C1480C649C7FCEB3FF0273A7C +B830>I<120FEA3FC0EA7FE0A2EAFFF0A4EA7FE0A2EA3FC0EA0F00C7FCAF120FEA3FC0EA +7FE0A2EAFFF0A4EA7FE0A2EA3FC0EA0F000C276EA630>II<16F01503ED07F8151F157FEDFFF014034A13C0021F138091383FFE00ECFFF8495B01 +0713C0495BD93FFEC7FC495A3801FFF0485B000F13804890C8FCEA7FFC5BEAFFE05B7FEA +7FF87FEA1FFF6C7F000313E06C7F38007FFC6D7E90380FFF806D7F010113F06D7FEC3FFE +91381FFF80020713C06E13F01400ED7FF8151F1507ED03F01500252F7BB230>I<007FB7 +FCA2B81280A36C16006C5DCBFCA7003FB612FE4881B81280A36C1600A229157DA530>I< +1278127EB4FC13C07FEA7FF813FEEA1FFF6C13C000037F6C13F86C6C7EEB1FFF6D7F0103 +13E06D7F9038007FFC6E7E91380FFF806E13C0020113F080ED3FF8151F153FEDFFF05C02 +0713C04A138091383FFE004A5A903801FFF0495B010F13804990C7FCEB7FFC48485A4813 +E0000F5B4890C8FCEA7FFE13F8EAFFE05B90C9FC127E1278252F7BB230>I64 D<147F4A7EA2497FA449 +7F14F7A401077F14E3A3010F7FA314C1A2011F7FA490383F80FEA590387F007FA4498049 +133F90B6FCA34881A39038FC001F00038149130FA4000781491307A2D87FFFEB7FFFB56C +B51280A46C496C130029397DB830>I<007FB512F0B612FE6F7E82826C813A03F8001FF8 +15076F7E1501A26F7EA615015EA24B5A1507ED1FF0ED7FE090B65A5E4BC7FC6F7E16E082 +9039F8000FF8ED03FC6F7E1500167FA3EE3F80A6167F1700A25E4B5A1503ED1FFC007FB6 +FCB75A5E16C05E6C02FCC7FC29387EB730>I<91387F803C903903FFF03E49EBFC7E011F +13FE49EBFFFE5B9038FFE07F48EB801F3903FE000F484813075B48481303A2484813015B +123F491300A2127F90C8FC167C16005A5AAC7E7EA2167C6D14FE123FA27F121F6D13016C +6C14FCA26C6CEB03F86D13076C6CEB0FF03901FF801F6C9038E07FE06DB512C06D14806D +1400010713FC6D13F09038007FC0273A7CB830>I<003FB512E04814FCB67E6F7E6C816C +813A03F8007FF0ED1FF8150F6F7E6F7E15016F7EA2EE7F80A2163F17C0161FA4EE0FE0AC +161F17C0A3163F1780A2167F17005E4B5A15034B5A150F4B5AED7FF0003FB65A485DB75A +93C7FC6C14FC6C14E02B387FB730>I<007FB7FCB81280A47ED803F8C7123FA8EE1F0093 +C7FCA4157C15FEA490B5FCA6EBF800A4157C92C8FCA5EE07C0EE0FE0A9007FB7FCB8FCA4 +6C16C02B387EB730>I<003FB712804816C0B8FCA27E7ED801FCC7121FA8EE0F8093C7FC +A5153E157FA490B6FCA69038FC007FA4153E92C8FCAE383FFFF8487FB5FCA27E6C5B2A38 +7EB730>I<02FF13F00103EBC0F8010F13F1013F13FD4913FF90B6FC4813C1EC007F4848 +133F4848131F49130F485A491307121F5B123F491303A2127F90C7FC6F5A92C8FC5A5AA8 +92B5FC4A14805CA26C7F6C6D1400ED03F8A27F003F1407A27F121F6D130F120F7F6C6C13 +1FA2D803FE133F6C6C137FECC1FF6C90B5FC7F6D13FB010F13F30103EBC1F0010090C8FC +293A7DB830>I<3B3FFF800FFFE0486D4813F0B56C4813F8A26C496C13F06C496C13E0D8 +03F8C7EAFE00B290B6FCA601F8C7FCB3A23B3FFF800FFFE0486D4813F0B56C4813F8A26C +496C13F06C496C13E02D387FB730>I<007FB6FCB71280A46C1500260007F0C7FCB3B3A8 +007FB6FCB71280A46C1500213879B730>I<49B512F04914F85BA27F6D14F090C7EAFE00 +B3B3123C127EB4FCA24A5A1403EB8007397FF01FF86CB55A5D6C5C00075C000149C7FC38 +003FF025397AB730>II<383FFFF8487FB57EA26C5B6C5BD801FCC9FCB3B0EE0F +80EE1FC0A9003FB7FC5AB8FCA27E6C16802A387EB730>III<90383FFFE048B512FC00 +0714FF4815804815C04815E0EBF80001E0133FD87F80EB0FF0A290C71207A44815F84814 +03B3A96C1407A26C15F0A36D130FA26D131F6C6CEB3FE001F813FF90B6FC6C15C06C1580 +6C1500000114FCD8003F13E0253A7BB830>I<007FB512F0B612FE6F7E16E0826C813903 +F8003FED0FFCED03FE15016F7EA2821780163FA6167F17005EA24B5A1503ED0FFCED3FF8 +90B6FC5E5E16804BC7FC15F001F8C9FCB0387FFFC0B57EA46C5B29387EB730>I<90383F +FFE048B512FC000714FF4815804815C04815E0EBF80001E0133F4848EB1FF049130F90C7 +1207A44815F8481403B3A8147E14FE6CEBFF076C15F0EC7F87A2EC3FC7018013CF9038C0 +1FFFD83FE014E0EBF80F90B6FC6C15C06C15806C1500000114FCD8003F7FEB00016E7EA2 +1680157F16C0153F16E0151F16F0150FED07E025467BB830>I<003FB57E4814F0B612FC +15FF6C816C812603F8017F9138003FF0151F6F7E15071503821501A515035E1507150F4B +5A153F4AB45A90B65A5E93C7FC5D8182D9F8007FED3FE0151F150F821507A817F8EEF1FC +A53A3FFF8003FB4801C0EBFFF8B56C7E17F06C496C13E06C49EB7FC0C9EA1F002E397FB7 +30>I<90390FF803C0D97FFF13E048B512C74814F74814FF5A381FF80F383FE001497E48 +48137F90C7123F5A48141FA2150FA37EED07C06C91C7FC7F7FEA3FF0EA1FFEEBFFF06C13 +FF6C14E0000114F86C80011F13FF01031480D9003F13C014019138007FE0151FED0FF0A2 +ED07F8A2007C140312FEA56C140716F07F6DEB0FE06D131F01F8EB3FC001FF13FF91B512 +80160000FD5CD8FC7F13F8D8F81F5BD878011380253A7BB830>I<003FB712C04816E0B8 +FCA43AFE003F800FA8007CED07C0C791C7FCB3B1011FB5FC4980A46D91C7FC2B387EB730 +>I<3B7FFFC007FFFCB56C4813FEA46C496C13FCD803F8C7EA3F80B3B16D147F00011600 +A36C6C14FE6D13016D5CEC800390393FE00FF890391FF83FF06DB55A6D5C6D5C6D91C7FC +9038007FFCEC1FF02F3980B730>III<3A3FFF01FFF84801837F02C77FA202835B6C01015B3A01FC007F806D91C7 +FC00005C6D5BEB7F01EC81FCEB3F8314C3011F5B14E7010F5B14FF6D5BA26D5BA26D5BA2 +6D90C8FCA4497FA2497FA2815B81EB0FE781EB1FC381EB3F8181EB7F0081497F49800001 +143F49800003141F49800007140FD87FFEEB7FFFB590B5128080A25C6C486D130029387D +B730>II<001FB612FC4815FE5AA490C7EA03FCED07F816F0150FED1FE016C0153F +ED7F80003E1500C85A4A5A5D14034A5A5D140F4A5A5D143F4A5A92C7FC5C495A5C130349 +5A5C130F495A5C133F495A91C8FC5B4848147C4914FE1203485A5B120F485A5B123F485A +90B6FCB7FCA46C15FC27387CB730>I<007FB5FCB61280A4150048C8FCB3B3B3A5B6FC15 +80A46C140019476DBE30>I<007FB5FCB61280A47EC7123FB3B3B3A5007FB5FCB6FCA46C +140019477DBE30>93 D<1307EB1FC0EB7FF0497E000313FE000FEBFF80003F14E0D87FFD +13F039FFF07FF8EBC01FEB800F38FE0003007CEB01F00010EB00401D0E77B730>I<007F +B612F0A2B712F8A36C15F0A225077B7D30>I97 +DII<913801FFE04A7F5C +A28080EC0007AAEB03FE90381FFF874913E790B6FC5A5A481303380FFC00D81FF0133F49 +131F485A150F4848130790C7FCA25AA25AA87E6C140FA27F003F141F6D133F6C7E6D137F +390FF801FF2607FE07EBFFC06CB712E06C16F06C14F76D01C713E0011F010313C0D907FC +C8FC2C397DB730>I<49B4FC010713E0011F13F8017F7F90B57E488048018113803A07FC +007FC04848133FD81FE0EB1FE0150F484814F0491307127F90C7FCED03F85A5AB7FCA516 +F048C9FC7E7EA27F003FEC01F06DEB03F86C7E6C7E6D1307D807FEEB1FF03A03FFC07FE0 +6C90B5FC6C15C0013F14806DEBFE00010713F8010013C0252A7CA830>IIII< +14E0EB03F8A2497EA36D5AA2EB00E091C8FCA9381FFFF8487F5AA27E7EEA0001B3A9003F +B612C04815E0B7FCA27E6C15C023397AB830>III<387FFFF8B57EA47EEA0001B3B3A8007FB612F0B712F8A46C15F025387BB7 +30>I<02FC137E3B7FC3FF01FF80D8FFEF01877F90B500CF7F15DF92B57E6C010F138726 +07FE07EB03F801FC13FE9039F803FC01A201F013F8A301E013F0B3A23C7FFE0FFF07FF80 +B548018F13C0A46C486C01071380322881A730>II< +49B4FC010F13E0013F13F8497F90B57E0003ECFF8014013A07FC007FC04848EB3FE0D81F +E0EB0FF0A24848EB07F8491303007F15FC90C71201A300FEEC00FEA86C14016C15FCA26D +1303003F15F86D13076D130F6C6CEB1FF06C6CEB3FE06D137F3A07FF01FFC06C90B51280 +6C15006C6C13FC6D5B010F13E0010190C7FC272A7CA830>II<49B413F8010FEBC1FC013F13F14913FD48B6FC5A4813 +81390FFC007F49131F4848130F491307485A491303127F90C7FC15015A5AA77E7E15037F +A26C6C1307150F6C6C131F6C6C133F01FC137F3907FF01FF6C90B5FC6C14FD6C14F9013F +13F1010F13C1903803FE0190C7FCAD92B512F84A14FCA46E14F82E3C7DA730>II<90381FFC1E48B5129F000714FF5A5A5A387FF007EB800100FEC7FC4880A46C143E +007F91C7FC13E06CB4FC6C13FC6CEBFF806C14E0000114F86C6C7F01037F9038000FFF02 +001380007C147F00FEEC1FC0A2150F7EA27F151F6DEB3F806D137F9039FC03FF0090B6FC +5D5D00FC14F0D8F83F13C026780FFEC7FC222A79A830>III<3B3F +FFC07FFF80486DB512C0B515E0A26C16C06C496C13803B01F80003F000A26D130700005D +A26D130F017E5CA2017F131F6D5CA2EC803F011F91C7FCA26E5A010F137EA2ECE0FE0107 +5BA214F101035BA3903801FBF0A314FF6D5BA36E5A6E5A2B277EA630>I<3B3FFFC01FFF +E0486D4813F0B515F8A26C16F06C496C13E0D807E0C7EA3F00A26D5C0003157EA56D14FE +00015DEC0F80EC1FC0EC3FE0A33A00FC7FF1F8A2147DA2ECFDF9017C5C14F8A3017E13FB +A290393FF07FE0A3ECE03FA2011F5C90390F800F802D277FA630>I<3A3FFF81FFFC4801 +C37FB580A26C5D6C01815BC648C66CC7FC137FEC80FE90383F81FC90381FC3F8EB0FE3EC +E7F06DB45A6D5B7F6D5B92C8FC147E147F5C497F81903803F7E0EB07E790380FE3F0ECC1 +F890381F81FC90383F80FE90387F007E017E137F01FE6D7E48486D7E267FFF80B5FCB500 +C1148014E3A214C16C0180140029277DA630>I<3B3FFFC07FFF80486DB512C0B515E0A2 +6C16C06C496C13803B01FC0003F000A2000014076D5C137E150F017F5C7F151FD91F805B +A214C0010F49C7FCA214E00107137EA2EB03F0157C15FCEB01F85DA2EB00F9ECFDF0147D +147FA26E5AA36E5AA35DA2143F92C8FCA25C147EA2000F13FE486C5AEA3FC1EBC3F81387 +EB8FF0EBFFE06C5B5C6C90C9FC6C5AEA01F02B3C7EA630>I<001FB612FC4815FE5AA316 +FC90C7EA0FF8ED1FF0ED3FE0ED7FC0EDFF80003E491300C7485A4A5A4A5A4A5A4A5A4A5A +4A5A4990C7FC495A495A495A495A495A495A4948133E4890C7127F485A485A485A485A48 +5A48B7FCB8FCA46C15FE28277DA630>II< +127CA212FEB3B3B3AD127CA207476CBE30>II<017C13 +3848B4137C48EB80FE4813C14813C348EBEFFC397FEFFFF0D8FF8713E0010713C0486C13 +80D87C0113003838007C1F0C78B730>I E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fk cmbx12 14.4 49 +/Fk 49 122 df12 D45 DI<157815FC14031407141F14FF130F00 +07B5FCB6FCA2147F13F0EAF800C7FCB3B3B3A6007FB712FEA52F4E76CD43>49 +DI<91380FFFC091B512FC0107ECFF80011F15E09026 +3FF8077F9026FF800113FC4848C76C7ED803F86E7E491680D807FC8048B416C080486D15 +E0A4805CA36C17C06C5B6C90C75AD801FC1680C9FC4C13005FA24C5A4B5B4B5B4B13C04B +5BDBFFFEC7FC91B512F816E016FCEEFF80DA000713E0030113F89238007FFE707E701380 +7013C018E07013F0A218F8A27013FCA218FEA2EA03E0EA0FF8487E487E487EB57EA318FC +A25E18F891C7FC6C17F0495C6C4816E001F04A13C06C484A1380D80FF84A13006CB44A5A +6CD9F0075BC690B612F06D5D011F1580010302FCC7FCD9001F1380374F7ACD43>I<177C +17FEA2160116031607160FA2161F163F167FA216FF5D5DA25D5DED1FBFED3F3F153E157C +15FCEC01F815F0EC03E01407EC0FC01580EC1F005C147E147C5C1301495A495A5C495A13 +1F49C7FC133E5B13FC485A5B485A1207485A485A90C8FC123E127E5ABA12C0A5C96C48C7 +FCAF020FB712C0A53A4F7CCE43>III<121F7F7FEB +FF8091B81280A45A1900606060A2606060485F0180C86CC7FC007EC95A4C5A007C4B5A5F +4C5A160F4C5A484B5A4C5A94C8FC16FEC812014B5A5E4B5A150F4B5AA24B5AA24B5A15FF +A24A90C9FCA25C5D1407A2140FA25D141FA2143FA4147F5DA314FFA55BAC6D5BA2EC3FC0 +6E5A395279D043>I<913807FFC0027F13FC0103B67E010F15E090261FFC0113F8903A3F +E0003FFCD97F80EB0FFE49C76C7E48488048486E1380000717C04980120F18E0177FA212 +1F7FA27F7F6E14FF02E015C014F802FE4913806C7FDBC00313009238F007FE6C02F85B92 +38FE1FF86C9138FFBFF06CEDFFE017806C4BC7FC6D806D81010F15E06D81010115FC0107 +81011F81491680EBFFE748018115C048D9007F14E04848011F14F048487F484813030300 +14F8484880161F4848020713FC1601824848157F173FA2171FA2170FA218F8A27F007F17 +F06D151FA26C6CED3FE0001F17C06D157F6C6CEDFF806C6C6C010313006C01E0EB0FFE6C +01FCEBFFFC6C6CB612F06D5D010F1580010102FCC7FCD9000F13C0364F7ACD43>I<9138 +0FFF8091B512F8010314FE010F6E7E4901037F90267FF8007F4948EB3FF048496D7E4849 +80486F7E484980824817805A91C714C05A7013E0A218F0B5FCA318F8A618FCA46C5DA37E +A25E6C7F6C5DA26C5D6C7F6C6D137B6C6D13F390387FF803011FB512E36D14C301030283 +13F89039007FFE03EC00401500A218F05EA3D801F816E0487E486C16C0487E486D491380 +A218005E5F4C5A91C7FC6C484A5A494A5A49495B6C48495BD803FC010F5B9027FF807FFE +C7FC6C90B55A6C6C14F06D14C0010F49C8FC010013F0364F7ACD43>I<91B5FC010F14F8 +017F14FF90B712C00003D9C00F7F2707FC00017FD80FE06D7F48486E7E48C87FD87FE06E +7E7F7F486C1680A66C5A18006C485C6C5AC9485A5F4B5B4B5B4B5B4B5B4B90C7FC16FC4B +5A4B5A16C04B5A93C8FC4A5A5D14035D5D14075DA25D140FA25DAB91CAFCAAEC1FC04A7E +ECFFF8497FA2497FA76D5BA26D5BEC3FE06E5A315479D340>63 D68 DI +I72 D +I<027FB71280A591C76C90C7FCB3B3B3EA07F0EA1FFC487E487EA2B57EA44C5AA34A485B +7E49495BD83FF8495BD81FE05DD80FFC011F5B2707FF807F90C8FC000190B512FC6C6C14 +F0011F14C0010101F8C9FC39537DD145>I76 DI80 +D82 D<91260FFF80130791B5 +00F85B010702FF5B011FEDC03F49EDF07F9026FFFC006D5A4801E0EB0FFD4801800101B5 +FC4848C87E48488149150F001F824981123F4981007F82A28412FF84A27FA26D82A27F7F +6D93C7FC14C06C13F014FF15F86CECFF8016FC6CEDFFC017F06C16FC6C16FF6C17C06C83 +6C836D826D82010F821303010082021F16801400030F15C0ED007F040714E01600173F05 +0F13F08383A200788200F882A3187FA27EA219E07EA26CEFFFC0A27F6D4B13806D17006D +5D01FC4B5A01FF4B5A02C04A5A02F8EC7FF0903B1FFFC003FFE0486C90B65AD8FC0393C7 +FC48C66C14FC48010F14F048D9007F90C8FC3C5479D24B>I<003FBC1280A59126C0003F +9038C0007F49C71607D87FF8060113C001E08449197F49193F90C8171FA2007E1A0FA300 +7C1A07A500FC1BE0481A03A6C994C7FCB3B3AC91B912F0A553517BD05E>II87 +D97 +DI<913801FFF8021FEBFF8091B612F0010315FC010F9038C00FFE903A1FFE0001 +FFD97FFC491380D9FFF05B4817C048495B5C5A485BA2486F138091C7FC486F1300705A48 +92C8FC5BA312FFAD127F7FA27EA2EF03E06C7F17076C6D15C07E6E140F6CEE1F806C6DEC +3F006C6D147ED97FFE5C6D6CEB03F8010F9038E01FF0010390B55A01001580023F49C7FC +020113E033387CB63C>I<4DB47E0407B5FCA5EE001F1707B3A4913801FFE0021F13FC91 +B6FC010315C7010F9038E03FE74990380007F7D97FFC0101B5FC49487F4849143F484980 +485B83485B5A91C8FC5AA3485AA412FFAC127FA36C7EA37EA26C7F5F6C6D5C7E6C6D5C6C +6D49B5FC6D6C4914E0D93FFED90FEFEBFF80903A0FFFC07FCF6D90B5128F0101ECFE0FD9 +003F13F8020301C049C7FC41547CD24B>I<913803FFC0023F13FC49B6FC010715C04901 +817F903A3FFC007FF849486D7E49486D7E4849130F48496D7E48178048497F18C0488191 +C7FC4817E0A248815B18F0A212FFA490B8FCA318E049CAFCA6127FA27F7EA218E06CEE01 +F06E14037E6C6DEC07E0A26C6DEC0FC06C6D141F6C6DEC3F806D6CECFF00D91FFEEB03FE +903A0FFFC03FF8010390B55A010015C0021F49C7FC020113F034387CB63D>IIII<137F497E +000313E0487FA2487FA76C5BA26C5BC613806DC7FC90C8FCADEB3FF0B5FCA512017EB3B3 +A6B612E0A51B547BD325>I +107 DIII<913801FFE0021F13FE91B612C0010315F0010F9038 +807FFC903A1FFC000FFED97FF86D6C7E49486D7F48496D7F48496D7F4A147F48834890C8 +6C7EA24883A248486F7EA3007F1880A400FF18C0AC007F1880A3003F18006D5DA26C5FA2 +6C5F6E147F6C5F6C6D4A5A6C6D495B6C6D495B6D6C495BD93FFE011F90C7FC903A0FFF80 +7FFC6D90B55A010015C0023F91C8FC020113E03A387CB643>I<903A3FF001FFE0B5010F +13FE033FEBFFC092B612F002F301017F913AF7F8007FFE0003D9FFE0EB1FFFC602806D7F +92C76C7F4A824A6E7F4A6E7FA2717FA285187F85A4721380AC1A0060A36118FFA2615F61 +6E4A5BA26E4A5B6E4A5B6F495B6F4990C7FC03F0EBFFFC9126FBFE075B02F8B612E06F14 +80031F01FCC8FC030313C092CBFCB1B612F8A5414D7BB54B>I<90397FE003FEB590380F +FF80033F13E04B13F09238FE1FF89139E1F83FFC0003D9E3E013FEC6ECC07FECE78014EF +150014EE02FEEB3FFC5CEE1FF8EE0FF04A90C7FCA55CB3AAB612FCA52F367CB537>114 +D<903903FFF00F013FEBFE1F90B7FC120348EB003FD80FF81307D81FE0130148487F4980 +127F90C87EA24881A27FA27F01F091C7FC13FCEBFFC06C13FF15F86C14FF16C06C15F06C +816C816C81C681013F1580010F15C01300020714E0EC003F030713F015010078EC007F00 +F8153F161F7E160FA27E17E07E6D141F17C07F6DEC3F8001F8EC7F0001FEEB01FE9039FF +C00FFC6DB55AD8FC1F14E0D8F807148048C601F8C7FC2C387CB635>I<143EA6147EA414 +FEA21301A313031307A2130F131F133F13FF5A000F90B6FCB8FCA426003FFEC8FCB3A9EE +07C0AB011FEC0F8080A26DEC1F0015806DEBC03E6DEBF0FC6DEBFFF86D6C5B021F5B0203 +13802A4D7ECB34>IIII121 D E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fl cmr10 10.95 86 +/Fl 86 124 df<4AB4EB0FE0021F9038E03FFC913A7F00F8FC1ED901FC90383FF03FD907 +F090397FE07F80494801FF13FF4948485BD93F805C137F0200ED7F00EF003E01FE6D91C7 +FC82ADB97EA3C648C76CC8FCB3AE486C4A7E007FD9FC3FEBFF80A339407FBF35>11 +D<4AB4FC021F13C091387F01F0903901FC0078D907F0131C4948133E494813FF49485A13 +7F1400A213FE6F5A163893C7FCAA167FB8FCA33900FE00018182B3AC486CECFF80007FD9 +FC3F13FEA32F407FBF33>I<4AB47E021F13F791387F00FFEB01F8903807F001EB0FE0EB +1FC0EB3F80137F14008101FE80AEB8FCA3C648C77EB3AE486CECFF80007FD9FC3F13FEA3 +2F407FBF33>I<4AB4ECFF80021FD9C00F13E0913B7F01F03F80F8903C01F80078FE003C +D907F0D93FF8130E49484948131F49484948EB7F804948484913FF137F02005CA201FE92 +C7FC6FED7F0070141C96C7FCAAF13F80BBFCA3C648C76CC7FC197F193FB3AC486C4A6CEB +7FC0007FD9FC3FD9FE1FB5FCA348407FBF4C>I<121EEA7F80EAFFC0A9EA7F80ACEA3F00 +AC121EAB120CC7FCA8121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A4179C019>33 +D<001E130F397F803FC000FF137F01C013E0A201E013F0A3007F133F391E600F30000013 +00A401E01370491360A3000114E04913C00003130101001380481303000EEB070048130E +0018130C0038131C003013181C1C7DBE2D>I<013F4C7ED9FFC04B7E2601E0E015072607 +C070150F48486C4B5A023E4BC7FC48486C5D48D90FC0EB01FE003ED90EF0EB07FCDA0F3F +133E007E903A070FFFF8F8007C0200EBC1F0EE000300FC6D6C495A604D5A171F95C8FC17 +3E177E177C5F16015F007C4948485A1607007E5E003E49495A020E131F003F93C9FC6C49 +133E260F803C137E0238137C6C6C485B3901E0E0016CB448485AD93F0049133F90C74848 +EBFFC0030F903801E0E093398007C0704B4848487E4B153C033E90381F001C4B497F03FC +133E4B150F4A48017E7F0203147C5D4A4801FCEB0380140F5D4AC7FC5C143E5C14FC5C49 +5A13034948027CEB07005C4948147E011F033E5B91C8140E013E153F017E6F5B017C9238 +0F803C4917380001706C5A49923801E0E0496FB45A6C48043FC7FC41497BC34C>37 +DI<121EEA7F8012FF13C0A213E0A3127FEA1E601200A413E013C0A3120113801203 +13005A120E5A1218123812300B1C79BE19>I<1430147014E0EB01C0EB03801307EB0F00 +131E133E133C5B13F85B12015B1203A2485AA2120F5BA2121F90C7FCA25AA3123E127EA6 +127C12FCB2127C127EA6123E123FA37EA27F120FA27F1207A26C7EA212017F12007F1378 +7F133E131E7FEB07801303EB01C0EB00E014701430145A77C323>I<12C07E12707E7E12 +1E7E6C7E7F12036C7E7F12007F1378137CA27FA2133F7FA21480130FA214C0A3130714E0 +A6130314F0B214E01307A614C0130FA31480A2131F1400A25B133EA25BA2137813F85B12 +015B485A12075B48C7FC121E121C5A5A5A5A145A7BC323>II<121EEA7F8012FF13C0A213 +E0A3127FEA1E601200A413E013C0A312011380120313005A120E5A1218123812300B1C79 +8919>44 DI<121EEA7F80A2EAFFC0A4EA7F80A2EA1E000A0A79 +8919>IIIIII<150E151E153EA2157EA215FE1401A21403EC +077E1406140E141CA214381470A214E0EB01C0A2EB0380EB0700A2130E5BA25B5BA25B5B +1201485A90C7FC5A120E120C121C5AA25A5AB8FCA3C8EAFE00AC4A7E49B6FCA3283E7EBD +2D>I<00061403D80780131F01F813FE90B5FC5D5D5D15C092C7FC14FCEB3FE090C9FCAC +EB01FE90380FFF8090383E03E090387001F8496C7E49137E497F90C713800006141FC813 +C0A216E0150FA316F0A3120C127F7F12FFA416E090C7121F12FC007015C012780038EC3F +80123C6CEC7F00001F14FE6C6C485A6C6C485A3903F80FE0C6B55A013F90C7FCEB07F824 +3F7CBC2D>II<1238123C123F90B6 +12FCA316F85A16F016E00078C712010070EC03C0ED078016005D48141E151C153C5DC812 +7015F04A5A5D14034A5A92C7FC5C141EA25CA2147C147814F8A213015C1303A31307A313 +0F5CA2131FA6133FAA6D5A0107C8FC26407BBD2D>III<12 +1EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3121EEA7F80A2EAFFC0A4EA7F80A2EA1E00 +0A2779A619>I<121EEA7F80A2EAFFC0A4EA7F80A2EA1E00C7FCB3121E127FEAFF80A213 +C0A4127F121E1200A412011380A3120313005A1206120E120C121C5A1230A20A3979A619 +>I<007FB912E0BA12F0A26C18E0CDFCAE007FB912E0BA12F0A26C18E03C167BA147>61 +D63 D<15074B7EA34B7EA34B7EA34B7EA34B7E15E7A2913801C7FC15C3A291380381 +FEA34AC67EA3020E6D7EA34A6D7EA34A6D7EA34A6D7EA34A6D7EA349486D7E91B6FCA249 +819138800001A249C87EA24982010E157FA2011E82011C153FA2013C820138151FA20178 +82170F13FC00034C7ED80FFF4B7EB500F0010FB512F8A33D417DC044>65 +DII +IIII< +B6D8C01FB512F8A3000101E0C7383FFC0026007F80EC0FF0B3A691B7FCA30280C7120FB3 +A92601FFE0EC3FFCB6D8C01FB512F8A33D3E7DBD44>II<011FB512FCA3D9000713006E5A1401B3B3A6123FEA +7F80EAFFC0A44A5A1380D87F005B007C130700385C003C495A6C495A6C495A2603E07EC7 +FC3800FFF8EB3FC026407CBD2F>IIIIIII +III<003FB91280A3903AF0 +007FE001018090393FC0003F48C7ED1FC0007E1707127C00781703A300701701A548EF00 +E0A5C81600B3B14B7E4B7E0107B612FEA33B3D7DBC42>IIII<007F +B5D8C003B512E0A3C649C7EBFC00D93FF8EC3FE06D48EC1F806D6C92C7FC171E6D6C141C +6D6C143C5F6D6C14706D6D13F04C5ADA7FC05B023F13036F485ADA1FF090C8FC020F5BED +F81E913807FC1C163C6E6C5A913801FF7016F06E5B6F5AA26F7E6F7EA28282153FED3BFE +ED71FF15F103E07F913801C07F0203804B6C7EEC07004A6D7E020E6D7E5C023C6D7E0238 +6D7E14784A6D7E4A6D7F130149486E7E4A6E7E130749C86C7E496F7E497ED9FFC04A7E00 +076DEC7FFFB500FC0103B512FEA33F3E7EBD44>II<003FB712F8A391C7EA1FF013F801E0EC3FE00180EC7FC090C8FC003EED +FF80A2003C4A1300007C4A5A12784B5A4B5AA200704A5AA24B5A4B5AA2C8485A4A90C7FC +A24A5A4A5AA24A5AA24A5A4A5AA24A5A4A5AA24990C8FCA2495A4948141CA2495A495AA2 +495A495A173C495AA24890C8FC485A1778485A484815F8A24848140116034848140F4848 +143FED01FFB8FCA32E3E7BBD38>I +I<486C13C00003130101001380481303000EEB070048130E0018130C0038131C00301318 +0070133800601330A300E01370481360A400CFEB678039FFC07FE001E013F0A3007F133F +A2003F131F01C013E0390F0007801C1C73BE2D>II97 +DI<49B4FC010F13E090383F00F8017C131E4848131F +4848137F0007ECFF80485A5B121FA24848EB7F00151C007F91C7FCA290C9FC5AAB6C7EA3 +003FEC01C07F001F140316806C6C13076C6C14000003140E6C6C131E6C6C137890383F01 +F090380FFFC0D901FEC7FC222A7DA828>II +II<167C903903F801 +FF903A1FFF078F8090397E0FDE1F9038F803F83803F001A23B07E000FC0600000F6EC7FC +49137E001F147FA8000F147E6D13FE00075C6C6C485AA23901F803E03903FE0FC026071F +FFC8FCEB03F80006CAFC120EA3120FA27F7F6CB512E015FE6C6E7E6C15E06C810003813A +0FC0001FFC48C7EA01FE003E140048157E825A82A46C5D007C153E007E157E6C5D6C6C49 +5A6C6C495AD803F0EB0FC0D800FE017FC7FC90383FFFFC010313C0293D7EA82D>III<1478EB01FEA2EB03FFA4EB01FEA2EB00781400AC147FEB7FFFA313 +017F147FB3B3A5123E127F38FF807E14FEA214FCEB81F8EA7F01387C03F0381E07C0380F +FF803801FC00185185BD1C>II +I<2701F801FE14FF00FF902707FFC00313E0913B1E07E00F03F0913B7803F03C01F80007 +903BE001F87000FC2603F9C06D487F000101805C01FBD900FF147F91C75B13FF4992C7FC +A2495CB3A6486C496CECFF80B5D8F87FD9FC3F13FEA347287DA74C>I<3901F801FE00FF +903807FFC091381E07E091387803F000079038E001F82603F9C07F0001138001FB6D7E91 +C7FC13FF5BA25BB3A6486C497EB5D8F87F13FCA32E287DA733>I<14FF010713E090381F +81F890387E007E01F8131F4848EB0F804848EB07C04848EB03E0000F15F04848EB01F8A2 +003F15FCA248C812FEA44815FFA96C15FEA36C6CEB01FCA3001F15F86C6CEB03F0A26C6C +EB07E06C6CEB0FC06C6CEB1F80D8007EEB7E0090383F81FC90380FFFF0010090C7FC282A +7EA82D>I<3901FC03FC00FF90381FFF8091387C0FE09039FDE003F03A03FFC001FC6C49 +6C7E91C7127F49EC3F805BEE1FC017E0A2EE0FF0A3EE07F8AAEE0FF0A4EE1FE0A2EE3FC0 +6D1580EE7F007F6E13FE9138C001F89039FDE007F09039FC780FC0DA3FFFC7FCEC07F891 +C9FCAD487EB512F8A32D3A7EA733>I<02FF131C0107EBC03C90381F80F090397F00387C +01FC131CD803F8130E4848EB0FFC150748481303121F485A1501485AA448C7FCAA6C7EA3 +6C7EA2001F14036C7E15076C6C130F6C7E6C6C133DD8007E137990383F81F190380FFFC1 +903801FE0190C7FCAD4B7E92B512F8A32D3A7DA730>I<3901F807E000FFEB1FF8EC787C +ECE1FE3807F9C100031381EA01FB1401EC00FC01FF1330491300A35BB3A5487EB512FEA3 +1F287EA724>I<90383FC0603901FFF8E03807C03F381F000F003E1307003C1303127C00 +78130112F81400A27E7E7E6D1300EA7FF8EBFFC06C13F86C13FE6C7F6C1480000114C0D8 +003F13E0010313F0EB001FEC0FF800E01303A214017E1400A27E15F07E14016C14E06CEB +03C0903880078039F3E01F0038E0FFFC38C01FE01D2A7DA824>I<131CA6133CA4137CA2 +13FCA2120112031207001FB512C0B6FCA2D801FCC7FCB3A215E0A912009038FE01C0A2EB +7F03013F138090381F8700EB07FEEB01F81B397EB723>IIIIII<001FB61280A2EBE0000180140049485A001E495A121C4A5A003C49 +5A141F00385C4A5A147F5D4AC7FCC6485AA2495A495A130F5C495A90393FC00380A2EB7F +80EBFF005A5B484813071207491400485A48485BA248485B4848137F00FF495A90B6FCA2 +21277EA628>II E +%EndDVIPSBitmapFont +%DVIPSBitmapFont: Fm cmbx12 20.736 9 +/Fm 9 123 df<92380FFFE04AB67E020F15F0027F15FE49B87E4917E0010F17F8013F83 +49D9C01F14FF9027FFFC0001814801E06D6C80480180021F804890C86C8048486F804848 +6F8001FF6F804801C06E8002F081486D18806E816E18C0B5821BE06E81A37214F0A56C5B +A36C5B6C5B6C5B000313C0C690C9FC90CA15E060A34E14C0A21B80601B0060626295B55A +5F624D5C624D5C4D91C7FC614D5B4D13F04D5B6194B55A4C49C8FC4C5B4C5B4C13E04C5B +604C90C9FCEE7FFC4C5A4B5B4B5B4B0180EC0FF04B90C8FC4B5A4B5A4B48ED1FE0EDFFE0 +4A5B4A5B4A90C9FC4A48163F4A5ADA3FF017C05D4A48167F4A5A4990CA12FFD903FC1607 +49BAFC5B4919805B5B90BBFC5A5A5A5A481A005A5ABCFCA462A44C7176F061>50 +D<92383FFFF80207B612E0027F15FC49B87E010717E0011F83499026F0007F13FC4948C7 +000F7F90B502036D7E486E6D806F6D80727F486E6E7F8486727FA28684A26C5C72806C5C +6D90C8FC6D5AEB0FF8EB03E090CAFCA70507B6FC041FB7FC0303B8FC157F0203B9FC021F +ECFE0391B612800103ECF800010F14C04991C7FC017F13FC90B512F04814C0485C4891C8 +FC485B5A485B5C5A5CA2B5FC5CA360A36E5DA26C5F6E5D187E6C6D846E4A48806C6D4A48 +14FC6C6ED90FF0ECFFFC6C02E090263FE07F14FE00019139FC03FFC06C91B6487E013F4B +487E010F4B1307010303F01301D9003F0280D9003F13FC020101F8CBFC57507ACE5E>97 +D<903801FFFCB6FCA8C67E131F7FB3ADF0FFFC050FEBFFE0057F14FE0403B77E040F16E0 +043F16F84CD9007F13FE9226FDFFF001077F92B500C001018094C86C13E004FC6F7F4C6F +7F04E06F7F4C6F7F5E747F93C915804B7014C0A27414E0A21DF087A21DF8A31DFC87A41D +FEAF1DFCA4631DF8A31DF098B5FC1DE0A25014C0A26F1980501400705D705F704B5B505B +704B5B04FC4B5BDBE7FE92B55A9226C3FF8001035C038101E0011F49C7FC9226807FFC90 +B55A4B6CB712F04A010F16C04A010393C8FC4A010015F84A023F14C090C9000301F0C9FC +5F797AF76C>I<97380FFFE00607B6FCA8F00003190086B3AD93383FFF800307B512F803 +3F14FF4AB712C0020716F0021F16FC027F9039FE007FFE91B500F0EB0FFF010302800101 +90B5FC4949C87E49498149498149498149498190B548814884484A8192CAFC5AA2485BA2 +5A5C5AA35A5CA4B5FCAF7EA4807EA37EA2807EA26C7F616C6E5D6C606C80616D6D5D6D6D +5D6D6D92B67E6D6D4A15FC010301FF0207EDFFFE6D02C0EB3FFE6D6C9039FC01FFF86E90 +B65A020F16C002031600DA007F14FC030F14E09226007FFEC749C7FC5F797AF76C>100 +D105 D<903801FFFCB6FCA8C67E131F7FB3B3B3B3B3ABB812C0A82A7879F7 +35>108 D<902601FFF891380FFFE0B692B512FE05036E7E050F15E0053F15F84D819327 +01FFF01F7F4CD900077FDC07FC6D80C66CDA0FF06D80011FDA1FC07F6D4A48824CC8FC04 +7E6F7F5EEDF9F85E03FB707F5E15FF5EA25EA293C9FCA45DB3B3A6B8D8E003B81280A861 +4E79CD6C>110 D<902601FFFCEC7FFEB6020FB512F0057F14FE4CB712C0040716F0041F +82047F16FE93B5C66C7F92B500F0010F14C0C66C0380010380011F4AC76C806D4A6E8004 +F06F7F4C6F7F4C6F7F4C8193C915804B7014C0861DE0A27414F0A27414F8A47513FCA575 +13FEAF5113FCA598B512F8A31DF0621DE0621DC0621D806F5E701800704B5B505B704B5B +7092B55A04FC4A5C704A5C706C010F5C05E0013F49C7FC9227FE7FFC01B55A70B712F004 +0F16C0040393C8FC040015F8053F14C0050301F0C9FC94CCFCB3A6B812E0A85F6F7ACD6C +>112 D<0007BA12FC1AFEA503E0C714FC4AC74814F84801F04A14F05C02804A14E091C8 +4814C04D14805B494B14004D5B4992B55AA24C5C494A5C615E4C5C001F4B5C5B4C91C7FC +4C5B93B55AA24B5CC8485C4B5CA24B5C4B5C4B91C8FCA24B5B92B55AA24A5C4A5C4A4A14 +FFA24A5C4A5C4A91C8FC614A4915FE91B55A495CA2495C494A14035E5B495C4991C81207 +A24949ED0FFC90B55A484A151FA2484A153F484A157F484A15FF1803484A140F4891C812 +3F48490207B5FC91B9FCBB12F8A57E484D7BCC56>122 D E +%EndDVIPSBitmapFont +end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: A4 + +%%EndSetup +%%Page: 1 1 +1 0 bop 150 1318 a Fm(bzip2)64 b(and)g(libbzip2)p 150 +1418 3600 34 v 2010 1515 a Fl(a)31 b(program)f(and)g(library)e(for)i +(data)h(compression)2198 1623 y(cop)m(yrigh)m(t)f(\(C\))h(1996-2000)j +(Julian)28 b(Sew)m(ard)2605 1731 y(v)m(ersion)i(1.0)h(of)g(21)g(Marc)m +(h)g(2000)150 5091 y Fk(Julian)46 b(Sew)l(ard)p 150 5141 +3600 17 v eop +%%Page: 1 2 +1 1 bop 3705 -116 a Fl(1)150 299 y(This)24 b(program,)j +Fj(bzip2)p Fl(,)e(and)g(asso)s(ciated)i(library)c Fj(libbzip2)p +Fl(,)i(are)h(Cop)m(yrigh)m(t)g(\(C\))g(1996-2000)j(Julian)150 +408 y(R)h(Sew)m(ard.)40 b(All)29 b(righ)m(ts)h(reserv)m(ed.)150 +565 y(Redistribution)f(and)i(use)h(in)f(source)h(and)g(binary)e(forms,) +j(with)e(or)h(without)f(mo)s(di\014cation,)g(are)i(p)s(er-)150 +675 y(mitted)d(pro)m(vided)f(that)i(the)f(follo)m(wing)f(conditions)g +(are)i(met:)225 832 y Fi(\017)60 b Fl(Redistributions)26 +b(of)k(source)g(co)s(de)g(m)m(ust)g(retain)f(the)h(ab)s(o)m(v)m(e)h +(cop)m(yrigh)m(t)g(notice,)f(this)f(list)f(of)i(con-)330 +941 y(ditions)e(and)i(the)h(follo)m(wing)e(disclaimer.)225 +1076 y Fi(\017)60 b Fl(The)33 b(origin)f(of)h(this)f(soft)m(w)m(are)j +(m)m(ust)e(not)h(b)s(e)e(misrepresen)m(ted;)i(y)m(ou)g(m)m(ust)f(not)g +(claim)g(that)h(y)m(ou)330 1185 y(wrote)d(the)h(original)d(soft)m(w)m +(are.)44 b(If)31 b(y)m(ou)g(use)g(this)f(soft)m(w)m(are)i(in)e(a)h(pro) +s(duct,)g(an)f(ac)m(kno)m(wledgmen)m(t)330 1295 y(in)f(the)i(pro)s +(duct)e(do)s(cumen)m(tation)h(w)m(ould)f(b)s(e)h(appreciated)g(but)g +(is)f(not)i(required.)225 1429 y Fi(\017)60 b Fl(Altered)21 +b(source)g(v)m(ersions)f(m)m(ust)h(b)s(e)f(plainly)e(mark)m(ed)j(as)g +(suc)m(h,)i(and)d(m)m(ust)h(not)g(b)s(e)f(misrepresen)m(ted)330 +1539 y(as)31 b(b)s(eing)e(the)h(original)f(soft)m(w)m(are.)225 +1674 y Fi(\017)60 b Fl(The)27 b(name)h(of)f(the)h(author)f(ma)m(y)h +(not)g(b)s(e)f(used)g(to)h(endorse)f(or)h(promote)g(pro)s(ducts)e +(deriv)m(ed)g(from)330 1783 y(this)j(soft)m(w)m(are)j(without)d(sp)s +(eci\014c)h(prior)e(written)i(p)s(ermission.)150 1965 +y(THIS)37 b(SOFTW)-10 b(ARE)38 b(IS)f(PR)m(O)m(VIDED)i(BY)g(THE)f(A)m +(UTHOR)g(\\AS)g(IS")g(AND)h(ANY)f(EXPRESS)150 2074 y(OR)31 +b(IMPLIED)h(W)-10 b(ARRANTIES,)31 b(INCLUDING,)i(BUT)f(NOT)f(LIMITED)g +(TO,)h(THE)f(IMPLIED)150 2184 y(W)-10 b(ARRANTIES)27 +b(OF)h(MER)m(CHANT)-8 b(ABILITY)28 b(AND)g(FITNESS)f(F)m(OR)g(A)h(P)-8 +b(AR)g(TICULAR)28 b(PUR-)150 2294 y(POSE)37 b(ARE)g(DISCLAIMED.)h(IN)f +(NO)h(EVENT)f(SHALL)g(THE)g(A)m(UTHOR)h(BE)g(LIABLE)g(F)m(OR)150 +2403 y(ANY)56 b(DIRECT,)f(INDIRECT,)h(INCIDENT)-8 b(AL,)56 +b(SPECIAL,)e(EXEMPLAR)-8 b(Y,)57 b(OR)e(CONSE-)150 2513 +y(QUENTIAL)48 b(D)m(AMA)m(GES)i(\(INCLUDING,)g(BUT)f(NOT)f(LIMITED)g +(TO,)g(PR)m(OCUREMENT)150 2622 y(OF)35 b(SUBSTITUTE)e(GOODS)i(OR)f(SER) +-10 b(VICES;)34 b(LOSS)f(OF)i(USE,)g(D)m(A)-8 b(T)g(A,)36 +b(OR)f(PR)m(OFITS;)f(OR)150 2732 y(BUSINESS)28 b(INTERR)m(UPTION\))g +(HO)m(WEVER)i(CA)m(USED)f(AND)g(ON)g(ANY)g(THEOR)-8 b(Y)29 +b(OF)g(LIA-)150 2842 y(BILITY,)36 b(WHETHER)g(IN)g(CONTRA)m(CT,)g +(STRICT)e(LIABILITY,)i(OR)g(TOR)-8 b(T)35 b(\(INCLUDING)150 +2951 y(NEGLIGENCE)45 b(OR)g(OTHER)-10 b(WISE\))44 b(ARISING)h(IN)g(ANY) +h(W)-10 b(A)i(Y)46 b(OUT)e(OF)i(THE)e(USE)h(OF)150 3061 +y(THIS)29 b(SOFTW)-10 b(ARE,)31 b(EVEN)f(IF)g(AD)m(VISED)i(OF)e(THE)g +(POSSIBILITY)e(OF)j(SUCH)f(D)m(AMA)m(GE.)150 3218 y(Julian)e(Sew)m +(ard,)i(Cam)m(bridge,)g(UK.)150 3374 y Fj(jseward@acm.org)150 +3531 y(http://sourceware.cygnus)o(.com)o(/bzi)o(p2)150 +3688 y(http://www.cacheprof.org)150 3845 y(http://www.muraroa.demon)o +(.co.)o(uk)150 4002 y(bzip2)p Fl(/)p Fj(libbzip2)d Fl(v)m(ersion)j(1.0) +i(of)e(21)h(Marc)m(h)g(2000.)150 4159 y(P)-8 b(A)g(TENTS:)40 +b(T)-8 b(o)40 b(the)g(b)s(est)g(of)g(m)m(y)g(kno)m(wledge,)j +Fj(bzip2)38 b Fl(do)s(es)i(not)g(use)g(an)m(y)g(paten)m(ted)h +(algorithms.)150 4268 y(Ho)m(w)m(ev)m(er,)33 b(I)e(do)f(not)h(ha)m(v)m +(e)h(the)f(resources)g(a)m(v)-5 b(ailable)30 b(to)h(carry)g(out)g(a)g +(full)d(paten)m(t)k(searc)m(h.)42 b(Therefore)150 4378 +y(I)30 b(cannot)h(giv)m(e)g(an)m(y)g(guaran)m(tee)h(of)e(the)h(ab)s(o)m +(v)m(e)g(statemen)m(t.)p eop +%%Page: 2 3 +2 2 bop 150 -116 a Fl(Chapter)30 b(1:)41 b(In)m(tro)s(duction)2591 +b(2)150 299 y Fh(1)80 b(In)l(tro)t(duction)150 555 y +Fj(bzip2)20 b Fl(compresses)h(\014les)f(using)g(the)h(Burro)m +(ws-Wheeler)g(blo)s(c)m(k-sorting)f(text)j(compression)d(algorithm,)150 +665 y(and)33 b(Hu\013man)g(co)s(ding.)50 b(Compression)32 +b(is)h(generally)g(considerably)f(b)s(etter)i(than)f(that)h(ac)m(hiev)m +(ed)h(b)m(y)150 775 y(more)f(con)m(v)m(en)m(tional)g(LZ77/LZ78-based)g +(compressors,)g(and)f(approac)m(hes)h(the)f(p)s(erformance)g(of)h(the) +150 884 y(PPM)c(family)f(of)i(statistical)f(compressors.)150 +1041 y Fj(bzip2)k Fl(is)h(built)e(on)i(top)h(of)g Fj(libbzip2)p +Fl(,)e(a)i(\015exible)e(library)f(for)i(handling)e(compressed)i(data)i +(in)d(the)150 1151 y Fj(bzip2)c Fl(format.)43 b(This)30 +b(man)m(ual)g(describ)s(es)g(b)s(oth)g(ho)m(w)i(to)g(use)f(the)g +(program)g(and)g(ho)m(w)g(to)h(w)m(ork)f(with)150 1260 +y(the)d(library)d(in)m(terface.)41 b(Most)28 b(of)g(the)g(man)m(ual)f +(is)g(dev)m(oted)i(to)f(this)f(library)-8 b(,)26 b(not)i(the)g +(program,)g(whic)m(h)150 1370 y(is)h(go)s(o)s(d)i(news)e(if)h(y)m(our)g +(in)m(terest)h(is)e(only)g(in)h(the)g(program.)150 1527 +y(Chapter)24 b(2)g(describ)s(es)f(ho)m(w)h(to)h(use)f +Fj(bzip2)p Fl(;)h(this)e(is)g(the)i(only)e(part)h(y)m(ou)h(need)f(to)h +(read)f(if)f(y)m(ou)h(just)g(w)m(an)m(t)150 1636 y(to)35 +b(kno)m(w)f(ho)m(w)g(to)g(op)s(erate)h(the)f(program.)51 +b(Chapter)34 b(3)g(describ)s(es)e(the)i(programming)f(in)m(terfaces)h +(in)150 1746 y(detail,)23 b(and)d(Chapter)h(4)h(records)f(some)h +(miscellaneous)e(notes)i(whic)m(h)e(I)h(though)m(t)h(ough)m(t)g(to)g(b) +s(e)f(recorded)150 1855 y(somewhere.)p eop +%%Page: 3 4 +3 3 bop 150 -116 a Fl(Chapter)30 b(2:)41 b(Ho)m(w)31 +b(to)g(use)f Fj(bzip2)2375 b Fl(3)150 299 y Fh(2)80 b(Ho)l(w)53 +b(to)g(use)g Fg(bzip2)150 566 y Fl(This)29 b(c)m(hapter)i(con)m(tains)f +(a)h(cop)m(y)g(of)g(the)f Fj(bzip2)f Fl(man)h(page,)h(and)f(nothing)g +(else.)390 818 y Ff(NAME)570 1004 y Fj(bzip2)p Fl(,)f +Fj(bunzip2)g Fl(-)h(a)h(blo)s(c)m(k-sorting)f(\014le)f(compressor,)i +(v1.0)570 1136 y Fj(bzcat)e Fl(-)i(decompresses)f(\014les)f(to)i +(stdout)570 1267 y Fj(bzip2recover)c Fl(-)k(reco)m(v)m(ers)h(data)f +(from)f(damaged)g(bzip2)g(\014les)390 1519 y Ff(SYNOPSIS)570 +1706 y Fj(bzip2)f Fl([)h(-cdfkqstvzVL123456789)35 b(])c([)g +(\014lenames)e(...)41 b(])570 1837 y Fj(bunzip2)28 b +Fl([)j(-fkvsVL)f(])h([)f(\014lenames)g(...)41 b(])570 +1968 y Fj(bzcat)29 b Fl([)h(-s)h(])g([)f(\014lenames)g(...)41 +b(])570 2100 y Fj(bzip2recover)27 b Fl(\014lename)390 +2352 y Ff(DESCRIPTION)390 2538 y Fj(bzip2)i Fl(compresses)i(\014les)f +(using)f(the)i(Burro)m(ws-Wheeler)g(blo)s(c)m(k)f(sorting)g(text)i +(compres-)390 2642 y(sion)40 b(algorithm,)j(and)d(Hu\013man)h(co)s +(ding.)71 b(Compression)40 b(is)g(generally)g(considerably)390 +2746 y(b)s(etter)25 b(than)g(that)h(ac)m(hiev)m(ed)g(b)m(y)f(more)g +(con)m(v)m(en)m(tional)h(LZ77/LZ78-based)g(compressors,)390 +2850 y(and)k(approac)m(hes)h(the)f(p)s(erformance)g(of)h(the)f(PPM)g +(family)f(of)i(statistical)f(compressors.)390 3001 y(The)e +(command-line)e(options)i(are)h(delib)s(erately)d(v)m(ery)i(similar)e +(to)j(those)g(of)f(GNU)h Fj(gzip)p Fl(,)390 3104 y(but)h(they)g(are)h +(not)g(iden)m(tical.)390 3255 y Fj(bzip2)f Fl(exp)s(ects)h(a)g(list)f +(of)h(\014le)f(names)h(to)h(accompan)m(y)h(the)e(command-line)e +(\015ags.)43 b(Eac)m(h)390 3359 y(\014le)e(is)h(replaced)g(b)m(y)g(a)h +(compressed)f(v)m(ersion)g(of)g(itself,)i(with)e(the)g(name)g +Fj(original_)390 3463 y(name.bz2)p Fl(.)49 b(Eac)m(h)34 +b(compressed)g(\014le)f(has)g(the)h(same)g(mo)s(di\014cation)e(date,)k +(p)s(ermissions,)390 3567 y(and,)24 b(when)f(p)s(ossible,)f(o)m +(wnership)f(as)j(the)f(corresp)s(onding)f(original,)h(so)g(that)h +(these)g(prop-)390 3671 y(erties)34 b(can)g(b)s(e)f(correctly)i +(restored)f(at)g(decompression)f(time.)51 b(File)34 b(name)g(handling)d +(is)390 3774 y(naiv)m(e)26 b(in)f(the)i(sense)f(that)h(there)f(is)f(no) +i(mec)m(hanism)e(for)h(preserving)f(original)f(\014le)i(names,)390 +3878 y(p)s(ermissions,)37 b(o)m(wnerships)f(or)h(dates)i(in)d +(\014lesystems)h(whic)m(h)g(lac)m(k)h(these)g(concepts,)j(or)390 +3982 y(ha)m(v)m(e)32 b(serious)d(\014le)g(name)i(length)f +(restrictions,)f(suc)m(h)h(as)h(MS-DOS.)390 4133 y Fj(bzip2)26 +b Fl(and)h Fj(bunzip2)e Fl(will)f(b)m(y)k(default)e(not)i(o)m(v)m +(erwrite)g(existing)e(\014les.)38 b(If)27 b(y)m(ou)h(w)m(an)m(t)g(this) +390 4237 y(to)j(happ)s(en,)e(sp)s(ecify)g(the)i Fj(-f)e +Fl(\015ag.)390 4388 y(If)34 b(no)h(\014le)f(names)g(are)i(sp)s +(eci\014ed,)e Fj(bzip2)f Fl(compresses)i(from)f(standard)g(input)f(to)j +(stan-)390 4491 y(dard)c(output.)49 b(In)32 b(this)g(case,)k +Fj(bzip2)31 b Fl(will)g(decline)h(to)i(write)e(compressed)h(output)g +(to)h(a)390 4595 y(terminal,)29 b(as)i(this)e(w)m(ould)g(b)s(e)h(en)m +(tirely)f(incomprehensible)e(and)j(therefore)h(p)s(oin)m(tless.)390 +4746 y Fj(bunzip2)36 b Fl(\(or)j Fj(bzip2)29 b(-d)p Fl(\))37 +b(decompresses)i(all)e(sp)s(eci\014ed)f(\014les.)63 b(Files)37 +b(whic)m(h)g(w)m(ere)i(not)390 4850 y(created)e(b)m(y)f +Fj(bzip2)f Fl(will)e(b)s(e)i(detected)j(and)d(ignored,)i(and)e(a)i(w)m +(arning)d(issued.)56 b Fj(bzip2)390 4954 y Fl(attempts)31 +b(to)f(guess)g(the)g(\014lename)f(for)h(the)g(decompressed)f(\014le)g +(from)h(that)g(of)g(the)g(com-)390 5058 y(pressed)f(\014le)h(as)h +(follo)m(ws:)570 5209 y Fj(filename.bz2)57 b Fl(b)s(ecomes)31 +b Fj(filename)570 5340 y(filename.bz)58 b Fl(b)s(ecomes)30 +b Fj(filename)p eop +%%Page: 4 5 +4 4 bop 150 -116 a Fl(Chapter)30 b(2:)41 b(Ho)m(w)31 +b(to)g(use)f Fj(bzip2)2375 b Fl(4)570 299 y Fj(filename.tbz2)27 +b Fl(b)s(ecomes)j Fj(filename.tar)570 470 y(filename.tbz)57 +b Fl(b)s(ecomes)31 b Fj(filename.tar)570 641 y(anyothername)57 +b Fl(b)s(ecomes)31 b Fj(anyothername.out)390 859 y Fl(If)j(the)h +(\014le)e(do)s(es)i(not)f(end)g(in)f(one)i(of)g(the)g(recognised)f +(endings,)g Fj(.bz2)p Fl(,)h Fj(.bz)p Fl(,)g Fj(.tbz2)e +Fl(or)390 963 y Fj(.tbz)p Fl(,)h Fj(bzip2)f Fl(complains)f(that)j(it)e +(cannot)i(guess)f(the)g(name)h(of)f(the)g(original)e(\014le,)j(and)390 +1067 y(uses)30 b(the)g(original)f(name)h(with)g Fj(.out)f +Fl(app)s(ended.)390 1218 y(As)j(with)f(compression,)h(supplying)c(no)k +(\014lenames)f(causes)i(decompression)e(from)h(stan-)390 +1321 y(dard)d(input)g(to)i(standard)e(output.)390 1472 +y Fj(bunzip2)k Fl(will)g(correctly)j(decompress)e(a)i(\014le)e(whic)m +(h)g(is)h(the)g(concatenation)i(of)e(t)m(w)m(o)i(or)390 +1576 y(more)j(compressed)f(\014les.)67 b(The)39 b(result)g(is)g(the)g +(concatenation)i(of)f(the)g(corresp)s(onding)390 1680 +y(uncompressed)c(\014les.)59 b(In)m(tegrit)m(y)38 b(testing)f(\()p +Fj(-t)p Fl(\))g(of)g(concatenated)i(compressed)e(\014les)f(is)390 +1784 y(also)30 b(supp)s(orted.)390 1935 y(Y)-8 b(ou)40 +b(can)g(also)f(compress)g(or)g(decompress)g(\014les)g(to)h(the)f +(standard)g(output)g(b)m(y)g(giving)390 2039 y(the)30 +b Fj(-c)g Fl(\015ag.)40 b(Multiple)28 b(\014les)h(ma)m(y)i(b)s(e)e +(compressed)h(and)f(decompressed)h(lik)m(e)f(this.)39 +b(The)390 2142 y(resulting)31 b(outputs)i(are)h(fed)f(sequen)m(tially)f +(to)i(stdout.)49 b(Compression)32 b(of)h(m)m(ultiple)e(\014les)390 +2246 y(in)24 b(this)g(manner)h(generates)h(a)g(stream)f(con)m(taining)g +(m)m(ultiple)e(compressed)i(\014le)f(represen-)390 2350 +y(tations.)58 b(Suc)m(h)36 b(a)g(stream)g(can)h(b)s(e)e(decompressed)h +(correctly)h(only)e(b)m(y)h Fj(bzip2)e Fl(v)m(ersion)390 +2454 y(0.9.0)g(or)e(later.)47 b(Earlier)30 b(v)m(ersions)i(of)g +Fj(bzip2)f Fl(will)f(stop)i(after)h(decompressing)e(the)i(\014rst)390 +2558 y(\014le)c(in)h(the)g(stream.)390 2709 y Fj(bzcat)f +Fl(\(or)i Fj(bzip2)e(-dc)p Fl(\))g(decompresses)i(all)e(sp)s(eci\014ed) +g(\014les)g(to)i(the)g(standard)e(output.)390 2860 y +Fj(bzip2)f Fl(will)g(read)i(argumen)m(ts)g(from)f(the)h(en)m(vironmen)m +(t)g(v)-5 b(ariables)28 b Fj(BZIP2)h Fl(and)g Fj(BZIP)p +Fl(,)g(in)390 2963 y(that)24 b(order,)g(and)f(will)e(pro)s(cess)i(them) +g(b)s(efore)g(an)m(y)h(argumen)m(ts)f(read)h(from)f(the)g(command)390 +3067 y(line.)39 b(This)29 b(giv)m(es)h(a)h(con)m(v)m(enien)m(t)h(w)m(a) +m(y)f(to)g(supply)d(default)i(argumen)m(ts.)390 3218 +y(Compression)h(is)h(alw)m(a)m(ys)i(p)s(erformed,)e(ev)m(en)h(if)f(the) +h(compressed)g(\014le)f(is)g(sligh)m(tly)f(larger)390 +3322 y(than)26 b(the)g(original.)38 b(Files)25 b(of)h(less)g(than)g(ab) +s(out)g(one)g(h)m(undred)e(b)m(ytes)j(tend)f(to)h(get)g(larger,)390 +3426 y(since)34 b(the)g(compression)f(mec)m(hanism)h(has)f(a)i(constan) +m(t)g(o)m(v)m(erhead)h(in)d(the)h(region)g(of)g(50)390 +3529 y(b)m(ytes.)54 b(Random)34 b(data)h(\(including)d(the)i(output)h +(of)f(most)h(\014le)f(compressors\))h(is)e(co)s(ded)390 +3633 y(at)e(ab)s(out)f(8.05)i(bits)d(p)s(er)h(b)m(yte,)h(giving)e(an)h +(expansion)g(of)g(around)g(0.5\045.)390 3784 y(As)h(a)g(self-c)m(hec)m +(k)h(for)e(y)m(our)h(protection,)g Fj(bzip2)f Fl(uses)g(32-bit)h(CR)m +(Cs)f(to)i(mak)m(e)f(sure)f(that)390 3888 y(the)45 b(decompressed)f(v)m +(ersion)g(of)g(a)h(\014le)e(is)h(iden)m(tical)f(to)i(the)g(original.)81 +b(This)43 b(guards)390 3992 y(against)i(corruption)e(of)h(the)h +(compressed)f(data,)49 b(and)44 b(against)h(undetected)g(bugs)e(in)390 +4096 y Fj(bzip2)35 b Fl(\(hop)s(efully)e(v)m(ery)k(unlik)m(ely\).)56 +b(The)36 b(c)m(hances)h(of)f(data)h(corruption)e(going)h(unde-)390 +4199 y(tected)g(is)e(microscopic,)h(ab)s(out)f(one)h(c)m(hance)g(in)f +(four)g(billion)d(for)j(eac)m(h)i(\014le)d(pro)s(cessed.)390 +4303 y(Be)38 b(a)m(w)m(are,)k(though,)d(that)f(the)g(c)m(hec)m(k)i(o)s +(ccurs)d(up)s(on)f(decompression,)j(so)f(it)f(can)h(only)390 +4407 y(tell)28 b(y)m(ou)g(that)i(something)d(is)h(wrong.)40 +b(It)28 b(can't)i(help)d(y)m(ou)i(reco)m(v)m(er)h(the)e(original)f +(uncom-)390 4511 y(pressed)h(data.)41 b(Y)-8 b(ou)30 +b(can)f(use)g Fj(bzip2recover)d Fl(to)k(try)f(to)h(reco)m(v)m(er)h +(data)f(from)e(damaged)390 4614 y(\014les.)390 4766 y(Return)22 +b(v)-5 b(alues:)37 b(0)23 b(for)g(a)g(normal)f(exit,)j(1)e(for)g(en)m +(vironmen)m(tal)f(problems)f(\(\014le)i(not)g(found,)390 +4869 y(in)m(v)-5 b(alid)30 b(\015ags,)k(I/O)f(errors,)g(&c\),)h(2)f(to) +g(indicate)f(a)h(corrupt)f(compressed)h(\014le,)f(3)i(for)e(an)390 +4973 y(in)m(ternal)d(consistency)h(error)g(\(eg,)i(bug\))e(whic)m(h)f +(caused)i Fj(bzip2)e Fl(to)i(panic.)390 5304 y Ff(OPTIONS)p +eop +%%Page: 5 6 +5 5 bop 150 -116 a Fl(Chapter)30 b(2:)41 b(Ho)m(w)31 +b(to)g(use)f Fj(bzip2)2375 b Fl(5)390 299 y Fj(-c)30 +b(--stdout)870 403 y Fl(Compress)f(or)i(decompress)f(to)h(standard)e +(output.)390 557 y Fj(-d)h(--decompress)870 661 y Fl(F)-8 +b(orce)44 b(decompression.)77 b Fj(bzip2)p Fl(,)44 b +Fj(bunzip2)d Fl(and)h Fj(bzcat)f Fl(are)i(really)f(the)870 +764 y(same)27 b(program,)h(and)e(the)i(decision)d(ab)s(out)i(what)g +(actions)g(to)h(tak)m(e)g(is)e(done)870 868 y(on)k(the)h(basis)e(of)i +(whic)m(h)e(name)h(is)g(used.)40 b(This)28 b(\015ag)j(o)m(v)m(errides)f +(that)h(mec)m(h-)870 972 y(anism,)e(and)h(forces)h(bzip2)e(to)i +(decompress.)390 1126 y Fj(-z)f(--compress)870 1230 y +Fl(The)39 b(complemen)m(t)h(to)g Fj(-d)p Fl(:)59 b(forces)40 +b(compression,)h(regardless)d(of)i(the)g(in-)870 1334 +y(v)m(ok)-5 b(ation)31 b(name.)390 1488 y Fj(-t)f(--test)8 +b Fl(Chec)m(k)33 b(in)m(tegrit)m(y)j(of)f(the)g(sp)s(eci\014ed)e +(\014le\(s\),)k(but)d(don't)h(decompress)g(them.)870 +1591 y(This)40 b(really)g(p)s(erforms)g(a)i(trial)e(decompression)h +(and)g(thro)m(ws)g(a)m(w)m(a)m(y)j(the)870 1695 y(result.)390 +1849 y Fj(-f)30 b(--force)870 1953 y Fl(F)-8 b(orce)31 +b(o)m(v)m(erwrite)f(of)g(output)f(\014les.)40 b(Normally)-8 +b(,)29 b Fj(bzip2)f Fl(will)f(not)j(o)m(v)m(erwrite)870 +2057 y(existing)e(output)g(\014les.)39 b(Also)28 b(forces)h +Fj(bzip2)e Fl(to)i(break)g(hard)e(links)f(to)k(\014les,)870 +2161 y(whic)m(h)f(it)h(otherwise)g(w)m(ouldn't)f(do.)390 +2315 y Fj(-k)h(--keep)8 b Fl(Keep)24 b(\(don't)i(delete\))h(input)d +(\014les)g(during)g(compression)h(or)h(decompression.)390 +2469 y Fj(-s)k(--small)870 2573 y Fl(Reduce)23 b(memory)f(usage,)j(for) +d(compression,)h(decompression)f(and)g(testing.)870 2676 +y(Files)f(are)i(decompressed)e(and)h(tested)h(using)e(a)h(mo)s +(di\014ed)e(algorithm)h(whic)m(h)870 2780 y(only)30 b(requires)g(2.5)j +(b)m(ytes)f(p)s(er)e(blo)s(c)m(k)h(b)m(yte.)44 b(This)30 +b(means)h(an)m(y)h(\014le)e(can)i(b)s(e)870 2884 y(decompressed)d(in)f +(2300k)j(of)e(memory)-8 b(,)30 b(alb)s(eit)e(at)i(ab)s(out)f(half)g +(the)g(normal)870 2988 y(sp)s(eed.)870 3117 y(During)42 +b(compression,)k Fj(-s)d Fl(selects)h(a)g(blo)s(c)m(k)g(size)f(of)h +(200k,)k(whic)m(h)42 b(lim-)870 3220 y(its)33 b(memory)g(use)g(to)h +(around)e(the)i(same)f(\014gure,)h(at)g(the)g(exp)s(ense)f(of)g(y)m +(our)870 3324 y(compression)g(ratio.)50 b(In)33 b(short,)i(if)d(y)m +(our)i(mac)m(hine)f(is)g(lo)m(w)g(on)h(memory)f(\(8)870 +3428 y(megab)m(ytes)42 b(or)e(less\),)j(use)d(-s)g(for)g(ev)m +(erything.)71 b(See)40 b(MEMOR)-8 b(Y)41 b(MAN-)870 3532 +y(A)m(GEMENT)31 b(b)s(elo)m(w.)390 3686 y Fj(-q)f(--quiet)870 +3790 y Fl(Suppress)j(non-essen)m(tial)j(w)m(arning)e(messages.)58 +b(Messages)38 b(p)s(ertaining)33 b(to)870 3893 y(I/O)d(errors)g(and)g +(other)h(critical)e(ev)m(en)m(ts)j(will)27 b(not)k(b)s(e)f(suppressed.) +390 4047 y Fj(-v)g(--verbose)870 4151 y Fl(V)-8 b(erb)s(ose)28 +b(mo)s(de)f({)i(sho)m(w)e(the)h(compression)f(ratio)h(for)f(eac)m(h)i +(\014le)e(pro)s(cessed.)870 4255 y(F)-8 b(urther)30 b +Fj(-v)p Fl('s)g(increase)g(the)g(v)m(erb)s(osit)m(y)g(lev)m(el,)h(sp)s +(ewing)d(out)j(lots)f(of)g(infor-)870 4359 y(mation)g(whic)m(h)f(is)h +(primarily)d(of)j(in)m(terest)h(for)f(diagnostic)g(purp)s(oses.)390 +4513 y Fj(-L)g(--license)e(-V)h(--version)870 4617 y +Fl(Displa)m(y)h(the)g(soft)m(w)m(are)i(v)m(ersion,)e(license)f(terms)i +(and)e(conditions.)390 4771 y Fj(-1)h(to)g(-9)72 b Fl(Set)35 +b(the)g(blo)s(c)m(k)f(size)h(to)g(100)h(k,)g(200)g(k)f(..)53 +b(900)36 b(k)f(when)f(compressing.)53 b(Has)870 4875 +y(no)41 b(e\013ect)h(when)d(decompressing.)71 b(See)41 +b(MEMOR)-8 b(Y)41 b(MANA)m(GEMENT)870 4978 y(b)s(elo)m(w.)390 +5132 y Fj(--)324 b Fl(T)-8 b(reats)25 b(all)e(subsequen)m(t)g(argumen)m +(ts)i(as)f(\014le)g(names,)h(ev)m(en)g(if)e(they)i(start)f(with)870 +5236 y(a)32 b(dash.)43 b(This)29 b(is)h(so)i(y)m(ou)g(can)f(handle)f +(\014les)g(with)g(names)i(b)s(eginning)c(with)870 5340 +y(a)j(dash,)f(for)g(example:)40 b Fj(bzip2)29 b(--)h(-myfilename)p +Fl(.)p eop +%%Page: 6 7 +6 6 bop 150 -116 a Fl(Chapter)30 b(2:)41 b(Ho)m(w)31 +b(to)g(use)f Fj(bzip2)2375 b Fl(6)390 299 y Fj(--repetitive-fast)390 +427 y(--repetitive-best)870 530 y Fl(These)34 b(\015ags)g(are)h +(redundan)m(t)e(in)g(v)m(ersions)g(0.9.5)j(and)e(ab)s(o)m(v)m(e.)53 +b(They)34 b(pro-)870 634 y(vided)h(some)i(coarse)g(con)m(trol)g(o)m(v)m +(er)g(the)g(b)s(eha)m(viour)e(of)h(the)g(sorting)g(algo-)870 +738 y(rithm)h(in)h(earlier)g(v)m(ersions,)j(whic)m(h)d(w)m(as)h +(sometimes)h(useful.)65 b(0.9.5)41 b(and)870 842 y(ab)s(o)m(v)m(e)34 +b(ha)m(v)m(e)g(an)f(impro)m(v)m(ed)g(algorithm)f(whic)m(h)f(renders)h +(these)h(\015ags)h(irrel-)870 946 y(ev)-5 b(an)m(t.)390 +1190 y Ff(MEMOR)-10 b(Y)40 b(MANA)m(GEMENT)390 1377 y +Fj(bzip2)25 b Fl(compresses)i(large)g(\014les)e(in)g(blo)s(c)m(ks.)39 +b(The)26 b(blo)s(c)m(k)h(size)f(a\013ects)i(b)s(oth)e(the)h(compres-) +390 1481 y(sion)39 b(ratio)g(ac)m(hiev)m(ed,)k(and)d(the)f(amoun)m(t)i +(of)e(memory)h(needed)f(for)h(compression)f(and)390 1585 +y(decompression.)59 b(The)36 b(\015ags)h Fj(-1)f Fl(through)h +Fj(-9)f Fl(sp)s(ecify)f(the)i(blo)s(c)m(k)g(size)f(to)i(b)s(e)e +(100,000)390 1688 y(b)m(ytes)29 b(through)e(900,000)k(b)m(ytes)d(\(the) +h(default\))e(resp)s(ectiv)m(ely)-8 b(.)40 b(A)m(t)29 +b(decompression)e(time,)390 1792 y(the)32 b(blo)s(c)m(k)g(size)g(used)g +(for)g(compression)f(is)g(read)h(from)g(the)g(header)g(of)h(the)f +(compressed)390 1896 y(\014le,)j(and)f Fj(bunzip2)e Fl(then)i(allo)s +(cates)h(itself)e(just)h(enough)g(memory)g(to)i(decompress)e(the)390 +2000 y(\014le.)39 b(Since)29 b(blo)s(c)m(k)g(sizes)g(are)h(stored)f(in) +f(compressed)h(\014les,)g(it)g(follo)m(ws)f(that)i(the)g(\015ags)g +Fj(-1)390 2103 y Fl(to)h Fj(-9)f Fl(are)h(irrelev)-5 +b(an)m(t)29 b(to)i(and)f(so)h(ignored)e(during)f(decompression.)390 +2255 y(Compression)h(and)g(decompression)h(requiremen)m(ts,)f(in)g(b)m +(ytes,)j(can)e(b)s(e)g(estimated)h(as:)869 2406 y Fj(Compression:)140 +b(400k)46 b(+)i(\()f(8)h(x)f(block)f(size)h(\))869 2613 +y(Decompression:)d(100k)i(+)i(\()f(4)h(x)f(block)f(size)h(\),)g(or)1585 +2717 y(100k)f(+)i(\()f(2.5)g(x)g(block)g(size)f(\))390 +2868 y Fl(Larger)29 b(blo)s(c)m(k)f(sizes)h(giv)m(e)g(rapidly)d +(diminishing)e(marginal)k(returns.)39 b(Most)29 b(of)g(the)g(com-)390 +2972 y(pression)d(comes)j(from)f(the)g(\014rst)g(t)m(w)m(o)h(or)f +(three)h(h)m(undred)d(k)i(of)g(blo)s(c)m(k)g(size,)g(a)h(fact)g(w)m +(orth)390 3075 y(b)s(earing)j(in)f(mind)g(when)h(using)f +Fj(bzip2)h Fl(on)g(small)g(mac)m(hines.)47 b(It)33 b(is)f(also)h(imp)s +(ortan)m(t)f(to)390 3179 y(appreciate)j(that)h(the)f(decompression)f +(memory)h(requiremen)m(t)f(is)h(set)g(at)h(compression)390 +3283 y(time)30 b(b)m(y)g(the)h(c)m(hoice)g(of)g(blo)s(c)m(k)f(size.)390 +3434 y(F)-8 b(or)45 b(\014les)f(compressed)g(with)g(the)g(default)g +(900k)i(blo)s(c)m(k)e(size,)49 b Fj(bunzip2)42 b Fl(will)g(require)390 +3538 y(ab)s(out)29 b(3700)j(kb)m(ytes)e(to)h(decompress.)40 +b(T)-8 b(o)30 b(supp)s(ort)e(decompression)h(of)h(an)m(y)g(\014le)f(on) +g(a)i(4)390 3642 y(megab)m(yte)h(mac)m(hine,)d Fj(bunzip2)f +Fl(has)i(an)g(option)f(to)i(decompress)e(using)g(appro)m(ximately)390 +3745 y(half)k(this)g(amoun)m(t)i(of)f(memory)-8 b(,)36 +b(ab)s(out)e(2300)i(kb)m(ytes.)53 b(Decompression)34 +b(sp)s(eed)g(is)f(also)390 3849 y(halv)m(ed,)i(so)f(y)m(ou)h(should)d +(use)h(this)g(option)h(only)f(where)h(necessary)-8 b(.)53 +b(The)33 b(relev)-5 b(an)m(t)35 b(\015ag)390 3953 y(is)29 +b Fj(-s)p Fl(.)390 4104 y(In)34 b(general,)i(try)f(and)f(use)g(the)h +(largest)h(blo)s(c)m(k)e(size)h(memory)f(constrain)m(ts)h(allo)m(w,)h +(since)390 4208 y(that)45 b(maximises)f(the)h(compression)f(ac)m(hiev)m +(ed.)85 b(Compression)43 b(and)h(decompression)390 4311 +y(sp)s(eed)30 b(are)g(virtually)e(una\013ected)j(b)m(y)f(blo)s(c)m(k)g +(size.)390 4463 y(Another)25 b(signi\014can)m(t)f(p)s(oin)m(t)g +(applies)f(to)j(\014les)e(whic)m(h)g(\014t)h(in)e(a)j(single)d(blo)s(c) +m(k)i({)g(that)h(means)390 4566 y(most)g(\014les)g(y)m(ou'd)g(encoun)m +(ter)h(using)d(a)j(large)f(blo)s(c)m(k)g(size.)39 b(The)25 +b(amoun)m(t)i(of)f(real)g(memory)390 4670 y(touc)m(hed)38 +b(is)e(prop)s(ortional)f(to)j(the)f(size)g(of)h(the)f(\014le,)h(since)f +(the)g(\014le)g(is)f(smaller)g(than)h(a)390 4774 y(blo)s(c)m(k.)49 +b(F)-8 b(or)35 b(example,)f(compressing)e(a)i(\014le)e(20,000)k(b)m +(ytes)e(long)f(with)f(the)i(\015ag)g Fj(-9)f Fl(will)390 +4878 y(cause)28 b(the)f(compressor)g(to)h(allo)s(cate)f(around)f(7600k) +j(of)e(memory)-8 b(,)28 b(but)f(only)f(touc)m(h)i(400k)390 +4981 y Fj(+)h Fl(20000)j(*)e(8)g(=)f(560)i(kb)m(ytes)f(of)g(it.)40 +b(Similarly)-8 b(,)26 b(the)k(decompressor)f(will)e(allo)s(cate)j +(3700k)390 5085 y(but)g(only)f(touc)m(h)i(100k)h Fj(+)e +Fl(20000)i(*)f(4)g(=)f(180)i(kb)m(ytes.)390 5236 y(Here)41 +b(is)f(a)i(table)f(whic)m(h)e(summarises)g(the)j(maxim)m(um)d(memory)i +(usage)h(for)e(di\013eren)m(t)390 5340 y(blo)s(c)m(k)25 +b(sizes.)38 b(Also)25 b(recorded)g(is)f(the)i(total)g(compressed)e +(size)h(for)g(14)h(\014les)e(of)i(the)f(Calgary)p eop +%%Page: 7 8 +7 7 bop 150 -116 a Fl(Chapter)30 b(2:)41 b(Ho)m(w)31 +b(to)g(use)f Fj(bzip2)2375 b Fl(7)390 299 y(T)-8 b(ext)38 +b(Compression)d(Corpus)h(totalling)h(3,141,622)k(b)m(ytes.)61 +b(This)36 b(column)g(giv)m(es)i(some)390 403 y(feel)23 +b(for)f(ho)m(w)h(compression)f(v)-5 b(aries)23 b(with)e(blo)s(c)m(k)i +(size.)38 b(These)23 b(\014gures)f(tend)g(to)i(understate)390 +506 y(the)g(adv)-5 b(an)m(tage)26 b(of)e(larger)f(blo)s(c)m(k)h(sizes)f +(for)h(larger)f(\014les,)h(since)g(the)g(Corpus)e(is)h(dominated)390 +610 y(b)m(y)30 b(smaller)f(\014les.)1107 761 y Fj(Compress)141 +b(Decompress)g(Decompress)f(Corpus)773 865 y(Flag)238 +b(usage)285 b(usage)332 b(-s)48 b(usage)237 b(Size)821 +1073 y(-1)286 b(1200k)332 b(500k)429 b(350k)285 b(914704)821 +1176 y(-2)h(2000k)332 b(900k)429 b(600k)285 b(877703)821 +1280 y(-3)h(2800k)f(1300k)428 b(850k)285 b(860338)821 +1384 y(-4)h(3600k)f(1700k)380 b(1100k)285 b(846899)821 +1488 y(-5)h(4400k)f(2100k)380 b(1350k)285 b(845160)821 +1591 y(-6)h(5200k)f(2500k)380 b(1600k)285 b(838626)821 +1695 y(-7)h(6100k)f(2900k)380 b(1850k)285 b(834096)821 +1799 y(-8)h(6800k)f(3300k)380 b(2100k)285 b(828642)821 +1903 y(-9)h(7600k)f(3700k)380 b(2350k)285 b(828642)390 +2147 y Ff(RECO)m(VERING)37 b(D)m(A)-10 b(T)g(A)40 b(FR)m(OM)h(D)m(AMA)m +(GED)e(FILES)390 2333 y Fj(bzip2)25 b Fl(compresses)h(\014les)g(in)f +(blo)s(c)m(ks,)h(usually)e(900kb)m(ytes)29 b(long.)39 +b(Eac)m(h)27 b(blo)s(c)m(k)e(is)h(handled)390 2437 y(indep)s(enden)m +(tly)-8 b(.)47 b(If)32 b(a)i(media)e(or)h(transmission)e(error)i +(causes)h(a)f(m)m(ulti-blo)s(c)m(k)f Fj(.bz2)g Fl(\014le)390 +2541 y(to)k(b)s(ecome)h(damaged,)g(it)e(ma)m(y)i(b)s(e)e(p)s(ossible)e +(to)k(reco)m(v)m(er)g(data)f(from)g(the)f(undamaged)390 +2645 y(blo)s(c)m(ks)30 b(in)f(the)h(\014le.)390 2796 +y(The)j(compressed)h(represen)m(tation)f(of)h(eac)m(h)h(blo)s(c)m(k)e +(is)g(delimited)e(b)m(y)j(a)g(48-bit)g(pattern,)390 2900 +y(whic)m(h)27 b(mak)m(es)j(it)e(p)s(ossible)e(to)j(\014nd)e(the)i(blo)s +(c)m(k)f(b)s(oundaries)e(with)i(reasonable)g(certain)m(t)m(y)-8 +b(.)390 3003 y(Eac)m(h)34 b(blo)s(c)m(k)f(also)g(carries)g(its)g(o)m +(wn)g(32-bit)g(CR)m(C,)h(so)f(damaged)h(blo)s(c)m(ks)f(can)g(b)s(e)g +(distin-)390 3107 y(guished)c(from)h(undamaged)g(ones.)390 +3258 y Fj(bzip2recover)37 b Fl(is)j(a)h(simple)e(program)h(whose)g +(purp)s(ose)f(is)h(to)i(searc)m(h)f(for)f(blo)s(c)m(ks)g(in)390 +3362 y Fj(.bz2)34 b Fl(\014les,)i(and)f(write)f(eac)m(h)j(blo)s(c)m(k)d +(out)i(in)m(to)f(its)g(o)m(wn)g Fj(.bz2)f Fl(\014le.)55 +b(Y)-8 b(ou)36 b(can)f(then)g(use)390 3466 y Fj(bzip2)29 +b(-t)c Fl(to)i(test)f(the)g(in)m(tegrit)m(y)g(of)g(the)g(resulting)e +(\014les,)i(and)f(decompress)h(those)g(whic)m(h)390 3569 +y(are)31 b(undamaged.)390 3721 y Fj(bzip2recover)41 b +Fl(tak)m(es)46 b(a)f(single)e(argumen)m(t,)49 b(the)44 +b(name)h(of)g(the)f(damaged)h(\014le,)j(and)390 3824 +y(writes)33 b(a)i(n)m(um)m(b)s(er)d(of)j(\014les)e Fj(rec0001file.bz2)p +Fl(,)e Fj(rec0002file.bz2)p Fl(,)g(etc,)36 b(con)m(taining)390 +3928 y(the)42 b(extracted)g(blo)s(c)m(ks.)74 b(The)41 +b(output)g(\014lenames)f(are)i(designed)e(so)i(that)g(the)g(use)f(of) +390 4032 y(wildcards)30 b(in)h(subsequen)m(t)h(pro)s(cessing)f({)i(for) +g(example,)g Fj(bzip2)c(-dc)g(rec*file.bz2)e(>)390 4136 +y(recovered_data)f Fl({)31 b(lists)e(the)i(\014les)e(in)g(the)i +(correct)g(order.)390 4287 y Fj(bzip2recover)38 b Fl(should)i(b)s(e)g +(of)i(most)g(use)f(dealing)f(with)g(large)i Fj(.bz2)e +Fl(\014les,)k(as)d(these)390 4390 y(will)29 b(con)m(tain)j(man)m(y)g +(blo)s(c)m(ks.)45 b(It)32 b(is)f(clearly)g(futile)f(to)i(use)g(it)f(on) +h(damaged)g(single-blo)s(c)m(k)390 4494 y(\014les,)g(since)f(a)h +(damaged)h(blo)s(c)m(k)e(cannot)i(b)s(e)e(reco)m(v)m(ered.)47 +b(If)32 b(y)m(ou)g(wish)e(to)j(minimise)c(an)m(y)390 +4598 y(p)s(oten)m(tial)36 b(data)i(loss)e(through)g(media)h(or)f +(transmission)f(errors,)j(y)m(ou)f(migh)m(t)g(consider)390 +4702 y(compressing)29 b(with)g(a)i(smaller)e(blo)s(c)m(k)h(size.)390 +4946 y Ff(PERF)m(ORMANCE)39 b(NOTES)390 5132 y Fl(The)f(sorting)f +(phase)h(of)h(compression)e(gathers)i(together)h(similar)35 +b(strings)i(in)g(the)i(\014le.)390 5236 y(Because)54 +b(of)f(this,)58 b(\014les)52 b(con)m(taining)g(v)m(ery)h(long)g(runs)e +(of)i(rep)s(eated)g(sym)m(b)s(ols,)58 b(lik)m(e)390 5340 +y Fj(")p Fl(aabaabaabaab)e(...)p Fj(")g Fl(\(rep)s(eated)g(sev)m(eral)f +(h)m(undred)e(times\))i(ma)m(y)h(compress)f(more)p eop +%%Page: 8 9 +8 8 bop 150 -116 a Fl(Chapter)30 b(2:)41 b(Ho)m(w)31 +b(to)g(use)f Fj(bzip2)2375 b Fl(8)390 299 y(slo)m(wly)33 +b(than)g(normal.)50 b(V)-8 b(ersions)33 b(0.9.5)i(and)f(ab)s(o)m(v)m(e) +h(fare)e(m)m(uc)m(h)h(b)s(etter)g(than)f(previous)390 +403 y(v)m(ersions)i(in)g(this)f(resp)s(ect.)57 b(The)35 +b(ratio)h(b)s(et)m(w)m(een)h(w)m(orst-case)g(and)e(a)m(v)m(erage-case) +40 b(com-)390 506 y(pression)e(time)h(is)f(in)g(the)h(region)g(of)h +(10:1.)69 b(F)-8 b(or)40 b(previous)e(v)m(ersions,)j(this)d(\014gure)h +(w)m(as)390 610 y(more)f(lik)m(e)g(100:1.)66 b(Y)-8 b(ou)38 +b(can)h(use)e(the)i Fj(-vvvv)d Fl(option)i(to)h(monitor)e(progress)h +(in)f(great)390 714 y(detail,)30 b(if)f(y)m(ou)i(w)m(an)m(t.)390 +865 y(Decompression)f(sp)s(eed)g(is)f(una\013ected)i(b)m(y)f(these)h +(phenomena.)390 1016 y Fj(bzip2)i Fl(usually)g(allo)s(cates)i(sev)m +(eral)f(megab)m(ytes)j(of)d(memory)h(to)g(op)s(erate)h(in,)e(and)g +(then)390 1120 y(c)m(harges)k(all)d(o)m(v)m(er)j(it)f(in)e(a)i(fairly)e +(random)h(fashion.)59 b(This)34 b(means)j(that)g(p)s(erformance,)390 +1224 y(b)s(oth)27 b(for)h(compressing)f(and)g(decompressing,)h(is)f +(largely)g(determined)g(b)m(y)h(the)g(sp)s(eed)f(at)390 +1327 y(whic)m(h)35 b(y)m(our)h(mac)m(hine)g(can)g(service)g(cac)m(he)i +(misses.)57 b(Because)37 b(of)g(this,)f(small)f(c)m(hanges)390 +1431 y(to)f(the)f(co)s(de)h(to)f(reduce)g(the)h(miss)d(rate)j(ha)m(v)m +(e)h(b)s(een)d(observ)m(ed)h(to)h(giv)m(e)g(disprop)s(ortion-)390 +1535 y(ately)i(large)f(p)s(erformance)f(impro)m(v)m(emen)m(ts.)56 +b(I)35 b(imagine)f Fj(bzip2)g Fl(will)e(p)s(erform)i(b)s(est)h(on)390 +1639 y(mac)m(hines)30 b(with)f(v)m(ery)i(large)f(cac)m(hes.)390 +1885 y Ff(CA)-14 b(VEA)k(TS)390 2072 y Fl(I/O)38 b(error)g(messages)h +(are)f(not)h(as)f(helpful)e(as)i(they)g(could)f(b)s(e.)64 +b Fj(bzip2)37 b Fl(tries)g(hard)g(to)390 2176 y(detect)29 +b(I/O)e(errors)g(and)f(exit)i(cleanly)-8 b(,)27 b(but)g(the)h(details)e +(of)h(what)h(the)f(problem)f(is)g(some-)390 2280 y(times)k(seem)h +(rather)f(misleading.)390 2431 y(This)j(man)m(ual)g(page)i(p)s(ertains) +e(to)i(v)m(ersion)f(1.0)i(of)e Fj(bzip2)p Fl(.)51 b(Compressed)34 +b(data)h(created)390 2534 y(b)m(y)25 b(this)e(v)m(ersion)i(is)e(en)m +(tirely)h(forw)m(ards)h(and)f(bac)m(kw)m(ards)h(compatible)f(with)f +(the)i(previous)390 2638 y(public)18 b(releases,)24 b(v)m(ersions)c +(0.1pl2,)k(0.9.0)e(and)f(0.9.5,)k(but)20 b(with)g(the)h(follo)m(wing)e +(exception:)390 2742 y(0.9.0)43 b(and)e(ab)s(o)m(v)m(e)h(can)g +(correctly)f(decompress)g(m)m(ultiple)e(concatenated)k(compressed)390 +2846 y(\014les.)c(0.1pl2)30 b(cannot)g(do)f(this;)f(it)h(will)e(stop)i +(after)h(decompressing)e(just)g(the)i(\014rst)e(\014le)g(in)390 +2949 y(the)j(stream.)390 3100 y Fj(bzip2recover)20 b +Fl(uses)k(32-bit)g(in)m(tegers)f(to)i(represen)m(t)f(bit)e(p)s +(ositions)g(in)g(compressed)i(\014les,)390 3204 y(so)j(it)f(cannot)i +(handle)d(compressed)i(\014les)f(more)h(than)f(512)i(megab)m(ytes)h +(long.)39 b(This)25 b(could)390 3308 y(easily)30 b(b)s(e)f(\014xed.)390 +3555 y Ff(A)m(UTHOR)390 3741 y Fl(Julian)f(Sew)m(ard,)i +Fj(jseward@acm.org)p Fl(.)390 3892 y(The)24 b(ideas)f(em)m(b)s(o)s +(died)f(in)h Fj(bzip2)f Fl(are)j(due)e(to)i(\(at)g(least\))g(the)f +(follo)m(wing)e(p)s(eople:)37 b(Mic)m(hael)390 3996 y(Burro)m(ws)48 +b(and)g(Da)m(vid)h(Wheeler)f(\(for)h(the)g(blo)s(c)m(k)f(sorting)g +(transformation\),)53 b(Da)m(vid)390 4100 y(Wheeler)45 +b(\(again,)50 b(for)45 b(the)g(Hu\013man)g(co)s(der\),)k(P)m(eter)d(F) +-8 b(en)m(wic)m(k)46 b(\(for)g(the)f(structured)390 4204 +y(co)s(ding)26 b(mo)s(del)g(in)f(the)i(original)e Fj(bzip)p +Fl(,)i(and)f(man)m(y)h(re\014nemen)m(ts\),)h(and)e(Alistair)f +(Mo\013at,)390 4307 y(Radford)34 b(Neal)h(and)f(Ian)h(Witten)g(\(for)f +(the)h(arithmetic)g(co)s(der)f(in)g(the)h(original)d +Fj(bzip)p Fl(\).)390 4411 y(I)41 b(am)g(m)m(uc)m(h)h(indebted)e(for)h +(their)f(help,)j(supp)s(ort)c(and)i(advice.)74 b(See)41 +b(the)h(man)m(ual)e(in)390 4515 y(the)28 b(source)g(distribution)23 +b(for)28 b(p)s(oin)m(ters)e(to)j(sources)e(of)h(do)s(cumen)m(tation.)40 +b(Christian)25 b(v)m(on)390 4619 y(Ro)s(ques)31 b(encouraged)h(me)g(to) +g(lo)s(ok)f(for)h(faster)g(sorting)f(algorithms,)f(so)i(as)g(to)g(sp)s +(eed)f(up)390 4723 y(compression.)47 b(Bela)34 b(Lubkin)c(encouraged)k +(me)f(to)g(impro)m(v)m(e)g(the)g(w)m(orst-case)i(compres-)390 +4826 y(sion)25 b(p)s(erformance.)38 b(Man)m(y)26 b(p)s(eople)f(sen)m(t) +h(patc)m(hes,)h(help)s(ed)d(with)g(p)s(ortabilit)m(y)f(problems,)390 +4930 y(len)m(t)30 b(mac)m(hines,)g(ga)m(v)m(e)j(advice)d(and)g(w)m(ere) +h(generally)f(helpful.)p eop +%%Page: 9 10 +9 9 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1927 b Fl(9)150 299 y Fh(3)80 b(Programming)53 +b(with)h Fg(libbzip2)150 568 y Fl(This)29 b(c)m(hapter)i(describ)s(es)d +(the)j(programming)e(in)m(terface)i(to)g Fj(libbzip2)p +Fl(.)150 725 y(F)-8 b(or)36 b(general)e(bac)m(kground)h(information,)f +(particularly)f(ab)s(out)h(memory)h(use)f(and)g(p)s(erformance)g(as-) +150 834 y(p)s(ects,)d(y)m(ou'd)f(b)s(e)g(w)m(ell)f(advised)g(to)j(read) +e(Chapter)g(2)g(as)h(w)m(ell.)150 1124 y Fk(3.1)68 b(T)-11 +b(op-lev)l(el)46 b(structure)150 1316 y Fj(libbzip2)33 +b Fl(is)i(a)h(\015exible)e(library)f(for)j(compressing)f(and)g +(decompressing)f(data)j(in)d(the)i Fj(bzip2)e Fl(data)150 +1426 y(format.)39 b(Although)24 b(pac)m(k)-5 b(aged)26 +b(as)e(a)h(single)e(en)m(tit)m(y)-8 b(,)27 b(it)d(helps)f(to)i(regard)g +(the)g(library)d(as)i(three)h(separate)150 1535 y(parts:)40 +b(the)31 b(lo)m(w)f(lev)m(el)g(in)m(terface,)h(and)f(the)h(high)e(lev)m +(el)h(in)m(terface,)h(and)f(some)h(utilit)m(y)d(functions.)150 +1692 y(The)38 b(structure)g(of)g Fj(libbzip2)p Fl('s)e(in)m(terfaces)j +(is)e(similar)f(to)j(that)g(of)g(Jean-loup)e(Gailly's)g(and)h(Mark)150 +1802 y(Adler's)29 b(excellen)m(t)i Fj(zlib)e Fl(library)-8 +b(.)150 1959 y(All)29 b(externally)g(visible)f(sym)m(b)s(ols)h(ha)m(v)m +(e)i(names)f(b)s(eginning)e Fj(BZ2_)p Fl(.)39 b(This)29 +b(is)g(new)h(in)f(v)m(ersion)h(1.0.)41 b(The)150 2068 +y(in)m(ten)m(tion)30 b(is)f(to)i(minimise)d(p)s(ollution)f(of)k(the)f +(namespaces)h(of)g(library)d(clien)m(ts.)150 2321 y Ff(3.1.1)63 +b(Lo)m(w-lev)m(el)39 b(summary)150 2514 y Fl(This)21 +b(in)m(terface)h(pro)m(vides)g(services)g(for)g(compressing)f(and)h +(decompressing)f(data)i(in)e(memory)-8 b(.)38 b(There's)150 +2623 y(no)43 b(pro)m(vision)e(for)h(dealing)g(with)f(\014les,)k +(streams)e(or)g(an)m(y)g(other)g(I/O)g(mec)m(hanisms,)i(just)e(straigh) +m(t)150 2733 y(memory-to-memory)25 b(w)m(ork.)38 b(In)23 +b(fact,)k(this)22 b(part)i(of)f(the)h(library)d(can)j(b)s(e)f(compiled) +f(without)h(inclusion)150 2843 y(of)31 b Fj(stdio.h)p +Fl(,)d(whic)m(h)h(ma)m(y)i(b)s(e)f(helpful)d(for)k(em)m(b)s(edded)e +(applications.)150 2999 y(The)h(lo)m(w-lev)m(el)g(part)g(of)h(the)f +(library)e(has)i(no)h(global)e(v)-5 b(ariables)29 b(and)h(is)g +(therefore)g(thread-safe.)150 3156 y(Six)d(routines)g(mak)m(e)j(up)d +(the)i(lo)m(w)f(lev)m(el)g(in)m(terface:)41 b Fj(BZ2_bzCompressInit)p +Fl(,)24 b Fj(BZ2_bzCompress)p Fl(,)h(and)150 3266 y Fj +(BZ2_bzCompressEnd)h Fl(for)k(compression,)f(and)h(a)h(corresp)s +(onding)d(trio)i Fj(BZ2_bzDecompressInit)p Fl(,)150 3375 +y Fj(BZ2_bzDecompress)37 b Fl(and)j Fj(BZ2_bzDecompressEnd)c +Fl(for)42 b(decompression.)72 b(The)41 b Fj(*Init)e Fl(functions)150 +3485 y(allo)s(cate)44 b(memory)g(for)f(compression/decompression)f(and) +h(do)h(other)g(initialisations,)f(whilst)f(the)150 3595 +y Fj(*End)29 b Fl(functions)g(close)i(do)m(wn)f(op)s(erations)f(and)h +(release)h(memory)-8 b(.)150 3751 y(The)36 b(real)f(w)m(ork)i(is)e +(done)h(b)m(y)g Fj(BZ2_bzCompress)c Fl(and)j Fj(BZ2_bzDecompress)p +Fl(.)54 b(These)36 b(compress)g(and)150 3861 y(decompress)30 +b(data)h(from)f(a)h(user-supplied)c(input)i(bu\013er)g(to)i(a)g +(user-supplied)c(output)j(bu\013er.)40 b(These)150 3971 +y(bu\013ers)32 b(can)i(b)s(e)e(an)m(y)i(size;)g(arbitrary)e(quan)m +(tities)h(of)g(data)h(are)g(handled)d(b)m(y)i(making)f(rep)s(eated)i +(calls)150 4080 y(to)f(these)f(functions.)44 b(This)30 +b(is)h(a)h(\015exible)e(mec)m(hanism)i(allo)m(wing)e(a)i(consumer-pull) +e(st)m(yle)i(of)g(activit)m(y)-8 b(,)150 4190 y(or)30 +b(pro)s(ducer-push,)e(or)i(a)h(mixture)e(of)i(b)s(oth.)150 +4443 y Ff(3.1.2)63 b(High-lev)m(el)41 b(summary)150 4635 +y Fl(This)d(in)m(terface)j(pro)m(vides)e(some)h(handy)f(wrapp)s(ers)f +(around)h(the)i(lo)m(w-lev)m(el)f(in)m(terface)g(to)h(facilitate)150 +4745 y(reading)26 b(and)g(writing)f Fj(bzip2)g Fl(format)i(\014les)f +(\()p Fj(.bz2)g Fl(\014les\).)38 b(The)27 b(routines)e(pro)m(vide)h(ho) +s(oks)h(to)g(facilitate)150 4854 y(reading)43 b(\014les)f(in)h(whic)m +(h)f(the)i Fj(bzip2)f Fl(data)h(stream)g(is)f(em)m(b)s(edded)f(within)g +(some)i(larger-scale)g(\014le)150 4964 y(structure,)30 +b(or)h(where)e(there)i(are)g(m)m(ultiple)d Fj(bzip2)h +Fl(data)i(streams)f(concatenated)j(end-to-end.)150 5121 +y(F)-8 b(or)31 b(reading)f(\014les,)f Fj(BZ2_bzReadOpen)p +Fl(,)e Fj(BZ2_bzRead)p Fl(,)h Fj(BZ2_bzReadClose)e Fl(and)150 +5230 y Fj(BZ2_bzReadGetUnused)19 b Fl(are)25 b(supplied.)36 +b(F)-8 b(or)25 b(writing)d(\014les,)j Fj(BZ2_bzWriteOpen)p +Fl(,)d Fj(BZ2_bzWrite)g Fl(and)150 5340 y Fj(BZ2_bzWriteFinish)k +Fl(are)k(a)m(v)-5 b(ailable.)p eop +%%Page: 10 11 +10 10 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(10)150 299 y(As)24 b(with)f(the)h(lo)m +(w-lev)m(el)h(library)-8 b(,)23 b(no)h(global)g(v)-5 +b(ariables)23 b(are)h(used)g(so)g(the)h(library)c(is)j(p)s(er)f(se)h +(thread-safe.)150 408 y(Ho)m(w)m(ev)m(er,)32 b(if)c(I/O)h(errors)g(o)s +(ccur)g(whilst)e(reading)i(or)g(writing)e(the)j(underlying)c +(compressed)j(\014les,)g(y)m(ou)150 518 y(ma)m(y)j(ha)m(v)m(e)g(to)g +(consult)e Fj(errno)g Fl(to)h(determine)g(the)g(cause)g(of)h(the)f +(error.)42 b(In)30 b(that)i(case,)h(y)m(ou'd)e(need)g(a)150 +628 y(C)f(library)e(whic)m(h)h(correctly)i(supp)s(orts)d +Fj(errno)h Fl(in)g(a)i(m)m(ultithreaded)e(en)m(vironmen)m(t.)150 +784 y(T)-8 b(o)56 b(mak)m(e)g(the)g(library)d(a)j(little)e(simpler)f +(and)i(more)h(p)s(ortable,)61 b Fj(BZ2_bzReadOpen)51 +b Fl(and)k Fj(BZ2_)150 894 y(bzWriteOpen)34 b Fl(require)j(y)m(ou)g(to) +i(pass)e(them)g(\014le)g(handles)f(\()p Fj(FILE*)p Fl(s\))g(whic)m(h)h +(ha)m(v)m(e)h(previously)e(b)s(een)150 1004 y(op)s(ened)41 +b(for)g(reading)f(or)h(writing)f(resp)s(ectiv)m(ely)-8 +b(.)73 b(That)41 b(a)m(v)m(oids)h(p)s(ortabilit)m(y)d(problems)g(asso)s +(ciated)150 1113 y(with)j(\014le)h(op)s(erations)g(and)g(\014le)g +(attributes,)j(whilst)c(not)i(b)s(eing)e(m)m(uc)m(h)h(of)h(an)g(imp)s +(osition)c(on)k(the)150 1223 y(programmer.)150 1474 y +Ff(3.1.3)63 b(Utilit)m(y)40 b(functions)h(summary)150 +1666 y Fl(F)-8 b(or)45 b(v)m(ery)g(simple)d(needs,)48 +b Fj(BZ2_bzBuffToBuffCompres)o(s)38 b Fl(and)44 b Fj +(BZ2_bzBuffToBuffDecompres)o(s)150 1776 y Fl(are)29 b(pro)m(vided.)38 +b(These)28 b(compress)g(data)h(in)e(memory)h(from)g(one)h(bu\013er)e +(to)i(another)f(bu\013er)g(in)f(a)h(single)150 1885 y(function)38 +b(call.)67 b(Y)-8 b(ou)40 b(should)d(assess)j(whether)f(these)h +(functions)d(ful\014ll)f(y)m(our)k(memory-to-memory)150 +1995 y(compression/decompression)26 b(requiremen)m(ts)h(b)s(efore)g(in) +m(v)m(esting)g(e\013ort)i(in)d(understanding)f(the)j(more)150 +2105 y(general)i(but)g(more)h(complex)f(lo)m(w-lev)m(el)g(in)m +(terface.)150 2261 y(Y)-8 b(oshiok)j(a)47 b(Tsuneo)e(\()p +Fj(QWF00133@niftyserve.or.jp)40 b Fl(/)46 b Fj +(tsuneo-y@is.aist-nara.ac.)o(jp)p Fl(\))40 b(has)150 +2371 y(con)m(tributed)f(some)h(functions)e(to)j(giv)m(e)f(b)s(etter)g +Fj(zlib)f Fl(compatibilit)m(y)-8 b(.)67 b(These)40 b(functions)e(are)i +Fj(BZ2_)150 2481 y(bzopen)p Fl(,)e Fj(BZ2_bzread)p Fl(,)f +Fj(BZ2_bzwrite)p Fl(,)g Fj(BZ2_bzflush)p Fl(,)g Fj(BZ2_bzclose)p +Fl(,)f Fj(BZ2_bzerror)f Fl(and)i Fj(BZ2_)150 2590 y(bzlibVersion)p +Fl(.)49 b(Y)-8 b(ou)35 b(ma)m(y)g(\014nd)e(these)i(functions)d(more)j +(con)m(v)m(enien)m(t)g(for)f(simple)f(\014le)g(reading)h(and)150 +2700 y(writing,)c(than)h(those)h(in)e(the)i(high-lev)m(el)e(in)m +(terface.)45 b(These)31 b(functions)f(are)i(not)g(\(y)m(et\))h +(o\016cially)d(part)150 2809 y(of)k(the)g(library)-8 +b(,)33 b(and)g(are)h(minimally)c(do)s(cumen)m(ted)k(here.)51 +b(If)33 b(they)h(break,)h(y)m(ou)f(get)h(to)g(k)m(eep)f(all)f(the)150 +2919 y(pieces.)40 b(I)31 b(hop)s(e)e(to)i(do)s(cumen)m(t)g(them)f(prop) +s(erly)e(when)h(time)i(p)s(ermits.)150 3076 y(Y)-8 b(oshiok)j(a)27 +b(also)g(con)m(tributed)f(mo)s(di\014cations)f(to)i(allo)m(w)f(the)h +(library)e(to)i(b)s(e)f(built)f(as)i(a)g(Windo)m(ws)f(DLL.)150 +3362 y Fk(3.2)68 b(Error)45 b(handling)150 3554 y Fl(The)23 +b(library)f(is)h(designed)g(to)i(reco)m(v)m(er)g(cleanly)f(in)e(all)h +(situations,)h(including)d(the)j(w)m(orst-case)i(situation)150 +3664 y(of)j(decompressing)e(random)g(data.)41 b(I'm)28 +b(not)h(100\045)g(sure)f(that)h(it)f(can)h(alw)m(a)m(ys)g(do)f(this,)g +(so)g(y)m(ou)h(migh)m(t)150 3774 y(w)m(an)m(t)i(to)g(add)e(a)i(signal)d +(handler)g(to)j(catc)m(h)h(segmen)m(tation)f(violations)e(during)f +(decompression)h(if)g(y)m(ou)150 3883 y(are)g(feeling)f(esp)s(ecially)f +(paranoid.)39 b(I)28 b(w)m(ould)g(b)s(e)g(in)m(terested)h(in)e(hearing) +h(more)h(ab)s(out)f(the)h(robustness)150 3993 y(of)i(the)f(library)e +(to)j(corrupted)f(compressed)g(data.)150 4150 y(V)-8 +b(ersion)39 b(1.0)h(is)f(m)m(uc)m(h)g(more)h(robust)e(in)g(this)g(resp) +s(ect)i(than)f(0.9.0)i(or)e(0.9.5.)70 b(In)m(v)m(estigations)39 +b(with)150 4259 y(Chec)m(k)m(er)21 b(\(a)g(to)s(ol)g(for)f(detecting)h +(problems)d(with)h(memory)h(managemen)m(t,)k(similar)18 +b(to)j(Purify\))e(indicate)150 4369 y(that,)40 b(at)e(least)f(for)g +(the)h(few)e(\014les)h(I)g(tested,)j(all)c(single-bit)f(errors)i(in)e +(the)j(decompressed)f(data)h(are)150 4478 y(caugh)m(t)c(prop)s(erly)-8 +b(,)31 b(with)g(no)i(segmen)m(tation)h(faults,)e(no)g(reads)h(of)g +(uninitialised)27 b(data)34 b(and)e(no)g(out)h(of)150 +4588 y(range)f(reads)g(or)f(writes.)44 b(So)32 b(it's)f(certainly)g(m)m +(uc)m(h)h(impro)m(v)m(ed,)g(although)f(I)g(w)m(ouldn't)g(claim)g(it)g +(to)i(b)s(e)150 4698 y(totally)d(b)s(om)m(bpro)s(of.)150 +4854 y(The)25 b(\014le)g Fj(bzlib.h)f Fl(con)m(tains)i(all)f +(de\014nitions)e(needed)i(to)i(use)e(the)h(library)-8 +b(.)37 b(In)26 b(particular,)f(y)m(ou)h(should)150 4964 +y(de\014nitely)i(not)j(include)d Fj(bzlib_private.h)p +Fl(.)150 5121 y(In)39 b Fj(bzlib.h)p Fl(,)h(the)g(v)-5 +b(arious)39 b(return)f(v)-5 b(alues)39 b(are)h(de\014ned.)68 +b(The)39 b(follo)m(wing)f(list)h(is)f(not)i(in)m(tended)f(as)150 +5230 y(an)c(exhaustiv)m(e)h(description)d(of)i(the)h(circumstances)f +(in)f(whic)m(h)g(a)i(giv)m(en)f(v)-5 b(alue)35 b(ma)m(y)h(b)s(e)e +(returned)h({)150 5340 y(those)h(descriptions)d(are)j(giv)m(en)f +(later.)56 b(Rather,)37 b(it)d(is)h(in)m(tended)f(to)i(con)m(v)m(ey)h +(the)e(rough)g(meaning)g(of)p eop +%%Page: 11 12 +11 11 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(11)150 299 y(eac)m(h)38 +b(return)d(v)-5 b(alue.)59 b(The)36 b(\014rst)g(\014v)m(e)g(actions)h +(are)g(normal)f(and)f(not)i(in)m(tended)f(to)h(denote)g(an)f(error)150 +408 y(situation.)150 592 y Fj(BZ_OK)180 b Fl(The)30 b(requested)g +(action)h(w)m(as)g(completed)f(successfully)-8 b(.)150 +756 y Fj(BZ_RUN_OK)150 866 y(BZ_FLUSH_OK)150 975 y(BZ_FINISH_OK)630 +1085 y Fl(In)24 b Fj(BZ2_bzCompress)p Fl(,)e(the)i(requested)g +(\015ush/\014nish/nothing-sp)s(ecial)c(action)k(w)m(as)h(com-)630 +1194 y(pleted)30 b(successfully)-8 b(.)150 1358 y Fj(BZ_STREAM_END)630 +1468 y Fl(Compression)38 b(of)j(data)f(w)m(as)h(completed,)h(or)f(the)f +(logical)f(stream)i(end)e(w)m(as)i(detected)630 1577 +y(during)28 b(decompression.)150 1761 y(The)i(follo)m(wing)f(return)g +(v)-5 b(alues)30 b(indicate)f(an)h(error)g(of)h(some)g(kind.)150 +1945 y Fj(BZ_CONFIG_ERROR)630 2055 y Fl(Indicates)48 +b(that)h(the)g(library)e(has)h(b)s(een)g(improp)s(erly)d(compiled)j(on) +g(y)m(our)h(platform)630 2164 y({)j(a)g(ma)5 b(jor)51 +b(con\014guration)g(error.)104 b(Sp)s(eci\014cally)-8 +b(,)55 b(it)c(means)g(that)h Fj(sizeof\(char\))p Fl(,)630 +2274 y Fj(sizeof\(short\))44 b Fl(and)i Fj(sizeof\(int\))f +Fl(are)j(not)f(1,)52 b(2)c(and)f(4)h(resp)s(ectiv)m(ely)-8 +b(,)51 b(as)d(they)630 2384 y(should)27 b(b)s(e.)40 b(Note)30 +b(that)g(the)f(library)e(should)g(still)g(w)m(ork)i(prop)s(erly)e(on)i +(64-bit)g(platforms)630 2493 y(whic)m(h)d(follo)m(w)h(the)g(LP64)h +(programming)e(mo)s(del)h({)g(that)h(is,)g(where)e Fj(sizeof\(long\))f +Fl(and)630 2603 y Fj(sizeof\(void*\))e Fl(are)k(8.)40 +b(Under)25 b(LP64,)j Fj(sizeof\(int\))c Fl(is)h(still)f(4,)k(so)f +Fj(libbzip2)p Fl(,)e(whic)m(h)630 2712 y(do)s(esn't)30 +b(use)g(the)h Fj(long)e Fl(t)m(yp)s(e,)i(is)e(OK.)150 +2876 y Fj(BZ_SEQUENCE_ERROR)630 2986 y Fl(When)43 b(using)f(the)i +(library)-8 b(,)45 b(it)e(is)f(imp)s(ortan)m(t)h(to)h(call)e(the)i +(functions)e(in)g(the)i(correct)630 3095 y(sequence)28 +b(and)f(with)f(data)j(structures)e(\(bu\013ers)f(etc\))j(in)e(the)g +(correct)i(states.)41 b Fj(libbzip2)630 3205 y Fl(c)m(hec)m(ks)26 +b(as)e(m)m(uc)m(h)h(as)f(it)g(can)g(to)h(ensure)f(this)f(is)g(happ)s +(ening,)h(and)f(returns)g Fj(BZ_SEQUENCE_)630 3314 y(ERROR)36 +b Fl(if)h(not.)62 b(Co)s(de)37 b(whic)m(h)g(complies)f(precisely)g +(with)h(the)g(function)g(seman)m(tics,)j(as)630 3424 +y(detailed)d(b)s(elo)m(w,)i(should)d(nev)m(er)i(receiv)m(e)h(this)d(v) +-5 b(alue;)41 b(suc)m(h)d(an)g(ev)m(en)m(t)h(denotes)f(buggy)630 +3534 y(co)s(de)31 b(whic)m(h)e(y)m(ou)h(should)f(in)m(v)m(estigate.)150 +3697 y Fj(BZ_PARAM_ERROR)630 3807 y Fl(Returned)43 b(when)f(a)i +(parameter)g(to)h(a)f(function)e(call)h(is)f(out)i(of)g(range)g(or)g +(otherwise)630 3917 y(manifestly)34 b(incorrect.)57 b(As)36 +b(with)e Fj(BZ_SEQUENCE_ERROR)p Fl(,)f(this)i(denotes)h(a)g(bug)f(in)g +(the)630 4026 y(clien)m(t)23 b(co)s(de.)39 b(The)22 b(distinction)f(b)s +(et)m(w)m(een)j Fj(BZ_PARAM_ERROR)c Fl(and)j Fj(BZ_SEQUENCE_ERROR)630 +4136 y Fl(is)29 b(a)i(bit)f(hazy)-8 b(,)31 b(but)f(still)e(w)m(orth)i +(making.)150 4300 y Fj(BZ_MEM_ERROR)630 4409 y Fl(Returned)g(when)f(a)i +(request)f(to)i(allo)s(cate)f(memory)f(failed.)40 b(Note)31 +b(that)g(the)g(quan)m(tit)m(y)g(of)630 4519 y(memory)21 +b(needed)g(to)i(decompress)e(a)g(stream)h(cannot)g(b)s(e)f(determined)f +(un)m(til)g(the)h(stream's)630 4628 y(header)29 b(has)g(b)s(een)g +(read.)40 b(So)29 b Fj(BZ2_bzDecompress)c Fl(and)j Fj(BZ2_bzRead)f +Fl(ma)m(y)j(return)e Fj(BZ_)630 4738 y(MEM_ERROR)d Fl(ev)m(en)k(though) +e(some)h(of)g(the)g(compressed)g(data)g(has)g(b)s(een)f(read.)39 +b(The)28 b(same)630 4847 y(is)38 b(not)i(true)f(for)g(compression;)k +(once)d Fj(BZ2_bzCompressInit)34 b Fl(or)39 b Fj(BZ2_bzWriteOpen)630 +4957 y Fl(ha)m(v)m(e)32 b(successfully)c(completed,)j +Fj(BZ_MEM_ERROR)c Fl(cannot)k(o)s(ccur.)150 5121 y Fj(BZ_DATA_ERROR)630 +5230 y Fl(Returned)h(when)g(a)h(data)g(in)m(tegrit)m(y)g(error)g(is)e +(detected)k(during)30 b(decompression.)47 b(Most)630 +5340 y(imp)s(ortan)m(tly)-8 b(,)31 b(this)f(means)i(when)f(stored)g +(and)g(computed)h(CR)m(Cs)f(for)g(the)h(data)g(do)g(not)p +eop +%%Page: 12 13 +12 12 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(12)630 299 y(matc)m(h.)41 +b(This)28 b(v)-5 b(alue)29 b(is)f(also)i(returned)e(up)s(on)g +(detection)i(of)g(an)m(y)g(other)f(anomaly)h(in)e(the)630 +408 y(compressed)i(data.)150 560 y Fj(BZ_DATA_ERROR_MAGIC)630 +670 y Fl(As)k(a)g(sp)s(ecial)f(case)i(of)f Fj(BZ_DATA_ERROR)p +Fl(,)d(it)i(is)g(sometimes)h(useful)e(to)j(kno)m(w)f(when)f(the)630 +779 y(compressed)d(stream)h(do)s(es)f(not)g(start)h(with)e(the)i +(correct)h(magic)e(b)m(ytes)h(\()p Fj('B')f('Z')f('h')p +Fl(\).)150 931 y Fj(BZ_IO_ERROR)630 1040 y Fl(Returned)k(b)m(y)h +Fj(BZ2_bzRead)d Fl(and)i Fj(BZ2_bzWrite)e Fl(when)i(there)h(is)f(an)g +(error)h(reading)f(or)630 1150 y(writing)28 b(in)h(the)h(compressed)g +(\014le,)f(and)h(b)m(y)g Fj(BZ2_bzReadOpen)c Fl(and)j +Fj(BZ2_bzWriteOpen)630 1259 y Fl(for)i(attempts)i(to)f(use)f(a)h +(\014le)e(for)i(whic)m(h)e(the)h(error)g(indicator)g(\(viz,)g +Fj(ferror\(f\))p Fl(\))f(is)g(set.)630 1369 y(On)h(receipt)g(of)h +Fj(BZ_IO_ERROR)p Fl(,)e(the)h(caller)h(should)d(consult)i +Fj(errno)g Fl(and/or)g Fj(perror)f Fl(to)630 1479 y(acquire)g(op)s +(erating-system)g(sp)s(eci\014c)f(information)g(ab)s(out)h(the)h +(problem.)150 1630 y Fj(BZ_UNEXPECTED_EOF)630 1740 y +Fl(Returned)36 b(b)m(y)g Fj(BZ2_bzRead)e Fl(when)i(the)h(compressed)f +(\014le)g(\014nishes)e(b)s(efore)j(the)f(logical)630 +1849 y(end)30 b(of)g(stream)h(is)e(detected.)150 2001 +y Fj(BZ_OUTBUFF_FULL)630 2110 y Fl(Returned)g(b)m(y)i +Fj(BZ2_bzBuffToBuffCompres)o(s)24 b Fl(and)30 b Fj +(BZ2_bzBuffToBuffDecompres)o(s)630 2220 y Fl(to)h(indicate)f(that)h +(the)f(output)g(data)h(will)d(not)i(\014t)h(in)m(to)f(the)h(output)f +(bu\013er)f(pro)m(vided.)150 2492 y Fk(3.3)68 b(Lo)l(w-lev)l(el)47 +b(in)l(terface)150 2766 y Ff(3.3.1)63 b Fe(BZ2_bzCompressInit)390 +2953 y Fj(typedef)533 3057 y(struct)46 b({)676 3161 y(char)h(*next_in;) +676 3264 y(unsigned)f(int)h(avail_in;)676 3368 y(unsigned)f(int)h +(total_in_lo32;)676 3472 y(unsigned)f(int)h(total_in_hi32;)676 +3680 y(char)g(*next_out;)676 3783 y(unsigned)f(int)h(avail_out;)676 +3887 y(unsigned)f(int)h(total_out_lo32;)676 3991 y(unsigned)f(int)h +(total_out_hi32;)676 4198 y(void)g(*state;)676 4406 y(void)g +(*\(*bzalloc\)\(void)c(*,int,int\);)676 4510 y(void)k +(\(*bzfree\)\(void)d(*,void)i(*\);)676 4614 y(void)h(*opaque;)533 +4717 y(})533 4821 y(bz_stream;)390 5029 y(int)g(BZ2_bzCompressInit)c +(\()k(bz_stream)e(*strm,)1583 5132 y(int)i(blockSize100k,)1583 +5236 y(int)g(verbosity,)1583 5340 y(int)g(workFactor)e(\);)p +eop +%%Page: 13 14 +13 13 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(13)150 456 y(Prepares)32 +b(for)h(compression.)47 b(The)32 b Fj(bz_stream)e Fl(structure)j(holds) +e(all)h(data)h(p)s(ertaining)e(to)i(the)g(com-)150 565 +y(pression)i(activit)m(y)-8 b(.)62 b(A)37 b Fj(bz_stream)e +Fl(structure)h(should)f(b)s(e)i(allo)s(cated)g(and)f(initialised)e +(prior)h(to)j(the)150 675 y(call.)67 b(The)39 b(\014elds)e(of)j +Fj(bz_stream)d Fl(comprise)h(the)i(en)m(tiret)m(y)g(of)f(the)h +(user-visible)c(data.)68 b Fj(state)38 b Fl(is)h(a)150 +784 y(p)s(oin)m(ter)29 b(to)i(the)g(priv)-5 b(ate)30 +b(data)h(structures)f(required)e(for)i(compression.)150 +941 y(Custom)37 b(memory)g(allo)s(cators)g(are)h(supp)s(orted,)f(via)g +(\014elds)f Fj(bzalloc)p Fl(,)h Fj(bzfree)p Fl(,)g(and)g +Fj(opaque)p Fl(.)59 b(The)150 1051 y(v)-5 b(alue)32 b +Fj(opaque)e Fl(is)i(passed)f(to)i(as)g(the)f(\014rst)g(argumen)m(t)h +(to)g(all)e(calls)g(to)i Fj(bzalloc)d Fl(and)i Fj(bzfree)p +Fl(,)f(but)h(is)150 1160 y(otherwise)d(ignored)g(b)m(y)h(the)g(library) +-8 b(.)38 b(The)29 b(call)h Fj(bzalloc)e(\()i(opaque,)e(n,)i(m)g(\))g +Fl(is)e(exp)s(ected)j(to)f(return)150 1270 y(a)g(p)s(oin)m(ter)e +Fj(p)h Fl(to)h Fj(n)g(*)g(m)f Fl(b)m(ytes)h(of)g(memory)-8 +b(,)30 b(and)e Fj(bzfree)h(\()h(opaque,)f(p)h(\))f Fl(should)e(free)i +(that)h(memory)-8 b(.)150 1427 y(If)33 b(y)m(ou)g(don't)h(w)m(an)m(t)g +(to)g(use)f(a)g(custom)h(memory)f(allo)s(cator,)h(set)g +Fj(bzalloc)p Fl(,)e Fj(bzfree)g Fl(and)h Fj(opaque)e +Fl(to)150 1537 y Fj(NULL)p Fl(,)e(and)h(the)h(library)d(will)f(then)k +(use)f(the)g(standard)g Fj(malloc)p Fl(/)p Fj(free)e +Fl(routines.)150 1693 y(Before)39 b(calling)d Fj(BZ2_bzCompressInit)p +Fl(,)f(\014elds)h Fj(bzalloc)p Fl(,)h Fj(bzfree)f Fl(and)h +Fj(opaque)f Fl(should)g(b)s(e)h(\014lled)150 1803 y(appropriately)-8 +b(,)35 b(as)h(just)f(describ)s(ed.)53 b(Up)s(on)34 b(return,)i(the)g +(in)m(ternal)e(state)i(will)d(ha)m(v)m(e)j(b)s(een)f(allo)s(cated)150 +1913 y(and)43 b(initialised,)g(and)g Fj(total_in_lo32)p +Fl(,)h Fj(total_in_hi32)p Fl(,)f Fj(total_out_lo32)d +Fl(and)j Fj(total_out_)150 2022 y(hi32)37 b Fl(will)f(ha)m(v)m(e)j(b)s +(een)f(set)h(to)g(zero.)65 b(These)38 b(four)g(\014elds)e(are)j(used)f +(b)m(y)g(the)g(library)e(to)j(inform)e(the)150 2132 y(caller)j(of)g +(the)h(total)g(amoun)m(t)g(of)g(data)g(passed)f(in)m(to)g(and)g(out)g +(of)h(the)g(library)-8 b(,)41 b(resp)s(ectiv)m(ely)-8 +b(.)70 b(Y)-8 b(ou)150 2241 y(should)34 b(not)j(try)f(to)h(c)m(hange)g +(them.)58 b(As)36 b(of)h(v)m(ersion)f(1.0,)j(64-bit)d(coun)m(ts)h(are)f +(main)m(tained,)h(ev)m(en)g(on)150 2351 y(32-bit)i(platforms,)h(using)d +(the)i Fj(_hi32)e Fl(\014elds)g(to)j(store)f(the)g(upp)s(er)d(32)k +(bits)d(of)i(the)g(coun)m(t.)66 b(So,)41 b(for)150 2460 +y(example,)30 b(the)h(total)g(amoun)m(t)g(of)f(data)h(in)f(is)f +Fj(\(total_in_hi32)d(<<)k(32\))g(+)g(total_in_lo32)p +Fl(.)150 2617 y(P)m(arameter)g Fj(blockSize100k)25 b +Fl(sp)s(eci\014es)i(the)h(blo)s(c)m(k)g(size)h(to)g(b)s(e)f(used)f(for) +h(compression.)40 b(It)28 b(should)f(b)s(e)150 2727 y(a)k(v)-5 +b(alue)30 b(b)s(et)m(w)m(een)i(1)f(and)f(9)h(inclusiv)m(e,)e(and)h(the) +h(actual)g(blo)s(c)m(k)f(size)g(used)g(is)g(100000)j(x)e(this)e +(\014gure.)42 b(9)150 2836 y(giv)m(es)31 b(the)f(b)s(est)g(compression) +g(but)f(tak)m(es)j(most)f(memory)-8 b(.)150 2993 y(P)m(arameter)29 +b Fj(verbosity)c Fl(should)h(b)s(e)h(set)i(to)f(a)h(n)m(um)m(b)s(er)d +(b)s(et)m(w)m(een)j(0)f(and)f(4)h(inclusiv)m(e.)38 b(0)28 +b(is)f(silen)m(t,)h(and)150 3103 y(greater)j(n)m(um)m(b)s(ers)c(giv)m +(e)j(increasingly)d(v)m(erb)s(ose)j(monitoring/debugging)d(output.)40 +b(If)29 b(the)g(library)e(has)150 3212 y(b)s(een)j(compiled)e(with)i +Fj(-DBZ_NO_STDIO)p Fl(,)d(no)j(suc)m(h)g(output)g(will)e(app)s(ear)h +(for)h(an)m(y)h(v)m(erb)s(osit)m(y)f(setting.)150 3369 +y(P)m(arameter)35 b Fj(workFactor)d Fl(con)m(trols)i(ho)m(w)g(the)g +(compression)f(phase)h(b)s(eha)m(v)m(es)g(when)f(presen)m(ted)h(with) +150 3479 y(w)m(orst)40 b(case,)j(highly)37 b(rep)s(etitiv)m(e,)k(input) +d(data.)68 b(If)39 b(compression)g(runs)e(in)m(to)j(di\016culties)d +(caused)i(b)m(y)150 3588 y(rep)s(etitiv)m(e)34 b(data,)j(the)e(library) +d(switc)m(hes)j(from)f(the)h(standard)f(sorting)g(algorithm)g(to)i(a)f +(fallbac)m(k)f(al-)150 3698 y(gorithm.)47 b(The)32 b(fallbac)m(k)g(is)g +(slo)m(w)m(er)g(than)h(the)f(standard)g(algorithm)g(b)m(y)g(p)s(erhaps) +f(a)i(factor)h(of)e(three,)150 3808 y(but)e(alw)m(a)m(ys)h(b)s(eha)m(v) +m(es)f(reasonably)-8 b(,)31 b(no)f(matter)h(ho)m(w)g(bad)f(the)g +(input.)150 3965 y(Lo)m(w)m(er)25 b(v)-5 b(alues)24 b(of)h +Fj(workFactor)d Fl(reduce)i(the)h(amoun)m(t)g(of)g(e\013ort)g(the)g +(standard)f(algorithm)f(will)f(exp)s(end)150 4074 y(b)s(efore)j +(resorting)h(to)g(the)g(fallbac)m(k.)39 b(Y)-8 b(ou)27 +b(should)c(set)k(this)e(parameter)h(carefully;)g(to)s(o)h(lo)m(w,)g +(and)e(man)m(y)150 4184 y(inputs)32 b(will)f(b)s(e)i(handled)f(b)m(y)i +(the)g(fallbac)m(k)g(algorithm)f(and)g(so)h(compress)g(rather)g(slo)m +(wly)-8 b(,)34 b(to)s(o)h(high,)150 4293 y(and)24 b(y)m(our)h(a)m(v)m +(erage-to-w)m(orst)30 b(case)c(compression)e(times)h(can)g(b)s(ecome)g +(v)m(ery)h(large.)39 b(The)24 b(default)g(v)-5 b(alue)150 +4403 y(of)31 b(30)g(giv)m(es)f(reasonable)h(b)s(eha)m(viour)e(o)m(v)m +(er)i(a)g(wide)e(range)i(of)f(circumstances.)150 4560 +y(Allo)m(w)m(able)h(v)-5 b(alues)31 b(range)i(from)e(0)i(to)f(250)h +(inclusiv)m(e.)44 b(0)32 b(is)f(a)h(sp)s(ecial)f(case,)i(equiv)-5 +b(alen)m(t)32 b(to)g(using)f(the)150 4669 y(default)f(v)-5 +b(alue)29 b(of)i(30.)150 4826 y(Note)38 b(that)f(the)g(compressed)f +(output)g(generated)h(is)f(the)g(same)h(regardless)f(of)h(whether)f(or) +g(not)h(the)150 4936 y(fallbac)m(k)30 b(algorithm)f(is)h(used.)150 +5093 y(Be)23 b(a)m(w)m(are)h(also)f(that)g(this)f(parameter)h(ma)m(y)g +(disapp)s(ear)e(en)m(tirely)h(in)f(future)h(v)m(ersions)g(of)h(the)g +(library)-8 b(.)36 b(In)150 5202 y(principle)20 b(it)j(should)e(b)s(e)h +(p)s(ossible)f(to)j(devise)f(a)g(go)s(o)s(d)g(w)m(a)m(y)i(to)f +(automatically)f(c)m(ho)s(ose)h(whic)m(h)e(algorithm)150 +5312 y(to)31 b(use.)41 b(Suc)m(h)29 b(a)i(mec)m(hanism)f(w)m(ould)f +(render)g(the)i(parameter)g(obsolete.)p eop +%%Page: 14 15 +14 14 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(14)150 299 y(P)m(ossible)29 +b(return)h(v)-5 b(alues:)572 450 y Fj(BZ_CONFIG_ERROR)663 +554 y Fl(if)29 b(the)i(library)d(has)i(b)s(een)f(mis-compiled)572 +657 y Fj(BZ_PARAM_ERROR)663 761 y Fl(if)g Fj(strm)g Fl(is)h +Fj(NULL)663 865 y Fl(or)g Fj(blockSize)e(<)i Fl(1)h(or)f +Fj(blockSize)e(>)i Fl(9)663 969 y(or)g Fj(verbosity)e(<)i +Fl(0)h(or)f Fj(verbosity)e(>)i Fl(4)663 1073 y(or)g Fj(workFactor)e(<)i +Fl(0)g(or)h Fj(workFactor)c(>)j Fl(250)572 1176 y Fj(BZ_MEM_ERROR)663 +1280 y Fl(if)f(not)i(enough)f(memory)g(is)f(a)m(v)-5 +b(ailable)572 1384 y Fj(BZ_OK)663 1488 y Fl(otherwise)150 +1645 y(Allo)m(w)m(able)30 b(next)g(actions:)572 1796 +y Fj(BZ2_bzCompress)663 1899 y Fl(if)f Fj(BZ_OK)g Fl(is)g(returned)572 +2003 y(no)h(sp)s(eci\014c)f(action)i(needed)f(in)f(case)i(of)g(error) +150 2255 y Ff(3.3.2)63 b Fe(BZ2_bzCompress)533 2441 y +Fj(int)47 b(BZ2_bzCompress)d(\()j(bz_stream)f(*strm,)g(int)h(action)f +(\);)150 2598 y Fl(Pro)m(vides)28 b(more)g(input)f(and/or)h(output)g +(bu\013er)g(space)h(for)f(the)h(library)-8 b(.)38 b(The)28 +b(caller)g(main)m(tains)f(input)150 2708 y(and)j(output)g(bu\013ers,)f +(and)h(calls)g Fj(BZ2_bzCompress)c Fl(to)31 b(transfer)f(data)h(b)s(et) +m(w)m(een)g(them.)150 2865 y(Before)j(eac)m(h)g(call)e(to)i +Fj(BZ2_bzCompress)p Fl(,)c Fj(next_in)h Fl(should)g(p)s(oin)m(t)h(at)h +(the)g(data)h(to)g(b)s(e)e(compressed,)150 2974 y(and)41 +b Fj(avail_in)f Fl(should)g(indicate)h(ho)m(w)h(man)m(y)f(b)m(ytes)i +(the)f(library)d(ma)m(y)k(read.)75 b Fj(BZ2_bzCompress)150 +3084 y Fl(up)s(dates)29 b Fj(next_in)p Fl(,)g Fj(avail_in)f +Fl(and)i Fj(total_in)e Fl(to)j(re\015ect)g(the)g(n)m(um)m(b)s(er)e(of)h +(b)m(ytes)h(it)f(has)g(read.)150 3241 y(Similarly)-8 +b(,)27 b Fj(next_out)h Fl(should)g(p)s(oin)m(t)h(to)i(a)f(bu\013er)f +(in)g(whic)m(h)g(the)h(compressed)g(data)h(is)e(to)i(b)s(e)e(placed,) +150 3350 y(with)i Fj(avail_out)f Fl(indicating)h(ho)m(w)h(m)m(uc)m(h)h +(output)f(space)h(is)f(a)m(v)-5 b(ailable.)46 b Fj(BZ2_bzCompress)29 +b Fl(up)s(dates)150 3460 y Fj(next_out)p Fl(,)f Fj(avail_out)g +Fl(and)i Fj(total_out)e Fl(to)j(re\015ect)g(the)f(n)m(um)m(b)s(er)g(of) +g(b)m(ytes)h(output.)150 3617 y(Y)-8 b(ou)40 b(ma)m(y)g(pro)m(vide)e +(and)h(remo)m(v)m(e)i(as)f(little)e(or)h(as)h(m)m(uc)m(h)f(data)h(as)g +(y)m(ou)f(lik)m(e)g(on)g(eac)m(h)i(call)e(of)g Fj(BZ2_)150 +3726 y(bzCompress)p Fl(.)48 b(In)33 b(the)h(limit,)f(it)h(is)f +(acceptable)h(to)h(supply)c(and)j(remo)m(v)m(e)h(data)g(one)f(b)m(yte)g +(at)h(a)f(time,)150 3836 y(although)28 b(this)f(w)m(ould)g(b)s(e)h +(terribly)e(ine\016cien)m(t.)39 b(Y)-8 b(ou)29 b(should)e(alw)m(a)m(ys) +h(ensure)g(that)h(at)g(least)g(one)f(b)m(yte)150 3946 +y(of)j(output)f(space)g(is)g(a)m(v)-5 b(ailable)30 b(at)h(eac)m(h)g +(call.)150 4102 y(A)38 b(second)h(purp)s(ose)d(of)j Fj(BZ2_bzCompress) +34 b Fl(is)j(to)i(request)f(a)h(c)m(hange)g(of)g(mo)s(de)e(of)i(the)f +(compressed)150 4212 y(stream.)150 4369 y(Conceptually)-8 +b(,)24 b(a)g(compressed)g(stream)g(can)f(b)s(e)g(in)g(one)h(of)f(four)g +(states:)39 b(IDLE,)24 b(R)m(UNNING,)h(FLUSH-)150 4478 +y(ING)37 b(and)g(FINISHING.)g(Before)i(initialisation)33 +b(\()p Fj(BZ2_bzCompressInit)p Fl(\))g(and)j(after)i(termination)150 +4588 y(\()p Fj(BZ2_bzCompressEnd)p Fl(\),)27 b(a)j(stream)h(is)f +(regarded)g(as)g(IDLE.)150 4745 y(Up)s(on)35 b(initialisation)e(\()p +Fj(BZ2_bzCompressInit)p Fl(\),)h(the)i(stream)h(is)e(placed)h(in)e(the) +j(R)m(UNNING)g(state.)150 4854 y(Subsequen)m(t)j(calls)g(to)i +Fj(BZ2_bzCompress)37 b Fl(should)j(pass)g Fj(BZ_RUN)g +Fl(as)h(the)g(requested)h(action;)47 b(other)150 4964 +y(actions)31 b(are)f(illegal)f(and)h(will)d(result)j(in)f +Fj(BZ_SEQUENCE_ERROR)p Fl(.)150 5121 y(A)m(t)38 b(some)f(p)s(oin)m(t,)h +(the)f(calling)e(program)i(will)d(ha)m(v)m(e)k(pro)m(vided)e(all)f(the) +i(input)e(data)j(it)e(w)m(an)m(ts)i(to.)61 b(It)150 5230 +y(will)28 b(then)h(w)m(an)m(t)i(to)g(\014nish)d(up)h({)i(in)d +(e\013ect,)k(asking)e(the)g(library)e(to)j(pro)s(cess)f(an)m(y)g(data)h +(it)f(migh)m(t)g(ha)m(v)m(e)150 5340 y(bu\013ered)25 +b(in)m(ternally)-8 b(.)38 b(In)25 b(this)g(state,)k Fj(BZ2_bzCompress) +22 b Fl(will)i(no)i(longer)g(attempt)h(to)g(read)f(data)h(from)p +eop +%%Page: 15 16 +15 15 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(15)150 299 y Fj(next_in)p +Fl(,)33 b(but)g(it)h(will)d(w)m(an)m(t)k(to)g(write)e(data)h(to)h +Fj(next_out)p Fl(.)49 b(Because)36 b(the)e(output)f(bu\013er)g +(supplied)150 408 y(b)m(y)e(the)h(user)e(can)i(b)s(e)f(arbitrarily)d +(small,)j(the)g(\014nishing-up)d(op)s(eration)i(cannot)i(necessarily)e +(b)s(e)h(done)150 518 y(with)e(a)i(single)e(call)h(of)g +Fj(BZ2_bzCompress)p Fl(.)150 675 y(Instead,)47 b(the)d(calling)f +(program)g(passes)h Fj(BZ_FINISH)d Fl(as)j(an)g(action)g(to)h +Fj(BZ2_bzCompress)p Fl(.)77 b(This)150 784 y(c)m(hanges)30 +b(the)f(stream's)g(state)h(to)f(FINISHING.)g(An)m(y)g(remaining)e +(input)g(\(ie,)i Fj(next_in[0)f(..)i(avail_)150 894 y(in-1])p +Fl(\))36 b(is)f(compressed)i(and)f(transferred)g(to)h(the)g(output)g +(bu\013er.)58 b(T)-8 b(o)38 b(do)e(this,)i Fj(BZ2_bzCompress)150 +1004 y Fl(m)m(ust)h(b)s(e)f(called)g(rep)s(eatedly)h(un)m(til)e(all)h +(the)h(output)f(has)h(b)s(een)f(consumed.)66 b(A)m(t)40 +b(that)g(p)s(oin)m(t,)g Fj(BZ2_)150 1113 y(bzCompress)h +Fl(returns)h Fj(BZ_STREAM_END)p Fl(,)i(and)f(the)h(stream's)g(state)h +(is)d(set)j(bac)m(k)f(to)g(IDLE.)g Fj(BZ2_)150 1223 y(bzCompressEnd)27 +b Fl(should)h(then)i(b)s(e)g(called.)150 1380 y(Just)25 +b(to)i(mak)m(e)g(sure)e(the)i(calling)d(program)i(do)s(es)g(not)g(c)m +(heat,)i(the)f(library)c(mak)m(es)k(a)f(note)h(of)f Fj(avail_in)150 +1489 y Fl(at)g(the)g(time)f(of)g(the)g(\014rst)g(call)g(to)h +Fj(BZ2_bzCompress)21 b Fl(whic)m(h)j(has)h Fj(BZ_FINISH)e +Fl(as)i(an)h(action)f(\(ie,)i(at)f(the)150 1599 y(time)d(the)h(program) +g(has)f(announced)g(its)h(in)m(ten)m(tion)f(to)h(not)g(supply)e(an)m(y) +i(more)g(input\).)37 b(By)24 b(comparing)150 1708 y(this)k(v)-5 +b(alue)28 b(with)g(that)h(of)h Fj(avail_in)c Fl(o)m(v)m(er)k(subsequen) +m(t)f(calls)f(to)h Fj(BZ2_bzCompress)p Fl(,)d(the)j(library)e(can)150 +1818 y(detect)33 b(an)m(y)e(attempts)i(to)f(slip)d(in)h(more)h(data)h +(to)h(compress.)43 b(An)m(y)31 b(calls)g(for)g(whic)m(h)f(this)g(is)h +(detected)150 1928 y(will)j(return)h Fj(BZ_SEQUENCE_ERROR)p +Fl(.)55 b(This)34 b(indicates)i(a)h(programming)e(mistak)m(e)i(whic)m +(h)e(should)g(b)s(e)150 2037 y(corrected.)150 2194 y(Instead)i(of)g +(asking)f(to)h(\014nish,)f(the)h(calling)f(program)g(ma)m(y)h(ask)g +Fj(BZ2_bzCompress)c Fl(to)38 b(tak)m(e)g(all)e(the)150 +2304 y(remaining)j(input,)i(compress)f(it)g(and)g(terminate)h(the)g +(curren)m(t)f(\(Burro)m(ws-Wheeler\))h(compression)150 +2413 y(blo)s(c)m(k.)e(This)26 b(could)h(b)s(e)g(useful)f(for)h(error)h +(con)m(trol)g(purp)s(oses.)38 b(The)27 b(mec)m(hanism)g(is)g(analogous) +h(to)g(that)150 2523 y(for)35 b(\014nishing:)46 b(call)35 +b Fj(BZ2_bzCompress)c Fl(with)i(an)i(action)g(of)g Fj(BZ_FLUSH)p +Fl(,)g(remo)m(v)m(e)h(output)f(data,)i(and)150 2632 y(p)s(ersist)h +(with)g(the)i Fj(BZ_FLUSH)e Fl(action)i(un)m(til)e(the)i(v)-5 +b(alue)39 b Fj(BZ_RUN)f Fl(is)h(returned.)68 b(As)39 +b(with)g(\014nishing,)150 2742 y Fj(BZ2_bzCompress)23 +b Fl(detects)28 b(an)m(y)f(attempt)h(to)f(pro)m(vide)f(more)h(input)e +(data)i(once)g(the)g(\015ush)e(has)i(b)s(egun.)150 2899 +y(Once)j(the)h(\015ush)e(is)g(complete,)i(the)g(stream)f(returns)g(to)h +(the)f(normal)g(R)m(UNNING)h(state.)150 3056 y(This)f(all)h(sounds)g +(prett)m(y)h(complex,)h(but)e(isn't)g(really)-8 b(.)45 +b(Here's)33 b(a)f(table)g(whic)m(h)f(sho)m(ws)h(whic)m(h)f(actions)150 +3165 y(are)e(allo)m(w)m(able)f(in)f(eac)m(h)j(state,)g(what)f(action)g +(will)c(b)s(e)j(tak)m(en,)j(what)d(the)h(next)f(state)i(is,)e(and)g +(what)h(the)150 3275 y(non-error)h(return)f(v)-5 b(alues)29 +b(are.)41 b(Note)32 b(that)e(y)m(ou)h(can't)g(explicitly)d(ask)i(what)g +(state)i(the)e(stream)h(is)e(in,)150 3384 y(but)h(nor)g(do)g(y)m(ou)h +(need)f(to)h({)g(it)e(can)i(b)s(e)f(inferred)e(from)i(the)h(v)-5 +b(alues)29 b(returned)h(b)m(y)g Fj(BZ2_bzCompress)p Fl(.)390 +3535 y(IDLE/)p Fj(any)572 3639 y Fl(Illegal.)60 b(IDLE)30 +b(state)i(only)d(exists)h(after)h Fj(BZ2_bzCompressEnd)26 +b Fl(or)572 3743 y(b)s(efore)k Fj(BZ2_bzCompressInit)p +Fl(.)572 3847 y(Return)f(v)-5 b(alue)30 b(=)g Fj(BZ_SEQUENCE_ERROR)390 +4054 y Fl(R)m(UNNING/)p Fj(BZ_RUN)572 4158 y Fl(Compress)f(from)h +Fj(next_in)f Fl(to)i Fj(next_out)d Fl(as)i(m)m(uc)m(h)h(as)f(p)s +(ossible.)572 4262 y(Next)h(state)h(=)e(R)m(UNNING)572 +4366 y(Return)f(v)-5 b(alue)30 b(=)g Fj(BZ_RUN_OK)390 +4573 y Fl(R)m(UNNING/)p Fj(BZ_FLUSH)572 4677 y Fl(Remem)m(b)s(er)g +(curren)m(t)g(v)-5 b(alue)30 b(of)g Fj(next_in)p Fl(.)59 +b(Compress)30 b(from)g Fj(next_in)572 4781 y Fl(to)h +Fj(next_out)d Fl(as)j(m)m(uc)m(h)f(as)h(p)s(ossible,)d(but)i(do)g(not)g +(accept)i(an)m(y)f(more)f(input.)572 4885 y(Next)h(state)h(=)e +(FLUSHING)572 4988 y(Return)f(v)-5 b(alue)30 b(=)g Fj(BZ_FLUSH_OK)390 +5196 y Fl(R)m(UNNING/)p Fj(BZ_FINISH)572 5300 y Fl(Remem)m(b)s(er)g +(curren)m(t)g(v)-5 b(alue)30 b(of)g Fj(next_in)p Fl(.)59 +b(Compress)30 b(from)g Fj(next_in)p eop +%%Page: 16 17 +16 16 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(16)572 299 y(to)31 b Fj(next_out)d +Fl(as)j(m)m(uc)m(h)f(as)h(p)s(ossible,)d(but)i(do)g(not)g(accept)i(an)m +(y)f(more)f(input.)572 403 y(Next)h(state)h(=)e(FINISHING)572 +506 y(Return)f(v)-5 b(alue)30 b(=)g Fj(BZ_FINISH_OK)390 +714 y Fl(FLUSHING/)p Fj(BZ_FLUSH)572 818 y Fl(Compress)f(from)h +Fj(next_in)f Fl(to)i Fj(next_out)d Fl(as)i(m)m(uc)m(h)h(as)f(p)s +(ossible,)572 922 y(but)f(do)i(not)f(accept)i(an)m(y)f(more)f(input.) +572 1025 y(If)g(all)f(the)i(existing)e(input)f(has)i(b)s(een)g(used)g +(up)f(and)h(all)f(compressed)572 1129 y(output)h(has)g(b)s(een)g(remo)m +(v)m(ed)663 1233 y(Next)h(state)h(=)e(R)m(UNNING;)i(Return)d(v)-5 +b(alue)30 b(=)g Fj(BZ_RUN_OK)572 1337 y Fl(else)663 1440 +y(Next)h(state)h(=)e(FLUSHING;)h(Return)e(v)-5 b(alue)30 +b(=)g Fj(BZ_FLUSH_OK)390 1648 y Fl(FLUSHING/other)572 +1752 y(Illegal.)572 1856 y(Return)f(v)-5 b(alue)30 b(=)g +Fj(BZ_SEQUENCE_ERROR)390 2063 y Fl(FINISHING/)p Fj(BZ_FINISH)572 +2167 y Fl(Compress)f(from)h Fj(next_in)f Fl(to)i Fj(next_out)d +Fl(as)i(m)m(uc)m(h)h(as)f(p)s(ossible,)572 2271 y(but)f(to)j(not)e +(accept)i(an)m(y)f(more)f(input.)572 2374 y(If)g(all)f(the)i(existing)e +(input)f(has)i(b)s(een)g(used)g(up)f(and)h(all)f(compressed)572 +2478 y(output)h(has)g(b)s(een)g(remo)m(v)m(ed)663 2582 +y(Next)h(state)h(=)e(IDLE;)g(Return)g(v)-5 b(alue)30 +b(=)g Fj(BZ_STREAM_END)572 2686 y Fl(else)663 2790 y(Next)h(state)h(=)e +(FINISHING;)g(Return)g(v)-5 b(alue)30 b(=)g Fj(BZ_FINISHING)390 +2997 y Fl(FINISHING/other)572 3101 y(Illegal.)572 3205 +y(Return)f(v)-5 b(alue)30 b(=)g Fj(BZ_SEQUENCE_ERROR)150 +3361 y Fl(That)24 b(still)f(lo)s(oks)g(complicated?)39 +b(W)-8 b(ell,)25 b(fair)f(enough.)38 b(The)24 b(usual)f(sequence)i(of)f +(calls)g(for)g(compressing)150 3471 y(a)31 b(load)f(of)g(data)h(is:)225 +3628 y Fi(\017)60 b Fl(Get)31 b(started)g(with)e Fj(BZ2_bzCompressInit) +p Fl(.)225 3774 y Fi(\017)60 b Fl(Sho)m(v)m(el)38 b(data)h(in)e(and)g +(shlurp)e(out)k(its)e(compressed)h(form)g(using)e(zero)j(or)f(more)h +(calls)e(of)h Fj(BZ2_)330 3884 y(bzCompress)28 b Fl(with)h(action)h(=)g +Fj(BZ_RUN)p Fl(.)225 4030 y Fi(\017)60 b Fl(Finish)23 +b(up.)38 b(Rep)s(eatedly)25 b(call)f Fj(BZ2_bzCompress)e +Fl(with)i(action)h(=)g Fj(BZ_FINISH)p Fl(,)f(cop)m(ying)h(out)h(the)330 +4139 y(compressed)k(output,)g(un)m(til)f Fj(BZ_STREAM_END)e +Fl(is)i(returned.)225 4285 y Fi(\017)60 b Fl(Close)30 +b(up)f(and)h(go)h(home.)41 b(Call)29 b Fj(BZ2_bzCompressEnd)p +Fl(.)150 4478 y(If)23 b(the)h(data)h(y)m(ou)f(w)m(an)m(t)h(to)f +(compress)g(\014ts)f(in)m(to)h(y)m(our)g(input)e(bu\013er)h(all)f(at)j +(once,)h(y)m(ou)e(can)g(skip)f(the)h(calls)150 4588 y(of)37 +b Fj(BZ2_bzCompress)26 b(\()k(...,)f(BZ_RUN)g(\))36 b +Fl(and)g(just)g(do)h(the)g Fj(BZ2_bzCompress)26 b(\()k(...,)f +(BZ_FINISH)150 4698 y(\))h Fl(calls.)150 4854 y(All)36 +b(required)g(memory)h(is)f(allo)s(cated)i(b)m(y)f Fj +(BZ2_bzCompressInit)p Fl(.)56 b(The)37 b(compression)g(library)e(can) +150 4964 y(accept)g(an)m(y)f(data)h(at)g(all)d(\(ob)m(viously\).)51 +b(So)34 b(y)m(ou)g(shouldn't)e(get)j(an)m(y)f(error)f(return)g(v)-5 +b(alues)33 b(from)h(the)150 5074 y Fj(BZ2_bzCompress)29 +b Fl(calls.)46 b(If)32 b(y)m(ou)h(do,)g(they)g(will)d(b)s(e)i +Fj(BZ_SEQUENCE_ERROR)p Fl(,)d(and)j(indicate)f(a)i(bug)f(in)150 +5183 y(y)m(our)e(programming.)150 5340 y(T)-8 b(rivial)28 +b(other)j(p)s(ossible)d(return)h(v)-5 b(alues:)p eop +%%Page: 17 18 +17 17 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(17)572 299 y Fj(BZ_PARAM_ERROR)663 +403 y Fl(if)29 b Fj(strm)g Fl(is)h Fj(NULL)p Fl(,)f(or)i +Fj(strm->s)d Fl(is)h Fj(NULL)150 652 y Ff(3.3.3)63 b +Fe(BZ2_bzCompressEnd)390 839 y Fj(int)47 b(BZ2_bzCompressEnd)c(\()k +(bz_stream)f(*strm)g(\);)150 996 y Fl(Releases)31 b(all)e(memory)h +(asso)s(ciated)h(with)e(a)i(compression)e(stream.)150 +1153 y(P)m(ossible)g(return)h(v)-5 b(alues:)481 1304 +y Fj(BZ_PARAM_ERROR)117 b Fl(if)30 b Fj(strm)f Fl(is)g +Fj(NULL)g Fl(or)i Fj(strm->s)d Fl(is)i Fj(NULL)481 1408 +y(BZ_OK)120 b Fl(otherwise)150 1657 y Ff(3.3.4)63 b Fe +(BZ2_bzDecompressInit)390 1844 y Fj(int)47 b(BZ2_bzDecompressInit)42 +b(\()48 b(bz_stream)d(*strm,)h(int)h(verbosity,)e(int)i(small)f(\);)150 +2001 y Fl(Prepares)30 b(for)f(decompression.)40 b(As)29 +b(with)g Fj(BZ2_bzCompressInit)p Fl(,)c(a)31 b Fj(bz_stream)c +Fl(record)j(should)e(b)s(e)150 2110 y(allo)s(cated)c(and)f(initialised) +e(b)s(efore)i(the)i(call.)38 b(Fields)22 b Fj(bzalloc)p +Fl(,)i Fj(bzfree)e Fl(and)i Fj(opaque)e Fl(should)g(b)s(e)h(set)i(if) +150 2220 y(a)h(custom)f(memory)g(allo)s(cator)g(is)g(required,)f(or)h +(made)h Fj(NULL)e Fl(for)h(the)g(normal)f Fj(malloc)p +Fl(/)p Fj(free)f Fl(routines.)150 2330 y(Up)s(on)h(return,)h(the)g(in)m +(ternal)f(state)i(will)c(ha)m(v)m(e)k(b)s(een)f(initialised,)d(and)i +Fj(total_in)f Fl(and)h Fj(total_out)f Fl(will)150 2439 +y(b)s(e)30 b(zero.)150 2596 y(F)-8 b(or)31 b(the)g(meaning)e(of)i +(parameter)g Fj(verbosity)p Fl(,)d(see)j Fj(BZ2_bzCompressInit)p +Fl(.)150 2753 y(If)e Fj(small)e Fl(is)h(nonzero,)i(the)f(library)e +(will)f(use)j(an)g(alternativ)m(e)h(decompression)e(algorithm)g(whic)m +(h)f(uses)150 2862 y(less)c(memory)g(but)g(at)h(the)g(cost)h(of)e +(decompressing)g(more)g(slo)m(wly)g(\(roughly)f(sp)s(eaking,)i(half)f +(the)h(sp)s(eed,)150 2972 y(but)34 b(the)i(maxim)m(um)d(memory)i +(requiremen)m(t)g(drops)e(to)j(around)e(2300k\).)57 b(See)35 +b(Chapter)g(2)g(for)g(more)150 3082 y(information)29 +b(on)h(memory)g(managemen)m(t.)150 3238 y(Note)40 b(that)f(the)f(amoun) +m(t)h(of)g(memory)f(needed)g(to)i(decompress)e(a)h(stream)f(cannot)h(b) +s(e)f(determined)150 3348 y(un)m(til)j(the)h(stream's)h(header)f(has)g +(b)s(een)g(read,)j(so)e(ev)m(en)g(if)e Fj(BZ2_bzDecompressInit)c +Fl(succeeds,)46 b(a)150 3458 y(subsequen)m(t)30 b Fj(BZ2_bzDecompress)c +Fl(could)j(fail)g(with)g Fj(BZ_MEM_ERROR)p Fl(.)150 3614 +y(P)m(ossible)g(return)h(v)-5 b(alues:)572 3765 y Fj(BZ_CONFIG_ERROR) +663 3869 y Fl(if)29 b(the)i(library)d(has)i(b)s(een)f(mis-compiled)572 +3973 y Fj(BZ_PARAM_ERROR)663 4077 y Fl(if)g Fj(\(small)46 +b(!=)h(0)h(&&)f(small)f(!=)h(1\))663 4181 y Fl(or)30 +b Fj(\(verbosity)45 b(<)j(0)f(||)g(verbosity)e(>)j(4\))572 +4284 y(BZ_MEM_ERROR)663 4388 y Fl(if)29 b(insu\016cien)m(t)g(memory)h +(is)f(a)m(v)-5 b(ailable)150 4545 y(Allo)m(w)m(able)30 +b(next)g(actions:)572 4696 y Fj(BZ2_bzDecompress)663 +4800 y Fl(if)f Fj(BZ_OK)g Fl(w)m(as)i(returned)572 4904 +y(no)f(sp)s(eci\014c)f(action)i(required)e(in)g(case)i(of)g(error)150 +5153 y Ff(3.3.5)63 b Fe(BZ2_bzDecompress)390 5340 y Fj(int)47 +b(BZ2_bzDecompress)c(\()48 b(bz_stream)d(*strm)h(\);)p +eop +%%Page: 18 19 +18 18 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(18)150 299 y(Pro)m(vides)24 +b(more)g(input)f(and/out)h(output)g(bu\013er)g(space)h(for)f(the)g +(library)-8 b(.)37 b(The)24 b(caller)g(main)m(tains)f(input)150 +408 y(and)30 b(output)g(bu\013ers,)f(and)h(uses)g Fj(BZ2_bzDecompress)c +Fl(to)31 b(transfer)f(data)h(b)s(et)m(w)m(een)g(them.)150 +565 y(Before)g(eac)m(h)g(call)f(to)g Fj(BZ2_bzDecompress)p +Fl(,)c Fj(next_in)i Fl(should)h(p)s(oin)m(t)g(at)h(the)h(compressed)e +(data,)j(and)150 675 y Fj(avail_in)h Fl(should)h(indicate)h(ho)m(w)h +(man)m(y)f(b)m(ytes)i(the)e(library)f(ma)m(y)i(read.)56 +b Fj(BZ2_bzDecompress)32 b Fl(up-)150 784 y(dates)f Fj(next_in)p +Fl(,)e Fj(avail_in)f Fl(and)h Fj(total_in)g Fl(to)i(re\015ect)g(the)f +(n)m(um)m(b)s(er)f(of)i(b)m(ytes)g(it)f(has)g(read.)150 +941 y(Similarly)-8 b(,)37 b Fj(next_out)f Fl(should)g(p)s(oin)m(t)i(to) +g(a)h(bu\013er)e(in)g(whic)m(h)g(the)i(uncompressed)e(output)g(is)h(to) +h(b)s(e)150 1051 y(placed,)d(with)e Fj(avail_out)f Fl(indicating)g(ho)m +(w)i(m)m(uc)m(h)g(output)g(space)h(is)e(a)m(v)-5 b(ailable.)55 +b Fj(BZ2_bzCompress)150 1160 y Fl(up)s(dates)29 b Fj(next_out)p +Fl(,)g Fj(avail_out)f Fl(and)h Fj(total_out)f Fl(to)j(re\015ect)g(the)g +(n)m(um)m(b)s(er)e(of)h(b)m(ytes)h(output.)150 1317 y(Y)-8 +b(ou)40 b(ma)m(y)g(pro)m(vide)e(and)h(remo)m(v)m(e)i(as)f(little)e(or)h +(as)h(m)m(uc)m(h)f(data)h(as)g(y)m(ou)f(lik)m(e)g(on)g(eac)m(h)i(call)e +(of)g Fj(BZ2_)150 1427 y(bzDecompress)p Fl(.)e(In)27 +b(the)i(limit,)d(it)i(is)f(acceptable)j(to)f(supply)d(and)h(remo)m(v)m +(e)j(data)f(one)f(b)m(yte)h(at)g(a)g(time,)150 1537 y(although)f(this)f +(w)m(ould)g(b)s(e)h(terribly)e(ine\016cien)m(t.)39 b(Y)-8 +b(ou)29 b(should)e(alw)m(a)m(ys)h(ensure)g(that)h(at)g(least)g(one)f(b) +m(yte)150 1646 y(of)j(output)f(space)g(is)g(a)m(v)-5 +b(ailable)30 b(at)h(eac)m(h)g(call.)150 1803 y(Use)g(of)f +Fj(BZ2_bzDecompress)c Fl(is)k(simpler)e(than)i Fj(BZ2_bzCompress)p +Fl(.)150 1960 y(Y)-8 b(ou)31 b(should)d(pro)m(vide)h(input)f(and)i +(remo)m(v)m(e)i(output)d(as)i(describ)s(ed)d(ab)s(o)m(v)m(e,)k(and)d +(rep)s(eatedly)h(call)f Fj(BZ2_)150 2069 y(bzDecompress)35 +b Fl(un)m(til)i Fj(BZ_STREAM_END)e Fl(is)j(returned.)64 +b(App)s(earance)39 b(of)g Fj(BZ_STREAM_END)c Fl(denotes)150 +2179 y(that)47 b Fj(BZ2_bzDecompress)42 b Fl(has)k(detected)h(the)f +(logical)g(end)g(of)g(the)h(compressed)e(stream.)89 b +Fj(BZ2_)150 2289 y(bzDecompress)28 b Fl(will)g(not)j(pro)s(duce)f +Fj(BZ_STREAM_END)d Fl(un)m(til)j(all)f(output)i(data)h(has)e(b)s(een)h +(placed)f(in)m(to)150 2398 y(the)36 b(output)g(bu\013er,)h(so)g(once)g +Fj(BZ_STREAM_END)32 b Fl(app)s(ears,)38 b(y)m(ou)e(are)h(guaran)m(teed) +g(to)g(ha)m(v)m(e)h(a)m(v)-5 b(ailable)150 2508 y(all)29 +b(the)i(decompressed)f(output,)g(and)g Fj(BZ2_bzDecompressEnd)25 +b Fl(can)31 b(safely)f(b)s(e)f(called.)150 2665 y(If)40 +b(case)h(of)f(an)h(error)e(return)h(v)-5 b(alue,)42 b(y)m(ou)f(should)d +(call)h Fj(BZ2_bzDecompressEnd)c Fl(to)41 b(clean)f(up)g(and)150 +2774 y(release)31 b(memory)-8 b(.)150 2931 y(P)m(ossible)29 +b(return)h(v)-5 b(alues:)572 3082 y Fj(BZ_PARAM_ERROR)663 +3186 y Fl(if)29 b Fj(strm)g Fl(is)h Fj(NULL)f Fl(or)h +Fj(strm->s)f Fl(is)g Fj(NULL)663 3290 y Fl(or)h Fj(strm->avail_out)44 +b(<)j(1)572 3393 y(BZ_DATA_ERROR)663 3497 y Fl(if)29 +b(a)i(data)g(in)m(tegrit)m(y)f(error)g(is)g(detected)h(in)e(the)i +(compressed)f(stream)572 3601 y Fj(BZ_DATA_ERROR_MAGIC)663 +3705 y Fl(if)f(the)i(compressed)f(stream)g(do)s(esn't)h(b)s(egin)e +(with)g(the)h(righ)m(t)g(magic)h(b)m(ytes)572 3808 y +Fj(BZ_MEM_ERROR)663 3912 y Fl(if)e(there)i(w)m(asn't)f(enough)h(memory) +f(a)m(v)-5 b(ailable)572 4016 y Fj(BZ_STREAM_END)663 +4120 y Fl(if)29 b(the)i(logical)e(end)h(of)h(the)f(data)h(stream)g(w)m +(as)g(detected)g(and)f(all)663 4224 y(output)g(in)f(has)h(b)s(een)g +(consumed,)f(eg)j Fj(s->avail_out)44 b(>)k(0)572 4327 +y(BZ_OK)663 4431 y Fl(otherwise)150 4588 y(Allo)m(w)m(able)30 +b(next)g(actions:)572 4739 y Fj(BZ2_bzDecompress)663 +4843 y Fl(if)f Fj(BZ_OK)g Fl(w)m(as)i(returned)572 4946 +y Fj(BZ2_bzDecompressEnd)663 5050 y Fl(otherwise)p eop +%%Page: 19 20 +19 19 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(19)150 299 y Ff(3.3.6)63 +b Fe(BZ2_bzDecompressEnd)390 486 y Fj(int)47 b(BZ2_bzDecompressEnd)42 +b(\()48 b(bz_stream)d(*strm)i(\);)150 643 y Fl(Releases)31 +b(all)e(memory)h(asso)s(ciated)h(with)e(a)i(decompression)e(stream.)150 +799 y(P)m(ossible)g(return)h(v)-5 b(alues:)572 950 y +Fj(BZ_PARAM_ERROR)663 1054 y Fl(if)29 b Fj(strm)g Fl(is)h +Fj(NULL)f Fl(or)h Fj(strm->s)f Fl(is)g Fj(NULL)572 1158 +y(BZ_OK)663 1262 y Fl(otherwise)150 1419 y(Allo)m(w)m(able)h(next)g +(actions:)572 1570 y(None.)150 1857 y Fk(3.4)68 b(High-lev)l(el)47 +b(in)l(terface)150 2050 y Fl(This)35 b(in)m(terface)j(pro)m(vides)d +(functions)h(for)g(reading)g(and)h(writing)e Fj(bzip2)g +Fl(format)i(\014les.)59 b(First,)39 b(some)150 2159 y(general)30 +b(p)s(oin)m(ts.)225 2316 y Fi(\017)60 b Fl(All)35 b(of)h(the)g +(functions)e(tak)m(e)k(an)e Fj(int*)f Fl(\014rst)g(argumen)m(t,)j +Fj(bzerror)p Fl(.)56 b(After)36 b(eac)m(h)h(call,)g Fj(bzerror)330 +2426 y Fl(should)23 b(b)s(e)i(consulted)g(\014rst)g(to)h(determine)e +(the)i(outcome)h(of)e(the)h(call.)38 b(If)25 b Fj(bzerror)f +Fl(is)g Fj(BZ_OK)p Fl(,)i(the)330 2535 y(call)35 b(completed)g +(successfully)-8 b(,)36 b(and)f(only)g(then)g(should)f(the)h(return)g +(v)-5 b(alue)35 b(of)h(the)f(function)g(\(if)330 2645 +y(an)m(y\))30 b(b)s(e)f(consulted.)39 b(If)29 b Fj(bzerror)e +Fl(is)h Fj(BZ_IO_ERROR)p Fl(,)f(there)i(w)m(as)h(an)f(error)g +(reading/writing)e(the)330 2754 y(underlying)32 b(compressed)j(\014le,) +h(and)f(y)m(ou)h(should)d(then)i(consult)g Fj(errno)p +Fl(/)p Fj(perror)e Fl(to)j(determine)330 2864 y(the)i(cause)g(of)g(the) +g(di\016cult)m(y)-8 b(.)61 b Fj(bzerror)36 b Fl(ma)m(y)i(also)g(b)s(e)f +(set)h(to)g(v)-5 b(arious)37 b(other)h(v)-5 b(alues;)41 +b(precise)330 2974 y(details)29 b(are)i(giv)m(en)g(on)f(a)h(p)s +(er-function)d(basis)h(b)s(elo)m(w.)225 3111 y Fi(\017)60 +b Fl(If)40 b Fj(bzerror)f Fl(indicates)g(an)i(error)f(\(ie,)j(an)m +(ything)d(except)h Fj(BZ_OK)f Fl(and)g Fj(BZ_STREAM_END)p +Fl(\),)g(y)m(ou)330 3220 y(should)56 b(immediately)h(call)g +Fj(BZ2_bzReadClose)e Fl(\(or)j Fj(BZ2_bzWriteClose)p +Fl(,)j(dep)s(ending)56 b(on)330 3330 y(whether)50 b(y)m(ou)g(are)h +(attempting)g(to)g(read)f(or)g(to)i(write\))d(to)j(free)e(up)f(all)h +(resources)g(asso)s(ci-)330 3439 y(ated)33 b(with)e(the)i(stream.)47 +b(Once)32 b(an)h(error)f(has)g(b)s(een)g(indicated,)f(b)s(eha)m(viour)g +(of)i(all)e(calls)h(except)330 3549 y Fj(BZ2_bzReadClose)46 +b Fl(\()p Fj(BZ2_bzWriteClose)p Fl(\))h(is)j(unde\014ned.)99 +b(The)50 b(implication)e(is)i(that)h(\(1\))330 3659 y +Fj(bzerror)44 b Fl(should)g(b)s(e)h(c)m(hec)m(k)m(ed)j(after)e(eac)m(h) +h(call,)i(and)c(\(2\))i(if)e Fj(bzerror)f Fl(indicates)g(an)i(error,) +330 3768 y Fj(BZ2_bzReadClose)26 b Fl(\()p Fj(BZ2_bzWriteClose)p +Fl(\))h(should)h(then)i(b)s(e)g(called)g(to)h(clean)f(up.)225 +3905 y Fi(\017)60 b Fl(The)33 b Fj(FILE*)f Fl(argumen)m(ts)h(passed)g +(to)h Fj(BZ2_bzReadOpen)p Fl(/)p Fj(BZ2_bzWriteOp)o(en)27 +b Fl(should)32 b(b)s(e)g(set)i(to)330 4015 y(binary)23 +b(mo)s(de.)38 b(Most)26 b(Unix)d(systems)i(will)d(do)i(this)g(b)m(y)g +(default,)i(but)e(other)g(platforms,)h(including)330 +4124 y(Windo)m(ws)20 b(and)g(Mac,)k(will)19 b(not.)38 +b(If)20 b(y)m(ou)h(omit)g(this,)h(y)m(ou)f(ma)m(y)h(encoun)m(ter)f +(problems)e(when)h(mo)m(ving)330 4234 y(co)s(de)31 b(to)g(new)f +(platforms.)225 4371 y Fi(\017)60 b Fl(Memory)23 b(allo)s(cation)f +(requests)h(are)g(handled)e(b)m(y)i Fj(malloc)p Fl(/)p +Fj(free)p Fl(.)36 b(A)m(t)23 b(presen)m(t)g(there)g(is)f(no)h(facilit)m +(y)330 4481 y(for)40 b(user-de\014ned)e(memory)i(allo)s(cators)g(in)f +(the)h(\014le)g(I/O)g(functions)e(\(could)i(easily)f(b)s(e)g(added,)330 +4590 y(though\).)150 4842 y Ff(3.4.1)63 b Fe(BZ2_bzReadOpen)533 +5029 y Fj(typedef)46 b(void)h(BZFILE;)533 5236 y(BZFILE)f +(*BZ2_bzReadOpen)e(\()j(int)g(*bzerror,)f(FILE)g(*f,)1726 +5340 y(int)h(small,)f(int)h(verbosity,)p eop +%%Page: 20 21 +20 20 bop 150 -116 a Fl(Chapter)30 b(3:)h(Programming)e(with)g +Fj(libbzip2)1891 b Fl(20)1726 299 y Fj(void)47 b(*unused,)f(int)g +(nUnused)g(\);)150 456 y Fl(Prepare)29 b(to)g(read)g(compressed)f(data) +i(from)e(\014le)g(handle)f Fj(f)p Fl(.)40 b Fj(f)29 b +Fl(should)d(refer)j(to)h(a)f(\014le)f(whic)m(h)f(has)i(b)s(een)150 +565 y(op)s(ened)h(for)h(reading,)f(and)h(for)f(whic)m(h)g(the)h(error)g +(indicator)e(\()p Fj(ferror\(f\))p Fl(\)is)f(not)k(set.)42 +b(If)31 b Fj(small)e Fl(is)h(1,)150 675 y(the)h(library)d(will)f(try)j +(to)i(decompress)e(using)f(less)g(memory)-8 b(,)31 b(at)g(the)g(exp)s +(ense)f(of)g(sp)s(eed.)150 832 y(F)-8 b(or)39 b(reasons)f(explained)f +(b)s(elo)m(w,)j Fj(BZ2_bzRead)35 b Fl(will)h(decompress)i(the)g +Fj(nUnused)e Fl(b)m(ytes)j(starting)f(at)150 941 y Fj(unused)p +Fl(,)k(b)s(efore)e(starting)h(to)g(read)g(from)f(the)h(\014le)f +Fj(f)p Fl(.)71 b(A)m(t)42 b(most)f Fj(BZ_MAX_UNUSED)c +Fl(b)m(ytes)k(ma)m(y)h(b)s(e)150 1051 y(supplied)32 b(lik)m(e)k(this.) +55 b(If)36 b(this)e(facilit)m(y)h(is)g(not)h(required,)g(y)m(ou)g +(should)e(pass)h Fj(NULL)g Fl(and)g Fj(0)g Fl(for)h Fj(unused)150 +1160 y Fl(and)30 b(n)p Fj(Unused)e Fl(resp)s(ectiv)m(ely)-8 +b(.)150 1317 y(F)g(or)31 b(the)g(meaning)e(of)i(parameters)g +Fj(small)e Fl(and)g Fj(verbosity)p Fl(,)f(see)j Fj +(BZ2_bzDecompressInit)p Fl(.)150 1474 y(The)k(amoun)m(t)g(of)g(memory)g +(needed)g(to)g(decompress)g(a)h(\014le)e(cannot)h(b)s(e)g(determined)e +(un)m(til)h(the)h(\014le's)150 1584 y(header)22 b(has)f(b)s(een)g +(read.)38 b(So)22 b(it)f(is)g(p)s(ossible)e(that)k Fj(BZ2_bzReadOpen)17 +b Fl(returns)k Fj(BZ_OK)f Fl(but)h(a)i(subsequen)m(t)150 +1693 y(call)30 b(of)g Fj(BZ2_bzRead)e Fl(will)f(return)j +Fj(BZ_MEM_ERROR)p Fl(.)150 1850 y(P)m(ossible)f(assignmen)m(ts)h(to)h +Fj(bzerror)p Fl(:)572 2001 y Fj(BZ_CONFIG_ERROR)663 2105 +y Fl(if)e(the)i(library)d(has)i(b)s(een)f(mis-compiled)572 +2209 y Fj(BZ_PARAM_ERROR)663 2313 y Fl(if)g Fj(f)h Fl(is)g +Fj(NULL)663 2416 y Fl(or)g Fj(small)f Fl(is)g(neither)h +Fj(0)g Fl(nor)g Fj(1)663 2520 y Fl(or)g Fj(\(unused)46 +b(==)h(NULL)g(&&)g(nUnused)f(!=)h(0\))663 2624 y Fl(or)30 +b Fj(\(unused)46 b(!=)h(NULL)g(&&)g(!\(0)g(<=)g(nUnused)f(<=)h +(BZ_MAX_UNUSED\)\))572 2728 y(BZ_IO_ERROR)663 2831 y +Fl(if)29 b Fj(ferror\(f\))f Fl(is)h(nonzero)572 2935 +y Fj(BZ_MEM_ERROR)663 3039 y Fl(if)g(insu\016cien)m(t)g(memory)h(is)f +(a)m(v)-5 b(ailable)572 3143 y Fj(BZ_OK)663 3247 y Fl(otherwise.)150 +3403 y(P)m(ossible)29 b(return)h(v)-5 b(alues:)572 3554 +y(P)m(oin)m(ter)31 b(to)g(an)f(abstract)h Fj(BZFILE)663 +3658 y Fl(if)e Fj(bzerror)f Fl(is)i Fj(BZ_OK)572 3762 +y(NULL)663 3866 y Fl(otherwise)150 4023 y(Allo)m(w)m(able)g(next)g +(actions:)572 4174 y Fj(BZ2_bzRead)663 4277 y Fl(if)f +Fj(bzerror)f Fl(is)i Fj(BZ_OK)572 4381 y(BZ2_bzClose)663 +4485 y Fl(otherwise)150 4887 y Ff(3.4.2)63 b Fe(BZ2_bzRead)533 +5074 y Fj(int)47 b(BZ2_bzRead)e(\()j(int)e(*bzerror,)g(BZFILE)g(*b,)h +(void)f(*buf,)h(int)g(len)g(\);)150 5230 y Fl(Reads)35 +b(up)f(to)h Fj(len)f Fl(\(uncompressed\))h(b)m(ytes)g(from)f(the)h +(compressed)g(\014le)f Fj(b)g Fl(in)m(to)h(the)g(bu\013er)f +Fj(buf)p Fl(.)53 b(If)150 5340 y(the)30 b(read)f(w)m(as)h(successful,)f +Fj(bzerror)e Fl(is)i(set)h(to)g Fj(BZ_OK)e Fl(and)h(the)h(n)m(um)m(b)s +(er)e(of)i(b)m(ytes)g(read)f(is)g(returned.)p eop +%%Page: 21 22 +21 21 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(21)150 299 y(If)33 b(the)g(logical)g +(end-of-stream)h(w)m(as)g(detected,)i Fj(bzerror)31 b +Fl(will)g(b)s(e)h(set)i(to)g Fj(BZ_STREAM_END)p Fl(,)d(and)i(the)150 +408 y(n)m(um)m(b)s(er)c(of)i(b)m(ytes)f(read)h(is)e(returned.)40 +b(All)29 b(other)h Fj(bzerror)f Fl(v)-5 b(alues)29 b(denote)i(an)g +(error.)150 565 y Fj(BZ2_bzRead)37 b Fl(will)f(supply)h +Fj(len)i Fl(b)m(ytes,)j(unless)c(the)i(logical)f(stream)h(end)e(is)h +(detected)i(or)e(an)g(error)150 675 y(o)s(ccurs.)75 b(Because)43 +b(of)f(this,)i(it)d(is)g(p)s(ossible)e(to)k(detect)g(the)f(stream)g +(end)f(b)m(y)h(observing)f(when)g(the)150 784 y(n)m(um)m(b)s(er)29 +b(of)h(b)m(ytes)g(returned)f(is)g(less)g(than)h(the)g(n)m(um)m(b)s(er)f +(requested.)40 b(Nev)m(ertheless,)31 b(this)e(is)g(regarded)150 +894 y(as)38 b(inadvisable;)g(y)m(ou)g(should)d(instead)i(c)m(hec)m(k)i +Fj(bzerror)d Fl(after)i(ev)m(ery)g(call)e(and)h(w)m(atc)m(h)i(out)f +(for)f Fj(BZ_)150 1004 y(STREAM_END)p Fl(.)150 1160 y(In)m(ternally)-8 +b(,)47 b Fj(BZ2_bzRead)41 b Fl(copies)j(data)g(from)g(the)g(compressed) +g(\014le)f(in)f(c)m(h)m(unks)i(of)g(size)g Fj(BZ_MAX_)150 +1270 y(UNUSED)31 b Fl(b)m(ytes)i(b)s(efore)f(decompressing)f(it.)47 +b(If)32 b(the)h(\014le)e(con)m(tains)i(more)g(b)m(ytes)g(than)f +(strictly)f(needed)150 1380 y(to)48 b(reac)m(h)f(the)g(logical)f +(end-of-stream,)52 b Fj(BZ2_bzRead)44 b Fl(will)g(almost)j(certainly)f +(read)h(some)g(of)g(the)150 1489 y(trailing)c(data)j(b)s(efore)e +(signalling)f Fj(BZ_SEQUENCE_END)p Fl(.)80 b(T)-8 b(o)46 +b(collect)f(the)g(read)g(but)g(un)m(used)e(data)150 1599 +y(once)29 b Fj(BZ_SEQUENCE_END)24 b Fl(has)k(app)s(eared,)g(call)f +Fj(BZ2_bzReadGetUnused)c Fl(immediately)j(b)s(efore)i +Fj(BZ2_)150 1708 y(bzReadClose)p Fl(.)150 1865 y(P)m(ossible)h +(assignmen)m(ts)h(to)h Fj(bzerror)p Fl(:)572 2016 y Fj(BZ_PARAM_ERROR) +663 2120 y Fl(if)e Fj(b)h Fl(is)g Fj(NULL)f Fl(or)h Fj(buf)g +Fl(is)f Fj(NULL)g Fl(or)i Fj(len)46 b(<)i(0)572 2224 +y(BZ_SEQUENCE_ERROR)663 2328 y Fl(if)29 b Fj(b)h Fl(w)m(as)h(op)s(ened) +e(with)h Fj(BZ2_bzWriteOpen)572 2431 y(BZ_IO_ERROR)663 +2535 y Fl(if)f(there)i(is)e(an)h(error)g(reading)g(from)g(the)g +(compressed)g(\014le)572 2639 y Fj(BZ_UNEXPECTED_EOF)663 +2743 y Fl(if)f(the)i(compressed)f(\014le)f(ended)h(b)s(efore)g(the)g +(logical)g(end-of-stream)h(w)m(as)g(detected)572 2847 +y Fj(BZ_DATA_ERROR)663 2950 y Fl(if)e(a)i(data)g(in)m(tegrit)m(y)f +(error)g(w)m(as)h(detected)h(in)d(the)h(compressed)g(stream)572 +3054 y Fj(BZ_DATA_ERROR_MAGIC)663 3158 y Fl(if)f(the)i(stream)f(do)s +(es)g(not)h(b)s(egin)e(with)g(the)i(requisite)e(header)h(b)m(ytes)h +(\(ie,)f(is)g(not)663 3262 y(a)g Fj(bzip2)f Fl(data)i(\014le\).)61 +b(This)28 b(is)i(really)f(a)i(sp)s(ecial)e(case)i(of)g +Fj(BZ_DATA_ERROR)p Fl(.)572 3365 y Fj(BZ_MEM_ERROR)663 +3469 y Fl(if)e(insu\016cien)m(t)g(memory)h(w)m(as)h(a)m(v)-5 +b(ailable)572 3573 y Fj(BZ_STREAM_END)663 3677 y Fl(if)29 +b(the)i(logical)e(end)h(of)h(stream)f(w)m(as)h(detected.)572 +3781 y Fj(BZ_OK)663 3884 y Fl(otherwise.)150 4041 y(P)m(ossible)e +(return)h(v)-5 b(alues:)572 4192 y(n)m(um)m(b)s(er)29 +b(of)h(b)m(ytes)h(read)663 4296 y(if)e Fj(bzerror)f Fl(is)i +Fj(BZ_OK)f Fl(or)h Fj(BZ_STREAM_END)572 4400 y Fl(unde\014ned)663 +4503 y(otherwise)150 4660 y(Allo)m(w)m(able)g(next)g(actions:)572 +4811 y(collect)h(data)g(from)f Fj(buf)p Fl(,)f(then)h +Fj(BZ2_bzRead)e Fl(or)i Fj(BZ2_bzReadClose)663 4915 y +Fl(if)f Fj(bzerror)f Fl(is)i Fj(BZ_OK)572 5019 y Fl(collect)h(data)g +(from)f Fj(buf)p Fl(,)f(then)h Fj(BZ2_bzReadClose)d Fl(or)j +Fj(BZ2_bzReadGetUnused)663 5123 y Fl(if)f Fj(bzerror)f +Fl(is)i Fj(BZ_SEQUENCE_END)572 5226 y(BZ2_bzReadClose)663 +5330 y Fl(otherwise)p eop +%%Page: 22 23 +22 22 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(22)150 299 y Ff(3.4.3)63 +b Fe(BZ2_bzReadGetUnused)533 486 y Fj(void)47 b(BZ2_bzReadGetUnused)42 +b(\()48 b(int*)e(bzerror,)g(BZFILE)g(*b,)1822 589 y(void**)g(unused,)g +(int*)g(nUnused)g(\);)150 746 y Fl(Returns)36 b(data)i(whic)m(h)d(w)m +(as)j(read)f(from)f(the)h(compressed)g(\014le)f(but)g(w)m(as)h(not)h +(needed)e(to)i(get)g(to)g(the)150 856 y(logical)k(end-of-stream.)78 +b Fj(*unused)41 b Fl(is)h(set)h(to)g(the)g(address)f(of)g(the)h(data,)k +(and)42 b Fj(*nUnused)e Fl(to)k(the)150 965 y(n)m(um)m(b)s(er)29 +b(of)i(b)m(ytes.)41 b Fj(*nUnused)28 b Fl(will)g(b)s(e)h(set)i(to)g(a)g +(v)-5 b(alue)30 b(b)s(et)m(w)m(een)h Fj(0)f Fl(and)g +Fj(BZ_MAX_UNUSED)d Fl(inclusiv)m(e.)150 1122 y(This)d(function)h(ma)m +(y)h(only)g(b)s(e)f(called)g(once)i Fj(BZ2_bzRead)c Fl(has)j(signalled) +e Fj(BZ_STREAM_END)e Fl(but)j(b)s(efore)150 1232 y Fj(BZ2_bzReadClose)p +Fl(.)150 1389 y(P)m(ossible)k(assignmen)m(ts)h(to)h Fj(bzerror)p +Fl(:)572 1540 y Fj(BZ_PARAM_ERROR)663 1644 y Fl(if)e +Fj(b)h Fl(is)g Fj(NULL)663 1747 y Fl(or)g Fj(unused)f +Fl(is)g Fj(NULL)g Fl(or)i Fj(nUnused)d Fl(is)i Fj(NULL)572 +1851 y(BZ_SEQUENCE_ERROR)663 1955 y Fl(if)f Fj(BZ_STREAM_END)e +Fl(has)j(not)h(b)s(een)e(signalled)663 2059 y(or)h(if)f +Fj(b)h Fl(w)m(as)h(op)s(ened)f(with)f Fj(BZ2_bzWriteOpen)542 +2162 y(BZ_OK)663 2266 y Fl(otherwise)150 2423 y(Allo)m(w)m(able)h(next) +g(actions:)572 2574 y Fj(BZ2_bzReadClose)150 2882 y Ff(3.4.4)63 +b Fe(BZ2_bzReadClose)533 3068 y Fj(void)47 b(BZ2_bzReadClose)c(\()48 +b(int)f(*bzerror,)e(BZFILE)h(*b)h(\);)150 3225 y Fl(Releases)36 +b(all)e(memory)h(p)s(ertaining)e(to)i(the)h(compressed)f(\014le)f +Fj(b)p Fl(.)54 b Fj(BZ2_bzReadClose)31 b Fl(do)s(es)k(not)h(call)150 +3335 y Fj(fclose)c Fl(on)h(the)h(underlying)d(\014le)h(handle,)h(so)h +(y)m(ou)g(should)e(do)h(that)h(y)m(ourself)f(if)g(appropriate.)49 +b Fj(BZ2_)150 3445 y(bzReadClose)27 b Fl(should)i(b)s(e)g(called)h(to)h +(clean)f(up)g(after)h(all)e(error)h(situations.)150 3601 +y(P)m(ossible)f(assignmen)m(ts)h(to)h Fj(bzerror)p Fl(:)572 +3752 y Fj(BZ_SEQUENCE_ERROR)663 3856 y Fl(if)e Fj(b)h +Fl(w)m(as)h(op)s(ened)e(with)h Fj(BZ2_bzOpenWrite)572 +3960 y(BZ_OK)663 4064 y Fl(otherwise)150 4221 y(Allo)m(w)m(able)g(next) +g(actions:)572 4372 y(none)150 4679 y Ff(3.4.5)63 b Fe(BZ2_bzWriteOpen) +533 4866 y Fj(BZFILE)46 b(*BZ2_bzWriteOpen)e(\()j(int)g(*bzerror,)e +(FILE)i(*f,)1774 4970 y(int)g(blockSize100k,)d(int)j(verbosity,)1774 +5074 y(int)g(workFactor)e(\);)150 5230 y Fl(Prepare)33 +b(to)g(write)f(compressed)h(data)h(to)f(\014le)f(handle)g +Fj(f)p Fl(.)47 b Fj(f)33 b Fl(should)e(refer)i(to)g(a)g(\014le)f(whic)m +(h)g(has)h(b)s(een)150 5340 y(op)s(ened)d(for)g(writing,)e(and)i(for)g +(whic)m(h)f(the)i(error)f(indicator)f(\()p Fj(ferror\(f\))p +Fl(\)is)f(not)i(set.)p eop +%%Page: 23 24 +23 23 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(23)150 299 y(F)-8 b(or)31 +b(the)g(meaning)e(of)i(parameters)g Fj(blockSize100k)p +Fl(,)c Fj(verbosity)g Fl(and)j Fj(workFactor)p Fl(,)e(see)150 +408 y Fj(BZ2_bzCompressInit)p Fl(.)150 565 y(All)d(required)f(memory)i +(is)f(allo)s(cated)i(at)g(this)e(stage,)j(so)f(if)e(the)h(call)g +(completes)g(successfully)-8 b(,)26 b Fj(BZ_MEM_)150 +675 y(ERROR)j Fl(cannot)i(b)s(e)f(signalled)e(b)m(y)i(a)h(subsequen)m +(t)f(call)f(to)i Fj(BZ2_bzWrite)p Fl(.)150 832 y(P)m(ossible)e +(assignmen)m(ts)h(to)h Fj(bzerror)p Fl(:)572 983 y Fj(BZ_CONFIG_ERROR) +663 1087 y Fl(if)e(the)i(library)d(has)i(b)s(een)f(mis-compiled)572 +1190 y Fj(BZ_PARAM_ERROR)663 1294 y Fl(if)g Fj(f)h Fl(is)g +Fj(NULL)663 1398 y Fl(or)g Fj(blockSize100k)44 b(<)k(1)30 +b Fl(or)g Fj(blockSize100k)44 b(>)k(9)572 1502 y(BZ_IO_ERROR)663 +1605 y Fl(if)29 b Fj(ferror\(f\))f Fl(is)h(nonzero)572 +1709 y Fj(BZ_MEM_ERROR)663 1813 y Fl(if)g(insu\016cien)m(t)g(memory)h +(is)f(a)m(v)-5 b(ailable)572 1917 y Fj(BZ_OK)663 2021 +y Fl(otherwise)150 2177 y(P)m(ossible)29 b(return)h(v)-5 +b(alues:)572 2328 y(P)m(oin)m(ter)31 b(to)g(an)f(abstract)h +Fj(BZFILE)663 2432 y Fl(if)e Fj(bzerror)f Fl(is)i Fj(BZ_OK)572 +2536 y(NULL)663 2640 y Fl(otherwise)150 2797 y(Allo)m(w)m(able)g(next)g +(actions:)572 2948 y Fj(BZ2_bzWrite)663 3051 y Fl(if)f +Fj(bzerror)f Fl(is)i Fj(BZ_OK)604 3155 y Fl(\(y)m(ou)25 +b(could)e(go)h(directly)f(to)h Fj(BZ2_bzWriteClose)p +Fl(,)c(but)j(this)g(w)m(ould)g(b)s(e)g(prett)m(y)h(p)s(oin)m(tless\)) +572 3259 y Fj(BZ2_bzWriteClose)663 3363 y Fl(otherwise)150 +3639 y Ff(3.4.6)63 b Fe(BZ2_bzWrite)533 3826 y Fj(void)47 +b(BZ2_bzWrite)e(\()i(int)g(*bzerror,)e(BZFILE)h(*b,)h(void)g(*buf,)f +(int)h(len)g(\);)150 3983 y Fl(Absorbs)26 b Fj(len)g +Fl(b)m(ytes)i(from)e(the)i(bu\013er)e Fj(buf)p Fl(,)h(ev)m(en)m(tually) +g(to)h(b)s(e)e(compressed)h(and)f(written)g(to)i(the)g(\014le.)150 +4140 y(P)m(ossible)h(assignmen)m(ts)h(to)h Fj(bzerror)p +Fl(:)572 4291 y Fj(BZ_PARAM_ERROR)663 4395 y Fl(if)e +Fj(b)h Fl(is)g Fj(NULL)f Fl(or)h Fj(buf)g Fl(is)f Fj(NULL)g +Fl(or)i Fj(len)46 b(<)i(0)572 4498 y(BZ_SEQUENCE_ERROR)663 +4602 y Fl(if)29 b(b)h(w)m(as)h(op)s(ened)e(with)g Fj(BZ2_bzReadOpen)572 +4706 y(BZ_IO_ERROR)663 4810 y Fl(if)g(there)i(is)e(an)h(error)g +(writing)f(the)h(compressed)g(\014le.)572 4914 y Fj(BZ_OK)663 +5017 y Fl(otherwise)150 5294 y Ff(3.4.7)63 b Fe(BZ2_bzWriteClose)p +eop +%%Page: 24 25 +24 24 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(24)533 299 y Fj(void)47 +b(BZ2_bzWriteClose)c(\()48 b(int)f(*bzerror,)e(BZFILE*)h(f,)1679 +403 y(int)h(abandon,)1679 506 y(unsigned)e(int*)i(nbytes_in,)1679 +610 y(unsigned)e(int*)i(nbytes_out)e(\);)533 818 y(void)i +(BZ2_bzWriteClose64)c(\()k(int)g(*bzerror,)e(BZFILE*)h(f,)1774 +922 y(int)h(abandon,)1774 1025 y(unsigned)f(int*)g(nbytes_in_lo32,)1774 +1129 y(unsigned)g(int*)g(nbytes_in_hi32,)1774 1233 y(unsigned)g(int*)g +(nbytes_out_lo32,)1774 1337 y(unsigned)g(int*)g(nbytes_out_hi32)e(\);) +150 1493 y Fl(Compresses)39 b(and)g(\015ushes)g(to)h(the)g(compressed)g +(\014le)f(all)f(data)j(so)f(far)g(supplied)c(b)m(y)k +Fj(BZ2_bzWrite)p Fl(.)150 1603 y(The)27 b(logical)g(end-of-stream)h +(mark)m(ers)g(are)g(also)f(written,)h(so)f(subsequen)m(t)g(calls)g(to)h +Fj(BZ2_bzWrite)d Fl(are)150 1713 y(illegal.)50 b(All)33 +b(memory)h(asso)s(ciated)g(with)f(the)i(compressed)e(\014le)h +Fj(b)f Fl(is)g(released.)52 b Fj(fflush)33 b Fl(is)g(called)g(on)150 +1822 y(the)e(compressed)f(\014le,)f(but)h(it)g(is)f(not)i +Fj(fclose)p Fl('d.)150 1979 y(If)i Fj(BZ2_bzWriteClose)c +Fl(is)k(called)f(to)j(clean)e(up)f(after)i(an)g(error,)g(the)g(only)e +(action)i(is)f(to)h(release)g(the)150 2089 y(memory)-8 +b(.)42 b(The)30 b(library)e(records)j(the)g(error)f(co)s(des)h(issued)e +(b)m(y)h(previous)f(calls,)i(so)f(this)g(situation)g(will)150 +2198 y(b)s(e)c(detected)h(automatically)-8 b(.)40 b(There)26 +b(is)g(no)g(attempt)h(to)h(complete)e(the)h(compression)f(op)s +(eration,)g(nor)150 2308 y(to)32 b Fj(fflush)d Fl(the)i(compressed)g +(\014le.)42 b(Y)-8 b(ou)32 b(can)f(force)h(this)e(b)s(eha)m(viour)g(to) +h(happ)s(en)f(ev)m(en)i(in)d(the)j(case)g(of)150 2417 +y(no)e(error,)g(b)m(y)h(passing)e(a)i(nonzero)f(v)-5 +b(alue)30 b(to)h Fj(abandon)p Fl(.)150 2574 y(If)j Fj(nbytes_in)d +Fl(is)j(non-n)m(ull,)f Fj(*nbytes_in)e Fl(will)h(b)s(e)h(set)i(to)g(b)s +(e)f(the)g(total)h(v)m(olume)f(of)g(uncompressed)150 +2684 y(data)k(handled.)60 b(Similarly)-8 b(,)35 b Fj(nbytes_out)g +Fl(will)g(b)s(e)h(set)i(to)g(the)g(total)g(v)m(olume)f(of)g(compressed) +g(data)150 2793 y(written.)h(F)-8 b(or)27 b(compatibilit)m(y)d(with)h +(older)g(v)m(ersions)h(of)g(the)g(library)-8 b(,)25 b +Fj(BZ2_bzWriteClose)d Fl(only)j(yields)150 2903 y(the)40 +b(lo)m(w)m(er)g(32)h(bits)d(of)i(these)h(coun)m(ts.)69 +b(Use)40 b Fj(BZ2_bzWriteClose64)35 b Fl(if)k(y)m(ou)h(w)m(an)m(t)h +(the)f(full)d(64)k(bit)150 3013 y(coun)m(ts.)g(These)30 +b(t)m(w)m(o)i(functions)d(are)i(otherwise)f(absolutely)f(iden)m(tical.) +150 3169 y(P)m(ossible)g(assignmen)m(ts)h(to)h Fj(bzerror)p +Fl(:)572 3320 y Fj(BZ_SEQUENCE_ERROR)663 3424 y Fl(if)e +Fj(b)h Fl(w)m(as)h(op)s(ened)e(with)h Fj(BZ2_bzReadOpen)572 +3528 y(BZ_IO_ERROR)663 3632 y Fl(if)f(there)i(is)e(an)h(error)g +(writing)f(the)h(compressed)g(\014le)572 3736 y Fj(BZ_OK)663 +3839 y Fl(otherwise)150 4161 y Ff(3.4.8)63 b(Handling)41 +b(em)m(b)s(edded)g(compressed)h(data)e(streams)150 4354 +y Fl(The)i(high-lev)m(el)g(library)f(facilitates)h(use)h(of)g +Fj(bzip2)e Fl(data)j(streams)f(whic)m(h)f(form)g(some)i(part)e(of)i(a) +150 4463 y(surrounding,)27 b(larger)j(data)h(stream.)225 +4620 y Fi(\017)60 b Fl(F)-8 b(or)22 b(writing,)f(the)g(library)e(tak)m +(es)k(an)e(op)s(en)f(\014le)g(handle,)i(writes)e(compressed)h(data)h +(to)g(it,)g Fj(fflush)p Fl(es)330 4730 y(it)34 b(but)f(do)s(es)h(not)h +Fj(fclose)d Fl(it.)52 b(The)34 b(calling)f(application)g(can)h(write)g +(its)f(o)m(wn)i(data)g(b)s(efore)f(and)330 4839 y(after)d(the)f +(compressed)h(data)g(stream,)g(using)d(that)j(same)g(\014le)f(handle.) +225 5011 y Fi(\017)60 b Fl(Reading)34 b(is)f(more)i(complex,)g(and)f +(the)h(facilities)d(are)j(not)g(as)g(general)f(as)h(they)f(could)g(b)s +(e)g(since)330 5121 y(generalit)m(y)e(is)f(hard)f(to)j(reconcile)e +(with)f(e\016ciency)-8 b(.)46 b Fj(BZ2_bzRead)29 b Fl(reads)i(from)g +(the)h(compressed)330 5230 y(\014le)39 b(in)g(blo)s(c)m(ks)g(of)h(size) +g Fj(BZ_MAX_UNUSED)c Fl(b)m(ytes,)44 b(and)39 b(in)g(doing)g(so)h +(probably)e(will)f(o)m(v)m(ersho)s(ot)330 5340 y(the)i(logical)g(end)f +(of)h(compressed)f(stream.)67 b(T)-8 b(o)40 b(reco)m(v)m(er)g(this)e +(data)i(once)f(decompression)f(has)p eop +%%Page: 25 26 +25 25 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(25)330 299 y(ended,)28 +b(call)g Fj(BZ2_bzReadGetUnused)23 b Fl(after)29 b(the)g(last)f(call)g +(of)g Fj(BZ2_bzRead)e Fl(\(the)j(one)g(returning)330 +408 y Fj(BZ_STREAM_END)p Fl(\))e(but)j(b)s(efore)g(calling)f +Fj(BZ2_bzReadClose)p Fl(.)150 596 y(This)51 b(mec)m(hanism)g(mak)m(es)j +(it)e(easy)h(to)g(decompress)f(m)m(ultiple)e Fj(bzip2)i +Fl(streams)g(placed)g(end-to-)150 706 y(end.)90 b(As)48 +b(the)f(end)f(of)i(one)f(stream,)52 b(when)46 b Fj(BZ2_bzRead)f +Fl(returns)h Fj(BZ_STREAM_END)p Fl(,)i(call)e Fj(BZ2_)150 +816 y(bzReadGetUnused)36 b Fl(to)41 b(collect)g(the)g(un)m(used)e(data) +i(\(cop)m(y)g(it)f(in)m(to)g(y)m(our)h(o)m(wn)f(bu\013er)f +(somewhere\).)150 925 y(That)25 b(data)g(forms)f(the)h(start)h(of)e +(the)h(next)g(compressed)g(stream.)39 b(T)-8 b(o)25 b(start)h +(uncompressing)c(that)k(next)150 1035 y(stream,)40 b(call)d +Fj(BZ2_bzReadOpen)d Fl(again,)40 b(feeding)d(in)g(the)h(un)m(used)e +(data)j(via)e(the)h Fj(unused)p Fl(/)p Fj(nUnused)150 +1144 y Fl(parameters.)54 b(Keep)34 b(doing)g(this)f(un)m(til)g +Fj(BZ_STREAM_END)e Fl(return)j(coincides)f(with)h(the)g(ph)m(ysical)g +(end)150 1254 y(of)d(\014le)e(\()p Fj(feof\(f\))p Fl(\).)39 +b(In)30 b(this)f(situation)h Fj(BZ2_bzReadGetUnused)25 +b Fl(will)i(of)k(course)g(return)e(no)h(data.)150 1411 +y(This)c(should)f(giv)m(e)j(some)g(feel)f(for)g(ho)m(w)h(the)g +(high-lev)m(el)e(in)m(terface)i(can)f(b)s(e)g(used.)39 +b(If)27 b(y)m(ou)h(require)e(extra)150 1520 y(\015exibilit)m(y)-8 +b(,)28 b(y)m(ou'll)i(ha)m(v)m(e)h(to)g(bite)f(the)h(bullet)d(and)i(get) +i(to)f(grips)e(with)g(the)h(lo)m(w-lev)m(el)h(in)m(terface.)150 +1779 y Ff(3.4.9)63 b(Standard)40 b(\014le-reading/writing)j(co)s(de)150 +1972 y Fl(Here's)31 b(ho)m(w)f(y)m(ou'd)h(write)e(data)j(to)f(a)f +(compressed)g(\014le:)390 2330 y Fj(FILE*)142 b(f;)390 +2434 y(BZFILE*)46 b(b;)390 2538 y(int)238 b(nBuf;)390 +2642 y(char)190 b(buf[)46 b(/*)i(whatever)d(size)i(you)g(like)f(*/)i +(];)390 2746 y(int)238 b(bzerror;)390 2849 y(int)g(nWritten;)390 +3057 y(f)47 b(=)h(fopen)e(\()i("myfile.bz2",)c("w")j(\);)390 +3161 y(if)g(\(!f\))g({)533 3264 y(/*)g(handle)f(error)h(*/)390 +3368 y(})390 3472 y(b)g(=)h(BZ2_bzWriteOpen)c(\()j(&bzerror,)e(f,)i(9)h +(\);)390 3576 y(if)f(\(bzerror)f(!=)h(BZ_OK\))f({)533 +3680 y(BZ2_bzWriteClose)e(\()j(b)g(\);)533 3783 y(/*)g(handle)f(error)h +(*/)390 3887 y(})390 4095 y(while)f(\()i(/*)f(condition)e(*/)i(\))h({) +533 4198 y(/*)f(get)g(data)g(to)g(write)f(into)h(buf,)g(and)g(set)g +(nBuf)f(appropriately)e(*/)533 4302 y(nWritten)i(=)h(BZ2_bzWrite)e(\()i +(&bzerror,)f(b,)h(buf,)f(nBuf)h(\);)533 4406 y(if)g(\(bzerror)f(==)h +(BZ_IO_ERROR\))e({)676 4510 y(BZ2_bzWriteClose)f(\()j(&bzerror,)e(b)j +(\);)676 4614 y(/*)g(handle)e(error)g(*/)533 4717 y(})390 +4821 y(})390 5029 y(BZ2_bzWriteClose)d(\()48 b(&bzerror,)d(b)j(\);)390 +5132 y(if)f(\(bzerror)f(==)h(BZ_IO_ERROR\))d({)533 5236 +y(/*)j(handle)f(error)h(*/)390 5340 y(})p eop +%%Page: 26 27 +26 26 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(26)150 299 y(And)29 b(to)j(read)e(from)g +(a)h(compressed)f(\014le:)390 450 y Fj(FILE*)142 b(f;)390 +554 y(BZFILE*)46 b(b;)390 657 y(int)238 b(nBuf;)390 761 +y(char)190 b(buf[)46 b(/*)i(whatever)d(size)i(you)g(like)f(*/)i(];)390 +865 y(int)238 b(bzerror;)390 969 y(int)g(nWritten;)390 +1176 y(f)47 b(=)h(fopen)e(\()i("myfile.bz2",)c("r")j(\);)390 +1280 y(if)g(\(!f\))g({)533 1384 y(/*)g(handle)f(error)h(*/)390 +1488 y(})390 1591 y(b)g(=)h(BZ2_bzReadOpen)c(\()j(&bzerror,)f(f,)h(0,)g +(NULL,)f(0)i(\);)390 1695 y(if)f(\(bzerror)f(!=)h(BZ_OK\))f({)533 +1799 y(BZ2_bzReadClose)e(\()j(&bzerror,)f(b)h(\);)533 +1903 y(/*)g(handle)f(error)h(*/)390 2007 y(})390 2214 +y(bzerror)f(=)h(BZ_OK;)390 2318 y(while)f(\(bzerror)g(==)h(BZ_OK)f(&&)i +(/*)f(arbitrary)e(other)h(conditions)f(*/\))i({)533 2422 +y(nBuf)g(=)g(BZ2_bzRead)e(\()j(&bzerror,)d(b,)i(buf,)g(/*)g(size)g(of)g +(buf)g(*/)g(\);)533 2525 y(if)g(\(bzerror)f(==)h(BZ_OK\))f({)676 +2629 y(/*)i(do)f(something)e(with)i(buf[0)f(..)h(nBuf-1])f(*/)533 +2733 y(})390 2837 y(})390 2941 y(if)h(\(bzerror)f(!=)h(BZ_STREAM_END\)) +d({)533 3044 y(BZ2_bzReadClose)g(\()j(&bzerror,)f(b)h(\);)533 +3148 y(/*)g(handle)f(error)h(*/)390 3252 y(})g(else)g({)533 +3356 y(BZ2_bzReadClose)d(\()j(&bzerror)f(\);)390 3459 +y(})150 3753 y Fk(3.5)68 b(Utilit)l(y)47 b(functions)150 +4045 y Ff(3.5.1)63 b Fe(BZ2_bzBuffToBuffCompress)533 +4232 y Fj(int)47 b(BZ2_bzBuffToBuffCompress\()41 b(char*)428 +b(dest,)1965 4335 y(unsigned)46 b(int*)g(destLen,)1965 +4439 y(char*)428 b(source,)1965 4543 y(unsigned)46 b(int)94 +b(sourceLen,)1965 4647 y(int)524 b(blockSize100k,)1965 +4751 y(int)g(verbosity,)1965 4854 y(int)g(workFactor)45 +b(\);)150 5011 y Fl(A)m(ttempts)33 b(to)g(compress)f(the)g(data)h(in)e +Fj(source[0)d(..)i(sourceLen-1])e Fl(in)m(to)k(the)h(destination)e +(bu\013er,)150 5121 y Fj(dest[0)e(..)g(*destLen-1])p +Fl(.)37 b(If)26 b(the)g(destination)g(bu\013er)f(is)h(big)f(enough,)j +Fj(*destLen)c Fl(is)h(set)i(to)g(the)g(size)150 5230 +y(of)i(the)f(compressed)h(data,)g(and)f Fj(BZ_OK)f Fl(is)h(returned.)39 +b(If)28 b(the)h(compressed)f(data)h(w)m(on't)g(\014t,)g +Fj(*destLen)150 5340 y Fl(is)g(unc)m(hanged,)i(and)e +Fj(BZ_OUTBUFF_FULL)e Fl(is)i(returned.)p eop +%%Page: 27 28 +27 27 bop 150 -116 a Fl(Chapter)30 b(3:)h(Programming)e(with)g +Fj(libbzip2)1891 b Fl(27)150 299 y(Compression)22 b(in)g(this)h(manner) +g(is)g(a)h(one-shot)g(ev)m(en)m(t,)j(done)c(with)g(a)h(single)e(call)h +(to)i(this)d(function.)37 b(The)150 408 y(resulting)25 +b(compressed)i(data)i(is)d(a)i(complete)f Fj(bzip2)f +Fl(format)i(data)g(stream.)40 b(There)27 b(is)f(no)i(mec)m(hanism)150 +518 y(for)23 b(making)g(additional)e(calls)i(to)h(pro)m(vide)f(extra)h +(input)e(data.)39 b(If)23 b(y)m(ou)h(w)m(an)m(t)g(that)g(kind)e(of)h +(mec)m(hanism,)150 628 y(use)30 b(the)h(lo)m(w-lev)m(el)f(in)m +(terface.)150 784 y(F)-8 b(or)31 b(the)g(meaning)e(of)i(parameters)g +Fj(blockSize100k)p Fl(,)c Fj(verbosity)g Fl(and)j Fj(workFactor)p +Fl(,)150 894 y(see)h Fj(BZ2_bzCompressInit)p Fl(.)150 +1051 y(T)-8 b(o)27 b(guaran)m(tee)h(that)e(the)h(compressed)f(data)h +(will)d(\014t)i(in)f(its)g(bu\013er,)i(allo)s(cate)f(an)g(output)g +(bu\013er)g(of)g(size)150 1160 y(1\045)31 b(larger)f(than)g(the)g +(uncompressed)f(data,)j(plus)c(six)h(h)m(undred)g(extra)i(b)m(ytes.)150 +1317 y Fj(BZ2_bzBuffToBuffDecompre)o(ss)25 b Fl(will)k(not)j(write)e +(data)j(at)f(or)f(b)s(ey)m(ond)g Fj(dest[*destLen])p +Fl(,)d(ev)m(en)k(in)150 1427 y(case)f(of)g(bu\013er)e(o)m(v)m(er\015o)m +(w.)150 1584 y(P)m(ossible)g(return)h(v)-5 b(alues:)572 +1735 y Fj(BZ_CONFIG_ERROR)663 1839 y Fl(if)29 b(the)i(library)d(has)i +(b)s(een)f(mis-compiled)572 1942 y Fj(BZ_PARAM_ERROR)663 +2046 y Fl(if)g Fj(dest)g Fl(is)h Fj(NULL)f Fl(or)h Fj(destLen)f +Fl(is)g Fj(NULL)663 2150 y Fl(or)h Fj(blockSize100k)44 +b(<)k(1)30 b Fl(or)g Fj(blockSize100k)44 b(>)k(9)663 +2254 y Fl(or)30 b Fj(verbosity)45 b(<)j(0)30 b Fl(or)g +Fj(verbosity)45 b(>)j(4)663 2357 y Fl(or)30 b Fj(workFactor)45 +b(<)j(0)30 b Fl(or)g Fj(workFactor)45 b(>)i(250)572 2461 +y(BZ_MEM_ERROR)663 2565 y Fl(if)29 b(insu\016cien)m(t)g(memory)h(is)f +(a)m(v)-5 b(ailable)572 2669 y Fj(BZ_OUTBUFF_FULL)663 +2773 y Fl(if)29 b(the)i(size)f(of)g(the)h(compressed)f(data)h(exceeds)g +Fj(*destLen)572 2876 y(BZ_OK)663 2980 y Fl(otherwise)150 +3349 y Ff(3.5.2)63 b Fe(BZ2_bzBuffToBuffDecompress)533 +3536 y Fj(int)47 b(BZ2_bzBuffToBuffDecompres)o(s)42 b(\()47 +b(char*)428 b(dest,)2108 3640 y(unsigned)46 b(int*)g(destLen,)2108 +3744 y(char*)428 b(source,)2108 3848 y(unsigned)46 b(int)94 +b(sourceLen,)2108 3951 y(int)524 b(small,)2108 4055 y(int)g(verbosity) +46 b(\);)150 4212 y Fl(A)m(ttempts)24 b(to)g(decompress)f(the)g(data)g +(in)f Fj(source[0)28 b(..)i(sourceLen-1])20 b Fl(in)m(to)j(the)g +(destination)f(bu\013er,)150 4322 y Fj(dest[0)29 b(..)g(*destLen-1])p +Fl(.)37 b(If)26 b(the)g(destination)g(bu\013er)f(is)h(big)f(enough,)j +Fj(*destLen)c Fl(is)h(set)i(to)g(the)g(size)150 4431 +y(of)21 b(the)g(uncompressed)e(data,)24 b(and)c Fj(BZ_OK)f +Fl(is)h(returned.)36 b(If)20 b(the)h(compressed)g(data)g(w)m(on't)h +(\014t,)g Fj(*destLen)150 4541 y Fl(is)29 b(unc)m(hanged,)i(and)e +Fj(BZ_OUTBUFF_FULL)e Fl(is)i(returned.)150 4698 y Fj(source)g +Fl(is)g(assumed)h(to)h(hold)e(a)i(complete)f Fj(bzip2)f +Fl(format)i(data)g(stream.)150 4807 y Fj(BZ2_bzBuffToBuffDecompre)o(ss) +22 b Fl(tries)28 b(to)i(decompress)e(the)h(en)m(tiret)m(y)g(of)g(the)f +(stream)h(in)m(to)g(the)f(out-)150 4917 y(put)i(bu\013er.)150 +5074 y(F)-8 b(or)31 b(the)g(meaning)e(of)i(parameters)g +Fj(small)e Fl(and)g Fj(verbosity)p Fl(,)f(see)j Fj +(BZ2_bzDecompressInit)p Fl(.)150 5230 y(Because)j(the)f(compression)e +(ratio)i(of)g(the)g(compressed)f(data)h(cannot)g(b)s(e)f(kno)m(wn)g(in) +g(adv)-5 b(ance,)34 b(there)150 5340 y(is)d(no)h(easy)g(w)m(a)m(y)h(to) +f(guaran)m(tee)i(that)e(the)g(output)f(bu\013er)g(will)e(b)s(e)i(big)g +(enough.)45 b(Y)-8 b(ou)32 b(ma)m(y)h(of)f(course)p eop +%%Page: 28 29 +28 28 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(28)150 299 y(mak)m(e)36 +b(arrangemen)m(ts)f(in)e(y)m(our)i(co)s(de)g(to)g(record)g(the)g(size)f +(of)h(the)g(uncompressed)f(data,)i(but)e(suc)m(h)h(a)150 +408 y(mec)m(hanism)30 b(is)f(b)s(ey)m(ond)h(the)g(scop)s(e)h(of)f(this) +g(library)-8 b(.)150 565 y Fj(BZ2_bzBuffToBuffDecompre)o(ss)25 +b Fl(will)k(not)j(write)e(data)j(at)f(or)f(b)s(ey)m(ond)g +Fj(dest[*destLen])p Fl(,)d(ev)m(en)k(in)150 675 y(case)f(of)g(bu\013er) +e(o)m(v)m(er\015o)m(w.)150 832 y(P)m(ossible)g(return)h(v)-5 +b(alues:)572 983 y Fj(BZ_CONFIG_ERROR)663 1087 y Fl(if)29 +b(the)i(library)d(has)i(b)s(een)f(mis-compiled)572 1190 +y Fj(BZ_PARAM_ERROR)663 1294 y Fl(if)g Fj(dest)g Fl(is)h +Fj(NULL)f Fl(or)h Fj(destLen)f Fl(is)g Fj(NULL)663 1398 +y Fl(or)h Fj(small)46 b(!=)i(0)f(&&)g(small)g(!=)g(1)663 +1502 y Fl(or)30 b Fj(verbosity)45 b(<)j(0)30 b Fl(or)g +Fj(verbosity)45 b(>)j(4)572 1605 y(BZ_MEM_ERROR)663 1709 +y Fl(if)29 b(insu\016cien)m(t)g(memory)h(is)f(a)m(v)-5 +b(ailable)572 1813 y Fj(BZ_OUTBUFF_FULL)663 1917 y Fl(if)29 +b(the)i(size)f(of)g(the)h(compressed)f(data)h(exceeds)g +Fj(*destLen)572 2021 y(BZ_DATA_ERROR)663 2124 y Fl(if)e(a)i(data)g(in)m +(tegrit)m(y)f(error)g(w)m(as)h(detected)h(in)d(the)h(compressed)g(data) +572 2228 y Fj(BZ_DATA_ERROR_MAGIC)663 2332 y Fl(if)f(the)i(compressed)f +(data)h(do)s(esn't)f(b)s(egin)f(with)g(the)i(righ)m(t)e(magic)i(b)m +(ytes)572 2436 y Fj(BZ_UNEXPECTED_EOF)663 2539 y Fl(if)e(the)i +(compressed)f(data)h(ends)e(unexp)s(ectedly)572 2643 +y Fj(BZ_OK)663 2747 y Fl(otherwise)150 3116 y Fk(3.6)68 +b Fd(zlib)43 b Fk(compatibilit)l(y)k(functions)150 3308 +y Fl(Y)-8 b(oshiok)j(a)33 b(Tsuneo)e(has)h(con)m(tributed)g(some)g +(functions)f(to)i(giv)m(e)g(b)s(etter)f Fj(zlib)f Fl(compatibilit)m(y) +-8 b(.)45 b(These)150 3418 y(functions)36 b(are)i Fj(BZ2_bzopen)p +Fl(,)e Fj(BZ2_bzread)p Fl(,)h Fj(BZ2_bzwrite)p Fl(,)f +Fj(BZ2_bzflush)p Fl(,)h Fj(BZ2_bzclose)p Fl(,)f Fj(BZ2_)150 +3527 y(bzerror)23 b Fl(and)h Fj(BZ2_bzlibVersion)p Fl(.)34 +b(These)25 b(functions)e(are)j(not)f(\(y)m(et\))h(o\016cially)e(part)h +(of)g(the)g(library)-8 b(.)150 3637 y(If)30 b(they)g(break,)h(y)m(ou)g +(get)g(to)g(k)m(eep)g(all)f(the)g(pieces.)41 b(Nev)m(ertheless,)31 +b(I)f(think)f(they)i(w)m(ork)f(ok.)390 3788 y Fj(typedef)46 +b(void)g(BZFILE;)390 3995 y(const)g(char)h(*)g(BZ2_bzlibVersion)d(\()j +(void)g(\);)150 4152 y Fl(Returns)29 b(a)i(string)f(indicating)e(the)i +(library)e(v)m(ersion.)390 4303 y Fj(BZFILE)46 b(*)i(BZ2_bzopen)92 +b(\()48 b(const)e(char)h(*path,)f(const)g(char)h(*mode)f(\);)390 +4407 y(BZFILE)g(*)i(BZ2_bzdopen)c(\()k(int)381 b(fd,)190 +b(const)46 b(char)h(*mode)f(\);)150 4564 y Fl(Op)s(ens)19 +b(a)j Fj(.bz2)e Fl(\014le)g(for)g(reading)g(or)h(writing,)g(using)f +(either)g(its)h(name)g(or)g(a)g(pre-existing)f(\014le)g(descriptor.)150 +4674 y(Analogous)30 b(to)i Fj(fopen)c Fl(and)i Fj(fdopen)p +Fl(.)390 4825 y Fj(int)47 b(BZ2_bzread)93 b(\()47 b(BZFILE*)f(b,)h +(void*)f(buf,)h(int)g(len)g(\);)390 4928 y(int)g(BZ2_bzwrite)e(\()i +(BZFILE*)f(b,)h(void*)f(buf,)h(int)g(len)g(\);)150 5085 +y Fl(Reads/writes)30 b(data)h(from/to)g(a)g(previously)d(op)s(ened)i +Fj(BZFILE)p Fl(.)39 b(Analogous)30 b(to)h Fj(fread)e +Fl(and)h Fj(fwrite)p Fl(.)390 5236 y Fj(int)95 b(BZ2_bzflush)44 +b(\()k(BZFILE*)e(b)h(\);)390 5340 y(void)g(BZ2_bzclose)d(\()k(BZFILE*)e +(b)h(\);)p eop +%%Page: 29 30 +29 29 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(29)150 299 y(Flushes/closes)27 +b(a)h Fj(BZFILE)p Fl(.)39 b Fj(BZ2_bzflush)24 b Fl(do)s(esn't)k +(actually)f(do)h(an)m(ything.)39 b(Analogous)28 b(to)h +Fj(fflush)150 408 y Fl(and)h Fj(fclose)p Fl(.)390 559 +y Fj(const)46 b(char)h(*)g(BZ2_bzerror)e(\()j(BZFILE)e(*b,)h(int)g +(*errnum)e(\))150 716 y Fl(Returns)31 b(a)i(string)e(describing)f(the)i +(more)g(recen)m(t)h(error)f(status)h(of)f Fj(b)p Fl(,)g(and)g(also)g +(sets)h Fj(*errnum)d Fl(to)j(its)150 826 y(n)m(umerical)c(v)-5 +b(alue.)150 1242 y Fk(3.7)68 b(Using)46 b(the)f(library)g(in)g(a)g +Fd(stdio)p Fk(-free)f(en)l(vironmen)l(t)150 1615 y Ff(3.7.1)63 +b(Getting)40 b(rid)h(of)g Fe(stdio)150 1807 y Fl(In)i(a)g(deeply)g(em)m +(b)s(edded)f(application,)j(y)m(ou)f(migh)m(t)f(w)m(an)m(t)h(to)g(use)f +(just)g(the)h(memory-to-memory)150 1917 y(functions.)39 +b(Y)-8 b(ou)30 b(can)f(do)g(this)g(con)m(v)m(enien)m(tly)g(b)m(y)g +(compiling)e(the)j(library)d(with)h(prepro)s(cessor)g(sym)m(b)s(ol)150 +2026 y Fj(BZ_NO_STDIO)35 b Fl(de\014ned.)63 b(Doing)39 +b(this)e(giv)m(es)h(y)m(ou)h(a)f(library)e(con)m(taining)i(only)f(the)i +(follo)m(wing)e(eigh)m(t)150 2136 y(functions:)150 2293 +y Fj(BZ2_bzCompressInit)p Fl(,)26 b Fj(BZ2_bzCompress)p +Fl(,)g Fj(BZ2_bzCompressEnd)150 2402 y(BZ2_bzDecompressInit)p +Fl(,)f Fj(BZ2_bzDecompress)p Fl(,)h Fj(BZ2_bzDecompressEnd)150 +2512 y(BZ2_bzBuffToBuffCompress)o Fl(,)f Fj(BZ2_bzBuffToBuffDecompre)o +(ss)150 2669 y Fl(When)30 b(compiled)f(lik)m(e)h(this,)f(all)g +(functions)g(will)f(ignore)i Fj(verbosity)e Fl(settings.)150 +3006 y Ff(3.7.2)63 b(Critical)40 b(error)h(handling)150 +3199 y Fj(libbzip2)20 b Fl(con)m(tains)j(a)g(n)m(um)m(b)s(er)f(of)g(in) +m(ternal)g(assertion)g(c)m(hec)m(ks)i(whic)m(h)d(should,)i(needless)f +(to)h(sa)m(y)-8 b(,)26 b(nev)m(er)150 3308 y(b)s(e)g(activ)-5 +b(ated.)40 b(Nev)m(ertheless,)28 b(if)d(an)i(assertion)f(should)e +(fail,)i(b)s(eha)m(viour)f(dep)s(ends)f(on)j(whether)e(or)i(not)150 +3418 y(the)k(library)d(w)m(as)i(compiled)f(with)g Fj(BZ_NO_STDIO)e +Fl(set.)150 3575 y(F)-8 b(or)31 b(a)g(normal)e(compile,)h(an)g +(assertion)g(failure)f(yields)f(the)j(message)533 3726 +y Fj(bzip2/libbzip2:)44 b(internal)h(error)i(number)f(N.)533 +3829 y(This)h(is)g(a)g(bug)g(in)h(bzip2/libbzip2,)43 +b(1.0)k(of)g(21-Mar-2000.)533 3933 y(Please)f(report)g(it)i(to)f(me)g +(at:)g(jseward@acm.org.)91 b(If)47 b(this)g(happened)533 +4037 y(when)g(you)g(were)f(using)h(some)f(program)g(which)h(uses)f +(libbzip2)g(as)h(a)533 4141 y(component,)e(you)i(should)f(also)h +(report)f(this)h(bug)f(to)i(the)f(author\(s\))533 4244 +y(of)g(that)g(program.)93 b(Please)46 b(make)h(an)g(effort)f(to)h +(report)g(this)f(bug;)533 4348 y(timely)g(and)h(accurate)f(bug)h +(reports)e(eventually)g(lead)i(to)g(higher)533 4452 y(quality)f +(software.)93 b(Thanks.)h(Julian)46 b(Seward,)f(21)j(March)e(2000.)150 +4609 y Fl(where)30 b Fj(N)g Fl(is)f(some)i(error)f(co)s(de)h(n)m(um)m +(b)s(er.)39 b Fj(exit\(3\))28 b Fl(is)i(then)g(called.)150 +4766 y(F)-8 b(or)31 b(a)g Fj(stdio)p Fl(-free)e(library)-8 +b(,)29 b(assertion)h(failures)e(result)i(in)f(a)i(call)e(to)i(a)g +(function)e(declared)h(as:)533 4917 y Fj(extern)46 b(void)h +(bz_internal_error)c(\()k(int)g(errcode)f(\);)150 5074 +y Fl(The)30 b(relev)-5 b(an)m(t)31 b(co)s(de)f(is)g(passed)f(as)i(a)g +(parameter.)41 b(Y)-8 b(ou)31 b(should)d(supply)g(suc)m(h)i(a)h +(function.)150 5230 y(In)g(either)g(case,)j(once)e(an)g(assertion)g +(failure)e(has)h(o)s(ccurred,)h(an)m(y)g Fj(bz_stream)e +Fl(records)h(in)m(v)m(olv)m(ed)h(can)150 5340 y(b)s(e)e(regarded)g(as)h +(in)m(v)-5 b(alid.)38 b(Y)-8 b(ou)31 b(should)d(not)j(attempt)g(to)g +(resume)f(normal)g(op)s(eration)f(with)g(them.)p eop +%%Page: 30 31 +30 30 bop 150 -116 a Fl(Chapter)30 b(3:)41 b(Programming)29 +b(with)g Fj(libbzip2)1881 b Fl(30)150 299 y(Y)-8 b(ou)22 +b(ma)m(y)-8 b(,)25 b(of)d(course,)h(c)m(hange)g(critical)e(error)g +(handling)e(to)j(suit)f(y)m(our)g(needs.)38 b(As)21 b(I)h(said)e(ab)s +(o)m(v)m(e,)25 b(critical)150 408 y(errors)30 b(indicate)g(bugs)g(in)g +(the)h(library)d(and)i(should)f(not)i(o)s(ccur.)42 b(All)29 +b Fj(")p Fl(normal)p Fj(")h Fl(error)g(situations)g(are)150 +518 y(indicated)f(via)h(error)g(return)f(co)s(des)i(from)f(functions,)f +(and)g(can)i(b)s(e)f(reco)m(v)m(ered)i(from.)150 798 +y Fk(3.8)68 b(Making)45 b(a)g(Windo)l(ws)h(DLL)150 990 +y Fl(Ev)m(erything)30 b(related)g(to)h(Windo)m(ws)f(has)g(b)s(een)f +(con)m(tributed)h(b)m(y)g(Y)-8 b(oshiok)j(a)31 b(Tsuneo)150 +1100 y(\()p Fj(QWF00133@niftyserve.or.jp)46 b Fl(/)52 +b Fj(tsuneo-y@is.aist-nara.ac.j)o(p)p Fl(\),)g(so)h(y)m(ou)f(should)f +(send)150 1210 y(y)m(our)30 b(queries)g(to)h(him)e(\(but)h(p)s(erhaps)e +(Cc:)41 b(me,)31 b Fj(jseward@acm.org)p Fl(\).)150 1366 +y(My)43 b(v)-5 b(ague)44 b(understanding)d(of)i(what)g(to)h(do)f(is:)65 +b(using)41 b(Visual)h(C)p Fj(++)g Fl(5.0,)48 b(op)s(en)42 +b(the)h(pro)5 b(ject)44 b(\014le)150 1476 y Fj(libbz2.dsp)p +Fl(,)28 b(and)i(build.)37 b(That's)31 b(all.)150 1633 +y(If)41 b(y)m(ou)g(can't)h(op)s(en)e(the)h(pro)5 b(ject)42 +b(\014le)e(for)h(some)g(reason,)j(mak)m(e)e(a)g(new)e(one,)k(naming)c +(these)i(\014les:)150 1742 y Fj(blocksort.c)p Fl(,)28 +b Fj(bzlib.c)p Fl(,)g Fj(compress.c)p Fl(,)g Fj(crctable.c)p +Fl(,)g Fj(decompress.c)p Fl(,)f Fj(huffman.c)p Fl(,)150 +1852 y Fj(randtable.c)32 b Fl(and)j Fj(libbz2.def)p Fl(.)53 +b(Y)-8 b(ou)36 b(will)d(also)i(need)g(to)h(name)g(the)g(header)f +(\014les)f Fj(bzlib.h)g Fl(and)150 1962 y Fj(bzlib_private.h)p +Fl(.)150 2118 y(If)c(y)m(ou)h(don't)f(use)g(V)m(C)p Fj(++)p +Fl(,)g(y)m(ou)h(ma)m(y)g(need)f(to)h(de\014ne)f(the)h(propro)s(cessor)e +(sym)m(b)s(ol)g Fj(_WIN32)p Fl(.)150 2275 y(Finally)-8 +b(,)28 b Fj(dlltest.c)e Fl(is)h(a)i(sample)f(program)g(using)g(the)g +(DLL.)h(It)g(has)f(a)h(pro)5 b(ject)29 b(\014le,)g Fj(dlltest.dsp)p +Fl(.)150 2432 y(If)h(y)m(ou)h(just)e(w)m(an)m(t)j(a)e(mak)m(e\014le)h +(for)f(Visual)f(C,)h(ha)m(v)m(e)i(a)e(lo)s(ok)g(at)i +Fj(makefile.msc)p Fl(.)150 2589 y(Be)k(a)m(w)m(are)g(that)g(if)e(y)m +(ou)h(compile)f Fj(bzip2)g Fl(itself)g(on)h(Win32,)h(y)m(ou)g(m)m(ust)f +(set)g Fj(BZ_UNIX)e Fl(to)j(0)f(and)g Fj(BZ_)150 2698 +y(LCCWIN32)27 b Fl(to)j(1,)g(in)f(the)g(\014le)g Fj(bzip2.c)p +Fl(,)e(b)s(efore)i(compiling.)39 b(Otherwise)28 b(the)h(resulting)f +(binary)f(w)m(on't)150 2808 y(w)m(ork)j(correctly)-8 +b(.)150 2965 y(I)30 b(ha)m(v)m(en't)i(tried)d(an)m(y)i(of)g(this)e +(stu\013)h(m)m(yself,)g(but)g(it)f(all)h(lo)s(oks)g(plausible.)p +eop +%%Page: 31 32 +31 31 bop 150 -116 a Fl(Chapter)30 b(4:)41 b(Miscellanea)2586 +b(31)150 299 y Fh(4)80 b(Miscellanea)150 583 y Fl(These)30 +b(are)h(just)f(some)g(random)g(though)m(ts)h(of)f(mine.)40 +b(Y)-8 b(our)30 b(mileage)h(ma)m(y)g(v)-5 b(ary)d(.)150 +884 y Fk(4.1)68 b(Limitations)47 b(of)e(the)g(compressed)g(\014le)h +(format)150 1077 y Fj(bzip2-1.0)p Fl(,)e Fj(0.9.5)e Fl(and)g +Fj(0.9.0)g Fl(use)h(exactly)h(the)f(same)h(\014le)e(format)i(as)f(the)h +(previous)d(v)m(ersion,)150 1186 y Fj(bzip2-0.1)p Fl(.)75 +b(This)41 b(decision)g(w)m(as)i(made)g(in)e(the)i(in)m(terests)g(of)g +(stabilit)m(y)-8 b(.)77 b(Creating)42 b(y)m(et)i(another)150 +1296 y(incompatible)21 b(compressed)i(\014le)f(format)i(w)m(ould)e +(create)i(further)e(confusion)g(and)h(disruption)d(for)j(users.)150 +1453 y(Nev)m(ertheless,)31 b(this)e(is)g(not)h(a)g(painless)e +(decision.)39 b(Dev)m(elopmen)m(t)31 b(w)m(ork)f(since)f(the)h(release) +h(of)f Fj(bzip2-)150 1562 y(0.1)19 b Fl(in)g(August)i(1997)h(has)e(sho) +m(wn)f(complexities)h(in)f(the)h(\014le)g(format)g(whic)m(h)f(slo)m(w)h +(do)m(wn)g(decompression)150 1672 y(and,)30 b(in)f(retrosp)s(ect,)i +(are)g(unnecessary)-8 b(.)40 b(These)31 b(are:)225 1829 +y Fi(\017)60 b Fl(The)20 b(run-length)g(enco)s(der,)i(whic)m(h)e(is)g +(the)h(\014rst)f(of)h(the)g(compression)f(transformations,)i(is)e(en)m +(tirely)330 1938 y(irrelev)-5 b(an)m(t.)63 b(The)38 b(original)e(purp)s +(ose)g(w)m(as)j(to)g(protect)g(the)f(sorting)g(algorithm)f(from)g(the)i +(v)m(ery)330 2048 y(w)m(orst)h(case)h(input:)58 b(a)41 +b(string)e(of)h(rep)s(eated)g(sym)m(b)s(ols.)68 b(But)40 +b(algorithm)f(steps)h(Q6a)h(and)e(Q6b)330 2157 y(in)30 +b(the)i(original)e(Burro)m(ws-Wheeler)i(tec)m(hnical)g(rep)s(ort)f +(\(SR)m(C-124\))i(sho)m(w)f(ho)m(w)g(rep)s(eats)g(can)g(b)s(e)330 +2267 y(handled)c(without)i(di\016cult)m(y)f(in)g(blo)s(c)m(k)h +(sorting.)225 2409 y Fi(\017)60 b Fl(The)30 b(randomisation)e(mec)m +(hanism)i(do)s(esn't)g(really)f(need)h(to)g(b)s(e)g(there.)41 +b(Udi)29 b(Man)m(b)s(er)h(and)f(Gene)330 2518 y(My)m(ers)j(published)c +(a)33 b(su\016x)e(arra)m(y)h(construction)f(algorithm)g(a)h(few)g(y)m +(ears)h(bac)m(k,)g(whic)m(h)d(can)j(b)s(e)330 2628 y(emplo)m(y)m(ed)27 +b(to)h(sort)g(an)m(y)f(blo)s(c)m(k,)h(no)f(matter)h(ho)m(w)f(rep)s +(etitiv)m(e,)h(in)d(O\(N)j(log)f(N\))h(time.)39 b(Subsequen)m(t)330 +2737 y(w)m(ork)25 b(b)m(y)f(Kunihik)m(o)f(Sadak)-5 b(ane)24 +b(has)h(pro)s(duced)e(a)i(deriv)-5 b(ativ)m(e)24 b(O\(N)h(\(log)g(N\))p +Fj(^)p Fl(2\))h(algorithm)d(whic)m(h)330 2847 y(usually)28 +b(outp)s(erforms)h(the)i(Man)m(b)s(er-My)m(ers)g(algorithm.)330 +2988 y(I)g(could)g(ha)m(v)m(e)i(c)m(hanged)f(to)g(Sadak)-5 +b(ane's)32 b(algorithm,)f(but)g(I)g(\014nd)f(it)h(to)h(b)s(e)f(slo)m(w) +m(er)h(than)f Fj(bzip2)p Fl('s)330 3098 y(existing)38 +b(algorithm)g(for)h(most)h(inputs,)f(and)g(the)g(randomisation)f(mec)m +(hanism)g(protects)i(ade-)330 3208 y(quately)34 b(against)f(bad)g +(cases.)52 b(I)33 b(didn't)f(think)g(it)i(w)m(as)g(a)g(go)s(o)s(d)f +(tradeo\013)i(to)f(mak)m(e.)51 b(P)m(artly)34 b(this)330 +3317 y(is)39 b(due)h(to)h(the)f(fact)h(that)g(I)f(w)m(as)g(not)h(\015o) +s(o)s(ded)e(with)g(email)g(complain)m(ts)g(ab)s(out)h +Fj(bzip2-0.1)p Fl('s)330 3427 y(p)s(erformance)30 b(on)g(rep)s(etitiv)m +(e)g(data,)h(so)g(p)s(erhaps)d(it)i(isn't)g(a)h(problem)d(for)j(real)f +(inputs.)330 3568 y(Probably)i(the)h(b)s(est)g(long-term)g(solution,)g +(and)g(the)g(one)h(I)f(ha)m(v)m(e)h(incorp)s(orated)e(in)m(to)i(0.9.5)h +(and)330 3678 y(ab)s(o)m(v)m(e,)42 b(is)c(to)h(use)f(the)h(existing)f +(sorting)g(algorithm)f(initially)-8 b(,)38 b(and)g(fall)f(bac)m(k)i(to) +h(a)f(O\(N)f(\(log)330 3787 y(N\))p Fj(^)p Fl(2\))31 +b(algorithm)f(if)f(the)i(standard)e(algorithm)h(gets)h(in)m(to)f +(di\016culties.)225 3929 y Fi(\017)60 b Fl(The)31 b(compressed)f +(\014le)g(format)i(w)m(as)f(nev)m(er)h(designed)d(to)j(b)s(e)f(handled) +e(b)m(y)i(a)g(library)-8 b(,)29 b(and)i(I)g(ha)m(v)m(e)330 +4039 y(had)d(to)i(jump)e(though)g(some)i(ho)s(ops)e(to)i(pro)s(duce)e +(an)h(e\016cien)m(t)g(implemen)m(tation)f(of)h(decompres-)330 +4148 y(sion.)38 b(It's)26 b(a)h(bit)e(hairy)-8 b(.)38 +b(T)-8 b(ry)26 b(passing)f Fj(decompress.c)d Fl(through)k(the)g(C)f +(prepro)s(cessor)g(and)h(y)m(ou'll)330 4258 y(see)32 +b(what)g(I)f(mean.)45 b(Muc)m(h)32 b(of)g(this)e(complexit)m(y)i(could) +f(ha)m(v)m(e)i(b)s(een)e(a)m(v)m(oided)h(if)e(the)i(compressed)330 +4367 y(size)e(of)h(eac)m(h)g(blo)s(c)m(k)f(of)h(data)g(w)m(as)g +(recorded)f(in)f(the)h(data)h(stream.)225 4509 y Fi(\017)60 +b Fl(An)30 b(Adler-32)g(c)m(hec)m(ksum,)i(rather)e(than)g(a)h(CR)m(C32) +g(c)m(hec)m(ksum,)g(w)m(ould)e(b)s(e)h(faster)h(to)g(compute.)150 +4698 y(It)e(w)m(ould)f(b)s(e)g(fair)g(to)h(sa)m(y)h(that)g(the)f +Fj(bzip2)e Fl(format)i(w)m(as)h(frozen)f(b)s(efore)f(I)h(prop)s(erly)d +(and)j(fully)d(under-)150 4807 y(sto)s(o)s(d)k(the)h(p)s(erformance)e +(consequences)i(of)g(doing)e(so.)150 4964 y(Impro)m(v)m(emen)m(ts)d +(whic)m(h)e(I)i(w)m(as)g(able)f(to)h(incorp)s(orate)f(in)m(to)g(0.9.0,) +k(despite)24 b(using)g(the)i(same)g(\014le)e(format,)150 +5074 y(are:)225 5230 y Fi(\017)60 b Fl(Single)30 b(arra)m(y)i(implemen) +m(tation)e(of)h(the)h(in)m(v)m(erse)f(BWT.)h(This)e(signi\014can)m(tly) +f(sp)s(eeds)i(up)f(decom-)330 5340 y(pression,)f(presumably)f(b)s +(ecause)i(it)g(reduces)g(the)h(n)m(um)m(b)s(er)e(of)i(cac)m(he)h +(misses.)p eop +%%Page: 32 33 +32 32 bop 150 -116 a Fl(Chapter)30 b(4:)41 b(Miscellanea)2586 +b(32)225 299 y Fi(\017)60 b Fl(F)-8 b(aster)27 b(in)m(v)m(erse)e(MTF)h +(transform)f(for)g(large)h(MTF)f(v)-5 b(alues.)39 b(The)25 +b(new)g(implemen)m(tation)f(is)g(based)330 408 y(on)30 +b(the)h(notion)f(of)g(sliding)e(blo)s(c)m(ks)h(of)i(v)-5 +b(alues.)225 544 y Fi(\017)60 b Fj(bzip2-0.9.0)24 b Fl(no)m(w)k(reads)f +(and)f(writes)h(\014les)f(with)g Fj(fread)g Fl(and)h +Fj(fwrite)p Fl(;)f(v)m(ersion)h(0.1)i(used)d Fj(putc)330 +653 y Fl(and)k Fj(getc)p Fl(.)39 b(Duh!)h(W)-8 b(ell,)31 +b(y)m(ou)f(liv)m(e)g(and)g(learn.)150 836 y(F)-8 b(urther)30 +b(ahead,)g(it)f(w)m(ould)g(b)s(e)g(nice)h(to)g(b)s(e)g(able)f(to)i(do)e +(random)g(access)j(in)m(to)d(\014les.)40 b(This)28 b(will)f(require)150 +945 y(some)k(careful)e(design)h(of)g(compressed)g(\014le)g(formats.)150 +1227 y Fk(4.2)68 b(P)l(ortabilit)l(y)47 b(issues)150 +1419 y Fl(After)36 b(some)g(consideration,)g(I)f(ha)m(v)m(e)i(decided)d +(not)i(to)g(use)g(GNU)g Fj(autoconf)d Fl(to)j(con\014gure)g(0.9.5)h(or) +150 1529 y(1.0.)150 1686 y Fj(autoconf)p Fl(,)31 b(admirable)g(and)h(w) +m(onderful)f(though)i(it)f(is,)h(mainly)d(assists)j(with)e(p)s +(ortabilit)m(y)g(problems)150 1795 y(b)s(et)m(w)m(een)f(Unix-lik)m(e)d +(platforms.)40 b(But)29 b Fj(bzip2)f Fl(do)s(esn't)h(ha)m(v)m(e)h(m)m +(uc)m(h)f(in)f(the)h(w)m(a)m(y)h(of)g(p)s(ortabilit)m(y)d(prob-)150 +1905 y(lems)35 b(on)h(Unix;)j(most)d(of)g(the)h(di\016culties)d(app)s +(ear)h(when)g(p)s(orting)g(to)i(the)f(Mac,)j(or)d(to)h(Microsoft's)150 +2015 y(op)s(erating)26 b(systems.)40 b Fj(autoconf)25 +b Fl(do)s(esn't)h(help)g(in)f(those)j(cases,)h(and)d(brings)f(in)g(a)j +(whole)e(load)g(of)h(new)150 2124 y(complexit)m(y)-8 +b(.)150 2281 y(Most)28 b(p)s(eople)f(should)f(b)s(e)h(able)g(to)h +(compile)e(the)i(library)d(and)i(program)h(under)e(Unix)g(straigh)m(t)i +(out-of-)150 2391 y(the-b)s(o)m(x,)j(so)g(to)g(sp)s(eak,)f(esp)s +(ecially)f(if)g(y)m(ou)i(ha)m(v)m(e)g(a)g(v)m(ersion)f(of)g(GNU)h(C)f +(a)m(v)-5 b(ailable.)150 2547 y(There)32 b(are)h(a)g(couple)f(of)h +Fj(__inline__)d Fl(directiv)m(es)i(in)f(the)i(co)s(de.)48 +b(GNU)33 b(C)f(\()p Fj(gcc)p Fl(\))g(should)f(b)s(e)h(able)g(to)150 +2657 y(handle)24 b(them.)39 b(If)25 b(y)m(ou're)i(not)e(using)g(GNU)h +(C,)f(y)m(our)h(C)f(compiler)f(shouldn't)g(see)i(them)f(at)i(all.)38 +b(If)25 b(y)m(our)150 2767 y(compiler)k(do)s(es,)i(for)g(some)g +(reason,)h(see)f(them)g(and)f(do)s(esn't)h(lik)m(e)f(them,)i(just)e +Fj(#define)f(__inline__)150 2876 y Fl(to)37 b(b)s(e)f +Fj(/*)30 b(*/)p Fl(.)58 b(One)36 b(easy)h(w)m(a)m(y)g(to)h(do)e(this)f +(is)h(to)h(compile)e(with)g(the)i(\015ag)g Fj(-D__inline__=)p +Fl(,)d(whic)m(h)150 2986 y(should)28 b(b)s(e)i(understo)s(o)s(d)f(b)m +(y)h(most)h(Unix)e(compilers.)150 3143 y(If)35 b(y)m(ou)g(still)e(ha)m +(v)m(e)j(di\016culties,)e(try)h(compiling)e(with)g(the)j(macro)f +Fj(BZ_STRICT_ANSI)c Fl(de\014ned.)54 b(This)150 3252 +y(should)28 b(enable)i(y)m(ou)h(to)g(build)d(the)i(library)e(in)h(a)i +(strictly)f(ANSI)g(complian)m(t)f(en)m(vironmen)m(t.)41 +b(Building)150 3362 y(the)25 b(program)f(itself)f(lik)m(e)g(this)h(is)f +(dangerous)h(and)g(not)g(supp)s(orted,)g(since)g(y)m(ou)h(remo)m(v)m(e) +g Fj(bzip2)p Fl('s)e(c)m(hec)m(ks)150 3471 y(against)30 +b(compressing)f(directories,)g(sym)m(b)s(olic)g(links,)f(devices,)i +(and)f(other)h(not-really-a-\014le)g(en)m(tities.)150 +3581 y(This)f(could)g(cause)i(\014lesystem)f(corruption!)150 +3738 y(One)e(other)i(thing:)39 b(if)27 b(y)m(ou)j(create)g(a)f +Fj(bzip2)f Fl(binary)f(for)i(public)d(distribution,)g(please)i(try)h +(and)g(link)d(it)150 3847 y(statically)g(\()p Fj(gcc)k(-s)p +Fl(\).)39 b(This)25 b(a)m(v)m(oids)i(all)f(sorts)h(of)g(library-v)m +(ersion)d(issues)h(that)i(others)g(ma)m(y)g(encoun)m(ter)150 +3957 y(later)j(on.)150 4114 y(If)f(y)m(ou)g(build)e Fj(bzip2)h +Fl(on)h(Win32,)h(y)m(ou)f(m)m(ust)g(set)h Fj(BZ_UNIX)e +Fl(to)i(0)f(and)g Fj(BZ_LCCWIN32)d Fl(to)k(1,)g(in)e(the)i(\014le)150 +4223 y Fj(bzip2.c)p Fl(,)f(b)s(efore)h(compiling.)38 +b(Otherwise)29 b(the)i(resulting)d(binary)h(w)m(on't)i(w)m(ork)f +(correctly)-8 b(.)150 4505 y Fk(4.3)68 b(Rep)t(orting)46 +b(bugs)150 4698 y Fl(I)25 b(tried)f(prett)m(y)i(hard)e(to)i(mak)m(e)g +(sure)f Fj(bzip2)e Fl(is)i(bug)f(free,)j(b)s(oth)d(b)m(y)h(design)f +(and)h(b)m(y)g(testing.)39 b(Hop)s(efully)150 4807 y(y)m(ou'll)29 +b(nev)m(er)i(need)f(to)h(read)g(this)e(section)h(for)h(real.)150 +4964 y(Nev)m(ertheless,)36 b(if)c Fj(bzip2)h Fl(dies)g(with)f(a)i +(segmen)m(tation)h(fault,)g(a)f(bus)f(error)g(or)h(an)g(in)m(ternal)e +(assertion)150 5074 y(failure,)i(it)h(will)d(ask)j(y)m(ou)g(to)g(email) +f(me)h(a)g(bug)f(rep)s(ort.)54 b(Exp)s(erience)33 b(with)h(v)m(ersion)g +(0.1)i(sho)m(ws)e(that)150 5183 y(almost)c(all)g(these)h(problems)d +(can)j(b)s(e)f(traced)h(to)g(either)f(compiler)e(bugs)i(or)g(hardw)m +(are)g(problems.)225 5340 y Fi(\017)60 b Fl(Recompile)22 +b(the)h(program)g(with)f(no)h(optimisation,)g(and)f(see)i(if)e(it)g(w)m +(orks.)39 b(And/or)22 b(try)h(a)g(di\013eren)m(t)p eop +%%Page: 33 34 +33 33 bop 150 -116 a Fl(Chapter)30 b(4:)41 b(Miscellanea)2586 +b(33)330 299 y(compiler.)77 b(I)43 b(heard)f(all)g(sorts)h(of)h +(stories)e(ab)s(out)h(v)-5 b(arious)42 b(\015a)m(v)m(ours)h(of)h(GNU)f +(C)g(\(and)g(other)330 408 y(compilers\))20 b(generating)i(bad)e(co)s +(de)i(for)f Fj(bzip2)p Fl(,)h(and)f(I'v)m(e)h(run)e(across)i(t)m(w)m(o) +g(suc)m(h)f(examples)g(m)m(yself.)330 606 y(2.7.X)35 +b(v)m(ersions)e(of)g(GNU)h(C)f(are)h(kno)m(wn)f(to)h(generate)h(bad)d +(co)s(de)i(from)f(time)g(to)h(time,)g(at)g(high)330 716 +y(optimisation)20 b(lev)m(els.)37 b(If)21 b(y)m(ou)g(get)i(problems,)e +(try)g(using)f(the)i(\015ags)f Fj(-O2)f(-fomit-frame-pointer)330 +825 y(-fno-strength-reduce)p Fl(.)35 b(Y)-8 b(ou)31 b(should)d(sp)s +(eci\014cally)h Fc(not)j Fl(use)e Fj(-funroll-loops)p +Fl(.)330 1023 y(Y)-8 b(ou)38 b(ma)m(y)g(notice)g(that)g(the)g(Mak)m +(e\014le)g(runs)e(six)g(tests)i(as)g(part)f(of)h(the)g(build)c(pro)s +(cess.)62 b(If)37 b(the)330 1132 y(program)43 b(passes)g(all)f(of)h +(these,)k(it's)c(a)h(prett)m(y)f(go)s(o)s(d)g(\(but)g(not)g(100\045\))i +(indication)c(that)j(the)330 1242 y(compiler)29 b(has)h(done)g(its)g +(job)g(correctly)-8 b(.)225 1440 y Fi(\017)60 b Fl(If)33 +b Fj(bzip2)f Fl(crashes)i(randomly)-8 b(,)33 b(and)g(the)h(crashes)g +(are)g(not)g(rep)s(eatable,)g(y)m(ou)g(ma)m(y)g(ha)m(v)m(e)h(a)f +(\015aky)330 1549 y(memory)k(subsystem.)64 b Fj(bzip2)37 +b Fl(really)g(hammers)h(y)m(our)g(memory)g(hierarc)m(h)m(y)-8 +b(,)41 b(and)d(if)f(it's)h(a)h(bit)330 1659 y(marginal,)33 +b(y)m(ou)h(ma)m(y)g(get)h(these)f(problems.)49 b(Ditto)34 +b(if)f(y)m(our)h(disk)e(or)h(I/O)h(subsystem)e(is)h(slo)m(wly)330 +1768 y(failing.)39 b(Y)-8 b(up,)30 b(this)f(really)g(do)s(es)h(happ)s +(en.)330 1966 y(T)-8 b(ry)28 b(using)f(a)i(di\013eren)m(t)f(mac)m(hine) +g(of)h(the)g(same)f(t)m(yp)s(e,)i(and)e(see)h(if)e(y)m(ou)i(can)g(rep)s +(eat)g(the)f(problem.)225 2163 y Fi(\017)60 b Fl(This)21 +b(isn't)i(really)f(a)h(bug,)i(but)d(...)39 b(If)23 b +Fj(bzip2)f Fl(tells)g(y)m(ou)h(y)m(our)h(\014le)e(is)g(corrupted)h(on)g +(decompression,)330 2273 y(and)29 b(y)m(ou)g(obtained)f(the)i(\014le)e +(via)h(FTP)-8 b(,)29 b(there)h(is)e(a)h(p)s(ossibilit)m(y)d(that)k(y)m +(ou)f(forgot)h(to)g(tell)e(FTP)h(to)330 2383 y(do)23 +b(a)g(binary)e(mo)s(de)i(transfer.)38 b(That)23 b(absolutely)f(will)e +(cause)j(the)h(\014le)e(to)h(b)s(e)g(non-decompressible.)330 +2492 y(Y)-8 b(ou'll)30 b(ha)m(v)m(e)h(to)g(transfer)f(it)g(again.)150 +2737 y(If)i(y)m(ou'v)m(e)h(incorp)s(orated)e Fj(libbzip2)f +Fl(in)m(to)i(y)m(our)g(o)m(wn)g(program)g(and)g(are)g(getting)h +(problems,)e(please,)150 2847 y(please,)d(please,)h(c)m(hec)m(k)g(that) +f(the)g(parameters)g(y)m(ou)g(are)g(passing)f(in)f(calls)h(to)h(the)g +(library)-8 b(,)26 b(are)j(correct,)150 2956 y(and)e(in)f(accordance)k +(with)c(what)i(the)g(do)s(cumen)m(tation)f(sa)m(ys)h(is)f(allo)m(w)m +(able.)39 b(I)28 b(ha)m(v)m(e)h(tried)e(to)h(mak)m(e)h(the)150 +3066 y(library)f(robust)i(against)g(suc)m(h)g(problems,)f(but)h(I'm)g +(sure)g(I)g(ha)m(v)m(en't)h(succeeded.)150 3223 y(Finally)-8 +b(,)32 b(if)g(the)h(ab)s(o)m(v)m(e)i(commen)m(ts)e(don't)g(help,)g(y)m +(ou'll)f(ha)m(v)m(e)i(to)g(send)e(me)h(a)g(bug)g(rep)s(ort.)48 +b(No)m(w,)34 b(it's)150 3332 y(just)c(amazing)g(ho)m(w)h(man)m(y)f(p)s +(eople)g(will)d(send)j(me)g(a)h(bug)f(rep)s(ort)g(sa)m(ying)g +(something)g(lik)m(e)481 3483 y(bzip2)f(crashed)h(with)f(segmen)m +(tation)j(fault)e(on)g(m)m(y)g(mac)m(hine)150 3640 y(and)h(absolutely)f +(nothing)h(else.)44 b(Needless)32 b(to)g(sa)m(y)-8 b(,)33 +b(a)f(suc)m(h)f(a)h(rep)s(ort)f(is)g Fc(totally)-8 b(,)32 +b(utterly)-8 b(,)32 b(completely)150 3750 y(and)40 b(comprehensiv)m +(ely)g(100\045)h(useless;)46 b(a)41 b(w)m(aste)g(of)g(y)m(our)g(time,)i +(m)m(y)e(time,)i(and)e(net)g(bandwidth)p Fl(.)150 3859 +y(With)31 b(no)h(details)f(at)i(all,)e(there's)h(no)g(w)m(a)m(y)h(I)f +(can)g(p)s(ossibly)d(b)s(egin)h(to)j(\014gure)e(out)i(what)e(the)i +(problem)150 3969 y(is.)150 4126 y(The)d(rules)e(of)i(the)g(game)h +(are:)41 b(facts,)32 b(facts,)f(facts.)41 b(Don't)31 +b(omit)f(them)g(b)s(ecause)g Fj(")p Fl(oh,)g(they)g(w)m(on't)h(b)s(e) +150 4235 y(relev)-5 b(an)m(t)p Fj(")p Fl(.)41 b(A)m(t)31 +b(the)g(bare)f(minim)m(um:)481 4386 y(Mac)m(hine)h(t)m(yp)s(e.)61 +b(Op)s(erating)29 b(system)h(v)m(ersion.)481 4490 y(Exact)h(v)m(ersion) +f(of)h Fj(bzip2)e Fl(\(do)h Fj(bzip2)47 b(-V)p Fl(\).)481 +4594 y(Exact)31 b(v)m(ersion)f(of)h(the)f(compiler)f(used.)481 +4698 y(Flags)i(passed)e(to)j(the)e(compiler.)150 4854 +y(Ho)m(w)m(ev)m(er,)i(the)d(most)h(imp)s(ortan)m(t)f(single)f(thing)g +(that)i(will)d(help)h(me)h(is)f(the)i(\014le)e(that)i(y)m(ou)g(w)m(ere) +g(trying)150 4964 y(to)f(compress)f(or)g(decompress)g(at)h(the)f(time)g +(the)g(problem)f(happ)s(ened.)38 b(Without)28 b(that,)h(m)m(y)g(abilit) +m(y)d(to)150 5074 y(do)k(an)m(ything)g(more)h(than)f(sp)s(eculate)g(ab) +s(out)g(the)g(cause,)i(is)d(limited.)150 5230 y(Please)34 +b(remem)m(b)s(er)f(that)h(I)f(connect)i(to)f(the)g(In)m(ternet)g(with)e +(a)i(mo)s(dem,)g(so)f(y)m(ou)h(should)e(con)m(tact)k(me)150 +5340 y(b)s(efore)30 b(mailing)e(me)j(h)m(uge)f(\014les.)p +eop +%%Page: 34 35 +34 34 bop 150 -116 a Fl(Chapter)30 b(4:)41 b(Miscellanea)2586 +b(34)150 299 y Fk(4.4)68 b(Did)45 b(y)l(ou)g(get)h(the)f(righ)l(t)h +(pac)l(k)-7 b(age?)150 491 y Fj(bzip2)34 b Fl(is)h(a)h(resource)g(hog.) +56 b(It)36 b(soaks)g(up)f(large)g(amoun)m(ts)h(of)g(CPU)f(cycles)h(and) +f(memory)-8 b(.)57 b(Also,)36 b(it)150 601 y(giv)m(es)26 +b(v)m(ery)h(large)f(latencies.)39 b(In)25 b(the)h(w)m(orst)g(case,)i(y) +m(ou)f(can)f(feed)g(man)m(y)g(megab)m(ytes)h(of)f(uncompressed)150 +711 y(data)45 b(in)m(to)e(the)i(library)c(b)s(efore)j(getting)g(an)m(y) +g(compressed)g(output,)j(so)d(this)f(probably)f(rules)h(out)150 +820 y(applications)29 b(requiring)e(in)m(teractiv)m(e)32 +b(b)s(eha)m(viour.)150 977 y(These)38 b(aren't)h(faults)e(of)h(m)m(y)g +(implemen)m(tation,)h(I)f(hop)s(e,)i(but)d(more)h(an)g(in)m(trinsic)e +(prop)s(ert)m(y)h(of)i(the)150 1087 y(Burro)m(ws-Wheeler)30 +b(transform)g(\(unfortunately\).)40 b(Ma)m(yb)s(e)31 +b(this)e(isn't)h(what)g(y)m(ou)h(w)m(an)m(t.)150 1244 +y(If)h(y)m(ou)h(w)m(an)m(t)g(a)g(compressor)g(and/or)f(library)e(whic)m +(h)h(is)h(faster,)i(uses)e(less)g(memory)g(but)g(gets)h(prett)m(y)150 +1353 y(go)s(o)s(d)e(compression,)g(and)g(has)h(minimal)c(latency)-8 +b(,)33 b(consider)e(Jean-loup)f(Gailly's)g(and)h(Mark)h(Adler's)150 +1463 y(w)m(ork,)f Fj(zlib-1.1.2)c Fl(and)j Fj(gzip-1.2.4)p +Fl(.)38 b(Lo)s(ok)31 b(for)f(them)g(at)150 1620 y Fj +(http://www.cdrom.com/pub)o(/inf)o(ozip)o(/zl)o(ib)24 +b Fl(and)30 b Fj(http://www.gzip.org)25 b Fl(resp)s(ectiv)m(ely)-8 +b(.)150 1776 y(F)g(or)32 b(something)f(faster)i(and)e(ligh)m(ter)f +(still,)h(y)m(ou)g(migh)m(t)h(try)f(Markus)h(F)g(X)f(J)h(Ob)s(erh)m +(umer's)d Fj(LZO)i Fl(real-)150 1886 y(time)f +(compression/decompression)f(library)-8 b(,)28 b(at)150 +1996 y Fj(http://wildsau.idv.uni-l)o(inz.)o(ac.a)o(t/m)o(fx/l)o(zo.h)o +(tml)o Fl(.)150 2152 y(If)38 b(y)m(ou)h(w)m(an)m(t)g(to)h(use)e(the)g +Fj(bzip2)g Fl(algorithms)f(to)i(compress)f(small)g(blo)s(c)m(ks)f(of)i +(data,)j(64k)d(b)m(ytes)g(or)150 2262 y(smaller,)i(for)e(example)g(on)h +(an)f(on-the-\015y)h(disk)e(compressor,)k(y)m(ou'd)e(b)s(e)f(w)m(ell)g +(advised)f(not)i(to)g(use)150 2372 y(this)i(library)-8 +b(.)77 b(Instead,)47 b(I'v)m(e)d(made)f(a)h(sp)s(ecial)e(library)f +(tuned)h(for)h(that)h(kind)d(of)j(use.)79 b(It's)43 b(part)150 +2481 y(of)d Fj(e2compr-0.40)p Fl(,)f(an)g(on-the-\015y)h(disk)e +(compressor)h(for)h(the)f(Lin)m(ux)f Fj(ext2)h Fl(\014lesystem.)67 +b(Lo)s(ok)40 b(at)150 2591 y Fj(http://www.netspace.net.)o(au/~)o(reit) +o(er/)o(e2co)o(mpr)p Fl(.)150 2880 y Fk(4.5)68 b(T)-11 +b(esting)150 3072 y Fl(A)30 b(record)h(of)f(the)h(tests)g(I'v)m(e)g +(done.)150 3229 y(First,)f(some)h(data)g(sets:)225 3386 +y Fi(\017)60 b Fl(B:)32 b(a)f(directory)f(con)m(taining)h(6001)i +(\014les,)d(one)h(for)g(ev)m(ery)h(length)e(in)g(the)h(range)g(0)h(to)f +(6000)i(b)m(ytes.)330 3496 y(The)d(\014les)f(con)m(tain)i(random)e(lo)m +(w)m(ercase)j(letters.)41 b(18.7)32 b(megab)m(ytes.)225 +3633 y Fi(\017)60 b Fl(H:)36 b(m)m(y)f(home)h(directory)f(tree.)56 +b(Do)s(cumen)m(ts,)38 b(source)d(co)s(de,)i(mail)d(\014les,)i +(compressed)f(data.)57 b(H)330 3743 y(con)m(tains)39 +b(B,)h(and)f(also)g(a)g(directory)g(of)g(\014les)f(designed)g(as)i(b)s +(oundary)d(cases)j(for)f(the)g(sorting;)330 3853 y(mostly)30 +b(v)m(ery)h(rep)s(etitiv)m(e,)f(nast)m(y)h(\014les.)39 +b(565)32 b(megab)m(ytes.)225 3990 y Fi(\017)60 b Fl(A:)43 +b(directory)f(tree)i(holding)d(v)-5 b(arious)41 b(applications)g(built) +g(from)h(source:)66 b Fj(egcs)p Fl(,)45 b Fj(gcc-2.8.1)p +Fl(,)330 4100 y(KDE,)31 b(GTK,)f(Octa)m(v)m(e,)j(etc.)41 +b(2200)33 b(megab)m(ytes.)150 4285 y(The)i(tests)g(conducted)g(are)h +(as)f(follo)m(ws.)54 b(Eac)m(h)36 b(test)g(means)f(compressing)f(\(a)h +(cop)m(y)h(of)7 b(\))36 b(eac)m(h)g(\014le)e(in)150 4394 +y(the)d(data)g(set,)g(decompressing)e(it)h(and)g(comparing)f(it)h +(against)h(the)g(original.)150 4551 y(First,)26 b(a)g(bunc)m(h)f(of)h +(tests)h(with)d(blo)s(c)m(k)h(sizes)h(and)f(in)m(ternal)g(bu\013er)f +(sizes)i(set)g(v)m(ery)g(small,)g(to)g(detect)i(an)m(y)150 +4661 y(problems)g(with)g(the)i(blo)s(c)m(king)f(and)g(bu\013ering)e +(mec)m(hanisms.)40 b(This)28 b(required)g(mo)s(difying)f(the)j(source) +150 4770 y(co)s(de)h(so)f(as)h(to)g(try)f(to)h(break)g(it.)199 +4927 y(1.)61 b(Data)32 b(set)f(H,)g(with)e(bu\013er)g(size)h(of)h(1)g +(b)m(yte,)g(and)f(blo)s(c)m(k)g(size)g(of)g(23)i(b)m(ytes.)199 +5065 y(2.)61 b(Data)32 b(set)f(B,)g(bu\013er)e(sizes)h(1)h(b)m(yte,)g +(blo)s(c)m(k)f(size)g(1)h(b)m(yte.)199 5202 y(3.)61 b(As)30 +b(\(2\))i(but)d(small-mo)s(de)g(decompression.)199 5340 +y(4.)61 b(As)30 b(\(2\))i(with)d(blo)s(c)m(k)h(size)g(2)h(b)m(ytes.)p +eop +%%Page: 35 36 +35 35 bop 150 -116 a Fl(Chapter)30 b(4:)41 b(Miscellanea)2586 +b(35)199 299 y(5.)61 b(As)30 b(\(2\))i(with)d(blo)s(c)m(k)h(size)g(3)h +(b)m(ytes.)199 431 y(6.)61 b(As)30 b(\(2\))i(with)d(blo)s(c)m(k)h(size) +g(4)h(b)m(ytes.)199 564 y(7.)61 b(As)30 b(\(2\))i(with)d(blo)s(c)m(k)h +(size)g(5)h(b)m(ytes.)199 697 y(8.)61 b(As)30 b(\(2\))i(with)d(blo)s(c) +m(k)h(size)g(6)h(b)m(ytes)g(and)e(small-mo)s(de)g(decompression.)199 +829 y(9.)61 b(H)30 b(with)g(bu\013er)f(size)h(of)h(1)f(b)m(yte,)i(but)d +(normal)h(blo)s(c)m(k)g(size)g(\(up)f(to)j(900000)h(b)m(ytes\).)150 +1009 y(Then)c(some)i(tests)g(with)e(unmo)s(di\014ed)f(source)i(co)s +(de.)199 1166 y(1.)61 b(H,)31 b(all)e(settings)h(normal.)199 +1299 y(2.)61 b(As)30 b(\(1\),)i(with)d(small-mo)s(de)g(decompress.)199 +1431 y(3.)61 b(H,)31 b(compress)f(with)f(\015ag)i Fj(-1)p +Fl(.)199 1564 y(4.)61 b(H,)31 b(compress)f(with)f(\015ag)i +Fj(-s)p Fl(,)f(decompress)g(with)f(\015ag)i Fj(-s)p Fl(.)199 +1697 y(5.)61 b(F)-8 b(orw)m(ards)33 b(compatibilit)m(y:)45 +b(H,)33 b Fj(bzip2-0.1pl2)d Fl(compressing,)j Fj(bzip2-0.9.5)d +Fl(decompressing,)330 1806 y(all)f(settings)i(normal.)199 +1939 y(6.)61 b(Bac)m(kw)m(ards)23 b(compatibilit)m(y:)35 +b(H,)23 b Fj(bzip2-0.9.5)c Fl(compressing,)k Fj(bzip2-0.1pl2)c +Fl(decompressing,)330 2048 y(all)29 b(settings)i(normal.)199 +2181 y(7.)61 b(Bigger)31 b(tests:)41 b(A,)31 b(all)e(settings)i +(normal.)199 2314 y(8.)61 b(As)30 b(\(7\),)i(using)d(the)i(fallbac)m(k) +e(\(Sadak)-5 b(ane-lik)m(e\))31 b(sorting)f(algorithm.)199 +2446 y(9.)61 b(As)30 b(\(8\),)i(compress)e(with)f(\015ag)i +Fj(-1)p Fl(,)f(decompress)g(with)f(\015ag)i Fj(-s)p Fl(.)154 +2579 y(10.)61 b(H,)31 b(using)e(the)h(fallbac)m(k)g(sorting)g +(algorithm.)154 2711 y(11.)61 b(F)-8 b(orw)m(ards)33 +b(compatibilit)m(y:)45 b(A,)33 b Fj(bzip2-0.1pl2)d Fl(compressing,)j +Fj(bzip2-0.9.5)d Fl(decompressing,)330 2821 y(all)f(settings)i(normal.) +154 2954 y(12.)61 b(Bac)m(kw)m(ards)23 b(compatibilit)m(y:)35 +b(A,)23 b Fj(bzip2-0.9.5)c Fl(compressing,)k Fj(bzip2-0.1pl2)c +Fl(decompressing,)330 3063 y(all)29 b(settings)i(normal.)154 +3196 y(13.)61 b(Misc)39 b(test:)58 b(ab)s(out)39 b(400)h(megab)m(ytes)h +(of)e Fj(.tar)f Fl(\014les)f(with)h Fj(bzip2)f Fl(compiled)h(with)f +(Chec)m(k)m(er)j(\(a)330 3305 y(memory)30 b(access)i(error)e(detector,) +i(lik)m(e)e(Purify\).)154 3438 y(14.)61 b(Misc)30 b(tests)h(to)g(mak)m +(e)h(sure)d(it)h(builds)e(and)h(runs)g(ok)i(on)f(non-Lin)m(ux/x86)g +(platforms.)150 3618 y(These)35 b(tests)h(w)m(ere)f(conducted)g(on)g(a) +h(225)g(MHz)g(IDT)f(WinChip)d(mac)m(hine,)k(running)d(Lin)m(ux)g +(2.0.36.)150 3728 y(They)d(represen)m(t)g(nearly)g(a)h(w)m(eek)g(of)f +(con)m(tin)m(uous)g(computation.)41 b(All)29 b(tests)i(completed)f +(successfully)-8 b(.)150 4003 y Fk(4.6)68 b(F)-11 b(urther)44 +b(reading)150 4196 y Fj(bzip2)28 b Fl(is)h(not)h(researc)m(h)g(w)m +(ork,)g(in)e(the)i(sense)g(that)g(it)f(do)s(esn't)g(presen)m(t)h(an)m +(y)g(new)f(ideas.)40 b(Rather,)30 b(it's)150 4306 y(an)g(engineering)f +(exercise)i(based)f(on)g(existing)g(ideas.)150 4463 y(F)-8 +b(our)31 b(do)s(cumen)m(ts)f(describ)s(e)e(essen)m(tially)i(all)f(the)i +(ideas)e(b)s(ehind)f Fj(bzip2)p Fl(:)390 4614 y Fj(Michael)46 +b(Burrows)g(and)h(D.)g(J.)g(Wheeler:)485 4717 y("A)h(block-sorting)c +(lossless)h(data)i(compression)e(algorithm")533 4821 +y(10th)i(May)g(1994.)533 4925 y(Digital)f(SRC)h(Research)e(Report)i +(124.)533 5029 y(ftp://ftp.digital.com/pub)o(/DEC)o(/SR)o(C/re)o(sear)o +(ch-)o(repo)o(rts/)o(SRC)o(-124)o(.ps.)o(gz)533 5132 +y(If)g(you)g(have)g(trouble)f(finding)g(it,)g(try)h(searching)f(at)h +(the)533 5236 y(New)g(Zealand)f(Digital)g(Library,)f +(http://www.nzdl.org.)p eop +%%Page: 36 37 +36 36 bop 150 -116 a Fl(Chapter)30 b(4:)41 b(Miscellanea)2586 +b(36)390 299 y Fj(Daniel)46 b(S.)h(Hirschberg)e(and)i(Debra)g(A.)g +(LeLewer)485 403 y("Efficient)e(Decoding)h(of)h(Prefix)f(Codes")533 +506 y(Communications)e(of)j(the)g(ACM,)g(April)f(1990,)h(Vol)f(33,)h +(Number)f(4.)533 610 y(You)h(might)f(be)i(able)e(to)h(get)g(an)h +(electronic)d(copy)h(of)h(this)676 714 y(from)g(the)g(ACM)g(Digital)f +(Library.)390 922 y(David)g(J.)i(Wheeler)533 1025 y(Program)e(bred3.c)g +(and)h(accompanying)d(document)i(bred3.ps.)533 1129 y(This)h(contains)e +(the)i(idea)g(behind)f(the)h(multi-table)e(Huffman)533 +1233 y(coding)h(scheme.)533 1337 y(ftp://ftp.cl.cam.ac.uk/us)o(ers/)o +(djw)o(3/)390 1544 y(Jon)h(L.)g(Bentley)f(and)h(Robert)f(Sedgewick)485 +1648 y("Fast)h(Algorithms)e(for)i(Sorting)f(and)g(Searching)g(Strings") +533 1752 y(Available)f(from)i(Sedgewick's)e(web)i(page,)533 +1856 y(www.cs.princeton.edu/~rs)150 2012 y Fl(The)29 +b(follo)m(wing)f(pap)s(er)g(giv)m(es)h(v)-5 b(aluable)28 +b(additional)g(insigh)m(ts)f(in)m(to)j(the)f(algorithm,)g(but)g(is)f +(not)i(imme-)150 2122 y(diately)g(the)g(basis)f(of)i(an)m(y)g(co)s(de)f +(used)g(in)f(bzip2.)390 2273 y Fj(Peter)46 b(Fenwick:)533 +2377 y(Block)h(Sorting)e(Text)i(Compression)533 2481 +y(Proceedings)e(of)i(the)g(19th)g(Australasian)d(Computer)i(Science)f +(Conference,)629 2584 y(Melbourne,)g(Australia.)92 b(Jan)47 +b(31)g(-)h(Feb)f(2,)g(1996.)533 2688 y(ftp://ftp.cs.auckland.ac.)o +(nz/p)o(ub/)o(pete)o(r-f/)o(ACS)o(C96p)o(aper)o(.ps)150 +2845 y Fl(Kunihik)m(o)28 b(Sadak)-5 b(ane's)31 b(sorting)e(algorithm,)h +(men)m(tioned)g(ab)s(o)m(v)m(e,)i(is)d(a)m(v)-5 b(ailable)30 +b(from:)390 2996 y Fj(http://naomi.is.s.u-toky)o(o.ac)o(.jp/)o(~sa)o +(da/p)o(aper)o(s/S)o(ada9)o(8b.p)o(s.g)o(z)150 3153 y +Fl(The)41 b(Man)m(b)s(er-My)m(ers)g(su\016x)g(arra)m(y)g(construction)g +(algorithm)f(is)g(describ)s(ed)f(in)h(a)i(pap)s(er)e(a)m(v)-5 +b(ailable)150 3262 y(from:)390 3413 y Fj(http://www.cs.arizona.ed)o +(u/pe)o(ople)o(/ge)o(ne/P)o(APER)o(S/s)o(uffi)o(x.ps)150 +3570 y Fl(Finally)d(,)33 b(the)h(follo)m(wing)e(pap)s(er)h(do)s(cumen)m +(ts)g(some)h(recen)m(t)h(in)m(v)m(estigations)e(I)h(made)f(in)m(to)h +(the)g(p)s(erfor-)150 3680 y(mance)d(of)f(sorting)g(algorithms:)390 +3831 y Fj(Julian)46 b(Seward:)533 3935 y(On)h(the)g(Performance)e(of)i +(BWT)g(Sorting)f(Algorithms)533 4038 y(Proceedings)f(of)i(the)g(IEEE)g +(Data)f(Compression)f(Conference)g(2000)629 4142 y(Snowbird,)g(Utah.)94 +b(28-30)46 b(March)h(2000.)p eop +%%Page: -1 38 +-1 37 bop 3725 -116 a Fl(i)150 299 y Fh(T)-13 b(able)54 +b(of)g(Con)l(ten)l(ts)150 641 y Fk(1)135 b(In)l(tro)t(duction)15 +b Fb(.)20 b(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f +(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)60 +b Fk(2)150 911 y(2)135 b(Ho)l(w)45 b(to)h(use)f Fd(bzip2)31 +b Fb(.)19 b(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g +(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)78 b Fk(3)1047 +1048 y Fl(NAME)20 b Fa(.)c(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)50 b Fl(3)1047 +1157 y(SYNOPSIS)21 b Fa(.)13 b(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)h(.)f(.)g(.)50 b Fl(3)1047 1267 y(DESCRIPTION)10 +b Fa(.)j(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)40 +b Fl(3)1047 1377 y(OPTIONS)16 b Fa(.)d(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)45 b Fl(4)1047 +1486 y(MEMOR)-8 b(Y)31 b(MANA)m(GEMENT)14 b Fa(.)j(.)e(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)44 +b Fl(6)1047 1596 y(RECO)m(VERING)30 b(D)m(A)-8 b(T)g(A)32 +b(FR)m(OM)f(D)m(AMA)m(GED)i(FILES)1256 1705 y Fa(.)15 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)57 b Fl(7)1047 1815 y(PERF)m(ORMANCE)30 +b(NOTES)9 b Fa(.)14 b(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)38 b Fl(7)1047 1924 +y(CA)-10 b(VEA)i(TS)10 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)40 b Fl(8)1047 2034 +y(A)m(UTHOR)23 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)53 b Fl(8)150 2276 y Fk(3)135 +b(Programming)46 b(with)f Fd(libbzip2)29 b Fb(.)16 b(.)j(.)h(.)f(.)h(.) +f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)74 b Fk(9)449 +2413 y Fl(3.1)92 b(T)-8 b(op-lev)m(el)30 b(structure)24 +b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)54 b Fl(9)748 2523 y(3.1.1)93 b(Lo)m(w-lev)m(el)30 +b(summary)23 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)53 +b Fl(9)748 2633 y(3.1.2)93 b(High-lev)m(el)29 b(summary)12 +b Fa(.)i(.)h(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)41 b +Fl(9)748 2742 y(3.1.3)93 b(Utilit)m(y)29 b(functions)g(summary)12 +b Fa(.)h(.)j(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)41 b Fl(10)449 2852 y(3.2)92 b(Error)29 +b(handling)18 b Fa(.)13 b(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)48 b Fl(10)449 +2961 y(3.3)92 b(Lo)m(w-lev)m(el)31 b(in)m(terface)d Fa(.)15 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)57 b Fl(12)748 3071 y(3.3.1)93 b Fj(BZ2_bzCompressInit)21 +b Fa(.)9 b(.)15 b(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)50 b Fl(12)748 +3181 y(3.3.2)93 b Fj(BZ2_bzCompress)9 b Fa(.)h(.)15 b(.)g(.)g(.)g(.)g +(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)38 b Fl(14)748 3290 y(3.3.3)93 +b Fj(BZ2_bzCompressEnd)23 b Fa(.)10 b(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g +(.)52 b Fl(17)748 3400 y(3.3.4)93 b Fj(BZ2_bzDecompressInit)16 +b Fa(.)9 b(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)45 b Fl(17)748 3509 +y(3.3.5)93 b Fj(BZ2_bzDecompress)21 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)55 b Fl(17)748 3619 y(3.3.6)93 b Fj(BZ2_bzDecompressEnd)18 +b Fa(.)10 b(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)48 b Fl(19)449 +3729 y(3.4)92 b(High-lev)m(el)30 b(in)m(terface)16 b +Fa(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)45 b Fl(19)748 3838 y(3.4.1)93 b Fj(BZ2_bzReadOpen)9 +b Fa(.)h(.)15 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)38 +b Fl(19)748 3948 y(3.4.2)93 b Fj(BZ2_bzRead)18 b Fa(.)12 +b(.)j(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)47 +b Fl(20)748 4057 y(3.4.3)93 b Fj(BZ2_bzReadGetUnused)18 +b Fa(.)10 b(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)48 b Fl(22)748 +4167 y(3.4.4)93 b Fj(BZ2_bzReadClose)23 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)57 b Fl(22)748 4276 y(3.4.5)93 b +Fj(BZ2_bzWriteOpen)23 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)57 b Fl(22)748 4386 y(3.4.6)93 b Fj(BZ2_bzWrite)16 +b Fa(.)11 b(.)k(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +45 b Fl(23)748 4496 y(3.4.7)93 b Fj(BZ2_bzWriteClose)21 +b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)55 b Fl(23)748 +4605 y(3.4.8)93 b(Handling)28 b(em)m(b)s(edded)h(compressed)h(data)h +(streams)17 b Fa(.)f(.)f(.)g(.)46 b Fl(24)748 4715 y(3.4.9)93 +b(Standard)29 b(\014le-reading/writing)e(co)s(de)22 b +Fa(.)16 b(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)52 +b Fl(25)449 4824 y(3.5)92 b(Utilit)m(y)29 b(functions)f +Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)59 b Fl(26)748 4934 y(3.5.1)93 b +Fj(BZ2_bzBuffToBuffCompres)o(s)22 b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)57 b Fl(26)748 +5044 y(3.5.2)93 b Fj(BZ2_bzBuffToBuffDecompr)o(ess)17 +b Fa(.)e(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +53 b Fl(27)449 5153 y(3.6)92 b Fj(zlib)29 b Fl(compatibilit)m(y)g +(functions)23 b Fa(.)13 b(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)52 +b Fl(28)449 5263 y(3.7)92 b(Using)30 b(the)g(library)e(in)h(a)i +Fj(stdio)p Fl(-free)e(en)m(vironmen)m(t)23 b Fa(.)15 +b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)52 b Fl(29)p +eop +%%Page: -2 39 +-2 38 bop 3699 -116 a Fl(ii)748 83 y(3.7.1)93 b(Getting)31 +b(rid)d(of)j Fj(stdio)20 b Fa(.)13 b(.)i(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)49 +b Fl(29)748 193 y(3.7.2)93 b(Critical)28 b(error)i(handling)22 +b Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)54 b Fl(29)449 302 +y(3.8)92 b(Making)30 b(a)h(Windo)m(ws)e(DLL)15 b Fa(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)44 b Fl(30)150 545 +y Fk(4)135 b(Miscellanea)11 b Fb(.)21 b(.)f(.)f(.)h(.)f(.)g(.)h(.)f(.)h +(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.)g(.)h(.)f(.)h(.)f(.)h(.)f(.) +h(.)f(.)g(.)h(.)56 b Fk(31)449 682 y Fl(4.1)92 b(Limitations)29 +b(of)h(the)h(compressed)f(\014le)f(format)9 b Fa(.)15 +b(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)38 +b Fl(31)449 791 y(4.2)92 b(P)m(ortabilit)m(y)30 b(issues)14 +b Fa(.)f(.)j(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)h(.)f(.)g(.)43 b Fl(32)449 901 y(4.3)92 b(Rep)s(orting)29 +b(bugs)f Fa(.)15 b(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)58 b Fl(32)449 1010 y(4.4)92 +b(Did)29 b(y)m(ou)i(get)h(the)e(righ)m(t)g(pac)m(k)-5 +b(age?)22 b Fa(.)17 b(.)e(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h +(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)51 +b Fl(34)449 1120 y(4.5)92 b(T)-8 b(esting)16 b Fa(.)f(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)45 b Fl(34)449 1230 y(4.6)92 +b(F)-8 b(urther)30 b(reading)22 b Fa(.)14 b(.)h(.)g(.)h(.)f(.)g(.)g(.)g +(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.) +g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)g(.)h(.)f(.)51 +b Fl(35)p eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/drivers/lib/bzip2/manual.texi b/drivers/lib/bzip2/manual.texi new file mode 100644 index 0000000..336776a --- /dev/null +++ b/drivers/lib/bzip2/manual.texi @@ -0,0 +1,2215 @@ +\input texinfo @c -*- Texinfo -*- +@setfilename bzip2.info + +@ignore +This file documents bzip2 version 1.0, and associated library +libbzip2, written by Julian Seward (jseward@acm.org). + +Copyright (C) 1996-2000 Julian R Seward + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for verbatim copies. +@end ignore + +@ifinfo +@format +START-INFO-DIR-ENTRY +* Bzip2: (bzip2). A program and library for data compression. +END-INFO-DIR-ENTRY +@end format + +@end ifinfo + +@iftex +@c @finalout +@settitle bzip2 and libbzip2 +@titlepage +@title bzip2 and libbzip2 +@subtitle a program and library for data compression +@subtitle copyright (C) 1996-2000 Julian Seward +@subtitle version 1.0 of 21 March 2000 +@author Julian Seward + +@end titlepage + +@parindent 0mm +@parskip 2mm + +@end iftex +@node Top, Overview, (dir), (dir) + +This program, @code{bzip2}, +and associated library @code{libbzip2}, are +Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +@itemize @bullet +@item + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +@item + The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. +@item + Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. +@item + The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. +@end itemize +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, Cambridge, UK. + +@code{jseward@@acm.org} + +@code{http://sourceware.cygnus.com/bzip2} + +@code{http://www.cacheprof.org} + +@code{http://www.muraroa.demon.co.uk} + +@code{bzip2}/@code{libbzip2} version 1.0 of 21 March 2000. + +PATENTS: To the best of my knowledge, @code{bzip2} does not use any patented +algorithms. However, I do not have the resources available to carry out +a full patent search. Therefore I cannot give any guarantee of the +above statement. + + + + + + + +@node Overview, Implementation, Top, Top +@chapter Introduction + +@code{bzip2} compresses files using the Burrows-Wheeler +block-sorting text compression algorithm, and Huffman coding. +Compression is generally considerably better than that +achieved by more conventional LZ77/LZ78-based compressors, +and approaches the performance of the PPM family of statistical compressors. + +@code{bzip2} is built on top of @code{libbzip2}, a flexible library +for handling compressed data in the @code{bzip2} format. This manual +describes both how to use the program and +how to work with the library interface. Most of the +manual is devoted to this library, not the program, +which is good news if your interest is only in the program. + +Chapter 2 describes how to use @code{bzip2}; this is the only part +you need to read if you just want to know how to operate the program. +Chapter 3 describes the programming interfaces in detail, and +Chapter 4 records some miscellaneous notes which I thought +ought to be recorded somewhere. + + +@chapter How to use @code{bzip2} + +This chapter contains a copy of the @code{bzip2} man page, +and nothing else. + +@quotation + +@unnumberedsubsubsec NAME +@itemize +@item @code{bzip2}, @code{bunzip2} +- a block-sorting file compressor, v1.0 +@item @code{bzcat} +- decompresses files to stdout +@item @code{bzip2recover} +- recovers data from damaged bzip2 files +@end itemize + +@unnumberedsubsubsec SYNOPSIS +@itemize +@item @code{bzip2} [ -cdfkqstvzVL123456789 ] [ filenames ... ] +@item @code{bunzip2} [ -fkvsVL ] [ filenames ... ] +@item @code{bzcat} [ -s ] [ filenames ... ] +@item @code{bzip2recover} filename +@end itemize + +@unnumberedsubsubsec DESCRIPTION + +@code{bzip2} compresses files using the Burrows-Wheeler block sorting +text compression algorithm, and Huffman coding. Compression is +generally considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of the PPM +family of statistical compressors. + +The command-line options are deliberately very similar to those of GNU +@code{gzip}, but they are not identical. + +@code{bzip2} expects a list of file names to accompany the command-line +flags. Each file is replaced by a compressed version of itself, with +the name @code{original_name.bz2}. Each compressed file has the same +modification date, permissions, and, when possible, ownership as the +corresponding original, so that these properties can be correctly +restored at decompression time. File name handling is naive in the +sense that there is no mechanism for preserving original file names, +permissions, ownerships or dates in filesystems which lack these +concepts, or have serious file name length restrictions, such as MS-DOS. + +@code{bzip2} and @code{bunzip2} will by default not overwrite existing +files. If you want this to happen, specify the @code{-f} flag. + +If no file names are specified, @code{bzip2} compresses from standard +input to standard output. In this case, @code{bzip2} will decline to +write compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless. + +@code{bunzip2} (or @code{bzip2 -d}) decompresses all +specified files. Files which were not created by @code{bzip2} +will be detected and ignored, and a warning issued. +@code{bzip2} attempts to guess the filename for the decompressed file +from that of the compressed file as follows: +@itemize +@item @code{filename.bz2 } becomes @code{filename} +@item @code{filename.bz } becomes @code{filename} +@item @code{filename.tbz2} becomes @code{filename.tar} +@item @code{filename.tbz } becomes @code{filename.tar} +@item @code{anyothername } becomes @code{anyothername.out} +@end itemize +If the file does not end in one of the recognised endings, +@code{.bz2}, @code{.bz}, +@code{.tbz2} or @code{.tbz}, @code{bzip2} complains that it cannot +guess the name of the original file, and uses the original name +with @code{.out} appended. + +As with compression, supplying no +filenames causes decompression from standard input to standard output. + +@code{bunzip2} will correctly decompress a file which is the +concatenation of two or more compressed files. The result is the +concatenation of the corresponding uncompressed files. Integrity +testing (@code{-t}) of concatenated compressed files is also supported. + +You can also compress or decompress files to the standard output by +giving the @code{-c} flag. Multiple files may be compressed and +decompressed like this. The resulting outputs are fed sequentially to +stdout. Compression of multiple files in this manner generates a stream +containing multiple compressed file representations. Such a stream +can be decompressed correctly only by @code{bzip2} version 0.9.0 or +later. Earlier versions of @code{bzip2} will stop after decompressing +the first file in the stream. + +@code{bzcat} (or @code{bzip2 -dc}) decompresses all specified files to +the standard output. + +@code{bzip2} will read arguments from the environment variables +@code{BZIP2} and @code{BZIP}, in that order, and will process them +before any arguments read from the command line. This gives a +convenient way to supply default arguments. + +Compression is always performed, even if the compressed file is slightly +larger than the original. Files of less than about one hundred bytes +tend to get larger, since the compression mechanism has a constant +overhead in the region of 50 bytes. Random data (including the output +of most file compressors) is coded at about 8.05 bits per byte, giving +an expansion of around 0.5%. + +As a self-check for your protection, @code{bzip2} uses 32-bit CRCs to +make sure that the decompressed version of a file is identical to the +original. This guards against corruption of the compressed data, and +against undetected bugs in @code{bzip2} (hopefully very unlikely). The +chances of data corruption going undetected is microscopic, about one +chance in four billion for each file processed. Be aware, though, that +the check occurs upon decompression, so it can only tell you that +something is wrong. It can't help you recover the original uncompressed +data. You can use @code{bzip2recover} to try to recover data from +damaged files. + +Return values: 0 for a normal exit, 1 for environmental problems (file +not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt +compressed file, 3 for an internal consistency error (eg, bug) which +caused @code{bzip2} to panic. + + +@unnumberedsubsubsec OPTIONS +@table @code +@item -c --stdout +Compress or decompress to standard output. +@item -d --decompress +Force decompression. @code{bzip2}, @code{bunzip2} and @code{bzcat} are +really the same program, and the decision about what actions to take is +done on the basis of which name is used. This flag overrides that +mechanism, and forces bzip2 to decompress. +@item -z --compress +The complement to @code{-d}: forces compression, regardless of the +invokation name. +@item -t --test +Check integrity of the specified file(s), but don't decompress them. +This really performs a trial decompression and throws away the result. +@item -f --force +Force overwrite of output files. Normally, @code{bzip2} will not overwrite +existing output files. Also forces @code{bzip2} to break hard links +to files, which it otherwise wouldn't do. +@item -k --keep +Keep (don't delete) input files during compression +or decompression. +@item -s --small +Reduce memory usage, for compression, decompression and testing. Files +are decompressed and tested using a modified algorithm which only +requires 2.5 bytes per block byte. This means any file can be +decompressed in 2300k of memory, albeit at about half the normal speed. + +During compression, @code{-s} selects a block size of 200k, which limits +memory use to around the same figure, at the expense of your compression +ratio. In short, if your machine is low on memory (8 megabytes or +less), use -s for everything. See MEMORY MANAGEMENT below. +@item -q --quiet +Suppress non-essential warning messages. Messages pertaining to +I/O errors and other critical events will not be suppressed. +@item -v --verbose +Verbose mode -- show the compression ratio for each file processed. +Further @code{-v}'s increase the verbosity level, spewing out lots of +information which is primarily of interest for diagnostic purposes. +@item -L --license -V --version +Display the software version, license terms and conditions. +@item -1 to -9 +Set the block size to 100 k, 200 k .. 900 k when compressing. Has no +effect when decompressing. See MEMORY MANAGEMENT below. +@item -- +Treats all subsequent arguments as file names, even if they start +with a dash. This is so you can handle files with names beginning +with a dash, for example: @code{bzip2 -- -myfilename}. +@item --repetitive-fast +@item --repetitive-best +These flags are redundant in versions 0.9.5 and above. They provided +some coarse control over the behaviour of the sorting algorithm in +earlier versions, which was sometimes useful. 0.9.5 and above have an +improved algorithm which renders these flags irrelevant. +@end table + + +@unnumberedsubsubsec MEMORY MANAGEMENT + +@code{bzip2} compresses large files in blocks. The block size affects +both the compression ratio achieved, and the amount of memory needed for +compression and decompression. The flags @code{-1} through @code{-9} +specify the block size to be 100,000 bytes through 900,000 bytes (the +default) respectively. At decompression time, the block size used for +compression is read from the header of the compressed file, and +@code{bunzip2} then allocates itself just enough memory to decompress +the file. Since block sizes are stored in compressed files, it follows +that the flags @code{-1} to @code{-9} are irrelevant to and so ignored +during decompression. + +Compression and decompression requirements, in bytes, can be estimated +as: +@example + Compression: 400k + ( 8 x block size ) + + Decompression: 100k + ( 4 x block size ), or + 100k + ( 2.5 x block size ) +@end example +Larger block sizes give rapidly diminishing marginal returns. Most of +the compression comes from the first two or three hundred k of block +size, a fact worth bearing in mind when using @code{bzip2} on small machines. +It is also important to appreciate that the decompression memory +requirement is set at compression time by the choice of block size. + +For files compressed with the default 900k block size, @code{bunzip2} +will require about 3700 kbytes to decompress. To support decompression +of any file on a 4 megabyte machine, @code{bunzip2} has an option to +decompress using approximately half this amount of memory, about 2300 +kbytes. Decompression speed is also halved, so you should use this +option only where necessary. The relevant flag is @code{-s}. + +In general, try and use the largest block size memory constraints allow, +since that maximises the compression achieved. Compression and +decompression speed are virtually unaffected by block size. + +Another significant point applies to files which fit in a single block +-- that means most files you'd encounter using a large block size. The +amount of real memory touched is proportional to the size of the file, +since the file is smaller than a block. For example, compressing a file +20,000 bytes long with the flag @code{-9} will cause the compressor to +allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 +kbytes of it. Similarly, the decompressor will allocate 3700k but only +touch 100k + 20000 * 4 = 180 kbytes. + +Here is a table which summarises the maximum memory usage for different +block sizes. Also recorded is the total compressed size for 14 files of +the Calgary Text Compression Corpus totalling 3,141,622 bytes. This +column gives some feel for how compression varies with block size. +These figures tend to understate the advantage of larger block sizes for +larger files, since the Corpus is dominated by smaller files. +@example + Compress Decompress Decompress Corpus + Flag usage usage -s usage Size + + -1 1200k 500k 350k 914704 + -2 2000k 900k 600k 877703 + -3 2800k 1300k 850k 860338 + -4 3600k 1700k 1100k 846899 + -5 4400k 2100k 1350k 845160 + -6 5200k 2500k 1600k 838626 + -7 6100k 2900k 1850k 834096 + -8 6800k 3300k 2100k 828642 + -9 7600k 3700k 2350k 828642 +@end example + +@unnumberedsubsubsec RECOVERING DATA FROM DAMAGED FILES + +@code{bzip2} compresses files in blocks, usually 900kbytes long. Each +block is handled independently. If a media or transmission error causes +a multi-block @code{.bz2} file to become damaged, it may be possible to +recover data from the undamaged blocks in the file. + +The compressed representation of each block is delimited by a 48-bit +pattern, which makes it possible to find the block boundaries with +reasonable certainty. Each block also carries its own 32-bit CRC, so +damaged blocks can be distinguished from undamaged ones. + +@code{bzip2recover} is a simple program whose purpose is to search for +blocks in @code{.bz2} files, and write each block out into its own +@code{.bz2} file. You can then use @code{bzip2 -t} to test the +integrity of the resulting files, and decompress those which are +undamaged. + +@code{bzip2recover} +takes a single argument, the name of the damaged file, +and writes a number of files @code{rec0001file.bz2}, + @code{rec0002file.bz2}, etc, containing the extracted blocks. + The output filenames are designed so that the use of + wildcards in subsequent processing -- for example, +@code{bzip2 -dc rec*file.bz2 > recovered_data} -- lists the files in + the correct order. + +@code{bzip2recover} should be of most use dealing with large @code{.bz2} + files, as these will contain many blocks. It is clearly + futile to use it on damaged single-block files, since a + damaged block cannot be recovered. If you wish to minimise +any potential data loss through media or transmission errors, +you might consider compressing with a smaller + block size. + + +@unnumberedsubsubsec PERFORMANCE NOTES + +The sorting phase of compression gathers together similar strings in the +file. Because of this, files containing very long runs of repeated +symbols, like "aabaabaabaab ..." (repeated several hundred times) may +compress more slowly than normal. Versions 0.9.5 and above fare much +better than previous versions in this respect. The ratio between +worst-case and average-case compression time is in the region of 10:1. +For previous versions, this figure was more like 100:1. You can use the +@code{-vvvv} option to monitor progress in great detail, if you want. + +Decompression speed is unaffected by these phenomena. + +@code{bzip2} usually allocates several megabytes of memory to operate +in, and then charges all over it in a fairly random fashion. This means +that performance, both for compressing and decompressing, is largely +determined by the speed at which your machine can service cache misses. +Because of this, small changes to the code to reduce the miss rate have +been observed to give disproportionately large performance improvements. +I imagine @code{bzip2} will perform best on machines with very large +caches. + + +@unnumberedsubsubsec CAVEATS + +I/O error messages are not as helpful as they could be. @code{bzip2} +tries hard to detect I/O errors and exit cleanly, but the details of +what the problem is sometimes seem rather misleading. + +This manual page pertains to version 1.0 of @code{bzip2}. Compressed +data created by this version is entirely forwards and backwards +compatible with the previous public releases, versions 0.1pl2, 0.9.0 and +0.9.5, but with the following exception: 0.9.0 and above can correctly +decompress multiple concatenated compressed files. 0.1pl2 cannot do +this; it will stop after decompressing just the first file in the +stream. + +@code{bzip2recover} uses 32-bit integers to represent bit positions in +compressed files, so it cannot handle compressed files more than 512 +megabytes long. This could easily be fixed. + + +@unnumberedsubsubsec AUTHOR +Julian Seward, @code{jseward@@acm.org}. + +The ideas embodied in @code{bzip2} are due to (at least) the following +people: Michael Burrows and David Wheeler (for the block sorting +transformation), David Wheeler (again, for the Huffman coder), Peter +Fenwick (for the structured coding model in the original @code{bzip}, +and many refinements), and Alistair Moffat, Radford Neal and Ian Witten +(for the arithmetic coder in the original @code{bzip}). I am much +indebted for their help, support and advice. See the manual in the +source distribution for pointers to sources of documentation. Christian +von Roques encouraged me to look for faster sorting algorithms, so as to +speed up compression. Bela Lubkin encouraged me to improve the +worst-case compression performance. Many people sent patches, helped +with portability problems, lent machines, gave advice and were generally +helpful. + +@end quotation + + + + +@chapter Programming with @code{libbzip2} + +This chapter describes the programming interface to @code{libbzip2}. + +For general background information, particularly about memory +use and performance aspects, you'd be well advised to read Chapter 2 +as well. + +@section Top-level structure + +@code{libbzip2} is a flexible library for compressing and decompressing +data in the @code{bzip2} data format. Although packaged as a single +entity, it helps to regard the library as three separate parts: the low +level interface, and the high level interface, and some utility +functions. + +The structure of @code{libbzip2}'s interfaces is similar to +that of Jean-loup Gailly's and Mark Adler's excellent @code{zlib} +library. + +All externally visible symbols have names beginning @code{BZ2_}. +This is new in version 1.0. The intention is to minimise pollution +of the namespaces of library clients. + +@subsection Low-level summary + +This interface provides services for compressing and decompressing +data in memory. There's no provision for dealing with files, streams +or any other I/O mechanisms, just straight memory-to-memory work. +In fact, this part of the library can be compiled without inclusion +of @code{stdio.h}, which may be helpful for embedded applications. + +The low-level part of the library has no global variables and +is therefore thread-safe. + +Six routines make up the low level interface: +@code{BZ2_bzCompressInit}, @code{BZ2_bzCompress}, and @* @code{BZ2_bzCompressEnd} +for compression, +and a corresponding trio @code{BZ2_bzDecompressInit}, @* @code{BZ2_bzDecompress} +and @code{BZ2_bzDecompressEnd} for decompression. +The @code{*Init} functions allocate +memory for compression/decompression and do other +initialisations, whilst the @code{*End} functions close down operations +and release memory. + +The real work is done by @code{BZ2_bzCompress} and @code{BZ2_bzDecompress}. +These compress and decompress data from a user-supplied input buffer +to a user-supplied output buffer. These buffers can be any size; +arbitrary quantities of data are handled by making repeated calls +to these functions. This is a flexible mechanism allowing a +consumer-pull style of activity, or producer-push, or a mixture of +both. + + + +@subsection High-level summary + +This interface provides some handy wrappers around the low-level +interface to facilitate reading and writing @code{bzip2} format +files (@code{.bz2} files). The routines provide hooks to facilitate +reading files in which the @code{bzip2} data stream is embedded +within some larger-scale file structure, or where there are +multiple @code{bzip2} data streams concatenated end-to-end. + +For reading files, @code{BZ2_bzReadOpen}, @code{BZ2_bzRead}, +@code{BZ2_bzReadClose} and @* @code{BZ2_bzReadGetUnused} are supplied. For +writing files, @code{BZ2_bzWriteOpen}, @code{BZ2_bzWrite} and +@code{BZ2_bzWriteFinish} are available. + +As with the low-level library, no global variables are used +so the library is per se thread-safe. However, if I/O errors +occur whilst reading or writing the underlying compressed files, +you may have to consult @code{errno} to determine the cause of +the error. In that case, you'd need a C library which correctly +supports @code{errno} in a multithreaded environment. + +To make the library a little simpler and more portable, +@code{BZ2_bzReadOpen} and @code{BZ2_bzWriteOpen} require you to pass them file +handles (@code{FILE*}s) which have previously been opened for reading or +writing respectively. That avoids portability problems associated with +file operations and file attributes, whilst not being much of an +imposition on the programmer. + + + +@subsection Utility functions summary +For very simple needs, @code{BZ2_bzBuffToBuffCompress} and +@code{BZ2_bzBuffToBuffDecompress} are provided. These compress +data in memory from one buffer to another buffer in a single +function call. You should assess whether these functions +fulfill your memory-to-memory compression/decompression +requirements before investing effort in understanding the more +general but more complex low-level interface. + +Yoshioka Tsuneo (@code{QWF00133@@niftyserve.or.jp} / +@code{tsuneo-y@@is.aist-nara.ac.jp}) has contributed some functions to +give better @code{zlib} compatibility. These functions are +@code{BZ2_bzopen}, @code{BZ2_bzread}, @code{BZ2_bzwrite}, @code{BZ2_bzflush}, +@code{BZ2_bzclose}, +@code{BZ2_bzerror} and @code{BZ2_bzlibVersion}. You may find these functions +more convenient for simple file reading and writing, than those in the +high-level interface. These functions are not (yet) officially part of +the library, and are minimally documented here. If they break, you +get to keep all the pieces. I hope to document them properly when time +permits. + +Yoshioka also contributed modifications to allow the library to be +built as a Windows DLL. + + +@section Error handling + +The library is designed to recover cleanly in all situations, including +the worst-case situation of decompressing random data. I'm not +100% sure that it can always do this, so you might want to add +a signal handler to catch segmentation violations during decompression +if you are feeling especially paranoid. I would be interested in +hearing more about the robustness of the library to corrupted +compressed data. + +Version 1.0 is much more robust in this respect than +0.9.0 or 0.9.5. Investigations with Checker (a tool for +detecting problems with memory management, similar to Purify) +indicate that, at least for the few files I tested, all single-bit +errors in the decompressed data are caught properly, with no +segmentation faults, no reads of uninitialised data and no +out of range reads or writes. So it's certainly much improved, +although I wouldn't claim it to be totally bombproof. + +The file @code{bzlib.h} contains all definitions needed to use +the library. In particular, you should definitely not include +@code{bzlib_private.h}. + +In @code{bzlib.h}, the various return values are defined. The following +list is not intended as an exhaustive description of the circumstances +in which a given value may be returned -- those descriptions are given +later. Rather, it is intended to convey the rough meaning of each +return value. The first five actions are normal and not intended to +denote an error situation. +@table @code +@item BZ_OK +The requested action was completed successfully. +@item BZ_RUN_OK +@itemx BZ_FLUSH_OK +@itemx BZ_FINISH_OK +In @code{BZ2_bzCompress}, the requested flush/finish/nothing-special action +was completed successfully. +@item BZ_STREAM_END +Compression of data was completed, or the logical stream end was +detected during decompression. +@end table + +The following return values indicate an error of some kind. +@table @code +@item BZ_CONFIG_ERROR +Indicates that the library has been improperly compiled on your +platform -- a major configuration error. Specifically, it means +that @code{sizeof(char)}, @code{sizeof(short)} and @code{sizeof(int)} +are not 1, 2 and 4 respectively, as they should be. Note that the +library should still work properly on 64-bit platforms which follow +the LP64 programming model -- that is, where @code{sizeof(long)} +and @code{sizeof(void*)} are 8. Under LP64, @code{sizeof(int)} is +still 4, so @code{libbzip2}, which doesn't use the @code{long} type, +is OK. +@item BZ_SEQUENCE_ERROR +When using the library, it is important to call the functions in the +correct sequence and with data structures (buffers etc) in the correct +states. @code{libbzip2} checks as much as it can to ensure this is +happening, and returns @code{BZ_SEQUENCE_ERROR} if not. Code which +complies precisely with the function semantics, as detailed below, +should never receive this value; such an event denotes buggy code +which you should investigate. +@item BZ_PARAM_ERROR +Returned when a parameter to a function call is out of range +or otherwise manifestly incorrect. As with @code{BZ_SEQUENCE_ERROR}, +this denotes a bug in the client code. The distinction between +@code{BZ_PARAM_ERROR} and @code{BZ_SEQUENCE_ERROR} is a bit hazy, but still worth +making. +@item BZ_MEM_ERROR +Returned when a request to allocate memory failed. Note that the +quantity of memory needed to decompress a stream cannot be determined +until the stream's header has been read. So @code{BZ2_bzDecompress} and +@code{BZ2_bzRead} may return @code{BZ_MEM_ERROR} even though some of +the compressed data has been read. The same is not true for +compression; once @code{BZ2_bzCompressInit} or @code{BZ2_bzWriteOpen} have +successfully completed, @code{BZ_MEM_ERROR} cannot occur. +@item BZ_DATA_ERROR +Returned when a data integrity error is detected during decompression. +Most importantly, this means when stored and computed CRCs for the +data do not match. This value is also returned upon detection of any +other anomaly in the compressed data. +@item BZ_DATA_ERROR_MAGIC +As a special case of @code{BZ_DATA_ERROR}, it is sometimes useful to +know when the compressed stream does not start with the correct +magic bytes (@code{'B' 'Z' 'h'}). +@item BZ_IO_ERROR +Returned by @code{BZ2_bzRead} and @code{BZ2_bzWrite} when there is an error +reading or writing in the compressed file, and by @code{BZ2_bzReadOpen} +and @code{BZ2_bzWriteOpen} for attempts to use a file for which the +error indicator (viz, @code{ferror(f)}) is set. +On receipt of @code{BZ_IO_ERROR}, the caller should consult +@code{errno} and/or @code{perror} to acquire operating-system +specific information about the problem. +@item BZ_UNEXPECTED_EOF +Returned by @code{BZ2_bzRead} when the compressed file finishes +before the logical end of stream is detected. +@item BZ_OUTBUFF_FULL +Returned by @code{BZ2_bzBuffToBuffCompress} and +@code{BZ2_bzBuffToBuffDecompress} to indicate that the output data +will not fit into the output buffer provided. +@end table + + + +@section Low-level interface + +@subsection @code{BZ2_bzCompressInit} +@example +typedef + struct @{ + char *next_in; + unsigned int avail_in; + unsigned int total_in_lo32; + unsigned int total_in_hi32; + + char *next_out; + unsigned int avail_out; + unsigned int total_out_lo32; + unsigned int total_out_hi32; + + void *state; + + void *(*bzalloc)(void *,int,int); + void (*bzfree)(void *,void *); + void *opaque; + @} + bz_stream; + +int BZ2_bzCompressInit ( bz_stream *strm, + int blockSize100k, + int verbosity, + int workFactor ); + +@end example + +Prepares for compression. The @code{bz_stream} structure +holds all data pertaining to the compression activity. +A @code{bz_stream} structure should be allocated and initialised +prior to the call. +The fields of @code{bz_stream} +comprise the entirety of the user-visible data. @code{state} +is a pointer to the private data structures required for compression. + +Custom memory allocators are supported, via fields @code{bzalloc}, +@code{bzfree}, +and @code{opaque}. The value +@code{opaque} is passed to as the first argument to +all calls to @code{bzalloc} and @code{bzfree}, but is +otherwise ignored by the library. +The call @code{bzalloc ( opaque, n, m )} is expected to return a +pointer @code{p} to +@code{n * m} bytes of memory, and @code{bzfree ( opaque, p )} +should free +that memory. + +If you don't want to use a custom memory allocator, set @code{bzalloc}, +@code{bzfree} and +@code{opaque} to @code{NULL}, +and the library will then use the standard @code{malloc}/@code{free} +routines. + +Before calling @code{BZ2_bzCompressInit}, fields @code{bzalloc}, +@code{bzfree} and @code{opaque} should +be filled appropriately, as just described. Upon return, the internal +state will have been allocated and initialised, and @code{total_in_lo32}, +@code{total_in_hi32}, @code{total_out_lo32} and +@code{total_out_hi32} will have been set to zero. +These four fields are used by the library +to inform the caller of the total amount of data passed into and out of +the library, respectively. You should not try to change them. +As of version 1.0, 64-bit counts are maintained, even on 32-bit +platforms, using the @code{_hi32} fields to store the upper 32 bits +of the count. So, for example, the total amount of data in +is @code{(total_in_hi32 << 32) + total_in_lo32}. + +Parameter @code{blockSize100k} specifies the block size to be used for +compression. It should be a value between 1 and 9 inclusive, and the +actual block size used is 100000 x this figure. 9 gives the best +compression but takes most memory. + +Parameter @code{verbosity} should be set to a number between 0 and 4 +inclusive. 0 is silent, and greater numbers give increasingly verbose +monitoring/debugging output. If the library has been compiled with +@code{-DBZ_NO_STDIO}, no such output will appear for any verbosity +setting. + +Parameter @code{workFactor} controls how the compression phase behaves +when presented with worst case, highly repetitive, input data. If +compression runs into difficulties caused by repetitive data, the +library switches from the standard sorting algorithm to a fallback +algorithm. The fallback is slower than the standard algorithm by +perhaps a factor of three, but always behaves reasonably, no matter how +bad the input. + +Lower values of @code{workFactor} reduce the amount of effort the +standard algorithm will expend before resorting to the fallback. You +should set this parameter carefully; too low, and many inputs will be +handled by the fallback algorithm and so compress rather slowly, too +high, and your average-to-worst case compression times can become very +large. The default value of 30 gives reasonable behaviour over a wide +range of circumstances. + +Allowable values range from 0 to 250 inclusive. 0 is a special case, +equivalent to using the default value of 30. + +Note that the compressed output generated is the same regardless of +whether or not the fallback algorithm is used. + +Be aware also that this parameter may disappear entirely in future +versions of the library. In principle it should be possible to devise a +good way to automatically choose which algorithm to use. Such a +mechanism would render the parameter obsolete. + +Possible return values: +@display + @code{BZ_CONFIG_ERROR} + if the library has been mis-compiled + @code{BZ_PARAM_ERROR} + if @code{strm} is @code{NULL} + or @code{blockSize} < 1 or @code{blockSize} > 9 + or @code{verbosity} < 0 or @code{verbosity} > 4 + or @code{workFactor} < 0 or @code{workFactor} > 250 + @code{BZ_MEM_ERROR} + if not enough memory is available + @code{BZ_OK} + otherwise +@end display +Allowable next actions: +@display + @code{BZ2_bzCompress} + if @code{BZ_OK} is returned + no specific action needed in case of error +@end display + +@subsection @code{BZ2_bzCompress} +@example + int BZ2_bzCompress ( bz_stream *strm, int action ); +@end example +Provides more input and/or output buffer space for the library. The +caller maintains input and output buffers, and calls @code{BZ2_bzCompress} to +transfer data between them. + +Before each call to @code{BZ2_bzCompress}, @code{next_in} should point at +the data to be compressed, and @code{avail_in} should indicate how many +bytes the library may read. @code{BZ2_bzCompress} updates @code{next_in}, +@code{avail_in} and @code{total_in} to reflect the number of bytes it +has read. + +Similarly, @code{next_out} should point to a buffer in which the +compressed data is to be placed, with @code{avail_out} indicating how +much output space is available. @code{BZ2_bzCompress} updates +@code{next_out}, @code{avail_out} and @code{total_out} to reflect the +number of bytes output. + +You may provide and remove as little or as much data as you like on each +call of @code{BZ2_bzCompress}. In the limit, it is acceptable to supply and +remove data one byte at a time, although this would be terribly +inefficient. You should always ensure that at least one byte of output +space is available at each call. + +A second purpose of @code{BZ2_bzCompress} is to request a change of mode of the +compressed stream. + +Conceptually, a compressed stream can be in one of four states: IDLE, +RUNNING, FLUSHING and FINISHING. Before initialisation +(@code{BZ2_bzCompressInit}) and after termination (@code{BZ2_bzCompressEnd}), a +stream is regarded as IDLE. + +Upon initialisation (@code{BZ2_bzCompressInit}), the stream is placed in the +RUNNING state. Subsequent calls to @code{BZ2_bzCompress} should pass +@code{BZ_RUN} as the requested action; other actions are illegal and +will result in @code{BZ_SEQUENCE_ERROR}. + +At some point, the calling program will have provided all the input data +it wants to. It will then want to finish up -- in effect, asking the +library to process any data it might have buffered internally. In this +state, @code{BZ2_bzCompress} will no longer attempt to read data from +@code{next_in}, but it will want to write data to @code{next_out}. +Because the output buffer supplied by the user can be arbitrarily small, +the finishing-up operation cannot necessarily be done with a single call +of @code{BZ2_bzCompress}. + +Instead, the calling program passes @code{BZ_FINISH} as an action to +@code{BZ2_bzCompress}. This changes the stream's state to FINISHING. Any +remaining input (ie, @code{next_in[0 .. avail_in-1]}) is compressed and +transferred to the output buffer. To do this, @code{BZ2_bzCompress} must be +called repeatedly until all the output has been consumed. At that +point, @code{BZ2_bzCompress} returns @code{BZ_STREAM_END}, and the stream's +state is set back to IDLE. @code{BZ2_bzCompressEnd} should then be +called. + +Just to make sure the calling program does not cheat, the library makes +a note of @code{avail_in} at the time of the first call to +@code{BZ2_bzCompress} which has @code{BZ_FINISH} as an action (ie, at the +time the program has announced its intention to not supply any more +input). By comparing this value with that of @code{avail_in} over +subsequent calls to @code{BZ2_bzCompress}, the library can detect any +attempts to slip in more data to compress. Any calls for which this is +detected will return @code{BZ_SEQUENCE_ERROR}. This indicates a +programming mistake which should be corrected. + +Instead of asking to finish, the calling program may ask +@code{BZ2_bzCompress} to take all the remaining input, compress it and +terminate the current (Burrows-Wheeler) compression block. This could +be useful for error control purposes. The mechanism is analogous to +that for finishing: call @code{BZ2_bzCompress} with an action of +@code{BZ_FLUSH}, remove output data, and persist with the +@code{BZ_FLUSH} action until the value @code{BZ_RUN} is returned. As +with finishing, @code{BZ2_bzCompress} detects any attempt to provide more +input data once the flush has begun. + +Once the flush is complete, the stream returns to the normal RUNNING +state. + +This all sounds pretty complex, but isn't really. Here's a table +which shows which actions are allowable in each state, what action +will be taken, what the next state is, and what the non-error return +values are. Note that you can't explicitly ask what state the +stream is in, but nor do you need to -- it can be inferred from the +values returned by @code{BZ2_bzCompress}. +@display +IDLE/@code{any} + Illegal. IDLE state only exists after @code{BZ2_bzCompressEnd} or + before @code{BZ2_bzCompressInit}. + Return value = @code{BZ_SEQUENCE_ERROR} + +RUNNING/@code{BZ_RUN} + Compress from @code{next_in} to @code{next_out} as much as possible. + Next state = RUNNING + Return value = @code{BZ_RUN_OK} + +RUNNING/@code{BZ_FLUSH} + Remember current value of @code{next_in}. Compress from @code{next_in} + to @code{next_out} as much as possible, but do not accept any more input. + Next state = FLUSHING + Return value = @code{BZ_FLUSH_OK} + +RUNNING/@code{BZ_FINISH} + Remember current value of @code{next_in}. Compress from @code{next_in} + to @code{next_out} as much as possible, but do not accept any more input. + Next state = FINISHING + Return value = @code{BZ_FINISH_OK} + +FLUSHING/@code{BZ_FLUSH} + Compress from @code{next_in} to @code{next_out} as much as possible, + but do not accept any more input. + If all the existing input has been used up and all compressed + output has been removed + Next state = RUNNING; Return value = @code{BZ_RUN_OK} + else + Next state = FLUSHING; Return value = @code{BZ_FLUSH_OK} + +FLUSHING/other + Illegal. + Return value = @code{BZ_SEQUENCE_ERROR} + +FINISHING/@code{BZ_FINISH} + Compress from @code{next_in} to @code{next_out} as much as possible, + but to not accept any more input. + If all the existing input has been used up and all compressed + output has been removed + Next state = IDLE; Return value = @code{BZ_STREAM_END} + else + Next state = FINISHING; Return value = @code{BZ_FINISHING} + +FINISHING/other + Illegal. + Return value = @code{BZ_SEQUENCE_ERROR} +@end display + +That still looks complicated? Well, fair enough. The usual sequence +of calls for compressing a load of data is: +@itemize @bullet +@item Get started with @code{BZ2_bzCompressInit}. +@item Shovel data in and shlurp out its compressed form using zero or more +calls of @code{BZ2_bzCompress} with action = @code{BZ_RUN}. +@item Finish up. +Repeatedly call @code{BZ2_bzCompress} with action = @code{BZ_FINISH}, +copying out the compressed output, until @code{BZ_STREAM_END} is returned. +@item Close up and go home. Call @code{BZ2_bzCompressEnd}. +@end itemize +If the data you want to compress fits into your input buffer all +at once, you can skip the calls of @code{BZ2_bzCompress ( ..., BZ_RUN )} and +just do the @code{BZ2_bzCompress ( ..., BZ_FINISH )} calls. + +All required memory is allocated by @code{BZ2_bzCompressInit}. The +compression library can accept any data at all (obviously). So you +shouldn't get any error return values from the @code{BZ2_bzCompress} calls. +If you do, they will be @code{BZ_SEQUENCE_ERROR}, and indicate a bug in +your programming. + +Trivial other possible return values: +@display + @code{BZ_PARAM_ERROR} + if @code{strm} is @code{NULL}, or @code{strm->s} is @code{NULL} +@end display + +@subsection @code{BZ2_bzCompressEnd} +@example +int BZ2_bzCompressEnd ( bz_stream *strm ); +@end example +Releases all memory associated with a compression stream. + +Possible return values: +@display + @code{BZ_PARAM_ERROR} if @code{strm} is @code{NULL} or @code{strm->s} is @code{NULL} + @code{BZ_OK} otherwise +@end display + + +@subsection @code{BZ2_bzDecompressInit} +@example +int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small ); +@end example +Prepares for decompression. As with @code{BZ2_bzCompressInit}, a +@code{bz_stream} record should be allocated and initialised before the +call. Fields @code{bzalloc}, @code{bzfree} and @code{opaque} should be +set if a custom memory allocator is required, or made @code{NULL} for +the normal @code{malloc}/@code{free} routines. Upon return, the internal +state will have been initialised, and @code{total_in} and +@code{total_out} will be zero. + +For the meaning of parameter @code{verbosity}, see @code{BZ2_bzCompressInit}. + +If @code{small} is nonzero, the library will use an alternative +decompression algorithm which uses less memory but at the cost of +decompressing more slowly (roughly speaking, half the speed, but the +maximum memory requirement drops to around 2300k). See Chapter 2 for +more information on memory management. + +Note that the amount of memory needed to decompress +a stream cannot be determined until the stream's header has been read, +so even if @code{BZ2_bzDecompressInit} succeeds, a subsequent +@code{BZ2_bzDecompress} could fail with @code{BZ_MEM_ERROR}. + +Possible return values: +@display + @code{BZ_CONFIG_ERROR} + if the library has been mis-compiled + @code{BZ_PARAM_ERROR} + if @code{(small != 0 && small != 1)} + or @code{(verbosity < 0 || verbosity > 4)} + @code{BZ_MEM_ERROR} + if insufficient memory is available +@end display + +Allowable next actions: +@display + @code{BZ2_bzDecompress} + if @code{BZ_OK} was returned + no specific action required in case of error +@end display + + + +@subsection @code{BZ2_bzDecompress} +@example +int BZ2_bzDecompress ( bz_stream *strm ); +@end example +Provides more input and/out output buffer space for the library. The +caller maintains input and output buffers, and uses @code{BZ2_bzDecompress} +to transfer data between them. + +Before each call to @code{BZ2_bzDecompress}, @code{next_in} +should point at the compressed data, +and @code{avail_in} should indicate how many bytes the library +may read. @code{BZ2_bzDecompress} updates @code{next_in}, @code{avail_in} +and @code{total_in} +to reflect the number of bytes it has read. + +Similarly, @code{next_out} should point to a buffer in which the uncompressed +output is to be placed, with @code{avail_out} indicating how much output space +is available. @code{BZ2_bzCompress} updates @code{next_out}, +@code{avail_out} and @code{total_out} to reflect +the number of bytes output. + +You may provide and remove as little or as much data as you like on +each call of @code{BZ2_bzDecompress}. +In the limit, it is acceptable to +supply and remove data one byte at a time, although this would be +terribly inefficient. You should always ensure that at least one +byte of output space is available at each call. + +Use of @code{BZ2_bzDecompress} is simpler than @code{BZ2_bzCompress}. + +You should provide input and remove output as described above, and +repeatedly call @code{BZ2_bzDecompress} until @code{BZ_STREAM_END} is +returned. Appearance of @code{BZ_STREAM_END} denotes that +@code{BZ2_bzDecompress} has detected the logical end of the compressed +stream. @code{BZ2_bzDecompress} will not produce @code{BZ_STREAM_END} until +all output data has been placed into the output buffer, so once +@code{BZ_STREAM_END} appears, you are guaranteed to have available all +the decompressed output, and @code{BZ2_bzDecompressEnd} can safely be +called. + +If case of an error return value, you should call @code{BZ2_bzDecompressEnd} +to clean up and release memory. + +Possible return values: +@display + @code{BZ_PARAM_ERROR} + if @code{strm} is @code{NULL} or @code{strm->s} is @code{NULL} + or @code{strm->avail_out < 1} + @code{BZ_DATA_ERROR} + if a data integrity error is detected in the compressed stream + @code{BZ_DATA_ERROR_MAGIC} + if the compressed stream doesn't begin with the right magic bytes + @code{BZ_MEM_ERROR} + if there wasn't enough memory available + @code{BZ_STREAM_END} + if the logical end of the data stream was detected and all + output in has been consumed, eg @code{s->avail_out > 0} + @code{BZ_OK} + otherwise +@end display +Allowable next actions: +@display + @code{BZ2_bzDecompress} + if @code{BZ_OK} was returned + @code{BZ2_bzDecompressEnd} + otherwise +@end display + + +@subsection @code{BZ2_bzDecompressEnd} +@example +int BZ2_bzDecompressEnd ( bz_stream *strm ); +@end example +Releases all memory associated with a decompression stream. + +Possible return values: +@display + @code{BZ_PARAM_ERROR} + if @code{strm} is @code{NULL} or @code{strm->s} is @code{NULL} + @code{BZ_OK} + otherwise +@end display + +Allowable next actions: +@display + None. +@end display + + +@section High-level interface + +This interface provides functions for reading and writing +@code{bzip2} format files. First, some general points. + +@itemize @bullet +@item All of the functions take an @code{int*} first argument, + @code{bzerror}. + After each call, @code{bzerror} should be consulted first to determine + the outcome of the call. If @code{bzerror} is @code{BZ_OK}, + the call completed + successfully, and only then should the return value of the function + (if any) be consulted. If @code{bzerror} is @code{BZ_IO_ERROR}, + there was an error + reading/writing the underlying compressed file, and you should + then consult @code{errno}/@code{perror} to determine the + cause of the difficulty. + @code{bzerror} may also be set to various other values; precise details are + given on a per-function basis below. +@item If @code{bzerror} indicates an error + (ie, anything except @code{BZ_OK} and @code{BZ_STREAM_END}), + you should immediately call @code{BZ2_bzReadClose} (or @code{BZ2_bzWriteClose}, + depending on whether you are attempting to read or to write) + to free up all resources associated + with the stream. Once an error has been indicated, behaviour of all calls + except @code{BZ2_bzReadClose} (@code{BZ2_bzWriteClose}) is undefined. + The implication is that (1) @code{bzerror} should + be checked after each call, and (2) if @code{bzerror} indicates an error, + @code{BZ2_bzReadClose} (@code{BZ2_bzWriteClose}) should then be called to clean up. +@item The @code{FILE*} arguments passed to + @code{BZ2_bzReadOpen}/@code{BZ2_bzWriteOpen} + should be set to binary mode. + Most Unix systems will do this by default, but other platforms, + including Windows and Mac, will not. If you omit this, you may + encounter problems when moving code to new platforms. +@item Memory allocation requests are handled by + @code{malloc}/@code{free}. + At present + there is no facility for user-defined memory allocators in the file I/O + functions (could easily be added, though). +@end itemize + + + +@subsection @code{BZ2_bzReadOpen} +@example + typedef void BZFILE; + + BZFILE *BZ2_bzReadOpen ( int *bzerror, FILE *f, + int small, int verbosity, + void *unused, int nUnused ); +@end example +Prepare to read compressed data from file handle @code{f}. @code{f} +should refer to a file which has been opened for reading, and for which +the error indicator (@code{ferror(f)})is not set. If @code{small} is 1, +the library will try to decompress using less memory, at the expense of +speed. + +For reasons explained below, @code{BZ2_bzRead} will decompress the +@code{nUnused} bytes starting at @code{unused}, before starting to read +from the file @code{f}. At most @code{BZ_MAX_UNUSED} bytes may be +supplied like this. If this facility is not required, you should pass +@code{NULL} and @code{0} for @code{unused} and n@code{Unused} +respectively. + +For the meaning of parameters @code{small} and @code{verbosity}, +see @code{BZ2_bzDecompressInit}. + +The amount of memory needed to decompress a file cannot be determined +until the file's header has been read. So it is possible that +@code{BZ2_bzReadOpen} returns @code{BZ_OK} but a subsequent call of +@code{BZ2_bzRead} will return @code{BZ_MEM_ERROR}. + +Possible assignments to @code{bzerror}: +@display + @code{BZ_CONFIG_ERROR} + if the library has been mis-compiled + @code{BZ_PARAM_ERROR} + if @code{f} is @code{NULL} + or @code{small} is neither @code{0} nor @code{1} + or @code{(unused == NULL && nUnused != 0)} + or @code{(unused != NULL && !(0 <= nUnused <= BZ_MAX_UNUSED))} + @code{BZ_IO_ERROR} + if @code{ferror(f)} is nonzero + @code{BZ_MEM_ERROR} + if insufficient memory is available + @code{BZ_OK} + otherwise. +@end display + +Possible return values: +@display + Pointer to an abstract @code{BZFILE} + if @code{bzerror} is @code{BZ_OK} + @code{NULL} + otherwise +@end display + +Allowable next actions: +@display + @code{BZ2_bzRead} + if @code{bzerror} is @code{BZ_OK} + @code{BZ2_bzClose} + otherwise +@end display + + +@subsection @code{BZ2_bzRead} +@example + int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len ); +@end example +Reads up to @code{len} (uncompressed) bytes from the compressed file +@code{b} into +the buffer @code{buf}. If the read was successful, +@code{bzerror} is set to @code{BZ_OK} +and the number of bytes read is returned. If the logical end-of-stream +was detected, @code{bzerror} will be set to @code{BZ_STREAM_END}, +and the number +of bytes read is returned. All other @code{bzerror} values denote an error. + +@code{BZ2_bzRead} will supply @code{len} bytes, +unless the logical stream end is detected +or an error occurs. Because of this, it is possible to detect the +stream end by observing when the number of bytes returned is +less than the number +requested. Nevertheless, this is regarded as inadvisable; you should +instead check @code{bzerror} after every call and watch out for +@code{BZ_STREAM_END}. + +Internally, @code{BZ2_bzRead} copies data from the compressed file in chunks +of size @code{BZ_MAX_UNUSED} bytes +before decompressing it. If the file contains more bytes than strictly +needed to reach the logical end-of-stream, @code{BZ2_bzRead} will almost certainly +read some of the trailing data before signalling @code{BZ_SEQUENCE_END}. +To collect the read but unused data once @code{BZ_SEQUENCE_END} has +appeared, call @code{BZ2_bzReadGetUnused} immediately before @code{BZ2_bzReadClose}. + +Possible assignments to @code{bzerror}: +@display + @code{BZ_PARAM_ERROR} + if @code{b} is @code{NULL} or @code{buf} is @code{NULL} or @code{len < 0} + @code{BZ_SEQUENCE_ERROR} + if @code{b} was opened with @code{BZ2_bzWriteOpen} + @code{BZ_IO_ERROR} + if there is an error reading from the compressed file + @code{BZ_UNEXPECTED_EOF} + if the compressed file ended before the logical end-of-stream was detected + @code{BZ_DATA_ERROR} + if a data integrity error was detected in the compressed stream + @code{BZ_DATA_ERROR_MAGIC} + if the stream does not begin with the requisite header bytes (ie, is not + a @code{bzip2} data file). This is really a special case of @code{BZ_DATA_ERROR}. + @code{BZ_MEM_ERROR} + if insufficient memory was available + @code{BZ_STREAM_END} + if the logical end of stream was detected. + @code{BZ_OK} + otherwise. +@end display + +Possible return values: +@display + number of bytes read + if @code{bzerror} is @code{BZ_OK} or @code{BZ_STREAM_END} + undefined + otherwise +@end display + +Allowable next actions: +@display + collect data from @code{buf}, then @code{BZ2_bzRead} or @code{BZ2_bzReadClose} + if @code{bzerror} is @code{BZ_OK} + collect data from @code{buf}, then @code{BZ2_bzReadClose} or @code{BZ2_bzReadGetUnused} + if @code{bzerror} is @code{BZ_SEQUENCE_END} + @code{BZ2_bzReadClose} + otherwise +@end display + + + +@subsection @code{BZ2_bzReadGetUnused} +@example + void BZ2_bzReadGetUnused ( int* bzerror, BZFILE *b, + void** unused, int* nUnused ); +@end example +Returns data which was read from the compressed file but was not needed +to get to the logical end-of-stream. @code{*unused} is set to the address +of the data, and @code{*nUnused} to the number of bytes. @code{*nUnused} will +be set to a value between @code{0} and @code{BZ_MAX_UNUSED} inclusive. + +This function may only be called once @code{BZ2_bzRead} has signalled +@code{BZ_STREAM_END} but before @code{BZ2_bzReadClose}. + +Possible assignments to @code{bzerror}: +@display + @code{BZ_PARAM_ERROR} + if @code{b} is @code{NULL} + or @code{unused} is @code{NULL} or @code{nUnused} is @code{NULL} + @code{BZ_SEQUENCE_ERROR} + if @code{BZ_STREAM_END} has not been signalled + or if @code{b} was opened with @code{BZ2_bzWriteOpen} + @code{BZ_OK} + otherwise +@end display + +Allowable next actions: +@display + @code{BZ2_bzReadClose} +@end display + + +@subsection @code{BZ2_bzReadClose} +@example + void BZ2_bzReadClose ( int *bzerror, BZFILE *b ); +@end example +Releases all memory pertaining to the compressed file @code{b}. +@code{BZ2_bzReadClose} does not call @code{fclose} on the underlying file +handle, so you should do that yourself if appropriate. +@code{BZ2_bzReadClose} should be called to clean up after all error +situations. + +Possible assignments to @code{bzerror}: +@display + @code{BZ_SEQUENCE_ERROR} + if @code{b} was opened with @code{BZ2_bzOpenWrite} + @code{BZ_OK} + otherwise +@end display + +Allowable next actions: +@display + none +@end display + + + +@subsection @code{BZ2_bzWriteOpen} +@example + BZFILE *BZ2_bzWriteOpen ( int *bzerror, FILE *f, + int blockSize100k, int verbosity, + int workFactor ); +@end example +Prepare to write compressed data to file handle @code{f}. +@code{f} should refer to +a file which has been opened for writing, and for which the error +indicator (@code{ferror(f)})is not set. + +For the meaning of parameters @code{blockSize100k}, +@code{verbosity} and @code{workFactor}, see +@* @code{BZ2_bzCompressInit}. + +All required memory is allocated at this stage, so if the call +completes successfully, @code{BZ_MEM_ERROR} cannot be signalled by a +subsequent call to @code{BZ2_bzWrite}. + +Possible assignments to @code{bzerror}: +@display + @code{BZ_CONFIG_ERROR} + if the library has been mis-compiled + @code{BZ_PARAM_ERROR} + if @code{f} is @code{NULL} + or @code{blockSize100k < 1} or @code{blockSize100k > 9} + @code{BZ_IO_ERROR} + if @code{ferror(f)} is nonzero + @code{BZ_MEM_ERROR} + if insufficient memory is available + @code{BZ_OK} + otherwise +@end display + +Possible return values: +@display + Pointer to an abstract @code{BZFILE} + if @code{bzerror} is @code{BZ_OK} + @code{NULL} + otherwise +@end display + +Allowable next actions: +@display + @code{BZ2_bzWrite} + if @code{bzerror} is @code{BZ_OK} + (you could go directly to @code{BZ2_bzWriteClose}, but this would be pretty pointless) + @code{BZ2_bzWriteClose} + otherwise +@end display + + + +@subsection @code{BZ2_bzWrite} +@example + void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len ); +@end example +Absorbs @code{len} bytes from the buffer @code{buf}, eventually to be +compressed and written to the file. + +Possible assignments to @code{bzerror}: +@display + @code{BZ_PARAM_ERROR} + if @code{b} is @code{NULL} or @code{buf} is @code{NULL} or @code{len < 0} + @code{BZ_SEQUENCE_ERROR} + if b was opened with @code{BZ2_bzReadOpen} + @code{BZ_IO_ERROR} + if there is an error writing the compressed file. + @code{BZ_OK} + otherwise +@end display + + + + +@subsection @code{BZ2_bzWriteClose} +@example + void BZ2_bzWriteClose ( int *bzerror, BZFILE* f, + int abandon, + unsigned int* nbytes_in, + unsigned int* nbytes_out ); + + void BZ2_bzWriteClose64 ( int *bzerror, BZFILE* f, + int abandon, + unsigned int* nbytes_in_lo32, + unsigned int* nbytes_in_hi32, + unsigned int* nbytes_out_lo32, + unsigned int* nbytes_out_hi32 ); +@end example + +Compresses and flushes to the compressed file all data so far supplied +by @code{BZ2_bzWrite}. The logical end-of-stream markers are also written, so +subsequent calls to @code{BZ2_bzWrite} are illegal. All memory associated +with the compressed file @code{b} is released. +@code{fflush} is called on the +compressed file, but it is not @code{fclose}'d. + +If @code{BZ2_bzWriteClose} is called to clean up after an error, the only +action is to release the memory. The library records the error codes +issued by previous calls, so this situation will be detected +automatically. There is no attempt to complete the compression +operation, nor to @code{fflush} the compressed file. You can force this +behaviour to happen even in the case of no error, by passing a nonzero +value to @code{abandon}. + +If @code{nbytes_in} is non-null, @code{*nbytes_in} will be set to be the +total volume of uncompressed data handled. Similarly, @code{nbytes_out} +will be set to the total volume of compressed data written. For +compatibility with older versions of the library, @code{BZ2_bzWriteClose} +only yields the lower 32 bits of these counts. Use +@code{BZ2_bzWriteClose64} if you want the full 64 bit counts. These +two functions are otherwise absolutely identical. + + +Possible assignments to @code{bzerror}: +@display + @code{BZ_SEQUENCE_ERROR} + if @code{b} was opened with @code{BZ2_bzReadOpen} + @code{BZ_IO_ERROR} + if there is an error writing the compressed file + @code{BZ_OK} + otherwise +@end display + +@subsection Handling embedded compressed data streams + +The high-level library facilitates use of +@code{bzip2} data streams which form some part of a surrounding, larger +data stream. +@itemize @bullet +@item For writing, the library takes an open file handle, writes +compressed data to it, @code{fflush}es it but does not @code{fclose} it. +The calling application can write its own data before and after the +compressed data stream, using that same file handle. +@item Reading is more complex, and the facilities are not as general +as they could be since generality is hard to reconcile with efficiency. +@code{BZ2_bzRead} reads from the compressed file in blocks of size +@code{BZ_MAX_UNUSED} bytes, and in doing so probably will overshoot +the logical end of compressed stream. +To recover this data once decompression has +ended, call @code{BZ2_bzReadGetUnused} after the last call of @code{BZ2_bzRead} +(the one returning @code{BZ_STREAM_END}) but before calling +@code{BZ2_bzReadClose}. +@end itemize + +This mechanism makes it easy to decompress multiple @code{bzip2} +streams placed end-to-end. As the end of one stream, when @code{BZ2_bzRead} +returns @code{BZ_STREAM_END}, call @code{BZ2_bzReadGetUnused} to collect the +unused data (copy it into your own buffer somewhere). +That data forms the start of the next compressed stream. +To start uncompressing that next stream, call @code{BZ2_bzReadOpen} again, +feeding in the unused data via the @code{unused}/@code{nUnused} +parameters. +Keep doing this until @code{BZ_STREAM_END} return coincides with the +physical end of file (@code{feof(f)}). In this situation +@code{BZ2_bzReadGetUnused} +will of course return no data. + +This should give some feel for how the high-level interface can be used. +If you require extra flexibility, you'll have to bite the bullet and get +to grips with the low-level interface. + +@subsection Standard file-reading/writing code +Here's how you'd write data to a compressed file: +@example @code +FILE* f; +BZFILE* b; +int nBuf; +char buf[ /* whatever size you like */ ]; +int bzerror; +int nWritten; + +f = fopen ( "myfile.bz2", "w" ); +if (!f) @{ + /* handle error */ +@} +b = BZ2_bzWriteOpen ( &bzerror, f, 9 ); +if (bzerror != BZ_OK) @{ + BZ2_bzWriteClose ( b ); + /* handle error */ +@} + +while ( /* condition */ ) @{ + /* get data to write into buf, and set nBuf appropriately */ + nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf ); + if (bzerror == BZ_IO_ERROR) @{ + BZ2_bzWriteClose ( &bzerror, b ); + /* handle error */ + @} +@} + +BZ2_bzWriteClose ( &bzerror, b ); +if (bzerror == BZ_IO_ERROR) @{ + /* handle error */ +@} +@end example +And to read from a compressed file: +@example +FILE* f; +BZFILE* b; +int nBuf; +char buf[ /* whatever size you like */ ]; +int bzerror; +int nWritten; + +f = fopen ( "myfile.bz2", "r" ); +if (!f) @{ + /* handle error */ +@} +b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 ); +if (bzerror != BZ_OK) @{ + BZ2_bzReadClose ( &bzerror, b ); + /* handle error */ +@} + +bzerror = BZ_OK; +while (bzerror == BZ_OK && /* arbitrary other conditions */) @{ + nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ ); + if (bzerror == BZ_OK) @{ + /* do something with buf[0 .. nBuf-1] */ + @} +@} +if (bzerror != BZ_STREAM_END) @{ + BZ2_bzReadClose ( &bzerror, b ); + /* handle error */ +@} else @{ + BZ2_bzReadClose ( &bzerror ); +@} +@end example + + + +@section Utility functions +@subsection @code{BZ2_bzBuffToBuffCompress} +@example + int BZ2_bzBuffToBuffCompress( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int blockSize100k, + int verbosity, + int workFactor ); +@end example +Attempts to compress the data in @code{source[0 .. sourceLen-1]} +into the destination buffer, @code{dest[0 .. *destLen-1]}. +If the destination buffer is big enough, @code{*destLen} is +set to the size of the compressed data, and @code{BZ_OK} is +returned. If the compressed data won't fit, @code{*destLen} +is unchanged, and @code{BZ_OUTBUFF_FULL} is returned. + +Compression in this manner is a one-shot event, done with a single call +to this function. The resulting compressed data is a complete +@code{bzip2} format data stream. There is no mechanism for making +additional calls to provide extra input data. If you want that kind of +mechanism, use the low-level interface. + +For the meaning of parameters @code{blockSize100k}, @code{verbosity} +and @code{workFactor}, @* see @code{BZ2_bzCompressInit}. + +To guarantee that the compressed data will fit in its buffer, allocate +an output buffer of size 1% larger than the uncompressed data, plus +six hundred extra bytes. + +@code{BZ2_bzBuffToBuffDecompress} will not write data at or +beyond @code{dest[*destLen]}, even in case of buffer overflow. + +Possible return values: +@display + @code{BZ_CONFIG_ERROR} + if the library has been mis-compiled + @code{BZ_PARAM_ERROR} + if @code{dest} is @code{NULL} or @code{destLen} is @code{NULL} + or @code{blockSize100k < 1} or @code{blockSize100k > 9} + or @code{verbosity < 0} or @code{verbosity > 4} + or @code{workFactor < 0} or @code{workFactor > 250} + @code{BZ_MEM_ERROR} + if insufficient memory is available + @code{BZ_OUTBUFF_FULL} + if the size of the compressed data exceeds @code{*destLen} + @code{BZ_OK} + otherwise +@end display + + + +@subsection @code{BZ2_bzBuffToBuffDecompress} +@example + int BZ2_bzBuffToBuffDecompress ( char* dest, + unsigned int* destLen, + char* source, + unsigned int sourceLen, + int small, + int verbosity ); +@end example +Attempts to decompress the data in @code{source[0 .. sourceLen-1]} +into the destination buffer, @code{dest[0 .. *destLen-1]}. +If the destination buffer is big enough, @code{*destLen} is +set to the size of the uncompressed data, and @code{BZ_OK} is +returned. If the compressed data won't fit, @code{*destLen} +is unchanged, and @code{BZ_OUTBUFF_FULL} is returned. + +@code{source} is assumed to hold a complete @code{bzip2} format +data stream. @* @code{BZ2_bzBuffToBuffDecompress} tries to decompress +the entirety of the stream into the output buffer. + +For the meaning of parameters @code{small} and @code{verbosity}, +see @code{BZ2_bzDecompressInit}. + +Because the compression ratio of the compressed data cannot be known in +advance, there is no easy way to guarantee that the output buffer will +be big enough. You may of course make arrangements in your code to +record the size of the uncompressed data, but such a mechanism is beyond +the scope of this library. + +@code{BZ2_bzBuffToBuffDecompress} will not write data at or +beyond @code{dest[*destLen]}, even in case of buffer overflow. + +Possible return values: +@display + @code{BZ_CONFIG_ERROR} + if the library has been mis-compiled + @code{BZ_PARAM_ERROR} + if @code{dest} is @code{NULL} or @code{destLen} is @code{NULL} + or @code{small != 0 && small != 1} + or @code{verbosity < 0} or @code{verbosity > 4} + @code{BZ_MEM_ERROR} + if insufficient memory is available + @code{BZ_OUTBUFF_FULL} + if the size of the compressed data exceeds @code{*destLen} + @code{BZ_DATA_ERROR} + if a data integrity error was detected in the compressed data + @code{BZ_DATA_ERROR_MAGIC} + if the compressed data doesn't begin with the right magic bytes + @code{BZ_UNEXPECTED_EOF} + if the compressed data ends unexpectedly + @code{BZ_OK} + otherwise +@end display + + + +@section @code{zlib} compatibility functions +Yoshioka Tsuneo has contributed some functions to +give better @code{zlib} compatibility. These functions are +@code{BZ2_bzopen}, @code{BZ2_bzread}, @code{BZ2_bzwrite}, @code{BZ2_bzflush}, +@code{BZ2_bzclose}, +@code{BZ2_bzerror} and @code{BZ2_bzlibVersion}. +These functions are not (yet) officially part of +the library. If they break, you get to keep all the pieces. +Nevertheless, I think they work ok. +@example +typedef void BZFILE; + +const char * BZ2_bzlibVersion ( void ); +@end example +Returns a string indicating the library version. +@example +BZFILE * BZ2_bzopen ( const char *path, const char *mode ); +BZFILE * BZ2_bzdopen ( int fd, const char *mode ); +@end example +Opens a @code{.bz2} file for reading or writing, using either its name +or a pre-existing file descriptor. +Analogous to @code{fopen} and @code{fdopen}. +@example +int BZ2_bzread ( BZFILE* b, void* buf, int len ); +int BZ2_bzwrite ( BZFILE* b, void* buf, int len ); +@end example +Reads/writes data from/to a previously opened @code{BZFILE}. +Analogous to @code{fread} and @code{fwrite}. +@example +int BZ2_bzflush ( BZFILE* b ); +void BZ2_bzclose ( BZFILE* b ); +@end example +Flushes/closes a @code{BZFILE}. @code{BZ2_bzflush} doesn't actually do +anything. Analogous to @code{fflush} and @code{fclose}. + +@example +const char * BZ2_bzerror ( BZFILE *b, int *errnum ) +@end example +Returns a string describing the more recent error status of +@code{b}, and also sets @code{*errnum} to its numerical value. + + +@section Using the library in a @code{stdio}-free environment + +@subsection Getting rid of @code{stdio} + +In a deeply embedded application, you might want to use just +the memory-to-memory functions. You can do this conveniently +by compiling the library with preprocessor symbol @code{BZ_NO_STDIO} +defined. Doing this gives you a library containing only the following +eight functions: + +@code{BZ2_bzCompressInit}, @code{BZ2_bzCompress}, @code{BZ2_bzCompressEnd} @* +@code{BZ2_bzDecompressInit}, @code{BZ2_bzDecompress}, @code{BZ2_bzDecompressEnd} @* +@code{BZ2_bzBuffToBuffCompress}, @code{BZ2_bzBuffToBuffDecompress} + +When compiled like this, all functions will ignore @code{verbosity} +settings. + +@subsection Critical error handling +@code{libbzip2} contains a number of internal assertion checks which +should, needless to say, never be activated. Nevertheless, if an +assertion should fail, behaviour depends on whether or not the library +was compiled with @code{BZ_NO_STDIO} set. + +For a normal compile, an assertion failure yields the message +@example + bzip2/libbzip2: internal error number N. + This is a bug in bzip2/libbzip2, 1.0 of 21-Mar-2000. + Please report it to me at: jseward@@acm.org. If this happened + when you were using some program which uses libbzip2 as a + component, you should also report this bug to the author(s) + of that program. Please make an effort to report this bug; + timely and accurate bug reports eventually lead to higher + quality software. Thanks. Julian Seward, 21 March 2000. +@end example +where @code{N} is some error code number. @code{exit(3)} +is then called. + +For a @code{stdio}-free library, assertion failures result +in a call to a function declared as: +@example + extern void bz_internal_error ( int errcode ); +@end example +The relevant code is passed as a parameter. You should supply +such a function. + +In either case, once an assertion failure has occurred, any +@code{bz_stream} records involved can be regarded as invalid. +You should not attempt to resume normal operation with them. + +You may, of course, change critical error handling to suit +your needs. As I said above, critical errors indicate bugs +in the library and should not occur. All "normal" error +situations are indicated via error return codes from functions, +and can be recovered from. + + +@section Making a Windows DLL +Everything related to Windows has been contributed by Yoshioka Tsuneo +@* (@code{QWF00133@@niftyserve.or.jp} / +@code{tsuneo-y@@is.aist-nara.ac.jp}), so you should send your queries to +him (but perhaps Cc: me, @code{jseward@@acm.org}). + +My vague understanding of what to do is: using Visual C++ 5.0, +open the project file @code{libbz2.dsp}, and build. That's all. + +If you can't +open the project file for some reason, make a new one, naming these files: +@code{blocksort.c}, @code{bzlib.c}, @code{compress.c}, +@code{crctable.c}, @code{decompress.c}, @code{huffman.c}, @* +@code{randtable.c} and @code{libbz2.def}. You will also need +to name the header files @code{bzlib.h} and @code{bzlib_private.h}. + +If you don't use VC++, you may need to define the proprocessor symbol +@code{_WIN32}. + +Finally, @code{dlltest.c} is a sample program using the DLL. It has a +project file, @code{dlltest.dsp}. + +If you just want a makefile for Visual C, have a look at +@code{makefile.msc}. + +Be aware that if you compile @code{bzip2} itself on Win32, you must set +@code{BZ_UNIX} to 0 and @code{BZ_LCCWIN32} to 1, in the file +@code{bzip2.c}, before compiling. Otherwise the resulting binary won't +work correctly. + +I haven't tried any of this stuff myself, but it all looks plausible. + + + +@chapter Miscellanea + +These are just some random thoughts of mine. Your mileage may +vary. + +@section Limitations of the compressed file format +@code{bzip2-1.0}, @code{0.9.5} and @code{0.9.0} +use exactly the same file format as the previous +version, @code{bzip2-0.1}. This decision was made in the interests of +stability. Creating yet another incompatible compressed file format +would create further confusion and disruption for users. + +Nevertheless, this is not a painless decision. Development +work since the release of @code{bzip2-0.1} in August 1997 +has shown complexities in the file format which slow down +decompression and, in retrospect, are unnecessary. These are: +@itemize @bullet +@item The run-length encoder, which is the first of the + compression transformations, is entirely irrelevant. + The original purpose was to protect the sorting algorithm + from the very worst case input: a string of repeated + symbols. But algorithm steps Q6a and Q6b in the original + Burrows-Wheeler technical report (SRC-124) show how + repeats can be handled without difficulty in block + sorting. +@item The randomisation mechanism doesn't really need to be + there. Udi Manber and Gene Myers published a suffix + array construction algorithm a few years back, which + can be employed to sort any block, no matter how + repetitive, in O(N log N) time. Subsequent work by + Kunihiko Sadakane has produced a derivative O(N (log N)^2) + algorithm which usually outperforms the Manber-Myers + algorithm. + + I could have changed to Sadakane's algorithm, but I find + it to be slower than @code{bzip2}'s existing algorithm for + most inputs, and the randomisation mechanism protects + adequately against bad cases. I didn't think it was + a good tradeoff to make. Partly this is due to the fact + that I was not flooded with email complaints about + @code{bzip2-0.1}'s performance on repetitive data, so + perhaps it isn't a problem for real inputs. + + Probably the best long-term solution, + and the one I have incorporated into 0.9.5 and above, + is to use the existing sorting + algorithm initially, and fall back to a O(N (log N)^2) + algorithm if the standard algorithm gets into difficulties. +@item The compressed file format was never designed to be + handled by a library, and I have had to jump though + some hoops to produce an efficient implementation of + decompression. It's a bit hairy. Try passing + @code{decompress.c} through the C preprocessor + and you'll see what I mean. Much of this complexity + could have been avoided if the compressed size of + each block of data was recorded in the data stream. +@item An Adler-32 checksum, rather than a CRC32 checksum, + would be faster to compute. +@end itemize +It would be fair to say that the @code{bzip2} format was frozen +before I properly and fully understood the performance +consequences of doing so. + +Improvements which I was able to incorporate into +0.9.0, despite using the same file format, are: +@itemize @bullet +@item Single array implementation of the inverse BWT. This + significantly speeds up decompression, presumably + because it reduces the number of cache misses. +@item Faster inverse MTF transform for large MTF values. The + new implementation is based on the notion of sliding blocks + of values. +@item @code{bzip2-0.9.0} now reads and writes files with @code{fread} + and @code{fwrite}; version 0.1 used @code{putc} and @code{getc}. + Duh! Well, you live and learn. + +@end itemize +Further ahead, it would be nice +to be able to do random access into files. This will +require some careful design of compressed file formats. + + + +@section Portability issues +After some consideration, I have decided not to use +GNU @code{autoconf} to configure 0.9.5 or 1.0. + +@code{autoconf}, admirable and wonderful though it is, +mainly assists with portability problems between Unix-like +platforms. But @code{bzip2} doesn't have much in the way +of portability problems on Unix; most of the difficulties appear +when porting to the Mac, or to Microsoft's operating systems. +@code{autoconf} doesn't help in those cases, and brings in a +whole load of new complexity. + +Most people should be able to compile the library and program +under Unix straight out-of-the-box, so to speak, especially +if you have a version of GNU C available. + +There are a couple of @code{__inline__} directives in the code. GNU C +(@code{gcc}) should be able to handle them. If you're not using +GNU C, your C compiler shouldn't see them at all. +If your compiler does, for some reason, see them and doesn't +like them, just @code{#define} @code{__inline__} to be @code{/* */}. One +easy way to do this is to compile with the flag @code{-D__inline__=}, +which should be understood by most Unix compilers. + +If you still have difficulties, try compiling with the macro +@code{BZ_STRICT_ANSI} defined. This should enable you to build the +library in a strictly ANSI compliant environment. Building the program +itself like this is dangerous and not supported, since you remove +@code{bzip2}'s checks against compressing directories, symbolic links, +devices, and other not-really-a-file entities. This could cause +filesystem corruption! + +One other thing: if you create a @code{bzip2} binary for public +distribution, please try and link it statically (@code{gcc -s}). This +avoids all sorts of library-version issues that others may encounter +later on. + +If you build @code{bzip2} on Win32, you must set @code{BZ_UNIX} to 0 and +@code{BZ_LCCWIN32} to 1, in the file @code{bzip2.c}, before compiling. +Otherwise the resulting binary won't work correctly. + + + +@section Reporting bugs +I tried pretty hard to make sure @code{bzip2} is +bug free, both by design and by testing. Hopefully +you'll never need to read this section for real. + +Nevertheless, if @code{bzip2} dies with a segmentation +fault, a bus error or an internal assertion failure, it +will ask you to email me a bug report. Experience with +version 0.1 shows that almost all these problems can +be traced to either compiler bugs or hardware problems. +@itemize @bullet +@item +Recompile the program with no optimisation, and see if it +works. And/or try a different compiler. +I heard all sorts of stories about various flavours +of GNU C (and other compilers) generating bad code for +@code{bzip2}, and I've run across two such examples myself. + +2.7.X versions of GNU C are known to generate bad code from +time to time, at high optimisation levels. +If you get problems, try using the flags +@code{-O2} @code{-fomit-frame-pointer} @code{-fno-strength-reduce}. +You should specifically @emph{not} use @code{-funroll-loops}. + +You may notice that the Makefile runs six tests as part of +the build process. If the program passes all of these, it's +a pretty good (but not 100%) indication that the compiler has +done its job correctly. +@item +If @code{bzip2} crashes randomly, and the crashes are not +repeatable, you may have a flaky memory subsystem. @code{bzip2} +really hammers your memory hierarchy, and if it's a bit marginal, +you may get these problems. Ditto if your disk or I/O subsystem +is slowly failing. Yup, this really does happen. + +Try using a different machine of the same type, and see if +you can repeat the problem. +@item This isn't really a bug, but ... If @code{bzip2} tells +you your file is corrupted on decompression, and you +obtained the file via FTP, there is a possibility that you +forgot to tell FTP to do a binary mode transfer. That absolutely +will cause the file to be non-decompressible. You'll have to transfer +it again. +@end itemize + +If you've incorporated @code{libbzip2} into your own program +and are getting problems, please, please, please, check that the +parameters you are passing in calls to the library, are +correct, and in accordance with what the documentation says +is allowable. I have tried to make the library robust against +such problems, but I'm sure I haven't succeeded. + +Finally, if the above comments don't help, you'll have to send +me a bug report. Now, it's just amazing how many people will +send me a bug report saying something like +@display + bzip2 crashed with segmentation fault on my machine +@end display +and absolutely nothing else. Needless to say, a such a report +is @emph{totally, utterly, completely and comprehensively 100% useless; +a waste of your time, my time, and net bandwidth}. +With no details at all, there's no way I can possibly begin +to figure out what the problem is. + +The rules of the game are: facts, facts, facts. Don't omit +them because "oh, they won't be relevant". At the bare +minimum: +@display + Machine type. Operating system version. + Exact version of @code{bzip2} (do @code{bzip2 -V}). + Exact version of the compiler used. + Flags passed to the compiler. +@end display +However, the most important single thing that will help me is +the file that you were trying to compress or decompress at the +time the problem happened. Without that, my ability to do anything +more than speculate about the cause, is limited. + +Please remember that I connect to the Internet with a modem, so +you should contact me before mailing me huge files. + + +@section Did you get the right package? + +@code{bzip2} is a resource hog. It soaks up large amounts of CPU cycles +and memory. Also, it gives very large latencies. In the worst case, you +can feed many megabytes of uncompressed data into the library before +getting any compressed output, so this probably rules out applications +requiring interactive behaviour. + +These aren't faults of my implementation, I hope, but more +an intrinsic property of the Burrows-Wheeler transform (unfortunately). +Maybe this isn't what you want. + +If you want a compressor and/or library which is faster, uses less +memory but gets pretty good compression, and has minimal latency, +consider Jean-loup +Gailly's and Mark Adler's work, @code{zlib-1.1.2} and +@code{gzip-1.2.4}. Look for them at + +@code{http://www.cdrom.com/pub/infozip/zlib} and +@code{http://www.gzip.org} respectively. + +For something faster and lighter still, you might try Markus F X J +Oberhumer's @code{LZO} real-time compression/decompression library, at +@* @code{http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html}. + +If you want to use the @code{bzip2} algorithms to compress small blocks +of data, 64k bytes or smaller, for example on an on-the-fly disk +compressor, you'd be well advised not to use this library. Instead, +I've made a special library tuned for that kind of use. It's part of +@code{e2compr-0.40}, an on-the-fly disk compressor for the Linux +@code{ext2} filesystem. Look at +@code{http://www.netspace.net.au/~reiter/e2compr}. + + + +@section Testing + +A record of the tests I've done. + +First, some data sets: +@itemize @bullet +@item B: a directory containing 6001 files, one for every length in the + range 0 to 6000 bytes. The files contain random lowercase + letters. 18.7 megabytes. +@item H: my home directory tree. Documents, source code, mail files, + compressed data. H contains B, and also a directory of + files designed as boundary cases for the sorting; mostly very + repetitive, nasty files. 565 megabytes. +@item A: directory tree holding various applications built from source: + @code{egcs}, @code{gcc-2.8.1}, KDE, GTK, Octave, etc. + 2200 megabytes. +@end itemize +The tests conducted are as follows. Each test means compressing +(a copy of) each file in the data set, decompressing it and +comparing it against the original. + +First, a bunch of tests with block sizes and internal buffer +sizes set very small, +to detect any problems with the +blocking and buffering mechanisms. +This required modifying the source code so as to try to +break it. +@enumerate +@item Data set H, with + buffer size of 1 byte, and block size of 23 bytes. +@item Data set B, buffer sizes 1 byte, block size 1 byte. +@item As (2) but small-mode decompression. +@item As (2) with block size 2 bytes. +@item As (2) with block size 3 bytes. +@item As (2) with block size 4 bytes. +@item As (2) with block size 5 bytes. +@item As (2) with block size 6 bytes and small-mode decompression. +@item H with buffer size of 1 byte, but normal block + size (up to 900000 bytes). +@end enumerate +Then some tests with unmodified source code. +@enumerate +@item H, all settings normal. +@item As (1), with small-mode decompress. +@item H, compress with flag @code{-1}. +@item H, compress with flag @code{-s}, decompress with flag @code{-s}. +@item Forwards compatibility: H, @code{bzip2-0.1pl2} compressing, + @code{bzip2-0.9.5} decompressing, all settings normal. +@item Backwards compatibility: H, @code{bzip2-0.9.5} compressing, + @code{bzip2-0.1pl2} decompressing, all settings normal. +@item Bigger tests: A, all settings normal. +@item As (7), using the fallback (Sadakane-like) sorting algorithm. +@item As (8), compress with flag @code{-1}, decompress with flag + @code{-s}. +@item H, using the fallback sorting algorithm. +@item Forwards compatibility: A, @code{bzip2-0.1pl2} compressing, + @code{bzip2-0.9.5} decompressing, all settings normal. +@item Backwards compatibility: A, @code{bzip2-0.9.5} compressing, + @code{bzip2-0.1pl2} decompressing, all settings normal. +@item Misc test: about 400 megabytes of @code{.tar} files with + @code{bzip2} compiled with Checker (a memory access error + detector, like Purify). +@item Misc tests to make sure it builds and runs ok on non-Linux/x86 + platforms. +@end enumerate +These tests were conducted on a 225 MHz IDT WinChip machine, running +Linux 2.0.36. They represent nearly a week of continuous computation. +All tests completed successfully. + + +@section Further reading +@code{bzip2} is not research work, in the sense that it doesn't present +any new ideas. Rather, it's an engineering exercise based on existing +ideas. + +Four documents describe essentially all the ideas behind @code{bzip2}: +@example +Michael Burrows and D. J. Wheeler: + "A block-sorting lossless data compression algorithm" + 10th May 1994. + Digital SRC Research Report 124. + ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz + If you have trouble finding it, try searching at the + New Zealand Digital Library, http://www.nzdl.org. + +Daniel S. Hirschberg and Debra A. LeLewer + "Efficient Decoding of Prefix Codes" + Communications of the ACM, April 1990, Vol 33, Number 4. + You might be able to get an electronic copy of this + from the ACM Digital Library. + +David J. Wheeler + Program bred3.c and accompanying document bred3.ps. + This contains the idea behind the multi-table Huffman + coding scheme. + ftp://ftp.cl.cam.ac.uk/users/djw3/ + +Jon L. Bentley and Robert Sedgewick + "Fast Algorithms for Sorting and Searching Strings" + Available from Sedgewick's web page, + www.cs.princeton.edu/~rs +@end example +The following paper gives valuable additional insights into the +algorithm, but is not immediately the basis of any code +used in bzip2. +@example +Peter Fenwick: + Block Sorting Text Compression + Proceedings of the 19th Australasian Computer Science Conference, + Melbourne, Australia. Jan 31 - Feb 2, 1996. + ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps +@end example +Kunihiko Sadakane's sorting algorithm, mentioned above, +is available from: +@example +http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz +@end example +The Manber-Myers suffix array construction +algorithm is described in a paper +available from: +@example +http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps +@end example +Finally, the following paper documents some recent investigations +I made into the performance of sorting algorithms: +@example +Julian Seward: + On the Performance of BWT Sorting Algorithms + Proceedings of the IEEE Data Compression Conference 2000 + Snowbird, Utah. 28-30 March 2000. +@end example + + +@contents + +@bye + diff --git a/drivers/lib/bzip2/manual_1.html b/drivers/lib/bzip2/manual_1.html new file mode 100644 index 0000000..92ba7c6 --- /dev/null +++ b/drivers/lib/bzip2/manual_1.html @@ -0,0 +1,47 @@ + + + + +bzip2 and libbzip2 - Introduction + + + + + +

Go to the first, previous, next, last section, table of contents. +


+ + +

Introduction

+ +

+bzip2 compresses files using the Burrows-Wheeler +block-sorting text compression algorithm, and Huffman coding. +Compression is generally considerably better than that +achieved by more conventional LZ77/LZ78-based compressors, +and approaches the performance of the PPM family of statistical compressors. + +

+

+bzip2 is built on top of libbzip2, a flexible library +for handling compressed data in the bzip2 format. This manual +describes both how to use the program and +how to work with the library interface. Most of the +manual is devoted to this library, not the program, +which is good news if your interest is only in the program. + +

+

+Chapter 2 describes how to use bzip2; this is the only part +you need to read if you just want to know how to operate the program. +Chapter 3 describes the programming interfaces in detail, and +Chapter 4 records some miscellaneous notes which I thought +ought to be recorded somewhere. + +

+ +


+

Go to the first, previous, next, last section, table of contents. + + diff --git a/drivers/lib/bzip2/manual_2.html b/drivers/lib/bzip2/manual_2.html new file mode 100644 index 0000000..39453c4 --- /dev/null +++ b/drivers/lib/bzip2/manual_2.html @@ -0,0 +1,484 @@ + + + + +bzip2 and libbzip2 - How to use bzip2 + + + + + + +

Go to the first, previous, next, last section, table of contents. +


+ + +

How to use bzip2

+ +

+This chapter contains a copy of the bzip2 man page, +and nothing else. + +

+ +
+ + + +

NAME

+ +
    +
  • bzip2, bunzip2 + +- a block-sorting file compressor, v1.0 +
  • bzcat + +- decompresses files to stdout +
  • bzip2recover + +- recovers data from damaged bzip2 files +
+ + + +

SYNOPSIS

+ +
    +
  • bzip2 [ -cdfkqstvzVL123456789 ] [ filenames ... ] + +
  • bunzip2 [ -fkvsVL ] [ filenames ... ] + +
  • bzcat [ -s ] [ filenames ... ] + +
  • bzip2recover filename + +
+ + + +

DESCRIPTION

+ +

+bzip2 compresses files using the Burrows-Wheeler block sorting +text compression algorithm, and Huffman coding. Compression is +generally considerably better than that achieved by more conventional +LZ77/LZ78-based compressors, and approaches the performance of the PPM +family of statistical compressors. + +

+

+The command-line options are deliberately very similar to those of GNU +gzip, but they are not identical. + +

+

+bzip2 expects a list of file names to accompany the command-line +flags. Each file is replaced by a compressed version of itself, with +the name original_name.bz2. Each compressed file has the same +modification date, permissions, and, when possible, ownership as the +corresponding original, so that these properties can be correctly +restored at decompression time. File name handling is naive in the +sense that there is no mechanism for preserving original file names, +permissions, ownerships or dates in filesystems which lack these +concepts, or have serious file name length restrictions, such as MS-DOS. + +

+

+bzip2 and bunzip2 will by default not overwrite existing +files. If you want this to happen, specify the -f flag. + +

+

+If no file names are specified, bzip2 compresses from standard +input to standard output. In this case, bzip2 will decline to +write compressed output to a terminal, as this would be entirely +incomprehensible and therefore pointless. + +

+

+bunzip2 (or bzip2 -d) decompresses all +specified files. Files which were not created by bzip2 +will be detected and ignored, and a warning issued. +bzip2 attempts to guess the filename for the decompressed file +from that of the compressed file as follows: + +

    +
  • filename.bz2 becomes filename + +
  • filename.bz becomes filename + +
  • filename.tbz2 becomes filename.tar + +
  • filename.tbz becomes filename.tar + +
  • anyothername becomes anyothername.out + +
+ +

+If the file does not end in one of the recognised endings, +.bz2, .bz, +.tbz2 or .tbz, bzip2 complains that it cannot +guess the name of the original file, and uses the original name +with .out appended. + +

+

+As with compression, supplying no +filenames causes decompression from standard input to standard output. + +

+

+bunzip2 will correctly decompress a file which is the +concatenation of two or more compressed files. The result is the +concatenation of the corresponding uncompressed files. Integrity +testing (-t) of concatenated compressed files is also supported. + +

+

+You can also compress or decompress files to the standard output by +giving the -c flag. Multiple files may be compressed and +decompressed like this. The resulting outputs are fed sequentially to +stdout. Compression of multiple files in this manner generates a stream +containing multiple compressed file representations. Such a stream +can be decompressed correctly only by bzip2 version 0.9.0 or +later. Earlier versions of bzip2 will stop after decompressing +the first file in the stream. + +

+

+bzcat (or bzip2 -dc) decompresses all specified files to +the standard output. + +

+

+bzip2 will read arguments from the environment variables +BZIP2 and BZIP, in that order, and will process them +before any arguments read from the command line. This gives a +convenient way to supply default arguments. + +

+

+Compression is always performed, even if the compressed file is slightly +larger than the original. Files of less than about one hundred bytes +tend to get larger, since the compression mechanism has a constant +overhead in the region of 50 bytes. Random data (including the output +of most file compressors) is coded at about 8.05 bits per byte, giving +an expansion of around 0.5%. + +

+

+As a self-check for your protection, bzip2 uses 32-bit CRCs to +make sure that the decompressed version of a file is identical to the +original. This guards against corruption of the compressed data, and +against undetected bugs in bzip2 (hopefully very unlikely). The +chances of data corruption going undetected is microscopic, about one +chance in four billion for each file processed. Be aware, though, that +the check occurs upon decompression, so it can only tell you that +something is wrong. It can't help you recover the original uncompressed +data. You can use bzip2recover to try to recover data from +damaged files. + +

+

+Return values: 0 for a normal exit, 1 for environmental problems (file +not found, invalid flags, I/O errors, &c), 2 to indicate a corrupt +compressed file, 3 for an internal consistency error (eg, bug) which +caused bzip2 to panic. + +

+ + + +

OPTIONS

+
+ +
-c --stdout +
+Compress or decompress to standard output. +
-d --decompress +
+Force decompression. bzip2, bunzip2 and bzcat are +really the same program, and the decision about what actions to take is +done on the basis of which name is used. This flag overrides that +mechanism, and forces bzip2 to decompress. +
-z --compress +
+The complement to -d: forces compression, regardless of the +invokation name. +
-t --test +
+Check integrity of the specified file(s), but don't decompress them. +This really performs a trial decompression and throws away the result. +
-f --force +
+Force overwrite of output files. Normally, bzip2 will not overwrite +existing output files. Also forces bzip2 to break hard links +to files, which it otherwise wouldn't do. +
-k --keep +
+Keep (don't delete) input files during compression +or decompression. +
-s --small +
+Reduce memory usage, for compression, decompression and testing. Files +are decompressed and tested using a modified algorithm which only +requires 2.5 bytes per block byte. This means any file can be +decompressed in 2300k of memory, albeit at about half the normal speed. + +During compression, -s selects a block size of 200k, which limits +memory use to around the same figure, at the expense of your compression +ratio. In short, if your machine is low on memory (8 megabytes or +less), use -s for everything. See MEMORY MANAGEMENT below. +
-q --quiet +
+Suppress non-essential warning messages. Messages pertaining to +I/O errors and other critical events will not be suppressed. +
-v --verbose +
+Verbose mode -- show the compression ratio for each file processed. +Further -v's increase the verbosity level, spewing out lots of +information which is primarily of interest for diagnostic purposes. +
-L --license -V --version +
+Display the software version, license terms and conditions. +
-1 to -9 +
+Set the block size to 100 k, 200 k .. 900 k when compressing. Has no +effect when decompressing. See MEMORY MANAGEMENT below. +
-- +
+Treats all subsequent arguments as file names, even if they start +with a dash. This is so you can handle files with names beginning +with a dash, for example: bzip2 -- -myfilename. +
--repetitive-fast +
+
--repetitive-best +
+These flags are redundant in versions 0.9.5 and above. They provided +some coarse control over the behaviour of the sorting algorithm in +earlier versions, which was sometimes useful. 0.9.5 and above have an +improved algorithm which renders these flags irrelevant. +
+ + + +

MEMORY MANAGEMENT

+ +

+bzip2 compresses large files in blocks. The block size affects +both the compression ratio achieved, and the amount of memory needed for +compression and decompression. The flags -1 through -9 +specify the block size to be 100,000 bytes through 900,000 bytes (the +default) respectively. At decompression time, the block size used for +compression is read from the header of the compressed file, and +bunzip2 then allocates itself just enough memory to decompress +the file. Since block sizes are stored in compressed files, it follows +that the flags -1 to -9 are irrelevant to and so ignored +during decompression. + +

+

+Compression and decompression requirements, in bytes, can be estimated +as: + +

+     Compression:   400k + ( 8 x block size )
+
+     Decompression: 100k + ( 4 x block size ), or
+                    100k + ( 2.5 x block size )
+
+ +

+Larger block sizes give rapidly diminishing marginal returns. Most of +the compression comes from the first two or three hundred k of block +size, a fact worth bearing in mind when using bzip2 on small machines. +It is also important to appreciate that the decompression memory +requirement is set at compression time by the choice of block size. + +

+

+For files compressed with the default 900k block size, bunzip2 +will require about 3700 kbytes to decompress. To support decompression +of any file on a 4 megabyte machine, bunzip2 has an option to +decompress using approximately half this amount of memory, about 2300 +kbytes. Decompression speed is also halved, so you should use this +option only where necessary. The relevant flag is -s. + +

+

+In general, try and use the largest block size memory constraints allow, +since that maximises the compression achieved. Compression and +decompression speed are virtually unaffected by block size. + +

+

+Another significant point applies to files which fit in a single block +-- that means most files you'd encounter using a large block size. The +amount of real memory touched is proportional to the size of the file, +since the file is smaller than a block. For example, compressing a file +20,000 bytes long with the flag -9 will cause the compressor to +allocate around 7600k of memory, but only touch 400k + 20000 * 8 = 560 +kbytes of it. Similarly, the decompressor will allocate 3700k but only +touch 100k + 20000 * 4 = 180 kbytes. + +

+

+Here is a table which summarises the maximum memory usage for different +block sizes. Also recorded is the total compressed size for 14 files of +the Calgary Text Compression Corpus totalling 3,141,622 bytes. This +column gives some feel for how compression varies with block size. +These figures tend to understate the advantage of larger block sizes for +larger files, since the Corpus is dominated by smaller files. + +

+          Compress   Decompress   Decompress   Corpus
+   Flag     usage      usage       -s usage     Size
+
+    -1      1200k       500k         350k      914704
+    -2      2000k       900k         600k      877703
+    -3      2800k      1300k         850k      860338
+    -4      3600k      1700k        1100k      846899
+    -5      4400k      2100k        1350k      845160
+    -6      5200k      2500k        1600k      838626
+    -7      6100k      2900k        1850k      834096
+    -8      6800k      3300k        2100k      828642
+    -9      7600k      3700k        2350k      828642
+
+ + + +

RECOVERING DATA FROM DAMAGED FILES

+ +

+bzip2 compresses files in blocks, usually 900kbytes long. Each +block is handled independently. If a media or transmission error causes +a multi-block .bz2 file to become damaged, it may be possible to +recover data from the undamaged blocks in the file. + +

+

+The compressed representation of each block is delimited by a 48-bit +pattern, which makes it possible to find the block boundaries with +reasonable certainty. Each block also carries its own 32-bit CRC, so +damaged blocks can be distinguished from undamaged ones. + +

+

+bzip2recover is a simple program whose purpose is to search for +blocks in .bz2 files, and write each block out into its own +.bz2 file. You can then use bzip2 -t to test the +integrity of the resulting files, and decompress those which are +undamaged. + +

+

+bzip2recover +takes a single argument, the name of the damaged file, +and writes a number of files rec0001file.bz2, + rec0002file.bz2, etc, containing the extracted blocks. + The output filenames are designed so that the use of + wildcards in subsequent processing -- for example, +bzip2 -dc rec*file.bz2 > recovered_data -- lists the files in + the correct order. + +

+

+bzip2recover should be of most use dealing with large .bz2 + files, as these will contain many blocks. It is clearly + futile to use it on damaged single-block files, since a + damaged block cannot be recovered. If you wish to minimise +any potential data loss through media or transmission errors, +you might consider compressing with a smaller + block size. + +

+ + + +

PERFORMANCE NOTES

+ +

+The sorting phase of compression gathers together similar strings in the +file. Because of this, files containing very long runs of repeated +symbols, like "aabaabaabaab ..." (repeated several hundred times) may +compress more slowly than normal. Versions 0.9.5 and above fare much +better than previous versions in this respect. The ratio between +worst-case and average-case compression time is in the region of 10:1. +For previous versions, this figure was more like 100:1. You can use the +-vvvv option to monitor progress in great detail, if you want. + +

+

+Decompression speed is unaffected by these phenomena. + +

+

+bzip2 usually allocates several megabytes of memory to operate +in, and then charges all over it in a fairly random fashion. This means +that performance, both for compressing and decompressing, is largely +determined by the speed at which your machine can service cache misses. +Because of this, small changes to the code to reduce the miss rate have +been observed to give disproportionately large performance improvements. +I imagine bzip2 will perform best on machines with very large +caches. + +

+ + + +

CAVEATS

+ +

+I/O error messages are not as helpful as they could be. bzip2 +tries hard to detect I/O errors and exit cleanly, but the details of +what the problem is sometimes seem rather misleading. + +

+

+This manual page pertains to version 1.0 of bzip2. Compressed +data created by this version is entirely forwards and backwards +compatible with the previous public releases, versions 0.1pl2, 0.9.0 and +0.9.5, but with the following exception: 0.9.0 and above can correctly +decompress multiple concatenated compressed files. 0.1pl2 cannot do +this; it will stop after decompressing just the first file in the +stream. + +

+

+bzip2recover uses 32-bit integers to represent bit positions in +compressed files, so it cannot handle compressed files more than 512 +megabytes long. This could easily be fixed. + +

+ + + +

AUTHOR

+

+Julian Seward, jseward@acm.org. + +

+

+The ideas embodied in bzip2 are due to (at least) the following +people: Michael Burrows and David Wheeler (for the block sorting +transformation), David Wheeler (again, for the Huffman coder), Peter +Fenwick (for the structured coding model in the original bzip, +and many refinements), and Alistair Moffat, Radford Neal and Ian Witten +(for the arithmetic coder in the original bzip). I am much +indebted for their help, support and advice. See the manual in the +source distribution for pointers to sources of documentation. Christian +von Roques encouraged me to look for faster sorting algorithms, so as to +speed up compression. Bela Lubkin encouraged me to improve the +worst-case compression performance. Many people sent patches, helped +with portability problems, lent machines, gave advice and were generally +helpful. + +

+
+ +


+

Go to the first, previous, next, last section, table of contents. + + diff --git a/drivers/lib/bzip2/manual_3.html b/drivers/lib/bzip2/manual_3.html new file mode 100644 index 0000000..a8fa7e6 --- /dev/null +++ b/drivers/lib/bzip2/manual_3.html @@ -0,0 +1,1773 @@ + + + + +bzip2 and libbzip2 - Programming with libbzip2 + + + + + + +

Go to the first, previous, next, last section, table of contents. +


+ + +

Programming with libbzip2

+ +

+This chapter describes the programming interface to libbzip2. + +

+

+For general background information, particularly about memory +use and performance aspects, you'd be well advised to read Chapter 2 +as well. + +

+ + +

Top-level structure

+ +

+libbzip2 is a flexible library for compressing and decompressing +data in the bzip2 data format. Although packaged as a single +entity, it helps to regard the library as three separate parts: the low +level interface, and the high level interface, and some utility +functions. + +

+

+The structure of libbzip2's interfaces is similar to +that of Jean-loup Gailly's and Mark Adler's excellent zlib +library. + +

+

+All externally visible symbols have names beginning BZ2_. +This is new in version 1.0. The intention is to minimise pollution +of the namespaces of library clients. + +

+ + +

Low-level summary

+ +

+This interface provides services for compressing and decompressing +data in memory. There's no provision for dealing with files, streams +or any other I/O mechanisms, just straight memory-to-memory work. +In fact, this part of the library can be compiled without inclusion +of stdio.h, which may be helpful for embedded applications. + +

+

+The low-level part of the library has no global variables and +is therefore thread-safe. + +

+

+Six routines make up the low level interface: +BZ2_bzCompressInit, BZ2_bzCompress, and
BZ2_bzCompressEnd +for compression, +and a corresponding trio BZ2_bzDecompressInit,
BZ2_bzDecompress +and BZ2_bzDecompressEnd for decompression. +The *Init functions allocate +memory for compression/decompression and do other +initialisations, whilst the *End functions close down operations +and release memory. + +

+

+The real work is done by BZ2_bzCompress and BZ2_bzDecompress. +These compress and decompress data from a user-supplied input buffer +to a user-supplied output buffer. These buffers can be any size; +arbitrary quantities of data are handled by making repeated calls +to these functions. This is a flexible mechanism allowing a +consumer-pull style of activity, or producer-push, or a mixture of +both. + +

+ + + +

High-level summary

+ +

+This interface provides some handy wrappers around the low-level +interface to facilitate reading and writing bzip2 format +files (.bz2 files). The routines provide hooks to facilitate +reading files in which the bzip2 data stream is embedded +within some larger-scale file structure, or where there are +multiple bzip2 data streams concatenated end-to-end. + +

+

+For reading files, BZ2_bzReadOpen, BZ2_bzRead, +BZ2_bzReadClose and
BZ2_bzReadGetUnused are supplied. For +writing files, BZ2_bzWriteOpen, BZ2_bzWrite and +BZ2_bzWriteFinish are available. + +

+

+As with the low-level library, no global variables are used +so the library is per se thread-safe. However, if I/O errors +occur whilst reading or writing the underlying compressed files, +you may have to consult errno to determine the cause of +the error. In that case, you'd need a C library which correctly +supports errno in a multithreaded environment. + +

+

+To make the library a little simpler and more portable, +BZ2_bzReadOpen and BZ2_bzWriteOpen require you to pass them file +handles (FILE*s) which have previously been opened for reading or +writing respectively. That avoids portability problems associated with +file operations and file attributes, whilst not being much of an +imposition on the programmer. + +

+ + + +

Utility functions summary

+

+For very simple needs, BZ2_bzBuffToBuffCompress and +BZ2_bzBuffToBuffDecompress are provided. These compress +data in memory from one buffer to another buffer in a single +function call. You should assess whether these functions +fulfill your memory-to-memory compression/decompression +requirements before investing effort in understanding the more +general but more complex low-level interface. + +

+

+Yoshioka Tsuneo (QWF00133@niftyserve.or.jp / +tsuneo-y@is.aist-nara.ac.jp) has contributed some functions to +give better zlib compatibility. These functions are +BZ2_bzopen, BZ2_bzread, BZ2_bzwrite, BZ2_bzflush, +BZ2_bzclose, +BZ2_bzerror and BZ2_bzlibVersion. You may find these functions +more convenient for simple file reading and writing, than those in the +high-level interface. These functions are not (yet) officially part of +the library, and are minimally documented here. If they break, you +get to keep all the pieces. I hope to document them properly when time +permits. + +

+

+Yoshioka also contributed modifications to allow the library to be +built as a Windows DLL. + +

+ + + +

Error handling

+ +

+The library is designed to recover cleanly in all situations, including +the worst-case situation of decompressing random data. I'm not +100% sure that it can always do this, so you might want to add +a signal handler to catch segmentation violations during decompression +if you are feeling especially paranoid. I would be interested in +hearing more about the robustness of the library to corrupted +compressed data. + +

+

+Version 1.0 is much more robust in this respect than +0.9.0 or 0.9.5. Investigations with Checker (a tool for +detecting problems with memory management, similar to Purify) +indicate that, at least for the few files I tested, all single-bit +errors in the decompressed data are caught properly, with no +segmentation faults, no reads of uninitialised data and no +out of range reads or writes. So it's certainly much improved, +although I wouldn't claim it to be totally bombproof. + +

+

+The file bzlib.h contains all definitions needed to use +the library. In particular, you should definitely not include +bzlib_private.h. + +

+

+In bzlib.h, the various return values are defined. The following +list is not intended as an exhaustive description of the circumstances +in which a given value may be returned -- those descriptions are given +later. Rather, it is intended to convey the rough meaning of each +return value. The first five actions are normal and not intended to +denote an error situation. +

+ +
BZ_OK +
+The requested action was completed successfully. +
BZ_RUN_OK +
+
BZ_FLUSH_OK +
+
BZ_FINISH_OK +
+In BZ2_bzCompress, the requested flush/finish/nothing-special action +was completed successfully. +
BZ_STREAM_END +
+Compression of data was completed, or the logical stream end was +detected during decompression. +
+ +

+The following return values indicate an error of some kind. +

+ +
BZ_CONFIG_ERROR +
+Indicates that the library has been improperly compiled on your +platform -- a major configuration error. Specifically, it means +that sizeof(char), sizeof(short) and sizeof(int) +are not 1, 2 and 4 respectively, as they should be. Note that the +library should still work properly on 64-bit platforms which follow +the LP64 programming model -- that is, where sizeof(long) +and sizeof(void*) are 8. Under LP64, sizeof(int) is +still 4, so libbzip2, which doesn't use the long type, +is OK. +
BZ_SEQUENCE_ERROR +
+When using the library, it is important to call the functions in the +correct sequence and with data structures (buffers etc) in the correct +states. libbzip2 checks as much as it can to ensure this is +happening, and returns BZ_SEQUENCE_ERROR if not. Code which +complies precisely with the function semantics, as detailed below, +should never receive this value; such an event denotes buggy code +which you should investigate. +
BZ_PARAM_ERROR +
+Returned when a parameter to a function call is out of range +or otherwise manifestly incorrect. As with BZ_SEQUENCE_ERROR, +this denotes a bug in the client code. The distinction between +BZ_PARAM_ERROR and BZ_SEQUENCE_ERROR is a bit hazy, but still worth +making. +
BZ_MEM_ERROR +
+Returned when a request to allocate memory failed. Note that the +quantity of memory needed to decompress a stream cannot be determined +until the stream's header has been read. So BZ2_bzDecompress and +BZ2_bzRead may return BZ_MEM_ERROR even though some of +the compressed data has been read. The same is not true for +compression; once BZ2_bzCompressInit or BZ2_bzWriteOpen have +successfully completed, BZ_MEM_ERROR cannot occur. +
BZ_DATA_ERROR +
+Returned when a data integrity error is detected during decompression. +Most importantly, this means when stored and computed CRCs for the +data do not match. This value is also returned upon detection of any +other anomaly in the compressed data. +
BZ_DATA_ERROR_MAGIC +
+As a special case of BZ_DATA_ERROR, it is sometimes useful to +know when the compressed stream does not start with the correct +magic bytes ('B' 'Z' 'h'). +
BZ_IO_ERROR +
+Returned by BZ2_bzRead and BZ2_bzWrite when there is an error +reading or writing in the compressed file, and by BZ2_bzReadOpen +and BZ2_bzWriteOpen for attempts to use a file for which the +error indicator (viz, ferror(f)) is set. +On receipt of BZ_IO_ERROR, the caller should consult +errno and/or perror to acquire operating-system +specific information about the problem. +
BZ_UNEXPECTED_EOF +
+Returned by BZ2_bzRead when the compressed file finishes +before the logical end of stream is detected. +
BZ_OUTBUFF_FULL +
+Returned by BZ2_bzBuffToBuffCompress and +BZ2_bzBuffToBuffDecompress to indicate that the output data +will not fit into the output buffer provided. +
+ + + +

Low-level interface

+ + + +

BZ2_bzCompressInit

+ +
+typedef 
+   struct {
+      char *next_in;
+      unsigned int avail_in;
+      unsigned int total_in_lo32;
+      unsigned int total_in_hi32;
+
+      char *next_out;
+      unsigned int avail_out;
+      unsigned int total_out_lo32;
+      unsigned int total_out_hi32;
+
+      void *state;
+
+      void *(*bzalloc)(void *,int,int);
+      void (*bzfree)(void *,void *);
+      void *opaque;
+   } 
+   bz_stream;
+
+int BZ2_bzCompressInit ( bz_stream *strm, 
+                         int blockSize100k, 
+                         int verbosity,
+                         int workFactor );
+
+
+ +

+Prepares for compression. The bz_stream structure +holds all data pertaining to the compression activity. +A bz_stream structure should be allocated and initialised +prior to the call. +The fields of bz_stream +comprise the entirety of the user-visible data. state +is a pointer to the private data structures required for compression. + +

+

+Custom memory allocators are supported, via fields bzalloc, +bzfree, +and opaque. The value +opaque is passed to as the first argument to +all calls to bzalloc and bzfree, but is +otherwise ignored by the library. +The call bzalloc ( opaque, n, m ) is expected to return a +pointer p to +n * m bytes of memory, and bzfree ( opaque, p ) +should free +that memory. + +

+

+If you don't want to use a custom memory allocator, set bzalloc, +bzfree and +opaque to NULL, +and the library will then use the standard malloc/free +routines. + +

+

+Before calling BZ2_bzCompressInit, fields bzalloc, +bzfree and opaque should +be filled appropriately, as just described. Upon return, the internal +state will have been allocated and initialised, and total_in_lo32, +total_in_hi32, total_out_lo32 and +total_out_hi32 will have been set to zero. +These four fields are used by the library +to inform the caller of the total amount of data passed into and out of +the library, respectively. You should not try to change them. +As of version 1.0, 64-bit counts are maintained, even on 32-bit +platforms, using the _hi32 fields to store the upper 32 bits +of the count. So, for example, the total amount of data in +is (total_in_hi32 << 32) + total_in_lo32. + +

+

+Parameter blockSize100k specifies the block size to be used for +compression. It should be a value between 1 and 9 inclusive, and the +actual block size used is 100000 x this figure. 9 gives the best +compression but takes most memory. + +

+

+Parameter verbosity should be set to a number between 0 and 4 +inclusive. 0 is silent, and greater numbers give increasingly verbose +monitoring/debugging output. If the library has been compiled with +-DBZ_NO_STDIO, no such output will appear for any verbosity +setting. + +

+

+Parameter workFactor controls how the compression phase behaves +when presented with worst case, highly repetitive, input data. If +compression runs into difficulties caused by repetitive data, the +library switches from the standard sorting algorithm to a fallback +algorithm. The fallback is slower than the standard algorithm by +perhaps a factor of three, but always behaves reasonably, no matter how +bad the input. + +

+

+Lower values of workFactor reduce the amount of effort the +standard algorithm will expend before resorting to the fallback. You +should set this parameter carefully; too low, and many inputs will be +handled by the fallback algorithm and so compress rather slowly, too +high, and your average-to-worst case compression times can become very +large. The default value of 30 gives reasonable behaviour over a wide +range of circumstances. + +

+

+Allowable values range from 0 to 250 inclusive. 0 is a special case, +equivalent to using the default value of 30. + +

+

+Note that the compressed output generated is the same regardless of +whether or not the fallback algorithm is used. + +

+

+Be aware also that this parameter may disappear entirely in future +versions of the library. In principle it should be possible to devise a +good way to automatically choose which algorithm to use. Such a +mechanism would render the parameter obsolete. + +

+

+Possible return values: + +

+      BZ_CONFIG_ERROR
+         if the library has been mis-compiled
+      BZ_PARAM_ERROR 
+         if strm is NULL 
+         or blockSize < 1 or blockSize > 9
+         or verbosity < 0 or verbosity > 4
+         or workFactor < 0 or workFactor > 250
+      BZ_MEM_ERROR 
+         if not enough memory is available
+      BZ_OK 
+         otherwise
+
+ +

+Allowable next actions: + +

+      BZ2_bzCompress 
+         if BZ_OK is returned
+      no specific action needed in case of error
+
+ + + +

BZ2_bzCompress

+ +
+   int BZ2_bzCompress ( bz_stream *strm, int action );
+
+ +

+Provides more input and/or output buffer space for the library. The +caller maintains input and output buffers, and calls BZ2_bzCompress to +transfer data between them. + +

+

+Before each call to BZ2_bzCompress, next_in should point at +the data to be compressed, and avail_in should indicate how many +bytes the library may read. BZ2_bzCompress updates next_in, +avail_in and total_in to reflect the number of bytes it +has read. + +

+

+Similarly, next_out should point to a buffer in which the +compressed data is to be placed, with avail_out indicating how +much output space is available. BZ2_bzCompress updates +next_out, avail_out and total_out to reflect the +number of bytes output. + +

+

+You may provide and remove as little or as much data as you like on each +call of BZ2_bzCompress. In the limit, it is acceptable to supply and +remove data one byte at a time, although this would be terribly +inefficient. You should always ensure that at least one byte of output +space is available at each call. + +

+

+A second purpose of BZ2_bzCompress is to request a change of mode of the +compressed stream. + +

+

+Conceptually, a compressed stream can be in one of four states: IDLE, +RUNNING, FLUSHING and FINISHING. Before initialisation +(BZ2_bzCompressInit) and after termination (BZ2_bzCompressEnd), a +stream is regarded as IDLE. + +

+

+Upon initialisation (BZ2_bzCompressInit), the stream is placed in the +RUNNING state. Subsequent calls to BZ2_bzCompress should pass +BZ_RUN as the requested action; other actions are illegal and +will result in BZ_SEQUENCE_ERROR. + +

+

+At some point, the calling program will have provided all the input data +it wants to. It will then want to finish up -- in effect, asking the +library to process any data it might have buffered internally. In this +state, BZ2_bzCompress will no longer attempt to read data from +next_in, but it will want to write data to next_out. +Because the output buffer supplied by the user can be arbitrarily small, +the finishing-up operation cannot necessarily be done with a single call +of BZ2_bzCompress. + +

+

+Instead, the calling program passes BZ_FINISH as an action to +BZ2_bzCompress. This changes the stream's state to FINISHING. Any +remaining input (ie, next_in[0 .. avail_in-1]) is compressed and +transferred to the output buffer. To do this, BZ2_bzCompress must be +called repeatedly until all the output has been consumed. At that +point, BZ2_bzCompress returns BZ_STREAM_END, and the stream's +state is set back to IDLE. BZ2_bzCompressEnd should then be +called. + +

+

+Just to make sure the calling program does not cheat, the library makes +a note of avail_in at the time of the first call to +BZ2_bzCompress which has BZ_FINISH as an action (ie, at the +time the program has announced its intention to not supply any more +input). By comparing this value with that of avail_in over +subsequent calls to BZ2_bzCompress, the library can detect any +attempts to slip in more data to compress. Any calls for which this is +detected will return BZ_SEQUENCE_ERROR. This indicates a +programming mistake which should be corrected. + +

+

+Instead of asking to finish, the calling program may ask +BZ2_bzCompress to take all the remaining input, compress it and +terminate the current (Burrows-Wheeler) compression block. This could +be useful for error control purposes. The mechanism is analogous to +that for finishing: call BZ2_bzCompress with an action of +BZ_FLUSH, remove output data, and persist with the +BZ_FLUSH action until the value BZ_RUN is returned. As +with finishing, BZ2_bzCompress detects any attempt to provide more +input data once the flush has begun. + +

+

+Once the flush is complete, the stream returns to the normal RUNNING +state. + +

+

+This all sounds pretty complex, but isn't really. Here's a table +which shows which actions are allowable in each state, what action +will be taken, what the next state is, and what the non-error return +values are. Note that you can't explicitly ask what state the +stream is in, but nor do you need to -- it can be inferred from the +values returned by BZ2_bzCompress. + +

+IDLE/any           
+      Illegal.  IDLE state only exists after BZ2_bzCompressEnd or
+      before BZ2_bzCompressInit.
+      Return value = BZ_SEQUENCE_ERROR
+
+RUNNING/BZ_RUN     
+      Compress from next_in to next_out as much as possible.
+      Next state = RUNNING
+      Return value = BZ_RUN_OK
+
+RUNNING/BZ_FLUSH   
+      Remember current value of next_in.  Compress from next_in
+      to next_out as much as possible, but do not accept any more input.  
+      Next state = FLUSHING
+      Return value = BZ_FLUSH_OK
+
+RUNNING/BZ_FINISH  
+      Remember current value of next_in.  Compress from next_in
+      to next_out as much as possible, but do not accept any more input.
+      Next state = FINISHING
+      Return value = BZ_FINISH_OK
+
+FLUSHING/BZ_FLUSH  
+      Compress from next_in to next_out as much as possible, 
+      but do not accept any more input.  
+      If all the existing input has been used up and all compressed
+      output has been removed
+         Next state = RUNNING; Return value = BZ_RUN_OK
+      else
+         Next state = FLUSHING; Return value = BZ_FLUSH_OK
+
+FLUSHING/other     
+      Illegal.
+      Return value = BZ_SEQUENCE_ERROR
+
+FINISHING/BZ_FINISH  
+      Compress from next_in to next_out as much as possible,
+      but to not accept any more input.  
+      If all the existing input has been used up and all compressed
+      output has been removed
+         Next state = IDLE; Return value = BZ_STREAM_END
+      else
+         Next state = FINISHING; Return value = BZ_FINISHING
+
+FINISHING/other
+      Illegal.
+      Return value = BZ_SEQUENCE_ERROR
+
+ +

+That still looks complicated? Well, fair enough. The usual sequence +of calls for compressing a load of data is: + +

    +
  • Get started with BZ2_bzCompressInit. + +
  • Shovel data in and shlurp out its compressed form using zero or more + +calls of BZ2_bzCompress with action = BZ_RUN. +
  • Finish up. + +Repeatedly call BZ2_bzCompress with action = BZ_FINISH, +copying out the compressed output, until BZ_STREAM_END is returned. +
  • Close up and go home. Call BZ2_bzCompressEnd. + +
+ +

+If the data you want to compress fits into your input buffer all +at once, you can skip the calls of BZ2_bzCompress ( ..., BZ_RUN ) and +just do the BZ2_bzCompress ( ..., BZ_FINISH ) calls. + +

+

+All required memory is allocated by BZ2_bzCompressInit. The +compression library can accept any data at all (obviously). So you +shouldn't get any error return values from the BZ2_bzCompress calls. +If you do, they will be BZ_SEQUENCE_ERROR, and indicate a bug in +your programming. + +

+

+Trivial other possible return values: + +

+      BZ_PARAM_ERROR   
+         if strm is NULL, or strm->s is NULL
+
+ + + +

BZ2_bzCompressEnd

+ +
+int BZ2_bzCompressEnd ( bz_stream *strm );
+
+ +

+Releases all memory associated with a compression stream. + +

+

+Possible return values: + +

+   BZ_PARAM_ERROR    if strm is NULL or strm->s is NULL
+   BZ_OK    otherwise
+
+ + + +

BZ2_bzDecompressInit

+ +
+int BZ2_bzDecompressInit ( bz_stream *strm, int verbosity, int small );
+
+ +

+Prepares for decompression. As with BZ2_bzCompressInit, a +bz_stream record should be allocated and initialised before the +call. Fields bzalloc, bzfree and opaque should be +set if a custom memory allocator is required, or made NULL for +the normal malloc/free routines. Upon return, the internal +state will have been initialised, and total_in and +total_out will be zero. + +

+

+For the meaning of parameter verbosity, see BZ2_bzCompressInit. + +

+

+If small is nonzero, the library will use an alternative +decompression algorithm which uses less memory but at the cost of +decompressing more slowly (roughly speaking, half the speed, but the +maximum memory requirement drops to around 2300k). See Chapter 2 for +more information on memory management. + +

+

+Note that the amount of memory needed to decompress +a stream cannot be determined until the stream's header has been read, +so even if BZ2_bzDecompressInit succeeds, a subsequent +BZ2_bzDecompress could fail with BZ_MEM_ERROR. + +

+

+Possible return values: + +

+      BZ_CONFIG_ERROR
+         if the library has been mis-compiled
+      BZ_PARAM_ERROR
+         if (small != 0 && small != 1)
+         or (verbosity < 0 || verbosity > 4)
+      BZ_MEM_ERROR
+         if insufficient memory is available
+
+ +

+Allowable next actions: + +

+      BZ2_bzDecompress
+         if BZ_OK was returned
+      no specific action required in case of error
+
+ +

+ + +

+ + +

BZ2_bzDecompress

+ +
+int BZ2_bzDecompress ( bz_stream *strm );
+
+ +

+Provides more input and/out output buffer space for the library. The +caller maintains input and output buffers, and uses BZ2_bzDecompress +to transfer data between them. + +

+

+Before each call to BZ2_bzDecompress, next_in +should point at the compressed data, +and avail_in should indicate how many bytes the library +may read. BZ2_bzDecompress updates next_in, avail_in +and total_in +to reflect the number of bytes it has read. + +

+

+Similarly, next_out should point to a buffer in which the uncompressed +output is to be placed, with avail_out indicating how much output space +is available. BZ2_bzCompress updates next_out, +avail_out and total_out to reflect +the number of bytes output. + +

+

+You may provide and remove as little or as much data as you like on +each call of BZ2_bzDecompress. +In the limit, it is acceptable to +supply and remove data one byte at a time, although this would be +terribly inefficient. You should always ensure that at least one +byte of output space is available at each call. + +

+

+Use of BZ2_bzDecompress is simpler than BZ2_bzCompress. + +

+

+You should provide input and remove output as described above, and +repeatedly call BZ2_bzDecompress until BZ_STREAM_END is +returned. Appearance of BZ_STREAM_END denotes that +BZ2_bzDecompress has detected the logical end of the compressed +stream. BZ2_bzDecompress will not produce BZ_STREAM_END until +all output data has been placed into the output buffer, so once +BZ_STREAM_END appears, you are guaranteed to have available all +the decompressed output, and BZ2_bzDecompressEnd can safely be +called. + +

+

+If case of an error return value, you should call BZ2_bzDecompressEnd +to clean up and release memory. + +

+

+Possible return values: + +

+      BZ_PARAM_ERROR
+         if strm is NULL or strm->s is NULL
+         or strm->avail_out < 1
+      BZ_DATA_ERROR
+         if a data integrity error is detected in the compressed stream
+      BZ_DATA_ERROR_MAGIC
+         if the compressed stream doesn't begin with the right magic bytes
+      BZ_MEM_ERROR
+         if there wasn't enough memory available
+      BZ_STREAM_END
+         if the logical end of the data stream was detected and all
+         output in has been consumed, eg s->avail_out > 0
+      BZ_OK
+         otherwise
+
+ +

+Allowable next actions: + +

+      BZ2_bzDecompress
+         if BZ_OK was returned
+      BZ2_bzDecompressEnd
+         otherwise
+
+ + + +

BZ2_bzDecompressEnd

+ +
+int BZ2_bzDecompressEnd ( bz_stream *strm );
+
+ +

+Releases all memory associated with a decompression stream. + +

+

+Possible return values: + +

+      BZ_PARAM_ERROR
+         if strm is NULL or strm->s is NULL
+      BZ_OK
+         otherwise
+
+ +

+Allowable next actions: + +

+      None.
+
+ + + +

High-level interface

+ +

+This interface provides functions for reading and writing +bzip2 format files. First, some general points. + +

+ +
    +
  • All of the functions take an int* first argument, + + bzerror. + After each call, bzerror should be consulted first to determine + the outcome of the call. If bzerror is BZ_OK, + the call completed + successfully, and only then should the return value of the function + (if any) be consulted. If bzerror is BZ_IO_ERROR, + there was an error + reading/writing the underlying compressed file, and you should + then consult errno/perror to determine the + cause of the difficulty. + bzerror may also be set to various other values; precise details are + given on a per-function basis below. +
  • If bzerror indicates an error + + (ie, anything except BZ_OK and BZ_STREAM_END), + you should immediately call BZ2_bzReadClose (or BZ2_bzWriteClose, + depending on whether you are attempting to read or to write) + to free up all resources associated + with the stream. Once an error has been indicated, behaviour of all calls + except BZ2_bzReadClose (BZ2_bzWriteClose) is undefined. + The implication is that (1) bzerror should + be checked after each call, and (2) if bzerror indicates an error, + BZ2_bzReadClose (BZ2_bzWriteClose) should then be called to clean up. +
  • The FILE* arguments passed to + + BZ2_bzReadOpen/BZ2_bzWriteOpen + should be set to binary mode. + Most Unix systems will do this by default, but other platforms, + including Windows and Mac, will not. If you omit this, you may + encounter problems when moving code to new platforms. +
  • Memory allocation requests are handled by + + malloc/free. + At present + there is no facility for user-defined memory allocators in the file I/O + functions (could easily be added, though). +
+ + + +

BZ2_bzReadOpen

+ +
+   typedef void BZFILE;
+
+   BZFILE *BZ2_bzReadOpen ( int *bzerror, FILE *f, 
+                            int small, int verbosity,
+                            void *unused, int nUnused );
+
+ +

+Prepare to read compressed data from file handle f. f +should refer to a file which has been opened for reading, and for which +the error indicator (ferror(f))is not set. If small is 1, +the library will try to decompress using less memory, at the expense of +speed. + +

+

+For reasons explained below, BZ2_bzRead will decompress the +nUnused bytes starting at unused, before starting to read +from the file f. At most BZ_MAX_UNUSED bytes may be +supplied like this. If this facility is not required, you should pass +NULL and 0 for unused and nUnused +respectively. + +

+

+For the meaning of parameters small and verbosity, +see BZ2_bzDecompressInit. + +

+

+The amount of memory needed to decompress a file cannot be determined +until the file's header has been read. So it is possible that +BZ2_bzReadOpen returns BZ_OK but a subsequent call of +BZ2_bzRead will return BZ_MEM_ERROR. + +

+

+Possible assignments to bzerror: + +

+      BZ_CONFIG_ERROR
+         if the library has been mis-compiled
+      BZ_PARAM_ERROR
+         if f is NULL 
+         or small is neither 0 nor 1                 
+         or (unused == NULL && nUnused != 0)
+         or (unused != NULL && !(0 <= nUnused <= BZ_MAX_UNUSED))
+      BZ_IO_ERROR    
+         if ferror(f) is nonzero
+      BZ_MEM_ERROR   
+         if insufficient memory is available
+      BZ_OK
+         otherwise.
+
+ +

+Possible return values: + +

+      Pointer to an abstract BZFILE        
+         if bzerror is BZ_OK   
+      NULL
+         otherwise
+
+ +

+Allowable next actions: + +

+      BZ2_bzRead
+         if bzerror is BZ_OK   
+      BZ2_bzClose 
+         otherwise
+
+ + + +

BZ2_bzRead

+ +
+   int BZ2_bzRead ( int *bzerror, BZFILE *b, void *buf, int len );
+
+ +

+Reads up to len (uncompressed) bytes from the compressed file +b into +the buffer buf. If the read was successful, +bzerror is set to BZ_OK +and the number of bytes read is returned. If the logical end-of-stream +was detected, bzerror will be set to BZ_STREAM_END, +and the number +of bytes read is returned. All other bzerror values denote an error. + +

+

+BZ2_bzRead will supply len bytes, +unless the logical stream end is detected +or an error occurs. Because of this, it is possible to detect the +stream end by observing when the number of bytes returned is +less than the number +requested. Nevertheless, this is regarded as inadvisable; you should +instead check bzerror after every call and watch out for +BZ_STREAM_END. + +

+

+Internally, BZ2_bzRead copies data from the compressed file in chunks +of size BZ_MAX_UNUSED bytes +before decompressing it. If the file contains more bytes than strictly +needed to reach the logical end-of-stream, BZ2_bzRead will almost certainly +read some of the trailing data before signalling BZ_SEQUENCE_END. +To collect the read but unused data once BZ_SEQUENCE_END has +appeared, call BZ2_bzReadGetUnused immediately before BZ2_bzReadClose. + +

+

+Possible assignments to bzerror: + +

+      BZ_PARAM_ERROR
+         if b is NULL or buf is NULL or len < 0
+      BZ_SEQUENCE_ERROR 
+         if b was opened with BZ2_bzWriteOpen
+      BZ_IO_ERROR 
+         if there is an error reading from the compressed file
+      BZ_UNEXPECTED_EOF 
+         if the compressed file ended before the logical end-of-stream was detected
+      BZ_DATA_ERROR 
+         if a data integrity error was detected in the compressed stream
+      BZ_DATA_ERROR_MAGIC
+         if the stream does not begin with the requisite header bytes (ie, is not 
+         a bzip2 data file).  This is really a special case of BZ_DATA_ERROR.
+      BZ_MEM_ERROR 
+         if insufficient memory was available
+      BZ_STREAM_END 
+         if the logical end of stream was detected.
+      BZ_OK
+         otherwise.
+
+ +

+Possible return values: + +

+      number of bytes read
+         if bzerror is BZ_OK or BZ_STREAM_END
+      undefined
+         otherwise
+
+ +

+Allowable next actions: + +

+      collect data from buf, then BZ2_bzRead or BZ2_bzReadClose
+         if bzerror is BZ_OK 
+      collect data from buf, then BZ2_bzReadClose or BZ2_bzReadGetUnused 
+         if bzerror is BZ_SEQUENCE_END   
+      BZ2_bzReadClose 
+         otherwise
+
+ + + +

BZ2_bzReadGetUnused

+ +
+   void BZ2_bzReadGetUnused ( int* bzerror, BZFILE *b, 
+                              void** unused, int* nUnused );
+
+ +

+Returns data which was read from the compressed file but was not needed +to get to the logical end-of-stream. *unused is set to the address +of the data, and *nUnused to the number of bytes. *nUnused will +be set to a value between 0 and BZ_MAX_UNUSED inclusive. + +

+

+This function may only be called once BZ2_bzRead has signalled +BZ_STREAM_END but before BZ2_bzReadClose. + +

+

+Possible assignments to bzerror: + +

+      BZ_PARAM_ERROR 
+         if b is NULL 
+         or unused is NULL or nUnused is NULL
+      BZ_SEQUENCE_ERROR 
+         if BZ_STREAM_END has not been signalled
+         or if b was opened with BZ2_bzWriteOpen
+     BZ_OK
+         otherwise
+
+ +

+Allowable next actions: + +

+      BZ2_bzReadClose
+
+ + + +

BZ2_bzReadClose

+ +
+   void BZ2_bzReadClose ( int *bzerror, BZFILE *b );
+
+ +

+Releases all memory pertaining to the compressed file b. +BZ2_bzReadClose does not call fclose on the underlying file +handle, so you should do that yourself if appropriate. +BZ2_bzReadClose should be called to clean up after all error +situations. + +

+

+Possible assignments to bzerror: + +

+      BZ_SEQUENCE_ERROR 
+         if b was opened with BZ2_bzOpenWrite 
+      BZ_OK 
+         otherwise
+
+ +

+Allowable next actions: + +

+      none
+
+ + + +

BZ2_bzWriteOpen

+ +
+   BZFILE *BZ2_bzWriteOpen ( int *bzerror, FILE *f, 
+                             int blockSize100k, int verbosity,
+                             int workFactor );
+
+ +

+Prepare to write compressed data to file handle f. +f should refer to +a file which has been opened for writing, and for which the error +indicator (ferror(f))is not set. + +

+

+For the meaning of parameters blockSize100k, +verbosity and workFactor, see +
BZ2_bzCompressInit. + +

+

+All required memory is allocated at this stage, so if the call +completes successfully, BZ_MEM_ERROR cannot be signalled by a +subsequent call to BZ2_bzWrite. + +

+

+Possible assignments to bzerror: + +

+      BZ_CONFIG_ERROR
+         if the library has been mis-compiled
+      BZ_PARAM_ERROR 
+         if f is NULL 
+         or blockSize100k < 1 or blockSize100k > 9
+      BZ_IO_ERROR 
+         if ferror(f) is nonzero
+      BZ_MEM_ERROR 
+         if insufficient memory is available
+      BZ_OK 
+         otherwise
+
+ +

+Possible return values: + +

+      Pointer to an abstract BZFILE  
+         if bzerror is BZ_OK   
+      NULL 
+         otherwise
+
+ +

+Allowable next actions: + +

+      BZ2_bzWrite 
+         if bzerror is BZ_OK 
+         (you could go directly to BZ2_bzWriteClose, but this would be pretty pointless)
+      BZ2_bzWriteClose 
+         otherwise
+
+ + + +

BZ2_bzWrite

+ +
+   void BZ2_bzWrite ( int *bzerror, BZFILE *b, void *buf, int len );
+
+ +

+Absorbs len bytes from the buffer buf, eventually to be +compressed and written to the file. + +

+

+Possible assignments to bzerror: + +

+      BZ_PARAM_ERROR 
+         if b is NULL or buf is NULL or len < 0
+      BZ_SEQUENCE_ERROR 
+         if b was opened with BZ2_bzReadOpen
+      BZ_IO_ERROR 
+         if there is an error writing the compressed file.
+      BZ_OK 
+         otherwise
+
+ + + +

BZ2_bzWriteClose

+ +
+   void BZ2_bzWriteClose ( int *bzerror, BZFILE* f,
+                           int abandon,
+                           unsigned int* nbytes_in,
+                           unsigned int* nbytes_out );
+
+   void BZ2_bzWriteClose64 ( int *bzerror, BZFILE* f,
+                             int abandon,
+                             unsigned int* nbytes_in_lo32,
+                             unsigned int* nbytes_in_hi32,
+                             unsigned int* nbytes_out_lo32,
+                             unsigned int* nbytes_out_hi32 );
+
+ +

+Compresses and flushes to the compressed file all data so far supplied +by BZ2_bzWrite. The logical end-of-stream markers are also written, so +subsequent calls to BZ2_bzWrite are illegal. All memory associated +with the compressed file b is released. +fflush is called on the +compressed file, but it is not fclose'd. + +

+

+If BZ2_bzWriteClose is called to clean up after an error, the only +action is to release the memory. The library records the error codes +issued by previous calls, so this situation will be detected +automatically. There is no attempt to complete the compression +operation, nor to fflush the compressed file. You can force this +behaviour to happen even in the case of no error, by passing a nonzero +value to abandon. + +

+

+If nbytes_in is non-null, *nbytes_in will be set to be the +total volume of uncompressed data handled. Similarly, nbytes_out +will be set to the total volume of compressed data written. For +compatibility with older versions of the library, BZ2_bzWriteClose +only yields the lower 32 bits of these counts. Use +BZ2_bzWriteClose64 if you want the full 64 bit counts. These +two functions are otherwise absolutely identical. + +

+ +

+Possible assignments to bzerror: + +

+      BZ_SEQUENCE_ERROR 
+         if b was opened with BZ2_bzReadOpen
+      BZ_IO_ERROR 
+         if there is an error writing the compressed file
+      BZ_OK 
+         otherwise
+
+ + + +

Handling embedded compressed data streams

+ +

+The high-level library facilitates use of +bzip2 data streams which form some part of a surrounding, larger +data stream. + +

    +
  • For writing, the library takes an open file handle, writes + +compressed data to it, fflushes it but does not fclose it. +The calling application can write its own data before and after the +compressed data stream, using that same file handle. +
  • Reading is more complex, and the facilities are not as general + +as they could be since generality is hard to reconcile with efficiency. +BZ2_bzRead reads from the compressed file in blocks of size +BZ_MAX_UNUSED bytes, and in doing so probably will overshoot +the logical end of compressed stream. +To recover this data once decompression has +ended, call BZ2_bzReadGetUnused after the last call of BZ2_bzRead +(the one returning BZ_STREAM_END) but before calling +BZ2_bzReadClose. +
+ +

+This mechanism makes it easy to decompress multiple bzip2 +streams placed end-to-end. As the end of one stream, when BZ2_bzRead +returns BZ_STREAM_END, call BZ2_bzReadGetUnused to collect the +unused data (copy it into your own buffer somewhere). +That data forms the start of the next compressed stream. +To start uncompressing that next stream, call BZ2_bzReadOpen again, +feeding in the unused data via the unused/nUnused +parameters. +Keep doing this until BZ_STREAM_END return coincides with the +physical end of file (feof(f)). In this situation +BZ2_bzReadGetUnused +will of course return no data. + +

+

+This should give some feel for how the high-level interface can be used. +If you require extra flexibility, you'll have to bite the bullet and get +to grips with the low-level interface. + +

+ + +

Standard file-reading/writing code

+

+Here's how you'd write data to a compressed file: + +

+FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "w" );
+if (!f) {
+   /* handle error */
+}
+b = BZ2_bzWriteOpen ( &bzerror, f, 9 );
+if (bzerror != BZ_OK) {
+   BZ2_bzWriteClose ( b );
+   /* handle error */
+}
+
+while ( /* condition */ ) {
+   /* get data to write into buf, and set nBuf appropriately */
+   nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf );
+   if (bzerror == BZ_IO_ERROR) { 
+      BZ2_bzWriteClose ( &bzerror, b );
+      /* handle error */
+   }
+}
+
+BZ2_bzWriteClose ( &bzerror, b );
+if (bzerror == BZ_IO_ERROR) {
+   /* handle error */
+}
+
+ +

+And to read from a compressed file: + +

+FILE*   f;
+BZFILE* b;
+int     nBuf;
+char    buf[ /* whatever size you like */ ];
+int     bzerror;
+int     nWritten;
+
+f = fopen ( "myfile.bz2", "r" );
+if (!f) {
+   /* handle error */
+}
+b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 );
+if (bzerror != BZ_OK) {
+   BZ2_bzReadClose ( &bzerror, b );
+   /* handle error */
+}
+
+bzerror = BZ_OK;
+while (bzerror == BZ_OK && /* arbitrary other conditions */) {
+   nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ );
+   if (bzerror == BZ_OK) {
+      /* do something with buf[0 .. nBuf-1] */
+   }
+}
+if (bzerror != BZ_STREAM_END) {
+   BZ2_bzReadClose ( &bzerror, b );
+   /* handle error */
+} else {
+   BZ2_bzReadClose ( &bzerror );
+}
+
+ + + +

Utility functions

+ + +

BZ2_bzBuffToBuffCompress

+ +
+   int BZ2_bzBuffToBuffCompress( char*         dest,
+                                 unsigned int* destLen,
+                                 char*         source,
+                                 unsigned int  sourceLen,
+                                 int           blockSize100k,
+                                 int           verbosity,
+                                 int           workFactor );
+
+ +

+Attempts to compress the data in source[0 .. sourceLen-1] +into the destination buffer, dest[0 .. *destLen-1]. +If the destination buffer is big enough, *destLen is +set to the size of the compressed data, and BZ_OK is +returned. If the compressed data won't fit, *destLen +is unchanged, and BZ_OUTBUFF_FULL is returned. + +

+

+Compression in this manner is a one-shot event, done with a single call +to this function. The resulting compressed data is a complete +bzip2 format data stream. There is no mechanism for making +additional calls to provide extra input data. If you want that kind of +mechanism, use the low-level interface. + +

+

+For the meaning of parameters blockSize100k, verbosity +and workFactor,
see BZ2_bzCompressInit. + +

+

+To guarantee that the compressed data will fit in its buffer, allocate +an output buffer of size 1% larger than the uncompressed data, plus +six hundred extra bytes. + +

+

+BZ2_bzBuffToBuffDecompress will not write data at or +beyond dest[*destLen], even in case of buffer overflow. + +

+

+Possible return values: + +

+      BZ_CONFIG_ERROR
+         if the library has been mis-compiled
+      BZ_PARAM_ERROR 
+         if dest is NULL or destLen is NULL
+         or blockSize100k < 1 or blockSize100k > 9
+         or verbosity < 0 or verbosity > 4 
+         or workFactor < 0 or workFactor > 250
+      BZ_MEM_ERROR
+         if insufficient memory is available 
+      BZ_OUTBUFF_FULL
+         if the size of the compressed data exceeds *destLen
+      BZ_OK 
+         otherwise
+
+ + + +

BZ2_bzBuffToBuffDecompress

+ +
+   int BZ2_bzBuffToBuffDecompress ( char*         dest,
+                                    unsigned int* destLen,
+                                    char*         source,
+                                    unsigned int  sourceLen,
+                                    int           small,
+                                    int           verbosity );
+
+ +

+Attempts to decompress the data in source[0 .. sourceLen-1] +into the destination buffer, dest[0 .. *destLen-1]. +If the destination buffer is big enough, *destLen is +set to the size of the uncompressed data, and BZ_OK is +returned. If the compressed data won't fit, *destLen +is unchanged, and BZ_OUTBUFF_FULL is returned. + +

+

+source is assumed to hold a complete bzip2 format +data stream.
BZ2_bzBuffToBuffDecompress tries to decompress +the entirety of the stream into the output buffer. + +

+

+For the meaning of parameters small and verbosity, +see BZ2_bzDecompressInit. + +

+

+Because the compression ratio of the compressed data cannot be known in +advance, there is no easy way to guarantee that the output buffer will +be big enough. You may of course make arrangements in your code to +record the size of the uncompressed data, but such a mechanism is beyond +the scope of this library. + +

+

+BZ2_bzBuffToBuffDecompress will not write data at or +beyond dest[*destLen], even in case of buffer overflow. + +

+

+Possible return values: + +

+      BZ_CONFIG_ERROR
+         if the library has been mis-compiled
+      BZ_PARAM_ERROR 
+         if dest is NULL or destLen is NULL
+         or small != 0 && small != 1
+         or verbosity < 0 or verbosity > 4 
+      BZ_MEM_ERROR
+         if insufficient memory is available 
+      BZ_OUTBUFF_FULL
+         if the size of the compressed data exceeds *destLen
+      BZ_DATA_ERROR
+         if a data integrity error was detected in the compressed data
+      BZ_DATA_ERROR_MAGIC
+         if the compressed data doesn't begin with the right magic bytes
+      BZ_UNEXPECTED_EOF
+         if the compressed data ends unexpectedly
+      BZ_OK 
+         otherwise
+
+ + + +

zlib compatibility functions

+

+Yoshioka Tsuneo has contributed some functions to +give better zlib compatibility. These functions are +BZ2_bzopen, BZ2_bzread, BZ2_bzwrite, BZ2_bzflush, +BZ2_bzclose, +BZ2_bzerror and BZ2_bzlibVersion. +These functions are not (yet) officially part of +the library. If they break, you get to keep all the pieces. +Nevertheless, I think they work ok. + +

+typedef void BZFILE;
+
+const char * BZ2_bzlibVersion ( void );
+
+ +

+Returns a string indicating the library version. + +

+BZFILE * BZ2_bzopen  ( const char *path, const char *mode );
+BZFILE * BZ2_bzdopen ( int        fd,    const char *mode );
+
+ +

+Opens a .bz2 file for reading or writing, using either its name +or a pre-existing file descriptor. +Analogous to fopen and fdopen. + +

+int BZ2_bzread  ( BZFILE* b, void* buf, int len );
+int BZ2_bzwrite ( BZFILE* b, void* buf, int len );
+
+ +

+Reads/writes data from/to a previously opened BZFILE. +Analogous to fread and fwrite. + +

+int  BZ2_bzflush ( BZFILE* b );
+void BZ2_bzclose ( BZFILE* b );
+
+ +

+Flushes/closes a BZFILE. BZ2_bzflush doesn't actually do +anything. Analogous to fflush and fclose. + +

+ +
+const char * BZ2_bzerror ( BZFILE *b, int *errnum )
+
+ +

+Returns a string describing the more recent error status of +b, and also sets *errnum to its numerical value. + +

+ + + +

Using the library in a stdio-free environment

+ + + +

Getting rid of stdio

+ +

+In a deeply embedded application, you might want to use just +the memory-to-memory functions. You can do this conveniently +by compiling the library with preprocessor symbol BZ_NO_STDIO +defined. Doing this gives you a library containing only the following +eight functions: + +

+

+BZ2_bzCompressInit, BZ2_bzCompress, BZ2_bzCompressEnd
+BZ2_bzDecompressInit, BZ2_bzDecompress, BZ2_bzDecompressEnd
+BZ2_bzBuffToBuffCompress, BZ2_bzBuffToBuffDecompress + +

+

+When compiled like this, all functions will ignore verbosity +settings. + +

+ + +

Critical error handling

+

+libbzip2 contains a number of internal assertion checks which +should, needless to say, never be activated. Nevertheless, if an +assertion should fail, behaviour depends on whether or not the library +was compiled with BZ_NO_STDIO set. + +

+

+For a normal compile, an assertion failure yields the message + +

+   bzip2/libbzip2: internal error number N.
+   This is a bug in bzip2/libbzip2, 1.0 of 21-Mar-2000.
+   Please report it to me at: jseward@acm.org.  If this happened
+   when you were using some program which uses libbzip2 as a
+   component, you should also report this bug to the author(s)
+   of that program.  Please make an effort to report this bug;
+   timely and accurate bug reports eventually lead to higher
+   quality software.  Thanks.  Julian Seward, 21 March 2000.
+
+ +

+where N is some error code number. exit(3) +is then called. + +

+

+For a stdio-free library, assertion failures result +in a call to a function declared as: + +

+   extern void bz_internal_error ( int errcode );
+
+ +

+The relevant code is passed as a parameter. You should supply +such a function. + +

+

+In either case, once an assertion failure has occurred, any +bz_stream records involved can be regarded as invalid. +You should not attempt to resume normal operation with them. + +

+

+You may, of course, change critical error handling to suit +your needs. As I said above, critical errors indicate bugs +in the library and should not occur. All "normal" error +situations are indicated via error return codes from functions, +and can be recovered from. + +

+ + + +

Making a Windows DLL

+

+Everything related to Windows has been contributed by Yoshioka Tsuneo +
(QWF00133@niftyserve.or.jp / +tsuneo-y@is.aist-nara.ac.jp), so you should send your queries to +him (but perhaps Cc: me, jseward@acm.org). + +

+

+My vague understanding of what to do is: using Visual C++ 5.0, +open the project file libbz2.dsp, and build. That's all. + +

+

+If you can't +open the project file for some reason, make a new one, naming these files: +blocksort.c, bzlib.c, compress.c, +crctable.c, decompress.c, huffman.c,
+randtable.c and libbz2.def. You will also need +to name the header files bzlib.h and bzlib_private.h. + +

+

+If you don't use VC++, you may need to define the proprocessor symbol +_WIN32. + +

+

+Finally, dlltest.c is a sample program using the DLL. It has a +project file, dlltest.dsp. + +

+

+If you just want a makefile for Visual C, have a look at +makefile.msc. + +

+

+Be aware that if you compile bzip2 itself on Win32, you must set +BZ_UNIX to 0 and BZ_LCCWIN32 to 1, in the file +bzip2.c, before compiling. Otherwise the resulting binary won't +work correctly. + +

+

+I haven't tried any of this stuff myself, but it all looks plausible. + +

+ +


+

Go to the first, previous, next, last section, table of contents. + + diff --git a/drivers/lib/bzip2/manual_4.html b/drivers/lib/bzip2/manual_4.html new file mode 100644 index 0000000..9ab7fb2 --- /dev/null +++ b/drivers/lib/bzip2/manual_4.html @@ -0,0 +1,528 @@ + + + + +bzip2 and libbzip2 - Miscellanea + + + + + +

Go to the first, previous, next, last section, table of contents. +


+ + +

Miscellanea

+ +

+These are just some random thoughts of mine. Your mileage may +vary. + +

+ + +

Limitations of the compressed file format

+

+bzip2-1.0, 0.9.5 and 0.9.0 +use exactly the same file format as the previous +version, bzip2-0.1. This decision was made in the interests of +stability. Creating yet another incompatible compressed file format +would create further confusion and disruption for users. + +

+

+Nevertheless, this is not a painless decision. Development +work since the release of bzip2-0.1 in August 1997 +has shown complexities in the file format which slow down +decompression and, in retrospect, are unnecessary. These are: + +

    +
  • The run-length encoder, which is the first of the + + compression transformations, is entirely irrelevant. + The original purpose was to protect the sorting algorithm + from the very worst case input: a string of repeated + symbols. But algorithm steps Q6a and Q6b in the original + Burrows-Wheeler technical report (SRC-124) show how + repeats can be handled without difficulty in block + sorting. +
  • The randomisation mechanism doesn't really need to be + + there. Udi Manber and Gene Myers published a suffix + array construction algorithm a few years back, which + can be employed to sort any block, no matter how + repetitive, in O(N log N) time. Subsequent work by + Kunihiko Sadakane has produced a derivative O(N (log N)^2) + algorithm which usually outperforms the Manber-Myers + algorithm. + + I could have changed to Sadakane's algorithm, but I find + it to be slower than bzip2's existing algorithm for + most inputs, and the randomisation mechanism protects + adequately against bad cases. I didn't think it was + a good tradeoff to make. Partly this is due to the fact + that I was not flooded with email complaints about + bzip2-0.1's performance on repetitive data, so + perhaps it isn't a problem for real inputs. + + Probably the best long-term solution, + and the one I have incorporated into 0.9.5 and above, + is to use the existing sorting + algorithm initially, and fall back to a O(N (log N)^2) + algorithm if the standard algorithm gets into difficulties. +
  • The compressed file format was never designed to be + + handled by a library, and I have had to jump though + some hoops to produce an efficient implementation of + decompression. It's a bit hairy. Try passing + decompress.c through the C preprocessor + and you'll see what I mean. Much of this complexity + could have been avoided if the compressed size of + each block of data was recorded in the data stream. +
  • An Adler-32 checksum, rather than a CRC32 checksum, + + would be faster to compute. +
+ +

+It would be fair to say that the bzip2 format was frozen +before I properly and fully understood the performance +consequences of doing so. + +

+

+Improvements which I was able to incorporate into +0.9.0, despite using the same file format, are: + +

    +
  • Single array implementation of the inverse BWT. This + + significantly speeds up decompression, presumably + because it reduces the number of cache misses. +
  • Faster inverse MTF transform for large MTF values. The + + new implementation is based on the notion of sliding blocks + of values. +
  • bzip2-0.9.0 now reads and writes files with fread + + and fwrite; version 0.1 used putc and getc. + Duh! Well, you live and learn. + +
+ +

+Further ahead, it would be nice +to be able to do random access into files. This will +require some careful design of compressed file formats. + +

+ + + +

Portability issues

+

+After some consideration, I have decided not to use +GNU autoconf to configure 0.9.5 or 1.0. + +

+

+autoconf, admirable and wonderful though it is, +mainly assists with portability problems between Unix-like +platforms. But bzip2 doesn't have much in the way +of portability problems on Unix; most of the difficulties appear +when porting to the Mac, or to Microsoft's operating systems. +autoconf doesn't help in those cases, and brings in a +whole load of new complexity. + +

+

+Most people should be able to compile the library and program +under Unix straight out-of-the-box, so to speak, especially +if you have a version of GNU C available. + +

+

+There are a couple of __inline__ directives in the code. GNU C +(gcc) should be able to handle them. If you're not using +GNU C, your C compiler shouldn't see them at all. +If your compiler does, for some reason, see them and doesn't +like them, just #define __inline__ to be /* */. One +easy way to do this is to compile with the flag -D__inline__=, +which should be understood by most Unix compilers. + +

+

+If you still have difficulties, try compiling with the macro +BZ_STRICT_ANSI defined. This should enable you to build the +library in a strictly ANSI compliant environment. Building the program +itself like this is dangerous and not supported, since you remove +bzip2's checks against compressing directories, symbolic links, +devices, and other not-really-a-file entities. This could cause +filesystem corruption! + +

+

+One other thing: if you create a bzip2 binary for public +distribution, please try and link it statically (gcc -s). This +avoids all sorts of library-version issues that others may encounter +later on. + +

+

+If you build bzip2 on Win32, you must set BZ_UNIX to 0 and +BZ_LCCWIN32 to 1, in the file bzip2.c, before compiling. +Otherwise the resulting binary won't work correctly. + +

+ + + +

Reporting bugs

+

+I tried pretty hard to make sure bzip2 is +bug free, both by design and by testing. Hopefully +you'll never need to read this section for real. + +

+

+Nevertheless, if bzip2 dies with a segmentation +fault, a bus error or an internal assertion failure, it +will ask you to email me a bug report. Experience with +version 0.1 shows that almost all these problems can +be traced to either compiler bugs or hardware problems. + +

    +
  • + +Recompile the program with no optimisation, and see if it +works. And/or try a different compiler. +I heard all sorts of stories about various flavours +of GNU C (and other compilers) generating bad code for +bzip2, and I've run across two such examples myself. + +2.7.X versions of GNU C are known to generate bad code from +time to time, at high optimisation levels. +If you get problems, try using the flags +-O2 -fomit-frame-pointer -fno-strength-reduce. +You should specifically not use -funroll-loops. + +You may notice that the Makefile runs six tests as part of +the build process. If the program passes all of these, it's +a pretty good (but not 100%) indication that the compiler has +done its job correctly. +
  • + +If bzip2 crashes randomly, and the crashes are not +repeatable, you may have a flaky memory subsystem. bzip2 +really hammers your memory hierarchy, and if it's a bit marginal, +you may get these problems. Ditto if your disk or I/O subsystem +is slowly failing. Yup, this really does happen. + +Try using a different machine of the same type, and see if +you can repeat the problem. +
  • This isn't really a bug, but ... If bzip2 tells + +you your file is corrupted on decompression, and you +obtained the file via FTP, there is a possibility that you +forgot to tell FTP to do a binary mode transfer. That absolutely +will cause the file to be non-decompressible. You'll have to transfer +it again. +
+ +

+If you've incorporated libbzip2 into your own program +and are getting problems, please, please, please, check that the +parameters you are passing in calls to the library, are +correct, and in accordance with what the documentation says +is allowable. I have tried to make the library robust against +such problems, but I'm sure I haven't succeeded. + +

+

+Finally, if the above comments don't help, you'll have to send +me a bug report. Now, it's just amazing how many people will +send me a bug report saying something like + +

+   bzip2 crashed with segmentation fault on my machine
+
+ +

+and absolutely nothing else. Needless to say, a such a report +is totally, utterly, completely and comprehensively 100% useless; +a waste of your time, my time, and net bandwidth. +With no details at all, there's no way I can possibly begin +to figure out what the problem is. + +

+

+The rules of the game are: facts, facts, facts. Don't omit +them because "oh, they won't be relevant". At the bare +minimum: + +

+   Machine type.  Operating system version.  
+   Exact version of bzip2 (do bzip2 -V).  
+   Exact version of the compiler used.  
+   Flags passed to the compiler.
+
+ +

+However, the most important single thing that will help me is +the file that you were trying to compress or decompress at the +time the problem happened. Without that, my ability to do anything +more than speculate about the cause, is limited. + +

+

+Please remember that I connect to the Internet with a modem, so +you should contact me before mailing me huge files. + +

+ + + +

Did you get the right package?

+ +

+bzip2 is a resource hog. It soaks up large amounts of CPU cycles +and memory. Also, it gives very large latencies. In the worst case, you +can feed many megabytes of uncompressed data into the library before +getting any compressed output, so this probably rules out applications +requiring interactive behaviour. + +

+

+These aren't faults of my implementation, I hope, but more +an intrinsic property of the Burrows-Wheeler transform (unfortunately). +Maybe this isn't what you want. + +

+

+If you want a compressor and/or library which is faster, uses less +memory but gets pretty good compression, and has minimal latency, +consider Jean-loup +Gailly's and Mark Adler's work, zlib-1.1.2 and +gzip-1.2.4. Look for them at + +

+

+http://www.cdrom.com/pub/infozip/zlib and +http://www.gzip.org respectively. + +

+

+For something faster and lighter still, you might try Markus F X J +Oberhumer's LZO real-time compression/decompression library, at +
http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html. + +

+

+If you want to use the bzip2 algorithms to compress small blocks +of data, 64k bytes or smaller, for example on an on-the-fly disk +compressor, you'd be well advised not to use this library. Instead, +I've made a special library tuned for that kind of use. It's part of +e2compr-0.40, an on-the-fly disk compressor for the Linux +ext2 filesystem. Look at +http://www.netspace.net.au/~reiter/e2compr. + +

+ + + +

Testing

+ +

+A record of the tests I've done. + +

+

+First, some data sets: + +

    +
  • B: a directory containing 6001 files, one for every length in the + + range 0 to 6000 bytes. The files contain random lowercase + letters. 18.7 megabytes. +
  • H: my home directory tree. Documents, source code, mail files, + + compressed data. H contains B, and also a directory of + files designed as boundary cases for the sorting; mostly very + repetitive, nasty files. 565 megabytes. +
  • A: directory tree holding various applications built from source: + + egcs, gcc-2.8.1, KDE, GTK, Octave, etc. + 2200 megabytes. +
+ +

+The tests conducted are as follows. Each test means compressing +(a copy of) each file in the data set, decompressing it and +comparing it against the original. + +

+

+First, a bunch of tests with block sizes and internal buffer +sizes set very small, +to detect any problems with the +blocking and buffering mechanisms. +This required modifying the source code so as to try to +break it. + +

    +
  1. Data set H, with + + buffer size of 1 byte, and block size of 23 bytes. +
  2. Data set B, buffer sizes 1 byte, block size 1 byte. + +
  3. As (2) but small-mode decompression. + +
  4. As (2) with block size 2 bytes. + +
  5. As (2) with block size 3 bytes. + +
  6. As (2) with block size 4 bytes. + +
  7. As (2) with block size 5 bytes. + +
  8. As (2) with block size 6 bytes and small-mode decompression. + +
  9. H with buffer size of 1 byte, but normal block + + size (up to 900000 bytes). +
+ +

+Then some tests with unmodified source code. + +

    +
  1. H, all settings normal. + +
  2. As (1), with small-mode decompress. + +
  3. H, compress with flag -1. + +
  4. H, compress with flag -s, decompress with flag -s. + +
  5. Forwards compatibility: H, bzip2-0.1pl2 compressing, + + bzip2-0.9.5 decompressing, all settings normal. +
  6. Backwards compatibility: H, bzip2-0.9.5 compressing, + + bzip2-0.1pl2 decompressing, all settings normal. +
  7. Bigger tests: A, all settings normal. + +
  8. As (7), using the fallback (Sadakane-like) sorting algorithm. + +
  9. As (8), compress with flag -1, decompress with flag + + -s. +
  10. H, using the fallback sorting algorithm. + +
  11. Forwards compatibility: A, bzip2-0.1pl2 compressing, + + bzip2-0.9.5 decompressing, all settings normal. +
  12. Backwards compatibility: A, bzip2-0.9.5 compressing, + + bzip2-0.1pl2 decompressing, all settings normal. +
  13. Misc test: about 400 megabytes of .tar files with + + bzip2 compiled with Checker (a memory access error + detector, like Purify). +
  14. Misc tests to make sure it builds and runs ok on non-Linux/x86 + + platforms. +
+ +

+These tests were conducted on a 225 MHz IDT WinChip machine, running +Linux 2.0.36. They represent nearly a week of continuous computation. +All tests completed successfully. + +

+ + + +

Further reading

+

+bzip2 is not research work, in the sense that it doesn't present +any new ideas. Rather, it's an engineering exercise based on existing +ideas. + +

+

+Four documents describe essentially all the ideas behind bzip2: + +

+Michael Burrows and D. J. Wheeler:
+  "A block-sorting lossless data compression algorithm"
+   10th May 1994. 
+   Digital SRC Research Report 124.
+   ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.gz
+   If you have trouble finding it, try searching at the
+   New Zealand Digital Library, http://www.nzdl.org.
+
+Daniel S. Hirschberg and Debra A. LeLewer
+  "Efficient Decoding of Prefix Codes"
+   Communications of the ACM, April 1990, Vol 33, Number 4.
+   You might be able to get an electronic copy of this
+      from the ACM Digital Library.
+
+David J. Wheeler
+   Program bred3.c and accompanying document bred3.ps.
+   This contains the idea behind the multi-table Huffman
+   coding scheme.
+   ftp://ftp.cl.cam.ac.uk/users/djw3/
+
+Jon L. Bentley and Robert Sedgewick
+  "Fast Algorithms for Sorting and Searching Strings"
+   Available from Sedgewick's web page,
+   www.cs.princeton.edu/~rs
+
+ +

+The following paper gives valuable additional insights into the +algorithm, but is not immediately the basis of any code +used in bzip2. + +

+Peter Fenwick:
+   Block Sorting Text Compression
+   Proceedings of the 19th Australasian Computer Science Conference,
+     Melbourne, Australia.  Jan 31 - Feb 2, 1996.
+   ftp://ftp.cs.auckland.ac.nz/pub/peter-f/ACSC96paper.ps
+
+ +

+Kunihiko Sadakane's sorting algorithm, mentioned above, +is available from: + +

+http://naomi.is.s.u-tokyo.ac.jp/~sada/papers/Sada98b.ps.gz
+
+ +

+The Manber-Myers suffix array construction +algorithm is described in a paper +available from: + +

+http://www.cs.arizona.edu/people/gene/PAPERS/suffix.ps
+
+ +

+Finally, the following paper documents some recent investigations +I made into the performance of sorting algorithms: + +

+Julian Seward:
+   On the Performance of BWT Sorting Algorithms
+   Proceedings of the IEEE Data Compression Conference 2000
+     Snowbird, Utah.  28-30 March 2000.
+
+ +


+

Go to the first, previous, next, last section, table of contents. + + diff --git a/drivers/lib/bzip2/manual_toc.html b/drivers/lib/bzip2/manual_toc.html new file mode 100644 index 0000000..d4132c4 --- /dev/null +++ b/drivers/lib/bzip2/manual_toc.html @@ -0,0 +1,173 @@ + + + + +bzip2 and libbzip2 - Table of Contents + + + +

bzip2 and libbzip2

+

a program and library for data compression

+

copyright (C) 1996-2000 Julian Seward

+

version 1.0 of 21 March 2000

+
Julian Seward
+

+


+ +

+This program, bzip2, +and associated library libbzip2, are +Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + +

+

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +

    +
  • + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +
  • + + The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. +
  • + + Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. +
  • + + The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. +
+ +

+THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +

+

+Julian Seward, Cambridge, UK. + +

+

+jseward@acm.org + +

+

+http://sourceware.cygnus.com/bzip2 + +

+

+http://www.cacheprof.org + +

+

+http://www.muraroa.demon.co.uk + +

+

+bzip2/libbzip2 version 1.0 of 21 March 2000. + +

+

+PATENTS: To the best of my knowledge, bzip2 does not use any patented +algorithms. However, I do not have the resources available to carry out +a full patent search. Therefore I cannot give any guarantee of the +above statement. + +

+ + +


+This document was generated on 23 March 2000 using the +texi2html +translator version 1.51a.

+ + diff --git a/drivers/lib/bzip2/randtable.c b/drivers/lib/bzip2/randtable.c new file mode 100644 index 0000000..983089d --- /dev/null +++ b/drivers/lib/bzip2/randtable.c @@ -0,0 +1,124 @@ + +/*-------------------------------------------------------------*/ +/*--- Table for randomising repetitive blocks ---*/ +/*--- randtable.c ---*/ +/*-------------------------------------------------------------*/ + +/*-- + This file is a part of bzip2 and/or libbzip2, a program and + library for lossless, block-sorting data compression. + + Copyright (C) 1996-2000 Julian R Seward. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Julian Seward, Cambridge, UK. + jseward@acm.org + bzip2/libbzip2 version 1.0 of 21 March 2000 + + This program is based on (at least) the work of: + Mike Burrows + David Wheeler + Peter Fenwick + Alistair Moffat + Radford Neal + Ian H. Witten + Robert Sedgewick + Jon L. Bentley + + For more information on these sources, see the manual. +--*/ + + +#include "bzlib_private.h" + + +/*---------------------------------------------*/ +Int32 BZ2_rNums[512] = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 +}; + + +/*-------------------------------------------------------------*/ +/*--- end randtable.c ---*/ +/*-------------------------------------------------------------*/ diff --git a/drivers/lib/bzip2/sample1.ref b/drivers/lib/bzip2/sample1.ref new file mode 100644 index 0000000000000000000000000000000000000000..f443cffd39dd00952fc52951b14c66dd5b5f5e3c GIT binary patch literal 308 zcmey)#MnIPfQ&T*5HP=xRtQOrP{=PWDJU&bFtoHZ)iW^HGcdF=G&MBu2C85LDI)~_ z1Hl5O^fNKN3;wP*Ub2A62+VwPXIAgT7{7wg{EQpkcr);&rGYV9a&A(Ep~)_%)XJ%S z@ALB}r_5&cIUP`xUozo%d49>{%7O_N9jP-sa|RTdk=4|i8w7+%%AR|EPDs%IT3NkV$yi87p8aI*Qkz!VAGFZzD$Gi#ipCsl~ z7EiV4$ediOHLW)8%_zLupWh{^!D|w?C$O9?(I9T zcg6Can{mY~y6k_wj^H&_ynXk<@u@d2C={lOcNPlcQ*U+Q-^p8Ud~Lk#9B`%=KJ}Z+ zrwR)ymBKu%*JXPnn|sgMGZac;hdx&-o?WT*`^;@Bq1v-A*>Pg~b!!FFYb5g>u0JC} zT*J?6-E|^XZGT|TJ?nTwict7fx-qPAEhCpJ9aJ>^@~N@*k@xLjZp1fXLG-bhz+QQ&#p-#M`-RGLYy8wq#qz~fH$`1s@-Kl{Y={8LXW?<~y4 zrs<81t7dP{V^*uxnq1PnZJb`)3;XAMa{A0qzx;(}Vea&DbD@c&=h;gmS1`YA-BTIj zjcq?Tl}V@7x@-Q99pec8tV=KEbtXd!;0LFMF|NY?5fQ41Act(heVdo{dS8qs*tQ6h zCS_=l`F2v{3Ky02VDEC>xArnz_30K;LeV^U{sq&k4*d1wn>*1U>@e)@IjDF85nT64 zTXlQP?`C#)G>VvrufNIPyJk238l2+iV{>?}2jL8h)XH zY;nzi8NmT0T@7yU-xp|S0@v0xmnLo?EeURaqHhczBrL%mtN5Ujtt~l2LPKH4)~h!l zIh1XnRF&JM?)}KH5?@5dqPi&uVhtjN2(^oSAkAHS53j|pxXd@4KQXqZ&z@I}01MN6 zGx$LNwYz>)SWSD7fu}vrR3!5}gd%N!)KY|T>C~Z+jnW>KUgI)V4U$HuA-1aJ)UfD9gxtXuELf>vX>KtOfW3!Mq1;U-4^Ac;9Nae;~!P=_X=+tiyP zVJD+mvce#?4%|Jm6PTw}WRTZ1tztb1glPiZsBut^@a;h2L!gc}C@8noBLH@`AmNwt z=en`AXgJ%6)D)y169#B_3N={(k^qvrTa)v5Ej3`jB9d`w>zCiDy+Dz)J0^T;N6ESN zSi7*bbsaz}d_PE1+|z=pI}2sCkO~{luyt5B02w}E{qz*>)!jfh0Ub|l=1zhVH&9e3 z0S=N8X6sS&tHSS4i9GLUTtLX3->3;2E7c}SXM7di8|a2gB9(+e;sgoyX2Rm8OVR~! zW5R(|KM|-v&8UHCZDJUk$JUol|xL1ygm%FrkRH9Y}mC;2NCh-$#ksd`E8s#=Fs^JqhB3u-ht87(V7+ZZej1avx zu>v%YNOnx1|G+OKv0RUU7aRmd8-sQd6=nR5pA(2kUJTqB8vcrl`)8%$Ay=j1{i_9P zmZz%t+szrFBx69b1JL-XE>VLxVu4Nh>Vz0nV(a=>-d2dTiGbb_ja?@(Gi;Z-0Tt*~U-V#qDf@px~m{jb};a)}?x zVB6|SM!T(h%pZ3Tn5CB)upr~t{L>HoW%F4W7t78u?Slt|+!W0hn<6kzjUgSxvUxT^ z36eXpb>p`gN&&J=r2#>v(Hb%fl0fs#^@RI5s_5^TVjRU!xk415QhEDRX$nu1#->D2 z7aPa^cRI!wbs#U0fk#PaAj^w*WqF@ZDQl=y|h7uDTB?vfj9jXd2G6r36bVHC(gxW&{ zk*#ZO+?C-+n|&NjV?K|&mK;J)6Ut2E;Rg?i&znahE=a!(KnnsqT~}u+2av;U=I}FA zT$;Rsx} zS$wQV8t(?kQG=cVQf~MfhFxVAL>u)X<8-uG3{xm^sr+l`3T@eup_ZUjR3d- z?$i9x)F0C15m<=&DR};C#|PH-^|ab2eesQrLB`;kpLP^PqLuMr-mo zxKy+bmvQl-{bRU~3_FA~tv5ljzHQY~E`jOyS8AC`en2O?1v*}6-HE@~GKe+d+y1a3shMgdg@= z(4b+NX&C`C(5ksG;$a!k4Ed6|Od@J*vy7ke3$^yO<7)>{o#n0e=|6mZBTBUvz0!A1 zt9|m<_igNM-ACTT+;bKA1o-RwUYN0V<%#0nYp|cxUYAL{-!=#skRHRgT;_407vs`x z2WC7GaP`WQ02s_>)o@BC`ze!mb_exDmSFEYJ2G&^1Zs`F{!SL3njW^{zxnz+CgI1W z;`(F!ea70E)GH+F!bqOGsx`5=b%@f2-}-u6$wnBGLuze05172U0u^Ag37Yw4)`SwC z*APrcYO+eh1A$s4gV+I}r7a7MX@-jM&5YQaSi&qSBcCRT*cxAq^k*{S7^h5r27pG} zF+CLddI(#wm-Y6*5kK%Qra#(yuCem@N*PLGYs-cP^(>{9M*p;L zj07V0*k~%@h-u+`d^2<7;(?-z!7ySFe_(Cy`u=wD#aCvg1`GkPsi`Bu{8HhW4ih{& zIRH)&+GYDGG*r(q6xmTYQ@em%2hE(oiZQW3&oy^LGsw+DcS)*D;vk&{($Bw?X(wb} zWW1YFW~3tU+MpRPMm0xEJ^#{RKn{!gqZ1S!2vL9YI{`{)0}^J|RM>)qzfX&gSWpj? z$k=G~3T;3|Bl&ECE`DzFFfm?`heyDVtzAFIQ3ZCe_b*3H≫McDC%UL(|oG3pEaS(osk*`UuR!X=Qe#gwSTrFjC8$ zmNWItCHuncU`uu;F-`r1qoCuuK8B+pDg`E&{(TS@ss;lqhapJ<6n2Imx{n_p$eGh0$RViAujZ?pr01ElV{73Z zok7~;n4}UgDLe(77#_X&`1P+wfF5o&K6Qfx&ShR|%RAg{b4i(8tP!I|t2~9L+r>jdUcDQZn^WT%7p$AQ($u z8o=GB#-ew5Pfw5W5i_TA8SU#YrDO_~GeeeH$TmpF{4jhmifxjg*$j#6QA|7tu)$v# z1|lEyjMFf1a}&DLNN1e%pvkP3!USns^Yz^CQrU;!3!vmyNlyNI-v%pz>&V@J1<(Z%aWv}~1qPp|E*+0C=?HKw2@|fqH0j zl(~GdJb{Se^vC+!mRHD!@7VHAHjP6A7-=sJVRSnv+!bcBoQcr>kM$7U&8L%t$j(XW z 2GB) in a reasonable amount of time. + I suggest you use the undocumented --exponential option to + bzip2 when compressing the resulting file; this saves a bit of + time. Note: *don't* bother with --exponential when compressing + Real Files; it'll just waste a lot of CPU time :-) + (but is otherwise harmless). +*/ + +#define _FILE_OFFSET_BITS 64 + +#include +#include + +/* The number of megabytes of junk to spew out (roughly) */ +#define MEGABYTES 5000 + +#define N_BUF 1000000 +char buf[N_BUF]; + +int main ( int argc, char** argv ) +{ + int ii, kk, p; + srandom(1); + setbuffer ( stdout, buf, N_BUF ); + for (kk = 0; kk < MEGABYTES * 515; kk+=3) { + p = 25+random()%50; + for (ii = 0; ii < p; ii++) + printf ( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); + for (ii = 0; ii < p-1; ii++) + printf ( "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); + for (ii = 0; ii < p+1; ii++) + printf ( "ccccccccccccccccccccccccccccccccccccc" ); + } + fflush(stdout); + return 0; +} diff --git a/drivers/lib/bzip2/unbzip2.def b/drivers/lib/bzip2/unbzip2.def new file mode 100644 index 0000000..181a120 --- /dev/null +++ b/drivers/lib/bzip2/unbzip2.def @@ -0,0 +1,4 @@ +LIBRARY unbzip2.dll + +EXPORTS +BZ2_bzBuffToBuffDecompress@24 diff --git a/drivers/lib/bzip2/unbzip2.edf b/drivers/lib/bzip2/unbzip2.edf new file mode 100644 index 0000000..2eca816 --- /dev/null +++ b/drivers/lib/bzip2/unbzip2.edf @@ -0,0 +1,5 @@ +LIBRARY unbzip2.dll + +EXPORTS +BZ2_bzBuffToBuffDecompress=BZ2_bzBuffToBuffDecompress@24 + diff --git a/drivers/lib/bzip2/unzcrash.c b/drivers/lib/bzip2/unzcrash.c new file mode 100644 index 0000000..f0f17fc --- /dev/null +++ b/drivers/lib/bzip2/unzcrash.c @@ -0,0 +1,126 @@ + +/* A test program written to test robustness to decompression of + corrupted data. Usage is + unzcrash filename + and the program will read the specified file, compress it (in memory), + and then repeatedly decompress it, each time with a different bit of + the compressed data inverted, so as to test all possible one-bit errors. + This should not cause any invalid memory accesses. If it does, + I want to know about it! + + p.s. As you can see from the above description, the process is + incredibly slow. A file of size eg 5KB will cause it to run for + many hours. +*/ + +#include +#include +#include "bzlib.h" + +#define M_BLOCK 1000000 + +typedef unsigned char uchar; + +#define M_BLOCK_OUT (M_BLOCK + 1000000) +uchar inbuf[M_BLOCK]; +uchar outbuf[M_BLOCK_OUT]; +uchar zbuf[M_BLOCK + 600 + (M_BLOCK / 100)]; + +int nIn, nOut, nZ; + +static char *bzerrorstrings[] = { + "OK" + ,"SEQUENCE_ERROR" + ,"PARAM_ERROR" + ,"MEM_ERROR" + ,"DATA_ERROR" + ,"DATA_ERROR_MAGIC" + ,"IO_ERROR" + ,"UNEXPECTED_EOF" + ,"OUTBUFF_FULL" + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ + ,"???" /* for future */ +}; + +void flip_bit ( int bit ) +{ + int byteno = bit / 8; + int bitno = bit % 8; + uchar mask = 1 << bitno; + //fprintf ( stderr, "(byte %d bit %d mask %d)", + // byteno, bitno, (int)mask ); + zbuf[byteno] ^= mask; +} + +int main ( int argc, char** argv ) +{ + FILE* f; + int r; + int bit; + int i; + + if (argc != 2) { + fprintf ( stderr, "usage: unzcrash filename\n" ); + return 1; + } + + f = fopen ( argv[1], "r" ); + if (!f) { + fprintf ( stderr, "unzcrash: can't open %s\n", argv[1] ); + return 1; + } + + nIn = fread ( inbuf, 1, M_BLOCK, f ); + fprintf ( stderr, "%d bytes read\n", nIn ); + + nZ = M_BLOCK; + r = BZ2_bzBuffToBuffCompress ( + zbuf, &nZ, inbuf, nIn, 9, 0, 30 ); + + assert (r == BZ_OK); + fprintf ( stderr, "%d after compression\n", nZ ); + + for (bit = 0; bit < nZ*8; bit++) { + fprintf ( stderr, "bit %d ", bit ); + flip_bit ( bit ); + nOut = M_BLOCK_OUT; + r = BZ2_bzBuffToBuffDecompress ( + outbuf, &nOut, zbuf, nZ, 0, 0 ); + fprintf ( stderr, " %d %s ", r, bzerrorstrings[-r] ); + + if (r != BZ_OK) { + fprintf ( stderr, "\n" ); + } else { + if (nOut != nIn) { + fprintf(stderr, "nIn/nOut mismatch %d %d\n", nIn, nOut ); + return 1; + } else { + for (i = 0; i < nOut; i++) + if (inbuf[i] != outbuf[i]) { + fprintf(stderr, "mismatch at %d\n", i ); + return 1; + } + if (i == nOut) fprintf(stderr, "really ok!\n" ); + } + } + + flip_bit ( bit ); + } + +#if 0 + assert (nOut == nIn); + for (i = 0; i < nOut; i++) { + if (inbuf[i] != outbuf[i]) { + fprintf ( stderr, "difference at %d !\n", i ); + return 1; + } + } +#endif + + fprintf ( stderr, "all ok\n" ); + return 0; +} diff --git a/drivers/lib/bzip2/words0 b/drivers/lib/bzip2/words0 new file mode 100644 index 0000000..164a8ed --- /dev/null +++ b/drivers/lib/bzip2/words0 @@ -0,0 +1,5 @@ + +If compilation produces errors, or a large number of warnings, +please read README.COMPILATION.PROBLEMS -- you might be able to +adjust the flags in this Makefile to improve matters. + diff --git a/drivers/lib/bzip2/words1 b/drivers/lib/bzip2/words1 new file mode 100644 index 0000000..2e83de9 --- /dev/null +++ b/drivers/lib/bzip2/words1 @@ -0,0 +1,4 @@ + +Doing 6 tests (3 compress, 3 uncompress) ... +If there's a problem, things might stop at this point. + diff --git a/drivers/lib/bzip2/words2 b/drivers/lib/bzip2/words2 new file mode 100644 index 0000000..203ee39 --- /dev/null +++ b/drivers/lib/bzip2/words2 @@ -0,0 +1,5 @@ + +Checking test results. If any of the four "cmp"s which follow +report any differences, something is wrong. If you can't easily +figure out what, please let me know (jseward@acm.org). + diff --git a/drivers/lib/bzip2/words3 b/drivers/lib/bzip2/words3 new file mode 100644 index 0000000..8486a84 --- /dev/null +++ b/drivers/lib/bzip2/words3 @@ -0,0 +1,23 @@ + +If you got this far and the "cmp"s didn't complain, it looks +like you're in business. + +To install in /usr/bin, /usr/lib, /usr/man and /usr/include, type + make install +To install somewhere else, eg, /xxx/yyy/{bin,lib,man,include}, type + make install PREFIX=/xxx/yyy +If you are (justifiably) paranoid and want to see what 'make install' +is going to do, you can first do + make -n install or + make -n install PREFIX=/xxx/yyy respectively. +The -n instructs make to show the commands it would execute, but +not actually execute them. + +Instructions for use are in the preformatted manual page, in the file +bzip2.txt. For more detailed documentation, read the full manual. +It is available in Postscript form (manual.ps) and HTML form +(manual_toc.html). + +You can also do "bzip2 --help" to see some helpful information. +"bzip2 -L" displays the software license. + diff --git a/drivers/lib/zlib/.cvsignore b/drivers/lib/zlib/.cvsignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/drivers/lib/zlib/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/drivers/lib/zlib/ChangeLog b/drivers/lib/zlib/ChangeLog new file mode 100644 index 0000000..bf2e3f9 --- /dev/null +++ b/drivers/lib/zlib/ChangeLog @@ -0,0 +1,481 @@ + + ChangeLog file for zlib + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occuring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generated bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/drivers/lib/zlib/FAQ b/drivers/lib/zlib/FAQ new file mode 100644 index 0000000..47a7d60 --- /dev/null +++ b/drivers/lib/zlib/FAQ @@ -0,0 +1,100 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://www.zlib.org which may have more recent information. +The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. If you + want a precompiled DLL, see http://www.winimage.com/zLibDll/ . Questions + about the zlib DLL should be sent to Gilles Vollant (info@winimage.com). + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://www.winimage.com/zLibDll/cmp-z-it.zip + * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm + * contrib/visual-basic.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR + + Make sure that before the call of compress, the length of the compressed + buffer is equal to the total size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR + + Before making the call, make sure that avail_in and avail_out are not + zero. When setting the parameter flush equal to Z_FINISH, also make sure + that avail_out is big enough to allow processing all pending input. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h for the moment, and Francis S. Lin has converted it to a + web page zlib.html. Volunteers to transform this to Unix-style man pages, + please contact Jean-loup Gailly (jloup@gzip.org). Examples of zlib usage + are in the files example.c and minigzip.c. + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple + package. zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of + zlib. Please try to reproduce the problem with a small program and send + the corresponding source to us at zlib@gzip.org . Do not send + multi-megabyte data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the directories contrib/delphi and contrib/delphi2 in the zlib + distribution. + +11. Can zlib handle .zip archives? + + See the directory contrib/minizip in the zlib distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + make clean + ./configure -s + make + +14. Why does "make test" fail on Mac OS X? + + Mac OS X already includes zlib as a shared library, and so -lz links the + shared library instead of the one that the "make" compiled. For zlib + 1.1.3, the two are incompatible due to different compile-time + options. Simply change the -lz in the Makefile to libz.a, and it will use + the compiled library instead of the shared one and the "make test" will + succeed. + +15. I have a question about OttoPDF + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site Joel Hainley jhainley@myndkryme.com. diff --git a/drivers/lib/zlib/INDEX b/drivers/lib/zlib/INDEX new file mode 100644 index 0000000..8a24576 --- /dev/null +++ b/drivers/lib/zlib/INDEX @@ -0,0 +1,86 @@ +ChangeLog history of changes +INDEX this file +FAQ Frequently Asked Questions about zlib +Make_vms.com script for Vax/VMS +Makefile makefile for Unix (generated by configure) +Makefile.in makefile for Unix (template for configure) +Makefile.riscos makefile for RISCOS +README guess what +algorithm.txt description of the (de)compression algorithm +configure configure script for Unix +descrip.mms makefile for Vax/VMS +zlib.3 mini man page for zlib (volunteers to write full + man pages from zlib.h welcome. write to jloup@gzip.org) + +amiga/Makefile.sas makefile for Amiga SAS/C +amiga/Makefile.pup makefile for Amiga powerUP SAS/C PPC + +msdos/Makefile.w32 makefile for Microsoft Visual C++ 32-bit +msdos/Makefile.b32 makefile for Borland C++ 32-bit +msdos/Makefile.bor makefile for Borland C/C++ 16-bit +msdos/Makefile.dj2 makefile for DJGPP 2.x +msdos/Makefile.emx makefile for EMX 0.9c (32-bit DOS/OS2) +msdos/Makefile.msc makefile for Microsoft C 16-bit +msdos/Makefile.tc makefile for Turbo C +msdos/Makefile.wat makefile for Watcom C +msdos/zlib.def definition file for Windows DLL +msdos/zlib.rc definition file for Windows DLL + +nt/Makefile.nt makefile for Windows NT +nt/zlib.dnt definition file for Windows NT DLL +nt/Makefile.emx makefile for EMX 0.9c/RSXNT 1.41 (Win32 Intel) +nt/Makefile.gcc makefile for Windows NT using GCC (mingw32) + + + zlib public header files (must be kept): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +deflate.c +deflate.h +gzio.c +infblock.c +infblock.h +infcodes.c +infcodes.h +inffast.c +inffast.h +inflate.c +inftrees.c +inftrees.h +infutil.c +infutil.h +maketree.c +trees.c +uncompr.c +zutil.c +zutil.h + + source files for sample programs: +example.c +minigzip.c + + unsupported contribution by third parties + +contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + +contrib/minizip/ by Gilles Vollant + Mini zip and unzip based on zlib + See http://www.winimage.com/zLibDll/unzip.html + +contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + +contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + +contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz extractor using zlib + +contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. diff --git a/drivers/lib/zlib/Make_vms.com b/drivers/lib/zlib/Make_vms.com new file mode 100644 index 0000000..1c57e8f --- /dev/null +++ b/drivers/lib/zlib/Make_vms.com @@ -0,0 +1,115 @@ +$! make libz under VMS +$! written by Martin P.J. Zinser +$! +$! Look for the compiler used +$! +$ ccopt = "" +$ if f$getsyi("HW_MODEL").ge.1024 +$ then +$ ccopt = "/prefix=all"+ccopt +$ comp = "__decc__=1" +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ else +$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" +$ then +$ comp = "__vaxc__=1" +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ else +$ if f$trnlnm("SYS").eqs."" then define sys decc$library_include: +$ ccopt = "/decc/prefix=all"+ccopt +$ comp = "__decc__=1" +$ endif +$ endif +$! +$! Build the thing plain or with mms +$! +$ write sys$output "Compiling Zlib sources ..." +$ if f$search("SYS$SYSTEM:MMS.EXE").eqs."" +$ then +$ dele example.obj;*,minigzip.obj;* +$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - + adler32.c zlib.h zconf.h +$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - + compress.c zlib.h zconf.h +$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - + crc32.c zlib.h zconf.h +$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - + deflate.c deflate.h zutil.h zlib.h zconf.h +$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" - + gzio.c zutil.h zlib.h zconf.h +$ CALL MAKE infblock.OBJ "CC ''CCOPT' infblock" - + infblock.c zutil.h zlib.h zconf.h infblock.h +$ CALL MAKE infcodes.OBJ "CC ''CCOPT' infcodes" - + infcodes.c zutil.h zlib.h zconf.h inftrees.h +$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - + inffast.c zutil.h zlib.h zconf.h inffast.h +$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - + inflate.c zutil.h zlib.h zconf.h infblock.h +$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - + inftrees.c zutil.h zlib.h zconf.h inftrees.h +$ CALL MAKE infutil.OBJ "CC ''CCOPT' infutil" - + infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h +$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - + trees.c deflate.h zutil.h zlib.h zconf.h +$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - + uncompr.c zlib.h zconf.h +$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - + zutil.c zutil.h zlib.h zconf.h +$ write sys$output "Building Zlib ..." +$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ +$ write sys$output "Building example..." +$ CALL MAKE example.OBJ "CC ''CCOPT' example" - + example.c zlib.h zconf.h +$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb +$ write sys$output "Building minigzip..." +$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" - + minigzip.c zlib.h zconf.h +$ call make minigzip.exe - + "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" - + minigzip.obj libz.olb +$ else +$ mms/macro=('comp') +$ endif +$ write sys$output "Zlib build completed" +$ exit +$! +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE diff --git a/drivers/lib/zlib/Makefile b/drivers/lib/zlib/Makefile new file mode 100644 index 0000000..0202634 --- /dev/null +++ b/drivers/lib/zlib/Makefile @@ -0,0 +1,29 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = library + +TARGET_NAME = zlib + +TARGET_CFLAGS = \ + -MMD -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +TARGET_OBJECTS = \ + adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o \ + inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +zlib.sym: + @echo FIXME!>$@ + +# FIXME: this rule should be defined in helper.mk +$(TARGET_NAME).nostrip.a: + @echo FIXME! + @echo FIXME!>$@ + +# EOF diff --git a/drivers/lib/zlib/Makefile.in b/drivers/lib/zlib/Makefile.in new file mode 100644 index 0000000..531562b --- /dev/null +++ b/drivers/lib/zlib/Makefile.in @@ -0,0 +1,175 @@ +# Makefile for zlib +# Copyright (C) 1995-2002 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# The call of configure is optional if you don't have special requirements +# If you wish to build zlib as a shared library, use: ./configure -s + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DDEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +LDFLAGS=-L. -lz +LDSHARED=$(CC) +CPP=$(CC) -E + +VER=1.1.4 +LIBS=libz.a +SHAREDLIB=libz.so + +AR=ar rc +RANLIB=ranlib +TAR=tar +SHELL=/bin/sh + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +includedir = ${prefix}/include + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +OBJA = +# to use the asm code: make OBJA=match.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README FAQ INDEX ChangeLog configure Make*[a-z0-9] *.[ch] *.mms \ + algorithm.txt zlib.3 zlib.html \ + msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Make*[a-z0-9] nt/zlib.dnt amiga/Make*.??? os2/M*.os2 os2/zlib.def \ + contrib/RE*.contrib contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/asm[56]86/*.?86 \ + contrib/asm[56]86/*.S contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \ + contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]?? \ + contrib/delphi*/*.??? + +all: example minigzip + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +libz.a: $(OBJS) $(OBJA) + $(AR) $@ $(OBJS) $(OBJA) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +$(SHAREDLIB).$(VER): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + rm -f $(SHAREDLIB) $(SHAREDLIB).1 + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIB).1 + +example: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +install: $(LIBS) + -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi + -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi + cp zlib.h zconf.h $(includedir) + chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h + cp $(LIBS) $(libdir) + cd $(libdir); chmod 755 $(LIBS) + -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1 + cd $(libdir); if test -f $(SHAREDLIB).$(VER); then \ + rm -f $(SHAREDLIB) $(SHAREDLIB).1; \ + ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \ + ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \ + (ldconfig || true) >/dev/null 2>&1; \ + fi +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +uninstall: + cd $(includedir); \ + v=$(VER); \ + if test -f zlib.h; then \ + v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \ + rm -f zlib.h zconf.h; \ + fi; \ + cd $(libdir); rm -f libz.a; \ + if test -f $(SHAREDLIB).$$v; then \ + rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \ + fi + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz so_locations \ + _match.s maketree + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c contrib/minizip/test.zip + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c contrib/minizip/test.zip + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/drivers/lib/zlib/Makefile.riscos b/drivers/lib/zlib/Makefile.riscos new file mode 100644 index 0000000..d97f449 --- /dev/null +++ b/drivers/lib/zlib/Makefile.riscos @@ -0,0 +1,151 @@ +# Project: zlib_1_03 +# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 +# test works out-of-the-box, installs `somewhere' on demand + +# Toolflags: +CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah +C++flags = -c -depend !Depend -IC: -throwback +Linkflags = -aif -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -l -o $@ +Squeezeflags = -o $@ + +# change the line below to where _you_ want the library installed. +libdest = lib:zlib + +# Final targets: +@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ + @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ + @.o.uncompr @.o.zutil + LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ + @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ + @.o.trees @.o.uncompr @.o.zutil +test: @.minigzip @.example @.lib + @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV + @echo running tests: hang on. + @/@.minigzip -f -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -f -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -1 libc + @/@.minigzip -d libc-gz + @diff @.lib @.libc + @echo that should have reported '@.lib and @.libc identical' if you have diff. + @/@.example @.fred @.fred + @echo that will have given lots of hello!'s. + +@.minigzip: @.o.minigzip @.lib C:o.Stubs + Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs +@.example: @.o.example @.lib C:o.Stubs + Link $(Linkflags) @.o.example @.lib C:o.Stubs + +install: @.lib + cdir $(libdest) + cdir $(libdest).h + @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV + @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV + @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV + @echo okay, installed zlib in $(libdest) + +clean:; remove @.minigzip + remove @.example + remove @.libc + -wipe @.o.* F~r~cV + remove @.fred + +# User-editable dependencies: +.c.o: + cc $(ccflags) -o $@ $< + +# Static dependencies: + +# Dynamic dependencies: +o.example: c.example +o.example: h.zlib +o.example: h.zconf +o.minigzip: c.minigzip +o.minigzip: h.zlib +o.minigzip: h.zconf +o.adler32: c.adler32 +o.adler32: h.zlib +o.adler32: h.zconf +o.compress: c.compress +o.compress: h.zlib +o.compress: h.zconf +o.crc32: c.crc32 +o.crc32: h.zlib +o.crc32: h.zconf +o.deflate: c.deflate +o.deflate: h.deflate +o.deflate: h.zutil +o.deflate: h.zlib +o.deflate: h.zconf +o.gzio: c.gzio +o.gzio: h.zutil +o.gzio: h.zlib +o.gzio: h.zconf +o.infblock: c.infblock +o.infblock: h.zutil +o.infblock: h.zlib +o.infblock: h.zconf +o.infblock: h.infblock +o.infblock: h.inftrees +o.infblock: h.infcodes +o.infblock: h.infutil +o.infcodes: c.infcodes +o.infcodes: h.zutil +o.infcodes: h.zlib +o.infcodes: h.zconf +o.infcodes: h.inftrees +o.infcodes: h.infblock +o.infcodes: h.infcodes +o.infcodes: h.infutil +o.infcodes: h.inffast +o.inffast: c.inffast +o.inffast: h.zutil +o.inffast: h.zlib +o.inffast: h.zconf +o.inffast: h.inftrees +o.inffast: h.infblock +o.inffast: h.infcodes +o.inffast: h.infutil +o.inffast: h.inffast +o.inflate: c.inflate +o.inflate: h.zutil +o.inflate: h.zlib +o.inflate: h.zconf +o.inflate: h.infblock +o.inftrees: c.inftrees +o.inftrees: h.zutil +o.inftrees: h.zlib +o.inftrees: h.zconf +o.inftrees: h.inftrees +o.inftrees: h.inffixed +o.infutil: c.infutil +o.infutil: h.zutil +o.infutil: h.zlib +o.infutil: h.zconf +o.infutil: h.infblock +o.infutil: h.inftrees +o.infutil: h.infcodes +o.infutil: h.infutil +o.trees: c.trees +o.trees: h.deflate +o.trees: h.zutil +o.trees: h.zlib +o.trees: h.zconf +o.trees: h.trees +o.uncompr: c.uncompr +o.uncompr: h.zlib +o.uncompr: h.zconf +o.zutil: c.zutil +o.zutil: h.zutil +o.zutil: h.zlib +o.zutil: h.zconf diff --git a/drivers/lib/zlib/README b/drivers/lib/zlib/README new file mode 100644 index 0000000..29d6714 --- /dev/null +++ b/drivers/lib/zlib/README @@ -0,0 +1,147 @@ +zlib 1.1.4 is a general purpose data compression library. All the code +is thread safe. The data format used by the zlib library +is described by RFCs (Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate +format) and rfc1952.txt (gzip format). These documents are also available in +other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact jloup@gzip.org). A usage +example of the library is given in the file example.c which also tests that +the library is working correctly. Another example is given in the file +minigzip.c. The compression library itself is composed of all source files +except example.c and minigzip.c. + +To compile all files and run the test program, follow the instructions +given at the top of Makefile. In short "make test; make install" +should work for most machines. For Unix: "./configure; make test; make install" +For MSDOS, use one of the special makefiles such as Makefile.msc. +For VMS, use Make_vms.com or descrip.mms. + +Questions about zlib should be sent to , or to +Gilles Vollant for the Windows DLL version. +The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/ +Before reporting a problem, please check this site to verify that +you have the latest version of zlib; otherwise get the latest version and +check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html +before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available in +http://dogma.net/markn/articles/zlibtool/zlibtool.htm + +The changes made in version 1.1.4 are documented in the file ChangeLog. +The only changes made since 1.1.3 are bug corrections: + +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +The beta version 1.1.5beta includes many more changes. A new official +version 1.1.5 will be released as soon as extensive testing has been +completed on it. + + +Unsupported third party contributions are provided in directory "contrib". + +A Java implementation of zlib is available in the Java Development Kit +http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html +See the zlib home page http://www.zlib.org for details. + +A Perl interface to zlib written by Paul Marquess +is in the CPAN (Comprehensive Perl Archive Network) sites +http://www.cpan.org/modules/by-module/Compress/ + +A Python interface to zlib written by A.M. Kuchling +is available in Python 1.5 and later versions, see +http://www.python.org/doc/lib/module-zlib.html + +A zlib binding for TCL written by Andreas Kupries +is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html + +An experimental package to read and write files in .zip format, +written on top of zlib by Gilles Vollant , is +available at http://www.winimage.com/zLibDll/unzip.html +and also in the contrib/minizip directory of zlib. + + +Notes for some targets: + +- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc + and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL + The zlib DLL support was initially done by Alessandro Iacopetti and is + now maintained by Gilles Vollant . Check the zlib DLL + home page at http://www.winimage.com/zLibDll + + From Visual Basic, you can call the DLL functions which do not take + a structure as argument: compress, uncompress and all gz* functions. + See contrib/visual-basic.txt for more information, or get + http://www.tcfb.com/dowseware/cmp-z-it.zip + +- For 64-bit Irix, deflate.c must be compiled without any optimization. + With -O, one libpng test fails. The test works in 32 bit mode (with + the -n32 compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 + it works when compiled with cc. + +- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 + is necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works + with other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. + +- For Turbo C the small model is supported only with reduced performance to + avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 + +- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html + Per Harald Myrvang + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate + and zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; + they are too numerous to cite here. + +Copyright notice: + + (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* +receiving lengthy legal documents to sign. The sources are provided +for free but without warranty of any kind. The library has been +entirely written by Jean-loup Gailly and Mark Adler; it does not +include third-party code. + +If you redistribute modified sources, we would appreciate that you include +in the file ChangeLog history information documenting your changes. diff --git a/drivers/lib/zlib/adler32.c b/drivers/lib/zlib/adler32.c new file mode 100644 index 0000000..fae88b6 --- /dev/null +++ b/drivers/lib/zlib/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/drivers/lib/zlib/algorithm.txt b/drivers/lib/zlib/algorithm.txt new file mode 100644 index 0000000..cdc830b --- /dev/null +++ b/drivers/lib/zlib/algorithm.txt @@ -0,0 +1,213 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The real question is, given a Huffman tree, how to decode fast. The most +important realization is that shorter codes are much more common than +longer codes, so pay attention to decoding the short codes fast, and let +the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and set it +for the maximum speed. + +inflate() sends new trees relatively often, so it is possibly set for a +smaller first level table than an application that has only one tree for +all the data. For inflate, which has 286 possible codes for the +literal/length tree, the size of the first table is nine bits. Also the +distance trees have 30 possible values, and the size of the first table is +six bits. Note that for each of those cases, the table ended up one bit +longer than the ``average'' code length, i.e. the code length of an +approximately flat code which would be a little more than eight bits for +286 symbols and a little less than five bits for 30 symbols. It would be +interesting to see if optimizing the first level table for other +applications gave values within a bit or two of the flat code size. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend two much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode to and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +ftp://ds.internic.net/rfc/rfc1951.txt diff --git a/drivers/lib/zlib/amiga/Makefile.pup b/drivers/lib/zlib/amiga/Makefile.pup new file mode 100644 index 0000000..6cfad1d --- /dev/null +++ b/drivers/lib/zlib/amiga/Makefile.pup @@ -0,0 +1,66 @@ +# Amiga powerUP (TM) Makefile +# makefile for libpng and SAS C V6.58/7.00 PPC compiler +# Copyright (C) 1998 by Andreas R. Kleinert + +CC = scppc +CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ + OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 +LIBNAME = libzip.a +AR = ppc-amigaos-ar +AR_FLAGS = cr +RANLIB = ppc-amigaos-ranlib +LDFLAGS = -r -o +LDLIBS = LIB:scppc.a +LN = ppc-amigaos-ld +RM = delete quiet + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example minigzip + +test: all + example + echo hello world | minigzip | minigzip -d + +$(LIBNAME): $(OBJS) + $(AR) $(AR_FLAGS) $@ $(OBJS) + $(RANLIB) $@ + +example: example.o $(LIBNAME) + $(LN) $(LDFLAGS) example LIB:c_ppc.o example.o $(LIBNAME) $(LDLIBS) LIB:end.o + +minigzip: minigzip.o $(LIBNAME) + $(LN) $(LDFLAGS) minigzip LIB:c_ppc.o minigzip.o $(LIBNAME) $(LDLIBS) LIB:end.o + +clean: + $(RM) *.o example minigzip $(LIBNAME) foo.gz + +zip: + zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ + descrip.mms *.[ch] + +tgz: + cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ + zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zutil.h zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zutil.h zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +infcodes.o: zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h inftrees.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/drivers/lib/zlib/amiga/Makefile.sas b/drivers/lib/zlib/amiga/Makefile.sas new file mode 100644 index 0000000..5323e82 --- /dev/null +++ b/drivers/lib/zlib/amiga/Makefile.sas @@ -0,0 +1,64 @@ +# SMakefile for zlib +# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly +# Osma Ahvenlampi +# Amiga, SAS/C 6.56 & Smake + +CC=sc +CFLAGS=OPT +#CFLAGS=OPT CPU=68030 +#CFLAGS=DEBUG=LINE +LDFLAGS=LIB z.lib + +SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ + NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: SCOPTIONS example minigzip + +test: all + `cd`/example + echo hello world | minigzip | minigzip -d + +install: z.lib + copy zlib.h zconf.h INCLUDE: clone + copy z.lib LIB: clone + +z.lib: $(OBJS) + oml z.lib r $(OBJS) + +example: example.o z.lib + $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) + +minigzip: minigzip.o z.lib + $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) + +clean: + -delete force quiet *.o example minigzip z.lib foo.gz *.lnk SCOPTIONS + +SCOPTIONS: Smakefile + copy to $@ 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/drivers/lib/zlib/configure b/drivers/lib/zlib/configure new file mode 100644 index 0000000..e894235 --- /dev/null +++ b/drivers/lib/zlib/configure @@ -0,0 +1,212 @@ +#!/bin/sh +# configure script for zlib. This script is needed only if +# you wish to build a shared library and your system supports them, +# of if you need special compiler, flags or install directory. +# Otherwise, you can just use directly "make test; make install" +# +# To create a shared library, use "configure --shared"; by default a static +# library is created. If the primitive shared library support provided here +# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz +# +# To impose specific compiler or flags or install directory, use for example: +# prefix=$HOME CC=cc CFLAGS="-O4" ./configure +# or for csh/tcsh users: +# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) +# LDSHARED is the command to be used to create a shared library + +# Incorrect settings of CC or CFLAGS may prevent creating a shared library. +# If you have problems, try without defining CC and CFLAGS before reporting +# an error. + +LIBS=libz.a +SHAREDLIB=libz.so +VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` +AR=${AR-"ar rc"} +RANLIB=${RANLIB-"ranlib"} +prefix=${prefix-/usr/local} +exec_prefix=${exec_prefix-'${prefix}'} +libdir=${libdir-'${exec_prefix}/lib'} +includedir=${includedir-'${prefix}/include'} +shared_ext='.so' +shared=0 +gcc=0 +old_cc="$CC" +old_cflags="$CFLAGS" + +while test $# -ge 1 +do +case "$1" in + -h* | --h*) + echo 'usage:' + echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]' + echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]' + exit 0;; + -p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; + -e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; + -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; + -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;; + -p* | --p*) prefix="$2"; shift; shift;; + -e* | --e*) exec_prefix="$2"; shift; shift;; + -l* | --l*) libdir="$2"; shift; shift;; + -i* | --i*) includedir="$2"; shift; shift;; + -s* | --s*) shared=1; shift;; + esac +done + +test=ztest$$ +cat > $test.c </dev/null; then + CC="$cc" + SFLAGS=${CFLAGS-"-fPIC -O3"} + CFLAGS="$cflags" + case `(uname -s || echo unknown) 2>/dev/null` in + Linux | linux) LDSHARED=${LDSHARED-"gcc -shared -Wl,-soname,libz.so.1"};; + *) LDSHARED=${LDSHARED-"gcc -shared"};; + esac +else + # find system name and corresponding cc options + CC=${CC-cc} + case `(uname -sr || echo unknown) 2>/dev/null` in + HP-UX*) SFLAGS=${CFLAGS-"-O +z"} + CFLAGS=${CFLAGS-"-O"} +# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} + LDSHARED=${LDSHARED-"ld -b"} + shared_ext='.sl' + SHAREDLIB='libz.sl';; + IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} + CFLAGS=${CFLAGS-"-ansi -O2"} + LDSHARED=${LDSHARED-"cc -shared"};; + OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,$SHAREDLIB -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};; + OSF1*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared"};; + QNX*) SFLAGS=${CFLAGS-"-4 -O"} + CFLAGS=${CFLAGS-"-4 -O"} + LDSHARED=${LDSHARED-"cc"} + RANLIB=${RANLIB-"true"} + AR="cc -A";; + SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} + CFLAGS=${CFLAGS-"-O3"} + LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};; + SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."} + CFLAGS=${CFLAGS-"-fast -xcg89"} + LDSHARED=${LDSHARED-"cc -G"};; + SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} + CFLAGS=${CFLAGS-"-O2"} + LDSHARED=${LDSHARED-"ld"};; + UNIX_System_V\ 4.2.0) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"};; + UNIX_SV\ 4.2MP) + SFLAGS=${CFLAGS-"-Kconform_pic -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"};; + # send working options for other systems to support@gzip.org + *) SFLAGS=${CFLAGS-"-O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -shared"};; + esac +fi + +if test $shared -eq 1; then + echo Checking for shared library support... + # we must test in two steps (cc then ld), required at least on SunOS 4.x + if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" && + test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then + CFLAGS="$SFLAGS" + LIBS="$SHAREDLIB.$VER" + echo Building shared library $SHAREDLIB.$VER with $CC. + elif test -z "$old_cc" -a -z "$old_cflags"; then + echo No shared library suppport. + shared=0; + else + echo 'No shared library suppport; try without defining CC and CFLAGS' + shared=0; + fi +fi +if test $shared -eq 0; then + LDSHARED="$CC" + echo Building static library $LIBS version $VER with $CC. +fi + +cat > $test.c < +int main() { return 0; } +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + CFLAGS="$CFLAGS -DHAVE_UNISTD_H" + echo "Checking for unistd.h... Yes." +else + echo "Checking for unistd.h... No." +fi + +cat > $test.c < +int main() { return 0; } +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + echo "Checking for errno.h... Yes." +else + echo "Checking for errno.h... No." + CFLAGS="$CFLAGS -DNO_ERRNO_H" +fi + +cat > $test.c < +#include +#include +caddr_t hello() { + return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0); +} +EOF +if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then + CFLAGS="$CFLAGS -DUSE_MMAP" + echo Checking for mmap support... Yes. +else + echo Checking for mmap support... No. +fi + +CPP=${CPP-"$CC -E"} +case $CFLAGS in + *ASMV*) + if test "`nm $test.o | grep _hello`" = ""; then + CPP="$CPP -DNO_UNDERLINE" + echo Checking for underline in external names... No. + else + echo Checking for underline in external names... Yes. + fi;; +esac + +rm -f $test.[co] $test$shared_ext + +# udpate Makefile +sed < Makefile.in " +/^CC *=/s%=.*%=$CC% +/^CFLAGS *=/s%=.*%=$CFLAGS% +/^CPP *=/s%=.*%=$CPP% +/^LDSHARED *=/s%=.*%=$LDSHARED% +/^LIBS *=/s%=.*%=$LIBS% +/^SHAREDLIB *=/s%=.*%=$SHAREDLIB% +/^AR *=/s%=.*%=$AR% +/^RANLIB *=/s%=.*%=$RANLIB% +/^VER *=/s%=.*%=$VER% +/^prefix *=/s%=.*%=$prefix% +/^exec_prefix *=/s%=.*%=$exec_prefix% +/^libdir *=/s%=.*%=$libdir% +/^includedir *=/s%=.*%=$includedir% +" > Makefile diff --git a/drivers/lib/zlib/contrib/README.contrib b/drivers/lib/zlib/contrib/README.contrib new file mode 100644 index 0000000..7ad191c --- /dev/null +++ b/drivers/lib/zlib/contrib/README.contrib @@ -0,0 +1,34 @@ +All files under this contrib directory are UNSUPPORTED. There were +provided by users of zlib and were not tested by the authors of zlib. +Use at your own risk. Please contact the authors of the contributions +for help about these, not the zlib authors. Thanks. + + +asm386/ by Gilles Vollant + 386 asm code replacing longest_match(), for Visual C++ 4.2 and ML 6.11c + +asm586/ and asm686/ by Brian Raiter + asm code for Pentium and Pentium Pro + See http://www.muppetlabs.com/~breadbox/software/assembly.html + +delphi/ by Bob Dellaca + Support for Delphi + +delphi2/ by Davide Moretti + Another support for C++Builder and Delphi + +minizip/ by Gilles Vollant + Mini zip and unzip based on zlib + See http://www.winimage.com/zLibDll/unzip.html + +iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + +iostream2/ by Tyge Løvset + Another C++ I/O streams interface + +untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + +visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. diff --git a/drivers/lib/zlib/contrib/asm386/gvmat32.asm b/drivers/lib/zlib/contrib/asm386/gvmat32.asm new file mode 100644 index 0000000..28d527f --- /dev/null +++ b/drivers/lib/zlib/contrib/asm386/gvmat32.asm @@ -0,0 +1,559 @@ +; +; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86 +; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. +; File written by Gilles Vollant, by modifiying the longest_match +; from Jean-loup Gailly in deflate.c +; It need wmask == 0x7fff +; (assembly code is faster with a fixed wmask) +; +; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK) +; I compile with : "ml /coff /Zi /c gvmat32.asm" +; + +;uInt longest_match_7fff(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ + + NbStack equ 76 + cur_match equ dword ptr[esp+NbStack-0] + str_s equ dword ptr[esp+NbStack-4] +; 5 dword on top (ret,ebp,esi,edi,ebx) + adrret equ dword ptr[esp+NbStack-8] + pushebp equ dword ptr[esp+NbStack-12] + pushedi equ dword ptr[esp+NbStack-16] + pushesi equ dword ptr[esp+NbStack-20] + pushebx equ dword ptr[esp+NbStack-24] + + chain_length equ dword ptr [esp+NbStack-28] + limit equ dword ptr [esp+NbStack-32] + best_len equ dword ptr [esp+NbStack-36] + window equ dword ptr [esp+NbStack-40] + prev equ dword ptr [esp+NbStack-44] + scan_start equ word ptr [esp+NbStack-48] + wmask equ dword ptr [esp+NbStack-52] + match_start_ptr equ dword ptr [esp+NbStack-56] + nice_match equ dword ptr [esp+NbStack-60] + scan equ dword ptr [esp+NbStack-64] + + windowlen equ dword ptr [esp+NbStack-68] + match_start equ dword ptr [esp+NbStack-72] + strend equ dword ptr [esp+NbStack-76] + NbStackAdd equ (NbStack-24) + + .386p + + name gvmatch + .MODEL FLAT + + + +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure + dep_chain_length equ 70h+4 + dep_window equ 2ch+4 + dep_strstart equ 60h+4 + dep_prev_length equ 6ch+4 + dep_nice_match equ 84h+4 + dep_w_size equ 20h+4 + dep_prev equ 34h+4 + dep_w_mask equ 28h+4 + dep_good_match equ 80h+4 + dep_match_start equ 64h+4 + dep_lookahead equ 68h+4 + + +_TEXT segment + +IFDEF NOUNDERLINE + public longest_match_7fff +; public match_init +ELSE + public _longest_match_7fff +; public _match_init +ENDIF + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + + +IFDEF NOUNDERLINE +;match_init proc near +; ret +;match_init endp +ELSE +;_match_init proc near +; ret +;_match_init endp +ENDIF + + +IFDEF NOUNDERLINE +longest_match_7fff proc near +ELSE +_longest_match_7fff proc near +ENDIF + + mov edx,[esp+4] + + + + push ebp + push edi + push esi + push ebx + + sub esp,NbStackAdd + +; initialize or check the variables used in match.asm. + mov ebp,edx + +; chain_length = s->max_chain_length +; if (prev_length>=good_match) chain_length >>= 2 + mov edx,[ebp+dep_chain_length] + mov ebx,[ebp+dep_prev_length] + cmp [ebp+dep_good_match],ebx + ja noshr + shr edx,2 +noshr: +; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop + inc edx + mov edi,[ebp+dep_nice_match] + mov chain_length,edx + mov eax,[ebp+dep_lookahead] + cmp eax,edi +; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + jae nolookaheadnicematch + mov edi,eax +nolookaheadnicematch: +; best_len = s->prev_length + mov best_len,ebx + +; window = s->window + mov esi,[ebp+dep_window] + mov ecx,[ebp+dep_strstart] + mov window,esi + + mov nice_match,edi +; scan = window + strstart + add esi,ecx + mov scan,esi +; dx = *window + mov dx,word ptr [esi] +; bx = *(window+best_len-1) + mov bx,word ptr [esi+ebx-1] + add esi,MAX_MATCH-1 +; scan_start = *scan + mov scan_start,dx +; strend = scan + MAX_MATCH-1 + mov strend,esi +; bx = scan_end = *(window+best_len-1) + +; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov esi,[ebp+dep_w_size] + sub esi,MIN_LOOKAHEAD +; here esi = MAX_DIST(s) + sub ecx,esi + ja nodist + xor ecx,ecx +nodist: + mov limit,ecx + +; prev = s->prev + mov edx,[ebp+dep_prev] + mov prev,edx + +; + mov edx,dword ptr [ebp+dep_match_start] + mov bp,scan_start + mov eax,cur_match + mov match_start,edx + + mov edx,window + mov edi,edx + add edi,best_len + mov esi,prev + dec edi +; windowlen = window + best_len -1 + mov windowlen,edi + + jmp beginloop2 + align 4 + +; here, in the loop +; eax = ax = cur_match +; ecx = limit +; bx = scan_end +; bp = scan_start +; edi = windowlen (window + best_len -1) +; esi = prev + + +;// here; chain_length <=16 +normalbeg0add16: + add chain_length,16 + jz exitloop +normalbeg0: + cmp word ptr[edi+eax],bx + je normalbeg2noroll +rcontlabnoroll: +; cur_match = prev[cur_match & wmask] + and eax,7fffh + mov ax,word ptr[esi+eax*2] +; if cur_match > limit, go to exitloop + cmp ecx,eax + jnb exitloop +; if --chain_length != 0, go to exitloop + dec chain_length + jnz normalbeg0 + jmp exitloop + +normalbeg2noroll: +; if (scan_start==*(cur_match+window)) goto normalbeg2 + cmp bp,word ptr[edx+eax] + jne rcontlabnoroll + jmp normalbeg2 + +contloop3: + mov edi,windowlen + +; cur_match = prev[cur_match & wmask] + and eax,7fffh + mov ax,word ptr[esi+eax*2] +; if cur_match > limit, go to exitloop + cmp ecx,eax +jnbexitloopshort1: + jnb exitloop +; if --chain_length != 0, go to exitloop + + +; begin the main loop +beginloop2: + sub chain_length,16+1 +; if chain_length <=16, don't use the unrolled loop + jna normalbeg0add16 + +do16: + cmp word ptr[edi+eax],bx + je normalbeg2dc0 + +maccn MACRO lab + and eax,7fffh + mov ax,word ptr[esi+eax*2] + cmp ecx,eax + jnb exitloop + cmp word ptr[edi+eax],bx + je lab + ENDM + +rcontloop0: + maccn normalbeg2dc1 + +rcontloop1: + maccn normalbeg2dc2 + +rcontloop2: + maccn normalbeg2dc3 + +rcontloop3: + maccn normalbeg2dc4 + +rcontloop4: + maccn normalbeg2dc5 + +rcontloop5: + maccn normalbeg2dc6 + +rcontloop6: + maccn normalbeg2dc7 + +rcontloop7: + maccn normalbeg2dc8 + +rcontloop8: + maccn normalbeg2dc9 + +rcontloop9: + maccn normalbeg2dc10 + +rcontloop10: + maccn short normalbeg2dc11 + +rcontloop11: + maccn short normalbeg2dc12 + +rcontloop12: + maccn short normalbeg2dc13 + +rcontloop13: + maccn short normalbeg2dc14 + +rcontloop14: + maccn short normalbeg2dc15 + +rcontloop15: + and eax,7fffh + mov ax,word ptr[esi+eax*2] + cmp ecx,eax + jnb exitloop + + sub chain_length,16 + ja do16 + jmp normalbeg0add16 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +normbeg MACRO rcontlab,valsub +; if we are here, we know that *(match+best_len-1) == scan_end + cmp bp,word ptr[edx+eax] +; if (match != scan_start) goto rcontlab + jne rcontlab +; calculate the good chain_length, and we'll compare scan and match string + add chain_length,16-valsub + jmp iseq + ENDM + + +normalbeg2dc11: + normbeg rcontloop11,11 + +normalbeg2dc12: + normbeg short rcontloop12,12 + +normalbeg2dc13: + normbeg short rcontloop13,13 + +normalbeg2dc14: + normbeg short rcontloop14,14 + +normalbeg2dc15: + normbeg short rcontloop15,15 + +normalbeg2dc10: + normbeg rcontloop10,10 + +normalbeg2dc9: + normbeg rcontloop9,9 + +normalbeg2dc8: + normbeg rcontloop8,8 + +normalbeg2dc7: + normbeg rcontloop7,7 + +normalbeg2dc6: + normbeg rcontloop6,6 + +normalbeg2dc5: + normbeg rcontloop5,5 + +normalbeg2dc4: + normbeg rcontloop4,4 + +normalbeg2dc3: + normbeg rcontloop3,3 + +normalbeg2dc2: + normbeg rcontloop2,2 + +normalbeg2dc1: + normbeg rcontloop1,1 + +normalbeg2dc0: + normbeg rcontloop0,0 + + +; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end + +normalbeg2: + mov edi,window + + cmp bp,word ptr[edi+eax] + jne contloop3 ; if *(ushf*)match != scan_start, continue + +iseq: +; if we are here, we know that *(match+best_len-1) == scan_end +; and (match == scan_start) + + mov edi,edx + mov esi,scan ; esi = scan + add edi,eax ; edi = window + cur_match = match + + mov edx,[esi+3] ; compare manually dword at match+3 + xor edx,[edi+3] ; and scan +3 + + jz begincompare ; if equal, go to long compare + +; we will determine the unmatch byte and calculate len (in esi) + or dl,dl + je eq1rr + mov esi,3 + jmp trfinval +eq1rr: + or dx,dx + je eq1 + + mov esi,4 + jmp trfinval +eq1: + and edx,0ffffffh + jz eq11 + mov esi,5 + jmp trfinval +eq11: + mov esi,6 + jmp trfinval + +begincompare: + ; here we now scan and match begin same + add edi,6 + add esi,6 + mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes + repe cmpsd ; loop until mismatch + + je trfin ; go to trfin if not unmatch +; we determine the unmatch byte + sub esi,4 + mov edx,[edi-4] + xor edx,[esi] + + or dl,dl + jnz trfin + inc esi + + or dx,dx + jnz trfin + inc esi + + and edx,0ffffffh + jnz trfin + inc esi + +trfin: + sub esi,scan ; esi = len +trfinval: +; here we have finised compare, and esi contain len of equal string + cmp esi,best_len ; if len > best_len, go newbestlen + ja short newbestlen +; now we restore edx, ecx and esi, for the big loop + mov esi,prev + mov ecx,limit + mov edx,window + jmp contloop3 + +newbestlen: + mov best_len,esi ; len become best_len + + mov match_start,eax ; save new position as match_start + cmp esi,nice_match ; if best_len >= nice_match, exit + jae exitloop + mov ecx,scan + mov edx,window ; restore edx=window + add ecx,esi + add esi,edx + + dec esi + mov windowlen,esi ; windowlen = window + best_len-1 + mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end + +; now we restore ecx and esi, for the big loop : + mov esi,prev + mov ecx,limit + jmp contloop3 + +exitloop: +; exit : s->match_start=match_start + mov ebx,match_start + mov ebp,str_s + mov ecx,best_len + mov dword ptr [ebp+dep_match_start],ebx + mov eax,dword ptr [ebp+dep_lookahead] + cmp ecx,eax + ja minexlo + mov eax,ecx +minexlo: +; return min(best_len,s->lookahead) + +; restore stack and register ebx,esi,edi,ebp + add esp,NbStackAdd + + pop ebx + pop esi + pop edi + pop ebp + ret +InfoAuthor: +; please don't remove this string ! +; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary! + db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah + + + +IFDEF NOUNDERLINE +longest_match_7fff endp +ELSE +_longest_match_7fff endp +ENDIF + + +IFDEF NOUNDERLINE +cpudetect32 proc near +ELSE +_cpudetect32 proc near +ENDIF + + + pushfd ; push original EFLAGS + pop eax ; get original EFLAGS + mov ecx, eax ; save original EFLAGS + xor eax, 40000h ; flip AC bit in EFLAGS + push eax ; save new EFLAGS value on stack + popfd ; replace current EFLAGS value + pushfd ; get new EFLAGS + pop eax ; store new EFLAGS in EAX + xor eax, ecx ; can’t toggle AC bit, processor=80386 + jz end_cpu_is_386 ; jump if 80386 processor + push ecx + popfd ; restore AC bit in EFLAGS first + + pushfd + pushfd + pop ecx + + mov eax, ecx ; get original EFLAGS + xor eax, 200000h ; flip ID bit in EFLAGS + push eax ; save new EFLAGS value on stack + popfd ; replace current EFLAGS value + pushfd ; get new EFLAGS + pop eax ; store new EFLAGS in EAX + popfd ; restore original EFLAGS + xor eax, ecx ; can’t toggle ID bit, + je is_old_486 ; processor=old + + mov eax,1 + db 0fh,0a2h ;CPUID + +exitcpudetect: + ret + +end_cpu_is_386: + mov eax,0300h + jmp exitcpudetect + +is_old_486: + mov eax,0400h + jmp exitcpudetect + +IFDEF NOUNDERLINE +cpudetect32 endp +ELSE +_cpudetect32 endp +ENDIF + +_TEXT ends +end diff --git a/drivers/lib/zlib/contrib/asm386/gvmat32c.c b/drivers/lib/zlib/contrib/asm386/gvmat32c.c new file mode 100644 index 0000000..d853bb7 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm386/gvmat32c.c @@ -0,0 +1,200 @@ +/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 + * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. + * File written by Gilles Vollant, by modifiying the longest_match + * from Jean-loup Gailly in deflate.c + * it prepare all parameters and call the assembly longest_match_gvasm + * longest_match execute standard C code is wmask != 0x7fff + * (assembly code is faster with a fixed wmask) + * + */ + +#include "deflate.h" + +#undef FAR +#include + +#ifdef ASMV +#define NIL 0 + +#define UNALIGNED_OK + + +/* if your C compiler don't add underline before function name, + define ADD_UNDERLINE_ASMFUNC */ +#ifdef ADD_UNDERLINE_ASMFUNC +#define longest_match_7fff _longest_match_7fff +#endif + + + +void match_init() +{ +} + +unsigned long cpudetect32(); + +uInt longest_match_c( + deflate_state *s, + IPos cur_match); /* current match */ + + +uInt longest_match_7fff( + deflate_state *s, + IPos cur_match); /* current match */ + +uInt longest_match( + deflate_state *s, + IPos cur_match) /* current match */ +{ + static uInt iIsPPro=2; + + if ((s->w_mask == 0x7fff) && (iIsPPro==0)) + return longest_match_7fff(s,cur_match); + + if (iIsPPro==2) + iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; + + return longest_match_c(s,cur_match); +} + + + +uInt longest_match_c(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#endif /* ASMV */ diff --git a/drivers/lib/zlib/contrib/asm386/mkgvmt32.bat b/drivers/lib/zlib/contrib/asm386/mkgvmt32.bat new file mode 100644 index 0000000..6c5ffd7 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm386/mkgvmt32.bat @@ -0,0 +1 @@ +c:\masm611\bin\ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm diff --git a/drivers/lib/zlib/contrib/asm386/zlibvc.def b/drivers/lib/zlib/contrib/asm386/zlibvc.def new file mode 100644 index 0000000..7e9d60d --- /dev/null +++ b/drivers/lib/zlib/contrib/asm386/zlibvc.def @@ -0,0 +1,74 @@ +LIBRARY "zlib" + +DESCRIPTION '"""zlib data compression library"""' + + +VERSION 1.11 + + +HEAPSIZE 1048576,8192 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 diff --git a/drivers/lib/zlib/contrib/asm386/zlibvc.dsp b/drivers/lib/zlib/contrib/asm386/zlibvc.dsp new file mode 100644 index 0000000..a70d4d4 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm386/zlibvc.dsp @@ -0,0 +1,651 @@ +# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=zlibvc - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc__" +# PROP BASE Intermediate_Dir "zlibvc__" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc__" +# PROP Intermediate_Dir "zlibvc__" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_0" +# PROP BASE Intermediate_Dir "zlibvc_0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_0" +# PROP Intermediate_Dir "zlibvc_0" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_1" +# PROP BASE Intermediate_Dir "zlibvc_1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_1" +# PROP Intermediate_Dir "zlibvc_1" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "zlibvc - Win32 Release" +# Name "zlibvc - Win32 Debug" +# Name "zlibvc - Win32 ReleaseAxp" +# Name "zlibvc - Win32 ReleaseWithoutAsm" +# Name "zlibvc - Win32 ReleaseWithoutCrtdll" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\adler32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ADLER=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\compress.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_COMPR=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\crc32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_CRC32=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\deflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_DEFLA=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gvmat32c.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gzio.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_GZIO_=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infblock.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFBL=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infcodes.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFCO=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inffast.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFFA=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFLA=\ + ".\infblock.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inftrees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFTR=\ + ".\inftrees.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFUT=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\trees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_TREES=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\uncompr.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_UNCOM=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\unzip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zlib.rc +# End Source File +# Begin Source File + +SOURCE=.\zlibvc.def +# End Source File +# Begin Source File + +SOURCE=.\zutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ZUTIL=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\deflate.h +# End Source File +# Begin Source File + +SOURCE=.\infblock.h +# End Source File +# Begin Source File + +SOURCE=.\infcodes.h +# End Source File +# Begin Source File + +SOURCE=.\inffast.h +# End Source File +# Begin Source File + +SOURCE=.\inftrees.h +# End Source File +# Begin Source File + +SOURCE=.\infutil.h +# End Source File +# Begin Source File + +SOURCE=.\zconf.h +# End Source File +# Begin Source File + +SOURCE=.\zlib.h +# End Source File +# Begin Source File + +SOURCE=.\zutil.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/drivers/lib/zlib/contrib/asm386/zlibvc.dsw b/drivers/lib/zlib/contrib/asm386/zlibvc.dsw new file mode 100644 index 0000000..493cd87 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm386/zlibvc.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/drivers/lib/zlib/contrib/asm586/README.586 b/drivers/lib/zlib/contrib/asm586/README.586 new file mode 100644 index 0000000..6bb78f3 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm586/README.586 @@ -0,0 +1,43 @@ +This is a patched version of zlib modified to use +Pentium-optimized assembly code in the deflation algorithm. The files +changed/added by this patch are: + +README.586 +match.S + +The effectiveness of these modifications is a bit marginal, as the the +program's bottleneck seems to be mostly L1-cache contention, for which +there is no real way to work around without rewriting the basic +algorithm. The speedup on average is around 5-10% (which is generally +less than the amount of variance between subsequent executions). +However, when used at level 9 compression, the cache contention can +drop enough for the assembly version to achieve 10-20% speedup (and +sometimes more, depending on the amount of overall redundancy in the +files). Even here, though, cache contention can still be the limiting +factor, depending on the nature of the program using the zlib library. +This may also mean that better improvements will be seen on a Pentium +with MMX, which suffers much less from L1-cache contention, but I have +not yet verified this. + +Note that this code has been tailored for the Pentium in particular, +and will not perform well on the Pentium Pro (due to the use of a +partial register in the inner loop). + +If you are using an assembler other than GNU as, you will have to +translate match.S to use your assembler's syntax. (Have fun.) + +Brian Raiter +breadbox@muppetlabs.com +April, 1998 + + +Added for zlib 1.1.3: + +The patches come from +http://www.muppetlabs.com/~breadbox/software/assembly.html + +To compile zlib with this asm file, copy match.S to the zlib directory +then do: + +CFLAGS="-O3 -DASMV" ./configure +make OBJA=match.o diff --git a/drivers/lib/zlib/contrib/asm586/match.S b/drivers/lib/zlib/contrib/asm586/match.S new file mode 100644 index 0000000..8f16140 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm586/match.S @@ -0,0 +1,354 @@ +/* match.s -- Pentium-optimized version of longest_match() + * Written for zlib 1.1.2 + * Copyright (C) 1998 Brian Raiter + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License. + */ + +#ifndef NO_UNDERLINE +#define match_init _match_init +#define longest_match _longest_match +#endif + +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ + +#define wmask 0 /* local copy of s->wmask */ +#define window 4 /* local copy of s->window */ +#define windowbestlen 8 /* s->window + bestlen */ +#define chainlenscanend 12 /* high word: current chain len */ + /* low word: last bytes sought */ +#define scanstart 16 /* first two bytes of string */ +#define scanalign 20 /* dword-misalignment of string */ +#define nicematch 24 /* a good enough match size */ +#define bestlen 28 /* size of best match so far */ +#define scan 32 /* ptr to string wanting match */ + +#define LocalVarsSize (36) +/* saved ebx 36 */ +/* saved edi 40 */ +/* saved esi 44 */ +/* saved ebp 48 */ +/* return address 52 */ +#define deflatestate 56 /* the function arguments */ +#define curmatch 60 + +/* Offsets for fields in the deflate_state structure. These numbers + * are calculated from the definition of deflate_state, with the + * assumption that the compiler will dword-align the fields. (Thus, + * changing the definition of deflate_state could easily cause this + * program to crash horribly, without so much as a warning at + * compile time. Sigh.) + */ +#define dsWSize 36 +#define dsWMask 44 +#define dsWindow 48 +#define dsPrev 56 +#define dsMatchLen 88 +#define dsPrevMatch 92 +#define dsStrStart 100 +#define dsMatchStart 104 +#define dsLookahead 108 +#define dsPrevLen 112 +#define dsMaxChainLen 116 +#define dsGoodMatch 132 +#define dsNiceMatch 136 + + +.file "match.S" + +.globl match_init, longest_match + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ + +longest_match: + +/* Save registers that the compiler may be using, and adjust %esp to */ +/* make room for our stack frame. */ + + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + subl $LocalVarsSize, %esp + +/* Retrieve the function arguments. %ecx will hold cur_match */ +/* throughout the entire function. %edx will hold the pointer to the */ +/* deflate_state structure during the function's setup (before */ +/* entering the main loop). */ + + movl deflatestate(%esp), %edx + movl curmatch(%esp), %ecx + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch(%edx), %eax + movl dsLookahead(%edx), %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, nicematch(%esp) + +/* register Bytef *scan = s->window + s->strstart; */ + + movl dsWindow(%edx), %esi + movl %esi, window(%esp) + movl dsStrStart(%edx), %ebp + lea (%esi,%ebp), %edi + movl %edi, scan(%esp) + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + movl %edi, %eax + negl %eax + andl $3, %eax + movl %eax, scanalign(%esp) + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize(%edx), %eax + subl $MIN_LOOKAHEAD, %eax + subl %eax, %ebp + jg LimitPositive + xorl %ebp, %ebp +LimitPositive: + +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen(%edx), %eax + movl dsGoodMatch(%edx), %ebx + cmpl %ebx, %eax + movl dsMaxChainLen(%edx), %ebx + jl LastMatchGood + shrl $2, %ebx +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the scanend */ +/* scanend value, which it will always accompany. */ + + decl %ebx + shll $16, %ebx + +/* int best_len = s->prev_length; */ + + movl dsPrevLen(%edx), %eax + movl %eax, bestlen(%esp) + +/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ + + addl %eax, %esi + movl %esi, windowbestlen(%esp) + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ + + movw (%edi), %bx + movw %bx, scanstart(%esp) + movw -1(%edi,%eax), %bx + movl %ebx, chainlenscanend(%esp) + +/* Posf *prev = s->prev; */ +/* uInt wmask = s->w_mask; */ + + movl dsPrev(%edx), %edi + movl dsWMask(%edx), %edx + mov %edx, wmask(%esp) + +/* Jump into the main loop. */ + + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + * + * Within this loop: + * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) + * %ecx = curmatch + * %edx = curmatch & wmask + * %esi = windowbestlen - i.e., (window + bestlen) + * %edi = prev + * %ebp = limit + * + * Two optimization notes on the choice of instructions: + * + * The first instruction uses a 16-bit address, which costs an extra, + * unpairable cycle. This is cheaper than doing a 32-bit access and + * zeroing the high word, due to the 3-cycle misalignment penalty which + * would occur half the time. This also turns out to be cheaper than + * doing two separate 8-bit accesses, as the memory is so rarely in the + * L1 cache. + * + * The window buffer, however, apparently spends a lot of time in the + * cache, and so it is faster to retrieve the word at the end of the + * match string with two 8-bit loads. The instructions that test the + * word at the beginning of the match string, however, are executed + * much less frequently, and there it was cheaper to use 16-bit + * instructions, which avoided the necessity of saving off and + * subsequently reloading one of the other registers. + */ +LookupLoop: + /* 1 U & V */ + movw (%edi,%edx,2), %cx /* 2 U pipe */ + movl wmask(%esp), %edx /* 2 V pipe */ + cmpl %ebp, %ecx /* 3 U pipe */ + jbe LeaveNow /* 3 V pipe */ + subl $0x00010000, %ebx /* 4 U pipe */ + js LeaveNow /* 4 V pipe */ +LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ + andl %ecx, %edx /* 5 V pipe */ + cmpb %bl, %al /* 6 U pipe */ + jnz LookupLoop /* 6 V pipe */ + movb (%esi,%ecx), %ah + cmpb %bh, %ah + jnz LookupLoop + movl window(%esp), %eax + movw (%eax,%ecx), %ax + cmpw scanstart(%esp), %ax + jnz LookupLoop + +/* Store the current value of chainlen. */ + + movl %ebx, chainlenscanend(%esp) + +/* Point %edi to the string under scrutiny, and %esi to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + movl window(%esp), %esi + movl scan(%esp), %edi + addl %ecx, %esi + movl scanalign(%esp), %eax + movl $(-MAX_MATCH_8), %edx + lea MAX_MATCH_8(%edi,%eax), %edi + lea MAX_MATCH_8(%esi,%eax), %esi + +/* Test the strings for equality, 8 bytes at a time. At the end, + * adjust %edx so that it is offset to the exact byte that mismatched. + * + * We already know at this point that the first three bytes of the + * strings match each other, and they can be safely passed over before + * starting the compare loop. So what this code does is skip over 0-3 + * bytes, as much as necessary in order to dword-align the %edi + * pointer. (%esi will still be misaligned three times out of four.) + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance. + */ +LoopCmps: + movl (%esi,%edx), %eax + movl (%edi,%edx), %ebx + xorl %ebx, %eax + jnz LeaveLoopCmps + movl 4(%esi,%edx), %eax + movl 4(%edi,%edx), %ebx + xorl %ebx, %eax + jnz LeaveLoopCmps4 + addl $8, %edx + jnz LoopCmps + jmp LenMaximum +LeaveLoopCmps4: addl $4, %edx +LeaveLoopCmps: testl $0x0000FFFF, %eax + jnz LenLower + addl $2, %edx + shrl $16, %eax +LenLower: subb $1, %al + adcl $0, %edx + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%edi,%edx), %eax + movl scan(%esp), %edi + subl %edi, %eax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + cmpl %ebx, %eax + jg LongerMatch + movl chainlenscanend(%esp), %ebx + movl windowbestlen(%esp), %esi + movl dsPrev(%edx), %edi + movl wmask(%esp), %edx + andl %ecx, %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: movl nicematch(%esp), %ebx + movl %eax, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + cmpl %ebx, %eax + jge LeaveNow + movl window(%esp), %esi + addl %eax, %esi + movl %esi, windowbestlen(%esp) + movl chainlenscanend(%esp), %ebx + movw -1(%edi,%eax), %bx + movl dsPrev(%edx), %edi + movl %ebx, chainlenscanend(%esp) + movl wmask(%esp), %edx + andl %ecx, %edx + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: movl deflatestate(%esp), %edx + movl $MAX_MATCH, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + movl dsLookahead(%edx), %eax + cmpl %eax, %ebx + jg LookaheadRet + movl %ebx, %eax +LookaheadRet: + +/* Restore the stack and return from whence we came. */ + + addl $LocalVarsSize, %esp + popl %ebx + popl %esi + popl %edi + popl %ebp +match_init: ret diff --git a/drivers/lib/zlib/contrib/asm686/README.686 b/drivers/lib/zlib/contrib/asm686/README.686 new file mode 100644 index 0000000..a593f23 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm686/README.686 @@ -0,0 +1,34 @@ +This is a patched version of zlib, modified to use +Pentium-Pro-optimized assembly code in the deflation algorithm. The +files changed/added by this patch are: + +README.686 +match.S + +The speedup that this patch provides varies, depending on whether the +compiler used to build the original version of zlib falls afoul of the +PPro's speed traps. My own tests show a speedup of around 10-20% at +the default compression level, and 20-30% using -9, against a version +compiled using gcc 2.7.2.3. Your mileage may vary. + +Note that this code has been tailored for the PPro/PII in particular, +and will not perform particuarly well on a Pentium. + +If you are using an assembler other than GNU as, you will have to +translate match.S to use your assembler's syntax. (Have fun.) + +Brian Raiter +breadbox@muppetlabs.com +April, 1998 + + +Added for zlib 1.1.3: + +The patches come from +http://www.muppetlabs.com/~breadbox/software/assembly.html + +To compile zlib with this asm file, copy match.S to the zlib directory +then do: + +CFLAGS="-O3 -DASMV" ./configure +make OBJA=match.o diff --git a/drivers/lib/zlib/contrib/asm686/match.S b/drivers/lib/zlib/contrib/asm686/match.S new file mode 100644 index 0000000..8e86c33 --- /dev/null +++ b/drivers/lib/zlib/contrib/asm686/match.S @@ -0,0 +1,327 @@ +/* match.s -- Pentium-Pro-optimized version of longest_match() + * Written for zlib 1.1.2 + * Copyright (C) 1998 Brian Raiter + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License. + */ + +#ifndef NO_UNDERLINE +#define match_init _match_init +#define longest_match _longest_match +#endif + +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ + +#define chainlenwmask 0 /* high word: current chain len */ + /* low word: s->wmask */ +#define window 4 /* local copy of s->window */ +#define windowbestlen 8 /* s->window + bestlen */ +#define scanstart 16 /* first two bytes of string */ +#define scanend 12 /* last two bytes of string */ +#define scanalign 20 /* dword-misalignment of string */ +#define nicematch 24 /* a good enough match size */ +#define bestlen 28 /* size of best match so far */ +#define scan 32 /* ptr to string wanting match */ + +#define LocalVarsSize (36) +/* saved ebx 36 */ +/* saved edi 40 */ +/* saved esi 44 */ +/* saved ebp 48 */ +/* return address 52 */ +#define deflatestate 56 /* the function arguments */ +#define curmatch 60 + +/* Offsets for fields in the deflate_state structure. These numbers + * are calculated from the definition of deflate_state, with the + * assumption that the compiler will dword-align the fields. (Thus, + * changing the definition of deflate_state could easily cause this + * program to crash horribly, without so much as a warning at + * compile time. Sigh.) + */ +#define dsWSize 36 +#define dsWMask 44 +#define dsWindow 48 +#define dsPrev 56 +#define dsMatchLen 88 +#define dsPrevMatch 92 +#define dsStrStart 100 +#define dsMatchStart 104 +#define dsLookahead 108 +#define dsPrevLen 112 +#define dsMaxChainLen 116 +#define dsGoodMatch 132 +#define dsNiceMatch 136 + + +.file "match.S" + +.globl match_init, longest_match + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ + +longest_match: + +/* Save registers that the compiler may be using, and adjust %esp to */ +/* make room for our stack frame. */ + + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + subl $LocalVarsSize, %esp + +/* Retrieve the function arguments. %ecx will hold cur_match */ +/* throughout the entire function. %edx will hold the pointer to the */ +/* deflate_state structure during the function's setup (before */ +/* entering the main loop). */ + + movl deflatestate(%esp), %edx + movl curmatch(%esp), %ecx + +/* uInt wmask = s->w_mask; */ +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen(%edx), %eax + movl dsGoodMatch(%edx), %ebx + cmpl %ebx, %eax + movl dsWMask(%edx), %eax + movl dsMaxChainLen(%edx), %ebx + jl LastMatchGood + shrl $2, %ebx +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the wmask */ +/* value, which it will always accompany. */ + + decl %ebx + shll $16, %ebx + orl %eax, %ebx + movl %ebx, chainlenwmask(%esp) + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch(%edx), %eax + movl dsLookahead(%edx), %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, nicematch(%esp) + +/* register Bytef *scan = s->window + s->strstart; */ + + movl dsWindow(%edx), %esi + movl %esi, window(%esp) + movl dsStrStart(%edx), %ebp + lea (%esi,%ebp), %edi + movl %edi, scan(%esp) + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + movl %edi, %eax + negl %eax + andl $3, %eax + movl %eax, scanalign(%esp) + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize(%edx), %eax + subl $MIN_LOOKAHEAD, %eax + subl %eax, %ebp + jg LimitPositive + xorl %ebp, %ebp +LimitPositive: + +/* int best_len = s->prev_length; */ + + movl dsPrevLen(%edx), %eax + movl %eax, bestlen(%esp) + +/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ + + addl %eax, %esi + movl %esi, windowbestlen(%esp) + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ +/* Posf *prev = s->prev; */ + + movzwl (%edi), %ebx + movl %ebx, scanstart(%esp) + movzwl -1(%edi,%eax), %ebx + movl %ebx, scanend(%esp) + movl dsPrev(%edx), %edi + +/* Jump into the main loop. */ + + movl chainlenwmask(%esp), %edx + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + * + * Within this loop: + * %ebx = scanend + * %ecx = curmatch + * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) + * %esi = windowbestlen - i.e., (window + bestlen) + * %edi = prev + * %ebp = limit + */ +LookupLoop: + andl %edx, %ecx + movzwl (%edi,%ecx,2), %ecx + cmpl %ebp, %ecx + jbe LeaveNow + subl $0x00010000, %edx + js LeaveNow +LoopEntry: movzwl -1(%esi,%ecx), %eax + cmpl %ebx, %eax + jnz LookupLoop + movl window(%esp), %eax + movzwl (%eax,%ecx), %eax + cmpl scanstart(%esp), %eax + jnz LookupLoop + +/* Store the current value of chainlen. */ + + movl %edx, chainlenwmask(%esp) + +/* Point %edi to the string under scrutiny, and %esi to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + movl window(%esp), %esi + movl scan(%esp), %edi + addl %ecx, %esi + movl scanalign(%esp), %eax + movl $(-MAX_MATCH_8), %edx + lea MAX_MATCH_8(%edi,%eax), %edi + lea MAX_MATCH_8(%esi,%eax), %esi + +/* Test the strings for equality, 8 bytes at a time. At the end, + * adjust %edx so that it is offset to the exact byte that mismatched. + * + * We already know at this point that the first three bytes of the + * strings match each other, and they can be safely passed over before + * starting the compare loop. So what this code does is skip over 0-3 + * bytes, as much as necessary in order to dword-align the %edi + * pointer. (%esi will still be misaligned three times out of four.) + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance. + */ +LoopCmps: + movl (%esi,%edx), %eax + xorl (%edi,%edx), %eax + jnz LeaveLoopCmps + movl 4(%esi,%edx), %eax + xorl 4(%edi,%edx), %eax + jnz LeaveLoopCmps4 + addl $8, %edx + jnz LoopCmps + jmp LenMaximum +LeaveLoopCmps4: addl $4, %edx +LeaveLoopCmps: testl $0x0000FFFF, %eax + jnz LenLower + addl $2, %edx + shrl $16, %eax +LenLower: subb $1, %al + adcl $0, %edx + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%edi,%edx), %eax + movl scan(%esp), %edi + subl %edi, %eax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + cmpl %ebx, %eax + jg LongerMatch + movl windowbestlen(%esp), %esi + movl dsPrev(%edx), %edi + movl scanend(%esp), %ebx + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: movl nicematch(%esp), %ebx + movl %eax, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + cmpl %ebx, %eax + jge LeaveNow + movl window(%esp), %esi + addl %eax, %esi + movl %esi, windowbestlen(%esp) + movzwl -1(%edi,%eax), %ebx + movl dsPrev(%edx), %edi + movl %ebx, scanend(%esp) + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: movl deflatestate(%esp), %edx + movl $MAX_MATCH, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + movl dsLookahead(%edx), %eax + cmpl %eax, %ebx + jg LookaheadRet + movl %ebx, %eax +LookaheadRet: + +/* Restore the stack and return from whence we came. */ + + addl $LocalVarsSize, %esp + popl %ebx + popl %esi + popl %edi + popl %ebp +match_init: ret diff --git a/drivers/lib/zlib/contrib/delphi/zlib.mak b/drivers/lib/zlib/contrib/delphi/zlib.mak new file mode 100644 index 0000000..ba557e2 --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi/zlib.mak @@ -0,0 +1,36 @@ +# Makefile for zlib32bd.lib +# ------------- Borland C++ 4.5 ------------- + +# The (32-bit) zlib32bd.lib made with this makefile is intended for use +# in making the (32-bit) DLL, png32bd.dll. It uses the "stdcall" calling +# convention. + +CFLAGS= -ps -O2 -C -K -N- -k- -d -3 -r- -w-par -w-aus -WDE +CC=f:\bc45\bin\bcc32 +LIBFLAGS= /C +LIB=f:\bc45\bin\tlib +ZLIB=zlib32bd.lib + +.autodepend +.c.obj: + $(CC) -c $(CFLAGS) $< + +OBJ1=adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj +OBJ2=infcodes.obj inflate.obj inftrees.obj infutil.obj inffast.obj +OBJ3=trees.obj uncompr.obj zutil.obj +pOBJ1=+adler32.obj+compress.obj+crc32.obj+deflate.obj+gzio.obj+infblock.obj +pOBJ2=+infcodes.obj+inflate.obj+inftrees.obj+infutil.obj+inffast.obj +pOBJ3=+trees.obj+uncompr.obj+zutil.obj + +all: $(ZLIB) + +$(ZLIB): $(OBJ1) $(OBJ2) $(OBJ3) + @if exist $@ del $@ + $(LIB) @&&| +$@ $(LIBFLAGS) & +$(pOBJ1) & +$(pOBJ2) & +$(pOBJ3) +| + +# End of makefile for zlib32bd.lib diff --git a/drivers/lib/zlib/contrib/delphi/zlibdef.pas b/drivers/lib/zlib/contrib/delphi/zlibdef.pas new file mode 100644 index 0000000..4f96b7d --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi/zlibdef.pas @@ -0,0 +1,169 @@ +unit zlibdef; + +interface + +uses + Windows; + +const + ZLIB_VERSION = '1.1.3'; + +type + voidpf = Pointer; + int = Integer; + uInt = Cardinal; + pBytef = PChar; + uLong = Cardinal; + + alloc_func = function(opaque: voidpf; items, size: uInt): voidpf; + stdcall; + free_func = procedure(opaque, address: voidpf); + stdcall; + + internal_state = Pointer; + + z_streamp = ^z_stream; + z_stream = packed record + next_in: pBytef; // next input byte + avail_in: uInt; // number of bytes available at next_in + total_in: uLong; // total nb of input bytes read so far + + next_out: pBytef; // next output byte should be put there + avail_out: uInt; // remaining free space at next_out + total_out: uLong; // total nb of bytes output so far + + msg: PChar; // last error message, NULL if no error + state: internal_state; // not visible by applications + + zalloc: alloc_func; // used to allocate the internal state + zfree: free_func; // used to free the internal state + opaque: voidpf; // private data object passed to zalloc and zfree + + data_type: int; // best guess about the data type: ascii or binary + adler: uLong; // adler32 value of the uncompressed data + reserved: uLong; // reserved for future use + end; + +const + Z_NO_FLUSH = 0; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + + Z_OK = 0; + Z_STREAM_END = 1; + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = -1; + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + + MAX_MEM_LEVEL = 9; + +function adler32(adler: uLong; const buf: pBytef; len: uInt): uLong; + stdcall; +function crc32(crc: uLong; const buf: pBytef; len: uInt): uLong; + stdcall; +function deflate(strm: z_streamp; flush: int): int; + stdcall; +function deflateCopy(dest, source: z_streamp): int; + stdcall; +function deflateEnd(strm: z_streamp): int; + stdcall; +function deflateInit2_(strm: z_streamp; level, method, + windowBits, memLevel, strategy: int; + const version: PChar; stream_size: int): int; + stdcall; +function deflateInit_(strm: z_streamp; level: int; + const version: PChar; stream_size: int): int; + stdcall; +function deflateParams(strm: z_streamp; level, strategy: int): int; + stdcall; +function deflateReset(strm: z_streamp): int; + stdcall; +function deflateSetDictionary(strm: z_streamp; + const dictionary: pBytef; + dictLength: uInt): int; + stdcall; +function inflate(strm: z_streamp; flush: int): int; + stdcall; +function inflateEnd(strm: z_streamp): int; + stdcall; +function inflateInit2_(strm: z_streamp; windowBits: int; + const version: PChar; stream_size: int): int; + stdcall; +function inflateInit_(strm: z_streamp; const version: PChar; + stream_size: int): int; + stdcall; +function inflateReset(strm: z_streamp): int; + stdcall; +function inflateSetDictionary(strm: z_streamp; + const dictionary: pBytef; + dictLength: uInt): int; + stdcall; +function inflateSync(strm: z_streamp): int; + stdcall; + +function deflateInit(strm: z_streamp; level: int): int; +function deflateInit2(strm: z_streamp; level, method, windowBits, + memLevel, strategy: int): int; +function inflateInit(strm: z_streamp): int; +function inflateInit2(strm: z_streamp; windowBits: int): int; + +implementation + +function deflateInit(strm: z_streamp; level: int): int; +begin + Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); +end; + +function deflateInit2(strm: z_streamp; level, method, windowBits, + memLevel, strategy: int): int; +begin + Result := deflateInit2_(strm, level, method, windowBits, memLevel, + strategy, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit(strm: z_streamp): int; +begin + Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit2(strm: z_streamp; windowBits: int): int; +begin + Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, + sizeof(z_stream)); +end; + +const + zlibDLL = 'png32bd.dll'; + +function adler32; external zlibDLL; +function crc32; external zlibDLL; +function deflate; external zlibDLL; +function deflateCopy; external zlibDLL; +function deflateEnd; external zlibDLL; +function deflateInit2_; external zlibDLL; +function deflateInit_; external zlibDLL; +function deflateParams; external zlibDLL; +function deflateReset; external zlibDLL; +function deflateSetDictionary; external zlibDLL; +function inflate; external zlibDLL; +function inflateEnd; external zlibDLL; +function inflateInit2_; external zlibDLL; +function inflateInit_; external zlibDLL; +function inflateReset; external zlibDLL; +function inflateSetDictionary; external zlibDLL; +function inflateSync; external zlibDLL; + +end. diff --git a/drivers/lib/zlib/contrib/delphi2/d_zlib.bpr b/drivers/lib/zlib/contrib/delphi2/d_zlib.bpr new file mode 100644 index 0000000..78bb254 --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/d_zlib.bpr @@ -0,0 +1,224 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = d_zlib.lib +OBJFILES = d_zlib.obj adler32.obj deflate.obj infblock.obj infcodes.obj inffast.obj \ + inflate.obj inftrees.obj infutil.obj trees.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +DEFFILE = +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \ + dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -O2 -Ve -d -k- -vi +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -ff -pr -5 +PFLAGS = -U;$(DEBUGLIBPATH) -I$(BCB)\include;$(BCB)\include\vcl -H -W -$I- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn +LFLAGS = +IFLAGS = -g -Gn +# --------------------------------------------------------------------------- +ALLOBJ = c0w32.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include +Item1=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + + --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = TLib +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include;$(BCB)\include\vcl +Item1=$(BCB)\include + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) $(IFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/drivers/lib/zlib/contrib/delphi2/d_zlib.cpp b/drivers/lib/zlib/contrib/delphi2/d_zlib.cpp new file mode 100644 index 0000000..f5dea59 --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/d_zlib.cpp @@ -0,0 +1,17 @@ +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEUNIT("adler32.c"); +USEUNIT("deflate.c"); +USEUNIT("infblock.c"); +USEUNIT("infcodes.c"); +USEUNIT("inffast.c"); +USEUNIT("inflate.c"); +USEUNIT("inftrees.c"); +USEUNIT("infutil.c"); +USEUNIT("trees.c"); +//--------------------------------------------------------------------------- +#define Library + +// To add a file to the library use the Project menu 'Add to Project'. + diff --git a/drivers/lib/zlib/contrib/delphi2/readme.txt b/drivers/lib/zlib/contrib/delphi2/readme.txt new file mode 100644 index 0000000..cbd3162 --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/readme.txt @@ -0,0 +1,17 @@ +These are files used to compile zlib under Borland C++ Builder 3. + +zlib.bpg is the main project group that can be loaded in the BCB IDE and +loads all other *.bpr projects + +zlib.bpr is a project used to create a static zlib.lib library with C calling +convention for functions. + +zlib32.bpr creates a zlib32.dll dynamic link library with Windows standard +calling convention. + +d_zlib.bpr creates a set of .obj files with register calling convention. +These files are used by zlib.pas to create a Delphi unit containing zlib. +The d_zlib.lib file generated isn't useful and can be deleted. + +zlib.cpp, zlib32.cpp and d_zlib.cpp are used by the above projects. + diff --git a/drivers/lib/zlib/contrib/delphi2/zlib.bpg b/drivers/lib/zlib/contrib/delphi2/zlib.bpg new file mode 100644 index 0000000..b6c9acd --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/zlib.bpg @@ -0,0 +1,26 @@ +#------------------------------------------------------------------------------ +VERSION = BWS.01 +#------------------------------------------------------------------------------ +!ifndef ROOT +ROOT = $(MAKEDIR)\.. +!endif +#------------------------------------------------------------------------------ +MAKE = $(ROOT)\bin\make.exe -$(MAKEFLAGS) -f$** +DCC = $(ROOT)\bin\dcc32.exe $** +BRCC = $(ROOT)\bin\brcc32.exe $** +#------------------------------------------------------------------------------ +PROJECTS = zlib zlib32 d_zlib +#------------------------------------------------------------------------------ +default: $(PROJECTS) +#------------------------------------------------------------------------------ + +zlib: zlib.bpr + $(MAKE) + +zlib32: zlib32.bpr + $(MAKE) + +d_zlib: d_zlib.bpr + $(MAKE) + + diff --git a/drivers/lib/zlib/contrib/delphi2/zlib.bpr b/drivers/lib/zlib/contrib/delphi2/zlib.bpr new file mode 100644 index 0000000..cf3945b --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/zlib.bpr @@ -0,0 +1,225 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = zlib.lib +OBJFILES = zlib.obj adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj \ + infcodes.obj inffast.obj inflate.obj inftrees.obj infutil.obj trees.obj \ + uncompr.obj zutil.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = VCL35.lib +SPARELIBS = VCL35.lib +DEFFILE = +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \ + dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -O2 -Ve -d -k- -vi +CFLAG2 = -I$(BCB)\include;$(BCB)\include\vcl -H=$(BCB)\lib\vcl35.csm +CFLAG3 = -ff -5 +PFLAGS = -U;$(DEBUGLIBPATH) -I$(BCB)\include;$(BCB)\include\vcl -H -W -$I- -v -JPHN -M +RFLAGS = -i$(BCB)\include;$(BCB)\include\vcl +AFLAGS = /i$(BCB)\include /i$(BCB)\include\vcl /mx /w2 /zn +LFLAGS = +IFLAGS = -g -Gn +# --------------------------------------------------------------------------- +ALLOBJ = c0w32.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) $(LIBRARIES) import32.lib cp32mt.lib +# --------------------------------------------------------------------------- +!!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include +Item1=$(BCB)\include;$(BCB)\include\vcl + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + + --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = TLib +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=0 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription= +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=2 +Item0=$(BCB)\include;$(BCB)\include\vcl +Item1=$(BCB)\include + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib\obj;$(BCB)\lib + +[HistoryLists\hlDebugSourcePath] +Count=1 +Item0=$(BCB)\source\vcl + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) $(IFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/drivers/lib/zlib/contrib/delphi2/zlib.cpp b/drivers/lib/zlib/contrib/delphi2/zlib.cpp new file mode 100644 index 0000000..bf6953b --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/zlib.cpp @@ -0,0 +1,22 @@ +#include +#pragma hdrstop +//--------------------------------------------------------------------------- +USEUNIT("adler32.c"); +USEUNIT("compress.c"); +USEUNIT("crc32.c"); +USEUNIT("deflate.c"); +USEUNIT("gzio.c"); +USEUNIT("infblock.c"); +USEUNIT("infcodes.c"); +USEUNIT("inffast.c"); +USEUNIT("inflate.c"); +USEUNIT("inftrees.c"); +USEUNIT("infutil.c"); +USEUNIT("trees.c"); +USEUNIT("uncompr.c"); +USEUNIT("zutil.c"); +//--------------------------------------------------------------------------- +#define Library + +// To add a file to the library use the Project menu 'Add to Project'. + diff --git a/drivers/lib/zlib/contrib/delphi2/zlib.pas b/drivers/lib/zlib/contrib/delphi2/zlib.pas new file mode 100644 index 0000000..10ae4ca --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/zlib.pas @@ -0,0 +1,534 @@ +{*******************************************************} +{ } +{ Delphi Supplemental Components } +{ ZLIB Data Compression Interface Unit } +{ } +{ Copyright (c) 1997 Borland International } +{ } +{*******************************************************} + +{ Modified for zlib 1.1.3 by Davide Moretti Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, 256); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := 256; + end; + finally + CCheck(deflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + + +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; + BufInc: Integer; +begin + FillChar(strm, sizeof(strm), 0); + BufInc := (InBytes + 255) and not 255; + if OutEstimate = 0 then + OutBytes := BufInc + else + OutBytes := OutEstimate; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, BufInc); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := BufInc; + end; + finally + DCheck(inflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + + +// TCustomZlibStream + +constructor TCustomZLibStream.Create(Strm: TStream); +begin + inherited Create; + FStrm := Strm; + FStrmPos := Strm.Position; +end; + +procedure TCustomZLibStream.Progress(Sender: TObject); +begin + if Assigned(FOnProgress) then FOnProgress(Sender); +end; + + +// TCompressionStream + +constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; + Dest: TStream); +const + Levels: array [TCompressionLevel] of ShortInt = + (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); +begin + inherited Create(Dest); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); +end; + +destructor TCompressionStream.Destroy; +begin + FZRec.next_in := nil; + FZRec.avail_in := 0; + try + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) + and (FZRec.avail_out = 0) do + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + end; + if FZRec.avail_out < sizeof(FBuffer) then + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); + finally + deflateEnd(FZRec); + end; + inherited Destroy; +end; + +function TCompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + raise ECompressionError.Create('Invalid stream operation'); +end; + +function TCompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + FZRec.next_in := @Buffer; + FZRec.avail_in := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_in > 0) do + begin + CCheck(deflate(FZRec, 0)); + if FZRec.avail_out = 0 then + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + FStrmPos := FStrm.Position; + Progress(Self); + end; + end; + Result := Count; +end; + +function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +begin + if (Offset = 0) and (Origin = soFromCurrent) then + Result := FZRec.total_in + else + raise ECompressionError.Create('Invalid stream operation'); +end; + +function TCompressionStream.GetCompressionRate: Single; +begin + if FZRec.total_in = 0 then + Result := 0 + else + Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; +end; + + +// TDecompressionStream + +constructor TDecompressionStream.Create(Source: TStream); +begin + inherited Create(Source); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); +end; + +destructor TDecompressionStream.Destroy; +begin + inflateEnd(FZRec); + inherited Destroy; +end; + +function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + FZRec.next_out := @Buffer; + FZRec.avail_out := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_out > 0) do + begin + if FZRec.avail_in = 0 then + begin + FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); + if FZRec.avail_in = 0 then + begin + Result := Count - FZRec.avail_out; + Exit; + end; + FZRec.next_in := FBuffer; + FStrmPos := FStrm.Position; + Progress(Self); + end; + DCheck(inflate(FZRec, 0)); + end; + Result := Count; +end; + +function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + raise EDecompressionError.Create('Invalid stream operation'); +end; + +function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +var + I: Integer; + Buf: array [0..4095] of Char; +begin + if (Offset = 0) and (Origin = soFromBeginning) then + begin + DCheck(inflateReset(FZRec)); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + FStrm.Position := 0; + FStrmPos := 0; + end + else if ( (Offset >= 0) and (Origin = soFromCurrent)) or + ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then + begin + if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); + if Offset > 0 then + begin + for I := 1 to Offset div sizeof(Buf) do + ReadBuffer(Buf, sizeof(Buf)); + ReadBuffer(Buf, Offset mod sizeof(Buf)); + end; + end + else + raise EDecompressionError.Create('Invalid stream operation'); + Result := FZRec.total_out; +end; + +end. diff --git a/drivers/lib/zlib/contrib/delphi2/zlib32.bpr b/drivers/lib/zlib/contrib/delphi2/zlib32.bpr new file mode 100644 index 0000000..cabcec4 --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/zlib32.bpr @@ -0,0 +1,174 @@ +# --------------------------------------------------------------------------- +!if !$d(BCB) +BCB = $(MAKEDIR)\.. +!endif + +# --------------------------------------------------------------------------- +# IDE SECTION +# --------------------------------------------------------------------------- +# The following section of the project makefile is managed by the BCB IDE. +# It is recommended to use the IDE to change any of the values in this +# section. +# --------------------------------------------------------------------------- + +VERSION = BCB.03 +# --------------------------------------------------------------------------- +PROJECT = zlib32.dll +OBJFILES = zlib32.obj adler32.obj compress.obj crc32.obj deflate.obj gzio.obj infblock.obj \ + infcodes.obj inffast.obj inflate.obj inftrees.obj infutil.obj trees.obj \ + uncompr.obj zutil.obj +RESFILES = +RESDEPEN = $(RESFILES) +LIBFILES = +LIBRARIES = +SPARELIBS = +DEFFILE = +PACKAGES = VCLX35.bpi VCL35.bpi VCLDB35.bpi VCLDBX35.bpi ibsmp35.bpi bcbsmp35.bpi \ + dclocx35.bpi QRPT35.bpi TEEUI35.bpi TEEDB35.bpi TEE35.bpi DSS35.bpi \ + NMFAST35.bpi INETDB35.bpi INET35.bpi VCLMID35.bpi +# --------------------------------------------------------------------------- +PATHCPP = .; +PATHASM = .; +PATHPAS = .; +PATHRC = .; +DEBUGLIBPATH = $(BCB)\lib\debug +RELEASELIBPATH = $(BCB)\lib\release +# --------------------------------------------------------------------------- +CFLAG1 = -WD -O2 -Ve -d -k- -vi -c -tWD +CFLAG2 = -D_NO_VCL;ZLIB_DLL -I$(BCB)\include +CFLAG3 = -ff -5 +PFLAGS = -D_NO_VCL;ZLIB_DLL -U$(BCB)\lib;$(RELEASELIBPATH) -I$(BCB)\include -$I- -v \ + -JPHN -M +RFLAGS = -D_NO_VCL;ZLIB_DLL -i$(BCB)\include +AFLAGS = /i$(BCB)\include /d_NO_VCL /dZLIB_DLL /mx /w2 /zn +LFLAGS = -L$(BCB)\lib;$(RELEASELIBPATH) -aa -Tpd -x -Gi +IFLAGS = -Gn -g +# --------------------------------------------------------------------------- +ALLOBJ = c0d32.obj $(OBJFILES) +ALLRES = $(RESFILES) +ALLLIB = $(LIBFILES) import32.lib cw32mt.lib +# --------------------------------------------------------------------------- +!ifdef IDEOPTIONS + +[Version Info] +IncludeVerInfo=0 +AutoIncBuild=0 +MajorVer=1 +MinorVer=0 +Release=0 +Build=0 +Debug=0 +PreRelease=0 +Special=0 +Private=0 +DLL=1 +Locale=1040 +CodePage=1252 + +[Version Info Keys] +CompanyName= +FileDescription=DLL (GUI) +FileVersion=1.0.0.0 +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion=1.0.0.0 +Comments= + +[HistoryLists\hlIncludePath] +Count=1 +Item0=$(BCB)\include + +[HistoryLists\hlLibraryPath] +Count=1 +Item0=$(BCB)\lib + +[HistoryLists\hlConditionals] +Count=1 +Item0=_NO_VCL;ZLIB_DLL + +[Debugging] +DebugSourceDirs= + +[Parameters] +RunParams= +HostApplication= + +!endif + +# --------------------------------------------------------------------------- +# MAKE SECTION +# --------------------------------------------------------------------------- +# This section of the project file is not used by the BCB IDE. It is for +# the benefit of building from the command-line using the MAKE utility. +# --------------------------------------------------------------------------- + +.autodepend +# --------------------------------------------------------------------------- +!if !$d(BCC32) +BCC32 = bcc32 +!endif + +!if !$d(DCC32) +DCC32 = dcc32 +!endif + +!if !$d(TASM32) +TASM32 = tasm32 +!endif + +!if !$d(LINKER) +LINKER = ilink32 +!endif + +!if !$d(BRCC32) +BRCC32 = brcc32 +!endif +# --------------------------------------------------------------------------- +!if $d(PATHCPP) +.PATH.CPP = $(PATHCPP) +.PATH.C = $(PATHCPP) +!endif + +!if $d(PATHPAS) +.PATH.PAS = $(PATHPAS) +!endif + +!if $d(PATHASM) +.PATH.ASM = $(PATHASM) +!endif + +!if $d(PATHRC) +.PATH.RC = $(PATHRC) +!endif +# --------------------------------------------------------------------------- +$(PROJECT): $(OBJFILES) $(RESDEPEN) $(DEFFILE) + $(BCB)\BIN\$(LINKER) @&&! + $(LFLAGS) $(IFLAGS) + + $(ALLOBJ), + + $(PROJECT),, + + $(ALLLIB), + + $(DEFFILE), + + $(ALLRES) +! +# --------------------------------------------------------------------------- +.pas.hpp: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.pas.obj: + $(BCB)\BIN\$(DCC32) $(PFLAGS) {$< } + +.cpp.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.c.obj: + $(BCB)\BIN\$(BCC32) $(CFLAG1) $(CFLAG2) $(CFLAG3) -n$(@D) {$< } + +.asm.obj: + $(BCB)\BIN\$(TASM32) $(AFLAGS) $<, $@ + +.rc.res: + $(BCB)\BIN\$(BRCC32) $(RFLAGS) -fo$@ $< +# --------------------------------------------------------------------------- diff --git a/drivers/lib/zlib/contrib/delphi2/zlib32.cpp b/drivers/lib/zlib/contrib/delphi2/zlib32.cpp new file mode 100644 index 0000000..7372f6b --- /dev/null +++ b/drivers/lib/zlib/contrib/delphi2/zlib32.cpp @@ -0,0 +1,42 @@ + +#include +#pragma hdrstop +#include + + +//--------------------------------------------------------------------------- +// Important note about DLL memory management in a VCL DLL: +// +// +// +// If your DLL uses VCL and exports any functions that pass VCL String objects +// (or structs/classes containing nested Strings) as parameter or function +// results, you will need to build both your DLL project and any EXE projects +// that use your DLL with the dynamic RTL (the RTL DLL). This will change your +// DLL and its calling EXE's to use BORLNDMM.DLL as their memory manager. In +// these cases, the file BORLNDMM.DLL should be deployed along with your DLL +// and the RTL DLL (CP3240MT.DLL). To avoid the requiring BORLNDMM.DLL in +// these situations, pass string information using "char *" or ShortString +// parameters and then link with the static RTL. +// +//--------------------------------------------------------------------------- +USEUNIT("adler32.c"); +USEUNIT("compress.c"); +USEUNIT("crc32.c"); +USEUNIT("deflate.c"); +USEUNIT("gzio.c"); +USEUNIT("infblock.c"); +USEUNIT("infcodes.c"); +USEUNIT("inffast.c"); +USEUNIT("inflate.c"); +USEUNIT("inftrees.c"); +USEUNIT("infutil.c"); +USEUNIT("trees.c"); +USEUNIT("uncompr.c"); +USEUNIT("zutil.c"); +//--------------------------------------------------------------------------- +#pragma argsused +int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) +{ + return 1; +} diff --git a/drivers/lib/zlib/contrib/iostream/test.cpp b/drivers/lib/zlib/contrib/iostream/test.cpp new file mode 100644 index 0000000..7d265b3 --- /dev/null +++ b/drivers/lib/zlib/contrib/iostream/test.cpp @@ -0,0 +1,24 @@ + +#include "zfstream.h" + +int main() { + + // Construct a stream object with this filebuffer. Anything sent + // to this stream will go to standard out. + gzofstream os( 1, ios::out ); + + // This text is getting compressed and sent to stdout. + // To prove this, run 'test | zcat'. + os << "Hello, Mommy" << endl; + + os << setcompressionlevel( Z_NO_COMPRESSION ); + os << "hello, hello, hi, ho!" << endl; + + setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) + << "I'm compressing again" << endl; + + os.close(); + + return 0; + +} diff --git a/drivers/lib/zlib/contrib/iostream/zfstream.cpp b/drivers/lib/zlib/contrib/iostream/zfstream.cpp new file mode 100644 index 0000000..a690bbe --- /dev/null +++ b/drivers/lib/zlib/contrib/iostream/zfstream.cpp @@ -0,0 +1,329 @@ + +#include +#include "zfstream.h" + +gzfilebuf::gzfilebuf() : + file(NULL), + mode(0), + own_file_descriptor(0) +{ } + +gzfilebuf::~gzfilebuf() { + + sync(); + if ( own_file_descriptor ) + close(); + +} + +gzfilebuf *gzfilebuf::open( const char *name, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p; + memset(char_mode,'\0',10); + p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + if ( (file = gzopen(name, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 1; + + return this; + +} + +gzfilebuf *gzfilebuf::attach( int file_descriptor, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p; + memset(char_mode,'\0',10); + p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 0; + + return this; + +} + +gzfilebuf *gzfilebuf::close() { + + if ( is_open() ) { + + sync(); + gzclose( file ); + file = NULL; + + } + + return this; + +} + +int gzfilebuf::setcompressionlevel( short comp_level ) { + + return gzsetparams(file, comp_level, -2); + +} + +int gzfilebuf::setcompressionstrategy( short comp_strategy ) { + + return gzsetparams(file, -2, comp_strategy); + +} + + +streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { + + return streampos(EOF); + +} + +int gzfilebuf::underflow() { + + // If the file hasn't been opened for reading, error. + if ( !is_open() || !(mode & ios::in) ) + return EOF; + + // if a buffer doesn't exists, allocate one. + if ( !base() ) { + + if ( (allocate()) == EOF ) + return EOF; + setp(0,0); + + } else { + + if ( in_avail() ) + return (unsigned char) *gptr(); + + if ( out_waiting() ) { + if ( flushbuf() == EOF ) + return EOF; + } + + } + + // Attempt to fill the buffer. + + int result = fillbuf(); + if ( result == EOF ) { + // disable get area + setg(0,0,0); + return EOF; + } + + return (unsigned char) *gptr(); + +} + +int gzfilebuf::overflow( int c ) { + + if ( !is_open() || !(mode & ios::out) ) + return EOF; + + if ( !base() ) { + if ( allocate() == EOF ) + return EOF; + setg(0,0,0); + } else { + if (in_avail()) { + return EOF; + } + if (out_waiting()) { + if (flushbuf() == EOF) + return EOF; + } + } + + int bl = blen(); + setp( base(), base() + bl); + + if ( c != EOF ) { + + *pptr() = c; + pbump(1); + + } + + return 0; + +} + +int gzfilebuf::sync() { + + if ( !is_open() ) + return EOF; + + if ( out_waiting() ) + return flushbuf(); + + return 0; + +} + +int gzfilebuf::flushbuf() { + + int n; + char *q; + + q = pbase(); + n = pptr() - q; + + if ( gzwrite( file, q, n) < n ) + return EOF; + + setp(0,0); + + return 0; + +} + +int gzfilebuf::fillbuf() { + + int required; + char *p; + + p = base(); + + required = blen(); + + int t = gzread( file, p, required ); + + if ( t <= 0) return EOF; + + setg( base(), base(), base()+t); + + return t; + +} + +gzfilestream_common::gzfilestream_common() : + ios( gzfilestream_common::rdbuf() ) +{ } + +gzfilestream_common::~gzfilestream_common() +{ } + +void gzfilestream_common::attach( int fd, int io_mode ) { + + if ( !buffer.attach( fd, io_mode) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::open( const char *name, int io_mode ) { + + if ( !buffer.open( name, io_mode ) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::close() { + + if ( !buffer.close() ) + clear( ios::failbit | ios::badbit ); + +} + +gzfilebuf *gzfilestream_common::rdbuf() { + + return &buffer; + +} + +gzifstream::gzifstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzifstream::gzifstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzifstream::gzifstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzifstream::~gzifstream() { } + +gzofstream::gzofstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzofstream::gzofstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzofstream::gzofstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzofstream::~gzofstream() { } diff --git a/drivers/lib/zlib/contrib/iostream/zfstream.h b/drivers/lib/zlib/contrib/iostream/zfstream.h new file mode 100644 index 0000000..c87fa08 --- /dev/null +++ b/drivers/lib/zlib/contrib/iostream/zfstream.h @@ -0,0 +1,142 @@ + +#ifndef _zfstream_h +#define _zfstream_h + +#include +#include "zlib.h" + +class gzfilebuf : public streambuf { + +public: + + gzfilebuf( ); + virtual ~gzfilebuf(); + + gzfilebuf *open( const char *name, int io_mode ); + gzfilebuf *attach( int file_descriptor, int io_mode ); + gzfilebuf *close(); + + int setcompressionlevel( short comp_level ); + int setcompressionstrategy( short comp_strategy ); + + inline int is_open() const { return (file !=NULL); } + + virtual streampos seekoff( streamoff, ios::seek_dir, int ); + + virtual int sync(); + +protected: + + virtual int underflow(); + virtual int overflow( int = EOF ); + +private: + + gzFile file; + short mode; + short own_file_descriptor; + + int flushbuf(); + int fillbuf(); + +}; + +class gzfilestream_common : virtual public ios { + + friend class gzifstream; + friend class gzofstream; + friend gzofstream &setcompressionlevel( gzofstream &, int ); + friend gzofstream &setcompressionstrategy( gzofstream &, int ); + +public: + virtual ~gzfilestream_common(); + + void attach( int fd, int io_mode ); + void open( const char *name, int io_mode ); + void close(); + +protected: + gzfilestream_common(); + +private: + gzfilebuf *rdbuf(); + + gzfilebuf buffer; + +}; + +class gzifstream : public gzfilestream_common, public istream { + +public: + + gzifstream(); + gzifstream( const char *name, int io_mode = ios::in ); + gzifstream( int fd, int io_mode = ios::in ); + + virtual ~gzifstream(); + +}; + +class gzofstream : public gzfilestream_common, public ostream { + +public: + + gzofstream(); + gzofstream( const char *name, int io_mode = ios::out ); + gzofstream( int fd, int io_mode = ios::out ); + + virtual ~gzofstream(); + +}; + +template class gzomanip { + friend gzofstream &operator<<(gzofstream &, const gzomanip &); +public: + gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } +private: + gzofstream &(*func)(gzofstream &, T); + T val; +}; + +template gzofstream &operator<<(gzofstream &s, + const gzomanip &m) { + return (*m.func)(s, m.val); + +} + +inline gzofstream &setcompressionlevel( gzofstream &s, int l ) { + (s.rdbuf())->setcompressionlevel(l); + return s; +} + +inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) { + (s.rdbuf())->setcompressionstrategy(l); + return s; +} + +inline gzomanip setcompressionlevel(int l) +{ + return gzomanip(&setcompressionlevel,l); +} + +inline gzomanip setcompressionstrategy(int l) +{ + return gzomanip(&setcompressionstrategy,l); +} + +#endif + + + + + + + + + + + + + + + diff --git a/drivers/lib/zlib/contrib/iostream2/zstream.h b/drivers/lib/zlib/contrib/iostream2/zstream.h new file mode 100644 index 0000000..861ef2b --- /dev/null +++ b/drivers/lib/zlib/contrib/iostream2/zstream.h @@ -0,0 +1,307 @@ +/* + * + * Copyright (c) 1997 + * Christian Michelsen Research AS + * Advanced Computing + * Fantoftvegen 38, 5036 BERGEN, Norway + * http://www.cmr.no + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Christian Michelsen Research AS makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef ZSTREAM__H +#define ZSTREAM__H + +/* + * zstream.h - C++ interface to the 'zlib' general purpose compression library + * $Id$ + */ + +#include +#include +#include +#include "zlib.h" + +#if defined(_WIN32) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +class zstringlen { +public: + zstringlen(class izstream&); + zstringlen(class ozstream&, const char*); + size_t value() const { return val.word; } +private: + struct Val { unsigned char byte; size_t word; } val; +}; + +// ----------------------------- izstream ----------------------------- + +class izstream +{ + public: + izstream() : m_fp(0) {} + izstream(FILE* fp) : m_fp(0) { open(fp); } + izstream(const char* name) : m_fp(0) { open(name); } + ~izstream() { close(); } + + /* Opens a gzip (.gz) file for reading. + * open() can be used to read a file which is not in gzip format; + * in this case read() will directly read from the file without + * decompression. errno can be checked to distinguish two error + * cases (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name) { + if (m_fp) close(); + m_fp = ::gzopen(name, "rb"); + } + + void open(FILE* fp) { + SET_BINARY_MODE(fp); + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), "rb"); + } + + /* Flushes all pending input if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + int r = ::gzclose(m_fp); + m_fp = 0; return r; + } + + /* Binary read the given number of bytes from the compressed file. + */ + int read(void* buf, size_t len) { + return ::gzread(m_fp, buf, len); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + private: + gzFile m_fp; +}; + +/* + * Binary read the given (array of) object(s) from the compressed file. + * If the input file was not in gzip format, read() copies the objects number + * of bytes into the buffer. + * returns the number of uncompressed bytes actually read + * (0 for end of file, -1 for error). + */ +template +inline int read(izstream& zs, T* x, Items items) { + return ::gzread(zs.fp(), x, items*sizeof(T)); +} + +/* + * Binary input with the '>' operator. + */ +template +inline izstream& operator>(izstream& zs, T& x) { + ::gzread(zs.fp(), &x, sizeof(T)); + return zs; +} + + +inline zstringlen::zstringlen(izstream& zs) { + zs > val.byte; + if (val.byte == 255) zs > val.word; + else val.word = val.byte; +} + +/* + * Read length of string + the string with the '>' operator. + */ +inline izstream& operator>(izstream& zs, char* x) { + zstringlen len(zs); + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return zs; +} + +inline char* read_string(izstream& zs) { + zstringlen len(zs); + char* x = new char[len.value()+1]; + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return x; +} + +// ----------------------------- ozstream ----------------------------- + +class ozstream +{ + public: + ozstream() : m_fp(0), m_os(0) { + } + ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(fp, level); + } + ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(name, level); + } + ~ozstream() { + close(); + } + + /* Opens a gzip (.gz) file for writing. + * The compression level parameter should be in 0..9 + * errno can be checked to distinguish two error cases + * (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzopen(name, mode); + } + + /* open from a FILE pointer. + */ + void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { + SET_BINARY_MODE(fp); + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), mode); + } + + /* Flushes all pending output if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + if (m_os) { + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = 0; + } + int r = ::gzclose(m_fp); m_fp = 0; return r; + } + + /* Binary write the given number of bytes into the compressed file. + */ + int write(const void* buf, size_t len) { + return ::gzwrite(m_fp, (voidp) buf, len); + } + + /* Flushes all pending output into the compressed file. The parameter + * _flush is as in the deflate() function. The return value is the zlib + * error number (see function gzerror below). flush() returns Z_OK if + * the flush_ parameter is Z_FINISH and all output could be flushed. + * flush() should be called only when strictly necessary because it can + * degrade compression. + */ + int flush(int _flush) { + os_flush(); + return ::gzflush(m_fp, _flush); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + ostream& os() { + if (m_os == 0) m_os = new ostrstream; + return *m_os; + } + + void os_flush() { + if (m_os && m_os->pcount()>0) { + ostrstream* oss = new ostrstream; + oss->fill(m_os->fill()); + oss->flags(m_os->flags()); + oss->precision(m_os->precision()); + oss->width(m_os->width()); + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = oss; + } + } + + private: + gzFile m_fp; + ostrstream* m_os; +}; + +/* + * Binary write the given (array of) object(s) into the compressed file. + * returns the number of uncompressed bytes actually written + * (0 in case of error). + */ +template +inline int write(ozstream& zs, const T* x, Items items) { + return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); +} + +/* + * Binary output with the '<' operator. + */ +template +inline ozstream& operator<(ozstream& zs, const T& x) { + ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); + return zs; +} + +inline zstringlen::zstringlen(ozstream& zs, const char* x) { + val.byte = 255; val.word = ::strlen(x); + if (val.word < 255) zs < (val.byte = val.word); + else zs < val; +} + +/* + * Write length of string + the string with the '<' operator. + */ +inline ozstream& operator<(ozstream& zs, const char* x) { + zstringlen len(zs, x); + ::gzwrite(zs.fp(), (voidp) x, len.value()); + return zs; +} + +#ifdef _MSC_VER +inline ozstream& operator<(ozstream& zs, char* const& x) { + return zs < (const char*) x; +} +#endif + +/* + * Ascii write with the << operator; + */ +template +inline ostream& operator<<(ozstream& zs, const T& x) { + zs.os_flush(); + return zs.os() << x; +} + +#endif diff --git a/drivers/lib/zlib/contrib/iostream2/zstream_test.cpp b/drivers/lib/zlib/contrib/iostream2/zstream_test.cpp new file mode 100644 index 0000000..5bbd56c --- /dev/null +++ b/drivers/lib/zlib/contrib/iostream2/zstream_test.cpp @@ -0,0 +1,25 @@ +#include "zstream.h" +#include +#include +#include + +void main() { + char h[256] = "Hello"; + char* g = "Goodbye"; + ozstream out("temp.gz"); + out < "This works well" < h < g; + out.close(); + + izstream in("temp.gz"); // read it back + char *x = read_string(in), *y = new char[256], z[256]; + in > y > z; + in.close(); + cout << x << endl << y << endl << z << endl; + + out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results + out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; + out << z << endl << y << endl << x << endl; + out << 1.1234567890123456789 << endl; + + delete[] x; delete[] y; +} diff --git a/drivers/lib/zlib/contrib/minizip/ChangeLogUnzip b/drivers/lib/zlib/contrib/minizip/ChangeLogUnzip new file mode 100644 index 0000000..9987c54 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/ChangeLogUnzip @@ -0,0 +1,38 @@ +Change in 0.15: (19 Mar 98) +- fix memory leak in minizip.c + +Change in 0.14: (10 Mar 98) +- fix bugs in minizip.c sample for zipping big file +- fix problem in month in date handling +- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for + comment handling + +Change in 0.13: (6 Mar 98) +- fix bugs in zip.c +- add real minizip sample + +Change in 0.12: (4 Mar 98) +- add zip.c and zip.h for creates .zip file +- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly) +- fix miniunz.c for file without specific record for directory + +Change in 0.11: (3 Mar 98) +- fix bug in unzGetCurrentFileInfo for get extra field and comment +- enhance miniunz sample, remove the bad unztst.c sample + +Change in 0.10: (2 Mar 98) +- fix bug in unzReadCurrentFile +- rename unzip* to unz* function and structure +- remove Windows-like hungary notation variable name +- modify some structure in unzip.h +- add somes comment in source +- remove unzipGetcCurrentFile function +- replace ZUNZEXPORT by ZEXPORT +- add unzGetLocalExtrafield for get the local extrafield info +- add a new sample, miniunz.c + +Change in 0.4: (25 Feb 98) +- suppress the type unzipFileInZip. + Only on file in the zipfile can be open at the same time +- fix somes typo in code +- added tm_unz structure in unzip_file_info (date/time in readable format) diff --git a/drivers/lib/zlib/contrib/minizip/Makefile b/drivers/lib/zlib/contrib/minizip/Makefile new file mode 100644 index 0000000..a1dfc16 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/Makefile @@ -0,0 +1,25 @@ +CC=cc +CFLAGS=-O -I../.. + +UNZ_OBJS = miniunz.o unzip.o ../../libz.a +ZIP_OBJS = minizip.o zip.o ../../libz.a + +.c.o: + $(CC) -c $(CFLAGS) $*.c + +all: miniunz minizip + +miniunz: $(UNZ_OBJS) + $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) + +minizip: $(ZIP_OBJS) + $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) + +test: miniunz minizip + ./minizip test readme.txt + ./miniunz -l test.zip + mv readme.txt readme.old + ./miniunz test.zip + +clean: + /bin/rm -f *.o *~ minizip miniunz diff --git a/drivers/lib/zlib/contrib/minizip/miniunz.c b/drivers/lib/zlib/contrib/minizip/miniunz.c new file mode 100644 index 0000000..f3b7832 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/miniunz.c @@ -0,0 +1,508 @@ +#include +#include +#include +#include +#include +#include + +#ifdef unix +# include +# include +#else +# include +# include +#endif + +#include "unzip.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) + +/* + mini unzip, demo of unzip package + + usage : + Usage : miniunz [-exvlo] file.zip [file_to_extract] + + list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT + if it exists +*/ + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(filename,dosdate,tmu_date) + const char *filename; + uLong dosdate; + tm_unz tmu_date; +{ +#ifdef WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix + struct utimbuf ut; + struct tm newdate; + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +/* mymkdir and change_file_date are not 100 % portable + As I don't know well Unix, I wait feedback for the unix portion */ + +int mymkdir(dirname) + const char* dirname; +{ + int ret=0; +#ifdef WIN32 + ret = mkdir(dirname); +#else +#ifdef unix + ret = mkdir (dirname,0775); +#endif +#endif + return ret; +} + +int makedir (newdir) + char *newdir; +{ + char *buffer ; + char *p; + int len = strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +void do_banner() +{ + printf("MiniUnz 0.15, demo of zLib + Unz package written by Gilles Vollant\n"); + printf("more info at http://wwww.winimage/zLibDll/unzip.htm\n\n"); +} + +void do_help() +{ + printf("Usage : miniunz [-exvlo] file.zip [file_to_extract]\n\n") ; +} + + +int do_list(uf) + unzFile uf; +{ + uLong i; + unz_global_info gi; + int err; + + err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); + printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); + for (i=0;i0) + ratio = (file_info.compressed_size*100)/file_info.uncompressed_size; + + if (file_info.compression_method==0) + string_method="Stored"; + else + if (file_info.compression_method==Z_DEFLATED) + { + uInt iLevel=(uInt)((file_info.flag & 0x6)/2); + if (iLevel==0) + string_method="Defl:N"; + else if (iLevel==1) + string_method="Defl:X"; + else if ((iLevel==2) || (iLevel==3)) + string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ + } + else + string_method="Unkn. "; + + printf("%7lu %6s %7lu %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", + file_info.uncompressed_size,string_method,file_info.compressed_size, + ratio, + (uLong)file_info.tmu_date.tm_mon + 1, + (uLong)file_info.tmu_date.tm_mday, + (uLong)file_info.tmu_date.tm_year % 100, + (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, + (uLong)file_info.crc,filename_inzip); + if ((i+1)='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=fopen(write_filename,"wb"); + + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=fopen(write_filename,"wb"); + } + + if (fout==NULL) + { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } + while (err>0); + fclose(fout); + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +int do_extract(uf,opt_extract_without_path,opt_overwrite) + unzFile uf; + int opt_extract_without_path; + int opt_overwrite; +{ + uLong i; + unz_global_info gi; + int err; + FILE* fout=NULL; + + err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i +#include +#include +#include +#include +#include + +#ifdef unix +# include +# include +# include +# include +#else +# include +# include +#endif + +#include "zip.h" + + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + +#ifdef WIN32 +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATA ff32; + + hFind = FindFirstFile(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} +#else +#ifdef unix +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) + { + char name[MAXFILENAME]; + int len = strlen(f); + strcpy(name, f); + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) + { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} +#else +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + return 0; +} +#endif +#endif + + + + +int check_exist_file(filename) + const char* filename; +{ + FILE* ftestexist; + int ret = 1; + ftestexist = fopen(filename,"rb"); + if (ftestexist==NULL) + ret = 0; + else + fclose(ftestexist); + return ret; +} + +void do_banner() +{ + printf("MiniZip 0.15, demo of zLib + Zip package written by Gilles Vollant\n"); + printf("more info at http://wwww.winimage/zLibDll/unzip.htm\n\n"); +} + +void do_help() +{ + printf("Usage : minizip [-o] file.zip [files_to_add]\n\n") ; +} + +int main(argc,argv) + int argc; + char *argv[]; +{ + int i; + int opt_overwrite=0; + int opt_compress_level=Z_DEFAULT_COMPRESSION; + int zipfilenamearg = 0; + char filename_try[MAXFILENAME]; + int zipok; + int err=0; + int size_buf=0; + void* buf=NULL, + + + do_banner(); + if (argc==1) + { + do_help(); + exit(0); + return 0; + } + else + { + for (i=1;i='0') && (c<='9')) + opt_compress_level = c-'0'; + } + } + else + if (zipfilenamearg == 0) + zipfilenamearg = i ; + } + } + + size_buf = WRITEBUFFERSIZE; + buf = (void*)malloc(size_buf); + if (buf==NULL) + { + printf("Error allocating memory\n"); + return ZIP_INTERNALERROR; + } + + if (zipfilenamearg==0) + zipok=0; + else + { + int i,len; + int dot_found=0; + + zipok = 1 ; + strcpy(filename_try,argv[zipfilenamearg]); + len=strlen(filename_try); + for (i=0;i='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N')); + if (rep=='N') + zipok = 0; + } + } + + if (zipok==1) + { + zipFile zf; + int errclose; + zf = zipOpen(filename_try,0); + if (zf == NULL) + { + printf("error opening %s\n",filename_try); + err= ZIP_ERRNO; + } + else + printf("creating %s\n",filename_try); + + for (i=zipfilenamearg+1;(i0) + { + err = zipWriteInFileInZip (zf,buf,size_read); + if (err<0) + { + printf("error in writing %s in the zipfile\n", + filenameinzip); + } + + } + } while ((err == ZIP_OK) && (size_read>0)); + + fclose(fin); + if (err<0) + err=ZIP_ERRNO; + else + { + err = zipCloseFileInZip(zf); + if (err!=ZIP_OK) + printf("error in closing %s in the zipfile\n", + filenameinzip); + } + } + } + errclose = zipClose(zf,NULL); + if (errclose != ZIP_OK) + printf("error in closing %s\n",filename_try); + } + + free(buf); + exit(0); + return 0; /* to avoid warning */ +} diff --git a/drivers/lib/zlib/contrib/minizip/readme.txt b/drivers/lib/zlib/contrib/minizip/readme.txt new file mode 100644 index 0000000..1fc023c --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/readme.txt @@ -0,0 +1,37 @@ + +UnZip 0.15 additionnal library + + + This unzip package allow extract file from .ZIP file, compatible with +PKZip 2.04g, WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported, and old compression used by old +PKZip 1.x are not supported. + +See probdesc.zip from PKWare for specification of .ZIP format. + +What is Unzip + The Zlib library support the deflate compression and the creation of gzip (.gz) +file. Zlib is free and small. + The .Zip format, which can contain several compressed files (.gz can containt +only one file) is a very popular format. This is why I've written a package for reading file compressed in Zipfile. + +Using Unzip package + +You need source of Zlib (get zlib111.zip and read zlib.h). +Get unzlb015.zip and read unzip.h (whith documentation of unzip functions) + +The Unzip package is only two file : unzip.h and unzip.c. But it use the Zlib + files. +unztst.c is a simple sample program, which list file in a zipfile and display + README.TXT or FILE_ID.DIZ (if these files are found). +miniunz.c is a mini unzip program. + +I'm also currenlyt writing a zipping portion (zip.h, zip.c and test with minizip.c) + +Please email me for feedback. +I hope my source is compatible with Unix system, but I need your help for be sure + +Latest revision : Mar 04th, 1998 + +Check http://www.winimage.com/zLibDll/unzip.html for up to date info. diff --git a/drivers/lib/zlib/contrib/minizip/unzip.c b/drivers/lib/zlib/contrib/minizip/unzip.c new file mode 100644 index 0000000..ff71a47 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/unzip.c @@ -0,0 +1,1294 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + + +#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ + !defined(CASESENSITIVITYDEFAULT_NO) +#define CASESENSITIVITYDEFAULT_NO +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char unz_copyright[] = + " unzip 0.15 Copyright 1998 Gilles Vollant "; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + FILE* file; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + FILE* file; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ +} unz_s; + + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte(fin,pi) + FILE *fin; + int *pi; +{ + unsigned char c; + int err = fread(&c, 1, 1, fin); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ferror(fin)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong (fin,pX) + FILE* fin; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(fin,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(fin,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#define BUFREADCOMMENT (0x400) + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir(fin) + FILE *fin; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (fseek(fin,0,SEEK_END) != 0) + return 0; + + + uSizeFile = ftell( fin ); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (fseek(fin,uReadPos,SEEK_SET)!=0) + break; + + if (fread(buf,(uInt)uReadSize,1,fin)!=1) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer + "zlib/zlib109.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen (path) + const char *path; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + FILE * fin ; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + fin=fopen(path,"rb"); + if (fin==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(fin); + if (central_pos==0) + err=UNZ_ERRNO; + + if (fseek(fin,central_pos,SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(fin,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + fclose(s->file); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + return err; +} + + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (fseek(s->file,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(s->file,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + int Store; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + Store = s->cur_file_info.compression_method==0; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->file=s->file; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if (!Store) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + + s->pfile_in_zip_read = pfile_in_zip_read_info; + return UNZ_OK; +} + + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if (len>pfile_in_zip_read_info->rest_read_uncompressed) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) + return UNZ_ERRNO; + if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, + pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if (pfile_in_zip_read_info->compression_method==0) + { + uInt uDoCopy,i ; + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (fseek(pfile_in_zip_read_info->file, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + int err=UNZ_OK; + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} diff --git a/drivers/lib/zlib/contrib/minizip/unzip.def b/drivers/lib/zlib/contrib/minizip/unzip.def new file mode 100644 index 0000000..f6ede89 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/unzip.def @@ -0,0 +1,15 @@ + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 diff --git a/drivers/lib/zlib/contrib/minizip/unzip.h b/drivers/lib/zlib/contrib/minizip/unzip.h new file mode 100644 index 0000000..76692cb --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/unzip.h @@ -0,0 +1,275 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip */ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer + "zlib/zlib111.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/drivers/lib/zlib/contrib/minizip/zip.c b/drivers/lib/zlib/contrib/minizip/zip.c new file mode 100644 index 0000000..0cae64a --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/zip.c @@ -0,0 +1,718 @@ +/* zip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read zip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +const char zip_copyright[] = + " zip 0.15 Copyright 1998 Gilles Vollant "; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + uLong pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralheader; /* size of the central header for cur file */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; +} curfile_info; + +typedef struct +{ + FILE * filezip; + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile_info ci; /* info on the file curretly writing */ + + uLong begin_pos; /* position of the beginning of the zipfile */ + uLong number_entry; +} zip_internal; + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(ldi) + linkedlist_datablock_internal* ldi; +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(ll) + linkedlist_data* ll; +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(ll) + linkedlist_data* ll; +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(ll,buf,len) + linkedlist_data* ll; + const void* buf; + uLong len; +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + +local int write_datablock(fout,ll) + FILE * fout; + linkedlist_data* ll; +{ + linkedlist_datablock_internal* ldi; + ldi = ll->first_block; + while (ldi!=NULL) + { + if (ldi->filled_in_this_block > 0) + if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1) + return ZIP_ERRNO; + ldi = ldi->next_datablock; + } + return ZIP_OK; +} + +/****************************************************************************/ + +/* =========================================================================== + Outputs a long in LSB order to the given file + nbByte == 1, 2 or 4 (byte, short or long) +*/ + +local int ziplocal_putValue OF((FILE *file, uLong x, int nbByte)); +local int ziplocal_putValue (file, x, nbByte) + FILE *file; + uLong x; + int nbByte; +{ + unsigned char buf[4]; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (fwrite(buf,nbByte,1,file)!=1) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); +local void ziplocal_putValue_inmemory (dest, x, nbByte) + void* dest; + uLong x; + int nbByte; +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } +} +/****************************************************************************/ + + +local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) + tm_zip* ptm; + uLong dosDate; +{ + uLong year = (uLong)ptm->tm_year; + if (year>1980) + year-=1980; + else if (year>80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +extern zipFile ZEXPORT zipOpen (pathname, append) + const char *pathname; + int append; +{ + zip_internal ziinit; + zip_internal* zi; + + ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab"); + if (ziinit.filezip == NULL) + return NULL; + ziinit.begin_pos = ftell(ziinit.filezip); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + init_linkedlist(&(ziinit.central_dir)); + + + zi = (zip_internal*)ALLOC(sizeof(zip_internal)); + if (zi==NULL) + { + fclose(ziinit.filezip); + return NULL; + } + + *zi = ziinit; + return (zipFile)zi; +} + +extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; +{ + zip_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = strlen(comment); + + size_filename = strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); + } + + zi->ci.flag = 0; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if ((level==2)) + zi->ci.flag |= 4; + if ((level==1)) + zi->ci.flag |= 6; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.pos_local_header = ftell(zi->filezip); + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + + size_extrafield_global + size_comment; + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); + + ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(filename+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + /* write the local header */ + err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */ + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */ + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2); + + if ((err==ZIP_OK) && (size_filename>0)) + if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1) + err = ZIP_ERRNO; + + if ((err==ZIP_OK) && (size_extrafield_local>0)) + if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED)) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + err = deflateInit2(&zi->ci.stream, level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); + + if (err==Z_OK) + zi->ci.stream_initialised = 1; + } + + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (file, buf, len) + zipFile file; + const voidp buf; + unsigned len; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.stream.next_in = buf; + zi->ci.stream.avail_in = len; + zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + if (zi->ci.method == Z_DEFLATED) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + for (i=0;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return 0; +} + +extern int ZEXPORT zipCloseFileInZip (file) + zipFile file; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if (zi->ci.method == Z_DEFLATED) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip) + !=1) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + (uLong)zi->ci.stream.total_out,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24, + (uLong)zi->ci.stream.total_in,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ftell(zi->filezip); + if (fseek(zi->filezip, + zi->ci.pos_local_header + 14,SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4); + + if (fseek(zi->filezip, + cur_pos_inzip,SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipClose (file, global_comment) + zipFile file; + const char* global_comment; +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip ; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = strlen(global_comment); + + + centraldir_pos_inzip = ftell(zi->filezip); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block, + 1,zi->filezip) !=1 ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(zi->filezip,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(zi->filezip,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 ) + err = ZIP_ERRNO; + fclose(zi->filezip); + TRYFREE(zi); + + return err; +} diff --git a/drivers/lib/zlib/contrib/minizip/zip.def b/drivers/lib/zlib/contrib/minizip/zip.def new file mode 100644 index 0000000..5d5079f --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/zip.def @@ -0,0 +1,5 @@ + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 diff --git a/drivers/lib/zlib/contrib/minizip/zip.h b/drivers/lib/zlib/contrib/minizip/zip.h new file mode 100644 index 0000000..678260b --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/zip.h @@ -0,0 +1,150 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 0.15 alpha, Mar 19th, 1998, + + Copyright (C) 1998 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Encryption and multi volume ZipFile (span) are not supported. + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE + CAN CHANGE IN FUTURE VERSION !! + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/zip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_INTERNALERROR (-104) + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on + an Unix computer "zlib/zlib111.zip". + if the file pathname exist and append=1, the zip will be created at the end + of the file. (useful if the file contain a self extractor code) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. + + +*/ + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const voidp buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/drivers/lib/zlib/contrib/minizip/zlibvc.def b/drivers/lib/zlib/contrib/minizip/zlibvc.def new file mode 100644 index 0000000..7e9d60d --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/zlibvc.def @@ -0,0 +1,74 @@ +LIBRARY "zlib" + +DESCRIPTION '"""zlib data compression library"""' + + +VERSION 1.11 + + +HEAPSIZE 1048576,8192 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 diff --git a/drivers/lib/zlib/contrib/minizip/zlibvc.dsp b/drivers/lib/zlib/contrib/minizip/zlibvc.dsp new file mode 100644 index 0000000..a70d4d4 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/zlibvc.dsp @@ -0,0 +1,651 @@ +# Microsoft Developer Studio Project File - Name="zlibvc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 +# TARGTYPE "Win32 (ALPHA) Dynamic-Link Library" 0x0602 + +CFG=zlibvc - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zlibvc.mak" CFG="zlibvc - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zlibvc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseAxp" (based on\ + "Win32 (ALPHA) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutAsm" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "zlibvc - Win32 ReleaseWithoutCrtdll" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\zlib.dll" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc__" +# PROP BASE Intermediate_Dir "zlibvc__" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc__" +# PROP Intermediate_Dir "zlibvc__" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +CPP=cl.exe +# ADD BASE CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /Gt0 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 crtdll.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /map /machine:ALPHA /nodefaultlib /out:"zlibvc__\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_0" +# PROP BASE Intermediate_Dir "zlibvc_0" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_0" +# PROP Intermediate_Dir "zlibvc_0" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_0\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "zlibvc_1" +# PROP BASE Intermediate_Dir "zlibvc_1" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "zlibvc_1" +# PROP Intermediate_Dir "zlibvc_1" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_WINDLL" /D "_WIN32" /D "BUILD_ZLIBDLL" /D "ZLIB_DLL" /D "DYNAMIC_CRC_TABLE" /D "ASMV" /FAcs /FR /FD /c +# SUBTRACT CPP /YX +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\Release\zlib.dll" +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 gvmat32.obj kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib crtdll.lib /nologo /subsystem:windows /dll /map /machine:I386 /nodefaultlib /out:".\zlibvc_1\zlib.dll" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "zlibvc - Win32 Release" +# Name "zlibvc - Win32 Debug" +# Name "zlibvc - Win32 ReleaseAxp" +# Name "zlibvc - Win32 ReleaseWithoutAsm" +# Name "zlibvc - Win32 ReleaseWithoutCrtdll" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\adler32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ADLER=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\compress.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_COMPR=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\crc32.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_CRC32=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\deflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_DEFLA=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gvmat32c.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\gzio.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_GZIO_=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infblock.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFBL=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infcodes.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFCO=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inffast.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFFA=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inffast.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inflate.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFLA=\ + ".\infblock.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\inftrees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFTR=\ + ".\inftrees.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\infutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_INFUT=\ + ".\infblock.h"\ + ".\infcodes.h"\ + ".\inftrees.h"\ + ".\infutil.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\trees.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_TREES=\ + ".\deflate.h"\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\uncompr.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_UNCOM=\ + ".\zconf.h"\ + ".\zlib.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\unzip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zip.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\zlib.rc +# End Source File +# Begin Source File + +SOURCE=.\zlibvc.def +# End Source File +# Begin Source File + +SOURCE=.\zutil.c + +!IF "$(CFG)" == "zlibvc - Win32 Release" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 Debug" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseAxp" + +DEP_CPP_ZUTIL=\ + ".\zconf.h"\ + ".\zlib.h"\ + ".\zutil.h"\ + + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutAsm" + +!ELSEIF "$(CFG)" == "zlibvc - Win32 ReleaseWithoutCrtdll" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\deflate.h +# End Source File +# Begin Source File + +SOURCE=.\infblock.h +# End Source File +# Begin Source File + +SOURCE=.\infcodes.h +# End Source File +# Begin Source File + +SOURCE=.\inffast.h +# End Source File +# Begin Source File + +SOURCE=.\inftrees.h +# End Source File +# Begin Source File + +SOURCE=.\infutil.h +# End Source File +# Begin Source File + +SOURCE=.\zconf.h +# End Source File +# Begin Source File + +SOURCE=.\zlib.h +# End Source File +# Begin Source File + +SOURCE=.\zutil.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/drivers/lib/zlib/contrib/minizip/zlibvc.dsw b/drivers/lib/zlib/contrib/minizip/zlibvc.dsw new file mode 100644 index 0000000..493cd87 --- /dev/null +++ b/drivers/lib/zlib/contrib/minizip/zlibvc.dsw @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "zlibstat"=.\zlibstat.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zlibvc"=.\zlibvc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/drivers/lib/zlib/contrib/untgz/Makefile b/drivers/lib/zlib/contrib/untgz/Makefile new file mode 100644 index 0000000..409b4bd --- /dev/null +++ b/drivers/lib/zlib/contrib/untgz/Makefile @@ -0,0 +1,14 @@ +CC=cc +CFLAGS=-g + +untgz: untgz.o ../../libz.a + $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz + +untgz.o: untgz.c ../../zlib.h + $(CC) $(CFLAGS) -c -I../.. untgz.c + +../../libz.a: + cd ../..; make + +clean: + rm -f untgz untgz.o *~ diff --git a/drivers/lib/zlib/contrib/untgz/makefile.w32 b/drivers/lib/zlib/contrib/untgz/makefile.w32 new file mode 100644 index 0000000..c99dc28 --- /dev/null +++ b/drivers/lib/zlib/contrib/untgz/makefile.w32 @@ -0,0 +1,63 @@ +# Makefile for zlib. Modified for mingw32 +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, +# +# make -fmakefile.w32 +# + +CC=gcc + +# Generate dependencies (see end of the file) + +CPPFLAGS=-MMD + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is not found, replace with copy /Y . +CP=cp -f + +# The default value of RM is "rm -f." +# If "rm.exe" is not found, uncomment: +# RM=del + +LD=gcc +LDLIBS=-L. -lz +LDFLAGS=-s + + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o \ + inffast.o + +TEST_OBJS = minigzip.o untgz.o + +all: minigzip.exe untgz.exe + +rebuild: clean all + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $(LDFLAGS) -o $@ $< $(LDLIBS) + +.PHONY : clean + +clean: + $(RM) *.d *.o *.exe libz.a foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif + diff --git a/drivers/lib/zlib/contrib/untgz/untgz.c b/drivers/lib/zlib/contrib/untgz/untgz.c new file mode 100644 index 0000000..4a431ff --- /dev/null +++ b/drivers/lib/zlib/contrib/untgz/untgz.c @@ -0,0 +1,522 @@ +/* + * untgz.c -- Display contents and/or extract file from + * a gzip'd TAR file + * written by "Pedro A. Aranda Guti\irrez" + * adaptation to Unix by Jean-loup Gailly + */ + +#include +#include +#include +#include +#include +#include +#ifdef unix +# include +#else +# include +# include +#endif + +#include "zlib.h" + +#ifdef WIN32 +# ifndef F_OK +# define F_OK (0) +# endif +# ifdef _MSC_VER +# define mkdir(dirname,mode) _mkdir(dirname) +# define strdup(str) _strdup(str) +# define unlink(fn) _unlink(fn) +# define access(path,mode) _access(path,mode) +# else +# define mkdir(dirname,mode) _mkdir(dirname) +# endif +#else +# include +#endif + + +/* Values used in typeflag field. */ + +#define REGTYPE '0' /* regular file */ +#define AREGTYPE '\0' /* regular file */ +#define LNKTYPE '1' /* link */ +#define SYMTYPE '2' /* reserved */ +#define CHRTYPE '3' /* character special */ +#define BLKTYPE '4' /* block special */ +#define DIRTYPE '5' /* directory */ +#define FIFOTYPE '6' /* FIFO special */ +#define CONTTYPE '7' /* reserved */ + +#define BLOCKSIZE 512 + +struct tar_header +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + /* 500 */ +}; + +union tar_buffer { + char buffer[BLOCKSIZE]; + struct tar_header header; +}; + +enum { TGZ_EXTRACT = 0, TGZ_LIST }; + +static char *TGZfname OF((const char *)); +void TGZnotfound OF((const char *)); + +int getoct OF((char *, int)); +char *strtime OF((time_t *)); +int ExprMatch OF((char *,char *)); + +int makedir OF((char *)); +int matchname OF((int,int,char **,char *)); + +void error OF((const char *)); +int tar OF((gzFile, int, int, int, char **)); + +void help OF((int)); +int main OF((int, char **)); + +char *prog; + +/* This will give a benign warning */ + +static char *TGZprefix[] = { "\0", ".tgz", ".tar.gz", ".tar", NULL }; + +/* Return the real name of the TGZ archive */ +/* or NULL if it does not exist. */ + +static char *TGZfname OF((const char *fname)) +{ + static char buffer[1024]; + int origlen,i; + + strcpy(buffer,fname); + origlen = strlen(buffer); + + for (i=0; TGZprefix[i]; i++) + { + strcpy(buffer+origlen,TGZprefix[i]); + if (access(buffer,F_OK) == 0) + return buffer; + } + return NULL; +} + +/* error message for the filename */ + +void TGZnotfound OF((const char *fname)) +{ + int i; + + fprintf(stderr,"%s : couldn't find ",prog); + for (i=0;TGZprefix[i];i++) + fprintf(stderr,(TGZprefix[i+1]) ? "%s%s, " : "or %s%s\n", + fname, + TGZprefix[i]); + exit(1); +} + + +/* help functions */ + +int getoct(char *p,int width) +{ + int result = 0; + char c; + + while (width --) + { + c = *p++; + if (c == ' ') + continue; + if (c == 0) + break; + result = result * 8 + (c - '0'); + } + return result; +} + +char *strtime (time_t *t) +{ + struct tm *local; + static char result[32]; + + local = localtime(t); + sprintf(result,"%2d/%02d/%4d %02d:%02d:%02d", + local->tm_mday, local->tm_mon+1, local->tm_year+1900, + local->tm_hour, local->tm_min, local->tm_sec); + return result; +} + + +/* regular expression matching */ + +#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) + +int ExprMatch(char *string,char *expr) +{ + while (1) + { + if (ISSPECIAL(*expr)) + { + if (*expr == '/') + { + if (*string != '\\' && *string != '/') + return 0; + string ++; expr++; + } + else if (*expr == '*') + { + if (*expr ++ == 0) + return 1; + while (*++string != *expr) + if (*string == 0) + return 0; + } + } + else + { + if (*string != *expr) + return 0; + if (*expr++ == 0) + return 1; + string++; + } + } +} + +/* recursive make directory */ +/* abort if you get an ENOENT errno somewhere in the middle */ +/* e.g. ignore error "mkdir on existing directory" */ +/* */ +/* return 1 if OK */ +/* 0 on error */ + +int makedir (char *newdir) +{ + char *buffer = strdup(newdir); + char *p; + int len = strlen(buffer); + + if (len <= 0) { + free(buffer); + return 0; + } + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mkdir(buffer, 0775) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mkdir(buffer, 0775) == -1) && (errno == ENOENT)) + { + fprintf(stderr,"%s: couldn't create directory %s\n",prog,buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +int matchname (int arg,int argc,char **argv,char *fname) +{ + if (arg == argc) /* no arguments given (untgz tgzarchive) */ + return 1; + + while (arg < argc) + if (ExprMatch(fname,argv[arg++])) + return 1; + + return 0; /* ignore this for the moment being */ +} + + +/* Tar file list or extract */ + +int tar (gzFile in,int action,int arg,int argc,char **argv) +{ + union tar_buffer buffer; + int len; + int err; + int getheader = 1; + int remaining = 0; + FILE *outfile = NULL; + char fname[BLOCKSIZE]; + time_t tartime; + + if (action == TGZ_LIST) + printf(" day time size file\n" + " ---------- -------- --------- -------------------------------------\n"); + while (1) + { + len = gzread(in, &buffer, BLOCKSIZE); + if (len < 0) + error (gzerror(in, &err)); + /* + * Always expect complete blocks to process + * the tar information. + */ + if (len != BLOCKSIZE) + error("gzread: incomplete block read"); + + /* + * If we have to get a tar header + */ + if (getheader == 1) + { + /* + * if we met the end of the tar + * or the end-of-tar block, + * we are done + */ + if ((len == 0) || (buffer.header.name[0]== 0)) break; + + tartime = (time_t)getoct(buffer.header.mtime,12); + strcpy(fname,buffer.header.name); + + switch (buffer.header.typeflag) + { + case DIRTYPE: + if (action == TGZ_LIST) + printf(" %s %s\n",strtime(&tartime),fname); + if (action == TGZ_EXTRACT) + makedir(fname); + break; + case REGTYPE: + case AREGTYPE: + remaining = getoct(buffer.header.size,12); + if (action == TGZ_LIST) + printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); + if (action == TGZ_EXTRACT) + { + if ((remaining) && (matchname(arg,argc,argv,fname))) + { + outfile = fopen(fname,"wb"); + if (outfile == NULL) { + /* try creating directory */ + char *p = strrchr(fname, '/'); + if (p != NULL) { + *p = '\0'; + makedir(fname); + *p = '/'; + outfile = fopen(fname,"wb"); + } + } + fprintf(stderr, + "%s %s\n", + (outfile) ? "Extracting" : "Couldn't create", + fname); + } + else + outfile = NULL; + } + /* + * could have no contents + */ + getheader = (remaining) ? 0 : 1; + break; + default: + if (action == TGZ_LIST) + printf(" %s <---> %s\n",strtime(&tartime),fname); + break; + } + } + else + { + unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; + + if ((action == TGZ_EXTRACT) && (outfile != NULL)) + { + if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) + { + fprintf(stderr,"%s : error writing %s skipping...\n",prog,fname); + fclose(outfile); + unlink(fname); + } + } + remaining -= bytes; + if (remaining == 0) + { + getheader = 1; + if ((action == TGZ_EXTRACT) && (outfile != NULL)) + { +#ifdef WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal; + SYSTEMTIME st; + struct tm localt; + + fclose(outfile); + + localt = *localtime(&tartime); + + hFile = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, NULL); + + st.wYear = (WORD)localt.tm_year+1900; + st.wMonth = (WORD)localt.tm_mon; + st.wDayOfWeek = (WORD)localt.tm_wday; + st.wDay = (WORD)localt.tm_mday; + st.wHour = (WORD)localt.tm_hour; + st.wMinute = (WORD)localt.tm_min; + st.wSecond = (WORD)localt.tm_sec; + st.wMilliseconds = 0; + SystemTimeToFileTime(&st,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,NULL,&ftm); + CloseHandle(hFile); + + outfile = NULL; +#else + struct utimbuf settime; + + settime.actime = settime.modtime = tartime; + + fclose(outfile); + outfile = NULL; + utime(fname,&settime); +#endif + } + } + } + } + + if (gzclose(in) != Z_OK) + error("failed gzclose"); + + return 0; +} + + +/* =========================================================== */ + +void help(int exitval) +{ + fprintf(stderr, + "untgz v 0.1\n" + " an sample application of zlib 1.0.4\n\n" + "Usage : untgz TGZfile to extract all files\n" + " untgz TGZfile fname ... to extract selected files\n" + " untgz -l TGZfile to list archive contents\n" + " untgz -h to display this help\n\n"); + exit(exitval); +} + +void error(const char *msg) +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + + +/* ====================================================================== */ + +int _CRT_glob = 0; /* disable globbing of the arguments */ + +int main(int argc,char **argv) +{ + int action = TGZ_EXTRACT; + int arg = 1; + char *TGZfile; + gzFile *f; + + + prog = strrchr(argv[0],'\\'); + if (prog == NULL) + { + prog = strrchr(argv[0],'/'); + if (prog == NULL) + { + prog = strrchr(argv[0],':'); + if (prog == NULL) + prog = argv[0]; + else + prog++; + } + else + prog++; + } + else + prog++; + + if (argc == 1) + help(0); + + if (strcmp(argv[arg],"-l") == 0) + { + action = TGZ_LIST; + if (argc == ++arg) + help(0); + } + else if (strcmp(argv[arg],"-h") == 0) + { + help(0); + } + + if ((TGZfile = TGZfname(argv[arg])) == NULL) + TGZnotfound(argv[arg]); + + ++arg; + if ((action == TGZ_LIST) && (arg != argc)) + help(1); + +/* + * Process the TGZ file + */ + switch(action) + { + case TGZ_LIST: + case TGZ_EXTRACT: + f = gzopen(TGZfile,"rb"); + if (f == NULL) + { + fprintf(stderr,"%s: Couldn't gzopen %s\n", + prog, + TGZfile); + return 1; + } + exit(tar(f, action, arg, argc, argv)); + break; + + default: + error("Unknown option!"); + exit(1); + } + + return 0; +} diff --git a/drivers/lib/zlib/contrib/visual-basic.txt b/drivers/lib/zlib/contrib/visual-basic.txt new file mode 100644 index 0000000..10fb44b --- /dev/null +++ b/drivers/lib/zlib/contrib/visual-basic.txt @@ -0,0 +1,69 @@ +See below some functions declarations for Visual Basic. + +Frequently Asked Question: + +Q: Each time I use the compress function I get the -5 error (not enough + room in the output buffer). + +A: Make sure that the length of the compressed buffer is passed by + reference ("as any"), not by value ("as long"). Also check that + before the call of compress this length is equal to the total size of + the compressed buffer and not zero. + + +From: "Jon Caruana" +Subject: Re: How to port zlib declares to vb? +Date: Mon, 28 Oct 1996 18:33:03 -0600 + +Got the answer! (I haven't had time to check this but it's what I got, and +looks correct): + +He has the following routines working: + compress + uncompress + gzopen + gzwrite + gzread + gzclose + +Declares follow: (Quoted from Carlos Rios , in Vb4 form) + +#If Win16 Then 'Use Win16 calls. +Declare Function compress Lib "ZLIB.DLL" (ByVal compr As + String, comprLen As Any, ByVal buf As String, ByVal buflen + As Long) As Integer +Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr + As String, uncomprLen As Any, ByVal compr As String, ByVal + lcompr As Long) As Integer +Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As + String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As + Long) As Integer +#Else +Declare Function compress Lib "ZLIB32.DLL" + (ByVal compr As String, comprLen As Any, ByVal buf As + String, ByVal buflen As Long) As Integer +Declare Function uncompress Lib "ZLIB32.DLL" + (ByVal uncompr As String, uncomprLen As Any, ByVal compr As + String, ByVal lcompr As Long) As Long +Declare Function gzopen Lib "ZLIB32.DLL" + (ByVal file As String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzwrite Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzclose Lib "ZLIB32.DLL" + (ByVal file As Long) As Long +#End If + +-Jon Caruana +jon-net@usa.net +Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member diff --git a/drivers/lib/zlib/crc32.c b/drivers/lib/zlib/crc32.c new file mode 100644 index 0000000..60deca2 --- /dev/null +++ b/drivers/lib/zlib/crc32.c @@ -0,0 +1,162 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define local static + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/drivers/lib/zlib/deflate.c b/drivers/lib/zlib/deflate.c new file mode 100644 index 0000000..16ebdad --- /dev/null +++ b/drivers/lib/zlib/deflate.c @@ -0,0 +1,1350 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/drivers/lib/zlib/deflate.h b/drivers/lib/zlib/deflate.h new file mode 100644 index 0000000..b99a48a --- /dev/null +++ b/drivers/lib/zlib/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/drivers/lib/zlib/descrip.mms b/drivers/lib/zlib/descrip.mms new file mode 100644 index 0000000..9d36459 --- /dev/null +++ b/drivers/lib/zlib/descrip.mms @@ -0,0 +1,48 @@ +# descrip.mms: MMS description file for building zlib on VMS +# written by Martin P.J. Zinser + +cc_defs = +c_deb = + +.ifdef __DECC__ +pref = /prefix=all +.endif + +OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ + deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ + inftrees.obj, infcodes.obj, infutil.obj, inffast.obj + +CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) + +all : example.exe minigzip.exe + @ write sys$output " Example applications available" +libz.olb : libz.olb($(OBJS)) + @ write sys$output " libz available" + +example.exe : example.obj libz.olb + link example,libz.olb/lib + +minigzip.exe : minigzip.obj libz.olb + link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib + +clean : + delete *.obj;*,libz.olb;* + + +# Other dependencies. +adler32.obj : zutil.h zlib.h zconf.h +compress.obj : zlib.h zconf.h +crc32.obj : zutil.h zlib.h zconf.h +deflate.obj : deflate.h zutil.h zlib.h zconf.h +example.obj : zlib.h zconf.h +gzio.obj : zutil.h zlib.h zconf.h +infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h +inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h +inflate.obj : zutil.h zlib.h zconf.h infblock.h +inftrees.obj : zutil.h zlib.h zconf.h inftrees.h +infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h +minigzip.obj : zlib.h zconf.h +trees.obj : deflate.h zutil.h zlib.h zconf.h +uncompr.obj : zlib.h zconf.h +zutil.obj : zutil.h zlib.h zconf.h diff --git a/drivers/lib/zlib/example.c b/drivers/lib/zlib/example.c new file mode 100644 index 0000000..e7e3673 --- /dev/null +++ b/drivers/lib/zlib/example.c @@ -0,0 +1,556 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include +#include "zlib.h" + +#ifdef STDC +# include +# include +#else + extern void exit OF((int)); +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +const char dictionary[] = "hello"; +uLong dictId; /* Adler32 value of the dictionary */ + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *out, const char *in, + Byte *uncompr, int uncomprLen)); +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(out, in, uncompr, uncomprLen) + const char *out; /* compressed output file */ + const char *in; /* compressed input file */ + Byte *uncompr; + int uncomprLen; +{ + int err; + int len = strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(out, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(in, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + } + strcpy((char*)uncompr, "garbage"); + + uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen); + if (uncomprLen != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char *)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, uncomprLen); + uncomprLen = strlen((char*)uncompr); + if (uncomprLen != 6) { /* "hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello+7)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char *)uncompr); + } + + gzclose(file); +} + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + int len = strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + int len = strlen(hello)+1; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (Bytef*)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = (alloc_func)0; + c_stream.zfree = (free_func)0; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (Bytef*)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = (alloc_func)0; + d_stream.zfree = (free_func)0; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + (argc > 2 ? argv[2] : TESTFILE), + uncompr, (int)uncomprLen); + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + exit(0); + return 0; /* to avoid warning */ +} diff --git a/drivers/lib/zlib/gzio.c b/drivers/lib/zlib/gzio.c new file mode 100644 index 0000000..09e0a20 --- /dev/null +++ b/drivers/lib/zlib/gzio.c @@ -0,0 +1,875 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. + */ + +/* @(#) $Id$ */ + +#include + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + long startpos; /* start of compressed data in file (header skipped) */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open return NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->startpos = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * startpos anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->startpos = (ftell(s->file) - s->stream.avail_in); + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ +local int get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(s); + if (c != gz_magic[len]) { + if (len != 0) s->stream.avail_in++, s->stream.next_in--; + if (c != EOF) { + s->stream.avail_in++, s->stream.next_in--; + s->transparent = 1; + } + s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + } + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->stream.total_in += (uLong)len; + s->stream.total_out += (uLong)len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may + * be different from s->stream.total_out) in case of + * concatenated .gz files. Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + uLong total_in = s->stream.total_in; + uLong total_out = s->stream.total_out; + + inflateReset(&(s->stream)); + s->stream.total_in = total_in; + s->stream.total_out = total_out; + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_DEFLATE +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + const voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + va_start(va, format); +#ifdef HAS_vsnprintf + (void)vsnprintf(buf, sizeof(buf), format, va); +#else + (void)vsprintf(buf, format, va); +#endif + va_end(va); + len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + +#ifdef HAS_snprintf + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#else + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#endif + len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->z_err = deflate(&(s->stream), flush); + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_DEFLATE */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->stream.total_in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return (z_off_t)s->stream.total_in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->stream.total_out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->stream.total_in = s->stream.total_out = (uLong)offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if ((uLong)offset >= s->stream.total_out) { + offset -= s->stream.total_out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return (z_off_t)s->stream.total_out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + + if (s->startpos == 0) { /* not a compressed file */ + rewind(s->file); + return 0; + } + + (void) inflateReset(&s->stream); + return fseek(s->file, s->startpos, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, s->stream.total_in); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char* ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} diff --git a/drivers/lib/zlib/infblock.c b/drivers/lib/zlib/infblock.c new file mode 100644 index 0000000..dd7a6d4 --- /dev/null +++ b/drivers/lib/zlib/infblock.c @@ -0,0 +1,403 @@ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Table for deflate from PKZIP's appnote.txt. */ +local const uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + ZFREE(z, s->sub.trees.blens); + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/drivers/lib/zlib/infblock.h b/drivers/lib/zlib/infblock.h new file mode 100644 index 0000000..173b226 --- /dev/null +++ b/drivers/lib/zlib/infblock.h @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/drivers/lib/zlib/infcodes.c b/drivers/lib/zlib/infcodes.c new file mode 100644 index 0000000..9abe541 --- /dev/null +++ b/drivers/lib/zlib/infcodes.c @@ -0,0 +1,251 @@ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ + f = q - c->sub.copy.dist; + while (f < s->window) /* modulo window size-"while" instead */ + f += s->end - s->window; /* of "if" handles invalid distances */ + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/drivers/lib/zlib/infcodes.h b/drivers/lib/zlib/infcodes.h new file mode 100644 index 0000000..46821a0 --- /dev/null +++ b/drivers/lib/zlib/infcodes.h @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/drivers/lib/zlib/inffast.c b/drivers/lib/zlib/inffast.c new file mode 100644 index 0000000..aa7f1d4 --- /dev/null +++ b/drivers/lib/zlib/inffast.c @@ -0,0 +1,183 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + r = q - d; + if (r < s->window) /* wrap if needed */ + { + do { + r += s->end - s->window; /* force pointer in window */ + } while (r < s->window); /* covers invalid distances */ + e = s->end - r; + if (c > e) + { + c -= e; /* wrapped copy */ + do { + *q++ = *r++; + } while (--e); + r = s->window; + do { + *q++ = *r++; + } while (--c); + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/drivers/lib/zlib/inffast.h b/drivers/lib/zlib/inffast.h new file mode 100644 index 0000000..a31a4bb --- /dev/null +++ b/drivers/lib/zlib/inffast.h @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/drivers/lib/zlib/inffixed.h b/drivers/lib/zlib/inffixed.h new file mode 100644 index 0000000..77f7e76 --- /dev/null +++ b/drivers/lib/zlib/inffixed.h @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/drivers/lib/zlib/inflate.c b/drivers/lib/zlib/inflate.c new file mode 100644 index 0000000..dfb2e86 --- /dev/null +++ b/drivers/lib/zlib/inflate.c @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<state->wbits)) + { + length = (1<state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/drivers/lib/zlib/inftrees.c b/drivers/lib/zlib/inftrees.c new file mode 100644 index 0000000..4c32ca3 --- /dev/null +++ b/drivers/lib/zlib/inftrees.c @@ -0,0 +1,454 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), or Z_DATA_ERROR if the input is invalid. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_DATA_ERROR; /* overflow of MANY */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} diff --git a/drivers/lib/zlib/inftrees.h b/drivers/lib/zlib/inftrees.h new file mode 100644 index 0000000..04b73b7 --- /dev/null +++ b/drivers/lib/zlib/inftrees.h @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/drivers/lib/zlib/infutil.c b/drivers/lib/zlib/infutil.c new file mode 100644 index 0000000..9a07622 --- /dev/null +++ b/drivers/lib/zlib/infutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/drivers/lib/zlib/infutil.h b/drivers/lib/zlib/infutil.h new file mode 100644 index 0000000..4401df8 --- /dev/null +++ b/drivers/lib/zlib/infutil.h @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/drivers/lib/zlib/makefile.reactos b/drivers/lib/zlib/makefile.reactos new file mode 100644 index 0000000..0dd73db --- /dev/null +++ b/drivers/lib/zlib/makefile.reactos @@ -0,0 +1,26 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = library + +TARGET_NAME = zlib + +TARGET_CFLAGS = \ + -MMD -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +TARGET_OBJECTS = \ + adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o \ + inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# FIXME: this rule should be defined in helper.mk +$(TARGET_NAME).nostrip.a: + @echo FIXME! + @echo FIXME!>$@ + +# EOF diff --git a/drivers/lib/zlib/maketree.c b/drivers/lib/zlib/maketree.c new file mode 100644 index 0000000..a16d4b1 --- /dev/null +++ b/drivers/lib/zlib/maketree.c @@ -0,0 +1,85 @@ +/* maketree.c -- make inffixed.h table for decoding fixed codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* This program is included in the distribution for completeness. + You do not need to compile or run this program since inffixed.h + is already included in the distribution. To use this program + you need to compile zlib with BUILDFIXED defined and then compile + and link this program with the zlib library. Then the output of + this program can be piped to inffixed.h. */ + +#include +#include +#include "zutil.h" +#include "inftrees.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* generate initialization table for an inflate_huft structure array */ +void maketree(uInt b, inflate_huft *t) +{ + int i, e; + + i = 0; + while (1) + { + e = t[i].exop; + if (e && (e & (16+64)) == 0) /* table pointer */ + { + fprintf(stderr, "maketree: cannot initialize sub-tables!\n"); + exit(1); + } + if (i % 4 == 0) + printf("\n "); + printf(" {{{%u,%u}},%u}", t[i].exop, t[i].bits, t[i].base); + if (++i == (1< +#include "zlib.h" + +#ifdef STDC +# include +# include +#else + extern void exit OF((int)); +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fileno */ +#endif + +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + int len = strlen(file); + + strcpy(buf, file); + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; + strcat(infile, GZ_SUFFIX); + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-d] [-f] [-h] [-1 to -9] [files...] + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int uncompr = 0; + gzFile file; + char outmode[20]; + + strcpy(outmode, "wb6 "); + + prog = argv[0]; + argc--, argv++; + + while (argc > 0) { + if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + do { + if (uncompr) { + file_uncompress(*argv); + } else { + file_compress(*argv, outmode); + } + } while (argv++, --argc); + } + exit(0); + return 0; /* to avoid warning */ +} diff --git a/drivers/lib/zlib/msdos/Makefile.b32 b/drivers/lib/zlib/msdos/Makefile.b32 new file mode 100644 index 0000000..f476da9 --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.b32 @@ -0,0 +1,104 @@ +# Makefile for zlib +# Borland C++ + +# This version of the zlib makefile was adapted by Chris Young for use +# with Borland C 4.5x with the Dos Power Pack for a 32-bit protected mode +# flat memory model. It was created for use with POV-Ray ray tracer and +# you may choose to edit the CFLAGS to suit your needs but the +# switches -WX and -DMSDOS are required. +# -- Chris Young 76702.1655@compuserve.com + +# To use, do "make -fmakefile.b32" + +# See zconf.h for details about the memory requirements. + +# ------------- Borland C++ ------------- +MODEL=-WX +CFLAGS= $(MODEL) -P-C -K -N- -k- -d -3 -r- -v- -f -DMSDOS +CC=bcc32 +LD=bcc32 +LIB=tlib +LDFLAGS= $(MODEL) +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +all: test + +adler32.obj: adler32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h\ + infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h\ + infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +zlib.lib: $(OBJ1) $(OBJ2) + del zlib.lib + $(LIB) zlib +$(OBJP1) + $(LIB) zlib +$(OBJP2) + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/drivers/lib/zlib/msdos/Makefile.bor b/drivers/lib/zlib/msdos/Makefile.bor new file mode 100644 index 0000000..f5651b4 --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.bor @@ -0,0 +1,125 @@ +# Makefile for zlib +# Borland C++ ************ UNTESTED *********** + +# To use, do "make -fmakefile.bor" +# To compile in small model, set below: MODEL=s + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Turbo C++, Borland C++ ------------- + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# Memory model: one of s, m, c, l (small, medium, compact, large) +MODEL=l + +CC=bcc +# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version +LD=$(CC) +AR=tlib + +# compiler flags +CFLAGS=-O2 -Z -m$(MODEL) $(LOC) +# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 + +LDFLAGS=-m$(MODEL) + +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +ZLIB_H = zlib.h zconf.h +ZUTIL_H = zutil.h $(ZLIB_H) + +ZLIB_LIB = zlib_$(MODEL).lib + +all: test + +# individual dependencies and action rules: +adler32.obj: adler32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c $(ZUTIL_H) infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) +$(OBJP1) + $(AR) $(ZLIB_LIB) +$(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/drivers/lib/zlib/msdos/Makefile.dj2 b/drivers/lib/zlib/msdos/Makefile.dj2 new file mode 100644 index 0000000..0ab431c --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.dj2 @@ -0,0 +1,100 @@ +# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.dj2; make test -fmakefile.dj2 +# +# To install libz.a, zconf.h and zlib.h in the djgpp directories, type: +# +# make install -fmakefile.dj2 +# +# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as +# in the sample below if the pattern of the DJGPP distribution is to +# be followed. Remember that, while 'es around <=> are ignored in +# makefiles, they are *not* in batch files or in djgpp.env. +# - - - - - +# [make] +# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include +# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib +# BUTT=-m486 +# - - - - - +# Alternately, these variables may be defined below, overriding the values +# in djgpp.env, as +# INCLUDE_PATH=c:\usr\include +# LIBRARY_PATH=c:\usr\lib + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lz +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + +# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . + +.PHONY : uninstall clean + +install: $(INCL) $(LIBS) + -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) + -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) + $(INSTALL) zlib.h $(INCLUDE_PATH) + $(INSTALL) zconf.h $(INCLUDE_PATH) + $(INSTALL) libz.a $(LIBRARY_PATH) + +uninstall: + $(RM) $(INCLUDE_PATH)\zlib.h + $(RM) $(INCLUDE_PATH)\zconf.h + $(RM) $(LIBRARY_PATH)\libz.a + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) libz.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/drivers/lib/zlib/msdos/Makefile.emx b/drivers/lib/zlib/msdos/Makefile.emx new file mode 100644 index 0000000..0e5e5cc --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/drivers/lib/zlib/msdos/Makefile.msc b/drivers/lib/zlib/msdos/Makefile.msc new file mode 100644 index 0000000..562201d --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.msc @@ -0,0 +1,121 @@ +# Makefile for zlib +# Microsoft C 5.1 or later + +# To use, do "make makefile.msc" +# To compile in small model, set below: MODEL=S + +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Microsoft C 5.1 and later ------------- + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# Memory model: one of S, M, C, L (small, medium, compact, large) +MODEL=L + +CC=cl +CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) +#-Ox generates bad code with MSC 5.1 +LIB_CFLAGS=-Zl $(CFLAGS) + +LD=link +LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode +# "/farcall/packcode" are only useful for `large code' memory models +# but should be a "no-op" for small code models. + +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +ZLIB_H = zlib.h zconf.h +ZUTIL_H = zutil.h $(ZLIB_H) + +ZLIB_LIB = zlib_$(MODEL).lib + +all: $(ZLIB_LIB) example.exe minigzip.exe + +# individual dependencies and action rules: +adler32.obj: adler32.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +compress.obj: compress.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +crc32.obj: crc32.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +gzio.obj: gzio.c $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h + $(CC) -c $(LIB_CFLAGS) $*.c + +infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h + $(CC) -c $(LIB_CFLAGS) $*.c + +inflate.obj: inflate.c $(ZUTIL_H) infblock.h + $(CC) -c $(LIB_CFLAGS) $*.c + +inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h + $(CC) -c $(LIB_CFLAGS) $*.c + +infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h + $(CC) -c $(LIB_CFLAGS) $*.c + +inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h + $(CC) -c $(LIB_CFLAGS) $*.c + +trees.obj: trees.c deflate.h $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +uncompr.obj: uncompr.c $(ZLIB_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +zutil.obj: zutil.c $(ZUTIL_H) + $(CC) -c $(LIB_CFLAGS) $*.c + +example.obj: example.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + if exist $(ZLIB_LIB) del $(ZLIB_LIB) + lib $(ZLIB_LIB) $(OBJ1); + lib $(ZLIB_LIB) $(OBJ2); + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/drivers/lib/zlib/msdos/Makefile.tc b/drivers/lib/zlib/msdos/Makefile.tc new file mode 100644 index 0000000..63e0550 --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.tc @@ -0,0 +1,108 @@ +# Makefile for zlib +# TurboC 2.0 + +# To use, do "make -fmakefile.tc" +# To compile in small model, set below: MODEL=-ms + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to CFLAGS below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Turbo C 2.0 ------------- +MODEL=l +# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +CFLAGS=-O2 -G -Z -m$(MODEL) +CC=tcc -I\tc\include +LD=tcc -L\tc\lib +AR=tlib +LDFLAGS=-m$(MODEL) -f- +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +ZLIB_H = zlib.h zconf.h +ZUTIL_H = zutil.h $(ZLIB_H) + +ZLIB_LIB = zlib_$(MODEL).lib + +all: test + +adler32.obj: adler32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c $(ZUTIL_H) infblock.h inftrees.h infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c $(ZUTIL_H) inftrees.h infutil.h infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c $(ZUTIL_H) infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c $(ZUTIL_H) inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c $(ZUTIL_H) inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c $(ZUTIL_H) inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c $(ZUTIL_H) + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c $(ZLIB_H) + $(CC) -c $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) +$(OBJP1) + $(AR) $(ZLIB_LIB) +$(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) -eexample.exe example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) -eminigzip.exe minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/drivers/lib/zlib/msdos/Makefile.w32 b/drivers/lib/zlib/msdos/Makefile.w32 new file mode 100644 index 0000000..0a05fa9 --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.w32 @@ -0,0 +1,97 @@ +# Makefile for zlib +# Microsoft 32-bit Visual C++ 4.0 or later (may work on earlier versions) + +# To use, do "nmake /f makefile.w32" + +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to CFLAGS below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Microsoft Visual C++ 4.0 and later ------------- +MODEL= +CFLAGS=-Ox -GA3s -nologo -W3 +CC=cl +LD=link +LDFLAGS= +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJP1 = adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O)+\ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) +OBJP2 = zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O)+\ + infutil$(O)+inffast$(O) + +all: zlib.lib example.exe minigzip.exe + +adler32.obj: adler32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +crc32.obj: crc32.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h\ + infcodes.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h\ + infcodes.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) -c $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) -c $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) -c $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) -c $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +zlib.lib: $(OBJ1) $(OBJ2) + if exist zlib.lib del zlib.lib + lib /OUT:zlib.lib $(OBJ1) $(OBJ2) + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib /OUT:example.exe /SUBSYSTEM:CONSOLE + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib /OUT:minigzip.exe /SUBSYSTEM:CONSOLE + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +#clean: +# del *.obj +# del *.exe diff --git a/drivers/lib/zlib/msdos/Makefile.wat b/drivers/lib/zlib/msdos/Makefile.wat new file mode 100644 index 0000000..44bf860 --- /dev/null +++ b/drivers/lib/zlib/msdos/Makefile.wat @@ -0,0 +1,103 @@ +# Makefile for zlib +# Watcom 10a + +# This version of the zlib makefile was adapted by Chris Young for use +# with Watcom 10a 32-bit protected mode flat memory model. It was created +# for use with POV-Ray ray tracer and you may choose to edit the CFLAGS to +# suit your needs but the -DMSDOS is required. +# -- Chris Young 76702.1655@compuserve.com + +# To use, do "wmake -f makefile.wat" + +# See zconf.h for details about the memory requirements. + +# ------------- Watcom 10a ------------- +MODEL=-mf +CFLAGS= $(MODEL) -fpi87 -fp5 -zp4 -5r -w5 -oneatx -DMSDOS +CC=wcc386 +LD=wcl386 +LIB=wlib -b -c +LDFLAGS= +O=.obj + +# variables +OBJ1=adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) +OBJ2=trees$(O) zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) +OBJ3=infutil$(O) inffast$(O) +OBJP1=adler32$(O)+compress$(O)+crc32$(O)+gzio$(O)+uncompr$(O)+deflate$(O) +OBJP2=trees$(O)+zutil$(O)+inflate$(O)+infblock$(O)+inftrees$(O)+infcodes$(O) +OBJP3=infutil$(O)+inffast$(O) + +all: test + +adler32.obj: adler32.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +crc32.obj: crc32.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h & + infcodes.h infutil.h + $(CC) $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h & + infcodes.h inffast.h + $(CC) $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) $(CFLAGS) $*.c + +# we must cut the command line to fit in the MS/DOS 128 byte limit: +zlib.lib: $(OBJ1) $(OBJ2) $(OBJ3) + del zlib.lib + $(LIB) zlib.lib +$(OBJP1) + $(LIB) zlib.lib +$(OBJP2) + $(LIB) zlib.lib +$(OBJP3) + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib + +test: minigzip.exe example.exe + example + echo hello world | minigzip | minigzip -d >test + type test + +#clean: +# del *.obj +# del *.exe diff --git a/drivers/lib/zlib/msdos/zlib.def b/drivers/lib/zlib/msdos/zlib.def new file mode 100644 index 0000000..6c04412 --- /dev/null +++ b/drivers/lib/zlib/msdos/zlib.def @@ -0,0 +1,60 @@ +LIBRARY "zlib" + +DESCRIPTION '"""zlib data compression library"""' + +EXETYPE NT + +SUBSYSTEM WINDOWS + +STUB 'WINSTUB.EXE' + +VERSION 1.13 + +CODE EXECUTE READ + +DATA READ WRITE + +HEAPSIZE 1048576,4096 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 diff --git a/drivers/lib/zlib/msdos/zlib.rc b/drivers/lib/zlib/msdos/zlib.rc new file mode 100644 index 0000000..556d4ff --- /dev/null +++ b/drivers/lib/zlib/msdos/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1,1,3,0 + PRODUCTVERSION 1,1,3,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression library\0" + VALUE "FileVersion", "1.1.3\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlib.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-1998 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/drivers/lib/zlib/nt/Makefile.emx b/drivers/lib/zlib/nt/Makefile.emx new file mode 100644 index 0000000..2d475b1 --- /dev/null +++ b/drivers/lib/zlib/nt/Makefile.emx @@ -0,0 +1,138 @@ +# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc -Zwin32 + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif +# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/drivers/lib/zlib/nt/Makefile.gcc b/drivers/lib/zlib/nt/Makefile.gcc new file mode 100644 index 0000000..cdd652f --- /dev/null +++ b/drivers/lib/zlib/nt/Makefile.gcc @@ -0,0 +1,87 @@ +# Makefile for zlib. Modified for mingw32 by C. Spieler, 6/16/98. +# (This Makefile is directly derived from Makefile.dj2) +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.gcc; make test -fmakefile.gcc +# +# To install libz.a, zconf.h and zlib.h in the mingw32 directories, type: +# +# make install -fmakefile.gcc +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DDEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lz +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libz.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + +# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . + +.PHONY : uninstall clean + +install: $(INCL) $(LIBS) + -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) + -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) + $(INSTALL) zlib.h $(INCLUDE_PATH) + $(INSTALL) zconf.h $(INCLUDE_PATH) + $(INSTALL) libz.a $(LIBRARY_PATH) + +uninstall: + $(RM) $(INCLUDE_PATH)\zlib.h + $(RM) $(INCLUDE_PATH)\zconf.h + $(RM) $(LIBRARY_PATH)\libz.a + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) libz.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/drivers/lib/zlib/nt/Makefile.nt b/drivers/lib/zlib/nt/Makefile.nt new file mode 100644 index 0000000..b250f2a --- /dev/null +++ b/drivers/lib/zlib/nt/Makefile.nt @@ -0,0 +1,88 @@ +# Makefile for zlib + +!include + +CC=cl +LD=link +CFLAGS=-O -nologo +LDFLAGS= +O=.obj + +# variables +OBJ1 = adler32$(O) compress$(O) crc32$(O) gzio$(O) uncompr$(O) deflate$(O) \ + trees$(O) +OBJ2 = zutil$(O) inflate$(O) infblock$(O) inftrees$(O) infcodes$(O) \ + infutil$(O) inffast$(O) + +all: zlib.dll example.exe minigzip.exe + +adler32.obj: adler32.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +compress.obj: compress.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +crc32.obj: crc32.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +gzio.obj: gzio.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +infblock.obj: infblock.c zutil.h zlib.h zconf.h infblock.h inftrees.h\ + infcodes.h infutil.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +infcodes.obj: infcodes.c zutil.h zlib.h zconf.h inftrees.h infutil.h\ + infcodes.h inffast.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +inflate.obj: inflate.c zutil.h zlib.h zconf.h infblock.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +infutil.obj: infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +trees.obj: trees.c deflate.h zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +uncompr.obj: uncompr.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +example.obj: example.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +minigzip.obj: minigzip.c zlib.h zconf.h + $(CC) -c $(cvarsdll) $(CFLAGS) $*.c + +zlib.dll: $(OBJ1) $(OBJ2) zlib.dnt + link $(dlllflags) -out:$@ -def:zlib.dnt $(OBJ1) $(OBJ2) $(guilibsdll) + +zlib.lib: zlib.dll + +example.exe: example.obj zlib.lib + $(LD) $(LDFLAGS) example.obj zlib.lib + +minigzip.exe: minigzip.obj zlib.lib + $(LD) $(LDFLAGS) minigzip.obj zlib.lib + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + del *.obj + del *.exe + del *.dll + del *.lib diff --git a/drivers/lib/zlib/nt/zlib.dnt b/drivers/lib/zlib/nt/zlib.dnt new file mode 100644 index 0000000..7f9475c --- /dev/null +++ b/drivers/lib/zlib/nt/zlib.dnt @@ -0,0 +1,47 @@ +LIBRARY zlib.dll +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 diff --git a/drivers/lib/zlib/os2/Makefile.os2 b/drivers/lib/zlib/os2/Makefile.os2 new file mode 100644 index 0000000..4f56947 --- /dev/null +++ b/drivers/lib/zlib/os2/Makefile.os2 @@ -0,0 +1,136 @@ +# Makefile for zlib under OS/2 using GCC (PGCC) +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# cp Makefile.os2 .. +# cd .. +# make -f Makefile.os2 test + +# This makefile will build a static library z.lib, a shared library +# z.dll and a import library zdll.lib. You can use either z.lib or +# zdll.lib by specifying either -lz or -lzdll on gcc's command line + +CC=gcc -Zomf -s + +CFLAGS=-O6 -Wall +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DDEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +#################### BUG WARNING: ##################### +## infcodes.c hits a bug in pgcc-1.0, so you have to use either +## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) +## This bug is reportedly fixed in pgcc >1.0, but this was not tested +CFLAGS+=-fno-force-mem + +LDFLAGS=-s -L. -lzdll -Zcrtdll +LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll + +VER=1.1.0 +ZLIB=z.lib +SHAREDLIB=z.dll +SHAREDLIBIMP=zdll.lib +LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) + +AR=emxomfar cr +IMPLIB=emximp +RANLIB=echo +TAR=tar +SHELL=bash + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ + algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ + contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 + +all: example.exe minigzip.exe + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +$(ZLIB): $(OBJS) + $(AR) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +$(SHAREDLIB): $(OBJS) os2/z.def + $(LDSHARED) -o $@ $^ + +$(SHAREDLIBIMP): os2/z.def + $(IMPLIB) -o $@ $^ + +example.exe: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip.exe: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/drivers/lib/zlib/os2/zlib.def b/drivers/lib/zlib/os2/zlib.def new file mode 100644 index 0000000..4c753f1 --- /dev/null +++ b/drivers/lib/zlib/os2/zlib.def @@ -0,0 +1,51 @@ +; +; Slightly modified version of ../nt/zlib.dnt :-) +; + +LIBRARY Z +DESCRIPTION "Zlib compression library for OS/2" +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +EXPORTS + adler32 + compress + crc32 + deflate + deflateCopy + deflateEnd + deflateInit2_ + deflateInit_ + deflateParams + deflateReset + deflateSetDictionary + gzclose + gzdopen + gzerror + gzflush + gzopen + gzread + gzwrite + inflate + inflateEnd + inflateInit2_ + inflateInit_ + inflateReset + inflateSetDictionary + inflateSync + uncompress + zlibVersion + gzprintf + gzputc + gzgetc + gzseek + gzrewind + gztell + gzeof + gzsetparams + zError + inflateSyncPoint + get_crc_table + compress2 + gzputs + gzgets diff --git a/drivers/lib/zlib/trees.c b/drivers/lib/zlib/trees.c new file mode 100644 index 0000000..0a98405 --- /dev/null +++ b/drivers/lib/zlib/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/drivers/lib/zlib/trees.h b/drivers/lib/zlib/trees.h new file mode 100644 index 0000000..72facf9 --- /dev/null +++ b/drivers/lib/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/drivers/lib/zlib/uncompr.c b/drivers/lib/zlib/uncompr.c new file mode 100644 index 0000000..a287714 --- /dev/null +++ b/drivers/lib/zlib/uncompr.c @@ -0,0 +1,58 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/drivers/lib/zlib/zconf.h b/drivers/lib/zlib/zconf.h new file mode 100644 index 0000000..eb0ae2e --- /dev/null +++ b/drivers/lib/zlib/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/drivers/lib/zlib/zlib.3 b/drivers/lib/zlib/zlib.3 new file mode 100644 index 0000000..3a6e450 --- /dev/null +++ b/drivers/lib/zlib/zlib.3 @@ -0,0 +1,107 @@ +.TH ZLIB 3 "11 March 2002" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms will be added later and will have the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +(for example if an input file is mmap'ed), +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.I gzip +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. The decoder checks +the consistency of the compressed data, so the library should never +crash even in case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h. +The distribution source includes examples of use of the library +the files +.I example.c +and +.IR minigzip.c . +.LP +A Java implementation of +.IR zlib +is available in the Java Development Kit 1.1 +.IP +http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html +.LP +A Perl interface to +.IR zlib , +written by Paul Marquess (pmarquess@bfsec.bt.co.uk) +is available at CPAN (Comprehensive Perl Archive Network) sites, +such as: +.IP +ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib* +.LP +A Python interface to +.IR zlib +written by A.M. Kuchling +is available from the Python Software Association sites, such as: +.IP +ftp://ftp.python.org/pub/python/contrib/Encoding/zlib*.tar.gz +.SH "SEE ALSO" +Questions about zlib should be sent to: +.IP +zlib@quest.jpl.nasa.gov +or, if this fails, to the author addresses given below. +The zlib home page is: +.IP +http://www.cdrom.com/pub/infozip/zlib/ +.LP +The data format used by the zlib library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +ftp://ds.internic.net/rfc/rfc1950.txt (zlib format) +.br +rfc1951.txt (deflate format) +.br +rfc1952.txt (gzip format) +.LP +These documents are also available in other formats from: +.IP +ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html +.SH AUTHORS +Version 1.1.4 +Copyright (C) 1995-2002 Jean-loup Gailly (jloup@gzip.org) +and Mark Adler (madler@alumni.caltech.edu). +.LP +This software is provided "as-is," +without any express or implied warranty. +In no event will the authors be held liable for any damages +arising from the use of this software. +See the distribution directory with respect to requirements +governing redistribution. +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/drivers/lib/zlib/zlib.h b/drivers/lib/zlib/zlib.h new file mode 100644 index 0000000..52cb529 --- /dev/null +++ b/drivers/lib/zlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/drivers/lib/zlib/zlib.html b/drivers/lib/zlib/zlib.html new file mode 100644 index 0000000..c343703 --- /dev/null +++ b/drivers/lib/zlib/zlib.html @@ -0,0 +1,971 @@ + + + + zlib general purpose compression library version 1.1.4 + + + + + +

zlib 1.1.4 Manual

+
+

Contents

+
    +
  1. Prologue +
  2. Introduction +
  3. Utility functions +
  4. Basic functions +
  5. Advanced functions +
  6. Constants +
  7. struct z_stream_s +
  8. Checksum functions +
  9. Misc +
+
+

Prologue

+ 'zlib' general purpose compression library version 1.1.4, March 11th, 2002 +

+ Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler +

+ This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. +

+ Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: +

    +
  1. The origin of this software must not be misrepresented ; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +
  2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +
  3. This notice may not be removed or altered from any source distribution. +
+ +
+
Jean-loup Gailly +
jloup@gzip.org +
Mark Adler +
madler@alumni.caltech.edu +
+ + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files + + ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), + + rfc1951.txt + (deflate format) and + + rfc1952.txt + (gzip format). +

+ This manual is converted from zlib.h by + piaip +

+ Visit + http://ftp.cdrom.com/pub/infozip/zlib/ + for the official zlib web page. +

+ +


+

Introduction

+ The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. +

+ + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. +

+ + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. +

+ + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +

+ +


+

Utility functions

+ The following utility functions are implemented on top of the +
basic stream-oriented functions. + To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +

Function list

+
    +
  • int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
  • int compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); +
  • int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
  • typedef voidp gzFile; +
  • gzFile gzopen (const char *path, const char *mode); +
  • gzFile gzdopen (int fd, const char *mode); +
  • int gzsetparams (gzFile file, int level, int strategy); +
  • int gzread (gzFile file, voidp buf, unsigned len); +
  • int gzwrite (gzFile file, const voidp buf, unsigned len); +
  • int VA gzprintf (gzFile file, const char *format, ...); +
  • int gzputs (gzFile file, const char *s); +
  • char * gzgets (gzFile file, char *buf, int len); +
  • int gzputc (gzFile file, int c); +
  • int gzgetc (gzFile file); +
  • int gzflush (gzFile file, int flush); +
  • z_off_t gzseek (gzFile file, z_off_t offset, int whence); +
  • z_off_t gztell (gzFile file); +
  • int gzrewind (gzFile file); +
  • int gzeof (gzFile file); +
  • int gzclose (gzFile file); +
  • const char * gzerror (gzFile file, int *errnum); +
+

Function description

+
+
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
+ Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer.

+ This function can be used to compress a whole file at once if the + input file is mmap'ed.

+ compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer.

+ +

int compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); +
+ Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. +

+ + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +

+ +

int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +
+ Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer.

+ This function can be used to decompress a whole file at once if the + input file is mmap'ed. +

+ + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +

+ +

typedef voidp gzFile; +

+ +

gzFile gzopen (const char *path, const char *mode); +
+ Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) +

+ + gzopen can be used to read a file which is not in gzip format ; in this + case gzread will directly read from the file without decompression. +

+ + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state ; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +

+ +

gzFile gzdopen (int fd, const char *mode); +
+ gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. +

+ The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). +

+ gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +

+ +

int gzsetparams (gzFile file, int level, int strategy); +
+ Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. +

+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +

+ +

int gzread (gzFile file, voidp buf, unsigned len); +
+ Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. +

+ gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). +

+ +

int gzwrite (gzFile file, const voidp buf, unsigned len); +
+ Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +

+ +

int VA gzprintf (gzFile file, const char *format, ...); +
+ Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +

+ +

int gzputs (gzFile file, const char *s); +
+ Writes the given null-terminated string to the compressed file, excluding + the terminating null character. +

+ gzputs returns the number of characters written, or -1 in case of error. +

+ +

char * gzgets (gzFile file, char *buf, int len); +
+ Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. +

+ gzgets returns buf, or Z_NULL in case of error. +

+ +

int gzputc (gzFile file, int c); +
+ Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +

+ +

int gzgetc (gzFile file); +
+ Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +

+ +

int gzflush (gzFile file, int flush); +
+ Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. +

+ gzflush should be called only when strictly necessary because it can + degrade compression. +

+ +

z_off_t gzseek (gzFile file, z_off_t offset, int whence); +
+ Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. +

+ If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported ; gzseek then compresses a sequence of zeroes up to the new + starting position. +

+ gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +

+ +

int gzrewind (gzFile file); +
+ Rewinds the given file. This function is supported only for reading. +

+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +

+ +

z_off_t gztell (gzFile file); +
+ Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +

+ + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +

+ +

int gzeof (gzFile file); +
+ Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +

+ +

int gzclose (gzFile file); +
+ Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +

+ +

const char * gzerror (gzFile file, int *errnum); +
+ Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +

+

+
+

Basic functions

+

Function list

+
+ +

Function description

+
+
const char * zlibVersion (void); +
The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. +

+ +

int deflateInit (z_streamp strm, int level); +
+ Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. +

+ + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). +

+ + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). +

+ + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +

+ +

int deflate (z_streamp strm, int flush); +
+ deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush.

+ + The detailed semantics are as follows. deflate performs one or both of the + following actions: + +

    +
  • Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + +
  • + Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. +

+ + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly ; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. +

+ + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. +

+ + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. +

+ + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). +

+ + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space ; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. +

+ + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. +

+ + deflate() sets strm-> adler to the adler32 checksum of all input read + so far (that is, total_in bytes). +

+ + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. +

+ + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +

+ +

int deflateEnd (z_streamp strm); +
+ All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. +

+ + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +

+ +

int inflateInit (z_streamp strm); +
+ Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly ; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. +

+ + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +

+ +

int inflate (z_streamp strm, int flush); +
+ inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. +

+ + The detailed semantics are as follows. inflate performs one or both of the + following actions: + +

    +
  • Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + +
  • Provide more output starting at next_out and update next_out and + avail_out accordingly. inflate() provides as much output as possible, + until there is no more input data or no more space in the output buffer + (see below about the flush parameter). +

+ + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. +

+ + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. +

+ + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed ; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. +

+ + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT ; otherwise + it sets strm-> adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. +

+ + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +

+ +

int inflateEnd (z_streamp strm); +
+ All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. +

+ + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +

+
+

Advanced functions

+ The following functions are needed only in some special applications. +

Function list

+
+

Function description

+
+
int deflateInit2 (z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy); + +
This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller.

+ + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library.

+ + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead.

+ + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio ; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel.

+ + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching ; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately.

+ + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate().

+ +

int deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength); +
+ Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary).

+ + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy ; the data can then be compressed better than + with the default empty dictionary.

+ + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front.

+ + Upon return of this function, strm-> adler is set to the Adler32 value + of the dictionary ; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.)

+ + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate().

+ +

int deflateCopy (z_streamp dest, z_streamp source); +
+ Sets the destination stream as a complete copy of the source stream.

+ + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory.

+ + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination.

+ +

int deflateReset (z_streamp strm); +
This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2.

+ + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL).

+ +

int deflateParams (z_streamp strm, int level, int strategy); +
+ Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate().

+ + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm-> avail_out must be + non-zero.

+ + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero.

+ +

int inflateInit2 (z_streamp strm, int windowBits); + +
This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller.

+ + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window.

+ + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.)

+ +

int inflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength); +
+ Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary).

+ + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate().

+ +

int inflateSync (z_streamp strm); + +
Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided.

+ + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data.

+ +

int inflateReset (z_streamp strm); +
+ This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. +

+ + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +

+

+ +
+

Checksum functions

+ These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +

Function list

+
+

Function description

+
+
uLong adler32 (uLong adler, const Bytef *buf, uInt len); +
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. +

+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: +

+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+   
+ +
uLong crc32 (uLong crc, const Bytef *buf, uInt len); +
+ Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: +
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+   
+
+
+

struct z_stream_s

+ +
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream ;
+
+typedef z_stream FAR * z_streamp;  ÿ 
+
+
+ The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application.

+ + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value.

+ + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe.

+ + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). +

+ + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step).

+ +


+

Constants

+ +
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 
+	/* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values ; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy ; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions less than 1.0.2 */
+
+
+ +
+

Misc

+
deflateInit and inflateInit are macros to allow checking the zlib version + and the compiler's view of z_stream. +

+ Other functions: +

+
const char * zError (int err); +
int inflateSyncPoint (z_streamp z); +
const uLongf * get_crc_table (void); +
+
+ + Last update: Wed Oct 13 20:42:34 1999
+ piapi@csie.ntu.edu.tw +
+ + + diff --git a/drivers/lib/zlib/zutil.c b/drivers/lib/zlib/zutil.c new file mode 100644 index 0000000..dfc38ec --- /dev/null +++ b/drivers/lib/zlib/zutil.c @@ -0,0 +1,225 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/drivers/lib/zlib/zutil.h b/drivers/lib/zlib/zutil.h new file mode 100644 index 0000000..718ebc1 --- /dev/null +++ b/drivers/lib/zlib/zutil.h @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/drivers/net/afd/.cvsignore b/drivers/net/afd/.cvsignore new file mode 100644 index 0000000..4592925 --- /dev/null +++ b/drivers/net/afd/.cvsignore @@ -0,0 +1 @@ +afd.coff \ No newline at end of file diff --git a/drivers/net/afd/afd.def b/drivers/net/afd/afd.def new file mode 100644 index 0000000..c83c3a9 --- /dev/null +++ b/drivers/net/afd/afd.def @@ -0,0 +1,7 @@ +; Ancillary Function Driver - ReactOS Operating System + +LIBRARY AFDTEST.SYS + +EXPORTS + +; EOF diff --git a/drivers/net/afd/afd.rc b/drivers/net/afd/afd.rc new file mode 100644 index 0000000..65281ec --- /dev/null +++ b/drivers/net/afd/afd.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Ancillary Function Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "afd\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "afd.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/net/afd/afd/afd.c b/drivers/net/afd/afd/afd.c new file mode 100644 index 0000000..845272b --- /dev/null +++ b/drivers/net/afd/afd/afd.c @@ -0,0 +1,202 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/afd.c + * PURPOSE: MSAFD kernel mode module + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MIN_TRACE; +//DWORD DebugTraceLevel = DEBUG_ULTRA; + +#endif /* DBG */ + + +NPAGED_LOOKASIDE_LIST BufferLookasideList; +NPAGED_LOOKASIDE_LIST ReadRequestLookasideList; + + +NTSTATUS +STDCALL +AfdFileSystemControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + UNIMPLEMENTED + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + return STATUS_UNSUCCESSFUL; +} + + +NTSTATUS +STDCALL +AfdDispatch( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: IOCTL dispatch routine + * ARGUMENTS: + * DeviceObject = Pointer to a device object for this driver + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of the operation + */ +{ + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + AFD_DbgPrint(MAX_TRACE, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X), IrpSp->FileObject (0x%X).\n", + DeviceObject, Irp, IrpSp->FileObject)); + + Irp->IoStatus.Information = 0; + + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { + case IOCTL_AFD_BIND: + Status = AfdDispBind(Irp, IrpSp); + break; + + case IOCTL_AFD_LISTEN: + Status = AfdDispListen(Irp, IrpSp); + break; + + case IOCTL_AFD_SENDTO: + Status = AfdDispSendTo(Irp, IrpSp); + break; + + case IOCTL_AFD_RECVFROM: + Status = AfdDispRecvFrom(Irp, IrpSp); + break; + + case IOCTL_AFD_SELECT: + Status = AfdDispSelect(Irp, IrpSp); + break; + + case IOCTL_AFD_EVENTSELECT: + Status = AfdDispEventSelect(Irp, IrpSp); + break; + + case IOCTL_AFD_ENUMNETWORKEVENTS: + Status = AfdDispEnumNetworkEvents(Irp, IrpSp); + break; + + case IOCTL_AFD_RECV: + Status = AfdDispRecv(Irp, IrpSp); + break; + + case IOCTL_AFD_SEND: + Status = AfdDispSend(Irp, IrpSp); + break; + + case IOCTL_AFD_CONNECT: + Status = AfdDispConnect(Irp, IrpSp); + break; + + default: + AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%X).\n", + IrpSp->Parameters.DeviceIoControl.IoControlCode)); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + } + + AFD_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status)); + + return Status; +} + + +VOID AfdUnload( + PDRIVER_OBJECT DriverObject) +/* + * FUNCTION: Unloads the driver + * ARGUMENTS: + * DriverObject = Pointer to driver object created by the system + */ +{ +} + + +NTSTATUS +STDCALL +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Called by the system to initialize the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: + * Status of operation + */ +{ + PDEVICE_EXTENSION DeviceExt; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\Afd"); + NTSTATUS Status; + + Status = IoCreateDevice(DriverObject, + sizeof(DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_NAMED_PIPE, + 0, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE, ("Could not create device (0x%X).\n", Status)); + return Status; + } + + DeviceObject->Flags |= DO_DIRECT_IO; + + DeviceExt = DeviceObject->DeviceExtension; + KeInitializeSpinLock(&DeviceExt->FCBListLock); + InitializeListHead(&DeviceExt->FCBListHead); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdClose; + DriverObject->MajorFunction[IRP_MJ_READ] = AfdRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdWrite; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = AfdFileSystemControl; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdClose; + + DriverObject->DriverUnload = (PDRIVER_UNLOAD)AfdUnload; + +/* ExInitializeNPagedLookasideList( + &BufferLookasideList, + NULL, + NULL, + 0, + sizeof(AFD_BUFFER), + TAG('A', 'F', 'D', 'B'), + 0);*/ + +/* ExInitializeNPagedLookasideList( + &ReadRequestLookasideList, + NULL, + NULL, + 0, + sizeof(AFD_READ_REQUEST), + TAG('A', 'F', 'D', 'R'), + 0);*/ + + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/afd/afd/dispatch.c b/drivers/net/afd/afd/dispatch.c new file mode 100644 index 0000000..40b9c87 --- /dev/null +++ b/drivers/net/afd/afd/dispatch.c @@ -0,0 +1,843 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/dispatch.c + * PURPOSE: File object dispatch functions + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +NTSTATUS AfdpDispRecv( + PIRP Irp, + PAFDFCB FCB, + PFILE_REQUEST_RECVFROM Request, + PFILE_REPLY_RECVFROM Reply) +/* + * FUNCTION: Receives data + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * FCB = Pointer to file control block + * Request = Address of request buffer + * Reply = Address of reply buffer (same as request buffer) + * RETURNS: + * Status of operation + */ +{ + PAFD_READ_REQUEST ReadRequest; + NTSTATUS Status; + KIRQL OldIrql; + ULONG Count; + + KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql); + if (IsListEmpty(&FCB->ReceiveQueue)) { + KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql); + + /* Queue a read request and return STATUS_PENDING */ + + AFD_DbgPrint(MAX_TRACE, ("Queueing read request.\n")); + + /*ReadRequest = (PAFD_READ_REQUEST)ExAllocateFromNPagedLookasideList( + &ReadRequestLookasideList);*/ + ReadRequest = (PAFD_READ_REQUEST)ExAllocatePool( + NonPagedPool, + sizeof(AFD_READ_REQUEST)); + if (ReadRequest) { + ReadRequest->Irp = Irp; + ReadRequest->RecvFromRequest = Request; + ReadRequest->RecvFromReply = Reply; + + ExInterlockedInsertTailList( + &FCB->ReadRequestQueue, + &ReadRequest->ListEntry, + &FCB->ReadRequestQueueLock); + Status = STATUS_PENDING; + } else { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } else { + AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n")); + + /* Satisfy the request at once */ + Status = FillWSABuffers( + FCB, + Request->Buffers, + Request->BufferCount, + &Count); + KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql); + + Reply->NumberOfBytesRecvd = Count; + Reply->Status = NO_ERROR; + + AFD_DbgPrint(MAX_TRACE, ("Bytes received (0x%X).\n", Count)); + } + + return Status; +} + + +NTSTATUS AfdDispBind( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Binds to an address + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_BIND Request; + PFILE_REPLY_BIND Reply; + PAFDFCB FCB; + INT Errno; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_BIND)) && + (OutputBufferLength >= sizeof(FILE_REPLY_BIND))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_BIND)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_BIND)Irp->AssociatedIrp.SystemBuffer; + + Status = TdiOpenAddressFile( + &FCB->TdiDeviceName, + &Request->Name, + &FCB->TdiAddressObjectHandle, + &FCB->TdiAddressObject); + + if (NT_SUCCESS(Status)) { + AfdRegisterEventHandlers(FCB); + FCB->State = SOCKET_STATE_BOUND; + Reply->Status = NO_ERROR; + } else { + //FIXME: WSAEADDRNOTAVAIL + Reply->Status = WSAEINVAL; + } + } else + Status = STATUS_INVALID_PARAMETER; + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS AfdDispListen( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Starts listening for connections + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_LISTEN Request; + PFILE_REPLY_LISTEN Reply; + PAFDFCB FCB; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + Status = STATUS_INVALID_PARAMETER; + if ((InputBufferLength >= sizeof(FILE_REQUEST_LISTEN)) && + (OutputBufferLength >= sizeof(FILE_REPLY_LISTEN))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_LISTEN)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_LISTEN)Irp->AssociatedIrp.SystemBuffer; + + if (FCB->State == SOCKET_STATE_BOUND) { + + /* We have a bound socket so go ahead and create a connection endpoint + and associate it with the address file object */ + + Status = TdiOpenConnectionEndpointFile( + &FCB->TdiDeviceName, + &FCB->TdiConnectionObjectHandle, + &FCB->TdiConnectionObject); + + if (NT_SUCCESS(Status)) { + Status = TdiAssociateAddressFile( + FCB->TdiAddressObjectHandle, + FCB->TdiConnectionObject); + } + + if (NT_SUCCESS(Status)) { + Reply->Status = NO_ERROR; + } else { + Reply->Status = WSAEINVAL; + } + } else if (FCB->State == SOCKET_STATE_CONNECTED) { + Reply->Status = WSAEISCONN; + } else { + Reply->Status = WSAEINVAL; + } + } + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS AfdDispSendTo( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Sends data to an address + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_SENDTO Request; + PFILE_REPLY_SENDTO Reply; + PAFDFCB FCB; + PVOID SystemVirtualAddress; + PVOID DataBufferAddress; + ULONG BufferSize; + ULONG BytesCopied; + PMDL Mdl; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_SENDTO)) && + (OutputBufferLength >= sizeof(FILE_REPLY_SENDTO))) { + + AFD_DbgPrint(MAX_TRACE, ("FileObject at (0x%X).\n", IrpSp->FileObject)); + AFD_DbgPrint(MAX_TRACE, ("FCB at (0x%X).\n", IrpSp->FileObject->FsContext)); + AFD_DbgPrint(MAX_TRACE, ("CCB at (0x%X).\n", IrpSp->FileObject->FsContext2)); + + FCB = IrpSp->FileObject->FsContext; + Request = (PFILE_REQUEST_SENDTO)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_SENDTO)Irp->AssociatedIrp.SystemBuffer; + + /* Since we're using bufferred I/O */ + Request->Buffers = (LPWSABUF)(Request + 1); + BufferSize = WSABufferSize(Request->Buffers, Request->BufferCount); + + + /* FIXME: Should we handle special cases here? */ + if ((FCB->SocketType == SOCK_RAW) && (FCB->AddressFamily == AF_INET)) { + BufferSize += sizeof(IPv4_HEADER); + } + + + if (BufferSize != 0) { + AFD_DbgPrint(MAX_TRACE, ("Allocating %d bytes for send buffer.\n", BufferSize)); + SystemVirtualAddress = ExAllocatePool(NonPagedPool, BufferSize); + if (!SystemVirtualAddress) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* FIXME: Should we handle special cases here? */ + if ((FCB->SocketType == SOCK_RAW) && (FCB->AddressFamily == AF_INET)) { + DataBufferAddress = SystemVirtualAddress + sizeof(IPv4_HEADER); + + /* FIXME: Should TCP/IP driver assign source address for raw sockets? */ + ((PSOCKADDR_IN)&FCB->SocketName)->sin_addr.S_un.S_addr = 0x0100007F; + + BuildIPv4Header( + (PIPv4_HEADER)SystemVirtualAddress, + BufferSize, + FCB->Protocol, + &FCB->SocketName, + &Request->To); + } else { + DataBufferAddress = SystemVirtualAddress; + } + + Status = MergeWSABuffers( + Request->Buffers, + Request->BufferCount, + DataBufferAddress, + BufferSize, + &BytesCopied); + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + return Status; + } + } else { + SystemVirtualAddress = NULL; + BytesCopied = 0; + } + + Mdl = IoAllocateMdl( + SystemVirtualAddress, /* Virtual address of buffer */ + BufferSize, /* Length of buffer */ + FALSE, /* Not secondary */ + FALSE, /* Don't charge quota */ + NULL); /* Don't use IRP */ + if (!Mdl) { + ExFreePool(SystemVirtualAddress); + return STATUS_INSUFFICIENT_RESOURCES; + } + + MmBuildMdlForNonPagedPool(Mdl); + + AFD_DbgPrint(MAX_TRACE, ("System virtual address is (0x%X).\n", SystemVirtualAddress)); + AFD_DbgPrint(MAX_TRACE, ("MDL for data buffer is at (0x%X).\n", Mdl)); + + AFD_DbgPrint(MAX_TRACE, ("AFD.SYS: NDIS data buffer is at (0x%X).\n", Mdl)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer MdlFlags is (0x%X).\n", Mdl->MdlFlags)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer Next is at (0x%X).\n", Mdl->Next)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer Size is (0x%X).\n", Mdl->Size)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer MappedSystemVa is (0x%X).\n", Mdl->MappedSystemVa)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer StartVa is (0x%X).\n", Mdl->StartVa)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteCount is (0x%X).\n", Mdl->ByteCount)); + AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteOffset is (0x%X).\n", Mdl->ByteOffset)); + +#if 0 +#ifdef _MSC_VER + try { +#endif + MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); +#ifdef _MSC_VER + } except(EXCEPTION_EXECUTE_HANDLER) { + AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); + IoFreeMdl(Mdl); + if (BufferSize != 0) { + ExFreePool(SystemVirtualAddress); + } + return STATUS_UNSUCCESSFUL; + } +#endif +#endif + + Status = TdiSendDatagram(FCB->TdiAddressObject, + &Request->To, + Mdl, + BufferSize); + + /* FIXME: Assumes synchronous operation */ +#if 0 + MmUnlockPages(Mdl); +#endif + + IoFreeMdl(Mdl); + + if (BufferSize != 0) { + ExFreePool(SystemVirtualAddress); + } + + Reply->NumberOfBytesSent = BufferSize; + Reply->Status = NO_ERROR; + } else + Status = STATUS_INVALID_PARAMETER; + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS AfdDispRecvFrom( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Receives data from an address + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_RECVFROM Request; + PFILE_REPLY_RECVFROM Reply; + DWORD NumberOfBytesRecvd; + PAFDFCB FCB; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_RECVFROM)) && + (OutputBufferLength >= sizeof(FILE_REPLY_RECVFROM))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_RECVFROM)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_RECVFROM)Irp->AssociatedIrp.SystemBuffer; + /* Since we're using bufferred I/O */ + Request->Buffers = (LPWSABUF)(Request + 1); + + Status = AfdpDispRecv( + Irp, + FCB, + Request, + Reply); + } else { + Status = STATUS_INVALID_PARAMETER; + } + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +typedef enum { + soRead, + soWrite, + soExcept +} SelectOperation; + + +DWORD AfdpDispSelectEx( + LPFD_SET FDSet, + SelectOperation Operation) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + PAFDFCB Current; + KIRQL OldIrql; + DWORD Count; + ULONG i; + + AFD_DbgPrint(MAX_TRACE, ("FDSet (0x%X) Operation (0x%X).\n", + FDSet, Operation)); + + AFD_DbgPrint(MAX_TRACE, ("FDSet->fd_count (0x%X).\n", FDSet->fd_count)); + + Count = 0; + for (i = 0; i < FDSet->fd_count; i++) { + + AFD_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", FDSet->fd_array[i])); + + Status = ObReferenceObjectByHandle( + (HANDLE)FDSet->fd_array[i], + 0, + IoFileObjectType, + KernelMode, + (PVOID*)&FileObject, + NULL); + if (NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("File object is at (0x%X).\n", FileObject)); + + Current = FileObject->FsContext; + + switch (Operation) { + case soRead: + KeAcquireSpinLock(&Current->ReceiveQueueLock, &OldIrql); + if (!IsListEmpty(&Current->ReceiveQueue)) { + AFD_DbgPrint(MAX_TRACE, ("Socket is readable.\n")); + Count++; + } + KeReleaseSpinLock(&Current->ReceiveQueueLock, OldIrql); + break; + case soWrite: + /* FIXME: How can we check for writability? */ + Count++; + break; + case soExcept: + /* FIXME: What is this? */ + Count++; + break; + } + + ObDereferenceObject(FileObject); + } + } + + return Count; +} + +NTSTATUS AfdDispSelect( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Checks if sockets have data in the receive buffers + * and/or if client can send data + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_SELECT Request; + PFILE_REPLY_SELECT Reply; + DWORD SocketCount; + PAFDFCB FCB; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_SELECT)) && + (OutputBufferLength >= sizeof(FILE_REPLY_SELECT))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_SELECT)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_SELECT)Irp->AssociatedIrp.SystemBuffer; + + AFD_DbgPrint(MAX_TRACE, ("R (0x%X) W (0x%X).\n", + Request->ReadFDSet, Request->WriteFDSet)); + + SocketCount = 0; + + if (Request->WriteFDSet) { + AFD_DbgPrint(MAX_TRACE, ("Write.\n")); + SocketCount += AfdpDispSelectEx(Request->WriteFDSet, soWrite); + } + if (Request->ReadFDSet) { + AFD_DbgPrint(MAX_TRACE, ("Read.\n")); + SocketCount += AfdpDispSelectEx(Request->ReadFDSet, soRead); + } + if (Request->ExceptFDSet) { + SocketCount += AfdpDispSelectEx(Request->ExceptFDSet, soExcept); + } + + AFD_DbgPrint(MAX_TRACE, ("Sockets selected (0x%X).\n", SocketCount)); + + Reply->Status = NO_ERROR; + Reply->SocketCount = SocketCount; + Status = STATUS_SUCCESS; + } else + Status = STATUS_INVALID_PARAMETER; + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + +NTSTATUS AfdDispEventSelect( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Associate an event object with one or more network events + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_EVENTSELECT Request; + PFILE_REPLY_EVENTSELECT Reply; + PAFDFCB FCB; + ULONG i; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_EVENTSELECT)) && + (OutputBufferLength >= sizeof(FILE_REPLY_EVENTSELECT))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer; + + FCB->NetworkEvents.lNetworkEvents = Request->lNetworkEvents; + for (i = 0; i < FD_MAX_EVENTS; i++) { + if ((Request->lNetworkEvents & (1 << i)) > 0) { + FCB->EventObjects[i] = Request->hEventObject; + } else { + /* The effect of any previous call to this function is cancelled */ + FCB->EventObjects[i] = (WSAEVENT)0; + } + } + + Reply->Status = NO_ERROR; + Status = STATUS_SUCCESS; + } else + Status = STATUS_INVALID_PARAMETER; + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + +NTSTATUS AfdDispEnumNetworkEvents( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Reports network events + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_ENUMNETWORKEVENTS Request; + PFILE_REPLY_ENUMNETWORKEVENTS Reply; + HANDLE EventObject; + PAFDFCB FCB; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_ENUMNETWORKEVENTS)) && + (OutputBufferLength >= sizeof(FILE_REPLY_ENUMNETWORKEVENTS))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_ENUMNETWORKEVENTS)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_ENUMNETWORKEVENTS)Irp->AssociatedIrp.SystemBuffer; + + EventObject = (HANDLE)Request->hEventObject; + + RtlCopyMemory( + &Reply->NetworkEvents, + &FCB->NetworkEvents, + sizeof(WSANETWORKEVENTS)); + + RtlZeroMemory( + &FCB->NetworkEvents, + sizeof(WSANETWORKEVENTS)); + + if (EventObject != NULL) { + ZwClearEvent(EventObject); + } + + Reply->Status = NO_ERROR; + Status = STATUS_SUCCESS; + } else + Status = STATUS_INVALID_PARAMETER; + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS AfdDispRecv( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Receives data from an address + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ +#if 0 + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_RECV Request; + PFILE_REPLY_RECV Reply; + DWORD NumberOfBytesRecvd; + PAFDFCB FCB; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_RECV)) && + (OutputBufferLength >= sizeof(FILE_REPLY_RECV))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_RECV)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_RECV)Irp->AssociatedIrp.SystemBuffer; + + Status = AfdpDispRecv( + Irp, + FCB, + Request->Buffers, + Request->BufferCount, + &NumberOfBytesRecvd); + Reply->NumberOfBytesRecvd = NumberOfBytesRecvd; + Reply->Status = NO_ERROR; + } else { + Status = STATUS_INVALID_PARAMETER; + } + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +#else + return STATUS_SUCCESS; +#endif +} + + +NTSTATUS AfdDispSend( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Sends data + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_SEND Request; + PFILE_REPLY_SEND Reply; + PAFDFCB FCB; + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength >= sizeof(FILE_REQUEST_SEND)) && + (OutputBufferLength >= sizeof(FILE_REPLY_SEND))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_SEND)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_SEND)Irp->AssociatedIrp.SystemBuffer; + + Reply->NumberOfBytesSent = 0; + Reply->Status = NO_ERROR; + } else + Status = STATUS_INVALID_PARAMETER; + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS AfdDispConnect( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: Connect to a remote peer + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + UINT InputBufferLength; + UINT OutputBufferLength; + PFILE_REQUEST_CONNECT Request; + PFILE_REPLY_CONNECT Reply; + PAFDFCB FCB; + SOCKADDR_IN LocalAddress; + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + Status = STATUS_INVALID_PARAMETER; + if ((InputBufferLength >= sizeof(FILE_REQUEST_CONNECT)) && + (OutputBufferLength >= sizeof(FILE_REPLY_CONNECT))) { + FCB = IrpSp->FileObject->FsContext; + + Request = (PFILE_REQUEST_CONNECT)Irp->AssociatedIrp.SystemBuffer; + Reply = (PFILE_REPLY_CONNECT)Irp->AssociatedIrp.SystemBuffer; + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + if (FCB->State == SOCKET_STATE_BOUND) { + Reply->Status = WSAEADDRINUSE; + } else if (FCB->State == SOCKET_STATE_CONNECTED) { + Reply->Status = WSAEISCONN; + } else { + /* We have an unbound socket so go ahead and create an address + file object and a connection endpoint and associate the two */ + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + /* FIXME: Get from client */ + LocalAddress.sin_family = AF_INET; + LocalAddress.sin_port = 1700; + LocalAddress.sin_addr.S_un.S_addr = 0x0; /* Dynamically allocate */ + + Status = TdiOpenAddressFile( + &FCB->TdiDeviceName, + (LPSOCKADDR)&LocalAddress, + &FCB->TdiAddressObjectHandle, + &FCB->TdiAddressObject); + + if (NT_SUCCESS(Status)) { + AfdRegisterEventHandlers(FCB); + FCB->State = SOCKET_STATE_BOUND; + } + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + if (NT_SUCCESS(Status)) { + Status = TdiOpenConnectionEndpointFile( + &FCB->TdiDeviceName, + &FCB->TdiConnectionObjectHandle, + &FCB->TdiConnectionObject); + } + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + if (NT_SUCCESS(Status)) { + Status = TdiAssociateAddressFile( + FCB->TdiAddressObjectHandle, + FCB->TdiConnectionObject); + } + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + if (NT_SUCCESS(Status)) { + /* Now attempt to connect to the remote peer */ + Status = TdiConnect( + FCB->TdiConnectionObject, + Request->name); + } + + AFD_DbgPrint(MIN_TRACE, ("\n")); + + if (NT_SUCCESS(Status)) { + FCB->State = SOCKET_STATE_CONNECTED; + Reply->Status = NO_ERROR; + } else { + Reply->Status = WSAEINVAL; + } + } + } + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + +/* EOF */ diff --git a/drivers/net/afd/afd/event.c b/drivers/net/afd/afd/event.c new file mode 100644 index 0000000..729ea22 --- /dev/null +++ b/drivers/net/afd/afd/event.c @@ -0,0 +1,272 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/event.c + * PURPOSE: TDI event handlers + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +NTSTATUS AfdEventError( + IN PVOID TdiEventContext, + IN NTSTATUS Status) +{ + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + return STATUS_SUCCESS; +} + + +NTSTATUS AfdEventDisconnect( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN LONG DisconnectDataLength, + IN PVOID DisconnectData, + IN LONG DisconnectInformationLength, + IN PVOID DisconnectInformation, + IN ULONG DisconnectFlags) +{ + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + return STATUS_SUCCESS; +} + + +NTSTATUS AfdEventReceive( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket) +{ + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + return STATUS_SUCCESS; +} + + +TDI_STATUS ClientEventReceiveExpedited( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket) +{ + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + return STATUS_SUCCESS; +} + + +NTSTATUS ClientEventChainedReceive( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor) +{ + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + return STATUS_SUCCESS; +} + + +NTSTATUS AfdEventReceiveDatagramHandler( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket) +{ + PAFDFCB FCB = (PAFDFCB)TdiEventContext; + PAFD_READ_REQUEST ReadRequest; + PIO_STACK_LOCATION IrpSp; + PVOID ReceiveBuffer; + PAFD_BUFFER Buffer; + PLIST_ENTRY Entry; + NTSTATUS Status; + KIRQL OldIrql; + ULONG Count; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes from (0x%X).\n", + BytesAvailable, *(PULONG)SourceAddress)); + + ReceiveBuffer = ExAllocatePool(NonPagedPool, BytesAvailable); + if (!ReceiveBuffer) + return STATUS_INSUFFICIENT_RESOURCES; + + /*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList( + &BufferLookasideList);*/ + Buffer = (PAFD_BUFFER)ExAllocatePool(NonPagedPool, sizeof(AFD_BUFFER)); + if (!Buffer) { + ExFreePool(ReceiveBuffer); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Copy the data to a local buffer */ + RtlCopyMemory(ReceiveBuffer, Tsdu, BytesAvailable); + + Buffer->Buffer.len = BytesAvailable; + Buffer->Buffer.buf = ReceiveBuffer; + + ExInterlockedInsertTailList( + &FCB->ReceiveQueue, + &Buffer->ListEntry, + &FCB->ReceiveQueueLock); + + KeAcquireSpinLock(&FCB->ReadRequestQueueLock, &OldIrql); + + if (!IsListEmpty(&FCB->ReadRequestQueue)) { + AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n")); + + Entry = RemoveHeadList(&FCB->ReceiveQueue); + ReadRequest = CONTAINING_RECORD(Entry, AFD_READ_REQUEST, ListEntry); + + Status = FillWSABuffers( + FCB, + ReadRequest->RecvFromRequest->Buffers, + ReadRequest->RecvFromRequest->BufferCount, + &Count); + ReadRequest->RecvFromReply->NumberOfBytesRecvd = Count; + ReadRequest->RecvFromReply->Status = NO_ERROR; + + ReadRequest->Irp->IoStatus.Information = 0; + ReadRequest->Irp->IoStatus.Status = Status; + + AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", ReadRequest->Irp)); + + IoCompleteRequest(ReadRequest->Irp, IO_NETWORK_INCREMENT); + } + + KeReleaseSpinLock(&FCB->ReadRequestQueueLock, OldIrql); + + *BytesTaken = BytesAvailable; + + AFD_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return STATUS_SUCCESS; +} + + +NTSTATUS AfdRegisterEventHandlers( + PAFDFCB FCB) +{ + NTSTATUS Status; + + assert(FCB->TdiAddressObject); + + /* Report errors for all types of sockets */ + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_ERROR, + (PVOID)AfdEventError, + (PVOID)FCB); + if (!NT_SUCCESS(Status)) { return Status; } + + switch (FCB->SocketType) { + case SOCK_STREAM: + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_DISCONNECT, + (PVOID)AfdEventDisconnect, + (PVOID)FCB); + if (!NT_SUCCESS(Status)) { return Status; } + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_RECEIVE, + (PVOID)AfdEventReceive, + (PVOID)FCB); + if (!NT_SUCCESS(Status)) { return Status; } + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_RECEIVE_EXPEDITED, + (PVOID)ClientEventReceiveExpedited, + (PVOID)FCB); + if (!NT_SUCCESS(Status)) { return Status; } + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_CHAINED_RECEIVE, + (PVOID)ClientEventChainedReceive, + (PVOID)FCB); + if (!NT_SUCCESS(Status)) { return Status; } + break; + + case SOCK_DGRAM: + case SOCK_RAW: + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_RECEIVE_DATAGRAM, + (PVOID)AfdEventReceiveDatagramHandler, + (PVOID)FCB); + if (!NT_SUCCESS(Status)) { return Status; } + } + return STATUS_SUCCESS; +} + + +NTSTATUS AfdDeregisterEventHandlers( + PAFDFCB FCB) +{ + NTSTATUS Status; + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_ERROR, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { return Status; } + + switch (FCB->SocketType) { + case SOCK_STREAM: + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_DISCONNECT, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { return Status; } + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_RECEIVE, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { return Status; } + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_RECEIVE_EXPEDITED, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { return Status; } + + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_CHAINED_RECEIVE, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { return Status; } + break; + + case SOCK_DGRAM: + case SOCK_RAW: + Status = TdiSetEventHandler(FCB->TdiAddressObject, + TDI_EVENT_RECEIVE_DATAGRAM, + NULL, + NULL); + if (!NT_SUCCESS(Status)) { return Status; } + } + return STATUS_SUCCESS; +} + + +/* EOF */ diff --git a/drivers/net/afd/afd/opnclose.c b/drivers/net/afd/afd/opnclose.c new file mode 100644 index 0000000..81593e8 --- /dev/null +++ b/drivers/net/afd/afd/opnclose.c @@ -0,0 +1,263 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/opnclose.c + * PURPOSE: File object creation and destruction + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +PAFDFCB AfdInitializeFCB( + PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject OPTIONAL) +/* + * FUNCTION: Allocates and initializes a File Control Block structure + */ +{ + PAFDFCB NewFCB; + + NewFCB = ExAllocatePool(NonPagedPool, sizeof(AFDFCB)); + if (!NewFCB) + return NULL; + + RtlZeroMemory(NewFCB, sizeof(AFDFCB)); + + ExInitializeResourceLite(&NewFCB->NTRequiredFCB.MainResource); + ExInitializeResourceLite(&NewFCB->NTRequiredFCB.PagingIoResource); + + NewFCB->DeviceExt = DeviceExt; + NewFCB->ReferenceCount = 1; + NewFCB->OpenHandleCount = 1; + + NewFCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE; + NewFCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE; + + InitializeListHead(&NewFCB->CCBListHead); + + InsertTailList(&DeviceExt->FCBListHead, &NewFCB->ListEntry); + + InitializeListHead(&NewFCB->ReceiveQueue); + KeInitializeSpinLock(&NewFCB->ReceiveQueueLock); + + InitializeListHead(&NewFCB->ReadRequestQueue); + KeInitializeSpinLock(&NewFCB->ReadRequestQueueLock); + + if (FileObject) + FileObject->FsContext = (PVOID)NewFCB; + + AFD_DbgPrint(MAX_TRACE, ("FCB created for file object (0x%X) at (0x%X).\n", FileObject, NewFCB)); + + return NewFCB; +} + + +PAFDCCB AfdInitializeCCB( + PAFDFCB FCB, + PFILE_OBJECT FileObject) +/* + * FUNCTION: Allocates and initializes a Context Control Block structure + */ +{ + PAFDCCB NewCCB; + + NewCCB = ExAllocatePool(NonPagedPool, sizeof(AFDCCB)); + if (!NewCCB) + return NULL; + + RtlZeroMemory(NewCCB, sizeof(AFDCCB)); + + NewCCB->FileObject = FileObject; + + FileObject->FsContext2 = (PVOID)NewCCB; + + InsertTailList(&FCB->CCBListHead, &NewCCB->ListEntry); + + AFD_DbgPrint(MAX_TRACE, ("CCB created for file object (0x%X) at (0x%X).\n", FileObject, NewCCB)); + + return NewCCB; +} + + +NTSTATUS +STDCALL +AfdCreate( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PAFD_SOCKET_INFORMATION SocketInfo; + PFILE_FULL_EA_INFORMATION EaInfo; + PDEVICE_EXTENSION DeviceExt; + PTA_ADDRESS Address; + NTSTATUS Status; + ULONG EaLength; + PAFDFCB FCB; + PAFDCCB CCB; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = IrpSp->FileObject; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + assert(DeviceObject); + + DeviceExt = DeviceObject->DeviceExtension; + + EaInfo = Irp->AssociatedIrp.SystemBuffer; + + /* Parameter check */ + if (!EaInfo) { + AFD_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n")); + return STATUS_INVALID_PARAMETER; + } + + SocketInfo = (PAFD_SOCKET_INFORMATION)(EaInfo->EaName + EaInfo->EaNameLength); + + EaLength = sizeof(FILE_FULL_EA_INFORMATION) + + EaInfo->EaNameLength + + EaInfo->EaValueLength; + + if (EaLength < sizeof(FILE_FULL_EA_INFORMATION) + + AFD_SOCKET_LENGTH + sizeof(AFD_SOCKET_INFORMATION)) { + AFD_DbgPrint(MIN_TRACE, ("EA information has invalid length.\n")); + return STATUS_INVALID_PARAMETER; + } + + AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X) length is (%d).\n", EaInfo, EaLength)); + + /* FIXME: File/socket could already be open, do a search for it */ + + FCB = AfdInitializeFCB(DeviceExt, FileObject); + + CCB = AfdInitializeCCB(FCB, FileObject); + + if (CCB && FCB) { + FCB->CommandChannel = SocketInfo->CommandChannel; + + if (!FCB->CommandChannel) { + FCB->AddressFamily = SocketInfo->AddressFamily; + FCB->SocketType = SocketInfo->SocketType; + FCB->Protocol = SocketInfo->Protocol; + FCB->SocketName = SocketInfo->Name; + FCB->HelperContext = SocketInfo->HelperContext; + FCB->NotificationEvents = SocketInfo->NotificationEvents; + + if (RtlCreateUnicodeString(&FCB->TdiDeviceName, SocketInfo->TdiDeviceName.Buffer)) { + + RtlCopyUnicodeString(&FCB->TdiDeviceName, &SocketInfo->TdiDeviceName); + + AFD_DbgPrint(MAX_TRACE, ("TDI device name is (%wZ).\n", &FCB->TdiDeviceName)); + + /* Open address file now for raw sockets */ + if (FCB->SocketType == SOCK_RAW) { + AFD_DbgPrint(MAX_TRACE, ("Opening raw socket.\n")); + + Status = TdiOpenAddressFile( + &FCB->TdiDeviceName, + &SocketInfo->Name, + &FCB->TdiAddressObjectHandle, + &FCB->TdiAddressObject); + if (NT_SUCCESS(Status)) { + Status = AfdRegisterEventHandlers(FCB); + if (NT_SUCCESS(Status)) { + FCB->State = SOCKET_STATE_BOUND; + } else { + AFD_DbgPrint(MAX_TRACE, ("AfdRegisterEventHandlers() failed (0x%X).\n", Status)); + } + } else { + AFD_DbgPrint(MAX_TRACE, ("TdiOpenAddressFile() failed (0x%X).\n", Status)); + } + } else + Status = STATUS_SUCCESS; + } else + Status = STATUS_INSUFFICIENT_RESOURCES; + } else + Status = STATUS_SUCCESS; + } else + Status = STATUS_INSUFFICIENT_RESOURCES; + + if (!NT_SUCCESS(Status)) { + /* FIXME: Cleanup */ + AFD_DbgPrint(MAX_TRACE, ("FIXME: Cleanup.\n")); + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + AFD_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS +STDCALL +AfdClose( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = IrpSp->FileObject; + NTSTATUS Status; + PAFDFCB FCB; + PAFDCCB CCB; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + assert(DeviceObject); + assert(FileObject); + + FCB = FileObject->FsContext; + CCB = FileObject->FsContext2; + + switch (IrpSp->MajorFunction) { + /* Close a file object */ + case IRP_MJ_CLOSE: + FCB->ReferenceCount--; + if (FCB->ReferenceCount < 1) { + if (!FCB->CommandChannel) { + /* Close TDI connection file object */ + if (FCB->TdiConnectionObjectHandle != INVALID_HANDLE_VALUE) { + TdiCloseDevice(FCB->TdiConnectionObjectHandle, FCB->TdiConnectionObject); + FCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE; + } + + /* Close TDI address file object */ + if (FCB->TdiAddressObjectHandle != INVALID_HANDLE_VALUE) { + AfdDeregisterEventHandlers(FCB); + TdiCloseDevice(FCB->TdiAddressObjectHandle, FCB->TdiAddressObject); + FCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE; + } + } + + ExFreePool(FCB); + } + + Status = STATUS_SUCCESS; + break; + + /* Release resources bound to a file object */ + case IRP_MJ_CLEANUP: + FCB->OpenHandleCount--; + Status = STATUS_SUCCESS; + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + ExFreePool(CCB); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +/* EOF */ diff --git a/drivers/net/afd/afd/rdwr.c b/drivers/net/afd/afd/rdwr.c new file mode 100644 index 0000000..ce28180 --- /dev/null +++ b/drivers/net/afd/afd/rdwr.c @@ -0,0 +1,119 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/rdwr.c + * PURPOSE: File object read/write functions + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +NTSTATUS AfdReadFile( + PDEVICE_EXTENSION DeviceExt, + PFILE_OBJECT FileObject, + PVOID Buffer, + ULONG Length, + ULONG Offset) +/* + * FUNCTION: Reads data from a file + */ +{ + UNIMPLEMENTED + + return STATUS_UNSUCCESSFUL; +} + + +NTSTATUS +STDCALL +AfdRead( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ +#if 1 + UNIMPLEMENTED + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + return STATUS_UNSUCCESSFUL; +#else + PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION IoSp = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = IoSp->FileObject; + NTSTATUS Status; + ULONG Length; + PVOID Buffer; + ULONG Offset; + + Length = IoSp->Parameters.Read.Length; + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Offset = IoSp->Parameters.Read.ByteOffset.u.LowPart; + + Status = AfdReadFile(DeviceExt, FileObject, Buffer, Length, Offset); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +#endif +} + + +NTSTATUS +STDCALL +AfdWrite( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION IoSp = IoGetCurrentIrpStackLocation(Irp); + PFILE_OBJECT FileObject = IoSp->FileObject; + NTSTATUS Status; + ULONG Length; + PVOID Buffer; + ULONG Offset; + PAFDFCB FCB; + PAFDCCB CCB; + + FCB = FileObject->FsContext; + CCB = FileObject->FsContext2; + + assert(FCB); + assert(CCB); + + Length = IoSp->Parameters.Write.Length; + Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Offset = IoSp->Parameters.Write.ByteOffset.u.LowPart; + + AFD_DbgPrint(MAX_TRACE, ("Called. Length (%d) Buffer (0x%X) Offset (0x%X)\n", + Length, Buffer, Offset)); + + assert((FCB->SocketType == SOCK_STREAM) || (FCB->SocketType == SOCK_DGRAM)); + + switch (FCB->SocketType) { + case SOCK_STREAM: + /* FIXME: Support connectionful communication */ + break; + case SOCK_DGRAM: + /* Connectionless communication */ + //Status = TdiSendDatagram(FCB->TdiAddressObject, WH2N(2000), 0x7F000001, Buffer, Length); + //if (!NT_SUCCESS(Status)) { + Length = 0; + //} + break; + case SOCK_RAW: + /* FIXME: Support raw communication */ + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Length; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + AFD_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return Status; +} + +/* EOF */ diff --git a/drivers/net/afd/afd/routines.c b/drivers/net/afd/afd/routines.c new file mode 100644 index 0000000..2947304 --- /dev/null +++ b/drivers/net/afd/afd/routines.c @@ -0,0 +1,241 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/routines.c + * PURPOSE: Support routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/02-2001 Created + */ +#include +#include + + +ULONG WSABufferSize( + LPWSABUF Buffers, + DWORD BufferCount) +{ + ULONG i; + LPWSABUF p; + ULONG Count = 0; + + p = Buffers; + for (i = 0; i < BufferCount; i++) { + Count += p->len; + p++; + } + + AFD_DbgPrint(MAX_TRACE, ("Buffer is %d bytes.\n", Count)); + + return Count; +} + + +NTSTATUS MergeWSABuffers( + LPWSABUF Buffers, + DWORD BufferCount, + PVOID Destination, + ULONG MaxLength, + PULONG BytesCopied) +{ + NTSTATUS Status; + ULONG Length; + LPWSABUF p; + ULONG i; + + *BytesCopied = 0; + if (BufferCount == 0) + return STATUS_SUCCESS; + + p = Buffers; + + AFD_DbgPrint(MAX_TRACE, ("Destination is 0x%X\n", Destination)); + AFD_DbgPrint(MAX_TRACE, ("p is 0x%X\n", p)); + + for (i = 0; i < BufferCount; i++) { + Length = p->len; + if (Length > MaxLength) + /* Don't copy out of bounds */ + Length = MaxLength; + + RtlCopyMemory(Destination, p->buf, Length); + Destination += Length; + AFD_DbgPrint(MAX_TRACE, ("Destination is 0x%X\n", Destination)); + p++; + AFD_DbgPrint(MAX_TRACE, ("p is 0x%X\n", p)); + + *BytesCopied += Length; + + MaxLength -= Length; + if (MaxLength == 0) + /* Destination buffer is full */ + break; + } + + return STATUS_SUCCESS; +} + +/* + * NOTES: ReceiveQueueLock must be acquired for the FCB when called + */ +NTSTATUS FillWSABuffers( + PAFDFCB FCB, + LPWSABUF Buffers, + DWORD BufferCount, + PULONG BytesCopied) +{ + NTSTATUS Status; + PUCHAR DstData, SrcData; + UINT DstSize, SrcSize; + UINT Count, Total; + PAFD_BUFFER SrcBuffer; + PLIST_ENTRY Entry; + ULONG Size; + + *BytesCopied = 0; + if (BufferCount == 0) + return STATUS_SUCCESS; + + if (IsListEmpty(&FCB->ReceiveQueue)) + return STATUS_SUCCESS; + + Entry = RemoveHeadList(&FCB->ReceiveQueue); + SrcBuffer = CONTAINING_RECORD(Entry, AFD_BUFFER, ListEntry); + SrcData = SrcBuffer->Buffer.buf; + SrcSize = SrcBuffer->Buffer.len; + + DstData = Buffers->buf; + DstSize = Buffers->len; + + /* Copy the data */ + for (Total = 0;;) { + /* Find out how many bytes we can copy at one time */ + if (DstSize < SrcSize) + Count = DstSize; + else + Count = SrcSize; + + AFD_DbgPrint(MAX_TRACE, ("DstData (0x%X) SrcData (0x%X) Count (0x%X).\n", + DstData, SrcData, Count)); + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); + + Total += Count; + + SrcSize -= Count; + if (SrcSize == 0) { + ExFreePool(SrcBuffer->Buffer.buf); + ExFreePool(SrcBuffer); + + /* No more bytes in source buffer. Proceed to the next buffer + in the source buffer chain if there is one */ + if (IsListEmpty(&FCB->ReceiveQueue)) { + SrcBuffer = NULL; + SrcData = 0; + SrcSize = 0; + break; + } + + Entry = RemoveHeadList(&FCB->ReceiveQueue); + SrcBuffer = CONTAINING_RECORD(Entry, AFD_BUFFER, ListEntry); + SrcData = SrcBuffer->Buffer.buf; + SrcSize = SrcBuffer->Buffer.len; + } + + DstSize -= Count; + if (DstSize == 0) { + /* No more bytes in destination buffer. Proceed to + the next buffer in the destination buffer chain */ + BufferCount--; + if (BufferCount < 1) + break; + Buffers++; + DstData = Buffers->buf; + DstSize = Buffers->len; + } + } + + if (SrcSize > 0) { + InsertHeadList(&FCB->ReceiveQueue, Entry); + } else if (SrcBuffer != NULL) { + ExFreePool(SrcBuffer->Buffer.buf); + ExFreePool(SrcBuffer); + } + + *BytesCopied = Total; + + return STATUS_SUCCESS; +} + +ULONG ChecksumCompute( + PVOID Data, + UINT Count, + ULONG Seed) +/* + * FUNCTION: Calculate checksum of a buffer + * ARGUMENTS: + * Data = Pointer to buffer with data + * Count = Number of bytes in buffer + * Seed = Previously calculated checksum (if any) + * RETURNS: + * Checksum of buffer + */ +{ + /* FIXME: This should be done in assembler */ + + register ULONG Sum = Seed; + + while (Count > 1) { + Sum += *(PUSHORT)Data; + Count -= 2; + (ULONG_PTR)Data += 2; + } + + /* Add left-over byte, if any */ + if (Count > 0) + Sum += *(PUCHAR)Data; + + /* Fold 32-bit sum to 16 bits */ + while (Sum >> 16) + Sum = (Sum & 0xFFFF) + (Sum >> 16); + + return ~Sum; +} + +VOID BuildIPv4Header( + PIPv4_HEADER IPHeader, + ULONG TotalSize, + ULONG Protocol, + PSOCKADDR SourceAddress, + PSOCKADDR DestinationAddress) +{ + PSOCKADDR_IN SrcNameIn = (PSOCKADDR_IN)SourceAddress; + PSOCKADDR_IN DstNameIn = (PSOCKADDR_IN)DestinationAddress; + + /* Version = 4, Length = 5 DWORDs */ + IPHeader->VerIHL = 0x45; + /* Normal Type-of-Service */ + IPHeader->Tos = 0; + /* Length of header and data */ + IPHeader->TotalLength = WH2N((USHORT)TotalSize); + /* Identification */ + IPHeader->Id = 0; + /* One fragment at offset 0 */ + IPHeader->FlagsFragOfs = 0; + /* Time-to-Live is 128 */ + IPHeader->Ttl = 128; + /* Protocol number */ + IPHeader->Protocol = Protocol; + /* Checksum is 0 (calculated later) */ + IPHeader->Checksum = 0; + /* Source address */ + IPHeader->SrcAddr = SrcNameIn->sin_addr.S_un.S_addr; + /* Destination address */ + IPHeader->DstAddr = DstNameIn->sin_addr.S_un.S_addr; + + /* Calculate checksum of IP header */ + IPHeader->Checksum = (USHORT) + ChecksumCompute(IPHeader, sizeof(IPv4_HEADER), 0); +} + +/* EOF */ diff --git a/drivers/net/afd/afd/tdi.c b/drivers/net/afd/afd/tdi.c new file mode 100644 index 0000000..a97a278 --- /dev/null +++ b/drivers/net/afd/afd/tdi.c @@ -0,0 +1,1210 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: afd/tdi.c + * PURPOSE: Transport Driver Interface functions + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +#ifdef DBG +VOID DisplayBuffer( + PVOID Buffer, + ULONG Size) +{ + ULONG i; + PCHAR p; + + if ((DebugTraceLevel & MAX_TRACE) == 0) + return; + + if (!Buffer) { + AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n")); + return; + } + + AFD_DbgPrint(MIN_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size)); + + p = (PCHAR)Buffer; + for (i = 0; i < Size; i++) { + if (i % 16 == 0) + DbgPrint("\n"); + DbgPrint("%02X ", (p[i]) & 0xFF); + } + DbgPrint("\n"); +} +#endif /* DBG */ + + +inline DWORD TdiAddressSizeFromName( + LPSOCKADDR Name) +/* + * FUNCTION: Returns the size of a TDI style address equivalent to a + * WinSock style name + * ARGUMENTS: + * Name = WinSock style name + * RETURNS: + * Size of TDI style address, 0 if Name is not valid + */ +{ + switch (Name->sa_family) { + case AF_INET: + return sizeof(TA_ADDRESS_IP); + /* FIXME: More to come */ + } + AFD_DbgPrint(MIN_TRACE, ("Unknown address family (%d).\n", Name->sa_family)); + return 0; +} + + +VOID TdiBuildAddressIPv4( + PTA_ADDRESS_IP Address, + LPSOCKADDR Name) +/* + * FUNCTION: Builds an IPv4 TDI style address + * ARGUMENTS: + * Address = Address of buffer to place TDI style IPv4 address + * Name = Pointer to WinSock style IPv4 name + */ +{ + Address->TAAddressCount = 1; + Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; + Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; + Address->Address[0].Address[0].sin_port = ((LPSOCKADDR_IN)Name)->sin_port; + Address->Address[0].Address[0].in_addr = ((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr; +} + + +NTSTATUS TdiBuildAddress( + PTA_ADDRESS Address, + LPSOCKADDR Name) +/* + * FUNCTION: Builds a TDI style address + * ARGUMENTS: + * Address = Address of buffer to place TDI style address + * Name = Pointer to WinSock style name + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status = STATUS_SUCCESS; + + switch (Name->sa_family) { + case AF_INET: + TdiBuildAddressIPv4((PTA_ADDRESS_IP)Address, Name); + break; + /* FIXME: More to come */ + default: + AFD_DbgPrint(MID_TRACE, ("Unknown address family (%d).\n", Name->sa_family)); + Status = STATUS_INVALID_PARAMETER; + } + + return Status; +} + + +NTSTATUS TdiBuildName( + LPSOCKADDR Name, + PTA_ADDRESS Address) +/* + * FUNCTION: Builds a WinSock style address + * ARGUMENTS: + * Name = Address of buffer to place WinSock style name + * Address = Pointer to TDI style address + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status = STATUS_SUCCESS; + + switch (Address->AddressType) { + case TDI_ADDRESS_TYPE_IP: + Name->sa_family = AF_INET; + ((LPSOCKADDR_IN)Name)->sin_port = + ((PTDI_ADDRESS_IP)&Address->Address[0])->sin_port; + ((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr = + ((PTDI_ADDRESS_IP)&Address->Address[0])->in_addr; + break; + /* FIXME: More to come */ + default: + AFD_DbgPrint(MID_TRACE, ("Unknown TDI address type (%d).\n", Address->AddressType)); + Status = STATUS_INVALID_PARAMETER; + } + + return Status; + +} + + +NTSTATUS TdiBuildConnectionInfo( + PTDI_CONNECTION_INFORMATION *ConnectionInfo, + LPSOCKADDR Name) +/* + * FUNCTION: Builds a TDI connection information structure + * ARGUMENTS: + * ConnectionInfo = Address of buffer to place connection information + * Name = Pointer to WinSock style name + * RETURNS: + * Status of operation + */ +{ + PTDI_CONNECTION_INFORMATION ConnInfo; + ULONG TdiAddressSize; + + TdiAddressSize = TdiAddressSizeFromName(Name); + + ConnInfo = (PTDI_CONNECTION_INFORMATION) + ExAllocatePool(NonPagedPool, + sizeof(TDI_CONNECTION_INFORMATION) + + TdiAddressSize); + if (!ConnInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(ConnInfo, + sizeof(TDI_CONNECTION_INFORMATION) + + TdiAddressSize); + + ConnInfo->RemoteAddressLength = TdiAddressSize; + ConnInfo->RemoteAddress = (PVOID) + (ConnInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + TdiBuildAddress(ConnInfo->RemoteAddress, Name); + + *ConnectionInfo = ConnInfo; + + return STATUS_SUCCESS; +} + + +NTSTATUS TdiCall( + PIRP Irp, + PDEVICE_OBJECT DeviceObject, + PKEVENT Event, + PIO_STATUS_BLOCK Iosb) +/* + * FUNCTION: Calls a transport driver device + * ARGUMENTS: + * Irp = Pointer to I/O Request Packet + * DeviceObject = Pointer to device object to call + * Event = An optional pointer to an event handle that will be + * waited upon + * Iosb = Pointer to an IO status block + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("Called\n")); + + Status = IoCallDriver(DeviceObject, Irp); + if ((Status == STATUS_PENDING) && (Event != NULL)) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + KeWaitForSingleObject( + Event, + Executive, + UserMode, + FALSE, + NULL); + Status = Iosb->Status; + } + + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS TdiOpenDevice( + PUNICODE_STRING DeviceName, + ULONG EaLength, + PFILE_FULL_EA_INFORMATION EaInfo, + PHANDLE Handle, + PFILE_OBJECT *Object) +/* + * FUNCTION: Opens a device + * ARGUMENTS: + * DeviceName = Pointer to counted string with name of device + * EaLength = Length of EA information + * EaInfo = Pointer to buffer with EA information + * Handle = Address of buffer to place device handle + * Object = Address of buffer to place device object + * RETURNS: + * Status of operation + */ +{ + OBJECT_ATTRIBUTES Attr; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName)); + + InitializeObjectAttributes(&Attr, /* Attribute buffer */ + DeviceName, /* Device name */ + OBJ_CASE_INSENSITIVE, /* Attributes */ + NULL, /* Root directory */ + NULL); /* Security descriptor */ + + Status = ZwCreateFile(Handle, /* Return file handle */ + GENERIC_READ | GENERIC_WRITE, /* Desired access */ + &Attr, /* Object attributes */ + &Iosb, /* IO status */ + 0, /* Initial allocation size */ + FILE_ATTRIBUTE_NORMAL, /* File attributes */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access */ + FILE_OPEN_IF, /* Create disposition */ + 0, /* Create options */ + EaInfo, /* EA buffer */ + EaLength); /* EA length */ + if (NT_SUCCESS(Status)) { + Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */ + GENERIC_READ | GENERIC_WRITE, /* Access mode */ + NULL, /* Object type */ + KernelMode, /* Access mode */ + (PVOID*)Object, /* Pointer to object */ + NULL); /* Handle information */ + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status)); + ZwClose(*Handle); + } else { + AFD_DbgPrint(MAX_TRACE, ("Got handle (0x%X) Object (0x%X)\n", + *Handle, *Object)); + } + } else { + AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status)); + } + return Status; +} + + +NTSTATUS TdiCloseDevice( + HANDLE Handle, + PFILE_OBJECT FileObject) +{ + AFD_DbgPrint(MAX_TRACE, ("Called. Handle (0x%X) FileObject (0x%X)\n", + Handle, FileObject)); + + if (Handle) + ZwClose(Handle); + + if (FileObject) + ObDereferenceObject(FileObject); + + return STATUS_SUCCESS; +} + + +NTSTATUS TdiOpenAddressFileIPv4( + PUNICODE_STRING DeviceName, + LPSOCKADDR Name, + PHANDLE AddressHandle, + PFILE_OBJECT *AddressObject) +/* + * FUNCTION: Opens an IPv4 address file object + * ARGUMENTS: + * DeviceName = Pointer to counted string with name of device + * Name = Pointer to socket name (IPv4 address family) + * AddressHandle = Address of buffer to place address file handle + * AddressObject = Address of buffer to place address file object + * RETURNS: + * Status of operation + */ +{ + PFILE_FULL_EA_INFORMATION EaInfo; + PTA_ADDRESS_IP Address; + NTSTATUS Status; + ULONG EaLength; + + AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ) Name (0x%X)\n", + DeviceName, Name)); + + EaLength = sizeof(FILE_FULL_EA_INFORMATION) + + TDI_TRANSPORT_ADDRESS_LENGTH + + sizeof(TA_ADDRESS_IP); + EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength); + if (!EaInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(EaInfo, EaLength); + EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; + RtlCopyMemory(EaInfo->EaName, + TdiTransportAddress, + TDI_TRANSPORT_ADDRESS_LENGTH); + EaInfo->EaValueLength = sizeof(TA_ADDRESS_IP); + Address = (PTA_ADDRESS_IP)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH); + TdiBuildAddressIPv4(Address, Name); + Status = TdiOpenDevice(DeviceName, + EaLength, + EaInfo, + AddressHandle, + AddressObject); + ExFreePool(EaInfo); + return Status; +} + + +NTSTATUS TdiOpenAddressFile( + PUNICODE_STRING DeviceName, + LPSOCKADDR Name, + PHANDLE AddressHandle, + PFILE_OBJECT *AddressObject) +/* + * FUNCTION: Opens an address file object + * ARGUMENTS: + * DeviceName = Pointer to counted string with name of device + * Name = Pointer to socket name + * AddressHandle = Address of buffer to place address file handle + * AddressObject = Address of buffer to place address file object + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + + switch (Name->sa_family) { + case AF_INET: + Status = TdiOpenAddressFileIPv4( + DeviceName, + Name, + AddressHandle, + AddressObject); + break; + + default: + AFD_DbgPrint(MAX_TRACE, ("Unknown socket address family (0x%X)\n", + Name->sa_family)); + Status = STATUS_INVALID_PARAMETER; + } + + return Status; +} + + +NTSTATUS TdiOpenConnectionEndpointFile( + PUNICODE_STRING DeviceName, + PHANDLE ConnectionHandle, + PFILE_OBJECT *ConnectionObject) +/* + * FUNCTION: Opens a connection endpoint file object + * ARGUMENTS: + * DeviceName = Pointer to counted string with name of device + * ConnectionHandle = Address of buffer to place connection endpoint file handle + * ConnectionObject = Address of buffer to place connection endpoint file object + * RETURNS: + * Status of operation + */ +{ + PFILE_FULL_EA_INFORMATION EaInfo; + PVOID *ContextArea; + NTSTATUS Status; + ULONG EaLength; + + AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName)); + + EaLength = sizeof(FILE_FULL_EA_INFORMATION) + + TDI_CONNECTION_CONTEXT_LENGTH + + sizeof(PVOID); + + EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength); + if (!EaInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(EaInfo, EaLength); + EaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; + RtlCopyMemory(EaInfo->EaName, + TdiConnectionContext, + TDI_CONNECTION_CONTEXT_LENGTH); + EaInfo->EaValueLength = sizeof(PVOID); + ContextArea = (PVOID*)(EaInfo->EaName + TDI_CONNECTION_CONTEXT_LENGTH); + /* FIXME: Allocate context area */ + *ContextArea = NULL; + Status = TdiOpenDevice(DeviceName, + EaLength, + EaInfo, + ConnectionHandle, + ConnectionObject); + ExFreePool(EaInfo); + return Status; +} + + +NTSTATUS TdiConnect( + PFILE_OBJECT ConnectionObject, + LPSOCKADDR RemoteAddress) +/* + * FUNCTION: Connect a connection endpoint to a remote peer + * ARGUMENTS: + * ConnectionObject = Pointer to connection endpoint file object + * RemoteAddress = Pointer to remote address + * RETURNS: + * Status of operation + */ +{ + PTDI_CONNECTION_INFORMATION RequestConnectionInfo; + PTDI_CONNECTION_INFORMATION ReturnConnectionInfo; + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + AFD_DbgPrint(MAX_TRACE, ("Called\n")); + + assert(ConnectionObject); + + DeviceObject = IoGetRelatedDeviceObject(ConnectionObject); + + Status = TdiBuildConnectionInfo(&RequestConnectionInfo, RemoteAddress); + if (!NT_SUCCESS(Status)) + return Status; + + /* Use same TDI address type for return connection information */ + Status = TdiBuildConnectionInfo(&ReturnConnectionInfo, RemoteAddress); + if (!NT_SUCCESS(Status)) { + ExFreePool(RequestConnectionInfo); + return Status; + } + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */ + DeviceObject, /* Device object */ + ConnectionObject, /* File object */ + &Event, /* Event */ + &Iosb); /* Status */ + if (!Irp) { + ExFreePool(RequestConnectionInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + + TdiBuildConnect(Irp, /* IRP */ + DeviceObject, /* Device object */ + ConnectionObject, /* File object */ + NULL, /* Completion routine */ + NULL, /* Completion routine context */ + NULL, /* Time */ + RequestConnectionInfo, /* Request connection information */ + ReturnConnectionInfo); /* Return connection information */ + + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + + ExFreePool(RequestConnectionInfo); + ExFreePool(ReturnConnectionInfo); + + return Status; +} + + +NTSTATUS TdiAssociateAddressFile( + HANDLE AddressHandle, + PFILE_OBJECT ConnectionObject) +/* + * FUNCTION: Associates a connection endpoint to an address file object + * ARGUMENTS: + * AddressHandle = Handle to address file object + * ConnectionObject = Connection endpoint file object + * RETURNS: + * Status of operation + */ +{ + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (0x%X) ConnectionObject (0x%X)\n", + AddressHandle, ConnectionObject)); + + assert(ConnectionObject); + + DeviceObject = IoGetRelatedDeviceObject(ConnectionObject); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, /* Sub function */ + DeviceObject, /* Device object */ + ConnectionObject, /* File object */ + &Event, /* Event */ + &Iosb); /* Status */ + if (!Irp) + return STATUS_INSUFFICIENT_RESOURCES; + + TdiBuildAssociateAddress(Irp, + DeviceObject, + ConnectionObject, + NULL, + NULL, + AddressHandle); + + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + + return Status; +} + + +NTSTATUS TdiSetEventHandler( + PFILE_OBJECT FileObject, + LONG EventType, + PVOID Handler, + PVOID Context) +/* + * FUNCTION: Sets or resets an event handler + * ARGUMENTS: + * FileObject = Pointer to file object + * EventType = Event code + * Handler = Event handler to be called when the event occurs + * Context = Context input to handler when the event occurs + * RETURNS: + * Status of operation + * NOTES: + * Specify NULL for Handler to stop calling event handler + */ +{ + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + AFD_DbgPrint(MAX_TRACE, ("Called\n")); + + assert(FileObject); + + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */ + DeviceObject, /* Device object */ + FileObject, /* File object */ + &Event, /* Event */ + &Iosb); /* Status */ + if (!Irp) + return STATUS_INSUFFICIENT_RESOURCES; + + + + TdiBuildSetEventHandler(Irp, + DeviceObject, + FileObject, + NULL, + NULL, + EventType, + Handler, + Context); + + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + + return Status; +} + + +NTSTATUS TdiQueryDeviceControl( + PFILE_OBJECT FileObject, + ULONG IoControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + PULONG Return) +/* + * FUNCTION: Queries a device for information + * ARGUMENTS: + * FileObject = Pointer to file object + * IoControlCode = I/O control code + * InputBuffer = Pointer to buffer with input data + * InputBufferLength = Length of InputBuffer + * OutputBuffer = Address of buffer to place output data + * OutputBufferLength = Length of OutputBuffer + * RETURNS: + * Status of operation + */ +{ + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = IoBuildDeviceIoControlRequest(IoControlCode, + DeviceObject, + InputBuffer, + InputBufferLength, + OutputBuffer, + OutputBufferLength, + FALSE, + &Event, + &Iosb); + if (!Irp) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + + if (Return) + *Return = Iosb.Information; + + return Status; +} + + +NTSTATUS TdiQueryInformationEx( + PFILE_OBJECT FileObject, + ULONG Entity, + ULONG Instance, + ULONG Class, + ULONG Type, + ULONG Id, + PVOID OutputBuffer, + PULONG OutputLength) +/* + * FUNCTION: Extended query for information + * ARGUMENTS: + * FileObject = Pointer to file object + * Entity = Entity + * Instance = Instance + * Class = Entity class + * Type = Entity type + * Id = Entity id + * OutputBuffer = Address of buffer to place data + * OutputLength = Address of buffer with length of OutputBuffer (updated) + * RETURNS: + * Status of operation + */ +{ + TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo; + + RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); + QueryInfo.ID.toi_entity.tei_entity = Entity; + QueryInfo.ID.toi_entity.tei_instance = Instance; + QueryInfo.ID.toi_class = Class; + QueryInfo.ID.toi_type = Type; + QueryInfo.ID.toi_id = Id; + + return TdiQueryDeviceControl(FileObject, /* Transport/connection object */ + IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */ + &QueryInfo, /* Input buffer */ + sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */ + OutputBuffer, /* Output buffer */ + *OutputLength, /* Output buffer length */ + OutputLength); /* Return information */ +} + + +NTSTATUS TdiQueryAddress( + PFILE_OBJECT FileObject, + PULONG Address) +/* + * FUNCTION: Queries for a local IP address + * ARGUMENTS: + * FileObject = Pointer to file object + * Address = Address of buffer to place local address + * RETURNS: + * Status of operation + */ +{ + UINT i; + TDIEntityID *Entities; + ULONG EntityCount; + ULONG EntityType; + IPSNMP_INFO SnmpInfo; + PIPADDR_ENTRY IpAddress; + ULONG BufferSize; + NTSTATUS Status = STATUS_SUCCESS; + + AFD_DbgPrint(MAX_TRACE, ("Called\n")); + + BufferSize = sizeof(TDIEntityID) * 20; + Entities = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize); + if (!Entities) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Query device for supported entities */ + + Status = TdiQueryInformationEx(FileObject, /* File object */ + GENERIC_ENTITY, /* Entity */ + TL_INSTANCE, /* Instance */ + INFO_CLASS_GENERIC, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + ENTITY_LIST_ID, /* Entity id */ + Entities, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status)); + ExFreePool(Entities); + return Status; + } + + /* Locate an IP entity */ + EntityCount = BufferSize / sizeof(TDIEntityID); + + AFD_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount)); + + for (i = 0; i < EntityCount; i++) { + if (Entities[i].tei_entity == CL_NL_ENTITY) { + /* Query device for entity type */ + + BufferSize = sizeof(EntityType); + Status = TdiQueryInformationEx(FileObject, /* File object */ + CL_NL_ENTITY, /* Entity */ + Entities[i].tei_instance, /* Instance */ + INFO_CLASS_GENERIC, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + ENTITY_TYPE_ID, /* Entity id */ + &EntityType, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) { + AFD_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status)); + break; + } + + /* Query device for SNMP information */ + + BufferSize = sizeof(SnmpInfo); + Status = TdiQueryInformationEx(FileObject, /* File object */ + CL_NL_ENTITY, /* Entity */ + Entities[i].tei_instance, /* Instance */ + INFO_CLASS_PROTOCOL, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + IP_MIB_STATS_ID, /* Entity id */ + &SnmpInfo, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) { + AFD_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status)); + break; + } + + /* Query device for all IP addresses */ + + if (SnmpInfo.NumAddr != 0) { + BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY); + IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize); + if (!IpAddress) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + break; + } + + Status = TdiQueryInformationEx(FileObject, /* File object */ + CL_NL_ENTITY, /* Entity */ + Entities[i].tei_instance, /* Instance */ + INFO_CLASS_PROTOCOL, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + IP_MIB_ADDRTABLE_ENTRY_ID, /* Entity id */ + IpAddress, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status)); + ExFreePool(IpAddress); + break; + } + + if (SnmpInfo.NumAddr != 1) { + /* Skip loopback address */ + *Address = DN2H(((PIPADDR_ENTRY)((ULONG)IpAddress + sizeof(IPADDR_ENTRY)))->Addr); + } else { + /* Select the first address returned */ + *Address = DN2H(IpAddress->Addr); + } + + ExFreePool(IpAddress); + } else { + Status = STATUS_UNSUCCESSFUL; + break; + } + } + } + + ExFreePool(Entities); + + AFD_DbgPrint(MAX_TRACE, ("Leaving\n")); + + return Status; +} + + +NTSTATUS TdiSend( + PFILE_OBJECT TransportObject, + PVOID Buffer, + ULONG BufferSize) +/* + * FUNCTION: Sends a block of data + * ARGUMENTS: + * TransportObject = Pointer to transport object + * Buffer = Pointer to buffer with data to send + * BufferSize = Length of Buffer + * RETURNS: + * Status of operation + */ +{ +#if 0 + PTDI_CONNECTION_INFORMATION ConnectInfo; + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + DWORD TdiAddressSize; + PVOID BaseAddress; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + PMDL Mdl; + + DeviceObject = IoGetRelatedDeviceObject(TransportObject); + if (!DeviceObject) { + AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); + return STATUS_INVALID_PARAMETER; + } + + TdiAddressSize = TdiAddressSizeFromName(Address); + + ConnectInfo = (PTDI_CONNECTION_INFORMATION) + ExAllocatePool(NonPagedPool, + sizeof(TDI_CONNECTION_INFORMATION) + + TdiAddressSize); + + if (!ConnectInfo) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(ConnectInfo, + sizeof(TDI_CONNECTION_INFORMATION) + + TdiAddressSize); + + ConnectInfo->RemoteAddressLength = TdiAddressSize; + ConnectInfo->RemoteAddress = (PVOID) + (ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + TdiBuildAddress(ConnectInfo->RemoteAddress, Address); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + &Event, /* Event */ + &Iosb); /* Status */ + if (!Irp) { + AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n")); + ExFreePool(ConnectInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + +DisplayBuffer(Request->Buffers->buf, Request->Buffers->len); + + + /* FIXME: There may be more than one buffer */ + BufferSize = Request->Buffers->len; + Mdl = IoAllocateMdl( + Request->Buffers->buf, /* Virtual address of buffer */ + Request->Buffers->len, /* Length of buffer */ + FALSE, /* Not secondary */ + FALSE, /* Don't charge quota */ + NULL); /* Don't use IRP */ + if (!Mdl) { + AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n")); + IoFreeIrp(Irp); + ExFreePool(ConnectInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#ifdef _MSC_VER + try { +#endif + MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); +#ifdef _MSC_VER + } except(EXCEPTION_EXECUTE_HANDLER) { + AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); + IoFreeMdl(Mdl); + IoFreeIrp(Irp); + ExFreePool(ConnectInfo); + return STATUS_UNSUCCESSFUL; + } +#endif + + BaseAddress = MmMapLockedPages(Mdl, KernelMode); + + AFD_DbgPrint(MAX_TRACE, ("Mapped user mode buffer at 0x%X.\n", BaseAddress)); + + TdiBuildSendDatagram(Irp, /* I/O Request Packet */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Completion routine */ + NULL, /* Completion context */ + Mdl, /* Descriptor for data buffer */ + BufferSize, /* Size of data to send */ + ConnectInfo); /* Connection information */ + + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + + MmUnmapLockedPages(BaseAddress, Mdl); + + MmUnlockPages(Mdl); + + IoFreeMdl(Mdl); + + ExFreePool(ConnectInfo); + + return Status; +#endif + return STATUS_SUCCESS; +} + + +NTSTATUS TdiSendDatagram( + PFILE_OBJECT TransportObject, + LPSOCKADDR Address, + PMDL Mdl, + ULONG BufferSize) +/* + * FUNCTION: Sends a datagram + * ARGUMENTS: + * TransportObject = Pointer to transport object + * Address = Remote address to send data to + * Mdl = MDL of buffer to send + * BufferSize = Length of buffer + * RETURNS: + * Status of operation + */ +{ + PTDI_CONNECTION_INFORMATION ConnectInfo; + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + DWORD TdiAddressSize; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + DeviceObject = IoGetRelatedDeviceObject(TransportObject); + if (!DeviceObject) { + AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); + return STATUS_INVALID_PARAMETER; + } + + TdiAddressSize = TdiAddressSizeFromName(Address); + + ConnectInfo = (PTDI_CONNECTION_INFORMATION) + ExAllocatePool(NonPagedPool, + sizeof(TDI_CONNECTION_INFORMATION) + + TdiAddressSize); + if (!ConnectInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(ConnectInfo, + sizeof(TDI_CONNECTION_INFORMATION) + + TdiAddressSize); + + ConnectInfo->RemoteAddressLength = TdiAddressSize; + ConnectInfo->RemoteAddress = (PVOID) + (ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + TdiBuildAddress(ConnectInfo->RemoteAddress, Address); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + &Event, /* Event */ + &Iosb); /* Status */ + if (!Irp) { + AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n")); + ExFreePool(ConnectInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#if 0 + Mdl = IoAllocateMdl(Buffer, /* Virtual address of buffer */ + BufferSize, /* Length of buffer */ + FALSE, /* Not secondary */ + FALSE, /* Don't charge quota */ + NULL); /* Don't use IRP */ + if (!Mdl) { + AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n")); + IoFreeIrp(Irp); + ExFreePool(ConnectInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } +#ifdef _MSC_VER + try { +#endif + MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); +#ifdef _MSC_VER + } except(EXCEPTION_EXECUTE_HANDLER) { + AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); + IoFreeIrp(Irp); + ExFreePool(ConnectInfo); + return STATUS_UNSUCCESSFUL; + } +#endif +#endif + + TdiBuildSendDatagram(Irp, /* I/O Request Packet */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Completion routine */ + NULL, /* Completion context */ + Mdl, /* Descriptor for data buffer */ + BufferSize, /* Size of data to send */ + ConnectInfo); /* Connection information */ + + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + +#if 0 + MmUnlockPages(Mdl); + + IoFreeMdl(Mdl); +#endif + + ExFreePool(ConnectInfo); + + return Status; +} + + +NTSTATUS TdiReceiveDatagram( + PFILE_OBJECT TransportObject, + LPSOCKADDR From, + LPSOCKADDR Address, + PUCHAR Buffer, + PULONG BufferSize) +/* + * FUNCTION: Receives a datagram + * ARGUMENTS: + * TransportObject = Pointer to transport object + * From = Receive filter (NULL if none) + * Address = Address of buffer to place remote address + * Buffer = Address of buffer to place received data + * BufferSize = Address of buffer with length of Buffer (updated) + * RETURNS: + * Status of operation + */ +{ + PTDI_CONNECTION_INFORMATION ReceiveInfo; + PTDI_CONNECTION_INFORMATION ReturnInfo; + PTA_ADDRESS_IP ReturnAddress; + PDEVICE_OBJECT DeviceObject; + IO_STATUS_BLOCK Iosb; + DWORD TdiAddressSize; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + PMDL Mdl; + + if (From != NULL) { + /* FIXME: Check that the socket type match the socket */ + } + + DeviceObject = IoGetRelatedDeviceObject(TransportObject); + if (!DeviceObject) { + AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); + return STATUS_INVALID_PARAMETER; + } + + /* FIXME: Get from socket information */ + TdiAddressSize = sizeof(TA_ADDRESS_IP); + + ReceiveInfo = (PTDI_CONNECTION_INFORMATION) + ExAllocatePool(NonPagedPool, + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TDI_CONNECTION_INFORMATION) + + 2 * TdiAddressSize); + if (!ReceiveInfo) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(ReceiveInfo, + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TDI_CONNECTION_INFORMATION) + + 2 * TdiAddressSize); + + if (From != NULL) { + ReceiveInfo->RemoteAddressLength = TdiAddressSize; + ReceiveInfo->RemoteAddress = (PVOID) + (ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION)); + /* Filter datagrams */ + TdiBuildAddress(ReceiveInfo->RemoteAddress, From); + } else { + /* Receive from any address */ + ReceiveInfo->RemoteAddressLength = 0; + ReceiveInfo->RemoteAddress = NULL; + } + + ReturnInfo = (PTDI_CONNECTION_INFORMATION) + (ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize); + ReturnInfo->RemoteAddressLength = TdiAddressSize; + ReturnInfo->RemoteAddress = (PVOID) + (ReturnInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, /* Sub function */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + &Event, /* Event */ + &Iosb); /* Status */ + if (!Irp) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + ExFreePool(ReceiveInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Mdl = IoAllocateMdl(Buffer, /* Virtual address */ + *BufferSize, /* Length of buffer */ + FALSE, /* Not secondary */ + FALSE, /* Don't charge quota */ + NULL); /* Don't use IRP */ + if (!Mdl) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + IoFreeIrp(Irp); + ExFreePool(ReceiveInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#ifdef _MSC_VER + try { +#endif + MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); +#ifdef _MSC_VER + } except (EXCEPTION_EXECUTE_HANDLER) { + AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); + IoFreeMdl(Mdl); + IoFreeIrp(Irp); + ExFreePool(ReceiveInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } +#endif + + TdiBuildReceiveDatagram(Irp, /* I/O Request Packet */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Completion routine */ + NULL, /* Completion context */ + Mdl, /* Data buffer */ + *BufferSize, /* Size of data buffer */ + ReceiveInfo, /* Connection information */ + ReturnInfo, /* Connection information */ + TDI_RECEIVE_NORMAL); /* Flags */ + Status = TdiCall(Irp, DeviceObject, &Event, &Iosb); + if (NT_SUCCESS(Status)) { + *BufferSize = Iosb.Information; + TdiBuildName(Address, ReturnInfo->RemoteAddress); + } + + MmUnlockPages(Mdl); + + IoFreeMdl(Mdl); + + ExFreePool(ReceiveInfo); + + return Status; +} + +/* EOF */ diff --git a/drivers/net/afd/include/afd.h b/drivers/net/afd/include/afd.h new file mode 100644 index 0000000..1dc02f0 --- /dev/null +++ b/drivers/net/afd/include/afd.h @@ -0,0 +1,409 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: include/afd.h + * PURPOSE: Main driver header + */ +#ifndef __AFD_H +#define __AFD_H + +#include +#include +#include +#include +#include +#include + +/* Forward declarations */ +struct _AFDFCB; + +typedef struct _DEVICE_EXTENSION { + PDEVICE_OBJECT StorageDevice; + KSPIN_LOCK FCBListLock; + LIST_ENTRY FCBListHead; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +/* Context Control Block structure */ +typedef struct _AFDCCB { + struct _AFDFCB *FCB; + LIST_ENTRY ListEntry; + PFILE_OBJECT FileObject; + ULONG Flags; + LARGE_INTEGER CurrentByteOffset; +} AFDCCB, *PAFDCCB; + +/* Flags for CCB structure */ +#define CCB_CLEANED 0x00000001 + +/* Borrowed from http://www.acc.umu.se/~bosse/ntifs.h by Bo Branten */ +typedef struct _FSRTL_COMMON_FCB_HEADER { + CSHORT NodeTypeCode; + CSHORT NodeByteSize; + UCHAR Flags; + UCHAR IsFastIoPossible; + UCHAR Flags2; + UCHAR Reserved; + PERESOURCE Resource; + PERESOURCE PagingIoResource; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + LARGE_INTEGER ValidDataLength; +} FSRTL_COMMON_FCB_HEADER, *PFSRTL_COMMON_FCB_HEADER; + +typedef struct _FsdNTRequiredFCB { + FSRTL_COMMON_FCB_HEADER CommonFCBHeader; + SECTION_OBJECT_POINTERS SectionObject; + ERESOURCE MainResource; + ERESOURCE PagingIoResource; +} FsdNTRequiredFCB, *PFsdNTRequiredFCB; + +typedef struct _AFDFCB { + FsdNTRequiredFCB NTRequiredFCB; + LIST_ENTRY ListEntry; + BOOL CommandChannel; + PDEVICE_EXTENSION DeviceExt; + SHARE_ACCESS ShareAccess; + ULONG ReferenceCount; + ULONG OpenHandleCount; + HANDLE TdiAddressObjectHandle; + PFILE_OBJECT TdiAddressObject; + HANDLE TdiConnectionObjectHandle; + PFILE_OBJECT TdiConnectionObject; + LIST_ENTRY CCBListHead; + INT AddressFamily; + INT SocketType; + INT Protocol; + SOCKADDR SocketName; + PVOID HelperContext; + DWORD NotificationEvents; + UNICODE_STRING TdiDeviceName; + DWORD State; + PVOID SendBuffer; + LIST_ENTRY ReceiveQueue; + KSPIN_LOCK ReceiveQueueLock; + LIST_ENTRY ReadRequestQueue; + KSPIN_LOCK ReadRequestQueueLock; + /* For WSAEventSelect() */ + WSANETWORKEVENTS NetworkEvents; + WSAEVENT EventObjects[FD_MAX_EVENTS]; +} AFDFCB, *PAFDFCB; + +/* Socket states */ +#define SOCKET_STATE_CREATED 0 +#define SOCKET_STATE_BOUND 1 +#define SOCKET_STATE_LISTENING 2 +#define SOCKET_STATE_CONNECTED 3 + +typedef struct _AFD_BUFFER { + LIST_ENTRY ListEntry; + WSABUF Buffer; +} AFD_BUFFER, *PAFD_BUFFER; + +typedef struct _AFD_READ_REQUEST { + LIST_ENTRY ListEntry; + PIRP Irp; + PFILE_REQUEST_RECVFROM RecvFromRequest; + PFILE_REPLY_RECVFROM RecvFromReply; +} AFD_READ_REQUEST, *PAFD_READ_REQUEST; + +typedef struct IPSNMP_INFO { + ULONG Forwarding; + ULONG DefaultTTL; + ULONG InReceives; + ULONG InHdrErrors; + ULONG InAddrErrors; + ULONG ForwDatagrams; + ULONG InUnknownProtos; + ULONG InDiscards; + ULONG InDelivers; + ULONG OutRequests; + ULONG RoutingDiscards; + ULONG OutDiscards; + ULONG OutNoRoutes; + ULONG ReasmTimeout; + ULONG ReasmReqds; + ULONG ReasmOks; + ULONG ReasmFails; + ULONG FragOks; + ULONG FragFails; + ULONG FragCreates; + ULONG NumIf; + ULONG NumAddr; + ULONG NumRoutes; +} IPSNMP_INFO, *PIPSNMP_INFO; + +typedef struct IPADDR_ENTRY { + ULONG Addr; + ULONG Index; + ULONG Mask; + ULONG BcastAddr; + ULONG ReasmSize; + USHORT Context; + USHORT Pad; +} IPADDR_ENTRY, *PIPADDR_ENTRY; + + +#define TL_INSTANCE 0 + +#define IP_MIB_STATS_ID 0x1 +#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 + + +/* IPv4 header format */ +typedef struct IPv4_HEADER { + UCHAR VerIHL; /* 4-bit version, 4-bit Internet Header Length */ + UCHAR Tos; /* Type of Service */ + USHORT TotalLength; /* Total Length */ + USHORT Id; /* Identification */ + USHORT FlagsFragOfs; /* 3-bit Flags, 13-bit Fragment Offset */ + UCHAR Ttl; /* Time to Live */ + UCHAR Protocol; /* Protocol */ + USHORT Checksum; /* Header Checksum */ + ULONG SrcAddr; /* Source Address */ + ULONG DstAddr; /* Destination Address */ +} IPv4_HEADER, *PIPv4_HEADER; + + +/* IOCTL codes */ + +#define IOCTL_TCP_QUERY_INFORMATION_EX \ + CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS) + +#define IOCTL_TCP_SET_INFORMATION_EX \ + CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + +#ifdef i386 + +/* DWORD network to host byte order conversion for i386 */ +#define DN2H(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* DWORD host to network byte order conversion for i386 */ +#define DH2N(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* WORD network to host order conversion for i386 */ +#define WN2H(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +/* WORD host to network byte order conversion for i386 */ +#define WH2N(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +#else /* i386 */ + +/* DWORD network to host byte order conversion for other architectures */ +#define DN2H(dw) \ + (dw) + +/* DWORD host to network byte order conversion for other architectures */ +#define DH2N(dw) \ + (dw) + +/* WORD network to host order conversion for other architectures */ +#define WN2H(w) \ + (w) + +/* WORD host to network byte order conversion for other architectures */ +#define WH2N(w) \ + (w) + +#endif /* i386 */ + + +extern NPAGED_LOOKASIDE_LIST BufferLookasideList; +extern NPAGED_LOOKASIDE_LIST ReadRequestLookasideList; + + +/* Prototypes from dispatch.c */ + +NTSTATUS AfdDispBind( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispListen( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispSendTo( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispRecvFrom( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispSelect( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispEventSelect( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispEnumNetworkEvents( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispRecv( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispSend( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS AfdDispConnect( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +/* Prototypes from event.c */ + +NTSTATUS AfdRegisterEventHandlers( + PAFDFCB FCB); + +NTSTATUS AfdDeregisterEventHandlers( + PAFDFCB FCB); + +/* Prototypes from opnclose.c */ + +NTSTATUS STDCALL AfdCreate( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL AfdClose( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* Prototypes from rdwr.c */ + +NTSTATUS AfdEventReceiveDatagramHandler( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG * BytesTaken, + IN PVOID Tsdu, + OUT PIRP * IoRequestPacket); + +NTSTATUS STDCALL AfdRead( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS STDCALL AfdWrite( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +/* Prototypes from routines.c */ + +ULONG WSABufferSize( + LPWSABUF Buffers, + DWORD BufferCount); + +NTSTATUS MergeWSABuffers( + LPWSABUF Buffers, + DWORD BufferCount, + PVOID Destination, + ULONG MaxLength, + PULONG BytesCopied); + +NTSTATUS FillWSABuffers( + PAFDFCB FCB, + LPWSABUF Buffers, + DWORD BufferCount, + PULONG BytesCopied); + +VOID BuildIPv4Header( + PIPv4_HEADER IPHeader, + ULONG TotalSize, + ULONG Protocol, + PSOCKADDR SourceAddress, + PSOCKADDR DestinationAddress); + +/* Prototypes from tdi.c */ + +NTSTATUS TdiCloseDevice( + HANDLE Handle, + PFILE_OBJECT FileObject); + +NTSTATUS TdiOpenAddressFileIPv4( + PUNICODE_STRING DeviceName, + LPSOCKADDR Name, + PHANDLE AddressHandle, + PFILE_OBJECT *AddressObject); + +NTSTATUS TdiOpenAddressFile( + PUNICODE_STRING DeviceName, + LPSOCKADDR Name, + PHANDLE AddressHandle, + PFILE_OBJECT *AddressObject); + +NTSTATUS TdiOpenConnectionEndpointFile( + PUNICODE_STRING DeviceName, + PHANDLE ConnectionHandle, + PFILE_OBJECT *ConnectionObject); + +NTSTATUS TdiConnect( + PFILE_OBJECT ConnectionObject, + LPSOCKADDR RemoteAddress); + +NTSTATUS TdiAssociateAddressFile( + HANDLE AddressHandle, + PFILE_OBJECT ConnectionObject); + +NTSTATUS TdiSetEventHandler( + PFILE_OBJECT FileObject, + LONG EventType, + PVOID Handler, + PVOID Context); + +NTSTATUS TdiQueryDeviceControl( + PFILE_OBJECT FileObject, + ULONG IoControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + PULONG Return); + +NTSTATUS TdiQueryInformationEx( + PFILE_OBJECT FileObject, + ULONG Entity, + ULONG Instance, + ULONG Class, + ULONG Type, + ULONG Id, + PVOID OutputBuffer, + PULONG OutputLength); + +NTSTATUS TdiQueryAddress( + PFILE_OBJECT FileObject, + PULONG Address); + +NTSTATUS TdiSend( + PFILE_OBJECT TransportObject, + PVOID Buffer, + ULONG BufferSize); + +NTSTATUS TdiSendDatagram( + PFILE_OBJECT TransportObject, + LPSOCKADDR Address, + PMDL Mdl, + ULONG BufferSize); + +#endif /*__AFD_H */ + +/* EOF */ diff --git a/drivers/net/afd/include/debug.h b/drivers/net/afd/include/debug.h new file mode 100644 index 0000000..dc1fe31 --- /dev/null +++ b/drivers/net/afd/include/debug.h @@ -0,0 +1,97 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_CHECK 0x00000100 +#define DEBUG_IRP 0x00000200 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#ifdef _MSC_VER + +#define AFD_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d) ", __FILE__, __LINE__); \ + DbgPrint _x_ ; \ + } + +#else /* _MSC_VER */ + +#define AFD_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_ ; \ + } + +#endif /* _MSC_VER */ + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { AFD_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } +#endif /* NASSERT */ + +#define ASSERT_KM(x) ASSERT((x) >= 0xC0000000) +#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) + +#else /* DBG */ + +#define AFD_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERTKM(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_km(x) ASSERT_KM(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#ifdef _MSC_VER + +#define UNIMPLEMENTED \ + AFD_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \ + but come back another day.\n", __FILE__, __LINE__)); + +#else /* _MSC_VER */ + +#define UNIMPLEMENTED \ + AFD_DbgPrint(MIN_TRACE, ("%s at %s:%d is unimplemented, " \ + "but come back another day.\n", __FUNCTION__, __FILE__, __LINE__)); + +#endif /* _MSC_VER */ + + +#define CHECKPOINT \ + AFD_DbgPrint(DEBUG_CHECK, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/drivers/net/afd/makefile b/drivers/net/afd/makefile new file mode 100644 index 0000000..321a1ef --- /dev/null +++ b/drivers/net/afd/makefile @@ -0,0 +1,22 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = afd + +TARGET_CFLAGS = -I./include -DDBG + +TARGET_OBJECTS = \ + afd/afd.o \ + afd/dispatch.o \ + afd/event.o \ + afd/opnclose.o \ + afd/rdwr.o \ + afd/routines.o \ + afd/tdi.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/dd/ne2000/.cvsignore b/drivers/net/dd/ne2000/.cvsignore new file mode 100644 index 0000000..51ffd22 --- /dev/null +++ b/drivers/net/dd/ne2000/.cvsignore @@ -0,0 +1,4 @@ +base.tmp +junk.tmp +ne2000.coff +temp.exp \ No newline at end of file diff --git a/drivers/net/dd/ne2000/Makefile b/drivers/net/dd/ne2000/Makefile new file mode 100644 index 0000000..d4a1e73 --- /dev/null +++ b/drivers/net/dd/ne2000/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../../.. + +TARGET_TYPE = driver + +TARGET_NAME = ne2000 + +TARGET_CFLAGS = -I./include + +TARGET_OBJECTS = \ + ne2000/8390.o \ + ne2000/main.o + +TARGET_DDKLIBS = ndis.a + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/dd/ne2000/include/8390.h b/drivers/net/dd/ne2000/include/8390.h new file mode 100644 index 0000000..57b3107 --- /dev/null +++ b/drivers/net/dd/ne2000/include/8390.h @@ -0,0 +1,161 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Novell Eagle 2000 driver + * FILE: include/8390.h + * PURPOSE: National Semiconductor 8390 NIC definitions + */ +#ifndef __8390_H +#define __8390_H + +/* Page 0 register layout (PS1 = 0, PS0 = 0) */ +#define PG0_CR 0x00 /* Command Register (R/W) */ +#define PG0_CLDA0 0x01 /* Current Local DMA Address 0 (R) */ +#define PG0_PSTART 0x01 /* Page Start Register (W) */ +#define PG0_CLDA1 0x02 /* Current Local DMA Address 1 (R) */ +#define PG0_PSTOP 0x02 /* Page Stop Register (W) */ +#define PG0_BNRY 0x03 /* Boundary Pointer (R/W) */ +#define PG0_TSR 0x04 /* Transmit Status Register (R) */ +#define PG0_TPSR 0x04 /* Transmit Page Start Register (W) */ +#define PG0_NCR 0x05 /* Number of Collisions Register (R) */ +#define PG0_TBCR0 0x05 /* Transmit Byte Count Register 0 (W) */ +#define PG0_FIFO 0x06 /* FIFO (R) */ +#define PG0_TBCR1 0x06 /* Transmit Byte Count Register 1 (W) */ +#define PG0_ISR 0x07 /* Interrupt Status Register (R/W) */ +#define PG0_CRDA0 0x08 /* Current Remote DMA Address 0 (R) */ +#define PG0_RSAR0 0x08 /* Remote Start Address Register 0 (W) */ +#define PG0_CRDA1 0x09 /* Current Remote DMA Address 1 (R) */ +#define PG0_RSAR1 0x09 /* Remote Start Address Register 1 (W) */ +#define PG0_RBCR0 0x0A /* Remote Byte Count Register 0 (W) */ +#define PG0_RBCR1 0x0B /* Remote Byte Count Register 1 (W) */ +#define PG0_RSR 0x0C /* Receive Status Register (R) */ +#define PG0_RCR 0x0C /* Receive Configuration Register (W) */ +#define PG0_CNTR0 0x0D /* Tally Counter 0 (Frame Alignment Errors) (R) */ +#define PG0_TCR 0x0D /* Transmit Configuration Register (W) */ +#define PG0_CNTR1 0x0E /* Tally Counter 1 (CRC Errors) (R) */ +#define PG0_DCR 0x0E /* Data Configuration Register (W) */ +#define PG0_CNTR2 0x0F /* Tally Counter 2 (Missed Packet Errors) (R) */ +#define PG0_IMR 0x0F /* Interrupt Mask Register (W) */ + +/* Page 1 register layout (PS1 = 0, PS0 = 1) */ +#define PG1_CR 0x00 /* Command Register (R/W) */ +#define PG1_PAR 0x01 /* Physical Address Registers (6 registers) (R/W) */ +#define PG1_CURR 0x07 /* Current Page Register (R/W) */ +#define PG1_MAR 0x08 /* Multicast Address Registers (8 registers) (R/W) */ + +/* Page 2 register layout (PS1 = 1, PS0 = 0) */ +#define PG2_CR 0x00 /* Command Register (R/W) */ +#define PG2_PSTART 0x01 /* Page Start Register (R) */ +#define PG2_CLDA0 0x01 /* Current Local DMA Address 0 (W) */ +#define PG2_PSTOP 0x02 /* Page Stop Register (R) */ +#define PG2_CLDA1 0x02 /* Current Local DMA Address 1 (W) */ +#define PG2_RNPP 0x03 /* Remote Next Packet Pointer (R/W) */ +#define PG2_TPSR 0x04 /* Transmit Page Start Address (R) */ +#define PG2_LNPP 0x05 /* Local Next Packet Pointer (R/W) */ +#define PG2_AC1 0x06 /* Address Counter (Upper) (R/W) */ +#define PG2_AC0 0x07 /* Address Counter (Lower) (R/W) */ +#define PG2_RCR 0x0C /* Receive Configuration Register (R) */ +#define PG2_TCR 0x0D /* Transmit Configuration Register (R) */ +#define PG2_DCR 0x0E /* Data Configuration Register (R) */ +#define PG2_IMR 0x0F /* Interrupt Mask Register (R) */ + +/* Bits in PGX_CR - Command Register */ +#define CR_STP 0x01 /* Stop chip */ +#define CR_STA 0x02 /* Start chip */ +#define CR_TXP 0x04 /* Transmit a frame */ +#define CR_RD0 0x08 /* Remote read */ +#define CR_RD1 0x10 /* Remote write */ +#define CR_RD2 0x20 /* Abort/complete remote DMA */ +#define CR_PAGE0 0x00 /* Select page 0 of chip registers */ +#define CR_PAGE1 0x40 /* Select page 1 of chip registers */ +#define CR_PAGE2 0x80 /* Select page 2 of chip registers */ + +/* Bits in PG0_ISR - Interrupt Status Register */ +#define ISR_PRX 0x01 /* Packet received, no errors */ +#define ISR_PTX 0x02 /* Packet transmitted, no errors */ +#define ISR_RXE 0x04 /* Receive error */ +#define ISR_TXE 0x08 /* Transmit error */ +#define ISR_OVW 0x10 /* Overwrite warning */ +#define ISR_CNT 0x20 /* Counter overflow */ +#define ISR_RDC 0x40 /* Remote DMA complete */ +#define ISR_RST 0x80 /* Reset status */ + +/* Bits in PG0_TSR - Transmit Status Register */ +#define TSR_PTX 0x01h /* Packet transmitted without error */ +#define TSR_COL 0x04h /* Collided at least once */ +#define TSR_ABT 0x08h /* Collided 16 times and was dropped */ +#define TSR_CRS 0x10h /* Carrier sense lost */ +#define TSR_FU 0x20h /* Transmit FIFO Underrun */ +#define TSR_CDH 0x40h /* Collision detect heartbeat */ +#define TSR_OWC 0x80h /* Out of window collision */ + +/* Bits for PG0_RCR - Receive Configuration Register */ +#define RCR_SEP 0x01 /* Save error packets */ +#define RCR_AR 0x02 /* Accept runt packets */ +#define RCR_AB 0x04 /* Accept broadcasts */ +#define RCR_AM 0x08 /* Accept multicast */ +#define RCR_PRO 0x10 /* Promiscuous physical addresses */ +#define RCR_MON 0x20 /* Monitor mode */ + +/* Bits in PG0_RSR - Receive Status Register */ +#define RSR_PRX 0x01 /* Received packet intact */ +#define RSR_CRC 0x02 /* CRC error */ +#define RSR_FAE 0x04 /* Frame alignment error */ +#define RSR_FO 0x08 /* FIFO overrun */ +#define RSR_MPA 0x10 /* Missed packet */ +#define RSR_PHY 0x20 /* Physical/multicast address */ +#define RSR_DIS 0x40 /* Receiver disabled (monitor mode) */ +#define RSR_DFR 0x80 /* Deferring */ + +/* Bits in PG0_TCR - Transmit Configuration Register */ +#define TCR_CRC 0x01 /* Inhibit CRC, do not append CRC */ +#define TCR_LOOP 0x02 /* Set loopback mode */ +#define TCR_LB01 0x06 /* Encoded loopback control */ +#define TCR_ATD 0x08 /* Auto transmit disable */ +#define TCR_OFST 0x10 /* Collision offset enable */ + +/* Bits in PG0_DCR - Data Configuration Register */ +#define DCR_WTS 0x01 /* Word transfer mode selection */ +#define DCR_BOS 0x02 /* Byte order selection */ +#define DCR_LAS 0x04 /* Long address selection */ +#define DCR_LS 0x08 /* Loopback select (when 0) */ +#define DCR_ARM 0x10 /* Autoinitialize remote */ +#define DCR_FT00 0x00 /* Burst length selection (1 word/2 bytes) */ +#define DCR_FT01 0x20 /* burst length selection (2 words/4 bytes) */ +#define DCR_FT10 0x40 /* Burst length selection (4 words/8 bytes) */ +#define DCR_FT11 0x60 /* Burst length selection (6 words/12 bytes) */ + +/* Bits in PG0_IMR - Interrupt Mask Register */ +#define IMR_PRXE 0x01 /* Packet received interrupt enable */ +#define IMR_PTXE 0x02 /* Packet transmitted interrupt enable */ +#define IMR_RXEE 0x04 /* Receive error interrupt enable */ +#define IMR_TXEE 0x08 /* Transmit error interrupt enable */ +#define IMR_OVWE 0x10 /* Overwrite warning interrupt enable */ +#define IMR_CNTE 0x20 /* Counter overflow interrupt enable */ +#define IMR_RDCE 0x40 /* Remote DMA complete interrupt enable */ +#define IMR_ALLE 0x7F /* All interrupts enable */ + + +/* NIC prepended structure to a received packet */ +typedef struct _PACKET_HEADER { + UCHAR Status; /* See RSR_* constants */ + UCHAR NextPacket; /* Pointer to next packet in chain */ + USHORT PacketLength; /* Length of packet including this header */ +} PACKET_HEADER, PPACKET_HEADER; + + +#define NICDisableInterrupts(Adapter) { \ + NDIS_DbgPrint(MAX_TRACE, ("NICDisableInterrupts()\n")); \ + NdisRawWritePortUchar((Adapter)->IOBase + PG0_IMR, 0x00); \ +} + +#define NICEnableInterrupts(Adapter) { \ + NDIS_DbgPrint(MAX_TRACE, ("NICEnableInterrupts() Mask (0x%X)\n", (Adapter)->InterruptMask)); \ + NdisRawWritePortUchar((Adapter)->IOBase + PG0_IMR, (Adapter)->InterruptMask); \ +} + +VOID MiniportHandleInterrupt( + IN NDIS_HANDLE MiniportAdapterContext); + +#endif /* __8390_H */ + +/* EOF */ diff --git a/drivers/net/dd/ne2000/include/debug.h b/drivers/net/dd/ne2000/include/debug.h new file mode 100644 index 0000000..5b96c6f --- /dev/null +++ b/drivers/net/dd/ne2000/include/debug.h @@ -0,0 +1,92 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Novell Eagle 2000 driver + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_MEMORY 0x00000100 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern ULONG DebugTraceLevel; + +#ifdef _MSC_VER + +#define NDIS_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d) ", __FILE__, __LINE__); \ + DbgPrint _x_ ; \ + } + +#else /* _MSC_VER */ + +#define NDIS_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_ ; \ + } + +#endif /* _MSC_VER */ + + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { NDIS_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } +#endif /* NASSERT */ + +#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) + +#else /* DBG */ + +#define NDIS_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#ifdef _MSC_VER + +#define UNIMPLEMENTED \ + NDIS_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \ + but come back another day.\n", __FILE__, __LINE__)); + +#else /* _MSC_VER */ + +#define UNIMPLEMENTED \ + NDIS_DbgPrint(MIN_TRACE, ("%s at %s:%d is unimplemented, \ + but come back another day.\n", __FUNCTION__, __FILE__, __LINE__)); + +#endif /* _MSC_VER */ + + +#define CHECKPOINT \ + do { NDIS_DbgPrint(MIN_TRACE, ("%s:%d\n", __FILE__, __LINE__)); } while(0); + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/drivers/net/dd/ne2000/include/ne2000.h b/drivers/net/dd/ne2000/include/ne2000.h new file mode 100644 index 0000000..0da7d50 --- /dev/null +++ b/drivers/net/dd/ne2000/include/ne2000.h @@ -0,0 +1,250 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Novell Eagle 2000 driver + * FILE: include/ne2000.h + * PURPOSE: NE2000 driver definitions + */ +#ifndef __NE2000_H +#define __NE2000_H + +#ifdef _MSC_VER + +#ifndef ULONG_PTR +#define ULONG ULONG_PTR +#endif + +#include +#else +#include +#endif +#include <8390.h> +#include + +/* Define NOCARD to test NDIS without a card */ +//#define NOCARD + +/* NE2000 sepcific constants */ +#define NIC_DATA 0x10 /* Data register */ +#define NIC_RESET 0x1F /* Reset register */ + + +/* Global constants */ + +#define DRIVER_NDIS_MAJOR_VERSION 3 +#define DRIVER_NDIS_MINOR_VERSION 0 + +#define DRIVER_DEFAULT_IO_BASE_ADDRESS 0x300 +#define DRIVER_DEFAULT_INTERRUPT_NUMBER 10 + +#define DRIVER_MAX_MULTICAST_LIST_SIZE 8 + +#define DRIVER_VENDOR_DESCRIPTION "Novell Eagle 2000 Adapter." +#define DRIVER_VENDOR_DRIVER_VERSION 0x0100 /* 1.0 */ + +#define DRIVER_FRAME_SIZE 1514 /* Size of an ethernet frame */ +#define DRIVER_HEADER_SIZE 14 /* Size of an ethernet header */ +#define DRIVER_LENGTH_OF_ADDRESS 6 /* Size of an ethernet address */ + +/* Maximum lookahead buffer size */ +#define DRIVER_MAXIMUM_LOOKAHEAD (252 - DRIVER_HEADER_SIZE) + +/* Size of a block in a buffer ring */ +#define DRIVER_BLOCK_SIZE 256 + + +/* Default number of transmit buffers */ +#define DRIVER_DEFAULT_TX_BUFFER_COUNT 12 +#define BUFFERS_PER_TX_BUF 1 + +/* Interrupt Mask Register value */ +#define DRIVER_INTERRUPT_MASK IMR_ALLE - IMR_RDCE + + + +/* Global structures */ + +typedef struct _MINIPORT_RESERVED +{ + PNDIS_PACKET Next; +} MINIPORT_RESERVED, *PMINIPORT_RESERVED; + +#define RESERVED(Packet) ((PMINIPORT_RESERVED)((Packet)->u.s1.MiniportReserved)) + +typedef UCHAR DRIVER_HARDWARE_ADDRESS[DRIVER_LENGTH_OF_ADDRESS]; + +/* Information about an adapter */ +typedef struct _NIC_ADAPTER +{ + /* Entry on global adapter list */ + LIST_ENTRY ListEntry; + /* Adapter handle */ + NDIS_HANDLE MiniportAdapterHandle; + /* NDIS interrupt object */ + NDIS_MINIPORT_INTERRUPT Interrupt; + + /* I/O base address and interrupt number of adapter */ + ULONG IoBaseAddress; + ULONG InterruptNumber; + + /* Mapped address of the I/O base port */ + PUCHAR IOBase; + + /* TRUE if the NIC can transfer in word mode */ + BOOLEAN WordMode; + + /* Base address and size of the onboard memory window */ + PUCHAR RamBase; + UINT RamSize; + + /* Station Address PROM (SAPROM) */ + UCHAR SAPROM[16]; + + /* Onboard ethernet address from the manufacturer */ + DRIVER_HARDWARE_ADDRESS PermanentAddress; + + /* Ethernet address currently in use */ + DRIVER_HARDWARE_ADDRESS StationAddress; + + /* Maximum number of multicast addresses this adapter supports */ + ULONG MaxMulticastListSize; + + /* List of multicast addresses in use */ + DRIVER_HARDWARE_ADDRESS Addresses[DRIVER_MAX_MULTICAST_LIST_SIZE]; + + /* Current multicast address mask */ + UCHAR MulticastAddressMask[8]; + + /* Masked interrupts (IMR value) */ + ULONG InterruptMask; + + /* Interrupts that have occurred */ + UCHAR InterruptStatus; + + /* Current packet filter */ + ULONG PacketFilter; + + /* Lookahead buffer */ + UINT LookaheadSize; + UCHAR Lookahead[DRIVER_MAXIMUM_LOOKAHEAD + DRIVER_HEADER_SIZE]; + + /* Receive buffer ring */ + UINT PageStart; + UINT PageStop; + UINT CurrentPage; + UINT NextPacket; + + /* TRUE if there was a buffer overflow */ + BOOLEAN BufferOverflow; + + /* TRUE if an error occurred during reception of a packet */ + BOOLEAN ReceiveError; + + /* TRUE if an error occurred during transmission of a packet */ + BOOLEAN TransmitError; + + /* TRUE if a transmit interrupt is pending */ + BOOLEAN TransmitPending; + + /* Received packet header */ + PACKET_HEADER PacketHeader; + + /* Offset in onboard RAM of received packet */ + ULONG PacketOffset; + + /* TRUE if receive indications are done and should be completed */ + BOOLEAN DoneIndicating; + + /* Transmit buffers */ + UINT TXStart; /* Start block of transmit buffer ring */ + UINT TXCount; /* Number of blocks in transmit buffer ring */ + UINT TXFree; /* Number of free transmit buffers */ + UINT TXNext; /* Next buffer to use */ + /* Length of packet. 0 means buffer is unused */ + INT TXSize[DRIVER_DEFAULT_TX_BUFFER_COUNT]; + INT TXCurrent; /* Current buffer beeing transmitted. -1 means none */ + + /* Head of transmit queue */ + PNDIS_PACKET TXQueueHead; + /* Tail of transmit queue */ + PNDIS_PACKET TXQueueTail; + + /* Statistics */ + ULONG FrameAlignmentErrors; + ULONG CrcErrors; + ULONG MissedPackets; + + /* Flags used for driver cleanup */ + BOOLEAN IOPortRangeRegistered; + BOOLEAN InterruptRegistered; +} NIC_ADAPTER, *PNIC_ADAPTER; + +/* Global driver information */ +typedef struct _DRIVER_INFORMATION +{ + NDIS_HANDLE NdisWrapperHandle; /* Returned from NdisInitializeWrapper */ + NDIS_HANDLE NdisMacHandle; /* Returned from NdisRegisterMac */ + LIST_ENTRY AdapterListHead; /* Adapters this driver control */ +} DRIVER_INFORMATION, *PDRIVER_INFORMATION; + + + +/* Global variable */ + +extern DRIVER_INFORMATION DriverInfo; +extern NDIS_PHYSICAL_ADDRESS HighestAcceptableMax; + + + +/* Prototypes */ + +BOOLEAN NICCheck( + PNIC_ADAPTER Adapter); + +NDIS_STATUS NICInitialize( + PNIC_ADAPTER Adapter); + +NDIS_STATUS NICSetup( + PNIC_ADAPTER Adapter); + +NDIS_STATUS NICStart( + PNIC_ADAPTER Adapter); + +NDIS_STATUS NICStop( + PNIC_ADAPTER Adapter); + +NDIS_STATUS NICReset( + PNIC_ADAPTER Adapter); + +VOID NICUpdateCounters( + PNIC_ADAPTER Adapter); + +VOID NICReadDataAlign( + PNIC_ADAPTER Adapter, + PUSHORT Target, + ULONG Source, + USHORT Length); + +VOID NICWriteDataAlign( + PNIC_ADAPTER Adapter, + ULONG Target, + PUSHORT Source, + USHORT Length); + +VOID NICReadData( + PNIC_ADAPTER Adapter, + PUCHAR Target, + ULONG Source, + USHORT Length); + +VOID NICWriteData( + PNIC_ADAPTER Adapter, + ULONG Target, + PUCHAR Source, + USHORT Length); + +VOID NICTransmit( + PNIC_ADAPTER Adapter); + +#endif /* __NE2000_H */ + +/* EOF */ diff --git a/drivers/net/dd/ne2000/ne2000.rc b/drivers/net/dd/ne2000/ne2000.rc new file mode 100644 index 0000000..d345102 --- /dev/null +++ b/drivers/net/dd/ne2000/ne2000.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Novell NE2000 network driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "ne2000\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ne2000.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/net/dd/ne2000/ne2000/8390.c b/drivers/net/dd/ne2000/ne2000/8390.c new file mode 100644 index 0000000..2c285d2 --- /dev/null +++ b/drivers/net/dd/ne2000/ne2000/8390.c @@ -0,0 +1,1367 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Novell Eagle 2000 driver + * FILE: ne2000/8390.c + * PURPOSE: DP8390 NIC specific routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 27/08-2000 Created + */ +#include + + +BOOLEAN NICCheck( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Tests for a NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * TRUE if NIC is believed to be present, FALSE if not + * NOTES: + * If the adapter responds correctly to a + * stop command we assume it is present + */ +{ + UCHAR Tmp; + + /* Disable interrupts */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_IMR, 0); + + /* Stop the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2); + + /* Pause for 1.6ms */ + NdisStallExecution(1600); + + /* Read NIC response */ + NdisRawReadPortUchar(Adapter->IOBase + PG0_CR, &Tmp); + + if ((Tmp == (CR_RD2 | CR_STP)) || (Tmp == (CR_RD2 | CR_STP | CR_STA))) + return TRUE; + else + return FALSE; +} + + +BOOLEAN NICTestAddress( + PNIC_ADAPTER Adapter, + ULONG Address) +/* + * FUNCTION: Tests if an address is writable + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * TRUE if the address is writable, FALSE if not + */ +{ + USHORT Data; + USHORT Tmp; + + /* Read one word */ + NICReadDataAlign(Adapter, &Data, Address, 0x02); + + /* Alter it */ + Data ^= 0xFFFF; + + /* Write it back */ + NICWriteDataAlign(Adapter, Address, &Data, 0x02); + + /* Check if it has changed on the NIC */ + NICReadDataAlign(Adapter, &Tmp, Address, 0x02); + + return (Data == Tmp); +} + + +BOOLEAN NICTestRAM( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Finds out how much RAM a NIC has + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * TRUE if the RAM size was found, FALSE if not + * NOTES: + * Start at 1KB and test for every 1KB up to 64KB + */ +{ + ULONG Base; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Locate RAM base address */ + for (Base = 0x0400; Base < 0x10000; Base += 0x0400) { + if (NICTestAddress(Adapter, Base)) + break; + } + + if (Base == 0x10000) { + /* No RAM on this board */ + NDIS_DbgPrint(MIN_TRACE, ("No RAM found on board.\n")); + return FALSE; + } + + Adapter->RamBase = (PUCHAR)Base; + + /* Find RAM size */ + for (; Base < 0x10000; Base += 0x0400) { + if (!NICTestAddress(Adapter, Base)) + break; + } + + Adapter->RamSize = (UINT)(Base - (ULONG_PTR)Adapter->RamBase); + + NDIS_DbgPrint(MID_TRACE, ("RAM is at (0x%X). Size is (0x%X).\n", + Adapter->RamBase, Adapter->RamSize)); + + return TRUE; +} + + +VOID NICSetPhysicalAddress( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Initializes the physical address on the NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * NOTES: + * The physical address is taken from Adapter. + * The NIC is stopped by this operation + */ +{ + UINT i; + + /* Select page 1 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1); + + /* Initialize PAR - Physical Address Registers */ + for (i = 0; i < 0x06; i++) + NdisRawWritePortUchar(Adapter->IOBase + PG1_PAR + i, Adapter->StationAddress[i]); + + /* Go back to page 0 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); +} + + +VOID NICSetMulticastAddressMask( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Initializes the multicast address mask on the NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * NOTES: + * The multicast address mask is taken from Adapter. + * The NIC is stopped by this operation + */ +{ + UINT i; + + /* Select page 1 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1); + + /* Initialize MAR - Multicast Address Registers */ + for (i = 0; i < 0x08; i++) + NdisRawWritePortUchar(Adapter->IOBase + PG1_MAR + i, Adapter->MulticastAddressMask[i]); + + /* Go back to page 0 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); +} + + +BOOLEAN NICReadSAPROM( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Reads the Station Address PROM data from the NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * TRUE if a the NIC is an NE2000 + * NOTES: + * This routine also determines if the NIC can support word mode transfers + * and if it does initializes the NIC for word mode. + * The station address in the adapter structure is initialized with + * the address from the SAPROM + */ +{ + UINT i; + UCHAR Buffer[32]; + UCHAR WordLength; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Read Station Address PROM (SAPROM) which is 16 bytes at remote DMA address 0. + Some cards double the data read which we must compensate for */ + + /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x20); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); + + /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, 0x00); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, 0x00); + + /* Select page 0, read and start the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0); + + /* Read one byte at a time */ + WordLength = 2; /* Assume a word is two bytes */ + for (i = 0; i < 32; i += 2) { + NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i]); + NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i + 1]); + if (Buffer[i] != Buffer[i + 1]) + WordLength = 1; /* A word is one byte long */ + } + + /* If WordLength is 2 the data read before was doubled. We must compensate for this */ + if (WordLength == 2) { + DbgPrint("NE2000 or compatible network adapter found.\n"); + + Adapter->WordMode = TRUE; + + /* Move the SAPROM data to the adapter object */ + for (i = 0; i < 16; i++) + Adapter->SAPROM[i] = Buffer[i * 2]; + + /* Copy the station address */ + NdisMoveMemory( + (PVOID)&Adapter->StationAddress, + (PVOID)&Adapter->SAPROM, + DRIVER_LENGTH_OF_ADDRESS); + + /* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10); + + return TRUE; + } else { + DbgPrint("NE1000 or compatible network adapter found.\n"); + + Adapter->WordMode = FALSE; + + return FALSE; + } +} + + +NDIS_STATUS NICInitialize( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Initializes a NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * Status of NIC initialization + * NOTES: + * The NIC is put into loopback mode + */ +{ + UCHAR Tmp; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (!NICCheck(Adapter)) { + NDIS_DbgPrint(MID_TRACE, ("No adapter found at (0x%X).\n", Adapter->IOBase)); + return NDIS_STATUS_ADAPTER_NOT_FOUND; + } else + NDIS_DbgPrint(MID_TRACE, ("Adapter found at (0x%X).\n", Adapter->IOBase)); + + /* Reset the NIC */ + NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp); + + /* Wait for 1.6ms */ + NdisStallExecution(1600); + + /* Write the value back */ + NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp); + + /* Select page 0 and stop NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); + + /* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10); + + /* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); + + /* Initialize RCR - Receive Configuration Register (monitor mode) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON); + + /* Enter loopback mode (internal NIC module loopback) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); + + /* Read the Station Address PROM */ + if (!NICReadSAPROM(Adapter)) + return NDIS_STATUS_ADAPTER_NOT_FOUND; + + NDIS_DbgPrint(MID_TRACE, ("Station address is (%02X %02X %02X %02X %02X %02X).\n", + Adapter->StationAddress[0], Adapter->StationAddress[1], + Adapter->StationAddress[2], Adapter->StationAddress[3], + Adapter->StationAddress[4], Adapter->StationAddress[5])); + + /* Select page 0 and start NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); + + /* Clear ISR - Interrupt Status Register */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF); + + /* Find NIC RAM size */ + NICTestRAM(Adapter); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS NICSetup( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Sets up a NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * Status of operation + * NOTES: + * The NIC is put into loopback mode + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (Adapter->WordMode ) { + /* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10); + } else { + /* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10); + } + + /* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); + + /* Initialize RCR - Receive Configuration Register (monitor mode) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON); + + /* Enter loopback mode (internal NIC module loopback) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); + + /* Set boundary page */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, Adapter->NextPacket); + + /* Set start page */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTART, Adapter->PageStart); + + /* Set stop page */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTOP, Adapter->PageStop); + + /* Program our address on the NIC */ + NICSetPhysicalAddress(Adapter); + + /* Program the multicast address mask on the NIC */ + NICSetMulticastAddressMask(Adapter); + + /* Select page 1 and stop NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1); + + /* Initialize current page register */ + NdisRawWritePortUchar(Adapter->IOBase + PG1_CURR, Adapter->PageStart + 1); + + /* Select page 0 and stop NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); + + /* Clear ISR - Interrupt Status Register */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF); + + /* Initialize IMR - Interrupt Mask Register */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_IMR, Adapter->InterruptMask); + + /* Select page 0 and start NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); + + Adapter->CurrentPage = Adapter->PageStart + 1; + Adapter->NextPacket = Adapter->PageStart + 1; + Adapter->BufferOverflow = FALSE; + Adapter->ReceiveError = FALSE; + Adapter->TransmitError = FALSE; + + NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS NICStart( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Starts a NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * Status of operation + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Take NIC out of loopback mode */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, 0x00); + + /* Initialize RCR - Receive Configuration Register (accept all) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_AB | RCR_AM | RCR_PRO); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS NICStop( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Stops a NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * Status of operation + */ +{ + UCHAR Tmp; + UINT i; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Select page 0 and stop NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); + + /* Clear Remote Byte Count Register so ISR_RST will be set */ + NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00); + NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00); + + /* Wait for ISR_RST to be set, but timeout after 2ms */ + for (i = 0; i < 4; i++) { + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); + if (Tmp & ISR_RST) + break; + + NdisStallExecution(500); + } + +#ifdef DBG + if (i == 4) + NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n")); +#endif + + /* Initialize RCR - Receive Configuration Register (monitor mode) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON); + + /* Initialize TCR - Transmit Configuration Register (loopback mode) */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); + + /* Start NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS NICReset( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Resets a NIC + * ARGUMENTS: + * Adapter = Pointer to adapter information + * RETURNS: + * Status of operation + */ +{ + UCHAR Tmp; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Stop the NIC */ + NICStop(Adapter); + + /* Reset the NIC */ + NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp); + + /* Wait for 1.6ms */ + NdisStallExecution(1600); + + /* Write the value back */ + NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp); + + /* Restart the NIC */ + NICStart(Adapter); + + return NDIS_STATUS_SUCCESS; +} + + +VOID NICStartTransmit( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Starts transmitting a packet + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + UINT Length; + UCHAR FrameStart; + UCHAR Tmp; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + //FrameStart = Adapter->TXStart + Adapter->TXCurrent * DRIVER_BLOCK_SIZE; + //FrameStart = Adapter->TXStart; + FrameStart = (UCHAR)(Adapter->TXStart + (UCHAR)(Adapter->TXCurrent * BUFFERS_PER_TX_BUF)); + + /* Set start of frame */ + NdisRawReadPortUchar(Adapter->IOBase + PG0_TPSR, &Tmp); +// NdisRawWritePortUchar(Adapter->IOBase + PG0_TPSR, +// Adapter->TXStart + Adapter->TXCurrent * DRIVER_BLOCK_SIZE); + + NdisRawWritePortUchar(Adapter->IOBase + PG0_TPSR, FrameStart); + //NDIS_DbgPrint(MID_TRACE, ("Setting start of frame to (%d).\n", FrameStart)); + + /* Set length of frame */ + Length = Adapter->TXSize[Adapter->TXCurrent]; + NdisRawWritePortUchar(Adapter->IOBase + PG0_TBCR0, Length & 0xFF); + NdisRawWritePortUchar(Adapter->IOBase + PG0_TBCR1, Length >> 8); + + /* Start transmitting */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_TXP | CR_RD2); + + NDIS_DbgPrint(MID_TRACE, ("Transmitting. FrameStart (%d) TXCurrent (%d) TXStart (%d) Length (%d).\n\n", + FrameStart, + Adapter->TXCurrent, + Adapter->TXStart, + Length)); + +} + + +VOID NICSetBoundaryPage( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Sets the boundary page on the adapter to be one less than NextPacket + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + if (Adapter->NextPacket == Adapter->PageStart) { + NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, + (UCHAR)(Adapter->PageStop - 1)); + } else { + NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, + (UCHAR)(Adapter->NextPacket - 1)); + } +} + + +VOID NICGetCurrentPage( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Retrieves the current page from the adapter + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + UCHAR Current; + + /* Select page 1 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE1); + + /* Read current page */ + NdisRawReadPortUchar(Adapter->IOBase + PG1_CURR, &Current); + + /* Select page 0 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); + + Adapter->CurrentPage = Current; +} + + +VOID NICUpdateCounters( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Updates counters + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + UCHAR Tmp; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR0, &Tmp); + Adapter->FrameAlignmentErrors += Tmp; + + NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR1, &Tmp); + Adapter->CrcErrors += Tmp; + + NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR2, &Tmp); + Adapter->MissedPackets += Tmp; +} + + +VOID NICReadDataAlign( + PNIC_ADAPTER Adapter, + PUSHORT Target, + ULONG Source, + USHORT Length) +/* + * FUNCTION: Copies data from a NIC's RAM into a buffer + * ARGUMENTS: + * Adapter = Pointer to adapter information + * Target = Pointer to buffer to copy data into (in host memory) + * Source = Offset into NIC's RAM (must be an even number) + * Length = Number of bytes to copy from NIC's RAM (must be an even number) + */ +{ + UCHAR Tmp; + USHORT Count; + + Count = Length; + + /* Select page 0 and start the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); + + /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Source & 0xFF)); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Source >> 8)); + + /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, (UCHAR)(Count & 0xFF)); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, (UCHAR)(Count >> 8)); + + /* Select page 0, read and start the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0); + + if (Adapter->WordMode) + NdisRawReadPortBufferUshort(Adapter->IOBase + NIC_DATA, Target, Count >> 1); + else + NdisRawReadPortBufferUchar(Adapter->IOBase + NIC_DATA, Target, Count); + + /* Wait for remote DMA to complete, but timeout after some time */ + for (Count = 0; Count < 0xFFFF; Count++) { + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); + if (Tmp & ISR_RDC) + break; + + NdisStallExecution(4); + } + +#ifdef DBG + if (Count == 0xFFFF) + NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n")); +#endif + + /* Clear remote DMA bit in ISR - Interrupt Status Register */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC); +} + + +VOID NICWriteDataAlign( + PNIC_ADAPTER Adapter, + ULONG Target, + PUSHORT Source, + USHORT Length) +/* + * FUNCTION: Copies data from a buffer into the NIC's RAM + * ARGUMENTS: + * Adapter = Pointer to adapter information + * Target = Offset into NIC's RAM (must be an even number) + * Source = Pointer to buffer to copy data from (in host memory) + * Length = Number of bytes to copy from the buffer (must be an even number) + */ +{ + UCHAR Tmp; + USHORT Count; + + /* Select page 0 and start the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); + + /* Handle read-before-write bug */ + + /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Target & 0xFF)); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Target >> 8)); + + /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x02); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); + + /* Read and start the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0); + + /* Read data */ + NdisRawReadPortUshort(Adapter->IOBase + NIC_DATA, &Count); + + /* Wait for remote DMA to complete, but timeout after some time */ + for (Count = 0; Count < 0xFFFF; Count++) { + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); + if (Tmp & ISR_RDC) + break; + + NdisStallExecution(4); + } + +#ifdef DBG + if (Count == 0xFFFF) + NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n")); +#endif + + /* Clear remote DMA bit in ISR - Interrupt Status Register */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC); + + + /* Now output some data */ + Count = Length; + + /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Target & 0xFF)); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Target >> 8)); + + /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, (UCHAR)(Count & 0xFF)); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, (UCHAR)(Count >> 8)); + + /* Write and start the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD1 | CR_PAGE0); + + if (Adapter->WordMode) + NdisRawWritePortBufferUshort(Adapter->IOBase + NIC_DATA, Source, Count >> 1); + else + NdisRawWritePortBufferUchar(Adapter->IOBase + NIC_DATA, Source, Count); + + /* Wait for remote DMA to complete, but timeout after some time */ + for (Count = 0; Count < 0xFFFF; Count++) { + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); + if (Tmp & ISR_RDC) + break; + + NdisStallExecution(4); + } + +#ifdef DBG + if (Count == 0xFFFF) + NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n")); +#endif + + /* Clear remote DMA bit in ISR - Interrupt Status Register */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC); +} + + +VOID NICReadData( + PNIC_ADAPTER Adapter, + PUCHAR Target, + ULONG Source, + USHORT Length) +/* + * FUNCTION: Copies data from a NIC's RAM into a buffer + * ARGUMENTS: + * Adapter = Pointer to adapter information + * Target = Pointer to buffer to copy data into (in host memory) + * Source = Offset into NIC's RAM + * Length = Number of bytes to copy from NIC's RAM + */ +{ + USHORT Tmp; + + /* Avoid transfers to odd addresses */ + if (Source & 0x01) { + /* Transfer one word and use the MSB */ + NICReadDataAlign(Adapter, &Tmp, Source - 1, 0x02); + *Target = (UCHAR)(Tmp >> 8); + Source++; + Target++; + Length--; + } + + if (Length & 0x01) { + /* Transfer as many words as we can without exceeding the buffer length */ + Tmp = Length & 0xFFFE; + NICReadDataAlign(Adapter, (PUSHORT)Target, Source, Tmp); + Source += Tmp; + (ULONG_PTR)Target += Tmp; + + /* Read one word and keep the LSB */ + NICReadDataAlign(Adapter, &Tmp, Source, 0x02); + *Target = (UCHAR)(Tmp & 0x00FF); + } else + /* Transfer the rest of the data */ + NICReadDataAlign(Adapter, (PUSHORT)Target, Source, Length); +} + + +VOID NICWriteData( + PNIC_ADAPTER Adapter, + ULONG Target, + PUCHAR Source, + USHORT Length) +/* + * FUNCTION: Copies data from a buffer into NIC's RAM + * ARGUMENTS: + * Adapter = Pointer to adapter information + * Target = Offset into NIC's RAM to store data + * Source = Pointer to buffer to copy data from (in host memory) + * Length = Number of bytes to copy from buffer + */ +{ + USHORT Tmp; + + /* Avoid transfers to odd addresses */ + if (Target & 0x01) { + /* Read one word */ + NICReadDataAlign(Adapter, &Tmp, Target - 1, 0x02); + + /* Merge LSB with the new byte which become the new MSB */ + Tmp = (Tmp & 0x00FF) | (*Source << 8); + + /* Finally write the value back */ + NICWriteDataAlign(Adapter, Target - 1, &Tmp, 0x02); + + /* Update pointers */ + (ULONG_PTR)Source += 1; + (ULONG_PTR)Target += 1; + Length--; + } + + if (Length & 0x01) { + /* Transfer as many words as we can without exceeding the transfer length */ + Tmp = Length & 0xFFFE; + NICWriteDataAlign(Adapter, Target, (PUSHORT)Source, Tmp); + Source += Tmp; + (ULONG_PTR)Target += Tmp; + + /* Read one word */ + NICReadDataAlign(Adapter, &Tmp, Target, 0x02); + + /* Merge MSB with the new byte which become the new LSB */ + Tmp = (Tmp & 0xFF00) | (*Source); + + /* Finally write the value back */ + NICWriteDataAlign(Adapter, Target, &Tmp, 0x02); + } else + /* Transfer the rest of the data */ + NICWriteDataAlign(Adapter, Target, (PUSHORT)Source, Length); +} + + +VOID NICIndicatePacket( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Indicates a packet to the wrapper + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + UINT IndicateLength; + + IndicateLength = (Adapter->PacketHeader.PacketLength < + (Adapter->LookaheadSize + DRIVER_HEADER_SIZE))? + (Adapter->PacketHeader.PacketLength) : + (Adapter->LookaheadSize + DRIVER_HEADER_SIZE); + + /* Fill the lookahead buffer */ + NICReadData(Adapter, + (PUCHAR)&Adapter->Lookahead, + Adapter->PacketOffset + sizeof(PACKET_HEADER), + IndicateLength + DRIVER_HEADER_SIZE); + + NDIS_DbgPrint(MID_TRACE, ("Indicating (%d) bytes.\n", IndicateLength)); + +#if 0 + NDIS_DbgPrint(MAX_TRACE, ("FRAME:\n")); + for (i = 0; i < (IndicateLength + 7) / 8; i++) { + NDIS_DbgPrint(MAX_TRACE, ("%02X %02X %02X %02X %02X %02X %02X %02X\n", + Adapter->Lookahead[i*8+0], + Adapter->Lookahead[i*8+1], + Adapter->Lookahead[i*8+2], + Adapter->Lookahead[i*8+3], + Adapter->Lookahead[i*8+4], + Adapter->Lookahead[i*8+5], + Adapter->Lookahead[i*8+6], + Adapter->Lookahead[i*8+7])); + } +#endif + + if (IndicateLength >= DRIVER_HEADER_SIZE) { + NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, + NULL, + (PVOID)&Adapter->Lookahead, + DRIVER_HEADER_SIZE, + (PVOID)&Adapter->Lookahead[DRIVER_HEADER_SIZE], + IndicateLength - DRIVER_HEADER_SIZE, + Adapter->PacketHeader.PacketLength - DRIVER_HEADER_SIZE); + } else { + NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, + NULL, + (PVOID)&Adapter->Lookahead, + IndicateLength, + NULL, + 0, + 0); + } +} + + +VOID NICReadPacket( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Reads a full packet from the receive buffer ring + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + BOOLEAN SkipPacket = FALSE; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Get the header of the next packet in the receive ring */ + Adapter->PacketOffset = Adapter->NextPacket << 8; + NICReadData(Adapter, + (PUCHAR)&Adapter->PacketHeader, + Adapter->PacketOffset, + sizeof(PACKET_HEADER)); + + NDIS_DbgPrint(MAX_TRACE, ("HEADER: (Status) (0x%X)\n", Adapter->PacketHeader.Status)); + NDIS_DbgPrint(MAX_TRACE, ("HEADER: (NextPacket) (0x%X)\n", Adapter->PacketHeader.NextPacket)); + NDIS_DbgPrint(MAX_TRACE, ("HEADER: (PacketLength) (0x%X)\n", Adapter->PacketHeader.PacketLength)); + + if (Adapter->PacketHeader.PacketLength < 64 || + Adapter->PacketHeader.PacketLength > 1518) { + NDIS_DbgPrint(MAX_TRACE, ("Bogus packet size (%d).\n", + Adapter->PacketHeader.PacketLength)); + SkipPacket = TRUE; + } + + if (SkipPacket) { + /* Skip packet */ + Adapter->NextPacket = Adapter->CurrentPage; + } else { + NICIndicatePacket(Adapter); + + /* Go to the next free buffer in receive ring */ + Adapter->NextPacket = Adapter->PacketHeader.NextPacket; + } + + /* Update boundary page */ + NICSetBoundaryPage(Adapter); +} + + +VOID NICWritePacket( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Writes a full packet to the transmit buffer ring + * ARGUMENTS: + * Adapter = Pointer to adapter information + * NOTES: + * There must be enough free buffers available in the transmit buffer ring. + * The packet is taken from the head of the transmit queue and the position + * into the transmit buffer ring is taken from TXNext + */ +{ + PNDIS_BUFFER SrcBuffer; + UINT BytesToCopy, SrcSize, DstSize; + PUCHAR SrcData; + ULONG DstData; + UINT TXStart; + UINT TXStop; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + TXStart = Adapter->TXStart * DRIVER_BLOCK_SIZE; + TXStop = (Adapter->TXStart + Adapter->TXCount) * DRIVER_BLOCK_SIZE; + + NdisQueryPacket(Adapter->TXQueueHead, + NULL, + NULL, + &SrcBuffer, + &Adapter->TXSize[Adapter->TXNext]); + + NDIS_DbgPrint(MID_TRACE, ("Packet (%d) is now size (%d).\n", + Adapter->TXNext, + Adapter->TXSize[Adapter->TXNext])); + + NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); + + DstData = TXStart + Adapter->TXNext * DRIVER_BLOCK_SIZE; + DstSize = TXStop - DstData; + + /* Start copying the data */ + for (;;) { + BytesToCopy = (SrcSize < DstSize)? SrcSize : DstSize; + + NICWriteData(Adapter, DstData, SrcData, BytesToCopy); + + (ULONG_PTR)SrcData += BytesToCopy; + SrcSize -= BytesToCopy; + DstData += BytesToCopy; + DstSize -= BytesToCopy; + + if (SrcSize == 0) { + /* No more bytes in source buffer. Proceed to + the next buffer in the source buffer chain */ + NdisGetNextBuffer(SrcBuffer, &SrcBuffer); + if (!SrcBuffer) + break; + + NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); + } + + if (DstSize == 0) { + /* Wrap around the end of the transmit buffer ring */ + DstData = TXStart; + DstSize = Adapter->TXCount * DRIVER_BLOCK_SIZE; + } + } +} + + +BOOLEAN NICPrepareForTransmit( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Prepares a packet for transmission + * ARGUMENTS: + * Adapter = Pointer to adapter information + * NOTES: + * There must be at least one packet in the transmit queue + * RETURNS: + * TRUE if a packet was prepared, FALSE if not + */ +{ + UINT Length; + UINT BufferCount; + PNDIS_PACKET Packet; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Calculate number of buffers needed to transmit packet */ + NdisQueryPacket(Adapter->TXQueueHead, + NULL, + NULL, + NULL, + &Length); + + BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE; + + if (BufferCount > Adapter->TXFree) { + NDIS_DbgPrint(MID_TRACE, ("No transmit resources. Have (%d) buffers, need (%d).\n", + Adapter->TXFree, BufferCount)); + /* We don't have the resources to transmit this packet right now */ + return FALSE; + } + + /* Write the packet to the card */ + NICWritePacket(Adapter); + + /* If the NIC is not transmitting, reset the current transmit pointer */ + if (Adapter->TXCurrent == -1) + Adapter->TXCurrent = Adapter->TXNext; + + Adapter->TXNext = (Adapter->TXNext + BufferCount) % Adapter->TXCount; + Adapter->TXFree -= BufferCount; + + /* Remove the packet from the queue */ + Packet = Adapter->TXQueueHead; + Adapter->TXQueueHead = RESERVED(Packet)->Next; + + if (Packet == Adapter->TXQueueTail) + Adapter->TXQueueTail = NULL; + + /* Assume the transmit went well */ + NdisMSendComplete(Adapter->MiniportAdapterHandle, + Packet, + NDIS_STATUS_SUCCESS); + + return TRUE; +} + + +VOID NICTransmit( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Starts transmitting packets in the transmit queue + * ARGUMENTS: + * Adapter = Pointer to adapter information + * NOTES: + * There must be at least one packet in the transmit queue + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (Adapter->TXCurrent == -1) { + /* NIC is not transmitting, so start transmitting now */ + + /* Load next packet onto the card, and start transmitting */ + if (NICPrepareForTransmit(Adapter)) + NICStartTransmit(Adapter); + } +} + + +VOID HandleReceive( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Handles reception of a packet + * ARGUMENTS: + * Adapter = Pointer to adapter information + * NOTES: + * Buffer overflows are also handled here + */ +{ + UINT i; + UCHAR Tmp; + UINT PacketCount; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + Adapter->DoneIndicating = FALSE; + PacketCount = 0; + + NICGetCurrentPage(Adapter); + + if (Adapter->BufferOverflow) { + + NDIS_DbgPrint(MID_TRACE, ("Receive ring overflow.\n")); + + /* Select page 0 and stop the NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); + + /* Clear RBCR0,RBCR1 - Remote Byte Count Registers */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00); + NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); + + /* Wait for ISR_RST to be set, but timeout after 2ms */ + for (i = 0; i < 4; i++) { + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); + if (Tmp & ISR_RST) + break; + + NdisStallExecution(500); + } + +#ifdef DBG + if (i == 4) + NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n")); +#endif + + if ((Adapter->InterruptStatus & (ISR_PTX | ISR_TXE)) == 0) { + /* We may need to restart the transmitter */ + Adapter->TransmitPending = TRUE; + } + + /* Initialize TCR - Transmit Configuration Register to loopback mode 1 */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); + + /* Start NIC */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2); + + NICStart(Adapter); + + Adapter->BufferOverflow = FALSE; + } + + if (Adapter->ReceiveError) { + NDIS_DbgPrint(MID_TRACE, ("Receive error.\n")); + + /* Skip this packet */ + Adapter->NextPacket = Adapter->CurrentPage; + NICSetBoundaryPage(Adapter); + + Adapter->ReceiveError = FALSE; + } + + for (;;) { + NICGetCurrentPage(Adapter); + + NDIS_DbgPrint(MID_TRACE, ("Current page (0x%X) NextPacket (0x%X).\n", + Adapter->CurrentPage, + Adapter->NextPacket)); + + if (Adapter->CurrentPage == Adapter->NextPacket) { + NDIS_DbgPrint(MID_TRACE, ("No more packets.\n")); + break; + } else { + NDIS_DbgPrint(MID_TRACE, ("Got a packet in the receive ring.\n")); + + /* Read packet from receive buffer ring */ + NICReadPacket(Adapter); + + Adapter->DoneIndicating = TRUE; + + PacketCount++; + if (PacketCount == 10) { + /* Don't starve transmit interrupts */ + break; + } + } + } + + if ((Adapter->TransmitPending) && (Adapter->TXCurrent != -1)) { + NDIS_DbgPrint(MID_TRACE, ("Retransmitting current packet at (%d).\n", Adapter->TXCurrent)); + /* Retransmit packet */ + NICStartTransmit(Adapter); + Adapter->TransmitPending = FALSE; + } + + if (Adapter->DoneIndicating) + NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle); +} + + +VOID HandleTransmit( + PNIC_ADAPTER Adapter) +/* + * FUNCTION: Handles transmission of a packet + * ARGUMENTS: + * Adapter = Pointer to adapter information + */ +{ + UINT Length; + UINT BufferCount; + +// PIP_PACKET pIPPacket; +// pIPPacket = (PIP_PACKET) +// DisplayIPPacket(pIPPacket); + + if (Adapter->TransmitError) { + /* FIXME: Retransmit now or let upper layer protocols handle retransmit? */ + Adapter->TransmitError = FALSE; + } + + /* Free transmit buffers */ + Length = Adapter->TXSize[Adapter->TXCurrent]; + BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE; + + NDIS_DbgPrint(MID_TRACE, ("Freeing (%d) buffers at (%d).\n", + BufferCount, + Adapter->TXCurrent)); + + Adapter->TXFree += BufferCount; + Adapter->TXSize[Adapter->TXCurrent] = 0; + Adapter->TXCurrent = (Adapter->TXCurrent + BufferCount) % Adapter->TXCount; + + if (Adapter->TXSize[Adapter->TXCurrent] == 0) { + NDIS_DbgPrint(MID_TRACE, ("No more packets in transmit buffer.\n")); + + Adapter->TXCurrent = -1; + } + + if (Adapter->TXQueueTail) { + if (NICPrepareForTransmit(Adapter)) + NICStartTransmit(Adapter); + } +} + + +VOID MiniportHandleInterrupt( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Handler for deferred processing of interrupts + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + * NOTES: + * Interrupt Service Register is read to determine which interrupts + * are pending. All pending interrupts are handled + */ +{ + UCHAR ISRValue; + UCHAR ISRMask; + UCHAR Mask; + PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; + + ISRMask = Adapter->InterruptMask; + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue); + + NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue)); + + Adapter->InterruptStatus |= (ISRValue & ISRMask); + + if (ISRValue != 0x00) + /* Acknowledge interrupts */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue); + + Mask = 0x01; + while (Adapter->InterruptStatus != 0x00) { + + NDIS_DbgPrint(MID_TRACE, ("Adapter->InterruptStatus (0x%X) Mask (0x%X).\n", + Adapter->InterruptStatus, Mask)); + + /* Find next interrupt type */ + while (((Adapter->InterruptStatus & Mask) == 0) && (Mask < ISRMask)) + Mask = (Mask << 1); + + switch (Adapter->InterruptStatus & Mask) { + case ISR_OVW: + NDIS_DbgPrint(MID_TRACE, ("Overflow interrupt.\n")); + /* Overflow. Handled almost the same way as a receive interrupt */ + Adapter->BufferOverflow = TRUE; + + HandleReceive(Adapter); + + Adapter->InterruptStatus &= ~ISR_OVW; + break; + + case ISR_RXE: + NDIS_DbgPrint(MID_TRACE, ("Receive error interrupt.\n")); + NICUpdateCounters(Adapter); + + Adapter->ReceiveError = TRUE; + + case ISR_PRX: + NDIS_DbgPrint(MID_TRACE, ("Receive interrupt.\n")); + + HandleReceive(Adapter); + + Adapter->InterruptStatus &= ~(ISR_PRX | ISR_RXE); + break; + + case ISR_TXE: + NDIS_DbgPrint(MID_TRACE, ("Transmit error interrupt.\n")); + NICUpdateCounters(Adapter); + + Adapter->TransmitError = TRUE; + + case ISR_PTX: + NDIS_DbgPrint(MID_TRACE, ("Transmit interrupt.\n")); + + HandleTransmit(Adapter); + + Adapter->InterruptStatus &= ~(ISR_PTX | ISR_TXE); + break; + + case ISR_CNT: + NDIS_DbgPrint(MID_TRACE, ("Counter interrupt.\n")); + /* Counter overflow. Read counters from the NIC */ + NICUpdateCounters(Adapter); + + Adapter->InterruptStatus &= ~ISR_CNT; + break; + + default: + NDIS_DbgPrint(MID_TRACE, ("Unknown interrupt. Adapter->InterruptStatus (0x%X).\n", Adapter->InterruptStatus)); + Adapter->InterruptStatus &= ~Mask; + break; + } + + Mask = (Mask << 1); + + /* Check if new interrupts are generated */ + + NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue); + + NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue)); + + Adapter->InterruptStatus |= (ISRValue & ISRMask); + + if (ISRValue != 0x00) { + /* Acknowledge interrupts */ + NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue); + Mask = 0x01; + } + } + + NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext); +} + +/* EOF */ diff --git a/drivers/net/dd/ne2000/ne2000/main.c b/drivers/net/dd/ne2000/ne2000/main.c new file mode 100644 index 0000000..be3acee --- /dev/null +++ b/drivers/net/dd/ne2000/ne2000/main.c @@ -0,0 +1,812 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Novell Eagle 2000 driver + * FILE: ne2000/main.c + * PURPOSE: Driver entry point + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 27/08-2000 Created + */ +#include + + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +//DWORD DebugTraceLevel = MID_TRACE; +ULONG DebugTraceLevel = MIN_TRACE; + +#endif /* DBG */ + + +/* List of supported OIDs */ +static ULONG MiniportOIDList[] = { + OID_GEN_SUPPORTED_LIST, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_LOOKAHEAD, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BUFFER_SPACE, + OID_GEN_RECEIVE_BUFFER_SPACE, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_DRIVER_VERSION, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_PROTOCOL_OPTIONS, + OID_GEN_MAC_OPTIONS, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_MAXIMUM_SEND_PACKETS, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_MAC_OPTIONS +}; + +DRIVER_INFORMATION DriverInfo = {0}; +NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1); + + +BOOLEAN MiniportCheckForHang( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Examines if an adapter has hung + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + * RETURNS: + * TRUE if the adapter has hung, FALSE if not + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + return FALSE; +} + + +VOID MiniportDisableInterrupt( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Disables interrupts from an adapter + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called. (MiniportDisableInterrupt).\n")); +#ifndef NOCARD + NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext); +#endif +} + + +VOID MiniportEnableInterrupt( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Enables interrupts from an adapter + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called. (MiniportEnableInterrupt).\n")); +#ifndef NOCARD + NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext); +#endif +} + + +VOID MiniportHalt( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Deallocates resources for and halts an adapter + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + */ +{ + PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); +#ifndef NOCARD + /* Stop the NIC */ + NICStop(Adapter); +#endif + /* Wait for any DPCs to complete. FIXME: Use something else */ + NdisStallExecution(250000); + + if (Adapter->InterruptRegistered) + /* Deregister interrupt */ + NdisMDeregisterInterrupt(&Adapter->Interrupt); + + if (Adapter->IOPortRangeRegistered) + /* Deregister I/O port range */ + NdisMDeregisterIoPortRange( + Adapter->MiniportAdapterHandle, + Adapter->IoBaseAddress, + 0x20, + Adapter->IOBase); + + /* Remove adapter from global adapter list */ + if ((&Adapter->ListEntry)->Blink != NULL) { + RemoveEntryList(&Adapter->ListEntry); + } + + /* Free adapter context area */ + NdisFreeMemory(Adapter, sizeof(NIC_ADAPTER), 0); +} + + +NDIS_STATUS MiniportInitialize( + OUT PNDIS_STATUS OpenErrorStatus, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE WrapperConfigurationContext) +/* + * FUNCTION: Adapter initialization function + * ARGUMENTS: + * OpenErrorStatus = Address of buffer to place additional status information + * SelectedMediumIndex = Address of buffer to place selected medium index + * MediumArray = Pointer to an array of NDIS_MEDIUMs + * MediaArraySize = Number of elements in MediumArray + * MiniportAdapterHandle = Miniport adapter handle assigned by NDIS + * WrapperConfigurationContext = Handle used to identify configuration context + * RETURNS: + * Status of operation + */ +{ + UINT i; + NDIS_STATUS Status; + PNIC_ADAPTER Adapter; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Search for 802.3 media which is the only one we support */ + for (i = 0; i < MediumArraySize; i++) { + if (MediumArray[i] == NdisMedium802_3) + break; + } + + if (i == MediumArraySize) { + NDIS_DbgPrint(MIN_TRACE, ("No supported medias.\n")); + return NDIS_STATUS_UNSUPPORTED_MEDIA; + } + + *SelectedMediumIndex = i; + + Status = NdisAllocateMemory((PVOID)&Adapter, + sizeof(NIC_ADAPTER), + 0, + HighestAcceptableMax); + if (Status != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return Status; + } + + NdisZeroMemory(Adapter, sizeof(NIC_ADAPTER)); + Adapter->MiniportAdapterHandle = MiniportAdapterHandle; + Adapter->IoBaseAddress = DRIVER_DEFAULT_IO_BASE_ADDRESS; + Adapter->InterruptNumber = DRIVER_DEFAULT_INTERRUPT_NUMBER; + Adapter->MaxMulticastListSize = DRIVER_MAX_MULTICAST_LIST_SIZE; + Adapter->InterruptMask = DRIVER_INTERRUPT_MASK; + Adapter->LookaheadSize = DRIVER_MAXIMUM_LOOKAHEAD; + + NdisMSetAttributes( + MiniportAdapterHandle, + (NDIS_HANDLE)Adapter, + FALSE, + NdisInterfaceIsa); + + Status = NdisMRegisterIoPortRange( + (PVOID*)&Adapter->IOBase, + MiniportAdapterHandle, + Adapter->IoBaseAddress, + 0x20); + + if (Status != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("Cannot register port range. Status (0x%X).\n", Status)); + MiniportHalt((NDIS_HANDLE)Adapter); + return Status; + } + + Adapter->IOPortRangeRegistered = TRUE; + + /* Initialize NIC */ +#ifndef NOCARD + Status = NICInitialize(Adapter); + if (Status != NDIS_STATUS_SUCCESS) { + DbgPrint("No NE2000 or compatible network adapter found at address 0x%X.\n", + Adapter->IOBase); + + NDIS_DbgPrint(MID_TRACE, ("Status (0x%X).\n", Status)); + MiniportHalt((NDIS_HANDLE)Adapter); + return Status; + } + + NDIS_DbgPrint(MID_TRACE, ("BOARDDATA:\n")); + for (i = 0; i < 4; i++) { + NDIS_DbgPrint(MID_TRACE, ("%02X %02X %02X %02X\n", + Adapter->SAPROM[i*4+0], + Adapter->SAPROM[i*4+1], + Adapter->SAPROM[i*4+2], + Adapter->SAPROM[i*4+3])); + } + + /* Setup adapter structure */ + Adapter->TXStart = ((ULONG_PTR)Adapter->RamBase >> 8); + Adapter->TXCount = DRIVER_DEFAULT_TX_BUFFER_COUNT; + Adapter->TXFree = DRIVER_DEFAULT_TX_BUFFER_COUNT; + Adapter->TXCurrent = -1; + Adapter->PageStart = Adapter->TXStart + Adapter->TXCount; + Adapter->PageStop = Adapter->TXStart + (Adapter->RamSize >> 8); + + /* Initialize multicast address mask to accept all */ + for (i = 0; i < 8; i++) + Adapter->MulticastAddressMask[i] = 0xFF; + + /* Setup the NIC */ + NICSetup(Adapter); + + NDIS_DbgPrint(MID_TRACE, ("TXStart (0x%X) TXCount (0x%X) PageStart (0x%X)\n", + Adapter->TXStart, + Adapter->TXCount, + Adapter->PageStart)); + + NDIS_DbgPrint(MID_TRACE, ("PageStop (0x%X) CurrentPage (0x%X) NextPacket (0x%X).\n", + Adapter->PageStop, + Adapter->CurrentPage, + Adapter->NextPacket)); +#endif + /* Register the interrupt */ + Status = NdisMRegisterInterrupt( + &Adapter->Interrupt, + MiniportAdapterHandle, + Adapter->InterruptNumber, + Adapter->InterruptNumber, + FALSE, + FALSE, + NdisInterruptLatched); + if (Status != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("Cannot register interrupt. Status (0x%X).\n", Status)); + MiniportHalt((NDIS_HANDLE)Adapter); + return Status; + } + + Adapter->InterruptRegistered = TRUE; +#ifndef NOCARD + /* Start the NIC */ + NICStart(Adapter); +#endif + /* Add adapter to the global adapter list */ + InsertTailList(&DriverInfo.AdapterListHead, &Adapter->ListEntry); + + NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return NDIS_STATUS_SUCCESS; +} + + +VOID MiniportISR( + OUT PBOOLEAN InterruptRecognized, + OUT PBOOLEAN QueueMiniportHandleInterrupt, + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Interrupt Service Routine for controlled adapters + * ARGUMENTS: + * InterruptRecognized = Address of buffer to place wether + * the adapter generated the interrupt + * QueueMiniportHandleInterrupt = Address of buffer to place wether + * MiniportHandleInterrupt should be called + * MiniportAdapterContext = Pointer to adapter context area + * NOTES: + * All pending interrupts are handled + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext); + + *InterruptRecognized = TRUE; + *QueueMiniportHandleInterrupt = TRUE; +} + + +NDIS_STATUS MiniportQueryInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesWritten, + OUT PULONG BytesNeeded) +/* + * FUNCTION: Handler to process queries + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + * Oid = OID code designating query operation + * InformationBuffer = Address of return buffer + * InformationBufferLength = Length of return buffer + * BytesWritten = Address of buffer to place number of bytes returned + * BytesNeeded = Address of buffer to place number of bytes needed + * in InformationBuffer for specified OID + * RETURNS: + * Status of operation + */ +{ + NDIS_STATUS Status; + PVOID CopyFrom; + UINT CopySize; + ULONG GenericULONG; + USHORT GenericUSHORT; + NDIS_MEDIUM Medium = NdisMedium802_3; + PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; + + NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid)); + + Status = NDIS_STATUS_SUCCESS; + CopyFrom = (PVOID)&GenericULONG; + CopySize = sizeof(ULONG); + + switch (Oid) { + case OID_GEN_SUPPORTED_LIST: + CopyFrom = (PVOID)&MiniportOIDList; + CopySize = sizeof(MiniportOIDList); + break; + case OID_GEN_HARDWARE_STATUS: + GenericULONG = (ULONG)NdisHardwareStatusReady; + break; + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + CopyFrom = (PVOID)&Medium; + CopySize = sizeof(NDIS_MEDIUM); + break; + case OID_GEN_MAXIMUM_LOOKAHEAD: + GenericULONG = DRIVER_MAXIMUM_LOOKAHEAD; + break; + case OID_GEN_MAXIMUM_FRAME_SIZE: + GenericULONG = DRIVER_FRAME_SIZE - DRIVER_HEADER_SIZE; + break; + case OID_GEN_LINK_SPEED: + GenericULONG = 100000; /* 10Mbps */ + break; + case OID_GEN_TRANSMIT_BUFFER_SPACE: + GenericULONG = Adapter->TXCount * DRIVER_BLOCK_SIZE; + break; + case OID_GEN_RECEIVE_BUFFER_SPACE: + GenericULONG = Adapter->RamSize - + (ULONG_PTR)Adapter->RamBase - + (Adapter->TXCount * DRIVER_BLOCK_SIZE); + break; + case OID_GEN_TRANSMIT_BLOCK_SIZE: + GenericULONG = DRIVER_BLOCK_SIZE; + break; + case OID_GEN_RECEIVE_BLOCK_SIZE: + GenericULONG = DRIVER_BLOCK_SIZE; + break; + case OID_GEN_VENDOR_ID: + NdisMoveMemory(&GenericULONG, &Adapter->PermanentAddress, 3); + GenericULONG &= 0xFFFFFF00; + GenericULONG |= 0x01; + break; + case OID_GEN_VENDOR_DESCRIPTION: + CopyFrom = (PVOID)&DRIVER_VENDOR_DESCRIPTION; + CopySize = sizeof(DRIVER_VENDOR_DESCRIPTION); + break; + case OID_GEN_VENDOR_DRIVER_VERSION: + GenericUSHORT = (USHORT)DRIVER_VENDOR_DRIVER_VERSION; + CopyFrom = (PVOID)&GenericUSHORT; + CopySize = sizeof(USHORT); + break; + case OID_GEN_CURRENT_PACKET_FILTER: + GenericULONG = Adapter->PacketFilter; + break; + case OID_GEN_CURRENT_LOOKAHEAD: + GenericULONG = Adapter->LookaheadSize; + break; + case OID_GEN_DRIVER_VERSION: + GenericUSHORT = ((USHORT)DRIVER_NDIS_MAJOR_VERSION << 8) | DRIVER_NDIS_MINOR_VERSION; + CopyFrom = (PVOID)&GenericUSHORT; + CopySize = sizeof(USHORT); + break; + case OID_GEN_MAXIMUM_TOTAL_SIZE: + GenericULONG = DRIVER_FRAME_SIZE; + break; + case OID_GEN_PROTOCOL_OPTIONS: + NDIS_DbgPrint(MID_TRACE, ("OID_GEN_PROTOCOL_OPTIONS.\n")); + Status = NDIS_STATUS_NOT_SUPPORTED; + break; + case OID_GEN_MAC_OPTIONS: + GenericULONG = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | + NDIS_MAC_OPTION_RECEIVE_SERIALIZED | + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | + NDIS_MAC_OPTION_NO_LOOPBACK; + break; + case OID_GEN_MEDIA_CONNECT_STATUS: + GenericULONG = (ULONG)NdisMediaStateConnected; + break; + case OID_GEN_MAXIMUM_SEND_PACKETS: + GenericULONG = 1; + break; + case OID_802_3_PERMANENT_ADDRESS: + CopyFrom = (PVOID)&Adapter->PermanentAddress; + CopySize = DRIVER_LENGTH_OF_ADDRESS; + break; + case OID_802_3_CURRENT_ADDRESS: + CopyFrom = (PVOID)&Adapter->StationAddress; + CopySize = DRIVER_LENGTH_OF_ADDRESS; + break; + case OID_802_3_MULTICAST_LIST: + NDIS_DbgPrint(MID_TRACE, ("OID_802_3_MULTICAST_LIST.\n")); + Status = NDIS_STATUS_NOT_SUPPORTED; + break; + case OID_802_3_MAXIMUM_LIST_SIZE: + GenericULONG = Adapter->MaxMulticastListSize; + break; + case OID_802_3_MAC_OPTIONS: + NDIS_DbgPrint(MID_TRACE, ("OID_802_3_MAC_OPTIONS.\n")); + Status = NDIS_STATUS_NOT_SUPPORTED; + break; + default: + NDIS_DbgPrint(MIN_TRACE, ("Unknown OID (0x%X).\n", Oid)); + Status = NDIS_STATUS_INVALID_OID; + break; + } + + if (Status == NDIS_STATUS_SUCCESS) { + if (CopySize > InformationBufferLength) { + *BytesNeeded = (CopySize - InformationBufferLength); + *BytesWritten = 0; + Status = NDIS_STATUS_INVALID_LENGTH; + } else { + NdisMoveMemory(InformationBuffer, CopyFrom, CopySize); + *BytesWritten = CopySize; + *BytesNeeded = 0; + } + } + + NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status is (0x%X).\n", Status)); + + return Status; +} + + +NDIS_STATUS MiniportReconfigure( + OUT PNDIS_STATUS OpenErrorStatus, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE WrapperConfigurationContext) +/* + * FUNCTION: Reconfigures an adapter + * ARGUMENTS: + * OpenErrorStatus = Address of buffer to place additional status information + * MiniportAdapterContext = Pointer to adapter context area + * WrapperConfigurationContext = Handle used to identify configuration context + * RETURNS: + * Status of operation + * NOTES: + * Never called by NDIS library + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + return NDIS_STATUS_FAILURE; +} + + + +NDIS_STATUS MiniportReset( + OUT PBOOLEAN AddressingReset, + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Resets an adapter + * ARGUMENTS: + * AddressingReset = Address of a buffer to place value indicating + * wether NDIS library should call MiniportSetInformation + * to restore addressing information + * MiniportAdapterContext = Pointer to adapter context area + * RETURNS: + * Status of operation + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS MiniportSend( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags) +/* + * FUNCTION: Transmits a packet + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + * Packet = Pointer to a packet descriptor specifying + * the data to be transmitted + * Flags = Specifies optional packet flags + * RETURNS: + * Status of operation + */ +{ + PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; + + NDIS_DbgPrint(MID_TRACE, ("Queueing packet.\n")); + +#ifdef NOCARD + NdisMSendComplete(Adapter->MiniportAdapterHandle, + Packet, + NDIS_STATUS_SUCCESS); +#else + /* Queue the packet on the transmit queue */ + RESERVED(Packet)->Next = NULL; + if (Adapter->TXQueueHead == NULL) { + Adapter->TXQueueHead = Packet; + } else { + RESERVED(Adapter->TXQueueTail)->Next = Packet; + } + + Adapter->TXQueueTail = Packet; + + /* Transmit the packet */ + NICTransmit(Adapter); +#endif + return NDIS_STATUS_PENDING; +} + + +NDIS_STATUS MiniportSetInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesRead, + OUT PULONG BytesNeeded) +/* + * FUNCTION: Changes state information in the driver + * ARGUMENTS: + * MiniportAdapterContext = Pointer to adapter context area + * Oid = OID code designating set operation + * InformationBuffer = Pointer to buffer with state information + * InformationBufferLength = Length of InformationBuffer + * BytesRead = Address of buffer to place number of bytes read + * BytesNeeded = Address of buffer to place number of extra bytes + * needed in InformationBuffer for specified OID + * RETURNS: + * Status of operation + */ +{ + ULONG GenericULONG; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; + + NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid)); + + switch (Oid) { + case OID_GEN_CURRENT_PACKET_FILTER: + /* Verify length */ + if (InformationBufferLength < sizeof(ULONG)) { + *BytesRead = 0; + *BytesNeeded = sizeof(ULONG) - InformationBufferLength; + Status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG)); + /* Check for properties the driver don't support */ + if (GenericULONG & + (NDIS_PACKET_TYPE_ALL_FUNCTIONAL | + NDIS_PACKET_TYPE_FUNCTIONAL | + NDIS_PACKET_TYPE_GROUP | + NDIS_PACKET_TYPE_MAC_FRAME | + NDIS_PACKET_TYPE_SMT | + NDIS_PACKET_TYPE_SOURCE_ROUTING)) { + *BytesRead = 4; + *BytesNeeded = 0; + Status = NDIS_STATUS_NOT_SUPPORTED; + break; + } + + Adapter->PacketFilter = GenericULONG; + + /* FIXME: Set filter on hardware */ + + break; + case OID_GEN_CURRENT_LOOKAHEAD: + /* Verify length */ + if (InformationBufferLength < sizeof(ULONG)) { + *BytesRead = 0; + *BytesNeeded = sizeof(ULONG) - InformationBufferLength; + Status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG)); + if (GenericULONG > DRIVER_MAXIMUM_LOOKAHEAD) + Status = NDIS_STATUS_INVALID_LENGTH; + else + Adapter->LookaheadSize = GenericULONG; + break; + case OID_802_3_MULTICAST_LIST: + /* Verify length. Must be multiplum of hardware address length */ + if ((InformationBufferLength % DRIVER_LENGTH_OF_ADDRESS) != 0) { + *BytesRead = 0; + *BytesNeeded = 0; + Status = NDIS_STATUS_INVALID_LENGTH; + break; + } + + /* Set new multicast address list */ + NdisMoveMemory(Adapter->Addresses, InformationBuffer, InformationBufferLength); + + /* FIXME: Update hardware */ + + break; + default: + NDIS_DbgPrint(MIN_TRACE, ("Invalid object ID (0x%X).\n", Oid)); + *BytesRead = 0; + *BytesNeeded = 0; + Status = NDIS_STATUS_INVALID_OID; + break; + } + + if (Status == NDIS_STATUS_SUCCESS) { + *BytesRead = InformationBufferLength; + *BytesNeeded = 0; + } + + NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status)); + + return Status; +} + + +NDIS_STATUS MiniportTransferData( + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer) +/* + * FUNCTION: Transfers data from a received frame into an NDIS packet + * ARGUMENTS: + * Packet = Address of packet to copy received data into + * BytesTransferred = Address of buffer to place number of bytes transmitted + * MiniportAdapterContext = Pointer to adapter context area + * MiniportReceiveContext = Pointer to receive context area (actually NULL) + * ByteOffset = Offset within received packet to begin copying + * BytesToTransfer = Number of bytes to copy into packet + * RETURNS: + * Status of operation + */ +{ + PNDIS_BUFFER DstBuffer; + UINT BytesCopied, BytesToCopy, DstSize; + ULONG SrcData; + PUCHAR DstData; + UINT RecvStart; + UINT RecvStop; + PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; + + NDIS_DbgPrint(MAX_TRACE, ("Called. Packet (0x%X) ByteOffset (0x%X) BytesToTransfer (%d).\n", + Packet, ByteOffset, BytesToTransfer)); + + if (BytesToTransfer == 0) { + *BytesTransferred = 0; + return NDIS_STATUS_SUCCESS; + } + + RecvStart = Adapter->PageStart * DRIVER_BLOCK_SIZE; + RecvStop = Adapter->PageStop * DRIVER_BLOCK_SIZE; + + NdisQueryPacket(Packet, NULL, NULL, &DstBuffer, NULL); + NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); + + SrcData = Adapter->PacketOffset + sizeof(PACKET_HEADER) + ByteOffset; + if (ByteOffset + sizeof(PACKET_HEADER) + BytesToTransfer > Adapter->PacketHeader.PacketLength) + BytesToTransfer = Adapter->PacketHeader.PacketLength- sizeof(PACKET_HEADER) - ByteOffset; + + /* Start copying the data */ + BytesCopied = 0; + for (;;) { + BytesToCopy = (DstSize < BytesToTransfer)? DstSize : BytesToTransfer; + if (SrcData + BytesToCopy > RecvStop) + BytesToCopy = (RecvStop - SrcData); + + NICReadData(Adapter, DstData, SrcData, BytesToCopy); + + BytesCopied += BytesToCopy; + SrcData += BytesToCopy; + (ULONG_PTR)DstData += BytesToCopy; + BytesToTransfer -= BytesToCopy; + if (BytesToTransfer == 0) + break; + + DstSize -= BytesToCopy; + if (DstSize == 0) { + /* No more bytes in destination buffer. Proceed to + the next buffer in the destination buffer chain */ + NdisGetNextBuffer(DstBuffer, &DstBuffer); + if (!DstBuffer) + break; + + NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); + } + + if (SrcData == RecvStop) + SrcData = RecvStart; + } + + NDIS_DbgPrint(MID_TRACE, ("Transferred (%d) bytes.\n", BytesToTransfer)); + + *BytesTransferred = BytesCopied; + + return NDIS_STATUS_SUCCESS; +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Main driver entry point + * ARGUMENTS: + * DriverObject = Pointer to a driver object for this driver + * RegistryPath = Registry node for configuration parameters + * RETURNS: + * Status of driver initialization + */ +{ + NDIS_STATUS Status; + NDIS_HANDLE NdisWrapperHandle; + NDIS_MINIPORT_CHARACTERISTICS Miniport; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + NdisZeroMemory(&Miniport, sizeof(Miniport)); + Miniport.MajorNdisVersion = DRIVER_NDIS_MAJOR_VERSION; + Miniport.MinorNdisVersion = DRIVER_NDIS_MINOR_VERSION; + Miniport.CheckForHangHandler = NULL; //MiniportCheckForHang; + Miniport.DisableInterruptHandler = MiniportDisableInterrupt; + Miniport.EnableInterruptHandler = MiniportEnableInterrupt; + Miniport.HaltHandler = MiniportHalt; + Miniport.HandleInterruptHandler = MiniportHandleInterrupt; + Miniport.InitializeHandler = MiniportInitialize; + Miniport.ISRHandler = MiniportISR; + Miniport.QueryInformationHandler = MiniportQueryInformation; + Miniport.ReconfigureHandler = MiniportReconfigure; + Miniport.ResetHandler = MiniportReset; + Miniport.u1.SendHandler = MiniportSend; + Miniport.SetInformationHandler = MiniportSetInformation; + Miniport.u2.TransferDataHandler = MiniportTransferData; + + NdisMInitializeWrapper(&NdisWrapperHandle, + DriverObject, + RegistryPath, + NULL); + + DriverInfo.NdisWrapperHandle = NdisWrapperHandle; + DriverInfo.NdisMacHandle = NULL; + InitializeListHead(&DriverInfo.AdapterListHead); + + Status = NdisMRegisterMiniport(NdisWrapperHandle, + &Miniport, + sizeof(NDIS_MINIPORT_CHARACTERISTICS)); + if (Status != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("NdisMRegisterMiniport() failed with status code (0x%X).\n", Status)); + NdisTerminateWrapper(NdisWrapperHandle, NULL); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/ndis/.cvsignore b/drivers/net/ndis/.cvsignore new file mode 100644 index 0000000..dea5140 --- /dev/null +++ b/drivers/net/ndis/.cvsignore @@ -0,0 +1,5 @@ +objects +ndis.coff +*.d +*.o +*.sym diff --git a/drivers/net/ndis/DIRS b/drivers/net/ndis/DIRS new file mode 100644 index 0000000..f8cacae --- /dev/null +++ b/drivers/net/ndis/DIRS @@ -0,0 +1 @@ +DIRS= ndis diff --git a/drivers/net/ndis/Makefile b/drivers/net/ndis/Makefile new file mode 100644 index 0000000..91634da --- /dev/null +++ b/drivers/net/ndis/Makefile @@ -0,0 +1,31 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = ndis + +TARGET_CFLAGS = -I./include -DNDIS_WRAPPER -DBINARY_COMPATIBLE=1 + +TARGET_OBJECTS = \ + ndis/main.o \ + ndis/40gone.o \ + ndis/50gone.o \ + ndis/buffer.o \ + ndis/cl.o \ + ndis/cm.o \ + ndis/co.o \ + ndis/control.o \ + ndis/hardware.o \ + ndis/io.o \ + ndis/memory.o \ + ndis/miniport.o \ + ndis/protocol.o \ + ndis/string.o \ + ndis/stubs.o \ + ndis/time.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/ndis/include/buffer.h b/drivers/net/ndis/include/buffer.h new file mode 100644 index 0000000..7beaa66 --- /dev/null +++ b/drivers/net/ndis/include/buffer.h @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/buffer.h + * PURPOSE: Buffer management routine definitions + */ +#ifndef __BUFFER_H +#define __BUFFER_H + +#include + + +/* FIXME: Possibly move this to ntddk.h */ +typedef struct _NETWORK_HEADER +{ + MDL Mdl; /* Memory Descriptor List */ + struct _NETWORK_HEADER *Next; /* Link to next NDIS buffer in pool */ + struct _NDIS_BUFFER_POOL *BufferPool; /* Link to NDIS buffer pool */ +} NETWORK_HEADER, *PNETWORK_HEADER; + +typedef struct _NDIS_BUFFER_POOL +{ + KSPIN_LOCK SpinLock; + PNETWORK_HEADER FreeList; + NETWORK_HEADER Buffers[0]; +} NDIS_BUFFER_POOL, *PNDIS_BUFFER_POOL; + + +UINT CopyBufferToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PUCHAR SrcData, + UINT Length); + +UINT CopyBufferChainToBuffer( + PUCHAR DstData, + PNDIS_BUFFER SrcBuffer, + UINT SrcOffset, + UINT Length); + +UINT CopyPacketToBuffer( + PUCHAR DstData, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length); + +UINT CopyPacketToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length); + +#endif /* __BUFFER_H */ + +/* EOF */ diff --git a/drivers/net/ndis/include/debug.h b/drivers/net/ndis/include/debug.h new file mode 100644 index 0000000..fbe3f88 --- /dev/null +++ b/drivers/net/ndis/include/debug.h @@ -0,0 +1,95 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_REFCOUNT 0x00000100 +#define DEBUG_MINIPORT 0x00000200 +#define DEBUG_PROTOCOL 0x00000400 +#define DEBUG_PACKET 0x00000800 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#ifdef _MSC_VER + +#define NDIS_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d) ", __FILE__, __LINE__); \ + DbgPrint _x_ ; \ + } + +#else /* _MSC_VER */ + +#define NDIS_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_ ; \ + } + +#endif /* _MSC_VER */ + + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { NDIS_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } +#endif /* NASSERT */ + +#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) + +#else /* DBG */ + +#define NDIS_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#ifdef _MSC_VER + +#define UNIMPLEMENTED \ + NDIS_DbgPrint(MIN_TRACE, ("The function at (%s:%d) is unimplemented.\n", __FILE__, __LINE__)); + +#else /* _MSC_VER */ + +#define UNIMPLEMENTED \ + NDIS_DbgPrint(MIN_TRACE, ("(%s) at (%s:%d) is unimplemented.\n", __FUNCTION__, __FILE__, __LINE__)); + +#endif /* _MSC_VER */ + + +#define CHECKPOINT \ + do { NDIS_DbgPrint(MIN_TRACE, ("(%s:%d)\n", __FILE__, __LINE__)); } while(0); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/drivers/net/ndis/include/miniport.h b/drivers/net/ndis/include/miniport.h new file mode 100644 index 0000000..1ae54f0 --- /dev/null +++ b/drivers/net/ndis/include/miniport.h @@ -0,0 +1,133 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/miniport.h + * PURPOSE: Definitions for routines used by NDIS miniport drivers + */ + +#ifndef __MINIPORT_H +#define __MINIPORT_H + +#include + + +typedef struct _HARDWARE_ADDRESS { + union { + UCHAR Medium802_3[ETH_LENGTH_OF_ADDRESS]; + } Type; +} HARDWARE_ADDRESS, *PHARDWARE_ADDRESS; + +/* Information about a miniport */ +typedef struct _MINIPORT_DRIVER { + LIST_ENTRY ListEntry; /* Entry on global list */ + KSPIN_LOCK Lock; /* Protecting spin lock */ + ULONG RefCount; /* Reference count */ + NDIS_MINIPORT_CHARACTERISTICS Chars; /* Miniport characteristics */ + WORK_QUEUE_ITEM WorkItem; /* Work item */ + PDRIVER_OBJECT DriverObject; /* Driver object of miniport */ + LIST_ENTRY AdapterListHead; /* Adapters created by miniport */ +} MINIPORT_DRIVER, *PMINIPORT_DRIVER; + +#define GET_MINIPORT_DRIVER(Handle)((PMINIPORT_DRIVER)Handle) + +/* Information about a logical adapter */ +typedef struct _LOGICAL_ADAPTER { + NDIS_MINIPORT_BLOCK NdisMiniportBlock; /* NDIS defined fields */ + + KDPC MiniportDpc; /* DPC routine for adapter */ + BOOLEAN MiniportBusy; /* A MiniportXxx routine is executing */ + NDIS_HANDLE MiniportAdapterBinding; /* Binding handle for current caller */ + ULONG WorkQueueLevel; /* Number of used work item buffers */ + NDIS_MINIPORT_WORK_ITEM WorkQueue[NDIS_MINIPORT_WORK_QUEUE_SIZE]; + PNDIS_MINIPORT_WORK_ITEM WorkQueueHead; /* Head of work queue */ + PNDIS_MINIPORT_WORK_ITEM WorkQueueTail; /* Tail of work queue */ + + LIST_ENTRY ListEntry; /* Entry on global list */ + LIST_ENTRY MiniportListEntry; /* Entry on miniport driver list */ + LIST_ENTRY ProtocolListHead; /* List of bound protocols */ + ULONG RefCount; /* Reference count */ + PMINIPORT_DRIVER Miniport; /* Miniport owning this adapter */ + UNICODE_STRING DeviceName; /* Device name of this adapter */ + ULONG Attributes; /* Attributes of adapter */ + /* TRUE if the miniport has called NdisSetAttributes(Ex) for this adapter */ + BOOLEAN AttributesSet; + PVOID QueryBuffer; /* Buffer to use for queries */ + ULONG QueryBufferLength; /* Length of QueryBuffer */ + ULONG MediumHeaderSize; /* Size of medium header */ + HARDWARE_ADDRESS Address; /* Hardware address of adapter */ + ULONG AddressLength; /* Length of hardware address */ + PUCHAR LookaheadBuffer; /* Pointer to lookahead buffer */ + ULONG LookaheadLength; /* Length of lookahead buffer */ + ULONG CurLookaheadLength; /* Current (selected) length of lookahead buffer */ + ULONG MaxLookaheadLength; /* Maximum length of lookahead buffer */ + + PNDIS_PACKET PacketQueueHead; /* Head of packet queue */ + PNDIS_PACKET PacketQueueTail; /* Head of packet queue */ + + PNDIS_PACKET LoopPacket; /* Current packet beeing looped */ +} LOGICAL_ADAPTER, *PLOGICAL_ADAPTER; + +#define GET_LOGICAL_ADAPTER(Handle)((PLOGICAL_ADAPTER)Handle) + +extern LIST_ENTRY MiniportListHead; +extern KSPIN_LOCK MiniportListLock; +extern LIST_ENTRY AdapterListHead; +extern KSPIN_LOCK AdapterListLock; + + +#ifdef DBG +VOID +MiniDisplayPacket( + PNDIS_PACKET Packet); +#endif /* DBG */ + +VOID +MiniIndicateData( + PLOGICAL_ADAPTER Adapter, + NDIS_HANDLE MacReceiveContext, + PVOID HeaderBuffer, + UINT HeaderBufferSize, + PVOID LookaheadBuffer, + UINT LookaheadBufferSize, + UINT PacketSize); + +BOOLEAN +MiniAdapterHasAddress( + PLOGICAL_ADAPTER Adapter, + PNDIS_PACKET Packet); + +PLOGICAL_ADAPTER +MiniLocateDevice( + PNDIS_STRING AdapterName); + +NDIS_STATUS +MiniQueryInformation( + PLOGICAL_ADAPTER Adapter, + NDIS_OID Oid, + ULONG Size, + PULONG BytesWritten); + +NDIS_STATUS +FASTCALL +MiniQueueWorkItem( + PLOGICAL_ADAPTER Adapter, + NDIS_WORK_ITEM_TYPE WorkItemType, + PVOID WorkItemContext, + NDIS_HANDLE Initiator); + +NDIS_STATUS +FASTCALL +MiniDequeueWorkItem( + PLOGICAL_ADAPTER Adapter, + NDIS_WORK_ITEM_TYPE *WorkItemType, + PVOID *WorkItemContext, + NDIS_HANDLE *Initiator); + +NDIS_STATUS +MiniDoRequest( + PLOGICAL_ADAPTER Adapter, + PNDIS_REQUEST NdisRequest); + +#endif /* __MINIPORT_H */ + +/* EOF */ diff --git a/drivers/net/ndis/include/ndissys.h b/drivers/net/ndis/include/ndissys.h new file mode 100644 index 0000000..4082871 --- /dev/null +++ b/drivers/net/ndis/include/ndissys.h @@ -0,0 +1,101 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndissys.h + * PURPOSE: NDIS library definitions + * NOTES: Spin lock acquire order: + * - Miniport list lock + * - Adapter list lock + */ +#ifndef __NDISSYS_H +#define __NDISSYS_H + +#define NDIS50 1 /* Use NDIS 5.0 structures by default */ + +#ifdef _MSC_VER +#include +#include +#include +#include +#else /* _MSC_VER */ +#include +#include +#endif /* _MSC_VER */ + +#include + + +#ifndef _MSC_VER +/* FIXME: The following should be moved to ntddk.h */ + +/* + * ULONG MmGetMdlByteCount( + * IN PMDL Mdl) + */ +#define MmGetMdlByteCount(Mdl) \ + ((Mdl)->ByteCount) + +#endif + + +/* Exported functions */ +#ifdef _MSC_VER +#define EXPORT __declspec(dllexport) +#else +#define EXPORT STDCALL +#endif + + +#ifdef DBG + +#define DEBUG_REFCHECK(Object) { \ + if ((Object)->RefCount <= 0) { \ + NDIS_DbgPrint(MIN_TRACE, ("Object at (0x%X) has invalid reference count (%d).\n", \ + (Object), (Object)->RefCount)); \ + } \ +} + +#else + +#define DEBUG_REFCHECK(Object) + +#endif + + +/* + * VOID ReferenceObject( + * PVOID Object) + */ +#define ReferenceObject(Object) \ +{ \ + DEBUG_REFCHECK(Object); \ + NDIS_DbgPrint(DEBUG_REFCOUNT, ("Referencing object at (0x%X). RefCount (%d).\n", \ + (Object), (Object)->RefCount)); \ + \ + InterlockedIncrement(&((Object)->RefCount)); \ +} + +/* + * VOID DereferenceObject( + * PVOID Object) + */ +#define DereferenceObject(Object) \ +{ \ + DEBUG_REFCHECK(Object); \ + NDIS_DbgPrint(DEBUG_REFCOUNT, ("Dereferencing object at (0x%X). RefCount (%d).\n", \ + (Object), (Object)->RefCount)); \ + \ + if (InterlockedDecrement(&((Object)->RefCount)) == 0) \ + PoolFreeBuffer(Object); \ +} + + +#define MIN(value1, value2) \ + ((value1 < value2)? value1 : value2) + +#define MAX(value1, value2) \ + ((value1 > value2)? value1 : value2) + +#endif /* __NDISSYS_H */ + +/* EOF */ diff --git a/drivers/net/ndis/include/protocol.h b/drivers/net/ndis/include/protocol.h new file mode 100644 index 0000000..583d186 --- /dev/null +++ b/drivers/net/ndis/include/protocol.h @@ -0,0 +1,53 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/protocol.h + * PURPOSE: Definitions for routines used by NDIS protocol drivers + */ + +#ifndef __PROTOCOL_H +#define __PROTOCOL_H + +#include +#include + + +typedef struct _PROTOCOL_BINDING { + LIST_ENTRY ListEntry; /* Entry on global list */ + KSPIN_LOCK Lock; /* Protecting spin lock */ + ULONG RefCount; /* Reference count */ + NDIS_PROTOCOL_CHARACTERISTICS Chars; /* Characteristics */ + WORK_QUEUE_ITEM WorkItem; /* Work item */ + LIST_ENTRY AdapterListHead; /* List of adapter bindings */ +} PROTOCOL_BINDING, *PPROTOCOL_BINDING; + +#define GET_PROTOCOL_BINDING(Handle)((PPROTOCOL_BINDING)Handle) + + +typedef struct _ADAPTER_BINDING { + NDIS_OPEN_BLOCK NdisOpenBlock; /* NDIS defined fields */ + + LIST_ENTRY ListEntry; /* Entry on global list */ + LIST_ENTRY ProtocolListEntry; /* Entry on protocol binding adapter list */ + LIST_ENTRY AdapterListEntry; /* Entry on logical adapter list */ + KSPIN_LOCK Lock; /* Protecting spin lock */ + ULONG RefCount; /* Reference count */ + PPROTOCOL_BINDING ProtocolBinding; /* Protocol that opened adapter */ + PLOGICAL_ADAPTER Adapter; /* Adapter opened by protocol */ +} ADAPTER_BINDING, *PADAPTER_BINDING; + +#define GET_ADAPTER_BINDING(Handle)((PADAPTER_BINDING)Handle) + + +extern LIST_ENTRY ProtocolListHead; +extern KSPIN_LOCK ProtocolListLock; + + +NDIS_STATUS +ProIndicatePacket( + PLOGICAL_ADAPTER Adapter, + PNDIS_PACKET Packet); + +#endif /* __PROTOCOL_H */ + +/* EOF */ diff --git a/drivers/net/ndis/ndis.def b/drivers/net/ndis/ndis.def new file mode 100644 index 0000000..f2dbdad --- /dev/null +++ b/drivers/net/ndis/ndis.def @@ -0,0 +1,316 @@ +; NDIS Kernel Module - ReactOS Operating System + +LIBRARY NDIS.SYS + +EXPORTS +ArcFilterDprIndicateReceive@16 +ArcFilterDprIndicateReceiveComplete@4 +EthChangeFilterAddresses@24 +EthCreateFilter@28 +EthDeleteFilter@4 +EthDeleteFilterOpenAdapter@12 +EthFilterAdjust@20 +;EthFilterDprIndicateReceive@32 ? +;EthFilterDprIndicateReceiveComplete@4 ? +EthFilterIndicateReceive@32 +EthFilterIndicateReceiveComplete@4 +EthNoteFilterOpenAdapter@16 +EthNumberOfOpenFilterAddresses@8 +EthQueryGlobalFilterAddresses@20 +EthQueryOpenFilterAddresses@24 +EthShouldAddressLoopBack@8 +FddiChangeFilterLongAddresses@24 +FddiChangeFilterShortAddresses@24 +FddiCreateFilter@36 +FddiDeleteFilter@4 +FddiDeleteFilterOpenAdapter@12 +FddiFilterAdjust@20 +;FddiFilterDprIndicateReceive@36 ? +;FddiFilterDprIndicateReceiveComplete@4 ? +FddiFilterIndicateReceive@36 +FddiFilterIndicateReceiveComplete@4 +FddiNoteFilterOpenAdapter@16 +FddiNumberOfOpenFilterLongAddresses@8 +FddiNumberOfOpenFilterShortAddresses@8 +FddiQueryGlobalFilterLongAddresses@20 +FddiQueryGlobalFilterShortAddresses@20 +FddiQueryOpenFilterLongAddresses@24 +FddiQueryOpenFilterShortAddresses@24 +FddiShouldAddressLoopBack@12 +NDIS_BUFFER_TO_SPAN_PAGES@4 +NdisAcquireReadWriteLock@12 +NdisAcquireSpinLock@4 +NdisAdjustBufferLength@8 +NdisAllocateBuffer@20 +NdisAllocateBufferPool@12 +NdisAllocateDmaChannel@20 +NdisAllocateMemory@20 +NdisAllocateMemoryWithTag@12 +NdisAllocatePacket@12 +NdisAllocatePacketPool@16 +NdisAllocatePacketPoolEx@20 +NdisAllocateSharedMemory@20 +NdisAllocateSpinLock@4 +NdisAnsiStringToUnicodeString@8 +NdisBufferLength@4 +NdisBufferVirtualAddress@4 +NdisCancelTimer@8 +NdisClAddParty@16 +NdisClCloseAddressFamily@4 +NdisClCloseCall@16 +NdisClDeregisterSap@4 +NdisClDropParty@12 +NdisClIncomingCallComplete@12 +NdisClMakeCall@16 +NdisClModifyCallQoS@8 +NdisClOpenAddressFamily@24 +NdisClRegisterSap@16 +NdisCloseAdapter@8 +NdisCloseConfiguration@4 +NdisCloseFile@4 +NdisCmActivateVc@8 +NdisCmAddPartyComplete@16 +NdisCmCloseAddressFamilyComplete@8 +NdisCmCloseCallComplete@12 +NdisCmDeactivateVc@4 +NdisCmDeregisterSapComplete@8 +NdisCmDispatchCallConnected@4 +NdisCmDispatchIncomingCall@12 +NdisCmDispatchIncomingCallQoSChange@8 +NdisCmDispatchIncomingCloseCall@16 +NdisCmDispatchIncomingDropParty@16 +NdisCmDropPartyComplete@8 +NdisCmMakeCallComplete@20 +NdisCmModifyCallQoSComplete@12 +NdisCmOpenAddressFamilyComplete@12 +NdisCmRegisterAddressFamily@16 +NdisCmRegisterSapComplete@12 +NdisCoCreateVc@16 +NdisCoDeleteVc@4 +NdisCoRequest@20 +NdisCoRequestComplete@20 +NdisCoSendPackets@12 +;NdisCompareAnsiString ? +;NdisCompareUnicodeString ? +NdisCompleteBindAdapter@12 +NdisCompleteCloseAdapter@8 +NdisCompleteDmaTransfer@24 +NdisCompleteOpenAdapter@12 +NdisCompletePnPEvent@12 +NdisCompleteQueryStatistics@12 +NdisCompleteUnbindAdapter@8 +NdisConvertStringToAtmAddress@12 +NdisCopyBuffer@24 +NdisCopyFromPacketToPacket@24 +NdisDeregisterAdapter@4 +NdisDeregisterAdapterShutdownHandler@4 +NdisDeregisterMac@8 +NdisDeregisterProtocol@8 +NdisDprAcquireSpinLock@4 +NdisDprAllocatePacket@12 +NdisDprAllocatePacketNonInterlocked@12 +NdisDprFreePacket@4 +NdisDprFreePacketNonInterlocked@4 +NdisDprReleaseSpinLock@4 +NdisEqualString@12 +NdisFlushBuffer@8 +NdisFreeBuffer@4 +NdisFreeBufferPool@4 +NdisFreeDmaChannel@4 +NdisFreeMemory@12 +NdisFreePacket@4 +NdisFreePacketPool@4 +NdisFreeSharedMemory@24 +NdisFreeSpinLock@4 +NdisGetBufferPhysicalArraySize@8 +NdisGetCurrentProcessorCounts@12 +NdisGetCurrentProcessorCpuUsage@4 +NdisGetCurrentSystemTime@4 +NdisGetDriverHandle@8 +NdisGetFirstBufferFromPacket@20 +NdisGetReceivedPacket@8 +NdisGetSystemUptime@4 +NdisIMAssociateMiniport@8 +NdisIMCancelInitializeDeviceInstance@8 +NdisIMCopySendCompletePerPacketInfo@8 +NdisIMCopySendPerPacketInfo@8 +NdisIMDeInitializeDeviceInstance@4 +NdisIMDeregisterLayeredMiniport@4 +NdisIMGetBindingContext@4 +NdisIMGetDeviceContext@4 +NdisIMInitializeDeviceInstance@8 +NdisIMInitializeDeviceInstanceEx@12 +NdisImmediateReadPciSlotInformation@20 +NdisImmediateReadPortUchar@12 +NdisImmediateReadPortUlong@12 +NdisImmediateReadPortUshort@12 +NdisImmediateReadSharedMemory@16 +NdisImmediateWritePciSlotInformation@20 +NdisImmediateWritePortUchar@12 +NdisImmediateWritePortUlong@12 +NdisImmediateWritePortUshort@12 +NdisImmediateWriteSharedMemory@16 +NdisIMQueueMiniportCallback@12 +NdisIMRegisterLayeredMiniport@16 +NdisIMRevertBack@8 +NdisIMSwitchToMiniport@8 +NdisInitAnsiString@8 +NdisInitializeEvent@4 +NdisInitializeInterrupt@40 +NdisInitializeReadWriteLock@4 +NdisInitializeString@8 +NdisInitializeTimer@12 +NdisInitializeWrapper@16 +NdisInitUnicodeString@8 +;NdisInterlockedAddLargeInterger ? +NdisInterlockedAddUlong@12 +NdisInterlockedDecrement@4 +NdisInterlockedIncrement@4 +NdisInterlockedInsertHeadList@12 +NdisInterlockedInsertTailList@12 +NdisInterlockedPopEntrySList@8 +NdisInterlockedPushEntrySList@12 +NdisInterlockedRemoveHeadList@8 +NdisMAllocateMapRegisters@20 +NdisMAllocateSharedMemory@20 +NdisMAllocateSharedMemoryAsync@16 +NdisMapFile@12 +NdisMapIoSpace@24 +;NdisMatchPdoWithPacket ? +NdisMCancelTimer@8 +NdisMCloseLog@4 +NdisMCmActivateVc@8 +NdisMCmCreateVc@16 +NdisMCmDeactivateVc@4 +NdisMCmDeleteVc@4 +NdisMCmRegisterAddressFamily@16 +NdisMCmRequest@16 +NdisMCoActivateVcComplete@12 +NdisMCoDeactivateVcComplete@8 +NdisMCoIndicateReceivePacket@12 +NdisMCoIndicateStatus@20 +NdisMCompleteBufferPhysicalMapping@12 +NdisMCoReceiveComplete@4 +NdisMCoRequestComplete@12 +NdisMCoSendComplete@12 +NdisMCreateLog@12 +NdisMDeregisterAdapterShutdownHandler@4 +NdisMDeregisterDevice@4 +NdisMDeregisterDmaChannel@4 +NdisMDeregisterInterrupt@4 +NdisMDeregisterIoPortRange@16 +NdisMFlushLog@4 +NdisMFreeMapRegisters@4 +NdisMFreeSharedMemory@24 +NdisMGetDeviceProperty@24 +NdisMIndicateStatus@16 +NdisMIndicateStatusComplete@4 +NdisMInitializeScatterGatherDma@12 +NdisMInitializeTimer@16 +NdisMMapIoSpace@20 +NdisMoveMappedMemory@12 +NdisMPciAssignResources@12 +NdisMPromoteMiniport@4 +NdisMQueryAdapterInstanceName@8 +NdisMQueryAdapterResources@16 +NdisMQueryInformationComplete@8 +NdisMReadDmaCounter@4 +NdisMRegisterAdapterShutdownHandler@12 +NdisMRegisterDevice@24 +NdisMRegisterDmaChannel@24 +NdisMRegisterInterrupt@28 +NdisMRegisterIoPortRange@16 +NdisMRegisterMiniport@12 +NdisMRegisterUnloadHandler@8 +NdisMRemoveMiniport@4 +NdisMResetComplete@12 +NdisMSendComplete@12 +NdisMSendResourcesAvailable@4 +NdisMSetAttributes@16 +NdisMSetAttributesEx@20 +NdisMSetInformationComplete@8 +NdisMSetMiniportSecondary@8 +NdisMSetPeriodicTimer@8 +NdisMSetTimer@8 +NdisMSleep@4 +NdisMStartBufferPhysicalMapping@24 +NdisMSynchronizeWithInterrupt@12 +NdisMTransferDataComplete@16 +NdisMUnmapIoSpace@12 +NdisMWanIndicateReceive@20 +NdisMWanIndicateReceiveComplete@4 +NdisMWanSendComplete@12 +NdisMWriteLogData@12 +NdisOpenAdapter@44 +NdisOpenConfiguration@12 +NdisOpenConfigurationKeyByIndex@20 +NdisOpenConfigurationKeyByName@16 +NdisOpenFile@24 +NdisOpenProtocolConfiguration@12 +;NdisOverrideBusNumber ? +NdisPacketPoolUsage@4 +NdisPciAssignResources@20 +NdisQueryAdapterInstanceName@8 +;NdisQueryBindInstanceName? +NdisQueryBuffer@12 +NdisQueryBufferOffset@12 +NdisQueryBufferSafe@16 +NdisQueryMapRegisterCount@8 +NdisReadConfiguration@20 +NdisReadEisaSlotInformation@16 +NdisReadEisaSlotInformationEx@20 +NdisReadMcaPosInformation@16 +NdisReadNetworkAddress@16 +NdisReadPciSlotInformation@20 +NdisReadPcmciaAttributeMemory@16 +;NdisReEnumerateProtocolBindings ? +NdisReinitializePacket@4 +NdisRegisterAdapter@24 +NdisRegisterAdapterShutdownHandler@12 +NdisRegisterMac@24 +NdisRegisterProtocol@16 +;NdisRegisterTdiCallBack ? +NdisReleaseAdapterResources@4 +NdisReleaseReadWriteLock@8 +NdisReleaseSpinLock@4 +NdisRemoveInterrupt@4 +NdisRequest@12 +NdisReset@8 +NdisResetEvent@4 +NdisReturnPackets@8 +NdisSend@12 +NdisSendPackets@12 +NdisSetEvent@4 +;NdisSetPacketPoolProtocolId ? +;NdisSetProtocolFilter ? +NdisSetTimer@8 +NdisSetupDmaTransfer@24 +NdisSystemProcessorCount@0 +NdisTerminateWrapper@8 +NdisTransferData@28 +NdisUnchainBufferAtBack@8 +NdisUnchainBufferAtFront@8 +NdisUnicodeStringToAnsiString@8 +NdisUnmapFile@4 +NdisUpcaseUnicodeString@8 +NdisUpdateSharedMemory@20 +NdisWaitEvent@8 +NdisWriteConfiguration@16 +;NdisWriteErrorLogEntry ? +NdisWriteEventLogEntry@28 +NdisWritePciSlotInformation@20 +NdisWritePcmciaAttributeMemory@16 +TrChangeFunctionalAddress@20 +TrChangeGroupAddress@20 +TrCreateFilter@28 +TrDeleteFilter@4 +TrDeleteFilterOpenAdapter@12 +TrFilterAdjust@20 +;TrFilterDprIndicateReceive@28 +;TrFilterDprIndicateReceiveComplete@4 +TrFilterIndicateReceive@28 +TrFilterIndicateReceiveComplete@4 +TrNoteFilterOpenAdapter@16 +TrShouldAddressLoopBack@12 + +; EOF diff --git a/drivers/net/ndis/ndis.edf b/drivers/net/ndis/ndis.edf new file mode 100644 index 0000000..11ee1f9 --- /dev/null +++ b/drivers/net/ndis/ndis.edf @@ -0,0 +1,316 @@ +; NDIS Kernel Module - ReactOS Operating System + +LIBRARY NDIS.SYS + +EXPORTS +ArcFilterDprIndicateReceive=ArcFilterDprIndicateReceive@16 +ArcFilterDprIndicateReceiveComplete=ArcFilterDprIndicateReceiveComplete@4 +EthChangeFilterAddresses=EthChangeFilterAddresses@24 +EthCreateFilter=EthCreateFilter@28 +EthDeleteFilter=EthDeleteFilter@4 +EthDeleteFilterOpenAdapter=EthDeleteFilterOpenAdapter@12 +EthFilterAdjust=EthFilterAdjust@20 +;EthFilterDprIndicateReceive@32 ? +;EthFilterDprIndicateReceiveComplete@4 ? +EthFilterIndicateReceive=EthFilterIndicateReceive@32 +EthFilterIndicateReceiveComplete=EthFilterIndicateReceiveComplete@4 +EthNoteFilterOpenAdapter=EthNoteFilterOpenAdapter@16 +EthNumberOfOpenFilterAddresses=EthNumberOfOpenFilterAddresses@8 +EthQueryGlobalFilterAddresses=EthQueryGlobalFilterAddresses@20 +EthQueryOpenFilterAddresses=EthQueryOpenFilterAddresses@24 +EthShouldAddressLoopBack=EthShouldAddressLoopBack@8 +FddiChangeFilterLongAddresses=FddiChangeFilterLongAddresses@24 +FddiChangeFilterShortAddresses=FddiChangeFilterShortAddresses@24 +FddiCreateFilter=FddiCreateFilter@36 +FddiDeleteFilter=FddiDeleteFilter@4 +FddiDeleteFilterOpenAdapter=FddiDeleteFilterOpenAdapter@12 +FddiFilterAdjust=FddiFilterAdjust@20 +;FddiFilterDprIndicateReceive@36 ? +;FddiFilterDprIndicateReceiveComplete@4 ? +FddiFilterIndicateReceive=FddiFilterIndicateReceive@36 +FddiFilterIndicateReceiveComplete=FddiFilterIndicateReceiveComplete@4 +FddiNoteFilterOpenAdapter=FddiNoteFilterOpenAdapter@16 +FddiNumberOfOpenFilterLongAddresses=FddiNumberOfOpenFilterLongAddresses@8 +FddiNumberOfOpenFilterShortAddresses=FddiNumberOfOpenFilterShortAddresses@8 +FddiQueryGlobalFilterLongAddresses=FddiQueryGlobalFilterLongAddresses@20 +FddiQueryGlobalFilterShortAddresses=FddiQueryGlobalFilterShortAddresses@20 +FddiQueryOpenFilterLongAddresses=FddiQueryOpenFilterLongAddresses@24 +FddiQueryOpenFilterShortAddresses=FddiQueryOpenFilterShortAddresses@24 +FddiShouldAddressLoopBack=FddiShouldAddressLoopBack@12 +NDIS_BUFFER_TO_SPAN_PAGES=NDIS_BUFFER_TO_SPAN_PAGES@4 +NdisAcquireReadWriteLock=NdisAcquireReadWriteLock@12 +NdisAcquireSpinLock=NdisAcquireSpinLock@4 +NdisAdjustBufferLength=NdisAdjustBufferLength@8 +NdisAllocateBuffer=NdisAllocateBuffer@20 +NdisAllocateBufferPool=NdisAllocateBufferPool@12 +NdisAllocateDmaChannel=NdisAllocateDmaChannel@20 +NdisAllocateMemory=NdisAllocateMemory@20 +NdisAllocateMemoryWithTag=NdisAllocateMemoryWithTag@12 +NdisAllocatePacket=NdisAllocatePacket@12 +NdisAllocatePacketPool=NdisAllocatePacketPool@16 +NdisAllocatePacketPoolEx=NdisAllocatePacketPoolEx@20 +NdisAllocateSharedMemory=NdisAllocateSharedMemory@20 +NdisAllocateSpinLock=NdisAllocateSpinLock@4 +NdisAnsiStringToUnicodeString=NdisAnsiStringToUnicodeString@8 +NdisBufferLength=NdisBufferLength@4 +NdisBufferVirtualAddress=NdisBufferVirtualAddress@4 +NdisCancelTimer=NdisCancelTimer@8 +NdisClAddParty=NdisClAddParty@16 +NdisClCloseAddressFamily=NdisClCloseAddressFamily@4 +NdisClCloseCall=NdisClCloseCall@16 +NdisClDeregisterSap=NdisClDeregisterSap@4 +NdisClDropParty=NdisClDropParty@12 +NdisClIncomingCallComplete=NdisClIncomingCallComplete@12 +NdisClMakeCall=NdisClMakeCall@16 +NdisClModifyCallQoS=NdisClModifyCallQoS@8 +NdisClOpenAddressFamily=NdisClOpenAddressFamily@24 +NdisClRegisterSap=NdisClRegisterSap@16 +NdisCloseAdapter=NdisCloseAdapter@8 +NdisCloseConfiguration=NdisCloseConfiguration@4 +NdisCloseFile=NdisCloseFile@4 +NdisCmActivateVc=NdisCmActivateVc@8 +NdisCmAddPartyComplete=NdisCmAddPartyComplete@16 +NdisCmCloseAddressFamilyComplete=NdisCmCloseAddressFamilyComplete@8 +NdisCmCloseCallComplete=NdisCmCloseCallComplete@12 +NdisCmDeactivateVc=NdisCmDeactivateVc@4 +NdisCmDeregisterSapComplete=NdisCmDeregisterSapComplete@8 +NdisCmDispatchCallConnected=NdisCmDispatchCallConnected@4 +NdisCmDispatchIncomingCall=NdisCmDispatchIncomingCall@12 +NdisCmDispatchIncomingCallQoSChange=NdisCmDispatchIncomingCallQoSChange@8 +NdisCmDispatchIncomingCloseCall=NdisCmDispatchIncomingCloseCall@16 +NdisCmDispatchIncomingDropParty=NdisCmDispatchIncomingDropParty@16 +NdisCmDropPartyComplete=NdisCmDropPartyComplete@8 +NdisCmMakeCallComplete=NdisCmMakeCallComplete@20 +NdisCmModifyCallQoSComplete=NdisCmModifyCallQoSComplete@12 +NdisCmOpenAddressFamilyComplete=NdisCmOpenAddressFamilyComplete@12 +NdisCmRegisterAddressFamily=NdisCmRegisterAddressFamily@16 +NdisCmRegisterSapComplete=NdisCmRegisterSapComplete@12 +NdisCoCreateVc=NdisCoCreateVc@16 +NdisCoDeleteVc=NdisCoDeleteVc@4 +NdisCoRequest=NdisCoRequest@20 +NdisCoRequestComplete=NdisCoRequestComplete@20 +NdisCoSendPackets=NdisCoSendPackets@12 +;NdisCompareAnsiString ? +;NdisCompareUnicodeString ? +NdisCompleteBindAdapter=NdisCompleteBindAdapter@12 +NdisCompleteCloseAdapter=NdisCompleteCloseAdapter@8 +NdisCompleteDmaTransfer=NdisCompleteDmaTransfer@24 +NdisCompleteOpenAdapter=NdisCompleteOpenAdapter@12 +NdisCompletePnPEvent=NdisCompletePnPEvent@12 +NdisCompleteQueryStatistics=NdisCompleteQueryStatistics@12 +NdisCompleteUnbindAdapter=NdisCompleteUnbindAdapter@8 +NdisConvertStringToAtmAddress=NdisConvertStringToAtmAddress@12 +NdisCopyBuffer=NdisCopyBuffer@24 +NdisCopyFromPacketToPacket=NdisCopyFromPacketToPacket@24 +NdisDeregisterAdapter=NdisDeregisterAdapter@4 +NdisDeregisterAdapterShutdownHandler=NdisDeregisterAdapterShutdownHandler@4 +NdisDeregisterMac=NdisDeregisterMac@8 +NdisDeregisterProtocol=NdisDeregisterProtocol@8 +NdisDprAcquireSpinLock=NdisDprAcquireSpinLock@4 +NdisDprAllocatePacket=NdisDprAllocatePacket@12 +NdisDprAllocatePacketNonInterlocked=NdisDprAllocatePacketNonInterlocked@12 +NdisDprFreePacket=NdisDprFreePacket@4 +NdisDprFreePacketNonInterlocked=NdisDprFreePacketNonInterlocked@4 +NdisDprReleaseSpinLock=NdisDprReleaseSpinLock@4 +NdisEqualString=NdisEqualString@12 +NdisFlushBuffer=NdisFlushBuffer@8 +NdisFreeBuffer=NdisFreeBuffer@4 +NdisFreeBufferPool=NdisFreeBufferPool@4 +NdisFreeDmaChannel=NdisFreeDmaChannel@4 +NdisFreeMemory=NdisFreeMemory@12 +NdisFreePacket=NdisFreePacket@4 +NdisFreePacketPool=NdisFreePacketPool@4 +NdisFreeSharedMemory=NdisFreeSharedMemory@24 +NdisFreeSpinLock=NdisFreeSpinLock@4 +NdisGetBufferPhysicalArraySize=NdisGetBufferPhysicalArraySize@8 +NdisGetCurrentProcessorCounts=NdisGetCurrentProcessorCounts@12 +NdisGetCurrentProcessorCpuUsage=NdisGetCurrentProcessorCpuUsage@4 +NdisGetCurrentSystemTime=NdisGetCurrentSystemTime@4 +NdisGetDriverHandle=NdisGetDriverHandle@8 +NdisGetFirstBufferFromPacket=NdisGetFirstBufferFromPacket@20 +NdisGetReceivedPacket=NdisGetReceivedPacket@8 +NdisGetSystemUptime=NdisGetSystemUptime@4 +NdisIMAssociateMiniport=NdisIMAssociateMiniport@8 +NdisIMCancelInitializeDeviceInstance=NdisIMCancelInitializeDeviceInstance@8 +NdisIMCopySendCompletePerPacketInfo=NdisIMCopySendCompletePerPacketInfo@8 +NdisIMCopySendPerPacketInfo=NdisIMCopySendPerPacketInfo@8 +NdisIMDeInitializeDeviceInstance=NdisIMDeInitializeDeviceInstance@4 +NdisIMDeregisterLayeredMiniport=NdisIMDeregisterLayeredMiniport@4 +NdisIMGetBindingContext=NdisIMGetBindingContext@4 +NdisIMGetDeviceContext=NdisIMGetDeviceContext@4 +NdisIMInitializeDeviceInstance=NdisIMInitializeDeviceInstance@8 +NdisIMInitializeDeviceInstanceEx=NdisIMInitializeDeviceInstanceEx@12 +NdisImmediateReadPciSlotInformation=NdisImmediateReadPciSlotInformation@20 +NdisImmediateReadPortUchar=NdisImmediateReadPortUchar@12 +NdisImmediateReadPortUlong=NdisImmediateReadPortUlong@12 +NdisImmediateReadPortUshort=NdisImmediateReadPortUshort@12 +NdisImmediateReadSharedMemory=NdisImmediateReadSharedMemory@16 +NdisImmediateWritePciSlotInformation=NdisImmediateWritePciSlotInformation@20 +NdisImmediateWritePortUchar=NdisImmediateWritePortUchar@12 +NdisImmediateWritePortUlong=NdisImmediateWritePortUlong@12 +NdisImmediateWritePortUshort=NdisImmediateWritePortUshort@12 +NdisImmediateWriteSharedMemory=NdisImmediateWriteSharedMemory@16 +NdisIMQueueMiniportCallback=NdisIMQueueMiniportCallback@12 +NdisIMRegisterLayeredMiniport=NdisIMRegisterLayeredMiniport@16 +NdisIMRevertBack=NdisIMRevertBack@8 +NdisIMSwitchToMiniport=NdisIMSwitchToMiniport@8 +NdisInitAnsiString=NdisInitAnsiString@8 +NdisInitializeEvent=NdisInitializeEvent@4 +NdisInitializeInterrupt=NdisInitializeInterrupt@40 +NdisInitializeReadWriteLock=NdisInitializeReadWriteLock@4 +NdisInitializeString=NdisInitializeString@8 +NdisInitializeTimer=NdisInitializeTimer@12 +NdisInitializeWrapper=NdisInitializeWrapper@16 +NdisInitUnicodeString=NdisInitUnicodeString@8 +;NdisInterlockedAddLargeInterger ? +NdisInterlockedAddUlong=NdisInterlockedAddUlong@12 +NdisInterlockedDecrement=NdisInterlockedDecrement@4 +NdisInterlockedIncrement=NdisInterlockedIncrement@4 +NdisInterlockedInsertHeadList=NdisInterlockedInsertHeadList@12 +NdisInterlockedInsertTailList=NdisInterlockedInsertTailList@12 +NdisInterlockedPopEntrySList=NdisInterlockedPopEntrySList@8 +NdisInterlockedPushEntrySList=NdisInterlockedPushEntrySList@12 +NdisInterlockedRemoveHeadList=NdisInterlockedRemoveHeadList@8 +NdisMAllocateMapRegisters=NdisMAllocateMapRegisters@20 +NdisMAllocateSharedMemory=NdisMAllocateSharedMemory@20 +NdisMAllocateSharedMemoryAsync=NdisMAllocateSharedMemoryAsync@16 +NdisMapFile=NdisMapFile@12 +NdisMapIoSpace=NdisMapIoSpace@24 +;NdisMatchPdoWithPacket ? +NdisMCancelTimer=NdisMCancelTimer@8 +NdisMCloseLog=NdisMCloseLog@4 +NdisMCmActivateVc=NdisMCmActivateVc@8 +NdisMCmCreateVc=NdisMCmCreateVc@16 +NdisMCmDeactivateVc=NdisMCmDeactivateVc@4 +NdisMCmDeleteVc=NdisMCmDeleteVc@4 +NdisMCmRegisterAddressFamily=NdisMCmRegisterAddressFamily@16 +NdisMCmRequest=NdisMCmRequest@16 +NdisMCoActivateVcComplete=NdisMCoActivateVcComplete@12 +NdisMCoDeactivateVcComplete=NdisMCoDeactivateVcComplete@8 +NdisMCoIndicateReceivePacket=NdisMCoIndicateReceivePacket@12 +NdisMCoIndicateStatus=NdisMCoIndicateStatus@20 +NdisMCompleteBufferPhysicalMapping=NdisMCompleteBufferPhysicalMapping@12 +NdisMCoReceiveComplete=NdisMCoReceiveComplete@4 +NdisMCoRequestComplete=NdisMCoRequestComplete@12 +NdisMCoSendComplete=NdisMCoSendComplete@12 +NdisMCreateLog=NdisMCreateLog@12 +NdisMDeregisterAdapterShutdownHandler=NdisMDeregisterAdapterShutdownHandler@4 +NdisMDeregisterDevice=NdisMDeregisterDevice@4 +NdisMDeregisterDmaChannel=NdisMDeregisterDmaChannel@4 +NdisMDeregisterInterrupt=NdisMDeregisterInterrupt@4 +NdisMDeregisterIoPortRange=NdisMDeregisterIoPortRange@16 +NdisMFlushLog=NdisMFlushLog@4 +NdisMFreeMapRegisters=NdisMFreeMapRegisters@4 +NdisMFreeSharedMemory=NdisMFreeSharedMemory@24 +NdisMGetDeviceProperty=NdisMGetDeviceProperty@24 +NdisMIndicateStatus=NdisMIndicateStatus@16 +NdisMIndicateStatusComplete=NdisMIndicateStatusComplete@4 +NdisMInitializeScatterGatherDma=NdisMInitializeScatterGatherDma@12 +NdisMInitializeTimer=NdisMInitializeTimer@16 +NdisMMapIoSpace=NdisMMapIoSpace@20 +NdisMoveMappedMemory=NdisMoveMappedMemory@12 +NdisMPciAssignResources=NdisMPciAssignResources@12 +NdisMPromoteMiniport=NdisMPromoteMiniport@4 +NdisMQueryAdapterInstanceName=NdisMQueryAdapterInstanceName@8 +NdisMQueryAdapterResources=NdisMQueryAdapterResources@16 +NdisMQueryInformationComplete=NdisMQueryInformationComplete@8 +NdisMReadDmaCounter=NdisMReadDmaCounter@4 +NdisMRegisterAdapterShutdownHandler=NdisMRegisterAdapterShutdownHandler@12 +NdisMRegisterDevice=NdisMRegisterDevice@24 +NdisMRegisterDmaChannel=NdisMRegisterDmaChannel@24 +NdisMRegisterInterrupt=NdisMRegisterInterrupt@28 +NdisMRegisterIoPortRange=NdisMRegisterIoPortRange@16 +NdisMRegisterMiniport=NdisMRegisterMiniport@12 +NdisMRegisterUnloadHandler=NdisMRegisterUnloadHandler@8 +NdisMRemoveMiniport=NdisMRemoveMiniport@4 +NdisMResetComplete=NdisMResetComplete@12 +NdisMSendComplete=NdisMSendComplete@12 +NdisMSendResourcesAvailable=NdisMSendResourcesAvailable@4 +NdisMSetAttributes=NdisMSetAttributes@16 +NdisMSetAttributesEx=NdisMSetAttributesEx@20 +NdisMSetInformationComplete=NdisMSetInformationComplete@8 +NdisMSetMiniportSecondary=NdisMSetMiniportSecondary@8 +NdisMSetPeriodicTimer=NdisMSetPeriodicTimer@8 +NdisMSetTimer=NdisMSetTimer@8 +NdisMSleep=NdisMSleep@4 +NdisMStartBufferPhysicalMapping=NdisMStartBufferPhysicalMapping@24 +NdisMSynchronizeWithInterrupt=NdisMSynchronizeWithInterrupt@12 +NdisMTransferDataComplete=NdisMTransferDataComplete@16 +NdisMUnmapIoSpace=NdisMUnmapIoSpace@12 +NdisMWanIndicateReceive=NdisMWanIndicateReceive@20 +NdisMWanIndicateReceiveComplete=NdisMWanIndicateReceiveComplete@4 +NdisMWanSendComplete=NdisMWanSendComplete@12 +NdisMWriteLogData=NdisMWriteLogData@12 +NdisOpenAdapter=NdisOpenAdapter@44 +NdisOpenConfiguration=NdisOpenConfiguration@12 +NdisOpenConfigurationKeyByIndex=NdisOpenConfigurationKeyByIndex@20 +NdisOpenConfigurationKeyByName=NdisOpenConfigurationKeyByName@16 +NdisOpenFile=NdisOpenFile@24 +NdisOpenProtocolConfiguration=NdisOpenProtocolConfiguration@12 +;NdisOverrideBusNumber ? +NdisPacketPoolUsage=NdisPacketPoolUsage@4 +NdisPciAssignResources=NdisPciAssignResources@20 +NdisQueryAdapterInstanceName=NdisQueryAdapterInstanceName@8 +;NdisQueryBindInstanceName? +NdisQueryBuffer=NdisQueryBuffer@12 +NdisQueryBufferOffset=NdisQueryBufferOffset@12 +NdisQueryBufferSafe=NdisQueryBufferSafe@16 +NdisQueryMapRegisterCount=NdisQueryMapRegisterCount@8 +NdisReadConfiguration=NdisReadConfiguration@20 +NdisReadEisaSlotInformation=NdisReadEisaSlotInformation@16 +NdisReadEisaSlotInformationEx=NdisReadEisaSlotInformationEx@20 +NdisReadMcaPosInformation=NdisReadMcaPosInformation@16 +NdisReadNetworkAddress=NdisReadNetworkAddress@16 +NdisReadPciSlotInformation=NdisReadPciSlotInformation@20 +NdisReadPcmciaAttributeMemory=NdisReadPcmciaAttributeMemory@16 +;NdisReEnumerateProtocolBindings ? +NdisReinitializePacket=NdisReinitializePacket@4 +NdisRegisterAdapter=NdisRegisterAdapter@24 +NdisRegisterAdapterShutdownHandler=NdisRegisterAdapterShutdownHandler@12 +NdisRegisterMac=NdisRegisterMac@24 +NdisRegisterProtocol=NdisRegisterProtocol@16 +;NdisRegisterTdiCallBack ? +NdisReleaseAdapterResources=NdisReleaseAdapterResources@4 +NdisReleaseReadWriteLock=NdisReleaseReadWriteLock@8 +NdisReleaseSpinLock=NdisReleaseSpinLock@4 +NdisRemoveInterrupt=NdisRemoveInterrupt@4 +NdisRequest=NdisRequest@12 +NdisReset=NdisReset@8 +NdisResetEvent=NdisResetEvent@4 +NdisReturnPackets=NdisReturnPackets@8 +NdisSend=NdisSend@12 +NdisSendPackets=NdisSendPackets@12 +NdisSetEvent=NdisSetEvent@4 +;NdisSetPacketPoolProtocolId ? +;NdisSetProtocolFilter ? +NdisSetTimer=NdisSetTimer@8 +NdisSetupDmaTransfer=NdisSetupDmaTransfer@24 +NdisSystemProcessorCount=NdisSystemProcessorCount@0 +NdisTerminateWrapper=NdisTerminateWrapper@8 +NdisTransferData=NdisTransferData@28 +NdisUnchainBufferAtBack=NdisUnchainBufferAtBack@8 +NdisUnchainBufferAtFront=NdisUnchainBufferAtFront@8 +NdisUnicodeStringToAnsiString=NdisUnicodeStringToAnsiString@8 +NdisUnmapFile=NdisUnmapFile@4 +NdisUpcaseUnicodeString=NdisUpcaseUnicodeString@8 +NdisUpdateSharedMemory=NdisUpdateSharedMemory@20 +NdisWaitEvent=NdisWaitEvent@8 +NdisWriteConfiguration=NdisWriteConfiguration@16 +;NdisWriteErrorLogEntry ? +NdisWriteEventLogEntry=NdisWriteEventLogEntry@28 +NdisWritePciSlotInformation=NdisWritePciSlotInformation@20 +NdisWritePcmciaAttributeMemory=NdisWritePcmciaAttributeMemory@16 +TrChangeFunctionalAddress=TrChangeFunctionalAddress@20 +TrChangeGroupAddress=TrChangeGroupAddress@20 +TrCreateFilter=TrCreateFilter@28 +TrDeleteFilter=TrDeleteFilter@4 +TrDeleteFilterOpenAdapter=TrDeleteFilterOpenAdapter@12 +TrFilterAdjust=TrFilterAdjust@20 +;TrFilterDprIndicateReceive@28 +;TrFilterDprIndicateReceiveComplete@4 +TrFilterIndicateReceive=TrFilterIndicateReceive@28 +TrFilterIndicateReceiveComplete=TrFilterIndicateReceiveComplete@4 +TrNoteFilterOpenAdapter=TrNoteFilterOpenAdapter@16 +TrShouldAddressLoopBack=TrShouldAddressLoopBack@12 + +; EOF diff --git a/drivers/net/ndis/ndis.rc b/drivers/net/ndis/ndis.rc new file mode 100644 index 0000000..2ea36d0 --- /dev/null +++ b/drivers/net/ndis/ndis.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "NDIS library\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "ndis\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ndis.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/net/ndis/ndis/40gone.c b/drivers/net/ndis/ndis/40gone.c new file mode 100644 index 0000000..64e4cd5 --- /dev/null +++ b/drivers/net/ndis/ndis/40gone.c @@ -0,0 +1,749 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/40gone.c + * PURPOSE: Obsoleted functions in NDIS 4.0 + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +VOID +EXPORT +ArcFilterDprIndicateReceive( + IN PARC_FILTER Filter, + IN PUCHAR pRawHeader, + IN PUCHAR pData, + IN UINT Length) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +ArcFilterDprIndicateReceiveComplete( + IN PARC_FILTER Filter) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +EthChangeFilterAddresses( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT AddressCount, + IN CHAR Addresses [] [ETH_LENGTH_OF_ADDRESS], + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +BOOLEAN +EXPORT +EthCreateFilter( + IN UINT MaximumMulticastAddresses, + IN ETH_ADDRESS_CHANGE AddressChangeAction, + IN ETH_FILTER_CHANGE FilterChangeAction, + IN ETH_DEFERRED_CLOSE CloseAction, + IN PUCHAR AdapterAddress, + IN PNDIS_SPIN_LOCK Lock, + OUT PETH_FILTER * Filter) +{ + UNIMPLEMENTED + + return FALSE; +} + + +VOID +EXPORT +EthDeleteFilter( + IN PETH_FILTER Filter) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +EthDeleteFilterOpenAdapter( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +EthFilterAdjust( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT FilterClasses, + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +EthFilterIndicateReceive( + IN PETH_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +EthFilterIndicateReceiveComplete( + IN PETH_FILTER Filter) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +EthNoteFilterOpenAdapter( + IN PETH_FILTER Filter, + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE NdisBindingContext, + OUT PNDIS_HANDLE NdisFilterHandle) +{ + UNIMPLEMENTED + + return FALSE; +} + + +UINT +EXPORT +EthNumberOfOpenFilterAddresses( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle) +{ + UNIMPLEMENTED + + return 0; +} + + +VOID +EXPORT +EthQueryGlobalFilterAddresses ( + OUT PNDIS_STATUS Status, + IN PETH_FILTER Filter, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray [] [ETH_LENGTH_OF_ADDRESS]) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +EthQueryOpenFilterAddresses( + OUT PNDIS_STATUS Status, + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray [] [ETH_LENGTH_OF_ADDRESS]) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +EthShouldAddressLoopBack( + IN PETH_FILTER Filter, + IN CHAR Address [ETH_LENGTH_OF_ADDRESS]) +{ + UNIMPLEMENTED + + return FALSE; +} + + +NDIS_STATUS +EXPORT +FddiChangeFilterLongAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT AddressCount, + IN CHAR Addresses [] [FDDI_LENGTH_OF_LONG_ADDRESS], + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +FddiChangeFilterShortAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT AddressCount, + IN CHAR Addresses [] [FDDI_LENGTH_OF_SHORT_ADDRESS], + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +BOOLEAN +EXPORT +FddiCreateFilter( + IN UINT MaximumMulticastLongAddresses, + IN UINT MaximumMulticastShortAddresses, + IN FDDI_ADDRESS_CHANGE AddressChangeAction, + IN FDDI_FILTER_CHANGE FilterChangeAction, + IN FDDI_DEFERRED_CLOSE CloseAction, + IN PUCHAR AdapterLongAddress, + IN PUCHAR AdapterShortAddress, + IN PNDIS_SPIN_LOCK Lock, + OUT PFDDI_FILTER * Filter) +{ + UNIMPLEMENTED + + return FALSE; +} + + +VOID +EXPORT +FddiDeleteFilter( + IN PFDDI_FILTER Filter) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +FddiDeleteFilterOpenAdapter( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest) +{ + UNIMPLEMENTED + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +EXPORT +FddiFilterAdjust( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT FilterClasses, + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +FddiFilterIndicateReceive( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN UINT AddressLength, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +FddiFilterIndicateReceiveComplete( + IN PFDDI_FILTER Filter) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +FddiNoteFilterOpenAdapter( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE NdisBindingContext, + OUT PNDIS_HANDLE NdisFilterHandle) +{ + UNIMPLEMENTED + + return FALSE; +} + + +UINT +EXPORT +FddiNumberOfOpenFilterLongAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle) +{ + UNIMPLEMENTED + + return 0; +} + + +UINT +EXPORT +FddiNumberOfOpenFilterShortAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle) +{ + UNIMPLEMENTED + + return 0; +} + + +VOID +EXPORT +FddiQueryGlobalFilterLongAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray [] [FDDI_LENGTH_OF_LONG_ADDRESS]) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +FddiQueryGlobalFilterShortAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray [] [FDDI_LENGTH_OF_SHORT_ADDRESS]) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +FddiQueryOpenFilterLongAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray [] [FDDI_LENGTH_OF_LONG_ADDRESS]) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +FddiQueryOpenFilterShortAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray [] [FDDI_LENGTH_OF_SHORT_ADDRESS]) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +FddiShouldAddressLoopBack( + IN PFDDI_FILTER Filter, + IN CHAR Address [], + IN UINT LengthOfAddress) +{ + UNIMPLEMENTED + + return FALSE; +} + + +VOID +EXPORT +NdisAllocateDmaChannel( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE NdisDmaHandle, + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_DMA_DESCRIPTION DmaDescription, + IN ULONG MaximumLength) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisAllocateSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteBufferPhysicalMapping( + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG PhysicalMapRegister) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteRequest( + IN NDIS_HANDLE NdisBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteReset( + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_STATUS Status) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteSend( + IN NDIS_HANDLE NdisBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteTransferData( + IN NDIS_HANDLE NdisBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisIndicateReceive( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisIndicateReceiveComplete( + IN NDIS_HANDLE NdisBindingContext) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisIndicateStatus( + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisIndicateStatusComplete( + IN NDIS_HANDLE NdisBindingContext) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisPciAssignResources( + IN NDIS_HANDLE NdisMacHandle, + IN NDIS_HANDLE NdisWrapperHandle, + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SlotNumber, + OUT PNDIS_RESOURCE_LIST *AssignedResources) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisReadBindingInformation ( + OUT PNDIS_STATUS Status, + OUT PNDIS_STRING * Binding, + IN NDIS_HANDLE ConfigurationHandle) +{ + UNIMPLEMENTED +} + + +ULONG +EXPORT +NdisReadDmaCounter( + IN NDIS_HANDLE NdisDmaHandle) +{ + UNIMPLEMENTED + + return 0; +} + + +VOID +EXPORT +NdisStartBufferPhysicalMapping( + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG PhysicalMapRegister, + IN BOOLEAN WriteToDevice, + OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray, + OUT PUINT ArraySize) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +NdisSynchronizeWithInterrupt( + IN PNDIS_INTERRUPT Interrupt, + IN PVOID SynchronizeFunction, + IN PVOID SynchronizeContext) +{ + UNIMPLEMENTED + + return FALSE; +} + + +VOID +EXPORT +NdisUnmapIoSpace( + IN NDIS_HANDLE NdisAdapterHandle, + IN PVOID VirtualAddress, + IN UINT Length) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +TrChangeFunctionalAddress( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN CHAR FunctionalAddressArray [TR_LENGTH_OF_FUNCTIONAL], + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +TrChangeGroupAddress( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN CHAR GroupAddressArray [TR_LENGTH_OF_FUNCTIONAL], + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +BOOLEAN +EXPORT +TrCreateFilter( + IN TR_ADDRESS_CHANGE AddressChangeAction, + IN TR_GROUP_CHANGE GroupChangeAction, + IN TR_FILTER_CHANGE FilterChangeAction, + IN TR_DEFERRED_CLOSE CloseAction, + IN PUCHAR AdapterAddress, + IN PNDIS_SPIN_LOCK Lock, + OUT PTR_FILTER * Filter) +{ + UNIMPLEMENTED + + return FALSE; +} + + +VOID +EXPORT +TrDeleteFilter( + IN PTR_FILTER Filter) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +TrDeleteFilterOpenAdapter ( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest) +{ + UNIMPLEMENTED + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +EXPORT +TrFilterAdjust( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT FilterClasses, + IN BOOLEAN Set) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +TrFilterIndicateReceive( + IN PTR_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +TrFilterIndicateReceiveComplete( + IN PTR_FILTER Filter) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +TrNoteFilterOpenAdapter( + IN PTR_FILTER Filter, + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE NdisBindingContext, + OUT PNDIS_HANDLE NdisFilterHandle) +{ + UNIMPLEMENTED + + return FALSE; +} + + +BOOLEAN +EXPORT +TrShouldAddressLoopBack( + IN PTR_FILTER Filter, + IN CHAR DestinationAddress [TR_LENGTH_OF_ADDRESS], + IN CHAR SourceAddress [TR_LENGTH_OF_ADDRESS]) +{ + UNIMPLEMENTED + + return FALSE; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/50gone.c b/drivers/net/ndis/ndis/50gone.c new file mode 100644 index 0000000..1f1a4b5 --- /dev/null +++ b/drivers/net/ndis/ndis/50gone.c @@ -0,0 +1,408 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/50gone.c + * PURPOSE: Obsoleted functions in NDIS 5.0 + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +VOID +EXPORT +NdisCompleteCloseAdapter( + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_STATUS Status) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteOpenAdapter( + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisDeregisterAdapter( + IN NDIS_HANDLE NdisAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisDeregisterAdapterShutdownHandler( + IN NDIS_HANDLE NdisAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisDeregisterMac( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisMacHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisFreeDmaChannel( + IN PNDIS_HANDLE NdisDmaHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisFreeSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisIMQueueMiniportCallback( + IN NDIS_HANDLE MiniportAdapterHandle, + IN W_MINIPORT_CALLBACK CallbackRoutine, + IN PVOID CallbackContext) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisIMRevertBack( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE SwitchHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +NdisIMSwitchToMiniport( + IN NDIS_HANDLE MiniportAdapterHandle, + OUT PNDIS_HANDLE SwitchHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED + + return FALSE; +} + + +VOID +EXPORT +NdisInitializeInterrupt( + OUT PNDIS_STATUS Status, + IN OUT PNDIS_INTERRUPT Interrupt, + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_INTERRUPT_SERVICE InterruptServiceRoutine, + IN PVOID InterruptContext, + IN PNDIS_DEFERRED_PROCESSING DeferredProcessingRoutine, + IN UINT InterruptVector, + IN UINT InterruptLevel, + IN BOOLEAN SharedInterrupt, + IN NDIS_INTERRUPT_MODE InterruptMode) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMapIoSpace( + OUT PNDIS_STATUS Status, + OUT PVOID *VirtualAddress, + IN NDIS_HANDLE NdisAdapterHandle, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT Length) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisOverrideBusNumber( + IN NDIS_HANDLE WrapperConfigurationContext, + IN NDIS_HANDLE MiniportAdapterHandle OPTIONAL, + IN ULONG BusNumber) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisQueryReceiveInformation( + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE MacContext, + OUT PLONGLONG TimeSent OPTIONAL, + OUT PLONGLONG TimeReceived OPTIONAL, + IN PUCHAR Buffer, + IN UINT BufferSize, + OUT PUINT SizeNeeded) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisReadMcaPosInformation( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PUINT ChannelNumber, + OUT PNDIS_MCA_POS_DATA McaData) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisRegisterAdapter( + OUT PNDIS_HANDLE NdisAdapterHandle, + IN NDIS_HANDLE NdisMacHandle, + IN NDIS_HANDLE MacAdapterContext, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PNDIS_STRING AdapterName, + IN PVOID AdapterInformation) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisRegisterAdapterShutdownHandler( + IN NDIS_HANDLE NdisAdapterHandle, + IN PVOID ShutdownContext, + IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisRegisterMac( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE NdisMacHandle, + IN NDIS_HANDLE NdisWrapperHandle, + IN NDIS_HANDLE MacMacContext, + IN PNDIS_MAC_CHARACTERISTICS MacCharacteristics, + IN UINT CharacteristicsLength) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisReleaseAdapterResources( + IN NDIS_HANDLE NdisAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisRemoveInterrupt( + IN PNDIS_INTERRUPT Interrupt) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisSetupDmaTransfer( + OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE NdisDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisUpdateSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 4.0 + */ +{ + UNIMPLEMENTED +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/SOURCES b/drivers/net/ndis/ndis/SOURCES new file mode 100644 index 0000000..692b996 --- /dev/null +++ b/drivers/net/ndis/ndis/SOURCES @@ -0,0 +1,29 @@ +TARGETNAME=ndis +TARGETPATH=..\objects +TARGETTYPE=EXPORT_DRIVER + +TARGETLIBS= + +C_DEFINES=$(C_DEFINES) -DUNICODE -DNDIS_WRAPPER -DBINARY_COMPATIBLE=1 + +INCLUDES=..\include;..\..\..\..\include\net;$(BASEDIR)\INC + +SOURCES= 40gone.c \ + 50gone.c \ + buffer.c \ + cl.c \ + cm.c \ + co.c \ + control.c \ + hardware.c \ + io.c \ + main.c \ + memory.c \ + miniport.c \ + protocol.c \ + string.c \ + stubs.c \ + time.c \ + RESOURCE.RC + +MSC_WARNING_LEVEL=/W3 /WX diff --git a/drivers/net/ndis/ndis/buffer.c b/drivers/net/ndis/ndis/buffer.c new file mode 100644 index 0000000..fdaf4b2 --- /dev/null +++ b/drivers/net/ndis/ndis/buffer.c @@ -0,0 +1,1033 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/buffer.c + * PURPOSE: Buffer management routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + + +__inline ULONG SkipToOffset( + PNDIS_BUFFER Buffer, + UINT Offset, + PUCHAR *Data, + PUINT Size) +/* + * FUNCTION: Skips Offset bytes into a buffer chain + * ARGUMENTS: + * Buffer = Pointer to NDIS buffer + * Offset = Number of bytes to skip + * Data = Address of a pointer that on return will contain the + * address of the offset in the buffer + * Size = Address of a pointer that on return will contain the + * size of the destination buffer + * RETURNS: + * Offset into buffer, -1 if buffer chain was smaller than Offset bytes + * NOTES: + * Buffer may be NULL + */ +{ + for (;;) { + + if (!Buffer) + return -1; + + NdisQueryBuffer(Buffer, (PVOID)Data, Size); + + if (Offset < *Size) { + ((ULONG_PTR)*Data) += Offset; + *Size -= Offset; + break; + } + + Offset -= *Size; + + NdisGetNextBuffer(Buffer, &Buffer); + } + + return Offset; +} + + +UINT CopyBufferToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PUCHAR SrcData, + UINT Length) +/* + * FUNCTION: Copies data from a buffer to an NDIS buffer chain + * ARGUMENTS: + * DstBuffer = Pointer to destination NDIS buffer + * DstOffset = Destination start offset + * SrcData = Pointer to source buffer + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the destination + * buffer size + */ +{ + UINT BytesCopied, BytesToCopy, DstSize; + PUCHAR DstData; + + NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length)); + + /* Skip DstOffset bytes in the destination buffer chain */ + if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) + return 0; + + /* Start copying the data */ + BytesCopied = 0; + for (;;) { + BytesToCopy = MIN(DstSize, Length); + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); + BytesCopied += BytesToCopy; + (ULONG_PTR)SrcData += BytesToCopy; + + Length -= BytesToCopy; + if (Length == 0) + break; + + DstSize -= BytesToCopy; + if (DstSize == 0) { + /* No more bytes in desination buffer. Proceed to + the next buffer in the destination buffer chain */ + NdisGetNextBuffer(DstBuffer, &DstBuffer); + if (!DstBuffer) + break; + + NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); + } + } + + return BytesCopied; +} + + +UINT CopyBufferChainToBuffer( + PUCHAR DstData, + PNDIS_BUFFER SrcBuffer, + UINT SrcOffset, + UINT Length) +/* + * FUNCTION: Copies data from an NDIS buffer chain to a buffer + * ARGUMENTS: + * DstData = Pointer to destination buffer + * SrcBuffer = Pointer to source NDIS buffer + * SrcOffset = Source start offset + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the source + * buffer size + */ +{ + UINT BytesCopied, BytesToCopy, SrcSize; + PUCHAR SrcData; + + NDIS_DbgPrint(MAX_TRACE, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length)); + + /* Skip SrcOffset bytes in the source buffer chain */ + if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) + return 0; + + /* Start copying the data */ + BytesCopied = 0; + for (;;) { + BytesToCopy = MIN(SrcSize, Length); + + NDIS_DbgPrint(MAX_TRACE, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData)); + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); + BytesCopied += BytesToCopy; + (ULONG_PTR)DstData += BytesToCopy; + + Length -= BytesToCopy; + if (Length == 0) + break; + + SrcSize -= BytesToCopy; + if (SrcSize == 0) { + /* No more bytes in source buffer. Proceed to + the next buffer in the source buffer chain */ + NdisGetNextBuffer(SrcBuffer, &SrcBuffer); + if (!SrcBuffer) + break; + + NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); + } + } + + return BytesCopied; +} + + +UINT CopyPacketToBuffer( + PUCHAR DstData, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length) +/* + * FUNCTION: Copies data from an NDIS packet to a buffer + * ARGUMENTS: + * DstData = Pointer to destination buffer + * SrcPacket = Pointer to source NDIS packet + * SrcOffset = Source start offset + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the source + * buffer size + */ +{ + PNDIS_BUFFER FirstBuffer; + PVOID Address; + UINT FirstLength; + UINT TotalLength; + + NDIS_DbgPrint(MAX_TRACE, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length)); + + NdisGetFirstBufferFromPacket(SrcPacket, + &FirstBuffer, + &Address, + &FirstLength, + &TotalLength); + + return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length); +} + + +UINT CopyPacketToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length) +/* + * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain + * ARGUMENTS: + * DstBuffer = Pointer to destination NDIS buffer + * DstOffset = Destination start offset + * SrcPacket = Pointer to source NDIS packet + * SrcOffset = Source start offset + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the source and + * destination buffer sizes + */ +{ + PNDIS_BUFFER SrcBuffer; + PUCHAR DstData, SrcData; + UINT DstSize, SrcSize; + UINT Count, Total; + + NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length)); + + /* Skip DstOffset bytes in the destination buffer chain */ + NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); + if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) + return 0; + + /* Skip SrcOffset bytes in the source packet */ + NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total); + if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) + return 0; + + /* Copy the data */ + for (Total = 0;;) { + /* Find out how many bytes we can copy at one time */ + if (Length < SrcSize) + Count = Length; + else + Count = SrcSize; + if (DstSize < Count) + Count = DstSize; + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); + + Total += Count; + Length -= Count; + if (Length == 0) + break; + + DstSize -= Count; + if (DstSize == 0) { + /* No more bytes in destination buffer. Proceed to + the next buffer in the destination buffer chain */ + NdisGetNextBuffer(DstBuffer, &DstBuffer); + if (!DstBuffer) + break; + + NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); + } + + SrcSize -= Count; + if (SrcSize == 0) { + /* No more bytes in source buffer. Proceed to + the next buffer in the source buffer chain */ + NdisGetNextBuffer(SrcBuffer, &SrcBuffer); + if (!SrcBuffer) + break; + + NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); + } + } + + return Total; +} + + + +VOID +EXPORT +NdisAdjustBufferLength( + IN PNDIS_BUFFER Buffer, + IN UINT Length) +/* + * FUNCTION: Modifies the length of an NDIS buffer + * ARGUMENTS: + * Buffer = Pointer to NDIS buffer descriptor + * Length = New size of buffer + */ +{ + Buffer->ByteCount = Length; +} + + +ULONG +EXPORT +NDIS_BUFFER_TO_SPAN_PAGES( + IN PNDIS_BUFFER Buffer) +/* + * FUNCTION: Determines how many physical pages a buffer is made of + * ARGUMENTS: + * Buffer = Pointer to NDIS buffer descriptor + */ +{ + if (MmGetMdlByteCount(Buffer) == 0) + return 1; + + return ADDRESS_AND_SIZE_TO_SPAN_PAGES( + MmGetMdlVirtualAddress(Buffer), + MmGetMdlByteCount(Buffer)); +} + + +VOID +EXPORT +NdisAllocateBuffer( + OUT PNDIS_STATUS Status, + OUT PNDIS_BUFFER * Buffer, + IN NDIS_HANDLE PoolHandle, + IN PVOID VirtualAddress, + IN UINT Length) +/* + * FUNCTION: Allocates an NDIS buffer descriptor + * ARGUMENTS: + * Status = Address of buffer for status + * Buffer = Address of buffer for NDIS buffer descriptor + * PoolHandle = Handle returned by NdisAllocateBufferPool + * VirtualAddress = Pointer to virtual address of data buffer + * Length = Number of bytes in data buffer + */ +{ + KIRQL OldIrql; + PNETWORK_HEADER Temp; + PNDIS_BUFFER_POOL Pool = (PNDIS_BUFFER_POOL)PoolHandle; + + NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Buffer (0x%X) PoolHandle (0x%X) " + "VirtualAddress (0x%X) Length (%d)\n", + Status, Buffer, PoolHandle, VirtualAddress, Length)); + + KeAcquireSpinLock(&Pool->SpinLock, &OldIrql); + + if (Pool->FreeList) { + Temp = Pool->FreeList; + Pool->FreeList = Temp->Next; + + KeReleaseSpinLock(&Pool->SpinLock, OldIrql); + + Temp->Next = NULL; + +#ifdef _MSC_VER + MmInitializeMdl(&Temp->Mdl, VirtualAddress, Length); + Temp->Mdl.MdlFlags |= (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE); + Temp->Mdl.MappedSystemVa = VirtualAddress; +#else + Temp->Mdl.Next = (PMDL)NULL; + Temp->Mdl.Size = (CSHORT)(sizeof(MDL) + + (ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length) * sizeof(ULONG))); + Temp->Mdl.MdlFlags = (MDL_SOURCE_IS_NONPAGED_POOL | MDL_ALLOCATED_FIXED_SIZE); +; Temp->Mdl.StartVa = (PVOID)PAGE_ROUND_DOWN(VirtualAddress); + Temp->Mdl.ByteOffset = (ULONG_PTR)(VirtualAddress - PAGE_ROUND_DOWN(VirtualAddress)); + Temp->Mdl.ByteCount = Length; + Temp->Mdl.MappedSystemVa = VirtualAddress; +#if 0 + //Temp->Mdl.Process = PsGetCurrentProcess(); +#else + Temp->Mdl.Process = NULL; +#endif +#endif + + Temp->BufferPool = Pool; + + *Buffer = (PNDIS_BUFFER)Temp; + *Status = NDIS_STATUS_SUCCESS; + } else { + KeReleaseSpinLock(&Pool->SpinLock, OldIrql); + *Status = NDIS_STATUS_FAILURE; + } +} + + +VOID +EXPORT +NdisAllocateBufferPool( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE PoolHandle, + IN UINT NumberOfDescriptors) +/* + * FUNCTION: Allocates storage for an NDIS buffer pool + * ARGUMENTS: + * Status = Address of buffer for status + * PoolHandle = Address of buffer for pool handle + * NumberOfDescriptors = Size of buffer pool in number of descriptors + */ +{ + UINT i; + PNDIS_BUFFER_POOL Pool; + PNETWORK_HEADER Buffer; + + NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) NumberOfDescriptors (%d).\n", + Status, PoolHandle, NumberOfDescriptors)); + + Pool = ExAllocatePool(NonPagedPool, + sizeof(NDIS_BUFFER_POOL) + + sizeof(NETWORK_HEADER) * + NumberOfDescriptors); + if (Pool) { + KeInitializeSpinLock(&Pool->SpinLock); + + if (NumberOfDescriptors > 0) { + Buffer = &Pool->Buffers[0]; + Pool->FreeList = Buffer; + for (i = 1; i < NumberOfDescriptors; i++) { + Buffer->Next = &Pool->Buffers[i]; + Buffer = Buffer->Next; + } + Buffer->Next = NULL; + } else + Pool->FreeList = NULL; + + *Status = NDIS_STATUS_SUCCESS; + *PoolHandle = (PNDIS_HANDLE)Pool; + } else + *Status = NDIS_STATUS_RESOURCES; +} + + +VOID +EXPORT +NdisAllocatePacket( + OUT PNDIS_STATUS Status, + OUT PNDIS_PACKET * Packet, + IN NDIS_HANDLE PoolHandle) +/* + * FUNCTION: Allocates an NDIS packet descriptor + * ARGUMENTS: + * Status = Address of buffer for status + * Packet = Address of buffer for packet descriptor + * PoolHandle = Handle returned by NdisAllocatePacketPool + */ +{ + KIRQL OldIrql; + PNDIS_PACKET Temp; + PNDIS_PACKET_POOL Pool = (PNDIS_PACKET_POOL)PoolHandle; + + NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n", + Status, Packet, PoolHandle)); + + KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &OldIrql); + + if (Pool->FreeList) { + Temp = Pool->FreeList; + Pool->FreeList = (PNDIS_PACKET)Temp->Private.Head; + + KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql); + + RtlZeroMemory(&Temp->Private, sizeof(NDIS_PACKET_PRIVATE)); + Temp->Private.Pool = Pool; + + *Packet = Temp; + *Status = NDIS_STATUS_SUCCESS; + } else { + *Status = NDIS_STATUS_RESOURCES; + KeReleaseSpinLock(&Pool->SpinLock.SpinLock, OldIrql); + } +} + + +VOID +EXPORT +NdisAllocatePacketPool( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE PoolHandle, + IN UINT NumberOfDescriptors, + IN UINT ProtocolReservedLength) +/* + * FUNCTION: Allocates storage for an NDIS packet pool + * ARGUMENTS: + * Status = Address of buffer for status + * PoolHandle = Address of buffer for pool handle + * NumberOfDescriptors = Size of packet pool in number of descriptors + * ProtocolReservedLength = Size of protocol reserved area in bytes + */ +{ + PNDIS_PACKET_POOL Pool; + UINT Size, Length, i; + PNDIS_PACKET Packet, NextPacket; + + NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) " + "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n", + Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength)); + + Length = sizeof(NDIS_PACKET) + ProtocolReservedLength; + Size = sizeof(NDIS_PACKET_POOL) + Length * NumberOfDescriptors; + + Pool = ExAllocatePool(NonPagedPool, Size); + if (Pool) { + KeInitializeSpinLock(&Pool->SpinLock.SpinLock); + Pool->PacketLength = Length; + + if (NumberOfDescriptors > 0) { + Packet = (PNDIS_PACKET)&Pool->Buffer; + Pool->FreeList = Packet; + + NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length); + for (i = 1; i < NumberOfDescriptors; i++) { + Packet->Private.Head = (PNDIS_BUFFER)NextPacket; + Packet = NextPacket; + NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length); + } + Packet->Private.Head = NULL; + } else + Pool->FreeList = NULL; + + *Status = NDIS_STATUS_SUCCESS; + *PoolHandle = (PNDIS_HANDLE)Pool; + } else + *Status = NDIS_STATUS_RESOURCES; +} + + +VOID +EXPORT +NdisAllocatePacketPoolEx( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE PoolHandle, + IN UINT NumberOfDescriptors, + IN UINT NumberOfOverflowDescriptors, + IN UINT ProtocolReservedLength) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +ULONG +EXPORT +NdisBufferLength( + IN PNDIS_BUFFER Buffer) +/* + * FUNCTION: Modifies the length of an NDIS buffer + * ARGUMENTS: + * Buffer = Pointer to NDIS buffer descriptor + * Length = New size of buffer + * NOTES: + * NDIS 5.0 + * RETURNS: + * Length of NDIS buffer + */ +{ + return Buffer->ByteCount; +} + + +PVOID +EXPORT +NdisBufferVirtualAddress( + IN PNDIS_BUFFER Buffer) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NULL; +} + + +VOID +EXPORT +NdisCopyBuffer( + OUT PNDIS_STATUS Status, + OUT PNDIS_BUFFER *Buffer, + IN NDIS_HANDLE PoolHandle, + IN PVOID MemoryDescriptor, + IN UINT Offset, + IN UINT Length) +/* + * FUNCTION: Returns a new buffer descriptor for a (partial) buffer + * ARGUMENTS: + * Status = Address of a buffer to place status of operation + * Buffer = Address of a buffer to place new buffer descriptor + * PoolHandle = Handle returned by NdisAllocateBufferPool + * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER) + * Offset = Offset in buffer to start copying + * Length = Number of bytes to copy + */ +{ + *Status = NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCopyFromPacketToPacket( + IN PNDIS_PACKET Destination, + IN UINT DestinationOffset, + IN UINT BytesToCopy, + IN PNDIS_PACKET Source, + IN UINT SourceOffset, + OUT PUINT BytesCopied) +/* + * FUNCTION: Copies data from one packet to another + * ARGUMENTS: + * Destination = Pointer to packet to copy data to + * DestinationOffset = Offset in destination packet to copy data to + * BytesToCopy = Number of bytes to copy + * Source = Pointer to packet descriptor to copy from + * SourceOffset = Offset in source packet to start copying from + * BytesCopied = Address of buffer to place number of bytes copied + */ +{ + PNDIS_BUFFER SrcBuffer; + PNDIS_BUFFER DstBuffer; + PUCHAR DstData, SrcData; + UINT DstSize, SrcSize; + UINT Count, Total; + + *BytesCopied = 0; + + /* Skip DestinationOffset bytes in the destination packet */ + NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID)&DstData, &DstSize, &Total); + if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == -1) + return; + + /* Skip SourceOffset bytes in the source packet */ + NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total); + if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == -1) + return; + + /* Copy the data */ + for (Total = 0;;) { + /* Find out how many bytes we can copy at one time */ + if (BytesToCopy < SrcSize) + Count = BytesToCopy; + else + Count = SrcSize; + if (DstSize < Count) + Count = DstSize; + + RtlCopyMemory(DstData, SrcData, Count); + + Total += Count; + BytesToCopy -= Count; + if (BytesToCopy == 0) + break; + + DstSize -= Count; + if (DstSize == 0) { + /* No more bytes in destination buffer. Proceed to + the next buffer in the destination buffer chain */ + NdisGetNextBuffer(DstBuffer, &DstBuffer); + if (!DstBuffer) + break; + + NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); + } + + SrcSize -= Count; + if (SrcSize == 0) { + /* No more bytes in source buffer. Proceed to + the next buffer in the source buffer chain */ + NdisGetNextBuffer(SrcBuffer, &SrcBuffer); + if (!SrcBuffer) + break; + + NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); + } + } + + *BytesCopied = Total; +} + + +VOID +EXPORT +NdisDprAllocatePacket( + OUT PNDIS_STATUS Status, + OUT PNDIS_PACKET *Packet, + IN NDIS_HANDLE PoolHandle) +/* + * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL + * ARGUMENTS: + * Status = Address of buffer to place status of operation + * Packet = Address of buffer to place a pointer to a packet descriptor + * PoolHandle = Handle returned by NdisAllocatePacketPool + */ +{ +} + + +VOID +EXPORT +NdisDprAllocatePacketNonInterlocked( + OUT PNDIS_STATUS Status, + OUT PNDIS_PACKET *Packet, + IN NDIS_HANDLE PoolHandle) +/* + * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization) + * ARGUMENTS: + * Status = Address of buffer to place status of operation + * Packet = Address of buffer to place a pointer to a packet descriptor + * PoolHandle = Handle returned by NdisAllocatePacketPool + */ +{ + *Status = NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisDprFreePacket( + IN PNDIS_PACKET Packet) +/* + * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL + * ARGUMENTS: + * Packet = Pointer to packet to free + */ +{ +} + + +VOID +EXPORT +NdisDprFreePacketNonInterlocked( + IN PNDIS_PACKET Packet) +/* + * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization) + * ARGUMENTS: + * Packet = Pointer to packet to free + */ +{ +} + + +VOID +EXPORT +NdisFreeBufferPool( + IN NDIS_HANDLE PoolHandle) +/* + * FUNCTION: Frees storage allocated for an NDIS buffer pool + * ARGUMENTS: + * PoolHandle = Handle returned by NdisAllocateBufferPool + */ +{ + ExFreePool((PVOID)PoolHandle); +} + + +VOID +EXPORT +NdisFreePacketPool( + IN NDIS_HANDLE PoolHandle) +/* + * FUNCTION: Frees storage allocated for an NDIS packet pool + * ARGUMENTS: + * PoolHandle = Handle returned by NdisAllocatePacketPool + */ +{ + ExFreePool((PVOID)PoolHandle); +} + + +VOID +EXPORT +NdisFreeBuffer( + IN PNDIS_BUFFER Buffer) +/* + * FUNCTION: Puts an NDIS buffer descriptor back in it's pool + * ARGUMENTS: + * Buffer = Pointer to buffer descriptor + */ +{ + KIRQL OldIrql; + PNDIS_BUFFER_POOL Pool; + PNETWORK_HEADER Temp = (PNETWORK_HEADER)Buffer; + + NDIS_DbgPrint(MAX_TRACE, ("Buffer (0x%X).\n", Buffer)); + + Pool = Temp->BufferPool; + + KeAcquireSpinLock(&Pool->SpinLock, &OldIrql); + Buffer->Next = (PMDL)Pool->FreeList; + Pool->FreeList = (PNETWORK_HEADER)Buffer; + KeReleaseSpinLock(&Pool->SpinLock, OldIrql); +} + + +VOID +EXPORT +NdisFreePacket( + IN PNDIS_PACKET Packet) +/* + * FUNCTION: Puts an NDIS packet descriptor back in it's pool + * ARGUMENTS: + * Packet = Pointer to packet descriptor + */ +{ + KIRQL OldIrql; + + NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet)); + + KeAcquireSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, &OldIrql); + Packet->Private.Head = (PNDIS_BUFFER)Packet->Private.Pool->FreeList; + Packet->Private.Pool->FreeList = Packet; + KeReleaseSpinLock(&Packet->Private.Pool->SpinLock.SpinLock, OldIrql); +} + + +VOID +EXPORT +NdisGetBufferPhysicalArraySize( + IN PNDIS_BUFFER Buffer, + OUT PUINT ArraySize) +/* + * FUNCTION: Returns number of discontiguous physical blocks backing a buffer + * ARGUMENTS: + * Buffer = Pointer to buffer descriptor + * ArraySize = Address of buffer to place number of physical blocks + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisGetFirstBufferFromPacket( + IN PNDIS_PACKET _Packet, + OUT PNDIS_BUFFER *_FirstBuffer, + OUT PVOID *_FirstBufferVA, + OUT PUINT _FirstBufferLength, + OUT PUINT _TotalBufferLength) +/* + * FUNCTION: Retrieves information about an NDIS packet + * ARGUMENTS: + * _Packet = Pointer to NDIS packet + * _FirstBuffer = Address of buffer for pointer to first NDIS buffer + * _FirstBufferVA = Address of buffer for address of first NDIS buffer + * _FirstBufferLength = Address of buffer for length of first buffer + * _TotalBufferLength = Address of buffer for total length of packet + */ +{ + PNDIS_BUFFER Buffer; + + Buffer = _Packet->Private.Head; + *_FirstBuffer = Buffer; + *_FirstBufferVA = MmGetMdlVirtualAddress(Buffer); + + if (Buffer != NULL) { + *_FirstBufferLength = MmGetMdlByteCount(Buffer); + Buffer = Buffer->Next; + } else + *_FirstBufferLength = 0; + + *_TotalBufferLength = *_FirstBufferLength; + + while (Buffer != NULL) { + *_TotalBufferLength += MmGetMdlByteCount(Buffer); + Buffer = Buffer->Next; + } +} + + +VOID +EXPORT +NdisReturnPackets( + IN PNDIS_PACKET *PacketsToReturn, + IN UINT NumberOfPackets) +/* + * FUNCTION: Releases ownership of one or more packets + * ARGUMENTS: + * PacketsToReturn = Pointer to an array of pointers to packet descriptors + * NumberOfPackets = Number of pointers in descriptor pointer array + */ +{ + UNIMPLEMENTED +} + + +UINT +EXPORT +NdisPacketPoolUsage( + IN NDIS_HANDLE PoolHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return 0; +} + + +VOID +EXPORT +NdisQueryBuffer( + IN PNDIS_BUFFER Buffer, + OUT PVOID *VirtualAddress OPTIONAL, + OUT PUINT Length) +/* + * FUNCTION: + * Queries an NDIS buffer for information + * ARGUMENTS: + * Buffer = Pointer to NDIS buffer to query + * VirtualAddress = Address of buffer to place virtual address + * Length = Address of buffer to place length of buffer + */ +{ + if (VirtualAddress != NULL) + *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer); + + *Length = MmGetMdlByteCount(Buffer); +} + + +VOID +EXPORT +NdisQueryBufferOffset( + IN PNDIS_BUFFER Buffer, + OUT PUINT Offset, + OUT PUINT Length) +{ + *((PUINT)Offset) = MmGetMdlByteOffset(Buffer); + *((PUINT)Length) = MmGetMdlByteCount(Buffer); +} + + +VOID +EXPORT +NdisUnchainBufferAtBack( + IN OUT PNDIS_PACKET Packet, + OUT PNDIS_BUFFER *Buffer) +/* + * FUNCTION: + * Removes the last buffer in a packet + * ARGUMENTS: + * Packet = Pointer to NDIS packet + * Buffer = Address of buffer to place pointer to removed NDIS buffer + */ +{ + PNDIS_BUFFER NdisBuffer, Previous; + + NdisQueryPacket(Packet, + NULL, + NULL, + &NdisBuffer, + NULL); + if (!NdisBuffer) { + *Buffer = NULL; + return; + } + + Previous = NULL; + while (NdisBuffer->Next) { + Previous = NdisBuffer; + NdisBuffer = NdisBuffer->Next; + } + + if (Previous) { + Previous->Next = NULL; + Packet->Private.Tail = Previous; + } else { + Packet->Private.Head = NULL; + Packet->Private.Tail = NULL; + } + + Packet->Private.ValidCounts = FALSE; + + *Buffer = NdisBuffer; +} + + +VOID +EXPORT +NdisUnchainBufferAtFront( + IN OUT PNDIS_PACKET Packet, + OUT PNDIS_BUFFER *Buffer) +/* + * FUNCTION: + * Removes the first buffer in a packet + * ARGUMENTS: + * Packet = Pointer to NDIS packet + * Buffer = Address of buffer to place pointer to removed NDIS buffer + */ +{ + PNDIS_BUFFER NdisBuffer; + + NdisQueryPacket(Packet, + NULL, + NULL, + &NdisBuffer, + NULL); + if (!NdisBuffer) { + *Buffer = NULL; + return; + } + + Packet->Private.Head = NdisBuffer->Next; + + if (!NdisBuffer->Next) + Packet->Private.Tail = NULL; + + NdisBuffer->Next = NULL; + + Packet->Private.ValidCounts = FALSE; + + *Buffer = NdisBuffer; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/cl.c b/drivers/net/ndis/ndis/cl.c new file mode 100644 index 0000000..7a24f74 --- /dev/null +++ b/drivers/net/ndis/ndis/cl.c @@ -0,0 +1,202 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/cl.c + * PURPOSE: Services for connectionless NDIS drivers + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +NDIS_STATUS +EXPIMP +NdisClAddParty( + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE ProtocolPartyContext, + IN OUT PCO_CALL_PARAMETERS CallParameters, + OUT PNDIS_HANDLE NdisPartyHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClCloseAddressFamily( + IN NDIS_HANDLE NdisAfHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClCloseCall( + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN PVOID Buffer OPTIONAL, + IN UINT Size) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClDeregisterSap( + IN NDIS_HANDLE NdisSapHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClDropParty( + IN NDIS_HANDLE NdisPartyHandle, + IN PVOID Buffer OPTIONAL, + IN UINT Size) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPIMP +NdisClIncomingCallComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPIMP +NdisClMakeCall( + IN NDIS_HANDLE NdisVcHandle, + IN OUT PCO_CALL_PARAMETERS CallParameters, + IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, + OUT PNDIS_HANDLE NdisPartyHandle OPTIONAL) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClModifyCallQoS( + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClOpenAddressFamily( + IN NDIS_HANDLE NdisBindingHandle, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN NDIS_HANDLE ProtocolAfContext, + IN PNDIS_CLIENT_CHARACTERISTICS ClCharacteristics, + IN UINT SizeOfClCharacteristics, + OUT PNDIS_HANDLE NdisAfHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPIMP +NdisClRegisterSap( + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE ProtocolSapContext, + IN PCO_SAP Sap, + OUT PNDIS_HANDLE NdisSapHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/cm.c b/drivers/net/ndis/ndis/cm.c new file mode 100644 index 0000000..d6e0ca9 --- /dev/null +++ b/drivers/net/ndis/ndis/cm.c @@ -0,0 +1,418 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/cm.c + * PURPOSE: Call Manager services + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +NDIS_STATUS +EXPORT +NdisCmActivateVc( + IN NDIS_HANDLE NdisVcHandle, + IN OUT PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCmAddPartyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisPartyHandle, + IN NDIS_HANDLE CallMgrPartyContext OPTIONAL, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmCloseAddressFamilyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisAfHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmCloseCallComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisCmDeactivateVc( + IN NDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCmDeregisterSapComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisSapHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmDispatchCallConnected( + IN NDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisCmDispatchIncomingCall( + IN NDIS_HANDLE NdisSapHandle, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCmDispatchIncomingCallQoSChange( + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmDispatchIncomingCloseCall( + IN NDIS_STATUS CloseStatus, + IN NDIS_HANDLE NdisVcHandle, + IN PVOID Buffer OPTIONAL, + IN UINT Size) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmDispatchIncomingDropParty( + IN NDIS_STATUS DropStatus, + IN NDIS_HANDLE NdisPartyHandle, + IN PVOID Buffer OPTIONAL, + IN UINT Size) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmDropPartyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisPartyHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmMakeCallComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN NDIS_HANDLE CallMgrPartyContext OPTIONAL, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmModifyCallQoSComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCmOpenAddressFamilyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE CallMgrAfContext) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisCmRegisterAddressFamily( + IN NDIS_HANDLE NdisBindingHandle, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN PNDIS_CALL_MANAGER_CHARACTERISTICS CmCharacteristics, + IN UINT SizeOfCmCharacteristics) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCmRegisterSapComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisSapHandle, + IN NDIS_HANDLE CallMgrSapContext) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + + +NDIS_STATUS +EXPORT +NdisMCmActivateVc( + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMCmCreateVc( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE MiniportVcContext, + OUT PNDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMCmDeactivateVc( + IN NDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMCmDeleteVc( + IN NDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMCmRegisterAddressFamily( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN PNDIS_CALL_MANAGER_CHARACTERISTICS CmCharacteristics, + IN UINT SizeOfCmCharacteristics) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + +NDIS_STATUS +EXPORT +NdisMCmRequest( + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN OUT PNDIS_REQUEST NdisRequest) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/co.c b/drivers/net/ndis/ndis/co.c new file mode 100644 index 0000000..c560cc4 --- /dev/null +++ b/drivers/net/ndis/ndis/co.c @@ -0,0 +1,226 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/co.c + * PURPOSE: Services for connection-oriented NDIS drivers + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +NDIS_STATUS +EXPORT +NdisCoCreateVc( + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE NdisAfHandle OPTIONAL, + IN NDIS_HANDLE ProtocolVcContext, + IN OUT PNDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisCoDeleteVc( + IN NDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisCoRequest( + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE NdisAfHandle OPTIONAL, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN OUT PNDIS_REQUEST NdisRequest) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCoRequestComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN PNDIS_REQUEST NdisRequest) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCoSendPackets( + IN NDIS_HANDLE NdisVcHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + + +VOID +EXPORT +NdisMCoActivateVcComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMCoDeactivateVcComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMCoIndicateReceivePacket( + IN NDIS_HANDLE NdisVcHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMCoIndicateStatus( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer OPTIONAL, + IN ULONG StatusBufferSize) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMCoReceiveComplete( + IN NDIS_HANDLE MiniportAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMCoRequestComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_REQUEST Request) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMCoSendComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PNDIS_PACKET Packet) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +/* EOF */ diff --git a/drivers/net/ndis/ndis/control.c b/drivers/net/ndis/ndis/control.c new file mode 100644 index 0000000..3947bc5 --- /dev/null +++ b/drivers/net/ndis/ndis/control.c @@ -0,0 +1,197 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/control.c + * PURPOSE: Program control routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + +VOID +EXPORT +NdisReinitializePacket( + IN OUT PNDIS_PACKET Packet) +{ + (Packet)->Private.Head = (PNDIS_BUFFER)NULL; + (Packet)->Private.ValidCounts = FALSE; +} + +VOID +EXPORT +NdisAcquireReadWriteLock( + IN PNDIS_RW_LOCK Lock, + IN BOOLEAN fWrite, + IN PLOCK_STATE LockState) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisAcquireSpinLock( + IN PNDIS_SPIN_LOCK SpinLock) +/* + * FUNCTION: Acquires a spin lock for exclusive access to a resource + * ARGUMENTS: + * SpinLock = Pointer to the initialized NDIS spin lock to be acquired + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisAllocateSpinLock( + IN PNDIS_SPIN_LOCK SpinLock) +/* + * FUNCTION: Initializes for an NDIS spin lock + * ARGUMENTS: + * SpinLock = Pointer to an NDIS spin lock structure + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisDprAcquireSpinLock( + IN PNDIS_SPIN_LOCK SpinLock) +/* + * FUNCTION: Acquires a spin lock from IRQL DISPATCH_LEVEL + * ARGUMENTS: + * SpinLock = Pointer to the initialized NDIS spin lock to be acquired + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisDprReleaseSpinLock( + IN PNDIS_SPIN_LOCK SpinLock) +/* + * FUNCTION: Releases an acquired spin lock from IRQL DISPATCH_LEVEL + * ARGUMENTS: + * SpinLock = Pointer to the acquired NDIS spin lock to be released + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisFreeSpinLock( + IN PNDIS_SPIN_LOCK SpinLock) +/* + * FUNCTION: Releases a spin lock initialized with NdisAllocateSpinLock + * ARGUMENTS: + * SpinLock = Pointer to an initialized NDIS spin lock + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisGetCurrentProcessorCpuUsage( + PULONG pCpuUsage) +/* + * FUNCTION: Returns how busy the current processor is as a percentage + * ARGUMENTS: + * pCpuUsage = Pointer to a buffer to place CPU usage + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisInitializeEvent( + IN PNDIS_EVENT Event) +/* + * FUNCTION: Initializes an event to be used for synchronization + * ARGUMENTS: + * Event = Pointer to an NDIS event structure to be initialized + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisReleaseSpinLock( + IN PNDIS_SPIN_LOCK SpinLock) +/* + * FUNCTION: Releases a spin lock previously acquired with NdisAcquireSpinLock + * ARGUMENTS: + * SpinLock = Pointer to the acquired NDIS spin lock to be released + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisResetEvent( + IN PNDIS_EVENT Event) +/* + * FUNCTION: Clears the signaled state of an event + * ARGUMENTS: + * Event = Pointer to the initialized event object to be reset + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisSetEvent( + IN PNDIS_EVENT Event) +/* + * FUNCTION: Sets an event to a signaled state if not already signaled + * ARGUMENTS: + * Event = Pointer to the initialized event object to be set + */ +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +NdisWaitEvent( + IN PNDIS_EVENT Event, + IN UINT MsToWait) +/* + * FUNCTION: Waits for an event to become signaled + * ARGUMENTS: + * Event = Pointer to the initialized event object to wait for + * MsToWait = Maximum milliseconds to wait for the event to become signaled + * RETURNS: + * TRUE if the event is in the signaled state + */ +{ + UNIMPLEMENTED + + return FALSE; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/hardware.c b/drivers/net/ndis/ndis/hardware.c new file mode 100644 index 0000000..8fcbb80 --- /dev/null +++ b/drivers/net/ndis/ndis/hardware.c @@ -0,0 +1,134 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/hardware.c + * PURPOSE: Hardware related routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +ULONG +EXPORT +NdisImmediateReadPciSlotInformation( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SlotNumber, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length) +{ + UNIMPLEMENTED + + return 0; +} + + +ULONG +EXPORT +NdisImmediateWritePciSlotInformation( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SlotNumber, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length) +{ + UNIMPLEMENTED + + return 0; +} + + +NDIS_STATUS +EXPORT +NdisMPciAssignResources( + IN NDIS_HANDLE MiniportHandle, + IN ULONG SlotNumber, + OUT PNDIS_RESOURCE_LIST *AssignedResources) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMQueryAdapterResources( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + OUT PNDIS_RESOURCE_LIST ResourceList, + IN OUT PUINT BufferSize) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisQueryMapRegisterCount( + IN NDIS_INTERFACE_TYPE BusType, + OUT PUINT MapRegisterCount) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisReadEisaSlotInformation( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + OUT PUINT SlotNumber, + OUT PNDIS_EISA_FUNCTION_INFORMATION EisaData) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisReadEisaSlotInformationEx( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + OUT PUINT SlotNumber, + OUT PNDIS_EISA_FUNCTION_INFORMATION *EisaData, + OUT PUINT NumberOfFunctions) +{ + UNIMPLEMENTED +} + + +ULONG +EXPORT +NdisReadPciSlotInformation( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG SlotNumber, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length) +{ + UNIMPLEMENTED + + return 0; +} + + +ULONG +EXPORT +NdisWritePciSlotInformation( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG SlotNumber, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/io.c b/drivers/net/ndis/ndis/io.c new file mode 100644 index 0000000..8ba5b98 --- /dev/null +++ b/drivers/net/ndis/ndis/io.c @@ -0,0 +1,467 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/io.c + * PURPOSE: I/O related routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include + + +VOID STDCALL HandleDeferredProcessing( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +/* + * FUNCTION: Deferred interrupt processing routine + * ARGUMENTS: + * Dpc = Pointer to DPC object + * DeferredContext = Pointer to context information (LOGICAL_ADAPTER) + * SystemArgument1 = Unused + * SystemArgument2 = Unused + */ +{ + BOOLEAN WasBusy; + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock); + WasBusy = Adapter->MiniportBusy; + Adapter->MiniportBusy = TRUE; + KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock); + + /* Call the deferred interrupt service handler for this adapter */ + (*Adapter->Miniport->Chars.HandleInterruptHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext); + + KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock); + if ((!WasBusy) && (Adapter->WorkQueueHead)) { + KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL); + } else { + Adapter->MiniportBusy = WasBusy; + } + KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock); + + NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +BOOLEAN STDCALL ServiceRoutine( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext) +/* + * FUNCTION: Interrupt service routine + * ARGUMENTS: + * Interrupt = Pointer to interrupt object + * ServiceContext = Pointer to context information (LOGICAL_ADAPTER) + * RETURNS + * TRUE if a miniport controlled device generated the interrupt + */ +{ + BOOLEAN InterruptRecognized; + BOOLEAN QueueMiniportHandleInterrupt; + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(ServiceContext); + + NDIS_DbgPrint(MAX_TRACE, ("Called. Adapter (0x%X)\n", Adapter)); + + (*Adapter->Miniport->Chars.ISRHandler)(&InterruptRecognized, + &QueueMiniportHandleInterrupt, + Adapter->NdisMiniportBlock.MiniportAdapterContext); + + if (QueueMiniportHandleInterrupt) { + NDIS_DbgPrint(MAX_TRACE, ("Queueing DPC.\n")); + KeInsertQueueDpc(&Adapter->NdisMiniportBlock.Interrupt->InterruptDpc, NULL, NULL); + } + + NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return InterruptRecognized; +} + + +VOID +EXPORT +NdisCompleteDmaTransfer( + OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE NdisDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisFlushBuffer( + IN PNDIS_BUFFER Buffer, + IN BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED +} + + +ULONG +EXPORT +NdisGetCacheFillSize( + VOID) +{ + UNIMPLEMENTED + + return 0; +} + + +VOID +EXPORT +NdisImmediateReadPortUchar( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + OUT PUCHAR Data) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisImmediateReadPortUlong( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + OUT PULONG Data) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisImmediateReadPortUshort( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + OUT PUSHORT Data) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisImmediateWritePortUchar( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + IN UCHAR Data) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisImmediateWritePortUlong( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + IN ULONG Data) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisImmediateWritePortUshort( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + IN USHORT Data) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisMAllocateMapRegisters( + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT DmaChannel, + IN BOOLEAN Dma32BitAddresses, + IN ULONG PhysicalMapRegistersNeeded, + IN ULONG MaximumPhysicalMapping) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMCompleteDmaTransfer( + OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE MiniportDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMDeregisterDmaChannel( + IN PNDIS_HANDLE MiniportDmaHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMDeregisterInterrupt( + IN PNDIS_MINIPORT_INTERRUPT Interrupt) +/* + * FUNCTION: Releases an interrupt vector + * ARGUMENTS: + * Interrupt = Pointer to interrupt object + */ +{ + IoDisconnectInterrupt(Interrupt->InterruptObject); +} + + +VOID +EXPORT +NdisMDeregisterIoPortRange( + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InitialPort, + IN UINT NumberOfPorts, + IN PVOID PortOffset) +/* + * FUNCTION: Releases a register mapping to I/O ports + * ARGUMENTS: + * MiniportAdapterHandle = Specifies handle input to MiniportInitialize + * InitialPort = Bus-relative base port address of a range to be mapped + * NumberOfPorts = Specifies number of ports to be mapped + * PortOffset = Pointer to mapped base port address + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Thank you */ +} + + +VOID +EXPORT +NdisMFreeMapRegisters( + IN NDIS_HANDLE MiniportAdapterHandle) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisMMapIoSpace( + OUT PVOID *VirtualAddress, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT Length) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +ULONG +EXPORT +NdisMReadDmaCounter( + IN NDIS_HANDLE MiniportDmaHandle) +{ + UNIMPLEMENTED + + return 0; +} + + +NDIS_STATUS +EXPORT +NdisMRegisterDmaChannel( + OUT PNDIS_HANDLE MiniportDmaHandle, + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT DmaChannel, + IN BOOLEAN Dma32BitAddresses, + IN PNDIS_DMA_DESCRIPTION DmaDescription, + IN ULONG MaximumLength) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMRegisterInterrupt( + OUT PNDIS_MINIPORT_INTERRUPT Interrupt, + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InterruptVector, + IN UINT InterruptLevel, + IN BOOLEAN RequestIsr, + IN BOOLEAN SharedInterrupt, + IN NDIS_INTERRUPT_MODE InterruptMode) +/* + * FUNCTION: Claims access to an interrupt vector + * ARGUMENTS: + * Interrupt = Address of interrupt object to initialize + * MiniportAdapterHandle = Specifies handle input to MiniportInitialize + * InterruptVector = Specifies bus-relative vector to register + * InterruptLevel = Specifies bus-relative DIRQL vector for interrupt + * RequestIsr = TRUE if MiniportISR should always be called + * SharedInterrupt = TRUE if other devices may use the same interrupt + * InterruptMode = Specifies type of interrupt + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + ULONG MappedIRQ; + KIRQL DIrql; + KAFFINITY Affinity; + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called. InterruptVector (0x%X) InterruptLevel (0x%X) " + "SharedInterrupt (%d) InterruptMode (0x%X)\n", + InterruptVector, InterruptLevel, SharedInterrupt, InterruptMode)); + + RtlZeroMemory(Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT)); + + KeInitializeSpinLock(&Interrupt->DpcCountLock); + + KeInitializeDpc(&Interrupt->InterruptDpc, + HandleDeferredProcessing, + Adapter); + + KeInitializeEvent(&Interrupt->DpcsCompletedEvent, + NotificationEvent, + FALSE); + + Interrupt->SharedInterrupt = SharedInterrupt; + + Adapter->NdisMiniportBlock.Interrupt = Interrupt; + + MappedIRQ = HalGetInterruptVector(Internal, /* Adapter->AdapterType, */ + 0, + InterruptLevel, + InterruptVector, + &DIrql, + &Affinity); + + NDIS_DbgPrint(MAX_TRACE, ("Connecting to interrupt vector (0x%X) Affinity (0x%X).\n", MappedIRQ, Affinity)); + + Status = IoConnectInterrupt(&Interrupt->InterruptObject, + ServiceRoutine, + Adapter, + &Interrupt->DpcCountLock, + MappedIRQ, + DIrql, + DIrql, + InterruptMode, + SharedInterrupt, + Affinity, + FALSE); + + NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status)); + + if (NT_SUCCESS(Status)) + return NDIS_STATUS_SUCCESS; + + if (Status == STATUS_INSUFFICIENT_RESOURCES) { + /* FIXME: Log error */ + return NDIS_STATUS_RESOURCE_CONFLICT; + } + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMRegisterIoPortRange( + OUT PVOID *PortOffset, + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InitialPort, + IN UINT NumberOfPorts) +/* + * FUNCTION: Sets up driver access to device I/O ports + * ARGUMENTS: + * PortOffset = Address of buffer to place mapped base port address + * MiniportAdapterHandle = Specifies handle input to MiniportInitialize + * InitialPort = Bus-relative base port address of a range to be mapped + * NumberOfPorts = Specifies number of ports to be mapped + * RETURNS: + * Status of operation + */ +{ +#if 0 + NTSTATUS Status; + BOOLEAN ConflictDetected; + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle); + PMINIPORT_DRIVER Miniport = Adapter->Miniport; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Non-PnP hardware. NT5 function */ + Status = IoReportResourceForDetection(Miniport->DriverObject, + NULL, + 0, + NULL, + NULL, + 0, + &ConflictDetected); + return NDIS_STATUS_FAILURE; +#else + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* It's yours! */ + *PortOffset = (PVOID)InitialPort; + + return NDIS_STATUS_SUCCESS; +#endif +} + + +VOID +EXPORT +NdisMSetupDmaTransfer( + OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE MiniportDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMUnmapIoSpace( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PVOID VirtualAddress, + IN UINT Length) +{ + UNIMPLEMENTED +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/main.c b/drivers/net/ndis/ndis/main.c new file mode 100644 index 0000000..4188cf7 --- /dev/null +++ b/drivers/net/ndis/ndis/main.c @@ -0,0 +1,71 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/main.c + * PURPOSE: Driver entry point + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include + + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MIN_TRACE; + +#endif /* DBG */ + + +VOID MainUnload( + PDRIVER_OBJECT DriverObject) +/* + * FUNCTION: Unloads the driver + * ARGUMENTS: + * DriverObject = Pointer to driver object created by the system + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Main driver entry point + * ARGUMENTS: + * DriverObject = Pointer to a driver object for this driver + * RegistryPath = Registry node for configuration parameters + * RETURNS: + * Status of driver initialization + */ +{ + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + InitializeListHead(&ProtocolListHead); + KeInitializeSpinLock(&ProtocolListLock); + + InitializeListHead(&MiniportListHead); + KeInitializeSpinLock(&MiniportListLock); + + InitializeListHead(&AdapterListHead); + KeInitializeSpinLock(&AdapterListLock); + +#ifdef _MSC_VER + DriverObject->DriverUnload = MainUnload; +#else + DriverObject->DriverUnload = (PDRIVER_UNLOAD)MainUnload; +#endif + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/memory.c b/drivers/net/ndis/ndis/memory.c new file mode 100644 index 0000000..f4facd2 --- /dev/null +++ b/drivers/net/ndis/ndis/memory.c @@ -0,0 +1,229 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/memory.c + * PURPOSE: Memory management routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +NDIS_STATUS +EXPORT +NdisAllocateMemoryWithTag( + OUT PVOID *VirtualAddress, + IN UINT Length, + IN ULONG Tag) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisCreateLookaheadBufferFromSharedMemory( + IN PVOID pSharedMemory, + IN UINT LookaheadLength, + OUT PVOID *pLookaheadBuffer) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisDestroyLookaheadBufferFromSharedMemory( + IN PVOID pLookaheadBuffer) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMoveFromMappedMemory( + OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMoveMappedMemory( + OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length) +{ + RtlCopyMemory(Destination,Source,Length); +} + + +VOID +EXPORT +NdisMoveToMappedMemory( + OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMUpdateSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisAllocateMemory( + OUT PVOID *VirtualAddress, + IN UINT Length, + IN UINT MemoryFlags, + IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress) +/* + * FUNCTION: Allocates a block of memory + * ARGUMENTS: + * VirtualAddress = Address of buffer to place virtual + * address of the allocated memory + * Length = Size of the memory block to allocate + * MemoryFlags = Flags to specify special restrictions + * HighestAcceptableAddress = Specifies -1 + */ +{ + PVOID Block; + + if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS) { + /* FIXME */ + *VirtualAddress = NULL; + return NDIS_STATUS_FAILURE; + } + + if (MemoryFlags & NDIS_MEMORY_NONCACHED) { + /* FIXME */ + *VirtualAddress = NULL; + return NDIS_STATUS_FAILURE; + } + + /* Plain nonpaged memory */ + Block = ExAllocatePool(NonPagedPool, Length); + *VirtualAddress = Block; + if (!Block) + return NDIS_STATUS_FAILURE; + + return NDIS_STATUS_SUCCESS; +} + + +VOID +EXPORT +NdisFreeMemory( + IN PVOID VirtualAddress, + IN UINT Length, + IN UINT MemoryFlags) +/* + * FUNCTION: Frees a memory block allocated with NdisAllocateMemory + * ARGUMENTS: + * VirtualAddress = Pointer to the base virtual address of the allocated memory + * Length = Size of the allocated memory block as passed to NdisAllocateMemory + * MemoryFlags = Memory flags passed to NdisAllocateMemory + */ +{ + if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS) { + /* FIXME */ + return; + } + + if (MemoryFlags & NDIS_MEMORY_NONCACHED) { + /* FIXME */ + return; + } + + /* Plain nonpaged memory */ + ExFreePool(VirtualAddress); +} + + +VOID +EXPORT +NdisImmediateReadSharedMemory( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SharedMemoryAddress, + OUT PUCHAR Buffer, + IN ULONG Length) +{ +} + + +VOID +EXPORT +NdisImmediateWriteSharedMemory( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SharedMemoryAddress, + IN PUCHAR Buffer, + IN ULONG Length) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMAllocateSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisMAllocateSharedMemoryAsync( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID Context) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMFreeSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress) +{ + UNIMPLEMENTED +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/miniport.c b/drivers/net/ndis/ndis/miniport.c new file mode 100644 index 0000000..cd1d3e7 --- /dev/null +++ b/drivers/net/ndis/ndis/miniport.c @@ -0,0 +1,1336 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/miniport.c + * PURPOSE: Routines used by NDIS miniport drivers + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#define DBG +#include +#include +#ifdef DBG +#include +#endif /* DBG */ + +#ifdef DBG +/* See debug.h for debug/trace constants */ +ULONG DebugTraceLevel = MIN_TRACE; +//ULONG DebugTraceLevel = (MAX_TRACE + DEBUG_MINIPORT); +#endif /* DBG */ + + +/* Number of media we know */ +#define MEDIA_ARRAY_SIZE 15 + +static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] = { + NdisMedium802_3, + NdisMedium802_5, + NdisMediumFddi, + NdisMediumWan, + NdisMediumLocalTalk, + NdisMediumDix, + NdisMediumArcnetRaw, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMediumWirelessWan, + NdisMediumIrda, + NdisMediumBpc, + NdisMediumCoWan, + NdisMedium1394, + NdisMediumMax +}; + + +LIST_ENTRY MiniportListHead; +KSPIN_LOCK MiniportListLock; +LIST_ENTRY AdapterListHead; +KSPIN_LOCK AdapterListLock; + + +#ifdef DBG +VOID +MiniDisplayPacket( + PNDIS_PACKET Packet) +{ + ULONG i, Length; + UCHAR Buffer[64]; +#if 0 + if ((DebugTraceLevel | DEBUG_PACKET) > 0) { + Length = CopyPacketToBuffer( + (PUCHAR)&Buffer, + Packet, + 0, + 64); + + DbgPrint("*** PACKET START ***"); + + for (i = 0; i < Length; i++) { + if (i % 12 == 0) + DbgPrint("\n%04X ", i); + DbgPrint("%02X ", Buffer[i]); + } + + DbgPrint("*** PACKET STOP ***\n"); + } +#endif +} +#endif /* DBG */ + + +VOID +MiniIndicateData( + PLOGICAL_ADAPTER Adapter, + NDIS_HANDLE MacReceiveContext, + PVOID HeaderBuffer, + UINT HeaderBufferSize, + PVOID LookaheadBuffer, + UINT LookaheadBufferSize, + UINT PacketSize) +/* + * FUNCTION: Indicate received data to bound protocols + * ARGUMENTS: + * Adapter = Pointer to logical adapter + * MacReceiveContext = MAC receive context handle + * HeaderBuffer = Pointer to header buffer + * HeaderBufferSize = Size of header buffer + * LookaheadBuffer = Pointer to lookahead buffer + * LookaheadBufferSize = Size of lookahead buffer + * PacketSize = Total size of received packet + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PADAPTER_BINDING AdapterBinding; + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. Adapter (0x%X) HeaderBuffer (0x%X) " + "HeaderBufferSize (0x%X) LookaheadBuffer (0x%X) LookaheadBufferSize (0x%X).\n", + Adapter, HeaderBuffer, HeaderBufferSize, LookaheadBuffer, LookaheadBufferSize)); + +#ifdef DBG +#if 0 + if ((DebugTraceLevel | DEBUG_PACKET) > 0) { + ULONG i, Length; + PUCHAR p; + + DbgPrint("*** RECEIVE PACKET START ***\n"); + DbgPrint("HEADER:"); + p = HeaderBuffer; + for (i = 0; i < HeaderBufferSize; i++) { + if (i % 16 == 0) + DbgPrint("\n%04X ", i); + DbgPrint("%02X ", *p); + (ULONG_PTR)p += 1; + } + + DbgPrint("\nFRAME:"); + + p = LookaheadBuffer; + Length = (LookaheadBufferSize < 64)? LookaheadBufferSize : 64; + for (i = 0; i < Length; i++) { + if (i % 16 == 0) + DbgPrint("\n%04X ", i); + DbgPrint("%02X ", *p); + (ULONG_PTR)p += 1; + } + + DbgPrint("\n*** RECEIVE PACKET STOP ***\n"); + } +#endif +#endif /* DBG */ + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + CurrentEntry = Adapter->ProtocolListHead.Flink; + + if (CurrentEntry == &Adapter->ProtocolListHead) { + NDIS_DbgPrint(DEBUG_MINIPORT, ("WARNING: No upper protocol layer.\n")); + } + + while (CurrentEntry != &Adapter->ProtocolListHead) { + AdapterBinding = CONTAINING_RECORD(CurrentEntry, + ADAPTER_BINDING, + AdapterListEntry); + + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)( + AdapterBinding->NdisOpenBlock.ProtocolBindingContext, + MacReceiveContext, + HeaderBuffer, + HeaderBufferSize, + LookaheadBuffer, + LookaheadBufferSize, + PacketSize); + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); +} + + +VOID +MiniEthReceiveComplete( + IN PETH_FILTER Filter) +/* + * FUNCTION: Receive indication complete function for Ethernet devices + * ARGUMENTS: + * Filter = Pointer to Ethernet filter + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLOGICAL_ADAPTER Adapter; + PADAPTER_BINDING AdapterBinding; + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); + + Adapter = (PLOGICAL_ADAPTER)Filter->Miniport; + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + CurrentEntry = Adapter->ProtocolListHead.Flink; + while (CurrentEntry != &Adapter->ProtocolListHead) { + AdapterBinding = CONTAINING_RECORD(CurrentEntry, + ADAPTER_BINDING, + AdapterListEntry); + + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + (*AdapterBinding->ProtocolBinding->Chars.ReceiveCompleteHandler)( + AdapterBinding->NdisOpenBlock.ProtocolBindingContext); + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); +} + + +VOID +MiniEthReceiveIndication( + IN PETH_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize) +/* + * FUNCTION: Receive indication function for Ethernet devices + * ARGUMENTS: + * Filter = Pointer to Ethernet filter + * MacReceiveContext = MAC receive context handle + * Address = Pointer to destination Ethernet address + * HeaderBuffer = Pointer to Ethernet header buffer + * HeaderBufferSize = Size of Ethernet header buffer + * LookaheadBuffer = Pointer to lookahead buffer + * LookaheadBufferSize = Size of lookahead buffer + * PacketSize = Total size of received packet + */ +{ + MiniIndicateData((PLOGICAL_ADAPTER)Filter->Miniport, + MacReceiveContext, + HeaderBuffer, + HeaderBufferSize, + LookaheadBuffer, + LookaheadBufferSize, + PacketSize); +} + + +VOID +MiniResetComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status, + IN BOOLEAN AddressingReset) +{ + UNIMPLEMENTED +} + + +VOID +MiniSendComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status) +/* + * FUNCTION: Forwards a message to the initiating protocol saying + * that a packet was handled + * ARGUMENTS: + * NdisAdapterHandle = Handle input to MiniportInitialize + * Packet = Pointer to NDIS packet that was sent + * Status = Status of send operation + */ +{ + PADAPTER_BINDING AdapterBinding; + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); + + AdapterBinding = (PADAPTER_BINDING)Packet->Reserved[0]; + + (*AdapterBinding->ProtocolBinding->Chars.u2.SendCompleteHandler)( + AdapterBinding->NdisOpenBlock.ProtocolBindingContext, + Packet, + Status); +} + + +VOID +MiniSendResourcesAvailable( + IN NDIS_HANDLE MiniportAdapterHandle) +{ + UNIMPLEMENTED +} + + +VOID +MiniTransferDataComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred) +{ + PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle; + PADAPTER_BINDING AdapterBinding = Adapter->MiniportAdapterBinding; + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); + + (*AdapterBinding->ProtocolBinding->Chars.u3.TransferDataCompleteHandler)( + AdapterBinding->NdisOpenBlock.ProtocolBindingContext, + Packet, + Status, + BytesTransferred); +} + + +BOOLEAN +MiniAdapterHasAddress( + PLOGICAL_ADAPTER Adapter, + PNDIS_PACKET Packet) +/* + * FUNCTION: Determines wether a packet has the same destination address as an adapter + * ARGUMENTS: + * Adapter = Pointer to logical adapter object + * Packet = Pointer to NDIS packet + * RETURNS: + * TRUE if the destination address is that of the adapter, FALSE if not + */ +{ + UINT Length; + PUCHAR Start1; + PUCHAR Start2; + PNDIS_BUFFER NdisBuffer; + UINT BufferLength; + + Start1 = (PUCHAR)&Adapter->Address; + NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL); + if (!NdisBuffer) { + NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n")); + return FALSE; + } + + NdisQueryBuffer(NdisBuffer, (PVOID)&Start2, &BufferLength); + + /* FIXME: Should handle fragmented packets */ + + switch (Adapter->NdisMiniportBlock.MediaType) { + case NdisMedium802_3: + Length = ETH_LENGTH_OF_ADDRESS; + /* Destination address is the first field */ + break; + + default: + NDIS_DbgPrint(MIN_TRACE, ("Adapter has unsupported media type (0x%X).\n", + Adapter->NdisMiniportBlock.MediaType)); + return FALSE; + } + + if (BufferLength < Length) { + NDIS_DbgPrint(MID_TRACE, ("Buffer is too small.\n")); + return FALSE; + } + + return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length); +} + + +PLOGICAL_ADAPTER +MiniLocateDevice( + PNDIS_STRING AdapterName) +/* + * FUNCTION: Returns the logical adapter object for a specific adapter + * ARGUMENTS: + * AdapterName = Pointer to name of adapter + * RETURNS: + * Pointer to logical adapter object, or NULL if none was found. + * If found, the adapter is referenced for the caller. The caller + * is responsible for dereferencing after use + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLOGICAL_ADAPTER Adapter; + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); + + KeAcquireSpinLock(&AdapterListLock, &OldIrql); + CurrentEntry = AdapterListHead.Flink; + while (CurrentEntry != &AdapterListHead) { + Adapter = CONTAINING_RECORD(CurrentEntry, LOGICAL_ADAPTER, ListEntry); + + if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0) { + ReferenceObject(Adapter); + KeReleaseSpinLock(&AdapterListLock, OldIrql); + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving. Adapter found at (0x%X).\n", Adapter)); + + return Adapter; + } + + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&AdapterListLock, OldIrql); + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Leaving (adapter not found).\n")); + + return NULL; +} + + +NDIS_STATUS +MiniQueryInformation( + PLOGICAL_ADAPTER Adapter, + NDIS_OID Oid, + ULONG Size, + PULONG BytesWritten) +/* + * FUNCTION: Queries a logical adapter for properties + * ARGUMENTS: + * Adapter = Pointer to the logical adapter object to query + * Oid = Specifies the Object ID to query for + * Size = If non-zero overrides the length in the adapter object + * BytesWritten = Address of buffer to place number of bytes written + * NOTES: + * If the specified buffer is too small, a new buffer is allocated, + * and the query is attempted again + * RETURNS: + * Status of operation + */ +{ + NDIS_STATUS NdisStatus; + ULONG BytesNeeded; + + if (Adapter->QueryBufferLength == 0) { + Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, (Size == 0)? 32 : Size); + + if (!Adapter->QueryBuffer) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NDIS_STATUS_RESOURCES; + } + + Adapter->QueryBufferLength = (Size == 0)? 32 : Size; + } + + BytesNeeded = (Size == 0)? Adapter->QueryBufferLength : Size; + + NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext, + Oid, + Adapter->QueryBuffer, + BytesNeeded, + BytesWritten, + &BytesNeeded); + + if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING)) { + NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus)); + return NdisStatus; + } + + if (NdisStatus == NDIS_STATUS_INVALID_LENGTH) { + ExFreePool(Adapter->QueryBuffer); + + Adapter->QueryBufferLength += BytesNeeded; + Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, + Adapter->QueryBufferLength); + + if (!Adapter->QueryBuffer) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NDIS_STATUS_RESOURCES; + } + + NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext, + Oid, + Adapter->QueryBuffer, + Size, + BytesWritten, + &BytesNeeded); + } + + return NdisStatus; +} + + +NDIS_STATUS +FASTCALL +MiniQueueWorkItem( + PLOGICAL_ADAPTER Adapter, + NDIS_WORK_ITEM_TYPE WorkItemType, + PVOID WorkItemContext, + NDIS_HANDLE Initiator) +/* + * FUNCTION: Queues a work item for execution at a later time + * ARGUMENTS: + * Adapter = Pointer to the logical adapter object to queue work item on + * WorkItemType = Type of work item to queue + * WorkItemContext = Pointer to context information for work item + * Initiator = Pointer to ADAPTER_BINDING structure of initiating protocol + * NOTES: + * Adapter lock must be held when called + * RETURNS: + * Status of operation + */ +{ + PNDIS_MINIPORT_WORK_ITEM Item; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1) { + Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel]; + Adapter->WorkQueueLevel++; + } else { + Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM)); + if (Item) { + /* Set flag so we know that the buffer should be freed + when work item is dequeued */ + Item->Allocated = TRUE; + } else { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NDIS_STATUS_RESOURCES; + } + } + + Item->WorkItemType = WorkItemType; + Item->WorkItemContext = WorkItemContext; + Item->Initiator = Initiator; + + Item->Link.Next = NULL; + if (!Adapter->WorkQueueHead) { + Adapter->WorkQueueHead = Item; + } else { + Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item; + } + + KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +FASTCALL +MiniDequeueWorkItem( + PLOGICAL_ADAPTER Adapter, + NDIS_WORK_ITEM_TYPE *WorkItemType, + PVOID *WorkItemContext, + NDIS_HANDLE *Initiator) +/* + * FUNCTION: Dequeues a work item from the work queue of a logical adapter + * ARGUMENTS: + * Adapter = Pointer to the logical adapter object to dequeue work item from + * WorkItemType = Address of buffer for work item type + * WorkItemContext = Address of buffer for pointer to context information + * Initiator = Address of buffer for initiator of the work (ADAPTER_BINDING) + * NOTES: + * Adapter lock must be held when called + * RETURNS: + * Status of operation + */ +{ + PNDIS_MINIPORT_WORK_ITEM Item; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + Item = Adapter->WorkQueueHead; + if (Item) { + Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next; + if (Item == Adapter->WorkQueueTail) + Adapter->WorkQueueTail = NULL; + + *WorkItemType = Item->WorkItemType; + *WorkItemContext = Item->WorkItemContext; + *Initiator = Item->Initiator; + + if (Item->Allocated) { + ExFreePool(Item); + } else { + Adapter->WorkQueueLevel--; +#ifdef DBG + if (Adapter->WorkQueueLevel < 0) { + NDIS_DbgPrint(MIN_TRACE, ("Adapter->WorkQueueLevel is < 0 (should be >= 0).\n")); + } +#endif + } + + return NDIS_STATUS_SUCCESS; + } + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +MiniDoRequest( + PLOGICAL_ADAPTER Adapter, + PNDIS_REQUEST NdisRequest) +/* + * FUNCTION: Sends a request to a miniport + * ARGUMENTS: + * Adapter = Pointer to logical adapter object + * NdisRequest = Pointer to NDIS request structure describing request + * RETURNS: + * Status of operation + */ +{ + Adapter->NdisMiniportBlock.MediaRequest = NdisRequest; + + switch (NdisRequest->RequestType) { + case NdisRequestQueryInformation: + return (*Adapter->Miniport->Chars.QueryInformationHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext, + NdisRequest->DATA.QUERY_INFORMATION.Oid, + NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, + NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength, + (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten, + (PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded); + break; + + case NdisRequestSetInformation: + return (*Adapter->Miniport->Chars.SetInformationHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext, + NdisRequest->DATA.SET_INFORMATION.Oid, + NdisRequest->DATA.SET_INFORMATION.InformationBuffer, + NdisRequest->DATA.SET_INFORMATION.InformationBufferLength, + (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead, + (PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded); + break; + + default: + return NDIS_STATUS_FAILURE; + } +} + + +VOID STDCALL MiniportDpc( + IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +/* + * FUNCTION: Deferred routine to handle serialization + * ARGUMENTS: + * Dpc = Pointer to DPC object + * DeferredContext = Pointer to context information (LOGICAL_ADAPTER) + * SystemArgument1 = Unused + * SystemArgument2 = Unused + */ +{ + NDIS_STATUS NdisStatus; + PVOID WorkItemContext; + NDIS_WORK_ITEM_TYPE WorkItemType; + PADAPTER_BINDING AdapterBinding; + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext); + + NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n")); + + NdisStatus = MiniDequeueWorkItem(Adapter, + &WorkItemType, + &WorkItemContext, + (PNDIS_HANDLE)&AdapterBinding); + if (NdisStatus == NDIS_STATUS_SUCCESS) { + Adapter->MiniportAdapterBinding = AdapterBinding; + switch (WorkItemType) { + case NdisWorkItemSend: +#ifdef DBG + MiniDisplayPacket((PNDIS_PACKET)WorkItemContext); +#endif + NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext, + (PNDIS_PACKET)WorkItemContext, + 0); + if (NdisStatus != NDIS_STATUS_PENDING) { + MiniSendComplete((NDIS_HANDLE)Adapter, + (PNDIS_PACKET)WorkItemContext, + NdisStatus); + } + break; + + case NdisWorkItemSendLoopback: + NdisStatus = ProIndicatePacket(Adapter, + (PNDIS_PACKET)WorkItemContext); + MiniSendComplete((NDIS_HANDLE)Adapter, + (PNDIS_PACKET)WorkItemContext, + NdisStatus); + break; + + case NdisWorkItemReturnPackets: + break; + + case NdisWorkItemResetRequested: + break; + + case NdisWorkItemResetInProgress: + break; + + case NdisWorkItemHalt: + break; + + case NdisWorkItemMiniportCallback: + break; + + case NdisWorkItemRequest: + NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext); + + if (NdisStatus == NDIS_STATUS_PENDING) + break; + + switch (((PNDIS_REQUEST)WorkItemContext)->RequestType) { + case NdisRequestQueryInformation: + NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus); + break; + + case NdisRequestSetInformation: + NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus); + break; + + default: + NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS request type.\n")); + break; + } + break; + + default: + NDIS_DbgPrint(MIN_TRACE, ("Unknown NDIS work item type (%d).\n", WorkItemType)); + break; + } + } +} + + +VOID +EXPORT +NdisMCloseLog( + IN NDIS_HANDLE LogHandle) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisMCreateLog( + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT Size, + OUT PNDIS_HANDLE LogHandle) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMDeregisterAdapterShutdownHandler( + IN NDIS_HANDLE MiniportHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMFlushLog( + IN NDIS_HANDLE LogHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMIndicateStatus( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMIndicateStatusComplete( + IN NDIS_HANDLE MiniportAdapterHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisInitializeWrapper( + OUT PNDIS_HANDLE NdisWrapperHandle, + IN PVOID SystemSpecific1, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +/* + * FUNCTION: Notifies the NDIS library that a new miniport is initializing + * ARGUMENTS: + * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle + * SystemSpecific1 = Pointer to the driver's driver object + * SystemSpecific2 = Pointer to the driver's registry path + * SystemSpecific3 = Always NULL + */ +{ + PMINIPORT_DRIVER Miniport; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER)); + if (!Miniport) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + *NdisWrapperHandle = NULL; + return; + } + + RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER)); + + KeInitializeSpinLock(&Miniport->Lock); + + Miniport->RefCount = 1; + + Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1; + + InitializeListHead(&Miniport->AdapterListHead); + + /* Put miniport in global miniport list */ + ExInterlockedInsertTailList(&MiniportListHead, + &Miniport->ListEntry, + &MiniportListLock); + + *NdisWrapperHandle = Miniport; +} + + +VOID +EXPORT +NdisMQueryInformationComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status) +{ + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle); + PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)( + AdapterBinding->NdisOpenBlock.ProtocolBindingContext, + Adapter->NdisMiniportBlock.MediaRequest, + Status); +} + + +VOID +EXPORT +NdisMRegisterAdapterShutdownHandler( + IN NDIS_HANDLE MiniportHandle, + IN PVOID ShutdownContext, + IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +DoQueries( + PLOGICAL_ADAPTER Adapter, + NDIS_OID AddressOID) +/* + * FUNCTION: Queries miniport for information + * ARGUMENTS: + * Adapter = Pointer to logical adapter + * AddressOID = OID to use to query for current address + * RETURNS: + * Status of operation + */ +{ + ULONG BytesWritten; + NDIS_STATUS NdisStatus; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Get MAC options for adapter */ + NdisStatus = MiniQueryInformation(Adapter, + OID_GEN_MAC_OPTIONS, + 0, + &BytesWritten); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAC_OPTIONS failed. NdisStatus (0x%X).\n", NdisStatus)); + return NdisStatus; + } + + RtlCopyMemory(&Adapter->NdisMiniportBlock.MacOptions, Adapter->QueryBuffer, sizeof(UINT)); + + NDIS_DbgPrint(DEBUG_MINIPORT, ("MacOptions (0x%X).\n", Adapter->NdisMiniportBlock.MacOptions)); + + /* Get current hardware address of adapter */ + NdisStatus = MiniQueryInformation(Adapter, + AddressOID, + 0, + &BytesWritten); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("Address OID (0x%X) failed. NdisStatus (0x%X).\n", + AddressOID, NdisStatus)); + return NdisStatus; + } + + RtlCopyMemory(&Adapter->Address, Adapter->QueryBuffer, Adapter->AddressLength); +#ifdef DBG + { + /* 802.3 only */ + + PUCHAR A = (PUCHAR)&Adapter->Address.Type.Medium802_3; + + NDIS_DbgPrint(MAX_TRACE, ("Adapter address is (%02X %02X %02X %02X %02X %02X).\n", + A[0], A[1], A[2], A[3], A[4], A[5])); + } +#endif /* DBG */ + + /* Get maximum lookahead buffer size of adapter */ + NdisStatus = MiniQueryInformation(Adapter, + OID_GEN_MAXIMUM_LOOKAHEAD, + 0, + &BytesWritten); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_MAXIMUM_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus)); + return NdisStatus; + } + + Adapter->MaxLookaheadLength = *((PULONG)Adapter->QueryBuffer); + + NDIS_DbgPrint(DEBUG_MINIPORT, ("MaxLookaheadLength (0x%X).\n", Adapter->MaxLookaheadLength)); + + /* Get current lookahead buffer size of adapter */ + NdisStatus = MiniQueryInformation(Adapter, + OID_GEN_CURRENT_LOOKAHEAD, + 0, + &BytesWritten); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NDIS_DbgPrint(MIN_TRACE, ("OID_GEN_CURRENT_LOOKAHEAD failed. NdisStatus (0x%X).\n", NdisStatus)); + return NdisStatus; + } + + Adapter->CurLookaheadLength = *((PULONG)Adapter->QueryBuffer); + + NDIS_DbgPrint(DEBUG_MINIPORT, ("CurLookaheadLength (0x%X).\n", Adapter->CurLookaheadLength)); + + if (Adapter->MaxLookaheadLength != 0) { + Adapter->LookaheadLength = Adapter->MaxLookaheadLength + + Adapter->MediumHeaderSize; + Adapter->LookaheadBuffer = ExAllocatePool(NonPagedPool, + Adapter->LookaheadLength); + if (!Adapter->LookaheadBuffer) + return NDIS_STATUS_RESOURCES; + } + + return STATUS_SUCCESS; +} + + +NDIS_STATUS +EXPORT +NdisMRegisterMiniport( + IN NDIS_HANDLE NdisWrapperHandle, + IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics, + IN UINT CharacteristicsLength) +/* + * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library + * ARGUMENTS: + * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper + * MiniportCharacteristics = Pointer to a buffer with miniport characteristics + * CharacteristicsLength = Number of bytes in characteristics buffer + * RETURNS: + * Status of operation + */ +{ + UINT MinSize; + KIRQL OldIrql; + NTSTATUS Status; + NDIS_STATUS NdisStatus; + NDIS_STATUS OpenErrorStatus; + UINT SelectedMediumIndex; + PLOGICAL_ADAPTER Adapter; + NDIS_OID AddressOID; + BOOLEAN MemError = FALSE; + PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (MiniportCharacteristics->MajorNdisVersion) { + case 0x03: + MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S); + break; + + case 0x04: + MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S); + break; + + case 0x05: + MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S); + break; + + default: + NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n")); + return NDIS_STATUS_BAD_VERSION; + } + + if (CharacteristicsLength < MinSize) { + NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n")); + return NDIS_STATUS_BAD_CHARACTERISTICS; + } + + /* Check if mandatory MiniportXxx functions are specified */ + if ((!MiniportCharacteristics->HaltHandler) || + (!MiniportCharacteristics->InitializeHandler)|| + (!MiniportCharacteristics->QueryInformationHandler) || + (!MiniportCharacteristics->ResetHandler) || + (!MiniportCharacteristics->SetInformationHandler)) { + NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n")); + return NDIS_STATUS_BAD_CHARACTERISTICS; + } + + if (MiniportCharacteristics->MajorNdisVersion == 0x03) { + if (!MiniportCharacteristics->u1.SendHandler) { + NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n")); + return NDIS_STATUS_BAD_CHARACTERISTICS; + } + } else if (MiniportCharacteristics->MajorNdisVersion >= 0x04) { + /* NDIS 4.0+ */ + if ((!MiniportCharacteristics->u1.SendHandler) && + (!MiniportCharacteristics->SendPacketsHandler)) { + NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n")); + return NDIS_STATUS_BAD_CHARACTERISTICS; + } + } + + RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize); + + Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER)); + if (!Adapter) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NDIS_STATUS_RESOURCES; + } + + /* This is very important */ + RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER)); + + /* Create the device object for this adapter */ + /* FIXME: Use GUIDs */ + RtlInitUnicodeStringFromLiteral(&Adapter->DeviceName, L"\\Device\\ne2000"); + Status = IoCreateDevice(Miniport->DriverObject, + 0, + &Adapter->DeviceName, + FILE_DEVICE_PHYSICAL_NETCARD, + 0, + FALSE, + &Adapter->NdisMiniportBlock.DeviceObject); + if (!NT_SUCCESS(Status)) { + NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n")); + ExFreePool(Adapter); + return NDIS_STATUS_FAILURE; + } + + /* Initialize adapter object */ + + KeInitializeSpinLock(&Adapter->NdisMiniportBlock.Lock); + + InitializeListHead(&Adapter->ProtocolListHead); + + Adapter->RefCount = 1; + + Adapter->Miniport = Miniport; + + /* Set handlers (some NDIS macros require these) */ + + Adapter->NdisMiniportBlock.EthRxCompleteHandler = MiniEthReceiveComplete; + Adapter->NdisMiniportBlock.EthRxIndicateHandler = MiniEthReceiveIndication; + + Adapter->NdisMiniportBlock.SendCompleteHandler = MiniSendComplete; + Adapter->NdisMiniportBlock.SendResourcesHandler = MiniSendResourcesAvailable; + Adapter->NdisMiniportBlock.ResetCompleteHandler = MiniResetComplete; + Adapter->NdisMiniportBlock.TDCompleteHandler = MiniTransferDataComplete; + + + KeInitializeDpc(&Adapter->MiniportDpc, MiniportDpc, (PVOID)Adapter); + + /* Put adapter in adapter list for this miniport */ + ExInterlockedInsertTailList(&Miniport->AdapterListHead, + &Adapter->MiniportListEntry, + &Miniport->Lock); + + /* Put adapter in global adapter list */ + ExInterlockedInsertTailList(&AdapterListHead, + &Adapter->ListEntry, + &AdapterListLock); + + /* Call MiniportInitialize */ + NdisStatus = (*Miniport->Chars.InitializeHandler)( + &OpenErrorStatus, + &SelectedMediumIndex, + &MediaArray[0], + MEDIA_ARRAY_SIZE, + Adapter, + NULL /* FIXME: WrapperConfigurationContext */); + + if ((NdisStatus == NDIS_STATUS_SUCCESS) && + (SelectedMediumIndex < MEDIA_ARRAY_SIZE)) { + + Adapter->NdisMiniportBlock.MediaType = MediaArray[SelectedMediumIndex]; + + switch (Adapter->NdisMiniportBlock.MediaType) { + case NdisMedium802_3: + Adapter->MediumHeaderSize = 14; + AddressOID = OID_802_3_CURRENT_ADDRESS; + Adapter->AddressLength = ETH_LENGTH_OF_ADDRESS; + + Adapter->NdisMiniportBlock.FilterDbs.u.EthDB = ExAllocatePool(NonPagedPool, + sizeof(ETH_FILTER)); + if (Adapter->NdisMiniportBlock.FilterDbs.u.EthDB) { + RtlZeroMemory(Adapter->NdisMiniportBlock.FilterDbs.u.EthDB, sizeof(ETH_FILTER)); + Adapter->NdisMiniportBlock.FilterDbs.u.EthDB->Miniport = (PNDIS_MINIPORT_BLOCK)Adapter; + } else + MemError = TRUE; + break; + + default: + /* FIXME: Support other types of medias */ + ASSERT(FALSE); + return NDIS_STATUS_FAILURE; + } + + NdisStatus = DoQueries(Adapter, AddressOID); + } + + if ((MemError) || + (NdisStatus != NDIS_STATUS_SUCCESS) || + (SelectedMediumIndex >= MEDIA_ARRAY_SIZE)) { + + /* Remove adapter from adapter list for this miniport */ + KeAcquireSpinLock(&Miniport->Lock, &OldIrql); + RemoveEntryList(&Adapter->MiniportListEntry); + KeReleaseSpinLock(&Miniport->Lock, OldIrql); + + /* Remove adapter from global adapter list */ + KeAcquireSpinLock(&AdapterListLock, &OldIrql); + RemoveEntryList(&Adapter->ListEntry); + KeReleaseSpinLock(&AdapterListLock, OldIrql); + + if (Adapter->LookaheadBuffer) + ExFreePool(Adapter->LookaheadBuffer); + + IoDeleteDevice(Adapter->NdisMiniportBlock.DeviceObject); + ExFreePool(Adapter); + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + + +VOID +EXPORT +NdisMResetComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status, + IN BOOLEAN AddressingReset) +{ + MiniResetComplete(MiniportAdapterHandle, + Status, + AddressingReset); +} + + +VOID +EXPORT +NdisMSendComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status) +/* + * FUNCTION: Forwards a message to the initiating protocol saying + * that a packet was handled + * ARGUMENTS: + * NdisAdapterHandle = Handle input to MiniportInitialize + * Packet = Pointer to NDIS packet that was sent + * Status = Status of send operation + */ +{ + MiniSendComplete(MiniportAdapterHandle, + Packet, + Status); +} + + +VOID +EXPORT +NdisMSendResourcesAvailable( + IN NDIS_HANDLE MiniportAdapterHandle) +{ + MiniSendResourcesAvailable(MiniportAdapterHandle); +} + + +VOID +EXPORT +NdisMTransferDataComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred) +{ + MiniTransferDataComplete(MiniportAdapterHandle, + Packet, + Status, + BytesTransferred); +} + + +VOID +EXPORT +NdisMSetInformationComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status) +{ + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle); + PADAPTER_BINDING AdapterBinding = (PADAPTER_BINDING)Adapter->MiniportAdapterBinding; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + (*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)( + AdapterBinding->NdisOpenBlock.ProtocolBindingContext, + Adapter->NdisMiniportBlock.MediaRequest, + Status); +} + + +VOID +EXPORT +NdisMSetAttributes( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE MiniportAdapterContext, + IN BOOLEAN BusMaster, + IN NDIS_INTERFACE_TYPE AdapterType) +/* + * FUNCTION: Informs the NDIS library of significant features of the caller's NIC + * ARGUMENTS: + * MiniportAdapterHandle = Handle input to MiniportInitialize + * MiniportAdapterContext = Pointer to context information + * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device + * AdapterType = Specifies the I/O bus interface of the caller's NIC + */ +{ + PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + Adapter->NdisMiniportBlock.MiniportAdapterContext = MiniportAdapterContext; + Adapter->Attributes = BusMaster? NDIS_ATTRIBUTE_BUS_MASTER : 0; + Adapter->NdisMiniportBlock.AdapterType = AdapterType; + Adapter->AttributesSet = TRUE; +} + + +VOID +EXPORT +NdisMSetAttributesEx( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE MiniportAdapterContext, + IN UINT CheckForHangTimeInSeconds OPTIONAL, + IN ULONG AttributeFlags, + IN NDIS_INTERFACE_TYPE AdapterType) +/* + * FUNCTION: Informs the NDIS library of significant features of the caller's NIC + * ARGUMENTS: + * MiniportAdapterHandle = Handle input to MiniportInitialize + * MiniportAdapterContext = Pointer to context information + * CheckForHangTimeInSeconds = Specifies interval in seconds at which + * MiniportCheckForHang should be called + * AttributeFlags = Bitmask that indicates specific attributes + * AdapterType = Specifies the I/O bus interface of the caller's NIC + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMSleep( + IN ULONG MicrosecondsToSleep) +{ + UNIMPLEMENTED +} + + +BOOLEAN +EXPORT +NdisMSynchronizeWithInterrupt( + IN PNDIS_MINIPORT_INTERRUPT Interrupt, + IN PVOID SynchronizeFunction, + IN PVOID SynchronizeContext) +{ + UNIMPLEMENTED + + return FALSE; +} + + +NDIS_STATUS +EXPORT +NdisMWriteLogData( + IN NDIS_HANDLE LogHandle, + IN PVOID LogBuffer, + IN UINT LogBufferSize) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisTerminateWrapper( + IN NDIS_HANDLE NdisWrapperHandle, + IN PVOID SystemSpecific) +/* + * FUNCTION: Releases resources allocated by a call to NdisInitializeWrapper + * ARGUMENTS: + * NdisWrapperHandle = Handle returned by NdisInitializeWrapper (MINIPORT_DRIVER) + * SystemSpecific = Always NULL + */ +{ + PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + ExFreePool(Miniport); +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/protocol.c b/drivers/net/ndis/ndis/protocol.c new file mode 100644 index 0000000..60937e6 --- /dev/null +++ b/drivers/net/ndis/ndis/protocol.c @@ -0,0 +1,629 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/protocol.c + * PURPOSE: Routines used by NDIS protocol drivers + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include + + +LIST_ENTRY ProtocolListHead; +KSPIN_LOCK ProtocolListLock; + + +NDIS_STATUS +ProIndicatePacket( + PLOGICAL_ADAPTER Adapter, + PNDIS_PACKET Packet) +/* + * FUNCTION: Indicates a packet to bound protocols + * ARGUMENTS: + * Adapter = Pointer to logical adapter + * Packet = Pointer to packet to indicate + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; + UINT Length; + UINT Total; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + +#ifdef DBG + MiniDisplayPacket(Packet); +#endif + + NdisQueryPacket(Packet, NULL, NULL, NULL, &Total); + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + + Adapter->LoopPacket = Packet; + + Length = CopyPacketToBuffer( + Adapter->LookaheadBuffer, + Packet, + 0, + Adapter->CurLookaheadLength); + + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + if (Length > Adapter->MediumHeaderSize) { + MiniIndicateData(Adapter, + NULL, + Adapter->LookaheadBuffer, + Adapter->MediumHeaderSize, + &Adapter->LookaheadBuffer[Adapter->MediumHeaderSize], + Length - Adapter->MediumHeaderSize, + Total - Adapter->MediumHeaderSize); + } else { + MiniIndicateData(Adapter, + NULL, + Adapter->LookaheadBuffer, + Adapter->MediumHeaderSize, + NULL, + 0, + 0); + } + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + + Adapter->LoopPacket = NULL; + + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + return STATUS_SUCCESS; +} + + +NDIS_STATUS +ProRequest( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_REQUEST NdisRequest) +/* + * FUNCTION: Forwards a request to an NDIS miniport + * ARGUMENTS: + * MacBindingHandle = Adapter binding handle + * NdisRequest = Pointer to request to perform + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; + BOOLEAN Queue; + NDIS_STATUS NdisStatus; + PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle); + PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + Queue = Adapter->MiniportBusy; + if (Queue) { + MiniQueueWorkItem(Adapter, + NdisWorkItemRequest, + (PVOID)NdisRequest, + (NDIS_HANDLE)AdapterBinding); + } else { + Adapter->MiniportBusy = TRUE; + } + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + if (!Queue) { + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + NdisStatus = MiniDoRequest(Adapter, NdisRequest); + KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock); + Adapter->MiniportBusy = FALSE; + if (Adapter->WorkQueueHead) + KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL); + KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock); + KeLowerIrql(OldIrql); + } else { + NdisStatus = NDIS_STATUS_PENDING; + } + return NdisStatus; +} + + +NDIS_STATUS +ProReset( + IN NDIS_HANDLE MacBindingHandle) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +ProSend( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_PACKET Packet) +/* + * FUNCTION: Forwards a request to send a packet to an NDIS miniport + * ARGUMENTS: + * MacBindingHandle = Adapter binding handle + * Packet = Pointer to NDIS packet descriptor + */ +{ + KIRQL OldIrql; + BOOLEAN Queue; + NDIS_STATUS NdisStatus; + PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle); + PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* FIXME: Should queue packet if miniport returns NDIS_STATUS_RESOURCES */ + + Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle; + + KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql); + Queue = Adapter->MiniportBusy; + + /* We may have to loop this packet if miniport cannot */ + if (Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) { + if (MiniAdapterHasAddress(Adapter, Packet)) { + /* Do software loopback because miniport does not support it */ + + NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n")); + + if (Queue) { + + /* FIXME: Packets should properbly be queued directly on the adapter instead */ + + MiniQueueWorkItem(Adapter, + NdisWorkItemSendLoopback, + (PVOID)Packet, + (NDIS_HANDLE)AdapterBinding); + } else { + Adapter->MiniportBusy = TRUE; + } + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + if (!Queue) { + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + NdisStatus = ProIndicatePacket(Adapter, Packet); + KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock); + Adapter->MiniportBusy = FALSE; + if (Adapter->WorkQueueHead) + KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL); + KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock); + KeLowerIrql(OldIrql); + return NdisStatus; + } else { + return NDIS_STATUS_PENDING; + } + } + } + + if (Queue) { + + /* FIXME: Packets should properbly be queued directly on the adapter instead */ + + MiniQueueWorkItem(Adapter, + NdisWorkItemSend, + (PVOID)Packet, + (NDIS_HANDLE)AdapterBinding); + } else { + Adapter->MiniportBusy = TRUE; + } + KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql); + + if (!Queue) { + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)( + Adapter->NdisMiniportBlock.MiniportAdapterContext, + Packet, + 0); + KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock); + Adapter->MiniportBusy = FALSE; + if (Adapter->WorkQueueHead) + KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL); + KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock); + KeLowerIrql(OldIrql); + } else { + NdisStatus = NDIS_STATUS_PENDING; + } + return NdisStatus; +} + + +VOID +ProSendPackets( + IN NDIS_HANDLE NdisBindingHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +ProTransferData( + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE MacReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer, + IN OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred) +/* + * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet + * ARGUMENTS: + * MacBindingHandle = Adapter binding handle + * MacReceiveContext = MAC receive context + * ByteOffset = Offset in packet to place data + * BytesToTransfer = Number of bytes to copy into packet + * Packet = Pointer to NDIS packet descriptor + * BytesTransferred = Address of buffer to place number of bytes copied + */ +{ + PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle); + PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* FIXME: Interrupts must be disabled for adapter */ + + if (Packet == Adapter->LoopPacket) { + /* NDIS is responsible for looping this packet */ + NdisCopyFromPacketToPacket(Packet, + ByteOffset, + BytesToTransfer, + Adapter->LoopPacket, + 0, + BytesTransferred); + return NDIS_STATUS_SUCCESS; + } + + return (*Adapter->Miniport->Chars.u2.TransferDataHandler)( + Packet, + BytesTransferred, + Adapter->NdisMiniportBlock.MiniportAdapterContext, + MacReceiveContext, + ByteOffset, + BytesToTransfer); +} + + + +VOID +EXPORT +NdisCloseAdapter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle) +/* + * FUNCTION: Closes an adapter opened with NdisOpenAdapter + * ARGUMENTS: + * Status = Address of buffer for status information + * NdisBindingHandle = Handle returned by NdisOpenAdapter + */ +{ + KIRQL OldIrql; + PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(NdisBindingHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Remove from protocol's bound adapters list */ + KeAcquireSpinLock(&AdapterBinding->ProtocolBinding->Lock, &OldIrql); + RemoveEntryList(&AdapterBinding->ProtocolListEntry); + KeReleaseSpinLock(&AdapterBinding->ProtocolBinding->Lock, OldIrql); + + /* Remove protocol from adapter's bound protocols list */ + KeAcquireSpinLock(&AdapterBinding->Adapter->NdisMiniportBlock.Lock, &OldIrql); + RemoveEntryList(&AdapterBinding->AdapterListEntry); + KeReleaseSpinLock(&AdapterBinding->Adapter->NdisMiniportBlock.Lock, OldIrql); + + ExFreePool(AdapterBinding); + + *Status = NDIS_STATUS_SUCCESS; +} + + +VOID +EXPORT +NdisDeregisterProtocol( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisProtocolHandle) +/* + * FUNCTION: Releases the resources allocated by NdisRegisterProtocol + * ARGUMENTS: + * Status = Address of buffer for status information + * NdisProtocolHandle = Handle returned by NdisRegisterProtocol + */ +{ + KIRQL OldIrql; + PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* FIXME: Make sure no adapter bindings exist */ + + /* Remove protocol from global list */ + KeAcquireSpinLock(&ProtocolListLock, &OldIrql); + RemoveEntryList(&Protocol->ListEntry); + KeReleaseSpinLock(&ProtocolListLock, OldIrql); + + ExFreePool(Protocol); + + *Status = NDIS_STATUS_SUCCESS; +} + + +VOID +EXPORT +NdisOpenAdapter( + OUT PNDIS_STATUS Status, + OUT PNDIS_STATUS OpenErrorStatus, + OUT PNDIS_HANDLE NdisBindingHandle, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE NdisProtocolHandle, + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_STRING AdapterName, + IN UINT OpenOptions, + IN PSTRING AddressingInformation OPTIONAL) +/* + * FUNCTION: Opens an adapter for communication + * ARGUMENTS: + * Status = Address of buffer for status information + * OpenErrorStatus = Address of buffer for secondary error code + * NdisBindingHandle = Address of buffer for adapter binding handle + * SelectedMediumIndex = Address of buffer for selected medium + * MediumArray = Pointer to an array of NDIS_MEDIUMs called can support + * MediumArraySize = Number of elements in MediumArray + * NdisProtocolHandle = Handle returned by NdisRegisterProtocol + * ProtocolBindingContext = Pointer to caller suplied context area + * AdapterName = Pointer to buffer with name of adapter + * OpenOptions = Bitmask with flags passed to next-lower driver + * AddressingInformation = Optional pointer to buffer with NIC specific information + */ +{ + UINT i; + BOOLEAN Found; + PLOGICAL_ADAPTER Adapter; + PADAPTER_BINDING AdapterBinding; + PPROTOCOL_BINDING Protocol = GET_PROTOCOL_BINDING(NdisProtocolHandle); + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + Adapter = MiniLocateDevice(AdapterName); + if (!Adapter) { + NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n")); + *Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + return; + } + + /* Find the media type in the list provided by the protocol driver */ + Found = FALSE; + for (i = 0; i < MediumArraySize; i++) { + if (Adapter->NdisMiniportBlock.MediaType == MediumArray[i]) { + *SelectedMediumIndex = i; + Found = TRUE; + break; + } + } + + if (!Found) { + NDIS_DbgPrint(MIN_TRACE, ("Medium is not supported.\n")); + *Status = NDIS_STATUS_UNSUPPORTED_MEDIA; + return; + } + + AdapterBinding = ExAllocatePool(NonPagedPool, sizeof(ADAPTER_BINDING)); + if (!AdapterBinding) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + *Status = NDIS_STATUS_RESOURCES; + return; + } + + RtlZeroMemory(AdapterBinding, sizeof(ADAPTER_BINDING)); + + AdapterBinding->ProtocolBinding = Protocol; + AdapterBinding->Adapter = Adapter; + AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext; + + /* Set fields required by some NDIS macros */ + AdapterBinding->NdisOpenBlock.MacBindingHandle = (NDIS_HANDLE)AdapterBinding; + + /* Set handlers (some NDIS macros require these) */ + + AdapterBinding->NdisOpenBlock.RequestHandler = ProRequest; + AdapterBinding->NdisOpenBlock.ResetHandler = ProReset; + AdapterBinding->NdisOpenBlock.u1.SendHandler = ProSend; + AdapterBinding->NdisOpenBlock.SendPacketsHandler = ProSendPackets; + AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData; + + /* Put on protocol's bound adapters list */ + ExInterlockedInsertTailList(&Protocol->AdapterListHead, + &AdapterBinding->ProtocolListEntry, + &Protocol->Lock); + + /* Put protocol on adapter's bound protocols list */ + ExInterlockedInsertTailList(&Adapter->ProtocolListHead, + &AdapterBinding->AdapterListEntry, + &Adapter->NdisMiniportBlock.Lock); + + *NdisBindingHandle = (NDIS_HANDLE)AdapterBinding; + + *Status = NDIS_STATUS_SUCCESS; +} + + +VOID +EXPORT +NdisRegisterProtocol( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE NdisProtocolHandle, + IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics, + IN UINT CharacteristicsLength) +/* + * FUNCTION: Registers an NDIS driver's ProtocolXxx entry points + * ARGUMENTS: + * Status = Address of buffer for status information + * NdisProtocolHandle = Address of buffer for handle used to identify the driver + * ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure + * CharacteristicsLength = Size of structure which ProtocolCharacteristics targets + */ +{ + PPROTOCOL_BINDING Protocol; + NTSTATUS NtStatus; + UINT MinSize; + + NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (ProtocolCharacteristics->MajorNdisVersion) { + case 0x03: + MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS_S); + break; + + case 0x04: + MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS_S); + break; + + case 0x05: + MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS_S); + break; + + default: + *Status = NDIS_STATUS_BAD_VERSION; + return; + } + + if (CharacteristicsLength < MinSize) { + NDIS_DbgPrint(DEBUG_PROTOCOL, ("Bad protocol characteristics.\n")); + *Status = NDIS_STATUS_BAD_CHARACTERISTICS; + return; + } + + Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING)); + if (!Protocol) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + *Status = NDIS_STATUS_RESOURCES; + return; + } + + RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING)); + RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize); + + NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, + &ProtocolCharacteristics->Name, + TRUE); + if (!NT_SUCCESS(NtStatus)) { + NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + ExFreePool(Protocol); + *Status = NDIS_STATUS_RESOURCES; + return; + } + + KeInitializeSpinLock(&Protocol->Lock); + + Protocol->RefCount = 1; + + InitializeListHead(&Protocol->AdapterListHead); + + /* Put protocol binding on global list */ + ExInterlockedInsertTailList(&ProtocolListHead, + &Protocol->ListEntry, + &ProtocolListLock); + + *NdisProtocolHandle = Protocol; + *Status = NDIS_STATUS_SUCCESS; +} + + +VOID +EXPORT +NdisRequest( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN PNDIS_REQUEST NdisRequest) +/* + * FUNCTION: Forwards a request to an NDIS driver + * ARGUMENTS: + * Status = Address of buffer for status information + * NdisBindingHandle = Adapter binding handle + * NdisRequest = Pointer to request to perform + */ +{ + *Status = ProRequest(NdisBindingHandle, NdisRequest); +} + + +VOID +EXPORT +NdisReset( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle) +{ + *Status = ProReset(NdisBindingHandle); +} + + +VOID +EXPORT +NdisSend( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN PNDIS_PACKET Packet) +/* + * FUNCTION: Forwards a request to send a packet + * ARGUMENTS: + * Status = Address of buffer for status information + * NdisBindingHandle = Adapter binding handle + * Packet = Pointer to NDIS packet descriptor + */ +{ + *Status = ProSend(NdisBindingHandle, Packet); +} + + +VOID +EXPORT +NdisSendPackets( + IN NDIS_HANDLE NdisBindingHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets) +{ + ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets); +} + + +VOID +EXPORT +NdisTransferData( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE MacReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer, + IN OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred) +/* + * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet + * ARGUMENTS: + * Status = Address of buffer for status information + * NdisBindingHandle = Adapter binding handle + * MacReceiveContext = MAC receive context + * ByteOffset = Offset in packet to place data + * BytesToTransfer = Number of bytes to copy into packet + * Packet = Pointer to NDIS packet descriptor + * BytesTransferred = Address of buffer to place number of bytes copied + */ +{ + *Status = ProTransferData(NdisBindingHandle, + MacReceiveContext, + ByteOffset, + BytesToTransfer, + Packet, + BytesTransferred); +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/string.c b/drivers/net/ndis/ndis/string.c new file mode 100644 index 0000000..bd9fbb8 --- /dev/null +++ b/drivers/net/ndis/ndis/string.c @@ -0,0 +1,149 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/string.c + * PURPOSE: String management routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +NDIS_STATUS +EXPORT +NdisAnsiStringToUnicodeString( + IN OUT PNDIS_STRING DestinationString, + IN PNDIS_ANSI_STRING SourceString) +/* + * FUNCTION: Converts an ANSI string to an NDIS (unicode) string + * ARGUMENTS: + * DestinationString = Address of buffer to place converted string in + * SourceString = Pointer to ANSI string to be converted + */ +{ + return (NDIS_STATUS)RtlAnsiStringToUnicodeString( + (PUNICODE_STRING)DestinationString, + (PANSI_STRING)SourceString, FALSE); +} + + +BOOLEAN +EXPORT +NdisEqualString( + IN PNDIS_STRING String1, + IN PNDIS_STRING String2, + IN BOOLEAN CaseInsensitive) +/* + * FUNCTION: Tests two strings for equality + * ARGUMENTS: + * String1 = Pointer to first string + * String2 = Pointer to second string + * CaseInsensitive = TRUE if the compare should be case insensitive + */ +{ + return RtlEqualUnicodeString( + (PUNICODE_STRING)String1, + (PUNICODE_STRING)String2, + CaseInsensitive); +} + + +VOID +EXPORT +NdisInitAnsiString( + IN OUT PNDIS_ANSI_STRING DestinationString, + IN PCSTR SourceString) +/* + * FUNCTION: Initializes an ANSI string + * ARGUMENTS: + * DestinationString = Address of buffer to place string in + * SourceString = Pointer to null terminated ANSI string + */ +{ + RtlInitString( + (PANSI_STRING)DestinationString, + (PCSZ)SourceString); +} + + +VOID +EXPORT +NdisInitializeString( + IN OUT PNDIS_STRING DestinationString, + IN PUCHAR SourceString) +/* + * FUNCTION: Initializes an NDIS (unicode) string + * ARGUMENTS: + * DestinationString = Address of buffer to place string in + * SourceString = Pointer to null terminated ANSI string + */ +{ + ANSI_STRING AnsiString; + + RtlInitAnsiString( + &AnsiString, + (PCSZ)SourceString); + + RtlAnsiStringToUnicodeString( + (PUNICODE_STRING)DestinationString, + &AnsiString, + TRUE); +} + + +VOID +EXPORT +NdisInitUnicodeString( + IN OUT PNDIS_STRING DestinationString, + IN PCWSTR SourceString) +/* + * FUNCTION: Initializes an unicode string + * ARGUMENTS: + * DestinationString = Address of buffer to place string in + * SourceString = Pointer to null terminated unicode string + */ +{ + RtlInitUnicodeString( + (PUNICODE_STRING)DestinationString, + SourceString); +} + + +NDIS_STATUS +EXPORT +NdisUnicodeStringToAnsiString( + IN OUT PNDIS_ANSI_STRING DestinationString, + IN PNDIS_STRING SourceString) +/* + * FUNCTION: Converts an NDIS (unicode) string to an ANSI string + * ARGUMENTS: + * DestinationString = Address of buffer to place converted string in + * SourceString = Pointer to unicode string to be converted + */ +{ + return (NDIS_STATUS)RtlUnicodeStringToAnsiString( + (PANSI_STRING)DestinationString, + (PUNICODE_STRING)SourceString, + FALSE); +} + + +NTSTATUS +EXPORT +NdisUpcaseUnicodeString( + OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/stubs.c b/drivers/net/ndis/ndis/stubs.c new file mode 100644 index 0000000..76c2eb2 --- /dev/null +++ b/drivers/net/ndis/ndis/stubs.c @@ -0,0 +1,1023 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/stubs.c + * PURPOSE: Stubs + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +VOID +EXPORT +NdisCompleteBindAdapter( + IN NDIS_HANDLE BindAdapterContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenStatus) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteQueryStatistics( + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCompleteUnbindAdapter( + IN NDIS_HANDLE UnbindAdapterContext, + IN NDIS_STATUS Status) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisInitializeListHead( + IN PLIST_ENTRY ListHead) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisInterlockedAddUlong ( + IN PULONG Addend, + IN ULONG Increment, + IN PNDIS_SPIN_LOCK SpinLock) +{ + UNIMPLEMENTED +} + + +PLIST_ENTRY +EXPORT +NdisInterlockedInsertHeadList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PNDIS_SPIN_LOCK SpinLock) +{ + UNIMPLEMENTED + + return NULL; +} + + +PLIST_ENTRY +EXPORT +NdisInterlockedInsertTailList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PNDIS_SPIN_LOCK SpinLock) +{ + UNIMPLEMENTED + + return NULL; +} + + +PLIST_ENTRY +EXPORT +NdisInterlockedRemoveHeadList( + IN PLIST_ENTRY ListHead, + IN PNDIS_SPIN_LOCK SpinLock) +{ + UNIMPLEMENTED + + return NULL; +} + + +VOID +EXPORT +NdisMCompleteBufferPhysicalMapping( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG PhysicalMapRegister) +{ +} + + +VOID +EXPORT +NdisMStartBufferPhysicalMapping( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG PhysicalMapRegister, + IN BOOLEAN WriteToDevice, + OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray, + OUT PUINT ArraySize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMapFile( + OUT PNDIS_STATUS Status, + OUT PVOID * MappedBuffer, + IN NDIS_HANDLE FileHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisWriteConfiguration( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PNDIS_STRING Keyword, + IN PNDIS_CONFIGURATION_PARAMETER * ParameterValue) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisWriteErrorLogEntry( + IN NDIS_HANDLE NdisAdapterHandle, + IN NDIS_ERROR_CODE ErrorCode, + IN ULONG NumberOfErrorValues, + /* IN ULONG */ ...) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCloseConfiguration( + IN NDIS_HANDLE ConfigurationHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisCloseFile( + IN NDIS_HANDLE FileHandle) +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisIMDeInitializeDeviceInstance( + IN NDIS_HANDLE NdisMiniportHandle) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisIMInitializeDeviceInstance( + IN NDIS_HANDLE DriverHandle, + IN PNDIS_STRING DeviceInstance) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisIMRegisterLayeredMiniport( + IN NDIS_HANDLE NdisWrapperHandle, + IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics, + IN UINT CharacteristicsLength, + OUT PNDIS_HANDLE DriverHandle) +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMWanIndicateReceive( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisLinkContext, + IN PUCHAR PacketBuffer, + IN UINT PacketSize) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMWanIndicateReceiveComplete( + IN NDIS_HANDLE MiniportAdapterHandle) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisMWanSendComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_WAN_PACKET Packet, + IN NDIS_STATUS Status) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisOpenConfiguration( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE ConfigurationHandle, + IN NDIS_HANDLE WrapperConfigurationContext) +{ + UNIMPLEMENTED +} + + +/* +NdisOpenConfigurationKeyByIndex +NdisOpenConfigurationKeyByName +*/ + + +VOID +EXPORT +NdisOpenFile( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE FileHandle, + OUT PUINT FileLength, + IN PNDIS_STRING FileName, + IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress) +{ + UNIMPLEMENTED +} + + +/* +NdisOpenGlobalConfiguration +*/ + +VOID +EXPORT +NdisOpenProtocolConfiguration( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING ProtocolSection) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisReadConfiguration( + OUT PNDIS_STATUS Status, + OUT PNDIS_CONFIGURATION_PARAMETER * ParameterValue, + IN NDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING Keyword, + IN NDIS_PARAMETER_TYPE ParameterType) +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisReadNetworkAddress( + OUT PNDIS_STATUS Status, + OUT PVOID * NetworkAddress, + OUT PUINT NetworkAddressLength, + IN NDIS_HANDLE ConfigurationHandle) +{ + UNIMPLEMENTED +} + + +#if 0 +VOID +EXPORT +NdisRegisterTdiCallBack( + IN TDI_REGISTER_CALLBACK RegsterCallback) +{ + UNIMPLEMENTED +} +#endif + + +/* +NdisScheduleWorkItem +*/ + + +#if 0 +VOID +EXPORT +NdisSetProtocolFilter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN RECEIVE_HANDLER ReceiveHandler, + IN RECEIVE_PACKET_HANDLER ReceivePacketHandler, + IN NDIS_MEDIUM Medium, + IN UINT Offset, + IN UINT Size, + IN PUCHAR Pattern) +{ + UNIMPLEMENTED +} +#endif + + +CCHAR +EXPORT +NdisSystemProcessorCount( + VOID) +{ + return (CCHAR)1; +} + + +VOID +EXPORT +NdisUnmapFile( + IN NDIS_HANDLE FileHandle) +{ + UNIMPLEMENTED +} + + +/* +NdisUpcaseUnicodeString +NdisUpdateSharedMemory@4 +*/ + + +/* +NdisWriteEventLogEntry +*/ + + + +/* NDIS 5.0 extensions */ + +VOID +EXPORT +NdisCompletePnPEvent( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN PNET_PNP_EVENT NetPnPEvent) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisConvertStringToAtmAddress( + OUT PNDIS_STATUS Status, + IN PNDIS_STRING String, + OUT PATM_ADDRESS AtmAddress) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisGetCurrentProcessorCounts( + OUT PULONG pIdleCount, + OUT PULONG pKernelAndUser, + OUT PULONG pIndex) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisGetDriverHandle( + IN PNDIS_HANDLE NdisBindingHandle, + OUT PNDIS_HANDLE NdisDriverHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +PNDIS_PACKET +EXPORT +NdisGetReceivedPacket( + IN PNDIS_HANDLE NdisBindingHandle, + IN PNDIS_HANDLE MacContext) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NULL; +} + + +VOID +EXPORT +NdisGetSystemUptime( + OUT PULONG pSystemUpTime) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisInitializeReadWriteLock( + IN PNDIS_RW_LOCK Lock) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +LONG +EXPORT +NdisInterlockedDecrement( + IN PLONG Addend) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return 0; +} + + +LONG +EXPORT +NdisInterlockedIncrement( + IN PLONG Addend) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return 0; +} + + +PSINGLE_LIST_ENTRY +EXPORT +NdisInterlockedPopEntrySList( + IN PSLIST_HEADER ListHead, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NULL; +} + + +PSINGLE_LIST_ENTRY +EXPORT +NdisInterlockedPushEntrySList( + IN PSLIST_HEADER ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NULL; +} + + +NDIS_STATUS +EXPORT +NdisMDeregisterDevice( + IN NDIS_HANDLE NdisDeviceHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMGetDeviceProperty( + IN NDIS_HANDLE MiniportAdapterHandle, + IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL, + IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL, + IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL, + IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL, + IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisMInitializeScatterGatherDma( + IN NDIS_HANDLE MiniportAdapterHandle, + IN BOOLEAN Dma64BitAddresses, + IN ULONG MaximumPhysicalMapping) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMPromoteMiniport( + IN NDIS_HANDLE MiniportAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMQueryAdapterInstanceName( + OUT PNDIS_STRING AdapterInstanceName, + IN NDIS_HANDLE MiniportAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMRegisterDevice( + IN NDIS_HANDLE NdisWrapperHandle, + IN PNDIS_STRING DeviceName, + IN PNDIS_STRING SymbolicName, + IN PDRIVER_DISPATCH MajorFunctions[], + OUT PDEVICE_OBJECT *pDeviceObject, + OUT NDIS_HANDLE *NdisDeviceHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisMRegisterUnloadHandler( + IN NDIS_HANDLE NdisWrapperHandle, + IN PDRIVER_UNLOAD UnloadHandler) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisMRemoveMiniport( + IN NDIS_HANDLE MiniportAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +NDIS_STATUS +EXPORT +NdisMSetMiniportSecondary( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE PrimaryMiniportAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisOpenConfigurationKeyByIndex( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ConfigurationHandle, + IN ULONG Index, + OUT PNDIS_STRING KeyName, + OUT PNDIS_HANDLE KeyHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisOpenConfigurationKeyByName( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING SubKeyName, + OUT PNDIS_HANDLE SubKeyHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisQueryAdapterInstanceName( + OUT PNDIS_STRING AdapterInstanceName, + IN NDIS_HANDLE NdisBindingHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisQueryBufferSafe( + IN PNDIS_BUFFER Buffer, + OUT PVOID *VirtualAddress OPTIONAL, + OUT PUINT Length, + IN UINT Priority) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +ULONG +EXPORT +NdisReadPcmciaAttributeMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return 0; +} + + +VOID +EXPORT +NdisReleaseReadWriteLock( + IN PNDIS_RW_LOCK Lock, + IN PLOCK_STATE LockState) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisWriteEventLogEntry( + IN PVOID LogHandle, + IN NDIS_STATUS EventCode, + IN ULONG UniqueEventValue, + IN USHORT NumStrings, + IN PVOID StringsList OPTIONAL, + IN ULONG DataSize, + IN PVOID Data OPTIONAL) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +ULONG +EXPORT +NdisWritePcmciaAttributeMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return 0; +} + + +/* NDIS 5.0 extensions for intermediate drivers */ + +VOID +EXPORT +NdisIMAssociateMiniport( + IN NDIS_HANDLE DriverHandle, + IN NDIS_HANDLE ProtocolHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_STATUS +EXPORT +NdisIMCancelInitializeDeviceInstance( + IN NDIS_HANDLE DriverHandle, + IN PNDIS_STRING DeviceInstance) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + + +VOID +EXPORT +NdisIMCopySendCompletePerPacketInfo( + IN PNDIS_PACKET DstPacket, + IN PNDIS_PACKET SrcPacket) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisIMCopySendPerPacketInfo( + IN PNDIS_PACKET DstPacket, + IN PNDIS_PACKET SrcPacket) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +VOID +EXPORT +NdisIMDeregisterLayeredMiniport( + IN NDIS_HANDLE DriverHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED +} + + +NDIS_HANDLE +EXPORT +NdisIMGetBindingContext( + IN NDIS_HANDLE NdisBindingHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return (NDIS_HANDLE)NULL; +} + + +NDIS_HANDLE +EXPORT +NdisIMGetDeviceContext( + IN NDIS_HANDLE MiniportAdapterHandle) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return (NDIS_HANDLE)NULL; +} + + +NDIS_STATUS +EXPORT +NdisIMInitializeDeviceInstanceEx( + IN NDIS_HANDLE DriverHandle, + IN PNDIS_STRING DriverInstance, + IN NDIS_HANDLE DeviceContext OPTIONAL) +/* + * FUNCTION: + * ARGUMENTS: + * NOTES: + * NDIS 5.0 + */ +{ + UNIMPLEMENTED + + return NDIS_STATUS_FAILURE; +} + +/* EOF */ diff --git a/drivers/net/ndis/ndis/time.c b/drivers/net/ndis/ndis/time.c new file mode 100644 index 0000000..95b0416 --- /dev/null +++ b/drivers/net/ndis/ndis/time.c @@ -0,0 +1,86 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: ndis/time.c + * PURPOSE: Time related routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +VOID +EXPORT +NdisCancelTimer( + IN PNDIS_TIMER Timer, + OUT PBOOLEAN TimerCancelled) +{ +} + + +VOID +EXPORT +NdisGetCurrentSystemTime ( + IN OUT PLONGLONG pSystemTime) +{ +} + + +VOID +EXPORT +NdisInitializeTimer( + IN OUT PNDIS_TIMER Timer, + IN PNDIS_TIMER_FUNCTION TimerFunction, + IN PVOID FunctionContext) +{ +} + + +VOID +EXPORT +NdisMCancelTimer( + IN PNDIS_MINIPORT_TIMER Timer, + OUT PBOOLEAN TimerCancelled) +{ +} + + +VOID +EXPORT +NdisMInitializeTimer( + IN OUT PNDIS_MINIPORT_TIMER Timer, + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_TIMER_FUNCTION TimerFunction, + IN PVOID FunctionContext) +{ +} + + +VOID +EXPORT +NdisMSetPeriodicTimer( + IN PNDIS_MINIPORT_TIMER Timer, + IN UINT MillisecondsPeriod) +{ +} + + +VOID +EXPORT +NdisMSetTimer( + IN PNDIS_MINIPORT_TIMER Timer, + IN UINT MillisecondsToDelay) +{ +} + + +VOID +EXPORT +NdisSetTimer( + IN PNDIS_TIMER Timer, + IN UINT MillisecondsToDelay) +{ +} + +/* EOF */ diff --git a/drivers/net/ndis/readme.txt b/drivers/net/ndis/readme.txt new file mode 100644 index 0000000..aeaa136 --- /dev/null +++ b/drivers/net/ndis/readme.txt @@ -0,0 +1,18 @@ +Build instructions for NDIS library +----------------------------------- + +Building with Visual C++ and Windows NT DDK: + +Variables: +%BASEDIR% = path to NT4 DDK (e.g. c:\ntddk) +%DDKBUILDENV% = DDK build environment (free or checked) + +DDK environment variables must be set! (run setenv.bat) + + - Create the directory objects/i386/%DDKBUILDENV% + - Run "build" to build the library + + +Building with Mingw32 and ReactOS include files: + + - Run "make ndis" FROM THE ReactOS ROOT DIRECTORY to build the library diff --git a/drivers/net/packet/.cvsignore b/drivers/net/packet/.cvsignore new file mode 100644 index 0000000..d7687d4 --- /dev/null +++ b/drivers/net/packet/.cvsignore @@ -0,0 +1,5 @@ +*.coff +*.d +*.o +*.sym +*.sys diff --git a/drivers/net/packet/Makefile b/drivers/net/packet/Makefile new file mode 100644 index 0000000..30fc7e2 --- /dev/null +++ b/drivers/net/packet/Makefile @@ -0,0 +1,41 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +#TARGET_TYPE = export_driver +TARGET_TYPE = driver + +TARGET_NAME = packet + +TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS + +TARGET_OBJECTS = \ + packet.o \ + openclos.o \ + read.o \ + write.o \ + dump.o \ + jitter.o \ + win_bpf_filter.o \ + tme.o \ + count_packets.o \ + win_bpf_filter_init.o \ + tcp_session.o \ + memory_t.o \ + time_calls.o \ + functions.o \ + bucket_lookup.o \ + normal_lookup.o + + +TARGET_DDKLIBS = ndis.a + +TARGET_CLEAN = \ + *.o \ + *.coff + +TARGET_PATH = . + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/packet/bucket_lookup.c b/drivers/net/packet/bucket_lookup.c new file mode 100644 index 0000000..e2c5fde --- /dev/null +++ b/drivers/net/packet/bucket_lookup.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef WIN32 +#include "tme.h" +#include "bucket_lookup.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#include +#else +#include +#include +#endif + +#endif + + + +/* the key is represented by the initial and final value */ +/* of the bucket. At the moment bucket_lookup is able to */ +/* manage values of 16, 32 bits. */ +uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref) +{ + uint32 value; + uint32 i,j; + int found=-1; + uint32 blocks; + uint32 block_size; + uint8 *temp; + if ((data->key_len!=1)&& /*16 bit value*/ + (data->key_len!=2)) /*32 bit value*/ + return TME_ERROR; + + /*32 bit values*/ + blocks=data->filled_blocks-1; + block_size=data->block_size; + i=blocks/2; /*relative shift*/ + j=i; + temp=data->shared_memory_base_address+block_size; + + if (data->key_len==2) + { + value=SW_ULONG_AT(key,0); + + if((valueSW_ULONG_AT(temp+block_size*(blocks-1),4))) + { + uint32 *key32=(uint32*) key; + key32[0]=key32[1]=0; + + GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref); + + data->last_found=NULL; + return TME_FALSE; + } + + while(found==-1) /* search routine */ + { + i=(i==1)? 1:i>>1; + if (SW_ULONG_AT(temp+block_size*j,0)>value) + if (SW_ULONG_AT(temp+block_size*(j-1),4)value) + found=-2; + else + j+=i; + else found=j; + } + if (found<0) + { + uint32 *key32=(uint32*) key; + key32[0]=key32[1]=0; + + GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref); + + data->last_found=NULL; + return TME_FALSE; + } + + data->last_found=data->lut_base_address+found*sizeof(RECORD); + + COPY_MEMORY(key,temp+block_size*found,8); + + GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref); + + return TME_TRUE; + } + else + { + value=SW_USHORT_AT(key,0); + + if((valueSW_USHORT_AT(temp+block_size*(blocks-1),2))) + { + uint16 *key16=(uint16*) key; + key16[0]=key16[1]=0; + + GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref); + + data->last_found=NULL; + return TME_FALSE; + } + + while(found==-1) /* search routine */ + { + i=(i==1)? 1:i>>1; + if (SW_USHORT_AT(temp+block_size*j,0)>value) + if (SW_USHORT_AT(temp+block_size*(j-1),2)value) + found=-2; + else + j+=i; + else found=j; + } + + if (found<0) + { + uint16 *key16=(uint16*) key; + key16[0]=key16[1]=0; + + GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref); + + data->last_found=NULL; + return TME_FALSE; + } + + data->last_found=data->lut_base_address+found*sizeof(RECORD); + + GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref); + + COPY_MEMORY(key,temp+block_size*found,4); + + return TME_TRUE; + } + +} + +uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref) +{ + RECORD *records=(RECORD*)data->lut_base_address; + + if ((data->key_len!=1)&& /*16 bit value*/ + (data->key_len!=2)) /*32 bit value*/ + return TME_ERROR; + + if(data->key_len==2) + { + uint32 start,stop; + uint8 *tmp; + + start=SW_ULONG_AT(key,0); + stop=SW_ULONG_AT(key,4); + + if (start>stop) + return TME_ERROR; + if (data->filled_entries>0) + { + tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0); + /*check if it is coherent with the previous block*/ + if (SW_ULONG_AT(tmp,4)>=start) + return TME_ERROR; + } + + if (data->filled_blocks==data->shared_memory_blocks) + return TME_ERROR; + + if (data->filled_entries==data->lut_entries) + return TME_ERROR; + + tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks; + + COPY_MEMORY(tmp,key,8); + + SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer); + SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec); + + GET_TIME((struct timeval *)(tmp+8),time_ref); + + data->filled_blocks++; + data->filled_entries++; + + return TME_TRUE; + } + else + { + uint16 start,stop; + uint8 *tmp; + + start=SW_USHORT_AT(key,0); + stop=SW_USHORT_AT(key,2); + + if (start>stop) + return TME_ERROR; + if (data->filled_entries>0) + { + tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0); + /*check if it is coherent with the previous block*/ + if (SW_USHORT_AT(tmp,2)>=start) + return TME_ERROR; + } + + if (data->filled_blocks==data->shared_memory_blocks) + return TME_ERROR; + + if (data->filled_entries==data->lut_entries) + return TME_ERROR; + + tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0); + + COPY_MEMORY(tmp,key,4); + + SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer); + SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec); + + GET_TIME((struct timeval *)(tmp+4),time_ref); + + data->filled_blocks++; + data->filled_entries++; + + return TME_TRUE; + } +} \ No newline at end of file diff --git a/drivers/net/packet/bucket_lookup.h b/drivers/net/packet/bucket_lookup.h new file mode 100644 index 0000000..ffe4523 --- /dev/null +++ b/drivers/net/packet/bucket_lookup.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __bucket_lookup +#define __bucket_lookup +#ifdef WIN32 +#include "tme.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#else +#include +#endif + +#endif + +#define BUCKET_LOOKUP_INSERT 0x00000011 +uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref); +#define BUCKET_LOOKUP 0x00000010 +uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref); + +#endif \ No newline at end of file diff --git a/drivers/net/packet/count_packets.c b/drivers/net/packet/count_packets.c new file mode 100644 index 0000000..71aa61f --- /dev/null +++ b/drivers/net/packet/count_packets.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef WIN32 +#include "tme.h" +#include "count_packets.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#include +#else +#include +#include +#endif + +#endif + + + +uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data) +{ + + c_p_data *counters=(c_p_data*)(block+data->key_len*4); + + counters->bytes+=pkt_size; + counters->packets++; + + return TME_SUCCESS; + +} diff --git a/drivers/net/packet/count_packets.h b/drivers/net/packet/count_packets.h new file mode 100644 index 0000000..0599964 --- /dev/null +++ b/drivers/net/packet/count_packets.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __count_packets +#define __count_packets + +#ifdef WIN32 +#include "tme.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#else +#include +#endif + +#endif + +typedef struct __c_p_data +{ + struct timeval timestamp; + uint64 packets; + uint64 bytes; +} + c_p_data; + +#define COUNT_PACKETS 0x00000000 +uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data); + +#endif + diff --git a/drivers/net/packet/debug.h b/drivers/net/packet/debug.h new file mode 100644 index 0000000..9fcd26b --- /dev/null +++ b/drivers/net/packet/debug.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __DEBUG_INCLUDE +#define __DEBUG_INCLUDE + + +#if DBG + +#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f)) +extern ULONG PacketDebugFlag; + +#define PACKET_DEBUG_LOUD 0x00000001 // debugging info +#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info + +#define PACKET_DEBUG_INIT 0x00000100 // init debugging info + +// +// Macro for deciding whether to dump lots of debugging information. +// + +#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A } +#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A } +#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A } + +#else + +#define IF_LOUD(A) +#define IF_VERY_LOUD(A) +#define IF_INIT_LOUD(A) + +#endif + +#endif /*#define __DEBUG_INCLUDE*/ diff --git a/drivers/net/packet/dump.c b/drivers/net/packet/dump.c new file mode 100644 index 0000000..e7c40fb --- /dev/null +++ b/drivers/net/packet/dump.c @@ -0,0 +1,587 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef _MSC_VER +#include "stdarg.h" +#include "ntddk.h" +#include "ntiologc.h" +#include "ndis.h" +#else +#include +#include +#endif + +#include "debug.h" +#include "packet.h" +#include "win_bpf.h" + +//------------------------------------------------------------------- + +NTSTATUS +NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append) +{ + NTSTATUS ntStatus; + IO_STATUS_BLOCK IoStatus; + OBJECT_ATTRIBUTES ObjectAttributes; + PWCHAR PathPrefix; + USHORT PathLen; + UNICODE_STRING FullFileName; + ULONG FullFileNameLength; + PDEVICE_OBJECT fsdDevice; + + FILE_STANDARD_INFORMATION StandardInfo; + + IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");) + + if(fileName->Buffer[0] == L'\\' && + fileName->Buffer[1] == L'?' && + fileName->Buffer[2] == L'?' && + fileName->Buffer[3] == L'\\' + ){ + PathLen = 0; + } + else{ + PathPrefix = L"\\??\\"; + PathLen = 8; + } + + // Insert the correct path prefix. + FullFileNameLength = PathLen + fileName->MaximumLength; + + FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, + FullFileNameLength, + '0DWA'); + + if (FullFileName.Buffer == NULL) { + ntStatus = STATUS_INSUFFICIENT_RESOURCES; + return ntStatus; + } + + FullFileName.Length = PathLen; + FullFileName.MaximumLength = (USHORT)FullFileNameLength; + + if(PathLen) + RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen); + + RtlAppendUnicodeStringToString (&FullFileName, fileName); + + IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);) + + InitializeObjectAttributes ( &ObjectAttributes, + &FullFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + // Create the dump file + ntStatus = ZwCreateFile( &Open->DumpFileHandle, + SYNCHRONIZE | FILE_WRITE_DATA, + &ObjectAttributes, + &IoStatus, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + (Append)?FILE_OPEN_IF:FILE_SUPERSEDE, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0 ); + + if ( !NT_SUCCESS( ntStatus ) ) + { + IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);) + + ExFreePool(FullFileName.Buffer); + Open->DumpFileHandle=NULL; + ntStatus = STATUS_NO_SUCH_FILE; + return ntStatus; + } + + ExFreePool(FullFileName.Buffer); + + ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle, + FILE_WRITE_ACCESS, +#ifndef __GNUC__ + *IoFileObjectType, +#else + IoFileObjectType, +#endif + KernelMode, + &Open->DumpFileObject, + 0); + + if ( !NT_SUCCESS( ntStatus ) ) + { + IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);) + + ZwClose( Open->DumpFileHandle ); + Open->DumpFileHandle=NULL; + + ntStatus = STATUS_NO_SUCH_FILE; + return ntStatus; + } + + fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject); + + IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);) + + return ntStatus; +} + +//------------------------------------------------------------------- + +NTSTATUS +NPF_StartDump(POPEN_INSTANCE Open) +{ + NTSTATUS ntStatus; + struct packet_file_header hdr; + IO_STATUS_BLOCK IoStatus; + NDIS_REQUEST pRequest; + ULONG MediaType; + OBJECT_ATTRIBUTES ObjectAttributes; + + IF_LOUD(DbgPrint("NPF: StartDump.\n");) + + // Init the file header + hdr.magic = TCPDUMP_MAGIC; + hdr.version_major = PCAP_VERSION_MAJOR; + hdr.version_minor = PCAP_VERSION_MINOR; + hdr.thiszone = 0; /*Currently not set*/ + hdr.snaplen = 1514; + hdr.sigfigs = 0; + + // Detect the medium type + switch (Open->Medium){ + + case NdisMediumWan: + hdr.linktype = DLT_EN10MB; + break; + + case NdisMedium802_3: + hdr.linktype = DLT_EN10MB; + break; + + case NdisMediumFddi: + hdr.linktype = DLT_FDDI; + break; + + case NdisMedium802_5: + hdr.linktype = DLT_IEEE802; + break; + + case NdisMediumArcnet878_2: + hdr.linktype = DLT_ARCNET; + break; + + case NdisMediumAtm: + hdr.linktype = DLT_ATM_RFC1483; + break; + + default: + hdr.linktype = DLT_EN10MB; + } + + // Write the header. + // We can use ZwWriteFile because we are in the context of the application + ntStatus = ZwWriteFile(Open->DumpFileHandle, + NULL, + NULL, + NULL, + &IoStatus, + &hdr, + sizeof(hdr), + NULL, + NULL ); + + + if ( !NT_SUCCESS( ntStatus ) ) + { + IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);) + + ZwClose( Open->DumpFileHandle ); + Open->DumpFileHandle=NULL; + + ntStatus = STATUS_NO_SUCH_FILE; + return ntStatus; + } + + Open->DumpOffset.QuadPart=24; + + ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle, + THREAD_ALL_ACCESS, + (ACCESS_MASK)0L, + 0, + 0, + NPF_DumpThread, + Open); + + if ( !NT_SUCCESS( ntStatus ) ) + { + IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);) + + ZwClose( Open->DumpFileHandle ); + Open->DumpFileHandle=NULL; + + return ntStatus; + } +#ifndef __GNUC__ + ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle, + THREAD_ALL_ACCESS, + NULL, + KernelMode, + &Open->DumpThreadObject, + 0); +#else +#endif + if ( !NT_SUCCESS( ntStatus ) ) + { + IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);) + + ObDereferenceObject(Open->DumpFileObject); + ZwClose( Open->DumpFileHandle ); + Open->DumpFileHandle=NULL; + + return ntStatus; + } + + + return ntStatus; + +} + +//------------------------------------------------------------------- +// Dump Thread +//------------------------------------------------------------------- + +VOID NPF_DumpThread(POPEN_INSTANCE Open) +{ + ULONG FrozenNic; + + IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%0x\n",Open);) + + while(TRUE){ + + // Wait until some packets arrive or the timeout expires + NdisWaitEvent(&Open->DumpEvent, 5000); + + IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");) + + if(Open->DumpLimitReached || + Open->BufSize==0){ // BufSize=0 means that this instance was closed, or that the buffer is too + // small for any capture. In both cases it is better to end the dump + + IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");) + IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);) + + PsTerminateSystemThread(STATUS_SUCCESS); + return; + } + + NdisResetEvent(&Open->DumpEvent); + + // Write the content of the buffer to the file + if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){ + PsTerminateSystemThread(STATUS_SUCCESS); + return; + } + + } + +} + +//------------------------------------------------------------------- + +NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open) +{ + UINT Thead; + UINT Ttail; + UINT TLastByte; + PUCHAR CurrBuff; + NTSTATUS ntStatus; + IO_STATUS_BLOCK IoStatus; + PMDL lMdl; + UINT SizeToDump; + + + Thead=Open->Bhead; + Ttail=Open->Btail; + TLastByte=Open->BLastByte; + + IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");) + + // Get the address of the buffer + CurrBuff=Open->Buffer; + // + // Fill the application buffer + // + if( Ttail < Thead ) + { + if(Open->MaxDumpBytes && + (UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes) + { + // Size limit reached + UINT PktLen; + + SizeToDump = 0; + + // Scan the buffer to detect the exact amount of data to save + while(TRUE){ + PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr); + + if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes) + break; + + SizeToDump += PktLen; + } + + } + else + SizeToDump = TLastByte-Thead; + + lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL); + if (lMdl == NULL) + { + // No memory: stop dump + IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");) + return STATUS_UNSUCCESSFUL; + } + + MmBuildMdlForNonPagedPool(lMdl); + + // Write to disk + NPF_WriteDumpFile(Open->DumpFileObject, + &Open->DumpOffset, + SizeToDump, + lMdl, + &IoStatus); + + IoFreeMdl(lMdl); + + if(!NT_SUCCESS(IoStatus.Status)){ + // Error + return STATUS_UNSUCCESSFUL; + } + + if(SizeToDump != TLastByte-Thead){ + // Size limit reached. + Open->DumpLimitReached = TRUE; + + // Awake the application + KeSetEvent(Open->ReadEvent,0,FALSE); + + return STATUS_UNSUCCESSFUL; + } + + // Update the packet buffer + Open->DumpOffset.QuadPart+=(TLastByte-Thead); + Open->BLastByte=Ttail; + Open->Bhead=0; + } + + if( Ttail > Thead ){ + + if(Open->MaxDumpBytes && + (UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes) + { + // Size limit reached + UINT PktLen; + + SizeToDump = 0; + + // Scan the buffer to detect the exact amount of data to save + while(Thead + SizeToDump < Ttail){ + + PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr); + + if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes) + break; + + SizeToDump += PktLen; + } + + } + else + SizeToDump = Ttail-Thead; + + lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL); + if (lMdl == NULL) + { + // No memory: stop dump + IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");) + return STATUS_UNSUCCESSFUL; + } + + MmBuildMdlForNonPagedPool(lMdl); + + // Write to disk + NPF_WriteDumpFile(Open->DumpFileObject, + &Open->DumpOffset, + SizeToDump, + lMdl, + &IoStatus); + + IoFreeMdl(lMdl); + + if(!NT_SUCCESS(IoStatus.Status)){ + // Error + return STATUS_UNSUCCESSFUL; + } + + if(SizeToDump != Ttail-Thead){ + // Size limit reached. + Open->DumpLimitReached = TRUE; + + // Awake the application + KeSetEvent(Open->ReadEvent,0,FALSE); + + return STATUS_UNSUCCESSFUL; + } + + // Update the packet buffer + Open->DumpOffset.QuadPart+=(Ttail-Thead); + Open->Bhead=Ttail; + + } + + return STATUS_SUCCESS; +} + +//------------------------------------------------------------------- + +NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){ + NTSTATUS ntStatus; + IO_STATUS_BLOCK IoStatus; + PMDL WriteMdl; + PUCHAR VMBuff; + UINT VMBufLen; + + + IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");) + IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);) + +DbgPrint("1\n"); + // Consistency check + if(Open->DumpFileHandle == NULL) + return STATUS_UNSUCCESSFUL; + +DbgPrint("2\n"); + ZwClose( Open->DumpFileHandle ); + + ObDereferenceObject(Open->DumpFileObject); +/* + if(Open->DumpLimitReached == TRUE) + // Limit already reached: don't save the rest of the buffer. + return STATUS_SUCCESS; +*/ +DbgPrint("3\n"); + + NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE); + + // Flush the buffer to file + NPF_SaveCurrentBuffer(Open); + + // Close The file + ObDereferenceObject(Open->DumpFileObject); + ZwClose( Open->DumpFileHandle ); + + Open->DumpFileHandle = NULL; + + ObDereferenceObject(Open->DumpFileObject); + + return STATUS_SUCCESS; +} + +//------------------------------------------------------------------- + +static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + + // Copy the status information back into the "user" IOSB + *Irp->UserIosb = Irp->IoStatus; + + // Wake up the mainline code + KeSetEvent(Irp->UserEvent, 0, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +//------------------------------------------------------------------- + +VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject, + PLARGE_INTEGER Offset, + ULONG Length, + PMDL Mdl, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PIRP irp; + KEVENT event; + PIO_STACK_LOCATION ioStackLocation; + PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject); + NTSTATUS Status; + + // Set up the event we'll use + KeInitializeEvent(&event, SynchronizationEvent, FALSE); + + // Allocate and build the IRP we'll be sending to the FSD + irp = IoAllocateIrp(fsdDevice->StackSize, FALSE); + + if (!irp) { + // Allocation failed, presumably due to memory allocation failure + IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES; + IoStatusBlock->Information = 0; + + return; + } + + irp->MdlAddress = Mdl; + irp->UserEvent = &event; + irp->UserIosb = IoStatusBlock; + irp->Tail.Overlay.Thread = PsGetCurrentThread(); + irp->Tail.Overlay.OriginalFileObject= FileObject; + irp->RequestorMode = KernelMode; + + // Indicate that this is a WRITE operation + irp->Flags = IRP_WRITE_OPERATION; + + // Set up the next I/O stack location + ioStackLocation = IoGetNextIrpStackLocation(irp); + ioStackLocation->MajorFunction = IRP_MJ_WRITE; + ioStackLocation->MinorFunction = 0; + ioStackLocation->DeviceObject = fsdDevice; + ioStackLocation->FileObject = FileObject; + IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE); + ioStackLocation->Parameters.Write.Length = Length; + ioStackLocation->Parameters.Write.ByteOffset = *Offset; + + + // Send it on. Ignore the return code + (void) IoCallDriver(fsdDevice, irp); + + // Wait for the I/O to complete. + KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); + + // Free the IRP now that we are done with it + IoFreeIrp(irp); + + return; + +} diff --git a/drivers/net/packet/functions.c b/drivers/net/packet/functions.c new file mode 100644 index 0000000..04c7e4b --- /dev/null +++ b/drivers/net/packet/functions.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef WIN32 +#include "tme.h" +#include "functions.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#include +#include +#else +#include +#include +#include +#endif + +#endif + + + +lut_fcn lut_fcn_mapper(uint32 index) +{ + + switch (index) + { + case NORMAL_LUT_W_INSERT: + return (lut_fcn) normal_lut_w_insert; + + case NORMAL_LUT_WO_INSERT: + return (lut_fcn) normal_lut_wo_insert; + + case BUCKET_LOOKUP: + return (lut_fcn) bucket_lookup; + + case BUCKET_LOOKUP_INSERT: + return (lut_fcn) bucket_lookup_insert; + + default: + return NULL; + } + + return NULL; + +} + +exec_fcn exec_fcn_mapper(uint32 index) +{ + switch (index) + { + case COUNT_PACKETS: + return (exec_fcn) count_packets; + + case TCP_SESSION: + return (exec_fcn) tcp_session; + default: + return NULL; + } + + return NULL; +} diff --git a/drivers/net/packet/functions.h b/drivers/net/packet/functions.h new file mode 100644 index 0000000..91f242a --- /dev/null +++ b/drivers/net/packet/functions.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __FUNCTIONS +#define __FUNCTIONS + +#ifdef WIN32 +#include "tme.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#else +#include +#endif + +#endif +/*function mappers */ + +lut_fcn lut_fcn_mapper(uint32 index); +exec_fcn exec_fcn_mapper(uint32 index); + +/* lookup functions */ + +#ifdef WIN32 +#include "bucket_lookup.h" +#include "normal_lookup.h" +#endif + +#ifdef __FreeBSD__ +#include +#include +#endif + +/* execution functions */ + +#ifdef WIN32 +#include "count_packets.h" +#include "tcp_session.h" +#endif + +#ifdef __FreeBSD__ +#include +#include +#endif + +#endif \ No newline at end of file diff --git a/drivers/net/packet/jitter.c b/drivers/net/packet/jitter.c new file mode 100644 index 0000000..4a71a7c --- /dev/null +++ b/drivers/net/packet/jitter.c @@ -0,0 +1,677 @@ +/* + * Copyright (c) 2002 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef _MSC_VER +#include "stdarg.h" +#include "ntddk.h" +#include "ntiologc.h" +#include "ndis.h" +#else +#include +#include +#endif + +#include "packet.h" +#include "win_bpf.h" + +emit_func emitm; + +// +// emit routine to update the jump table +// +void emit_lenght(binary_stream *stream, ULONG value, UINT len) +{ + (stream->refs)[stream->bpf_pc]+=len; + stream->cur_ip+=len; +} + +// +// emit routine to output the actual binary code +// +void emit_code(binary_stream *stream, ULONG value, UINT len) +{ + + switch (len){ + + case 1: + stream->ibuf[stream->cur_ip]=(UCHAR)value; + stream->cur_ip++; + break; + + case 2: + *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value; + stream->cur_ip+=2; + break; + + case 4: + *((ULONG*)(stream->ibuf+stream->cur_ip))=value; + stream->cur_ip+=4; + break; + + default:; + + } + + return; + +} + +// +// Function that does the real stuff +// +BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem) +{ + struct bpf_insn *ins; + UINT i, pass; + binary_stream stream; + + + // Allocate the reference table for the jumps +#ifdef NTKERNEL + stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA'); +#else + stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT)); +#endif + if(stream.refs==NULL) + { + return NULL; + } + + // Reset the reference table + for(i=0; i< nins + 1; i++) + stream.refs[i]=0; + + stream.cur_ip=0; + stream.bpf_pc=0; + + // the first pass will emit the lengths of the instructions + // to create the reference table + emitm=emit_lenght; + + for(pass=0;;){ + + ins = prog; + + /* create the procedure header */ + PUSH(EBP) + MOVrd(EBP,ESP) + PUSH(EBX) + PUSH(ECX) + PUSH(EDX) + PUSH(ESI) + PUSH(EDI) + MOVodd(EBX, EBP, 8) + + for(i=0;icode) { + + default: + + return NULL; + + case BPF_RET|BPF_K: + + MOVid(EAX,ins->k) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + RET() + + break; + + + case BPF_RET|BPF_A: + + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + RET() + + break; + + + case BPF_LD|BPF_W|BPF_ABS: + + MOVid(ECX,ins->k) + MOVrd(ESI,ECX) + ADDib(ECX,sizeof(INT)) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) //this can be optimized with xor eax,eax + RET() + MOVobd(EAX, EBX, ESI) + BSWAP(EAX) + + break; + + case BPF_LD|BPF_H|BPF_ABS: + + MOVid(ECX,ins->k) + MOVrd(ESI,ECX) + ADDib(ECX,sizeof(SHORT)) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVid(EAX,0) + MOVobw(AX, EBX, ESI) + SWAP_AX() + + break; + + case BPF_LD|BPF_B|BPF_ABS: + + MOVid(ECX,ins->k) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVid(EAX,0) + MOVobb(AL,EBX,ECX) + + break; + + case BPF_LD|BPF_W|BPF_LEN: + + MOVodd(EAX, EBP, 0xc) + + break; + + case BPF_LDX|BPF_W|BPF_LEN: + + MOVodd(EDX, EBP, 0xc) + + break; + + case BPF_LD|BPF_W|BPF_IND: + + MOVid(ECX,ins->k) + ADDrd(ECX,EDX) + MOVrd(ESI,ECX) + ADDib(ECX,sizeof(INT)) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVobd(EAX, EBX, ESI) + BSWAP(EAX) + + break; + + case BPF_LD|BPF_H|BPF_IND: + + MOVid(ECX,ins->k) + ADDrd(ECX,EDX) + MOVrd(ESI,ECX) + ADDib(ECX,sizeof(SHORT)) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVid(EAX,0) + MOVobw(AX, EBX, ESI) + SWAP_AX() + + break; + + case BPF_LD|BPF_B|BPF_IND: + + MOVid(ECX,ins->k) + ADDrd(ECX,EDX) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVid(EAX,0) + MOVobb(AL,EBX,ECX) + + break; + + case BPF_LDX|BPF_MSH|BPF_B: + + MOVid(ECX,ins->k) + CMPodd(ECX, EBP, 0x10) + JLEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVid(EDX,0) + MOVobb(DL,EBX,ECX) + ANDib(DL, 0xf) + SHLib(EDX, 2) + + break; + + case BPF_LD|BPF_IMM: + + MOVid(EAX,ins->k) + + break; + + case BPF_LDX|BPF_IMM: + + MOVid(EDX,ins->k) + + break; + + case BPF_LD|BPF_MEM: + + MOVid(ECX,(INT)mem) + MOVid(ESI,ins->k*4) + MOVobd(EAX, ECX, ESI) + + break; + + case BPF_LDX|BPF_MEM: + + MOVid(ECX,(INT)mem) + MOVid(ESI,ins->k*4) + MOVobd(EDX, ECX, ESI) + + break; + + case BPF_ST: + + // XXX: this command and the following could be optimized if the previous + // instruction was already of this type + MOVid(ECX,(INT)mem) + MOVid(ESI,ins->k*4) + MOVomd(ECX, ESI, EAX) + + break; + + case BPF_STX: + + MOVid(ECX,(INT)mem) + MOVid(ESI,ins->k*4) + MOVomd(ECX, ESI, EDX) + break; + + case BPF_JMP|BPF_JA: + + JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_JMP|BPF_JGT|BPF_K: + + CMPid(EAX, ins->k) + JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP + JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) + break; + + case BPF_JMP|BPF_JGE|BPF_K: + + CMPid(EAX, ins->k) + JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_JMP|BPF_JEQ|BPF_K: + + CMPid(EAX, ins->k) + JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_JMP|BPF_JSET|BPF_K: + + MOVrd(ECX,EAX) + ANDid(ECX,ins->k) + JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_JMP|BPF_JGT|BPF_X: + + CMPrd(EAX, EDX) + JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) + break; + + case BPF_JMP|BPF_JGE|BPF_X: + + CMPrd(EAX, EDX) + JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_JMP|BPF_JEQ|BPF_X: + + CMPrd(EAX, EDX) + JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_JMP|BPF_JSET|BPF_X: + + MOVrd(ECX,EAX) + ANDrd(ECX,EDX) + JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5) + JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]) + + break; + + case BPF_ALU|BPF_ADD|BPF_X: + + ADDrd(EAX,EDX) + + break; + + case BPF_ALU|BPF_SUB|BPF_X: + + SUBrd(EAX,EDX) + + break; + + case BPF_ALU|BPF_MUL|BPF_X: + + MOVrd(ECX,EDX) + MULrd(EDX) + MOVrd(EDX,ECX) + break; + + case BPF_ALU|BPF_DIV|BPF_X: + + CMPid(EDX, 0) + JNEb(12) + POP(EDI) + POP(ESI) + POP(EDX) + POP(ECX) + POP(EBX) + POP(EBP) + MOVid(EAX,0) + RET() + MOVrd(ECX,EDX) + MOVid(EDX,0) + DIVrd(ECX) + MOVrd(EDX,ECX) + + break; + + case BPF_ALU|BPF_AND|BPF_X: + + ANDrd(EAX,EDX) + + break; + + case BPF_ALU|BPF_OR|BPF_X: + + ORrd(EAX,EDX) + + break; + + case BPF_ALU|BPF_LSH|BPF_X: + + MOVrd(ECX,EDX) + SHL_CLrb(EAX) + + break; + + case BPF_ALU|BPF_RSH|BPF_X: + + MOVrd(ECX,EDX) + SHR_CLrb(EAX) + + break; + + case BPF_ALU|BPF_ADD|BPF_K: + + ADD_EAXi(ins->k) + + break; + + case BPF_ALU|BPF_SUB|BPF_K: + + SUB_EAXi(ins->k) + + break; + + case BPF_ALU|BPF_MUL|BPF_K: + + MOVrd(ECX,EDX) + MOVid(EDX,ins->k) + MULrd(EDX) + MOVrd(EDX,ECX) + + break; + + case BPF_ALU|BPF_DIV|BPF_K: + + MOVrd(ECX,EDX) + MOVid(EDX,0) + MOVid(ESI,ins->k) + DIVrd(ESI) + MOVrd(EDX,ECX) + + break; + + case BPF_ALU|BPF_AND|BPF_K: + + ANDid(EAX, ins->k) + + break; + + case BPF_ALU|BPF_OR|BPF_K: + + ORid(EAX, ins->k) + + break; + + case BPF_ALU|BPF_LSH|BPF_K: + + SHLib(EAX, (ins->k) & 255) + + break; + + case BPF_ALU|BPF_RSH|BPF_K: + + SHRib(EAX, (ins->k) & 255) + + break; + + case BPF_ALU|BPF_NEG: + + NEGd(EAX) + + break; + + case BPF_MISC|BPF_TAX: + + MOVrd(EDX,EAX) + + break; + + case BPF_MISC|BPF_TXA: + + MOVrd(EAX,EDX) + + break; + + + + } + + ins++; + } + + pass++; + if(pass == 2) break; + +#ifdef NTKERNEL + stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA'); +#else + stream.ibuf=(CHAR*)malloc(stream.cur_ip); +#endif + if(stream.ibuf==NULL) + { +#ifdef NTKERNEL + ExFreePool(stream.refs); +#else + free(stream.refs); +#endif + return NULL; + } + + // modify the reference table to contain the offsets and not the lengths of the instructions + for(i=1; i< nins + 1; i++) + stream.refs[i]+=stream.refs[i-1]; + + // Reset the counters + stream.cur_ip=0; + stream.bpf_pc=0; + // the second pass creates the actual code + emitm=emit_code; + + } + + // the reference table is needed only during compilation, now we can free it +#ifdef NTKERNEL + ExFreePool(stream.refs); +#else + free(stream.refs); +#endif + return (BPF_filter_function)stream.ibuf; + +} + + +JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins) +{ + JIT_BPF_Filter *Filter; + + + // Allocate the filter structure +#ifdef NTKERNEL + Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA'); +#else + Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter)); +#endif + if(Filter==NULL) + { + return NULL; + } + + // Allocate the filter's memory +#ifdef NTKERNEL + Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA'); +#else + Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT)); +#endif + if(Filter->mem==NULL) + { +#ifdef NTKERNEL + ExFreePool(Filter); +#else + free(Filter); +#endif + return NULL; + } + + // Create the binary + if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL) + { +#ifdef NTKERNEL + ExFreePool(Filter->mem); + ExFreePool(Filter); +#else + free(Filter->mem); + free(Filter); + + return NULL; +#endif + } + + return Filter; + +} + +////////////////////////////////////////////////////////////// + +void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){ + +#ifdef NTKERNEL + ExFreePool(Filter->mem); + ExFreePool(Filter->Function); + ExFreePool(Filter); +#else + free(Filter->mem); + free(Filter->Function); + free(Filter); +#endif + +} diff --git a/drivers/net/packet/jitter.h b/drivers/net/packet/jitter.h new file mode 100644 index 0000000..4f9c7fd --- /dev/null +++ b/drivers/net/packet/jitter.h @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2002 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** @ingroup NPF + * @{ + */ + +/** @defgroup NPF_include NPF structures and definitions + * @{ + */ + +// +// Registers +// +#define EAX 0 +#define ECX 1 +#define EDX 2 +#define EBX 3 +#define ESP 4 +#define EBP 5 +#define ESI 6 +#define EDI 7 + +#define AX 0 +#define CX 1 +#define DX 2 +#define BX 3 +#define SP 4 +#define BP 5 +#define SI 6 +#define DI 7 + +#define AL 0 +#define CL 1 +#define DL 2 +#define BL 3 + +/*! \brief A stream of X86 binary code.*/ +typedef struct binary_stream{ + INT cur_ip; ///< Current X86 instruction pointer. + INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter. + PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code. + PUINT refs; ///< Jumps reference table. +}binary_stream; + + +/*! \brief Prototype of a filtering function created by the jitter. + + The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter + is not among the parameters, because it is hardwired in the function. +*/ +typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT); + +/*! \brief Prototype of the emit functions. + + Different emit functions are used to create the reference table and to generate the actual filtering code. + This allows to have simpler instruction macros. + The first parameter is the stream that will receive the data. The secon one is a variable containing + the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short + or a work at a time. +*/ +typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n); + +/*! \brief Structure describing a x86 filtering program created by the jitter.*/ +typedef struct JIT_BPF_Filter{ + BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function. + PINT mem; +} +JIT_BPF_Filter; + + + + +/**************************/ +/* X86 INSTRUCTION MACROS */ +/**************************/ + +/// mov r32,i32 +#define MOVid(r32, i32) \ + emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4); + +/// mov dr32,sr32 +#define MOVrd(dr32, sr32) \ + emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1); + +/// mov dr32,sr32[off] +#define MOVodd(dr32, sr32, off) \ + emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \ + emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\ + emitm(&stream, off, 1); + +/// mov dr32,sr32[or32] +#define MOVobd(dr32, sr32, or32) \ + emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \ + emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\ + emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1); + +/// mov dr16,sr32[or32] +#define MOVobw(dr32, sr32, or32) \ + emitm(&stream, 0x66, 1); \ + emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \ + emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\ + emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1); + +/// mov dr8,sr32[or32] +#define MOVobb(dr8, sr32, or32) \ + emitm(&stream, 0x8a, 1); \ + emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\ + emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1); + +/// mov [dr32][or32],sr32 +#define MOVomd(dr32, or32, sr32) \ + emitm(&stream, 0x89, 1); \ + emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\ + emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1); + +/// bswap dr32 +#define BSWAP(dr32) \ + emitm(&stream, 0xf, 1); \ + emitm(&stream, 0x19 << 3 | dr32 , 1); + +/// xchg al,ah +#define SWAP_AX() \ + emitm(&stream, 0x86, 1); \ + emitm(&stream, 0xc4 , 1); + +/// push r32 +#define PUSH(r32) \ + emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1); + +/// pop r32 +#define POP(r32) \ + emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1); + +/// ret +#define RET() \ + emitm(&stream, 12 << 4 | 0 << 3 | 3, 1); + +/// add dr32,sr32 +#define ADDrd(dr32, sr32) \ + emitm(&stream, 0x03, 1);\ + emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1); + +/// add eax,i32 +#define ADD_EAXi(i32) \ + emitm(&stream, 0x05, 1);\ + emitm(&stream, i32, 4); + +/// add r32,i32 +#define ADDid(r32, i32) \ + emitm(&stream, 0x81, 1);\ + emitm(&stream, 24 << 3 | r32, 1);\ + emitm(&stream, i32, 4); + +/// add r32,i8 +#define ADDib(r32, i8) \ + emitm(&stream, 0x83, 1);\ + emitm(&stream, 24 << 3 | r32, 1);\ + emitm(&stream, i8, 1); + +/// sub dr32,sr32 +#define SUBrd(dr32, sr32) \ + emitm(&stream, 0x2b, 1);\ + emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1); + +/// sub eax,i32 +#define SUB_EAXi(i32) \ + emitm(&stream, 0x2d, 1);\ + emitm(&stream, i32, 4); + +/// mul r32 +#define MULrd(r32) \ + emitm(&stream, 0xf7, 1);\ + emitm(&stream, 7 << 5 | (r32 & 0x7), 1); + +/// div r32 +#define DIVrd(r32) \ + emitm(&stream, 0xf7, 1);\ + emitm(&stream, 15 << 4 | (r32 & 0x7), 1); + +/// and r8,i8 +#define ANDib(r8, i8) \ + emitm(&stream, 0x80, 1);\ + emitm(&stream, 7 << 5 | r8, 1);\ + emitm(&stream, i8, 1); + +/// and r32,i32 +#define ANDid(r32, i32) \ + if (r32 == EAX){ \ + emitm(&stream, 0x25, 1);\ + emitm(&stream, i32, 4);}\ + else{ \ + emitm(&stream, 0x81, 1);\ + emitm(&stream, 7 << 5 | r32, 1);\ + emitm(&stream, i32, 4);} + +/// and dr32,sr32 +#define ANDrd(dr32, sr32) \ + emitm(&stream, 0x23, 1);\ + emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1); + +/// or dr32,sr32 +#define ORrd(dr32, sr32) \ + emitm(&stream, 0x0b, 1);\ + emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1); + +/// or r32,i32 +#define ORid(r32, i32) \ + if (r32 == EAX){ \ + emitm(&stream, 0x0d, 1);\ + emitm(&stream, i32, 4);}\ + else{ \ + emitm(&stream, 0x81, 1);\ + emitm(&stream, 25 << 3 | r32, 1);\ + emitm(&stream, i32, 4);} + +/// shl r32,i8 +#define SHLib(r32, i8) \ + emitm(&stream, 0xc1, 1);\ + emitm(&stream, 7 << 5 | r32 & 0x7, 1);\ + emitm(&stream, i8, 1); + +/// shl dr32,cl +#define SHL_CLrb(dr32) \ + emitm(&stream, 0xd3, 1);\ + emitm(&stream, 7 << 5 | dr32 & 0x7, 1); + +/// shr r32,i8 +#define SHRib(r32, i8) \ + emitm(&stream, 0xc1, 1);\ + emitm(&stream, 29 << 3 | r32 & 0x7, 1);\ + emitm(&stream, i8, 1); + +/// shr dr32,cl +#define SHR_CLrb(dr32) \ + emitm(&stream, 0xd3, 1);\ + emitm(&stream, 29 << 3 | dr32 & 0x7, 1); + +/// neg r32 +#define NEGd(r32) \ + emitm(&stream, 0xf7, 1);\ + emitm(&stream, 27 << 3 | r32 & 0x7, 1); + +/// cmp dr32,sr32[off] +#define CMPodd(dr32, sr32, off) \ + emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \ + emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\ + emitm(&stream, off, 1); + +/// cmp dr32,sr32 +#define CMPrd(dr32, sr32) \ + emitm(&stream, 0x3b, 1); \ + emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1); + +/// cmp dr32,i32 +#define CMPid(dr32, i32) \ + if (dr32 == EAX){ \ + emitm(&stream, 0x3d, 1); \ + emitm(&stream, i32, 4);} \ + else{ \ + emitm(&stream, 0x81, 1); \ + emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\ + emitm(&stream, i32, 4);} + +/// jne off32 +#define JNEb(off8) \ + emitm(&stream, 0x75, 1);\ + emitm(&stream, off8, 1); + +/// je off32 +#define JE(off32) \ + emitm(&stream, 0x0f, 1);\ + emitm(&stream, 0x84, 1);\ + emitm(&stream, off32, 4); + +/// jle off32 +#define JLE(off32) \ + emitm(&stream, 0x0f, 1);\ + emitm(&stream, 0x8e, 1);\ + emitm(&stream, off32, 4); + +/// jle off8 +#define JLEb(off8) \ + emitm(&stream, 0x7e, 1);\ + emitm(&stream, off8, 1); + +/// ja off32 +#define JA(off32) \ + emitm(&stream, 0x0f, 1);\ + emitm(&stream, 0x87, 1);\ + emitm(&stream, off32, 4); + +/// jae off32 +#define JAE(off32) \ + emitm(&stream, 0x0f, 1);\ + emitm(&stream, 0x83, 1);\ + emitm(&stream, off32, 4); + +/// jg off32 +#define JG(off32) \ + emitm(&stream, 0x0f, 1);\ + emitm(&stream, 0x8f, 1);\ + emitm(&stream, off32, 4); + +/// jge off32 +#define JGE(off32) \ + emitm(&stream, 0x0f, 1);\ + emitm(&stream, 0x8d, 1);\ + emitm(&stream, off32, 4); + +/// jmp off32 +#define JMP(off32) \ + emitm(&stream, 0xe9, 1);\ + emitm(&stream, off32, 4); + +/** + * @} + */ + +/** + * @} + */ + +/**************************/ +/* Prototypes */ +/**************************/ + +/** @ingroup NPF + * @{ + */ + +/** @defgroup NPF_code NPF functions + * @{ + */ + +/*! + \brief BPF jitter, builds an x86 function from a BPF program. + \param fp The BPF pseudo-assembly filter that will be translated into x86 code. + \param nins Number of instructions of the input filter. + \return The JIT_BPF_Filter structure containing the x86 filtering binary. + + BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp + calling BPFtoX86(). +*/ +JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins); + +/*! + \brief Translates a set of BPF instructions in a set of x86 ones. + \param ins Pointer to the BPF instructions that will be translated into x86 code. + \param nins Number of instructions to translate. + \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor. + \return The x86 filtering function. + + This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and + through the instruction macros defined in jitter.h it is able to create an function directly executable + by NPF. +*/ +BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem); +/*! + \brief Deletes a filtering function that was previously created by BPF_jitter(). + \param Filter The filter to destroy. + + This function frees the variuos buffers (code, memory, etc.) associated with a filtering function. +*/ +void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter); + +/** + * @} + */ + +/** + * @} + */ diff --git a/drivers/net/packet/memory_t.c b/drivers/net/packet/memory_t.c new file mode 100644 index 0000000..2a02998 --- /dev/null +++ b/drivers/net/packet/memory_t.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "tme.h" +#include "memory_t.h" + + +int32 SW_LONG_AT(void *b, uint32 c) +{ + return ((int32)*((uint8 *)b+c)<<24| + (int32)*((uint8 *)b+c+1)<<16| + (int32)*((uint8 *)b+c+2)<<8| + (int32)*((uint8 *)b+c+3)<<0); +} + +uint32 SW_ULONG_AT(void *b, uint32 c) +{ + return ((uint32)*((uint8 *)b+c)<<24| + (uint32)*((uint8 *)b+c+1)<<16| + (uint32)*((uint8 *)b+c+2)<<8| + (uint32)*((uint8 *)b+c+3)<<0); +} + +int16 SW_SHORT_AT(void *b, uint32 os) +{ + return ((int16) + ((int16)*((uint8 *)b+os+0)<<8| + (int16)*((uint8 *)b+os+1)<<0)); +} + +uint16 SW_USHORT_AT(void *b, uint32 os) +{ + return ((uint16) + ((uint16)*((uint8 *)b+os+0)<<8| + (uint16)*((uint8 *)b+os+1)<<0)); +} + +VOID SW_ULONG_ASSIGN(void *dst, uint32 src) +{ + *((uint8*)dst+0)=*((uint8*)&src+3); + *((uint8*)dst+1)=*((uint8*)&src+2); + *((uint8*)dst+2)=*((uint8*)&src+1); + *((uint8*)dst+3)=*((uint8*)&src+0); + +} + +void assert(void* assert, const char* file, int line, void* msg) { }; diff --git a/drivers/net/packet/memory_t.h b/drivers/net/packet/memory_t.h new file mode 100644 index 0000000..0ecd90b --- /dev/null +++ b/drivers/net/packet/memory_t.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __memory_t +#define __memory_t + +#define uint8 UCHAR +#define int8 CHAR +#define uint16 USHORT +#define int16 SHORT +#define uint32 ULONG +#define int32 LONG +#define uint64 ULONGLONG +#define int64 LONGLONG + +/*memory type*/ +typedef struct __MEM_TYPE +{ + uint8 *buffer; + uint32 size; +} MEM_TYPE, *PMEM_TYPE; + +#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset)) + +#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset)) + +#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset)) + +#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset)) + +#ifdef __GNUC__ + +int32 SW_LONG_AT(void *b, uint32 c); +uint32 SW_ULONG_AT(void *b, uint32 c); +int16 SW_SHORT_AT(void *b, uint32 os); +uint16 SW_USHORT_AT(void *b, uint32 os); +VOID SW_ULONG_ASSIGN(void *dst, uint32 src); + +#else /* __GNUC__ */ + +__inline int32 SW_LONG_AT(void *b, uint32 c) +{ + return ((int32)*((uint8 *)b+c)<<24| + (int32)*((uint8 *)b+c+1)<<16| + (int32)*((uint8 *)b+c+2)<<8| + (int32)*((uint8 *)b+c+3)<<0); +} + +__inline uint32 SW_ULONG_AT(void *b, uint32 c) +{ + return ((uint32)*((uint8 *)b+c)<<24| + (uint32)*((uint8 *)b+c+1)<<16| + (uint32)*((uint8 *)b+c+2)<<8| + (uint32)*((uint8 *)b+c+3)<<0); +} + +__inline int16 SW_SHORT_AT(void *b, uint32 os) +{ + return ((int16) + ((int16)*((uint8 *)b+os+0)<<8| + (int16)*((uint8 *)b+os+1)<<0)); +} + +__inline uint16 SW_USHORT_AT(void *b, uint32 os) +{ + return ((uint16) + ((uint16)*((uint8 *)b+os+0)<<8| + (uint16)*((uint8 *)b+os+1)<<0)); +} + +__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src) +{ + *((uint8*)dst+0)=*((uint8*)&src+3); + *((uint8*)dst+1)=*((uint8*)&src+2); + *((uint8*)dst+2)=*((uint8*)&src+1); + *((uint8*)dst+3)=*((uint8*)&src+0); + +} + +#endif /* __GNUC__ */ + +#ifdef WIN_NT_DRIVER + +#define ALLOCATE_MEMORY(dest,type,amount) \ + (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); +#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \ + { \ + (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \ + if ((dest)!=NULL) \ + RtlZeroMemory((dest),sizeof(type)*(amount)); \ + } + +#define FREE_MEMORY(dest) ExFreePool(dest); +#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount); +#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount); + +#endif /*WIN_NT_DRIVER*/ + + +#endif + diff --git a/drivers/net/packet/normal_lookup.c b/drivers/net/packet/normal_lookup.c new file mode 100644 index 0000000..ea6442f --- /dev/null +++ b/drivers/net/packet/normal_lookup.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef WIN32 +#include "tme.h" +#include "normal_lookup.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#include +#else +#include +#include +#endif + +#endif + + +/* lookup in the table, seen as an hash */ +/* if not found, inserts an element */ +/* returns TME_TRUE if the entry is found or created, */ +/* returns TME_FALSE if no more blocks are available */ +uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref) +{ + uint32 i; + uint32 tocs=0; + uint32 *key32=(uint32*) key; + uint32 shrinked_key=0; + uint32 index; + RECORD *records=(RECORD*)data->lut_base_address; + uint8 *offset; + uint32 key_len=data->key_len; + /*the key is shrinked into a 32-bit value */ + for (i=0; ilut_entries; + + while (tocs<=data->filled_entries) + { + + if (records[index].block==0) + { /*creation of a new entry*/ + + if (data->filled_blocks==data->shared_memory_blocks) + { + /*no more free blocks*/ + GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref); + data->last_found=NULL; + return TME_FALSE; + } + + /*offset=absolute pointer to the block associated*/ + /*with the newly created entry*/ + offset=data->shared_memory_base_address+ + data->block_size*data->filled_blocks; + + /*copy the key in the block*/ + COPY_MEMORY(offset,key32,key_len*4); + GET_TIME((struct timeval *)(offset+4*key_len),time_ref); + /*assign the block relative offset to the entry, in NBO*/ + SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer); + + data->filled_blocks++; + + /*assign the exec function ID to the entry, in NBO*/ + SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec); + data->filled_entries++; + + data->last_found=(uint8*)&records[index]; + + return TME_TRUE; + } + /*offset contains the absolute pointer to the block*/ + /*associated with the current entry */ + offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0); + + for (i=0; (ilast_found=(uint8*)&records[index]; + return TME_TRUE; + } + else + { + /* wrong entry, rehashing */ + if (IS_DELETABLE(offset+key_len*4,data)) + { + ZERO_MEMORY(offset,data->block_size); + COPY_MEMORY(offset,key32,key_len*4); + SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec); + GET_TIME((struct timeval*)(offset+key_len*4),time_ref); + data->last_found=(uint8*)&records[index]; + return TME_TRUE; + } + else + { + index=(index+data->rehashing_value) % data->lut_entries; + tocs++; + } + } + } + + /* nothing found, last found= out of lut */ + GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref); + data->last_found=NULL; + return TME_FALSE; + +} + +/* lookup in the table, seen as an hash */ +/* if not found, returns out of count entry index */ +/* returns TME_TRUE if the entry is found */ +/* returns TME_FALSE if the entry is not found */ +uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref) +{ + uint32 i; + uint32 tocs=0; + uint32 *key32=(uint32*) key; + uint32 shrinked_key=0; + uint32 index; + RECORD *records=(RECORD*)data->lut_base_address; + uint8 *offset; + uint32 key_len=data->key_len; + /*the key is shrinked into a 32-bit value */ + for (i=0; ilut_entries; + + while (tocs<=data->filled_entries) + { + + if (records[index].block==0) + { /*out of table, insertion is not allowed*/ + GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref); + data->last_found=NULL; + return TME_FALSE; + } + /*offset contains the absolute pointer to the block*/ + /*associated with the current entry */ + + offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0); + + for (i=0; (ilast_found=(uint8*)&records[index]; + return TME_TRUE; + } + else + { + /*wrong entry, rehashing*/ + index=(index+data->rehashing_value) % data->lut_entries; + tocs++; + } + } + + /*nothing found, last found= out of lut*/ + GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref); + data->last_found=NULL; + return TME_FALSE; + +} diff --git a/drivers/net/packet/normal_lookup.h b/drivers/net/packet/normal_lookup.h new file mode 100644 index 0000000..c88d890 --- /dev/null +++ b/drivers/net/packet/normal_lookup.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __normal_lookup +#define __normal_lookup + +#ifdef WIN32 +#include "tme.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#else +#include +#endif + +#endif + +#define NORMAL_LUT_W_INSERT 0x00000000 +uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref); +#define NORMAL_LUT_WO_INSERT 0x00000001 +uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref); +#define DUMMY_INSERT 1234 + +#endif \ No newline at end of file diff --git a/drivers/net/packet/ntddpack.h b/drivers/net/packet/ntddpack.h new file mode 100644 index 0000000..a868cc7 --- /dev/null +++ b/drivers/net/packet/ntddpack.h @@ -0,0 +1,30 @@ +#ifndef __NTDDPACKET +#define __NTDDPACKET 1 + +#ifdef _MSC_VER +#include "devioctl.h" +/*#include */ +#else +#endif + +struct _PACKET_OID_DATA { + ULONG Oid; + ULONG Length; + UCHAR Data[1]; +}; + +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; + +/*#include */ +#define FILE_DEVICE_PROTOCOL 0x8000 +#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif diff --git a/drivers/net/packet/openclos.c b/drivers/net/packet/openclos.c new file mode 100644 index 0000000..6c857a8 --- /dev/null +++ b/drivers/net/packet/openclos.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef _MSC_VER +#include "ntddk.h" +#include "ntiologc.h" +#include "ndis.h" +#else +#include +#include +#endif +#include "debug.h" +#include "packet.h" + +static NDIS_MEDIUM MediumArray[] = { + NdisMedium802_3, + NdisMediumWan, + NdisMediumFddi, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMedium802_5 +}; + +#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0]) + +ULONG NamedEventsCounter=0; + +//Itoa. Replaces the buggy RtlIntegerToUnicodeString +void PacketItoa(UINT n,PUCHAR buf){ +int i; + + for(i=0;i<20;i+=2){ + buf[18-i]=(n%10)+48; + buf[19-i]=0; + n/=10; + } + +} + +/// Global start time. Used as an absolute reference for timestamp conversion. +struct time_conv G_Start_Time = { + 0, + {0, 0}, +}; + +UINT n_Opened_Instances = 0; + +NDIS_SPIN_LOCK Opened_Instances_Lock; + +//------------------------------------------------------------------- + +NTSTATUS +NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + + PDEVICE_EXTENSION DeviceExtension; + + POPEN_INSTANCE Open; + + PIO_STACK_LOCATION IrpSp; + + NDIS_STATUS Status; + NDIS_STATUS ErrorStatus; + UINT i; + PUCHAR tpointer; + PLIST_ENTRY PacketListEntry; + PCHAR EvName; + + + IF_LOUD(DbgPrint("NPF: OpenAdapter\n");) + + DeviceExtension = DeviceObject->DeviceExtension; + + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + // allocate some memory for the open structure + Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA'); + + + if (Open==NULL) { + // no memory + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory( + Open, + sizeof(OPEN_INSTANCE) + ); + + + EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), '1OWA'); + + if (EvName==NULL) { + // no memory + ExFreePool(Open); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Save or open here + IrpSp->FileObject->FsContext=Open; + + Open->DeviceExtension=DeviceExtension; + + + // Save the Irp here for the completeion routine to retrieve + Open->OpenCloseIrp=Irp; + + // Allocate a packet pool for our xmit and receive packets + NdisAllocatePacketPool( + &Status, + &Open->PacketPool, + TRANSMIT_PACKETS, + sizeof(PACKET_RESERVED)); + + + if (Status != NDIS_STATUS_SUCCESS) { + + IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");) + + ExFreePool(Open); + ExFreePool(EvName); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INSUFFICIENT_RESOURCES; + } + + + RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000")); + + //Create the string containing the name of the read event + RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName); + + PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21)); + + InterlockedIncrement(&NamedEventsCounter); + + IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);) + + //allocate the event objects + Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle); + if(Open->ReadEvent==NULL){ + ExFreePool(Open); + ExFreePool(EvName); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INSUFFICIENT_RESOURCES; + } + + KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE); + KeClearEvent(Open->ReadEvent); + NdisInitializeEvent(&Open->WriteEvent); + NdisInitializeEvent(&Open->IOEvent); + NdisInitializeEvent(&Open->DumpEvent); + NdisInitializeEvent(&Open->IOEvent); + NdisAllocateSpinLock(&Open->machine_lock); + + + // list to hold irp's want to reset the adapter + InitializeListHead(&Open->ResetIrpList); + + + // Initialize the request list + KeInitializeSpinLock(&Open->RequestSpinLock); + InitializeListHead(&Open->RequestList); + + // Initializes the extended memory of the NPF machine + Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA'); + if((Open->mem_ex.buffer) == NULL) + { + // no memory + ExFreePool(Open); + ExFreePool(EvName); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Open->mem_ex.size = DEFAULT_MEM_EX_SIZE; + RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE); + + // + // Initialize the open instance + // + Open->BufSize = 0; + Open->Buffer = NULL; + Open->Bhead = 0; + Open->Btail = 0; + Open->BLastByte = 0; + Open->Dropped = 0; //reset the dropped packets counter + Open->Received = 0; //reset the received packets counter + Open->Accepted = 0; //reset the accepted packets counter + Open->bpfprogram = NULL; //reset the filter + Open->mode = MODE_CAPT; + Open->Nbytes.QuadPart = 0; + Open->Npackets.QuadPart = 0; + Open->Nwrites = 1; + Open->Multiple_Write_Counter = 0; + Open->MinToCopy = 0; + Open->TimeOut.QuadPart = (LONGLONG)1; + Open->Bound = TRUE; + Open->DumpFileName.Buffer = NULL; + Open->DumpFileHandle = NULL; + Open->tme.active = TME_NONE_ACTIVE; + Open->DumpLimitReached = FALSE; + + //allocate the spinlock for the statistic counters + NdisAllocateSpinLock(&Open->CountersLock); + + //allocate the spinlock for the buffer pointers + NdisAllocateSpinLock(&Open->BufLock); + + // + // link up the request stored in our open block + // + for (i=0;iRequestList, + &Open->Requests[i].ListElement, + &Open->RequestSpinLock); + + } + + + IoMarkIrpPending(Irp); + + // + // Try to open the MAC + // + IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);) + + NdisOpenAdapter( + &Status, + &ErrorStatus, + &Open->AdapterHandle, + &Open->Medium, + MediumArray, + NUM_NDIS_MEDIA, + DeviceExtension->NdisProtocolHandle, + Open, + &DeviceExtension->AdapterName, + 0, + NULL); + + IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);) + + if (Status != NDIS_STATUS_PENDING) + { + NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS); + } + + return(STATUS_PENDING); +} + +//------------------------------------------------------------------- + +VOID NPF_OpenAdapterComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus) +{ + + PIRP Irp; + POPEN_INSTANCE Open; + + IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + // + // get the open irp + // + Irp=Open->OpenCloseIrp; + + if (Status != NDIS_STATUS_SUCCESS) { + + IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");) + + NdisFreePacketPool(Open->PacketPool); + + //free mem_ex + Open->mem_ex.size = 0; + if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer); + + ExFreePool(Open->ReadEventName.Buffer); + + ExFreePool(Open); + } + else { + NdisAcquireSpinLock(&Opened_Instances_Lock); + n_Opened_Instances++; + NdisReleaseSpinLock(&Opened_Instances_Lock); + + IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);) + + // Get the absolute value of the system boot time. + // This is used for timestamp conversion. + TIME_SYNCHRONIZE(&G_Start_Time); + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return; + +} + +//------------------------------------------------------------------- + +NTSTATUS +NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) +{ + + POPEN_INSTANCE Open; + NDIS_STATUS Status; + PIO_STACK_LOCATION IrpSp; + LARGE_INTEGER ThreadDelay; + + IF_LOUD(DbgPrint("NPF: CloseAdapter\n");) + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Open=IrpSp->FileObject->FsContext; + + // Reset the buffer size. This tells the dump thread to stop. + Open->BufSize = 0; + + if( Open->Bound == FALSE){ + + NdisWaitEvent(&Open->IOEvent,10000); + + // Free the filter if it's present + if(Open->bpfprogram != NULL) + ExFreePool(Open->bpfprogram); + + // Free the jitted filter if it's present + if(Open->Filter != NULL) + BPF_Destroy_JIT_Filter(Open->Filter); + + //free the buffer + Open->BufSize=0; + if(Open->Buffer != NULL)ExFreePool(Open->Buffer); + + //free mem_ex + Open->mem_ex.size = 0; + if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer); + + NdisFreePacketPool(Open->PacketPool); + + // Free the string with the name of the dump file + if(Open->DumpFileName.Buffer!=NULL) + ExFreePool(Open->DumpFileName.Buffer); + + ExFreePool(Open->ReadEventName.Buffer); + ExFreePool(Open); + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); + } + + // Unfreeze the consumer + if(Open->mode & MODE_DUMP) + NdisSetEvent(&Open->DumpEvent); + else + KeSetEvent(Open->ReadEvent,0,FALSE); + + // Save the IRP + Open->OpenCloseIrp = Irp; + + IoMarkIrpPending(Irp); + + // If this instance is in dump mode, complete the dump and close the file + if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){ +#ifndef __GNUC__ + NTSTATUS wres; + + ThreadDelay.QuadPart = -50000000; + // Wait the completion of the thread + wres = KeWaitForSingleObject(Open->DumpThreadObject, + UserRequest, + KernelMode, + TRUE, + &ThreadDelay); + + ObDereferenceObject(Open->DumpThreadObject); + + + // Flush and close the dump file + NPF_CloseDumpFile(Open); +#endif + } + + // Destroy the read Event + ZwClose(Open->ReadEventHandle); + + // Close the adapter + NdisCloseAdapter( + &Status, + Open->AdapterHandle + ); + + if (Status != NDIS_STATUS_PENDING) { + + NPF_CloseAdapterComplete( + Open, + Status + ); + return STATUS_SUCCESS; + + } + + return(STATUS_PENDING); +} + +//------------------------------------------------------------------- + +VOID +NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status) +{ + POPEN_INSTANCE Open; + PIRP Irp; + + IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + // free the allocated structures only if the instance is still bound to the adapter + if(Open->Bound == TRUE){ + + // Free the filter if it's present + if(Open->bpfprogram != NULL) + ExFreePool(Open->bpfprogram); + + // Free the jitted filter if it's present + if(Open->Filter != NULL) + BPF_Destroy_JIT_Filter(Open->Filter); + + //free the buffer + Open->BufSize = 0; + if(Open->Buffer!=NULL)ExFreePool(Open->Buffer); + + //free mem_ex + Open->mem_ex.size = 0; + if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer); + + NdisFreePacketPool(Open->PacketPool); + + Irp=Open->OpenCloseIrp; + + // Free the string with the name of the dump file + if(Open->DumpFileName.Buffer!=NULL) + ExFreePool(Open->DumpFileName.Buffer); + + ExFreePool(Open->ReadEventName.Buffer); + ExFreePool(Open); + + // Complete the request only if the instance is still bound to the adapter + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + else + NdisSetEvent(&Open->IOEvent); + + // Decrease the counter of open instances + NdisAcquireSpinLock(&Opened_Instances_Lock); + n_Opened_Instances--; + NdisReleaseSpinLock(&Opened_Instances_Lock); + + IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);) + + if(n_Opened_Instances == 0){ + // Force a synchronization at the next NPF_Open(). + // This hopefully avoids the synchronization issues caused by hibernation or standby. + TIME_DESYNCHRONIZE(&G_Start_Time); + } + + return; + +} +//------------------------------------------------------------------- + +#ifdef NDIS50 +NDIS_STATUS +NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent) +{ + IF_LOUD(DbgPrint("NPF: PowerChange\n");) + + TIME_DESYNCHRONIZE(&G_Start_Time); + + TIME_SYNCHRONIZE(&G_Start_Time); + + return STATUS_SUCCESS; +} +#endif + +//------------------------------------------------------------------- + +VOID +NPF_BindAdapter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE BindContext, + IN PNDIS_STRING DeviceName, + IN PVOID SystemSpecific1, + IN PVOID SystemSpecific2 + ) +{ + IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");) +} + +//------------------------------------------------------------------- + +VOID +NPF_UnbindAdapter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE UnbindContext + ) +{ + POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext; + NDIS_STATUS lStatus; + + IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");) + + // Reset the buffer size. This tells the dump thread to stop. + Open->BufSize=0; + + NdisResetEvent(&Open->IOEvent); + + // This open instance is no more bound to the adapter, set Bound to False + InterlockedExchange( (PLONG) &Open->Bound, FALSE ); + + // Awake a possible pending read on this instance + if(Open->mode & MODE_DUMP) + NdisSetEvent(&Open->DumpEvent); + else + KeSetEvent(Open->ReadEvent,0,FALSE); + + // If this instance is in dump mode, complete the dump and close the file + if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL) + NPF_CloseDumpFile(Open); + + // Destroy the read Event + ZwClose(Open->ReadEventHandle); + + // close the adapter + NdisCloseAdapter( + &lStatus, + Open->AdapterHandle + ); + + if (lStatus != NDIS_STATUS_PENDING) { + + NPF_CloseAdapterComplete( + Open, + lStatus + ); + + *Status = NDIS_STATUS_SUCCESS; + return; + + } + + *Status = NDIS_STATUS_SUCCESS; + return; +} + +//------------------------------------------------------------------- + +VOID +NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status) + +{ + POPEN_INSTANCE Open; + PIRP Irp; + + PLIST_ENTRY ResetListEntry; + + IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + + // + // remove the reset IRP from the list + // + ResetListEntry=ExInterlockedRemoveHeadList( + &Open->ResetIrpList, + &Open->RequestSpinLock + ); + +#if DBG + if (ResetListEntry == NULL) { + DbgBreakPoint(); + return; + } +#endif + + Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");) + + return; + +} diff --git a/drivers/net/packet/packet.c b/drivers/net/packet/packet.c new file mode 100644 index 0000000..1891a8a --- /dev/null +++ b/drivers/net/packet/packet.c @@ -0,0 +1,1332 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef _MSC_VER +#include "stdarg.h" +#include "ntddk.h" +#include "ntiologc.h" +#include "ndis.h" +#else +#include +#include +#endif + +#include "ntddpack.h" + +#include "debug.h" +#include "packet.h" +#include "win_bpf.h" +#include "win_bpf_filter_init.h" + +#include "tme.h" + +#if DBG +// Declare the global debug flag for this driver. +//ULONG PacketDebugFlag = PACKET_DEBUG_LOUD; +ULONG PacketDebugFlag = PACKET_DEBUG_LOUD + PACKET_DEBUG_VERY_LOUD + PACKET_DEBUG_INIT; + +#endif + +PDEVICE_EXTENSION GlobalDeviceExtension; + +//////////////////////////////////////////////////////////////////////////////// +#define ROBERTS_PATCH +#ifdef ROBERTS_PATCH + +#define NDIS_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x} + +//void __moddi3(void) {} +//void __divdi3(void) {} + +#endif // ROBERTS_PATCH +//////////////////////////////////////////////////////////////////////////////// +// +// Global strings +// +NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_"); +NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\"); +NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\"); +NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System" + L"\\CurrentControlSet\\Services\\Tcpip\\Linkage"); +NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System" + L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"); +NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind"); + + +/// Global variable that points to the names of the bound adapters +WCHAR* bindP = NULL; + +extern struct time_conv G_Start_Time; // from openclos.c + +extern NDIS_SPIN_LOCK Opened_Instances_Lock; + +// +// Packet Driver's entry routine. +// +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +{ + + NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar; + UNICODE_STRING MacDriverName; + UNICODE_STRING UnicodeDeviceName; + PDEVICE_OBJECT DeviceObject = NULL; + PDEVICE_EXTENSION DeviceExtension = NULL; + NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS ErrorCode = STATUS_SUCCESS; + NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver"); + ULONG DevicesCreated=0; + PWSTR BindString; + PWSTR ExportString; + PWSTR BindStringSave; + PWSTR ExportStringSave; + NDIS_HANDLE NdisProtocolHandle; + WCHAR* bindT; + PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP; + UNICODE_STRING macName; + + // This driver at the moment works only on single processor machines + if(NdisSystemProcessorCount() != 1){ + return STATUS_IMAGE_MP_UP_MISMATCH; + } + + IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");) + + RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); + +#ifdef NDIS50 + ProtocolChar.MajorNdisVersion = 5; +#else + ProtocolChar.MajorNdisVersion = 3; +#endif + ProtocolChar.MinorNdisVersion = 0; +#ifndef __GNUC__ + ProtocolChar.Reserved = 0; +#endif + ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete; + ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete; +#ifndef __GNUC__ + ProtocolChar.SendCompleteHandler = NPF_SendComplete; + ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete; +#endif + ProtocolChar.ResetCompleteHandler = NPF_ResetComplete; + ProtocolChar.RequestCompleteHandler = NPF_RequestComplete; +#ifndef __GNUC__ + ProtocolChar.ReceiveHandler = NPF_tap; +#endif + ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete; + ProtocolChar.StatusHandler = NPF_Status; + ProtocolChar.StatusCompleteHandler = NPF_StatusComplete; +#ifdef NDIS50 + ProtocolChar.BindAdapterHandler = NPF_BindAdapter; + ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter; + ProtocolChar.PnPEventHandler = NPF_PowerChange; + ProtocolChar.ReceivePacketHandler = NULL; +#endif + ProtocolChar.Name = ProtoName; + + NdisRegisterProtocol( + &Status, + &NdisProtocolHandle, + &ProtocolChar, + sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); + + if (Status != NDIS_STATUS_SUCCESS) { + + IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");) + + return Status; + + } + + NdisAllocateSpinLock(&Opened_Instances_Lock); + + // Set up the device driver entry points. + DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close; + DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read; + DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl; + DriverObject->DriverUnload = NPF_Unload; + + // Get the name of the Packet driver and the name of the NIC driver + // to bind to from the registry + Status=NPF_ReadRegistry( + &BindString, + &ExportString, + RegistryPath + ); + + if (Status != STATUS_SUCCESS) { + + IF_LOUD(DbgPrint("Trying dynamic binding\n");) + + bindP = getAdaptersList(); + + if (bindP == NULL) { + IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");) + + tcpBindingsP = getTcpBindings(); + + if (tcpBindingsP == NULL){ + IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");) + goto RegistryError; + } + + bindP = (WCHAR*)tcpBindingsP; + bindT = (WCHAR*)(tcpBindingsP->Data); + } else { + bindT = bindP; + + } + + for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) { + RtlInitUnicodeString(&macName, bindT); + createDevice(DriverObject, &macName, NdisProtocolHandle); + } + + return STATUS_SUCCESS; + + } + + BindStringSave = BindString; + ExportStringSave = ExportString; + + + // + // create a device object for each entry + // + while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) { + // + // Create a counted unicode string for both null terminated strings + // + RtlInitUnicodeString( + &MacDriverName, + BindString + ); + + RtlInitUnicodeString( + &UnicodeDeviceName, + ExportString + ); + + // + // Advance to the next string of the MULTI_SZ string + // + BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR); + + ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR); + + IF_LOUD(DbgPrint("NPF: DeviceName=%ws MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);) + + // + // Create the device object + // + Status = IoCreateDevice( + DriverObject, + sizeof(DEVICE_EXTENSION), + &UnicodeDeviceName, + FILE_DEVICE_PROTOCOL, + 0, + FALSE, + &DeviceObject + ); + + if (Status != STATUS_SUCCESS) { + IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");) + + break; + } + + DevicesCreated++; + + + DeviceObject->Flags |= DO_DIRECT_IO; + DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; + DeviceExtension->DeviceObject = DeviceObject; + + // + // Save the the name of the MAC driver to open in the Device Extension + // + + DeviceExtension->AdapterName=MacDriverName; + + if (DevicesCreated == 1) { + + DeviceExtension->BindString = NULL; + DeviceExtension->ExportString = NULL; + } + + + DeviceExtension->NdisProtocolHandle=NdisProtocolHandle; + + + } + + if (DevicesCreated > 0) { + // + // Managed to create at least one device. + // + IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");) + return STATUS_SUCCESS; + } + + + + ExFreePool(BindStringSave); + ExFreePool(ExportStringSave); + +RegistryError: + IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");) + NdisDeregisterProtocol( + &Status, + NdisProtocolHandle + ); + + Status=STATUS_UNSUCCESSFUL; + + return(Status); + +} + +//------------------------------------------------------------------- + +PWCHAR getAdaptersList(void) +{ + PKEY_VALUE_PARTIAL_INFORMATION result = NULL; + OBJECT_ATTRIBUTES objAttrs; + NTSTATUS status; + HANDLE keyHandle; + UINT BufPos=0; + + PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, '0PWA'); + + if (DeviceNames == NULL) { + IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");) + return NULL; + } + + InitializeObjectAttributes(&objAttrs, &AdapterListKey, + OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs); + if (!NT_SUCCESS(status)) { + IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);) + } else { //OK + ULONG resultLength; + KEY_VALUE_PARTIAL_INFORMATION valueInfo; + CHAR AdapInfo[1024]; + UINT i=0; + + IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);) + + // Scan the list of the devices + while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS) { + WCHAR ExportKeyName [512]; + PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"; + UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"); + PWCHAR LinkageKeyPrefix = L"\\Linkage"; + UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage"); + NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export"); + PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo; + UNICODE_STRING AdapterKeyName; + HANDLE ExportKeyHandle; + KEY_VALUE_PARTIAL_INFORMATION valueInfo; + ULONG resultLength; + + RtlCopyMemory(ExportKeyName, + ExportKeyPrefix, + ExportKeyPrefixSize); + + RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize, + tInfo->Name, + tInfo->NameLength+2); + + RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength, + LinkageKeyPrefix, + LinkageKeyPrefixSize); + + IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);) + + RtlInitUnicodeString(&AdapterKeyName, ExportKeyName); + + InitializeObjectAttributes(&objAttrs, &AdapterKeyName, + OBJ_CASE_INSENSITIVE, NULL, NULL); + + status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs); + + if (!NT_SUCCESS(status)) { + DbgPrint("OpenKey Failed, %d!\n",status); + i++; + continue; + } + + status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey, + KeyValuePartialInformation, &valueInfo, + sizeof(valueInfo), &resultLength); + + if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) { + IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);) + } else { // We know how big it needs to be. + ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]); + PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA'); + if (valueInfoP != NULL) { + status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey, + KeyValuePartialInformation, + valueInfoP, + valueInfoLength, &resultLength); + if (!NT_SUCCESS(status)) { + IF_LOUD(DbgPrint("Status of %x querying key value\n", status);) + } else { + IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);) + RtlCopyMemory((PCHAR)DeviceNames+BufPos, + valueInfoP->Data, + valueInfoP->DataLength); + BufPos+=valueInfoP->DataLength-2; + } + + ExFreePool(valueInfoP); + } else { + IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");) + } + + } + + // terminate the buffer + DeviceNames[BufPos/2]=0; + DeviceNames[BufPos/2+1]=0; + + ZwClose (ExportKeyHandle); + i++; + + } + + ZwClose (keyHandle); + + } + if(BufPos==0){ + ExFreePool(DeviceNames); + return NULL; + } + return DeviceNames; +} + +//------------------------------------------------------------------- + +PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void) +{ + PKEY_VALUE_PARTIAL_INFORMATION result = NULL; + OBJECT_ATTRIBUTES objAttrs; + NTSTATUS status; + HANDLE keyHandle; + + InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName, + OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs); + if (!NT_SUCCESS(status)) { + IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);) + } else { + ULONG resultLength; + KEY_VALUE_PARTIAL_INFORMATION valueInfo; + + IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);) + + status = ZwQueryValueKey(keyHandle, &bindValueName, + KeyValuePartialInformation, &valueInfo, + sizeof(valueInfo), &resultLength); + if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) { + IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);) + } else { // We know how big it needs to be. + ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]); + PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = + (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA'); + + if (valueInfoP != NULL) { + status = ZwQueryValueKey(keyHandle, &bindValueName, + KeyValuePartialInformation, + valueInfoP, + valueInfoLength, &resultLength); + + if (!NT_SUCCESS(status)) { + IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);) + } + else if (valueInfoLength != resultLength) { + IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u " + "but previous len = %u\n", + resultLength, valueInfoLength);) + } + else if (valueInfoP->Type != REG_MULTI_SZ) { + IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n", + valueInfoP->Type);) + } + else { // It's OK +#if DBG + ULONG i; + WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]); + IF_LOUD(DbgPrint("\n\nBind value:\n");) + for (i = 0; *dataP != UNICODE_NULL; i++) { + UNICODE_STRING macName; + RtlInitUnicodeString(&macName, dataP); + IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);) + dataP += + (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR); + } +#endif // DBG + result = valueInfoP; + } + } + } + ZwClose(keyHandle); + } + return result; +} + +//------------------------------------------------------------------- + +BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP, + IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle) +{ + NTSTATUS status; + PDEVICE_OBJECT devObjP; + UNICODE_STRING deviceName; + BOOLEAN result = FALSE; + + IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer);) + if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer, + devicePrefix.Length) < devicePrefix.Length) { + return result; + } + + deviceName.Length = 0; + deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL)); + deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA'); + + if (deviceName.Buffer != NULL) { + RtlAppendUnicodeStringToString(&deviceName, &devicePrefix); + RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix); + RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer + + devicePrefix.Length / sizeof(WCHAR)); + + IF_LOUD(DbgPrint("\n\nDevice name: %ws\n", deviceName.Buffer);) + + status = IoCreateDevice(adriverObjectP, sizeof(PDEVICE_EXTENSION), + &deviceName, FILE_DEVICE_TRANSPORT, 0, FALSE, + &devObjP); + + if (NT_SUCCESS(status)) { + PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension; + + IF_LOUD(DbgPrint("\n\nDevice created succesfully\n");) + + devObjP->Flags |= DO_DIRECT_IO; + + devExtP->DeviceObject = devObjP; + RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer); + devExtP->BindString = NULL; + devExtP->ExportString = NULL; + devExtP->NdisProtocolHandle=aProtoHandle; + + } + + else IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status);); + + ExFreePool(deviceName.Buffer); + } + + return result; +} + +//------------------------------------------------------------------- + +VOID +NPF_Unload(IN PDRIVER_OBJECT DriverObject) +{ + + PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT OldDeviceObject; + PDEVICE_EXTENSION DeviceExtension; + + NDIS_HANDLE NdisProtocolHandle; + NDIS_STATUS Status; + + IF_LOUD(DbgPrint("NPF: Unload\n");) + + + DeviceObject = DriverObject->DeviceObject; + + while (DeviceObject != NULL) { + DeviceExtension = DeviceObject->DeviceExtension; + + NdisProtocolHandle=DeviceExtension->NdisProtocolHandle; + OldDeviceObject=DeviceObject; + + DeviceObject=DeviceObject->NextDevice; + + IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n", + DeviceExtension->AdapterName.Buffer, + NdisProtocolHandle, + DeviceObject, + OldDeviceObject);) + + IoDeleteDevice(OldDeviceObject); + + } + + NdisDeregisterProtocol( + &Status, + NdisProtocolHandle + ); + + // Free the adapters names + ExFreePool( bindP ); + +} + +//------------------------------------------------------------------- + +NTSTATUS +NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) +{ + POPEN_INSTANCE Open; + PIO_STACK_LOCATION IrpSp; + PLIST_ENTRY RequestListEntry; + PINTERNAL_REQUEST pRequest; + ULONG FunctionCode; + NDIS_STATUS Status; + PLIST_ENTRY PacketListEntry; + UINT i; + PUCHAR tpointer; + ULONG dim,timeout; + PUCHAR prog; + PPACKET_OID_DATA OidData; + int *StatsBuf; + PNDIS_PACKET pPacket; + ULONG mode; + PWSTR DumpNameBuff; + PUCHAR TmpBPFProgram; + INT WriteRes; + BOOLEAN SyncWrite = FALSE; + struct bpf_insn *initprogram; + ULONG insns; + ULONG cnt; + BOOLEAN IsExtendedFilter=FALSE; + + IF_LOUD(DbgPrint("NPF: IoControl\n");) + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode; + Open=IrpSp->FileObject->FsContext; + + Irp->IoStatus.Status = STATUS_SUCCESS; + + IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);) + + + switch (FunctionCode){ + + case BIOCGSTATS: //function to get the capture stats + + if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){ + EXIT_FAILURE(0); + } + + *(((PUINT)Irp->UserBuffer)+3) = Open->Accepted; + *(((PUINT)Irp->UserBuffer)) = Open->Received; + *(((PUINT)Irp->UserBuffer)+1) = Open->Dropped; + *(((PUINT)Irp->UserBuffer)+2) = 0; // Not yet supported + + EXIT_SUCCESS(4*sizeof(INT)); + + break; + + case BIOCGEVNAME: //function to get the name of the event associated with the current instance + + if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){ + EXIT_FAILURE(0); + } + + RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26); + + EXIT_SUCCESS(26); + + break; + + case BIOCSENDPACKETSSYNC: + + SyncWrite = TRUE; + + case BIOCSENDPACKETSNOSYNC: + + WriteRes = NPF_BufferedWrite(Irp, + (PUCHAR)Irp->AssociatedIrp.SystemBuffer, + IrpSp->Parameters.DeviceIoControl.InputBufferLength, + SyncWrite); + + if( WriteRes != -1) + { + EXIT_SUCCESS(WriteRes); + } + + EXIT_FAILURE(WriteRes); + + break; + + case BIOCSETF: + + // Free the previous buffer if it was present + if(Open->bpfprogram!=NULL){ + TmpBPFProgram=Open->bpfprogram; + Open->bpfprogram = NULL; + ExFreePool(TmpBPFProgram); + } + + if (Open->Filter!=NULL) + { + JIT_BPF_Filter *OldFilter=Open->Filter; + Open->Filter=NULL; + BPF_Destroy_JIT_Filter(OldFilter); + } + + // Get the pointer to the new program + prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer; + + if(prog==NULL){ + IF_LOUD(DbgPrint("0001");) + + EXIT_FAILURE(0); + } + + insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn); + + //count the number of operative instructions + for (cnt=0;(cntmem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK) + { + + IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");) + + EXIT_FAILURE(0); + } + } + + //the NPF processor has been initialized, we have to validate the operative instructions + insns=cnt; + + if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0) + { + IF_LOUD(DbgPrint("Error validating program");) + //FIXME: the machine has been initialized(?), but the operative code is wrong. + //we have to reset the machine! + //something like: reallocate the mem_ex, and reset the tme_core + EXIT_FAILURE(0); + } + + // Allocate the memory to contain the new filter program + // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers() + TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA'); + if (TmpBPFProgram==NULL){ + IF_LOUD(DbgPrint("Error - No memory for filter");) + // no memory + EXIT_FAILURE(0); + } + + //copy the program in the new buffer + RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn)); + Open->bpfprogram=TmpBPFProgram; + + // Create the new JIT filter function + + if(!IsExtendedFilter) + if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) + == NULL) + { + IF_LOUD(DbgPrint("Error jittering filter");) + EXIT_FAILURE(0); + } + + //return + Open->Bhead = 0; + Open->Btail = 0; + Open->BLastByte = 0; + Open->Received = 0; + Open->Dropped = 0; + + EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength); + + break; + + case BIOCSMODE: //set the capture mode + + mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer); + + if(mode == MODE_CAPT){ + Open->mode=MODE_CAPT; + + EXIT_SUCCESS(0); + } + else if (mode==MODE_MON){ + Open->mode=MODE_MON; + + EXIT_SUCCESS(0); + } + else{ + if(mode & MODE_STAT){ + Open->mode = MODE_STAT; + Open->Nbytes.QuadPart=0; + Open->Npackets.QuadPart=0; + + if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000; + + } + + if(mode & MODE_DUMP){ + + Open->mode |= MODE_DUMP; + Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000; + + } + EXIT_SUCCESS(0); + } + + EXIT_FAILURE(0); + + break; + + case BIOCSETDUMPFILENAME: + + if(Open->mode & MODE_DUMP) + { + + // Close current dump file + if(Open->DumpFileHandle != NULL){ + NPF_CloseDumpFile(Open); + Open->DumpFileHandle = NULL; + } + + if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){ + EXIT_FAILURE(0); + } + + // Allocate the buffer that will contain the string + DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA'); + if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){ + IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");) + EXIT_FAILURE(0); + } + + // Copy the buffer + RtlCopyBytes((PVOID)DumpNameBuff, + Irp->AssociatedIrp.SystemBuffer, + IrpSp->Parameters.DeviceIoControl.InputBufferLength); + + // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system + ((SHORT*)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0; + + // Create the unicode string + RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff); + + IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n", + Open->DumpFileName.Buffer, + IrpSp->Parameters.DeviceIoControl.InputBufferLength);) + + // Try to create the file + if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) && + NT_SUCCESS( NPF_StartDump(Open))){ + + EXIT_SUCCESS(0); + } + } + + EXIT_FAILURE(0); + + break; + + case BIOCSETDUMPLIMITS: + + Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer; + Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1); + + IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);) + + EXIT_SUCCESS(0); + + break; + + case BIOCISDUMPENDED: + if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){ + EXIT_FAILURE(0); + } + + *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0; + + EXIT_SUCCESS(4); + + break; + + case BIOCSETBUFFERSIZE: + + // Get the number of bytes to allocate + dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer); + + // Free the old buffer + tpointer = Open->Buffer; + if(tpointer != NULL){ + Open->BufSize = 0; + Open->Buffer = NULL; + ExFreePool(tpointer); + } + // Allocate the new buffer + if(dim!=0){ + tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA'); + if (tpointer==NULL) { + // no memory + Open->BufSize = 0; + Open->Buffer = NULL; + EXIT_FAILURE(0); + } + } + else + tpointer = NULL; + + Open->Buffer = tpointer; + Open->Bhead = 0; + Open->Btail = 0; + Open->BLastByte = 0; + + Open->BufSize = (UINT)dim; + EXIT_SUCCESS(dim); + + break; + + case BIOCSRTIMEOUT: //set the timeout on the read calls + + timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer); + if((int)timeout==-1) + Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE; + else { + Open->TimeOut.QuadPart=(LONGLONG)timeout; + Open->TimeOut.QuadPart*=10000; + Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart; + } + + //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);) + EXIT_SUCCESS(timeout); + + break; + + case BIOCSWRITEREP: //set the writes repetition number + + Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer); + + EXIT_SUCCESS(Open->Nwrites); + + break; + + case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application + + Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer); + + EXIT_SUCCESS(Open->MinToCopy); + + break; + + case IOCTL_PROTOCOL_RESET: + + IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");) + + IoMarkIrpPending(Irp); + Irp->IoStatus.Status = STATUS_SUCCESS; + + ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock); + NdisReset(&Status,Open->AdapterHandle); + if (Status != NDIS_STATUS_PENDING) { + IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");) + NPF_ResetComplete(Open,Status); + } + + break; + + + case BIOCSETOID: + case BIOCQUERYOID: + + // Extract a request from the list of free ones + RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock); + if (RequestListEntry == NULL) + { + EXIT_FAILURE(0); + } + + pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement); + pRequest->Irp=Irp; + + // + // See if it is an Ndis request + // + OidData=Irp->AssociatedIrp.SystemBuffer; + + if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID)) + && + (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength) + && + (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)) + && + (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) { + + IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);) + + // + // The buffer is valid + // + if (FunctionCode == BIOCSETOID){ + + pRequest->Request.RequestType=NdisRequestSetInformation; + pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid; + + pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data; + pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length; + } else{ + pRequest->Request.RequestType=NdisRequestQueryInformation; + pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid; + + pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data; + pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length; + + } + + NdisResetEvent(&Open->IOEvent); + // + // submit the request + // + NdisRequest( + &Status, + Open->AdapterHandle, + &pRequest->Request + ); + + } else { + // + // buffer too small + // + Status=NDIS_STATUS_FAILURE; + pRequest->Request.DATA.SET_INFORMATION.BytesRead=0; + pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0; + + } + + if (Status != NDIS_STATUS_PENDING) { + IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");) + + NPF_RequestComplete(Open, &pRequest->Request, Status); + return Status; + + } + + NdisWaitEvent(&Open->IOEvent, 5000); + + return(Open->IOStatus); + + break; + + + default: + + EXIT_FAILURE(0); + } + + return Status; +} + +//------------------------------------------------------------------- + +VOID +NPF_RequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status + ) + +{ + POPEN_INSTANCE Open; + PIO_STACK_LOCATION IrpSp; + PIRP Irp; + PINTERNAL_REQUEST pRequest; + UINT FunctionCode; + KIRQL OldIrq; + + PPACKET_OID_DATA OidData; + + IF_LOUD(DbgPrint("NPF: RequestComplete\n");) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request); + Irp=pRequest->Irp; + + if(Irp == NULL){ + + // Put the request in the list of the free ones + ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock); + + return; + } + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode; + + OidData=Irp->AssociatedIrp.SystemBuffer; + + if (FunctionCode == BIOCSETOID) { + + OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead; + + } else { + + if (FunctionCode == BIOCQUERYOID) { + + OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten; + + IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);) + } + + } + + Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength; + + IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);) + + ExInterlockedInsertTailList( + &Open->RequestList, + &pRequest->ListElement, + &Open->RequestSpinLock); + + Irp->IoStatus.Status = Status; + + Open->IOStatus = Status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // Unlock the IOCTL call + NdisSetEvent(&Open->IOEvent); + + return; + + +} + +//------------------------------------------------------------------- + +VOID +NPF_Status( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ) + +{ + + IF_LOUD(DbgPrint("NPF: Status Indication\n");) + + return; + +} + +//------------------------------------------------------------------- + +VOID +NPF_StatusComplete( + IN NDIS_HANDLE ProtocolBindingContext + ) + +{ + + IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");) + + return; + +} + +//------------------------------------------------------------------- + +NTSTATUS +NPF_ReadRegistry( + IN PWSTR *MacDriverName, + IN PWSTR *PacketDriverName, + IN PUNICODE_STRING RegistryPath + ) + +{ + NTSTATUS Status; + + RTL_QUERY_REGISTRY_TABLE ParamTable[4]; + + PWSTR Bind = L"Bind"; + PWSTR Export = L"Export"; + PWSTR Parameters = L"Parameters"; + PWSTR Linkage = L"Linkage"; + + PWCHAR Path; + + Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA'); + + if (Path == NULL) { + IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");) + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory( + Path, + RegistryPath->Length+sizeof(WCHAR) + ); + + RtlCopyMemory( + Path, + RegistryPath->Buffer, + RegistryPath->Length + ); + + IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);) + + RtlZeroMemory( + ParamTable, + sizeof(ParamTable) + ); + + + + // + // change to the linkage key + // + //ParamTable[0].QueryRoutine = NULL; + ParamTable[0].QueryRoutine = NPF_QueryRegistryRoutine; + ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; + ParamTable[0].Name = Linkage; + + + // + // Get the name of the mac driver we should bind to + // + + ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine; + ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_NOEXPAND; + + ParamTable[1].Name = Bind; + ParamTable[1].EntryContext = (PVOID)MacDriverName; + ParamTable[1].DefaultType = REG_MULTI_SZ; + + // + // Get the name that we should use for the driver object + // + + ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine; + ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_NOEXPAND; + + ParamTable[2].Name = Export; + ParamTable[2].EntryContext = (PVOID)PacketDriverName; + ParamTable[2].DefaultType = REG_MULTI_SZ; + + + Status=RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + Path, + ParamTable, + NULL, + NULL + ); + + if (Status != STATUS_SUCCESS) { + // insert hard coded parameters here while registry on ROS is not working... + IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");) + + *MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR)); + //memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR)); + memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR)); + + *PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR)); + memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR)); + Status = STATUS_SUCCESS; + + } + + ExFreePool(Path); + return Status; +} + +//------------------------------------------------------------------- + +NTSTATUS +NPF_QueryRegistryRoutine( + IN PWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength, + IN PVOID Context, + IN PVOID EntryContext + ) + +{ + + PUCHAR Buffer; + + IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");) + + if (ValueType != REG_MULTI_SZ) { + + return STATUS_OBJECT_NAME_NOT_FOUND; + + } + + Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA'); + + if (Buffer==NULL) { + + return STATUS_INSUFFICIENT_RESOURCES; + + } + + RtlCopyMemory( + Buffer, + ValueData, + ValueLength + ); + + *((PUCHAR *)EntryContext)=Buffer; + + return STATUS_SUCCESS; + +} diff --git a/drivers/net/packet/packet.def b/drivers/net/packet/packet.def new file mode 100644 index 0000000..3517ee3 --- /dev/null +++ b/drivers/net/packet/packet.def @@ -0,0 +1,8 @@ +; packet capture driver - ReactOS Operating System + +LIBRARY PACKET.SYS + +EXPORTS +DriverEntry@8 + +; EOF diff --git a/drivers/net/packet/packet.edf b/drivers/net/packet/packet.edf new file mode 100644 index 0000000..11994e4 --- /dev/null +++ b/drivers/net/packet/packet.edf @@ -0,0 +1,8 @@ +; PACKET.SYS - PACKET protocol driver + +LIBRARY packet.sys + +EXPORTS +DriverEntry=DriverEntry@8 + +; EOF diff --git a/drivers/net/packet/packet.h b/drivers/net/packet/packet.h new file mode 100644 index 0000000..18dfcb1 --- /dev/null +++ b/drivers/net/packet/packet.h @@ -0,0 +1,957 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** @ingroup NPF + * @{ + */ + +/** @defgroup NPF_include NPF structures and definitions + * @{ + */ + +#ifndef __PACKET_INCLUDE______ +#define __PACKET_INCLUDE______ + +#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls + +#define UNICODE_NULL ((WCHAR)0) // winnt + +#include "win_bpf.h" + +#include "jitter.h" +#include "tme.h" + +#define MAX_REQUESTS 32 ///< Maximum number of simultaneous IOCTL requests. + +#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size. +#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next + ///< even multiple of Packet_ALIGNMENT. +/***************************/ +/* IOCTLs */ +/***************************/ + +/*! + \brief IOCTL code: set kernel buffer size. + + This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF. + When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one + and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently + buffered packets are lost. +*/ +#define BIOCSETBUFFERSIZE 9592 + +/*! + \brief IOCTL code: set packet filtering program. + + This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the + bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE, + the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the + OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to + every incoming packet. This command also empties the circular buffer used by current instance + to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter. +*/ +#define BIOCSETF 9030 + +/*! + \brief IOCTL code: get the capture stats + + This command returns to the application the number of packets received and the number of packets dropped by + an instance of the driver. +*/ +#define BIOCGSTATS 9031 + +/*! + \brief IOCTL code: set the read timeout + + This command sets the maximum timeout after which a read is released, also if no data packets were received. +*/ +#define BIOCSRTIMEOUT 7416 + +/*! + \brief IOCTL code: set working mode + + This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the + buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for + statistical mode or #MODE_DUMP for dump mode. +*/ +#define BIOCSMODE 7412 + +/*! + \brief IOCTL code: set number of physical repetions of every packet written by the app + + Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites + member, and is used to implement the 'multiple write' feature of the driver. +*/ +#define BIOCSWRITEREP 7413 + +/*! + \brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call + + This command sets the OPEN_INSTANCE::MinToCopy member. +*/ +#define BIOCSMINTOCOPY 7414 + +/*! + \brief IOCTL code: set an OID value + + This IOCTL is used to perform an OID set operation on the NIC driver. +*/ +#define BIOCSETOID 2147483648 + +/*! + \brief IOCTL code: get an OID value + + This IOCTL is used to perform an OID get operation on the NIC driver. +*/ +#define BIOCQUERYOID 2147483652 + +/*! + \brief IOCTL code: set the name of a the file used by kernel dump mode + + This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance. + The dump thread uses it to copy the content of the circular buffer to file. + If a file was already opened, the driver closes it before opening the new one. +*/ +#define BIOCSETDUMPFILENAME 9029 + +/*! + \brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer + + Command used by the application to retrieve the name of the global event associated with a NPF instance. + The event is signaled by the driver when the kernel buffer contains enough data for a transfer. +*/ +#define BIOCGEVNAME 7415 + +/*! + \brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps. + + Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by + a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as + possible. The NPF_BufferedWrite() function is invoked to send the packets. +*/ +#define BIOCSENDPACKETSNOSYNC 9032 + +/*! + \brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps. + + Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by + a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets + are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each + packet. NPF_BufferedWrite() function is invoked to send the packets. +*/ +#define BIOCSENDPACKETSSYNC 9033 + +/*! + \brief IOCTL code: Set the dump file limits. + + This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the + driver works in dump mode. +*/ +#define BIOCSETDUMPLIMITS 9034 + +/*! + \brief IOCTL code: Get the status of the kernel dump process. + + This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS + (amount of bytes or number of packets) has been reached. +*/ +#define BIOCISDUMPENDED 7411 + +// Working modes +#define MODE_CAPT 0x0 ///< Capture working mode +#define MODE_STAT 0x1 ///< Statistical working mode +#define MODE_MON 0x2 ///< Kernel monitoring mode +#define MODE_DUMP 0x10 ///< Kernel dump working mode + + +#define IMMEDIATE 1 ///< Immediate timeout. Forces a read call to return immediately. + + +// The following definitions are used to provide compatibility +// of the dump files with the ones of libpcap +#define TCPDUMP_MAGIC 0xa1b2c3d4 ///< Libpcap magic number. Used by programs like tcpdump to recognize a driver's generated dump file. +#define PCAP_VERSION_MAJOR 2 ///< Major libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file. +#define PCAP_VERSION_MINOR 4 ///< Minor libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file. + +/*! + \brief Header of a libpcap dump file. + + Used when a driver instance is set in dump mode to create a libpcap-compatible file. +*/ +struct packet_file_header +{ + UINT magic; ///< Libpcap magic number + USHORT version_major; ///< Libpcap major version + USHORT version_minor; ///< Libpcap minor version + UINT thiszone; ///< Gmt to local correction + UINT sigfigs; ///< Accuracy of timestamps + UINT snaplen; ///< Length of the max saved portion of each packet + UINT linktype; ///< Data link type (DLT_*). See win_bpf.h for details. +}; + +/*! + \brief Header associated to a packet in the driver's buffer when the driver is in dump mode. + Similar to the bpf_hdr structure, but simpler. +*/ +struct sf_pkthdr { + struct timeval ts; ///< time stamp + UINT caplen; ///< Length of captured portion. The captured portion can be different from + ///< the original packet, because it is possible (with a proper filter) to + ///< instruct the driver to capture only a portion of the packets. + UINT len; ///< Length of the original packet (off wire). +}; + +/*! + \brief Stores an OID request. + + This structure is used by the driver to perform OID query or set operations on the underlying NIC driver. + The OID operations be performed usually only by network drivers, but NPF exports this mechanism to user-level + applications through an IOCTL interface. The driver uses this structure to wrap a NDIS_REQUEST structure. + This allows to handle correctly the callback structure of NdisRequest(), handling multiple requests and + maintaining information about the IRPs to complete. +*/ +typedef struct _INTERNAL_REQUEST { + LIST_ENTRY ListElement; ///< Used to handle lists of requests. + PIRP Irp; ///< Irp that performed the request + NDIS_REQUEST Request; ///< The structure with the actual request, that will be passed to NdisRequest(). +} INTERNAL_REQUEST, *PINTERNAL_REQUEST; + +/*! + \brief Contains a NDIS packet. + + The driver uses this structure to wrap a NDIS_PACKET structure. + This allows to handle correctly the callback structure of NdisTransferData(), handling multiple requests and + maintaining information about the IRPs to complete. +*/ +typedef struct _PACKET_RESERVED { + LIST_ENTRY ListElement; ///< Used to handle lists of packets. + PIRP Irp; ///< Irp that performed the request + PMDL pMdl; ///< MDL mapping the buffer of the packet. + BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed + ///< after a call to NdisSend(). +} PACKET_RESERVED, *PPACKET_RESERVED; + +#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED + +/*! + \brief Port device extension. + + Structure containing some data relative to every adapter on which NPF is bound. +*/ +typedef struct _DEVICE_EXTENSION { + PDEVICE_OBJECT DeviceObject; ///< Adapter's device. + NDIS_HANDLE NdisProtocolHandle; ///< NDIS handle of NPF. + NDIS_STRING AdapterName; ///< Name of the adapter. + PWSTR BindString; ///< Original device name of the adapter. + PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use + ///< to open this adapter through WinPcap. +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +/*! + \brief Contains the state of a running instance of the NPF driver. + + This is the most important structure of NPF: it is used by almost all the functions of the driver. An + _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access + to the driver. +*/ +typedef struct _OPEN_INSTANCE +{ + PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which + ///< the instance is bound. + NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance. + UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the + ///< documentation of NdisOpenAdapter in the MS DDK for details. + NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver. + PIRP OpenCloseIrp; ///< Pointer used to store the open/close IRP requests and provide them to the + ///< callbacks of NDIS. + KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests. + LIST_ENTRY RequestList; ///< List of pending OID requests. + LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests. + INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request. + PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory. + PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait. + HANDLE ReadEventHandle; ///< Handle of the event on which the read calls on this instance must wait. + UNICODE_STRING ReadEventName; ///< Name of the event on which the read calls on this instance must wait. + ///< The event is created with a name, so it can be used at user level to know when it + ///< is possible to access the driver without being blocked. This fiels stores the name + ///< that and is used by the BIOCGEVNAME IOCTL call. + INT Received; ///< Number of packets received by current instance from its opening, i.e. number of + ///< packet received by the network adapter since the beginning of the + ///< capture/monitoring/dump session. + INT Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet + ///< is dropped if there is no more space to store it in the circular buffer that the + ///< driver associates to current instance. + INT Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet + ///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the + ///< ones that reach the application. + PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver. + ///< This code is used only in particular situations (for example when the packet received + ///< from the NIC driver is stored in two non-consecutive buffers. In normal situations + ///< the filtering routine created by the JIT compiler and pointed by the next field + ///< is used. See \ref NPF for details on the filtering process. + JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter. + ///< See BPF_jitter() for details. + PUCHAR Buffer; ///< Pointer to the circular buffer associated with every driver instance. It contains the + ///< data that will be passed to the application. See \ref NPF for details. + UINT Bhead; ///< Head of the circular buffer. + UINT Btail; ///< Tail of the circular buffer. + UINT BufSize; ///< Size of the circular buffer. + UINT BLastByte; ///< Position of the last valid byte in the circular buffer. + PMDL TransferMdl; ///< MDL used to map the portion of the buffer that will contain an incoming packet. + ///< Used by NdisTransferData(). + NDIS_SPIN_LOCK BufLock; ///< SpinLock that protects the access tho the circular buffer variables. + UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the + ///< BIOCSMINTOCOPY IOCTL. + LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is + ///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL. + + int mode; ///< Working mode of the driver. See PacketSetMode() for details. + LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode. + LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode. + NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters. + UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an + ///< explanation + UINT Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated. + NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process. + NDIS_EVENT IOEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS. + NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application. + BOOLEAN Bound; ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be + ///< FALSE if a Plug and Play adapter has been removed or disabled by the user. + HANDLE DumpFileHandle; ///< Handle of the file used in dump mode. + PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode. +// PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode. + HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk. + NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode. + LARGE_INTEGER DumpOffset; ///< Current offset in the dump file. + UNICODE_STRING DumpFileName; ///< String containing the name of the dump file. + UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it + ///< will be closed. A value of 0 means unlimited size. + UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of + ///< packets is reached the dump will be closed. A value of 0 means unlimited number of + ///< packets. + BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is + ///< reached. + MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor + TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor + NDIS_SPIN_LOCK machine_lock; ///< SpinLock that protects the mem_ex buffer +} OPEN_INSTANCE, *POPEN_INSTANCE; + + +#define TRANSMIT_PACKETS 256 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number + ///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets. + +#ifdef __GNUC__ +#undef EXIT_SUCCESS +#undef EXIT_FAILURE +#endif + +/// Macro used in the I/O routines to return the control to user-mode with a success status. +#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\ +Irp->IoStatus.Status = STATUS_SUCCESS;\ +IoCompleteRequest(Irp, IO_NO_INCREMENT);\ +return STATUS_SUCCESS;\ + +/// Macro used in the I/O routines to return the control to user-mode with a failure status. +#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\ +Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\ +IoCompleteRequest(Irp, IO_NO_INCREMENT);\ +return STATUS_UNSUCCESSFUL;\ + +/** + * @} + */ + + +/***************************/ +/* Prototypes */ +/***************************/ + +/** @defgroup NPF_code NPF functions + * @{ + */ + + +/*! + \brief The initialization routine of the driver. + \param DriverObject The driver object of NPF created by the system. + \param RegistryPath The registry path containing the keys related to the driver. + \return A string containing a list of network adapters. + + DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called + by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver, + performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O + callbacks, creates the devices, defines NPF as a protocol inside NDIS. +*/ +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ); + +/*! + \brief Returns the list of the MACs available on the system. + \return A string containing a list of network adapters. + + The list of adapters is retrieved from the + SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key. + NPF tries to create its bindings from this list. In this way it is possible to be loaded + and unloaded dynamically without passing from the control panel. +*/ +PWCHAR getAdaptersList(VOID); + +/*! + \brief Returns the MACs that bind to TCP/IP. + \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound. + + If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function. +*/ +PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID); + +/*! + \brief Creates a device for a given MAC. + \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF. + \param amacNameP The name of the network interface that the device will point. + \param aProtoHandle NDIS protocol handle of NPF. + \return If the function succeeds, the return value is nonzero. + + NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains + information about the original device. In this way, when the user opens the new device, NPF will be able to + determine the correct adapter to use. +*/ +BOOLEAN createDevice( + IN OUT PDRIVER_OBJECT adriverObjectP, + IN PUNICODE_STRING amacNameP, + NDIS_HANDLE aProtoHandle); + +/*! + \brief Opens a new instance of the driver. + \param DeviceObject Pointer to the device object utilized by the user. + \param Irp Pointer to the IRP containing the user request. + \return The status of the operation. See ntstatus.h in the DDK. + + This function is called by the OS when a new instance of the driver is opened, i.e. when a user application + performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects + and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the + adapter with a call to NdisOpenAdapter. +*/ +NTSTATUS +NPF_Open( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +/*! + \brief Ends the opening of an adapter. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + \param Status Status of the opening operation performed by NDIS. + \param OpenErrorStatus not used by NPF. + + Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC + driver has finished an open operation that was previously started by NPF_Open(). +*/ +VOID +NPF_OpenAdapterComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus + ); + +/*! + \brief Closes an instance of the driver. + \param DeviceObject Pointer to the device object utilized by the user. + \param Irp Pointer to the IRP containing the user request. + \return The status of the operation. See ntstatus.h in the DDK. + + This function is called when a running instance of the driver is closed by the user with a CloseHandle(). + It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the + instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter. +*/ +NTSTATUS +NPF_Close( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +/*! + \brief Ends the closing of an adapter. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + \param Status Status of the close operation performed by NDIS. + + Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC + driver has finished a close operation that was previously started by NPF_Close(). +*/ +VOID +NPF_CloseAdapterComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +/*! + \brief Callback invoked by NDIS when a packet arrives from the network. + \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies + the NPF instance to which the packets are destined. + \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request. + This value must be used when the packet is transferred from the NIC driver with NdisTransferData(). + \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet. + \param HeaderBufferSize Size in bytes of the header. + \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's + data available to NPF. This value does not necessarily coincide with the actual size of the packet, + since only a portion can be available at this time. The remaining portion can be obtained with the + NdisTransferData() NDIS function. + \param LookaheadBufferSize Size in bytes of the lookahead buffer. + \param PacketSize Total size of the incoming packet, excluded the header. + \return The status of the operation. See ntstatus.h in the DDK. + + NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of + the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in + statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function, + along with the filtering ones, that is executed for every incoming packet, therefore it is carefully + optimized. +*/ +NDIS_STATUS +NPF_tap( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookAheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize + ); + +/*! + \brief Ends the transfer of a packet. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + \param Packet Pointer to the NDIS_PACKET structure that received the packet data. + \param Status Status of the transfer operation. + \param BytesTransferred Amount of bytes transferred. + + Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC + driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer. +*/ +VOID +NPF_TransferDataComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred + ); + +/*! + \brief Callback function that signals the end of a packet reception. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + + does nothing in NPF +*/ +VOID +NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext); + +/*! + \brief Handles the IOCTL calls. + \param DeviceObject Pointer to the device object utilized by the user. + \param Irp Pointer to the IRP containing the user request. + \return The status of the operation. See ntstatus.h in the DDK. + + Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands + using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF. + The following commands are recognized: + - #BIOCSETBUFFERSIZE + - #BIOCSETF + - #BIOCGSTATS + - #BIOCSRTIMEOUT + - #BIOCSMODE + - #BIOCSWRITEREP + - #BIOCSMINTOCOPY + - #BIOCSETOID + - #BIOCQUERYOID + - #BIOCSETDUMPFILENAME + - #BIOCGEVNAME + - #BIOCSENDPACKETSSYNC + - #BIOCSENDPACKETSNOSYNC +*/ +NTSTATUS +NPF_IoControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + + +/*! + \brief Ends an OID request. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + \param pRequest Pointer to the completed OID request. + \param Status Status of the operation. + + Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC + driver has finished an OID request operation that was previously started by NPF_IoControl(). +*/ +VOID +NPF_RequestComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST pRequest, + IN NDIS_STATUS Status + ); + +/*! + \brief Writes a raw packet to the network. + \param DeviceObject Pointer to the device object on which the user wrote the packet. + \param Irp Pointer to the IRP containing the user request. + \return The status of the operation. See ntstatus.h in the DDK. + + This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must + be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and + delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure + associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the + packet can be sent for performance reasons. +*/ +NTSTATUS +NPF_Write( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + + +/*! + \brief Writes a buffer of raw packets to the network. + \param Irp Pointer to the IRP containing the user request. + \param UserBuff Pointer to the buffer containing the packets to send. + \param UserBuffSize Size of the buffer with the packets. + \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an + error occurred during the send. The error can be caused by an adapter problem or by an + inconsistent/bogus user buffer. + + This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL. + The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a + sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function. + When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function. + This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision + of some microseconds (depending on the precision of the performance counter of the machine). + If Sync is false, the timestamps are ignored and the packets are sent as fat as possible. +*/ + +INT NPF_BufferedWrite(IN PIRP Irp, + IN PCHAR UserBuff, + IN ULONG UserBuffSize, + BOOLEAN sync); + +/*! + \brief Ends a send operation. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + \param pRequest Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet. + \param Status Status of the operation. + + Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC + driver has finished an OID request operation that was previously started by NPF_Write(). +*/ +VOID +NPF_SendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET pPacket, + IN NDIS_STATUS Status + ); + +/*! + \brief Ends a reset of the adapter. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance. + \param Status Status of the operation. + + Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC + driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET + command. +*/ +VOID +NPF_ResetComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status + ); + +/*! + \brief Callback for NDIS StatusHandler. Not used by NPF +*/ +VOID +NPF_Status( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize + ); + + +/*! + \brief Callback for NDIS StatusCompleteHandler. Not used by NPF +*/ +VOID +NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext); + +/*! + \brief Function called by the OS when NPF is unloaded. + \param DriverObject The driver object of NPF created by the system. + + This is the last function executed when the driver is unloaded from the system. It frees global resources, + delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF + service (from control panel or with a console 'net stop npf'). +*/ +VOID +NPF_Unload(IN PDRIVER_OBJECT DriverObject); + + +/*! + \brief Function that serves the user's reads. + \param DeviceObject Pointer to the device used by the user. + \param Irp Pointer to the IRP containing the user request. + \return The status of the operation. See ntstatus.h in the DDK. + + This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the + kernel buffer to the user buffer associated with Irp. + First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance. + - If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes, + NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the + user is not blocking. + - If the buffer contains less than MinToCopy bytes, the application's request isn't + satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net + or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field. + - If the instance is in statistical mode or in dump mode, the application's request is blocked until the + timeout kept in OPEN_INSTANCE::TimeOut expires. +*/ +NTSTATUS +NPF_Read( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +/*! + \brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel. + + Normally not used in recent versions of NPF. +*/ +NTSTATUS +NPF_ReadRegistry( + IN PWSTR *MacDriverName, + IN PWSTR *PacketDriverName, + IN PUNICODE_STRING RegistryPath + ); + +/*! + \brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver + is manually installed via the control panel. + + Normally not used in recent versions of NPF. +*/ +NTSTATUS +NPF_QueryRegistryRoutine( + IN PWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength, + IN PVOID Context, + IN PVOID EntryContext + ); + +/*! + \brief Callback for NDIS BindAdapterHandler. Not used by NPF. + + Function called by NDIS when a new adapter is installed on the machine With Plug and Play. +*/ +VOID NPF_BindAdapter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE BindContext, + IN PNDIS_STRING DeviceName, + IN PVOID SystemSpecific1, + IN PVOID SystemSpecific2 + ); + +/*! + \brief Callback for NDIS UnbindAdapterHandler. + \param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation. + \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance. + \param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration. + + Function called by NDIS when a new adapter is removed from the machine without shutting it down. + NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures + associated with it. It also releases the waiting user-level app and closes the dump thread if the instance + is in dump mode. +*/ +VOID +NPF_UnbindAdapter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE UnbindContext + ); + +/*! + \brief Validates a filtering program arriving from the user-level app. + \param f The filter. + \param len Its length, in pseudo instructions. + \param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory + \return true if f is a valid filter program.. + + The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily + crash the system. + This function returns true if f is a valid filter program. The constraints are that each jump be forward and + to a valid code. The code must terminate with either an accept or reject. +*/ +int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size); + +/*! + \brief The filtering pseudo-machine interpreter. + \param pc The filter. + \param p Pointer to a memory buffer containing the packet on which the filter will be executed. + \param wirelen Original length of the packet. + \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM + has not yet finished), bpf_filter can be executed on a portion of the packet. + \param mem_ex The extended memory. + \param tme The virtualization of the TME co-processor + \param time_ref Data structure needed by the TME co-processor to timestamp data + \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that + the whole packet must be kept. + + \note this function is not used in normal situations, because the jitter creates a native filtering function + that is faster than the interpreter. +*/ +UINT bpf_filter(register struct bpf_insn *pc, + register UCHAR *p, + UINT wirelen, + register UINT buflen, + PMEM_TYPE mem_ex, + PTME_CORE tme, + struct time_conv *time_ref); + +/*! + \brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(), + but works correctly also if the MAC header and the data of the packet are in two different buffers. + \param pc The filter. + \param p Pointer to a memory buffer containing the MAC header of the packet. + \param pd Pointer to a memory buffer containing the data of the packet. + \param wirelen Original length of the packet. + \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM + has not yet finished), bpf_filter can be executed on a portion of the packet. + \param mem_ex The extended memory. + \param tme The virtualization of the TME co-processor + \param time_ref Data structure needed by the TME co-processor to timestamp data + \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that + the whole packet must be kept. + + This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one. +*/ +UINT bpf_filter_with_2_buffers(register struct bpf_insn *pc, + register UCHAR *p, + register UCHAR *pd, + register int headersize, + UINT wirelen, + register UINT buflen, + PMEM_TYPE mem_ex, + PTME_CORE tme, + struct time_conv *time_ref); + +/*! + \brief Creates the file that will receive the packets when the driver is in dump mode. + \param Open The NPF instance that opens the file. + \param fileName Pointer to a UNICODE string containing the name of the file. + \param append Boolean value that specifies if the data must be appended to the file. + \return The status of the operation. See ntstatus.h in the DDK. +*/ +NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append); + +/*! + \brief Starts dump to file. + \param Open The NPF instance that opens the file. + \return The status of the operation. See ntstatus.h in the DDK. + + This function performs two operations. First, it writes the libpcap header at the beginning of the file. + Second, it starts the thread that asynchronously dumps the network data to the file. +*/ +NTSTATUS NPF_StartDump(POPEN_INSTANCE Open); + +/*! + \brief The dump thread. + \param Open The NPF instance that creates the thread. + + This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower + priority than the TAP. +*/ +VOID NPF_DumpThread(POPEN_INSTANCE Open); + +/*! + \brief Saves the content of the packet buffer to the file associated with current instance. + \param Open The NPF instance that creates the thread. + + Used by NPF_DumpThread() and NPF_CloseDumpFile(). +*/ +NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open); + +/*! + \brief Writes a block of packets on the dump file. + \param FileObject The file object that will receive the packets. + \param Offset The offset in the file where the packets will be put. + \param Length The amount of bytes to write. + \param Mdl MDL mapping the memory buffer that will be written to disk. + \param IoStatusBlock Used by the function to return the status of the operation. + \return The status of the operation. See ntstatus.h in the DDK. + + NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion + of the NPF circular buffer to disk. This function is used by NPF_DumpThread(). +*/ +VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject, + PLARGE_INTEGER Offset, + ULONG Length, + PMDL Mdl, + PIO_STATUS_BLOCK IoStatusBlock); + + + +/*! + \brief Closes the dump file associated with an instance of the driver. + \param Open The NPF instance that closes the file. + \return The status of the operation. See ntstatus.h in the DDK. +*/ +NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open); + +/*! + \brief Returns the amount of bytes present in the packet buffer. + \param Open The NPF instance that closes the file. +*/ +UINT GetBuffOccupation(POPEN_INSTANCE Open); + +/*! + \brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change. + + \param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig + events. + \param pNetPnPEvent Pointer to the PnP event + + If there is a power state change, the driver is forced to resynchronize the global timer. + This hopefully avoids the synchronization issues caused by hibernation or standby. + This function is excluded from the NT4 driver, where PnP is not supported +*/ +#ifdef NDIS50 +NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent); +#endif + +/** + * @} + */ + +/** + * @} + */ + +#endif /*main ifndef/define*/ + diff --git a/drivers/net/packet/packet.rc b/drivers/net/packet/packet.rc new file mode 100644 index 0000000..47f2b3d --- /dev/null +++ b/drivers/net/packet/packet.rc @@ -0,0 +1,47 @@ +//#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3,0,0,13 + PRODUCTVERSION 3,0,0,13 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x3L + FILESUBTYPE 0x7L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Netgroup Packet Filter Driver\0" + VALUE "CompanyName", "Politecnico di Torino\0" + VALUE "FileDescription", "NPF Driver - TME extensions\0" + VALUE "FileVersion", "3, 0, 0, 13\0" + VALUE "InternalName", "NPF + TME \0" + VALUE "LegalCopyright", "Copyright © 2002\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "NPF.RC\0" + VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0" + VALUE "ProductName", "NPF Driver\0" + VALUE "ProductVersion", "3, 0, 0, 13\0" + VALUE "SpecialBuild", "Beta testing use only\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +///////////////////////////////////////////////////////////////////////////// + + diff --git a/drivers/net/packet/read.c b/drivers/net/packet/read.c new file mode 100644 index 0000000..fc82870 --- /dev/null +++ b/drivers/net/packet/read.c @@ -0,0 +1,664 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef _MSC_VER +#include +#include +#include +#include +#else +#include +#include +#endif + +#include "debug.h" +#include "packet.h" +#include "win_bpf.h" + +#include "tme.h" +#include "time_calls.h" + +extern struct time_conv G_Start_Time; // from openclos.c + +//------------------------------------------------------------------- + +UINT GetBuffOccupation(POPEN_INSTANCE Open) +{ + UINT Occupation; + + NdisAcquireSpinLock( &Open->BufLock ); + + if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead; + else Occupation = Open->BLastByte-Open->Bhead+Open->Btail; + + NdisReleaseSpinLock( &Open->BufLock ); + + return Occupation; +} + +//------------------------------------------------------------------- + +void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT *Bhead) +{ +ULONG WordLength; +UINT n,i,NBlocks; + + WordLength=Length>>2; + NBlocks=WordLength>>8; + + for(n=0;nFileObject->FsContext; + + if( Open->Bound == FALSE ){ + // The Network adapter was removed. + EXIT_FAILURE(0); + } + + if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){ + // this instance is in dump mode, but the dump file has still not been opened + EXIT_FAILURE(0); + } + + //See if the buffer is full enough to be copied + if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP ) + { + //wait until some packets arrive or the timeout expires + if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE) + KeWaitForSingleObject(Open->ReadEvent, + UserRequest, + KernelMode, + TRUE, + (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut)); + + KeClearEvent(Open->ReadEvent); + + if(Open->mode & MODE_STAT){ //this capture instance is in statistics mode + CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress); + + //fill the bpf header for this packet + header=(struct bpf_hdr*)CurrBuff; + GET_TIME(&header->bh_tstamp,&G_Start_Time); + + if(Open->mode & MODE_DUMP){ + *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart; + header->bh_caplen=24; + header->bh_datalen=24; + Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr); + } + else{ + header->bh_caplen=16; + header->bh_datalen=16; + header->bh_hdrlen=sizeof(struct bpf_hdr); + Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr); + } + + *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart; + *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart; + + //reset the countetrs + NdisAcquireSpinLock( &Open->CountersLock ); + Open->Npackets.QuadPart=0; + Open->Nbytes.QuadPart=0; + NdisReleaseSpinLock( &Open->CountersLock ); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; + } + + if(Open->mode==MODE_MON) //this capture instance is in monitor mode + { + PTME_DATA data; + ULONG cnt; + ULONG block_size; + PUCHAR tmp; + + UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress); + + if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Lengthbh_tstamp,&G_Start_Time); + + + header->bh_hdrlen=sizeof(struct bpf_hdr); + + + //moves user memory pointer + UserPointer+=sizeof(struct bpf_hdr); + + //calculus of data to be copied + //if the user buffer is smaller than data to be copied, + //only some data will be copied + data=&Open->tme.block_data[Open->tme.active_read]; + + if (data->last_read.tv_sec!=0) + data->last_read=header->bh_tstamp; + + + bytecopy=data->block_size*data->filled_blocks; + + if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size; + else + bytecopy=data->filled_blocks; + + tmp=data->shared_memory_base_address; + block_size=data->block_size; + + for (cnt=0;cntmachine_lock); + RtlCopyMemory(UserPointer,tmp,block_size); + NdisReleaseSpinLock(&Open->machine_lock); + tmp+=block_size; + UserPointer+=block_size; + } + + bytecopy*=block_size; + + header->bh_caplen=bytecopy; + header->bh_datalen=header->bh_caplen; + + EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr)); + } + + if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP) + // The timeout has expired, but the buffer is still empty (or the packets must be written to file). + // We must awake the application, returning an empty buffer. + { + EXIT_SUCCESS(0); + } + + } + + // + // The buffer if full enough to be copied, + // + NdisAcquireSpinLock( &Open->BufLock ); + + Thead = Open->Bhead; + Ttail = Open->Btail; + TLastByte = Open->BLastByte; + + //get the address of the buffer + CurrBuff=Open->Buffer; + + NdisReleaseSpinLock( &Open->BufLock ); + + Input_Buffer_Length=IrpSp->Parameters.Read.Length; + packp=(PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress); + + + // + //fill the application buffer + // + if(Ttail > Thead){ //first of all see if it we can copy all the buffer in one time + if((Ttail-Thead)ReadEvent); + + PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead)); + EXIT_SUCCESS(Ttail-Thead); + } + } + else if((TLastByte - Thead) < Input_Buffer_Length){ + PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead)); + + NdisAcquireSpinLock( &Open->BufLock ); + + Open->BLastByte = Open->Btail; + Open->Bhead = 0; + + NdisReleaseSpinLock( &Open->BufLock ); + + EXIT_SUCCESS(TLastByte-Thead); + } + + //the buffer must be scannned to determine the number of bytes to copy + CpStart=Thead; + i=0; + while(TRUE){ + if(Thead == Ttail)break; + + if(Thead == TLastByte){ + // Copy the portion between thead and TLastByte + PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead)); + packp+=(Thead-CpStart); + + NdisAcquireSpinLock( &Open->BufLock ); + + Open->BLastByte = Open->Btail; + Open->Bhead = 0; + + NdisReleaseSpinLock( &Open->BufLock ); + + Thead=0; + CpStart=0; + } + cplen=((struct bpf_hdr*)(CurrBuff+Thead))->bh_caplen+sizeof(struct bpf_hdr); + + if((i+cplen > Input_Buffer_Length)){//no more space in the application's buffer + PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead)); + + EXIT_SUCCESS(i); + } + cplen=Packet_WORDALIGN(cplen); + i+=cplen; + Thead+=cplen; + } + + + KeResetEvent(Open->ReadEvent); + + PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead)); + + Open->Bhead=Thead; + + + EXIT_SUCCESS(i); +} + +//------------------------------------------------------------------- + +NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer, + IN UINT LookaheadBufferSize,IN UINT PacketSize) +{ + POPEN_INSTANCE Open; + PNDIS_PACKET pPacketb; + ULONG SizeToTransfer; + NDIS_STATUS Status; + UINT BytesTransfered; + ULONG BufferLength; + PMDL pMdl; + LARGE_INTEGER CapTime; + LARGE_INTEGER TimeFreq; + struct bpf_hdr *header; + PUCHAR CurrBuff; + UINT Thead; + UINT Ttail; + UINT TLastByte; + UINT fres; + UINT maxbufspace; + USHORT NPFHdrSize; + UINT BufOccupation; + + IF_VERY_LOUD(DbgPrint("NPF: tap\n");) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + Open->Received++; // Number of packets received by filter ++ + + BufOccupation = GetBuffOccupation(Open); // Get the full buffer space + + if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){ + // Heuristic that drops the packet also if it possibly fits in the buffer. + // It allows to avoid filtering in critical situations when CPU is very important. + Open->Dropped++; + return NDIS_STATUS_NOT_ACCEPTED; + } + + NdisAcquireSpinLock(&Open->machine_lock); + + // + //Check if the lookahead buffer follows the mac header. + //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is + //executed on the packet. + //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or + //things like this) bpf_filter_with_2_buffers() is executed. + // + if((UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize) + fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram), + HeaderBuffer, + LookAheadBuffer, + HeaderBufferSize, + PacketSize+HeaderBufferSize, + LookaheadBufferSize+HeaderBufferSize, + &Open->mem_ex, + &Open->tme, + &G_Start_Time); + + + else + if(Open->Filter != NULL) + { + if (Open->bpfprogram != NULL) + { + fres=Open->Filter->Function(HeaderBuffer, + PacketSize+HeaderBufferSize, + LookaheadBufferSize+HeaderBufferSize); + + // Restore the stack. + // I ignore the reason, but this instruction is needed only at kernel level +#ifndef __GNUC__ + _asm add esp,12 +#else +#endif + } + else + fres = -1; + } + else + fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram), + HeaderBuffer, + PacketSize+HeaderBufferSize, + LookaheadBufferSize+HeaderBufferSize, + &Open->mem_ex, + &Open->tme, + &G_Start_Time); + + NdisReleaseSpinLock(&Open->machine_lock); + + if(Open->mode==MODE_MON) + // we are in monitor mode + { + if (fres==1) + KeSetEvent(Open->ReadEvent,0,FALSE); + return NDIS_STATUS_NOT_ACCEPTED; + + } + + if(fres==0) + // Packet not accepted by the filter, ignore it. + return NDIS_STATUS_NOT_ACCEPTED; + + //if the filter returns -1 the whole packet must be accepted + if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize; + + if(Open->mode & MODE_STAT){ + // we are in statistics mode + NdisAcquireSpinLock( &Open->CountersLock ); + + Open->Npackets.QuadPart++; + + if(PacketSize+HeaderBufferSize<60) + Open->Nbytes.QuadPart+=60; + else + Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize; + // add preamble+SFD+FCS to the packet + // these values must be considered because are not part of the packet received from NDIS + Open->Nbytes.QuadPart+=12; + + NdisReleaseSpinLock( &Open->CountersLock ); + + if(!(Open->mode & MODE_DUMP)){ + return NDIS_STATUS_NOT_ACCEPTED; + } + } + + if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED; + + if(Open->mode & MODE_DUMP && Open->MaxDumpPacks && (UINT)Open->Accepted > Open->MaxDumpPacks){ + // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread. + Open->DumpLimitReached = TRUE; // This stops the thread + // Awake the dump thread + NdisSetEvent(&Open->DumpEvent); + + // Awake the application + KeSetEvent(Open->ReadEvent,0,FALSE); + + return NDIS_STATUS_NOT_ACCEPTED; + } + + // Calculate the correct size for the header associated with the packet + NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr); + + NdisAcquireSpinLock( &Open->BufLock ); + + Thead=Open->Bhead; + Ttail=Open->Btail; + TLastByte = Open->BLastByte; + + NdisReleaseSpinLock( &Open->BufLock ); + + maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize); + + if(Ttail+maxbufspace >= Open->BufSize){ + if(Thead <= maxbufspace) + { + Open->Dropped++; + return NDIS_STATUS_NOT_ACCEPTED; + } + else{ + Ttail=0; + } + } + + CurrBuff=Open->Buffer+Ttail; + + if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize) + { + // Allocate an MDL to map the portion of the buffer following the header + pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize, + maxbufspace, + FALSE, + FALSE, + NULL); + + if (pMdl == NULL) + { + // Unable to map the memory: packet lost + IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");) + Open->Dropped++; + return NDIS_STATUS_NOT_ACCEPTED; + } + MmBuildMdlForNonPagedPool(pMdl); + + //allocate the packet from NDIS + NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool); + if (Status != NDIS_STATUS_SUCCESS) + { + IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");) + IoFreeMdl(pMdl); + Open->Dropped++; + return NDIS_STATUS_NOT_ACCEPTED; + } + //link the buffer to the packet + NdisChainBufferAtFront(pPacketb,pMdl); + + BufferLength=fres-HeaderBufferSize; + //Find out how much to transfer + SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength; + + //copy the ethernet header into buffer + NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize); + + //Copy the look ahead buffer + if(LookaheadBufferSize) + { + NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize, + LookAheadBuffer, + (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize ); + + SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)? + SizeToTransfer - LookaheadBufferSize : 0; + } + + Open->TransferMdl=pMdl; + + if(SizeToTransfer) + { + //Call the Mac to transfer the packet + NdisTransferData(&Status, + Open->AdapterHandle, + MacReceiveContext, + LookaheadBufferSize, + SizeToTransfer, + pPacketb, + &BytesTransfered); + } + else{ + BytesTransfered = 0; + } + + } + else + { + // The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData. + // This allows us to avoid the allocation of the MDL and the NDIS packet as well + RtlCopyMemory((CurrBuff) + NPFHdrSize, + HeaderBuffer, + HeaderBufferSize + LookaheadBufferSize); + + Open->TransferMdl = NULL; + Status = NDIS_STATUS_SUCCESS; + } + + Open->Accepted++; // Increase the accepted packets counter + + if (Status != NDIS_STATUS_FAILURE) + { + + if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) ) + fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize; + + // + // Build the header + // + header=(struct bpf_hdr*)CurrBuff; + GET_TIME(&header->bh_tstamp,&G_Start_Time); + header->bh_caplen=fres; + header->bh_datalen=PacketSize+HeaderBufferSize; + if(Open->mode==MODE_CAPT){ + header->bh_hdrlen=NPFHdrSize; + // Don't align if the packet goes to disk + Ttail+=Packet_WORDALIGN(fres + NPFHdrSize); + } + else + Ttail+=fres+NPFHdrSize; + + //update the buffer + if(Ttail > Thead)TLastByte = Ttail; + + NdisAcquireSpinLock( &Open->BufLock ); + + Open->Btail=Ttail; + Open->BLastByte=TLastByte; + + NdisReleaseSpinLock( &Open->BufLock ); + } + + if (Status != NDIS_STATUS_PENDING){ + + if( Open->TransferMdl != NULL) + // Complete the request and free the buffers + NPF_TransferDataComplete(Open,pPacketb,Status,fres); + else{ + // Unfreeze the consumer + if(GetBuffOccupation(Open)>Open->MinToCopy){ + if(Open->mode & MODE_DUMP){ + NdisSetEvent(&Open->DumpEvent); + } + else + KeSetEvent(Open->ReadEvent,0,FALSE); + } + + } + } + + return NDIS_STATUS_SUCCESS; + +} + +//------------------------------------------------------------------- + +VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket, + IN NDIS_STATUS Status,IN UINT BytesTransfered) +{ + POPEN_INSTANCE Open; + + IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + IoFreeMdl(Open->TransferMdl); + //recylcle the packet + NdisReinitializePacket(pPacket); + //Put the packet on the free queue + NdisFreePacket(pPacket); + // Unfreeze the consumer + if(GetBuffOccupation(Open)>Open->MinToCopy){ + if(Open->mode & MODE_DUMP){ + NdisSetEvent(&Open->DumpEvent); + } + else + KeSetEvent(Open->ReadEvent,0,FALSE); + } + return; +} + +//------------------------------------------------------------------- + +VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext) +{ + IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");) + return; +} diff --git a/drivers/net/packet/resource.h b/drivers/net/packet/resource.h new file mode 100644 index 0000000..d704eca --- /dev/null +++ b/drivers/net/packet/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by NPF.RC +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/drivers/net/packet/tcp_session.c b/drivers/net/packet/tcp_session.c new file mode 100644 index 0000000..4eb6410 --- /dev/null +++ b/drivers/net/packet/tcp_session.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef WIN32 +#include "tme.h" +#include "tcp_session.h" +#endif + +#ifdef __FreeBSD + +#ifdef _KERNEL +#include +#include +#else +#include +#include +#endif + +#endif + +uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data) + +{ + + uint32 next_status; + uint32 direction=ULONG_AT(mem_data,12); + uint8 flags=mem_ex->buffer[25]; + tcp_data *session=(tcp_data*)(block+data->key_len*4); + + session->last_timestamp=session->timestamp_block; + session->timestamp_block.tv_sec=0x7fffffff; + + if (direction==session->direction) + { + session->pkts_cln_to_srv++; + session->bytes_cln_to_srv+=pkt_size; + } + else + { + session->pkts_srv_to_cln++; + session->bytes_srv_to_cln+=pkt_size; + } + /* we use only thes four flags, we don't need PSH or URG */ + flags&=(ACK|FIN|SYN|RST); + + switch (session->status) + { + case ERROR_TCP: + next_status=ERROR_TCP; + break; + + case UNKNOWN: + if (flags==SYN) + { + if (SW_ULONG_AT(mem_ex->buffer,20)!=0) + { + + next_status=ERROR_TCP; + break; + } + next_status=SYN_RCV; + session->syn_timestamp=session->last_timestamp; + + session->direction=direction; + session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16); + } + else + next_status=UNKNOWN; + break; + + case SYN_RCV: + if ((flags&RST)&&(direction!=session->direction)) + { + next_status=CLOSED_RST; + break; + } + if ((flags==SYN)&&(direction==session->direction)) + { /* two syns... */ + next_status=SYN_RCV; + session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16); + break; + } + + if ((flags==(SYN|ACK))&&(direction!=session->direction)) + { + if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1) + { + next_status=ERROR_TCP; + break; + } + next_status=SYN_ACK_RCV; + + session->syn_ack_timestamp=session->last_timestamp; + + session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16); + session->ack_cln=session->seq_n_0_cln+1; + } + else + { + next_status=ERROR_TCP; + } + break; + + case SYN_ACK_RCV: + if ((flags&ACK)&&(flags&RST)&&(direction==session->direction)) + { + next_status=CLOSED_RST; + session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20); + break; + } + + if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction)) + { + if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1) + { + next_status=ERROR_TCP; + break; + } + next_status=ESTABLISHED; + session->ack_srv=session->seq_n_0_srv+1; + break; + } + if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction)) + { + next_status=SYN_ACK_RCV; + break; + } + + next_status=ERROR_TCP; + break; + + case ESTABLISHED: + if (flags&SYN) + { + if ((flags&ACK)&& + (direction!=session->direction)&& + ((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))direction)&& + (SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&& + (ULONG_AT(mem_ex->buffer,20)==0) + ) + { /* syn duplicato */ + next_status=ESTABLISHED; + break; + } + + next_status=ERROR_TCP; + break; + } + if (flags&ACK) + if (direction==session->direction) + { + uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20); + if (new_ack-session->ack_srvack_srv=new_ack; + } + else + { + uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20); + if (new_ack-session->ack_clnack_cln=new_ack; + } + if (flags&RST) + { + next_status=CLOSED_RST; + break; + } + if (flags&FIN) + if (direction==session->direction) + { /* an hack to make all things work */ + session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16); + next_status=FIN_CLN_RCV; + break; + } + else + { + session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16); + next_status=FIN_SRV_RCV; + break; + } + next_status=ESTABLISHED; + break; + + case CLOSED_RST: + next_status=CLOSED_RST; + break; + + case FIN_SRV_RCV: + if (flags&SYN) + { + next_status=ERROR_TCP; + break; + } + + next_status=FIN_SRV_RCV; + + if (flags&ACK) + { + uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20); + if (direction!=session->direction) + if ((new_ack-session->ack_cln)ack_cln=new_ack; + } + + if (flags&RST) + next_status=CLOSED_RST; + else + if ((flags&FIN)&&(direction==session->direction)) + { + session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16); + next_status=CLOSED_FIN; + } + + break; + + case FIN_CLN_RCV: + if (flags&SYN) + { + next_status=ERROR_TCP; + break; + } + + next_status=FIN_CLN_RCV; + + if (flags&ACK) + { + uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20); + if (direction==session->direction) + if (new_ack-session->ack_srvack_srv=new_ack; + } + + if (flags&RST) + next_status=CLOSED_RST; + else + if ((flags&FIN)&&(direction!=session->direction)) + { + session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16); + next_status=CLOSED_FIN; + } + + break; + + case CLOSED_FIN: + next_status=CLOSED_FIN; + break; + default: + next_status=ERROR_TCP; + + } + + session->status=next_status; + + if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP)) + session->timestamp_block=session->last_timestamp; + + return TME_SUCCESS; +} \ No newline at end of file diff --git a/drivers/net/packet/tcp_session.h b/drivers/net/packet/tcp_session.h new file mode 100644 index 0000000..7b0fe91 --- /dev/null +++ b/drivers/net/packet/tcp_session.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __tcp_session +#define __tcp_session + +#ifdef WIN32 +#include "tme.h" +#endif + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#else +#include +#endif + +#endif + +#define UNKNOWN 0 +#define SYN_RCV 1 +#define SYN_ACK_RCV 2 +#define ESTABLISHED 3 +#define CLOSED_RST 4 +#define FIN_CLN_RCV 5 +#define FIN_SRV_RCV 6 +#define CLOSED_FIN 7 +#define ERROR_TCP 8 +#define FIRST_IS_CLN 0 +#define FIRST_IS_SRV 0xffffffff +#define FIN_CLN 1 +#define FIN_SRV 2 + +#define MAX_WINDOW 65536 + +typedef struct __tcp_data +{ + struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/ + struct timeval syn_timestamp; + struct timeval last_timestamp; + struct timeval syn_ack_timestamp; + uint32 direction; + uint32 seq_n_0_srv; + uint32 seq_n_0_cln; + uint32 ack_srv; /* acknowledge of (data sent by server) */ + uint32 ack_cln; /* acknowledge of (data sent by client) */ + uint32 status; + uint32 pkts_cln_to_srv; + uint32 pkts_srv_to_cln; + uint32 bytes_srv_to_cln; + uint32 bytes_cln_to_srv; + uint32 close_state; +} + tcp_data; + +#define FIN 1 +#define SYN 2 +#define RST 4 +#define PSH 8 +#define ACK 16 +#define URG 32 + +#define TCP_SESSION 0x00000800 +uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data); + +#endif \ No newline at end of file diff --git a/drivers/net/packet/time_calls.c b/drivers/net/packet/time_calls.c new file mode 100644 index 0000000..66f18b7 --- /dev/null +++ b/drivers/net/packet/time_calls.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "tme.h" +#include "win_bpf.h" +#include "time_calls.h" + + +void TIME_DESYNCHRONIZE(struct time_conv *data) +{ +#ifndef __GNUC__ + data->reference = 0; + data->start.tv_sec = 0; + data->start.tv_usec = 0; +#endif +} + +#ifdef KQPC_TS + +/* KeQueryPerformanceCounter TimeStamps */ + +VOID TIME_SYNCHRONIZE(struct time_conv *data) +{ +#ifndef __GNUC__ + struct timeval tmp; + LARGE_INTEGER SystemTime; + LARGE_INTEGER i; + ULONG tmp2; + LARGE_INTEGER TimeFreq,PTime; + + if (data->reference!=0) + return; + + // get the absolute value of the system boot time. + PTime=KeQueryPerformanceCounter(&TimeFreq); + KeQuerySystemTime(&SystemTime); + tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600); + tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10); + tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart); + tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart); + if (tmp.tv_usec<0) { + tmp.tv_sec--; + tmp.tv_usec+=1000000; + } + data->start=tmp; + data->reference=1; +#endif +} + +void FORCE_TIME(struct timeval *src, struct time_conv *dest) +{ + dest->start=*src; +} + +void GET_TIME(struct timeval *dst, struct time_conv *data) +{ +#ifndef __GNUC__ + LARGE_INTEGER PTime, TimeFreq; + LONG tmp; + + PTime=KeQueryPerformanceCounter(&TimeFreq); + tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart); + dst->tv_sec=data->start.tv_sec+tmp; + dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart); + if (dst->tv_usec>=1000000) { + dst->tv_sec++; + dst->tv_usec-=1000000; + } +#endif +} + +#else + +/*RDTSC timestamps*/ + +/* callers must be at IRQL=PASSIVE_LEVEL */ +VOID TIME_SYNCHRONIZE(struct time_conv *data) +{ +#ifndef __GNUC__ + struct timeval tmp; + LARGE_INTEGER system_time; + ULONGLONG curr_ticks; + KIRQL old; + LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq; + ULONGLONG start_ticks,stop_ticks; + ULONGLONG delta,delta2; + KEVENT event; + LARGE_INTEGER i; + ULONGLONG reference; + + if (data->reference!=0) + return; + + KeInitializeEvent(&event,NotificationEvent,FALSE); + i.QuadPart=-3500000; + KeRaiseIrql(HIGH_LEVEL,&old); + start_kqpc=KeQueryPerformanceCounter(&start_freq); +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, start_ticks + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + KeLowerIrql(old); + KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i); + KeRaiseIrql(HIGH_LEVEL,&old); + stop_kqpc=KeQueryPerformanceCounter(&stop_freq); +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, stop_ticks + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + KeLowerIrql(old); + delta=stop_ticks-start_ticks; + delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart; + if (delta>10000000000) { + delta/=16; + delta2/=16; + } + reference=delta*(start_freq.QuadPart)/delta2; + data->reference=reference/1000; + if (reference%1000>500) + data->reference++; + data->reference*=1000; + reference=data->reference; + KeQuerySystemTime(&system_time); +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, curr_ticks + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + tmp.tv_sec=-(LONG)(curr_ticks/reference); + tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference); + system_time.QuadPart-=116444736000000000; + tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000); + tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10); + if (tmp.tv_usec<0) { + tmp.tv_sec--; + tmp.tv_usec+=1000000; + } + data->start=tmp; + IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);) +#else +#endif +} + +void FORCE_TIME(struct timeval *src, struct time_conv *dest) +{ + dest->start=*src; +} + +void GET_TIME(struct timeval *dst, struct time_conv *data) +{ +#ifndef __GNUC__ + ULONGLONG tmp; +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, tmp + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + if (data->reference==0) { + return; + } + dst->tv_sec=(LONG)(tmp/data->reference); + dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference); + dst->tv_sec+=data->start.tv_sec; + dst->tv_usec+=data->start.tv_usec; + if (dst->tv_usec>=1000000) { + dst->tv_sec++; + dst->tv_usec-=1000000; + } +#endif +} + +#endif /*KQPC_TS*/ diff --git a/drivers/net/packet/time_calls.h b/drivers/net/packet/time_calls.h new file mode 100644 index 0000000..2355d45 --- /dev/null +++ b/drivers/net/packet/time_calls.h @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef _time_calls +#define _time_calls + +#ifdef WIN_NT_DRIVER + +#include "debug.h" + +/*! + \brief A microsecond precise timestamp. + + included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet. +*/ + +struct timeval { + long tv_sec; ///< seconds + long tv_usec; ///< microseconds +}; + +#endif /*WIN_NT_DRIVER*/ + +struct time_conv { + ULONGLONG reference; + struct timeval start; +}; + +#ifdef __GNUC__ + +void TIME_DESYNCHRONIZE(struct time_conv *data); +VOID TIME_SYNCHRONIZE(struct time_conv *data); +void FORCE_TIME(struct timeval *src, struct time_conv *dest); +void GET_TIME(struct timeval *dst, struct time_conv *data); + +#else /* __GNUC__ */ + +#ifdef WIN_NT_DRIVER + +__inline void TIME_DESYNCHRONIZE(struct time_conv *data) +{ + data->reference = 0; + data->start.tv_sec = 0; + data->start.tv_usec = 0; +} + +#ifdef KQPC_TS + +/* KeQueryPerformanceCounter TimeStamps */ + +__inline VOID TIME_SYNCHRONIZE(struct time_conv *data) +{ + struct timeval tmp; + LARGE_INTEGER SystemTime; + LARGE_INTEGER i; + ULONG tmp2; + LARGE_INTEGER TimeFreq,PTime; + + if (data->reference!=0) + return; + + // get the absolute value of the system boot time. + PTime=KeQueryPerformanceCounter(&TimeFreq); + KeQuerySystemTime(&SystemTime); + tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600); + tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10); + tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart); + tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart); + if (tmp.tv_usec<0) { + tmp.tv_sec--; + tmp.tv_usec+=1000000; + } + data->start=tmp; + data->reference=1; +} + +__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest) +{ + dest->start=*src; +} + +__inline void GET_TIME(struct timeval *dst, struct time_conv *data) +{ + LARGE_INTEGER PTime, TimeFreq; + LONG tmp; + + PTime=KeQueryPerformanceCounter(&TimeFreq); + tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart); + dst->tv_sec=data->start.tv_sec+tmp; + dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart); + if (dst->tv_usec>=1000000) { + dst->tv_sec++; + dst->tv_usec-=1000000; + } +} + +#else + +/*RDTSC timestamps*/ + +/* callers must be at IRQL=PASSIVE_LEVEL */ +__inline VOID TIME_SYNCHRONIZE(struct time_conv *data) +{ + struct timeval tmp; + LARGE_INTEGER system_time; + ULONGLONG curr_ticks; + KIRQL old; + LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq; + ULONGLONG start_ticks,stop_ticks; + ULONGLONG delta,delta2; + KEVENT event; + LARGE_INTEGER i; + ULONGLONG reference; + + if (data->reference!=0) + return; + + KeInitializeEvent(&event,NotificationEvent,FALSE); + i.QuadPart=-3500000; + KeRaiseIrql(HIGH_LEVEL,&old); + start_kqpc=KeQueryPerformanceCounter(&start_freq); +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, start_ticks + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + KeLowerIrql(old); + KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i); + KeRaiseIrql(HIGH_LEVEL,&old); + stop_kqpc=KeQueryPerformanceCounter(&stop_freq); +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, stop_ticks + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + KeLowerIrql(old); + delta=stop_ticks-start_ticks; + delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart; + if (delta>10000000000) { + delta/=16; + delta2/=16; + } + reference=delta*(start_freq.QuadPart)/delta2; + data->reference=reference/1000; + if (reference%1000>500) + data->reference++; + data->reference*=1000; + reference=data->reference; + KeQuerySystemTime(&system_time); +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, curr_ticks + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + tmp.tv_sec=-(LONG)(curr_ticks/reference); + tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference); + system_time.QuadPart-=116444736000000000; + tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000); + tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10); + if (tmp.tv_usec<0) { + tmp.tv_sec--; + tmp.tv_usec+=1000000; + } + data->start=tmp; + IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);) +} + +__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest) +{ + dest->start=*src; +} + +__inline void GET_TIME(struct timeval *dst, struct time_conv *data) +{ + ULONGLONG tmp; +#ifndef __GNUC__ + __asm + { + push eax + push edx + push ecx + rdtsc + lea ecx, tmp + mov [ecx+4], edx + mov [ecx], eax + pop ecx + pop edx + pop eax + } +#else +#endif + if (data->reference==0) { + return; + } + dst->tv_sec=(LONG)(tmp/data->reference); + dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference); + dst->tv_sec+=data->start.tv_sec; + dst->tv_usec+=data->start.tv_usec; + if (dst->tv_usec>=1000000) { + dst->tv_sec++; + dst->tv_usec-=1000000; + } +} + +#endif /*KQPC_TS*/ + +#endif /*WIN_NT_DRIVER*/ + +#endif /* __GNUC__ */ + +#endif /*_time_calls*/ diff --git a/drivers/net/packet/tme.c b/drivers/net/packet/tme.c new file mode 100644 index 0000000..87ed7dc --- /dev/null +++ b/drivers/net/packet/tme.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef WIN32 +#include "tme.h" +#endif + +#ifdef __FreeBSD__ +#include +#endif + +/* resizes extended memory */ +uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex) +{ + uint8 *tmp; + + if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0)) + return TME_ERROR; /* awfully never reached!!!! */ + + tmp=mem_ex->buffer; + mem_ex->buffer=NULL; + FREE_MEMORY(tmp); + + ALLOCATE_MEMORY(tmp,uint8,size); + if (tmp==NULL) + return TME_ERROR; /* no memory */ + + mem_ex->size=size; + mem_ex->buffer=tmp; + return TME_SUCCESS; + +} + +/* activates a block of the TME */ +uint32 set_active_tme_block(TME_CORE *tme, uint32 block) +{ + + if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block))) + return TME_ERROR; + tme->active=block; + tme->working=block; + return TME_SUCCESS; + +} + +/* simply inserts default values in a TME block */ +/* it DOESN'T initialize the block in the core!! */ +/* FIXME default values are defined at compile time, */ +/* it will be useful to store them in the registry */ +uint32 init_tme_block(TME_CORE *tme, uint32 block) +{ + + TME_DATA *data; + if (block>=MAX_TME_DATA_BLOCKS) + return TME_ERROR; + data=&(tme->block_data[block]); + tme->working=block; + + ZERO_MEMORY(data,sizeof(TME_DATA)); + + /* entries in LUT */ + data->lut_entries=TME_LUT_ENTRIES_DEFAULT; + /* blocks */ + data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT; + /* block size */ + data->block_size=TME_BLOCK_SIZE_DEFAULT; + /* lookup function */ + data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT); + /* rehashing value */ + data->rehashing_value=TME_REHASHING_VALUE_DEFAULT; + /* out lut function */ + data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT; + /* default function */ + data->default_exec=TME_DEFAULT_EXEC_DEFAULT; + /* extra segment size */ + data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT; + + + data->enable_deletion=FALSE; + data->last_read.tv_sec=0; + data->last_read.tv_usec=0; + return TME_SUCCESS; + +} +/* it validates a TME block and */ +/* (on OK) inserts the block in the core */ +uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset) +{ + uint32 required_memory; + uint8 *base=mem_ex_offset+mem_ex->buffer; + TME_DATA *data; + + /* FIXME soluzione un po' posticcia... */ + if (mem_ex_offset==0) + return TME_ERROR; + + if (block>=MAX_TME_DATA_BLOCKS) + return TME_ERROR; + data=&tme->block_data[block]; + + if (data->lut_entries==0) + return TME_ERROR; + + if (data->key_len==0) + return TME_ERROR; + + if (data->shared_memory_blocks==0) + return TME_ERROR; + + if (data->block_size==0) + return TME_ERROR; + + /* checks if the lookup function is valid */ + if (data->lookup_code==NULL) + return TME_ERROR; + + /* checks if the out lut exec function is valid */ + if (exec_fcn_mapper(data->out_lut_exec)==NULL) + return TME_ERROR; + + /* checks if the default exec function is valid */ + if (exec_fcn_mapper(data->default_exec)==NULL) + return TME_ERROR; + + /* let's calculate memory needed */ + required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/ + required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/ + required_memory+=data->extra_segment_size; /*extra segment*/ + + if (required_memory>(mem_ex->size-mem_ex_offset)) + return TME_ERROR; /*not enough memory*/ + + /* the TME block can be initialized */ + ZERO_MEMORY(base,required_memory); + + data->lut_base_address=base; + + data->shared_memory_base_address= + data->lut_base_address+ + data->lut_entries*sizeof(RECORD); + + data->extra_segment_base_address= + data->shared_memory_base_address+ + data->block_size*data->shared_memory_blocks; + data->filled_blocks=1; + VALIDATE(tme->validated_blocks,block); + tme->active=block; + tme->working=block; + return TME_SUCCESS; +} + +/* I/F between the bpf machine and the callbacks, just some checks */ +uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref) +{ + if (tme->active==TME_NONE_ACTIVE) + return TME_FALSE; + + return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref); +} + +/* I/F between the bpf machine and the callbacks, just some checks */ +uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset) +{ + + exec_fcn tmp; + TME_DATA *data; + uint8 *block; + uint8 *mem_data; + + if (tme->active==TME_NONE_ACTIVE) + return TME_ERROR; + + data=&tme->block_data[tme->active]; + + if (data->last_found==NULL) + { /*out lut exec */ + tmp=exec_fcn_mapper(data->out_lut_exec); + block=data->shared_memory_base_address; + } + else + { /*checks if last_found is valid */ + if ((data->last_foundlut_base_address)||(data->last_found>=data->shared_memory_base_address)) + return TME_ERROR; + else + { + tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0)); + if (tmp==NULL) + return TME_ERROR; + block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer; + if ((blockshared_memory_base_address)||(block>=data->extra_segment_base_address)) + return TME_ERROR; + } + } + + if (offset>=mem_ex->size) + return TME_ERROR; + + mem_data=mem_ex->buffer+offset; + + return tmp(block,pkt_size,data,mem_ex,mem_data); +} + +/*resets all the TME core*/ +uint32 reset_tme(TME_CORE *tme) +{ + if (tme==NULL) + return TME_ERROR; + ZERO_MEMORY(tme, sizeof(TME_CORE)); + return TME_SUCCESS; +} + +/* returns a register value of the active TME block */ +/* FIXME last found in maniera elegante e veloce ?!?! */ +uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval) +{ + switch(rgstr) + { + case TME_LUT_ENTRIES: + *rval=data->lut_entries; + return TME_SUCCESS; + case TME_MAX_FILL_STATE: + *rval=data->max_fill_state; + return TME_SUCCESS; + case TME_REHASHING_VALUE: + *rval=data->rehashing_value; + return TME_SUCCESS; + case TME_KEY_LEN: + *rval=data->key_len; + return TME_SUCCESS; + case TME_SHARED_MEMORY_BLOCKS: + *rval=data->shared_memory_blocks; + return TME_SUCCESS; + case TME_FILLED_ENTRIES: + *rval=data->filled_entries; + return TME_SUCCESS; + case TME_BLOCK_SIZE: + *rval=data->block_size; + return TME_SUCCESS; + case TME_EXTRA_SEGMENT_SIZE: + *rval=data->extra_segment_size; + return TME_SUCCESS; + case TME_FILLED_BLOCKS: + *rval=data->filled_blocks; + return TME_SUCCESS; + case TME_DEFAULT_EXEC: + *rval=data->default_exec; + return TME_SUCCESS; + case TME_OUT_LUT_EXEC: + *rval=data->out_lut_exec; + return TME_SUCCESS; + case TME_SHARED_MEMORY_BASE_ADDRESS: + *rval=data->shared_memory_base_address-mem_ex->buffer; + return TME_SUCCESS; + case TME_LUT_BASE_ADDRESS: + *rval=data->lut_base_address-mem_ex->buffer; + return TME_SUCCESS; + case TME_EXTRA_SEGMENT_BASE_ADDRESS: + *rval=data->extra_segment_base_address-mem_ex->buffer; + return TME_SUCCESS; + case TME_LAST_FOUND_BLOCK: + if (data->last_found==NULL) + *rval=0; + else + *rval=data->last_found-mem_ex->buffer; + return TME_SUCCESS; + + default: + return TME_ERROR; + } +} + +/* sets a register value in the active block */ +/* FIXME last found in maniera elegante e veloce ?!?! */ +uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init) +{ /* very very very dangerous!!!!!!!!!!! */ + lut_fcn tmp; + switch(rgstr) + { + case TME_MAX_FILL_STATE: + data->max_fill_state=value; + return TME_SUCCESS; + case TME_REHASHING_VALUE: + data->rehashing_value=value; + return TME_SUCCESS; + case TME_FILLED_ENTRIES: + data->filled_entries=value; + return TME_SUCCESS; + case TME_FILLED_BLOCKS: + if (value<=data->shared_memory_blocks) + { + data->filled_blocks=value; + return TME_SUCCESS; + } + else + return TME_ERROR; + case TME_DEFAULT_EXEC: + data->default_exec=value; + return TME_SUCCESS; + case TME_OUT_LUT_EXEC: + data->out_lut_exec=value; + return TME_SUCCESS; + case TME_LOOKUP_CODE: + tmp=lut_fcn_mapper(value); + if (tmp==NULL) + return TME_ERROR; + else + data->lookup_code=tmp; + return TME_SUCCESS; + default: + break; + } + + if (init) + switch (rgstr) + { + + case TME_LUT_ENTRIES: + data->lut_entries=value; + return TME_SUCCESS; + case TME_KEY_LEN: + data->key_len=value; + return TME_SUCCESS; + case TME_SHARED_MEMORY_BLOCKS: + data->shared_memory_blocks=value; + return TME_SUCCESS; + case TME_BLOCK_SIZE: + data->block_size=value; + return TME_SUCCESS; + case TME_EXTRA_SEGMENT_SIZE: + data->extra_segment_size=value; + return TME_SUCCESS; + default: + return TME_ERROR; + } + else + return TME_ERROR; + +} + +/* chooses the TME block for read */ +uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block) +{ + + if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block))) + return TME_ERROR; + tme->active_read=block; + return TME_SUCCESS; + +} + +/* chooses if the autodeletion must be used */ +uint32 set_autodeletion(TME_DATA *data, uint32 value) +{ + if (value==0) /* no autodeletion */ + data->enable_deletion=FALSE; + else + data->enable_deletion=TRUE; + + return TME_SUCCESS; +} \ No newline at end of file diff --git a/drivers/net/packet/tme.h b/drivers/net/packet/tme.h new file mode 100644 index 0000000..f6916f9 --- /dev/null +++ b/drivers/net/packet/tme.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef __tme_include_ +#define __tme_include_ + +#ifdef WIN_NT_DRIVER + +#include "ntddk.h" +#include "memory_t.h" +#include "time_calls.h" +#endif /*WIN_NT_DRIVER*/ + +#ifdef WIN32 +#include "memory_t.h" +#include "time_calls.h" +#endif /*WIN32*/ + + + +#ifdef __FreeBSD__ + +#ifdef _KERNEL +#include +#else +#include +#endif + +#endif + +/* error codes */ +#define TME_ERROR 0 +#define TME_SUCCESS 1 +#define TME_TRUE 2 +#define TME_FALSE 3 + +/* some constants */ +#define DEFAULT_MEM_EX_SIZE 65536 +#define MAX_TME_DATA_BLOCKS 4 +#define TME_NONE_ACTIVE 0xffffffff +#define DELTA_READ 2 /* secs */ + +#define TME_LUT_ENTRIES 0x00000000 +#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */ +#define TME_REHASHING_VALUE 0x00000002 +#define TME_KEY_LEN 0x00000003 +#define TME_SHARED_MEMORY_BLOCKS 0x00000004 +#define TME_FILLED_ENTRIES 0x00000005 +#define TME_BLOCK_SIZE 0x00000006 +#define TME_EXTRA_SEGMENT_SIZE 0x00000007 +#define TME_LOOKUP_CODE 0x00000008 +#define TME_OUT_LUT_EXEC 0x00000009 +#define TME_FILLED_BLOCKS 0x0000000a +#define TME_DEFAULT_EXEC 0x0000000b +#define TME_LUT_BASE_ADDRESS 0x0000000c +#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d +#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e +#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */ +#define TME_LAST_FOUND_BLOCK 0x00000010 +/* TME default values */ +#define TME_LUT_ENTRIES_DEFAULT 32007 +#define TME_REHASHING_VALUE_DEFAULT 1 +#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000 +#define TME_BLOCK_SIZE_DEFAULT 64 +#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0 +#define TME_LOOKUP_CODE_DEFAULT 0 +#define TME_OUT_LUT_EXEC_DEFAULT 0 +#define TME_DEFAULT_EXEC_DEFAULT 0 +#define TME_MAX_FILL_STATE_DEFAULT 15000 + +#define IS_VALIDATED(src,index) (src&(1<tv_sec=0x7fffffff; + +/* TME callback prototypes */ +#ifndef __GNUC__ +typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref ); +typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data); +#else +typedef uint32 (*lut_fcn)(uint8 *key, void *data,MEM_TYPE *mem_ex, struct time_conv *time_ref ); +typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, void *data, MEM_TYPE *mem_ex, uint8 *mem_data); +#endif + +/* DO NOT MODIFY THIS STRUCTURE!!!! GV */ +typedef struct __RECORD + +{ + uint32 block; + uint32 exec_fcn; +} + RECORD, *PRECORD; + +/* TME data registers */ +struct __TME_DATA +{ + uint32 lut_entries; + uint32 max_fill_state; + uint32 rehashing_value; + uint32 key_len; + uint32 shared_memory_blocks; + uint32 filled_entries; + uint32 block_size; + uint32 extra_segment_size; + uint32 filled_blocks; + lut_fcn lookup_code; + uint32 default_exec; + uint32 out_lut_exec; + uint8 *lut_base_address; + uint8 *shared_memory_base_address; + uint8 *extra_segment_base_address; + struct timeval last_read; + uint32 enable_deletion; + uint8 *last_found; +}; + +typedef struct __TME_DATA TME_DATA,*PTME_DATA; + + + +/* TME core */ +typedef struct __TME_CORE +{ + uint32 working; + uint32 active; + uint32 validated_blocks; + TME_DATA block_data[MAX_TME_DATA_BLOCKS]; + uint32 active_read; + +} TME_CORE, *PTME_CORE; + +static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data) +{ + struct timeval *ts=(struct timeval*)timestamp; + + if (data->enable_deletion==FALSE) + return FALSE; + if (data->filled_entriesmax_fill_state) + return FALSE; + if ((ts->tv_sec+DELTA_READ)last_read.tv_sec) + return TRUE; + return FALSE; +} + +/* functions to manage TME */ +uint32 init_tme_block(TME_CORE *tme, uint32 block); +uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset); +uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref); +uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset); +uint32 set_active_tme_block(TME_CORE *tme, uint32 block); +uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex); +uint32 reset_tme(TME_CORE *tme); +uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval); +uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init); +uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block); +uint32 set_autodeletion(TME_DATA *data, uint32 value); + +/* function mappers */ +lut_fcn lut_fcn_mapper(uint32 index); +exec_fcn exec_fcn_mapper(uint32 index); + +#endif \ No newline at end of file diff --git a/drivers/net/packet/valid_insns.h b/drivers/net/packet/valid_insns.h new file mode 100644 index 0000000..20b115d --- /dev/null +++ b/drivers/net/packet/valid_insns.h @@ -0,0 +1,73 @@ +u_short valid_instructions[]= + { + BPF_RET|BPF_K, + BPF_RET|BPF_A, + BPF_LD|BPF_IMM, + BPF_LDX|BPF_IMM, + BPF_LD|BPF_MEM, + BPF_LDX|BPF_MEM, + BPF_LD|BPF_MEM_EX_IMM|BPF_B, + BPF_LD|BPF_MEM_EX_IMM|BPF_H, + BPF_LD|BPF_MEM_EX_IMM|BPF_W, + BPF_LD|BPF_MEM_EX_IND|BPF_B, + BPF_LD|BPF_MEM_EX_IND|BPF_H, + BPF_LD|BPF_MEM_EX_IND|BPF_W, + BPF_LD|BPF_W|BPF_ABS, + BPF_LD|BPF_H|BPF_ABS, + BPF_LD|BPF_B|BPF_ABS, + BPF_LDX|BPF_W|BPF_ABS, + BPF_LDX|BPF_H|BPF_ABS, + BPF_LDX|BPF_B|BPF_ABS, + BPF_LD|BPF_W|BPF_LEN, + BPF_LDX|BPF_W|BPF_LEN, + BPF_LD|BPF_W|BPF_IND, + BPF_LD|BPF_H|BPF_IND, + BPF_LD|BPF_B|BPF_IND, + BPF_LDX|BPF_MSH|BPF_B, + BPF_ST, + BPF_STX, + BPF_ST|BPF_MEM_EX_IMM|BPF_B, + BPF_STX|BPF_MEM_EX_IMM|BPF_B, + BPF_ST|BPF_MEM_EX_IMM|BPF_W, + BPF_STX|BPF_MEM_EX_IMM|BPF_W, + BPF_ST|BPF_MEM_EX_IMM|BPF_H, + BPF_STX|BPF_MEM_EX_IMM|BPF_H, + BPF_ST|BPF_MEM_EX_IND|BPF_B, + BPF_ST|BPF_MEM_EX_IND|BPF_W, + BPF_ST|BPF_MEM_EX_IND|BPF_H, + BPF_JMP|BPF_JA, + BPF_JMP|BPF_JGT|BPF_K, + BPF_JMP|BPF_JGE|BPF_K, + BPF_JMP|BPF_JEQ|BPF_K, + BPF_JMP|BPF_JSET|BPF_K, + BPF_JMP|BPF_JGT|BPF_X, + BPF_JMP|BPF_JGE|BPF_X, + BPF_JMP|BPF_JEQ|BPF_X, + BPF_JMP|BPF_JSET|BPF_X, + BPF_ALU|BPF_ADD|BPF_X, + BPF_ALU|BPF_SUB|BPF_X, + BPF_ALU|BPF_MUL|BPF_X, + BPF_ALU|BPF_DIV|BPF_X, + BPF_ALU|BPF_AND|BPF_X, + BPF_ALU|BPF_OR|BPF_X, + BPF_ALU|BPF_LSH|BPF_X, + BPF_ALU|BPF_RSH|BPF_X, + BPF_ALU|BPF_ADD|BPF_K, + BPF_ALU|BPF_SUB|BPF_K, + BPF_ALU|BPF_MUL|BPF_K, + BPF_ALU|BPF_DIV|BPF_K, + BPF_ALU|BPF_AND|BPF_K, + BPF_ALU|BPF_OR|BPF_K, + BPF_ALU|BPF_LSH|BPF_K, + BPF_ALU|BPF_RSH|BPF_K, + BPF_ALU|BPF_NEG, + BPF_MISC|BPF_TAX, + BPF_MISC|BPF_TXA, + BPF_MISC|BPF_TME|BPF_LOOKUP, + BPF_MISC|BPF_TME|BPF_EXECUTE, + BPF_MISC|BPF_TME|BPF_SET_ACTIVE, + BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE, + BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE + }; + +#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short)) diff --git a/drivers/net/packet/win_bpf.h b/drivers/net/packet/win_bpf.h new file mode 100644 index 0000000..c0f9b51 --- /dev/null +++ b/drivers/net/packet/win_bpf.h @@ -0,0 +1,325 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header$ (LBL) + */ + +#ifndef BPF_MAJOR_VERSION + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef UCHAR u_char; +typedef USHORT u_short; +typedef ULONG u_int; +typedef LONG bpf_int32; +typedef ULONG bpf_u_int32; +typedef ULONG u_int32; + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +#include "time_calls.h" + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_int32 k; +}; + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + bpf_u_int32 bh_caplen; /* length of captured portion */ + bpf_u_int32 bh_datalen; /* original length of packet */ + u_short bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; + +/* + * Data-link level type codes. + */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * This value is defined by NetBSD; other platforms should refrain from + * using it for other purposes, so that NetBSD savefiles with a link + * type of 50 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +/* + * Reserved for future use. + * Do not pick other numerical value for these unless you have also + * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c", + * which will arrange that capture files for these DLT_ types have + * the same "network" value on all platforms, regardless of what + * value is chosen for their DLT_ type (thus allowing captures made + * on one platform to be read on other platforms, even if the two + * platforms don't use the same numerical values for all DLT_ types). + */ +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * Values between 106 and 107 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 for any purpose. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* TME instructions */ +#define BPF_TME 0x08 + +#define BPF_LOOKUP 0x90 +#define BPF_EXECUTE 0xa0 +#define BPF_INIT 0xb0 +#define BPF_VALIDATE 0xc0 +#define BPF_SET_ACTIVE 0xd0 +#define BPF_RESET 0xe0 +#define BPF_SET_MEMORY 0x80 +#define BPF_GET_REGISTER_VALUE 0x70 +#define BPF_SET_REGISTER_VALUE 0x60 +#define BPF_SET_WORKING 0x50 +#define BPF_SET_ACTIVE_READ 0x40 +#define BPF_SET_AUTODELETION 0x30 +#define BPF_SEPARATION 0xff + +#define BPF_MEM_EX_IMM 0xc0 +#define BPF_MEM_EX_IND 0xe0 +/*used for ST */ +#define BPF_MEM_EX 0xc0 + + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#endif diff --git a/drivers/net/packet/win_bpf_filter.c b/drivers/net/packet/win_bpf_filter.c new file mode 100644 index 0000000..76dee6e --- /dev/null +++ b/drivers/net/packet/win_bpf_filter.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * + * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + + @(#)bpf.c 7.5 (Berkeley) 7/15/91 +*/ + +#include "tme.h" +#include "win_bpf.h" + +#include "debug.h" + +#include "valid_insns.h" + +#define EXTRACT_SHORT(p)\ + ((u_short)\ + ((u_short)*((u_char *)p+0)<<8|\ + (u_short)*((u_char *)p+1)<<0)) +#define EXTRACT_LONG(p)\ + ((u_int32)*((u_char *)p+0)<<24|\ + (u_int32)*((u_char *)p+1)<<16|\ + (u_int32)*((u_char *)p+2)<<8|\ + (u_int32)*((u_char *)p+3)<<0) + + +u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref) + register struct bpf_insn *pc; + register u_char *p; + u_int wirelen; + register u_int buflen; + PMEM_TYPE mem_ex; + PTME_CORE tme; + struct time_conv *time_ref; + +{ + register u_int32 A, X; + register int k; + u_int32 j,tmp; + u_short tmp2; + + int32 mem[BPF_MEMWORDS]; + + if (pc == 0) + /* + * No filter means accept all. + */ + return (u_int)-1; + A = 0; + X = 0; + --pc; + while (1) { + ++pc; + switch (pc->code) { + + default: + + return 0; + + case BPF_RET|BPF_K: + return (u_int)pc->k; + + case BPF_RET|BPF_A: + return (u_int)A; + + case BPF_LD|BPF_W|BPF_ABS: + k = pc->k; + if (k + sizeof(int32) > buflen) { + return 0; + } + A = EXTRACT_LONG(&p[k]); + continue; + + case BPF_LD|BPF_H|BPF_ABS: + k = pc->k; + if (k + sizeof(short) > buflen) { + return 0; + } + A = EXTRACT_SHORT(&p[k]); + continue; + + case BPF_LD|BPF_B|BPF_ABS: + k = pc->k; + if ((int)k >= (int)buflen) { + return 0; + } + A = p[k]; + continue; + + case BPF_LD|BPF_W|BPF_LEN: + A = wirelen; + continue; + + case BPF_LDX|BPF_W|BPF_LEN: + X = wirelen; + continue; + + case BPF_LD|BPF_W|BPF_IND: + k = X + pc->k; + if (k + sizeof(int32) > buflen) { + return 0; + } + A = EXTRACT_LONG(&p[k]); + continue; + + case BPF_LD|BPF_H|BPF_IND: + k = X + pc->k; + if (k + sizeof(short) > buflen) { + return 0; + } + A = EXTRACT_SHORT(&p[k]); + continue; + + case BPF_LD|BPF_B|BPF_IND: + k = X + pc->k; + if ((int)k >= (int)buflen) { + return 0; + } + A = p[k]; + continue; + + case BPF_LDX|BPF_MSH|BPF_B: + k = pc->k; + if ((int)k >= (int)buflen) { + return 0; + } + X = (p[pc->k] & 0xf) << 2; + continue; + + case BPF_LD|BPF_IMM: + A = pc->k; + continue; + + case BPF_LDX|BPF_IMM: + X = pc->k; + continue; + + case BPF_LD|BPF_MEM: + A = mem[pc->k]; + continue; + + case BPF_LDX|BPF_MEM: + X = mem[pc->k]; + continue; + +/* LD NO PACKET INSTRUCTIONS */ + + case BPF_LD|BPF_MEM_EX_IMM|BPF_B: + A= mem_ex->buffer[pc->k]; + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_B: + X= mem_ex->buffer[pc->k]; + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_H: + A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_H: + X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_W: + A = EXTRACT_LONG(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_W: + X = EXTRACT_LONG(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_B: + k = X + pc->k; + if ((int32)k>= (int32)mem_ex->size) { + return 0; + } + A= mem_ex->buffer[k]; + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_H: + k = X + pc->k; + if ((int32)(k+1)>= (int32)mem_ex->size) { + return 0; + } + A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]); + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_W: + k = X + pc->k; + if ((int32)(k+3)>= (int32)mem_ex->size) { + return 0; + } + A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]); + continue; +/* END LD NO PACKET INSTRUCTIONS */ + + case BPF_ST: + mem[pc->k] = A; + continue; + + case BPF_STX: + mem[pc->k] = X; + continue; + +/* STORE INSTRUCTIONS */ + case BPF_ST|BPF_MEM_EX_IMM|BPF_B: + mem_ex->buffer[pc->k]=(uint8)A; + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_B: + mem_ex->buffer[pc->k]=(uint8)X; + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_W: + tmp=A; + *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp); + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_W: + tmp=X; + *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp); + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16)A; + *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2); + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16)X; + *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2); + continue; + + case BPF_ST|BPF_MEM_EX_IND|BPF_B: + mem_ex->buffer[pc->k+X]=(uint8)A; + + case BPF_ST|BPF_MEM_EX_IND|BPF_W: + tmp=A; + *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp); + continue; + + case BPF_ST|BPF_MEM_EX_IND|BPF_H: + tmp2=(uint16)A; + *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2); + continue; +/* END STORE INSTRUCTIONS */ + + case BPF_JMP|BPF_JA: + pc += pc->k; + continue; + + case BPF_JMP|BPF_JGT|BPF_K: + pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_K: + pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_K: + pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_K: + pc += (A & pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGT|BPF_X: + pc += (A > X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_X: + pc += (A >= X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_X: + pc += (A == X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_X: + pc += (A & X) ? pc->jt : pc->jf; + continue; + + case BPF_ALU|BPF_ADD|BPF_X: + A += X; + continue; + + case BPF_ALU|BPF_SUB|BPF_X: + A -= X; + continue; + + case BPF_ALU|BPF_MUL|BPF_X: + A *= X; + continue; + + case BPF_ALU|BPF_DIV|BPF_X: + if (X == 0) + return 0; + A /= X; + continue; + + case BPF_ALU|BPF_AND|BPF_X: + A &= X; + continue; + + case BPF_ALU|BPF_OR|BPF_X: + A |= X; + continue; + + case BPF_ALU|BPF_LSH|BPF_X: + A <<= X; + continue; + + case BPF_ALU|BPF_RSH|BPF_X: + A >>= X; + continue; + + case BPF_ALU|BPF_ADD|BPF_K: + A += pc->k; + continue; + + case BPF_ALU|BPF_SUB|BPF_K: + A -= pc->k; + continue; + + case BPF_ALU|BPF_MUL|BPF_K: + A *= pc->k; + continue; + + case BPF_ALU|BPF_DIV|BPF_K: + A /= pc->k; + continue; + + case BPF_ALU|BPF_AND|BPF_K: + A &= pc->k; + continue; + + case BPF_ALU|BPF_OR|BPF_K: + A |= pc->k; + continue; + + case BPF_ALU|BPF_LSH|BPF_K: + A <<= pc->k; + continue; + + case BPF_ALU|BPF_RSH|BPF_K: + A >>= pc->k; + continue; + + case BPF_ALU|BPF_NEG: + (int)A = -((int)A); + continue; + + case BPF_MISC|BPF_TAX: + X = A; + continue; + + case BPF_MISC|BPF_TXA: + A = X; + continue; + +/* TME INSTRUCTIONS */ + case BPF_MISC|BPF_TME|BPF_LOOKUP: + j=lookup_frontend(mem_ex,tme,pc->k,time_ref); + if (j==TME_ERROR) + return 0; + pc += (j == TME_TRUE) ? pc->jt : pc->jf; + continue; + + case BPF_MISC|BPF_TME|BPF_EXECUTE: + if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_ACTIVE: + if (set_active_tme_block(tme,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE: + if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR) + return 0; + A=j; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE: + if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR) + return 0; + continue; +/* END TME INSTRUCTIONS */ + + } + } +} + +//------------------------------------------------------------------- + +u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref) + register struct bpf_insn *pc; + register u_char *p; + register u_char *pd; + register int headersize; + u_int wirelen; + register u_int buflen; + PMEM_TYPE mem_ex; + PTME_CORE tme; + struct time_conv *time_ref; +{ + register u_int32 A, X; + register int k; + int32 mem[BPF_MEMWORDS]; + u_int32 j,tmp; + u_short tmp2; + + if (pc == 0) + /* + * No filter means accept all. + */ + return (u_int)-1; + A = 0; + X = 0; + --pc; + while (1) { + ++pc; + switch (pc->code) { + + default: + + return 0; + + case BPF_RET|BPF_K: + return (u_int)pc->k; + + case BPF_RET|BPF_A: + return (u_int)A; + + case BPF_LD|BPF_W|BPF_ABS: + k = pc->k; + if (k + sizeof(int32) > buflen) { + return 0; + } + + if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]); + else if(k + 2 == headersize){ + A=(u_int32)*((u_char *)p+k)<<24| + (u_int32)*((u_char *)p+k+1)<<16| + (u_int32)*((u_char *)p+k+2)<<8| + (u_int32)*((u_char *)pd+k-headersize); + } + else if(k == headersize-1){ + A=(u_int32)*((u_char *)p+k)<<24| + (u_int32)*((u_char *)p+k+1)<<16| + (u_int32)*((u_char *)pd+k-headersize)<<8| + (u_int32)*((u_char *)pd+k-headersize+1); + } + else if(k == headersize){ + A=(u_int32)*((u_char *)p+k)<<24| + (u_int32)*((u_char *)pd+k-headersize+1)<<16| + (u_int32)*((u_char *)pd+k-headersize+2)<<8| + (u_int32)*((u_char *)pd+k-headersize+3); + } + A = EXTRACT_LONG(&pd[k-headersize]); + + continue; + + case BPF_LD|BPF_H|BPF_ABS: + k = pc->k; + if (k + sizeof(short) > buflen) { + return 0; + } + + if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]); + else if(k == headersize){ + A=(u_short)*((u_char *)p+k)<<8| + (u_short)*((u_char *)pd+k-headersize); + } + A = EXTRACT_SHORT(&pd[k-headersize]); + + continue; + + case BPF_LD|BPF_B|BPF_ABS: + k = pc->k; + if ((int)k >= (int)buflen) { + return 0; + } + + if(kk; + if (k + sizeof(int32) > buflen) { + return 0; + } + + if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]); + else if(k + (int)sizeof(int32) == headersize+2){ + A=(u_int32)*((u_char *)p+k)<<24| + (u_int32)*((u_char *)p+k+1)<<16| + (u_int32)*((u_char *)p+k+2)<<8| + (u_int32)*((u_char *)pd+k-headersize); + } + else if(k + (int)sizeof(int32) == headersize+3){ + A=(u_int32)*((u_char *)p+k)<<24| + (u_int32)*((u_char *)p+k+1)<<16| + (u_int32)*((u_char *)pd+k-headersize)<<8| + (u_int32)*((u_char *)pd+k-headersize+1); + } + else if(k + (int)sizeof(int32) == headersize+4){ + A=(u_int32)*((u_char *)p+k)<<24| + (u_int32)*((u_char *)pd+k-headersize+1)<<16| + (u_int32)*((u_char *)pd+k-headersize+2)<<8| + (u_int32)*((u_char *)pd+k-headersize+3); + } + A = EXTRACT_LONG(&pd[k-headersize]); + + continue; + + case BPF_LD|BPF_H|BPF_IND: + k = X + pc->k; + if (k + sizeof(short) > buflen) { + return 0; + } + + if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]); + else if(k == headersize){ + A=(u_short)*((u_char *)p+k)<<8| + (u_short)*((u_char *)pd+k-headersize); + } + A = EXTRACT_SHORT(&pd[k-headersize]); + + continue; + + case BPF_LD|BPF_B|BPF_IND: + k = X + pc->k; + if ((int)k >= (int)buflen) { + return 0; + } + + if(kk; + if ((int)k >= (int)buflen) { + return 0; + } + + if((pc->k)k] & 0xf) << 2; + else X = (pd[(pc->k)-headersize] & 0xf) << 2; + + continue; + + case BPF_LD|BPF_IMM: + A = pc->k; + continue; + + case BPF_LDX|BPF_IMM: + X = pc->k; + continue; + + case BPF_LD|BPF_MEM: + A = mem[pc->k]; + continue; + + case BPF_LDX|BPF_MEM: + X = mem[pc->k]; + continue; + +/* LD NO PACKET INSTRUCTIONS */ + + case BPF_LD|BPF_MEM_EX_IMM|BPF_B: + A= mem_ex->buffer[pc->k]; + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_B: + X= mem_ex->buffer[pc->k]; + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_H: + A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_H: + X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_W: + A = EXTRACT_LONG(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_W: + X = EXTRACT_LONG(&mem_ex->buffer[pc->k]); + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_B: + k = X + pc->k; + if ((int32)k>= (int32)mem_ex->size) { + return 0; + } + A= mem_ex->buffer[k]; + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_H: + k = X + pc->k; + if ((int32)(k+1)>= (int32)mem_ex->size) { + return 0; + } + A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]); + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_W: + k = X + pc->k; + if ((int32)(k+3)>= (int32)mem_ex->size) { + return 0; + } + A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]); + continue; +/* END LD NO PACKET INSTRUCTIONS */ + + case BPF_ST: + mem[pc->k] = A; + continue; + + case BPF_STX: + mem[pc->k] = X; + continue; + + +/* STORE INSTRUCTIONS */ + case BPF_ST|BPF_MEM_EX_IMM|BPF_B: + mem_ex->buffer[pc->k]=(uint8)A; + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_B: + mem_ex->buffer[pc->k]=(uint8)X; + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_W: + tmp=A; + *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp); + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_W: + tmp=X; + *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp); + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16)A; + *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2); + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16)X; + *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2); + continue; + + case BPF_ST|BPF_MEM_EX_IND|BPF_B: + mem_ex->buffer[pc->k+X]=(uint8)A; + + case BPF_ST|BPF_MEM_EX_IND|BPF_W: + tmp=A; + *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp); + continue; + + case BPF_ST|BPF_MEM_EX_IND|BPF_H: + tmp2=(uint16)A; + *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2); + continue; +/* END STORE INSTRUCTIONS */ + + + + case BPF_JMP|BPF_JA: + pc += pc->k; + continue; + + case BPF_JMP|BPF_JGT|BPF_K: + pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_K: + pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_K: + pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_K: + pc += (A & pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGT|BPF_X: + pc += (A > X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_X: + pc += (A >= X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_X: + pc += (A == X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_X: + pc += (A & X) ? pc->jt : pc->jf; + continue; + + case BPF_ALU|BPF_ADD|BPF_X: + A += X; + continue; + + case BPF_ALU|BPF_SUB|BPF_X: + A -= X; + continue; + + case BPF_ALU|BPF_MUL|BPF_X: + A *= X; + continue; + + case BPF_ALU|BPF_DIV|BPF_X: + if (X == 0) + return 0; + A /= X; + continue; + + case BPF_ALU|BPF_AND|BPF_X: + A &= X; + continue; + + case BPF_ALU|BPF_OR|BPF_X: + A |= X; + continue; + + case BPF_ALU|BPF_LSH|BPF_X: + A <<= X; + continue; + + case BPF_ALU|BPF_RSH|BPF_X: + A >>= X; + continue; + + case BPF_ALU|BPF_ADD|BPF_K: + A += pc->k; + continue; + + case BPF_ALU|BPF_SUB|BPF_K: + A -= pc->k; + continue; + + case BPF_ALU|BPF_MUL|BPF_K: + A *= pc->k; + continue; + + case BPF_ALU|BPF_DIV|BPF_K: + A /= pc->k; + continue; + + case BPF_ALU|BPF_AND|BPF_K: + A &= pc->k; + continue; + + case BPF_ALU|BPF_OR|BPF_K: + A |= pc->k; + continue; + + case BPF_ALU|BPF_LSH|BPF_K: + A <<= pc->k; + continue; + + case BPF_ALU|BPF_RSH|BPF_K: + A >>= pc->k; + continue; + + case BPF_ALU|BPF_NEG: + (int)A = -((int)A); + continue; + + case BPF_MISC|BPF_TAX: + X = A; + continue; + + case BPF_MISC|BPF_TXA: + A = X; + continue; + +/* TME INSTRUCTIONS */ + case BPF_MISC|BPF_TME|BPF_LOOKUP: + j=lookup_frontend(mem_ex,tme,pc->k,time_ref); + if (j==TME_ERROR) + return 0; + pc += (j == TME_TRUE) ? pc->jt : pc->jf; + continue; + + case BPF_MISC|BPF_TME|BPF_EXECUTE: + if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_ACTIVE: + if (set_active_tme_block(tme,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE: + if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR) + return 0; + A=j; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE: + if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR) + return 0; + continue; +/* END TME INSTRUCTIONS */ + + } + } +} + +int32 +bpf_validate(f, len,mem_ex_size) + struct bpf_insn *f; + int32 len; + uint32 mem_ex_size; +{ + register int32 i,j; + register struct bpf_insn *p; + int32 flag; + + for (i = 0; i < len; ++i) { + /* + * Check that that jumps are forward, and within + * the code block. + */ + + p = &f[i]; + + IF_LOUD(DbgPrint("Validating program");) + + flag=0; + for(j=0;jcode==valid_instructions[j]) + flag=1; + if (flag==0) + return 0; + + IF_LOUD(DbgPrint("Validating program: no unknown instructions");) + + if (BPF_CLASS(p->code) == BPF_JMP) { + register int32 from = i + 1; + + if (BPF_OP(p->code) == BPF_JA) { + if (from + p->k >= len) + return 0; + } + else if (from + p->jt >= len || from + p->jf >= len) + return 0; + } + + IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");) + + /* + * Check that memory operations use valid addresses. + */ + if (((BPF_CLASS(p->code) == BPF_ST && ((p->code &BPF_MEM_EX_IMM)!=BPF_MEM_EX_IMM && (p->code &BPF_MEM_EX_IND)!=BPF_MEM_EX_IND)) || + (BPF_CLASS(p->code) == BPF_LD && + (p->code & 0xe0) == BPF_MEM)) && + (p->k >= BPF_MEMWORDS || p->k < 0)) + return 0; + + IF_LOUD(DbgPrint("Validating program: no wrong ST/LD memory locations");) + + /* + * Check if key stores use valid addresses + */ + if (BPF_CLASS(p->code) == BPF_ST && (p->code &BPF_MEM_EX_IMM)==BPF_MEM_EX_IMM) + switch (BPF_SIZE(p->code)) + { + case BPF_W: if (p->k<0 || p->k+3>=(int32)mem_ex_size) return 0; + case BPF_H: if (p->k<0 || p->k+1>=(int32)mem_ex_size) return 0; + case BPF_B: if (p->k<0 || p->k>=(int32)mem_ex_size) return 0; + } + + IF_LOUD(DbgPrint("Validating program: no wrong ST/LD mem_ex locations");) + + /* + * Check for constant division by 0. + */ + if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) + return 0; + } + return BPF_CLASS(f[len - 1].code) == BPF_RET; +} \ No newline at end of file diff --git a/drivers/net/packet/win_bpf_filter_init.c b/drivers/net/packet/win_bpf_filter_init.c new file mode 100644 index 0000000..96e7e4c --- /dev/null +++ b/drivers/net/packet/win_bpf_filter_init.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * + * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "tme.h" +#include "win_bpf.h" + +/* + * Initialize the filter machine + */ +uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref) +{ + register uint32 A, X; + int32 mem[BPF_MEMWORDS]; + register int32 k; + uint32 *tmp; + uint16 *tmp2; + uint32 j; + if (pc == 0) + /* + * No filter means accept all. + */ + return (uint32)-1; + A = 0; + X = 0; + --pc; + while (1) { + ++pc; + switch (pc->code) { + + default: + return 0; + +/* RET INSTRUCTIONS */ + case BPF_RET|BPF_K: + return (uint32)pc->k; + + case BPF_RET|BPF_A: + return (uint32)A; +/* END RET INSTRUCTIONS */ + +/* LD NO PACKET INSTRUCTIONS */ + case BPF_LD|BPF_IMM: + A = pc->k; + continue; + + case BPF_LDX|BPF_IMM: + X = pc->k; + continue; + + case BPF_LD|BPF_MEM: + A = mem[pc->k]; + continue; + + case BPF_LDX|BPF_MEM: + X = mem[pc->k]; + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_B: + A= mem_ex->buffer[pc->k]; + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_B: + X= mem_ex->buffer[pc->k]; + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx,tmp2 + xor eax, eax + mov ax, [ebx] + bswap eax + mov A, eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx,tmp2 + xor eax, eax + mov ax, [ebx] + bswap eax + mov X, eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_LD|BPF_MEM_EX_IMM|BPF_W: + tmp=(uint32*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx,tmp + mov eax, [ebx] + bswap eax + mov A, eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_LDX|BPF_MEM_EX_IMM|BPF_W: + tmp=(uint32*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx,tmp + mov eax, [ebx] + bswap eax + mov X, eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_B: + k = X + pc->k; + if ((int32)k>= (int32)mem_ex->size) { + return 0; + } + A= mem_ex->buffer[k]; + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_H: + k = X + pc->k; + if ((int32)(k+1)>= (int32)mem_ex->size) { + return 0; + } + tmp2=(uint16*)&mem_ex->buffer[k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx,tmp2 + xor eax, eax + mov ax, [ebx] + bswap eax + mov A, eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_LD|BPF_MEM_EX_IND|BPF_W: + k = X + pc->k; + if ((int32)(k+3)>= (int32)mem_ex->size) { + return 0; + } + tmp=(uint32*)&mem_ex->buffer[k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx,tmp + mov eax, [ebx] + bswap eax + mov A, eax + pop ebx + pop eax + } +#else +#endif + continue; +/* END LD NO PACKET INSTRUCTIONS */ + +/* STORE INSTRUCTIONS */ + case BPF_ST: + mem[pc->k] = A; + continue; + + case BPF_STX: + mem[pc->k] = X; + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_B: + mem_ex->buffer[pc->k]=(uint8)A; + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_B: + mem_ex->buffer[pc->k]=(uint8)X; + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_W: + tmp=(uint32*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx, tmp + mov eax, A + bswap eax + mov [ebx], eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_W: + tmp=(uint32*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx, tmp + mov eax, X + bswap eax + mov [ebx], eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_ST|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx, tmp2 + mov eax, A + xchg ah, al + mov [ebx], ax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_STX|BPF_MEM_EX_IMM|BPF_H: + tmp2=(uint16*)&mem_ex->buffer[pc->k]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx, tmp2 + mov eax, X + xchg ah, al + mov [ebx], ax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_ST|BPF_MEM_EX_IND|BPF_B: + mem_ex->buffer[pc->k+X]=(uint8)A; + + case BPF_ST|BPF_MEM_EX_IND|BPF_W: + tmp=(uint32*)&mem_ex->buffer[pc->k+X]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx, tmp + mov eax, A + bswap eax + mov [ebx], eax + pop ebx + pop eax + } +#else +#endif + continue; + + case BPF_ST|BPF_MEM_EX_IND|BPF_H: + tmp2=(uint16*)&mem_ex->buffer[pc->k+X]; +#ifndef __GNUC__ + __asm + { + push eax + push ebx + mov ebx, tmp2 + mov eax, A + xchg ah, al + mov [ebx], ax + pop ebx + pop eax + } +#else +#endif + continue; +/* END STORE INSTRUCTIONS */ + +/* JUMP INSTRUCTIONS */ + case BPF_JMP|BPF_JA: + pc += pc->k; + continue; + + case BPF_JMP|BPF_JGT|BPF_K: + pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_K: + pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_K: + pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_K: + pc += (A & pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGT|BPF_X: + pc += (A > X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_X: + pc += (A >= X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_X: + pc += (A == X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_X: + pc += (A & X) ? pc->jt : pc->jf; + continue; +/* END JUMP INSTRUCTIONS */ + +/* ARITHMETIC INSTRUCTIONS */ + case BPF_ALU|BPF_ADD|BPF_X: + A += X; + continue; + + case BPF_ALU|BPF_SUB|BPF_X: + A -= X; + continue; + + case BPF_ALU|BPF_MUL|BPF_X: + A *= X; + continue; + + case BPF_ALU|BPF_DIV|BPF_X: + if (X == 0) + return 0; + A /= X; + continue; + + case BPF_ALU|BPF_AND|BPF_X: + A &= X; + continue; + + case BPF_ALU|BPF_OR|BPF_X: + A |= X; + continue; + + case BPF_ALU|BPF_LSH|BPF_X: + A <<= X; + continue; + + case BPF_ALU|BPF_RSH|BPF_X: + A >>= X; + continue; + + case BPF_ALU|BPF_ADD|BPF_K: + A += pc->k; + continue; + + case BPF_ALU|BPF_SUB|BPF_K: + A -= pc->k; + continue; + + case BPF_ALU|BPF_MUL|BPF_K: + A *= pc->k; + continue; + + case BPF_ALU|BPF_DIV|BPF_K: + A /= pc->k; + continue; + + case BPF_ALU|BPF_AND|BPF_K: + A &= pc->k; + continue; + + case BPF_ALU|BPF_OR|BPF_K: + A |= pc->k; + continue; + + case BPF_ALU|BPF_LSH|BPF_K: + A <<= pc->k; + continue; + + case BPF_ALU|BPF_RSH|BPF_K: + A >>= pc->k; + continue; + + case BPF_ALU|BPF_NEG: + (int32)A = -((int32)A); + continue; +/* ARITHMETIC INSTRUCTIONS */ + +/* MISC INSTRUCTIONS */ + case BPF_MISC|BPF_TAX: + X = A; + continue; + + case BPF_MISC|BPF_TXA: + A = X; + continue; +/* END MISC INSTRUCTIONS */ + +/* TME INSTRUCTIONS */ + case BPF_MISC|BPF_TME|BPF_LOOKUP: + j=lookup_frontend(mem_ex,tme,pc->k,time_ref); + if (j==TME_ERROR) + return 0; + pc += (j == TME_TRUE) ? pc->jt : pc->jf; + continue; + + case BPF_MISC|BPF_TME|BPF_EXECUTE: + if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_INIT: + if (init_tme_block(tme,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_VALIDATE: + if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_MEMORY: + if (init_extended_memory(pc->k,mem_ex)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_ACTIVE: + if (set_active_tme_block(tme,pc->k)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ: + if (set_active_tme_block(tme,pc->k)==TME_ERROR) + return 0; + continue; + case BPF_MISC|BPF_TME|BPF_SET_WORKING: + if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS)) + return 0; + tme->working=pc->k; + continue; + + + + case BPF_MISC|BPF_TME|BPF_RESET: + if (reset_tme(tme)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE: + if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR) + return 0; + A=j; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE: + if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR) + return 0; + continue; + + case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION: + set_autodeletion(&tme->block_data[tme->working],pc->k); + continue; + +/* END TME INSTRUCTIONS */ + + } + } +} + diff --git a/drivers/net/packet/win_bpf_filter_init.h b/drivers/net/packet/win_bpf_filter_init.h new file mode 100644 index 0000000..23e7a9f --- /dev/null +++ b/drivers/net/packet/win_bpf_filter_init.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2001 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef __FILTER_INIT +#define __FILTER_INIT + +#include "tme.h" + +#define INIT_OK 1 +#define INIT_ERROR 0 + +uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref); + +#endif \ No newline at end of file diff --git a/drivers/net/packet/write.c b/drivers/net/packet/write.c new file mode 100644 index 0000000..f12818f --- /dev/null +++ b/drivers/net/packet/write.c @@ -0,0 +1,332 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifdef _MSC_VER +#include "stdarg.h" +#include "ntddk.h" +#include "ntiologc.h" +#include "ndis.h" +#else +#include +#include +#endif + +#include "debug.h" +#include "packet.h" + + +//------------------------------------------------------------------- +NTSTATUS +//STDCALL +NPF_Write( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +{ + POPEN_INSTANCE Open; + PIO_STACK_LOCATION IrpSp; + PNDIS_PACKET pPacket; + UINT i; + NDIS_STATUS Status; + + + IF_LOUD(DbgPrint("Packet: SendAdapter\n");) + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + + Open=IrpSp->FileObject->FsContext; + + // Check the length of the packet to avoid to use an empty packet + if(IrpSp->Parameters.Write.Length==0) + { + Irp->IoStatus.Status = NDIS_STATUS_SUCCESS; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return NDIS_STATUS_SUCCESS; + } + + + IoMarkIrpPending(Irp); + + Open->Multiple_Write_Counter=Open->Nwrites; + + NdisResetEvent(&Open->WriteEvent); + + + for(i=0;iNwrites;i++){ + + // Try to get a packet from our list of free ones + NdisAllocatePacket( + &Status, + &pPacket, + Open->PacketPool + ); + + if (Status != NDIS_STATUS_SUCCESS) { + + // No free packets + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // The packet has a buffer that needs not to be freed after every single write + RESERVED(pPacket)->FreeBufAfterWrite = FALSE; + + // Save the IRP associated with the packet + RESERVED(pPacket)->Irp=Irp; + + // Attach the writes buffer to the packet + NdisChainBufferAtFront(pPacket,Irp->MdlAddress); + + // Call the MAC + NdisSend( + &Status, + Open->AdapterHandle, + pPacket); + + if (Status != NDIS_STATUS_PENDING) { + // The send didn't pend so call the completion handler now + NPF_SendComplete( + Open, + pPacket, + Status + ); + + } + + if(i%100==99){ + NdisWaitEvent(&Open->WriteEvent,1000); + NdisResetEvent(&Open->WriteEvent); + } + } + + return(STATUS_PENDING); + +} + + +//------------------------------------------------------------------- + +INT +NPF_BufferedWrite( + IN PIRP Irp, + IN PCHAR UserBuff, + IN ULONG UserBuffSize, + BOOLEAN Sync) +{ + POPEN_INSTANCE Open; + PIO_STACK_LOCATION IrpSp; + PNDIS_PACKET pPacket; + UINT i; + NDIS_STATUS Status; + LARGE_INTEGER StartTicks, CurTicks, TargetTicks; + LARGE_INTEGER TimeFreq; + struct timeval BufStartTime; + struct sf_pkthdr *winpcap_hdr; + PMDL TmpMdl; + PCHAR CurPos; + PCHAR EndOfUserBuff = UserBuff + UserBuffSize; + + IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);) + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + Open=IrpSp->FileObject->FsContext; + + // Security check on the length of the user buffer + if(UserBuff==0) + { + return 0; + } + + // Start from the first packet + winpcap_hdr = (struct sf_pkthdr*)UserBuff; + + // Retrieve the time references + StartTicks = KeQueryPerformanceCounter(&TimeFreq); + BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec; + BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec; + + // Chech the consistency of the user buffer + if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff ) + { + IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");) + + return -1; + } + + // Save the current time stamp counter + CurTicks = KeQueryPerformanceCounter(NULL); + + // Main loop: send the buffer to the wire + while( TRUE ){ + + if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > 65536) + { + // Malformed header + IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed user buffer, aborting write.\n");) + + return -1; + } + + // Allocate an MDL to map the packet data + TmpMdl=IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr), + winpcap_hdr->caplen, + FALSE, + FALSE, + NULL); + + if (TmpMdl == NULL) + { + // Unable to map the memory: packet lost + IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");) + + return -1; + } + + MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed? + + // Allocate a packet from our free list + NdisAllocatePacket( &Status, &pPacket, Open->PacketPool); + + if (Status != NDIS_STATUS_SUCCESS) { + // No free packets + IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");) + + return (PCHAR)winpcap_hdr - UserBuff; + } + + // The packet has a buffer that needs to be freed after every single write + RESERVED(pPacket)->FreeBufAfterWrite = TRUE; + + // Attach the MDL to the packet + NdisChainBufferAtFront(pPacket,TmpMdl); + + // Call the MAC + NdisSend( &Status, Open->AdapterHandle, pPacket); + + if (Status != NDIS_STATUS_PENDING) { + // The send didn't pend so call the completion handler now + NPF_SendComplete( + Open, + pPacket, + Status + ); + } + + // Step to the next packet in the buffer + (PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr); + + // Check if the end of the user buffer has been reached + if( (PCHAR)winpcap_hdr >= EndOfUserBuff ) + { + IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");) + + return (PCHAR)winpcap_hdr - UserBuff; + } + + if( Sync ){ + +#if 0 + // Release the application if it has been blocked for approximately more than 1 seconds + if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 ) + { + IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");) + + return (PCHAR)winpcap_hdr - UserBuff; + } + + // Calculate the time interval to wait before sending the next packet + TargetTicks.QuadPart = StartTicks.QuadPart + + (LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 + + winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) * + (TimeFreq.QuadPart) / 1000000; + + // Wait until the time interval has elapsed + while( CurTicks.QuadPart <= TargetTicks.QuadPart ) + CurTicks = KeQueryPerformanceCounter(NULL); +#endif + + } + + } + + return (PCHAR)winpcap_hdr - UserBuff; + +} + + +//------------------------------------------------------------------- + +VOID +NPF_SendComplete( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET pPacket, + IN NDIS_STATUS Status + ) + +{ + PIRP Irp; + PIO_STACK_LOCATION irpSp; + POPEN_INSTANCE Open; + PMDL TmpMdl; + + IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);) + + Open= (POPEN_INSTANCE)ProtocolBindingContext; + + if( RESERVED(pPacket)->FreeBufAfterWrite ){ + // Free the MDL associated with the packet + NdisUnchainBufferAtFront(pPacket, &TmpMdl); + IoFreeMdl(TmpMdl); + } + else{ + if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99) + NdisSetEvent(&Open->WriteEvent); + + Open->Multiple_Write_Counter--; + } + + // recyle the packet + NdisReinitializePacket(pPacket); + + // Put the packet back on the free list + NdisFreePacket(pPacket); + + if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){ + if(Open->Multiple_Write_Counter==0){ + // Release the buffer and awake the application + NdisUnchainBufferAtFront(pPacket, &TmpMdl); + + Irp=RESERVED(pPacket)->Irp; + irpSp = IoGetCurrentIrpStackLocation(Irp); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = irpSp->Parameters.Write.Length; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + } + } + + return; +} diff --git a/drivers/net/tcpip/.cvsignore b/drivers/net/tcpip/.cvsignore new file mode 100644 index 0000000..48a5fe0 --- /dev/null +++ b/drivers/net/tcpip/.cvsignore @@ -0,0 +1,5 @@ +objects +tcpip.coff +*.d +*.o +*.sym diff --git a/drivers/net/tcpip/DIRS b/drivers/net/tcpip/DIRS new file mode 100644 index 0000000..de50bbd --- /dev/null +++ b/drivers/net/tcpip/DIRS @@ -0,0 +1,5 @@ +DIRS= datalink \ + network \ + transport \ + tcpip + diff --git a/drivers/net/tcpip/datalink/Makefile b/drivers/net/tcpip/datalink/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/datalink/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/datalink/SOURCES b/drivers/net/tcpip/datalink/SOURCES new file mode 100644 index 0000000..25571ac --- /dev/null +++ b/drivers/net/tcpip/datalink/SOURCES @@ -0,0 +1,13 @@ +TARGETNAME=datalink +TARGETPATH=..\objects +TARGETTYPE=LIBRARY + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +INCLUDES=..\include;$(BASEDIR)\INC;..\..\..\..\include\net +SOURCES= arp.c \ + lan.c \ + loopback.c + +MSC_WARNING_LEVEL=/W3 /WX diff --git a/drivers/net/tcpip/datalink/arp.c b/drivers/net/tcpip/datalink/arp.c new file mode 100644 index 0000000..01a21b5 --- /dev/null +++ b/drivers/net/tcpip/datalink/arp.c @@ -0,0 +1,284 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: datalink/arp.c + * PURPOSE: Address Resolution Protocol routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + + +PNDIS_PACKET PrepareARPPacket( + USHORT HardwareType, + USHORT ProtocolType, + UCHAR LinkAddressLength, + UCHAR ProtoAddressLength, + PVOID SenderLinkAddress, + PVOID SenderProtoAddress, + PVOID TargetLinkAddress, + PVOID TargetProtoAddress, + USHORT Opcode) +/* + * FUNCTION: Prepares an ARP packet + * ARGUMENTS: + * HardwareType = Hardware type (in network byte order) + * ProtocolType = Protocol type (in network byte order) + * LinkAddressLength = Length of link address fields + * ProtoAddressLength = Length of protocol address fields + * SenderLinkAddress = Sender's link address + * SenderProtoAddress = Sender's protocol address + * TargetLinkAddress = Target's link address (NULL if don't care) + * TargetProtoAddress = Target's protocol address + * Opcode = ARP opcode (in network byte order) + * RETURNS: + * Pointer to NDIS packet, NULL if there is not enough free resources + */ +{ + PNDIS_PACKET NdisPacket; + PNDIS_BUFFER NdisBuffer; + NDIS_STATUS NdisStatus; + PARP_HEADER Header; + PVOID DataBuffer; + ULONG Size; + + TI_DbgPrint(DEBUG_ARP, ("Called.\n")); + + /* Prepare ARP packet */ + Size = MaxLLHeaderSize + sizeof(ARP_HEADER) + + 2 * LinkAddressLength + /* Hardware address length */ + 2 * ProtoAddressLength; /* Protocol address length */ + Size = MAX(Size, MinLLFrameSize); + + DataBuffer = ExAllocatePool(NonPagedPool, Size); + if (!DataBuffer) + return NULL; + + /* Allocate NDIS packet */ + NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + ExFreePool(DataBuffer); + return NULL; + } + + /* Allocate NDIS buffer for maximum link level header and ARP packet */ + NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool, + DataBuffer, Size); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NdisFreePacket(NdisPacket); + ExFreePool(DataBuffer); + return NULL; + } + + /* Link NDIS buffer into packet */ + NdisChainBufferAtFront(NdisPacket, NdisBuffer); + RtlZeroMemory(DataBuffer, Size); + Header = (PARP_HEADER)((ULONG_PTR)DataBuffer + MaxLLHeaderSize); + Header->HWType = HardwareType; + Header->ProtoType = ProtocolType; + Header->HWAddrLen = LinkAddressLength; + Header->ProtoAddrLen = ProtoAddressLength; + Header->Opcode = Opcode; /* Already swapped */ + DataBuffer = (PVOID)((ULONG_PTR)Header + sizeof(ARP_HEADER)); + + /* Our hardware address */ + RtlCopyMemory(DataBuffer, SenderLinkAddress, LinkAddressLength); + (ULONG_PTR)DataBuffer += LinkAddressLength; + + /* Our protocol address */ + RtlCopyMemory(DataBuffer, SenderProtoAddress, ProtoAddressLength); + + if (TargetLinkAddress) { + (ULONG_PTR)DataBuffer += ProtoAddressLength; + /* Target hardware address */ + RtlCopyMemory(DataBuffer, TargetLinkAddress, LinkAddressLength); + (ULONG_PTR)DataBuffer += LinkAddressLength; + } else + /* Don't care about target hardware address */ + (ULONG_PTR)DataBuffer += (ProtoAddressLength + LinkAddressLength); + + /* Target protocol address */ + RtlCopyMemory(DataBuffer, TargetProtoAddress, ProtoAddressLength); + + return NdisPacket; +} + + +VOID ARPTransmitComplete( + PVOID Context, + PNDIS_PACKET NdisPacket, + NDIS_STATUS NdisStatus) +/* + * FUNCTION: ARP request transmit completion handler + * ARGUMENTS: + * Context = Pointer to context information (IP_INTERFACE) + * Packet = Pointer to NDIS packet that was sent + * NdisStatus = NDIS status of operation + * NOTES: + * This routine is called when an ARP request has been sent + */ +{ + TI_DbgPrint(DEBUG_ARP, ("Called.\n")); + + FreeNdisPacket(NdisPacket); +} + + +BOOLEAN ARPTransmit( + PIP_ADDRESS Address, + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Creates an ARP request and transmits it on a network + * ARGUMENTS: + * Address = Pointer to IP address to resolve + * NTE = Pointer to net table entru to use for transmitting request + * RETURNS: + * TRUE if the request was successfully sent, FALSE if not + */ +{ + PIP_INTERFACE Interface; + PNDIS_PACKET NdisPacket; + UCHAR ProtoAddrLen; + USHORT ProtoType; + + TI_DbgPrint(DEBUG_ARP, ("Called.\n")); + + Interface = NTE->Interface; + + switch (Address->Type) { + case IP_ADDRESS_V4: + ProtoType = (USHORT)ETYPE_IPv4; /* IPv4 */ + ProtoAddrLen = 4; /* Length of IPv4 address */ + break; + case IP_ADDRESS_V6: + ProtoType = (USHORT)ETYPE_IPv6; /* IPv6 */ + ProtoAddrLen = 16; /* Length of IPv6 address */ + break; + default: + /* Should not happen */ + return FALSE; + } + + NdisPacket = PrepareARPPacket( + WN2H(0x0001), /* FIXME: Ethernet only */ + ProtoType, /* Protocol type */ + (UCHAR)Interface->AddressLength, /* Hardware address length */ + (UCHAR)ProtoAddrLen, /* Protocol address length */ + Interface->Address, /* Sender's (local) hardware address */ + &NTE->Address->Address, /* Sender's (local) protocol address */ + NULL, /* Don't care */ + &Address->Address, /* Target's (remote) protocol address */ + ARP_OPCODE_REQUEST); /* ARP request */ + + PC(NdisPacket)->DLComplete = ARPTransmitComplete; + + (*Interface->Transmit)(Interface->Context, NdisPacket, + MaxLLHeaderSize, NULL, LAN_PROTO_ARP); + + return TRUE; +} + + +VOID ARPReceive( + PVOID Context, + PIP_PACKET Packet) +/* + * FUNCTION: Receives an ARP packet + * ARGUMENTS: + * Context = Pointer to context information (IP_INTERFACE) + * Packet = Pointer to packet + */ +{ + PARP_HEADER Header; + PIP_ADDRESS Address; + PVOID SenderHWAddress; + PVOID SenderProtoAddress; + PVOID TargetProtoAddress; + PADDRESS_ENTRY ADE; + PNEIGHBOR_CACHE_ENTRY NCE; + PNDIS_PACKET NdisPacket; + PIP_INTERFACE Interface = (PIP_INTERFACE)Context; + + TI_DbgPrint(DEBUG_ARP, ("Called.\n")); + + Header = (PARP_HEADER)Packet->Header; + + /* FIXME: Ethernet only */ + if (WN2H(Header->HWType) != 1) { + TI_DbgPrint(DEBUG_ARP, ("Unknown ARP hardware type (0x%X).\n", WN2H(Header->HWType))); + return; + } + + /* Check protocol type */ + if (Header->ProtoType != ETYPE_IPv4) { + TI_DbgPrint(DEBUG_ARP, ("Unknown ARP protocol type (0x%X).\n", WN2H(Header->ProtoType))); + return; + } + + SenderHWAddress = (PVOID)((ULONG_PTR)Header + sizeof(ARP_HEADER)); + SenderProtoAddress = (PVOID)((ULONG_PTR)SenderHWAddress + Header->HWAddrLen); + + /* Check if we have the target protocol address */ + + TargetProtoAddress = (PVOID)((ULONG_PTR)SenderProtoAddress + + Header->ProtoAddrLen + Header->HWAddrLen); + + Address = AddrBuildIPv4(*((PULONG)TargetProtoAddress)); + ADE = IPLocateADE(Address, ADE_UNICAST); + if (!ADE) { + TI_DbgPrint(DEBUG_ARP, ("Target address (0x%X) is not mine.\n", *((PULONG)TargetProtoAddress))); + return; + } + + /* Check if we know the sender */ + + AddrInitIPv4(Address, *((PULONG)SenderProtoAddress)); + NCE = NBLocateNeighbor(Address); + if (NCE) { + DereferenceObject(Address); + /* We know the sender. Update the hardware address + and state in our neighbor address cache */ + NBUpdateNeighbor(NCE, SenderHWAddress, NUD_REACHABLE); + } else { + /* The packet had our protocol address as target. The sender + may want to communicate with us soon, so add his address + to our address cache */ + NCE = NBAddNeighbor(Interface, Address, SenderHWAddress, + Header->HWAddrLen, NUD_REACHABLE); + } + if (NCE) + DereferenceObject(NCE) + + if (Header->Opcode != ARP_OPCODE_REQUEST) + return; + + /* This is a request for our address. Swap the addresses and + send an ARP reply back to the sender */ + NdisPacket = PrepareARPPacket( + Header->HWType, /* Hardware type */ + Header->ProtoType, /* Protocol type */ + (UCHAR)Interface->AddressLength, /* Hardware address length */ + (UCHAR)Header->ProtoAddrLen, /* Protocol address length */ + Interface->Address, /* Sender's (local) hardware address */ + &ADE->Address->Address, /* Sender's (local) protocol address */ + SenderHWAddress, /* Target's (remote) hardware address */ + SenderProtoAddress, /* Target's (remote) protocol address */ + ARP_OPCODE_REPLY); /* ARP reply */ + if (NdisPacket) { + PC(NdisPacket)->DLComplete = ARPTransmitComplete; + (*Interface->Transmit)(Interface->Context, + NdisPacket, + MaxLLHeaderSize, + SenderHWAddress, + LAN_PROTO_ARP); + } +} + +/* EOF */ diff --git a/drivers/net/tcpip/datalink/lan.c b/drivers/net/tcpip/datalink/lan.c new file mode 100644 index 0000000..1af32e9 --- /dev/null +++ b/drivers/net/tcpip/datalink/lan.c @@ -0,0 +1,994 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: datalink/lan.c + * PURPOSE: Local Area Network media routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + + +NDIS_HANDLE NdisProtocolHandle = (NDIS_HANDLE)NULL; +BOOLEAN ProtocolRegistered = FALSE; +LIST_ENTRY AdapterListHead; +KSPIN_LOCK AdapterListLock; + + +NDIS_STATUS NDISCall( + PLAN_ADAPTER Adapter, + NDIS_REQUEST_TYPE Type, + NDIS_OID OID, + PVOID Buffer, + UINT Length) +/* + * FUNCTION: Send a request to NDIS + * ARGUMENTS: + * Adapter = Pointer to a LAN_ADAPTER structure + * Type = Type of request (Set or Query) + * OID = Value to be set/queried for + * Buffer = Pointer to a buffer to use + * Length = Number of bytes in Buffer + * RETURNS: + * Status of operation + */ +{ + NDIS_REQUEST Request; + NDIS_STATUS NdisStatus; + + Request.RequestType = Type; + if (Type == NdisRequestSetInformation) { + Request.DATA.SET_INFORMATION.Oid = OID; + Request.DATA.SET_INFORMATION.InformationBuffer = Buffer; + Request.DATA.SET_INFORMATION.InformationBufferLength = Length; + } else { + Request.DATA.QUERY_INFORMATION.Oid = OID; + Request.DATA.QUERY_INFORMATION.InformationBuffer = Buffer; + Request.DATA.QUERY_INFORMATION.InformationBufferLength = Length; + } + + if (Adapter->State != LAN_STATE_RESETTING) { + NdisRequest(&NdisStatus, Adapter->NdisHandle, &Request); + } else { + NdisStatus = NDIS_STATUS_NOT_ACCEPTED; + } + + /* Wait for NDIS to complete the request */ + if (NdisStatus == NDIS_STATUS_PENDING) { + KeWaitForSingleObject(&Adapter->Event, + UserRequest, + KernelMode, + FALSE, + NULL); + NdisStatus = Adapter->NdisStatus; + } + + return NdisStatus; +} + + +PNDIS_PACKET AllocateTDPacket( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Allocates an NDIS packet for NdisTransferData + * ARGUMENTS: + * Adapter = Pointer to LAN_ADAPTER structure + * RETURNS: + * Pointer to NDIS packet or NULL if there was not enough free + * non-paged memory + */ +{ + NDIS_STATUS NdisStatus; + PNDIS_PACKET NdisPacket; + PNDIS_BUFFER Buffer; + PVOID Data; + + NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) + return NULL; + + Data = ExAllocatePool(NonPagedPool, Adapter->MTU); + if (!Data) { + NdisFreePacket(NdisPacket); + return NULL; + } + + NdisAllocateBuffer(&NdisStatus, + &Buffer, + GlobalBufferPool, + Data, + Adapter->MTU); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NdisFreePacket(NdisPacket); + ExFreePool(Data); + return NULL; + } + + NdisChainBufferAtFront(NdisPacket, Buffer); + + PC(NdisPacket)->Context = NULL; /* End of list */ + + return NdisPacket; +} + + +VOID FreeTDPackets( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Frees transfer data packets + * ARGUMENTS: + * Adapter = Pointer to LAN_ADAPTER structure + */ +{ + PNDIS_PACKET NdisPacket, Next; + + /* Release transfer data packets */ + NdisPacket = Adapter->TDPackets; + while (NdisPacket) { + Next = PC(NdisPacket)->Context; + FreeNdisPacket(NdisPacket); + NdisPacket = Next; + } + Adapter->TDPackets = NULL; +} + + +VOID FreeAdapter( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Frees memory for a LAN_ADAPTER structure + * ARGUMENTS: + * Adapter = Pointer to LAN_ADAPTER structure to free + */ +{ + FreeTDPackets(Adapter); + ExFreePool(Adapter); +} + + +VOID ProtocolOpenAdapterComplete( + NDIS_HANDLE BindingContext, + NDIS_STATUS Status, + NDIS_STATUS OpenErrorStatus) +/* + * FUNCTION: Called by NDIS to complete opening of an adapter + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * Status = Status of the operation + * OpenErrorStatus = Additional status information + */ +{ + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + KeSetEvent(&Adapter->Event, 0, FALSE); +} + + +VOID ProtocolCloseAdapterComplete( + NDIS_HANDLE BindingContext, + NDIS_STATUS Status) +/* + * FUNCTION: Called by NDIS to complete closing an adapter + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * Status = Status of the operation + */ +{ + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + Adapter->NdisStatus = Status; + + KeSetEvent(&Adapter->Event, 0, FALSE); +} + + +VOID ProtocolResetComplete( + NDIS_HANDLE BindingContext, + NDIS_STATUS Status) +/* + * FUNCTION: Called by NDIS to complete resetting an adapter + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * Status = Status of the operation + */ +{ + TI_DbgPrint(MID_TRACE, ("Called.\n")); +} + + +VOID ProtocolRequestComplete( + NDIS_HANDLE BindingContext, + PNDIS_REQUEST NdisRequest, + NDIS_STATUS Status) +/* + * FUNCTION: Called by NDIS to complete a request + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * NdisRequest = Pointer to an object describing the request + * Status = Status of the operation + */ +{ + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + /* Save status of request and signal an event */ + Adapter->NdisStatus = Status; + + KeSetEvent(&Adapter->Event, 0, FALSE); +} + + +VOID ProtocolSendComplete( + NDIS_HANDLE BindingContext, + PNDIS_PACKET Packet, + NDIS_STATUS Status) +/* + * FUNCTION: Called by NDIS to complete sending process + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * Packet = Pointer to a packet descriptor + * Status = Status of the operation + */ +{ + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + AdjustPacket(Packet, Adapter->HeaderSize, PC(Packet)->DLOffset); + + (*PC(Packet)->DLComplete)(Adapter->Context, Packet, Status); +} + + +VOID ProtocolTransferDataComplete( + NDIS_HANDLE BindingContext, + PNDIS_PACKET Packet, + NDIS_STATUS Status, + UINT BytesTransferred) +/* + * FUNCTION: Called by NDIS to complete reception of data + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * Packet = Pointer to a packet descriptor + * Status = Status of the operation + * BytesTransferred = Number of bytes transferred + * NOTES: + * If the packet was successfully received, determine the protocol + * type and pass it to the correct receive handler + */ +{ + UINT PacketType; + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + if (Status == NDIS_STATUS_SUCCESS) { + PNDIS_BUFFER NdisBuffer; + IP_PACKET IPPacket; + + IPPacket.NdisPacket = Packet; + + NdisGetFirstBufferFromPacket(Packet, + &NdisBuffer, + &IPPacket.Header, + &IPPacket.ContigSize, + &IPPacket.TotalSize); + + /* Determine which upper layer protocol that should receive + this packet and pass it to the correct receive handler */ + PacketType = ((PETH_HEADER)IPPacket.Header)->EType; + switch (PacketType) { + case ETYPE_IPv4: + case ETYPE_IPv6: + IPReceive(Adapter->Context, &IPPacket); + break; + case ETYPE_ARP: + ARPReceive(Adapter->Context, &IPPacket); + default: + break; + } + } + + /* Release the packet descriptor */ + KeAcquireSpinLockAtDpcLevel(&Adapter->Lock); + + PC(Packet)->Context = Adapter->TDPackets; + Adapter->TDPackets = Packet; + + KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); +} + + +NDIS_STATUS ProtocolReceive( + NDIS_HANDLE BindingContext, + NDIS_HANDLE MacReceiveContext, + PVOID HeaderBuffer, + UINT HeaderBufferSize, + PVOID LookaheadBuffer, + UINT LookaheadBufferSize, + UINT PacketSize) +/* + * FUNCTION: Called by NDIS when a packet has been received on the physical link + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * MacReceiveContext = Handle used by underlying NIC driver + * HeaderBuffer = Pointer to a buffer containing the packet header + * HeaderBufferSize = Number of bytes in HeaderBuffer + * LookaheadBuffer = Pointer to a buffer containing buffered packet data + * LookaheadBufferSize = Size of LookaheadBuffer. May be less than asked for + * PacketSize = Overall size of the packet (not including header) + * RETURNS: + * Status of operation + */ +{ + USHORT EType; + UINT PacketType; + IP_PACKET IPPacket; + PNDIS_PACKET NdisPacket; + PNDIS_BUFFER NdisBuffer; + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext; + PETH_HEADER EHeader = (PETH_HEADER)HeaderBuffer; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + if (Adapter->State != LAN_STATE_STARTED) { + TI_DbgPrint(DEBUG_DATALINK, ("Adapter is stopped.\n")); + return NDIS_STATUS_NOT_ACCEPTED; + } + + if (HeaderBufferSize < Adapter->HeaderSize) { + TI_DbgPrint(DEBUG_DATALINK, ("Runt frame received.\n")); + return NDIS_STATUS_NOT_ACCEPTED; + } + + if (Adapter->Media == NdisMedium802_3) { + /* Ethernet and IEEE 802.3 frames can be destinguished by + looking at the IEEE 802.3 length field. This field is + less than or equal to 1500 for a valid IEEE 802.3 frame + and larger than 1500 is it's a valid EtherType value. + See RFC 1122, section 2.3.3 for more information */ + /* FIXME: Test for Ethernet and IEEE 802.3 frame */ + if (((EType = EHeader->EType) != ETYPE_IPv4) && (EType != ETYPE_ARP)) { + TI_DbgPrint(DEBUG_DATALINK, ("Not IP or ARP frame. EtherType (0x%X).\n", EType)); + return NDIS_STATUS_NOT_ACCEPTED; + } + /* We use EtherType constants to destinguish packet types */ + PacketType = EType; + } else { + TI_DbgPrint(MIN_TRACE, ("Unsupported media.\n")); + /* FIXME: Support other medias */ + return NDIS_STATUS_NOT_ACCEPTED; + } + + /* Get a transfer data packet */ + + KeAcquireSpinLockAtDpcLevel(&Adapter->Lock); + + NdisPacket = Adapter->TDPackets; + if (NdisPacket == (PNDIS_PACKET)NULL) { + TI_DbgPrint(DEBUG_DATALINK, ("No available packet descriptors.\n")); + /* We don't have a free packet descriptor. Drop the packet */ + KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); + return NDIS_STATUS_SUCCESS; + } + Adapter->TDPackets = PC(NdisPacket)->Context; + + KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); + + if (LookaheadBufferSize < PacketSize) { + NDIS_STATUS NdisStatus; + UINT BytesTransferred; + + /* Get the data */ + NdisTransferData(&NdisStatus, + Adapter->NdisHandle, + MacReceiveContext, + 0, + PacketSize, + NdisPacket, + &BytesTransferred); + if (NdisStatus != NDIS_STATUS_PENDING) + ProtocolTransferDataComplete(BindingContext, + NdisPacket, + NdisStatus, + BytesTransferred); + + return NDIS_STATUS_SUCCESS; + } + + /* We got all the data in the lookahead buffer */ + + IPPacket.NdisPacket = NdisPacket; + + NdisGetFirstBufferFromPacket(NdisPacket, + &NdisBuffer, + &IPPacket.Header, + &IPPacket.ContigSize, + &IPPacket.TotalSize); + + RtlCopyMemory(IPPacket.Header, LookaheadBuffer, PacketSize); + + switch (PacketType) { + case ETYPE_IPv4: + case ETYPE_IPv6: + IPReceive(Adapter->Context, &IPPacket); + break; + case ETYPE_ARP: + ARPReceive(Adapter->Context, &IPPacket); + break; + default: + break; + } + + /* Release the packet descriptor */ + KeAcquireSpinLockAtDpcLevel(&Adapter->Lock); + + PC(NdisPacket)->Context = Adapter->TDPackets; + Adapter->TDPackets = NdisPacket; + + KeReleaseSpinLockFromDpcLevel(&Adapter->Lock); + + return NDIS_STATUS_SUCCESS; +} + + +VOID ProtocolReceiveComplete( + NDIS_HANDLE BindingContext) +/* + * FUNCTION: Called by NDIS when we're done receiving data + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + */ +{ + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); +} + + +VOID ProtocolStatus( + NDIS_HANDLE BindingContext, + NDIS_STATUS GenerelStatus, + PVOID StatusBuffer, + UINT StatusBufferSize) +/* + * FUNCTION: Called by NDIS when the underlying driver has changed state + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + * GenerelStatus = A generel status code + * StatusBuffer = Pointer to a buffer with medium-specific data + * StatusBufferSize = Number of bytes in StatusBuffer + */ +{ + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); +} + + +VOID ProtocolStatusComplete( + NDIS_HANDLE NdisBindingContext) +/* + * FUNCTION: Called by NDIS when a status-change has occurred + * ARGUMENTS: + * BindingContext = Pointer to a device context (LAN_ADAPTER) + */ +{ + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); +} + + +VOID LANTransmit( + PVOID Context, + PNDIS_PACKET NdisPacket, + UINT Offset, + PVOID LinkAddress, + USHORT Type) +/* + * FUNCTION: Transmits a packet + * ARGUMENTS: + * Context = Pointer to context information (LAN_ADAPTER) + * NdisPacket = Pointer to NDIS packet to send + * Offset = Offset in packet where data starts + * LinkAddress = Pointer to link address of destination (NULL = broadcast) + * Type = LAN protocol type (LAN_PROTO_*) + */ +{ + NDIS_STATUS NdisStatus; + PETH_HEADER EHeader; + PVOID Data; + PLAN_ADAPTER Adapter = (PLAN_ADAPTER)Context; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + /* NDIS send routines don't have an offset argument so we + must offset the data in upper layers and adjust the + packet here. We save the offset in the packet context + area so it can be undone before we release the packet */ + Data = AdjustPacket(NdisPacket, Offset, Adapter->HeaderSize); + PC(NdisPacket)->DLOffset = Offset; + + if (Adapter->State == LAN_STATE_STARTED) { + switch (Adapter->Media) { + case NdisMedium802_3: + EHeader = (PETH_HEADER)Data; + + if (LinkAddress) { + /* Unicast address */ + RtlCopyMemory(EHeader->DstAddr, LinkAddress, IEEE_802_ADDR_LENGTH); + } else { + /* Broadcast address */ + RtlFillMemory(EHeader->DstAddr, IEEE_802_ADDR_LENGTH, 0xFF); + } + + RtlCopyMemory(EHeader->SrcAddr, Adapter->HWAddress, IEEE_802_ADDR_LENGTH); + + switch (Type) { + case LAN_PROTO_IPv4: + EHeader->EType = ETYPE_IPv4; + break; + case LAN_PROTO_ARP: + EHeader->EType = ETYPE_ARP; + break; + case LAN_PROTO_IPv6: + EHeader->EType = ETYPE_IPv6; + break; + default: +#ifdef DBG + /* Should not happen */ + TI_DbgPrint(MIN_TRACE, ("Unknown LAN protocol.\n")); + + ProtocolSendComplete((NDIS_HANDLE)Context, + NdisPacket, + NDIS_STATUS_FAILURE); +#endif + return; + } + break; + + default: + /* FIXME: Support other medias */ + break; + } + + NdisSend(&NdisStatus, Adapter->NdisHandle, NdisPacket); + if (NdisStatus != NDIS_STATUS_PENDING) + ProtocolSendComplete((NDIS_HANDLE)Context, NdisPacket, NdisStatus); + } else { + ProtocolSendComplete((NDIS_HANDLE)Context, NdisPacket, NDIS_STATUS_CLOSED); + } +} + + +VOID BindAdapter( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Binds a LAN adapter to IP layer + * ARGUMENTS: + * Adapter = Pointer to LAN_ADAPTER structure + * NOTES: + * We set the lookahead buffer size, set the packet filter and + * bind the adapter to IP layer + */ +{ + INT i; + PIP_INTERFACE IF; + PIP_ADDRESS Address; + PNDIS_PACKET Packet; + NDIS_STATUS NdisStatus; + LLIP_BIND_INFO BindInfo; + ULONG Lookahead = LOOKAHEAD_SIZE; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + Adapter->State = LAN_STATE_OPENING; + + NdisStatus = NDISCall(Adapter, + NdisRequestSetInformation, + OID_GEN_CURRENT_LOOKAHEAD, + &Lookahead, + sizeof(ULONG)); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MID_TRACE, ("Could not set lookahead buffer size (0x%X).\n", NdisStatus)); + return; + } + + /* Allocate packets for NdisTransferData */ + /* FIXME: How many should we allocate? */ + Adapter->TDPackets = NULL; + for (i = 0; i < 2; i++) { + Packet = AllocateTDPacket(Adapter); + PC(Packet)->Context = Adapter->TDPackets; + Adapter->TDPackets = Packet; + if (!Packet) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + FreeTDPackets(Adapter); + return; + } + } + + /* Bind the adapter to IP layer */ + BindInfo.Context = Adapter; + BindInfo.HeaderSize = Adapter->HeaderSize; + BindInfo.MinFrameSize = Adapter->MinFrameSize; + BindInfo.MTU = Adapter->MTU; + BindInfo.Address = (PUCHAR)&Adapter->HWAddress; + BindInfo.AddressLength = Adapter->HWAddressLength; + BindInfo.Transmit = LANTransmit; + + IF = IPCreateInterface(&BindInfo); + if (!IF) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + FreeTDPackets(Adapter); + return; + } + + /* FIXME: Get address from registry. + For now just use a private address, eg. 10.0.0.100 */ + Address = AddrBuildIPv4(0x6400000A); + if (!Address) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + FreeTDPackets(Adapter); + IPDestroyInterface(Adapter->Context); + return; + } + /* Create a net table entry for this interface */ + if (!IPCreateNTE(IF, Address, 8)) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + FreeTDPackets(Adapter); + IPDestroyInterface(IF); + return; + } + + /* Reference the interface for the NTE. The reference + for the address is just passed on to the NTE */ + ReferenceObject(IF); + + /* Register interface with IP layer */ + IPRegisterInterface(IF); + + /* Set packet filter so we can send and receive packets */ + NdisStatus = NDISCall(Adapter, + NdisRequestSetInformation, + OID_GEN_CURRENT_PACKET_FILTER, + &Adapter->PacketFilter, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MID_TRACE, ("Could not set packet filter (0x%X).\n", NdisStatus)); + FreeTDPackets(Adapter); + IPDestroyInterface(IF); + return; + } + + Adapter->Context = IF; + + Adapter->State = LAN_STATE_STARTED; +} + + +VOID UnbindAdapter( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Unbinds a LAN adapter from IP layer + * ARGUMENTS: + * Adapter = Pointer to LAN_ADAPTER structure + */ +{ + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + if (Adapter->State == LAN_STATE_STARTED) { + PIP_INTERFACE IF = Adapter->Context; + + IPUnregisterInterface(IF); + + IPDestroyInterface(IF); + + /* Free transfer data packets */ + FreeTDPackets(Adapter); + } +} + + +NDIS_STATUS LANRegisterAdapter( + PNDIS_STRING AdapterName, + PLAN_ADAPTER *Adapter) +/* + * FUNCTION: Registers protocol with an NDIS adapter + * ARGUMENTS: + * AdapterName = Pointer to string with name of adapter to register + * Adapter = Address of pointer to a LAN_ADAPTER structure + * RETURNS: + * Status of operation + */ +{ + PLAN_ADAPTER IF; + NDIS_STATUS NdisStatus; + NDIS_STATUS OpenStatus; + UINT MediaIndex; + NDIS_MEDIUM MediaArray[MAX_MEDIA]; + UINT AddressOID; + UINT Speed; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + IF = ExAllocatePool(NonPagedPool, sizeof(LAN_ADAPTER)); + if (!IF) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NDIS_STATUS_RESOURCES; + } + + RtlZeroMemory(IF, sizeof(LAN_ADAPTER)); + + /* Put adapter in stopped state */ + IF->State = LAN_STATE_STOPPED; + + /* Initialize protecting spin lock */ + KeInitializeSpinLock(&IF->Lock); + + KeInitializeEvent(&IF->Event, SynchronizationEvent, FALSE); + + /* Initialize array with media IDs we support */ + MediaArray[MEDIA_ETH] = NdisMedium802_3; + + /* Open the adapter. */ + NdisOpenAdapter(&NdisStatus, + &OpenStatus, + &IF->NdisHandle, + &MediaIndex, + MediaArray, + MAX_MEDIA, + NdisProtocolHandle, + IF, + AdapterName, + 0, + NULL); + + /* Wait until the adapter is opened */ + if (NdisStatus == NDIS_STATUS_PENDING) + KeWaitForSingleObject(&IF->Event, UserRequest, KernelMode, FALSE, NULL); + else if (NdisStatus != NDIS_STATUS_SUCCESS) { + ExFreePool(IF); + return NdisStatus; + } + + IF->Media = MediaArray[MediaIndex]; + + /* Fill LAN_ADAPTER structure with some adapter specific information */ + switch (IF->Media) { + case NdisMedium802_3: + IF->HWAddressLength = IEEE_802_ADDR_LENGTH; + IF->BCastMask = BCAST_ETH_MASK; + IF->BCastCheck = BCAST_ETH_CHECK; + IF->BCastOffset = BCAST_ETH_OFFSET; + IF->HeaderSize = sizeof(ETH_HEADER); + IF->MinFrameSize = 60; + AddressOID = OID_802_3_CURRENT_ADDRESS; + IF->PacketFilter = + NDIS_PACKET_TYPE_BROADCAST | + NDIS_PACKET_TYPE_DIRECTED | + NDIS_PACKET_TYPE_MULTICAST; + break; + + default: + /* Unsupported media */ + TI_DbgPrint(MIN_TRACE, ("Unsupported media.\n")); + ExFreePool(IF); + return NDIS_STATUS_NOT_SUPPORTED; + } + + /* Get maximum frame size */ + NdisStatus = NDISCall(IF, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_FRAME_SIZE, + &IF->MTU, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + ExFreePool(IF); + return NdisStatus; + } + + /* Get maximum packet size */ + NdisStatus = NDISCall(IF, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_TOTAL_SIZE, + &IF->MaxPacketSize, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Query for maximum packet size failed.\n")); + ExFreePool(IF); + return NdisStatus; + } + + /* Get maximum number of packets we can pass to NdisSend(Packets) at one time */ + NdisStatus = NDISCall(IF, + NdisRequestQueryInformation, + OID_GEN_MAXIMUM_SEND_PACKETS, + &IF->MaxSendPackets, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) + /* Legacy NIC drivers may not support this query, if it fails we + assume it can send at least one packet per call to NdisSend(Packets) */ + IF->MaxSendPackets = 1; + + /* Get current hardware address */ + NdisStatus = NDISCall(IF, + NdisRequestQueryInformation, + AddressOID, + &IF->HWAddress, + IF->HWAddressLength); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Query for current hardware address failed.\n")); + ExFreePool(IF); + return NdisStatus; + } + + /* Get maximum link speed */ + NdisStatus = NDISCall(IF, + NdisRequestQueryInformation, + OID_GEN_LINK_SPEED, + &Speed, + sizeof(UINT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Query for maximum link speed failed.\n")); + ExFreePool(IF); + return NdisStatus; + } + + /* Convert returned link speed to bps (it is in 100bps increments) */ + IF->Speed = Speed * 100L; + + *Adapter = IF; + + /* Add adapter to the adapter list */ + ExInterlockedInsertTailList(&AdapterListHead, + &IF->ListEntry, + &AdapterListLock); + + /* Bind adapter to IP layer */ + BindAdapter(IF); + + TI_DbgPrint(DEBUG_DATALINK, ("Leaving.\n")); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS LANUnregisterAdapter( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Unregisters protocol with NDIS adapter + * ARGUMENTS: + * Adapter = Pointer to a LAN_ADAPTER structure + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; + NDIS_HANDLE NdisHandle; + NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + /* Unlink the adapter from the list */ + RemoveEntryList(&Adapter->ListEntry); + + /* Unbind adapter from IP layer */ + UnbindAdapter(Adapter); + + KeAcquireSpinLock(&Adapter->Lock, &OldIrql); + NdisHandle = Adapter->NdisHandle; + if (NdisHandle) { + Adapter->NdisHandle = NULL; + KeReleaseSpinLock(&Adapter->Lock, OldIrql); + + NdisCloseAdapter(&NdisStatus, NdisHandle); + if (NdisStatus == NDIS_STATUS_PENDING) { + KeWaitForSingleObject(&Adapter->Event, + UserRequest, + KernelMode, + FALSE, + NULL); + NdisStatus = Adapter->NdisStatus; + } + } else + KeReleaseSpinLock(&Adapter->Lock, OldIrql); + + FreeAdapter(Adapter); + + return NDIS_STATUS_SUCCESS; +} + + +NTSTATUS LANRegisterProtocol( + PSTRING Name) +/* + * FUNCTION: Registers this protocol driver with NDIS + * ARGUMENTS: + * Name = Name of this protocol driver + * RETURNS: + * Status of operation + */ +{ + NDIS_STATUS NdisStatus; + NDIS_PROTOCOL_CHARACTERISTICS ProtChars; + + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + InitializeListHead(&AdapterListHead); + KeInitializeSpinLock(&AdapterListLock); + + /* Set up protocol characteristics */ + RtlZeroMemory(&ProtChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); + ProtChars.MajorNdisVersion = NDIS_VERSION_MAJOR; + ProtChars.MinorNdisVersion = NDIS_VERSION_MINOR; + ProtChars.Name.Length = Name->Length; + ProtChars.Name.Buffer = (PVOID)Name->Buffer; + ProtChars.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete; + ProtChars.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete; + ProtChars.ResetCompleteHandler = ProtocolResetComplete; + ProtChars.RequestCompleteHandler = ProtocolRequestComplete; + ProtChars.u2.SendCompleteHandler = ProtocolSendComplete; + ProtChars.u3.TransferDataCompleteHandler = ProtocolTransferDataComplete; + ProtChars.u4.ReceiveHandler = ProtocolReceive; + ProtChars.ReceiveCompleteHandler = ProtocolReceiveComplete; + ProtChars.StatusHandler = ProtocolStatus; + ProtChars.StatusCompleteHandler = ProtocolStatusComplete; + + /* Try to register protocol */ + NdisRegisterProtocol(&NdisStatus, + &NdisProtocolHandle, + &ProtChars, + sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + Name->Length); + if (NdisStatus != NDIS_STATUS_SUCCESS) + return (NTSTATUS)NdisStatus; + + ProtocolRegistered = TRUE; + + return STATUS_SUCCESS; +} + + +VOID LANUnregisterProtocol( + VOID) +/* + * FUNCTION: Unregisters this protocol driver with NDIS + * NOTES: Does not care wether we are already registered + */ +{ + TI_DbgPrint(DEBUG_DATALINK, ("Called.\n")); + + if (ProtocolRegistered) { + NDIS_STATUS NdisStatus; + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PLAN_ADAPTER Current; + KIRQL OldIrql; + + KeAcquireSpinLock(&AdapterListLock, &OldIrql); + + /* Search the list and remove every adapter we find */ + CurrentEntry = AdapterListHead.Flink; + while (CurrentEntry != &AdapterListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, LAN_ADAPTER, ListEntry); + /* Unregister it */ + LANUnregisterAdapter(Current); + CurrentEntry = NextEntry; + } + + KeReleaseSpinLock(&AdapterListLock, OldIrql); + + NdisDeregisterProtocol(&NdisStatus, NdisProtocolHandle); + ProtocolRegistered = FALSE; + } +} + +/* EOF */ diff --git a/drivers/net/tcpip/datalink/loopback.c b/drivers/net/tcpip/datalink/loopback.c new file mode 100644 index 0000000..9172ad7 --- /dev/null +++ b/drivers/net/tcpip/datalink/loopback.c @@ -0,0 +1,214 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: datalink/loopback.c + * PURPOSE: Loopback adapter + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + + +WORK_QUEUE_ITEM LoopWorkItem; +PIP_INTERFACE Loopback = NULL; +/* Indicates wether the loopback interface is currently transmitting */ +BOOLEAN LoopBusy = FALSE; +/* Loopback transmit queue */ +PNDIS_PACKET LoopQueueHead = (PNDIS_PACKET)NULL; +PNDIS_PACKET LoopQueueTail = (PNDIS_PACKET)NULL; +/* Spin lock for protecting loopback transmit queue */ +KSPIN_LOCK LoopLock; + + +VOID RealTransmit( + PVOID Context) +/* + * FUNCTION: Transmits one or more packet(s) in loopback queue to ourselves + * ARGUMENTS: + * Context = Pointer to context information (loopback interface) + */ +{ + KIRQL OldIrql; + PNDIS_PACKET NdisPacket; + PNDIS_BUFFER NdisBuffer; + IP_PACKET IPPacket; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + KeAcquireSpinLockAtDpcLevel(&LoopLock); + + for (;;) { + /* Get the next packet from the queue (if any) */ + NdisPacket = LoopQueueHead; + if (!NdisPacket) + break; + + TI_DbgPrint(MAX_TRACE, ("NdisPacket (0x%X)\n", NdisPacket)); + + LoopQueueHead = *(PNDIS_PACKET*)NdisPacket->u.s3.MacReserved; + KeReleaseSpinLockFromDpcLevel(&LoopLock); + IPPacket.NdisPacket = NdisPacket; + + NdisGetFirstBufferFromPacket(NdisPacket, + &NdisBuffer, + &IPPacket.Header, + &IPPacket.ContigSize, + &IPPacket.TotalSize); + IPReceive(Context, &IPPacket); + AdjustPacket(NdisPacket, 0, PC(NdisPacket)->DLOffset); + PC(NdisPacket)->DLComplete(Context, NdisPacket, NDIS_STATUS_SUCCESS); + /* Lower IRQL for a moment to prevent starvation */ + KeLowerIrql(OldIrql); + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + KeAcquireSpinLockAtDpcLevel(&LoopLock); + } + LoopBusy = FALSE; + KeReleaseSpinLockFromDpcLevel(&LoopLock); + KeLowerIrql(OldIrql); +} + + +VOID LoopTransmit( + PVOID Context, + PNDIS_PACKET NdisPacket, + UINT Offset, + PVOID LinkAddress, + USHORT Type) +/* + * FUNCTION: Transmits a packet + * ARGUMENTS: + * Context = Pointer to context information (NULL) + * NdisPacket = Pointer to NDIS packet to send + * Offset = Offset in packet where packet data starts + * LinkAddress = Pointer to link address + * Type = LAN protocol type (unused) + */ +{ + PNDIS_PACKET *pNdisPacket; + KIRQL OldIrql; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* NDIS send routines don't have an offset argument so we + must offset the data in upper layers and adjust the + packet here. We save the offset in the packet context + area so it can be undone before we release the packet */ + AdjustPacket(NdisPacket, Offset, 0); + PC(NdisPacket)->DLOffset = Offset; + + pNdisPacket = (PNDIS_PACKET*)NdisPacket->u.s3.MacReserved; + *pNdisPacket = NULL; + + KeAcquireSpinLock(&LoopLock, &OldIrql); + + /* Add packet to transmit queue */ + if (LoopQueueHead) { + /* Transmit queue is not empty */ + pNdisPacket = (PNDIS_PACKET*)LoopQueueTail->u.s3.MacReserved; + *pNdisPacket = NdisPacket; + } else + /* Transmit queue is empty */ + LoopQueueHead = NdisPacket; + + LoopQueueTail = NdisPacket; + + /* If LoopTransmit is not running (or scheduled), schedule it to run */ + if (!LoopBusy) { + LoopBusy = TRUE; + ExQueueWorkItem(&LoopWorkItem, CriticalWorkQueue); + } + + KeReleaseSpinLock(&LoopLock, OldIrql); +} + + +NDIS_STATUS LoopRegisterAdapter( + PNDIS_STRING AdapterName, + PLAN_ADAPTER *Adapter) +/* + * FUNCTION: Registers loopback adapter + * ARGUMENTS: + * AdapterName = Unused + * Adapter = Unused + * RETURNS: + * Status of operation + */ +{ + PIP_ADDRESS Address; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + Address = AddrBuildIPv4(LOOPBACK_ADDRESS_IPv4); + if (Address) { + LLIP_BIND_INFO BindInfo; + + /* Bind the adapter to IP layer */ + BindInfo.Context = NULL; + BindInfo.HeaderSize = 0; + BindInfo.MinFrameSize = 0; + BindInfo.MTU = 16384; + BindInfo.Address = NULL; + BindInfo.AddressLength = 0; + BindInfo.Transmit = LoopTransmit; + + Loopback = IPCreateInterface(&BindInfo); + if ((Loopback) && (IPCreateNTE(Loopback, Address, 8))) { + /* Reference the interface for the NTE. The reference for + the address is just passed on to the NTE */ + ReferenceObject(Loopback); + + IPRegisterInterface(Loopback); + + ExInitializeWorkItem(&LoopWorkItem, RealTransmit, Loopback); + + KeInitializeSpinLock(&LoopLock); + LoopBusy = FALSE; + } else + Status = NDIS_STATUS_RESOURCES; + } else + Status = NDIS_STATUS_RESOURCES; + + if (!NT_SUCCESS(Status)) + LoopUnregisterAdapter(NULL); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return Status; +} + + +NDIS_STATUS LoopUnregisterAdapter( + PLAN_ADAPTER Adapter) +/* + * FUNCTION: Unregisters loopback adapter + * ARGUMENTS: + * Adapter = Unused + * RETURNS: + * Status of operation + * NOTES: + * Does not care wether we have registered loopback adapter + */ +{ + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + if (Loopback) { + IPUnregisterInterface(Loopback); + IPDestroyInterface(Loopback); + Loopback = NULL; + } + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return NDIS_STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/tcpip/include/address.h b/drivers/net/tcpip/include/address.h new file mode 100644 index 0000000..171da16 --- /dev/null +++ b/drivers/net/tcpip/include/address.h @@ -0,0 +1,78 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/address.h + * PURPOSE: Address manipulation prototypes + */ +#ifndef __ADDRESS_H +#define __ADDRESS_H + +/* + * Initialize an IPv4 style address + * VOID AddrInitIPv4( + * PIP_ADDRESS IPAddress, + * IPv4_RAW_ADDRESS RawAddress) + */ +#define AddrInitIPv4(IPAddress, RawAddress) \ +{ \ + INIT_TAG((IPAddress), TAG('I','P','V','4')); \ + (IPAddress)->RefCount = 1; \ + (IPAddress)->Type = IP_ADDRESS_V4; \ + (IPAddress)->Address.IPv4Address = (RawAddress); \ + (IPAddress)->Free = IPAddressFree; \ +} + +#ifdef DBG + +PCHAR A2S( + PIP_ADDRESS Address); + +#endif /* DBG */ + +VOID IPAddressFree( + PVOID Object); + +BOOLEAN AddrIsUnspecified( + PIP_ADDRESS Address); + +NTSTATUS AddrGetAddress( + PTRANSPORT_ADDRESS AddrList, + PIP_ADDRESS *Address, + PUSHORT Port, + PIP_ADDRESS *Cache); + +NTSTATUS AddrBuildAddress( + PTA_ADDRESS TdiAddress, + PIP_ADDRESS *Address, + PUSHORT Port); + +BOOLEAN AddrIsEqual( + PIP_ADDRESS Address1, + PIP_ADDRESS Address2); + +INT AddrCompare( + PIP_ADDRESS Address1, + PIP_ADDRESS Address2); + +BOOLEAN AddrIsEqualIPv4( + PIP_ADDRESS Address1, + IPv4_RAW_ADDRESS Address2); + +PIP_ADDRESS AddrBuildIPv4( + IPv4_RAW_ADDRESS Address); + +PADDRESS_ENTRY AddrLocateADEv4( + IPv4_RAW_ADDRESS Address); + +PADDRESS_FILE AddrSearchFirst( + PIP_ADDRESS Address, + USHORT Port, + USHORT Protocol, + PAF_SEARCH SearchContext); + +PADDRESS_FILE AddrSearchNext( + PAF_SEARCH SearchContext); + +#endif /* __ADDRESS_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/arp.h b/drivers/net/tcpip/include/arp.h new file mode 100644 index 0000000..bd1c6bf --- /dev/null +++ b/drivers/net/tcpip/include/arp.h @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/arp.h + * PURPOSE: Address Resolution Protocol definitions + */ +#ifndef __ARP_H +#define __ARP_H + +typedef struct ARP_HEADER { + USHORT HWType; /* Hardware Type */ + USHORT ProtoType; /* Protocol Type */ + UCHAR HWAddrLen; /* Hardware Address Length */ + UCHAR ProtoAddrLen; /* Protocol Address Length */ + USHORT Opcode; /* Opcode */ + /* Sender's Hardware Address */ + /* Sender's Protocol Address */ + /* Target's Hardware Address */ + /* Target's Protocol Address */ +} ARP_HEADER, *PARP_HEADER; + +/* We swap constants so we can compare values at runtime without swapping them */ +#define ARP_OPCODE_REQUEST WH2N(0x0001) /* ARP request */ +#define ARP_OPCODE_REPLY WH2N(0x0002) /* ARP reply */ + + +BOOLEAN ARPTransmit( + PIP_ADDRESS Address, + PNET_TABLE_ENTRY NTE); + +VOID ARPReceive( + PVOID Context, + PIP_PACKET Packet); + +#endif /* __ARP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/checksum.h b/drivers/net/tcpip/include/checksum.h new file mode 100644 index 0000000..e23c0a5 --- /dev/null +++ b/drivers/net/tcpip/include/checksum.h @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/checksum.h + * PURPOSE: Checksum routine definitions + */ +#ifndef __CHECKSUM_H +#define __CHECKSUM_H + + +ULONG ChecksumCompute( + PVOID Data, + UINT Count, + ULONG Seed); + +#define IPv4Checksum(Data, Count, Seed)(ChecksumCompute(Data, Count, Seed)) + +/* + * Macro to check for a correct checksum + * BOOLEAN CorrectChecksum(PVOID Data, UINT Count) + */ +#define CorrectChecksum(Data, Count) \ + (BOOLEAN)(IPv4Checksum(Data, Count, 0) == DH2N(0x0000FFFF)) + +#endif /* __CHECKSUM_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/datagram.h b/drivers/net/tcpip/include/datagram.h new file mode 100644 index 0000000..f2cc413 --- /dev/null +++ b/drivers/net/tcpip/include/datagram.h @@ -0,0 +1,59 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/datagram.h + * PURPOSE: Datagram types and constants + */ +#ifndef __DATAGRAM_H +#define __DATAGRAM_H + +#include + + +VOID DGSend( + PVOID Context, + PDATAGRAM_SEND_REQUEST SendRequest); + +VOID DGDeliverData( + PADDRESS_FILE AddrFile, + PIP_ADDRESS Address, + PIP_PACKET IPPacket, + UINT DataSize); + +VOID DGCancelSendRequest( + PADDRESS_FILE AddrFile, + PVOID Context); + +VOID DGCancelReceiveRequest( + PADDRESS_FILE AddrFile, + PVOID Context); + +NTSTATUS DGTransmit( + PADDRESS_FILE AddressFile, + PDATAGRAM_SEND_REQUEST SendRequest); + +NTSTATUS DGSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize, + DATAGRAM_BUILD_ROUTINE Build); + +NTSTATUS DGReceiveDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG ReceiveLength, + ULONG ReceiveFlags, + PTDI_CONNECTION_INFORMATION ReturnInfo, + PULONG BytesReceived); + +NTSTATUS DGStartup( + VOID); + +NTSTATUS DGShutdown( + VOID); + +#endif /* __DATAGRAM_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/debug.h b/drivers/net/tcpip/include/debug.h new file mode 100644 index 0000000..768907e --- /dev/null +++ b/drivers/net/tcpip/include/debug.h @@ -0,0 +1,106 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_CHECK 0x00000100 +#define DEBUG_MEMORY 0x00000200 +#define DEBUG_BUFFER 0x00000400 +#define DEBUG_IRP 0x00000800 +#define DEBUG_REFCOUNT 0x00001000 +#define DEBUG_ADDRFILE 0x00002000 +#define DEBUG_DATALINK 0x00004000 +#define DEBUG_ARP 0x00008000 +#define DEBUG_IP 0x00010000 +#define DEBUG_ICMP 0x00020000 +#define DEBUG_ROUTER 0x00040000 +#define DEBUG_RCACHE 0x00080000 +#define DEBUG_NCACHE 0x00100000 +#define DEBUG_CPOINT 0x00200000 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#ifdef _MSC_VER + +#define TI_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d) ", __FILE__, __LINE__); \ + DbgPrint _x_ ; \ + } + +#else /* _MSC_VER */ + +#define TI_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_ ; \ + } + +#endif /* _MSC_VER */ + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { TI_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } +#endif /* NASSERT */ + +#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) + +#else /* DBG */ + +#define TI_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#ifdef _MSC_VER + +#define UNIMPLEMENTED \ + TI_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \ + but come back another day.\n", __FILE__, __LINE__)); + +#else /* _MSC_VER */ + +#define UNIMPLEMENTED \ + TI_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \ + but come back another day.\n", __FILE__, __LINE__, __FUNCTION__)); + +#endif /* _MSC_VER */ + + +#define CHECKPOINT \ + do { TI_DbgPrint(DEBUG_CHECK, ("(%s:%d)\n", __FILE__, __LINE__)); } while(0); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/dispatch.h b/drivers/net/tcpip/include/dispatch.h new file mode 100644 index 0000000..5108ff5 --- /dev/null +++ b/drivers/net/tcpip/include/dispatch.h @@ -0,0 +1,61 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/dispatch.h + * PURPOSE: Dispatch routine prototypes + */ +#ifndef __DISPATCH_H +#define __DISPATCH_H + + +NTSTATUS DispTdiAccept( + PIRP Irp); + +NTSTATUS DispTdiAssociateAddress( + PIRP Irp); + +NTSTATUS DispTdiConnect( + PIRP Irp); + +NTSTATUS DispTdiDisassociateAddress( + PIRP Irp); + +NTSTATUS DispTdiDisconnect( + PIRP Irp); + +NTSTATUS DispTdiListen( + PIRP Irp); + +NTSTATUS DispTdiQueryInformation( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS DispTdiReceive( + PIRP Irp); + +NTSTATUS DispTdiReceiveDatagram( + PIRP Irp); + +NTSTATUS DispTdiSend( + PIRP Irp); + +NTSTATUS DispTdiSendDatagram( + PIRP Irp); + +NTSTATUS DispTdiSetEventHandler( + PIRP Irp); + +NTSTATUS DispTdiSetInformation( + PIRP Irp); + +NTSTATUS DispTdiQueryInformationEx( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +NTSTATUS DispTdiSetInformationEx( + PIRP Irp, + PIO_STACK_LOCATION IrpSp); + +#endif /* __DISPATCH_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/fileobjs.h b/drivers/net/tcpip/include/fileobjs.h new file mode 100644 index 0000000..4ce5f2c --- /dev/null +++ b/drivers/net/tcpip/include/fileobjs.h @@ -0,0 +1,41 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/fileobjs.h + * PURPOSE: File object routine prototypes + */ +#ifndef __FILEOBJS_H +#define __FILEOBJS_H + + +extern LIST_ENTRY AddressFileListHead; +extern KSPIN_LOCK AddressFileListLock; +extern LIST_ENTRY ConnectionEndpointListHead; +extern KSPIN_LOCK ConnectionEndpointListLock; + + +NTSTATUS FileOpenAddress( + PTDI_REQUEST Request, + PTA_ADDRESS_IP AddrList, + USHORT Protocol, + PVOID Options); + +NTSTATUS FileCloseAddress( + PTDI_REQUEST Request); + +NTSTATUS FileOpenConnection( + PTDI_REQUEST Request, + PVOID ClientContext); + +NTSTATUS FileCloseConnection( + PTDI_REQUEST Request); + +NTSTATUS FileOpenControlChannel( + PTDI_REQUEST Request); + +NTSTATUS FileCloseControlChannel( + PTDI_REQUEST Request); + +#endif /* __FILEOBJS_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/icmp.h b/drivers/net/tcpip/include/icmp.h new file mode 100644 index 0000000..10bd22c --- /dev/null +++ b/drivers/net/tcpip/include/icmp.h @@ -0,0 +1,68 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/icmp.h + * PURPOSE: Internet Control Message Protocol definitions + */ +#ifndef __ICMP_H +#define __ICMP_H + +typedef struct ICMP_HEADER { + UCHAR Type; /* ICMP message type */ + UCHAR Code; /* ICMP message code */ + USHORT Checksum; /* ICMP message checksum */ + ULONG Unused; /* ICMP unused */ +} ICMP_HEADER, *PICMP_HEADER; + +/* ICMP message types */ +#define ICMP_TYPE_ECHO_REPLY 0 /* Echo reply */ +#define ICMP_TYPE_DEST_UNREACH 3 /* Destination unreachable */ +#define ICMP_TYPE_SOURCE_QUENCH 4 /* Source quench */ +#define ICMP_TYPE_REDIRECT 5 /* Redirect */ +#define ICMP_TYPE_ECHO_REQUEST 8 /* Echo request */ +#define ICMP_TYPE_TIME_EXCEEDED 11 /* Time exceeded */ +#define ICMP_TYPE_PARAMETER 12 /* Parameter problem */ +#define ICMP_TYPE_TIMESTAMP_REQUEST 13 /* Timestamp request */ +#define ICMP_TYPE_TIMESTAMP_REPLY 14 /* Timestamp reply */ +#define ICMP_TYPE_INFO_REQUEST 15 /* Information request */ +#define ICMP_TYPE_INFO_REPLY 16 /* Information reply */ + +/* ICMP codes for ICMP_TYPE_DEST_UNREACH */ +#define ICMP_CODE_DU_NET_UNREACH 0 /* Network unreachable */ +#define ICMP_CODE_DU_HOST_UNREACH 1 /* Host unreachable */ +#define ICMP_CODE_DU_PROTOCOL_UNREACH 2 /* Protocol unreachable */ +#define ICMP_CODE_DU_PORT_UNREACH 3 /* Port unreachable */ +#define ICMP_CODE_DU_FRAG_DF_SET 4 /* Fragmentation needed and DF set */ +#define ICMP_CODE_DU_SOURCE_ROUTE_FAILED 5 /* Source route failed */ + +/* ICMP codes for ICMP_TYPE_REDIRECT */ +#define ICMP_CODE_RD_NET 0 /* Redirect datagrams for the network */ +#define ICMP_CODE_RD_HOST 1 /* Redirect datagrams for the host */ +#define ICMP_CODE_RD_TOS_NET 2 /* Redirect datagrams for the Type of Service and network */ +#define ICMP_CODE_RD_TOS_HOST 3 /* Redirect datagrams for the Type of Service and host */ + +/* ICMP codes for ICMP_TYPE_TIME_EXCEEDED */ +#define ICMP_CODE_TE_TTL 0 /* Time to live exceeded in transit */ +#define ICMP_CODE_TE_REASSEMBLY 1 /* Fragment reassembly time exceeded */ + +/* ICMP codes for ICMP_TYPE_PARAMETER */ +#define ICMP_CODE_TP_POINTER 1 /* Pointer indicates the error */ + + +VOID ICMPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket); + +VOID ICMPTransmit( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket); + +VOID ICMPReply( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket, + UCHAR Type, + UCHAR Code); + +#endif /* __ICMP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/info.h b/drivers/net/tcpip/include/info.h new file mode 100644 index 0000000..a1b4f67 --- /dev/null +++ b/drivers/net/tcpip/include/info.h @@ -0,0 +1,93 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/info.h + * PURPOSE: TdiQueryInformation definitions + */ +#ifndef __INFO_H +#define __INFO_H + + +typedef struct IPSNMP_INFO { + ULONG Forwarding; + ULONG DefaultTTL; + ULONG InReceives; + ULONG InHdrErrors; + ULONG InAddrErrors; + ULONG ForwDatagrams; + ULONG InUnknownProtos; + ULONG InDiscards; + ULONG InDelivers; + ULONG OutRequests; + ULONG RoutingDiscards; + ULONG OutDiscards; + ULONG OutNoRoutes; + ULONG ReasmTimeout; + ULONG ReasmReqds; + ULONG ReasmOks; + ULONG ReasmFails; + ULONG FragOks; + ULONG FragFails; + ULONG FragCreates; + ULONG NumIf; + ULONG NumAddr; + ULONG NumRoutes; +} IPSNMP_INFO, *PIPSNMP_INFO; + +typedef struct IPADDR_ENTRY { + ULONG Addr; + ULONG Index; + ULONG Mask; + ULONG BcastAddr; + ULONG ReasmSize; + USHORT Context; + USHORT Pad; +} IPADDR_ENTRY, *PIPADDR_ENTRY; + +#define IP_MIB_STATS_ID 1 +#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 + +#define MAX_PHYSADDR_SIZE 8 + + +/* Only UDP is supported */ +#define TDI_SERVICE_FLAGS (TDI_SERVICE_CONNECTIONLESS_MODE | \ + TDI_SERVICE_BROADCAST_SUPPORTED) + +#define TCP_MIB_STAT_ID 1 +#define UDP_MIB_STAT_ID 1 +#define TCP_MIB_TABLE_ID 0x101 +#define UDP_MIB_TABLE_ID 0x101 + +#define TL_INSTANCE 0 + + +typedef struct ADDRESS_INFO { + ULONG LocalAddress; + ULONG LocalPort; +} ADDRESS_INFO, *PADDRESS_INFO; + +typedef union TDI_INFO { + TDI_CONNECTION_INFO ConnInfo; + TDI_ADDRESS_INFO AddrInfo; + TDI_PROVIDER_INFO ProviderInfo; + TDI_PROVIDER_STATISTICS ProviderStats; +} TDI_INFO, *PTDI_INFO; + + +TDI_STATUS InfoTdiQueryInformationEx( + PTDI_REQUEST Request, + TDIObjectID *ID, + PNDIS_BUFFER Buffer, + PUINT BufferSize, + PVOID Context); + +TDI_STATUS InfoTdiSetInformationEx( + PTDI_REQUEST Request, + TDIObjectID *ID, + PVOID Buffer, + UINT BufferSize); + +#endif /* __INFO_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/ip.h b/drivers/net/tcpip/include/ip.h new file mode 100644 index 0000000..7c8be71 --- /dev/null +++ b/drivers/net/tcpip/include/ip.h @@ -0,0 +1,266 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/ip.h + * PURPOSE: Internet Protocol related definitions + */ +#ifndef __IP_H +#define __IP_H + +typedef VOID (*OBJECT_FREE_ROUTINE)(PVOID Object); + + +/* Raw IPv4 style address */ +typedef ULONG IPv4_RAW_ADDRESS; +typedef IPv4_RAW_ADDRESS *PIPv4_RAW_ADDRESS; + +/* Raw IPv6 style address */ +typedef USHORT IPv6_RAW_ADDRESS[8]; +typedef IPv6_RAW_ADDRESS *PIPv6_RAW_ADDRESS; + +/* IP style address */ +typedef struct IP_ADDRESS { + DEFINE_TAG + ULONG RefCount; /* Number of references to this address */ + UCHAR Type; /* Type of IP address */ + union { + IPv4_RAW_ADDRESS IPv4Address; /* IPv4 address (in network byte order) */ + PIPv6_RAW_ADDRESS IPv6Address; /* IPv6 address (in network byte order) */ + } Address; + OBJECT_FREE_ROUTINE Free; /* The free routine */ +} IP_ADDRESS, *PIP_ADDRESS; + +/* IP type constants */ +#define IP_ADDRESS_V4 0x00 /* IPv4 style address */ +#define IP_ADDRESS_V6 0x01 /* IPv6 style address */ + + +/* IPv4 header format */ +typedef struct IPv4_HEADER { + UCHAR VerIHL; /* 4-bit version, 4-bit Internet Header Length */ + UCHAR Tos; /* Type of Service */ + USHORT TotalLength; /* Total Length */ + USHORT Id; /* Identification */ + USHORT FlagsFragOfs; /* 3-bit Flags, 13-bit Fragment Offset */ + UCHAR Ttl; /* Time to Live */ + UCHAR Protocol; /* Protocol */ + USHORT Checksum; /* Header Checksum */ + IPv4_RAW_ADDRESS SrcAddr; /* Source Address */ + IPv4_RAW_ADDRESS DstAddr; /* Destination Address */ +} IPv4_HEADER, *PIPv4_HEADER; + +#define IPv4_FRAGOFS_MASK 0x1FFF +#define IPv4_MF_MASK 0x2000 +#define IPv4_MAX_HEADER_SIZE 60 + +/* Packet completion handler prototype */ +typedef VOID (*PACKET_COMPLETION_ROUTINE)( + PVOID Context, + PNDIS_PACKET NdisPacket, + NDIS_STATUS NdisStatus); + +/* Structure for an IP packet */ +typedef struct IP_PACKET { + DEFINE_TAG + ULONG RefCount; /* Reference count for this object */ + OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */ + UCHAR Type; /* Type of IP packet (see IP_ADDRESS_xx above) */ + UCHAR Flags; /* Flags for packet (see IP_PACKET_FLAG_xx below)*/ + PVOID Header; /* Pointer to IP header for this packet */ + UINT HeaderSize; /* Size of IP header */ + PVOID Data; /* Current pointer into packet data */ + UINT TotalSize; /* Total amount of data in packet (IP header and data) */ + UINT ContigSize; /* Number of contiguous bytes left in current buffer */ + UINT Position; /* Current logical offset into packet */ + PNDIS_PACKET NdisPacket; /* Pointer to NDIS packet */ + IP_ADDRESS SrcAddr; /* Source address */ + IP_ADDRESS DstAddr; /* Destination address */ +} IP_PACKET, *PIP_PACKET; + +#define IP_PACKET_FLAG_RAW 0x01 /* Raw IP packet */ + + +/* Packet context */ +typedef struct PACKET_CONTEXT { + PACKET_COMPLETION_ROUTINE Complete; /* Transport level completion handler */ + PVOID Context; /* Context information for handler */ + PACKET_COMPLETION_ROUTINE DLComplete; /* Data link level completion handler. Also + used to link to next packet in a queue */ + UINT DLOffset; /* Offset where data (IP header) starts */ +} PACKET_CONTEXT, *PPACKET_CONTEXT; + +/* The ProtocolReserved field is structured as a PACKET_CONTEXT */ +#define PC(Packet) ((PPACKET_CONTEXT)(&Packet->ProtocolReserved)) + + +/* Address information a.k.a ADE */ +typedef struct _ADDRESS_ENTRY { + DEFINE_TAG + LIST_ENTRY ListEntry; /* Entry on list */ + ULONG RefCount; /* Reference count */ + OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */ + struct _NET_TABLE_ENTRY *NTE; /* NTE associated with this address */ + UCHAR Type; /* Address type */ + PIP_ADDRESS Address; /* Pointer to address identifying this entry */ +} ADDRESS_ENTRY, *PADDRESS_ENTRY; + +/* Values for address type */ +#define ADE_UNICAST 0x01 +#define ADE_MULTICAST 0x02 +#define ADE_ADDRMASK 0x03 + +/* There is one NTE for each source (unicast) address assigned to an interface */ +typedef struct _NET_TABLE_ENTRY { + DEFINE_TAG + LIST_ENTRY IFListEntry; /* Entry on interface list */ + LIST_ENTRY NTListEntry; /* Entry on net table list */ + struct _IP_INTERFACE *Interface; /* Pointer to interface on this net */ + struct _PREFIX_LIST_ENTRY *PLE; /* Pointer to prefix list entry for this net */ + ULONG RefCount; /* Reference count */ + OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */ + PIP_ADDRESS Address; /* Pointer to unicast address for this net */ +} NET_TABLE_ENTRY, *PNET_TABLE_ENTRY; + + +/* Link layer transmit prototype */ +typedef VOID (*LL_TRANSMIT_ROUTINE)( + PVOID Context, + PNDIS_PACKET NdisPacket, + UINT Offset, + PVOID LinkAddress, + USHORT Type); + +/* Link layer to IP binding information */ +typedef struct _LLIP_BIND_INFO { + PVOID Context; /* Pointer to link layer context information */ + UINT HeaderSize; /* Size of link level header */ + UINT MinFrameSize; /* Minimum frame size in bytes */ + UINT MTU; /* Maximum transmission unit */ + PUCHAR Address; /* Pointer to interface address */ + UINT AddressLength; /* Length of address in bytes */ + LL_TRANSMIT_ROUTINE Transmit; /* Transmit function for this interface */ +} LLIP_BIND_INFO, *PLLIP_BIND_INFO; + + +/* Information about an IP interface */ +typedef struct _IP_INTERFACE { + DEFINE_TAG + LIST_ENTRY ListEntry; /* Entry on list */ + ULONG RefCount; /* Reference count */ + OBJECT_FREE_ROUTINE Free; /* Routine used to free resources used by the object */ + KSPIN_LOCK Lock; /* Spin lock for this object */ + LIST_ENTRY NTEListHead; /* List of NTEs on this interface */ + LIST_ENTRY ADEListHead; /* List of ADEs on this interface */ + PVOID Context; /* Pointer to link layer context information */ + UINT HeaderSize; /* Size of link level header */ + UINT MinFrameSize; /* Minimum frame size in bytes */ + UINT MTU; /* Maximum transmission unit */ + PUCHAR Address; /* Pointer to interface address */ + UINT AddressLength; /* Length of address in bytes */ + LL_TRANSMIT_ROUTINE Transmit; /* Pointer to transmit function */ +} IP_INTERFACE, *PIP_INTERFACE; + + +/* Prefix List Entry */ +typedef struct _PREFIX_LIST_ENTRY { + DEFINE_TAG + LIST_ENTRY ListEntry; /* Entry on list */ + ULONG RefCount; /* Reference count */ + PIP_INTERFACE Interface; /* Pointer to interface */ + PIP_ADDRESS Prefix; /* Pointer to prefix */ + UINT PrefixLength; /* Length of prefix */ +} PREFIX_LIST_ENTRY, *PPREFIX_LIST_ENTRY; + + +#define IP_PROTOCOL_TABLE_SIZE 0x100 + +typedef VOID (*IP_PROTOCOL_HANDLER)( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket); + +/* Loopback adapter address information (network byte order) */ +#define LOOPBACK_ADDRESS_IPv4 ((IPv4_RAW_ADDRESS)DH2N(0x7F000001)) +#define LOOPBACK_BCASTADDR_IPv4 ((IPv4_RAW_ADDRESS)DH2N(0x7F0000FF)) +#define LOOPBACK_ADDRMASK_IPv4 ((IPv4_RAW_ADDRESS)DH2N(0xFFFFFF00)) + +/* Protocol definitions */ +#define IPPROTO_RAW 0 /* Raw IP */ +#define IPPROTO_ICMP 1 /* Internet Control Message Protocol */ +#define IPPROTO_IGMP 2 /* Internet Group Management Protocol */ +#define IPPROTO_TCP 6 /* Transmission Control Protocol */ +#define IPPROTO_UDP 17 /* User Datagram Protocol */ + +/* Timeout timer constants */ +#define IP_TICKS_SECOND 2 /* Two ticks per second */ +#define IP_TIMEOUT (1000 / IP_TICKS_SECOND) /* Timeout in milliseconds */ + + +extern LIST_ENTRY InterfaceListHead; +extern KSPIN_LOCK InterfaceListLock; +extern LIST_ENTRY NetTableListHead; +extern KSPIN_LOCK NetTableListLock; +extern LIST_ENTRY PrefixListHead; +extern KSPIN_LOCK PrefixListLock; +extern UINT MaxLLHeaderSize; +extern UINT MinLLFrameSize; + +PIP_PACKET IPCreatePacket( + ULONG Type); + +PNET_TABLE_ENTRY IPCreateNTE( + PIP_INTERFACE IF, + PIP_ADDRESS Address, + UINT PrefixLength); + +PIP_INTERFACE IPCreateInterface( + PLLIP_BIND_INFO BindInfo); + +VOID IPDestroyInterface( + PIP_INTERFACE IF); + +BOOLEAN IPRegisterInterface( + PIP_INTERFACE IF); + +VOID IPUnregisterInterface( + PIP_INTERFACE IF); + +PNET_TABLE_ENTRY IPLocateNTEOnInterface( + PIP_INTERFACE IF, + PIP_ADDRESS Address, + PUINT AddressType); + +PNET_TABLE_ENTRY IPLocateNTE( + PIP_ADDRESS Address, + PUINT AddressType); + +PADDRESS_ENTRY IPLocateADE( + PIP_ADDRESS Address, + UINT AddressType); + +PADDRESS_ENTRY IPGetDefaultADE( + UINT AddressType); + +VOID STDCALL IPTimeout( + PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + +VOID IPDispatchProtocol( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket); + +VOID IPRegisterProtocol( + UINT ProtocolNumber, + IP_PROTOCOL_HANDLER Handler); + +NTSTATUS IPStartup( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath); + +NTSTATUS IPShutdown( + VOID); + +#endif /* __IP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/lan.h b/drivers/net/tcpip/include/lan.h new file mode 100644 index 0000000..f61e84a --- /dev/null +++ b/drivers/net/tcpip/include/lan.h @@ -0,0 +1,98 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/lan.h + * PURPOSE: LAN adapter definitions + */ +#ifndef __LAN_H +#define __LAN_H + + +/* Medias we support */ +#define MEDIA_ETH 0 + +#define MAX_MEDIA 1 + +#define IEEE_802_ADDR_LENGTH 6 + +/* Ethernet header layout */ +typedef struct ETH_HEADER { + UCHAR DstAddr[IEEE_802_ADDR_LENGTH]; /* Destination MAC address */ + UCHAR SrcAddr[IEEE_802_ADDR_LENGTH]; /* Source MAC address */ + USHORT EType; /* Ethernet protocol type */ +} ETH_HEADER, *PETH_HEADER; + +#define MAX_MEDIA_ETH sizeof(ETH_HEADER) + +/* Broadcast masks */ +#define BCAST_ETH_MASK 0x01 + +/* Broadcast values to check against */ +#define BCAST_ETH_CHECK 0x01 + +/* Offset of broadcast address */ +#define BCAST_ETH_OFFSET 0x00 + +/* Per adapter information */ +typedef struct LAN_ADAPTER { + LIST_ENTRY ListEntry; /* Entry on list */ + KSPIN_LOCK Lock; /* Lock for this structure */ + UCHAR State; /* State of the adapter */ + KEVENT Event; /* Opening event */ + PVOID Context; /* Upper layer context information */ + NDIS_HANDLE NdisHandle; /* NDIS binding handle */ + NDIS_STATUS NdisStatus; /* NDIS status of last request */ + NDIS_MEDIUM Media; /* Media type */ + UCHAR HWAddress[IEEE_802_ADDR_LENGTH]; /* Local HW address */ + UINT HWAddressLength; /* Length of HW address */ + UCHAR BCastMask; /* Mask for checking broadcast */ + UCHAR BCastCheck; /* Value to check against */ + UCHAR BCastOffset; /* Offset in frame to check against */ + UCHAR HeaderSize; /* Size of link-level header */ + USHORT MTU; /* Maximum Transfer Unit */ + UINT MinFrameSize; /* Minimum frame size in bytes */ + UINT MaxPacketSize; /* Maximum packet size when sending */ + UINT MaxSendPackets; /* Maximum number of packets per send */ + UINT MacOptions; /* MAC options for NIC driver/adapter */ + UINT Speed; /* Link speed */ + UINT PacketFilter; /* Packet filter for this adapter */ + PNDIS_PACKET TDPackets; /* Transfer Data packets */ +} LAN_ADAPTER, *PLAN_ADAPTER; + +/* LAN adapter state constants */ +#define LAN_STATE_OPENING 0 +#define LAN_STATE_RESETTING 1 +#define LAN_STATE_STARTED 2 +#define LAN_STATE_STOPPED 3 + +/* Size of out lookahead buffer */ +#define LOOKAHEAD_SIZE 128 + +/* Ethernet types. We swap constants so we can compare values at runtime + without swapping them there */ +#define ETYPE_IPv4 WH2N(0x0800) +#define ETYPE_IPv6 WH2N(0x0000) /* FIXME */ +#define ETYPE_ARP WH2N(0x0806) + +/* Protocols */ +#define LAN_PROTO_IPv4 0x0000 /* Internet Protocol version 4 */ +#define LAN_PROTO_IPv6 0x0001 /* Internet Protocol version 6 */ +#define LAN_PROTO_ARP 0x0002 /* Address Resolution Protocol */ + + +NDIS_STATUS LANRegisterAdapter( + PNDIS_STRING AdapterName, + PLAN_ADAPTER *Adapter); + +NDIS_STATUS LANUnregisterAdapter( + PLAN_ADAPTER Adapter); + +NTSTATUS LANRegisterProtocol( + STRING *Name); + +VOID LANUnregisterProtocol( + VOID); + +#endif /* __LAN_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/loopback.h b/drivers/net/tcpip/include/loopback.h new file mode 100644 index 0000000..e5c31c4 --- /dev/null +++ b/drivers/net/tcpip/include/loopback.h @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/loopback.h + * PURPOSE: Loopback adapter definitions + */ +#ifndef __LOOPBACK_H +#define __LOOPBACK_H + +#include + + +extern PIP_INTERFACE Loopback; + + +NDIS_STATUS LoopRegisterAdapter( + PNDIS_STRING AdapterName, + PLAN_ADAPTER *Adapter); + +NDIS_STATUS LoopUnregisterAdapter( + PLAN_ADAPTER Adapter); + +#endif /* __LOOPBACK_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/neighbor.h b/drivers/net/tcpip/include/neighbor.h new file mode 100644 index 0000000..1c401f8 --- /dev/null +++ b/drivers/net/tcpip/include/neighbor.h @@ -0,0 +1,103 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/neighbor.h + * PURPOSE: Neighbor definitions + */ +#ifndef __NEIGHBOR_H +#define __NEIGHBOR_H + + +#define NB_HASHMASK 0xF /* Hash mask for neighbor cache */ + +typedef struct NEIGHBOR_CACHE_TABLE { + struct NEIGHBOR_CACHE_ENTRY *Cache; /* Pointer to cache */ + KSPIN_LOCK Lock; /* Protecting lock */ +} NEIGHBOR_CACHE_TABLE, *PNEIGHBOR_CACHE_TABLE; + +/* Information about a neighbor */ +typedef struct NEIGHBOR_CACHE_ENTRY { + DEFINE_TAG + struct NEIGHBOR_CACHE_ENTRY *Next; /* Pointer to next entry */ + struct NEIGHBOR_CACHE_TABLE *Table; /* Pointer to table */ + ULONG RefCount; /* Number of references */ + OBJECT_FREE_ROUTINE Free; /* Routine to free resources for the object */ + UCHAR State; /* State of NCE */ + UINT EventTimer; /* Ticks since last event */ + UINT EventCount; /* Number of events */ + PIP_INTERFACE Interface; /* Pointer to interface */ + PIP_ADDRESS Address; /* IP address of neighbor */ + UINT LinkAddressLength; /* Length of link address */ + PVOID LinkAddress; /* Pointer to link address */ + PNDIS_PACKET WaitQueue; /* Pointer to NDIS packets + waiting to be sent */ +} NEIGHBOR_CACHE_ENTRY, *PNEIGHBOR_CACHE_ENTRY; + +/* NCE states */ +#define NUD_NONE 0x00 +#define NUD_INCOMPLETE 0x01 +#define NUD_REACHABLE 0x02 +#define NUD_STALE 0x04 +#define NUD_DELAY 0x08 +#define NUD_PROBE 0x10 +#define NUD_FAILED 0x20 +#define NUD_NOARP 0x40 +#define NUD_PERMANENT 0x80 + +#define NUD_IN_TIMER (NUD_INCOMPLETE | NUD_DELAY | NUD_PROBE) +#define NUD_VALID (NUD_REACHABLE | NUD_NOARP | NUD_STALE | NUD_DELAY | \ + NUD_PROBE | NUD_PERMANENT) +#define NUD_CONNECTED (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE) + + +/* Maximum number of retransmissions of multicast solicits */ +#define MAX_MULTICAST_SOLICIT 3 /* 3 transmissions */ + +/* Number of ticks between address resolution messages */ +#define RETRANS_TIMER IP_TICKS_SECOND /* One second */ + + +extern NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1]; + + +VOID NBTimeout( + VOID); + +VOID NBStartup( + VOID); + +VOID NBShutdown( + VOID); + +VOID NBSendSolicit( + PNEIGHBOR_CACHE_ENTRY NCE); + +PNEIGHBOR_CACHE_ENTRY NBAddNeighbor( + PIP_INTERFACE Interface, + PIP_ADDRESS Address, + PVOID LinkAddress, + UINT LinkAddressLength, + UCHAR Type); + +VOID NBUpdateNeighbor( + PNEIGHBOR_CACHE_ENTRY NCE, + PVOID LinkAddress, + UCHAR State); + +PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor( + PIP_ADDRESS Address); + +PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor( + PIP_INTERFACE Interface, + PIP_ADDRESS Address); + +BOOLEAN NBQueuePacket( + PNEIGHBOR_CACHE_ENTRY NCE, + PNDIS_PACKET NdisPacket); + +VOID NBRemoveNeighbor( + PNEIGHBOR_CACHE_ENTRY NCE); + +#endif /* __NEIGHBOR_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/pool.h b/drivers/net/tcpip/include/pool.h new file mode 100644 index 0000000..04b088a --- /dev/null +++ b/drivers/net/tcpip/include/pool.h @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/pool.h + * PURPOSE: Prototypes for memory pooling + */ +#ifndef __POOL_H +#define __POOL_H + + +PVOID PoolAllocateBuffer( + ULONG Size); + +VOID PoolFreeBuffer( + PVOID Buffer); + +#endif /* __POOL_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/rawip.h b/drivers/net/tcpip/include/rawip.h new file mode 100644 index 0000000..fbd0961 --- /dev/null +++ b/drivers/net/tcpip/include/rawip.h @@ -0,0 +1,28 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/rawip.h + * PURPOSE: Raw IP types and constants + */ +#ifndef __RAWIP_H +#define __RAWIP_H + +NTSTATUS RawIPSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize); + +VOID RawIPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket); + +NTSTATUS RawIPStartup( + VOID); + +NTSTATUS RawIPShutdown( + VOID); + +#endif /* __RAWIP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/receive.h b/drivers/net/tcpip/include/receive.h new file mode 100644 index 0000000..7b3f14d --- /dev/null +++ b/drivers/net/tcpip/include/receive.h @@ -0,0 +1,64 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/receive.h + * PURPOSE: Internet Protocol receive prototypes + */ +#ifndef __RECEIVE_H +#define __RECEIVE_H + +#include + + +/* IP datagram fragment descriptor. Used to store IP datagram fragments */ +typedef struct IP_FRAGMENT { + LIST_ENTRY ListEntry; /* Entry on list */ + PVOID Data; /* Pointer to fragment data */ + UINT Offset; /* Offset into datagram where this fragment is */ + UINT Size; /* Size of this fragment */ +} IP_FRAGMENT, *PIP_FRAGMENT; + +/* IP datagram hole descriptor. Used to reassemble IP datagrams */ +typedef struct IPDATAGRAM_HOLE { + LIST_ENTRY ListEntry; /* Entry on list */ + UINT First; /* Offset of first octet of the hole */ + UINT Last; /* Offset of last octet of the hole */ +} IPDATAGRAM_HOLE, *PIPDATAGRAM_HOLE; + +/* IP datagram reassembly information */ +typedef struct IPDATAGRAM_REASSEMBLY { + LIST_ENTRY ListEntry; /* Entry on list */ + KSPIN_LOCK Lock; /* Protecting spin lock */ + ULONG RefCount; /* Reference count for this object */ + UINT DataSize; /* Size of datagram data area */ + IP_ADDRESS SrcAddr; /* Source address */ + IP_ADDRESS DstAddr; /* Destination address */ + UCHAR Protocol; /* Internet Protocol number */ + USHORT Id; /* Identification number */ + PIPv4_HEADER IPv4Header; /* Pointer to IP header */ + UINT HeaderSize; /* Length of IP header */ + LIST_ENTRY FragmentListHead; /* IP fragment list */ + LIST_ENTRY HoleListHead; /* IP datagram hole list */ +} IPDATAGRAM_REASSEMBLY, *PIPDATAGRAM_REASSEMBLY; + + +extern LIST_ENTRY ReassemblyListHead; +extern KSPIN_LOCK ReassemblyListLock; +extern NPAGED_LOOKASIDE_LIST IPDRList; +extern NPAGED_LOOKASIDE_LIST IPFragmentList; +extern NPAGED_LOOKASIDE_LIST IPHoleList; + + +VOID IPFreeReassemblyList( + VOID); + +VOID IPDatagramReassemblyTimeout( + VOID); + +VOID IPReceive( + PVOID Context, + PIP_PACKET IPPacket); + +#endif /* __RECEIVE_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/route.h b/drivers/net/tcpip/include/route.h new file mode 100644 index 0000000..79cd0ec --- /dev/null +++ b/drivers/net/tcpip/include/route.h @@ -0,0 +1,80 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/route.h + * PURPOSE: Routing cache definitions + */ +#ifndef __ROUTE_H +#define __ROUTE_H + +#include +#include +#include +#include +#include + + +/* Route Cache Node structure. + * The primary purpose of the RCN is to cache selected source and + * next-hop addresses. The routing cache is implemented as a binary + * search tree to provide fast lookups when many RCNs are in the cache. + */ +typedef struct ROUTE_CACHE_NODE { + struct ROUTE_CACHE_NODE *Parent; /* Pointer to parent */ + struct ROUTE_CACHE_NODE *Left; /* Pointer to left child */ + struct ROUTE_CACHE_NODE *Right; /* Pointer to right child */ + /* Memebers above this line must not be moved */ + DEFINE_TAG + ULONG RefCount; /* Reference count */ + OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */ + UCHAR State; /* RCN state (RCN_STATE_*) */ + IP_ADDRESS Destination; /* Destination address */ + PNET_TABLE_ENTRY NTE; /* Preferred NTE */ + PNEIGHBOR_CACHE_ENTRY NCE; /* Pointer to NCE for first hop (NULL if none) */ + UINT PathMTU; /* Path MTU to destination */ +} ROUTE_CACHE_NODE, *PROUTE_CACHE_NODE; + +/* RCN states */ +#define RCN_STATE_PERMANENT 0x00 /* RCN is permanent (properly local) */ +#define RCN_STATE_COMPUTED 0x01 /* RCN is computed */ + + +extern NPAGED_LOOKASIDE_LIST IPRCNList; + + +#define IsExternalRCN(RCN) \ + (RCN == ExternalRCN) + +#define IsInternalRCN(RCN) \ + (RCN != ExternalRCN) + + +NTSTATUS RouteStartup( + VOID); + +NTSTATUS RouteShutdown( + VOID); + +UINT RouteGetRouteToDestination( + PIP_ADDRESS Destination, + PNET_TABLE_ENTRY NTE, + PROUTE_CACHE_NODE *RCN); + +PROUTE_CACHE_NODE RouteAddRouteToDestination( + PIP_ADDRESS Destination, + PNET_TABLE_ENTRY NTE, + PIP_INTERFACE IF, + PNEIGHBOR_CACHE_ENTRY NCE); + +VOID RouteRemoveRouteToDestination( + PROUTE_CACHE_NODE RCN); + +VOID RouteInvalidateNTE( + PNET_TABLE_ENTRY NTE); + +VOID RouteInvalidateNCE( + PNEIGHBOR_CACHE_ENTRY NCE); + +#endif /* __ROUTE_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/router.h b/drivers/net/tcpip/include/router.h new file mode 100644 index 0000000..d6157ba --- /dev/null +++ b/drivers/net/tcpip/include/router.h @@ -0,0 +1,63 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/router.h + * PURPOSE: IP routing definitions + */ +#ifndef __ROUTER_H +#define __ROUTER_H + +#include + + +/* Forward Information Base Entry */ +typedef struct _FIB_ENTRY { + LIST_ENTRY ListEntry; /* Entry on list */ + ULONG RefCount; /* Reference count */ + OBJECT_FREE_ROUTINE Free; /* Routine used to free resources for the object */ + PIP_ADDRESS NetworkAddress; /* Address of network */ + PIP_ADDRESS Netmask; /* Netmask of network */ + PNET_TABLE_ENTRY NTE; /* Pointer to NTE to use */ + PNEIGHBOR_CACHE_ENTRY Router; /* Pointer to NCE of router to use */ + UINT Metric; /* Cost of this route */ +} FIB_ENTRY, *PFIB_ENTRY; + + +PNET_TABLE_ENTRY RouterFindBestNTE( + PIP_INTERFACE Interface, + PIP_ADDRESS Destination); + +PIP_INTERFACE RouterFindOnLinkInterface( + PIP_ADDRESS Address, + PNET_TABLE_ENTRY NTE); + +PFIB_ENTRY RouterAddRoute( + PIP_ADDRESS NetworkAddress, + PIP_ADDRESS Netmask, + PNET_TABLE_ENTRY NTE, + PNEIGHBOR_CACHE_ENTRY Router, + UINT Metric); + +PNEIGHBOR_CACHE_ENTRY RouterGetRoute( + PIP_ADDRESS Destination, + PNET_TABLE_ENTRY NTE); + +VOID RouterRemoveRoute( + PFIB_ENTRY FIBE); + +PFIB_ENTRY RouterCreateRouteIPv4( + IPv4_RAW_ADDRESS NetworkAddress, + IPv4_RAW_ADDRESS Netmask, + IPv4_RAW_ADDRESS RouterAddress, + PNET_TABLE_ENTRY NTE, + UINT Metric); + +NTSTATUS RouterStartup( + VOID); + +NTSTATUS RouterShutdown( + VOID); + +#endif /* __ROUTER_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/routines.h b/drivers/net/tcpip/include/routines.h new file mode 100644 index 0000000..2d94e20 --- /dev/null +++ b/drivers/net/tcpip/include/routines.h @@ -0,0 +1,78 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/routines.h + * PURPOSE: Common routine prototypes + */ +#ifndef __ROUTINES_H +#define __ROUTINES_H + + +inline NTSTATUS BuildDatagramSendRequest( + PDATAGRAM_SEND_REQUEST *SendRequest, + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, + PNDIS_BUFFER Buffer, + DWORD BufferSize, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + DATAGRAM_BUILD_ROUTINE Build, + ULONG Flags); + +inline NTSTATUS BuildTCPSendRequest( + PTCP_SEND_REQUEST *SendRequest, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + PVOID ProtocolContext); + +UINT Random( + VOID); + +UINT CopyBufferToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PUCHAR SrcData, + UINT Length); + +UINT CopyBufferChainToBuffer( + PUCHAR DstData, + PNDIS_BUFFER SrcBuffer, + UINT SrcOffset, + UINT Length); + +UINT CopyPacketToBuffer( + PUCHAR DstData, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length); + +UINT CopyPacketToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length); + +VOID FreeNdisPacket( + PNDIS_PACKET Packet); + +PVOID AdjustPacket( + PNDIS_PACKET Packet, + UINT Available, + UINT Needed); + +UINT ResizePacket( + PNDIS_PACKET Packet, + UINT Size); + +#ifdef DBG +VOID DisplayIPPacket( + PIP_PACKET IPPacket); +#define DISPLAY_IP_PACKET(x) DisplayIPPacket(x) +#else +#define DISPLAY_IP_PACKET(x) +#endif /* DBG */ + +#endif /* __ROUTINES_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/tcp.h b/drivers/net/tcpip/include/tcp.h new file mode 100644 index 0000000..2442b56 --- /dev/null +++ b/drivers/net/tcpip/include/tcp.h @@ -0,0 +1,112 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/tcp.h + * PURPOSE: Transmission Control Protocol definitions + */ +#ifndef __TCP_H +#define __TCP_H + + +/* TCPv4 header structure */ +typedef struct TCP_HEADER { + USHORT SourcePort; /* Source port */ + USHORT DestPort; /* Destination port */ + USHORT SeqNum; /* Sequence number */ + USHORT AckNum; /* Acknowledgment number */ + UCHAR DataOfs; /* Data offset (leftmost 4 bits) */ + UCHAR Flags; /* Control bits (rightmost 6 bits) */ + USHORT Window; /* Maximum acceptable receive window */ + USHORT Checksum; /* Checksum of segment */ + USHORT Urgent; /* Pointer to urgent data */ +} __attribute__((packed)) TCP_HEADER, *PTCP_HEADER; + +/* TCPv4 header flags */ +#define TCP_URG 0x04 +#define TCP_ACK 0x08 +#define TCP_PSH 0x10 +#define TCP_RST 0x20 +#define TCP_SYN 0x40 +#define TCP_FIN 0x80 + + +#define TCPOPT_END_OF_LIST 0x0 +#define TCPOPT_NO_OPERATION 0x1 +#define TCPOPT_MAX_SEG_SIZE 0x2 + +#define TCPOPTLEN_MAX_SEG_SIZE 0x4 + + +/* TCPv4 pseudo header */ +typedef struct TCP_PSEUDO_HEADER { + ULONG SourceAddress; /* Source address */ + ULONG DestAddress; /* Destination address */ + UCHAR Zero; /* Reserved */ + UCHAR Protocol; /* Protocol */ + USHORT TCPLength; /* Size of TCP segment */ +} __attribute__((packed)) TCP_PSEUDO_HEADER, *PTCP_PSEUDO_HEADER; + + +/* Retransmission timeout constants */ + +/* Lower bound for retransmission timeout in TCP timer ticks */ +#define TCP_MIN_RETRANSMISSION_TIMEOUT 1*1000 /* 1 tick */ + +/* Upper bound for retransmission timeout in TCP timer ticks */ +#define TCP_MAX_RETRANSMISSION_TIMEOUT 1*60*1000 /* 1 tick */ + +/* Smoothing factor */ +#define TCP_ALPHA_RETRANSMISSION_TIMEOUT(x)(((x)*8)/10) /* 0.8 */ + +/* Delay variance factor */ +#define TCP_BETA_RETRANSMISSION_TIMEOUT(x)(((x)*16)/10) /* 1.6 */ + + +/* Datagram/segment send request flags */ + +#define SRF_URG TCP_URG +#define SRF_ACK TCP_ACK +#define SRF_PSH TCP_PSH +#define SRF_RST TCP_RST +#define SRF_SYN TCP_SYN +#define SRF_FIN TCP_FIN + + +inline NTSTATUS TCPBuildSendRequest( + PTCP_SEND_REQUEST *SendRequest, + PDATAGRAM_SEND_REQUEST *DGSendRequest, + PCONNECTION_ENDPOINT Connection, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + PNDIS_BUFFER Buffer, + DWORD BufferSize, + ULONG Flags); + +inline NTSTATUS TCPBuildAndTransmitSendRequest( + PCONNECTION_ENDPOINT Connection, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + PNDIS_BUFFER Buffer, + DWORD BufferSize, + ULONG Flags); + +NTSTATUS TCPConnect( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PTDI_CONNECTION_INFORMATION ReturnInfo); + +NTSTATUS TCPSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize); + +NTSTATUS TCPStartup( + VOID); + +NTSTATUS TCPShutdown( + VOID); + +#endif /* __TCP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/tcpip.h b/drivers/net/tcpip/include/tcpip.h new file mode 100644 index 0000000..20876f5 --- /dev/null +++ b/drivers/net/tcpip/include/tcpip.h @@ -0,0 +1,131 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/tcpip.h + * PURPOSE: TCP/IP protocol driver definitions + * NOTES: Spin lock acquire order: + * - Net table list lock + * - Interface lock + * - Interface list lock + * - Prefix list lock + * - Neighbor cache lock + * - Route cache lock + */ +#ifndef __TCPIP_H +#define __TCPIP_H + +#ifdef _MSC_VER +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include + + +/* Define _NTTEST_ to make test version. Device names are prefixed with + 'NT' to allow the driver to run side by side with MS TCP/IP driver */ +//#define _NTTEST_ + +/* FIXME: The following should be moved to ntddk.h or tdi headers */ +#ifndef _MSC_VER + +#ifndef IO_NETWORK_INCREMENT +#define IO_NETWORK_INCREMENT 2 +#endif + +#endif + +#ifdef _MSC_VER +/* EXPORTED is already defined ddk/defines.h */ +#define EXPORTED __declspec(dllexport) + +#endif + +#include +#include +#include + + +/* Macros */ + +#define MIN(value1, value2) \ + ((value1 < value2)? value1 : value2) + +#define MAX(value1, value2) \ + ((value1 > value2)? value1 : value2) + + +#ifdef i386 + +/* DWORD network to host byte order conversion for i386 */ +#define DN2H(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* DWORD host to network byte order conversion for i386 */ +#define DH2N(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* WORD network to host order conversion for i386 */ +#define WN2H(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +/* WORD host to network byte order conversion for i386 */ +#define WH2N(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +#else /* i386 */ + +/* DWORD network to host byte order conversion for other architectures */ +#define DN2H(dw) \ + (dw) + +/* DWORD host to network byte order conversion for other architectures */ +#define DH2N(dw) \ + (dw) + +/* WORD network to host order conversion for other architectures */ +#define WN2H(w) \ + (w) + +/* WORD host to network byte order conversion for other architectures */ +#define WH2N(w) \ + (w) + +#endif /* i386 */ + + +/* Global variable */ +extern PDEVICE_OBJECT TCPDeviceObject; +extern PDEVICE_OBJECT UDPDeviceObject; +extern PDEVICE_OBJECT IPDeviceObject; +extern PDEVICE_OBJECT RawIPDeviceObject; +extern LIST_ENTRY InterfaceListHead; +extern KSPIN_LOCK InterfaceListLock; +extern LIST_ENTRY AddressFileListHead; +extern KSPIN_LOCK AddressFileListLock; +extern NDIS_HANDLE GlobalPacketPool; +extern NDIS_HANDLE GlobalBufferPool; +extern TDIEntityID *EntityList; +extern ULONG EntityCount; +extern UDP_STATISTICS UDPStats; + +#endif /* __TCPIP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/ticonsts.h b/drivers/net/tcpip/include/ticonsts.h new file mode 100644 index 0000000..d73436c --- /dev/null +++ b/drivers/net/tcpip/include/ticonsts.h @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/ticonsts.h + * PURPOSE: TCP/IP protocol driver constants + */ +#ifndef __TICONSTS_H +#define __TICONSTS_H + +/* NDIS version this driver supports */ +#define NDIS_VERSION_MAJOR 3 +#define NDIS_VERSION_MINOR 0 + +#ifdef _NTTEST_ +/* Name of devices */ +#define DD_TCP_DEVICE_NAME L"\\Device\\NTTcp" +#define DD_UDP_DEVICE_NAME L"\\Device\\NTUdp" +#define DD_IP_DEVICE_NAME L"\\Device\\NTIp" +#define DD_RAWIP_DEVICE_NAME L"\\Device\\NTRawIp" + +/* For NDIS protocol registration */ +#define IP_DEVICE_NAME "\\Device\\NTIp" +#else +#define DD_TCP_DEVICE_NAME L"\\Device\\Tcp" +#define DD_UDP_DEVICE_NAME L"\\Device\\Udp" +#define DD_IP_DEVICE_NAME L"\\Device\\Ip" +#define DD_RAWIP_DEVICE_NAME L"\\Device\\RawIp" + +/* For NDIS protocol registration */ +#define IP_DEVICE_NAME "\\Device\\Ip" +#endif /* _NTTEST_ */ + +/* TCP/UDP/RawIP IOCTL code definitions */ + +#define FSCTL_TCP_BASE FILE_DEVICE_NETWORK + +#define _TCP_CTL_CODE(Function, Method, Access) \ + CTL_CODE(FSCTL_TCP_BASE, Function, Method, Access) + +#define IOCTL_TCP_QUERY_INFORMATION_EX \ + _TCP_CTL_CODE(0, METHOD_NEITHER, FILE_ANY_ACCESS) + +#define IOCTL_TCP_SET_INFORMATION_EX \ + _TCP_CTL_CODE(1, METHOD_BUFFERED, FILE_WRITE_ACCESS) + +/* Unique error values for log entries */ +#define TI_ERROR_DRIVERENTRY 0 + +/* Internal status codes */ +#define IP_SUCCESS 0x0000 /* Successful */ +#define IP_NO_RESOURCES 0x0001 /* Not enough free resources */ +#define IP_NO_ROUTE_TO_DESTINATION 0x0002 /* No route to destination */ + +#endif /* __TICONSTS_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/titypes.h b/drivers/net/tcpip/include/titypes.h new file mode 100644 index 0000000..c57b55c --- /dev/null +++ b/drivers/net/tcpip/include/titypes.h @@ -0,0 +1,372 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/titypes.h + * PURPOSE: TCP/IP protocol driver types + */ +#ifndef __TITYPES_H +#define __TITYPES_H + + +#ifdef DBG + +#define DEFINE_TAG ULONG Tag; +#define INIT_TAG(_Object, _Tag) \ + ((_Object)->Tag = (_Tag)) + +#define DEBUG_REFCHECK(Object) { \ + if ((Object)->RefCount <= 0) { \ + TI_DbgPrint(MIN_TRACE, ("Object at (0x%X) has invalid reference count (%d).\n", \ + (Object), (Object)->RefCount)); \ + } \ +} + +/* + * VOID ReferenceObject( + * PVOID Object) + */ +#define ReferenceObject(Object) \ +{ \ + CHAR c1, c2, c3, c4; \ + \ + c1 = ((Object)->Tag >> 24) & 0xFF; \ + c2 = ((Object)->Tag >> 16) & 0xFF; \ + c3 = ((Object)->Tag >> 8) & 0xFF; \ + c4 = ((Object)->Tag & 0xFF); \ + \ + DEBUG_REFCHECK(Object); \ + TI_DbgPrint(DEBUG_REFCOUNT, ("Referencing object of type (%c%c%c%c) at (0x%X). RefCount (%d).\n", \ + c4, c3, c2, c1, (Object), (Object)->RefCount)); \ + \ + InterlockedIncrement(&((Object)->RefCount)); \ +} + + /* + * VOID DereferenceObject( + * PVOID Object) + */ +#define DereferenceObject(Object) \ +{ \ + CHAR c1, c2, c3, c4; \ + \ + c1 = ((Object)->Tag >> 24) & 0xFF; \ + c2 = ((Object)->Tag >> 16) & 0xFF; \ + c3 = ((Object)->Tag >> 8) & 0xFF; \ + c4 = ((Object)->Tag & 0xFF); \ + \ + DEBUG_REFCHECK(Object); \ + TI_DbgPrint(DEBUG_REFCOUNT, ("Dereferencing object of type (%c%c%c%c) at (0x%X). RefCount (%d).\n", \ + c4, c3, c2, c1, (Object), (Object)->RefCount)); \ + \ + if (InterlockedDecrement(&((Object)->RefCount)) == 0) \ + (((Object)->Free)(Object)); \ +} + +#else /* DBG */ + +#define DEFINE_TAG +#define INIT_TAG (Object, Tag) + +/* + * VOID ReferenceObject( + * PVOID Object) + */ +#define ReferenceObject(Object) \ +{ \ + InterlockedIncrement(&((Object)->RefCount)); \ +} + +/* + * VOID DereferenceObject( + * PVOID Object) + */ +#define DereferenceObject(Object) \ +{ \ + if (InterlockedDecrement(&((Object)->RefCount)) == 0) \ + (((Object)->Free)(Object)); \ +} + +#endif /* DBG */ + + +#include + + +/*************************************************** +* Connection-less communication support structures * +***************************************************/ + +typedef NTSTATUS (*DATAGRAM_SEND_ROUTINE)( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize); + +/* Datagram completion handler prototype */ +typedef VOID (*DATAGRAM_COMPLETION_ROUTINE)( + PVOID Context, + NDIS_STATUS Status, + ULONG Count); + +typedef struct _DATAGRAM_RECEIVE_REQUEST { + LIST_ENTRY ListEntry; /* Entry on list */ + PIP_ADDRESS RemoteAddress; /* Remote address we receive from (NULL means any) */ + USHORT RemotePort; /* Remote port we receive from (0 means any) */ + PTDI_CONNECTION_INFORMATION ReturnInfo; /* Return information */ + PNDIS_BUFFER Buffer; /* Pointer to receive buffer */ + ULONG BufferSize; /* Size of Buffer */ + DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */ + PVOID Context; /* Pointer to context information */ +} DATAGRAM_RECEIVE_REQUEST, *PDATAGRAM_RECEIVE_REQUEST; + +/* Datagram build routine prototype */ +typedef NTSTATUS (*DATAGRAM_BUILD_ROUTINE)( + PVOID Context, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET *IPPacket); + +typedef struct _DATAGRAM_SEND_REQUEST { + LIST_ENTRY ListEntry; /* Entry on list */ + PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */ + USHORT RemotePort; /* Remote port number */ + PNDIS_BUFFER Buffer; /* Pointer to NDIS buffer to send */ + DWORD BufferSize; /* Size of Buffer */ + DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */ + PVOID Context; /* Pointer to context information */ + DATAGRAM_BUILD_ROUTINE Build; /* Datagram build routine */ + ULONG Flags; /* Protocol specific flags */ +} DATAGRAM_SEND_REQUEST, *PDATAGRAM_SEND_REQUEST; + +#define InitializeDatagramSendRequest( \ + _SendRequest, \ + _RemoteAddress, \ + _RemotePort, \ + _Buffer, \ + _BufferSize, \ + _Complete, \ + _Context, \ + _Build, \ + _Flags) { \ + (_SendRequest)->RemoteAddress = (_RemoteAddress); \ + (_SendRequest)->RemotePort = (_RemotePort); \ + (_SendRequest)->Buffer = (_Buffer); \ + (_SendRequest)->BufferSize = (_BufferSize); \ + (_SendRequest)->Complete = (_Complete); \ + (_SendRequest)->Context = (_Context); \ + (_SendRequest)->Build = (_Build); \ + (_SendRequest)->Flags = (_Flags); \ + } + +/* Transport address file context structure. The FileObject->FsContext2 + field holds a pointer to this structure */ +typedef struct _ADDRESS_FILE { + DEFINE_TAG + LIST_ENTRY ListEntry; /* Entry on list */ + KSPIN_LOCK Lock; /* Spin lock to manipulate this structure */ + ULONG RefCount; /* Number of references to this object */ + OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */ + USHORT Flags; /* Flags for address file (see below) */ + PADDRESS_ENTRY ADE; /* Associated address entry */ + USHORT Protocol; /* Protocol number */ + USHORT Port; /* Network port (network byte order) */ + WORK_QUEUE_ITEM WorkItem; /* Work queue item handle */ + DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine for delete request */ + PVOID Context; /* Delete request context */ + DATAGRAM_SEND_ROUTINE Send; /* Routine to send a datagram */ + LIST_ENTRY ReceiveQueue; /* List of outstanding receive requests */ + LIST_ENTRY TransmitQueue; /* List of outstanding transmit requests */ + LIST_ENTRY Connections; /* List of associated connections */ + PIP_ADDRESS AddrCache; /* One entry address cache (destination + address of last packet transmitted) */ + + /* The following members are used to control event notification */ + + /* Connection indication handler */ + PTDI_IND_CONNECT ConnectHandler; + PVOID ConnectHandlerContext; + BOOL RegisteredConnectHandler; + /* Disconnect indication handler */ + PTDI_IND_DISCONNECT DisconnectHandler; + PVOID DisconnectHandlerContext; + BOOL RegisteredDisconnectHandler; + /* Error indication handler */ + PTDI_IND_ERROR ErrorHandler; + PVOID ErrorHandlerContext; + PVOID ErrorHandlerOwner; + BOOL RegisteredErrorHandler; + /* Receive indication handler */ + PTDI_IND_RECEIVE ReceiveHandler; + PVOID ReceiveHandlerContext; + BOOL RegisteredReceiveHandler; + /* Receive datagram indication handler */ + PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler; + PVOID ReceiveDatagramHandlerContext; + BOOL RegisteredReceiveDatagramHandler; + /* Expedited receive indication handler */ + PTDI_IND_RECEIVE_EXPEDITED ExpeditedReceiveHandler; + PVOID ExpeditedReceiveHandlerContext; + BOOL RegisteredExpeditedReceiveHandler; + /* Chained receive indication handler */ + PTDI_IND_CHAINED_RECEIVE ChainedReceiveHandler; + PVOID ChainedReceiveHandlerContext; + BOOL RegisteredChainedReceiveHandler; + /* Chained receive datagram indication handler */ + PTDI_IND_CHAINED_RECEIVE_DATAGRAM ChainedReceiveDatagramHandler; + PVOID ChainedReceiveDatagramHandlerContext; + BOOL RegisteredChainedReceiveDatagramHandler; + /* Chained expedited receive indication handler */ + PTDI_IND_CHAINED_RECEIVE_EXPEDITED ChainedReceiveExpeditedHandler; + PVOID ChainedReceiveExpeditedHandlerContext; + BOOL RegisteredChainedReceiveExpeditedHandler; +} ADDRESS_FILE, *PADDRESS_FILE; + +/* Address File Flag constants */ +#define AFF_VALID 0x0001 /* Address file object is valid for use */ +#define AFF_BUSY 0x0002 /* Address file object is exclusive to someone */ +#define AFF_DELETE 0x0004 /* Address file object is sheduled to be deleted */ +#define AFF_SEND 0x0008 /* A send request is pending */ +#define AFF_RECEIVE 0x0010 /* A receive request is pending */ +#define AFF_PENDING 0x001C /* A request is pending */ + +/* Macros for manipulating address file object flags */ + +#define AF_IS_VALID(ADF) ((ADF)->Flags & AFF_VALID) +#define AF_SET_VALID(ADF) ((ADF)->Flags |= AFF_VALID) +#define AF_CLR_VALID(ADF) ((ADF)->Flags &= ~AFF_VALID) + +#define AF_IS_BUSY(ADF) ((ADF)->Flags & AFF_BUSY) +#define AF_SET_BUSY(ADF) ((ADF)->Flags |= AFF_BUSY) +#define AF_CLR_BUSY(ADF) ((ADF)->Flags &= ~AFF_BUSY) + +#define AF_IS_PENDING(ADF, X) (ADF->Flags & X) +#define AF_SET_PENDING(ADF, X) (ADF->Flags |= X) +#define AF_CLR_PENDING(ADF, X) (ADF->Flags &= ~X) + + +/* Structure used to search through Address Files */ +typedef struct _AF_SEARCH { + PLIST_ENTRY Next; /* Next address file to check */ + PIP_ADDRESS Address; /* Pointer to address to be found */ + USHORT Port; /* Network port */ + USHORT Protocol; /* Protocol number */ +} AF_SEARCH, *PAF_SEARCH; + + + +/******************************************************* +* Connection-oriented communication support structures * +*******************************************************/ + +typedef struct _TCP_SEND_REQUEST { + LIST_ENTRY ListEntry; /* Entry on list */ + DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine */ + PVOID Context; /* Pointer to context information */ + PVOID ProtocolContext; /* Protocol specific context */ + ULONG Flags; /* Protocol specific flags */ +} TCP_SEND_REQUEST, *PTCP_SEND_REQUEST; + +#define InitializeTCPSendRequest( \ + _SendRequest, \ + _Complete, \ + _Context, \ + _ProtocolContext) { \ + (_SendRequest)->Complete = (_Complete); \ + (_SendRequest)->Context = (_Context); \ + (_SendRequest)->ProtocolContext = (_ProtocolContext); \ + } + + +/* Connection states */ +typedef enum { + ctListen = 0, /* Waiting for incoming connection requests */ + ctSynSent, /* Waiting for matching connection request */ + ctSynReceived, /* Waiting for connection request acknowledgment */ + ctEstablished, /* Connection is open for data transfer */ + ctFinWait1, /* Waiting for termination request or ack. for same */ + ctFinWait2, /* Waiting for termination request from remote TCP */ + ctCloseWait, /* Waiting for termination request from local user */ + ctClosing, /* Waiting for termination ack. from remote TCP */ + ctLastAck, /* Waiting for termination request ack. from remote TCP */ + ctTimeWait, /* Waiting for enough time to pass to be sure the remote TCP + received the ack. of its connection termination request */ + ctClosed /* Represents a closed connection */ +} CONNECTION_STATE, *PCONNECTION_STATE; + + +/* Transport connection context structure A.K.A. Transmission Control Block + (TCB) in TCP terminology. The FileObject->FsContext2 field holds a pointer + to this structure */ +typedef struct _CONNECTION_ENDPOINT { + LIST_ENTRY ListEntry; /* Entry on list */ + LIST_ENTRY AddrFileEntry; /* Entry on address file list */ + KSPIN_LOCK Lock; /* Spin lock to protect this structure */ + ULONG RefCount; /* Number of references to this object */ + PVOID ClientContext; /* Pointer to client context information */ + PADDRESS_FILE AddressFile; /* Associated address file object (NULL if none) */ + + CONNECTION_STATE State; /* Connection state */ + + PIP_ADDRESS LocalAddress; /* Pointer to local IP address */ + USHORT LocalPort; /* Local port number */ + + PIP_ADDRESS RemoteAddress; /* Pointer to remote IP address */ + USHORT RemotePort; /* Remote port number */ + + /* Send sequence variables */ + ULONG SendUnacknowledged; /* Highest sequence number that is acknowledged */ + ULONG SendNext; /* Sequence number of last data block sent */ + ULONG SendWindow; /* Maximum allowed number of octets in a segment */ + ULONG SendUrgentPointer; /* Sequence number of start of urgent data */ + ULONG SendWL1; /* Sequence number used for last window update */ + ULONG SendWL2; /* Acknowledgment number used for last window update */ + ULONG SendISS; /* Initial send sequence number */ + + /* Receive sequence variables */ + ULONG RecvNext; /* Sequence number of last data block received */ + ULONG RecvWindow; /* Maximum allowed number of octets in a segment */ + ULONG RecvUrgentPointer; /* Sequence number of start of urgent data */ + ULONG RecvIRS; /* Initial receive sequence number */ + + /* Statistics for computing the retransmission timeout */ + ULONG TimestampSend; /* Timestamp when sending a segment */ + ULONG TimestampAck; /* Timestamp when receiving acknowledgment */ +} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT; + + + +/************************* +* TDI support structures * +*************************/ + +/* Transport control channel context structure. The FileObject->FsContext2 + field holds a pointer to this structure */ +typedef struct _CONTROL_CHANNEL { + LIST_ENTRY ListEntry; /* Entry on list */ + KSPIN_LOCK Lock; /* Spin lock to protect this structure */ + ULONG RefCount; /* Number of references to this object */ +} CONTROL_CHANNEL, *PCONTROL_CHANNEL; + +/* Transport (TCP/UDP) endpoint context structure. The FileObject->FsContext + field holds a pointer to this structure */ +typedef struct _TRANSPORT_CONTEXT { + union { + HANDLE AddressHandle; + CONNECTION_CONTEXT ConnectionContext; + HANDLE ControlChannel; + } Handle; + ULONG RefCount; + BOOL CancelIrps; + KEVENT CleanupEvent; +} TRANSPORT_CONTEXT, *PTRANSPORT_CONTEXT; + +typedef struct _TI_QUERY_CONTEXT { + PIRP Irp; + PMDL InputMdl; + PMDL OutputMdl; + TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo; +} TI_QUERY_CONTEXT, *PTI_QUERY_CONTEXT; + +#endif /* __TITYPES_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/transmit.h b/drivers/net/tcpip/include/transmit.h new file mode 100644 index 0000000..618e632 --- /dev/null +++ b/drivers/net/tcpip/include/transmit.h @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/transmit.h + * PURPOSE: Internet Protocol transmit prototypes + */ +#ifndef __TRANSMIT_H +#define __TRANSMIT_H + +#include +#include +#include + + +/* IP fragment context information */ +typedef struct IPFRAGMENT_CONTEXT { + struct IPFRAGMENT_CONTEXT *Next; /* Pointer to next in list */ + PNDIS_PACKET Datagram; /* Pointer to original NDIS packet */ + PVOID DatagramData; /* Pointer to datagram data */ + UINT HeaderSize; /* IP datagram header size */ + PNDIS_PACKET NdisPacket; /* Pointer to NDIS packet */ + PNDIS_BUFFER NdisBuffer; /* Pointer to NDIS buffer */ + PVOID Header; /* Pointer to IP header in fragment buffer */ + PVOID Data; /* Pointer to fragment data */ + UINT Position; /* Current fragment offset */ + UINT BytesLeft; /* Number of bytes left to send */ + UINT PathMTU; /* Path Maximum Transmission Unit */ + PNEIGHBOR_CACHE_ENTRY NCE; /* Pointer to NCE to use */ +} IPFRAGMENT_CONTEXT, *PIPFRAGMENT_CONTEXT; + + +VOID IPSendComplete( + PVOID Context, + PNDIS_PACKET NdisPacket, + NDIS_STATUS NdisStatus); + +NTSTATUS IPSendFragment( + PNDIS_PACKET NdisPacket, + PNEIGHBOR_CACHE_ENTRY NCE); + +NTSTATUS IPSendDatagram( + PIP_PACKET IPPacket, + PROUTE_CACHE_NODE RCN); + +#endif /* __TRANSMIT_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/include/udp.h b/drivers/net/tcpip/include/udp.h new file mode 100644 index 0000000..0246404 --- /dev/null +++ b/drivers/net/tcpip/include/udp.h @@ -0,0 +1,68 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: include/udp.h + * PURPOSE: User Datagram Protocol definitions + */ +#ifndef __UDP_H +#define __UDP_H + + +/* UDPv4 header structure */ +typedef struct UDP_HEADER { + USHORT SourcePort; /* Source port */ + USHORT DestPort; /* Destination port */ + USHORT Length; /* Size of header and data */ + USHORT Checksum; /* Checksum of datagram */ +} __attribute__((packed)) UDP_HEADER, *PUDP_HEADER; + +/* UDPv4 pseudo header */ +typedef struct UDP_PSEUDO_HEADER { + ULONG SourceAddress; /* Source address */ + ULONG DestAddress; /* Destination address */ + UCHAR Zero; /* Reserved */ + UCHAR Protocol; /* Protocol */ + USHORT UDPLength; /* Size of UDP datagram */ +} __attribute__((packed)) UDP_PSEUDO_HEADER, *PUDP_PSEUDO_HEADER; + + +typedef struct UDP_STATISTICS { + ULONG InputDatagrams; + ULONG NumPorts; + ULONG InputErrors; + ULONG OutputDatagrams; + ULONG NumAddresses; +} UDP_STATISTICS, *PUDP_STATISTICS; + +VOID UDPSend( + PVOID Context, + PDATAGRAM_SEND_REQUEST SendRequest); + +NTSTATUS UDPSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize); + +NTSTATUS UDPReceiveDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG ReceiveLength, + ULONG ReceiveFlags, + PTDI_CONNECTION_INFORMATION ReturnInfo, + PULONG BytesReceived); + +VOID UDPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket); + +NTSTATUS UDPStartup( + VOID); + +NTSTATUS UDPShutdown( + VOID); + +#endif /* __UDP_H */ + +/* EOF */ diff --git a/drivers/net/tcpip/makefile b/drivers/net/tcpip/makefile new file mode 100644 index 0000000..f5128cf --- /dev/null +++ b/drivers/net/tcpip/makefile @@ -0,0 +1,45 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = tcpip + +TARGET_CFLAGS = -I./include -DDBG + +TARGET_DDKLIBS = ndis.a + +TARGET_CLEAN = \ + tcpip/*.o \ + datalink/*.o \ + network/*.o \ + transport/datagram/*.o \ + transport/rawip/*.o \ + transport/tcp/*.o \ + transport/udp/*.o + +TCPIP_OBJECTS = tcpip/main.o tcpip/address.o tcpip/checksum.o \ + tcpip/dispatch.o tcpip/fileobjs.o tcpip/info.o \ + tcpip/pool.o tcpip/routines.o +DATALINK_OBJECTS = datalink/arp.o datalink/lan.o datalink/loopback.o +NETWORK_OBJECTS = network/icmp.o network/ip.o network/neighbor.o \ + network/receive.o network/route.o network/router.o \ + network/transmit.o +DATAGRAM_OBJECTS = transport/datagram/datagram.o +RAWIP_OBJECTS = transport/rawip/rawip.o +TCP_OBJECTS = transport/tcp/tcp.o +UDP_OBJECTS = transport/udp/udp.o + +TARGET_OBJECTS = \ + $(TCPIP_OBJECTS) \ + $(DATALINK_OBJECTS) \ + $(NETWORK_OBJECTS) \ + $(DATAGRAM_OBJECTS) \ + $(RAWIP_OBJECTS) \ + $(TCP_OBJECTS) \ + $(UDP_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/tcpip/network/Makefile b/drivers/net/tcpip/network/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/network/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/network/SOURCES b/drivers/net/tcpip/network/SOURCES new file mode 100644 index 0000000..3723ad5 --- /dev/null +++ b/drivers/net/tcpip/network/SOURCES @@ -0,0 +1,20 @@ +TARGETNAME=network +TARGETPATH=..\objects +TARGETTYPE=LIBRARY + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +INCLUDES=..\include;$(BASEDIR)\INC;..\..\..\..\include\net + + +SOURCES= icmp.c \ + ip.c \ + neighbor.c \ + receive.c \ + route.c \ + router.c \ + transmit.c + +MSC_WARNING_LEVEL=/W3 /WX + diff --git a/drivers/net/tcpip/network/icmp.c b/drivers/net/tcpip/network/icmp.c new file mode 100644 index 0000000..f45bb49 --- /dev/null +++ b/drivers/net/tcpip/network/icmp.c @@ -0,0 +1,310 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/icmp.c + * PURPOSE: Internet Control Message Protocol routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + + +VOID SendICMPComplete( + PVOID Context, + PNDIS_PACKET Packet, + NDIS_STATUS NdisStatus) +/* + * FUNCTION: ICMP datagram transmit completion handler + * ARGUMENTS: + * Context = Pointer to context infomation (IP_PACKET) + * Packet = Pointer to NDIS packet + * NdisStatus = Status of transmit operation + * NOTES: + * This routine is called by IP when a ICMP send completes + */ +{ + PIP_PACKET IPPacket = (PIP_PACKET)Context; + + TI_DbgPrint(DEBUG_ICMP, ("Freeing NDIS packet (%X).\n", Packet)); + + /* Free packet */ + FreeNdisPacket(Packet); + + TI_DbgPrint(DEBUG_ICMP, ("Freeing IP packet at %X.\n", IPPacket)); + + (*IPPacket->Free)(IPPacket); +} + + +PIP_PACKET PrepareICMPPacket( + PNET_TABLE_ENTRY NTE, + PIP_ADDRESS Destination, + UINT DataSize) +/* + * FUNCTION: Prepares an ICMP packet + * ARGUMENTS: + * NTE = Pointer to net table entry to use + * Destination = Pointer to destination address + * DataSize = Size of dataarea + * RETURNS: + * Pointer to IP packet, NULL if there is not enough free resources + */ +{ + PIP_PACKET IPPacket; + PNDIS_PACKET NdisPacket; + PNDIS_BUFFER NdisBuffer; + NDIS_STATUS NdisStatus; + PIPv4_HEADER IPHeader; + PVOID DataBuffer; + ULONG Size; + + TI_DbgPrint(DEBUG_ICMP, ("Called. DataSize (%d).\n", DataSize)); + + /* Prepare ICMP packet */ + + /* FIXME: Assumes IPv4*/ + IPPacket = IPCreatePacket(IP_ADDRESS_V4); + if (!IPPacket) + return NULL; + + /* No special flags */ + IPPacket->Flags = 0; + + Size = MaxLLHeaderSize + sizeof(IPv4_HEADER) + + sizeof(ICMP_HEADER) + DataSize; + DataBuffer = ExAllocatePool(NonPagedPool, Size); + if (!DataBuffer) { + (*IPPacket->Free)(IPPacket); + return NULL; + } + + TI_DbgPrint(DEBUG_ICMP, ("Size (%d). Data at (0x%X).\n", Size, DataBuffer)); + + /* Allocate NDIS packet */ + NdisAllocatePacket(&NdisStatus, &NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + (*IPPacket->Free)(IPPacket); + ExFreePool(DataBuffer); + return NULL; + } + + TI_DbgPrint(MAX_TRACE, ("NdisPacket at (0x%X).\n", NdisPacket)); + + /* Allocate NDIS buffer for maximum link level header and ICMP packet */ + NdisAllocateBuffer(&NdisStatus, &NdisBuffer, GlobalBufferPool, + DataBuffer, Size); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + (*IPPacket->Free)(IPPacket); + NdisFreePacket(NdisPacket); + ExFreePool(DataBuffer); + return NULL; + } + + TI_DbgPrint(MAX_TRACE, ("NdisBuffer at (0x%X).\n", NdisBuffer)); + + /* Link NDIS buffer into packet */ + NdisChainBufferAtFront(NdisPacket, NdisBuffer); + IPPacket->NdisPacket = NdisPacket; + IPPacket->Header = (PVOID)((ULONG_PTR)DataBuffer + MaxLLHeaderSize); + IPPacket->Data = (PVOID)((ULONG_PTR)DataBuffer + MaxLLHeaderSize + sizeof(IPv4_HEADER)); + + IPPacket->HeaderSize = sizeof(IPv4_HEADER); + IPPacket->TotalSize = Size - MaxLLHeaderSize; + RtlCopyMemory(&IPPacket->DstAddr, Destination, sizeof(IP_ADDRESS)); + + /* Build IPv4 header. FIXME: IPv4 only */ + + IPHeader = (PIPv4_HEADER)IPPacket->Header; + + /* Version = 4, Length = 5 DWORDs */ + IPHeader->VerIHL = 0x45; + /* Normal Type-of-Service */ + IPHeader->Tos = 0; + /* Length of data and header */ + IPHeader->TotalLength = WH2N((USHORT)DataSize + + sizeof(IPv4_HEADER) + sizeof(ICMP_HEADER)); + /* Identification */ + IPHeader->Id = (USHORT)Random(); + /* One fragment at offset 0 */ + IPHeader->FlagsFragOfs = 0; + /* Time-to-Live is 128 */ + IPHeader->Ttl = 128; + /* Internet Control Message Protocol */ + IPHeader->Protocol = IPPROTO_ICMP; + /* Checksum is 0 (for later calculation of this) */ + IPHeader->Checksum = 0; + /* Source address */ + IPHeader->SrcAddr = NTE->Address->Address.IPv4Address; + /* Destination address */ + IPHeader->DstAddr = Destination->Address.IPv4Address; + + /* Completion handler */ + PC(NdisPacket)->Complete = SendICMPComplete; + PC(NdisPacket)->Context = IPPacket; + + return IPPacket; +} + + +VOID ICMPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* + * FUNCTION: Receives an ICMP packet + * ARGUMENTS: + * NTE = Pointer to net table entry which the packet was received on + * IPPacket = Pointer to an IP packet that was received + */ +{ + PICMP_HEADER ICMPHeader; + PIP_PACKET NewPacket; + UINT DataSize; + + TI_DbgPrint(DEBUG_ICMP, ("Called.\n")); + + ICMPHeader = (PICMP_HEADER)IPPacket->Data; + + TI_DbgPrint(DEBUG_ICMP, ("Size (%d).\n", IPPacket->TotalSize)); + + TI_DbgPrint(DEBUG_ICMP, ("HeaderSize (%d).\n", IPPacket->HeaderSize)); + + TI_DbgPrint(DEBUG_ICMP, ("Type (%d).\n", ICMPHeader->Type)); + + TI_DbgPrint(DEBUG_ICMP, ("Code (%d).\n", ICMPHeader->Code)); + + TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum)); + + /* Checksum ICMP header and data */ + if (!CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) { + TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n")); + /* Discard packet */ + return; + } + + switch (ICMPHeader->Type) { + case ICMP_TYPE_ECHO_REQUEST: + /* Reply with an ICMP echo reply message */ + DataSize = IPPacket->TotalSize - IPPacket->HeaderSize - sizeof(ICMP_HEADER); + NewPacket = PrepareICMPPacket(NTE, &IPPacket->SrcAddr, DataSize); + if (!NewPacket) + return; + + /* Copy ICMP header and data into new packet */ + RtlCopyMemory(NewPacket->Data, IPPacket->Data, DataSize + sizeof(ICMP_HEADER)); + ((PICMP_HEADER)NewPacket->Data)->Type = ICMP_TYPE_ECHO_REPLY; + ((PICMP_HEADER)NewPacket->Data)->Code = 0; + ((PICMP_HEADER)NewPacket->Data)->Checksum = 0; + + DisplayIPPacket(IPPacket); + + DisplayIPPacket(NewPacket); + + ICMPTransmit(NTE, NewPacket); + + TI_DbgPrint(DEBUG_ICMP, ("Echo reply sent.\n")); + return; + + case ICMP_TYPE_ECHO_REPLY: + break; + + default: + TI_DbgPrint(DEBUG_ICMP, ("Discarded ICMP datagram of unknown type %d.\n", + ICMPHeader->Type)); + /* Discard packet */ + break; + } + + /* Send datagram up the protocol stack */ + RawIPReceive(NTE, IPPacket); +} + + +VOID ICMPTransmit( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* + * FUNCTION: Transmits an ICMP packet + * ARGUMENTS: + * NTE = Pointer to net table entry to use (NULL if don't care) + * IPPacket = Pointer to IP packet to transmit + */ +{ + PROUTE_CACHE_NODE RCN; + + TI_DbgPrint(DEBUG_ICMP, ("Called.\n")); + + /* Calculate checksum of ICMP header and data */ + ((PICMP_HEADER)IPPacket->Data)->Checksum = (USHORT) + IPv4Checksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize, 0); + + /* Get a route to the destination address */ + if (RouteGetRouteToDestination(&IPPacket->DstAddr, NTE, &RCN) == IP_SUCCESS) { + /* Send the packet */ + if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) { + FreeNdisPacket(IPPacket->NdisPacket); + (*IPPacket->Free)(IPPacket); + } + /* We're done with the RCN */ + DereferenceObject(RCN); + } else { + TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X).\n", RCN)); + + /* No route to destination (or no free resources) */ + TI_DbgPrint(DEBUG_ICMP, ("No route to destination address 0x%X.\n", + IPPacket->DstAddr.Address.IPv4Address)); + /* Discard packet */ + FreeNdisPacket(IPPacket->NdisPacket); + (*IPPacket->Free)(IPPacket); + } +} + + +VOID ICMPReply( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket, + UCHAR Type, + UCHAR Code) +/* + * FUNCTION: Transmits an ICMP packet in response to an incoming packet + * ARGUMENTS: + * NTE = Pointer to net table entry to use + * IPPacket = Pointer to IP packet that was received + * Type = ICMP message type + * Code = ICMP message code + * NOTES: + * We have received a packet from someone and is unable to + * process it due to error(s) in the packet or we have run out + * of resources. We transmit an ICMP message to the host to + * notify him of the problem + */ +{ + UINT DataSize; + PIP_PACKET NewPacket; + + TI_DbgPrint(DEBUG_ICMP, ("Called. Type (%d) Code (%d).\n", Type, Code)); + + DataSize = IPPacket->TotalSize; + if ((DataSize) > (576 - sizeof(IPv4_HEADER) - sizeof(ICMP_HEADER))) + DataSize = 576; + + NewPacket = PrepareICMPPacket(NTE, &IPPacket->SrcAddr, DataSize); + if (!NewPacket) + return; + + RtlCopyMemory((PVOID)((ULONG_PTR)NewPacket->Data + sizeof(ICMP_HEADER)), + IPPacket->Header, DataSize); + ((PICMP_HEADER)NewPacket->Data)->Type = Type; + ((PICMP_HEADER)NewPacket->Data)->Code = Code; + ((PICMP_HEADER)NewPacket->Data)->Checksum = 0; + + ICMPTransmit(NTE, NewPacket); +} + +/* EOF */ diff --git a/drivers/net/tcpip/network/ip.c b/drivers/net/tcpip/network/ip.c new file mode 100644 index 0000000..acfebfd --- /dev/null +++ b/drivers/net/tcpip/network/ip.c @@ -0,0 +1,1164 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/ip.c + * PURPOSE: Internet Protocol module + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +KTIMER IPTimer; +KDPC IPTimeoutDpc; +LIST_ENTRY InterfaceListHead; +KSPIN_LOCK InterfaceListLock; +LIST_ENTRY NetTableListHead; +KSPIN_LOCK NetTableListLock; +LIST_ENTRY PrefixListHead; +KSPIN_LOCK PrefixListLock; +UINT MaxLLHeaderSize; /* Largest maximum header size */ +UINT MinLLFrameSize; /* Largest minimum frame size */ +BOOLEAN IPInitialized = FALSE; +NPAGED_LOOKASIDE_LIST IPPacketList; + +IP_PROTOCOL_HANDLER ProtocolTable[IP_PROTOCOL_TABLE_SIZE]; + + +VOID FreePacket( + PVOID Object) +/* + * FUNCTION: Frees an IP packet object + * ARGUMENTS: + * Object = Pointer to an IP packet structure + */ +{ + ExFreeToNPagedLookasideList(&IPPacketList, Object); +} + + +VOID FreeADE( + PVOID Object) +/* + * FUNCTION: Frees an address entry object + * ARGUMENTS: + * Object = Pointer to an address entry structure + */ +{ + ExFreePool(Object); +} + + +VOID FreeNTE( + PVOID Object) +/* + * FUNCTION: Frees a net table entry object + * ARGUMENTS: + * Object = Pointer to an net table entry structure + */ +{ + ExFreePool(Object); +} + + +VOID FreeIF( + PVOID Object) +/* + * FUNCTION: Frees an interface object + * ARGUMENTS: + * Object = Pointer to an interface structure + */ +{ + ExFreePool(Object); +} + + +PADDRESS_ENTRY CreateADE( + PIP_INTERFACE IF, PIP_ADDRESS Address, + UCHAR Type, + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Creates an address entry and binds it to an interface + * ARGUMENTS: + * IF = Pointer to interface + * Address = Pointer to referenced interface address + * Type = Type of address (ADE_*) + * NTE = Pointer to net table entry + * RETURNS: + * Pointer to ADE, NULL if there was not enough free resources + * NOTES: + * The interface lock must be held when called. The address entry + * retains a reference to the provided address and NTE. The caller + * is responsible for referencing the these before calling. + * As long as you have referenced an ADE you can safely use the + * address and NTE as the ADE references both + */ +{ + PADDRESS_ENTRY ADE; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) Address (0x%X) Type (0x%X) NTE (0x%X).\n", + IF, Address, Type, NTE)); + + TI_DbgPrint(DEBUG_IP, ("Address (%s) NTE (%s).\n", + A2S(Address), A2S(NTE->Address))); + + /* Allocate space for an ADE and set it up */ + ADE = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_ENTRY)); + if (!ADE) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + INIT_TAG(ADE, TAG('A','D','E',' ')); + ADE->Free = FreeADE; + ADE->RefCount = 1; + ADE->NTE = NTE; + ADE->Type = Type; + ADE->Address = Address; + + /* Add ADE to the list on the interface */ + InsertTailList(&IF->ADEListHead, &ADE->ListEntry); + + return ADE; +} + + +VOID DestroyADE( + PIP_INTERFACE IF, + PADDRESS_ENTRY ADE) +/* + * FUNCTION: Destroys an address entry + * ARGUMENTS: + * IF = Pointer to interface + * ADE = Pointer to address entry + * NOTES: + * The interface lock must be held when called + */ +{ + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) ADE (0x%X).\n", IF, ADE)); + + TI_DbgPrint(DEBUG_IP, ("ADE (%s).\n", ADE->Address)); + + /* Unlink the address entry from the list */ + RemoveEntryList(&ADE->ListEntry); + + /* Dereference the address */ + DereferenceObject(ADE->Address); + + /* Dereference the NTE */ + DereferenceObject(ADE->NTE); + +#ifdef DBG + ADE->RefCount--; + + if (ADE->RefCount != 0) { + TI_DbgPrint(MIN_TRACE, ("Address entry at (0x%X) has (%d) references (should be 0).\n", ADE, ADE->RefCount)); + } +#endif + + /* And free the ADE */ + FreeADE(ADE); +} + + +VOID DestroyADEs( + PIP_INTERFACE IF) +/* + * FUNCTION: Destroys all address entries on an interface + * ARGUMENTS: + * IF = Pointer to interface + * NOTES: + * The interface lock must be held when called + */ +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PADDRESS_ENTRY Current; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); + + /* Search the list and remove every ADE we find */ + CurrentEntry = IF->ADEListHead.Flink; + while (CurrentEntry != &IF->ADEListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_ENTRY, ListEntry); + /* Destroy the ADE */ + DestroyADE(IF, Current); + CurrentEntry = NextEntry; + } +} + + +PIP_PACKET IPCreatePacket( + ULONG Type) +/* + * FUNCTION: Creates an IP packet object + * ARGUMENTS: + * Type = Type of IP packet + * RETURNS: + * Pointer to the created IP packet. NULL if there was not enough free resources. + */ +{ + PIP_PACKET IPPacket; + + IPPacket = ExAllocateFromNPagedLookasideList(&IPPacketList); + if (!IPPacket) + return NULL; + + /* FIXME: Is this needed? */ + RtlZeroMemory(IPPacket, sizeof(IP_PACKET)); + + INIT_TAG(IPPacket, TAG('I','P','K','T')); + + IPPacket->Free = FreePacket; + IPPacket->RefCount = 1; + IPPacket->Type = Type; + + return IPPacket; +} + + +PPREFIX_LIST_ENTRY CreatePLE( + PIP_INTERFACE IF, + PIP_ADDRESS Prefix, + UINT Length) +/* + * FUNCTION: Creates a prefix list entry and binds it to an interface + * ARGUMENTS: + * IF = Pointer to interface + * Prefix = Pointer to prefix + * Length = Length of prefix + * RETURNS: + * Pointer to PLE, NULL if there was not enough free resources + * NOTES: + * The prefix list entry retains a reference to the interface and + * the provided address. The caller is responsible for providing + * these references + */ +{ + PPREFIX_LIST_ENTRY PLE; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) Prefix (0x%X) Length (%d).\n", IF, Prefix, Length)); + + TI_DbgPrint(DEBUG_IP, ("Prefix (%s).\n", A2S(Prefix))); + + /* Allocate space for an PLE and set it up */ + PLE = ExAllocatePool(NonPagedPool, sizeof(PREFIX_LIST_ENTRY)); + if (!PLE) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + INIT_TAG(PLE, TAG('P','L','E',' ')); + PLE->RefCount = 1; + PLE->Interface = IF; + PLE->Prefix = Prefix; + PLE->PrefixLength = Length; + + /* Add PLE to the global prefix list */ + ExInterlockedInsertTailList(&PrefixListHead, &PLE->ListEntry, &PrefixListLock); + + return PLE; +} + + +VOID DestroyPLE( + PPREFIX_LIST_ENTRY PLE) +/* + * FUNCTION: Destroys an prefix list entry + * ARGUMENTS: + * PLE = Pointer to prefix list entry + * NOTES: + * The prefix list lock must be held when called + */ +{ + TI_DbgPrint(DEBUG_IP, ("Called. PLE (0x%X).\n", PLE)); + + TI_DbgPrint(DEBUG_IP, ("PLE (%s).\n", PLE->Prefix)); + + /* Unlink the prefix list entry from the list */ + RemoveEntryList(&PLE->ListEntry); + + /* Dereference the address */ + DereferenceObject(PLE->Prefix); + + /* Dereference the interface */ + DereferenceObject(PLE->Interface); + +#ifdef DBG + PLE->RefCount--; + + if (PLE->RefCount != 0) { + TI_DbgPrint(MIN_TRACE, ("Prefix list entry at (0x%X) has (%d) references (should be 0).\n", PLE, PLE->RefCount)); + } +#endif + + /* And free the PLE */ + ExFreePool(PLE); +} + + +VOID DestroyPLEs( + VOID) +/* + * FUNCTION: Destroys all prefix list entries + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PPREFIX_LIST_ENTRY Current; + + TI_DbgPrint(DEBUG_IP, ("Called.\n")); + + KeAcquireSpinLock(&PrefixListLock, &OldIrql); + + /* Search the list and remove every PLE we find */ + CurrentEntry = PrefixListHead.Flink; + while (CurrentEntry != &PrefixListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, PREFIX_LIST_ENTRY, ListEntry); + /* Destroy the PLE */ + DestroyPLE(Current); + CurrentEntry = NextEntry; + } + KeReleaseSpinLock(&PrefixListLock, OldIrql); +} + + +PNET_TABLE_ENTRY IPCreateNTE( + PIP_INTERFACE IF, + PIP_ADDRESS Address, + UINT PrefixLength) +/* + * FUNCTION: Creates a net table entry and binds it to an interface + * ARGUMENTS: + * IF = Pointer to interface + * Address = Pointer to interface address + * PrefixLength = Length of prefix + * RETURNS: + * Pointer to NTE, NULL if there was not enough free resources + * NOTES: + * The interface lock must be held when called. + * The net table entry retains a reference to the interface and + * the provided address. The caller is responsible for providing + * these references + */ +{ + PNET_TABLE_ENTRY NTE; + PADDRESS_ENTRY ADE; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) Address (0x%X) PrefixLength (%d).\n", IF, Address, PrefixLength)); + + TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address))); + + /* Allocate room for an NTE */ + NTE = ExAllocatePool(NonPagedPool, sizeof(NET_TABLE_ENTRY)); + if (!NTE) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + INIT_TAG(NTE, TAG('N','T','E',' ')); + INIT_TAG(Address, TAG('A','D','R','S')); + + NTE->Free = FreeNTE; + + NTE->Interface = IF; + + /* One reference is for beeing alive and one reference is for the ADE */ + NTE->RefCount = 2; + + NTE->Address = Address; + /* One reference is for NTE, one reference is given to the + address entry, and one reference is given to the prefix + list entry */ + ReferenceObject(Address); + ReferenceObject(Address); + ReferenceObject(Address); + + /* Create an address entry and add it to the list */ + ADE = CreateADE(IF, NTE->Address, ADE_UNICAST, NTE); + if (!ADE) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + ExFreePool(NTE); + return NULL; + } + + /* Create a prefix list entry for unicast address */ + NTE->PLE = CreatePLE(IF, NTE->Address, PrefixLength); + if (!NTE->PLE) { + DestroyADE(IF, ADE); + ExFreePool(NTE); + return NULL; + } + + /* Reference the interface for the prefix list entry */ + ReferenceObject(IF); + + /* Add NTE to the list on the interface */ + InsertTailList(&IF->NTEListHead, &NTE->IFListEntry); + + /* Add NTE to the global net table list */ + ExInterlockedInsertTailList(&NetTableListHead, &NTE->NTListEntry, &NetTableListLock); + + return NTE; +} + + +VOID DestroyNTE( + PIP_INTERFACE IF, + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Destroys a net table entry + * ARGUMENTS: + * IF = Pointer to interface + * NTE = Pointer to net table entry + * NOTES: + * The net table list lock must be held when called + * The interface lock must be held when called + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) NTE (0x%X).\n", IF, NTE)); + + TI_DbgPrint(DEBUG_IP, ("NTE (%s).\n", NTE->Address)); + + /* Invalidate the prefix list entry for this NTE */ + KeAcquireSpinLock(&PrefixListLock, &OldIrql); + DestroyPLE(NTE->PLE); + KeReleaseSpinLock(&PrefixListLock, OldIrql); + + /* Remove NTE from the interface list */ + RemoveEntryList(&NTE->IFListEntry); + /* Remove NTE from the net table list */ + +/* TODO: DEBUG: removed by RobD to prevent failure when testing under bochs 6 sept 2002. + + RemoveEntryList(&NTE->NTListEntry); + + */ + + /* Dereference the objects that are referenced */ + DereferenceObject(NTE->Address); + DereferenceObject(NTE->Interface); +#ifdef DBG + NTE->RefCount--; + + if (NTE->RefCount != 0) { + TI_DbgPrint(MIN_TRACE, ("Net table entry at (0x%X) has (%d) references (should be 0).\n", NTE, NTE->RefCount)); + } +#endif + /* And free the NTE */ + ExFreePool(NTE); +} + + +VOID DestroyNTEs( + PIP_INTERFACE IF) +/* + * FUNCTION: Destroys all net table entries on an interface + * ARGUMENTS: + * IF = Pointer to interface + * NOTES: + * The net table list lock must be held when called + * The interface lock may be held when called + */ +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PNET_TABLE_ENTRY Current; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); + + /* Search the list and remove every NTE we find */ + CurrentEntry = IF->NTEListHead.Flink; + while (CurrentEntry != &IF->NTEListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry); + /* Destroy the NTE */ + DestroyNTE(IF, Current); + CurrentEntry = NextEntry; + } +} + + +PNET_TABLE_ENTRY IPLocateNTEOnInterface( + PIP_INTERFACE IF, + PIP_ADDRESS Address, + PUINT AddressType) +/* + * FUNCTION: Locates an NTE on an interface + * ARGUMENTS: + * IF = Pointer to interface + * Address = Pointer to IP address + * AddressType = Address of type of IP address + * NOTES: + * If found, the NTE is referenced for the caller. The caller is + * responsible for dereferencing after use + * RETURNS: + * Pointer to net table entry, NULL if none was found + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PADDRESS_ENTRY Current; + +// TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X) Address (0x%X) AddressType (0x%X).\n", +// IF, Address, AddressType)); + +// TI_DbgPrint(DEBUG_IP, ("Address (%s) AddressType (0x%X).\n", A2S(Address))); + + KeAcquireSpinLock(&IF->Lock, &OldIrql); + + /* Search the list and return the NTE if found */ + CurrentEntry = IF->ADEListHead.Flink; + + if (CurrentEntry == &IF->ADEListHead) { + TI_DbgPrint(DEBUG_IP, ("NTE list is empty!!!\n")); + } + + while (CurrentEntry != &IF->ADEListHead) { + Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_ENTRY, ListEntry); + if (AddrIsEqual(Address, Current->Address)) { + ReferenceObject(Current->NTE); + *AddressType = Current->Type; + KeReleaseSpinLock(&IF->Lock, OldIrql); + return Current->NTE; + } + else { + TI_DbgPrint(DEBUG_IP, ("CurrentEntry = 0x%X != &IF->ADEListHead = 0x%X.\n", CurrentEntry, &IF->ADEListHead)); + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&IF->Lock, OldIrql); + + return NULL; +} + + +PNET_TABLE_ENTRY IPLocateNTE( + PIP_ADDRESS Address, + PUINT AddressType) +/* + * FUNCTION: Locates an NTE for the network Address is on + * ARGUMENTS: + * Address = Pointer to an address to find associated NTE of + * AddressType = Address of address type + * NOTES: + * If found the NTE is referenced for the caller. The caller is + * responsible for dereferencing after use + * RETURNS: + * Pointer to NTE if the address was found, NULL if not. + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PNET_TABLE_ENTRY Current; + PNET_TABLE_ENTRY NTE; + +// TI_DbgPrint(DEBUG_IP, ("Called. Address (0x%X) AddressType (0x%X).\n", +// Address, AddressType)); + +// TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address))); + + KeAcquireSpinLock(&NetTableListLock, &OldIrql); + + /* Search the list and return the NTE if found */ + CurrentEntry = NetTableListHead.Flink; + while (CurrentEntry != &NetTableListHead) { + Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, NTListEntry); + NTE = IPLocateNTEOnInterface(Current->Interface, Address, AddressType); + if (NTE) { + ReferenceObject(NTE); + KeReleaseSpinLock(&NetTableListLock, OldIrql); + return NTE; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&NetTableListLock, OldIrql); + + return NULL; +} + + +PADDRESS_ENTRY IPLocateADE( + PIP_ADDRESS Address, + UINT AddressType) +/* + * FUNCTION: Locates an ADE for the address + * ARGUMENTS: + * Address = Pointer to an address to find associated ADE of + * AddressType = Type of address + * RETURNS: + * Pointer to ADE if the address was found, NULL if not. + * NOTES: + * If found the ADE is referenced for the caller. The caller is + * responsible for dereferencing after use + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentIFEntry; + PLIST_ENTRY CurrentADEEntry; + PIP_INTERFACE CurrentIF; + PADDRESS_ENTRY CurrentADE; + +// TI_DbgPrint(DEBUG_IP, ("Called. Address (0x%X) AddressType (0x%X).\n", +// Address, AddressType)); + +// TI_DbgPrint(DEBUG_IP, ("Address (%s).\n", A2S(Address))); + + KeAcquireSpinLock(&InterfaceListLock, &OldIrql); + + /* Search the interface list */ + CurrentIFEntry = InterfaceListHead.Flink; + while (CurrentIFEntry != &InterfaceListHead) { + CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry); + + /* Search the address entry list and return the ADE if found */ + CurrentADEEntry = CurrentIF->ADEListHead.Flink; + while (CurrentADEEntry != &CurrentIF->ADEListHead) { + CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry); + if ((AddrIsEqual(Address, CurrentADE->Address)) && + (CurrentADE->Type == AddressType)) { + ReferenceObject(CurrentADE); + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + return CurrentADE; + } + CurrentADEEntry = CurrentADEEntry->Flink; + } + CurrentIFEntry = CurrentIFEntry->Flink; + } + + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + + return NULL; +} + + +PADDRESS_ENTRY IPGetDefaultADE( + UINT AddressType) +/* + * FUNCTION: Returns a default address entry + * ARGUMENTS: + * AddressType = Type of address + * RETURNS: + * Pointer to ADE if found, NULL if not. + * NOTES: + * Loopback interface is only considered if it is the only interface. + * If found, the address entry is referenced + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentIFEntry; + PLIST_ENTRY CurrentADEEntry; + PIP_INTERFACE CurrentIF; + PADDRESS_ENTRY CurrentADE; + BOOLEAN LoopbackIsRegistered = FALSE; + + TI_DbgPrint(DEBUG_IP, ("Called. AddressType (0x%X).\n", AddressType)); + + KeAcquireSpinLock(&InterfaceListLock, &OldIrql); + + /* Search the interface list */ + CurrentIFEntry = InterfaceListHead.Flink; + while (CurrentIFEntry != &InterfaceListHead) { + CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry); + + if (CurrentIF != Loopback) { + /* Search the address entry list and return the first appropriate ADE found */ + CurrentADEEntry = CurrentIF->ADEListHead.Flink; + while (CurrentADEEntry != &CurrentIF->ADEListHead) { + CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry); + if (CurrentADE->Type == AddressType) + ReferenceObject(CurrentADE); + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + return CurrentADE; + } + CurrentADEEntry = CurrentADEEntry->Flink; + } else + LoopbackIsRegistered = TRUE; + CurrentIFEntry = CurrentIFEntry->Flink; + } + + /* No address was found. Use loopback interface if available */ + if (LoopbackIsRegistered) { + CurrentADEEntry = Loopback->ADEListHead.Flink; + while (CurrentADEEntry != &Loopback->ADEListHead) { + CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry); + if (CurrentADE->Type == AddressType) { + ReferenceObject(CurrentADE); + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + return CurrentADE; + } + CurrentADEEntry = CurrentADEEntry->Flink; + } + } + + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + + return NULL; +} + + +VOID STDCALL IPTimeout( + PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +/* + * FUNCTION: Timeout DPC + * ARGUMENTS: + * Dpc = Pointer to our DPC object + * DeferredContext = Pointer to context information (unused) + * SystemArgument1 = Unused + * SystemArgument2 = Unused + * NOTES: + * This routine is dispatched once in a while to do maintainance jobs + */ +{ + /* Check if datagram fragments have taken too long to assemble */ + IPDatagramReassemblyTimeout(); + + /* Clean possible outdated cached neighbor addresses */ + NBTimeout(); + + /* Call upper layer timeout routines */ + TCPTimeout(); +} + + +VOID IPDispatchProtocol( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* + * FUNCTION: IP protocol dispatcher + * ARGUMENTS: + * NTE = Pointer to net table entry which the packet was received on + * IPPacket = Pointer to an IP packet that was received + * NOTES: + * This routine examines the IP header and passes the packet on to the + * right upper level protocol receive handler + */ +{ + UINT Protocol; + + switch (IPPacket->Type) { + case IP_ADDRESS_V4: + Protocol = ((PIPv4_HEADER)(IPPacket->Header))->Protocol; + break; + case IP_ADDRESS_V6: + /* FIXME: IPv6 adresses not supported */ + TI_DbgPrint(MIN_TRACE, ("IPv6 datagram discarded.\n")); + return; + default: + Protocol = 0; + } + + /* Call the appropriate protocol handler */ + (*ProtocolTable[Protocol])(NTE, IPPacket); +} + + +PIP_INTERFACE IPCreateInterface( + PLLIP_BIND_INFO BindInfo) +/* + * FUNCTION: Creates an IP interface + * ARGUMENTS: + * BindInfo = Pointer to link layer to IP binding information + * RETURNS: + * Pointer to IP_INTERFACE structure, NULL if there was + * not enough free resources + */ +{ + PIP_INTERFACE IF; + + TI_DbgPrint(DEBUG_IP, ("Called. BindInfo (0x%X).\n", BindInfo)); + +#ifdef DBG + if (BindInfo->Address) { + PUCHAR A = BindInfo->Address; + TI_DbgPrint(DEBUG_IP, ("Interface address (%02X %02X %02X %02X %02X %02X).\n", + A[0], A[1], A[2], A[3], A[4], A[5])); + } +#endif + + IF = ExAllocatePool(NonPagedPool, sizeof(IP_INTERFACE)); + if (!IF) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + INIT_TAG(IF, TAG('F','A','C','E')); + + IF->Free = FreeIF; + IF->RefCount = 1; + IF->Context = BindInfo->Context; + IF->HeaderSize = BindInfo->HeaderSize; + if (IF->HeaderSize > MaxLLHeaderSize) + MaxLLHeaderSize = IF->HeaderSize; + + IF->MinFrameSize = BindInfo->MinFrameSize; + if (IF->MinFrameSize > MinLLFrameSize) + MinLLFrameSize = IF->MinFrameSize; + + IF->MTU = BindInfo->MTU; + IF->Address = BindInfo->Address; + IF->AddressLength = BindInfo->AddressLength; + IF->Transmit = BindInfo->Transmit; + + InitializeListHead(&IF->ADEListHead); + InitializeListHead(&IF->NTEListHead); + + KeInitializeSpinLock(&IF->Lock); + + return IF; +} + + +VOID IPDestroyInterface( + PIP_INTERFACE IF) +/* + * FUNCTION: Destroys an IP interface + * ARGUMENTS: + * IF = Pointer to interface to destroy + */ +{ + KIRQL OldIrql1; + KIRQL OldIrql2; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); + + KeAcquireSpinLock(&NetTableListLock, &OldIrql1); + KeAcquireSpinLock(&IF->Lock, &OldIrql2); + DestroyADEs(IF); + DestroyNTEs(IF); + KeReleaseSpinLock(&IF->Lock, OldIrql2); + KeReleaseSpinLock(&NetTableListLock, OldIrql1); + +#ifdef DBG + IF->RefCount--; + + if (IF->RefCount != 0) { + TI_DbgPrint(MIN_TRACE, ("Interface at (0x%X) has (%d) references (should be 0).\n", IF, IF->RefCount)); + } +#endif + ExFreePool(IF); +} + + +BOOLEAN IPRegisterInterface( + PIP_INTERFACE IF) +/* + * FUNCTION: Registers an IP interface with IP layer + * ARGUMENTS: + * IF = Pointer to interface to register + * RETURNS; + * TRUE if interface was successfully registered, FALSE if not + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PNET_TABLE_ENTRY Current; + PROUTE_CACHE_NODE RCN; + PNEIGHBOR_CACHE_ENTRY NCE; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); + + KeAcquireSpinLock(&IF->Lock, &OldIrql); + + /* Add routes to all NTEs on this interface */ + CurrentEntry = IF->NTEListHead.Flink; + while (CurrentEntry != &IF->NTEListHead) { + Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry); + + /* Add a permanent neighbor for this NTE */ + ReferenceObject(Current->Address); + NCE = NBAddNeighbor(IF, Current->Address, IF->Address, + IF->AddressLength, NUD_PERMANENT); + if (!NCE) { + TI_DbgPrint(MIN_TRACE, ("Could not create NCE.\n")); + DereferenceObject(Current->Address); + KeReleaseSpinLock(&IF->Lock, OldIrql); + return FALSE; + } +#if 1 + /* Reference objects for forward information base */ + ReferenceObject(Current->Address); + ReferenceObject(Current->PLE->Prefix); + ReferenceObject(Current); + /* NCE is already referenced */ + if (!RouterAddRoute(Current->Address, Current->PLE->Prefix, Current, NCE, 1)) { + TI_DbgPrint(MIN_TRACE, ("Could not add route due to insufficient resources.\n")); + DereferenceObject(Current->Address); + DereferenceObject(Current->PLE->Prefix); + DereferenceObject(Current); + DereferenceObject(NCE); + } +#else + RCN = RouteAddRouteToDestination(Current->Address, Current, IF, NCE); + if (!RCN) { + TI_DbgPrint(MIN_TRACE, ("Could not create RCN.\n")); + DereferenceObject(Current->Address); + KeReleaseSpinLock(&IF->Lock, OldIrql); + return FALSE; + } + /* Don't need this any more since the route cache references the NCE */ + DereferenceObject(NCE); +#endif + CurrentEntry = CurrentEntry->Flink; + } + + /* Add interface to the global interface list */ + ExInterlockedInsertTailList(&InterfaceListHead, &IF->ListEntry, &InterfaceListLock); + + KeReleaseSpinLock(&IF->Lock, OldIrql); + + return TRUE; +} + + +VOID IPUnregisterInterface( + PIP_INTERFACE IF) +/* + * FUNCTION: Unregisters an IP interface with IP layer + * ARGUMENTS: + * IF = Pointer to interface to unregister + */ +{ + KIRQL OldIrql1; + KIRQL OldIrql2; + KIRQL OldIrql3; + PLIST_ENTRY CurrentEntry; + PNET_TABLE_ENTRY Current; + PNEIGHBOR_CACHE_ENTRY NCE; + + TI_DbgPrint(DEBUG_IP, ("Called. IF (0x%X).\n", IF)); + + KeAcquireSpinLock(&NetTableListLock, &OldIrql1); + KeAcquireSpinLock(&IF->Lock, &OldIrql2); + + /* Remove routes to all NTEs on this interface */ + CurrentEntry = IF->NTEListHead.Flink; + while (CurrentEntry != &IF->NTEListHead) { + Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry); + + /* Remove NTE from global net table list */ + RemoveEntryList(&Current->NTListEntry); + + /* Remove all references from route cache to NTE */ + RouteInvalidateNTE(Current); + + /* Remove permanent NCE, but first we have to find it */ + NCE = NBLocateNeighbor(Current->Address); + if (NCE) { + DereferenceObject(NCE); + NBRemoveNeighbor(NCE); + } + + CurrentEntry = CurrentEntry->Flink; + } + + KeAcquireSpinLock(&InterfaceListLock, &OldIrql3); + /* Ouch...three spinlocks acquired! Fortunately + we don't unregister interfaces very often */ + RemoveEntryList(&IF->ListEntry); + KeReleaseSpinLock(&InterfaceListLock, OldIrql3); + + KeReleaseSpinLock(&IF->Lock, OldIrql2); + KeReleaseSpinLock(&NetTableListLock, OldIrql1); +} + + +VOID IPRegisterProtocol( + UINT ProtocolNumber, + IP_PROTOCOL_HANDLER Handler) +/* + * FUNCTION: Registers a handler for an IP protocol number + * ARGUMENTS: + * ProtocolNumber = Internet Protocol number for which to register handler + * Handler = Pointer to handler to be called when a packet is received + * NOTES: + * To unregister a protocol handler, call this function with Handler = NULL + */ +{ +#ifdef DBG + if (ProtocolNumber >= IP_PROTOCOL_TABLE_SIZE) + TI_DbgPrint(MIN_TRACE, ("Protocol number is out of range (%d).\n", ProtocolNumber)); +#endif + + ProtocolTable[ProtocolNumber] = Handler; +} + + +VOID DefaultProtocolHandler( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* + * FUNCTION: Default handler for Internet protocols + * ARGUMENTS: + * NTE = Pointer to net table entry which the packet was received on + * IPPacket = Pointer to an IP packet that was received + */ +{ + TI_DbgPrint(MID_TRACE, ("Packet of unknown Internet protocol discarded.\n")); +} + + +NTSTATUS IPStartup( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Initializes the IP subsystem + * ARGUMENTS: + * DriverObject = Pointer to a driver object for this driver + * RegistryPath = Our registry node for configuration parameters + * RETURNS: + * Status of operation + */ +{ + UINT i; + LARGE_INTEGER DueTime; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + MaxLLHeaderSize = 0; + MinLLFrameSize = 0; + + /* Initialize lookaside lists */ + ExInitializeNPagedLookasideList( + &IPDRList, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(IPDATAGRAM_REASSEMBLY), /* Size of each entry */ + TAG('I','P','D','R'), /* Tag */ + 0); /* Depth */ + + ExInitializeNPagedLookasideList( + &IPPacketList, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(IP_PACKET), /* Size of each entry */ + TAG('I','P','P','K'), /* Tag */ + 0); /* Depth */ + + ExInitializeNPagedLookasideList( + &IPFragmentList, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(IP_FRAGMENT), /* Size of each entry */ + TAG('I','P','F','G'), /* Tag */ + 0); /* Depth */ + + ExInitializeNPagedLookasideList( + &IPHoleList, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(IPDATAGRAM_HOLE), /* Size of each entry */ + TAG('I','P','H','L'), /* Tag */ + 0); /* Depth */ + + /* Start routing subsystem */ + RouterStartup(); + + /* Start route cache subsystem */ + RouteStartup(); + + /* Start neighbor cache subsystem */ + NBStartup(); + + /* Fill the protocol dispatch table with pointers + to the default protocol handler */ + for (i = 0; i < IP_PROTOCOL_TABLE_SIZE; i++) + IPRegisterProtocol(i, DefaultProtocolHandler); + + /* Register network level protocol receive handlers */ + IPRegisterProtocol(IPPROTO_ICMP, ICMPReceive); + + /* Initialize NTE list and protecting lock */ + InitializeListHead(&NetTableListHead); + KeInitializeSpinLock(&NetTableListLock); + + /* Initialize reassembly list and protecting lock */ + InitializeListHead(&ReassemblyListHead); + KeInitializeSpinLock(&ReassemblyListLock); + + /* Initialize the prefix list and protecting lock */ + InitializeListHead(&PrefixListHead); + KeInitializeSpinLock(&PrefixListLock); + + /* Initialize our periodic timer and its associated DPC object. When the + timer expires, the IPTimeout deferred procedure call (DPC) is queued */ + KeInitializeDpc(&IPTimeoutDpc, IPTimeout, NULL); + KeInitializeTimer(&IPTimer); + + /* Start the periodic timer with an initial and periodic + relative expiration time of IP_TIMEOUT milliseconds */ + DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000; + KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc); + + IPInitialized = TRUE; + + return STATUS_SUCCESS; +} + + +NTSTATUS IPShutdown( + VOID) +/* + * FUNCTION: Shuts down the IP subsystem + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (!IPInitialized) + return STATUS_SUCCESS; + + /* Cancel timer */ + KeCancelTimer(&IPTimer); + + /* Shutdown neighbor cache subsystem */ + NBShutdown(); + + /* Shutdown route cache subsystem */ + RouteShutdown(); + + /* Shutdown routing subsystem */ + RouterShutdown(); + + IPFreeReassemblyList(); + + /* Clear prefix list */ + DestroyPLEs(); + + /* Destroy lookaside lists */ + ExDeleteNPagedLookasideList(&IPHoleList); + ExDeleteNPagedLookasideList(&IPDRList); + ExDeleteNPagedLookasideList(&IPPacketList); + ExDeleteNPagedLookasideList(&IPFragmentList); + + IPInitialized = FALSE; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/tcpip/network/neighbor.c b/drivers/net/tcpip/network/neighbor.c new file mode 100644 index 0000000..d99ef28 --- /dev/null +++ b/drivers/net/tcpip/network/neighbor.c @@ -0,0 +1,518 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/neighbor.c + * PURPOSE: Neighbor address cache + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +NEIGHBOR_CACHE_TABLE NeighborCache[NB_HASHMASK + 1]; + + +VOID FreeNCE( + PVOID Object) +{ + ExFreePool(Object); +} + + +VOID NCETimeout( + PNEIGHBOR_CACHE_ENTRY NCE) +/* + * FUNCTION: Neighbor cache entry timeout handler + * NOTES: + * The neighbor cache lock must be held + */ +{ + PNDIS_PACKET NdisPacket, Next; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE)); + + TI_DbgPrint(DEBUG_NCACHE, ("NCE->State is (0x%X).\n", NCE->State)); + + switch (NCE->State) { + case NUD_INCOMPLETE: + /* Retransmission timer expired */ + if (NCE->EventCount++ > MAX_MULTICAST_SOLICIT) { + /* We have retransmitted too many times */ + + /* Calling IPSendComplete with cache lock held is not + a great thing to do. We don't get here very often + so maybe it's not that big a problem */ + + /* Flush packet queue */ + NdisPacket = NCE->WaitQueue; + while (NdisPacket) { + Next = (PNDIS_PACKET)PC(NdisPacket)->DLComplete; + IPSendComplete((PVOID)NCE->Interface, NdisPacket, + NDIS_STATUS_REQUEST_ABORTED); + NdisPacket = Next; + } + NCE->WaitQueue = NULL; + + NCE->EventCount = 0; + + /* Remove route cache entries with references to this NCE. + Remember that neighbor cache lock is taken before + route cache lock */ + RouteInvalidateNCE(NCE); + } else + /* Retransmit request */ + NBSendSolicit(NCE); + break; + + case NUD_DELAY: + /* FIXME: Delayed state */ + TI_DbgPrint(DEBUG_NCACHE, ("NCE delay state.\n")); + break; + + case NUD_PROBE: + /* FIXME: Probe state */ + TI_DbgPrint(DEBUG_NCACHE, ("NCE probe state.\n")); + break; + + default: + /* Should not happen since other states don't use the event timer */ + TI_DbgPrint(MIN_TRACE, ("Invalid NCE state (%d).\n", NCE->State)); + break; + } +} + + +VOID NBTimeout( + VOID) +/* + * FUNCTION: Neighbor address cache timeout handler + * NOTES: + * This routine is called by IPTimeout to remove outdated cache + * entries. + */ +{ + UINT i; + KIRQL OldIrql; + PNEIGHBOR_CACHE_ENTRY NCE; + + for (i = 0; i <= NB_HASHMASK; i++) { + KeAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql); + + for (NCE = NeighborCache[i].Cache; + NCE != NULL; NCE = NCE->Next) { + /* Check if event timer is running */ + if (NCE->EventTimer != 0) { + if (--NCE->EventTimer == 0) { + /* Call timeout handler for NCE */ + NCETimeout(NCE); + } + } + } + + KeReleaseSpinLock(&NeighborCache[i].Lock, OldIrql); + } +} + + +VOID NBStartup( + VOID) +/* + * FUNCTION: Starts the neighbor cache + */ +{ + UINT i; + + TI_DbgPrint(DEBUG_NCACHE, ("Called.\n")); + + for (i = 0; i <= NB_HASHMASK; i++) { + NeighborCache[i].Cache = NULL; + KeInitializeSpinLock(&NeighborCache[i].Lock); + } +} + + +VOID NBShutdown( + VOID) +/* + * FUNCTION: Shuts down the neighbor cache + */ +{ + UINT i; + KIRQL OldIrql; + PNDIS_PACKET NdisPacket, Next; + PNEIGHBOR_CACHE_ENTRY CurNCE, NextNCE; + + TI_DbgPrint(DEBUG_NCACHE, ("Called.\n")); + + /* Remove possible entries from the cache */ + for (i = 0; i <= NB_HASHMASK; i++) { + KeAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql); + + CurNCE = NeighborCache[i].Cache; + while (CurNCE) { + NextNCE = CurNCE->Next; + + /* Remove all references from route cache */ + RouteInvalidateNCE(CurNCE); + + /* Flush wait queue */ + NdisPacket = CurNCE->WaitQueue; + while (NdisPacket) { + Next = (PNDIS_PACKET)PC(NdisPacket)->DLComplete; + FreeNdisPacket(NdisPacket); + NdisPacket = Next; + } + +#if DBG + if (CurNCE->RefCount != 1) { + TI_DbgPrint(DEBUG_REFCOUNT, ("NCE at (0x%X) has (%d) references (should be 1).\n", CurNCE, CurNCE->RefCount)); + } +#endif + + /* Remove reference for being alive */ + DereferenceObject(CurNCE); + + CurNCE = NextNCE; + } + NeighborCache[i].Cache = NULL; + + KeReleaseSpinLock(&NeighborCache[i].Lock, OldIrql); + } + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID NBSendSolicit( + PNEIGHBOR_CACHE_ENTRY NCE) +/* + * FUNCTION: Sends a neighbor solicitation message + * ARGUMENTS: + * NCE = Pointer to NCE of neighbor to solicit + * NOTES: + * May be called with lock held on NCE's table + */ +{ + PLIST_ENTRY CurrentEntry; + PNET_TABLE_ENTRY NTE; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE)); + + if (NCE->State == NUD_INCOMPLETE) { + /* This is the first solicitation of this neighbor. Broadcast + a request for the neighbor */ + + /* FIXME: Choose first NTE. We might want to give an NTE as argument */ + CurrentEntry = NCE->Interface->NTEListHead.Flink; + if (!IsListEmpty(CurrentEntry)) { + NTE = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry); + ARPTransmit(NCE->Address, NTE); + } else { + TI_DbgPrint(MIN_TRACE, ("Interface at 0x%X has zero NTE.\n", NCE->Interface)); + } + } else { + /* FIXME: Unicast solicitation since we have a cached address */ + TI_DbgPrint(MIN_TRACE, ("Uninplemented unicast solicitation.\n")); + } +} + + +PNEIGHBOR_CACHE_ENTRY NBAddNeighbor( + PIP_INTERFACE Interface, + PIP_ADDRESS Address, + PVOID LinkAddress, + UINT LinkAddressLength, + UCHAR State) +/* + * FUNCTION: Adds a neighbor to the neighbor cache + * ARGUMENTS: + * Interface = Pointer to interface + * Address = Pointer to IP address + * LinkAddress = Pointer to link address (may be NULL) + * LinkAddressLength = Length of link address + * State = State of NCE + * RETURNS: + * Pointer to NCE, NULL there is not enough free resources + * NOTES: + * The NCE if referenced for the caller if created. The NCE retains + * a reference to the IP address if it is created, the caller is + * responsible for providing this reference + */ +{ + ULONG HashValue; + KIRQL OldIrql; + PNEIGHBOR_CACHE_ENTRY NCE; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. Interface (0x%X) Address (0x%X) " + "LinkAddress (0x%X) LinkAddressLength (%d) State (0x%X)\n", + Interface, Address, LinkAddress, LinkAddressLength, State)); + + NCE = ExAllocatePool(NonPagedPool, sizeof(NEIGHBOR_CACHE_ENTRY) + LinkAddressLength); + if (!NCE) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + INIT_TAG(NCE, TAG('N','C','E',' ')); + + /* Initialize NCE free routine */ + NCE->Free = FreeNCE; + + /* Reference once for beeing alive and once for the caller */ + NCE->RefCount = 2; + NCE->Interface = Interface; + NCE->Address = Address; + NCE->LinkAddressLength = LinkAddressLength; + NCE->LinkAddress = (PVOID)((ULONG_PTR)NCE + sizeof(NEIGHBOR_CACHE_ENTRY)); + if (LinkAddress) + RtlCopyMemory(NCE->LinkAddress, LinkAddress, LinkAddressLength); + NCE->State = State; + NCE->EventTimer = 0; /* Not in use */ + NCE->WaitQueue = NULL; + + HashValue = *(PULONG)&Address->Address; + HashValue ^= HashValue >> 16; + HashValue ^= HashValue >> 8; + HashValue ^= HashValue >> 4; + HashValue &= NB_HASHMASK; + + NCE->Table = &NeighborCache[HashValue]; + + KeAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql); + + NCE->Next = NeighborCache[HashValue].Cache; + NeighborCache[HashValue].Cache = NCE; + + KeReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); + + return NCE; +} + + +VOID NBUpdateNeighbor( + PNEIGHBOR_CACHE_ENTRY NCE, + PVOID LinkAddress, + UCHAR State) +/* + * FUNCTION: Update link address information in NCE + * ARGUMENTS: + * NCE = Pointer to NCE to update + * LinkAddress = Pointer to link address + * State = State of NCE + * NOTES: + * The link address and state is updated. Any waiting packets are sent + */ +{ + KIRQL OldIrql; + PNDIS_PACKET Current; + PNDIS_PACKET Next; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X) LinkAddress (0x%X) State (0x%X).\n", NCE, LinkAddress, State)); + + KeAcquireSpinLock(&NCE->Table->Lock, &OldIrql); + + RtlCopyMemory(NCE->LinkAddress, LinkAddress, NCE->LinkAddressLength); + NCE->State = State; + Current = NCE->WaitQueue; + NCE->WaitQueue = NULL; + + KeReleaseSpinLock(&NCE->Table->Lock, OldIrql); +#if 1 + /* Send any waiting packets */ + while (Current) { + /* Our link to the next packet is broken by the + datalink layer code so we must save it here */ + Next = (PNDIS_PACKET)PC(Current)->DLComplete; + IPSendFragment(Current, NCE); + Current = Next; + } +#endif +} + + +PNEIGHBOR_CACHE_ENTRY NBLocateNeighbor( + PIP_ADDRESS Address) +/* + * FUNCTION: Locates a neighbor in the neighbor cache + * ARGUMENTS: + * Address = Pointer to IP address + * RETURNS: + * Pointer to NCE, NULL if not found + * NOTES: + * If the NCE is found, it is referenced. The caller is + * responsible for dereferencing it again after use + */ +{ + UINT HashValue; + KIRQL OldIrql; + PNEIGHBOR_CACHE_ENTRY NCE; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. Address (0x%X).\n", Address)); + + HashValue = *(PULONG)&Address->Address; + HashValue ^= HashValue >> 16; + HashValue ^= HashValue >> 8; + HashValue ^= HashValue >> 4; + HashValue &= NB_HASHMASK; + + KeAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql); + + NCE = NeighborCache[HashValue].Cache; + + while ((NCE) && (!AddrIsEqual(Address, NCE->Address))) + NCE = NCE->Next; + + if (NCE) + ReferenceObject(NCE); + + KeReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return NCE; +} + + +PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor( + PIP_INTERFACE Interface, + PIP_ADDRESS Address) +/* + * FUNCTION: Tries to find a neighbor and if unsuccesful, creates a new NCE + * ARGUMENTS: + * Interface = Pointer to interface to use (if NCE is not found) + * Address = Pointer to IP address + * RETURNS: + * Pointer to NCE, NULL if there is not enough free resources + * NOTES: + * The NCE is referenced if found or created. The caller is + * responsible for dereferencing it again after use + */ +{ + PNEIGHBOR_CACHE_ENTRY NCE; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. Interface (0x%X) Address (0x%X).\n", Interface, Address)); + + NCE = NBLocateNeighbor(Address); + if (!NCE) { + ReferenceObject(Address); + NCE = NBAddNeighbor(Interface, Address, NULL, + Interface->AddressLength, NUD_INCOMPLETE); + NCE->EventTimer = 1; + NCE->EventCount = 0; + } + + return NCE; +} + + +BOOLEAN NBQueuePacket( + PNEIGHBOR_CACHE_ENTRY NCE, + PNDIS_PACKET NdisPacket) +/* + * FUNCTION: Queues a packet on an NCE for later transmission + * ARGUMENTS: + * NCE = Pointer to NCE to queue packet on + * NdisPacket = Pointer to NDIS packet to queue + * RETURNS: + * TRUE if the packet was successfully queued, FALSE if not + */ +{ + KIRQL OldIrql; + PKSPIN_LOCK Lock; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X) NdisPacket (0x%X).\n", NCE, NdisPacket)); + + /* FIXME: Should we limit the number of queued packets? */ + + Lock = &NCE->Table->Lock; + + KeAcquireSpinLock(Lock, &OldIrql); + + /* Use data link level completion handler pointer to link + queued packets together */ + PC(NdisPacket)->DLComplete = (PACKET_COMPLETION_ROUTINE)NCE->WaitQueue; + NCE->WaitQueue = NdisPacket; + + KeReleaseSpinLock(Lock, OldIrql); + + return TRUE; +} + + +VOID NBRemoveNeighbor( + PNEIGHBOR_CACHE_ENTRY NCE) +/* + * FUNCTION: Removes a neighbor from the neighbor cache + * ARGUMENTS: + * NCE = Pointer to NCE to remove from cache + * NOTES: + * The NCE must be in a safe state + */ +{ + ULONG HashValue; + KIRQL OldIrql; + PNEIGHBOR_CACHE_ENTRY *PrevNCE; + PNEIGHBOR_CACHE_ENTRY CurNCE; + PNDIS_PACKET NdisPacket, Next; + + TI_DbgPrint(DEBUG_NCACHE, ("Called. NCE (0x%X).\n", NCE)); + + HashValue = *(PULONG)(&NCE->Address->Address); + HashValue ^= HashValue >> 16; + HashValue ^= HashValue >> 8; + HashValue ^= HashValue >> 4; + HashValue &= NB_HASHMASK; + + KeAcquireSpinLock(&NeighborCache[HashValue].Lock, &OldIrql); + + /* Search the list and remove the NCE from the list if found */ + for (PrevNCE = &NeighborCache[HashValue].Cache; + (CurNCE = *PrevNCE) != NULL; + PrevNCE = &CurNCE->Next) { + if (CurNCE == NCE) { + /* Found it, now unlink it from the list */ + *PrevNCE = CurNCE->Next; + + /* Purge wait queue */ + NdisPacket = CurNCE->WaitQueue; + while (NdisPacket) { + Next = (PNDIS_PACKET)PC(NdisPacket)->DLComplete; + FreeNdisPacket(NdisPacket); + NdisPacket = Next; + } + + /* Remove all references from route cache */ + RouteInvalidateNCE(CurNCE); + + /* Remove reference to the address */ + DereferenceObject(CurNCE->Address); + +#if DBG + CurNCE->RefCount--; + + if (CurNCE->RefCount != 0) { + TI_DbgPrint(DEBUG_REFCOUNT, ("NCE at (0x%X) has (%d) references (should be 0).\n", CurNCE, CurNCE->RefCount)); + } +#endif + ExFreePool(CurNCE); + + KeReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); + + return; + } + } + + KeReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); +} + +/* EOF */ diff --git a/drivers/net/tcpip/network/receive.c b/drivers/net/tcpip/network/receive.c new file mode 100644 index 0000000..c983838 --- /dev/null +++ b/drivers/net/tcpip/network/receive.c @@ -0,0 +1,640 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/receive.c + * PURPOSE: Internet Protocol receive routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: The IP datagram reassembly algorithm is taken from + * from RFC 815 + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +LIST_ENTRY ReassemblyListHead; +KSPIN_LOCK ReassemblyListLock; +NPAGED_LOOKASIDE_LIST IPDRList; +NPAGED_LOOKASIDE_LIST IPFragmentList; +NPAGED_LOOKASIDE_LIST IPHoleList; + + +PIPDATAGRAM_HOLE CreateHoleDescriptor( + ULONG First, + ULONG Last) +/* + * FUNCTION: Returns a pointer to a IP datagram hole descriptor + * ARGUMENTS: + * First = Offset of first octet of the hole + * Last = Offset of last octet of the hole + * RETURNS: + * Pointer to descriptor, NULL if there was not enough free + * resources + */ +{ + PIPDATAGRAM_HOLE Hole; + + TI_DbgPrint(DEBUG_IP, ("Called. First (%d) Last (%d).\n", First, Last)); + + Hole = ExAllocateFromNPagedLookasideList(&IPHoleList); + if (!Hole) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + Hole->First = First; + Hole->Last = Last; + + TI_DbgPrint(DEBUG_IP, ("Returning hole descriptor at (0x%X).\n", Hole)); + + return Hole; +} + + +VOID FreeIPDR( + PIPDATAGRAM_REASSEMBLY IPDR) +/* + * FUNCTION: Frees an IP datagram reassembly structure + * ARGUMENTS: + * IPDR = Pointer to IP datagram reassembly structure + */ +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PIPDATAGRAM_HOLE CurrentH; + PIP_FRAGMENT CurrentF; + + TI_DbgPrint(DEBUG_IP, ("Freeing IP datagram reassembly descriptor (0x%X).\n", IPDR)); + + /* Free all descriptors */ + CurrentEntry = IPDR->HoleListHead.Flink; + while (CurrentEntry != &IPDR->HoleListHead) { + NextEntry = CurrentEntry->Flink; + CurrentH = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry); + /* Unlink it from the list */ + RemoveEntryList(CurrentEntry); + + TI_DbgPrint(DEBUG_IP, ("Freeing hole descriptor at (0x%X).\n", CurrentH)); + + /* And free the hole descriptor */ + ExFreeToNPagedLookasideList(&IPHoleList, CurrentH); + + CurrentEntry = NextEntry; + } + + /* Free all fragments */ + CurrentEntry = IPDR->FragmentListHead.Flink; + while (CurrentEntry != &IPDR->FragmentListHead) { + NextEntry = CurrentEntry->Flink; + CurrentF = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry); + /* Unlink it from the list */ + RemoveEntryList(CurrentEntry); + + TI_DbgPrint(DEBUG_IP, ("Freeing fragment data at (0x%X).\n", CurrentF->Data)); + + /* Free the fragment data buffer */ + ExFreePool(CurrentF->Data); + + TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF)); + + /* And free the fragment descriptor */ + ExFreeToNPagedLookasideList(&IPFragmentList, CurrentF); + CurrentEntry = NextEntry; + } + + /* Free resources for the header, if it exists */ + if (IPDR->IPv4Header) { + TI_DbgPrint(DEBUG_IP, ("Freeing IPv4 header data at (0x%X).\n", IPDR->IPv4Header)); + ExFreePool(IPDR->IPv4Header); + } + + TI_DbgPrint(DEBUG_IP, ("Freeing IPDR data at (0x%X).\n", IPDR)); + + ExFreeToNPagedLookasideList(&IPDRList, IPDR); +} + + +VOID RemoveIPDR( + PIPDATAGRAM_REASSEMBLY IPDR) +/* + * FUNCTION: Removes an IP datagram reassembly structure from the global list + * ARGUMENTS: + * IPDR = Pointer to IP datagram reassembly structure + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IP, ("Removing IPDR at (0x%X).\n", IPDR)); + + KeAcquireSpinLock(&ReassemblyListLock, &OldIrql); + RemoveEntryList(&IPDR->ListEntry); + KeReleaseSpinLock(&ReassemblyListLock, OldIrql); +} + + +PIPDATAGRAM_REASSEMBLY GetReassemblyInfo( + PIP_PACKET IPPacket) +/* + * FUNCTION: Returns a pointer to an IP datagram reassembly structure + * ARGUMENTS: + * IPPacket = Pointer to IP packet + * NOTES: + * A datagram is identified by four paramters, which are + * Source and destination address, protocol number and + * identification number + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PIPDATAGRAM_REASSEMBLY Current; + PIPv4_HEADER Header = (PIPv4_HEADER)IPPacket->Header; + + TI_DbgPrint(DEBUG_IP, ("Searching for IPDR for IP packet at (0x%X).\n", IPPacket)); + + KeAcquireSpinLock(&ReassemblyListLock, &OldIrql); + + /* FIXME: Assume IPv4 */ + + CurrentEntry = ReassemblyListHead.Flink; + while (CurrentEntry != &ReassemblyListHead) { + Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry); + if (AddrIsEqual(&IPPacket->SrcAddr, &Current->SrcAddr) && + (Header->Id == Current->Id) && + (Header->Protocol == Current->Protocol) && + (AddrIsEqual(&IPPacket->DstAddr, &Current->DstAddr))) { + KeReleaseSpinLock(&ReassemblyListLock, OldIrql); + + return Current; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&ReassemblyListLock, OldIrql); + + return NULL; +} + + +PIP_PACKET ReassembleDatagram( + PIPDATAGRAM_REASSEMBLY IPDR) +/* + * FUNCTION: Reassembles an IP datagram + * ARGUMENTS: + * IPDR = Pointer to IP datagram reassembly structure + * NOTES: + * This routine concatenates fragments into a complete IP datagram. + * The lock is held when this routine is called + * RETURNS: + * Pointer to IP packet, NULL if there was not enough free resources + */ +{ + PIP_PACKET IPPacket; + PLIST_ENTRY CurrentEntry; + PIP_FRAGMENT Current; + PVOID Data; + + TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR)); + + /* FIXME: Assume IPv4 */ + IPPacket = IPCreatePacket(IP_ADDRESS_V4); + if (!IPPacket) + return NULL; + + IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize; + IPPacket->ContigSize = IPPacket->TotalSize; + IPPacket->HeaderSize = IPDR->HeaderSize; + IPPacket->Position = IPDR->HeaderSize; + + RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS)); + RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS)); + + /* Allocate space for full IP datagram */ + IPPacket->Header = ExAllocatePool(NonPagedPool, IPPacket->TotalSize); + if (!IPPacket->Header) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + (*IPPacket->Free)(IPPacket); + return NULL; + } + + /* Copy the header into the buffer */ + RtlCopyMemory(IPPacket->Header, IPDR->IPv4Header, IPDR->HeaderSize); + + Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPDR->HeaderSize); + IPPacket->Data = Data; + + /* Copy data from all fragments into buffer */ + CurrentEntry = IPDR->FragmentListHead.Flink; + while (CurrentEntry != &IPDR->FragmentListHead) { + Current = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry); + + TI_DbgPrint(DEBUG_IP, ("Copying (%d) bytes of fragment data from (0x%X) to offset (%d).\n", + Current->Size, Data, Current->Offset)); + /* Copy fragment data to the destination buffer at the correct offset */ + RtlCopyMemory( + (PVOID)((ULONG_PTR)Data + Current->Offset), + Current->Data, + Current->Size); + + CurrentEntry = CurrentEntry->Flink; + } + + return IPPacket; +} + + +__inline VOID Cleanup( + PKSPIN_LOCK Lock, + KIRQL OldIrql, + PIPDATAGRAM_REASSEMBLY IPDR, + PVOID Buffer OPTIONAL) +/* + * FUNCTION: Performs cleaning operations on errors + * ARGUMENTS: + * Lock = Pointer to spin lock to be released + * OldIrql = Value of IRQL when spin lock was acquired + * IPDR = Pointer to IP datagram reassembly structure to free + * Buffer = Optional pointer to a buffer to free + */ +{ + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + + KeReleaseSpinLock(Lock, OldIrql); + RemoveIPDR(IPDR); + FreeIPDR(IPDR); + if (Buffer) + ExFreePool(Buffer); +} + + +VOID ProcessFragment( + PIP_INTERFACE IF, + PIP_PACKET IPPacket, + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Processes an IP datagram or fragment + * ARGUMENTS: + * IF = Pointer to IP interface packet was receive on + * IPPacket = Pointer to IP packet + * NTE = Pointer to NTE packet was received on + * NOTES: + * This routine reassembles fragments and, if a whole datagram can + * be assembled, passes the datagram on to the IP protocol dispatcher + */ +{ + KIRQL OldIrql; + PIPDATAGRAM_REASSEMBLY IPDR; + PLIST_ENTRY CurrentEntry; + PIPDATAGRAM_HOLE Hole, NewHole; + USHORT FragFirst; + USHORT FragLast; + BOOLEAN MoreFragments; + PIPv4_HEADER IPv4Header; + PIP_PACKET Datagram; + PIP_FRAGMENT Fragment; + + /* FIXME: Assume IPv4 */ + + IPv4Header = (PIPv4_HEADER)IPPacket->Header; + + /* Check if we already have an reassembly structure for this datagram */ + IPDR = GetReassemblyInfo(IPPacket); + if (IPDR) { + TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n")); + /* We have a reassembly structure */ + KeAcquireSpinLock(&IPDR->Lock, &OldIrql); + CurrentEntry = IPDR->HoleListHead.Flink; + Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry); + } else { + TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n")); + + /* We don't have a reassembly structure, create one */ + IPDR = ExAllocateFromNPagedLookasideList(&IPDRList); + if (!IPDR) + /* We don't have the resources to process this packet, discard it */ + return; + + /* Create a descriptor spanning from zero to infinity. + Actually, we use a value slightly greater than the + maximum number of octets an IP datagram can contain */ + Hole = CreateHoleDescriptor(0, 65536); + if (!Hole) { + /* We don't have the resources to process this packet, discard it */ + ExFreeToNPagedLookasideList(&IPDRList, IPDR); + return; + } + AddrInitIPv4(&IPDR->SrcAddr, IPv4Header->SrcAddr); + AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr); + IPDR->Id = IPv4Header->Id; + IPDR->Protocol = IPv4Header->Protocol; + IPDR->IPv4Header = NULL; + InitializeListHead(&IPDR->FragmentListHead); + InitializeListHead(&IPDR->HoleListHead); + InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry); + CurrentEntry = IPDR->HoleListHead.Flink; + + KeInitializeSpinLock(&IPDR->Lock); + + KeAcquireSpinLock(&IPDR->Lock, &OldIrql); + + /* Update the reassembly list */ + ExInterlockedInsertTailList( + &ReassemblyListHead, + &IPDR->ListEntry, + &ReassemblyListLock); + } + + FragFirst = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_FRAGOFS_MASK) << 3; + FragLast = FragFirst + WN2H(IPv4Header->TotalLength); + MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0; + + for (;;) { + if (CurrentEntry == &IPDR->HoleListHead) + /* No more entries */ + break; + + TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n", + FragFirst, FragLast, Hole->First, Hole->Last)); + + if ((FragFirst > Hole->Last) || (FragLast < Hole->First)) { + TI_DbgPrint(MID_TRACE, ("No overlap.\n")); + /* The fragment does not overlap with the hole, try next + descriptor in the list */ + + CurrentEntry = CurrentEntry->Flink; + if (CurrentEntry != &IPDR->HoleListHead) + Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry); + continue; + } + + /* The fragment overlap with the hole, unlink the descriptor */ + RemoveEntryList(CurrentEntry); + + if (FragFirst > Hole->First) { + NewHole = CreateHoleDescriptor(Hole->First, FragLast - 1); + if (!NewHole) { + /* We don't have the resources to process this packet, discard it */ + Cleanup(&IPDR->Lock, OldIrql, IPDR, Hole); + return; + } + + /* Put the new descriptor in the list */ + InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry); + } + + if ((FragLast < Hole->Last) && (MoreFragments)) { + /* We can reuse the descriptor for the new hole */ + Hole->First = FragLast + 1; + + /* Put the new hole descriptor in the list */ + InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry); + } else + ExFreeToNPagedLookasideList(&IPHoleList, Hole); + + /* If this is the first fragment, save the IP header */ + if (FragFirst == 0) { + IPDR->IPv4Header = ExAllocatePool(NonPagedPool, IPPacket->HeaderSize); + if (!IPDR->IPv4Header) { + /* We don't have the resources to process this packet, discard it */ + Cleanup(&IPDR->Lock, OldIrql, IPDR, NULL); + return; + } + + TI_DbgPrint(DEBUG_IP, ("First fragment found. Header buffer is at (0x%X). " + "Header size is (%d).\n", IPDR->IPv4Header, IPPacket->HeaderSize)); + + RtlCopyMemory(IPDR->IPv4Header, IPPacket->Header, IPPacket->HeaderSize); + IPDR->HeaderSize = IPPacket->HeaderSize; + } + + /* Create a buffer, copy the data into it and put it + in the fragment list */ + + Fragment = ExAllocateFromNPagedLookasideList(&IPFragmentList); + if (!Fragment) { + /* We don't have the resources to process this packet, discard it */ + Cleanup(&IPDR->Lock, OldIrql, IPDR, NULL); + return; + } + + TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment)); + + Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize; + Fragment->Data = ExAllocatePool(NonPagedPool, Fragment->Size); + if (!Fragment->Data) { + /* We don't have the resources to process this packet, discard it */ + Cleanup(&IPDR->Lock, OldIrql, IPDR, Fragment); + return; + } + + TI_DbgPrint(DEBUG_IP, ("Fragment data buffer allocated at (0x%X) Size (%d).\n", + Fragment->Data, Fragment->Size)); + + /* Copy datagram data into fragment buffer */ + CopyPacketToBuffer( + Fragment->Data, + IPPacket->NdisPacket, + IPPacket->Position, + Fragment->Size); + Fragment->Offset = FragFirst; + + /* If this is the last fragment, compute and save the datagram data size */ + if (!MoreFragments) + IPDR->DataSize = FragFirst + Fragment->Size; + + /* Put the fragment in the list */ + InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry); + break; + } + + TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n")); + + if (IsListEmpty(&IPDR->HoleListHead)) { + /* Hole list is empty which means a complete datagram can be assembled. + Assemble the datagram and pass it to an upper layer protocol */ + + TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n")); + + Datagram = ReassembleDatagram(IPDR); + + KeReleaseSpinLock(&IPDR->Lock, OldIrql); + + RemoveIPDR(IPDR); + FreeIPDR(IPDR); + + if (!Datagram) + /* Not enough free resources, discard the packet */ + return; + + DISPLAY_IP_PACKET(Datagram); + + /* Give the packet to the protocol dispatcher */ + IPDispatchProtocol(NTE, Datagram); + + /* We're done with this datagram */ + ExFreePool(Datagram->Header); + TI_DbgPrint(MAX_TRACE, ("Freeing datagram at (0x%X).\n", Datagram)); + (*Datagram->Free)(Datagram); + } else + KeReleaseSpinLock(&IPDR->Lock, OldIrql); +} + + +VOID IPFreeReassemblyList( + VOID) +/* + * FUNCTION: Frees all IP datagram reassembly structures in the list + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PIPDATAGRAM_REASSEMBLY Current; + + KeAcquireSpinLock(&ReassemblyListLock, &OldIrql); + + CurrentEntry = ReassemblyListHead.Flink; + while (CurrentEntry != &ReassemblyListHead) { + Current = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry); + /* Unlink it from the list */ + RemoveEntryList(CurrentEntry); + + /* And free the descriptor */ + FreeIPDR(Current); + + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&ReassemblyListLock, OldIrql); +} + + +VOID IPDatagramReassemblyTimeout( + VOID) +/* + * FUNCTION: IP datagram reassembly timeout handler + * NOTES: + * This routine is called by IPTimeout to free any resources used + * to hold IP fragments that have taken too long to reassemble + */ +{ +} + + +VOID IPv4Receive( + PVOID Context, + PIP_PACKET IPPacket) +/* + * FUNCTION: Receives an IPv4 datagram (or fragment) + * ARGUMENTS: + * Context = Pointer to context information (IP_INTERFACE) + * IPPacket = Pointer to IP packet + */ +{ +//PNEIGHBOR_CACHE_ENTRY NCE; + PNET_TABLE_ENTRY NTE; + UINT AddressType; + + TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n")); + + IPPacket->HeaderSize = (((PIPv4_HEADER)IPPacket->Header)->VerIHL & 0x0F) << 2; + + if (IPPacket->HeaderSize > IPv4_MAX_HEADER_SIZE) { + TI_DbgPrint(MIN_TRACE, ("Datagram received with incorrect header size (%d).\n", + IPPacket->HeaderSize)); + /* Discard packet */ + return; + } + + /* Checksum IPv4 header */ + if (!CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) { + TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n", + WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum))); + /* Discard packet */ + return; + } + +// TI_DbgPrint(DEBUG_IP, ("TotalSize (datalink) is (%d).\n", IPPacket->TotalSize)); + + IPPacket->TotalSize = WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength); + +// TI_DbgPrint(DEBUG_IP, ("TotalSize (IPv4) is (%d).\n", IPPacket->TotalSize)); + + AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr); + AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr); + + IPPacket->Position = IPPacket->HeaderSize; + IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize); + + /* FIXME: Possibly forward packets with multicast addresses */ + + /* FIXME: Should we allow packets to be received on the wrong interface? */ +#if 0 + NTE = IPLocateNTE(&IPPacket->DstAddr, &AddressType); +#else + NTE = IPLocateNTEOnInterface((PIP_INTERFACE)Context, &IPPacket->DstAddr, &AddressType); +#endif + if (NTE) { + /* This packet is destined for us */ + ProcessFragment((PIP_INTERFACE)Context, IPPacket, NTE); + + /* Done with this NTE */ + DereferenceObject(NTE); + } else { + /* This packet is not destined for us. If we are a router, + try to find a route and forward the packet */ + + /* FIXME: Check if acting as a router */ +#if 0 + NCE = RouteFindRouter(&IPPacket->DstAddr, NULL); + if (NCE) { + /* FIXME: Possibly fragment datagram */ + /* Forward the packet */ + IPSendFragment(IPPacket, NCE); + } else { + TI_DbgPrint(MIN_TRACE, ("No route to destination (0x%X).\n", + IPPacket->DstAddr.Address.IPv4Address)); + + /* FIXME: Send ICMP error code */ + } +#endif + } +} + + +VOID IPReceive( + PVOID Context, + PIP_PACKET IPPacket) +/* + * FUNCTION: Receives an IP datagram (or fragment) + * ARGUMENTS: + * Context = Pointer to context information (IP_INTERFACE) + * IPPacket = Pointer to IP packet + */ +{ + UINT Version; + + /* Check that IP header has a supported version */ + Version = (((PIPv4_HEADER)IPPacket->Header)->VerIHL >> 4); + + switch (Version) { + case 4: + IPPacket->Type = IP_ADDRESS_V4; + IPv4Receive(Context, IPPacket); + break; + case 6: + IPPacket->Type = IP_ADDRESS_V6; + TI_DbgPrint(MAX_TRACE, ("Datagram of type IPv6 discarded.\n")); + return; + default: + TI_DbgPrint(MIN_TRACE, ("Datagram has an unsupported IP version %d.\n", Version)); + return; + } +} + +/* EOF */ diff --git a/drivers/net/tcpip/network/route.c b/drivers/net/tcpip/network/route.c new file mode 100644 index 0000000..e980f44 --- /dev/null +++ b/drivers/net/tcpip/network/route.c @@ -0,0 +1,702 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/route.c + * PURPOSE: Route cache + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: The route cache is implemented as a binary search + * tree to obtain fast searches + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include + + +/* This RCN is shared by all external nodes. It complicates things, + but the memory requirements are reduced by approximately 50%. + The RCN is protected by the route cache spin lock */ +PROUTE_CACHE_NODE ExternalRCN; +PROUTE_CACHE_NODE RouteCache; +KSPIN_LOCK RouteCacheLock; +NPAGED_LOOKASIDE_LIST IPRCNList; + + +#if DBG +VOID PrintTree( + PROUTE_CACHE_NODE Node) +/* + * FUNCTION: Prints all nodes on tree + * ARGUMENTS: + * Node = Pointer to root node of tree + * NOTES: + * This function must be called with the route cache lock held. + */ +{ + if (IsInternalRCN(Node)) { + /* Traverse left subtree */ + PrintTree(Node->Left); + + /* Traverse right subtree */ + PrintTree(Node->Right); + + /* Finally check the node itself */ + TI_DbgPrint(MIN_TRACE, ("(Internal) Self,Parent,Left,Right,Data = (%08X, %08X, %08X, %08X, %08X).\n", + Node, Node->Parent, Node->Left, Node->Right, (ULONG_PTR)Node->Destination.Address.IPv4Address)); + } else + TI_DbgPrint(MIN_TRACE, ("(External) Self,Parent,Left,Right = (%08X, %08X, %08X, %08X).\n", + Node, Node->Parent, Node->Left, Node->Right)); +} +#endif + + +VOID FreeRCN( + PVOID Object) +/* + * FUNCTION: Frees an route cache node object + * ARGUMENTS: + * Object = Pointer to an route cache node structure + */ +{ + ExFreeToNPagedLookasideList(&IPRCNList, Object); +} + + +VOID RemoveAboveExternal(VOID) +/* + * FUNCTION: Removes the parent node of the selected external node from the route cache tree + * NOTES: + * This function must be called with the route cache lock held. + * ExternalRCN->Parent must be initialized + */ +{ + PROUTE_CACHE_NODE Parent; + PROUTE_CACHE_NODE Sibling; + + TI_DbgPrint(DEBUG_RCACHE, ("Called.\n")); + +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree (before).\n")); + PrintTree(RouteCache); +#endif + + Parent = ExternalRCN->Parent; + /* Find sibling of external node */ + if (ExternalRCN == Parent->Left) + Sibling = Parent->Right; + else + Sibling = Parent->Left; + + /* Replace parent node with sibling of external node */ + if (Parent != RouteCache) { + if (Parent->Parent->Left == Parent) + Parent->Parent->Left = Sibling; + else + Parent->Parent->Right = Sibling; + /* Give sibling a new parent */ + Sibling->Parent = Parent->Parent; + } else { + /* This is the root we're removing */ + RouteCache = Sibling; + Sibling->Parent = NULL; + } + + DereferenceObject(Parent); + +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree (after).\n")); + PrintTree(RouteCache); +#endif +} + + +PROUTE_CACHE_NODE SearchRouteCache( + PIP_ADDRESS Destination, + PROUTE_CACHE_NODE Node) +/* + * FUNCTION: Searches route cache for a RCN for a destination address + * ARGUMENTS: + * Destination = Pointer to destination address (key) + * Node = Pointer to start route cache node + * NOTES: + * This function must be called with the route cache lock held + * RETURNS: + * Pointer to internal node if a matching node was found, or + * external node where it should be if none was found + */ +{ + INT Value; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X) Node (0x%X)\n", Destination, Node)); + + /* Is this an external node? */ + if (IsExternalRCN(Node)) + return Node; + + /* Is it this node we are looking for? */ + Value = AddrCompare(Destination, &Node->Destination); + if (Value == 0) + return Node; + + /* Traverse down the left subtree if the key is smaller than + the key of the node, otherwise traverse the right subtree */ + if (Value < 0) { + Node->Left->Parent = Node; + ExternalRCN->Left = (PROUTE_CACHE_NODE)&Node->Left; + return SearchRouteCache(Destination, Node->Left); + } else { + Node->Right->Parent = Node; + ExternalRCN->Left = (PROUTE_CACHE_NODE)&Node->Right; + return SearchRouteCache(Destination, Node->Right); + } +} + + +PROUTE_CACHE_NODE ExpandExternalRCN(VOID) +/* + * FUNCTION: Expands an external route cache node + * NOTES: + * This function must be called with the route cache lock held. + * We cheat a little here to save memory. We don't actually allocate memory + * for external nodes. We wait until they're turned into internal nodes. + * ExternalRCN->Parent must be initialized + * ExternalRCN->Left must be a pointer to the correct child link of it's parent + * RETURNS: + * Pointer to new internal node if the external node was expanded, NULL if not + */ +{ + PROUTE_CACHE_NODE RCN; + + TI_DbgPrint(DEBUG_RCACHE, ("Called.\n")); + + RCN = ExAllocateFromNPagedLookasideList(&IPRCNList); + if (!RCN) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + RCN->Free = FreeRCN; + + if (ExternalRCN->Left) + /* Register RCN as a child with it's parent */ + *(PROUTE_CACHE_NODE*)ExternalRCN->Left = RCN; + + RCN->Parent = ExternalRCN->Parent; + RCN->Left = ExternalRCN; + RCN->Right = ExternalRCN; + + return RCN; +} + +#if 0 +VOID SwapRCN( + PROUTE_CACHE_NODE *Node1, + PROUTE_CACHE_NODE *Node2) +/* + * FUNCTION: Swaps two nodes + * ARGUMENTS: + * Node1 = Address of pointer to first node + * Node2 = Address of pointer to second node + */ +{ + PROUTE_CACHE_NODE Temp; + + Temp = *Node2; + *Node2 = *Node1; + *Node1 = Temp; +} +#endif + +/* + * FUNCTION: Removes a route to a destination + * ARGUMENTS: + * RCN = Pointer to route cache node to remove + * NOTES: + * Internal version. Route cache lock must be held + */ +VOID RemoveRouteToDestination( + PROUTE_CACHE_NODE RCN) +{ + PROUTE_CACHE_NODE RemNode, Parent, SwapNode; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. RCN (0x%X).\n", RCN)); + + if (IsExternalRCN(RCN->Left)) { + /* Left node is external */ + RemNode = RCN->Left; + RemNode->Parent = RCN; + } else if (IsExternalRCN(RCN->Right)) { + /* Right node is external */ + RemNode = RCN->Right; + RemNode->Parent = RCN; + } else { + /* The node has internal children */ + + /* Normally we would replace the item of RCN with the item + of the leftmost external node on the right subtree of + RCN. This we cannot do here because there may be + references directly to that node. Instead we swap pointer + values (parent, left and right) of the two nodes */ + RemNode = RCN->Right; + do { + Parent = RemNode; + RemNode = RemNode->Left; + } while (IsInternalRCN(RemNode)); + RemNode->Parent = Parent; + + SwapNode = RemNode->Parent; +#if 0 + if (RCN != RouteCache) { + /* Set SwapNode to be child of RCN's parent instead of RCN */ + Parent = RCN->Parent; + if (RCN == Parent->Left) + Parent->Left = SwapNode; + else + Parent->Right = SwapNode; + } else + /* SwapNode is the new cache root */ + RouteCache = SwapNode; + + /* Set RCN to be child of SwapNode's parent instead of SwapNode */ + Parent = SwapNode->Parent; + if (SwapNode == Parent->Left) + Parent->Left = RCN; + else + Parent->Right = RCN; + + /* Swap parents */ + SwapRCN(&SwapNode->Parent, &RCN->Parent); + /* Swap children */ + SwapRCN(&SwapNode->Left, &RCN->Left); + SwapRCN(&SwapNode->Right, &RCN->Right); +#endif + } + + /* Dereference NTE and NCE */ + DereferenceObject(RCN->NTE); + DereferenceObject(RCN->NCE); + + ExternalRCN->Parent = RemNode->Parent; + + RemoveAboveExternal(); +} + + +VOID InvalidateNTEOnSubtree( + PNET_TABLE_ENTRY NTE, + PROUTE_CACHE_NODE Node) +/* + * FUNCTION: Removes all RCNs with references to an NTE on a subtree + * ARGUMENNTS: + * NTE = Pointer to NTE to invalidate + * Node = Pointer to RCN to start removing nodes at + * NOTES: + * This function must be called with the route cache lock held. + */ +{ + TI_DbgPrint(DEBUG_RCACHE, ("Called. NTE (0x%X) Node (0x%X).\n", NTE, Node)); + + if (IsInternalRCN(Node)) { + /* Traverse left subtree */ + InvalidateNTEOnSubtree(NTE, Node->Left); + + /* Traverse right subtree */ + InvalidateNTEOnSubtree(NTE, Node->Right); + + /* Finally check the node itself */ + if (Node->NTE == NTE) + RemoveRouteToDestination(Node); + } +} + + +VOID InvalidateNCEOnSubtree( + PNEIGHBOR_CACHE_ENTRY NCE, + PROUTE_CACHE_NODE Node) +/* + * FUNCTION: Removes all RCNs with references to an NCE on a subtree + * ARGUMENNTS: + * NCE = Pointer to NCE to invalidate + * Node = Pointer to RCN to start removing nodes at + * NOTES: + * This function must be called with the route cache lock held + */ +{ + TI_DbgPrint(DEBUG_RCACHE, ("Called. NCE (0x%X) Node (0x%X).\n", NCE, Node)); + + if (IsInternalRCN(Node)) { + /* Traverse left subtree */ + InvalidateNCEOnSubtree(NCE, Node->Left); + + /* Traverse right subtree */ + InvalidateNCEOnSubtree(NCE, Node->Right); + + /* Finally check the node itself */ + if (Node->NCE == NCE) + RemoveRouteToDestination(Node); + } +} + + +VOID RemoveSubtree( + PROUTE_CACHE_NODE Node) +/* + * FUNCTION: Removes a subtree from the tree using recursion + * ARGUMENNTS: + * Node = Pointer to RCN to start removing nodes at + * NOTES: + * This function must be called with the route cache lock held + */ +{ + TI_DbgPrint(DEBUG_RCACHE, ("Called. Node (0x%X).\n", Node)); + + if (IsInternalRCN(Node)) { + /* Traverse left subtree */ + RemoveSubtree(Node->Left); + + /* Traverse right subtree */ + RemoveSubtree(Node->Right); + + /* Finally remove the node itself */ + + /* It's an internal node, so dereference NTE and NCE */ + DereferenceObject(Node->NTE); + DereferenceObject(Node->NCE); + +#if DBG + if (Node->RefCount != 1) + TI_DbgPrint(MIN_TRACE, ("RCN at (0x%X) has (%d) references (should be 1).\n", Node, Node->RefCount)); +#endif + + /* Remove reference for being alive */ + DereferenceObject(Node); + } +} + + +NTSTATUS RouteStartup( + VOID) +/* + * FUNCTION: Initializes the routing subsystem + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_RCACHE, ("Called.\n")); + + ExInitializeNPagedLookasideList( + &IPRCNList, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(ROUTE_CACHE_NODE), /* Size of each entry */ + TAG('I','P','R','C'), /* Tag */ + 0); /* Depth */ + + /* Initialize the pseudo external route cache node */ + ExternalRCN = ExAllocateFromNPagedLookasideList(&IPRCNList); + if (!ExternalRCN) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + INIT_TAG(ExternalRCN, TAG('R','C','N',' ')); + + ExternalRCN->Free = FreeRCN; + ExternalRCN->Parent = NULL; + ExternalRCN->Left = NULL; + ExternalRCN->Right = NULL; + + /* Initialize the route cache root */ + RouteCache = ExternalRCN; + + KeInitializeSpinLock(&RouteCacheLock); + +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree.\n")); + PrintTree(RouteCache); +#endif + return STATUS_SUCCESS; +} + + +NTSTATUS RouteShutdown( + VOID) +/* + * FUNCTION: Shuts down the routing subsystem + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_RCACHE, ("Called.\n")); + + KeAcquireSpinLock(&RouteCacheLock, &OldIrql); +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree.\n")); + PrintTree(RouteCache); +#endif + /* Clear route cache */ + RemoveSubtree(RouteCache); + + FreeRCN(ExternalRCN); + + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + + ExDeleteNPagedLookasideList(&IPRCNList); + + return STATUS_SUCCESS; +} + + +UINT RouteGetRouteToDestination( + PIP_ADDRESS Destination, + PNET_TABLE_ENTRY NTE, + PROUTE_CACHE_NODE *RCN) +/* + * FUNCTION: Locates an RCN describing a route to a destination address + * ARGUMENTS: + * Destination = Pointer to destination address to find route to + * NTE = Pointer to NTE describing net to send on + * (NULL means routing module choose NTE to send on) + * RCN = Address of pointer to an RCN + * RETURNS: + * Status of operation + * NOTES: + * The RCN is referenced for the caller. The caller is responsible + * for dereferencing it after use + */ +{ + KIRQL OldIrql; + PROUTE_CACHE_NODE RCN2; + PNEIGHBOR_CACHE_ENTRY NCE; + PIP_INTERFACE Interface; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X) NTE (0x%X).\n", + Destination, NTE)); + + TI_DbgPrint(DEBUG_RCACHE, ("Destination (%s) NTE (%s).\n", + A2S(Destination), A2S(NTE->Address))); + + KeAcquireSpinLock(&RouteCacheLock, &OldIrql); + +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree (before).\n")); + PrintTree(RouteCache); +#endif + + ExternalRCN->Left = NULL; + RCN2 = SearchRouteCache(Destination, RouteCache); + if (IsExternalRCN(RCN2)) { + /* No route was found in the cache */ + + /* Check if the destination is on-link */ + Interface = RouterFindOnLinkInterface(Destination, NTE); + if (Interface) { + if (!NTE) { + NTE = RouterFindBestNTE(Interface, Destination); + if (!NTE) { + /* We cannot get to the specified destination. Return error */ + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + return IP_NO_ROUTE_TO_DESTINATION; + } + } else + ReferenceObject(NTE); + + /* The destination address is on-link. Check our neighbor cache */ + NCE = NBFindOrCreateNeighbor(Interface, Destination); + if (!NCE) { + DereferenceObject(NTE); + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + return IP_NO_RESOURCES; + } + } else { + /* Destination is not on any subnets we're on. Find a router to use */ + NCE = RouterGetRoute(Destination, NTE); + if (!NCE) { + /* We cannot get to the specified destination. Return error */ + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + return IP_NO_ROUTE_TO_DESTINATION; + } + } + + /* Add the new route to the route cache */ + if (RCN2 == RouteCache) { + RCN2 = ExpandExternalRCN(); + RouteCache = RCN2; + } else + RCN2 = ExpandExternalRCN(); + if (!RCN2) { + DereferenceObject(NTE); + DereferenceObject(NCE); + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + return IP_NO_RESOURCES; + } + + RCN2->RefCount = 1; + RCN2->State = RCN_STATE_COMPUTED; + RCN2->NTE = NTE; + RtlCopyMemory(&RCN2->Destination, Destination, sizeof(IP_ADDRESS)); + RCN2->PathMTU = NCE->Interface->MTU; + RCN2->NCE = NCE; + + /* The route cache node references the NTE and the NCE. The + NTE was referenced before and NCE is already referenced by + RouteGetRoute() or NBFindOrCreateNeighbor() so we don't + reference them here */ + } + + /* Reference the RCN for the user */ + ReferenceObject(RCN2); + +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree (after).\n")); + PrintTree(RouteCache); +#endif + + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + + *RCN = RCN2; + + return IP_SUCCESS; +} + + +PROUTE_CACHE_NODE RouteAddRouteToDestination( + PIP_ADDRESS Destination, + PNET_TABLE_ENTRY NTE, + PIP_INTERFACE IF, + PNEIGHBOR_CACHE_ENTRY NCE) +/* + * FUNCTION: Adds a (permanent) route to a destination + * ARGUMENTS: + * Destination = Pointer to destination address + * NTE = Pointer to net table entry + * IF = Pointer to interface to use + * NCE = Pointer to first hop to destination + * RETURNS: + * Pointer to RCN if the route was added, NULL if not. + * There can be at most one RCN per destination address / interface pair + */ +{ + KIRQL OldIrql; + PROUTE_CACHE_NODE RCN; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. Destination (0x%X) NTE (0x%X) IF (0x%X) NCE (0x%X).\n", + Destination, NTE, IF, NCE)); + + TI_DbgPrint(DEBUG_RCACHE, ("Destination (%s) NTE (%s) NCE (%s).\n", + A2S(Destination), A2S(NTE->Address), A2S(NCE->Address))); + + KeAcquireSpinLock(&RouteCacheLock, &OldIrql); + + /* Locate an external RCN we can expand */ + RCN = RouteCache; + ExternalRCN->Left = NULL; + for (;;) { + RCN = SearchRouteCache(Destination, RCN); + if (IsInternalRCN(RCN)) { + ExternalRCN->Left = (PROUTE_CACHE_NODE)&RCN->Right; + /* This is an internal node, continue the search to the right */ + RCN = RCN->Right; + } else + /* This is an external node, we've found an empty spot */ + break; + } + + /* Expand the external node */ + if (RCN == RouteCache) { + RCN = ExpandExternalRCN(); + RouteCache = RCN; + } else + RCN = ExpandExternalRCN(); + if (!RCN) { + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + return NULL; + } + + /* Initialize the newly created internal node */ + + INIT_TAG(RCN, TAG('R','C','N',' ')); + + /* Reference once for beeing alive */ + RCN->RefCount = 1; + RCN->State = RCN_STATE_PERMANENT; + RCN->NTE = NTE; + RtlCopyMemory(&RCN->Destination, Destination, sizeof(IP_ADDRESS)); + RCN->PathMTU = IF->MTU; + RCN->NCE = NCE; + + KeReleaseSpinLock(&RouteCacheLock, OldIrql); + + /* The route cache node references the NTE and the NCE */ + ReferenceObject(NTE); + if (NCE) + ReferenceObject(NCE); + +#if 0 + TI_DbgPrint(MIN_TRACE, ("Displaying tree.\n")); + PrintTree(RouteCache); +#endif + + return RCN; +} + + +VOID RouteRemoveRouteToDestination( + PROUTE_CACHE_NODE RCN) +/* + * FUNCTION: Removes a route to a destination + * ARGUMENTS: + * RCN = Pointer to route cache node to remove + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. RCN (0x%X).\n", RCN)); + + KeAcquireSpinLock(&RouteCacheLock, &OldIrql); + + RemoveRouteToDestination(RCN); + + KeReleaseSpinLock(&RouteCacheLock, OldIrql); +} + + +VOID RouteInvalidateNTE( + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Removes all RCNs with references to an NTE + * ARGUMENTS: + * NTE = Pointer to net table entry to invalidate + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. NTE (0x%X).\n", NTE)); + + KeAcquireSpinLock(&RouteCacheLock, &OldIrql); + InvalidateNTEOnSubtree(NTE, RouteCache); + KeReleaseSpinLock(&RouteCacheLock, OldIrql); +} + + +VOID RouteInvalidateNCE( + PNEIGHBOR_CACHE_ENTRY NCE) +/* + * FUNCTION: Removes all RCNs with references to an NCE + * ARGUMENTS: + * NCE = Pointer to neighbor cache entry to invalidate + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_RCACHE, ("Called. NCE (0x%X).\n", NCE)); + + KeAcquireSpinLock(&RouteCacheLock, &OldIrql); + InvalidateNCEOnSubtree(NCE, RouteCache); + KeReleaseSpinLock(&RouteCacheLock, OldIrql); +} + +/* EOF */ diff --git a/drivers/net/tcpip/network/router.c b/drivers/net/tcpip/network/router.c new file mode 100644 index 0000000..5ea1d28 --- /dev/null +++ b/drivers/net/tcpip/network/router.c @@ -0,0 +1,541 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/router.c + * PURPOSE: IP routing subsystem + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include + + +LIST_ENTRY FIBListHead; +KSPIN_LOCK FIBLock; + + +VOID FreeFIB( + PVOID Object) +/* + * FUNCTION: Frees an forward information base object + * ARGUMENTS: + * Object = Pointer to an forward information base structure + */ +{ + ExFreePool(Object); +} + + +VOID DestroyFIBE( + PFIB_ENTRY FIBE) +/* + * FUNCTION: Destroys an forward information base entry + * ARGUMENTS: + * FIBE = Pointer to FIB entry + * NOTES: + * The forward information base lock must be held when called + */ +{ + TI_DbgPrint(DEBUG_ROUTER, ("Called. FIBE (0x%X).\n", FIBE)); + + /* Unlink the FIB entry from the list */ + RemoveEntryList(&FIBE->ListEntry); + + /* Dereference the referenced objects */ + DereferenceObject(FIBE->NetworkAddress); + DereferenceObject(FIBE->Netmask); + DereferenceObject(FIBE->Router); + DereferenceObject(FIBE->NTE); + +#ifdef DBG + FIBE->RefCount--; + + if (FIBE->RefCount != 0) { + TI_DbgPrint(MIN_TRACE, ("FIB entry at (0x%X) has (%d) references (Should be 0).\n", FIBE, FIBE->RefCount)); + } +#endif + + /* And free the FIB entry */ + FreeFIB(FIBE); +} + + +VOID DestroyFIBEs( + VOID) +/* + * FUNCTION: Destroys all forward information base entries + * NOTES: + * The forward information base lock must be held when called + */ +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PFIB_ENTRY Current; + + /* Search the list and remove every FIB entry we find */ + CurrentEntry = FIBListHead.Flink; + while (CurrentEntry != &FIBListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry); + /* Destroy the FIB entry */ + DestroyFIBE(Current); + CurrentEntry = NextEntry; + } +} + + +UINT CommonPrefixLength( + PIP_ADDRESS Address1, + PIP_ADDRESS Address2) +/* + * FUNCTION: Computes the length of the longest prefix common to two addresses + * ARGUMENTS: + * Address1 = Pointer to first address + * Address2 = Pointer to second address + * NOTES: + * The two addresses must be of the same type + * RETURNS: + * Length of longest common prefix + */ +{ + PUCHAR Addr1, Addr2; + UINT Size; + UINT i, j; + UINT Bitmask; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. Address1 (0x%X) Address2 (0x%X).\n", Address1, Address2)); + + TI_DbgPrint(DEBUG_ROUTER, ("Address1 (%s) Address2 (%s).\n", + A2S(Address1), A2S(Address2))); + + if (Address1->Type == IP_ADDRESS_V4) + Size = sizeof(IPv4_RAW_ADDRESS); + else + Size = sizeof(IPv6_RAW_ADDRESS); + + Addr1 = (PUCHAR)&Address1->Address; + Addr2 = (PUCHAR)&Address2->Address; + + /* Find first non-matching byte */ + for (i = 0; ; i++) { + if (i == Size) + return 8 * i; /* The two addresses are equal */ + + if (Addr1[i] != Addr2[i]) + break; + } + + /* Find first non-matching bit */ + Bitmask = 0x80; + for (j = 0; ; j++) { + if ((Addr1[i] & Bitmask) != (Addr2[i] & Bitmask)) + break; + Bitmask >>= 1; + } + + return 8 * i + j; +} + + +BOOLEAN HasPrefix( + PIP_ADDRESS Address, + PIP_ADDRESS Prefix, + UINT Length) +/* + * FUNCTION: Determines wether an address has an given prefix + * ARGUMENTS: + * Address = Pointer to address to use + * Prefix = Pointer to prefix to check for + * Length = Length of prefix + * RETURNS: + * TRUE if the address has the prefix, FALSE if not + * NOTES: + * The two addresses must be of the same type + */ +{ + PUCHAR pAddress = (PUCHAR)&Address->Address; + PUCHAR pPrefix = (PUCHAR)&Prefix->Address; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) Prefix (0x%X) Length (%d).\n", Address, Prefix, Length)); + + TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) Prefix (%s).\n", + A2S(Address), A2S(Prefix))); + + /* Check that initial integral bytes match */ + while (Length > 8) { + if (*pAddress++ != *pPrefix++) + return FALSE; + Length -= 8; + } + + /* Check any remaining bits */ + if ((Length > 0) && ((*pAddress >> (8 - Length)) != (*pPrefix >> (8 - Length)))) + return FALSE; + + return TRUE; +} + + +PNET_TABLE_ENTRY RouterFindBestNTE( + PIP_INTERFACE Interface, + PIP_ADDRESS Destination) +/* + * FUNCTION: Checks all on-link prefixes to find out if an address is on-link + * ARGUMENTS: + * Interface = Pointer to interface to use + * Destination = Pointer to destination address + * NOTES: + * If found the NTE if referenced + * RETURNS: + * Pointer to NTE if found, NULL if not + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PNET_TABLE_ENTRY Current; + UINT Length, BestLength = 0; + PNET_TABLE_ENTRY BestNTE = NULL; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. Interface (0x%X) Destination (0x%X).\n", Interface, Destination)); + + TI_DbgPrint(DEBUG_ROUTER, ("Destination (%s).\n", A2S(Destination))); + + KeAcquireSpinLock(&Interface->Lock, &OldIrql); + + CurrentEntry = Interface->NTEListHead.Flink; + while (CurrentEntry != &Interface->NTEListHead) { + Current = CONTAINING_RECORD(CurrentEntry, NET_TABLE_ENTRY, IFListEntry); + + Length = CommonPrefixLength(Destination, Current->Address); + if (BestNTE) { + if (Length > BestLength) { + /* This seems to be a better NTE */ + DereferenceObject(BestNTE); + ReferenceObject(Current); + BestNTE = Current; + BestLength = Length; + } + } else { + /* First suitable NTE found, save it */ + ReferenceObject(Current); + BestNTE = Current; + BestLength = Length; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&Interface->Lock, OldIrql); + + return BestNTE; +} + + +PIP_INTERFACE RouterFindOnLinkInterface( + PIP_ADDRESS Address, + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Checks all on-link prefixes to find out if an address is on-link + * ARGUMENTS: + * Address = Pointer to address to check + * NTE = Pointer to NTE to check (NULL = check all interfaces) + * RETURNS: + * Pointer to interface if address is on-link, NULL if not + */ +{ + PLIST_ENTRY CurrentEntry; + PPREFIX_LIST_ENTRY Current; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. Address (0x%X) NTE (0x%X).\n", Address, NTE)); + + TI_DbgPrint(DEBUG_ROUTER, ("Address (%s) NTE (%s).\n", + A2S(Address), A2S(NTE->Address))); + + CurrentEntry = PrefixListHead.Flink; + while (CurrentEntry != &PrefixListHead) { + Current = CONTAINING_RECORD(CurrentEntry, PREFIX_LIST_ENTRY, ListEntry); + + if (HasPrefix(Address, Current->Prefix, Current->PrefixLength) && + ((!NTE) || (NTE->Interface == Current->Interface))) + return Current->Interface; + + CurrentEntry = CurrentEntry->Flink; + } + + return NULL; +} + + +PFIB_ENTRY RouterAddRoute( + PIP_ADDRESS NetworkAddress, + PIP_ADDRESS Netmask, + PNET_TABLE_ENTRY NTE, + PNEIGHBOR_CACHE_ENTRY Router, + UINT Metric) +/* + * FUNCTION: Adds a route to the Forward Information Base (FIB) + * ARGUMENTS: + * NetworkAddress = Pointer to address of network + * Netmask = Pointer to netmask of network + * NTE = Pointer to NTE to use + * Router = Pointer to NCE of router to use + * Metric = Cost of this route + * RETURNS: + * Pointer to FIB entry if the route was added, NULL if not + * NOTES: + * The FIB entry references the NetworkAddress, Netmask, NTE and + * the NCE of the router. The caller is responsible for providing + * these references + */ +{ + PFIB_ENTRY FIBE; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. NetworkAddress (0x%X) Netmask (0x%X) NTE (0x%X) " + "Router (0x%X) Metric (%d).\n", NetworkAddress, Netmask, NTE, Router, Metric)); + + TI_DbgPrint(DEBUG_ROUTER, ("NetworkAddress (%s) Netmask (%s) NTE (%s) Router (%s).\n", + A2S(NetworkAddress), A2S(Netmask), A2S(NTE->Address), A2S(Router->Address))); + + FIBE = ExAllocatePool(NonPagedPool, sizeof(FIB_ENTRY)); + if (!FIBE) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + INIT_TAG(NTE, TAG('N','T','E',' ')); + INIT_TAG(Router, TAG('R','O','U','T')); + + FIBE->Free = FreeFIB; + FIBE->NetworkAddress = NetworkAddress; + FIBE->Netmask = Netmask; + FIBE->NTE = NTE; + FIBE->Router = Router; + FIBE->Metric = Metric; + + /* Add FIB to the forward information base */ + ExInterlockedInsertTailList(&FIBListHead, &FIBE->ListEntry, &FIBLock); + + return FIBE; +} + + +PNEIGHBOR_CACHE_ENTRY RouterGetRoute( + PIP_ADDRESS Destination, + PNET_TABLE_ENTRY NTE) +/* + * FUNCTION: Finds a router to use to get to Destination + * ARGUMENTS: + * Destination = Pointer to destination address (NULL means don't care) + * NTE = Pointer to NTE describing net to send on + * (NULL means don't care) + * RETURNS: + * Pointer to NCE for router, NULL if none was found + * NOTES: + * If found the NCE is referenced + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PFIB_ENTRY Current; + UCHAR State, BestState = 0; + UINT Length, BestLength = 0; + PNEIGHBOR_CACHE_ENTRY NCE, BestNCE = NULL; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. Destination (0x%X) NTE (0x%X).\n", Destination, NTE)); + + TI_DbgPrint(DEBUG_ROUTER, ("Destination (%s) NTE (%s).\n", + A2S(Destination), A2S(NTE->Address))); + + KeAcquireSpinLock(&FIBLock, &OldIrql); + + CurrentEntry = FIBListHead.Flink; + while (CurrentEntry != &FIBListHead) { + NextEntry = CurrentEntry->Flink; + Current = CONTAINING_RECORD(CurrentEntry, FIB_ENTRY, ListEntry); + + NCE = Current->Router; + State = NCE->State; + + if ((!NTE) || (NTE->Interface == NCE->Interface)) { + if (Destination) + Length = CommonPrefixLength(Destination, NCE->Address); + else + Length = 0; + + if (BestNCE) { + if ((State > BestState) || + ((State == BestState) && + (Length > BestLength))) { + /* This seems to be a better router */ + DereferenceObject(BestNCE); + ReferenceObject(NCE); + BestNCE = NCE; + BestLength = Length; + BestState = State; + } + } else { + /* First suitable router found, save it */ + ReferenceObject(NCE); + BestNCE = NCE; + BestLength = Length; + BestState = State; + } + } + CurrentEntry = NextEntry; + } + + KeReleaseSpinLock(&FIBLock, OldIrql); + + return BestNCE; +} + + +VOID RouterRemoveRoute( + PFIB_ENTRY FIBE) +/* + * FUNCTION: Removes a route from the Forward Information Base (FIB) + * ARGUMENTS: + * FIBE = Pointer to FIB entry describing route + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_ROUTER, ("Called. FIBE (0x%X).\n", FIBE)); + + TI_DbgPrint(DEBUG_ROUTER, ("FIBE (%s).\n", A2S(FIBE->NetworkAddress))); + + KeAcquireSpinLock(&FIBLock, &OldIrql); + DestroyFIBE(FIBE); + KeReleaseSpinLock(&FIBLock, OldIrql); +} + + +PFIB_ENTRY RouterCreateRouteIPv4( + IPv4_RAW_ADDRESS NetworkAddress, + IPv4_RAW_ADDRESS Netmask, + IPv4_RAW_ADDRESS RouterAddress, + PNET_TABLE_ENTRY NTE, + UINT Metric) +/* + * FUNCTION: Creates a route with IPv4 addresses as parameters + * ARGUMENTS: + * NetworkAddress = Address of network + * Netmask = Netmask of network + * RouterAddress = Address of router to use + * NTE = Pointer to NTE to use + * Metric = Cost of this route + * RETURNS: + * Pointer to FIB entry if the route was created, NULL if not. + * The FIB entry references the NTE. The caller is responsible + * for providing this reference + */ +{ + PIP_ADDRESS pNetworkAddress; + PIP_ADDRESS pNetmask; + PIP_ADDRESS pRouterAddress; + PNEIGHBOR_CACHE_ENTRY NCE; + PFIB_ENTRY FIBE; + + pNetworkAddress = AddrBuildIPv4(NetworkAddress); + if (!pNetworkAddress) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return NULL; + } + + pNetmask = AddrBuildIPv4(Netmask); + if (!pNetmask) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + DereferenceObject(pNetworkAddress); + return NULL; + } + + pRouterAddress = AddrBuildIPv4(RouterAddress); + if (!pRouterAddress) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + DereferenceObject(pNetworkAddress); + DereferenceObject(pNetmask); + return NULL; + } + + /* The NCE references RouterAddress. The NCE is referenced for us */ + NCE = NBAddNeighbor(NTE->Interface, + pRouterAddress, + NULL, + NTE->Interface->AddressLength, + NUD_PROBE); + if (!NCE) { + /* Not enough free resources */ + DereferenceObject(pNetworkAddress); + DereferenceObject(pNetmask); + DereferenceObject(pRouterAddress); + return NULL; + } + + ReferenceObject(pNetworkAddress); + ReferenceObject(pNetmask); + FIBE = RouterAddRoute(pNetworkAddress, pNetmask, NTE, NCE, 1); + if (!FIBE) { + /* Not enough free resources */ + NBRemoveNeighbor(NCE); + DereferenceObject(pNetworkAddress); + DereferenceObject(pNetmask); + DereferenceObject(pRouterAddress); + + (pNetworkAddress->Free)(pNetworkAddress); + (pNetmask->Free)(pNetmask); + (pRouterAddress->Free)(pRouterAddress); + } + + return FIBE; +} + + +NTSTATUS RouterStartup( + VOID) +/* + * FUNCTION: Initializes the routing subsystem + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_ROUTER, ("Called.\n")); + + /* Initialize the Forward Information Base */ + InitializeListHead(&FIBListHead); + KeInitializeSpinLock(&FIBLock); + +#if 0 + /* TEST: Create a test route */ + /* Network is 10.0.0.0 */ + /* Netmask is 255.0.0.0 */ + /* Router is 10.0.0.1 */ + RouterCreateRouteIPv4(0x0000000A, 0x000000FF, 0x0100000A, NTE?, 1); +#endif + return STATUS_SUCCESS; +} + + +NTSTATUS RouterShutdown( + VOID) +/* + * FUNCTION: Shuts down the routing subsystem + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_ROUTER, ("Called.\n")); + + /* Clear Forward Information Base */ + KeAcquireSpinLock(&FIBLock, &OldIrql); + DestroyFIBEs(); + KeReleaseSpinLock(&FIBLock, OldIrql); + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/tcpip/network/transmit.c b/drivers/net/tcpip/network/transmit.c new file mode 100644 index 0000000..b650a54 --- /dev/null +++ b/drivers/net/tcpip/network/transmit.c @@ -0,0 +1,342 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: network/transmit.c + * PURPOSE: Internet Protocol transmit routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + + +BOOLEAN PrepareNextFragment( + PIPFRAGMENT_CONTEXT IFC) +/* + * FUNCTION: Prepares the next fragment of an IP datagram for transmission + * ARGUMENTS: + * IFC = Pointer to IP fragment context + * RETURNS: + * TRUE if a fragment was prepared for transmission, FALSE if + * there are no more fragments to send + */ +{ + UINT MaxData; + UINT DataSize; + PIPv4_HEADER Header; + BOOLEAN MoreFragments; + USHORT FragOfs; + + TI_DbgPrint(MAX_TRACE, ("Called. IFC (0x%X)\n", IFC)); + + if (IFC->BytesLeft != 0) { + + TI_DbgPrint(MAX_TRACE, ("Preparing 1 fragment.\n")); + + MaxData = IFC->PathMTU - IFC->HeaderSize; + /* Make fragment a multiplum of 64bit */ + MaxData -= MaxData % 8; + if (IFC->BytesLeft > MaxData) { + DataSize = MaxData; + MoreFragments = TRUE; + } else { + DataSize = IFC->BytesLeft; + MoreFragments = FALSE; + } + + RtlCopyMemory(IFC->Data, IFC->DatagramData, DataSize); + + FragOfs = (USHORT)IFC->Position; // Swap? + if (MoreFragments) + FragOfs |= IPv4_MF_MASK; + else + FragOfs &= ~IPv4_MF_MASK; + + Header = IFC->Header; + Header->FlagsFragOfs = FragOfs; + + /* FIXME: Handle options */ + + /* Calculate checksum of IP header */ + Header->Checksum = 0; + Header->Checksum = (USHORT)IPv4Checksum(Header, IFC->HeaderSize, 0); + + /* Update pointers */ + (ULONG_PTR)IFC->DatagramData += DataSize; + IFC->Position += DataSize; + IFC->BytesLeft -= DataSize; + + return TRUE; + } else { + TI_DbgPrint(MAX_TRACE, ("No more fragments.\n")); + return FALSE; + } +} + + +NTSTATUS SendFragments( + PIP_PACKET IPPacket, + PNEIGHBOR_CACHE_ENTRY NCE, + UINT PathMTU) +/* + * FUNCTION: Fragments and sends the first fragment of an IP datagram + * ARGUMENTS: + * IPPacket = Pointer to an IP packet + * NCE = Pointer to NCE for first hop to destination + * PathMTU = Size of Maximum Transmission Unit of path + * RETURNS: + * Status of operation + * NOTES: + * IP datagram is larger than PathMTU when this is called + */ +{ + PIPFRAGMENT_CONTEXT IFC; + NDIS_STATUS NdisStatus; + PVOID Data; + + TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) NCE (0x%X) PathMTU (%d).\n", + IPPacket, NCE, PathMTU)); + + IFC = ExAllocatePool(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT)); + if (!IFC) + return STATUS_INSUFFICIENT_RESOURCES; + + /* We allocate a buffer for a PathMTU sized packet and reuse + it for all fragments */ + Data = ExAllocatePool(NonPagedPool, MaxLLHeaderSize + PathMTU); + if (!IFC->Header) { + ExFreePool(IFC); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Allocate NDIS packet */ + NdisAllocatePacket(&NdisStatus, &IFC->NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + //ExFreePool(Data); // RobD - why are we trying to free this here?, not allocated yet! + ExFreePool(IFC); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Allocate NDIS buffer */ + NdisAllocateBuffer(&NdisStatus, &IFC->NdisBuffer, + GlobalBufferPool, Data, MaxLLHeaderSize + PathMTU); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + NdisFreePacket(IFC->NdisPacket); + ExFreePool(Data); + ExFreePool(IFC); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Link NDIS buffer into packet */ + NdisChainBufferAtFront(IFC->NdisPacket, IFC->NdisBuffer); + + IFC->Header = (PVOID)((ULONG_PTR)Data + MaxLLHeaderSize); + IFC->Datagram = IPPacket->NdisPacket; + IFC->DatagramData = IPPacket->Header; + IFC->HeaderSize = IPPacket->HeaderSize; + IFC->PathMTU = PathMTU; + IFC->NCE = NCE; + IFC->Position = 0; + IFC->BytesLeft = IPPacket->TotalSize - IPPacket->HeaderSize; + IFC->Data = (PVOID)((ULONG_PTR)IFC->Header + IPPacket->HeaderSize); + + PC(IFC->NdisPacket)->DLComplete = IPSendComplete; + /* Set upper layer completion function to NULL to indicate that + this packet is an IP datagram fragment and thus we should + check for more fragments to send. If this is NULL the + Context field is a pointer to an IPFRAGMENT_CONTEXT structure */ + PC(IFC->NdisPacket)->Complete = NULL; + PC(IFC->NdisPacket)->Context = IFC; + + /* Copy IP datagram header to fragment buffer */ + RtlCopyMemory(IFC->Header, IPPacket->Header, IPPacket->HeaderSize); + + /* Prepare next fragment for transmission and send it */ + + PrepareNextFragment(IFC); + + IPSendFragment(IFC->NdisPacket, NCE); + + return STATUS_SUCCESS; +} + + +VOID IPSendComplete( + PVOID Context, + PNDIS_PACKET NdisPacket, + NDIS_STATUS NdisStatus) +/* + * FUNCTION: IP datagram fragment send completion handler + * ARGUMENTS: + * Context = Pointer to context information (IP_INTERFACE) + * Packet = Pointer to NDIS packet that was sent + * NdisStatus = NDIS status of operation + * NOTES: + * This routine is called when an IP datagram fragment has been sent + */ +{ + TI_DbgPrint(MAX_TRACE, ("Called. Context (0x%X) NdisPacket (0x%X) NdisStatus (0x%X)\n", + Context, NdisPacket, NdisStatus)); + + /* FIXME: Stop sending fragments and cleanup datagram buffers if + there was an error */ + + if (PC(NdisPacket)->Complete) + /* This datagram was only one fragment long so call completion handler now */ + (*PC(NdisPacket)->Complete)(PC(NdisPacket)->Context, NdisPacket, NdisStatus); + else { + /* This was one of many fragments of an IP datagram. Prepare + next fragment and send it or if there are no more fragments, + call upper layer completion routine */ + + PIPFRAGMENT_CONTEXT IFC = (PIPFRAGMENT_CONTEXT)PC(NdisPacket)->Context; + + if (PrepareNextFragment(IFC)) { + /* A fragment was prepared for transmission, so send it */ + IPSendFragment(IFC->NdisPacket, IFC->NCE); + } else { + TI_DbgPrint(MAX_TRACE, ("Calling completion handler.\n")); + + /* There are no more fragments to transmit, so call completion handler */ + NdisPacket = IFC->Datagram; + FreeNdisPacket(IFC->NdisPacket); + ExFreePool(IFC); + (*PC(NdisPacket)->Complete)(PC(NdisPacket)->Context, NdisPacket, NdisStatus); + } + } +} + + +NTSTATUS IPSendFragment( + PNDIS_PACKET NdisPacket, + PNEIGHBOR_CACHE_ENTRY NCE) +/* + * FUNCTION: Sends an IP datagram fragment to a neighbor + * ARGUMENTS: + * NdisPacket = Pointer to an NDIS packet containing fragment + * NCE = Pointer to NCE for first hop to destination + * RETURNS: + * Status of operation + * NOTES: + * Lowest level IP send routine + */ +{ + TI_DbgPrint(MAX_TRACE, ("Called. NdisPacket (0x%X) NCE (0x%X).\n", NdisPacket, NCE)); + + TI_DbgPrint(MAX_TRACE, ("NCE->State = %d.\n", NCE->State)); + + switch (NCE->State) { + case NUD_PERMANENT: + /* Neighbor is always valid */ + break; + + case NUD_REACHABLE: + /* Neighbor is reachable */ + + /* FIXME: Set reachable timer */ + + break; + + case NUD_STALE: + /* Enter delay state and send packet */ + + /* FIXME: Enter delay state */ + + break; + + case NUD_DELAY: + case NUD_PROBE: + /* In these states we send the packet and hope the neighbor + hasn't changed hardware address */ + break; + + case NUD_INCOMPLETE: + TI_DbgPrint(MAX_TRACE, ("Queueing packet.\n")); + + /* We don't know the hardware address of the first hop to + the destination. Queue the packet on the NCE and return */ + NBQueuePacket(NCE, NdisPacket); + + return STATUS_SUCCESS; + default: + /* Should not happen */ + TI_DbgPrint(MIN_TRACE, ("Unknown NCE state.\n")); + + return STATUS_SUCCESS; + } + + PC(NdisPacket)->DLComplete = IPSendComplete; + (*NCE->Interface->Transmit)(NCE->Interface->Context, + NdisPacket, + MaxLLHeaderSize, + NCE->LinkAddress, + LAN_PROTO_IPv4); + + return STATUS_SUCCESS; +} + + +NTSTATUS IPSendDatagram( + PIP_PACKET IPPacket, + PROUTE_CACHE_NODE RCN) +/* + * FUNCTION: Sends an IP datagram to a remote address + * ARGUMENTS: + * IPPacket = Pointer to an IP packet + * RCN = Pointer to route cache node + * RETURNS: + * Status of operation + * NOTES: + * This is the highest level IP send routine. It possibly breaks the packet + * into two or more fragments before passing it on to the next lower level + * send routine (IPSendFragment) + */ +{ + PNEIGHBOR_CACHE_ENTRY NCE; + UINT PathMTU; + + TI_DbgPrint(MAX_TRACE, ("Called. IPPacket (0x%X) RCN (0x%X)\n", IPPacket, RCN)); + + DISPLAY_IP_PACKET(IPPacket); + + NCE = RCN->NCE; + +#if DBG + if (!NCE) { + TI_DbgPrint(MIN_TRACE, ("No NCE to use.\n")); + FreeNdisPacket(IPPacket->NdisPacket); + return STATUS_SUCCESS; + } +#endif + + /* Fetch path MTU now, because it may change */ + PathMTU = RCN->PathMTU; + + if (IPPacket->TotalSize > PathMTU) { + return SendFragments(IPPacket, NCE, PathMTU); + } else { + if ((IPPacket->Flags & IP_PACKET_FLAG_RAW) == 0) { + /* Calculate checksum of IP header */ + ((PIPv4_HEADER)IPPacket->Header)->Checksum = 0; + + ((PIPv4_HEADER)IPPacket->Header)->Checksum = (USHORT) + IPv4Checksum(IPPacket->Header, IPPacket->HeaderSize, 0); + + TI_DbgPrint(MAX_TRACE, ("Sending packet (length is %d).\n", + WN2H(((PIPv4_HEADER)IPPacket->Header)->TotalLength))); + } else { + TI_DbgPrint(MAX_TRACE, ("Sending raw packet (flags are 0x%X).\n", + IPPacket->Flags)); + } + + return IPSendFragment(IPPacket->NdisPacket, NCE); + } +} + +/* EOF */ diff --git a/drivers/net/tcpip/readme.txt b/drivers/net/tcpip/readme.txt new file mode 100644 index 0000000..b87c9df --- /dev/null +++ b/drivers/net/tcpip/readme.txt @@ -0,0 +1,19 @@ +Build instructions for TCP/IP protocol driver +--------------------------------------------- + +Building with Visual C++ and Windows NT DDK: + +Variables: +%BASEDIR% = path to NT4 DDK (e.g. c:\ntddk) +%DDKBUILDENV% = DDK build environment (free or checked) + +DDK environment variables must be set! (run setenv.bat) + + - Create the directory objects/i386/%DDKBUILDENV% + - Run "build" to build the driver + + +Building with Mingw32 and ReactOS include files: + + - Build NDIS.SYS (i.e. "make ndis") + - Run "make tcpip" FROM THE ReactOS ROOT DIRECTORY to build the driver diff --git a/drivers/net/tcpip/tcpip.def b/drivers/net/tcpip/tcpip.def new file mode 100644 index 0000000..cec8466 --- /dev/null +++ b/drivers/net/tcpip/tcpip.def @@ -0,0 +1,32 @@ +; TCPIP.SYS - TCP/IP protocol driver + +LIBRARY tcpip.sys + +EXPORTS +;FreeIprBuff +;GetIFAndLink +IPAddInterface@20 +;IPAllocBuff +IPDelInterface@4 +;IPDelayedNdisReEnumerateBindings +;IPDeregisterARP +;IPDisableSniffer +;IPEnableSniffer +;IPFreeBuff +;IPGetAddrType +;IPGetBestInterface +;IPGetInfo +;IPInjectPkt +;IPProxyNdisRequest +;IPRegisterARP +;IPRegisterProtocol +;IPSetIPSecStatus +;IPTransmit +LookupRoute@8 +;LookupRouteInformation +;SendICMPErr +;SetIPSecPtr +;UnSetIPSecPtr +;UnSetIPSecSendPtr + +; EOF diff --git a/drivers/net/tcpip/tcpip.edf b/drivers/net/tcpip/tcpip.edf new file mode 100644 index 0000000..56e0c62 --- /dev/null +++ b/drivers/net/tcpip/tcpip.edf @@ -0,0 +1,32 @@ +; TCPIP.SYS - TCP/IP protocol driver + +LIBRARY tcpip.sys + +EXPORTS +;FreeIprBuff +;GetIFAndLink +IPAddInterface=IPAddInterface@20 +;IPAllocBuff +IPDelInterface=IPDelInterface@4 +;IPDelayedNdisReEnumerateBindings +;IPDeregisterARP +;IPDisableSniffer +;IPEnableSniffer +;IPFreeBuff +;IPGetAddrType +;IPGetBestInterface +;IPGetInfo +;IPInjectPkt +;IPProxyNdisRequest +;IPRegisterARP +;IPRegisterProtocol +;IPSetIPSecStatus +;IPTransmit +LookupRoute=LookupRoute@8 +;LookupRouteInformation +;SendICMPErr +;SetIPSecPtr +;UnSetIPSecPtr +;UnSetIPSecSendPtr + +; EOF diff --git a/drivers/net/tcpip/tcpip.rc b/drivers/net/tcpip/tcpip.rc new file mode 100644 index 0000000..6f31df8 --- /dev/null +++ b/drivers/net/tcpip/tcpip.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "TCP/IP protocol driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "tcpip\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "tcpip.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/net/tcpip/tcpip/Makefile b/drivers/net/tcpip/tcpip/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/tcpip/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/tcpip/SOURCES b/drivers/net/tcpip/tcpip/SOURCES new file mode 100644 index 0000000..6e20291 --- /dev/null +++ b/drivers/net/tcpip/tcpip/SOURCES @@ -0,0 +1,28 @@ +TARGETNAME=tcpip +TARGETPATH=..\objects +TARGETTYPE=EXPORT_DRIVER + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib \ + ..\objects\*\free\datagram.lib \ + ..\objects\*\free\datalink.lib \ + ..\objects\*\free\network.lib \ + ..\objects\*\free\rawip.lib \ + ..\objects\*\free\tcp.lib \ + ..\objects\*\free\udp.lib + +INCLUDES=..\include;$(BASEDIR)\INC;..\..\..\..\include\net + + +SOURCES= address.c \ + checksum.c \ + dispatch.c \ + fileobjs.c \ + info.c \ + main.c \ + pool.c \ + routines.c \ + RESOURCE.RC + +MSC_WARNING_LEVEL=/W3 /WX + diff --git a/drivers/net/tcpip/tcpip/address.c b/drivers/net/tcpip/tcpip/address.c new file mode 100644 index 0000000..820ae7e --- /dev/null +++ b/drivers/net/tcpip/tcpip/address.c @@ -0,0 +1,417 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/address.c + * PURPOSE: Routines for handling addresses + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include + +#ifdef DBG + +CHAR A2SStr[128]; + +PCHAR A2S( + PIP_ADDRESS Address) +/* + * FUNCTION: Convert an IP address to a string (for debugging) + * ARGUMENTS: + * Address = Pointer to an IP address structure + * RETURNS: + * Pointer to buffer with string representation of IP address + */ +{ + ULONG ip; + CHAR b[10]; + PCHAR p; + + p = A2SStr; + + if (!Address) { + TI_DbgPrint(MIN_TRACE, ("NULL address given.\n")); + strcpy(p, "(NULL)"); + return p; + } + + switch (Address->Type) { + case IP_ADDRESS_V4: + ip = DN2H(Address->Address.IPv4Address); + sprintf(p, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); + break; + + case IP_ADDRESS_V6: + /* FIXME: IPv6 is not supported */ + strcpy(p, "(IPv6 address not supported)"); + break; + } + return p; +} + +#endif /* DBG */ + + +VOID IPAddressFree( + PVOID Object) +/* + * FUNCTION: Frees an IP_ADDRESS object + * ARGUMENTS: + * Object = Pointer to an IP address structure + * RETURNS: + * Nothing + */ +{ + ExFreePool(Object); +} + + +BOOLEAN AddrIsUnspecified( + PIP_ADDRESS Address) +/* + * FUNCTION: Return wether IP address is an unspecified address + * ARGUMENTS: + * Address = Pointer to an IP address structure + * RETURNS: + * TRUE if the IP address is an unspecified address, FALSE if not + */ +{ + switch (Address->Type) { + case IP_ADDRESS_V4: + return (Address->Address.IPv4Address == 0); + + case IP_ADDRESS_V6: + /* FIXME: IPv6 is not supported */ + default: + return FALSE; + } +} + + +/* + * FUNCTION: Extract IP address from TDI address structure + * ARGUMENTS: + * AddrList = Pointer to transport address list to extract from + * Address = Address of a pointer to where an IP address is stored + * Port = Pointer to where port number is stored + * Cache = Address of pointer to a cached address (updated on return) + * RETURNS: + * Status of operation + */ +NTSTATUS AddrGetAddress( + PTRANSPORT_ADDRESS AddrList, + PIP_ADDRESS *Address, + PUSHORT Port, + PIP_ADDRESS *Cache) +{ + PTA_ADDRESS CurAddr; + INT i; + + /* We can only use IP addresses. Search the list until we find one */ + CurAddr = AddrList->Address; + + for (i = 0; i < AddrList->TAAddressCount; i++) { + switch (CurAddr->AddressType) { + case TDI_ADDRESS_TYPE_IP: + if (CurAddr->AddressLength >= TDI_ADDRESS_LENGTH_IP) { + /* This is an IPv4 address */ + PIP_ADDRESS IPAddress; + PTDI_ADDRESS_IP ValidAddr = (PTDI_ADDRESS_IP)CurAddr->Address; + + *Port = ValidAddr->sin_port; + + if ((Cache) && (*Cache)) { + if (((*Cache)->Type == IP_ADDRESS_V4) && + ((*Cache)->Address.IPv4Address == ValidAddr->in_addr)) { + *Address = *Cache; + return STATUS_SUCCESS; + } else { + /* Release the cached address as we cannot use it this time */ + DereferenceObject(*Cache); + *Cache = NULL; + } + } + + IPAddress = ExAllocatePool(NonPagedPool, sizeof(IP_ADDRESS)); + if (IPAddress) { + AddrInitIPv4(IPAddress, ValidAddr->in_addr); + *Address = IPAddress; + + /* Update address cache */ + if (Cache) { + *Cache = IPAddress; + ReferenceObject(*Cache); + } + return STATUS_SUCCESS; + } else + return STATUS_INSUFFICIENT_RESOURCES; + } else + return STATUS_INVALID_ADDRESS; + default: + /* This is an unsupported address type. + Skip it and go to the next in the list */ + CurAddr = (PTA_ADDRESS)((ULONG_PTR)CurAddr->Address + CurAddr->AddressLength); + } + } + + return STATUS_INVALID_ADDRESS; +} + + +/* + * FUNCTION: Extract IP address from TDI address structure + * ARGUMENTS: + * TdiAddress = Pointer to transport address list to extract from + * Address = Address of a pointer to where an IP address is stored + * Port = Pointer to where port number is stored + * RETURNS: + * Status of operation + */ +NTSTATUS AddrBuildAddress( + PTA_ADDRESS TdiAddress, + PIP_ADDRESS *Address, + PUSHORT Port) +{ + PTDI_ADDRESS_IP ValidAddr; + PIP_ADDRESS IPAddress; + + if (TdiAddress->AddressType != TDI_ADDRESS_TYPE_IP) + return STATUS_INVALID_ADDRESS; + + if (TdiAddress->AddressLength >= TDI_ADDRESS_LENGTH_IP) + return STATUS_INVALID_ADDRESS; + + ValidAddr = (PTDI_ADDRESS_IP)TdiAddress->Address; + + IPAddress = ExAllocatePool(NonPagedPool, sizeof(IP_ADDRESS)); + if (!IPAddress) + return STATUS_INSUFFICIENT_RESOURCES; + + AddrInitIPv4(IPAddress, ValidAddr->in_addr); + *Address = IPAddress; + *Port = ValidAddr->sin_port; + + return STATUS_SUCCESS; +} + + +/* + * FUNCTION: Returns wether two addresses are equal + * ARGUMENTS: + * Address1 = Pointer to first address + * Address2 = Pointer to last address + * RETURNS: + * TRUE if Address1 = Address2, FALSE if not + */ +BOOLEAN AddrIsEqual( + PIP_ADDRESS Address1, + PIP_ADDRESS Address2) +{ + if (Address1->Type != Address2->Type) + return FALSE; + + switch (Address1->Type) { + case IP_ADDRESS_V4: + return (Address1->Address.IPv4Address == Address2->Address.IPv4Address); + + case IP_ADDRESS_V6: + return (RtlCompareMemory(&Address1->Address, &Address2->Address, + sizeof(IPv6_RAW_ADDRESS)) == sizeof(IPv6_RAW_ADDRESS)); + break; + } + + return FALSE; +} + + +/* + * FUNCTION: Returns wether Address1 is less than Address2 + * ARGUMENTS: + * Address1 = Pointer to first address + * Address2 = Pointer to last address + * RETURNS: + * -1 if Address1 < Address2, 1 if Address1 > Address2, + * or 0 if they are equal + */ +INT AddrCompare( + PIP_ADDRESS Address1, + PIP_ADDRESS Address2) +{ + switch (Address1->Type) { + case IP_ADDRESS_V4: { + ULONG Addr1, Addr2; + if (Address2->Type == IP_ADDRESS_V4) { + Addr1 = DN2H(Address1->Address.IPv4Address); + Addr2 = DN2H(Address2->Address.IPv4Address); + if (Addr1 < Addr2) + return -1; + else + if (Addr1 == Addr2) + return 0; + else + return 1; + } else + /* FIXME: Support IPv6 */ + return -1; + + case IP_ADDRESS_V6: + /* FIXME: Support IPv6 */ + break; + } + } + + return FALSE; +} + + +/* + * FUNCTION: Returns wether two addresses are equal with IPv4 as input + * ARGUMENTS: + * Address1 = Pointer to first address + * Address2 = Pointer to last address + * RETURNS: + * TRUE if Address1 = Address2, FALSE if not + */ +BOOLEAN AddrIsEqualIPv4( + PIP_ADDRESS Address1, + IPv4_RAW_ADDRESS Address2) +{ + if (Address1->Type == IP_ADDRESS_V4) + return (Address1->Address.IPv4Address == Address2); + + return FALSE; +} + + +/* + * FUNCTION: Build an IPv4 style address + * ARGUMENTS: + * Address = Raw IPv4 address + * RETURNS: + * Pointer to IP address structure, NULL if there was not enough free + * non-paged memory + */ +PIP_ADDRESS AddrBuildIPv4( + IPv4_RAW_ADDRESS Address) +{ + PIP_ADDRESS IPAddress; + + IPAddress = ExAllocatePool(NonPagedPool, sizeof(IP_ADDRESS)); + if (IPAddress) { + IPAddress->RefCount = 1; + IPAddress->Type = IP_ADDRESS_V4; + IPAddress->Address.IPv4Address = Address; + IPAddress->Free = IPAddressFree; + } + + return IPAddress; +} + + +/* + * FUNCTION: Locates and returns an address entry using IPv4 adress as argument + * ARGUMENTS: + * Address = Raw IPv4 address + * RETURNS: + * Pointer to address entry if found, NULL if not found + * NOTES: + * Only unicast addresses are considered. + * If found, the address is referenced + */ +PADDRESS_ENTRY AddrLocateADEv4( + IPv4_RAW_ADDRESS Address) +{ + IP_ADDRESS Addr; + + AddrInitIPv4(&Addr, Address); + + return IPLocateADE(&Addr, ADE_UNICAST); +} + + +/* + * FUNCTION: Searches through address file entries to find the first match + * ARGUMENTS: + * Address = IP address + * Port = Port number + * Protocol = Protocol number + * SearchContext = Pointer to search context + * RETURNS: + * Pointer to address file, NULL if none was found + */ +PADDRESS_FILE AddrSearchFirst( + PIP_ADDRESS Address, + USHORT Port, + USHORT Protocol, + PAF_SEARCH SearchContext) +{ + SearchContext->Address = Address; + SearchContext->Port = Port; + SearchContext->Next = AddressFileListHead.Flink; + SearchContext->Protocol = Protocol; + + return AddrSearchNext(SearchContext); +} + + +/* + * FUNCTION: Searches through address file entries to find next match + * ARGUMENTS: + * SearchContext = Pointer to search context + * RETURNS: + * Pointer to address file, NULL if none was found + */ +PADDRESS_FILE AddrSearchNext( + PAF_SEARCH SearchContext) +{ + PLIST_ENTRY CurrentEntry; + PIP_ADDRESS IPAddress; + KIRQL OldIrql; + PADDRESS_FILE Current = NULL; + BOOLEAN Found = FALSE; + + if (IsListEmpty(SearchContext->Next)) + return NULL; + + CurrentEntry = SearchContext->Next; + + KeAcquireSpinLock(&AddressFileListLock, &OldIrql); + + while (CurrentEntry != &AddressFileListHead) { + Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry); + + IPAddress = Current->ADE->Address; + + TI_DbgPrint(DEBUG_ADDRFILE, ("Comparing: ((%d, %d, %s), (%d, %d, %s)).\n", + Current->Port, + Current->Protocol, + A2S(IPAddress), + SearchContext->Port, + SearchContext->Protocol, + A2S(SearchContext->Address))); + + /* See if this address matches the search criteria */ + if (((Current->Port == SearchContext->Port) && + (Current->Protocol == SearchContext->Protocol) && + (AddrIsEqual(IPAddress, SearchContext->Address))) || + (AddrIsUnspecified(IPAddress))) { + /* We've found a match */ + Found = TRUE; + break; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&AddressFileListLock, OldIrql); + + if (Found) { + SearchContext->Next = CurrentEntry->Flink; + return Current; + } else + return NULL; +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/checksum.c b/drivers/net/tcpip/tcpip/checksum.c new file mode 100644 index 0000000..72c08e8 --- /dev/null +++ b/drivers/net/tcpip/tcpip/checksum.c @@ -0,0 +1,50 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/checksum.c + * PURPOSE: Checksum routines + * NOTES: The checksum routine is from RFC 1071 + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include + + +ULONG ChecksumCompute( + PVOID Data, + UINT Count, + ULONG Seed) +/* + * FUNCTION: Calculate checksum of a buffer + * ARGUMENTS: + * Data = Pointer to buffer with data + * Count = Number of bytes in buffer + * Seed = Previously calculated checksum (if any) + * RETURNS: + * Checksum of buffer + */ +{ + /* FIXME: This should be done in assembler */ + + register ULONG Sum = Seed; + + while (Count > 1) { + Sum += *(PUSHORT)Data; + Count -= 2; + (ULONG_PTR)Data += 2; + } + + /* Add left-over byte, if any */ + if (Count > 0) + Sum += *(PUCHAR)Data; + + /* Fold 32-bit sum to 16 bits */ + while (Sum >> 16) + Sum = (Sum & 0xFFFF) + (Sum >> 16); + + return ~Sum; +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/dispatch.c b/drivers/net/tcpip/tcpip/dispatch.c new file mode 100644 index 0000000..e9cc811 --- /dev/null +++ b/drivers/net/tcpip/tcpip/dispatch.c @@ -0,0 +1,1051 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/dispatch.h + * PURPOSE: TDI dispatch routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + * TODO: Validate device object in all dispatch routines + */ +#include +#include +#include +#include +#include + + +NTSTATUS DispPrepareIrpForCancel( + PTRANSPORT_CONTEXT Context, + PIRP Irp, + PDRIVER_CANCEL CancelRoutine) +/* + * FUNCTION: Prepare an IRP for cancellation + * ARGUMENTS: + * Context = Pointer to context information + * Irp = Pointer to an I/O request packet + * CancelRoutine = Routine to be called when I/O request is cancelled + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IoAcquireCancelSpinLock(&OldIrql); + + if (!Irp->Cancel) { + IoMarkIrpPending(Irp); + IoSetCancelRoutine(Irp, CancelRoutine); + Context->RefCount++; + IoReleaseCancelSpinLock(OldIrql); + + TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp)); + + return STATUS_SUCCESS; + } + + /* IRP has already been cancelled */ + + IoReleaseCancelSpinLock(OldIrql); + + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + + TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n")); + + return STATUS_CANCELLED; +} + + +VOID DispCancelComplete( + PVOID Context) +/* + * FUNCTION: Completes a cancel request + * ARGUMENTS: + * Context = Pointer to context information (FILE_OBJECT) + */ +{ + KIRQL OldIrql; + PFILE_OBJECT FileObject; + PTRANSPORT_CONTEXT TranContext; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + FileObject = (PFILE_OBJECT)Context; + TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext; + + IoAcquireCancelSpinLock(&OldIrql); + + /* Remove the reference taken by the cancel routine */ + TranContext->RefCount--; + + if (TranContext->RefCount == 0) { + TI_DbgPrint(DEBUG_IRP, ("Setting TranContext->CleanupEvent to signaled.\n")); + /* Set the cleanup event */ + KeSetEvent(&TranContext->CleanupEvent, 0, FALSE); + } + + TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount (%d).\n", TranContext->RefCount)); + + IoReleaseCancelSpinLock(OldIrql); + + TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); +} + + +VOID DispCancelRequest( + PDEVICE_OBJECT Device, + PIRP Irp) +/* + * FUNCTION: Cancels an IRP + * ARGUMENTS: + * Device = Pointer to device object + * Irp = Pointer to an I/O request packet + */ +{ + PIO_STACK_LOCATION IrpSp; + PTRANSPORT_CONTEXT TranContext; + PFILE_OBJECT FileObject; + UCHAR MinorFunction; + NTSTATUS Status = STATUS_SUCCESS; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + FileObject = IrpSp->FileObject; + TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext; + MinorFunction = IrpSp->MinorFunction; + + TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp)); + +#ifdef DBG + if (!Irp->Cancel) + TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n")); +#endif + + /* Increase reference count to prevent accidential closure + of the object while inside the cancel routine */ + TranContext->RefCount++; + + IoReleaseCancelSpinLock(Irp->CancelIrql); + + /* Try canceling the request */ + switch(MinorFunction) { + case TDI_SEND: + + case TDI_RECEIVE: + /* FIXME: Close connection */ + break; + + case TDI_SEND_DATAGRAM: + if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { + TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n")); + break; + } + + DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp); + break; + + case TDI_RECEIVE_DATAGRAM: + if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { + TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n")); + break; + } + + DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp); + break; + + default: + TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction)); + break; + } + + if (Status != STATUS_PENDING) + DispCancelComplete(FileObject); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID DispDataRequestComplete( + PVOID Context, + NTSTATUS Status, + ULONG Count) +/* + * FUNCTION: Completes a send/receive IRP + * ARGUMENTS: + * Context = Pointer to context information (IRP) + * Status = Status of the request + * Count = Number of bytes sent or received + */ +{ + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PTRANSPORT_CONTEXT TranContext; + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + Irp = (PIRP)Context; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; + + IoAcquireCancelSpinLock(&OldIrql); + + IoSetCancelRoutine(Irp, NULL); + TranContext->RefCount--; + TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount (%d).\n", TranContext->RefCount)); + if (TranContext->RefCount == 0) { + TI_DbgPrint(DEBUG_IRP, ("Setting TranContext->CleanupEvent to signaled.\n")); + + KeSetEvent(&TranContext->CleanupEvent, 0, FALSE); + } + + if (Irp->Cancel || TranContext->CancelIrps) { + /* The IRP has been cancelled */ + + TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n")); + + Status = STATUS_CANCELLED; + Count = 0; + } + + IoReleaseCancelSpinLock(OldIrql); + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Count; + + TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); +} + + +NTSTATUS DispTdiAccept( + PIRP Irp) +/* + * FUNCTION: TDI_ACCEPT handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS DispTdiAssociateAddress( + PIRP Irp) +/* + * FUNCTION: TDI_ASSOCIATE_ADDRESS handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + PTDI_REQUEST_KERNEL_ASSOCIATE Parameters; + PTRANSPORT_CONTEXT TranContext; + PIO_STACK_LOCATION IrpSp; + PCONNECTION_ENDPOINT Connection; + PFILE_OBJECT FileObject; + PADDRESS_FILE AddrFile; + NTSTATUS Status; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* Get associated connection endpoint file object. Quit if none exists */ + + TranContext = IrpSp->FileObject->FsContext; + if (!TranContext) { + TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); + return STATUS_INVALID_PARAMETER; + } + + Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; + if (!Connection) { + TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); + return STATUS_INVALID_PARAMETER; + } + + if (Connection->AddressFile) { + TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n")); + return STATUS_INVALID_PARAMETER; + } + + Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters; + + Status = ObReferenceObjectByHandle( + Parameters->AddressHandle, + 0, + IoFileObjectType, + KernelMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X).\n", + Parameters->AddressHandle)); + return STATUS_INVALID_PARAMETER; + } + + if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) { + ObDereferenceObject(FileObject); + TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n", + FileObject->FsContext2)); + return STATUS_INVALID_PARAMETER; + } + + /* Get associated address file object. Quit if none exists */ + + TranContext = FileObject->FsContext; + if (!TranContext) { + ObDereferenceObject(FileObject); + TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); + return STATUS_INVALID_PARAMETER; + } + + AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; + if (!AddrFile) { + ObDereferenceObject(FileObject); + TI_DbgPrint(MID_TRACE, ("No address file object.\n")); + return STATUS_INVALID_PARAMETER; + } + + /* The connection endpoint references the address file object */ + ReferenceObject(AddrFile); + Connection->AddressFile = AddrFile; + + /* Add connection endpoint to connection list on the address file */ + ExInterlockedInsertTailList( + &AddrFile->Connections, + &Connection->AddrFileEntry, + &AddrFile->Lock); + + /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */ + ObDereferenceObject(FileObject); + + return STATUS_SUCCESS; +} + + +NTSTATUS DispTdiConnect( + PIRP Irp) +/* + * FUNCTION: TDI_CONNECT handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + PCONNECTION_ENDPOINT Connection; + PTDI_REQUEST_KERNEL Parameters; + PTRANSPORT_CONTEXT TranContext; + PIO_STACK_LOCATION IrpSp; + TDI_REQUEST Request; + NTSTATUS Status; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* Get associated connection endpoint file object. Quit if none exists */ + + TranContext = IrpSp->FileObject->FsContext; + if (!TranContext) { + TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); + return STATUS_INVALID_CONNECTION; + } + + Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; + if (!Connection) { + TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); + return STATUS_INVALID_CONNECTION; + } + + Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters; + + /* Initialize a connect request */ + Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; + Request.RequestNotifyObject = DispDataRequestComplete; + Request.RequestContext = Irp; + + Status = TCPConnect( + &Request, + Parameters->RequestConnectionInformation, + Parameters->ReturnConnectionInformation); + + return Status; +} + + +NTSTATUS DispTdiDisassociateAddress( + PIRP Irp) +/* + * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + PCONNECTION_ENDPOINT Connection; + PTRANSPORT_CONTEXT TranContext; + PIO_STACK_LOCATION IrpSp; + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* Get associated connection endpoint file object. Quit if none exists */ + + TranContext = IrpSp->FileObject->FsContext; + if (!TranContext) { + TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); + return STATUS_INVALID_PARAMETER; + } + + Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext; + if (!Connection) { + TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); + return STATUS_INVALID_PARAMETER; + } + + if (!Connection->AddressFile) { + TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n")); + return STATUS_INVALID_PARAMETER; + } + + KeAcquireSpinLock(&Connection->Lock, &OldIrql); + RemoveEntryList(&Connection->AddrFileEntry); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + + /* Remove the reference put on the address file object */ + DereferenceObject(Connection->AddressFile); + + return STATUS_SUCCESS; +} + + +NTSTATUS DispTdiDisconnect( + PIRP Irp) +/* + * FUNCTION: TDI_DISCONNECT handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS DispTdiListen( + PIRP Irp) +/* + * FUNCTION: TDI_LISTEN handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS DispTdiQueryInformation( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: TDI_QUERY_INFORMATION handler + * ARGUMENTS: + * DeviceObject = Pointer to device object structure + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS DispTdiReceive( + PIRP Irp) +/* + * FUNCTION: TDI_RECEIVE handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS DispTdiReceiveDatagram( + PIRP Irp) +/* + * FUNCTION: TDI_RECEIVE_DATAGRAM handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + PIO_STACK_LOCATION IrpSp; + PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo; + PTRANSPORT_CONTEXT TranContext; + TDI_REQUEST Request; + NTSTATUS Status; + ULONG BytesReceived; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters); + + TranContext = IrpSp->FileObject->FsContext; + /* Initialize a receive request */ + Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; + Request.RequestNotifyObject = DispDataRequestComplete; + Request.RequestContext = Irp; + Status = DispPrepareIrpForCancel( + IrpSp->FileObject->FsContext, + Irp, + (PDRIVER_CANCEL)DispCancelRequest); + if (NT_SUCCESS(Status)) { + Status = UDPReceiveDatagram( + &Request, + DgramInfo->ReceiveDatagramInformation, + (PNDIS_BUFFER)Irp->MdlAddress, + DgramInfo->ReceiveLength, + DgramInfo->ReceiveFlags, + DgramInfo->ReturnDatagramInformation, + &BytesReceived); + if (Status != STATUS_PENDING) { + DispDataRequestComplete(Irp, Status, BytesReceived); + /* Return STATUS_PENDING because DispPrepareIrpForCancel marks + the Irp as pending */ + Status = STATUS_PENDING; + } + } + + TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); + + return Status; +} + + +NTSTATUS DispTdiSend( + PIRP Irp) +/* + * FUNCTION: TDI_SEND handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS DispTdiSendDatagram( + PIRP Irp) +/* + * FUNCTION: TDI_SEND_DATAGRAM handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + PIO_STACK_LOCATION IrpSp; + TDI_REQUEST Request; + PTDI_REQUEST_KERNEL_SENDDG DgramInfo; + PTRANSPORT_CONTEXT TranContext; + NTSTATUS Status; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters); + TranContext = IrpSp->FileObject->FsContext; + + /* Initialize a send request */ + Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; + Request.RequestNotifyObject = DispDataRequestComplete; + Request.RequestContext = Irp; + + Status = DispPrepareIrpForCancel( + IrpSp->FileObject->FsContext, + Irp, + (PDRIVER_CANCEL)DispCancelRequest); + if (NT_SUCCESS(Status)) { + + /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress + must be of type PTDI_ADDRESS_IP */ + + Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( + &Request, DgramInfo->SendDatagramInformation, + (PNDIS_BUFFER)Irp->MdlAddress, DgramInfo->SendLength); + if (Status != STATUS_PENDING) { + DispDataRequestComplete(Irp, Status, 0); + /* Return STATUS_PENDING because DispPrepareIrpForCancel + marks Irp as pending */ + Status = STATUS_PENDING; + } + } + + TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); + + return Status; +} + + +NTSTATUS DispTdiSetEventHandler( + PIRP Irp) +/* + * FUNCTION: TDI_SET_EVENT_HANDER handler + * ARGUMENTS: + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of operation + */ +{ + PTDI_REQUEST_KERNEL_SET_EVENT Parameters; + PTRANSPORT_CONTEXT TranContext; + PIO_STACK_LOCATION IrpSp; + PADDRESS_FILE AddrFile; + NTSTATUS Status; + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* Get associated address file object. Quit if none exists */ + + TranContext = IrpSp->FileObject->FsContext; + if (!TranContext) { + TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n")); + return STATUS_INVALID_PARAMETER; + } + + AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle; + if (!AddrFile) { + TI_DbgPrint(MIN_TRACE, ("No address file object.\n")); + return STATUS_INVALID_PARAMETER; + } + + Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters; + Status = STATUS_SUCCESS; + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + /* Set the event handler. if an event handler is associated with + a specific event, it's flag (RegisteredXxxHandler) is TRUE. + If an event handler is not used it's flag is FALSE */ + switch (Parameters->EventType) { + case TDI_EVENT_CONNECT: + if (!Parameters->EventHandler) { + AddrFile->ConnectHandlerContext = NULL; + AddrFile->RegisteredConnectHandler = FALSE; + } else { + AddrFile->ConnectHandler = + (PTDI_IND_CONNECT)Parameters->EventHandler; + AddrFile->ConnectHandlerContext = Parameters->EventContext; + AddrFile->RegisteredConnectHandler = TRUE; + } + break; + + case TDI_EVENT_DISCONNECT: + if (!Parameters->EventHandler) { + AddrFile->DisconnectHandlerContext = NULL; + AddrFile->RegisteredDisconnectHandler = FALSE; + } else { + AddrFile->DisconnectHandler = + (PTDI_IND_DISCONNECT)Parameters->EventHandler; + AddrFile->DisconnectHandlerContext = Parameters->EventContext; + AddrFile->RegisteredDisconnectHandler = TRUE; + } + break; + + case TDI_EVENT_ERROR: + if (Parameters->EventHandler == NULL) { + AddrFile->ErrorHandlerContext = NULL; + AddrFile->RegisteredErrorHandler = FALSE; + } else { + AddrFile->ErrorHandler = + (PTDI_IND_ERROR)Parameters->EventHandler; + AddrFile->ErrorHandlerContext = Parameters->EventContext; + AddrFile->RegisteredErrorHandler = TRUE; + } + break; + + case TDI_EVENT_RECEIVE: + if (Parameters->EventHandler == NULL) { + AddrFile->ReceiveHandlerContext = NULL; + AddrFile->RegisteredReceiveHandler = FALSE; + } else { + AddrFile->ReceiveHandler = + (PTDI_IND_RECEIVE)Parameters->EventHandler; + AddrFile->ReceiveHandlerContext = Parameters->EventContext; + AddrFile->RegisteredReceiveHandler = TRUE; + } + break; + + case TDI_EVENT_RECEIVE_DATAGRAM: + if (Parameters->EventHandler == NULL) { + AddrFile->ReceiveDatagramHandlerContext = NULL; + AddrFile->RegisteredReceiveDatagramHandler = FALSE; + } else { + AddrFile->ReceiveDatagramHandler = + (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler; + AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext; + AddrFile->RegisteredReceiveDatagramHandler = TRUE; + } + break; + + case TDI_EVENT_RECEIVE_EXPEDITED: + if (Parameters->EventHandler == NULL) { + AddrFile->ExpeditedReceiveHandlerContext = NULL; + AddrFile->RegisteredExpeditedReceiveHandler = FALSE; + } else { + AddrFile->ExpeditedReceiveHandler = + (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler; + AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext; + AddrFile->RegisteredExpeditedReceiveHandler = TRUE; + } + break; + + case TDI_EVENT_CHAINED_RECEIVE: + if (Parameters->EventHandler == NULL) { + AddrFile->ChainedReceiveHandlerContext = NULL; + AddrFile->RegisteredChainedReceiveHandler = FALSE; + } else { + AddrFile->ChainedReceiveHandler = + (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler; + AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext; + AddrFile->RegisteredChainedReceiveHandler = TRUE; + } + break; + + case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM: + if (Parameters->EventHandler == NULL) { + AddrFile->ChainedReceiveDatagramHandlerContext = NULL; + AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE; + } else { + AddrFile->ChainedReceiveDatagramHandler = + (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler; + AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext; + AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE; + } + break; + + case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED: + if (Parameters->EventHandler == NULL) { + AddrFile->ChainedReceiveExpeditedHandlerContext = NULL; + AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE; + } else { + AddrFile->ChainedReceiveExpeditedHandler = + (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler; + AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext; + AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE; + } + break; + + default: + TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n", + Parameters->EventType)); + + Status = STATUS_INVALID_PARAMETER; + } + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + return Status; +} + + +NTSTATUS DispTdiSetInformation( + PIRP Irp) +/* + * FUNCTION: TDI_SET_INFORMATION handler + * ARGUMENTS: + * Irp = Pointer to an I/O request packet + * RETURNS: + * Status of operation + */ +{ + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + return STATUS_NOT_IMPLEMENTED; +} + + +VOID DispTdiQueryInformationExComplete( + PVOID Context, + ULONG Status, + UINT ByteCount) +/* + * FUNCTION: Completes a TDI QueryInformationEx request + * ARGUMENTS: + * Context = Pointer to the IRP for the request + * Status = TDI status of the request + * ByteCount = Number of bytes returned in output buffer + */ +{ + PTI_QUERY_CONTEXT QueryContext; + UINT Count = 0; + + QueryContext = (PTI_QUERY_CONTEXT)Context; + if (NT_SUCCESS(Status)) { + Count = CopyBufferToBufferChain( + QueryContext->InputMdl, + FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context), + (PUCHAR)&QueryContext->QueryInfo.Context, + CONTEXT_SIZE); + } + + MmUnlockPages(QueryContext->InputMdl); + IoFreeMdl(QueryContext->InputMdl); + MmUnlockPages(QueryContext->OutputMdl); + IoFreeMdl(QueryContext->OutputMdl); + + QueryContext->Irp->IoStatus.Information = Count; + QueryContext->Irp->IoStatus.Status = Status; + + ExFreePool(QueryContext); +} + + +NTSTATUS DispTdiQueryInformationEx( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: TDI QueryInformationEx handler + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer; + PTRANSPORT_CONTEXT TranContext; + PTI_QUERY_CONTEXT QueryContext; + PVOID OutputBuffer; + TDI_REQUEST Request; + UINT Size; + UINT InputBufferLength; + UINT OutputBufferLength; + BOOLEAN InputMdlLocked = FALSE; + BOOLEAN OutputMdlLocked = FALSE; + PMDL InputMdl = NULL; + PMDL OutputMdl = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; + + switch ((ULONG)IrpSp->FileObject->FsContext2) { + case TDI_TRANSPORT_ADDRESS_FILE: + Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; + break; + + case TDI_CONNECTION_FILE: + Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; + break; + + case TDI_CONTROL_CHANNEL_FILE: + Request.Handle.ControlChannel = TranContext->Handle.ControlChannel; + break; + + default: + TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n")); + return STATUS_INVALID_PARAMETER; + } + + InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; + + /* Validate parameters */ + if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) && + (OutputBufferLength != 0)) { + + InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX) + IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + OutputBuffer = Irp->UserBuffer; + + QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT)); + if (QueryContext) { +#ifdef _MSC_VER + try { +#endif + InputMdl = IoAllocateMdl(InputBuffer, + sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), + FALSE, TRUE, NULL); + + OutputMdl = IoAllocateMdl(OutputBuffer, + OutputBufferLength, FALSE, TRUE, NULL); + + if (InputMdl && OutputMdl) { + + MmProbeAndLockPages(InputMdl, Irp->RequestorMode, + IoModifyAccess); + + InputMdlLocked = TRUE; + + MmProbeAndLockPages(OutputMdl, Irp->RequestorMode, + IoWriteAccess); + + OutputMdlLocked = TRUE; + + RtlCopyMemory(&QueryContext->QueryInfo, + InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); + + } else + Status = STATUS_INSUFFICIENT_RESOURCES; +#ifdef _MSC_VER + } except(EXCEPTION_EXECUTE_HANDLER) { + Status = GetExceptionCode(); + } +#endif + if (NT_SUCCESS(Status)) { + Size = MmGetMdlByteCount(OutputMdl); + + QueryContext->Irp = Irp; + QueryContext->InputMdl = InputMdl; + QueryContext->OutputMdl = OutputMdl; + + Request.RequestNotifyObject = DispTdiQueryInformationExComplete; + Request.RequestContext = QueryContext; + Status = InfoTdiQueryInformationEx(&Request, + &QueryContext->QueryInfo.ID, OutputMdl, + &Size, &QueryContext->QueryInfo.Context); + DispTdiQueryInformationExComplete(QueryContext, Status, Size); + + TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status)); + + return Status; + } + + /* An error occurred if we get here */ + + if (InputMdl) { + if (InputMdlLocked) + MmUnlockPages(InputMdl); + IoFreeMdl(InputMdl); + } + + if (OutputMdl) { + if (OutputMdlLocked) + MmUnlockPages(OutputMdl); + IoFreeMdl(OutputMdl); + } + + ExFreePool(QueryContext); + } else + Status = STATUS_INSUFFICIENT_RESOURCES; + } else + Status = STATUS_INVALID_PARAMETER; + + TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status)); + + return Status; +} + + +NTSTATUS DispTdiSetInformationEx( + PIRP Irp, + PIO_STACK_LOCATION IrpSp) +/* + * FUNCTION: TDI SetInformationEx handler + * ARGUMENTS: + * Irp = Pointer to I/O request packet + * IrpSp = Pointer to current stack location of Irp + * RETURNS: + * Status of operation + */ +{ + PTRANSPORT_CONTEXT TranContext; + PTCP_REQUEST_SET_INFORMATION_EX Info; + TDI_REQUEST Request; + TDI_STATUS Status; + KIRQL OldIrql; + + TI_DbgPrint(DEBUG_IRP, ("Called.\n")); + + TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; + Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer; + + switch ((ULONG)IrpSp->FileObject->FsContext2) { + case TDI_TRANSPORT_ADDRESS_FILE: + Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; + break; + + case TDI_CONNECTION_FILE: + Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext; + break; + + case TDI_CONTROL_CHANNEL_FILE: + Request.Handle.ControlChannel = TranContext->Handle.ControlChannel; + break; + + default: + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + + TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + + return STATUS_INVALID_PARAMETER; + } + + Status = DispPrepareIrpForCancel(TranContext, Irp, NULL); + if (NT_SUCCESS(Status)) { + Request.RequestNotifyObject = DispDataRequestComplete; + Request.RequestContext = Irp; + + Status = InfoTdiSetInformationEx(&Request, &Info->ID, + &Info->Buffer, Info->BufferSize); + + if (Status != STATUS_PENDING) { + IoAcquireCancelSpinLock(&OldIrql); + IoSetCancelRoutine(Irp, NULL); + IoReleaseCancelSpinLock(OldIrql); + } + } + + return Status; +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/fileobjs.c b/drivers/net/tcpip/tcpip/fileobjs.c new file mode 100644 index 0000000..3304399 --- /dev/null +++ b/drivers/net/tcpip/tcpip/fileobjs.c @@ -0,0 +1,556 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/fileobjs.c + * PURPOSE: Routines for handling file objects + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* List of all address file objects managed by this driver */ +LIST_ENTRY AddressFileListHead; +KSPIN_LOCK AddressFileListLock; + +/* List of all connection endpoint file objects managed by this driver */ +LIST_ENTRY ConnectionEndpointListHead; +KSPIN_LOCK ConnectionEndpointListLock; + + +VOID AddrFileFree( + PVOID Object) +/* + * FUNCTION: Frees an address file object + * ARGUMENTS: + * Object = Pointer to address file object to free + */ +{ + ExFreePool(Object); +} + + +VOID DeleteAddress( + PADDRESS_FILE AddrFile) +/* + * FUNCTION: Deletes an address file object + * ARGUMENTS: + * AddrFile = Pointer to address file object to delete + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PDATAGRAM_SEND_REQUEST SendRequest; + PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + /* Remove address file from the global list */ + KeAcquireSpinLock(&AddressFileListLock, &OldIrql); + RemoveEntryList(&AddrFile->ListEntry); + KeReleaseSpinLock(&AddressFileListLock, OldIrql); + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + /* FIXME: Kill TCP connections on this address file object */ + + /* Return pending requests with error */ + + TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile)); + + /* Go through pending receive request list and cancel them all */ + CurrentEntry = AddrFile->ReceiveQueue.Flink; + while (CurrentEntry != &AddrFile->ReceiveQueue) { + NextEntry = CurrentEntry->Flink; + ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry); + /* Abort the request and free its resources */ + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_ADDRESS_CLOSED, 0); + ExFreePool(ReceiveRequest); + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + CurrentEntry = NextEntry; + } + + TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile)); + + /* Go through pending send request list and cancel them all */ + CurrentEntry = AddrFile->TransmitQueue.Flink; + while (CurrentEntry != &AddrFile->TransmitQueue) { + NextEntry = CurrentEntry->Flink; + SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); + /* Abort the request and free its resources */ + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + (*SendRequest->Complete)(SendRequest->Context, STATUS_ADDRESS_CLOSED, 0); + ExFreePool(SendRequest); + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + CurrentEntry = NextEntry; + } + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + /* Dereference address entry */ + DereferenceObject(AddrFile->ADE); + + /* Dereference address cache */ + if (AddrFile->AddrCache) + DereferenceObject(AddrFile->AddrCache); + +#ifdef DBG + /* Remove reference provided at creation time */ + AddrFile->RefCount--; + + if (AddrFile->RefCount != 0) + TI_DbgPrint(DEBUG_REFCOUNT, ("AddrFile->RefCount is (%d) (should be 0).\n", AddrFile->RefCount)); +#endif + + (*AddrFile->Free)(AddrFile); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +/* + * FUNCTION: Deletes a connection endpoint file object + * ARGUMENTS: + * Connection = Pointer to connection endpoint to delete + */ +VOID DeleteConnectionEndpoint( + PCONNECTION_ENDPOINT Connection) +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + /* Remove connection endpoint from the global list */ + KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql); + RemoveEntryList(&Connection->ListEntry); + KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql); + + KeAcquireSpinLock(&Connection->Lock, &OldIrql); + + /* Dereference and remove the address file if it exists */ + if (Connection->AddressFile) { + RemoveEntryList(&Connection->AddrFileEntry); + DereferenceObject(Connection->AddressFile); + } + + KeReleaseSpinLock(&Connection->Lock, OldIrql); + +#ifdef DBG + /* Remove reference provided at creation time */ + Connection->RefCount--; + + if (Connection->RefCount != 0) + TI_DbgPrint(DEBUG_REFCOUNT, ("Connection->RefCount is (%d) (should be 0).\n", + Connection->RefCount)); +#endif + + ExFreePool(Connection); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID RequestWorker( + PVOID Context) +/* + * FUNCTION: Worker routine for processing address file object requests + * ARGUMENTS: + * Context = Pointer to context information (ADDRESS_FILE) + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PADDRESS_FILE AddrFile = Context; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + /* Check it the address file should be deleted */ + if (AF_IS_PENDING(AddrFile, AFF_DELETE)) { + DATAGRAM_COMPLETION_ROUTINE RtnComplete; + PVOID RtnContext; + + RtnComplete = AddrFile->Complete; + RtnContext = AddrFile->Context; + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + DeleteAddress(AddrFile); + + (*RtnComplete)(RtnContext, TDI_SUCCESS, 0); + + TI_DbgPrint(MAX_TRACE, ("Leaving (delete).\n")); + + return; + } + + /* Check if there is a pending send request */ + if (AF_IS_PENDING(AddrFile, AFF_SEND)) { + if (!IsListEmpty(&AddrFile->TransmitQueue)) { + PDATAGRAM_SEND_REQUEST SendRequest; + + CurrentEntry = RemoveHeadList(&AddrFile->TransmitQueue); + SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); + + AF_CLR_BUSY(AddrFile); + + ReferenceObject(AddrFile); + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + /* The send routine processes the send requests in + the transmit queue on the address file. When the + queue is empty the pending send flag is cleared. + The routine may return with the pending send flag + set. This can happen if there was not enough free + resources available to complete all send requests */ + DGSend(AddrFile, SendRequest); + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + DereferenceObject(AddrFile); + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (send request).\n")); + + return; + } else + /* There was a pending send, but no send request. + Print a debug message and continue */ + TI_DbgPrint(MIN_TRACE, ("Pending send, but no send request.\n")); + } + + AF_CLR_BUSY(AddrFile); + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +/* + * FUNCTION: Open an address file object + * ARGUMENTS: + * Request = Pointer to TDI request structure for this request + * Address = Pointer to address to be opened + * Protocol = Protocol on which to open the address + * Options = Pointer to option buffer + * RETURNS: + * Status of operation + */ +NTSTATUS FileOpenAddress( + PTDI_REQUEST Request, + PTA_ADDRESS_IP Address, + USHORT Protocol, + PVOID Options) +{ + PADDRESS_FILE AddrFile; + IPv4_RAW_ADDRESS IPv4Address; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + AddrFile = ExAllocatePool(NonPagedPool, sizeof(ADDRESS_FILE)); + if (!AddrFile) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + TI_DbgPrint(DEBUG_ADDRFILE, ("Address file object allocated at (0x%X).\n", AddrFile)); + + RtlZeroMemory(AddrFile, sizeof(ADDRESS_FILE)); + + AddrFile->Free = AddrFileFree; + + /* Make sure address is a local unicast address or 0 */ + + /* Locate address entry. If specified address is 0, a random address is chosen */ + + /* FIXME: IPv4 only */ + IPv4Address = Address->Address[0].Address[0].in_addr; + if (IPv4Address == 0) + AddrFile->ADE = IPGetDefaultADE(ADE_UNICAST); + else + AddrFile->ADE = AddrLocateADEv4(IPv4Address); + + if (!AddrFile->ADE) { + ExFreePool(AddrFile); + TI_DbgPrint(MIN_TRACE, ("Non-local address given (0x%X).\n", DN2H(IPv4Address))); + return STATUS_INVALID_PARAMETER; + } + + TI_DbgPrint(MID_TRACE, ("Opening address %s for communication.\n", + A2S(AddrFile->ADE->Address))); + + /* Protocol specific handling */ + switch (Protocol) { + case IPPROTO_TCP: + /* FIXME: If specified port is 0, a port is chosen dynamically */ + AddrFile->Port = Address->Address[0].Address[0].sin_port; + AddrFile->Send = TCPSendDatagram; + break; + + case IPPROTO_UDP: + /* FIXME: If specified port is 0, a port is chosen dynamically */ + AddrFile->Port = Address->Address[0].Address[0].sin_port; + AddrFile->Send = UDPSendDatagram; + break; + + default: + /* Use raw IP for all other protocols */ + AddrFile->Port = 0; + AddrFile->Send = RawIPSendDatagram; + break; + } + + TI_DbgPrint(MID_TRACE, ("IP protocol number for address file object is %d.\n", + Protocol)); + + /* Set protocol */ + AddrFile->Protocol = Protocol; + + /* Initialize receive and transmit queues */ + InitializeListHead(&AddrFile->ReceiveQueue); + InitializeListHead(&AddrFile->TransmitQueue); + + /* Initialize associated connection list */ + InitializeListHead(&AddrFile->Connections); + + /* Initialize work queue item. We use this for pending requests */ + ExInitializeWorkItem(&AddrFile->WorkItem, RequestWorker, AddrFile); + + /* Initialize spin lock that protects the address file object */ + KeInitializeSpinLock(&AddrFile->Lock); + + /* Reference the object */ + AddrFile->RefCount = 1; + + /* Set valid flag so the address can be used */ + AF_SET_VALID(AddrFile); + + /* Return address file object */ + Request->Handle.AddressHandle = AddrFile; + + /* Add address file to global list */ + ExInterlockedInsertTailList( + &AddressFileListHead, + &AddrFile->ListEntry, + &AddressFileListLock); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return STATUS_SUCCESS; +} + + +/* + * FUNCTION: Closes an address file object + * ARGUMENTS: + * Request = Pointer to TDI request structure for this request + * RETURNS: + * Status of operation + */ +NTSTATUS FileCloseAddress( + PTDI_REQUEST Request) +{ + KIRQL OldIrql; + PADDRESS_FILE AddrFile; + NTSTATUS Status = STATUS_SUCCESS; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + AddrFile = Request->Handle.AddressHandle; + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if ((!AF_IS_BUSY(AddrFile)) && (AddrFile->RefCount == 1)) { + /* Set address file object exclusive to us */ + AF_SET_BUSY(AddrFile); + AF_CLR_VALID(AddrFile); + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + DeleteAddress(AddrFile); + } else { + if (!AF_IS_PENDING(AddrFile, AFF_DELETE)) { + AddrFile->Complete = Request->RequestNotifyObject; + AddrFile->Context = Request->RequestContext; + + /* Shedule address file for deletion */ + AF_SET_PENDING(AddrFile, AFF_DELETE); + AF_CLR_VALID(AddrFile); + + if (!AF_IS_BUSY(AddrFile)) { + /* Worker function is not running, so shedule it to run */ + AF_SET_BUSY(AddrFile); + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + ExQueueWorkItem(&AddrFile->WorkItem, CriticalWorkQueue); + } else + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); + + return STATUS_PENDING; + } else + Status = STATUS_ADDRESS_CLOSED; + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + } + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return Status; +} + + +/* + * FUNCTION: Opens a connection file object + * ARGUMENTS: + * Request = Pointer to TDI request structure for this request + * ClientContext = Pointer to client context information + * RETURNS: + * Status of operation + */ +NTSTATUS FileOpenConnection( + PTDI_REQUEST Request, + PVOID ClientContext) +{ + PCONNECTION_ENDPOINT Connection; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + Connection = ExAllocatePool(NonPagedPool, sizeof(CONNECTION_ENDPOINT)); + if (!Connection) + return STATUS_INSUFFICIENT_RESOURCES; + + TI_DbgPrint(DEBUG_CPOINT, ("Connection point file object allocated at (0x%X).\n", Connection)); + + RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT)); + + /* Initialize spin lock that protects the connection endpoint file object */ + KeInitializeSpinLock(&Connection->Lock); + + /* Reference the object */ + Connection->RefCount = 1; + + /* Put connection in the closed state */ + Connection->State = ctClosed; + + /* Save client context pointer */ + Connection->ClientContext = ClientContext; + + /* Return connection endpoint file object */ + Request->Handle.ConnectionContext = Connection; + + /* Add connection endpoint to global list */ + ExInterlockedInsertTailList( + &ConnectionEndpointListHead, + &Connection->ListEntry, + &ConnectionEndpointListLock); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return STATUS_SUCCESS; +} + + +/* + * FUNCTION: Closes an connection file object + * ARGUMENTS: + * Request = Pointer to TDI request structure for this request + * RETURNS: + * Status of operation + */ +NTSTATUS FileCloseConnection( + PTDI_REQUEST Request) +{ + KIRQL OldIrql; + PCONNECTION_ENDPOINT Connection; + NTSTATUS Status = STATUS_SUCCESS; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + Connection = Request->Handle.ConnectionContext; + + KeAcquireSpinLock(&Connection->Lock, &OldIrql); +#if 0 + if ((!AF_IS_BUSY(Connection)) && (Connection->RefCount == 1)) { + /* Set connection endpoint file object exclusive to us */ + AF_SET_BUSY(Connection); + AF_CLR_VALID(Connection); + + KeReleaseSpinLock(&Connection->Lock, OldIrql); +#endif + DeleteConnectionEndpoint(Connection); +#if 0 + } else { + if (!AF_IS_PENDING(Connection, AFF_DELETE)) { + Connection->Complete = Request->RequestNotifyObject; + Connection->Context = Request->RequestContext; + + /* Shedule connection endpoint for deletion */ + AF_SET_PENDING(Connection, AFF_DELETE); + AF_CLR_VALID(Connection); + + if (!AF_IS_BUSY(Connection)) { + /* Worker function is not running, so shedule it to run */ + AF_SET_BUSY(Connection); + KeReleaseSpinLock(&Connection->Lock, OldIrql); + ExQueueWorkItem(&Connection->WorkItem, CriticalWorkQueue); + } else + KeReleaseSpinLock(&Connection->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); + + return STATUS_PENDING; + } else + Status = STATUS_ADDRESS_CLOSED; + + KeReleaseSpinLock(&Connection->Lock, OldIrql); + } +#endif + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + return Status; +} + + +/* + * FUNCTION: Opens a control channel file object + * ARGUMENTS: + * Request = Pointer to TDI request structure for this request + * RETURNS: + * Status of operation + */ +NTSTATUS FileOpenControlChannel( + PTDI_REQUEST Request) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* + * FUNCTION: Closes a control channel file object + * ARGUMENTS: + * Request = Pointer to TDI request structure for this request + * RETURNS: + * Status of operation + */ +NTSTATUS FileCloseControlChannel( + PTDI_REQUEST Request) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/info.c b/drivers/net/tcpip/tcpip/info.c new file mode 100644 index 0000000..b24c4f7 --- /dev/null +++ b/drivers/net/tcpip/tcpip/info.c @@ -0,0 +1,339 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/info.c + * PURPOSE: TDI query and set information routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include + + +TDI_STATUS IPTdiQueryInformationEx( + PTDI_REQUEST Request, + TDIObjectID *ID, + PNDIS_BUFFER Buffer, + PUINT BufferSize, + PVOID Context) +/* + * FUNCTION: Returns extended information about network layer + * ARGUMENTS: + * Request = Pointer to TDI request structure for the request + * ID = TDI object ID + * Buffer = Pointer to buffer with data to use. + * BufferSize = Pointer to buffer with size of Buffer. On return + * this is filled with number of bytes returned + * Context = Pointer to context buffer + * RETURNS: + * Status of operation + */ +{ + PLIST_ENTRY CurrentIFEntry; + PLIST_ENTRY CurrentADEEntry; + PIP_INTERFACE CurrentIF; + PADDRESS_ENTRY CurrentADE; + IPADDR_ENTRY IpAddress; + IPSNMP_INFO SnmpInfo; + ULONG Temp; + UINT Count; + ULONG Entity; + KIRQL OldIrql; + UINT BufSize = *BufferSize; + + /* Make return parameters consistent every time */ + *BufferSize = 0; + + Entity = ID->toi_entity.tei_entity; + if (Entity != CL_NL_ENTITY) { + /* We can't handle this entity */ + return TDI_INVALID_PARAMETER; + } + + if (ID->toi_entity.tei_instance != TL_INSTANCE) + /* We only support a single instance */ + return TDI_INVALID_REQUEST; + if (ID->toi_class == INFO_CLASS_GENERIC) { + if (ID->toi_type == INFO_TYPE_PROVIDER && + ID->toi_id == ENTITY_TYPE_ID) { + + if (BufSize < sizeof(ULONG)) + return TDI_BUFFER_TOO_SMALL; + Temp = CL_NL_IP; + + Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG)); + + return TDI_SUCCESS; + } + return TDI_INVALID_PARAMETER; + } + + if (ID->toi_class == INFO_CLASS_PROTOCOL) { + if (ID->toi_type != INFO_TYPE_PROVIDER) + return TDI_INVALID_PARAMETER; + + switch (ID->toi_id) { + case IP_MIB_ADDRTABLE_ENTRY_ID: + Temp = 0; + + KeAcquireSpinLock(&InterfaceListLock, &OldIrql); + + CurrentIFEntry = InterfaceListHead.Flink; + while (CurrentIFEntry != &InterfaceListHead) { + CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry); + + if (Temp + sizeof(IPADDR_ENTRY) > BufSize) { + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + return TDI_BUFFER_TOO_SMALL; + } + + IpAddress.Addr = 0; + IpAddress.BcastAddr = 0; + IpAddress.Mask = 0; + + /* Locate the diffrent addresses and put them the right place */ + CurrentADEEntry = CurrentIF->ADEListHead.Flink; + while (CurrentADEEntry != &CurrentIF->ADEListHead) { + CurrentADE = CONTAINING_RECORD(CurrentADEEntry, ADDRESS_ENTRY, ListEntry); + + switch (CurrentADE->Type) { + case ADE_UNICAST: + IpAddress.Addr = CurrentADE->Address->Address.IPv4Address; + break; + case ADE_MULTICAST: + IpAddress.BcastAddr = CurrentADE->Address->Address.IPv4Address; + break; + case ADE_ADDRMASK: + IpAddress.Mask = CurrentADE->Address->Address.IPv4Address; + break; + default: + /* Should not happen */ + TI_DbgPrint(MIN_TRACE, ("Unknown address entry type (0x%X)\n", CurrentADE->Type)); + break; + } + CurrentADEEntry = CurrentADEEntry->Flink; + } + /* Pack the address information into IPADDR_ENTRY structure */ + IpAddress.Index = 0; + IpAddress.ReasmSize = 0; + IpAddress.Context = 0; + IpAddress.Pad = 0; + + Count = CopyBufferToBufferChain(Buffer, Temp, (PUCHAR)&IpAddress, sizeof(IPADDR_ENTRY)); + + Temp += sizeof(IPADDR_ENTRY); + + CurrentIFEntry = CurrentIFEntry->Flink; + } + + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + + return TDI_SUCCESS; + + case IP_MIB_STATS_ID: + if (BufSize < sizeof(IPSNMP_INFO)) + return TDI_BUFFER_TOO_SMALL; + + RtlZeroMemory(&SnmpInfo, sizeof(IPSNMP_INFO)); + + /* Count number of addresses */ + Count = 0; + KeAcquireSpinLock(&InterfaceListLock, &OldIrql); + + CurrentIFEntry = InterfaceListHead.Flink; + while (CurrentIFEntry != &InterfaceListHead) { + CurrentIF = CONTAINING_RECORD(CurrentIFEntry, IP_INTERFACE, ListEntry); + Count++; + CurrentIFEntry = CurrentIFEntry->Flink; + } + + KeReleaseSpinLock(&InterfaceListLock, OldIrql); + + SnmpInfo.NumAddr = Count; + + Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&SnmpInfo, sizeof(IPSNMP_INFO)); + + return TDI_SUCCESS; + + default: + /* We can't handle this ID */ + return TDI_INVALID_PARAMETER; + } + } + + return TDI_INVALID_PARAMETER; +} + + +TDI_STATUS InfoTdiQueryInformationEx( + PTDI_REQUEST Request, + TDIObjectID *ID, + PNDIS_BUFFER Buffer, + PUINT BufferSize, + PVOID Context) +/* + * FUNCTION: Returns extended information + * ARGUMENTS: + * Request = Pointer to TDI request structure for the request + * ID = TDI object ID + * Buffer = Pointer to buffer with data to use + * BufferSize = Pointer to buffer with size of Buffer. On return + * this is filled with number of bytes returned + * Context = Pointer to context buffer + * RETURNS: + * Status of operation + */ +{ + PLIST_ENTRY CurrentADFEntry; + PADDRESS_FILE CurrentADF; + ADDRESS_INFO Info; + KIRQL OldIrql; + UINT Entity; + UINT Count; + UINT Size; + ULONG Temp; + UINT Offset = 0; + UINT BufSize = *BufferSize; + + /* Check wether it is a query for a list of entities */ + Entity = ID->toi_entity.tei_entity; + if (Entity == GENERIC_ENTITY) { + if (ID->toi_class != INFO_CLASS_GENERIC || + ID->toi_type != INFO_TYPE_PROVIDER || + ID->toi_id != ENTITY_LIST_ID) + return TDI_INVALID_PARAMETER; + + *BufferSize = 0; + + Size = EntityCount * sizeof(TDIEntityID); + if (BufSize < Size) + /* The buffer is too small to contain requested data */ + return TDI_BUFFER_TOO_SMALL; + + /* Return entity list */ + Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)EntityList, Size); + + *BufferSize = Size; + + return TDI_SUCCESS; + } + + if ((Entity != CL_TL_ENTITY) && (Entity != CO_TL_ENTITY)) { + /* We can't handle this entity, pass it on */ + return IPTdiQueryInformationEx( + Request, ID, Buffer, BufferSize, Context); + } + + /* Make return parameters consistent every time */ + *BufferSize = 0; + + if (ID->toi_entity.tei_instance != TL_INSTANCE) + /* We only support a single instance */ + return TDI_INVALID_REQUEST; + + if (ID->toi_class == INFO_CLASS_GENERIC) { + + if (ID->toi_type != INFO_TYPE_PROVIDER || + ID->toi_id != ENTITY_TYPE_ID) + return TDI_INVALID_PARAMETER; + + if (BufSize < sizeof(ULONG)) + return TDI_BUFFER_TOO_SMALL; + + if (Entity == CL_TL_ENTITY) + Temp = CL_TL_UDP; + else if (Entity == CO_TL_ENTITY) + Temp = CO_TL_TCP; + else + return TDI_INVALID_PARAMETER; + + Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&Temp, sizeof(ULONG)); + + return TDI_SUCCESS; + } + + if (ID->toi_class == INFO_CLASS_PROTOCOL) { + + if (ID->toi_type != INFO_TYPE_PROVIDER) + return TDI_INVALID_PARAMETER; + + switch (ID->toi_id) { + case UDP_MIB_STAT_ID: + if (Entity != CL_TL_ENTITY) + return TDI_INVALID_PARAMETER; + + if (BufSize < sizeof(UDPStats)) + return TDI_BUFFER_TOO_SMALL; + + Count = CopyBufferToBufferChain(Buffer, 0, (PUCHAR)&UDPStats, sizeof(UDP_STATISTICS)); + + return TDI_SUCCESS; + + case UDP_MIB_TABLE_ID: + if (Entity != CL_TL_ENTITY) + return TDI_INVALID_PARAMETER; + + Offset = 0; + + KeAcquireSpinLock(&AddressFileListLock, &OldIrql); + + CurrentADFEntry = AddressFileListHead.Flink; + while (CurrentADFEntry != &AddressFileListHead) { + CurrentADF = CONTAINING_RECORD(CurrentADFEntry, ADDRESS_FILE, ListEntry); + + if (Offset + sizeof(ADDRESS_INFO) > BufSize) { + KeReleaseSpinLock(&AddressFileListLock, OldIrql); + *BufferSize = Offset; + return TDI_BUFFER_OVERFLOW; + } + + Info.LocalAddress = CurrentADF->ADE->Address->Address.IPv4Address; + Info.LocalPort = CurrentADF->Port; + + Count = CopyBufferToBufferChain(Buffer, Offset, (PUCHAR)&Info, sizeof(ADDRESS_INFO)); + + Offset += Count; + + CurrentADFEntry = CurrentADFEntry->Flink; + } + + KeReleaseSpinLock(&AddressFileListLock, OldIrql); + + *BufferSize = Offset; + + return STATUS_SUCCESS; + + default: + /* We can't handle this ID */ + return TDI_INVALID_PARAMETER; + } + } + + return TDI_INVALID_PARAMETER; +} + + +TDI_STATUS InfoTdiSetInformationEx( + PTDI_REQUEST Request, + TDIObjectID *ID, + PVOID Buffer, + UINT BufferSize) +/* + * FUNCTION: Sets extended information + * ARGUMENTS: + * Request = Pointer to TDI request structure for the request + * ID = Pointer to TDI object ID + * Buffer = Pointer to buffer with data to use + * BufferSize = Size of Buffer + * RETURNS: + * Status of operation + */ +{ + /* FIXME: Set extended information */ + + return TDI_INVALID_REQUEST; +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/main.c b/drivers/net/tcpip/tcpip/main.c new file mode 100644 index 0000000..dde71b9 --- /dev/null +++ b/drivers/net/tcpip/tcpip/main.c @@ -0,0 +1,924 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/main.c + * PURPOSE: Driver entry point + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include + +//#define _USE_NE2000 + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +#ifdef _USE_NE2000 +DWORD DebugTraceLevel = MID_TRACE; +//DWORD DebugTraceLevel = (MAX_TRACE + DEBUG_DATALINK); +#else +DWORD DebugTraceLevel = MIN_TRACE; +//DWORD DebugTraceLevel = MAX_TRACE; +//DWORD DebugTraceLevel = DEBUG_ULTRA; +#endif + +#endif /* DBG */ + +PDEVICE_OBJECT TCPDeviceObject = NULL; +PDEVICE_OBJECT UDPDeviceObject = NULL; +PDEVICE_OBJECT IPDeviceObject = NULL; +PDEVICE_OBJECT RawIPDeviceObject = NULL; +NDIS_HANDLE GlobalPacketPool = NULL; +NDIS_HANDLE GlobalBufferPool = NULL; +TDIEntityID *EntityList = NULL; +ULONG EntityCount = 0; +UDP_STATISTICS UDPStats; + + +VOID TiWriteErrorLog( + PDRIVER_OBJECT DriverContext, + NTSTATUS ErrorCode, + ULONG UniqueErrorValue, + NTSTATUS FinalStatus, + PWSTR String, + ULONG DumpDataCount, + PULONG DumpData) +/* + * FUNCTION: Writes an error log entry + * ARGUMENTS: + * DriverContext = Pointer to the driver or device object + * ErrorCode = An error code to put in the log entry + * UniqueErrorValue = UniqueErrorValue in the error log packet + * FinalStatus = FinalStatus in the error log packet + * String = If not NULL, a pointer to a string to put in log entry + * DumpDataCount = Number of ULONGs of dump data + * DumpData = Pointer to dump data for the log entry + */ +{ +#ifdef _MSC_VER + PIO_ERROR_LOG_PACKET LogEntry; + UCHAR EntrySize; + ULONG StringSize; + PUCHAR pString; + static WCHAR DriverName[] = L"TCP/IP"; + + EntrySize = sizeof(IO_ERROR_LOG_PACKET) + + (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName); + + if (String) { + StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL); + EntrySize += (UCHAR)StringSize; + } + + LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( + DriverContext, EntrySize); + + if (LogEntry) { + LogEntry->MajorFunctionCode = -1; + LogEntry->RetryCount = -1; + LogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG)); + LogEntry->NumberOfStrings = (String == NULL) ? 1 : 2; + LogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount-1) * sizeof(ULONG); + LogEntry->EventCategory = 0; + LogEntry->ErrorCode = ErrorCode; + LogEntry->UniqueErrorValue = UniqueErrorValue; + LogEntry->FinalStatus = FinalStatus; + LogEntry->SequenceNumber = -1; + LogEntry->IoControlCode = 0; + + if (DumpDataCount) + RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG)); + + pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset; + RtlCopyMemory(pString, DriverName, sizeof(DriverName)); + pString += sizeof(DriverName); + + if (String) + RtlCopyMemory(pString, String, StringSize); + + IoWriteErrorLogEntry(LogEntry); + } +#endif +} + + +NTSTATUS TiGetProtocolNumber( + PUNICODE_STRING FileName, + PULONG Protocol) +/* + * FUNCTION: Returns the protocol number from a file name + * ARGUMENTS: + * FileName = Pointer to string with file name + * Protocol = Pointer to buffer to put protocol number in + * RETURNS: + * Status of operation + */ +{ + UNICODE_STRING us; + NTSTATUS Status; + ULONG Value; + PWSTR Name; + + TI_DbgPrint(MAX_TRACE, ("Called. FileName (%wZ).\n", FileName)); + + Name = FileName->Buffer; + + if (*Name++ != (WCHAR)L'\\') + return STATUS_UNSUCCESSFUL; + + if (*Name == (WCHAR)NULL) + return STATUS_UNSUCCESSFUL; + + RtlInitUnicodeString(&us, Name); + + Status = RtlUnicodeStringToInteger(&us, 10, &Value); + if (!NT_SUCCESS(Status) || ((Value > 255))) + return STATUS_UNSUCCESSFUL; + + *Protocol = Value; + + return STATUS_SUCCESS; +} + + +/* + * FUNCTION: Creates a file object + * ARGUMENTS: + * DeviceObject = Pointer to a device object for this driver + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of the operation + */ +NTSTATUS TiCreateFileObject( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PFILE_FULL_EA_INFORMATION EaInfo; + PTRANSPORT_CONTEXT Context; + PIO_STACK_LOCATION IrpSp; + PTA_ADDRESS_IP Address; + TDI_REQUEST Request; + PVOID ClientContext; + NTSTATUS Status; + ULONG Protocol; + + TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp)); + + EaInfo = Irp->AssociatedIrp.SystemBuffer; +CP + /* Parameter check */ + if (!EaInfo) { + TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n")); + return STATUS_INVALID_PARAMETER; + } +CP + /* Allocate resources here. We release them again if something failed */ + Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT)); + if (!Context) { + TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } +CP + Context->RefCount = 1; + Context->CancelIrps = FALSE; + KeInitializeEvent(&Context->CleanupEvent, NotificationEvent, FALSE); +CP + IrpSp = IoGetCurrentIrpStackLocation(Irp); + IrpSp->FileObject->FsContext = Context; + Request.RequestContext = Irp; +CP + /* Branch to the right handler */ + if ((EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) && + (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress, + TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) { + /* This is a request to open an address */ +CP + /* Parameter checks */ + Address = (PTA_ADDRESS_IP)(EaInfo->EaName + EaInfo->EaNameLength); + if ((EaInfo->EaValueLength < sizeof(TA_ADDRESS_IP)) || + (Address->TAAddressCount != 1) || + (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) || + (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP)) { + TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n")); + ExFreePool(Context); + return STATUS_INVALID_PARAMETER; + } +CP + /* Open address file object */ + + /* Protocol depends on device object so find the protocol */ + if (DeviceObject == TCPDeviceObject) + Protocol = IPPROTO_TCP; + else if (DeviceObject == UDPDeviceObject) + Protocol = IPPROTO_UDP; + else if (DeviceObject == IPDeviceObject) + Protocol = IPPROTO_RAW; + else if (DeviceObject == RawIPDeviceObject) { + Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n")); + ExFreePool(Context); + return STATUS_INVALID_PARAMETER; + } + } else { + TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject)); + ExFreePool(Context); + return STATUS_INVALID_PARAMETER; + } +CP + Status = FileOpenAddress(&Request, Address, Protocol, NULL); + if (NT_SUCCESS(Status)) { + IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE; + Context->Handle.AddressHandle = Request.Handle.AddressHandle; + } +CP + } else if ((EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) && + (RtlCompareMemory(&EaInfo->EaName, TdiConnectionContext, + TDI_CONNECTION_CONTEXT_LENGTH) == TDI_CONNECTION_CONTEXT_LENGTH)) { + /* This is a request to open a connection endpoint */ +CP + /* Parameter checks */ + + if (EaInfo->EaValueLength < sizeof(PVOID)) { + TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n")); + ExFreePool(Context); + return STATUS_INVALID_PARAMETER; + } + + /* Can only do connection oriented communication using TCP */ + + if (DeviceObject != TCPDeviceObject) { + TI_DbgPrint(MIN_TRACE, ("Bad device object.\n")); + ExFreePool(Context); + return STATUS_INVALID_PARAMETER; + } + + ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength)); + + /* Open connection endpoint file object */ + + Status = FileOpenConnection(&Request, ClientContext); + if (NT_SUCCESS(Status)) { + IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE; + Context->Handle.ConnectionContext = Request.Handle.ConnectionContext; + } + } else { + /* This is a request to open a control connection */ + + TI_DbgPrint(MIN_TRACE, ("Control connections are not implemented yet\n")); + + Status = STATUS_NOT_IMPLEMENTED; + } + + if (!NT_SUCCESS(Status)) + ExFreePool(Context); + + TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status)); + + return Status; +} + + +VOID TiCleanupFileObjectComplete( + PVOID Context, + NTSTATUS Status) +/* + * FUNCTION: Completes an object cleanup IRP I/O request + * ARGUMENTS: + * Context = Pointer to the IRP for this request + * Status = Final status of the operation + */ +{ + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + PTRANSPORT_CONTEXT TranContext; + KIRQL OldIrql; + + Irp = (PIRP)Context; + IrpSp = IoGetCurrentIrpStackLocation(Irp); + TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; + + Irp->IoStatus.Status = Status; + + IoAcquireCancelSpinLock(&OldIrql); + + /* Remove the initial reference provided at object creation time */ + TranContext->RefCount--; + +#ifdef DBG + if (TranContext->RefCount != 0) + TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount is %i, should be 0.\n", TranContext->RefCount)); +#endif + + KeSetEvent(&TranContext->CleanupEvent, 0, FALSE); + + IoReleaseCancelSpinLock(OldIrql); +} + + +/* + * FUNCTION: Releases resources used by a file object + * ARGUMENTS: + * DeviceObject = Pointer to a device object for this driver + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of the operation + * NOTES: + * This function does not pend + */ +NTSTATUS TiCleanupFileObject( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp; + PTRANSPORT_CONTEXT Context; + TDI_REQUEST Request; + NTSTATUS Status; + KIRQL OldIrql; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + Context = IrpSp->FileObject->FsContext; + if (!Context) { + TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n")); + return STATUS_INVALID_PARAMETER; + } + + IoAcquireCancelSpinLock(&OldIrql); + + Context->CancelIrps = TRUE; + KeResetEvent(&Context->CleanupEvent); + + IoReleaseCancelSpinLock(OldIrql); + + Request.RequestNotifyObject = TiCleanupFileObjectComplete; + Request.RequestContext = Irp; + + switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) { + case TDI_TRANSPORT_ADDRESS_FILE: + Request.Handle.AddressHandle = Context->Handle.AddressHandle; + Status = FileCloseAddress(&Request); + break; + + case TDI_CONNECTION_FILE: + Request.Handle.ConnectionContext = Context->Handle.ConnectionContext; + Status = FileCloseConnection(&Request); + break; + + case TDI_CONTROL_CHANNEL_FILE: + Request.Handle.ControlChannel = Context->Handle.ControlChannel; + Status = FileCloseControlChannel(&Request); + break; + + default: + /* This should never happen */ + + TI_DbgPrint(MIN_TRACE, ("Unknown transport context.\n")); + + IoAcquireCancelSpinLock(&OldIrql); + Context->CancelIrps = FALSE; + IoReleaseCancelSpinLock(OldIrql); + + return STATUS_INVALID_PARAMETER; + } + + if (Status != STATUS_PENDING) + TiCleanupFileObjectComplete(Irp, Status); + + KeWaitForSingleObject(&Context->CleanupEvent, + UserRequest, KernelMode, FALSE, NULL); + + return Irp->IoStatus.Status; +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +TiDispatchOpenClose( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Main dispath routine + * ARGUMENTS: + * DeviceObject = Pointer to a device object for this driver + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of the operation + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + PTRANSPORT_CONTEXT Context; + + TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp)); + + IoMarkIrpPending(Irp); + Irp->IoStatus.Status = STATUS_PENDING; + Irp->IoStatus.Information = 0; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MajorFunction) { + /* Open an address file, connection endpoint, or control connection */ + case IRP_MJ_CREATE: + Status = TiCreateFileObject(DeviceObject, Irp); + break; + + /* Close an address file, connection endpoint, or control connection */ + case IRP_MJ_CLOSE: + Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext; + if (Context) + ExFreePool(Context); + Status = STATUS_SUCCESS; + break; + + /* Release resources bound to an address file, connection endpoint, + or control connection */ + case IRP_MJ_CLEANUP: + Status = TiCleanupFileObject(DeviceObject, Irp); + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + if (Status != STATUS_PENDING) { + IrpSp->Control &= ~SL_PENDING_RETURNED; + Irp->IoStatus.Status = Status; + + TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + } + + TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); + + return Status; +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +TiDispatchInternal( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Internal IOCTL dispatch routine + * ARGUMENTS: + * DeviceObject = Pointer to a device object for this driver + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of the operation + */ +{ + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n", + DeviceObject, Irp, IrpSp->MinorFunction)); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + switch (IrpSp->MinorFunction) { + case TDI_RECEIVE: + Status = DispTdiReceive(Irp); + break; + + case TDI_RECEIVE_DATAGRAM: + Status = DispTdiReceiveDatagram(Irp); + break; + + case TDI_SEND: + Status = DispTdiSend(Irp); + break; + + case TDI_SEND_DATAGRAM: + Status = DispTdiSendDatagram(Irp); + break; + + case TDI_ACCEPT: + Status = DispTdiAccept(Irp); + break; + + case TDI_LISTEN: + Status = DispTdiListen(Irp); + break; + + case TDI_CONNECT: + Status = DispTdiConnect(Irp); + break; + + case TDI_DISCONNECT: + Status = DispTdiDisconnect(Irp); + break; + + case TDI_ASSOCIATE_ADDRESS: + Status = DispTdiAssociateAddress(Irp); + break; + + case TDI_DISASSOCIATE_ADDRESS: + Status = DispTdiDisassociateAddress(Irp); + break; + + case TDI_QUERY_INFORMATION: + Status = DispTdiQueryInformation(DeviceObject, Irp); + break; + + case TDI_SET_INFORMATION: + Status = DispTdiSetInformation(Irp); + break; + + case TDI_SET_EVENT_HANDLER: + Status = DispTdiSetEventHandler(Irp); + break; + + case TDI_ACTION: + Status = STATUS_SUCCESS; + break; + + /* An unsupported IOCTL code was submitted */ + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + + TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + } + + TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +TiDispatch( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests + * ARGUMENTS: + * DeviceObject = Pointer to a device object for this driver + * Irp = Pointer to a I/O request packet + * RETURNS: + * Status of the operation + */ +{ + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + + TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp)); + + Irp->IoStatus.Information = 0; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); +#ifdef _MSC_VER + Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp); + if (NT_SUCCESS(Status)) { + TiDispatchInternal(DeviceObject, Irp); + Status = STATUS_PENDING; + } else { +#else + if (TRUE) { +#endif + /* See if this request is TCP/IP specific */ + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { + case IOCTL_TCP_QUERY_INFORMATION_EX: + Status = DispTdiQueryInformationEx(Irp, IrpSp); + break; + + case IOCTL_TCP_SET_INFORMATION_EX: + Status = DispTdiSetInformationEx(Irp, IrpSp); + break; + + default: + TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n", + IrpSp->Parameters.DeviceIoControl.IoControlCode)); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + + TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp)); + + IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + } + + TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status)); + + return Status; +} + + +VOID TiUnload( + PDRIVER_OBJECT DriverObject) +/* + * FUNCTION: Unloads the driver + * ARGUMENTS: + * DriverObject = Pointer to driver object created by the system + */ +{ +#ifdef DBG + KIRQL OldIrql; + + KeAcquireSpinLock(&AddressFileListLock, &OldIrql); + if (!IsListEmpty(&AddressFileListHead)) { + TI_DbgPrint(MIN_TRACE, ("Open address file objects exists.\n")); + } + KeReleaseSpinLock(&AddressFileListLock, OldIrql); +#endif + + /* Unregister loopback adapter */ + LoopUnregisterAdapter(NULL); + + /* Unregister protocol with NDIS */ + LANUnregisterProtocol(); + + /* Shutdown transport level protocol subsystems */ + TCPShutdown(); + UDPShutdown(); + RawIPShutdown(); + DGShutdown(); + + /* Shutdown network level protocol subsystem */ + IPShutdown(); + + /* Free NDIS buffer descriptors */ + if (GlobalBufferPool) + NdisFreeBufferPool(GlobalBufferPool); + + /* Free NDIS packet descriptors */ + if (GlobalPacketPool) + NdisFreePacketPool(GlobalPacketPool); + + /* Release all device objects */ + + if (TCPDeviceObject) + IoDeleteDevice(TCPDeviceObject); + + if (UDPDeviceObject) + IoDeleteDevice(UDPDeviceObject); + + if (RawIPDeviceObject) + IoDeleteDevice(RawIPDeviceObject); + + if (IPDeviceObject) + IoDeleteDevice(IPDeviceObject); + + if (EntityList) + ExFreePool(EntityList); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Main driver entry point + * ARGUMENTS: + * DriverObject = Pointer to a driver object for this driver + * RegistryPath = Registry node for configuration parameters + * RETURNS: + * Status of driver initialization + */ +{ + NTSTATUS Status; + UNICODE_STRING strDeviceName; + STRING strNdisDeviceName; + NDIS_STATUS NdisStatus; + PLAN_ADAPTER Adapter; + NDIS_STRING DeviceName; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* FIXME: Create symbolic links in Win32 namespace */ + + /* Create IP device object */ + RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_IP_DEVICE_NAME); + Status = IoCreateDevice(DriverObject, 0, &strDeviceName, + FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status)); + return Status; + } + + /* Create RawIP device object */ + RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_RAWIP_DEVICE_NAME); + Status = IoCreateDevice(DriverObject, 0, &strDeviceName, + FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status)); + TiUnload(DriverObject); + return Status; + } + + /* Create UDP device object */ + RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_UDP_DEVICE_NAME); + Status = IoCreateDevice(DriverObject, 0, &strDeviceName, + FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status)); + TiUnload(DriverObject); + return Status; + } + + /* Create TCP device object */ + RtlInitUnicodeStringFromLiteral(&strDeviceName, DD_TCP_DEVICE_NAME); + Status = IoCreateDevice(DriverObject, 0, &strDeviceName, + FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject); + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status)); + TiUnload(DriverObject); + return Status; + } + + /* Allocate NDIS packet descriptors */ + NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT)); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TiUnload(DriverObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Allocate NDIS buffer descriptors */ + NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TiUnload(DriverObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Initialize address file list and protecting spin lock */ + InitializeListHead(&AddressFileListHead); + KeInitializeSpinLock(&AddressFileListLock); + + /* Initialize connection endpoint list and protecting spin lock */ + InitializeListHead(&ConnectionEndpointListHead); + KeInitializeSpinLock(&ConnectionEndpointListLock); + + /* Initialize interface list and protecting spin lock */ + InitializeListHead(&InterfaceListHead); + KeInitializeSpinLock(&InterfaceListLock); + + /* Initialize network level protocol subsystem */ + IPStartup(DriverObject, RegistryPath); + + /* Initialize transport level protocol subsystems */ + DGStartup(); + RawIPStartup(); + UDPStartup(); + TCPStartup(); + + /* Register protocol with NDIS */ + RtlInitString(&strNdisDeviceName, IP_DEVICE_NAME); + Status = LANRegisterProtocol(&strNdisDeviceName); + if (!NT_SUCCESS(Status)) { + TiWriteErrorLog( + DriverObject, + EVENT_TRANSPORT_REGISTER_FAILED, + TI_ERROR_DRIVERENTRY, + Status, + NULL, + 0, + NULL); + TiUnload(DriverObject); + return Status; + } + + /* Open loopback adapter */ + if (!NT_SUCCESS(LoopRegisterAdapter(NULL, NULL))) { + TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status)); + TiUnload(DriverObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + +/* Open underlying adapter(s) we are bound to */ + + /* FIXME: Get binding information from registry */ + + /* Put your own NDIS adapter device name here */ +#ifdef _USE_NE2000 + /* ReactOS */ + NdisInitUnicodeString(&DeviceName, L"\\Device\\ne2000"); + + /* NT4 style */ + //NdisInitUnicodeString(&DeviceName, L"\\Device\\El90x1"); + + /* NT5 style */ + //NdisInitUnicodeString(&DeviceName, L"\\Device\\{56388B49-67BB-4419-A3F4-28DF190B9149}"); + + NdisStatus = LANRegisterAdapter(&DeviceName, &Adapter); + + /* Skip network adapter if it does not exist */ + if (!NT_SUCCESS(NdisStatus)) { + TI_DbgPrint(MIN_TRACE, ("Failed to intialize adapter. Status (0x%X).\n", Status)); + TiWriteErrorLog( + DriverObject, + EVENT_TRANSPORT_ADAPTER_NOT_FOUND, + TI_ERROR_DRIVERENTRY, + NdisStatus, + NULL, + 0, + NULL); + TiUnload(DriverObject); + return STATUS_DEVICE_DOES_NOT_EXIST; + } +#endif + /* Setup network layer and transport layer entities */ + EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * 2); + if (!NT_SUCCESS(Status)) { + TiUnload(DriverObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + EntityList[0].tei_entity = CL_NL_ENTITY; + EntityList[0].tei_instance = 0; + EntityList[1].tei_entity = CL_TL_ENTITY; + EntityList[1].tei_instance = 0; + EntityCount = 2; + + /* Use direct I/O */ + IPDeviceObject->Flags |= DO_DIRECT_IO; + RawIPDeviceObject->Flags |= DO_DIRECT_IO; + UDPDeviceObject->Flags |= DO_DIRECT_IO; + TCPDeviceObject->Flags |= DO_DIRECT_IO; + + /* Initialize the driver object with this driver's entry points */ + DriverObject->MajorFunction[IRP_MJ_CREATE] = TiDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = TiDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TiDispatchOpenClose; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch; + + DriverObject->DriverUnload = (PDRIVER_UNLOAD)TiUnload; + + return STATUS_SUCCESS; +} + + +VOID +#ifndef _MSC_VER +STDCALL +#endif +IPAddInterface( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED +} + + +VOID +#ifndef _MSC_VER +STDCALL +#endif +IPDelInterface( + DWORD Unknown0) +{ + UNIMPLEMENTED +} + + +VOID +#ifndef _MSC_VER +STDCALL +#endif +LookupRoute( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/pool.c b/drivers/net/tcpip/tcpip/pool.c new file mode 100644 index 0000000..ca67822 --- /dev/null +++ b/drivers/net/tcpip/tcpip/pool.c @@ -0,0 +1,50 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/pool.c + * PURPOSE: Routines for controling pools + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include + + +PVOID PoolAllocateBuffer( + ULONG Size) +/* + * FUNCTION: Returns a buffer from the free buffer pool + * RETURNS: + * Pointer to buffer, NULL if there was not enough + * free resources + */ +{ + PVOID Buffer; + + /* FIXME: Get buffer from a free buffer pool with enough room */ + + Buffer = ExAllocatePool(NonPagedPool, Size); + + TI_DbgPrint(DEBUG_MEMORY, ("Allocated (%i) bytes at (0x%X).\n", Size, Buffer)); + + return Buffer; +} + + +VOID PoolFreeBuffer( + PVOID Buffer) +/* + * FUNCTION: Returns a buffer to the free buffer pool + * ARGUMENTS: + * Buffer = Buffer to return to free buffer pool + */ +{ + /* FIXME: Put buffer in free buffer pool */ + + TI_DbgPrint(DEBUG_MEMORY, ("Freeing buffer at (0x%X).\n", Buffer)); + + ExFreePool(Buffer); +} + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/resource.rc b/drivers/net/tcpip/tcpip/resource.rc new file mode 100644 index 0000000..a5c8ca5 --- /dev/null +++ b/drivers/net/tcpip/tcpip/resource.rc @@ -0,0 +1,10 @@ +#include +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_NETWORK +#define VER_FILEDESCRIPTION_STR "TCP/IP protocol driver" +#define VER_INTERNALNAME_STR "TCPIP.SYS" +#define VER_ORIGINALFILENAME_STR "TCPIP.SYS" + +#include "common.ver" diff --git a/drivers/net/tcpip/tcpip/routines.c b/drivers/net/tcpip/tcpip/routines.c new file mode 100644 index 0000000..edbb297 --- /dev/null +++ b/drivers/net/tcpip/tcpip/routines.c @@ -0,0 +1,533 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: tcpip/routines.c + * PURPOSE: Common routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include + + +UINT RandomNumber = 0x12345678; + + +inline NTSTATUS BuildDatagramSendRequest( + PDATAGRAM_SEND_REQUEST *SendRequest, + PIP_ADDRESS RemoteAddress, + USHORT RemotePort, + PNDIS_BUFFER Buffer, + DWORD BufferSize, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + DATAGRAM_BUILD_ROUTINE Build, + ULONG Flags) +/* + * FUNCTION: Allocates and intializes a datagram send request + * ARGUMENTS: + * SendRequest = Pointer to datagram send request + * RemoteAddress = Pointer to remote IP address + * RemotePort = Remote port number + * Buffer = Pointer to NDIS buffer to send + * BufferSize = Size of Buffer + * Complete = Completion routine + * Context = Pointer to context information + * Build = Datagram build routine + * Flags = Protocol specific flags + * RETURNS: + * Status of operation + */ +{ + PDATAGRAM_SEND_REQUEST Request; + + Request = ExAllocatePool(NonPagedPool, sizeof(DATAGRAM_SEND_REQUEST)); + if (!Request) + return STATUS_INSUFFICIENT_RESOURCES; + + InitializeDatagramSendRequest( + Request, + RemoteAddress, + RemotePort, + Buffer, + BufferSize, + Complete, + Context, + Build, + Flags); + + *SendRequest = Request; + + return STATUS_SUCCESS; +} + + +inline NTSTATUS BuildTCPSendRequest( + PTCP_SEND_REQUEST *SendRequest, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + PVOID ProtocolContext) +/* + * FUNCTION: Allocates and intializes a TCP send request + * ARGUMENTS: + * SendRequest = Pointer to TCP send request + * Complete = Completion routine + * Context = Pointer to context information + * ProtocolContext = Protocol specific context + * RETURNS: + * Status of operation + */ +{ + PTCP_SEND_REQUEST Request; + + Request = ExAllocatePool(NonPagedPool, sizeof(TCP_SEND_REQUEST)); + if (!Request) + return STATUS_INSUFFICIENT_RESOURCES; + + InitializeTCPSendRequest( + Request, + Complete, + Context, + ProtocolContext); + + *SendRequest = Request; + + return STATUS_SUCCESS; +} + + +UINT Random( + VOID) +/* + * FUNCTION: Returns a pseudo random number + * RETURNS: + * Pseudo random number + */ +{ + RandomNumber ^= 0x78563412; + + return RandomNumber; +} + + +__inline INT SkipToOffset( + PNDIS_BUFFER Buffer, + UINT Offset, + PUCHAR *Data, + PUINT Size) +/* + * FUNCTION: Skip Offset bytes into a buffer chain + * ARGUMENTS: + * Buffer = Pointer to NDIS buffer + * Offset = Number of bytes to skip + * Data = Address of a pointer that on return will contain the + * address of the offset in the buffer + * Size = Address of a pointer that on return will contain the + * size of the destination buffer + * RETURNS: + * Offset into buffer, -1 if buffer chain was smaller than Offset bytes + * NOTES: + * Buffer may be NULL + */ +{ + for (;;) { + + if (!Buffer) + return -1; + + NdisQueryBuffer(Buffer, Data, Size); + + if (Offset < *Size) { + ((ULONG_PTR)*Data) += Offset; + *Size -= Offset; + break; + } + + Offset -= *Size; + + NdisGetNextBuffer(Buffer, &Buffer); + } + + return Offset; +} + + +UINT CopyBufferToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PUCHAR SrcData, + UINT Length) +/* + * FUNCTION: Copies data from a buffer to an NDIS buffer chain + * ARGUMENTS: + * DstBuffer = Pointer to destination NDIS buffer + * DstOffset = Destination start offset + * SrcData = Pointer to source buffer + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the destination + * buffer size + */ +{ + UINT BytesCopied, BytesToCopy, DstSize; + PUCHAR DstData; + + TI_DbgPrint(DEBUG_BUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length)); + + /* Skip DstOffset bytes in the destination buffer chain */ + if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) + return 0; + + /* Start copying the data */ + BytesCopied = 0; + for (;;) { + BytesToCopy = MIN(DstSize, Length); + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); + BytesCopied += BytesToCopy; + (ULONG_PTR)SrcData += BytesToCopy; + + Length -= BytesToCopy; + if (Length == 0) + break; + + DstSize -= BytesToCopy; + if (DstSize == 0) { + /* No more bytes in desination buffer. Proceed to + the next buffer in the destination buffer chain */ + NdisGetNextBuffer(DstBuffer, &DstBuffer); + if (!DstBuffer) + break; + + NdisQueryBuffer(DstBuffer, &DstData, &DstSize); + } + } + + return BytesCopied; +} + + +UINT CopyBufferChainToBuffer( + PUCHAR DstData, + PNDIS_BUFFER SrcBuffer, + UINT SrcOffset, + UINT Length) +/* + * FUNCTION: Copies data from an NDIS buffer chain to a buffer + * ARGUMENTS: + * DstData = Pointer to destination buffer + * SrcBuffer = Pointer to source NDIS buffer + * SrcOffset = Source start offset + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the source + * buffer size + */ +{ + UINT BytesCopied, BytesToCopy, SrcSize; + PUCHAR SrcData; + + TI_DbgPrint(DEBUG_BUFFER, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length)); + + /* Skip SrcOffset bytes in the source buffer chain */ + if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) + return 0; + + /* Start copying the data */ + BytesCopied = 0; + for (;;) { + BytesToCopy = MIN(SrcSize, Length); + + TI_DbgPrint(DEBUG_BUFFER, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData)); + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); + BytesCopied += BytesToCopy; + (ULONG_PTR)DstData += BytesToCopy; + + Length -= BytesToCopy; + if (Length == 0) + break; + + SrcSize -= BytesToCopy; + if (SrcSize == 0) { + /* No more bytes in source buffer. Proceed to + the next buffer in the source buffer chain */ + NdisGetNextBuffer(SrcBuffer, &SrcBuffer); + if (!SrcBuffer) + break; + + NdisQueryBuffer(SrcBuffer, &SrcData, &SrcSize); + } + } + + return BytesCopied; +} + + +UINT CopyPacketToBuffer( + PUCHAR DstData, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length) +/* + * FUNCTION: Copies data from an NDIS packet to a buffer + * ARGUMENTS: + * DstData = Pointer to destination buffer + * SrcPacket = Pointer to source NDIS packet + * SrcOffset = Source start offset + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the source + * buffer size + */ +{ + PNDIS_BUFFER FirstBuffer; + PVOID Address; + UINT FirstLength; + UINT TotalLength; + + TI_DbgPrint(DEBUG_BUFFER, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length)); + + NdisGetFirstBufferFromPacket(SrcPacket, + &FirstBuffer, + &Address, + &FirstLength, + &TotalLength); + + return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length); +} + + +UINT CopyPacketToBufferChain( + PNDIS_BUFFER DstBuffer, + UINT DstOffset, + PNDIS_PACKET SrcPacket, + UINT SrcOffset, + UINT Length) +/* + * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain + * ARGUMENTS: + * DstBuffer = Pointer to destination NDIS buffer + * DstOffset = Destination start offset + * SrcPacket = Pointer to source NDIS packet + * SrcOffset = Source start offset + * Length = Number of bytes to copy + * RETURNS: + * Number of bytes copied to destination buffer + * NOTES: + * The number of bytes copied may be limited by the source and + * destination buffer sizes + */ +{ + PNDIS_BUFFER SrcBuffer; + PUCHAR DstData, SrcData; + UINT DstSize, SrcSize; + UINT Count, Total; + + TI_DbgPrint(DEBUG_BUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length)); + + /* Skip DstOffset bytes in the destination buffer chain */ + NdisQueryBuffer(DstBuffer, &DstData, &DstSize); + if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) + return 0; + + /* Skip SrcOffset bytes in the source packet */ + NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, &SrcData, &SrcSize, &Total); + if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) + return 0; + + /* Copy the data */ + for (Total = 0;;) { + /* Find out how many bytes we can copy at one time */ + if (Length < SrcSize) + Count = Length; + else + Count = SrcSize; + if (DstSize < Count) + Count = DstSize; + + RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); + + Total += Count; + Length -= Count; + if (Length == 0) + break; + + DstSize -= Count; + if (DstSize == 0) { + /* No more bytes in destination buffer. Proceed to + the next buffer in the destination buffer chain */ + NdisGetNextBuffer(DstBuffer, &DstBuffer); + if (!DstBuffer) + break; + + NdisQueryBuffer(DstBuffer, &DstData, &DstSize); + } + + SrcSize -= Count; + if (SrcSize == 0) { + /* No more bytes in source buffer. Proceed to + the next buffer in the source buffer chain */ + NdisGetNextBuffer(SrcBuffer, &SrcBuffer); + if (!SrcBuffer) + break; + + NdisQueryBuffer(SrcBuffer, &SrcData, &SrcSize); + } + } + + return Total; +} + + +VOID FreeNdisPacket( + PNDIS_PACKET Packet) +/* + * FUNCTION: Frees an NDIS packet + * ARGUMENTS: + * Packet = Pointer to NDIS packet to be freed + */ +{ + PNDIS_BUFFER Buffer, NextBuffer; + + TI_DbgPrint(DEBUG_BUFFER, ("Packet (0x%X)\n", Packet)); + + /* Free all the buffers in the packet first */ + NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL); + for (; Buffer != NULL; Buffer = NextBuffer) { + PVOID Data; + UINT Length; + + NdisGetNextBuffer(Buffer, &NextBuffer); + NdisQueryBuffer(Buffer, &Data, &Length); + NdisFreeBuffer(Buffer); + ExFreePool(Data); + } + + /* Finally free the NDIS packet discriptor */ + NdisFreePacket(Packet); +} + + +PVOID AdjustPacket( + PNDIS_PACKET Packet, + UINT Available, + UINT Needed) +/* + * FUNCTION: Adjusts the amount of unused space at the beginning of the packet + * ARGUMENTS: + * Packet = Pointer to packet + * Available = Number of bytes available at start of first buffer + * Needed = Number of bytes needed for the header + * RETURNS: + * Pointer to start of packet + */ +{ + PNDIS_BUFFER NdisBuffer; + INT Adjust; + + TI_DbgPrint(DEBUG_BUFFER, ("Available = %d, Needed = %d.\n", Available, Needed)); + + Adjust = Available - Needed; + + NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL); + + /* If Adjust is zero there is no need to adjust this packet as + there is no additional space at start the of first buffer */ + if (Adjust != 0) { + (ULONG_PTR)(NdisBuffer->MappedSystemVa) += Adjust; + NdisBuffer->ByteOffset += Adjust; + NdisBuffer->ByteCount -= Adjust; + } + + return NdisBuffer->MappedSystemVa; +} + + +UINT ResizePacket( + PNDIS_PACKET Packet, + UINT Size) +/* + * FUNCTION: Resizes an NDIS packet + * ARGUMENTS: + * Packet = Pointer to packet + * Size = Number of bytes in first buffer + * RETURNS: + * Previous size of first buffer + */ +{ + PNDIS_BUFFER NdisBuffer; + UINT OldSize; + + NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL); + + OldSize = NdisBuffer->ByteCount; + + if (Size != OldSize) + NdisBuffer->ByteCount = Size; + + return OldSize; +} + +#ifdef DBG + +VOID DisplayIPPacket( + PIP_PACKET IPPacket) +{ + UINT i; + PCHAR p; + UINT Length; + PNDIS_BUFFER Buffer; + PNDIS_BUFFER NextBuffer; + + if ((DebugTraceLevel & DEBUG_BUFFER) == 0) { + return; + } + + if (!IPPacket) { + TI_DbgPrint(MIN_TRACE, ("Cannot display null packet.\n")); + return; + } + + TI_DbgPrint(MIN_TRACE, ("IPPacket is at (0x%X).\n", IPPacket)); + TI_DbgPrint(MIN_TRACE, ("Header buffer is at (0x%X).\n", IPPacket->Header)); + TI_DbgPrint(MIN_TRACE, ("Header size is (%d).\n", IPPacket->HeaderSize)); + TI_DbgPrint(MIN_TRACE, ("TotalSize (%d).\n", IPPacket->TotalSize)); + TI_DbgPrint(MIN_TRACE, ("ContigSize (%d).\n", IPPacket->ContigSize)); + TI_DbgPrint(MIN_TRACE, ("NdisPacket (0x%X).\n", IPPacket->NdisPacket)); + + if (IPPacket->NdisPacket) { + NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, &Buffer, NULL); + for (; Buffer != NULL; Buffer = NextBuffer) { + NdisGetNextBuffer(Buffer, &NextBuffer); + NdisQueryBuffer(Buffer, (PVOID)&p, &Length); + + for (i = 0; i < Length; i++) { + if (i % 16 == 0) + DbgPrint("\n"); + DbgPrint("%02X ", (p[i]) & 0xFF); + } + DbgPrint("\n"); + } + } else { + p = IPPacket->Header; + Length = IPPacket->ContigSize; + for (i = 0; i < Length; i++) { + if (i % 16 == 0) + DbgPrint("\n"); + DbgPrint("%02X ", (p[i]) & 0xFF); + } + DbgPrint("\n"); + } +} +#endif /* DBG */ + +/* EOF */ diff --git a/drivers/net/tcpip/tcpip/tcpip.def b/drivers/net/tcpip/tcpip/tcpip.def new file mode 100644 index 0000000..136ec91 --- /dev/null +++ b/drivers/net/tcpip/tcpip/tcpip.def @@ -0,0 +1,32 @@ +; TCPIP.SYS - TCP/IP protocol driver + +LIBRARY tcpip.sys + +EXPORTS +;FreeIprBuff +;GetIFAndLink +IPAddInterface +;IPAllocBuff +IPDelInterface +;IPDelayedNdisReEnumerateBindings +;IPDeregisterARP +;IPDisableSniffer +;IPEnableSniffer +;IPFreeBuff +;IPGetAddrType +;IPGetBestInterface +;IPGetInfo +;IPInjectPkt +;IPProxyNdisRequest +;IPRegisterARP +;IPRegisterProtocol +;IPSetIPSecStatus +;IPTransmit +LookupRoute +;LookupRouteInformation +;SendICMPErr +;SetIPSecPtr +;UnSetIPSecPtr +;UnSetIPSecSendPtr + +; EOF diff --git a/drivers/net/tcpip/transport/DIRS b/drivers/net/tcpip/transport/DIRS new file mode 100644 index 0000000..4ff3f7f --- /dev/null +++ b/drivers/net/tcpip/transport/DIRS @@ -0,0 +1,5 @@ +DIRS= datagram \ + rawip \ + tcp \ + udp + diff --git a/drivers/net/tcpip/transport/datagram/Makefile b/drivers/net/tcpip/transport/datagram/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/transport/datagram/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/transport/datagram/SOURCES b/drivers/net/tcpip/transport/datagram/SOURCES new file mode 100644 index 0000000..50cbe51 --- /dev/null +++ b/drivers/net/tcpip/transport/datagram/SOURCES @@ -0,0 +1,13 @@ +TARGETNAME=datagram +TARGETPATH=..\..\objects +TARGETTYPE=LIBRARY + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +INCLUDES=..\..\include;$(BASEDIR)\INC;..\..\..\..\..\include\net + +SOURCES= datagram.c + +MSC_WARNING_LEVEL=/W3 /WX + diff --git a/drivers/net/tcpip/transport/datagram/datagram.c b/drivers/net/tcpip/transport/datagram/datagram.c new file mode 100644 index 0000000..7c3a689 --- /dev/null +++ b/drivers/net/tcpip/transport/datagram/datagram.c @@ -0,0 +1,681 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: transport/datagram/datagram.c + * PURPOSE: Routines for sending and receiving datagrams + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include + + +/* Pending request queue */ +LIST_ENTRY DGPendingListHead; +KSPIN_LOCK DGPendingListLock; +/* Work queue item for pending requests */ +WORK_QUEUE_ITEM DGWorkItem; + + +VOID DatagramWorker( + PVOID Context) +/* + * FUNCTION: Handles pending send requests + * ARGUMENTS: + * Context = Pointer to context information (unused) + * NOTES: + * This routine is called after the driver has run out of resources. + * It processes send requests or shedules them to be processed + */ +{ + PLIST_ENTRY CurrentADFEntry; + PLIST_ENTRY CurrentSREntry; + PADDRESS_FILE CurrentADF; + PDATAGRAM_SEND_REQUEST CurrentSR; + KIRQL OldIrql1; + KIRQL OldIrql2; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeAcquireSpinLock(&DGPendingListLock, &OldIrql1); + + CurrentADFEntry = DGPendingListHead.Flink; + while (CurrentADFEntry != &DGPendingListHead) { + RemoveEntryList(CurrentADFEntry); + CurrentADF = CONTAINING_RECORD(CurrentADFEntry, + ADDRESS_FILE, + ListEntry); + + KeAcquireSpinLock(&CurrentADF->Lock, &OldIrql2); + + if (AF_IS_BUSY(CurrentADF)) { + /* The send worker function is already running so we just + set the pending send flag on the address file object */ + + AF_SET_PENDING(CurrentADF, AFF_SEND); + KeReleaseSpinLock(&CurrentADF->Lock, OldIrql2); + } else { + if (!IsListEmpty(&CurrentADF->TransmitQueue)) { + /* The transmit queue is not empty. Dequeue a send + request and process it */ + + CurrentSREntry = RemoveHeadList(&CurrentADF->TransmitQueue); + CurrentSR = CONTAINING_RECORD(CurrentADFEntry, + DATAGRAM_SEND_REQUEST, + ListEntry); + + KeReleaseSpinLock(&CurrentADF->Lock, OldIrql2); + + DGSend(CurrentADF, CurrentSR); + } else + KeReleaseSpinLock(&CurrentADF->Lock, OldIrql2); + } + CurrentADFEntry = CurrentADFEntry->Flink; + } + + KeReleaseSpinLock(&DGPendingListLock, OldIrql1); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID SendDatagramComplete( + PVOID Context, + PNDIS_PACKET Packet, + NDIS_STATUS NdisStatus) +/* + * FUNCTION: Datagram transmit completion handler + * ARGUMENTS: + * Context = Pointer to context infomation (DATAGRAM_SEND_REQUEST) + * Packet = Pointer to NDIS packet + * NdisStatus = Status of transmit operation + * NOTES: + * This routine is called by IP when a datagram send completes. + * We shedule the out-of-resource worker function if there + * are pending address files in the queue + */ +{ + KIRQL OldIrql; + ULONG BytesSent; + PVOID CompleteContext; + PNDIS_BUFFER NdisBuffer; + PDATAGRAM_SEND_REQUEST SendRequest; + DATAGRAM_COMPLETION_ROUTINE Complete; + BOOLEAN QueueWorkItem; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + SendRequest = (PDATAGRAM_SEND_REQUEST)Context; + Complete = SendRequest->Complete; + CompleteContext = SendRequest->Context; + BytesSent = SendRequest->BufferSize; + + /* Remove data buffer before releasing memory for packet buffers */ + NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL); + NdisUnchainBufferAtBack(Packet, &NdisBuffer); + FreeNdisPacket(Packet); + DereferenceObject(SendRequest->RemoteAddress); + ExFreePool(SendRequest); + + /* If there are pending send requests, shedule worker function */ + KeAcquireSpinLock(&DGPendingListLock, &OldIrql); + QueueWorkItem = (!IsListEmpty(&DGPendingListHead)); + KeReleaseSpinLock(&DGPendingListLock, OldIrql); + if (QueueWorkItem) + ExQueueWorkItem(&DGWorkItem, CriticalWorkQueue); + + TI_DbgPrint(MAX_TRACE, ("Calling 0x%X.\n", Complete)); + + /* Call completion routine for send request */ + (*Complete)(CompleteContext, NdisStatus, BytesSent); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID DGSend( + PVOID Context, + PDATAGRAM_SEND_REQUEST SendRequest) +/* + * FUNCTION: Sends a datagram to IP layer + * ARGUMENTS: + * Context = Pointer to context information (ADDRESS_FILE) + * SendRequest = Pointer to send request + */ +{ + KIRQL OldIrql; + NTSTATUS Status; + USHORT LocalPort; + PIP_PACKET IPPacket; + PROUTE_CACHE_NODE RCN; + PLIST_ENTRY CurrentEntry; + PADDRESS_FILE AddrFile = Context; + PADDRESS_ENTRY ADE; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Get the information we need from the address file + now so we minimize the time we hold the spin lock */ + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + LocalPort = AddrFile->Port; + ADE = AddrFile->ADE; + ReferenceObject(ADE); + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + /* Loop until there are no more send requests in the + transmit queue or until we run out of resources */ + for (;;) { + Status = (*SendRequest->Build)(SendRequest, ADE->Address, LocalPort, &IPPacket); + if (!NT_SUCCESS(Status)) { + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + /* An error occurred, enqueue the send request again and return */ + InsertTailList(&AddrFile->TransmitQueue, &SendRequest->ListEntry); + DereferenceObject(ADE); + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MIN_TRACE, ("Leaving (insufficient resources).\n")); + return; + } + + /* Get a route to the destination address */ + if (RouteGetRouteToDestination(SendRequest->RemoteAddress, ADE->NTE, &RCN) == IP_SUCCESS) { + /* Set completion routine and send the packet */ + PC(IPPacket->NdisPacket)->Complete = SendDatagramComplete; + PC(IPPacket->NdisPacket)->Context = SendRequest; + if (IPSendDatagram(IPPacket, RCN) != STATUS_SUCCESS) + SendDatagramComplete( + SendRequest, + IPPacket->NdisPacket, + NDIS_STATUS_REQUEST_ABORTED); + /* We're done with the RCN */ + DereferenceObject(RCN); + } else { + /* No route to destination */ + /* FIXME: Which error code should we use here? */ + TI_DbgPrint(MIN_TRACE, ("No route to destination address (0x%X).\n", + SendRequest->RemoteAddress->Address.IPv4Address)); + SendDatagramComplete( + SendRequest, + IPPacket->NdisPacket, + NDIS_STATUS_REQUEST_ABORTED); + } + + (*IPPacket->Free)(IPPacket); + + /* Check transmit queue for more to send */ + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if (!IsListEmpty(&AddrFile->TransmitQueue)) { + /* Transmit queue is not empty, process one more request */ + CurrentEntry = RemoveHeadList(&AddrFile->TransmitQueue); + SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + } else { + /* Transmit queue is empty */ + AF_CLR_PENDING(AddrFile, AFF_SEND); + DereferenceObject(ADE); + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (empty queue).\n")); + return; + } + } +} + + +VOID DGDeliverData( + PADDRESS_FILE AddrFile, + PIP_ADDRESS Address, + PIP_PACKET IPPacket, + UINT DataSize) +/* + * FUNCTION: Delivers datagram data to a user + * ARGUMENTS: + * AddrFile = Address file to deliver data to + * Address = Remote address the packet came from + * IPPacket = Pointer to IP packet to deliver + * DataSize = Number of bytes in data area + * (incl. IP header for raw IP file objects) + * NOTES: + * If there is a receive request, then we copy the data to the + * buffer supplied by the user and complete the receive request. + * If no suitable receive request exists, then we call the event + * handler if it exists, otherwise we drop the packet. + */ +{ + KIRQL OldIrql; + PTDI_IND_RECEIVE_DATAGRAM ReceiveHandler; + PVOID HandlerContext; + LONG AddressLength; + PVOID SourceAddress; + ULONG BytesTaken; + NTSTATUS Status; + PVOID DataBuffer; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if (AddrFile->Protocol == IPPROTO_UDP) { + DataBuffer = IPPacket->Data; + } else { + /* Give client the IP header too if it is a raw IP file object */ + DataBuffer = IPPacket->Header; + } + + if (!IsListEmpty(&AddrFile->ReceiveQueue)) { + PLIST_ENTRY CurrentEntry; + PDATAGRAM_RECEIVE_REQUEST Current; + BOOLEAN Found; + + TI_DbgPrint(MAX_TRACE, ("There is a receive request.\n")); + + /* Search receive request list to find a match */ + Found = FALSE; + CurrentEntry = AddrFile->ReceiveQueue.Flink; + while ((CurrentEntry != &AddrFile->ReceiveQueue) && (!Found)) { + Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry); + if (!Current->RemoteAddress) + Found = TRUE; + else if (AddrIsEqual(Address, Current->RemoteAddress)) + Found = TRUE; + + if (Found) { + /* FIXME: Maybe we should check if the buffer of this + receive request is large enough and if not, search + for another */ + + /* Remove the request from the queue */ + RemoveEntryList(&Current->ListEntry); + AddrFile->RefCount--; + break; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + if (Found) { + TI_DbgPrint(MAX_TRACE, ("Suitable receive request found.\n")); + + /* Copy the data into buffer provided by the user */ + CopyBufferToBufferChain( + Current->Buffer, + 0, + DataBuffer, + DataSize); + + /* Complete the receive request */ + (*Current->Complete)(Current->Context, STATUS_SUCCESS, DataSize); + + /* Finally free the receive request */ + if (Current->RemoteAddress) + DereferenceObject(Current->RemoteAddress); + ExFreePool(Current); + } + } else if (AddrFile->RegisteredReceiveDatagramHandler) { + TI_DbgPrint(MAX_TRACE, ("Calling receive event handler.\n")); + + ReceiveHandler = AddrFile->ReceiveDatagramHandler; + HandlerContext = AddrFile->ReceiveDatagramHandlerContext; + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + if (Address->Type == IP_ADDRESS_V4) { + AddressLength = sizeof(IPv4_RAW_ADDRESS); + SourceAddress = &Address->Address.IPv4Address; + } else /* (Address->Type == IP_ADDRESS_V6) */ { + AddressLength = sizeof(IPv6_RAW_ADDRESS); + SourceAddress = Address->Address.IPv6Address; + } + + Status = (*ReceiveHandler)( + HandlerContext, + AddressLength, + SourceAddress, + 0, + NULL, + TDI_RECEIVE_ENTIRE_MESSAGE, + DataSize, + DataSize, + &BytesTaken, + DataBuffer, + NULL); + } else { + TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n")); + } + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID DGCancelSendRequest( + PADDRESS_FILE AddrFile, + PVOID Context) +/* + * FUNCTION: Cancels a datagram send request + * ARGUMENTS: + * AddrFile = Pointer to address file of the request + * Context = Pointer to context information for completion handler + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PDATAGRAM_SEND_REQUEST Current = NULL; + BOOLEAN Found = FALSE; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + /* Search the request list for the specified request and remove it */ + CurrentEntry = AddrFile->TransmitQueue.Flink; + while ((CurrentEntry != &AddrFile->TransmitQueue) && (!Found)) { + Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry); + if (Context == Current->Context) { + /* We've found the request, now remove it from the queue */ + RemoveEntryList(CurrentEntry); + AddrFile->RefCount--; + Found = TRUE; + break; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + if (Found) { + /* Complete the request and free its resources */ + (*Current->Complete)(Current->Context, STATUS_CANCELLED, 0); + DereferenceObject(Current->RemoteAddress); + ExFreePool(Current); + } else { + TI_DbgPrint(MID_TRACE, ("Cannot find send request.\n")); + } +} + + +VOID DGCancelReceiveRequest( + PADDRESS_FILE AddrFile, + PVOID Context) +/* + * FUNCTION: Cancels a datagram receive request + * ARGUMENTS: + * AddrFile = Pointer to address file of the request + * Context = Pointer to context information for completion handler + */ +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PDATAGRAM_RECEIVE_REQUEST Current = NULL; + BOOLEAN Found = FALSE; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + /* Search the request list for the specified request and remove it */ + CurrentEntry = AddrFile->ReceiveQueue.Flink; + while ((CurrentEntry != &AddrFile->ReceiveQueue) && (!Found)) { + Current = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry); + if (Context == Current->Context) { + /* We've found the request, now remove it from the queue */ + RemoveEntryList(CurrentEntry); + AddrFile->RefCount--; + Found = TRUE; + break; + } + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + if (Found) { + /* Complete the request and free its resources */ + (*Current->Complete)(Current->Context, STATUS_CANCELLED, 0); + /* Remote address can be NULL if the caller wants to receive + packets sent from any address */ + if (Current->RemoteAddress) + DereferenceObject(Current->RemoteAddress); + ExFreePool(Current); + } else { + TI_DbgPrint(MID_TRACE, ("Cannot find receive request.\n")); + } +} + + +NTSTATUS DGTransmit( + PADDRESS_FILE AddressFile, + PDATAGRAM_SEND_REQUEST SendRequest) +/* + * FUNCTION: Transmits or queues a send request + * ARGUMENTS: + * AddressFile = Pointer to address file + * SendRequest = Pointer to send request + * RETURNS: + * Status of operation + */ +{ + KIRQL OldIrql; +CP + KeAcquireSpinLock(&AddressFile->Lock, &OldIrql); +CP + if (AF_IS_BUSY(AddressFile)) { +CP + /* Queue send request on the transmit queue */ + InsertTailList(&AddressFile->TransmitQueue, &SendRequest->ListEntry); +CP + /* Reference address file and set pending send request flag */ + ReferenceObject(AddressFile); +CP + AF_SET_PENDING(AddressFile, AFF_SEND); +CP + KeReleaseSpinLock(&AddressFile->Lock, OldIrql); +CP + TI_DbgPrint(MAX_TRACE, ("Leaving (queued).\n")); + } else { +CP + KeReleaseSpinLock(&AddressFile->Lock, OldIrql); +CP + /* Send the datagram */ + DGSend(AddressFile, SendRequest); +CP + TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); + } +CP + return STATUS_PENDING; +} + +NTSTATUS DGSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize, + DATAGRAM_BUILD_ROUTINE Build) +/* + * FUNCTION: Sends a datagram to a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer with data + * DataSize = Size in bytes of data to be sent + * Build = Pointer to datagram build routine + * RETURNS: + * Status of operation + */ +{ + PADDRESS_FILE AddrFile; + KIRQL OldIrql; + NTSTATUS Status; + PDATAGRAM_SEND_REQUEST SendRequest; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + AddrFile = Request->Handle.AddressHandle; + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if (AF_IS_VALID(AddrFile)) { + /* Initialize a send request */ + Status = BuildDatagramSendRequest( + &SendRequest, + NULL, + 0, + Buffer, + DataSize, + Request->RequestNotifyObject, + Request->RequestContext, + Build, + 0); + if (NT_SUCCESS(Status)) { + Status = AddrGetAddress( + ConnInfo->RemoteAddress, + &SendRequest->RemoteAddress, + &SendRequest->RemotePort, + &AddrFile->AddrCache); + if (NT_SUCCESS(Status)) { + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + return DGTransmit(AddrFile, SendRequest); + } else { + ExFreePool(SendRequest); + } + } else + Status = STATUS_INSUFFICIENT_RESOURCES; + } else + Status = STATUS_ADDRESS_CLOSED; + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X)\n", Status)); + + return Status; +} + + +NTSTATUS DGReceiveDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG ReceiveLength, + ULONG ReceiveFlags, + PTDI_CONNECTION_INFORMATION ReturnInfo, + PULONG BytesReceived) +/* + * FUNCTION: Attempts to receive a datagram from a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer chain to store received data + * ReceiveLength = Maximum size to use of buffer (0 if all can be used) + * ReceiveFlags = Receive flags (None, Normal, Peek) + * ReturnInfo = Pointer to structure for return information + * BytesReceive = Pointer to structure for number of bytes received + * RETURNS: + * Status of operation + * NOTES: + * This is the high level interface for receiving datagrams + */ +{ + PADDRESS_FILE AddrFile; + KIRQL OldIrql; + NTSTATUS Status; + PDATAGRAM_RECEIVE_REQUEST ReceiveRequest; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + AddrFile = Request->Handle.AddressHandle; + + KeAcquireSpinLock(&AddrFile->Lock, &OldIrql); + + if (AF_IS_VALID(AddrFile)) { + ReceiveRequest = ExAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST)); + if (ReceiveRequest) { + /* Initialize a receive request */ + + /* Extract the remote address filter from the request (if any) */ + if (((ConnInfo->RemoteAddressLength != 0)) && (ConnInfo->RemoteAddress)) { + Status = AddrGetAddress(ConnInfo->RemoteAddress, + &ReceiveRequest->RemoteAddress, + &ReceiveRequest->RemotePort, + &AddrFile->AddrCache); + if (!NT_SUCCESS(Status)) { + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + ExFreePool(ReceiveRequest); + return Status; + } + } else { + ReceiveRequest->RemotePort = 0; + ReceiveRequest->RemoteAddress = NULL; + } + ReceiveRequest->ReturnInfo = ReturnInfo; + ReceiveRequest->Buffer = Buffer; + /* If ReceiveLength is 0, the whole buffer is available to us */ + ReceiveRequest->BufferSize = (ReceiveLength == 0) ? + MmGetMdlByteCount(Buffer) : ReceiveLength; + ReceiveRequest->Complete = Request->RequestNotifyObject; + ReceiveRequest->Context = Request->RequestContext; + + /* Queue receive request */ + InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry); + + /* Reference address file and set pending receive request flag */ + AddrFile->RefCount++; + AF_SET_PENDING(AddrFile, AFF_RECEIVE); + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving (pending).\n")); + + return STATUS_PENDING; + } else + Status = STATUS_INSUFFICIENT_RESOURCES; + } else + Status = STATUS_INVALID_ADDRESS; + + KeReleaseSpinLock(&AddrFile->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status)); + + return Status; +} + + +NTSTATUS DGStartup( + VOID) +/* + * FUNCTION: Initializes the datagram subsystem + * RETURNS: + * Status of operation + */ +{ + InitializeListHead(&DGPendingListHead); + + KeInitializeSpinLock(&DGPendingListLock); + + ExInitializeWorkItem(&DGWorkItem, DatagramWorker, NULL); + + return STATUS_SUCCESS; +} + + +NTSTATUS DGShutdown( + VOID) +/* + * FUNCTION: Shuts down the datagram subsystem + * RETURNS: + * Status of operation + */ +{ + return STATUS_SUCCESS; +} + + +/* EOF */ diff --git a/drivers/net/tcpip/transport/rawip/Makefile b/drivers/net/tcpip/transport/rawip/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/transport/rawip/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/transport/rawip/SOURCES b/drivers/net/tcpip/transport/rawip/SOURCES new file mode 100644 index 0000000..7c92afe --- /dev/null +++ b/drivers/net/tcpip/transport/rawip/SOURCES @@ -0,0 +1,13 @@ +TARGETNAME=rawip +TARGETPATH=..\..\objects +TARGETTYPE=LIBRARY + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +INCLUDES=..\..\include;$(BASEDIR)\INC;..\..\..\..\..\include\net + +SOURCES= rawip.c + +MSC_WARNING_LEVEL=/W3 /WX + diff --git a/drivers/net/tcpip/transport/rawip/rawip.c b/drivers/net/tcpip/transport/rawip/rawip.c new file mode 100644 index 0000000..16c5130 --- /dev/null +++ b/drivers/net/tcpip/transport/rawip/rawip.c @@ -0,0 +1,222 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: transport/rawip/rawip.c + * PURPOSE: Raw IP routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include + + +BOOLEAN RawIPInitialized = FALSE; + + +NTSTATUS BuildRawIPPacket( + PVOID Context, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET *IPPacket) +/* + * FUNCTION: Builds an UDP packet + * ARGUMENTS: + * Context = Pointer to context information (DATAGRAM_SEND_REQUEST) + * LocalAddress = Pointer to our local address (NULL) + * LocalPort = The port we send this datagram from (0) + * IPPacket = Address of pointer to IP packet + * RETURNS: + * Status of operation + */ +{ + PVOID Header; + PIP_PACKET Packet; + NDIS_STATUS NdisStatus; + PNDIS_BUFFER HeaderBuffer; + PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context; + + TI_DbgPrint(MAX_TRACE, ("TCPIP.SYS: NDIS data buffer is at (0x%X).\n", SendRequest->Buffer)); + TI_DbgPrint(MAX_TRACE, ("NDIS data buffer Next is at (0x%X).\n", SendRequest->Buffer->Next)); + TI_DbgPrint(MAX_TRACE, ("NDIS data buffer Size is (0x%X).\n", SendRequest->Buffer->Size)); + TI_DbgPrint(MAX_TRACE, ("NDIS data buffer MappedSystemVa is (0x%X).\n", SendRequest->Buffer->MappedSystemVa)); + TI_DbgPrint(MAX_TRACE, ("NDIS data buffer StartVa is (0x%X).\n", SendRequest->Buffer->StartVa)); + TI_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteCount is (0x%X).\n", SendRequest->Buffer->ByteCount)); + TI_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteOffset is (0x%X).\n", SendRequest->Buffer->ByteOffset)); + + /* Prepare packet */ + + /* FIXME: Assumes IPv4 */ + Packet = IPCreatePacket(IP_ADDRESS_V4); + if (!Packet) + return STATUS_INSUFFICIENT_RESOURCES; + + Packet->Flags = IP_PACKET_FLAG_RAW; /* Don't touch IP header */ + Packet->TotalSize = SendRequest->BufferSize; + + /* Allocate NDIS packet */ + NdisAllocatePacket(&NdisStatus, &Packet->NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS packet. NdisStatus = (0x%X)\n", NdisStatus)) + (*Packet->Free)(Packet); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (MaxLLHeaderSize != 0) { + Header = ExAllocatePool(NonPagedPool, MaxLLHeaderSize); + if (!Header) { + TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n")); + NdisFreePacket(Packet->NdisPacket); + (*Packet->Free)(Packet); + return STATUS_INSUFFICIENT_RESOURCES; + } + + TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", + MaxLLHeaderSize, Header)); + + /* Allocate NDIS buffer for maximum link level header */ + NdisAllocateBuffer(&NdisStatus, + &HeaderBuffer, + GlobalBufferPool, + Header, + MaxLLHeaderSize); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus)); + ExFreePool(Header); + NdisFreePacket(Packet->NdisPacket); + (*Packet->Free)(Packet); + return STATUS_INSUFFICIENT_RESOURCES; + } + /* Chain header at front of packet */ + NdisChainBufferAtFront(Packet->NdisPacket, HeaderBuffer); + } + + /* Chain data after link level header if it exists */ + NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer); + + DISPLAY_IP_PACKET(Packet); + + *IPPacket = Packet; + + return STATUS_SUCCESS; +} + + +NTSTATUS RawIPSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize) +/* + * FUNCTION: Sends a raw IP datagram to a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer with data + * DataSize = Size in bytes of data to be sent + * RETURNS: + * Status of operation + */ +{ + return DGSendDatagram(Request, ConnInfo, + Buffer, DataSize, BuildRawIPPacket); +} + + +VOID RawIPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* + * FUNCTION: Receives and queues a raw IP datagram + * ARGUMENTS: + * NTE = Pointer to net table entry which the packet was received on + * IPPacket = Pointer to an IP packet that was received + * NOTES: + * This is the low level interface for receiving ICMP datagrams. + * It delivers the packet header and data to anyone that wants it + * When we get here the datagram has already passed sanity checks + */ +{ + AF_SEARCH SearchContext; + PADDRESS_FILE AddrFile; + PIP_ADDRESS DstAddress; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (IPPacket->Type) { + /* IPv4 packet */ + case IP_ADDRESS_V4: + DstAddress = &IPPacket->DstAddr; + break; + + /* IPv6 packet */ + case IP_ADDRESS_V6: + TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 raw IP datagram (%i bytes).\n", + IPPacket->TotalSize)); + + /* FIXME: IPv6 is not supported */ + return; + + default: + return; + } + + /* Locate a receive request on destination address file object + and deliver the packet if one is found. If there is no receive + request on the address file object, call the associated receive + handler. If no receive handler is registered, drop the packet */ + + AddrFile = AddrSearchFirst(DstAddress, + 0, + IPPROTO_ICMP, + &SearchContext); + if (AddrFile) { + do { + DGDeliverData(AddrFile, + DstAddress, + IPPacket, + IPPacket->TotalSize); + } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); + } else { + /* There are no open address files that will take this datagram */ + /* FIXME: IPv4 only */ + TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 ICMP datagram to address (0x%X).\n", + DN2H(DstAddress->Address.IPv4Address))); + } + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS RawIPStartup( + VOID) +/* + * FUNCTION: Initializes the Raw IP subsystem + * RETURNS: + * Status of operation + */ +{ + RawIPInitialized = TRUE; + + return STATUS_SUCCESS; +} + + +NTSTATUS RawIPShutdown( + VOID) +/* + * FUNCTION: Shuts down the Raw IP subsystem + * RETURNS: + * Status of operation + */ +{ + if (!RawIPInitialized) + return STATUS_SUCCESS; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/tcpip/transport/tcp/Makefile b/drivers/net/tcpip/transport/tcp/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/transport/tcp/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/transport/tcp/SOURCES b/drivers/net/tcpip/transport/tcp/SOURCES new file mode 100644 index 0000000..82d019f --- /dev/null +++ b/drivers/net/tcpip/transport/tcp/SOURCES @@ -0,0 +1,13 @@ +TARGETNAME=tcp +TARGETPATH=..\..\objects +TARGETTYPE=LIBRARY + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +INCLUDES=..\..\include;$(BASEDIR)\INC;..\..\..\..\..\include\net + +SOURCES= tcp.c + +MSC_WARNING_LEVEL=/W3 /WX + diff --git a/drivers/net/tcpip/transport/tcp/tcp.c b/drivers/net/tcpip/transport/tcp/tcp.c new file mode 100644 index 0000000..ffebef0 --- /dev/null +++ b/drivers/net/tcpip/transport/tcp/tcp.c @@ -0,0 +1,498 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: transport/tcp/tcp.c + * PURPOSE: Transmission Control Protocol + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include + + +BOOLEAN TCPInitialized = FALSE; + + +NTSTATUS TCPiAddHeaderIPv4( + PDATAGRAM_SEND_REQUEST SendRequest, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET IPPacket) +/* + * FUNCTION: Adds an IPv4 and TCP header to an IP packet + * ARGUMENTS: + * SendRequest = Pointer to send request + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this segment from + * IPPacket = Pointer to IP packet + * RETURNS: + * Status of operation + */ +{ + PIPv4_HEADER IPHeader; + PTCP_HEADER TCPHeader; + PVOID Header; + ULONG BufferSize; + NDIS_STATUS NdisStatus; + PNDIS_BUFFER HeaderBuffer; + + BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(TCP_HEADER); + Header = ExAllocatePool(NonPagedPool, BufferSize); + if (!Header) + return STATUS_INSUFFICIENT_RESOURCES; + + TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", BufferSize, Header)); + + /* Allocate NDIS buffer for maximum Link level, IP and TCP header */ + NdisAllocateBuffer(&NdisStatus, + &HeaderBuffer, + GlobalBufferPool, + Header, + BufferSize); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + ExFreePool(Header); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Chain header at front of NDIS packet */ + NdisChainBufferAtFront(IPPacket->NdisPacket, HeaderBuffer); + + IPPacket->Header = (PVOID)((ULONG_PTR)Header + MaxLLHeaderSize); + IPPacket->HeaderSize = 20; + + /* Build IPv4 header */ + IPHeader = (PIPv4_HEADER)IPPacket->Header; + /* Version = 4, Length = 5 DWORDs */ + IPHeader->VerIHL = 0x45; + /* Normal Type-of-Service */ + IPHeader->Tos = 0; + /* Length of header and data */ + IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize); + /* Identification */ + IPHeader->Id = 0; + /* One fragment at offset 0 */ + IPHeader->FlagsFragOfs = 0; + /* Time-to-Live is 128 */ + IPHeader->Ttl = 128; + /* Transmission Control Protocol */ + IPHeader->Protocol = IPPROTO_TCP; + /* Checksum is 0 (for later calculation of this) */ + IPHeader->Checksum = 0; + /* Source address */ + IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; + /* Destination address. FIXME: IPv4 only */ + IPHeader->DstAddr = SendRequest->RemoteAddress->Address.IPv4Address; + + /* Build TCP header */ + TCPHeader = (PTCP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER)); + /* Port values are already big-endian values */ + TCPHeader->SourcePort = LocalPort; + TCPHeader->DestPort = SendRequest->RemotePort; + TCPHeader->SeqNum = 0; + TCPHeader->AckNum = 0; + TCPHeader->DataOfs = 0; + TCPHeader->Flags = SendRequest->Flags; + TCPHeader->Window = 0; + /* FIXME: Calculate TCP checksum and put it in TCP header */ + TCPHeader->Checksum = 0; + TCPHeader->Urgent = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS TCPiBuildPacket( + PVOID Context, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET *IPPacket) +/* + * FUNCTION: Builds a TCP packet + * ARGUMENTS: + * Context = Pointer to context information (DATAGRAM_SEND_REQUEST) + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this segment from + * IPPacket = Address of pointer to IP packet + * RETURNS: + * Status of operation + * NOTES: + * The ProcotolContext field in the send request structure (pointed to + * by the Context field) contains a pointer to the CONNECTION_ENDPOINT + * structure for the connection + */ +{ + NTSTATUS Status; + PIP_PACKET Packet; + NDIS_STATUS NdisStatus; + PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Prepare packet */ + + /* FIXME: Assumes IPv4*/ + Packet = IPCreatePacket(IP_ADDRESS_V4); + if (!Packet) + return STATUS_INSUFFICIENT_RESOURCES; + + Packet->TotalSize = sizeof(IPv4_HEADER) + + sizeof(TCP_HEADER) + + SendRequest->BufferSize; + + /* Allocate NDIS packet */ + NdisAllocatePacket(&NdisStatus, &Packet->NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + (*Packet->Free)(Packet); + return STATUS_INSUFFICIENT_RESOURCES; + } + + switch (SendRequest->RemoteAddress->Type) { + case IP_ADDRESS_V4: + Status = TCPiAddHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet); + break; + case IP_ADDRESS_V6: + /* FIXME: Support IPv6 */ + TI_DbgPrint(MIN_TRACE, ("IPv6 TCP segments are not supported.\n")); + default: + Status = STATUS_UNSUCCESSFUL; + break; + } + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Cannot add TCP header. Status (0x%X)\n", Status)); + NdisFreePacket(Packet->NdisPacket); + (*Packet->Free)(Packet); + return Status; + } + + /* Chain data after header */ + NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer); + + //DISPLAY_IP_PACKET(Packet); + + *IPPacket = Packet; + + return STATUS_SUCCESS; +} + + +VOID TCPiSendRequestComplete( + PVOID Context, + NTSTATUS Status, + ULONG Count) +/* + * FUNCTION: Completion routine for datagram send requests + * ARGUMENTS: + * Context = Pointer to context information (TCP_SEND_REQUEST) + * Status = Status of the request + * Count = Number of bytes sent or received + */ +{ + DATAGRAM_COMPLETION_ROUTINE Complete; + PVOID CompleteContext; + PTCP_SEND_REQUEST SendRequest = (PTCP_SEND_REQUEST)Context; + + Complete = SendRequest->Complete; + CompleteContext = SendRequest->Context; + ExFreePool(SendRequest); + + TI_DbgPrint(MAX_TRACE, ("Calling completion routine.\n")); + + /* Call upper level completion routine */ + (*Complete)(CompleteContext, Status, Count); + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +VOID TCPTimeout(VOID) +/* + * FUNCTION: Transmission Control Protocol timeout handler + * NOTES: + * This routine is called by IPTimeout to perform several + * maintainance tasks + */ +{ +} + + +inline NTSTATUS TCPBuildSendRequest( + PTCP_SEND_REQUEST *SendRequest, + PDATAGRAM_SEND_REQUEST *DGSendRequest, + PCONNECTION_ENDPOINT Connection, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + PNDIS_BUFFER Buffer, + DWORD BufferSize, + ULONG Flags) +/* + * FUNCTION: Allocates and intializes a TCP send request + * ARGUMENTS: + * SendRequest = TCP send request + * DGSendRequest = Datagram send request (optional) + * Connection = Connection endpoint + * Complete = Completion routine + * Context = Pointer to context information + * Buffer = Pointer to NDIS buffer to send + * BufferSize = Size of Buffer + * Flags = Protocol specific flags + * RETURNS: + * Status of operation + */ +{ + PDATAGRAM_SEND_REQUEST DGSendReq; + NTSTATUS Status; + + Status = BuildTCPSendRequest( + SendRequest, + Complete, + Context, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + Status = BuildDatagramSendRequest( + &DGSendReq, /* Datagram send request */ + Connection->RemoteAddress, /* Address of remote peer */ + Connection->RemotePort, /* Port of remote peer */ + Buffer, /* Buffer */ + BufferSize, /* Size of buffer */ + TCPiSendRequestComplete, /* Completion function */ + *SendRequest, /* Context for completion function */ + TCPiBuildPacket, /* Packet build function */ + Flags); /* Protocol specific flags */ + if (!NT_SUCCESS(Status)) { + ExFreePool(*SendRequest); + return Status; + } + + if (DGSendRequest) + *DGSendRequest = DGSendReq; + + return STATUS_SUCCESS; +} + + +inline NTSTATUS TCPBuildAndTransmitSendRequest( + PCONNECTION_ENDPOINT Connection, + DATAGRAM_COMPLETION_ROUTINE Complete, + PVOID Context, + PNDIS_BUFFER Buffer, + DWORD BufferSize, + ULONG Flags) +/* + * FUNCTION: Allocates and intializes a TCP send request + * ARGUMENTS: + * Connection = Connection endpoint + * Complete = Completion routine + * Context = Pointer to context information + * Buffer = Pointer to NDIS buffer to send + * BufferSize = Size of Buffer + * Flags = Protocol specific flags + * RETURNS: + * Status of operation + */ +{ + PDATAGRAM_SEND_REQUEST DGSendRequest; + PTCP_SEND_REQUEST TCPSendRequest; + NTSTATUS Status; + + Status = TCPBuildSendRequest( + &TCPSendRequest, + &DGSendRequest, + Connection, /* Connection endpoint */ + Complete, /* Completion routine */ + Context, /* Completion routine context */ + Buffer, /* Buffer */ + BufferSize, /* Size of buffer */ + Flags); /* Protocol specific flags */ + if (!NT_SUCCESS(Status)) + return Status; + + Status = DGTransmit( + Connection->AddressFile, + DGSendRequest); + if (!NT_SUCCESS(Status)) { + ExFreePool(DGSendRequest); + ExFreePool(TCPSendRequest); + return Status; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS TCPConnect( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PTDI_CONNECTION_INFORMATION ReturnInfo) +/* + * FUNCTION: Attempts to connect to a remote peer + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * ReturnInfo = Pointer to structure for return information + * RETURNS: + * Status of operation + * NOTES: + * This is the high level interface for connecting to remote peers + */ +{ + PDATAGRAM_SEND_REQUEST DGSendRequest; + PTCP_SEND_REQUEST TCPSendRequest; + PCONNECTION_ENDPOINT Connection; + LARGE_INTEGER DueTime; + NTSTATUS Status; + KIRQL OldIrql; + + TI_DbgPrint(MID_TRACE, ("Called.\n")); + + Connection = Request->Handle.ConnectionContext; + + KeAcquireSpinLock(&Connection->Lock, &OldIrql); + + if (Connection->State != ctClosed) { + /* The connection has already been opened so return success */ + KeReleaseSpinLock(&Connection->Lock, OldIrql); + return STATUS_SUCCESS; + } + + Connection->LocalAddress = Connection->AddressFile->ADE->Address; + Connection->LocalPort = Connection->AddressFile->Port; + + Status = AddrBuildAddress( + (PTA_ADDRESS)ConnInfo->RemoteAddress, + &Connection->RemoteAddress, + &Connection->RemotePort); + if (!NT_SUCCESS(Status)) { + KeReleaseSpinLock(&Connection->Lock, OldIrql); + return Status; + } + + /* Issue SYN segment */ + + Status = TCPBuildAndTransmitSendRequest( + Connection, /* Connection endpoint */ + Request->RequestNotifyObject, /* Completion routine */ + Request->RequestContext, /* Completion routine context */ + NULL, /* Buffer */ + 0, /* Size of buffer */ + SRF_SYN); /* Protocol specific flags */ + if (!NT_SUCCESS(Status)) { + KeReleaseSpinLock(&Connection->Lock, OldIrql); + ExFreePool(Connection->RemoteAddress); + return Status; + } + + KeReleaseSpinLock(&Connection->Lock, OldIrql); + + TI_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X)\n", Status)); + + return Status; +} + + +NTSTATUS TCPSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize) +/* + * FUNCTION: Sends TCP data to a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer with data + * DataSize = Size in bytes of data to be sent + * RETURNS: + * Status of operation + */ +{ + return STATUS_SUCCESS; +} + + +VOID TCPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* + * FUNCTION: Receives and queues TCP data + * ARGUMENTS: + * NTE = Pointer to net table entry which the packet was received on + * IPPacket = Pointer to an IP packet that was received + * NOTES: + * This is the low level interface for receiving TCP data + */ +{ + PIPv4_HEADER IPv4Header; + PADDRESS_FILE AddrFile; + PTCP_HEADER TCPHeader; + PIP_ADDRESS DstAddress; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (IPPacket->Type) { + /* IPv4 packet */ + case IP_ADDRESS_V4: + IPv4Header = IPPacket->Header; + DstAddress = &IPPacket->DstAddr; + break; + + /* IPv6 packet */ + case IP_ADDRESS_V6: + TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 TCP data (%i bytes).\n", + IPPacket->TotalSize)); + + /* FIXME: IPv6 is not supported */ + return; + + default: + return; + } + + TCPHeader = (PTCP_HEADER)IPPacket->Data; + + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS TCPStartup( + VOID) +/* + * FUNCTION: Initializes the TCP subsystem + * RETURNS: + * Status of operation + */ +{ + /* Register this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_TCP, TCPReceive); + + TCPInitialized = TRUE; + + return STATUS_SUCCESS; +} + + +NTSTATUS TCPShutdown( + VOID) +/* + * FUNCTION: Shuts down the TCP subsystem + * RETURNS: + * Status of operation + */ +{ + if (!TCPInitialized) + return STATUS_SUCCESS; + + /* Deregister this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_TCP, NULL); + + TCPInitialized = FALSE; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/tcpip/transport/udp/Makefile b/drivers/net/tcpip/transport/udp/Makefile new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/drivers/net/tcpip/transport/udp/Makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tcpip/transport/udp/SOURCES b/drivers/net/tcpip/transport/udp/SOURCES new file mode 100644 index 0000000..ebbec23 --- /dev/null +++ b/drivers/net/tcpip/transport/udp/SOURCES @@ -0,0 +1,12 @@ +TARGETNAME=udp +TARGETPATH=..\..\objects +TARGETTYPE=LIBRARY + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +INCLUDES=..\..\include;$(BASEDIR)\INC;..\..\..\..\..\include\net + +SOURCES= udp.c + +MSC_WARNING_LEVEL=/W3 /WX diff --git a/drivers/net/tcpip/transport/udp/udp.c b/drivers/net/tcpip/transport/udp/udp.c new file mode 100644 index 0000000..ed48779 --- /dev/null +++ b/drivers/net/tcpip/transport/udp/udp.c @@ -0,0 +1,360 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TCP/IP protocol driver + * FILE: transport/udp/udp.c + * PURPOSE: User Datagram Protocol routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +BOOLEAN UDPInitialized = FALSE; + + +NTSTATUS AddUDPHeaderIPv4( + PDATAGRAM_SEND_REQUEST SendRequest, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET IPPacket) +/* + * FUNCTION: Adds an IPv4 and UDP header to an IP packet + * ARGUMENTS: + * SendRequest = Pointer to send request + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this datagram from + * IPPacket = Pointer to IP packet + * RETURNS: + * Status of operation + */ +{ + PIPv4_HEADER IPHeader; + PUDP_HEADER UDPHeader; + PVOID Header; + ULONG BufferSize; + NDIS_STATUS NdisStatus; + PNDIS_BUFFER HeaderBuffer; + + BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(UDP_HEADER); + Header = ExAllocatePool(NonPagedPool, BufferSize); + if (!Header) { + TI_DbgPrint(MIN_TRACE, ("Cannot allocate memory for packet headers.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + TI_DbgPrint(MAX_TRACE, ("Allocated %d bytes for headers at 0x%X.\n", BufferSize, Header)); + + /* Allocate NDIS buffer for maximum Link level, IP and UDP header */ + NdisAllocateBuffer(&NdisStatus, + &HeaderBuffer, + GlobalBufferPool, + Header, + BufferSize); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS buffer for packet headers. NdisStatus = (0x%X)\n", NdisStatus)); + ExFreePool(Header); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Chain header at front of NDIS packet */ + NdisChainBufferAtFront(IPPacket->NdisPacket, HeaderBuffer); + + IPPacket->Header = (PVOID)((ULONG_PTR)Header + MaxLLHeaderSize); + IPPacket->HeaderSize = 20; + + /* Build IPv4 header */ + IPHeader = (PIPv4_HEADER)IPPacket->Header; + /* Version = 4, Length = 5 DWORDs */ + IPHeader->VerIHL = 0x45; + /* Normal Type-of-Service */ + IPHeader->Tos = 0; + /* Length of header and data */ + IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize); + /* Identification */ + IPHeader->Id = 0; + /* One fragment at offset 0 */ + IPHeader->FlagsFragOfs = 0; + /* Time-to-Live is 128 */ + IPHeader->Ttl = 128; + /* User Datagram Protocol */ + IPHeader->Protocol = IPPROTO_UDP; + /* Checksum is 0 (for later calculation of this) */ + IPHeader->Checksum = 0; + /* Source address */ + IPHeader->SrcAddr = LocalAddress->Address.IPv4Address; + /* Destination address. FIXME: IPv4 only */ + IPHeader->DstAddr = SendRequest->RemoteAddress->Address.IPv4Address; + + /* Build UDP header */ + UDPHeader = (PUDP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER)); + /* Port values are already big-endian values */ + UDPHeader->SourcePort = LocalPort; + UDPHeader->DestPort = SendRequest->RemotePort; + /* FIXME: Calculate UDP checksum and put it in UDP header */ + UDPHeader->Checksum = 0; + /* Length of UDP header and data */ + UDPHeader->Length = WH2N((USHORT)IPPacket->TotalSize - IPPacket->HeaderSize); + + return STATUS_SUCCESS; +} + + +NTSTATUS BuildUDPPacket( + PVOID Context, + PIP_ADDRESS LocalAddress, + USHORT LocalPort, + PIP_PACKET *IPPacket) +/* + * FUNCTION: Builds an UDP packet + * ARGUMENTS: + * Context = Pointer to context information (DATAGRAM_SEND_REQUEST) + * LocalAddress = Pointer to our local address + * LocalPort = The port we send this datagram from + * IPPacket = Address of pointer to IP packet + * RETURNS: + * Status of operation + */ +{ + NTSTATUS Status; + PIP_PACKET Packet; + NDIS_STATUS NdisStatus; + PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + /* Prepare packet */ + + /* FIXME: Assumes IPv4 */ + Packet = IPCreatePacket(IP_ADDRESS_V4); + if (!Packet) + return STATUS_INSUFFICIENT_RESOURCES; + + Packet->TotalSize = sizeof(IPv4_HEADER) + + sizeof(UDP_HEADER) + + SendRequest->BufferSize; + + /* Allocate NDIS packet */ + NdisAllocatePacket(&NdisStatus, &Packet->NdisPacket, GlobalPacketPool); + if (NdisStatus != NDIS_STATUS_SUCCESS) { + TI_DbgPrint(MIN_TRACE, ("Cannot allocate NDIS packet. NdisStatus = (0x%X)\n", NdisStatus)); + (*Packet->Free)(Packet); + return STATUS_INSUFFICIENT_RESOURCES; + } + + switch (SendRequest->RemoteAddress->Type) { + case IP_ADDRESS_V4: + Status = AddUDPHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet); + break; + case IP_ADDRESS_V6: + /* FIXME: Support IPv6 */ + TI_DbgPrint(MIN_TRACE, ("IPv6 UDP datagrams are not supported.\n")); + default: + Status = STATUS_UNSUCCESSFUL; + break; + } + if (!NT_SUCCESS(Status)) { + TI_DbgPrint(MIN_TRACE, ("Cannot add UDP header. Status = (0x%X)\n", Status)); + NdisFreePacket(Packet->NdisPacket); + (*Packet->Free)(Packet); + return Status; + } + + /* Chain data after header */ + NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer); + + DISPLAY_IP_PACKET(Packet); + + *IPPacket = Packet; + + return STATUS_SUCCESS; +} + + +NTSTATUS UDPSendDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG DataSize) +/* + * FUNCTION: Sends an UDP datagram to a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer with data + * DataSize = Size in bytes of data to be sent + * RETURNS: + * Status of operation + */ +{ + return DGSendDatagram(Request, + ConnInfo, + Buffer, + DataSize, + BuildUDPPacket); +} + + +NTSTATUS UDPReceiveDatagram( + PTDI_REQUEST Request, + PTDI_CONNECTION_INFORMATION ConnInfo, + PNDIS_BUFFER Buffer, + ULONG ReceiveLength, + ULONG ReceiveFlags, + PTDI_CONNECTION_INFORMATION ReturnInfo, + PULONG BytesReceived) +/* + * FUNCTION: Attempts to receive an UDP datagram from a remote address + * ARGUMENTS: + * Request = Pointer to TDI request + * ConnInfo = Pointer to connection information + * Buffer = Pointer to NDIS buffer chain to store received data + * ReceiveLength = Maximum size to use of buffer, 0 if all can be used + * ReceiveFlags = Receive flags (None, Normal, Peek) + * ReturnInfo = Pointer to structure for return information + * BytesReceive = Pointer to structure for number of bytes received + * RETURNS: + * Status of operation + * NOTES: + * This is the high level interface for receiving UDP datagrams + */ +{ + return DGReceiveDatagram(Request, + ConnInfo, + Buffer, + ReceiveLength, + ReceiveFlags, + ReturnInfo, + BytesReceived); +} + + +VOID UDPReceive( + PNET_TABLE_ENTRY NTE, + PIP_PACKET IPPacket) +/* +* FUNCTION: Receives and queues a UDP datagram +* ARGUMENTS: +* NTE = Pointer to net table entry which the packet was received on +* IPPacket = Pointer to an IP packet that was received +* NOTES: +* This is the low level interface for receiving UDP datagrams. It strips +* the UDP header from a packet and delivers the data to anyone that wants it +*/ +{ + AF_SEARCH SearchContext; + PIPv4_HEADER IPv4Header; + PADDRESS_FILE AddrFile; + PUDP_HEADER UDPHeader; + PIP_ADDRESS DstAddress; + UINT DataSize, i; + + TI_DbgPrint(MAX_TRACE, ("Called.\n")); + + switch (IPPacket->Type) { + /* IPv4 packet */ + case IP_ADDRESS_V4: + IPv4Header = IPPacket->Header; + DstAddress = &IPPacket->DstAddr; + break; + + /* IPv6 packet */ + case IP_ADDRESS_V6: + TI_DbgPrint(MIN_TRACE, ("Discarded IPv6 UDP datagram (%i bytes).\n", IPPacket->TotalSize)); + + /* FIXME: IPv6 is not supported */ + return; + + default: + return; + } + + UDPHeader = (PUDP_HEADER)IPPacket->Data; + + /* FIXME: Calculate and validate UDP checksum */ + + /* Sanity checks */ + i = WH2N(UDPHeader->Length); + if ((i < sizeof(UDP_HEADER)) || (i > IPPacket->TotalSize - IPPacket->Position)) { + /* Incorrect or damaged packet received, discard it */ + TI_DbgPrint(MIN_TRACE, ("Incorrect or damaged UDP packet received.\n")); + return; + } + + DataSize = i - sizeof(UDP_HEADER); + + /* Go to UDP data area */ + (ULONG_PTR)IPPacket->Data += sizeof(UDP_HEADER); + + /* Locate a receive request on destination address file object + and deliver the packet if one is found. If there is no receive + request on the address file object, call the associated receive + handler. If no receive handler is registered, drop the packet */ + + AddrFile = AddrSearchFirst(DstAddress, + UDPHeader->DestPort, + IPPROTO_UDP, + &SearchContext); + if (AddrFile) { + do { + DGDeliverData(AddrFile, + DstAddress, + IPPacket, + DataSize); + } while ((AddrFile = AddrSearchNext(&SearchContext)) != NULL); + } else { + /* There are no open address files that will take this datagram */ + /* FIXME: IPv4 only */ + TI_DbgPrint(MID_TRACE, ("Cannot deliver IPv4 UDP datagram to address (0x%X).\n", + DN2H(DstAddress->Address.IPv4Address))); + + /* FIXME: Send ICMP reply */ + } + TI_DbgPrint(MAX_TRACE, ("Leaving.\n")); +} + + +NTSTATUS UDPStartup( + VOID) +/* + * FUNCTION: Initializes the UDP subsystem + * RETURNS: + * Status of operation + */ +{ + RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS)); + + /* Register this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_UDP, UDPReceive); + + UDPInitialized = TRUE; + + return STATUS_SUCCESS; +} + + +NTSTATUS UDPShutdown( + VOID) +/* + * FUNCTION: Shuts down the UDP subsystem + * RETURNS: + * Status of operation + */ +{ + if (!UDPInitialized) + return STATUS_SUCCESS; + + /* Deregister this protocol with IP layer */ + IPRegisterProtocol(IPPROTO_UDP, NULL); + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/tdi/Makefile b/drivers/net/tdi/Makefile new file mode 100644 index 0000000..e98000c --- /dev/null +++ b/drivers/net/tdi/Makefile @@ -0,0 +1,41 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = tdi + +TARGET_OBJECTS = \ + ne2000/8390.o \ + ne2000/main.o + +OBJECTS_CTE = \ + cte/string.o \ + cte/stubs.o + +OBJECTS_MISC = \ + misc/main.o + +OBJECTS_TDI = \ + tdi/dereg.o \ + tdi/handler.o \ + tdi/obsolete.o \ + tdi/stubs.o + +TARGET_OBJECTS = \ + $(OBJECTS_CTE) \ + $(OBJECTS_MISC) \ + $(OBJECTS_TDI) + +TARGET_CLEAN = \ + cte/*.o \ + misc/*.o \ + misc/*.coff \ + tdi/*.o + +TARGET_PATH = misc + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/tdi/cte/string.c b/drivers/net/tdi/cte/string.c new file mode 100644 index 0000000..2599812 --- /dev/null +++ b/drivers/net/tdi/cte/string.c @@ -0,0 +1,28 @@ +/* $Id$ + * + */ +#include + +BOOLEAN +STDCALL +CTEAllocateString ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + return FALSE; +} + + +BOOLEAN +STDCALL +CTEInitString ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + return FALSE; +} + + +/* EOF */ diff --git a/drivers/net/tdi/cte/stubs.c b/drivers/net/tdi/cte/stubs.c new file mode 100644 index 0000000..3602bd6 --- /dev/null +++ b/drivers/net/tdi/cte/stubs.c @@ -0,0 +1,121 @@ +/* $Id$ + * + */ +#include + + +NTSTATUS +STDCALL +CTEBlock ( + DWORD Unknown0 + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +VOID +STDCALL +CTEInitEvent ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ +} + + +VOID +STDCALL +CTEInitTimer ( + DWORD Unknown0 + ) +{ +} + + +BOOLEAN +STDCALL +CTEInitialize ( + VOID + ) +{ + /* FIXME: what should it initialize? */ + return TRUE; +} + + +NTSTATUS +STDCALL +CTELogEvent ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6 + ) +{ + /* Probably call + * IoAllocateErrorLogEntry and + * IoWriteErrorLogEntry + */ + return STATUS_NOT_IMPLEMENTED; +} + + +BOOLEAN +STDCALL +CTEScheduleEvent ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + return FALSE; +} + + +LONG +STDCALL +CTESignal ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ +#if 0 + PKEVENT kevent = (PKEVENT) Unknown0; + + return KeSetEvent ( + kevent, + 0, + FALSE + ); +#endif + return 0; +} + + +BOOLEAN +STDCALL +CTEStartTimer ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + return FALSE; +} + + +ULONG +STDCALL +CTESystemUpTime ( + VOID + ) +{ + return 0; +} + + +/* EOF */ diff --git a/drivers/net/tdi/misc/.cvsignore b/drivers/net/tdi/misc/.cvsignore new file mode 100644 index 0000000..3775129 --- /dev/null +++ b/drivers/net/tdi/misc/.cvsignore @@ -0,0 +1 @@ +tdi.coff \ No newline at end of file diff --git a/drivers/net/tdi/misc/main.c b/drivers/net/tdi/misc/main.c new file mode 100644 index 0000000..838c57c --- /dev/null +++ b/drivers/net/tdi/misc/main.c @@ -0,0 +1,19 @@ +/* $Id$ + * + * DESCRIPTION: Entry point for TDI.SYS + */ +#include + +NTSTATUS +STDCALL +DriverEntry ( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +{ + return STATUS_UNSUCCESSFUL; +} + + + +/* EOF */ diff --git a/drivers/net/tdi/misc/tdi.def b/drivers/net/tdi/misc/tdi.def new file mode 100644 index 0000000..4f10551 --- /dev/null +++ b/drivers/net/tdi/misc/tdi.def @@ -0,0 +1,47 @@ +; $Id$ +; +; TDI.SYS Kernel Module - ReactOS Operating System +; +LIBRARY TDI.SYS + +EXPORTS +CTEAllocateString@8 +CTEBlock@4 +CTEInitEvent@8 +CTEInitString@8 +CTEInitTimer@4 +CTEInitialize@0 +CTELogEvent@28 +CTEScheduleEvent@8 +CTESignal@8 +CTEStartTimer@16 +CTESystemUpTime@0 +TdiBuildNetbiosAddress@12 +TdiBuildNetbiosAddressEa@12 +TdiCopyBufferToMdl@24 +TdiCopyMdlToBuffer@24 +TdiDefaultChainedRcvDatagramHandler@40 +TdiDefaultChainedRcvExpeditedHandler@28 +TdiDefaultChainedReceiveHandler@28 +TdiDefaultConnectHandler@36 +TdiDefaultDisconnectHandler@28 +TdiDefaultErrorHandler@8 +TdiDefaultRcvDatagramHandler@44 +TdiDefaultRcvExpeditedHandler@32 +TdiDefaultReceiveHandler@32 +TdiDefaultSendPossibleHandler@12 +TdiDeregisterAddressChangeHandler@4 +TdiDeregisterDeviceObject@4 +TdiDeregisterNetAddress@4 +TdiDeregisterNotificationHandler@4 +TdiInitialize@4 +TdiMapBuffer@4 +TdiMapUserRequest@12 +TdiOpenNetbiosAddress@16 +TdiRegisterAddressChangeHandler@12 +TdiRegisterDeviceObject@8 +TdiRegisterNetAddress@8 +TdiRegisterNotificationHandler@12 +TdiReturnChainedReceives@8 +TdiUnmapBuffer@4 +; EOF diff --git a/drivers/net/tdi/misc/tdi.edf b/drivers/net/tdi/misc/tdi.edf new file mode 100644 index 0000000..e53477e --- /dev/null +++ b/drivers/net/tdi/misc/tdi.edf @@ -0,0 +1,47 @@ +; $Id$ +; +; TDI.SYS Kernel Module - ReactOS Operating System +; +LIBRARY TDI.SYS + +EXPORTS +CTEAllocateString=CTEAllocateString@8 +CTEBlock=CTEBlock@4 +CTEInitEvent=CTEInitEvent@8 +CTEInitString=CTEInitString@8 +CTEInitTimer=CTEInitTimer@4 +CTEInitialize=CTEInitialize@0 +CTELogEvent=CTELogEvent@28 +CTEScheduleEvent=CTEScheduleEvent@8 +CTESignal=CTESignal@8 +CTEStartTimer=CTEStartTimer@16 +CTESystemUpTime=CTESystemUpTime@0 +TdiBuildNetbiosAddress=TdiBuildNetbiosAddress@12 +TdiBuildNetbiosAddressEa=TdiBuildNetbiosAddressEa@12 +TdiCopyBufferToMdl=TdiCopyBufferToMdl@24 +TdiCopyMdlToBuffer=TdiCopyMdlToBuffer@24 +TdiDefaultChainedRcvDatagramHandler=TdiDefaultChainedRcvDatagramHandler@40 +TdiDefaultChainedRcvExpeditedHandler=TdiDefaultChainedRcvExpeditedHandler@28 +TdiDefaultChainedReceiveHandler=TdiDefaultChainedReceiveHandler@28 +TdiDefaultConnectHandler=TdiDefaultConnectHandler@36 +TdiDefaultDisconnectHandler=TdiDefaultDisconnectHandler@28 +TdiDefaultErrorHandler=TdiDefaultErrorHandler@8 +TdiDefaultRcvDatagramHandler=TdiDefaultRcvDatagramHandler@44 +TdiDefaultRcvExpeditedHandler=TdiDefaultRcvExpeditedHandler@32 +TdiDefaultReceiveHandler=TdiDefaultReceiveHandler@32 +TdiDefaultSendPossibleHandler=TdiDefaultSendPossibleHandler@12 +TdiDeregisterAddressChangeHandler=TdiDeregisterAddressChangeHandler@4 +TdiDeregisterDeviceObject=TdiDeregisterDeviceObject@4 +TdiDeregisterNetAddress=TdiDeregisterNetAddress@4 +TdiDeregisterNotificationHandler=TdiDeregisterNotificationHandler@4 +TdiInitialize=TdiInitialize@4 +TdiMapBuffer=TdiMapBuffer@4 +TdiMapUserRequest=TdiMapUserRequest@12 +TdiOpenNetbiosAddress=TdiOpenNetbiosAddress@16 +TdiRegisterAddressChangeHandler=TdiRegisterAddressChangeHandler@12 +TdiRegisterDeviceObject=TdiRegisterDeviceObject@8 +TdiRegisterNetAddress=TdiRegisterNetAddress@8 +TdiRegisterNotificationHandler=TdiRegisterNotificationHandler@12 +TdiReturnChainedReceives=TdiReturnChainedReceives@8 +TdiUnmapBuffer=TdiUnmapBuffer@4 +; EOF diff --git a/drivers/net/tdi/misc/tdi.rc b/drivers/net/tdi/misc/tdi.rc new file mode 100644 index 0000000..5c8f2bb --- /dev/null +++ b/drivers/net/tdi/misc/tdi.rc @@ -0,0 +1,39 @@ +/* $Id$ */ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "TDI wrapper kernel module\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "tdi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "tdi.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/net/tdi/tdi/dereg.c b/drivers/net/tdi/tdi/dereg.c new file mode 100644 index 0000000..56bf684 --- /dev/null +++ b/drivers/net/tdi/tdi/dereg.c @@ -0,0 +1,170 @@ +/* $Id$ + * + */ +#include +#include + +/* De-/Register Action IDs for TdiDeRegister */ + +typedef +enum +{ + R_NOTIFICATION_HANDLER = 0, + DT_NOTIFICATION_HANDLER, + R_DEVICE_OBJECT, + D_DEVICE_OBJECT, + R_ADDRESS_CHANGE_HANDLER, + D_ADDRESS_CHANGE_HANDLER, + R_NET_ADDRESS, + D_NET_ADDRESS + +} TDI_OBJECT_ACTION; + + +static +NTSTATUS +STDCALL +TdiDeRegister ( + IN TDI_OBJECT_ACTION Action, + IN OUT PVOID Object + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ADDRESS_CHANGE_HANDLER */ + +NTSTATUS +STDCALL +TdiRegisterAddressChangeHandler ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + NTSTATUS Status = STATUS_SUCCESS; +#if 0 + Status = TdiDeRegister ( + R_ADDRESS_CHANGE_HANDLER, + AddressChangeHandler + ); +#endif + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +TdiDeregisterAddressChangeHandler ( + IN PVOID AddressChangeHandler + ) +{ + return TdiDeRegister ( + D_ADDRESS_CHANGE_HANDLER, + AddressChangeHandler + ); +} + + +/* DEVICE_OBJECT */ + +NTSTATUS +STDCALL +TdiRegisterDeviceObject ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + NTSTATUS Status = STATUS_SUCCESS; +#if 0 + Status = TdiDeRegister ( + R_DEVICE_OBJECT, + DeviceObject + ); +#endif + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +TdiDeregisterDeviceObject ( + IN PVOID DeviceObject + ) +{ + return TdiDeRegister ( + D_DEVICE_OBJECT, + DeviceObject + ); +} + + +/* NET_ADDRESS */ + +NTSTATUS +STDCALL +TdiRegisterNetAddress ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + NTSTATUS Status = STATUS_SUCCESS; +#if 0 + Status = TdiDeRegister ( + R_NET_ADDRESS, + NetAddress + ); +#endif + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +TdiDeregisterNetAddress ( + IN PVOID NetAddress + ) +{ + return TdiDeRegister ( + D_NET_ADDRESS, + NetAddress + ); +} + + +/* NOTIFICATION_HANDLER */ + +NTSTATUS +STDCALL +TdiRegisterNotificationHandler ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + NTSTATUS Status = STATUS_SUCCESS; +#if 0 + Status = TdiDeRegister ( + R_NOTIFICATION_HANDLER, + NotificationHandler + ); +#endif + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +TdiDeregisterNotificationHandler ( + IN PVOID NotificationHandler + ) +{ + return TdiDeRegister ( + DT_NOTIFICATION_HANDLER, + NotificationHandler + ); +} + + +/* EOF */ diff --git a/drivers/net/tdi/tdi/handler.c b/drivers/net/tdi/tdi/handler.c new file mode 100644 index 0000000..aa553c5 --- /dev/null +++ b/drivers/net/tdi/tdi/handler.c @@ -0,0 +1,181 @@ +/* $Id$ + * + * DESCRIPTION: Default TDI event handlers. + */ +#include +#include + + +/* ClientEventChainedReceiveDatagram */ +NTSTATUS +STDCALL +TdiDefaultChainedRcvDatagramHandler ( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG ReceiveDatagramLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventChainedReceiveExpedited */ +NTSTATUS +STDCALL +TdiDefaultChainedRcvExpeditedHandler ( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventChainedReceive */ +NTSTATUS +STDCALL +TdiDefaultChainedReceiveHandler ( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventConnect */ +NTSTATUS +STDCALL +TdiDefaultConnectHandler ( + IN PVOID TdiEventContext, + IN LONG RemoteAddressLength, + IN PVOID RemoteAddress, + IN LONG UserDataLength, + IN PVOID UserData, + IN LONG OptionsLength, + IN PVOID Options, + OUT CONNECTION_CONTEXT * ConnectionContext, + OUT PIRP * AcceptIrp + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventDisconnect */ +NTSTATUS +STDCALL +TdiDefaultDisconnectHandler ( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN LONG DisconnectDataLength, + IN PVOID DisconnectData, + IN LONG DisconnectInformationLength, + IN PVOID DisconnectInformation, + IN ULONG DisconnectFlags + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventError */ +NTSTATUS +STDCALL +TdiDefaultErrorHandler ( + IN PVOID TdiEventContext, + IN NTSTATUS Status + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventReceiveDatagram */ +NTSTATUS +STDCALL +TdiDefaultRcvDatagramHandler ( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG * BytesTaken, + IN PVOID Tsdu, + OUT PIRP * IoRequestPacket + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventReceiveExpedited */ +TDI_STATUS +STDCALL +TdiDefaultRcvExpeditedHandler ( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG * BytesTaken, + IN PVOID Tsdu, + OUT PIRP * IoRequestPacket + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventReceive */ +NTSTATUS +STDCALL +TdiDefaultReceiveHandler ( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG * BytesTaken, + IN PVOID Tsdu, + OUT PIRP * IoRequestPacket + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* ClientEventSendPossible */ +TDI_STATUS +STDCALL +TdiDefaultSendPossibleHandler ( + IN PVOID TdiEventContext, + IN PVOID ConnectionContext, + IN ULONG BytesAvailable + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* EOF */ diff --git a/drivers/net/tdi/tdi/obsolete.c b/drivers/net/tdi/tdi/obsolete.c new file mode 100644 index 0000000..4d70f76 --- /dev/null +++ b/drivers/net/tdi/tdi/obsolete.c @@ -0,0 +1,27 @@ +/* $Id$ + * + */ + +#include + +VOID +STDCALL +TdiMapBuffer ( + DWORD Unknown0 + ) +{ + /* This function is absolete */ +} + + +VOID +STDCALL +TdiUnmapBuffer ( + DWORD Unknown0 + ) +{ + /* This function is obsolete */ +} + + +/* EOF */ diff --git a/drivers/net/tdi/tdi/stubs.c b/drivers/net/tdi/tdi/stubs.c new file mode 100644 index 0000000..5b6d989 --- /dev/null +++ b/drivers/net/tdi/tdi/stubs.c @@ -0,0 +1,104 @@ + +/* $Id$ + * + */ +#include +#include + +VOID +STDCALL +TdiBuildNetbiosAddress ( + IN PUCHAR NetbiosName, + IN BOOLEAN IsGroupName, + IN OUT PTA_NETBIOS_ADDRESS NetworkName + ) +{ +} + + +NTSTATUS +STDCALL +TdiBuildNetbiosAddressEa ( + IN PUCHAR Buffer, + IN BOOLEAN GroupName, + IN PUCHAR NetbiosName + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +TdiCopyBufferToMdl ( + IN PVOID SourceBuffer, + IN ULONG SourceOffset, + IN ULONG SourceBytesToCopy, + IN PMDL DestinationMdlChain, + IN ULONG DestinationOffset, + IN PULONG BytesCopied + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +TdiCopyMdlToBuffer ( + IN PMDL SourceMdlChain, + IN ULONG SourceOffset, + IN PVOID DestinationBuffer, + IN ULONG DestinationOffset, + IN ULONG DestinationBufferSize, + OUT PULONG BytesCopied + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +VOID +STDCALL +TdiInitialize ( + PVOID Unknown0 + ) +{ +} + + +NTSTATUS +STDCALL +TdiMapUserRequest ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +VOID +STDCALL +TdiOpenNetbiosAddress ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ +} + + +VOID +STDCALL +TdiReturnChainedReceives ( + IN PVOID * TsduDescriptors, + IN ULONG NumberOfTsdus + ) +{ +} + + +/* EOF */ diff --git a/drivers/net/tditest/.cvsignore b/drivers/net/tditest/.cvsignore new file mode 100644 index 0000000..b2e0f39 --- /dev/null +++ b/drivers/net/tditest/.cvsignore @@ -0,0 +1,5 @@ +objects +tditest.coff +*.d +*.o +*.sym diff --git a/drivers/net/tditest/DIRS b/drivers/net/tditest/DIRS new file mode 100644 index 0000000..0f4605a --- /dev/null +++ b/drivers/net/tditest/DIRS @@ -0,0 +1 @@ +DIRS= tditest diff --git a/drivers/net/tditest/include/debug.h b/drivers/net/tditest/include/debug.h new file mode 100644 index 0000000..ee80cc3 --- /dev/null +++ b/drivers/net/tditest/include/debug.h @@ -0,0 +1,90 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TDI test driver + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#ifdef _MSC_VER + +#define TDI_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d) ", __FILE__, __LINE__); \ + DbgPrint _x_ ; \ + } + +#else /* _MSC_VER */ + +#define TDI_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_ ; \ + } + +#endif /* _MSC_VER */ + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { TDI_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } +#endif /* NASSERT */ + +#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) + +#else /* DBG */ + +#define TDI_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#ifdef _MSC_VER + +#define UNIMPLEMENTED \ + TDI_DbgPrint(MIN_TRACE, ("The function at %s:%d is unimplemented, \ + but come back another day.\n", __FILE__, __LINE__)); + +#else /* _MSC_VER */ + +#define UNIMPLEMENTED \ + TDI_DbgPrint(MIN_TRACE, ("%s at %s:%d is unimplemented, \ + but come back another day.\n", __FUNCTION__, __FILE__, __LINE__)); + +#endif /* _MSC_VER */ + + +#define CHECKPOINT \ +do { TDI_DbgPrint(MIN_TRACE, ("%s:%d\n", __FILE__, __LINE__)); } while(0); + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/drivers/net/tditest/include/tditest.h b/drivers/net/tditest/include/tditest.h new file mode 100644 index 0000000..95a2208 --- /dev/null +++ b/drivers/net/tditest/include/tditest.h @@ -0,0 +1,131 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TDI test driver + * FILE: include/tditest.h + * PURPOSE: Testing TDI drivers + */ +#ifndef __TDITEST_H +#define __TDITEST_H + +#ifdef _MSC_VER +#include +#include +#include +#include +#include +#else +#include +#include +#include +#endif + +#include + + +/* Name of UDP device */ +#define UDP_DEVICE_NAME L"\\Device\\Udp" +//#define UDP_DEVICE_NAME L"\\Device\\NTUdp" + + +#ifdef i386 + +/* DWORD network to host byte order conversion for i386 */ +#define DN2H(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* DWORD host to network byte order conversion for i386 */ +#define DH2N(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* WORD network to host order conversion for i386 */ +#define WN2H(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +/* WORD host to network byte order conversion for i386 */ +#define WH2N(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +#else /* i386 */ + +/* DWORD network to host byte order conversion for other architectures */ +#define DN2H(dw) \ + (dw) + +/* DWORD host to network byte order conversion for other architectures */ +#define DH2N(dw) \ + (dw) + +/* WORD network to host order conversion for other architectures */ +#define WN2H(w) \ + (w) + +/* WORD host to network byte order conversion for other architectures */ +#define WH2N(w) \ + (w) + +#endif /* i386 */ + + +typedef struct IPSNMP_INFO { + ULONG Forwarding; + ULONG DefaultTTL; + ULONG InReceives; + ULONG InHdrErrors; + ULONG InAddrErrors; + ULONG ForwDatagrams; + ULONG InUnknownProtos; + ULONG InDiscards; + ULONG InDelivers; + ULONG OutRequests; + ULONG RoutingDiscards; + ULONG OutDiscards; + ULONG OutNoRoutes; + ULONG ReasmTimeout; + ULONG ReasmReqds; + ULONG ReasmOks; + ULONG ReasmFails; + ULONG FragOks; + ULONG FragFails; + ULONG FragCreates; + ULONG NumIf; + ULONG NumAddr; + ULONG NumRoutes; +} IPSNMP_INFO, *PIPSNMP_INFO; + +typedef struct IPADDR_ENTRY { + ULONG Addr; + ULONG Index; + ULONG Mask; + ULONG BcastAddr; + ULONG ReasmSize; + USHORT Context; + USHORT Pad; +} IPADDR_ENTRY, *PIPADDR_ENTRY; + + +#define TL_INSTANCE 0 + +#define IP_MIB_STATS_ID 0x1 +#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 + + +/* IOCTL codes */ +#define IOCTL_TCP_QUERY_INFORMATION_EX \ + CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_TCP_SET_INFORMATION_EX \ + CTL_CODE(FILE_DEVICE_NETWORK, 1, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + +#define TEST_PORT 2000 + +#endif /*__TDITEST_H */ + +/* EOF */ diff --git a/drivers/net/tditest/makefile b/drivers/net/tditest/makefile new file mode 100644 index 0000000..a3810ff --- /dev/null +++ b/drivers/net/tditest/makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = tditest + +TARGET_CFLAGS = -I./include + +TARGET_OBJECTS = \ + tditest/tditest.o + +TARGET_CLEAN = \ + tditest/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/tditest/readme.txt b/drivers/net/tditest/readme.txt new file mode 100644 index 0000000..41e6e9c --- /dev/null +++ b/drivers/net/tditest/readme.txt @@ -0,0 +1,18 @@ +Build instructions for TDITEST driver +------------------------------------- + +Building with Visual C++ and Windows NT DDK: + +Variables: +%BASEDIR% = path to NT4 DDK (e.g. c:\ntddk) +%DDKBUILDENV% = DDK build environment (free or checked) + +DDK environment variables must be set! (run setenv.bat) + + - Create the directory objects/i386/%DDKBUILDENV% + - Run "build" to build the driver + + +Building with Mingw32 and ReactOS include files: + + - Run "make tditest" FROM THE ReactOS ROOT DIRECTORY to build the driver diff --git a/drivers/net/tditest/tditest.def b/drivers/net/tditest/tditest.def new file mode 100644 index 0000000..2acbb5b --- /dev/null +++ b/drivers/net/tditest/tditest.def @@ -0,0 +1,7 @@ +; TDI test driver - ReactOS Operating System + +LIBRARY TDITEST.SYS + +EXPORTS + +; EOF diff --git a/drivers/net/tditest/tditest.rc b/drivers/net/tditest/tditest.rc new file mode 100644 index 0000000..37601b2 --- /dev/null +++ b/drivers/net/tditest/tditest.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "TDI test driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "tditest\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "tditest.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/net/tditest/tditest/Makefile b/drivers/net/tditest/tditest/Makefile new file mode 100644 index 0000000..0ad3c88 --- /dev/null +++ b/drivers/net/tditest/tditest/Makefile @@ -0,0 +1,8 @@ +# MAKEFILE for ARTICLE +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/drivers/net/tditest/tditest/SOURCES b/drivers/net/tditest/tditest/SOURCES new file mode 100644 index 0000000..c2c4df0 --- /dev/null +++ b/drivers/net/tditest/tditest/SOURCES @@ -0,0 +1,14 @@ +TARGETNAME=tditest +TARGETPATH=..\objects +TARGETTYPE=DRIVER + +TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib \ + $(DDK_LIB_PATH)\ndis.lib + +C_DEFINES=$(C_DEFINES) -DDBG + +INCLUDES=..\include;..\..\..\..\include\net;$(BASEDIR)\inc + +SOURCES= tditest.c + +MSC_WARNING_LEVEL=/W3 /WX diff --git a/drivers/net/tditest/tditest/tditest.c b/drivers/net/tditest/tditest/tditest.c new file mode 100644 index 0000000..eb60caa --- /dev/null +++ b/drivers/net/tditest/tditest/tditest.c @@ -0,0 +1,953 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TDI test driver + * FILE: tditest.c + * PURPOSE: Testing TDI drivers + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/08-2000 Created + */ +#include + + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MIN_TRACE; + +#endif /* DBG */ + + +HANDLE TdiTransport = 0; +PFILE_OBJECT TdiTransportObject = NULL; +ULONG LocalAddress; +BOOLEAN OpenError; +KEVENT StopEvent; +HANDLE SendThread; +KEVENT SendThreadEvent; +HANDLE ReceiveThread; +KEVENT ReceiveThreadEvent; +PVOID ReceiveThreadObject; +PVOID SendThreadObject; + + +NTSTATUS TdiCall( + PIRP Irp, + PDEVICE_OBJECT DeviceObject, + PIO_STATUS_BLOCK IoStatusBlock, + BOOLEAN CanCancel) +/* + * FUNCTION: Calls a transport driver device + * ARGUMENTS: + * Irp = Pointer to I/O Request Packet + * DeviceObject = Pointer to device object to call + * IoStatusBlock = Address of buffer with I/O status block + * CanCancel = TRUE if the IRP can be cancelled, FALSE if not + * RETURNS: + * Status of operation + * NOTES + * All requests are completed synchronously. A request may be cancelled + */ +{ + KEVENT Event; + PKEVENT Events[2]; + NTSTATUS Status; + Events[0] = &StopEvent; + Events[1] = &Event; + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Irp->UserEvent = &Event; + Irp->UserIosb = IoStatusBlock; + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) { + if (CanCancel) { + Status = KeWaitForMultipleObjects(2, + (PVOID)&Events, + WaitAny, + Executive, + KernelMode, + FALSE, + NULL, + NULL); + + if (KeReadStateEvent(&StopEvent) != 0) { + if (IoCancelIrp(Irp)) { + TDI_DbgPrint(MAX_TRACE, ("Cancelled IRP.\n")); + } else { + TDI_DbgPrint(MIN_TRACE, ("Could not cancel IRP.\n")); + } + return STATUS_CANCELLED; + } + } else + Status = KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + } + + return (Status == STATUS_SUCCESS)? IoStatusBlock->Status : STATUS_SUCCESS; +} + + +NTSTATUS TdiOpenDevice( + PWSTR Protocol, + ULONG EaLength, + PFILE_FULL_EA_INFORMATION EaInfo, + PHANDLE Handle, + PFILE_OBJECT *Object) +/* + * FUNCTION: Opens a device + * ARGUMENTS: + * Protocol = Pointer to buffer with name of device + * EaLength = Length of EA information + * EaInfo = Pointer to buffer with EA information + * Handle = Address of buffer to place device handle + * Object = Address of buffer to place device object + * RETURNS: + * Status of operation + */ +{ + OBJECT_ATTRIBUTES Attr; + IO_STATUS_BLOCK Iosb; + UNICODE_STRING Name; + NTSTATUS Status; + + RtlInitUnicodeString(&Name, Protocol); + InitializeObjectAttributes(&Attr, /* Attribute buffer */ + &Name, /* Device name */ + OBJ_CASE_INSENSITIVE, /* Attributes */ + NULL, /* Root directory */ + NULL); /* Security descriptor */ + + Status = ZwCreateFile(Handle, /* Return file handle */ + GENERIC_READ | GENERIC_WRITE, /* Desired access */ + &Attr, /* Object attributes */ + &Iosb, /* IO status */ + 0, /* Initial allocation size */ + FILE_ATTRIBUTE_NORMAL, /* File attributes */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access */ + FILE_OPEN_IF, /* Create disposition */ + 0, /* Create options */ + EaInfo, /* EA buffer */ + EaLength); /* EA length */ + if (NT_SUCCESS(Status)) { + Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */ + GENERIC_READ | GENERIC_WRITE, /* Access mode */ + NULL, /* Object type */ + KernelMode, /* Access mode */ + (PVOID*)Object, /* Pointer to object */ + NULL); /* Handle information */ + if (!NT_SUCCESS(Status)) { + TDI_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status)); + ZwClose(*Handle); + } + } else { + TDI_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status)); + } + + return Status; +} + + +NTSTATUS TdiCloseDevice( + HANDLE Handle, + PFILE_OBJECT FileObject) +{ + if (FileObject) + ObDereferenceObject(FileObject); + + if (Handle) + ZwClose(Handle); + + return STATUS_SUCCESS; +} + + +NTSTATUS TdiOpenTransport( + PWSTR Protocol, + USHORT Port, + PHANDLE Transport, + PFILE_OBJECT *TransportObject) +/* + * FUNCTION: Opens a transport driver + * ARGUMENTS: + * Protocol = Pointer to buffer with name of device + * Port = Port number to use + * Transport = Address of buffer to place transport device handle + * TransportObject = Address of buffer to place transport object + * RETURNS: + * Status of operation + */ +{ + PFILE_FULL_EA_INFORMATION EaInfo; + PTA_ADDRESS_IP Address; + NTSTATUS Status; + ULONG EaLength; + + EaLength = sizeof(FILE_FULL_EA_INFORMATION) + + TDI_TRANSPORT_ADDRESS_LENGTH + + sizeof(TA_ADDRESS_IP); + EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength); + if (!EaInfo) { + TDI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(EaInfo, EaLength); + EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; + RtlCopyMemory(EaInfo->EaName, + TdiTransportAddress, + TDI_TRANSPORT_ADDRESS_LENGTH); + EaInfo->EaValueLength = sizeof(TA_ADDRESS_IP); + Address = (PTA_ADDRESS_IP)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH); + Address->TAAddressCount = 1; + Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; + Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; + Address->Address[0].Address[0].sin_port = WH2N(Port); + Address->Address[0].Address[0].in_addr = 0; + Status = TdiOpenDevice(Protocol, + EaLength, + EaInfo, + Transport, + TransportObject); + ExFreePool(EaInfo); + + return Status; +} + + +NTSTATUS TdiQueryDeviceControl( + PFILE_OBJECT FileObject, + ULONG IoControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + PULONG Return) +/* + * FUNCTION: Queries a device for information + * ARGUMENTS: + * FileObject = Pointer to device object + * IoControlCode = I/O control code + * InputBuffer = Pointer to buffer with input data + * InputBufferLength = Length of InputBuffer + * OutputBuffer = Address of buffer to place output data + * OutputBufferLength = Length of OutputBuffer + * RETURNS: + * Status of operation + */ +{ + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION IoStack; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + PIRP Irp; + + DeviceObject = IoGetRelatedDeviceObject(FileObject); + Irp = IoBuildDeviceIoControlRequest(IoControlCode, + DeviceObject, + InputBuffer, + InputBufferLength, + OutputBuffer, + OutputBufferLength, + FALSE, + NULL, + NULL); + if (!Irp) { + TDI_DbgPrint(MIN_TRACE, ("IoBuildDeviceIoControlRequest() failed.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + IoStack = IoGetNextIrpStackLocation(Irp); + IoStack->DeviceObject = DeviceObject; + IoStack->FileObject = FileObject; + Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE); + if (Return) + *Return = Iosb.Information; + + return Status; +} + + +NTSTATUS TdiQueryInformationEx( + PFILE_OBJECT FileObject, + ULONG Entity, + ULONG Instance, + ULONG Class, + ULONG Type, + ULONG Id, + PVOID OutputBuffer, + PULONG OutputLength) +/* + * FUNCTION: Extended query for information + * ARGUMENTS: + * FileObject = Pointer to transport object + * Entity = Entity + * Instance = Instance + * Class = Entity class + * Type = Entity type + * Id = Entity id + * OutputBuffer = Address of buffer to place data + * OutputLength = Address of buffer with length of OutputBuffer (updated) + * RETURNS: + * Status of operation + */ +{ + TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo; + + RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)); + QueryInfo.ID.toi_entity.tei_entity = Entity; + QueryInfo.ID.toi_entity.tei_instance = Instance; + QueryInfo.ID.toi_class = Class; + QueryInfo.ID.toi_type = Type; + QueryInfo.ID.toi_id = Id; + + return TdiQueryDeviceControl(FileObject, /* Transport/connection object */ + IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */ + &QueryInfo, /* Input buffer */ + sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */ + OutputBuffer, /* Output buffer */ + *OutputLength, /* Output buffer length */ + OutputLength); /* Return information */ +} + + +NTSTATUS TdiQueryAddress( + PFILE_OBJECT FileObject, + PULONG Address) +/* + * FUNCTION: Queries for a local IP address + * ARGUMENTS: + * FileObject = Pointer to file object + * Address = Address of buffer to place local address + * RETURNS: + * Status of operation + */ +{ + UINT i; + TDIEntityID *Entities; + ULONG EntityCount; + ULONG EntityType; + IPSNMP_INFO SnmpInfo; + PIPADDR_ENTRY IpAddress; + ULONG BufferSize; + NTSTATUS Status = STATUS_SUCCESS; + + TDI_DbgPrint(MAX_TRACE, ("Called\n")); + + BufferSize = sizeof(TDIEntityID) * 20; + Entities = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize); + if (!Entities) { + TDI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Query device for supported entities */ + + Status = TdiQueryInformationEx(FileObject, /* File object */ + GENERIC_ENTITY, /* Entity */ + TL_INSTANCE, /* Instance */ + INFO_CLASS_GENERIC, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + ENTITY_LIST_ID, /* Entity id */ + Entities, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status)) { + TDI_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status)); + ExFreePool(Entities); + return Status; + } + + /* Locate an IP entity */ + EntityCount = BufferSize / sizeof(TDIEntityID); + + TDI_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount)); + + for (i = 0; i < EntityCount; i++) { + if (Entities[i].tei_entity == CL_NL_ENTITY) { + /* Query device for entity type */ + + BufferSize = sizeof(EntityType); + Status = TdiQueryInformationEx(FileObject, /* File object */ + CL_NL_ENTITY, /* Entity */ + Entities[i].tei_instance, /* Instance */ + INFO_CLASS_GENERIC, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + ENTITY_TYPE_ID, /* Entity id */ + &EntityType, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) { + TDI_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status)); + break; + } + + /* Query device for SNMP information */ + + BufferSize = sizeof(SnmpInfo); + Status = TdiQueryInformationEx(FileObject, /* File object */ + CL_NL_ENTITY, /* Entity */ + Entities[i].tei_instance, /* Instance */ + INFO_CLASS_PROTOCOL, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + IP_MIB_STATS_ID, /* Entity id */ + &SnmpInfo, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) { + TDI_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status)); + break; + } + + /* Query device for all IP addresses */ + + if (SnmpInfo.NumAddr != 0) { + BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY); + IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize); + if (!IpAddress) { + TDI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + break; + } + + Status = TdiQueryInformationEx(FileObject, /* File object */ + CL_NL_ENTITY, /* Entity */ + Entities[i].tei_instance, /* Instance */ + INFO_CLASS_PROTOCOL, /* Entity class */ + INFO_TYPE_PROVIDER, /* Entity type */ + IP_MIB_ADDRTABLE_ENTRY_ID, /* Entity id */ + IpAddress, /* Output buffer */ + &BufferSize); /* Output buffer size */ + if (!NT_SUCCESS(Status)) { + TDI_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status)); + ExFreePool(IpAddress); + break; + } + + if (SnmpInfo.NumAddr != 1) { + /* Skip loopback address */ + *Address = DN2H(((PIPADDR_ENTRY)((ULONG)IpAddress + sizeof(IPADDR_ENTRY)))->Addr); + } else { + /* Select the first address returned */ + *Address = DN2H(IpAddress->Addr); + } + + ExFreePool(IpAddress); + } else { + Status = STATUS_UNSUCCESSFUL; + break; + } + } + } + + ExFreePool(Entities); + + TDI_DbgPrint(MAX_TRACE, ("Leaving\n")); + + return Status; +} + + +NTSTATUS TdiSendDatagram( + PFILE_OBJECT TransportObject, + USHORT Port, + ULONG Address, + PVOID Buffer, + ULONG BufferSize) +/* + * FUNCTION: Sends a datagram + * ARGUMENTS: + * TransportObject = Pointer to transport object + * Port = Remote port + * Address = Remote address + * Buffer = Pointer to buffer with data to send + * BufferSize = Length of Buffer + * RETURNS: + * Status of operation + */ +{ + PIRP Irp; + PMDL Mdl; + PDEVICE_OBJECT DeviceObject; + PTDI_CONNECTION_INFORMATION ConnectInfo; + PTA_ADDRESS_IP TA; + PTDI_ADDRESS_IP IpAddress; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + DeviceObject = IoGetRelatedDeviceObject(TransportObject); + ConnectInfo = (PTDI_CONNECTION_INFORMATION) + ExAllocatePool(NonPagedPool, + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TA_ADDRESS_IP)); + + if (!ConnectInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(ConnectInfo, + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TA_ADDRESS_IP)); + + ConnectInfo->RemoteAddressLength = sizeof(TA_ADDRESS_IP); + ConnectInfo->RemoteAddress = (PUCHAR) + ((ULONG)ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + TA = (PTA_ADDRESS_IP)(ConnectInfo->RemoteAddress); + TA->TAAddressCount = 1; + TA->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP); + TA->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; + IpAddress = (PTDI_ADDRESS_IP)(TA->Address[0].Address); + IpAddress->sin_port = WH2N(Port); + IpAddress->in_addr = DH2N(Address); + Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Event */ + NULL); /* Return buffer */ + if (!Irp) { + TDI_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n")); + ExFreePool(ConnectInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Mdl = IoAllocateMdl(Buffer, /* Virtual address of buffer */ + BufferSize, /* Length of buffer */ + FALSE, /* Not secondary */ + FALSE, /* Don't charge quota */ + NULL); /* Don't use IRP */ + if (!Mdl) { + TDI_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n")); + IoFreeIrp(Irp); + ExFreePool(ConnectInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#ifdef _MSC_VER + try { +#endif + MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); +#ifdef _MSC_VER + } except(EXCEPTION_EXECUTE_HANDLER) { + TDI_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); + IoFreeMdl(Mdl); + IoFreeIrp(Irp); + ExFreePool(ConnectInfo); + return STATUS_UNSUCCESSFUL; + } +#endif + + TdiBuildSendDatagram(Irp, /* I/O Request Packet */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Completion routine */ + NULL, /* Completion context */ + Mdl, /* Descriptor for data buffer */ + BufferSize, /* Size of data to send */ + ConnectInfo); /* Connection information */ + + Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE); + + ExFreePool(ConnectInfo); + + return Status; +} + + +NTSTATUS TdiReceiveDatagram( + PFILE_OBJECT TransportObject, + USHORT Port, + PULONG Address, + PUCHAR Buffer, + PULONG BufferSize) +/* + * FUNCTION: Receives a datagram + * ARGUMENTS: + * TransportObject = Pointer to transport object + * Port = Port to receive on + * Address = Address of buffer to place remote address + * Buffer = Address of buffer to place received data + * BufferSize = Address of buffer with length of Buffer (updated) + * RETURNS: + * Status of operation + */ +{ + PTDI_CONNECTION_INFORMATION ReceiveInfo; + PTDI_CONNECTION_INFORMATION ReturnInfo; + PTA_ADDRESS_IP ReturnAddress; + PDEVICE_OBJECT DeviceObject; + PTDI_ADDRESS_IP IpAddress; + IO_STATUS_BLOCK Iosb; + PVOID MdlBuffer; + NTSTATUS Status; + PIRP Irp; + PMDL Mdl; + + DeviceObject = IoGetRelatedDeviceObject(TransportObject); + if (!DeviceObject) + return STATUS_INVALID_PARAMETER; + + ReceiveInfo = (PTDI_CONNECTION_INFORMATION) + ExAllocatePool(NonPagedPool, + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TA_ADDRESS_IP)); + if (!ReceiveInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + MdlBuffer = ExAllocatePool(PagedPool, *BufferSize); + if (!MdlBuffer) + return STATUS_INSUFFICIENT_RESOURCES; + + + RtlZeroMemory(ReceiveInfo, + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TDI_CONNECTION_INFORMATION) + + sizeof(TA_ADDRESS_IP)); + RtlCopyMemory(MdlBuffer, Buffer, *BufferSize); + + /* Receive from any address */ + ReceiveInfo->RemoteAddressLength = 0; + ReceiveInfo->RemoteAddress = NULL; + + ReturnInfo = (PTDI_CONNECTION_INFORMATION) + ((ULONG)ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + ReturnInfo->RemoteAddressLength = sizeof(TA_ADDRESS_IP); + ReturnInfo->RemoteAddress = (PUCHAR) + ((ULONG)ReturnInfo + sizeof(TDI_CONNECTION_INFORMATION)); + + ReturnAddress = (PTA_ADDRESS_IP)(ReturnInfo->RemoteAddress); + ReturnAddress->TAAddressCount = 1; + ReturnAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP); + ReturnAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; + + IpAddress = (PTDI_ADDRESS_IP)(ReturnAddress->Address[0].Address); + IpAddress->sin_port = WH2N(Port); + IpAddress->in_addr = DH2N(LocalAddress); + + Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, /* Sub function */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Event */ + NULL); /* Return buffer */ + if (!Irp) { + ExFreePool(MdlBuffer); + ExFreePool(ReceiveInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Mdl = IoAllocateMdl(MdlBuffer, /* Virtual address */ + *BufferSize, /* Length of buffer */ + FALSE, /* Not secondary */ + FALSE, /* Don't charge quota */ + NULL); /* Don't use IRP */ + if (!Mdl) { + IoFreeIrp(Irp); + ExFreePool(MdlBuffer); + ExFreePool(ReceiveInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#ifdef _MSC_VER + try { +#endif + MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); +#ifdef _MSC_VER + } except (EXCEPTION_EXECUTE_HANDLER) { + TDI_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); + IoFreeMdl(Mdl); + IoFreeIrp(Irp); + ExFreePool(MdlBuffer); + ExFreePool(ReceiveInfo); + return STATUS_INSUFFICIENT_RESOURCES; + } +#endif + + TdiBuildReceiveDatagram(Irp, /* I/O Request Packet */ + DeviceObject, /* Device object */ + TransportObject, /* File object */ + NULL, /* Completion routine */ + NULL, /* Completion context */ + Mdl, /* Data buffer */ + *BufferSize, /* Size of data buffer */ + ReceiveInfo, /* Connection information */ + ReturnInfo, /* Connection information */ + TDI_RECEIVE_NORMAL); /* Flags */ + Status = TdiCall(Irp, DeviceObject, &Iosb, TRUE); + if (NT_SUCCESS(Status)) { + RtlCopyMemory(Buffer, MdlBuffer, Iosb.Information); + *BufferSize = Iosb.Information; + *Address = DN2H(IpAddress->in_addr); + } + + ExFreePool(MdlBuffer); + ExFreePool(ReceiveInfo); + + return Status; +} + + +VOID TdiSendThread( + PVOID Context) +/* + * FUNCTION: Send thread + * ARGUMENTS: + * Context = Pointer to context information + * NOTES: + * Transmits an UDP packet every two seconds to ourselves on the chosen port + */ +{ + KEVENT Event; + PKEVENT Events[2]; + LARGE_INTEGER Timeout; + NTSTATUS Status = STATUS_SUCCESS; + UCHAR Data[40] = "Testing one, two, three, ..."; + + if (!OpenError) { + Timeout.QuadPart = 10000000L; /* Second factor */ + Timeout.QuadPart *= 2; /* Number of seconds */ + Timeout.QuadPart = -(Timeout.QuadPart); /* Relative time */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + + Events[0] = &StopEvent; + Events[1] = &Event; + + while (NT_SUCCESS(Status)) { + /* Wait until timeout or stop flag is set */ + KeWaitForMultipleObjects( + 2, + (PVOID)&Events, + WaitAny, + Executive, + KernelMode, + FALSE, + &Timeout, + NULL); + + if (KeReadStateEvent(&StopEvent) != 0) { + TDI_DbgPrint(MAX_TRACE, ("Received terminate signal...\n")); + break; + } + + DbgPrint("Sending data - '%s'\n", Data); + + Status = TdiSendDatagram(TdiTransportObject, + TEST_PORT, + LocalAddress, + Data, + sizeof(Data)); + if (!NT_SUCCESS(Status)) + DbgPrint("Failed sending data (Status = 0x%X)\n", Status); + } + } + + TDI_DbgPrint(MAX_TRACE, ("Terminating send thread...\n")); + + KeSetEvent(&SendThreadEvent, 0, FALSE); + + PsTerminateSystemThread(STATUS_SUCCESS); +} + + +VOID TdiReceiveThread( + PVOID Context) +/* + * FUNCTION: Receive thread + * ARGUMENTS: + * Context = Pointer to context information + * NOTES: + * Waits until an UDP packet is received on the chosen endpoint and displays the data + */ +{ + ULONG Address; + UCHAR Data[40]; + ULONG Size; + NTSTATUS Status = STATUS_SUCCESS; + + if (!OpenError) { + while (NT_SUCCESS(Status)) { + Size = sizeof(Data); + RtlZeroMemory(Data, Size); + + Status = TdiReceiveDatagram(TdiTransportObject, + TEST_PORT, + &Address, + Data, + &Size); + if (NT_SUCCESS(Status)) { + DbgPrint("Received data - '%s'\n", Data); + } else + if (Status != STATUS_CANCELLED) { + TDI_DbgPrint(MIN_TRACE, ("Receive error (Status = 0x%X).\n", Status)); + } else { + TDI_DbgPrint(MAX_TRACE, ("IRP was cancelled.\n")); + } + } + } + + TDI_DbgPrint(MAX_TRACE, ("Terminating receive thread...\n")); + + KeSetEvent(&ReceiveThreadEvent, 0, FALSE); + + PsTerminateSystemThread(STATUS_SUCCESS); +} + + +VOID TdiOpenThread( + PVOID Context) +/* + * FUNCTION: Open thread + * ARGUMENTS: + * Context = Pointer to context information (event) + */ +{ + NTSTATUS Status; + + TDI_DbgPrint(MAX_TRACE, ("Called.\n")); + + OpenError = TRUE; + + Status = TdiOpenTransport(UDP_DEVICE_NAME, + TEST_PORT, + &TdiTransport, + &TdiTransportObject); + if (NT_SUCCESS(Status)) { + Status = TdiQueryAddress(TdiTransportObject, &LocalAddress); + if (NT_SUCCESS(Status)) { + OpenError = FALSE; + DbgPrint("Using local IP address 0x%X\n", LocalAddress); + } else { + TDI_DbgPrint(MIN_TRACE, ("Unable to determine local IP address.\n")); + } + } else + TDI_DbgPrint(MIN_TRACE, ("Cannot open transport (Status = 0x%X).\n", Status)); + + TDI_DbgPrint(MAX_TRACE, ("Setting close event.\n")); + + KeSetEvent((PKEVENT)Context, 0, FALSE); + + TDI_DbgPrint(MIN_TRACE, ("Leaving.\n")); +} + + +VOID TdiUnload( + PDRIVER_OBJECT DriverObject) +/* + * FUNCTION: Unload routine + * ARGUMENTS: + * DriverObject = Pointer to a driver object for this driver + */ +{ + TDI_DbgPrint(MAX_TRACE, ("Setting stop flag\n")); + + KeSetEvent(&StopEvent, 0, FALSE); + + /* Wait for send thread to stop */ + KeWaitForSingleObject(&SendThreadEvent, + Executive, + KernelMode, + FALSE, + NULL); + + ObDereferenceObject(SendThreadObject); + + /* Wait for receive thread to stop */ + KeWaitForSingleObject(&ReceiveThreadEvent, + Executive, + KernelMode, + FALSE, + NULL); + + ObDereferenceObject(ReceiveThreadObject); + + /* Close device */ + TdiCloseDevice(TdiTransport, TdiTransportObject); +} + + +NTSTATUS +#ifndef _MSC_VER +STDCALL +#endif +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Main driver entry point + * ARGUMENTS: + * DriverObject = Pointer to a driver object for this driver + * RegistryPath = Registry node for configuration parameters + * RETURNS: + * Status of driver initialization + */ +{ + KEVENT Event; + NTSTATUS Status; + WORK_QUEUE_ITEM WorkItem; + + KeInitializeEvent(&StopEvent, NotificationEvent, FALSE); + KeInitializeEvent(&SendThreadEvent, NotificationEvent, FALSE); + KeInitializeEvent(&ReceiveThreadEvent, NotificationEvent, FALSE); + + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + ExInitializeWorkItem(&WorkItem, TdiOpenThread, &Event); + ExQueueWorkItem(&WorkItem, DelayedWorkQueue); + + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + TRUE, + NULL); + + + Status = PsCreateSystemThread(&SendThread, /* Thread handle */ + 0, /* Desired access */ + NULL, /* Object attributes */ + NULL, /* Process handle */ + NULL, /* Client id */ + (PKSTART_ROUTINE)TdiSendThread, /* Start routine */ + NULL); /* Start context */ + if (!NT_SUCCESS(Status)) { + TDI_DbgPrint(MIN_TRACE, ("PsCreateSystemThread() failed for send thread (Status = 0x%X).\n", Status)); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Get a pointer to the thread object */ + ObReferenceObjectByHandle(SendThread, + THREAD_ALL_ACCESS, + NULL, + KernelMode, + &SendThreadObject, + NULL); + + + Status = PsCreateSystemThread(&ReceiveThread, /* Thread handle */ + 0, /* Desired access */ + NULL, /* Object attributes */ + NULL, /* Process handle */ + NULL, /* Client id */ + (PKSTART_ROUTINE)TdiReceiveThread, /* Start routine */ + NULL); /* Start context */ + if (!NT_SUCCESS(Status)) { + TDI_DbgPrint(MIN_TRACE, ("PsCreateSystemThread() failed for receive thread (Status = 0x%X).\n", Status)); + ZwClose(SendThread); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Get a pointer to the thread object */ + ObReferenceObjectByHandle(ReceiveThread, + THREAD_ALL_ACCESS, + NULL, + KernelMode, + &ReceiveThreadObject, + NULL); + + /* Don't need these for anything, so we might as well close them now. + The threads will call PsTerminateSystemThread themselves when they are done */ + ZwClose(SendThread); + ZwClose(ReceiveThread); + + DriverObject->DriverUnload = (PDRIVER_UNLOAD)TdiUnload; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/drivers/net/wshtcpip/.cvsignore b/drivers/net/wshtcpip/.cvsignore new file mode 100644 index 0000000..d64b399 --- /dev/null +++ b/drivers/net/wshtcpip/.cvsignore @@ -0,0 +1,10 @@ +wshtcpip.a +wshtcpip.dll +wshtcpip.nostrip.dll +wshtcpip.coff +base.tmp +junk.tmp +temp.exp +*.d +*.o +*.sym diff --git a/drivers/net/wshtcpip/debug.h b/drivers/net/wshtcpip/debug.h new file mode 100644 index 0000000..ec9e995 --- /dev/null +++ b/drivers/net/wshtcpip/debug.h @@ -0,0 +1,65 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock Helper DLL for TCP/IP + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define WSH_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { WSH_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define WSH_DbgPrint(_t_, _x_) + +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + WSH_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \ + please try again later.\n", __FILE__, __LINE__, __FUNCTION__)); + +#define CHECKPOINT \ + WSH_DbgPrint(MIN_TRACE, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/drivers/net/wshtcpip/makefile b/drivers/net/wshtcpip/makefile new file mode 100644 index 0000000..a398024 --- /dev/null +++ b/drivers/net/wshtcpip/makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = wshtcpip + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = -DUNICODE + +TARGET_SDKLIBS = ntdll.a kernel32.a ws2_32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/net/wshtcpip/wshtcpip.c b/drivers/net/wshtcpip/wshtcpip.c new file mode 100644 index 0000000..84d316d --- /dev/null +++ b/drivers/net/wshtcpip/wshtcpip.c @@ -0,0 +1,397 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock Helper DLL for TCP/IP + * FILE: wshtcpip.c + * PURPOSE: DLL entry + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + +/* To make the linker happy */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +BOOL +EXPORT +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + WSH_DbgPrint(MIN_TRACE, ("DllMain of wshtcpip.dll\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications + so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + +INT +EXPORT +WSHAddressToString( + IN LPSOCKADDR Address, + IN INT AddressLength, + IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, + OUT LPWSTR AddressString, + IN OUT LPDWORD AddressStringLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHEnumProtocols( + IN LPINT lpiProtocols OPTIONAL, + IN LPWSTR lpTransportKeyName, + IN OUT LPVOID lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHGetBroadcastSockaddr( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHGetProviderGuid( + IN LPWSTR ProviderName, + OUT LPGUID ProviderGuid) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHGetSockaddrType( + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + OUT PSOCKADDR_INFO SockaddrInfo) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHGetSocketInformation( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + OUT PCHAR OptionValue, + OUT INT OptionLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHGetWildcardSockaddr( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength) +{ + UNIMPLEMENTED + + return 0; +} + + +DWORD +EXPORT +WSHGetWinsockMapping( + OUT PWINSOCK_MAPPING Mapping, + IN DWORD MappingLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHGetWSAProtocolInfo( + IN LPWSTR ProviderName, + OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, + OUT LPDWORD ProtocolInfoEntries) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHIoctl( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD IoControlCode, + IN LPVOID InputBuffer, + IN DWORD InputBufferLength, + IN LPVOID OutputBuffer, + IN DWORD OutputBufferLength, + OUT LPDWORD NumberOfBytesReturned, + IN LPWSAOVERLAPPED Overlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, + OUT LPBOOL NeedsCompletion) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHJoinLeaf( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN PVOID LeafHelperDllSocketContext, + IN SOCKET LeafSocketHandle, + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + IN LPWSABUF CallerData, + IN LPWSABUF CalleeData, + IN LPQOS SocketQOS, + IN LPQOS GroupQOS, + IN DWORD Flags) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHNotify( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD NotifyEvent) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHOpenSocket( + IN OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID HelperDllSocketContext, + OUT PDWORD NotificationEvents) +/* + * FUNCTION: Opens a socket + */ +{ + return WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + 0, + 0, + TransportDeviceName, + HelperDllSocketContext, + NotificationEvents); +} + + +INT +EXPORT +WSHOpenSocket2( + OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + IN GROUP Group, + IN DWORD Flags, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID *HelperDllSocketContext, + OUT PDWORD NotificationEvents) +/* + * FUNCTION: Opens a socket + * ARGUMENTS: + * AddressFamily = Address of buffer with address family (updated) + * SocketType = Address of buffer with type of socket (updated) + * Protocol = Address of buffer with protocol number (updated) + * Group = Socket group + * Flags = Socket flags + * TransportDeviceName = Address of buffer to place name of transport device + * HelperDllSocketContext = Address of buffer to place socket context pointer + * NotificationEvents = Address of buffer to place flags for event notification + * RETURNS: + * Status of operation + * NOTES: + * Mapping tripple is returned in an canonicalized form + */ +{ + PSOCKET_CONTEXT Context; + UNICODE_STRING String; + NTSTATUS Status; + + WSH_DbgPrint(MAX_TRACE, ("\n")); + + switch (*SocketType) { + case SOCK_STREAM: + RtlInitUnicodeStringFromLiteral(&String, DD_TCP_DEVICE_NAME); + break; + + case SOCK_DGRAM: + RtlInitUnicodeStringFromLiteral(&String, DD_UDP_DEVICE_NAME); + break; + + case SOCK_RAW: + if ((*Protocol < 0) || (*Protocol > 255)) + return WSAEINVAL; + + RtlInitUnicodeStringFromLiteral(&String, DD_RAW_IP_DEVICE_NAME); + break; + + default: + return WSAEINVAL; + } + + RtlInitUnicodeString(TransportDeviceName, NULL); + + TransportDeviceName->MaximumLength = String.Length + /* Transport device name */ + (4 * sizeof(WCHAR) + /* Separator and protocol */ + sizeof(UNICODE_NULL)); /* Terminating null */ + + TransportDeviceName->Buffer = HeapAlloc( + GetProcessHeap(), + 0, + TransportDeviceName->MaximumLength); + + if (!TransportDeviceName->Buffer) + return WSAENOBUFS; + + /* Append the transport device name */ + Status = RtlAppendUnicodeStringToString(TransportDeviceName, &String); + + if (*SocketType == SOCK_RAW) { + /* Append a separator */ + TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR; + TransportDeviceName->Length += sizeof(WCHAR); + TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL; + + /* Append the protocol number */ + String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR)); + String.Length = 0; + String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length; + + Status = RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String); + + TransportDeviceName->Length += String.Length; + } + + /* Setup a socket context area */ + + Context = HeapAlloc(GetProcessHeap(), 0, sizeof(SOCKET_CONTEXT)); + if (!Context) { + RtlFreeUnicodeString(TransportDeviceName); + return WSAENOBUFS; + } + + Context->AddressFamily = *AddressFamily; + Context->SocketType = *SocketType; + Context->Protocol = *Protocol; + Context->Flags = Flags; + + *HelperDllSocketContext = Context; + + return NO_ERROR; +} + + +INT +EXPORT +WSHSetSocketInformation( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + IN PCHAR OptionValue, + IN INT OptionLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSHStringToAddress( + IN LPWSTR AddressString, + IN DWORD AddressFamily, + IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, + OUT LPSOCKADDR Address, + IN OUT LPDWORD AddressStringLength) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/drivers/net/wshtcpip/wshtcpip.def b/drivers/net/wshtcpip/wshtcpip.def new file mode 100644 index 0000000..f4f70d6 --- /dev/null +++ b/drivers/net/wshtcpip/wshtcpip.def @@ -0,0 +1,23 @@ +; WSHTCPIP.DLL - Windows Sockets Helper DLL for TCP/IP + +LIBRARY wshtcpip.dll + +EXPORTS +WSHAddressToString@20 +WSHEnumProtocols@16 +WSHGetBroadcastSockaddr@12 +WSHGetProviderGuid@8 +WSHGetSockaddrType@12 +WSHGetSocketInformation@32 +WSHGetWildcardSockaddr@12 +WSHGetWinsockMapping@8 +WSHGetWSAProtocolInfo@12 +WSHIoctl@52 +WSHJoinLeaf@52 +WSHNotify@20 +WSHOpenSocket@24 +WSHOpenSocket2@32 +WSHSetSocketInformation@32 +WSHStringToAddress@20 + +; EOF diff --git a/drivers/net/wshtcpip/wshtcpip.edf b/drivers/net/wshtcpip/wshtcpip.edf new file mode 100644 index 0000000..80c9db3 --- /dev/null +++ b/drivers/net/wshtcpip/wshtcpip.edf @@ -0,0 +1,23 @@ +; WSHTCPIP.DLL - Windows Sockets Helper DLL for TCP/IP + +LIBRARY wshtcpip.dll + +EXPORTS +WSHAddressToString=WSHAddressToString@20 +WSHEnumProtocols=WSHEnumProtocols@16 +WSHGetBroadcastSockaddr=WSHGetBroadcastSockaddr@12 +WSHGetProviderGuid=WSHGetProviderGuid@8 +WSHGetSockaddrType=WSHGetSockaddrType@12 +WSHGetSocketInformation=WSHGetSocketInformation@32 +WSHGetWildcardSockaddr=WSHGetWildcardSockaddr@12 +WSHGetWinsockMapping=WSHGetWinsockMapping@8 +WSHGetWSAProtocolInfo=WSHGetWSAProtocolInfo@12 +WSHIoctl=WSHIoctl@52 +WSHJoinLeaf=WSHJoinLeaf@52 +WSHNotify=WSHNotify@20 +WSHOpenSocket=WSHOpenSocket@24 +WSHOpenSocket2=WSHOpenSocket2@32 +WSHSetSocketInformation=WSHSetSocketInformation@32 +WSHStringToAddress=WSHStringToAddress@20 + +; EOF diff --git a/drivers/net/wshtcpip/wshtcpip.h b/drivers/net/wshtcpip/wshtcpip.h new file mode 100644 index 0000000..3f52842 --- /dev/null +++ b/drivers/net/wshtcpip/wshtcpip.h @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock Helper DLL for TCP/IP + * FILE: include/wshtcpip.h + * PURPOSE: WinSock Helper DLL for TCP/IP header + */ +#ifndef __WSHTCPIP_H +#define __WSHTCPIP_H + +#include +#include +#include +#include + +#define EXPORT STDCALL + +#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') + +#define DD_TCP_DEVICE_NAME L"\\Device\\Tcp" +#define DD_UDP_DEVICE_NAME L"\\Device\\Udp" +#define DD_RAW_IP_DEVICE_NAME L"\\Device\\RawIp" + + +typedef struct _SOCKET_CONTEXT { + INT AddressFamily; + INT SocketType; + INT Protocol; + DWORD Flags; +} SOCKET_CONTEXT, *PSOCKET_CONTEXT; + +#endif /* __WSHTCPIP_H */ + +/* EOF */ diff --git a/drivers/net/wshtcpip/wshtcpip.rc b/drivers/net/wshtcpip/wshtcpip.rc new file mode 100644 index 0000000..ec734e4 --- /dev/null +++ b/drivers/net/wshtcpip/wshtcpip.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Windows Sockets 2 API\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ws2_32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ws2_32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/drivers/net/wshtcpip/wshtcpip_specs b/drivers/net/wshtcpip/wshtcpip_specs new file mode 100644 index 0000000..02ba08d --- /dev/null +++ b/drivers/net/wshtcpip/wshtcpip_specs @@ -0,0 +1,78 @@ +*asm: + + +*asm_final: + + +*cpp: +-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} + +*cc1: +%(cc1_spec) + +*cc1plus: + + +*endfile: + + +*link: +%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMain@12} + +*lib: + + +*libgcc: +-lgcc + +*startfile: + + +*switches_need_spaces: + + +*signed_char: +%{funsigned-char:-D__CHAR_UNSIGNED__} + +*predefines: +-Di386 -D_WIN32 -DWIN32 -D__WIN32__ -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D_stdcall=__attribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)=__attribute__((x)) -Asystem(winnt) -Acpu(i386) -Amachine(i386) + +*cross_compile: +1 + +*version: +egcs-2.91.57 + +*multilib: +. ; + +*multilib_defaults: + + +*multilib_extra: + + +*multilib_matches: + + +*linker: +collect2 + +*cpp_486: +%{!ansi:-Di486} -D__i486 -D__i486__ + +*cpp_586: +%{!ansi:-Di586 -Dpentium} -D__i586 -D__i586__ -D__pentium -D__pentium__ + +*cpp_686: +%{!ansi:-Di686 -Dpentiumpro} -D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__ + +*cpp_cpu_default: +%(cpp_586) + +*cpp_cpu: +-Acpu(i386) -Amachine(i386) %{!ansi:-Di386} -D__i386 -D__i386__ %{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} %{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} %{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} %{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}} + +*cc1_cpu: +%{!mcpu*: %{m386:-mcpu=i386 -march=i386} %{mno-486:-mcpu=i386 -march=i386} %{m486:-mcpu=i486 -march=i486} %{mno-386:-mcpu=i486 -march=i486} %{mno-pentium:-mcpu=i486 -march=i486} %{mpentium:-mcpu=pentium} %{mno-pentiumpro:-mcpu=pentium} %{mpentiumpro:-mcpu=pentiumpro}} + diff --git a/drivers/readme b/drivers/readme new file mode 100644 index 0000000..4f9dd7c --- /dev/null +++ b/drivers/readme @@ -0,0 +1,11 @@ +These are a selection of services for the ReactOS kernel. They include + + parallel = parallel port driver + serial = serial port driver + mouse = mouse driver + null = null device driver + ide = IDE (hard disk) driver + keyboard = keyboard driver + loop = Allows accessing a file as a block device + scramdisk = Filesystem encryption driver + event = Sample driver demonstrating notifying a user thread using an event diff --git a/drivers/storage/atapi/.cvsignore b/drivers/storage/atapi/.cvsignore new file mode 100644 index 0000000..b44c068 --- /dev/null +++ b/drivers/storage/atapi/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +atapi.coff +atapi.sys.unstripped diff --git a/drivers/storage/atapi/atapi.c b/drivers/storage/atapi/atapi.c new file mode 100644 index 0000000..be4eaff --- /dev/null +++ b/drivers/storage/atapi/atapi.c @@ -0,0 +1,2146 @@ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS ATAPI miniport driver + * FILE: services/storage/atapi/atapi.c + * PURPOSE: ATAPI miniport driver + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) + * REVISIONS: + * 09-09-2001 Created + */ + +/* + * Note: + * This driver is derived from Rex Jolliff's ide driver. Lots of his + * routines are still in here although they belong into the higher level + * drivers. They will be moved away as soon as possible. + */ + +/* + * TODO: + * - implement sending of atapi commands + * - handle removable atapi non-cdrom drives + */ + +#define ENABLE_PCI +#define ENABLE_ISA + +// ------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include "atapi.h" + +#define NDEBUG +#include + +#define VERSION "0.0.1" + + +// ------------------------------------------------------- File Static Data + +// ATAPI_MINIPORT_EXTENSION +// +// DESCRIPTION: +// Extension to be placed in each port device object +// +// ACCESS: +// Allocated from NON-PAGED POOL +// Available at any IRQL +// + +typedef struct _ATAPI_MINIPORT_EXTENSION +{ + IDE_DRIVE_IDENTIFY DeviceParams[2]; + BOOLEAN DevicePresent[2]; + BOOLEAN DeviceAtapi[2]; + + ULONG CommandPortBase; + ULONG ControlPortBase; + ULONG BusMasterRegisterBase; + + BOOLEAN ExpectingInterrupt; + PSCSI_REQUEST_BLOCK CurrentSrb; + + PUSHORT DataBuffer; +} ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION; + + +typedef struct _UNIT_EXTENSION +{ + ULONG Dummy; +} UNIT_EXTENSION, *PUNIT_EXTENSION; + + +// ----------------------------------------------- Discardable Declarations + +#ifdef ALLOC_PRAGMA + +// make the initialization routines discardable, so that they +// don't waste space + +#pragma alloc_text(init, DriverEntry) +#pragma alloc_text(init, IDECreateController) +#pragma alloc_text(init, IDEPolledRead) + +// make the PASSIVE_LEVEL routines pageable, so that they don't +// waste nonpaged memory + +#pragma alloc_text(page, IDEShutdown) +#pragma alloc_text(page, IDEDispatchOpenClose) +#pragma alloc_text(page, IDEDispatchRead) +#pragma alloc_text(page, IDEDispatchWrite) + +#endif /* ALLOC_PRAGMA */ + +// ---------------------------------------------------- Forward Declarations + +static ULONG STDCALL +AtapiFindCompatiblePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again); + +static ULONG STDCALL +AtapiFindIsaBusController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again); + +static ULONG STDCALL +AtapiFindNativePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again); + +static BOOLEAN STDCALL +AtapiInitialize(IN PVOID DeviceExtension); + +static BOOLEAN STDCALL +AtapiResetBus(IN PVOID DeviceExtension, + IN ULONG PathId); + +static BOOLEAN STDCALL +AtapiStartIo(IN PVOID DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static BOOLEAN STDCALL +AtapiInterrupt(IN PVOID DeviceExtension); + +static BOOLEAN +AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PPORT_CONFIGURATION_INFORMATION ConfigInfo); + +static BOOLEAN +AtapiIdentifyDevice(IN ULONG CommandPort, + IN ULONG ControlPort, + IN ULONG DriveNum, + IN BOOLEAN Atapi, + OUT PIDE_DRIVE_IDENTIFY DrvParms); + +static BOOLEAN +IDEResetController(IN ULONG CommandPort, + IN ULONG ControlPort); + +static int +AtapiPolledRead(IN ULONG CommandPort, + IN ULONG ControlPort, + IN BYTE PreComp, + IN BYTE SectorCnt, + IN BYTE SectorNum, + IN BYTE CylinderLow, + IN BYTE CylinderHigh, + IN BYTE DrvHead, + IN BYTE Command, + OUT BYTE *Buffer); + + + +static ULONG +AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static ULONG +AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static ULONG +AtapiInquiry(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static ULONG +AtapiReadCapacity(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +static ULONG +AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + + +static UCHAR +AtapiErrorToScsi(PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb); + +// ---------------------------------------------------------------- Inlines + +void +IDESwapBytePairs(char *Buf, + int Cnt) +{ + char t; + int i; + + for (i = 0; i < Cnt; i += 2) + { + t = Buf[i]; + Buf[i] = Buf[i+1]; + Buf[i+1] = t; + } +} + + +// ------------------------------------------------------- Public Interface + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver, locates and claims +// hardware resources, and creates various NT objects needed +// to process I/O requests. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject System allocated Driver Object +// for this driver +// IN PUNICODE_STRING RegistryPath Name of registry driver service +// key +// +// RETURNS: +// NTSTATUS + +STDCALL NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + HW_INITIALIZATION_DATA InitData; + NTSTATUS Status; + + DPRINT("ATAPI Driver %s\n", VERSION); + DPRINT("RegistryPath: '%wZ'\n", RegistryPath); + + /* Initialize data structure */ + RtlZeroMemory(&InitData, + sizeof(HW_INITIALIZATION_DATA)); + InitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); + InitData.HwInitialize = AtapiInitialize; + InitData.HwResetBus = AtapiResetBus; + InitData.HwStartIo = AtapiStartIo; + InitData.HwInterrupt = AtapiInterrupt; + + InitData.DeviceExtensionSize = sizeof(ATAPI_MINIPORT_EXTENSION); + InitData.SpecificLuExtensionSize = sizeof(UNIT_EXTENSION); + + InitData.MapBuffers = TRUE; + + /* Search the PCI bus for compatibility mode ide controllers */ +#ifdef ENABLE_PCI + InitData.HwFindAdapter = AtapiFindCompatiblePciController; + InitData.NumberOfAccessRanges = 3; + InitData.AdapterInterfaceType = PCIBus; + + InitData.VendorId = NULL; + InitData.VendorIdLength = 0; + InitData.DeviceId = NULL; + InitData.DeviceIdLength = 0; + + Status = ScsiPortInitialize(DriverObject, + RegistryPath, + &InitData, + NULL); +// if (newStatus < statusToReturn) +// statusToReturn = newStatus; +#endif + + /* Search the ISA bus for ide controllers */ +#ifdef ENABLE_ISA + InitData.HwFindAdapter = AtapiFindIsaBusController; + InitData.NumberOfAccessRanges = 2; + InitData.AdapterInterfaceType = Isa; + + InitData.VendorId = NULL; + InitData.VendorIdLength = 0; + InitData.DeviceId = NULL; + InitData.DeviceIdLength = 0; + + Status = ScsiPortInitialize(DriverObject, + RegistryPath, + &InitData, + NULL); +// if (newStatus < statusToReturn) +// statusToReturn = newStatus; +#endif + + /* Search the PCI bus for native mode ide controllers */ +#if 0 + InitData.HwFindAdapter = AtapiFindNativePciController; + InitData.NumberOfAccessRanges = 2; + InitData.AdapterInterfaceType = PCIBus; + + InitData.VendorId = NULL; + InitData.VendorIdLength = 0; + InitData.DeviceId = NULL; + InitData.DeviceIdLength = 0; + + Status = ScsiPortInitialize(DriverObject, + RegistryPath, + &InitData, + (PVOID)i); +// if (newStatus < statusToReturn) +// statusToReturn = newStatus; +#endif + + DPRINT("Returning from DriverEntry\n"); + + return(Status); +} + + +static ULONG STDCALL +AtapiFindCompatiblePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again) +{ + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciConfig; + ULONG DataSize; + ULONG FunctionNumber; + BOOLEAN ChannelFound; + BOOLEAN DeviceFound; + + DPRINT("AtapiFindCompatiblePciController() Bus: %lu Slot: %lu\n", + ConfigInfo->SystemIoBusNumber, + ConfigInfo->SlotNumber); + + *Again = FALSE; + + /* both channels were claimed: exit */ + if (ConfigInfo->AtdiskPrimaryClaimed == TRUE && + ConfigInfo->AtdiskSecondaryClaimed == TRUE) + return(SP_RETURN_NOT_FOUND); + + + SlotNumber.u.AsULONG = 0; + for (FunctionNumber = 0 /*ConfigInfo->SlotNumber*/; FunctionNumber < 256; FunctionNumber++) + { + SlotNumber.u.AsULONG = FunctionNumber; + + ChannelFound = FALSE; + DeviceFound = FALSE; + + DataSize = ScsiPortGetBusData(DeviceExtension, + PCIConfiguration, + 0, + SlotNumber.u.AsULONG, + &PciConfig, + sizeof(PCI_COMMON_CONFIG)); +// if (DataSize != sizeof(PCI_COMMON_CONFIG) || +// PciConfig.VendorID == PCI_INVALID_VENDORID) + if (DataSize == 0) + { +// if ((SlotNumber.u.AsULONG & 0x07) == 0) +// return(SP_RETURN_ERROR); /* No bus found */ + + continue; +// return(SP_RETURN_ERROR); + } + + if (PciConfig.BaseClass == 0x01 && + PciConfig.SubClass == 0x01) // && +// (PciConfig.ProgIf & 0x05) == 0) + { + /* both channels are in compatibility mode */ + DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n", + ConfigInfo->SystemIoBusNumber, + SlotNumber.u.bits.DeviceNumber, + SlotNumber.u.bits.FunctionNumber, + PciConfig.VendorID, + PciConfig.DeviceID); + DPRINT("ProgIF 0x%02hx\n", PciConfig.ProgIf); + + DPRINT("Found IDE controller in compatibility mode!\n"); + + ConfigInfo->NumberOfBuses = 1; + ConfigInfo->MaximumNumberOfTargets = 2; + ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */ + + if (PciConfig.ProgIf & 0x80) + { + DPRINT("Found IDE Bus Master controller!\n"); + if (PciConfig.u.type0.BaseAddresses[4] & 0x00000001) + { + DPRINT(" IDE Bus Master Registers at IO %lx\n", + PciConfig.u.type0.BaseAddresses[4] & ~0x00000003); + } + } + + if (ConfigInfo->AtdiskPrimaryClaimed == FALSE) + { + /* Both channels unclaimed: Claim primary channel */ + DPRINT("Primary channel!\n"); + + DevExt->CommandPortBase = 0x01F0; + DevExt->ControlPortBase = 0x03F6; + + ConfigInfo->BusInterruptLevel = 14; + ConfigInfo->BusInterruptVector = 14; + ConfigInfo->InterruptMode = LevelSensitive; + + ConfigInfo->AccessRanges[0].RangeStart = + ScsiPortConvertUlongToPhysicalAddress(0x01F0); + ConfigInfo->AccessRanges[0].RangeLength = 8; + ConfigInfo->AccessRanges[0].RangeInMemory = FALSE; + + ConfigInfo->AccessRanges[1].RangeStart = + ScsiPortConvertUlongToPhysicalAddress(0x03F6); + ConfigInfo->AccessRanges[1].RangeLength = 1; + ConfigInfo->AccessRanges[1].RangeInMemory = FALSE; + + /* Claim bus master registers */ + if (PciConfig.ProgIf & 0x80) + { + DevExt->BusMasterRegisterBase = + PciConfig.u.type0.BaseAddresses[4] & ~0x00000003; + + ConfigInfo->AccessRanges[2].RangeStart = + ScsiPortConvertUlongToPhysicalAddress(DevExt->BusMasterRegisterBase); + ConfigInfo->AccessRanges[2].RangeLength = 8; + ConfigInfo->AccessRanges[2].RangeInMemory = FALSE; + } + + ConfigInfo->AtdiskPrimaryClaimed = TRUE; + ChannelFound = TRUE; + *Again = TRUE; + } + else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE) + { + /* Primary channel already claimed: claim secondary channel */ + DPRINT("Secondary channel!\n"); + + DevExt->CommandPortBase = 0x0170; + DevExt->ControlPortBase = 0x0376; + + ConfigInfo->BusInterruptLevel = 15; + ConfigInfo->BusInterruptVector = 15; + ConfigInfo->InterruptMode = LevelSensitive; + + ConfigInfo->AccessRanges[0].RangeStart = + ScsiPortConvertUlongToPhysicalAddress(0x0170); + ConfigInfo->AccessRanges[0].RangeLength = 8; + ConfigInfo->AccessRanges[0].RangeInMemory = FALSE; + + ConfigInfo->AccessRanges[1].RangeStart = + ScsiPortConvertUlongToPhysicalAddress(0x0376); + ConfigInfo->AccessRanges[1].RangeLength = 1; + ConfigInfo->AccessRanges[1].RangeInMemory = FALSE; + + /* Claim bus master registers */ + if (PciConfig.ProgIf & 0x80) + { + DevExt->BusMasterRegisterBase = + (PciConfig.u.type0.BaseAddresses[4] & ~0x00000003) + 8; + + ConfigInfo->AccessRanges[2].RangeStart = + ScsiPortConvertUlongToPhysicalAddress(DevExt->BusMasterRegisterBase); + ConfigInfo->AccessRanges[2].RangeLength = 8; + ConfigInfo->AccessRanges[2].RangeInMemory = FALSE; + } + + ConfigInfo->AtdiskSecondaryClaimed = TRUE; + ChannelFound = TRUE; + *Again = FALSE; + } + + /* Find attached devices */ + if (ChannelFound == TRUE) + { + DeviceFound = AtapiFindDevices(DevExt, + ConfigInfo); + } + DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n"); + return(SP_RETURN_FOUND); + } + } + + DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_NOT_FOUND\n"); + + return(SP_RETURN_NOT_FOUND); +} + + +static ULONG STDCALL +AtapiFindIsaBusController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again) +{ + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + BOOLEAN ChannelFound = FALSE; + BOOLEAN DeviceFound = FALSE; + + DPRINT("AtapiFindIsaBusController() called!\n"); + + *Again = FALSE; + + ConfigInfo->NumberOfBuses = 1; + ConfigInfo->MaximumNumberOfTargets = 2; + ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */ + + if (ConfigInfo->AtdiskPrimaryClaimed == FALSE) + { + /* Both channels unclaimed: Claim primary channel */ + DPRINT("Primary channel!\n"); + + DevExt->CommandPortBase = 0x01F0; + DevExt->ControlPortBase = 0x03F6; + + ConfigInfo->BusInterruptLevel = 14; + ConfigInfo->BusInterruptVector = 14; + ConfigInfo->InterruptMode = LevelSensitive; + + ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x01F0); + ConfigInfo->AccessRanges[0].RangeLength = 8; + ConfigInfo->AccessRanges[0].RangeInMemory = FALSE; + + ConfigInfo->AccessRanges[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x03F6); + ConfigInfo->AccessRanges[1].RangeLength = 1; + ConfigInfo->AccessRanges[1].RangeInMemory = FALSE; + + ConfigInfo->AtdiskPrimaryClaimed = TRUE; + ChannelFound = TRUE; + *Again = FALSE/*TRUE*/; + } + else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE) + { + /* Primary channel already claimed: claim secondary channel */ + DPRINT("Secondary channel!\n"); + + DevExt->CommandPortBase = 0x0170; + DevExt->ControlPortBase = 0x0376; + + ConfigInfo->BusInterruptLevel = 15; + ConfigInfo->BusInterruptVector = 15; + ConfigInfo->InterruptMode = LevelSensitive; + + ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0170); + ConfigInfo->AccessRanges[0].RangeLength = 8; + ConfigInfo->AccessRanges[0].RangeInMemory = FALSE; + + ConfigInfo->AccessRanges[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0376); + ConfigInfo->AccessRanges[1].RangeLength = 1; + ConfigInfo->AccessRanges[1].RangeInMemory = FALSE; + + ConfigInfo->AtdiskSecondaryClaimed = TRUE; + ChannelFound = TRUE; + *Again = FALSE; + } + else + { + DPRINT("AtapiFindIsaBusController() both channels claimed. Returns: SP_RETURN_NOT_FOUND\n"); + *Again = FALSE; + return(SP_RETURN_NOT_FOUND); + } + + /* Find attached devices */ + if (ChannelFound) + { + DeviceFound = AtapiFindDevices(DevExt, + ConfigInfo); + } + + DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n"); + return(SP_RETURN_FOUND); +} + + +static ULONG STDCALL +AtapiFindNativePciController(PVOID DeviceExtension, + PVOID HwContext, + PVOID BusInformation, + PCHAR ArgumentString, + PPORT_CONFIGURATION_INFORMATION ConfigInfo, + PBOOLEAN Again) +{ + PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + + DPRINT("AtapiFindNativePciController() called!\n"); + + *Again = FALSE; + + DPRINT("AtapiFindNativePciController() done!\n"); + + return(SP_RETURN_NOT_FOUND); +} + + +static BOOLEAN STDCALL +AtapiInitialize(IN PVOID DeviceExtension) +{ + return(TRUE); +} + + +static BOOLEAN STDCALL +AtapiResetBus(IN PVOID DeviceExtension, + IN ULONG PathId) +{ + return(TRUE); +} + + +static BOOLEAN STDCALL +AtapiStartIo(IN PVOID DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb) +{ + PATAPI_MINIPORT_EXTENSION DevExt; + ULONG Result; + + DPRINT("AtapiStartIo() called\n"); + + DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + + switch (Srb->Function) + { + case SRB_FUNCTION_EXECUTE_SCSI: + DevExt->CurrentSrb = Srb; + if (DevExt->DeviceAtapi[Srb->TargetId] == TRUE) + { + Result = AtapiSendAtapiCommand(DevExt, + Srb); + } + else + { + Result = AtapiSendIdeCommand(DevExt, + Srb); + } + break; + + } + + Srb->SrbStatus = Result; + + + if (Result != SRB_STATUS_PENDING) + { + DevExt->CurrentSrb = NULL; + Srb->SrbStatus = (UCHAR)Result; + + ScsiPortNotification(RequestComplete, + DeviceExtension, + Srb); + ScsiPortNotification(NextRequest, + DeviceExtension, + NULL); + } + else + { + DPRINT("SrbStatus = SRB_STATUS_PENDING\n"); + } + + DPRINT("AtapiStartIo() done\n"); + + return(TRUE); +} + + +static BOOLEAN STDCALL +AtapiInterrupt(IN PVOID DeviceExtension) +{ + PATAPI_MINIPORT_EXTENSION DevExt; + PSCSI_REQUEST_BLOCK Srb; + ULONG CommandPortBase; + ULONG ControlPortBase; + + UCHAR DeviceStatus; + BOOLEAN IsLastBlock; + BOOLEAN IsAtapi; + ULONG Retries; + PUCHAR TargetAddress; + ULONG SectorSize; + ULONG TransferSize; + + DPRINT("AtapiInterrupt() called!\n"); + + DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + if (DevExt->ExpectingInterrupt == FALSE) + { + DPRINT("AtapiInterrupt(): Unexpected interrupt\n"); + return(FALSE); + } + + Srb = DevExt->CurrentSrb; + DPRINT("Srb: %p\n", Srb); + + CommandPortBase = DevExt->CommandPortBase; + ControlPortBase = DevExt->ControlPortBase; + DPRINT("CommandPortBase: %lx ControlPortBase: %lx\n", CommandPortBase, ControlPortBase); + + IsAtapi = DevExt->DeviceAtapi[Srb->TargetId]; + DPRINT("IsAtapi == %s\n", (IsAtapi) ? "TRUE" : "FALSE"); + + IsLastBlock = FALSE; + + DeviceStatus = IDEReadStatus(CommandPortBase); + DPRINT("DeviceStatus: %x\n", DeviceStatus); + + if (DeviceStatus & IDE_SR_BUSY) + { + /* Wait for BUSY to drop */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + DeviceStatus = IDEReadStatus(CommandPortBase); + if (!(DeviceStatus & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(10); + } + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT1("Drive is BUSY for too long\n"); + /* FIXME: handle timeout */ + } + } + + if ((DeviceStatus & IDE_SR_ERR) && + (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) + { + /* Report error condition */ + Srb->SrbStatus = SRB_STATUS_ERROR; + IsLastBlock = TRUE; + } + else + { + if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) + { + DPRINT("Read data\n"); + + /* Update controller/device state variables */ + TargetAddress = Srb->DataBuffer; + + if (IsAtapi) + { + TransferSize = IDEReadCylinderLow(CommandPortBase); + TransferSize += IDEReadCylinderHigh(CommandPortBase) << 8; + } + else + { + TransferSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector; + } + + DPRINT("TransferLength: %lu\n", Srb->DataTransferLength); + DPRINT("TransferSize: %lu\n", TransferSize); + + if (Srb->DataTransferLength <= TransferSize) + { + Srb->DataTransferLength = 0; + IsLastBlock = TRUE; + } + else + { + Srb->DataTransferLength -= TransferSize; + IsLastBlock = FALSE; + } + Srb->DataBuffer += TransferSize; + DPRINT("IsLastBlock == %s\n", (IsLastBlock) ? "TRUE" : "FALSE"); + + /* Wait for DRQ assertion */ + for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES && + !(IDEReadStatus(CommandPortBase) & IDE_SR_DRQ); + Retries++) + { + KeStallExecutionProcessor(10); + } + + /* Copy the block of data */ + IDEReadBlock(CommandPortBase, + TargetAddress, + TransferSize); + + /* check DRQ */ + if (IsLastBlock) + { + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES && + (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY); + Retries++) + { + KeStallExecutionProcessor(10); + } + + /* Check for data overrun */ + if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ) + { + /* FIXME: Handle error! */ + DPRINT1("AtapiInterrupt(): data overrun error!"); + } + } + + Srb->SrbStatus = SRB_STATUS_SUCCESS; + } + else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) + { + DPRINT("Write data\n"); + + if (Srb->DataTransferLength == 0) + { + + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES && + (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY); + Retries++) + { + KeStallExecutionProcessor(10); + } + + /* Check for data overrun */ + if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ) + { + /* FIXME: Handle error! */ + DPRINT1("AtapiInterrupt(): data overrun error!"); + } + + DevExt->ExpectingInterrupt = FALSE; + IsLastBlock = TRUE; + } + else + { + /* Update SRB data */ + SectorSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector; + + TargetAddress = Srb->DataBuffer; + Srb->DataBuffer += SectorSize; + Srb->DataTransferLength -= SectorSize; + + /* Write the sector */ + IDEWriteBlock(CommandPortBase, + TargetAddress, + SectorSize); + } + + Srb->SrbStatus = SRB_STATUS_SUCCESS; + } + else + { + DPRINT1("Unspecified transfer direction!\n"); + Srb->SrbStatus = SRB_STATUS_SUCCESS; // SRB_STATUS_ERROR; + IsLastBlock = TRUE; + } + } + + + if (Srb->SrbStatus == SRB_STATUS_ERROR) + { + Srb->SrbStatus = AtapiErrorToScsi(DeviceExtension, + Srb); + } + + + /* complete this packet */ + if (IsLastBlock) + { + DevExt->ExpectingInterrupt = FALSE; + + ScsiPortNotification(RequestComplete, + DeviceExtension, + Srb); + + ScsiPortNotification(NextRequest, + DeviceExtension, + NULL); + } + + DPRINT("AtapiInterrupt() done!\n"); + + return(TRUE); +} + + + + + + +// ---------------------------------------------------- Discardable statics + + +/********************************************************************** + * NAME INTERNAL + * AtapiFindDevices + * + * DESCRIPTION + * Searches for devices on the given port. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceExtension + * Port device specific information. + * + * ConfigInfo + * Port configuration information. + * + * RETURN VALUE + * TRUE: At least one device is attached to the port. + * FALSE: No device is attached to the port. + */ + +static BOOLEAN +AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PPORT_CONFIGURATION_INFORMATION ConfigInfo) +{ + BOOLEAN DeviceFound = FALSE; + ULONG CommandPortBase; + ULONG ControlPortBase; + ULONG UnitNumber; + ULONG Retries; + BYTE High, Low; + + DPRINT("AtapiFindDevices() called\n"); + + CommandPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[0].RangeStart); + DPRINT(" CommandPortBase: %x\n", CommandPortBase); + + ControlPortBase = ScsiPortConvertPhysicalAddressToUlong(ConfigInfo->AccessRanges[1].RangeStart); + DPRINT(" ControlPortBase: %x\n", ControlPortBase); + + for (UnitNumber = 0; UnitNumber < 2; UnitNumber++) + { + /* Select drive */ + IDEWriteDriveHead(CommandPortBase, + IDE_DH_FIXED | (UnitNumber ? IDE_DH_DRV1 : 0)); + ScsiPortStallExecution(500); + + /* Disable interrupts */ + IDEWriteDriveControl(ControlPortBase, + IDE_DC_nIEN); + ScsiPortStallExecution(500); + + IDEWriteCylinderHigh(CommandPortBase, 0); + IDEWriteCylinderLow(CommandPortBase, 0); + IDEWriteCommand(CommandPortBase, IDE_CMD_RESET); + + for (Retries = 0; Retries < 20000; Retries++) + { + if (!(IDEReadStatus(CommandPortBase) & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(150); + } + if (Retries >= 20000) + { + DPRINT("Timeout on drive %lu\n", UnitNumber); + DeviceExtension->DevicePresent[UnitNumber] = FALSE; + continue; + } + + High = IDEReadCylinderHigh(CommandPortBase); + Low = IDEReadCylinderLow(CommandPortBase); + + DPRINT(" Check drive %lu: High 0x%x Low 0x%x\n", + UnitNumber, + High, + Low); + + if (High == 0xEB && Low == 0x14) + { + if (AtapiIdentifyDevice(CommandPortBase, + ControlPortBase, + UnitNumber, + TRUE, + &DeviceExtension->DeviceParams[UnitNumber])) + { + DPRINT(" ATAPI drive found!\n"); + DeviceExtension->DevicePresent[UnitNumber] = TRUE; + DeviceExtension->DeviceAtapi[UnitNumber] = TRUE; + DeviceFound = TRUE; + } + else + { + DPRINT(" No ATAPI drive found!\n"); + } + } + else + { + if (AtapiIdentifyDevice(CommandPortBase, + ControlPortBase, + UnitNumber, + FALSE, + &DeviceExtension->DeviceParams[UnitNumber])) + { + DPRINT(" IDE drive found!\n"); + DeviceExtension->DevicePresent[UnitNumber] = TRUE; + DeviceExtension->DeviceAtapi[UnitNumber] = FALSE; + DeviceFound = TRUE; + } + else + { + DPRINT(" No IDE drive found!\n"); + } + } + } + + + DPRINT("AtapiFindDrives() done (DeviceFound %s)\n", (DeviceFound) ? "TRUE" : "FALSE"); + + return(DeviceFound); +} + + +// AtapiResetController +// +// DESCRIPTION: +// Reset the controller and report completion status +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN WORD CommandPort The address of the command port +// IN WORD ControlPort The address of the control port +// +// RETURNS: +// + +static BOOLEAN +AtapiResetController(IN ULONG CommandPort, + IN ULONG ControlPort) +{ + int Retries; + + /* Assert drive reset line */ + IDEWriteDriveControl(ControlPort, IDE_DC_SRST); + + /* Wait for min. 25 microseconds */ + ScsiPortStallExecution(IDE_RESET_PULSE_LENGTH); + + /* Negate drive reset line */ + IDEWriteDriveControl(ControlPort, 0); + + /* Wait for BUSY negation */ + for (Retries = 0; Retries < IDE_RESET_BUSY_TIMEOUT * 1000; Retries++) + { + if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(10); + } + + if (Retries >= IDE_RESET_BUSY_TIMEOUT * 1000) + { + return(FALSE); + } + + // return TRUE if controller came back to life. and + // the registers are initialized correctly + return(IDEReadError(CommandPort) == 1); +} + +/* + * AtapiIdentifyDevice + * + * DESCRIPTION: + * Get the identification block from the drive + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * CommandPort + * Address of the command port + * ControlPort + * Address of the control port + * DriveNum + * The drive index (0,1) + * Atapi + * Send an ATA(FALSE) or an ATAPI(TRUE) identify comand + * DrvParms + * Address to write drive ident block + * + * RETURNS: + * TRUE: The drive identification block was retrieved successfully + * FALSE: an error ocurred + */ + +static BOOLEAN +AtapiIdentifyDevice(IN ULONG CommandPort, + IN ULONG ControlPort, + IN ULONG DriveNum, + IN BOOLEAN Atapi, + OUT PIDE_DRIVE_IDENTIFY DrvParms) +{ + LONG i; + + /* Get the Drive Identify block from drive or die */ + if (AtapiPolledRead(CommandPort, + ControlPort, + 0, + 1, + 0, + 0, + 0, + (DriveNum ? IDE_DH_DRV1 : 0), + (Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV), + (BYTE *)DrvParms) != 0) + { + DPRINT("IDEPolledRead() failed\n"); + return(FALSE); + } + + /* Report on drive parameters if debug mode */ + IDESwapBytePairs(DrvParms->SerialNumber, 20); + IDESwapBytePairs(DrvParms->FirmwareRev, 8); + IDESwapBytePairs(DrvParms->ModelNumber, 40); + DPRINT("Config:%04x Cyls:%5d Heads:%2d Sectors/Track:%3d Gaps:%02d %02d\n", + DrvParms->ConfigBits, + DrvParms->LogicalCyls, + DrvParms->LogicalHeads, + DrvParms->SectorsPerTrack, + DrvParms->InterSectorGap, + DrvParms->InterSectorGapSize); + DPRINT("Bytes/PLO:%3d Vendor Cnt:%2d Serial number:[%.20s]\n", + DrvParms->BytesInPLO, + DrvParms->VendorUniqueCnt, + DrvParms->SerialNumber); + DPRINT("Cntlr type:%2d BufSiz:%5d ECC bytes:%3d Firmware Rev:[%.8s]\n", + DrvParms->ControllerType, + DrvParms->BufferSize * IDE_SECTOR_BUF_SZ, + DrvParms->ECCByteCnt, + DrvParms->FirmwareRev); + DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber); + DPRINT("RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n", + (DrvParms->RWMultImplemented) & 0xff, + (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0, + (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0, + DrvParms->MinPIOTransTime, + DrvParms->MinDMATransTime); + DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%ld\n", + DrvParms->TMCylinders, + DrvParms->TMHeads, + DrvParms->TMSectorsPerTrk, + (ULONG)(DrvParms->TMCapacityLo + (DrvParms->TMCapacityHi << 16))); + DPRINT("TM:SectorCount: 0x%04x%04x = %lu\n", + DrvParms->TMSectorCountHi, + DrvParms->TMSectorCountLo, + (ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo)); + + DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); + if (DrvParms->BytesPerSector == 0) + { + DrvParms->BytesPerSector = 512; + } + else + { + for (i = 15; i >= 0; i--) + { + if (DrvParms->BytesPerSector & (1 << i)) + { + DrvParms->BytesPerSector = 1 << i; + break; + } + } + } + DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector); + + return(TRUE); +} + + +// AtapiPolledRead +// +// DESCRIPTION: +// Read a sector of data from the drive in a polled fashion. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN WORD Address Address of command port for drive +// IN BYTE PreComp Value to write to precomp register +// IN BYTE SectorCnt Value to write to sectorCnt register +// IN BYTE SectorNum Value to write to sectorNum register +// IN BYTE CylinderLow Value to write to CylinderLow register +// IN BYTE CylinderHigh Value to write to CylinderHigh register +// IN BYTE DrvHead Value to write to Drive/Head register +// IN BYTE Command Value to write to Command register +// OUT BYTE *Buffer Buffer for output data +// +// RETURNS: +// int 0 is success, non 0 is an error code +// + +static int +AtapiPolledRead(IN ULONG CommandPort, + IN ULONG ControlPort, + IN BYTE PreComp, + IN BYTE SectorCnt, + IN BYTE SectorNum, + IN BYTE CylinderLow, + IN BYTE CylinderHigh, + IN BYTE DrvHead, + IN BYTE Command, + OUT BYTE *Buffer) +{ + ULONG SectorCount = 0; + ULONG RetryCount; + BOOLEAN Junk = FALSE; + UCHAR Status; + UCHAR Control; + +//#if 0 + /* Wait for BUSY to clear */ + for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) + { + Status = IDEReadStatus(CommandPort); + if (!(Status & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT("status=%02x\n", Status); + DPRINT("waited %ld usecs for busy to clear\n", RetryCount * 10); + if (RetryCount >= IDE_MAX_BUSY_RETRIES) + { + DPRINT("Drive is BUSY for too long\n"); + return(IDE_ER_ABRT); + } +//#endif + + /* Write Drive/Head to select drive */ + IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead); + ScsiPortStallExecution(500); + + /* Disable interrupts */ + Control = IDEReadAltStatus(ControlPort); + IDEWriteDriveControl(ControlPort, Control | IDE_DC_nIEN); + ScsiPortStallExecution(500); + +#if 0 + /* Wait for STATUS.BUSY and STATUS.DRQ to clear */ + for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) + { + Status = IDEReadStatus(CommandPort); + if (!(Status & IDE_SR_BUSY) && !(Status & IDE_SR_DRQ)) + { + break; + } + ScsiPortStallExecution(10); + } + if (RetryCount >= IDE_MAX_BUSY_RETRIES) + { + return IDE_ER_ABRT; + } +#endif + + /* Issue command to drive */ + if (DrvHead & IDE_DH_LBA) + { + DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", + DrvHead & IDE_DH_DRV1 ? 1 : 0, + ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum, + SectorCnt, + Command); + } + else + { + DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", + DrvHead & IDE_DH_DRV1 ? 1 : 0, + CylinderHigh, + CylinderLow, + DrvHead & 0x0f, + SectorNum, + SectorCnt, + Command); + } + + /* Setup command parameters */ + IDEWritePrecomp(CommandPort, PreComp); + IDEWriteSectorCount(CommandPort, SectorCnt); + IDEWriteSectorNum(CommandPort, SectorNum); + IDEWriteCylinderHigh(CommandPort, CylinderHigh); + IDEWriteCylinderLow(CommandPort, CylinderLow); + IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead); + + /* Issue the command */ + IDEWriteCommand(CommandPort, Command); + ScsiPortStallExecution(50); + + /* wait for DRQ or error */ + for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++) + { + Status = IDEReadStatus(CommandPort); + if (!(Status & IDE_SR_BUSY)) + { + if (Status & IDE_SR_ERR) + { + IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN); + return(IDE_ER_ABRT); + } + if (Status & IDE_SR_DRQ) + { + break; + } + else + { + IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN); + return(IDE_ER_ABRT); + } + } + ScsiPortStallExecution(10); + } + + /* timed out */ + if (RetryCount >= IDE_MAX_POLL_RETRIES) + { + IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN); + return(IDE_ER_ABRT); + } + + while (1) + { + /* Read data into buffer */ + if (Junk == FALSE) + { + IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ); + Buffer += IDE_SECTOR_BUF_SZ; + } + else + { + UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ]; + IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ); + } + SectorCount++; + + /* Check for error or more sectors to read */ + for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) + { + Status = IDEReadStatus(CommandPort); + if (!(Status & IDE_SR_BUSY)) + { + if (Status & IDE_SR_ERR) + { + IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN); + return(IDE_ER_ABRT); + } + if (Status & IDE_SR_DRQ) + { + if (SectorCount >= SectorCnt) + { + DPRINT("Buffer size exceeded!\n"); + Junk = TRUE; + } + break; + } + else + { + if (SectorCount > SectorCnt) + { + DPRINT("Read %lu sectors of junk!\n", + SectorCount - SectorCnt); + } + IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN); + return(0); + } + } + } + } +} + + +// ------------------------------------------- Nondiscardable statics + +static ULONG +AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb) +{ + UCHAR ByteCountHigh; + UCHAR ByteCountLow; + ULONG Retries; + ULONG CdbSize; + UCHAR Status; + + DPRINT("AtapiSendAtapiCommand() called!\n"); + + if (Srb->PathId != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID; + return(SRB_STATUS_INVALID_PATH_ID); + } + + if (Srb->TargetId > 1) + { + Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID; + return(SRB_STATUS_INVALID_TARGET_ID); + } + + if (Srb->Lun != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_LUN; + return(SRB_STATUS_INVALID_LUN); + } + + if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE) + { + Srb->SrbStatus = SRB_STATUS_NO_DEVICE; + return(SRB_STATUS_NO_DEVICE); + } + + DPRINT("AtapiSendAtapiCommand(): TargetId: %lu\n", + Srb->TargetId); + + if (Srb->Cdb[0] == SCSIOP_INQUIRY) + return(AtapiInquiry(DeviceExtension, + Srb)); + + /* Set pointer to data buffer. */ + DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer; + DeviceExtension->CurrentSrb = Srb; + + /* Wait for BUSY to clear */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT("status=%02x\n", Status); + DPRINT("waited %ld usecs for busy to clear\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT("Drive is BUSY for too long\n"); + return(SRB_STATUS_BUSY); + } + + /* Select the desired drive */ + IDEWriteDriveHead(DeviceExtension->CommandPortBase, + IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0)); + + /* Wait a little while */ + ScsiPortStallExecution(50); + +#if 0 + /* Wait for BUSY to clear and DRDY to assert */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT("Drive is BUSY for too long after drive select\n"); + return(SRB_STATUS_BUSY); + } +#endif + + if (Srb->DataTransferLength < 0x10000) + { + ByteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF); + ByteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8); + } + else + { + ByteCountLow = 0xFF; + ByteCountHigh = 0xFF; + } + + /* Set feature register */ + IDEWritePrecomp(DeviceExtension->CommandPortBase, 0); + + /* Set command packet length */ + IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, ByteCountHigh); + IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow); + + /* Issue command to drive */ + IDEWriteCommand(DeviceExtension->CommandPortBase, 0xA0); /* Packet command */ + + /* Wait for DRQ to assert */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if ((Status & IDE_SR_DRQ)) + { + break; + } + ScsiPortStallExecution(10); + } + + CdbSize = (DeviceExtension->DeviceParams[Srb->TargetId].ConfigBits & 0x3 == 1) ? 16 : 12; + DPRINT("CdbSize: %lu\n", CdbSize); + + /* Write command packet */ + IDEWriteBlock(DeviceExtension->CommandPortBase, + (PUSHORT)Srb->Cdb, + CdbSize); + + DeviceExtension->ExpectingInterrupt = TRUE; + + DPRINT("AtapiSendAtapiCommand() done\n"); + + return(SRB_STATUS_PENDING); +} + + +static ULONG +AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb) +{ + ULONG SrbStatus = SRB_STATUS_SUCCESS; + + DPRINT("AtapiSendIdeCommand() called!\n"); + + DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", + Srb->PathId, + Srb->TargetId, + Srb->Lun); + + switch (Srb->Cdb[0]) + { + case SCSIOP_INQUIRY: + SrbStatus = AtapiInquiry(DeviceExtension, + Srb); + break; + + case SCSIOP_READ_CAPACITY: + SrbStatus = AtapiReadCapacity(DeviceExtension, + Srb); + break; + + case SCSIOP_READ: + case SCSIOP_WRITE: + SrbStatus = AtapiReadWrite(DeviceExtension, + Srb); + break; + + case SCSIOP_MODE_SENSE: + case SCSIOP_TEST_UNIT_READY: + case SCSIOP_VERIFY: + case SCSIOP_START_STOP_UNIT: + case SCSIOP_REQUEST_SENSE: + break; + + default: + DbgPrint("AtapiSendIdeCommand():unknown command %x\n", + Srb->Cdb[0]); + SrbStatus = SRB_STATUS_INVALID_REQUEST; + break; + } + + DPRINT("AtapiSendIdeCommand() done!\n"); + + return(SrbStatus); +} + + +static ULONG +AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PIDE_DRIVE_IDENTIFY DeviceParams; + PINQUIRYDATA InquiryData; + ULONG i; + + DPRINT("SCSIOP_INQUIRY: DeviceExtension %p TargetId: %lu\n", + DeviceExtension, Srb->TargetId); + + if (Srb->PathId != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID; + return(SRB_STATUS_INVALID_PATH_ID); + } + + if (Srb->TargetId > 1) + { + Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID; + return(SRB_STATUS_INVALID_TARGET_ID); + } + + if (Srb->Lun != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_LUN; + return(SRB_STATUS_INVALID_LUN); + } + + if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE) + { + Srb->SrbStatus = SRB_STATUS_NO_DEVICE; + return(SRB_STATUS_NO_DEVICE); + } + + InquiryData = Srb->DataBuffer; + DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId]; + + /* clear buffer */ + for (i = 0; i < Srb->DataTransferLength; i++) + { + ((PUCHAR)Srb->DataBuffer)[i] = 0; + } + + /* set device class */ + if (DeviceExtension->DeviceAtapi[Srb->TargetId] == FALSE) + { + /* hard-disk */ + InquiryData->DeviceType = DIRECT_ACCESS_DEVICE; + } + else + { + /* get it from the ATAPI configuration word */ + InquiryData->DeviceType = (DeviceParams->ConfigBits >> 8) & 0x1F; + DPRINT("Device class: %u\n", InquiryData->DeviceType); + } + + DPRINT("ConfigBits: 0x%x\n", DeviceParams->ConfigBits); + if (DeviceParams->ConfigBits & 0x80) + { + DPRINT("Removable media!\n"); + InquiryData->RemovableMedia = 1; + } + + for (i = 0; i < 20; i += 2) + { + InquiryData->VendorId[i] = + ((PUCHAR)DeviceParams->ModelNumber)[i]; + InquiryData->VendorId[i+1] = + ((PUCHAR)DeviceParams->ModelNumber)[i+1]; + } + + for (i = 0; i < 4; i++) + { + InquiryData->ProductId[12+i] = ' '; + } + + for (i = 0; i < 4; i += 2) + { + InquiryData->ProductRevisionLevel[i] = + ((PUCHAR)DeviceParams->FirmwareRev)[i]; + InquiryData->ProductRevisionLevel[i+1] = + ((PUCHAR)DeviceParams->FirmwareRev)[i+1]; + } + + DPRINT("VendorId: '%.20s'\n", InquiryData->VendorId); + + Srb->SrbStatus = SRB_STATUS_SUCCESS; + return(SRB_STATUS_SUCCESS); +} + + +static ULONG +AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PREAD_CAPACITY_DATA CapacityData; + PIDE_DRIVE_IDENTIFY DeviceParams; + ULONG LastSector; + + DPRINT("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb->TargetId); + + if (Srb->PathId != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID; + return(SRB_STATUS_INVALID_PATH_ID); + } + + if (Srb->TargetId > 1) + { + Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID; + return(SRB_STATUS_INVALID_TARGET_ID); + } + + if (Srb->Lun != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_LUN; + return(SRB_STATUS_INVALID_LUN); + } + + if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE) + { + Srb->SrbStatus = SRB_STATUS_NO_DEVICE; + return(SRB_STATUS_NO_DEVICE); + } + + CapacityData = (PREAD_CAPACITY_DATA)Srb->DataBuffer; + DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId]; + + /* Set sector (block) size to 512 bytes (big-endian). */ + CapacityData->BytesPerBlock = 0x20000; + + /* Calculate last sector (big-endian). */ + if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED) + { + LastSector = (ULONG)((DeviceParams->TMSectorCountHi << 16) + + DeviceParams->TMSectorCountLo) - 1; + } + else + { + LastSector = (ULONG)(DeviceParams->LogicalCyls * + DeviceParams->LogicalHeads * + DeviceParams->SectorsPerTrack)-1; + } + + CapacityData->LogicalBlockAddress = (((PUCHAR)&LastSector)[0] << 24) | + (((PUCHAR)&LastSector)[1] << 16) | + (((PUCHAR)&LastSector)[2] << 8) | + ((PUCHAR)&LastSector)[3]; + + DPRINT("LastCount: %lu (%08lx / %08lx)\n", + LastSector, + LastSector, + CapacityData->LogicalBlockAddress); + + Srb->SrbStatus = SRB_STATUS_SUCCESS; + return(SRB_STATUS_SUCCESS); +} + + +static ULONG +AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PIDE_DRIVE_IDENTIFY DeviceParams; + ULONG StartingSector; + ULONG SectorCount; + UCHAR CylinderHigh; + UCHAR CylinderLow; + UCHAR DrvHead; + UCHAR SectorNumber; + UCHAR Command; + ULONG Retries; + UCHAR Status; + + DPRINT("AtapiReadWrite() called!\n"); + + if (Srb->PathId != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID; + return(SRB_STATUS_INVALID_PATH_ID); + } + + if (Srb->TargetId > 1) + { + Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID; + return(SRB_STATUS_INVALID_TARGET_ID); + } + + if (Srb->Lun != 0) + { + Srb->SrbStatus = SRB_STATUS_INVALID_LUN; + return(SRB_STATUS_INVALID_LUN); + } + + if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE) + { + Srb->SrbStatus = SRB_STATUS_NO_DEVICE; + return(SRB_STATUS_NO_DEVICE); + } + + DPRINT("SCSIOP_WRITE: TargetId: %lu\n", + Srb->TargetId); + + DeviceParams = &DeviceExtension->DeviceParams[Srb->TargetId]; + + /* Get starting sector number from CDB. */ + StartingSector = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 | + ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 | + ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 | + ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24; + + SectorCount = (Srb->DataTransferLength + DeviceParams->BytesPerSector - 1) / + DeviceParams->BytesPerSector; + + DPRINT("Starting sector %lu Number of bytes %lu Sectors %lu\n", + StartingSector, + Srb->DataTransferLength, + SectorCount); + + if (DeviceParams->Capabilities & IDE_DRID_LBA_SUPPORTED) + { + SectorNumber = StartingSector & 0xff; + CylinderLow = (StartingSector >> 8) & 0xff; + CylinderHigh = (StartingSector >> 16) & 0xff; + DrvHead = ((StartingSector >> 24) & 0x0f) | + (Srb->TargetId ? IDE_DH_DRV1 : 0) | + IDE_DH_LBA; + } + else + { + SectorNumber = (StartingSector % DeviceParams->SectorsPerTrack) + 1; + StartingSector /= DeviceParams->SectorsPerTrack; + DrvHead = (StartingSector % DeviceParams->LogicalHeads) | + (Srb->TargetId ? IDE_DH_DRV1 : 0); + StartingSector /= DeviceParams->LogicalHeads; + CylinderLow = StartingSector & 0xff; + CylinderHigh = StartingSector >> 8; + } + + + if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) + { + Command = IDE_CMD_READ; + } + else + { + Command = IDE_CMD_WRITE; + } + + if (DrvHead & IDE_DH_LBA) + { + DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n", + (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE", + DeviceExtension->CommandPortBase, + DrvHead & IDE_DH_DRV1 ? 1 : 0, + ((DrvHead & 0x0f) << 24) + + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNumber, + SectorCount, + Command); + } + else + { + DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n", + (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE", + DeviceExtension->CommandPortBase, + DrvHead & IDE_DH_DRV1 ? 1 : 0, + CylinderHigh, + CylinderLow, + DrvHead & 0x0f, + SectorNumber, + SectorCount, + Command); + } + + /* Set pointer to data buffer. */ + DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer; + + DeviceExtension->CurrentSrb = Srb; + DeviceExtension->ExpectingInterrupt = TRUE; + + + + /* wait for BUSY to clear */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT("status=%02x\n", Status); + DPRINT("waited %ld usecs for busy to clear\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT ("Drive is BUSY for too long\n"); + return(SRB_STATUS_BUSY); +#if 0 + if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES) + { + DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + DPRINT ("Beginning drive reset sequence\n"); + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } +#endif + } + + /* Select the desired drive */ + IDEWriteDriveHead(DeviceExtension->CommandPortBase, + IDE_DH_FIXED | DrvHead); + + ScsiPortStallExecution(10); +#if 0 + /* wait for BUSY to clear and DRDY to assert */ + for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++) + { + Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY)) + { + break; + } + ScsiPortStallExecution(10); + } + DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries * 10); + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT("Drive is BUSY for too long after drive select\n"); + return(SRB_STATUS_BUSY); +#if 0 + if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES) + { + DbgPrint ("Max Retries on Drive reset reached, returning failure\n"); + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + DPRINT("Beginning drive reset sequence\n"); + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } +#endif + } +#endif + + /* Indicate expecting an interrupt. */ + DeviceExtension->ExpectingInterrupt = TRUE; + + /* Setup command parameters */ + IDEWritePrecomp(DeviceExtension->CommandPortBase, 0); + IDEWriteSectorCount(DeviceExtension->CommandPortBase, SectorCount); + IDEWriteSectorNum(DeviceExtension->CommandPortBase, SectorNumber); + IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, CylinderHigh); + IDEWriteCylinderLow(DeviceExtension->CommandPortBase, CylinderLow); + IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead); + + /* Issue command to drive */ + IDEWriteCommand(DeviceExtension->CommandPortBase, Command); + + /* Write data block */ + if (Command == IDE_CMD_WRITE) + { + PUCHAR TargetAddress; + ULONG SectorSize; + + /* Wait for controller ready */ + for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++) + { + BYTE Status = IDEReadStatus(DeviceExtension->CommandPortBase); + if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR)) + { + break; + } + KeStallExecutionProcessor(10); + } + if (Retries >= IDE_MAX_BUSY_RETRIES) + { + DPRINT("Drive is BUSY for too long after sending write command\n"); + return(SRB_STATUS_BUSY); +#if 0 + if (DeviceExtension->Retries++ > IDE_MAX_CMD_RETRIES) + { + Irp = ControllerExtension->CurrentIrp; + Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; + Irp->IoStatus.Information = 0; + + return FALSE; + } + else + { + IDEBeginControllerReset(ControllerExtension); + + return TRUE; + } +#endif + } + + /* Update SRB data */ + SectorSize = DeviceExtension->DeviceParams[Srb->TargetId].BytesPerSector; + TargetAddress = Srb->DataBuffer; + Srb->DataBuffer += SectorSize; + Srb->DataTransferLength -= SectorSize; + + /* Write data block */ + IDEWriteBlock(DeviceExtension->CommandPortBase, + TargetAddress, + SectorSize); + } + + + DPRINT("AtapiReadWrite() done!\n"); + + /* Wait for interrupt. */ + return(SRB_STATUS_PENDING); +} + + +static UCHAR +AtapiErrorToScsi(PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PATAPI_MINIPORT_EXTENSION DevExt; + ULONG CommandPortBase; + ULONG ControlPortBase; + UCHAR ErrorReg; + UCHAR ScsiStatus; + UCHAR SrbStatus; + + DPRINT("AtapiErrorToScsi() called\n"); + + DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + + CommandPortBase = DevExt->CommandPortBase; + ControlPortBase = DevExt->ControlPortBase; + + ErrorReg = IDEReadError(CommandPortBase); + + if (DevExt->DeviceAtapi[Srb->TargetId]) + { + switch (ErrorReg >> 4) + { + case SCSI_SENSE_NO_SENSE: + DPRINT("ATAPI error: SCSI_SENSE_NO_SENSE\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_RECOVERED_ERROR: + DPRINT("ATAPI error: SCSI_SENSE_RECOVERED_SENSE\n"); + ScsiStatus = 0; + SrbStatus = SRB_STATUS_SUCCESS; + break; + + case SCSI_SENSE_NOT_READY: + DPRINT("ATAPI error: SCSI_SENSE_NOT_READY\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_MEDIUM_ERROR: + DPRINT("ATAPI error: SCSI_SENSE_MEDIUM_ERROR\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_HARDWARE_ERROR: + DPRINT("ATAPI error: SCSI_SENSE_HARDWARE_ERROR\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_ILLEGAL_REQUEST: + DPRINT("ATAPI error: SCSI_SENSE_ILLEGAL_REQUEST\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_UNIT_ATTENTION: + DPRINT("ATAPI error: SCSI_SENSE_UNIT_ATTENTION\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_DATA_PROTECT: + DPRINT("ATAPI error: SCSI_SENSE_DATA_PROTECT\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_BLANK_CHECK: + DPRINT("ATAPI error: SCSI_SENSE_BLANK_CHECK\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_ABORTED_COMMAND: + DPRINT("ATAPI error: SCSI_SENSE_ABORTED_COMMAND\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + default: + DPRINT("ATAPI error: Invalid sense key\n"); + ScsiStatus = 0; + SrbStatus = SRB_STATUS_ERROR; + break; + } + } + else + { + DPRINT1("IDE error: %02x\n", ErrorReg); + + ScsiStatus = 0; + SrbStatus = SRB_STATUS_ERROR; + +#if 0 + UCHAR SectorCount, SectorNum, CylinderLow, CylinderHigh; + UCHAR DriveHead; + + CylinderLow = IDEReadCylinderLow(CommandPortBase); + CylinderHigh = IDEReadCylinderHigh(CommandPortBase); + DriveHead = IDEReadDriveHead(CommandPortBase); + SectorCount = IDEReadSectorCount(CommandPortBase); + SectorNum = IDEReadSectorNum(CommandPortBase); + + DPRINT1("IDE Error: ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n", + ErrorReg, + CylinderLow, + CylinderHigh, + SectorCount, + SectorNum); +#endif + } + + + + Srb->ScsiStatus = ScsiStatus; + + DPRINT("AtapiErrorToScsi() done\n"); + + return(SrbStatus); +} + +/* EOF */ diff --git a/drivers/storage/atapi/atapi.h b/drivers/storage/atapi/atapi.h new file mode 100644 index 0000000..9ccac81 --- /dev/null +++ b/drivers/storage/atapi/atapi.h @@ -0,0 +1,177 @@ +// +// ATAPI.H - defines and typedefs for the IDE Driver module. +// + +#ifndef __ATAPI_H +#define __ATAPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define IDE_MAXIMUM_DEVICES 8 + +#define IDE_MAX_NAME_LENGTH 50 + +#define IDE_SECTOR_BUF_SZ 512 +#define IDE_MAX_SECTORS_PER_XFER 256 +#define IDE_MAX_RESET_RETRIES 10000 +#define IDE_MAX_POLL_RETRIES 100000 +#define IDE_MAX_WRITE_RETRIES 1000 +#define IDE_MAX_BUSY_RETRIES 50000 +#define IDE_MAX_DRQ_RETRIES 10000 +//#define IDE_MAX_CMD_RETRIES 1 +#define IDE_MAX_CMD_RETRIES 0 +#define IDE_CMD_TIMEOUT 5 +#define IDE_RESET_PULSE_LENGTH 500 /* maybe a little too long */ +#define IDE_RESET_BUSY_TIMEOUT 120 +#define IDE_RESET_DRDY_TIMEOUT 120 + +// Control Block offsets and masks +#define IDE_REG_ALT_STATUS 0x0000 +#define IDE_REG_DEV_CNTRL 0x0000 /* device control register */ +#define IDE_DC_SRST 0x04 /* drive reset (both drives) */ +#define IDE_DC_nIEN 0x02 /* IRQ enable (active low) */ +#define IDE_REG_DRV_ADDR 0x0001 + +// Command Block offsets and masks +#define IDE_REG_DATA_PORT 0x0000 +#define IDE_REG_ERROR 0x0001 /* error register */ +#define IDE_ER_AMNF 0x01 /* addr mark not found */ +#define IDE_ER_TK0NF 0x02 /* track 0 not found */ +#define IDE_ER_ABRT 0x04 /* command aborted */ +#define IDE_ER_MCR 0x08 /* media change requested */ +#define IDE_ER_IDNF 0x10 /* ID not found */ +#define IDE_ER_MC 0x20 /* Media changed */ +#define IDE_ER_UNC 0x40 /* Uncorrectable data error */ +#define IDE_REG_PRECOMP 0x0001 +#define IDE_REG_SECTOR_CNT 0x0002 +#define IDE_REG_SECTOR_NUM 0x0003 +#define IDE_REG_CYL_LOW 0x0004 +#define IDE_REG_CYL_HIGH 0x0005 +#define IDE_REG_DRV_HEAD 0x0006 +#define IDE_DH_FIXED 0xA0 +#define IDE_DH_LBA 0x40 +#define IDE_DH_HDMASK 0x0F +#define IDE_DH_DRV0 0x00 +#define IDE_DH_DRV1 0x10 +#define IDE_REG_STATUS 0x0007 +#define IDE_SR_BUSY 0x80 +#define IDE_SR_DRDY 0x40 +#define IDE_SR_DRQ 0x08 +#define IDE_SR_ERR 0x01 +#define IDE_REG_COMMAND 0x0007 +#define IDE_CMD_RESET 0x08 +#define IDE_CMD_READ 0x20 +#define IDE_CMD_READ_RETRY 0x21 +#define IDE_CMD_WRITE 0x30 +#define IDE_CMD_WRITE_RETRY 0x31 +#define IDE_CMD_IDENT_ATA_DRV 0xEC +#define IDE_CMD_IDENT_ATAPI_DRV 0xA1 +// +// Access macros for command registers +// Each macro takes an address of the command port block, and data +// +#define IDEReadError(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_ERROR))) +#define IDEWritePrecomp(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data))) +#define IDEReadSectorCount(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_SECTOR_CNT))) +#define IDEWriteSectorCount(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data))) +#define IDEReadSectorNum(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_SECTOR_NUM))) +#define IDEWriteSectorNum(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data))) +#define IDEReadCylinderLow(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_CYL_LOW))) +#define IDEWriteCylinderLow(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data))) +#define IDEReadCylinderHigh(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_CYL_HIGH))) +#define IDEWriteCylinderHigh(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data))) +#define IDEReadDriveHead(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_DRV_HEAD))) +#define IDEWriteDriveHead(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data))) +#define IDEReadStatus(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_STATUS))) +#define IDEWriteCommand(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_COMMAND), (Data))) + + +// +// Data block read and write commands +// +#define IDEReadBlock(Address, Buffer, Count) \ + (ScsiPortReadPortBufferUshort((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) +#define IDEWriteBlock(Address, Buffer, Count) \ + (ScsiPortWritePortBufferUshort((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) + +// +// Access macros for control registers +// Each macro takes an address of the control port blank and data +// +#define IDEReadAltStatus(Address) \ + (ScsiPortReadPortUchar((PUCHAR)((Address) + IDE_REG_ALT_STATUS))) +#define IDEWriteDriveControl(Address, Data) \ + (ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data))) + + + +// IDE_DRIVE_IDENTIFY + +typedef struct _IDE_DRIVE_IDENTIFY +{ + WORD ConfigBits; /*00*/ + WORD LogicalCyls; /*01*/ + WORD Reserved02; /*02*/ + WORD LogicalHeads; /*03*/ + WORD BytesPerTrack; /*04*/ + WORD BytesPerSector; /*05*/ + WORD SectorsPerTrack; /*06*/ + BYTE InterSectorGap; /*07*/ + BYTE InterSectorGapSize; + BYTE Reserved08H; /*08*/ + BYTE BytesInPLO; + WORD VendorUniqueCnt; /*09*/ + char SerialNumber[20]; /*10*/ + WORD ControllerType; /*20*/ + WORD BufferSize; /*21*/ + WORD ECCByteCnt; /*22*/ + char FirmwareRev[8]; /*23*/ + char ModelNumber[40]; /*27*/ + WORD RWMultImplemented; /*47*/ + WORD Reserved48; /*48*/ + WORD Capabilities; /*49*/ +#define IDE_DRID_STBY_SUPPORTED 0x2000 +#define IDE_DRID_IORDY_SUPPORTED 0x0800 +#define IDE_DRID_IORDY_DISABLE 0x0400 +#define IDE_DRID_LBA_SUPPORTED 0x0200 +#define IDE_DRID_DMA_SUPPORTED 0x0100 + WORD Reserved50; /*50*/ + WORD MinPIOTransTime; /*51*/ + WORD MinDMATransTime; /*52*/ + WORD TMFieldsValid; /*53*/ + WORD TMCylinders; /*54*/ + WORD TMHeads; /*55*/ + WORD TMSectorsPerTrk; /*56*/ + WORD TMCapacityLo; /*57*/ + WORD TMCapacityHi; /*58*/ + WORD Reserved59; /*59*/ + WORD TMSectorCountLo; /*60*/ + WORD TMSectorCountHi; /*61*/ + WORD Reserved62[193]; /*62*/ + WORD Checksum; /*255*/ +} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY; + + +#ifdef __cplusplus +} +#endif + +#endif /* __ATAPT_H */ + + diff --git a/drivers/storage/atapi/atapi.rc b/drivers/storage/atapi/atapi.rc new file mode 100644 index 0000000..407833a --- /dev/null +++ b/drivers/storage/atapi/atapi.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ATAPI Device Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "atapi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "atapi.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/storage/atapi/makefile b/drivers/storage/atapi/makefile new file mode 100644 index 0000000..b24da0d --- /dev/null +++ b/drivers/storage/atapi/makefile @@ -0,0 +1,17 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = atapi + +TARGET_DDKLIBS = scsiport.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/storage/cdrom/.cvsignore b/drivers/storage/cdrom/.cvsignore new file mode 100644 index 0000000..6ab709c --- /dev/null +++ b/drivers/storage/cdrom/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +cdrom.coff +cdrom.sys.unstripped diff --git a/drivers/storage/cdrom/cdrom.c b/drivers/storage/cdrom/cdrom.c new file mode 100644 index 0000000..08440ca --- /dev/null +++ b/drivers/storage/cdrom/cdrom.c @@ -0,0 +1,769 @@ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/cdrom/cdrom.c + * PURPOSE: cdrom class driver + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* + * TODO: + * - Add io timer routine for autorun support. + * - Add cdaudio support (cd player). + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +#define VERSION "0.0.1" + + +typedef struct _CDROM_DATA +{ + ULONG Dummy; +} CDROM_DATA, *PCDROM_DATA; + + + +BOOLEAN STDCALL +CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN PCLASS_INIT_DATA InitializationData, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber); + +BOOLEAN STDCALL +CdromClassCheckDevice(IN PINQUIRYDATA InquiryData); + +NTSTATUS STDCALL +CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS +CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber, + IN ULONG DeviceNumber, + IN PIO_SCSI_CAPABILITIES Capabilities, + IN PSCSI_INQUIRY_DATA InquiryData, + IN PCLASS_INIT_DATA InitializationData); + + +NTSTATUS STDCALL +CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS STDCALL +CdromClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +VOID STDCALL +CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context); + + +/* FUNCTIONS ****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * DriverEntry + * + * DESCRIPTION: + * This function initializes the driver, locates and claims + * hardware resources, and creates various NT objects needed + * to process I/O requests. + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * DriverObject + * System allocated Driver Object for this driver + * RegistryPath + * Name of registry driver service key + * + * RETURNS: + * Status. + */ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + CLASS_INIT_DATA InitData; + + DPRINT("CD-ROM Class Driver %s\n", + VERSION); + DPRINT("RegistryPath '%wZ'\n", + RegistryPath); + + InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA); + InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA); + InitData.DeviceType = FILE_DEVICE_CD_ROM; + InitData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_READ_ONLY_DEVICE; + + InitData.ClassError = NULL; // CdromClassProcessError; + InitData.ClassReadWriteVerification = CdromClassCheckReadWrite; + InitData.ClassFindDeviceCallBack = CdromClassCheckDevice; + InitData.ClassFindDevices = CdromClassFindDevices; + InitData.ClassDeviceControl = CdromClassDeviceControl; + InitData.ClassShutdownFlush = CdromClassShutdownFlush; + InitData.ClassCreateClose = NULL; + InitData.ClassStartIo = NULL; + + return(ScsiClassInitialize(DriverObject, + RegistryPath, + &InitData)); +} + + +/********************************************************************** + * NAME EXPORTED + * CdromClassFindDevices + * + * DESCRIPTION: + * This function searches for device that are attached to the + * given scsi port. + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * DriverObject + * System allocated Driver Object for this driver + * RegistryPath + * Name of registry driver service key. + * InitializationData + * Pointer to the main initialization data + * PortDeviceObject + * Scsi port device object + * PortNumber + * Port number + * + * RETURNS: + * TRUE: At least one disk drive was found + * FALSE: No disk drive found + */ + +BOOLEAN STDCALL +CdromClassFindDevices(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN PCLASS_INIT_DATA InitializationData, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber) +{ + PCONFIGURATION_INFORMATION ConfigInfo; + PIO_SCSI_CAPABILITIES PortCapabilities; + PSCSI_ADAPTER_BUS_INFO AdapterBusInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + PCHAR Buffer; + ULONG Bus; + ULONG DeviceCount; + BOOLEAN FoundDevice; + NTSTATUS Status; + + DPRINT("CdromClassFindDevices() called.\n"); + + /* Get port capabilities */ + Status = ScsiClassGetCapabilities(PortDeviceObject, + &PortCapabilities); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status); + return(FALSE); + } + + DPRINT("PortCapabilities: %p\n", PortCapabilities); + DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength); + DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages); + + /* Get inquiry data */ + Status = ScsiClassGetInquiryData(PortDeviceObject, + (PSCSI_ADAPTER_BUS_INFO *)&Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ScsiClassGetInquiryData() failed! (Status 0x%lX)\n", Status); + return(FALSE); + } + + /* Check whether there are unclaimed devices */ + AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer; + DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData, + AdapterBusInfo); + if (DeviceCount == 0) + { + DPRINT("No unclaimed devices!\n"); + return(FALSE); + } + + DPRINT("Found %lu unclaimed devices!\n", DeviceCount); + + ConfigInfo = IoGetConfigurationInformation(); + DPRINT("Number of SCSI ports: %lu\n", ConfigInfo->ScsiPortCount); + + /* Search each bus of this adapter */ + for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++) + { + DPRINT("Searching bus %lu\n", Bus); + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset); + + while (AdapterBusInfo->BusData[Bus].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if ((InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) && + (InquiryData->DeviceTypeQualifier == 0) && + (UnitInfo->DeviceClaimed == FALSE)) + { + DPRINT("Vendor: '%.24s'\n", + InquiryData->VendorId); + + /* Create device objects for disk */ + Status = CdromClassCreateDeviceObject(DriverObject, + RegistryPath, + PortDeviceObject, + PortNumber, + ConfigInfo->CDRomCount, + PortCapabilities, + UnitInfo, + InitializationData); + if (NT_SUCCESS(Status)) + { + ConfigInfo->CDRomCount++; + FoundDevice = TRUE; + } + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset); + } + } + + ExFreePool(Buffer); + + DPRINT("CdromClassFindDevices() done\n"); + + return(FoundDevice); +// return(TRUE); +} + + +/********************************************************************** + * NAME EXPORTED + * CdromClassCheckDevice + * + * DESCRIPTION + * This function checks the InquiryData for the correct device + * type and qualifier. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * InquiryData + * Pointer to the inquiry data for the device in question. + * + * RETURN VALUE + * TRUE: A disk device was found. + * FALSE: Otherwise. + */ + +BOOLEAN STDCALL +CdromClassCheckDevice(IN PINQUIRYDATA InquiryData) +{ + return((InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) && + (InquiryData->DeviceTypeQualifier == 0)); +} + + +/********************************************************************** + * NAME EXPORTED + * CdromClassCheckReadWrite + * + * DESCRIPTION + * This function checks the given IRP for correct data. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceObject + * Pointer to the device. + * Irp + * Irp to check. + * + * RETURN VALUE + * STATUS_SUCCESS: The IRP matches the requirements of the given device. + * Others: Failure. + */ + +NTSTATUS STDCALL +CdromClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("CdromClassCheckReadWrite() called\n"); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * CdromClassCreateDeviceObject + * + * DESCRIPTION: + * Create the raw device and any partition devices on this drive + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * DriverObject + * System allocated Driver Object for this driver. + * RegistryPath + * Name of registry driver service key. + * PortDeviceObject + * PortNumber + * DeviceNumber + * Capabilities + * InquiryData + * InitializationData + * + * RETURNS: + * Status. + */ + +static NTSTATUS +CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber, + IN ULONG DeviceNumber, + IN PIO_SCSI_CAPABILITIES Capabilities, + IN PSCSI_INQUIRY_DATA InquiryData, + IN PCLASS_INIT_DATA InitializationData) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeDeviceDirName; + CHAR NameBuffer[80]; + PDEVICE_OBJECT DiskDeviceObject; + PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */ + HANDLE Handle; + PCDROM_DATA CdromData; + NTSTATUS Status; + + DPRINT("CdromClassCreateDeviceObject() called\n"); + + /* Claim the cdrom device */ + Status = ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + FALSE, + &PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not claim cdrom device\n"); + return(Status); + } + + /* Create cdrom device */ + sprintf(NameBuffer, + "\\Device\\CdRom%lu", + DeviceNumber); + + Status = ScsiClassCreateDeviceObject(DriverObject, + NameBuffer, + NULL, + &DiskDeviceObject, + InitializationData); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status); + + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + return(Status); + } + + DiskDeviceObject->Flags |= DO_DIRECT_IO; + DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; + DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1; + + if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement) + { + DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; + } + + DiskDeviceExtension = DiskDeviceObject->DeviceExtension; + DiskDeviceExtension->LockCount = 0; + DiskDeviceExtension->DeviceNumber = DeviceNumber; + DiskDeviceExtension->PortDeviceObject = PortDeviceObject; + DiskDeviceExtension->PhysicalDevice = DiskDeviceObject; + DiskDeviceExtension->PortCapabilities = Capabilities; + DiskDeviceExtension->StartingOffset.QuadPart = 0; + DiskDeviceExtension->PortNumber = (UCHAR)PortNumber; + DiskDeviceExtension->PathId = InquiryData->PathId; + DiskDeviceExtension->TargetId = InquiryData->TargetId; + DiskDeviceExtension->Lun = InquiryData->Lun; + + /* zero-out disk data */ + CdromData = (PCDROM_DATA)(DiskDeviceExtension + 1); + RtlZeroMemory(CdromData, + sizeof(CDROM_DATA)); + + DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool, + sizeof(SENSE_DATA)); + if (DiskDeviceExtension->SenseData == NULL) + { + DPRINT1("Failed to allocate sense data buffer!\n"); + + IoDeleteDevice(DiskDeviceObject); + + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Get disk geometry */ + DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool, + sizeof(DISK_GEOMETRY)); + if (DiskDeviceExtension->DiskGeometry == NULL) + { + DPRINT1("Failed to allocate geometry buffer!\n"); + + IoDeleteDevice(DiskDeviceObject); + + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Read the drive's capacity */ + Status = ScsiClassReadDriveCapacity(DiskDeviceObject); + if (!NT_SUCCESS(Status) || + DiskDeviceExtension->DiskGeometry->BytesPerSector == 0) + { + /* Set ISO9660 defaults */ + DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048; + DiskDeviceExtension->DiskGeometry->MediaType = RemovableMedia; + DiskDeviceExtension->SectorShift = 11; + DiskDeviceExtension->PartitionLength.QuadPart = (ULONGLONG)0x7fffffff; + } + else + { + /* Make sure the BytesPerSector value is a power of 2 */ +// DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048; + } + + DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector); + + /* FIXME: initialize media change support */ + + IoInitializeTimer(DiskDeviceObject, + CdromTimerRoutine, + NULL); + IoStartTimer(DiskDeviceObject); + + DPRINT("CdromClassCreateDeviceObjects() done\n"); + + return(STATUS_SUCCESS); +} + +/********************************************************************** + * NAME + * CdromClassReadTocEntry + * + * ARGUMENTS: + * DeviceObject + * TrackNo + * Buffer + * Length + * + * RETURNS: + * Status. + */ + +static NTSTATUS +CdromClassReadTocEntry(PDEVICE_OBJECT DeviceObject, UINT TrackNo, PVOID Buffer, UINT Length) +{ + PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + SCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + + RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK)); + Srb.CdbLength = 10; + Srb.TimeOutValue = DeviceExtension->TimeOutValue; + + Cdb = (PCDB)Srb.Cdb; + Cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC; + Cdb->READ_TOC.StartingTrack = TrackNo; + Cdb->READ_TOC.Format = 0; + Cdb->READ_TOC.AllocationLength[0] = Length >> 8; + Cdb->READ_TOC.AllocationLength[1] = Length & 0xff; + Cdb->READ_TOC.Msf = 1; + + return ScsiClassSendSrbSynchronous(DeviceObject, + &Srb, + Buffer, + Length, + FALSE); +} + +static NTSTATUS +CdromClassReadLastSession(PDEVICE_OBJECT DeviceObject, UINT TrackNo, PVOID Buffer, UINT Length) +{ + PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + SCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + + RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK)); + Srb.CdbLength = 10; + Srb.TimeOutValue = DeviceExtension->TimeOutValue; + + Cdb = (PCDB)Srb.Cdb; + Cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC; + Cdb->READ_TOC.StartingTrack = TrackNo; + Cdb->READ_TOC.Format = 1; + Cdb->READ_TOC.AllocationLength[0] = Length >> 8; + Cdb->READ_TOC.AllocationLength[1] = Length & 0xff; + Cdb->READ_TOC.Msf = 0; + + return ScsiClassSendSrbSynchronous(DeviceObject, + &Srb, + Buffer, + Length, + FALSE); +} + +/********************************************************************** + * NAME EXPORTED + * CdromClassDeviceControl + * + * DESCRIPTION: + * Answer requests for device control calls + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * DeviceObject + * Irp + * Standard dispatch arguments + * + * RETURNS: + * Status. + */ + +NTSTATUS STDCALL +CdromClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + ULONG ControlCode, InputLength, OutputLength; + PCDROM_DATA CdromData; + ULONG Information; + NTSTATUS Status; + + DPRINT("CdromClassDeviceControl() called!\n"); + + Status = STATUS_INVALID_DEVICE_REQUEST; + Information = 0; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + CdromData = (PCDROM_DATA)(DeviceExtension + 1); + + switch (ControlCode) + { + case IOCTL_CDROM_GET_DRIVE_GEOMETRY: + DPRINT("IOCTL_CDROM_GET_DRIVE_GEOMETRY\n"); + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PDISK_GEOMETRY Geometry; + + if (DeviceExtension->DiskGeometry == NULL) + { + DPRINT("No cdrom geometry available!\n"); + DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool, + sizeof(DISK_GEOMETRY)); + } + Status = ScsiClassReadDriveCapacity(DeviceObject); + if (NT_SUCCESS(Status)) + { + Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer; + RtlMoveMemory(Geometry, + DeviceExtension->DiskGeometry, + sizeof(DISK_GEOMETRY)); + + Status = STATUS_SUCCESS; + Information = sizeof(DISK_GEOMETRY); + } + } + break; + case IOCTL_CDROM_READ_TOC: + DPRINT("IOCTL_CDROM_READ_TOC\n"); + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(CDROM_TOC)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + PCDROM_TOC TocBuffer; + USHORT Length; + + TocBuffer = Irp->AssociatedIrp.SystemBuffer; + + /* First read the lead out */ + Length = 4 + sizeof(TRACK_DATA); + Status = CdromClassReadTocEntry(DeviceObject, 0xaa, TocBuffer, Length); + + if (NT_SUCCESS(Status)) + { + if (TocBuffer->FirstTrack == 0xaa) + { + /* there is an empty cd */ + Information = Length; + } + else + { + /* read the toc */ + Length = 4 + sizeof(TRACK_DATA) * (TocBuffer->LastTrack - TocBuffer->FirstTrack + 2); + Status = CdromClassReadTocEntry(DeviceObject, TocBuffer->FirstTrack, TocBuffer, Length); + if (NT_SUCCESS(Status)) + { + Information = Length; + } + } + } + } + break; + case IOCTL_CDROM_GET_LAST_SESSION: + DPRINT("IOCTL_CDROM_GET_LAST_SESSION\n"); + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < 4 + sizeof(TRACK_DATA)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + USHORT Length; + PCDROM_TOC TocBuffer = Irp->AssociatedIrp.SystemBuffer; + + Length = 4 + sizeof(TRACK_DATA); + Status = CdromClassReadLastSession(DeviceObject, 0, TocBuffer, Length); + if (NT_SUCCESS(Status)) + { + Information = Length; + } + } + break; + default: + /* Call the common device control function */ + return(ScsiClassDeviceControl(DeviceObject, Irp)); + } + + /* Verify the device if the user caused the error */ + if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status)) + { + IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Information; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * CdromClassShutdownFlush + * + * DESCRIPTION: + * Answer requests for shutdown and flush calls + * + * RUN LEVEL: + * PASSIVE_LEVEL + * + * ARGUMENTS: + * DeviceObject + * Irp + * Standard dispatch arguments + * + * RETURNS: + * Status. + */ + +NTSTATUS STDCALL +CdromClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("CdromClassShutdownFlush() called!\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +CdromTimerRoutine(PDEVICE_OBJECT DeviceObject, + PVOID Context) +{ + DPRINT("CdromTimerRoutine() called\n"); + +} + +/* EOF */ diff --git a/drivers/storage/cdrom/cdrom.rc b/drivers/storage/cdrom/cdrom.rc new file mode 100644 index 0000000..87a1ca0 --- /dev/null +++ b/drivers/storage/cdrom/cdrom.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "CD-ROM Class Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "cdrom\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "cdrom.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/storage/cdrom/makefile b/drivers/storage/cdrom/makefile new file mode 100644 index 0000000..3e3ad3a --- /dev/null +++ b/drivers/storage/cdrom/makefile @@ -0,0 +1,17 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = cdrom + +TARGET_DDKLIBS = class2.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/storage/class2/.cvsignore b/drivers/storage/class2/.cvsignore new file mode 100644 index 0000000..f815d77 --- /dev/null +++ b/drivers/storage/class2/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +class2.coff +class2.sys.unstripped diff --git a/drivers/storage/class2/class2.c b/drivers/storage/class2/class2.c new file mode 100644 index 0000000..0b01fca --- /dev/null +++ b/drivers/storage/class2/class2.c @@ -0,0 +1,1687 @@ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/class2/class2.c + * PURPOSE: SCSI class driver + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* + * TODO: + * - finish ScsiClassDeviceControl(). + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +#define VERSION "0.0.1" + +#define TAG_SRBT TAG('S', 'r', 'b', 'T') + +#define INQUIRY_DATA_SIZE 2048 + + +static NTSTATUS STDCALL +ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static VOID +ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PSCSI_REQUEST_BLOCK Srb, + BOOLEAN Associated); + +/* FUNCTIONS ****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * DriverEntry + * + * DESCRIPTION + * This function initializes the driver. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * System allocated Driver Object for this driver. + * RegistryPath + * Name of registry driver service key. + * + * RETURNS + * Status + */ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT("Class Driver %s\n", VERSION); + return(STATUS_SUCCESS); +} + + +VOID +ScsiClassDebugPrint(IN ULONG DebugPrintLevel, + IN PCHAR DebugMessage, + ...) +{ + char Buffer[256]; + va_list ap; + +#if 0 + if (DebugPrintLevel > InternalDebugLevel) + return; +#endif + + va_start(ap, DebugMessage); + vsprintf(Buffer, DebugMessage, ap); + va_end(ap); + + DbgPrint(Buffer); +} + + +NTSTATUS STDCALL +ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + UNIMPLEMENTED; +} + + +VOID STDCALL +ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION CurrentIrpStack; + PIO_STACK_LOCATION NextIrpStack; + LARGE_INTEGER StartingOffset; + LARGE_INTEGER StartingBlock; + PSCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + ULONG LogicalBlockAddress; + USHORT TransferBlocks; + + DeviceExtension = DeviceObject->DeviceExtension; + CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp); + NextIrpStack = IoGetNextIrpStackLocation(Irp); + StartingOffset = CurrentIrpStack->Parameters.Read.ByteOffset; + + /* Calculate logical block address */ + StartingBlock.QuadPart = StartingOffset.QuadPart >> DeviceExtension->SectorShift; + LogicalBlockAddress = (ULONG)StartingBlock.u.LowPart; + + DPRINT("Logical block address: %lu\n", LogicalBlockAddress); + + /* Allocate and initialize an SRB */ + /* FIXME: use lookaside list instead */ + Srb = ExAllocatePool(NonPagedPool, + sizeof(SCSI_REQUEST_BLOCK)); + + Srb->SrbFlags = 0; + Srb->Length = sizeof(SCSI_REQUEST_BLOCK); //SCSI_REQUEST_BLOCK_SIZE; + Srb->OriginalRequest = Irp; + Srb->PathId = DeviceExtension->PathId; + Srb->TargetId = DeviceExtension->TargetId; + Srb->Lun = DeviceExtension->Lun; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb->DataBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress); + Srb->DataTransferLength = CurrentIrpStack->Parameters.Read.Length; + Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; + Srb->QueueSortKey = LogicalBlockAddress; + + Srb->SenseInfoBuffer = DeviceExtension->SenseData; + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + + Srb->TimeOutValue = + ((Srb->DataTransferLength + 0xFFFF) >> 16) * DeviceExtension->TimeOutValue; + + Srb->SrbStatus = SRB_STATUS_SUCCESS; + Srb->ScsiStatus = 0; + Srb->NextSrb = 0; + + Srb->CdbLength = 10; + Cdb = (PCDB)Srb->Cdb; + + /* Initialize ATAPI packet (12 bytes) */ + RtlZeroMemory(Cdb, + MAXIMUM_CDB_SIZE); + + Cdb->CDB10.LogicalUnitNumber = DeviceExtension->Lun; + TransferBlocks = (USHORT)(CurrentIrpStack->Parameters.Read.Length >> DeviceExtension->SectorShift); + + /* Copy little endian values into CDB in big endian format */ + Cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte3; + Cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte2; + Cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte1; + Cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&LogicalBlockAddress)->Byte0; + + Cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&TransferBlocks)->Byte1; + Cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&TransferBlocks)->Byte0; + + + if (CurrentIrpStack->MajorFunction == IRP_MJ_READ) + { + DPRINT("ScsiClassBuildRequest: Read Command\n"); + + Srb->SrbFlags |= SRB_FLAGS_DATA_IN; + Cdb->CDB10.OperationCode = SCSIOP_READ; + } + else + { + DPRINT("ScsiClassBuildRequest: Write Command\n"); + + Srb->SrbFlags |= SRB_FLAGS_DATA_OUT; + Cdb->CDB10.OperationCode = SCSIOP_WRITE; + } + +#if 0 + /* if this is not a write-through request, then allow caching */ + if (!(CurrentIrpStack->Flags & SL_WRITE_THROUGH)) + { + Srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE; + } + else if (DeviceExtension->DeviceFlags & DEV_WRITE_CACHE) + { + /* if write caching is enable then force media access in the cdb */ + Cdb->CDB10.ForceUnitAccess = TRUE; + } +#endif + + /* Update srb flags */ + Srb->SrbFlags |= DeviceExtension->SrbFlags; + + /* Initialize next stack location */ + NextIrpStack->MajorFunction = IRP_MJ_SCSI; + NextIrpStack->Parameters.Scsi.Srb = Srb; + NextIrpStack->DeviceObject = DeviceObject; + + /* Set retry count */ + NextIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; + + DPRINT("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp, Srb); + IoSetCompletionRoutine(Irp, + ScsiClassIoComplete, + Srb, + TRUE, + TRUE, + TRUE); +} + + +NTSTATUS STDCALL +ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject, + PSCSI_INQUIRY_DATA LunInfo, + BOOLEAN Release, + PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL) +{ + PIO_STACK_LOCATION IoStack; + IO_STATUS_BLOCK IoStatusBlock; + SCSI_REQUEST_BLOCK Srb; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + DPRINT("ScsiClassClaimDevice() called\n"); + + if (NewPortDeviceObject != NULL) + *NewPortDeviceObject = NULL; + + /* initialize an SRB */ + RtlZeroMemory(&Srb, + sizeof(SCSI_REQUEST_BLOCK)); + Srb.Length = SCSI_REQUEST_BLOCK_SIZE; + Srb.PathId = LunInfo->PathId; + Srb.TargetId = LunInfo->TargetId; + Srb.Lun = LunInfo->Lun; + Srb.Function = + (Release == TRUE) ? SRB_FUNCTION_RELEASE_DEVICE : SRB_FUNCTION_CLAIM_DEVICE; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE, + PortDeviceObject, + NULL, + 0, + NULL, + 0, + TRUE, + &Event, + &IoStatusBlock); + if (Irp == NULL) + { + DPRINT("Failed to allocate Irp!\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Link Srb and Irp */ + IoStack = IoGetNextIrpStackLocation(Irp); + IoStack->Parameters.Scsi.Srb = &Srb; + Srb.OriginalRequest = Irp; + + /* Call SCSI port driver */ + Status = IoCallDriver(PortDeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Suspended, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + if (Release == TRUE) + { + ObDereferenceObject(PortDeviceObject); + return(STATUS_SUCCESS); + } + +// Status = ObReferenceObjectByPointer(Srb.DataBuffer, + Status = ObReferenceObjectByPointer(PortDeviceObject, + 0, + NULL, + KernelMode); + + if (NewPortDeviceObject != NULL) + { +// *NewPortDeviceObject = Srb.DataBuffer; + *NewPortDeviceObject = PortDeviceObject; + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PCCHAR ObjectNameBuffer, + IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, + IN OUT PDEVICE_OBJECT *DeviceObject, + IN PCLASS_INIT_DATA InitializationData) +{ + PDEVICE_OBJECT InternalDeviceObject; + PDEVICE_EXTENSION DeviceExtension; + ANSI_STRING AnsiName; + UNICODE_STRING DeviceName; + NTSTATUS Status; + + DPRINT("ScsiClassCreateDeviceObject() called\n"); + + *DeviceObject = NULL; + + RtlInitAnsiString(&AnsiName, + ObjectNameBuffer); + + Status = RtlAnsiStringToUnicodeString(&DeviceName, + &AnsiName, + TRUE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("Device name: '%wZ'\n", &DeviceName); + + Status = IoCreateDevice(DriverObject, + InitializationData->DeviceExtensionSize, + &DeviceName, + InitializationData->DeviceType, + InitializationData->DeviceCharacteristics, + FALSE, + &InternalDeviceObject); + if (NT_SUCCESS(Status)) + { + DeviceExtension = InternalDeviceObject->DeviceExtension; + + DeviceExtension->ClassError = InitializationData->ClassError; + DeviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification; + DeviceExtension->ClassFindDevices = InitializationData->ClassFindDevices; + DeviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl; + DeviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush; + DeviceExtension->ClassCreateClose = InitializationData->ClassCreateClose; + DeviceExtension->ClassStartIo = InitializationData->ClassStartIo; + + DeviceExtension->MediaChangeCount = 0; + + if (PhysicalDeviceObject != NULL) + { + DeviceExtension->PhysicalDevice = PhysicalDeviceObject; + } + else + { + DeviceExtension->PhysicalDevice = InternalDeviceObject; + } + + *DeviceObject = InternalDeviceObject; + } + + RtlFreeUnicodeString(&DeviceName); + + return(Status); +} + + +NTSTATUS STDCALL +ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION Stack; + ULONG IoControlCode; + ULONG OutputBufferLength; + + DPRINT1("ScsiClassDeviceControl() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + + IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode; + OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength; + + if (IoControlCode == IOCTL_SCSI_GET_ADDRESS) + { + PSCSI_ADDRESS ScsiAddress; + + if (OutputBufferLength < sizeof(SCSI_ADDRESS)) + { + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_BUFFER_TOO_SMALL); + } + + ScsiAddress = Irp->AssociatedIrp.SystemBuffer; + ScsiAddress->Length = sizeof(SCSI_ADDRESS); + ScsiAddress->PortNumber = DeviceExtension->PortNumber; + ScsiAddress->PathId = DeviceExtension->PathId; + ScsiAddress->TargetId = DeviceExtension->TargetId; + ScsiAddress->Lun = DeviceExtension->Lun; + + Irp->IoStatus.Information = sizeof(SCSI_ADDRESS); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); + } + + if (IoControlCode == IOCTL_SCSI_PASS_THROUGH || + IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) + { + DPRINT1("Fixme: IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n"); + + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_UNSUCCESSFUL); + } + + DPRINT1("Fixme: unknown device io control code\n"); + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_UNSUCCESSFUL); +} + + +PVOID STDCALL +ScsiClassFindModePage(PCHAR ModeSenseBuffer, + ULONG Length, + UCHAR PageMode, + BOOLEAN Use6Byte) +{ + UNIMPLEMENTED; +} + + +ULONG STDCALL +ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData, + PSCSI_ADAPTER_BUS_INFO AdapterInformation) +{ + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + PUCHAR Buffer; + ULONG Bus; + ULONG UnclaimedDevices = 0; + NTSTATUS Status; + + DPRINT("ScsiClassFindUnclaimedDevices() called\n"); + + DPRINT("NumberOfBuses: %lu\n",AdapterInformation->NumberOfBuses); + Buffer = (PUCHAR)AdapterInformation; + for (Bus = 0; Bus < (ULONG)AdapterInformation->NumberOfBuses; Bus++) + { + DPRINT("Searching bus %lu\n", Bus); + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterInformation->BusData[Bus].InquiryDataOffset); + + while (AdapterInformation->BusData[Bus].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + DPRINT("Device: '%.8s'\n", InquiryData->VendorId); + + if ((InitializationData->ClassFindDeviceCallBack(InquiryData) == TRUE) && + (UnitInfo->DeviceClaimed == FALSE)) + { + UnclaimedDevices++; + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA) (Buffer + UnitInfo->NextInquiryDataOffset); + } + } + + return(UnclaimedDevices); +} + + +NTSTATUS STDCALL +ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject, + PIO_SCSI_CAPABILITIES *PortCapabilities) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES, + PortDeviceObject, + NULL, + 0, + PortCapabilities, + sizeof(PVOID), + FALSE, + &Event, + &IoStatusBlock); + if (Irp == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = IoCallDriver(PortDeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Suspended, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + DPRINT("PortCapabilities at %p\n", *PortCapabilities); + + return(Status); +} + + +NTSTATUS STDCALL +ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject, + PSCSI_ADAPTER_BUS_INFO *ConfigInfo) +{ + PSCSI_ADAPTER_BUS_INFO Buffer; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + DPRINT("ScsiClassGetInquiryData() called\n"); + + *ConfigInfo = NULL; + Buffer = ExAllocatePool(NonPagedPool, + INQUIRY_DATA_SIZE); + if (Buffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA, + PortDeviceObject, + NULL, + 0, + Buffer, + INQUIRY_DATA_SIZE, + FALSE, + &Event, + &IoStatusBlock); + if (Irp == NULL) + { + ExFreePool(Buffer); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = IoCallDriver(PortDeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Suspended, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + if (!NT_SUCCESS(Status)) + { + ExFreePool(Buffer); + } + else + { + *ConfigInfo = Buffer; + } + + DPRINT("ScsiClassGetInquiryData() done\n"); + + return(Status); +} + + +ULONG STDCALL +ScsiClassInitialize(PVOID Argument1, + PVOID Argument2, + PCLASS_INIT_DATA InitializationData) +{ + PCONFIGURATION_INFORMATION ConfigInfo; + PDRIVER_OBJECT DriverObject = Argument1; + WCHAR NameBuffer[80]; + UNICODE_STRING PortName; + ULONG PortNumber; + PDEVICE_OBJECT PortDeviceObject; + PFILE_OBJECT FileObject; + BOOLEAN DiskFound = FALSE; + NTSTATUS Status; + + DPRINT("ScsiClassInitialize() called!\n"); + + DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose; + DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite; + DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassScsiDispatch; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceDispatch; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush; + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush; + if (InitializationData->ClassStartIo) + { + DriverObject->DriverStartIo = InitializationData->ClassStartIo; + } + + ConfigInfo = IoGetConfigurationInformation(); + + DPRINT("ScsiPorts: %lu\n", ConfigInfo->ScsiPortCount); + + /* look for ScsiPortX scsi port devices */ + for (PortNumber = 0; PortNumber < ConfigInfo->ScsiPortCount; PortNumber++) + { + swprintf(NameBuffer, + L"\\Device\\ScsiPort%lu", + PortNumber); + RtlInitUnicodeString(&PortName, + NameBuffer); + DPRINT("Checking scsi port %ld\n", PortNumber); + Status = IoGetDeviceObjectPointer(&PortName, + FILE_READ_ATTRIBUTES, + &FileObject, + &PortDeviceObject); + DPRINT("Status 0x%08lX\n", Status); + if (NT_SUCCESS(Status)) + { + DPRINT("ScsiPort%lu found.\n", PortNumber); + + /* check scsi port for attached disk drives */ + if (InitializationData->ClassFindDevices(DriverObject, + Argument2, + InitializationData, + PortDeviceObject, + PortNumber)) + { + DiskFound = TRUE; + } + } + else + { + DbgPrint("Couldn't find ScsiPort%lu (Status %lx)\n", PortNumber, Status); + } + } + + DPRINT("ScsiClassInitialize() done!\n"); + + return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE); +} + + +/********************************************************************** + * NAME EXPORTED + * ScsiClassInitializeSrbLookasideList + * + * DESCRIPTION + * Initializes a lookaside list for SRBs. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceExtension + * Class specific device extension. + * + * NumberElements + * Maximum number of elements of the lookaside list. + * + * RETURN VALUE + * None. + */ + +VOID STDCALL +ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension, + ULONG NumberElements) +{ + ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead, + NULL, + NULL, + NonPagedPool, + sizeof(SCSI_REQUEST_BLOCK), + TAG_SRBT, + (USHORT)NumberElements); +} + + +NTSTATUS STDCALL +ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + UNIMPLEMENTED; +} + + +BOOLEAN STDCALL +ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + UCHAR MajorFunctionCode, + ULONG IoDeviceCode, + ULONG RetryCount, + NTSTATUS *Status) +{ + PDEVICE_EXTENSION DeviceExtension; + PSENSE_DATA SenseData; + BOOLEAN Retry; + + DPRINT("ScsiClassInterpretSenseInfo() called\n"); + + DPRINT("Srb->SrbStatus %lx\n", Srb->SrbStatus); + + if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING) + { + *Status = STATUS_SUCCESS; + return(FALSE); + } + + DeviceExtension = DeviceObject->DeviceExtension; + SenseData = Srb->SenseInfoBuffer; + Retry = TRUE; + + if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && + (Srb->SenseInfoBufferLength > 0)) + { + /* Got valid sense data, interpret them */ + + DPRINT("ErrorCode: %x\n", SenseData->ErrorCode); + DPRINT("SenseKey: %x\n", SenseData->SenseKey); + DPRINT("SenseCode: %x\n", SenseData->AdditionalSenseCode); + + switch (SenseData->SenseKey & 0xf) + { + /* FIXME: add more sense key codes */ + + case SCSI_SENSE_NOT_READY: + DPRINT("SCSI_SENSE_NOT_READY\n"); + *Status = STATUS_DEVICE_NOT_READY; + break; + + case SCSI_SENSE_UNIT_ATTENTION: + DPRINT("SCSI_SENSE_UNIT_ATTENTION\n"); + if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) && + (DeviceObject->Vpb->Flags & VPB_MOUNTED)) + { + DeviceObject->Flags |= DO_VERIFY_VOLUME; + *Status = STATUS_VERIFY_REQUIRED; + Retry = FALSE; + } + else + { + *Status = STATUS_IO_DEVICE_ERROR; + } + break; + + case SCSI_SENSE_ILLEGAL_REQUEST: + DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n"); + *Status = STATUS_INVALID_DEVICE_REQUEST; + Retry = FALSE; + break; + + + default: + DPRINT1("SCSI error (sense key: %x)\n", + SenseData->SenseKey & 0xf); + *Status = STATUS_IO_DEVICE_ERROR; + break; + } + } + else + { + /* Got no or invalid sense data, return generic error codes */ + switch (SRB_STATUS(Srb->SrbStatus)) + { + /* FIXME: add more srb status codes */ + + case SRB_STATUS_INVALID_PATH_ID: + case SRB_STATUS_INVALID_TARGET_ID: + case SRB_STATUS_INVALID_LUN: + case SRB_STATUS_NO_DEVICE: + case SRB_STATUS_NO_HBA: + *Status = STATUS_NO_SUCH_DEVICE; + Retry = FALSE; + break; + + case SRB_STATUS_BUSY: + *Status = STATUS_DEVICE_BUSY; + Retry = TRUE; + break; + + case SRB_STATUS_DATA_OVERRUN: + *Status = STATUS_DATA_OVERRUN; + Retry = FALSE; + break; + + default: + DPRINT1("SCSI error (SRB status: %x)\n", + SRB_STATUS(Srb->SrbStatus)); + *Status = STATUS_IO_DEVICE_ERROR; + break; + } + } + + /* Call the class driver specific error function */ + if (DeviceExtension->ClassError != NULL) + { + DeviceExtension->ClassError(DeviceObject, + Srb, + Status, + &Retry); + } + + /* FIXME: log severe errors */ + + DPRINT("ScsiClassInterpretSenseInfo() done\n"); + + return(Retry); +} + + +NTSTATUS STDCALL +ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + PSCSI_REQUEST_BLOCK Srb; + BOOLEAN Retry; + NTSTATUS Status; + + DPRINT("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n", + DeviceObject, Irp, Context); + + DeviceExtension = DeviceObject->DeviceExtension; + Srb = (PSCSI_REQUEST_BLOCK)Context; + DPRINT("Srb %p\n", Srb); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS) + { + Status = STATUS_SUCCESS; + } + else + { + Retry = ScsiClassInterpretSenseInfo(DeviceObject, + Srb, + IrpStack->MajorFunction, + 0, + MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4), + &Status); + if ((Retry == TRUE) && + ((ULONG)IrpStack->Parameters.Others.Argument4 > 0)) + { + ((ULONG)IrpStack->Parameters.Others.Argument4)--; + + ScsiClassRetryRequest(DeviceObject, + Irp, + Srb, + FALSE); + return(STATUS_MORE_PROCESSING_REQUIRED); + } + } + + /* FIXME: use lookaside list instead */ + DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb); + ExFreePool(IrpStack->Parameters.Scsi.Srb); + + Irp->IoStatus.Status = Status; + if (!NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = 0; + if (IoIsErrorUserInduced(Status)) + { + IoSetHardErrorOrVerifyDevice(Irp, + DeviceObject); + } + } + + if (DeviceExtension->ClassStartIo != NULL) + { + if (IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) + { + IoStartNextPacket(DeviceObject, + FALSE); + } + } + + DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status); + + return(Status); +} + + +NTSTATUS STDCALL +ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + PSCSI_REQUEST_BLOCK Srb; + PIRP MasterIrp; + BOOLEAN Retry; + LONG RequestCount; + NTSTATUS Status; + + DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n", + DeviceObject, Irp, Context); + + MasterIrp = Irp->AssociatedIrp.MasterIrp; + DeviceExtension = DeviceObject->DeviceExtension; + Srb = (PSCSI_REQUEST_BLOCK)Context; + DPRINT("Srb %p\n", Srb); + + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS) + { + Status = STATUS_SUCCESS; + } + else + { + /* Get more detailed status information */ + Retry = ScsiClassInterpretSenseInfo(DeviceObject, + Srb, + IrpStack->MajorFunction, + 0, + MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4), + &Status); + + DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4); + + if ((Retry == TRUE) && + ((ULONG)IrpStack->Parameters.Others.Argument4 > 0)) + { + ((ULONG)IrpStack->Parameters.Others.Argument4)--; + + ScsiClassRetryRequest(DeviceObject, + Irp, + Srb, + TRUE); + return(STATUS_MORE_PROCESSING_REQUIRED); + } + } + + /* FIXME: use lookaside list instead */ + DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb); + ExFreePool(IrpStack->Parameters.Scsi.Srb); + + Irp->IoStatus.Status = Status; + + IrpStack = IoGetNextIrpStackLocation(MasterIrp); + if (!NT_SUCCESS(Status)) + { + MasterIrp->IoStatus.Status = Status; + MasterIrp->IoStatus.Information = 0; + + if (IoIsErrorUserInduced(Status)) + { + IoSetHardErrorOrVerifyDevice(MasterIrp, + DeviceObject); + } + } + + /* Decrement the request counter in the Master IRP */ + RequestCount = InterlockedDecrement((PLONG)&IrpStack->Parameters.Others.Argument1); + + if (RequestCount == 0) + { + /* Complete the Master IRP */ + IoCompleteRequest(MasterIrp, + IO_DISK_INCREMENT); + + if (DeviceExtension->ClassStartIo) + { + IoStartNextPacket(DeviceObject, + FALSE); + } + } + + /* Free the current IRP */ + IoFreeIrp(Irp); + + return(STATUS_MORE_PROCESSING_REQUIRED); +} + + +ULONG STDCALL +ScsiClassModeSense(PDEVICE_OBJECT DeviceObject, + CHAR ModeSenseBuffer, + ULONG Length, + UCHAR PageMode) +{ + UNIMPLEMENTED; +} + + +ULONG STDCALL +ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_EXTENSION DeviceExtension; + PREAD_CAPACITY_DATA CapacityBuffer; + SCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + NTSTATUS Status; + ULONG LastSector; + ULONG SectorSize; + + DPRINT("ScsiClassReadDriveCapacity() called\n"); + + DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + CapacityBuffer = ExAllocatePool(NonPagedPool, + sizeof(READ_CAPACITY_DATA)); + if (CapacityBuffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK)); + + Srb.CdbLength = 10; + Srb.TimeOutValue = DeviceExtension->TimeOutValue; + + Cdb = (PCDB)Srb.Cdb; + Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY; + + + Status = ScsiClassSendSrbSynchronous(DeviceObject, + &Srb, + CapacityBuffer, + sizeof(READ_CAPACITY_DATA), + FALSE); + DPRINT("Status: %lx\n", Status); + DPRINT("Srb: %p\n", &Srb); + if (NT_SUCCESS(Status)) + { + SectorSize = (((PUCHAR)&CapacityBuffer->BytesPerBlock)[0] << 24) | + (((PUCHAR)&CapacityBuffer->BytesPerBlock)[1] << 16) | + (((PUCHAR)&CapacityBuffer->BytesPerBlock)[2] << 8) | + ((PUCHAR)&CapacityBuffer->BytesPerBlock)[3]; + + + LastSector = (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[0] << 24) | + (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[1] << 16) | + (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[2] << 8) | + ((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[3]; + + DeviceExtension->DiskGeometry->BytesPerSector = SectorSize; + + DeviceExtension->PartitionLength.QuadPart = (LONGLONG)(LastSector + 1); + WHICH_BIT(DeviceExtension->DiskGeometry->BytesPerSector, + DeviceExtension->SectorShift); + DeviceExtension->PartitionLength.QuadPart = + (DeviceExtension->PartitionLength.QuadPart << DeviceExtension->SectorShift); + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + DeviceExtension->DiskGeometry->MediaType = RemovableMedia; + } + else + { + DeviceExtension->DiskGeometry->MediaType = FixedMedia; + } + DeviceExtension->DiskGeometry->Cylinders.QuadPart = (LONGLONG)((LastSector + 1)/(32 * 64)); + DeviceExtension->DiskGeometry->SectorsPerTrack = 32; + DeviceExtension->DiskGeometry->TracksPerCylinder = 64; + + DPRINT("SectorSize: %lu SectorCount: %lu\n", SectorSize, LastSector + 1); + } + else + { + /* Use default values if disk geometry cannot be read */ + RtlZeroMemory(DeviceExtension->DiskGeometry, + sizeof(DISK_GEOMETRY)); + DeviceExtension->DiskGeometry->BytesPerSector = 512; + DeviceExtension->SectorShift = 9; + DeviceExtension->PartitionLength.QuadPart = 0; + + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + DeviceExtension->DiskGeometry->MediaType = RemovableMedia; + } + else + { + DeviceExtension->DiskGeometry->MediaType = FixedMedia; + } + + DPRINT("SectorSize: 512 SectorCount: 0\n"); + } + + ExFreePool(CapacityBuffer); + + DPRINT("ScsiClassReadDriveCapacity() done\n"); + + return(Status); +} + + +VOID STDCALL +ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PIRP Irp, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice) +{ + PDEVICE_EXTENSION DeviceExtension; + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION IrpStack; + ULONG RequestType; + BOOLEAN Retry; + ULONG RetryCount; + PKEVENT Event; + PIRP Irp; + NTSTATUS Status; + + DPRINT("ScsiClassSendSrbSynchronous() called\n"); + + RetryCount = MAXIMUM_RETRIES; + DeviceExtension = DeviceObject->DeviceExtension; + + Srb->Length = SCSI_REQUEST_BLOCK_SIZE; + Srb->PathId = DeviceExtension->PathId; + Srb->TargetId = DeviceExtension->TargetId; + Srb->Lun = DeviceExtension->Lun; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + Srb->SenseInfoBuffer = ExAllocatePool(NonPagedPool, + SENSE_BUFFER_SIZE); + if (Srb->SenseInfoBuffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + if (BufferAddress == NULL) + { + BufferLength = 0; + RequestType = IOCTL_SCSI_EXECUTE_NONE; + Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER; + } + else + { + if (WriteToDevice == TRUE) + { + RequestType = IOCTL_SCSI_EXECUTE_OUT; + Srb->SrbFlags = SRB_FLAGS_DATA_OUT; + } + else + { + RequestType = IOCTL_SCSI_EXECUTE_IN; + Srb->SrbFlags = SRB_FLAGS_DATA_IN; + } + } + + Srb->DataTransferLength = BufferLength; + Srb->DataBuffer = BufferAddress; + + Event = ExAllocatePool(NonPagedPool, + sizeof(KEVENT)); +TryAgain: + KeInitializeEvent(Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(RequestType, + DeviceExtension->PortDeviceObject, + NULL, + 0, + BufferAddress, + BufferLength, + TRUE, + Event, + &IoStatusBlock); + if (Irp == NULL) + { + DPRINT("IoBuildDeviceIoControlRequest() failed\n"); + ExFreePool(Srb->SenseInfoBuffer); + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Attach Srb to the Irp */ + IrpStack = IoGetNextIrpStackLocation(Irp); + IrpStack->Parameters.Scsi.Srb = Srb; + Srb->OriginalRequest = Irp; + + /* Call the SCSI port driver */ + Status = IoCallDriver(DeviceExtension->PortDeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(Event, + Suspended, + KernelMode, + FALSE, + NULL); + } + + if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) + { + Retry = ScsiClassInterpretSenseInfo(DeviceObject, + Srb, + IRP_MJ_SCSI, + 0, + MAXIMUM_RETRIES - RetryCount, + &Status); + if (Retry == TRUE) + { + DPRINT("Try again (RetryCount %lu)\n", RetryCount); + + /* FIXME: Wait a little if we got a timeout error */ + + if (RetryCount--) + goto TryAgain; + } + } + else + { + Status = STATUS_SUCCESS; + } + + ExFreePool(Srb->SenseInfoBuffer); + ExFreePool(Event); + + DPRINT("ScsiClassSendSrbSynchronous() done\n"); + + return(Status); +} + + +VOID STDCALL +ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + ULONG MaximumBytes) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION CurrentStack; + PIO_STACK_LOCATION NextStack; + PIO_STACK_LOCATION NewStack; + PSCSI_REQUEST_BLOCK Srb; + LARGE_INTEGER Offset; + PIRP NewIrp; + PVOID DataBuffer; + ULONG TransferLength; + ULONG RequestCount; + ULONG DataLength; + ULONG i; + + DPRINT("ScsiClassSplitRequest(DeviceObject %lx Irp %lx MaximumBytes %lu)\n", + DeviceObject, Irp, MaximumBytes); + + DeviceExtension = DeviceObject->DeviceExtension; + CurrentStack = IoGetCurrentIrpStackLocation(Irp); + NextStack = IoGetNextIrpStackLocation(Irp); + DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + + /* Initialize transfer data for first request */ + Offset = CurrentStack->Parameters.Read.ByteOffset; + TransferLength = CurrentStack->Parameters.Read.Length; + DataLength = MaximumBytes; + RequestCount = ROUND_UP(TransferLength, MaximumBytes) / MaximumBytes; + + /* Save request count in the original IRP */ + NextStack->Parameters.Others.Argument1 = (PVOID)RequestCount; + + DPRINT("RequestCount %lu\n", RequestCount); + + for (i = 0; i < RequestCount; i++) + { + /* Create a new IRP */ + NewIrp = IoAllocateIrp(DeviceObject->StackSize, + FALSE); + if (NewIrp == NULL) + { + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + + if (i == 0) + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return; + } + + /* Initialize the new IRP */ + NewIrp->MdlAddress = Irp->MdlAddress; + + IoSetNextIrpStackLocation(NewIrp); + NewStack = IoGetCurrentIrpStackLocation(NewIrp); + + NewStack->MajorFunction = CurrentStack->MajorFunction; + NewStack->Parameters.Read.ByteOffset = Offset; + NewStack->Parameters.Read.Length = DataLength; + NewStack->DeviceObject = DeviceObject; + + ScsiClassBuildRequest(DeviceObject, + NewIrp); + + NewStack = IoGetNextIrpStackLocation(NewIrp); + Srb = NewStack->Parameters.Others.Argument1; + Srb->DataBuffer = DataBuffer; + + NewIrp->AssociatedIrp.MasterIrp = Irp; + + /* Initialize completion routine */ + IoSetCompletionRoutine(NewIrp, + ScsiClassIoCompleteAssociated, + Srb, + TRUE, + TRUE, + TRUE); + + /* Send the new IRP down to the port driver */ + IoCallDriver(DeviceExtension->PortDeviceObject, + NewIrp); + + /* Adjust transfer data for next request */ + DataBuffer = (PCHAR)DataBuffer + MaximumBytes; + TransferLength -= MaximumBytes; + DataLength = (TransferLength > MaximumBytes) ? MaximumBytes : TransferLength; + Offset.QuadPart = Offset.QuadPart + MaximumBytes; + } +} + + +/* INTERNAL FUNCTIONS *******************************************************/ + +static NTSTATUS STDCALL +ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + + DPRINT("ScsiClassCreateClose() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + + if (DeviceExtension->ClassCreateClose) + return(DeviceExtension->ClassCreateClose(DeviceObject, + Irp)); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + ULONG MaximumTransferLength; + ULONG CurrentTransferLength; + ULONG MaximumTransferPages; + ULONG CurrentTransferPages; + NTSTATUS Status; + + DPRINT("ScsiClassReadWrite() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("Relative Offset: %I64u Length: %lu\n", + IrpStack->Parameters.Read.ByteOffset.QuadPart, + IrpStack->Parameters.Read.Length); + + MaximumTransferLength = DeviceExtension->PortCapabilities->MaximumTransferLength; + MaximumTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages; + + CurrentTransferLength = IrpStack->Parameters.Read.Length; + + if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && + !(IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) + { + IoSetHardErrorOrVerifyDevice(Irp, + DeviceObject); + + Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_VERIFY_REQUIRED); + } + + /* Class driver verifies the IRP */ + Status = DeviceExtension->ClassReadWriteVerification(DeviceObject, + Irp); + if (!NT_SUCCESS(Status)) + { + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(Status); + } + else if (Status == STATUS_PENDING) + { + IoMarkIrpPending(Irp); + return(STATUS_PENDING); + } + + /* Finish a zero-byte transfer */ + if (CurrentTransferLength == 0) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + return(STATUS_SUCCESS); + } + + if (DeviceExtension->ClassStartIo != NULL) + { + DPRINT("ScsiClassReadWrite() starting packet\n"); + + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, + Irp, + NULL, + NULL); + + return(STATUS_PENDING); + } + + /* Adjust partition-relative starting offset to absolute offset */ + IrpStack->Parameters.Read.ByteOffset.QuadPart += DeviceExtension->StartingOffset.QuadPart; + + /* Calculate number of pages in this transfer */ + CurrentTransferPages = + ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress), + IrpStack->Parameters.Read.Length); + + if (CurrentTransferLength > MaximumTransferLength || + CurrentTransferPages > MaximumTransferPages) + { + DPRINT("Split current request: MaximumTransferLength %lu CurrentTransferLength %lu\n", + MaximumTransferLength, CurrentTransferLength); + + /* Adjust the maximum transfer length */ + CurrentTransferPages = DeviceExtension->PortCapabilities->MaximumPhysicalPages; + + if (MaximumTransferLength > CurrentTransferPages * PAGE_SIZE) + MaximumTransferLength = CurrentTransferPages * PAGE_SIZE; + + if (MaximumTransferLength == 0) + MaximumTransferLength = PAGE_SIZE; + + IoMarkIrpPending(Irp); + + /* Split current request */ + ScsiClassSplitRequest(DeviceObject, + Irp, + MaximumTransferLength); + + return(STATUS_PENDING); + } + + ScsiClassBuildRequest(DeviceObject, + Irp); + + DPRINT("ScsiClassReadWrite() done\n"); + + /* Call the port driver */ + return(IoCallDriver(DeviceExtension->PortDeviceObject, + Irp)); +} + + +static NTSTATUS STDCALL +ScsiClassScsiDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT1("ScsiClassScsiDispatch() called\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +ScsiClassDeviceDispatch(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + + DPRINT("ScsiClassDeviceDispatch() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + if (DeviceExtension->ClassDeviceControl) + { + return(DeviceExtension->ClassDeviceControl(DeviceObject, Irp)); + } + + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_INVALID_DEVICE_REQUEST); +} + + +static NTSTATUS STDCALL +ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + + DPRINT("ScsiClassShutdownFlush() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + if (DeviceExtension->ClassShutdownFlush) + { + return(DeviceExtension->ClassShutdownFlush(DeviceObject, Irp)); + } + + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_INVALID_DEVICE_REQUEST); +} + + +static VOID +ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PSCSI_REQUEST_BLOCK Srb, + BOOLEAN Associated) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION CurrentIrpStack; + PIO_STACK_LOCATION NextIrpStack; + ULONG TransferLength; + + DPRINT("ScsiPortRetryRequest() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp); + NextIrpStack = IoGetNextIrpStackLocation(Irp); + + if (CurrentIrpStack->MajorFunction == IRP_MJ_READ || + CurrentIrpStack->MajorFunction == IRP_MJ_WRITE) + { + TransferLength = CurrentIrpStack->Parameters.Read.Length; + } + else if (Irp->MdlAddress != NULL) + { + TransferLength = Irp->MdlAddress->ByteCount; + } + else + { + TransferLength = 0; + } + + Srb->DataTransferLength = TransferLength; + Srb->SrbStatus = 0; + Srb->ScsiStatus = 0; + + /* Don't modify the flags */ +// Srb->Flags = +// Srb->QueueTag = SP_UNTAGGED; + + NextIrpStack->MajorFunction = IRP_MJ_SCSI; + NextIrpStack->Parameters.Scsi.Srb = Srb; + + if (Associated == FALSE) + { + IoSetCompletionRoutine(Irp, + ScsiClassIoComplete, + Srb, + TRUE, + TRUE, + TRUE); + } + else + { + IoSetCompletionRoutine(Irp, + ScsiClassIoCompleteAssociated, + Srb, + TRUE, + TRUE, + TRUE); + } + + IoCallDriver(DeviceExtension->PortDeviceObject, + Irp); + + DPRINT("ScsiPortRetryRequest() done\n"); +} + +/* EOF */ diff --git a/drivers/storage/class2/class2.def b/drivers/storage/class2/class2.def new file mode 100644 index 0000000..44c490e --- /dev/null +++ b/drivers/storage/class2/class2.def @@ -0,0 +1,29 @@ +; $Id$ +; +; class2.def - export definition file for scsi class driver +; +LIBRARY CLASS2.SYS +EXPORTS +ScsiClassAsynchronousCompletion@12 +ScsiClassBuildRequest@8 +ScsiClassClaimDevice@16 +ScsiClassCreateDeviceObject@20 +ScsiClassDeviceControl@8 +ScsiClassFindModePage@16 +ScsiClassFindUnclaimedDevices@8 +ScsiClassGetCapabilities@8 +ScsiClassGetInquiryData@8 +ScsiClassInitialize@12 +ScsiClassInitializeSrbLookasideList@8 +ScsiClassInternalIoControl@8 +ScsiClassInterpretSenseInfo@24 +ScsiClassIoComplete@12 +ScsiClassIoCompleteAssociated@12 +ScsiClassModeSense@16 +ScsiClassQueryTimeOutRegistryValue@4 +ScsiClassReadDriveCapacity@4 +ScsiClassReleaseQueue@4 +ScsiClassSendSrbAsynchronous@24 +ScsiClassSendSrbSynchronous@20 +ScsiClassSplitRequest@12 +;EOF \ No newline at end of file diff --git a/drivers/storage/class2/class2.edf b/drivers/storage/class2/class2.edf new file mode 100644 index 0000000..d8e83f2 --- /dev/null +++ b/drivers/storage/class2/class2.edf @@ -0,0 +1,29 @@ +; $Id$ +; +; class2.edf - export definition file for scsi class driver +; +LIBRARY CLASS2.SYS +EXPORTS +ScsiClassAsynchronousCompletion=ScsiClassAsynchronousCompletion@12 +ScsiClassBuildRequest=ScsiClassBuildRequest@8 +ScsiClassClaimDevice=ScsiClassClaimDevice@16 +ScsiClassCreateDeviceObject=ScsiClassCreateDeviceObject@20 +ScsiClassDeviceControl=ScsiClassDeviceControl@8 +ScsiClassFindModePage=ScsiClassFindModePage@16 +ScsiClassFindUnclaimedDevices=ScsiClassFindUnclaimedDevices@8 +ScsiClassGetCapabilities=ScsiClassGetCapabilities@8 +ScsiClassGetInquiryData=ScsiClassGetInquiryData@8 +ScsiClassInitialize=ScsiClassInitialize@12 +ScsiClassInitializeSrbLookasideList=ScsiClassInitializeSrbLookasideList@8 +ScsiClassInternalIoControl=ScsiClassInternalIoControl@8 +ScsiClassInterpretSenseInfo=ScsiClassInterpretSenseInfo@24 +ScsiClassIoComplete=ScsiClassIoComplete@12 +ScsiClassIoCompleteAssociated=ScsiClassIoCompleteAssociated@12 +ScsiClassModeSense=ScsiClassModeSense@16 +ScsiClassQueryTimeOutRegistryValue=ScsiClassQueryTimeOutRegistryValue@4 +ScsiClassReadDriveCapacity=ScsiClassReadDriveCapacity@4 +ScsiClassReleaseQueue=ScsiClassReleaseQueue@4 +ScsiClassSendSrbAsynchronous=ScsiClassSendSrbAsynchronous@24 +ScsiClassSendSrbSynchronous=ScsiClassSendSrbSynchronous@20 +ScsiClassSplitRequest=ScsiClassSplitRequest@12 +;EOF \ No newline at end of file diff --git a/drivers/storage/class2/class2.rc b/drivers/storage/class2/class2.rc new file mode 100644 index 0000000..99c1875 --- /dev/null +++ b/drivers/storage/class2/class2.rc @@ -0,0 +1,38 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "SCSI Class Driver Helper\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "class2\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "class2.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/drivers/storage/class2/makefile b/drivers/storage/class2/makefile new file mode 100644 index 0000000..bdfe08f --- /dev/null +++ b/drivers/storage/class2/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = class2 + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/storage/disk/.cvsignore b/drivers/storage/disk/.cvsignore new file mode 100644 index 0000000..0449f28 --- /dev/null +++ b/drivers/storage/disk/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +disk.coff +disk.sys.unstripped \ No newline at end of file diff --git a/drivers/storage/disk/disk.c b/drivers/storage/disk/disk.c new file mode 100644 index 0000000..682ae7c --- /dev/null +++ b/drivers/storage/disk/disk.c @@ -0,0 +1,1011 @@ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/disk/disk.c + * PURPOSE: disk class driver + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +#define VERSION "0.0.1" + + +typedef struct _DISK_DATA +{ + ULONG HiddenSectors; + ULONG PartitionNumber; + ULONG PartitionOrdinal; + UCHAR PartitionType; + BOOLEAN BootIndicator; + BOOLEAN DriveNotReady; +} DISK_DATA, *PDISK_DATA; + + +BOOLEAN STDCALL +DiskClassFindDevices(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath, + PCLASS_INIT_DATA InitializationData, + PDEVICE_OBJECT PortDeviceObject, + ULONG PortNumber); + +BOOLEAN STDCALL +DiskClassCheckDevice(IN PINQUIRYDATA InquiryData); + +NTSTATUS STDCALL +DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +static NTSTATUS +DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, /* what's this used for? */ + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber, + IN ULONG DiskNumber, + IN PIO_SCSI_CAPABILITIES Capabilities, + IN PSCSI_INQUIRY_DATA InquiryData, + IN PCLASS_INIT_DATA InitializationData); + +NTSTATUS STDCALL +DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS STDCALL +DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + + +/* FUNCTIONS ****************************************************************/ + +// DriverEntry +// +// DESCRIPTION: +// This function initializes the driver, locates and claims +// hardware resources, and creates various NT objects needed +// to process I/O requests. +// +// RUN LEVEL: +// PASSIVE_LEVEL +// +// ARGUMENTS: +// IN PDRIVER_OBJECT DriverObject System allocated Driver Object +// for this driver +// IN PUNICODE_STRING RegistryPath Name of registry driver service +// key +// +// RETURNS: +// NTSTATUS + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + CLASS_INIT_DATA InitData; + + DPRINT("Disk Class Driver %s\n", + VERSION); + DPRINT("RegistryPath '%wZ'\n", + RegistryPath); + + RtlZeroMemory(&InitData, + sizeof(CLASS_INIT_DATA)); + + InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA); + InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA); + InitData.DeviceType = FILE_DEVICE_DISK; + InitData.DeviceCharacteristics = 0; + + InitData.ClassError = NULL; // DiskClassProcessError; + InitData.ClassReadWriteVerification = DiskClassCheckReadWrite; + InitData.ClassFindDeviceCallBack = DiskClassCheckDevice; + InitData.ClassFindDevices = DiskClassFindDevices; + InitData.ClassDeviceControl = DiskClassDeviceControl; + InitData.ClassShutdownFlush = DiskClassShutdownFlush; + InitData.ClassCreateClose = NULL; + InitData.ClassStartIo = NULL; + + return(ScsiClassInitialize(DriverObject, + RegistryPath, + &InitData)); +} + + +/********************************************************************** + * NAME EXPORTED + * DiskClassFindDevices + * + * DESCRIPTION + * This function searches for device that are attached to the + * given scsi port. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * System allocated Driver Object for this driver + * + * RegistryPath + * Name of registry driver service key + * + * InitializationData + * Pointer to the main initialization data + * + * PortDeviceObject + * Pointer to the port Device Object + * + * PortNumber + * Port number + * + * RETURN VALUE + * TRUE: At least one disk drive was found + * FALSE: No disk drive found + */ + +BOOLEAN STDCALL +DiskClassFindDevices(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath, + PCLASS_INIT_DATA InitializationData, + PDEVICE_OBJECT PortDeviceObject, + ULONG PortNumber) +{ + PCONFIGURATION_INFORMATION ConfigInfo; + PIO_SCSI_CAPABILITIES PortCapabilities; + PSCSI_ADAPTER_BUS_INFO AdapterBusInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + PCHAR Buffer; + ULONG Bus; + ULONG DeviceCount; + BOOLEAN FoundDevice; + NTSTATUS Status; + + DPRINT("DiskClassFindDevices() called.\n"); + + /* Get port capabilities */ + Status = ScsiClassGetCapabilities(PortDeviceObject, + &PortCapabilities); + if (!NT_SUCCESS(Status)) + { + DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status); + return(FALSE); + } + + DPRINT("PortCapabilities: %p\n", PortCapabilities); + DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength); + DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages); + + /* Get inquiry data */ + Status = ScsiClassGetInquiryData(PortDeviceObject, + (PSCSI_ADAPTER_BUS_INFO *)&Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status); + return(FALSE); + } + + /* Check whether there are unclaimed devices */ + AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer; + DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData, + AdapterBusInfo); + if (DeviceCount == 0) + { + DPRINT("No unclaimed devices!\n"); + return(FALSE); + } + + DPRINT("Found %lu unclaimed devices!\n", DeviceCount); + + ConfigInfo = IoGetConfigurationInformation(); + + /* Search each bus of this adapter */ + for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++) + { + DPRINT("Searching bus %lu\n", Bus); + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset); + + while (AdapterBusInfo->BusData[Bus].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) || + (InquiryData->DeviceType == OPTICAL_DEVICE)) && + (InquiryData->DeviceTypeQualifier == 0) && + (UnitInfo->DeviceClaimed == FALSE)) + { + DPRINT("Vendor: '%.24s'\n", + InquiryData->VendorId); + + /* Create device objects for disk */ + Status = DiskClassCreateDeviceObject(DriverObject, + RegistryPath, + PortDeviceObject, + PortNumber, + ConfigInfo->DiskCount, + PortCapabilities, + UnitInfo, + InitializationData); + if (NT_SUCCESS(Status)) + { + ConfigInfo->DiskCount++; + FoundDevice = TRUE; + } + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset); + } + } + + ExFreePool(Buffer); + + DPRINT("DiskClassFindDevices() done\n"); + + return(FoundDevice); +} + + +/********************************************************************** + * NAME EXPORTED + * DiskClassCheckDevice + * + * DESCRIPTION + * This function checks the InquiryData for the correct device + * type and qualifier. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * InquiryData + * Pointer to the inquiry data for the device in question. + * + * RETURN VALUE + * TRUE: A disk device was found. + * FALSE: Otherwise. + */ + +BOOLEAN STDCALL +DiskClassCheckDevice(IN PINQUIRYDATA InquiryData) +{ + return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE || + InquiryData->DeviceType == OPTICAL_DEVICE) && + InquiryData->DeviceTypeQualifier == 0); +} + + +/********************************************************************** + * NAME EXPORTED + * DiskClassCheckReadWrite + * + * DESCRIPTION + * This function checks the given IRP for correct data. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceObject + * Pointer to the device. + * + * Irp + * Irp to check. + * + * RETURN VALUE + * STATUS_SUCCESS: The IRP matches the requirements of the given device. + * Others: Failure. + */ + +NTSTATUS STDCALL +DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PDISK_DATA DiskData; + + DPRINT("DiskClassCheckReadWrite() called\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + DiskData = (PDISK_DATA)(DeviceExtension + 1); + + if (DiskData->DriveNotReady == TRUE) + { + Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; + IoSetHardErrorOrVerifyDevice(Irp, + DeviceObject); + return(STATUS_INVALID_PARAMETER); + } + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * DiskClassCreateDeviceObject + * + * DESCRIPTION + * Create the raw device and any partition devices on this drive + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * The system created driver object + * RegistryPath + * PortDeviceObject + * PortNumber + * DiskNumber + * Capabilities + * InquiryData + * InitialzationData + * + * RETURN VALUE + * STATUS_SUCCESS: Device objects for disk and partitions were created. + * Others: Failure. + */ + +static NTSTATUS +DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, /* what's this used for? */ + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber, + IN ULONG DiskNumber, + IN PIO_SCSI_CAPABILITIES Capabilities, + IN PSCSI_INQUIRY_DATA InquiryData, + IN PCLASS_INIT_DATA InitializationData) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeDeviceDirName; + WCHAR NameBuffer[80]; + CHAR NameBuffer2[80]; + PDEVICE_OBJECT DiskDeviceObject; + PDEVICE_OBJECT PartitionDeviceObject; + PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */ + PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */ + PDRIVE_LAYOUT_INFORMATION PartitionList = NULL; + HANDLE Handle; + PPARTITION_INFORMATION PartitionEntry; + PDISK_DATA DiskData; + ULONG PartitionNumber; + NTSTATUS Status; + + DPRINT("DiskClassCreateDeviceObject() called\n"); + + /* Create the harddisk device directory */ + swprintf(NameBuffer, + L"\\Device\\Harddisk%lu", + DiskNumber); + RtlInitUnicodeString(&UnicodeDeviceDirName, + NameBuffer); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeDeviceDirName, + 0, + NULL, + NULL); + Status = ZwCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not create device dir object\n"); + return(Status); + } + + /* Claim the disk device */ + Status = ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + FALSE, + &PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not claim disk device\n"); + + ZwMakeTemporaryObject(Handle); + ZwClose(Handle); + + return(Status); + } + + /* Create disk device (Partition 0) */ + sprintf(NameBuffer2, + "\\Device\\Harddisk%lu\\Partition0", + DiskNumber); + + Status = ScsiClassCreateDeviceObject(DriverObject, + NameBuffer2, + NULL, + &DiskDeviceObject, + InitializationData); + if (!NT_SUCCESS(Status)) + { + DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status); + + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + /* Delete the harddisk device directory */ + ZwMakeTemporaryObject(Handle); + ZwClose(Handle); + + return(Status); + } + + DiskDeviceObject->Flags |= DO_DIRECT_IO; + if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia) + { + DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; + } + DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1; + + if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement) + { + DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement; + } + + DiskDeviceExtension = DiskDeviceObject->DeviceExtension; + DiskDeviceExtension->LockCount = 0; + DiskDeviceExtension->DeviceNumber = DiskNumber; + DiskDeviceExtension->PortDeviceObject = PortDeviceObject; + DiskDeviceExtension->PhysicalDevice = DiskDeviceObject; + DiskDeviceExtension->PortCapabilities = Capabilities; + DiskDeviceExtension->StartingOffset.QuadPart = 0; + DiskDeviceExtension->PortNumber = (UCHAR)PortNumber; + DiskDeviceExtension->PathId = InquiryData->PathId; + DiskDeviceExtension->TargetId = InquiryData->TargetId; + DiskDeviceExtension->Lun = InquiryData->Lun; + + /* zero-out disk data */ + DiskData = (PDISK_DATA)(DiskDeviceExtension + 1); + RtlZeroMemory(DiskData, + sizeof(DISK_DATA)); + + /* Get disk geometry */ + DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool, + sizeof(DISK_GEOMETRY)); + if (DiskDeviceExtension->DiskGeometry == NULL) + { + DPRINT("Failed to allocate geometry buffer!\n"); + + IoDeleteDevice(DiskDeviceObject); + + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + /* Delete the harddisk device directory */ + ZwMakeTemporaryObject(Handle); + ZwClose(Handle); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Read the drive's capacity */ + Status = ScsiClassReadDriveCapacity(DiskDeviceObject); + if (!NT_SUCCESS(Status) && + (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0) + { + DPRINT1("Failed to retrieve drive capacity!\n"); + return(STATUS_SUCCESS); + } + else + { + /* Clear the verify flag for removable media drives. */ + DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME; + } + + DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector); + + if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) && + (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia)) + { + /* Allocate a partition list for a single entry. */ + PartitionList = ExAllocatePool(NonPagedPool, + sizeof(DRIVE_LAYOUT_INFORMATION)); + if (PartitionList != NULL) + { + RtlZeroMemory(PartitionList, + sizeof(DRIVE_LAYOUT_INFORMATION)); + PartitionList->PartitionCount = 1; + + DiskData->DriveNotReady = TRUE; + Status = STATUS_SUCCESS; + } + } + else + { + /* Read partition table */ + Status = IoReadPartitionTable(DiskDeviceObject, + DiskDeviceExtension->DiskGeometry->BytesPerSector, + TRUE, + &PartitionList); + + DPRINT("IoReadPartitionTable(): Status: %lx\n", Status); + + if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) && + DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + if (!NT_SUCCESS(Status)) + { + /* Drive is not ready. */ + DPRINT("Drive not ready\n"); + DiskData->DriveNotReady = TRUE; + } + else + { + ExFreePool(PartitionList); + } + + /* Allocate a partition list for a single entry. */ + PartitionList = ExAllocatePool(NonPagedPool, + sizeof(DRIVE_LAYOUT_INFORMATION)); + if (PartitionList != NULL) + { + RtlZeroMemory(PartitionList, + sizeof(DRIVE_LAYOUT_INFORMATION)); + PartitionList->PartitionCount = 1; + + Status = STATUS_SUCCESS; + } + } + } + + if (NT_SUCCESS(Status)) + { + DPRINT("Read partition table!\n"); + + DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount); + + for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++) + { + PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber]; + + DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n", + PartitionNumber, + PartitionEntry->PartitionNumber, + PartitionEntry->BootIndicator, + PartitionEntry->PartitionType, + PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/, + PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/); + + /* Create partition device object */ + sprintf(NameBuffer2, + "\\Device\\Harddisk%lu\\Partition%lu", + DiskNumber, + PartitionNumber + 1); + + Status = ScsiClassCreateDeviceObject(DriverObject, + NameBuffer2, + DiskDeviceObject, + &PartitionDeviceObject, + InitializationData); + DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status); + if (NT_SUCCESS(Status)) + { + PartitionDeviceObject->Flags = DiskDeviceObject->Flags; + PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics; + PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize; + PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement; + + PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension; + PartitionDeviceExtension->LockCount = 0; + PartitionDeviceExtension->DeviceNumber = DiskNumber; + PartitionDeviceExtension->PortDeviceObject = PortDeviceObject; + PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry; + PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice; + PartitionDeviceExtension->PortCapabilities = Capabilities; + PartitionDeviceExtension->StartingOffset.QuadPart = + PartitionEntry->StartingOffset.QuadPart; + PartitionDeviceExtension->PartitionLength.QuadPart = + PartitionEntry->PartitionLength.QuadPart; + PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber; + PartitionDeviceExtension->PathId = InquiryData->PathId; + PartitionDeviceExtension->TargetId = InquiryData->TargetId; + PartitionDeviceExtension->Lun = InquiryData->Lun; + PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift; + + DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1); + DiskData->PartitionType = PartitionEntry->PartitionType; + DiskData->PartitionNumber = PartitionNumber + 1; + DiskData->PartitionOrdinal = PartitionNumber + 1; + DiskData->HiddenSectors = PartitionEntry->HiddenSectors; + DiskData->BootIndicator = PartitionEntry->BootIndicator; + DiskData->DriveNotReady = FALSE; + } + else + { + DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status); + + break; + } + } + } + + if (PartitionList != NULL) + ExFreePool(PartitionList); + + DPRINT("DiskClassCreateDeviceObjects() done\n"); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * DiskClassDeviceControl + * + * DESCRIPTION + * Answer requests for device control calls + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * Standard dispatch arguments + * + * RETURNS + * Status + */ + +NTSTATUS STDCALL +DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + ULONG ControlCode, InputLength, OutputLength; + PDISK_DATA DiskData; + ULONG Information; + NTSTATUS Status; + + DPRINT("DiskClassDeviceControl() called!\n"); + + Status = STATUS_INVALID_DEVICE_REQUEST; + Information = 0; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; + InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + DiskData = (PDISK_DATA)(DeviceExtension + 1); + + switch (ControlCode) + { + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n"); + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PDISK_GEOMETRY Geometry; + + if (DeviceExtension->DiskGeometry == NULL) + { + DPRINT("No disk geometry available!\n"); + DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool, + sizeof(DISK_GEOMETRY)); + } + Status = ScsiClassReadDriveCapacity(DeviceObject); + DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status); + if (NT_SUCCESS(Status)) + { + Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer; + RtlMoveMemory(Geometry, + DeviceExtension->DiskGeometry, + sizeof(DISK_GEOMETRY)); + + Status = STATUS_SUCCESS; + Information = sizeof(DISK_GEOMETRY); + } + } + break; + + case IOCTL_DISK_GET_PARTITION_INFO: + DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n"); + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(PARTITION_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else if (DiskData->PartitionNumber == 0) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + PPARTITION_INFORMATION PartitionInfo; + + PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + PartitionInfo->PartitionType = DiskData->PartitionType; + PartitionInfo->StartingOffset = DeviceExtension->StartingOffset; + PartitionInfo->PartitionLength = DeviceExtension->PartitionLength; + PartitionInfo->HiddenSectors = DiskData->HiddenSectors; + PartitionInfo->PartitionNumber = DiskData->PartitionNumber; + PartitionInfo->BootIndicator = DiskData->BootIndicator; + PartitionInfo->RewritePartition = FALSE; + PartitionInfo->RecognizedPartition = + IsRecognizedPartition(DiskData->PartitionType); + + Status = STATUS_SUCCESS; + Information = sizeof(PARTITION_INFORMATION); + } + break; + + case IOCTL_DISK_SET_PARTITION_INFO: + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < + sizeof(SET_PARTITION_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else if (DiskData->PartitionNumber == 0) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + PSET_PARTITION_INFORMATION PartitionInfo; + + PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice, + DeviceExtension->DiskGeometry->BytesPerSector, + DiskData->PartitionOrdinal, + PartitionInfo->PartitionType); + if (NT_SUCCESS(Status)) + { + DiskData->PartitionType = PartitionInfo->PartitionType; + } + } + break; + + case IOCTL_DISK_GET_DRIVE_LAYOUT: + if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(DRIVE_LAYOUT_INFORMATION)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + PDRIVE_LAYOUT_INFORMATION PartitionList; + + Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice, + DeviceExtension->DiskGeometry->BytesPerSector, + FALSE, + &PartitionList); + if (NT_SUCCESS(Status)) + { + ULONG BufferSize; + + BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, + PartitionEntry[0]); + BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION); + + if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, + PartitionList, + BufferSize); + Status = STATUS_SUCCESS; + Information = BufferSize; + } + ExFreePool(PartitionList); + } + } + break; + + case IOCTL_DISK_SET_DRIVE_LAYOUT: + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < + sizeof(DRIVE_LAYOUT_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PDRIVE_LAYOUT_INFORMATION PartitionList; + ULONG TableSize; + + PartitionList = Irp->AssociatedIrp.SystemBuffer; + TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) + + ((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION)); + + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + Status = IoWritePartitionTable(DeviceExtension->DeviceObject, + DeviceExtension->DiskGeometry->BytesPerSector, + DeviceExtension->DiskGeometry->SectorsPerTrack, + DeviceExtension->DiskGeometry->TracksPerCylinder, + PartitionList); + if (NT_SUCCESS(Status)) + { + /* FIXME: Update partition device objects */ + + Information = TableSize; + } + } + } + break; + + case IOCTL_DISK_VERIFY: + case IOCTL_DISK_FORMAT_TRACKS: + case IOCTL_DISK_PERFORMANCE: + case IOCTL_DISK_IS_WRITABLE: + case IOCTL_DISK_LOGGING: + case IOCTL_DISK_FORMAT_TRACKS_EX: + case IOCTL_DISK_HISTOGRAM_STRUCTURE: + case IOCTL_DISK_HISTOGRAM_DATA: + case IOCTL_DISK_HISTOGRAM_RESET: + case IOCTL_DISK_REQUEST_STRUCTURE: + case IOCTL_DISK_REQUEST_DATA: + /* If we get here, something went wrong. Inform the requestor */ + DPRINT1("Unhandled control code: %lx\n", ControlCode); + Status = STATUS_INVALID_DEVICE_REQUEST; + Information = 0; + break; + + default: + /* Call the common device control function */ + return(ScsiClassDeviceControl(DeviceObject, Irp)); + } + + /* Verify the device if the user caused the error */ + if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status)) + { + IoSetHardErrorOrVerifyDevice(Irp, DeviceObject); + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = Information; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + + return(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * DiskClassShutdownFlush + * + * DESCRIPTION + * Answer requests for shutdown and flush calls. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceObject + * Pointer to the device. + * + * Irp + * Pointer to the IRP + * + * RETURN VALUE + * Status + */ + +NTSTATUS STDCALL +DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + PSCSI_REQUEST_BLOCK Srb; + + DPRINT("DiskClassShutdownFlush() called!\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + + /* Allocate SRB */ + Srb = ExAllocatePool(NonPagedPool, + sizeof(SCSI_REQUEST_BLOCK)); + if (Srb == NULL) + { + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Initialize SRB */ + RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK)); + Srb->Length = sizeof(SCSI_REQUEST_BLOCK); + + /* Set device IDs */ + Srb->PathId = DeviceExtension->PathId; + Srb->TargetId = DeviceExtension->TargetId; + Srb->Lun = DeviceExtension->Lun; + + + /* FIXME: Flush write cache */ + + + /* Get current stack location */ + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + + /* FIXME: Unlock removable media upon shutdown */ + + + /* No retry */ + IrpStack->Parameters.Others.Argument4 = (PVOID)0; + + /* Send shutdown or flush request to the port driver */ + Srb->CdbLength = 0; + if (IrpStack->MajorFunction == IRP_MJ_SHUTDOWN) + Srb->Function = SRB_FUNCTION_SHUTDOWN; + else + Srb->Function = SRB_FUNCTION_FLUSH; + + /* Init completion routine */ + IoSetCompletionRoutine(Irp, + ScsiClassIoComplete, + Srb, + TRUE, + TRUE, + TRUE); + + /* Prepare next stack location for a call to the port driver */ + IrpStack = IoGetNextIrpStackLocation(Irp); + IrpStack->MajorFunction = IRP_MJ_SCSI; + IrpStack->Parameters.Scsi.Srb = Srb; + Srb->OriginalRequest = Irp; + + /* Call port driver */ + return(IoCallDriver(DeviceExtension->PortDeviceObject, Irp)); +} + +/* EOF */ diff --git a/drivers/storage/disk/disk.h b/drivers/storage/disk/disk.h new file mode 100644 index 0000000..eb34864 --- /dev/null +++ b/drivers/storage/disk/disk.h @@ -0,0 +1,250 @@ +// +// IDE.H - defines and typedefs for the IDE Driver module. +// + +#ifndef __IDE_H +#define __IDE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define IDE_MAXIMUM_DEVICES 8 + +#define IDE_MAX_NAME_LENGTH 50 + +#define IDE_SECTOR_BUF_SZ 512 +#define IDE_MAX_SECTORS_PER_XFER 256 +#define IDE_MAX_RESET_RETRIES 10000 +#define IDE_MAX_POLL_RETRIES 100000 +#define IDE_MAX_WRITE_RETRIES 1000 +#define IDE_MAX_BUSY_RETRIES 100 +//#define IDE_MAX_BUSY_RETRIES 100000 +#define IDE_MAX_DRQ_RETRIES 10000 +//#define IDE_MAX_CMD_RETRIES 1 +#define IDE_MAX_CMD_RETRIES 0 +#define IDE_CMD_TIMEOUT 5 +#define IDE_RESET_PULSE_LENGTH 500 /* maybe a little too long */ +#define IDE_RESET_BUSY_TIMEOUT 31 +#define IDE_RESET_DRDY_TIMEOUT 120 + +// Control Block offsets and masks +#define IDE_REG_ALT_STATUS 0x0000 +#define IDE_REG_DEV_CNTRL 0x0000 /* device control register */ +#define IDE_DC_SRST 0x04 /* drive reset (both drives) */ +#define IDE_DC_nIEN 0x02 /* IRQ enable (active low) */ +#define IDE_REG_DRV_ADDR 0x0001 + +// Command Block offsets and masks +#define IDE_REG_DATA_PORT 0x0000 +#define IDE_REG_ERROR 0x0001 /* error register */ +#define IDE_ER_AMNF 0x01 /* addr mark not found */ +#define IDE_ER_TK0NF 0x02 /* track 0 not found */ +#define IDE_ER_ABRT 0x04 /* command aborted */ +#define IDE_ER_MCR 0x08 /* media change requested */ +#define IDE_ER_IDNF 0x10 /* ID not found */ +#define IDE_ER_MC 0x20 /* Media changed */ +#define IDE_ER_UNC 0x40 /* Uncorrectable data error */ +#define IDE_REG_PRECOMP 0x0001 +#define IDE_REG_SECTOR_CNT 0x0002 +#define IDE_REG_SECTOR_NUM 0x0003 +#define IDE_REG_CYL_LOW 0x0004 +#define IDE_REG_CYL_HIGH 0x0005 +#define IDE_REG_DRV_HEAD 0x0006 +#define IDE_DH_FIXED 0xA0 +#define IDE_DH_LBA 0x40 +#define IDE_DH_HDMASK 0x0F +#define IDE_DH_DRV0 0x00 +#define IDE_DH_DRV1 0x10 +#define IDE_REG_STATUS 0x0007 +#define IDE_SR_BUSY 0x80 +#define IDE_SR_DRDY 0x40 +#define IDE_SR_DRQ 0x08 +#define IDE_SR_ERR 0x01 +#define IDE_REG_COMMAND 0x0007 +#define IDE_CMD_READ 0x20 +#define IDE_CMD_READ_RETRY 0x21 +#define IDE_CMD_WRITE 0x30 +#define IDE_CMD_WRITE_RETRY 0x31 +#define IDE_CMD_IDENT_DRV 0xEC + +// +// Access macros for command registers +// Each macro takes an address of the command port block, and data +// +#define IDEReadError(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR))) +#define IDEWritePrecomp(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data))) +#define IDEReadSectorCount(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT))) +#define IDEWriteSectorCount(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data))) +#define IDEReadSectorNum(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM))) +#define IDEWriteSectorNum(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data))) +#define IDEReadCylinderLow(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW))) +#define IDEWriteCylinderLow(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data))) +#define IDEReadCylinderHigh(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH))) +#define IDEWriteCylinderHigh(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data))) +#define IDEReadDriveHead(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD))) +#define IDEWriteDriveHead(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data))) +#define IDEReadStatus(Address) \ + (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS))) +#define IDEWriteCommand(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data))) + + +// +// Data block read and write commands +// +#define IDEReadBlock(Address, Buffer, Count) \ + (READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) +#define IDEWriteBlock(Address, Buffer, Count) \ + (WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) + +// +// Access macros for control registers +// Each macro takes an address of the control port blank and data +// +#define IDEWriteDriveControl(Address, Data) \ + (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data))) + +// IDE_DEVICE_EXTENSION +// +// DESCRIPTION: +// Extension to be placed in each device object +// +// ACCESS: +// Allocated from NON-PAGED POOL +// Available at any IRQL +// + +typedef struct _IDE_DEVICE_EXTENSION { + PDEVICE_OBJECT DeviceObject; + PCONTROLLER_OBJECT ControllerObject; + struct _IDE_DEVICE_EXTESION *DiskExtension; + int UnitNumber; + BOOLEAN LBASupported; + BOOLEAN DMASupported; + int BytesPerSector; + int LogicalHeads; + int SectorsPerLogCyl; + int SectorsPerLogTrk; + int Offset; + int Size; + + int Operation; + ULONG BytesRequested; + ULONG BytesToTransfer; + ULONG BytesRemaining; + ULONG StartingSector; + int SectorsTransferred; + BYTE *TargetAddress; + +} IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION; + +// IDE_TIMER_STATES +// +// DESCRIPTION: +// An enumeration containing the states in the timer DFA +// + +typedef enum _IDE_TIMER_STATES { + IDETimerIdle, + IDETimerCmdWait, + IDETimerResetWaitForBusyNegate, + IDETimerResetWaitForDrdyAssert +} IDE_TIMER_STATES; + +// IDE_CONTROLLER_EXTENSION +// +// DESCRIPTION: +// Driver-defined structure used to hold miscellaneous controller information. +// +// ACCESS: +// Allocated from NON-PAGED POOL +// Available at any IRQL +// + +typedef struct _IDE_CONTROLLER_EXTENSION { + KSPIN_LOCK SpinLock; + int Number; + int Vector; + int CommandPortBase; + int ControlPortBase; + BOOLEAN DMASupported; + BOOLEAN ControllerInterruptBug; + PKINTERRUPT Interrupt; + + BOOLEAN OperationInProgress; + BYTE DeviceStatus; + PIDE_DEVICE_EXTENSION DeviceForOperation; + PIRP CurrentIrp; + int Retries; + + IDE_TIMER_STATES TimerState; + LONG TimerCount; + PDEVICE_OBJECT TimerDevice; + +} IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION; + +// IDE_DRIVE_IDENTIFY + +typedef struct _IDE_DRIVE_IDENTIFY { + WORD ConfigBits; /*00*/ + WORD LogicalCyls; /*01*/ + WORD Reserved02; /*02*/ + WORD LogicalHeads; /*03*/ + WORD BytesPerTrack; /*04*/ + WORD BytesPerSector; /*05*/ + WORD SectorsPerTrack; /*06*/ + BYTE InterSectorGap; /*07*/ + BYTE InterSectorGapSize; + BYTE Reserved08H; /*08*/ + BYTE BytesInPLO; + WORD VendorUniqueCnt; /*09*/ + char SerialNumber[20]; /*10*/ + WORD ControllerType; /*20*/ + WORD BufferSize; /*21*/ + WORD ECCByteCnt; /*22*/ + char FirmwareRev[8]; /*23*/ + char ModelNumber[40]; /*27*/ + WORD RWMultImplemented; /*47*/ + WORD Reserved48; /*48*/ + WORD Capabilities; /*49*/ +#define IDE_DRID_STBY_SUPPORTED 0x2000 +#define IDE_DRID_IORDY_SUPPORTED 0x0800 +#define IDE_DRID_IORDY_DISABLE 0x0400 +#define IDE_DRID_LBA_SUPPORTED 0x0200 +#define IDE_DRID_DMA_SUPPORTED 0x0100 + WORD Reserved50; /*50*/ + WORD MinPIOTransTime; /*51*/ + WORD MinDMATransTime; /*52*/ + WORD TMFieldsValid; /*53*/ + WORD TMCylinders; /*54*/ + WORD TMHeads; /*55*/ + WORD TMSectorsPerTrk; /*56*/ + WORD TMCapacityLo; /*57*/ + WORD TMCapacityHi; /*58*/ + WORD Reserved59; /*59*/ + WORD TMSectorCountLo; /*60*/ + WORD TMSectorCountHi; /*61*/ + WORD Reserved62[194]; /*62*/ +} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY; + + +#ifdef __cplusplus +} +#endif + +#endif /* __IDE_H */ + + diff --git a/drivers/storage/disk/disk.rc b/drivers/storage/disk/disk.rc new file mode 100644 index 0000000..5a97ec3 --- /dev/null +++ b/drivers/storage/disk/disk.rc @@ -0,0 +1,39 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Disk Class Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "disk\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "disk.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/drivers/storage/disk/makefile b/drivers/storage/disk/makefile new file mode 100644 index 0000000..92a8f45 --- /dev/null +++ b/drivers/storage/disk/makefile @@ -0,0 +1,17 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = driver + +TARGET_NAME = disk + +TARGET_DDKLIBS = class2.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/drivers/storage/disk/partitio.h b/drivers/storage/disk/partitio.h new file mode 100644 index 0000000..06841ee --- /dev/null +++ b/drivers/storage/disk/partitio.h @@ -0,0 +1,41 @@ +/** +*** Partition.h - defines and structs for harddrive partition info +*** +*** 05/30/98 RJJ Created +**/ + +#ifndef __PARTITION_H +#define __PARTITION_H + +#define PARTITION_MAGIC 0xaa55 +#define PART_MAGIC_OFFSET 0x01fe +#define PARTITION_OFFSET 0x01be +#define PARTITION_TBL_SIZE 4 +#define PTCHSToLBA(c, h, s, scnt, hcnt) ((s) & 0x3f) + \ + (scnt) * ( (h) + (hcnt) * ((c) | (((s) & 0xc0) << 2))) +#define PTLBAToCHS(lba, c, h, s, scnt, hcnt) ( \ + (s) = (lba) % (scnt) + 1, \ + (lba) /= (scnt), \ + (h) = (lba) % (hcnt), \ + (lba) /= (heads), \ + (c) = (lba) & 0xff, \ + (s) |= ((lba) >> 2) & 0xc0) + + +typedef struct Partition { + unsigned char BootFlags; + unsigned char StartingHead; + unsigned char StartingSector; + unsigned char StartingCylinder; + unsigned char PartitionType; + unsigned char EndingHead; + unsigned char EndingSector; + unsigned char EndingCylinder; + unsigned int StartingBlock; + unsigned int SectorCount; + +} PARTITION; + +#endif // PARTITION_H + + diff --git a/drivers/storage/scsiport/.cvsignore b/drivers/storage/scsiport/.cvsignore new file mode 100644 index 0000000..71e1e21 --- /dev/null +++ b/drivers/storage/scsiport/.cvsignore @@ -0,0 +1,5 @@ +base.tmp +junk.tmp +temp.exp +scsiport.coff +scsiport.sys.unstripped diff --git a/drivers/storage/scsiport/makefile b/drivers/storage/scsiport/makefile new file mode 100644 index 0000000..1f50c8f --- /dev/null +++ b/drivers/storage/scsiport/makefile @@ -0,0 +1,13 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = scsiport + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/drivers/storage/scsiport/scsiport.c b/drivers/storage/scsiport/scsiport.c new file mode 100644 index 0000000..8269d0f --- /dev/null +++ b/drivers/storage/scsiport/scsiport.c @@ -0,0 +1,1616 @@ +/* + * ReactOS kernel + * Copyright (C) 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/scsiport/scsiport.c + * PURPOSE: SCSI port driver + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + + +#define VERSION "0.0.1" + + +/* TYPES *********************************************************************/ + + +typedef enum _SCSI_PORT_TIMER_STATES +{ + IDETimerIdle, + IDETimerCmdWait, + IDETimerResetWaitForBusyNegate, + IDETimerResetWaitForDrdyAssert +} SCSI_PORT_TIMER_STATES; + + +/* + * SCSI_PORT_DEVICE_EXTENSION + * + * DESCRIPTION + * First part of the port objects device extension. The second + * part is the miniport-specific device extension. + */ + +typedef struct _SCSI_PORT_DEVICE_EXTENSION +{ + ULONG Length; + ULONG MiniPortExtensionSize; + PORT_CONFIGURATION_INFORMATION PortConfig; + ULONG PortNumber; + + KSPIN_LOCK IrpLock; + KSPIN_LOCK SpinLock; + PKINTERRUPT Interrupt; + PIRP CurrentIrp; + ULONG IrpFlags; + + SCSI_PORT_TIMER_STATES TimerState; + LONG TimerCount; + + BOOLEAN Initializing; + + ULONG PortBusInfoSize; + PSCSI_ADAPTER_BUS_INFO PortBusInfo; + + PIO_SCSI_CAPABILITIES PortCapabilities; + + PDEVICE_OBJECT DeviceObject; + PCONTROLLER_OBJECT ControllerObject; + + PHW_STARTIO HwStartIo; + PHW_INTERRUPT HwInterrupt; + + PSCSI_REQUEST_BLOCK OriginalSrb; + SCSI_REQUEST_BLOCK InternalSrb; + SENSE_DATA InternalSenseData; + + UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */ +} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION; + + +/* + * SCSI_PORT_TIMER_STATES + * + * DESCRIPTION + * An enumeration containing the states in the timer DFA + */ + + + +#define IRP_FLAG_COMPLETE 0x00000001 +#define IRP_FLAG_NEXT 0x00000002 + + +/* GLOBALS *******************************************************************/ + +static NTSTATUS STDCALL +ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static NTSTATUS STDCALL +ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static VOID STDCALL +ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +static IO_ALLOCATION_ACTION STDCALL +ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context); + +static BOOLEAN STDCALL +ScsiPortStartPacket(IN OUT PVOID Context); + +static NTSTATUS +ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, + IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension, + IN ULONG PortCount); + +static VOID +ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension); + +static BOOLEAN STDCALL +ScsiPortIsr(IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext); + +static VOID STDCALL +ScsiPortDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext); + +static VOID STDCALL +ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, + PVOID Context); + +static PSCSI_REQUEST_BLOCK +ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK OriginalSrb); + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * DriverEntry + * + * DESCRIPTION + * This function initializes the driver. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * System allocated Driver Object for this driver. + * + * RegistryPath + * Name of registry driver service key. + * + * RETURN VALUE + * Status. + */ + +NTSTATUS STDCALL +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT("ScsiPort Driver %s\n", VERSION); + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * ScsiDebugPrint + * + * DESCRIPTION + * Prints debugging messages. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DebugPrintLevel + * Debug level of the given message. + * + * DebugMessage + * Pointer to printf()-compatible format string. + * + * ... + Additional output data (see printf()). + * + * RETURN VALUE + * None. + */ + +VOID +ScsiDebugPrint(IN ULONG DebugPrintLevel, + IN PCHAR DebugMessage, + ...) +{ + char Buffer[256]; + va_list ap; + +#if 0 + if (DebugPrintLevel > InternalDebugLevel) + return; +#endif + + va_start(ap, DebugMessage); + vsprintf(Buffer, DebugMessage, ap); + va_end(ap); + + DbgPrint(Buffer); +} + + +VOID STDCALL +ScsiPortCompleteRequest(IN PVOID HwDeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN UCHAR SrbStatus) +{ + UNIMPLEMENTED; +} + + +ULONG STDCALL +ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address) +{ + return(Address.u.LowPart); +} + + +VOID STDCALL +ScsiPortFlushDma(IN PVOID HwDeviceExtension) +{ + UNIMPLEMENTED; +} + + +VOID STDCALL +ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension, + IN PVOID MappedAddress) +{ + UNIMPLEMENTED; +} + + +ULONG STDCALL +ScsiPortGetBusData(IN PVOID DeviceExtension, + IN ULONG BusDataType, + IN ULONG SystemIoBusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length) +{ + return(HalGetBusData(BusDataType, + SystemIoBusNumber, + SlotNumber, + Buffer, + Length)); +} + + +PVOID STDCALL +ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension, + IN INTERFACE_TYPE BusType, + IN ULONG SystemIoBusNumber, + IN SCSI_PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfBytes, + IN BOOLEAN InIoSpace) +{ + ULONG AddressSpace; + PHYSICAL_ADDRESS TranslatedAddress; + PVOID VirtualAddress; + PVOID Buffer; + BOOLEAN rc; + + AddressSpace = (ULONG)InIoSpace; + + if (!HalTranslateBusAddress(BusType, + SystemIoBusNumber, + IoAddress, + &AddressSpace, + &TranslatedAddress)) + return NULL; + + /* i/o space */ + if (AddressSpace != 0) + return (PVOID)TranslatedAddress.u.LowPart; + + VirtualAddress = MmMapIoSpace(TranslatedAddress, + NumberOfBytes, + FALSE); + + Buffer = ExAllocatePool(NonPagedPool,0x20); + if (Buffer == NULL) + return VirtualAddress; + + return NULL; /* ?? */ +} + + +PVOID STDCALL +ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun) +{ + UNIMPLEMENTED; +} + + +SCSI_PHYSICAL_ADDRESS STDCALL +ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, + IN PVOID VirtualAddress, + OUT ULONG *Length) +{ + UNIMPLEMENTED; +} + + +PSCSI_REQUEST_BLOCK STDCALL +ScsiPortGetSrb(IN PVOID DeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN LONG QueueTag) +{ + UNIMPLEMENTED; +} + + +PVOID STDCALL +ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension, + IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, + IN ULONG NumberOfBytes) +{ + UNIMPLEMENTED; +} + + +PVOID STDCALL +ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension, + IN SCSI_PHYSICAL_ADDRESS PhysicalAddress) +{ + UNIMPLEMENTED; +} + + +/********************************************************************** + * NAME EXPORTED + * ScsiPortInitialize + * + * DESCRIPTION + * Initializes SCSI port driver specific data. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * Argument1 + * Pointer to the miniport driver's driver object. + * + * Argument2 + * Pointer to the miniport driver's registry path. + * + * HwInitializationData + * Pointer to port driver specific configuration data. + * + * HwContext + Miniport driver specific context. + * + * RETURN VALUE + * Status. + */ + +ULONG STDCALL +ScsiPortInitialize(IN PVOID Argument1, + IN PVOID Argument2, + IN struct _HW_INITIALIZATION_DATA *HwInitializationData, + IN PVOID HwContext) +{ + PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1; + PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2; + PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension; + PCONFIGURATION_INFORMATION SystemConfig; + PPORT_CONFIGURATION_INFORMATION PortConfig; + BOOLEAN Again; + ULONG i; + ULONG Result; + NTSTATUS Status; + ULONG MaxBus; + PACCESS_RANGE AccessRanges; + ULONG ExtensionSize; + + DPRINT("ScsiPortInitialize() called!\n"); + + if ((HwInitializationData->HwInitialize == NULL) || + (HwInitializationData->HwStartIo == NULL) || + (HwInitializationData->HwInterrupt == NULL) || + (HwInitializationData->HwFindAdapter == NULL) || + (HwInitializationData->HwResetBus == NULL)) + return(STATUS_INVALID_PARAMETER); + + DriverObject->DriverStartIo = ScsiPortStartIo; + DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl; + DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi; + + + SystemConfig = IoGetConfigurationInformation(); + + ExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) + + HwInitializationData->DeviceExtensionSize; + PseudoDeviceExtension = ExAllocatePool(PagedPool, + ExtensionSize); + RtlZeroMemory(PseudoDeviceExtension, + ExtensionSize); + PseudoDeviceExtension->Length = ExtensionSize; + PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize; + PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo; + PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt; + + PortConfig = &PseudoDeviceExtension->PortConfig; + + PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION); + PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType; + PortConfig->InterruptMode = + (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched; + PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed; + PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed; + PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges; + + PortConfig->AccessRanges = + ExAllocatePool(PagedPool, + sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges); + + + PortConfig->SystemIoBusNumber = 0; + PortConfig->SlotNumber = 0; + + MaxBus = (PortConfig->AdapterInterfaceType == PCIBus) ? 8 : 1; + + DPRINT("MaxBus: %lu\n", MaxBus); + + while (TRUE) + { + DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber); + +// RtlZeroMemory(AccessRanges, +// sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges); + + RtlZeroMemory(PseudoDeviceExtension->MiniPortDeviceExtension, + PseudoDeviceExtension->MiniPortExtensionSize); + + /* Note: HwFindAdapter is called once for each bus */ + Result = (HwInitializationData->HwFindAdapter)(&PseudoDeviceExtension->MiniPortDeviceExtension, + HwContext, + NULL, /* BusInformation */ + NULL, /* ArgumentString */ + &PseudoDeviceExtension->PortConfig, + &Again); + DPRINT("HwFindAdapter() result: %lu\n", Result); + + if (Result == SP_RETURN_FOUND) + { + DPRINT("ScsiPortInitialize(): Found HBA!\n"); + + Status = ScsiPortCreatePortDevice(DriverObject, + PseudoDeviceExtension, + SystemConfig->ScsiPortCount); + + if (!NT_SUCCESS(Status)) + { + DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status); + + ExFreePool(PortConfig->AccessRanges); + ExFreePool(PseudoDeviceExtension); + + return(Status); + } + + /* Update the configuration info */ + SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed; + SystemConfig->AtDiskSecondaryAddressClaimed = PortConfig->AtdiskSecondaryClaimed; + SystemConfig->ScsiPortCount++; + } + + if (Again == FALSE) + { + PortConfig->SystemIoBusNumber++; + PortConfig->SlotNumber = 0; + } + + DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig->SystemIoBusNumber, MaxBus); + if (PortConfig->SystemIoBusNumber >= MaxBus) + { + DPRINT("Scanned all buses!\n"); + break; + } + } + + ExFreePool(PortConfig->AccessRanges); + ExFreePool(PseudoDeviceExtension); + + DPRINT("ScsiPortInitialize() done!\n"); + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb, + IN ULONG LogicalAddress, + IN ULONG Length) +{ + UNIMPLEMENTED; +} + + +VOID STDCALL +ScsiPortLogError(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN ULONG ErrorCode, + IN ULONG UniqueId) +{ + UNIMPLEMENTED; +} + + +VOID STDCALL +ScsiPortMoveMemory(OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length) +{ + RtlMoveMemory(Destination, + Source, + Length); +} + + +VOID +ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, + IN PVOID HwDeviceExtension, + ...) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + + DPRINT("ScsiPortNotification() called\n"); + + DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, + SCSI_PORT_DEVICE_EXTENSION, + MiniPortDeviceExtension); + + DPRINT("DeviceExtension %p\n", DeviceExtension); + + DPRINT("Initializing = %s\n", (DeviceExtension->Initializing)?"TRUE":"FALSE"); + + if (DeviceExtension->Initializing == TRUE) + return; + + switch (NotificationType) + { + case RequestComplete: + DPRINT("Notify: RequestComplete\n"); + DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE; + break; + + case NextRequest: + DPRINT("Notify: NextRequest\n"); + DeviceExtension->IrpFlags |= IRP_FLAG_NEXT; + break; + + default: + break; + } +} + + +ULONG STDCALL +ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension, + IN ULONG BusDataType, + IN ULONG SystemIoBusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + return(HalSetBusDataByOffset(BusDataType, + SystemIoBusNumber, + SlotNumber, + Buffer, + Offset, + Length)); +} + + +BOOLEAN STDCALL +ScsiPortValidateRange(IN PVOID HwDeviceExtension, + IN INTERFACE_TYPE BusType, + IN ULONG SystemIoBusNumber, + IN SCSI_PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfBytes, + IN BOOLEAN InIoSpace) +{ + return(TRUE); +} + + +/* INTERNAL FUNCTIONS ********************************************************/ + +/********************************************************************** + * NAME INTERNAL + * ScsiPortCreateClose + * + * DESCRIPTION + * Answer requests for Create/Close calls: a null operation. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DeviceObject + * Pointer to a device object. + * + * Irp + * Pointer to an IRP. + * + * ... + Additional output data (see printf()). + * + * RETURN VALUE + * Status. + */ + +static NTSTATUS STDCALL +ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("ScsiPortCreateClose()\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = FILE_OPENED; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME INTERNAL + * ScsiPortDispatchScsi + * + * DESCRIPTION + * Answer requests for SCSI calls + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * Standard dispatch arguments + * + * RETURNS + * NTSTATUS + */ + +static NTSTATUS STDCALL +ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION Stack; + PSCSI_REQUEST_BLOCK Srb; + NTSTATUS Status = STATUS_SUCCESS; + ULONG DataSize = 0; + + DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", + DeviceObject, Irp); + + DeviceExtension = DeviceObject->DeviceExtension; + Stack = IoGetCurrentIrpStackLocation(Irp); + + Srb = Stack->Parameters.Scsi.Srb; + if (Srb == NULL) + { + Status = STATUS_UNSUCCESSFUL; + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); + } + + DPRINT("Srb: %p\n", Srb); + DPRINT("Srb->Function: %lu\n", Srb->Function); + DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun); + + switch (Srb->Function) + { + case SRB_FUNCTION_EXECUTE_SCSI: + IoStartPacket(DeviceObject, Irp, NULL, NULL); + return(STATUS_PENDING); + + case SRB_FUNCTION_SHUTDOWN: + case SRB_FUNCTION_FLUSH: + if (DeviceExtension->PortConfig.CachesData == TRUE) + { + IoStartPacket(DeviceObject, Irp, NULL, NULL); + return(STATUS_PENDING); + } + break; + + case SRB_FUNCTION_CLAIM_DEVICE: + { + PSCSI_ADAPTER_BUS_INFO AdapterInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + + DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n"); + DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun); + + Srb->DataBuffer = NULL; + + if (DeviceExtension->PortBusInfo != NULL) + { + AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; + + if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + + AdapterInfo->BusData[Srb->PathId].InquiryDataOffset); + + while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if ((UnitInfo->TargetId == Srb->TargetId) && + (UnitInfo->Lun == Srb->Lun) && + (UnitInfo->DeviceClaimed == FALSE)) + { + UnitInfo->DeviceClaimed = TRUE; + DPRINT("Claimed device!\n"); + + /* FIXME: Hack!!!!! */ + Srb->DataBuffer = DeviceObject; + + break; + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset); + } + } + } + break; + + case SRB_FUNCTION_RELEASE_DEVICE: + { + PSCSI_ADAPTER_BUS_INFO AdapterInfo; + PSCSI_INQUIRY_DATA UnitInfo; + PINQUIRYDATA InquiryData; + + DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n"); + DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun); + + if (DeviceExtension->PortBusInfo != NULL) + { + AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo; + + if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + + AdapterInfo->BusData[Srb->PathId].InquiryDataOffset); + + while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset) + { + InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData; + + if ((UnitInfo->TargetId == Srb->TargetId) && + (UnitInfo->Lun == Srb->Lun) && + (UnitInfo->DeviceClaimed == TRUE)) + { + UnitInfo->DeviceClaimed = FALSE; + DPRINT("Released device!\n"); + break; + } + + if (UnitInfo->NextInquiryDataOffset == 0) + break; + + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset); + } + } + } + break; + + default: + DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = DataSize; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(Status); +} + + +/********************************************************************** + * NAME INTERNAL + * ScsiPortDeviceControl + * + * DESCRIPTION + * Answer requests for device control calls + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * Standard dispatch arguments + * + * RETURNS + * NTSTATUS + */ + +static NTSTATUS STDCALL +ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + + DPRINT("ScsiPortDeviceControl()\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceExtension = DeviceObject->DeviceExtension; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + + case IOCTL_SCSI_GET_CAPABILITIES: + { + DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n"); + + *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) = + DeviceExtension->PortCapabilities; + + Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES); + } + break; + + case IOCTL_SCSI_GET_INQUIRY_DATA: + { + DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n"); + + /* Copy inquiry data to the port device extension */ + memcpy(Irp->AssociatedIrp.SystemBuffer, + DeviceExtension->PortBusInfo, + DeviceExtension->PortBusInfoSize); + + DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize); + Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize; + } + break; + + default: + DPRINT1(" unknown ioctl code: 0x%lX\n", + Stack->Parameters.DeviceIoControl.IoControlCode); + break; + } + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return(STATUS_SUCCESS); +} + + +static VOID STDCALL +ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + KIRQL OldIrql; + + DPRINT("ScsiPortStartIo() called!\n"); + + DeviceExtension = DeviceObject->DeviceExtension; + IrpStack = IoGetCurrentIrpStackLocation(Irp); + + // FIXME: implement the supported functions + + switch (IrpStack->MajorFunction) + { + case IRP_MJ_SCSI: + { + BOOLEAN Result; + PSCSI_REQUEST_BLOCK Srb; + KIRQL oldIrql; + + DPRINT("IRP_MJ_SCSI\n"); + + Srb = IrpStack->Parameters.Scsi.Srb; + + DPRINT("DeviceExtension %p\n", DeviceExtension); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Srb->DataTransferLength; + + DeviceExtension->CurrentIrp = Irp; + + if (!KeSynchronizeExecution(DeviceExtension->Interrupt, + ScsiPortStartPacket, + DeviceExtension)) + { + DPRINT("Synchronization failed!\n"); + + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, + FALSE); + } + KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql); + if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE) + { + DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + } + + if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT) + { + DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT; + KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); + IoStartNextPacket(DeviceObject, + FALSE); + } + else + { + KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); + } + } + break; + + default: + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, + IO_NO_INCREMENT); + IoStartNextPacket(DeviceObject, + FALSE); + break; + } + DPRINT("ScsiPortStartIo() done\n"); +} + + +static BOOLEAN STDCALL +ScsiPortStartPacket(IN OUT PVOID Context) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + PSCSI_REQUEST_BLOCK Srb; + + DPRINT("ScsiPortStartPacket() called\n"); + + DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context; + + IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp); + Srb = IrpStack->Parameters.Scsi.Srb; + + return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, + Srb)); +} + + +/********************************************************************** + * NAME INTERNAL + * ScsiPortCreatePortDevice + * + * DESCRIPTION + * Creates and initializes a SCSI port device object. + * + * RUN LEVEL + * PASSIVE_LEVEL + * + * ARGUMENTS + * DriverObject + * ... + * + * PseudoDeviceExtension + * ... + * + * PortNumber + * ... + * + * RETURNS + * NTSTATUS + */ + +static NTSTATUS +ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject, + IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension, + IN ULONG PortNumber) +{ + PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension; + PIO_SCSI_CAPABILITIES PortCapabilities; + PDEVICE_OBJECT PortDeviceObject; + WCHAR NameBuffer[80]; + UNICODE_STRING DeviceName; + WCHAR DosNameBuffer[80]; + UNICODE_STRING DosDeviceName; + NTSTATUS Status; + ULONG AccessRangeSize; + +#if 0 + ULONG MappedIrq; + KIRQL Dirql; + KAFFINITY Affinity; +#endif + + DPRINT("ScsiPortCreatePortDevice() called\n"); + +#if 0 + MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType, + PseudoDeviceExtension->PortConfig.SystemIoBusNumber, + 0, + PseudoDeviceExtension->PortConfig.BusInterruptLevel, + &Dirql, + &Affinity); +#endif + + /* Create a unicode device name */ + swprintf(NameBuffer, + L"\\Device\\ScsiPort%lu", + PortNumber); + RtlInitUnicodeString(&DeviceName, + NameBuffer); + + DPRINT("Creating device: %wZ\n", &DeviceName); + + /* Create the port device */ + Status = IoCreateDevice(DriverObject, + PseudoDeviceExtension->Length, + &DeviceName, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &PortDeviceObject); + if (!NT_SUCCESS(Status)) + { + DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status); + return(Status); + } + + DPRINT("Created device: %wZ\n", &DeviceName); + + /* Set the buffering strategy here... */ + PortDeviceObject->Flags |= DO_DIRECT_IO; + PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; + + PortDeviceExtension = PortDeviceObject->DeviceExtension; + + /* Copy pseudo device extension into the real device extension */ + memcpy(PortDeviceExtension, + PseudoDeviceExtension, + PseudoDeviceExtension->Length); + + /* Copy access ranges */ + AccessRangeSize = + sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges; + PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool, + AccessRangeSize); + memcpy(PortDeviceExtension->PortConfig.AccessRanges, + PseudoDeviceExtension->PortConfig.AccessRanges, + AccessRangeSize); + + PortDeviceExtension->DeviceObject = PortDeviceObject; + PortDeviceExtension->PortNumber = PortNumber; + + /* Initialize the spin lock in the controller extension */ + KeInitializeSpinLock(&PortDeviceExtension->IrpLock); + KeInitializeSpinLock(&PortDeviceExtension->SpinLock); + + /* Register an interrupt handler for this device */ + Status = IoConnectInterrupt(&PortDeviceExtension->Interrupt, + ScsiPortIsr, + PortDeviceExtension, + &PortDeviceExtension->SpinLock, + PortDeviceExtension->PortConfig.BusInterruptVector, // MappedIrq, + PortDeviceExtension->PortConfig.BusInterruptLevel, // Dirql, + 15, //Dirql, + PortDeviceExtension->PortConfig.InterruptMode, + FALSE, + 0xFFFF, //Affinity, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not Connect Interrupt %d\n", + PortDeviceExtension->PortConfig.BusInterruptVector); + return(Status); + } + + /* Initialize the DPC object */ + IoInitializeDpcRequest(PortDeviceExtension->DeviceObject, + ScsiPortDpcForIsr); + + /* Initialize the device timer */ + PortDeviceExtension->TimerState = IDETimerIdle; + PortDeviceExtension->TimerCount = 0; + IoInitializeTimer(PortDeviceExtension->DeviceObject, + ScsiPortIoTimer, + PortDeviceExtension); + + /* Initialize port capabilities */ + PortCapabilities = ExAllocatePool(NonPagedPool, + sizeof(IO_SCSI_CAPABILITIES)); + PortDeviceExtension->PortCapabilities = PortCapabilities; + PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES); + PortCapabilities->MaximumTransferLength = + PortDeviceExtension->PortConfig.MaximumTransferLength; + PortCapabilities->MaximumPhysicalPages = + PortCapabilities->MaximumTransferLength / PAGE_SIZE; + PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */ + PortCapabilities->AlignmentMask = + PortDeviceExtension->PortConfig.AlignmentMask; + PortCapabilities->TaggedQueuing = + PortDeviceExtension->PortConfig.TaggedQueuing; + PortCapabilities->AdapterScansDown = + PortDeviceExtension->PortConfig.AdapterScansDown; + PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */ + + /* Initialize inquiry data */ + PortDeviceExtension->PortBusInfoSize = 0; + PortDeviceExtension->PortBusInfo = NULL; + + DPRINT("DeviceExtension %p\n", PortDeviceExtension); + ScsiPortInquire(PortDeviceExtension); + + + /* FIXME: Copy more configuration data? */ + + /* Create the dos device link */ + swprintf(DosNameBuffer, + L"\\??\\Scsi%lu:", + PortNumber); + RtlInitUnicodeString(&DosDeviceName, + DosNameBuffer); + + IoCreateSymbolicLink(&DosDeviceName, + &DeviceName); + + DPRINT("ScsiPortCreatePortDevice() done\n"); + + return(STATUS_SUCCESS); +} + + +static VOID +ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension) +{ + PSCSI_ADAPTER_BUS_INFO AdapterInfo; + PSCSI_INQUIRY_DATA UnitInfo, PrevUnit; + SCSI_REQUEST_BLOCK Srb; + ULONG Bus; + ULONG Target; + ULONG UnitCount; + ULONG DataSize; + BOOLEAN Result; + + DPRINT("ScsiPortInquire() called\n"); + + DeviceExtension->Initializing = TRUE; + + /* Copy inquiry data to the port device extension */ + AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)ExAllocatePool(NonPagedPool, 4096); + RtlZeroMemory(AdapterInfo, 4096); + AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses; + + UnitInfo = (PSCSI_INQUIRY_DATA) + ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) + + (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1))); + + RtlZeroMemory(&Srb, + sizeof(SCSI_REQUEST_BLOCK)); + Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256); + Srb.Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb.DataTransferLength = 256; + Srb.Cdb[0] = SCSIOP_INQUIRY; + + for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++) + { + Srb.PathId = Bus; + + AdapterInfo->BusData[Bus].InitiatorBusId = 0; /* ? */ + AdapterInfo->BusData[Bus].InquiryDataOffset = + (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo); + + PrevUnit = NULL; + UnitCount = 0; + + for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++) + { + Srb.TargetId = Target; + Srb.Lun = 0; + Srb.SrbStatus = SRB_STATUS_SUCCESS; + + Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, + &Srb); + DPRINT("Result: %s Srb.SrbStatus %lx\n", (Result)?"True":"False", Srb.SrbStatus); + + if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS) + { + UnitInfo->PathId = Bus; + UnitInfo->TargetId = Target; + UnitInfo->Lun = 0; + UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE; + memcpy(&UnitInfo->InquiryData, + Srb.DataBuffer, + INQUIRYDATABUFFERSIZE); + if (PrevUnit != NULL) + PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); + PrevUnit = UnitInfo; + UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1); + UnitCount++; + } + } + DPRINT("UnitCount: %lu\n", UnitCount); + AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount; + if (UnitCount == 0) + AdapterInfo->BusData[Bus].InquiryDataOffset = 0; + } + DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo); + + ExFreePool(Srb.DataBuffer); + + DeviceExtension->Initializing = FALSE; + + /* copy inquiry data to the port driver's device extension */ + DeviceExtension->PortBusInfoSize = DataSize; + DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool, + DataSize); + RtlCopyMemory(DeviceExtension->PortBusInfo, + AdapterInfo, + DataSize); + + ExFreePool(AdapterInfo); + + DPRINT("ScsiPortInquire() done\n"); +} + + +static BOOLEAN STDCALL +ScsiPortIsr(IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + BOOLEAN Result; + + DPRINT("ScsiPortIsr() called!\n"); + + DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext; + + Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension); + if (Result == FALSE) + { + return(FALSE); + } + + if (DeviceExtension->IrpFlags) + { + IoRequestDpc(DeviceExtension->DeviceObject, + DeviceExtension->CurrentIrp, + DeviceExtension); + } + + return(TRUE); +} + + +// ScsiPortDpcForIsr +// DESCRIPTION: +// +// RUN LEVEL: +// +// ARGUMENTS: +// IN PKDPC Dpc +// IN PDEVICE_OBJECT DpcDeviceObject +// IN PIRP DpcIrp +// IN PVOID DpcContext +// +static VOID STDCALL +ScsiPortDpcForIsr(IN PKDPC Dpc, + IN PDEVICE_OBJECT DpcDeviceObject, + IN PIRP DpcIrp, + IN PVOID DpcContext) +{ + PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpStack; + PSCSI_REQUEST_BLOCK Srb; + KIRQL oldIrql; + + DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n", + Dpc, DpcDeviceObject, DpcIrp, DpcContext); + + DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext; + + KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql); + if (DeviceExtension->IrpFlags) + { + IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp); + Srb = IrpStack->Parameters.Scsi.Srb; + + if (DeviceExtension->OriginalSrb != NULL) + { + DPRINT("Got sense data!\n"); + + DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid); + DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode); + DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey); + DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode); + + /* Copy sense data */ + if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0) + { + RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer, + &DeviceExtension->InternalSenseData, + sizeof(SENSE_DATA)); + DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; + } + + /* Clear current sense data */ + RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA)); + + IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb; + DeviceExtension->OriginalSrb = NULL; + } + else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) && + (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION)) + { + DPRINT("SCSIOP_REQUEST_SENSE required!\n"); + + DeviceExtension->OriginalSrb = Srb; + IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension, + Srb); + KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); + if (!KeSynchronizeExecution(DeviceExtension->Interrupt, + ScsiPortStartPacket, + DeviceExtension)) + { + DPRINT("Synchronization failed!\n"); + + DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; + DpcIrp->IoStatus.Information = 0; + IoCompleteRequest(DpcIrp, + IO_NO_INCREMENT); + IoStartNextPacket(DpcDeviceObject, + FALSE); + } + + return; + } + + DeviceExtension->CurrentIrp = NULL; + + +// DpcIrp->IoStatus.Information = 0; +// DpcIrp->IoStatus.Status = STATUS_SUCCESS; + + if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE) + { + DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE; + IoCompleteRequest(DpcIrp, IO_NO_INCREMENT); + } + + if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT) + { + DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT; + KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); + IoStartNextPacket(DpcDeviceObject, FALSE); + } + else + { + KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); + } + } + else + { + KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql); + } + DPRINT("ScsiPortDpcForIsr() done\n"); +} + + +// ScsiPortIoTimer +// DESCRIPTION: +// This function handles timeouts and other time delayed processing +// +// RUN LEVEL: +// +// ARGUMENTS: +// IN PDEVICE_OBJECT DeviceObject Device object registered with timer +// IN PVOID Context the Controller extension for the +// controller the device is on +// +static VOID STDCALL +ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject, + PVOID Context) +{ + DPRINT1("ScsiPortIoTimer()\n"); +} + + +static PSCSI_REQUEST_BLOCK +ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK OriginalSrb) +{ + PSCSI_REQUEST_BLOCK Srb; + PCDB Cdb; + + Srb = &DeviceExtension->InternalSrb; + + RtlZeroMemory(Srb, + sizeof(SCSI_REQUEST_BLOCK)); + + Srb->PathId = OriginalSrb->PathId; + Srb->TargetId = OriginalSrb->TargetId; + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb->Length = sizeof(SCSI_REQUEST_BLOCK); + Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + + Srb->TimeOutValue = 4; + + Srb->CdbLength = 6; + Srb->DataBuffer = &DeviceExtension->InternalSenseData; + Srb->DataTransferLength = sizeof(SENSE_DATA); + + Cdb = (PCDB)Srb->Cdb; + Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE; + Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA); + + return(Srb); +} + + +static VOID +ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension) +{ + DeviceExtension->OriginalSrb = NULL; +} + + +#if 0 +static NTSTATUS +ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + WCHAR NameBuffer[32]; + ULONG Disposition; + HANDLE ScsiKey; + HANDLE ScsiPortKey; + HANDLE ScsiBusKey; + HANDLE ScsiTargetKey; + HANDLE ScsiUnitKey; + ULONG BusNumber; + NTSTATUS Status; + + /* Open or create the 'Scsi' subkey */ + RtlInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_OPENIF, + 0, + NULL); + Status = NtCreateKey(&ScsiKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Create new 'Scsi Port X' subkey */ + swprintf(NameBuffer, + L"Scsi Port %lu", + DeviceExtension->PortNumber); + RtlInitUnicodeString(&KeyName, + NameBuffer); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + 0, + ScsiKey, + NULL); + Status = NtCreateKey(&ScsiPortKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + if (!NT_SUCCESS(Status)) + { + NtClose(ScsiKey); + return(Status); + } + + /* Add port-specific values */ + + /* 'DMA Enabled' (REG_DWORD) */ + DPRINT1("DMA Enabled = %s\n", + (DeviceExtension->PortCapabilities->AdapterUsesPio)?"TRUE":"FALSE"); + + /* 'Driver' (REG_SZ) */ + + /* 'Interrupt' (REG_DWORD) (NT4 only) */ + DPRINT1("Interrupt = %lx\n", DeviceExtension->PortConfig.BusInterruptLevel); + + /* 'IOAddress' (REG_DWORD) (NT4 only) */ + DPRINT1("IOAddress = %lx\n", + ScsiPortConvertPhysicalAddressToUlong(DeviceExtension->PortConfig.AccessRanges[0].RangeStart)); + + + /* Create 'Scsi Bus X' keys */ + for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig.NumberOfBuses; BusNumber++) + { + swprintf(NameBuffer, + L"Scsi Bus %lu", + DeviceExtension->PortNumber); + RtlInitUnicodeString(&KeyName, + NameBuffer); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + 0, + ScsiPortKey, + NULL); + Status = NtCreateKey(&ScsiBusKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + if (!NT_SUCCESS(Status)) + { + NtClose(ScsiPortKey); + NtClose(ScsiKey); + return(Status); + } + + /* Create target keys */ + + + NtClose(ScsiBusKey); + } + + NtClose(ScsiPortKey); + NtClose(ScsiKey); + + return(Status); +} +#endif + +/* EOF */ diff --git a/drivers/storage/scsiport/scsiport.def b/drivers/storage/scsiport/scsiport.def new file mode 100644 index 0000000..0fe05c6 --- /dev/null +++ b/drivers/storage/scsiport/scsiport.def @@ -0,0 +1,52 @@ +; $Id$ +; +; scsiport.def - export definition file for scsiport driver +; +LIBRARY SCSIPORT.SYS +EXPORTS +ScsiDebugPrint +ScsiPortCompleteRequest@20 +ScsiPortConvertPhysicalAddressToUlong@8 +ScsiPortConvertUlongToPhysicalAddress@4 +ScsiPortFlushDma@4 +ScsiPortFreeDeviceBase@8 +ScsiPortGetBusData@24 +ScsiPortGetDeviceBase@28 +ScsiPortGetLogicalUnit@16 +ScsiPortGetPhysicalAddress@16 +ScsiPortGetSrb@20 +ScsiPortGetUncachedExtension@12 +ScsiPortGetVirtualAddress@12 +ScsiPortInitialize@16 +ScsiPortIoMapTransfer@16 +ScsiPortLogError@28 +ScsiPortMoveMemory@12 +ScsiPortNotification +ScsiPortReadPortBufferUchar@12 +ScsiPortReadPortBufferUshort@12 +ScsiPortReadPortBufferUlong@12 +ScsiPortReadPortUchar@4 +ScsiPortReadPortUshort@4 +ScsiPortReadPortUlong@4 +ScsiPortReadRegisterBufferUchar@12 +ScsiPortReadRegisterBufferUshort@12 +ScsiPortReadRegisterBufferUlong@12 +ScsiPortReadRegisterUchar@4 +ScsiPortReadRegisterUshort@4 +ScsiPortReadRegisterUlong@4 +ScsiPortSetBusDataByOffset@28 +ScsiPortStallExecution@4 +ScsiPortValidateRange@28 +ScsiPortWritePortBufferUchar@12 +ScsiPortWritePortBufferUshort@12 +ScsiPortWritePortBufferUlong@12 +ScsiPortWritePortUchar@8 +ScsiPortWritePortUshort@8 +ScsiPortWritePortUlong@8 +ScsiPortWriteRegisterBufferUchar@12 +ScsiPortWriteRegisterBufferUshort@12 +ScsiPortWriteRegisterBufferUlong@12 +ScsiPortWriteRegisterUchar@8 +ScsiPortWriteRegisterUshort@8 +ScsiPortWriteRegisterUlong@8 +;EOF diff --git a/drivers/storage/scsiport/scsiport.edf b/drivers/storage/scsiport/scsiport.edf new file mode 100644 index 0000000..746e7f9 --- /dev/null +++ b/drivers/storage/scsiport/scsiport.edf @@ -0,0 +1,52 @@ +; $Id$ +; +; scsiport.def - export definition file for scsiport driver +; +LIBRARY SCSIPORT.SYS +EXPORTS +ScsiDebugPrint +ScsiPortCompleteRequest=ScsiPortCompleteRequest@20 +ScsiPortConvertPhysicalAddressToUlong=ScsiPortConvertPhysicalAddressToUlong@8 +ScsiPortConvertUlongToPhysicalAddress=NTOSKRNL.RtlConvertUlongToLargeInteger +ScsiPortFlushDma=ScsiPortFlushDma@4 +ScsiPortFreeDeviceBase=ScsiPortFreeDeviceBase@8 +ScsiPortGetBusData=ScsiPortGetBusData@24 +ScsiPortGetDeviceBase=ScsiPortGetDeviceBase@28 +ScsiPortGetLogicalUnit=ScsiPortGetLogicalUnit@16 +ScsiPortGetPhysicalAddress=ScsiPortGetPhysicalAddress@16 +ScsiPortGetSrb=ScsiPortGetSrb@20 +ScsiPortGetUncachedExtension=ScsiPortGetUncachedExtension@12 +ScsiPortGetVirtualAddress=ScsiPortGetVirtualAddress@12 +ScsiPortInitialize=ScsiPortInitialize@16 +ScsiPortIoMapTransfer=ScsiPortIoMapTransfer@16 +ScsiPortLogError=ScsiPortLogError@28 +ScsiPortMoveMemory=ScsiPortMoveMemory@12 +ScsiPortNotification +ScsiPortReadPortBufferUchar=HAL.READ_PORT_BUFFER_UCHAR +ScsiPortReadPortBufferUshort=HAL.READ_PORT_BUFFER_USHORT +ScsiPortReadPortBufferUlong=HAL.READ_PORT_BUFFER_ULONG +ScsiPortReadPortUchar=HAL.READ_PORT_UCHAR +ScsiPortReadPortUshort=HAL.READ_PORT_USHORT +ScsiPortReadPortUlong=HAL.READ_PORT_ULONG +ScsiPortReadRegisterBufferUchar=NTOSKRNL.READ_REGISTER_BUFFER_UCHAR +ScsiPortReadRegisterBufferUshort=NTOSKRNL.READ_REGISTER_BUFFER_USHORT +ScsiPortReadRegisterBufferUlong=NTOSKRNL.READ_REGISTER_BUFFER_ULONG +ScsiPortReadRegisterUchar=NTOSKRNL.READ_REGISTER_UCHAR +ScsiPortReadRegisterUshort=NTOSKRNL.READ_REGISTER_USHORT +ScsiPortReadRegisterUlong=NTOSKRNL.READ_REGISTER_ULONG +ScsiPortSetBusDataByOffset=ScsiPortSetBusDataByOffset@28 +ScsiPortStallExecution=HAL.KeStallExecutionProcessor +ScsiPortValidateRange=ScsiPortValidateRange@28 +ScsiPortWritePortUchar=HAL.WRITE_PORT_UCHAR +ScsiPortWritePortUshort=HAL.WRITE_PORT_USHORT +ScsiPortWritePortUlong=HAL.WRITE_PORT_ULONG +ScsiPortWritePortBufferUchar=HAL.WRITE_PORT_BUFFER_UCHAR +ScsiPortWritePortBufferUshort=HAL.WRITE_PORT_BUFFER_USHORT +ScsiPortWritePortBufferUlong=HAL.WRITE_PORT_BUFFER_ULONG +ScsiPortWriteRegisterBufferUchar=NTOSKRNL.WRITE_REGISTER_BUFFER_UCHAR +ScsiPortWriteRegisterBufferUshort=NTOSKRNL.WRITE_REGISTER_BUFFER_USHORT +ScsiPortWriteRegisterBufferUlong=NTOSKRNL.WRITE_REGISTER_BUFFER_ULONG +ScsiPortWriteRegisterUchar=NTOSKRNL.WRITE_REGISTER_UCHAR +ScsiPortWriteRegisterUshort=NTOSKRNL.WRITE_REGISTER_USHORT +ScsiPortWriteRegisterUlong=NTOSKRNL.WRITE_REGISTER_ULONG +;EOF diff --git a/drivers/storage/scsiport/scsiport.rc b/drivers/storage/scsiport/scsiport.rc new file mode 100644 index 0000000..8450f6f --- /dev/null +++ b/drivers/storage/scsiport/scsiport.rc @@ -0,0 +1,38 @@ + +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "SCSI Port Driver\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "scsiport\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "scsiport.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/gdb.ini b/gdb.ini new file mode 100644 index 0000000..8a322d4 --- /dev/null +++ b/gdb.ini @@ -0,0 +1,4 @@ +directory /mnt/windows/CvsHome/reactos/ntoskrnl +symbol-file ntoskrnl/ntoskrnl.nostrip.exe -mapped +set remotebaud 115200 +target remote com2 diff --git a/hal/hal/.cvsignore b/hal/hal/.cvsignore new file mode 100644 index 0000000..a04f6d3 --- /dev/null +++ b/hal/hal/.cvsignore @@ -0,0 +1,7 @@ +*.d +halx86up.coff +hal.dll +hal.nostrip.dll +*.a +*.o +*.sym diff --git a/hal/hal/Makefile b/hal/hal/Makefile new file mode 100644 index 0000000..c6a9cdc --- /dev/null +++ b/hal/hal/Makefile @@ -0,0 +1,23 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = driver_library + +TARGET_ASFLAGS = -D__NTHAL__ -I$(PATH_TO_TOP)/ntoskrnl/include + +TARGET_CFLAGS = -D__NTHAL__ -I$(PATH_TO_TOP)/ntoskrnl/include + +TARGET_NAME = hal + +HEADER_FILES = $(PATH_TO_TOP)/include/roscfg.h + +TARGET_OBJECTS := $(TARGET_NAME).o $(HEADER_FILES) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/config.mk + +# EOF diff --git a/hal/hal/hal.c b/hal/hal/hal.c new file mode 100644 index 0000000..ae97f08 --- /dev/null +++ b/hal/hal/hal.c @@ -0,0 +1,975 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/hal.c + * PURPOSE: Hardware Abstraction Layer DLL + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 01-08-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* DATA **********************************************************************/ + +ULONG EXPORTED KdComPortInUse = 0; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + UNIMPLEMENTED; + + return STATUS_SUCCESS; +} + + +VOID +FASTCALL +ExAcquireFastMutex( + PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; +} + + +VOID +FASTCALL +ExReleaseFastMutex( + PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; +} + + +BOOLEAN FASTCALL +ExTryToAcquireFastMutex( + PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalAcquireDisplayOwnership( + PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +HalAdjustResourceList( + PCM_RESOURCE_LIST Resources) +{ + UNIMPLEMENTED; + + return STATUS_SUCCESS; +} + + +BOOLEAN +STDCALL +HalAllProcessorsStarted(VOID) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +NTSTATUS +STDCALL +HalAllocateAdapterChannel( + PADAPTER_OBJECT AdapterObject, + PDEVICE_OBJECT DeviceObject, + ULONG NumberOfMapRegisters, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context) +{ + UNIMPLEMENTED; + + return STATUS_SUCCESS; +} + + +PVOID +STDCALL +HalAllocateCommonBuffer( + PADAPTER_OBJECT AdapterObject, + ULONG Length, + PPHYSICAL_ADDRESS LogicalAddress, + BOOLEAN CacheEnabled) +{ + UNIMPLEMENTED; + + return NULL; +} + + +NTSTATUS +STDCALL +HalAssignSlotResources( + PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + INTERFACE_TYPE BusType, + ULONG BusNumber, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +HalBeginSystemInterrupt( + ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalCalibratePerformanceCounter( + ULONG Count) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalDisableSystemInterrupt( + ULONG Vector, + ULONG Unknown2) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalDisplayString( + PCH String) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalEnableSystemInterrupt( + ULONG Vector, + ULONG Unknown2, + ULONG Unknown3) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalEndSystemInterrupt( + KIRQL Irql, + ULONG Unknown2) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalFlushCommonBuffer( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6, + ULONG Unknown7, + ULONG Unknown8) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalFreeCommonBuffer( + PADAPTER_OBJECT AdapterObject, + ULONG Length, + PHYSICAL_ADDRESS LogicalAddress, + PVOID VirtualAddress, + BOOLEAN CacheEnabled) +{ + UNIMPLEMENTED; +} + + +PADAPTER_OBJECT +STDCALL +HalGetAdapter( + PDEVICE_DESCRIPTION DeviceDescription, + PULONG NumberOfMapRegisters) +{ + UNIMPLEMENTED; + + return (PADAPTER_OBJECT)NULL; +} + + +ULONG +STDCALL +HalGetBusData( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +ULONG +STDCALL +HalGetBusDataByOffset( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +BOOLEAN +STDCALL +HalGetEnvironmentVariable( + PCH Name, + PCH Value, + USHORT ValueLength) +{ + UNIMPLEMENTED; + + return FALSE; +} + + +ULONG +STDCALL +HalGetInterruptVector( + INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + UNIMPLEMENTED; + + return 0; +} + + +VOID +STDCALL +HalHandleNMI( + ULONG Unused) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalInitSystem( + ULONG BootPhase, + PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalInitializeProcessor( + ULONG ProcessorNumber, + PVOID ProcessorStack) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalMakeBeep( + ULONG Frequency) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalProcessorIdle(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalQueryDisplayParameters( + PULONG DispSizeX, + PULONG DispSizeY, + PULONG CursorPosX, + PULONG CursorPosY) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalQueryRealTimeClock( + PTIME_FIELDS Time) +{ + UNIMPLEMENTED; +} + + +ULONG +STDCALL +HalReadDmaCounter( + PADAPTER_OBJECT AdapterObject) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalReportResourceUsage(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalRequestIpi( + ULONG Unknown) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalReturnToFirmware( + ULONG Action) +{ + UNIMPLEMENTED; +} + + +ULONG +STDCALL +HalSetBusData( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +ULONG +STDCALL +HalSetBusDataByOffset( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +VOID +STDCALL +HalSetDisplayParameters( + ULONG CursorPosX, + ULONG CursorPosY) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalSetEnvironmentVariable( + PCH Name, + PCH Value) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalSetRealTimeClock( + PTIME_FIELDS Time) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalStartNextProcessor( + ULONG Unknown1, + ULONG Unknown2) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +ULONG +FASTCALL +HalSystemVectorDispatchEntry( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +{ + UNIMPLEMENTED; + + return 0; +} + + +BOOLEAN +STDCALL +HalTranslateBusAddress( + INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +IoAssignDriveLetters( + PLOADER_PARAMETER_BLOCK LoaderBlock, + PSTRING NtDeviceName, + PUCHAR NtSystemPath, + PSTRING NtSystemPathString) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +IoFlushAdapterBuffers( + PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + ULONG Length, + BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +IoFreeAdapterChannel( + PADAPTER_OBJECT AdapterObject) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +IoFreeMapRegisters( + PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters) +{ + UNIMPLEMENTED; +} + + +PHYSICAL_ADDRESS +STDCALL +IoMapTransfer( + PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + PULONG Length, + BOOLEAN WriteToDevice) +{ + PHYSICAL_ADDRESS Address; + + UNIMPLEMENTED; + + Address.QuadPart = 0; + + return Address; +} + + +BOOLEAN +STDCALL +KdPortGetByte( + PUCHAR ByteRecieved) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +KdPortGetByteEx( + PKD_PORT_INFORMATION PortInformation, + PUCHAR ByteRecieved) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +KdPortInitialize( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +KdPortPollByte( + PUCHAR ByteRecieved) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +KdPortPollByteEx( + PKD_PORT_INFORMATION PortInformation, + PUCHAR ByteRecieved) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +KdPortPutByte( + UCHAR ByteToSend) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KdPortPutByteEx( + PKD_PORT_INFORMATION PortInformation, + UCHAR ByteToSend) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KdPortRestore(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KdPortSave(VOID) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +KdPortDisableInterrupts() +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +KdPortEnableInterrupts() +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KeAcquireSpinLock( + PKSPIN_LOCK SpinLock, + PKIRQL OldIrql) +{ + UNIMPLEMENTED; +} + + +KIRQL +FASTCALL +KeAcquireSpinLockRaiseToSynch( + PKSPIN_LOCK SpinLock) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KeFlushWriteBuffer(VOID) +{ + UNIMPLEMENTED; +} + + +KIRQL +STDCALL +KeGetCurrentIrql(VOID) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +STDCALL +KeLowerIrql( + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +LARGE_INTEGER +STDCALL +KeQueryPerformanceCounter( + PLARGE_INTEGER PerformanceFreq) +{ + LARGE_INTEGER Value; + + UNIMPLEMENTED; + + Value.QuadPart = 0; + + return Value; +} + + +VOID +STDCALL +KeRaiseIrql( + KIRQL NewIrql, + PKIRQL OldIrql) +{ + UNIMPLEMENTED; +} + + +KIRQL +STDCALL +KeRaiseIrqlToDpcLevel(VOID) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +KIRQL +STDCALL +KeRaiseIrqlToSynchLevel(VOID) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +STDCALL +KeReleaseSpinLock( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KeStallExecutionProcessor( + ULONG Microseconds) +{ + UNIMPLEMENTED; +} + + +KIRQL +FASTCALL +KfAcquireSpinLock( + PKSPIN_LOCK SpinLock) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +FASTCALL +KfLowerIrql( + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +KIRQL +FASTCALL +KfRaiseIrql( + KIRQL NewIrql) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +FASTCALL +KfReleaseSpinLock( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +READ_PORT_BUFFER_UCHAR( + PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +READ_PORT_BUFFER_ULONG( + PULONG Port, + PULONG Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +READ_PORT_BUFFER_USHORT( + PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +UCHAR +STDCALL +READ_PORT_UCHAR( + PUCHAR Port) +{ + UNIMPLEMENTED; + + return 0; +} + + +ULONG +STDCALL +READ_PORT_ULONG( + PULONG Port) +{ + UNIMPLEMENTED; + + return 0; +} + + +USHORT +STDCALL +READ_PORT_USHORT( + PUSHORT Port) +{ + UNIMPLEMENTED; + + return 0; +} + + +VOID +STDCALL +WRITE_PORT_BUFFER_UCHAR( + PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +WRITE_PORT_BUFFER_USHORT( + PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +WRITE_PORT_BUFFER_ULONG( + PULONG Port, + PULONG Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +WRITE_PORT_UCHAR( + PUCHAR Port, + UCHAR Value) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +WRITE_PORT_ULONG( + PULONG Port, + ULONG Value) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +WRITE_PORT_USHORT( + PUSHORT Port, + USHORT Value) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/hal/hal/hal.def b/hal/hal/hal.def new file mode 100644 index 0000000..f75f867 --- /dev/null +++ b/hal/hal/hal.def @@ -0,0 +1,100 @@ +; Hardware Abstraction Layer - ReactOS Operating System + +LIBRARY hal.dll + +EXPORTS +@ExAcquireFastMutex@4 +@ExReleaseFastMutex@4 +@ExTryToAcquireFastMutex@4 +HalAcquireDisplayOwnership@4 +HalAdjustResourceList@4 +HalAllProcessorsStarted@0 +HalAllocateAdapterChannel@20 +HalAllocateCommonBuffer@16 +;HalAllocateCrashDumpRegisters@8 +HalAssignSlotResources@32 +HalBeginSystemInterrupt@12 +HalCalibratePerformanceCounter@4 +;@HalClearSoftwareInterrupt@4 +;HalClearSoftwareInterrupt@4 +HalDisableSystemInterrupt@8 +HalDisplayString@4 +HalEnableSystemInterrupt@12 +HalEndSystemInterrupt@8 +HalFlushCommonBuffer@32 +HalFreeCommonBuffer@24 +HalGetAdapter@8 +HalGetBusData@20 +HalGetBusDataByOffset@24 +HalGetEnvironmentVariable@12 +HalGetInterruptVector@24 +HalHandleNMI@4 +HalInitSystem@8 +HalInitializeProcessor@8 +HalMakeBeep@4 +HalProcessorIdle@0 +HalQueryDisplayParameters@16 +HalQueryRealTimeClock@4 +HalReadDmaCounter@4 +HalReportResourceUsage@0 +HalRequestIpi@4 +;@HalRequestSoftwareInterrupt@4 +;HalRequestSoftwareInterrupt@4 +HalReturnToFirmware@4 +HalSetBusData@20 +HalSetBusDataByOffset@24 +HalSetDisplayParameters@8 +HalSetEnvironmentVariable@8 +;HalSetProfileInterval@4 +HalSetRealTimeClock@4 +;HalSetTimeIncrement@4 +HalStartNextProcessor@8 +;HalStartProfileInterrupt@4 +;HalStopProfileInterrupt@4 +@HalSystemVectorDispatchEntry@12 +HalTranslateBusAddress@24 +IoAssignDriveLetters@16 +IoFlushAdapterBuffers@24 +IoFreeAdapterChannel@4 +IoFreeMapRegisters@12 +IoMapTransfer@24 +KdComPortInUse DATA +KdPortGetByte@4 +KdPortGetByteEx@8 +KdPortInitialize@12 +KdPortInitializeEx@12 +KdPortPollByte@4 +KdPortPollByteEx@8 +KdPortPutByte@4 +KdPortPutByteEx@8 +KdPortRestore@0 +KdPortSave@0 +KdPortDisableInterrupts@0 +KdPortEnableInterrupts@0 +KeAcquireSpinLock@8 +@KeAcquireSpinLockRaiseToSynch@4 +KeGetCurrentIrql@0 +KeFlushWriteBuffer@0 +KeLowerIrql@4 +KeQueryPerformanceCounter@4 +KeRaiseIrql@8 +KeRaiseIrqlToDpcLevel@0 +KeRaiseIrqlToSynchLevel@0 +KeReleaseSpinLock@8 +KeStallExecutionProcessor@4 +@KfAcquireSpinLock@4 +@KfLowerIrql@4 +@KfRaiseIrql@4 +@KfReleaseSpinLock@8 +READ_PORT_BUFFER_UCHAR@12 +READ_PORT_BUFFER_ULONG@12 +READ_PORT_BUFFER_USHORT@12 +READ_PORT_UCHAR@4 +READ_PORT_ULONG@4 +READ_PORT_USHORT@4 +WRITE_PORT_BUFFER_UCHAR@12 +WRITE_PORT_BUFFER_ULONG@12 +WRITE_PORT_BUFFER_USHORT@12 +WRITE_PORT_UCHAR@8 +WRITE_PORT_ULONG@8 +WRITE_PORT_USHORT@8 diff --git a/hal/hal/hal.edf b/hal/hal/hal.edf new file mode 100644 index 0000000..886888e --- /dev/null +++ b/hal/hal/hal.edf @@ -0,0 +1,100 @@ +; Hardware Abstraction Layer - ReactOS Operating System + +LIBRARY hal.dll + +EXPORTS +ExAcquireFastMutex=@ExAcquireFastMutex@4 +ExReleaseFastMutex=@ExReleaseFastMutex@4 +ExTryToAcquireFastMutex=@ExTryToAcquireFastMutex@4 +HalAcquireDisplayOwnership=HalAcquireDisplayOwnership@4 +HalAdjustResourceList=HalAdjustResourceList@4 +HalAllProcessorsStarted=HalAllProcessorsStarted@0 +HalAllocateAdapterChannel=HalAllocateAdapterChannel@20 +HalAllocateCommonBuffer=HalAllocateCommonBuffer@16 +;HalAllocateCrashDumpRegisters@8 +HalAssignSlotResources=HalAssignSlotResources@32 +HalBeginSystemInterrupt=HalBeginSystemInterrupt@12 +HalCalibratePerformanceCounter=HalCalibratePerformanceCounter@4 +;@HalClearSoftwareInterrupt@4 +;HalClearSoftwareInterrupt@4 +HalDisableSystemInterrupt=HalDisableSystemInterrupt@8 +HalDisplayString=HalDisplayString@4 +HalEnableSystemInterrupt=HalEnableSystemInterrupt@12 +HalEndSystemInterrupt=HalEndSystemInterrupt@8 +HalFlushCommonBuffer=HalFlushCommonBuffer@32 +HalFreeCommonBuffer=HalFreeCommonBuffer@24 +HalGetAdapter=HalGetAdapter@8 +HalGetBusData=HalGetBusData@20 +HalGetBusDataByOffset=HalGetBusDataByOffset@24 +HalGetEnvironmentVariable=HalGetEnvironmentVariable@12 +HalGetInterruptVector=HalGetInterruptVector@24 +HalHandleNMI=HalHandleNMI@4 +HalInitSystem=HalInitSystem@8 +HalInitializeProcessor=HalInitializeProcessor@8 +HalMakeBeep=HalMakeBeep@4 +HalProcessorIdle=HalProcessorIdle@0 +HalQueryDisplayParameters=HalQueryDisplayParameters@16 +HalQueryRealTimeClock=HalQueryRealTimeClock@4 +HalReadDmaCounter=HalReadDmaCounter@4 +HalReportResourceUsage=HalReportResourceUsage@0 +HalRequestIpi=HalRequestIpi@4 +;@HalRequestSoftwareInterrupt@4 +;HalRequestSoftwareInterrupt@4 +HalReturnToFirmware=HalReturnToFirmware@4 +HalSetBusData=HalSetBusData@20 +HalSetBusDataByOffset=HalSetBusDataByOffset@24 +HalSetDisplayParameters=HalSetDisplayParameters@8 +HalSetEnvironmentVariable=HalSetEnvironmentVariable@8 +;HalSetProfileInterval@4 +HalSetRealTimeClock=HalSetRealTimeClock@4 +;HalSetTimeIncrement@4 +HalStartNextProcessor=HalStartNextProcessor@8 +;HalStartProfileInterrupt@4 +;HalStopProfileInterrupt@4 +HalSystemVectorDispatchEntry=@HalSystemVectorDispatchEntry@12 +HalTranslateBusAddress=HalTranslateBusAddress@24 +IoAssignDriveLetters=IoAssignDriveLetters@16 +IoFlushAdapterBuffers=IoFlushAdapterBuffers@24 +IoFreeAdapterChannel=IoFreeAdapterChannel@4 +IoFreeMapRegisters=IoFreeMapRegisters@12 +IoMapTransfer=IoMapTransfer@24 +KdComPortInUse DATA +KdPortGetByte=KdPortGetByte@4 +KdPortGetByteEx=KdPortGetByteEx@8 +KdPortInitialize=KdPortInitialize@12 +KdPortInitializeEx=KdPortInitializeEx@12 +KdPortPollByte=KdPortPollByte@4 +KdPortPollByteEx=KdPortPollByteEx@8 +KdPortPutByte=KdPortPutByte@4 +KdPortPutByteEx=KdPortPutByteEx@8 +KdPortRestore=KdPortRestore@0 +KdPortSave=KdPortSave@0 +KdPortDisableInterrupts=KdPortDisableInterrupts@0 +KdPortEnableInterrupts=KdPortEnableInterrupts@0 +KeAcquireSpinLock=KeAcquireSpinLock@8 +KeAcquireSpinLockRaiseToSynch=@KeAcquireSpinLockRaiseToSynch@4 +KeGetCurrentIrql=KeGetCurrentIrql@0 +KeFlushWriteBuffer=KeFlushWriteBuffer@0 +KeLowerIrql=KeLowerIrql@4 +KeQueryPerformanceCounter=KeQueryPerformanceCounter@4 +KeRaiseIrql=KeRaiseIrql@8 +KeRaiseIrqlToDpcLevel=KeRaiseIrqlToDpcLevel@0 +KeRaiseIrqlToSynchLevel=KeRaiseIrqlToSynchLevel@0 +KeReleaseSpinLock=KeReleaseSpinLock@8 +KeStallExecutionProcessor=KeStallExecutionProcessor@4 +KfAcquireSpinLock=@KfAcquireSpinLock@4 +KfLowerIrql=@KfLowerIrql@4 +KfRaiseIrql=@KfRaiseIrql@4 +KfReleaseSpinLock=@KfReleaseSpinLock@8 +READ_PORT_BUFFER_UCHAR=READ_PORT_BUFFER_UCHAR@12 +READ_PORT_BUFFER_ULONG=READ_PORT_BUFFER_ULONG@12 +READ_PORT_BUFFER_USHORT=READ_PORT_BUFFER_USHORT@12 +READ_PORT_UCHAR=READ_PORT_UCHAR@4 +READ_PORT_ULONG=READ_PORT_ULONG@4 +READ_PORT_USHORT=READ_PORT_USHORT@4 +WRITE_PORT_BUFFER_UCHAR=WRITE_PORT_BUFFER_UCHAR@12 +WRITE_PORT_BUFFER_ULONG=WRITE_PORT_BUFFER_ULONG@12 +WRITE_PORT_BUFFER_USHORT=WRITE_PORT_BUFFER_USHORT@12 +WRITE_PORT_UCHAR=WRITE_PORT_UCHAR@8 +WRITE_PORT_ULONG=WRITE_PORT_ULONG@8 +WRITE_PORT_USHORT=WRITE_PORT_USHORT@8 diff --git a/hal/hal/hal.rc b/hal/hal/hal.rc new file mode 100644 index 0000000..2d3e9ff --- /dev/null +++ b/hal/hal/hal.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Template Hardware Abstraction Layer\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "hal\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "hal.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/hal/halx86/.cvsignore b/hal/halx86/.cvsignore new file mode 100644 index 0000000..ed49e46 --- /dev/null +++ b/hal/halx86/.cvsignore @@ -0,0 +1,7 @@ +*.d +hal.dll +hal.nostrip.dll +halx86up.coff +*.a +*.o +*.sym diff --git a/hal/halx86/Makefile b/hal/halx86/Makefile new file mode 100644 index 0000000..edd134c --- /dev/null +++ b/hal/halx86/Makefile @@ -0,0 +1,100 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +default: all + +# +# Build configuration +# +include $(PATH_TO_TOP)/rules.mak + +# +# Global configuration +# +include $(TOOLS_PATH)/config.mk + +TARGET_TYPE = hal + +TARGET_BASENAME = hal + +TARGET_DEFNAME = ../hal/hal + +TARGET_LIBPATH = . + +TARGET_ASFLAGS = -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include -D__ASM__ + +TARGET_CFLAGS = -I./include -I$(PATH_TO_TOP)/ntoskrnl/include -g + + +TARGET_NAME_UP = halx86up + +TARGET_NAME_MP = halx86mp + +ifeq ($(MP), 1) +TARGET_NAME = $(TARGET_NAME_MP) +else +TARGET_NAME = $(TARGET_NAME_UP) +endif + +HAL_OBJECTS = \ + adapter.o \ + beep.o \ + bios32.o \ + bus.o \ + display.o \ + dma.o \ + drive.o \ + enum.o \ + fmutex.o \ + halinit.o \ + isa.o \ + kdbg.o \ + mbr.o \ + mca.o \ + misc.o \ + mp.o \ + pci.o \ + perfcnt.o \ + portio.o \ + reboot.o \ + spinlock.o \ + sysbus.o \ + sysinfo.o \ + time.o \ + udelay.o + + #pwroff.o + +HAL_UP = \ + $(HAL_OBJECTS) \ + irql.o + +HAL_MP = \ + $(HAL_OBJECTS) \ + mpsirql.o \ + mpsboot.o \ + mps.o + +ifeq ($(MP), 1) +DEP_OBJECTS := $(HAL_MP) +else +DEP_OBJECTS := $(HAL_UP) +endif + +TARGET_OBJECTS := $(DEP_OBJECTS) $(PATH_TO_TOP)/include/roscfg.h + +# Note: Must be = and not := since $(DEP_FILES) is assigned a value below +TARGET_CLEAN = $(DEP_FILES) *.o *.dll + +# +# Helper makefile +# +include $(TOOLS_PATH)/helper.mk + +# +# Include automatic dependancy tracking +# +include $(TOOLS_PATH)/depend.mk + +# EOF diff --git a/hal/halx86/adapter.c b/hal/halx86/adapter.c new file mode 100644 index 0000000..10211f5 --- /dev/null +++ b/hal/halx86/adapter.c @@ -0,0 +1,154 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/x86/adapter.c (from ntoskrnl/io/adapter.c) + * PURPOSE: DMA handling + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +/* NOTE: IoAllocateAdapterChannel in NTOSKRNL.EXE */ + +NTSTATUS STDCALL +HalAllocateAdapterChannel(PADAPTER_OBJECT AdapterObject, + PDEVICE_OBJECT DeviceObject, + ULONG NumberOfMapRegisters, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context ) +{ + KIRQL OldIrql; + PVOID Buffer; + int ret; + LARGE_INTEGER MaxAddress; + + MaxAddress.QuadPart = 0x1000000; + Buffer = MmAllocateContiguousAlignedMemory( NumberOfMapRegisters * PAGE_SIZE, + MaxAddress, + 0x10000 ); + if( !Buffer ) + return STATUS_INSUFFICIENT_RESOURCES; + KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql ); + if( AdapterObject->Inuse ) + { + // someone is already using it, we need to wait + // create a wait block, and add it to the chain + UNIMPLEMENTED; + } + else { + AdapterObject->Inuse = TRUE; + KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql ); + ret = ExecutionRoutine( DeviceObject, + NULL, + Buffer, + Context ); + KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql ); + if( ret == DeallocateObject ) + { + MmFreeContiguousMemory( Buffer ); + AdapterObject->Inuse = FALSE; + } + else AdapterObject->Buffer = Buffer; + } + KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql ); + return STATUS_SUCCESS; +} + + +BOOLEAN STDCALL +IoFlushAdapterBuffers (PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + ULONG Length, + BOOLEAN WriteToDevice) +{ + // if this was a read from device, copy data back to caller buffer, otherwise, do nothing + if( !WriteToDevice ) + memcpy( (PVOID)((DWORD)MmGetSystemAddressForMdl( Mdl ) + (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl )), MapRegisterBase, Length ); + return TRUE; +} + + +VOID STDCALL +IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject) +{ + KIRQL OldIrql; + + KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql ); + if( AdapterObject->Inuse == FALSE ) + { + DbgPrint( "Attempting to IoFreeAdapterChannel on a channel not in use\n" ); + KeBugCheck(0); + } + AdapterObject->Inuse = FALSE; + if( AdapterObject->Buffer ) + { + MmFreeContiguousMemory( AdapterObject->Buffer ); + AdapterObject->Buffer = 0; + } + KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql ); +} + + +VOID STDCALL +IoFreeMapRegisters (PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters) +{ + UNIMPLEMENTED; +} + + +PHYSICAL_ADDRESS STDCALL +IoMapTransfer (PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + PULONG Length, + BOOLEAN WriteToDevice) +{ + PHYSICAL_ADDRESS Address; + // program up the dma controller, and return + // if it is a write to the device, copy the caller buffer to the low buffer + if( WriteToDevice ) + memcpy( MapRegisterBase, + MmGetSystemAddressForMdl( Mdl ) + ( (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl ) ), + *Length ); + Address = MmGetPhysicalAddress( MapRegisterBase ); + // port 0xA is the dma mask register, or a 0x10 on to the channel number to mask it + WRITE_PORT_UCHAR( (PVOID)0x0A, AdapterObject->Channel | 0x10 ); + // write zero to the reset register + WRITE_PORT_UCHAR( (PVOID)0x0C, 0 ); + // mode register, or channel with 0x4 for write memory, 0x8 for read memory, 0x10 for non auto initialize + WRITE_PORT_UCHAR( (PVOID)0x0B, AdapterObject->Channel | ( WriteToDevice ? 0x8 : 0x4 ) ); + // set the 64k page register for the channel + WRITE_PORT_UCHAR( AdapterObject->PagePort, (UCHAR)(((ULONG)Address.QuadPart)>>16) ); + // low, then high address byte, which is always 0 for us, because we have a 64k alligned address + WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 ); + WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 ); + // count is 1 less than length, low then high + WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)(*Length - 1) ); + WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)((*Length - 1)>>8) ); + // unmask the channel to let it rip + WRITE_PORT_UCHAR( (PVOID)0x0A, AdapterObject->Channel ); + Address.QuadPart = (DWORD)MapRegisterBase; + return Address; +} + + +/* EOF */ + + + + diff --git a/hal/halx86/beep.c b/hal/halx86/beep.c new file mode 100644 index 0000000..a0d8bfc --- /dev/null +++ b/hal/halx86/beep.c @@ -0,0 +1,77 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/beep.c + * PURPOSE: Speaker function (it's only one) + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 31/01/99 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +/* CONSTANTS *****************************************************************/ + +#define TIMER2 0x42 +#define TIMER3 0x43 +#define PORT_B 0x61 +#define CLOCKFREQ 1193167 + + +/* FUNCTIONS *****************************************************************/ +/* + * FUNCTION: Beeps the speaker. + * ARGUMENTS: + * Frequency = If 0, the speaker will be switched off, otherwise + * the speaker beeps with the specified frequency. + */ + +BOOLEAN +STDCALL +HalMakeBeep ( + ULONG Frequency + ) +{ + UCHAR b; + + /* save flags and disable interrupts */ + __asm__("pushf\n\t" \ + "cli\n\t"); + + /* speaker off */ + b = READ_PORT_UCHAR((PUCHAR)PORT_B); + WRITE_PORT_UCHAR((PUCHAR)PORT_B, b & 0xFC); + + if (Frequency) + { + DWORD Divider = CLOCKFREQ / Frequency; + + if (Divider > 0x10000) + { + /* restore flags */ + __asm__("popf\n\t"); + + return FALSE; + } + + /* set timer divider */ + WRITE_PORT_UCHAR((PUCHAR)TIMER3, 0xB6); + WRITE_PORT_UCHAR((PUCHAR)TIMER2, (UCHAR)(Divider & 0xFF)); + WRITE_PORT_UCHAR((PUCHAR)TIMER2, (UCHAR)((Divider>>8) & 0xFF)); + + /* speaker on */ + WRITE_PORT_UCHAR((PUCHAR)PORT_B, READ_PORT_UCHAR((PUCHAR)PORT_B) | 0x03); + } + + /* restore flags */ + __asm__("popf\n\t"); + + return TRUE; +} + diff --git a/hal/halx86/bios32.c b/hal/halx86/bios32.c new file mode 100644 index 0000000..4668367 --- /dev/null +++ b/hal/halx86/bios32.c @@ -0,0 +1,144 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/pci + * PURPOSE: Interfaces to BIOS32 interface + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 05/06/98: Created + */ + +/* + * NOTES: Sections copied from the Linux pci support + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include + + +/* TYPES ******************************************************************/ + +typedef struct +{ + /* + * "_32_" if present + */ + unsigned int signature; + + /* + * Entry point (physical address) + */ + unsigned long int entry; + + /* + * Revision level + */ + unsigned char revision; + + /* + * Length in paragraphs + */ + unsigned char length; + + /* + * Checksum (so all bytes add up to zero) + */ + unsigned char checksum; + + unsigned char reserved[5]; +} bios32; + +BOOLEAN bios32_detected = FALSE; + +static struct +{ + unsigned long address; + unsigned short segment; +} bios32_indirect = {0,KERNEL_CS}; + +/* FUNCTIONS **************************************************************/ + +#define BIOS32_SIGNATURE (('_' << 0)+('3'<<8)+('2'<<16)+('_'<<24)) + +#if 0 +BOOL static checksum(bios32* service_entry) +/* + * FUNCTION: Checks the checksum of a bios32 service entry + * ARGUMENTS: + * service_entry = Pointer to the service entry + * RETURNS: True if the sum of the bytes in the entry was zero + * False otherwise + */ +{ + unsigned char* p = (unsigned char *)service_entry; + int i; + unsigned char sum=0; + + for (i=0; i<(service_entry->length*16); i++) + { + sum=sum+p[i]; + } +// DbgPrint("sum = %d\n",sum); + if (sum==0) + { + return(TRUE); + } + return(FALSE); +} +#endif + +BOOLEAN Hal_bios32_is_service_present(ULONG service) +{ + unsigned char return_code; + unsigned int address; + unsigned int length; + unsigned int entry; + + __asm__("lcall *(%%edi)" + : "=a" (return_code), + "=b" (address), + "=c" (length), + "=d" (entry) + : "0" (service), + "1" (0), + "D" (&bios32_indirect)); + if (return_code==0) + { + return(address+entry); + } + return(0); +} + +VOID Hal_bios32_probe() +/* + * FUNCTION: Probes for an BIOS32 extension + * RETURNS: True if detected + */ +{ + DbgPrint ("Hal_bios32_probe()\n"); + + return; +#if 0 + int i; + + for (i=0xe0000;i<=0xffff0;i++) + { + bios32* service_entry = (bios32 *)physical_to_linear(i); + if ( service_entry->signature != BIOS32_SIGNATURE ) + { + continue; + } + DbgPrint("Signature detected at %x\n",i); + if (!checksum(service_entry)) + { + continue; + } + DbgPrint("ReactOS: BIOS32 detected at %x\n",i); + bios32_indirect.address = service_entry->entry; + bios32_detected=TRUE; + } +#endif +} diff --git a/hal/halx86/bus.c b/hal/halx86/bus.c new file mode 100644 index 0000000..da974ef --- /dev/null +++ b/hal/halx86/bus.c @@ -0,0 +1,525 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/bus.c + * PURPOSE: Bus functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + * + * + * TODO: + * - Add bus handler functions for all busses + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_BUS TAG('B', 'U', 'S', 'H') + +KSPIN_LOCK HalpBusHandlerSpinLock = {0,}; +LIST_ENTRY HalpBusHandlerList; + + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS STDCALL +HalpNoAdjustResourceList(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PCM_RESOURCE_LIST Resources) +{ + return STATUS_UNSUCCESSFUL; +} + +static NTSTATUS STDCALL +HalpNoAssignSlotResources(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources) +{ + return STATUS_NOT_SUPPORTED; +} + +static ULONG STDCALL +HalpNoBusData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + return 0; +} + +static ULONG STDCALL +HalpNoGetInterruptVector(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + return 0; +} + +static ULONG STDCALL +HalpNoTranslateBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + return 0; +} + + +PBUS_HANDLER +HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType, + BUS_DATA_TYPE BusDataType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler = NULL; + + DPRINT("HalpAllocateBusHandler()\n"); + + BusHandler = ExAllocatePoolWithTag(NonPagedPool, + sizeof(BUS_HANDLER), + TAG_BUS); + if (BusHandler == NULL) + return NULL; + + RtlZeroMemory(BusHandler, + sizeof(BUS_HANDLER)); + + InsertTailList(&HalpBusHandlerList, + &BusHandler->Entry); + + BusHandler->InterfaceType = InterfaceType; + BusHandler->BusDataType = BusDataType; + BusHandler->BusNumber = BusNumber; + + /* initialize default bus handler functions */ + BusHandler->GetBusData = HalpNoBusData; + BusHandler->SetBusData = HalpNoBusData; + BusHandler->AdjustResourceList = HalpNoAdjustResourceList; + BusHandler->AssignSlotResources = HalpNoAssignSlotResources; + BusHandler->GetInterruptVector = HalpNoGetInterruptVector; + BusHandler->TranslateBusAddress = HalpNoTranslateBusAddress; + + /* any more ?? */ + + DPRINT("HalpAllocateBusHandler() done\n"); + + return BusHandler; +} + + +VOID +HalpInitBusHandlers(VOID) +{ + PBUS_HANDLER BusHandler; + + /* general preparations */ + KeInitializeSpinLock(&HalpBusHandlerSpinLock); + InitializeListHead(&HalpBusHandlerList); + + /* initialize hal dispatch tables */ +#if 0 + + + HalDispatchTable->HalQueryBusSlots = HaliQueryBusSlots; +#endif + + /* add system bus handler */ + BusHandler = HalpAllocateBusHandler(Internal, + ConfigurationSpaceUndefined, + 0); + if (BusHandler == NULL) + return; + BusHandler->GetInterruptVector = + (pGetInterruptVector)HalpGetSystemInterruptVector; + BusHandler->TranslateBusAddress = + (pTranslateBusAddress)HalpTranslateSystemBusAddress; + + /* add cmos bus handler */ + BusHandler = HalpAllocateBusHandler(InterfaceTypeUndefined, + Cmos, + 0); + if (BusHandler == NULL) + return; + BusHandler->GetBusData = (pGetSetBusData)HalpGetCmosData; + BusHandler->SetBusData = (pGetSetBusData)HalpSetCmosData; + + /* add isa bus handler */ + BusHandler = HalpAllocateBusHandler(Isa, + ConfigurationSpaceUndefined, + 0); + if (BusHandler == NULL) + return; + + BusHandler->TranslateBusAddress = + (pTranslateBusAddress)HalpTranslateIsaBusAddress; + + + /* add MicroChannel bus handler */ + BusHandler = HalpAllocateBusHandler(MicroChannel, + Pos, + 0); + if (BusHandler == NULL) + return; + + BusHandler->GetBusData = (pGetSetBusData)HalpGetMicroChannelData; +} + + +PBUS_HANDLER FASTCALL +HaliHandlerForBus(INTERFACE_TYPE InterfaceType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->InterfaceType == InterfaceType && + BusHandler->BusNumber == BusNumber) + { + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +PBUS_HANDLER FASTCALL +HaliHandlerForConfigSpace(BUS_DATA_TYPE BusDataType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->BusDataType == BusDataType && + BusHandler->BusNumber == BusNumber) + { + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +PBUS_HANDLER FASTCALL +HaliReferenceHandlerForBus(INTERFACE_TYPE InterfaceType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->InterfaceType == InterfaceType && + BusHandler->BusNumber == BusNumber) + { + BusHandler->RefCount++; + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +PBUS_HANDLER FASTCALL +HaliReferenceHandlerForConfigSpace(BUS_DATA_TYPE BusDataType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->BusDataType == BusDataType && + BusHandler->BusNumber == BusNumber) + { + BusHandler->RefCount++; + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +VOID FASTCALL +HaliDereferenceBusHandler(PBUS_HANDLER BusHandler) +{ + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + BusHandler->RefCount--; + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); +} + + +NTSTATUS STDCALL +HalAdjustResourceList(PCM_RESOURCE_LIST Resources) +{ + PBUS_HANDLER BusHandler; + NTSTATUS Status; + + BusHandler = HaliReferenceHandlerForBus(Resources->List[0].InterfaceType, + Resources->List[0].BusNumber); + if (BusHandler == NULL) + return STATUS_SUCCESS; + + Status = BusHandler->AdjustResourceList(BusHandler, + Resources->List[0].BusNumber, + Resources); + HaliDereferenceBusHandler (BusHandler); + + return Status; +} + + +NTSTATUS STDCALL +HalAssignSlotResources(PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + INTERFACE_TYPE BusType, + ULONG BusNumber, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources) +{ + PBUS_HANDLER BusHandler; + NTSTATUS Status; + + BusHandler = HaliReferenceHandlerForBus(BusType, + BusNumber); + if (BusHandler == NULL) + return STATUS_NOT_FOUND; + + Status = BusHandler->AssignSlotResources(BusHandler, + BusNumber, + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + SlotNumber, + AllocatedResources); + + HaliDereferenceBusHandler(BusHandler); + + return Status; +} + + +ULONG STDCALL +HalGetBusData(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + return (HalGetBusDataByOffset(BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length)); +} + + +ULONG STDCALL +HalGetBusDataByOffset(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PBUS_HANDLER BusHandler; + ULONG Result; + + BusHandler = HaliReferenceHandlerForConfigSpace(BusDataType, + BusNumber); + if (BusHandler == NULL) + return 0; + + Result = BusHandler->GetBusData(BusHandler, + BusNumber, + SlotNumber, + Buffer, + Offset, + Length); + + HaliDereferenceBusHandler (BusHandler); + + return Result; +} + + +ULONG STDCALL +HalGetInterruptVector(INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + PBUS_HANDLER BusHandler; + ULONG Result; + + BusHandler = HaliReferenceHandlerForBus(InterfaceType, + BusNumber); + if (BusHandler == NULL) + return 0; + + Result = BusHandler->GetInterruptVector(BusHandler, + BusNumber, + BusInterruptLevel, + BusInterruptVector, + Irql, + Affinity); + + HaliDereferenceBusHandler(BusHandler); + + return Result; +} + + +ULONG STDCALL +HalSetBusData(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + return (HalSetBusDataByOffset(BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length)); +} + + +ULONG STDCALL +HalSetBusDataByOffset(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PBUS_HANDLER BusHandler; + ULONG Result; + + BusHandler = HaliReferenceHandlerForConfigSpace(BusDataType, + BusNumber); + if (BusHandler == NULL) + return 0; + + Result = BusHandler->SetBusData(BusHandler, + BusNumber, + SlotNumber, + Buffer, + Offset, + Length); + + HaliDereferenceBusHandler(BusHandler); + + return Result; +} + + +BOOLEAN STDCALL +HalTranslateBusAddress(INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + PBUS_HANDLER BusHandler; + BOOLEAN Result; + + BusHandler = HaliReferenceHandlerForBus(InterfaceType, + BusNumber); + if (BusHandler == NULL) + return FALSE; + + Result = BusHandler->TranslateBusAddress(BusHandler, + BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress); + + HaliDereferenceBusHandler(BusHandler); + + return Result; +} + +/* EOF */ diff --git a/hal/halx86/display.c b/hal/halx86/display.c new file mode 100644 index 0000000..d725feb --- /dev/null +++ b/hal/halx86/display.c @@ -0,0 +1,302 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/display.c + * PURPOSE: Blue screen display + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 08/10/99 + */ + +#include +#include + +#define SCREEN_SYNCHRONIZATION + + +#define CRTC_COMMAND 0x3d4 +#define CRTC_DATA 0x3d5 + +#define CRTC_COLUMNS 0x01 +#define CRTC_OVERFLOW 0x07 +#define CRTC_ROWS 0x12 +#define CRTC_SCANLINES 0x09 + +#define CRTC_CURHI 0x0e +#define CRTC_CURLO 0x0f + + +#define CHAR_ATTRIBUTE 0x17 /* grey on blue */ + + +/* VARIABLES ****************************************************************/ + +static ULONG CursorX = 0; /* Cursor Position */ +static ULONG CursorY = 0; +static ULONG SizeX = 80; /* Display size */ +static ULONG SizeY = 25; + +static BOOLEAN DisplayInitialized = FALSE; +static BOOLEAN HalOwnsDisplay = TRUE; + +static WORD *VideoBuffer = NULL; + +static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL; + + +/* STATIC FUNCTIONS *********************************************************/ + +static VOID +HalClearDisplay (VOID) +{ + WORD *ptr = (WORD*)VideoBuffer; + ULONG i; + + for (i = 0; i < SizeX * SizeY; i++, ptr++) + *ptr = ((CHAR_ATTRIBUTE << 8) + ' '); + + CursorX = 0; + CursorY = 0; +} + + +VOID +HalScrollDisplay (VOID) +{ + WORD *ptr; + int i; + + ptr = VideoBuffer + SizeX; + RtlMoveMemory(VideoBuffer, + ptr, + SizeX * (SizeY - 1) * 2); + + ptr = VideoBuffer + (SizeX * (SizeY - 1)); + for (i = 0; i < SizeX; i++, ptr++) + { + *ptr = (CHAR_ATTRIBUTE << 8) + ' '; + } +} + + +static VOID +HalPutCharacter (CHAR Character) +{ + WORD *ptr; + + ptr = VideoBuffer + ((CursorY * SizeX) + CursorX); + *ptr = (CHAR_ATTRIBUTE << 8) + Character; +} + + +/* PRIVATE FUNCTIONS ********************************************************/ + +VOID +HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock) +/* + * FUNCTION: Initalize the display + * ARGUMENTS: + * InitParameters = Parameters setup by the boot loader + */ +{ + if (DisplayInitialized == FALSE) + { + ULONG ScanLines; + ULONG Data; + + VideoBuffer = (WORD *)(0xd0000000 + 0xb8000); +// VideoBuffer = HalMapPhysicalMemory (0xb8000, 2); + + /* Set cursor position */ +// CursorX = LoaderBlock->cursorx; +// CursorY = LoaderBlock->cursory; + CursorX = 0; + CursorY = 0; + + /* read screen size from the crtc */ + /* FIXME: screen size should be read from the boot parameters */ + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_COLUMNS); + SizeX = READ_PORT_UCHAR((PUCHAR)CRTC_DATA) + 1; + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_ROWS); + SizeY = READ_PORT_UCHAR((PUCHAR)CRTC_DATA); + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_OVERFLOW); + Data = READ_PORT_UCHAR((PUCHAR)CRTC_DATA); + SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3)); + SizeY++; + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_SCANLINES); + ScanLines = (READ_PORT_UCHAR((PUCHAR)CRTC_DATA) & 0x1F) + 1; + SizeY = SizeY / ScanLines; + +#ifdef BOCHS_30ROWS + SizeY=30; +#endif + HalClearDisplay(); + + DisplayInitialized = TRUE; + } +} + + +VOID +HalResetDisplay(VOID) +/* + * FUNCTION: Reset the display + * ARGUMENTS: + * None + */ +{ + if (HalResetDisplayParameters == NULL) + return; + + if (HalOwnsDisplay == TRUE) + return; + + if (HalResetDisplayParameters(SizeX, SizeY) == TRUE) + { + HalOwnsDisplay = TRUE; + HalClearDisplay(); + } +} + + +/* PUBLIC FUNCTIONS *********************************************************/ + +VOID STDCALL +HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters) +/* + * FUNCTION: + * ARGUMENTS: + * ResetDisplayParameters = Pointer to a driver specific + * reset routine. + */ +{ + HalOwnsDisplay = FALSE; + HalResetDisplayParameters = ResetDisplayParameters; +} + + +VOID STDCALL +HalDisplayString(IN PCH String) +/* + * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there + * already and displays a string + * ARGUMENT: + * string = ASCII string to display + * NOTE: Use with care because there is no support for returning from BSOD + * mode + */ +{ + PCH pch; +#ifdef SCREEN_SYNCHRONIZATION + int offset; +#endif + static KSPIN_LOCK Lock; + ULONG Flags; + + pch = String; + + pushfl(Flags); + __asm__ ("cli\n\t"); + KeAcquireSpinLockAtDpcLevel(&Lock); + + if (HalOwnsDisplay == FALSE) + { + HalResetDisplay (); + } + +#ifdef SCREEN_SYNCHRONIZATION + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI); + offset = READ_PORT_UCHAR((PUCHAR)CRTC_DATA)<<8; + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO); + offset += READ_PORT_UCHAR((PUCHAR)CRTC_DATA); + + CursorY = offset / SizeX; + CursorX = offset % SizeX; +#endif + + while (*pch != 0) + { + if (*pch == '\n') + { + CursorY++; + CursorX = 0; + } + else if (*pch != '\r') + { + HalPutCharacter (*pch); + CursorX++; + + if (CursorX >= SizeX) + { + CursorY++; + CursorX = 0; + } + } + + if (CursorY >= SizeY) + { + HalScrollDisplay (); + CursorY = SizeY - 1; + } + + pch++; + } + +#ifdef SCREEN_SYNCHRONIZATION + offset = (CursorY * SizeX) + CursorX; + + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO); + WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, offset & 0xff); + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI); + WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, (offset >> 8) & 0xff); +#endif + KeReleaseSpinLockFromDpcLevel(&Lock); + popfl(Flags); +} + + +VOID STDCALL +HalQueryDisplayParameters(OUT PULONG DispSizeX, + OUT PULONG DispSizeY, + OUT PULONG CursorPosX, + OUT PULONG CursorPosY) +{ + if (DispSizeX) + *DispSizeX = SizeX; + if (DispSizeY) + *DispSizeY = SizeY; + if (CursorPosX) + *CursorPosX = CursorX; + if (CursorPosY) + *CursorPosY = CursorY; +} + + +VOID STDCALL +HalSetDisplayParameters(IN ULONG CursorPosX, + IN ULONG CursorPosY) +{ + CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1; + CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1; +} + +/* EOF */ diff --git a/hal/halx86/dma.c b/hal/halx86/dma.c new file mode 100644 index 0000000..35cc761 --- /dev/null +++ b/hal/halx86/dma.c @@ -0,0 +1,115 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/dma.c + * PURPOSE: DMA functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include +#include + +ADAPTER_OBJECT AdapterObjects[] = { + { 0, (PVOID)0x87, (PVOID)0x1, (PVOID)0x0, { 0 }, NULL }, + { 1, (PVOID)0x83, (PVOID)0x3, (PVOID)0x2, { 0 }, NULL }, + { 2, (PVOID)0x81, (PVOID)0x5, (PVOID)0x4, { 0 }, NULL }, + { 3, (PVOID)0x82, (PVOID)0x7, (PVOID)0x6, { 0 }, NULL } }; + + +/* FUNCTIONS *****************************************************************/ + +PVOID STDCALL +HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject, + ULONG Length, + PPHYSICAL_ADDRESS LogicalAddress, + BOOLEAN CacheEnabled) +/* + * FUNCTION: Allocates memory that is visible to both the processor(s) and + * a dma device + * ARGUMENTS: + * AdapterObject = Adapter object representing the bus master or + * system dma controller + * Length = Number of bytes to allocate + * LogicalAddress = Logical address the driver can use to access the + * buffer + * CacheEnabled = Specifies if the memory can be cached + * RETURNS: The base virtual address of the memory allocated + * NULL on failure + */ +{ + UNIMPLEMENTED; +} + +BOOLEAN STDCALL +HalFlushCommonBuffer (ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6, + ULONG Unknown7, + ULONG Unknown8) +{ + return TRUE; +} + +VOID STDCALL +HalFreeCommonBuffer (PADAPTER_OBJECT AdapterObject, + ULONG Length, + PHYSICAL_ADDRESS LogicalAddress, + PVOID VirtualAddress, + BOOLEAN CacheEnabled) +{ + MmFreeContiguousMemory(VirtualAddress); +} + +PADAPTER_OBJECT STDCALL +HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, + PULONG NumberOfMapRegisters) +/* + * FUNCTION: Returns a pointer to an adapter object for the DMA device + * defined in the device description structure + * ARGUMENTS: + * DeviceDescription = Structure describing the attributes of the device + * NumberOfMapRegisters (OUT) = Returns the maximum number of map + * registers the device driver can + * allocate for DMA transfer operations + * RETURNS: The allocated adapter object on success + * NULL on failure + */ +{ + /* Validate parameters in device description, and return a pointer to + the adapter object for the requested dma channel */ + if( DeviceDescription->Version != DEVICE_DESCRIPTION_VERSION ) + return NULL; + if( DeviceDescription->Master ) + return NULL; + if( DeviceDescription->ScatterGather ) + return NULL; + if( DeviceDescription->AutoInitialize ) + return NULL; + if( DeviceDescription->Dma32BitAddress ) + return NULL; + if( DeviceDescription->InterfaceType != Isa ) + return NULL; + /* if( DeviceDescription->DmaWidth != Width8Bits ) + return NULL;*/ + *NumberOfMapRegisters = 0x10; + AdapterObjects[DeviceDescription->DmaChannel].Buffer = 0; + return &AdapterObjects[DeviceDescription->DmaChannel]; +} + +ULONG STDCALL +HalReadDmaCounter (PADAPTER_OBJECT AdapterObject) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/hal/halx86/drive.c b/hal/halx86/drive.c new file mode 100644 index 0000000..cc04fbe --- /dev/null +++ b/hal/halx86/drive.c @@ -0,0 +1,31 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/x86/drive.c + * PURPOSE: Drive letter assignment + * PROGRAMMER: + * UPDATE HISTORY: + * 2000-03-25 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PSTRING NtDeviceName, + OUT PUCHAR NtSystemPath, + OUT PSTRING NtSystemPathString) +{ + HalDispatchTable.HalIoAssignDriveLetters(LoaderBlock, + NtDeviceName, + NtSystemPath, + NtSystemPathString); +} + +/* EOF */ diff --git a/hal/halx86/enum.c b/hal/halx86/enum.c new file mode 100644 index 0000000..135931f --- /dev/null +++ b/hal/halx86/enum.c @@ -0,0 +1,25 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/enum.c + * PURPOSE: Motherboard device enumerator + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * Created 01/05/2001 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +VOID +HalpStartEnumerator (VOID) +{ +} + +/* EOF */ diff --git a/hal/halx86/fmutex.c b/hal/halx86/fmutex.c new file mode 100644 index 0000000..b31e6b8 --- /dev/null +++ b/hal/halx86/fmutex.c @@ -0,0 +1,53 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/fmutex.c + * PURPOSE: Implements fast mutexes + * PROGRAMMER: David Welch (welch@cwcom.net) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 09/06/2000 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID FASTCALL +ExAcquireFastMutex (PFAST_MUTEX FastMutex) +{ + KeEnterCriticalRegion(); + ExAcquireFastMutexUnsafe(FastMutex); +} + + +VOID FASTCALL +ExReleaseFastMutex (PFAST_MUTEX FastMutex) +{ + ExReleaseFastMutexUnsafe(FastMutex); + KeLeaveCriticalRegion(); +} + + +BOOLEAN FASTCALL +ExTryToAcquireFastMutex (PFAST_MUTEX FastMutex) +{ + KeEnterCriticalRegion(); + if (InterlockedExchange(&FastMutex->Count, 0) == 1) + { + FastMutex->Owner = KeGetCurrentThread(); + return(TRUE); + } + else + { + KeLeaveCriticalRegion(); + return(FALSE); + } +} + +/* EOF */ diff --git a/hal/halx86/halinit.c b/hal/halx86/halinit.c new file mode 100644 index 0000000..287aa2f --- /dev/null +++ b/hal/halx86/halinit.c @@ -0,0 +1,71 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/halinit.c + * PURPOSE: Initalize the x86 hal + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 11/06/98: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#ifdef MP +#include +#endif /* MP */ + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS +STDCALL +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + return STATUS_SUCCESS; +} + +BOOLEAN STDCALL +HalInitSystem (ULONG BootPhase, + PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + if (BootPhase == 0) + { + HalInitializeDisplay (LoaderBlock); + +#ifdef MP + + HalpInitMPS(); + +#else + + HalpInitPICs(); + + /* Setup busy waiting */ + HalpCalibrateStallExecution(); + +#endif /* MP */ + + } + else if (BootPhase == 1) + { + HalpInitBusHandlers (); + HalpCalibrateStallExecution (); + + /* Enumerate the devices on the motherboard */ + HalpStartEnumerator(); + } + + return TRUE; +} + +/* EOF */ diff --git a/hal/halx86/halx86mp.rc b/hal/halx86/halx86mp.rc new file mode 100644 index 0000000..4021685 --- /dev/null +++ b/hal/halx86/halx86mp.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "X86 Multiprocessor Hardware Abstraction Layer\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "halx86mp\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "halx86mp.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/hal/halx86/halx86up.rc b/hal/halx86/halx86up.rc new file mode 100644 index 0000000..75e1a48 --- /dev/null +++ b/hal/halx86/halx86up.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "X86 Uniprocessor Hardware Abstraction Layer\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "halx86up\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "halx86up.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/hal/halx86/include/bus.h b/hal/halx86/include/bus.h new file mode 100644 index 0000000..d77a470 --- /dev/null +++ b/hal/halx86/include/bus.h @@ -0,0 +1,125 @@ +/* + + */ + +#ifndef __INTERNAL_HAL_BUS_H +#define __INTERNAL_HAL_BUS_H + + +typedef NTSTATUS STDCALL +(*pAdjustResourceList)(IN PBUS_HANDLER BusHandler, + IN ULONG BusNumber, + IN OUT PCM_RESOURCE_LIST Resources); + +typedef NTSTATUS STDCALL +(*pAssignSlotResources)(IN PBUS_HANDLER BusHandler, + IN ULONG BusNumber, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources); + +typedef ULONG STDCALL +(*pGetSetBusData)(IN PBUS_HANDLER BusHandler, + IN ULONG BusNumber, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length); + +typedef ULONG STDCALL +(*pGetInterruptVector)(IN PBUS_HANDLER BusHandler, + IN ULONG BusNumber, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity); + +typedef ULONG STDCALL +(*pTranslateBusAddress)(IN PBUS_HANDLER BusHandler, + IN ULONG BusNumber, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress); + +typedef struct _BUS_HANDLER +{ + LIST_ENTRY Entry; + INTERFACE_TYPE InterfaceType; + BUS_DATA_TYPE BusDataType; + ULONG BusNumber; + ULONG RefCount; + + pGetSetBusData GetBusData; + pGetSetBusData SetBusData; + pAdjustResourceList AdjustResourceList; + pAssignSlotResources AssignSlotResources; + pGetInterruptVector GetInterruptVector; + pTranslateBusAddress TranslateBusAddress; +} BUS_HANDLER; + + +/* FUNCTIONS *****************************************************************/ + +/* bus.c */ +PBUS_HANDLER +HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType, + BUS_DATA_TYPE BusDataType, + ULONG BusNumber); + +/* sysbus.h */ +ULONG STDCALL +HalpGetSystemInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity); + +BOOLEAN STDCALL +HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + +/* isa.c */ +BOOLEAN STDCALL +HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + +/* time.c */ +ULONG STDCALL +HalpGetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +ULONG STDCALL +HalpSetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +/* mca.h */ +ULONG STDCALL +HalpGetMicroChannelData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +#endif /* __INTERNAL_HAL_BUS_H */ + +/* EOF */ + diff --git a/hal/halx86/include/hal.h b/hal/halx86/include/hal.h new file mode 100644 index 0000000..704c2b3 --- /dev/null +++ b/hal/halx86/include/hal.h @@ -0,0 +1,48 @@ +/* + * + */ + +#ifndef __INTERNAL_HAL_HAL_H +#define __INTERNAL_HAL_HAL_H + +//#include +//#include + +/* + * FUNCTION: Probes for a BIOS32 extension + */ +VOID Hal_bios32_probe(VOID); + +/* + * FUNCTION: Determines if a a bios32 service is present + */ +BOOLEAN Hal_bios32_is_service_present(ULONG service); + +VOID HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock); +VOID HalResetDisplay (VOID); + +VOID HalpInitBusHandlers (VOID); + +/* irql.c */ +VOID HalpInitPICs(VOID); + +/* udelay.c */ +VOID HalpCalibrateStallExecution(VOID); + +/* pci.c */ +VOID HalpInitPciBus (VOID); + +/* enum.c */ +VOID HalpStartEnumerator (VOID); + +struct _ADAPTER_OBJECT { + int Channel; + PVOID PagePort; + PVOID CountPort; + PVOID OffsetPort; + KSPIN_LOCK SpinLock; + PVOID Buffer; + BOOLEAN Inuse; +}; + +#endif /* __INTERNAL_HAL_HAL_H */ diff --git a/hal/halx86/include/mps.h b/hal/halx86/include/mps.h new file mode 100644 index 0000000..6fc8e47 --- /dev/null +++ b/hal/halx86/include/mps.h @@ -0,0 +1,435 @@ +#ifndef __INCLUDE_HAL_MPS +#define __INCLUDE_HAL_MPS + +#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */ +#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */ + +/* APIC Register Address Map */ +#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */ +#define APIC_VER 0x0030 /* Local APIC Version Register (R) */ +#define APIC_TPR 0x0080 /* Task Priority Register (R/W) */ +#define APIC_APR 0x0090 /* Arbitration Priority Register (R) */ +#define APIC_PPR 0x00A0 /* Processor Priority Register (R) */ +#define APIC_EOI 0x00B0 /* EOI Register (W) */ +#define APIC_LDR 0x00D0 /* Logical Destination Register (R/W) */ +#define APIC_DFR 0x00E0 /* Destination Format Register (0-27 R, 28-31 R/W) */ +#define APIC_SIVR 0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */ +#define APIC_ISR 0x0100 /* Interrupt Service Register 0-255 (R) */ +#define APIC_TMR 0x0180 /* Trigger Mode Register 0-255 (R) */ +#define APIC_IRR 0x0200 /* Interrupt Request Register 0-255 (r) */ +#define APIC_ESR 0x0280 /* Error Status Register (R) */ +#define APIC_ICR0 0x0300 /* Interrupt Command Register 0-31 (R/W) */ +#define APIC_ICR1 0x0310 /* Interrupt Command Register 32-63 (R/W) */ +#define APIC_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */ +#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */ +#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */ +#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */ +#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */ +#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */ +#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */ +#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */ + +#define APIC_ID_MASK (0xF << 24) +#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24) +#define APIC_VER_MASK 0xFF00FF +#define GET_APIC_VERSION(x)((x) & 0xFF) +#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF) + +#define APIC_TPR_PRI 0xFF +#define APIC_TPR_INT 0xF0 +#define APIC_TPR_SUB 0xF +#define APIC_TPR_MAX 0xFF /* Maximum priority */ +#define APIC_TPR_MIN 0x20 /* Minimum priority */ + +#define APIC_LDR_MASK (0xFF << 24) + +#define APIC_SIVR_ENABLE (0x1 << 8) +#define APIC_SIVR_FOCUS (0x1 << 9) + +#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */ + +#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */ +#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */ +#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */ +#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */ +#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */ +#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */ +#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */ + +/* Delivery Modes */ +#define APIC_DM_FIXED (0x0 << 8) +#define APIC_DM_LOWEST (0x1 << 8) +#define APIC_DM_SMI (0x2 << 8) +#define APIC_DM_REMRD (0x3 << 8) +#define APIC_DM_NMI (0x4 << 8) +#define APIC_DM_INIT (0x5 << 8) +#define APIC_DM_STARTUP (0x6 << 8) +#define APIC_DM_EXTINT (0x7 << 8) +#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) +#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8)) + +/* Destination Shorthand values */ +#define APIC_ICR0_DESTS_FIELD (0x0 << 0) +#define APIC_ICR0_DESTS_SELF (0x1 << 18) +#define APIC_ICR0_DESTS_ALL (0x2 << 18) +#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18) + +#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */ +#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */ + +#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) +#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24) + +#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3) +#define SET_APIC_TIMER_BASE(x) ((x) << 18) +#define APIC_TIMER_BASE_CLKIN 0x0 +#define APIC_TIMER_BASE_TMBASE 0x1 +#define APIC_TIMER_BASE_DIV 0x2 + +#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */ +#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */ +#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */ +#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */ +#define APIC_LVT_MASKED (0x1 << 16) /* Mask */ +#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */ + +#define APIC_LVT3_DM (0x7 << 8) +#define APIC_LVT3_IIPP (0x1 << 13) +#define APIC_LVT3_TM (0x1 << 15) +#define APIC_LVT3_MASKED (0x1 << 16) +#define APIC_LVT3_OS (0x1 << 17) + +#define APIC_TDCR_TMBASE (0x1 << 2) +#define APIC_TDCR_MASK 0x0F +#define APIC_TDCR_2 0x00 +#define APIC_TDCR_4 0x01 +#define APIC_TDCR_8 0x02 +#define APIC_TDCR_16 0x03 +#define APIC_TDCR_32 0x08 +#define APIC_TDCR_64 0x09 +#define APIC_TDCR_128 0x0A +#define APIC_TDCR_1 0x0B + +#define APIC_TARGET_SELF 0x100 +#define APIC_TARGET_ALL 0x200 +#define APIC_TARGET_ALL_BUT_SELF 0x300 + +#define IPI_CACHE_FLUSH 0x40 +#define IPI_INV_TLB 0x41 +#define IPI_INV_PTE 0x42 +#define IPI_INV_RESCHED 0x43 +#define IPI_STOP 0x44 + + +#define APIC_INTEGRATED(version) (version & 0xF0) + + +/* I/O APIC Register Address Map */ +#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */ +#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */ + +#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */ +#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */ +#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */ +#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */ + +#define IOAPIC_ID_MASK (0xF << 24) +#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24) +#define SET_IOAPIC_ID(x) ((x) << 24) + +#define IOAPIC_VER_MASK (0xFF) +#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK)) +#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */ +#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16) + +#define IOAPIC_ARB_MASK (0xF << 24) +#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24) + +#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */ +#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */ +#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */ +#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */ +#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */ +#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */ +#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */ +#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */ +#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */ +#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */ + +typedef struct _IOAPIC_ROUTE_ENTRY { + ULONG vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest priority + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { struct { ULONG + __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + + struct { ULONG + __reserved_1 : 24, + logical_dest : 8; + } logical; + } dest; +} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY; + +typedef struct _IOAPIC_INFO +{ + ULONG ApicId; /* APIC ID */ + ULONG ApicVersion; /* APIC version */ + ULONG ApicAddress; /* APIC address */ + ULONG EntryCount; /* Number of redirection entries */ +} IOAPIC_INFO, *PIOAPIC_INFO; + + +/* + * Local APIC timer IRQ vector is on a different priority level, + * to work around the 'lost local interrupt if more than 2 IRQ + * sources per level' errata. + */ +#define LOCAL_TIMER_VECTOR 0xEF + +#define CALL_FUNCTION_VECTOR 0xFB +#define RESCHEDULE_VECTOR 0xFC +#define INVALIDATE_TLB_VECTOR 0xFD +#define ERROR_VECTOR 0xFE +#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ + +/* + * First APIC vector available to drivers: (vectors 0x30-0xEE) + * we start at 0x31 to spread out vectors evenly between priority + * levels. + */ +#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_SYSTEM_VECTOR 0xEF +#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) + + +/* MP Floating Pointer Structure */ +#define MPF_SIGNATURE (('_' << 24) | ('P' << 16) | ('M' << 8) | '_') + +typedef struct __attribute__((packed)) _MP_FLOATING_POINTER +{ + ULONG Signature; /* _MP_ */ + ULONG Address; /* Physical Address Pointer (0 means no configuration table exist) */ + UCHAR Length; /* Structure length in 16-byte paragraphs */ + UCHAR Specification; /* Specification revision */ + UCHAR Checksum; /* Checksum */ + UCHAR Feature1; /* MP System Configuration Type */ + UCHAR Feature2; /* Bit 7 set for IMCR|PIC */ + UCHAR Feature3; /* Unused (0) */ + UCHAR Feature4; /* Unused (0) */ + UCHAR Feature5; /* Unused (0) */ +} __attribute__((packed)) MP_FLOATING_POINTER, *PMP_FLOATING_POINTER; + +#define FEATURE2_IMCRP 0x80 + +/* MP Configuration Table Header */ +#define MPC_SIGNATURE (('P' << 24) | ('M' << 16) | ('C' << 8) | 'P') + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_TABLE +{ + ULONG Signature; /* PCMP */ + USHORT Length; /* Size of configuration table */ + CHAR Specification; /* Specification Revision */ + CHAR Checksum; /* Checksum */ + CHAR Oem[8]; /* OEM ID */ + CHAR ProductId[12]; /* Product ID */ + ULONG OemTable; /* 0 if not present */ + USHORT OemTableSize; /* 0 if not present */ + USHORT EntryCount; /* Number of entries */ + ULONG LocalAPICAddress; /* Local APIC address */ + USHORT ExtTableLength; /* Extended Table Length */ + UCHAR ExtTableChecksum; /* Extended Table Checksum */ + UCHAR Reserved; /* Reserved */ +} __attribute__((packed)) MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE; + +/* MP Configuration Table Entries */ +#define MPCTE_PROCESSOR 0 /* One entry per processor */ +#define MPCTE_BUS 1 /* One entry per bus */ +#define MPCTE_IOAPIC 2 /* One entry per I/O APIC */ +#define MPCTE_INTSRC 3 /* One entry per bus interrupt source */ +#define MPCTE_LINTSRC 4 /* One entry per system interrupt source */ + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_PROCESSOR +{ + UCHAR Type; /* 0 */ + UCHAR ApicId; /* Local APIC ID for the processor */ + UCHAR ApicVersion; /* Local APIC version */ + UCHAR CpuFlags; /* CPU flags */ + ULONG CpuSignature; /* CPU signature */ + ULONG FeatureFlags; /* CPUID feature value */ + ULONG Reserved[2]; /* Reserved (0) */ +} __attribute__((packed)) MP_CONFIGURATION_PROCESSOR, + *PMP_CONFIGURATION_PROCESSOR; + +#define CPU_FLAG_ENABLED 1 /* Processor is available */ +#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */ + +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_BUS +{ + UCHAR Type; /* 1 */ + UCHAR BusId; /* Bus ID */ + UCHAR BusType[6]; /* Bus type */ +} __attribute__((packed)) MP_CONFIGURATION_BUS, *PMP_CONFIGURATION_BUS; + +#define MAX_BUS 32 + +#define MP_BUS_ISA 1 +#define MP_BUS_EISA 2 +#define MP_BUS_PCI 3 +#define MP_BUS_MCA 4 + +#define BUSTYPE_EISA "EISA" +#define BUSTYPE_ISA "ISA" +#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ +#define BUSTYPE_MCA "MCA" +#define BUSTYPE_VL "VL" /* Local bus */ +#define BUSTYPE_PCI "PCI" +#define BUSTYPE_PCMCIA "PCMCIA" +#define BUSTYPE_CBUS "CBUS" +#define BUSTYPE_CBUSII "CBUSII" +#define BUSTYPE_FUTURE "FUTURE" +#define BUSTYPE_MBI "MBI" +#define BUSTYPE_MBII "MBII" +#define BUSTYPE_MPI "MPI" +#define BUSTYPE_MPSA "MPSA" +#define BUSTYPE_NUBUS "NUBUS" +#define BUSTYPE_TC "TC" +#define BUSTYPE_VME "VME" +#define BUSTYPE_XPRESS "XPRESS" + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_IOAPIC +{ + UCHAR Type; /* 2 */ + UCHAR ApicId; /* I/O APIC ID */ + UCHAR ApicVersion; /* I/O APIC version */ + UCHAR ApicFlags; /* I/O APIC flags */ + ULONG ApicAddress; /* I/O APIC base address */ +} __attribute__((packed)) MP_CONFIGURATION_IOAPIC, *PMP_CONFIGURATION_IOAPIC; + +#define MAX_IOAPIC 2 + +#define MP_IOAPIC_USABLE 0x01 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTSRC +{ + UCHAR Type; /* 3 */ + UCHAR IrqType; /* Interrupt type */ + USHORT IrqFlag; /* Interrupt flags */ + UCHAR SrcBusId; /* Source bus ID */ + UCHAR SrcBusIrq; /* Source bus interrupt */ + UCHAR DstApicId; /* Destination APIC ID */ + UCHAR DstApicInt; /* Destination interrupt */ +} __attribute__((packed)) MP_CONFIGURATION_INTSRC, *PMP_CONFIGURATION_INTSRC; + +#define MAX_IRQ_SOURCE 128 + +#define INT_VECTORED 0 +#define INT_NMI 1 +#define INT_SMI 2 +#define INT_EXTINT 3 + +#define IRQDIR_DEFAULT 0 +#define IRQDIR_HIGH 1 +#define IRQDIR_LOW 3 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTLOCAL +{ + UCHAR Type; /* 4 */ + UCHAR IrqType; /* Interrupt type */ + USHORT IrqFlag; /* Interrupt flags */ + UCHAR SrcBusId; /* Source bus ID */ + UCHAR SrcBusIrq; /* Source bus interrupt */ + UCHAR DstApicId; /* Destination local APIC ID */ + UCHAR DstApicLInt; /* Destination local APIC interrupt */ +} MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL; + +#define MP_APIC_ALL 0xFF + + +static inline VOID ReadPentiumClock(PULARGE_INTEGER Count) +{ + register ULONG nLow; + register ULONG nHigh; + + __asm__ __volatile__ ("rdtsc" : "=a" (nLow), "=d" (nHigh)); + + Count->u.LowPart = nLow; + Count->u.HighPart = nHigh; +} + + +#define MAX_CPU 32 + + +typedef struct _CPU_INFO +{ + UCHAR Flags; /* CPU flags */ + UCHAR APICId; /* Local APIC ID */ + UCHAR APICVersion; /* Local APIC version */ + UCHAR MaxLVT; /* Number of LVT registers */ + ULONG BusSpeed; /* BUS speed */ + ULONG CoreSpeed; /* Core speed */ + UCHAR Padding[16-12]; /* Padding to 16-byte */ +} CPU_INFO, *PCPU_INFO; + +/* CPU flags */ +#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */ +#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */ +#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */ + + +typedef enum { + amPIC = 0, /* IMCR and PIC compatibility mode */ + amVWIRE /* Virtual Wire compatibility mode */ +} APIC_MODE; + + +#define pushfl(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) +#define popfl(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") + + +#define PIC_IRQS 16 + +/* Prototypes */ + +VOID HalpInitMPS(VOID); +volatile ULONG IOAPICRead(ULONG Apic, ULONG Offset); +VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value); +VOID IOAPICMaskIrq(ULONG Apic, ULONG Irq); +VOID IOAPICUnmaskIrq(ULONG Apic, ULONG Irq); +volatile inline ULONG APICRead(ULONG Offset); +inline VOID APICWrite(ULONG Offset, ULONG Value); +inline VOID APICSendEOI(VOID); +inline ULONG ThisCPU(VOID); +VOID APICSendIPI(ULONG Target, + ULONG DeliveryMode, + ULONG IntNum, + ULONG Level); +/* For debugging */ +VOID IOAPICDump(VOID); +VOID APICDump(VOID); + +#endif /* __INCLUDE_HAL_MPS */ + +/* EOF */ diff --git a/hal/halx86/irql.c b/hal/halx86/irql.c new file mode 100644 index 0000000..a18a5aa --- /dev/null +++ b/hal/halx86/irql.c @@ -0,0 +1,387 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/irql.c + * PURPOSE: Implements IRQLs + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +#define NR_IRQS (16) +#define IRQ_BASE (0x40) + +/* + * PURPOSE: Current irq level + */ +static KIRQL CurrentIrql = HIGH_LEVEL; + +extern IMPORTED ULONG DpcQueueSize; + +static ULONG HalpPendingInterruptCount[NR_IRQS]; + +#define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x) +#define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x) + +VOID STDCALL +KiInterruptDispatch2 (ULONG Irq, KIRQL old_level); + +/* FUNCTIONS ****************************************************************/ + +KIRQL STDCALL KeGetCurrentIrql (VOID) +/* + * PURPOSE: Returns the current irq level + * RETURNS: The current irq level + */ +{ + return(CurrentIrql); +} + +VOID HalpInitPICs(VOID) +{ + memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount)); + + /* Initialization sequence */ + WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11); + WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11); + /* Start of hardware irqs (0x24) */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x40); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x48); + /* 8259-1 is master */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4); + /* 8259-2 is slave */ + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2); + /* 8086 mode */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1); + /* Enable all interrupts from PICs */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x0); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x0); + + /* We can now enable interrupts */ + __asm__ __volatile__ ("sti\n\t"); +} + +VOID STATIC +HalpExecuteIrqs(KIRQL NewIrql) +{ + ULONG IrqLimit, i; + + IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS); + + /* + * For each irq if there have been any deferred interrupts then now + * dispatch them. + */ + for (i = 0; i < IrqLimit; i++) + { + while (HalpPendingInterruptCount[i] > 0) + { + /* + * For each deferred interrupt execute all the handlers at DIRQL. + */ + CurrentIrql = IRQ_TO_DIRQL(i); + KiInterruptDispatch2(i, NewIrql); + HalpPendingInterruptCount[i]--; + } + } +} + +VOID STATIC +HalpLowerIrql(KIRQL NewIrql) +{ + if (NewIrql > PROFILE_LEVEL) + { + CurrentIrql = NewIrql; + return; + } + HalpExecuteIrqs(NewIrql); + if (NewIrql >= DISPATCH_LEVEL) + { + CurrentIrql = NewIrql; + return; + } + CurrentIrql = DISPATCH_LEVEL; + if (DpcQueueSize > 0) + { + KiDispatchInterrupt(); + } + if (NewIrql == APC_LEVEL) + { + CurrentIrql = NewIrql; + return; + } + CurrentIrql = APC_LEVEL; + if (KeGetCurrentThread() != NULL && + KeGetCurrentThread()->ApcState.KernelApcPending) + { + KiDeliverApc(0, 0, 0); + } + CurrentIrql = PASSIVE_LEVEL; +} + +/********************************************************************** + * NAME EXPORTED + * KfLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + * Uses fastcall convention + */ +VOID FASTCALL +KfLowerIrql (KIRQL NewIrql) +{ + KIRQL OldIrql; + + DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql); + + if (NewIrql > CurrentIrql) + { + DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n", + __FILE__, __LINE__, NewIrql, CurrentIrql); + KeBugCheck(0); + for(;;); + } + + HalpLowerIrql(NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KeLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + */ + +VOID STDCALL +KeLowerIrql (KIRQL NewIrql) +{ + KfLowerIrql (NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KfRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * + * RETURN VALUE + * previous irq level + * + * NOTES + * Uses fastcall convention + */ + +KIRQL FASTCALL +KfRaiseIrql (KIRQL NewIrql) +{ + KIRQL OldIrql; + + DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql); + + if (NewIrql < CurrentIrql) + { + DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n", + __FILE__,__LINE__,CurrentIrql,NewIrql); + KeBugCheck (0); + for(;;); + } + + OldIrql = CurrentIrql; + CurrentIrql = NewIrql; + return OldIrql; +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * OldIrql (OUT) = Caller supplied storage for the previous irql + * + * RETURN VALUE + * None + * + * NOTES + * Calls KfRaiseIrql + */ +VOID STDCALL +KeRaiseIrql (KIRQL NewIrql, + PKIRQL OldIrql) +{ + *OldIrql = KfRaiseIrql (NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToDpcLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to DISPATCH level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL STDCALL +KeRaiseIrqlToDpcLevel (VOID) +{ + return KfRaiseIrql (DISPATCH_LEVEL); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToSynchLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to CLOCK2 level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL STDCALL +KeRaiseIrqlToSynchLevel (VOID) +{ + return KfRaiseIrql (CLOCK2_LEVEL); +} + + +BOOLEAN STDCALL +HalBeginSystemInterrupt (ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) +{ + if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS) + { + return(FALSE); + } + + /* Send EOI to the PICs */ + WRITE_PORT_UCHAR((PUCHAR)0x20,0x20); + if ((Vector-IRQ_BASE)>=8) + { + WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20); + } + + if (CurrentIrql >= Irql) + { + HalpPendingInterruptCount[Vector - IRQ_BASE]++; + return(FALSE); + } + *OldIrql = CurrentIrql; + CurrentIrql = Irql; + + return(TRUE); +} + + +VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2) +/* + * FUNCTION: Finish a system interrupt and restore the specified irq level. + */ +{ + HalpLowerIrql(Irql); +} + +BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector, + ULONG Unknown2) +{ + ULONG irq; + + if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS) + return FALSE; + + irq = Vector - IRQ_BASE; + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, + READ_PORT_UCHAR((PUCHAR)0x21)|(1< IRQ_BASE + NR_IRQS) + return FALSE; + + irq = Vector - IRQ_BASE; + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, + READ_PORT_UCHAR((PUCHAR)0x21)&(~(1< +#include + + +/* FUNCTIONS *****************************************************************/ + +BOOL HalIsaProbe(VOID) +/* + * FUNCTION: Probes for an ISA bus + * RETURNS: True if detected + * NOTE: Since ISA is the default we are called last and always return + * true + */ +{ + DbgPrint("Assuming ISA bus\n"); + + /* + * Probe for plug and play support + */ + return(TRUE); +} + + +BOOLEAN STDCALL +HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + BOOLEAN Result; + + Result = HalTranslateBusAddress(PCIBus, + BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress); + if (Result != FALSE) + return Result; + + Result = HalTranslateBusAddress(Internal, + BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress); + return Result; +} + +/* EOF */ diff --git a/hal/halx86/kdbg.c b/hal/halx86/kdbg.c new file mode 100644 index 0000000..119ca73 --- /dev/null +++ b/hal/halx86/kdbg.c @@ -0,0 +1,533 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/kdbg.c + * PURPOSE: Serial i/o functions for the kernel debugger. + * PROGRAMMER: Emanuele Aliberti + * Eric Kohl + * UPDATE HISTORY: + * Created 05/09/99 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +#define DEFAULT_BAUD_RATE 19200 + + +/* MACROS *******************************************************************/ + +#define SER_RBR(x) ((x)+0) +#define SER_THR(x) ((x)+0) +#define SER_DLL(x) ((x)+0) +#define SER_IER(x) ((x)+1) +#define SR_IER_ERDA 0x01 +#define SR_IER_ETHRE 0x02 +#define SR_IER_ERLSI 0x04 +#define SR_IER_EMS 0x08 +#define SR_IER_ALL 0x0F +#define SER_DLM(x) ((x)+1) +#define SER_IIR(x) ((x)+2) +#define SER_LCR(x) ((x)+3) +#define SR_LCR_CS5 0x00 +#define SR_LCR_CS6 0x01 +#define SR_LCR_CS7 0x02 +#define SR_LCR_CS8 0x03 +#define SR_LCR_ST1 0x00 +#define SR_LCR_ST2 0x04 +#define SR_LCR_PNO 0x00 +#define SR_LCR_POD 0x08 +#define SR_LCR_PEV 0x18 +#define SR_LCR_PMK 0x28 +#define SR_LCR_PSP 0x38 +#define SR_LCR_BRK 0x40 +#define SR_LCR_DLAB 0x80 +#define SER_MCR(x) ((x)+4) +#define SR_MCR_DTR 0x01 +#define SR_MCR_RTS 0x02 +#define SR_MCR_OUT1 0x04 +#define SR_MCR_OUT2 0x08 +#define SR_MCR_LOOP 0x10 +#define SER_LSR(x) ((x)+5) +#define SR_LSR_DR 0x01 +#define SR_LSR_TBE 0x20 +#define SER_MSR(x) ((x)+6) +#define SR_MSR_CTS 0x10 +#define SR_MSR_DSR 0x20 +#define SER_SCR(x) ((x)+7) + + +/* GLOBAL VARIABLES *********************************************************/ + +ULONG EXPORTED KdComPortInUse = 0; + + +/* STATIC VARIABLES *********************************************************/ + +static ULONG ComPort = 0; +static ULONG BaudRate = 0; +static PUCHAR PortBase = (PUCHAR)0; + +/* The com port must only be initialized once! */ +static BOOLEAN PortInitialized = FALSE; + + +/* STATIC FUNCTIONS *********************************************************/ + +static BOOLEAN +KdpDoesComPortExist (PUCHAR BaseAddress) +{ + BOOLEAN found; + BYTE mcr; + BYTE msr; + + found = FALSE; + + /* save Modem Control Register (MCR) */ + mcr = READ_PORT_UCHAR (SER_MCR(BaseAddress)); + + /* enable loop mode (set Bit 4 of the MCR) */ + WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10); + + /* clear all modem output bits */ + WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10); + + /* read the Modem Status Register */ + msr = READ_PORT_UCHAR (SER_MSR(BaseAddress)); + + /* + * the upper nibble of the MSR (modem output bits) must be + * equal to the lower nibble of the MCR (modem input bits) + */ + if ((msr & 0xF0) == 0x00) + { + /* set all modem output bits */ + WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x1F); + + /* read the Modem Status Register */ + msr = READ_PORT_UCHAR (SER_MSR(BaseAddress)); + + /* + * the upper nibble of the MSR (modem output bits) must be + * equal to the lower nibble of the MCR (modem input bits) + */ + if ((msr & 0xF0) == 0xF0) + found = TRUE; + } + + /* restore MCR */ + WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr); + + return (found); +} + + +/* FUNCTIONS ****************************************************************/ + +/* HAL.KdPortInitialize */ +BOOLEAN +STDCALL +KdPortInitialize ( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; + char buffer[80]; + ULONG divisor; + BYTE lcr; + + if (PortInitialized == FALSE) + { + if (PortInformation->BaudRate != 0) + { + BaudRate = PortInformation->BaudRate; + } + else + { + BaudRate = DEFAULT_BAUD_RATE; + } + + if (PortInformation->ComPort == 0) + { + if (KdpDoesComPortExist ((PUCHAR)BaseArray[2])) + { + PortBase = (PUCHAR)BaseArray[2]; + ComPort = 2; + PortInformation->BaseAddress = (ULONG)PortBase; + PortInformation->ComPort = ComPort; +#ifndef NDEBUG + sprintf (buffer, + "\nSerial port COM%ld found at 0x%lx\n", + ComPort, + (ULONG)PortBase); + HalDisplayString (buffer); +#endif /* NDEBUG */ + } + else if (KdpDoesComPortExist ((PUCHAR)BaseArray[1])) + { + PortBase = (PUCHAR)BaseArray[1]; + ComPort = 1; + PortInformation->BaseAddress = (ULONG)PortBase; + PortInformation->ComPort = ComPort; +#ifndef NDEBUG + sprintf (buffer, + "\nSerial port COM%ld found at 0x%lx\n", + ComPort, + (ULONG)PortBase); + HalDisplayString (buffer); +#endif /* NDEBUG */ + } + else + { + sprintf (buffer, + "\nKernel Debugger: No COM port found!!!\n\n"); + HalDisplayString (buffer); + return FALSE; + } + } + else + { + if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort])) + { + PortBase = (PUCHAR)BaseArray[PortInformation->ComPort]; + ComPort = PortInformation->ComPort; + PortInformation->BaseAddress = (ULONG)PortBase; +#ifndef NDEBUG + sprintf (buffer, + "\nSerial port COM%ld found at 0x%lx\n", + ComPort, + (ULONG)PortBase); + HalDisplayString (buffer); +#endif /* NDEBUG */ + } + else + { + sprintf (buffer, + "\nKernel Debugger: No serial port found!!!\n\n"); + HalDisplayString (buffer); + return FALSE; + } + } + + PortInitialized = TRUE; + } + + /* + * set baud rate and data format (8N1) + */ + + /* turn on DTR and RTS */ + WRITE_PORT_UCHAR (SER_MCR(PortBase), SR_MCR_DTR | SR_MCR_RTS); + + /* set DLAB */ + lcr = READ_PORT_UCHAR (SER_LCR(PortBase)) | SR_LCR_DLAB; + WRITE_PORT_UCHAR (SER_LCR(PortBase), lcr); + + /* set baud rate */ + divisor = 115200 / BaudRate; + WRITE_PORT_UCHAR (SER_DLL(PortBase), divisor & 0xff); + WRITE_PORT_UCHAR (SER_DLM(PortBase), (divisor >> 8) & 0xff); + + /* reset DLAB and set 8N1 format */ + WRITE_PORT_UCHAR (SER_LCR(PortBase), + SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO); + + /* read junk out of the RBR */ + lcr = READ_PORT_UCHAR (SER_RBR(PortBase)); + + /* + * set global info + */ + KdComPortInUse = (ULONG)PortBase; + + /* + * print message to blue screen + */ + sprintf (buffer, + "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n", + ComPort, + (ULONG)PortBase, + BaudRate); + + HalDisplayString (buffer); + + return TRUE; +} + + +/* HAL.KdPortInitializeEx */ +BOOLEAN +STDCALL +KdPortInitializeEx ( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; + PUCHAR ComPortBase; + char buffer[80]; + ULONG divisor; + BYTE lcr; + + if (PortInformation->BaudRate == 0) + { + PortInformation->BaudRate = DEFAULT_BAUD_RATE; + } + + if (PortInformation->ComPort == 0) + { + return FALSE; + } + else + { + if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort])) + { + ComPortBase = (PUCHAR)BaseArray[PortInformation->ComPort]; + PortInformation->BaseAddress = (ULONG)ComPortBase; +#ifndef NDEBUG + sprintf (buffer, + "\nSerial port COM%ld found at 0x%lx\n", + PortInformation->ComPort, + (ULONG)ComPortBase]; + HalDisplayString (buffer); +#endif /* NDEBUG */ + } + else + { + sprintf (buffer, + "\nKernel Debugger: Serial port not found!!!\n\n"); + HalDisplayString (buffer); + return FALSE; + } + } + + /* + * set baud rate and data format (8N1) + */ + + /* turn on DTR and RTS */ + WRITE_PORT_UCHAR (SER_MCR(ComPortBase), SR_MCR_DTR | SR_MCR_RTS); + + /* set DLAB */ + lcr = READ_PORT_UCHAR (SER_LCR(ComPortBase)) | SR_LCR_DLAB; + WRITE_PORT_UCHAR (SER_LCR(ComPortBase), lcr); + + /* set baud rate */ + divisor = 115200 / PortInformation->BaudRate; + WRITE_PORT_UCHAR (SER_DLL(ComPortBase), divisor & 0xff); + WRITE_PORT_UCHAR (SER_DLM(ComPortBase), (divisor >> 8) & 0xff); + + /* reset DLAB and set 8N1 format */ + WRITE_PORT_UCHAR (SER_LCR(ComPortBase), + SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO); + + /* read junk out of the RBR */ + lcr = READ_PORT_UCHAR (SER_RBR(ComPortBase)); + +#ifndef NDEBUG + + /* + * print message to blue screen + */ + sprintf (buffer, + "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n", + PortInformation->ComPort, + (ULONG)ComPortBase, + PortInformation->BaudRate); + + HalDisplayString (buffer); + +#endif /* NDEBUG */ + + return TRUE; +} + + +/* HAL.KdPortGetByte */ +BOOLEAN +STDCALL +KdPortGetByte ( + PUCHAR ByteRecieved + ) +{ + if (PortInitialized == FALSE) + return FALSE; + + if ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR)) + { + *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase)); + return TRUE; + } + + return FALSE; +} + + +/* HAL.KdPortGetByteEx */ +BOOLEAN +STDCALL +KdPortGetByteEx ( + PKD_PORT_INFORMATION PortInformation, + PUCHAR ByteRecieved + ) +{ + PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress; + + if ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR)) + { + *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase)); + return TRUE; + } + + return FALSE; +} + + +/* HAL.KdPortPollByte */ +BOOLEAN +STDCALL +KdPortPollByte ( + PUCHAR ByteRecieved + ) +{ + if (PortInitialized == FALSE) + return FALSE; + + while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR) == 0) + ; + + *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase)); + + return TRUE; +} + + +/* HAL.KdPortPollByteEx */ +BOOLEAN +STDCALL +KdPortPollByteEx ( + PKD_PORT_INFORMATION PortInformation, + PUCHAR ByteRecieved + ) +{ + PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress; + + while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR) == 0) + ; + + *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase)); + + return TRUE; +} + + + + +/* HAL.KdPortPutByte */ +VOID +STDCALL +KdPortPutByte ( + UCHAR ByteToSend + ) +{ + if (PortInitialized == FALSE) + return; + + while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_TBE) == 0) + ; + + WRITE_PORT_UCHAR (SER_THR(PortBase), ByteToSend); +} + +/* HAL.KdPortPutByteEx */ +VOID +STDCALL +KdPortPutByteEx ( + PKD_PORT_INFORMATION PortInformation, + UCHAR ByteToSend + ) +{ + PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress; + + while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_TBE) == 0) + ; + + WRITE_PORT_UCHAR (SER_THR(ComPortBase), ByteToSend); +} + + +/* HAL.KdPortRestore */ +VOID +STDCALL +KdPortRestore ( + VOID + ) +{ +} + + +/* HAL.KdPortSave */ +VOID +STDCALL +KdPortSave ( + VOID + ) +{ +} + + +/* HAL.KdPortDisableInterrupts */ +BOOLEAN +STDCALL +KdPortDisableInterrupts() +{ + UCHAR ch; + + if (PortInitialized == FALSE) + return FALSE; + + ch = READ_PORT_UCHAR (SER_MCR (PortBase)); + ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2)); + WRITE_PORT_UCHAR (SER_MCR (PortBase), ch); + + ch = READ_PORT_UCHAR (SER_IER (PortBase)); + ch &= (~SR_IER_ALL); + WRITE_PORT_UCHAR (SER_IER (PortBase), ch); + + return TRUE; +} + + +/* HAL.KdPortEnableInterrupts */ +BOOLEAN +STDCALL +KdPortEnableInterrupts() +{ + UCHAR ch; + + if (PortInitialized == FALSE) + return FALSE; + + ch = READ_PORT_UCHAR (SER_IER (PortBase)); + ch &= (~SR_IER_ALL); + ch |= SR_IER_ERDA; + WRITE_PORT_UCHAR (SER_IER (PortBase), ch); + + ch = READ_PORT_UCHAR (SER_MCR (PortBase)); + ch &= (~SR_MCR_LOOP); + ch |= (SR_MCR_OUT1 | SR_MCR_OUT2); + WRITE_PORT_UCHAR (SER_MCR (PortBase), ch); + + return TRUE; +} + +/* EOF */ diff --git a/hal/halx86/mbr.c b/hal/halx86/mbr.c new file mode 100644 index 0000000..5dc30a9 --- /dev/null +++ b/hal/halx86/mbr.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mbr.c + * PURPOSE: Functions for reading the master boot record (MBR) + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID HalExamineMBR(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG MBRTypeIdentifier, + PVOID Buffer) +{ + UNIMPLEMENTED; +} diff --git a/hal/halx86/mca.c b/hal/halx86/mca.c new file mode 100644 index 0000000..e9fa1d7 --- /dev/null +++ b/hal/halx86/mca.c @@ -0,0 +1,82 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/halx86/mca.c + * PURPOSE: Interfaces to the MicroChannel bus + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* + * TODO: + * What Adapter ID is read from an empty slot? + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS ****************************************************************/ + +ULONG STDCALL +HalpGetMicroChannelData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PCM_MCA_POS_DATA PosData = (PCM_MCA_POS_DATA)Buffer; + + DPRINT("HalpGetMicroChannelData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if ((BusNumber != 0) || + (SlotNumber == 0) || (SlotNumber > 8) || + (Length < sizeof(CM_MCA_POS_DATA))) + return(0); + + /* Enter Setup-Mode for given slot */ + WRITE_PORT_UCHAR((PUCHAR)0x96, ((UCHAR)(SlotNumber - 1) & 0x07) | 0x08); + + /* Read POS data */ + PosData->AdapterId = (READ_PORT_UCHAR((PUCHAR)0x101) << 8) + + READ_PORT_UCHAR((PUCHAR)0x100); + PosData->PosData1 = READ_PORT_UCHAR((PUCHAR)0x102); + PosData->PosData2 = READ_PORT_UCHAR((PUCHAR)0x103); + PosData->PosData3 = READ_PORT_UCHAR((PUCHAR)0x104); + PosData->PosData4 = READ_PORT_UCHAR((PUCHAR)0x105); + + /* Leave Setup-Mode for given slot */ + WRITE_PORT_UCHAR((PUCHAR)0x96, (UCHAR)(SlotNumber - 1) & 0x07); + + return(sizeof(CM_MCA_POS_DATA)); +} + +/* EOF */ diff --git a/hal/halx86/misc.c b/hal/halx86/misc.c new file mode 100644 index 0000000..c3e0b4d --- /dev/null +++ b/hal/halx86/misc.c @@ -0,0 +1,105 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/misc.c + * PURPOSE: Miscellaneous hardware functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +HalHandleNMI (ULONG Unused) +{ + UCHAR ucStatus; + + ucStatus = READ_PORT_UCHAR((PUCHAR) 0x61); + + HalDisplayString ("\n*** Hardware Malfunction\n\n"); + HalDisplayString ("Call your hardware vendor for support\n\n"); + + if (ucStatus & 0x80) + HalDisplayString ("NMI: Parity Check / Memory Parity Error\n"); + + if (ucStatus & 0x40) + HalDisplayString ("NMI: Channel Check / IOCHK\n"); + + HalDisplayString ("\n*** The system has halted ***\n"); + KeEnterKernelDebugger (); +} + +VOID STDCALL +HalProcessorIdle (VOID) +{ +#if 1 + __asm__("sti\n\t" \ + "hlt\n\t"); +#else + +#endif +} + +VOID STDCALL +HalRequestIpi(ULONG Unknown) +{ + return; +} + +ULONG FASTCALL +HalSystemVectorDispatchEntry ( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3 + ) +{ + return 0; +} + +VOID STDCALL +KeFlushWriteBuffer ( + VOID + ) +{ + return; +} + +VOID STDCALL +HalReportResourceUsage ( + VOID + ) +{ + /* + * FIXME: Report all resources used by hal. + * Calls IoReportHalResourceUsage() + */ + + /* + * Initialize PCI bus. + */ + HalpInitPciBus (); +#if 0 + /* + * Initialize IsaPnP bus. + */ + HalpInitIsaPnpBus (); + + /* + * Initialize other busses??? + */ + + /* + * Probe for a BIOS32 extension + */ + Hal_bios32_probe(); +#endif + + return; +} + +/* EOF */ diff --git a/hal/halx86/mp.c b/hal/halx86/mp.c new file mode 100644 index 0000000..608f6d7 --- /dev/null +++ b/hal/halx86/mp.c @@ -0,0 +1,2367 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mp.c + * PURPOSE: Intel MultiProcessor specification support + * PROGRAMMER: David Welch (welch@cwcom.net) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: Parts adapted from linux SMP code + * UPDATE HISTORY: + * 22/05/1998 DW Created + * 12/04/2001 CSH Added MultiProcessor specification support + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#ifdef MP + +#include +#include + +#include +#include +#include +#include + +/* + Address of area to be used for communication between Application + Processors (APs) and the BootStrap Processor (BSP) + */ +#define COMMON_AREA 0x2000 + +#define BIOS_AREA 0x0 + +typedef struct __attribute__((packed)) _COMMON_AREA_INFO +{ + ULONG Stack; /* Location of AP stack */ + ULONG Debug[16]; /* For debugging */ +} COMMON_AREA_INFO, *PCOMMON_AREA_INFO; + +CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */ +ULONG CPUCount; /* Total number of CPUs */ +ULONG OnlineCPUs; /* Bitmask of online CPUs */ + +UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */ +UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */ + +IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */ +ULONG IOAPICCount; /* Number of I/O APICs in the system */ + +MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */ +ULONG IRQVectorMap[MAX_IRQ_SOURCE]; /* IRQ to vector map */ +ULONG IRQCount; /* Number of IRQs */ + +ULONG APICMode; /* APIC mode at startup */ +ULONG BootCPU; /* Bootstrap processor */ +ULONG NextCPU; /* Next CPU to start */ +PULONG BIOSBase; /* Virtual address of BIOS data segment */ +PULONG APICBase; /* Virtual address of local APIC */ +PULONG CommonBase; /* Virtual address of common area */ + +extern CHAR *APstart, *APend; +extern VOID (*APflush)(VOID); + +extern VOID MpsTimerInterrupt(VOID); +extern VOID MpsErrorInterrupt(VOID); +extern VOID MpsSpuriousInterrupt(VOID); + +#define CMOS_READ(address) ({ \ + WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \ + READ_PORT_UCHAR((PUCHAR)0x71)); \ +}) + +#define CMOS_WRITE(address, value) ({ \ + WRITE_PORT_UCHAR((PUCHAR)0x70, address); \ + WRITE_PORT_UCHAR((PUCHAR)0x71, value); \ +}) + +BOOLEAN MPSInitialized = FALSE; /* Is the MP system initialized? */ + +VOID APICDisable(VOID); +static VOID APICSyncArbIDs(VOID); + +/* For debugging */ +ULONG lastregr = 0; +ULONG lastvalr = 0; +ULONG lastregw = 0; +ULONG lastvalw = 0; + +#endif /* MP */ + + +BOOLEAN BSPInitialized = FALSE; /* Is the BSP initialized? */ + + +/* FUNCTIONS *****************************************************************/ + +#ifdef MP + +/* Functions for handling 8259A PICs */ + +VOID Disable8259AIrq( + ULONG irq) +{ + ULONG tmp; + + if (irq & 8) { + tmp = READ_PORT_UCHAR((PUCHAR)0xA1); + tmp |= (1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp); + } else { + tmp = READ_PORT_UCHAR((PUCHAR)0x21); + tmp |= (1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0x21, tmp); + } +} + + +VOID Enable8259AIrq( + ULONG irq) +{ + ULONG tmp; + + if (irq & 8) { + tmp = READ_PORT_UCHAR((PUCHAR)0xA1); + tmp &= ~(1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp); + } else { + tmp = READ_PORT_UCHAR((PUCHAR)0x21); + tmp &= ~(1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0x21, tmp); + } +} + + +/* Functions for handling I/O APICs */ + +volatile ULONG IOAPICRead( + ULONG Apic, + ULONG Offset) +{ + PULONG Base; + + Base = (PULONG)IOAPICMap[Apic].ApicAddress; + + *Base = Offset; + return *((PULONG)((ULONG)Base + IOAPIC_IOWIN)); +} + + +VOID IOAPICWrite( + ULONG Apic, + ULONG Offset, + ULONG Value) +{ + PULONG Base; + + Base = (PULONG)IOAPICMap[Apic].ApicAddress; + + *Base = Offset; + *((PULONG)((ULONG)Base + IOAPIC_IOWIN)) = Value; +} + + +VOID IOAPICClearPin( + ULONG Apic, + ULONG Pin) +{ + IOAPIC_ROUTE_ENTRY Entry; + + /* + * Disable it in the IO-APIC irq-routing table + */ + memset(&Entry, 0, sizeof(Entry)); + Entry.mask = 1; + IOAPICWrite(Apic, IOAPIC_REDTBL + 2 * Pin, *(((PULONG)&Entry) + 0)); + IOAPICWrite(Apic, IOAPIC_REDTBL + 1 + 2 * Pin, *(((PULONG)&Entry) + 1)); +} + +static VOID IOAPICClear( + ULONG Apic) +{ + ULONG Pin; + + for (Pin = 0; Pin < IOAPICMap[Apic].EntryCount; Pin++) + IOAPICClearPin(Apic, Pin); +} + +static VOID IOAPICClearAll( + VOID) +{ + ULONG Apic; + + for (Apic = 0; Apic < IOAPICCount; Apic++) + IOAPICClear(Apic); +} + +/* This is performance critical and should probably be done in assembler */ +VOID IOAPICMaskIrq( + ULONG Apic, + ULONG Irq) +{ + IOAPIC_ROUTE_ENTRY Entry; + + *((PULONG)&Entry) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq); + Entry.mask = 1; + IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *((PULONG)&Entry)); +} + + +/* This is performance critical and should probably be done in assembler */ +VOID IOAPICUnmaskIrq( + ULONG Apic, + ULONG Irq) +{ + IOAPIC_ROUTE_ENTRY Entry; + + *((PULONG)&Entry) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq); + Entry.mask = 0; + IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *((PULONG)&Entry)); +} + +static VOID +IOAPICSetupIds(VOID) +{ + ULONG tmp, apic, i; + UCHAR old_id; + + /* + * Set the IOAPIC ID to the value stored in the MPC table. + */ + for (apic = 0; apic < IOAPICCount; apic++) { + + /* Read the register 0 value */ + tmp = IOAPICRead(apic, IOAPIC_ID); + + old_id = IOAPICMap[apic].ApicId; + + if (IOAPICMap[apic].ApicId >= 0xf) { + DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", + apic, IOAPICMap[apic].ApicId); + DPRINT1("... fixing up to %d. (tell your hw vendor)\n", + GET_IOAPIC_ID(tmp)); + IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp); + } + + /* + * We need to adjust the IRQ routing table + * if the ID changed. + */ + if (old_id != IOAPICMap[apic].ApicId) + for (i = 0; i < IRQCount; i++) + if (IRQMap[i].DstApicId == old_id) + IRQMap[i].DstApicId = IOAPICMap[apic].ApicId; + + /* + * Read the right value from the MPC table and + * write it into the ID register. + */ + DPRINT("Changing IO-APIC physical APIC ID to %d\n", + IOAPICMap[apic].ApicId); + + tmp &= ~IOAPIC_ID_MASK; + tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId); + + IOAPICWrite(apic, IOAPIC_ID, tmp); + + /* + * Sanity check + */ + tmp = IOAPICRead(apic, 0); + if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId) { + DPRINT1("Could not set I/O APIC ID!\n"); + KeBugCheck(0); + } + } +} + + +/* + * EISA Edge/Level control register, ELCR + */ +static ULONG EISA_ELCR( + ULONG irq) +{ + if (irq < 16) { + PUCHAR port = (PUCHAR)(0x4d0 + (irq >> 3)); + return (READ_PORT_UCHAR(port) >> (irq & 7)) & 1; + } + DPRINT("Broken MPtable reports ISA irq %d\n", irq); + return 0; +} + +/* EISA interrupts are always polarity zero and can be edge or level + * trigger depending on the ELCR value. If an interrupt is listed as + * EISA conforming in the MP table, that means its trigger type must + * be read in from the ELCR */ + +#define default_EISA_trigger(idx) (EISA_ELCR(IRQMap[idx].SrcBusIrq)) +#define default_EISA_polarity(idx) (0) + +/* ISA interrupts are always polarity zero edge triggered, + * when listed as conforming in the MP table. */ + +#define default_ISA_trigger(idx) (0) +#define default_ISA_polarity(idx) (0) + +/* PCI interrupts are always polarity one level triggered, + * when listed as conforming in the MP table. */ + +#define default_PCI_trigger(idx) (1) +#define default_PCI_polarity(idx) (1) + +/* MCA interrupts are always polarity zero level triggered, + * when listed as conforming in the MP table. */ + +#define default_MCA_trigger(idx) (1) +#define default_MCA_polarity(idx) (0) + +static ULONG IRQPolarity( + ULONG idx) +{ + ULONG bus = IRQMap[idx].SrcBusId; + ULONG polarity; + + /* + * Determine IRQ line polarity (high active or low active): + */ + switch (IRQMap[idx].IrqFlag & 3) + { + case 0: /* conforms, ie. bus-type dependent polarity */ + { + switch (BUSMap[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + { + polarity = default_ISA_polarity(idx); + break; + } + case MP_BUS_EISA: /* EISA pin */ + { + polarity = default_EISA_polarity(idx); + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + polarity = default_PCI_polarity(idx); + break; + } + case MP_BUS_MCA: /* MCA pin */ + { + polarity = default_MCA_polarity(idx); + break; + } + default: + { + DPRINT("Broken BIOS!!\n"); + polarity = 1; + break; + } + } + break; + } + case 1: /* high active */ + { + polarity = 0; + break; + } + case 2: /* reserved */ + { + DPRINT("Broken BIOS!!\n"); + polarity = 1; + break; + } + case 3: /* low active */ + { + polarity = 1; + break; + } + default: /* invalid */ + { + DPRINT("Broken BIOS!!\n"); + polarity = 1; + break; + } + } + return polarity; +} + +static ULONG IRQTrigger( + ULONG idx) +{ + ULONG bus = IRQMap[idx].SrcBusId; + ULONG trigger; + + /* + * Determine IRQ trigger mode (edge or level sensitive): + */ + switch ((IRQMap[idx].IrqFlag >> 2) & 3) + { + case 0: /* conforms, ie. bus-type dependent */ + { + switch (BUSMap[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + { + trigger = default_ISA_trigger(idx); + break; + } + case MP_BUS_EISA: /* EISA pin */ + { + trigger = default_EISA_trigger(idx); + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + trigger = default_PCI_trigger(idx); + break; + } + case MP_BUS_MCA: /* MCA pin */ + { + trigger = default_MCA_trigger(idx); + break; + } + default: + { + DPRINT("Broken BIOS!!\n"); + trigger = 1; + break; + } + } + break; + } + case 1: /* edge */ + { + trigger = 0; + break; + } + case 2: /* reserved */ + { + DPRINT("Broken BIOS!!\n"); + trigger = 1; + break; + } + case 3: /* level */ + { + trigger = 1; + break; + } + default: /* invalid */ + { + DPRINT("Broken BIOS!!\n"); + trigger = 0; + break; + } + } + return trigger; +} + + +static ULONG Pin2Irq( + ULONG idx, + ULONG apic, + ULONG pin) +{ + ULONG irq, i; + ULONG bus = IRQMap[idx].SrcBusId; + + /* + * Debugging check, we are in big trouble if this message pops up! + */ + if (IRQMap[idx].DstApicInt != pin) { + DPRINT("broken BIOS or MPTABLE parser, ayiee!!\n"); + } + + switch (BUSMap[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + case MP_BUS_EISA: + case MP_BUS_MCA: + { + irq = IRQMap[idx].SrcBusIrq; + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + /* + * PCI IRQs are mapped in order + */ + i = irq = 0; + while (i < apic) + irq += IOAPICMap[i++].EntryCount; + irq += pin; + break; + } + default: + { + DPRINT("Unknown bus type %d.\n",bus); + irq = 0; + break; + } + } + + return irq; +} + + +/* + * Rough estimation of how many shared IRQs there are, can + * be changed anytime. + */ +#define MAX_PLUS_SHARED_IRQS PIC_IRQS +#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + PIC_IRQS) + +/* + * This is performance-critical, we want to do it O(1) + * + * the indexing order of this array favors 1:1 mappings + * between pins and IRQs. + */ + +static struct irq_pin_list { + ULONG apic, pin, next; +} irq_2_pin[PIN_MAP_SIZE]; + +/* + * The common case is 1:1 IRQ<->pin mappings. Sometimes there are + * shared ISA-space IRQs, so we have to support them. We are super + * fast in the common case, and fast for shared ISA-space IRQs. + */ +static VOID AddPinToIrq( + ULONG irq, + ULONG apic, + ULONG pin) +{ + static ULONG first_free_entry = PIC_IRQS; + struct irq_pin_list *entry = irq_2_pin + irq; + + while (entry->next) + entry = irq_2_pin + entry->next; + + if (entry->pin != -1) { + entry->next = first_free_entry; + entry = irq_2_pin + entry->next; + if (++first_free_entry >= PIN_MAP_SIZE) { + DPRINT1("Ohh no!"); + KeBugCheck(0); + } + } + entry->apic = apic; + entry->pin = pin; +} + + +/* + * Find the IRQ entry number of a certain pin. + */ +static ULONG IOAPICGetIrqEntry( + ULONG apic, + ULONG pin, + ULONG type) +{ + ULONG i; + + for (i = 0; i < IRQCount; i++) + if (IRQMap[i].IrqType == type && + (IRQMap[i].DstApicId == IOAPICMap[apic].ApicId || + IRQMap[i].DstApicId == MP_APIC_ALL) && + IRQMap[i].DstApicInt == pin) + return i; + + return -1; +} + + +static ULONG AssignIrqVector( + ULONG irq) +{ + static ULONG current_vector = FIRST_DEVICE_VECTOR, vector_offset = 0; + ULONG vector; + + /* There may already have been assigned a vector for this IRQ */ + vector = IRQVectorMap[irq]; + if (vector > 0) + return vector; + + current_vector += 8; + if (current_vector > FIRST_SYSTEM_VECTOR) { + vector_offset++; + current_vector = FIRST_DEVICE_VECTOR + vector_offset; + } else if (current_vector == FIRST_SYSTEM_VECTOR) { + DPRINT1("Ran out of interrupt sources!"); + KeBugCheck(0); + } + + IRQVectorMap[irq] = current_vector; + return current_vector; +} + + +VOID IOAPICSetupIrqs( + VOID) +{ + IOAPIC_ROUTE_ENTRY entry; + ULONG apic, pin, idx, irq, first_notcon = 1, vector; + + DPRINT("Init IO_APIC IRQs\n"); + + for (apic = 0; apic < IOAPICCount; apic++) { + for (pin = 0; pin < IOAPICMap[apic].EntryCount; pin++) { + + /* + * add it to the IO-APIC irq-routing table + */ + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = APIC_DM_LOWEST; + entry.dest_mode = 1; /* logical delivery */ + entry.mask = 0; /* enable IRQ */ + entry.dest.logical.logical_dest = OnlineCPUs; + + idx = IOAPICGetIrqEntry(apic,pin,INT_VECTORED); + if (idx == -1) { + if (first_notcon) { + DPRINT(" IO-APIC (apicid-pin) %d-%d\n", IOAPICMap[apic].ApicId, pin); + first_notcon = 0; + } else { + DPRINT(", %d-%d\n", IOAPICMap[apic].ApicId, pin); + } + continue; + } + + entry.trigger = IRQTrigger(idx); + entry.polarity = IRQPolarity(idx); + + if (entry.trigger) { + entry.trigger = 1; + entry.mask = 1; + entry.dest.logical.logical_dest = OnlineCPUs; + } + + irq = Pin2Irq(idx, apic, pin); + AddPinToIrq(irq, apic, pin); + + vector = AssignIrqVector(irq); + entry.vector = vector; + + if (irq == 0) + { + /* Mask timer IRQ */ + entry.mask = 1; + } + + if ((apic == 0) && (irq < 16)) + Disable8259AIrq(irq); + + IOAPICWrite(apic, IOAPIC_REDTBL+2*pin+1, *(((PULONG)&entry)+1)); + IOAPICWrite(apic, IOAPIC_REDTBL+2*pin, *(((PULONG)&entry)+0)); + } + } +} + + +static VOID IOAPICEnable( + VOID) +{ + ULONG i, tmp; + + for (i = 0; i < PIN_MAP_SIZE; i++) { + irq_2_pin[i].pin = -1; + irq_2_pin[i].next = 0; + } + + /* + * The number of IO-APIC IRQ registers (== #pins): + */ + for (i = 0; i < IOAPICCount; i++) { + tmp = IOAPICRead(i, IOAPIC_VER); + IOAPICMap[i].EntryCount = GET_IOAPIC_MRE(tmp) + 1; + } + + /* + * Do not trust the IO-APIC being empty at bootup + */ + IOAPICClearAll(); +} + +#if 0 +static VOID IOAPICDisable( + VOID) +{ + /* + * Clear the IO-APIC before rebooting + */ + IOAPICClearAll(); + + APICDisable(); +} +#endif + + +static VOID IOAPICSetup( + VOID) +{ + IOAPICEnable(); + IOAPICSetupIds(); + if (0) { + // FIXME: This causes application processors to not boot if asked to + APICSyncArbIDs(); + } + IOAPICSetupIrqs(); +} + + +VOID IOAPICDump(VOID) +{ + ULONG apic, i; + ULONG reg0, reg1, reg2; + + DbgPrint("Number of MP IRQ sources: %d.\n", IRQCount); + for (i = 0; i < IOAPICCount; i++) { + DbgPrint("Number of IO-APIC #%d registers: %d.\n", + IOAPICMap[i].ApicId, + IOAPICMap[i].EntryCount); + } + + /* + * We are a bit conservative about what we expect. We have to + * know about every hardware change ASAP. + */ + DbgPrint("Testing the IO APIC.......................\n"); + + for (apic = 0; apic < IOAPICCount; apic++) { + + reg0 = IOAPICRead(apic, IOAPIC_ID); + reg1 = IOAPICRead(apic, IOAPIC_VER); + if (GET_IOAPIC_VERSION(reg1) >= 0x10) { + reg2 = IOAPICRead(apic, IOAPIC_ARB); + } + + DbgPrint("\n"); + DbgPrint("IO APIC #%d......\n", IOAPICMap[apic].ApicId); + DbgPrint(".... register #00: %08X\n", reg0); + DbgPrint("....... : physical APIC id: %02X\n", GET_IOAPIC_ID(reg0)); + if (reg0 & 0xF0FFFFFF) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + DbgPrint(".... register #01: %08X\n", reg1); + i = GET_IOAPIC_MRE(reg1); + + DbgPrint("....... : max redirection entries: %04X\n", i); + if ((i != 0x0f) && /* older (Neptune) boards */ + (i != 0x17) && /* typical ISA+PCI boards */ + (i != 0x1b) && /* Compaq Proliant boards */ + (i != 0x1f) && /* dual Xeon boards */ + (i != 0x22) && /* bigger Xeon boards */ + (i != 0x2E) && + (i != 0x3F)) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + i = GET_IOAPIC_VERSION(reg1); + DbgPrint("....... : IO APIC version: %04X\n", i); + if ((i != 0x01) && /* 82489DX IO-APICs */ + (i != 0x10) && /* oldest IO-APICs */ + (i != 0x11) && /* Pentium/Pro IO-APICs */ + (i != 0x13)) { /* Xeon IO-APICs */ + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + if (reg1 & 0xFF00FF00) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + if (GET_IOAPIC_VERSION(reg1) >= 0x10) { + DbgPrint(".... register #02: %08X\n", reg2); + DbgPrint("....... : arbitration: %02X\n", + GET_IOAPIC_ARB(reg2)); + if (reg2 & 0xF0FFFFFF) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + } + + DbgPrint(".... IRQ redirection table:\n"); + DbgPrint(" NR Log Phy Mask Trig IRR Pol" + " Stat Dest Deli Vect: \n"); + + for (i = 0; i <= GET_IOAPIC_MRE(reg1); i++) { + IOAPIC_ROUTE_ENTRY entry; + + *(((PULONG)&entry)+0) = IOAPICRead(apic, 0x10+i*2); + *(((PULONG)&entry)+1) = IOAPICRead(apic, 0x11+i*2); + + DbgPrint(" %02x %03X %02X ", + i, + entry.dest.logical.logical_dest, + entry.dest.physical.physical_dest + ); + + DbgPrint("%C %C %1d %C %C %C %03X %02X\n", + (entry.mask == 0) ? 'U' : 'M', // Unmasked/masked + (entry.trigger == 0) ? 'E' : 'L', // Edge/level sensitive + entry.irr, + (entry.polarity == 0) ? 'H' : 'L', // Active high/active low + (entry.delivery_status == 0) ? 'I' : 'S', // Idle / send pending + (entry.dest_mode == 0) ? 'P' : 'L', // Physical logical + entry.delivery_mode, + entry.vector + ); + } + } + DbgPrint("IRQ to pin mappings:\n"); + for (i = 0; i < PIC_IRQS; i++) { + struct irq_pin_list *entry = irq_2_pin + i; + if (entry->pin < 0) + continue; + DbgPrint("IRQ%d ", i); + for (;;) { + DbgPrint("-> %d", entry->pin); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } + if (i % 2) { + DbgPrint("\n"); + } else { + DbgPrint(" "); + } + } + + DbgPrint(".................................... done.\n"); +} + + + +/* Functions for handling local APICs */ + +#if 0 +volatile inline ULONG APICRead( + ULONG Offset) +{ + PULONG p; + + p = (PULONG)((ULONG)APICBase + Offset); + return *p; +} +#else +volatile inline ULONG APICRead( + ULONG Offset) +{ + PULONG p; + + lastregr = Offset; + lastvalr = 0; + + //DPRINT1("R(0x%X)", Offset); + p = (PULONG)((ULONG)APICBase + Offset); + lastvalr = *p; + //DPRINT1("(0x%08X)\n", *p); + + return lastvalr; +} +#endif + +#if 0 +inline VOID APICWrite( + ULONG Offset, + ULONG Value) +{ + PULONG p; + + p = (PULONG)((ULONG)APICBase + Offset); + + *p = Value; +} +#else +inline VOID APICWrite( + ULONG Offset, + ULONG Value) +{ + PULONG p; + + lastregw = Offset; + lastvalw = Value; + + //DPRINT1("W(0x%X, 0x%08X)\n", Offset, Value); + p = (PULONG)((ULONG)APICBase + Offset); + + *p = Value; +} +#endif + + +inline VOID APICSendEOI(VOID) +{ + // Dummy read + APICRead(APIC_SIVR); + // Send the EOI + APICWrite(APIC_EOI, 0); +} + + +VOID DumpESR(VOID) +{ + ULONG tmp; + + if (CPUMap[ThisCPU()].MaxLVT > 3) + APICWrite(APIC_ESR, 0); + tmp = APICRead(APIC_ESR); + DbgPrint("ESR %08x\n", tmp); +} + + +ULONG APICGetMaxLVT(VOID) +{ + ULONG tmp, ver, maxlvt; + + tmp = APICRead(APIC_VER); + ver = GET_APIC_VERSION(tmp); + /* 82489DXs do not report # of LVT entries. */ + maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(tmp) : 2; + + return maxlvt; +} + + +static VOID APICClear( + VOID) +{ + ULONG tmp, maxlvt; + + maxlvt = CPUMap[ThisCPU()].MaxLVT; + + /* + * Careful: we have to set masks only first to deassert + * any level-triggered sources. + */ + tmp = APICRead(APIC_LVTT); + APICWrite(APIC_LVTT, tmp | APIC_LVT_MASKED); + + tmp = APICRead(APIC_LINT0); + APICWrite(APIC_LINT0, tmp | APIC_LVT_MASKED); + + tmp = APICRead(APIC_LINT1); + APICWrite(APIC_LINT1, tmp | APIC_LVT_MASKED); + + if (maxlvt >= 3) { + tmp = APICRead(APIC_LVT3); + APICWrite(APIC_LVT3, tmp | APIC_LVT3_MASKED); + } + + if (maxlvt >= 4) { + tmp = APICRead(APIC_LVTPC); + APICWrite(APIC_LVTPC, tmp | APIC_LVT_MASKED); + } + + /* + * Clean APIC state for other OSs: + */ + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LVTT, APIC_LVT_MASKED); + + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LINT0, APIC_LVT_MASKED); + + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LINT1, APIC_LVT_MASKED); + + if (maxlvt >= 3) { + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LVT3, APIC_LVT3_MASKED); + } + + if (maxlvt >= 4) { + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LVTPC, APIC_LVT_MASKED); + } +} + +/* Enable symetric I/O mode ie. connect the BSP's + local APIC to INT and NMI lines */ +inline VOID EnableSMPMode( + VOID) +{ + /* + * Do not trust the local APIC being empty at bootup. + */ + APICClear(); + + WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70); + WRITE_PORT_UCHAR((PUCHAR)0x23, 0x01); +} + + +/* Disable symetric I/O mode ie. go to PIC mode */ +inline VOID DisableSMPMode( + VOID) +{ + /* + * Put the board back into PIC mode (has an effect + * only on certain older boards). Note that APIC + * interrupts, including IPIs, won't work beyond + * this point! The only exception are INIT IPIs. + */ + WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70); + WRITE_PORT_UCHAR((PUCHAR)0x23, 0x00); +} + + +VOID APICDisable( + VOID) +{ + ULONG tmp; + + APICClear(); + + /* + * Disable APIC (implies clearing of registers for 82489DX!). + */ + tmp = APICRead(APIC_SIVR); + tmp &= ~APIC_SIVR_ENABLE; + APICWrite(APIC_SIVR, tmp); +} + + +inline ULONG ThisCPU( + VOID) +{ + return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24; +} + + +static VOID APICDumpBit(ULONG base) +{ + ULONG v, i, j; + + DbgPrint("0123456789abcdef0123456789abcdef\n"); + for (i = 0; i < 8; i++) { + APICRead(base + i*0x10); + for (j = 0; j < 32; j++) { + if (v & (1< 3) /* Due to the Pentium erratum 3AP. */ + APICWrite(APIC_ESR, 0); + v = APICRead(APIC_ESR); + DbgPrint("... ESR : %08x\n", v); + } + + v = APICRead(APIC_ICR0); + DbgPrint("... ICR0 : %08x ! ", v); + v = APICRead(APIC_ICR1); + DbgPrint("... ICR1 : %08x ! ", v); + + v = APICRead(APIC_LVTT); + DbgPrint("... LVTT : %08x\n", v); + + if (maxlvt > 3) { /* PC is LVT#4. */ + v = APICRead(APIC_LVTPC); + DbgPrint("... LVTPC : %08x ! ", v); + } + v = APICRead(APIC_LINT0); + DbgPrint("... LINT0 : %08x ! ", v); + v = APICRead(APIC_LINT1); + DbgPrint("... LINT1 : %08x\n", v); + + if (maxlvt > 2) { + v = APICRead(APIC_LVT3); + DbgPrint("... LVT3 : %08x\n", v); + } + + v = APICRead(APIC_ICRT); + DbgPrint("... ICRT : %08x ! ", v); + v = APICRead(APIC_CCRT); + DbgPrint("... CCCT : %08x ! ", v); + v = APICRead(APIC_TDCR); + DbgPrint("... TDCR : %08x\n", v); + DbgPrint("\n"); + DbgPrint("Last register read (offset): 0x%08X\n", r1); + DbgPrint("Last register read (value): 0x%08X\n", r2); + DbgPrint("Last register written (offset): 0x%08X\n", w1); + DbgPrint("Last register written (value): 0x%08X\n", w2); + DbgPrint("\n"); +} + + +ULONG Read8254Timer(VOID) +{ + ULONG Count; + + WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00); + Count = READ_PORT_UCHAR((PUCHAR)0x40); + Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8; + + return Count; +} + + +VOID WaitFor8254Wraparound(VOID) +{ + ULONG CurCount, PrevCount = ~0; + LONG Delta; + + CurCount = Read8254Timer(); + + do { + PrevCount = CurCount; + CurCount = Read8254Timer(); + Delta = CurCount - PrevCount; + + /* + * This limit for delta seems arbitrary, but it isn't, it's + * slightly above the level of error a buggy Mercury/Neptune + * chipset timer can cause. + */ + + } while (Delta < 300); +} + +#define HZ (100) +#define APIC_DIVISOR (16) + +VOID APICSetupLVTT( + ULONG ClockTicks) +{ + ULONG tmp; + + /* Periodic timer */ + tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | + APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR; + APICWrite(APIC_LVTT, tmp); + + tmp = APICRead(APIC_TDCR); + tmp &= ~(APIC_TDCR_1 | APIC_TDCR_TMBASE | APIC_TDCR_16); + APICWrite(APIC_TDCR, tmp); + APICWrite(APIC_ICRT, ClockTicks / APIC_DIVISOR); +} + + +VOID APICCalibrateTimer( + ULONG CPU) +{ + ULARGE_INTEGER t1, t2; + LONG tt1, tt2; + + DPRINT("Calibrating APIC timer...\n"); + + APICSetupLVTT(~0); + + /* + * The timer chip counts down to zero. Let's wait + * for a wraparound to start exact measurement: + * (the current tick might have been already half done) + */ + WaitFor8254Wraparound(); + + /* + * We wrapped around just now. Let's start + */ + ReadPentiumClock(&t1); + tt1 = APICRead(APIC_CCRT); + + WaitFor8254Wraparound(); + + tt2 = APICRead(APIC_CCRT); + ReadPentiumClock(&t2); + + CPUMap[CPU].BusSpeed = (HZ * (tt2 - tt1) * APIC_DIVISOR); + CPUMap[CPU].CoreSpeed = (HZ * (t2.QuadPart - t1.QuadPart)); + + /* Setup timer for normal operation */ + //APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100); // 100ns + APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 15000); // 15ms + //APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100000); // 100ms + + DPRINT("CPU clock speed is %ld.%04ld MHz.\n", + CPUMap[CPU].CoreSpeed/1000000, + CPUMap[CPU].CoreSpeed%1000000); + + DPRINT("Host bus clock speed is %ld.%04ld MHz.\n", + CPUMap[CPU].BusSpeed/1000000, + CPUMap[CPU].BusSpeed%1000000); +} + + +static VOID APICSleep( + ULONG Count) +/* + PARAMETERS: + Count = Number of microseconds to busy wait + */ +{ + KeStallExecutionProcessor(Count); +} + + +static VOID APICSyncArbIDs( + VOID) +{ + ULONG i, tmp; + + /* Wait up to 100ms for the APIC to become ready */ + for (i = 0; i < 10000; i++) { + tmp = APICRead(APIC_ICR0); + /* Check Delivery Status */ + if ((tmp & APIC_ICR0_DS) == 0) + break; + APICSleep(10); + } + + if (i == 10000) { + DPRINT("CPU(%d) APIC busy for 100ms.\n", ThisCPU()); + } + + DPRINT("Synchronizing Arb IDs.\n"); + APICWrite(APIC_ICR0, APIC_ICR0_DESTS_ALL | APIC_ICR0_LEVEL | APIC_DM_INIT); +} + + +VOID APICSendIPI( + ULONG Target, + ULONG DeliveryMode, + ULONG IntNum, + ULONG Level) +{ + ULONG tmp, i, flags; + + pushfl(flags); + __asm__ ("\n\tcli\n\t"); + + /* Wait up to 100ms for the APIC to become ready */ + for (i = 0; i < 10000; i++) { + tmp = APICRead(APIC_ICR0); + /* Check Delivery Status */ + if ((tmp & APIC_ICR0_DS) == 0) + break; + APICSleep(10); + } + + if (i == 10000) { + DPRINT("CPU(%d) Previous IPI was not delivered after 100ms.\n", ThisCPU()); + } + + /* Setup the APIC to deliver the IPI */ + tmp = APICRead(APIC_ICR1); + tmp &= 0x00FFFFFF; + APICWrite(APIC_ICR1, tmp | SET_APIC_DEST_FIELD(Target)); + + tmp = APICRead(APIC_ICR0); + tmp &= ~(APIC_ICR0_LEVEL | APIC_ICR0_DESTM | APIC_ICR0_DM | APIC_ICR0_VECTOR); + tmp |= (DeliveryMode | IntNum | Level); + + if (Target == APIC_TARGET_SELF) { + tmp |= APIC_ICR0_DESTS_SELF; + } else if (Target == APIC_TARGET_ALL) { + tmp |= APIC_ICR0_DESTS_ALL; + } else if (Target == APIC_TARGET_ALL_BUT_SELF) { + tmp |= APIC_ICR0_DESTS_ALL_BUT_SELF; + } else { + tmp |= APIC_ICR0_DESTS_FIELD; + } + + /* Now, fire off the IPI */ + APICWrite(APIC_ICR0, tmp); + + popfl(flags); +} + + +BOOLEAN VerifyLocalAPIC( + VOID) +{ + UINT reg0, reg1; + + /* The version register is read-only in a real APIC */ + reg0 = APICRead(APIC_VER); + APICWrite(APIC_VER, reg0 ^ APIC_VER_MASK); + reg1 = APICRead(APIC_VER); + + if (reg1 != reg0) + return FALSE; + + /* The ID register is read/write in a real APIC */ + reg0 = APICRead(APIC_ID); + APICWrite(APIC_ID, reg0 ^ APIC_ID_MASK); + reg1 = APICRead(APIC_ID); + APICWrite(APIC_ID, reg0); + if (reg1 != (reg0 ^ APIC_ID_MASK)) + return FALSE; + + return TRUE; +} + + +static VOID SetInterruptGate( + ULONG index, + ULONG address) +{ + IDT_DESCRIPTOR *idt; + + idt = (IDT_DESCRIPTOR*)((ULONG)KeGetCurrentKPCR()->IDT + index * sizeof(IDT_DESCRIPTOR)); + idt->a = (((ULONG)address)&0xffff) + (KERNEL_CS << 16); + idt->b = 0x8f00 + (((ULONG)address)&0xffff0000); +} + + +VOID MpsTimerHandler( + VOID) +{ +#if 0 + KIRQL OldIrql; +#endif + + DPRINT("T1"); + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); +#if 0 + /* + * Notify the rest of the kernel of the raised irq level + */ + OldIrql = KeRaiseIrqlToSynchLevel(); +#endif + __asm__("sti\n\t"); + + /* + * Call the dispatcher + */ + PsDispatchThread(THREAD_STATE_RUNNABLE); + +#if 0 + /* + * Lower irq level + */ + KeLowerIrql(OldIrql); +#endif +} + + +VOID MpsErrorHandler( + VOID) +{ + ULONG tmp1, tmp2; + + APICDump(); + + tmp1 = APICRead(APIC_ESR); + APICWrite(APIC_ESR, 0); + tmp2 = APICRead(APIC_ESR); + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); + + /* Here is what the APIC error bits mean: + 0: Send CS error + 1: Receive CS error + 2: Send accept error + 3: Receive accept error + 4: Reserved + 5: Send illegal vector + 6: Received illegal vector + 7: Illegal register address + */ + DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2); + for (;;); +} + + +VOID MpsSpuriousHandler( + VOID) +{ + DPRINT1("Spurious interrupt on CPU(%d)\n", ThisCPU()); + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); + APICDump(); + for (;;); +} + + +VOID APICSetup( + VOID) +{ + ULONG CPU, tmp; + + CPU = ThisCPU(); + + /* + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ + + /* + * Put the APIC into flat delivery mode. + * Must be "all ones" explicitly for 82489DX. + */ + APICWrite(APIC_DFR, 0xFFFFFFFF); + + /* + * Set up the logical destination ID. + */ + tmp = APICRead(APIC_LDR); + tmp &= ~APIC_LDR_MASK; + tmp |= (1 << (CPU + 24)); + APICWrite(APIC_LDR, tmp); + + /* Accept all interrupts */ + tmp = (APICRead(APIC_TPR) & ~APIC_TPR_PRI); + APICWrite(APIC_TPR, tmp); + + /* Enable local APIC */ + tmp = APICRead(APIC_SIVR) | APIC_SIVR_ENABLE | APIC_SIVR_FOCUS; // No focus processor + + /* Set spurious interrupt vector */ + tmp |= SPURIOUS_VECTOR; + + APICWrite(APIC_SIVR, tmp); + + /* + * Only the BP should see the LINT1 NMI signal, obviously. + */ + if (CPU == 0) + tmp = APIC_DM_NMI; + else + tmp = APIC_DM_NMI | APIC_LVT_MASKED; + if (!APIC_INTEGRATED(CPUMap[CPU].APICVersion)) /* 82489DX */ + tmp |= APIC_LVT_LEVEL_TRIGGER; + APICWrite(APIC_LINT1, tmp); + + if (APIC_INTEGRATED(CPUMap[CPU].APICVersion)) { /* !82489DX */ + if (CPUMap[CPU].MaxLVT > 3) { /* Due to the Pentium erratum 3AP */ + APICWrite(APIC_ESR, 0); + } + + tmp = APICRead(APIC_ESR); + DPRINT("ESR value before enabling vector: 0x%X\n", tmp); + + /* Enable sending errors */ + tmp = ERROR_VECTOR; + APICWrite(APIC_LVT3, tmp); + + /* + * Spec says clear errors after enabling vector + */ + if (CPUMap[CPU].MaxLVT > 3) + APICWrite(APIC_ESR, 0); + tmp = APICRead(APIC_ESR); + DPRINT("ESR value after enabling vector: 0x%X\n", tmp); + } +} + +VOID +HaliInitBSP( + VOID) +{ + PUSHORT ps; + + /* Only initialize the BSP once */ + if (BSPInitialized) + return; + + BSPInitialized = TRUE; + + DPRINT("APIC is mapped at 0x%X\n", APICBase); + + if (VerifyLocalAPIC()) { + DPRINT("APIC found\n"); + } else { + DPRINT1("No APIC found\n"); + KeBugCheck(0); + } + + CPUMap[BootCPU].MaxLVT = APICGetMaxLVT(); + + SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG)MpsTimerInterrupt); + SetInterruptGate(ERROR_VECTOR, (ULONG)MpsErrorInterrupt); + SetInterruptGate(SPURIOUS_VECTOR, (ULONG)MpsSpuriousInterrupt); + + if (APICMode == amPIC) { + EnableSMPMode(); + } + + APICSetup(); + + /* BIOS data segment */ + BIOSBase = (PULONG)BIOS_AREA; + + /* Area for communicating with the APs */ + CommonBase = (PULONG)COMMON_AREA; + + /* Copy bootstrap code to common area */ + memcpy((PVOID)((ULONG)CommonBase + PAGE_SIZE), + &APstart, + (ULONG)&APend - (ULONG)&APstart + 1); + + /* Set shutdown code */ + CMOS_WRITE(0xF, 0xA); + + /* Set warm reset vector */ + ps = (PUSHORT)((ULONG)BIOSBase + 0x467); + *ps = (COMMON_AREA + PAGE_SIZE) & 0xF; + + ps = (PUSHORT)((ULONG)BIOSBase + 0x469); + *ps = (COMMON_AREA + PAGE_SIZE) >> 4; + + /* Calibrate APIC timer */ + APICCalibrateTimer(0); + + /* The boot processor is online */ + OnlineCPUs = (1 << 0); +} + +#endif /* MP */ + +VOID +STDCALL +HalInitializeProcessor ( + ULONG ProcessorNumber, + PVOID ProcessorStack) +{ + +#ifdef MP + + PCOMMON_AREA_INFO Common; + ULONG StartupCount; + ULONG DeliveryStatus; + ULONG AcceptStatus; + ULONG CPU, i, j; + ULONG tmp, maxlvt; + + if (ProcessorNumber == 0) { + /* Boot processor is already initialized */ + NextCPU = 1; + return; + } + + if (NextCPU < CPUCount) { + CPU = NextCPU; + + DPRINT("Attempting to boot CPU %d\n", CPU); + + /* Send INIT IPI */ + APICSendIPI(CPUMap[CPU].APICId, APIC_DM_INIT, 0, APIC_ICR0_LEVEL_ASSERT); + + APICSleep(200); + + /* Deassert INIT */ + APICSendIPI(CPUMap[CPU].APICId, APIC_DM_INIT, 0, APIC_ICR0_LEVEL_DEASSERT); + + if (APIC_INTEGRATED(CPUMap[CPU].APICVersion)) { + /* Clear APIC errors */ + APICWrite(APIC_ESR, 0); + tmp = (APICRead(APIC_ESR) & APIC_ESR_MASK); + } + + Common = (PCOMMON_AREA_INFO)CommonBase; + + /* Write the location of the AP stack */ + Common->Stack = (ULONG)ProcessorStack; + + DPRINT("CPU %d got stack at 0x%X\n", CPU, Common->Stack); +#if 0 + for (j = 0; j < 16; j++) { + Common->Debug[j] = 0; + } +#endif + + maxlvt = APICGetMaxLVT(); + + /* Is this a local APIC or an 82489DX? */ + StartupCount = (APIC_INTEGRATED(CPUMap[CPU].APICVersion)) ? 2 : 0; + + for (i = 1; i <= StartupCount; i++) + { + /* It's a local APIC, so send STARTUP IPI */ + DPRINT("Sending startup signal %d\n", i); + /* Clear errors */ + APICWrite(APIC_ESR, 0); + APICRead(APIC_ESR); + + APICSendIPI(CPUMap[CPU].APICId, + 0, + APIC_DM_STARTUP | ((COMMON_AREA + PAGE_SIZE) >> 12), + APIC_ICR0_LEVEL_DEASSERT); + + /* Wait up to 10ms for IPI to be delivered */ + j = 0; + do { + APICSleep(10); + + /* Check Delivery Status */ + DeliveryStatus = APICRead(APIC_ICR0) & APIC_ICR0_DS; + + j++; + } while ((DeliveryStatus) && (j < 1000)); + + APICSleep(200); + + /* + * Due to the Pentium erratum 3AP. + */ + if (maxlvt > 3) { + APICRead(APIC_SIVR); + APICWrite(APIC_ESR, 0); + } + + AcceptStatus = APICRead(APIC_ESR) & APIC_ESR_MASK; + + if (DeliveryStatus || AcceptStatus) { + break; + } + } + + if (DeliveryStatus) { + DPRINT("STARTUP IPI for CPU %d was never delivered.\n", CPU); + } + + if (AcceptStatus) { + DPRINT("STARTUP IPI for CPU %d was never accepted.\n", CPU); + } + + if (!(DeliveryStatus || AcceptStatus)) { + + /* Wait no more than 5 seconds for processor to boot */ + DPRINT("Waiting for 5 seconds for CPU %d to boot\n", CPU); + + /* Wait no more than 5 seconds */ + for (j = 0; j < 50000; j++) { + + if (CPUMap[CPU].Flags & CPU_ENABLED) + break; + + APICSleep(100); + } + } + + if (CPUMap[CPU].Flags & CPU_ENABLED) { + DbgPrint("CPU %d is now running\n", CPU); + } else { + DbgPrint("Initialization of CPU %d failed\n", CPU); + } + +#if 0 + DPRINT("Debug bytes are:\n"); + + for (j = 0; j < 4; j++) { + DPRINT("0x%08X 0x%08X 0x%08X 0x%08X.\n", + Common->Debug[j*4+0], + Common->Debug[j*4+1], + Common->Debug[j*4+2], + Common->Debug[j*4+3]); + } +#endif + NextCPU++; + } + +#endif /* MP */ + +} + +BOOLEAN +STDCALL +HalAllProcessorsStarted ( + VOID + ) +{ + +#ifdef MP + + return (NextCPU >= CPUCount); + +#else /* MP */ + + if (BSPInitialized) { + return TRUE; + } else { + BSPInitialized = TRUE; + return FALSE; + } + +#endif /* MP */ + +} + +BOOLEAN +STDCALL +HalStartNextProcessor ( + ULONG Unknown1, + ULONG Unknown2 + ) +{ +#ifdef MP + + /* Display the APIC registers for debugging */ + switch (Unknown1) { + case 0: + APICDump(); + break; + case 1: + IOAPICDump(); + } + for(;;); + + return (NextCPU >= CPUCount); + +#endif /* MP */ + + return FALSE; +} + + +#ifdef MP + +ULONG MPChecksum( + PUCHAR Base, + ULONG Size) +/* + * Checksum an MP configuration block + */ +{ + ULONG Sum = 0; + + while (Size--) + Sum += *Base++; + + return((UCHAR)Sum); +} + + +PCHAR HaliMPFamily( + ULONG Family, + ULONG Model) +{ + static CHAR str[32]; + static PCHAR CPUs[] = + { + "80486DX", "80486DX", + "80486SX", "80486DX/2 or 80487", + "80486SL", "Intel5X2(tm)", + "Unknown", "Unknown", + "80486DX/4" + }; + if (Family == 0x6) + return ("Pentium(tm) Pro"); + if (Family == 0x5) + return ("Pentium(tm)"); + if (Family == 0x0F && Model == 0x0F) + return("Special controller"); + if (Family == 0x0F && Model == 0x00) + return("Pentium 4(tm)"); + if (Family == 0x04 && Model < 9) + return CPUs[Model]; + sprintf(str, "Unknown CPU with family ID %ld and model ID %ld", Family, Model); + return str; +} + + +static VOID HaliMPProcessorInfo(PMP_CONFIGURATION_PROCESSOR m) +{ + ULONG ver; + + if (!(m->CpuFlags & CPU_FLAG_ENABLED)) + return; + + DPRINT("Processor #%d %s APIC version %d\n", + m->ApicId, + HaliMPFamily((m->FeatureFlags & CPU_FAMILY_MASK) >> 8, + (m->FeatureFlags & CPU_MODEL_MASK) >> 4), + m->ApicVersion); + + if (m->FeatureFlags & (1 << 0)) + DPRINT(" Floating point unit present.\n"); + if (m->FeatureFlags & (1 << 7)) + DPRINT(" Machine Exception supported.\n"); + if (m->FeatureFlags & (1 << 8)) + DPRINT(" 64 bit compare & exchange supported.\n"); + if (m->FeatureFlags & (1 << 9)) + DPRINT(" Internal APIC present.\n"); + if (m->FeatureFlags & (1 << 11)) + DPRINT(" SEP present.\n"); + if (m->FeatureFlags & (1 << 12)) + DPRINT(" MTRR present.\n"); + if (m->FeatureFlags & (1 << 13)) + DPRINT(" PGE present.\n"); + if (m->FeatureFlags & (1 << 14)) + DPRINT(" MCA present.\n"); + if (m->FeatureFlags & (1 << 15)) + DPRINT(" CMOV present.\n"); + if (m->FeatureFlags & (1 << 16)) + DPRINT(" PAT present.\n"); + if (m->FeatureFlags & (1 << 17)) + DPRINT(" PSE present.\n"); + if (m->FeatureFlags & (1 << 18)) + DPRINT(" PSN present.\n"); + if (m->FeatureFlags & (1 << 19)) + DPRINT(" Cache Line Flush Instruction present.\n"); + /* 20 Reserved */ + if (m->FeatureFlags & (1 << 21)) + DPRINT(" Debug Trace and EMON Store present.\n"); + if (m->FeatureFlags & (1 << 22)) + DPRINT(" ACPI Thermal Throttle Registers present.\n"); + if (m->FeatureFlags & (1 << 23)) + DPRINT(" MMX present.\n"); + if (m->FeatureFlags & (1 << 24)) + DPRINT(" FXSR present.\n"); + if (m->FeatureFlags & (1 << 25)) + DPRINT(" XMM present.\n"); + if (m->FeatureFlags & (1 << 26)) + DPRINT(" Willamette New Instructions present.\n"); + if (m->FeatureFlags & (1 << 27)) + DPRINT(" Self Snoop present.\n"); + /* 28 Reserved */ + if (m->FeatureFlags & (1 << 29)) + DPRINT(" Thermal Monitor present.\n"); + /* 30, 31 Reserved */ + + CPUMap[CPUCount].APICId = m->ApicId; + + CPUMap[CPUCount].Flags = CPU_USABLE; + + if (m->CpuFlags & CPU_FLAG_BSP) { + DPRINT(" Bootup CPU\n"); + CPUMap[CPUCount].Flags |= CPU_BSP; + BootCPU = m->ApicId; + } + + if (m->ApicId > MAX_CPU) { + DPRINT("Processor #%d INVALID. (Max ID: %d).\n", m->ApicId, MAX_CPU); + return; + } + ver = m->ApicVersion; + + /* + * Validate version + */ + if (ver == 0x0) { + DPRINT("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->ApicId); + ver = 0x10; + } + CPUMap[CPUCount].APICVersion = ver; + + CPUCount++; +} + +static VOID HaliMPBusInfo(PMP_CONFIGURATION_BUS m) +{ + static ULONG CurrentPCIBusId = 0; + CHAR str[7]; + + memcpy(str, m->BusType, 6); + str[6] = 0; + DPRINT("Bus #%d is %s\n", m->BusId, str); + + if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_ISA; + } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_EISA; + } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_PCI; + PCIBUSMap[m->BusId] = CurrentPCIBusId; + CurrentPCIBusId++; + } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_MCA; + } else { + DPRINT("Unknown bustype %s - ignoring\n", str); + } +} + +static VOID HaliMPIOApicInfo(PMP_CONFIGURATION_IOAPIC m) +{ + if (!(m->ApicFlags & CPU_FLAG_ENABLED)) + return; + + DPRINT("I/O APIC #%d Version %d at 0x%lX.\n", + m->ApicId, m->ApicVersion, m->ApicAddress); + if (IOAPICCount > MAX_IOAPIC) { + DPRINT("Max # of I/O APICs (%d) exceeded (found %d).\n", + MAX_IOAPIC, IOAPICCount); + DPRINT1("Recompile with bigger MAX_IOAPIC!.\n"); + KeBugCheck(0); + } + IOAPICMap[IOAPICCount].ApicId = m->ApicId; + IOAPICMap[IOAPICCount].ApicVersion = m->ApicVersion; + IOAPICMap[IOAPICCount].ApicAddress = m->ApicAddress; + IOAPICCount++; +} + +static VOID HaliMPIntSrcInfo(PMP_CONFIGURATION_INTSRC m) +{ + DPRINT("Int: type %d, pol %d, trig %d, bus %d," + " IRQ %02x, APIC ID %x, APIC INT %02x\n", + m->IrqType, m->IrqFlag & 3, + (m->IrqFlag >> 2) & 3, m->SrcBusId, + m->SrcBusIrq, m->DstApicId, m->DstApicInt); + if (IRQCount > MAX_IRQ_SOURCE) { + DPRINT1("Max # of irq sources exceeded!!\n"); + KeBugCheck(0); + } + + IRQMap[IRQCount] = *m; + IRQCount++; +} + +static VOID HaliMPIntLocalInfo(PMP_CONFIGURATION_INTLOCAL m) +{ + DPRINT("Lint: type %d, pol %d, trig %d, bus %d," + " IRQ %02x, APIC ID %x, APIC LINT %02x\n", + m->IrqType, m->IrqFlag & 3, + (m->IrqFlag >> 2) & 3, m->SrcBusId, + m->SrcBusIrq, m->DstApicId, m->DstApicLInt); + /* + * Well it seems all SMP boards in existence + * use ExtINT/LVT1 == LINT0 and + * NMI/LVT2 == LINT1 - the following check + * will show us if this assumptions is false. + * Until then we do not have to add baggage. + */ + if ((m->IrqType == INT_EXTINT) && (m->DstApicLInt != 0)) { + DPRINT1("Invalid MP table!\n"); + KeBugCheck(0); + } + if ((m->IrqType == INT_NMI) && (m->DstApicLInt != 1)) { + DPRINT1("Invalid MP table!\n"); + KeBugCheck(0); + } +} + + +VOID +HaliReadMPConfigTable( + PMP_CONFIGURATION_TABLE Table) +/* + PARAMETERS: + Table = Pointer to MP configuration table + */ +{ + PUCHAR Entry; + ULONG Count; + + if (Table->Signature != MPC_SIGNATURE) + { + PUCHAR pc = (PUCHAR)&Table->Signature; + + DbgPrint("Bad MP configuration block signature: %c%c%c%c\n", + pc[0], pc[1], pc[2], pc[3]); + KeBugCheck(0); + return; + } + + if (MPChecksum((PUCHAR)Table, Table->Length)) + { + DbgPrint("Bad MP configuration block checksum\n"); + KeBugCheck(0); + return; + } + + if (Table->Specification < 0x04) + { + DbgPrint("Bad MP configuration table version (%d)\n", + Table->Specification); + KeBugCheck(0); + return; + } + + APICBase = (PULONG)Table->LocalAPICAddress; + if (APICBase != (PULONG)APIC_DEFAULT_BASE) + { + DbgPrint("APIC base address is at 0x%X. " \ + "I cannot handle non-standard adresses\n", APICBase); + KeBugCheck(0); + } + + Entry = (PUCHAR)((PVOID)Table + sizeof(MP_CONFIGURATION_TABLE)); + Count = 0; + while (Count < (Table->Length - sizeof(MP_CONFIGURATION_TABLE))) + { + /* Switch on type */ + switch (*Entry) + { + case MPCTE_PROCESSOR: + { + HaliMPProcessorInfo((PMP_CONFIGURATION_PROCESSOR)Entry); + Entry += sizeof(MP_CONFIGURATION_PROCESSOR); + Count += sizeof(MP_CONFIGURATION_PROCESSOR); + break; + } + case MPCTE_BUS: + { + HaliMPBusInfo((PMP_CONFIGURATION_BUS)Entry); + Entry += sizeof(MP_CONFIGURATION_BUS); + Count += sizeof(MP_CONFIGURATION_BUS); + break; + } + case MPCTE_IOAPIC: + { + HaliMPIOApicInfo((PMP_CONFIGURATION_IOAPIC)Entry); + Entry += sizeof(MP_CONFIGURATION_IOAPIC); + Count += sizeof(MP_CONFIGURATION_IOAPIC); + break; + } + case MPCTE_INTSRC: + { + HaliMPIntSrcInfo((PMP_CONFIGURATION_INTSRC)Entry); + Entry += sizeof(MP_CONFIGURATION_INTSRC); + Count += sizeof(MP_CONFIGURATION_INTSRC); + break; + } + case MPCTE_LINTSRC: + { + HaliMPIntLocalInfo((PMP_CONFIGURATION_INTLOCAL)Entry); + Entry += sizeof(MP_CONFIGURATION_INTLOCAL); + Count += sizeof(MP_CONFIGURATION_INTLOCAL); + break; + } + default: + DbgPrint("Unknown entry in MPC table\n"); + KeBugCheck(0); + } + } +} + + +static VOID HaliConstructDefaultIOIrqMPTable( + ULONG Type) +{ + MP_CONFIGURATION_INTSRC intsrc; + ULONG i; + + intsrc.Type = MPCTE_INTSRC; + intsrc.IrqFlag = 0; /* conforming */ + intsrc.SrcBusId = 0; + intsrc.DstApicId = IOAPICMap[0].ApicId; + + intsrc.IrqType = INT_VECTORED; + for (i = 0; i < 16; i++) { + switch (Type) { + case 2: + if (i == 0 || i == 13) + continue; /* IRQ0 & IRQ13 not connected */ + /* Fall through */ + default: + if (i == 2) + continue; /* IRQ2 is never connected */ + } + + intsrc.SrcBusIrq = i; + intsrc.DstApicInt = i ? i : 2; /* IRQ0 to INTIN2 */ + HaliMPIntSrcInfo(&intsrc); + } + + intsrc.IrqType = INT_EXTINT; + intsrc.SrcBusIrq = 0; + intsrc.DstApicInt = 0; /* 8259A to INTIN0 */ + HaliMPIntSrcInfo(&intsrc); +} + + +static VOID HaliConstructDefaultISAMPTable( + ULONG Type) +{ + MP_CONFIGURATION_PROCESSOR processor; + MP_CONFIGURATION_BUS bus; + MP_CONFIGURATION_IOAPIC ioapic; + MP_CONFIGURATION_INTLOCAL lintsrc; + ULONG linttypes[2] = { INT_EXTINT, INT_NMI }; + ULONG i; + + APICBase = (PULONG)APIC_DEFAULT_BASE; + + /* + * 2 CPUs, numbered 0 & 1. + */ + processor.Type = MPCTE_PROCESSOR; + /* Either an integrated APIC or a discrete 82489DX. */ + processor.ApicVersion = Type > 4 ? 0x10 : 0x01; + processor.CpuFlags = CPU_FLAG_ENABLED | CPU_FLAG_BSP; + /* FIXME: Get this from the bootstrap processor */ + processor.CpuSignature = 0; + processor.FeatureFlags = 0; + processor.Reserved[0] = 0; + processor.Reserved[1] = 0; + for (i = 0; i < 2; i++) { + processor.ApicId = i; + HaliMPProcessorInfo(&processor); + processor.CpuFlags &= ~CPU_FLAG_BSP; + } + + bus.Type = MPCTE_BUS; + bus.BusId = 0; + switch (Type) { + default: + DPRINT("Unknown standard configuration %d\n", Type); + /* Fall through */ + case 1: + case 5: + memcpy(bus.BusType, "ISA ", 6); + break; + case 2: + case 6: + case 3: + memcpy(bus.BusType, "EISA ", 6); + break; + case 4: + case 7: + memcpy(bus.BusType, "MCA ", 6); + } + HaliMPBusInfo(&bus); + if (Type > 4) { + bus.Type = MPCTE_BUS; + bus.BusId = 1; + memcpy(bus.BusType, "PCI ", 6); + HaliMPBusInfo(&bus); + } + + ioapic.Type = MPCTE_IOAPIC; + ioapic.ApicId = 2; + ioapic.ApicVersion = Type > 4 ? 0x10 : 0x01; + ioapic.ApicFlags = MP_IOAPIC_USABLE; + ioapic.ApicAddress = IOAPIC_DEFAULT_BASE; + HaliMPIOApicInfo(&ioapic); + + /* + * We set up most of the low 16 IO-APIC pins according to MPS rules. + */ + HaliConstructDefaultIOIrqMPTable(Type); + + lintsrc.Type = MPCTE_LINTSRC; + lintsrc.IrqType = 0; + lintsrc.IrqFlag = 0; /* conforming */ + lintsrc.SrcBusId = 0; + lintsrc.SrcBusIrq = 0; + lintsrc.DstApicId = MP_APIC_ALL; + for (i = 0; i < 2; i++) { + lintsrc.IrqType = linttypes[i]; + lintsrc.DstApicLInt = i; + HaliMPIntLocalInfo(&lintsrc); + } +} + +BOOLEAN +HaliScanForMPConfigTable( + ULONG Base, + ULONG Size) +/* + PARAMETERS: + Base = Base address of region + Size = Length of region to check + RETURNS: + TRUE if a valid MP configuration table was found + */ +{ + PULONG bp = (PULONG)Base; + MP_FLOATING_POINTER* mpf; + + while (Size > 0) + { + if (*bp == MPF_SIGNATURE) + { + DbgPrint("Found MPF signature at %x, checksum %x\n", bp, + MPChecksum((PUCHAR)bp, 16)); + if (MPChecksum((PUCHAR)bp, 16) == 0) + { + mpf = (MP_FLOATING_POINTER*)bp; + + DbgPrint("Intel MultiProcessor Specification v1.%d compliant system.\n", + mpf->Specification); + + if (mpf->Feature2 & FEATURE2_IMCRP) { + APICMode = amPIC; + DPRINT("Running in IMCR and PIC compatibility mode.\n") + } else { + APICMode = amVWIRE; + DPRINT("Running in Virtual Wire compatibility mode.\n"); + } + + switch (mpf->Feature1) + { + case 0: + /* Non standard configuration */ + break; + case 1: + DPRINT("ISA\n"); + break; + case 2: + DPRINT("EISA with no IRQ8 chaining\n"); + break; + case 3: + DPRINT("EISA\n"); + break; + case 4: + DPRINT("MCA\n"); + break; + case 5: + DPRINT("ISA and PCI\n"); + break; + case 6: + DPRINT("EISA and PCI\n"); + break; + case 7: + DPRINT("MCA and PCI\n"); + break; + default: + DbgPrint("Unknown standard configuration %d\n", mpf->Feature1); + return FALSE; + } + + CPUCount = 0; + IOAPICCount = 0; + IRQCount = 0; + + if ((mpf->Feature1 == 0) && (mpf->Address)) { + HaliReadMPConfigTable((PMP_CONFIGURATION_TABLE)mpf->Address); + } else { + HaliConstructDefaultISAMPTable(mpf->Feature1); + } + + return TRUE; + } + } + bp += 4; + Size -= 16; + } + return FALSE; +} + + +VOID +HalpInitMPS( + VOID) +{ + USHORT EBDA; + ULONG CPU; + + /* Only initialize MP system once. Once called the first time, + each subsequent call is part of the initialization sequence + for an application processor. */ + if (MPSInitialized) { + CPU = ThisCPU(); + + DPRINT("CPU %d says it is now booted.\n", CPU); + + APICSetup(); + APICCalibrateTimer(CPU); + + /* This processor is now booted */ + CPUMap[CPU].Flags |= CPU_ENABLED; + OnlineCPUs |= (1 << CPU); + + return; + } + + MPSInitialized = TRUE; + + /* + Scan the system memory for an MP configuration table + 1) Scan the first KB of system base memory + 2) Scan the last KB of system base memory + 3) Scan the BIOS ROM address space between 0F0000h and 0FFFFFh + 4) Scan the Extended BIOS Data Area + */ + + if (!HaliScanForMPConfigTable(0x0, 0x400)) { + if (!HaliScanForMPConfigTable(0x9FC00, 0x400)) { + if (!HaliScanForMPConfigTable(0xF0000, 0x10000)) { + EBDA = *((PUSHORT)0x040E); + EBDA <<= 4; + if (!HaliScanForMPConfigTable((ULONG)EBDA, 0x1000)) { + DbgPrint("No multiprocessor compliant system found.\n"); + KeBugCheck(0); + } + } + } + } + + /* Setup IRQ to vector translation map */ + memset(&IRQVectorMap, sizeof(IRQVectorMap), 0); + + /* Initialize the bootstrap processor */ + HaliInitBSP(); + + /* Setup I/O APIC */ + IOAPICSetup(); + + /* Setup busy waiting */ + HalpCalibrateStallExecution(); + + /* We can now enable interrupts */ + __asm__ __volatile__ ("sti\n\t"); + + NextCPU = 0; +} + +#endif /* MP */ + +/* EOF */ diff --git a/hal/halx86/mps.S b/hal/halx86/mps.S new file mode 100644 index 0000000..f3f957c --- /dev/null +++ b/hal/halx86/mps.S @@ -0,0 +1,76 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mps.S + * PURPOSE: Intel MultiProcessor specification support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * Created 12/04/2001 + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* FUNCTIONS *****************************************************************/ + +#define BEFORE \ + pusha; \ + pushl %ds; \ + pushl %es; \ + pushl %fs; \ + pushl %gs; \ + movl $(KERNEL_DS), %eax; \ + movl %eax, %ds; \ + movl %eax, %es; \ + movl %eax, %gs; \ + movl $(PCR_SELECTOR), %eax; \ + movl %eax, %fs; + +#define AFTER \ + popl %gs; \ + popl %fs; \ + popl %es; \ + popl %ds; \ + popa; + +.globl _MpsTimerInterrupt +_MpsTimerInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call _MpsTimerHandler + + /* Return to the caller */ + AFTER + iret + + +.globl _MpsErrorInterrupt +_MpsErrorInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call _MpsErrorHandler + + /* Return to the caller */ + AFTER + iret + + +.globl _MpsSpuriousInterrupt +_MpsSpuriousInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call _MpsSpuriousHandler + + /* Return to the caller */ + AFTER + iret + +/* EOF */ diff --git a/hal/halx86/mpsboot.asm b/hal/halx86/mpsboot.asm new file mode 100644 index 0000000..684b69a --- /dev/null +++ b/hal/halx86/mpsboot.asm @@ -0,0 +1,106 @@ +; +; COPYRIGHT: See COPYING in the top level directory +; PROJECT: ReactOS kernel +; FILE: ntoskrnl/hal/x86/mpsboot.c +; PURPOSE: Bootstrap code for application processors +; PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) +; UPDATE HISTORY: +; Created 12/04/2001 +; + +; +; Memory map at this stage is: +; 0x2000 Location of our stack +; 0x3000 Startup code for the APs (this code) +; + +; +; Base address of common area for BSP and APs +; +LOAD_BASE equ 00200000h + +; +; Magic value to be put in EAX when multiboot.S is called as part of the +; application processor initialization process +; +AP_MAGIC equ 12481020h + +; +; Segment selectors +; +%define KERNEL_CS (0x8) +%define KERNEL_DS (0x10) + +section .text + +global _APstart +global _APend + +; 16 bit code +BITS 16 + +_APstart: + cli ; Just in case + + xor ax, ax + mov ds, ax + mov ss, ax + + mov eax, 3000h + APgdt - _APstart + lgdt [eax] + + mov eax, cr0 + or eax, 00010001h ; Turn on protected mode and write protection + mov cr0, eax + + db 0eah + dw 3000h + flush - _APstart, KERNEL_CS + +; 32 bit code +BITS 32 + +flush: + mov ax, KERNEL_DS + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + ; Setup a stack for the AP + mov eax, 2000h + mov eax, [eax] + mov esp, eax + + ; Jump to start of the kernel with AP magic in eax + mov eax, AP_MAGIC + jmp dword KERNEL_CS:(LOAD_BASE + 0x1000) + + ; Never get here + + +; Temporary GDT descriptor for the APs + +APgdt: +; Limit + dw (3*8)-1 +; Base + dd 3000h + gdt - _APstart + +gdt: + dw 0x0 ; Null descriptor + dw 0x0 + dw 0x0 + dw 0x0 + + dw 0xffff ; Kernel code descriptor + dw 0x0000 + dw 0x9a00 + dw 0x00cf + + dw 0xffff ; Kernel data descriptor + dw 0x0000 + dw 0x9200 + dw 0x00cf + +_APend: diff --git a/hal/halx86/mpsirql.c b/hal/halx86/mpsirql.c new file mode 100644 index 0000000..182d6b9 --- /dev/null +++ b/hal/halx86/mpsirql.c @@ -0,0 +1,416 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mpsirql.c + * PURPOSE: Implements IRQLs for multiprocessor systems + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 12/04/2001 CSH Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/; + +extern IMPORTED ULONG DpcQueueSize; + +static VOID KeSetCurrentIrql(KIRQL newlvl); + +/* FUNCTIONS ****************************************************************/ + +#define IRQL2TPR(irql) (APIC_TPR_MIN + ((irql - DISPATCH_LEVEL - 1) * 8)) + +static VOID HiSetCurrentPriority( + ULONG Priority) +{ + //DbgPrint(" P(0x%X)\n", Priority); + APICWrite(APIC_TPR, Priority & APIC_TPR_PRI); +} + + +static VOID HiSwitchIrql(KIRQL OldIrql, ULONG Flags) +/* + * FUNCTION: Switches to the current irql + * NOTE: Must be called with interrupt disabled + */ +{ + PKTHREAD CurrentThread; + KIRQL CurrentIrql; + + //DbgPrint("HiSwitchIrql(OldIrql %d)\n", OldIrql); + + CurrentIrql = KeGetCurrentKPCR()->Irql; + + if (CurrentIrql >= IPI_LEVEL) + { + /* Block all interrupts */ + HiSetCurrentPriority(APIC_TPR_MAX); + return; + } + + if (CurrentIrql == CLOCK2_LEVEL) + { + HiSetCurrentPriority(APIC_TPR_MAX - 16); + popfl(Flags); + return; + } + + if (CurrentIrql > DISPATCH_LEVEL) + { + HiSetCurrentPriority(IRQL2TPR(CurrentIrql)); + popfl(Flags); + return; + } + + /* Pass all interrupts */ + HiSetCurrentPriority(0); + + if (CurrentIrql == DISPATCH_LEVEL) + { + popfl(Flags); + return; + } + + if (CurrentIrql == APC_LEVEL) + { + if (DpcQueueSize > 0 ) + { + KeSetCurrentIrql(DISPATCH_LEVEL); + __asm__("sti\n\t"); + KiDispatchInterrupt(); + __asm__("cli\n\t"); + KeSetCurrentIrql(PASSIVE_LEVEL); + } + popfl(Flags); + return; + } + + CurrentThread = KeGetCurrentThread(); + + if (CurrentIrql == PASSIVE_LEVEL && + CurrentThread != NULL && + CurrentThread->ApcState.KernelApcPending) + { + KeSetCurrentIrql(APC_LEVEL); + __asm__("sti\n\t"); + KiDeliverApc(0, 0, 0); + __asm__("cli\n\t"); + KeSetCurrentIrql(PASSIVE_LEVEL); + popfl(Flags); + } + else + { + popfl(Flags); + } +} + + +KIRQL STDCALL KeGetCurrentIrql (VOID) +/* + * PURPOSE: Returns the current irq level + * RETURNS: The current irq level + */ +{ + return(KeGetCurrentKPCR()->Irql); +} + + +static VOID KeSetCurrentIrql(KIRQL newlvl) +/* + * PURPOSE: Sets the current irq level without taking any action + */ +{ +// DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl); + + KeGetCurrentKPCR()->Irql = newlvl; +} + + +/********************************************************************** + * NAME EXPORTED + * KfLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + * Uses fastcall convention + */ + +VOID FASTCALL +KfLowerIrql ( + KIRQL NewIrql + ) +{ + KIRQL CurrentIrql; + KIRQL OldIrql; + ULONG Flags; + + //DbgPrint("KfLowerIrql(NewIrql %d)\n", NewIrql); + + pushfl(Flags); + __asm__ ("\n\tcli\n\t"); + + CurrentIrql = KeGetCurrentKPCR()->Irql; + + if (NewIrql > CurrentIrql) + { + DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n", + __FILE__, __LINE__, NewIrql, CurrentIrql); + KeBugCheck(0); + for(;;); + } + + OldIrql = CurrentIrql; + KeGetCurrentKPCR()->Irql = NewIrql; + HiSwitchIrql(OldIrql, Flags); +} + + +/********************************************************************** + * NAME EXPORTED + * KeLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + */ + +VOID +STDCALL +KeLowerIrql ( + KIRQL NewIrql + ) +{ + KfLowerIrql (NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KfRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * + * RETURN VALUE + * previous irq level + * + * NOTES + * Uses fastcall convention + */ + +KIRQL +FASTCALL +KfRaiseIrql ( + KIRQL NewIrql + ) +{ + KIRQL CurrentIrql; + KIRQL OldIrql; + ULONG Flags; + + //DbgPrint("KfRaiseIrql(NewIrql %d)\n", NewIrql); + + pushfl(Flags); + __asm__ ("\n\tcli\n\t"); + + CurrentIrql = KeGetCurrentKPCR()->Irql; + + if (NewIrql < CurrentIrql) + { + DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n", + __FILE__,__LINE__,CurrentIrql,NewIrql); + KeBugCheck (0); + for(;;); + } + + OldIrql = CurrentIrql; + KeGetCurrentKPCR()->Irql = NewIrql; + + //DPRINT("NewIrql %x OldIrql %x\n", NewIrql, OldIrql); + HiSwitchIrql(OldIrql, Flags); + return OldIrql; +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * OldIrql (OUT) = Caller supplied storage for the previous irql + * + * RETURN VALUE + * None + * + * NOTES + * Calls KfRaiseIrql + */ + +VOID +STDCALL +KeRaiseIrql ( + KIRQL NewIrql, + PKIRQL OldIrql + ) +{ + *OldIrql = KfRaiseIrql (NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToDpcLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to DISPATCH level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL +STDCALL +KeRaiseIrqlToDpcLevel (VOID) +{ + return KfRaiseIrql (DISPATCH_LEVEL); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToSynchLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to CLOCK2 level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL +STDCALL +KeRaiseIrqlToSynchLevel (VOID) +{ + return KfRaiseIrql (CLOCK2_LEVEL); +} + + +BOOLEAN STDCALL HalBeginSystemInterrupt (ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) +{ + DPRINT("Vector (0x%X) Irql (0x%X)\n", + Vector, Irql); + + if (Vector < FIRST_DEVICE_VECTOR || + Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) { + DPRINT("Not a device interrupt\n"); + return FALSE; + } + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); + + *OldIrql = KeGetCurrentIrql(); + + KeSetCurrentIrql(Irql); + + return TRUE; +} + + +VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, + ULONG Unknown2) +{ + KeSetCurrentIrql(Irql); +} + + +BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector, + ULONG Unknown2) +{ + ULONG irq; + + DPRINT("Vector (0x%X)\n", Vector); + + if (Vector < FIRST_DEVICE_VECTOR || + Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) { + DPRINT("Not a device interrupt\n"); + return FALSE; + } + + irq = VECTOR2IRQ(Vector); + + IOAPICMaskIrq(0, irq); + + return TRUE; +} + + +BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector, + ULONG Unknown2, + ULONG Unknown3) +{ + ULONG irq; + + DPRINT("Vector (0x%X)\n", Vector); + + if (Vector < FIRST_DEVICE_VECTOR || + Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) { + DPRINT("Not a device interrupt\n"); + return FALSE; + } + + irq = VECTOR2IRQ(Vector); + + IOAPICUnmaskIrq(0, irq); + + return TRUE; +} + +/* EOF */ diff --git a/hal/halx86/pci.c b/hal/halx86/pci.c new file mode 100644 index 0000000..ab271e0 --- /dev/null +++ b/hal/halx86/pci.c @@ -0,0 +1,509 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/pci.c + * PURPOSE: Interfaces to the PCI bus + * PROGRAMMER: David Welch (welch@mcmail.com) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 05/06/1998: Created + * 17/08/2000: Added preliminary pci bus scanner + * 13/06/2001: Implemented access to pci configuration space + */ + +/* + * NOTES: Sections copied from the Linux pci support + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* MACROS ******************************************************************/ + +/* access type 1 macros */ +#define PCI_FUNC(devfn) \ + ((devfn) & 0x07) +#define CONFIG_CMD(bus, device_fn, where) \ + (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) + +/* access type 2 macros */ +#define IOADDR(devfn, where) \ + ((0xC000 | ((devfn & 0x78) << 5)) + where) +#define FUNC(devfn) \ + (((devfn & 7) << 1) | 0xf0) + + +#define PCIBIOS_SUCCESSFUL 0x00 +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 +#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 + + +/* GLOBALS ******************************************************************/ + +static ULONG BusConfigType = 0; /* undetermined config type */ + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +ReadPciConfigUchar(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PUCHAR Value) +{ + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3)); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +ReadPciConfigUshort(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PUSHORT Value) +{ + if ((Offset & 1) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1)); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +ReadPciConfigUlong(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PULONG Value) +{ + if ((Offset & 3) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_ULONG((PULONG)0xCFC); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +WritePciConfigUchar(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + UCHAR Value) +{ + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +WritePciConfigUshort(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + USHORT Value) +{ + if ((Offset & 1) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +WritePciConfigUlong(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + ULONG Value) +{ + if ((Offset & 3) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_ULONG((PULONG)0xCFC, Value); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static ULONG STDCALL +HalpGetPciData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PVOID Ptr = Buffer; + ULONG Address = Offset; + ULONG Len = Length; + ULONG Vendor; + UCHAR HeaderType; + + DPRINT("HalpGetPciData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if ((Length == 0) || (BusConfigType == 0)) + return 0; + + /* 0E=PCI_HEADER_TYPE */ + ReadPciConfigUchar(BusNumber, + SlotNumber & 0xF8, + 0x0E, + &HeaderType); + if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0)) + return 0; + + ReadPciConfigUlong(BusNumber, + SlotNumber, + 0x00, + &Vendor); + /* some broken boards return 0 if a slot is empty: */ + if (Vendor == 0xFFFFFFFF || Vendor == 0) + return 0; + + if ((Address & 1) && (Len >= 1)) + { + ReadPciConfigUchar(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + if ((Address & 2) && (Len >= 2)) + { + ReadPciConfigUshort(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + while (Len >= 4) + { + ReadPciConfigUlong(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 4; + Address += 4; + Len -= 4; + } + + if (Len >= 2) + { + ReadPciConfigUshort(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + if (Len >= 1) + { + ReadPciConfigUchar(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + return Length - Len; +} + + +static ULONG STDCALL +HalpSetPciData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PVOID Ptr = Buffer; + ULONG Address = Offset; + ULONG Len = Length; + ULONG Vendor; + UCHAR HeaderType; + + DPRINT("HalpSetPciData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if ((Length == 0) || (BusConfigType == 0)) + return 0; + + /* 0E=PCI_HEADER_TYPE */ + ReadPciConfigUchar(BusNumber, + SlotNumber & 0xF8, + 0x0E, + &HeaderType); + if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0)) + return 0; + + ReadPciConfigUlong(BusNumber, + SlotNumber, + 0x00, + &Vendor); + /* some broken boards return 0 if a slot is empty: */ + if (Vendor == 0xFFFFFFFF || Vendor == 0) + return 0; + + if ((Address & 1) && (Len >= 1)) + { + WritePciConfigUchar(BusNumber, + SlotNumber, + Address, + *(PUCHAR)Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + if ((Address & 2) && (Len >= 2)) + { + WritePciConfigUshort(BusNumber, + SlotNumber, + Address, + *(PUSHORT)Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + while (Len >= 4) + { + WritePciConfigUlong(BusNumber, + SlotNumber, + Address, + *(PULONG)Ptr); + Ptr = Ptr + 4; + Address += 4; + Len -= 4; + } + + if (Len >= 2) + { + WritePciConfigUshort(BusNumber, + SlotNumber, + Address, + *(PUSHORT)Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + if (Len >= 1) + { + WritePciConfigUchar(BusNumber, + SlotNumber, + Address, + *(PUCHAR)Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + return Length - Len; +} + + +static ULONG +GetBusConfigType(VOID) +{ + ULONG Value; + + DPRINT("GetBusConfigType() called\n"); + + DPRINT("Checking configuration type 1:"); + WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01); + Value = READ_PORT_ULONG((PULONG)0xCF8); + WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000); + if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000) + { + WRITE_PORT_ULONG((PULONG)0xCF8, Value); + DPRINT(" Success!\n"); + return 1; + } + WRITE_PORT_ULONG((PULONG)0xCF8, Value); + DPRINT(" Unsuccessful!\n"); + + DPRINT("Checking configuration type 2:"); + WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00); + if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 && + READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00) + { + DPRINT(" Success!\n"); + return 2; + } + DPRINT(" Unsuccessful!\n"); + + DPRINT("No pci bus found!\n"); + return 0; +} + + +static ULONG STDCALL +HalpGetPciInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + *Irql = HIGH_LEVEL - BusInterruptVector; + *Affinity = 0xFFFFFFFF; + return BusInterruptVector; +} + + +VOID +HalpInitPciBus(VOID) +{ + PBUS_HANDLER BusHandler; + + DPRINT("HalpInitPciBus() called.\n"); + + BusConfigType = GetBusConfigType(); + if (BusConfigType == 0) + return; + + DPRINT("Bus configuration %lu used\n", BusConfigType); + + /* pci bus (bus 0) handler */ + BusHandler = HalpAllocateBusHandler(PCIBus, + PCIConfiguration, + 0); + BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData; + BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData; + BusHandler->GetInterruptVector = + (pGetInterruptVector)HalpGetPciInterruptVector; +// BusHandler->AdjustResourceList = +// (pGetSetBusData)HalpAdjustPciResourceList; +// BusHandler->AssignSlotResources = +// (pGetSetBusData)HalpAssignPciSlotResources; + + + /* agp bus (bus 1) handler */ + BusHandler = HalpAllocateBusHandler(PCIBus, + PCIConfiguration, + 1); + BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData; + BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData; + BusHandler->GetInterruptVector = + (pGetInterruptVector)HalpGetPciInterruptVector; +// BusHandler->AdjustResourceList = +// (pGetSetBusData)HalpAdjustPciResourceList; +// BusHandler->AssignSlotResources = +// (pGetSetBusData)HalpAssignPciSlotResources; + + DPRINT("HalpInitPciBus() finished.\n"); +} + +/* EOF */ diff --git a/hal/halx86/perfcnt.c b/hal/halx86/perfcnt.c new file mode 100644 index 0000000..8d4f76f --- /dev/null +++ b/hal/halx86/perfcnt.c @@ -0,0 +1,62 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/perfcnt.c + * PURPOSE: Performance counter functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 09/06/2000: Created + */ + + +/* INCLUDES ***************************************************************/ + +#include + +/* FUNCTIONS **************************************************************/ + + +VOID STDCALL +HalCalibratePerformanceCounter(ULONG Count) +{ + ULONG i; + + /* save flags and disable interrupts */ + __asm__("pushf\n\t" \ + "cli\n\t"); + + for (i = 0; i < Count; i++); + + /* restore flags */ + __asm__("popf\n\t"); +} + + +LARGE_INTEGER STDCALL +KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq) +/* + * FUNCTION: Queries the finest grained running count avaiable in the system + * ARGUMENTS: + * PerformanceFreq (OUT) = The routine stores the number of + * performance counters tick per second here + * RETURNS: The performance counter value in HERTZ + * NOTE: Returns the system tick count or the time-stamp on the pentium + */ +{ + if (PerformanceFreq != NULL) + { + PerformanceFreq->QuadPart = 0; + return *PerformanceFreq; + } + else + { + LARGE_INTEGER Value; + + Value.QuadPart = 0; + return Value; + } +} + +/* EOF */ diff --git a/hal/halx86/portio.c b/hal/halx86/portio.c new file mode 100644 index 0000000..744c26d --- /dev/null +++ b/hal/halx86/portio.c @@ -0,0 +1,182 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/portio.c + * PURPOSE: Port I/O functions + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 18/10/99 + */ + +#include + + +/* FUNCTIONS ****************************************************************/ + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + * Linus + */ + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") +#else +#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") +#endif + +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + +VOID STDCALL +READ_PORT_BUFFER_UCHAR (PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; insb\n\t" + : "=D" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +READ_PORT_BUFFER_USHORT (PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; insw" + : "=D" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +READ_PORT_BUFFER_ULONG (PULONG Port, + PULONG Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; insl" + : "=D" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +UCHAR STDCALL +READ_PORT_UCHAR (PUCHAR Port) +{ + UCHAR Value; + + __asm__("inb %w1, %0\n\t" + : "=a" (Value) + : "d" (Port)); + SLOW_DOWN_IO; + return(Value); +} + +USHORT STDCALL +READ_PORT_USHORT (PUSHORT Port) +{ + USHORT Value; + + __asm__("inw %w1, %0\n\t" + : "=a" (Value) + : "d" (Port)); + SLOW_DOWN_IO; + return(Value); +} + +ULONG STDCALL +READ_PORT_ULONG (PULONG Port) +{ + ULONG Value; + + __asm__("inl %w1, %0\n\t" + : "=a" (Value) + : "d" (Port)); + SLOW_DOWN_IO; + return(Value); +} + +VOID STDCALL +WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb" + : "=S" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +WRITE_PORT_BUFFER_USHORT (PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw" + : "=S" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +WRITE_PORT_BUFFER_ULONG (PULONG Port, + PULONG Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl" + : "=S" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +WRITE_PORT_UCHAR (PUCHAR Port, + UCHAR Value) +{ + __asm__("outb %0, %w1\n\t" + : + : "a" (Value), + "d" (Port)); + SLOW_DOWN_IO; +} + +VOID STDCALL +WRITE_PORT_USHORT (PUSHORT Port, + USHORT Value) +{ + __asm__("outw %0, %w1\n\t" + : + : "a" (Value), + "d" (Port)); + SLOW_DOWN_IO; +} + +VOID STDCALL +WRITE_PORT_ULONG (PULONG Port, + ULONG Value) +{ + __asm__("outl %0, %w1\n\t" + : + : "a" (Value), + "d" (Port)); + SLOW_DOWN_IO; +} + +/* EOF */ diff --git a/hal/halx86/pwroff.c b/hal/halx86/pwroff.c new file mode 100644 index 0000000..d941e48 --- /dev/null +++ b/hal/halx86/pwroff.c @@ -0,0 +1,114 @@ +/* $Id$ + * + * FILE : reactos/hal/x86/apm.c + * DESCRIPTION: Turn CPU off... + * PROJECT : ReactOS Operating System + * AUTHOR : D. Lindauer (July 11 1997) + * NOTE : This program is public domain + * REVISIONS : + * 1999-12-26 + */ + +#define APM_FUNCTION_AVAILABLE 0x5300 +#define APM_FUNCTION_CONNREAL 0x5301 +#define APM_FUNCTION_POWEROFF 0x5307 +#define APM_FUNCTION_ENABLECPU 0x530d +#define APM_FUNCTION_ENABLEAPM 0x530e + +#define APM_DEVICE_BIOS 0 +#define APM_DEVICE_ALL 1 + +#define APM_MODE_DISABLE 0 +#define APM_MODE_ENABLE 1 + + + +nopm db 'No power management functionality',10,13,'$' +errmsg db 'Power management error',10,13,'$' +wrongver db 'Need APM version 1.1 or better',10,13,'$' +; +; Entry point +; +go: + mov dx,offset nopm + jc error + cmp ax,101h ; See if version 1.1 or greater + mov dx,offset wrongver + jc error + + mov [ver],ax + mov ax,5301h ; Do a real mode connection + mov bx,0 ; device = BIOS + int 15h + jnc noconerr + + cmp ah,2 ; Pass if already connected + mov dx,offset errmsg ; else error + jnz error +noconerr: + mov ax,530eh ; Enable latest version of APM + mov bx,0 ; device = BIOS + mov cx,[ver] ; version + int 15h + mov dx,offset errmsg + jc error + + mov ax,530dh ; Now engage and enable CPU management + mov bx,1 ; device = all + mov cx,1 ; enable + int 15h + mov dx,offset errmsg + jc error + + mov ax,530fh + mov bx,1 ; device = ALL + mov cx,1 ; enable + int 15h + mov dx,offset errmsg + jc error + + mov dx,offset errmsg +error: + call print + mov ax,4c01h + int 21h + int 3 + end start + + +BOOLEAN +ApmCall ( + DWORD Function, + DWORD Device, + DWORD Mode + ) +{ + /* AX <== Function */ + /* BX <== Device */ + /* CX <== Mode */ + __asm__("int 21\n"); /* 0x15 */ +} + + +BOOLEAN +HalPowerOff (VOID) +{ + ApmCall ( + APM_FUNCTION_AVAILABLE, + APM_DEVICE_BIOS, + 0 + ); + ApmCall ( + APM_FUNCTION_ENABLEAPM, + ); + /* Shutdown CPU */ + ApmCall ( + APM_FUNCTION_POWEROFF, + APM_DEVICE_ALL, + 3 + ); + return TRUE; +} + + +/* EOF */ diff --git a/hal/halx86/reboot.c b/hal/halx86/reboot.c new file mode 100644 index 0000000..75384ca --- /dev/null +++ b/hal/halx86/reboot.c @@ -0,0 +1,74 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/reboot.c + * PURPOSE: Reboot functions. + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 11/10/99 + */ + + +#include +#include + + +static VOID +HalReboot (VOID) +{ + char data; + BYTE *mem; + + /* enable warm reboot */ + mem = (BYTE *)(0xd0000000 + 0x0000); +// mem = HalMapPhysicalMemory (0, 1); + mem[0x472] = 0x34; + mem[0x473] = 0x12; + + /* disable interrupts */ + __asm__("cli\n"); + + /* disable periodic interrupt (RTC) */ + WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0b); + data = READ_PORT_UCHAR((PUCHAR)0x71); + WRITE_PORT_UCHAR((PUCHAR)0x71, data & 0xbf); + + /* */ + WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0a); + data = READ_PORT_UCHAR((PUCHAR)0x71); + WRITE_PORT_UCHAR((PUCHAR)0x71, (data & 0xf0) | 0x06); + + /* */ + WRITE_PORT_UCHAR((PUCHAR)0x70, 0x15); + + /* generate RESET signal via keyboard controller */ + WRITE_PORT_UCHAR((PUCHAR)0x64, 0xfe); + + /* stop the processor */ +#if 1 + __asm__("hlt\n"); +#else + for(;;); +#endif +} + + +VOID STDCALL +HalReturnToFirmware ( + ULONG Action + ) +{ + if (Action == FIRMWARE_HALT) + { + DbgPrint ("HalReturnToFirmware called!\n"); + DbgBreakPoint (); + } + else if (Action == FIRMWARE_REBOOT) + { + HalResetDisplay (); + HalReboot (); + } +} + +/* EOF */ diff --git a/hal/halx86/spinlock.c b/hal/halx86/spinlock.c new file mode 100644 index 0000000..30c604d --- /dev/null +++ b/hal/halx86/spinlock.c @@ -0,0 +1,95 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/spinlock.c + * PURPOSE: Implements spinlocks + * PROGRAMMER: David Welch (welch@cwcom.net) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 09/06/2000 Created + */ + +/* + * NOTE: On a uniprocessor machine spinlocks are implemented by raising + * the irq level + */ + +/* INCLUDES ****************************************************************/ + +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +VOID STDCALL +KeAcquireSpinLock ( + PKSPIN_LOCK SpinLock, + PKIRQL OldIrql + ) +/* + * FUNCTION: Acquires a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to acquire + * OldIrql (OUT) = Caller supplied storage for the previous irql + */ +{ + KeRaiseIrql(DISPATCH_LEVEL,OldIrql); + KeAcquireSpinLockAtDpcLevel(SpinLock); +} + +KIRQL FASTCALL +KeAcquireSpinLockRaiseToSynch ( + PKSPIN_LOCK SpinLock + ) +{ + UNIMPLEMENTED; +} + +VOID STDCALL +KeReleaseSpinLock ( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql + ) +/* + * FUNCTION: Releases a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to release + * NewIrql = Irql level before acquiring the spinlock + */ +{ + KeReleaseSpinLockFromDpcLevel(SpinLock); + KeLowerIrql(NewIrql); +} + +KIRQL FASTCALL +KfAcquireSpinLock ( + PKSPIN_LOCK SpinLock + ) +{ + KIRQL OldIrql; + + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + KeAcquireSpinLockAtDpcLevel(SpinLock); + + return OldIrql; +} + +VOID FASTCALL +KfReleaseSpinLock ( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql + ) +/* + * FUNCTION: Releases a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to release + * NewIrql = Irql level before acquiring the spinlock + */ +{ + KeReleaseSpinLockFromDpcLevel(SpinLock); + KeLowerIrql(NewIrql); +} + +/* EOF */ diff --git a/hal/halx86/sysbus.c b/hal/halx86/sysbus.c new file mode 100644 index 0000000..6a2b7de --- /dev/null +++ b/hal/halx86/sysbus.c @@ -0,0 +1,64 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/sysbus.c + * PURPOSE: System bus handler functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 09/04/2000 Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + + +/* FUNCTIONS ****************************************************************/ + +ULONG STDCALL +HalpGetSystemInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + *Irql = HIGH_LEVEL - BusInterruptVector; + *Affinity = 0xFFFFFFFF; + return BusInterruptVector; +} + + +BOOLEAN STDCALL +HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + ULONG BaseAddress = 0; + + if (*AddressSpace == 0) + { + /* memory space */ + + } + else if (*AddressSpace == 1) + { + /* io space */ + + } + else + { + /* other */ + return FALSE; + } + + TranslatedAddress->QuadPart = BusAddress.QuadPart + BaseAddress; + + return TRUE; +} + +/* EOF */ diff --git a/hal/halx86/sysinfo.c b/hal/halx86/sysinfo.c new file mode 100644 index 0000000..5d04be8 --- /dev/null +++ b/hal/halx86/sysinfo.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/sysinfo.c + * PURPOSE: Getting system information + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID HalQuerySystemInformation() +{ + UNIMPLEMENTED; +} + diff --git a/hal/halx86/time.c b/hal/halx86/time.c new file mode 100644 index 0000000..57a4015 --- /dev/null +++ b/hal/halx86/time.c @@ -0,0 +1,307 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/time.c + * PURPOSE: Getting time information + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* MACROS and CONSTANTS ******************************************************/ + +/* macro BCD_INT : convert bcd to int */ +#define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f)) + +/* macro INT_BCD : convert int to bcd */ +#define INT_BCD(int) (((int / 10) << 4) + (int % 10)) + + +#define RTC_REGISTER_A 0x0A +#define RTC_REG_A_UIP 0x80 /* Update In Progress bit */ + +#define RTC_REGISTER_B 0x0B + +#define RTC_REGISTER_CENTURY 0x32 + + +/* FUNCTIONS *****************************************************************/ + + +static UCHAR +HalpQueryCMOS(UCHAR Reg) +{ + UCHAR Val; + ULONG Flags; + + Reg |= 0x80; + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x70, Reg); + Val = READ_PORT_UCHAR((PUCHAR)0x71); + WRITE_PORT_UCHAR((PUCHAR)0x70, 0); + popfl(Flags); + + return(Val); +} + + +static VOID +HalpSetCMOS(UCHAR Reg, + UCHAR Val) +{ + ULONG Flags; + + Reg |= 0x80; + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x70, Reg); + WRITE_PORT_UCHAR((PUCHAR)0x71, Val); + WRITE_PORT_UCHAR((PUCHAR)0x70, 0); + popfl(Flags); +} + + +static UCHAR +HalpQueryECMOS(USHORT Reg) +{ + UCHAR Val; + ULONG Flags; + + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF)); + WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8)); + Val = READ_PORT_UCHAR((PUCHAR)0x76); + popfl(Flags); + + return(Val); +} + + +static VOID +HalpSetECMOS(USHORT Reg, + UCHAR Val) +{ + ULONG Flags; + + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF)); + WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8)); + WRITE_PORT_UCHAR((PUCHAR)0x76, Val); + popfl(Flags); +} + + +VOID STDCALL +HalQueryRealTimeClock(PTIME_FIELDS Time) +{ + /* check 'Update In Progress' bit */ + while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP) + ; + + Time->Second = BCD_INT(HalpQueryCMOS (0)); + Time->Minute = BCD_INT(HalpQueryCMOS (2)); + Time->Hour = BCD_INT(HalpQueryCMOS (4)); + Time->Weekday = BCD_INT(HalpQueryCMOS (6)); + Time->Day = BCD_INT(HalpQueryCMOS (7)); + Time->Month = BCD_INT(HalpQueryCMOS (8)); + Time->Year = BCD_INT(HalpQueryCMOS (9)); + + if (Time->Year > 80) + Time->Year += 1900; + else + Time->Year += 2000; + +#if 0 + /* Century */ + Time->Year += BCD_INT(HalpQueryCMOS (RTC_REGISTER_CENTURY)) * 100; +#endif + +#ifndef NDEBUG + DbgPrint ("HalQueryRealTimeClock() %d:%d:%d %d/%d/%d\n", + Time->Hour, + Time->Minute, + Time->Second, + Time->Day, + Time->Month, + Time->Year + ); +#endif + + Time->Milliseconds = 0; +} + + +VOID STDCALL +HalSetRealTimeClock(PTIME_FIELDS Time) +{ + /* check 'Update In Progress' bit */ + while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP) + ; + + HalpSetCMOS (0, INT_BCD(Time->Second)); + HalpSetCMOS (2, INT_BCD(Time->Minute)); + HalpSetCMOS (4, INT_BCD(Time->Hour)); + HalpSetCMOS (6, INT_BCD(Time->Weekday)); + HalpSetCMOS (7, INT_BCD(Time->Day)); + HalpSetCMOS (8, INT_BCD(Time->Month)); + HalpSetCMOS (9, INT_BCD(Time->Year % 100)); + +#if 0 + /* Century */ + HalpSetCMOS (RTC_REGISTER_CENTURY, INT_BCD(Time->Year / 100)); +#endif +} + + +BOOLEAN STDCALL +HalGetEnvironmentVariable(PCH Name, + PCH Value, + USHORT ValueLength) +{ + if (_stricmp(Name, "LastKnownGood") != 0) + { + return FALSE; + } + + if (HalpQueryCMOS(RTC_REGISTER_B) & 0x01) + { + strncpy(Value, "FALSE", ValueLength); + } + else + { + strncpy(Value, "TRUE", ValueLength); + } + + return TRUE; +} + + +BOOLEAN STDCALL +HalSetEnvironmentVariable(PCH Name, + PCH Value) +{ + UCHAR Val; + + if (_stricmp(Name, "LastKnownGood") != 0) + return FALSE; + + Val = HalpQueryCMOS(RTC_REGISTER_B); + + if (_stricmp(Value, "TRUE") == 0) + HalpSetCMOS(RTC_REGISTER_B, Val | 0x01); + else if (_stricmp(Value, "FALSE") == 0) + HalpSetCMOS(RTC_REGISTER_B, Val & ~0x01); + else + return FALSE; + + return TRUE; +} + + +ULONG STDCALL +HalpGetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PUCHAR Ptr = Buffer; + ULONG Address = SlotNumber; + ULONG Len = Length; + + DPRINT("HalpGetCmosData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if (Length == 0) + return 0; + + if (BusNumber == 0) + { + /* CMOS */ + while ((Len > 0) && (Address < 0x100)) + { + *Ptr = HalpQueryCMOS((UCHAR)Address); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + else if (BusNumber == 1) + { + /* Extended CMOS */ + while ((Len > 0) && (Address < 0x1000)) + { + *Ptr = HalpQueryECMOS((USHORT)Address); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + + return(Length - Len); +} + + +ULONG STDCALL +HalpSetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PUCHAR Ptr = (PUCHAR)Buffer; + ULONG Address = SlotNumber; + ULONG Len = Length; + + DPRINT("HalpSetCmosData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if (Length == 0) + return 0; + + if (BusNumber == 0) + { + /* CMOS */ + while ((Len > 0) && (Address < 0x100)) + { + HalpSetCMOS((UCHAR)Address, *Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + else if (BusNumber == 1) + { + /* Extended CMOS */ + while ((Len > 0) && (Address < 0x1000)) + { + HalpSetECMOS((USHORT)Address, *Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + + return(Length - Len); +} + +/* EOF */ diff --git a/hal/halx86/udelay.c b/hal/halx86/udelay.c new file mode 100644 index 0000000..d4ef150 --- /dev/null +++ b/hal/halx86/udelay.c @@ -0,0 +1,223 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * Copyright (C) 1999 Gareth Owen , Ramon von Handel + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/udelay.c + * PURPOSE: Busy waiting + * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + * UPDATE HISTORY: + * 06/11/99 Created + */ + +/* INCLUDES ***************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +static unsigned int delay_count = 1; + +#define MILLISEC (10) +#define FREQ (1000/MILLISEC) + +#define PRECISION (8) + +#define TMR_CTRL 0x43 /* I/O for control */ +#define TMR_CNT0 0x40 /* I/O for counter 0 */ +#define TMR_CNT1 0x41 /* I/O for counter 1 */ +#define TMR_CNT2 0x42 /* I/O for counter 2 */ + +#define TMR_SC0 0 /* Select channel 0 */ +#define TMR_SC1 0x40 /* Select channel 1 */ +#define TMR_SC2 0x80 /* Select channel 2 */ + +#define TMR_LOW 0x10 /* RW low byte only */ +#define TMR_HIGH 0x20 /* RW high byte only */ +#define TMR_BOTH 0x30 /* RW both bytes */ + +#define TMR_MD0 0 /* Mode 0 */ +#define TMR_MD1 0x2 /* Mode 1 */ +#define TMR_MD2 0x4 /* Mode 2 */ +#define TMR_MD3 0x6 /* Mode 3 */ +#define TMR_MD4 0x8 /* Mode 4 */ +#define TMR_MD5 0xA /* Mode 5 */ + +#define TMR_BCD 1 /* BCD mode */ + +#define TMR_LATCH 0 /* Latch command */ + +#define TMR_READ 0xF0 /* Read command */ +#define TMR_CNT 0x20 /* CNT bit (Active low, subtract it) */ +#define TMR_STAT 0x10 /* Status bit (Active low, subtract it) */ +#define TMR_CH2 0x8 /* Channel 2 bit */ +#define TMR_CH1 0x4 /* Channel 1 bit */ +#define TMR_CH0 0x2 /* Channel 0 bit */ + +static BOOLEAN UdelayCalibrated = FALSE; + +/* FUNCTIONS **************************************************************/ + +void init_pit(float h, unsigned char channel) +{ + unsigned int temp=0; + + temp = 1193180/h; + +// WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, +// (channel*0x40) + TMR_BOTH + TMR_MD3); + WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, + (channel*0x40) + TMR_BOTH + TMR_MD2); + WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), + (unsigned char) temp); + WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), + (unsigned char) (temp>>8)); +} + +VOID STDCALL +__KeStallExecutionProcessor(ULONG Loops) +{ + register unsigned int i; + for (i=0; i> 8); /* MSB */ + + /* Stage 1: Coarse calibration */ + + WaitFor8254Wraparound(); + + delay_count = 1; + + do { + delay_count <<= 1; /* Next delay count to try */ + + WaitFor8254Wraparound(); + + __KeStallExecutionProcessor(delay_count); /* Do the delay */ + + CurCount = Read8254Timer(); + } while (CurCount > LATCH / 2); + + delay_count >>= 1; /* Get bottom value for delay */ + + /* Stage 2: Fine calibration */ + DbgPrint("delay_count: %d", delay_count); + + calib_bit = delay_count; /* Which bit are we going to test */ + + for(i=0;i>= 1; /* Next bit to calibrate */ + if(!calib_bit) break; /* If we have done all bits, stop */ + + delay_count |= calib_bit; /* Set the bit in delay_count */ + + WaitFor8254Wraparound(); + + __KeStallExecutionProcessor(delay_count); /* Do the delay */ + + CurCount = Read8254Timer(); + if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */ + delay_count &= ~calib_bit; /* calibrated bit back off */ + } + + /* We're finished: Do the finishing touches */ + + delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */ + + DbgPrint("]\n"); + DbgPrint("delay_count: %d\n", delay_count); + DbgPrint("CPU speed: %d\n", delay_count/250); +#if 0 + DbgPrint("About to start delay loop test\n"); + DbgPrint("Waiting for five minutes..."); + for (i = 0; i < (5*60*1000*20); i++) + { + KeStallExecutionProcessor(50); + } + DbgPrint("finished\n"); + for(;;); +#endif +} + +/* EOF */ diff --git a/iface/addsys/.cvsignore b/iface/addsys/.cvsignore new file mode 100644 index 0000000..f63b9e9 --- /dev/null +++ b/iface/addsys/.cvsignore @@ -0,0 +1,3 @@ +genw32k +genw32k.exe + diff --git a/iface/addsys/genw32k.c b/iface/addsys/genw32k.c new file mode 100644 index 0000000..d7908c5 --- /dev/null +++ b/iface/addsys/genw32k.c @@ -0,0 +1,379 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS version of ntdll + * FILE: iface/native/genntdll.c + * PURPOSE: Generates the system call stubs in ntdll + * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ] + * 19990616 (ea) + * Four arguments now required; 4th is the file + * for ntoskrnl ZwXXX functions (which are merely calls + * to twin NtXXX calls, via int 0x2e (x86). + * 19990617 (ea) + * Fixed a bug in function numbers in kernel ZwXXX stubs. + * + */ + +/* INCLUDE ******************************************************************/ + +#include +#include +#include + +#define PARAMETERIZED_LIBS + +#define VERBOSE + +#define INPUT_BUFFER_SIZE 255 + +#define INDEX 0x1000 /* SSDT index 1 */ + + +/* FUNCTIONS ****************************************************************/ + +int makeSystemServiceTable(FILE *in, FILE *out) +{ +char line [INPUT_BUFFER_SIZE]; +char *s; +char *name; +int sys_call_idx; +char *nr_args; +char *stmp; + + /* + * Main SSDT Header + */ + fprintf(out,"// Machine generated, don't edit\n"); + fprintf(out,"\n\n"); + + /* + * First we build the Win32k SSDT + */ + fprintf(out,"SSDT Win32kSSDT[] = {\n"); + + /* First system call has index zero */ + sys_call_idx = 0; + + /* Go on until EOF or read zero bytes */ + while ((!feof(in))&& (fgets(line, sizeof line, in) != NULL)) + { + if ((s = (char *) strchr(line,'\r')) != NULL) + { + *s = '\0'; + } + /* + * Skip comments (#) and empty lines. + */ + s = & line[0]; + if ((*s) != '#' && (*s) != '\0') + { + /* Extract the NtXXX name */ + name = (char *)strtok(s," \t"); + /* Extract the stack size */ + nr_args = (char *)strtok(NULL," \t"); + /* + * Remove, if present, the trailing LF. + */ + if ((stmp = strchr(nr_args, '\n')) != NULL) + { + *stmp = '\0'; + } +#ifdef VERBOSE + printf("%3d \"%s\"\n",sys_call_idx | INDEX,name); +#endif + + if (sys_call_idx > 0) + { + fprintf(out,",\n"); + } + /* + * Now write the current system call's name + * in the service table. + */ + fprintf(out,"\t\t{ (ULONG)%s }",name); + + /* Next system call index */ + sys_call_idx++; + } + } + /* Close the service table (C syntax) */ + fprintf(out,"\n};\n"); + + /* + * Now we build the Win32k SSPT + */ + rewind(in); + fprintf(out,"\n\n"); + fprintf(out,"SSPT Win32kSSPT[] = {\n"); + + /* First system call has index zero */ + sys_call_idx = 0; + + /* Go on until EOF or read zero bytes */ + while ((!feof(in))&& (fgets(line, sizeof line, in) != NULL)) + { + if ((s = (char *) strchr(line,'\r')) != NULL) + { + *s = '\0'; + } + /* + * Skip comments (#) and empty lines. + */ + s = & line[0]; + if ((*s) != '#' && (*s) != '\0') + { + /* Extract the NtXXX name */ + name = (char *)strtok(s," \t"); + /* Extract the stack size */ + nr_args = (char *)strtok(NULL," \t"); + /* + * Remove, if present, the trailing LF. + */ + if ((stmp = strchr(nr_args, '\n')) != NULL) + { + *stmp = '\0'; + } +#ifdef VERBOSE + printf("%3d \"%s\"\n",sys_call_idx|INDEX,name); +#endif + + if (sys_call_idx > 0) + { + fprintf(out,",\n"); + } + /* + * Now write the current system call's ID + * in the service table along with its Parameters Size. + */ + fprintf(out,"\t\t{ %d }",atoi(nr_args) * sizeof(void*)); + + /* Next system call index */ + sys_call_idx++; + } + } + /* + * Close the service table (C syntax) + */ + fprintf(out,"\n};\n"); + + /* + * We write some useful defines + */ + fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); + fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1); + fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx); + fprintf(out, "ULONG Win32kNumberOfSysCalls = %d;\n", sys_call_idx); + + return(0); +} + + +int +process( + FILE * in, + FILE * out1, + FILE * out2, + FILE * out3 + ) +{ + char line [INPUT_BUFFER_SIZE]; + char * s; + char * name; /* NtXXX name */ + int sys_call_idx; /* NtXXX index number in the service table */ + char * nr_args; /* stack_size / machine_word_size */ + char * stmp; + int stacksize; + + /* + * GDI32 stubs file header + */ + fprintf(out1,"// Machine generated, don't edit\n"); + fprintf(out1,"\n\n"); + + /* + * USER32 stubs file header + */ + fprintf(out2,"// Machine generated, don't edit\n"); + fprintf(out2,"\n\n"); + + /* + * CSRSS stubs file header + */ + fprintf(out3,"// Machine generated, don't edit\n"); + fprintf(out3,"\n\n"); + + /* + * Scan the database. DB is a text file; each line + * is a record, which contains data for one system + * function. Each record has three columns: + * + * NT_NAME (e.g. NtCreateProcess) + * ZW_NAME (e.g. ZwCreateProcess) + * STACK_SIZE (in machine words: for x[3456]86 + * processors a machine word is 4 bytes) + */ + + /* First system call has index zero */ + sys_call_idx = 0; + while ( + /* Go on until EOF or read zero bytes */ + ( (!feof(in)) + && (fgets(line, sizeof line, in) != NULL) + ) + ) + { + /* + * Remove, if present, the trailing CR. + * (os specific?) + */ + if ((s = (char *) strchr(line,'\r')) != NULL) + { + *s = '\0'; + } + /* + * Skip comments (#) and empty lines. + */ + s = & line[0]; + if ((*s) != '#' && (*s) != '\0') + { + /* Extract the NtXXX name */ + name = (char *)strtok(s," \t"); + /* Extract the stack size */ + nr_args = (char *)strtok(NULL," \t"); + stacksize = atoi(nr_args)*sizeof(void*); + /* + * Remove, if present, the trailing LF. + */ + if ((stmp = strchr(nr_args, '\n')) != NULL) + { + *stmp = '\0'; + } +#ifdef VERBOSE + printf("%3d \"%s\"\n",sys_call_idx | INDEX,name); +#endif + + /* + * Write the GDI32 stub for the current system call. + */ +#ifdef PARAMETERIZED_LIBS + fprintf(out1,"__asm__(\"\\n\\t.global _%s@%d\\n\\t\"\n",name,stacksize); + fprintf(out1,"\"_%s@%d:\\n\\t\"\n",name,stacksize); +#else + fprintf(out1,"__asm__(\"\\n\\t.global _%s\\n\\t\"\n",name); + fprintf(out1,"\"_%s:\\n\\t\"\n",name); +#endif + fprintf(out1,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx | INDEX); + fprintf(out1,"\t\"lea\t4(%%esp),%%edx\\n\\t\"\n"); + fprintf(out1,"\t\"int\t$0x2E\\n\\t\"\n"); + fprintf(out1,"\t\"ret\t$%d\\n\\t\");\n\n",stacksize); + + /* + * Write the USER32 stub for the current system call + */ +#ifdef PARAMETERIZED_LIBS + fprintf(out2,"__asm__(\"\\n\\t.global _%s@%d\\n\\t\"\n",name,stacksize); + fprintf(out2,"\"_%s@%d:\\n\\t\"\n",name,stacksize); +#else + fprintf(out2,"__asm__(\"\\n\\t.global _%s\\n\\t\"\n",name); + fprintf(out2,"\"_%s:\\n\\t\"\n",name); +#endif + fprintf(out2,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx | INDEX); + fprintf(out2,"\t\"lea\t4(%%esp),%%edx\\n\\t\"\n"); + fprintf(out2,"\t\"int\t$0x2E\\n\\t\"\n"); + fprintf(out2,"\t\"ret\t$%d\\n\\t\");\n\n",stacksize); + + /* + * Write the CSRSS stub for the current system call + */ +#ifdef PARAMETERIZED_LIBS + fprintf(out3,"__asm__(\"\\n\\t.global _%s@%d\\n\\t\"\n",name,stacksize); + fprintf(out3,"\"_%s@%d:\\n\\t\"\n",name,stacksize); +#else + fprintf(out3,"__asm__(\"\\n\\t.global _%s\\n\\t\"\n",name); + fprintf(out3,"\"_%s:\\n\\t\"\n",name); +#endif + fprintf(out3,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx | INDEX); + fprintf(out3,"\t\"lea\t4(%%esp),%%edx\\n\\t\"\n"); + fprintf(out3,"\t\"int\t$0x2E\\n\\t\"\n"); + fprintf(out3,"\t\"ret\t$%d\\n\\t\");\n\n",stacksize); + + /* Next system call index */ + sys_call_idx++; + } + } + + return(0); +} + +void usage(char * argv0) +{ + printf("Usage: %s w32k.lst ssdt.h win32k.c win32k.c\n" + " w32k.lst system functions database\n" + " ssdt.h WIN32K service table\n" + " win32k.c GDI32 stubs\n" + " win32k.c USER32 stubs\n", + argv0 + ); +} + +int main(int argc, char* argv[]) +{ + FILE * in; /* System calls database */ + FILE * out1; /* SERVICE_TABLE */ + FILE * out2; /* GDI32 stubs */ + FILE * out3; /* USER32 stubs */ + FILE * out4; /* CSRSS stubs */ + int ret; + + if (argc != 6) + { + usage(argv[0]); + return(1); + } + + in = fopen(argv[1],"rb"); + if (in == NULL) + { + perror("Failed to open input file (system calls database)"); + return(1); + } + + out1 = fopen(argv[2],"wb"); + if (out1 == NULL) + { + perror("Failed to open output file (WIN32K service table)"); + return(1); + } + + out2 = fopen(argv[3],"wb"); + if (out2 == NULL) + { + perror("Failed to open output file (GDI32 stubs)"); + return(1); + } + + out3 = fopen(argv[4],"wb"); + if (out3 == NULL) + { + perror("Failed to open output file (USER32 stubs)"); + return(1); + } + + out4 = fopen(argv[5],"wb"); + if (out4 == NULL) + { + perror("Failed to open output file (CSRSS stubs)"); + return(1); + } + + ret = process(in,out2,out3,out4); + rewind(in); + ret = makeSystemServiceTable(in, out1); + + fclose(in); + fclose(out1); + fclose(out2); + fclose(out3); + + return(ret); +} diff --git a/iface/addsys/makefile b/iface/addsys/makefile new file mode 100644 index 0000000..e95bd5f --- /dev/null +++ b/iface/addsys/makefile @@ -0,0 +1,51 @@ +# $Id$ +# +# ReactOS Operating System +# +# Generate files for a kernel module that needs to add a service table. +# +PATH_TO_TOP = ../.. + +#TARGETNAME = mktab +TARGETNAME = genw32k + +# WIN32K.SYS +SVC_DB=w32ksvc.db +SVC_MASK=0x1000 + +# DOS and Win32 kernels handle Unix paths too. +SVC_SERVICE_TABLE=../../subsys/win32k/main/svctab.c +SVC_GDI_STUBS=../../lib/gdi32/misc/win32k.c +SVC_USER_STUBS=../../lib/user32/misc/win32k.c +SVC_CSRSS_STUBS=../../subsys/csrss/win32k.c + +SVC_FILES = $(SVC_GDI_STUBS) $(SVC_USER_STUBS) $(SVC_SERVICE_TABLE) + +CLEAN_FILES = $(TARGETNAME)$(EXE_POSTFIX) $(SVC_FILES) + +BASE_CFLAGS = -I../../include + +all: $(SVC_FILES) + +$(TARGETNAME)$(EXE_POSTFIX): $(TARGETNAME).c + $(HOST_CC) \ + $(CFLAGS) \ + -o $(TARGETNAME) \ + -O2 \ + $(TARGETNAME).c + +$(SVC_FILES): $(SVC_DB) $(TARGETNAME)$(EXE_POSTFIX) + ./$(TARGETNAME)$(EXE_POSTFIX) \ + $(SVC_DB) \ + $(SVC_SERVICE_TABLE) \ + $(SVC_GDI_STUBS) \ + $(SVC_USER_STUBS) \ + $(SVC_CSRSS_STUBS) + + +clean: + - $(RM) $(CLEAN_FILES) + +.PHONY: all clean + +include ../../rules.mak diff --git a/iface/addsys/w32ksvc.db b/iface/addsys/w32ksvc.db new file mode 100644 index 0000000..b1190ea --- /dev/null +++ b/iface/addsys/w32ksvc.db @@ -0,0 +1,544 @@ +# NAME ARG_COUNT +W32kAbortDoc 1 +W32kAbortPath 1 +W32kAddFontResource 1 +W32kAngleArc 6 +W32kAnimatePalette 4 +W32kArc 9 +W32kArcTo 9 +W32kBeginPath 1 +W32kBitBlt 9 +W32kCancelDC 1 +W32kCheckColorsInGamut 4 +#W32kChoosePixelFormat (2?) +W32kChord 9 +W32kCloseEnhMetaFile 1 +W32kCloseFigure 1 +W32kCloseMetaFile 1 +W32kColorMatchToTarget 3 +W32kCombineRgn 4 +W32kCombineTransform 3 +W32kCopyEnhMetaFile 2 +W32kCopyMetaFile 2 +W32kCreateBitmap 5 +W32kCreateBitmapIndirect 1 +W32kCreateBrushIndirect 1 +W32kCreateColorSpace 1 +W32kCreateCompatibleBitmap 3 +W32kCreateCompatableDC 1 +W32kCreateDC 4 +W32kCreateDIBitmap 6 +W32kCreateDIBPatternBrush 2 +W32kCreateDIBPatternBrushPt 2 +W32kCreateDIBSection 6 +W32kCreateDiscardableBitmap 3 +W32kCreateEllipticRgn 4 +W32kCreateEllipticRgnIndirect 1 +W32kCreateEnhMetaFile 4 +W32kCreateFont 14 +W32kCreateFontIndirect 1 +W32kCreateHalftonePalette 1 +W32kCreateHatchBrush 2 +W32kCreateIC 4 +W32kCreateMetaFile 1 +W32kCreatePalette 1 +W32kCreatePatternBrush 1 +W32kCreatePen 3 +W32kCreatePenIndirect 1 +W32kCreatePolygonRgn 3 +W32kCreatePolyPolygonRgn 4 +W32kCreateRectRgn 4 +W32kCreateRectRgnIndirect 1 +W32kCreateRoundRectRgn 6 +W32kCreateScalableFontResource 4 +W32kCreateSolidBrush 1 +W32kDPtoLP 3 +W32kDeleteColorSpace 1 +W32kDeleteDC 1 +W32kDeleteEnhMetaFile 1 +W32kDeleteMetaFile 1 +W32kDeleteObject 1 +W32kCleanupForProcess 1 +W32kDescribePixelFormat 4 +#W32kDeviceCapabilitiesEx ? +W32kDrawEscape 4 +W32kEllipse 5 +W32kEndDoc 1 +W32kEndPage 1 +W32kEndPath 1 +W32kEnumEnhMetaFile 5 +W32kEnumFontFamilies 4 +W32kEnumFontFamiliesEx 5 +W32kEnumFonts 4 +W32kEnumICMProfiles 3 +W32kEnumMetaFile 4 +W32kEnumObjects 4 +W32kEqualRgn 2 +W32kEscape 5 +W32kExcludeClipRect 5 +W32kExtCreatePen 5 +W32kExtCreateRegion 3 +W32kExtEscape 6 +W32kExtFloodFill 5 +W32kExtSelectClipRgn 3 +W32kExtTextOut 8 +W32kFillPath 1 +W32kFillRgn 3 +W32kFixBrushOrgEx 0 +W32kFlattenPath 1 +W32kFloodFill 4 +W32kFrameRgn 5 +W32kGdiComment 3 +W32kGdiFlush 0 +W32kGdiGetBatchLimit 0 +#W32kGdiPlayDCScript ? +#W32kGdiPlayJournal ? +#W32kGdiPlayScript ? +#W32kGdiPlaySpoolStream ? +W32kGdiSetBatchLimit 1 +W32kGetArcDirection 1 +W32kGetAspectRatioFilterEx 2 +W32kGetBitmapBits 3 +W32kGetBitmapDimensionEx 2 +W32kGetBkColor 1 +W32kGetBkMode 1 +W32kGetBoundsRect 3 +W32kGetBrushOrgEx 2 +W32kGetCharABCWidths 4 +W32kGetCharABCWidthsFloat 4 +W32kGetCharacterPlacement 6 +W32kGetCharWidth 4 +W32kGetCharWidth32 4 +W32kGetCharWidthFloat 4 +W32kGetClipBox 2 +W32kGetClipRgn 1 +W32kGetColorAdjustment 2 +W32kGetColorSpace 1 +W32kGetCurrentObject 2 +W32kGetCurrentPositionEx 2 +W32kGetDCOrgEx 2 +W32kGetDIBColorTable 4 +W32kGetDIBits 7 +W32kGetDeviceCaps 2 +W32kGetDeviceGammaRamp 2 +W32kGetEnhMetaFile 1 +W32kGetEnhMetaFileBits 3 +W32kGetEnhMetaFileDescription 3 +W32kGetEnhMetaFileHeader 3 +W32kGetEnhMetaFilePaletteEntries 3 +W32kGetEnhMetaFilePixelFormat 3 +W32kGetFontLanguageInfo 1 +#W32kGetFontResourceInfo ? +W32kGetGlyphOutline 7 +#W32kGetGlyphOutlineWow ? +W32kGetGraphicsMode 1 +W32kGetICMProfile 3 +W32kGetKerningPairs 3 +W32kGetLogColorSpace 3 +W32kGetMapMode 1 +W32kGetMetaFile 1 +W32kGetMetaFileBitsEx 3 +W32kGetMetaRgn 2 +W32kGetMiterLimit 2 +W32kGetNearestColor 2 +W32kGetNearestPaletteIndex 2 +W32kGetObject 3 +W32kGetObjectType 1 +W32kGetOutlineTextMetrics 3 +W32kGetPaletteEntries 4 +W32kGetPath 4 +W32kGetPixel 1 +W32kGetPixelFormat 1 +W32kGetPolyFillMode 1 +W32kGetROP2 1 +#W32kGetRandomRgn ? +W32kGetRasterizerCaps 2 +W32kGetRelAbs 1 +W32kGetRegionData 3 +W32kGetRgnBox 2 +W32kGetStockObject 1 +W32kGetStretchBltMode 1 +W32kGetSystemPaletteEntries 4 +W32kGetSystemPaletteUse 1 +W32kGetTextAlign 1 +W32kGetTextCharset 1 +W32kGetTextCharsetInfo 3 +W32kGetTextColor 1 +W32kGetTextExtentExPoint 7 +W32kGetTextExtentPoint 4 +W32kGetTextExtentPoint32 4 +W32kGetTextFace 3 +W32kGetTextMetrics 2 +W32kGetViewportExtEx 2 +W32kGetViewportOrgEx 2 +W32kGetWinMetaFileBits 5 +W32kGetWindowExtEx 2 +W32kGetWindowOrgEx 2 +W32kGetWorldTransform 2 +W32kInitialize 0 +W32kIntersectClipRect 5 +W32kInvertRgn 2 +W32kLPtoDP 3 +W32kLineTo 3 +W32kMaskBlt 12 +W32kModifyWorldTransform 3 +W32kMoveToEx 4 +W32kOffsetClipRgn 3 +W32kOffsetRgn 3 +W32kOffsetViewportOrgEx 4 +W32kOffsetWindowOrgEx 4 +W32kPaintRgn 2 +W32kPatBlt 6 +W32kPathToRegion 1 +W32kPie 9 +W32kPlayEnhMetaFile 3 +W32kPlayEnhMetaFileRecord 4 +W32kPlayMetaFile 2 +W32kPlayMetaFileRecord 4 +W32kPlgBlt 10 +W32kPolyBezier 3 +W32kPolyBezierTo 3 +W32kPolyDraw 4 +W32kPolyline 3 +W32kPolylineTo 3 +W32kPolyPolyline 4 +W32kPolyTextOut 3 +W32kPolygon 3 +W32kPolyPolygon 4 +W32kPtInRegion 3 +W32kPtVisible 3 +W32kRealizePalette 1 +W32kRectInRegion 2 +W32kRectVisible 2 +W32kRectangle 5 +W32kRemoveFontResource 1 +W32kResetDC 2 +W32kResizePalette 2 +W32kRestoreDC 2 +W32kRoundRect 7 +W32kSaveDC 1 +W32kScaleViewportExtEx 6 +W32kScaleWindowExtEx 6 +#W32kSelectBrushLocal ? +W32kSelectClipPath 2 +W32kSelectClipRgn 2 +#W32kSelectFontLocal ? +W32kSelectObject 2 +W32kSelectPalette 3 +W32kSetAbortProc 2 +W32kSetArcDirection 2 +W32kSetBitmapBits 3 +W32kSetBitmapDimensionEx 4 +W32kSetBkColor 2 +W32kSetBkMode 2 +W32kSetBoundsRect 3 +W32kSetBrushOrgEx 4 +W32kSetColorAdjustment 2 +W32kSetColorSpace 2 +W32kSetDIBColorTable 4 +W32kSetDIBits 7 +W32kSetDIBitsToDevice 12 +W32kSetDeviceGammaRamp 2 +W32kSetEnhMetaFileBits 2 +#W32kSetFontEnumeration ? +W32kSetGraphicsMode 2 +W32kSetICMMode 2 +W32kSetICMProfile 2 +W32kSetMapMode 2 +W32kSetMapperFlags 2 +W32kSetMetaFileBitsEx 2 +W32kSetMetaRgn 1 +W32kSetMiterLimit 3 +W32kSetPaletteEntries 4 +W32kSetPixel 4 +W32kSetPixelFormat 3 +W32kSetPixelV 4 +W32kSetPolyFillMode 2 +W32kSetROP2 2 +W32kSetRectRgn 5 +#W32kSetRelAbs 2 +W32kSetStretchBltMode 2 +W32kSetSystemPaletteUse 2 +W32kSetTextAlign 2 +W32kSetTextColor 2 +W32kSetTextJustification 3 +W32kSetViewportExtEx 4 +W32kSetViewportOrgEx 4 +#W32kSetWinMetaFileBits 1 +W32kSetWindowExtEx 4 +W32kSetWindowOrgEx 4 +W32kSetWorldTransform 2 +W32kStartDoc 2 +W32kStartPage 1 +W32kStretchBlt 11 +W32kStretchDIBits 13 +W32kStrokeAndFillPath 1 +W32kStrokePath 1 +W32kSwapBuffers 1 +W32kTextOut 5 +W32kTranslateCharsetInfo 3 +W32kUnrealizeObject 2 +W32kUpdateColors 1 +W32kUpdateICMRegKey 4 +W32kWidenPath 1 +NtUserActivateKeyboardLayout 2 +NtUserAlterWindowStyle 3 +NtUserAttachThreadInput 3 +NtUserBeginPaint 2 +NtUserBitBltSysBmp 8 +NtUserBlockInput 1 +NtUserBuildHwndList 7 +NtUserBuildNameList 4 +NtUserBuildPropList 4 +NtUserCallHwnd 2 +NtUserCallHwndLock 2 +NtUserCallHwndOpt 2 +NtUserCallHwndParam 3 +NtUserCallHwndParamLock 3 +NtUserCallMsgFilter 2 +NtUserCallNextHookEx 4 +NtUserCallNoParam 1 +NtUserCallOneParam 2 +NtUserCallTwoParam 3 +NtUserChangeClipboardChain 2 +NtUserChangeDisplaySettings 5 +NtUserCheckMenuItem 3 +NtUserChildWindowFromPointEx 4 +NtUserClipCursor 1 +NtUserCloseClipboard 0 +NtUserCloseDesktop 1 +NtUserCloseWindowStation 1 +NtUserConvertMemHandle 2 +NtUserCopyAcceleratorTable 3 +NtUserCountClipboardFormats 0 +NtUserCreateAcceleratorTable 2 +NtUserCreateCaret 4 +NtUserCreateDesktop 5 +NtUserCreateLocalMemHandle 4 +NtUserCreateWindowEx 13 +NtUserCreateWindowStation 6 +NtUserDdeGetQualityOfService 3 +NtUserDdeInitialize 5 +NtUserDdeSetQualityOfService 3 +NtUserDeferWindowPos 8 +NtUserDefSetText 2 +NtUserDeleteMenu 3 +NtUserDestroyAcceleratorTable 1 +NtUserDestroyCursor 2 +NtUserDestroyMenu 1 +NtUserDestroyWindow 1 +NtUserDispatchMessage 1 +NtUserDragDetect 3 +NtUserDragObject 5 +NtUserDrawAnimatedRects 4 +NtUserDrawCaption 4 +NtUserDrawCaptionTemp 7 +NtUserDrawIconEx 11 +NtUserDrawMenuBarTemp 5 +NtUserEmptyClipboard 0 +NtUserEnableMenuItem 3 +NtUserEnableScrollBar 3 +NtUserEndDeferWindowPosEx 2 +NtUserEndMenu 0 +NtUserEndPaint 2 +NtUserEnumDisplayDevices 4 +NtUserEnumDisplayMonitors 4 +NtUserEnumDisplaySettings 4 +NtUserEvent 1 +NtUserExcludeUpdateRgn 2 +NtUserFillWindow 4 +NtUserFindExistingCursorIcon 3 +NtUserFindWindowEx 5 +NtUserFlashWindowEx 1 +NtUserGetAltTabInfo 6 +NtUserGetAncestor 2 +NtUserGetAsyncKeyState 1 +NtUserGetCaretBlinkTime 0 +NtUserGetCaretPos 1 +NtUserGetClassInfo 5 +NtUserGetClassLong 2 +NtUserGetClassName 3 +NtUserGetClientOrigin 2 +NtUserGetClipboardData 2 +NtUserGetClipboardFormatName 3 +NtUserGetClipboardOwner 0 +NtUserGetClipboardSequenceNumber 0 +NtUserGetClipboardViewer 0 +NtUserGetClipCursor 1 +NtUserGetComboBoxInfo 2 +NtUserGetControlBrush 3 +NtUserGetControlColor 4 +NtUserGetCPD 3 +NtUserGetCursorFrameInfo 4 +NtUserGetCursorInfo 1 +NtUserGetDC 1 +NtUserGetDCEx 3 +NtUserGetDoubleClickTime 0 +NtUserGetForegroundWindow 0 +NtUserGetGuiResources 2 +NtUserGetGUIThreadInfo 2 +NtUserGetIconInfo 6 +NtUserGetIconSize 4 +NtUserGetImeHotKey 4 +NtUserGetInternalWindowPos 3 +NtUserGetKeyboardLayoutList 2 +NtUserGetKeyboardLayoutName 1 +NtUserGetKeyboardState 1 +NtUserGetKeyNameText 3 +NtUserGetKeyState 1 +NtUserGetListBoxInfo 1 +NtUserGetMenuBarInfo 4 +NtUserGetMenuIndex 2 +NtUserGetMenuItemRect 4 +NtUserGetMessage 4 +NtUserGetMouseMovePointsEx 5 +NtUserGetObjectInformation 5 +NtUserGetOpenClipboardWindow 0 +NtUserGetProp 2 +NtUserGetPriorityClipboardFormat 2 +NtUserGetProcessWindowStation 0 +NtUserGetScrollBarInfo 3 +NtUserGetSystemMenu 2 +NtUserGetSystemMetrics 1 +NtUserGetThreadDesktop 2 +NtUserGetThreadState 1 +NtUserGetTitleBarInfo 2 +NtUserGetUpdateRect 3 +NtUserGetUpdateRgn 3 +NtUserGetWindowDC 1 +NtUserGetWindowPlacement 2 +NtUserGetWindowLong 2 +NtUserGetWindowRect 2 +NtUserGetWOWClass 2 +NtUserHideCaret 1 +NtUserHiliteMenuItem 4 +NtUserImpersonateDdeClientWindow 2 +NtUserInitializeClientPfnArrays 4 +NtUserInitTask 11 +NtUserInternalGetWindowText 3 +NtUserInvalidateRect 3 +NtUserInvalidateRgn 3 +NtUserIsClipboardFormatAvailable 1 +NtUserKillTimer 2 +NtUserLoadKeyboardLayoutEx 6 +NtUserLockWindowStation 1 +NtUserLockWindowUpdate 1 +NtUserLockWorkStation 0 +NtUserMapVirtualKeyEx 4 +NtUserMenuItemFromPoint 4 +NtUserMessageCall 7 +NtUserMinMaximize 3 +NtUserMNDragLeave 0 +NtUserMNDragOver 2 +NtUserModifyUserStartupInfoFlags 2 +NtUserMoveWindow 6 +NtUserNotifyIMEStatus 3 +NtUserNotifyWinEvent 4 +NtUserOpenClipboard 2 +NtUserOpenDesktop 3 +NtUserOpenInputDesktop 3 +NtUserOpenWindowStation 2 +NtUserPaintDesktop 1 +NtUserPeekMessage 5 +NtUserPostMessage 4 +NtUserPostThreadMessage 4 +NtUserQuerySendMessage 1 +NtUserQueryUserCounters 5 +NtUserQueryWindow 2 +NtUserRealChildWindowFromPoint 3 +NtUserRedrawWindow 4 +NtUserRegisterClassExWOW 6 +NtUserRegisterHotKey 4 +NtUserRegisterTasklist 1 +NtUserRegisterWindowMessage 1 +NtUserRemoveMenu 3 +NtUserRemoveProp 2 +NtUserResolveDesktopForWOW 1 +NtUserSBGetParms 4 +NtUserScrollDC 7 +NtUserScrollWindowEx 8 +NtUserSendInput 3 +NtUserSendMessage 4 +NtUserSendMessageCallback 6 +NtUserSendNotifyMessage 4 +NtUserSetActiveWindow 1 +NtUserSetCapture 1 +NtUserSetClassLong 4 +NtUserSetClassWord 3 +NtUserSetClipboardData 3 +NtUserSetClipboardViewer 1 +NtUserSetConsoleReserveKeys 2 +NtUserSetCursor 1 +NtUserSetCursorContents 2 +NtUserSetCursorIconData 4 +NtUserSetDbgTag 2 +NtUserSetFocus 1 +NtUserSetImeHotKey 5 +NtUserSetImeOwnerWindow 2 +NtUserSetInternalWindowPos 4 +NtUserSetKeyboardState 1 +NtUserSetLayeredWindowAttributes 4 +NtUserSetLogonNotifyWindow 1 +NtUserSetMenu 3 +NtUserSetMenuContextHelpId 2 +NtUserSetMenuDefaultItem 3 +NtUserSetMenuFlagRtoL 1 +NtUserSetObjectInformation 4 +NtUserSetParent 2 +NtUserSetProcessWindowStation 1 +NtUserSetProp 3 +NtUserSetRipFlags 2 +NtUserSetScrollInfo 4 +NtUserSetShellWindowEx 2 +NtUserSetSysColors 4 +NtUserSetSystemCursor 2 +NtUserSetSystemMenu 2 +NtUserSetSystemTimer 4 +NtUserSetThreadDesktop 1 +NtUserSetThreadState 2 +NtUserSetTimer 4 +NtUserSetWindowFNID 2 +NtUserSetWindowLong 4 +NtUserSetWindowPlacement 2 +NtUserSetWindowPos 7 +NtUserSetWindowRgn 3 +NtUserSetWindowsHookAW 3 +NtUserSetWindowsHookEx 6 +NtUserSetWindowStationUser 4 +NtUserSetWindowWord 3 +NtUserSetWinEventHook 8 +NtUserShowCaret 1 +NtUserShowScrollBar 3 +NtUserShowWindow 2 +NtUserShowWindowAsync 2 +NtUserSwitchDesktop 1 +NtUserSystemParametersInfo 4 +NtUserThunkedMenuInfo 2 +NtUserThunkedMenuItemInfo 6 +NtUserToUnicodeEx 7 +NtUserTrackMouseEvent 1 +NtUserTrackPopupMenuEx 6 +NtUserTranslateAccelerator 3 +NtUserTranslateMessage 2 +NtUserUnhookWindowsHookEx 1 +NtUserUnhookWinEvent 1 +NtUserUnloadKeyboardLayout 1 +NtUserUnlockWindowStation 1 +NtUserUnregisterClass 3 +NtUserUnregisterHotKey 2 +NtUserUpdateInputContext 3 +NtUserUpdateInstance 3 +NtUserUpdateLayeredWindow 9 +NtUserUpdatePerUserSystemParameters 2 +NtUserUserHandleGrantAccess 3 +NtUserValidateHandleSecure 1 +NtUserValidateRect 2 +NtUserVkKeyScanEx 3 +NtUserWaitForInputIdle 3 +NtUserWaitForMsgAndEvent 1 +NtUserWaitMessage 0 +NtUserWin32PoolAllocationStats 6 +NtUserWindowFromPoint 2 +NtUserYieldTask 0 +# ReactOS only system calls +NtUserAcquireOrReleaseInputOwnership 1 diff --git a/iface/dll/.cvsignore b/iface/dll/.cvsignore new file mode 100644 index 0000000..f94cbe9 --- /dev/null +++ b/iface/dll/.cvsignore @@ -0,0 +1,2 @@ +defedf +defedf.exe diff --git a/iface/dll/defedf.c b/iface/dll/defedf.c new file mode 100644 index 0000000..d23cf57 --- /dev/null +++ b/iface/dll/defedf.c @@ -0,0 +1,315 @@ +/* $Id$ + * + * reactos/iface/dll/defedf.c + * + * ReactOS Operating System + * + * Convert a *.def file for a PE image into an *.edf file, + * to build the PE image with a clean exports table. + * + * Written by EA (19990703) + * + */ +#include +#include +#include +#ifndef MAX_PATH +# ifdef PATH_MAX +# define MAX_PATH PATH_MAX +# else +# define MAX_PATH _MAX_PATH +# endif +#endif +#include + +#define INPUT_BUFFER_SIZE 1024 + +//#define DEBUG + +static const char * SUFFIX_DEF = ".def"; +static const char * SUFFIX_EDF = ".edf"; + + +int +Usage ( const char * ImageName ) +{ + fprintf( + stderr, + "Usage: %s def_file [edf_file]\n", + ImageName + ); + return EXIT_SUCCESS; +} + + +char * +AddSuffix ( + const char * Prototype, + const char * Suffix + ) +{ + char NewName [MAX_PATH]; + char * SuffixStart; + + if (!Prototype) return NULL; + strcpy( NewName, Prototype ); + SuffixStart = + NewName + + strlen(NewName) + - strlen(Suffix); + if (strcmp(SuffixStart,Suffix)) + { + strcat(NewName, Suffix); + } + return strdup(NewName); +} + + +char * +MakeEdfName ( + const char * NameDef, + const char * NameEdf + ) +{ + if (NULL == NameEdf) + { + char NewName [MAX_PATH]; + char * Dot; + + strcpy( NewName, NameDef ); + Dot = strrchr( NewName, '.'); + if (0 == strcmp(Dot, SUFFIX_DEF)) + { + *Dot = '\0'; + } + return AddSuffix( NewName, SUFFIX_EDF ); + } + return AddSuffix( NameEdf, SUFFIX_EDF ); +} + + +typedef +enum +{ + LineLibrary, + LineExports, + LineImports, + LineSymbol, +// LineSymbolCdecl, +// LineSymbolStdcall, +// LineSymbolFastcall, +// LineSymbolData, + LineComment, + LineEmpty + +} PARSING_EXIT_CODE; + + +PARSING_EXIT_CODE +ParseInput ( + char * InputBuffer, + char * CleanName + ) +{ + char * r; + + r = strrchr( InputBuffer, '\n' ); + if (r) *r = '\0'; +#ifdef DEBUG +printf("ParseInput(%s)\n",InputBuffer); +#endif + if (0 == strlen(InputBuffer)) + { +#ifdef DEBUG +printf("LineEmpty\n"); +#endif + return LineEmpty; + } + /* + * Skip blanks and tabs. + */ + for ( InputBuffer; + ( + (*InputBuffer) + && (*InputBuffer == ' ') + && (*InputBuffer == '\t') + ); + InputBuffer++ + ); +#ifdef DEBUG +printf("1st=\"%c\" (%d)\n", *InputBuffer, (int) *InputBuffer ); +#endif + r = InputBuffer; + if (*r == ';') + { + strcpy( InputBuffer, r ); +#ifdef DEBUG +printf("LineComment\n"); +#endif + return LineComment; + } + r = strchr( InputBuffer, '=' ); + if (r) + { + printf( "Fatal error: can not process DEF files with aliases!\n"); + exit(EXIT_FAILURE); + } + r = strchr( InputBuffer, '@' ); + if (r) + { + strcpy( CleanName, InputBuffer ); + r = strchr( CleanName, '@' ); + *r = '\0'; +#ifdef DEBUG +printf("LineSymbol: \"%s\"=\"%s\"\n",InputBuffer,CleanName); +#endif + return LineSymbol; + } + /* can not recognize it; copy it verbatim */ +#ifdef DEBUG +printf("LineComment\n"); +#endif + return LineComment; +} + + +int +DefEdf ( + const char * ImageName, + const char * Def, + const char * Edf + ) +{ + FILE * fDef; + FILE * fEdf; + char InputBuffer [INPUT_BUFFER_SIZE]; + + printf( + "%s --> %s\n", + Def, + Edf + ); + fDef = fopen( Def, "r" ); + if (!fDef) + { + fprintf( + stderr, + "%s: could not open \"%s\"\n", + ImageName, + Def + ); + return EXIT_FAILURE; + } + fEdf = fopen( Edf, "w" ); + if (!fEdf) + { + fprintf( + stderr, + "%s: could not create \"%s\"\n", + ImageName, + Edf + ); + return EXIT_FAILURE; + } + while ( fgets( InputBuffer, sizeof InputBuffer, fDef ) ) + { + char CleanName [MAX_PATH]; + + switch (ParseInput(InputBuffer,CleanName)) + { + case LineLibrary: + fprintf(fEdf,"%s\n",InputBuffer); + break; + + case LineExports: + fprintf(fEdf,"EXPORTS\n"); + break; + + case LineImports: + fprintf(fEdf,"IMPORTS\n"); + break; + + case LineSymbol: + fprintf( + fEdf, + "%s=%s\n", + CleanName, + InputBuffer + ); + break; + + case LineComment: + fprintf( + fEdf, + "%s\n", + InputBuffer + ); + break; + + case LineEmpty: + fprintf( + fEdf, + "\n" + ); + break; + } + } + fclose(fDef); + fclose(fEdf); + return EXIT_SUCCESS; +} + + +int +main( + int argc, + char * argv [] + ) +{ + char * NameDef; + char * NameEdf; + int rv; + + + if ((argc != 2) && (argc != 3)) + { + return Usage(argv[0]); + } + NameDef = AddSuffix( + argv [1], + SUFFIX_DEF + ); + if (!NameDef) + { + fprintf( + stderr, + "%s: can not build the def_file name\n", + argv [0] + ); + return EXIT_FAILURE; + } + NameEdf = MakeEdfName( + NameDef, + argv [2] + ); + if (!NameEdf) + { + fprintf( + stderr, + "%s: can not build the edf_file name\n", + argv [0] + ); + free(NameDef); + return EXIT_FAILURE; + } + rv = DefEdf( + argv [0], + NameDef, + NameEdf + ); + free(NameDef); + free(NameEdf); + return rv; +} + +/* EOF */ diff --git a/iface/dll/makefile b/iface/dll/makefile new file mode 100644 index 0000000..d47fd1f --- /dev/null +++ b/iface/dll/makefile @@ -0,0 +1,24 @@ +# $Id$ +# +# ReactOS Operating System +# +# Generate: +# - defedf +# +PATH_TO_TOP = ../.. + +TARGET = defedf + +BASE_CFLAGS = -I../../include + +all: $(TARGET)$(EXE_POSTFIX) + +$(TARGET)$(EXE_POSTFIX): $(TARGET).c + $(CC) -g $(TARGET).c -o $(TARGET)$(EXE_POSTFIX) + +clean: + - $(RM) $(TARGET)$(EXE_POSTFIX) + +.PHONY: all clean + +include ../../rules.mak diff --git a/iface/native/.cvsignore b/iface/native/.cvsignore new file mode 100644 index 0000000..6abf3b2 --- /dev/null +++ b/iface/native/.cvsignore @@ -0,0 +1,2 @@ +genntdll +genntdll.exe diff --git a/iface/native/genntdll.c b/iface/native/genntdll.c new file mode 100644 index 0000000..5d72e90 --- /dev/null +++ b/iface/native/genntdll.c @@ -0,0 +1,370 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS version of ntdll + * FILE: iface/native/genntdll.c + * PURPOSE: Generates the system call stubs in ntdll + * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ] + * 19990616 (ea) + * Four arguments now required; 4th is the file + * for ntoskrnl ZwXXX functions (which are merely calls + * to twin NtXXX calls, via int 0x2e (x86). + * 19990617 (ea) + * Fixed a bug in function numbers in kernel ZwXXX stubs. + * + */ + +/* INCLUDE ******************************************************************/ + +#include +#include +#include + +#define PARAMETERIZED_LIBS + +#define VERBOSE + +#define INPUT_BUFFER_SIZE 255 + +/* FUNCTIONS ****************************************************************/ + +void write_syscall_stub(FILE* out, FILE* out3, char* name, char* name2, + unsigned int nr_args, unsigned int sys_call_idx) +{ +#ifdef PARAMETERIZED_LIBS + fprintf(out,"__asm__(\"\\n\\t.global _%s@%s\\n\\t\"\n",name,nr_args); + fprintf(out,"\".global _%s@%s\\n\\t\"\n",name2,nr_args); + fprintf(out,"\"_%s@%s:\\n\\t\"\n",name,nr_args); + fprintf(out,"\"_%s@%s:\\n\\t\"\n",name2,nr_args); +#else + fprintf(out,"__asm__(\"\\n\\t.global _%s\\n\\t\"\n",name); + fprintf(out,"\".global _%s\\n\\t\"\n",name2); + fprintf(out,"\"_%s:\\n\\t\"\n",name); + fprintf(out,"\"_%s:\\n\\t\"\n",name2); +#endif + fprintf(out,"\t\"pushl\t%%ebp\\n\\t\"\n"); + fprintf(out,"\t\"movl\t%%esp, %%ebp\\n\\t\"\n"); + fprintf(out,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx); + fprintf(out,"\t\"lea\t8(%%ebp),%%edx\\n\\t\"\n"); + fprintf(out,"\t\"int\t$0x2E\\n\\t\"\n"); + fprintf(out,"\t\"popl\t%%ebp\\n\\t\"\n"); + fprintf(out,"\t\"ret\t$%s\\n\\t\");\n\n",nr_args); + + /* + * Now write the NTOSKRNL stub for the + * current system call. ZwXXX does NOT + * alias the corresponding NtXXX call. + */ + fprintf(out3,"__asm__(\n"); + fprintf(out3,"\".global _%s@%s\\n\\t\"\n",name2,nr_args); + fprintf(out3,"\"_%s@%s:\\n\\t\"\n",name2,nr_args); + fprintf(out3,"\t\"pushl\t%%ebp\\n\\t\"\n"); + fprintf(out3,"\t\"movl\t%%esp, %%ebp\\n\\t\"\n"); + fprintf(out3,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx); + fprintf(out3,"\t\"lea\t8(%%ebp),%%edx\\n\\t\"\n"); + fprintf(out3,"\t\"int\t$0x2E\\n\\t\"\n"); + fprintf(out3,"\t\"popl\t%%ebp\\n\\t\"\n"); + fprintf(out3,"\t\"ret\t$%s\\n\\t\");\n\n",nr_args); +} + +int makeSystemServiceTable(FILE *in, FILE *out) +{ +char line [INPUT_BUFFER_SIZE]; +char *s; +char *name; +char *name2; +int sys_call_idx; +char *nr_args; +char *stmp; + + /* + * Main SSDT Header + */ + fprintf(out,"// Machine generated, don't edit\n"); + fprintf(out,"\n\n"); + + /* + * First we build the Main SSDT + */ + fprintf(out,"\n\n\n"); + fprintf(out,"SSDT MainSSDT[] = {\n"); + + for ( /* First system call has index zero */ + sys_call_idx = 0; + /* Go on until EOF or read zero bytes */ + ( (!feof(in)) + && (fgets(line, sizeof line, in) != NULL) + ); + /* Next system call index */ + sys_call_idx++ + ) + { + if ((s = (char *) strchr(line,'\r')) != NULL) + { + *s = '\0'; + } + /* + * Skip comments (#) and empty lines. + */ + s = & line[0]; + if ((*s) != '#' && (*s) != '\0') + { + /* Extract the NtXXX name */ + name = (char *)strtok(s," \t"); + /* Extract the ZwXXX name */ + name2 = (char *)strtok(NULL," \t"); + //value = strtok(NULL," \t"); + /* Extract the stack size */ + nr_args = (char *)strtok(NULL," \t"); + /* + * Remove, if present, the trailing LF. + */ + if ((stmp = strchr(nr_args, '\n')) != NULL) + { + *stmp = '\0'; + } +#ifdef VERBOSE + printf("%3d \"%s\"\n",sys_call_idx,name); +#endif + + if (sys_call_idx > 0) + { + fprintf(out,",\n"); + } + /* + * Now write the current system call's name + * in the service table. + */ + fprintf(out,"\t\t{ (ULONG)%s }",name); + } + } + /* Close the service table (C syntax) */ + fprintf(out,"\n};\n"); + + /* + * Now we build the Main SSPT + */ + rewind(in); + fprintf(out,"\n\n\n"); + fprintf(out,"SSPT MainSSPT[] = {\n"); + + for ( /* First system call has index zero */ + sys_call_idx = 0; + /* Go on until EOF or read zero bytes */ + ( (!feof(in)) + && (fgets(line, sizeof line, in) != NULL) + ); + /* Next system call index */ + sys_call_idx++ + ) + { + if ((s = (char *) strchr(line,'\r')) != NULL) + { + *s = '\0'; + } + /* + * Skip comments (#) and empty lines. + */ + s = & line[0]; + if ((*s) != '#' && (*s) != '\0') + { + /* Extract the NtXXX name */ + name = (char *)strtok(s," \t"); + /* Extract the ZwXXX name */ + name2 = (char *)strtok(NULL," \t"); + //value = strtok(NULL," \t"); + /* Extract the stack size */ + nr_args = (char *)strtok(NULL," \t"); + /* + * Remove, if present, the trailing LF. + */ + if ((stmp = strchr(nr_args, '\n')) != NULL) + { + *stmp = '\0'; + } +#ifdef VERBOSE + printf("%3d \"%s\"\n",sys_call_idx,name); +#endif + + if (sys_call_idx > 0) + { + fprintf(out,",\n"); + } + /* + * Now write the current system call's ID + * in the service table along with its Parameters Size. + */ + fprintf(out,"\t\t{ %s }",nr_args); + } + } + /* + * Close the service table (C syntax) + */ + fprintf(out,"\n};\n"); + + /* + * We write some useful defines + */ + fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); + fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1); + fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx); + + return(0); +} + + +int +process( + FILE * in, + FILE * out, + FILE * out2, + FILE * out3 + ) +{ + char line [INPUT_BUFFER_SIZE]; + char * s; + char * name; /* NtXXX name */ + char * name2; /* ZwXXX name */ + int sys_call_idx; /* NtXXX index number in the service table */ + char * nr_args; /* stack_size / machine_word_size */ + char * stmp; + + /* + * NTDLL stubs file header + */ + fprintf(out,"// Machine generated, don't edit\n"); + fprintf(out,"\n\n"); + + /* + * NTOSKRNL Zw functions stubs header + */ + fprintf(out3,"// Machine generated, don't edit\n"); + fprintf(out3,"\n\n"); + /* + * Scan the database. DB is a text file; each line + * is a record, which contains data for one system + * function. Each record has three columns: + * + * NT_NAME (e.g. NtCreateProcess) + * ZW_NAME (e.g. ZwCreateProcess) + * STACK_SIZE (in machine words: for x[3456]86 + * processors a machine word is 4 bytes) + */ + for ( /* First system call has index zero */ + sys_call_idx = 0; + /* Go on until EOF or read zero bytes */ + ( (!feof(in)) + && (fgets(line, sizeof line, in) != NULL) + ); + /* Next system call index */ + sys_call_idx++ + ) + { + /* + * Remove, if present, the trailing CR. + * (os specific?) + */ + if ((s = (char *) strchr(line,'\r')) != NULL) + { + *s = '\0'; + } + /* + * Skip comments (#) and empty lines. + */ + s = & line[0]; + if ((*s) != '#' && (*s) != '\0') + { + /* Extract the NtXXX name */ + name = (char *)strtok(s," \t"); + /* Extract the ZwXXX name */ + name2 = (char *)strtok(NULL," \t"); + //value = strtok(NULL," \t"); + /* Extract the stack size */ + nr_args = (char *)strtok(NULL," \t"); + /* + * Remove, if present, the trailing LF. + */ + if ((stmp = strchr(nr_args, '\n')) != NULL) + { + *stmp = '\0'; + } +#ifdef VERBOSE + printf("%3d \"%s\"\n",sys_call_idx,name); +#endif + /* + * Write the NTDLL stub for the current + * system call: NtXXX and ZwXXX symbols + * are aliases. + */ + write_syscall_stub(out, out3, name, name2, + nr_args, sys_call_idx); + } + } + + return(0); +} + +void usage(char * argv0) +{ + printf("Usage: %s sysfuncs.lst napi.c napi.h zw.c\n" + " sysfuncs.lst system functions database\n" + " napi.c NTDLL stubs\n" + " napi.h NTOSKRNL service table\n" + " zw.c NTOSKRNL Zw stubs\n", + argv0 + ); +} + +int main(int argc, char* argv[]) +{ + FILE * in; /* System calls database */ + FILE * out1; /* NTDLL stubs */ + FILE * out2; /* SERVICE_TABLE */ + FILE * out3; /* NTOSKRNL Zw stubs */ + int ret; + + if (argc != 5) + { + usage(argv[0]); + return(1); + } + + in = fopen(argv[1],"rb"); + if (in == NULL) + { + perror("Failed to open input file (system calls database)"); + return(1); + } + + out1 = fopen(argv[2],"wb"); + if (out1 == NULL) + { + perror("Failed to open output file (NTDLL stubs)"); + return(1); + } + + out2 = fopen(argv[3],"wb"); + if (out2 == NULL) + { + perror("Failed to open output file (NTOSKRNL service table)"); + return(1); + } + + out3 = fopen(argv[4],"wb"); + if (out3 == NULL) + { + perror("Failed to open output file (NTOSKRNL Zw stubs)"); + return(1); + } + + ret = process(in,out1,out2,out3); + rewind(in); + ret = makeSystemServiceTable(in, out2); + + fclose(in); + fclose(out1); + fclose(out2); + fclose(out3); + + return(ret); +} diff --git a/iface/native/makefile b/iface/native/makefile new file mode 100644 index 0000000..a5a8415 --- /dev/null +++ b/iface/native/makefile @@ -0,0 +1,40 @@ +# $Id$ +# +# ReactOS Operating System +# +# Generate: +# - genntdll +# - ntoskrnl.exe service table; +# - ntoskrnl.exe Zw functions stubs to call Nt functions from kernel mode; +# - ntdll.dll stubs to call system functions from user mode applications. +# +PATH_TO_TOP = ../.. + +TARGET = genntdll +SYSTEM_CALLS_DB = sysfuncs.lst +NTDLL_STUBS = ../../lib/ntdll/napi.c +KERNEL_SERVICE_TABLE = ../../include/ntdll/napi.h +KERNEL_ZW_CALLS = ../../ntoskrnl/nt/zw.c +NAPI_FILES = $(NTDLL_STUBS) $(KERNEL_SERVICE_TABLE) $(KERNEL_ZW_CALLS) + +BASE_CFLAGS = -I../../include + +all: $(TARGET)$(EXE_POSTFIX) $(NAPI_FILES) + +$(NAPI_FILES): $(SYSTEM_CALLS_DB) $(TARGET)$(EXE_POSTFIX) + ./$(TARGET)$(EXE_POSTFIX) \ + $(SYSTEM_CALLS_DB) \ + $(NTDLL_STUBS) \ + $(KERNEL_SERVICE_TABLE) \ + $(KERNEL_ZW_CALLS) + +# (rjj) i removed the following option from line below: -If:\gnu\mingw32\include +$(TARGET)$(EXE_POSTFIX): $(TARGET).c + $(HOST_CC) -g $(TARGET).c -o $(TARGET)$(EXE_POSTFIX) + +clean: + - $(RM) $(TARGET)$(EXE_POSTFIX) $(NTDLL_STUBS) $(KERNEL_SERVICE_TABLE) $(KERNEL_ZW_CALLS) + +.PHONY: all clean + +include ../../rules.mak diff --git a/iface/native/sysfuncs.lst b/iface/native/sysfuncs.lst new file mode 100644 index 0000000..a1a1de9 --- /dev/null +++ b/iface/native/sysfuncs.lst @@ -0,0 +1,211 @@ +NtAcceptConnectPort ZwAcceptConnectPort 24 +NtAccessCheck ZwAccessCheck 32 +NtAccessCheckAndAuditAlarm ZwAccessCheckAndAuditAlarm 44 +NtAddAtom ZwAddAtom 8 +NtAdjustGroupsToken ZwAdjustGroupsToken 24 +NtAdjustPrivilegesToken ZwAdjustPrivilegesToken 24 +NtAlertResumeThread ZwAlertResumeThread 8 +NtAlertThread ZwAlertThread 4 +NtAllocateLocallyUniqueId ZwAllocateLocallyUniqueId 4 +NtAllocateUuids ZwAllocateUuids 12 +NtAllocateVirtualMemory ZwAllocateVirtualMemory 24 +NtCallbackReturn ZwCallbackReturn 12 +NtCancelIoFile ZwCancelIoFile 8 +NtCancelTimer ZwCancelTimer 8 +NtClearEvent ZwClearEvent 4 +NtClose ZwClose 4 +NtCloseObjectAuditAlarm ZwCloseObjectAuditAlarm 12 +NtCompleteConnectPort ZwCompleteConnectPort 4 +NtConnectPort ZwConnectPort 32 +NtContinue ZwContinue 8 +NtCreateDirectoryObject ZwCreateDirectoryObject 12 +NtCreateEvent ZwCreateEvent 20 +NtCreateEventPair ZwCreateEventPair 12 +NtCreateFile ZwCreateFile 44 +NtCreateIoCompletion ZwCreateIoCompletion 16 +NtCreateKey ZwCreateKey 28 +NtCreateMailslotFile ZwCreateMailslotFile 32 +NtCreateMutant ZwCreateMutant 16 +NtCreateNamedPipeFile ZwCreateNamedPipeFile 56 +NtCreatePagingFile ZwCreatePagingFile 16 +NtCreatePort ZwCreatePort 20 +NtCreateProcess ZwCreateProcess 32 +NtCreateProfile ZwCreateProfile 36 +NtCreateSection ZwCreateSection 28 +NtCreateSemaphore ZwCreateSemaphore 20 +NtCreateSymbolicLinkObject ZwCreateSymbolicLinkObject 16 +NtCreateThread ZwCreateThread 32 +NtCreateTimer ZwCreateTimer 16 +NtCreateToken ZwCreateToken 52 +NtCreateWaitablePort ZwCreateWaitablePort 20 +NtDelayExecution ZwDelayExecution 8 +NtDeleteAtom ZwDeleteAtom 4 +NtDeleteFile ZwDeleteFile 4 +NtDeleteKey ZwDeleteKey 4 +NtDeleteObjectAuditAlarm ZwDeleteObjectAuditAlarm 12 +NtDeleteValueKey ZwDeleteValueKey 8 +NtDeviceIoControlFile ZwDeviceIoControlFile 40 +NtDisplayString ZwDisplayString 4 +NtDuplicateObject ZwDuplicateObject 28 +NtDuplicateToken ZwDuplicateToken 24 +NtEnumerateKey ZwEnumerateKey 24 +NtEnumerateValueKey ZwEnumerateValueKey 24 +NtExtendSection ZwExtendSection 8 +NtFindAtom ZwFindAtom 8 +NtFlushBuffersFile ZwFlushBuffersFile 8 +NtFlushInstructionCache ZwFlushInstructionCache 12 +NtFlushKey ZwFlushKey 4 +NtFlushVirtualMemory ZwFlushVirtualMemory 16 +NtFlushWriteBuffer ZwFlushWriteBuffer 0 +NtFreeVirtualMemory ZwFreeVirtualMemory 16 +NtFsControlFile ZwFsControlFile 40 +NtGetContextThread ZwGetContextThread 8 +NtGetPlugPlayEvent ZwGetPlugPlayEvent 16 +NtGetTickCount ZwGetTickCount 4 +NtImpersonateClientOfPort ZwImpersonateClientOfPort 8 +NtImpersonateThread ZwImpersonateThread 12 +NtInitializeRegistry ZwInitializeRegistry 4 +NtListenPort ZwListenPort 8 +NtLoadDriver ZwLoadDriver 4 +NtLoadKey ZwLoadKey 8 +NtLoadKey2 ZwLoadKey2 12 +NtLockFile ZwLockFile 40 +NtLockVirtualMemory ZwLockVirtualMemory 16 +NtMakeTemporaryObject ZwMakeTemporaryObject 4 +NtMapViewOfSection ZwMapViewOfSection 40 +NtNotifyChangeDirectoryFile ZwNotifyChangeDirectoryFile 36 +NtNotifyChangeKey ZwNotifyChangeKey 40 +NtOpenDirectoryObject ZwOpenDirectoryObject 12 +NtOpenEvent ZwOpenEvent 12 +NtOpenEventPair ZwOpenEventPair 12 +NtOpenFile ZwOpenFile 24 +NtOpenIoCompletion ZwOpenIoCompletion 12 +NtOpenKey ZwOpenKey 12 +NtOpenMutant ZwOpenMutant 12 +NtOpenObjectAuditAlarm ZwOpenObjectAuditAlarm 48 +NtOpenProcess ZwOpenProcess 16 +NtOpenProcessToken ZwOpenProcessToken 12 +NtOpenSection ZwOpenSection 12 +NtOpenSemaphore ZwOpenSemaphore 12 +NtOpenSymbolicLinkObject ZwOpenSymbolicLinkObject 12 +NtOpenThread ZwOpenThread 16 +NtOpenThreadToken ZwOpenThreadToken 16 +NtOpenTimer ZwOpenTimer 12 +NtPlugPlayControl ZwPlugPlayControl 16 +NtPrivilegeCheck ZwPrivilegeCheck 12 +NtPrivilegedServiceAuditAlarm ZwPrivilegedServiceAuditAlarm 20 +NtPrivilegeObjectAuditAlarm ZwPrivilegeObjectAuditAlarm 24 +NtProtectVirtualMemory ZwProtectVirtualMemory 20 +NtPulseEvent ZwPulseEvent 8 +NtQueryInformationAtom ZwQueryInformationAtom 20 +NtQueryAttributesFile ZwQueryAttributesFile 8 +NtQueryDefaultLocale ZwQueryDefaultLocale 8 +NtQueryDirectoryFile ZwQueryDirectoryFile 44 +NtQueryDirectoryObject ZwQueryDirectoryObject 28 +NtQueryEaFile ZwQueryEaFile 36 +NtQueryEvent ZwQueryEvent 20 +NtQueryFullAttributesFile ZwQueryFullAttributesFile 8 +NtQueryInformationFile ZwQueryInformationFile 20 +NtQueryInformationPort ZwQueryInformationPort 20 +NtQueryInformationProcess ZwQueryInformationProcess 20 +NtQueryInformationThread ZwQueryInformationThread 20 +NtQueryInformationToken ZwQueryInformationToken 20 +NtQueryIntervalProfile ZwQueryIntervalProfile 8 +NtQueryIoCompletion ZwQueryIoCompletion 20 +NtQueryKey ZwQueryKey 20 +NtQueryMultipleValueKey ZwQueryMultipleValueKey 24 +NtQueryMutant ZwQueryMutant 20 +NtQueryObject ZwQueryObject 20 +NtQueryOleDirectoryFile ZwQueryOleDirectoryFile 44 +NtQueryPerformanceCounter ZwQueryPerformanceCounter 8 +NtQuerySection ZwQuerySection 20 +NtQuerySecurityObject ZwQuerySecurityObject 20 +NtQuerySemaphore ZwQuerySemaphore 20 +NtQuerySymbolicLinkObject ZwQuerySymbolicLinkObject 12 +NtQuerySystemEnvironmentValue ZwQuerySystemEnvironmentValue 16 +NtQuerySystemInformation ZwQuerySystemInformation 16 +NtQuerySystemTime ZwQuerySystemTime 4 +NtQueryTimer ZwQueryTimer 20 +NtQueryTimerResolution ZwQueryTimerResolution 12 +NtQueryValueKey ZwQueryValueKey 24 +NtQueryVirtualMemory ZwQueryVirtualMemory 24 +NtQueryVolumeInformationFile ZwQueryVolumeInformationFile 20 +NtQueueApcThread ZwQueueApcThread 20 +NtRaiseException ZwRaiseException 12 +NtRaiseHardError ZwRaiseHardError 24 +NtReadFile ZwReadFile 36 +NtReadFileScatter ZwReadFileScatter 36 +NtReadRequestData ZwReadRequestData 24 +NtReadVirtualMemory ZwReadVirtualMemory 20 +NtRegisterThreadTerminatePort ZwRegisterThreadTerminatePort 4 +NtReleaseMutant ZwReleaseMutant 8 +NtReleaseSemaphore ZwReleaseSemaphore 12 +NtRemoveIoCompletion ZwRemoveIoCompletion 20 +NtReplaceKey ZwReplaceKey 12 +NtReplyPort ZwReplyPort 8 +NtReplyWaitReceivePort ZwReplyWaitReceivePort 16 +NtReplyWaitReplyPort ZwReplyWaitReplyPort 8 +NtRequestPort ZwRequestPort 8 +NtRequestWaitReplyPort ZwRequestWaitReplyPort 12 +NtResetEvent ZwResetEvent 8 +NtRestoreKey ZwRestoreKey 12 +NtResumeThread ZwResumeThread 8 +NtSaveKey ZwSaveKey 8 +NtSetIoCompletion ZwSetIoCompletion 20 +NtSetContextThread ZwSetContextThread 8 +NtSetDefaultHardErrorPort ZwSetDefaultHardErrorPort 4 +NtSetDefaultLocale ZwSetDefaultLocale 8 +NtSetEaFile ZwSetEaFile 16 +NtSetEvent ZwSetEvent 8 +NtSetHighEventPair ZwSetHighEventPair 4 +NtSetHighWaitLowEventPair ZwSetHighWaitLowEventPair 4 +NtSetInformationFile ZwSetInformationFile 20 +NtSetInformationKey ZwSetInformationKey 16 +NtSetInformationObject ZwSetInformationObject 16 +NtSetInformationProcess ZwSetInformationProcess 16 +NtSetInformationThread ZwSetInformationThread 16 +NtSetInformationToken ZwSetInformationToken 16 +NtSetIntervalProfile ZwSetIntervalProfile 8 +NtSetLdtEntries ZwSetLdtEntries 24 +NtSetLowEventPair ZwSetLowEventPair 4 +NtSetLowWaitHighEventPair ZwSetLowWaitHighEventPair 4 +NtSetSecurityObject ZwSetSecurityObject 12 +NtSetSystemEnvironmentValue ZwSetSystemEnvironmentValue 8 +NtSetSystemInformation ZwSetSystemInformation 12 +NtSetSystemPowerState ZwSetSystemPowerState 12 +NtSetSystemTime ZwSetSystemTime 8 +NtSetTimer ZwSetTimer 28 +NtSetTimerResolution ZwSetTimerResolution 12 +NtSetValueKey ZwSetValueKey 24 +NtSetVolumeInformationFile ZwSetVolumeInformationFile 20 +NtShutdownSystem ZwShutdownSystem 4 +NtSignalAndWaitForSingleObject ZwSignalAndWaitForSingleObject 16 +NtStartProfile ZwStartProfile 4 +NtStopProfile ZwStopProfile 4 +NtSuspendThread ZwSuspendThread 8 +NtSystemDebugControl ZwSystemDebugControl 24 +NtTerminateProcess ZwTerminateProcess 8 +NtTerminateThread ZwTerminateThread 8 +NtTestAlert ZwTestAlert 0 +NtUnloadDriver ZwUnloadDriver 4 +NtUnloadKey ZwUnloadKey 4 +NtUnlockFile ZwUnlockFile 20 +NtUnlockVirtualMemory ZwUnlockVirtualMemory 16 +NtUnmapViewOfSection ZwUnmapViewOfSection 8 +NtVdmControl ZwVdmControl 8 +NtWaitForMultipleObjects ZwWaitForMultipleObjects 20 +NtWaitForSingleObject ZwWaitForSingleObject 12 +NtWaitHighEventPair ZwWaitHighEventPair 4 +NtWaitLowEventPair ZwWaitLowEventPair 4 +NtWriteFile ZwWriteFile 36 +NtWriteFileGather ZwWriteFileGather 36 +NtWriteRequestData ZwWriteRequestData 24 +NtWriteVirtualMemory ZwWriteVirtualMemory 20 +NtW32Call ZwW32Call 20 +NtCreateChannel ZwCreateChannel 8 +NtListenChannel ZwListenChannel 8 +NtOpenChannel ZwOpenChannel 8 +NtReplyWaitSendChannel ZwReplyWaitSendChannel 12 +NtSendWaitReplyChannel ZwSendWaitReplyChannel 16 +NtSetContextChannel ZwSetContextChannel 4 +NtYieldExecution ZwYieldExecution 0 diff --git a/include/.cvsignore b/include/.cvsignore new file mode 100644 index 0000000..48abe12 --- /dev/null +++ b/include/.cvsignore @@ -0,0 +1 @@ +roscfg.h diff --git a/include/afd/shared.h b/include/afd/shared.h new file mode 100644 index 0000000..deda8ee --- /dev/null +++ b/include/afd/shared.h @@ -0,0 +1,199 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver + * FILE: include/afd/shared.h + * PURPOSE: Shared definitions for AFD.SYS and MSAFD.DLL + */ +#ifndef __AFD_SHARED_H +#define __AFD_SHARED_H + +#define AfdSocket "AfdSocket" +#define AFD_SOCKET_LENGTH (sizeof(AfdSocket) - 1) + +typedef struct _AFD_SOCKET_INFORMATION { + BOOL CommandChannel; + INT AddressFamily; + INT SocketType; + INT Protocol; + PVOID HelperContext; + DWORD NotificationEvents; + UNICODE_STRING TdiDeviceName; + SOCKADDR Name; +} __attribute__((packed)) AFD_SOCKET_INFORMATION, *PAFD_SOCKET_INFORMATION; + + +/* AFD IOCTL code definitions */ + +#define FSCTL_AFD_BASE FILE_DEVICE_NAMED_PIPE // ??? + +#define AFD_CTL_CODE(Function, Method, Access) \ + CTL_CODE(FSCTL_AFD_BASE, Function, Method, Access) + +#define IOCTL_AFD_BIND \ + AFD_CTL_CODE(0, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_LISTEN \ + AFD_CTL_CODE(1, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_SENDTO \ + AFD_CTL_CODE(2, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_RECVFROM \ + AFD_CTL_CODE(3, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_SELECT \ + AFD_CTL_CODE(4, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_EVENTSELECT \ + AFD_CTL_CODE(5, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_ENUMNETWORKEVENTS \ + AFD_CTL_CODE(6, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_RECV \ + AFD_CTL_CODE(7, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_SEND \ + AFD_CTL_CODE(8, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_ACCEPT \ + AFD_CTL_CODE(9, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_AFD_CONNECT \ + AFD_CTL_CODE(10, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +typedef struct _FILE_REQUEST_BIND { + SOCKADDR Name; +} __attribute__((packed)) FILE_REQUEST_BIND, *PFILE_REQUEST_BIND; + +typedef struct _FILE_REPLY_BIND { + INT Status; + HANDLE TdiAddressObjectHandle; + HANDLE TdiConnectionObjectHandle; +} __attribute__((packed)) FILE_REPLY_BIND, *PFILE_REPLY_BIND; + +typedef struct _FILE_REQUEST_LISTEN { + INT Backlog; +} __attribute__((packed)) FILE_REQUEST_LISTEN, *PFILE_REQUEST_LISTEN; + +typedef struct _FILE_REPLY_LISTEN { + INT Status; +} __attribute__((packed)) FILE_REPLY_LISTEN, *PFILE_REPLY_LISTEN; + + +typedef struct _FILE_REQUEST_SENDTO { + LPWSABUF Buffers; + DWORD BufferCount; + DWORD Flags; + SOCKADDR To; + INT ToLen; +} __attribute__((packed)) FILE_REQUEST_SENDTO, *PFILE_REQUEST_SENDTO; + +typedef struct _FILE_REPLY_SENDTO { + INT Status; + DWORD NumberOfBytesSent; +} __attribute__((packed)) FILE_REPLY_SENDTO, *PFILE_REPLY_SENDTO; + + +typedef struct _FILE_REQUEST_RECVFROM { + LPWSABUF Buffers; + DWORD BufferCount; + LPDWORD Flags; + LPSOCKADDR From; + LPINT FromLen; +} __attribute__((packed)) FILE_REQUEST_RECVFROM, *PFILE_REQUEST_RECVFROM; + +typedef struct _FILE_REPLY_RECVFROM { + INT Status; + DWORD NumberOfBytesRecvd; +} __attribute__((packed)) FILE_REPLY_RECVFROM, *PFILE_REPLY_RECVFROM; + + +typedef struct _FILE_REQUEST_SELECT { + LPFD_SET ReadFDSet; + LPFD_SET WriteFDSet; + LPFD_SET ExceptFDSet; + TIMEVAL Timeout; +} __attribute__((packed)) FILE_REQUEST_SELECT, *PFILE_REQUEST_SELECT; + +typedef struct _FILE_REPLY_SELECT { + INT Status; + DWORD SocketCount; +} __attribute__((packed)) FILE_REPLY_SELECT, *PFILE_REPLY_SELECT; + + +typedef struct _FILE_REQUEST_EVENTSELECT { + WSAEVENT hEventObject; + LONG lNetworkEvents; +} __attribute__((packed)) FILE_REQUEST_EVENTSELECT, *PFILE_REQUEST_EVENTSELECT; + +typedef struct _FILE_REPLY_EVENTSELECT { + INT Status; +} __attribute__((packed)) FILE_REPLY_EVENTSELECT, *PFILE_REPLY_EVENTSELECT; + + +typedef struct _FILE_REQUEST_ENUMNETWORKEVENTS { + WSAEVENT hEventObject; +} __attribute__((packed)) FILE_REQUEST_ENUMNETWORKEVENTS, *PFILE_REQUEST_ENUMNETWORKEVENTS; + +typedef struct _FILE_REPLY_ENUMNETWORKEVENTS { + INT Status; + WSANETWORKEVENTS NetworkEvents; +} __attribute__((packed)) FILE_REPLY_ENUMNETWORKEVENTS, *PFILE_REPLY_ENUMNETWORKEVENTS; + + +typedef struct _FILE_REQUEST_RECV { + LPWSABUF Buffers; + DWORD BufferCount; + LPDWORD Flags; +} __attribute__((packed)) FILE_REQUEST_RECV, *PFILE_REQUEST_RECV; + +typedef struct _FILE_REPLY_RECV { + INT Status; + DWORD NumberOfBytesRecvd; +} __attribute__((packed)) FILE_REPLY_RECV, *PFILE_REPLY_RECV; + + +typedef struct _FILE_REQUEST_SEND { + LPWSABUF Buffers; + DWORD BufferCount; + DWORD Flags; +} __attribute__((packed)) FILE_REQUEST_SEND, *PFILE_REQUEST_SEND; + +typedef struct _FILE_REPLY_SEND { + INT Status; + DWORD NumberOfBytesSent; +} __attribute__((packed)) FILE_REPLY_SEND, *PFILE_REPLY_SEND; + + +typedef struct _FILE_REQUEST_ACCEPT { + LPSOCKADDR addr; + INT addrlen; + LPCONDITIONPROC lpfnCondition; + DWORD dwCallbackData; +} __attribute__((packed)) FILE_REQUEST_ACCEPT, *PFILE_REQUEST_ACCEPT; + +typedef struct _FILE_REPLY_ACCEPT { + INT Status; + INT addrlen; + SOCKET Socket; +} __attribute__((packed)) FILE_REPLY_ACCEPT, *PFILE_REPLY_ACCEPT; + + +typedef struct _FILE_REQUEST_CONNECT { + LPSOCKADDR name; + INT namelen; + LPWSABUF lpCallerData; + LPWSABUF lpCalleeData; + LPQOS lpSQOS; + LPQOS lpGQOS; +} __attribute__((packed)) FILE_REQUEST_CONNECT, *PFILE_REQUEST_CONNECT; + +typedef struct _FILE_REPLY_CONNECT { + INT Status; +} __attribute__((packed)) FILE_REPLY_CONNECT, *PFILE_REPLY_CONNECT; + +#endif /*__AFD_SHARED_H */ + +/* EOF */ diff --git a/include/ascii.h b/include/ascii.h new file mode 100644 index 0000000..b801316 --- /dev/null +++ b/include/ascii.h @@ -0,0 +1,2997 @@ +/* + ASCIIFunctions.h + + Declarations for all the Win32 ASCII Functions + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Scott Christley + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNU_H_WINDOWS32_ASCIIFUNCTIONS +#define _GNU_H_WINDOWS32_ASCIIFUNCTIONS + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +WINBOOL +STDCALL +GetBinaryTypeA( + LPCSTR lpApplicationName, + LPDWORD lpBinaryType + ); + +DWORD +STDCALL +GetShortPathNameA( + LPCSTR lpszLongPath, + LPSTR lpszShortPath, + DWORD cchBuffer + ); + +LPSTR +STDCALL +GetEnvironmentStringsA( + VOID + ); + +WINBOOL +STDCALL +FreeEnvironmentStringsA( + LPSTR + ); + +DWORD +STDCALL +FormatMessageA( + DWORD dwFlags, + LPCVOID lpSource, + DWORD dwMessageId, + DWORD dwLanguageId, + LPSTR lpBuffer, + DWORD nSize, + va_list *Arguments + ); + +HANDLE +STDCALL +CreateMailslotA( + LPCSTR lpName, + DWORD nMaxMessageSize, + DWORD lReadTimeout, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +int +STDCALL +lstrcmpA( + LPCSTR lpString1, + LPCSTR lpString2 + ); + +int +STDCALL +lstrcmpiA( + LPCSTR lpString1, + LPCSTR lpString2 + ); + +LPSTR +STDCALL +lstrcpynA( + LPSTR lpString1, + LPCSTR lpString2, + int iMaxLength + ); + +LPSTR +STDCALL +lstrcpyA( + LPSTR lpString1, + LPCSTR lpString2 + ); + +LPSTR +STDCALL +lstrcatA( + LPSTR lpString1, + LPCSTR lpString2 + ); + +int +STDCALL +lstrlenA( + LPCSTR lpString + ); + +HANDLE +STDCALL +CreateMutexA( + LPSECURITY_ATTRIBUTES lpMutexAttributes, + WINBOOL bInitialOwner, + LPCSTR lpName + ); + +HANDLE +STDCALL +OpenMutexA( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName + ); + +HANDLE +STDCALL +CreateEventA( + LPSECURITY_ATTRIBUTES lpEventAttributes, + WINBOOL bManualReset, + WINBOOL bInitialState, + LPCSTR lpName + ); + +HANDLE +STDCALL +OpenEventA( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName + ); + +HANDLE +STDCALL +CreateSemaphoreA( + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCSTR lpName + ); + +HANDLE +STDCALL +OpenSemaphoreA( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName + ); + +HANDLE +STDCALL +CreateFileMappingA( + HANDLE hFile, + LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + DWORD flProtect, + DWORD dwMaximumSizeHigh, + DWORD dwMaximumSizeLow, + LPCSTR lpName + ); + +HANDLE +STDCALL +OpenFileMappingA( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName + ); + +DWORD +STDCALL +GetLogicalDriveStringsA( + DWORD nBufferLength, + LPSTR lpBuffer + ); + +HINSTANCE +STDCALL +LoadLibraryA( + LPCSTR lpLibFileName + ); + +HINSTANCE +STDCALL +LoadLibraryExA( + LPCSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags + ); + +DWORD +STDCALL +GetModuleFileNameA( + HINSTANCE hModule, + LPSTR lpFilename, + DWORD nSize + ); + +HMODULE +STDCALL +GetModuleHandleA( + LPCSTR lpModuleName + ); + +VOID +STDCALL +FatalAppExitA( + UINT uAction, + LPCSTR lpMessageText + ); + +LPSTR +STDCALL +GetCommandLineA( + VOID + ); + +DWORD +STDCALL +GetEnvironmentVariableA( + LPCSTR lpName, + LPSTR lpBuffer, + DWORD nSize + ); + +WINBOOL +STDCALL +SetEnvironmentVariableA( + LPCSTR lpName, + LPCSTR lpValue + ); + +DWORD +STDCALL +ExpandEnvironmentStringsA( + LPCSTR lpSrc, + LPSTR lpDst, + DWORD nSize + ); + +VOID +STDCALL +OutputDebugStringA( + LPCSTR lpOutputString + ); + +HRSRC +STDCALL +FindResourceA( + HINSTANCE hModule, + LPCSTR lpName, + LPCSTR lpType + ); + +HRSRC +STDCALL +FindResourceExA( + HINSTANCE hModule, + LPCSTR lpType, + LPCSTR lpName, + WORD wLanguage + ); + +WINBOOL +STDCALL +EnumResourceTypesA( + HINSTANCE hModule, + ENUMRESTYPEPROC lpEnumFunc, + LONG lParam + ); + +WINBOOL +STDCALL +EnumResourceNamesA( + HINSTANCE hModule, + LPCSTR lpType, + ENUMRESNAMEPROC lpEnumFunc, + LONG lParam + ); + +WINBOOL +STDCALL +EnumResourceLanguagesA( + HINSTANCE hModule, + LPCSTR lpType, + LPCSTR lpName, + ENUMRESLANGPROC lpEnumFunc, + LONG lParam + ); + +HANDLE +STDCALL +BeginUpdateResourceA( + LPCSTR pFileName, + WINBOOL bDeleteExistingResources + ); + +WINBOOL +STDCALL +UpdateResourceA( + HANDLE hUpdate, + LPCSTR lpType, + LPCSTR lpName, + WORD wLanguage, + LPVOID lpData, + DWORD cbData + ); + +WINBOOL +STDCALL +EndUpdateResourceA( + HANDLE hUpdate, + WINBOOL fDiscard + ); + +ATOM +STDCALL +GlobalAddAtomA( + LPCSTR lpString + ); + +ATOM +STDCALL +GlobalFindAtomA( + LPCSTR lpString + ); + +UINT +STDCALL +GlobalGetAtomNameA( + ATOM nAtom, + LPSTR lpBuffer, + int nSize + ); + +ATOM +STDCALL +AddAtomA( + LPCSTR lpString + ); + +ATOM +STDCALL +FindAtomA( + LPCSTR lpString + ); + +UINT +STDCALL +GetAtomNameA( + ATOM nAtom, + LPSTR lpBuffer, + int nSize + ); + +UINT +STDCALL +GetProfileIntA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + INT nDefault + ); + +DWORD +STDCALL +GetProfileStringA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize + ); + +WINBOOL +STDCALL +WriteProfileStringA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpString + ); + +DWORD +STDCALL +GetProfileSectionA( + LPCSTR lpAppName, + LPSTR lpReturnedString, + DWORD nSize + ); + +WINBOOL +STDCALL +WriteProfileSectionA( + LPCSTR lpAppName, + LPCSTR lpString + ); + +UINT +STDCALL +GetPrivateProfileIntA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + INT nDefault, + LPCSTR lpFileName + ); + +DWORD +STDCALL +GetPrivateProfileStringA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName + ); + +WINBOOL +STDCALL +WritePrivateProfileStringA( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpString, + LPCSTR lpFileName + ); + +DWORD +STDCALL +GetPrivateProfileSectionA( + LPCSTR lpAppName, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName + ); + +WINBOOL +STDCALL +WritePrivateProfileSectionA( + LPCSTR lpAppName, + LPCSTR lpString, + LPCSTR lpFileName + ); + +UINT +STDCALL +GetDriveTypeA( + LPCSTR lpRootPathName + ); + +UINT +STDCALL +GetSystemDirectoryA( + LPSTR lpBuffer, + UINT uSize + ); + +DWORD +STDCALL +GetTempPathA( + DWORD nBufferLength, + LPSTR lpBuffer + ); + +UINT +STDCALL +GetTempFileNameA( + LPCSTR lpPathName, + LPCSTR lpPrefixString, + UINT uUnique, + LPSTR lpTempFileName + ); + +UINT +STDCALL +GetWindowsDirectoryA( + LPSTR lpBuffer, + UINT uSize + ); + +WINBOOL +STDCALL +SetCurrentDirectoryA( + LPCSTR lpPathName + ); + +DWORD +STDCALL +GetCurrentDirectoryA( + DWORD nBufferLength, + LPSTR lpBuffer + ); + +WINBOOL +STDCALL +GetDiskFreeSpaceA( + LPCSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters + ); + +WINBOOL +STDCALL +GetDiskFreeSpaceExA( + LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes + ); + +WINBOOL +STDCALL +CreateDirectoryA( + LPCSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +WINBOOL +STDCALL +CreateDirectoryExA( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +WINBOOL +STDCALL +RemoveDirectoryA( + LPCSTR lpPathName + ); + +DWORD +STDCALL +GetFullPathNameA( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart + ); + +WINBOOL +STDCALL +DefineDosDeviceA( + DWORD dwFlags, + LPCSTR lpDeviceName, + LPCSTR lpTargetPath + ); + +DWORD +STDCALL +QueryDosDeviceA( + LPCSTR lpDeviceName, + LPSTR lpTargetPath, + DWORD ucchMax + ); + +HANDLE +STDCALL +CreateFileA( + LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile + ); + +WINBOOL +STDCALL +SetFileAttributesA( + LPCSTR lpFileName, + DWORD dwFileAttributes + ); + +DWORD +STDCALL +GetFileAttributesA( + LPCSTR lpFileName + ); + +DWORD +STDCALL +GetCompressedFileSizeA( + LPCSTR lpFileName, + LPDWORD lpFileSizeHigh + ); + +WINBOOL +STDCALL +DeleteFileA( + LPCSTR lpFileName + ); + +DWORD +STDCALL +SearchPathA( + LPCSTR lpPath, + LPCSTR lpFileName, + LPCSTR lpExtension, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart + ); + +WINBOOL +STDCALL +CopyFileA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + WINBOOL bFailIfExists + ); + +WINBOOL +STDCALL +MoveFileA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName + ); + +WINBOOL +STDCALL +MoveFileExA( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + DWORD dwFlags + ); + +HANDLE +STDCALL +CreateNamedPipeA( + LPCSTR lpName, + DWORD dwOpenMode, + DWORD dwPipeMode, + DWORD nMaxInstances, + DWORD nOutBufferSize, + DWORD nInBufferSize, + DWORD nDefaultTimeOut, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +WINBOOL +STDCALL +GetNamedPipeHandleStateA( + HANDLE hNamedPipe, + LPDWORD lpState, + LPDWORD lpCurInstances, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout, + LPSTR lpUserName, + DWORD nMaxUserNameSize + ); + +WINBOOL +STDCALL +CallNamedPipeA( + LPCSTR lpNamedPipeName, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + DWORD nTimeOut + ); + +WINBOOL +STDCALL +WaitNamedPipeA( + LPCSTR lpNamedPipeName, + DWORD nTimeOut + ); + +WINBOOL +STDCALL +SetVolumeLabelA( + LPCSTR lpRootPathName, + LPCSTR lpVolumeName + ); + +WINBOOL +STDCALL +GetVolumeInformationA( + LPCSTR lpRootPathName, + LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize + ); + +WINBOOL +STDCALL +ClearEventLogA ( + HANDLE hEventLog, + LPCSTR lpBackupFileName + ); + +WINBOOL +STDCALL +BackupEventLogA ( + HANDLE hEventLog, + LPCSTR lpBackupFileName + ); + +HANDLE +STDCALL +OpenEventLogA ( + LPCSTR lpUNCServerName, + LPCSTR lpSourceName + ); + +HANDLE +STDCALL +RegisterEventSourceA ( + LPCSTR lpUNCServerName, + LPCSTR lpSourceName + ); + +HANDLE +STDCALL +OpenBackupEventLogA ( + LPCSTR lpUNCServerName, + LPCSTR lpFileName + ); + +WINBOOL +STDCALL +ReadEventLogA ( + HANDLE hEventLog, + DWORD dwReadFlags, + DWORD dwRecordOffset, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + DWORD *pnBytesRead, + DWORD *pnMinNumberOfBytesNeeded + ); + +WINBOOL +STDCALL +ReportEventA ( + HANDLE hEventLog, + WORD wType, + WORD wCategory, + DWORD dwEventID, + PSID lpUserSid, + WORD wNumStrings, + DWORD dwDataSize, + LPCSTR *lpStrings, + LPVOID lpRawData + ); + +WINBOOL +STDCALL +AccessCheckAndAuditAlarmA ( + LPCSTR SubsystemName, + LPVOID HandleId, + LPSTR ObjectTypeName, + LPSTR ObjectName, + PSECURITY_DESCRIPTOR SecurityDescriptor, + DWORD DesiredAccess, + PGENERIC_MAPPING GenericMapping, + WINBOOL ObjectCreation, + LPDWORD GrantedAccess, + LPBOOL AccessStatus, + LPBOOL pfGenerateOnClose + ); + +WINBOOL +STDCALL +ObjectOpenAuditAlarmA ( + LPCSTR SubsystemName, + LPVOID HandleId, + LPSTR ObjectTypeName, + LPSTR ObjectName, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + HANDLE ClientToken, + DWORD DesiredAccess, + DWORD GrantedAccess, + PPRIVILEGE_SET Privileges, + WINBOOL ObjectCreation, + WINBOOL AccessGranted, + LPBOOL GenerateOnClose + ); + +WINBOOL +STDCALL +ObjectPrivilegeAuditAlarmA ( + LPCSTR SubsystemName, + LPVOID HandleId, + HANDLE ClientToken, + DWORD DesiredAccess, + PPRIVILEGE_SET Privileges, + WINBOOL AccessGranted + ); + +WINBOOL +STDCALL +ObjectCloseAuditAlarmA ( + LPCSTR SubsystemName, + LPVOID HandleId, + WINBOOL GenerateOnClose + ); + +WINBOOL +STDCALL +PrivilegedServiceAuditAlarmA ( + LPCSTR SubsystemName, + LPCSTR ServiceName, + HANDLE ClientToken, + PPRIVILEGE_SET Privileges, + WINBOOL AccessGranted + ); + +WINBOOL +STDCALL +SetFileSecurityA ( + LPCSTR lpFileName, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor + ); + +WINBOOL +STDCALL +GetFileSecurityA ( + LPCSTR lpFileName, + SECURITY_INFORMATION RequestedInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD nLength, + LPDWORD lpnLengthNeeded + ); + +HANDLE +STDCALL +FindFirstChangeNotificationA( + LPCSTR lpPathName, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter + ); + +WINBOOL +STDCALL +IsBadStringPtrA( + LPCSTR lpsz, + UINT ucchMax + ); + +WINBOOL +STDCALL +LookupAccountSidA( + LPCSTR lpSystemName, + PSID Sid, + LPSTR Name, + LPDWORD cbName, + LPSTR ReferencedDomainName, + LPDWORD cbReferencedDomainName, + PSID_NAME_USE peUse + ); + +WINBOOL +STDCALL +LookupAccountNameA( + LPCSTR lpSystemName, + LPCSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPSTR ReferencedDomainName, + LPDWORD cbReferencedDomainName, + PSID_NAME_USE peUse + ); + +WINBOOL +STDCALL +LookupPrivilegeValueA( + LPCSTR lpSystemName, + LPCSTR lpName, + PLUID lpLuid + ); + +WINBOOL +STDCALL +LookupPrivilegeNameA( + LPCSTR lpSystemName, + PLUID lpLuid, + LPSTR lpName, + LPDWORD cbName + ); + +WINBOOL +STDCALL +LookupPrivilegeDisplayNameA( + LPCSTR lpSystemName, + LPCSTR lpName, + LPSTR lpDisplayName, + LPDWORD cbDisplayName, + LPDWORD lpLanguageId + ); + +WINBOOL +STDCALL +BuildCommDCBA( + LPCSTR lpDef, + LPDCB lpDCB + ); + +WINBOOL +STDCALL +BuildCommDCBAndTimeoutsA( + LPCSTR lpDef, + LPDCB lpDCB, + LPCOMMTIMEOUTS lpCommTimeouts + ); + +WINBOOL +STDCALL +CommConfigDialogA( + LPCSTR lpszName, + HWND hWnd, + LPCOMMCONFIG lpCC + ); + +WINBOOL +STDCALL +GetDefaultCommConfigA( + LPCSTR lpszName, + LPCOMMCONFIG lpCC, + LPDWORD lpdwSize + ); + +WINBOOL +STDCALL +SetDefaultCommConfigA( + LPCSTR lpszName, + LPCOMMCONFIG lpCC, + DWORD dwSize + ); + +WINBOOL +STDCALL +GetComputerNameA ( + LPSTR lpBuffer, + LPDWORD nSize + ); + +WINBOOL +STDCALL +SetComputerNameA ( + LPCSTR lpComputerName + ); + +WINBOOL +STDCALL +GetUserNameA ( + LPSTR lpBuffer, + LPDWORD nSize + ); + +int +STDCALL +wvsprintfA( + LPSTR, + LPCSTR, + va_list arglist); + +int +CDECL +wsprintfA(LPSTR, LPCSTR, ...); + +HKL +STDCALL +LoadKeyboardLayoutA( + LPCSTR pwszKLID, + UINT Flags); + +WINBOOL +STDCALL +GetKeyboardLayoutNameA( + LPSTR pwszKLID); + +HDESK +STDCALL +CreateDesktopA( + LPCSTR lpszDesktop, + LPCSTR lpszDevice, + LPDEVMODEA pDevmode, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa); + +HDESK +STDCALL +OpenDesktopA( + LPSTR lpszDesktop, + DWORD dwFlags, + WINBOOL fInherit, + DWORD dwDesiredAccess); + +WINBOOL +STDCALL +EnumDesktopsA( + HWINSTA hwinsta, + DESKTOPENUMPROC lpEnumFunc, + LPARAM lParam); + +HWINSTA +STDCALL +CreateWindowStationA( + LPSTR lpwinsta, + DWORD dwReserved, + DWORD dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa); + +HANDLE STDCALL CreateWaitableTimerA( LPSECURITY_ATTRIBUTES Attributes, + BOOL ManualReset, + LPCTSTR Name ); + +HWINSTA +STDCALL +OpenWindowStationA( + LPSTR lpszWinSta, + WINBOOL fInherit, + DWORD dwDesiredAccess); + +WINBOOL +STDCALL +EnumWindowStationsA( + ENUMWINDOWSTATIONPROC lpEnumFunc, + LPARAM lParam); + +WINBOOL +STDCALL +GetUserObjectInformationA( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength, + LPDWORD lpnLengthNeeded); + +WINBOOL +STDCALL +SetUserObjectInformationA( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength); + +UINT +STDCALL +RegisterWindowMessageA( + LPCSTR lpString); + +WINBOOL +STDCALL +GetMessageA( + LPMSG lpMsg, + HWND hWnd , + UINT wMsgFilterMin, + UINT wMsgFilterMax); + +LRESULT +STDCALL +DispatchMessageA( + CONST MSG *lpMsg); + +WINBOOL +STDCALL +PeekMessageA( + LPMSG lpMsg, + HWND hWnd , + UINT wMsgFilterMin, + UINT wMsgFilterMax, + UINT wRemoveMsg); + +LRESULT +STDCALL +SendMessageA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +SendMessageTimeoutA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + UINT fuFlags, + UINT uTimeout, + PDWORD_PTR lpdwResult); + +WINBOOL +STDCALL +SendNotifyMessageA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +WINBOOL +STDCALL +SendMessageCallbackA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC lpResultCallBack, + ULONG_PTR dwData); + +WINBOOL +STDCALL +PostMessageA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +WINBOOL +STDCALL +PostThreadMessageA( + DWORD idThread, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +DefWindowProcA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +CallWindowProcA( + WNDPROC lpPrevWndFunc, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +ATOM +STDCALL +RegisterClassA( + CONST WNDCLASS *lpWndClass); + +WINBOOL +STDCALL +UnregisterClassA( + LPCSTR lpClassName, + HINSTANCE hInstance); + +WINBOOL +STDCALL +GetClassInfoA( + HINSTANCE hInstance , + LPCSTR lpClassName, + LPWNDCLASS lpWndClass); + +ATOM +STDCALL +RegisterClassExA(CONST WNDCLASSEX *); + +WINBOOL +STDCALL +GetClassInfoExA(HINSTANCE, LPCSTR, LPWNDCLASSEX); + +HWND +STDCALL +CreateWindowExA( + DWORD dwExStyle, + LPCSTR lpClassName, + LPCSTR lpWindowName, + DWORD dwStyle, + int X, + int Y, + int nWidth, + int nHeight, + HWND hWndParent , + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam); + +HWND +STDCALL +CreateDialogParamA( + HINSTANCE hInstance, + LPCSTR lpTemplateName, + HWND hWndParent , + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +HWND +STDCALL +CreateDialogIndirectParamA( + HINSTANCE hInstance, + LPCDLGTEMPLATE lpTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +int +STDCALL +DialogBoxParamA( + HINSTANCE hInstance, + LPCSTR lpTemplateName, + HWND hWndParent , + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +int +STDCALL +DialogBoxIndirectParamA( + HINSTANCE hInstance, + LPCDLGTEMPLATE hDialogTemplate, + HWND hWndParent , + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +WINBOOL +STDCALL +SetDlgItemTextA( + HWND hDlg, + int nIDDlgItem, + LPCSTR lpString); + +UINT +STDCALL +GetDlgItemTextA( + HWND hDlg, + int nIDDlgItem, + LPSTR lpString, + int nMaxCount); + +LRESULT +STDCALL +SendDlgItemMessageA( + HWND hDlg, + int nIDDlgItem, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +DefDlgProcA( + HWND hDlg, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +WINBOOL +STDCALL +CallMsgFilterA( + LPMSG lpMsg, + int nCode); + +UINT +STDCALL +RegisterClipboardFormatA( + LPCSTR lpszFormat); + +int +STDCALL +GetClipboardFormatNameA( + UINT format, + LPSTR lpszFormatName, + int cchMaxCount); + +WINBOOL +STDCALL +CharToOemA( + LPCSTR lpszSrc, + LPSTR lpszDst); + +WINBOOL +STDCALL +OemToCharA( + LPCSTR lpszSrc, + LPSTR lpszDst); + +WINBOOL +STDCALL +CharToOemBuffA( + LPCSTR lpszSrc, + LPSTR lpszDst, + DWORD cchDstLength); + +WINBOOL +STDCALL +OemToCharBuffA( + LPCSTR lpszSrc, + LPSTR lpszDst, + DWORD cchDstLength); + +LPSTR +STDCALL +CharUpperA( + LPSTR lpsz); + +DWORD +STDCALL +CharUpperBuffA( + LPSTR lpsz, + DWORD cchLength); + +LPSTR +STDCALL +CharLowerA( + LPSTR lpsz); + +DWORD +STDCALL +CharLowerBuffA( + LPSTR lpsz, + DWORD cchLength); + +LPSTR +STDCALL +CharNextA( + LPCSTR lpsz); + +LPSTR +STDCALL +CharPrevA( + LPCSTR lpszStart, + LPCSTR lpszCurrent); + +WINBOOL +STDCALL +IsCharAlphaA( + CHAR ch); + +WINBOOL +STDCALL +IsCharAlphaNumericA( + CHAR ch); + +WINBOOL +STDCALL +IsCharUpperA( + CHAR ch); + +WINBOOL +STDCALL +IsCharLowerA( + CHAR ch); + +int +STDCALL +GetKeyNameTextA( + LONG lParam, + LPSTR lpString, + int nSize + ); + +SHORT +STDCALL +VkKeyScanA( + CHAR ch); + +SHORT +STDCALL VkKeyScanExA( + CHAR ch, + HKL dwhkl); + +UINT +STDCALL +MapVirtualKeyA( + UINT uCode, + UINT uMapType); + +UINT +STDCALL +MapVirtualKeyExA( + UINT uCode, + UINT uMapType, + HKL dwhkl); + +HACCEL +STDCALL +LoadAcceleratorsA( + HINSTANCE hInstance, + LPCSTR lpTableName); + +HACCEL +STDCALL +CreateAcceleratorTableA( + LPACCEL, int); + +int +STDCALL +CopyAcceleratorTableA( + HACCEL hAccelSrc, + LPACCEL lpAccelDst, + int cAccelEntries); + +int +STDCALL +TranslateAcceleratorA( + HWND hWnd, + HACCEL hAccTable, + LPMSG lpMsg); + +HMENU +STDCALL +LoadMenuA( + HINSTANCE hInstance, + LPCSTR lpMenuName); + +HMENU +STDCALL +LoadMenuIndirectA( + CONST MENUTEMPLATE *lpMenuTemplate); + +WINBOOL +STDCALL +ChangeMenuA( + HMENU hMenu, + UINT cmd, + LPCSTR lpszNewItem, + UINT cmdInsert, + UINT flags); + +int +STDCALL +GetMenuStringA( + HMENU hMenu, + UINT uIDItem, + LPSTR lpString, + int nMaxCount, + UINT uFlag); + +WINBOOL +STDCALL +InsertMenuA( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + UINT uIDNewItem, + LPCSTR lpNewItem + ); + +WINBOOL +STDCALL +AppendMenuA( + HMENU hMenu, + UINT uFlags, + UINT uIDNewItem, + LPCSTR lpNewItem + ); + +WINBOOL +STDCALL +ModifyMenuA( + HMENU hMnu, + UINT uPosition, + UINT uFlags, + UINT uIDNewItem, + LPCSTR lpNewItem + ); + +WINBOOL +STDCALL +InsertMenuItemA( + HMENU, + UINT, + WINBOOL, + LPCMENUITEMINFO + ); + +WINBOOL +STDCALL +GetMenuItemInfoA( + HMENU, + UINT, + WINBOOL, + LPMENUITEMINFO + ); + +WINBOOL +STDCALL +SetMenuItemInfoA( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPMENUITEMINFO lpmii); + +int +STDCALL +DrawTextA( + HDC hDC, + LPCSTR lpString, + int nCount, + LPRECT lpRect, + UINT uFormat); + +int +STDCALL +DrawTextExA(HDC, LPSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); + +WINBOOL +STDCALL +GrayStringA( + HDC hDC, + HBRUSH hBrush, + GRAYSTRINGPROC lpOutputFunc, + LPARAM lpData, + int nCount, + int X, + int Y, + int nWidth, + int nHeight); + +WINBOOL +STDCALL +DrawStateA(HDC, HBRUSH, DRAWSTATEPROC, LPARAM, WPARAM, int, int, int, int, UINT); + +LONG +STDCALL +TabbedTextOutA( + HDC hDC, + int X, + int Y, + LPCSTR lpString, + int nCount, + int nTabPositions, + LPINT lpnTabStopPositions, + int nTabOrigin); + +DWORD +STDCALL +GetTabbedTextExtentA( + HDC hDC, + LPCSTR lpString, + int nCount, + int nTabPositions, + LPINT lpnTabStopPositions); + +WINBOOL +STDCALL +SetPropA( + HWND hWnd, + LPCSTR lpString, + HANDLE hData); + +HANDLE +STDCALL +GetPropA( + HWND hWnd, + LPCSTR lpString); + +HANDLE +STDCALL +RemovePropA( + HWND hWnd, + LPCSTR lpString); + +int +STDCALL +EnumPropsExA( + HWND hWnd, + PROPENUMPROCEX lpEnumFunc, + LPARAM lParam); + +int +STDCALL +EnumPropsA( + HWND hWnd, + PROPENUMPROC lpEnumFunc); + +WINBOOL +STDCALL +SetWindowTextA( + HWND hWnd, + LPCSTR lpString); + +int +STDCALL +GetWindowTextA( + HWND hWnd, + LPSTR lpString, + int nMaxCount); + +int +STDCALL +GetWindowTextLengthA( + HWND hWnd); + +int +STDCALL +MessageBoxA( + HWND hWnd , + LPCSTR lpText, + LPCSTR lpCaption, + UINT uType); + +int +STDCALL +MessageBoxExA( + HWND hWnd , + LPCSTR lpText, + LPCSTR lpCaption, + UINT uType, + WORD wLanguageId); + +int +STDCALL +MessageBoxIndirectA(LPMSGBOXPARAMS); + +LONG +STDCALL +GetWindowLongA( + HWND hWnd, + int nIndex); + +LONG +STDCALL +SetWindowLongA( + HWND hWnd, + int nIndex, + LONG dwNewLong); + +DWORD +STDCALL +GetClassLongA( + HWND hWnd, + int nIndex); + +DWORD +STDCALL +SetClassLongA( + HWND hWnd, + int nIndex, + LONG dwNewLong); + +HWND +STDCALL +FindWindowA( + LPCSTR lpClassName , + LPCSTR lpWindowName); + +HWND +STDCALL +FindWindowExA(HWND, HWND, LPCSTR, LPCSTR); + +int +STDCALL +GetClassNameA( + HWND hWnd, + LPSTR lpClassName, + int nMaxCount); + +HHOOK +STDCALL +SetWindowsHookExA( + int idHook, + HOOKPROC lpfn, + HINSTANCE hmod, + DWORD dwThreadId); + +HBITMAP +STDCALL +LoadBitmapA( + HINSTANCE hInstance, + LPCSTR lpBitmapName); + +HCURSOR +STDCALL +LoadCursorA( + HINSTANCE hInstance, + LPCSTR lpCursorName); + +HCURSOR +STDCALL +LoadCursorFromFileA( + LPCSTR lpFileName); + +HICON +STDCALL +LoadIconA( + HINSTANCE hInstance, + LPCSTR lpIconName); + +HANDLE +STDCALL +LoadImageA( + HINSTANCE, + LPCSTR, + UINT, + int, + int, + UINT); + +int +STDCALL +LoadStringA( + HINSTANCE hInstance, + UINT uID, + LPSTR lpBuffer, + int nBufferMax); + +int +STDCALL +DlgDirListA( + HWND hDlg, + LPSTR lpPathSpec, + int nIDListBox, + int nIDStaticPath, + UINT uFileType); + +WINBOOL +STDCALL +DlgDirSelectExA( + HWND hDlg, + LPSTR lpString, + int nCount, + int nIDListBox); + +int +STDCALL +DlgDirListComboBoxA( + HWND hDlg, + LPSTR lpPathSpec, + int nIDComboBox, + int nIDStaticPath, + UINT uFiletype); + +WINBOOL +STDCALL +DlgDirSelectComboBoxExA( + HWND hDlg, + LPSTR lpString, + int nCount, + int nIDComboBox); + +LRESULT +STDCALL +DefFrameProcA( + HWND hWnd, + HWND hWndMDIClient , + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +DefMDIChildProcA( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +HWND +STDCALL +CreateMDIWindowA( + LPCSTR lpClassName, + LPCSTR lpWindowName, + DWORD dwStyle, + int X, + int Y, + int nWidth, + int nHeight, + HWND hWndParent, + HINSTANCE hInstance, + LPARAM lParam + ); + +WINBOOL +STDCALL +WinHelpA( + HWND hWndMain, + LPCSTR lpszHelp, + UINT uCommand, + DWORD dwData + ); + +LONG +STDCALL +ChangeDisplaySettingsA( + LPDEVMODEA lpDevMode, + DWORD dwFlags); + +WINBOOL +STDCALL +EnumDisplaySettingsA( + LPCSTR lpszDeviceName, + DWORD iModeNum, + LPDEVMODEA lpDevMode); + +WINBOOL +STDCALL +SystemParametersInfoA( + UINT uiAction, + UINT uiParam, + PVOID pvParam, + UINT fWinIni); + +int +STDCALL +AddFontResourceA(LPCSTR); + +HMETAFILE +STDCALL +CopyMetaFileA(HMETAFILE, LPCSTR); + +HFONT +STDCALL +CreateFontIndirectA(CONST LOGFONT *); + +HDC +STDCALL +CreateICA(LPCSTR, LPCSTR , LPCSTR , CONST DEVMODEA *); + +HDC +STDCALL +CreateMetaFileA(LPCSTR); + +WINBOOL +STDCALL +CreateScalableFontResourceA(DWORD, LPCSTR, LPCSTR, LPCSTR); + +int +STDCALL +DeviceCapabilitiesA(LPCSTR, LPCSTR, WORD, + LPSTR, CONST DEVMODEA *); + +int +STDCALL +EnumFontFamiliesExA(HDC, LPLOGFONT, FONTENUMEXPROC, LPARAM,DWORD); + +int +STDCALL +EnumFontFamiliesA(HDC, LPCSTR, FONTENUMPROC, LPARAM); + +int +STDCALL +EnumFontsA(HDC, LPCSTR, ENUMFONTSPROC, LPARAM); + +WINBOOL +STDCALL +GetCharWidthA(HDC, UINT, UINT, LPINT); + +WINBOOL +STDCALL +GetCharWidth32A(HDC, UINT, UINT, LPINT); + +WINBOOL +STDCALL +GetCharWidthFloatA(HDC, UINT, UINT, PFLOAT); + +WINBOOL +STDCALL +GetCharABCWidthsA(HDC, UINT, UINT, LPABC); + +WINBOOL +STDCALL +GetCharABCWidthsFloatA(HDC, UINT, UINT, LPABCFLOAT); +DWORD +STDCALL +GetGlyphOutlineA(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, CONST MAT2 *); + +HMETAFILE +STDCALL +GetMetaFileA(LPCSTR); + +UINT +STDCALL +GetOutlineTextMetricsA(HDC, UINT, LPOUTLINETEXTMETRIC); + +WINBOOL +STDCALL +GetTextExtentPointA( + HDC, + LPCSTR, + int, + LPSIZE + ); + +WINBOOL +STDCALL +GetTextExtentPoint32A( + HDC, + LPCSTR, + int, + LPSIZE + ); + +WINBOOL +STDCALL +GetTextExtentExPointA( + HDC, + LPCSTR, + int, + int, + LPINT, + LPINT, + LPSIZE + ); + +DWORD +STDCALL +GetCharacterPlacementA(HDC, LPCSTR, int, int, LPGCP_RESULTS, DWORD); + +HDC +STDCALL +ResetDCA(HDC, CONST DEVMODEA *); + +WINBOOL +STDCALL +RemoveFontResourceA(LPCSTR); + +HENHMETAFILE +STDCALL +CopyEnhMetaFileA(HENHMETAFILE, LPCSTR); + +HDC +STDCALL +CreateEnhMetaFileA(HDC, LPCSTR, CONST RECT *, LPCSTR); + +HENHMETAFILE +STDCALL +GetEnhMetaFileA(LPCSTR); + +UINT +STDCALL +GetEnhMetaFileDescriptionA(HENHMETAFILE, UINT, LPSTR ); + +WINBOOL +STDCALL +GetTextMetricsA(HDC, LPTEXTMETRIC); + +int +STDCALL +StartDocA(HDC, CONST DOCINFO *); + +int +STDCALL +GetObjectA(HGDIOBJ, int, LPVOID); + +WINBOOL +STDCALL +TextOutA(HDC, int, int, LPCSTR, int); + +WINBOOL +STDCALL +ExtTextOutA(HDC, int, int, UINT, CONST RECT *,LPCSTR, UINT, CONST INT *); + +WINBOOL +STDCALL +PolyTextOutA(HDC, CONST POLYTEXT *, int); + +int +STDCALL +GetTextFaceA(HDC, int, LPSTR); + +DWORD +STDCALL +GetKerningPairsA(HDC, DWORD, LPKERNINGPAIR); + +HCOLORSPACE +STDCALL +CreateColorSpaceA(LPLOGCOLORSPACE); + +WINBOOL +STDCALL +GetLogColorSpaceA(HCOLORSPACE,LPLOGCOLORSPACE,DWORD); + +WINBOOL +STDCALL +GetICMProfileA(HDC,DWORD,LPSTR); + +WINBOOL +STDCALL +SetICMProfileA(HDC,LPSTR); + +WINBOOL +STDCALL +UpdateICMRegKeyA(DWORD, DWORD, LPSTR, UINT); + +int +STDCALL +EnumICMProfilesA(HDC,ICMENUMPROC,LPARAM); + +int +STDCALL +PropertySheetA(LPCPROPSHEETHEADER lppsph); + +HIMAGELIST +STDCALL +ImageList_LoadImageA(HINSTANCE hi, LPCSTR lpbmp, int cx, int cGrow, COLORREF crMask, UINT uType, UINT uFlags); + +HWND +STDCALL +CreateStatusWindowA(LONG style, LPCSTR lpszText, HWND hwndParent, UINT wID); + +void +STDCALL +DrawStatusTextA(HDC hDC, LPRECT lprc, LPCSTR pszText, UINT uFlags); + +WINBOOL +STDCALL +GetOpenFileNameA(LPOPENFILENAME); + +WINBOOL +STDCALL +GetSaveFileNameA(LPOPENFILENAME); + +short +STDCALL +GetFileTitleA(LPCSTR, LPSTR, WORD); + +WINBOOL +STDCALL +ChooseColorA(LPCHOOSECOLOR); + +HWND +STDCALL +FindTextA(LPFINDREPLACE); + +HWND +STDCALL +ReplaceTextA(LPFINDREPLACE); + +WINBOOL +STDCALL +ChooseFontA(LPCHOOSEFONT); + +WINBOOL +STDCALL +PrintDlgA(LPPRINTDLG); + +WINBOOL +STDCALL +PageSetupDlgA( LPPAGESETUPDLG ); + +WINBOOL +STDCALL +CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + WINBOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation + ); + +VOID +STDCALL +GetStartupInfoA( + LPSTARTUPINFOA lpStartupInfo + ); + +WINBASEAPI +HANDLE +WINAPI +FindFirstFileExA ( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ); + +HANDLE +STDCALL +FindFirstFileA( + LPCSTR lpFileName, + LPWIN32_FIND_DATA lpFindFileData + ); + +WINBOOL +STDCALL +FindNextFileA( + HANDLE hFindFile, + LPWIN32_FIND_DATA lpFindFileData + ); + +WINBOOL +STDCALL +GetVersionExA( + LPOSVERSIONINFO lpVersionInformation + ); + +#define CreateWindowA(lpClassName, lpWindowName, dwStyle, x, y,\ +nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\ +CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y,\ +nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) + +#define CreateDialogA(hInstance, lpName, hWndParent, lpDialogFunc) \ +CreateDialogParamA(hInstance, lpName, hWndParent, lpDialogFunc, 0L) + +#define CreateDialogIndirectA(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ +CreateDialogIndirectParamA(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L) + +#define DialogBoxA(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ +DialogBoxParamA(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L) + +#define DialogBoxIndirectA(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ +DialogBoxIndirectParamA(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L) + +HDC +STDCALL +CreateDCA(LPCSTR, LPCSTR , LPCSTR , CONST DEVMODEA *); + +DWORD +STDCALL +VerInstallFileA( + DWORD uFlags, + LPSTR szSrcFileName, + LPSTR szDestFileName, + LPSTR szSrcDir, + LPSTR szDestDir, + LPSTR szCurDir, + LPSTR szTmpFile, + PUINT lpuTmpFileLen + ); + +DWORD +STDCALL +GetFileVersionInfoSizeA( + LPSTR lptstrFilename, + LPDWORD lpdwHandle + ); + +WINBOOL +STDCALL +GetFileVersionInfoA( + LPSTR lptstrFilename, + DWORD dwHandle, + DWORD dwLen, + LPVOID lpData + ); + +DWORD +STDCALL +VerLanguageNameA( + DWORD wLang, + LPSTR szLang, + DWORD nSize + ); + +WINBOOL +STDCALL +VerQueryValueA( + const LPVOID pBlock, + LPSTR lpSubBlock, + LPVOID * lplpBuffer, + PUINT puLen + ); + +DWORD +STDCALL +VerFindFileA( + DWORD uFlags, + LPSTR szFileName, + LPSTR szWinDir, + LPSTR szAppDir, + LPSTR szCurDir, + PUINT lpuCurDirLen, + LPSTR szDestDir, + PUINT lpuDestDirLen + ); + +LONG +STDCALL +RegConnectRegistryA ( + LPSTR lpMachineName, + HKEY hKey, + PHKEY phkResult + ); + +LONG +STDCALL +RegCreateKeyA ( + HKEY hKey, + LPCSTR lpSubKey, + PHKEY phkResult + ); + +LONG +STDCALL +RegCreateKeyExA ( + HKEY hKey, + LPCSTR lpSubKey, + DWORD Reserved, + LPSTR lpClass, + DWORD dwOptions, + REGSAM samDesired, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + PHKEY phkResult, + LPDWORD lpdwDisposition + ); + +LONG +STDCALL +RegDeleteKeyA ( + HKEY hKey, + LPCSTR lpSubKey + ); + +LONG +STDCALL +RegDeleteValueA ( + HKEY hKey, + LPCSTR lpValueName + ); + +LONG +STDCALL +RegEnumKeyA ( + HKEY hKey, + DWORD dwIndex, + LPSTR lpName, + DWORD cbName + ); + +LONG +STDCALL +RegEnumKeyExA ( + HKEY hKey, + DWORD dwIndex, + LPSTR lpName, + LPDWORD lpcbName, + LPDWORD lpReserved, + LPSTR lpClass, + LPDWORD lpcbClass, + PFILETIME lpftLastWriteTime + ); + +LONG +STDCALL +RegEnumValueA ( + HKEY hKey, + DWORD dwIndex, + LPSTR lpValueName, + LPDWORD lpcbValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ); + +LONG +STDCALL +RegLoadKeyA ( + HKEY hKey, + LPCSTR lpSubKey, + LPCSTR lpFile + ); + +LONG +STDCALL +RegOpenKeyA ( + HKEY hKey, + LPCSTR lpSubKey, + PHKEY phkResult + ); + +LONG +STDCALL +RegOpenKeyExA ( + HKEY hKey, + LPCSTR lpSubKey, + DWORD ulOptions, + REGSAM samDesired, + PHKEY phkResult + ); + +LONG +STDCALL +RegQueryInfoKeyA ( + HKEY hKey, + LPSTR lpClass, + LPDWORD lpcbClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime + ); + +LONG +STDCALL +RegQueryValueA ( + HKEY hKey, + LPCSTR lpSubKey, + LPSTR lpValue, + PLONG lpcbValue + ); + +LONG +STDCALL +RegQueryMultipleValuesA ( + HKEY hKey, + PVALENT val_list, + DWORD num_vals, + LPSTR lpValueBuf, + LPDWORD ldwTotsize + ); + +LONG +STDCALL +RegQueryValueExA ( + HKEY hKey, + LPSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ); + +LONG +STDCALL +RegReplaceKeyA ( + HKEY hKey, + LPCSTR lpSubKey, + LPCSTR lpNewFile, + LPCSTR lpOldFile + ); + +LONG +STDCALL +RegRestoreKeyA ( + HKEY hKey, + LPCSTR lpFile, + DWORD dwFlags + ); + +LONG +STDCALL +RegSaveKeyA ( + HKEY hKey, + LPCSTR lpFile, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +LONG +STDCALL +RegSetValueA ( + HKEY hKey, + LPCSTR lpSubKey, + DWORD dwType, + LPCSTR lpData, + DWORD cbData + ); + +LONG +STDCALL +RegSetValueExA ( + HKEY hKey, + LPCSTR lpValueName, + DWORD Reserved, + DWORD dwType, + CONST BYTE* lpData, + DWORD cbData + ); + +LONG +STDCALL +RegUnLoadKeyA ( + HKEY hKey, + LPCSTR lpSubKey + ); + +WINBOOL +STDCALL +InitiateSystemShutdownA( + LPSTR lpMachineName, + LPSTR lpMessage, + DWORD dwTimeout, + WINBOOL bForceAppsClosed, + WINBOOL bRebootAfterShutdown + ); + +WINBOOL +STDCALL +AbortSystemShutdownA( + LPSTR lpMachineName + ); + +int +STDCALL +CompareStringA( + LCID Locale, + DWORD dwCmpFlags, + LPCSTR lpString1, + int cchCount1, + LPCSTR lpString2, + int cchCount2); + +int +STDCALL +LCMapStringA( + LCID Locale, + DWORD dwMapFlags, + LPCSTR lpSrcStr, + int cchSrc, + LPSTR lpDestStr, + int cchDest); + +int +STDCALL +GetLocaleInfoA( + LCID Locale, + LCTYPE LCType, + LPSTR lpLCData, + int cchData); + +WINBOOL +STDCALL +SetLocaleInfoA( + LCID Locale, + LCTYPE LCType, + LPCSTR lpLCData); + +int +STDCALL +GetTimeFormatA( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME *lpTime, + LPCSTR lpFormat, + LPSTR lpTimeStr, + int cchTime); + +int +STDCALL +GetDateFormatA( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME *lpDate, + LPCSTR lpFormat, + LPSTR lpDateStr, + int cchDate); + +int +STDCALL +GetNumberFormatA( + LCID Locale, + DWORD dwFlags, + LPCSTR lpValue, + CONST NUMBERFMT *lpFormat, + LPSTR lpNumberStr, + int cchNumber); + +int +STDCALL +GetCurrencyFormatA( + LCID Locale, + DWORD dwFlags, + LPCSTR lpValue, + CONST CURRENCYFMT *lpFormat, + LPSTR lpCurrencyStr, + int cchCurrency); + +WINBOOL +STDCALL +EnumCalendarInfoA( + CALINFO_ENUMPROC lpCalInfoEnumProc, + LCID Locale, + CALID Calendar, + CALTYPE CalType); + +WINBOOL +STDCALL +EnumTimeFormatsA( + TIMEFMT_ENUMPROC lpTimeFmtEnumProc, + LCID Locale, + DWORD dwFlags); + +WINBOOL +STDCALL +EnumDateFormatsA( + DATEFMT_ENUMPROC lpDateFmtEnumProc, + LCID Locale, + DWORD dwFlags); + +WINBOOL +STDCALL +GetStringTypeExA( + LCID Locale, + DWORD dwInfoType, + LPCSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType); + +WINBOOL +STDCALL +GetStringTypeA( + LCID Locale, + DWORD dwInfoType, + LPCSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType); + + +int +STDCALL +FoldStringA( + DWORD dwMapFlags, + LPCSTR lpSrcStr, + int cchSrc, + LPSTR lpDestStr, + int cchDest); + +WINBOOL +STDCALL +EnumSystemLocalesA( + LOCALE_ENUMPROC lpLocaleEnumProc, + DWORD dwFlags); + +WINBOOL +STDCALL +EnumSystemCodePagesA( + CODEPAGE_ENUMPROC lpCodePageEnumProc, + DWORD dwFlags); + +WINBOOL +STDCALL +PeekConsoleInputA( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ); + +WINBOOL +STDCALL +ReadConsoleInputA( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ); + +WINBOOL +STDCALL +WriteConsoleInputA( + HANDLE hConsoleInput, + CONST INPUT_RECORD *lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten + ); + +WINBOOL +STDCALL +ReadConsoleOutputA( + HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion + ); + +WINBOOL +STDCALL +WriteConsoleOutputA( + HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion + ); + +WINBOOL +STDCALL +ReadConsoleOutputCharacterA( + HANDLE hConsoleOutput, + LPSTR lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead + ); + +WINBOOL +STDCALL +WriteConsoleOutputCharacterA( + HANDLE hConsoleOutput, + LPCSTR lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ); + +WINBOOL +STDCALL +FillConsoleOutputCharacterA( + HANDLE hConsoleOutput, + CHAR cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ); + +WINBOOL +STDCALL +ScrollConsoleScreenBufferA( + HANDLE hConsoleOutput, + CONST SMALL_RECT *lpScrollRectangle, + CONST SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + CONST CHAR_INFO *lpFill + ); + +DWORD +STDCALL +GetConsoleTitleA( + LPSTR lpConsoleTitle, + DWORD nSize + ); + +WINBOOL +STDCALL +SetConsoleTitleA( + LPCSTR lpConsoleTitle + ); + +WINBOOL +STDCALL +ReadConsoleA( + HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + LPVOID lpReserved + ); + +WINBOOL +STDCALL +WriteConsoleA( + HANDLE hConsoleOutput, + CONST VOID *lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved + ); + +DWORD STDCALL +WNetAddConnectionA( + LPCSTR lpRemoteName, + LPCSTR lpPassword, + LPCSTR lpLocalName + ); + +DWORD STDCALL +WNetAddConnection2A( + LPNETRESOURCE lpNetResource, + LPCSTR lpPassword, + LPCSTR lpUserName, + DWORD dwFlags + ); + +DWORD STDCALL +WNetAddConnection3A( + HWND hwndOwner, + LPNETRESOURCE lpNetResource, + LPCSTR lpPassword, + LPCSTR lpUserName, + DWORD dwFlags + ); + +DWORD STDCALL +WNetCancelConnectionA( + LPCSTR lpName, + WINBOOL fForce + ); + +DWORD STDCALL +WNetCancelConnection2A( + LPCSTR lpName, + DWORD dwFlags, + WINBOOL fForce + ); + +DWORD STDCALL +WNetGetConnectionA( + LPCSTR lpLocalName, + LPSTR lpRemoteName, + LPDWORD lpnLength + ); + +DWORD STDCALL +WNetUseConnectionA( + HWND hwndOwner, + LPNETRESOURCE lpNetResource, + LPCSTR lpUserID, + LPCSTR lpPassword, + DWORD dwFlags, + LPSTR lpAccessName, + LPDWORD lpBufferSize, + LPDWORD lpResult + ); + +DWORD STDCALL +WNetSetConnectionA( + LPCSTR lpName, + DWORD dwProperties, + LPVOID pvValues + ); + +DWORD STDCALL +WNetConnectionDialog1A( + LPCONNECTDLGSTRUCT lpConnDlgStruct + ); + +DWORD STDCALL +WNetDisconnectDialog1A( + LPDISCDLGSTRUCT lpConnDlgStruct + ); + +DWORD STDCALL +WNetOpenEnumA( + DWORD dwScope, + DWORD dwType, + DWORD dwUsage, + LPNETRESOURCE lpNetResource, + LPHANDLE lphEnum + ); + +DWORD STDCALL +WNetEnumResourceA( + HANDLE hEnum, + LPDWORD lpcCount, + LPVOID lpBuffer, + LPDWORD lpBufferSize + ); + +DWORD STDCALL +WNetGetUniversalNameA( + LPCSTR lpLocalPath, + DWORD dwInfoLevel, + LPVOID lpBuffer, + LPDWORD lpBufferSize + ); + +DWORD STDCALL +WNetGetUserA( + LPCSTR lpName, + LPSTR lpUserName, + LPDWORD lpnLength + ); + +DWORD STDCALL +WNetGetProviderNameA( + DWORD dwNetType, + LPSTR lpProviderName, + LPDWORD lpBufferSize + ); + +DWORD STDCALL +WNetGetNetworkInformationA( + LPCSTR lpProvider, + LPNETINFOSTRUCT lpNetInfoStruct + ); + +DWORD STDCALL +WNetGetLastErrorA( + LPDWORD lpError, + LPSTR lpErrorBuf, + DWORD nErrorBufSize, + LPSTR lpNameBuf, + DWORD nNameBufSize + ); + +DWORD STDCALL +MultinetGetConnectionPerformanceA( + LPNETRESOURCE lpNetResource, + LPNETCONNECTINFOSTRUCT lpNetConnectInfoStruct + ); + +WINBOOL +STDCALL +ChangeServiceConfigA( + SC_HANDLE hService, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCSTR lpDependencies, + LPCSTR lpServiceStartName, + LPCSTR lpPassword, + LPCSTR lpDisplayName + ); + +SC_HANDLE +STDCALL +CreateServiceA( + SC_HANDLE hSCManager, + LPCSTR lpServiceName, + LPCSTR lpDisplayName, + DWORD dwDesiredAccess, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCSTR lpDependencies, + LPCSTR lpServiceStartName, + LPCSTR lpPassword + ); + +WINBOOL +STDCALL +EnumDependentServicesA( + SC_HANDLE hService, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSA lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned + ); + +WINBOOL +STDCALL +EnumServicesStatusA( + SC_HANDLE hSCManager, + DWORD dwServiceType, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSA lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle + ); + +WINBOOL +STDCALL +GetServiceKeyNameA( + SC_HANDLE hSCManager, + LPCSTR lpDisplayName, + LPSTR lpServiceName, + LPDWORD lpcchBuffer + ); + +WINBOOL +STDCALL +GetServiceDisplayNameA( + SC_HANDLE hSCManager, + LPCSTR lpServiceName, + LPSTR lpDisplayName, + LPDWORD lpcchBuffer + ); + +SC_HANDLE +STDCALL +OpenSCManagerA( + LPCSTR lpMachineName, + LPCSTR lpDatabaseName, + DWORD dwDesiredAccess + ); + +SC_HANDLE +STDCALL +OpenServiceA( + SC_HANDLE hSCManager, + LPCSTR lpServiceName, + DWORD dwDesiredAccess + ); + +WINBOOL +STDCALL +QueryServiceConfigA( + SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGA lpServiceConfig, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ); + +WINBOOL +STDCALL +QueryServiceLockStatusA( + SC_HANDLE hSCManager, + LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ); + +SERVICE_STATUS_HANDLE +STDCALL +RegisterServiceCtrlHandlerA( + LPCSTR lpServiceName, + LPHANDLER_FUNCTION lpHandlerProc + ); + +WINBOOL +STDCALL +StartServiceCtrlDispatcherA( + LPSERVICE_TABLE_ENTRYA lpServiceStartTable + ); + +WINBOOL +STDCALL +StartServiceA( + SC_HANDLE hService, + DWORD dwNumServiceArgs, + LPCSTR *lpServiceArgVectors + ); + +/* Extensions to OpenGL */ + +WINBOOL STDCALL +wglUseFontBitmapsA(HDC, DWORD, DWORD, DWORD); + +WINBOOL STDCALL +wglUseFontOutlinesA(HDC, DWORD, DWORD, DWORD, FLOAT, + FLOAT, int, LPGLYPHMETRICSFLOAT); + +/* ------------------------------------- */ +/* From shellapi.h in old Cygnus headers */ + +unsigned int WINAPI +DragQueryFileA(HDROP, unsigned int, char *, unsigned int); + +HICON WINAPI +ExtractAssociatedIconA (HINSTANCE, char *, WORD *); + +HICON WINAPI +ExtractIconA (HINSTANCE, const char *, unsigned int); + +HINSTANCE WINAPI +FindExecutableA (const char *, const char *, char *); + +int WINAPI +ShellAboutA (HWND, const char *, const char *, HICON); + +HINSTANCE WINAPI +ShellExecuteA (HWND, const char *, const char *, char *, const char *, int); + +/* end of stuff from shellapi.h in old Cygnus headers */ +/* -------------------------------------------------- */ +/* From ddeml.h in old Cygnus headers */ + +HSZ WINAPI +DdeCreateStringHandleA (DWORD, char *, int); + +UINT WINAPI +DdeInitializeA (DWORD *, CALLB, DWORD, DWORD); + +DWORD WINAPI +DdeQueryStringA (DWORD, HSZ, char *, DWORD, int); + +/* end of stuff from ddeml.h in old Cygnus headers */ +/* ----------------------------------------------- */ + +WINBOOL STDCALL LogonUserA (LPSTR, LPSTR, LPSTR, DWORD, DWORD, HANDLE *); +WINBOOL STDCALL CreateProcessAsUserA (HANDLE, LPCTSTR, LPTSTR, + SECURITY_ATTRIBUTES*, SECURITY_ATTRIBUTES*, WINBOOL, DWORD, LPVOID, + LPCTSTR, STARTUPINFOA*, PROCESS_INFORMATION*); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GNU_H_WINDOWS32_ASCIIFUNCTIONS */ diff --git a/include/base.h b/include/base.h new file mode 100644 index 0000000..d57906e --- /dev/null +++ b/include/base.h @@ -0,0 +1,493 @@ +/* + Base.h + + Base definitions + + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + + Author: Scott Christley + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNU_H_WINDOWS32_BASE +#define _GNU_H_WINDOWS32_BASE + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef NULL +#ifdef __cplusplus +#define NULL (0) +#else +#define NULL ((void *)0) +#endif +#endif /* !NULL */ + +#include + +/* Check VOID before defining CHAR, SHORT, and LONG */ +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef short SHORT; +typedef long LONG; +#endif + + +#define CONST const + +#ifdef i386 +#define STDCALL __attribute__ ((stdcall)) +#define CDECL __attribute((cdecl)) +#define CALLBACK WINAPI +#define PASCAL WINAPI +#else +#define STDCALL +#define CDECL +#define CALLBACK +#define PASCAL +#endif +#define WINAPI STDCALL +#define APIENTRY STDCALL +#define WINGDIAPI + + + +#ifdef UNICODE +typedef unsigned short *LPTCH; +typedef unsigned short *LPTSTR; +#else +typedef char *LPTCH; +typedef char *LPTSTR; +#endif /* UNICODE */ + +#ifndef RC_INVOKED + +/* typedef ACMDRIVERENUMCB; +typedef ACMDRIVERPROC; +typedef ACMFILERCHOOSEHOOKPROC; +typedef ACMFILTERENUMCB; +typedef ACMFILTERTAGENUMCB; +typedef ACMFORMATCHOOSEHOOKPROC; +typedef ACMFORMATENUMCB; +typedef ACMFORMATTAGENUMCB; +typedef APPLET_PROC; +*/ +/* Changed from BOOL to WINBOOL to avoid Objective-C conflict */ +typedef unsigned long CALTYPE; +typedef unsigned long CALID; +typedef unsigned long COLORREF; + +/* +typedef CTRYID; +typedef DLGPROC; +*/ +typedef double DWORDLONG, *PDWORDLONG; +/* +typedef EDITWORDBREAKPROC; +typedef ENHMFENUMPROC; +typedef ENUMRESLANGPROC; +typedef ENUMRESNAMEPROC; +typedef ENUMRESTYPEPROC; +*/ +typedef float FLOAT; +/* typedef GLOBALHANDLE; */ +typedef HANDLE HACCEL; +typedef HANDLE HBITMAP; +typedef HANDLE HBRUSH; +typedef HANDLE HCOLORSPACE; +typedef HANDLE HCONV; +typedef HANDLE HCONVLIST; +typedef HANDLE HCURSOR; +typedef HANDLE HDBC; +typedef HANDLE HDC; +typedef HANDLE HDDEDATA; +typedef HANDLE HDESK; +typedef HANDLE HDROP; +typedef HANDLE HDWP; +typedef HANDLE HENHMETAFILE; +typedef HANDLE HENV; +typedef int HFILE; +typedef HANDLE HFONT; +typedef HANDLE HGDIOBJ; +typedef HANDLE HGLOBAL; +typedef HANDLE HGLRC; +typedef HANDLE HHOOK; +typedef HANDLE HICON; +typedef HANDLE HIMAGELIST; +typedef HANDLE HINSTANCE; +typedef HANDLE HKEY, *PHKEY; +typedef HANDLE HKL; +typedef HANDLE HLOCAL; +typedef HANDLE HMENU; +typedef HANDLE HMETAFILE; +typedef HANDLE HMODULE; +typedef HANDLE HPALETTE; +typedef HANDLE HPEN; +typedef HANDLE HRASCONN; +typedef long HRESULT; +typedef HANDLE HRGN; +typedef HANDLE HRSRC; +typedef HANDLE HSTMT; +typedef HANDLE HSZ; +typedef HANDLE HWINSTA; +typedef HANDLE HWND; +typedef unsigned short LANGID; +//typedef DWORD LCID; +typedef DWORD LCTYPE; +/* typedef LOCALHANDLE */ +typedef unsigned short *LP; +typedef long LPARAM; +typedef int WINBOOL; +typedef WINBOOL *LPBOOL; +typedef CONST CHAR *LPCCH; +typedef CHAR *LPCH; +typedef COLORREF *LPCOLORREF; + +#ifdef UNICODE +typedef const unsigned short *LPCTSTR; +#else +typedef const char *LPCTSTR; +#endif /* UNICODE */ + +typedef const unsigned short *LPCWCH; +typedef DWORD *LPDWORD; +/* typedef LPFRHOOKPROC; */ +typedef HANDLE *LPHANDLE; +/* typedef LPHANDLER_FUNCTION; */ +typedef PINT LPINT; +typedef PLONG LPLONG; + +typedef long LRESULT; +typedef unsigned short *LPWCH; +typedef unsigned short *LPWORD; +/* typedef NPSTR; */ +typedef unsigned short *NWPSTR; +typedef WINBOOL *PWINBOOL; +typedef const CHAR *PCCH; +typedef const char *PCSTR; +typedef const unsigned short *PCWCH; +/* typedef PHKEY; */ +/* typedef LCID *PLCID; */ +typedef short *PSHORT; +/* typedef PSID; */ +typedef char *PSTR; +typedef char *PSZ; + +#ifdef UNICODE +typedef unsigned short *PTBYTE; +typedef unsigned short *PTCH; +typedef unsigned short *PTCHAR; +typedef unsigned short *PTSTR; +#else +typedef unsigned char *PTBYTE; +typedef char *PTCH; +typedef char *PTCHAR; +typedef char *PTSTR; +#endif /* UNICODE */ + +/* + typedef PWSTR; + */ +typedef DWORD REGSAM; + + +typedef short RETCODE; + +typedef HANDLE SC_HANDLE; +typedef LPVOID SC_LOCK; +typedef SC_HANDLE *LPSC_HANDLE; +typedef DWORD SERVICE_STATUS_HANDLE; +/* typedef SPHANDLE; */ + +#ifdef UNICODE +typedef unsigned short TBYTE; +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +typedef unsigned short TCHAR; +#endif /* _TCHAR_DEFINED */ +typedef unsigned short BCHAR; +#else +typedef unsigned char TBYTE; +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +typedef char TCHAR; +#endif /* _TCHAR_DEFINED */ +typedef BYTE BCHAR; +#endif /* UNICODE */ + +typedef unsigned int WPARAM; +/* typedef YIELDPROC; */ + +/* Only use __stdcall under WIN32 compiler */ + +#define _export + +/* + Enumerations +*/ + + +#define RASCS_DONE 0x2000 +#define RASCS_PAUSED 0x1000 +typedef enum _RASCONNSTATE { + RASCS_OpenPort = 0, + RASCS_PortOpened, + RASCS_ConnectDevice, + RASCS_DeviceConnected, + RASCS_AllDevicesConnected, + RASCS_Authenticate, + RASCS_AuthNotify, + RASCS_AuthRetry, + RASCS_AuthCallback, + RASCS_AuthChangePassword, + RASCS_AuthProject, + RASCS_AuthLinkSpeed, + RASCS_AuthAck, + RASCS_ReAuthenticate, + RASCS_Authenticated, + RASCS_PrepareForCallback, + RASCS_WaitForModemReset, + RASCS_WaitForCallback, + RASCS_Projected, + + RASCS_StartAuthentication, + RASCS_CallbackComplete, + RASCS_LogonNetwork, + + RASCS_Interactive = RASCS_PAUSED, + RASCS_RetryAuthentication, + RASCS_CallbackSetByCaller, + RASCS_PasswordExpired, + + RASCS_Connected = RASCS_DONE, + RASCS_Disconnected +} RASCONNSTATE ; + +typedef enum _RASPROJECTION { + RASP_Amb = 0x10000, + RASP_PppNbf = 0x803F, + RASP_PppIpx = 0x802B, + RASP_PppIp = 0x8021 +} RASPROJECTION ; + +typedef enum _SID_NAME_USE { + SidTypeUser = 1, + SidTypeGroup, + SidTypeDomain, + SidTypeAlias, + SidTypeWellKnownGroup, + SidTypeDeletedAccount, + SidTypeInvalid, + SidTypeUnknown +} SID_NAME_USE, *PSID_NAME_USE; + +#endif /* ! defined (RC_INVOKED) */ + +/* + Macros +*/ +#define FORWARD_WM_NOTIFY(hwnd, idFrom, pnmhdr, fn) (void)(fn)((hwnd), WM_NOTIFY, (WPARAM)(int)(id), (LPARAM)(NMHDR FAR*)(pnmhdr)) + +#define GetBValue(rgb) ((BYTE) ((rgb) >> 16)) +#define GetGValue(rgb) ((BYTE) (((WORD) (rgb)) >> 8)) +#define GetRValue(rgb) ((BYTE) (rgb)) +#define RGB(r, g ,b) ((DWORD) (((BYTE) (r) | ((WORD) (g) << 8)) | (((DWORD) (BYTE) (b)) << 16))) + +#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) (fn)((hwnd), (int)(wParam), (NMHDR FAR*)(lParam)) + +#define HIBYTE(w) ((BYTE) (((WORD) (w) >> 8) & 0xFF)) +#define HIWORD(l) ((WORD) (((DWORD) (l) >> 16) & 0xFFFF)) +#define SHIWORD(l) ((INT16) (((DWORD) (l) >> 16) & 0xFFFF)) +#define LOBYTE(w) ((BYTE) (w)) +#define LOWORD(l) ((WORD) (l)) +#define SLOWORD(l) ((INT16) (l)) +#define MAKELONG(a, b) ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) +#define MAKEWORD(a, b) ((WORD) (((BYTE) (a)) | ((WORD) ((BYTE) (b))) << 8)) + +/* original Cygnus headers also had the following defined: */ +#define SEXT_HIWORD(l) ((((int)l) >> 16)) +#define ZEXT_HIWORD(l) ((((unsigned int)l) >> 16)) +#define SEXT_LOWORD(l) ((int)(short)l) + +#define INDEXTOOVERLAYMASK(i) ((i) << 8) +#define INDEXTOSTATEIMAGEMASK(i) ((i) << 12) + +#define MAKEINTATOM(i) (LPTSTR) ((DWORD) ((WORD) (i))) +#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i))) + +#define MAKELANGID(p, s) ((((WORD) (s)) << 10) | (WORD) (p)) +#define PRIMARYLANGID(lgid) ((WORD )(lgid) & 0x3ff) +#define SUBLANGID(lgid) ((WORD )(lgid) >> 10) + +#define LANGIDFROMLCID(lcid) ((WORD) (lcid)) +#define SORTIDFROMLCID(lcid) ((WORD )((((DWORD)(lcid)) & 0x000FFFFF) >> 16)) +#define MAKELCID(lgid, srtid) ((DWORD)((((DWORD)((WORD)(srtid))) << 16) | ((DWORD)((WORD)(lgid))))) +#define MAKELPARAM(l, h) ((LPARAM) MAKELONG(l, h)) +#define MAKELRESULT(l, h) ((LRESULT) MAKELONG(l, h)) +#define MAKEPOINTS(l) (*((POINTS FAR *) & (l))) +#define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore)) +#define MAKEWPARAM(l, h) ((WPARAM) MAKELONG(l, h)) + + +#define PALETTEINDEX(i) ((COLORREF) (0x01000000 | (DWORD) (WORD) (i))) +#define PALETTERGB(r, g, b) (0x02000000 | RGB(r, g, b)) +#define POINTSTOPOINT(pt, pts) {(pt).x = (SHORT) LOWORD(pts); (pt).y = (SHORT) HIWORD(pts);} +#define POINTTOPOINTS(pt) (MAKELONG((short) ((pt).x), (short) ((pt).y))) + +#define INDEXTOOVERLAYMASK(i) ((i) << 8) +#define INDEXTOSTATEIMAGEMASK(i) ((i) << 12) + +#ifdef UNICODE +#define _T(quote) L##quote +#define TEXT(quote) L##quote +#else +#define _T(quote) quote +#define TEXT(quote) quote +#endif + +#ifndef RC_INVOKED + +/* + Definitions for callback procedures +*/ +typedef int CALLBACK (*BFFCALLBACK) (HWND, UINT, LPARAM, LPARAM); +typedef UINT CALLBACK (*LPCCHOOKPROC) (HWND, UINT, WPARAM, LPARAM); +typedef UINT CALLBACK (*LPCFHOOKPROC) (HWND, UINT, WPARAM, LPARAM); +typedef DWORD CALLBACK (*EDITSTREAMCALLBACK) (DWORD, LPBYTE, LONG, LONG); +typedef UINT CALLBACK (*LPFRHOOKPROC) (HWND, UINT, WPARAM, LPARAM); +typedef UINT CALLBACK (*LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM); +typedef UINT CALLBACK (*LPPRINTHOOKPROC) (HWND, UINT, WPARAM, LPARAM); +typedef UINT CALLBACK (*LPSETUPHOOKPROC) (HWND, UINT, WPARAM, LPARAM); +typedef WINBOOL CALLBACK (*DLGPROC) (HWND, UINT, WPARAM, LPARAM); +typedef int CALLBACK (*PFNPROPSHEETCALLBACK) (HWND, UINT, LPARAM); +typedef VOID CALLBACK (*LPSERVICE_MAIN_FUNCTION) (DWORD, LPTSTR); +typedef int CALLBACK (*PFNTVCOMPARE) (LPARAM, LPARAM, LPARAM); +typedef LRESULT CALLBACK (*WNDPROC) (HWND, UINT, WPARAM, LPARAM); +typedef int CALLBACK (*FARPROC)(void); +typedef FARPROC PROC; +typedef WINBOOL CALLBACK (*ENUMRESTYPEPROC) (HANDLE, LPTSTR, LONG); +typedef WINBOOL CALLBACK (*ENUMRESNAMEPROC) (HANDLE, LPCTSTR, LPTSTR, LONG); +typedef WINBOOL CALLBACK (*ENUMRESLANGPROC) (HANDLE, LPCTSTR, LPCTSTR, WORD, LONG); +typedef FARPROC DESKTOPENUMPROC; +typedef WINBOOL CALLBACK (*ENUMWINDOWSPROC) (HWND, LPARAM); +typedef WINBOOL CALLBACK (*ENUMWINDOWSTATIONPROC) (LPTSTR, LPARAM); +typedef VOID CALLBACK (*SENDASYNCPROC) (HWND, UINT, DWORD, LRESULT); +typedef VOID CALLBACK (*TIMERPROC) (HWND, UINT, UINT, DWORD); +typedef FARPROC GRAYSTRINGPROC; +typedef WINBOOL CALLBACK (*DRAWSTATEPROC) (HDC, LPARAM, WPARAM, int, int); +typedef WINBOOL CALLBACK (*PROPENUMPROCEX) (HWND, LPCTSTR, HANDLE, DWORD); +typedef WINBOOL CALLBACK (*PROPENUMPROC) (HWND, LPCTSTR, HANDLE); +typedef LRESULT CALLBACK (*HOOKPROC) (int, WPARAM, LPARAM); +typedef VOID CALLBACK (*ENUMOBJECTSPROC) (LPVOID, LPARAM); +typedef VOID CALLBACK (*LINEDDAPROC) (int, int, LPARAM); +typedef WINBOOL CALLBACK (*ABORTPROC) (HDC, int); +typedef UINT CALLBACK (*LPPAGEPAINTHOOK) (HWND, UINT, WPARAM, LPARAM ); +typedef UINT CALLBACK (*LPPAGESETUPHOOK) (HWND, UINT, WPARAM, LPARAM ); +typedef int CALLBACK (*ICMENUMPROC) (LPTSTR, LPARAM); +typedef LONG (*EDITWORDBREAKPROCEX) (char *, LONG, BYTE, INT); +typedef int CALLBACK (*PFNLVCOMPARE) (LPARAM, LPARAM, LPARAM); +typedef WINBOOL CALLBACK (*LOCALE_ENUMPROC) (LPTSTR); +typedef WINBOOL CALLBACK (*CODEPAGE_ENUMPROC) (LPTSTR); +typedef WINBOOL CALLBACK (*DATEFMT_ENUMPROC) (LPTSTR); +typedef WINBOOL CALLBACK (*TIMEFMT_ENUMPROC) (LPTSTR); +typedef WINBOOL CALLBACK (*CALINFO_ENUMPROC) (LPTSTR); +typedef WINBOOL CALLBACK (*PHANDLER_ROUTINE) (DWORD); +typedef VOID CALLBACK (*LPHANDLER_FUNCTION) (DWORD); +typedef UINT CALLBACK (*PFNGETPROFILEPATH) (LPCTSTR, LPSTR, UINT); +typedef UINT CALLBACK (*PFNRECONCILEPROFILE) (LPCTSTR, LPCTSTR, DWORD); +typedef WINBOOL CALLBACK (*PFNPROCESSPOLICIES) (HWND, LPCTSTR, LPCTSTR, LPCTSTR, DWORD); + +#define SECURITY_NULL_SID_AUTHORITY {0,0,0,0,0,0} +#define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1} +#define SECURITY_LOCAL_SID_AUTHORITY {0,0,0,0,0,2} +#define SECURITY_CREATOR_SID_AUTHORITY {0,0,0,0,0,3} +#define SECURITY_NON_UNIQUE_AUTHORITY {0,0,0,0,0,4} +#define SECURITY_NT_AUTHORITY {0,0,0,0,0,5} + +#define SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege") +#define SE_ASSIGNPRIMARYTOKEN_NAME TEXT("SeAssignPrimaryTokenPrivilege") +#define SE_LOCK_MEMORY_NAME TEXT("SeLockMemoryPrivilege") +#define SE_INCREASE_QUOTA_NAME TEXT("SeIncreaseQuotaPrivilege") +#define SE_UNSOLICITED_INPUT_NAME TEXT("SeUnsolicitedInputPrivilege") +#define SE_MACHINE_ACCOUNT_NAME TEXT("SeMachineAccountPrivilege") +#define SE_TCB_NAME TEXT("SeTcbPrivilege") +#define SE_SECURITY_NAME TEXT("SeSecurityPrivilege") +#define SE_TAKE_OWNERSHIP_NAME TEXT("SeTakeOwnershipPrivilege") +#define SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege") +#define SE_SYSTEM_PROFILE_NAME TEXT("SeSystemProfilePrivilege") +#define SE_SYSTEMTIME_NAME TEXT("SeSystemtimePrivilege") +#define SE_PROF_SINGLE_PROCESS_NAME TEXT("SeProfileSingleProcessPrivilege") +#define SE_INC_BASE_PRIORITY_NAME TEXT("SeIncreaseBasePriorityPrivilege") +#define SE_CREATE_PAGEFILE_NAME TEXT("SeCreatePagefilePrivilege") +#define SE_CREATE_PERMANENT_NAME TEXT("SeCreatePermanentPrivilege") +#define SE_BACKUP_NAME TEXT("SeBackupPrivilege") +#define SE_RESTORE_NAME TEXT("SeRestorePrivilege") +#define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege") +#define SE_DEBUG_NAME TEXT("SeDebugPrivilege") +#define SE_AUDIT_NAME TEXT("SeAuditPrivilege") +#define SE_SYSTEM_ENVIRONMENT_NAME TEXT("SeSystemEnvironmentPrivilege") +#define SE_CHANGE_NOTIFY_NAME TEXT("SeChangeNotifyPrivilege") +#define SE_REMOTE_SHUTDOWN_NAME TEXT("SeRemoteShutdownPrivilege") + +#define SERVICES_ACTIVE_DATABASEW L"ServicesActive" +#define SERVICES_FAILED_DATABASEW L"ServicesFailed" +#define SERVICES_ACTIVE_DATABASEA "ServicesActive" +#define SERVICES_FAILED_DATABASEA "ServicesFailed" +#define SC_GROUP_IDENTIFIERW L'+' +#define SC_GROUP_IDENTIFIERA '+' + +#ifdef UNICODE +#define SERVICES_ACTIVE_DATABASE SERVICES_ACTIVE_DATABASEW +#define SERVICES_FAILED_DATABASE SERVICES_FAILED_DATABASEW +#define SC_GROUP_IDENTIFIER SC_GROUP_IDENTIFIERW +#else +#define SERVICES_ACTIVE_DATABASE SERVICES_ACTIVE_DATABASEA +#define SERVICES_FAILED_DATABASE SERVICES_FAILED_DATABASEA +#define SC_GROUP_IDENTIFIER SC_GROUP_IDENTIFIERA +#endif /* UNICODE */ + +/* ---------------------------------- */ +/* From ddeml.h in old Cygnus headers */ + +typedef void (*CALLB) (void); +typedef CALLB PFNCALLBACK; + + +/* End of stuff from ddeml.h in old Cygnus headers */ +/* ----------------------------------------------- */ + +typedef FARPROC WNDENUMPROC; +typedef FARPROC MFENUMPROC; +typedef FARPROC ENHMFENUMPROC; +typedef DWORD CCSTYLE, *PCCSTYLE, *LPCCSTYLE; +typedef DWORD CCSTYLEFLAGA, *PCCSTYLEFLAGA, *LPCCSTYLEFLAGA; +#define DECLARE_HANDLE(s) typedef HANDLE s + +#endif /* ! defined (RC_INVOKED) */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GNU_H_WINDOWS32_BASE */ diff --git a/include/coff.h b/include/coff.h new file mode 100644 index 0000000..4e467d3 --- /dev/null +++ b/include/coff.h @@ -0,0 +1,339 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_coff_h_ +#define __dj_include_coff_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +//#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +//#ifndef __STRICT_ANSI__ + +//#ifndef _POSIX_SOURCE + +/*** coff information for Intel 386/486. */ + +/********************** FILE HEADER **********************/ + +struct external_filehdr { + unsigned short f_magic; /* magic number */ + unsigned short f_nscns; /* number of sections */ + unsigned long f_timdat; /* time & date stamp */ + unsigned long f_symptr; /* file pointer to symtab */ + unsigned long f_nsyms; /* number of symtab entries */ + unsigned short f_opthdr; /* sizeof(optional hdr) */ + unsigned short f_flags; /* flags */ +}; + + +/* Bits for f_flags: + * F_RELFLG relocation info stripped from file + * F_EXEC file is executable (no unresolved external references) + * F_LNNO line numbers stripped from file + * F_LSYMS local symbols stripped from file + * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax) + */ + +#define F_RELFLG (0x0001) +#define F_EXEC (0x0002) +#define F_LNNO (0x0004) +#define F_LSYMS (0x0008) + + + +#define I386MAGIC 0x14c +#define I386AIXMAGIC 0x175 +#define I386BADMAG(x) (((x).f_magic!=I386MAGIC) && (x).f_magic!=I386AIXMAGIC) + + +#define FILHDR struct external_filehdr +#define FILHSZ sizeof(FILHDR) + + +/********************** AOUT "OPTIONAL HEADER" **********************/ + + +typedef struct +{ + unsigned short magic; /* type of file */ + unsigned short vstamp; /* version stamp */ + unsigned long tsize; /* text size in bytes, padded to FW bdry*/ + unsigned long dsize; /* initialized data " " */ + unsigned long bsize; /* uninitialized data " " */ + unsigned long entry; /* entry pt. */ + unsigned long text_start; /* base of text used for this file */ + unsigned long data_start; /* base of data used for this file */ +} +AOUTHDR; + + +typedef struct gnu_aout { + unsigned long info; + unsigned long tsize; + unsigned long dsize; + unsigned long bsize; + unsigned long symsize; + unsigned long entry; + unsigned long txrel; + unsigned long dtrel; + } GNU_AOUT; + +#define AOUTSZ (sizeof(AOUTHDR)) + +#define OMAGIC 0404 /* object files, eg as output */ +#define ZMAGIC 0413 /* demand load format, eg normal ld output */ +#define STMAGIC 0401 /* target shlib */ +#define SHMAGIC 0443 /* host shlib */ + + +/********************** SECTION HEADER **********************/ + + +struct external_scnhdr { + char s_name[8]; /* section name */ + unsigned long s_paddr; /* physical address, aliased s_nlib */ + unsigned long s_vaddr; /* virtual address */ + unsigned long s_size; /* section size */ + unsigned long s_scnptr; /* file ptr to raw data for section */ + unsigned long s_relptr; /* file ptr to relocation */ + unsigned long s_lnnoptr; /* file ptr to line numbers */ + unsigned short s_nreloc; /* number of relocation entries */ + unsigned short s_nlnno; /* number of line number entries*/ + unsigned long s_flags; /* flags */ +}; + +#define SCNHDR struct external_scnhdr +#define SCNHSZ sizeof(SCNHDR) + +/* + * names of "special" sections + */ +#define _TEXT ".text" +#define _DATA ".data" +#define _BSS ".bss" +#define _COMMENT ".comment" +#define _LIB ".lib" + +/* + * s_flags "type" + */ +#define STYP_TEXT (0x0020) /* section contains text only */ +#define STYP_DATA (0x0040) /* section contains data only */ +#define STYP_BSS (0x0080) /* section contains bss only */ + +/********************** LINE NUMBERS **********************/ + +/* 1 line number entry for every "breakpointable" source line in a section. + * Line numbers are grouped on a per function basis; first entry in a function + * grouping will have l_lnno = 0 and in place of physical address will be the + * symbol table index of the function name. + */ +struct external_lineno { + union { + unsigned long l_symndx __attribute__((packed)); /* function name symbol index, iff l_lnno == 0 */ + unsigned long l_paddr __attribute__((packed)); /* (physical) address of line number */ + } l_addr; + unsigned short l_lnno; /* line number */ +}; + + +#define LINENO struct external_lineno +#define LINESZ sizeof(LINENO) + + +/********************** SYMBOLS **********************/ + +#define E_SYMNMLEN 8 /* # characters in a symbol name */ +#define E_FILNMLEN 14 /* # characters in a file name */ +#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */ + +struct external_syment +{ + union { + char e_name[E_SYMNMLEN]; + struct { + unsigned long e_zeroes __attribute__((packed)); + unsigned long e_offset __attribute__((packed)); + } e; + } e; + unsigned long e_value __attribute__((packed)); + short e_scnum; + unsigned short e_type; + unsigned char e_sclass; + unsigned char e_numaux; +}; + +#define N_BTMASK (0xf) +#define N_TMASK (0x30) +#define N_BTSHFT (4) +#define N_TSHIFT (2) + +union external_auxent { + struct { + unsigned long x_tagndx __attribute__((packed)); /* str, un, or enum tag indx */ + union { + struct { + unsigned short x_lnno; /* declaration line number */ + unsigned short x_size; /* str/union/array size */ + } x_lnsz; + unsigned long x_fsize __attribute__((packed)); /* size of function */ + } x_misc; + union { + struct { /* if ISFCN, tag, or .bb */ + unsigned long x_lnnoptr __attribute__((packed)); /* ptr to fcn line # */ + unsigned long x_endndx __attribute__((packed)); /* entry ndx past block end */ + } x_fcn; + struct { /* if ISARY, up to 4 dimen. */ + unsigned short x_dimen[E_DIMNUM]; + } x_ary; + } x_fcnary; + unsigned short x_tvndx; /* tv index */ + } x_sym; + + union { + char x_fname[E_FILNMLEN]; + struct { + unsigned long x_zeroes __attribute__((packed)); + unsigned long x_offset __attribute__((packed)); + } x_n; + } x_file; + + struct { + unsigned long x_scnlen __attribute__((packed)); /* section length */ + unsigned short x_nreloc; /* # relocation entries */ + unsigned short x_nlinno; /* # line numbers */ + } x_scn; + + struct { + unsigned long x_tvfill __attribute__((packed)); /* tv fill value */ + unsigned short x_tvlen; /* length of .tv */ + unsigned short x_tvran[2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + +}; + +#define SYMENT struct external_syment +#define SYMESZ sizeof(SYMENT) +#define AUXENT union external_auxent +#define AUXESZ sizeof(AUXENT) + + +# define _ETEXT "etext" + + +/* Relocatable symbols have number of the section in which they are defined, + or one of the following: */ + +#define N_UNDEF ((short)0) /* undefined symbol */ +#define N_ABS ((short)-1) /* value of symbol is absolute */ +#define N_DEBUG ((short)-2) /* debugging symbol -- value is meaningless */ +#define N_TV ((short)-3) /* indicates symbol needs preload transfer vector */ +#define P_TV ((short)-4) /* indicates symbol needs postload transfer vector*/ + +/* + * Type of a symbol, in low N bits of the word + */ +#define T_NULL 0 +#define T_VOID 1 /* function argument (only used by compiler) */ +#define T_CHAR 2 /* character */ +#define T_SHORT 3 /* short integer */ +#define T_INT 4 /* integer */ +#define T_LONG 5 /* long integer */ +#define T_FLOAT 6 /* floating point */ +#define T_DOUBLE 7 /* double word */ +#define T_STRUCT 8 /* structure */ +#define T_UNION 9 /* union */ +#define T_ENUM 10 /* enumeration */ +#define T_MOE 11 /* member of enumeration*/ +#define T_UCHAR 12 /* unsigned character */ +#define T_USHORT 13 /* unsigned short */ +#define T_UINT 14 /* unsigned integer */ +#define T_ULONG 15 /* unsigned long */ +#define T_LNGDBL 16 /* long double */ + +/* + * derived types, in n_type +*/ +#define DT_NON (0) /* no derived type */ +#define DT_PTR (1) /* pointer */ +#define DT_FCN (2) /* function */ +#define DT_ARY (3) /* array */ + +#define BTYPE(x) ((x) & N_BTMASK) + +#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT)) +#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT)) +#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT)) +#define ISTAG(x) ((x)==C_STRTAG||(x)==C_UNTAG||(x)==C_ENTAG) +#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK)) + +/********************** STORAGE CLASSES **********************/ + +/* This used to be defined as -1, but now n_sclass is unsigned. */ +#define C_EFCN 0xff /* physical end of function */ +#define C_NULL 0 +#define C_AUTO 1 /* automatic variable */ +#define C_EXT 2 /* external symbol */ +#define C_STAT 3 /* static */ +#define C_REG 4 /* register variable */ +#define C_EXTDEF 5 /* external definition */ +#define C_LABEL 6 /* label */ +#define C_ULABEL 7 /* undefined label */ +#define C_MOS 8 /* member of structure */ +#define C_ARG 9 /* function argument */ +#define C_STRTAG 10 /* structure tag */ +#define C_MOU 11 /* member of union */ +#define C_UNTAG 12 /* union tag */ +#define C_TPDEF 13 /* type definition */ +#define C_USTATIC 14 /* undefined static */ +#define C_ENTAG 15 /* enumeration tag */ +#define C_MOE 16 /* member of enumeration */ +#define C_REGPARM 17 /* register parameter */ +#define C_FIELD 18 /* bit field */ +#define C_AUTOARG 19 /* auto argument */ +#define C_LASTENT 20 /* dummy entry (end of block) */ +#define C_BLOCK 100 /* ".bb" or ".eb" */ +#define C_FCN 101 /* ".bf" or ".ef" */ +#define C_EOS 102 /* end of structure */ +#define C_FILE 103 /* file name */ +#define C_LINE 104 /* line # reformatted as symbol table entry */ +#define C_ALIAS 105 /* duplicate tag */ +#define C_HIDDEN 106 /* ext symbol in dmert public lib */ + +/********************** RELOCATION DIRECTIVES **********************/ + + + +struct external_reloc { + unsigned long r_vaddr __attribute__((packed)); + unsigned long r_symndx __attribute__((packed)); + unsigned short r_type; +}; + + +#define RELOC struct external_reloc +#define RELSZ sizeof(RELOC) + +#define RELOC_REL32 20 /* 32-bit PC-relative address */ +#define RELOC_ADDR32 6 /* 32-bit absolute address */ + +#define DEFAULT_DATA_SECTION_ALIGNMENT 4 +#define DEFAULT_BSS_SECTION_ALIGNMENT 4 +#define DEFAULT_TEXT_SECTION_ALIGNMENT 4 +/* For new sections we havn't heard of before */ +#define DEFAULT_SECTION_ALIGNMENT 4 + +//#endif /* !_POSIX_SOURCE */ +//#endif /* !__STRICT_ANSI__ */ +//#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* !__dj_include_coff_h_ */ diff --git a/include/crtdll/alloc.h b/include/crtdll/alloc.h new file mode 100644 index 0000000..a351fde --- /dev/null +++ b/include/crtdll/alloc.h @@ -0,0 +1,77 @@ +/* + * alloc.h + * + * Memory management functions. Because most of these functions are + * actually declared in stdlib.h I have decided to simply include that + * header file. This file is included by malloc.h. My head hurts... + * + * NOTE: In the version of the Standard C++ Library from Cygnus there + * is also an alloc.h which needs to be on your include path. Most of + * the time I think the most sensible option would be to get rid of + * this file. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _ALLOC_H_ +#define _ALLOC_H_ + +#include + +#ifndef RC_INVOKED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The structure used to walk through the heap with _heapwalk. + * TODO: This is a guess at the internals of this structure. + */ +typedef struct _heapinfo +{ + void* ptr; + unsigned int size; + int in_use; +} _HEAPINFO; + +int _heapwalk (_HEAPINFO* pHeapinfo); +void * _alloca(size_t size); + + + +#ifndef _NO_OLDNAMES +#define heapwalk(x) _heapwalk(x) +#define alloca(s) _alloca(s) +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* Not _ALLOC_H_ */ + +#endif /* Not __STRICT_ANSI__ */ + diff --git a/include/crtdll/assert.h b/include/crtdll/assert.h new file mode 100644 index 0000000..8d85fcf --- /dev/null +++ b/include/crtdll/assert.h @@ -0,0 +1,69 @@ +/* + * assert.h + * + * Define the assert macro for debug output. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NDEBUG + +/* + * If not debugging, assert does nothing. + */ +#define assert(x) ((void)0); + +#else /* debugging enabled */ + +/* + * CRTDLL nicely supplies a function which does the actual output and + * call to abort. + */ +#ifndef __ATTRIB_NORETURN +#ifdef __GNUC__ +#define _ATTRIB_NORETURN __attribute__ ((noreturn)) +#else /* Not __GNUC__ */ +#define _ATTRIB_NORETURN +#endif /* __GNUC__ */ +#endif + +void _assert (const char* szExpression, const char* szFileName, int nLine) +_ATTRIB_NORETURN +; + +/* + * Definition of the assert macro. + */ +#define assert(x) if(!(x)) _assert( #x , __FILE__, __LINE__); +#endif /* NDEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crtdll/conio.h b/include/crtdll/conio.h new file mode 100644 index 0000000..db012be --- /dev/null +++ b/include/crtdll/conio.h @@ -0,0 +1,67 @@ +/* + * conio.h + * + * Low level console I/O functions. Pretty please try to use the ANSI + * standard ones if you are writing new code. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _CONIO_H_ +#define _CONIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +char* _cgets (char* szBuffer); +int _cprintf (const char* szFormat, ...); +int _cputs (const char* szString); +int _cscanf (char* szFormat, ...); + +int _getch (void); +int _getche (void); +int _kbhit (void); +int _putch (int cPut); +int _ungetch (int cUnget); + + +#ifndef _NO_OLDNAMES + +#define getch _getch +#define getche _getche +#define kbhit _kbhit +#define putch(cPut) _putch(cPut) +#define ungetch(cUnget) _ungetch(cUnget) + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _CONIO_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/crtdll.h b/include/crtdll/crtdll.h new file mode 100644 index 0000000..fb1f1ad --- /dev/null +++ b/include/crtdll/crtdll.h @@ -0,0 +1 @@ +void debug_printf(char* fmt, ...); diff --git a/include/crtdll/ctype.h b/include/crtdll/ctype.h new file mode 100644 index 0000000..7a11bdf --- /dev/null +++ b/include/crtdll/ctype.h @@ -0,0 +1,142 @@ +/* + * ctype.h + * + * Functions for testing character types and converting characters. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +#ifndef _LINUX_CTYPE_H +#define _LINUX_CTYPE_H + +#ifndef _CTYPE_H_ +#define _CTYPE_H_ + +#define __need_wchar_t +#define __need_wint_t +#include + + +/* + * The following flags are used to tell iswctype and _isctype what character + * types you are looking for. + */ +#define _UPPER 0x0001 +#define _LOWER 0x0002 +#define _DIGIT 0x0004 +#define _SPACE 0x0008 +#define _PUNCT 0x0010 +#define _CONTROL 0x0020 +#define _BLANK 0x0040 +#define _HEX 0x0080 + +#define _ALPHA 0x0103 +#define _LEADBYTE 0x8000 + + +#ifdef __cplusplus +extern "C" { +#endif + +int isalnum(int c); +int isalpha(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); + +#ifndef __STRICT_ANSI__ +int _isctype (unsigned int c, int ctypeFlags); +#endif + +int tolower(int c); +int toupper(int c); + +/* + * NOTE: The above are not old name type wrappers, but functions exported + * explicitly by CRTDLL. However, underscored versions are also exported. + */ +#ifndef __STRICT_ANSI__ +int _tolower(int c); +int _toupper(int c); +#endif + +#ifndef WEOF +#define WEOF (wchar_t)(0xFFFF) +#endif + +/* + * TODO: MB_CUR_MAX should be defined here (if not already defined, since + * it should also be defined in stdlib.h). It is supposed to be the + * maximum number of bytes in a multi-byte character in the current + * locale. Perhaps accessible through the __mb_curr_max_dll entry point, + * but I think (again) that that is a variable pointer, which leads to + * problems under the current Cygwin compiler distribution. + */ + +typedef int wctype_t; + +/* Wide character equivalents */ +int iswalnum(wint_t wc); +int iswalpha(wint_t wc); +int iswascii(wint_t wc); +int iswcntrl(wint_t wc); +int iswctype(wint_t wc, wctype_t wctypeFlags); +int is_wctype(wint_t wc, wctype_t wctypeFlags); /* Obsolete! */ +int iswdigit(wint_t wc); +int iswgraph(wint_t wc); +int iswlower(wint_t wc); +int iswprint(wint_t wc); +int iswpunct(wint_t wc); +int iswspace(wint_t wc); +int iswupper(wint_t wc); +int iswxdigit(wint_t wc); + +wchar_t towlower(wchar_t c); +wchar_t towupper(wchar_t c); + +int isleadbyte (int c); + +#ifndef __STRICT_ANSI__ +int __isascii (int c); +int __toascii (int c); +int __iscsymf (int c); /* Valid first character in C symbol */ +int __iscsym (int c); /* Valid character in C symbol (after first) */ + +#ifndef _NO_OLDNAMES +#define isascii(c) __isascii(c) +#define toascii(c) _toascii(c) +#define iscsymf(c) __iscsymf(c) +#define iscsym(c) __iscsym(c) +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif +#endif diff --git a/include/crtdll/dir.h b/include/crtdll/dir.h new file mode 100644 index 0000000..0cb14eb --- /dev/null +++ b/include/crtdll/dir.h @@ -0,0 +1,103 @@ +/* + * dir.h + * + * Functions for working with directories and path names. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _DIR_H_ +#define _DIR_H_ + +#include /* To get FILENAME_MAX... ugly. */ +#include /* To get time_t. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Attributes of files as returned by _findfirst et al. + */ +#define _A_NORMAL 0x00000000 +#define _A_RDONLY 0x00000001 +#define _A_HIDDEN 0x00000002 +#define _A_SYSTEM 0x00000004 +#define _A_VOLID 0x00000008 +#define _A_SUBDIR 0x00000010 +#define _A_ARCH 0x00000020 + +#ifndef _FSIZE_T_DEFINED +typedef unsigned long _fsize_t; +#define _FSIZE_T_DEFINED +#endif + +/* + * The following structure is filled in by _findfirst or _findnext when + * they succeed in finding a match. + */ +struct _finddata_t +{ + unsigned attrib; /* Attributes, see constants above. */ + time_t time_create; + time_t time_access; /* always midnight local time */ + time_t time_write; + _fsize_t size; + char name[FILENAME_MAX]; /* may include spaces. */ +}; + +/* + * Functions for searching for files. _findfirst returns -1 if no match + * is found. Otherwise it returns a handle to be used in _findnext and + * _findclose calls. _findnext also returns -1 if no match could be found, + * and 0 if a match was found. Call _findclose when you are finished. + */ +int _findfirst (const char* szFilespec, struct _finddata_t* find); +int _findnext (int nHandle, struct _finddata_t* find); +int _findclose (int nHandle); + +int _chdir (const char* szPath); +char* _getcwd (char* caBuffer, int nBufferSize); +int _mkdir (const char* szPath); +char* _mktemp (char* szTemplate); +int _rmdir (const char* szPath); + + +#ifndef _NO_OLDNAMES + +int chdir (const char* szPath); +char* getcwd (char* caBuffer, int nBufferSize); +int mkdir (const char* szPath); +char* mktemp (char* szTemplate); +int rmdir (const char* szPath); + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _DIR_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/direct.h b/include/crtdll/direct.h new file mode 100644 index 0000000..49dc129 --- /dev/null +++ b/include/crtdll/direct.h @@ -0,0 +1,27 @@ +#ifndef __include_direct_h_ +#define __include_direct_h_ + +struct _diskfree_t { + unsigned short total_clusters; + unsigned short avail_clusters; + unsigned short sectors_per_cluster; + unsigned short bytes_per_sector; +}; + + +int _chdrive( int drive ); +int _getdrive( void ); +char *_getcwd( char *buffer, int maxlen ); + +int _chdir(const char *_path); +char *_getcwd(char *, int); +int _mkdir(const char *_path); +int _rmdir(const char *_path); +unsigned int _getdiskfree(unsigned int _drive, struct _diskfree_t *_diskspace); +#define chdir _chdir +#define getcwd _getcwd +#define mkdir _mkdir +#define rmdir _rmdir + + +#endif diff --git a/include/crtdll/dirent.h b/include/crtdll/dirent.h new file mode 100644 index 0000000..26d6aba --- /dev/null +++ b/include/crtdll/dirent.h @@ -0,0 +1,61 @@ +/* + * DIRENT.H (formerly DIRLIB.H) + * + * by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Because I have heard that this feature (opendir, readdir, closedir) + * it so useful for programmers coming from UNIX or attempting to port + * UNIX code, and because it is reasonably light weight, I have included + * it in the Mingw32 package. + * - Colin Peters + * + * This code is distributed in the hope that is will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includeds but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _STRICT_ANSI + +#ifndef _DIRENT_H_ +#define _DIRENT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct dirent +{ + long d_ino; + unsigned short d_reclen; + unsigned short d_namlen; + char d_name[FILENAME_MAX+1]; +}; + +typedef struct +{ + struct _finddata_t dd_dta; /* disk transfer area for this dir */ + struct dirent dd_dir; /* dirent struct to return from dir */ + long dd_handle; /* _findnext handle */ + short dd_stat; /* status return from last lookup */ + char dd_name[1]; /* full name of file (struct is extended */ +} DIR; + +DIR* opendir (const char* szPath); +struct dirent* readdir (DIR* dir); +int closedir (DIR* dir); + +#ifdef __cplusplus +} +#endif + +#endif _DIRENT_H_ + +#endif /* Not _STRICT_ANSI */ diff --git a/include/crtdll/dos.h b/include/crtdll/dos.h new file mode 100644 index 0000000..f31ecb1 --- /dev/null +++ b/include/crtdll/dos.h @@ -0,0 +1,158 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_h_ +#define __dj_include_h_ + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + + + +struct ftime { + unsigned ft_tsec:5; /* 0-29, double to get real seconds */ + unsigned ft_min:6; /* 0-59 */ + unsigned ft_hour:5; /* 0-23 */ + unsigned ft_day:5; /* 1-31 */ + unsigned ft_month:4; /* 1-12 */ + unsigned ft_year:7; /* since 1980 */ +}; + +struct date { + short da_year; + char da_day; + char da_mon; +}; + +struct time { + unsigned char ti_min; + unsigned char ti_hour; + unsigned char ti_hund; + unsigned char ti_sec; +}; + +struct dfree { + unsigned df_avail; + unsigned df_total; + unsigned df_bsec; + unsigned df_sclus; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +extern unsigned short _osmajor, _osminor; +extern const char * _os_flavor; + +unsigned short _get_version(int); + + + + +int getftime(int handle, struct ftime *ftimep); +int setftime(int handle, struct ftime *ftimep); + +int getcbrk(void); +int setcbrk(int new_value); + +void getdate(struct date *); +void gettime(struct time *); +void setdate(struct date *); +void settime(struct time *); + +void getdfree(unsigned char drive, struct dfree *ptr); + +void delay(unsigned msec); +/* int _get_default_drive(void); +void _fixpath(const char *, char *); */ + + +/* + * For compatibility with other DOS C compilers. + */ + +#define _A_NORMAL 0x00 /* Normal file - No read/write restrictions */ +#define _A_RDONLY 0x01 /* Read only file */ +#define _A_HIDDEN 0x02 /* Hidden file */ +#define _A_SYSTEM 0x04 /* System file */ +#define _A_VOLID 0x08 /* Volume ID file */ +#define _A_SUBDIR 0x10 /* Subdirectory */ +#define _A_ARCH 0x20 /* Archive file */ + +#define _enable enable +#define _disable disable + +struct date_t { + unsigned char day; /* 1-31 */ + unsigned char month; /* 1-12 */ + unsigned short year; /* 1980-2099 */ + unsigned char dayofweek; /* 0-6, 0=Sunday */ +}; +#define dosdate_t date_t + +struct time_t { + unsigned char hour; /* 0-23 */ + unsigned char minute; /* 0-59 */ + unsigned char second; /* 0-59 */ + unsigned char hsecond; /* 0-99 */ +}; +#define dostime_t time_t + + + +#define finddata_t _finddata_t + + +#define diskfree_t _diskfree_t + +struct _DOSERROR { + int exterror; + #ifdef __cplusplus + char errclass; + #else + char class; + #endif + char action; + char locus; +}; +#define DOSERROR _DOSERROR + + + + +void _getdate(struct date_t *_date); +unsigned int _setdate(struct date_t *_date); +void _gettime(struct time_t *_time); +unsigned int _settime(struct time_t *_time); + +unsigned int _getftime(int _handle, unsigned int *_p_date, unsigned int *_p_time); +unsigned int _setftime(int _handle, unsigned int _date, unsigned int _time); +unsigned int _getfileattr(const char *_filename, unsigned int *_p_attr); +unsigned int _setfileattr(const char *_filename, unsigned int _attr); + + +void _setdrive(unsigned int _drive, unsigned int *_p_drives); + + +int exterr(struct _DOSERROR *_p_error); +#define dosexterr(_ep) exterr(_ep) + +#include + +#define int386(_i, _ir, _or) int86(_i, _ir, _or) +#define int386x(_i, _ir, _or, _sr) int86x(_i, _ir, _or, _sr) + +#ifdef __cplusplus +} +#endif + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#endif /* !__dj_include_h_ */ diff --git a/include/crtdll/errno.h b/include/crtdll/errno.h new file mode 100644 index 0000000..a69c3c5 --- /dev/null +++ b/include/crtdll/errno.h @@ -0,0 +1,134 @@ +/* + * errno.h + * + * Error numbers and access to error reporting. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Error numbers. + * TODO: Can't be sure of some of these assignments, I guessed from the + * names given by strerror and the defines in the Cygnus errno.h. A lot + * of the names from the Cygnus errno.h are not represented, and a few + * of the descriptions returned by strerror do not obviously match + * their error naming. + */ +#define EPERM 1 /* Operation not permitted */ +#define ENOFILE 2 /* No such file or directory */ +#define ENOENT 2 +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted function call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Resource temporarily unavailable */ +#define ENOMEM 12 /* Not enough space */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +/* 15 - Unknown Error */ +#define EBUSY 16 /* strerror reports "Resource device" */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Improper link (cross-device link?) */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate I/O control operation */ +/* 26 - Unknown Error */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Invalid seek (seek on a pipe?) */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Domain error (math functions) */ +#define ERANGE 34 /* Result too large (possibly too small) */ +/* 35 - Unknown Error */ +#define EDEADLOCK 36 /* Resource deadlock avoided (non-Cyg) */ +#define EDEADLK 36 +/* 37 - Unknown Error */ +#define ENAMETOOLONG 38 /* Filename too long (91 in Cyg?) */ +#define ENOLCK 39 /* No locks available (46 in Cyg?) */ +#define ENOSYS 40 /* Function not implemented (88 in Cyg?) */ +#define ENOTEMPTY 41 /* Directory not empty (90 in Cyg?) */ +#define EILSEQ 42 /* Illegal byte sequence */ + +/* + * NOTE: ENAMETOOLONG and ENOTEMPTY conflict with definitions in the + * sockets.h header provided with windows32api-0.1.2. + * You should go and put an #if 0 ... #endif around the whole block + * of errors (look at the comment above them). + */ + +/* + * Definitions of macros for the 'variables' errno, _doserrno, sys_nerr and + * sys_errlist. + */ +int* _errno(void); +#define errno (*_errno()) + +int* __doserrno(void); +#define _doserrno (*__doserrno()) + +#if __MSVCRT__ +/* One of the MSVCRTxx libraries */ + +extern int* __imp__sys_nerr; +#define sys_nerr (*__imp__sys_nerr) + +extern char** __imp__sys_errlist; +#ifndef sys_errlist +#define sys_errlist (__imp__sys_errlist) +#endif + +#else +/* CRTDLL run time library */ + + +#define _sys_nerr (*_sys_nerr_dll) +extern int* _sys_nerr_dll; +#define sys_nerr (*_sys_nerr_dll) + +extern const char* __sys_errlist[]; +#define sys_errlist (__sys_errlist) + +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crtdll/excpt.h b/include/crtdll/excpt.h new file mode 100644 index 0000000..a10c909 --- /dev/null +++ b/include/crtdll/excpt.h @@ -0,0 +1,121 @@ +/* + * excpt.h + * + * Support for operating system level structured exception handling. + * + * NOTE: This is very preliminary stuff. I am also pretty sure it is + * completely Intel specific. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * Based on code by Mikey + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _EXCPT_H_ +#define _EXCPT_H_ + +#ifndef __STRICT_ANSI__ + +#include + +/* + * NOTE: The constants structs and typedefs below should be defined in the + * Win32 API headers. + */ +#define EH_NONCONTINUABLE 0x01 +#define EH_UNWINDING 0x02 +#define EH_EXIT_UNWIND 0x04 +#define EH_STACK_INVALID 0x08 +#define EH_NESTED_CALL 0x10 + +#ifndef RC_INVOKED + +typedef enum { + ExceptionContinueExecution, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind +} EXCEPTION_DISPOSITION; + + +/* + * End of stuff that should be in the Win32 API files. + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The type of function that is expected as an exception handler to be + * installed with _try1. + */ +typedef EXCEPTION_DISPOSITION (*PEXCEPTION_HANDLER) + (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); + +/* + * This is not entirely necessary, but it is the structure installed by + * the _try1 primitive below. + */ +typedef struct _EXCEPTION_REGISTRATION +{ + struct _EXCEPTION_REGISTRATION* prev; + PEXCEPTION_HANDLER handler; +} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION; + +typedef EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION_RECORD; +typedef PEXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION_RECORD; + +/* + * A macro which installs the supplied exception handler. + * Push the pointer to the new handler onto the stack, + * then push the pointer to the old registration structure (at fs:0) + * onto the stack, then put a pointer to the new registration + * structure (i.e. the current stack pointer) at fs:0. + */ +#define __try1(pHandler) \ + __asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (pHandler)); + + +/* + * A macro which (dispite its name) *removes* an installed + * exception handler. Should be used only in conjunction with the above + * install routine __try1. + * Move the pointer to the old reg. struct (at the current stack + * position) to fs:0, replacing the pointer we installed above, + * then add 8 to the stack pointer to get rid of the space we + * used when we pushed on our new reg. struct above. Notice that + * the stack must be in the exact state at this point that it was + * after we did _try1 or this will smash things. + */ +#define __except1 \ + __asm__ ("movl (%%esp),%%eax;movl %%eax,%%fs:0;addl $8,%%esp;" \ + : : : "%eax"); + +#ifdef __cplusplus +} +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* Not strict ANSI */ + +#endif /* _EXCPT_H_ not defined */ diff --git a/include/crtdll/fcntl.h b/include/crtdll/fcntl.h new file mode 100644 index 0000000..ccb674a --- /dev/null +++ b/include/crtdll/fcntl.h @@ -0,0 +1,125 @@ +/* + * fcntl.h + * + * Access constants for _open. Note that the permissions constants are + * in sys/stat.h (ick). + * + * This code is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* added _O_RANDOM_O_SEQUENTIAL _O_SHORT_LIVED*/ +/* changed fmode_dll */ + +#ifndef _FCNTL_H_ +#define _FCNTL_H_ + +/* + * It appears that fcntl.h should include io.h for compatibility... + */ +#include + +/* + * This variable determines the default file mode. + * TODO: Which flags work? + */ +#if 0 +#if __MSVCRT__ +extern unsigned int* __imp__fmode; +#define _fmode (*__imp__fmode) +#else +/* CRTDLL */ +extern unsigned int* _fmode_dll; +#define _fmode (*_fmode_dll) +#endif +#endif /* 0 */ + +/* + * NOTE: This is the correct definition to build crtdll. + * It is NOT valid outside of crtdll. + */ +extern unsigned int* _fmode_dll; +extern unsigned int _fmode; + + +/* Specifiy one of these flags to define the access mode. */ +#define _O_RDONLY 0 +#define _O_WRONLY 1 +#define _O_RDWR 2 + +/* Mask for access mode bits in the _open flags. */ +#define _O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) + +#define _O_APPEND 0x0008 /* Writes will add to the end of the file. */ +#define _O_CREAT 0x0100 /* Create the file if it does not exist. */ +#define _O_TRUNC 0x0200 /* Truncate the file if it does exist. */ +#define _O_EXCL 0x0400 /* Open only if the file does not exist. */ + +/* NOTE: Text is the default even if the given _O_TEXT bit is not on. */ +#define _O_TEXT 0x4000 /* CR-LF in file becomes LF in memory. */ +#define _O_BINARY 0x8000 /* Input and output is not translated. */ +#define _O_RAW _O_BINARY + +#define _O_TEMPORARY 0x0040 /* Make the file dissappear after closing. + * WARNING: Even if not created by _open! */ + + +#define _O_RANDOM 0x0010 +#define _O_SEQUENTIAL _O_RANDOM +#define _O_SHORT_LIVED 0x1000 + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +/* POSIX/Non-ANSI names for increased portability */ +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_RDWR _O_RDWR +#define O_ACCMODE _O_ACCMODE +#define O_APPEND _O_APPEND +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC +#define O_EXCL _O_EXCL +#define O_TEXT _O_TEXT +#define O_BINARY _O_BINARY +#define O_TEMPORARY _O_TEMPORARY + +#define O_RANDOM _O_RANDOM +#define O_SEQUENTIAL _O_RANDOM +#define O_SHORT_LIVED _O_SHORT_LIVED + +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +extern "C" { +#endif + +int _setmode (int nHandle, int nAccessMode); + +#ifndef _NO_OLDNAMES +int setmode (int nHandle, int nAccessMode); +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not __STRICT_ANSI__ */ +#endif /* Not _FCNTL_H_ */ diff --git a/include/crtdll/float.h b/include/crtdll/float.h new file mode 100644 index 0000000..87f8b1c --- /dev/null +++ b/include/crtdll/float.h @@ -0,0 +1,199 @@ +/* + * float.h + * + * Constants related to floating point arithmetic. + * + * Also included here are some non-ANSI bits for accessing the floating + * point controller. + * + * NOTE: GCC provides float.h, and it is probably more accurate than this, + * but it doesn't include the non-standard stuff for accessing the + * fp controller. (TODO: Move those bits elsewhere?) Thus it is + * probably not a good idea to use the GCC supplied version instead + * of this header. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _FLOAT_H_ +#define _FLOAT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define FLT_ROUNDS 1 +#define FLT_GUARD 1 +#define FLT_NORMALIZE 1 + +/* + * The characteristics of float. + */ + +/* The radix for floating point representation. */ +#define FLT_RADIX 2 + +/* Decimal digits of precision. */ +#define FLT_DIG 6 + +/* Smallest number such that 1+x != 1 */ +#define FLT_EPSILON 1.19209290e-07F + +/* The number of base FLT_RADIX digits in the mantissa. */ +#define FLT_MANT_DIG 24 + +/* The maximum floating point number. */ +#define FLT_MAX 3.40282347e+38F + +/* Maximum n such that FLT_RADIX^n - 1 is representable. */ +#define FLT_MAX_EXP 128 + +/* Maximum n such that 10^n is representable. */ +#define FLT_MAX_10_EXP 38 + +/* Minimum normalized floating-point number. */ +#define FLT_MIN 1.17549435e-38F + +/* Minimum n such that FLT_RADIX^n is a normalized number. */ +#define FLT_MIN_EXP (-125) + +/* Minimum n such that 10^n is a normalized number. */ +#define FLT_MIN_10_EXP (-37) + + +/* + * The characteristics of double. + */ +#define DBL_DIG 15 +#define DBL_EPSILON 1.1102230246251568e-16 +#define DBL_MANT_DIG 53 +#define DBL_MAX 1.7976931348623157e+308 +#define DBL_MAX_EXP 1024 +#define DBL_MAX_10_EXP 308 +#define DBL_MIN 2.2250738585072014e-308 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN_10_EXP (-307) + + +/* + * The characteristics of long double. + * NOTE: long double is the same as double. + */ +#define LDBL_DIG 15 +#define LDBL_EPSILON 1.1102230246251568e-16L +#define LDBL_MANT_DIG 53 +#define LDBL_MAX 1.7976931348623157e+308L +#define LDBL_MAX_EXP 1024 +#define LDBL_MAX_10_EXP 308 +#define LDBL_MIN 2.2250738585072014e-308L +#define LDBL_MIN_EXP (-1021) +#define LDBL_MIN_10_EXP (-307) + + +/* + * Functions and definitions for controlling the FPU. + */ +#ifndef __STRICT_ANSI__ + +/* TODO: These constants are only valid for x86 machines */ + +/* Control word masks for unMask */ +#define _MCW_EM 0x0008001F /* Error masks */ +#define _MCW_IC 0x00040000 /* Infinity */ +#define _MCW_RC 0x00000300 /* Rounding */ +#define _MCW_PC 0x00030000 /* Precision */ + +/* Control word values for unNew (use with related unMask above) */ +#define _EM_INVALID 0x00000010 +#define _EM_DENORMAL 0x00080000 +#define _EM_ZERODIVIDE 0x00000008 +#define _EM_OVERFLOW 0x00000004 +#define _EM_UNDERFLOW 0x00000002 +#define _EM_INEXACT 0x00000001 +#define _IC_AFFINE 0x00040000 +#define _IC_PROJECTIVE 0x00000000 +#define _RC_CHOP 0x00000300 +#define _RC_UP 0x00000200 +#define _RC_DOWN 0x00000100 +#define _RC_NEAR 0x00000000 +#define _PC_24 0x00020000 +#define _PC_53 0x00010000 +#define _PC_64 0x00000000 + + +/* Set the FPU control word as cw = (cw & ~unMask) | (unNew & unMask), + * i.e. change the bits in unMask to have the values they have in unNew, + * leaving other bits unchanged. */ +unsigned int _controlfp (unsigned int unNew, unsigned int unMask); +unsigned int _control87 (unsigned int unNew, unsigned int unMask); + + +unsigned int _clearfp (void); /* Clear the FPU status word */ +unsigned int _statusfp (void); /* Report the FPU status word */ +#define _clear87 _clearfp +#define _status87 _statusfp + +void _fpreset (void); /* Reset the FPU */ + +/* Global 'variable' for the current floating point error code. */ +int * __fpecode(void); +#define _fpecode (*(__fpecode())) + +/* + * IEEE recommended functions + */ + +double _chgsign (double x); +double _copysign (double dTo, double dFrom); +double _logb (double x); +double _nextafter (double x, double y); +double _scalb (double x, long n); + +/* Return values for fpclass. */ +#define _FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */ +#define _FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */ +#define _FPCLASS_NINF 0x0004 /* Negative Infinity */ +#define _FPCLASS_NN 0x0008 /* Negative Normal */ +#define _FPCLASS_ND 0x0010 /* Negative Denormal */ +#define _FPCLASS_NZ 0x0020 /* Negative Zero */ +#define _FPCLASS_PZ 0x0040 /* Positive Zero */ +#define _FPCLASS_PD 0x0080 /* Positive Denormal */ +#define _FPCLASS_PN 0x0100 /* Positive Normal */ +#define _FPCLASS_PINF 0x0200 /* Positive Infinity */ + +int _finite (double x); +int _fpclass (double x); +int _isnan (double x); +int _isinf (double x); // not exported + +int _isnanl (long double x); // not exported +int _isinfl (long double x); // not exported + +#define isnan(x) _isnan(x) +#define isinf(x) _isinf(x) + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _FLOAT_H_ */ diff --git a/include/crtdll/internal/atexit.h b/include/crtdll/internal/atexit.h new file mode 100644 index 0000000..b3a9f01 --- /dev/null +++ b/include/crtdll/internal/atexit.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_atexit_h__ +#define __dj_include_libc_dosexec_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +struct __atexit { + struct __atexit *__next; + void (*__function)(void); +}; + +extern struct __atexit *__atexit_ptr; + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_dosexec_h__ */ diff --git a/include/crtdll/internal/file.h b/include/crtdll/internal/file.h new file mode 100644 index 0000000..b058381 --- /dev/null +++ b/include/crtdll/internal/file.h @@ -0,0 +1,93 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#ifndef __dj_include_libc_file_h__ +#define __dj_include_libc_file_h__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +#ifndef _IORMONCL +#define _IORMONCL 004000 /* remove on close, for temp files */ +#endif +/* if _flag & _IORMONCL, ._name_to_remove needs freeing */ + +#ifndef _IOUNGETC +#define _IOUNGETC 010000 /* there is an ungetc'ed character in the buffer */ +#endif + + +// might need check for IO_APPEND aswell +#define OPEN4WRITING(f) ((((f)->_flag & _IOWRT) == _IOWRT ) ) + +#define OPEN4READING(f) ((((f)->_flag & _IOREAD) == _IOREAD ) ) + +// might need check for IO_APPEND aswell +#define WRITE_STREAM(f) ((((f)->_flag & _IOWRT) == _IOWRT ) ) + +#define READ_STREAM(f) ((((f)->_flag & _IOREAD) == _IOREAD ) ) + + +char __validfp (FILE *f); + +int __set_errno(int err); +void *filehnd(int fn); + +char __is_text_file(FILE *p); + +int __fileno_alloc(void *hFile, int mode); + +int _doprnt(const char *fmt, va_list args, FILE *f); +int _doscan(FILE *iop, const char *fmt, va_list argp); + + +int __fileno_dup2( int handle1, int handle2 ); +int __fileno_setmode(int _fd, int _newmode); +int __fileno_close(int _fd); + +void sigabort_handler(int sig); + +#include + +void UnixTimeToFileTime( time_t unix_time, FILETIME *filetime, DWORD remainder ); +time_t FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ); + + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + + +#define __FILE_REC_MAX 20 +typedef struct __file_rec +{ + struct __file_rec *next; + int count; + FILE *files[__FILE_REC_MAX]; +} __file_rec; + +extern __file_rec *__file_rec_list; + + +#ifdef __cplusplus +} +#endif + + +#endif /* __dj_include_libc_file_h__ */ + + + diff --git a/include/crtdll/internal/ieee.h b/include/crtdll/internal/ieee.h new file mode 100644 index 0000000..788908b --- /dev/null +++ b/include/crtdll/internal/ieee.h @@ -0,0 +1,25 @@ +#ifndef _IEEE_H +#define _IEEE_H + +typedef struct { + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int sign:1; +} float_t; + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; +} double_t; + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:32; + unsigned int exponent:15; + unsigned int sign:1; + unsigned int empty:16; +} long_double_t; + +#endif diff --git a/include/crtdll/internal/quad.h b/include/crtdll/internal/quad.h new file mode 100644 index 0000000..339b6db --- /dev/null +++ b/include/crtdll/internal/quad.h @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)quad.h 8.1 (Berkeley) 6/4/93 + * $Id$ + */ + +/* + * Quad arithmetic. + * + * This library makes the following assumptions: + * + * - The type long long (aka quad_t) exists. + * + * - A quad variable is exactly twice as long as `long'. + * + * - The machine's arithmetic is two's complement. + * + * This library can provide 128-bit arithmetic on a machine with 128-bit + * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines + * with 48-bit longs. + */ +#include +//#include + + +typedef unsigned long long u_quad_t; /* quads */ +typedef long long quad_t; +typedef unsigned long u_long; + + + +/* + * Define the order of 32-bit words in 64-bit words. + */ +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 + +//#include +#include +#include + +/* + * Depending on the desired operation, we view a `long long' (aka quad_t) in + * one or more of the following formats. + */ +union uu { + quad_t q; /* as a (signed) quad */ + quad_t uq; /* as an unsigned quad */ + long sl[2]; /* as two signed longs */ + u_long ul[2]; /* as two unsigned longs */ +}; + +/* + * Define high and low longwords. + */ +#define H _QUAD_HIGHWORD +#define L _QUAD_LOWWORD + +/* + * Total number of bits in a quad_t and in the pieces that make it up. + * These are used for shifting, and also below for halfword extraction + * and assembly. + */ +#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT) +#define LONG_BITS (sizeof(long) * CHAR_BIT) +#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) + +/* + * Extract high and low shortwords from longword, and move low shortword of + * longword to upper half of long, i.e., produce the upper longword of + * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.) + * + * These are used in the multiply code, to split a longword into upper + * and lower halves, and to reassemble a product as a quad_t, shifted left + * (sizeof(long)*CHAR_BIT/2). + */ +#define HHALF(x) ((x) >> HALF_BITS) +#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1)) +#define LHUP(x) ((x) << HALF_BITS) + +quad_t __divdi3(quad_t a, quad_t b); +quad_t __moddi3(quad_t a, quad_t b); +u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem); +u_quad_t __udivdi3(u_quad_t a, u_quad_t b); +u_quad_t __umoddi3(u_quad_t a, u_quad_t b); + +/* + * XXX + * Compensate for gcc 1 vs gcc 2. Gcc 1 defines ?sh?di3's second argument + * as u_quad_t, while gcc 2 correctly uses int. Unfortunately, we still use + * both compilers. + */ +#if __GNUC__ >= 2 +typedef unsigned int qshift_t; +#else +typedef u_quad_t qshift_t; +#endif diff --git a/include/crtdll/io.h b/include/crtdll/io.h new file mode 100644 index 0000000..ab0a88f --- /dev/null +++ b/include/crtdll/io.h @@ -0,0 +1,140 @@ +/* + * io.h + * + * System level I/O functions and types. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* added D_OK */ +/* changed get_osfhandle and open_osfhandle */ +/* added fileno as macro */ +#ifndef _IO_H_ +#define _IO_H_ + +#ifndef __STRICT_ANSI__ + +#include + +#include + + +/* We need the definition of FILE anyway... */ +#include + +/* MSVC's io.h contains the stuff from dir.h, so I will too. + * NOTE: This also defines off_t, the file offset type, through + * and inclusion of sys/types.h */ +#include + +/* TODO: Maximum number of open handles has not been tested, I just set + * it the same as FOPEN_MAX. */ +#define HANDLE_MAX FOPEN_MAX + + +/* Some defines for _access nAccessMode (MS doesn't define them, but + * it doesn't seem to hurt to add them). */ +#define F_OK 0 /* Check for file existence */ +#define W_OK 2 /* Check for write permission */ +#define R_OK 4 /* Check for read permission */ +/* TODO: Is this safe? X_OK not supported directly... */ +#define X_OK R_OK /* Check for execute permission */ +#define D_OK 0x10 + + + +#ifdef __cplusplus +extern "C" { +#endif + +int _access (const char* szFileName, int nAccessMode); +int _chsize (int nHandle, long lnNewSize); +int _close (int nHandle); +int _commit(int _fd); +int _creat (const char* szFileName, int nAccessMode); +int _dup (int nHandle); +int _dup2 (int nOldHandle, int nNewHandle); +long _filelength (int nHandle); +int _fileno (FILE* fileGetHandle); +void* _get_osfhandle (int nHandle); +int _isatty (int nHandle); + +/* In a very odd turn of events this function is excluded from those + * files which define _STREAM_COMPAT. This is required in order to + * build GNU libio because of a conflict with _eof in streambuf.h + * line 107. Actually I might just be able to change the name of + * the enum member in streambuf.h... we'll see. TODO */ +#ifndef _STREAM_COMPAT +int _eof (int nHandle); +#endif + +/* LK_... locking commands defined in sys/locking.h. */ +int _locking (int nHandle, int nCmd, long lnLockRegionLength); + +off_t _lseek(int _fd, off_t _offset, int _whence); +int _open (const char* szFileName, int nFlags, ...); +int _open_osfhandle (void *lnOSHandle, int nFlags); +int _pipe (int *naHandles, unsigned int unSize, int nMode); +size_t _read(int _fd, void *_buf, size_t _nbyte); + +/* SH_... flags for nFlag defined in share.h */ +int _sopen (char* szFileName, int nAccess, int nFlag, int nMode); + +long _tell (int nHandle); +unsigned _umask (unsigned unMode); +int _unlink (const char* szFileName); +size_t _write(int _fd, const void *_buf, size_t _nbyte); + +#ifndef _NO_OLDNAMES +/* + * Non-underscored versions of non-ANSI functions to improve portability. + * These functions live in libmoldname.a. + */ + +#define access _access +#define chsize _chsize +#define close _close +#define creat _creat +#define dup _dup +#define dup2 _dup2 +#define eof _eof +#define filelength _filelength +#define fileno(f) ((f)->_file) +#define isatty _isatty +#define lseek _lseek +#define open _open +#define read _read +#define sopen(path,access,shflag,mode) _open((path), (access)|(shflag), (mode)) +#define tell(file) _lseek(_file, 0, SEEK_CUR) +#define umask _umask +#define unlink _unlink +#define write _write + + +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not strict ANSI */ + +#endif /* _IO_H_ not defined */ diff --git a/include/crtdll/locale.h b/include/crtdll/locale.h new file mode 100644 index 0000000..8a6e7d4 --- /dev/null +++ b/include/crtdll/locale.h @@ -0,0 +1,84 @@ +/* + * locale.h + * + * Functions and types for localization (ie. changing the appearance of + * output based on the standards of a certain country). + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _LOCALE_H_ +#define _LOCALE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NOTE: I have tried to test this, but I am limited by my knowledge of + * locale issues. The structure does not bomb if you look at the + * values, and 'decimal_point' even seems to be correct. But the + * rest of the values are, by default, not particularly useful + * (read meaningless and not related to the international settings + * of the system). + */ + +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 + +/* + * The structure returned by 'localeconv'. + */ +struct lconv +{ + char* decimal_point; + char* thousands_sep; + char* grouping; + char* int_curr_symbol; + char* currency_symbol; + char* mon_decimal_point; + char* mon_thousands_sep; + char* mon_grouping; + char* positive_sign; + char* negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; +}; + +char* setlocale (int nCategory, const char* locale); +struct lconv* localeconv (void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/crtdll/malloc.h b/include/crtdll/malloc.h new file mode 100644 index 0000000..1535929 --- /dev/null +++ b/include/crtdll/malloc.h @@ -0,0 +1,53 @@ +/* + * malloc.h + * + * Support for programs which want to use malloc.h to get memory management + * functions. Unless you absolutely need some of these functions and they are + * not in the ANSI headers you should use the ANSI standard header files + * instead. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _MALLOC_H_ +#define _MALLOC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void * _expand( void *memblock, size_t size ); +int _heapchk (void); /* Verify heap integrety. */ +int _heapmin (void); /* Return unused heap to the OS. */ +int _heapset (unsigned int unFill); +size_t _msize (void* pBlock); + +#ifdef __cplusplus +} +#endif + +#endif /* Not _MALLOC_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/math.h b/include/crtdll/math.h new file mode 100644 index 0000000..9afe1df --- /dev/null +++ b/include/crtdll/math.h @@ -0,0 +1,161 @@ +/* + * math.h + * + * Mathematical functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +// added modfl + +#ifndef _MATH_H_ +#define _MATH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * HUGE_VAL is returned by strtod when the value would overflow the + * representation of 'double'. There are other uses as well. + * + * __imp__HUGE is a pointer to the actual variable _HUGE in + * MSVCRT.DLL. If we used _HUGE directly we would get a pointer + * to a thunk function. + * + * NOTE: The CRTDLL version uses _HUGE_dll instead. + */ +#if __MSVCRT__ +extern double* __imp__HUGE; +#define HUGE_VAL (*__imp__HUGE) +#else +/* CRTDLL */ +extern double* _HUGE_dll; +#define HUGE_VAL (*_HUGE_dll) +#endif + + +struct _exception +{ + int type; + char *name; + double arg1; + double arg2; + double retval; +}; + +/* + * Types for the above _exception structure. + */ + +#define _DOMAIN 1 /* domain error in argument */ +#define _SING 2 /* singularity */ +#define _OVERFLOW 3 /* range overflow */ +#define _UNDERFLOW 4 /* range underflow */ +#define _TLOSS 5 /* total loss of precision */ +#define _PLOSS 6 /* partial loss of precision */ + +/* + * Exception types with non-ANSI names for compatibility. + */ + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +#define DOMAIN _DOMAIN +#define SING _SING +#define OVERFLOW _OVERFLOW +#define UNDERFLOW _UNDERFLOW +#define TLOSS _TLOSS +#define PLOSS _PLOSS + +#endif /* Not _NO_OLDNAMES */ +#endif /* Not __STRICT_ANSI__ */ + + +double sin (double x); +double cos (double x); +double tan (double x); +double sinh (double x); +double cosh (double x); +double tanh (double x); +double asin (double x); +double acos (double x); +double atan (double x); +double atan2 (double y, double x); +double exp (double x); +double log (double x); +double log10 (double x); +double pow (double x, double y); +long double powl (long double x,long double y); +double sqrt (double x); +double ceil (double x); +double floor (double x); +double fabs (double x); +double ldexp (double x, int n); +double frexp (double x, int* exp); +double modf (double x, double* ip); +long double modfl (long double x,long double* ip); +double fmod (double x, double y); + + +#ifndef __STRICT_ANSI__ + +/* Complex number (for cabs) */ +struct _complex +{ + double x; /* Real part */ + double y; /* Imaginary part */ +}; + +double _cabs (struct _complex x); +double _hypot (double x, double y); +double _j0 (double x); +double _j1 (double x); +double _jn (int n, double x); +double _y0 (double x); +double _y1 (double x); +double _yn (int n, double x); + +#ifndef _NO_OLDNAMES + +/* + * Non-underscored versions of non-ANSI functions. These reside in + * liboldnames.a. Provided for extra portability. + */ +double cabs (struct _complex x); +double hypot (double x, double y); +double j0 (double x); +double j1 (double x); +double jn (int n, double x); +double y0 (double x); +double y1 (double x); +double yn (int n, double x); + +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not _MATH_H_ */ + diff --git a/include/crtdll/mbctype.h b/include/crtdll/mbctype.h new file mode 100644 index 0000000..dc34d13 --- /dev/null +++ b/include/crtdll/mbctype.h @@ -0,0 +1,47 @@ +#ifndef _MBCTYPE_H +#define _MBCTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#define _MS 0x01 +//#define _MP 0x02 +//#define _M1 0x04 +//#define _M2 0x08 + +#define _MBC_SINGLE 0 +#define _MBC_LEAD 1 +#define _MBC_TRAIL 2 +#define _MBC_ILLEGAL -1 + +#define _MB_CP_SBCS 0 +#define _MB_CP_OEM -2 +#define _MB_CP_ANSI -3 +#define _MB_CP_LOCALE -4 + +#define _KNJ_M ((char)0x01) /* Non-punctuation of Kana-set */ +#define _KNJ_P ((char)0x02) /* Punctuation of Kana-set */ +#define _KNJ_1 ((char)0x04) /* Legal 1st byte of double byte stream */ +#define _KNJ_2 ((char)0x08) /* Legal 2nd btye of double byte stream */ + + +#define ___ 0 +#define _1_ _KNJ_1 /* Legal 1st byte of double byte code */ +#define __2 _KNJ_2 /* Legal 2nd byte of double byte code */ +#define _M_ _KNJ_M /* Non-puntuation in Kana-set */ +#define _P_ _KNJ_P /* Punctuation of Kana-set */ +#define _12 (_1_|__2) +#define _M2 (_M_|__2) +#define _P2 (_P_|__2) + +extern char _jctype[257]; + +int _ismbbkana( unsigned char c ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crtdll/mbstring.h b/include/crtdll/mbstring.h new file mode 100644 index 0000000..c0dd474 --- /dev/null +++ b/include/crtdll/mbstring.h @@ -0,0 +1,108 @@ +#ifndef _MBSTRING_H_ +#define _MBSTRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +size_t _mbstrlen(const char *str); + + + + +int _mbbtype(unsigned char c, int type); +int _mbsbtype( const unsigned char *str, size_t n ); + +unsigned int _mbbtombc(unsigned int c); +unsigned int _mbctombb(unsigned int c); + +unsigned char * _mbscat(unsigned char *dst, const unsigned char *src); +unsigned char * _mbschr(unsigned char *str, unsigned char* c); +int _mbscmp(const unsigned char *, const unsigned char *); +int _mbscoll(const unsigned char *, const unsigned char *); +unsigned char * _mbscpy(unsigned char *, const unsigned char *); +size_t _mbscspn(const unsigned char *, const unsigned char *); +unsigned char * _mbsdup(const unsigned char *str); +int _mbsicmp(const unsigned char *, const unsigned char *); +int _mbsicoll(const unsigned char *, const unsigned char *); +size_t _mbslen(const unsigned char *str); + +unsigned char * _mbsncat(unsigned char *, const unsigned char *, size_t); +unsigned char * _mbsnbcat(unsigned char *, const unsigned char *, size_t); + + +int _mbsncmp(const unsigned char *, const unsigned char *, size_t); +int _mbsnbcmp(const unsigned char *, const unsigned char *, size_t); + +int _mbsncoll(const unsigned char *, const unsigned char *, size_t); +int _mbsnbcoll(const unsigned char *, const unsigned char *, size_t); + + +unsigned char * _mbsncpy(unsigned char *, const unsigned char *, size_t); +unsigned char * _mbsnbcpy(unsigned char *, const unsigned char *, size_t); + +int _mbsnicmp(const unsigned char *, const unsigned char *, size_t); +int _mbsnbicmp(const unsigned char *, const unsigned char *, size_t); + +int _mbsnicoll(const unsigned char *, const unsigned char *, size_t); +int _mbsnbicoll(const unsigned char *, const unsigned char *, size_t); + +unsigned char * _mbsnset(unsigned char *, unsigned int, size_t); +unsigned char * _mbsnbset(unsigned char *, unsigned int, size_t); + +size_t _mbsnccnt(const unsigned char *, size_t); + + +unsigned char * _mbspbrk(const unsigned char *, const unsigned char *); +unsigned char * _mbsrchr(const unsigned char *, unsigned int); +unsigned char * _mbsrev(unsigned char *); +unsigned char * _mbsset(unsigned char *, unsigned int); +size_t _mbsspn(const unsigned char *, const unsigned char *); + +unsigned char * _mbsstr(const unsigned char *, const unsigned char *); +unsigned char * _mbstok(unsigned char *, unsigned char *); + +unsigned char * _mbslwr(unsigned char *str); +unsigned char * _mbsupr(unsigned char *str); + +size_t _mbclen(const unsigned char *); +void _mbccpy(unsigned char *, const unsigned char *); + +/* tchar routines */ + +unsigned char * _mbsdec(const unsigned char *, const unsigned char *); +unsigned char * _mbsinc(const unsigned char *); +size_t _mbsnbcnt(const unsigned char *, size_t); +unsigned int _mbsnextc (const unsigned char *); +unsigned char * _mbsninc(const unsigned char *, size_t); +unsigned char * _mbsspnp(const unsigned char *, const unsigned char *); + +/* character routines */ + +int _ismbcalnum(unsigned int c); +int _ismbcalpha(unsigned int c); +int _ismbcdigit(unsigned int c); +int _ismbcgraph(unsigned int c); +int _ismbclegal(unsigned int c); +int _ismbclower(unsigned int c); +int _ismbcprint(unsigned int c); +int _ismbcpunct(unsigned int c); +int _ismbcspace(unsigned int c); +int _ismbcupper(unsigned int c); + +unsigned int _mbctolower(unsigned int); +unsigned int _mbctoupper(unsigned int); + + +int _ismbblead( unsigned int c); +int _ismbbtrail( unsigned int c); +int _ismbslead( const unsigned char *s, const unsigned char *c); +int _ismbstrail( const unsigned char *s, const unsigned char *c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crtdll/process.h b/include/crtdll/process.h new file mode 100644 index 0000000..56f649b --- /dev/null +++ b/include/crtdll/process.h @@ -0,0 +1,160 @@ +/* + * process.h + * + * Function calls for spawning child processes. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* changed second argument of cwait from nPID to hProc */ + +#ifndef _PROCESS_H_ +#define _PROCESS_H_ + +#ifndef __STRICT_ANSI__ + +#ifdef __cplusplus +extern "C" { +#endif + +void _cexit(void); +void _c_exit(void); + +/* + * Constants for cwait actions. + * Obsolete for Win32. + */ +#define _WAIT_CHILD 0 +#define _WAIT_GRANDCHILD 1 + +#ifndef _NO_OLDNAMES +#define WAIT_CHILD _WAIT_CHILD +#define WAIT_GRANDCHILD _WAIT_GRANDCHILD +#endif /* Not _NO_OLDNAMES */ + +int _cwait (int* pnStatus, int hProc, int nAction); + +int _getpid(void); + +int _execl (const char* szPath, const char* szArgv0, ...); +int _execle (const char* szPath, const char* szArgv0, ...); +int _execlp (const char* szPath, const char* szArgv0, ...); +int _execlpe (const char* szPath, const char* szArgv0, ...); +int _execv (const char* szPath, char* const* szaArgv); +int _execve (const char* szPath, char* const* szaArgv, char* const* szaEnv); +int _execvp (const char* szPath, char* const* szaArgv); +int _execvpe (const char* szPath, char* const* szaArgv, char* const* szaEnv); + + +/* + * Mode constants for spawn functions. + */ +#define _P_WAIT 0 +#define _P_NOWAIT 1 +#define _P_OVERLAY 2 +#define _OLD_P_OVERLAY _P_OVERLAY +#define _P_NOWAITO 3 +#define _P_DETACH 4 + +#ifndef _NO_OLDNAMES +#define P_WAIT _P_WAIT +#define P_NOWAIT _P_NOWAIT +#define P_OVERLAY _P_OVERLAY +#define OLD_P_OVERLAY _OLD_P_OVERLAY +#define P_NOWAITO _P_NOWAITO +#define P_DETACH _P_DETACH +#endif /* Not _NO_OLDNAMES */ + +int _spawnl (int nMode, const char* szPath, const char* szArgv0, ...); +int _spawnle (int nMode, const char* szPath, const char* szArgv0,...); +int _spawnlp (int nMode, const char* szPath, const char* szArgv0,...); +int _spawnlpe (int nMode, const char* szPath, const char* szArgv0,...); +int _spawnv (int nMode, const char* szPath, char* const* szaArgv); +int _spawnve (int nMode, const char* szPath, char* const* szaArgv, char* const* szaEnv); +int _spawnvp (int nMode, const char* szPath, char* const* szaArgv); +int _spawnvpe (int nMode, const char* szPath, char* const* szaArgv, char* const* szaEnv); +/* + * The functions _beginthreadex and _endthreadex are not provided by CRTDLL. + * They are provided by MSVCRT. + * + * NOTE: Apparently _endthread calls CloseHandle on the handle of the thread, + * making for race conditions if you are not careful. Basically you have to + * make sure that no-one is going to do *anything* with the thread handle + * after the thread calls _endthread or returns from the thread function. + * + * NOTE: No old names for these functions. Use the underscore. + */ +unsigned long + _beginthread (void (*pfuncStart)(void *), + unsigned unStackSize, void* pArgList); +void _endthread (void); + +#if __MSVCRT__ +unsigned long + _beginthreadex (void *pSecurity, unsigned unStackSize, + unsigned (*pfuncStart)(void*), void* pArgList, + unsigned unInitFlags, unsigned* pThreadAddr); +void _endthreadex (unsigned unExitCode); +#endif + + +void *_loaddll (char *name); +int _unloaddll(void *handle); + +unsigned long __threadid(void); +#define _threadid __threadid() +void * __threadhandle(void); + + +#ifndef _NO_OLDNAMES + +#define cwait _cwait +#define getpid _getpid +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execlpe _execlpe + +#define execv _execv +#define execve _execve +#define execvp _execvp +#define execvpe _execvpe + +#define spawnl _spawnl +#define spawnle _spawnle +#define spawnlp _spawnlp +#define spawnlpe _spawnlpe + +#define spawnv _spawnv +#define spawnve _spawnve +#define spawnvp _spawnvp +#define spawnvpe _spawnvpe + + +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not __STRICT_ANSI__ */ + +#endif /* _PROCESS_H_ not defined */ diff --git a/include/crtdll/search.h b/include/crtdll/search.h new file mode 100644 index 0000000..c8242c6 --- /dev/null +++ b/include/crtdll/search.h @@ -0,0 +1,35 @@ + +#ifndef _SEARCH_H_ +#define _SEARCH_H_ + +//char *key +//void *data + +//enum { FIND, ENTER } ACTION; +//enum { preorder, postorder, endorder, leaf } VISIT; + +#include +#include + + +//The Single UNIX ® Specification, Version 2 Copyright © 1997 The Open Group + +//int hcreate(size_t); +//void hdestroy(void); +//ENTRY *hsearch(ENTRY, ACTION); +//void insque(void *, void *); +void *_lfind(const void *, const void *, size_t *, + size_t, int (*)(const void *, const void *)); +void *_lsearch(const void *, void *, size_t *, + size_t, int (*)(const void *, const void *)); +//void remque(void *); +//void *tdelete(const void *, void **, +// int(*)(const void *, const void *)); +//void *tfind(const void *, void *const *, +// int(*)(const void *, const void *)); +//void *tsearch(const void *, void **, +// int(*)(const void *, const void *)); +//void twalk(const void *, +// void (*)(const void *, VISIT, int )); + +#endif diff --git a/include/crtdll/setjmp.h b/include/crtdll/setjmp.h new file mode 100644 index 0000000..60335dd --- /dev/null +++ b/include/crtdll/setjmp.h @@ -0,0 +1,46 @@ +/* +** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 +** +** This file is distributed under the terms listed in the document +** "copying.dj", available from DJ Delorie at the address above. +** A copy of "copying.dj" should accompany this file; if not, a copy +** should be available from where this file was obtained. This file +** may not be distributed without a verbatim copy of "copying.dj". +** +** This file is distributed WITHOUT ANY WARRANTY; without even the implied +** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned long eax; + unsigned long ebx; + unsigned long ecx; + unsigned long edx; + unsigned long esi; + unsigned long edi; + unsigned long ebp; + unsigned long esp; + unsigned long eip; + unsigned short es; + unsigned short fs; + unsigned short gs; + unsigned short ss; +} jmp_buf[1]; + +extern int _setjmp(jmp_buf); +extern void longjmp(jmp_buf, int); + +#define setjmp(jmp_buf) _setjmp(jmp_buf) + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/include/crtdll/share.h b/include/crtdll/share.h new file mode 100644 index 0000000..8e3af3f --- /dev/null +++ b/include/crtdll/share.h @@ -0,0 +1,17 @@ +#ifndef _include_share_h_ +#define _include_share_h_ + + +#define SH_COMPAT 0x0000 +#define SH_DENYRW 0x0010 +#define SH_DENYWR 0x0020 +#define SH_DENYRD 0x0030 +#define SH_DENYNO 0x0040 + +#define _SH_COMPAT SH_COMPAT +#define _SH_DENYRW SH_DENYRW +#define _SH_DENYWR SH_DENYWR +#define _SH_DENYRD SH_DENYRD +#define _SH_DENYNO SH_DENYNO + +#endif diff --git a/include/crtdll/signal.h b/include/crtdll/signal.h new file mode 100644 index 0000000..05b2aac --- /dev/null +++ b/include/crtdll/signal.h @@ -0,0 +1,111 @@ +/* + * signal.h + * + * A way to set handlers for exceptional conditions (also known as signals). + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* added some extra signal constants */ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The prototypes (below) are the easy part. The hard part is figuring + * out what signals are available and what numbers they are assigned + * along with appropriate values of SIG_DFL and SIG_IGN. + */ + +/* + * A pointer to a signal handler function. A signal handler takes a + * single int, which is the signal it handles. + */ +typedef void (*_p_sig_fn_t)(int nSig); + +/* + * These are special values of signal handler pointers which are + * used to send a signal to the default handler (SIG_DFL), ignore + * the signal (SIG_IGN), or indicate an error return (SIG_ERR). + */ +#define SIG_DFL ((_p_sig_fn_t) 0) +#define SIG_IGN ((_p_sig_fn_t) 1) +#define SIG_ERR ((_p_sig_fn_t) -1) + +/* + * The actual signal values. Using other values with signal + * produces a SIG_ERR return value. + * + * NOTE: SIGINT is produced when the user presses Ctrl-C. + * SIGILL has not been tested. + * SIGFPE doesn't seem to work? + * SIGSEGV does not catch writing to a NULL pointer (that shuts down + * your app; can you say "segmentation violation core dump"?). + * SIGTERM comes from what kind of termination request exactly? + * SIGBREAK is indeed produced by pressing Ctrl-Break. + * SIGABRT is produced by calling abort. + * TODO: The above results may be related to not installing an appropriate + * structured exception handling frame. Results may be better if I ever + * manage to get the SEH stuff down. + */ +#define SIGINT 2 /* Interactive attention */ +#define SIGILL 4 /* Illegal instruction */ +#define SIGFPE 8 /* Floating point error */ +#define SIGSEGV 11 /* Segmentation violation */ +#define SIGTERM 15 /* Termination request */ +#define SIGBREAK 21 /* Control-break */ +#define SIGABRT 22 /* Abnormal termination (abort) */ + +#define SIGALRM 293 +#define SIGHUP 294 +/* SIGINT is ansi */ +#define SIGKILL 296 +#define SIGPIPE 297 +#define SIGQUIT 298 +#define SIGUSR1 299 +#define SIGUSR2 300 + +#define SIGNOFP 301 +#define SIGTRAP 302 +#define SIGTIMR 303 /* Internal for setitimer (SIGALRM, SIGPROF) */ +#define SIGPROF 304 +#define SIGMAX 320 + +/* + * Call signal to set the signal handler for signal sig to the + * function pointed to by handler. Returns a pointer to the + * previous handler, or SIG_ERR if an error occurs. Initially + * unhandled signals defined above will return SIG_DFL. + */ +_p_sig_fn_t signal(int sig, _p_sig_fn_t func); + +/* + * Raise the signal indicated by sig. Returns non-zero on success. + */ +int raise (int sig); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crtdll/stdarg.h b/include/crtdll/stdarg.h new file mode 100644 index 0000000..82656c6 --- /dev/null +++ b/include/crtdll/stdarg.h @@ -0,0 +1,107 @@ +/* + * stdarg.h + * + * Provides facilities for stepping through a list of function arguments of + * an unknown number and type. + * + * NOTE: Gcc should provide stdarg.h, and I believe their version will work + * with crtdll. If necessary I think you can replace this with the GCC + * stdarg.h (or is it vararg.h). + * + * Note that the type used in va_arg is supposed to match the actual type + * *after default promotions*. Thus, va_arg (..., short) is not valid. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +/* + * Don't do any of this stuff for the resource compiler. + */ +#ifndef RC_INVOKED + +/* + * I was told that Win NT likes this. + */ +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif + +#ifndef _VA_LIST +#define _VA_LIST +typedef char* va_list; +#endif + + +/* + * Amount of space required in an argument list (ie. the stack) for an + * argument of type t. + */ +#define __va_argsiz(t) \ + (((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int)) + + +/* + * Start variable argument list processing by setting AP to point to the + * argument after pN. + */ +#ifdef __GNUC__ +/* + * In GNU the stack is not necessarily arranged very neatly in order to + * pack shorts and such into a smaller argument list. Fortunately a + * neatly arranged version is available through the use of __builtin_next_arg. + */ +#define va_start(ap, pN) \ + ((ap) = ((va_list) __builtin_next_arg(pN))) +#else +/* + * For a simple minded compiler this should work (it works in GNU too for + * vararg lists that don't follow shorts and such). + */ +#define va_start(ap, pN) \ + ((ap) = ((va_list) (&pN) + __va_argsiz(pN))) +#endif + + +/* + * End processing of variable argument list. In this case we do nothing. + */ +#define va_end(ap) ((void)0) + + +/* + * Increment ap to the next argument in the list while returing a + * pointer to what ap pointed to first, which is of type t. + * + * We cast to void* and then to t* because this avoids a warning about + * increasing the alignment requirement. + */ + +#define va_arg(ap, t) \ + (((ap) = (ap) + __va_argsiz(t)), \ + *((t*) (void*) ((ap) - __va_argsiz(t)))) + +#endif /* Not RC_INVOKED */ + +#endif /* not _STDARG_H_ */ diff --git a/include/crtdll/stddef.h b/include/crtdll/stddef.h new file mode 100644 index 0000000..6a614b7 --- /dev/null +++ b/include/crtdll/stddef.h @@ -0,0 +1,173 @@ +/* + * stddef.h + * + * Standard type definitions provided by the C library. + * + * NOTE: Actually supplied by the compiler (correct?). As such, GCC + * supplies a version of this header file. Unfortunately, GCC's + * version is all tied up with the way other headers for the + * GNU C library are implemented (or vice-versa), in a similar + * way to how the other Mingw32 headers are dependent on + * certain internals of this file. It is not clear to me whether + * you can safely use the GCC version in place of this version. + * TODO: Line up usage in other header files to work with GCC + * stddef.h. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + + +#ifndef __CRTDLL_STDDEF_H_ + +/* + * Any one of these symbols __need_* means that a standard header file + * wants us just to define one data type. So don't define + * the symbols that indicate this file's entire job has been done. + */ +#if (!defined(__need_wchar_t) && !defined(__need_wint_t) \ + && !defined(__need_size_t) && !defined(__need_ptrdiff_t) \ + && !defined(__need_NULL)) +#define __CRTDLL_STDDEF_H_ +#endif + +/* + * NOTE: The following typedefs are done using __xxx_TYPE__ defines followed + * by typedefs using those defines. I have chosen to do it this way because + * GCC supplies definitions for __xxx_TYPE__ macros and if, for example, your + * size_t is typedef'ed differently from what GCC expects it will give you + * warnings when you prototype functions like memcmp and memcpy. The values + * for __xxx_TYPE__ in this header file are the same as those given by GCC. + * Those values appear to work with the CRTDLL functions. + */ + +/* + * Signed type of difference of two pointers. + */ + +/* Define this type if we are doing the whole job, or if we want this type + * in particular. */ +#if defined (__CRTDLL_STDDEF_H_) || defined (__need_ptrdiff_t) + +#ifndef _PTRDIFF_T_ +#define _PTRDIFF_T_ +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ int +#endif +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#endif + +/* If this symbol has done its job, get rid of it. */ +#undef __need_ptrdiff_t + +#endif /* __CRTDLL_STDDEF_H_ or __need_ptrdiff_t. */ + +/* + * Unsigned type of `sizeof' something. + */ + + +/* Define this type if we are doing the whole job, + * or if we want this type in particular. */ +#if defined (__CRTDLL_STDDEF_H_) || defined (__need_size_t) + +#ifndef _SIZE_T_ +#define _SIZE_T_ +#define SIZE_T_DEFINED +#define _SIZE_T +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ unsigned int +#endif +typedef __SIZE_TYPE__ size_t; +#endif + +#undef __need_size_t + +#endif /* __CRTDLL_STDDEF_H_ or __need_size_t. */ + +/* Wide character type. + Locale-writers should change this as necessary to + be big enough to hold unique values not between 0 and 127, + and not (wchar_t) -1, for each defined multibyte character. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (__CRTDLL_STDDEF_H_) || defined (__need_wchar_t) + +#ifndef _WCHAR_T_ +#define _WCHAR_T_ +#define _WCHAR_T +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ short unsigned int +#endif +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif /* C++ */ +#endif /* wchar_t not already defined */ + +#undef __need_wchar_t + +#endif /* __CRTDLL_STDDEF_H_ or __need_wchar_t. */ + +/* + * wint_t, the equivalent of int in wchar ctype functions. + */ +#if defined (__CRTDLL_STDDEF_H_) || defined (__need_wint_t) + +#ifndef _WINT_T_ +#define _WINT_T_ +#define _WINT_T /* To satisfy libstdc++ */ +#ifndef __WINT_TYPE__ +#define __WINT_TYPE__ short int +#endif /* Not defined __WINT_TYPE__ */ + +typedef __WINT_TYPE__ wint_t; +#endif /* Not defined _WINT_T_ */ + +#undef __need_wint_t + +#endif /* __CRTDLL_STDDEF_H_ or __need_wint_t. */ + + +/* + * A null pointer constant. + */ + +#if defined (__CRTDLL_STDDEF_H_) || defined (__need_NULL) + +#undef NULL +#define NULL (0) +#endif /* __CRTDLL_STDDEF_H_ or __need_NULL */ + +#undef __need_NULL + + +/* + * Offsetof, a macro for finding the offset of a member in a structure. + * Works by returning the 'address' of the MEMBER of a TYPE struct at address + * zero. + */ + +#if defined (__CRTDLL_STDDEF_H_) +#define offsetof(TYPE, MEMBER) ((size_t) &( ((TYPE *) 0)->MEMBER )) +#endif /* __CRTDLL_STDDEF_H_ */ + + +#endif /* not __CRTDLL__CRTDLL_STDDEF_H_ */ diff --git a/include/crtdll/stdio.h b/include/crtdll/stdio.h new file mode 100644 index 0000000..acdc2e4 --- /dev/null +++ b/include/crtdll/stdio.h @@ -0,0 +1,357 @@ +/* + * stdio.h + * + * Definitions of types and prototypes of functions for standard input and + * output. + * + * NOTE: The file manipulation functions provided by Microsoft seem to + * work with either slash (/) or backslash (\) as the path separator. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* implemented clearerr feof ferror perror as macros */ +/* added _IOCOMMIT */ +/* added filbuf and flsbuf and fwalk */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define __need_size_t +#define __need_NULL +#define __need_wchar_t +#define __need_wint_t +#include + + +/* Some flags for the iobuf structure provided by djgpp stdio.h */ +#define _IOREAD 0x000010 +#define _IOWRT 0x000020 +#define _IOMYBUF 0x000040 +#define _IOEOF 0x000100 +#define _IOERR 0x000200 +#define _IOSTRG 0x000400 + +#define _IOAPPEND 0x002000 +#define _IORMONCL 0x004000 /* remove on close, for temp files */ +/* if _flag & _IORMONCL, ._name_to_remove needs freeing */ +#define _IOUNGETC 0x010000 /* there is an ungetc'ed character in the buffer */ +#define _IOCOMMIT 0x008000 + +#define _IODIRTY 0x000080 +#define _IOAHEAD 0x000008 +#define _IORW (_IOREAD | _IOWRITE ) + + +/* + * I used to include stdarg.h at this point, in order to allow for the + * functions later on in the file which use va_list. That conflicts with + * using stdio.h and varargs.h in the same file, so I do the typedef myself. + */ +//#ifndef _VA_LIST +//#define _VA_LIST +//typedef char* va_list; +//#endif +#include + +/* + * FILE should be used as a pointer to an opaque data type. Do not rely on + * anything else, especially the size or contents of this structure! + */ +#ifndef _FILE_DEFINED +typedef struct { + char *_ptr; + int _cnt; + char *_base; + int _flag; + int _file; + int _ungotchar; + int _bufsiz; + char *_name_to_remove; +} FILE; +#define _FILE_DEFINED +#endif + +//#define _fillsize _bufsiz + +/* + * The three standard file pointers provided by the run time library. + * NOTE: These will go to the bit-bucket silently in GUI applications! + */ +extern FILE _iob[]; /* an array of FILE */ +#define stdin (&_iob[0]) +#define stdout (&_iob[1]) +#define stderr (&_iob[2]) +#define stdaux (&_iob[3]) +#define stdprn (&_iob[4]) + +/* Returned by various functions on end of file condition or error. */ +#define EOF (-1) + + +/* + * The maximum length of a file name. You should use GetVolumeInformation + * instead of this constant. But hey, this works. + * + * NOTE: This is used in the structure _finddata_t (see dir.h) so changing it + * is probably not a good idea. + */ +#define FILENAME_MAX (260) + +/* + * The maximum number of files that may be open at once. I have set this to + * a conservative number. The actual value may be higher. + */ +#define FOPEN_MAX (20) + + +/* + * File Operations + */ + +FILE* fopen (const char* szFileName, const char* szMode); +FILE* freopen (const char* szNewFileName, const char* szNewMode, + FILE* fileChangeAssociation); +int fflush (FILE* fileFlush); +int fclose (FILE* fileClose); +#define fcloseall _fcloseall +int remove (const char* szFileName); +int rename (const char* szOldFileName, const char* szNewFileName); +FILE* tmpfile (void); + +int _filbuf(FILE *f); +int _flsbuf(int c, FILE *f); +void _fwalk(void (*func)(FILE *)); // not exported +int _fcloseall( void ); + + +/* + * The maximum size of name (including NUL) that will be put in the user + * supplied buffer caName. + * NOTE: This has not been determined by experiment, but based on the + * maximum file name length above it is probably reasonable. I could be + * wrong... + */ +#define L_tmpnam (260) + +char* tmpnam (char caName[]); +char* _tempnam (const char *szDir, const char *szPfx); + +#ifndef _NO_OLDNAMES +#define tempnam _tempnam +#endif /* Not _NO_OLDNAMES */ + +/* + * The three possible buffering mode (nMode) values for setvbuf. + * NOTE: _IOFBF works, but _IOLBF seems to work like unbuffered... + * maybe I'm testing it wrong? + */ +#define _IOFBF 0 /* fully buffered */ +#define _IOLBF 1 /* line buffered */ +#define _IONBF 2 /* unbuffered */ + +int setvbuf (FILE* fileSetBuffer, char* caBuffer, int nMode, + size_t sizeBuffer); + + +/* + * The buffer size as used by setbuf such that it is equivalent to + * (void) setvbuf(fileSetBuffer, caBuffer, _IOFBF, BUFSIZ). + */ +#define BUFSIZ 512 + +void setbuf (FILE* fileSetBuffer, char* caBuffer); + +/* + * Pipe Operations + */ + +int _pclose (FILE* pipeClose); +FILE* _popen (const char* szPipeName, const char* szMode); + +#define popen _popen +#define pclose _pclose + +/* Wide character version */ +FILE* _wpopen (const wchar_t* szPipeName, const wchar_t* szMode); + +/* + * Formatted Output + */ + +int fprintf (FILE* filePrintTo, const char* szFormat, ...); +int printf (const char* szFormat, ...); +int sprintf (char* caBuffer, const char* szFormat, ...); +int vfprintf (FILE* filePrintTo, const char* szFormat, va_list varg); +int vprintf (const char* szFormat, va_list varg); +int vsprintf (char* caBuffer, const char* szFormat, va_list varg); + +/* Wide character versions */ +int fwprintf (FILE* filePrintTo, const wchar_t* wsFormat, ...); +int wprintf (const wchar_t* wsFormat, ...); +int swprintf (wchar_t* wcaBuffer, const wchar_t* wsFormat, ...); +int vfwprintf (FILE* filePrintTo, const wchar_t* wsFormat, va_list varg); +int vwprintf (const wchar_t* wsFormat, va_list varg); +int vswprintf (wchar_t* wcaBuffer, const wchar_t* wsFormat, va_list varg); + +/* + * Formatted Input + */ + +int fscanf (FILE* fileReadFrom, const char* szFormat, ...); +int scanf (const char* szFormat, ...); +int sscanf (const char* szReadFrom, const char* szFormat, ...); + +/* Wide character versions */ +int fwscanf (FILE* fileReadFrom, const wchar_t* wsFormat, ...); +int wscanf (const wchar_t* wsFormat, ...); +int swscanf (const wchar_t* wsReadFrom, const wchar_t* wsFormat, ...); + +/* + * Character Input and Output Functions + */ + +int fgetc (FILE* fileRead); +char* fgets (char* caBuffer, int nBufferSize, FILE* fileRead); +int fputc (int c, FILE* fileWrite); +int fputs (const char* szOutput, FILE* fileWrite); +int getc (FILE* fileRead); +int getchar (void); +char* gets (char* caBuffer); /* Unsafe: how does gets know how long the + * buffer is? */ +int putc (int c, FILE* fileWrite); +int putchar (int c); +int puts (const char* szOutput); +int ungetc (int c, FILE* fileWasRead); + +/* Wide character versions */ +wint_t fgetwc (FILE* fileRead); +wint_t fputwc (wchar_t wc, FILE* fileWrite); +wint_t getwc(FILE *fileRead); // not exported +wint_t ungetwc (wchar_t wc, FILE* fileWasRead); + +wint_t _filwbuf(FILE *f); +wint_t _flswbuf(wchar_t c, FILE *f); + +/* + * Not exported by CRTDLL.DLL included for reference purposes. + */ +#if 0 +wchar_t* fgetws (wchar_t* wcaBuffer, int nBufferSize, FILE* fileRead); +int fputws (const wchar_t* wsOutput, FILE* fileWrite); +int getwc (FILE* fileRead); +int getwchar (); +wchar_t* getws (wchar_t* wcaBuffer); +int putwc (wchar_t wc, FILE* fileWrite); +int putws (const wchar_t* wsOutput); +#endif /* 0 */ + +/* NOTE: putchar has no wide char equivalent even in tchar.h */ + + +/* + * Direct Input and Output Functions + */ + +size_t fread (void* pBuffer, size_t sizeObject, size_t sizeObjCount, + FILE* fileRead); +size_t fwrite (const void* pObjArray, size_t sizeObject, size_t sizeObjCount, + FILE* fileWrite); + + +/* + * File Positioning Functions + */ + +/* Constants for nOrigin indicating the position relative to which fseek + * sets the file position. Enclosed in ifdefs because io.h could also + * define them. (Though not anymore since io.h includes this file now.) */ +#ifndef SEEK_SET +#define SEEK_SET (0) +#endif + +#ifndef SEEK_CUR +#define SEEK_CUR (1) +#endif + +#ifndef SEEK_END +#define SEEK_END (2) +#endif + +int fseek (FILE* fileSetPosition, long lnOffset, int nOrigin); +long ftell (FILE* fileGetPosition); +void rewind (FILE* fileRewind); + +/* + * An opaque data type used for storing file positions... The contents of + * this type are unknown, but we (the compiler) need to know the size + * because the programmer using fgetpos and fsetpos will be setting aside + * storage for fpos_t structres. Actually I tested using a byte array and + * it is fairly evident that the fpos_t type is a long (in CRTDLL.DLL). + * Perhaps an unsigned long? TODO? + */ +typedef long fpos_t; + +int fgetpos (FILE* fileGetPosition, fpos_t* pfpos); +int fsetpos (FILE* fileSetPosition, const fpos_t* pfpos); + + +/* + * Error Functions + */ +#if 0 +void clearerr (FILE* fileClearErrors); +int feof (FILE* fileIsAtEnd); +int ferror (FILE* fileIsError); +void perror (const char* szErrorMessage); + +#endif + +#define clearerr(f) (((f)->_flag) &= ~(_IOERR|_IOEOF)) +#define feof(f) (((f)->_flag&_IOEOF)!=0) +#define ferror(f) (((f)->_flag&_IOERR)!=0) +#define perror(s) (fprintf(stderr, "%s: %s\n", (s), _strerror(NULL))) +/* + * Non ANSI functions + */ + +#ifndef __STRICT_ANSI__ +int _fgetchar (void); +int _fputchar (int c); +FILE* _fdopen (int nHandle, char* szMode); + +#ifndef _NO_OLDNAMES +#define fgetchar _fgetchar +#define fputchar _fputchar +#define fdopen _fdopen +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _STDIO_H_ */ diff --git a/include/crtdll/stdlib.h b/include/crtdll/stdlib.h new file mode 100644 index 0000000..22bfede --- /dev/null +++ b/include/crtdll/stdlib.h @@ -0,0 +1,210 @@ +/* + * stdlib.h + * + * Definitions for common types, variables, and functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* added splitpath */ +/* changed definition of environ and argc */ +/* moved prototype for swab from string.h to stdlib.h */ +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This seems like a convenient place to declare these variables, which + * give programs using WinMain (or main for that matter) access to main-ish + * argc and argv. environ is a pointer to a table of environment variables. + * NOTE: Strings in _argv and environ are ANSI strings. + */ +extern int* __argc_dll; +extern char*** __argv_dll; +extern char*** _environ_dll; +#define __argc (*__argc_dll) +#define __argv (*__argv_dll) +#define _environ (*_environ_dll) + + +#define __need_size_t +#define __need_wchar_t +#define __need_NULL +#include + +#include + +#ifndef __ATTRIB_NORETURN +#ifdef __GNUC__ +#define _ATTRIB_NORETURN __attribute__ ((noreturn)) +#else /* Not __GNUC__ */ +#define _ATTRIB_NORETURN +#endif /* __GNUC__ */ +#endif + +double atof (const char* szNumber); +int atoi (const char* szNumber); +long atol (const char* szNumber); + + +double strtod (const char* szNumber, char** pszAfterNumber); +double wcstod (const wchar_t* wsNumber, wchar_t** pwsAfterNumber); +long strtol (const char* szNumber, char** pszAfterNumber, int nBase); +long wcstol (const wchar_t* wsNumber, wchar_t** pwsAfterNumber, int nBase); + +unsigned long strtoul (const char* szNumber, char** pszAfterNumber, + int nBase); +unsigned long wcstoul (const wchar_t* wsNumber, wchar_t** pwsAfterNumber, + int nBase); + +size_t wcstombs (char* mbsDest, const wchar_t* wsConvert, size_t size); +int wctomb (char* mbDest, wchar_t wc); + +int mblen (const char* mbs, size_t sizeString); +size_t mbstowcs (wchar_t* wcaDest, const char* mbsConvert, + size_t size); +int mbtowc (wchar_t* wcDest, const char* mbConvert, size_t size); + + +/* + * RAND_MAX is the maximum value that may be returned by rand. + * The minimum is zero. + */ +#define RAND_MAX 0x7FFF + +int rand (void); +void srand (unsigned int nSeed); + + +void* calloc (size_t sizeObjCnt, size_t sizeObject); +void* malloc (size_t sizeObject); +void* realloc (void* pObject, size_t sizeNew); +void free (void* pObject); + +/* These values may be used as exit status codes. */ +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE -1 + +void abort (void) _ATTRIB_NORETURN; +void exit (int nStatus) _ATTRIB_NORETURN; +int atexit (void (*pfuncExitProcessing)(void)); + +int system (const char* szCommand); // impl in process +char* getenv (const char* szVarName); // impl in stdio + +typedef int (*_pfunccmp_t)(const void*, const void*); + +void* bsearch (const void* pKey, const void* pBase, size_t cntObjects, + size_t sizeObject, _pfunccmp_t pfuncCmp); +void qsort (const void* pBase, size_t cntObjects, size_t sizeObject, + _pfunccmp_t pfuncCmp); + +int abs (int n); +long labs (long n); + +/* + * div_t and ldiv_t are structures used to return the results of div and + * ldiv. + * + * NOTE: div and ldiv appear not to work correctly unless + * -fno-pcc-struct-return is specified. This is included in the + * mingw32 specs file. + */ +typedef struct { int quot, rem; } div_t; +typedef struct { long quot, rem; } ldiv_t; +typedef struct { long long quot, rem; } lldiv_t; + +div_t div (int nNumerator, int nDenominator); +ldiv_t ldiv (long lNumerator, long lDenominator); +lldiv_t lldiv (long long lNumerator, long long lDenominator); + + +#ifndef __STRICT_ANSI__ + +/* + * NOTE: Officially the three following functions are obsolete. The Win32 API + * functions SetErrorMode, Beep and Sleep are their replacements. + */ +void _beep (unsigned int, unsigned int); +void _seterrormode (int nMode); +void _sleep (unsigned long ulTime); + +void _exit (int nStatus) _ATTRIB_NORETURN; + +int _putenv (const char* szNameEqValue); +void _searchenv (const char* szFileName, const char* szVar, + char* szFullPathBuf); + +void _splitpath( const char *path, char *drive, char *dir, + char *fname, char *ext ); + +char* _itoa (int nValue, char* sz, int nRadix); +char* _ltoa (long lnValue, char* sz, int nRadix); + +char* _ecvt (double dValue, int nDig, int* pnDec, int* pnSign); +char* _fcvt (double dValue, int nDig, int* pnDec, int* pnSign); +char* _gcvt (double dValue, int nDec, char* caBuf); + +char* _fullpath (char* caBuf, const char* szPath, size_t sizeMax); + +void _swab (const char* caFrom, char* caTo, size_t sizeToCopy); + +unsigned int _rotl( unsigned int value, int shift ); +unsigned int _rotr( unsigned int value, int shift ); +unsigned long _lrotl( unsigned long value, int shift ); +unsigned long _lrotr( unsigned long value, int shift ); + + + + +#ifndef _NO_OLDNAMES +#define beep _beep +#define seterrormode _seterrormode +#define sleep _sleep +#define putenv _putenv +#define searchenv _searchenv +#define splitpath _splitpath + +#define itoa _itoa +#define ltoa _ltoa + +#define ecvt _ecvt +#define fcvt _fcvt +#define gcvt _gcvt + +#define swab _swab +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +/* + * Undefine the no return attribute used in some function definitions + */ +#undef _ATTRIB_NORETURN + +#ifdef __cplusplus +} +#endif + +#endif /* _STDLIB_H_ */ diff --git a/include/crtdll/string.h b/include/crtdll/string.h new file mode 100644 index 0000000..77dab36 --- /dev/null +++ b/include/crtdll/string.h @@ -0,0 +1,192 @@ +/* + * string.h + * + * Definitions for memory and string functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* changed prototype for _strerror */ +/* moved prototype for swab from string.h to stdlib.h */ + + +#ifndef _STRING_H_ +#define _STRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define size_t, wchar_t and NULL + */ +#define __need_size_t +#define __need_wchar_t +#define __need_NULL +#include + +char * ___strtok; // removed extern specifier 02-06-98, BD + +/* + * Prototypes of the ANSI Standard C library string functions. + */ +void* memchr (const void* p, int cSearchFor, size_t sizeSearch); +int memcmp (const void* p1, const void* p2, size_t sizeSearch); +void* memcpy (void* pCopyTo, const void* pSource, size_t sizeSource); +void* memmove (void* pMoveTo, const void* pSource, size_t sizeSource); +void* memset (void* p, int cFill, size_t sizeRepeatCount); +char* strcat (char* szAddTo, const char* szAdd); +char* strchr (const char* szSearch, int cFor); +int strcmp (const char* sz1, const char* sz2); +int strcoll (const char* sz1, const char* sz2); /* Compare using locale */ +char* strcpy (char* szCopyTo, const char* szSource); +size_t strcspn (const char* szGetPrefix, const char* szNotIncluding); +char* strerror (int nError); /* NOTE: NOT an old name wrapper. */ +char * _strerror(const char *s); +size_t strlen (const char* sz); +size_t strnlen (const char* sz, size_t count); // not exported +char* strncat (char* szAddTo, const char* szAdd, size_t sizeMaxAdd); +int strncmp (const char* sz1, const char* sz2, size_t sizeMaxCompare); +char* strncpy (char* szCopyTo, const char* szSource, size_t sizeMaxCopy); +char* strpbrk (const char* szSearch, const char* szAnyOf); +char* strrchr (const char* szSearch, int cFor); +size_t strspn (const char* szGetPrefix, const char *szIncluding); +char* strstr (const char* szSearch, const char *szFor); +char* strtok (char* szTokenize, const char* szDelimiters); +size_t strxfrm (char* szTransformed, const char *szSource, + size_t sizeTransform); + +#ifndef __STRICT_ANSI__ +/* + * Extra non-ANSI functions provided by the CRTDLL library + */ +void* _memccpy (void* pCopyTo, const void* pSource, int cTerminator, + size_t sizeMaxCopy); +int _memicmp (const void* p1, const void* p2, size_t sizeSearch); +char* _strdup (const char *szDuplicate); +int _strcmpi (const char* sz1, const char* sz2); +int _stricmp (const char* sz1, const char* sz2); +int _stricoll (const char* sz1, const char* sz2); +char* _strlwr (char* szToConvert); +int _strnicmp (const char* sz1, const char* sz2, + size_t sizeMaxCompare); +char* _strnset (char* szToFill, int cFill, size_t sizeMaxFill); +char* _strrev (char* szToReverse); +char* _strset (char* szToFill, int cFill); +char* _strupr (char* szToConvert); + + +#endif /* Not __STRICT_ANSI__ */ + + +/* + * Unicode versions of the standard calls. + */ +wchar_t* wcscat (wchar_t* wsAddTo, const wchar_t* wsAdd); +wchar_t* wcschr (const wchar_t* wsSearch, wchar_t wcFor); +int wcscmp (const wchar_t* ws1, const wchar_t* ws2); +int wcscoll (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* wcscpy (wchar_t* wsCopyTo, const wchar_t* wsSource); +size_t wcscspn (const wchar_t* wsGetPrefix, const wchar_t* wsNotIncluding); +/* Note: No wcserror in CRTDLL. */ +size_t wcslen (const wchar_t* ws); +wchar_t* wcsncat (wchar_t* wsAddTo, const wchar_t* wsAdd, size_t sizeMaxAdd); +int wcsncmp(const wchar_t* ws1, const wchar_t* ws2, size_t sizeMaxCompare); +wchar_t* wcsncpy(wchar_t* wsCopyTo, const wchar_t* wsSource, + size_t sizeMaxCopy); +wchar_t* wcspbrk(const wchar_t* wsSearch, const wchar_t* wsAnyOf); +wchar_t* wcsrchr(const wchar_t* wsSearch, wchar_t wcFor); +size_t wcsspn(const wchar_t* wsGetPrefix, const wchar_t* wsIncluding); +wchar_t* wcsstr(const wchar_t* wsSearch, const wchar_t* wsFor); +wchar_t* wcstok(wchar_t* wsTokenize, const wchar_t* wsDelimiters); +size_t wcsxfrm(wchar_t* wsTransformed, const wchar_t *wsSource, + size_t sizeTransform); + + +#ifndef __STRICT_ANSI__ +/* + * Unicode versions of non-ANSI functions provided by CRTDLL. + */ + +/* NOTE: _wcscmpi not provided by CRTDLL, this define is for portability */ +#define _wcscmpi _wcsicmp + +wchar_t* _wcsdup (const wchar_t* wsToDuplicate); +int _wcsicmp (const wchar_t* ws1, const wchar_t* ws2); +int _wcsicoll (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* _wcslwr (wchar_t* wsToConvert); +int _wcsnicmp (const wchar_t* ws1, const wchar_t* ws2, + size_t sizeMaxCompare); +wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill); +wchar_t* _wcsrev (wchar_t* wsToReverse); +wchar_t* _wcsset (wchar_t* wsToFill, wchar_t wcToFill); +wchar_t* _wcsupr (wchar_t* wsToConvert); + +#endif /* Not __STRICT_ANSI__ */ + + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +/* + * Non-underscored versions of non-ANSI functions. They live in liboldnames.a + * and provide a little extra portability. Also a few extra UNIX-isms like + * strcasecmp. + */ + +void* memccpy (void* pCopyTo, const void* pSource, int cTerminator, + size_t sizeMaxCopy); +int memicmp (const void* p1, const void* p2, size_t sizeSearch); +#define strdup(szDuplicate) _strdup(szDuplicate) +int strcmpi (const char* sz1, const char* sz2); +int stricmp (const char* sz1, const char* sz2); +int strcasecmp (const char* sz1, const char* sz2); +int stricoll (const char* sz1, const char* sz2); +char* strlwr (char* szToConvert); +int strnicmp (const char* sz1, const char* sz2, size_t sizeMaxCompare); +int strncasecmp (const char* sz1, const char* sz2, size_t sizeMaxCompare); +char* strnset (char* szToFill, int cFill, size_t sizeMaxFill); +char* strrev (char* szToReverse); +char* strset (char* szToFill, int cFill); +char* strupr (char* szToConvert); + + +/* NOTE: There is no _wcscmpi, but this is for compatibility. */ +int wcscmpi (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* wcsdup (const wchar_t* wsToDuplicate); +int wcsicmp (const wchar_t* ws1, const wchar_t* ws2); +int wcsicoll (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* wcslwr (wchar_t* wsToConvert); +int wcsnicmp (const wchar_t* ws1, const wchar_t* ws2, + size_t sizeMaxCompare); +wchar_t* wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill); +wchar_t* wcsrev (wchar_t* wsToReverse); +wchar_t* wcsset (wchar_t* wsToFill, wchar_t wcToFill); +wchar_t* wcsupr (wchar_t* wsToConvert); + +#endif /* Not _NO_OLDNAMES */ +#endif /* Not strict ANSI */ + +#endif + +#ifdef __cplusplus +}; /* extern "c" */ +#endif diff --git a/include/crtdll/sys/fcntl.h b/include/crtdll/sys/fcntl.h new file mode 100644 index 0000000..4f83933 --- /dev/null +++ b/include/crtdll/sys/fcntl.h @@ -0,0 +1,8 @@ +/* + * This file is part of the Mingw32 package. + * + * This fcntl.h maps to the root fcntl.h + */ +#ifndef __STRICT_ANSI__ +#include +#endif diff --git a/include/crtdll/sys/file.h b/include/crtdll/sys/file.h new file mode 100644 index 0000000..4497725 --- /dev/null +++ b/include/crtdll/sys/file.h @@ -0,0 +1,9 @@ +/* + * This file is part of the Mingw32 package. + * + * This file.h maps to the root fcntl.h + * TODO? + */ +#ifndef __STRICT_ANSI__ +#include +#endif diff --git a/include/crtdll/sys/locking.h b/include/crtdll/sys/locking.h new file mode 100644 index 0000000..d279c6d --- /dev/null +++ b/include/crtdll/sys/locking.h @@ -0,0 +1,38 @@ +/* + * locking.h + * + * Constants for the mode parameter of the locking function. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _LOCKING_H_ +#define _LOCKING_H_ + +/* + * TODO: Define LK_... constants. + */ + +#endif /* Not _LOCKING_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/sys/stat.h b/include/crtdll/sys/stat.h new file mode 100644 index 0000000..8ea94f2 --- /dev/null +++ b/include/crtdll/sys/stat.h @@ -0,0 +1,113 @@ +/* + * stat.h + * + * Symbolic constants for opening and creating files, also stat, fstat and + * chmod functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _STAT_H_ +#define _STAT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Constants for the stat st_mode member. + */ +#define S_IFIFO 0x1000 /* FIFO */ +#define S_IFCHR 0x2000 /* Character */ +#define S_IFBLK 0x3000 /* Block */ +#define S_IFDIR 0x4000 /* Directory */ +#define S_IFREG 0x8000 /* Regular */ + +#define S_IFMT 0xF000 /* File type mask */ + +#define S_IEXEC 0x0040 +#define S_IWRITE 0x0080 +#define S_IREAD 0x0100 + +#define S_ISDIR(m) ((m) & S_IFDIR) +#define S_ISFIFO(m) ((m) & S_IFIFO) +#define S_ISCHR(m) ((m) & S_IFCHR) +#define S_ISBLK(m) ((m) & S_IFBLK) +#define S_ISREG(m) ((m) & S_IFREG) + +#define S_IRWXU (S_IREAD | S_IWRITE | S_IEXEC) +#define S_IXUSR S_IEXEC +#define S_IWUSR S_IWRITE +#define S_IRUSR S_IREAD + +#define _S_IEXEC S_IEXEC +#define _S_IREAD S_IREAD +#define _S_IWRITE S_IWRITE + +/* + * The structure manipulated and returned by stat and fstat. + * + * NOTE: If called on a directory the values in the time fields are not only + * invalid, they will cause localtime et. al. to return NULL. And calling + * asctime with a NULL pointer causes an Invalid Page Fault. So watch it! + */ +struct stat +{ + short st_dev; /* Equivalent to drive number 0=A 1=B ... */ + short st_ino; /* Always zero ? */ + short st_mode; /* See above constants */ + short st_nlink; /* Number of links. */ + int st_uid; /* User: Maybe significant on NT ? */ + short st_gid; /* Group: Ditto */ + short st_rdev; /* Seems useless (not even filled in) */ + long st_size; /* File size in bytes */ + time_t st_atime; /* Accessed date (always 00:00 hrs local + * on FAT) */ + time_t st_mtime; /* Modified time */ + time_t st_ctime; /* Creation time */ +}; + + +int _fstat (int nFileNo, struct stat* pstat); +int _chmod (const char* szPath, int nMode); +int _stat (const char* szPath, struct stat* pstat); + + +#ifndef _NO_OLDNAMES + +#define fstat(nFileNo, pstat) _fstat(nFileNo, pstat) +#define chmod(szPath,nMode) _chmod(szPath,nMode) +#define stat(szPath,pstat) _stat(szPath,pstat) + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _STAT_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/sys/time.h b/include/crtdll/sys/time.h new file mode 100644 index 0000000..deffe97 --- /dev/null +++ b/include/crtdll/sys/time.h @@ -0,0 +1,3 @@ + +#include + diff --git a/include/crtdll/sys/timeb.h b/include/crtdll/sys/timeb.h new file mode 100644 index 0000000..85e57ed --- /dev/null +++ b/include/crtdll/sys/timeb.h @@ -0,0 +1,60 @@ +/* + * timeb.h + * + * Support for the UNIX System V ftime system call. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _TIMEB_H_ +#define _TIMEB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * TODO: Structure not tested. + */ +struct timeb +{ + long time; + short millitm; + short _timezone; + short dstflag; +}; + +/* TODO: Not tested. */ +void _ftime (struct timeb* timebBuffer); + +#ifndef _NO_OLDNAMES +void ftime (struct timeb* timebBuffer); +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not _TIMEB_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/sys/types.h b/include/crtdll/sys/types.h new file mode 100644 index 0000000..bafdbac --- /dev/null +++ b/include/crtdll/sys/types.h @@ -0,0 +1,77 @@ +/* + * types.h + * + * The definition of constants, data types and global variables. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#ifndef _TIME_T_ +#define _TIME_T_ +typedef long time_t; +#endif + + +#ifndef __STRICT_ANSI__ + +#ifndef _OFF_T_DEFINED +typedef long _off_t; + +#ifndef _NO_OLDNAMES +#define off_t _off_t +#endif + +#define _OFF_T_DEFINED + +#endif /* Not _OFF_T_DEFINED */ + + +#ifndef _DEV_T_DEFINED +typedef short _dev_t; + +#ifndef _NO_OLDNAMES +#define dev_t _dev_t +#endif + +#define _DEV_T_DEFINED + +#endif /* Not _DEV_T_DEFINED */ + + +#ifndef _INO_T_DEFINED +typedef short _ino_t; + +#ifndef _NO_OLDNAMES +#define ino_t _ino_t +#endif + +#define _INO_T_DEFINED + +#endif /* Not _INO_T_DEFINED */ + + +#endif /* Not __STRICT_ANSI__ */ + + +#endif /* Not _TYPES_H_ */ diff --git a/include/crtdll/sys/unistd.h b/include/crtdll/sys/unistd.h new file mode 100644 index 0000000..63cbb45 --- /dev/null +++ b/include/crtdll/sys/unistd.h @@ -0,0 +1,9 @@ +/* + * This file is part of the Mingw32 package. + * + * unistd.h maps (roughly) to io.h + */ +#ifndef __STRICT_ANSI__ +#include +#endif + diff --git a/include/crtdll/sys/utime.h b/include/crtdll/sys/utime.h new file mode 100644 index 0000000..f355e7e --- /dev/null +++ b/include/crtdll/sys/utime.h @@ -0,0 +1,75 @@ +/* + * utime.h + * + * Support for the utime function. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _UTIME_H_ +#define _UTIME_H_ + +#define __need_wchar_t +#define __need_size_t +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Structure used by _utime function. + */ +struct _utimbuf +{ + time_t actime; /* Access time */ + time_t modtime; /* Modification time */ +}; + +int _utime (const char* szFileName, struct _utimbuf* pTimes); +int _futime (int nHandle, struct _utimbuf *pTimes); + +/* Wide character version */ +int _wutime (const wchar_t *szFileName, struct _utimbuf *times); + +#ifndef _NO_OLDNAMES + +/* NOTE: Must be the same as _utimbuf above. */ +struct utimbuf +{ + time_t actime; + time_t modtime; +}; + +int utime (const char* szFileName, struct utimbuf* pTimes); + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _UTIME_H_ */ +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/crtdll/tchar.h b/include/crtdll/tchar.h new file mode 100644 index 0000000..9dc3ab4 --- /dev/null +++ b/include/crtdll/tchar.h @@ -0,0 +1,231 @@ +/* + * tchar.h + * + * Unicode mapping layer for the standard C library. By including this + * file and using the 't' names for string functions + * (eg. _tprintf) you can make code which can be easily adapted to both + * Unicode and non-unicode environments. In a unicode enabled compile define + * _UNICODE before including tchar.h, otherwise the standard non-unicode + * library functions will be used. + * + * Note that you still need to include string.h or stdlib.h etc. to define + * the appropriate functions. Also note that there are several defines + * included for non-ANSI functions which are commonly available (but using + * the convention of prepending an underscore to non-ANSI library function + * names). + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _TCHAR_H_ +#define _TCHAR_H_ + +/* + * NOTE: This tests _UNICODE, which is different from the UNICODE define + * used to differentiate Win32 API calls. + */ +#ifdef _UNICODE + + +/* + * Use TCHAR instead of char or wchar_t. It will be appropriately translated + * if _UNICODE is correctly defined (or not). + */ +#ifndef _TCHAR_DEFINED +#ifndef RC_INVOKED +typedef wchar_t TCHAR; +#endif /* Not RC_INVOKED */ +#define _TCHAR_DEFINED +#endif + + +/* + * Enclose constant strings and literal characters in the _TEXT and _T macro to make + * them unicode constant strings when _UNICODE is defined. + */ +#define _TEXT(x) L ## x +#define _T(x) L ## x + +/* + * Unicode functions + */ + +#define _tprintf wprintf +#define _ftprintf fwprintf +#define _stprintf swprintf +#define _sntprintf _snwprintf +#define _vtprintf vwprintf +#define _vftprintf vfwprintf +#define _vstprintf vswprintf +#define _vsntprintf _vsnwprintf +#define _tscanf wscanf +#define _ftscanf fwscanf +#define _stscanf swscanf +#define _fgettc fgetwc +#define _fgettchar _fgetwchar +#define _fgetts fgetws +#define _fputtc fputwc +#define _fputtchar _fputwchar +#define _fputts fputws +#define _gettc getwc +#define _getts getws +#define _puttc putwc +#define _putts putws +#define _ungettc ungetwc +#define _tcstod wcstod +#define _tcstol wcstol +#define _tcstoul wcstoul +#define _tcscat wcscat +#define _tcschr wcschr +#define _tcscmp wcscmp +#define _tcscpy wcscpy +#define _tcscspn wcscspn +#define _tcslen wcslen +#define _tcsncat wcsncat +#define _tcsncmp wcsncmp +#define _tcsncpy wcsncpy +#define _tcspbrk wcspbrk +#define _tcsrchr wcsrchr +#define _tcsspn wcsspn +#define _tcsstr wcsstr +#define _tcstok wcstok +#define _tcsdup _wcsdup +#define _tcsicmp _wcsicmp +#define _tcsnicmp _wcsnicmp +#define _tcsnset _wcsnset +#define _tcsrev _wcsrev +#define _tcsset _wcsset +#define _tcslwr _wcslwr +#define _tcsupr _wcsupr +#define _tcsxfrm wcsxfrm +#define _tcscoll wcscoll +#define _tcsicoll _wcsicoll +#define _istalpha iswalpha +#define _istupper iswupper +#define _istlower iswlower +#define _istdigit iswdigit +#define _istxdigit iswxdigit +#define _istspace iswspace +#define _istpunct iswpunct +#define _istalnum iswalnum +#define _istprint iswprint +#define _istgraph iswgraph +#define _istcntrl iswcntrl +#define _istascii iswascii +#define _totupper towupper +#define _totlower towlower +#define _ttoi _wtoi +#define _tcsftime wcsftime + +#else /* Not _UNICODE */ + +/* + * TCHAR, the type you should use instead of char. + */ +#ifndef _TCHAR_DEFINED +#ifndef RC_INVOKED +typedef char TCHAR; +#endif +#define _TCHAR_DEFINED +#endif + +/* + * Enclose constant strings and characters in the _TEXT and _T macro. + */ +#define _TEXT(x) x +#define _T(x) x + + +/* + * Non-unicode (standard) functions + */ + +#define _tprintf printf +#define _ftprintf fprintf +#define _stprintf sprintf +#define _sntprintf _snprintf +#define _vtprintf vprintf +#define _vftprintf vfprintf +#define _vstprintf vsprintf +#define _vsntprintf _vsnprintf +#define _tscanf scanf +#define _ftscanf fscanf +#define _stscanf sscanf +#define _fgettc fgetc +#define _fgettchar _fgetchar +#define _fgetts fgets +#define _fputtc fputc +#define _fputtchar _fputchar +#define _fputts fputs +#define _gettc getc +#define _getts gets +#define _puttc putc +#define _putts puts +#define _ungettc ungetc +#define _tcstod strtod +#define _tcstol strtol +#define _tcstoul strtoul +#define _tcscat strcat +#define _tcschr strchr +#define _tcscmp strcmp +#define _tcscpy strcpy +#define _tcscspn strcspn +#define _tcslen strlen +#define _tcsncat strncat +#define _tcsncmp strncmp +#define _tcsncpy strncpy +#define _tcspbrk strpbrk +#define _tcsrchr strrchr +#define _tcsspn strspn +#define _tcsstr strstr +#define _tcstok strtok +#define _tcsdup _strdup +#define _tcsicmp _stricmp +#define _tcsnicmp _strnicmp +#define _tcsnset _strnset +#define _tcsrev _strrev +#define _tcsset _strset +#define _tcslwr _strlwr +#define _tcsupr _strupr +#define _tcsxfrm strxfrm +#define _tcscoll strcoll +#define _tcsicoll _stricoll +#define _istalpha isalpha +#define _istupper isupper +#define _istlower islower +#define _istdigit isdigit +#define _istxdigit isxdigit +#define _istspace isspace +#define _istpunct ispunct +#define _istalnum isalnum +#define _istprint isprint +#define _istgraph isgraph +#define _istcntrl iscntrl +#define _istascii isascii +#define _totupper toupper +#define _totlower tolower +#define _ttoi atoi +#define _tcsftime strftime + +#endif /* Not _UNICODE */ + +#endif /* Not _TCHAR_H_ */ + diff --git a/include/crtdll/time.h b/include/crtdll/time.h new file mode 100644 index 0000000..ede0f82 --- /dev/null +++ b/include/crtdll/time.h @@ -0,0 +1,119 @@ +/* + * time.h + * + * Date and time functions and types. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +#ifndef _TIME_H_ +#define _TIME_H_ + +#define __need_wchar_t +#define __need_size_t +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Number of clock ticks per second. A clock tick is the unit by which + * processor time is measured and is returned by 'clock'. + */ +#define CLOCKS_PER_SEC 1000.0 +#define CLK_TICK CLOCKS_PER_SEC + +/* + * A type for measuring processor time (in clock ticks). + */ +#ifndef _CLOCK_T_ +#define _CLOCK_T_ +typedef long clock_t; +#endif + +/* + * Need a definition of time_t. + */ +#include + +/* + * A type for storing the current time and date. This is the number of + * seconds since midnight Jan 1, 1970. + * NOTE: Normally this is defined by the above include of sys/types.h + */ +#ifndef _TIME_T_ +#define _TIME_T_ +typedef long time_t; +#endif + +/* + * A structure for storing all kinds of useful information about the + * current (or another) time. + */ +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + char *tm_zone; + int tm_gmtoff; +}; + + + +clock_t clock (void); +time_t time (time_t* tp); +double difftime (time_t t2, time_t t1); +time_t mktime (struct tm* tmsp); + +/* + * These functions write to and return pointers to static buffers that may + * be overwritten by other function calls. Yikes! + * + * NOTE: localtime, and perhaps the others of the four functions grouped + * below may return NULL if their argument is not 'acceptable'. Also note + * that calling asctime with a NULL pointer will produce an Invalid Page + * Fault and crap out your program. Guess how I know. Hint: stat called on + * a directory gives 'invalid' times in st_atime etc... + */ +char* asctime (const struct tm* tmsp); +char* ctime (const time_t* tp); +struct tm* gmtime (const time_t* tm); +struct tm* localtime (const time_t* tm); + + +size_t strftime (char* caBuffer, size_t sizeMax, const char* szFormat, + const struct tm* tpPrint); + +size_t wcsftime (wchar_t* wcaBuffer, size_t sizeMax, + const wchar_t* wsFormat, const struct tm* tpPrint); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/crtdll/wchar.h b/include/crtdll/wchar.h new file mode 100644 index 0000000..eadb63d --- /dev/null +++ b/include/crtdll/wchar.h @@ -0,0 +1,32 @@ +/* + * wchar.h + * + * Defines of all functions for supporting wide characters. Actually it + * just includes all those headers, which is not a good thing to do from a + * processing time point of view, but it does mean that everything will be + * in sync. + * + * This file is part of the Mingw32 package. + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include +#include +#include +#include + diff --git a/include/csrss/csrss.h b/include/csrss/csrss.h new file mode 100644 index 0000000..9b3efe0 --- /dev/null +++ b/include/csrss/csrss.h @@ -0,0 +1,440 @@ +#ifndef __INCLUDE_CSRSS_CSRSS_H +#define __INCLUDE_CSRSS_CSRSS_H + +#include +#include +#include +#include + +#define CSR_PRIORITY_CLASS_NORMAL (0x10) +#define CSR_PRIORITY_CLASS_IDLE (0x20) +#define CSR_PRIORITY_CLASS_HIGH (0x40) +#define CSR_PRIORITY_CLASS_REALTIME (0x80) + +#define CSR_CSRSS_SECTION_SIZE (65536) + +typedef struct +{ +} CSRSS_CONNECT_PROCESS_REQUEST, PCSRSS_CONNECT_PROCESS_REQUEST; + +typedef struct +{ +} CSRSS_CONNECT_PROCESS_REPLY, PCSRSS_CONNECT_PROCESS_REPLY; + +typedef struct +{ + ULONG NewProcessId; + ULONG Flags; +} CSRSS_CREATE_PROCESS_REQUEST, *PCSRSS_CREATE_PROCESS_REQUEST; + +typedef struct +{ + HANDLE InputHandle; + HANDLE OutputHandle; +} CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + ULONG NrCharactersToWrite; + BYTE Buffer[1]; +} CSRSS_WRITE_CONSOLE_REQUEST, *PCSRSS_WRITE_CONSOLE_REQUEST; + +typedef struct +{ + ULONG NrCharactersWritten; +} CSRSS_WRITE_CONSOLE_REPLY, *PCSRSS_WRITE_CONSOLE_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + WORD NrCharactersToRead; + WORD nCharsCanBeDeleted; // number of chars already in buffer that can be backspaced +} CSRSS_READ_CONSOLE_REQUEST, *PCSRSS_READ_CONSOLE_REQUEST; + +typedef struct +{ + HANDLE EventHandle; + ULONG NrCharactersRead; + BYTE Buffer[1]; +} CSRSS_READ_CONSOLE_REPLY, *PCSRSS_READ_CONSOLE_REPLY; + +typedef struct +{ + HANDLE InputHandle; + HANDLE OutputHandle; +} CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; +} CSRSS_SCREEN_BUFFER_INFO_REQUEST, *PCSRSS_SCREEN_BUFFER_INFO_REQUEST; + +typedef struct +{ + CONSOLE_SCREEN_BUFFER_INFO Info; +} CSRSS_SCREEN_BUFFER_INFO_REPLY, *PCSRSS_SCREEN_BUFFER_INFO_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + COORD Position; +} CSRSS_SET_CURSOR_REQUEST, *PCSRSS_SET_CURSOR_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + CHAR Char; + COORD Position; + WORD Length; +} CSRSS_FILL_OUTPUT_REQUEST, *PCSRSS_FILL_OUTPUT_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + CHAR Attribute; + COORD Coord; + WORD Length; +} CSRSS_FILL_OUTPUT_ATTRIB_REQUEST, *PCSRSS_FILL_OUTPUT_ATTRIB_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; +} CSRSS_READ_INPUT_REQUEST, *PCSRSS_READ_INPUT_REQUEST; + +typedef struct +{ + INPUT_RECORD Input; + BOOL MoreEvents; + HANDLE Event; +} CSRSS_READ_INPUT_REPLY, *PCSRSS_READ_INPUT_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + WORD Length; + COORD Coord; + CHAR String[1]; +} CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST, *PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST; + +typedef struct +{ + COORD EndCoord; +} CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REPLY, *PCSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + WORD Length; + COORD Coord; + CHAR String[1]; +} CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST, *PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST; + +typedef struct +{ + COORD EndCoord; +} CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REPLY, *PCSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; +} CSRSS_GET_CURSOR_INFO_REQUEST, *PCSRSS_GET_CURSOR_INFO_REQUEST; + +typedef struct +{ + CONSOLE_CURSOR_INFO Info; +} CSRSS_GET_CURSOR_INFO_REPLY, *PCSRSS_GET_CURSOR_INFO_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + CONSOLE_CURSOR_INFO Info; +} CSRSS_SET_CURSOR_INFO_REQUEST, *PCSRSS_SET_CURSOR_INFO_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + CHAR Attrib; +} CSRSS_SET_ATTRIB_REQUEST, *PCSRSS_SET_ATTRIB_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + DWORD Mode; +} CSRSS_SET_CONSOLE_MODE_REQUEST, *PCSRSS_SET_CONSOLE_MODE_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; +} CSRSS_GET_CONSOLE_MODE_REQUEST, *PCSRSS_GET_CONSOLE_MODE_REQUEST; + +typedef struct +{ + DWORD ConsoleMode; +} CSRSS_GET_CONSOLE_MODE_REPLY, *PCSRSS_GET_CONSOLE_MODE_REPLY; + +typedef struct +{ + /* may want to add some parameters here someday */ +} CSRSS_CREATE_SCREEN_BUFFER_REQUEST, *PCSRSS_CREATE_SCREEN_BUFFER_REQUEST; + +typedef struct +{ + HANDLE OutputHandle; /* handle to newly created screen buffer */ +} CSRSS_CREATE_SCREEN_BUFFER_REPLY, *PCSRSS_CREATE_SCREEN_BUFFER_REPLY; + +typedef struct +{ + HANDLE OutputHandle; /* handle to screen buffer to switch to */ +} CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST, *PCSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST; + +typedef struct +{ + HANDLE UniqueThread; +} CSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST, * PCSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST; + +typedef struct +{ + CLIENT_ID Cid; +} CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY, * PCSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY; + +typedef struct +{ + HANDLE Console; + DWORD Length; + WCHAR Title[1]; +} CSRSS_SET_TITLE_REQUEST, *PCSRSS_SET_TITLE_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; +} CSRSS_GET_TITLE_REQUEST, *PCSRSS_GET_TITLE_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + DWORD Length; + WCHAR Title[1]; +} CSRSS_GET_TITLE_REPLY, *PCSRSS_GET_TITLE_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + COORD BufferSize; + COORD BufferCoord; + SMALL_RECT WriteRegion; + CHAR_INFO* CharInfo; +} CSRSS_WRITE_CONSOLE_OUTPUT_REQUEST, *PCSRSS_WRITE_CONSOLE_OUTPUT_REQUEST; + +typedef struct +{ + SMALL_RECT WriteRegion; +} CSRSS_WRITE_CONSOLE_OUTPUT_REPLY, *PCSRSS_WRITE_CONSOLE_OUTPUT_REPLY; + +typedef struct +{ + HANDLE ConsoleInput; +} CSRSS_FLUSH_INPUT_BUFFER_REQUEST, *PCSRSS_FLUSH_INPUT_BUFFER_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + SMALL_RECT ScrollRectangle; + BOOLEAN UseClipRectangle; + SMALL_RECT ClipRectangle; + COORD DestinationOrigin; + CHAR_INFO Fill; +} CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST, *PCSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST; + +typedef struct +{ + HANDLE ConsoleHandle; + DWORD NumCharsToRead; + COORD ReadCoord; +}CSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST, *PCSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST; + +typedef struct +{ + COORD EndCoord; + CHAR String[1]; +}CSRSS_READ_CONSOLE_OUTPUT_CHAR_REPLY, *PCSRSS_READ_CONSOLE_OUTPUT_CHAR_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; + DWORD NumAttrsToRead; + COORD ReadCoord; +}CSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REQUEST, *PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REQUEST; + +typedef struct +{ + COORD EndCoord; + CHAR String[1]; +}CSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REPLY, *PCSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REPLY; + +typedef struct +{ + HANDLE ConsoleHandle; +}CSRSS_GET_NUM_INPUT_EVENTS_REQUEST, *PCSRSS_GET_NUM_INPUT_EVENTS_REQUEST; + +typedef struct +{ + DWORD NumInputEvents; +}CSRSS_GET_NUM_INPUT_EVENTS_REPLY, *PCSRSS_GET_NUM_INPUT_EVENTS_REPLY; + +typedef struct +{ + DWORD ProcessId; +} CSRSS_REGISTER_SERVICES_PROCESS_REQUEST, *PCSRSS_REGISTER_SERVICES_PROCESS_REQUEST; + +typedef struct +{ + UINT Flags; + DWORD Reserved; +} CSRSS_EXIT_REACTOS_REQUEST, *PCSRSS_EXIT_REACTOS_REQUEST; + +typedef struct +{ + DWORD Level; + DWORD Flags; +} CSRSS_SHUTDOWN_PARAMETERS, *PCSRSS_SHUTDOWN_PARAMETERS; + +typedef struct +{ + HANDLE ConsoleHandle; + DWORD Length; + INPUT_RECORD* InputRecord; +} CSRSS_PEEK_CONSOLE_INPUT_REQUEST, *PCSRSS_PEEK_CONSOLE_INPUT_REQUEST; + +typedef struct +{ + DWORD Length; +} CSRSS_PEEK_CONSOLE_INPUT_REPLY, *PCSRSS_PEEK_CONSOLE_INPUT_REPLY; + + +#define CSRSS_MAX_WRITE_CONSOLE_REQUEST \ + (MAX_MESSAGE_DATA - sizeof(ULONG) - sizeof(CSRSS_WRITE_CONSOLE_REQUEST)) + +#define CSRSS_MAX_SET_TITLE_REQUEST (MAX_MESSAGE_DATA - sizeof( HANDLE ) - sizeof( DWORD ) - sizeof( ULONG ) - sizeof( LPC_MESSAGE_HEADER )) + +#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST )) + +#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB ((MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST )) / 2) + +#define CSRSS_MAX_READ_CONSOLE_REQUEST (MAX_MESSAGE_DATA - sizeof( ULONG ) - sizeof( CSRSS_READ_CONSOLE_REQUEST )) + +#define CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR (MAX_MESSAGE_DATA - sizeof(ULONG) - sizeof(HANDLE) - sizeof(DWORD) - sizeof(CSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST)) + +#define CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB (MAX_MESSAGE_DATA - sizeof(ULONG) - sizeof(HANDLE) - sizeof(DWORD) - sizeof(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REQUEST)) + +// FIXME: it should be 80. Is this a limit due to LPC msg size? +#define CSRSS_MAX_TITLE_LENGTH 50 + +#define CSRSS_CREATE_PROCESS (0x0) +#define CSRSS_TERMINATE_PROCESS (0x1) +#define CSRSS_WRITE_CONSOLE (0x2) +#define CSRSS_READ_CONSOLE (0x3) +#define CSRSS_ALLOC_CONSOLE (0x4) +#define CSRSS_FREE_CONSOLE (0x5) +#define CSRSS_CONNECT_PROCESS (0x6) +#define CSRSS_SCREEN_BUFFER_INFO (0x7) +#define CSRSS_SET_CURSOR (0x8) +#define CSRSS_FILL_OUTPUT (0x9) +#define CSRSS_READ_INPUT (0xA) +#define CSRSS_WRITE_CONSOLE_OUTPUT_CHAR (0xB) +#define CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB (0xC) +#define CSRSS_FILL_OUTPUT_ATTRIB (0xD) +#define CSRSS_GET_CURSOR_INFO (0xE) +#define CSRSS_SET_CURSOR_INFO (0xF) +#define CSRSS_SET_ATTRIB (0x10) +#define CSRSS_GET_MODE (0x11) +#define CSRSS_SET_MODE (0x12) +#define CSRSS_CREATE_SCREEN_BUFFER (0x13) +#define CSRSS_SET_SCREEN_BUFFER (0x14) +#define CSRSS_SET_TITLE (0x15) +#define CSRSS_GET_TITLE (0x16) +#define CSRSS_WRITE_CONSOLE_OUTPUT (0x17) +#define CSRSS_FLUSH_INPUT_BUFFER (0x18) +#define CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER (0x19) +#define CSRSS_READ_CONSOLE_OUTPUT_CHAR (0x1A) +#define CSRSS_READ_CONSOLE_OUTPUT_ATTRIB (0x1B) +#define CSRSS_GET_NUM_INPUT_EVENTS (0x1C) +#define CSRSS_REGISTER_SERVICES_PROCESS (0x1D) +#define CSRSS_EXIT_REACTOS (0x1E) +#define CSRSS_GET_SHUTDOWN_PARAMETERS (0x1F) +#define CSRSS_SET_SHUTDOWN_PARAMETERS (0x20) +#define CSRSS_PEEK_CONSOLE_INPUT (0x21) + + +/* Keep in sync with definition below. */ +#define CSRSS_REQUEST_HEADER_SIZE (sizeof(LPC_MESSAGE_HEADER) + sizeof(ULONG)) + +typedef struct +{ + LPC_MESSAGE_HEADER Header; + ULONG Type; + union + { + CSRSS_CREATE_PROCESS_REQUEST CreateProcessRequest; + CSRSS_CONNECT_PROCESS_REQUEST ConnectRequest; + CSRSS_WRITE_CONSOLE_REQUEST WriteConsoleRequest; + CSRSS_READ_CONSOLE_REQUEST ReadConsoleRequest; + CSRSS_SCREEN_BUFFER_INFO_REQUEST ScreenBufferInfoRequest; + CSRSS_SET_CURSOR_REQUEST SetCursorRequest; + CSRSS_FILL_OUTPUT_REQUEST FillOutputRequest; + CSRSS_READ_INPUT_REQUEST ReadInputRequest; + CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REQUEST WriteConsoleOutputCharRequest; + CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REQUEST WriteConsoleOutputAttribRequest; + CSRSS_FILL_OUTPUT_ATTRIB_REQUEST FillOutputAttribRequest; + CSRSS_SET_CURSOR_INFO_REQUEST SetCursorInfoRequest; + CSRSS_GET_CURSOR_INFO_REQUEST GetCursorInfoRequest; + CSRSS_SET_ATTRIB_REQUEST SetAttribRequest; + CSRSS_SET_CONSOLE_MODE_REQUEST SetConsoleModeRequest; + CSRSS_GET_CONSOLE_MODE_REQUEST GetConsoleModeRequest; + CSRSS_CREATE_SCREEN_BUFFER_REQUEST CreateScreenBufferRequest; + CSRSS_SET_ACTIVE_SCREEN_BUFFER_REQUEST SetActiveScreenBufferRequest; + CSRSS_SET_TITLE_REQUEST SetTitleRequest; + CSRSS_GET_TITLE_REQUEST GetTitleRequest; + CSRSS_WRITE_CONSOLE_OUTPUT_REQUEST WriteConsoleOutputRequest; + CSRSS_FLUSH_INPUT_BUFFER_REQUEST FlushInputBufferRequest; + CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER_REQUEST + ScrollConsoleScreenBufferRequest; + CSRSS_READ_CONSOLE_OUTPUT_CHAR_REQUEST ReadConsoleOutputCharRequest; + CSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REQUEST ReadConsoleOutputAttribRequest; + CSRSS_GET_NUM_INPUT_EVENTS_REQUEST GetNumInputEventsRequest; + CSRSS_REGISTER_SERVICES_PROCESS_REQUEST RegisterServicesProcessRequest; + CSRSS_EXIT_REACTOS_REQUEST ExitReactosRequest; + CSRSS_SHUTDOWN_PARAMETERS SetShutdownParametersRequest; + CSRSS_PEEK_CONSOLE_INPUT_REQUEST PeekConsoleInputRequest; + } Data; +} CSRSS_API_REQUEST, *PCSRSS_API_REQUEST; + +typedef struct +{ + LPC_MESSAGE_HEADER Header; + NTSTATUS Status; + union + { + CSRSS_CREATE_PROCESS_REPLY CreateProcessReply; + CSRSS_CONNECT_PROCESS_REPLY ConnectReply; + CSRSS_WRITE_CONSOLE_REPLY WriteConsoleReply; + CSRSS_READ_CONSOLE_REPLY ReadConsoleReply; + CSRSS_ALLOC_CONSOLE_REPLY AllocConsoleReply; + CSRSS_SCREEN_BUFFER_INFO_REPLY ScreenBufferInfoReply; + CSRSS_READ_INPUT_REPLY ReadInputReply; + CSRSS_WRITE_CONSOLE_OUTPUT_CHAR_REPLY WriteConsoleOutputCharReply; + CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB_REPLY WriteConsoleOutputAttribReply; + CSRSS_GET_CURSOR_INFO_REPLY GetCursorInfoReply; + CSRSS_GET_CONSOLE_MODE_REPLY GetConsoleModeReply; + CSRSS_CREATE_SCREEN_BUFFER_REPLY CreateScreenBufferReply; + CSRSS_GET_TITLE_REPLY GetTitleReply; + CSRSS_WRITE_CONSOLE_OUTPUT_REPLY WriteConsoleOutputReply; + CSRSS_READ_CONSOLE_OUTPUT_CHAR_REPLY ReadConsoleOutputCharReply; + CSRSS_READ_CONSOLE_OUTPUT_ATTRIB_REPLY ReadConsoleOutputAttribReply; + CSRSS_GET_NUM_INPUT_EVENTS_REPLY GetNumInputEventsReply; + CSRSS_SHUTDOWN_PARAMETERS GetShutdownParametersReply; + CSRSS_PEEK_CONSOLE_INPUT_REPLY PeekConsoleInputReply; + } Data; +} CSRSS_API_REPLY, *PCSRSS_API_REPLY; + +#endif /* __INCLUDE_CSRSS_CSRSS_H */ diff --git a/include/ddk/ccfuncs.h b/include/ddk/ccfuncs.h new file mode 100644 index 0000000..57cd9a1 --- /dev/null +++ b/include/ddk/ccfuncs.h @@ -0,0 +1,328 @@ + +#ifndef _NTOS_CCFUNCS_H +#define _NTOS_CCFUNCS_H +/* $Id$ */ + +/* exported variables */ +/* +CcFastMdlReadWait +CcFastReadNotPossible +CcFastReadWait +*/ + +BOOLEAN +STDCALL +CcCanIWrite ( + IN PFILE_OBJECT FileObject, + IN ULONG BytesToWrite, + IN BOOLEAN Wait, + IN BOOLEAN Retrying + ); + +BOOLEAN +STDCALL +CcCopyRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus + ); + +BOOLEAN +STDCALL +CcCopyWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN PVOID Buffer + ); + +VOID +STDCALL +CcDeferWrite ( + IN PFILE_OBJECT FileObject, + IN PCC_POST_DEFERRED_WRITE PostRoutine, + IN PVOID Context1, + IN PVOID Context2, + IN ULONG BytesToWrite, + IN BOOLEAN Retrying + ); + +BOOLEAN +STDCALL +CcFastCopyRead ( + IN PFILE_OBJECT FileObject, + IN ULONG FileOffset, + IN ULONG Length, + IN ULONG PageCount, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus + ); + +BOOLEAN +STDCALL +CcFastCopyWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN PVOID Buffer + ); + +VOID +STDCALL +CcFlushCache ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER FileOffset OPTIONAL, + IN ULONG Length, + OUT PIO_STATUS_BLOCK IoStatus OPTIONAL + ); + +LARGE_INTEGER +STDCALL +CcGetDirtyPages ( + IN PVOID LogHandle, + IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine, + IN PVOID Context1, + IN PVOID Context2 + ); + +PFILE_OBJECT +STDCALL +CcGetFileObjectFromBcb ( + IN PVOID Bcb + ); + +PFILE_OBJECT +STDCALL +CcGetFileObjectFromSectionPtrs ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer + ); + +LARGE_INTEGER +STDCALL +CcGetLsnForFileObject ( + IN PFILE_OBJECT FileObject, + OUT PLARGE_INTEGER OldestLsn OPTIONAL + ); + +VOID +STDCALL +CcInitializeCacheMap ( + IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes, + IN BOOLEAN PinAccess, + IN PCACHE_MANAGER_CALLBACKS CallBacks, + IN PVOID LazyWriterContext + ); + +BOOLEAN +STDCALL +CcIsThereDirtyData ( + IN PVPB Vpb + ); + +BOOLEAN +STDCALL +CcMapData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID * Bcb, + OUT PVOID * Buffer + ); + +VOID +STDCALL +CcMdlRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT PMDL * MdlChain, + OUT PIO_STATUS_BLOCK IoStatus + ); + +VOID +STDCALL +CcMdlReadComplete ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain + ); + +VOID +STDCALL +CcMdlWriteComplete ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain + ); + +BOOLEAN +STDCALL +CcPinMappedData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID * Bcb + ); + +BOOLEAN +STDCALL +CcPinRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID * Bcb, + OUT PVOID * Buffer + ); + +VOID +STDCALL +CcPrepareMdlWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + OUT PMDL * MdlChain, + OUT PIO_STATUS_BLOCK IoStatus + ); + +BOOLEAN +STDCALL +CcPreparePinWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Zero, + IN BOOLEAN Wait, + OUT PVOID * Bcb, + OUT PVOID * Buffer + ); + +BOOLEAN +STDCALL +CcPurgeCacheSection ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER FileOffset OPTIONAL, + IN ULONG Length, + IN BOOLEAN UninitializeCacheMaps + ); + +#define CcReadAhead(FO,FOFF,LEN) \ +{ \ + if ((LEN) >= 256) \ + { \ + CcScheduleReadAhead((FO),(FOFF),(LEN)); \ + } \ +} + +VOID +STDCALL +CcRepinBcb ( + IN PVOID Bcb + ); + +VOID +STDCALL +CcScheduleReadAhead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length + ); + +VOID +STDCALL +CcSetAdditionalCacheAttributes ( + IN PFILE_OBJECT FileObject, + IN BOOLEAN DisableReadAhead, + IN BOOLEAN DisableWriteBehind + ); + +VOID +STDCALL +CcSetBcbOwnerPointer ( + IN PVOID Bcb, + IN PVOID Owner + ); + +VOID +STDCALL +CcSetDirtyPageThreshold ( + IN PFILE_OBJECT FileObject, + IN ULONG DirtyPageThreshold + ); + +VOID +STDCALL +CcSetDirtyPinnedData ( + IN PVOID Bcb, + IN PLARGE_INTEGER Lsn OPTIONAL + ); + +VOID +STDCALL +CcSetFileSizes ( + IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes + ); + +VOID +STDCALL +CcSetLogHandleForFile ( + IN PFILE_OBJECT FileObject, + IN PVOID LogHandle, + IN PFLUSH_TO_LSN FlushToLsnRoutine + ); + +VOID +STDCALL +CcSetReadAheadGranularity ( + IN PFILE_OBJECT FileObject, + IN ULONG Granularity + ); + +BOOLEAN +STDCALL +CcUninitializeCacheMap ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER TruncateSize OPTIONAL, + IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL + ); + +VOID +STDCALL +CcUnpinData ( + IN PVOID Bcb + ); + +VOID +STDCALL +CcUnpinDataForThread ( + IN PVOID Bcb, + IN ERESOURCE_THREAD ResourceThreadId + ); + +VOID +STDCALL +CcUnpinRepinnedBcb ( + IN PVOID Bcb, + IN BOOLEAN WriteThrough, + IN PIO_STATUS_BLOCK IoStatus + ); + +BOOLEAN +STDCALL +CcZeroData ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER StartOffset, + IN PLARGE_INTEGER EndOffset, + IN BOOLEAN Wait + ); + +#endif + +/* EOF */ diff --git a/include/ddk/cctypes.h b/include/ddk/cctypes.h new file mode 100644 index 0000000..bd3f0ac --- /dev/null +++ b/include/ddk/cctypes.h @@ -0,0 +1,86 @@ +#ifndef __INCLUDE_DDK_CCTYPES_H +#define __INCLUDE_DDK_CCTYPES_H + +typedef struct _CACHE_UNINITIALIZE_EVENT +{ + struct _CACHE_UNINITIALIZE_EVENT * Next; + KEVENT Event; +} CACHE_UNINITIALIZE_EVENT, *PCACHE_UNINITIALIZE_EVENT; + +typedef struct _CC_FILE_SIZES +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + LARGE_INTEGER ValidDataLength; +} CC_FILE_SIZES, *PCC_FILE_SIZES; + + +typedef VOID STDCALL +(*PCC_POST_DEFERRED_WRITE)(IN PVOID Context1, + IN PVOID Context2); + +typedef struct _PUBLIC_BCB +{ + CSHORT NodeTypeCode; + CSHORT NodeByteSize; + ULONG MappedLength; + LARGE_INTEGER MappedFileOffset; +} PUBLIC_BCB, *PPUBLIC_BCB; + +typedef VOID (*PDIRTY_PAGE_ROUTINE) ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN PLARGE_INTEGER OldestLsn, + IN PLARGE_INTEGER NewestLsn, + IN PVOID Context1, + IN PVOID Context2 +); + +typedef BOOLEAN STDCALL +(*PACQUIRE_FOR_LAZY_WRITE)(IN PVOID Context, + IN BOOLEAN Wait); + +typedef VOID STDCALL +(*PRELEASE_FROM_LAZY_WRITE)(IN PVOID Context); + +typedef BOOLEAN STDCALL +(*PACQUIRE_FOR_READ_AHEAD)(IN PVOID Context, + IN BOOLEAN Wait); + +typedef VOID STDCALL +(*PRELEASE_FROM_READ_AHEAD)(IN PVOID Context); + +typedef struct _CACHE_MANAGER_CALLBACKS +{ + PACQUIRE_FOR_LAZY_WRITE AcquireForLazyWrite; + PRELEASE_FROM_LAZY_WRITE ReleaseFromLazyWrite; + PACQUIRE_FOR_READ_AHEAD AcquireForReadAhead; + PRELEASE_FROM_READ_AHEAD ReleaseFromReadAhead; +} CACHE_MANAGER_CALLBACKS, *PCACHE_MANAGER_CALLBACKS; + +/* this is already defined in iotypes.h */ +/* +typedef struct _SECTION_OBJECT_POINTERS +{ + PVOID DataSectionObject; + PVOID SharedCacheMap; + PVOID ImageSectionObject; +} SECTION_OBJECT_POINTERS, *PSECTION_OBJECT_POINTERS; +*/ + +typedef VOID STDCALL +(*PFLUSH_TO_LSN)(IN PVOID LogHandle, + IN LARGE_INTEGER Lsn); + +typedef struct _REACTOS_COMMON_FCB_HEADER +{ + CSHORT NodeTypeCode; + CSHORT NodeByteSize; + struct _BCB* Bcb; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + LARGE_INTEGER ValidDataLength; +} REACTOS_COMMON_FCB_HEADER, *PREACTOS_COMMON_FCB_HEADER; + +#endif /* __INCLUDE_DDK_CCTYPES_H */ diff --git a/include/ddk/class2.h b/include/ddk/class2.h new file mode 100644 index 0000000..941b35a --- /dev/null +++ b/include/ddk/class2.h @@ -0,0 +1,216 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/include/class2.h + * PURPOSE: SCSI class driver definitions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +#ifndef __STORAGE_INCLUDE_CLASS2_H +#define __STORAGE_INCLUDE_CLASS2_H + +#include "ntddscsi.h" +#include "srb.h" + +#define MAXIMUM_RETRIES 4 + +struct _CLASS_INIT_DATA; + +typedef VOID STDCALL +(*PCLASS_ERROR)(IN PDEVICE_OBJECT DeviceObject, + IN PSCSI_REQUEST_BLOCK Srb, + IN OUT NTSTATUS *Status, + IN OUT BOOLEAN *Retry); + +typedef BOOLEAN STDCALL +(*PCLASS_DEVICE_CALLBACK)(IN PINQUIRYDATA); + +typedef NTSTATUS STDCALL +(*PCLASS_READ_WRITE)(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +typedef BOOLEAN STDCALL +(*PCLASS_FIND_DEVICES)(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN struct _CLASS_INIT_DATA *InitializationData, + IN PDEVICE_OBJECT PortDeviceObject, + IN ULONG PortNumber); + +typedef NTSTATUS STDCALL +(*PCLASS_DEVICE_CONTROL)(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +typedef NTSTATUS STDCALL +(*PCLASS_SHUTDOWN_FLUSH)(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +typedef NTSTATUS STDCALL +(*PCLASS_CREATE_CLOSE)(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +typedef struct _CLASS_INIT_DATA +{ + ULONG InitializationDataSize; + ULONG DeviceExtensionSize; + DEVICE_TYPE DeviceType; + ULONG DeviceCharacteristics; + PCLASS_ERROR ClassError; + PCLASS_READ_WRITE ClassReadWriteVerification; + PCLASS_DEVICE_CALLBACK ClassFindDeviceCallBack; + PCLASS_FIND_DEVICES ClassFindDevices; + PCLASS_DEVICE_CONTROL ClassDeviceControl; + PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush; + PCLASS_CREATE_CLOSE ClassCreateClose; + PDRIVER_STARTIO ClassStartIo; +} CLASS_INIT_DATA, *PCLASS_INIT_DATA; + + +typedef struct _DEVICE_EXTENSION +{ + PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT PortDeviceObject; + LARGE_INTEGER PartitionLength; + LARGE_INTEGER StartingOffset; + ULONG DMByteSkew; + ULONG DMSkew; + BOOLEAN DMActive; + PCLASS_ERROR ClassError; + PCLASS_READ_WRITE ClassReadWriteVerification; + PCLASS_FIND_DEVICES ClassFindDevices; + PCLASS_DEVICE_CONTROL ClassDeviceControl; + PCLASS_SHUTDOWN_FLUSH ClassShutdownFlush; + PCLASS_CREATE_CLOSE ClassCreateClose; + PDRIVER_STARTIO ClassStartIo; + PIO_SCSI_CAPABILITIES PortCapabilities; + PDISK_GEOMETRY DiskGeometry; + PDEVICE_OBJECT PhysicalDevice; + PSENSE_DATA SenseData; + ULONG TimeOutValue; + ULONG DeviceNumber; + ULONG SrbFlags; + ULONG ErrorCount; + KSPIN_LOCK SplitRequestSpinLock; + NPAGED_LOOKASIDE_LIST SrbLookasideListHead; + LONG LockCount; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR SectorShift; + UCHAR ReservedByte; + USHORT DeviceFlags; + PKEVENT MediaChangeEvent; + HANDLE MediaChangeEventHandle; + BOOLEAN MediaChangeNoMedia; + ULONG MediaChangeCount; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +ScsiClassAsynchronousCompletion(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context); + +VOID STDCALL +ScsiClassBuildRequest(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS STDCALL +ScsiClassClaimDevice(IN PDEVICE_OBJECT PortDeviceObject, + IN PSCSI_INQUIRY_DATA LunInfo, + IN BOOLEAN Release, + OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL); + +NTSTATUS STDCALL +ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, + IN PCCHAR ObjectNameBuffer, + IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, + IN OUT PDEVICE_OBJECT *DeviceObject, + IN PCLASS_INIT_DATA InitializationData); + +NTSTATUS STDCALL +ScsiClassDeviceControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +ULONG STDCALL +ScsiClassFindUnclaimedDevices(IN PCLASS_INIT_DATA InitializationData, + OUT PSCSI_ADAPTER_BUS_INFO AdapterInformation); + +NTSTATUS STDCALL +ScsiClassGetCapabilities(IN PDEVICE_OBJECT PortDeviceObject, + OUT PIO_SCSI_CAPABILITIES *PortCapabilities); + +NTSTATUS STDCALL +ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject, + OUT PSCSI_ADAPTER_BUS_INFO *ConfigInfo); + +ULONG STDCALL +ScsiClassInitialize(IN PVOID Argument1, + IN PVOID Argument2, + IN PCLASS_INIT_DATA InitializationData); + +VOID STDCALL +ScsiClassInitializeSrbLookasideList(PDEVICE_EXTENSION DeviceExtension, + ULONG NumberElements); + +NTSTATUS STDCALL +ScsiClassInternalIoControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +BOOLEAN STDCALL +ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + UCHAR MajorFunctionCode, + ULONG IoDeviceCode, + ULONG RetryCount, + NTSTATUS *Status); + +NTSTATUS STDCALL +ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +NTSTATUS STDCALL +ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +ULONG STDCALL +ScsiClassModeSense(PDEVICE_OBJECT DeviceObject, + CHAR ModeSenseBuffer, + ULONG Length, + UCHAR PageMode); + +ULONG STDCALL +ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath); + +NTSTATUS STDCALL +ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject); + +NTSTATUS STDCALL +ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PIRP Irp, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice); + +NTSTATUS STDCALL +ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, + PSCSI_REQUEST_BLOCK Srb, + PVOID BufferAddress, + ULONG BufferLength, + BOOLEAN WriteToDevice); + +VOID STDCALL +ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + ULONG MaximumBytes); + +#endif /* __STORAGE_INCLUDE_CLASS2_H */ + +/* EOF */ \ No newline at end of file diff --git a/include/ddk/cmfuncs.h b/include/ddk/cmfuncs.h new file mode 100644 index 0000000..fee65aa --- /dev/null +++ b/include/ddk/cmfuncs.h @@ -0,0 +1,47 @@ +/* + * FUNCTION: Creates a registry key + * ARGUMENTS: + * KeyHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the key + * It can have a combination of the following values: + * KEY_READ | KEY_WRITE | KEY_EXECUTE | KEY_ALL_ACCESS + * or + * KEY_QUERY_VALUE The values of the key can be queried. + * KEY_SET_VALUE The values of the key can be modified. + * KEY_CREATE_SUB_KEYS The key may contain subkeys. + * KEY_ENUMERATE_SUB_KEYS Subkeys can be queried. + * KEY_NOTIFY + * KEY_CREATE_LINK A symbolic link to the key can be created. + * ObjectAttributes = The name of the key may be specified directly in the name field + * of object attributes or relative to a key in rootdirectory. + * TitleIndex = Might specify the position in the sequential order of subkeys. + * Class = Specifies the kind of data, for example REG_SZ for string data. [ ??? ] + * CreateOptions = Specifies additional options with which the key is created + * REG_OPTION_VOLATILE The key is not preserved across boots. + * REG_OPTION_NON_VOLATILE The key is preserved accross boots. + * REG_OPTION_CREATE_LINK The key is a symbolic link to another key. + * REG_OPTION_BACKUP_RESTORE Key is being opened or created for backup/restore operations. + * Disposition = Indicates if the call to NtCreateKey resulted in the creation of a key it + * can have the following values: REG_CREATED_NEW_KEY | REG_OPENED_EXISTING_KEY + * RETURNS: + * Status + */ + +NTSTATUS STDCALL +NtCreateKey(OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class OPTIONAL, + IN ULONG CreateOptions, + IN PULONG Disposition OPTIONAL); + +NTSTATUS STDCALL +ZwCreateKey(OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class OPTIONAL, + IN ULONG CreateOptions, + IN PULONG Disposition OPTIONAL); + diff --git a/include/ddk/cmtypes.h b/include/ddk/cmtypes.h new file mode 100644 index 0000000..a9af321 --- /dev/null +++ b/include/ddk/cmtypes.h @@ -0,0 +1,100 @@ + +/* + * Object Manager structures and typedefs + */ + +/* + * key query information class + */ + +typedef enum _KEY_INFORMATION_CLASS +{ + KeyBasicInformation, + KeyNodeInformation, + KeyFullInformation +} KEY_INFORMATION_CLASS; + +typedef struct _KEY_BASIC_INFORMATION +{ + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG NameLength; + WCHAR Name[1]; +} KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; + +typedef struct _KEY_FULL_INFORMATION +{ + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG ClassOffset; + ULONG ClassLength; + ULONG SubKeys; + ULONG MaxNameLen; + ULONG MaxClassLen; + ULONG Values; + ULONG MaxValueNameLen; + ULONG MaxValueDataLen; + WCHAR Class[1]; +} KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION; + +typedef struct _KEY_NODE_INFORMATION +{ + LARGE_INTEGER LastWriteTime; + ULONG TitleIndex; + ULONG ClassOffset; + ULONG ClassLength; + ULONG NameLength; + WCHAR Name[1]; +} KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION; + +/* key set information class */ +/* + * KeyWriteTimeInformation + */ + +/* key value information class */ + +typedef enum _KEY_VALUE_INFORMATION_CLASS +{ + KeyValueBasicInformation, + KeyValueFullInformation, + KeyValuePartialInformation +} KEY_VALUE_INFORMATION_CLASS; + +typedef struct _KEY_VALUE_BASIC_INFORMATION +{ + ULONG TitleIndex; + ULONG Type; + ULONG NameLength; + WCHAR Name[1]; +} KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; + +typedef struct _KEY_VALUE_FULL_INFORMATION +{ + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; +} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; + +typedef struct _KEY_VALUE_PARTIAL_INFORMATION +{ + ULONG TitleIndex; + ULONG Type; + ULONG DataLength; + UCHAR Data[1]; +} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; + + +/* used by [Nt/Zw]QueryMultipleValueKey */ + +typedef struct _KEY_VALUE_ENTRY +{ + PUNICODE_STRING ValueName; + ULONG DataLength; + ULONG DataOffset; + ULONG Type; +} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY; + diff --git a/include/ddk/dbgfuncs.h b/include/ddk/dbgfuncs.h new file mode 100644 index 0000000..96dd2f6 --- /dev/null +++ b/include/ddk/dbgfuncs.h @@ -0,0 +1,23 @@ +#ifndef __INCLUDE_DDK_DBGFUNCS_H +#define __INCLUDE_DDK_DBGFUNCS_H +/* $Id$ */ + +#define DBG_STATUS_CONTROL_C 1 +#define DBG_STATUS_SYSRQ 2 +#define DBG_STATUS_BUGCHECK_FIRST 3 +#define DBG_STATUS_BUGCHECK_SECOND 4 +#define DBG_STATUS_FATAL 5 +VOID STDCALL DbgBreakPointWithStatus (ULONG Status); +VOID STDCALL DbgBreakPoint(VOID); +ULONG DbgPrint(PCH Format,...); +VOID STDCALL DbgPrompt (PCH OutputString, PCH InputString, USHORT InputSize); + + +#define DBG_GET_SHOW_FACILITY 0x0001 +#define DBG_GET_SHOW_SEVERITY 0x0002 +#define DBG_GET_SHOW_ERRCODE 0x0004 +#define DBG_GET_SHOW_ERRTEXT 0x0008 +VOID DbgGetErrorText(NTSTATUS ErrorCode, PUNICODE_STRING ErrorText, ULONG Flags); +VOID DbgPrintErrorMessage(NTSTATUS ErrorCode); + +#endif /* __INCLUDE_DDK_DBGFUNCS_H */ diff --git a/include/ddk/defines.h b/include/ddk/defines.h new file mode 100644 index 0000000..ea65d82 --- /dev/null +++ b/include/ddk/defines.h @@ -0,0 +1,234 @@ +#ifndef _DDK_DEFINES_H +#define _DDK_DEFINES_H + +/* GENERAL DEFINITIONS ****************************************************/ + +#ifndef __ASM__ + +#define _WIN32_WINNT 0x0400 + +#include +#include + +#define EXPORTED __declspec(dllexport) +#define IMPORTED __declspec(dllimport) + +/* + * PURPOSE: Number of a thread priority levels + */ +#define NR_PRIORITY_LEVELS (32) + +/* + * PURPOSE: Type of queue to insert a work item in + */ +enum +{ + CriticalWorkQueue, + DelayedWorkQueue, + HyperCriticalWorkQueue, +}; + +/* + * Types of memory to allocate + */ +enum +{ + NonPagedPool, + NonPagedPoolMustSucceed, + NonPagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS, + PagedPool, + PagedPoolCacheAligned, +}; + +/* + * This is a list of bug check types (not MS's) + */ +enum +{ + APC_INDEX_MISMATCH = 1, + DEVICE_QUEUE_NOT_BUSY, + INVALID_AFFINITY_SET, + INVALID_DATA_ACCESS_TRAP, + INVALID_PROCESS_ATTACH_ATTEMPT, + INVALID_PROCESS_DEATTACH_ATTEMPT, + INVALID_SOFTWARE_INTERRUPT, + IRQL_NOT_DISPATCH_LEVEL, + IRQL_NOT_GREATER_OR_EQUAL, + NO_EXCEPTION_HANDLING_SUPPORT, + MAXIMUM_WAIT_OBJECTS_EXCEEDED, + MUTEX_LEVEL_NUMBER_VIOLATION, + NO_USER_MODE_CONTEXT, + SPIN_LOCK_ALREADY_OWNED, + SPIN_LOCK_NOT_OWNED, + THREAD_NOT_MUTEX_OWNER, + TRAP_CAUSE_UNKNOWN, + EMPTY_THREAD_REAPER_LIST, + CREATE_DELETE_LOCK_NOT_LOCKED, + LAST_CHANCE_CALLED_FROM_KMODE, + CID_HANDLE_CREATION, + CID_HANDLE_DELETION, + REFERENCE_BY_POINTER, + BAD_POOL_HEADER, + MEMORY_MANAGMENT, + PFN_SHARE_COUNT, + PFN_REFERENCE_COUNT, + NO_SPIN_LOCK_AVAILABLE, + KMODE_EXCEPTION_NOT_HANDLED, + SHARED_RESOURCE_CONV_ERROR, + KERNEL_APC_PENDING_DURING_EXIT, + QUOTA_UNDERFLOW, + FILE_SYSTEM, + FAT_FILE_SYSTEM, + NTFS_FILE_SYSTEM, + NPFS_FILE_SYSTEM, + CDFS_FILE_SYSTEM, + RDR_FILE_SYSTEM, + CORRUPT_ACCESS_TOKEN, + SECURITY_SYSTEM, + INCONSISTENT_IRP, + PANIC_STACK_SWITCH, + PORT_DRIVER_INTERNAL, + SCSI_DISK_DRIVER_INTERNAL, + INSTRUCTION_BUS_ERROR, + SET_OF_INVALID_CONTEXT, + PHASE0_INITIALIZATION_FAILED, + PHASE1_INITIALIZATION_FAILED, + UNEXPECTED_INITIALIZATION_CALL, + CACHE_MANAGER, + NO_MORE_IRP_STACK_LOCATIONS, + DEVICE_REFERENCE_COUNT_NOT_ZERO, + FLOPPY_INTERNAL_ERROR, + SERIAL_DRIVER_INTERNAL, + SYSTEM_EXIT_OWNED_MUTEX, + SYSTEM_UNWIND_PREVIOUS_USER, + SYSTEN_SERVICE_EXCEPTION, + INTERRUPT_UNWIND_ATTEMPTED, + INTERRUPT_EXCEPTION_NOT_HANDLED, + MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, + NO_MORE_SYSTEM_PTES, + TARGET_MDL_TOO_SMALL, + MUST_SUCCEED_POOL_EMPTY, + ATDISK_DRIVER_INTERNAL, + NO_SUCH_PARTITION, + MULTIPLE_IRP_COMPLETE_REQUESTS, + INSUFFICENT_SYSTEM_MAP_PAGES, + DEREF_UNKNOWN_LOGON_SERVICE, + REF_UNKNOWN_LOGON_SERVICE, + CANCEL_STATE_IN_COMPLETED_IRP, + PAGE_FAULT_WITH_INTERRUPTS_OFF, + IRQL_GT_ZERO_AT_SYSTEM_SERVICE, + STREAMS_INTERNAL_ERROR, + FATAL_UNHANDLED_HARD_ERROR, + NO_PAGES_AVAILABLE, + PFN_LIST_CORRUPT, + NDIS_INTERNAL_ERROR, + PAGE_FAULT_IN_NONPAGED_AREA, + REGISTRY_ERROR, + MAILSLOT_FILE_SYSTEM, + NO_BOOT_DEVICE, + LM_SERVER_INTERNAL_ERROR, + DATA_COHERENCY_EXCEPTION, + INSTRUCTION_COHERENCY_EXCEPTION, + XNS_INTERNAL_ERROR, + FTDISK_INTERNAL_ERROR, + PINBALL_FILE_SYSTEM, + CRITICAL_SERVICE_FAILED, + SET_ENV_VAR_FAILED, + HAL_INITIALIZED_FAILED, + UNSUPPORTED_PROCESSOR, + OBJECT_INITIALIZATION_FAILED, + SECURITY_INITIALIZATION_FAILED, + PROCESS_INITIALIZATION_FAILED, + HAL1_INITIALIZATION_FAILED, +}; +enum +{ + KBUG_NONE, + KBUG_ORPHANED_IRP, + KBUG_IO_STACK_OVERFLOW, + KBUG_OUT_OF_MEMORY, + KBUG_POOL_FREE_LIST_CORRUPT, + + /* + * These are well known but the actual value is unknown + */ +// NO_PAGES_AVAILABLE, + + /* + * These are well known (MS) bug types + * (Reference: NT Insider 1997 - http://www.osr.com) + */ + IRQL_NOT_LESS_OR_EQUAL = 0xa, +// KMODE_EXCEPTION_NOT_HANDLED = 0x1e, + UNEXPECTED_KERNEL_MODE_TRAP = 0x7f, + PAGE_FAULT_IN_NON_PAGED_AREA = 0x50, +}; + +/* + * PURPOSE: Object attributes + */ +enum +{ + OBJ_INHERIT = 0x2, + OBJ_PERMANENT = 0x10, + OBJ_EXCLUSIVE = 0x20, + OBJ_CASE_INSENSITIVE = 0x40, + OBJ_OPENIF = 0x80, + OBJ_OPENLINK = 0x100, + OBJ_VALID_ATTRIBUTES = 0x1F2, +}; + +/* + * PURPOSE: Timer types + */ +enum + { + NotificationTimer, + SynchronizationTimer, + }; + +/* + * PURPOSE: Some drivers use these + */ +#ifndef IN +#define IN +#define OUT +#define OPTIONAL +#endif + +/* + * PURPOSE: Arguments to MmProbeAndLockPages + */ +enum +{ + IoReadAccess, + IoWriteAccess, + IoModifyAccess, +}; + +#define MAXIMUM_VOLUME_LABEL_LENGTH (32) + +#include + +#define PASSIVE_LEVEL 0 // Passive release level +#define LOW_LEVEL 0 // Lowest interrupt level +#define APC_LEVEL 1 // APC interrupt level +#define DISPATCH_LEVEL 2 // Dispatcher level +/* timer used for profiling */ +#define PROFILE_LEVEL 27 +/* Interval clock 1 level - Not used on x86 */ +#define CLOCK1_LEVEL 28 +#define CLOCK2_LEVEL 28 // Interval clock 2 level +#define IPI_LEVEL 29 // Interprocessor interrupt level +#define POWER_LEVEL 30 // Power failure level +#define HIGH_LEVEL 31 // Highest interrupt level +#define SYNCH_LEVEL (IPI_LEVEL-1) // synchronization level + +#endif /* __ASM__ */ + +/* Values returned by KeGetPreviousMode() */ +#define KernelMode (0) +#define UserMode (1) + +#endif /* ndef _DDK_DEFINES_H */ diff --git a/include/ddk/exfuncs.h b/include/ddk/exfuncs.h new file mode 100644 index 0000000..fc13a68 --- /dev/null +++ b/include/ddk/exfuncs.h @@ -0,0 +1,912 @@ +#ifndef _NTOS_EXFUNCS_H +#define _NTOS_EXFUNCS_H + +/* EXECUTIVE ROUTINES ******************************************************/ + +#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) + +VOID +FASTCALL +ExAcquireFastMutex ( + PFAST_MUTEX FastMutex + ); +VOID +FASTCALL +ExAcquireFastMutexUnsafe ( + PFAST_MUTEX FastMutex + ); +BOOLEAN +STDCALL +ExAcquireResourceExclusive ( + PERESOURCE Resource, + BOOLEAN Wait + ); +BOOLEAN +STDCALL +ExAcquireResourceExclusiveLite ( + PERESOURCE Resource, + BOOLEAN Wait + ); +BOOLEAN +STDCALL +ExAcquireResourceSharedLite ( + PERESOURCE Resource, + BOOLEAN Wait + ); +BOOLEAN +STDCALL +ExAcquireSharedStarveExclusive ( + PERESOURCE Resource, + BOOLEAN Wait + ); +BOOLEAN +STDCALL +ExAcquireSharedWaitForExclusive ( + PERESOURCE Resource, + BOOLEAN Wait + ); + +PVOID +STDCALL +ExAllocateFromZone ( + PZONE_HEADER Zone + ); + +/* + * PVOID + * ExAllocateFromZone ( + * PZONE_HEADER Zone + * ); + * + * FUNCTION: + * Allocate a block from a zone + * + * ARGUMENTS: + * Zone = Zone to allocate from + * + * RETURNS: + * The base address of the block allocated + */ +#define ExAllocateFromZone(Zone) \ + (PVOID)((Zone)->FreeList.Next); \ + if ((Zone)->FreeList.Next) \ + (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next + +/* + * FUNCTION: Allocates memory from the nonpaged pool + * ARGUMENTS: + * NumberOfBytes = minimum size of the block to be allocated + * PoolType = the type of memory to use for the block (ignored) + * RETURNS: + * the address of the block if it succeeds + */ +PVOID +STDCALL +ExAllocatePool ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes + ); + +PVOID +STDCALL +ExAllocatePoolWithQuota ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes + ); +PVOID +STDCALL +ExAllocatePoolWithQuotaTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag + ); +PVOID +STDCALL +ExAllocatePoolWithTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag + ); + +VOID +STDCALL +ExConvertExclusiveToSharedLite ( + PERESOURCE Resource + ); + +NTSTATUS +STDCALL +ExCreateCallback ( + OUT PCALLBACK_OBJECT * CallbackObject, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN Create, + IN BOOLEAN AllowMultipleCallbacks + ); + +NTSTATUS +STDCALL +ExDeleteResource ( + PERESOURCE Resource + ); +NTSTATUS +STDCALL +ExDeleteResourceLite ( + PERESOURCE Resource + ); + +VOID +STDCALL +ExDisableResourceBoostLite ( + PERESOURCE Resource + ); + +NTSTATUS +STDCALL +ExExtendZone ( + PZONE_HEADER Zone, + PVOID Segment, + ULONG SegmentSize + ); + +/* + * FUNCTION: Releases previously allocated memory + * ARGUMENTS: + * block = block to free + */ +VOID +STDCALL +ExFreePool ( + PVOID block + ); + +/* + * PVOID + * ExFreeToZone ( + * PZONE_HEADER Zone, + * PVOID Block + * ); + * + * FUNCTION: + * Frees a block from a zone + * + * ARGUMENTS: + * Zone = Zone the block was allocated from + * Block = Block to free + */ +#define ExFreeToZone(Zone,Block) \ + (((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next, \ + (Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block)), \ + ((PSINGLE_LIST_ENTRY)(Block))->Next) + +/* + * ERESOURCE_THREAD + * ExGetCurrentResourceThread ( + * VOID + * ); + */ +#define ExGetCurrentResourceThread() \ + ((ERESOURCE_THREAD)PsGetCurrentThread()) + +ULONG +STDCALL +ExGetExclusiveWaiterCount ( + PERESOURCE Resource + ); + +ULONG +STDCALL +ExGetPreviousMode ( + VOID + ); + +ULONG +STDCALL +ExGetSharedWaiterCount ( + PERESOURCE Resource + ); + +/* + * VOID + * ExInitializeFastMutex ( + * PFAST_MUTEX FastMutex + * ); + */ +#define ExInitializeFastMutex(_FastMutex) \ + ((PFAST_MUTEX)_FastMutex)->Count = 1; \ + ((PFAST_MUTEX)_FastMutex)->Owner = NULL; \ + ((PFAST_MUTEX)_FastMutex)->Contention = 0; \ + KeInitializeEvent(&((PFAST_MUTEX)_FastMutex)->Event, \ + SynchronizationEvent, \ + FALSE); + +NTSTATUS +STDCALL +ExInitializeResource ( + PERESOURCE Resource + ); +NTSTATUS +STDCALL +ExInitializeResourceLite ( + PERESOURCE Resource + ); + +/* + * VOID + * ExInitializeSListHead ( + * PSLIST_HEADER SListHead + * ); + */ +#define ExInitializeSListHead(ListHead) \ + (ListHead)->Alignment = 0 + +/* + * VOID + * ExInitializeWorkItem ( + * PWORK_QUEUE_ITEM Item, + * PWORKER_THREAD_ROUTINE Routine, + * PVOID Context + * ); + * + * FUNCTION: + * Initializes a work item to be processed by one of the system + * worker threads + * + * ARGUMENTS: + * Item = Pointer to the item to be initialized + * Routine = Routine to be called by the worker thread + * Context = Parameter to be passed to the callback + */ +#define ExInitializeWorkItem(Item, WorkerRoutine, RoutineContext) \ + ASSERT_IRQL(DISPATCH_LEVEL); \ + (Item)->Routine = (WorkerRoutine); \ + (Item)->Context = (RoutineContext); \ + (Item)->Entry.Flink = NULL; \ + (Item)->Entry.Blink = NULL; + +NTSTATUS +STDCALL +ExInitializeZone ( + PZONE_HEADER Zone, + ULONG BlockSize, + PVOID InitialSegment, + ULONG InitialSegmentSize + ); + +LARGE_INTEGER +STDCALL +ExInterlockedAddLargeInteger ( + PLARGE_INTEGER Addend, + LARGE_INTEGER Increment, + PKSPIN_LOCK Lock + ); + +VOID +FASTCALL +ExInterlockedAddLargeStatistic ( + IN PLARGE_INTEGER Addend, + IN ULONG Increment + ); + +ULONG +STDCALL +ExInterlockedAddUlong ( + PULONG Addend, + ULONG Increment, + PKSPIN_LOCK Lock + ); + +/* + * PVOID + * STDCALL + * ExInterlockedAllocateFromZone ( + * PZONE_HEADER Zone, + * PKSPIN_LOCK Lock + * ); + */ +#define ExInterlockedAllocateFromZone(Zone,Lock) \ + (PVOID)ExInterlockedPopEntryList(&(Zone)->FreeList,Lock) + +LONGLONG +FASTCALL +ExInterlockedCompareExchange64 ( + IN OUT PLONGLONG Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand, + IN PKSPIN_LOCK Lock + ); + +INTERLOCKED_RESULT +STDCALL +ExInterlockedDecrementLong ( + PLONG Addend, + PKSPIN_LOCK Lock + ); +ULONG +STDCALL +ExInterlockedExchangeUlong ( + PULONG Target, + ULONG Value, + PKSPIN_LOCK Lock + ); +NTSTATUS +STDCALL +ExInterlockedExtendZone ( + PZONE_HEADER Zone, + PVOID Segment, + ULONG SegmentSize, + PKSPIN_LOCK Lock + ); + +/* + * PVOID + * ExInterlockedFreeToZone ( + * PZONE_HEADER Zone, + * PVOID Block, + * PKSPIN_LOCK Lock + * ); + */ +#define ExInterlockedFreeToZone(Zone,Block,Lock) \ + ExInterlockedPushEntryList(&(Zone)->FreeList,((PSINGLE_LIST_ENTRY)(Block)),(Lock)) + +INTERLOCKED_RESULT +STDCALL +ExInterlockedIncrementLong ( + PLONG Addend, + PKSPIN_LOCK Lock + ); +PLIST_ENTRY +STDCALL +ExInterlockedInsertHeadList ( + PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock + ); +PLIST_ENTRY +STDCALL +ExInterlockedInsertTailList ( + PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock + ); +PSINGLE_LIST_ENTRY +STDCALL +ExInterlockedPopEntryList ( + PSINGLE_LIST_ENTRY ListHead, + PKSPIN_LOCK Lock + ); +PSINGLE_LIST_ENTRY +FASTCALL +ExInterlockedPopEntrySList ( + PSLIST_HEADER ListHead, + PKSPIN_LOCK Lock + ); +PSINGLE_LIST_ENTRY +STDCALL +ExInterlockedPushEntryList ( + PSINGLE_LIST_ENTRY ListHead, + PSINGLE_LIST_ENTRY ListEntry, + PKSPIN_LOCK Lock + ); +PSINGLE_LIST_ENTRY +FASTCALL +ExInterlockedPushEntrySList ( + PSLIST_HEADER ListHead, + PSINGLE_LIST_ENTRY ListEntry, + PKSPIN_LOCK Lock + ); + +VOID +ExInterlockedRemoveEntryList ( + PLIST_ENTRY ListHead, + PLIST_ENTRY Entry, + PKSPIN_LOCK Lock + ); + +PLIST_ENTRY +STDCALL +ExInterlockedRemoveHeadList ( + PLIST_ENTRY Head, + PKSPIN_LOCK Lock + ); + +/* + * BOOLEAN + * ExIsFullZone ( + * PZONE_HEADER Zone + * ); + */ +#define ExIsFullZone(Zone) \ + ((Zone)->FreeList.Next==(PSINGLE_LIST_ENTRY)NULL) + +/* + * BOOLEAN + * ExIsObjectInFirstZoneSegment ( + * PZONE_HEADER Zone, + * PVOID Object + * ); + */ +#define ExIsObjectInFirstZoneSegment(Zone,Object) \ + (((PUCHAR)(Object)>=(PUCHAR)(Zone)->SegmentList.Next) && \ + ((PUCHAR)(Object)<(PUCHAR)(Zone)->SegmentList.Next+(Zone)->TotalSegmentSize)) + +BOOLEAN +STDCALL +ExIsProcessorFeaturePresent ( + IN ULONG ProcessorFeature + ); + +BOOLEAN +STDCALL +ExIsResourceAcquiredExclusiveLite ( + PERESOURCE Resource + ); + +ULONG +STDCALL +ExIsResourceAcquiredSharedLite ( + PERESOURCE Resource + ); + +VOID +STDCALL +ExLocalTimeToSystemTime ( + PLARGE_INTEGER LocalTime, + PLARGE_INTEGER SystemTime + ); + +VOID +STDCALL +ExNotifyCallback ( + IN PVOID CallbackObject, + IN PVOID Argument1, + IN PVOID Argument2 + ); + +VOID +STDCALL +ExPostSystemEvent ( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3 + ); + +/* + * USHORT + * ExQueryDepthSList ( + * PSLIST_HEADER SListHead + * ); + */ +#define ExQueryDepthSList(ListHead) \ + (USHORT)(ListHead)->s.Depth + +VOID +STDCALL +ExQueueWorkItem ( + PWORK_QUEUE_ITEM WorkItem, + WORK_QUEUE_TYPE QueueType + ); +VOID +STDCALL +ExRaiseAccessViolation ( + VOID + ); +VOID +STDCALL +ExRaiseDatatypeMisalignment ( + VOID + ); +VOID +STDCALL +ExRaiseStatus ( + NTSTATUS Status + ); + +PVOID +STDCALL +ExRegisterCallback ( + IN PCALLBACK_OBJECT CallbackObject, + IN PCALLBACK_FUNCTION CallbackFunction, + IN PVOID CallbackContext + ); + +VOID +STDCALL +ExReinitializeResourceLite ( + PERESOURCE Resource + ); +/* ReactOS Specific: begin */ +VOID +FASTCALL +ExReleaseFastMutex ( + PFAST_MUTEX Mutex + ); +/* ReactOS Specific: end */ +VOID +FASTCALL +ExReleaseFastMutexUnsafe ( + PFAST_MUTEX Mutex + ); +/* +VOID +STDCALL +ExReleaseResource ( + PERESOURCE Resource + ); +*/ +#define ExReleaseResource(Resource) \ + (ExReleaseResourceLite (Resource)) + +VOID +FASTCALL +ExReleaseResourceLite ( + PERESOURCE Resource + ); +VOID +STDCALL +ExReleaseResourceForThread ( + PERESOURCE Resource, + ERESOURCE_THREAD ResourceThreadId + ); +VOID +STDCALL +ExReleaseResourceForThreadLite ( + PERESOURCE Resource, + ERESOURCE_THREAD ResourceThreadId + ); + +VOID +STDCALL +ExSetResourceOwnerPointer ( + IN PERESOURCE Resource, + IN PVOID OwnerPointer + ); + +VOID +STDCALL +ExSystemTimeToLocalTime ( + PLARGE_INTEGER SystemTime, + PLARGE_INTEGER LocalTime + ); + +BOOLEAN +FASTCALL +ExTryToAcquireFastMutex ( + PFAST_MUTEX FastMutex + ); + +BOOLEAN +STDCALL +ExTryToAcquireResourceExclusiveLite ( + PERESOURCE Resource + ); + +VOID +STDCALL +ExUnregisterCallback ( + IN PVOID CallbackRegistration + ); + + +/* + * PVOID + * ExAllocateFromNPagedLookasideList ( + * PNPAGED_LOOKASIDE_LIST LookSide + * ); + * + * FUNCTION: + * Removes (pops) the first entry from the specified nonpaged + * lookaside list. + * + * ARGUMENTS: + * Lookaside = Pointer to a nonpaged lookaside list + * + * RETURNS: + * Address of the allocated list entry + */ +static +inline +PVOID +ExAllocateFromNPagedLookasideList ( + IN PNPAGED_LOOKASIDE_LIST Lookaside + ) +{ + PVOID Entry; + + Lookaside->TotalAllocates++; + Entry = ExInterlockedPopEntrySList (&Lookaside->ListHead, + &Lookaside->Lock); + if (Entry == NULL) + { + Lookaside->AllocateMisses++; + Entry = (Lookaside->Allocate)(Lookaside->Type, + Lookaside->Size, + Lookaside->Tag); + } + + return Entry; +} + +PVOID +STDCALL +ExAllocateFromPagedLookasideList ( + PPAGED_LOOKASIDE_LIST LookSide + ); + +VOID +STDCALL +ExDeleteNPagedLookasideList ( + PNPAGED_LOOKASIDE_LIST Lookaside + ); + +VOID +STDCALL +ExDeletePagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside + ); + + +/* + * VOID + * ExFreeToNPagedLookasideList ( + * PNPAGED_LOOKASIDE_LIST Lookaside, + * PVOID Entry + * ); + * + * FUNCTION: + * Inserts (pushes) the specified entry into the specified + * nonpaged lookaside list. + * + * ARGUMENTS: + * Lookaside = Pointer to the nonpaged lookaside list + * Entry = Pointer to the entry that is inserted in the lookaside list + */ +static +inline +VOID +ExFreeToNPagedLookasideList ( + IN PNPAGED_LOOKASIDE_LIST Lookaside, + IN PVOID Entry + ) +{ + Lookaside->TotalFrees++; + if (ExQueryDepthSList (&Lookaside->ListHead) >= Lookaside->MinimumDepth) + { + Lookaside->FreeMisses++; + (Lookaside->Free)(Entry); + } + else + { + ExInterlockedPushEntrySList (&Lookaside->ListHead, + (PSINGLE_LIST_ENTRY)Entry, + &Lookaside->Lock); + } +} + +VOID +STDCALL +ExFreeToPagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside, + PVOID Entry + ); + +VOID +STDCALL +ExInitializeNPagedLookasideList ( + PNPAGED_LOOKASIDE_LIST Lookaside, + PALLOCATE_FUNCTION Allocate, + PFREE_FUNCTION Free, + ULONG Flags, + ULONG Size, + ULONG Tag, + USHORT Depth + ); + +VOID +STDCALL +ExInitializePagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside, + PALLOCATE_FUNCTION Allocate, + PFREE_FUNCTION Free, + ULONG Flags, + ULONG Size, + ULONG Tag, + USHORT Depth + ); + +ULONG FASTCALL +ExfInterlockedAddUlong(IN PULONG Addend, + IN ULONG Increment, + IN PKSPIN_LOCK Lock); + +PLIST_ENTRY FASTCALL +ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock); + +PLIST_ENTRY FASTCALL +ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock); + +PSINGLE_LIST_ENTRY FASTCALL +ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, + IN PKSPIN_LOCK Lock); + +PSINGLE_LIST_ENTRY FASTCALL +ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock); + +PLIST_ENTRY FASTCALL +ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head, + IN PKSPIN_LOCK Lock); + +INTERLOCKED_RESULT FASTCALL +Exfi386InterlockedIncrementLong(IN PLONG Addend); + +INTERLOCKED_RESULT FASTCALL +Exfi386InterlockedDecrementLong(IN PLONG Addend); + +ULONG FASTCALL +Exfi386InterlockedExchangeUlong(IN PULONG Target, + IN ULONG Value); + +INTERLOCKED_RESULT STDCALL +Exi386InterlockedIncrementLong(IN PLONG Addend); + +INTERLOCKED_RESULT STDCALL +Exi386InterlockedDecrementLong(IN PLONG Addend); + +ULONG STDCALL +Exi386InterlockedExchangeUlong(IN PULONG Target, + IN ULONG Value); + + +LONG +FASTCALL +InterlockedCompareExchange ( + PLONG Destination, + LONG Exchange, + LONG Comperand + ); + +#ifdef _GNU_H_WINDOWS_H +#ifdef InterlockedDecrement +#undef InterlockedDecrement +#undef InterlockedExchange +#undef InterlockedExchangeAdd +#undef InterlockedIncrement +#endif /* def InterlockedDecrement */ +#endif /* def _GNU_H_WINDOWS_H */ +LONG +FASTCALL +InterlockedDecrement ( + PLONG Addend + ); +LONG +FASTCALL +InterlockedExchange ( + PLONG Target, + LONG Value + ); +LONG +FASTCALL +InterlockedExchangeAdd ( + PLONG Addend, + LONG Value + ); +LONG +FASTCALL +InterlockedIncrement ( + PLONG Addend + ); + +/*---*/ + +typedef +unsigned int +(exception_hook) ( + CONTEXT * c, + unsigned int exp + ); +unsigned int +ExHookException ( + exception_hook fn, + unsigned int exp + ); + +/* BEGIN REACTOS ONLY */ + +BOOLEAN STDCALL +ExInitializeBinaryTree(IN PBINARY_TREE Tree, + IN PKEY_COMPARATOR Compare, + IN BOOLEAN UseNonPagedPool); + +VOID STDCALL +ExDeleteBinaryTree(IN PBINARY_TREE Tree); + +VOID STDCALL +ExInsertBinaryTree(IN PBINARY_TREE Tree, + IN PVOID Key, + IN PVOID Value); + +BOOLEAN STDCALL +ExSearchBinaryTree(IN PBINARY_TREE Tree, + IN PVOID Key, + OUT PVOID * Value); + +BOOLEAN STDCALL +ExRemoveBinaryTree(IN PBINARY_TREE Tree, + IN PVOID Key, + IN PVOID * Value); + +BOOLEAN STDCALL +ExTraverseBinaryTree(IN PBINARY_TREE Tree, + IN TRAVERSE_METHOD Method, + IN PTRAVERSE_ROUTINE Routine, + IN PVOID Context); + +BOOLEAN STDCALL +ExInitializeSplayTree(IN PSPLAY_TREE Tree, + IN PKEY_COMPARATOR Compare, + IN BOOLEAN Weighted, + IN BOOLEAN UseNonPagedPool); + +VOID STDCALL +ExDeleteSplayTree(IN PSPLAY_TREE Tree); + +VOID STDCALL +ExInsertSplayTree(IN PSPLAY_TREE Tree, + IN PVOID Key, + IN PVOID Value); + +BOOLEAN STDCALL +ExSearchSplayTree(IN PSPLAY_TREE Tree, + IN PVOID Key, + OUT PVOID * Value); + +BOOLEAN STDCALL +ExRemoveSplayTree(IN PSPLAY_TREE Tree, + IN PVOID Key, + IN PVOID * Value); + +BOOLEAN STDCALL +ExWeightOfSplayTree(IN PSPLAY_TREE Tree, + OUT PULONG Weight); + +BOOLEAN STDCALL +ExTraverseSplayTree(IN PSPLAY_TREE Tree, + IN TRAVERSE_METHOD Method, + IN PTRAVERSE_ROUTINE Routine, + IN PVOID Context); + +BOOLEAN STDCALL +ExInitializeHashTable(IN PHASH_TABLE HashTable, + IN ULONG HashTableSize, + IN PKEY_COMPARATOR Compare OPTIONAL, + IN BOOLEAN UseNonPagedPool); + +VOID STDCALL +ExDeleteHashTable(IN PHASH_TABLE HashTable); + +VOID STDCALL +ExInsertHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + IN PVOID Value); + +BOOLEAN STDCALL +ExSearchHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + OUT PVOID * Value); + +BOOLEAN STDCALL +ExRemoveHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + IN PVOID * Value); + +/* END REACTOS ONLY */ + +#endif /* ndef _NTOS_EXFUNCS_H */ diff --git a/include/ddk/extypes.h b/include/ddk/extypes.h new file mode 100644 index 0000000..ee53a99 --- /dev/null +++ b/include/ddk/extypes.h @@ -0,0 +1,238 @@ +/* $Id$ */ + +#ifndef __INCLUDE_DDK_EXTYPES_H +#define __INCLUDE_DDK_EXTYPES_H + +#ifdef __NTOSKRNL__ +extern POBJECT_TYPE EXPORTED ExDesktopObjectType; +extern POBJECT_TYPE EXPORTED ExEventObjectType; +extern POBJECT_TYPE EXPORTED ExWindowStationObjectType; +#else +extern POBJECT_TYPE IMPORTED ExDesktopObjectType; +extern POBJECT_TYPE IMPORTED ExEventObjectType; +extern POBJECT_TYPE IMPORTED ExWindowStationObjectType; +#endif + +typedef ULONG INTERLOCKED_RESULT; +typedef ULONG WORK_QUEUE_TYPE; + +typedef ULONG ERESOURCE_THREAD, *PERESOURCE_THREAD; + +typedef struct _OWNER_ENTRY +{ + ERESOURCE_THREAD OwnerThread; + union + { + LONG OwnerCount; + ULONG TableSize; + } a; +} OWNER_ENTRY, *POWNER_ENTRY; + +typedef struct _ERESOURCE +{ + LIST_ENTRY SystemResourcesList; + POWNER_ENTRY OwnerTable; + SHORT ActiveCount; + USHORT Flag; + PKSEMAPHORE SharedWaiters; + PKEVENT ExclusiveWaiters; + OWNER_ENTRY OwnerThreads[2]; + ULONG ContentionCount; + USHORT NumberOfSharedWaiters; + USHORT NumberOfExclusiveWaiters; + union + { + PVOID Address; + ULONG CreatorBackTraceIndex; + } a; + KSPIN_LOCK SpinLock; +} ERESOURCE, *PERESOURCE; + + +typedef struct +{ + LONG Count; + struct _KTHREAD* Owner; + ULONG Contention; + KEVENT Event; + ULONG OldIrql; +} FAST_MUTEX, *PFAST_MUTEX; + +typedef struct _ZONE_HEADER +{ + SINGLE_LIST_ENTRY FreeList; + SINGLE_LIST_ENTRY SegmentList; + ULONG BlockSize; + ULONG TotalSegmentSize; +} ZONE_HEADER, *PZONE_HEADER; + +typedef struct _ZONE_SEGMENT +{ + SINGLE_LIST_ENTRY Entry; + ULONG size; +} ZONE_SEGMENT, *PZONE_SEGMENT; + +typedef struct _ZONE_ENTRY +{ + SINGLE_LIST_ENTRY Entry; +} ZONE_ENTRY, *PZONE_ENTRY; + + +typedef VOID STDCALL +(*PWORKER_THREAD_ROUTINE)(PVOID Parameter); + +typedef struct _WORK_QUEUE_ITEM +{ + LIST_ENTRY Entry; + PWORKER_THREAD_ROUTINE Routine; + PVOID Context; +} WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM; + +typedef PVOID STDCALL +(*PALLOCATE_FUNCTION)(POOL_TYPE PoolType, + ULONG NumberOfBytes, + ULONG Tag); + +typedef VOID STDCALL +(*PFREE_FUNCTION)(PVOID Buffer); + +typedef union _SLIST_HEADER +{ + ULONGLONG Alignment; + struct + { + SINGLE_LIST_ENTRY Next; + USHORT Depth; + USHORT Sequence; + } s; +} SLIST_HEADER, *PSLIST_HEADER; + +typedef struct _NPAGED_LOOKASIDE_LIST +{ + SLIST_HEADER ListHead; + USHORT MinimumDepth; + USHORT MaximumDepth; + ULONG TotalAllocates; + ULONG AllocateMisses; + ULONG TotalFrees; + ULONG FreeMisses; + POOL_TYPE Type; + ULONG Tag; + ULONG Size; + PALLOCATE_FUNCTION Allocate; + PFREE_FUNCTION Free; + LIST_ENTRY ListEntry; + ULONG LastTotalAllocates; + ULONG LastAllocateMisses; + ULONG Pad[2]; + KSPIN_LOCK Lock; +} NPAGED_LOOKASIDE_LIST, *PNPAGED_LOOKASIDE_LIST; + +typedef struct _PAGED_LOOKASIDE_LIST +{ + SLIST_HEADER ListHead; + USHORT MinimumDepth; + USHORT MaximumDepth; + ULONG TotalAllocates; + ULONG AllocateMisses; + ULONG TotalFrees; + ULONG FreeMisses; + POOL_TYPE Type; + ULONG Tag; + ULONG Size; + PALLOCATE_FUNCTION Allocate; + PFREE_FUNCTION Free; + LIST_ENTRY ListEntry; + ULONG LastTotalAllocates; + ULONG LastAllocateMisses; + FAST_MUTEX Lock; +} PAGED_LOOKASIDE_LIST, *PPAGED_LOOKASIDE_LIST; + + +/* callback object (not functional in NT4)*/ + +typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT; + +typedef VOID STDCALL +(*PCALLBACK_FUNCTION)(PVOID CallbackContext, + PVOID Argument1, + PVOID Argument2); + +/* BEGIN REACTOS ONLY */ + +typedef enum _TRAVERSE_METHOD { + TraverseMethodPreorder, + TraverseMethodInorder, + TraverseMethodPostorder +} TRAVERSE_METHOD; + +typedef LONG STDCALL +(*PKEY_COMPARATOR)(IN PVOID Key1, + IN PVOID Key2); + +typedef BOOLEAN STDCALL +(*PTRAVERSE_ROUTINE)(IN PVOID Context, + IN PVOID Key, + IN PVOID Value); + +struct _BINARY_TREE_NODE; + +typedef struct _BINARY_TREE +{ + struct _BINARY_TREE_NODE * RootNode; + PKEY_COMPARATOR Compare; + BOOLEAN UseNonPagedPool; + union { + NPAGED_LOOKASIDE_LIST NonPaged; + PAGED_LOOKASIDE_LIST Paged; + } List; + union { + KSPIN_LOCK NonPaged; + FAST_MUTEX Paged; + } Lock; +} BINARY_TREE, *PBINARY_TREE; + + +struct _SPLAY_TREE_NODE; + +typedef struct _SPLAY_TREE +{ + struct _SPLAY_TREE_NODE * RootNode; + PKEY_COMPARATOR Compare; + BOOLEAN Weighted; + BOOLEAN UseNonPagedPool; + union { + NPAGED_LOOKASIDE_LIST NonPaged; + PAGED_LOOKASIDE_LIST Paged; + } List; + union { + KSPIN_LOCK NonPaged; + FAST_MUTEX Paged; + } Lock; + PVOID Reserved[4]; +} SPLAY_TREE, *PSPLAY_TREE; + + +typedef struct _HASH_TABLE +{ + // Size of hash table in number of bits + ULONG HashTableSize; + + // Use non-paged pool memory? + BOOLEAN UseNonPagedPool; + + // Lock for this structure + union { + KSPIN_LOCK NonPaged; + FAST_MUTEX Paged; + } Lock; + + // Pointer to array of hash buckets with splay trees + PSPLAY_TREE HashTrees; +} HASH_TABLE, *PHASH_TABLE; + +/* END REACTOS ONLY */ + +#endif /* __INCLUDE_DDK_EXTYPES_H */ + +/* EOF */ diff --git a/include/ddk/fsfuncs.h b/include/ddk/fsfuncs.h new file mode 100644 index 0000000..6f03dd3 --- /dev/null +++ b/include/ddk/fsfuncs.h @@ -0,0 +1,612 @@ +#ifndef __INCLUDE_DDK_FSFUNCS_H +#define __INCLUDE_DDK_FSFUNCS_H +/* $Id$ */ +#define FlagOn(x,f) ((x) & (f)) + +BOOLEAN STDCALL +FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Lbn, + IN LONGLONG SectorCount); + +VOID STDCALL +FsRtlAddMcbEntry( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ); + +VOID STDCALL +FsRtlAddToTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey, + IN PUNICODE_STRING ShortName, + IN PUNICODE_STRING LongName, + IN BOOLEAN KeyByShortName, + IN ULONG DataLength, + IN PVOID Data + ); + +PVOID STDCALL +FsRtlAllocatePool ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes + ); + +PVOID STDCALL +FsRtlAllocatePoolWithQuota ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes + ); + +PVOID STDCALL +FsRtlAllocatePoolWithQuotaTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag + ); +PVOID +STDCALL +FsRtlAllocatePoolWithTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag + ); +DWORD +STDCALL +FsRtlAllocateResource ( + VOID + ); +BOOLEAN +STDCALL +FsRtlAreNamesEqual ( + IN PUNICODE_STRING Name1, + IN PUNICODE_STRING Name2, + IN BOOLEAN IgnoreCase, + IN PWCHAR UpcaseTable OPTIONAL + ); +DWORD +STDCALL +FsRtlBalanceReads ( + DWORD Unknown0 + ); +BOOLEAN +STDCALL +FsRtlCheckLockForReadAccess ( + IN PFILE_LOCK FileLock, + IN PIRP Irp + ); +BOOLEAN +STDCALL +FsRtlCheckLockForWriteAccess ( + IN PFILE_LOCK FileLock, + IN PIRP Irp + ); + +NTSTATUS STDCALL +FsRtlCheckOplock(IN POPLOCK Oplock, + IN PIRP Irp, + IN PVOID Context, + IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, + IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL); + +BOOLEAN +STDCALL +FsRtlCopyRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ); +BOOLEAN +STDCALL +FsRtlCopyWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ); + +BOOLEAN STDCALL +FsRtlCurrentBatchOplock(IN POPLOCK Oplock); + +VOID STDCALL +FsRtlDeleteKeyFromTunnelCache(IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey); + +VOID STDCALL +FsRtlDeleteTunnelCache(IN PTUNNEL Cache); + +VOID STDCALL +FsRtlDeregisterUncProvider(IN HANDLE Handle); + +VOID +STDCALL +FsRtlDissectDbcs ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ); +VOID +STDCALL +FsRtlDissectName ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ); +BOOLEAN +STDCALL +FsRtlDoesDbcsContainWildCards ( + IN DWORD Unknown0 + ); +BOOLEAN +STDCALL +FsRtlDoesNameContainWildCards ( + IN PUNICODE_STRING Name + ); +BOOLEAN +STDCALL +FsRtlFastCheckLockForRead ( + IN PFILE_LOCK FileLock, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process + ); +BOOLEAN +STDCALL +FsRtlFastCheckLockForWrite ( + IN PFILE_LOCK FileLock, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process + ); +NTSTATUS +STDCALL +FsRtlFastUnlockAll ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN PVOID Context OPTIONAL + ); +NTSTATUS +STDCALL +FsRtlFastUnlockAllByKey ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN DWORD Key, + IN PVOID Context OPTIONAL + ); +NTSTATUS +STDCALL +FsRtlFastUnlockSingle ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN PVOID Context OPTIONAL, + IN BOOLEAN AlreadySynchronized + ); +VOID +STDCALL +FsRtlFindInTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey, + IN PUNICODE_STRING Name, + OUT PUNICODE_STRING ShortName, + OUT PUNICODE_STRING LongName, + IN OUT PULONG DataLength, + OUT PVOID Data + ); +NTSTATUS +STDCALL +FsRtlGetFileSize ( + IN PFILE_OBJECT FileObject, + IN OUT PLARGE_INTEGER FileSize + ); +PFILE_LOCK_INFO +STDCALL +FsRtlGetNextFileLock ( + IN PFILE_LOCK FileLock, + IN BOOLEAN Restart + ); + +BOOLEAN STDCALL +FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, + IN ULONG RunIndex, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG SectorCount); + +VOID +STDCALL +FsRtlGetNextMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ); +#define FsRtlEnterFileSystem KeEnterCriticalRegion +#define FsRtlExitFileSystem KeLeaveCriticalRegion +VOID +STDCALL +FsRtlInitializeFileLock ( + IN PFILE_LOCK FileLock, + IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, + IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL + ); + +VOID STDCALL +FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, + IN POOL_TYPE PoolType); + +VOID +STDCALL +FsRtlInitializeMcb ( + DWORD Unknown0, + DWORD Unknown1 + ); + +VOID STDCALL +FsRtlInitializeOplock(IN OUT POPLOCK Oplock); + +VOID +STDCALL +FsRtlInitializeTunnelCache ( + IN PTUNNEL Cache + ); +BOOLEAN +STDCALL +FsRtlIsDbcsInExpression ( + DWORD Unknown0, + DWORD Unknown1 + ); +BOOLEAN +STDCALL +FsRtlIsFatDbcsLegal ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ); +BOOLEAN +STDCALL +FsRtlIsHpfsDbcsLegal ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ); +BOOLEAN +STDCALL +FsRtlIsNameInExpression ( + IN PUNICODE_STRING Expression, + IN PUNICODE_STRING Name, + IN BOOLEAN IgnoreCase, + IN PWCHAR UpcaseTable OPTIONAL + ); + +BOOLEAN STDCALL +FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus); + +BOOLEAN STDCALL +FsRtlIsTotalDeviceFailure(IN NTSTATUS NtStatus); + +#define FsRtlIsUnicodeCharacterWild(C) ( \ + (((C) >= 0x40) ? \ + FALSE : \ + FlagOn((*FsRtlLegalAnsiCharacterArray)[(C)], FSRTL_WILD_CHARACTER )) \ + ) + +BOOLEAN STDCALL +FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn OPTIONAL, + OUT PLONGLONG SectorCountFromLbn OPTIONAL, + OUT PLONGLONG StartingLbn OPTIONAL, + OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, + OUT PULONG Index OPTIONAL); + +BOOLEAN STDCALL +FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn); + +VOID +STDCALL +FsRtlLookupLastMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); +VOID +STDCALL +FsRtlLookupMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ); +BOOLEAN +STDCALL +FsRtlMdlRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus + ); +BOOLEAN +STDCALL +FsRtlMdlReadComplete ( + IN PFILE_OBJECT FileObject, + IN OUT PMDL MdlChain + ); +BOOLEAN +STDCALL +FsRtlMdlReadCompleteDev ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject + ); +BOOLEAN +STDCALL +FsRtlMdlReadDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ); +BOOLEAN +STDCALL +FsRtlMdlWriteComplete ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain + ); +BOOLEAN +STDCALL +FsRtlMdlWriteCompleteDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject + ); +VOID +STDCALL +FsRtlNotifyChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN PLIST_ENTRY NotifyList, + IN BOOLEAN WatchTree, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp + ); +VOID +STDCALL +FsRtlNotifyCleanup ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext + ); +typedef +BOOLEAN (*PCHECK_FOR_TRAVERSE_ACCESS) ( + IN PVOID NotifyContext, + IN PVOID TargetContext, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext + ); +VOID +STDCALL +FsRtlNotifyFullChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN BOOLEAN WatchTree, + IN BOOLEAN IgnoreBuffer, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp, + IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL + ); +VOID +STDCALL +FsRtlNotifyFullReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN USHORT TargetNameOffset, + IN PSTRING StreamName OPTIONAL, + IN PSTRING NormalizedParentName OPTIONAL, + IN ULONG FilterMatch, + IN ULONG Action, + IN PVOID TargetContext + ); +VOID +STDCALL +FsRtlNotifyUninitializeSync ( + IN OUT PNOTIFY_SYNC * NotifySync + ); +VOID +STDCALL +FsRtlNotifyReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN PUSHORT FileNamePartLength, + IN ULONG FilterMatch + ); + +VOID STDCALL +FsRtlNotifyInitializeSync(IN OUT PNOTIFY_SYNC *NotifySync); + +NTSTATUS STDCALL +FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, + IN ULONG EventCode); + +NTSTATUS STDCALL +FsRtlOplockFsctrl(IN POPLOCK Oplock, + IN PIRP Irp, + IN ULONG OpenCount); + +BOOLEAN STDCALL +FsRtlOplockIsFastIoPossible(IN POPLOCK Oplock); + +BOOLEAN +STDCALL +FsRtlPrepareMdlWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus + ); +BOOLEAN +STDCALL +FsRtlPrepareMdlWriteDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ); + +NTSTATUS STDCALL +FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize, + IN NTSTATUS NormalizedNtStatus); + +ULONG STDCALL +FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb); + +VOID +STDCALL +FsRtlNumberOfRunsInMcb ( + DWORD Unknown0 + ); +VOID +STDCALL +FsRtlPostPagingFileStackOverflow ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); +VOID +STDCALL +FsRtlPostStackOverflow ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); +BOOLEAN +STDCALL +FsRtlPrivateLock ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PIRP Irp OPTIONAL, + IN PVOID Context, + IN BOOLEAN AlreadySynchronized + ); +NTSTATUS +STDCALL +FsRtlProcessFileLock ( + IN PFILE_LOCK FileLock, + IN PIRP Irp, + IN PVOID Context OPTIONAL + ); + +NTSTATUS STDCALL +FsRtlRegisterUncProvider(IN OUT PHANDLE Handle, + IN PUNICODE_STRING RedirectorDeviceName, + IN BOOLEAN MailslotsSupported); + +VOID STDCALL +FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount); + +VOID +STDCALL +FsRtlRemoveMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); + +BOOLEAN STDCALL +FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Amount); + +NTSTATUS +STDCALL +FsRtlSyncVolumes ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); + +VOID STDCALL +FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn); + +VOID +STDCALL +FsRtlTruncateMcb ( + DWORD Unknown0, + DWORD Unknown1 + ); +VOID +STDCALL +FsRtlUninitializeFileLock ( + IN PFILE_LOCK FileLock + ); + +VOID STDCALL +FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb); + +VOID +STDCALL +FsRtlUninitializeMcb ( + DWORD Unknown0 + ); + +VOID STDCALL +FsRtlUninitializeOplock(IN POPLOCK Oplock); + +#endif /* __INCLUDE_DDK_FSFUNCS_H */ diff --git a/include/ddk/fstypes.h b/include/ddk/fstypes.h new file mode 100644 index 0000000..03a6401 --- /dev/null +++ b/include/ddk/fstypes.h @@ -0,0 +1,96 @@ +#ifndef __INCLUDE_DDK_FSTYPES_H +#define __INCLUDE_DDK_FSTYPES_H +/* $Id$ */ + +#define FSRTL_TAG TAG('F','S','r','t') + +typedef struct _FILE_LOCK_INFO { + LARGE_INTEGER StartingByte; + LARGE_INTEGER Length; + BOOLEAN ExclusiveLock; + ULONG Key; + PFILE_OBJECT FileObject; + PEPROCESS Process; + LARGE_INTEGER EndingByte; +} FILE_LOCK_INFO, *PFILE_LOCK_INFO; + +// raw internal file lock struct returned from FsRtlGetNextFileLock +typedef struct _FILE_SHARED_LOCK_ENTRY { + PVOID Unknown1; + PVOID Unknown2; + FILE_LOCK_INFO FileLock; +} FILE_SHARED_LOCK_ENTRY, *PFILE_SHARED_LOCK_ENTRY; + +// raw internal file lock struct returned from FsRtlGetNextFileLock +typedef struct _FILE_EXCLUSIVE_LOCK_ENTRY { + LIST_ENTRY ListEntry; + PVOID Unknown1; + PVOID Unknown2; + FILE_LOCK_INFO FileLock; +} FILE_EXCLUSIVE_LOCK_ENTRY, *PFILE_EXCLUSIVE_LOCK_ENTRY; + +typedef NTSTATUS (*PCOMPLETE_LOCK_IRP_ROUTINE) ( + IN PVOID Context, + IN PIRP Irp +); + +typedef VOID (*PUNLOCK_ROUTINE) ( + IN PVOID Context, + IN PFILE_LOCK_INFO FileLockInfo +); + +typedef struct _FILE_LOCK { + PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine; + PUNLOCK_ROUTINE UnlockRoutine; + BOOLEAN FastIoIsQuestionable; + BOOLEAN Pad[3]; + PVOID LockInformation; + FILE_LOCK_INFO LastReturnedLockInfo; + PVOID LastReturnedLock; +} FILE_LOCK, *PFILE_LOCK; + +typedef struct _TUNNEL { + FAST_MUTEX Mutex; + PRTL_SPLAY_LINKS Cache; + LIST_ENTRY TimerQueue; + USHORT NumEntries; +} TUNNEL, *PTUNNEL; + +typedef struct _NOTIFY_SYNC +{ + DWORD Unknown0; /* 0x00 */ + DWORD Unknown1; /* 0x04 */ + DWORD Unknown2; /* 0x08 */ + WORD Unknown3; /* 0x0c */ + WORD Unknown4; /* 0x0e */ + DWORD Unknown5; /* 0x10 */ + DWORD Unknown6; /* 0x14 */ + DWORD Unknown7; /* 0x18 */ + DWORD Unknown8; /* 0x1c */ + DWORD Unknown9; /* 0x20 */ + DWORD Unknown10; /* 0x24 */ + +} NOTIFY_SYNC, * PNOTIFY_SYNC; + + +typedef struct _LARGE_MCB +{ + PFAST_MUTEX FastMutex; + ULONG MaximumPairCount; + ULONG PairCount; + POOL_TYPE PoolType; + PVOID Mapping; +} LARGE_MCB, *PLARGE_MCB; + + +typedef VOID +(*POPLOCK_WAIT_COMPLETE_ROUTINE)(PVOID Context, + PIRP Irp); + +typedef VOID +(*POPLOCK_FS_PREPOST_IRP)(PVOID Context, + PIRP Irp); + +typedef PVOID OPLOCK, *POPLOCK; + +#endif /* __INCLUDE_DDK_FSFUNCS_H */ diff --git a/include/ddk/halfuncs.h b/include/ddk/halfuncs.h new file mode 100644 index 0000000..fd2be9d --- /dev/null +++ b/include/ddk/halfuncs.h @@ -0,0 +1,309 @@ +#ifndef __INCLUDE_DDK_HALFUNCS_H +#define __INCLUDE_DDK_HALFUNCS_H +/* $Id$ */ + +VOID STDCALL +HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters); + +NTSTATUS STDCALL +HalAdjustResourceList(PCM_RESOURCE_LIST Resources); + +NTSTATUS STDCALL +HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, + IN PDEVICE_OBJECT DeviceObject, + IN ULONG NumberOfMapRegisters, + IN PDRIVER_CONTROL ExecutionRoutine, + IN PVOID Context); + +PVOID STDCALL +HalAllocateCommonBuffer(PADAPTER_OBJECT AdapterObject, + ULONG Length, + PPHYSICAL_ADDRESS LogicalAddress, + BOOLEAN CacheEnabled); + +PVOID STDCALL +HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject, + IN OUT PULONG NumberOfMapRegisters); + +BOOLEAN STDCALL +HalAllProcessorsStarted(VOID); + +NTSTATUS STDCALL +HalAssignSlotResources( + PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + INTERFACE_TYPE BusType, + ULONG BusNumber, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources + ); + +BOOLEAN STDCALL +HalBeginSystemInterrupt(ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql); + +VOID STDCALL +HalCalibratePerformanceCounter(ULONG Count); + +/* +FASTCALL +HalClearSoftwareInterrupt +*/ + +BOOLEAN STDCALL +HalDisableSystemInterrupt(ULONG Vector, + ULONG Unknown2); + +VOID STDCALL +HalDisplayString(IN PCH String); + +BOOLEAN STDCALL +HalEnableSystemInterrupt(ULONG Vector, + ULONG Unknown2, + ULONG Unknown3); + +VOID STDCALL +HalEndSystemInterrupt(KIRQL Irql, + ULONG Unknown2); + + +/* Is this function really exported ?? */ +VOID +HalExamineMBR(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG MBRTypeIdentifier, + PVOID Buffer); + +BOOLEAN STDCALL +HalFlushCommonBuffer(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6, + ULONG Unknown7, + ULONG Unknown8); + +VOID STDCALL +HalFreeCommonBuffer(PADAPTER_OBJECT AdapterObject, + ULONG Length, + PHYSICAL_ADDRESS LogicalAddress, + PVOID VirtualAddress, + BOOLEAN CacheEnabled); + +PADAPTER_OBJECT STDCALL +HalGetAdapter(PDEVICE_DESCRIPTION DeviceDescription, + PULONG NumberOfMapRegisters); + +ULONG STDCALL +HalGetBusData(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length); + +ULONG STDCALL +HalGetBusDataByOffset(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +/* Is this function really exported ?? */ +ULONG +HalGetDmaAlignmentRequirement(VOID); + +BOOLEAN STDCALL +HalGetEnvironmentVariable(IN PCH Name, + OUT PCH Value, + IN USHORT ValueLength); + +ULONG STDCALL +HalGetInterruptVector(INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity); + +VOID STDCALL +HalInitializeProcessor(ULONG ProcessorNumber, + PVOID ProcessorStack); + +BOOLEAN STDCALL +HalInitSystem(ULONG BootPhase, + PLOADER_PARAMETER_BLOCK LoaderBlock); + +BOOLEAN STDCALL +HalMakeBeep(ULONG Frequency); + +VOID STDCALL +HalQueryDisplayParameters(PULONG DispSizeX, + PULONG DispSizeY, + PULONG CursorPosX, + PULONG CursorPosY); + +VOID STDCALL +HalQueryRealTimeClock(PTIME_FIELDS Time); + +/* Is this function really exported ?? */ +VOID +HalQuerySystemInformation(VOID); + +ULONG STDCALL +HalReadDmaCounter(PADAPTER_OBJECT AdapterObject); + +VOID STDCALL +HalReportResourceUsage(VOID); + +VOID STDCALL +HalRequestIpi(ULONG Unknown); + +/* +FASTCALL +HalRequestSoftwareInterrupt +*/ + +VOID STDCALL +HalReturnToFirmware(ULONG Action); + +ULONG STDCALL +HalSetBusData(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length); + +ULONG STDCALL +HalSetBusDataByOffset(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +VOID STDCALL +HalSetDisplayParameters(ULONG CursorPosX, + ULONG CursorPosY); + +BOOLEAN STDCALL +HalSetEnvironmentVariable(IN PCH Name, + IN PCH Value); + +/* +HalSetProfileInterval +*/ + +VOID STDCALL +HalSetRealTimeClock(PTIME_FIELDS Time); + +/* +HalSetTimeIncrement +*/ + +BOOLEAN STDCALL +HalStartNextProcessor(ULONG Unknown1, + ULONG Unknown2); + +/* +HalStartProfileInterrupt +*/ + +/* +HalStopProfileInterrupt +*/ + +ULONG FASTCALL +HalSystemVectorDispatchEntry(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3); + +BOOLEAN STDCALL +HalTranslateBusAddress(INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + + +/* + * Kernel debugger support functions + */ + +BOOLEAN STDCALL +KdPortInitialize(PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2); + +BOOLEAN STDCALL +KdPortGetByte(PUCHAR ByteRecieved); + +BOOLEAN STDCALL +KdPortPollByte(PUCHAR ByteRecieved); + +VOID STDCALL +KdPortPutByte(UCHAR ByteToSend); + + +/* + * Port I/O functions + */ + +VOID STDCALL +READ_PORT_BUFFER_UCHAR(PUCHAR Port, + PUCHAR Value, + ULONG Count); + +VOID STDCALL +READ_PORT_BUFFER_ULONG(PULONG Port, + PULONG Value, + ULONG Count); + +VOID STDCALL +READ_PORT_BUFFER_USHORT(PUSHORT Port, + PUSHORT Value, + ULONG Count); + +UCHAR STDCALL +READ_PORT_UCHAR(PUCHAR Port); + +ULONG STDCALL +READ_PORT_ULONG(PULONG Port); + +USHORT STDCALL +READ_PORT_USHORT(PUSHORT Port); + +VOID STDCALL +WRITE_PORT_BUFFER_UCHAR(PUCHAR Port, + PUCHAR Value, + ULONG Count); + +VOID STDCALL +WRITE_PORT_BUFFER_ULONG(PULONG Port, + PULONG Value, + ULONG Count); + +VOID STDCALL +WRITE_PORT_BUFFER_USHORT(PUSHORT Port, + PUSHORT Value, + ULONG Count); + +VOID STDCALL +WRITE_PORT_UCHAR(PUCHAR Port, + UCHAR Value); + +VOID STDCALL +WRITE_PORT_ULONG(PULONG Port, + ULONG Value); + +VOID STDCALL +WRITE_PORT_USHORT(PUSHORT Port, + USHORT Value); + +#endif /* __INCLUDE_DDK_HALDDK_H */ + +/* EOF */ diff --git a/include/ddk/haltypes.h b/include/ddk/haltypes.h new file mode 100644 index 0000000..2ccf398 --- /dev/null +++ b/include/ddk/haltypes.h @@ -0,0 +1,448 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ddk/haltypes.h + * PURPOSE: HAL provided defintions for device drivers + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Taken from linux system.h + */ + + +#ifndef __INCLUDE_DDK_HALTYPES_H +#define __INCLUDE_DDK_HALTYPES_H + + +/* HalReturnToFirmware */ +#define FIRMWARE_HALT 1 +#define FIRMWARE_REBOOT 3 + +enum +{ + DEVICE_DESCRIPTION_VERSION, + DEVICE_DESCRIPTION_VERSION1, +}; + +typedef ULONG DMA_WIDTH; +typedef ULONG DMA_SPEED; + +/* + * PURPOSE: Types for HalGetBusData + */ +typedef enum _BUS_DATA_TYPE +{ + ConfigurationSpaceUndefined = -1, + Cmos, + EisaConfiguration, + Pos, + CbusConfiguration, + PCIConfiguration, + VMEConfiguration, + NuBusConfiguration, + PCMCIAConfiguration, + MPIConfiguration, + MPSAConfiguration, + PNPISAConfiguration, + MaximumBusDataType, +} BUS_DATA_TYPE, *PBUS_DATA_TYPE; + +typedef struct _DEVICE_DESCRIPTION +{ + ULONG Version; + BOOLEAN Master; + BOOLEAN ScatterGather; + BOOLEAN DemandMode; + BOOLEAN AutoInitialize; + BOOLEAN Dma32BitAddress; + BOOLEAN IgnoreCount; + BOOLEAN Reserved1; + BOOLEAN Reserved2; + ULONG BusNumber; + ULONG DmaChannel; + INTERFACE_TYPE InterfaceType; + DMA_WIDTH DmaWidth; + DMA_SPEED DmaSpeed; + ULONG MaximumLength; + ULONG DmaPort; +} DEVICE_DESCRIPTION, *PDEVICE_DESCRIPTION; + + +/* PCI bus definitions */ + +#define PCI_TYPE0_ADDRESSES 6 +#define PCI_TYPE1_ADDRESSES 2 +#define PCI_TYPE2_ADDRESSES 5 + +typedef struct _PCI_COMMON_CONFIG +{ + USHORT VendorID; /* read-only */ + USHORT DeviceID; /* read-only */ + USHORT Command; + USHORT Status; + UCHAR RevisionID; /* read-only */ + UCHAR ProgIf; /* read-only */ + UCHAR SubClass; /* read-only */ + UCHAR BaseClass; /* read-only */ + UCHAR CacheLineSize; /* read-only */ + UCHAR LatencyTimer; /* read-only */ + UCHAR HeaderType; /* read-only */ + UCHAR BIST; + union + { + struct _PCI_HEADER_TYPE_0 + { + ULONG BaseAddresses[PCI_TYPE0_ADDRESSES]; + ULONG CIS; + USHORT SubVendorID; + USHORT SubSystemID; + ULONG ROMBaseAddress; + ULONG Reserved2[2]; + + UCHAR InterruptLine; + UCHAR InterruptPin; /* read-only */ + UCHAR MinimumGrant; /* read-only */ + UCHAR MaximumLatency; /* read-only */ + } type0; + + /* PCI to PCI Bridge */ + struct _PCI_HEADER_TYPE_1 + { + ULONG BaseAddresses[PCI_TYPE1_ADDRESSES]; + UCHAR PrimaryBus; + UCHAR SecondaryBus; + UCHAR SubordinateBus; + UCHAR SecondaryLatency; + UCHAR IOBase; + UCHAR IOLimit; + USHORT SecondaryStatus; + USHORT MemoryBase; + USHORT MemoryLimit; + USHORT PrefetchBase; + USHORT PrefetchLimit; + ULONG PrefetchBaseUpper32; + ULONG PrefetchLimitUpper32; + USHORT IOBaseUpper16; + USHORT IOLimitUpper16; + UCHAR CapabilitiesPtr; + UCHAR Reserved1[3]; + ULONG ROMBaseAddress; + UCHAR InterruptLine; + UCHAR InterruptPin; + USHORT BridgeControl; + } type1; + + /* PCI to CARDBUS Bridge */ + struct _PCI_HEADER_TYPE_2 + { + ULONG SocketRegistersBaseAddress; + UCHAR CapabilitiesPtr; + UCHAR Reserved; + USHORT SecondaryStatus; + UCHAR PrimaryBus; + UCHAR SecondaryBus; + UCHAR SubordinateBus; + UCHAR SecondaryLatency; + struct + { + ULONG Base; + ULONG Limit; + } Range[PCI_TYPE2_ADDRESSES-1]; + UCHAR InterruptLine; + UCHAR InterruptPin; + USHORT BridgeControl; + } type2; + } u; + UCHAR DeviceSpecific[192]; +} PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG; + +#define PCI_COMMON_HDR_LENGTH (FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceSpecific)) + +#define PCI_MAX_DEVICES 32 +#define PCI_MAX_FUNCTION 8 + +#define PCI_INVALID_VENDORID 0xFFFF + + +/* Bit encodings for PCI_COMMON_CONFIG.HeaderType */ + +#define PCI_MULTIFUNCTION 0x80 +#define PCI_DEVICE_TYPE 0x00 +#define PCI_BRIDGE_TYPE 0x01 + + +/* Bit encodings for PCI_COMMON_CONFIG.Command */ + +#define PCI_ENABLE_IO_SPACE 0x0001 +#define PCI_ENABLE_MEMORY_SPACE 0x0002 +#define PCI_ENABLE_BUS_MASTER 0x0004 +#define PCI_ENABLE_SPECIAL_CYCLES 0x0008 +#define PCI_ENABLE_WRITE_AND_INVALIDATE 0x0010 +#define PCI_ENABLE_VGA_COMPATIBLE_PALETTE 0x0020 +#define PCI_ENABLE_PARITY 0x0040 +#define PCI_ENABLE_WAIT_CYCLE 0x0080 +#define PCI_ENABLE_SERR 0x0100 +#define PCI_ENABLE_FAST_BACK_TO_BACK 0x0200 + + +/* Bit encodings for PCI_COMMON_CONFIG.Status */ + +#define PCI_STATUS_FAST_BACK_TO_BACK 0x0080 +#define PCI_STATUS_DATA_PARITY_DETECTED 0x0100 +#define PCI_STATUS_DEVSEL 0x0600 /* 2 bits wide */ +#define PCI_STATUS_SIGNALED_TARGET_ABORT 0x0800 +#define PCI_STATUS_RECEIVED_TARGET_ABORT 0x1000 +#define PCI_STATUS_RECEIVED_MASTER_ABORT 0x2000 +#define PCI_STATUS_SIGNALED_SYSTEM_ERROR 0x4000 +#define PCI_STATUS_DETECTED_PARITY_ERROR 0x8000 + + +/* Bit encodes for PCI_COMMON_CONFIG.u.type0.BaseAddresses */ + +#define PCI_ADDRESS_IO_SPACE 0x00000001 +#define PCI_ADDRESS_MEMORY_TYPE_MASK 0x00000006 +#define PCI_ADDRESS_MEMORY_PREFETCHABLE 0x00000008 + +#define PCI_TYPE_32BIT 0 +#define PCI_TYPE_20BIT 2 +#define PCI_TYPE_64BIT 4 + + +/* Bit encodes for PCI_COMMON_CONFIG.u.type0.ROMBaseAddresses */ + +#define PCI_ROMADDRESS_ENABLED 0x00000001 + + +typedef struct _PCI_SLOT_NUMBER +{ + union + { + struct + { + ULONG DeviceNumber:5; + ULONG FunctionNumber:3; + ULONG Reserved:24; + } bits; + ULONG AsULONG; + } u; +} PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER; + + +/* MicroChannel bus data */ + +typedef struct _CM_MCA_POS_DATA +{ + USHORT AdapterId; + UCHAR PosData1; + UCHAR PosData2; + UCHAR PosData3; + UCHAR PosData4; +} CM_MCA_POS_DATA, *PCM_MCA_POS_DATA; + + +/* Hal dispatch table */ + +typedef enum _HAL_QUERY_INFORMATION_CLASS +{ + HalInstalledBusInformation, + HalProfileSourceInformation, + HalSystemDockInformation, + HalPowerInformation, + HalProcessorSpeedInformation, + HalCallbackInformation, + HalMapRegisterInformation, + HalMcaLogInformation, + HalFrameBufferCachingInformation, + HalDisplayBiosInformation + /* information levels >= 0x8000000 reserved for OEM use */ +} HAL_QUERY_INFORMATION_CLASS, *PHAL_QUERY_INFORMATION_CLASS; + + +typedef enum _HAL_SET_INFORMATION_CLASS +{ + HalProfileSourceInterval, + HalProfileSourceInterruptHandler, + HalMcaRegisterDriver +} HAL_SET_INFORMATION_CLASS, *PHAL_SET_INFORMATION_CLASS; + + +typedef struct _BUS_HANDLER *PBUS_HANDLER; +typedef struct _DEVICE_HANDLER_OBJECT *PDEVICE_HANDLER_OBJECT; + + +typedef BOOLEAN STDCALL +(*PHAL_RESET_DISPLAY_PARAMETERS)(ULONG Columns, ULONG Rows); + +typedef NTSTATUS STDCALL +(*pHalQuerySystemInformation)(IN HAL_QUERY_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN OUT PVOID Buffer, + OUT PULONG ReturnedLength); + + +typedef NTSTATUS STDCALL +(*pHalSetSystemInformation)(IN HAL_SET_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN PVOID Buffer); + + +typedef NTSTATUS STDCALL +(*pHalQueryBusSlots)(IN PBUS_HANDLER BusHandler, + IN ULONG BufferSize, + OUT PULONG SlotNumbers, + OUT PULONG ReturnedLength); + + +/* Control codes of HalDeviceControl function */ +#define BCTL_EJECT 0x0001 +#define BCTL_QUERY_DEVICE_ID 0x0002 +#define BCTL_QUERY_DEVICE_UNIQUE_ID 0x0003 +#define BCTL_QUERY_DEVICE_CAPABILITIES 0x0004 +#define BCTL_QUERY_DEVICE_RESOURCES 0x0005 +#define BCTL_QUERY_DEVICE_RESOURCE_REQUIREMENTS 0x0006 +#define BCTL_QUERY_EJECT 0x0007 +#define BCTL_SET_LOCK 0x0008 +#define BCTL_SET_POWER 0x0009 +#define BCTL_SET_RESUME 0x000A +#define BCTL_SET_DEVICE_RESOURCES 0x000B + +/* Defines for BCTL structures */ +typedef struct +{ + BOOLEAN PowerSupported; + BOOLEAN ResumeSupported; + BOOLEAN LockSupported; + BOOLEAN EjectSupported; + BOOLEAN Removable; +} BCTL_DEVICE_CAPABILITIES, *PBCTL_DEVICE_CAPABILITIES; + + +typedef struct _DEVICE_CONTROL_CONTEXT +{ + NTSTATUS Status; + PDEVICE_HANDLER_OBJECT DeviceHandler; + PDEVICE_OBJECT DeviceObject; + ULONG ControlCode; + PVOID Buffer; + PULONG BufferLength; + PVOID Context; +} DEVICE_CONTROL_CONTEXT, *PDEVICE_CONTROL_CONTEXT; + + +typedef VOID STDCALL +(*PDEVICE_CONTROL_COMPLETION)(IN PDEVICE_CONTROL_CONTEXT ControlContext); + + +typedef NTSTATUS STDCALL +(*pHalDeviceControl)(IN PDEVICE_HANDLER_OBJECT DeviceHandler, + IN PDEVICE_OBJECT DeviceObject, + IN ULONG ControlCode, + IN OUT PVOID Buffer OPTIONAL, + IN OUT PULONG BufferLength OPTIONAL, + IN PVOID Context, + IN PDEVICE_CONTROL_COMPLETION CompletionRoutine); + +typedef VOID FASTCALL +(*pHalExamineMBR)(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG MBRTypeIdentifier, + OUT PVOID *Buffer); + +typedef VOID FASTCALL +(*pHalIoAssignDriveLetters)(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PSTRING NtDeviceName, + OUT PUCHAR NtSystemPath, + OUT PSTRING NtSystemPathString); + +typedef NTSTATUS FASTCALL +(*pHalIoReadPartitionTable)(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN BOOLEAN ReturnRecognizedPartitions, + OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer); + +typedef NTSTATUS FASTCALL +(*pHalIoSetPartitionInformation)(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG PartitionNumber, + IN ULONG PartitionType); + +typedef NTSTATUS FASTCALL +(*pHalIoWritePartitionTable)(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG SectorsPerTrack, + IN ULONG NumberOfHeads, + IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer); + +typedef PBUS_HANDLER FASTCALL +(*pHalHandlerForBus)(IN INTERFACE_TYPE InterfaceType, + IN ULONG BusNumber); + +typedef VOID FASTCALL +(*pHalReferenceBusHandler)(IN PBUS_HANDLER BusHandler); + + +typedef struct _HAL_DISPATCH +{ + ULONG Version; + pHalQuerySystemInformation HalQuerySystemInformation; + pHalSetSystemInformation HalSetSystemInformation; + pHalQueryBusSlots HalQueryBusSlots; + pHalDeviceControl HalDeviceControl; + pHalExamineMBR HalExamineMBR; + pHalIoAssignDriveLetters HalIoAssignDriveLetters; + pHalIoReadPartitionTable HalIoReadPartitionTable; + pHalIoSetPartitionInformation HalIoSetPartitionInformation; + pHalIoWritePartitionTable HalIoWritePartitionTable; + pHalHandlerForBus HalReferenceHandlerForBus; + pHalReferenceBusHandler HalReferenceBusHandler; + pHalReferenceBusHandler HalDereferenceBusHandler; +} HAL_DISPATCH, *PHAL_DISPATCH; + +#define HAL_DISPATCH_VERSION 1 + +#ifdef __NTOSKRNL__ +extern HAL_DISPATCH EXPORTED HalDispatchTable; +#else +extern HAL_DISPATCH IMPORTED HalDispatchTable; +#endif + + +/* Hal private dispatch table */ + +typedef struct _HAL_PRIVATE_DISPATCH +{ + ULONG Version; +} HAL_PRIVATE_DISPATCH, *PHAL_PRIVATE_DISPATCH; + +#define HAL_PRIVATE_DISPATCH_VERSION 1 + + +#ifdef __NTOSKRNL__ +extern HAL_PRIVATE_DISPATCH EXPORTED HalPrivateDispatchTable; +#else +extern HAL_PRIVATE_DISPATCH IMPORTED HalPrivateDispatchTable; +#endif + + + +/* + * Kernel debugger section + */ + +typedef struct _KD_PORT_INFORMATION +{ + ULONG ComPort; + ULONG BaudRate; + ULONG BaseAddress; +} KD_PORT_INFORMATION, *PKD_PORT_INFORMATION; + + +#ifdef __NTHAL__ +extern ULONG EXPORTED KdComPortInUse; +#else +extern ULONG IMPORTED KdComPortInUse; +#endif + +#endif /* __INCLUDE_DDK_HALTYPES_H */ + +/* EOF */ diff --git a/include/ddk/i386/irql.h b/include/ddk/i386/irql.h new file mode 100644 index 0000000..db7ef23 --- /dev/null +++ b/include/ddk/i386/irql.h @@ -0,0 +1,7 @@ +/* + * PURPOSE: The number of device specific level levels + */ +#define NR_DEVICE_SPECIFIC_LEVELS (16) + + + diff --git a/include/ddk/i386/pagesize.h b/include/ddk/i386/pagesize.h new file mode 100644 index 0000000..2978737 --- /dev/null +++ b/include/ddk/i386/pagesize.h @@ -0,0 +1,6 @@ +#ifndef __INCLUDE_DDK_I386_PAGESIZE_H +#define __INCLUDE_DDK_I386_PAGESIZE_H + +#define PAGE_SIZE (4096) + +#endif /* __INCLUDE_DDK_I386_PAGESIZE_H */ diff --git a/include/ddk/i386/tss.h b/include/ddk/i386/tss.h new file mode 100644 index 0000000..361086a --- /dev/null +++ b/include/ddk/i386/tss.h @@ -0,0 +1,57 @@ +/* + * + */ + +#ifndef __INCLUDE_DDK_I386_TSS_H +#define __INCLUDE_DDK_I386_TSS_H + +#define KTSS_ESP0 (0x4) + +#ifndef __ASM__ + +typedef struct _KTSS +{ + USHORT PreviousTask; + USHORT Reserved1; + ULONG Esp0; + USHORT Ss0; + USHORT Reserved2; + ULONG Esp1; + USHORT Ss1; + USHORT Reserved3; + ULONG Esp2; + USHORT Ss2; + USHORT Reserved4; + ULONG Cr3; + ULONG Eip; + ULONG Eflags; + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Esp; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + USHORT Es; + USHORT Reserved5; + USHORT Cs; + USHORT Reserved6; + USHORT Ss; + USHORT Reserved7; + USHORT Ds; + USHORT Reserved8; + USHORT Fs; + USHORT Reserved9; + USHORT Gs; + USHORT Reserved10; + USHORT Ldt; + USHORT Reserved11; + USHORT Trap; + USHORT IoMapBase; + UCHAR IoBitmap[1]; +} KTSS __attribute__((packed)); + +#endif /* not __ASM__ */ + +#endif /* __INCLUDE_DDK_I386_TSS_H */ diff --git a/include/ddk/ioctrl.h b/include/ddk/ioctrl.h new file mode 100644 index 0000000..867eb9a --- /dev/null +++ b/include/ddk/ioctrl.h @@ -0,0 +1,23 @@ +#ifndef __INCLUDE_DDK_IOCTRL_H +#define __INCLUDE_DDK_IOCTRL_H + + +#define CTL_CODE(Dev, Func, Meth, Acc) ( ((Dev)<<16) | ((Acc)<<14) | ((Func)<<2) | (Meth)) + + +#define DEVICE_TYPE_FROM_CTL_CODE(ctlCode) (((ULONG)(ctlCode&0xffff0000))>>16) +#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) + + +// IOCTL Parameter buffering methods +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +// IOCTL File access type +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS 1 +#define FILE_WRITE_ACCESS 2 + +#endif /* __INCLUDE_DDK_IOCTRL_H */ diff --git a/include/ddk/iodef.h b/include/ddk/iodef.h new file mode 100644 index 0000000..4d199cd --- /dev/null +++ b/include/ddk/iodef.h @@ -0,0 +1,393 @@ +#ifndef __INCLUDE_DDK_IODEF_H +#define __INCLUDE_DDK_IODEF_H + +typedef enum _IO_QUERY_DEVICE_DESCRIPTION +{ + IoQueryDeviceIdentifier = 0, + IoQueryDeviceConfigurationData, + IoQueryDeviceComponentInformation, + IoQueryDeviceDataFormatMaximum, +} IO_QUERY_DEVICE_DESCRIPTION, *PIO_QUERY_DEVICE_DESCRIPTION; + +typedef enum _CONFIGURATION_TYPE +{ + DiskController, + ParallelController, + MaximumType, +} CONFIGURATION_TYPE, *PCONFIGURATION_TYPE; + +typedef enum _CM_RESOURCE_TYPE +{ + CmResourceTypePort = 1, + CmResourceTypeInterrupt, + CmResourceTypeMemory, + CmResourceTypeDma, + CmResourceTypeDeviceSpecific, + CmResourceTypeMaximum, +} CM_RESOURCE_TYPE; + +typedef enum _CM_SHARE_DISPOSITION +{ + CmResourceShareDeviceExclusive = 1, + CmResourceShareDriverExclusive, + CmResourceShareShared, + CmResourceShareMaximum, +} CM_SHARE_DISPOSITION; + +enum +{ + CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE, + CM_RESOURCE_INTERRUPT_LATCHED, +}; + +enum +{ + CM_RESOURCE_PORT_MEMORY, + CM_RESOURCE_PORT_IO, +}; + +/* + * PURPOSE: Irp flags + */ +enum +{ + IRP_NOCACHE = 0x1, + IRP_PAGING_IO = 0x2, + IRP_MOUNT_COMPLETION = 0x2, + IRP_SYNCHRONOUS_API = 0x4, + IRP_ASSOCIATED_IRP = 0x8, + IRP_BUFFERED_IO = 0x10, + IRP_DEALLOCATE_BUFFER = 0x20, + IRP_INPUT_OPERATION = 0x40, + IRP_SYNCHRONOUS_PAGING_IO = 0x40, + IRP_CREATE_OPERATION = 0x80, + IRP_READ_OPERATION = 0x100, + IRP_WRITE_OPERATION = 0x200, + IRP_CLOSE_OPERATION = 0x400, + IRP_DEFER_IO_COMPLETION = 0x800, + IRP_OB_QUERY_NAME = 0x1000, + IRP_HOLD_DEVICE_QUEUE = 0x2000, + IRP_RETRY_IO_COMPLETION = 0x4000 +}; + +#define SL_FORCE_ACCESS_CHECK (0x1) +#define SL_OPEN_PAGING_FILE (0x2) +#define SL_OPEN_TARGET_DIRECTORY (0x4) +#define SL_CASE_SENSITIVE (0x80) + +#define SL_KEY_SPECIFIED (0x1) +#define SL_OVERRIDE_VERIFY_VOLUME (0x2) +#define SL_WRITE_THROUGHT (0x4) +#define SL_FT_SEQUENTIAL_WRITE (0x8) + +#define SL_FAIL_IMMEDIATELY (0x1) +#define SL_EXCLUSIVE_LOCK (0x2) + +#define SL_WATCH_TREE (0x1) + +#define SL_RESTART_SCAN (0x1) +#define SL_RETURN_SINGLE_ENTRY (0x2) +#define SL_INDEX_SPECIFIED (0x4) + +#define SL_ALLOW_RAW_MOUNT (0x1) + +#define SL_PENDING_RETURNED 0x01 +#define SL_INVOKE_ON_CANCEL 0x20 +#define SL_INVOKE_ON_SUCCESS 0x40 +#define SL_INVOKE_ON_ERROR 0x80 + +/* + * Possible flags for the device object flags + */ +#define DO_UNLOAD_PENDING 0x00000001 +#define DO_VERIFY_VOLUME 0x00000002 +#define DO_BUFFERED_IO 0x00000004 +#define DO_EXCLUSIVE 0x00000008 +#define DO_DIRECT_IO 0x00000010 +#define DO_MAP_IO_BUFFER 0x00000020 +#define DO_DEVICE_HAS_NAME 0x00000040 +#define DO_DEVICE_INITIALIZING 0x00000080 +#define DO_SYSTEM_BOOT_PARTITION 0x00000100 +#define DO_LONG_TERM_REQUESTS 0x00000200 +#define DO_NEVER_LAST_DEVICE 0x00000400 +#define DO_SHUTDOWN_REGISTERED 0x00000800 +#define DO_BUS_ENUMERATED_DEVICE 0x00001000 +#define DO_POWER_PAGABLE 0x00002000 +#define DO_POWER_INRUSH 0x00004000 +#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 + +/* + * Possible device types + */ +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +#define FILE_DEVICE_SMB 0x0000002e +#define FILE_DEVICE_KS 0x0000002f +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 + +#define FILE_REMOVABLE_MEDIA 0x00000001 +#define FILE_READ_ONLY_DEVICE 0x00000002 +#define FILE_FLOPPY_DISKETTE 0x00000004 +#define FILE_WRITE_ONCE_MEDIA 0x00000008 +#define FILE_REMOTE_DEVICE 0x00000010 +#define FILE_DEVICE_IS_MOUNTED 0x00000020 +#define FILE_VIRTUAL_VOLUME 0x00000040 +#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 +#define FILE_DEVICE_SECURE_OPEN 0x00000100 + + +/* + * PURPOSE: Bus types + */ +typedef enum _INTERFACE_TYPE +{ + InterfaceTypeUndefined = -1, + Internal, + Isa, + Eisa, + MicroChannel, + TurboChannel, + PCIBus, + VMEBus, + NuBus, + PCMCIABus, + CBus, + MPIBus, + MPSABus, + ProcessorInternal, + InternalPowerBus, + PNPISABus, + MaximumInterfaceType +} INTERFACE_TYPE, *PINTERFACE_TYPE; + + +enum +{ + IRP_MJ_CREATE, + IRP_MJ_CREATE_NAMED_PIPE, + IRP_MJ_CLOSE, + IRP_MJ_READ, + IRP_MJ_WRITE, + IRP_MJ_QUERY_INFORMATION, + IRP_MJ_SET_INFORMATION, + IRP_MJ_QUERY_EA, + IRP_MJ_SET_EA, + IRP_MJ_FLUSH_BUFFERS, + IRP_MJ_QUERY_VOLUME_INFORMATION, + IRP_MJ_SET_VOLUME_INFORMATION, + IRP_MJ_DIRECTORY_CONTROL, + IRP_MJ_FILE_SYSTEM_CONTROL, + IRP_MJ_DEVICE_CONTROL, + IRP_MJ_INTERNAL_DEVICE_CONTROL, + IRP_MJ_SHUTDOWN, + IRP_MJ_LOCK_CONTROL, + IRP_MJ_CLEANUP, + IRP_MJ_CREATE_MAILSLOT, + IRP_MJ_QUERY_SECURITY, + IRP_MJ_SET_SECURITY, + IRP_MJ_POWER, + IRP_MJ_SYSTEM_CONTROL, + IRP_MJ_DEVICE_CHANGE, + IRP_MJ_QUERY_QUOTA, + IRP_MJ_SET_QUOTA, + IRP_MJ_PNP, + IRP_MJ_MAXIMUM_FUNCTION, +}; + +#define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL + +/* + * Minor function numbers for IRP_MJ_FILE_SYSTEM_CONTROL + */ +#define IRP_MN_USER_FS_REQUEST 0x00 +#define IRP_MN_MOUNT_VOLUME 0x01 +#define IRP_MN_VERIFY_VOLUME 0x02 +#define IRP_MN_LOAD_FILE_SYSTEM 0x03 + +/* + * Minor function numbers for IRP_MJ_SCSI + */ +#define IRP_MN_SCSI_CLASS 0x01 + +/* + * Minor function codes for IRP_MJ_POWER + */ +#define IRP_MN_WAIT_WAKE 0x00 +#define IRP_MN_POWER_SEQUENCE 0x01 +#define IRP_MN_SET_POWER 0x02 +#define IRP_MN_QUERY_POWER 0x03 + +/* + * Minor function codes for IRP_MJ_PNP + */ +#define IRP_MN_START_DEVICE 0x00 +#define IRP_MN_QUERY_REMOVE_DEVICE 0x01 +#define IRP_MN_REMOVE_DEVICE 0x02 +#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 +#define IRP_MN_STOP_DEVICE 0x04 +#define IRP_MN_QUERY_STOP_DEVICE 0x05 +#define IRP_MN_CANCEL_STOP_DEVICE 0x06 +#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 +#define IRP_MN_QUERY_INTERFACE 0x08 +#define IRP_MN_QUERY_CAPABILITIES 0x09 +#define IRP_MN_QUERY_RESOURCES 0x0A +#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B +#define IRP_MN_QUERY_DEVICE_TEXT 0x0C +#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D +#define IRP_MN_READ_CONFIG 0x0F +#define IRP_MN_WRITE_CONFIG 0x10 +#define IRP_MN_EJECT 0x11 +#define IRP_MN_SET_LOCK 0x12 +#define IRP_MN_QUERY_ID 0x13 +#define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14 +#define IRP_MN_QUERY_BUS_INFORMATION 0x15 +#define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16 +#define IRP_MN_SURPRISE_REMOVAL 0x17 +#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18 + + +/* + * Priority increments + */ +#define EVENT_INCREMENT 1 +#define IO_NO_INCREMENT 0 +#define IO_CD_ROM_INCREMENT 1 +#define IO_DISK_INCREMENT 4 +#define IO_KEYBOARD_INCREMENT 6 +#define IO_MAILSLOT_INCREMENT 2 +#define IO_MOUSE_INCREMENT 6 +#define IO_NAMED_PIPE_INCREMENT 2 +#define IO_NETWORK_INCREMENT 2 +#define IO_PARALLEL_INCREMENT 1 +#define IO_SERIAL_INCREMENT 2 +#define IO_SOUND_INCREMENT 8 +#define IO_VIDEO_INCREMENT 1 +#define MUTANT_INCREMENT 1 +#define SEMAPHORE_INCREMENT 1 + +#define FILE_BYTE_ALIGNMENT 0x00000000 +#define FILE_WORD_ALIGNMENT 0x00000001 +#define FILE_LONG_ALIGNMENT 0x00000003 +#define FILE_QUAD_ALIGNMENT 0x00000007 +#define FILE_OCTA_ALIGNMENT 0x0000000f +#define FILE_32_BYTE_ALIGNMENT 0x0000001f +#define FILE_64_BYTE_ALIGNMENT 0x0000003f +#define FILE_128_BYTE_ALIGNMENT 0x0000007f +#define FILE_256_BYTE_ALIGNMENT 0x000000ff +#define FILE_512_BYTE_ALIGNMENT 0x000001ff + +/* + * File disposition values + */ +#define FILE_SUPERSEDED 0x0000 +#define FILE_OPENED 0x0001 +#define FILE_CREATED 0x0002 +#define FILE_OVERWRITTEN 0x0003 +#define FILE_EXISTS 0x0004 +#define FILE_DOES_NOT_EXIST 0x0005 + + +/* + * file creation flags + */ +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 + +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_FOR_RECOVERY 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 + +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 + +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_TRANSACTED_MODE 0x00200000 +#define FILE_OPEN_OFFLINE_FILE 0x00400000 + +#define FILE_VALID_OPTION_FLAGS 0x007fffff +#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032 +#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032 +#define FILE_VALID_SET_FLAGS 0x00001036 + + +typedef ULONG FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; + +/* + * file system information class values + */ +#define FileFsVolumeInformation 1 +#define FileFsLabelInformation 2 +#define FileFsSizeInformation 3 +#define FileFsDeviceInformation 4 +#define FileFsAttributeInformation 5 +#define FileFsControlInformation 6 +#define FileFsQuotaQueryInformation 7 +#define FileFsQuotaSetInformation 8 +#define FileFsMaximumInformation 9 + +#define IRP_MN_QUERY_DIRECTORY 0x01 +#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 + +#endif diff --git a/include/ddk/iofuncs.h b/include/ddk/iofuncs.h new file mode 100644 index 0000000..08b8797 --- /dev/null +++ b/include/ddk/iofuncs.h @@ -0,0 +1,1229 @@ +#ifndef _INCLUDE_DDK_IOFUNCS_H +#define _INCLUDE_DDK_IOFUNCS_H +/* $Id$ */ + +/* --- EXPORTED BY NTOSKRNL --- */ + +/********************************************************************** + * NAME EXPORTED + * IoAcquireCancelSpinLock@4 + * + * DESCRIPTION + * Synchronizes cancelable-state transistions for IRPs in a + * multiprocessor-safe way. + * + * ARGUMENTS + * Irpl + * Variable to store the current IRQ level. + * + * RETURN VALUE + * None. + * + * REVISIONS + * + */ +VOID +STDCALL +IoAcquireCancelSpinLock ( + PKIRQL Irpl + ); +VOID +STDCALL +IoAcquireVpbSpinLock ( + PKIRQL Irpl + ); +/********************************************************************** + * NAME EXPORTED + * IoAllocateAdapterChannel@ + * + * DESCRIPTION + * Allocates an adaptor object for a DMA operation on the target + * device. + * + * ARGUMENTS + * Adaptor + * Adapter channel or busmaster adapter to be allocated; + * + * DeviceObject + * Target device for DMA; + * + * NumberOfMapRegisters + * Number of map registers; + * + * ExecutionRoutine + * Routine to be called when the adaptor is available; + * + * Context + * Driver defined contex that will be passed to the + * execution routine. + * + * RETURN VALUE + * Success or failure code. + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +IoAllocateAdapterChannel ( + PADAPTER_OBJECT AdaperObject, + PDEVICE_OBJECT DeviceObject, + ULONG NumberOfMapRegisters, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context + ); +/********************************************************************** + * NAME EXPORTED + * IoAllocateController@16 + * + * DESCRIPTION + * Sets up a call to a driver supplied controller object as + * soon as it is available. + * + * ARGUMENTS + * ControllerObject + * Driver created controller object; + * + * DeviceObject + * Target device; + * + * ExecutionObject + * Routine to be called; + * + * Context + * Driver determined context to be based to the + * routine. + * + * RETURN VALUE + * None. + * + * REVISIONS + * + */ +VOID +STDCALL +IoAllocateController ( + PCONTROLLER_OBJECT ControllerObject, + PDEVICE_OBJECT DeviceObject, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context + ); +/********************************************************************** + * NAME EXPORTED + * IoAllocateErrorLogEntry@8 + * + * DESCRIPTION + * Allocates an error log packet. + * + * ARGUMENTS + * IoObject + * Object which found the error; + * + * EntrySize + * Size in bytes of the packet to be allocated. + * + * RETURN VALUE + * On success, a pointer to the allocated packet. + * On failure, it returns NULL. + */ +PVOID +STDCALL +IoAllocateErrorLogEntry ( + PVOID IoObject, + UCHAR EntrySize + ); +/********************************************************************** + * NAME EXPORTED + * IoAllocateIrp@8 + * + * DESCRIPTION + * Allocates an IRP. + * + * ARGUMENTS + * StackSize + * Number of stack locations to allocate; + * + * ChargeQuota + * Who knows. + * + * RETURN VALUE + * On success, the allocated IRP. On failure, NULL. + */ +PIRP +STDCALL +IoAllocateIrp ( + CCHAR StackSize, + BOOLEAN ChargeQuota + ); +/********************************************************************** + * NAME EXPORTED + * IoAllocateMdl@20 + * + * DESCRIPTION + * Allocates an MDL large enough to map the supplied buffer. + * + * ARGUMENTS + * VirtualAddress + * Base virtual address of the buffer to be mapped; + * + * Length + * Length of the buffer to be mapped; + * + * SecondaryBuffer + * Whether the buffer is primary or secondary; + * + * ChargeQuota + * Charge non-paged pool quota to current thread; + * + * Irp + * Optional irp to be associated with the MDL. + * + * RETURN VALUE + * On success, the allocated MDL; on failure, NULL. + */ +PMDL +STDCALL +IoAllocateMdl ( + PVOID VirtualAddress, + ULONG Length, + BOOLEAN SecondaryBuffer, + BOOLEAN ChargeQuota, + PIRP Irp + ); + +/********************************************************************** + * NAME MACRO + * IoAssignArcName + * + * DESCRIPTION + * Creates a symbolic link between the ARC name of a physical + * device and the name of the corresponding device object + * + * ARGUMENTS + * ArcName + * ARC name of the device + * + * DeviceName + * Name of the device object + * + * NOTES + * VOID + * IoAssignArcName ( + * PUNICODE_STRING ArcName, + * PUNICODE_STRING DeviceName + * ); + */ +#define IoAssignArcName(ArcName,DeviceName) \ + (IoCreateSymbolicLink((ArcName),(DeviceName))) + +/********************************************************************** + * NAME EXPORTED + * IoAssignResources@24 + * + * DESCRIPTION + * Takes a list of requested hardware resources and allocates + * them. + * + * ARGUMENTS + * RegisterPath + * ? + * + * DriverClassName + * ? + * + * DriverObject + * Driver object passed to the DriverEntry routine; + * + * DeviceObject + * ? + * + * RequestedResources + * List of resources. + * + * RETURN VALUE + */ +NTSTATUS +STDCALL +IoAssignResources ( + PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, + PCM_RESOURCE_LIST * AllocatedResources + ); +/* + * FUNCTION: Attaches the callers device object to a named target device + * ARGUMENTS: + * SourceDevice = caller's device + * TargetDevice = Name of the target device + * AttachedDevice = Caller allocated storage. On return contains + * a pointer to the target device + * RETURNS: Success or failure code + */ +NTSTATUS +STDCALL +IoAttachDevice ( + PDEVICE_OBJECT SourceDevice, + PUNICODE_STRING TargetDevice, + PDEVICE_OBJECT * AttachedDevice + ); +/* + * FUNCTION: Obsolete + * ARGUMENTS: + * SourceDevice = device to attach + * TargetDevice = device to be attached to + * RETURNS: Success or failure code + */ +NTSTATUS +STDCALL +IoAttachDeviceByPointer ( + PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice + ); +/* + * FUNCTION: Attaches the callers device to the highest device in the chain + * ARGUMENTS: + * SourceDevice = caller's device + * TargetDevice = Device to attach + * RETURNS: On success the previously highest device + * On failure NULL + */ +PDEVICE_OBJECT +STDCALL +IoAttachDeviceToDeviceStack ( + PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice + ); +/* + * FUNCTION: Builds a irp to be sent to lower level drivers + * ARGUMENTS: + * MajorFunction = Major function code to be set in the IRP + * DeviceObject = Next lower device object + * Buffer = Buffer (only required for some major function codes) + * Length = Length in bytes of the buffer + * StartingOffset = Starting offset on the target device + * IoStatusBlock = Storage for status about the operation (optional) + * RETURNS: On success the IRP allocated + * On failure NULL + */ +PIRP +STDCALL +IoBuildAsynchronousFsdRequest ( + ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock + ); +/* + * FUNCTION: Allocates and sets up an IRP for a device control request + * ARGUMENTS: + * IoControlCode = Type of request + * DeviceObject = Target device + * InputBuffer = Optional input buffer to the driver + * InputBufferLength = Length of the input buffer + * OutputBuffer = Optional output buffer + * OutputBufferLength = Length of the output buffer + * InternalDeviceIoControl = TRUE if the request is internal + * Event = Initialized event for the caller to wait for the request + * to be completed + * IoStatusBlock = I/O status block to be set when the request is + * completed + * RETURNS: Returns the IRP created + */ +PIRP +STDCALL +IoBuildDeviceIoControlRequest ( + ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock + ); +VOID +STDCALL +IoBuildPartialMdl ( + PMDL SourceMdl, + PMDL TargetMdl, + PVOID VirtualAddress, + ULONG Length + ); +PIRP +STDCALL +IoBuildSynchronousFsdRequest ( + ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock + ); +NTSTATUS +STDCALL +IoCallDriver ( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ); +BOOLEAN +STDCALL +IoCancelIrp ( + PIRP Irp + ); + +NTSTATUS STDCALL +IoCheckDesiredAccess(IN OUT PACCESS_MASK DesiredAccess, + IN ACCESS_MASK GrantedAccess); + +NTSTATUS STDCALL +IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, + IN ULONG EaLength, + OUT PULONG ErrorOffset); + +NTSTATUS STDCALL +IoCheckFunctionAccess(IN ACCESS_MASK GrantedAccess, + IN UCHAR MajorFunction, + IN UCHAR MinorFunction, + IN ULONG IoControlCode, + IN PFILE_INFORMATION_CLASS FileInformationClass OPTIONAL, + IN PFS_INFORMATION_CLASS FsInformationClass OPTIONAL); + +NTSTATUS +STDCALL +IoCheckShareAccess ( + ACCESS_MASK DesiredAccess, + ULONG DesiredShareAccess, + PFILE_OBJECT FileObject, + PSHARE_ACCESS ShareAccess, + BOOLEAN Update + ); +VOID +STDCALL +IoCompleteRequest ( + PIRP Irp, + CCHAR PriorityBoost + ); +NTSTATUS +STDCALL +IoConnectInterrupt ( + PKINTERRUPT * InterruptObject, + PKSERVICE_ROUTINE ServiceRoutine, + PVOID ServiceContext, + PKSPIN_LOCK SpinLock, + ULONG Vector, + KIRQL Irql, + KIRQL SynchronizeIrql, + KINTERRUPT_MODE InterruptMode, + BOOLEAN ShareVector, + KAFFINITY ProcessorEnableMask, + BOOLEAN FloatingSave + ); + +PCONTROLLER_OBJECT +STDCALL +IoCreateController ( + ULONG Size + ); +/* + * FUNCTION: Allocates memory for and intializes a device object for use for + * a driver + * ARGUMENTS: + * DriverObject : Driver object passed by iomgr when the driver was + * loaded + * DeviceExtensionSize : Number of bytes for the device extension + * DeviceName : Unicode name of device + * DeviceType : Device type + * DeviceCharacteristics : Bit mask of device characteristics + * Exclusive : True if only one thread can access the device at a + * time + * RETURNS: + * Success or failure + * DeviceObject : Contains a pointer to allocated device object + * if the call succeeded + * NOTES: See the DDK documentation for more information + */ +NTSTATUS +STDCALL +IoCreateDevice ( + PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + DEVICE_TYPE DeviceType, + ULONG DeviceCharacteristics, + BOOLEAN Exclusive, + PDEVICE_OBJECT * DeviceObject + ); +NTSTATUS +STDCALL +IoCreateFile ( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength, + IN CREATE_FILE_TYPE CreateFileType, + IN PVOID ExtraCreateParameters OPTIONAL, + IN ULONG Options + ); +PKEVENT +STDCALL +IoCreateNotificationEvent ( + PUNICODE_STRING EventName, + PHANDLE EventHandle + ); +PFILE_OBJECT +STDCALL +IoCreateStreamFileObject ( + PFILE_OBJECT FileObject, + PDEVICE_OBJECT DeviceObject + ); +NTSTATUS +STDCALL +IoCreateSymbolicLink ( + PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName + ); +PKEVENT +STDCALL +IoCreateSynchronizationEvent ( + PUNICODE_STRING EventName, + PHANDLE EventHandle + ); +NTSTATUS +STDCALL +IoCreateUnprotectedSymbolicLink ( + PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName + ); + +/* + * FUNCTION: + * Deletes a symbolic link between the ARC name of a physical + * device and the name of the corresponding device object + * + * ARGUMENTS: + * ArcName = ARC name of the device + * + * NOTES: + * VOID + * IoDeassignArcName ( + * PUNICODE_STRING ArcName + * ); + */ +#define IoDeassignArcName(ArcName) \ + (IoDeleteSymbolicLink((ArcName))) + +VOID +STDCALL +IoDeleteController ( + PCONTROLLER_OBJECT ControllerObject + ); +VOID +STDCALL +IoDeleteDevice ( + PDEVICE_OBJECT DeviceObject + ); +NTSTATUS +STDCALL +IoDeleteSymbolicLink ( + PUNICODE_STRING SymbolicLinkName + ); +VOID +STDCALL +IoDetachDevice ( + PDEVICE_OBJECT TargetDevice + ); +VOID +STDCALL +IoDisconnectInterrupt ( + PKINTERRUPT InterruptObject + ); +VOID +STDCALL +IoEnqueueIrp ( + PIRP Irp + ); + +BOOLEAN STDCALL +IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + IN ULONG OpenOptions, + OUT PIO_STATUS_BLOCK IoStatus, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer); + +VOID +STDCALL +IoFreeController ( + PCONTROLLER_OBJECT ControllerObject + ); +VOID +STDCALL +IoFreeIrp ( + PIRP Irp + ); +VOID +STDCALL +IoFreeMdl ( + PMDL Mdl + ); +PDEVICE_OBJECT +STDCALL +IoGetAttachedDevice ( + PDEVICE_OBJECT DeviceObject + ); +PDEVICE_OBJECT +STDCALL +IoGetAttachedDeviceReference ( + PDEVICE_OBJECT DeviceObject + ); +PDEVICE_OBJECT +STDCALL +IoGetBaseFileSystemDeviceObject ( + IN PFILE_OBJECT FileObject + ); +PCONFIGURATION_INFORMATION +STDCALL +IoGetConfigurationInformation ( + VOID + ); + +/* + * FUNCTION: Gets a pointer to the callers location in the I/O stack in + * the given IRP + * ARGUMENTS: + * Irp = Points to the IRP + * RETURNS: A pointer to the stack location + * + * NOTES: + * PIO_STACK_LOCATION + * IoGetCurrentIrpStackLocation (PIRP Irp) + */ +#define IoGetCurrentIrpStackLocation(Irp) \ + ((Irp)->Tail.Overlay.CurrentStackLocation) + +#define IoSetNextIrpStackLocation(Irp) { \ + (Irp)->CurrentLocation--; \ + (Irp)->Tail.Overlay.CurrentStackLocation--; } + +#define IoCopyCurrentIrpStackLocationToNext(Irp) { \ + PIO_STACK_LOCATION IrpSp; \ + PIO_STACK_LOCATION NextIrpSp; \ + IrpSp = IoGetCurrentIrpStackLocation((Irp)); \ + NextIrpSp = IoGetNextIrpStackLocation((Irp)); \ + RtlCopyMemory(NextIrpSp, IrpSp, \ + FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); \ + NextIrpSp->Control = 0; } + +#define IoSkipCurrentIrpStackLocation(Irp) \ + (Irp)->CurrentLocation++; \ + (Irp)->Tail.Overlay.CurrentStackLocation++; + +struct _EPROCESS* +STDCALL +IoGetCurrentProcess ( + VOID + ); +NTSTATUS +STDCALL +IoGetDeviceObjectPointer ( + PUNICODE_STRING ObjectName, + ACCESS_MASK DesiredAccess, + PFILE_OBJECT * FileObject, + PDEVICE_OBJECT * DeviceObject + ); +PDEVICE_OBJECT +STDCALL +IoGetDeviceToVerify ( + struct _ETHREAD* Thread + ); +PGENERIC_MAPPING +STDCALL +IoGetFileObjectGenericMapping ( + VOID + ); + +#define IoGetFunctionCodeFromCtlCode(ControlCode) \ + ((ControlCode >> 2) & 0x00000FFF) + +PVOID +STDCALL +IoGetInitialStack ( + VOID + ); + +/* + * FUNCTION: Gives a higher level driver access to the next lower driver's + * I/O stack location + * ARGUMENTS: + * Irp = points to the irp + * RETURNS: A pointer to the stack location + * + * NOTES: + * PIO_STACK_LOCATION + * IoGetNextIrpStackLocation (PIRP Irp) + */ +#define IoGetNextIrpStackLocation(Irp) \ + ((Irp)->Tail.Overlay.CurrentStackLocation-1) + + +PDEVICE_OBJECT +STDCALL +IoGetRelatedDeviceObject ( + PFILE_OBJECT FileObject + ); +struct _EPROCESS* +STDCALL +IoGetRequestorProcess ( + IN PIRP Irp + ); + +VOID +STDCALL +IoGetStackLimits ( + PULONG LowLimit, + PULONG HighLimit + ); + +PIRP +STDCALL +IoGetTopLevelIrp ( + VOID + ); + +#define IoInitializeDpcRequest(DeviceObject,DpcRoutine) \ + (KeInitializeDpc(&(DeviceObject)->Dpc, \ + (PKDEFERRED_ROUTINE)(DpcRoutine), \ + (DeviceObject))) + +/* + * FUNCTION: Initalizes an irp allocated by the caller + * ARGUMENTS: + * Irp = IRP to initalize + * PacketSize = Size in bytes of the IRP + * StackSize = Number of stack locations in the IRP + */ +VOID +STDCALL +IoInitializeIrp ( + PIRP Irp, + USHORT PacketSize, + CCHAR StackSize + ); +NTSTATUS +STDCALL +IoInitializeTimer ( + PDEVICE_OBJECT DeviceObject, + PIO_TIMER_ROUTINE TimerRoutine, + PVOID Context + ); + +/* + * NOTES: + * BOOLEAN + * IsErrorUserInduced (NTSTATUS Status) + */ +#define IoIsErrorUserInduced(Status) \ + ((BOOLEAN)(((Status) == STATUS_DEVICE_NOT_READY) || \ + ((Status) == STATUS_IO_TIMEOUT) || \ + ((Status) == STATUS_MEDIA_WRITE_PROTECTED) || \ + ((Status) == STATUS_NO_MEDIA_IN_DRIVE) || \ + ((Status) == STATUS_VERIFY_REQUIRED) || \ + ((Status) == STATUS_UNRECOGNIZED_MEDIA) || \ + ((Status) == STATUS_WRONG_VOLUME))) + +BOOLEAN +STDCALL +IoIsOperationSynchronous ( + IN PIRP Irp + ); +BOOLEAN +STDCALL +IoIsSystemThread ( + PVOID Unknown0 + ); +PIRP +STDCALL +IoMakeAssociatedIrp ( + PIRP Irp, + CCHAR StackSize + ); + +/* + * FUNCTION: Marks the specified irp, indicating further processing will + * be required by other driver routines + * ARGUMENTS: + * Irp = Irp to mark + * NOTES: + * VOID + * IoMarkIrpPending (PIRP Irp) + */ +#define IoMarkIrpPending(Irp) \ + (IoGetCurrentIrpStackLocation(Irp)->Control |= SL_PENDING_RETURNED) + + +NTSTATUS +STDCALL +IoOpenDeviceInstanceKey ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ); +NTSTATUS +STDCALL +IoQueryDeviceDescription ( + PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, + PVOID Context + ); +DWORD +STDCALL +IoQueryDeviceEnumInfo ( + DWORD Unknown0, + DWORD Unknown1 + ); +// IoQueryFileInformation: confirmed - Undocumented because it does not require a valid file handle +NTSTATUS +STDCALL +IoQueryFileInformation ( + IN PFILE_OBJECT FileObject, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + OUT PVOID FileInformation, + OUT PULONG ReturnedLength + ); +NTSTATUS +STDCALL +IoQueryVolumeInformation ( + IN PFILE_OBJECT FileObject, + IN FS_INFORMATION_CLASS FsInformationClass, + IN ULONG Length, + OUT PVOID FsInformation, + OUT PULONG ReturnedLength + ); +VOID +STDCALL +IoQueueThreadIrp ( + IN PIRP Irp + ); + +VOID +STDCALL +IoQueueWorkItem( + IN PIO_WORKITEM IoWorkItem, + IN PIO_WORKITEM_ROUTINE WorkerRoutine, + IN WORK_QUEUE_TYPE QueueType, + IN PVOID Context + ); + +VOID +STDCALL +IoFreeWorkItem( + PIO_WORKITEM IoWorkItem + ); + +PIO_WORKITEM +STDCALL +IoAllocateWorkItem( + PDEVICE_OBJECT DeviceObject + ); + +VOID +STDCALL +IoRaiseHardError ( + PIRP Irp, + PVPB Vpb, + PDEVICE_OBJECT RealDeviceObject + ); +BOOLEAN +STDCALL +IoRaiseInformationalHardError ( + NTSTATUS ErrorStatus, + PUNICODE_STRING String, + struct _KTHREAD* Thread + ); +VOID +STDCALL +IoRegisterDriverReinitialization ( + PDRIVER_OBJECT DriverObject, + PDRIVER_REINITIALIZE ReinitRoutine, + PVOID Context + ); +VOID +STDCALL +IoRegisterFileSystem ( + PDEVICE_OBJECT DeviceObject + ); +#if (_WIN32_WINNT >= 0x0400) +NTSTATUS +STDCALL +IoRegisterFsRegistrationChange ( + IN PDRIVER_OBJECT DriverObject, + IN PFSDNOTIFICATIONPROC FSDNotificationProc + ); +#endif // (_WIN32_WINNT >= 0x0400) +NTSTATUS +STDCALL +IoRegisterShutdownNotification ( + PDEVICE_OBJECT DeviceObject + ); +VOID +STDCALL +IoReleaseCancelSpinLock ( + IN KIRQL Irql + ); +VOID +STDCALL +IoReleaseVpbSpinLock ( + IN KIRQL Irql + ); +VOID +STDCALL +IoRemoveShareAccess ( + PFILE_OBJECT FileObject, + PSHARE_ACCESS ShareAccess + ); +NTSTATUS +STDCALL +IoReportHalResourceUsage ( + IN PUNICODE_STRING HalDescription, + IN PCM_RESOURCE_LIST RawList, + IN PCM_RESOURCE_LIST TranslatedList, + IN ULONG ListSize + ); +NTSTATUS +STDCALL +IoReportResourceUsage ( + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PCM_RESOURCE_LIST DriverList, + ULONG DriverListSize, + PDEVICE_OBJECT DeviceObject, + PCM_RESOURCE_LIST DeviceList, + ULONG DeviceListSize, + BOOLEAN OverrideConflict, + PBOOLEAN ConflictDetected + ); + +#define IoRequestDpc(DeviceObject,Irp,Context) \ + (KeInsertQueueDpc(&(DeviceObject)->Dpc,(Irp),(Context))) + +#define IoSetCancelRoutine(Irp,NewCancelRoutine) \ + ((PDRIVER_CANCEL)InterlockedExchange((PULONG)&(Irp)->CancelRoutine, \ + (ULONG)(NewCancelRoutine))); + +#define IoSetCompletionRoutine(Irp,Routine,Context,Success,Error,Cancel) \ + { \ + PIO_STACK_LOCATION param; \ + assert((Success)||(Error)||(Cancel)?(Routine)!=NULL:TRUE); \ + param = IoGetNextIrpStackLocation((Irp)); \ + param->CompletionRoutine=(Routine); \ + param->CompletionContext=(Context); \ + param->Control = 0; \ + if ((Success)) \ + param->Control = SL_INVOKE_ON_SUCCESS; \ + if ((Error)) \ + param->Control |= SL_INVOKE_ON_ERROR; \ + if ((Cancel)) \ + param->Control |= SL_INVOKE_ON_CANCEL; \ + } + +VOID STDCALL +IoSetDeviceToVerify (IN struct _ETHREAD* Thread, + IN PDEVICE_OBJECT DeviceObject); +VOID +STDCALL +IoSetHardErrorOrVerifyDevice ( + IN PIRP Irp, + IN PDEVICE_OBJECT DeviceObject + ); +NTSTATUS +STDCALL +IoSetInformation ( + IN PFILE_OBJECT FileObject, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + OUT PVOID FileInformation + ); + +#define IoSetNextIrpStackLocation(Irp) \ +{ \ + (Irp)->CurrentLocation--; \ + (Irp)->Tail.Overlay.CurrentStackLocation--; \ +} + +VOID +STDCALL +IoSetShareAccess ( + ACCESS_MASK DesiredAccess, + ULONG DesiredShareAccess, + PFILE_OBJECT FileObject, + PSHARE_ACCESS ShareAccess + ); +BOOLEAN +STDCALL +IoSetThreadHardErrorMode ( + IN BOOLEAN HardErrorEnabled + ); +VOID +STDCALL +IoSetTopLevelIrp ( + IN PIRP Irp + ); + +/* + * FUNCTION: Determines the size of an IRP + * ARGUMENTS: + * StackSize = number of stack locations in the IRP + * RETURNS: The size of the IRP in bytes +USHORT +IoSizeOfIrp (CCHAR StackSize) + */ +#define IoSizeOfIrp(StackSize) \ + ((USHORT)(sizeof(IRP)+(((StackSize)-1)*sizeof(IO_STACK_LOCATION)))) + +/* original macro */ +/* +#define IoSizeOfIrp(StackSize) \ + ((USHORT)(sizeof(IRP)+((StackSize)*sizeof(IO_STACK_LOCATION)))) +*/ + +/* + * FUNCTION: Dequeues the next IRP from the device's associated queue and + * calls its StartIo routine + * ARGUMENTS: + * DeviceObject = Device object + * Cancelable = True if IRPs in the queue can be cancelled + */ +VOID +STDCALL +IoStartNextPacket ( + PDEVICE_OBJECT DeviceObject, + BOOLEAN Cancelable + ); +VOID +STDCALL +IoStartNextPacketByKey ( + PDEVICE_OBJECT DeviceObject, + BOOLEAN Cancelable, + ULONG Key + ); +/* + * FUNCTION: Calls the drivers StartIO routine with the IRP or queues it if + * the device is busy + * ARGUMENTS: + * DeviceObject = Device to pass the IRP to + * Irp = Irp to be processed + * Key = Optional value for where to insert the IRP + * CancelFunction = Entry point for a driver supplied cancel function + */ +VOID +STDCALL +IoStartPacket ( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PULONG Key, + PDRIVER_CANCEL CancelFunction + ); +VOID +STDCALL +IoStartTimer ( + PDEVICE_OBJECT DeviceObject + ); +VOID +STDCALL +IoStopTimer ( + PDEVICE_OBJECT DeviceObject + ); + +NTSTATUS STDCALL +IoPageRead(PFILE_OBJECT FileObject, + PMDL Mdl, + PLARGE_INTEGER Offset, + PKEVENT Event, + PIO_STATUS_BLOCK StatusBlock); + +NTSTATUS STDCALL +IoSynchronousPageWrite (PFILE_OBJECT FileObject, + PMDL Mdl, + PLARGE_INTEGER Offset, + PKEVENT Event, + PIO_STATUS_BLOCK StatusBlock); + +struct _EPROCESS* STDCALL IoThreadToProcess (struct _ETHREAD* Thread); +VOID +STDCALL +IoUnregisterFileSystem ( + IN PDEVICE_OBJECT DeviceObject + ); +#if (_WIN32_WINNT >= 0x0400) +VOID +STDCALL +IoUnregisterFsRegistrationChange ( + IN PDRIVER_OBJECT DriverObject, + IN PFSDNOTIFICATIONPROC FSDNotificationProc + ); +#endif // (_WIN32_WINNT >= 0x0400) +VOID +STDCALL +IoUnregisterShutdownNotification ( + IN PDEVICE_OBJECT DeviceObject + ); +VOID +STDCALL +IoUpdateShareAccess ( + IN PFILE_OBJECT FileObject, + IN PSHARE_ACCESS ShareAccess + ); +NTSTATUS +STDCALL +IoVerifyVolume ( + IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN AllowRawMount + ); +VOID +STDCALL +IoWriteErrorLogEntry ( + PVOID ElEntry + ); +/* + * FUNCTION: Sends an irp to the next lower driver + */ +NTSTATUS +FASTCALL +IofCallDriver ( + PDEVICE_OBJECT DeviceObject, + PIRP Irp + ); +/* + * FUNCTION: Indicates the caller has finished all processing for a given + * I/O request and is returning the given IRP to the I/O manager + * ARGUMENTS: + * Irp = Irp to be cancelled + * PriorityBoost = Increment by which to boost the priority of the + * thread making the request + */ +VOID +FASTCALL +IofCompleteRequest ( + PIRP Irp, + CCHAR PriorityBoost + ); + +/* --- EXPORTED BY HAL --- */ + +VOID +STDCALL +IoAssignDriveLetters ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PSTRING NtDeviceName, + OUT PUCHAR NtSystemPath, + OUT PSTRING NtSystemPathString + ); + +BOOLEAN +STDCALL +IoFlushAdapterBuffers ( + PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + ULONG Length, + BOOLEAN WriteToDevice + ); + +VOID +STDCALL +IoFreeAdapterChannel ( + PADAPTER_OBJECT AdapterObject + ); + +VOID +STDCALL +IoFreeMapRegisters ( + PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters + ); + +PHYSICAL_ADDRESS +STDCALL +IoMapTransfer ( + PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + PULONG Length, + BOOLEAN WriteToDevice + ); + +NTSTATUS +STDCALL +IoReadPartitionTable ( + PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + BOOLEAN ReturnedRecognizedPartitions, + PDRIVE_LAYOUT_INFORMATION * PartitionBuffer + ); + +NTSTATUS +STDCALL +IoSetPartitionInformation ( + PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG PartitionNumber, + ULONG PartitionType + ); + +NTSTATUS +STDCALL +IoWritePartitionTable ( + PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG SectorsPerTrack, + ULONG NumberOfHeads, + PDRIVE_LAYOUT_INFORMATION PartitionBuffer + ); + + +/* --- --- --- INTERNAL or REACTOS ONLY --- --- --- */ + +/* + * FUNCTION: Registers the driver with WMI + * ARGUMENTS: + * DeviceObject = Device to register + * Action = Action to take + * RETURNS: Status (?) + */ +/* +NTSTATUS +IoWMIRegistrationControl ( + PDEVICE_OBJECT DeviceObject, + WMIREGACTION Action); +*/ + +BOOLEAN +IoIsTotalDeviceFailure ( + NTSTATUS Status + ); + + +#endif /* ndef _INCLUDE_DDK_IOFUNCS_H */ diff --git a/include/ddk/iotypes.h b/include/ddk/iotypes.h new file mode 100644 index 0000000..d04fd7f --- /dev/null +++ b/include/ddk/iotypes.h @@ -0,0 +1,854 @@ +/* $Id$ + * + */ + +#ifndef __INCLUDE_DDK_IOTYPES_H +#define __INCLUDE_DDK_IOTYPES_H + +#include +#include + +#ifdef __NTOSKRNL__ +extern POBJECT_TYPE EXPORTED IoAdapterObjectType; +extern POBJECT_TYPE EXPORTED IoDeviceHandlerObjectType; +extern POBJECT_TYPE EXPORTED IoDeviceObjectType; +extern POBJECT_TYPE EXPORTED IoDriverObjectType; +extern POBJECT_TYPE EXPORTED IoFileObjectType; +#else +extern POBJECT_TYPE IMPORTED IoAdapterObjectType; +extern POBJECT_TYPE IMPORTED IoDeviceHandlerObjectType; +extern POBJECT_TYPE IMPORTED IoDeviceObjectType; +extern POBJECT_TYPE IMPORTED IoDriverObjectType; +extern POBJECT_TYPE IMPORTED IoFileObjectType; +#endif + +/* + * These are referenced before they can be fully defined + */ +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _DEVICE_OBJECT; +struct _IRP; +struct _IO_STATUS_BLOCK; +struct _SCSI_REQUEST_BLOCK; + +/* SIMPLE TYPES *************************************************************/ + +enum +{ + DeallocateObject, + KeepObject, +}; + + +typedef enum _CREATE_FILE_TYPE +{ + CreateFileTypeNone, + CreateFileTypeNamedPipe, + CreateFileTypeMailslot +} CREATE_FILE_TYPE; + + +typedef struct _SHARE_ACCESS +{ + ULONG OpenCount; + ULONG Readers; + ULONG Writers; + ULONG Deleters; + ULONG SharedRead; + ULONG SharedWrite; + ULONG SharedDelete; +} SHARE_ACCESS, *PSHARE_ACCESS; + +/* FUNCTION TYPES ************************************************************/ + +typedef VOID STDCALL +(*PDRIVER_REINITIALIZE)(struct _DRIVER_OBJECT* DriverObject, + PVOID Context, + ULONG Count); + +typedef NTSTATUS STDCALL +(*PIO_QUERY_DEVICE_ROUTINE)(PVOID Context, + PUNICODE_STRING Pathname, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION* BI, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION* CI, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION* PI); + +typedef NTSTATUS STDCALL +(*PIO_COMPLETION_ROUTINE)(struct _DEVICE_OBJECT* DeviceObject, + struct _IRP* Irp, + PVOID Context); + +typedef VOID STDCALL +(*PIO_APC_ROUTINE)(PVOID ApcContext, + struct _IO_STATUS_BLOCK* IoStatusBlock, + ULONG Reserved); + + +/* STRUCTURE TYPES ***********************************************************/ + +typedef struct _ADAPTER_OBJECT ADAPTER_OBJECT, *PADAPTER_OBJECT; + +/* + * PURPOSE: Special timer associated with each device + * NOTES: This is a guess + */ +typedef struct _IO_TIMER +{ + KTIMER timer; + KDPC dpc; +} IO_TIMER, *PIO_TIMER; + +typedef struct _IO_SECURITY_CONTEXT +{ + PSECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_STATE AccessState; + ACCESS_MASK DesiredAccess; + ULONG FullCreateOptions; +} IO_SECURITY_CONTEXT, *PIO_SECURITY_CONTEXT; + + +typedef struct _IO_RESOURCE_DESCRIPTOR +{ + UCHAR Option; + UCHAR Type; + UCHAR ShareDisposition; + + /* + * Reserved for system use + */ + UCHAR Spare1; + + USHORT Flags; + + /* + * Reserved for system use + */ + UCHAR Spare2; + + union + { + struct + { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; + } Port; + struct + { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; + } Memory; + struct + { + ULONG MinimumVector; + ULONG MaximumVector; + } Interrupt; + struct + { + ULONG MinimumChannel; + ULONG MaximumChannel; + } Dma; + } u; +} IO_RESOURCE_DESCRIPTOR, *PIO_RESOURCE_DESCRIPTOR; + +// IO_RESOURCE_DESCRIPTOR Options +#define IO_RESOURCE_REQUIRED 0x00 +#define IO_RESOURCE_PREFERRED 0x01 +#define IO_RESOURCE_DEFAULT 0x02 +#define IO_RESOURCE_ALTERNATIVE 0x08 + +typedef struct _IO_RESOURCE_LIST +{ + USHORT Version; + USHORT Revision; + ULONG Count; + IO_RESOURCE_DESCRIPTOR Descriptors[1]; +} IO_RESOURCE_LIST, *PIO_RESOURCE_LIST; + +typedef struct _IO_RESOURCE_REQUIREMENTS_LIST +{ + /* + * List size in bytes + */ + ULONG ListSize; + + /* + * System defined enum for the bus + */ + INTERFACE_TYPE InterfaceType; + + ULONG BusNumber; + ULONG SlotNumber; + ULONG Reserved[3]; + ULONG AlternativeLists; + IO_RESOURCE_LIST List[1]; +} IO_RESOURCE_REQUIREMENTS_LIST, *PIO_RESOURCE_REQUIREMENTS_LIST; + +typedef struct +{ + UCHAR Type; + UCHAR ShareDisposition; + USHORT Flags; + union + { + struct + { + PHYSICAL_ADDRESS Start; + ULONG Length; + } __attribute__((packed)) Port; + struct + { + ULONG Level; + ULONG Vector; + ULONG Affinity; + } __attribute__((packed))Interrupt; + struct + { + PHYSICAL_ADDRESS Start; + ULONG Length; + } __attribute__((packed))Memory; + struct + { + ULONG Channel; + ULONG Port; + ULONG Reserved1; + } __attribute__((packed))Dma; + struct + { + ULONG DataSize; + ULONG Reserved1; + ULONG Reserved2; + } __attribute__((packed))DeviceSpecificData; + } __attribute__((packed)) u; +} __attribute__((packed)) CM_PARTIAL_RESOURCE_DESCRIPTOR, *PCM_PARTIAL_RESOURCE_DESCRIPTOR; + +typedef struct +{ + USHORT Version; + USHORT Revision; + ULONG Count; + CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; +} __attribute__((packed))CM_PARTIAL_RESOURCE_LIST, *PCM_PARTIAL_RESOURCE_LIST; + +typedef struct +{ + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + CM_PARTIAL_RESOURCE_LIST PartialResourceList; +} __attribute__((packed)) CM_FULL_RESOURCE_DESCRIPTOR; + +typedef struct +{ + ULONG Count; + CM_FULL_RESOURCE_DESCRIPTOR List[1]; +} CM_RESOURCE_LIST, *PCM_RESOURCE_LIST; + + +/* + * PURPOSE: IRP stack location + */ +typedef struct __attribute__((packed)) _IO_STACK_LOCATION +{ + UCHAR MajorFunction; + UCHAR MinorFunction; + UCHAR Flags; + UCHAR Control; + + union + { + struct + { + PIO_SECURITY_CONTEXT SecurityContext; + ULONG Options; + USHORT FileAttributes; + USHORT ShareAccess; + ULONG EaLength; + } Create; + struct + { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; + } Read; + struct + { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; + } Write; + struct + { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG IoControlCode; + PVOID Type3InputBuffer; + } DeviceIoControl; + struct + { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG IoControlCode; + PVOID Type3InputBuffer; + } FileSystemControl; + struct + { + struct _VPB* Vpb; + struct _DEVICE_OBJECT* DeviceObject; + } MountVolume; + struct + { + struct _VPB* Vpb; + struct _DEVICE_OBJECT* DeviceObject; + } VerifyVolume; + struct + { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; + } QueryFile; + struct + { + ULONG Length; + FS_INFORMATION_CLASS FsInformationClass; + } QueryVolume; + struct + { + ULONG Length; + FS_INFORMATION_CLASS FsInformationClass; + } SetVolume; + struct + { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; + struct _FILE_OBJECT* FileObject; + union + { + struct + { + BOOLEAN ReplaceIfExists; + BOOLEAN AdvanceOnly; + } d; + ULONG ClusterCount; + HANDLE DeleteHandle; + } u; + } SetFile; + struct + { + ULONG Length; + PUNICODE_STRING FileName; + FILE_INFORMATION_CLASS FileInformationClass; + ULONG FileIndex; + } QueryDirectory; + + // Parameters for IRP_MN_QUERY_DEVICE_RELATIONS + struct + { + DEVICE_RELATION_TYPE Type; + } QueryDeviceRelations; + + // Parameters for IRP_MN_QUERY_INTERFACE + struct + { + CONST GUID *InterfaceType; + USHORT Size; + USHORT Version; + PINTERFACE Interface; + PVOID InterfaceSpecificData; + } QueryInterface; + + // Parameters for IRP_MN_QUERY_CAPABILITIES + struct + { + PDEVICE_CAPABILITIES Capabilities; + } DeviceCapabilities; + + // Parameters for IRP_MN_FILTER_RESOURCE_REQUIREMENTS + struct + { + PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList; + } FilterResourceRequirements; + + // Parameters for IRP_MN_QUERY_ID + struct + { + BUS_QUERY_ID_TYPE IdType; + } QueryId; + + // Parameters for IRP_MN_QUERY_DEVICE_TEXT + struct + { + DEVICE_TEXT_TYPE DeviceTextType; + LCID LocaleId; + } QueryDeviceText; + + // Parameters for IRP_MN_DEVICE_USAGE_NOTIFICATION + struct + { + BOOLEAN InPath; + BOOLEAN Reserved[3]; + DEVICE_USAGE_NOTIFICATION_TYPE Type; + } UsageNotification; + + // Parameters for IRP_MN_WAIT_WAKE + struct + { + SYSTEM_POWER_STATE PowerState; + } WaitWake; + + // Parameter for IRP_MN_POWER_SEQUENCE + struct + { + PPOWER_SEQUENCE PowerSequence; + } PowerSequence; + + // Parameters for IRP_MN_SET_POWER and IRP_MN_QUERY_POWER + struct + { + ULONG SystemContext; + POWER_STATE_TYPE Type; + POWER_STATE State; + POWER_ACTION ShutdownType; + } Power; + + // Parameters for IRP_MN_START_DEVICE + struct + { + PCM_RESOURCE_LIST AllocatedResources; + PCM_RESOURCE_LIST AllocatedResourcesTranslated; + } StartDevice; + + /* Parameters for IRP_MN_SCSI_CLASS */ + struct + { + struct _SCSI_REQUEST_BLOCK *Srb; + } Scsi; + + /* Paramters for other calls */ + struct + { + PVOID Argument1; + PVOID Argument2; + PVOID Argument3; + PVOID Argument4; + } Others; + } Parameters; + + struct _DEVICE_OBJECT* DeviceObject; + struct _FILE_OBJECT* FileObject; + + PIO_COMPLETION_ROUTINE CompletionRoutine; + PVOID CompletionContext; + +} __attribute__((packed)) IO_STACK_LOCATION, *PIO_STACK_LOCATION; + + +typedef struct _IO_STATUS_BLOCK +{ + NTSTATUS Status; + ULONG Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + + +typedef struct _IO_PIPE_CREATE_BUFFER +{ + BOOLEAN WriteModeMessage; + BOOLEAN ReadModeMessage; + BOOLEAN NonBlocking; + ULONG MaxInstances; + ULONG InBufferSize; + ULONG OutBufferSize; + LARGE_INTEGER TimeOut; +} IO_PIPE_CREATE_BUFFER, *PIO_PIPE_CREATE_BUFFER; + + +typedef struct _IO_MAILSLOT_CREATE_BUFFER +{ + ULONG Param; /* ?? */ + ULONG MaxMessageSize; + LARGE_INTEGER TimeOut; +} IO_MAILSLOT_CREATE_BUFFER, *PIO_MAILSLOT_CREATE_BUFFER; + + +/* + * Driver entry point declaration + */ +typedef NTSTATUS STDCALL +(*PDRIVER_INITIALIZE)(struct _DRIVER_OBJECT* DriverObject, + PUNICODE_STRING RegistryPath); + +/* + * Driver cancel declaration + */ +typedef NTSTATUS STDCALL +(*PDRIVER_CANCEL)(struct _DEVICE_OBJECT* DeviceObject, + struct _IRP* RegistryPath); + + +typedef struct _SECTION_OBJECT_POINTERS +{ + PVOID DataSectionObject; + PVOID SharedCacheMap; + PVOID ImageSectionObject; +} SECTION_OBJECT_POINTERS, *PSECTION_OBJECT_POINTERS; + +typedef struct _IO_COMPLETION_CONTEXT +{ + PVOID Port; + ULONG Key; +} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT; + +#define FO_FILE_OPEN 0x00000001 +#define FO_SYNCHRONOUS_IO 0x00000002 +#define FO_ALERTABLE_IO 0x00000004 +#define FO_NO_INTERMEDIATE_BUFFERING 0x00000008 +#define FO_WRITE_THROUGH 0x00000010 +#define FO_SEQUENTIAL_ONLY 0x00000020 +#define FO_CACHE_SUPPORTED 0x00000040 +#define FO_NAMED_PIPE 0x00000080 +#define FO_STREAM_FILE 0x00000100 +#define FO_MAILSLOT 0x00000200 +#define FO_GENERATE_AUDIT_ON_CLOSE 0x00000400 +#define FO_DIRECT_DEVICE_OPEN 0x00000800 +#define FO_FILE_MODIFIED 0x00001000 +#define FO_FILE_SIZE_CHANGED 0x00002000 +#define FO_CLEANUP_COMPLETE 0x00004000 +#define FO_TEMPORARY_FILE 0x00008000 +#define FO_DELETE_ON_CLOSE 0x00010000 +#define FO_OPENED_CASE_SENSITIVE 0x00020000 +#define FO_HANDLE_CREATED 0x00040000 +#define FO_FILE_FAST_IO_READ 0x00080000 + +/* + * ReactOS specific flags + */ +#define FO_DIRECT_CACHE_READ 0x72000001 +#define FO_DIRECT_CACHE_WRITE 0x72000002 +#define FO_DIRECT_CACHE_PAGING_READ 0x72000004 +#define FO_DIRECT_CACHE_PAGING_WRITE 0x72000008 +#define FO_FCB_IS_VALID 0x72000010 + +typedef struct _FILE_OBJECT +{ + CSHORT Type; + CSHORT Size; + struct _DEVICE_OBJECT* DeviceObject; + struct _VPB* Vpb; + PVOID FsContext; + PVOID FsContext2; + PSECTION_OBJECT_POINTERS SectionObjectPointers; + PVOID PrivateCacheMap; + NTSTATUS FinalStatus; + struct _FILE_OBJECT* RelatedFileObject; + BOOLEAN LockOperation; + BOOLEAN DeletePending; + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + ULONG Flags; + UNICODE_STRING FileName; + LARGE_INTEGER CurrentByteOffset; + ULONG Waiters; + ULONG Busy; + PVOID LastLock; + KEVENT Lock; + KEVENT Event; + PIO_COMPLETION_CONTEXT CompletionContext; +} FILE_OBJECT, *PFILE_OBJECT; + + +typedef struct _IRP +{ + CSHORT Type; + USHORT Size; + PMDL MdlAddress; + ULONG Flags; + union + { + struct _IRP* MasterIrp; + LONG IrpCount; + PVOID SystemBuffer; + } AssociatedIrp; + LIST_ENTRY ThreadListEntry; + IO_STATUS_BLOCK IoStatus; + KPROCESSOR_MODE RequestorMode; + BOOLEAN PendingReturned; + CHAR StackCount; + CHAR CurrentLocation; + BOOLEAN Cancel; + KIRQL CancelIrql; + CCHAR ApcEnvironment;// CCHAR or PVOID? + UCHAR AllocationFlags;//UCHAR or ULONG? + PIO_STATUS_BLOCK UserIosb; + PKEVENT UserEvent; + union + { + struct + { + PIO_APC_ROUTINE UserApcRoutine; + PVOID UserApcContext; + } AsynchronousParameters; + LARGE_INTEGER AllocationSize; + } Overlay; + PDRIVER_CANCEL CancelRoutine; + PVOID UserBuffer; + union + { + struct + { + union { + KDEVICE_QUEUE_ENTRY DeviceQueueEntry; + PVOID DriverContext[4]; + }; + struct _ETHREAD* Thread; + PCHAR AuxiliaryBuffer; + LIST_ENTRY ListEntry; + struct _IO_STACK_LOCATION* CurrentStackLocation; + PFILE_OBJECT OriginalFileObject; + } Overlay; + KAPC Apc; + ULONG CompletionKey; + } Tail; + IO_STACK_LOCATION Stack[1]; +} IRP, *PIRP; + +#define VPB_MOUNTED 0x00000001 +#define VPB_LOCKED 0x00000002 +#define VPB_PERSISTENT 0x00000004 +#define VPB_REMOVE_PENDING 0x00000008 + +typedef struct _VPB +{ + CSHORT Type; + CSHORT Size; + USHORT Flags; + USHORT VolumeLabelLength; + struct _DEVICE_OBJECT* DeviceObject; + struct _DEVICE_OBJECT* RealDevice; + ULONG SerialNumber; + ULONG ReferenceCount; + WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH]; +} VPB, *PVPB; + + +typedef struct _DEVICE_OBJECT +{ + CSHORT Type; + CSHORT Size; + LONG ReferenceCount; + struct _DRIVER_OBJECT* DriverObject; + struct _DEVICE_OBJECT* NextDevice; + struct _DEVICE_OBJECT* AttachedDevice; + struct _IRP* CurrentIrp; + PIO_TIMER Timer; + ULONG Flags; + ULONG Characteristics; + PVPB Vpb; + PVOID DeviceExtension; + DEVICE_TYPE DeviceType; + CCHAR StackSize; + union + { + LIST_ENTRY ListHead; + WAIT_CONTEXT_BLOCK Wcb; + } Queue; + ULONG AlignmentRequirement; + KDEVICE_QUEUE DeviceQueue; + KDPC Dpc; + ULONG ActiveThreadCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; + KEVENT DeviceLock; + USHORT SectorSize; + USHORT Spare1; + struct _DEVOBJ_EXTENSION* DeviceObjectExtension; + PVOID Reserved; +} DEVICE_OBJECT, *PDEVICE_OBJECT; + + +/* + * Fast i/o routine type declaration + */ +//typedef NTSTATUS (*PFAST_IO_DISPATCH)(struct _DEVICE_OBJECT*, IRP*); +//FIXME : this type is ok for read and write, but not for all routines +typedef BOOLEAN STDCALL +(*PFAST_IO_ROUTINE)(IN struct _FILE_OBJECT *FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN struct _DEVICE_OBJECT *DeviceObject); + +typedef struct _FAST_IO_DISPATCH { + ULONG SizeOfFastIoDispatch; + PFAST_IO_ROUTINE FastIoCheckIfPossible; + PFAST_IO_ROUTINE FastIoRead; + PFAST_IO_ROUTINE FastIoWrite; + PFAST_IO_ROUTINE FastIoQueryBasicInfo; + PFAST_IO_ROUTINE FastIoQueryStandardInfo; + PFAST_IO_ROUTINE FastIoLock; + PFAST_IO_ROUTINE FastIoUnlockSingle; + PFAST_IO_ROUTINE FastIoUnlockAll; + PFAST_IO_ROUTINE FastIoUnlockAllByKey; + PFAST_IO_ROUTINE FastIoDeviceControl; + PFAST_IO_ROUTINE AcquireFileForNtCreateSection; + PFAST_IO_ROUTINE ReleaseFileForNtCreateSection; + PFAST_IO_ROUTINE FastIoDetachDevice; + PFAST_IO_ROUTINE FastIoQueryNetworkOpenInfo; + PFAST_IO_ROUTINE AcquireForModWrite; + PFAST_IO_ROUTINE MdlRead; + PFAST_IO_ROUTINE MdlReadComplete; + PFAST_IO_ROUTINE PrepareMdlWrite; + PFAST_IO_ROUTINE MdlWriteComplete; + PFAST_IO_ROUTINE FastIoReadCompressed; + PFAST_IO_ROUTINE FastIoWriteCompressed; + PFAST_IO_ROUTINE MdlReadCompleteCompressed; + PFAST_IO_ROUTINE MdlWriteCompleteCompressed; + PFAST_IO_ROUTINE FastIoQueryOpen; + PFAST_IO_ROUTINE ReleaseForModWrite; + PFAST_IO_ROUTINE AcquireForCcFlush; + PFAST_IO_ROUTINE ReleaseForCcFlush; +} FAST_IO_DISPATCH, *PFAST_IO_DISPATCH; + +/* + * Dispatch routine type declaration + */ +typedef NTSTATUS STDCALL +(*PDRIVER_DISPATCH)(IN struct _DEVICE_OBJECT *DeviceObject, + IN struct _IRP *Irp); + +/* + * StartIo routine type declaration + */ +typedef VOID STDCALL +(*PDRIVER_STARTIO)(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +/* + * Unload routine type declaration + */ +typedef VOID STDCALL +(*PDRIVER_UNLOAD)(IN struct _DRIVER_OBJECT *DriverObject); + +/* + * AddDevice routine type declaration + */ +typedef NTSTATUS STDCALL +(*PDRIVER_ADD_DEVICE)(IN struct _DRIVER_OBJECT *DriverObject, + IN struct _DEVICE_OBJECT *PhysicalDeviceObject); + + +typedef struct _DRIVER_EXTENSION +{ + struct _DRIVER_OBJECT* DriverObject; + PDRIVER_ADD_DEVICE AddDevice; + ULONG Count; + UNICODE_STRING ServiceKeyName; +} DRIVER_EXTENSION, *PDRIVER_EXTENSION; + +#if 0 +typedef +struct _FAST_IO_DISPATCH_TABLE +{ + ULONG Count; + PFAST_IO_DISPATCH Dispatch; + +} FAST_IO_DISPATCH_TABLE, * PFAST_IO_DISPATCH_TABLE; +#endif + +typedef struct _DRIVER_OBJECT +{ + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + PVOID DriverStart; + ULONG DriverSize; + PVOID DriverSection; + PDRIVER_EXTENSION DriverExtension; + UNICODE_STRING DriverName; + PUNICODE_STRING HardwareDatabase; +#if 0 + PFAST_IO_DISPATCH_TABLE FastIoDispatch; +#else + PFAST_IO_DISPATCH FastIoDispatch; +#endif + PDRIVER_INITIALIZE DriverInit; + PDRIVER_STARTIO DriverStartIo; + PDRIVER_UNLOAD DriverUnload; + PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; +} DRIVER_OBJECT, *PDRIVER_OBJECT; + + +typedef struct _CONFIGURATION_INFORMATION +{ + ULONG DiskCount; + ULONG FloppyCount; + ULONG CDRomCount; + ULONG TapeCount; + ULONG ScsiPortCount; + ULONG SerialCount; + ULONG ParallelCount; + BOOLEAN AtDiskPrimaryAddressClaimed; + BOOLEAN AtDiskSecondaryAddressClaimed; +} CONFIGURATION_INFORMATION, *PCONFIGURATION_INFORMATION; + +typedef VOID STDCALL +(*PIO_DPC_ROUTINE)(PKDPC Dpc, + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context); + +typedef VOID STDCALL +(*PIO_TIMER_ROUTINE)(PDEVICE_OBJECT DeviceObject, + PVOID Context); + +typedef struct _IO_WORKITEM *PIO_WORKITEM; +typedef VOID (*PIO_WORKITEM_ROUTINE)(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context); + +#if WINDOWS_STRUCTS_DOESNT_ALREADY_DEFINE_THIS +typedef struct _PARTITION_INFORMATION +{ + LARGE_INTEGER StartingOffset; + LARGE_INTEGER PartitionLength; + ULONG HiddenSectors; + ULONG PartitionNumber; + UCHAR PartitionType; + BOOLEAN BootIndicator; + BOOLEAN RecognizedPartition; + BOOLEAN RewritePartition; +} PARTITION_INFORMATION, *PPARTITION_INFORMATION; +#endif + +typedef struct _DRIVER_LAYOUT_INFORMATION +{ + ULONG PartitionCount; + ULONG Signature; + PARTITION_INFORMATION PartitionEntry[1]; +} DRIVER_LAYOUT_INFORMATION, *PDRIVER_LAYOUT_INFORMATION; + + +typedef IO_ALLOCATION_ACTION STDCALL +(*PDRIVER_CONTROL)(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID MapRegisterBase, + PVOID Context); +#if (_WIN32_WINNT >= 0x0400) +typedef VOID STDCALL +(*PFSDNOTIFICATIONPROC)(IN PDEVICE_OBJECT PtrTargetFileSystemDeviceObject, + IN BOOLEAN DriverActive); +#endif // (_WIN32_WINNT >= 0x0400) + +#endif /* __INCLUDE_DDK_IOTYPES_H */ diff --git a/include/ddk/kdfuncs.h b/include/ddk/kdfuncs.h new file mode 100644 index 0000000..c790da6 --- /dev/null +++ b/include/ddk/kdfuncs.h @@ -0,0 +1,99 @@ +#ifndef __INCLUDE_DDK_KDFUNCS_H +#define __INCLUDE_DDK_KDFUNCS_H +/* $Id$ */ + +/* --- NTOSKRNL.EXE --- */ +#if defined(__NTOSKRNL__) +extern BOOLEAN KdDebuggerEnabled __declspec(dllexport); +extern BOOLEAN KdDebuggerNotPresent __declspec(dllexport); +#else +extern BOOLEAN KdDebuggerEnabled __declspec(dllimport); +extern BOOLEAN KdDebuggerNotPresent __declspec(dllimport); +#endif + +BYTE +STDCALL +KdPollBreakIn ( + VOID + ); + +BOOLEAN +STDCALL +KdPortInitialize ( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2 + ); + +BOOLEAN +STDCALL +KdPortInitializeEx ( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2 + ); + +BOOLEAN +STDCALL +KdPortGetByte ( + PUCHAR ByteRecieved + ); + +BOOLEAN +STDCALL +KdPortGetByteEx ( + PKD_PORT_INFORMATION PortInformation, + PUCHAR ByteRecieved + ); + +BOOLEAN +STDCALL +KdPortPollByte ( + PUCHAR ByteRecieved + ); + +BOOLEAN +STDCALL +KdPortPollByteEx ( + PKD_PORT_INFORMATION PortInformation, + PUCHAR ByteRecieved + ); + +VOID +STDCALL +KdPortPutByte ( + UCHAR ByteToSend + ); + +VOID +STDCALL +KdPortPutByteEx ( + PKD_PORT_INFORMATION PortInformation, + UCHAR ByteToSend + ); + +VOID +STDCALL +KdPortRestore ( + VOID + ); + +VOID +STDCALL +KdPortSave ( + VOID + ); + +BOOLEAN +STDCALL +KdPortDisableInterrupts( + VOID + ); + +BOOLEAN +STDCALL +KdPortEnableInterrupts( + VOID + ); + +#endif /* __INCLUDE_DDK_KDFUNCS_H */ diff --git a/include/ddk/kedef.h b/include/ddk/kedef.h new file mode 100644 index 0000000..507f1b3 --- /dev/null +++ b/include/ddk/kedef.h @@ -0,0 +1,66 @@ +#ifndef __INCLUDE_DDK_KEDEF_H +#define __INCLUDE_DDK_KEDEF_H + +typedef enum _KBUGCHECK_BUFFER_DUMP_STATE +{ + BufferEmpty, + BufferInserted, + BufferStarted, + BufferFinished, + BufferIncomplete +}KBUGCHECK_BUFFER_DUMP_STATE; + +typedef enum _KINTERRUPT_MODE +{ + LevelSensitive, + Latched, +} KINTERRUPT_MODE; + +/* + * PURPOSE: DPC importance + */ +typedef enum _KDPC_IMPORTANCE +{ + LowImportance, + MediumImportance, + HighImportance +} KDPC_IMPORTANCE; + +typedef enum _EVENT_TYPE +{ + NotificationEvent, + SynchronizationEvent, +} EVENT_TYPE; + +typedef enum _KWAIT_REASON +{ + Executive, + FreePage, + PageIn, + PoolAllocation, + DelayExecution, + Suspended, + UserRequest, + WrExecutive, + WrFreePage, + WrPageIn, + WrDelayExecution, + WrSuspended, + WrUserRequest, + WrEventPair, + WrQueue, + WrLpcReceive, + WrLpcReply, + WrVirtualMemory, + WrPageOut, + WrRendezvous, + Spare2, + Spare3, + Spare4, + Spare5, + Spare6, + WrKernel, + MaximumWaitReason, +} KWAIT_REASON; + +#endif diff --git a/include/ddk/kefuncs.h b/include/ddk/kefuncs.h new file mode 100644 index 0000000..b99a1be --- /dev/null +++ b/include/ddk/kefuncs.h @@ -0,0 +1,493 @@ +#ifndef __INCLUDE_DDK_KEFUNCS_H +#define __INCLUDE_DDK_KEFUNCS_H + + +/* KERNEL FUNCTIONS ********************************************************/ + +#define KeFlushIoBuffers(Mdl, ReadOperation, DmaOperation) + +VOID STDCALL KeAttachProcess (struct _EPROCESS* Process); + +VOID KeDrainApcQueue(VOID); +struct _KPROCESS* KeGetCurrentProcess(VOID); + +/* + * FUNCTION: Acquires a spinlock so the caller can synchronize access to + * data + * ARGUMENTS: + * SpinLock = Initialized spinlock + * OldIrql (OUT) = Set the previous irql on return + */ +VOID STDCALL KeAcquireSpinLock (PKSPIN_LOCK SpinLock, + PKIRQL OldIrql); + +VOID STDCALL KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock); + +/* + * FUNCTION: Brings the system down in a controlled manner when an + * inconsistency that might otherwise cause corruption has been detected + * ARGUMENTS: + * BugCheckCode = Specifies the reason for the bug check + * RETURNS: Doesn't + */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode); + + +/* + * FUNCTION: Brings the system down in a controlled manner when an + * inconsistency that might otherwise cause corruption has been detected + * ARGUMENTS: + * BugCheckCode = Specifies the reason for the bug check + * BugCheckParameter[1-4] = Additional information about bug + * RETURNS: Doesn't + */ +VOID STDCALL KeBugCheckEx (ULONG BugCheckCode, + ULONG BugCheckParameter1, + ULONG BugCheckParameter2, + ULONG BugCheckParameter3, + ULONG BugCheckParameter4); + +BOOLEAN STDCALL KeCancelTimer (PKTIMER Timer); + +VOID STDCALL KeClearEvent (PKEVENT Event); + +NTSTATUS STDCALL KeConnectInterrupt(PKINTERRUPT InterruptObject); + +NTSTATUS STDCALL KeDelayExecutionThread (KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Internal); + +BOOLEAN STDCALL KeDeregisterBugCheckCallback ( + PKBUGCHECK_CALLBACK_RECORD CallbackRecord); + +VOID STDCALL KeDetachProcess (VOID); + +VOID STDCALL KeDisconnectInterrupt(PKINTERRUPT InterruptObject); + +VOID STDCALL KeEnterCriticalRegion (VOID); + +/* + * FUNCTION: Enters the kernel debugger + * ARGUMENTS: + * None + */ +VOID STDCALL KeEnterKernelDebugger (VOID); + +VOID STDCALL KeFlushWriteBuffer (VOID); + +KIRQL STDCALL KeGetCurrentIrql (VOID); + +ULONG KeGetCurrentProcessorNumber(VOID); + +struct _KTHREAD* STDCALL KeGetCurrentThread (VOID); + +ULONG KeGetDcacheFillSize(VOID); + +ULONG STDCALL KeGetPreviousMode (VOID); + +VOID STDCALL KeInitializeApc (PKAPC Apc, + struct _KTHREAD* Thread, + UCHAR StateIndex, + PKKERNEL_ROUTINE KernelRoutine, + PKRUNDOWN_ROUTINE RundownRoutine, + PKNORMAL_ROUTINE NormalRoutine, + UCHAR Mode, + PVOID Context); + +/* + * VOID + * KeInitializeCallbackRecord ( + * PKBUGCHECK_CALLBACK_RECORD CallbackRecord + * ); + */ +#define KeInitializeCallbackRecord(CallbackRecord) \ + (CallbackRecord)->State = BufferEmpty + +VOID STDCALL KeInitializeDeviceQueue (PKDEVICE_QUEUE DeviceQueue); + +VOID STDCALL KeInitializeDpc (PKDPC Dpc, + PKDEFERRED_ROUTINE DeferredRoutine, + PVOID DeferredContext); + +VOID STDCALL KeInitializeEvent (PKEVENT Event, + EVENT_TYPE Type, + BOOLEAN State); + +NTSTATUS STDCALL KeInitializeInterrupt(PKINTERRUPT InterruptObject, + PKSERVICE_ROUTINE ServiceRoutine, + PVOID ServiceContext, + PKSPIN_LOCK SpinLock, + ULONG Vector, + KIRQL Irql, + KIRQL SynchronizeIrql, + KINTERRUPT_MODE InterruptMode, + BOOLEAN ShareVector, + KAFFINITY ProcessorEnableMask, + BOOLEAN FloatingSave); + +VOID STDCALL KeInitializeMutant(IN PKMUTANT Mutant, + IN BOOLEAN InitialOwner); + +VOID STDCALL KeInitializeMutex (PKMUTEX Mutex, + ULONG Level); + +VOID STDCALL +KeInitializeQueue(IN PKQUEUE Queue, + IN ULONG Count); + +VOID STDCALL KeInitializeSemaphore (PKSEMAPHORE Semaphore, + LONG Count, + LONG Limit); + +/* + * FUNCTION: Initializes a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to initialize + */ +VOID STDCALL KeInitializeSpinLock (PKSPIN_LOCK SpinLock); + +VOID STDCALL KeInitializeTimer (PKTIMER Timer); + +VOID STDCALL KeInitializeTimerEx (PKTIMER Timer, + TIMER_TYPE Type); + +BOOLEAN STDCALL KeInsertByKeyDeviceQueue (PKDEVICE_QUEUE DeviceQueue, + PKDEVICE_QUEUE_ENTRY QueueEntry, + ULONG SortKey); + +BOOLEAN STDCALL KeInsertDeviceQueue (PKDEVICE_QUEUE DeviceQueue, + PKDEVICE_QUEUE_ENTRY DeviceQueueEntry); + +LONG STDCALL +KeInsertHeadQueue(IN PKQUEUE Queue, + IN PLIST_ENTRY Entry); + +LONG STDCALL +KeInsertQueue(IN PKQUEUE Queue, + IN PLIST_ENTRY Entry); + +VOID STDCALL KeInsertQueueApc (PKAPC Apc, + PVOID SystemArgument1, + PVOID SystemArgument2, + UCHAR Mode); + +BOOLEAN STDCALL KeInsertQueueDpc (PKDPC Dpc, + PVOID SystemArgument1, + PVOID SystemArgument2); + +VOID STDCALL KeLeaveCriticalRegion (VOID); + +VOID STDCALL KeLowerIrql (KIRQL NewIrql); + +NTSTATUS STDCALL KePulseEvent (PKEVENT Event, + KPRIORITY Increment, + BOOLEAN Wait); + +LARGE_INTEGER +STDCALL +KeQueryPerformanceCounter ( + PLARGE_INTEGER PerformanceFrequency + ); + +VOID +STDCALL +KeQuerySystemTime ( + PLARGE_INTEGER CurrentTime + ); + +VOID +STDCALL +KeQueryTickCount ( + PLARGE_INTEGER TickCount + ); + +ULONG +STDCALL +KeQueryTimeIncrement ( + VOID + ); + +VOID +STDCALL +KeRaiseIrql ( + KIRQL NewIrql, + PKIRQL OldIrql + ); + +KIRQL +STDCALL +KeRaiseIrqlToDpcLevel ( + VOID + ); + +KIRQL +STDCALL +KeRaiseIrqlToSynchLevel ( + VOID + ); + +/* + * FUNCTION: Raises a user mode exception + * ARGUMENTS: + * ExceptionCode = Status code of the exception + */ +VOID +STDCALL +KeRaiseUserException ( + IN NTSTATUS ExceptionCode + ); + +LONG +STDCALL +KeReadStateEvent ( + PKEVENT Event + ); + +LONG STDCALL +KeReadStateMutant(IN PKMUTANT Mutant); + +LONG STDCALL +KeReadStateMutex(IN PKMUTEX Mutex); + +LONG STDCALL +KeReadStateQueue(IN PKQUEUE Queue); + +LONG STDCALL +KeReadStateSemaphore(IN PKSEMAPHORE Semaphore); + +BOOLEAN STDCALL +KeReadStateTimer(IN PKTIMER Timer); + +BOOLEAN +STDCALL +KeRegisterBugCheckCallback ( + PKBUGCHECK_CALLBACK_RECORD CallbackRecord, + PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine, + PVOID Buffer, + ULONG Length, + PUCHAR Component + ); + +LONG +STDCALL +KeReleaseMutant( + IN PKMUTANT Mutant, + IN KPRIORITY Increment, + IN BOOLEAN Abandon, + IN BOOLEAN Wait + ); + +LONG +STDCALL +KeReleaseMutex ( + PKMUTEX Mutex, + BOOLEAN Wait + ); + +LONG +STDCALL +KeReleaseSemaphore ( + PKSEMAPHORE Semaphore, + KPRIORITY Increment, + LONG Adjustment, + BOOLEAN Wait + ); + +VOID +STDCALL +KeReleaseSpinLock ( + PKSPIN_LOCK Spinlock, + KIRQL NewIrql + ); + +VOID +STDCALL +KeReleaseSpinLockFromDpcLevel ( + PKSPIN_LOCK Spinlock + ); + +PKDEVICE_QUEUE_ENTRY +STDCALL +KeRemoveByKeyDeviceQueue ( + PKDEVICE_QUEUE DeviceQueue, + ULONG SortKey + ); + +PKDEVICE_QUEUE_ENTRY +STDCALL +KeRemoveDeviceQueue ( + PKDEVICE_QUEUE DeviceQueue + ); + +BOOLEAN STDCALL +KeRemoveEntryDeviceQueue(PKDEVICE_QUEUE DeviceQueue, + PKDEVICE_QUEUE_ENTRY DeviceQueueEntry); + +PLIST_ENTRY STDCALL +KeRemoveQueue(IN PKQUEUE Queue, + IN KPROCESSOR_MODE WaitMode, + IN PLARGE_INTEGER Timeout OPTIONAL); + +BOOLEAN STDCALL +KeRemoveQueueDpc(IN PKDPC Dpc); + +LONG STDCALL +KeResetEvent(IN PKEVENT Event); + +LONG STDCALL +KeSetBasePriorityThread(struct _KTHREAD* Thread, + LONG Increment); + +LONG +STDCALL +KeSetEvent ( + PKEVENT Event, + KPRIORITY Increment, + BOOLEAN Wait + ); + +KPRIORITY STDCALL KeSetPriorityThread (struct _KTHREAD* Thread, + KPRIORITY Priority); + +BOOLEAN STDCALL KeSetTimer (PKTIMER Timer, + LARGE_INTEGER DueTime, + PKDPC Dpc); + +BOOLEAN STDCALL KeSetTimerEx (PKTIMER Timer, + LARGE_INTEGER DueTime, + LONG Period, + PKDPC Dpc); + +VOID STDCALL KeStallExecutionProcessor (ULONG MicroSeconds); + +BOOLEAN STDCALL KeSynchronizeExecution (PKINTERRUPT Interrupt, + PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, + PVOID SynchronizeContext); + +NTSTATUS STDCALL KeWaitForMultipleObjects (ULONG Count, + PVOID Object[], + WAIT_TYPE WaitType, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout, + PKWAIT_BLOCK WaitBlockArray); + +NTSTATUS +STDCALL +KeWaitForMutexObject ( + PKMUTEX Mutex, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout + ); + +NTSTATUS +STDCALL +KeWaitForSingleObject ( + PVOID Object, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout + ); + + + +// io permission map has a 8k size +// Each bit in the IOPM corresponds to an io port byte address. The bitmap +// is initialized to allow IO at any port. [ all bits set ]. + +typedef struct _IOPM +{ + UCHAR Bitmap[8192]; +} IOPM, *PIOPM; + +/* + * FUNCTION: Provides the kernel with a new access map for a driver + * ARGUMENTS: + * NewMap: = If FALSE the kernel's map is set to all disabled. If TRUE + * the kernel disables access to a particular port. + * IoPortMap = Caller supplies storage for the io permission map. + * REMARKS + * Each bit in the IOPM corresponds to an io port byte address. The bitmap + * is initialized to allow IO at any port. [ all bits set ]. The IOPL determines + * the minium privilege level required to perform IO prior to checking the permission map. + */ +VOID Ke386SetIoAccessMap(ULONG NewMap, PIOPM *IoPermissionMap); + +/* + * FUNCTION: Queries the io permission map. + * ARGUMENTS: + * NewMap: = If FALSE the kernel's map is set to all disabled. If TRUE + * the kernel disables access to a particular port. + * IoPortMap = Caller supplies storage for the io permission map. + * REMARKS + * Each bit in the IOPM corresponds to an io port byte address. The bitmap + * is initialized to allow IO at any port. [ all bits set ]. The IOPL determines + * the minium privilege level required to perform IO prior to checking the permission map. + */ +VOID Ke386QueryIoAccessMap(BOOLEAN NewMap, PIOPM *IoPermissionMap); + +/* + * FUNCTION: Set the process IOPL + * ARGUMENTS: + * Eprocess = Pointer to a executive process object + * EnableIo = Specify TRUE to enable IO and FALSE to disable + */ +NTSTATUS Ke386IoSetAccessProcess(struct _EPROCESS* Eprocess, BOOLEAN EnableIo); + +/* + * FUNCTION: Releases a set of Global Descriptor Table Selectors + * ARGUMENTS: + * SelArray = + * NumOfSelectors = + */ +NTSTATUS KeI386ReleaseGdtSelectors(OUT PULONG SelArray, + IN ULONG NumOfSelectors); + +/* + * FUNCTION: Allocates a set of Global Descriptor Table Selectors + * ARGUMENTS: + * SelArray = + * NumOfSelectors = + */ +NTSTATUS KeI386AllocateGdtSelectors(OUT PULONG SelArray, + IN ULONG NumOfSelectors); + + +KIRQL +FASTCALL +KfAcquireSpinLock ( + IN PKSPIN_LOCK SpinLock + ); + +VOID +FASTCALL +KfLowerIrql ( + IN KIRQL NewIrql + ); + + +KIRQL +FASTCALL +KfRaiseIrql ( + IN KIRQL NewIrql + ); + +VOID +FASTCALL +KfReleaseSpinLock ( + IN PKSPIN_LOCK SpinLock, + IN KIRQL NewIrql + ); + + +VOID STDCALL KiDeliverApc(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3); + +VOID STDCALL KiDispatchInterrupt(VOID); + +#endif /* __INCLUDE_DDK_KEFUNCS_H */ diff --git a/include/ddk/ketypes.h b/include/ddk/ketypes.h new file mode 100644 index 0000000..abb87b2 --- /dev/null +++ b/include/ddk/ketypes.h @@ -0,0 +1,288 @@ +/* KERNEL TYPES **************************************************************/ + +#ifndef __INCLUDE_DDK_KETYPES_H +#define __INCLUDE_DDK_KETYPES_H + +#define MB_FLAGS_MEM_INFO (0x1) +#define MB_FLAGS_BOOT_DEVICE (0x2) +#define MB_FLAGS_COMMAND_LINE (0x4) +#define MB_FLAGS_MODULE_INFO (0x8) +#define MB_FLAGS_AOUT_SYMS (0x10) +#define MB_FLAGS_ELF_SYMS (0x20) +#define MB_FLAGS_MMAP_INFO (0x40) +#define MB_FLAGS_DRIVES_INFO (0x80) +#define MB_FLAGS_CONFIG_TABLE (0x100) +#define MB_FLAGS_BOOT_LOADER_NAME (0x200) +#define MB_FLAGS_APM_TABLE (0x400) +#define MB_FLAGS_GRAPHICS_TABLE (0x800) + +typedef struct _LOADER_MODULE +{ + ULONG ModStart; + ULONG ModEnd; + ULONG String; + ULONG Reserved; +} LOADER_MODULE, *PLOADER_MODULE; + +typedef struct _ADDRESS_RANGE +{ + ULONG BaseAddrLow; + ULONG BaseAddrHigh; + ULONG LengthLow; + ULONG LengthHigh; + ULONG Type; +} ADDRESS_RANGE, *PADDRESS_RANGE; + +typedef struct _LOADER_PARAMETER_BLOCK +{ + ULONG Flags; + ULONG MemLower; + ULONG MemHigher; + ULONG BootDevice; + ULONG CommandLine; + ULONG ModsCount; + ULONG ModsAddr; + UCHAR Syms[12]; + ULONG MmapLength; + ULONG MmapAddr; + ULONG DrivesCount; + ULONG DrivesAddr; + ULONG ConfigTable; + ULONG BootLoaderName; +} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK; + +#ifdef __NTOSKRNL__ +extern CHAR EXPORTED KeNumberProcessors; +extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock; +extern ULONG EXPORTED KeDcacheFlushCount; +extern ULONG EXPORTED KeIcacheFlushCount; +#else +extern CHAR IMPORTED KeNumberProcessors; +extern LOADER_PARAMETER_BLOCK IMPORTED KeLoaderBlock; +extern ULONG EXPORTED KeDcacheFlushCount; +extern ULONG EXPORTED KeIcacheFlushCount; +#endif + + + +struct _KMUTANT; + +typedef LONG KPRIORITY; + +typedef VOID STDCALL +(*PKBUGCHECK_CALLBACK_ROUTINE)(PVOID Buffer, + ULONG Length); + +typedef BOOLEAN STDCALL +(*PKSYNCHRONIZE_ROUTINE)(PVOID SynchronizeContext); + +struct _KAPC; + +typedef VOID STDCALL +(*PKNORMAL_ROUTINE)(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + +typedef VOID STDCALL +(*PKKERNEL_ROUTINE)(struct _KAPC* Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2); + +typedef VOID STDCALL +(*PKRUNDOWN_ROUTINE)(struct _KAPC* Apc); + +struct _DISPATCHER_HEADER; + +typedef struct _KWAIT_BLOCK +/* + * PURPOSE: Object describing the wait a thread is currently performing + */ +{ + LIST_ENTRY WaitListEntry; + struct _KTHREAD* Thread; + struct _DISPATCHER_HEADER *Object; + struct _KWAIT_BLOCK* NextWaitBlock; + USHORT WaitKey; + USHORT WaitType; +} KWAIT_BLOCK, *PKWAIT_BLOCK; + +typedef struct _DISPATCHER_HEADER +{ + UCHAR Type; + UCHAR Absolute; + UCHAR Size; + UCHAR Inserted; + LONG SignalState; + LIST_ENTRY WaitListHead; +} __attribute__((packed)) DISPATCHER_HEADER, *PDISPATCHER_HEADER; + + +typedef struct _KQUEUE +{ + DISPATCHER_HEADER Header; + LIST_ENTRY EntryListHead; + ULONG CurrentCount; + ULONG MaximumCount; + LIST_ENTRY ThreadListEntry; +} KQUEUE, *PKQUEUE; + +struct _KDPC; + +typedef struct _KTIMER + { + DISPATCHER_HEADER Header; + ULARGE_INTEGER DueTime; + LIST_ENTRY TimerListEntry; + struct _KDPC* Dpc; + LONG Period; +} KTIMER, *PKTIMER; + +struct _KSPIN_LOCK; + +typedef struct _KSPIN_LOCK +{ + ULONG Lock; +} KSPIN_LOCK, *PKSPIN_LOCK; + +typedef struct _KDEVICE_QUEUE +{ + LIST_ENTRY ListHead; + BOOLEAN Busy; + KSPIN_LOCK Lock; +} KDEVICE_QUEUE, *PKDEVICE_QUEUE; + + +typedef struct _KAPC +{ + CSHORT Type; + CSHORT Size; + ULONG Spare0; + struct _KTHREAD* Thread; + LIST_ENTRY ApcListEntry; + PKKERNEL_ROUTINE KernelRoutine; + PKRUNDOWN_ROUTINE RundownRoutine; + PKNORMAL_ROUTINE NormalRoutine; + PVOID NormalContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + CCHAR ApcStateIndex; + KPROCESSOR_MODE ApcMode; + USHORT Inserted; +} __attribute__((packed)) KAPC, *PKAPC; + +typedef struct _KBUGCHECK_CALLBACK_RECORD +{ + LIST_ENTRY Entry; + PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine; + PVOID Buffer; + ULONG Length; + PUCHAR Component; + ULONG Checksum; + UCHAR State; +} KBUGCHECK_CALLBACK_RECORD, *PKBUGCHECK_CALLBACK_RECORD; + +typedef struct _KMUTEX +{ + DISPATCHER_HEADER Header; + LIST_ENTRY MutantListEntry; + struct _KTHREAD* OwnerThread; + BOOLEAN Abandoned; + UCHAR ApcDisable; +} KMUTEX, *PKMUTEX, KMUTANT, *PKMUTANT; + +typedef struct _KSEMAPHORE +{ + DISPATCHER_HEADER Header; + LONG Limit; +} __attribute__((packed)) KSEMAPHORE, *PKSEMAPHORE; + +typedef struct _KEVENT +{ + DISPATCHER_HEADER Header; +} KEVENT, *PKEVENT; + +typedef struct _KEVENT_PAIR +{ + CSHORT Type; + CSHORT Size; + KEVENT LowEvent; + KEVENT HighEvent; +} KEVENT_PAIR, *PKEVENT_PAIR; + + +struct _KDPC; + +/* + * PURPOSE: Defines a delayed procedure call routine + * NOTE: + * Dpc = The associated DPC object + * DeferredContext = Driver defined context for the DPC + * SystemArgument[1-2] = Undocumented. + * + */ +typedef VOID STDCALL +(*PKDEFERRED_ROUTINE)(struct _KDPC* Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + +/* + * PURPOSE: Defines a delayed procedure call object + */ +typedef struct _KDPC +{ + SHORT Type; + UCHAR Number; + UCHAR Importance; + LIST_ENTRY DpcListEntry; + PKDEFERRED_ROUTINE DeferredRoutine; + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + PULONG Lock; +} __attribute__((packed)) KDPC, *PKDPC; + + + +typedef struct _KDEVICE_QUEUE_ENTRY +{ + LIST_ENTRY Entry; + ULONG Key; + BOOLEAN Inserted; +} KDEVICE_QUEUE_ENTRY, *PKDEVICE_QUEUE_ENTRY; + +typedef struct _WAIT_CONTEXT_BLOCK +{ +} WAIT_CONTEXT_BLOCK, *PWAIT_CONTEXT_BLOCK; + +struct _KINTERRUPT; + +typedef BOOLEAN STDCALL +(*PKSERVICE_ROUTINE)(struct _KINTERRUPT* Interrupt, + PVOID ServiceContext); + +typedef struct _KINTERRUPT +{ + ULONG Vector; + KAFFINITY ProcessorEnableMask; + PKSPIN_LOCK IrqLock; + BOOLEAN Shareable; + BOOLEAN FloatingSave; + PKSERVICE_ROUTINE ServiceRoutine; + PVOID ServiceContext; + LIST_ENTRY Entry; + KIRQL SynchLevel; +} KINTERRUPT, *PKINTERRUPT; + +typedef struct _KSYSTEM_TIME +{ + ULONG LowPart; + LONG High1Part; + LONG High2Part; +} KSYSTEM_TIME, *PKSYSTEM_TIME; + +typedef struct _EPROCESS EPROCESS, *PEPROCESS; + +#endif /* __INCLUDE_DDK_KETYPES_H */ diff --git a/include/ddk/ldrfuncs.h b/include/ddk/ldrfuncs.h new file mode 100644 index 0000000..496fd80 --- /dev/null +++ b/include/ddk/ldrfuncs.h @@ -0,0 +1,17 @@ +#ifndef __INCLUDE_DDK_LDRFUNCS_H +#define __INCLUDE_DDK_LDRFUNCS_H +/* $Id$ */ + +NTSTATUS STDCALL +LdrAccessResource(IN PVOID BaseAddress, + IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry, + OUT PVOID *Resource OPTIONAL, + OUT PULONG Size OPTIONAL); + +NTSTATUS STDCALL +LdrFindResource_U(IN PVOID BaseAddress, + IN PLDR_RESOURCE_INFO ResourceInfo, + IN ULONG Level, + OUT PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry); + +#endif /* __INCLUDE_DDK_LDRFUNCS_H */ diff --git a/include/ddk/ldrtypes.h b/include/ddk/ldrtypes.h new file mode 100644 index 0000000..6e1209a --- /dev/null +++ b/include/ddk/ldrtypes.h @@ -0,0 +1,17 @@ +#ifndef __INCLUDE_DDK_LDRTYPES_H +#define __INCLUDE_DDK_LDRTYPES_H +/* $Id$ */ + +typedef struct _LDR_RESOURCE_INFO +{ + ULONG Type; + ULONG Name; + ULONG Language; +} LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO; + +#define RESOURCE_TYPE_LEVEL 0 +#define RESOURCE_NAME_LEVEL 1 +#define RESOURCE_LANGUAGE_LEVEL 2 +#define RESOURCE_DATA_LEVEL 3 + +#endif /* __INCLUDE_DDK_LDRTYPES_H */ diff --git a/include/ddk/miniport.h b/include/ddk/miniport.h new file mode 100644 index 0000000..d1ee3ab --- /dev/null +++ b/include/ddk/miniport.h @@ -0,0 +1,25 @@ +/* + * MINIPORT.H - miniport driver interface header + */ + +#define EMULATOR_READ_ACCESS 0x00000001 +#define EMULATOR_WRITE_ACCESS 0x00000002 + +typedef enum _EMULATOR_PORT_ACCESS_TYPE +{ + Uchar, + Ushort, + Ulong +} EMULATOR_PORT_ACCESS_TYPE, *PEMULATOR_PORT_ACCESS_TYPE; + +typedef struct _EMULATOR_ACCESS_ENTRY +{ + ULONG BasePort; + ULONG NumConsecutivePorts; + EMULATOR_PORT_ACCESS_TYPE AccessType; + UCHAR AccessMode; + UCHAR StringSupport; + PVOID Routine; +} EMULATOR_ACCESS_ENTRY, *PEMULATOR_ACCESS_ENTRY; + + diff --git a/include/ddk/mmfuncs.h b/include/ddk/mmfuncs.h new file mode 100644 index 0000000..4129003 --- /dev/null +++ b/include/ddk/mmfuncs.h @@ -0,0 +1,553 @@ +#ifndef _INCLUDE_DDK_MMFUNCS_H +#define _INCLUDE_DDK_MMFUNCS_H +/* $Id$ */ +/* MEMORY MANAGMENT ******************************************************/ + + +#ifdef __NTOSKRNL__ +extern PVOID EXPORTED MmUserProbeAddress; +extern PVOID EXPORTED MmHighestUserAddress; +#else +extern PVOID IMPORTED MmUserProbeAddress; +extern PVOID IMPORTED MmHighestUserAddress; +#endif + +#ifdef __NTOSKRNL__ +extern POBJECT_TYPE EXPORTED MmSectionObjectType; +#else +extern POBJECT_TYPE IMPORTED MmSectionObjectType; +#endif + + +/* + * FUNCTION: Returns the number of pages spanned by an address range + * ARGUMENTS: + * Va = start of range + * Size = Size of range + * RETURNS: The number of pages + */ +#if 0 +extern inline unsigned int ADDRESS_AND_SIZE_TO_SPAN_PAGES(PVOID Va, + ULONG Size) +{ + ULONG HighestAddr; + ULONG LowestAddr; + + HighestAddr = PAGE_ROUND_UP(Size + ((ULONG)Va)); + LowestAddr = PAGE_ROUND_DOWN((ULONG)Va); + return((HighestAddr - LowestAddr) / PAGE_SIZE); +} +#endif +#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(Va, Size) \ + (ULONG)((PAGE_ROUND_UP((Size) + ((ULONG)(Va))) - \ + PAGE_ROUND_DOWN((ULONG)(Va))) / PAGE_SIZE) + +/* + * FUNCTION: Returns FALSE is the pointer is NULL, TRUE otherwise + */ +#define ARGUMENT_PRESENT(arg) ((arg)!=NULL) + +/* + * FUNCTION: Returns the byte offset of the address within its page + */ +#define BYTE_OFFSET(va) (((ULONG)va)%PAGE_SIZE) + +/* + * FUNCTION: Takes a count in bytes and returns the number of pages + * required to hold it + */ +#define BYTES_TO_PAGES(size) (?) + +DWORD +STDCALL +MmAdjustWorkingSetSize ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); +PVOID +STDCALL +MmAllocateContiguousMemory ( + IN ULONG NumberOfBytes, + IN PHYSICAL_ADDRESS HighestAcceptableAddress + ); + +PVOID STDCALL +MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes, + IN PHYSICAL_ADDRESS HighestAcceptableAddress, + IN ULONG Alignment); + +PVOID +STDCALL +MmAllocateNonCachedMemory ( + IN ULONG NumberOfBytes + ); +/* + * FUNCTION: Fills in the corresponding physical page array for a given MDL + * for a buffer in nonpaged system space + * ARGUMENTS: + * MemoryDescriptorList = MDL to fill + */ +VOID +STDCALL +MmBuildMdlForNonPagedPool ( + PMDL MemoryDescriptorList + ); +BOOLEAN +STDCALL +MmCanFileBeTruncated ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER NewFileSize + ); +/* + * FUNCTION: Allocates and initializes an MDL + * ARGUMENTS: + * MemoryDescriptorList = Optional caller allocated MDL to initalize + * Base = Base virtual address for buffer + * Length = Length in bytes of the buffer + * RETURNS: A pointer to the initalized MDL + */ +PMDL +STDCALL +MmCreateMdl ( + PMDL MemoryDescriptorList, + PVOID Base, + ULONG Length + ); +#if 0 +NTSTATUS +STDCALL +MmCreateSection ( + OUT PSECTION_OBJECT * SectionObject, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL, + IN PFILE_OBJECT File OPTIONAL + ); +#endif +DWORD +STDCALL +MmDbgTranslatePhysicalAddress ( + DWORD Unknown0, + DWORD Unknown1 + ); +BOOLEAN +STDCALL +MmDisableModifiedWriteOfSection ( + DWORD Unknown0 + ); +BOOLEAN +STDCALL +MmFlushImageSection ( + IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN MMFLUSH_TYPE FlushType + ); +BOOLEAN +STDCALL +MmForceSectionClosed ( + DWORD Unknown0, + DWORD Unknown1 + ); +VOID +STDCALL +MmFreeContiguousMemory ( + IN OUT PVOID BaseAddress + ); +VOID +STDCALL +MmFreeNonCachedMemory ( + IN PVOID BaseAddress, + IN ULONG NumberOfBytes + ); +/* + * FUNCTION: Returns the length in bytes of a buffer described by an MDL + * ARGUMENTS: + * Mdl = the mdl + * RETURNS: Size of the buffer + */ +#define MmGetMdlByteCount(Mdl) ((Mdl)->ByteCount) + +/* + * FUNCTION: Returns the byte offset within a page of the buffer described + * by an MDL + * ARGUMENTS: + * Mdl = the mdl + * RETURNS: The offset in bytes + */ +#define MmGetMdlByteOffset(Mdl) \ + ((Mdl)->ByteOffset) + +/* + * FUNCTION: Returns the initial virtual address for a buffer described + * by an MDL + * ARGUMENTS: + * Mdl = the mdl + * RETURNS: The initial virtual address + */ +#define MmGetMdlVirtualAddress(Mdl) \ + ((PVOID) ((PCHAR) (Mdl)->StartVa + (Mdl)->ByteOffset)) + +/* + * FUNCTION: Returns the physical address corresponding to a given valid + * virtual address + * ARGUMENTS: + * BaseAddress = the virtual address + * RETURNS: The physical address + */ +PHYSICAL_ADDRESS +STDCALL +MmGetPhysicalAddress ( + IN PVOID BaseAddress + ); + +#define MmGetProcedureAddress(Address) (Address) + +/* + * PVOID + * MmGetSystemAddressForMdl ( + * PMDL Mdl + * ); + * + * FUNCTION: + * Maps the physical pages described by an MDL into system space + * + * ARGUMENTS: + * Mdl = mdl + * + * RETURNS: + * The base system address for the mapped buffer + */ +#define MmGetSystemAddressForMdl(Mdl) \ + (((Mdl)->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) ? \ + ((Mdl)->MappedSystemVa):(MmMapLockedPages((Mdl),KernelMode))) + +NTSTATUS +STDCALL +MmGrowKernelStack ( + DWORD Unknown0 + ); + + +/* + * VOID + * MmInitializeMdl ( + * PMDL MemoryDescriptorList, + * PVOID BaseVa, + * ULONG Length + * ); + * + * FUNCTION: + * Initalizes an MDL + * + * ARGUMENTS: + * MemoryDescriptorList = MDL to be initalized + * BaseVa = Base virtual address of the buffer + * Length = Length in bytes of the buffer + */ +#define MmInitializeMdl(MemoryDescriptorList,BaseVa,Length) \ +{ \ + (MemoryDescriptorList)->Next = (PMDL)NULL; \ + (MemoryDescriptorList)->Size = (CSHORT)(sizeof(MDL) + \ + (ADDRESS_AND_SIZE_TO_SPAN_PAGES((BaseVa),(Length)) * sizeof(ULONG))); \ + (MemoryDescriptorList)->MdlFlags = 0; \ + (MemoryDescriptorList)->StartVa = (PVOID)PAGE_ROUND_DOWN((BaseVa)); \ + (MemoryDescriptorList)->ByteOffset = (ULONG)((BaseVa) - PAGE_ROUND_DOWN((BaseVa))); \ + (MemoryDescriptorList)->ByteCount = (Length); \ + (MemoryDescriptorList)->Process = PsGetCurrentProcess(); \ +} + +/* + * FUNCTION: Checks whether an address is valid for read/write + * ARGUMENTS: + * VirtualAddress = address to be check + * RETURNS: TRUE if an access would be valid + */ +BOOLEAN +STDCALL +MmIsAddressValid ( + IN PVOID VirtualAddress + ); +BOOLEAN +STDCALL +MmIsNonPagedSystemAddressValid ( + IN PVOID VirtualAddress + ); +BOOLEAN +STDCALL +MmIsRecursiveIoFault ( + VOID + ); +/* + * FUNCTION: Checks if the current platform is a workstation or a server + * RETURNS: If the system is a server returns true + * NOTE: Drivers can use this as an estimate of the likely resources + * available + */ +BOOLEAN +STDCALL +MmIsThisAnNtAsSystem ( + VOID + ); +/* + * FUNCTION: Locks a section of the driver's code into memory + * ARGUMENTS: + * AddressWithinSection = Any address in the region + * RETURNS: A handle to the region + */ +#define MmLockPagableCodeSection(Address) \ + MmLockPagableDataSection(Address) + +/* + * FUNCTION: Locks a section of the driver's data into memory + * ARGUMENTS: + * AddressWithinSection = Any address in the region + * RETURNS: A handle to the region + */ +PVOID +STDCALL +MmLockPagableDataSection ( + PVOID AddressWithinSection + ); +PVOID +STDCALL +MmLockPagableImageSection ( + PVOID AddressWithinSection + ); +/* + * FUNCTION: Locks a section of memory + * ARGUMENTS: + * ImageSectionHandle = handle returned from MmLockPagableCodeSection + * or MmLockPagableDataSection + */ +VOID +STDCALL +MmLockPagableSectionByHandle ( + PVOID ImageSectionHandle + ); +PVOID +STDCALL +MmMapIoSpace ( + PHYSICAL_ADDRESS PhysicalAddress, + ULONG NumberOfBytes, + BOOLEAN CacheEnable + ); +/* + * FUNCTION: Maps the pages described by a given MDL + * ARGUMENTS: + * MemoryDescriptorList = MDL updated by MmProbeAndLockPages + * AccessMode = Access mode in which to map the MDL + * RETURNS: The base virtual address which maps the buffer + */ +PVOID +STDCALL +MmMapLockedPages ( + PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode + ); +VOID +STDCALL +MmMapMemoryDumpMdl ( + PVOID Unknown0 + ); +PVOID +STDCALL +MmMapVideoDisplay ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG NumberOfBytes, + IN MEMORY_CACHING_TYPE CacheType + ); +NTSTATUS +STDCALL +MmMapViewInSystemSpace ( + IN PVOID Section, + OUT PVOID * MappedBase, + IN PULONG ViewSize + ); +NTSTATUS +STDCALL +MmMapViewOfSection ( + IN PVOID SectionObject, + IN PEPROCESS Process, + IN OUT PVOID * BaseAddress, + IN ULONG ZeroBits, + IN ULONG CommitSize, + IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, + IN OUT PULONG ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG Protect + ); + +/* + * FUNCTION: Makes the whole driver pageable + * ARGUMENTS: + * AddressWithinSection = Any address within the driver + */ +VOID +STDCALL +MmPageEntireDriver ( + PVOID AddressWithinSection + ); + +/* + * VOID + * MmPrepareMdlForReuse ( + * PMDL Mdl + * ); + * + * FUNCTION: + * Reinitializes a caller-allocated MDL + * + * ARGUMENTS: + * Mdl = Points to the MDL that will be reused + */ +#define MmPrepareMdlForReuse(Mdl) \ + if (((Mdl)->MdlFlags & MDL_PARTIAL_HAS_BEEN_MAPPED) != 0) \ + { \ + assert(((Mdl)->MdlFlags & MDL_PARTIAL) != 0); \ + MmUnmapLockedPages ((Mdl)->MappedSystemVa, (Mdl)); \ + } \ + else if (((Mdl)->MdlFlags & MDL_PARTIAL) == 0) \ + { \ + assert(((Mdl)->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) == 0); \ + } + +/* + * FUNCTION: Probes the specified pages, makes them resident and locks + * the physical pages mapped by the virtual address range + * ARGUMENTS: + * MemoryDescriptorList = MDL which supplies the virtual address, + * byte offset and length + * AccessMode = Access mode with which to probe the arguments + * Operation = Types of operation for which the pages should be + * probed + */ +VOID +STDCALL +MmProbeAndLockPages ( + PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + LOCK_OPERATION Operation + ); + +/* + * FUNCTION: Returns an estimate of the amount of memory in the system + * RETURNS: Either MmSmallSystem, MmMediumSystem or MmLargeSystem + */ +MM_SYSTEM_SIZE +STDCALL +MmQuerySystemSize ( + VOID + ); + +/* + * FUNCTION: Resets the pageable status of a driver's sections to their + * compile time settings + * ARGUMENTS: + * AddressWithinSection = Any address within the driver + */ +VOID +STDCALL +MmResetDriverPaging ( + PVOID AddressWithinSection + ); + +DWORD +STDCALL +MmSecureVirtualMemory ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ); +BOOLEAN +STDCALL +MmSetAddressRangeModified ( + DWORD Unknown0, + DWORD Unknown1 + ); +NTSTATUS +STDCALL +MmSetBankedSection ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5 + ); + +/* + * FUNCTION: Returns the number of bytes to allocate for an MDL + * describing a given address range + * ARGUMENTS: + * Base = Base virtual address for the region + * Length = size in bytes of the region + * RETURNS: The number of bytes required for the MDL + */ +ULONG +STDCALL +MmSizeOfMdl ( + PVOID Base, + ULONG Length + ); +/* + * FUNCTION: Unlocks the physical pages described by a given MDL + * ARGUMENTS: + * Mdl = Mdl to unlock + */ +VOID +STDCALL +MmUnlockPages ( + PMDL Mdl + ); +/* + * FUNCTION: Releases a section of driver code or data previously locked into + * memory + * ARGUMENTS: + * ImageSectionHandle = Handle for the locked section + */ +VOID +STDCALL +MmUnlockPagableImageSection ( + PVOID ImageSectionHandle + ); +VOID +STDCALL +MmUnmapIoSpace ( + PVOID BaseAddress, + ULONG NumberOfBytes + ); +VOID +STDCALL +MmUnmapLockedPages ( + PVOID BaseAddress, + PMDL MemoryDescriptorList + ); +VOID +STDCALL +MmUnmapVideoDisplay ( + IN PVOID BaseAddress, + IN ULONG NumberOfBytes + ); +NTSTATUS +STDCALL +MmUnmapViewInSystemSpace ( + DWORD Unknown0 + ); +#if 0 +NTSTATUS +STDCALL +MmUnmapViewOfSection ( + PEPROCESS Process, + PMEMORY_AREA MemoryArea + ) +#endif +VOID +STDCALL +MmUnsecureVirtualMemory ( + DWORD Unknown0 + ); +#endif diff --git a/include/ddk/mmtypes.h b/include/ddk/mmtypes.h new file mode 100644 index 0000000..2498b39 --- /dev/null +++ b/include/ddk/mmtypes.h @@ -0,0 +1,88 @@ +/* $Id$ */ + +#ifndef _INCLUDE_DDK_MMTYPES_H +#define _INCLUDE_DDK_MMTYPES_H + +#include +#include + + +#define PAGE_ROUND_UP(x) ( (((ULONG)x)%PAGE_SIZE) ? ((((ULONG)x)&(~0xfff))+0x1000) : ((ULONG)x) ) +#define PAGE_ROUND_DOWN(x) (((ULONG)x)&(~0xfff)) + + +/* + * FUNCTION: Determines if the given virtual address is page aligned + */ +#define IS_PAGE_ALIGNED(Va) (((ULONG)Va)&0xfff) + +/* + * PURPOSE: Returns the byte offset of a field within a structure + */ +#define FIELD_OFFSET(Type,Field) (LONG)(&(((Type *)(0))->Field)) + +/* + * PURPOSE: Returns the base address structure if the caller knows the + * address of a field within the structure + * ARGUMENTS: + * Address = address of the field + * Type = Type of the whole structure + * Field = Name of the field whose address is none + */ +#define CONTAINING_RECORD(Address,Type,Field) (Type *)(((LONG)Address) - FIELD_OFFSET(Type,Field)) + + +#define MDL_MAPPED_TO_SYSTEM_VA (0x1) +#define MDL_PAGES_LOCKED (0x2) +#define MDL_SOURCE_IS_NONPAGED_POOL (0x4) +#define MDL_ALLOCATED_FIXED_SIZE (0x8) +#define MDL_PARTIAL (0x10) +#define MDL_PARTIAL_HAS_BEEN_MAPPED (0x20) +#define MDL_IO_PAGE_READ (0x40) +#define MDL_WRITE_OPERATION (0x80) +#define MDL_PARENT_MAPPED_SYSTEM_VA (0x100) +#define MDL_LOCK_HELD (0x200) +#define MDL_SCATTER_GATHER_VA (0x400) +#define MDL_IO_SPACE (0x800) +#define MDL_NETWORK_HEADER (0x1000) +#define MDL_MAPPING_CAN_FAIL (0x2000) +#define MDL_ALLOCATED_MUST_SUCCEED (0x4000) +#define MDL_64_BIT_VA (0x8000) + + +typedef struct _MDL +/* + * PURPOSE: Describes a user buffer passed to a system API + */ +{ + struct _MDL* Next; + CSHORT Size; + CSHORT MdlFlags; + struct _EPROCESS* Process; + PVOID MappedSystemVa; + PVOID StartVa; + ULONG ByteCount; + ULONG ByteOffset; +} MDL, *PMDL; + +#define MmSmallSystem (0) +#define MmMediumSystem (1) +#define MmLargeSystem (2) + +/* Used in MmFlushImageSection */ +typedef enum _MMFLUSH_TYPE +{ + MmFlushForDelete, + MmFlushForWrite +} MMFLUSH_TYPE; + +typedef enum _MEMORY_CACHING_TYPE +{ + MmNonCached = FALSE, + MmCached = TRUE, + MmFrameBufferCached, + MmHardwareCoherentCached, + MmMaximumCacheType +} MEMORY_CACHING_TYPE; + +#endif diff --git a/include/ddk/ntdd8042.h b/include/ddk/ntdd8042.h new file mode 100644 index 0000000..b57c487 --- /dev/null +++ b/include/ddk/ntdd8042.h @@ -0,0 +1,98 @@ +#ifndef _NTDD8042_ +#define _NTDD8042_ + +#define IOCTL_INTERNAL_I8042_HOOK_KEYBOARD CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF0, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_INTERNAL_I8042_HOOK_MOUSE CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF0, METHOD_NEITHER, FILE_ANY_ACCESS) + +typedef enum _KEYBOARD_SCAN_STATE { + Normal, + GotE0, + GotE1 +} KEYBOARD_SCAN_STATE, *PKEYBOARD_SCAN_STATE; + +typedef +NTSTATUS +(*PI8042_SYNCH_READ_PORT) ( + IN PVOID Context, + PUCHAR Value, + BOOLEAN WaitForACK + ); + +typedef +NTSTATUS +(*PI8042_SYNCH_WRITE_PORT) ( + IN PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK + ); + +typedef enum _TRANSMIT_STATE { + Idle = 0, + SendingBytes +} TRANSMIT_STATE; + +typedef struct _OUTPUT_PACKET { + PUCHAR Bytes; + ULONG CurrentByte; + ULONG ByteCount; + TRANSMIT_STATE State; +} OUTPUT_PACKET, *POUTPUT_PACKET; + +typedef +NTSTATUS +(*PI8042_KEYBOARD_INITIALIZATION_ROUTINE) ( + IN PVOID InitializationContext, + IN PVOID SynchFuncContext, + IN PI8042_SYNCH_READ_PORT ReadPort, + IN PI8042_SYNCH_WRITE_PORT WritePort, + OUT PBOOLEAN TurnTranslationOn + ); + +typedef +BOOLEAN +(*PI8042_KEYBOARD_ISR) ( + PVOID IsrContext, + PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, + PUCHAR Byte, + PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState + ); + +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD { + + // + // Context variable for all callback routines + // + PVOID Context; + + // + // Routine to call after the mouse is reset + // + PI8042_KEYBOARD_INITIALIZATION_ROUTINE InitializationRoutine; + + // + // Routine to call when a byte is received via the interrupt + // + PI8042_KEYBOARD_ISR IsrRoutine; + + // + // Write function + // + //UNIMPLEMENTED PI8042_ISR_WRITE_PORT IsrWritePort; + + // + // Queue the current packet (ie the one passed into the isr callback hook) + // to be reported to the class driver + // + //UNIMPLEMENTED PI8042_QUEUE_PACKET QueueKeyboardPacket; + + // + // Context for IsrWritePort, QueueKeyboardPacket + // + //UNIMPLEMENTED PVOID CallContext; + +} INTERNAL_I8042_HOOK_KEYBOARD, *PINTERNAL_I8042_HOOK_KEYBOARD; + +#endif //_NTDD8042_ diff --git a/include/ddk/ntddbeep.h b/include/ddk/ntddbeep.h new file mode 100644 index 0000000..2663ecd --- /dev/null +++ b/include/ddk/ntddbeep.h @@ -0,0 +1,50 @@ +/* + * ntddbeep.h + * + * Beep device IOCTL interface + * + * This file is part of the MinGW package. + * + * Contributors: + * Created by Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NTDDBEEP_H +#define __NTDDBEEP_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#define IOCTL_BEEP_SET \ + CTL_CODE(FILE_DEVICE_BEEP,0,METHOD_BUFFERED,FILE_ANY_ACCESS) + +typedef struct tagBEEP_SET_PARAMETERS { + ULONG Frequency; + ULONG Duration; +} BEEP_SET_PARAMETERS, *PBEEP_SET_PARAMETERS; + +#define BEEP_FREQUENCY_MINIMUM 0x25 +#define BEEP_FREQUENCY_MAXIMUM 0x7FFF + +#ifdef __cplusplus +} +#endif + +#endif /* __NTDDBEEP_H */ diff --git a/include/ddk/ntddblue.h b/include/ddk/ntddblue.h new file mode 100644 index 0000000..ed29427 --- /dev/null +++ b/include/ddk/ntddblue.h @@ -0,0 +1,64 @@ +#ifndef _NTDDBLUE_H_INCLUDED_ +#define _NTDDBLUE_H_INCLUDED_ + +#include + +#define IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO CTL_CODE(FILE_DEVICE_SCREEN, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO CTL_CODE(FILE_DEVICE_SCREEN, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_CONSOLE_GET_CURSOR_INFO CTL_CODE(FILE_DEVICE_SCREEN, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CONSOLE_SET_CURSOR_INFO CTL_CODE(FILE_DEVICE_SCREEN, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_CONSOLE_GET_MODE CTL_CODE(FILE_DEVICE_SCREEN, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CONSOLE_SET_MODE CTL_CODE(FILE_DEVICE_SCREEN, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + +#define IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE CTL_CODE(FILE_DEVICE_SCREEN, 0x810, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE CTL_CODE(FILE_DEVICE_SCREEN, 0x811, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE CTL_CODE(FILE_DEVICE_SCREEN, 0x812, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE CTL_CODE(FILE_DEVICE_SCREEN, 0x813, METHOD_BUFFERED, FILE_WRITE_ACCESS) + + +#define IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER CTL_CODE(FILE_DEVICE_SCREEN, 0x820, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_CONSOLE_READ_OUTPUT_CHARACTER CTL_CODE(FILE_DEVICE_SCREEN, 0x821, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER CTL_CODE(FILE_DEVICE_SCREEN, 0x822, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + + +#define IOCTL_CONSOLE_DRAW CTL_CODE(FILE_DEVICE_SCREEN, 0x830, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + + +/* TYPEDEFS **************************************************************/ + + +typedef struct _CONSOLE_MODE +{ + DWORD dwMode; +} CONSOLE_MODE, *PCONSOLE_MODE; + + +typedef struct _OUTPUT_ATTRIBUTE +{ + WORD wAttribute; + DWORD nLength; + COORD dwCoord; + DWORD dwTransfered; +} OUTPUT_ATTRIBUTE, *POUTPUT_ATTRIBUTE; + + +typedef struct _OUTPUT_CHARACTER +{ + CHAR cCharacter; + DWORD nLength; + COORD dwCoord; + DWORD dwTransfered; +} OUTPUT_CHARACTER, *POUTPUT_CHARACTER; + + +typedef struct _CONSOLE_DRAW +{ + SHORT X; // Origin + SHORT Y; + SHORT SizeX; // Size of the screen buffer + SHORT SizeY; +} CONSOLE_DRAW, *PCONSOLE_DRAW; + + +#endif /* _NTDDBLUE_H_INCLUDED_ */ diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h new file mode 100644 index 0000000..fd8d199 --- /dev/null +++ b/include/ddk/ntddk.h @@ -0,0 +1,90 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ddk/ntddk.h + * PURPOSE: Interface definitions for drivers + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 15/05/98: Created + */ + +#ifndef __NTDDK_H +#define __NTDDK_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* INCLUDES ***************************************************************/ + +#define FASTCALL __attribute__((fastcall)) + +#define STATIC static + +#ifndef _GNU_H_WINDOWS_H +/* NASTY HACK! Our msvcrt are messed up, causing msvcrt.dll to crash when + * the headers are mixed with MinGW msvcrt headers. Not including stdlib.h + * seems to correct this. + */ +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /*__NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ */ + +#ifdef __cplusplus +}; +#endif + +#endif /* __NTDDK_H */ + diff --git a/include/ddk/ntddkbd.h b/include/ddk/ntddkbd.h new file mode 100644 index 0000000..527392c --- /dev/null +++ b/include/ddk/ntddkbd.h @@ -0,0 +1,19 @@ +#ifndef _NTDDKBD_ +#define _NTDDKBD_ + +typedef struct _KEYBOARD_INPUT_DATA { + + // + // Unit number. E.g., for \Device\KeyboardPort0 the unit is '0', + // for \Device\KeyboardPort1 the unit is '1', and so on. + // + + USHORT UnitId; + USHORT MakeCode; + USHORT Flags; + USHORT Reserved; + ULONG ExtraInformation; + +} KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA; + +#endif // _NTDDKBD_ diff --git a/include/ddk/ntddscsi.h b/include/ddk/ntddscsi.h new file mode 100644 index 0000000..7ddfb16 --- /dev/null +++ b/include/ddk/ntddscsi.h @@ -0,0 +1,92 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/include/ntddscsi.h + * PURPOSE: Basic SCSI definitions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +#ifndef __STORAGE_INCLUDE_NTDDSCSI_H +#define __STORAGE_INCLUDE_NTDDSCSI_H + + +/* IOCTL codes */ + +#define IOCTL_SCSI_PASS_THROUGH \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_MINIPORT \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_INQUIRY_DATA \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_CAPABILITIES \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_ADDRESS \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_RESCAN_BUS \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_DUMP_POINTERS \ + CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS) + + + +/* Used by IOCTL_SCSI_GET_CAPABILITIES */ + +typedef struct _IO_SCSI_CAPABILITIES +{ + ULONG Length; + ULONG MaximumTransferLength; + ULONG MaximumPhysicalPages; + ULONG SupportedAsynchronousEvents; + ULONG AlignmentMask; + BOOLEAN TaggedQueuing; + BOOLEAN AdapterScansDown; + BOOLEAN AdapterUsesPio; +} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; + + +/* Used by IOCTL_SCSI_GET_INQUIRY_DATA */ + +typedef struct _SCSI_BUS_DATA +{ + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +}SCSI_BUS_DATA, *PSCSI_BUS_DATA; + + +typedef struct _SCSI_ADAPTER_BUS_INFO +{ + UCHAR NumberOfBuses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + + +typedef struct _SCSI_INQUIRY_DATA +{ + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +}SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + + +/* Used by IOCTL_SCSI_GET_ADDRESS */ + +typedef struct _SCSI_ADDRESS +{ + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + +#endif /* __STORAGE_INCLUDE_NTDDSCSI_H */ + +/* EOF */ diff --git a/include/ddk/ntddser.h b/include/ddk/ntddser.h new file mode 100644 index 0000000..1d53db4 --- /dev/null +++ b/include/ddk/ntddser.h @@ -0,0 +1,455 @@ +/* + * ntddser.h + * + * Serial port driver interface + * + * This file is part of the MinGW package. + * + * Contributors: + * Created by Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NTDDSER_H +#define __NTDDSER_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push,4) + +#include "ntddk.h" + + +/* GUIDs */ + +#ifdef DEFINE_GUID +DEFINE_GUID(GUID_DEVINTERFACE_COMPORT, + 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73); +DEFINE_GUID(GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, + 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18); +#endif // DEFINE_GUID + +#define IOCTL_SERIAL_CLEAR_STATS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 36, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CLR_DTR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CLR_RTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_CONFIG_SIZE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 32, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_BAUD_RATE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_CHARS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_COMMSTATUS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 27, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_DTRRTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_HANDFLOW \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_LINE_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_MODEM_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 37, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_MODEMSTATUS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_PROPERTIES \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 29, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_STATS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 35, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_TIMEOUTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_GET_WAIT_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_IMMEDIATE_CHAR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_LSRMST_INSERT \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 31, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_PURGE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 19, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_RESET_DEVICE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BAUD_RATE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BREAK_ON \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_BREAK_OFF \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_CHARS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_DTR \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_FIFO_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 39, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_HANDFLOW \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_LINE_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_MODEM_CONTROL \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 38, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_QUEUE_SIZE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_RTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_TIMEOUTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_WAIT_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 17, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_XOFF \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_SET_XON \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_WAIT_ON_MASK \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_XOFF_COUNTER \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 28, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_SERENUM_PORT_DESC \ + CTL_CODE (FILE_DEVICE_SERENUM, 130, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SERENUM_GET_PORT_NAME \ + CTL_CODE (FILE_DEVICE_SERENUM, 131, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_INTERNAL_SERENUM_REMOVE_SELF \ + CTL_CODE (FILE_DEVICE_SERENUM, 129, METHOD_NEITHER, FILE_ANY_ACCESS) + + +typedef struct _SERIAL_BAUD_RATE { + ULONG BaudRate; +} SERIAL_BAUD_RATE, *PSERIAL_BAUD_RATE; + +/* SERIAL_BAUD_RATE.BaudRate constants */ +#define SERIAL_BAUD_075 0x00000001 +#define SERIAL_BAUD_110 0x00000002 +#define SERIAL_BAUD_134_5 0x00000004 +#define SERIAL_BAUD_150 0x00000008 +#define SERIAL_BAUD_300 0x00000010 +#define SERIAL_BAUD_600 0x00000020 +#define SERIAL_BAUD_1200 0x00000040 +#define SERIAL_BAUD_1800 0x00000080 +#define SERIAL_BAUD_2400 0x00000100 +#define SERIAL_BAUD_4800 0x00000200 +#define SERIAL_BAUD_7200 0x00000400 +#define SERIAL_BAUD_9600 0x00000800 +#define SERIAL_BAUD_14400 0x00001000 +#define SERIAL_BAUD_19200 0x00002000 +#define SERIAL_BAUD_38400 0x00004000 +#define SERIAL_BAUD_56K 0x00008000 +#define SERIAL_BAUD_128K 0x00010000 +#define SERIAL_BAUD_115200 0x00020000 +#define SERIAL_BAUD_57600 0x00040000 +#define SERIAL_BAUD_USER 0x10000000 + +typedef struct _SERIAL_CHARS { + UCHAR EofChar; + UCHAR ErrorChar; + UCHAR BreakChar; + UCHAR EventChar; + UCHAR XonChar; + UCHAR XoffChar; +} SERIAL_CHARS, *PSERIAL_CHARS; + +typedef struct _SERIAL_STATUS { + ULONG Errors; + ULONG HoldReasons; + ULONG AmountInInQueue; + ULONG AmountInOutQueue; + BOOLEAN EofReceived; + BOOLEAN WaitForImmediate; +} SERIAL_STATUS, *PSERIAL_STATUS; + +typedef struct _SERIAL_HANDFLOW { + ULONG ControlHandShake; + ULONG FlowReplace; + LONG XonLimit; + LONG XoffLimit; +} SERIAL_HANDFLOW, *PSERIAL_HANDFLOW; + +#define SERIAL_DTR_MASK 0x00000003 +#define SERIAL_DTR_CONTROL 0x00000001 +#define SERIAL_DTR_HANDSHAKE 0x00000002 +#define SERIAL_CTS_HANDSHAKE 0x00000008 +#define SERIAL_DSR_HANDSHAKE 0x00000010 +#define SERIAL_DCD_HANDSHAKE 0x00000020 +#define SERIAL_OUT_HANDSHAKEMASK 0x00000038 +#define SERIAL_DSR_SENSITIVITY 0x00000040 +#define SERIAL_ERROR_ABORT 0x80000000 +#define SERIAL_CONTROL_INVALID 0x7fffff84 +#define SERIAL_AUTO_TRANSMIT 0x00000001 +#define SERIAL_AUTO_RECEIVE 0x00000002 +#define SERIAL_ERROR_CHAR 0x00000004 +#define SERIAL_NULL_STRIPPING 0x00000008 +#define SERIAL_BREAK_CHAR 0x00000010 +#define SERIAL_RTS_MASK 0x000000c0 +#define SERIAL_RTS_CONTROL 0x00000040 +#define SERIAL_RTS_HANDSHAKE 0x00000080 +#define SERIAL_TRANSMIT_TOGGLE 0x000000c0 +#define SERIAL_XOFF_CONTINUE 0x80000000 +#define SERIAL_FLOW_INVALID 0x7fffff20 + +typedef struct _SERIAL_LINE_CONTROL { + UCHAR StopBits; + UCHAR Parity; + UCHAR WordLength; +} SERIAL_LINE_CONTROL, *PSERIAL_LINE_CONTROL; + +/* SERIAL_LINE_CONTROL.StopBits constants */ +#define STOP_BIT_1 0x00 +#define STOP_BITS_1_5 0x01 +#define STOP_BITS_2 0x02 + +/* SERIAL_LINE_CONTROL.Parity constants */ +#define NO_PARITY 0x00 +#define ODD_PARITY 0x01 +#define EVEN_PARITY 0x02 +#define MARK_PARITY 0x03 +#define SPACE_PARITY 0x04 + +/* IOCTL_SERIAL_(GET_MODEM_CONTROL, SET_MODEM_CONTROL) flags */ +#define SERIAL_IOC_MCR_DTR 0x00000001 +#define SERIAL_IOC_MCR_RTS 0x00000002 +#define SERIAL_IOC_MCR_OUT1 0x00000004 +#define SERIAL_IOC_MCR_OUT2 0x00000008 +#define SERIAL_IOC_MCR_LOOP 0x00000010 + +typedef struct _SERIAL_COMMPROP { + USHORT PacketLength; + USHORT PacketVersion; + ULONG ServiceMask; + ULONG Reserved1; + ULONG MaxTxQueue; + ULONG MaxRxQueue; + ULONG MaxBaud; + ULONG ProvSubType; + ULONG ProvCapabilities; + ULONG SettableParams; + ULONG SettableBaud; + USHORT SettableData; + USHORT SettableStopParity; + ULONG CurrentTxQueue; + ULONG CurrentRxQueue; + ULONG ProvSpec1; + ULONG ProvSpec2; + WCHAR ProvChar[1]; +} SERIAL_COMMPROP, *PSERIAL_COMMPROP; + +/* SERIAL_COMMPROP.SettableParams flags */ +#define SERIAL_SP_PARITY 0x0001 +#define SERIAL_SP_BAUD 0x0002 +#define SERIAL_SP_DATABITS 0x0004 +#define SERIAL_SP_STOPBITS 0x0008 +#define SERIAL_SP_HANDSHAKING 0x0010 +#define SERIAL_SP_PARITY_CHECK 0x0020 +#define SERIAL_SP_CARRIER_DETECT 0x0040 + +/* SERIAL_COMMPROP.ProvCapabilities flags */ +#define SERIAL_PCF_DTRDSR 0x00000001 +#define SERIAL_PCF_RTSCTS 0x00000002 +#define SERIAL_PCF_CD 0x00000004 +#define SERIAL_PCF_PARITY_CHECK 0x00000008 +#define SERIAL_PCF_XONXOFF 0x00000010 +#define SERIAL_PCF_SETXCHAR 0x00000020 +#define SERIAL_PCF_TOTALTIMEOUTS 0x00000040 +#define SERIAL_PCF_INTTIMEOUTS 0x00000080 +#define SERIAL_PCF_SPECIALCHARS 0x00000100 +#define SERIAL_PCF_16BITMODE 0x00000200 + +/* SERIAL_COMMPROP.SettableData flags */ +#define SERIAL_DATABITS_5 0x0001 +#define SERIAL_DATABITS_6 0x0002 +#define SERIAL_DATABITS_7 0x0004 +#define SERIAL_DATABITS_8 0x0008 +#define SERIAL_DATABITS_16 0x0010 +#define SERIAL_DATABITS_16X 0x0020 + +/* SERIAL_COMMPROP.SettableStopParity flags */ +#define SERIAL_STOPBITS_10 0x0001 +#define SERIAL_STOPBITS_15 0x0002 +#define SERIAL_STOPBITS_20 0x0004 +#define SERIAL_PARITY_NONE 0x0100 +#define SERIAL_PARITY_ODD 0x0200 +#define SERIAL_PARITY_EVEN 0x0400 +#define SERIAL_PARITY_MARK 0x0800 +#define SERIAL_PARITY_SPACE 0x1000 + +typedef struct _SERIALPERF_STATS { + ULONG ReceivedCount; + ULONG TransmittedCount; + ULONG FrameErrorCount; + ULONG SerialOverrunErrorCount; + ULONG BufferOverrunErrorCount; + ULONG ParityErrorCount; +} SERIALPERF_STATS, *PSERIALPERF_STATS; + +typedef struct _SERIAL_TIMEOUTS { + ULONG ReadIntervalTimeout; + ULONG ReadTotalTimeoutMultiplier; + ULONG ReadTotalTimeoutConstant; + ULONG WriteTotalTimeoutMultiplier; + ULONG WriteTotalTimeoutConstant; +} SERIAL_TIMEOUTS, *PSERIAL_TIMEOUTS; + +/* IOCTL_SERIAL_(GET_WAIT_MASK, SET_WAIT_MASK, WAIT_ON_MASK) flags */ +#define SERIAL_EV_RXCHAR 0x0001 +#define SERIAL_EV_RXFLAG 0x0002 +#define SERIAL_EV_TXEMPTY 0x0004 +#define SERIAL_EV_CTS 0x0008 +#define SERIAL_EV_DSR 0x0010 +#define SERIAL_EV_RLSD 0x0020 +#define SERIAL_EV_BREAK 0x0040 +#define SERIAL_EV_ERR 0x0080 +#define SERIAL_EV_RING 0x0100 +#define SERIAL_EV_PERR 0x0200 +#define SERIAL_EV_RX80FULL 0x0400 +#define SERIAL_EV_EVENT1 0x0800 +#define SERIAL_EV_EVENT2 0x1000 + +/* IOCTL_SERIAL_LSRMST_INSERT constants */ +#define SERIAL_LSRMST_LSR_DATA 0x01 +#define SERIAL_LSRMST_LSR_NODATA 0x02 +#define SERIAL_LSRMST_MST 0x03 +#define SERIAL_LSRMST_ESCAPE 0x00 + +/* IOCTL_SERIAL_PURGE constants */ +#define SERIAL_PURGE_TXABORT 0x00000001 +#define SERIAL_PURGE_RXABORT 0x00000002 +#define SERIAL_PURGE_TXCLEAR 0x00000004 +#define SERIAL_PURGE_RXCLEAR 0x00000008 + +/* IOCTL_SERIAL_SET_FIFO_CONTROL constants */ +#define SERIAL_IOC_FCR_FIFO_ENABLE 0x00000001 +#define SERIAL_IOC_FCR_RCVR_RESET 0x00000002 +#define SERIAL_IOC_FCR_XMIT_RESET 0x00000004 +#define SERIAL_IOC_FCR_DMA_MODE 0x00000008 +#define SERIAL_IOC_FCR_RES1 0x00000010 +#define SERIAL_IOC_FCR_RES2 0x00000020 +#define SERIAL_IOC_FCR_RCVR_TRIGGER_LSB 0x00000040 +#define SERIAL_IOC_FCR_RCVR_TRIGGER_MSB 0x00000080 + +typedef struct _SERIAL_QUEUE_SIZE { + ULONG InSize; + ULONG OutSize; +} SERIAL_QUEUE_SIZE, *PSERIAL_QUEUE_SIZE; + +typedef struct _SERIAL_XOFF_COUNTER { + ULONG Timeout; + LONG Counter; + UCHAR XoffChar; +} SERIAL_XOFF_COUNTER, *PSERIAL_XOFF_COUNTER; + +typedef struct _SERIAL_BASIC_SETTINGS { + SERIAL_TIMEOUTS Timeouts; + SERIAL_HANDFLOW HandFlow; + ULONG RxFifo; + ULONG TxFifo; +} SERIAL_BASIC_SETTINGS, *PSERIAL_BASIC_SETTINGS; + +typedef struct _SERENUM_PORT_DESC { + ULONG Size; + PVOID PortHandle; + PHYSICAL_ADDRESS PortAddress; + USHORT Reserved[1]; +} SERENUM_PORT_DESC, *PSERENUM_PORT_DESC; + +typedef UCHAR STDCALL +(*PSERENUM_READPORT)( + PVOID SerPortAddress); + +typedef VOID STDCALL +(*PSERENUM_WRITEPORT)( + PVOID SerPortAddress, + UCHAR Value); + +typedef enum _SERENUM_PORTION { + SerenumFirstHalf, + SerenumSecondHalf, + SerenumWhole +} SERENUM_PORTION; + +typedef struct _SERENUM_PORT_PARAMETERS { + ULONG Size; + PSERENUM_READPORT ReadAccessor; + PSERENUM_WRITEPORT WriteAccessor; + PVOID SerPortAddress; + PVOID HardwareHandle; + SERENUM_PORTION Portion; + USHORT NumberAxis; + USHORT Reserved[3]; +} SERENUM_PORT_PARAMETERS, *PSERENUM_PORT_PARAMETERS; + +#define SERIAL_ERROR_BREAK 0x00000001 +#define SERIAL_ERROR_FRAMING 0x00000002 +#define SERIAL_ERROR_OVERRUN 0x00000004 +#define SERIAL_ERROR_QUEUEOVERRUN 0x00000008 +#define SERIAL_ERROR_PARITY 0x00000010 + +#define SERIAL_SP_UNSPECIFIED 0x00000000 +#define SERIAL_SP_RS232 0x00000001 +#define SERIAL_SP_PARALLEL 0x00000002 +#define SERIAL_SP_RS422 0x00000003 +#define SERIAL_SP_RS423 0x00000004 +#define SERIAL_SP_RS449 0x00000005 +#define SERIAL_SP_MODEM 0X00000006 +#define SERIAL_SP_FAX 0x00000021 +#define SERIAL_SP_SCANNER 0x00000022 +#define SERIAL_SP_BRIDGE 0x00000100 +#define SERIAL_SP_LAT 0x00000101 +#define SERIAL_SP_TELNET 0x00000102 +#define SERIAL_SP_X25 0x00000103 +#define SERIAL_SP_SERIALCOMM 0x00000001 + +#define SERIAL_TX_WAITING_FOR_CTS 0x00000001 +#define SERIAL_TX_WAITING_FOR_DSR 0x00000002 +#define SERIAL_TX_WAITING_FOR_DCD 0x00000004 +#define SERIAL_TX_WAITING_FOR_XON 0x00000008 +#define SERIAL_TX_WAITING_XOFF_SENT 0x00000010 +#define SERIAL_TX_WAITING_ON_BREAK 0x00000020 +#define SERIAL_RX_WAITING_FOR_DSR 0x00000040 + +#define SERIAL_DTR_STATE 0x00000001 +#define SERIAL_RTS_STATE 0x00000002 +#define SERIAL_CTS_STATE 0x00000010 +#define SERIAL_DSR_STATE 0x00000020 +#define SERIAL_RI_STATE 0x00000040 +#define SERIAL_DCD_STATE 0x00000080 + +typedef struct _SERIALCONFIG { + ULONG Size; + USHORT Version; + ULONG SubType; + ULONG ProvOffset; + ULONG ProviderSize; + WCHAR ProviderData[1]; +} SERIALCONFIG,*PSERIALCONFIG; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif /* __NTDDSER_H */ diff --git a/include/ddk/ntddvid.h b/include/ddk/ntddvid.h new file mode 100644 index 0000000..3240396 --- /dev/null +++ b/include/ddk/ntddvid.h @@ -0,0 +1,453 @@ +/* + * NTDDVID.H - Video Port and MiniPort driver interface + */ + +#include + +/* + * the rough idea: + * init: + * miniport driver defines entrypoint thusly: + * ULONG DriverEntry(PVOID Context1, PVOID Context2); + * miniport allocates and initializes a VIDEO_HW_INIT_DATA struct + * miniport calls VideoPortInitialize + * video port driver handles init of DriverObject (Context1) + * video port driver calls back into HwVidFindAdapter entry point + * video port driver finishes up and returns the status code that + * the miniport driver should return. + * io requests: + * video port driver reformats IRP into VRP + * video port driver calls back into HwVidStartIO entry point + * minimum IoControlCodes that must be handles by the miniport: + * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES + * IOCTL_VIDEO_QUERY_AVAIL_MODES + * IOCTL_VIDEO_SET_CURRENT_MODE + * IOCTL_VIDEO_MAP_MEMORY + * IOCTL_VIDEO_RESET_DEVICE + * interrupts are handled the same as KM drivers. + */ + +typedef LONG VP_STATUS, *PVP_STATUS; + +// Bit definitions for Attribute Flags +#define VIDEO_MODE_COLOR 0x0001 +#define VIDEO_MODE_GRAPHICS 0x0002 +#define VIDEO_MODE_PALETTE_DRIVEN 0x0004 + +#define VIDEO_MEMORY_SPACE_MEMORY 0x00 +#define VIDEO_MEMORY_SPACE_IO 0x01 +#define VIDEO_MEMORY_SPACE_USER_MODE 0x02 +#define VIDEO_MEMORY_SPACE_DENSE 0x04 +#define VIDEO_MEMORY_SPACE_P6CACHE 0x08 + +typedef struct _VIDEO_POINTER_CAPABILITIES +{ + ULONG Flags; + ULONG MaxWidth; + ULONG MaxHeight; + ULONG HWPtrBitmapStart; + ULONG HWPtrBitmapEnd; +} VIDEO_POINTER_CAPABILITIES, *PVIDEO_POINTER_CAPABILITIES; + +typedef struct _VIDEO_POINTER_ATTRIBUTES +{ + ULONG Flags; + ULONG Width; + ULONG Height; + ULONG WidthInBytes; + ULONG Enable; + SHORT Column; + SHORT Row; + UCHAR Pixels[1]; +} VIDEO_POINTER_ATTRIBUTES, *PVIDEO_POINTER_ATTRIBUTES; + +typedef enum _VIDEO_BANK_TYPE +{ + VideoNotBanked = 0, + VideoBanked1RW, + VideoBanked1R1W, + VideoBanked2RW, + NumVideoBankTypes +} VIDEO_BANK_TYPE, *PVIDEO_BANK_TYPE; + +typedef struct _VIDEO_BANK_SELECT +{ + ULONG Length; + ULONG Size; + ULONG BankingFlags; + ULONG BankingType; + ULONG PlanarHCBankingType; + ULONG BitmapWidthInBytes; + ULONG BitmapSize; + ULONG Granularity; + ULONG PlanarHCGranularity; + ULONG CodeOffset; + ULONG PlanarHCBankCodeOffset; + ULONG PlanarHCEnableCodeOffset; + ULONG PlanarHCDisableCodeOffset; +} VIDEO_BANK_SELECT, *PVIDEO_BANK_SELECT; + +typedef struct _VIDEO_CLUTDATA +{ + UCHAR Red; + UCHAR Green; + UCHAR Blue; + UCHAR Unused; +} VIDEO_CLUTDATA, *PVIDEO_CLUTDATA; + +typedef struct _VIDEO_NUM_MODES +{ + ULONG NumModes; + ULONG ModeInformationLength; +} VIDEO_NUM_MODES, *PVIDEO_NUM_MODES; + +typedef struct _VIDEO_MODE_INFORMATION +{ + ULONG Length; + ULONG ModeIndex; + ULONG VisScreenWidth; + ULONG VisScreenHeight; + ULONG ScreenStride; + ULONG NumberOfPlanes; + ULONG BitsPerPlane; + ULONG Frequency; + ULONG XMillimeter; + ULONG YMillimeter; + ULONG NumberRedBits; + ULONG NumberGreenBits; + ULONG NumberBlueBits; + ULONG RedMask; + ULONG GreenMask; + ULONG BlueMask; + ULONG AttributeFlags; + ULONG VideoMemoryBitmapWidth; + ULONG VideoMemoryBitmapHeight; + ULONG DriverSpecificAttributeFlags; +} VIDEO_MODE_INFORMATION, *PVIDEO_MODE_INFORMATION; + +typedef enum _VIDEO_DEVICE_DATA_TYPE +{ + VpMachineData, + VpCmosData, + VpBusData, + VpControllerData, + VpMonitorData +} VIDEO_DEVICE_DATA_TYPE, *PVIDEO_DEVICE_DATA_TYPE; + +typedef enum _VIDEO_SYNCHRONIZE_PRIORITY +{ + VpLowPriority, + VpMediumPriority, + VpHighPriority +} VIDEO_SYNCHRONIZE_PRIORITY, *PVIDEO_SYNCHRONIZE_PRIORITY; + +typedef struct _STATUS_BLOCK +{ + VP_STATUS Status; + ULONG Information; +} STATUS_BLOCK, *PSTATUS_BLOCK; + +typedef struct _VIDEO_REQUEST_PACKET +{ + ULONG IoControlCode; + PSTATUS_BLOCK StatusBlock; + PVOID InputBuffer; + ULONG InputBufferLength; + PVOID OutputBuffer; + ULONG OutputBufferLength; +} VIDEO_REQUEST_PACKET, *PVIDEO_REQUEST_PACKET; + +#define IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES CTL_CODE(FILE_DEVICE_VIDEO, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_AVAIL_MODES CTL_CODE(FILE_DEVICE_VIDEO, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_CURRENT_MODE CTL_CODE(FILE_DEVICE_VIDEO, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_CURRENT_MODE CTL_CODE(FILE_DEVICE_VIDEO, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_RESET_DEVICE CTL_CODE(FILE_DEVICE_VIDEO, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_MAP_VIDEO_MEMORY CTL_CODE(FILE_DEVICE_VIDEO, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_UNMAP_VIDEO_MEMORY CTL_CODE(FILE_DEVICE_VIDEO, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SHARE_VIDEO_MEMORY CTL_CODE(FILE_DEVICE_VIDEO, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY CTL_CODE(FILE_DEVICE_VIDEO, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_GET_PUBLIC_ACCESS_RANGES CTL_CODE(FILE_DEVICE_VIDEO, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES CTL_CODE(FILE_DEVICE_VIDEO, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_GET_POWER_MANAGEMENT CTL_CODE(FILE_DEVICE_VIDEO, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_POWER_MANAGEMENT CTL_CODE(FILE_DEVICE_VIDEO, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_COLOR_CAPABILITIES CTL_CODE(FILE_DEVICE_VIDEO, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_COLOR_REGISTERS CTL_CODE(FILE_DEVICE_VIDEO, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_DISABLE_POINTER CTL_CODE(FILE_DEVICE_VIDEO, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_ENABLE_POINTER CTL_CODE(FILE_DEVICE_VIDEO, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES CTL_CODE(FILE_DEVICE_VIDEO, 17, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_POINTER_ATTR CTL_CODE(FILE_DEVICE_VIDEO, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_POINTER_ATTR CTL_CODE(FILE_DEVICE_VIDEO, 19, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_POINTER_POSITION CTL_CODE(FILE_DEVICE_VIDEO, 20, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_POINTER_POSITION CTL_CODE(FILE_DEVICE_VIDEO, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SAVE_HARDWARE_STATE CTL_CODE(FILE_DEVICE_VIDEO, 22, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_RESTORE_HARDWARE_STATE CTL_CODE(FILE_DEVICE_VIDEO, 23, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_DISABLE_CURSOR CTL_CODE(FILE_DEVICE_VIDEO, 24, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_ENABLE_CURSOR CTL_CODE(FILE_DEVICE_VIDEO, 25, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_CURSOR_ATTR CTL_CODE(FILE_DEVICE_VIDEO, 26, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_CURSOR_ATTR CTL_CODE(FILE_DEVICE_VIDEO, 27, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_QUERY_CURSOR_POSITION CTL_CODE(FILE_DEVICE_VIDEO, 28, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_CURSOR_POSITION CTL_CODE(FILE_DEVICE_VIDEO, 29, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_GET_BANK_SELECT_CODE CTL_CODE(FILE_DEVICE_VIDEO, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_SET_PALETTE_REGISTERS CTL_CODE(FILE_DEVICE_VIDEO, 31, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VIDEO_LOAD_AND_SET_FONT CTL_CODE(FILE_DEVICE_VIDEO, 32, METHOD_BUFFERED, FILE_ANY_ACCESS) + +typedef struct _VIDEO_PORT_CONFIG_INFO +{ + ULONG Length; + ULONG SystemIoBusNumber; + INTERFACE_TYPE AdapterInterfaceType; + ULONG BusInterruptLevel; + ULONG BusInterruptVector; + KINTERRUPT_MODE InterruptMode; + ULONG NumEmulatorAccessEntries; + PEMULATOR_ACCESS_ENTRY EmulatorAccessEntries; + ULONG EmulatorAccessEntriesContext; + PHYSICAL_ADDRESS VdmPhysicalVideoMemoryAddress; + ULONG VdmPhysicalVideoMemoryLength; + ULONG HardwareStateSize; + ULONG DmaChannel; + ULONG DmaPort; + UCHAR DmaShareable; + UCHAR InterruptShareable; +} VIDEO_PORT_CONFIG_INFO, *PVIDEO_PORT_CONFIG_INFO; + +typedef VP_STATUS STDCALL +(*PVIDEO_HW_FIND_ADAPTER)(PVOID HwDeviceExtension, + PVOID HwContext, + PWSTR ArgumentString, + PVIDEO_PORT_CONFIG_INFO ConfigInfo, + PUCHAR Again); + +typedef BOOLEAN STDCALL +(*PVIDEO_HW_INITIALIZE)(PVOID HwDeviceExtension); + +typedef BOOLEAN STDCALL +(*PVIDEO_HW_INTERRUPT)(PVOID HwDeviceExtension); + +typedef BOOLEAN STDCALL +(*PVIDEO_HW_START_IO)(PVOID HwDeviceExtension, + PVIDEO_REQUEST_PACKET RequestPacket); + +typedef BOOLEAN STDCALL +(*PVIDEO_HW_RESET_HW)(PVOID HwDeviceExtension, + ULONG Columns, + ULONG Rows); + +typedef VOID STDCALL +(*PVIDEO_HW_TIMER)(PVOID HwDeviceExtension); + +typedef struct _VIDEO_HW_INITIALIZATION_DATA +{ + ULONG HwInitDataSize; + INTERFACE_TYPE AdapterInterfaceType; + PVIDEO_HW_FIND_ADAPTER HwFindAdapter; + PVIDEO_HW_INITIALIZE HwInitialize; + PVIDEO_HW_INTERRUPT HwInterrupt; + PVIDEO_HW_START_IO HwStartIO; + ULONG HwDeviceExtensionSize; + ULONG StartingDeviceNumber; + PVIDEO_HW_RESET_HW HwResetHw; + PVIDEO_HW_TIMER HwTimer; +} VIDEO_HW_INITIALIZATION_DATA, *PVIDEO_HW_INITIALIZATION_DATA; + +typedef VP_STATUS STDCALL +(*PMINIPORT_GET_REGISTRY_ROUTINE)(PVOID HwDeviceExtension, + PVOID Context, + PWSTR ValueName, + PVOID ValueData, + ULONG ValueLength); + +typedef VP_STATUS STDCALL +(*PMINIPORT_QUERY_DEVICE_ROUTINE)(PVOID HwDeviceExtension, + PVOID Context, + VIDEO_DEVICE_DATA_TYPE DeviceDataType, + PVOID Identifier, + ULONG IdentiferLength, + PVOID ConfigurationData, + ULONG ConfigurationDataLength, + PVOID ComponentInformation, + ULONG ComponentInformationLength); + +typedef BOOLEAN STDCALL +(*PMINIPORT_SYNCHRONIZE_ROUTINE)(PVOID Context); + +typedef struct _VIDEO_ACCESS_RANGE +{ + PHYSICAL_ADDRESS RangeStart; + ULONG RangeLength; + UCHAR RangeInIoSpace; + UCHAR RangeVisible; + UCHAR RangeShareable; +} VIDEO_ACCESS_RANGE, *PVIDEO_ACCESS_RANGE; + +typedef struct _VIDEO_X86_BIOS_ARGUMENTS +{ + ULONG Eax; + ULONG Ebx; + ULONG Ecx; + ULONG Edx; + ULONG Esi; + ULONG Edi; + ULONG Ebp; +} VIDEO_X86_BIOS_ARGUMENTS, *PVIDEO_X86_BIOS_ARGUMENTS; + +typedef VOID STDCALL +(*PBANKED_SECTION_ROUTINE)(IN ULONG ReadBank, + IN ULONG WriteBank, + IN PVOID Context); + +typedef struct +{ + USHORT NumEntries; + USHORT FirstEntry; + union + { + VIDEO_CLUTDATA RgbArray; + ULONG RgbLong; + } LookupTable[1]; +} VIDEO_CLUT, *PVIDEO_CLUT; + +typedef struct _VIDEO_MEMORY +{ + PVOID RequestedVirtualAddress; +} VIDEO_MEMORY, *PVIDEO_MEMORY; + +typedef struct _VIDEO_MEMORY_INFORMATION +{ + PVOID VideoRamBase; + ULONG VideoRamLength; + PVOID FrameBufferBase; + ULONG FrameBufferLength; +} VIDEO_MEMORY_INFORMATION, *PVIDEO_MEMORY_INFORMATION; + +typedef struct _VIDEO_MODE +{ + ULONG RequestedMode; +} VIDEO_MODE, *PVIDEO_MODE; + +typedef struct _VIDEO_SHARE_MEMORY +{ + HANDLE ProcessHandle; + ULONG ViewOffset; + ULONG ViewSize; + PVOID RequestedVirtualAddress; +} VIDEO_SHARE_MEMORY, *PVIDEO_SHARE_MEMORY; + +ULONG STDCALL VideoPortCompareMemory(IN PVOID Source1, IN PVOID Source2, IN ULONG Length); +VOID VideoPortDebugPrint(IN ULONG DebugPrintLevel, IN PCHAR DebugMessage, ...); +VP_STATUS STDCALL VideoPortDisableInterrupt(IN PVOID HwDeviceExtension); +VP_STATUS STDCALL VideoPortEnableInterrupt(IN PVOID HwDeviceExtension); +VOID STDCALL VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension, IN PVOID MappedAddress); +ULONG STDCALL VideoPortGetBusData(IN PVOID HwDeviceExtension, + IN BUS_DATA_TYPE BusDataType, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length); +UCHAR STDCALL VideoPortGetCurrentIrql(VOID); +PVOID STDCALL VideoPortGetDeviceBase(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfUchars, + IN UCHAR InIoSpace); +VP_STATUS STDCALL VideoPortGetDeviceData(IN PVOID HwDeviceExtension, + IN VIDEO_DEVICE_DATA_TYPE DeviceDataType, + IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine, + IN PVOID Context); +VP_STATUS STDCALL VideoPortGetAccessRanges(IN PVOID HwDeviceExtension, + IN ULONG NumRequestedResources, + IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRanges, + IN PVOID VendorId, + IN PVOID DeviceId, + IN PULONG Slot); +VP_STATUS STDCALL VideoPortGetRegistryParameters(IN PVOID HwDeviceExtension, + IN PWSTR ParameterName, + IN UCHAR IsParameterFileName, + IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine, + IN PVOID Context); +ULONG STDCALL VideoPortInitialize(IN PVOID Context1, + IN PVOID Context2, + IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData, + IN PVOID HwContext); +VP_STATUS STDCALL VideoPortInt10(IN PVOID HwDeviceExtension, + IN PVIDEO_X86_BIOS_ARGUMENTS BiosArguments); +VOID STDCALL VideoPortLogError(IN PVOID HwDeviceExtension, + IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL, + IN VP_STATUS ErrorCode, + IN ULONG UniqueId); +VP_STATUS STDCALL VideoPortMapBankedMemory(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN PULONG Length, + IN PULONG InIoSpace, + OUT PVOID *VirtualAddress, + IN ULONG BankLength, + IN UCHAR ReadWriteBank, + IN PBANKED_SECTION_ROUTINE BankRoutine, + IN PVOID Context); +VP_STATUS STDCALL VideoPortMapMemory(IN PVOID HwDeviceExtension, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN PULONG Length, + IN PULONG InIoSpace, + OUT PVOID *VirtualAddress); +VOID STDCALL VideoPortMoveMemory(OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length); +UCHAR STDCALL VideoPortReadPortUchar(IN PUCHAR Port); +USHORT STDCALL VideoPortReadPortUshort(IN PUSHORT Port); +ULONG STDCALL VideoPortReadPortUlong(IN PULONG Port); +VOID STDCALL VideoPortReadPortBufferUchar(IN PUCHAR Port, OUT PUCHAR Buffer, IN ULONG Count); +VOID STDCALL VideoPortReadPortBufferUshort(IN PUSHORT Port, OUT PUSHORT Buffer, IN ULONG Count); +VOID STDCALL VideoPortReadPortBufferUlong(IN PULONG Port, OUT PULONG Buffer, IN ULONG Count); +UCHAR STDCALL VideoPortReadRegisterUchar(IN PUCHAR Register); +USHORT STDCALL VideoPortReadRegisterUshort(IN PUSHORT Register); +ULONG STDCALL VideoPortReadRegisterUlong(IN PULONG Register); +VOID STDCALL VideoPortReadRegisterBufferUchar(IN PUCHAR Register, OUT PUCHAR Buffer, IN ULONG Count); +VOID STDCALL VideoPortReadRegisterBufferUshort(IN PUSHORT Register, OUT PUSHORT Buffer, IN ULONG Count); +VOID STDCALL VideoPortReadRegisterBufferUlong(IN PULONG Register, OUT PULONG Buffer, IN ULONG Count); +BOOLEAN STDCALL VideoPortScanRom(IN PVOID HwDeviceExtension, + IN PUCHAR RomBase, + IN ULONG RomLength, + IN PUCHAR String); +ULONG STDCALL VideoPortSetBusData(IN PVOID HwDeviceExtension, + IN BUS_DATA_TYPE BusDataType, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length); +VP_STATUS STDCALL VideoPortSetRegistryParameters(IN PVOID HwDeviceExtension, + IN PWSTR ValueName, + IN PVOID ValueData, + IN ULONG ValueLength); +VP_STATUS STDCALL VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRange); +VOID STDCALL VideoPortStallExecution(IN ULONG Microseconds); +VOID STDCALL VideoPortStartTimer(IN PVOID HwDeviceExtension); +VOID STDCALL VideoPortStopTimer(IN PVOID HwDeviceExtension); +BOOLEAN STDCALL VideoPortSynchronizeExecution(IN PVOID HwDeviceExtension, + IN VIDEO_SYNCHRONIZE_PRIORITY Priority, + IN PMINIPORT_SYNCHRONIZE_ROUTINE SynchronizeRoutine, + OUT PVOID Context); +VP_STATUS STDCALL VideoPortUnmapMemory(IN PVOID HwDeviceExtension, + IN PVOID VirtualAddress, + IN HANDLE ProcessHandle); +VP_STATUS STDCALL VideoPortVerifyAccessRanges(IN PVOID HwDeviceExtension, + IN ULONG NumAccessRanges, + IN PVIDEO_ACCESS_RANGE AccessRanges); +VOID STDCALL VideoPortWritePortUchar(IN PUCHAR Port, IN UCHAR Value); +VOID STDCALL VideoPortWritePortUshort(IN PUSHORT Port, IN USHORT Value); +VOID STDCALL VideoPortWritePortUlong(IN PULONG Port, IN ULONG Value); +VOID STDCALL VideoPortWritePortBufferUchar(IN PUCHAR Port, IN PUCHAR Buffer, IN ULONG Count); +VOID STDCALL VideoPortWritePortBufferUshort(IN PUSHORT Port, IN PUSHORT Buffer, IN ULONG Count); +VOID STDCALL VideoPortWritePortBufferUlong(IN PULONG Port, IN PULONG Buffer, IN ULONG Count); +VOID STDCALL VideoPortWriteRegisterUchar(IN PUCHAR Register, IN UCHAR Value); +VOID STDCALL VideoPortWriteRegisterUshort(IN PUSHORT Register, IN USHORT Value); +VOID STDCALL VideoPortWriteRegisterUlong(IN PULONG Register, IN ULONG Value); +VOID STDCALL VideoPortWriteRegisterBufferUchar(IN PUCHAR Register, IN PUCHAR Buffer, IN ULONG Count); +VOID STDCALL VideoPortWriteRegisterBufferUshort(IN PUSHORT Register, IN PUSHORT Buffer, IN ULONG Count); +VOID STDCALL VideoPortWriteRegisterBufferUlong(IN PULONG Register, IN PULONG Buffer, IN ULONG Count); +VOID STDCALL VideoPortZeroMemory(OUT PVOID Destination, IN ULONG Length); +VOID STDCALL VideoPortZeroDeviceMemory(OUT PVOID Destination, IN ULONG Length); + + diff --git a/include/ddk/ntdef.h b/include/ddk/ntdef.h new file mode 100644 index 0000000..264adc1 --- /dev/null +++ b/include/ddk/ntdef.h @@ -0,0 +1,13 @@ +#ifndef __INCLUDE_DDK_NTDEF_H +#define __INCLUDE_DDK_NTDEF_H + +struct _KTHREAD; +struct _ETHREAD; +struct _EPROCESS; + +#define NTKERNELAPI +#define NTSYSAPI +#define NTAPI + + +#endif diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h new file mode 100644 index 0000000..ca81c9b --- /dev/null +++ b/include/ddk/ntifs.h @@ -0,0 +1,41 @@ +#ifndef __INCLUDE_DDK_NTIFS_H +#define __INCLUDE_DDK_NTIFS_H + +struct _BCB; + +typedef struct _BCB* PBCB; + +struct _MEMORY_AREA; + +struct _CACHE_SEGMENT; + +typedef struct _CACHE_SEGMENT* PCACHE_SEGMENT; + +NTSTATUS STDCALL +CcRosReleaseCacheSegment (struct _BCB* Bcb, + struct _CACHE_SEGMENT* CacheSeg, + BOOLEAN Valid, + BOOLEAN Dirty, + BOOLEAN Mapped); +NTSTATUS STDCALL +CcRosRequestCacheSegment (struct _BCB* Bcb, + ULONG FileOffset, + PVOID* BaseAddress, + PBOOLEAN UptoDate, + struct _CACHE_SEGMENT** CacheSeg); +NTSTATUS STDCALL +CcRosInitializeFileCache (PFILE_OBJECT FileObject, + struct _BCB** Bcb, + ULONG CacheSegmentSize); +NTSTATUS STDCALL +CcRosReleaseFileCache (PFILE_OBJECT FileObject, + struct _BCB* Bcb); + +#include + +#include + +#include +#include + +#endif /* __INCLUDE_DDK_NTIFS_H */ diff --git a/include/ddk/obfuncs.h b/include/ddk/obfuncs.h new file mode 100644 index 0000000..9fb2d22 --- /dev/null +++ b/include/ddk/obfuncs.h @@ -0,0 +1,180 @@ +#ifndef _INCLUDE_DDK_OBFUNCS_H +#define _INCLUDE_DDK_OBFUNCS_H +/* OBJECT MANAGER ************************************************************/ + +NTSTATUS STDCALL +ObAssignSecurity(IN PACCESS_STATE AccessState, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PVOID Object, + IN POBJECT_TYPE Type); + +/* +BOOLEAN STDCALL +ObCheckCreateObjectAccess(IN PVOID Object, + IN ACCESS_MASK DesiredAccess, + ULONG Param3, + ULONG Param4, + ULONG Param5, + IN KPROCESSOR_MODE AccessMode, + OUT PNTSTATUS AccessStatus); +*/ + +/* +BOOLEAN STDCALL +ObCheckObjectAccess(IN PVOID Object, + ULONG Param2, + ULONG Param3, + IN KPROCESSOR_MODE AccessMode, + OUT PACCESS_MODE GrantedAccess); +*/ + +NTSTATUS STDCALL +ObCreateObject(OUT PHANDLE Handle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN POBJECT_TYPE Type, + OUT PVOID *Object); + +#if 0 +/* original implementation */ +NTSTATUS STDCALL +ObCreateObject(IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, + IN POBJECT_TYPE Type, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext OPTIONAL, + IN ULONG ObjectSize, + IN ULONG PagedPoolCharge OPTIONAL, + IN ULONG NonPagedPoolCharge OPTIONAL, + OUT PVOID *Object); +#endif + +VOID FASTCALL +ObfDereferenceObject(IN PVOID Object); + +VOID FASTCALL +ObfReferenceObject(IN PVOID Object); + +#define ObDereferenceObject(Object) \ + ObfDereferenceObject(Object) + +#define ObReferenceObject(Object) \ + ObfReferenceObject(Object) + +/* +BOOLEAN STDCALL +ObFindHandleForObject(ULONG Param1, + ULONG Param2, + ULONG Param3, + ULONG Param4); +*/ + +ULONG STDCALL +ObGetObjectPointerCount(IN PVOID Object); + +NTSTATUS STDCALL +ObGetObjectSecurity(IN PVOID Object, + OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, + OUT PBOOLEAN MemoryAllocated); + +NTSTATUS STDCALL +ObInsertObject(IN PVOID Object, + IN PACCESS_STATE PassedAccessState OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN ULONG AdditionalReferences, + OUT PVOID* ReferencedObject OPTIONAL, + OUT PHANDLE Handle); + +VOID STDCALL +ObMakeTemporaryObject(IN PVOID ObjectBody); + +NTSTATUS STDCALL +ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, + IN POBJECT_TYPE ObjectType, + IN OUT PVOID ParseContext OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + IN ACCESS_MASK DesiredAccess, + IN PACCESS_STATE PassedAccessState, + OUT PHANDLE Handle); + +NTSTATUS STDCALL +ObOpenObjectByPointer(IN PVOID Object, + IN ULONG HandleAttributes, + IN PACCESS_STATE PassedAccessState OPTIONAL, + IN ACCESS_MASK DesiredAccess OPTIONAL, + IN POBJECT_TYPE ObjectType OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + OUT PHANDLE Handle); + +NTSTATUS STDCALL +ObQueryNameString(IN PVOID Object, + OUT POBJECT_NAME_INFORMATION ObjectNameInfo, + IN ULONG Length, + OUT PULONG ReturnLength); + +NTSTATUS STDCALL +ObQueryObjectAuditingByHandle(IN HANDLE Handle, + OUT PBOOLEAN GenerateOnClose); + +/* + * FUNCTION: Performs access validation on an object handle and if access + * is granted returns a pointer to the object's body + * ARGUMENTS: + * Handle = Handle to the object + * DesiredAccess = Desired access to the object + * ObjectType (OPTIONAL) = Pointer to the object's type definition + * AccessMode = Access mode to use for the check + * Object (OUT) = Caller supplied storage for a pointer to the object's + * body + * HandleInformation (OUT) = Points to a structure which receives + * information about the handle + * RETURNS: Status + */ +NTSTATUS STDCALL +ObReferenceObjectByHandle(IN HANDLE Handle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE ObjectType OPTIONAL, + IN KPROCESSOR_MODE AccessMode, + OUT PVOID* Object, + OUT POBJECT_HANDLE_INFORMATION HandleInfo OPTIONAL); + +/* + * FUNCTION: Increments the reference count for a given object + * ARGUMENTS: + * Object = Points to the body of the object + * AccessMode = Requested access to the object + * ObjectType = Pointer to the object's type definition + * AccessMode = Access mode to use for the security check + * RETURNS: Status + */ +NTSTATUS STDCALL +ObReferenceObjectByPointer(IN PVOID Object, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode); + +NTSTATUS STDCALL +ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, + IN ULONG Attributes, + IN PACCESS_STATE PassedAccessState OPTIONAL, + IN ACCESS_MASK DesiredAccess OPTIONAL, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode, + IN OUT PVOID ParseContext OPTIONAL, + OUT PVOID* ObjectPtr); + +VOID STDCALL +ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN BOOLEAN MemoryAllocated); + +/* +NTSTATUS STDCALL +ObSetSecurityDescriptorInfo(IN PVOID Object, + IN PSECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + ULONG Param4, + IN POOL_TYPE PoolType, + IN PGENERIC_MAPPING GenericMapping); +*/ + +#endif /* ndef _INCLUDE_DDK_OBFUNCS_H */ diff --git a/include/ddk/obtypes.h b/include/ddk/obtypes.h new file mode 100644 index 0000000..bd55d80 --- /dev/null +++ b/include/ddk/obtypes.h @@ -0,0 +1,199 @@ +#ifndef _INCLUDE_DDK_OBTYPES_H +#define _INCLUDE_DDK_OBTYPES_H +/* $Id$ */ +struct _DIRECTORY_OBJECT; +struct _OBJECT_ATTRIBUTES; + +typedef ULONG ACCESS_STATE, *PACCESS_STATE; + +typedef struct _OBJECT_HANDLE_INFORMATION { + ULONG HandleAttributes; + ACCESS_MASK GrantedAccess; +} OBJECT_HANDLE_INFORMATION, *POBJECT_HANDLE_INFORMATION; + +typedef struct _OBJECT_TYPE +{ + /* + * PURPOSE: Tag to be used when allocating objects of this type + */ + ULONG Tag; + + /* + * PURPOSE: Name of the type + */ + UNICODE_STRING TypeName; + + /* + * PURPOSE: Total number of objects of this type + */ + ULONG TotalObjects; + + /* + * PURPOSE: Total number of handles of this type + */ + ULONG TotalHandles; + + /* + * PURPOSE: Maximum objects of this type + */ + ULONG MaxObjects; + + /* + * PURPOSE: Maximum handles of this type + */ + ULONG MaxHandles; + + /* + * PURPOSE: Paged pool charge + */ + ULONG PagedPoolCharge; + + /* + * PURPOSE: Nonpaged pool charge + */ + ULONG NonpagedPoolCharge; + + /* + * PURPOSE: Mapping of generic access rights + */ + PGENERIC_MAPPING Mapping; + + /* + * PURPOSE: Dumps the object + * NOTE: To be defined + */ + VOID STDCALL (*Dump)(VOID); + + /* + * PURPOSE: Opens the object + * NOTE: To be defined + */ + VOID STDCALL (*Open)(VOID); + + /* + * PURPOSE: Called to close an object if OkayToClose returns true + */ + VOID STDCALL (*Close)(PVOID ObjectBody, + ULONG HandleCount); + + /* + * PURPOSE: Called to delete an object when the last reference is removed + */ + VOID STDCALL (*Delete)(PVOID ObjectBody); + + /* + * PURPOSE: Called when an open attempts to open a file apparently + * residing within the object + * RETURNS + * STATUS_SUCCESS NextObject was found + * STATUS_UNSUCCESSFUL NextObject not found + * STATUS_REPARSE Path changed, restart parsing the path + */ + NTSTATUS STDCALL (*Parse)(PVOID ParsedObject, + PVOID *NextObject, + PUNICODE_STRING FullPath, + PWSTR *Path, + ULONG Attributes); + + /* + */ + NTSTATUS STDCALL (*Security)(PVOID Object, + ULONG InfoClass, + PVOID Info, + PULONG InfoLength); + + /* + */ + VOID STDCALL (*QueryName)(VOID); + + /* + * PURPOSE: Called when a process asks to close the object + */ + VOID STDCALL (*OkayToClose)(VOID); + + NTSTATUS STDCALL (*Create)(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes); + + VOID STDCALL (*DuplicationNotify)(PEPROCESS DuplicateTo, + PEPROCESS DuplicateFrom, + PVOID Object); +} OBJECT_TYPE, *POBJECT_TYPE; + + +typedef struct _OBJECT_HEADER +/* + * PURPOSE: Header for every object managed by the object manager + */ +{ + UNICODE_STRING Name; + LIST_ENTRY Entry; + LONG RefCount; + LONG HandleCount; + BOOLEAN CloseInProcess; + BOOLEAN Permanent; + struct _DIRECTORY_OBJECT* Parent; + POBJECT_TYPE ObjectType; + + /* + * PURPOSE: Object type + * NOTE: This overlaps the first member of the object body + */ + CSHORT Type; + + /* + * PURPOSE: Object size + * NOTE: This overlaps the second member of the object body + */ + CSHORT Size; + + +} OBJECT_HEADER, *POBJECT_HEADER; + +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + SECURITY_DESCRIPTOR *SecurityDescriptor; + SECURITY_QUALITY_OF_SERVICE *SecurityQualityOfService; +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + +typedef struct _HANDLE_TABLE +{ + LIST_ENTRY ListHead; + KSPIN_LOCK ListLock; +} HANDLE_TABLE, *PHANDLE_TABLE; + +extern POBJECT_TYPE ObDirectoryType; + +#if 0 +#define OBJECT_TYPE_0 0 +#define OBJECT_TYPE_1 1 +#define OBJECT_TYPE_DIRECTORY 2 +#define OBJECT_TYPE_SYMBOLICLINK 3 +#define OBJECT_TYPE_TOKEN 4 +#define OBJECT_TYPE_PROCESS 5 +#define OBJECT_TYPE_THREAD 6 +#define OBJECT_TYPE_EVENT 7 +#define OBJECT_TYPE_8 8 +#define OBJECT_TYPE_MUTANT 9 +#define OBJECT_TYPE_SEMAPHORE 10 +#define OBJECT_TYPE_TIMER 11 +#define OBJECT_TYPE_12 12 +#define OBJECT_TYPE_WINDOWSTATION 13 +#define OBJECT_TYPE_DESKTOP 14 +#define OBJECT_TYPE_SECTION 15 +#define OBJECT_TYPE_KEY 16 +#define OBJECT_TYPE_PORT 17 +#define OBJECT_TYPE_18 18 +#define OBJECT_TYPE_19 19 +#define OBJECT_TYPE_20 20 +#define OBJECT_TYPE_21 21 +#define OBJECT_TYPE_IOCOMPLETION 22 +#define OBJECT_TYPE_FILE 23 +#endif + +#endif /* ndef _INCLUDE_DDK_OBTYPES_H */ diff --git a/include/ddk/pnpfuncs.h b/include/ddk/pnpfuncs.h new file mode 100644 index 0000000..73ae2c3 --- /dev/null +++ b/include/ddk/pnpfuncs.h @@ -0,0 +1,176 @@ +#ifndef __INCLUDE_DDK_PNPFUNCS_H +#define __INCLUDE_DDK_PNPFUNCS_H + +#define IoInitializeRemoveLock(Lock, Tag, Maxmin, HighWater) \ + IoInitializeRemoveLockEx(Lock, Tag, Maxmin, HighWater, sizeof(IO_REMOVE_LOCK)) + +VOID +STDCALL +IoInitializeRemoveLockEx( + IN PIO_REMOVE_LOCK Lock, + IN ULONG AllocateTag, + IN ULONG MaxLockedMinutes, + IN ULONG HighWatermark, + IN ULONG RemlockSize); + +#define IoAcquireRemoveLock(RemoveLock, Tag) \ + IoAcquireRemoveLockEx(RemoveLock, Tag, __FILE__, __LINE__, sizeof(IO_REMOVE_LOCK)) + +NTSTATUS +STDCALL +IoAcquireRemoveLockEx( + IN PIO_REMOVE_LOCK RemoveLock, + IN OPTIONAL PVOID Tag, + IN LPCSTR File, + IN ULONG Line, + IN ULONG RemlockSize); + +#define IoReleaseRemoveLock(RemoveLock, Tag) \ + IoReleaseRemoveLockEx(RemoveLock, Tag, sizeof (IO_REMOVE_LOCK)) + +VOID +STDCALL +IoReleaseRemoveLockEx( + IN PIO_REMOVE_LOCK RemoveLock, + IN PVOID Tag, + IN ULONG RemlockSize); + +#define IoReleaseRemoveLockAndWait(RemoveLock, Tag) \ + IoReleaseRemoveLockAndWaitEx(RemoveLock, Tag, sizeof (IO_REMOVE_LOCK)) + +VOID +STDCALL +IoReleaseRemoveLockAndWaitEx( + IN PIO_REMOVE_LOCK RemoveLock, + IN PVOID Tag, + IN ULONG RemlockSize); + +VOID +STDCALL +IoAdjustPagingPathCount( + IN PLONG Count, + IN BOOLEAN Increment); + +NTSTATUS +STDCALL +IoGetDeviceInterfaceAlias( + IN PUNICODE_STRING SymbolicLinkName, + IN CONST GUID *AliasInterfaceClassGuid, + OUT PUNICODE_STRING AliasSymbolicLinkName); + +NTSTATUS +STDCALL +IoGetDeviceInterfaces( + IN CONST GUID *InterfaceClassGuid, + IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, + IN ULONG Flags, + OUT PWSTR *SymbolicLinkList); + +NTSTATUS +STDCALL +IoGetDeviceProperty( + IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_REGISTRY_PROPERTY DeviceProperty, + IN ULONG BufferLength, + OUT PVOID PropertyBuffer, + OUT PULONG ResultLength); + +VOID +STDCALL +IoInvalidateDeviceRelations( + IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_RELATION_TYPE Type); + +VOID +STDCALL +IoInvalidateDeviceState( + IN PDEVICE_OBJECT PhysicalDeviceObject); + +NTSTATUS +STDCALL +IoOpenDeviceInterfaceRegistryKey( + IN PUNICODE_STRING SymbolicLinkName, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE DeviceInterfaceKey); + +NTSTATUS +STDCALL +IoOpenDeviceRegistryKey( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DevInstKeyType, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE DevInstRegKey); + +NTSTATUS +STDCALL +IoRegisterDeviceInterface( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN CONST GUID *InterfaceClassGuid, + IN PUNICODE_STRING ReferenceString OPTIONAL, + OUT PUNICODE_STRING SymbolicLinkName); + +NTSTATUS +STDCALL +IoRegisterPlugPlayNotification( + IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, + IN ULONG EventCategoryFlags, + IN PVOID EventCategoryData OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, + IN PVOID Context, + OUT PVOID *NotificationEntry); + +NTSTATUS +STDCALL +IoReportDetectedDevice( + IN PDRIVER_OBJECT DriverObject, + IN INTERFACE_TYPE LegacyBusType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PCM_RESOURCE_LIST ResourceList, + IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL, + IN BOOLEAN ResourceAssigned, + IN OUT PDEVICE_OBJECT *DeviceObject); + +NTSTATUS +STDCALL +IoReportResourceForDetection( + IN PDRIVER_OBJECT DriverObject, + IN PCM_RESOURCE_LIST DriverList OPTIONAL, + IN ULONG DriverListSize OPTIONAL, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN PCM_RESOURCE_LIST DeviceList OPTIONAL, + IN ULONG DeviceListSize OPTIONAL, + OUT PBOOLEAN ConflictDetected); + +NTSTATUS +STDCALL +IoReportTargetDeviceChange( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PVOID NotificationStructure); + +NTSTATUS +STDCALL +IoReportTargetDeviceChangeAsynchronous( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PVOID NotificationStructure, + IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, + IN PVOID Context OPTIONAL); + +VOID +STDCALL +IoRequestDeviceEject( + IN PDEVICE_OBJECT PhysicalDeviceObject); + +NTSTATUS +STDCALL +IoSetDeviceInterfaceState( + IN PUNICODE_STRING SymbolicLinkName, + IN BOOLEAN Enable); + +NTSTATUS +STDCALL +IoUnregisterPlugPlayNotification( + IN PVOID NotificationEntry); + +#endif /* __INCLUDE_DDK_PNPFUNCS_H */ diff --git a/include/ddk/pnptypes.h b/include/ddk/pnptypes.h new file mode 100644 index 0000000..2ba5453 --- /dev/null +++ b/include/ddk/pnptypes.h @@ -0,0 +1,194 @@ +#ifndef __INCLUDE_DDK_PNPTYPES_H +#define __INCLUDE_DDK_PNPTYPES_H + +struct _DEVICE_OBJECT; +struct _FILE_OBJECT; + +// windows.h may be included before +#ifndef _GUID_DEFINED +#define _GUID_DEFINED + +typedef struct _GUID { + ULONG Data1; + USHORT Data2; + USHORT Data3; + UCHAR Data4[8]; +} GUID, *LPGUID; + +#endif + +typedef struct _PNP_BUS_INFORMATION { + GUID BusTypeGuid; + INTERFACE_TYPE LegacyBusType; + ULONG BusNumber; +} PNP_BUS_INFORMATION, *PPNP_BUS_INFORMATION; + +typedef struct _DEVICE_CAPABILITIES { + USHORT Size; + USHORT Version; + ULONG DeviceD1:1; + ULONG DeviceD2:1; + ULONG LockSupported:1; + ULONG EjectSupported:1; + ULONG Removable:1; + ULONG DockDevice:1; + ULONG UniqueID:1; + ULONG SilentInstall:1; + ULONG RawDeviceOK:1; + ULONG SurpriseRemovalOK:1; + ULONG WakeFromD0:1; + ULONG WakeFromD1:1; + ULONG WakeFromD2:1; + ULONG WakeFromD3:1; + ULONG HardwareDisabled:1; + ULONG NonDynamic:1; + ULONG WarmEjectSupported:1; + ULONG Reserved:15; + ULONG Address; + ULONG UINumber; + DEVICE_POWER_STATE DeviceState[PowerSystemMaximum]; + SYSTEM_POWER_STATE SystemWake; + DEVICE_POWER_STATE DeviceWake; + ULONG D1Latency; + ULONG D2Latency; + ULONG D3Latency; +} DEVICE_CAPABILITIES, *PDEVICE_CAPABILITIES; + +typedef struct _DEVICE_INTERFACE_CHANGE_NOTIFICATION { + USHORT Version; + USHORT Size; + GUID Event; + // + // Event-specific data + // + GUID InterfaceClassGuid; + PUNICODE_STRING SymbolicLinkName; +} DEVICE_INTERFACE_CHANGE_NOTIFICATION, *PDEVICE_INTERFACE_CHANGE_NOTIFICATION; + +typedef struct _HWPROFILE_CHANGE_NOTIFICATION { + USHORT Version; + USHORT Size; + GUID Event; + // + // (No event-specific data) + // +} HWPROFILE_CHANGE_NOTIFICATION, *PHWPROFILE_CHANGE_NOTIFICATION; + +typedef struct _PLUGPLAY_NOTIFICATION_HEADER { + USHORT Version; + USHORT Size; + GUID Event; +} PLUGPLAY_NOTIFICATION_HEADER, *PPLUGPLAY_NOTIFICATION_HEADER; + +typedef ULONG PNP_DEVICE_STATE, *PPNP_DEVICE_STATE; + +#define PNP_DEVICE_DISABLED 0x00000001 +#define PNP_DEVICE_DONT_DISPLAY_IN_UI 0x00000002 +#define PNP_DEVICE_FAILED 0x00000004 +#define PNP_DEVICE_REMOVED 0x00000008 +#define PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED 0x00000010 +#define PNP_DEVICE_NOT_DISABLEABLE 0x00000020 + +typedef struct _TARGET_DEVICE_CUSTOM_NOTIFICATION { + USHORT Version; + USHORT Size; + GUID Event; + // + // Event-specific data + // + struct _FILE_OBJECT *FileObject; + LONG NameBufferOffset; + UCHAR CustomDataBuffer[1]; +} TARGET_DEVICE_CUSTOM_NOTIFICATION, *PTARGET_DEVICE_CUSTOM_NOTIFICATION; + +typedef struct _TARGET_DEVICE_REMOVAL_NOTIFICATION { + USHORT Version; + USHORT Size; + GUID Event; + // + // Event-specific data + // + struct _FILE_OBJECT *FileObject; +} TARGET_DEVICE_REMOVAL_NOTIFICATION, *PTARGET_DEVICE_REMOVAL_NOTIFICATION; + + +// PnP Device Property for IoGetDeviceProperty +typedef enum { + DevicePropertyDeviceDescription, + DevicePropertyHardwareID, + DevicePropertyCompatibleIDs, + DevicePropertyBootConfiguration, + DevicePropertyBootConfigurationTranslated, + DevicePropertyClassName, + DevicePropertyClassGuid, + DevicePropertyDriverKeyName, + DevicePropertyManufacturer, + DevicePropertyFriendlyName, + DevicePropertyLocationInformation, + DevicePropertyPhysicalDeviceObjectName, + DevicePropertyBusTypeGuid, + DevicePropertyLegacyBusType, + DevicePropertyBusNumber, + DevicePropertyEnumeratorName, + DevicePropertyAddress, + DevicePropertyUINumber +} DEVICE_REGISTRY_PROPERTY; + +// DevInstKeyType values for IoOpenDeviceRegistryKey +#define PLUGPLAY_REGKEY_DEVICE 1 +#define PLUGPLAY_REGKEY_DRIVER 2 +#define PLUGPLAY_REGKEY_CURRENT_HWPROFILE 4 + +// EventCategory for IoRegisterPlugPlayNotification +typedef enum _IO_NOTIFICATION_EVENT_CATEGORY { + EventCategoryReserved, + EventCategoryHardwareProfileChange, + EventCategoryDeviceInterfaceChange, + EventCategoryTargetDeviceChange +} IO_NOTIFICATION_EVENT_CATEGORY; + +// CallbackRoutine for IoRegisterPlugPlayNotification +typedef NTSTATUS STDCALL +(*PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)( + IN PVOID NotificationStructure, + IN PVOID Context); + +// Callback for IoReportTargetDeviceChangeAsynchronous +typedef VOID STDCALL +(*PDEVICE_CHANGE_COMPLETE_CALLBACK)( + IN PVOID Context); + +// PNP/POWER values for IRP_MJ_PNP/IRP_MJ_POWER +typedef enum _DEVICE_RELATION_TYPE { + BusRelations, + EjectionRelations, + PowerRelations, + RemovalRelations, + TargetDeviceRelation +} DEVICE_RELATION_TYPE, *PDEVICE_RELATION_TYPE; + +typedef struct _DEVICE_RELATIONS { + ULONG Count; + struct _DEVICE_OBJECT *Objects[1]; +} DEVICE_RELATIONS, *PDEVICE_RELATIONS; + +typedef enum _DEVICE_USAGE_NOTIFICATION_TYPE { + DeviceUsageTypeUndefined, + DeviceUsageTypePaging, + DeviceUsageTypeHibernation, + DeviceUsageTypeDumpFile +} DEVICE_USAGE_NOTIFICATION_TYPE; + + +typedef struct _IO_REMOVE_LOCK_COMMON_BLOCK { + BOOLEAN Removed; + BOOLEAN Reserved[3]; + LONG IoCount; + KEVENT RemoveEvent; +} IO_REMOVE_LOCK_COMMON_BLOCK; + +typedef struct _IO_REMOVE_LOCK { + IO_REMOVE_LOCK_COMMON_BLOCK Common; +} IO_REMOVE_LOCK, *PIO_REMOVE_LOCK; + +#endif /* __INCLUDE_DDK_PNPTYPES_H */ diff --git a/include/ddk/pofuncs.h b/include/ddk/pofuncs.h new file mode 100644 index 0000000..16ae415 --- /dev/null +++ b/include/ddk/pofuncs.h @@ -0,0 +1,61 @@ +#ifndef __INCLUDE_DDK_POFUNCS_H +#define __INCLUDE_DDK_POFUNCS_H + +NTSTATUS +STDCALL +PoCallDriver( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp); + +PULONG +STDCALL +PoRegisterDeviceForIdleDetection( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG ConservationIdleTime, + IN ULONG PerformanceIdleTime, + IN DEVICE_POWER_STATE State); + +PVOID +STDCALL +PoRegisterSystemState( + IN PVOID StateHandle, + IN EXECUTION_STATE Flags); + +NTSTATUS +STDCALL +PoRequestPowerIrp( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PREQUEST_POWER_COMPLETE CompletionFunction, + IN PVOID Context, + OUT PIRP *Irp OPTIONAL); + +VOID +STDCALL +PoSetDeviceBusy( + PULONG IdlePointer); + +POWER_STATE +STDCALL +PoSetPowerState( + IN PDEVICE_OBJECT DeviceObject, + IN POWER_STATE_TYPE Type, + IN POWER_STATE State); + +VOID +STDCALL +PoSetSystemState( + IN EXECUTION_STATE Flags); + +VOID +STDCALL +PoStartNextPowerIrp( + IN PIRP Irp); + +VOID +STDCALL +PoUnregisterSystemState( + IN PVOID StateHandle); + +#endif /* __INCLUDE_DDK_POFUNCS_H */ diff --git a/include/ddk/potypes.h b/include/ddk/potypes.h new file mode 100644 index 0000000..ee720e7 --- /dev/null +++ b/include/ddk/potypes.h @@ -0,0 +1,101 @@ +#ifndef __INCLUDE_DDK_POTYPES_H +#define __INCLUDE_DDK_POTYPES_H + +struct _DEVICE_OBJECT; +struct _IO_STATUS_BLOCK; + +// Flags for PoSetSystemState +typedef ULONG EXECUTION_STATE; + +#define ES_SYSTEM_REQUIRED ((EXECUTION_STATE)0x00000001) +#define ES_DISPLAY_REQUIRED ((EXECUTION_STATE)0x00000002) +#define ES_USER_PRESENT ((EXECUTION_STATE)0x00000004) +#define ES_CONTINUOUS ((EXECUTION_STATE)0x80000000) + +// PowerState for PoRequestPowerIrp +typedef enum _SYSTEM_POWER_STATE { + PowerSystemUnspecified = 0, + PowerSystemWorking, + PowerSystemSleeping1, + PowerSystemSleeping2, + PowerSystemSleeping3, + PowerSystemHibernate, + PowerSystemShutdown, + PowerSystemMaximum +} SYSTEM_POWER_STATE, *PSYSTEM_POWER_STATE; + +// Values for IRP_MN_QUERY_POWER/IRP_MN_SET_POWER +typedef enum { + PowerActionNone = 0, + PowerActionReserved, + PowerActionSleep, + PowerActionHibernate, + PowerActionShutdown, + PowerActionShutdownReset, + PowerActionShutdownOff, + PowerActionWarmEject +} POWER_ACTION, *PPOWER_ACTION; + +// State for PoRegisterDeviceForIdleDetection +typedef enum _DEVICE_POWER_STATE { + PowerDeviceUnspecified = 0, + PowerDeviceD0, + PowerDeviceD1, + PowerDeviceD2, + PowerDeviceD3, + PowerDeviceMaximum +} DEVICE_POWER_STATE, *PDEVICE_POWER_STATE; + +// State for PoSetPowerState +typedef union _POWER_STATE { + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; +} POWER_STATE, *PPOWER_STATE; + +// Type for PoSetPowerState +typedef enum _POWER_STATE_TYPE { + SystemPowerState = 0, + DevicePowerState +} POWER_STATE_TYPE, *PPOWER_STATE_TYPE; + +// CompletionFunction for PoRequestPowerIrp +typedef VOID STDCALL +(*PREQUEST_POWER_COMPLETE) ( + IN struct _DEVICE_OBJECT *DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN struct _IO_STATUS_BLOCK *IoStatus); + + +typedef struct _POWER_SEQUENCE { + ULONG SequenceD1; + ULONG SequenceD2; + ULONG SequenceD3; +} POWER_SEQUENCE, *PPOWER_SEQUENCE; + +typedef VOID STDCALL (*PINTERFACE_REFERENCE)(PVOID Context); +typedef VOID STDCALL (*PINTERFACE_DEREFERENCE)(PVOID Context); + +typedef struct _INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + PINTERFACE_REFERENCE InterfaceReference; + PINTERFACE_DEREFERENCE InterfaceDereference; +} INTERFACE, *PINTERFACE; + +typedef enum { + BusQueryDeviceID = 0, + BusQueryHardwareIDs = 1, + BusQueryCompatibleIDs = 2, + BusQueryInstanceID = 3, + BusQueryDeviceSerialNumber = 4 +} BUS_QUERY_ID_TYPE, *PBUS_QUERY_ID_TYPE; + +typedef enum { + DeviceTextDescription = 0, + DeviceTextLocationInformation = 1 +} DEVICE_TEXT_TYPE, *PDEVICE_TEXT_TYPE; + +#endif /* __INCLUDE_DDK_POTYPES_H */ diff --git a/include/ddk/psfuncs.h b/include/ddk/psfuncs.h new file mode 100644 index 0000000..780ca7c --- /dev/null +++ b/include/ddk/psfuncs.h @@ -0,0 +1,98 @@ +/* $Id$ + */ +#ifndef _INCLUDE_DDK_PSFUNCS_H +#define _INCLUDE_DDK_PSFUNCS_H + +NTSTATUS STDCALL PsAssignImpersonationToken (struct _ETHREAD* Thread, + HANDLE TokenHandle); + +HANDLE STDCALL PsGetCurrentProcessId(VOID); +HANDLE STDCALL PsGetCurrentThreadId(VOID); + +/* + * FUNCTION: Creates a thread which executes in kernel mode + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the returned thread + * handle + * DesiredAccess = Requested access to the thread + * ObjectAttributes = Object attributes (optional) + * ProcessHandle = Handle of process thread will run in + * NULL to use system process + * ClientId (OUT) = Caller supplied storage for the returned client id + * of the thread (optional) + * StartRoutine = Entry point for the thread + * StartContext = Argument supplied to the thread when it begins + * execution + * RETURNS: Success or failure status + */ +NTSTATUS STDCALL PsCreateSystemThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext); +NTSTATUS STDCALL PsTerminateSystemThread(NTSTATUS ExitStatus); + +NTSTATUS STDCALL PsCreateSystemProcess(PHANDLE ProcessHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes); + +NTSTATUS STDCALL PsCreateWin32Process(struct _EPROCESS* Process); +NTSTATUS STDCALL PsCreateWin32Thread(struct _ETHREAD* Thread); + +VOID STDCALL PsEstablishWin32Callouts(PVOID Param1, + PVOID Param2, + PVOID Param3, + PVOID Param4, + ULONG W32ThreadSize, + ULONG W32ProcessSize); + +struct _ETHREAD* STDCALL PsGetCurrentThread(VOID); +struct _EPROCESS* STDCALL PsGetCurrentProcess(VOID); +PACCESS_TOKEN STDCALL PsReferenceImpersonationToken(struct _ETHREAD* Thread, + PULONG Unknown1, + PULONG Unknown2, + SECURITY_IMPERSONATION_LEVEL* + Level); +PACCESS_TOKEN STDCALL PsReferencePrimaryToken(struct _EPROCESS* Process); +NTSTATUS STDCALL PsAssignImpersonationToken(struct _ETHREAD* Thread, + HANDLE TokenHandle); + +VOID STDCALL PsImpersonateClient(struct _ETHREAD* Thread, + PACCESS_TOKEN Token, + UCHAR b, + UCHAR c, + SECURITY_IMPERSONATION_LEVEL Level); +VOID STDCALL PsRevertToSelf(VOID); + +BOOLEAN STDCALL PsGetVersion (PULONG MajorVersion OPTIONAL, + PULONG MinorVersion OPTIONAL, + PULONG BuildNumber OPTIONAL, + PUNICODE_STRING CSDVersion OPTIONAL); + +LARGE_INTEGER STDCALL PsGetProcessExitTime(VOID); +BOOLEAN STDCALL PsIsThreadTerminating(struct _ETHREAD* Thread); + +NTSTATUS STDCALL PsLookupProcessByProcessId(IN PVOID ProcessId, + OUT PEPROCESS *Process); + +NTSTATUS STDCALL PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, + OUT PEPROCESS *Process OPTIONAL, + OUT struct _ETHREAD **Thread); +// OUT PETHREAD *Thread); + +NTSTATUS STDCALL PsLookupThreadByThreadId(IN PVOID ThreadId, + OUT struct _ETHREAD **Thread); +// OUT PETHREAD *Thread); + +NTSTATUS STDCALL +PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, + IN BOOLEAN Remove); + +NTSTATUS STDCALL +PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine); + +#endif + +/* EOF */ diff --git a/include/ddk/pstypes.h b/include/ddk/pstypes.h new file mode 100644 index 0000000..9aae408 --- /dev/null +++ b/include/ddk/pstypes.h @@ -0,0 +1,57 @@ +#ifndef __INCLUDE_DDK_PSTYPES_H +#define __INCLUDE_DDK_PSTYPES_H + +#include + +#include +#include + +#ifndef TLS_MINIMUM_AVAILABLE +#define TLS_MINIMUM_AVAILABLE (64) +#endif +#ifndef MAX_PATH +#define MAX_PATH (260) +#endif + +struct _EPROCESS; +struct _KPROCESS; +struct _ETHREAD; +struct _KTHREAD; + +typedef NTSTATUS STDCALL (*PKSTART_ROUTINE)(PVOID StartContext); + +typedef VOID STDCALL (*PCREATE_PROCESS_NOTIFY_ROUTINE)(HANDLE ParentId, + HANDLE ProcessId, + BOOLEAN Create); + +typedef VOID STDCALL (*PCREATE_THREAD_NOTIFY_ROUTINE)(HANDLE ProcessId, + HANDLE ThreadId, + BOOLEAN Create); + +typedef struct _STACK_INFORMATION +{ + PVOID BaseAddress; + PVOID UpperAddress; +} STACK_INFORMATION, *PSTACK_INFORMATION; + +typedef ULONG THREADINFOCLASS; + +struct _KPROCESS; + +#define LOW_PRIORITY (0) +#define LOW_REALTIME_PRIORITY (16) +#define HIGH_PRIORITY (31) +#define MAXIMUM_PRIORITY (32) + + +#ifdef __NTOSKRNL__ +extern struct _EPROCESS* EXPORTED PsInitialSystemProcess; +extern POBJECT_TYPE EXPORTED PsProcessType; +extern POBJECT_TYPE EXPORTED PsThreadType; +#else +extern struct _EPROCESS* IMPORTED PsInitialSystemProcess; +extern POBJECT_TYPE IMPORTED PsProcessType; +extern POBJECT_TYPE IMPORTED PsThreadType; +#endif + +#endif /* __INCLUDE_DDK_PSTYPES_H */ diff --git a/include/ddk/rtl.h b/include/ddk/rtl.h new file mode 100644 index 0000000..178977d --- /dev/null +++ b/include/ddk/rtl.h @@ -0,0 +1,2183 @@ +/* $Id$ + * + */ + +#ifndef __DDK_RTL_H +#define __DDK_RTL_H + +#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) || defined(__NTDLL__) || defined (__NTAPP__) + +#include +#include + +#endif /* __NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ || __NTDLL__ || __NTAPP__ */ + +#include + + + +/* + * PURPOSE: Flags for RtlQueryRegistryValues + */ +#define RTL_QUERY_REGISTRY_SUBKEY (0x00000001) +#define RTL_QUERY_REGISTRY_TOPKEY (0x00000002) +#define RTL_QUERY_REGISTRY_REQUIRED (0x00000004) +#define RTL_QUERY_REGISTRY_NOVALUE (0x00000008) +#define RTL_QUERY_REGISTRY_NOEXPAND (0x00000010) +#define RTL_QUERY_REGISTRY_DIRECT (0x00000020) +#define RTL_QUERY_REGISTRY_DELETE (0x00000040) + + +/* + * PURPOSE: Used with RtlCheckRegistryKey, RtlCreateRegistryKey, + * RtlDeleteRegistryKey + */ +#define RTL_REGISTRY_ABSOLUTE 0 +#define RTL_REGISTRY_SERVICES 1 +#define RTL_REGISTRY_CONTROL 2 +#define RTL_REGISTRY_WINDOWS_NT 3 +#define RTL_REGISTRY_DEVICEMAP 4 +#define RTL_REGISTRY_USER 5 +#define RTL_REGISTRY_ENUM 6 // ReactOS specific: Used internally in kernel only +#define RTL_REGISTRY_MAXIMUM 7 + +#define RTL_REGISTRY_HANDLE 0x40000000 +#define RTL_REGISTRY_OPTIONAL 0x80000000 + + +#define SHORT_SIZE (sizeof(USHORT)) +#define SHORT_MASK (SHORT_SIZE-1) +#define LONG_SIZE (sizeof(ULONG)) +#define LONG_MASK (LONG_SIZE-1) +#define LOWBYTE_MASK 0x00FF + +#define FIRSTBYTE(Value) ((Value) & LOWBYTE_MASK) +#define SECONDBYTE(Value) (((Value) >> 8) & LOWBYTE_MASK) +#define THIRDBYTE(Value) (((Value) >> 16) & LOWBYTE_MASK) +#define FOURTHBYTE(Value) (((Value) >> 24) & LOWBYTE_MASK) + +/* FIXME: reverse byte-order on big-endian machines (e.g. MIPS) */ +#define SHORT_LEAST_SIGNIFICANT_BIT 0 +#define SHORT_MOST_SIGNIFICANT_BIT 1 + +#define LONG_LEAST_SIGNIFICANT_BIT 0 +#define LONG_3RD_MOST_SIGNIFICANT_BIT 1 +#define LONG_2RD_MOST_SIGNIFICANT_BIT 2 +#define LONG_MOST_SIGNIFICANT_BIT 3 + + + +#if defined(__NTOSKRNL__) || defined(__NTDLL__) +#define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag +#define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag +#else +#define NLS_MB_CODE_PAGE_TAG (*NlsMbCodePageTag) +#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag) +#endif /* __NTOSKRNL__ || __NTDLL__ */ + +extern BOOLEAN NLS_MB_CODE_PAGE_TAG; +extern BOOLEAN NLS_MB_OEM_CODE_PAGE_TAG; + + +/* + * NOTE: ReactOS extensions + */ +#define RtlMin(X,Y) (((X) < (Y))? (X) : (Y)) +#define RtlMax(X,Y) (((X) > (Y))? (X) : (Y)) +#define RtlMin3(X,Y,Z) (((X) < (Y)) ? RtlMin(X,Z) : RtlMin(Y,Z)) +#define RtlMax3(X,Y,Z) (((X) > (Y)) ? RtlMax(X,Z) : RtlMax(Y,Z)) + + +/* + * VOID + * InitializeObjectAttributes ( + * POBJECT_ATTRIBUTES InitializedAttributes, + * PUNICODE_STRING ObjectName, + * ULONG Attributes, + * HANDLE RootDirectory, + * PSECURITY_DESCRIPTOR SecurityDescriptor + * ); + * + * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a + * subsequent call to ZwCreateXXX or ZwOpenXXX + * ARGUMENTS: + * InitializedAttributes (OUT) = Caller supplied storage for the + * object attributes + * ObjectName = Full path name for object + * Attributes = Attributes for the object + * RootDirectory = Where the object should be placed or NULL + * SecurityDescriptor = Ignored + */ +#define InitializeObjectAttributes(p,n,a,r,s) \ +{ \ + (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ + (p)->ObjectName = n; \ + (p)->Attributes = a; \ + (p)->RootDirectory = r; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ +} + + +/* + * VOID + * InitializeListHead ( + * PLIST_ENTRY ListHead + * ); + * + * FUNCTION: Initializes a double linked list + * ARGUMENTS: + * ListHead = Caller supplied storage for the head of the list + */ +#define InitializeListHead(ListHead) \ +{ \ + (ListHead)->Flink = (ListHead); \ + (ListHead)->Blink = (ListHead); \ +} + + +/* + * VOID + * InsertHeadList ( + * PLIST_ENTRY ListHead, + * PLIST_ENTRY Entry + * ); + * + * FUNCTION: Inserts an entry in a double linked list + * ARGUMENTS: + * ListHead = Head of the list + * Entry = Entry to insert + */ +#define InsertHeadList(ListHead, ListEntry) \ +{ \ + PLIST_ENTRY OldFlink; \ + OldFlink = (ListHead)->Flink; \ + (ListEntry)->Flink = OldFlink; \ + (ListEntry)->Blink = (ListHead); \ + OldFlink->Blink = (ListEntry); \ + (ListHead)->Flink = (ListEntry); \ + assert((ListEntry) != NULL); \ + assert((ListEntry)->Blink!=NULL); \ + assert((ListEntry)->Blink->Flink == (ListEntry)); \ + assert((ListEntry)->Flink != NULL); \ + assert((ListEntry)->Flink->Blink == (ListEntry)); \ +} + + +/* + * VOID + * InsertTailList ( + * PLIST_ENTRY ListHead, + * PLIST_ENTRY Entry + * ); + * + * FUNCTION: + * Inserts an entry in a double linked list + * + * ARGUMENTS: + * ListHead = Head of the list + * Entry = Entry to insert + */ +#define InsertTailList(ListHead, ListEntry) \ +{ \ + PLIST_ENTRY OldBlink; \ + OldBlink = (ListHead)->Blink; \ + (ListEntry)->Flink = (ListHead); \ + (ListEntry)->Blink = OldBlink; \ + OldBlink->Flink = (ListEntry); \ + (ListHead)->Blink = (ListEntry); \ + assert((ListEntry) != NULL); \ + assert((ListEntry)->Blink != NULL); \ + assert((ListEntry)->Blink->Flink == (ListEntry)); \ + assert((ListEntry)->Flink != NULL); \ + assert((ListEntry)->Flink->Blink == (ListEntry)); \ +} + +/* + * BOOLEAN + * IsListEmpty ( + * PLIST_ENTRY ListHead + * ); + * + * FUNCTION: + * Checks if a double linked list is empty + * + * ARGUMENTS: + * ListHead = Head of the list +*/ +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + + +/* + * PSINGLE_LIST_ENTRY + * PopEntryList ( + * PSINGLE_LIST_ENTRY ListHead + * ); + * + * FUNCTION: + * Removes an entry from the head of a single linked list + * + * ARGUMENTS: + * ListHead = Head of the list + * + * RETURNS: + * The removed entry + */ +/* +#define PopEntryList(ListHead) \ + (ListHead)->Next; \ + { \ + PSINGLE_LIST_ENTRY FirstEntry; \ + FirstEntry = (ListHead)->Next; \ + if (FirstEntry != NULL) \ + { \ + (ListHead)->Next = FirstEntry->Next; \ + } \ + } +*/ +static +inline +PSINGLE_LIST_ENTRY + PopEntryList( + PSINGLE_LIST_ENTRY ListHead + ) +{ + PSINGLE_LIST_ENTRY ListEntry; + + ListEntry = ListHead->Next; + if (ListEntry!=NULL) + { + ListHead->Next = ListEntry->Next; + } + return ListEntry; +} + +/* +VOID +PushEntryList ( + PSINGLE_LIST_ENTRY ListHead, + PSINGLE_LIST_ENTRY Entry + ); +*/ +/* +#define PushEntryList(ListHead,Entry) \ + (Entry)->Next = (ListHead)->Next; \ + (ListHead)->Next = (Entry) +*/ +static +inline +VOID +PushEntryList ( + PSINGLE_LIST_ENTRY ListHead, + PSINGLE_LIST_ENTRY Entry + ) +{ + Entry->Next = ListHead->Next; + ListHead->Next = Entry; +} + + +/* + * An ReactOS extension + */ +static +inline +PSINGLE_LIST_ENTRY + PopEntrySList( + PSLIST_HEADER ListHead + ) +{ + PSINGLE_LIST_ENTRY ListEntry; + + ListEntry = ListHead->s.Next.Next; + if (ListEntry!=NULL) + { + ListHead->s.Next.Next = ListEntry->Next; + ListHead->s.Depth++; + ListHead->s.Sequence++; + } + return ListEntry; +} + + +/* + * An ReactOS extension + */ +static +inline +VOID +PushEntrySList ( + PSLIST_HEADER ListHead, + PSINGLE_LIST_ENTRY Entry + ) +{ + Entry->Next = ListHead->s.Next.Next; + ListHead->s.Next.Next = Entry; + ListHead->s.Depth++; + ListHead->s.Sequence++; +} + + +/* + *VOID + *RemoveEntryList ( + * PLIST_ENTRY Entry + * ); + * + * FUNCTION: + * Removes an entry from a double linked list + * + * ARGUMENTS: + * ListEntry = Entry to remove + */ +#define RemoveEntryList(ListEntry) \ +{ \ + PLIST_ENTRY OldFlink; \ + PLIST_ENTRY OldBlink; \ + assert((ListEntry) != NULL); \ + assert((ListEntry)->Blink!=NULL); \ + assert((ListEntry)->Blink->Flink == (ListEntry)); \ + assert((ListEntry)->Flink != NULL); \ + assert((ListEntry)->Flink->Blink == (ListEntry)); \ + OldFlink = (ListEntry)->Flink; \ + OldBlink = (ListEntry)->Blink; \ + OldFlink->Blink = OldBlink; \ + OldBlink->Flink = OldFlink; \ + (ListEntry)->Flink = NULL; \ + (ListEntry)->Blink = NULL; \ +} + + +/* + * PLIST_ENTRY + * RemoveHeadList ( + * PLIST_ENTRY ListHead + * ); + * + * FUNCTION: + * Removes the head entry from a double linked list + * + * ARGUMENTS: + * ListHead = Head of the list + * + * RETURNS: + * The removed entry + */ +/* +#define RemoveHeadList(ListHead) \ + (ListHead)->Flink; \ + {RemoveEntryList((ListHead)->Flink)} +*/ +/* +PLIST_ENTRY +RemoveHeadList ( + PLIST_ENTRY ListHead + ); +*/ + +static +inline +PLIST_ENTRY +RemoveHeadList ( + PLIST_ENTRY ListHead + ) +{ + PLIST_ENTRY Old; + PLIST_ENTRY OldFlink; + PLIST_ENTRY OldBlink; + + Old = ListHead->Flink; + + OldFlink = ListHead->Flink->Flink; + OldBlink = ListHead->Flink->Blink; + OldFlink->Blink = OldBlink; + OldBlink->Flink = OldFlink; + if (Old != ListHead) + { + Old->Flink = NULL; + Old->Blink = NULL; + } + + return(Old); +} + + +/* + * PLIST_ENTRY + * RemoveTailList ( + * PLIST_ENTRY ListHead + * ); + * + * FUNCTION: + * Removes the tail entry from a double linked list + * + * ARGUMENTS: + * ListHead = Head of the list + * + * RETURNS: + * The removed entry + */ +/* +#define RemoveTailList(ListHead) \ + (ListHead)->Blink; \ + {RemoveEntryList((ListHead)->Blink)} +*/ +/* +PLIST_ENTRY +RemoveTailList ( + PLIST_ENTRY ListHead + ); +*/ + +static +inline +PLIST_ENTRY +RemoveTailList ( + PLIST_ENTRY ListHead + ) +{ + PLIST_ENTRY Old; + PLIST_ENTRY OldFlink; + PLIST_ENTRY OldBlink; + + Old = ListHead->Blink; + + OldFlink = ListHead->Blink->Flink; + OldBlink = ListHead->Blink->Blink; + OldFlink->Blink = OldBlink; + OldBlink->Flink = OldFlink; + if (Old != ListHead) + { + Old->Flink = NULL; + Old->Blink = NULL; + } + + return(Old); +} + + +NTSTATUS +STDCALL +RtlAddAtomToAtomTable ( + IN PRTL_ATOM_TABLE AtomTable, + IN PWSTR AtomName, + OUT PRTL_ATOM Atom + ); + +PVOID STDCALL +RtlAllocateHeap ( + HANDLE Heap, + ULONG Flags, + ULONG Size + ); + +WCHAR +STDCALL +RtlAnsiCharToUnicodeChar ( + CHAR AnsiChar + ); + +ULONG +STDCALL +RtlAnsiStringToUnicodeSize ( + PANSI_STRING AnsiString + ); + +NTSTATUS +STDCALL +RtlAnsiStringToUnicodeString ( + PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlAppendAsciizToString( + PSTRING Destination, + PCSZ Source + ); + +NTSTATUS +STDCALL +RtlAppendStringToString ( + PSTRING Destination, + PSTRING Source + ); + +NTSTATUS +STDCALL +RtlAppendUnicodeStringToString ( + PUNICODE_STRING Destination, + PUNICODE_STRING Source + ); + +NTSTATUS +STDCALL +RtlAppendUnicodeToString ( + PUNICODE_STRING Destination, + PWSTR Source + ); + +BOOLEAN +STDCALL +RtlAreBitsClear ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ); + +BOOLEAN +STDCALL +RtlAreBitsSet ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ); + +VOID +STDCALL +RtlAssert ( + PVOID FailedAssertion, + PVOID FileName, + ULONG LineNumber, + PCHAR Message + ); + +NTSTATUS +STDCALL +RtlCharToInteger ( + PCSZ String, + ULONG Base, + PULONG Value + ); + +NTSTATUS +STDCALL +RtlCheckRegistryKey ( + ULONG RelativeTo, + PWSTR Path + ); + +VOID +STDCALL +RtlClearAllBits ( + IN PRTL_BITMAP BitMapHeader + ); + +VOID +STDCALL +RtlClearBits ( + IN PRTL_BITMAP BitMapHeader, + IN ULONG StartingIndex, + IN ULONG NumberToClear + ); + +DWORD +STDCALL +RtlCompactHeap ( + HANDLE hheap, + DWORD flags + ); + +ULONG +STDCALL +RtlCompareMemory ( + PVOID Source1, + PVOID Source2, + ULONG Length + ); + +LONG +STDCALL +RtlCompareString ( + PSTRING String1, + PSTRING String2, + BOOLEAN CaseInsensitive + ); + +LONG +STDCALL +RtlCompareUnicodeString ( + PUNICODE_STRING String1, + PUNICODE_STRING String2, + BOOLEAN BaseInsensitive + ); + +NTSTATUS STDCALL +RtlCompressBuffer(IN USHORT CompressionFormatAndEngine, + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG UncompressedChunkSize, + OUT PULONG FinalCompressedSize, + IN PVOID WorkSpace); + +NTSTATUS STDCALL +RtlCompressChunks(IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PVOID WorkSpace); + +LARGE_INTEGER STDCALL +RtlConvertLongToLargeInteger(IN LONG SignedInteger); + +NTSTATUS STDCALL +RtlConvertSidToUnicodeString(IN OUT PUNICODE_STRING String, + IN PSID Sid, + IN BOOLEAN AllocateString); + +LARGE_INTEGER STDCALL +RtlConvertUlongToLargeInteger(IN ULONG UnsignedInteger); + +#if 0 +VOID +RtlCopyBytes ( + PVOID Destination, + CONST VOID * Source, + ULONG Length + ); + +VOID +RtlCopyMemory ( + VOID * Destination, + CONST VOID * Source, + ULONG Length + ); +#endif + +#define RtlCopyMemory(Destination,Source,Length) \ + memcpy((Destination),(Source),(Length)) + +#define RtlCopyBytes RtlCopyMemory + +VOID STDCALL +RtlCopyLuid(IN PLUID LuidDest, + IN PLUID LuidSrc); + +VOID STDCALL +RtlCopyLuidAndAttributesArray(ULONG Count, + PLUID_AND_ATTRIBUTES Src, + PLUID_AND_ATTRIBUTES Dest); + +NTSTATUS STDCALL +RtlCopySid(ULONG BufferLength, + PSID Dest, + PSID Src); + +NTSTATUS STDCALL +RtlCopySidAndAttributesArray(ULONG Count, + PSID_AND_ATTRIBUTES Src, + ULONG SidAreaSize, + PSID_AND_ATTRIBUTES Dest, + PVOID SidArea, + PVOID* RemainingSidArea, + PULONG RemainingSidAreaSize); + +VOID STDCALL +RtlCopyString(PSTRING DestinationString, + PSTRING SourceString); + +VOID STDCALL +RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); + +NTSTATUS STDCALL +RtlCreateAtomTable(IN ULONG TableSize, + IN OUT PRTL_ATOM_TABLE *AtomTable); + +HANDLE +STDCALL +RtlCreateHeap ( + ULONG Flags, + PVOID BaseAddress, + ULONG SizeToReserve, + ULONG SizeToCommit, + PVOID Unknown, + PRTL_HEAP_DEFINITION Definition + ); + +NTSTATUS +STDCALL +RtlCreateRegistryKey ( + ULONG RelativeTo, + PWSTR Path + ); + +NTSTATUS +STDCALL +RtlCreateSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + ULONG Revision + ); + +BOOLEAN +STDCALL +RtlCreateUnicodeString ( + OUT PUNICODE_STRING Destination, + IN PWSTR Source + ); + +BOOLEAN STDCALL +RtlCreateUnicodeStringFromAsciiz (OUT PUNICODE_STRING Destination, + IN PCSZ Source); + +NTSTATUS +STDCALL +RtlCustomCPToUnicodeN ( + PRTL_NLS_DATA NlsData, + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR CustomString, + ULONG CustomSize + ); + +NTSTATUS STDCALL +RtlDecompressBuffer(IN USHORT CompressionFormat, + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + OUT PULONG FinalUncompressedSize); + +NTSTATUS STDCALL +RtlDecompressChunks(OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN PUCHAR CompressedTail, + IN ULONG CompressedTailSize, + IN PCOMPRESSED_DATA_INFO CompressedDataInfo); + +NTSTATUS STDCALL +RtlDecompressFragment(IN USHORT CompressionFormat, + OUT PUCHAR UncompressedFragment, + IN ULONG UncompressedFragmentSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG FragmentOffset, + OUT PULONG FinalUncompressedSize, + IN PVOID WorkSpace); + +NTSTATUS STDCALL +RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom); + +NTSTATUS STDCALL +RtlDeleteRegistryValue(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ValueName); + +NTSTATUS STDCALL +RtlDescribeChunk(IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + OUT PULONG ChunkSize); + +NTSTATUS STDCALL +RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable); + +BOOL STDCALL +RtlDestroyHeap(HANDLE hheap); + +NTSTATUS +STDCALL +RtlDowncaseUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlEmptyAtomTable ( + IN PRTL_ATOM_TABLE AtomTable, + IN BOOLEAN DeletePinned + ); + +LARGE_INTEGER +STDCALL +RtlEnlargedIntegerMultiply ( + LONG Multiplicand, + LONG Multiplier + ); + +ULONG +STDCALL +RtlEnlargedUnsignedDivide ( + ULARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ); + +LARGE_INTEGER +STDCALL +RtlEnlargedUnsignedMultiply ( + ULONG Multiplicand, + ULONG Multiplier + ); + +BOOLEAN STDCALL +RtlEqualLuid(IN PLUID Luid1, + IN PLUID Luid2); + +BOOLEAN +STDCALL +RtlEqualString ( + PSTRING String1, + PSTRING String2, + BOOLEAN CaseInSensitive + ); + +BOOLEAN +STDCALL +RtlEqualUnicodeString ( + PUNICODE_STRING String1, + PUNICODE_STRING String2, + BOOLEAN CaseInSensitive + ); + +LARGE_INTEGER +STDCALL +RtlExtendedIntegerMultiply ( + LARGE_INTEGER Multiplicand, + LONG Multiplier + ); + +LARGE_INTEGER +STDCALL +RtlExtendedLargeIntegerDivide ( + LARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ); + +LARGE_INTEGER +STDCALL +RtlExtendedMagicDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER MagicDivisor, + CCHAR ShiftCount + ); + +VOID +STDCALL +RtlFillMemory ( + PVOID Destination, + ULONG Length, + UCHAR Fill + ); + +VOID +STDCALL +RtlFillMemoryUlong ( + PVOID Destination, + ULONG Length, + ULONG Fill + ); + +ULONG +STDCALL +RtlFindClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +STDCALL +RtlFindClearBitsAndSet ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +STDCALL +RtlFindFirstRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +STDCALL +RtlFindFirstRunSet ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +STDCALL +RtlFindLongestRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +ULONG +STDCALL +RtlFindLongestRunSet ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ); + +NTSTATUS +STDCALL +RtlFindMessage ( + IN PVOID BaseAddress, + IN ULONG Type, + IN ULONG Language, + IN ULONG MessageId, + OUT PRTL_MESSAGE_RESOURCE_ENTRY *MessageResourceEntry + ); + +ULONG +STDCALL +RtlFindSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +ULONG +STDCALL +RtlFindSetBitsAndClear ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ); + +NTSTATUS +STDCALL +RtlFormatCurrentUserKeyPath ( + IN OUT PUNICODE_STRING KeyPath + ); + +VOID +STDCALL +RtlFreeAnsiString ( + PANSI_STRING AnsiString + ); + +BOOLEAN +STDCALL +RtlFreeHeap ( + HANDLE Heap, + ULONG Flags, + PVOID Address + ); + +VOID +STDCALL +RtlFreeOemString ( + POEM_STRING OemString + ); + +VOID +STDCALL +RtlFreeUnicodeString ( + PUNICODE_STRING UnicodeString + ); + +VOID STDCALL +RtlGenerate8dot3Name(IN PUNICODE_STRING Name, + IN BOOLEAN AllowExtendedCharacters, + IN OUT PGENERATE_NAME_CONTEXT Context, + OUT PUNICODE_STRING Name8dot3); + +VOID +RtlGetCallersAddress ( + PVOID * CallersAddress + ); + +NTSTATUS STDCALL +RtlGetCompressionWorkSpaceSize(IN USHORT CompressionFormatAndEngine, + OUT PULONG CompressBufferAndWorkSpaceSize, + OUT PULONG CompressFragmentWorkSpaceSize); + +VOID +STDCALL +RtlGetDefaultCodePage ( + PUSHORT AnsiCodePage, + PUSHORT OemCodePage + ); + +#define RtlGetProcessHeap() (NtCurrentPeb()->ProcessHeap) + +PVOID +STDCALL +RtlImageDirectoryEntryToData ( + PVOID BaseAddress, + BOOLEAN bFlag, + ULONG Directory, + PULONG Size + ); + +PIMAGE_NT_HEADERS +STDCALL +RtlImageNtHeader ( + PVOID BaseAddress + ); + +PIMAGE_SECTION_HEADER +STDCALL +RtlImageRvaToSection ( + PIMAGE_NT_HEADERS NtHeader, + PVOID BaseAddress, + ULONG Rva + ); + +ULONG +STDCALL +RtlImageRvaToVa ( + PIMAGE_NT_HEADERS NtHeader, + PVOID BaseAddress, + ULONG Rva, + PIMAGE_SECTION_HEADER *SectionHeader + ); + +VOID +STDCALL +RtlInitAnsiString ( + PANSI_STRING DestinationString, + PCSZ SourceString + ); + +VOID +STDCALL +RtlInitString ( + PSTRING DestinationString, + PCSZ SourceString + ); + +VOID +STDCALL +RtlInitUnicodeString ( + PUNICODE_STRING DestinationString, + PCWSTR SourceString + ); + +/* +VOID +InitializeUnicodeString ( + PUNICODE_STRING DestinationString, + USHORT Lenght, + USHORT MaximumLength, + PCWSTR Buffer + ); + + Initialize an UNICODE_STRING from its fields. Use when you know the values of + all the fields in advance + + */ + +#define InitializeUnicodeString(__PDEST_STRING__,__LENGTH__,__MAXLENGTH__,__BUFFER__) \ +{ \ + (__PDEST_STRING__)->Length = (__LENGTH__); \ + (__PDEST_STRING__)->MaximumLength = (__MAXLENGTH__); \ + (__PDEST_STRING__)->Buffer = (__BUFFER__); \ +} + +/* +VOID +RtlInitUnicodeStringFromLiteral ( + PUNICODE_STRING DestinationString, + PCWSTR SourceString + ); + + Initialize an UNICODE_STRING from a wide string literal. WARNING: use only with + string literals and statically initialized arrays, it will calculate the wrong + length otherwise + + */ + +#define RtlInitUnicodeStringFromLiteral(__PDEST_STRING__,__SOURCE_STRING__) \ + InitializeUnicodeString( \ + (__PDEST_STRING__), \ + sizeof(__SOURCE_STRING__) - sizeof(WCHAR), \ + sizeof(__SOURCE_STRING__), \ + (__SOURCE_STRING__) \ + ) + +/* + Static initializer for UNICODE_STRING variables. Usage: + + UNICODE_STRING wstr = UNICODE_STRING_INITIALIZER(L"string"); + +*/ + +#define UNICODE_STRING_INITIALIZER(__SOURCE_STRING__) \ +{ \ + sizeof((__SOURCE_STRING__)) - sizeof(WCHAR), \ + sizeof((__SOURCE_STRING__)), \ + (__SOURCE_STRING__) \ +} + +/* + Initializer for empty UNICODE_STRING variables. Usage: + + UNICODE_STRING wstr = EMPTY_UNICODE_STRING; + +*/ +#define EMPTY_UNICODE_STRING {0, 0, NULL} + +VOID +STDCALL +RtlInitializeBitMap ( + IN OUT PRTL_BITMAP BitMapHeader, + IN PULONG BitMapBuffer, + IN ULONG SizeOfBitMap + ); + +NTSTATUS +STDCALL +RtlInitializeContext ( + IN HANDLE ProcessHandle, + IN PCONTEXT Context, + IN PVOID Parameter, + IN PTHREAD_START_ROUTINE StartAddress, + IN OUT PINITIAL_TEB InitialTeb + ); + +VOID +STDCALL +RtlInitializeGenericTable ( + IN OUT PRTL_GENERIC_TABLE Table, + IN PVOID CompareRoutine, + IN PVOID AllocateRoutine, + IN PVOID FreeRoutine, + IN ULONG UserParameter + ); + +PVOID +STDCALL +RtlInsertElementGenericTable ( + IN OUT PRTL_GENERIC_TABLE Table, + IN PVOID Element, + IN ULONG ElementSize, + IN ULONG Unknown4 + ); + +NTSTATUS +STDCALL +RtlIntegerToChar ( + IN ULONG Value, + IN ULONG Base, + IN ULONG Length, + IN OUT PCHAR String + ); + +NTSTATUS +STDCALL +RtlIntegerToUnicodeString ( + IN ULONG Value, + IN ULONG Base, + IN OUT PUNICODE_STRING String + ); + +BOOLEAN +STDCALL +RtlIsGenericTableEmpty ( + IN PRTL_GENERIC_TABLE Table + ); + +BOOLEAN STDCALL +RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName, + IN PANSI_STRING AnsiName, + OUT PBOOLEAN SpacesFound); + +LARGE_INTEGER +STDCALL +RtlLargeIntegerAdd ( + LARGE_INTEGER Addend1, + LARGE_INTEGER Addend2 + ); + +/* + * VOID + * RtlLargeIntegerAnd ( + * PLARGE_INTEGER Result, + * LARGE_INTEGER Source, + * LARGE_INTEGER Mask + * ); + */ +#define RtlLargeIntegerAnd(Result, Source, Mask) \ +{ \ + Result.HighPart = Source.HighPart & Mask.HighPart; \ + Result.LowPart = Source.LowPart & Mask.LowPart; \ +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerArithmeticShift ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + +LARGE_INTEGER +STDCALL +RtlLargeIntegerDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER Divisor, + PLARGE_INTEGER Remainder + ); + +/* + * BOOLEAN + * RtlLargeIntegerEqualTo ( + * LARGE_INTEGER Operand1, + * LARGE_INTEGER Operand2 + * ); + */ +#define RtlLargeIntegerEqualTo(X,Y) \ + (!(((X).LowPart ^ (Y).LowPart) | ((X).HighPart ^ (Y).HighPart))) + +/* + * BOOLEAN + * RtlLargeIntegerEqualToZero ( + * LARGE_INTEGER Operand + * ); + */ +#define RtlLargeIntegerEqualToZero(X) \ + (!((X).LowPart | (X).HighPart)) + +/* + * BOOLEAN + * RtlLargeIntegerGreaterThan ( + * LARGE_INTEGER Operand1, + * LARGE_INTEGER Operand2 + * ); + */ +#define RtlLargeIntegerGreaterThan(X,Y) \ + ((((X).HighPart == (Y).HighPart) && ((X).LowPart > (Y).LowPart)) || \ + ((X).HighPart > (Y).HighPart)) + +/* + * BOOLEAN + * RtlLargeIntegerGreaterThanOrEqualTo ( + * LARGE_INTEGER Operand1, + * LARGE_INTEGER Operand2 + * ); + */ +#define RtlLargeIntegerGreaterThanOrEqualTo(X,Y) \ + ((((X).HighPart == (Y).HighPart) && ((X).LowPart >= (Y).LowPart)) || \ + ((X).HighPart > (Y).HighPart)) + +/* + * BOOLEAN + * RtlLargeIntegerGreaterThanOrEqualToZero ( + * LARGE_INTEGER Operand1 + * ); + */ +#define RtlLargeIntegerGreaterOrEqualToZero(X) \ + ((X).HighPart >= 0) + +/* + * BOOLEAN + * RtlLargeIntegerGreaterThanZero ( + * LARGE_INTEGER Operand1 + * ); + */ +#define RtlLargeIntegerGreaterThanZero(X) \ + ((((X).HighPart == 0) && ((X).LowPart > 0)) || \ + ((X).HighPart > 0 )) + +/* + * BOOLEAN + * RtlLargeIntegerLessThan ( + * LARGE_INTEGER Operand1, + * LARGE_INTEGER Operand2 + * ); + */ +#define RtlLargeIntegerLessThan(X,Y) \ + ((((X).HighPart == (Y).HighPart) && ((X).LowPart < (Y).LowPart)) || \ + ((X).HighPart < (Y).HighPart)) + +/* + * BOOLEAN + * RtlLargeIntegerLessThanOrEqualTo ( + * LARGE_INTEGER Operand1, + * LARGE_INTEGER Operand2 + * ); + */ +#define RtlLargeIntegerLessThanOrEqualTo(X,Y) \ + ((((X).HighPart == (Y).HighPart) && ((X).LowPart <= (Y).LowPart)) || \ + ((X).HighPart < (Y).HighPart)) + +/* + * BOOLEAN + * RtlLargeIntegerLessThanOrEqualToZero ( + * LARGE_INTEGER Operand + * ); + */ +#define RtlLargeIntegerLessOrEqualToZero(X) \ + (((X).HighPart < 0) || !((X).LowPart | (X).HighPart)) + +/* + * BOOLEAN + * RtlLargeIntegerLessThanZero ( + * LARGE_INTEGER Operand + * ); + */ +#define RtlLargeIntegerLessThanZero(X) \ + (((X).HighPart < 0)) + +LARGE_INTEGER +STDCALL +RtlLargeIntegerNegate ( + LARGE_INTEGER Subtrahend + ); + +/* + * BOOLEAN + * RtlLargeIntegerNotEqualTo ( + * LARGE_INTEGER Operand1, + * LARGE_INTEGER Operand2 + * ); + */ +#define RtlLargeIntegerNotEqualTo(X,Y) \ + ((((X).LowPart ^ (Y).LowPart) | ((X).HighPart ^ (Y).HighPart))) + +/* + * BOOLEAN + * RtlLargeIntegerNotEqualToZero ( + * LARGE_INTEGER Operand + * ); + */ +#define RtlLargeIntegerNotEqualToZero(X) \ + (((X).LowPart | (X).HighPart)) + +LARGE_INTEGER +STDCALL +RtlLargeIntegerShiftLeft ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + +LARGE_INTEGER +STDCALL +RtlLargeIntegerShiftRight ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ); + +LARGE_INTEGER +STDCALL +RtlLargeIntegerSubtract ( + LARGE_INTEGER Minuend, + LARGE_INTEGER Subtrahend + ); + +ULONG +STDCALL +RtlLengthSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +BOOL +STDCALL +RtlLockHeap ( + HANDLE hheap + ); + +NTSTATUS +STDCALL +RtlLookupAtomInAtomTable ( + IN PRTL_ATOM_TABLE AtomTable, + IN PWSTR AtomName, + OUT PRTL_ATOM Atom + ); + +VOID STDCALL +RtlMoveMemory (PVOID Destination, CONST VOID* Source, ULONG Length); + +NTSTATUS +STDCALL +RtlMultiByteToUnicodeN ( + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR MbString, + ULONG MbSize + ); + +NTSTATUS +STDCALL +RtlMultiByteToUnicodeSize ( + PULONG UnicodeSize, + PCHAR MbString, + ULONG MbSize + ); + +DWORD +STDCALL +RtlNtStatusToDosError ( + NTSTATUS StatusCode + ); + +DWORD +STDCALL +RtlNtStatusToDosErrorNoTeb ( + NTSTATUS StatusCode + ); + +int +STDCALL +RtlNtStatusToPsxErrno ( + NTSTATUS StatusCode + ); + +ULONG +STDCALL +RtlNumberGenericTableElements ( + IN PRTL_GENERIC_TABLE Table + ); + +ULONG +STDCALL +RtlNumberOfClearBits ( + PRTL_BITMAP BitMapHeader + ); + +ULONG +STDCALL +RtlNumberOfSetBits ( + PRTL_BITMAP BitMapHeader + ); + +ULONG +STDCALL +RtlOemStringToUnicodeSize ( + POEM_STRING AnsiString + ); + +NTSTATUS +STDCALL +RtlOemStringToUnicodeString ( + PUNICODE_STRING DestinationString, + POEM_STRING SourceString, + BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlOemToUnicodeN ( + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR OemString, + ULONG OemSize + ); + +NTSTATUS +STDCALL +RtlOpenCurrentUser ( + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE KeyHandle + ); + +NTSTATUS STDCALL +RtlPinAtomInAtomTable ( + IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom + ); + +BOOLEAN +STDCALL +RtlPrefixString ( + PANSI_STRING String1, + PANSI_STRING String2, + BOOLEAN CaseInsensitive + ); + +BOOLEAN +STDCALL +RtlPrefixUnicodeString ( + PUNICODE_STRING String1, + PUNICODE_STRING String2, + BOOLEAN CaseInsensitive + ); + +NTSTATUS +STDCALL +RtlQueryAtomInAtomTable ( + IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom, + IN OUT PULONG RefCount OPTIONAL, + IN OUT PULONG PinCount OPTIONAL, + IN OUT PWSTR AtomName OPTIONAL, + IN OUT PULONG NameLength OPTIONAL + ); + +NTSTATUS +STDCALL +RtlQueryRegistryValues ( + IN ULONG RelativeTo, + IN PWSTR Path, + IN PRTL_QUERY_REGISTRY_TABLE QueryTable, + IN PVOID Context, + IN PVOID Environment + ); + +NTSTATUS +STDCALL +RtlQueryTimeZoneInformation ( + IN OUT PTIME_ZONE_INFORMATION TimeZoneInformation + ); + +VOID +STDCALL +RtlRaiseException ( + IN PEXCEPTION_RECORD ExceptionRecord + ); + +LPVOID +STDCALL +RtlReAllocateHeap ( + HANDLE hheap, + DWORD flags, + LPVOID ptr, + DWORD size + ); + +NTSTATUS STDCALL +RtlReserveChunk(IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + IN ULONG ChunkSize); + +/* + * VOID + * RtlRetrieveUlong ( + * PULONG DestinationAddress, + * PULONG SourceAddress + * ); + */ +#define RtlRetrieveUlong(DestAddress,SrcAddress) \ + if ((ULONG)(SrcAddress) & LONG_MASK) \ + { \ + ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \ + ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \ + ((PUCHAR)(DestAddress))[2]=((PUCHAR)(SrcAddress))[2]; \ + ((PUCHAR)(DestAddress))[3]=((PUCHAR)(SrcAddress))[3]; \ + } \ + else \ + { \ + *((PULONG)(DestAddress))=*((PULONG)(SrcAddress)); \ + } + +/* + * VOID + * RtlRetrieveUshort ( + * PUSHORT DestinationAddress, + * PUSHORT SourceAddress + * ); + */ +#define RtlRetrieveUshort(DestAddress,SrcAddress) \ + if ((ULONG)(SrcAddress) & SHORT_MASK) \ + { \ + ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \ + ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \ + } \ + else \ + { \ + *((PUSHORT)(DestAddress))=*((PUSHORT)(SrcAddress)); \ + } + +VOID +STDCALL +RtlSecondsSince1970ToTime ( + ULONG SecondsSince1970, + PLARGE_INTEGER Time + ); + +VOID +STDCALL +RtlSecondsSince1980ToTime ( + ULONG SecondsSince1980, + PLARGE_INTEGER Time + ); + +VOID +STDCALL +RtlSetAllBits ( + IN PRTL_BITMAP BitMapHeader + ); + +VOID +STDCALL +RtlSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToSet + ); + +NTSTATUS +STDCALL +RtlSetDaclSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN DaclPresent, + PACL Dacl, + BOOLEAN DaclDefaulted + ); + +NTSTATUS +STDCALL +RtlSetTimeZoneInformation ( + IN OUT PTIME_ZONE_INFORMATION TimeZoneInformation + ); + +DWORD +STDCALL +RtlSizeHeap ( + HANDLE hheap, + DWORD flags, + PVOID pmem + ); + +/* + * VOID + * RtlStoreUlong ( + * PULONG Address, + * ULONG Value + * ); + */ +#define RtlStoreUlong(Address,Value) \ + if ((ULONG)(Address) & LONG_MASK) \ + { \ + ((PUCHAR)(Address))[LONG_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \ + ((PUCHAR)(Address))[LONG_3RD_MOST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \ + ((PUCHAR)(Address))[LONG_2ND_MOST_SIGNIFICANT_BIT]=(UCHAR)(THIRDBYTE(Value)); \ + ((PUCHAR)(Address))[LONG_MOST_SIGNIFICANT_BIT]=(UCHAR)(FOURTHBYTE(Value)); \ + } \ + else \ + { \ + *((PULONG)(Address))=(ULONG)(Value); \ + } + +/* + * VOID + * RtlStoreUshort ( + * PUSHORT Address, + * USHORT Value + * ); + */ +#define RtlStoreUshort(Address,Value) \ + if ((ULONG)(Address) & SHORT_MASK) \ + { \ + ((PUCHAR)(Address))[SHORT_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \ + ((PUCHAR)(Address))[SHORT_MOST_SIGNIFICANT_BIT]=(UCHAR)(SECONDBYTE(Value)); \ + } \ + else \ + { \ + *((PUSHORT)(Address))=(USHORT)(Value); \ + } + +BOOLEAN +STDCALL +RtlTimeFieldsToTime ( + PTIME_FIELDS TimeFields, + PLARGE_INTEGER Time + ); + +BOOLEAN +STDCALL +RtlTimeToSecondsSince1970 ( + PLARGE_INTEGER Time, + PULONG SecondsSince1970 + ); + +BOOLEAN +STDCALL +RtlTimeToSecondsSince1980 ( + PLARGE_INTEGER Time, + PULONG SecondsSince1980 + ); + +VOID +STDCALL +RtlTimeToTimeFields ( + PLARGE_INTEGER Time, + PTIME_FIELDS TimeFields + ); + +ULONG +STDCALL +RtlUnicodeStringToAnsiSize ( + IN PUNICODE_STRING UnicodeString + ); + +NTSTATUS +STDCALL +RtlUnicodeStringToAnsiString ( + IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUnicodeStringToInteger ( + IN PUNICODE_STRING String, + IN ULONG Base, + OUT PULONG Value + ); + +ULONG +STDCALL +RtlUnicodeStringToOemSize ( + IN PUNICODE_STRING UnicodeString + ); + +NTSTATUS +STDCALL +RtlUnicodeStringToCountedOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUnicodeStringToOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUnicodeToCustomCPN ( + PRTL_NLS_DATA NlsData, + PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +NTSTATUS +STDCALL +RtlUnicodeToMultiByteN ( + PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +NTSTATUS +STDCALL +RtlUnicodeToMultiByteSize ( + PULONG MbSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +NTSTATUS +STDCALL +RtlUnicodeToOemN ( + PCHAR OemString, + ULONG OemSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +BOOL +STDCALL +RtlUnlockHeap ( + HANDLE hheap + ); + +VOID +STDCALL +RtlUnwind ( + PEXCEPTION_REGISTRATION RegistrationFrame, + PVOID ReturnAddress, + PEXCEPTION_RECORD ExceptionRecord, + DWORD EaxValue + ); + +WCHAR +STDCALL +RtlUpcaseUnicodeChar ( + WCHAR Source + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeStringToAnsiString ( + IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeStringToCountedOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeStringToOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeToCustomCPN ( + PRTL_NLS_DATA NlsData, + PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeToMultiByteN ( + PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +NTSTATUS +STDCALL +RtlUpcaseUnicodeToOemN ( + PCHAR OemString, + ULONG OemSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ); + +CHAR +STDCALL +RtlUpperChar ( + CHAR Source + ); + +VOID +STDCALL +RtlUpperString ( + PSTRING DestinationString, + PSTRING SourceString + ); + +BOOL +STDCALL +RtlValidateHeap ( + HANDLE hheap, + DWORD flags, + PVOID pmem + ); + +BOOLEAN +STDCALL +RtlValidSecurityDescriptor ( + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +BOOLEAN STDCALL +RtlValidSid(IN PSID Sid); + +NTSTATUS +STDCALL +RtlWriteRegistryValue ( + ULONG RelativeTo, + PWSTR Path, + PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength + ); + +VOID STDCALL +RtlZeroMemory (PVOID Destination, ULONG Length); + +ULONG +STDCALL +RtlxAnsiStringToUnicodeSize ( + IN PANSI_STRING AnsiString + ); + +ULONG +STDCALL +RtlxOemStringToUnicodeSize ( + IN POEM_STRING OemString + ); + +ULONG +STDCALL +RtlxUnicodeStringToAnsiSize ( + IN PUNICODE_STRING UnicodeString + ); + +ULONG +STDCALL +RtlxUnicodeStringToOemSize ( + IN PUNICODE_STRING UnicodeString + ); + + +/* Register io functions */ + +UCHAR +STDCALL +READ_REGISTER_UCHAR ( + PUCHAR Register + ); + +USHORT +STDCALL +READ_REGISTER_USHORT ( + PUSHORT Register + ); + +ULONG +STDCALL +READ_REGISTER_ULONG ( + PULONG Register + ); + +VOID +STDCALL +READ_REGISTER_BUFFER_UCHAR ( + PUCHAR Register, + PUCHAR Buffer, + ULONG Count + ); + +VOID +STDCALL +READ_REGISTER_BUFFER_USHORT ( + PUSHORT Register, + PUSHORT Buffer, + ULONG Count + ); + +VOID +STDCALL +READ_REGISTER_BUFFER_ULONG ( + PULONG Register, + PULONG Buffer, + ULONG Count + ); + +VOID +STDCALL +WRITE_REGISTER_UCHAR ( + PUCHAR Register, + UCHAR Value + ); + +VOID +STDCALL +WRITE_REGISTER_USHORT ( + PUSHORT Register, + USHORT Value + ); + +VOID +STDCALL +WRITE_REGISTER_ULONG ( + PULONG Register, + ULONG Value + ); + +VOID +STDCALL +WRITE_REGISTER_BUFFER_UCHAR ( + PUCHAR Register, + PUCHAR Buffer, + ULONG Count + ); + +VOID +STDCALL +WRITE_REGISTER_BUFFER_USHORT ( + PUSHORT Register, + PUSHORT Buffer, + ULONG Count + ); + +VOID +STDCALL +WRITE_REGISTER_BUFFER_ULONG ( + PULONG Register, + PULONG Buffer, + ULONG Count + ); + + +NTSTATUS STDCALL RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision); +NTSTATUS STDCALL RtlQueryInformationAcl (PACL Acl, PVOID Information, ULONG InformationLength, ACL_INFORMATION_CLASS InformationClass); +NTSTATUS STDCALL RtlSetInformationAcl (PACL Acl, PVOID Information, ULONG InformationLength, ACL_INFORMATION_CLASS InformationClass); +BOOLEAN STDCALL RtlValidAcl (PACL Acl); + +NTSTATUS STDCALL RtlAddAccessAllowedAce(PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid); +NTSTATUS STDCALL RtlAddAccessDeniedAce(PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid); +NTSTATUS STDCALL RtlAddAce(PACL Acl, ULONG Revision, ULONG StartingIndex, PACE AceList, ULONG AceListLength); +NTSTATUS STDCALL RtlAddAuditAccessAce (PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid, BOOLEAN Success, BOOLEAN Failure); +NTSTATUS STDCALL RtlDeleteAce(PACL Acl, ULONG AceIndex); +BOOLEAN STDCALL RtlFirstFreeAce(PACL Acl, PACE* Ace); +NTSTATUS STDCALL RtlGetAce(PACL Acl, ULONG AceIndex, PACE *Ace); + +NTSTATUS STDCALL RtlAbsoluteToSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, PSECURITY_DESCRIPTOR RelSD, PULONG BufferLength); +NTSTATUS STDCALL RtlMakeSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, PSECURITY_DESCRIPTOR RelSD, PULONG BufferLength); +NTSTATUS STDCALL RtlCreateSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Revision); +BOOLEAN STDCALL RtlValidSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor); +ULONG STDCALL RtlLengthSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor); +NTSTATUS STDCALL RtlSetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN DaclPresent, PACL Dacl, BOOLEAN DaclDefaulted); +NTSTATUS STDCALL RtlGetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PBOOLEAN DaclPresent, PACL* Dacl, PBOOLEAN DaclDefauted); +NTSTATUS STDCALL RtlSetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Owner, BOOLEAN OwnerDefaulted); +NTSTATUS STDCALL RtlGetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Owner, PBOOLEAN OwnerDefaulted); +NTSTATUS STDCALL RtlSetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Group, BOOLEAN GroupDefaulted); +NTSTATUS STDCALL RtlGetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Group, PBOOLEAN GroupDefaulted); +NTSTATUS STDCALL RtlGetControlSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR_CONTROL Control, PULONG Revision); +NTSTATUS STDCALL RtlSetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN SaclPresent, PACL Sacl, BOOLEAN SaclDefaulted); +NTSTATUS STDCALL RtlGetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PBOOLEAN SaclPresent, PACL* Sacl, PBOOLEAN SaclDefauted); +NTSTATUS STDCALL RtlSelfRelativeToAbsoluteSD (PSECURITY_DESCRIPTOR RelSD, + PSECURITY_DESCRIPTOR AbsSD, + PDWORD AbsSDSize, + PACL Dacl, + PDWORD DaclSize, + PACL Sacl, + PDWORD SaclSize, + PSID Owner, + PDWORD OwnerSize, + PSID Group, + PDWORD GroupSize); + +NTSTATUS STDCALL RtlAllocateAndInitializeSid (PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + UCHAR SubAuthorityCount, + ULONG SubAuthority0, + ULONG SubAuthority1, + ULONG SubAuthority2, + ULONG SubAuthority3, + ULONG SubAuthority4, + ULONG SubAuthority5, + ULONG SubAuthority6, + ULONG SubAuthority7, + PSID *Sid); +ULONG STDCALL RtlLengthRequiredSid (UCHAR SubAuthorityCount); +PSID_IDENTIFIER_AUTHORITY STDCALL RtlIdentifierAuthoritySid (PSID Sid); +NTSTATUS STDCALL RtlInitializeSid (PSID Sid, PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, UCHAR SubAuthorityCount); +PULONG STDCALL RtlSubAuthoritySid (PSID Sid, ULONG SubAuthority); +BOOLEAN STDCALL RtlEqualPrefixSid (PSID Sid1, PSID Sid2); +BOOLEAN STDCALL RtlEqualSid(PSID Sid1, PSID Sid2); +PSID STDCALL RtlFreeSid (PSID Sid); +ULONG STDCALL RtlLengthSid (PSID Sid); +PULONG STDCALL RtlSubAuthoritySid (PSID Sid, ULONG SubAuthority); +PUCHAR STDCALL RtlSubAuthorityCountSid (PSID Sid); +BOOLEAN STDCALL RtlValidSid (PSID Sid); +NTSTATUS STDCALL RtlConvertSidToUnicodeString (PUNICODE_STRING String, PSID Sid, BOOLEAN AllocateBuffer); + +BOOLEAN STDCALL RtlAreAllAccessesGranted (ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess); +BOOLEAN STDCALL RtlAreAnyAccessesGranted (ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess); +VOID STDCALL RtlMapGenericMask (PACCESS_MASK AccessMask, PGENERIC_MAPPING GenericMapping); + + +/* functions exported from NTOSKRNL.EXE which are considered RTL */ + +#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) || defined(__NTDLL__) || defined(__NTAPP__) + +char *_itoa (int value, char *string, int radix); +int _snprintf(char * buf, size_t cnt, const char *fmt, ...); +int _snwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, ...); +int _stricmp(const char *s1, const char *s2); +char * _strlwr(char *x); +int _strnicmp(const char *s1, const char *s2, size_t n); +char * _strnset(char* szToFill, int szFill, size_t sizeMaxFill); +char * _strrev(char *s); +char * _strset(char* szToFill, int szFill); +char * _strupr(char *x); +int _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args); +int _wcsicmp (const wchar_t* cs, const wchar_t* ct); +wchar_t * _wcslwr (wchar_t *x); +int _wcsnicmp (const wchar_t * cs,const wchar_t * ct,size_t count); +wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill); +wchar_t * _wcsrev(wchar_t *s); +wchar_t *_wcsupr(wchar_t *x); + +int atoi(const char *str); +long atol(const char *str); +int isdigit(int c); +int islower(int c); +int isprint(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); +size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count); +int mbtowc (wchar_t *wchar, const char *mbchar, size_t count); +void * memchr(const void *s, int c, size_t n); +void * memcpy(void *to, const void *from, size_t count); +void * memmove(void *dest,const void *src, size_t count); +void * memset(void *src, int val, size_t count); + +#if 0 +qsort +#endif + +int rand(void); +int sprintf(char * buf, const char *fmt, ...); +void srand(unsigned seed); +char * strcat(char *s, const char *append); +char * strchr(const char *s, int c); +int strcmp(const char *s1, const char *s2); +char * strcpy(char *to, const char *from); +size_t strlen(const char *str); +char * strncat(char *dst, const char *src, size_t n); +int strncmp(const char *s1, const char *s2, size_t n); +char *strncpy(char *dst, const char *src, size_t n); +char *strrchr(const char *s, int c); +size_t strspn(const char *s1, const char *s2); +char *strstr(const char *s, const char *find); +int swprintf(wchar_t *buf, const wchar_t *fmt, ...); +int tolower(int c); +int toupper(int c); +wchar_t towlower(wchar_t c); +wchar_t towupper(wchar_t c); +int vsprintf(char *buf, const char *fmt, va_list args); +wchar_t * wcscat(wchar_t *dest, const wchar_t *src); +wchar_t * wcschr(const wchar_t *str, wchar_t ch); +int wcscmp(const wchar_t *cs, const wchar_t *ct); +wchar_t* wcscpy(wchar_t* str1, const wchar_t* str2); +size_t wcscspn(const wchar_t *str,const wchar_t *reject); +size_t wcslen(const wchar_t *s); +wchar_t * wcsncat(wchar_t *dest, const wchar_t *src, size_t count); +int wcsncmp(const wchar_t *cs, const wchar_t *ct, size_t count); +wchar_t * wcsncpy(wchar_t *dest, const wchar_t *src, size_t count); +wchar_t * wcsrchr(const wchar_t *str, wchar_t ch); +size_t wcsspn(const wchar_t *str,const wchar_t *accept); +wchar_t *wcsstr(const wchar_t *s,const wchar_t *b); +size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count); +int wctomb (char *mbchar, wchar_t wchar); + +#endif /* __NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ || __NTDLL__ || __NTAPP__ */ + +#endif /* __DDK_RTL_H */ diff --git a/include/ddk/rtltypes.h b/include/ddk/rtltypes.h new file mode 100644 index 0000000..ea718ad --- /dev/null +++ b/include/ddk/rtltypes.h @@ -0,0 +1,214 @@ +/* $Id$ + * + */ + +#ifndef __DDK_RTLTYPES_H +#define __DDK_RTLTYPES_H + + +#define COMPRESSION_FORMAT_NONE 0x0000 +#define COMPRESSION_FORMAT_DEFAULT 0x0001 +#define COMPRESSION_FORMAT_LZNT1 0x0002 + +#define COMPRESSION_ENGINE_STANDARD 0x0000 +#define COMPRESSION_ENGINE_MAXIMUM 0x0100 +#define COMPRESSION_ENGINE_HIBER 0x0200 + + +typedef struct _INITIAL_TEB +{ + ULONG StackCommit; + ULONG StackReserve; + PVOID StackBase; + PVOID StackLimit; + PVOID StackAllocate; +} INITIAL_TEB, *PINITIAL_TEB; + +typedef struct _CONTROLLER_OBJECT +{ + CSHORT Type; + CSHORT Size; + PVOID ControllerExtension; + KDEVICE_QUEUE DeviceWaitQueue; + ULONG Spare1; + LARGE_INTEGER Spare2; +} CONTROLLER_OBJECT, *PCONTROLLER_OBJECT; + +typedef struct _STRING +{ + /* + * Length in bytes of the string stored in buffer + */ + USHORT Length; + + /* + * Maximum length of the string + */ + USHORT MaximumLength; + + /* + * String + */ + PCHAR Buffer; +} STRING, *PSTRING; + +typedef STRING ANSI_STRING; +typedef PSTRING PANSI_STRING; + +typedef STRING OEM_STRING; +typedef PSTRING POEM_STRING; + + +typedef struct _TIME_FIELDS +{ + CSHORT Year; + CSHORT Month; + CSHORT Day; + CSHORT Hour; + CSHORT Minute; + CSHORT Second; + CSHORT Milliseconds; + CSHORT Weekday; +} TIME_FIELDS, *PTIME_FIELDS; + +typedef struct _RTL_BITMAP +{ + ULONG SizeOfBitMap; + PULONG Buffer; +} RTL_BITMAP, *PRTL_BITMAP; + +typedef struct _RTL_HEAP_DEFINITION +{ + ULONG Length; + ULONG Unknown[11]; +} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION; + +typedef struct _RTL_ATOM_TABLE +{ + ULONG TableSize; + ULONG NumberOfAtoms; + PVOID Lock; /* fast mutex (kernel mode)/ critical section (user mode) */ + PVOID HandleTable; + LIST_ENTRY Slot[0]; +} RTL_ATOM_TABLE, *PRTL_ATOM_TABLE; + +typedef struct _LB_RANGE +{ + UCHAR upper; + UCHAR lower; +} LB_RANGE; + +typedef struct _RTL_NLS_DATA +{ + USHORT CodePage; + USHORT MaxCharacterSize; // SBCS = 1, DBCS = 2 + WCHAR DefaultCharacter; + WCHAR char1; + WCHAR char2; + WCHAR char3; + USHORT DbcsFlag; + LB_RANGE LeadByteRange[6]; + USHORT reserved; + PWCHAR MultiByteToUnicode; + PCHAR UnicodeToMultiByte; + PWCHAR DosMultiByteToUnicode; + PCHAR DbcsTags; +} RTL_NLS_DATA, *PRTL_NLS_DATA; + +typedef struct _RTL_NLS_TABLE +{ + RTL_NLS_DATA OemInfo; + RTL_NLS_DATA AnsiInfo; + PWCHAR UpcaseTable; + PWCHAR DowncaseTable; +} RTL_NLS_TABLE, *PRTL_NLS_TABLE; + + +typedef struct _RTL_SPLAY_LINKS +{ + struct _RTL_SPLAY_LINKS *Parent; + struct _RTL_SPLAY_LINKS *LeftChild; + struct _RTL_SPLAY_LINKS *RightChild; +} RTL_SPLAY_LINKS, *PRTL_SPLAY_LINKS; + + +typedef struct _RTL_GENERIC_TABLE +{ + PVOID RootElement; + ULONG Unknown2; + ULONG Unknown3; + ULONG Unknown4; + ULONG Unknown5; + ULONG ElementCount; + PVOID CompareRoutine; + PVOID AllocateRoutine; + PVOID FreeRoutine; + ULONG UserParameter; +} RTL_GENERIC_TABLE, *PRTL_GENERIC_TABLE; + + +typedef struct _RTL_MESSAGE_RESOURCE_ENTRY +{ + USHORT Length; + USHORT Flags; + UCHAR Text[1]; +} RTL_MESSAGE_RESOURCE_ENTRY, *PRTL_MESSAGE_RESOURCE_ENTRY; + +typedef struct _RTL_MESSAGE_RESOURCE_BLOCK +{ + ULONG LowId; + ULONG HighId; + ULONG OffsetToEntries; +} RTL_MESSAGE_RESOURCE_BLOCK, *PRTL_MESSAGE_RESOURCE_BLOCK; + +typedef struct _RTL_MESSAGE_RESOURCE_DATA +{ + ULONG NumberOfBlocks; + RTL_MESSAGE_RESOURCE_BLOCK Blocks[1]; +} RTL_MESSAGE_RESOURCE_DATA, *PRTL_MESSAGE_RESOURCE_DATA; + + +typedef NTSTATUS STDCALL +(*PRTL_QUERY_REGISTRY_ROUTINE)(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext); + +typedef struct _RTL_QUERY_REGISTRY_TABLE +{ + PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; +} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; + + +typedef struct _GENERATE_NAME_CONTEXT +{ + USHORT Checksum; + BOOLEAN CheckSumInserted; + UCHAR NameLength; + WCHAR NameBuffer[8]; + ULONG ExtensionLength; + WCHAR ExtensionBuffer[4]; + ULONG LastIndexValue; +} GENERATE_NAME_CONTEXT, *PGENERATE_NAME_CONTEXT; + + +typedef struct _COMPRESSED_DATA_INFO +{ + USHORT CompressionFormatAndEngine; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved; + USHORT NumberOfChunks; + ULONG CompressedChunkSizes[1]; +} COMPRESSED_DATA_INFO, *PCOMPRESSED_DATA_INFO; + +#endif /* __DDK_RTLTYPES_H */ diff --git a/include/ddk/scsi.h b/include/ddk/scsi.h new file mode 100644 index 0000000..46d8f50 --- /dev/null +++ b/include/ddk/scsi.h @@ -0,0 +1,1306 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/include/scsi.h + * PURPOSE: SCSI class driver definitions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +#ifndef __STORAGE_INCLUDE_SCSI_H +#define __STORAGE_INCLUDE_SCSI_H + + +/* Command Descriptor Block */ + +typedef union _CDB +{ + /* Generic 6-Byte CDB */ + struct _CDB6GENERIC + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR CommandUniqueBits:4; + UCHAR LogicalUnitNumber:3; + UCHAR CommandUniqueBytes[3]; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved:4; + UCHAR VendorUnique:2; + } CDB6GENERIC, *PCDB6GENERIC; + + /* Standard 6-byte CDB */ + struct _CDB6READWRITE + { + UCHAR OperationCode; + UCHAR LogicalBlockMsb1:5; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockMsb0; + UCHAR LogicalBlockLsb; + UCHAR TransferBlocks; + UCHAR Control; + } CDB6READWRITE, *PCDB6READWRITE; + + /* SCSI Inquiry CDB */ + struct _CDB6INQUIRY + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode; + UCHAR IReserved; + UCHAR AllocationLength; + UCHAR Control; + } CDB6INQUIRY, *PCDB6INQUIRY; + + /* SCSI Format CDB */ + struct _CDB6FORMAT + { + UCHAR OperationCode; + UCHAR FormatControl:5; + UCHAR LogicalUnitNumber:3; + UCHAR FReserved1; + UCHAR InterleaveMsb; + UCHAR InterleaveLsb; + UCHAR FReserved2; + } CDB6FORMAT, *PCDB6FORMAT; + + /* Standard 10-byte CDB */ + struct _CDB10 + { + UCHAR OperationCode; + UCHAR RelativeAddress:1; + UCHAR Reserved1:2; + UCHAR ForceUnitAccess:1; + UCHAR DisablePageOut:1; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockByte0; + UCHAR LogicalBlockByte1; + UCHAR LogicalBlockByte2; + UCHAR LogicalBlockByte3; + UCHAR Reserved2; + UCHAR TransferBlocksMsb; + UCHAR TransferBlocksLsb; + UCHAR Control; + } CDB10, *PCDB10; + + /* CD Rom Audio CDBs */ + struct _PAUSE_RESUME + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[6]; + UCHAR Action; + UCHAR Control; + } PAUSE_RESUME, *PPAUSE_RESUME; + + /* Read Table of Contents */ + struct _READ_TOC + { + UCHAR OperationCode; + UCHAR Reserved0:1; + UCHAR Msf:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[4]; + UCHAR StartingTrack; + UCHAR AllocationLength[2]; + UCHAR Control:6; + UCHAR Format:2; + } READ_TOC, *PREAD_TOC; + + struct _PLAY_AUDIO_MSF + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2; + UCHAR StartingM; + UCHAR StartingS; + UCHAR StartingF; + UCHAR EndingM; + UCHAR EndingS; + UCHAR EndingF; + UCHAR Control; + } PLAY_AUDIO_MSF, *PPLAY_AUDIO_MSF; + + /* Read SubChannel Data */ + struct _SUBCHANNEL + { + UCHAR OperationCode; + UCHAR Reserved0:1; + UCHAR Msf:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2:6; + UCHAR SubQ:1; + UCHAR Reserved3:1; + UCHAR Format; + UCHAR Reserved4[2]; + UCHAR TrackNumber; + UCHAR AllocationLength[2]; + UCHAR Control; + } SUBCHANNEL, *PSUBCHANNEL; + + /* Read CD. Used by Atapi for raw sector reads. */ + struct _READ_CD + { + UCHAR OperationCode; + UCHAR Reserved0:2; + UCHAR ExpectedSectorType:3; + UCHAR Reserved1:3; + UCHAR StartingLBA[4]; + UCHAR TransferBlocks[3]; + UCHAR Reserved2:1; + UCHAR ErrorFlags:2; + UCHAR IncludeEDC:1; + UCHAR IncludeUserData:1; + UCHAR HeaderCode:2; + UCHAR IncludeSyncData:1; + UCHAR SubChannelSelection:3; + UCHAR Reserved3:5; + UCHAR Reserved4; + } READ_CD, *PREAD_CD; + + /* Plextor Read CD-DA */ + struct _PLXTR_READ_CDDA + { + UCHAR OperationCode; + UCHAR Reserved0:5; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockByte0; + UCHAR LogicalBlockByte1; + UCHAR LogicalBlockByte2; + UCHAR LogicalBlockByte3; + UCHAR TransferBlockByte0; + UCHAR TransferBlockByte1; + UCHAR TransferBlockByte2; + UCHAR TransferBlockByte3; + UCHAR SubCode; + UCHAR Control; + } PLXTR_READ_CDDA, *PPLXTR_READ_CDDA; + + /* NEC Read CD-DA */ + struct _NEC_READ_CDDA + { + UCHAR OperationCode; + UCHAR Reserved0; + UCHAR LogicalBlockByte0; + UCHAR LogicalBlockByte1; + UCHAR LogicalBlockByte2; + UCHAR LogicalBlockByte3; + UCHAR Reserved1; + UCHAR TransferBlockByte0; + UCHAR TransferBlockByte1; + UCHAR Control; + } NEC_READ_CDDA, *PNEC_READ_CDDA; + + /* Mode sense */ + struct _MODE_SENSE + { + UCHAR OperationCode; + UCHAR Reserved1:3; + UCHAR Dbd:1; + UCHAR Reserved2:1; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode:6; + UCHAR Pc:2; + UCHAR Reserved3; + UCHAR AllocationLength; + UCHAR Control; + } MODE_SENSE, *PMODE_SENSE; + + struct _MODE_SENSE10 + { + UCHAR OperationCode; + UCHAR Reserved1:3; + UCHAR Dbd:1; + UCHAR Reserved2:1; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode:6; + UCHAR Pc:2; + UCHAR Reserved3[4]; + UCHAR AllocationLength[2]; + UCHAR Control; + } MODE_SENSE10, *PMODE_SENSE10; + + /* Mode select */ + struct _MODE_SELECT + { + UCHAR OperationCode; + UCHAR SPBit:1; + UCHAR Reserved1:3; + UCHAR PFBit:1; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[2]; + UCHAR ParameterListLength; + UCHAR Control; + } MODE_SELECT, *PMODE_SELECT; + + struct _MODE_SELECT10 + { + UCHAR OperationCode; + UCHAR SPBit:1; + UCHAR Reserved1:3; + UCHAR PFBit:1; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[5]; + UCHAR ParameterListLength[2]; + UCHAR Control; + } MODE_SELECT10, *PMODE_SELECT10; + + struct _LOCATE + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR CPBit:1; + UCHAR BTBit:1; + UCHAR Reserved1:2; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved3; + UCHAR LogicalBlockAddress[4]; + UCHAR Reserved4; + UCHAR Partition; + UCHAR Control; + } LOCATE, *PLOCATE; + + struct _LOGSENSE + { + UCHAR OperationCode; + UCHAR SPBit:1; + UCHAR PPCBit:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR PageCode:6; + UCHAR PCBit:2; + UCHAR Reserved2; + UCHAR Reserved3; + UCHAR ParameterPointer[2]; /* [0]=MSB, [1]=LSB */ + UCHAR AllocationLength[2]; /* [0]=MSB, [1]=LSB */ + UCHAR Control; + } LOGSENSE, *PLOGSENSE; + + struct _PRINT + { + UCHAR OperationCode; + UCHAR Reserved:5; + UCHAR LogicalUnitNumber:3; + UCHAR TransferLength[3]; + UCHAR Control; + } PRINT, *PPRINT; + + struct _SEEK + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR LogicalBlockAddress[4]; + UCHAR Reserved2[3]; + UCHAR Control; + } SEEK, *PSEEK; + + struct _ERASE + { + UCHAR OperationCode; + UCHAR Long:1; + UCHAR Immediate:1; + UCHAR Reserved1:3; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[3]; + UCHAR Control; + } ERASE, *PERASE; + + struct _START_STOP + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Reserved1:4; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[2]; + UCHAR Start:1; + UCHAR LoadEject:1; + UCHAR Reserved3:6; + UCHAR Control; + } START_STOP, *PSTART_STOP; + + struct _MEDIA_REMOVAL + { + UCHAR OperationCode; + UCHAR Reserved1:5; + UCHAR LogicalUnitNumber:3; + UCHAR Reserved2[2]; + UCHAR Prevent; + UCHAR Control; + } MEDIA_REMOVAL, *PMEDIA_REMOVAL; + + /* Tape CDBs */ + struct _SEEK_BLOCK + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Reserved1:7; + UCHAR BlockAddress[3]; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved2:4; + UCHAR VendorUnique:2; + } SEEK_BLOCK, *PSEEK_BLOCK; + + struct _REQUEST_BLOCK_ADDRESS + { + UCHAR OperationCode; + UCHAR Reserved1[3]; + UCHAR AllocationLength; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved2:4; + UCHAR VendorUnique:2; + } REQUEST_BLOCK_ADDRESS, *PREQUEST_BLOCK_ADDRESS; + + struct _PARTITION + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Sel:1; + UCHAR PartitionSelect:6; + UCHAR Reserved1[3]; + UCHAR Control; + } PARTITION, *PPARTITION; + + struct _WRITE_TAPE_MARKS + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR WriteSetMarks:1; + UCHAR Reserved:3; + UCHAR LogicalUnitNumber:3; + UCHAR TransferLength[3]; + UCHAR Control; + } WRITE_TAPE_MARKS, *PWRITE_TAPE_MARKS; + + struct _SPACE_TAPE_MARKS + { + UCHAR OperationCode; + UCHAR Code:3; + UCHAR Reserved:2; + UCHAR LogicalUnitNumber:3; + UCHAR NumMarksMSB ; + UCHAR NumMarks; + UCHAR NumMarksLSB; + union + { + UCHAR value; + struct + { + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved:4; + UCHAR VendorUnique:2; + } Fields; + } Byte6; + } SPACE_TAPE_MARKS, *PSPACE_TAPE_MARKS; + + /* Read tape position */ + struct _READ_POSITION + { + UCHAR Operation; + UCHAR BlockType:1; + UCHAR Reserved1:4; + UCHAR Lun:3; + UCHAR Reserved2[7]; + UCHAR Control; + } READ_POSITION, *PREAD_POSITION; + + /* ReadWrite for Tape */ + struct _CDB6READWRITETAPE + { + UCHAR OperationCode; + UCHAR VendorSpecific:5; + UCHAR Reserved:3; + UCHAR TransferLenMSB; + UCHAR TransferLen; + UCHAR TransferLenLSB; + UCHAR Link:1; + UCHAR Flag:1; + UCHAR Reserved1:4; + UCHAR VendorUnique:2; + } CDB6READWRITETAPE, *PCDB6READWRITETAPE; + + /* Atapi 2.5 Changer 12-byte CDBs */ + struct _LOAD_UNLOAD + { + UCHAR OperationCode; + UCHAR Immediate:1; + UCHAR Reserved1:7; + UCHAR Reserved2[2]; + UCHAR Start:1; + UCHAR LoadEject:1; + UCHAR Reserved3:6; + UCHAR Reserved4[3]; + UCHAR Slot; + UCHAR Reserved5[3]; + } LOAD_UNLOAD, *PLOAD_UNLOAD; + + struct _MECH_STATUS + { + UCHAR OperationCode; + UCHAR Reserved1[7]; + UCHAR AllocationLength[2]; + UCHAR Reserved2[2]; + } MECH_STATUS, *PMECH_STATUS; +} CDB, *PCDB; + + +/* Command Descriptor Block constants */ + +#define CDB6GENERIC_LENGTH 6 +#define CDB10GENERIC_LENGTH 10 +#define CDB12GENERIC_LENGTH 12 + +#define SETBITON 1 +#define SETBITOFF 0 + + +/* Mode Sense/Select page constants */ + +#define MODE_PAGE_ERROR_RECOVERY 0x01 +#define MODE_PAGE_DISCONNECT 0x02 +#define MODE_PAGE_FORMAT_DEVICE 0x03 +#define MODE_PAGE_RIGID_GEOMETRY 0x04 +#define MODE_PAGE_FLEXIBILE 0x05 +#define MODE_PAGE_VERIFY_ERROR 0x07 +#define MODE_PAGE_CACHING 0x08 +#define MODE_PAGE_PERIPHERAL 0x09 +#define MODE_PAGE_CONTROL 0x0A +#define MODE_PAGE_MEDIUM_TYPES 0x0B +#define MODE_PAGE_NOTCH_PARTITION 0x0C +#define MODE_SENSE_RETURN_ALL 0x3f +#define MODE_SENSE_CURRENT_VALUES 0x00 +#define MODE_SENSE_CHANGEABLE_VALUES 0x40 +#define MODE_SENSE_DEFAULT_VAULES 0x80 +#define MODE_SENSE_SAVED_VALUES 0xc0 +#define MODE_PAGE_DEVICE_CONFIG 0x10 +#define MODE_PAGE_MEDIUM_PARTITION 0x11 +#define MODE_PAGE_DATA_COMPRESS 0x0f +#define MODE_PAGE_CAPABILITIES 0x2A + + +/* SCSI CDB operation codes */ + +#define SCSIOP_TEST_UNIT_READY 0x00 +#define SCSIOP_REZERO_UNIT 0x01 +#define SCSIOP_REWIND 0x01 +#define SCSIOP_REQUEST_BLOCK_ADDR 0x02 +#define SCSIOP_REQUEST_SENSE 0x03 +#define SCSIOP_FORMAT_UNIT 0x04 +#define SCSIOP_READ_BLOCK_LIMITS 0x05 +#define SCSIOP_REASSIGN_BLOCKS 0x07 +#define SCSIOP_READ6 0x08 +#define SCSIOP_RECEIVE 0x08 +#define SCSIOP_WRITE6 0x0A +#define SCSIOP_PRINT 0x0A +#define SCSIOP_SEND 0x0A +#define SCSIOP_SEEK6 0x0B +#define SCSIOP_TRACK_SELECT 0x0B +#define SCSIOP_SLEW_PRINT 0x0B +#define SCSIOP_SEEK_BLOCK 0x0C +#define SCSIOP_PARTITION 0x0D +#define SCSIOP_READ_REVERSE 0x0F +#define SCSIOP_WRITE_FILEMARKS 0x10 +#define SCSIOP_FLUSH_BUFFER 0x10 +#define SCSIOP_SPACE 0x11 +#define SCSIOP_INQUIRY 0x12 +#define SCSIOP_VERIFY6 0x13 +#define SCSIOP_RECOVER_BUF_DATA 0x14 +#define SCSIOP_MODE_SELECT 0x15 +#define SCSIOP_RESERVE_UNIT 0x16 +#define SCSIOP_RELEASE_UNIT 0x17 +#define SCSIOP_COPY 0x18 +#define SCSIOP_ERASE 0x19 +#define SCSIOP_MODE_SENSE 0x1A +#define SCSIOP_START_STOP_UNIT 0x1B +#define SCSIOP_STOP_PRINT 0x1B +#define SCSIOP_LOAD_UNLOAD 0x1B +#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C +#define SCSIOP_SEND_DIAGNOSTIC 0x1D +#define SCSIOP_MEDIUM_REMOVAL 0x1E +#define SCSIOP_READ_CAPACITY 0x25 +#define SCSIOP_READ 0x28 +#define SCSIOP_WRITE 0x2A +#define SCSIOP_SEEK 0x2B +#define SCSIOP_LOCATE 0x2B +#define SCSIOP_WRITE_VERIFY 0x2E +#define SCSIOP_VERIFY 0x2F +#define SCSIOP_SEARCH_DATA_HIGH 0x30 +#define SCSIOP_SEARCH_DATA_EQUAL 0x31 +#define SCSIOP_SEARCH_DATA_LOW 0x32 +#define SCSIOP_SET_LIMITS 0x33 +#define SCSIOP_READ_POSITION 0x34 +#define SCSIOP_SYNCHRONIZE_CACHE 0x35 +#define SCSIOP_COMPARE 0x39 +#define SCSIOP_COPY_COMPARE 0x3A +#define SCSIOP_WRITE_DATA_BUFF 0x3B +#define SCSIOP_READ_DATA_BUFF 0x3C +#define SCSIOP_CHANGE_DEFINITION 0x40 +#define SCSIOP_READ_SUB_CHANNEL 0x42 +#define SCSIOP_READ_TOC 0x43 +#define SCSIOP_READ_HEADER 0x44 +#define SCSIOP_PLAY_AUDIO 0x45 +#define SCSIOP_PLAY_AUDIO_MSF 0x47 +#define SCSIOP_PLAY_TRACK_INDEX 0x48 +#define SCSIOP_PLAY_TRACK_RELATIVE 0x49 +#define SCSIOP_PAUSE_RESUME 0x4B +#define SCSIOP_LOG_SELECT 0x4C +#define SCSIOP_LOG_SENSE 0x4D +#define SCSIOP_MODE_SELECT10 0x55 +#define SCSIOP_MODE_SENSE10 0x5A +#define SCSIOP_LOAD_UNLOAD_SLOT 0xA6 +#define SCSIOP_MECHANISM_STATUS 0xBD +#define SCSIOP_READ_CD 0xBE + +// +// If the IMMED bit is 1, status is returned as soon +// as the operation is initiated. If the IMMED bit +// is 0, status is not returned until the operation +// is completed. +// + +#define CDB_RETURN_ON_COMPLETION 0 +#define CDB_RETURN_IMMEDIATE 1 + + +// +// CDB Force media access used in extended read and write commands. +// + +#define CDB_FORCE_MEDIA_ACCESS 0x08 + +// +// Denon CD ROM operation codes +// + +#define SCSIOP_DENON_EJECT_DISC 0xE6 +#define SCSIOP_DENON_STOP_AUDIO 0xE7 +#define SCSIOP_DENON_PLAY_AUDIO 0xE8 +#define SCSIOP_DENON_READ_TOC 0xE9 +#define SCSIOP_DENON_READ_SUBCODE 0xEB + +// +// SCSI Bus Messages +// + +#define SCSIMESS_ABORT 0x06 +#define SCSIMESS_ABORT_WITH_TAG 0x0D +#define SCSIMESS_BUS_DEVICE_RESET 0X0C +#define SCSIMESS_CLEAR_QUEUE 0X0E +#define SCSIMESS_COMMAND_COMPLETE 0X00 +#define SCSIMESS_DISCONNECT 0X04 +#define SCSIMESS_EXTENDED_MESSAGE 0X01 +#define SCSIMESS_IDENTIFY 0X80 +#define SCSIMESS_IDENTIFY_WITH_DISCON 0XC0 +#define SCSIMESS_IGNORE_WIDE_RESIDUE 0X23 +#define SCSIMESS_INITIATE_RECOVERY 0X0F +#define SCSIMESS_INIT_DETECTED_ERROR 0X05 +#define SCSIMESS_LINK_CMD_COMP 0X0A +#define SCSIMESS_LINK_CMD_COMP_W_FLAG 0X0B +#define SCSIMESS_MESS_PARITY_ERROR 0X09 +#define SCSIMESS_MESSAGE_REJECT 0X07 +#define SCSIMESS_NO_OPERATION 0X08 +#define SCSIMESS_HEAD_OF_QUEUE_TAG 0X21 +#define SCSIMESS_ORDERED_QUEUE_TAG 0X22 +#define SCSIMESS_SIMPLE_QUEUE_TAG 0X20 +#define SCSIMESS_RELEASE_RECOVERY 0X10 +#define SCSIMESS_RESTORE_POINTERS 0X03 +#define SCSIMESS_SAVE_DATA_POINTER 0X02 +#define SCSIMESS_TERMINATE_IO_PROCESS 0X11 + +// +// SCSI Extended Message operation codes +// + +#define SCSIMESS_MODIFY_DATA_POINTER 0X00 +#define SCSIMESS_SYNCHRONOUS_DATA_REQ 0X01 +#define SCSIMESS_WIDE_DATA_REQUEST 0X03 + +// +// SCSI Extended Message Lengths +// + +#define SCSIMESS_MODIFY_DATA_LENGTH 5 +#define SCSIMESS_SYNCH_DATA_LENGTH 3 +#define SCSIMESS_WIDE_DATA_LENGTH 2 + +// +// SCSI extended message structure +// + +#pragma pack (1) +typedef struct _SCSI_EXTENDED_MESSAGE +{ + UCHAR InitialMessageCode; + UCHAR MessageLength; + UCHAR MessageType; + union _EXTENDED_ARGUMENTS + { + struct + { + UCHAR Modifier[4]; + } Modify; + + struct + { + UCHAR TransferPeriod; + UCHAR ReqAckOffset; + } Synchronous; + + struct + { + UCHAR Width; + } Wide; + } ExtendedArguments; +}SCSI_EXTENDED_MESSAGE, *PSCSI_EXTENDED_MESSAGE; +#pragma pack () + + +/* SCSI bus status codes */ + +#define SCSISTAT_GOOD 0x00 +#define SCSISTAT_CHECK_CONDITION 0x02 +#define SCSISTAT_CONDITION_MET 0x04 +#define SCSISTAT_BUSY 0x08 +#define SCSISTAT_INTERMEDIATE 0x10 +#define SCSISTAT_INTERMEDIATE_COND_MET 0x14 +#define SCSISTAT_RESERVATION_CONFLICT 0x18 +#define SCSISTAT_COMMAND_TERMINATED 0x22 +#define SCSISTAT_QUEUE_FULL 0x28 + +// +// Enable Vital Product Data Flag (EVPD) +// used with INQUIRY command. +// + +#define CDB_INQUIRY_EVPD 0x01 + +// +// Defines for format CDB +// + +#define LUN0_FORMAT_SAVING_DEFECT_LIST 0 +#define USE_DEFAULTMSB 0 +#define USE_DEFAULTLSB 0 + +#define START_UNIT_CODE 0x01 +#define STOP_UNIT_CODE 0x00 + + + +// +// Inquiry buffer structure. This is the data returned from the target +// after it receives an inquiry. +// +// This structure may be extended by the number of bytes specified +// in the field AdditionalLength. The defined size constant only +// includes fields through ProductRevisionLevel. +// +// The NT SCSI drivers are only interested in the first 36 bytes of data. +// + +#define INQUIRYDATABUFFERSIZE 36 + + +typedef struct _INQUIRYDATA +{ + UCHAR DeviceType:5; + UCHAR DeviceTypeQualifier:3; + UCHAR DeviceTypeModifier:7; + UCHAR RemovableMedia:1; + UCHAR Versions; + UCHAR ResponseDataFormat; + UCHAR AdditionalLength; + UCHAR Reserved[2]; + UCHAR SoftReset:1; + UCHAR CommandQueue:1; + UCHAR Reserved2:1; + UCHAR LinkedCommands:1; + UCHAR Synchronous:1; + UCHAR Wide16Bit:1; + UCHAR Wide32Bit:1; + UCHAR RelativeAddressing:1; + UCHAR VendorId[8]; + UCHAR ProductId[16]; + UCHAR ProductRevisionLevel[4]; + UCHAR VendorSpecific[20]; + UCHAR Reserved3[40]; +} INQUIRYDATA, *PINQUIRYDATA; + +// +// Inquiry defines. Used to interpret data returned from target as result +// of inquiry command. +// +// DeviceType field +// + +#define DIRECT_ACCESS_DEVICE 0x00 // disks +#define SEQUENTIAL_ACCESS_DEVICE 0x01 // tapes +#define PRINTER_DEVICE 0x02 // printers +#define PROCESSOR_DEVICE 0x03 // scanners, printers, etc +#define WRITE_ONCE_READ_MULTIPLE_DEVICE 0x04 // worms +#define READ_ONLY_DIRECT_ACCESS_DEVICE 0x05 // cdroms +#define SCANNER_DEVICE 0x06 // scanners +#define OPTICAL_DEVICE 0x07 // optical disks +#define MEDIUM_CHANGER 0x08 // jukebox +#define COMMUNICATION_DEVICE 0x09 // network +#define LOGICAL_UNIT_NOT_PRESENT_DEVICE 0x7F +#define DEVICE_QUALIFIER_NOT_SUPPORTED 0x03 + +// +// DeviceTypeQualifier field +// + +#define DEVICE_CONNECTED 0x00 + + +/* Sense Data Format */ + +typedef struct _SENSE_DATA +{ + UCHAR ErrorCode:7; + UCHAR Valid:1; + UCHAR SegmentNumber; + UCHAR SenseKey:4; + UCHAR Reserved:1; + UCHAR IncorrectLength:1; + UCHAR EndOfMedia:1; + UCHAR FileMark:1; + UCHAR Information[4]; + UCHAR AdditionalSenseLength; + UCHAR CommandSpecificInformation[4]; + UCHAR AdditionalSenseCode; + UCHAR AdditionalSenseCodeQualifier; + UCHAR FieldReplaceableUnitCode; + UCHAR SenseKeySpecific[3]; +} SENSE_DATA, *PSENSE_DATA; + + +/* Default request sense buffer size */ + +#define SENSE_BUFFER_SIZE 18 + +/* Sense codes */ + +#define SCSI_SENSE_NO_SENSE 0x00 +#define SCSI_SENSE_RECOVERED_ERROR 0x01 +#define SCSI_SENSE_NOT_READY 0x02 +#define SCSI_SENSE_MEDIUM_ERROR 0x03 +#define SCSI_SENSE_HARDWARE_ERROR 0x04 +#define SCSI_SENSE_ILLEGAL_REQUEST 0x05 +#define SCSI_SENSE_UNIT_ATTENTION 0x06 +#define SCSI_SENSE_DATA_PROTECT 0x07 +#define SCSI_SENSE_BLANK_CHECK 0x08 +#define SCSI_SENSE_UNIQUE 0x09 +#define SCSI_SENSE_COPY_ABORTED 0x0A +#define SCSI_SENSE_ABORTED_COMMAND 0x0B +#define SCSI_SENSE_EQUAL 0x0C +#define SCSI_SENSE_VOL_OVERFLOW 0x0D +#define SCSI_SENSE_MISCOMPARE 0x0E +#define SCSI_SENSE_RESERVED 0x0F + +/* Additional tape bit */ + +#define SCSI_ILLEGAL_LENGTH 0x20 +#define SCSI_EOM 0x40 +#define SCSI_FILE_MARK 0x80 + +/* Additional Sense codes */ + +#define SCSI_ADSENSE_NO_SENSE 0x00 +#define SCSI_ADSENSE_LUN_NOT_READY 0x04 +#define SCSI_ADSENSE_ILLEGAL_COMMAND 0x20 +#define SCSI_ADSENSE_ILLEGAL_BLOCK 0x21 +#define SCSI_ADSENSE_INVALID_LUN 0x25 +#define SCSI_ADSENSE_INVALID_CDB 0x24 +#define SCSI_ADSENSE_MUSIC_AREA 0xA0 +#define SCSI_ADSENSE_DATA_AREA 0xA1 +#define SCSI_ADSENSE_VOLUME_OVERFLOW 0xA7 + +#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE 0x3a +#define SCSI_ADWRITE_PROTECT 0x27 +#define SCSI_ADSENSE_MEDIUM_CHANGED 0x28 +#define SCSI_ADSENSE_BUS_RESET 0x29 +#define SCSI_ADSENSE_TRACK_ERROR 0x14 +#define SCSI_ADSENSE_SEEK_ERROR 0x15 +#define SCSI_ADSENSE_REC_DATA_NOECC 0x17 +#define SCSI_ADSENSE_REC_DATA_ECC 0x18 + +/* Additional sense code qualifier */ + +#define SCSI_SENSEQ_FORMAT_IN_PROGRESS 0x04 +#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED 0x02 +#define SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED 0x03 +#define SCSI_SENSEQ_BECOMING_READY 0x01 +#define SCSI_SENSEQ_FILEMARK_DETECTED 0x01 +#define SCSI_SENSEQ_SETMARK_DETECTED 0x03 +#define SCSI_SENSEQ_END_OF_MEDIA_DETECTED 0x02 +#define SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED 0x04 + +/* SCSI IO Device Control Codes */ + +#define FILE_DEVICE_SCSI 0x0000001b + +#define IOCTL_SCSI_EXECUTE_IN ((FILE_DEVICE_SCSI << 16) + 0x0011) +#define IOCTL_SCSI_EXECUTE_OUT ((FILE_DEVICE_SCSI << 16) + 0x0012) +#define IOCTL_SCSI_EXECUTE_NONE ((FILE_DEVICE_SCSI << 16) + 0x0013) + +/* SMART support in atapi */ + +#define IOCTL_SCSI_MINIPORT_SMART_VERSION ((FILE_DEVICE_SCSI << 16) + 0x0500) +#define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501) +#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS ((FILE_DEVICE_SCSI << 16) + 0x0502) +#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS ((FILE_DEVICE_SCSI << 16) + 0x0503) +#define IOCTL_SCSI_MINIPORT_ENABLE_SMART ((FILE_DEVICE_SCSI << 16) + 0x0504) +#define IOCTL_SCSI_MINIPORT_DISABLE_SMART ((FILE_DEVICE_SCSI << 16) + 0x0505) +#define IOCTL_SCSI_MINIPORT_RETURN_STATUS ((FILE_DEVICE_SCSI << 16) + 0x0506) +#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE ((FILE_DEVICE_SCSI << 16) + 0x0507) +#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES ((FILE_DEVICE_SCSI << 16) + 0x0508) +#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS ((FILE_DEVICE_SCSI << 16) + 0x0509) + + +/* Read Capacity Data - returned in Big Endian format */ + +typedef struct _READ_CAPACITY_DATA +{ + ULONG LogicalBlockAddress; + ULONG BytesPerBlock; +} READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA; + + +// +// Read Block Limits Data - returned in Big Endian format +// This structure returns the maximum and minimum block +// size for a TAPE device. +// + +typedef struct _READ_BLOCK_LIMITS +{ + UCHAR Reserved; + UCHAR BlockMaximumSize[3]; + UCHAR BlockMinimumSize[2]; +} READ_BLOCK_LIMITS_DATA, *PREAD_BLOCK_LIMITS_DATA; + + +// +// Mode data structures. +// + +// +// Define Mode parameter header. +// + +typedef struct _MODE_PARAMETER_HEADER +{ + UCHAR ModeDataLength; + UCHAR MediumType; + UCHAR DeviceSpecificParameter; + UCHAR BlockDescriptorLength; +}MODE_PARAMETER_HEADER, *PMODE_PARAMETER_HEADER; + +typedef struct _MODE_PARAMETER_HEADER10 +{ + UCHAR ModeDataLength[2]; + UCHAR MediumType; + UCHAR DeviceSpecificParameter; + UCHAR Reserved[2]; + UCHAR BlockDescriptorLength[2]; +}MODE_PARAMETER_HEADER10, *PMODE_PARAMETER_HEADER10; + +#define MODE_FD_SINGLE_SIDE 0x01 +#define MODE_FD_DOUBLE_SIDE 0x02 +#define MODE_FD_MAXIMUM_TYPE 0x1E +#define MODE_DSP_FUA_SUPPORTED 0x10 +#define MODE_DSP_WRITE_PROTECT 0x80 + +// +// Define the mode parameter block. +// + +typedef struct _MODE_PARAMETER_BLOCK +{ + UCHAR DensityCode; + UCHAR NumberOfBlocks[3]; + UCHAR Reserved; + UCHAR BlockLength[3]; +}MODE_PARAMETER_BLOCK, *PMODE_PARAMETER_BLOCK; + + +/* Define Disconnect-Reconnect page */ +typedef struct _MODE_DISCONNECT_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR BufferFullRatio; + UCHAR BufferEmptyRatio; + UCHAR BusInactivityLimit[2]; + UCHAR BusDisconnectTime[2]; + UCHAR BusConnectTime[2]; + UCHAR MaximumBurstSize[2]; + UCHAR DataTransferDisconnect:2; + UCHAR Reserved2[3]; +}MODE_DISCONNECT_PAGE, *PMODE_DISCONNECT_PAGE; + +// +// Define mode caching page. +// + +typedef struct _MODE_CACHING_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR ReadDisableCache:1; + UCHAR MultiplicationFactor:1; + UCHAR WriteCacheEnable:1; + UCHAR Reserved2:5; + UCHAR WriteRetensionPriority:4; + UCHAR ReadRetensionPriority:4; + UCHAR DisablePrefetchTransfer[2]; + UCHAR MinimumPrefetch[2]; + UCHAR MaximumPrefetch[2]; + UCHAR MaximumPrefetchCeiling[2]; +}MODE_CACHING_PAGE, *PMODE_CACHING_PAGE; + +// +// Define mode flexible disk page. +// + +typedef struct _MODE_FLEXIBLE_DISK_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR TransferRate[2]; + UCHAR NumberOfHeads; + UCHAR SectorsPerTrack; + UCHAR BytesPerSector[2]; + UCHAR NumberOfCylinders[2]; + UCHAR StartWritePrecom[2]; + UCHAR StartReducedCurrent[2]; + UCHAR StepRate[2]; + UCHAR StepPluseWidth; + UCHAR HeadSettleDelay[2]; + UCHAR MotorOnDelay; + UCHAR MotorOffDelay; + UCHAR Reserved2:5; + UCHAR MotorOnAsserted:1; + UCHAR StartSectorNumber:1; + UCHAR TrueReadySignal:1; + UCHAR StepPlusePerCyclynder:4; + UCHAR Reserved3:4; + UCHAR WriteCompenstation; + UCHAR HeadLoadDelay; + UCHAR HeadUnloadDelay; + UCHAR Pin2Usage:4; + UCHAR Pin34Usage:4; + UCHAR Pin1Usage:4; + UCHAR Pin4Usage:4; + UCHAR MediumRotationRate[2]; + UCHAR Reserved4[2]; +}MODE_FLEXIBLE_DISK_PAGE, *PMODE_FLEXIBLE_DISK_PAGE; + +// +// Define mode format page. +// + +typedef struct _MODE_FORMAT_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR TracksPerZone[2]; + UCHAR AlternateSectorsPerZone[2]; + UCHAR AlternateTracksPerZone[2]; + UCHAR AlternateTracksPerLogicalUnit[2]; + UCHAR SectorsPerTrack[2]; + UCHAR BytesPerPhysicalSector[2]; + UCHAR Interleave[2]; + UCHAR TrackSkewFactor[2]; + UCHAR CylinderSkewFactor[2]; + UCHAR Reserved2:4; + UCHAR SurfaceFirst:1; + UCHAR RemovableMedia:1; + UCHAR HardSectorFormating:1; + UCHAR SoftSectorFormating:1; + UCHAR Reserved3[2]; +}MODE_FORMAT_PAGE, *PMODE_FORMAT_PAGE; + +// +// Define rigid disk driver geometry page. +// + +typedef struct _MODE_RIGID_GEOMETRY_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved:1; + UCHAR PageSavable:1; + UCHAR PageLength; + UCHAR NumberOfCylinders[2]; + UCHAR NumberOfHeads; + UCHAR StartWritePrecom[2]; + UCHAR StartReducedCurrent[2]; + UCHAR DriveStepRate[2]; + UCHAR LandZoneCyclinder[2]; + UCHAR RotationalPositionLock:2; + UCHAR Reserved2:6; + UCHAR RotationOffset; + UCHAR Reserved3; + UCHAR RoataionRate[2]; + UCHAR Reserved4[2]; +}MODE_RIGID_GEOMETRY_PAGE, *PMODE_RIGID_GEOMETRY_PAGE; + +// +// Define read write recovery page +// + +typedef struct _MODE_READ_WRITE_RECOVERY_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved1:1; + UCHAR PSBit:1; + UCHAR PageLength; + UCHAR DCRBit:1; + UCHAR DTEBit:1; + UCHAR PERBit:1; + UCHAR EERBit:1; + UCHAR RCBit:1; + UCHAR TBBit:1; + UCHAR ARRE:1; + UCHAR AWRE:1; + UCHAR ReadRetryCount; + UCHAR Reserved4[4]; + UCHAR WriteRetryCount; + UCHAR Reserved5[3]; +} MODE_READ_WRITE_RECOVERY_PAGE, *PMODE_READ_WRITE_RECOVERY_PAGE; + +// +// Define read recovery page - cdrom +// + +typedef struct _MODE_READ_RECOVERY_PAGE +{ + UCHAR PageCode:6; + UCHAR Reserved1:1; + UCHAR PSBit:1; + UCHAR PageLength; + UCHAR DCRBit:1; + UCHAR DTEBit:1; + UCHAR PERBit:1; + UCHAR Reserved2:1; + UCHAR RCBit:1; + UCHAR TBBit:1; + UCHAR Reserved3:2; + UCHAR ReadRetryCount; + UCHAR Reserved4[4]; +} MODE_READ_RECOVERY_PAGE, *PMODE_READ_RECOVERY_PAGE; + +// +// Define CD-ROM Capabilities and Mechanical Status Page. +// + +typedef struct _MODE_CAPABILITIES_PAGE2 +{ + UCHAR PageCode:6; + UCHAR Reserved1:1; + UCHAR PSBit:1; + UCHAR PageLength; + UCHAR Reserved2[2]; + UCHAR Capabilities[4]; + UCHAR MaximumSpeedSupported[2]; + UCHAR Reserved3; + UCHAR NumberVolumeLevels; + UCHAR BufferSize[2]; + UCHAR CurrentSpeed[2]; + UCHAR Reserved4; + UCHAR Reserved5:1; + UCHAR DigitalOutput:4; + UCHAR Reserved6:3; + UCHAR Reserved7[2]; +} MODE_CAPABILITIES_PAGE2, *PMODE_CAPABILITIES_PAGE2; + +// +// Bit definitions of Capabilites and DigitalOutput +// + +#define AUDIO_PLAY_SUPPORTED 0x01 +#define MODE2_FORM1_SUPPORTED 0x10 +#define MODE2_FORM2_SUPPORTED 0x20 +#define MULTI_SESSION_SUPPORTED 0x40 + +#define READ_CD_SUPPORTED 0x01 + +#define MEDIA_LOCKING_SUPPORTED 0x01 +#define CURRENT_LOCK_STATE 0x02 +#define SOFTWARE_EJECT_SUPPORT 0x08 + +#define DISC_PRESENT_REPORTING 0x04 + +// +// Mode parameter list block descriptor - +// set the block length for reading/writing +// +// + +#define MODE_BLOCK_DESC_LENGTH 8 +#define MODE_HEADER_LENGTH 4 +#define MODE_HEADER_LENGTH10 8 + +typedef struct _MODE_PARM_READ_WRITE +{ + MODE_PARAMETER_HEADER ParameterListHeader; /* List Header Format */ + MODE_PARAMETER_BLOCK ParameterListBlock; /* List Block Descriptor */ +} MODE_PARM_READ_WRITE_DATA, *PMODE_PARM_READ_WRITE_DATA; + + +// +// CDROM audio control (0x0E) +// + +#define CDB_AUDIO_PAUSE 0 +#define CDB_AUDIO_RESUME 1 + +#define CDB_DEVICE_START 0x11 +#define CDB_DEVICE_STOP 0x10 + +#define CDB_EJECT_MEDIA 0x10 +#define CDB_LOAD_MEDIA 0x01 + +#define CDB_SUBCHANNEL_HEADER 0x00 +#define CDB_SUBCHANNEL_BLOCK 0x01 + +#define CDROM_AUDIO_CONTROL_PAGE 0x0E +#define MODE_SELECT_IMMEDIATE 0x04 +#define MODE_SELECT_PFBIT 0x10 + +#define CDB_USE_MSF 0x01 + +typedef struct _PORT_OUTPUT +{ + UCHAR ChannelSelection; + UCHAR Volume; +} PORT_OUTPUT, *PPORT_OUTPUT; + +typedef struct _AUDIO_OUTPUT +{ + UCHAR CodePage; + UCHAR ParameterLength; + UCHAR Immediate; + UCHAR Reserved[2]; + UCHAR LbaFormat; + UCHAR LogicalBlocksPerSecond[2]; + PORT_OUTPUT PortOutput[4]; +} AUDIO_OUTPUT, *PAUDIO_OUTPUT; + + +/* Multisession CDROM */ + +#define GET_LAST_SESSION 0x01 +#define GET_SESSION_DATA 0x02; + + +/* Atapi 2.5 changer */ + +typedef struct _MECHANICAL_STATUS_INFORMATION_HEADER +{ + UCHAR CurrentSlot:5; + UCHAR ChangerState:2; + UCHAR Fault:1; + UCHAR Reserved:5; + UCHAR MechanismState:3; + UCHAR CurrentLogicalBlockAddress[3]; + UCHAR NumberAvailableSlots; + UCHAR SlotTableLength[2]; +} MECHANICAL_STATUS_INFORMATION_HEADER, *PMECHANICAL_STATUS_INFORMATION_HEADER; + +typedef struct _SLOT_TABLE_INFORMATION +{ + UCHAR DiscChanged:1; + UCHAR Reserved:6; + UCHAR DiscPresent:1; + UCHAR Reserved2[3]; +} SLOT_TABLE_INFORMATION, *PSLOT_TABLE_INFORMATION; + +typedef struct _MECHANICAL_STATUS +{ + MECHANICAL_STATUS_INFORMATION_HEADER MechanicalStatusHeader; + SLOT_TABLE_INFORMATION SlotTableInfo[1]; +} MECHANICAL_STATUS, *PMECHANICAL_STATUS; + + +/* Tape definitions */ + +typedef struct _TAPE_POSITION_DATA +{ + UCHAR Reserved1:2; + UCHAR BlockPositionUnsupported:1; + UCHAR Reserved2:3; + UCHAR EndOfPartition:1; + UCHAR BeginningOfPartition:1; + UCHAR PartitionNumber; + USHORT Reserved3; + UCHAR FirstBlock[4]; + UCHAR LastBlock[4]; + UCHAR Reserved4; + UCHAR NumberOfBlocks[3]; + UCHAR NumberOfBytes[4]; +} TAPE_POSITION_DATA, *PTAPE_POSITION_DATA; + +/* + * This structure is used to convert little endian + * ULONGs to SCSI CDB 4 byte big endians values. + */ + +typedef struct _FOUR_BYTE +{ + UCHAR Byte0; + UCHAR Byte1; + UCHAR Byte2; + UCHAR Byte3; +} FOUR_BYTE, *PFOUR_BYTE; + +/* + * Byte reversing macro for converting + * between big- and little-endian formats + */ + +#define REVERSE_BYTES(Destination, Source) \ +{ \ + PFOUR_BYTE d = (PFOUR_BYTE)(Destination); \ + PFOUR_BYTE s = (PFOUR_BYTE)(Source); \ + d->Byte3 = s->Byte0; \ + d->Byte2 = s->Byte1; \ + d->Byte1 = s->Byte2; \ + d->Byte0 = s->Byte3; \ +} + + +/* This macro has the effect of Bit = log2(Data) */ + +#define WHICH_BIT(Data, Bit) \ +{ \ + for (Bit = 0; Bit < 32; Bit++) \ + { \ + if ((Data >> Bit) == 1) \ + { \ + break; \ + } \ + } \ +} + + +#endif /* __STORAGE_INCLUDE_SCSI_H */ + +/* EOF */ diff --git a/include/ddk/sefuncs.h b/include/ddk/sefuncs.h new file mode 100644 index 0000000..004359b --- /dev/null +++ b/include/ddk/sefuncs.h @@ -0,0 +1,152 @@ +#ifndef _INCLUDE_DDK_SEFUNCS_H +#define _INCLUDE_DDK_SEFUNCS_H +/* $Id$ */ + +BOOLEAN STDCALL +SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, + IN BOOLEAN SubjectContextLocked, + IN ACCESS_MASK DesiredAccess, + IN ACCESS_MASK PreviouslyGrantedAccess, + OUT PPRIVILEGE_SET* Privileges OPTIONAL, + IN PGENERIC_MAPPING GenericMapping, + IN KPROCESSOR_MODE AccessMode, + OUT PACCESS_MODE GrantedAccess, + OUT PNTSTATUS AccessStatus); + +NTSTATUS STDCALL +SeAppendPrivileges(IN PACCESS_STATE AccessState, + IN PPRIVILEGE_SET Privileges); + +NTSTATUS STDCALL +SeAssignSecurity(IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL, + IN PSECURITY_DESCRIPTOR ExplicitDescriptor, + OUT PSECURITY_DESCRIPTOR* NewDescriptor, + IN BOOLEAN IsDirectoryObject, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext, + IN PGENERIC_MAPPING GenericMapping, + IN POOL_TYPE PoolType); + +BOOLEAN STDCALL +SeAuditingFileEvents(IN BOOLEAN AccessGranted, + IN PSECURITY_DESCRIPTOR SecurityDescriptor); + +BOOLEAN STDCALL +SeAuditingFileOrGlobalEvents(IN BOOLEAN AccessGranted, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext); + +VOID STDCALL +SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext); + +NTSTATUS STDCALL +SeCreateAccessState(OUT PACCESS_STATE AccessState, + IN PVOID AuxData, + IN ACCESS_MASK AccessMask, + IN PGENERIC_MAPPING Mapping); + +NTSTATUS STDCALL +SeCreateClientSecurity(IN struct _ETHREAD *Thread, + IN PSECURITY_QUALITY_OF_SERVICE Qos, + IN BOOLEAN RemoteClient, + OUT PSECURITY_CLIENT_CONTEXT ClientContext); + +NTSTATUS STDCALL +SeDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR* SecurityDescriptor); + +VOID STDCALL +SeDeleteAccessState(IN PACCESS_STATE AccessState); + +VOID STDCALL +SeDeleteObjectAuditAlarm(IN PVOID Object, + IN HANDLE Handle); + +VOID STDCALL +SeFreePrivileges(IN PPRIVILEGE_SET Privileges); + +VOID STDCALL +SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext, + IN struct _ETHREAD *ServerThread OPTIONAL); + +VOID STDCALL +SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext); + +NTSTATUS STDCALL +SeMarkLogonSessionForTerminationNotification(IN PLUID LogonId); + +VOID STDCALL +SeOpenObjectAuditAlarm(IN PUNICODE_STRING ObjectTypeName, + IN PVOID Object OPTIONAL, + IN PUNICODE_STRING AbsoluteObjectName OPTIONAL, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PACCESS_STATE AccessState, + IN BOOLEAN ObjectCreated, + IN BOOLEAN AccessGranted, + IN KPROCESSOR_MODE AccessMode, + OUT PBOOLEAN GenerateOnClose); + +VOID STDCALL +SeOpenObjectForDeleteAuditAlarm(IN PUNICODE_STRING ObjectTypeName, + IN PVOID Object OPTIONAL, + IN PUNICODE_STRING AbsoluteObjectName OPTIONAL, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PACCESS_STATE AccessState, + IN BOOLEAN ObjectCreated, + IN BOOLEAN AccessGranted, + IN KPROCESSOR_MODE AccessMode, + OUT PBOOLEAN GenerateOnClose); + +BOOLEAN STDCALL +SePrivilegeCheck(IN OUT PPRIVILEGE_SET RequiredPrivileges, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext, + IN KPROCESSOR_MODE AccessMode); + +NTSTATUS STDCALL +SeQueryAuthenticationIdToken(IN PACCESS_TOKEN Token, + OUT PLUID LogonId); + +NTSTATUS STDCALL +SeQuerySecurityDescriptorInfo(IN PSECURITY_INFORMATION SecurityInformation, + OUT PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OUT PULONG Length, + IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor); + +NTSTATUS STDCALL +SeRegisterLogonSessionTerminatedRoutine(IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine); + +VOID STDCALL +SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext); + +VOID STDCALL +SeSetAccessStateGenericMapping(IN PACCESS_STATE AccessState, + IN PGENERIC_MAPPING GenericMapping); + +NTSTATUS STDCALL +SeSetSecurityDescriptorInfo(IN PVOID Object OPTIONAL, + IN PSECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + IN POOL_TYPE PoolType, + IN PGENERIC_MAPPING GenericMapping); + +BOOLEAN STDCALL +SeSinglePrivilegeCheck(IN LUID PrivilegeValue, + IN KPROCESSOR_MODE PreviousMode); + +SECURITY_IMPERSONATION_LEVEL STDCALL +SeTokenImpersonationLevel(IN PACCESS_TOKEN Token); + +TOKEN_TYPE STDCALL +SeTokenType(IN PACCESS_TOKEN Token); + +VOID STDCALL +SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext); + +NTSTATUS STDCALL +SeUnregisterLogonSessionTerminatedRoutine(IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine); + +BOOLEAN STDCALL +SeValidSecurityDescriptor(IN ULONG Length, + IN PSECURITY_DESCRIPTOR SecurityDescriptor); + +#endif /* ndef _INCLUDE_DDK_SEFUNCS_H */ diff --git a/include/ddk/service.h b/include/ddk/service.h new file mode 100644 index 0000000..e6a6848 --- /dev/null +++ b/include/ddk/service.h @@ -0,0 +1,60 @@ + +#ifndef __INTERNAL_SERVICE_H +#define __INTERNAL_SERVICE_H + + +/* number of entries in the service descriptor tables */ +#define SSDT_MAX_ENTRIES 4 + + +#pragma pack(1) + +// System Service Dispatch Table +typedef struct t_SSDT { + ULONG SysCallPtr; +} SSDT, *PSSDT; + +// System Service Parameters Table +typedef struct t_SSPT { + unsigned int ParamBytes; +} SSPT, *PSSPT; + +typedef struct t_KeServiceDescriptorTableEntry { + PSSDT SSDT; + PULONG ServiceCounterTable; + unsigned int NumberOfServices; + PSSPT SSPT; + +} KE_SERVICE_DESCRIPTOR_TABLE_ENTRY, *PKE_SERVICE_DESCRIPTOR_TABLE_ENTRY; + +#pragma pack() + + +/* --- NTOSKRNL.EXE --- */ +#if defined(__NTOSKRNL__) +extern +KE_SERVICE_DESCRIPTOR_TABLE_ENTRY +KeServiceDescriptorTable[SSDT_MAX_ENTRIES] __declspec(dllexport); +#else +extern +KE_SERVICE_DESCRIPTOR_TABLE_ENTRY +KeServiceDescriptorTable[SSDT_MAX_ENTRIES] __declspec(dllimport); +#endif + +extern +KE_SERVICE_DESCRIPTOR_TABLE_ENTRY +KeServiceDescriptorTableShadow[SSDT_MAX_ENTRIES]; + + +BOOLEAN +STDCALL +KeAddSystemServiceTable ( + PSSDT SSDT, + PULONG ServiceCounterTable, + ULONG NumberOfServices, + PSSPT SSPT, + ULONG TableIndex + ); + +#endif + diff --git a/include/ddk/setypes.h b/include/ddk/setypes.h new file mode 100644 index 0000000..7cd7f99 --- /dev/null +++ b/include/ddk/setypes.h @@ -0,0 +1,164 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory for details + * PROJECT: ReactOS kernel + * FILE: include/ddk/setypes.h + * PURPOSE: Security manager types + * REVISION HISTORY: + * ??/??/??: Created with empty stubs by David Welch + * 29/08/98: ACCESS_TOKEN definition from Boudewijn Dekker + */ + +#ifndef __INCLUDE_DDK_SETYPES_H +#define __INCLUDE_DDK_SETYPES_H + +#include + +/* TOKEN_GROUPS structure */ +#define SE_GROUP_MANDATORY (0x1L) +#define SE_GROUP_ENABLED_BY_DEFAULT (0x2L) +#define SE_GROUP_ENABLED (0x4L) +#define SE_GROUP_OWNER (0x8L) +#define SE_GROUP_LOGON_ID (0xc0000000L) + +/* ACL Defines */ +#define ACL_REVISION (2) + +/* ACE_HEADER structure */ +#define ACCESS_ALLOWED_ACE_TYPE (0x0) +#define ACCESS_DENIED_ACE_TYPE (0x1) +#define SYSTEM_AUDIT_ACE_TYPE (0x2) +#define SYSTEM_ALARM_ACE_TYPE (0x3) + +/* ACE flags in the ACE_HEADER structure */ +#define OBJECT_INHERIT_ACE (0x1) +#define CONTAINER_INHERIT_ACE (0x2) +#define NO_PROPAGATE_INHERIT_ACE (0x4) +#define INHERIT_ONLY_ACE (0x8) +#define SUCCESSFUL_ACCESS_ACE_FLAG (0x40) +#define FAILED_ACCESS_ACE_FLAG (0x80) + +/* SECURITY_DESCRIPTOR_CONTROL */ +#define SECURITY_DESCRIPTOR_REVISION (1) +#define SECURITY_DESCRIPTOR_MIN_LENGTH (20) +#define SE_OWNER_DEFAULTED (1) +#define SE_GROUP_DEFAULTED (2) +#define SE_DACL_PRESENT (4) +#define SE_DACL_DEFAULTED (8) +#define SE_SACL_PRESENT (16) +#define SE_SACL_DEFAULTED (32) +#define SE_SELF_RELATIVE (32768) + +/* PRIVILEGE_SET */ +#define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x1L) +#define SE_PRIVILEGE_ENABLED (0x2L) +#define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L) +#define PRIVILEGE_SET_ALL_NECESSARY (0x1) + +typedef struct _ACCESS_TOKEN +{ + TOKEN_SOURCE TokenSource; // 0x00 + LUID TokenId; // 0x10 + LUID AuthenticationId; // 0x18 + LARGE_INTEGER ExpirationTime; // 0x20 + LUID ModifiedId; // 0x28 + ULONG UserAndGroupCount; // 0x30 + ULONG PrivilegeCount; // 0x34 + ULONG VariableLength; // 0x38 + ULONG DynamicCharged; // 0x3C + ULONG DynamicAvailable; // 0x40 + ULONG DefaultOwnerIndex; // 0x44 + PSID_AND_ATTRIBUTES UserAndGroups; // 0x48 + PSID PrimaryGroup; // 0x4C + PLUID_AND_ATTRIBUTES Privileges; // 0x50 + ULONG Unknown1; // 0x54 + PACL DefaultDacl; // 0x58 + TOKEN_TYPE TokenType; // 0x5C + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; // 0x60 + UCHAR TokenFlags; // 0x64 + UCHAR TokenInUse; // 0x65 + UCHAR Unused[2]; // 0x66 + PVOID ProxyData; // 0x68 + PVOID AuditData; // 0x6c + UCHAR VariablePart[0]; // 0x70 +} ACCESS_TOKEN, *PACCESS_TOKEN; + + +typedef struct _SECURITY_SUBJECT_CONTEXT +{ + PACCESS_TOKEN ClientToken; // 0x0 + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; // 0x4 + PACCESS_TOKEN PrimaryToken; // 0x8 + PVOID ProcessAuditId; // 0xC +} SECURITY_SUBJECT_CONTEXT, *PSECURITY_SUBJECT_CONTEXT; + + +typedef struct _SECURITY_CLIENT_CONTEXT +{ + SECURITY_QUALITY_OF_SERVICE SecurityQos; // 0x00 + PACCESS_TOKEN Token; // 0x0C + BOOLEAN DirectlyAccessClientToken; // 0x10 + BOOLEAN DirectAccessEffectiveOnly; // 0x11 + BOOLEAN ServerIsRemote; // 0x12 + TOKEN_CONTROL ClientTokenControl; // 0x14 +} SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT; + + +typedef struct _SE_EXPORTS +{ + /* Privilege values */ + LUID SeCreateTokenPrivilege; + LUID SeAssignPrimaryTokenPrivilege; + LUID SeLockMemoryPrivilege; + LUID SeIncreaseQuotaPrivilege; + LUID SeUnsolicitedInputPrivilege; + LUID SeTcbPrivilege; + LUID SeSecurityPrivilege; + LUID SeTakeOwnershipPrivilege; + LUID SeLoadDriverPrivilege; + LUID SeCreatePagefilePrivilege; + LUID SeIncreaseBasePriorityPrivilege; + LUID SeSystemProfilePrivilege; + LUID SeSystemtimePrivilege; + LUID SeProfileSingleProcessPrivilege; + LUID SeCreatePermanentPrivilege; + LUID SeBackupPrivilege; + LUID SeRestorePrivilege; + LUID SeShutdownPrivilege; + LUID SeDebugPrivilege; + LUID SeAuditPrivilege; + LUID SeSystemEnvironmentPrivilege; + LUID SeChangeNotifyPrivilege; + LUID SeRemoteShutdownPrivilege; + + /* Universally defined SIDs */ + PSID SeNullSid; + PSID SeWorldSid; + PSID SeLocalSid; + PSID SeCreatorOwnerSid; + PSID SeCreatorGroupSid; + + /* Nt defined SIDs */ + PSID SeNtAuthoritySid; + PSID SeDialupSid; + PSID SeNetworkSid; + PSID SeBatchSid; + PSID SeInteractiveSid; + PSID SeLocalSystemSid; + PSID SeAliasAdminsSid; + PSID SeAliasUsersSid; + PSID SeAliasGuestsSid; + PSID SeAliasPowerUsersSid; + PSID SeAliasAccountOpsSid; + PSID SeAliasSystemOpsSid; + PSID SeAliasPrintOpsSid; + PSID SeAliasBackupOpsSid; +} SE_EXPORTS, *PSE_EXPORTS; + + +typedef NTSTATUS STDCALL +(*PSE_LOGON_SESSION_TERMINATED_ROUTINE)(IN PLUID LogonId); + +#endif + +/* EOF */ diff --git a/include/ddk/srb.h b/include/ddk/srb.h new file mode 100644 index 0000000..a911c55 --- /dev/null +++ b/include/ddk/srb.h @@ -0,0 +1,534 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/storage/include/srb.c + * PURPOSE: SCSI port driver definitions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +#ifndef __STORAGE_INCLUDE_SRB_H +#define __STORAGE_INCLUDE_SRB_H + + +/* Define SCSI maximum configuration parameters. */ + +#define SCSI_MAXIMUM_LOGICAL_UNITS 8 +#define SCSI_MAXIMUM_TARGETS_PER_BUS 32 +#define SCSI_MAXIMUM_BUSES 8 +#define SCSI_MINIMUM_PHYSICAL_BREAKS 16 +#define SCSI_MAXIMUM_PHYSICAL_BREAKS 255 + + +/* Obsolete. For backward compatibility only. */ + +#define SCSI_MAXIMUM_TARGETS 8 + + +#define MAXIMUM_CDB_SIZE 12 + + +typedef PHYSICAL_ADDRESS SCSI_PHYSICAL_ADDRESS, *PSCSI_PHYSICAL_ADDRESS; + + +typedef struct _ACCESS_RANGE +{ + SCSI_PHYSICAL_ADDRESS RangeStart; + ULONG RangeLength; + BOOLEAN RangeInMemory; +}ACCESS_RANGE, *PACCESS_RANGE; + + +typedef struct _PORT_CONFIGURATION_INFORMATION +{ + ULONG Length; + ULONG SystemIoBusNumber; + INTERFACE_TYPE AdapterInterfaceType; + ULONG BusInterruptLevel; + ULONG BusInterruptVector; + KINTERRUPT_MODE InterruptMode; + ULONG MaximumTransferLength; + ULONG NumberOfPhysicalBreaks; + ULONG DmaChannel; + ULONG DmaPort; + DMA_WIDTH DmaWidth; + DMA_SPEED DmaSpeed; + ULONG AlignmentMask; + ULONG NumberOfAccessRanges; +#ifdef __GNUC__ + ACCESS_RANGE *AccessRanges; +#else + ACCESS_RANGE (*AccessRanges)[]; +#endif + PVOID Reserved; + UCHAR NumberOfBuses; + CCHAR InitiatorBusId[8]; + BOOLEAN ScatterGather; + BOOLEAN Master; + BOOLEAN CachesData; + BOOLEAN AdapterScansDown; + BOOLEAN AtdiskPrimaryClaimed; + BOOLEAN AtdiskSecondaryClaimed; + BOOLEAN Dma32BitAddresses; + BOOLEAN DemandMode; + BOOLEAN MapBuffers; + BOOLEAN NeedPhysicalAddresses; + BOOLEAN TaggedQueuing; + BOOLEAN AutoRequestSense; + BOOLEAN MultipleRequestPerLu; + BOOLEAN ReceiveEvent; + BOOLEAN RealModeInitialized; + BOOLEAN BufferAccessScsiPortControlled; + UCHAR MaximumNumberOfTargets; + UCHAR ReservedUchars[2]; + ULONG SlotNumber; + ULONG BusInterruptLevel2; + ULONG BusInterruptVector2; + KINTERRUPT_MODE InterruptMode2; + ULONG DmaChannel2; + ULONG DmaPort2; + DMA_WIDTH DmaWidth2; + DMA_SPEED DmaSpeed2; + ULONG DeviceExtensionSize; + ULONG SpecificLuExtensionSize; + ULONG SrbExtensionSize; +} PORT_CONFIGURATION_INFORMATION, *PPORT_CONFIGURATION_INFORMATION; + +#define CONFIG_INFO_VERSION_2 sizeof(PORT_CONFIGURATION_INFORMATION) + + +typedef struct _SCSI_REQUEST_BLOCK +{ + USHORT Length; // 0x00 + UCHAR Function; // 0x02 + UCHAR SrbStatus; // 0x03 + UCHAR ScsiStatus; // 0x04 + UCHAR PathId; // 0x05 + UCHAR TargetId; // 0x06 + UCHAR Lun; // 0x07 + UCHAR QueueTag; // 0x08 + UCHAR QueueAction; // 0x09 + UCHAR CdbLength; // 0x0A + UCHAR SenseInfoBufferLength; // 0x0B + ULONG SrbFlags; // 0x0C + ULONG DataTransferLength; // 0x10 + ULONG TimeOutValue; // 0x14 + PVOID DataBuffer; // 0x18 + PVOID SenseInfoBuffer; // 0x1C + struct _SCSI_REQUEST_BLOCK *NextSrb; // 0x20 + PVOID OriginalRequest; // 0x24 + PVOID SrbExtension; // 0x28 + ULONG QueueSortKey; // 0x2C + UCHAR Cdb[16]; // 0x30 +} SCSI_REQUEST_BLOCK, *PSCSI_REQUEST_BLOCK; + +#define SCSI_REQUEST_BLOCK_SIZE sizeof(SCSI_REQUEST_BLOCK) + + +/* SRB Functions */ + +#define SRB_FUNCTION_EXECUTE_SCSI 0x00 +#define SRB_FUNCTION_CLAIM_DEVICE 0x01 +#define SRB_FUNCTION_IO_CONTROL 0x02 +#define SRB_FUNCTION_RECEIVE_EVENT 0x03 +#define SRB_FUNCTION_RELEASE_QUEUE 0x04 +#define SRB_FUNCTION_ATTACH_DEVICE 0x05 +#define SRB_FUNCTION_RELEASE_DEVICE 0x06 +#define SRB_FUNCTION_SHUTDOWN 0x07 +#define SRB_FUNCTION_FLUSH 0x08 +#define SRB_FUNCTION_ABORT_COMMAND 0x10 +#define SRB_FUNCTION_RELEASE_RECOVERY 0x11 +#define SRB_FUNCTION_RESET_BUS 0x12 +#define SRB_FUNCTION_RESET_DEVICE 0x13 +#define SRB_FUNCTION_TERMINATE_IO 0x14 +#define SRB_FUNCTION_FLUSH_QUEUE 0x15 +#define SRB_FUNCTION_REMOVE_DEVICE 0x16 + + +/* SRB Status */ + +#define SRB_STATUS_PENDING 0x00 +#define SRB_STATUS_SUCCESS 0x01 +#define SRB_STATUS_ABORTED 0x02 +#define SRB_STATUS_ABORT_FAILED 0x03 +#define SRB_STATUS_ERROR 0x04 +#define SRB_STATUS_BUSY 0x05 +#define SRB_STATUS_INVALID_REQUEST 0x06 +#define SRB_STATUS_INVALID_PATH_ID 0x07 +#define SRB_STATUS_NO_DEVICE 0x08 +#define SRB_STATUS_TIMEOUT 0x09 +#define SRB_STATUS_SELECTION_TIMEOUT 0x0A +#define SRB_STATUS_COMMAND_TIMEOUT 0x0B +#define SRB_STATUS_MESSAGE_REJECTED 0x0D +#define SRB_STATUS_BUS_RESET 0x0E +#define SRB_STATUS_PARITY_ERROR 0x0F +#define SRB_STATUS_REQUEST_SENSE_FAILED 0x10 +#define SRB_STATUS_NO_HBA 0x11 +#define SRB_STATUS_DATA_OVERRUN 0x12 +#define SRB_STATUS_UNEXPECTED_BUS_FREE 0x13 +#define SRB_STATUS_PHASE_SEQUENCE_FAILURE 0x14 +#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH 0x15 +#define SRB_STATUS_REQUEST_FLUSHED 0x16 +#define SRB_STATUS_INVALID_LUN 0x20 +#define SRB_STATUS_INVALID_TARGET_ID 0x21 +#define SRB_STATUS_BAD_FUNCTION 0x22 +#define SRB_STATUS_ERROR_RECOVERY 0x23 + + +/* SRB Status Masks */ + +#define SRB_STATUS_QUEUE_FROZEN 0x40 +#define SRB_STATUS_AUTOSENSE_VALID 0x80 + +#define SRB_STATUS(Status) (Status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) + + +/* SRB Flag Bits */ + +#define SRB_FLAGS_QUEUE_ACTION_ENABLE 0x00000002 +#define SRB_FLAGS_DISABLE_DISCONNECT 0x00000004 +#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER 0x00000008 +#define SRB_FLAGS_BYPASS_FROZEN_QUEUE 0x00000010 +#define SRB_FLAGS_DISABLE_AUTOSENSE 0x00000020 +#define SRB_FLAGS_DATA_IN 0x00000040 +#define SRB_FLAGS_DATA_OUT 0x00000080 +#define SRB_FLAGS_NO_DATA_TRANSFER 0x00000000 +#define SRB_FLAGS_UNSPECIFIED_DIRECTION (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT) +#define SRB_FLAGS_NO_QUEUE_FREEZE 0x00000100 +#define SRB_FLAGS_ADAPTER_CACHE_ENABLE 0x00000200 +#define SRB_FLAGS_IS_ACTIVE 0x00010000 +#define SRB_FLAGS_ALLOCATED_FROM_ZONE 0x00020000 +#define SRB_FLAGS_SGLIST_FROM_POOL 0x00040000 + + +/* Queue Action */ + +#define SRB_SIMPLE_TAG_REQUEST 0x20 +#define SRB_HEAD_OF_QUEUE_TAG_REQUEST 0x21 +#define SRB_ORDERED_QUEUE_TAG_REQUEST 0x22 + + +/* Port driver error codes */ + +#define SP_BUS_PARITY_ERROR 0x0001 +#define SP_UNEXPECTED_DISCONNECT 0x0002 +#define SP_INVALID_RESELECTION 0x0003 +#define SP_BUS_TIME_OUT 0x0004 +#define SP_PROTOCOL_ERROR 0x0005 +#define SP_INTERNAL_ADAPTER_ERROR 0x0006 +#define SP_REQUEST_TIMEOUT 0x0007 +#define SP_IRQ_NOT_RESPONDING 0x0008 +#define SP_BAD_FW_WARNING 0x0009 +#define SP_BAD_FW_ERROR 0x000a + + +/* Return values for SCSI_HW_FIND_ADAPTER. */ + +#define SP_RETURN_NOT_FOUND 0 +#define SP_RETURN_FOUND 1 +#define SP_RETURN_ERROR 2 +#define SP_RETURN_BAD_CONFIG 3 + + +typedef enum _SCSI_NOTIFICATION_TYPE +{ + RequestComplete, + NextRequest, + NextLuRequest, + ResetDetected, + CallDisableInterrupts, + CallEnableInterrupts, + RequestTimerCall +} SCSI_NOTIFICATION_TYPE, *PSCSI_NOTIFICATION_TYPE; + + +typedef BOOLEAN STDCALL +(*PHW_INITIALIZE)(IN PVOID DeviceExtension); + +typedef BOOLEAN STDCALL +(*PHW_STARTIO)(IN PVOID DeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb); + +typedef BOOLEAN STDCALL +(*PHW_INTERRUPT)(IN PVOID DeviceExtension); + +typedef VOID STDCALL +(*PHW_TIMER)(IN PVOID DeviceExtension); + +typedef VOID STDCALL +(*PHW_DMA_STARTED)(IN PVOID DeviceExtension); + +typedef ULONG STDCALL +(*PHW_FIND_ADAPTER)(IN PVOID DeviceExtension, + IN PVOID HwContext, + IN PVOID BusInformation, + IN PCHAR ArgumentString, + IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, + OUT PBOOLEAN Again); + +typedef BOOLEAN STDCALL +(*PHW_RESET_BUS)(IN PVOID DeviceExtension, + IN ULONG PathId); + +typedef BOOLEAN STDCALL +(*PHW_ADAPTER_STATE)(IN PVOID DeviceExtension, + IN PVOID Context, + IN BOOLEAN SaveState); + +typedef struct _HW_INITIALIZATION_DATA +{ + ULONG HwInitializationDataSize; + INTERFACE_TYPE AdapterInterfaceType; + PHW_INITIALIZE HwInitialize; + PHW_STARTIO HwStartIo; + PHW_INTERRUPT HwInterrupt; + PHW_FIND_ADAPTER HwFindAdapter; + PHW_RESET_BUS HwResetBus; + PHW_DMA_STARTED HwDmaStarted; + PHW_ADAPTER_STATE HwAdapterState; + ULONG DeviceExtensionSize; + ULONG SpecificLuExtensionSize; + ULONG SrbExtensionSize; + ULONG NumberOfAccessRanges; + PVOID Reserved; + BOOLEAN MapBuffers; + BOOLEAN NeedPhysicalAddresses; + BOOLEAN TaggedQueuing; + BOOLEAN AutoRequestSense; + BOOLEAN MultipleRequestPerLu; + BOOLEAN ReceiveEvent; + USHORT VendorIdLength; + PVOID VendorId; + USHORT ReservedUshort; + USHORT DeviceIdLength; + PVOID DeviceId; +} HW_INITIALIZATION_DATA, *PHW_INITIALIZATION_DATA; + + +/* FUNCTIONS ****************************************************************/ + +VOID +ScsiDebugPrint(IN ULONG DebugPrintLevel, + IN PCHAR DebugMessage, + ...); + +VOID STDCALL +ScsiPortCompleteRequest(IN PVOID HwDeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN UCHAR SrbStatus); + +ULONG STDCALL +ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address); + +SCSI_PHYSICAL_ADDRESS STDCALL +ScsiPortConvertUlongToPhysicalAddress(IN ULONG UlongAddress); + +VOID STDCALL +ScsiPortFlushDma(IN PVOID HwDeviceExtension); + +VOID STDCALL +ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension, + IN PVOID MappedAddress); + +ULONG STDCALL +ScsiPortGetBusData(IN PVOID DeviceExtension, + IN ULONG BusDataType, + IN ULONG SystemIoBusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length); + +PVOID STDCALL +ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension, + IN INTERFACE_TYPE BusType, + IN ULONG SystemIoBusNumber, + IN SCSI_PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfBytes, + IN BOOLEAN InIoSpace); + +PVOID STDCALL +ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun); + +SCSI_PHYSICAL_ADDRESS STDCALL +ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, + IN PVOID VirtualAddress, + OUT PULONG Length); + +PSCSI_REQUEST_BLOCK STDCALL +ScsiPortGetSrb(IN PVOID DeviceExtension, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN LONG QueueTag); + +PVOID STDCALL +ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension, + IN PPORT_CONFIGURATION_INFORMATION ConfigInfo, + IN ULONG NumberOfBytes); + +PVOID STDCALL +ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension, + IN SCSI_PHYSICAL_ADDRESS PhysicalAddress); + +ULONG STDCALL +ScsiPortInitialize(IN PVOID Argument1, + IN PVOID Argument2, + IN struct _HW_INITIALIZATION_DATA *HwInitializationData, + IN PVOID HwContext); + +VOID STDCALL +ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb, + IN ULONG LogicalAddress, + IN ULONG Length); + +VOID STDCALL +ScsiPortLogError(IN PVOID HwDeviceExtension, + IN PSCSI_REQUEST_BLOCK Srb OPTIONAL, + IN UCHAR PathId, + IN UCHAR TargetId, + IN UCHAR Lun, + IN ULONG ErrorCode, + IN ULONG UniqueId); + +VOID STDCALL +ScsiPortMoveMemory(OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length); + +VOID +ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, + IN PVOID HwDeviceExtension, + ...); + +VOID STDCALL +ScsiPortReadPortBufferUchar(IN PUCHAR Port, + IN PUCHAR Value, + IN ULONG Count); + +VOID STDCALL +ScsiPortReadPortBufferUlong(IN PULONG Port, + IN PULONG Value, + IN ULONG Count); + +VOID STDCALL +ScsiPortReadPortBufferUshort(IN PUSHORT Port, + IN PUSHORT Value, + IN ULONG Count); + +UCHAR STDCALL +ScsiPortReadPortUchar(IN PUCHAR Port); + +ULONG STDCALL +ScsiPortReadPortUlong(IN PULONG Port); + +USHORT STDCALL +ScsiPortReadPortUshort(IN PUSHORT Port); + +VOID STDCALL +ScsiPortReadRegisterBufferUchar(IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortReadRegisterBufferUlong(IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortReadRegisterBufferUshort(IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count); + +UCHAR STDCALL +ScsiPortReadRegisterUchar(IN PUCHAR Register); + +ULONG STDCALL +ScsiPortReadRegisterUlong(IN PULONG Register); + +USHORT STDCALL +ScsiPortReadRegisterUshort(IN PUSHORT Register); + +ULONG STDCALL +ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension, + IN ULONG BusDataType, + IN ULONG SystemIoBusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length); + +VOID STDCALL +ScsiPortStallExecution(IN ULONG MicroSeconds); + +BOOLEAN STDCALL +ScsiPortValidateRange(IN PVOID HwDeviceExtension, + IN INTERFACE_TYPE BusType, + IN ULONG SystemIoBusNumber, + IN SCSI_PHYSICAL_ADDRESS IoAddress, + IN ULONG NumberOfBytes, + IN BOOLEAN InIoSpace); + +VOID STDCALL +ScsiPortWritePortBufferUchar(IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortWritePortBufferUlong(IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortWritePortBufferUshort(IN PUSHORT Port, + IN PUSHORT Value, + IN ULONG Count); + +VOID STDCALL +ScsiPortWritePortUchar(IN PUCHAR Port, + IN UCHAR Value); + +VOID STDCALL +ScsiPortWritePortUlong(IN PULONG Port, + IN ULONG Value); + +VOID STDCALL +ScsiPortWritePortUshort(IN PUSHORT Port, + IN USHORT Value); + +VOID STDCALL +ScsiPortWriteRegisterBufferUchar(IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortWriteRegisterBufferUlong(IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortWriteRegisterBufferUshort(IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count); + +VOID STDCALL +ScsiPortWriteRegisterUchar(IN PUCHAR Register, + IN ULONG Value); + +VOID STDCALL +ScsiPortWriteRegisterUlong(IN PULONG Register, + IN ULONG Value); + +VOID STDCALL +ScsiPortWriteRegisterUshort(IN PUSHORT Register, + IN USHORT Value); + +#endif /* __STORAGE_INCLUDE_SRB_H */ + +/* EOF */ diff --git a/include/ddk/status.h b/include/ddk/status.h new file mode 100644 index 0000000..81edfb9 --- /dev/null +++ b/include/ddk/status.h @@ -0,0 +1,713 @@ +#ifndef __INCLUDE_DDK_STATUS_H +#define __INCLUDE_DDK_STATUS_H + +#define NTSTAT_SEVERITY_SHIFT 30 +#define NTSTAT_SEVERITY_MASK 0x00000003 +#define NTSTAT_FACILITY_SHIFT 16 +#define NTSTAT_FACILITY_MASK 0x00000FFF +#define NTSTAT_CUSTOMER_MASK 0x20000000 + +#define NT_SEVERITY(StatCode) (((StatCode) >> NTSTAT_SEVERITY_SHIFT) & NTSTAT_SEVERITY_MASK) +#define NT_FACILITY(StatCode) (((StatCode) >> NTSTAT_FACILITY_SHIFT) & NTSTAT_FACILITY_MASK) +#define NT_CUSTOMER(StatCode) ((StatCode) & NTSTAT_CUSTOMER_MASK) +#define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode) >= 0) + +/* + * Possible status codes + * FIXME: These may not be the actual values used by NT + */ + +#define STATUS_SUCCESS (0x00000000) +#ifndef STATUS_WAIT_0 +#define STATUS_WAIT_0 (0x00000000) +#endif +#define STATUS_WAIT_63 (0x0000003F) +#define STATUS_ABANDONED (0x00000080) +#ifndef STATUS_ABANDONED_WAIT_0 +#define STATUS_ABANDONED_WAIT_0 (0x00000080) +#endif +#define STATUS_ABANDONED_WAIT_63 (0x000000BF) +#ifndef STATUS_USER_APC +#define STATUS_USER_APC (0x000000C0) +#endif +#define STATUS_KERNEL_APC (0x00000100) +#define STATUS_ALERTED (0x00000101) +#ifndef STATUS_TIMEOUT +#define STATUS_TIMEOUT (0x00000102) +#endif +#ifndef STATUS_PENDING +#define STATUS_PENDING (0x00000103) +#endif +#define STATUS_REPARSE (0x00000104) +#define STATUS_MORE_ENTRIES (0x00000105) +#define STATUS_NOT_ALL_ASSIGNED (0x00000106) +#define STATUS_SOME_NOT_MAPPED (0x00000107) +#define STATUS_OPLOCK_BREAK_IN_PROCESS (0x00000108) +#define STATUS_VOLUME_MOUNTED (0x00000109) +#define STATUS_RXACT_COMMITTED (0x0000010A) +#define STATUS_NOTIFY_CLEANUP (0x0000010B) +#define STATUS_NOTIFY_ENUM_DIR (0x0000010C) +#define STATUS_NO_QUOTAS_NO_ACCOUNT (0x0000010D) +#define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED (0x0000010E) + +#define STATUS_OBJECT_EXISTS (0x40000000) +#define STATUS_THREAD_WAS_SUSPENDED (0x40000001) +#define STATUS_WORKING_SET_LIMIT_RANGE (0x40000002) +#define STATUS_IMAGE_NOT_AT_BASE (0x40000003) +#define STATUS_RXACT_STATE_CREATED (0x40000004) +#define STATUS_SEGMENT_NOTIFICATION (0x40000005) +#define STATUS_LOCAL_USER_SESSION_KEY (0x40000006) +#define STATUS_BAD_CURRENT_DIRECTORY (0x40000007) +#define STATUS_SERIAL_MORE_WRITES (0x40000008) +#define STATUS_REGISTRY_RECOVERED (0x40000009) +#define STATUS_FT_READ_RECOVERING_FROM_BACKUP (0x4000000A) +#define STATUS_FT_WRITE_RECOVERY (0x4000000B) +#define STATUS_SERIAL_COUNTER_TIMEOUT (0x4000000C) +#define STATUS_NULL_LM_PASSWORD (0x4000000D) +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH (0x4000000E) +#define STATUS_RECEIVE_PARTIAL (0x4000000F) +#define STATUS_RECEIVE_EXPEDITED (0x40000010) +#define STATUS_RECEIVE_PARTIAL_EXPEDITED (0x40000011) +#define STATUS_EVENT_DONE (0x40000012) +#define STATUS_EVENT_PENDING (0x40000013) +#define STATUS_CHECKING_FILE_SYSTEM (0x40000014) +#define STATUS_FATAL_APP_EXIT (0x40000015) +#define STATUS_PREDEFINED_HANDLE (0x40000016) +#define STATUS_WAS_UNLOCKED (0x40000017) +#define STATUS_SERVICE_NOTIFICATION (0x40000018) +#define STATUS_WAS_LOCKED (0x40000019) +#define STATUS_LOG_HARD_ERROR (0x4000001A) +#define STATUS_ALREADY_WIN32 (0x4000001B) +#define STATUS_WX86_UNSIMULATE (0x4000001C) +#define STATUS_WX86_CONTINUE (0x4000001D) +#define STATUS_WX86_SINGLE_STEP (0x4000001E) +#define STATUS_WX86_BREAKPOINT (0x4000001F) +#define STATUS_WX86_EXCEPTION_CONTINUE (0x40000020) +#define STATUS_WX86_EXCEPTION_LASTCHANCE (0x40000021) +#define STATUS_WX86_EXCEPTION_CHAIN (0x40000022) +#define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE (0x40000023) +#define STATUS_NO_YIELD_PERFORMED (0x40000024) +#define STATUS_TIMER_RESUME_IGNORED (0x40000025) +#define STATUS_ARBITRATION_UNHANDLED (0x40000026) +#define STATUS_CARDBUS_NOT_SUPPORTED (0x40000027) +#define STATUS_WX86_CREATEWX86TIB (0x40000028) + +#define STATUS_GUARD_PAGE_VIOLATION (0x80000001) +#define STATUS_DATATYPE_MISALIGNMENT (0x80000002) +#define STATUS_BREAKPOINT (0x80000003) +#define STATUS_SINGLE_STEP (0x80000004) +#define STATUS_BUFFER_OVERFLOW (0x80000005) +#define STATUS_NO_MORE_FILES (0x80000006) +#define STATUS_WAKE_SYSTEM_DEBUGGER (0x80000007) + +#define STATUS_HANDLES_CLOSED (0x8000000A) +#define STATUS_NO_INHERITANCE (0x8000000B) +#define STATUS_GUID_SUBSTITUTION_MADE (0x8000000C) +#define STATUS_PARTIAL_COPY (0x8000000D) +#define STATUS_DEVICE_PAPER_EMPTY (0x8000000E) +#define STATUS_DEVICE_POWERED_OFF (0x8000000F) +#define STATUS_DEVICE_OFF_LINE (0x80000010) +#define STATUS_DEVICE_BUSY (0x80000011) +#define STATUS_NO_MORE_EAS (0x80000012) +#define STATUS_INVALID_EA_NAME (0x80000013) +#define STATUS_EA_LIST_INCONSISTENT (0x80000014) +#define STATUS_INVALID_EA_FLAG (0x80000015) +#define STATUS_VERIFY_REQUIRED (0x80000016) +#define STATUS_EXTRANEOUS_INFORMATION (0x80000017) +#define STATUS_RXACT_COMMIT_NECESSARY (0x80000018) + +#define STATUS_NO_MORE_ENTRIES (0x8000001A) +#define STATUS_FILEMARK_DETECTED (0x8000001B) +#define STATUS_MEDIA_CHANGED (0x8000001C) +#define STATUS_BUS_RESET (0x8000001D) +#define STATUS_END_OF_MEDIA (0x8000001E) +#define STATUS_BEGINNING_OF_MEDIA (0x8000001F) +#define STATUS_MEDIA_CHECK (0x80000020) +#define STATUS_SETMARK_DETECTED (0x80000021) +#define STATUS_NO_DATA_DETECTED (0x80000022) +#define STATUS_REDIRECTOR_HAS_OPEN_HANDLES (0x80000023) +#define STATUS_SERVER_HAS_OPEN_HANDLES (0x80000024) +#define STATUS_ALREADY_DISCONNECTED (0x80000025) +#define STATUS_LONGJUMP (0x80000026) + +#define STATUS_UNSUCCESSFUL (0xc0000001) +#define STATUS_NOT_IMPLEMENTED (0xc0000002) +#define STATUS_INVALID_INFO_CLASS (0xc0000003) +#define STATUS_INFO_LENGTH_MISMATCH (0xc0000004) +#define STATUS_ACCESS_VIOLATION (0xc0000005) +#define STATUS_IN_PAGE_ERROR (0xc0000006) +#define STATUS_PAGEFILE_QUOTA (0xc0000007) +#define STATUS_INVALID_HANDLE (0xc0000008) +#define STATUS_BAD_INITIAL_STACK (0xc0000009) +#define STATUS_BAD_INITIAL_PC (0xc000000a) +#define STATUS_INVALID_CID (0xc000000b) +#define STATUS_TIMER_NOT_CANCELED (0xc000000c) +#define STATUS_INVALID_PARAMETER (0xc000000d) +#define STATUS_NO_SUCH_DEVICE (0xc000000e) +#define STATUS_NO_SUCH_FILE (0xc000000f) +#define STATUS_INVALID_DEVICE_REQUEST (0xc0000010) +#define STATUS_END_OF_FILE (0xc0000011) +#define STATUS_WRONG_VOLUME (0xc0000012) +#define STATUS_NO_MEDIA_IN_DEVICE (0xc0000013) +#define STATUS_UNRECOGNIZED_MEDIA (0xc0000014) +#define STATUS_NONEXISTENT_SECTOR (0xc0000015) +#define STATUS_MORE_PROCESSING_REQUIRED (0xc0000016) +#define STATUS_NO_MEMORY (0xc0000017) +#define STATUS_CONFLICTING_ADDRESSES (0xc0000018) +#define STATUS_NOT_MAPPED_VIEW (0xc0000019) +#define STATUS_UNABLE_TO_FREE_VM (0xc000001a) +#define STATUS_UNABLE_TO_DELETE_SECTION (0xc000001b) +#define STATUS_INVALID_SYSTEM_SERVICE (0xc000001c) +#define STATUS_ILLEGAL_INSTRUCTION (0xc000001d) +#define STATUS_INVALID_LOCK_SEQUENCE (0xc000001e) +#define STATUS_INVALID_VIEW_SIZE (0xc000001f) +#define STATUS_INVALID_FILE_FOR_SECTION (0xc0000020) +#define STATUS_ALREADY_COMMITTED (0xc0000021) +#define STATUS_ACCESS_DENIED (0xc0000022) +#define STATUS_BUFFER_TOO_SMALL (0xc0000023) +#define STATUS_OBJECT_TYPE_MISMATCH (0xc0000024) +#define STATUS_NONCONTINUABLE_EXCEPTION (0xc0000025) +#define STATUS_INVALID_DISPOSITION (0xc0000026) +#define STATUS_UNWIND (0xc0000027) +#define STATUS_BAD_STACK (0xc0000028) +#define STATUS_INVALID_UNWIND_TARGET (0xc0000029) +#define STATUS_NOT_LOCKED (0xc000002a) +#define STATUS_PARITY_ERROR (0xc000002b) +#define STATUS_UNABLE_TO_DECOMMIT_VM (0xc000002c) +#define STATUS_NOT_COMMITTED (0xc000002d) +#define STATUS_INVALID_PORT_ATTRIBUTES (0xc000002e) +#define STATUS_PORT_MESSAGE_TOO_LONG (0xc000002f) +#define STATUS_INVALID_PARAMETER_MIX (0xc0000030) +#define STATUS_INVALID_QUOTA_LOWER (0xc0000031) +#define STATUS_DISK_CORRUPT_ERROR (0xc0000032) +#define STATUS_OBJECT_NAME_INVALID (0xc0000033) +#define STATUS_OBJECT_NAME_NOT_FOUND (0xc0000034) +#define STATUS_OBJECT_NAME_COLLISION (0xc0000035) +#define STATUS_OBJECT_NAME_EXISTS (0x40000000) + + +#define STATUS_PORT_DISCONNECTED (0xc0000037) +#define STATUS_DEVICE_ALREADY_ATTACHED (0xc0000038) +#define STATUS_OBJECT_PATH_INVALID (0xc0000039) +#define STATUS_OBJECT_PATH_NOT_FOUND (0xc000003a) +#define STATUS_PATH_SYNTAX_BAD (0xc000003b) +#define STATUS_DATA_OVERRUN (0xc000003c) +#define STATUS_DATA_LATE_ERROR (0xc000003d) +#define STATUS_DATA_ERROR (0xc000003e) +#define STATUS_CRC_ERROR (0xc000003f) +#define STATUS_SECTION_TOO_BIG (0xc0000040) +#define STATUS_PORT_CONNECTION_REFUSED (0xc0000041) +#define STATUS_INVALID_PORT_HANDLE (0xc0000042) +#define STATUS_SHARING_VIOLATION (0xc0000043) +#define STATUS_QUOTA_EXCEEDED (0xc0000044) +#define STATUS_INVALID_PAGE_PROTECTION (0xc0000045) +#define STATUS_MUTANT_NOT_OWNED (0xc0000046) +#define STATUS_SEMAPHORE_LIMIT_EXCEEDED (0xc0000047) +#define STATUS_PORT_ALREADY_SET (0xc0000048) +#define STATUS_SECTION_NOT_IMAGE (0xc0000049) +#define STATUS_SUSPEND_COUNT_EXCEEDED (0xc000004a) +#define STATUS_THREAD_IS_TERMINATING (0xc000004b) +#define STATUS_BAD_WORKING_SET_LIMIT (0xc000004c) +#define STATUS_INCOMPATIBLE_FILE_MAP (0xc000004d) +#define STATUS_SECTION_PROTECTION (0xc000004e) +#define STATUS_EAS_NOT_SUPPORTED (0xc000004f) +#define STATUS_EA_TOO_LARGE (0xc0000050) +#define STATUS_NONEXISTENT_EA_ENTRY (0xc0000051) +#define STATUS_NO_EAS_ON_FILE (0xc0000052) +#define STATUS_EA_CORRUPT_ERROR (0xc0000053) +#define STATUS_FILE_LOCK_CONFLICT (0xc0000054) +#define STATUS_LOCK_NOT_GRANTED (0xc0000055) +#define STATUS_DELETE_PENDING (0xc0000056) +#define STATUS_CTL_FILE_NOT_SUPPORTED (0xc0000057) +#define STATUS_UNKNOWN_REVISION (0xc0000058) +#define STATUS_REVISION_MISMATCH (0xc0000059) +#define STATUS_INVALID_OWNER (0xc000005a) +#define STATUS_INVALID_PRIMARY_GROUP (0xc000005b) +#define STATUS_NO_IMPERSONATION_TOKEN (0xc000005c) +#define STATUS_CANT_DISABLE_MANDATORY (0xc000005d) +#define STATUS_NO_LOGON_SERVERS (0xc000005e) +#define STATUS_NO_SUCH_LOGON_SESSION (0xc000005f) +#define STATUS_NO_SUCH_PRIVILEGE (0xc0000060) +#define STATUS_PRIVILEGE_NOT_HELD (0xc0000061) +#define STATUS_INVALID_ACCOUNT_NAME (0xc0000062) +#define STATUS_USER_EXISTS (0xc0000063) +#define STATUS_NO_SUCH_USER (0xc0000064) +#define STATUS_GROUP_EXISTS (0xc0000065) +#define STATUS_NO_SUCH_GROUP (0xc0000066) +#define STATUS_MEMBER_IN_GROUP (0xc0000067) +#define STATUS_MEMBER_NOT_IN_GROUP (0xc0000068) +#define STATUS_LAST_ADMIN (0xc0000069) +#define STATUS_WRONG_PASSWORD (0xc000006a) +#define STATUS_ILL_FORMED_PASSWORD (0xc000006b) +#define STATUS_PASSWORD_RESTRICTION (0xc000006c) +#define STATUS_LOGON_FAILURE (0xc000006d) +#define STATUS_ACCOUNT_RESTRICTION (0xc000006e) +#define STATUS_INVALID_LOGON_HOURS (0xc000006f) +#define STATUS_INVALID_WORKSTATION (0xc0000070) +#define STATUS_PASSWORD_EXPIRED (0xc0000071) +#define STATUS_ACCOUNT_DISABLED (0xc0000072) +#define STATUS_NONE_MAPPED (0xc0000073) +#define STATUS_TOO_MANY_LUIDS_REQUESTED (0xc0000074) +#define STATUS_LUIDS_EXHAUSTED (0xc0000075) +#define STATUS_INVALID_SUB_AUTHORITY (0xc0000076) +#define STATUS_INVALID_ACL (0xc0000077) +#define STATUS_INVALID_SID (0xc0000078) +#define STATUS_INVALID_SECURITY_DESCR (0xc0000079) +#define STATUS_PROCEDURE_NOT_FOUND (0xc000007a) +#define STATUS_INVALID_IMAGE_FORMAT (0xc000007b) +#define STATUS_NO_TOKEN (0xc000007c) +#define STATUS_BAD_INHERITANCE_ACL (0xc000007d) +#define STATUS_RANGE_NOT_LOCKED (0xc000007e) +#define STATUS_DISK_FULL (0xc000007f) +#define STATUS_SERVER_DISABLED (0xc0000080) +#define STATUS_SERVER_NOT_DISABLED (0xc0000081) +#define STATUS_TOO_MANY_GUIDS_REQUESTED (0xc0000082) +#define STATUS_GUIDS_EXHAUSTED (0xc0000083) +#define STATUS_INVALID_ID_AUTHORITY (0xc0000084) +#define STATUS_AGENTS_EXHAUSTED (0xc0000085) +#define STATUS_INVALID_VOLUME_LABEL (0xc0000086) +#define STATUS_SECTION_NOT_EXTENDED (0xc0000087) +#define STATUS_NOT_MAPPED_DATA (0xc0000088) +#define STATUS_RESOURCE_DATA_NOT_FOUND (0xc0000089) +#define STATUS_RESOURCE_TYPE_NOT_FOUND (0xc000008a) +#define STATUS_RESOURCE_NAME_NOT_FOUND (0xc000008b) +#define STATUS_ARRAY_BOUNDS_EXCEEDED (0xc000008c) +#define STATUS_FLOAT_DENORMAL_OPERAND (0xc000008d) +#define STATUS_FLOAT_DIVIDE_BY_ZERO (0xc000008e) +#define STATUS_FLOAT_INEXACT_RESULT (0xc000008f) +#define STATUS_FLOAT_INVALID_OPERATION (0xc0000090) +#define STATUS_FLOAT_OVERFLOW (0xc0000091) +#define STATUS_FLOAT_STACK_CHECK (0xc0000092) +#define STATUS_FLOAT_UNDERFLOW (0xc0000093) +#define STATUS_INTEGER_DIVIDE_BY_ZERO (0xc0000094) +#define STATUS_INTEGER_OVERFLOW (0xc0000095) +#define STATUS_PRIVILEGED_INSTRUCTION (0xc0000096) +#define STATUS_TOO_MANY_PAGING_FILES (0xc0000097) +#define STATUS_FILE_INVALID (0xc0000098) +#define STATUS_ALLOTTED_SPACE_EXCEEDED (0xc0000099) +#define STATUS_INSUFFICIENT_RESOURCES (0xc000009a) +#define STATUS_DFS_EXIT_PATH_FOUND (0xc000009b) +#define STATUS_DEVICE_DATA_ERROR (0xc000009c) +#define STATUS_DEVICE_NOT_CONNECTED (0xc000009d) +#define STATUS_DEVICE_POWER_FAILURE (0xc000009e) +#define STATUS_FREE_VM_NOT_AT_BASE (0xc000009f) +#define STATUS_MEMORY_NOT_ALLOCATED (0xc00000a0) +#define STATUS_WORKING_SET_QUOTA (0xc00000a1) +#define STATUS_MEDIA_WRITE_PROTECTED (0xc00000a2) +#define STATUS_DEVICE_NOT_READY (0xc00000a3) +#define STATUS_INVALID_GROUP_ATTRIBUTES (0xc00000a4) +#define STATUS_BAD_IMPERSONATION_LEVEL (0xc00000a5) +#define STATUS_CANT_OPEN_ANONYMOUS (0xc00000a6) +#define STATUS_BAD_VALIDATION_CLASS (0xc00000a7) +#define STATUS_BAD_TOKEN_TYPE (0xc00000a8) +#define STATUS_BAD_MASTER_BOOT_RECORD (0xc00000a9) +#define STATUS_INSTRUCTION_MISALIGNMENT (0xc00000aa) +#define STATUS_INSTANCE_NOT_AVAILABLE (0xc00000ab) +#define STATUS_PIPE_NOT_AVAILABLE (0xc00000ac) +#define STATUS_INVALID_PIPE_STATE (0xc00000ad) +#define STATUS_PIPE_BUSY (0xc00000ae) +#define STATUS_ILLEGAL_FUNCTION (0xc00000af) +#define STATUS_PIPE_DISCONNECTED (0xc00000b0) +#define STATUS_PIPE_CLOSING (0xc00000b1) +#define STATUS_PIPE_CONNECTED (0xc00000b2) +#define STATUS_PIPE_LISTENING (0xc00000b3) +#define STATUS_INVALID_READ_MODE (0xc00000b4) +#define STATUS_IO_TIMEOUT (0xc00000b5) +#define STATUS_FILE_FORCED_CLOSED (0xc00000b6) +#define STATUS_PROFILING_NOT_STARTED (0xc00000b7) +#define STATUS_PROFILING_NOT_STOPPED (0xc00000b8) +#define STATUS_COULD_NOT_INTERPRET (0xc00000b9) +#define STATUS_FILE_IS_A_DIRECTORY (0xc00000ba) +#define STATUS_NOT_SUPPORTED (0xc00000bb) +#define STATUS_REMOTE_NOT_LISTENING (0xc00000bc) +#define STATUS_DUPLICATE_NAME (0xc00000bd) +#define STATUS_BAD_NETWORK_PATH (0xc00000be) +#define STATUS_NETWORK_BUSY (0xc00000bf) +#define STATUS_DEVICE_DOES_NOT_EXIST (0xc00000c0) +#define STATUS_TOO_MANY_COMMANDS (0xc00000c1) +#define STATUS_ADAPTER_HARDWARE_ERROR (0xc00000c2) +#define STATUS_INVALID_NETWORK_RESPONSE (0xc00000c3) +#define STATUS_UNEXPECTED_NETWORK_ERROR (0xc00000c4) +#define STATUS_BAD_REMOTE_ADAPTER (0xc00000c5) +#define STATUS_PRINT_QUEUE_FULL (0xc00000c6) +#define STATUS_NO_SPOOL_SPACE (0xc00000c7) +#define STATUS_PRINT_CANCELLED (0xc00000c8) +#define STATUS_NETWORK_NAME_DELETED (0xc00000c9) +#define STATUS_NETWORK_ACCESS_DENIED (0xc00000ca) +#define STATUS_BAD_DEVICE_TYPE (0xc00000cb) +#define STATUS_BAD_NETWORK_NAME (0xc00000cc) +#define STATUS_TOO_MANY_NAMES (0xc00000cd) +#define STATUS_TOO_MANY_SESSIONS (0xc00000ce) +#define STATUS_SHARING_PAUSED (0xc00000cf) +#define STATUS_REQUEST_NOT_ACCEPTED (0xc00000d0) +#define STATUS_REDIRECTOR_PAUSED (0xc00000d1) +#define STATUS_NET_WRITE_FAULT (0xc00000d2) +#define STATUS_PROFILING_AT_LIMIT (0xc00000d3) +#define STATUS_NOT_SAME_DEVICE (0xc00000d4) +#define STATUS_FILE_RENAMED (0xc00000d5) +#define STATUS_VIRTUAL_CIRCUIT_CLOSED (0xc00000d6) +#define STATUS_NO_SECURITY_ON_OBJECT (0xc00000d7) +#define STATUS_CANT_WAIT (0xc00000d8) +#define STATUS_PIPE_EMPTY (0xc00000d9) +#define STATUS_CANT_ACCESS_DOMAIN_INFO (0xc00000da) +#define STATUS_CANT_TERMINATE_SELF (0xc00000db) +#define STATUS_INVALID_SERVER_STATE (0xc00000dc) +#define STATUS_INVALID_DOMAIN_STATE (0xc00000dd) +#define STATUS_INVALID_DOMAIN_ROLE (0xc00000de) +#define STATUS_NO_SUCH_DOMAIN (0xc00000df) +#define STATUS_DOMAIN_EXISTS (0xc00000e0) +#define STATUS_DOMAIN_LIMIT_EXCEEDED (0xc00000e1) +#define STATUS_OPLOCK_NOT_GRANTED (0xc00000e2) +#define STATUS_INVALID_OPLOCK_PROTOCOL (0xc00000e3) +#define STATUS_INTERNAL_DB_CORRUPTION (0xc00000e4) +#define STATUS_INTERNAL_ERROR (0xc00000e5) +#define STATUS_GENERIC_NOT_MAPPED (0xc00000e6) +#define STATUS_BAD_DESCRIPTOR_FORMAT (0xc00000e7) +#define STATUS_INVALID_USER_BUFFER (0xc00000e8) +#define STATUS_UNEXPECTED_IO_ERROR (0xc00000e9) +#define STATUS_UNEXPECTED_MM_CREATE_ERR (0xc00000ea) +#define STATUS_UNEXPECTED_MM_MAP_ERROR (0xc00000eb) +#define STATUS_UNEXPECTED_MM_EXTEND_ERR (0xc00000ec) +#define STATUS_NOT_LOGON_PROCESS (0xc00000ed) +#define STATUS_LOGON_SESSION_EXISTS (0xc00000ee) +#define STATUS_INVALID_PARAMETER_1 (0xc00000ef) +#define STATUS_INVALID_PARAMETER_2 (0xc00000f0) +#define STATUS_INVALID_PARAMETER_3 (0xc00000f1) +#define STATUS_INVALID_PARAMETER_4 (0xc00000f2) +#define STATUS_INVALID_PARAMETER_5 (0xc00000f3) +#define STATUS_INVALID_PARAMETER_6 (0xc00000f4) +#define STATUS_INVALID_PARAMETER_7 (0xc00000f5) +#define STATUS_INVALID_PARAMETER_8 (0xc00000f6) +#define STATUS_INVALID_PARAMETER_9 (0xc00000f7) +#define STATUS_INVALID_PARAMETER_10 (0xc00000f8) +#define STATUS_INVALID_PARAMETER_11 (0xc00000f9) +#define STATUS_INVALID_PARAMETER_12 (0xc00000fa) +#define STATUS_REDIRECTOR_NOT_STARTED (0xc00000fb) +#define STATUS_REDIRECTOR_STARTED (0xc00000fc) +#define STATUS_STACK_OVERFLOW (0xc00000fd) +#define STATUS_NO_SUCH_PACKAGE (0xc00000fe) +#define STATUS_BAD_FUNCTION_TABLE (0xc00000ff) +#define STATUS_VARIABLE_NOT_FOUND (0xc0000100) +#define STATUS_DIRECTORY_NOT_EMPTY (0xc0000101) +#define STATUS_FILE_CORRUPT_ERROR (0xc0000102) +#define STATUS_NOT_A_DIRECTORY (0xc0000103) +#define STATUS_BAD_LOGON_SESSION_STATE (0xc0000104) +#define STATUS_LOGON_SESSION_COLLISION (0xc0000105) +#define STATUS_NAME_TOO_LONG (0xc0000106) +#define STATUS_FILES_OPEN (0xc0000107) +#define STATUS_CONNECTION_IN_USE (0xc0000108) +#define STATUS_MESSAGE_NOT_FOUND (0xc0000109) +#define STATUS_PROCESS_IS_TERMINATING (0xc000010a) +#define STATUS_INVALID_LOGON_TYPE (0xc000010b) +#define STATUS_NO_GUID_TRANSLATION (0xc000010c) +#define STATUS_CANNOT_IMPERSONATE (0xc000010d) +#define STATUS_IMAGE_ALREADY_LOADED (0xc000010e) +#define STATUS_ABIOS_NOT_PRESENT (0xc000010f) +#define STATUS_ABIOS_LID_NOT_EXIST (0xc0000110) +#define STATUS_ABIOS_LID_ALREADY_OWNED (0xc0000111) +#define STATUS_ABIOS_NOT_LID_OWNER (0xc0000112) +#define STATUS_ABIOS_INVALID_COMMAND (0xc0000113) +#define STATUS_ABIOS_INVALID_LID (0xc0000114) +#define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (0xc0000115) +#define STATUS_ABIOS_INVALID_SELECTOR (0xc0000116) +#define STATUS_NO_LDT (0xc0000117) +#define STATUS_INVALID_LDT_SIZE (0xc0000118) +#define STATUS_INVALID_LDT_OFFSET (0xc0000119) +#define STATUS_INVALID_LDT_DESCRIPTOR (0xc000011a) +#define STATUS_INVALID_IMAGE_NE_FORMAT (0xc000011b) +#define STATUS_RXACT_INVALID_STATE (0xc000011c) +#define STATUS_RXACT_COMMIT_FAILURE (0xc000011d) +#define STATUS_MAPPED_FILE_SIZE_ZERO (0xc000011e) +#define STATUS_TOO_MANY_OPENED_FILES (0xc000011f) +#define STATUS_CANCELLED (0xc0000120) +#define STATUS_CANNOT_DELETE (0xc0000121) +#define STATUS_INVALID_COMPUTER_NAME (0xc0000122) +#define STATUS_FILE_DELETED (0xc0000123) +#define STATUS_SPECIAL_ACCOUNT (0xc0000124) +#define STATUS_SPECIAL_GROUP (0xc0000125) +#define STATUS_SPECIAL_USER (0xc0000126) +#define STATUS_MEMBERS_PRIMARY_GROUP (0xc0000127) +#define STATUS_FILE_CLOSED (0xc0000128) +#define STATUS_TOO_MANY_THREADS (0xc0000129) +#define STATUS_THREAD_NOT_IN_PROCESS (0xc000012a) +#define STATUS_TOKEN_ALREADY_IN_USE (0xc000012b) +#define STATUS_PAGEFILE_QUOTA_EXCEEDED (0xc000012c) +#define STATUS_COMMITMENT_LIMIT (0xc000012d) +#define STATUS_INVALID_IMAGE_LE_FORMAT (0xc000012e) +#define STATUS_INVALID_IMAGE_NOT_MZ (0xc000012f) +#define STATUS_INVALID_IMAGE_PROTECT (0xc0000130) +#define STATUS_INVALID_IMAGE_WIN_16 (0xc0000131) +#define STATUS_LOGON_SERVER_CONFLICT (0xc0000132) +#define STATUS_TIME_DIFFERENCE_AT_DC (0xc0000133) +#define STATUS_SYNCHRONIZATION_REQUIRED (0xc0000134) +#define STATUS_DLL_NOT_FOUND (0xc0000135) +#define STATUS_OPEN_FAILED (0xc0000136) +#define STATUS_IO_PRIVILEGE_FAILED (0xc0000137) +#define STATUS_ORDINAL_NOT_FOUND (0xc0000138) +#define STATUS_ENTRYPOINT_NOT_FOUND (0xc0000139) +#define STATUS_CONTROL_C_EXIT (0xc000013a) +#define STATUS_LOCAL_DISCONNECT (0xc000013b) +#define STATUS_REMOTE_DISCONNECT (0xc000013c) +#define STATUS_REMOTE_RESOURCES (0xc000013d) +#define STATUS_LINK_FAILED (0xc000013e) +#define STATUS_LINK_TIMEOUT (0xc000013f) +#define STATUS_INVALID_CONNECTION (0xc0000140) +#define STATUS_INVALID_ADDRESS (0xc0000141) +#define STATUS_DLL_INIT_FAILED (0xc0000142) +#define STATUS_MISSING_SYSTEMFILE (0xc0000143) +#define STATUS_UNHANDLED_EXCEPTION (0xc0000144) +#define STATUS_APP_INIT_FAILURE (0xc0000145) +#define STATUS_PAGEFILE_CREATE_FAILED (0xc0000146) +#define STATUS_NO_PAGEFILE (0xc0000147) +#define STATUS_INVALID_LEVEL (0xc0000148) +#define STATUS_WRONG_PASSWORD_CORE (0xc0000149) +#define STATUS_ILLEGAL_FLOAT_CONTEXT (0xc000014a) +#define STATUS_PIPE_BROKEN (0xc000014b) +#define STATUS_REGISTRY_CORRUPT (0xc000014c) +#define STATUS_REGISTRY_IO_FAILED (0xc000014d) +#define STATUS_NO_EVENT_PAIR (0xc000014e) +#define STATUS_UNRECOGNIZED_VOLUME (0xc000014f) +#define STATUS_SERIAL_NO_DEVICE_INITED (0xc0000150) +#define STATUS_NO_SUCH_ALIAS (0xc0000151) +#define STATUS_MEMBER_NOT_IN_ALIAS (0xc0000152) +#define STATUS_MEMBER_IN_ALIAS (0xc0000153) +#define STATUS_ALIAS_EXISTS (0xc0000154) +#define STATUS_LOGON_NOT_GRANTED (0xc0000155) +#define STATUS_TOO_MANY_SECRETS (0xc0000156) +#define STATUS_SECRET_TOO_LONG (0xc0000157) +#define STATUS_INTERNAL_DB_ERROR (0xc0000158) +#define STATUS_FULLSCREEN_MODE (0xc0000159) +#define STATUS_TOO_MANY_CONTEXT_IDS (0xc000015a) +#define STATUS_LOGON_TYPE_NOT_GRANTED (0xc000015b) +#define STATUS_NOT_REGISTRY_FILE (0xc000015c) +#define STATUS_NT_CROSS_ENCRYPTION_REQUIRED (0xc000015d) +#define STATUS_DOMAIN_CTRLR_CONFIG_ERROR (0xc000015e) +#define STATUS_FT_MISSING_MEMBER (0xc000015f) +#define STATUS_ILL_FORMED_SERVICE_ENTRY (0xc0000160) +#define STATUS_ILLEGAL_CHARACTER (0xc0000161) +#define STATUS_UNMAPPABLE_CHARACTER (0xc0000162) +#define STATUS_UNDEFINED_CHARACTER (0xc0000163) +#define STATUS_FLOPPY_VOLUME (0xc0000164) +#define STATUS_FLOPPY_ID_MARK_NOT_FOUND (0xc0000165) +#define STATUS_FLOPPY_WRONG_CYLINDER (0xc0000166) +#define STATUS_FLOPPY_UNKNOWN_ERROR (0xc0000167) +#define STATUS_FLOPPY_BAD_REGISTERS (0xc0000168) +#define STATUS_DISK_RECALIBRATE_FAILED (0xc0000169) +#define STATUS_DISK_OPERATION_FAILED (0xc000016a) +#define STATUS_DISK_RESET_FAILED (0xc000016b) +#define STATUS_SHARED_IRQ_BUSY (0xc000016c) +#define STATUS_FT_ORPHANING (0xc000016d) +#define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT (0xc000016e) + +#define STATUS_PARTITION_FAILURE (0xc0000172) +#define STATUS_INVALID_BLOCK_LENGTH (0xc0000173) +#define STATUS_DEVICE_NOT_PARTITIONED (0xc0000174) +#define STATUS_UNABLE_TO_LOCK_MEDIA (0xc0000175) +#define STATUS_UNABLE_TO_UNLOAD_MEDIA (0xc0000176) +#define STATUS_EOM_OVERFLOW (0xc0000177) +#define STATUS_NO_MEDIA (0xc0000178) + +#define STATUS_NO_SUCH_MEMBER (0xc000017a) +#define STATUS_INVALID_MEMBER (0xc000017b) +#define STATUS_KEY_DELETED (0xc000017c) +#define STATUS_NO_LOG_SPACE (0xc000017d) +#define STATUS_TOO_MANY_SIDS (0xc000017e) +#define STATUS_LM_CROSS_ENCRYPTION_REQUIRED (0xc000017f) +#define STATUS_KEY_HAS_CHILDREN (0xc0000180) +#define STATUS_CHILD_MUST_BE_VOLATILE (0xc0000181) +#define STATUS_DEVICE_CONFIGURATION_ERROR (0xc0000182) +#define STATUS_DRIVER_INTERNAL_ERROR (0xc0000183) +#define STATUS_INVALID_DEVICE_STATE (0xc0000184) +#define STATUS_IO_DEVICE_ERROR (0xc0000185) +#define STATUS_DEVICE_PROTOCOL_ERROR (0xc0000186) +#define STATUS_BACKUP_CONTROLLER (0xc0000187) +#define STATUS_LOG_FILE_FULL (0xc0000188) +#define STATUS_TOO_LATE (0xc0000189) +#define STATUS_NO_TRUST_LSA_SECRET (0xc000018a) +#define STATUS_NO_TRUST_SAM_ACCOUNT (0xc000018b) +#define STATUS_TRUSTED_DOMAIN_FAILURE (0xc000018c) +#define STATUS_TRUSTED_RELATIONSHIP_FAILURE (0xc000018d) +#define STATUS_EVENTLOG_FILE_CORRUPT (0xc000018e) +#define STATUS_EVENTLOG_CANT_START (0xc000018f) +#define STATUS_TRUST_FAILURE (0xc0000190) +#define STATUS_MUTANT_LIMIT_EXCEEDED (0xc0000191) +#define STATUS_NETLOGON_NOT_STARTED (0xc0000192) +#define STATUS_ACCOUNT_EXPIRED (0xc0000193) +#define STATUS_POSSIBLE_DEADLOCK (0xc0000194) +#define STATUS_NETWORK_CREDENTIAL_CONFLICT (0xc0000195) +#define STATUS_REMOTE_SESSION_LIMIT (0xc0000196) +#define STATUS_EVENTLOG_FILE_CHANGED (0xc0000197) +#define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (0xc0000198) +#define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (0xc0000199) +#define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (0xc000019a) +#define STATUS_DOMAIN_TRUST_INCONSISTENT (0xc000019b) +#define STATUS_FS_DRIVER_REQUIRED (0xc000019c) + +#define STATUS_NO_USER_SESSION_KEY (0xc0000202) +#define STATUS_USER_SESSION_DELETED (0xc0000203) +#define STATUS_RESOURCE_LANG_NOT_FOUND (0xc0000204) +#define STATUS_INSUFF_SERVER_RESOURCES (0xc0000205) +#define STATUS_INVALID_BUFFER_SIZE (0xc0000206) +#define STATUS_INVALID_ADDRESS_COMPONENT (0xc0000207) +#define STATUS_INVALID_ADDRESS_WILDCARD (0xc0000208) +#define STATUS_TOO_MANY_ADDRESSES (0xc0000209) +#define STATUS_ADDRESS_ALREADY_EXISTS (0xc000020a) +#define STATUS_ADDRESS_CLOSED (0xc000020b) +#define STATUS_CONNECTION_DISCONNECTED (0xc000020c) +#define STATUS_CONNECTION_RESET (0xc000020d) +#define STATUS_TOO_MANY_NODES (0xc000020e) +#define STATUS_TRANSACTION_ABORTED (0xc000020f) +#define STATUS_TRANSACTION_TIMED_OUT (0xc0000210) +#define STATUS_TRANSACTION_NO_RELEASE (0xc0000211) +#define STATUS_TRANSACTION_NO_MATCH (0xc0000212) +#define STATUS_TRANSACTION_RESPONDED (0xc0000213) +#define STATUS_TRANSACTION_INVALID_ID (0xc0000214) +#define STATUS_TRANSACTION_INVALID_TYPE (0xc0000215) +#define STATUS_NOT_SERVER_SESSION (0xc0000216) +#define STATUS_NOT_CLIENT_SESSION (0xc0000217) +#define STATUS_CANNOT_LOAD_REGISTRY_FILE (0xc0000218) +#define STATUS_DEBUG_ATTACH_FAILED (0xc0000219) +#define STATUS_SYSTEM_PROCESS_TERMINATED (0xc000021a) +#define STATUS_DATA_NOT_ACCEPTED (0xc000021b) +#define STATUS_NO_BROWSER_SERVERS_FOUND (0xc000021c) +#define STATUS_VDM_HARD_ERROR (0xc000021d) +#define STATUS_DRIVER_CANCEL_TIMEOUT (0xc000021e) +#define STATUS_REPLY_MESSAGE_MISMATCH (0xc000021f) +#define STATUS_MAPPED_ALIGNMENT (0xc0000220) +#define STATUS_IMAGE_CHECKSUM_MISMATCH (0xc0000221) +#define STATUS_LOST_WRITEBEHIND_DATA (0xc0000222) +#define STATUS_CLIENT_SERVER_PARAMETERS_INVALID (0xc0000223) +#define STATUS_PASSWORD_MUST_CHANGE (0xc0000224) +#define STATUS_NOT_FOUND (0xc0000225) +#define STATUS_NOT_TINY_STREAM (0xc0000226) +#define STATUS_RECOVERY_FAILURE (0xc0000227) +#define STATUS_STACK_OVERFLOW_READ (0xc0000228) +#define STATUS_FAIL_CHECK (0xc0000229) +#define STATUS_DUPLICATE_OBJECTID (0xc000022a) +#define STATUS_OBJECTID_EXISTS (0xc000022b) +#define STATUS_CONVERT_TO_LARGE (0xc000022c) +#define STATUS_RETRY (0xc000022d) +#define STATUS_FOUND_OUT_OF_SCOPE (0xc000022e) +#define STATUS_ALLOCATE_BUCKET (0xc000022f) +#define STATUS_PROPSET_NOT_FOUND (0xc0000230) +#define STATUS_MARSHALL_OVERFLOW (0xc0000231) +#define STATUS_INVALID_VARIANT (0xc0000232) +#define STATUS_DOMAIN_CONTROLLER_NOT_FOUND (0xc0000233) +#define STATUS_ACCOUNT_LOCKED_OUT (0xc0000234) +#define STATUS_HANDLE_NOT_CLOSABLE (0xc0000235) +#define STATUS_CONNECTION_REFUSED (0xc0000236) +#define STATUS_GRACEFUL_DISCONNECT (0xc0000237) +#define STATUS_ADDRESS_ALREADY_ASSOCIATED (0xc0000238) +#define STATUS_ADDRESS_NOT_ASSOCIATED (0xc0000239) +#define STATUS_CONNECTION_INVALID (0xc000023a) +#define STATUS_CONNECTION_ACTIVE (0xc000023b) +#define STATUS_NETWORK_UNREACHABLE (0xc000023c) +#define STATUS_HOST_UNREACHABLE (0xc000023d) +#define STATUS_PROTOCOL_UNREACHABLE (0xc000023e) +#define STATUS_PORT_UNREACHABLE (0xc000023f) +#define STATUS_REQUEST_ABORTED (0xc0000240) +#define STATUS_CONNECTION_ABORTED (0xc0000241) +#define STATUS_BAD_COMPRESSION_BUFFER (0xc0000242) +#define STATUS_USER_MAPPED_FILE (0xc0000243) +#define STATUS_AUDIT_FAILED (0xc0000244) +#define STATUS_TIMER_RESOLUTION_NOT_SET (0xc0000245) +#define STATUS_CONNECTION_COUNT_LIMIT (0xc0000246) +#define STATUS_LOGIN_TIME_RESTRICTION (0xc0000247) +#define STATUS_LOGIN_WKSTA_RESTRICTION (0xc0000248) +#define STATUS_IMAGE_MP_UP_MISMATCH (0xc0000249) + +#define STATUS_INSUFFICIENT_LOGON_INFO (0xc0000250) +#define STATUS_BAD_DLL_ENTRYPOINT (0xc0000251) +#define STATUS_BAD_SERVICE_ENTRYPOINT (0xc0000252) +#define STATUS_LPC_REPLY_LOST (0xc0000253) +#define STATUS_IP_ADDRESS_CONFLICT1 (0xc0000254) +#define STATUS_IP_ADDRESS_CONFLICT2 (0xc0000255) +#define STATUS_REGISTRY_QUOTA_LIMIT (0xc0000256) +#define STATUS_PATH_NOT_COVERED (0xc0000257) +#define STATUS_NO_CALLBACK_ACTIVE (0xc0000258) +#define STATUS_LICENSE_QUOTA_EXCEEDED (0xc0000259) +#define STATUS_PWD_TOO_SHORT (0xc000025a) +#define STATUS_PWD_TOO_RECENT (0xc000025b) +#define STATUS_PWD_HISTORY_CONFLICT (0xc000025c) +#define STATUS_PLUGPLAY_NO_DEVICE (0xc000025e) +#define STATUS_UNSUPPORTED_COMPRESSION (0xc000025f) +#define STATUS_INVALID_HW_PROFILE (0xc0000260) +#define STATUS_INVALID_PLUGPLAY_DEVICE_PATH (0xc0000261) +#define STATUS_DRIVER_ORDINAL_NOT_FOUND (0xc0000262) +#define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (0xc0000263) +#define STATUS_RESOURCE_NOT_OWNED (0xc0000264) +#define STATUS_TOO_MANY_LINKS (0xc0000265) +#define STATUS_QUOTA_LIST_INCONSISTENT (0xc0000266) +#define STATUS_FILE_IS_OFFLINE (0xc0000267) +#define STATUS_EVALUATION_EXPIRATION (0xc0000268) +#define STATUS_ILLEGAL_DLL_RELOCATION (0xc0000269) +#define STATUS_LICENSE_VIOLATION (0xc000026a) +#define STATUS_DLL_INIT_FAILED_LOGOFF (0xc000026b) +#define STATUS_DRIVER_UNABLE_TO_LOAD (0xc000026c) +#define STATUS_DFS_UNAVAILABLE (0xc000026d) +#define STATUS_VOLUME_DISMOUNTED (0xc000026e) +#define STATUS_WX86_INTERNAL_ERROR (0xc000026f) +#define STATUS_WX86_FLOAT_STACK_CHECK (0xc0000270) +#define STATUS_VALIDATE_CONTINUE (0xc0000271) +#define STATUS_NO_MATCH (0xc0000272) +#define STATUS_NO_MORE_MATCHES (0xc0000273) +#define STATUS_INVALID_VLM_OPERATION (0xc0000274) +#define STATUS_NOT_A_REPARSE_POINT (0xc0000275) +#define STATUS_IO_REPARSE_TAG_INVALID (0xc0000276) +#define STATUS_IO_REPARSE_TAG_MISMATCH (0xc0000277) +#define STATUS_IO_REPARSE_DATA_INVALID (0xc0000278) +#define STATUS_IO_REPARSE_TAG_NOT_HANDLED (0xc0000279) + + +#define STATUS_SAM_INIT_FAILURE (0xC00002CB) + + +#define RPC_NT_INVALID_STRING_BINDING (0xC0020001) +#define RPC_NT_WRONG_KIND_OF_BINDING (0xC0020002) +#define RPC_NT_INVALID_BINDING (0xC0020003) +#define RPC_NT_PROTSEQ_NOT_SUPPORTED (0xC0020004) +#define RPC_NT_INVALID_RPC_PROTSEQ (0xC0020005) +#define RPC_NT_INVALID_STRING_UUID (0xC0020006) +#define RPC_NT_INVALID_ENDPOINT_FORMAT (0xC0020007) +#define RPC_NT_INVALID_NET_ADDR (0xC0020008) +#define RPC_NT_NO_ENDPOINT_FOUND (0xC0020009) +#define RPC_NT_INVALID_TIMEOUT (0xC002000A) +#define RPC_NT_OBJECT_NOT_FOUND (0xC002000B) +#define RPC_NT_ALREADY_REGISTERED (0xC002000C) +#define RPC_NT_TYPE_ALREADY_REGISTERED (0xC002000D) +#define RPC_NT_ALREADY_LISTENING (0xC002000E) +#define RPC_NT_NO_PROTSEQS_REGISTERED (0xC002000F) +#define RPC_NT_NOT_LISTENING (0xC0020010) +#define RPC_NT_UNKNOWN_MGR_TYPE (0xC0020011) +#define RPC_NT_UNKNOWN_IF (0xC0020012) +#define RPC_NT_NO_BINDINGS (0xC0020013) +#define RPC_NT_NO_PROTSEQS (0xC0020014) +#define RPC_NT_CANT_CREATE_ENDPOINT (0xC0020015) +#define RPC_NT_OUT_OF_RESOURCES (0xC0020016) +#define RPC_NT_SERVER_UNAVAILABLE (0xC0020017) +#define RPC_NT_SERVER_TOO_BUSY (0xC0020018) +#define RPC_NT_INVALID_NETWORK_OPTIONS (0xC0020019) +#define RPC_NT_NO_CALL_ACTIVE (0xC002001A) +#define RPC_NT_CALL_FAILED (0xC002001B) +#define RPC_NT_CALL_FAILED_DNE (0xC002001C) +#define RPC_NT_PROTOCOL_ERROR (0xC002001D) + + +#define RPC_NT_SS_IN_NULL_CONTEXT (0xC0030004) + + +/* FIXME: Are these official values ?? */ +#define STATUS_FS_QUERY_REQUIRED (0xC1000001) +#define STATUS_HANDLE_NOT_WAITABLE (0xC1000002) +#define STATUS_OBJECT_FILE_MISMATCH (0xC1000003) +#define STATUS_INVALID_PARAMETER_MAX (0xC1000004) +#define STATUS_CONFLICTING_ADDRESS (0xC1000005) +#define STATUS_NO_MEDIA_IN_DRIVE (0xC1000006) + +#endif /* __INCLUDE_DDK_STATUS_H */ + + + + + + diff --git a/include/ddk/structs.h b/include/ddk/structs.h new file mode 100644 index 0000000..113eff3 --- /dev/null +++ b/include/ddk/structs.h @@ -0,0 +1,10 @@ +/* SYSTEM STRUCTURES ******************************************************/ + +#include +#include +#include +#include +#include +#include +#include + diff --git a/include/ddk/types.h b/include/ddk/types.h new file mode 100644 index 0000000..908a477 --- /dev/null +++ b/include/ddk/types.h @@ -0,0 +1,32 @@ +#ifndef __INCLUDE_DDK_TYPES_H +#define __INCLUDE_DDK_TYPES_H + +// these should be moved to a file like ntdef.h + + + +typedef ULONG KAFFINITY, *PKAFFINITY; + + + + + +/* + * Various other types (all quite pointless) + */ +typedef CCHAR KPROCESSOR_MODE; +typedef UCHAR KIRQL; +typedef KIRQL* PKIRQL; +typedef ULONG IO_ALLOCATION_ACTION; +typedef ULONG POOL_TYPE; +typedef ULONG TIMER_TYPE; +typedef ULONG MM_SYSTEM_SIZE; +typedef ULONG LOCK_OPERATION; + +typedef LARGE_INTEGER PHYSICAL_ADDRESS; +typedef PHYSICAL_ADDRESS* PPHYSICAL_ADDRESS; + + + + +#endif /* __INCLUDE_DDK_TYPES_H */ diff --git a/include/ddk/winddi.h b/include/ddk/winddi.h new file mode 100644 index 0000000..c4de4c7 --- /dev/null +++ b/include/ddk/winddi.h @@ -0,0 +1,1366 @@ +/* + * WinDDI.h - definition of the GDI - DDI interface + */ + +#ifndef __DDK_WINDDI_H +#define __DDK_WINDDI_H + +#if defined(WIN32_LEAN_AND_MEAN) && defined(_GNU_H_WINDOWS32_STRUCTURES) +#error "windows.h cannot be included before winddi.h if WIN32_LEAN_AND_MEAN is defined" +#endif + +#ifdef WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#include +#define WIN32_LEAN_AND_MEAN +#else +#include +#endif + +#ifndef IN +#define IN +#define OUT +#define OPTIONAL +#endif + +#ifndef PTRDIFF +typedef DWORD PTRDIFF; +#endif + +#define GDI_DRIVER_VERSION 0x4000 // NT 4 compatibility + +/* FIXME: find definitions for these structs */ +typedef PVOID PCOLORADJUSTMENT; +typedef PVOID PDD_CALLBACKS; +typedef PVOID PDD_HALINFO; +typedef PVOID PDD_PALETTECALLBACKS; +typedef PVOID PDD_SURFACECALLBACKS; +typedef PVOID PFONTINFO; +typedef PVOID PGAMMA_TABLES; +typedef PVOID PGLYPHDATA; +typedef PVOID PLINEATTRS; +typedef DWORD MIX; +typedef DWORD ROP4; +typedef PVOID PSTROBJ; +typedef PVOID PTTPOLYGONHEADER; +typedef PVOID PVIDEOMEMORY; + +#define DDI_DRIVER_VERSION 0x00010000 + +/* FIXME: how big should this constant be? */ +#define HS_DDI_MAX 6 + +/* XLate types */ +#define XO_TRIVIAL 0x00000001 +#define XO_TABLE 0x00000002 +#define XO_TO_MONO 0x00000004 + +#define XO_SRCPALETTE 1 +#define XO_DESTPALETTE 2 +#define XO_DESTDCPALETTE 3 + +/* EngCreateBitmap format types */ +enum _BMF_TYPES +{ + BMF_1BPP = 1, + BMF_4BPP, + BMF_8BPP, + BMF_16BPP, + BMF_24BPP, + BMF_32BPP, + BMF_4RLE, + BMF_8RLE +}; + +#define BMF_TOPDOWN 0x00000001 +#define BMF_NOZEROINIT 0x00000002 +#define BMF_DONTCACHE 0x00000004 +#define BMF_USERMEM 0x00000008 +#define BMF_KMSECTION 0x00000010 + +#define DC_TRIVIAL 0 +#define DC_RECT 1 +#define DC_COMPLEX 3 + +#define FC_RECT 1 +#define FC_RECT4 2 +#define FC_COMPLEX 3 + +#define TC_RECTANGLES 0 +#define TC_PATHOBJ 2 + +#define OC_BANK_CLIP 1 + +#define CT_RECTANGLES 0L + +#define CD_LEFTWARDS 1L +#define CD_UPWARDS 2L + +/* Options for CLIPOBJ_cEnumStart BuildOrder field */ +enum _CD_ORDERS +{ + CD_RIGHTDOWN, + CD_LEFTDOWN, + CD_RIGHTUP, + CD_LEFTUP, + CD_ANY +}; + +/* Options for CLIPOBJ_cEnumStart Type field */ +#define CT_RECTANGLE 1 + +#define DCR_SOLID 0 +#define DCR_DRIVER 1 +#define DCR_HALFTONE 2 + +#define DMMAXDEVICENAME 32 +#define DMMAXFORMNAME 32 + +#define DM_DEFAULT 0x00000001 +#define DM_MONOCHROME 0x00000002 + +#define ED_ABORTDOC 0x00000001 + +enum _ESCAPE_CODES +{ + ESC_PASSTHROUGH, + ESC_QUERYESCSUPPORT +}; + +#define FM_INFO_TECH_TRUETYPE 0x00000001 +#define FM_INFO_TECH_BITMAP 0x00000002 +#define FM_INFO_TECH_STROKE 0x00000004 +#define FM_INFO_TECH_OUTLINE_NOT_TRUETYPE 0x00000008 +#define FM_INFO_ARB_XFORMS 0x00000010 +#define FM_INFO_1BPP 0x00000020 +#define FM_INFO_4BPP 0x00000040 +#define FM_INFO_8BPP 0x00000080 +#define FM_INFO_16BPP 0x00000100 +#define FM_INFO_24BPP 0x00000200 +#define FM_INFO_32BPP 0x00000400 +#define FM_INFO_INTEGER_WIDTH 0x00000800 +#define FM_INFO_CONSTANT_WIDTH 0x00001000 +#define FM_INFO_NOT_CONTIGUOUS 0x00002000 +#define FM_INFO_PID_EMBEDDED 0x00004000 +#define FM_INFO_RETURNS_OUTLINES 0x00008000 +#define FM_INFO_RETURNS_STROKES 0x00010000 +#define FM_INFO_RETURNS_BITMAPS 0x00020000 +#define FM_INFO_UNICODE_COMPLIANT 0x00040000 +#define FM_INFO_RIGHT_HANDED 0x00080000 +#define FM_INFO_INTEGRAL_SCALING 0x00100000 +#define FM_INFO_90DEGREE_ROTATIONS 0x00200000 +#define FM_INFO_OPTICALLY_FIXED_PITCH 0x00400000 +#define FM_INFO_DO_NOT_ENUMERATE 0x00800000 +#define FM_INFO_ISOTROPIC_SCALING_ONLY 0x01000000 +#define FM_INFO_ANISOTROPIC_SCALING_ONLY 0x02000000 +#define FM_INFO_TID_EMBEDDED 0x04000000 +#define FM_INFO_FAMILY_EQUIV 0x08000000 +#define FM_INFO_DBCS_FIXED_PITCH 0x10000000 +#define FM_INFO_NONNEGATIVE_AC 0x20000000 +#define FM_INFO_IGNORE_TC_RA_ABLE 0x40000000 +#define FM_INFO_TECH_TYPE1 0x80000000 + +#define FM_SEL_ITALIC 0x00000001 +#define FM_SEL_UNDERSCORE 0x00000002 +#define FM_SEL_NEGATIVE 0x00000004 +#define FM_SEL_OUTLINED 0x00000008 +#define FM_SEL_STRIKEOUT 0x00000010 +#define FM_SEL_BOLD 0x00000020 +#define FM_SEL_REGULAR 0x00000040 + +#define FM_TYPE_LICENSED 0x00000002 +#define FM_READONLY_EMBED 0x00000004 +#define FM_EDITABLE_EMBED 0x00000008 +#define FM_NO_EMBEDDING 0x00000002 + +#define FO_TYPE_RASTER RASTER_FONTTYPE +#define FO_TYPE_DEVICE DEVICE_FONTTYPE +#define FO_TYPE_TRUETYPE TRUETYPE_FONTTYPE +#define FO_SIM_BOLD 0x00002000 +#define FO_SIM_ITALIC 0x00004000 +#define FO_EM_HEIGHT 0x00008000 +#define FO_GRAY16 0x00010000 +#define FO_NOGRAY16 0x00020000 +#define FO_NOHINTS 0x00040000 +#define FO_NO_CHOICE 0x00080000 + +enum _FP_MODES +{ + FP_ALTERNATEMODE = 1, + FP_WINDINGMODE +}; + +enum _GLYPH_MODE +{ + FO_HGLYPHS, + FO_GLYPHBITS, + FO_PATHOBJ +}; + +// Allowed values for GDIINFO.ulPrimaryOrder. + +#define PRIMARY_ORDER_ABC 0 +#define PRIMARY_ORDER_ACB 1 +#define PRIMARY_ORDER_BAC 2 +#define PRIMARY_ORDER_BCA 3 +#define PRIMARY_ORDER_CBA 4 +#define PRIMARY_ORDER_CAB 5 + +// Allowed values for GDIINFO.ulHTPatternSize. + +#define HT_PATSIZE_2x2 0 +#define HT_PATSIZE_2x2_M 1 +#define HT_PATSIZE_4x4 2 +#define HT_PATSIZE_4x4_M 3 +#define HT_PATSIZE_6x6 4 +#define HT_PATSIZE_6x6_M 5 +#define HT_PATSIZE_8x8 6 +#define HT_PATSIZE_8x8_M 7 +#define HT_PATSIZE_10x10 8 +#define HT_PATSIZE_10x10_M 9 +#define HT_PATSIZE_12x12 10 +#define HT_PATSIZE_12x12_M 11 +#define HT_PATSIZE_14x14 12 +#define HT_PATSIZE_14x14_M 13 +#define HT_PATSIZE_16x16 14 +#define HT_PATSIZE_16x16_M 15 +#define HT_PATSIZE_MAX_INDEX HT_PATSIZE_16x16_M +#define HT_PATSIZE_DEFAULT HT_PATSIZE_4x4_M + +// Allowed values for GDIINFO.ulHTOutputFormat. + +#define HT_FORMAT_1BPP 0 +#define HT_FORMAT_4BPP 2 +#define HT_FORMAT_4BPP_IRGB 3 +#define HT_FORMAT_8BPP 4 +#define HT_FORMAT_16BPP 5 +#define HT_FORMAT_24BPP 6 +#define HT_FORMAT_32BPP 7 + +// Allowed values for GDIINFO.flHTFlags. + +#define HT_FLAG_SQUARE_DEVICE_PEL 0x00000001 +#define HT_FLAG_HAS_BLACK_DYE 0x00000002 +#define HT_FLAG_ADDITIVE_PRIMS 0x00000004 +#define HT_FLAG_OUTPUT_CMY 0x00000100 + +#define GCAPS_BEZIERS 0x00000001 +#define GCAPS_GEOMETRICWIDE 0x00000002 +#define GCAPS_ALTERNATEFILL 0x00000004 +#define GCAPS_WINDINGFILL 0x00000008 +#define GCAPS_HALFTONE 0x00000010 +#define GCAPS_COLOR_DITHER 0x00000020 +#define GCAPS_HORIZSTRIKE 0x00000040 +#define GCAPS_VERTSTRIKE 0x00000080 +#define GCAPS_OPAQUERECT 0x00000100 +#define GCAPS_VECTORFONT 0x00000200 +#define GCAPS_MONO_DITHER 0x00000400 +#define GCAPS_ASYNCCHANGE 0x00000800 +#define GCAPS_ASYNCMOVE 0x00001000 +#define GCAPS_DONTJOURNAL 0x00002000 +#define GCAPS_DIRECTDRAW 0x00004000 +#define GCAPS_ARBRUSHOPAQUE 0x00008000 +#define GCAPS_PANNING 0x00010000 +#define GCAPS_HIGHRESTEXT 0x00040000 +#define GCAPS_PALMANAGED 0x00080000 +#define GCAPS_DITHERONREALIZE 0x00200000 +#define GCAPS_NO64BITMEMACCESS 0x00400000 +#define GCAPS_FORCEDITHER 0x00800000 +#define GCAPS_GRAY16 0x01000000 + +/* EngAssocateSurface hook flags */ +#define HOOK_BITBLT 0x00000001 +#define HOOK_STRETCHBLT 0x00000002 +#define HOOK_PLGBLT 0x00000004 +#define HOOK_TEXTOUT 0x00000008 +#define HOOK_PAINT 0x00000010 +#define HOOK_STROKEPATH 0x00000020 +#define HOOK_FILLPATH 0x00000040 +#define HOOK_STROKEANDFILLPATH 0x00000080 +#define HOOK_LINETO 0x00000100 +#define HOOK_COPYBITS 0x00000400 +#define HOOK_SYNCHRONIZE 0x00001000 +#define HOOK_SYNCHRONIZEACCESS 0x00004000 +#define HOOK_TRANSPARENTBLT 0x00008000 + +enum _DRV_HOOK_FUNCS +{ + INDEX_DrvEnablePDEV, + INDEX_DrvCompletePDEV, + INDEX_DrvDisablePDEV, + INDEX_DrvEnableSurface, + INDEX_DrvDisableSurface, + INDEX_DrvAssertMode, + INDEX_DrvResetPDEV = 7, + INDEX_DrvCreateDeviceBitmap = 10, + INDEX_DrvDeleteDeviceBitmap, + INDEX_DrvRealizeBrush, + INDEX_DrvDitherColor, + INDEX_DrvStrokePath, + INDEX_DrvFillPath, + INDEX_DrvStrokeAndFillPath, + INDEX_DrvPaint, + INDEX_DrvBitBlt, + INDEX_DrvCopyBits, + INDEX_DrvStretchBlt, + INDEX_DrvSetPalette = 22, + INDEX_DrvTextOut, + INDEX_DrvEscape, + INDEX_DrvDrawEscape, + INDEX_DrvQueryFont, + INDEX_DrvQueryFontTree, + INDEX_DrvQueryFontData, + INDEX_DrvSetPointerShape, + INDEX_DrvMovePointer, + INDEX_DrvLineTo, + INDEX_DrvSendPage, + INDEX_DrvStartPage, + INDEX_DrvEndDoc, + INDEX_DrvStartDoc, + INDEX_DrvGetGlyphMode = 37, + INDEX_DrvSynchronize, + INDEX_DrvSaveScreenBits = 40, + INDEX_DrvGetModes, + INDEX_DrvFree, + INDEX_DrvDestroyFont, + INDEX_DrvQueryFontCaps, + INDEX_DrvLoadFontFile, + INDEX_DrvUnloadFontFile, + INDEX_DrvFontManagement, + INDEX_DrvQueryTrueTypeTable, + INDEX_DrvQueryTrueTypeOutline, + INDEX_DrvGetTrueTypeFile, + INDEX_DrvQueryFontFile, + INDEX_DrvQueryAdvanceWidths = 53, + INDEX_DrvSetPixelFormat, + INDEX_DrvDescribePixelFormat, + INDEX_DrvSwapBuffers, + INDEX_DrvStartBanding, + INDEX_DrvNextBand, + INDEX_DrvGetDirectDrawInfo, + INDEX_DrvEnableDirectDraw, + INDEX_DrvDisableDirectDraw, + INDEX_DrvQuerySpoolType, + INDEX_DrvTransparentBlt = 74, + INDEX_LAST +}; + +/* EngCreatePalette mode types */ +#define PAL_INDEXED 0x00000001 +#define PAL_BITFIELDS 0x00000002 +#define PAL_RGB 0x00000004 +#define PAL_BGR 0x00000008 + +enum _QUERY_ADVANCE_WIDTH_TYPES +{ + QAW_GETWIDTHS = 1, + QAW_GETEASYWIDTHS +}; + +#define QC_OUTLINES 0x00000001 +#define QC_1BIT 0x00000002 +#define QC_4BIT 0x00000004 + +enum _QFF_MODES +{ + QFF_DESCRIPTION = 1, + QFF_NUMFACES +}; + +#define RB_DITHERCOLOR 0x80000000 + +enum _SPS_RC +{ + SPS_ERROR, + SPS_DECLINE, + SPS_ACCEPT_NOEXCLUDE, + SPS_ACCEPT_EXCLUDE +}; + +#define SPS_CHANGE 0x00000001L +#define SPS_ASYNCCHANGE 0x00000002L +#define SPS_ANIMATESTART 0x00000004L +#define SPS_ANIMATEUPDATE 0x00000008L + +#define SS_SAVE 0 +#define SS_RESTORE 1 +#define SS_FREE 2 + +enum _SURF_TYPES +{ + STYPE_BITMAP = 1, + STYPE_DEVICE, + STYPE_DEVBITMAP +}; + +#define WO_RGN_CLIENT_DELTA 0x00000001 +#define WO_RGN_CLIENT 0x00000002 +#define WO_RGN_SURFACE_DELTA 0x00000004 +#define WO_RGN_SURFACE 0x00000008 +#define WO_RGN_UPDATE_ALL 0x00000010 + +#define WOC_RGN_CLIENT_DELTA 0x00000001 +#define WOC_RGN_CLIENT 0x00000002 +#define WOC_RGN_SURFACE_DELTA 0x00000004 +#define WOC_RGN_SURFACE 0x00000008 +#define WOC_CHANGED 0x00000010 +#define WOC_DELETE 0x00000020 + +typedef HANDLE HDEV; +typedef HANDLE HGLYPH; +typedef HANDLE HSURF; +typedef HANDLE DHPDEV; +typedef HANDLE DHSURF; +typedef ULONG (*PFN)(VOID); +typedef ULONG IDENT; + +typedef struct _DRVFN +{ + ULONG iFunc; + PFN pfn; +} DRVFN, *PDRVFN; + +/* + * DRVENABLEDATA - this structure is passed to the DDI from the GDI + * in the function DrvEnableDriver to determine driver parameters. + */ + +typedef struct _DRVENABLEDATA +{ + ULONG iDriverVersion; + ULONG c; + DRVFN *pdrvfn; +} DRVENABLEDATA, *PDRVENABLEDATA; + +/* FIXME: replace this with correct def for LDECI4 */ +typedef DWORD LDECI4; + +typedef struct _CIECHROMA +{ + LDECI4 x; + LDECI4 y; + LDECI4 Y; +} CIECHROMA, *PCIECHROMA; + +typedef struct _COLORINFO +{ + CIECHROMA Red; + CIECHROMA Green; + CIECHROMA Blue; + CIECHROMA Cyan; + CIECHROMA Magenta; + CIECHROMA Yellow; + CIECHROMA AlignmentWhite; + LDECI4 RedGamma; + LDECI4 GreenGamma; + LDECI4 BlueGamma; + LDECI4 MagentaInCyanDye; + LDECI4 YellowInCyanDye; + LDECI4 CyanInMagentaDye; + LDECI4 YellowInMagentaDye; + LDECI4 CyanInYellowDye; + LDECI4 MagentaInYellowDye; +} COLORINFO, *PCOLORINFO; + +typedef struct _DEVINFO +{ + ULONG flGraphicsCaps; + LOGFONTW lfDefaultFont; + LOGFONTW lfAnsiVarFont; + LOGFONTW lfAnsiFixFont; + ULONG cFonts; + ULONG iDitherFormat; + USHORT cxDither; + USHORT cyDither; + HPALETTE hpalDefault; +} DEVINFO, *PDEVINFO; + +typedef struct _GDIINFO +{ + ULONG ulVersion; + ULONG ulTechnology; + ULONG ulHorzSize; + ULONG ulVertSize; + ULONG ulHorzRes; + ULONG ulVertRes; + ULONG cBitsPixel; + ULONG cPlanes; + ULONG ulNumColors; + ULONG flRaster; + ULONG ulLogPixelsX; + ULONG ulLogPixelsY; + ULONG flTextCaps; + ULONG ulDACRed; + ULONG ulDACGreen; + ULONG ulDACBlue; + ULONG ulAspectX; + ULONG ulAspectY; + ULONG ulAspectXY; + LONG xStyleStep; + LONG yStyleStep; + LONG denStyleStep; + POINTL ptlPhysOffset; + SIZEL szlPhysSize; + ULONG ulNumPalReg; + COLORINFO ciDevice; + ULONG ulDevicePelsDPI; + ULONG ulPrimaryOrder; + ULONG ulHTPatternSize; + ULONG ulHTOutputFormat; + ULONG flHTFlags; + ULONG ulVRefresh; + ULONG ulBltAlignment; + ULONG ulPanningHorzRes; + ULONG ulPanningVertRes; +} GDIINFO, *PGDIINFO; + +typedef struct _BRUSHOBJ +{ + ULONG iSolidColor; + PVOID pvRbrush; + + /* remainder of fields are for GDI internal use */ + LOGBRUSH logbrush; +} BRUSHOBJ, *PBRUSHOBJ; + +typedef struct _CLIPOBJ +{ + ULONG iUniq; + RECTL rclBounds; + BYTE iDComplexity; + BYTE iFComplexity; + BYTE iMode; + BYTE fjOptions; +} CLIPOBJ, *PCLIPOBJ; + +typedef struct _ENUMRECTS +{ + ULONG c; + RECTL arcl[1]; +} ENUMRECTS, *PENUMRECTS; + +typedef struct _FONTOBJ +{ + ULONG iUniq; + ULONG iFace; + ULONG cxMax; + ULONG flFontType; + ULONG iTTUniq; + ULONG iFile; + SIZE sizLogResPpi; + ULONG ulStyleSize; + PVOID pvConsumer; + PVOID pvProducer; +} FONTOBJ, *PFONTOBJ; + +typedef struct _IFIMETRICS +{ + ULONG cjThis; + ULONG ulVersion; + PTRDIFF dpwszFamilyName; + PTRDIFF dpwszStyleName; + PTRDIFF dpwszFaceName; + PTRDIFF dpwszUniqueName; + PTRDIFF dpFontSim; + LONG lEmbedId; + LONG lItalicAngle; + LONG lCharBias; + PTRDIFF dpCharSets; + BYTE jWinCharSet; + BYTE jWinPitchAndFamily; + USHORT usWinWeight; + ULONG flInfo; + USHORT fsSelection; + USHORT fsType; + WORD fwdUnitsPerEm; + WORD fwdLowestPPEm; + WORD fwdWinAscender; + WORD fwdWinDescender; + WORD fwdMacAscender; + WORD fwdMacDescender; + WORD fwdMacLineGap; + WORD fwdTypoAscender; + WORD fwdTypoDescender; + WORD fwdTypoLineGap; + WORD fwdAveCharWidth; + WORD fwdMaxCharInc; + WORD fwdCapHeight; + WORD fwdXHeight; + WORD fwdSubScriptXSize; + WORD fwdSubScriptYSize; + WORD fwdSubScriptXOffset; + WORD fwdSubScriptYOffset; + WORD fwdSuperScriptXSize; + WORD fwdSuperScriptYSize; + WORD fwdSuperScriptXOffset; + WORD fwdSuperScriptYOffset; + WORD fwdUnderscoreSize; + WORD fwdUnderscorePosition; + WORD fwdStrikeoutSize; + WORD fwdStrikeoutPosition; + BYTE chFirstChar; + BYTE chLastChar; + BYTE chDefaultChar; + BYTE chBreakChar; + WCHAR wcFirstChar; + WCHAR wcLastChar; + WCHAR wcDefaultChar; + WCHAR wcBreakChar; + POINTL ptlBaseline; + POINTL ptlAspect; + POINTL ptlCaret; + RECTL rclFontBox; + BYTE achVendId[4]; + ULONG cKerningPairs; + ULONG ulPanoseCulture; + PANOSE panose; +} IFIMETRICS, *PIFIMETRICS; + +#define NB_RESERVED_COLORS 20 // number of fixed colors in system palette + +typedef struct _XLATEOBJ +{ + ULONG iUniq; + ULONG flXlate; + USHORT iSrcType; + USHORT iDstType; + ULONG cEntries; + ULONG *pulXlate; +} XLATEOBJ, *PXLATEOBJ; + +typedef struct _PALOBJ +{ + PXLATEOBJ logicalToSystem; + int *mapping; + PLOGPALETTE logpalette; // _MUST_ be the last field +} PALOBJ, *PPALOBJ; + +typedef struct _PATHOBJ +{ + ULONG fl; + ULONG cCurves; +} PATHOBJ, *PPATHOBJ; + +typedef struct _SURFOBJ +{ + DHSURF dhsurf; + HSURF hsurf; + DHPDEV dhpdev; + HDEV hdev; + SIZEL sizlBitmap; + ULONG cjBits; + PVOID pvBits; + PVOID pvScan0; + LONG lDelta; + ULONG iUniq; + ULONG iBitmapFormat; + USHORT iType; + USHORT fjBitmap; +} SURFOBJ, *PSURFOBJ; + +typedef struct _WNDOBJ +{ + CLIPOBJ coClient; + PVOID pvConsumer; + RECTL rclClient; +} WNDOBJ, *PWNDOBJ; + +typedef VOID (CALLBACK * WNDOBJCHANGEPROC)(PWNDOBJ WndObj, ULONG Flags); + +typedef struct _XFORMOBJ +{ + /* FIXME: what does this beast look like? */ +} XFORMOBJ, *PXFORMOBJ; + +/* + * Functions Prefixed with Drv are calls made from GDI to DDI, and + * everything else are calls made from DDI to GDI. DDI is + * not allowed to make calls to any other kernel or user modules. + */ + +/* GDI --> DDI calls */ +BOOL STDCALL +DrvAssertMode(IN DHPDEV PDev, + IN BOOL ShouldEnable); +BOOL STDCALL +DrvBitBlt(IN PSURFOBJ DestSurface, + IN PSURFOBJ SrcSurface, + IN PSURFOBJ MaskSurface, + IN PCLIPOBJ ClipObj, + IN PXLATEOBJ XLateObj, + IN PRECTL DestRectL, + IN PPOINTL SrcPointL, + IN PPOINTL MaskPointL, + IN PBRUSHOBJ BrushObj, + IN PPOINTL BrushPointL, + IN ROP4 RasterOp); +VOID STDCALL +DrvCompletePDEV(IN DHPDEV PDev, + IN HDEV Dev); +BOOL STDCALL +DrvCopyBits(OUT PSURFOBJ DestSurface, + IN PSURFOBJ SrcSurface, + IN PCLIPOBJ ClipObj, + IN PXLATEOBJ XLateObj, + IN PRECTL DestRectL, + IN PPOINTL SrcPointL); +HBITMAP STDCALL +DrvCreateDeviceBitmap(IN DHPDEV DPev, + IN SIZEL SizeL, + IN ULONG Format); +VOID STDCALL +DrvDeleteDeviceBitmap(IN DHSURF Surface); +LONG STDCALL +DrvDescribePixelFormat(IN DHPDEV DPev, + IN LONG PixelFormat, + IN ULONG DescriptorSize, + OUT PPIXELFORMATDESCRIPTOR PFD); +VOID STDCALL +DrvDestroyFont(IN PFONTOBJ FontObj); +VOID STDCALL +DrvDisableDirectDraw(IN DHPDEV PDev); +VOID STDCALL +DrvDisableDriver(VOID); +VOID STDCALL +DrvDisablePDEV(IN DHPDEV PDev); +VOID STDCALL +DrvDisableSurface(IN DHPDEV PDev); +ULONG STDCALL +DrvDitherColor(IN DHPDEV DPev, + IN ULONG Mode, + IN ULONG RGB, + OUT PULONG DitherBits); +ULONG STDCALL +DrvDrawEscape(IN PSURFOBJ SurfObj, + IN ULONG EscCode, + IN PCLIPOBJ ClipObj, + IN PRECTL RectL, + IN ULONG InputSize, + IN PVOID *InputData); +BOOL STDCALL +DrvEnableDirectDraw(IN DHPDEV PDev, + IN PDD_CALLBACKS Callbacks, + IN PDD_SURFACECALLBACKS SurfaceCallbacks, + IN PDD_PALETTECALLBACKS PaletteCallbacks); +BOOL STDCALL +DrvEnableDriver(IN ULONG Version, + IN ULONG DEDSize, + OUT PDRVENABLEDATA DED); +DHPDEV STDCALL +DrvEnablePDEV(IN DEVMODEW *DM, + IN LPWSTR LogAddress, + IN ULONG PatternCount, + OUT HSURF *SurfPatterns, + IN ULONG CapsSize, + OUT ULONG *DevCaps, + IN ULONG DevInfoSize, + OUT DEVINFO *DI, + IN LPWSTR DevDataFile, + IN LPWSTR DeviceName, + IN HANDLE Driver); +HSURF STDCALL +DrvEnableSurface(IN DHPDEV PDev); +BOOL STDCALL +DrvEndDoc(IN PSURFOBJ SurfObj, + IN ULONG Flags); +ULONG STDCALL +DrvEscape(IN PSURFOBJ SurfObj, + IN ULONG EscCode, + IN ULONG InputSize, + IN PVOID *InputData, + IN ULONG OutputSize, + OUT PVOID *OutputData); +BOOL STDCALL +DrvFillPath(IN PSURFOBJ SurfObj, + IN PPATHOBJ PathObj, + IN PCLIPOBJ ClipObj, + IN PBRUSHOBJ BrushObj, + IN PPOINTL BrushOrg, + IN MIX Mix, + IN ULONG Options); +ULONG STDCALL +DrvFontManagement(IN PSURFOBJ SurfObj, + IN PFONTOBJ FontObj, + IN ULONG Mode, + IN ULONG InputSize, + IN PVOID InputData, + IN ULONG OutputSize, + OUT PVOID OutputData); +VOID STDCALL +DrvFree(IN PVOID Obj, + IN ULONG ID); +BOOL STDCALL +DrvGetDirectDrawInfo(IN DHPDEV PDev, + IN PDD_HALINFO HalInfo, + IN PDWORD NumHeaps, + IN PVIDEOMEMORY List, + IN PDWORD NumFourCCCodes, + IN PDWORD FourCC); +ULONG STDCALL +DrvGetGlyphMode(IN DHPDEV DPev, + IN PFONTOBJ FontObj); +ULONG STDCALL +DrvGetModes(IN HANDLE Driver, + IN ULONG DataSize, + OUT PDEVMODEW DM); +PVOID STDCALL +DrvGetTrueTypeFile(IN ULONG FileNumber, + IN PULONG Size); +BOOL STDCALL +DrvLineTo(IN PSURFOBJ SurfObj, + IN PCLIPOBJ ClipObj, + IN PBRUSHOBJ BrushObj, + IN LONG x1, + IN LONG y1, + IN LONG x2, + IN LONG y2, + IN PRECTL Bounds, + IN MIX Mix); +ULONG STDCALL +DrvLoadFontFile(IN ULONG FileNumber, + IN PVOID ViewData, + IN ULONG ViewSize, + IN ULONG LangID); +VOID STDCALL +DrvMovePointer(IN PSURFOBJ SurfObj, + IN LONG x, + IN LONG y, + IN PRECTL RectL); +BOOL STDCALL +DrvNextBand(IN PSURFOBJ SurfObj, + OUT PPOINTL PointL); +BOOL STDCALL +DrvPaint(IN PSURFOBJ SurfObj, + IN PCLIPOBJ ClipObj, + IN PBRUSHOBJ BrushObj, + IN PPOINTL BrushOrg, + IN MIX Mix); +BOOL STDCALL +DrvQueryAdvanceWidths(IN DHPDEV DPev, + IN PFONTOBJ FontObj, + IN ULONG Mode, + IN HGLYPH Glyph, + OUT PVOID *Widths, + IN ULONG NumGlyphs); +PIFIMETRICS STDCALL +DrvQueryFont(IN DHPDEV PDev, + IN ULONG FileNumber, + IN ULONG FaceIndex, + IN PULONG Identifier); +LONG STDCALL +DrvQueryFontCaps(IN ULONG CapsSize, + OUT PULONG CapsData); +LONG STDCALL +DrvQueryFontData(IN DHPDEV DPev, + IN PFONTOBJ FontObj, + IN ULONG Mode, + IN HGLYPH Glyph, + IN PGLYPHDATA GlyphData, + IN PVOID DataBuffer, + IN ULONG BufferSize); +LONG STDCALL +DrvQueryFontFile(IN ULONG FileNumber, + IN ULONG Mode, + IN ULONG BufSize, + OUT PULONG Buf); +PVOID STDCALL +DrvQueryFontTree(IN DHPDEV PDev, + IN ULONG FileNumber, + IN ULONG FaceIndex, + IN ULONG Mode, + OUT ULONG *ID); +BOOL STDCALL +DrvQuerySpoolType(DHPDEV PDev, + LPWSTR SpoolType); +LONG STDCALL +DrvQueryTrueTypeOutline(IN DHPDEV PDev, + IN PFONTOBJ FontObj, + IN HGLYPH Glyph, + IN BOOL MetricsOnly, + IN PGLYPHDATA GlyphData, + IN ULONG BufSize, + OUT PTTPOLYGONHEADER Polygons); +LONG STDCALL +DrvQueryTrueTypeTable(IN ULONG FileNumber, + IN ULONG Font, + IN ULONG Tag, + IN PTRDIFF Start, + IN ULONG BufSize, + OUT BYTE *Buf); +BOOL STDCALL +DrvRealizeBrush(IN PBRUSHOBJ BrushObj, + IN PSURFOBJ TargetSurface, + IN PSURFOBJ PatternSurface, + IN PSURFOBJ MaskSurface, + IN PXLATEOBJ XLateObj, + IN ULONG iHatch); +BOOL STDCALL +DrvResetPDEV(IN DHPDEV PDevOld, + IN DHPDEV PDevNew); +ULONG STDCALL +DrvSaveScreenBits(IN PSURFOBJ SurfObj, + IN ULONG Mode, + IN ULONG ID, + IN PRECTL RectL); +BOOL STDCALL +DrvSendPage(IN PSURFOBJ SurfObj); +BOOL STDCALL +DrvSetPalette(IN DHPDEV PDev, + IN PPALOBJ PaletteObj, + IN ULONG Flags, + IN ULONG Start, + IN ULONG NumColors); +ULONG STDCALL +DrvSetPointerShape(IN PSURFOBJ SurfObj, + IN PSURFOBJ MaskSurface, + IN PSURFOBJ ColorSurface, + IN PXLATEOBJ XLateObj, + IN LONG xHot, + IN LONG yHot, + IN LONG x, + IN LONG y, + IN PRECTL RectL, + IN ULONG Flags); +BOOL STDCALL +DrvStartBanding(IN PSURFOBJ SurfObj, + IN PPOINTL PointL); +BOOL STDCALL +DrvStartDoc(IN PSURFOBJ SurfObj, + IN LPWSTR DocName, + IN DWORD JobID); +BOOL STDCALL +DrvStartPage(IN PSURFOBJ SurfObj); +BOOL STDCALL +DrvStretchBlt(IN PSURFOBJ DestSurface, + IN PSURFOBJ SrcSurface, + IN PSURFOBJ MaskSurface, + IN PCLIPOBJ ClipObj, + IN PXLATEOBJ XLateObj, + IN PCOLORADJUSTMENT CA, + IN PPOINTL HTOrg, + IN PRECTL Dest, + IN PRECTL Src, + IN PPOINTL Mask, + IN ULONG Mode); +BOOL STDCALL +DrvStrokeAndFillPath(IN PSURFOBJ SurfObj, + IN PPATHOBJ PathObj, + IN PCLIPOBJ ClipObj, + IN PXFORMOBJ XFormObj, + IN PBRUSHOBJ StrokeBrush, + IN PLINEATTRS LineAttrs, + IN PBRUSHOBJ FillBrush, + IN PPOINTL BrushOrg, + IN MIX MixFill, + IN ULONG Options); +BOOL STDCALL +DrvStrokePath(IN PSURFOBJ SurfObj, + IN PPATHOBJ PathObj, + IN PCLIPOBJ PClipObj, + IN PXFORMOBJ XFormObj, + IN PBRUSHOBJ BrushObj, + IN PPOINTL BrushOrg, + IN PLINEATTRS LineAttrs, + IN MIX Mix); +VOID STDCALL +DrvSynchronize(IN DHPDEV PDev, + IN PRECTL RectL); +BOOL STDCALL +DrvTextOut(IN PSURFOBJ SurfObj, + IN PSTROBJ StrObj, + IN PFONTOBJ FontObj, + IN PCLIPOBJ ClipObj, + IN PRECTL ExtraRect, + IN PRECTL OpaqueRect, + IN PBRUSHOBJ ForegroundBrush, + IN PBRUSHOBJ OpaqueBrush, + IN PPOINTL OrgPoint, + IN MIX Mix); +BOOL STDCALL +DrvTransparentBlt(PSURFOBJ Dest, + PSURFOBJ Source, + PCLIPOBJ Clip, + PXLATEOBJ ColorTranslation, + PRECTL DestRect, + PRECTL SourceRect, + ULONG TransparentColor, + ULONG Reserved); +BOOL STDCALL +DrvUnloadFontFile(IN ULONG FileNumber); + +/* DDI --> GDI calls */ +PVOID STDCALL +BRUSHOBJ_pvAllocRbrush(IN PBRUSHOBJ BrushObj, + IN ULONG ObjSize); +PVOID STDCALL +BRUSHOBJ_pvGetRbrush(IN PBRUSHOBJ BrushObj); + +BOOL STDCALL +CLIPOBJ_bEnum(IN PCLIPOBJ ClipObj, + IN ULONG ObjSize, + OUT ULONG *EnumRects); + +ULONG STDCALL +CLIPOBJ_cEnumStart(IN PCLIPOBJ ClipObj, + IN BOOL ShouldDoAll, + IN ULONG ClipType, + IN ULONG BuildOrder, + IN ULONG MaxRects); + +PPATHOBJ STDCALL +CLIPOBJ_ppoGetPath(PCLIPOBJ ClipObj); + +/* +EngAcquireSemaphore +*/ + +/* FIXME: find correct defines for following symbols */ +#define FL_ZERO_MEMORY 1 + +PVOID STDCALL +EngAllocMem(ULONG Flags, + ULONG MemSize, + ULONG Tag); + +PVOID STDCALL +EngAllocUserMem(ULONG cj, + ULONG tag); + +BOOL STDCALL +EngAssociateSurface(IN HSURF Surface, + IN HDEV Dev, + IN ULONG Hooks); + +BOOL STDCALL +EngBitBlt(SURFOBJ *Dest, + SURFOBJ *Source, + SURFOBJ *Mask, + CLIPOBJ *ClipRegion, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint, + POINTL *MaskRect, + BRUSHOBJ *Brush, + POINTL *BrushOrigin, + ROP4 rop4); + +/* +EngCheckAbort +EngComputeGlyphSet +*/ + +BOOL STDCALL +EngCopyBits(SURFOBJ *Dest, + SURFOBJ *Source, + CLIPOBJ *Clip, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint); + +HBITMAP STDCALL +EngCreateBitmap(IN SIZEL Size, + IN LONG Width, + IN ULONG Format, + IN ULONG Flags, + IN PVOID Bits); + +PCLIPOBJ STDCALL +EngCreateClip(VOID); + +HBITMAP STDCALL +EngCreateDeviceBitmap(IN DHSURF Surface, + IN SIZEL Size, + IN ULONG Format); + +HSURF STDCALL +EngCreateDeviceSurface(IN DHSURF Surface, + IN SIZEL Size, + IN ULONG FormatVersion); + +/* +EngCreateDriverObj +EngCreateEvent +*/ + +HPALETTE STDCALL +EngCreatePalette(IN ULONG Mode, + IN ULONG NumColors, + IN PULONG *Colors, + IN ULONG Red, + IN ULONG Green, + IN ULONG Blue); + +/* +EngCreatePath +EngCreateSemaphore +EngCreateWnd +*/ + +VOID STDCALL +EngDebugBreak(VOID); + +VOID STDCALL +EngDebugPrint(PCHAR StandardPrefix, + PCHAR DebugMessage, + va_list ArgList); + +VOID STDCALL +EngDeleteClip(CLIPOBJ *ClipRegion); + +/* +EngDeleteDriverObj +EngDeleteEvent +*/ + +BOOL STDCALL +EngDeletePalette(IN HPALETTE Palette); + +/* +EngDeletePath +EngDeleteSemaphore +*/ + +BOOL STDCALL +EngDeleteSurface(IN HSURF Surface); + +/* +EngDeleteWnd +*/ + +DWORD STDCALL +EngDeviceIoControl(HANDLE hDevice, + DWORD dwIoControlCode, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + DWORD *lpBytesReturned); + +/* +EngEnumForms +*/ + +BOOL STDCALL +EngEraseSurface(SURFOBJ *Surface, + RECTL *Rect, + ULONG iColor); + +/* +EngFillPath +EngFindImageProcAddress +EngFindResource +*/ + +VOID STDCALL +EngFreeMem(PVOID Mem); + +/* +EngFreeModule +*/ + +VOID STDCALL +EngFreeUserMem(PVOID pv); + +/* +EngGetCurrentCodePage +EngGetDriverName +EngGetFileChangeTime +EngGetFilePath +EngGetForm +EngGetLastError +EngGetPrinter +EngGetPrinterData +EngGetPrinterDataFileName +EngGetProcessHandle +EngGetType1FontList +*/ + +BOOL STDCALL +EngLineTo(SURFOBJ *Surface, + CLIPOBJ *Clip, + BRUSHOBJ *Brush, + LONG x1, + LONG y1, + LONG x2, + LONG y2, + RECTL *RectBounds, + MIX mix); + +HANDLE STDCALL +EngLoadImage(LPWSTR DriverName); + +/* +EngLoadModule +EngLoadModuleForWrite +EngLockDriverObj +*/ + +SURFOBJ * STDCALL +EngLockSurface(IN HSURF Surface); + +/* +EngMapEvent +EngMapFontFile +EngMapModule +EngMarkBandingSurface +EngMovePointer +EngMultiByteToUnicodeN +EngMultiByteToWideChar +*/ + +INT STDCALL EngMulDiv( + INT nMultiplicand, + INT nMultiplier, + INT nDivisor); + +BOOL STDCALL +EngPaint(IN SURFOBJ *Surface, + IN CLIPOBJ *ClipRegion, + IN BRUSHOBJ *Brush, + IN POINTL *BrushOrigin, + IN MIX Mix); + +/* +EngProbeForRead +EngProbeForReadAndWrite = NTOSKRNL.ProbeForWrite +EngQueryLocalTime +EngQueryPalette +EngQueryPerformanceCounter +EngQueryPerformanceFrequency +EngReleaseSemaphore +EngRestoreFloatingPointState +EngSaveFloatingPointState +EngSecureMem +EngSetEvent +EngSetLastError +EngSetPointerShape +EngSetPointerTag +EngSetPrinterData +EngSort +EngStretchBlt +EngStrokeAndFillPath +EngStrokePath +EngTextOut +*/ + +BOOL STDCALL +EngTransparentBlt(PSURFOBJ Dest, + PSURFOBJ Source, + PCLIPOBJ Clip, + PXLATEOBJ ColorTranslation, + PRECTL DestRect, + PRECTL SourceRect, + ULONG TransparentColor, + ULONG Reserved); + +/* +EngUnicodeToMultiByteN +EngUnloadImage +EngUnlockDriverObj +EngUnlockSurface +EngUnmapEvent +EngUnmapFontFile +EngUnsecureMem = NTOSKRNL.MmUnsecureVirtualMemory +EngWaitForSingleObject +EngWideCharToMultiByte +EngWritePrinter +FLOATOBJ_Add +FLOATOBJ_AddFloat +FLOATOBJ_AddFloatObj +FLOATOBJ_AddLong +FLOATOBJ_Div +FLOATOBJ_DivFloat +FLOATOBJ_DivFloatObj +FLOATOBJ_DivLong +FLOATOBJ_Equal +FLOATOBJ_EqualLong +FLOATOBJ_GetFloat +FLOATOBJ_GetLong +FLOATOBJ_GreaterThan +FLOATOBJ_GreaterThanLong +FLOATOBJ_LessThan +FLOATOBJ_LessThanLong +FLOATOBJ_Mul +FLOATOBJ_MulFloat +FLOATOBJ_MulFloatObj +FLOATOBJ_MulLong +FLOATOBJ_Neg +FLOATOBJ_SetFloat +FLOATOBJ_SetLong +FLOATOBJ_Sub +FLOATOBJ_SubFloat +FLOATOBJ_SubFloatObj +FLOATOBJ_SubLong +*/ + +ULONG FONTOBJ_cGetAllGlyphHandles(IN PFONTOBJ FontObj, + IN HGLYPH *Glyphs); +ULONG FONTOBJ_cGetGlyphs(IN PFONTOBJ FontObj, + IN ULONG Mode, + IN ULONG NumGlyphs, + IN HGLYPH *GlyphHandles, + IN PVOID *OutGlyphs); +PGAMMA_TABLES FONTOBJ_pGetGammaTables(IN PFONTOBJ FontObj); +IFIMETRICS *FONTOBJ_pifi(IN PFONTOBJ FontObj); +PVOID FONTOBJ_pvTrueTypeFontFile(IN PFONTOBJ FontObj, + IN ULONG *FileSize); +XFORMOBJ *FONTOBJ_pxoGetXform(IN PFONTOBJ FontObj); +VOID FONTOBJ_vGetInfo(IN PFONTOBJ FontObj, + IN ULONG InfoSize, + OUT PFONTINFO FontInfo); + +/* +HT_ComputeRGBGammaTable +HT_Get8BPPFormatPalette +*/ + +ULONG STDCALL +PALOBJ_cGetColors(PALOBJ *PalObj, + ULONG Start, + ULONG Colors, + ULONG *PaletteEntry); + +/* +PATHOBJ_bCloseFigure +PATHOBJ_bEnum +PATHOBJ_bEnumClipLines +PATHOBJ_bMoveTo +PATHOBJ_bPolyBezierTo +PATHOBJ_bPolyLineTo +PATHOBJ_vEnumStart +PATHOBJ_vEnumStartClipLines +PATHOBJ_vGetBounds +RtlAnsiCharToUnicodeChar = NTOSKRNL.RtlAnsiCharToUnicodeChar +RtlMultiByteToUnicodeN = NTOSKRNL.RtlMultiByteToUnicodeN +RtlRaiseException = NTOSKRNL.RtlRaiseException +RtlUnicodeToMultiByteN = NTOSKRNL.RtlUnicodeToMultiByteN +RtlUnicodeToMultiByteSize = NTOSKRNL.RtlUnicodeToMultiByteSize +RtlUnwind = NTOSKRNL.RtlUnwind +RtlUpcaseUnicodeChar = NTOSKRNL.RtlUpcaseUnicodeChar +RtlUpcaseUnicodeToMultiByteN = NTOSKRNL.RtlUpcaseUnicodeToMultiByteN +STROBJ_bEnum +STROBJ_dwGetCodePage +STROBJ_vEnumStart +WNDOBJ_bEnum +WNDOBJ_cEnumStart +WNDOBJ_vSetConsumer +XFORMOBJ_bApplyXform +XFORMOBJ_iGetFloatObjXform +XFORMOBJ_iGetXform +*/ + +ULONG STDCALL +XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj, + ULONG PalOutType, + ULONG cPal, + ULONG *OutPal); + +ULONG STDCALL +XLATEOBJ_iXlate(XLATEOBJ *XlateObj, + ULONG Color); + +ULONG * STDCALL +XLATEOBJ_piVector(XLATEOBJ *XlateObj); + +#endif + diff --git a/include/ddk/zw.h b/include/ddk/zw.h new file mode 100644 index 0000000..e1c2ad5 --- /dev/null +++ b/include/ddk/zw.h @@ -0,0 +1,5308 @@ + +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: System call definitions + * FILE: include/ddk/zw.h + * REVISION HISTORY: + * ??/??/??: First few functions (David Welch) + * ??/??/??: Complete implementation by Ariadne + * 13/07/98: Reorganised things a bit (David Welch) + * 04/08/98: Added some documentation (Ariadne) + * 14/08/98: Added type TIME and change variable type from [1] to [0] + * 14/09/98: Added for each Nt call a corresponding Zw Call + */ + +#ifndef __DDK_ZW_H +#define __DDK_ZW_H + +#include +#include + +//#define LCID ULONG +//#define SECURITY_INFORMATION ULONG +//typedef ULONG SECURITY_INFORMATION; + + +/* + * FUNCTION: Checks a clients access rights to a object + * ARGUMENTS: + * SecurityDescriptor = Security information against which the access is checked + * ClientToken = Represents a client + * DesiredAcces = + * GenericMapping = + * PrivilegeSet = + * ReturnLength = Bytes written + * GrantedAccess = + * AccessStatus = Indicates if the ClientToken allows the requested access + * REMARKS: The arguments map to the win32 AccessCheck + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtAccessCheck( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAcces, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + OUT PULONG ReturnLength, + OUT PULONG GrantedAccess, + OUT PBOOLEAN AccessStatus + ); + +NTSTATUS +STDCALL +ZwAccessCheck( + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAcces, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + OUT PULONG ReturnLength, + OUT PULONG GrantedAccess, + OUT PBOOLEAN AccessStatus + ); + +/* + * FUNCTION: Checks a clients access rights to a object and issues a audit a alarm. ( it logs the access ) + * ARGUMENTS: + * SubsystemName = Specifies the name of the subsystem, can be "WIN32" or "DEBUG" + * ObjectHandle = + * ObjectAttributes = + * DesiredAcces = + * GenericMapping = + * ObjectCreation = + * GrantedAccess = + * AccessStatus = + * GenerateOnClose = + * REMARKS: The arguments map to the win32 AccessCheck + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtAccessCheckAndAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PHANDLE ObjectHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PULONG GrantedAccess, + OUT PBOOLEAN AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + +NTSTATUS +STDCALL +ZwAccessCheckAndAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PHANDLE ObjectHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PULONG GrantedAccess, + OUT PBOOLEAN AccessStatus, + OUT PBOOLEAN GenerateOnClose + ); + +/* + * FUNCTION: Adds an atom to the global atom table + * ARGUMENTS: + * AtomString = The string to add to the atom table. + * Atom (OUT) = Caller supplies storage for the resulting atom. + * REMARKS: The arguments map to the win32 add GlobalAddAtom. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtAddAtom( + IN PWSTR AtomName, + IN OUT PRTL_ATOM Atom + ); + + +NTSTATUS +STDCALL +ZwAddAtom( + IN PWSTR AtomName, + IN OUT PRTL_ATOM Atom + ); + + +/* + * FUNCTION: Adjusts the groups in an access token + * ARGUMENTS: + * TokenHandle = Specifies the access token + * ResetToDefault = If true the NewState parameter is ignored and the groups are set to + * their default state, if false the groups specified in + * NewState are set. + * NewState = + * BufferLength = Specifies the size of the buffer for the PreviousState. + * PreviousState = + * ReturnLength = Bytes written in PreviousState buffer. + * REMARKS: The arguments map to the win32 AdjustTokenGroups + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtAdjustGroupsToken( + IN HANDLE TokenHandle, + IN BOOLEAN ResetToDefault, + IN PTOKEN_GROUPS NewState, + IN ULONG BufferLength, + OUT PTOKEN_GROUPS PreviousState OPTIONAL, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwAdjustGroupsToken( + IN HANDLE TokenHandle, + IN BOOLEAN ResetToDefault, + IN PTOKEN_GROUPS NewState, + IN ULONG BufferLength, + OUT PTOKEN_GROUPS PreviousState, + OUT PULONG ReturnLength + ); + + +/* + * FUNCTION: + * + * ARGUMENTS: + * TokenHandle = Handle to the access token + * DisableAllPrivileges = The resulting suspend count. + NewState = + BufferLength = + PreviousState = + ReturnLength = + * REMARK: + * The arguments map to the win32 AdjustTokenPrivileges + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtAdjustPrivilegesToken( + IN HANDLE TokenHandle, + IN BOOLEAN DisableAllPrivileges, + IN PTOKEN_PRIVILEGES NewState, + IN ULONG BufferLength, + OUT PTOKEN_PRIVILEGES PreviousState, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwAdjustPrivilegesToken( + IN HANDLE TokenHandle, + IN BOOLEAN DisableAllPrivileges, + IN PTOKEN_PRIVILEGES NewState, + IN ULONG BufferLength, + OUT PTOKEN_PRIVILEGES PreviousState, + OUT PULONG ReturnLength + ); + + +/* + * FUNCTION: Decrements a thread's suspend count and places it in an alerted + * state. + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * SuspendCount = The resulting suspend count. + * REMARK: + * A thread is resumed if its suspend count is 0 + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtAlertResumeThread( + IN HANDLE ThreadHandle, + OUT PULONG SuspendCount + ); + +NTSTATUS +STDCALL +ZwAlertResumeThread( + IN HANDLE ThreadHandle, + OUT PULONG SuspendCount + ); + +/* + * FUNCTION: Puts the thread in a alerted state + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be alerted + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtAlertThread( + IN HANDLE ThreadHandle + ); + +NTSTATUS +STDCALL +ZwAlertThread( + IN HANDLE ThreadHandle + ); + + +/* + * FUNCTION: Allocates a locally unique id + * ARGUMENTS: + * LocallyUniqueId = Locally unique number + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtAllocateLocallyUniqueId( + OUT LUID *LocallyUniqueId + ); + +NTSTATUS +STDCALL +ZwAllocateLocallyUniqueId( + OUT PLUID Luid + ); + +NTSTATUS +STDCALL +NtAllocateUuids( + PULARGE_INTEGER Time, + PULONG Range, + PULONG Sequence + ); + +NTSTATUS +STDCALL +ZwAllocateUuids( + PULARGE_INTEGER Time, + PULONG Range, + PULONG Sequence + ); + + +/* + * FUNCTION: Allocates a block of virtual memory in the process address space + * ARGUMENTS: + * ProcessHandle = The handle of the process which owns the virtual memory + * BaseAddress = A pointer to the virtual memory allocated. If you supply a non zero + * value the system will try to allocate the memory at the address supplied. It rounds + * it down to a multiple if the page size. + * ZeroBits = (OPTIONAL) You can specify the number of high order bits that must be zero, ensuring that + * the memory will be allocated at a address below a certain value. + * RegionSize = The number of bytes to allocate + * AllocationType = Indicates the type of virtual memory you like to allocated, + * can be one of the values : MEM_COMMIT, MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN + * Protect = Indicates the protection type of the pages allocated, can be a combination of + * PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ, + * PAGE_EXECUTE_READWRITE, PAGE_GUARD, PAGE_NOACCESS, PAGE_NOACCESS + * REMARKS: + * This function maps to the win32 VirtualAllocEx. Virtual memory is process based so the + * protocol starts with a ProcessHandle. I splitted the functionality of obtaining the actual address and specifying + * the start address in two parameters ( BaseAddress and StartAddress ) The NumberOfBytesAllocated specify the range + * and the AllocationType and ProctectionType map to the other two parameters. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtAllocateVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN OUT PULONG RegionSize, + IN ULONG AllocationType, + IN ULONG Protect + ); + +NTSTATUS +STDCALL +ZwAllocateVirtualMemory ( + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN OUT PULONG RegionSize, + IN ULONG AllocationType, + IN ULONG Protect); + +/* + * FUNCTION: Returns from a callback into user mode + * ARGUMENTS: + * RETURN Status + */ +//FIXME: this function might need 3 parameters +NTSTATUS STDCALL NtCallbackReturn(PVOID Result, + ULONG ResultLength, + NTSTATUS Status); + +NTSTATUS STDCALL ZwCallbackReturn(PVOID Result, + ULONG ResultLength, + NTSTATUS Status); + +/* + * FUNCTION: Cancels a IO request + * ARGUMENTS: + * FileHandle = Handle to the file + * IoStatusBlock = + * + * REMARKS: + * This function maps to the win32 CancelIo. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCancelIoFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + +NTSTATUS +STDCALL +ZwCancelIoFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); +/* + * FUNCTION: Cancels a timer + * ARGUMENTS: + * TimerHandle = Handle to the timer + * CurrentState = Specifies the state of the timer when cancelled. + * REMARKS: + * The arguments to this function map to the function CancelWaitableTimer. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCancelTimer( + IN HANDLE TimerHandle, + OUT PBOOLEAN CurrentState OPTIONAL + ); + +NTSTATUS +STDCALL +ZwCancelTimer( + IN HANDLE TimerHandle, + OUT ULONG ElapsedTime + ); +/* + * FUNCTION: Sets the status of the event back to non-signaled + * ARGUMENTS: + * EventHandle = Handle to the event + * REMARKS: + * This function maps to win32 function ResetEvent. + * RETURcNS: Status + */ + +NTSTATUS +STDCALL +NtClearEvent( + IN HANDLE EventHandle + ); + +NTSTATUS +STDCALL +ZwClearEvent( + IN HANDLE EventHandle + ); + +/* + * FUNCTION: Closes an object handle + * ARGUMENTS: + * Handle = Handle to the object + * REMARKS: + * This function maps to the win32 function CloseHandle. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtClose( + IN HANDLE Handle + ); + +NTSTATUS +STDCALL +ZwClose( + IN HANDLE Handle + ); + +/* + * FUNCTION: Generates an audit message when a handle to an object is dereferenced + * ARGUMENTS: + * SubsystemName = + HandleId = Handle to the object + GenerateOnClose = + * REMARKS: + * This function maps to the win32 function ObjectCloseAuditAlarm. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCloseObjectAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + +NTSTATUS +STDCALL +ZwCloseObjectAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + +/* + * FUNCTION: Continues a thread with the specified context + * ARGUMENTS: + * Context = Specifies the processor context + * IrqLevel = Specifies the Interupt Request Level to continue with. Can + * be PASSIVE_LEVEL or APC_LEVEL + * REMARKS + * NtContinue can be used to continue after an exception or apc. + * RETURNS: Status + */ +//FIXME This function might need another parameter + +NTSTATUS +STDCALL +NtContinue( + IN PCONTEXT Context, + IN BOOLEAN TestAlert + ); + +NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel); + + +/* + * FUNCTION: Creates a directory object + * ARGUMENTS: + * DirectoryHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies access to the directory + * ObjectAttribute = Initialized attributes for the object + * REMARKS: This function maps to the win32 CreateDirectory. A directory is like a file so it needs a + * handle, a access mask and a OBJECT_ATTRIBUTES structure to map the path name and the SECURITY_ATTRIBUTES. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCreateDirectoryObject( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwCreateDirectoryObject( + OUT PHANDLE DirectoryHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Creates an event object + * ARGUMENTS: + * EventHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies access to the event + * ObjectAttribute = Initialized attributes for the object + * ManualReset = manual-reset or auto-reset if true you have to reset the state of the event manually + * using NtResetEvent/NtClearEvent. if false the system will reset the event to a non-signalled state + * automatically after the system has rescheduled a thread waiting on the event. + * InitialState = specifies the initial state of the event to be signaled ( TRUE ) or non-signalled (FALSE). + * REMARKS: This function maps to the win32 CreateEvent. Demanding a out variable of type HANDLE, + * a access mask and a OBJECT_ATTRIBUTES structure mapping to the SECURITY_ATTRIBUTES. ManualReset and InitialState are + * both parameters aswell ( possibly the order is reversed ). + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCreateEvent( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN ManualReset, + IN BOOLEAN InitialState + ); + +NTSTATUS +STDCALL +ZwCreateEvent( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN ManualReset, + IN BOOLEAN InitialState + ); + +/* + * FUNCTION: Creates an eventpair object + * ARGUMENTS: + * EventPairHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies access to the event + * ObjectAttribute = Initialized attributes for the object + */ + +NTSTATUS +STDCALL +NtCreateEventPair( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwCreateEventPair( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + + +/* + * FUNCTION: Creates or opens a file, directory or device object. + * ARGUMENTS: + * FileHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the file can + * be a combination of DELETE | FILE_READ_DATA .. + * ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename + * IoStatusBlock (OUT) = Caller supplied storage for the resulting status information, indicating if the + * the file is created and opened or allready existed and is just opened. + * FileAttributes = file attributes can be a combination of FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN ... + * ShareAccess = can be a combination of the following: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + * CreateDisposition = specifies what the behavior of the system if the file allready exists. + * CreateOptions = specifies the behavior of the system on file creation. + * EaBuffer (OPTIONAL) = Extended Attributes buffer, applies only to files and directories. + * EaLength = Extended Attributes buffer size, applies only to files and directories. + * REMARKS: This function maps to the win32 CreateFile. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCreateFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength + ); + +NTSTATUS +STDCALL +ZwCreateFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength + ); + +/* + * FUNCTION: Creates or opens a file, directory or device object. + * ARGUMENTS: + * CompletionPort (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the port + * IoStatusBlock = + * NumberOfConcurrentThreads = + * REMARKS: This function maps to the win32 CreateIoCompletionPort + * RETURNS: + * Status + */ + +NTSTATUS +STDCALL +NtCreateIoCompletion( + OUT PHANDLE CompletionPort, + IN ACCESS_MASK DesiredAccess, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NumberOfConcurrentThreads + ); + +NTSTATUS +STDCALL +ZwCreateIoCompletion( + OUT PHANDLE CompletionPort, + IN ACCESS_MASK DesiredAccess, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NumberOfConcurrentThreads + ); + + +/* + * FUNCTION: Creates a mail slot file + * ARGUMENTS: + * MailSlotFileHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the file + * ObjectAttributes = Contains the name of the mailslotfile. + * IoStatusBlock = + * FileAttributes = + * ShareAccess = + * MaxMessageSize = + * TimeOut = + * + * REMARKS: This funciton maps to the win32 function CreateMailSlot + * RETURNS: + * Status + */ + +NTSTATUS +STDCALL +NtCreateMailslotFile( + OUT PHANDLE MailSlotFileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG MaxMessageSize, + IN PLARGE_INTEGER TimeOut + ); + +NTSTATUS +STDCALL +ZwCreateMailslotFile( + OUT PHANDLE MailSlotFileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG MaxMessageSize, + IN PLARGE_INTEGER TimeOut + ); + +/* + * FUNCTION: Creates or opens a mutex + * ARGUMENTS: + * MutantHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the port + * ObjectAttributes = Contains the name of the mutex. + * InitialOwner = If true the calling thread acquires ownership + * of the mutex. + * REMARKS: This funciton maps to the win32 function CreateMutex + * RETURNS: + * Status + */ +NTSTATUS +STDCALL +NtCreateMutant( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN InitialOwner + ); + +NTSTATUS +STDCALL +ZwCreateMutant( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN InitialOwner + ); + + +/* + * FUNCTION: Creates a paging file. + * ARGUMENTS: + * FileName = Name of the pagefile + * InitialSize = Specifies the initial size in bytes + * MaximumSize = Specifies the maximum size in bytes + * Reserved = Reserved for future use + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCreatePagingFile( + IN PUNICODE_STRING FileName, + IN PLARGE_INTEGER InitialSize, + IN PLARGE_INTEGER MaxiumSize, + IN ULONG Reserved + ); + +NTSTATUS +STDCALL +ZwCreatePagingFile( + IN PUNICODE_STRING FileName, + IN PLARGE_INTEGER InitialSize, + IN PLARGE_INTEGER MaxiumSize, + IN ULONG Reserved + ); + +/* + * FUNCTION: Creates a process. + * ARGUMENTS: + * ProcessHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the process can + * be a combinate of STANDARD_RIGHTS_REQUIRED| .. + * ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename + * ParentProcess = Handle to the parent process. + * InheritObjectTable = Specifies to inherit the objects of the parent process if true. + * SectionHandle = Handle to a section object to back the image file + * DebugPort = Handle to a DebugPort if NULL the system default debug port will be used. + * ExceptionPort = Handle to a exception port. + * REMARKS: + * This function maps to the win32 CreateProcess. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCreateProcess( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcess, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL + ); + +NTSTATUS +STDCALL +ZwCreateProcess( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcess, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL + ); + +/* + * FUNCTION: Creates a profile + * ARGUMENTS: + * ProfileHandle (OUT) = Caller supplied storage for the resulting handle + * ObjectAttribute = Initialized attributes for the object + * ImageBase = Start address of executable image + * ImageSize = Size of the image + * Granularity = Bucket size + * Buffer = Caller supplies buffer for profiling info + * ProfilingSize = Buffer size + * ClockSource = Specify 0 / FALSE ?? + * ProcessorMask = A value of -1 indicates disables per processor profiling, + otherwise bit set for the processor to profile. + * REMARKS: + * This function maps to the win32 CreateProcess. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCreateProfile(OUT PHANDLE ProfileHandle, + IN HANDLE ProcessHandle, + IN PVOID ImageBase, + IN ULONG ImageSize, + IN ULONG Granularity, + OUT PULONG Buffer, + IN ULONG ProfilingSize, + IN KPROFILE_SOURCE Source, + IN ULONG ProcessorMask); + +NTSTATUS +STDCALL +ZwCreateProfile( + OUT PHANDLE ProfileHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG ImageBase, + IN ULONG ImageSize, + IN ULONG Granularity, + OUT PVOID Buffer, + IN ULONG ProfilingSize, + IN ULONG ClockSource, + IN ULONG ProcessorMask + ); + +/* + * FUNCTION: Creates a section object. + * ARGUMENTS: + * SectionHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the desired access to the section can be a combination of STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | + * SECTION_MAP_READ | SECTION_MAP_EXECUTE. + * ObjectAttribute = Initialized attributes for the object can be used to create a named section + * MaxiumSize = Maximizes the size of the memory section. Must be non-NULL for a page-file backed section. + * If value specified for a mapped file and the file is not large enough, file will be extended. + * SectionPageProtection = Can be a combination of PAGE_READONLY | PAGE_READWRITE | PAGE_WRITEONLY | PAGE_WRITECOPY. + * AllocationAttributes = can be a combination of SEC_IMAGE | SEC_RESERVE + * FileHanlde = Handle to a file to create a section mapped to a file instead of a memory backed section. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCreateSection( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize OPTIONAL, + IN ULONG SectionPageProtection OPTIONAL, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL + ); + +NTSTATUS +STDCALL +ZwCreateSection( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize OPTIONAL, + IN ULONG SectionPageProtection OPTIONAL, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL + ); + +/* + * FUNCTION: Creates a semaphore object for interprocess synchronization. + * ARGUMENTS: + * SemaphoreHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the semaphore. + * ObjectAttribute = Initialized attributes for the object. + * InitialCount = Not necessary zero, might be smaller than zero. + * MaximumCount = Maxiumum count the semaphore can reach. + * RETURNS: Status + * REMARKS: + * The semaphore is set to signaled when its count is greater than zero, and non-signaled when its count is zero. + */ + +//FIXME: should a semaphore's initial count allowed to be smaller than zero ?? +NTSTATUS +STDCALL +NtCreateSemaphore( + OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN LONG InitialCount, + IN LONG MaximumCount + ); + +NTSTATUS +STDCALL +ZwCreateSemaphore( + OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN LONG InitialCount, + IN LONG MaximumCount + ); + +/* + * FUNCTION: Creates a symbolic link object + * ARGUMENTS: + * SymbolicLinkHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the thread. + * ObjectAttributes = Initialized attributes for the object. + * Name = Target name of the symbolic link + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCreateSymbolicLinkObject( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING Name + ); + +NTSTATUS +STDCALL +ZwCreateSymbolicLinkObject( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING Name + ); + +/* + * FUNCTION: Creates a user mode thread + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the thread. + * ObjectAttributes = Initialized attributes for the object. + * ProcessHandle = Handle to the threads parent process. + * ClientId (OUT) = Caller supplies storage for returned process id and thread id. + * ThreadContext = Initial processor context for the thread. + * InitialTeb = Initial user mode stack context for the thread. + * CreateSuspended = Specifies if the thread is ready for scheduling + * REMARKS: + * This function maps to the win32 function CreateThread. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCreateThread( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, + IN PCONTEXT ThreadContext, + IN PINITIAL_TEB InitialTeb, + IN BOOLEAN CreateSuspended + ); + +NTSTATUS +STDCALL +ZwCreateThread( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, + IN PCONTEXT ThreadContext, + IN PINITIAL_TEB InitialTeb, + IN BOOLEAN CreateSuspended + ); + +/* + * FUNCTION: Creates a waitable timer. + * ARGUMENTS: + * TimerHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the timer. + * ObjectAttributes = Initialized attributes for the object. + * TimerType = Specifies if the timer should be reset manually. + * REMARKS: + * This function maps to the win32 CreateWaitableTimer. lpTimerAttributes and lpTimerName map to + * corresponding fields in OBJECT_ATTRIBUTES structure. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtCreateTimer( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN TIMER_TYPE TimerType + ); + +NTSTATUS +STDCALL +ZwCreateTimer( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN TIMER_TYPE TimerType + ); + +/* + * FUNCTION: Creates a token. + * ARGUMENTS: + * TokenHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Specifies the allowed or desired access to the process can + * be a combinate of STANDARD_RIGHTS_REQUIRED| .. + * ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename + * TokenType = + * AuthenticationId = + * ExpirationTime = + * TokenUser = + * TokenGroups = + * TokenPrivileges = + * TokenOwner = + * TokenPrimaryGroup = + * TokenDefaultDacl = + * TokenSource = + * REMARKS: + * This function does not map to a win32 function + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtCreateToken( + OUT PHANDLE TokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER TokenUser, + IN PTOKEN_GROUPS TokenGroups, + IN PTOKEN_PRIVILEGES TokenPrivileges, + IN PTOKEN_OWNER TokenOwner, + IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, + IN PTOKEN_DEFAULT_DACL TokenDefaultDacl, + IN PTOKEN_SOURCE TokenSource + ); + +NTSTATUS +STDCALL +ZwCreateToken( + OUT PHANDLE TokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER TokenUser, + IN PTOKEN_GROUPS TokenGroups, + IN PTOKEN_PRIVILEGES TokenPrivileges, + IN PTOKEN_OWNER TokenOwner, + IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, + IN PTOKEN_DEFAULT_DACL TokenDefaultDacl, + IN PTOKEN_SOURCE TokenSource + ); + +/* + * FUNCTION: Returns the callers thread TEB. + * RETURNS: The resulting teb. + */ +#if 0 + NT_TEB * +STDCALL +NtCurrentTeb(VOID + ); +#endif + +/* + * FUNCTION: Delays the execution of the calling thread. + * ARGUMENTS: + * Alertable = If TRUE the thread is alertable during is wait period + * Interval = Specifies the interval to wait. + * RETURNS: Status + */ +NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable, IN TIME* Interval); + +NTSTATUS +STDCALL +ZwDelayExecution( + IN BOOLEAN Alertable, + IN TIME *Interval + ); + + +/* + * FUNCTION: Deletes an atom from the global atom table + * ARGUMENTS: + * Atom = Identifies the atom to delete + * REMARKS: + * The function maps to the win32 GlobalDeleteAtom + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtDeleteAtom( + IN RTL_ATOM Atom + ); + +NTSTATUS +STDCALL +ZwDeleteAtom( + IN RTL_ATOM Atom + ); + +/* + * FUNCTION: Deletes a file or a directory + * ARGUMENTS: + * ObjectAttributes = Name of the file which should be deleted + * REMARKS: + * This system call is functionally equivalent to NtSetInformationFile + * setting the disposition information. + * The function maps to the win32 DeleteFile. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtDeleteFile( + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwDeleteFile( + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Deletes a registry key + * ARGUMENTS: + * KeyHandle = Handle of the key + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtDeleteKey( + IN HANDLE KeyHandle + ); +NTSTATUS +STDCALL +ZwDeleteKey( + IN HANDLE KeyHandle + ); + +/* + * FUNCTION: Generates a audit message when an object is deleted + * ARGUMENTS: + * SubsystemName = Spefies the name of the subsystem can be 'WIN32' or 'DEBUG' + * HandleId= Handle to an audit object + * GenerateOnClose = Value returned by NtAccessCheckAndAuditAlarm + * REMARKS: This function maps to the win32 ObjectCloseAuditAlarm + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtDeleteObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + +NTSTATUS +STDCALL +ZwDeleteObjectAuditAlarm ( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose + ); + + +/* + * FUNCTION: Deletes a value from a registry key + * ARGUMENTS: + * KeyHandle = Handle of the key + * ValueName = Name of the value to delete + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtDeleteValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName + ); + +NTSTATUS +STDCALL +ZwDeleteValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName + ); +/* + * FUNCTION: Sends IOCTL to the io sub system + * ARGUMENTS: + * DeviceHandle = Points to the handle that is created by NtCreateFile + * Event = Event to synchronize on STATUS_PENDING + * ApcRoutine = Asynchroneous procedure callback + * ApcContext = Callback context. + * IoStatusBlock = Caller should supply storage for extra information.. + * IoControlCode = Contains the IO Control command. This is an + * index to the structures in InputBuffer and OutputBuffer. + * InputBuffer = Caller should supply storage for input buffer if IOTL expects one. + * InputBufferSize = Size of the input bufffer + * OutputBuffer = Caller should supply storage for output buffer if IOTL expects one. + * OutputBufferSize = Size of the input bufffer + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtDeviceIoControlFile( + IN HANDLE DeviceHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferSize + ); + +NTSTATUS +STDCALL +ZwDeviceIoControlFile( + IN HANDLE DeviceHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferSize + ); +/* + * FUNCTION: Displays a string on the blue screen + * ARGUMENTS: + * DisplayString = The string to display + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtDisplayString( + IN PUNICODE_STRING DisplayString + ); + +NTSTATUS +STDCALL +ZwDisplayString( + IN PUNICODE_STRING DisplayString + ); + +/* + * FUNCTION: Copies a handle from one process space to another + * ARGUMENTS: + * SourceProcessHandle = The source process owning the handle. The source process should have opened + * the SourceHandle with PROCESS_DUP_HANDLE access. + * SourceHandle = The handle to the object. + * TargetProcessHandle = The destination process owning the handle + * TargetHandle (OUT) = Caller should supply storage for the duplicated handle. + * DesiredAccess = The desired access to the handle. + * InheritHandle = Indicates wheter the new handle will be inheritable or not. + * Options = Specifies special actions upon duplicating the handle. Can be + * one of the values DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS. + * DUPLICATE_CLOSE_SOURCE specifies that the source handle should be + * closed after duplicating. DUPLICATE_SAME_ACCESS specifies to ignore + * the DesiredAccess paramter and just grant the same access to the new + * handle. + * RETURNS: Status + * REMARKS: This function maps to the win32 DuplicateHandle. + */ + +NTSTATUS +STDCALL +NtDuplicateObject( + IN HANDLE SourceProcessHandle, + IN HANDLE SourceHandle, + IN HANDLE TargetProcessHandle, + OUT PHANDLE TargetHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN InheritHandle, + IN ULONG Options + ); + +NTSTATUS +STDCALL +ZwDuplicateObject( + IN HANDLE SourceProcessHandle, + IN PHANDLE SourceHandle, + IN HANDLE TargetProcessHandle, + OUT PHANDLE TargetHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN InheritHandle, + IN ULONG Options + ); + +NTSTATUS +STDCALL +NtDuplicateToken( + IN HANDLE ExistingToken, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN TOKEN_TYPE TokenType, + OUT PHANDLE NewToken + ); + +NTSTATUS +STDCALL +ZwDuplicateToken( + IN HANDLE ExistingToken, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN TOKEN_TYPE TokenType, + OUT PHANDLE NewToken + ); +/* + * FUNCTION: Returns information about the subkeys of an open key + * ARGUMENTS: + * KeyHandle = Handle of the key whose subkeys are to enumerated + * Index = zero based index of the subkey for which information is + * request + * KeyInformationClass = Type of information returned + * KeyInformation (OUT) = Caller allocated buffer for the information + * about the key + * Length = Length in bytes of the KeyInformation buffer + * ResultLength (OUT) = Caller allocated storage which holds + * the number of bytes of information retrieved + * on return + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtEnumerateKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwEnumerateKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); +/* + * FUNCTION: Returns information about the value entries of an open key + * ARGUMENTS: + * KeyHandle = Handle of the key whose value entries are to enumerated + * Index = zero based index of the subkey for which information is + * request + * KeyInformationClass = Type of information returned + * KeyInformation (OUT) = Caller allocated buffer for the information + * about the key + * Length = Length in bytes of the KeyInformation buffer + * ResultLength (OUT) = Caller allocated storage which holds + * the number of bytes of information retrieved + * on return + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtEnumerateValueKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwEnumerateValueKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); +/* + * FUNCTION: Extends a section + * ARGUMENTS: + * SectionHandle = Handle to the section + * NewMaximumSize = Adjusted size + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtExtendSection( + IN HANDLE SectionHandle, + IN ULONG NewMaximumSize + ); +NTSTATUS +STDCALL +ZwExtendSection( + IN HANDLE SectionHandle, + IN ULONG NewMaximumSize + ); + +/* + * FUNCTION: Finds a atom + * ARGUMENTS: + * AtomName = Name to search for. + * Atom = Caller supplies storage for the resulting atom + * RETURNS: Status + * REMARKS: + * This funciton maps to the win32 GlobalFindAtom + */ +NTSTATUS +STDCALL +NtFindAtom( + IN PWSTR AtomName, + OUT PRTL_ATOM Atom OPTIONAL + ); + +NTSTATUS +STDCALL +ZwFindAtom( + IN PWSTR AtomName, + OUT PRTL_ATOM Atom OPTIONAL + ); + +/* + * FUNCTION: Flushes chached file data to disk + * ARGUMENTS: + * FileHandle = Points to the file + * IoStatusBlock = Caller must supply storage to receive the result of the flush + * buffers operation. The information field is set to number of bytes + * flushed to disk. + * RETURNS: Status + * REMARKS: + * This funciton maps to the win32 FlushFileBuffers + */ +NTSTATUS +STDCALL +NtFlushBuffersFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + +NTSTATUS +STDCALL +ZwFlushBuffersFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); +/* + * FUNCTION: Flushes a the processors instruction cache + * ARGUMENTS: + * ProcessHandle = Points to the process owning the cache + * BaseAddress = // might this be a image address ???? + * NumberOfBytesToFlush = + * RETURNS: Status + * REMARKS: + * This funciton is used by debuggers + */ +NTSTATUS +STDCALL +NtFlushInstructionCache( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN UINT NumberOfBytesToFlush + ); +NTSTATUS +STDCALL +ZwFlushInstructionCache( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN UINT NumberOfBytesToFlush + ); +/* + * FUNCTION: Flushes a registry key to disk + * ARGUMENTS: + * KeyHandle = Points to the registry key handle + * RETURNS: Status + * REMARKS: + * This funciton maps to the win32 RegFlushKey. + */ +NTSTATUS +STDCALL +NtFlushKey( + IN HANDLE KeyHandle + ); + +NTSTATUS +STDCALL +ZwFlushKey( + IN HANDLE KeyHandle + ); + +/* + * FUNCTION: Flushes virtual memory to file + * ARGUMENTS: + * ProcessHandle = Points to the process that allocated the virtual memory + * BaseAddress = Points to the memory address + * NumberOfBytesToFlush = Limits the range to flush, + * NumberOfBytesFlushed = Actual number of bytes flushed + * RETURNS: Status + * REMARKS: + * Check return status on STATUS_NOT_MAPPED_DATA + */ +NTSTATUS +STDCALL +NtFlushVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToFlush, + OUT PULONG NumberOfBytesFlushed OPTIONAL + ); +NTSTATUS +STDCALL +ZwFlushVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToFlush, + OUT PULONG NumberOfBytesFlushed OPTIONAL + ); + +/* + * FUNCTION: Flushes the dirty pages to file + * RETURNS: Status + * FIXME: Not sure this does (how is the file specified) + */ +NTSTATUS STDCALL NtFlushWriteBuffer(VOID); +NTSTATUS STDCALL ZwFlushWriteBuffer(VOID); + + /* + * FUNCTION: Frees a range of virtual memory + * ARGUMENTS: + * ProcessHandle = Points to the process that allocated the virtual + * memory + * BaseAddress = Points to the memory address, rounded down to a + * multiple of the pagesize + * RegionSize = Limits the range to free, rounded up to a multiple of + * the paging size + * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE + * RETURNS: Status + */ +NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN PULONG RegionSize, + IN ULONG FreeType); +NTSTATUS STDCALL ZwFreeVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID *BaseAddress, + IN PULONG RegionSize, + IN ULONG FreeType); + +/* + * FUNCTION: Sends FSCTL to the filesystem + * ARGUMENTS: + * DeviceHandle = Points to the handle that is created by NtCreateFile + * Event = Event to synchronize on STATUS_PENDING + * ApcRoutine = + * ApcContext = + * IoStatusBlock = Caller should supply storage for + * IoControlCode = Contains the File System Control command. This is an + * index to the structures in InputBuffer and OutputBuffer. + * FSCTL_GET_RETRIEVAL_POINTERS MAPPING_PAIR + * FSCTL_GET_RETRIEVAL_POINTERS GET_RETRIEVAL_DESCRIPTOR + * FSCTL_GET_VOLUME_BITMAP BITMAP_DESCRIPTOR + * FSCTL_MOVE_FILE MOVEFILE_DESCRIPTOR + * + * InputBuffer = Caller should supply storage for input buffer if FCTL expects one. + * InputBufferSize = Size of the input bufffer + * OutputBuffer = Caller should supply storage for output buffer if FCTL expects one. + * OutputBufferSize = Size of the input bufffer + * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES | + * STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST ] + */ +NTSTATUS +STDCALL +NtFsControlFile( + IN HANDLE DeviceHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferSize + ); + +NTSTATUS +STDCALL +ZwFsControlFile( + IN HANDLE DeviceHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferSize + ); + +/* + * FUNCTION: Retrieves the processor context of a thread + * ARGUMENTS: + * ThreadHandle = Handle to a thread + * Context (OUT) = Caller allocated storage for the processor context + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtGetContextThread( + IN HANDLE ThreadHandle, + OUT PCONTEXT Context + ); + +NTSTATUS +STDCALL +ZwGetContextThread( + IN HANDLE ThreadHandle, + OUT PCONTEXT Context + ); +/* + * FUNCTION: Retrieves the uptime of the system + * ARGUMENTS: + * UpTime = Number of clock ticks since boot. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtGetTickCount( + PULONG UpTime + ); + +NTSTATUS +STDCALL +ZwGetTickCount( + PULONG UpTime + ); + +/* + * FUNCTION: Sets a thread to impersonate another + * ARGUMENTS: + * ThreadHandle = Server thread that will impersonate a client. + ThreadToImpersonate = Client thread that will be impersonated + SecurityQualityOfService = Specifies the impersonation level. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtImpersonateThread( + IN HANDLE ThreadHandle, + IN HANDLE ThreadToImpersonate, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService + ); + +NTSTATUS +STDCALL +ZwImpersonateThread( + IN HANDLE ThreadHandle, + IN HANDLE ThreadToImpersonate, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService + ); + +/* + * FUNCTION: Initializes the registry. + * ARGUMENTS: + * SetUpBoot = This parameter is true for a setup boot. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtInitializeRegistry( + BOOLEAN SetUpBoot + ); +NTSTATUS +STDCALL +ZwInitializeRegistry( + BOOLEAN SetUpBoot + ); + +/* + * FUNCTION: Loads a driver. + * ARGUMENTS: + * DriverServiceName = Name of the driver to load + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtLoadDriver( + IN PUNICODE_STRING DriverServiceName + ); + +NTSTATUS +STDCALL +ZwLoadDriver( + IN PUNICODE_STRING DriverServiceName + ); + +/* + * FUNCTION: Loads a registry key. + * ARGUMENTS: + * KeyHandle = Handle to the registry key + * ObjectAttributes = ??? + * REMARK: + * This procedure maps to the win32 procedure RegLoadKey + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtLoadKey( + PHANDLE KeyHandle, + POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwLoadKey( + PHANDLE KeyHandle, + POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Loads a registry key. + * ARGUMENTS: + * KeyHandle = Handle to the registry key + * ObjectAttributes = ??? + * Unknown3 = ??? + * REMARK: + * This procedure maps to the win32 procedure RegLoadKey + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtLoadKey2 ( + PHANDLE KeyHandle, + POBJECT_ATTRIBUTES ObjectAttributes, + ULONG Unknown3 + ); +NTSTATUS +STDCALL +ZwLoadKey2 ( + PHANDLE KeyHandle, + POBJECT_ATTRIBUTES ObjectAttributes, + ULONG Unknown3 + ); + +/* + * FUNCTION: Locks a range of bytes in a file. + * ARGUMENTS: + * FileHandle = Handle to the file + * Event = Should be null if apc is specified. + * ApcRoutine = Asynchroneous Procedure Callback + * ApcContext = Argument to the callback + * IoStatusBlock (OUT) = Caller should supply storage for a structure containing + * the completion status and information about the requested lock operation. + * ByteOffset = Offset + * Length = Number of bytes to lock. + * Key = Special value to give other threads the possibility to unlock the file + by supplying the key in a call to NtUnlockFile. + * FailImmediatedly = If false the request will block untill the lock is obtained. + * ExclusiveLock = Specifies whether a exclusive or a shared lock is obtained. + * REMARK: + This procedure maps to the win32 procedure LockFileEx. STATUS_PENDING is returned if the lock could + not be obtained immediately, the device queue is busy and the IRP is queued. + * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES | + STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_LOCK_NOT_GRANTED ] + + */ +NTSTATUS +STDCALL +NtLockFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN PULONG Key, + IN BOOLEAN FailImmediatedly, + IN BOOLEAN ExclusiveLock + ); + +NTSTATUS +STDCALL +ZwLockFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN PULONG Key, + IN BOOLEAN FailImmediatedly, + IN BOOLEAN ExclusiveLock + ); +/* + * FUNCTION: Locks a range of virtual memory. + * ARGUMENTS: + * ProcessHandle = Handle to the process + * BaseAddress = Lower boundary of the range of bytes to lock. + * NumberOfBytesLock = Offset to the upper boundary. + * NumberOfBytesLocked (OUT) = Number of bytes actually locked. + * REMARK: + This procedure maps to the win32 procedure VirtualLock + * RETURNS: Status [STATUS_SUCCESS | STATUS_WAS_LOCKED ] + */ +NTSTATUS +STDCALL +NtLockVirtualMemory( + HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToLock, + PULONG NumberOfBytesLocked + ); +NTSTATUS +STDCALL +ZwLockVirtualMemory( + HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToLock, + PULONG NumberOfBytesLocked + ); +/* + * FUNCTION: Makes temporary object that will be removed at next boot. + * ARGUMENTS: + * Handle = Handle to object + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtMakeTemporaryObject( + IN HANDLE Handle + ); + +NTSTATUS +STDCALL +ZwMakeTemporaryObject( + IN HANDLE Handle + ); +/* + * FUNCTION: Maps a view of a section into the virtual address space of a + * process + * ARGUMENTS: + * SectionHandle = Handle of the section + * ProcessHandle = Handle of the process + * BaseAddress = Desired base address (or NULL) on entry + * Actual base address of the view on exit + * ZeroBits = Number of high order address bits that must be zero + * CommitSize = Size in bytes of the initially committed section of + * the view + * SectionOffset = Offset in bytes from the beginning of the section + * to the beginning of the view + * ViewSize = Desired length of map (or zero to map all) on entry + * Actual length mapped on exit + * InheritDisposition = Specified how the view is to be shared with + * child processes + * AllocateType = Type of allocation for the pages + * Protect = Protection for the committed region of the view + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtMapViewOfSection( + IN HANDLE SectionHandle, + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN ULONG CommitSize, + IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, + IN OUT PULONG ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG AccessProtection + ); + +NTSTATUS +STDCALL +ZwMapViewOfSection( + IN HANDLE SectionHandle, + IN HANDLE ProcessHandle, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN ULONG CommitSize, + IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, + IN OUT PULONG ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG AccessProtection + ); + +/* + * FUNCTION: Installs a notify for the change of a directory's contents + * ARGUMENTS: + * FileHandle = Handle to the directory + Event = + * ApcRoutine = Start address + * ApcContext = Delimits the range of virtual memory + * for which the new access protection holds + * IoStatusBlock = The new access proctection for the pages + * Buffer = Caller supplies storage for resulting information --> FILE_NOTIFY_INFORMATION + * BufferSize = Size of the buffer + CompletionFilter = Can be one of the following values: + FILE_NOTIFY_CHANGE_FILE_NAME + FILE_NOTIFY_CHANGE_DIR_NAME + FILE_NOTIFY_CHANGE_NAME ( FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME ) + FILE_NOTIFY_CHANGE_ATTRIBUTES + FILE_NOTIFY_CHANGE_SIZE + FILE_NOTIFY_CHANGE_LAST_WRITE + FILE_NOTIFY_CHANGE_LAST_ACCESS + FILE_NOTIFY_CHANGE_CREATION ( change of creation timestamp ) + FILE_NOTIFY_CHANGE_EA + FILE_NOTIFY_CHANGE_SECURITY + FILE_NOTIFY_CHANGE_STREAM_NAME + FILE_NOTIFY_CHANGE_STREAM_SIZE + FILE_NOTIFY_CHANGE_STREAM_WRITE + WatchTree = If true the notify will be installed recursively on the targetdirectory and all subdirectories. + * + * REMARKS: + * The function maps to the win32 FindFirstChangeNotification, FindNextChangeNotification + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtNotifyChangeDirectoryFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG BufferSize, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree + ); + +NTSTATUS +STDCALL +ZwNotifyChangeDirectoryFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG BufferSize, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree + ); + +/* + * FUNCTION: Installs a notfication callback on registry changes + * ARGUMENTS: + KeyHandle = Handle to the registry key + Event = Event that should be signalled on modification of the key + ApcRoutine = Routine that should be called on modification of the key + ApcContext = Argument to the ApcRoutine + IoStatusBlock = ??? + CompletionFilter = Specifies the kind of notification the caller likes to receive. + Can be a combination of the following values: + + REG_NOTIFY_CHANGE_NAME + REG_NOTIFY_CHANGE_ATTRIBUTES + REG_NOTIFY_CHANGE_LAST_SET + REG_NOTIFY_CHANGE_SECURITY + + + Asynchroneous = If TRUE the changes are reported by signalling an event if false + the function will not return before a change occurs. + ChangeBuffer = Will return the old value + Length = Size of the change buffer + WatchSubtree = Indicates if the caller likes to receive a notification of changes in + sub keys or not. + * REMARKS: If the key is closed the event is signalled aswell. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtNotifyChangeKey( + IN HANDLE KeyHandle, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN Asynchroneous, + OUT PVOID ChangeBuffer, + IN ULONG Length, + IN BOOLEAN WatchSubtree + ); + +NTSTATUS +STDCALL +ZwNotifyChangeKey( + IN HANDLE KeyHandle, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN Asynchroneous, + OUT PVOID ChangeBuffer, + IN ULONG Length, + IN BOOLEAN WatchSubtree + ); + +/* + * FUNCTION: Opens an existing directory object + * ARGUMENTS: + * FileHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the directory + * ObjectAttributes = Initialized attributes for the object + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtOpenDirectoryObject( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwOpenDirectoryObject( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Opens an existing event + * ARGUMENTS: + * EventHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the event + * ObjectAttributes = Initialized attributes for the object + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenEvent( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwOpenEvent( + OUT PHANDLE EventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Opens an existing event pair + * ARGUMENTS: + * EventHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the event + * ObjectAttributes = Initialized attributes for the object + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtOpenEventPair( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwOpenEventPair( + OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +/* + * FUNCTION: Opens an existing file + * ARGUMENTS: + * FileHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the file + * ObjectAttributes = Initialized attributes for the object + * IoStatusBlock = + * ShareAccess = + * OpenOptions = + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions + ); + +NTSTATUS +STDCALL +ZwOpenFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions + ); + +/* + * FUNCTION: Opens an existing io completion object + * ARGUMENTS: + * CompletionPort (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the io completion object + * ObjectAttributes = Initialized attributes for the object + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtOpenIoCompletion( + OUT PHANDLE CompetionPort, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwOpenIoCompletion( + OUT PHANDLE CompetionPort, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Opens an existing key in the registry + * ARGUMENTS: + * KeyHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the key + * ObjectAttributes = Initialized attributes for the object + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +ZwOpenKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +/* + * FUNCTION: Opens an existing key in the registry + * ARGUMENTS: + * MutantHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the mutant + * ObjectAttribute = Initialized attributes for the object + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenMutant( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwOpenMutant( + OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +NTSTATUS +STDCALL +NtOpenObjectAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ClientToken, + IN ULONG DesiredAccess, + IN ULONG GrantedAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN ObjectCreation, + IN BOOLEAN AccessGranted, + OUT PBOOLEAN GenerateOnClose + ); + +NTSTATUS +STDCALL +ZwOpenObjectAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ClientToken, + IN ULONG DesiredAccess, + IN ULONG GrantedAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN ObjectCreation, + IN BOOLEAN AccessGranted, + OUT PBOOLEAN GenerateOnClose + ); +/* + * FUNCTION: Opens an existing process + * ARGUMENTS: + * ProcessHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the process + * ObjectAttribute = Initialized attributes for the object + * ClientId = Identifies the process id to open + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId + ); +NTSTATUS +STDCALL +ZwOpenProcess ( + OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId + ); +/* + * FUNCTION: Opens an existing process + * ARGUMENTS: + * ProcessHandle = Handle of the process of which owns the token + * DesiredAccess = Requested access to the token + * TokenHandle (OUT) = Caller supplies storage for the resulting token. + * REMARKS: + This function maps to the win32 + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtOpenProcessToken( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle + ); + +NTSTATUS +STDCALL +ZwOpenProcessToken( + IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle + ); + +/* + * FUNCTION: Opens an existing section object + * ARGUMENTS: + * KeyHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the key + * ObjectAttribute = Initialized attributes for the object + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtOpenSection( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwOpenSection( + OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +/* + * FUNCTION: Opens an existing semaphore + * ARGUMENTS: + * SemaphoreHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the semaphore + * ObjectAttribute = Initialized attributes for the object + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenSemaphore( + IN HANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAcces, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwOpenSemaphore( + IN HANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAcces, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +/* + * FUNCTION: Opens an existing symbolic link + * ARGUMENTS: + * SymbolicLinkHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the symbolic link + * ObjectAttribute = Initialized attributes for the object + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenSymbolicLinkObject( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwOpenSymbolicLinkObject( + OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +/* + * FUNCTION: Opens an existing thread + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the thread + * ObjectAttribute = Initialized attributes for the object + * ClientId = Identifies the thread to open. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenThread( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId + ); +NTSTATUS +STDCALL +ZwOpenThread( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId + ); + +NTSTATUS +STDCALL +NtOpenThreadToken( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle + ); + +NTSTATUS +STDCALL +ZwOpenThreadToken( + IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle + ); +/* + * FUNCTION: Opens an existing timer + * ARGUMENTS: + * TimerHandle (OUT) = Caller supplied storage for the resulting handle + * DesiredAccess = Requested access to the timer + * ObjectAttribute = Initialized attributes for the object + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtOpenTimer( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); +NTSTATUS +STDCALL +ZwOpenTimer( + OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ); + +/* + * FUNCTION: Checks an access token for specific privileges + * ARGUMENTS: + * ClientToken = Handle to a access token structure + * RequiredPrivileges = Specifies the requested privileges. + * Result = Caller supplies storage for the result. If PRIVILEGE_SET_ALL_NECESSARY is + set in the Control member of PRIVILEGES_SET Result + will only be TRUE if all privileges are present in the access token. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtPrivilegeCheck( + IN HANDLE ClientToken, + IN PPRIVILEGE_SET RequiredPrivileges, + IN PBOOLEAN Result + ); + +NTSTATUS +STDCALL +ZwPrivilegeCheck( + IN HANDLE ClientToken, + IN PPRIVILEGE_SET RequiredPrivileges, + IN PBOOLEAN Result + ); + +NTSTATUS +STDCALL +NtPrivilegedServiceAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PUNICODE_STRING ServiceName, + IN HANDLE ClientToken, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + +NTSTATUS +STDCALL +ZwPrivilegedServiceAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PUNICODE_STRING ServiceName, + IN HANDLE ClientToken, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + +NTSTATUS +STDCALL +NtPrivilegeObjectAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN HANDLE ClientToken, + IN ULONG DesiredAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + +NTSTATUS +STDCALL +ZwPrivilegeObjectAuditAlarm( + IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN HANDLE ClientToken, + IN ULONG DesiredAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted + ); + +/* + * FUNCTION: Entry point for native applications + * ARGUMENTS: + * Peb = Pointes to the Process Environment Block (PEB) + * REMARKS: + * Native applications should use this function instead of a main. + * Calling proces should terminate itself. + * RETURNS: Status + */ +VOID STDCALL +NtProcessStartup( + IN PPEB Peb + ); + +/* + * FUNCTION: Set the access protection of a range of virtual memory + * ARGUMENTS: + * ProcessHandle = Handle to process owning the virtual address space + * BaseAddress = Start address + * NumberOfBytesToProtect = Delimits the range of virtual memory + * for which the new access protection holds + * NewAccessProtection = The new access proctection for the pages + * OldAccessProtection = Caller should supply storage for the old + * access protection + * + * REMARKS: + * The function maps to the win32 VirtualProtectEx + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection + ); + +NTSTATUS +STDCALL +ZwProtectVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG OldAccessProtection + ); + + +/* + * FUNCTION: Signals an event and resets it afterwards. + * ARGUMENTS: + * EventHandle = Handle to the event + * PulseCount = Number of times the action is repeated + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtPulseEvent( + IN HANDLE EventHandle, + IN PULONG PulseCount OPTIONAL + ); + +NTSTATUS +STDCALL +ZwPulseEvent( + IN HANDLE EventHandle, + IN PULONG PulseCount OPTIONAL + ); + +/* + * FUNCTION: Queries the attributes of a file + * ARGUMENTS: + * ObjectAttributes = Initialized attributes for the object + * Buffer = Caller supplies storage for the attributes + * RETURNS: Status + */ + +NTSTATUS STDCALL +NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_BASIC_INFORMATION FileInformation); + +NTSTATUS STDCALL +ZwQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_BASIC_INFORMATION FileInformation); + +/* + * FUNCTION: Queries the default locale id + * ARGUMENTS: + * UserProfile = Type of locale id + * TRUE: thread locale id + * FALSE: system locale id + * DefaultLocaleId = Caller supplies storage for the locale id + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtQueryDefaultLocale( + IN BOOLEAN UserProfile, + OUT PLCID DefaultLocaleId + ); + +NTSTATUS +STDCALL +ZwQueryDefaultLocale( + IN BOOLEAN UserProfile, + OUT PLCID DefaultLocaleId + ); + +/* + * FUNCTION: Queries a directory file. + * ARGUMENTS: + * FileHandle = Handle to a directory file + * EventHandle = Handle to the event signaled on completion + * ApcRoutine = Asynchroneous procedure callback, called on completion + * ApcContext = Argument to the apc. + * IoStatusBlock = Caller supplies storage for extended status information. + * FileInformation = Caller supplies storage for the resulting information. + * + * FileNameInformation FILE_NAMES_INFORMATION + * FileDirectoryInformation FILE_DIRECTORY_INFORMATION + * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION + * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION + * + * Length = Size of the storage supplied + * FileInformationClass = Indicates the type of information requested. + * ReturnSingleEntry = Specify true if caller only requests the first directory found. + * FileName = Initial directory name to query, that may contain wild cards. + * RestartScan = Number of times the action should be repeated + * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES, + * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW, + * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ] + */ + +NTSTATUS +STDCALL +NtQueryDirectoryFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN PUNICODE_STRING FileName OPTIONAL, + IN BOOLEAN RestartScan + ); + +NTSTATUS +STDCALL +ZwQueryDirectoryFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN PUNICODE_STRING FileName OPTIONAL, + IN BOOLEAN RestartScan + ); + +/* + * FUNCTION: Query information about the content of a directory object + * ARGUMENTS: + DirObjInformation = Buffer must be large enough to hold the name strings too + GetNextIndex = If TRUE :return the index of the next object in this directory in ObjectIndex + If FALSE: return the number of objects in this directory in ObjectIndex + IgnoreInputIndex= If TRUE: ignore input value of ObjectIndex always start at index 0 + If FALSE use input value of ObjectIndex + ObjectIndex = zero based index of object in the directory depends on GetNextIndex and IgnoreInputIndex + DataWritten = Actual size of the ObjectIndex ??? + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtQueryDirectoryObject( + IN HANDLE DirObjHandle, + OUT POBJDIR_INFORMATION DirObjInformation, + IN ULONG BufferLength, + IN BOOLEAN GetNextIndex, + IN BOOLEAN IgnoreInputIndex, + IN OUT PULONG ObjectIndex, + OUT PULONG DataWritten OPTIONAL + ); + +NTSTATUS +STDCALL +ZwQueryDirectoryObject( + IN HANDLE DirObjHandle, + OUT POBJDIR_INFORMATION DirObjInformation, + IN ULONG BufferLength, + IN BOOLEAN GetNextIndex, + IN BOOLEAN IgnoreInputIndex, + IN OUT PULONG ObjectIndex, + OUT PULONG DataWritten OPTIONAL + ); + +/* + * FUNCTION: Queries the extended attributes of a file + * ARGUMENTS: + * FileHandle = Handle to the event + * IoStatusBlock = Number of times the action is repeated + * Buffer + * Length + * ReturnSingleEntry + * EaList + * EaListLength + * EaIndex + * RestartScan + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtQueryEaFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN PVOID EaList OPTIONAL, + IN ULONG EaListLength, + IN PULONG EaIndex OPTIONAL, + IN BOOLEAN RestartScan + ); + +NTSTATUS +STDCALL +ZwQueryEaFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN PVOID EaList OPTIONAL, + IN ULONG EaListLength, + IN PULONG EaIndex OPTIONAL, + IN BOOLEAN RestartScan + ); + +/* + * FUNCTION: Queries an event + * ARGUMENTS: + * EventHandle = Handle to the event + * EventInformationClass = Index of the information structure + + EventBasicInformation EVENT_BASIC_INFORMATION + + * EventInformation = Caller supplies storage for the information structure + * EventInformationLength = Size of the information structure + * ReturnLength = Data written + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtQueryEvent( + IN HANDLE EventHandle, + IN EVENT_INFORMATION_CLASS EventInformationClass, + OUT PVOID EventInformation, + IN ULONG EventInformationLength, + OUT PULONG ReturnLength + ); +NTSTATUS +STDCALL +ZwQueryEvent( + IN HANDLE EventHandle, + IN EVENT_INFORMATION_CLASS EventInformationClass, + OUT PVOID EventInformation, + IN ULONG EventInformationLength, + OUT PULONG ReturnLength + ); + +NTSTATUS STDCALL +NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation); + +NTSTATUS STDCALL +ZwQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation); + +NTSTATUS +STDCALL +NtQueryInformationAtom( + IN RTL_ATOM Atom, + IN ATOM_INFORMATION_CLASS AtomInformationClass, + OUT PVOID AtomInformation, + IN ULONG AtomInformationLength, + OUT PULONG ReturnLength OPTIONAL + ); + +NTSTATUS +STDCALL +NtQueryInformationAtom( + IN RTL_ATOM Atom, + IN ATOM_INFORMATION_CLASS AtomInformationClass, + OUT PVOID AtomInformation, + IN ULONG AtomInformationLength, + OUT PULONG ReturnLength OPTIONAL + ); + + +/* + * FUNCTION: Queries the information of a file object. + * ARGUMENTS: + * FileHandle = Handle to the file object + * IoStatusBlock = Caller supplies storage for extended information + * on the current operation. + * FileInformation = Storage for the new file information + * Lenght = Size of the storage for the file information. + * FileInformationClass = Indicates which file information is queried + + FileDirectoryInformation FILE_DIRECTORY_INFORMATION + FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION + FileBothDirectoryInformation FILE_BOTH_DIRECTORY_INFORMATION + FileBasicInformation FILE_BASIC_INFORMATION + FileStandardInformation FILE_STANDARD_INFORMATION + FileInternalInformation FILE_INTERNAL_INFORMATION + FileEaInformation FILE_EA_INFORMATION + FileAccessInformation FILE_ACCESS_INFORMATION + FileNameInformation FILE_NAME_INFORMATION + FileRenameInformation FILE_RENAME_INFORMATION + FileLinkInformation + FileNamesInformation FILE_NAMES_INFORMATION + FileDispositionInformation FILE_DISPOSITION_INFORMATION + FilePositionInformation FILE_POSITION_INFORMATION + FileFullEaInformation FILE_FULL_EA_INFORMATION + FileModeInformation FILE_MODE_INFORMATION + FileAlignmentInformation FILE_ALIGNMENT_INFORMATION + FileAllInformation FILE_ALL_INFORMATION + + FileEndOfFileInformation FILE_END_OF_FILE_INFORMATION + FileAlternateNameInformation + FileStreamInformation FILE_STREAM_INFORMATION + FilePipeInformation + FilePipeLocalInformation + FilePipeRemoteInformation + FileMailslotQueryInformation + FileMailslotSetInformation + FileCompressionInformation FILE_COMPRESSION_INFORMATION + FileCopyOnWriteInformation + FileCompletionInformation IO_COMPLETION_CONTEXT + FileMoveClusterInformation + FileOleClassIdInformation + FileOleStateBitsInformation + FileNetworkOpenInformation FILE_NETWORK_OPEN_INFORMATION + FileObjectIdInformation + FileOleAllInformation + FileOleDirectoryInformation + FileContentIndexInformation + FileInheritContentIndexInformation + FileOleInformation + FileMaximumInformation + + * REMARK: + * This procedure maps to the win32 GetShortPathName, GetLongPathName, + GetFullPathName, GetFileType, GetFileSize, GetFileTime functions. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtQueryInformationFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + +NTSTATUS +STDCALL +ZwQueryInformationFile( + HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass + ); + +/* + * FUNCTION: Queries the information of a process object. + * ARGUMENTS: + * ProcessHandle = Handle to the process object + * ProcessInformation = Index to a certain information structure + + ProcessBasicInformation PROCESS_BASIC_INFORMATION + ProcessQuotaLimits QUOTA_LIMITS + ProcessIoCounters IO_COUNTERS + ProcessVmCounters VM_COUNTERS + ProcessTimes KERNEL_USER_TIMES + ProcessBasePriority KPRIORITY + ProcessRaisePriority KPRIORITY + ProcessDebugPort HANDLE + ProcessExceptionPort HANDLE + ProcessAccessToken PROCESS_ACCESS_TOKEN + ProcessLdtInformation LDT_ENTRY ?? + ProcessLdtSize ULONG + ProcessDefaultHardErrorMode ULONG + ProcessIoPortHandlers // kernel mode only + ProcessPooledUsageAndLimits POOLED_USAGE_AND_LIMITS + ProcessWorkingSetWatch PROCESS_WS_WATCH_INFORMATION + ProcessUserModeIOPL (I/O Privilege Level) + ProcessEnableAlignmentFaultFixup BOOLEAN + ProcessPriorityClass ULONG + ProcessWx86Information ULONG + ProcessHandleCount ULONG + ProcessAffinityMask ULONG + ProcessPooledQuotaLimits QUOTA_LIMITS + MaxProcessInfoClass + + * ProcessInformation = Caller supplies storage for the process information structure + * ProcessInformationLength = Size of the process information structure + * ReturnLength = Actual number of bytes written + + * REMARK: + * This procedure maps to the win32 GetProcessTimes, GetProcessVersion, + GetProcessWorkingSetSize, GetProcessPriorityBoost, GetProcessAffinityMask, GetPriorityClass, + GetProcessShutdownParameters functions. + * RETURNS: Status +*/ + +NTSTATUS +STDCALL +NtQueryInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwQueryInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength + ); + + +/* + * FUNCTION: Queries the information of a thread object. + * ARGUMENTS: + * ThreadHandle = Handle to the thread object + * ThreadInformationClass = Index to a certain information structure + + ThreadBasicInformation THREAD_BASIC_INFORMATION + ThreadTimes KERNEL_USER_TIMES + ThreadPriority KPRIORITY + ThreadBasePriority KPRIORITY + ThreadAffinityMask KAFFINITY + ThreadImpersonationToken + ThreadDescriptorTableEntry + ThreadEnableAlignmentFaultFixup + ThreadEventPair + ThreadQuerySetWin32StartAddress + ThreadZeroTlsCell + ThreadPerformanceCount + ThreadAmILastThread BOOLEAN + ThreadIdealProcessor ULONG + ThreadPriorityBoost ULONG + MaxThreadInfoClass + + + * ThreadInformation = Caller supplies torage for the thread information + * ThreadInformationLength = Size of the thread information structure + * ReturnLength = Actual number of bytes written + + * REMARK: + * This procedure maps to the win32 GetThreadTimes, GetThreadPriority, + GetThreadPriorityBoost functions. + * RETURNS: Status +*/ + + +NTSTATUS +STDCALL +NtQueryInformationThread( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + OUT PVOID ThreadInformation, + IN ULONG ThreadInformationLength, + OUT PULONG ReturnLength + ); + + +NTSTATUS +STDCALL +NtQueryInformationToken( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwQueryInformationToken( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength + ); + +/* + * FUNCTION: Query the interval and the clocksource for profiling + * ARGUMENTS: + Interval = + ClockSource = + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtQueryIntervalProfile( + OUT PULONG Interval, + OUT KPROFILE_SOURCE ClockSource + ); + +NTSTATUS +STDCALL +ZwQueryIntervalProfile( + OUT PULONG Interval, + OUT KPROFILE_SOURCE ClockSource + ); + + + +NTSTATUS +STDCALL +NtQueryIoCompletion( + IN HANDLE CompletionPort, + IN ULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PULONG NumberOfBytesTransferred + ); +NTSTATUS +STDCALL +ZwQueryIoCompletion( + IN HANDLE CompletionPort, + IN ULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PULONG NumberOfBytesTransferred + ); + + +/* + * FUNCTION: Queries the information of a registry key object. + * ARGUMENTS: + KeyHandle = Handle to a registry key + KeyInformationClass = Index to a certain information structure + KeyInformation = Caller supplies storage for resulting information + Length = Size of the supplied storage + ResultLength = Bytes written + */ +NTSTATUS +STDCALL +NtQueryKey( + IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwQueryKey( + IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + +// draft + +NTSTATUS +STDCALL +NtQueryMultipleValueKey( + IN HANDLE KeyHandle, + IN OUT PKEY_VALUE_ENTRY ValueList, + IN ULONG NumberOfValues, + OUT PVOID Buffer, + IN OUT PULONG Length, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwQueryMultipleValueKey( + IN HANDLE KeyHandle, + IN OUT PKEY_VALUE_ENTRY ValueList, + IN ULONG NumberOfValues, + OUT PVOID Buffer, + IN OUT PULONG Length, + OUT PULONG ReturnLength + ); + +/* + * FUNCTION: Queries the information of a mutant object. + * ARGUMENTS: + MutantHandle = Handle to a mutant + MutantInformationClass = Index to a certain information structure + MutantInformation = Caller supplies storage for resulting information + Length = Size of the supplied storage + ResultLength = Bytes written + */ +NTSTATUS +STDCALL +NtQueryMutant( + IN HANDLE MutantHandle, + IN CINT MutantInformationClass, + OUT PVOID MutantInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwQueryMutant( + IN HANDLE MutantHandle, + IN CINT MutantInformationClass, + OUT PVOID MutantInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); +/* + * FUNCTION: Queries the information of a object. + * ARGUMENTS: + ObjectHandle = Handle to a object + ObjectInformationClass = Index to a certain information structure + + ObjectBasicInformation + ObjectTypeInformation OBJECT_TYPE_INFORMATION + ObjectNameInformation OBJECT_NAME_INFORMATION + ObjectDataInformation OBJECT_DATA_INFORMATION + + ObjectInformation = Caller supplies storage for resulting information + Length = Size of the supplied storage + ResultLength = Bytes written + */ + +NTSTATUS +STDCALL +NtQueryObject( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwQueryObject( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +/* + * FUNCTION: Queries the system ( high-resolution ) performance counter. + * ARGUMENTS: + * Counter = Performance counter + * Frequency = Performance frequency + * REMARKS: + This procedure queries a tick count faster than 10ms ( The resolution for Intel®-based CPUs is about 0.8 microseconds.) + This procedure maps to the win32 QueryPerformanceCounter, QueryPerformanceFrequency + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQueryPerformanceCounter( + IN PLARGE_INTEGER Counter, + IN PLARGE_INTEGER Frequency + ); + +NTSTATUS +STDCALL +ZwQueryPerformanceCounter( + IN PLARGE_INTEGER Counter, + IN PLARGE_INTEGER Frequency + ); +/* + * FUNCTION: Queries the information of a section object. + * ARGUMENTS: + * SectionHandle = Handle to the section link object + * SectionInformationClass = Index to a certain information structure + * SectionInformation (OUT)= Caller supplies storage for resulting information + * Length = Size of the supplied storage + * ResultLength = Data written + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQuerySection( + IN HANDLE SectionHandle, + IN CINT SectionInformationClass, + OUT PVOID SectionInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwQuerySection( + IN HANDLE SectionHandle, + IN CINT SectionInformationClass, + OUT PVOID SectionInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +NtQuerySecurityObject( + IN HANDLE Object, + IN CINT SecurityObjectInformationClass, + OUT PVOID SecurityObjectInformation, + IN ULONG Length, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwQuerySecurityObject( + IN HANDLE Object, + IN CINT SecurityObjectInformationClass, + OUT PVOID SecurityObjectInformation, + IN ULONG Length, + OUT PULONG ReturnLength + ); + + +/* + * FUNCTION: Queries the information of a semaphore. + * ARGUMENTS: + * SemaphoreHandle = Handle to the semaphore object + * SemaphoreInformationClass = Index to a certain information structure + + SemaphoreBasicInformation SEMAPHORE_BASIC_INFORMATION + + * SemaphoreInformation = Caller supplies storage for the semaphore information structure + * Length = Size of the infomation structure + */ +NTSTATUS +STDCALL +NtQuerySemaphore( + IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG Length, + OUT PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwQuerySemaphore( + IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG Length, + OUT PULONG ReturnLength + ); + + +/* + * FUNCTION: Queries the information of a symbolic link object. + * ARGUMENTS: + * SymbolicLinkHandle = Handle to the symbolic link object + * LinkTarget = resolved name of link + * DataWritten = size of the LinkName. + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQuerySymbolicLinkObject( + IN HANDLE SymLinkObjHandle, + OUT PUNICODE_STRING LinkTarget, + OUT PULONG DataWritten OPTIONAL + ); + +NTSTATUS +STDCALL +ZwQuerySymbolicLinkObject( + IN HANDLE SymLinkObjHandle, + OUT PUNICODE_STRING LinkName, + OUT PULONG DataWritten OPTIONAL + ); + + +/* + * FUNCTION: Queries a system environment variable. + * ARGUMENTS: + * Name = Name of the variable + * Value (OUT) = value of the variable + * Length = size of the buffer + * ReturnLength = data written + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQuerySystemEnvironmentValue( + IN PUNICODE_STRING Name, + OUT PVOID Value, + ULONG Length, + PULONG ReturnLength + ); + +NTSTATUS +STDCALL +ZwQuerySystemEnvironmentValue( + IN PUNICODE_STRING Name, + OUT PVOID Value, + ULONG Length, + PULONG ReturnLength + ); + + +/* + * FUNCTION: Queries the system information. + * ARGUMENTS: + * SystemInformationClass = Index to a certain information structure + + SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT + SystemCacheInformation SYSTEM_CACHE_INFORMATION + SystemConfigurationInformation CONFIGURATION_INFORMATION + + * SystemInformation = caller supplies storage for the information structure + * Length = size of the structure + ResultLength = Data written + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQuerySystemInformation( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT PVOID SystemInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwQuerySystemInformation( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT PVOID SystemInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +/* + * FUNCTION: Retrieves the system time + * ARGUMENTS: + * CurrentTime (OUT) = Caller should supply storage for the resulting time. + * RETURNS: Status + * +*/ + +NTSTATUS +STDCALL +NtQuerySystemTime ( + OUT TIME *CurrentTime + ); + +NTSTATUS +STDCALL +ZwQuerySystemTime ( + OUT TIME *CurrentTime + ); + +/* + * FUNCTION: Queries information about a timer + * ARGUMENTS: + * TimerHandle = Handle to the timer + TimerValueInformationClass = Index to a certain information structure + TimerValueInformation = Caller supplies storage for the information structure + Length = Size of the information structure + ResultLength = Data written + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQueryTimer( + IN HANDLE TimerHandle, + IN CINT TimerInformationClass, + OUT PVOID TimerInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); +NTSTATUS +STDCALL +ZwQueryTimer( + IN HANDLE TimerHandle, + IN CINT TimerInformationClass, + OUT PVOID TimerInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +/* + * FUNCTION: Queries the timer resolution + * ARGUMENTS: + * MinimumResolution (OUT) = Caller should supply storage for the resulting time. + Maximum Resolution (OUT) = Caller should supply storage for the resulting time. + ActualResolution (OUT) = Caller should supply storage for the resulting time. + * RETURNS: Status + * +*/ + + +NTSTATUS +STDCALL +NtQueryTimerResolution ( + OUT PULONG MinimumResolution, + OUT PULONG MaximumResolution, + OUT PULONG ActualResolution + ); + +NTSTATUS +STDCALL +ZwQueryTimerResolution ( + OUT PULONG MinimumResolution, + OUT PULONG MaximumResolution, + OUT PULONG ActualResolution + ); + +/* + * FUNCTION: Queries a registry key value + * ARGUMENTS: + * KeyHandle = Handle to the registry key + ValueName = Name of the value in the registry key + KeyValueInformationClass = Index to a certain information structure + + KeyValueBasicInformation = KEY_VALUE_BASIC_INFORMATION + KeyValueFullInformation = KEY_FULL_INFORMATION + KeyValuePartialInformation = KEY_VALUE_PARTIAL_INFORMATION + + KeyValueInformation = Caller supplies storage for the information structure + Length = Size of the information structure + ResultLength = Data written + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtQueryValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +NTSTATUS +STDCALL +ZwQueryValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + + + + +/* + * FUNCTION: Queries the virtual memory information. + * ARGUMENTS: + ProcessHandle = Process owning the virtual address space + BaseAddress = Points to the page where the information is queried for. + * VirtualMemoryInformationClass = Index to a certain information structure + + MemoryBasicInformation MEMORY_BASIC_INFORMATION + + * VirtualMemoryInformation = caller supplies storage for the information structure + * Length = size of the structure + ResultLength = Data written + * RETURNS: Status + * +*/ + +NTSTATUS +STDCALL +NtQueryVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID Address, + IN IN CINT VirtualMemoryInformationClass, + OUT PVOID VirtualMemoryInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); +NTSTATUS +STDCALL +ZwQueryVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID Address, + IN IN CINT VirtualMemoryInformationClass, + OUT PVOID VirtualMemoryInformation, + IN ULONG Length, + OUT PULONG ResultLength + ); + +/* + * FUNCTION: Queries the volume information + * ARGUMENTS: + * FileHandle = Handle to a file object on the target volume + * IoStatusBlock = Caller should supply storage for additional status information + * ReturnLength = DataWritten + * FsInformation = Caller should supply storage for the information structure. + * Length = Size of the information structure + * FsInformationClass = Index to a information structure + + FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION + FileFsLabelInformation FILE_FS_LABEL_INFORMATION + FileFsSizeInformation FILE_FS_SIZE_INFORMATION + FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION + FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION + FileFsControlInformation + FileFsQuotaQueryInformation -- + FileFsQuotaSetInformation -- + FileFsMaximumInformation + + * RETURNS: Status [ STATUS_SUCCESS | STATUS_INSUFFICIENT_RESOURCES | STATUS_INVALID_PARAMETER | + STATUS_INVALID_DEVICE_REQUEST | STATUS_BUFFER_OVERFLOW ] + * +*/ +NTSTATUS +STDCALL +NtQueryVolumeInformationFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + +NTSTATUS +STDCALL +ZwQueryVolumeInformationFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); +// draft +// FIXME: Should I specify if the apc is user or kernel mode somewhere ?? +/* + * FUNCTION: Queues a (user) apc to a thread. + * ARGUMENTS: + ThreadHandle = Thread to which the apc is queued. + ApcRoutine = Points to the apc routine + NormalContext = Argument to Apc Routine + * SystemArgument1 = Argument of the Apc Routine + SystemArgument2 = Argument of the Apc Routine + * REMARK: If the apc is queued against a thread of a different process than the calling thread + the apc routine should be specified in the address space of the queued thread's process. + * RETURNS: Status +*/ + +NTSTATUS +STDCALL +NtQueueApcThread( + HANDLE ThreadHandle, + PKNORMAL_ROUTINE ApcRoutine, + PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + +NTSTATUS +STDCALL +ZwQueueApcThread( + HANDLE ThreadHandle, + PKNORMAL_ROUTINE ApcRoutine, + PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2); + + +/* + * FUNCTION: Raises an exception + * ARGUMENTS: + * ExceptionRecord = Structure specifying the exception + * Context = Context in which the excpetion is raised + * IsDebugger = + * RETURNS: Status + * +*/ + +NTSTATUS +STDCALL +NtRaiseException( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN BOOLEAN SearchFrames + ); + +NTSTATUS +STDCALL +ZwRaiseException( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN BOOLEAN SearchFrames + ); + +/* + * FUNCTION: Raises a hard error (stops the system) + * ARGUMENTS: + * Status = Status code of the hard error + * Unknown2 = ?? + * Unknown3 = ?? + * Unknown4 = ?? + * Unknown5 = ?? + * Unknown6 = ?? + * RETURNS: Status + * + */ + +NTSTATUS +STDCALL +NtRaiseHardError( + IN NTSTATUS Status, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6 + ); + +NTSTATUS +STDCALL +ZwRaiseHardError( + IN NTSTATUS Status, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6 + ); + +/* + * FUNCTION: Read a file + * ARGUMENTS: + * FileHandle = Handle of a file to read + * Event = This event is signalled when the read operation completes + * UserApcRoutine = Call back , if supplied Event should be NULL + * UserApcContext = Argument to the callback + * IoStatusBlock = Caller should supply storage for additional status information + * Buffer = Caller should supply storage to receive the information + * BufferLength = Size of the buffer + * ByteOffset = Offset to start reading the file + * Key = If a range is lock a matching key will allow the read to continue. + * RETURNS: Status + * + */ + +NTSTATUS +STDCALL +NtReadFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); + +NTSTATUS +STDCALL +ZwReadFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); +/* + * FUNCTION: Read a file using scattered io + * ARGUMENTS: + FileHandle = Handle of a file to read + Event = This event is signalled when the read operation completes + * UserApcRoutine = Call back , if supplied Event should be NULL + UserApcContext = Argument to the callback + IoStatusBlock = Caller should supply storage for additional status information + BufferDescription = Caller should supply storage to receive the information + BufferLength = Size of the buffer + ByteOffset = Offset to start reading the file + Key = Key = If a range is lock a matching key will allow the read to continue. + * RETURNS: Status + * +*/ +NTSTATUS +STDCALL +NtReadFileScatter( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK UserIoStatusBlock, + IN FILE_SEGMENT_ELEMENT BufferDescription[], + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ); + +NTSTATUS +STDCALL +ZwReadFileScatter( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK UserIoStatusBlock, + IN FILE_SEGMENT_ELEMENT BufferDescription[], + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ); +/* + * FUNCTION: Copies a range of virtual memory to a buffer + * ARGUMENTS: + * ProcessHandle = Specifies the process owning the virtual address space + * BaseAddress = Points to the address of virtual memory to start the read + * Buffer = Caller supplies storage to copy the virtual memory to. + * NumberOfBytesToRead = Limits the range to read + * NumberOfBytesRead = The actual number of bytes read. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtReadVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + OUT PVOID Buffer, + IN ULONG NumberOfBytesToRead, + OUT PULONG NumberOfBytesRead + ); +NTSTATUS +STDCALL +ZwReadVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + OUT PVOID Buffer, + IN ULONG NumberOfBytesToRead, + OUT PULONG NumberOfBytesRead + ); + + +/* + * FUNCTION: Debugger can register for thread termination + * ARGUMENTS: + * TerminationPort = Port on which the debugger likes to be notified. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtRegisterThreadTerminatePort( + HANDLE TerminationPort + ); +NTSTATUS +STDCALL +ZwRegisterThreadTerminatePort( + HANDLE TerminationPort + ); + +/* + * FUNCTION: Releases a mutant + * ARGUMENTS: + * MutantHandle = Handle to the mutant + * ReleaseCount = + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtReleaseMutant( + IN HANDLE MutantHandle, + IN PULONG ReleaseCount OPTIONAL + ); + +NTSTATUS +STDCALL +ZwReleaseMutant( + IN HANDLE MutantHandle, + IN PULONG ReleaseCount OPTIONAL + ); + +/* + * FUNCTION: Releases a semaphore + * ARGUMENTS: + * SemaphoreHandle = Handle to the semaphore object + * ReleaseCount = Number to decrease the semaphore count + * PreviousCount = Previous semaphore count + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtReleaseSemaphore( + IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT PLONG PreviousCount + ); + +NTSTATUS +STDCALL +ZwReleaseSemaphore( + IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT PLONG PreviousCount + ); + +/* + * FUNCTION: Removes an io completion + * ARGUMENTS: + * CompletionPort (OUT) = Caller supplied storage for the resulting handle + * CompletionKey = Requested access to the key + * IoStatusBlock = Caller provides storage for extended status information + * CompletionStatus = Current status of the io operation. + * WaitTime = Time to wait if .. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtRemoveIoCompletion( + IN HANDLE CompletionPort, + OUT PULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PULONG CompletionStatus, + IN PLARGE_INTEGER WaitTime + ); + +NTSTATUS +STDCALL +ZwRemoveIoCompletion( + IN HANDLE CompletionPort, + OUT PULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PULONG CompletionStatus, + IN PLARGE_INTEGER WaitTime + ); +/* + * FUNCTION: Replaces one registry key with another + * ARGUMENTS: + * ObjectAttributes = Specifies the attributes of the key + * Key = Handle to the key + * ReplacedObjectAttributes = The function returns the old object attributes + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtReplaceKey( + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE Key, + IN POBJECT_ATTRIBUTES ReplacedObjectAttributes + ); +NTSTATUS +STDCALL +ZwReplaceKey( + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE Key, + IN POBJECT_ATTRIBUTES ReplacedObjectAttributes + ); + +/* + * FUNCTION: Resets a event to a non signaled state + * ARGUMENTS: + * EventHandle = Handle to the event that should be reset + * NumberOfWaitingThreads = The number of threads released. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtResetEvent( + HANDLE EventHandle, + PULONG NumberOfWaitingThreads OPTIONAL + ); +NTSTATUS +STDCALL +ZwResetEvent( + HANDLE EventHandle, + PULONG NumberOfWaitingThreads OPTIONAL + ); +//draft +NTSTATUS +STDCALL +NtRestoreKey( + HANDLE KeyHandle, + HANDLE FileHandle, + ULONG RestoreFlags + ); + +NTSTATUS +STDCALL +ZwRestoreKey( + HANDLE KeyHandle, + HANDLE FileHandle, + ULONG RestoreFlags + ); +/* + * FUNCTION: Decrements a thread's resume count + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * ResumeCount = The resulting resume count. + * REMARK: + * A thread is resumed if its suspend count is 0. This procedure maps to + * the win32 ResumeThread function. ( documentation about the the suspend count can be found here aswell ) + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtResumeThread( + IN HANDLE ThreadHandle, + OUT PULONG SuspendCount + ); +NTSTATUS +STDCALL +ZwResumeThread( + IN HANDLE ThreadHandle, + OUT PULONG SuspendCount + ); +/* + * FUNCTION: Writes the content of a registry key to ascii file + * ARGUMENTS: + * KeyHandle = Handle to the key + * FileHandle = Handle of the file + * REMARKS: + This function maps to the Win32 RegSaveKey. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtSaveKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle + ); +NTSTATUS +STDCALL +ZwSaveKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle + ); + +/* + * FUNCTION: Sets the context of a specified thread. + * ARGUMENTS: + * ThreadHandle = Handle to the thread + * Context = The processor context. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtSetContextThread( + IN HANDLE ThreadHandle, + IN PCONTEXT Context + ); +NTSTATUS +STDCALL +ZwSetContextThread( + IN HANDLE ThreadHandle, + IN PCONTEXT Context + ); + +/* + * FUNCTION: Sets the default locale id + * ARGUMENTS: + * UserProfile = Type of locale id + * TRUE: thread locale id + * FALSE: system locale id + * DefaultLocaleId = Locale id + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtSetDefaultLocale( + IN BOOLEAN UserProfile, + IN LCID DefaultLocaleId + ); + +NTSTATUS +STDCALL +ZwSetDefaultLocale( + IN BOOLEAN UserProfile, + IN LCID DefaultLocaleId + ); + +/* + * FUNCTION: Sets the default hard error port + * ARGUMENTS: + * PortHandle = Handle to the port + * NOTE: The hard error port is used for first change exception handling + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtSetDefaultHardErrorPort( + IN HANDLE PortHandle + ); +NTSTATUS +STDCALL +ZwSetDefaultHardErrorPort( + IN HANDLE PortHandle + ); + +/* + * FUNCTION: Sets the extended attributes of a file. + * ARGUMENTS: + * FileHandle = Handle to the file + * IoStatusBlock = Storage for a resulting status and information + * on the current operation. + * EaBuffer = Extended Attributes buffer. + * EaBufferSize = Size of the extended attributes buffer + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtSetEaFile( + IN HANDLE FileHandle, + IN PIO_STATUS_BLOCK IoStatusBlock, + PVOID EaBuffer, + ULONG EaBufferSize + ); +NTSTATUS +STDCALL +ZwSetEaFile( + IN HANDLE FileHandle, + IN PIO_STATUS_BLOCK IoStatusBlock, + PVOID EaBuffer, + ULONG EaBufferSize + ); + +//FIXME: should I return the event state ? + +/* + * FUNCTION: Sets the event to a signalled state. + * ARGUMENTS: + * EventHandle = Handle to the event + * NumberOfThreadsReleased = The number of threads released + * REMARK: + * This procedure maps to the win32 SetEvent function. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtSetEvent( + IN HANDLE EventHandle, + PULONG NumberOfThreadsReleased + ); + +NTSTATUS +STDCALL +ZwSetEvent( + IN HANDLE EventHandle, + PULONG NumberOfThreadsReleased + ); + +/* + * FUNCTION: Sets the high part of an event pair + * ARGUMENTS: + EventPair = Handle to the event pair + * RETURNS: Status +*/ + +NTSTATUS +STDCALL +NtSetHighEventPair( + IN HANDLE EventPairHandle + ); + +NTSTATUS +STDCALL +ZwSetHighEventPair( + IN HANDLE EventPairHandle + ); +/* + * FUNCTION: Sets the high part of an event pair and wait for the low part + * ARGUMENTS: + EventPair = Handle to the event pair + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetHighWaitLowEventPair( + IN HANDLE EventPairHandle + ); +NTSTATUS +STDCALL +ZwSetHighWaitLowEventPair( + IN HANDLE EventPairHandle + ); + +/* + * FUNCTION: Sets the information of a file object. + * ARGUMENTS: + * FileHandle = Handle to the file object + * IoStatusBlock = Caller supplies storage for extended information + * on the current operation. + * FileInformation = Storage for the new file information + * Lenght = Size of the new file information. + * FileInformationClass = Indicates to a certain information structure + + FileNameInformation FILE_NAME_INFORMATION + FileRenameInformation FILE_RENAME_INFORMATION + FileStreamInformation FILE_STREAM_INFORMATION + * FileCompletionInformation IO_COMPLETION_CONTEXT + + * REMARK: + * This procedure maps to the win32 SetEndOfFile, SetFileAttributes, + * SetNamedPipeHandleState, SetMailslotInfo functions. + * RETURNS: Status + */ + + +NTSTATUS +STDCALL +NtSetInformationFile( + IN HANDLE FileHandle, + IN PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); +NTSTATUS +STDCALL +ZwSetInformationFile( + IN HANDLE FileHandle, + IN PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass + ); + + + +/* + * FUNCTION: Sets the information of a registry key. + * ARGUMENTS: + * KeyHandle = Handle to the registry key + * KeyInformationClass = Index to the a certain information structure. + Can be one of the following values: + + * KeyWriteTimeInformation KEY_WRITE_TIME_INFORMATION + + KeyInformation = Storage for the new information + * KeyInformationLength = Size of the information strucure + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtSetInformationKey( + IN HANDLE KeyHandle, + IN CINT KeyInformationClass, + IN PVOID KeyInformation, + IN ULONG KeyInformationLength + ); + +NTSTATUS +STDCALL +ZwSetInformationKey( + IN HANDLE KeyHandle, + IN CINT KeyInformationClass, + IN PVOID KeyInformation, + IN ULONG KeyInformationLength + ); +/* + * FUNCTION: Changes a set of object specific parameters + * ARGUMENTS: + * ObjectHandle = + * ObjectInformationClass = Index to the set of parameters to change. + + + ObjectBasicInformation + ObjectTypeInformation OBJECT_TYPE_INFORMATION + ObjectAllInformation + ObjectDataInformation OBJECT_DATA_INFORMATION + ObjectNameInformation OBJECT_NAME_INFORMATION + + + * ObjectInformation = Caller supplies storage for parameters to set. + * Length = Size of the storage supplied + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetInformationObject( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG Length + ); + +NTSTATUS +STDCALL +ZwSetInformationObject( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG Length + ); + +/* + * FUNCTION: Changes a set of process specific parameters + * ARGUMENTS: + * ProcessHandle = Handle to the process + * ProcessInformationClass = Index to a information structure. + * + * ProcessBasicInformation PROCESS_BASIC_INFORMATION + * ProcessQuotaLimits QUOTA_LIMITS + * ProcessBasePriority KPRIORITY + * ProcessRaisePriority KPRIORITY + * ProcessDebugPort HANDLE + * ProcessExceptionPort HANDLE + * ProcessAccessToken PROCESS_ACCESS_TOKEN + * ProcessDefaultHardErrorMode ULONG + * ProcessPriorityClass ULONG + * ProcessAffinityMask KAFFINITY //?? + * + * ProcessInformation = Caller supplies storage for information to set. + * ProcessInformationLength = Size of the information structure + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength + ); +NTSTATUS +STDCALL +ZwSetInformationProcess( + IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength + ); +/* + * FUNCTION: Changes a set of thread specific parameters + * ARGUMENTS: + * ThreadHandle = Handle to the thread + * ThreadInformationClass = Index to the set of parameters to change. + * Can be one of the following values: + * + * ThreadBasicInformation THREAD_BASIC_INFORMATION + * ThreadPriority KPRIORITY //??? + * ThreadBasePriority KPRIORITY + * ThreadAffinityMask KAFFINITY //?? + * ThreadImpersonationToken ACCESS_TOKEN + * ThreadIdealProcessor ULONG + * ThreadPriorityBoost ULONG + * + * ThreadInformation = Caller supplies storage for parameters to set. + * ThreadInformationLength = Size of the storage supplied + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetInformationThread( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + IN PVOID ThreadInformation, + IN ULONG ThreadInformationLength + ); +NTSTATUS +STDCALL +ZwSetInformationThread( + IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + IN PVOID ThreadInformation, + IN ULONG ThreadInformationLength + ); + +/* + * FUNCTION: Changes a set of token specific parameters + * ARGUMENTS: + * TokenHandle = Handle to the token + * TokenInformationClass = Index to a certain information structure. + * Can be one of the following values: + * + TokenUser TOKEN_USER + TokenGroups TOKEN_GROUPS + TokenPrivileges TOKEN_PRIVILEGES + TokenOwner TOKEN_OWNER + TokenPrimaryGroup TOKEN_PRIMARY_GROUP + TokenDefaultDacl TOKEN_DEFAULT_DACL + TokenSource TOKEN_SOURCE + TokenType TOKEN_TYPE + TokenImpersonationLevel TOKEN_IMPERSONATION_LEVEL + TokenStatistics TOKEN_STATISTICS + * + * TokenInformation = Caller supplies storage for information structure. + * TokenInformationLength = Size of the information structure + * RETURNS: Status +*/ + +NTSTATUS +STDCALL +NtSetInformationToken( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength + ); + +NTSTATUS +STDCALL +ZwSetInformationToken( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength + ); + + +/* + * FUNCTION: Sets an io completion + * ARGUMENTS: + * CompletionPort = + * CompletionKey = + * IoStatusBlock = + * NumberOfBytesToTransfer = + * NumberOfBytesTransferred = + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetIoCompletion( + IN HANDLE CompletionPort, + IN ULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NumberOfBytesToTransfer, + OUT PULONG NumberOfBytesTransferred + ); +NTSTATUS +STDCALL +ZwSetIoCompletion( + IN HANDLE CompletionPort, + IN ULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NumberOfBytesToTransfer, + OUT PULONG NumberOfBytesTransferred + ); + +/* + * FUNCTION: Set properties for profiling + * ARGUMENTS: + * Interval = + * ClockSource = + * RETURNS: Status + * + */ + +NTSTATUS +STDCALL +NtSetIntervalProfile( + ULONG Interval, + KPROFILE_SOURCE ClockSource + ); + +NTSTATUS +STDCALL +ZwSetIntervalProfile( + ULONG Interval, + KPROFILE_SOURCE ClockSource + ); + + +/* + * FUNCTION: Sets the low part of an event pair + * ARGUMENTS: + EventPair = Handle to the event pair + * RETURNS: Status +*/ + +NTSTATUS +STDCALL +NtSetLowEventPair( + HANDLE EventPair + ); +NTSTATUS +STDCALL +ZwSetLowEventPair( + HANDLE EventPair + ); +/* + * FUNCTION: Sets the low part of an event pair and wait for the high part + * ARGUMENTS: + EventPair = Handle to the event pair + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetLowWaitHighEventPair( + HANDLE EventPair + ); +NTSTATUS +STDCALL +ZwSetLowWaitHighEventPair( + HANDLE EventPair + ); + +NTSTATUS +STDCALL +NtSetSecurityObject( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor + ); + +NTSTATUS +STDCALL +ZwSetSecurityObject( + IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor + ); + + +/* + * FUNCTION: Sets a system environment variable + * ARGUMENTS: + * ValueName = Name of the environment variable + * Value = Value of the environment variable + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetSystemEnvironmentValue( + IN PUNICODE_STRING VariableName, + IN PUNICODE_STRING Value + ); +NTSTATUS +STDCALL +ZwSetSystemEnvironmentValue( + IN PUNICODE_STRING VariableName, + IN PUNICODE_STRING Value + ); +/* + * FUNCTION: Sets system parameters + * ARGUMENTS: + * SystemInformationClass = Index to a particular set of system parameters + * Can be one of the following values: + * + * SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT + * + * SystemInformation = Structure containing the parameters. + * SystemInformationLength = Size of the structure. + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetSystemInformation( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN PVOID SystemInformation, + IN ULONG SystemInformationLength + ); + +NTSTATUS +STDCALL +ZwSetSystemInformation( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN PVOID SystemInformation, + IN ULONG SystemInformationLength + ); + +/* + * FUNCTION: Sets the system time + * ARGUMENTS: + * SystemTime = Old System time + * NewSystemTime = New System time + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetSystemTime( + IN PLARGE_INTEGER SystemTime, + IN PLARGE_INTEGER NewSystemTime OPTIONAL + ); +NTSTATUS +STDCALL +ZwSetSystemTime( + IN PLARGE_INTEGER SystemTime, + IN PLARGE_INTEGER NewSystemTime OPTIONAL + ); +/* + * FUNCTION: Sets the characteristics of a timer + * ARGUMENTS: + * TimerHandle = Handle to the timer + * DueTime = Time before the timer becomes signalled for the first time. + * TimerApcRoutine = Completion routine can be called on time completion + * TimerContext = Argument to the completion routine + * Resume = Specifies if the timer should repeated after completing one cycle + * Period = Cycle of the timer + * REMARKS: This routine maps to the win32 SetWaitableTimer. + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetTimer( + IN HANDLE TimerHandle, + IN PLARGE_INTEGER DueTime, + IN PTIMERAPCROUTINE TimerApcRoutine, + IN PVOID TimerContext, + IN BOOL WakeTimer, + IN ULONG Period OPTIONAL, + OUT PBOOLEAN PreviousState OPTIONAL + ); +NTSTATUS +STDCALL +ZwSetTimer( + IN HANDLE TimerHandle, + IN PLARGE_INTEGER DueTime, + IN PTIMERAPCROUTINE TimerApcRoutine, + IN PVOID TimerContext, + IN BOOL WakeTimer, + IN ULONG Period OPTIONAL, + OUT PBOOLEAN PreviousState OPTIONAL + ); + +/* + * FUNCTION: Sets the frequency of the system timer + * ARGUMENTS: + * RequestedResolution = + * SetOrUnset = + * ActualResolution = + * RETURNS: Status +*/ +NTSTATUS +STDCALL +NtSetTimerResolution( + IN ULONG RequestedResolution, + IN BOOL SetOrUnset, + OUT PULONG ActualResolution + ); +NTSTATUS +STDCALL +ZwSetTimerResolution( + IN ULONG RequestedResolution, + IN BOOL SetOrUnset, + OUT PULONG ActualResolution + ); + +/* + * FUNCTION: Sets the value of a registry key + * ARGUMENTS: + * KeyHandle = Handle to a registry key + * ValueName = Name of the value entry to change + * TitleIndex = pointer to a structure containing the new volume information + * Type = Type of the registry key. Can be one of the values: + * REG_BINARY Unspecified binary data + * REG_DWORD A 32 bit value + * REG_DWORD_LITTLE_ENDIAN Same as REG_DWORD + * REG_DWORD_BIG_ENDIAN A 32 bit value whose least significant byte is at the highest address + * REG_EXPAND_SZ A zero terminated wide character string with unexpanded environment variables ( "%PATH%" ) + * REG_LINK A zero terminated wide character string referring to a symbolic link. + * REG_MULTI_SZ A series of zero-terminated strings including a additional trailing zero + * REG_NONE Unspecified type + * REG_SZ A wide character string ( zero terminated ) + * REG_RESOURCE_LIST ?? + * REG_RESOURCE_REQUIREMENTS_LIST ?? + * REG_FULL_RESOURCE_DESCRIPTOR ?? + * Data = Contains the data for the registry key. + * DataSize = size of the data. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtSetValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN ULONG TitleIndex OPTIONAL, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize + ); +NTSTATUS +STDCALL +ZwSetValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN ULONG TitleIndex OPTIONAL, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize + ); + +/* + * FUNCTION: Sets the volume information. + * ARGUMENTS: + * FileHandle = Handle to the file + * IoStatusBlock = Caller should supply storage for additional status information + * VolumeInformation = pointer to a structure containing the new volume information + * Length = size of the structure. + * VolumeInformationClass = specifies the particular volume information to set + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtSetVolumeInformationFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + +NTSTATUS +STDCALL +ZwSetVolumeInformationFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass + ); + +/* + * FUNCTION: Shuts the system down + * ARGUMENTS: + * Action = Specifies the type of shutdown, it can be one of the following values: + * ShutdownNoReboot, ShutdownReboot, ShutdownPowerOff + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtShutdownSystem( + IN SHUTDOWN_ACTION Action + ); + +NTSTATUS +STDCALL +ZwShutdownSystem( + IN SHUTDOWN_ACTION Action + ); + + +/* --- PROFILING --- */ + +/* + * FUNCTION: Starts profiling + * ARGUMENTS: + * ProfileHandle = Handle to the profile + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtStartProfile( + HANDLE ProfileHandle + ); + +NTSTATUS +STDCALL +ZwStartProfile( + HANDLE ProfileHandle + ); + +/* + * FUNCTION: Stops profiling + * ARGUMENTS: + * ProfileHandle = Handle to the profile + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtStopProfile( + HANDLE ProfileHandle + ); + +NTSTATUS +STDCALL +ZwStopProfile( + HANDLE ProfileHandle + ); + +/* --- PROCESS MANAGEMENT --- */ + +//--NtSystemDebugControl +/* + * FUNCTION: Terminates the execution of a process. + * ARGUMENTS: + * ThreadHandle = Handle to the process + * ExitStatus = The exit status of the process to terminate with. + * REMARKS + Native applications should kill themselves using this function. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtTerminateProcess( + IN HANDLE ProcessHandle , + IN NTSTATUS ExitStatus + ); +NTSTATUS +STDCALL +ZwTerminateProcess( + IN HANDLE ProcessHandle , + IN NTSTATUS ExitStatus + ); + +/* --- DEVICE DRIVER CONTROL --- */ + +/* + * FUNCTION: Unloads a driver. + * ARGUMENTS: + * DriverServiceName = Name of the driver to unload + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtUnloadDriver( + IN PUNICODE_STRING DriverServiceName + ); +NTSTATUS +STDCALL +ZwUnloadDriver( + IN PUNICODE_STRING DriverServiceName + ); + +/* --- VIRTUAL MEMORY MANAGEMENT --- */ + +/* + * FUNCTION: Writes a range of virtual memory + * ARGUMENTS: + * ProcessHandle = The handle to the process owning the address space. + * BaseAddress = The points to the address to write to + * Buffer = Pointer to the buffer to write + * NumberOfBytesToWrite = Offset to the upper boundary to write + * NumberOfBytesWritten = Total bytes written + * REMARKS: + * This function maps to the win32 WriteProcessMemory + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtWriteVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, + OUT PULONG NumberOfBytesWritten + ); + +NTSTATUS +STDCALL +ZwWriteVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, + OUT PULONG NumberOfBytesWritten + ); + +/* + * FUNCTION: Unlocks a range of virtual memory. + * ARGUMENTS: + * ProcessHandle = Handle to the process + * BaseAddress = Lower boundary of the range of bytes to unlock. + * NumberOfBytesToUnlock = Offset to the upper boundary to unlock. + * NumberOfBytesUnlocked (OUT) = Number of bytes actually unlocked. + * REMARK: + This procedure maps to the win32 procedure VirtualUnlock + * RETURNS: Status [ STATUS_SUCCESS | STATUS_PAGE_WAS_ULOCKED ] + */ +NTSTATUS +STDCALL +NtUnlockVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToUnlock, + OUT PULONG NumberOfBytesUnlocked OPTIONAL + ); + +NTSTATUS +STDCALL +ZwUnlockVirtualMemory( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToUnlock, + OUT PULONG NumberOfBytesUnlocked OPTIONAL + ); +/* + * FUNCTION: Unmaps a piece of virtual memory backed by a file. + * ARGUMENTS: + * ProcessHandle = Handle to the process + * BaseAddress = The address where the mapping begins + * REMARK: + This procedure maps to the win32 UnMapViewOfFile + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtUnmapViewOfSection( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress + ); +NTSTATUS +STDCALL +ZwUnmapViewOfSection( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress + ); + +/* --- OBJECT SYNCHRONIZATION --- */ + +/* + * FUNCTION: Signals an object and wait for an other one. + * ARGUMENTS: + * SignalObject = Handle to the object that should be signaled + * WaitObject = Handle to the object that should be waited for + * Alertable = True if the wait is alertable + * Time = The time to wait + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtSignalAndWaitForSingleObject( + IN HANDLE SignalObject, + IN HANDLE WaitObject, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time + ); + +NTSTATUS +STDCALL +NtSignalAndWaitForSingleObject( + IN HANDLE SignalObject, + IN HANDLE WaitObject, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time + ); + +/* + * FUNCTION: Waits for multiple objects to become signalled. + * ARGUMENTS: + * Count = The number of objects + * Object = The array of object handles + * WaitType = Can be one of the values UserMode or KernelMode + * Alertable = If true the wait is alertable. + * Time = The maximum wait time. + * REMARKS: + * This function maps to the win32 WaitForMultipleObjectEx. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtWaitForMultipleObjects ( + IN ULONG Count, + IN HANDLE Object[], + IN CINT WaitType, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time + ); + +NTSTATUS +STDCALL +ZwWaitForMultipleObjects ( + IN ULONG Count, + IN HANDLE Object[], + IN CINT WaitType, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time + ); + +/* + * FUNCTION: Waits for an object to become signalled. + * ARGUMENTS: + * Object = The object handle + * Alertable = If true the wait is alertable. + * Time = The maximum wait time. + * REMARKS: + * This function maps to the win32 WaitForSingleObjectEx. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtWaitForSingleObject ( + IN HANDLE Object, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time + ); + +NTSTATUS +STDCALL +ZwWaitForSingleObject ( + IN HANDLE Object, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time + ); + +/* --- EVENT PAIR OBJECT --- */ + +/* + * FUNCTION: Waits for the high part of an eventpair to become signalled + * ARGUMENTS: + * EventPairHandle = Handle to the event pair. + * RETURNS: Status + */ + +NTSTATUS +STDCALL +NtWaitHighEventPair( + IN HANDLE EventPairHandle + ); + +NTSTATUS +STDCALL +ZwWaitHighEventPair( + IN HANDLE EventPairHandle + ); + +/* + * FUNCTION: Waits for the low part of an eventpair to become signalled + * ARGUMENTS: + * EventPairHandle = Handle to the event pair. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtWaitLowEventPair( + IN HANDLE EventPairHandle + ); + +NTSTATUS +STDCALL +ZwWaitLowEventPair( + IN HANDLE EventPairHandle + ); + +/* --- FILE MANAGEMENT --- */ + +/* + * FUNCTION: Unlocks a range of bytes in a file. + * ARGUMENTS: + * FileHandle = Handle to the file + * IoStatusBlock = Caller should supply storage for a structure containing + * the completion status and information about the requested unlock operation. + The information field is set to the number of bytes unlocked. + * ByteOffset = Offset to start the range of bytes to unlock + * Length = Number of bytes to unlock. + * Key = Special value to enable other threads to unlock a file than the + thread that locked the file. The key supplied must match with the one obtained + in a previous call to NtLockFile. + * REMARK: + This procedure maps to the win32 procedure UnlockFileEx. STATUS_PENDING is returned if the lock could + not be obtained immediately, the device queue is busy and the IRP is queued. + * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES | + STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_RANGE_NOT_LOCKED ] + */ +NTSTATUS +STDCALL +NtUnlockFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Lenght, + OUT PULONG Key OPTIONAL + ); +NTSTATUS +STDCALL +ZwUnlockFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Lenght, + OUT PULONG Key OPTIONAL + ); + +/* + * FUNCTION: Writes data to a file + * ARGUMENTS: + * FileHandle = The handle a file ( from NtCreateFile ) + * Event = Specifies a event that will become signalled when the write operation completes. + * ApcRoutine = Asynchroneous Procedure Callback [ Should not be used by device drivers ] + * ApcContext = Argument to the Apc Routine + * IoStatusBlock = Caller should supply storage for a structure containing the completion status and information about the requested write operation. + * Buffer = Caller should supply storage for a buffer that will contain the information to be written to file. + * Length = Size in bytest of the buffer + * ByteOffset = Points to a file offset. If a combination of Length and BytesOfSet is past the end-of-file mark the file will be enlarged. + * BytesOffset is ignored if the file is created with FILE_APPEND_DATA in the DesiredAccess. BytesOffset is also ignored if + * the file is created with CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT set, in that case a offset + * should be created by specifying FILE_USE_FILE_POINTER_POSITION. + * Key = Unused + * REMARKS: + * This function maps to the win32 WriteFile. + * Callers to NtWriteFile should run at IRQL PASSIVE_LEVEL. + * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES + STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_FILE_LOCK_CONFLICT ] + */ +NTSTATUS +STDCALL +NtWriteFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ); + +NTSTATUS +STDCALL +ZwWriteFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset , + IN PULONG Key OPTIONAL + ); + +/* + * FUNCTION: Writes a file + * ARGUMENTS: + * FileHandle = The handle of the file + * Event = + * ApcRoutine = Asynchroneous Procedure Callback [ Should not be used by device drivers ] + * ApcContext = Argument to the Apc Routine + * IoStatusBlock = Caller should supply storage for a structure containing the completion status and information about the requested write operation. + * BufferDescription = Caller should supply storage for a buffer that will contain the information to be written to file. + * BufferLength = Size in bytest of the buffer + * ByteOffset = Points to a file offset. If a combination of Length and BytesOfSet is past the end-of-file mark the file will be enlarged. + * BytesOffset is ignored if the file is created with FILE_APPEND_DATA in the DesiredAccess. BytesOffset is also ignored if + * the file is created with CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT set, in that case a offset + * should be created by specifying FILE_USE_FILE_POINTER_POSITION. Use FILE_WRITE_TO_END_OF_FILE to write to the EOF. + * Key = If a matching key [ a key provided at NtLockFile ] is provided the write operation will continue even if a byte range is locked. + * REMARKS: + * This function maps to the win32 WriteFile. + * Callers to NtWriteFile should run at IRQL PASSIVE_LEVEL. + * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES + STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_FILE_LOCK_CONFLICT ] + */ + +NTSTATUS +STDCALL +NtWriteFileGather( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN FILE_SEGMENT_ELEMENT BufferDescription[], + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ); + +NTSTATUS +STDCALL +ZwWriteFileGather( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN FILE_SEGMENT_ELEMENT BufferDescription[], + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ); + + +/* --- THREAD MANAGEMENT --- */ + +/* + * FUNCTION: Increments a thread's resume count + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * PreviousSuspendCount = The resulting/previous suspend count. + * REMARK: + * A thread will be suspended if its suspend count is greater than 0. This procedure maps to + * the win32 SuspendThread function. ( documentation about the the suspend count can be found here aswell ) + * The suspend count is not increased if it is greater than MAXIMUM_SUSPEND_COUNT. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtSuspendThread( + IN HANDLE ThreadHandle, + IN PULONG PreviousSuspendCount + ); + +NTSTATUS +STDCALL +ZwSuspendThread( + IN HANDLE ThreadHandle, + IN PULONG PreviousSuspendCount + ); + +/* + * FUNCTION: Terminates the execution of a thread. + * ARGUMENTS: + * ThreadHandle = Handle to the thread + * ExitStatus = The exit status of the thread to terminate with. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtTerminateThread( + IN HANDLE ThreadHandle , + IN NTSTATUS ExitStatus + ); +NTSTATUS +STDCALL +ZwTerminateThread( + IN HANDLE ThreadHandle , + IN NTSTATUS ExitStatus + ); +/* + * FUNCTION: Tests to see if there are any pending alerts for the calling thread + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtTestAlert( + VOID + ); +NTSTATUS +STDCALL +ZwTestAlert( + VOID + ); + +/* + * FUNCTION: Yields the callers thread. + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtYieldExecution( + VOID + ); + +NTSTATUS +STDCALL +ZwYieldExecution( + VOID + ); + + +/* + * --- Local Procedure Call Facility + * These prototypes are unknown as yet + * (stack sizes by Peter-Michael Hager) + */ + +/* --- REGISTRY --- */ + +/* + * FUNCTION: Unloads a registry key. + * ARGUMENTS: + * KeyHandle = Handle to the registry key + * REMARK: + * This procedure maps to the win32 procedure RegUnloadKey + * RETURNS: Status + */ +NTSTATUS +STDCALL +NtUnloadKey( + HANDLE KeyHandle + ); +NTSTATUS +STDCALL +ZwUnloadKey( + HANDLE KeyHandle + ); + + +/* --- PLUG AND PLAY --- */ + +NTSTATUS +STDCALL +NtPlugPlayControl ( + VOID + ); + +NTSTATUS +STDCALL +NtGetPlugPlayEvent ( + VOID + ); + +/* --- POWER MANAGEMENT --- */ + +NTSTATUS STDCALL +NtSetSystemPowerState(IN POWER_ACTION SystemAction, + IN SYSTEM_POWER_STATE MinSystemState, + IN ULONG Flags); + +/* --- DEBUG SUBSYSTEM --- */ + +NTSTATUS STDCALL +NtSystemDebugControl(DEBUG_CONTROL_CODE ControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + PULONG ReturnLength); + +/* --- VIRTUAL DOS MACHINE (VDM) --- */ + +NTSTATUS +STDCALL +NtVdmControl (ULONG ControlCode, PVOID ControlData); + + +/* --- WIN32 --- */ + +NTSTATUS STDCALL +NtW32Call(IN ULONG RoutineIndex, + IN PVOID Argument, + IN ULONG ArgumentLength, + OUT PVOID* Result OPTIONAL, + OUT PULONG ResultLength OPTIONAL); + +/* --- CHANNELS --- */ + +NTSTATUS +STDCALL +NtCreateChannel ( + VOID + ); + +NTSTATUS +STDCALL +NtListenChannel ( + VOID + ); + +NTSTATUS +STDCALL +NtOpenChannel ( + VOID + ); + +NTSTATUS +STDCALL +NtReplyWaitSendChannel ( + VOID + ); + +NTSTATUS +STDCALL +NtSendWaitReplyChannel ( + VOID + ); + +NTSTATUS +STDCALL +NtSetContextChannel ( + VOID + ); + +/* --- MISCELLANEA --- */ + +//NTSTATUS STDCALL NtSetLdtEntries(VOID); +NTSTATUS +STDCALL +NtSetLdtEntries ( + HANDLE Thread, + ULONG FirstEntry, + PULONG Entries + ); + + +NTSTATUS +STDCALL +NtQueryOleDirectoryFile ( + VOID + ); + +#endif /* __DDK_ZW_H */ diff --git a/include/ddk/zwtypes.h b/include/ddk/zwtypes.h new file mode 100644 index 0000000..1095c91 --- /dev/null +++ b/include/ddk/zwtypes.h @@ -0,0 +1,1662 @@ +#ifndef __INCLUDE_DDK_ZWTYPES_H +#define __INCLUDE_DDK_ZWTYPES_H + +typedef enum _DEBUG_CONTROL_CODE +{ + DebugGetTraceInformation = 1, + DebugSetInternalBreakpoint, + DebugSetSpecialCalls, + DebugClearSpecialCalls, + DebugQuerySpecialCalls, + DebugDbgBreakPoint, + DebugDbgLoadSymbols +} DEBUG_CONTROL_CODE; + +typedef enum _KPROFILE_SOURCE +{ + ProfileTime +} KPROFILE_SOURCE; + +#define NtCurrentProcess() ( (HANDLE) 0xFFFFFFFF ) +#define NtCurrentThread() ( (HANDLE) 0xFFFFFFFE ) + +#ifdef __NTOSKRNL__ +extern ULONG EXPORTED NtBuildNumber; +#else +extern ULONG IMPORTED NtBuildNumber; +#endif + + +// event access mask + +#define EVENT_READ_ACCESS 1 +#define EVENT_WRITE_ACCESS 2 + + +// file disposition values + + +#define FILE_SUPERSEDE 0x0000 +#define FILE_OPEN 0x0001 +#define FILE_CREATE 0x0002 +#define FILE_OPEN_IF 0x0003 +#define FILE_OVERWRITE 0x0004 +#define FILE_OVERWRITE_IF 0x0005 +#define FILE_MAXIMUM_DISPOSITION 0x0005 + +// job query / set information class + +typedef enum _JOBOBJECTINFOCLASS { // Q S + JobObjectBasicAccountingInformation = 1, // Y N + JobObjectBasicLimitInformation, // Y Y + JobObjectBasicProcessIdList, // Y N + JobObjectBasicUIRestrictions, // Y Y + JobObjectSecurityLimitInformation, // Y Y + JobObjectEndOfJobTimeInformation, // N Y + JobObjectAssociateCompletionPortInformation, // N Y + JobObjectBasicAndIoAccountingInformation, // Y N + JobObjectExtendedLimitInformation, // Y Y +} JOBOBJECTINFOCLASS; + +//process query / set information class + +#define ProcessBasicInformation 0 +#define ProcessQuotaLimits 1 +#define ProcessIoCounters 2 +#define ProcessVmCounters 3 +#define ProcessTimes 4 +#define ProcessBasePriority 5 +#define ProcessRaisePriority 6 +#define ProcessDebugPort 7 +#define ProcessExceptionPort 8 +#define ProcessAccessToken 9 +#define ProcessLdtInformation 10 +#define ProcessLdtSize 11 +#define ProcessDefaultHardErrorMode 12 +#define ProcessIoPortHandlers 13 +#define ProcessPooledUsageAndLimits 14 +#define ProcessWorkingSetWatch 15 +#define ProcessUserModeIOPL 16 +#define ProcessEnableAlignmentFaultFixup 17 +#define ProcessPriorityClass 18 +#define ProcessWx86Information 19 +#define ProcessHandleCount 20 +#define ProcessAffinityMask 21 +#define ProcessPriorityBoost 22 +#define ProcessDeviceMap 23 +#define ProcessSessionInformation 24 +#define ProcessForegroundInformation 25 +#define ProcessWow64Information 26 +/* ReactOS private. */ +#define ProcessImageFileName 27 +#define ProcessDesktop 28 +#define MaxProcessInfoClass 29 + +/* + * thread query / set information class + */ +#define ThreadBasicInformation 0 +#define ThreadTimes 1 +#define ThreadPriority 2 +#define ThreadBasePriority 3 +#define ThreadAffinityMask 4 +#define ThreadImpersonationToken 5 +#define ThreadDescriptorTableEntry 6 +#define ThreadEnableAlignmentFaultFixup 7 +#define ThreadEventPair 8 +#define ThreadQuerySetWin32StartAddress 9 +#define ThreadZeroTlsCell 10 +#define ThreadPerformanceCount 11 +#define ThreadAmILastThread 12 +#define ThreadIdealProcessor 13 +#define ThreadPriorityBoost 14 +#define ThreadSetTlsArrayAddress 15 +#define ThreadIsIoPending 16 +#define ThreadHideFromDebugger 17 +#define MaxThreadInfoClass 17 + +// object handle information + +#define ObjectBasicInformation 0 +#define ObjectNameInformation 1 +#define ObjectTypeInformation 2 +#define ObjectAllInformation 3 +#define ObjectDataInformation 4 + +// atom information + +typedef enum _ATOM_INFORMATION_CLASS +{ + AtomBasicInformation = 0, + AtomTableInformation = 1, +} ATOM_INFORMATION_CLASS; + +typedef struct _ATOM_BASIC_INFORMATION +{ + USHORT UsageCount; + USHORT Flags; + USHORT NameLength; + WCHAR Name[1]; +} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION; + +typedef struct _ATOM_TABLE_INFORMATION +{ + ULONG NumberOfAtoms; + RTL_ATOM Atoms[1]; +} ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION; + + +// mutant information + +typedef enum _MUTANT_INFORMATION_CLASS +{ + MutantBasicInformation = 0 +} MUTANT_INFORMATION_CLASS; + +typedef struct _MUTANT_BASIC_INFORMATION +{ + LONG Count; + BOOLEAN Owned; + BOOLEAN Abandoned; +} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION; + + +// semaphore information + +typedef enum _SEMAPHORE_INFORMATION_CLASS +{ + SemaphoreBasicInformation = 0 +} SEMAPHORE_INFORMATION_CLASS; + +typedef struct _SEMAPHORE_BASIC_INFORMATION +{ + LONG CurrentCount; + LONG MaximumCount; +} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION; + + +// event information + +typedef enum _EVENT_INFORMATION_CLASS +{ + EventBasicInformation = 0 +} EVENT_INFORMATION_CLASS; + +typedef struct _EVENT_BASIC_INFORMATION +{ + EVENT_TYPE EventType; + LONG EventState; +} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; + + +// system information +// {Nt|Zw}{Query|Set}SystemInformation +// (GN means Gary Nebbet in "NT/W2K Native API Reference") + +typedef +enum _SYSTEM_INFORMATION_CLASS +{ + SystemInformationClassMin = 0, + SystemBasicInformation = 0, /* Q */ + + SystemProcessorInformation = 1, /* Q */ + + SystemPerformanceInformation = 2, /* Q */ + + SystemTimeOfDayInformation = 3, /* Q */ + + SystemPathInformation = 4, /* Q (checked build only) */ + SystemNotImplemented1 = 4, /* Q (GN) */ + + SystemProcessInformation = 5, /* Q */ + SystemProcessesAndThreadsInformation = 5, /* Q (GN) */ + + SystemCallCountInfoInformation = 6, /* Q */ + SystemCallCounts = 6, /* Q (GN) */ + + SystemDeviceInformation = 7, /* Q */ +// It conflicts with symbol in ntoskrnl/io/resource.c +// SystemConfigurationInformation = 7, /* Q (GN) */ + + SystemProcessorPerformanceInformation = 8, /* Q */ + SystemProcessorTimes = 8, /* Q (GN) */ + + SystemFlagsInformation = 9, /* QS */ + SystemGlobalFlag = 9, /* QS (GN) */ + + SystemCallTimeInformation = 10, + SystemNotImplemented2 = 10, /* (GN) */ + + SystemModuleInformation = 11, /* Q */ + + SystemLocksInformation = 12, /* Q */ + SystemLockInformation = 12, /* Q (GN) */ + + SystemStackTraceInformation = 13, + SystemNotImplemented3 = 13, /* Q (GN) */ + + SystemPagedPoolInformation = 14, + SystemNotImplemented4 = 14, /* Q (GN) */ + + SystemNonPagedPoolInformation = 15, + SystemNotImplemented5 = 15, /* Q (GN) */ + + SystemHandleInformation = 16, /* Q */ + + SystemObjectInformation = 17, /* Q */ + + SystemPageFileInformation = 18, /* Q */ + SystemPagefileInformation = 18, /* Q (GN) */ + + SystemVdmInstemulInformation = 19, /* Q */ + SystemInstructionEmulationCounts = 19, /* Q (GN) */ + + SystemVdmBopInformation = 20, + SystemInvalidInfoClass1 = 20, /* (GN) */ + + SystemFileCacheInformation = 21, /* QS */ + SystemCacheInformation = 21, /* QS (GN) */ + + SystemPoolTagInformation = 22, /* Q (checked build only) */ + + SystemInterruptInformation = 23, /* Q */ + SystemProcessorStatistics = 23, /* Q (GN) */ + + SystemDpcBehaviourInformation = 24, /* QS */ + SystemDpcInformation = 24, /* QS (GN) */ + + SystemFullMemoryInformation = 25, + SystemNotImplemented6 = 25, /* (GN) */ + + SystemLoadImage = 26, /* S (callable) (GN) */ + + SystemUnloadImage = 27, /* S (callable) (GN) */ + + SystemTimeAdjustmentInformation = 28, /* QS */ + SystemTimeAdjustment = 28, /* QS (GN) */ + + SystemSummaryMemoryInformation = 29, + SystemNotImplemented7 = 29, /* (GN) */ + + SystemNextEventIdInformation = 30, + SystemNotImplemented8 = 30, /* (GN) */ + + SystemEventIdsInformation = 31, + SystemNotImplemented9 = 31, /* (GN) */ + + SystemCrashDumpInformation = 32, /* Q */ + + SystemExceptionInformation = 33, /* Q */ + + SystemCrashDumpStateInformation = 34, /* Q */ + + SystemKernelDebuggerInformation = 35, /* Q */ + + SystemContextSwitchInformation = 36, /* Q */ + + SystemRegistryQuotaInformation = 37, /* QS */ + + SystemLoadAndCallImage = 38, /* S (GN) */ + + SystemPrioritySeparation = 39, /* S */ + + SystemPlugPlayBusInformation = 40, + SystemNotImplemented10 = 40, /* Q (GN) */ + + SystemDockInformation = 41, + SystemNotImplemented11 = 41, /* Q (GN) */ + + SystemPowerInformation = 42, + SystemInvalidInfoClass2 = 42, /* (GN) */ + + SystemProcessorSpeedInformation = 43, + SystemInvalidInfoClass3 = 43, /* (GN) */ + + SystemCurrentTimeZoneInformation = 44, /* QS */ + SystemTimeZoneInformation = 44, /* QS (GN) */ + + SystemLookasideInformation = 45, /* Q */ + + SystemSetTimeSlipEvent = 46, /* S (GN) */ + + SystemCreateSession = 47, /* S (GN) */ + + SystemDeleteSession = 48, /* S (GN) */ + + SystemInvalidInfoClass4 = 49, /* (GN) */ + + SystemRangeStartInformation = 50, /* Q (GN) */ + + SystemVerifierInformation = 51, /* QS (GN) */ + + SystemAddVerifier = 52, /* S (GN) */ + + SystemSessionProcessesInformation = 53, /* Q (GN) */ + SystemInformationClassMax + +} SYSTEM_INFORMATION_CLASS; + +// SystemBasicInformation (0) +typedef +struct _SYSTEM_BASIC_INFORMATION +{ + ULONG Reserved; + ULONG TimerResolution; + ULONG PageSize; + ULONG NumberOfPhysicalPages; + ULONG LowestPhysicalPageNumber; + ULONG HighestPhysicalPageNumber; + ULONG AllocationGranularity; + ULONG MinimumUserModeAddress; + ULONG MaximumUserModeAddress; + KAFFINITY ActiveProcessorsAffinityMask; + CCHAR NumberOfProcessors; +} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; + +// SystemProcessorInformation (1) +typedef +struct _SYSTEM_PROCESSOR_INFORMATION +{ + USHORT ProcessorArchitecture; + USHORT ProcessorLevel; + USHORT ProcessorRevision; + USHORT Reserved; + ULONG ProcessorFeatureBits; +} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; + +// SystemPerformanceInfo (2) +typedef +struct _SYSTEM_PERFORMANCE_INFORMATION +{ + LARGE_INTEGER IdleProcessorTime; + LARGE_INTEGER IoReadTransferCount; + LARGE_INTEGER IoWriteTransferCount; + LARGE_INTEGER IoOtherTransferCount; + ULONG IoReadOperationCount; + ULONG IoWriteOperationCount; + ULONG IoOtherOperationCount; + ULONG AvailablePages; + ULONG CommitedPages; + ULONG CommitLimit; + ULONG PeakCommitment; + ULONG PageFaultCount; + ULONG CopyOnWriteCount; + ULONG TransitionCount; + ULONG CacheTransitionCount; + ULONG DemandZeroCount; + ULONG PageReadCount; + ULONG PageReadIoCount; + ULONG CacheReadCount; + ULONG CacheIoCount; + ULONG DirtyPagesWriteCount; + ULONG DirtyWriteIoCount; + ULONG MappedPagesWriteCount; + ULONG MappedWriteIoCount; + ULONG PagedPoolPages; + ULONG NonPagedPoolPages; + ULONG Unknown6; + ULONG Unknown7; + ULONG Unknown8; + ULONG Unknown9; + ULONG MmTotalSystemFreePtes; + ULONG MmSystemCodepage; + ULONG MmTotalSystemDriverPages; + ULONG MmTotalSystemCodePages; + ULONG Unknown10; + ULONG Unknown11; + ULONG Unknown12; + ULONG MmSystemCachePage; + ULONG MmPagedPoolPage; + ULONG MmSystemDriverPage; + ULONG CcFastReadNoWait; + ULONG CcFastReadWait; + ULONG CcFastReadResourceMiss; + ULONG CcFastReadNotPossible; + ULONG CcFastMdlReadNoWait; + ULONG CcFastMdlReadWait; + ULONG CcFastMdlReadResourceMiss; + ULONG CcFastMdlReadNotPossible; + ULONG CcMapDataNoWait; + ULONG CcMapDataWait; + ULONG CcMapDataNoWaitMiss; + ULONG CcMapDataWaitMiss; + ULONG CcPinMappedDataCount; + ULONG CcPinReadNoWait; + ULONG CcPinReadWait; + ULONG CcPinReadNoWaitMiss; + ULONG CcPinReadWaitMiss; + ULONG CcCopyReadNoWait; + ULONG CcCopyReadWait; + ULONG CcCopyReadNoWaitMiss; + ULONG CcCopyReadWaitMiss; + ULONG CcMdlReadNoWait; + ULONG CcMdlReadWait; + ULONG CcMdlReadNoWaitMiss; + ULONG CcMdlReadWaitMiss; + ULONG CcReadaheadIos; + ULONG CcLazyWriteIos; + ULONG CcLazyWritePages; + ULONG CcDataFlushes; + ULONG CcDataPages; + ULONG ContextSwitches; + ULONG Unknown13; + ULONG Unknown14; + ULONG SystemCalls; + +} SYSTEM_PERFORMANCE_INFO, *PSYSTEM_PERFORMANCE_INFO; + +// SystemTimeOfDayInformation (3) +typedef +struct _SYSTEM_TIMEOFDAY_INFORMATION +{ + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG TimeZoneId; + ULONG Reserved; +} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION; + +// SystemPathInformation (4) +// IT DOES NOT WORK +typedef +struct _SYSTEM_PATH_INFORMATION +{ + PVOID Dummy; + +} SYSTEM_PATH_INFORMATION, * PSYSTEM_PATH_INFORMATION; + +// SystemProcessInformation (5) +typedef +struct _SYSTEM_THREAD_INFORMATION +{ + TIME KernelTime; + TIME UserTime; + TIME CreateTime; + ULONG TickCount; + ULONG StartEIP; + CLIENT_ID ClientId; + ULONG DynamicPriority; + ULONG BasePriority; + ULONG nSwitches; + DWORD State; + KWAIT_REASON WaitReason; + +} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef +struct SYSTEM_PROCESS_INFORMATION +{ + ULONG RelativeOffset; + ULONG ThreadCount; + ULONG Unused1 [6]; + TIME CreateTime; + TIME UserTime; + TIME KernelTime; + UNICODE_STRING Name; + ULONG BasePriority; + ULONG ProcessId; + ULONG ParentProcessId; + ULONG HandleCount; + ULONG Unused2[2]; + ULONG PeakVirtualSizeBytes; + ULONG TotalVirtualSizeBytes; + ULONG PageFaultCount; + ULONG PeakWorkingSetSizeBytes; + ULONG TotalWorkingSetSizeBytes; + ULONG PeakPagedPoolUsagePages; + ULONG TotalPagedPoolUsagePages; + ULONG PeakNonPagedPoolUsagePages; + ULONG TotalNonPagedPoolUsagePages; + ULONG TotalPageFileUsageBytes; + ULONG PeakPageFileUsageBytes; + ULONG TotalPrivateBytes; + SYSTEM_THREAD_INFORMATION ThreadSysInfo [1]; + +} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; + +// SystemCallCountInformation (6) +typedef +struct _SYSTEM_SDT_INFORMATION +{ + ULONG BufferLength; + ULONG NumberOfSystemServiceTables; + ULONG NumberOfServices [1]; + ULONG ServiceCounters [1]; + +} SYSTEM_SDT_INFORMATION, *PSYSTEM_SDT_INFORMATION; + +// SystemDeviceInformation (7) +typedef +struct _SYSTEM_DEVICE_INFORMATION +{ + ULONG NumberOfDisks; + ULONG NumberOfFloppies; + ULONG NumberOfCdRoms; + ULONG NumberOfTapes; + ULONG NumberOfSerialPorts; + ULONG NumberOfParallelPorts; +} SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION; + +// SystemProcessorPerformanceInformation (8) +// (one per processor in the system) +typedef +struct _SYSTEM_PROCESSORTIME_INFO +{ + TIME TotalProcessorRunTime; + TIME TotalProcessorTime; + TIME TotalProcessorUserTime; + TIME TotalDPCTime; + TIME TotalInterruptTime; + ULONG TotalInterrupts; + ULONG Unused; + +} SYSTEM_PROCESSORTIME_INFO, *PSYSTEM_PROCESSORTIME_INFO; + +// SystemFlagsInformation (9) +typedef +struct _SYSTEM_FLAGS_INFORMATION +{ + ULONG Flags; + +} SYSTEM_FLAGS_INFORMATION, * PSYSTEM_FLAGS_INFORMATION; + +#define FLG_STOP_ON_EXCEPTION 0x00000001 +#define FLG_SHOW_LDR_SNAPS 0x00000002 +#define FLG_DEBUG_INITIAL_COMMAND 0x00000004 +#define FLG_STOP_ON_HANG_GUI 0x00000008 +#define FLG_HEAP_ENABLE_TAIL_CHECK 0x00000010 +#define FLG_HEAP_ENABLE_FREE_CHECK 0x00000020 +#define FLG_HEAP_VALIDATE_PARAMETERS 0x00000040 +#define FLG_HEAP_VALIDATE_ALL 0x00000080 +#define FLG_POOL_ENABLE_TAIL_CHECK 0x00000100 +#define FLG_POOL_ENABLE_FREE_CHECK 0x00000200 +#define FLG_POOL_ENABLE_TAGGING 0x00000400 +#define FLG_HEAP_ENABLE_TAGGING 0x00000800 +#define FLG_USER_STACK_TRACE_DB 0x00001000 +#define FLG_KERNEL_STACK_TRACE_DB 0x00002000 +#define FLG_MAINTAIN_OBJECT_TYPELIST 0x00004000 +#define FLG_HEAP_ENABLE_TAG_BY_DLL 0x00008000 +#define FLG_IGNORE_DEBUG_PRIV 0x00010000 +#define FLG_ENABLE_CSRDEBUG 0x00020000 +#define FLG_ENABLE_KDEBUG_SYMBOL_LOAD 0x00040000 +#define FLG_DISABLE_PAGE_KERNEL_STACKS 0x00080000 +#define FLG_HEAP_ENABLE_CALL_TRACING 0x00100000 +#define FLG_HEAP_DISABLE_COALESCING 0x00200000 +#define FLG_ENABLE_CLOSE_EXCEPTION 0x00400000 +#define FLG_ENABLE_EXCEPTION_LOGGING 0x00800000 +#define FLG_UNKNOWN_01000000 0x01000000 +#define FLG_UNKNOWN_02000000 0x02000000 +#define FLG_UNKNOWN_04000000 0x04000000 +#define FLG_ENABLE_DBGPRINT_BUFFERING 0x08000000 +#define FLG_UNKNOWN_10000000 0x10000000 +#define FLG_UNKNOWN_20000000 0x20000000 +#define FLG_UNKNOWN_40000000 0x40000000 +#define FLG_UNKNOWN_80000000 0x80000000 + +// SystemCallTimeInformation (10) +// UNKNOWN + +// SystemModuleInformation (11) +typedef +struct _SYSTEM_MODULE_ENTRY +{ + ULONG Unknown1; + ULONG Unknown2; + PVOID BaseAddress; + ULONG Size; + ULONG Flags; + ULONG EntryIndex; + USHORT NameLength; /* Length of module name not including the path, this field contains valid value only for NTOSKRNL module*/ + USHORT PathLength; /* Length of 'directory path' part of modulename*/ + CHAR Name [256]; +} SYSTEM_MODULE_ENTRY, * PSYSTEM_MODULE_ENTRY; + +typedef +struct _SYSTEM_MODULE_INFORMATION +{ + ULONG Count; + SYSTEM_MODULE_ENTRY Module [1]; +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + +// SystemLocksInformation (12) +typedef +struct _SYSTEM_RESOURCE_LOCK_ENTRY +{ + ULONG ResourceAddress; + ULONG Always1; + ULONG Unknown; + ULONG ActiveCount; + ULONG ContentionCount; + ULONG Unused[2]; + ULONG NumberOfSharedWaiters; + ULONG NumberOfExclusiveWaiters; + +} SYSTEM_RESOURCE_LOCK_ENTRY, *PSYSTEM_RESOURCE_LOCK_ENTRY; + +typedef +struct _SYSTEM_RESOURCE_LOCK_INFO +{ + ULONG Count; + SYSTEM_RESOURCE_LOCK_ENTRY Lock [1]; + +} SYSTEM_RESOURCE_LOCK_INFO, *PSYSTEM_RESOURCE_LOCK_INFO; + +// SystemInformation13 (13) +// UNKNOWN + +// SystemInformation14 (14) +// UNKNOWN + +// SystemInformation15 (15) +// UNKNOWN + +// SystemHandleInformation (16) +// (see ontypes.h) +typedef +struct _SYSTEM_HANDLE_ENTRY +{ + ULONG OwnerPid; + BYTE ObjectType; + BYTE HandleFlags; + USHORT HandleValue; + PVOID ObjectPointer; + ULONG AccessMask; + +} SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY; + +typedef +struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG Count; + SYSTEM_HANDLE_ENTRY Handle [1]; + +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +// SystemObjectInformation (17) +typedef +struct _SYSTEM_OBJECT_TYPE_INFORMATION +{ + ULONG NextEntryOffset; + ULONG ObjectCount; + ULONG HandleCount; + ULONG TypeNumber; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ACCESS_MASK ValidAccessMask; + POOL_TYPE PoolType; + UCHAR Unknown; + UNICODE_STRING Name; + +} SYSTEM_OBJECT_TYPE_INFORMATION, *PSYSTEM_OBJECT_TYPE_INFORMATION; + +typedef +struct _SYSTEM_OBJECT_INFORMATION +{ + ULONG NextEntryOffset; + PVOID Object; + ULONG CreatorProcessId; + USHORT Unknown; + USHORT Flags; + ULONG PointerCount; + ULONG HandleCount; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; + ULONG ExclusiveProcessId; + PSECURITY_DESCRIPTOR SecurityDescriptor; + UNICODE_STRING Name; + +} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION; + +// SystemPageFileInformation (18) +typedef +struct _SYSTEM_PAGEFILE_INFORMATION +{ + ULONG RelativeOffset; + ULONG CurrentSizePages; + ULONG TotalUsedPages; + ULONG PeakUsedPages; + UNICODE_STRING PagefileFileName; + +} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; + +// SystemInstructionEmulationInfo (19) +typedef +struct _SYSTEM_VDM_INFORMATION +{ + ULONG VdmSegmentNotPresentCount; + ULONG VdmINSWCount; + ULONG VdmESPREFIXCount; + ULONG VdmCSPREFIXCount; + ULONG VdmSSPREFIXCount; + ULONG VdmDSPREFIXCount; + ULONG VdmFSPREFIXCount; + ULONG VdmGSPREFIXCount; + ULONG VdmOPER32PREFIXCount; + ULONG VdmADDR32PREFIXCount; + ULONG VdmINSBCount; + ULONG VdmINSWV86Count; + ULONG VdmOUTSBCount; + ULONG VdmOUTSWCount; + ULONG VdmPUSHFCount; + ULONG VdmPOPFCount; + ULONG VdmINTNNCount; + ULONG VdmINTOCount; + ULONG VdmIRETCount; + ULONG VdmINBIMMCount; + ULONG VdmINWIMMCount; + ULONG VdmOUTBIMMCount; + ULONG VdmOUTWIMMCount; + ULONG VdmINBCount; + ULONG VdmINWCount; + ULONG VdmOUTBCount; + ULONG VdmOUTWCount; + ULONG VdmLOCKPREFIXCount; + ULONG VdmREPNEPREFIXCount; + ULONG VdmREPPREFIXCount; + ULONG VdmHLTCount; + ULONG VdmCLICount; + ULONG VdmSTICount; + ULONG VdmBopCount; + +} SYSTEM_VDM_INFORMATION, *PSYSTEM_VDM_INFORMATION; + +// SystemInformation20 (20) +// UNKNOWN + +// SystemCacheInformation (21) +typedef +struct _SYSTEM_CACHE_INFORMATION +{ + ULONG CurrentSize; + ULONG PeakSize; + ULONG PageFaultCount; + ULONG MinimumWorkingSet; + ULONG MaximumWorkingSet; + ULONG Unused[4]; + +} SYSTEM_CACHE_INFORMATION; + +// SystemPoolTagInformation (22) +// found by Klaus P. Gerlicher +// (implemented only in checked builds) +typedef +struct _POOL_TAG_STATS +{ + ULONG AllocationCount; + ULONG FreeCount; + ULONG SizeBytes; + +} POOL_TAG_STATS; + +typedef +struct _SYSTEM_POOL_TAG_ENTRY +{ + ULONG Tag; + POOL_TAG_STATS Paged; + POOL_TAG_STATS NonPaged; + +} SYSTEM_POOL_TAG_ENTRY, * PSYSTEM_POOL_TAG_ENTRY; + +typedef +struct _SYSTEM_POOL_TAG_INFO +{ + ULONG Count; + SYSTEM_POOL_TAG_ENTRY PoolEntry [1]; + +} SYSTEM_POOL_TAG_INFO, *PSYSTEM_POOL_TAG_INFO; + +// SystemProcessorScheduleInfo (23) +typedef +struct _SYSTEM_PROCESSOR_SCHEDULE_INFO +{ + ULONG nContextSwitches; + ULONG nDPCQueued; + ULONG nDPCRate; + ULONG TimerResolution; + ULONG nDPCBypasses; + ULONG nAPCBypasses; + +} SYSTEM_PROCESSOR_SCHEDULE_INFO, *PSYSTEM_PROCESSOR_SCHEDULE_INFO; + +// SystemDpcInformation (24) +typedef +struct _SYSTEM_DPC_INFORMATION +{ + ULONG Unused; + ULONG KiMaximumDpcQueueDepth; + ULONG KiMinimumDpcRate; + ULONG KiAdjustDpcThreshold; + ULONG KiIdealDpcRate; + +} SYSTEM_DPC_INFORMATION, *PSYSTEM_DPC_INFORMATION; + +// SystemInformation25 (25) +// UNKNOWN + +// SystemLoadImage (26) +typedef struct _SYSTEM_LOAD_IMAGE +{ + UNICODE_STRING ModuleName; + PVOID ModuleBase; + PVOID SectionPointer; + PVOID EntryPoint; + PVOID ExportDirectory; +} SYSTEM_LOAD_IMAGE, *PSYSTEM_LOAD_IMAGE; + +// SystemUnloadImage (27) +typedef struct _SYSTEM_UNLOAD_IMAGE +{ + PVOID ModuleBase; +} SYSTEM_UNLOAD_IMAGE, *PSYSTEM_UNLOAD_IMAGE; + +// SystemTimeAdjustmentInformation (28) +typedef +struct _SYSTEM_QUERY_TIME_ADJUSTMENT +{ + ULONG TimeAdjustment; + ULONG MaximumIncrement; + BOOLEAN TimeSynchronization; + +} SYSTEM_QUERY_TIME_ADJUSTMENT, *PSYSTEM_QUERY_TIME_ADJUSTMENT; + +typedef +struct _SYSTEM_SET_TIME_ADJUSTMENT +{ + ULONG TimeAdjustment; + BOOLEAN TimeSynchronization; + +} SYSTEM_TIME_ADJUSTMENT_INFO, *PSYSTEM_TIME_ADJUSTMENT_INFO; + +// SystemProcessorFaultCountInfo (33) +typedef +struct _SYSTEM_PROCESSOR_FAULT_INFO +{ + ULONG nAlignmentFixup; + ULONG nExceptionDispatches; + ULONG nFloatingEmulation; + ULONG Unknown; + +} SYSTEM_PROCESSOR_FAULT_INFO, *PSYSTEM_PROCESSOR_FAULT_INFO; + +// SystemCrashDumpStateInfo (34) +// + +// SystemDebuggerInformation (35) +typedef +struct _SYSTEM_DEBUGGER_INFO +{ + BOOLEAN KdDebuggerEnabled; + BOOLEAN KdDebuggerPresent; + +} SYSTEM_DEBUGGER_INFO, *PSYSTEM_DEBUGGER_INFO; + +// SystemInformation36 (36) +// UNKNOWN + +// SystemQuotaInformation (37) +typedef +struct _SYSTEM_QUOTA_INFORMATION +{ + ULONG CmpGlobalQuota; + ULONG CmpGlobalQuotaUsed; + ULONG MmSizeofPagedPoolInBytes; + +} SYSTEM_QUOTA_INFORMATION, *PSYSTEM_QUOTA_INFORMATION; + +// SystemLoadAndCallImage(38) +typedef struct _SYSTEM_LOAD_AND_CALL_IMAGE +{ + UNICODE_STRING ModuleName; +} SYSTEM_LOAD_AND_CALL_IMAGE, *PSYSTEM_LOAD_AND_CALL_IMAGE; + +// SystemTimeZoneInformation (44) +typedef +struct _SYSTEM_TIME_ZONE_INFORMATION +{ + LONG Bias; + WCHAR StandardName [32]; + TIME StandardDate; + LONG StandardBias; + WCHAR DaylightName [32]; + TIME DaylightDate; + LONG DaylightBias; + +} SYSTEM_TIME_ZONE_INFORMATION, * PSYSTEM_TIME_ZONE_INFORMATION; + +// SystemLookasideInformation (45) +typedef +struct _SYSTEM_LOOKASIDE_INFORMATION +{ + USHORT Depth; + USHORT MaximumDepth; + ULONG TotalAllocates; + ULONG AllocatesMisses; + ULONG TotalFrees; + ULONG FreeMisses; + POOL_TYPE Type; + ULONG Tag; + ULONG Size; + +} SYSTEM_LOOKASIDE_INFORMATION, * PSYSTEM_LOOKASIDE_INFORMATION; + +// SystemSetTimeSlipEvent (46) +typedef +struct _SYSTEM_SET_TIME_SLIP_EVENT +{ + HANDLE TimeSlipEvent; /* IN */ + +} SYSTEM_SET_TIME_SLIP_EVENT, * PSYSTEM_SET_TIME_SLIP_EVENT; + +// SystemCreateSession (47) +// (available only on TSE/NT5+) +typedef +struct _SYSTEM_CREATE_SESSION +{ + ULONG SessionId; /* OUT */ + +} SYSTEM_CREATE_SESSION, * PSYSTEM_CREATE_SESSION; + +// SystemDeleteSession (48) +// (available only on TSE/NT5+) +typedef +struct _SYSTEM_DELETE_SESSION +{ + ULONG SessionId; /* IN */ + +} SYSTEM_DELETE_SESSION, * PSYSTEM_DELETE_SESSION; + +// (49) +// UNKNOWN + +// SystemRangeStartInformation (50) +typedef +struct _SYSTEM_RANGE_START_INFORMATION +{ + PVOID SystemRangeStart; + +} SYSTEM_RANGE_START_INFORMATION, * PSYSTEM_RANGE_START_INFORMATION; + +// SystemVerifierInformation (51) +// UNKNOWN + +// SystemAddVerifier (52) +// UNKNOWN + +// SystemSessionProcessesInformation (53) +// (available only on TSE/NT5+) +typedef +struct _SYSTEM_SESSION_PROCESSES_INFORMATION +{ + ULONG SessionId; + ULONG BufferSize; + PVOID Buffer; /* same format as in SystemProcessInformation */ + +} SYSTEM_SESSION_PROCESSES_INFORMATION, * PSYSTEM_SESSION_PROCESSES_INFORMATION; + +// memory information + +typedef enum _MEMORY_INFORMATION_CLASS { + MemoryBasicInformation, + MemoryWorkingSetList, + MemorySectionName //, + //MemoryBasicVlmInformation //??? +} MEMORY_INFORMATION_CLASS; + +typedef struct _MEMORY_BASIC_INFORMATION { // Information Class 0 + PVOID BaseAddress; + PVOID AllocationBase; + ULONG AllocationProtect; + ULONG RegionSize; + ULONG State; + ULONG Protect; + ULONG Type; +} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; + +typedef struct _MEMORY_WORKING_SET_LIST { // Information Class 1 + ULONG NumberOfPages; + ULONG WorkingSetList[1]; +} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST; + +// Information Class 2 +#define _MEMORY_SECTION_NAME_STATIC(__bufsize__) \ + { \ + UNICODE_STRING SectionFileName; \ + WCHAR NameBuffer[(__bufsize__)]; \ +} + +#define MEMORY_SECTION_NAME_STATIC(__bufsize__) \ + struct _MEMORY_SECTION_NAME_STATIC((__bufsize__) + +typedef struct _MEMORY_SECTION_NAME_STATIC(ANYSIZE_ARRAY) + MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME; + +// shutdown action + +typedef enum SHUTDOWN_ACTION_TAG { + ShutdownNoReboot, + ShutdownReboot, + ShutdownPowerOff +} SHUTDOWN_ACTION; + +// wait type + +#define WaitAll 0 +#define WaitAny 1 + +// number of wait objects + +#define THREAD_WAIT_OBJECTS 3 +//#define MAXIMUM_WAIT_OBJECTS 64 + +// key restore flags + +#define REG_WHOLE_HIVE_VOLATILE 1 +#define REG_REFRESH_HIVE 2 + +// object type access rights + +#define OBJECT_TYPE_CREATE 0x0001 +#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +// directory access rights + +#define DIRECTORY_QUERY 0x0001 +#define DIRECTORY_TRAVERSE 0x0002 +#define DIRECTORY_CREATE_OBJECT 0x0004 +#define DIRECTORY_CREATE_SUBDIRECTORY 0x0008 + +#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) + +// symbolic link access rights + +#define SYMBOLIC_LINK_QUERY 0x0001 +#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +// Information class 0 +typedef struct _PROCESS_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PPEB PebBaseAddress; + KAFFINITY AffinityMask; + KPRIORITY BasePriority; + ULONG UniqueProcessId; + ULONG InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; + +// Information class 1 +typedef struct _QUOTA_LIMITS +{ + ULONG PagedPoolLimit; + ULONG NonPagedPoolLimit; + ULONG MinimumWorkingSetSize; + ULONG MaximumWorkingSetSize; + ULONG PagefileLimit; + TIME TimeLimit; +} QUOTA_LIMITS, *PQUOTA_LIMITS; + +// Information class 2 +typedef struct _IO_COUNTERS +{ + ULONG ReadOperationCount; + ULONG WriteOperationCount; + ULONG OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; +} IO_COUNTERS, *PIO_COUNTERS; + +// Information class 3 +typedef struct _VM_COUNTERS_ +{ + ULONG PeakVirtualSize; + ULONG VirtualSize; + ULONG PageFaultCount; + ULONG PeakWorkingSetSize; + ULONG WorkingSetSize; + ULONG QuotaPeakPagedPoolUsage; + ULONG QuotaPagedPoolUsage; + ULONG QuotaPeakNonPagedPoolUsage; + ULONG QuotaNonPagedPoolUsage; + ULONG PagefileUsage; + ULONG PeakPagefileUsage; +} VM_COUNTERS, *PVM_COUNTERS; + +// Information class 4 +typedef struct _KERNEL_USER_TIMES +{ + TIME CreateTime; + TIME ExitTime; + TIME KernelTime; + TIME UserTime; +} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; + +// Information class 9 +typedef struct _PROCESS_ACCESS_TOKEN +{ + HANDLE Token; + HANDLE Thread; +} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN; + +// Information class 14 +typedef struct _POOLED_USAGE_AND_LIMITS_ +{ + ULONG PeakPagedPoolUsage; + ULONG PagedPoolUsage; + ULONG PagedPoolLimit; + ULONG PeakNonPagedPoolUsage; + ULONG NonPagedPoolUsage; + ULONG NonPagedPoolLimit; + ULONG PeakPagefileUsage; + ULONG PagefileUsage; + ULONG PagefileLimit; +} POOLED_USAGE_AND_LIMITS, *PPOOLED_USAGE_AND_LIMITS; + +// Information class 15 +typedef struct _PROCESS_WS_WATCH_INFORMATION +{ + PVOID FaultingPc; + PVOID FaultingVa; +} PROCESS_WS_WATCH_INFORMATION, *PPROCESS_WS_WATCH_INFORMATION; + +// Information class 18 +typedef struct _PROCESS_PRIORITY_CLASS +{ + BOOLEAN Foreground; + UCHAR PriorityClass; +} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS; + +// Information class 23 +typedef struct _PROCESS_DEVICEMAP_INFORMATION +{ + union { + struct { + HANDLE DirectoryHandle; + } Set; + struct { + ULONG DriveMap; + UCHAR DriveType[32]; + } Query; + }; +} PROCESS_DEVICEMAP_INFORMATION, *pPROCESS_DEVICEMAP_INFORMATION; + +// Information class 24 +typedef struct _PROCESS_SESSION_INFORMATION +{ + ULONG SessionId; +} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION; + +// thread information + +// incompatible with MS NT + +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PVOID TebBaseAddress; // PNT_TIB (GN) + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +// object information + +typedef struct _OBJECT_NAME_INFORMATION +{ + UNICODE_STRING Name; +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; + + + +typedef struct _OBJECT_DATA_INFORMATION +{ + BOOLEAN bInheritHandle; + BOOLEAN bProtectFromClose; +} OBJECT_DATA_INFORMATION, *POBJECT_DATA_INFORMATION; + + +typedef struct _OBJECT_TYPE_INFORMATION +{ + UNICODE_STRING Name; + UNICODE_STRING Type; + ULONG TotalHandles; + ULONG ReferenceCount; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +// file information + +typedef struct _FILE_BASIC_INFORMATION +{ + TIME CreationTime; + TIME LastAccessTime; + TIME LastWriteTime; + TIME ChangeTime; + ULONG FileAttributes; +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + +typedef struct _FILE_STANDARD_INFORMATION +{ + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; + +typedef struct _FILE_POSITION_INFORMATION +{ + LARGE_INTEGER CurrentByteOffset; +} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; + +typedef struct _FILE_ALIGNMENT_INFORMATION +{ + ULONG AlignmentRequirement; +} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; + +typedef struct _FILE_DISPOSITION_INFORMATION +{ + BOOLEAN DoDeleteFile; +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; + +typedef struct _FILE_END_OF_FILE_INFORMATION +{ + LARGE_INTEGER EndOfFile; +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; + +typedef struct _FILE_NETWORK_OPEN_INFORMATION +{ + TIME CreationTime; + TIME LastAccessTime; + TIME LastWriteTime; + TIME ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; +} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION; + +typedef struct _FILE_FULL_EA_INFORMATION +{ + ULONG NextEntryOffset; + UCHAR Flags; + UCHAR EaNameLength; + USHORT EaValueLength; + CHAR EaName[0]; +} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; + + +typedef struct _FILE_EA_INFORMATION { + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + + +typedef struct _FILE_GET_EA_INFORMATION { + ULONG NextEntryOffset; + UCHAR EaNameLength; + CHAR EaName[0]; +} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION; + +typedef struct _FILE_STREAM_INFORMATION { + ULONG NextEntryOffset; + ULONG StreamNameLength; + LARGE_INTEGER StreamSize; + LARGE_INTEGER StreamAllocationSize; + WCHAR StreamName[0]; +} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION; + +typedef struct _FILE_ALLOCATION_INFORMATION { + LARGE_INTEGER AllocationSize; +} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION; + +typedef struct _FILE_NAME_INFORMATION { + ULONG FileNameLength; + WCHAR FileName[0]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + +typedef struct _FILE_NAMES_INFORMATION +{ + ULONG NextEntryOffset; + ULONG FileIndex; + ULONG FileNameLength; + WCHAR FileName[0]; +} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION; + + +typedef struct _FILE_RENAME_INFORMATION { + BOOLEAN Replace; + HANDLE RootDir; + ULONG FileNameLength; + WCHAR FileName[0]; +} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; + + +typedef struct _FILE_INTERNAL_INFORMATION { + LARGE_INTEGER IndexNumber; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_ACCESS_INFORMATION { + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + + +typedef struct _FILE_MODE_INFORMATION { + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + + +typedef struct _FILE_PIPE_INFORMATION { + ULONG ReadMode; + ULONG CompletionMode; +} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION; + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + +typedef struct _FILE_PIPE_REMOTE_INFORMATION { + LARGE_INTEGER CollectDataTime; + ULONG MaximumCollectionCount; +} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION; + +typedef struct _FILE_MAILSLOT_QUERY_INFORMATION { + ULONG MaxMessageSize; + ULONG Unknown; /* ?? */ + ULONG NextSize; + ULONG MessageCount; + LARGE_INTEGER Timeout; +} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION; + +typedef struct _FILE_MAILSLOT_SET_INFORMATION { + LARGE_INTEGER Timeout; +} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION; + +typedef struct _FILE_COMPRESSION_INFORMATION { + LARGE_INTEGER CompressedFileSize; + USHORT CompressionFormat; + UCHAR CompressionUnitShift; + UCHAR ChunkShift; + UCHAR ClusterShift; + UCHAR Reserved[3]; +} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION; + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + + +// file system information structures + +typedef struct _FILE_FS_DEVICE_INFORMATION { + DEVICE_TYPE DeviceType; + ULONG Characteristics; +} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; + + +typedef struct _FILE_FS_VOLUME_INFORMATION { + TIME VolumeCreationTime; + ULONG VolumeSerialNumber; + ULONG VolumeLabelLength; + BOOLEAN SupportsObjects; + WCHAR VolumeLabel[0]; +} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; + +typedef struct _FILE_FS_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER AvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; +} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; + +typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { + ULONG FileSystemAttributes; + LONG MaximumComponentNameLength; + ULONG FileSystemNameLength; + WCHAR FileSystemName[0]; +} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; + +/* + FileSystemAttributes is one of the following values: + + FILE_CASE_SENSITIVE_SEARCH 0x00000001 + FILE_CASE_PRESERVED_NAMES 0x00000002 + FILE_UNICODE_ON_DISK 0x00000004 + FILE_PERSISTENT_ACLS 0x00000008 + FILE_FILE_COMPRESSION 0x00000010 + FILE_VOLUME_QUOTAS 0x00000020 + FILE_VOLUME_IS_COMPRESSED 0x00008000 +*/ +typedef struct _FILE_FS_LABEL_INFORMATION { + ULONG VolumeLabelLength; + WCHAR VolumeLabel[0]; +} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; + +// read file scatter / write file scatter +//FIXME I am a win32 struct aswell + +typedef union _FILE_SEGMENT_ELEMENT { + PVOID Buffer; + ULONG Alignment; +}FILE_SEGMENT_ELEMENT, *PFILE_SEGMENT_ELEMENT; + +// directory information + +typedef struct _OBJDIR_INFORMATION { + UNICODE_STRING ObjectName; + UNICODE_STRING ObjectTypeName; // Directory, Device ... + UCHAR Data[0]; +} OBJDIR_INFORMATION, *POBJDIR_INFORMATION; + + +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + TIME CreationTime; + TIME LastAccessTime; + TIME LastWriteTime; + TIME ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[0]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_FULL_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + TIME CreationTime; + TIME LastAccessTime; + TIME LastWriteTime; + TIME ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + WCHAR FileName[0]; // variable size +} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION, + FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; + + +typedef struct _FILE_BOTH_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + TIME CreationTime; + TIME LastAccessTime; + TIME LastWriteTime; + TIME ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CHAR ShortNameLength; + WCHAR ShortName[12]; // 8.3 name + WCHAR FileName[0]; +} FILE_BOTH_DIRECTORY_INFORMATION, *PFILE_BOTH_DIRECTORY_INFORMATION, + FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + + +/* + NotifyFilter / CompletionFilter: + + FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001 + FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002 + FILE_NOTIFY_CHANGE_NAME 0x00000003 + FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004 + FILE_NOTIFY_CHANGE_SIZE 0x00000008 + FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 + FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020 + FILE_NOTIFY_CHANGE_CREATION 0x00000040 + FILE_NOTIFY_CHANGE_EA 0x00000080 + FILE_NOTIFY_CHANGE_SECURITY 0x00000100 + FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200 + FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400 + FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 +*/ + +typedef struct _FILE_NOTIFY_INFORMATION { + ULONG Action; + ULONG FileNameLength; + WCHAR FileName[0]; +} FILE_NOTIFY_INFORMATION; + + +/* + Action is one of the following values: + + FILE_ACTION_ADDED 0x00000001 + FILE_ACTION_REMOVED 0x00000002 + FILE_ACTION_MODIFIED 0x00000003 + FILE_ACTION_RENAMED_OLD_NAME 0x00000004 + FILE_ACTION_RENAMED_NEW_NAME 0x00000005 + FILE_ACTION_ADDED_STREAM 0x00000006 + FILE_ACTION_REMOVED_STREAM 0x00000007 + FILE_ACTION_MODIFIED_STREAM 0x00000008 + +*/ + + +// File System Control commands ( related to defragging ) + +#define FSCTL_READ_MFT_RECORD 0x90068 // NTFS only +#define FSCTL_GET_VOLUME_BITMAP 0x9006F +#define FSCTL_GET_RETRIEVAL_POINTERS 0x90073 +#define FSCTL_MOVE_FILE 0x90074 + +typedef struct _MAPPING_PAIR +{ + ULONGLONG Vcn; + ULONGLONG Lcn; +} MAPPING_PAIR, *PMAPPING_PAIR; + +typedef struct _GET_RETRIEVAL_DESCRIPTOR +{ + ULONG NumberOfPairs; + ULONGLONG StartVcn; + MAPPING_PAIR Pair[0]; // variable size +} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR; + +typedef struct _BITMAP_DESCRIPTOR +{ + ULONGLONG StartLcn; + ULONGLONG ClustersToEndOfVol; + BYTE Map[0]; // variable size +} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR; + +typedef struct _MOVEFILE_DESCRIPTOR +{ + HANDLE FileHandle; + ULONG Reserved; + LARGE_INTEGER StartVcn; + LARGE_INTEGER TargetLcn; + ULONG NumVcns; + ULONG Reserved1; +} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR; + + + +//typedef enum _TIMER_TYPE +//{ +// NotificationTimer, +// SynchronizationTimer +//} TIMER_TYPE; + +typedef struct _TIMER_BASIC_INFORMATION +{ + LARGE_INTEGER TimeRemaining; + BOOLEAN SignalState; +} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION; + +typedef enum _TIMER_INFORMATION_CLASS +{ + TimerBasicInformation +} TIMER_INFORMATION_CLASS; + +typedef +struct _LPC_PORT_BASIC_INFORMATION +{ + DWORD Unknown0; + DWORD Unknown1; + DWORD Unknown2; + DWORD Unknown3; + DWORD Unknown4; + DWORD Unknown5; + DWORD Unknown6; + DWORD Unknown7; + DWORD Unknown8; + DWORD Unknown9; + DWORD Unknown10; + DWORD Unknown11; + DWORD Unknown12; + DWORD Unknown13; + +} LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION; + +typedef struct _SECTION_BASIC_INFORMATION +{ + PVOID BaseAddress; + ULONG Attributes; + LARGE_INTEGER Size; +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; + +typedef struct _SECTION_IMAGE_INFORMATION +{ + PVOID EntryPoint; + ULONG Unknown1; + ULONG StackReserve; + ULONG StackCommit; + ULONG Subsystem; + USHORT MinorSubsystemVersion; + USHORT MajorSubsystemVersion; + ULONG Unknown2; + ULONG Characteristics; + USHORT ImageNumber; + BOOLEAN Executable; + UCHAR Unknown3; + ULONG Unknown4[3]; +} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; + +typedef enum _SECTION_INFORMATION_CLASS +{ + SectionBasicInformation, + SectionImageInformation, +} SECTION_INFORMATION_CLASS; + +#endif diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..75d8798 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,98 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/debug.h + * PURPOSE: Useful debugging macros + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 28/05/98: Created + */ + +/* + * NOTE: Define NDEBUG before including this header to disable debugging + * macros + */ + +#ifndef __INTERNAL_DEBUG +#define __INTERNAL_DEBUG + +#define UNIMPLEMENTED do {DbgPrint("%s at %s:%d is unimplemented, have a nice day\n",__FUNCTION__,__FILE__,__LINE__); for(;;); } while(0); + +/* FIXME: should probably remove this later */ +#if !defined(CHECKED) && !defined(NDEBUG) +#define CHECKED +#endif + +#ifndef NASSERT +#define assert(x) if (!(x)) {RtlAssert("#x",__FILE__,__LINE__, ""); } +#else +#define assert(x) +#endif + +#define DPRINT1(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT1 do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0); + +extern unsigned int old_idt[256][2]; +//extern unsigned int idt; +extern unsigned int old_idt_valid; + +#ifdef __NTOSKRNL__ +//#define DPRINT_CHECKS ExAllocatePool(NonPagedPool,0); assert(old_idt_valid || (!memcmp(old_idt,KiIdt,256*2))); +//#define DPRINT_CHECKS ExAllocatePool(NonPagedPool,0); +#define DPRINT_CHECKS +#else +#define DPRINT_CHECKS +#endif + +#ifndef NDEBUG +#define OLD_DPRINT(fmt,args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(fmt,args); } while(0); +#define DPRINT(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); DPRINT_CHECKS } while(0); +#define CHECKPOINT do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0); +#else +//#define DPRINT(args...) do { DPRINT_CHECKS } while (0); +#define DPRINT(args...) +#define OLD_DPRINT(args...) +#define CHECKPOINT +#endif /* NDEBUG */ + +/* + * FUNCTION: Assert a maximum value for the current irql + * ARGUMENTS: + * x = Maximum irql + */ +#define ASSERT_IRQL(x) assert(KeGetCurrentIrql()<=(x)) +#define assert_irql(x) assert(KeGetCurrentIrql()<=(x)) + +#define HBP_EXECUTE (0) +#define HBP_WRITE (1) +#define HBP_READWRITE (3) + +#define HBP_BYTE (0) +#define HBP_WORD (1) +#define HBP_DWORD (3) + +/* + * FUNCTION: Sets a hardware breakpoint + * ARGUMENTS: + * i = breakpoint to set (0 to 3) + * addr = linear address to break on + * type = Type of access to break on + * len = length of the variable to watch + * NOTES: + * The variable to watch must be aligned to its length (i.e. a dword + * breakpoint must be aligned to a dword boundary) + * + * A fatal exception will be generated on the access to the variable. + * It is (at the moment) only really useful for catching undefined + * pointers if you know the variable effected but not the buggy + * routine. + * + * FIXME: Extend to call out to kernel debugger on breakpoint + * Add support for I/O breakpoints + * REFERENCES: See the i386 programmer manual for more details + */ +void set_breakpoint(unsigned int i, unsigned int addr, unsigned int type, + unsigned int len); + + +#endif /* __INTERNAL_DEBUG */ diff --git a/include/defines.h b/include/defines.h new file mode 100644 index 0000000..3923d6a --- /dev/null +++ b/include/defines.h @@ -0,0 +1,4727 @@ +/* + Defines.h + + Windows32 API definitions + + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + + Author: Scott Christley + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +/* WARNING: This file is automatically generated. */ + +#ifndef _GNU_H_WINDOWS32_DEFINES +#define _GNU_H_WINDOWS32_DEFINES + +#ifndef RC_INVOKED +#include +#include +#endif + +#define WINBASEAPI + + + +#ifndef WIN32_NO_STATUS +//#define STATUS_WAIT_0 (0x00000000L) +//#define STATUS_ABANDONED_WAIT_0 (0x00000080L) +//#define STATUS_USER_APC (0x000000C0L) +//#define STATUS_TIMEOUT (0x00000102L) +//#define STATUS_PENDING (0x00000103L) +#endif /* WIN32_NO_STATUS */ + +#define GA_PARENT (1) +#define GA_ROOT (2) +#define GA_ROOTOWNER (3) + +/* CreateFile, GetFileAttributes, SetFileAttributes */ + +#define SECURITY_ANONYMOUS (0) +#define SECURITY_IDENTIFICATION (65536) +#define SECURITY_IMPERSONATION (131072) +#define SECURITY_DELEGATION (196608) +#define SECURITY_CONTEXT_TRACKING (262144) +#define SECURITY_EFFECTIVE_ONLY (524288) +#define SECURITY_SQOS_PRESENT (1048576) + + + + +#ifndef WIN32_LEAN_AND_MEAN + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MAX_PATH (260) +#define UNICODE_NULL ((WCHAR)0) +#define LF_FACESIZE (32) +#define LF_FULLFACESIZE (64) +#define ELF_VENDOR_SIZE (4) +#define MAX_DEFAULTCHAR (2) +#define MAX_LEADBYTES (12) +#define MENU_TEXT_LEN (40) +#define MAX_LANA (254) +#define NCBNAMSZ (16) +#define NETBIOS_NAME_LEN (16) +#define OFS_MAXPATHNAME (128) +#define MAX_TAB_STOPS (32) +#define RAS_MaxCallbackNumber (128) +#define RAS_MaxDeviceName (128) +#define RAS_MaxDeviceType (16) +#define RAS_MaxEntryName (256) +#define RAS_MaxIpAddress (15) +#define RAS_MaxIpxAddress (21) +#define RAS_MaxPhoneNumber (128) +#define UNLEN (256) +#define PWLEN (256) +#define CNLEN (15) +#define DNLEN (15) +/* Unsigned types max */ +#define MAXDWORD (0xFFFFFFFF) +#define MAXWORD (0xFFFF) +#define MAXBYTE (0xFF) +/* Signed types max/min */ +#define MINCHAR (0x80) +#define MAXCHAR (0x7F) +#define MINSHORT (0x8000) +#define MAXSHORT (0x7FFF) +#define MINLONG (0x80000000) +#define MAXLONG (0x7FFFFFFF) + +/* _llseek */ +#define FILE_BEGIN (0) +#define FILE_CURRENT (1) +#define FILE_END (2) + +/* _lopen, LZOpenFile, OpenFile */ +#define OF_READ (0) +#define OF_READWRITE (2) +#define OF_WRITE (1) +#define OF_SHARE_COMPAT (0) +#define OF_SHARE_DENY_NONE (64) +#define OF_SHARE_DENY_READ (48) +#define OF_SHARE_DENY_WRITE (32) +#define OF_SHARE_EXCLUSIVE (16) +#define OF_CANCEL (2048) +#define OF_CREATE (4096) +#define OF_DELETE (512) +#define OF_EXIST (16384) +#define OF_PARSE (256) +#define OF_PROMPT (8192) +#define OF_REOPEN (32768) +#define OF_VERIFY (1024) + +/* ActivateKeyboardLayout, LoadKeyboardLayout */ +#define HKL_NEXT (1) +#define HKL_PREV (0) +#define KLF_REORDER (8) +#define KLF_UNLOADPREVIOUS (4) +#define KLF_ACTIVATE (1) +#define KLF_NOTELLSHELL (128) +#define KLF_REPLACELANG (16) +#define KLF_SUBSTITUTE_OK (2) + +/* AppendMenu */ +#define MF_BITMAP (0x4L) +#define MF_DISABLED (0x2L) +#define MF_ENABLED (0L) +#define MF_GRAYED (0x1L) +#define MF_HELP (0x4000L) +#define MF_MENUBARBREAK (0x20L) +#define MF_MENUBREAK (0x40L) +#define MF_MOUSESELECT (0x8000L) +#define MF_OWNERDRAW (0x100L) +#define MF_POPUP (0x10L) +#define MF_SEPARATOR (0x800L) +#define MF_STRING (0L) +#define MF_SYSMENU (0x2000L) +#define MF_USECHECKBITMAPS (0x200L) + +/* Ternary Raster Operations - BitBlt */ +#define BLACKNESS 0x00000042 +#define NOTSRCERASE 0x001100A6 +#define NOTSRCCOPY 0x00330008 +#define SRCERASE 0x00440328 +#define DSTINVERT 0x00550009 +#define PATINVERT 0x005A0049 +#define SRCINVERT 0x00660046 +#define SRCAND 0x008800C6 +#define MERGEPAINT 0x00BB0226 +#define MERGECOPY 0x00C000CA +#define SRCCOPY 0x00CC0020 +#define SRCPAINT 0x00EE0086 +#define PATCOPY 0x00F00021 +#define PATPAINT 0x00FB0A09 +#define WHITENESS 0x00FF0062 + +/* Binary Raster Operations */ +#define R2_BLACK (1) +#define R2_COPYPEN (13) +#define R2_MASKNOTPEN (3) +#define R2_MASKPEN (9) +#define R2_MASKPENNOT (5) +#define R2_MERGENOTPEN (12) +#define R2_MERGEPEN (15) +#define R2_MERGEPENNOT (14) +#define R2_NOP (11) +#define R2_NOT (6) +#define R2_NOTCOPYPEN (4) +#define R2_NOTMASKPEN (8) +#define R2_NOTMERGEPEN (2) +#define R2_NOTXORPEN (10) +#define R2_WHITE (16) +#define R2_XORPEN (7) + +/* BroadcastSystemMessage */ +#define BSF_FLUSHDISK (4) +#define BSF_FORCEIFHUNG (32) +#define BSF_IGNORECURRENTTASK (2) +#define BSF_NOHANG (8) +#define BSF_POSTMESSAGE (16) +#define BSF_QUERY (1) +#define BSM_ALLCOMPONENTS (0) +#define BSM_APPLICATIONS (8) +#define BSM_INSTALLABLEDRIVERS (4) +#define BSM_NETDRIVER (2) +#define BSM_VXDS (1) +#define BROADCAST_QUERY_DENY (1112363332) + +/* BrowseCallbackProc */ + +/* CallNamedPipe */ +#define NMPWAIT_NOWAIT (1) +#define NMPWAIT_WAIT_FOREVER (-1) +#define NMPWAIT_USE_DEFAULT_WAIT (0) + +/* CascadeWindows, TileWindows */ +#define MDITILE_SKIPDISABLED (2) +#define MDITILE_HORIZONTAL (1) +#define MDITILE_VERTICAL (0) + +/* CBTProc */ +#define HCBT_ACTIVATE (5) +#define HCBT_CLICKSKIPPED (6) +#define HCBT_CREATEWND (3) +#define HCBT_DESTROYWND (4) +#define HCBT_KEYSKIPPED (7) +#define HCBT_MINMAX (1) +#define HCBT_MOVESIZE (0) +#define HCBT_QS (2) +#define HCBT_SETFOCUS (9) +#define HCBT_SYSCOMMAND (8) + +/* ChangeDisplaySettings */ +#define DM_BITSPERPEL (0x40000L) +#define DM_PELSWIDTH (0x80000L) +#define DM_PELSHEIGHT (0x100000L) +#define DM_DISPLAYFLAGS (0x200000L) +#define DM_DISPLAYFREQUENCY (0x400000L) +#define CDS_UPDATEREGISTRY (1) +#define CDS_TEST (2) +#define DISP_CHANGE_SUCCESSFUL (0) +#define DISP_CHANGE_RESTART (1) +#define DISP_CHANGE_BADFLAGS (-4) +#define DISP_CHANGE_FAILED (-1) +#define DISP_CHANGE_BADMODE (-2) +#define DISP_CHANGE_NOTUPDATED (-3) + +/* ChangeServiceConfig */ +#define SERVICE_NO_CHANGE (-1) +#define SERVICE_KERNEL_DRIVER (1) +#define SERVICE_FILE_SYSTEM_DRIVER (2) +#define SERVICE_RECOGNIZER_DRIVER (8) +#define SERVICE_WIN32_OWN_PROCESS (16) +#define SERVICE_WIN32_SHARE_PROCESS (32) +#define SERVICE_INTERACTIVE_PROCESS (256) +#define SERVICE_BOOT_START (0) +#define SERVICE_SYSTEM_START (1) +#define SERVICE_AUTO_START (2) +#define SERVICE_DEMAND_START (3) +#define SERVICE_DISABLED (4) + +/* SERVICE_STATUS structure */ +#define SERVICE_STOPPED (1) +#define SERVICE_START_PENDING (2) +#define SERVICE_STOP_PENDING (3) +#define SERVICE_RUNNING (4) +#define SERVICE_CONTINUE_PENDING (5) +#define SERVICE_PAUSE_PENDING (6) +#define SERVICE_PAUSED (7) +#define SERVICE_ACCEPT_STOP (1) +#define SERVICE_ACCEPT_PAUSE_CONTINUE (2) +#define SERVICE_ACCEPT_SHUTDOWN (4) + +/* CheckDlgButton */ +#define BST_CHECKED (1) +#define BST_INDETERMINATE (2) +#define BST_UNCHECKED (0) +#define BST_FOCUS (8) +#define BST_PUSHED (4) + +/* CheckMenuItem, HiliteMenuItem */ +#define MF_BYCOMMAND (0L) +#define MF_BYPOSITION (0x400L) +#define MF_CHECKED (0x8L) +#define MF_UNCHECKED (0L) +#define MF_HILITE (0x80L) +#define MF_UNHILITE (0L) + +/* ChildWindowFromPointEx */ +#define CWP_ALL (0) +#define CWP_SKIPINVISIBLE (1) +#define CWP_SKIPDISABLED (2) +#define CWP_SKIPTRANSPARENT (4) + +/* ClearCommError */ +#define CE_BREAK (16) +#define CE_DNS (2048) +#define CE_FRAME (8) +#define CE_IOE (1024) +#define CE_MODE (32768) +#define CE_OOP (4096) +#define CE_OVERRUN (2) +#define CE_PTO (512) +#define CE_RXOVER (1) +#define CE_RXPARITY (4) +#define CE_TXFULL (256) + +/* ChooseMatchToTarget */ + +/* CombineRgn */ +#define RGN_AND (1) +#define RGN_COPY (5) +#define RGN_DIFF (4) +#define RGN_OR (2) +#define RGN_XOR (3) +#define NULLREGION (1) +#define SIMPLEREGION (2) +#define COMPLEXREGION (3) +#define ERROR (0) + +/* CommonDlgExtendedError */ +#define CDERR_DIALOGFAILURE (0xffff) +#define CDERR_FINDRESFAILURE (6) +#define CDERR_INITIALIZATION (2) +#define CDERR_LOADRESFAILURE (7) +#define CDERR_LOADSTRFAILURE (5) +#define CDERR_LOCKRESFAILURE (8) +#define CDERR_MEMALLOCFAILURE (9) +#define CDERR_MEMLOCKFAILURE (10) +#define CDERR_NOHINSTANCE (4) +#define CDERR_NOHOOK (11) +#define CDERR_NOTEMPLATE (3) +#define CDERR_REGISTERMSGFAIL (12) +#define CDERR_STRUCTSIZE (1) +#define PDERR_CREATEICFAILURE (0x1000 + 10) +#define PDERR_DEFAULTDIFFERENT (0x1000 + 12) +#define PDERR_DNDMMISMATCH (0x1000 + 9) +#define PDERR_GETDEVMODEFAIL (0x1000 + 5) +#define PDERR_INITFAILURE (0x1000 + 6) +#define PDERR_LOADDRVFAILURE (0x1000 + 4) +#define PDERR_NODEFAULTPRN (0x1000 + 8) +#define PDERR_NODEVICES (0x1000 + 7) +#define PDERR_PARSEFAILURE (0x1000 + 2) +#define PDERR_PRINTERNOTFOUND (0x1000 + 11) +#define PDERR_RETDEFFAILURE (0x1000 + 3) +#define PDERR_SETUPFAILURE (0x1000 + 1) +#define CFERR_MAXLESSTHANMIN (0x2000 + 2) +#define CFERR_NOFONTS (0x2000 + 1) +#define FNERR_BUFFERTOOSMALL (0x3000 + 3) +#define FNERR_INVALIDFILENAME (0x3000 + 2) +#define FNERR_SUBCLASSFAILURE (0x3000 + 1) +#define FRERR_BUFFERLENGTHZERO (0x4000 + 1) + +/* CompareString, LCMapString */ +#define LOCALE_SYSTEM_DEFAULT (0x800L) +#define LOCALE_USER_DEFAULT (0x400L) +#define NORM_IGNORECASE (1) +#define NORM_IGNOREKANATYPE (65536) +#define NORM_IGNORENONSPACE (2) +#define NORM_IGNORESYMBOLS (4) +#define NORM_IGNOREWIDTH (131072) +#define SORT_STRINGSORT (4096) +#define LCMAP_BYTEREV (2048) +#define LCMAP_FULLWIDTH (8388608) +#define LCMAP_HALFWIDTH (4194304) +#define LCMAP_HIRAGANA (1048576) +#define LCMAP_KATAKANA (2097152) +#define LCMAP_LOWERCASE (256) +#define LCMAP_SORTKEY (1024) +#define LCMAP_UPPERCASE (512) + +/* ContinueDebugEvent */ +#define DBG_CONTINUE (0x10002L) +#define DBG_CONTROL_BREAK (0x40010008L) +#define DBG_CONTROL_C (0x40010005L) +#define DBG_EXCEPTION_NOT_HANDLED (0x80010001L) +#define DBG_TERMINATE_THREAD (0x40010003L) +#define DBG_TERMINATE_PROCESS (0x40010004L) + +/* ControlService */ +#define SERVICE_CONTROL_STOP (1) +#define SERVICE_CONTROL_PAUSE (2) +#define SERVICE_CONTROL_CONTINUE (3) +#define SERVICE_CONTROL_INTERROGATE (4) +#define SERVICE_CONTROL_SHUTDOWN (5) + +/* CopyImage, LoadImage */ +#define IMAGE_BITMAP (0) +#define IMAGE_CURSOR (2) +#define IMAGE_ENHMETAFILE (1) +#define IMAGE_ICON (1) +#define LR_COPYDELETEORG (8) +#define LR_COPYRETURNORG (4) +#define LR_MONOCHROME (1) +#define LR_CREATEDIBSECTION (8192) +#define LR_DEFAULTSIZE (64) + +/* CreateDesktop */ +#define DF_ALLOWOTHERACCOUNTHOOK (0x1L) +#define DESKTOP_CREATEMENU (0x4L) +#define DESKTOP_CREATEWINDOW (0x2L) +#define DESKTOP_ENUMERATE (0x40L) +#define DESKTOP_HOOKCONTROL (0x8L) +#define DESKTOP_JOURNALPLAYBACK (0x20L) +#define DESKTOP_JOURNALRECORD (0x10L) +#define DESKTOP_READOBJECTS (0x1L) +#define DESKTOP_SWITCHDESKTOP (0x100L) +#define DESKTOP_WRITEOBJECTS (0x80L) +#define WSF_VISIBLE (0x1L) + +/* CreateDIBitmap */ +#define CBM_INIT (0x4L) +#define DIB_PAL_COLORS (1) +#define DIB_RGB_COLORS (0) + +/* CreateFileMapping, VirtualAlloc, VirtualFree, VirtualProtect */ + +/* CreateFont */ +#define FW_DONTCARE (0) +#define FW_THIN (100) +#define FW_EXTRALIGHT (200) +#define FW_LIGHT (300) +#define FW_NORMAL (400) +#define FW_REGULAR FW_NORMAL +#define FW_MEDIUM (500) +#define FW_SEMIBOLD (600) +#define FW_BOLD (700) +#define FW_EXTRABOLD (800) +#define FW_HEAVY (900) +#define ANSI_CHARSET (0) +#define DEFAULT_CHARSET (1) +#define SYMBOL_CHARSET (2) +#define SHIFTJIS_CHARSET (128) +#define HANGEUL_CHARSET (129) +#define GB2312_CHARSET (134) +#define CHINESEBIG5_CHARSET (136) +#define GREEK_CHARSET (161) +#define TURKISH_CHARSET (162) +#define HEBREW_CHARSET (177) +#define ARABIC_CHARSET (178) +#define BALTIC_CHARSET (186) +#define RUSSIAN_CHARSET (204) +#define THAI_CHARSET (222) +#define EASTEUROPE_CHARSET (238) +#define OEM_CHARSET (255) +#define OUT_DEFAULT_PRECIS (0) +#define OUT_STRING_PRECIS (1) +#define OUT_CHARACTER_PRECIS (2) +#define OUT_STROKE_PRECIS (3) +#define OUT_TT_PRECIS (4) +#define OUT_DEVICE_PRECIS (5) +#define OUT_RASTER_PRECIS (6) +#define OUT_TT_ONLY_PRECIS (7) +#define OUT_OUTLINE_PRECIS (8) +#define CLIP_DEFAULT_PRECIS (0) +#define CLIP_CHARACTER_PRECIS (1) +#define CLIP_STROKE_PRECIS (2) +#define CLIP_MASK (15) +#define CLIP_LH_ANGLES (16) +#define CLIP_TT_ALWAYS (32) +#define CLIP_EMBEDDED (128) +#define DEFAULT_QUALITY (0) +#define DRAFT_QUALITY (1) +#define PROOF_QUALITY (2) +#define DEFAULT_PITCH (0) +#define FIXED_PITCH (1) +#define VARIABLE_PITCH (2) +#define FF_DECORATIVE (80) +#define FF_DONTCARE (0) +#define FF_MODERN (48) +#define FF_ROMAN (16) +#define FF_SCRIPT (64) +#define FF_SWISS (32) + +/* CreateHatchBrush */ +#define HS_BDIAGONAL (3) +#define HS_CROSS (4) +#define HS_DIAGCROSS (5) +#define HS_FDIAGONAL (2) +#define HS_HORIZONTAL (0) +#define HS_VERTICAL (1) + +/* CreateIconFromResourceEx */ +#define LR_DEFAULTCOLOR (0) +#define LR_LOADREALSIZE (128) +#define LR_MONOCHROME (1) + +/* CreateMailslot, GetMailslotInfo */ +#define MAILSLOT_WAIT_FOREVER (0xffffffffL) +#define MAILSLOT_NO_MESSAGE (0xffffffffL) + +/* CreateMappedBitmap */ +#define CMB_MASKED (2) + +/* CreateNamedPipe */ +#define PIPE_ACCESS_DUPLEX (3) +#define PIPE_ACCESS_INBOUND (1) +#define PIPE_ACCESS_OUTBOUND (2) +#define WRITE_DAC (0x40000L) +#define WRITE_OWNER (0x80000L) +#define ACCESS_SYSTEM_SECURITY (0x1000000L) +#define PIPE_TYPE_BYTE (0) +#define PIPE_TYPE_MESSAGE (4) +#define PIPE_READMODE_BYTE (0) +#define PIPE_READMODE_MESSAGE (2) +#define PIPE_WAIT (0) +#define PIPE_NOWAIT (1) +#define PIPE_UNLIMITED_INSTANCES (255) + +/* CreatePen, ExtCreatePen */ +#define PS_GEOMETRIC (65536) +#define PS_COSMETIC (0) +#define PS_ALTERNATE (8) +#define PS_SOLID (0) +#define PS_DASH (1) +#define PS_DOT (2) +#define PS_DASHDOT (3) +#define PS_DASHDOTDOT (4) +#define PS_NULL (5) +#define PS_USERSTYLE (7) +#define PS_INSIDEFRAME (6) +#define PS_ENDCAP_ROUND (0) +#define PS_ENDCAP_SQUARE (256) +#define PS_ENDCAP_FLAT (512) +#define PS_JOIN_BEVEL (4096) +#define PS_JOIN_MITER (8192) +#define PS_JOIN_ROUND (0) +#define PS_STYLE_MASK (15) +#define PS_ENDCAP_MASK (3840) +#define PS_TYPE_MASK (983040) + +/* CreatePolygonRgn */ +#define ALTERNATE (1) +#define WINDING (2) + + +/* CreateService */ +#define SERVICE_ALL_ACCESS (0xf01ffL) +#define SERVICE_CHANGE_CONFIG (2) +#define SERVICE_ENUMERATE_DEPENDENTS (8) +#define SERVICE_INTERROGATE (128) +#define SERVICE_PAUSE_CONTINUE (64) +#define SERVICE_QUERY_CONFIG (1) +#define SERVICE_QUERY_STATUS (4) +#define SERVICE_START (16) +#define SERVICE_STOP (32) +#define SERVICE_USER_DEFINED_CONTROL (256) +#define SERVICE_WIN32_OWN_PROCESS (16) +#define SERVICE_WIN32_SHARE_PROCESS (32) +#define SERVICE_KERNEL_DRIVER (1) +#define SERVICE_FILE_SYSTEM_DRIVER (2) +#define SERVICE_INTERACTIVE_PROCESS (256) +#define SERVICE_BOOT_START (0) +#define SERVICE_SYSTEM_START (1) +#define SERVICE_AUTO_START (2) +#define SERVICE_DEMAND_START (3) +#define SERVICE_DISABLED (4) +#define SERVICE_ERROR_IGNORE (0) +#define SERVICE_ERROR_NORMAL (1) +#define SERVICE_ERROR_SEVERE (2) +#define SERVICE_ERROR_CRITICAL (3) + +/* CreateTapePartition, WriteTapemark */ +#define TAPE_FIXED_PARTITIONS (0L) +#define TAPE_INITIATOR_PARTITIONS (0x2L) +#define TAPE_SELECT_PARTITIONS (0x1L) +#define TAPE_FILEMARKS (0x1L) +#define TAPE_LONG_FILEMARKS (0x3L) +#define TAPE_SETMARKS (0L) +#define TAPE_SHORT_FILEMARKS (0x2L) + +/* CreateWindow */ +#define CW_USEDEFAULT (0x80000000) +#define WS_BORDER (0x800000L) +#define WS_CAPTION (0xc00000L) +#define WS_CHILD (0x40000000L) +#define WS_CHILDWINDOW (0x40000000L) +#define WS_CLIPCHILDREN (0x2000000L) +#define WS_CLIPSIBLINGS (0x4000000L) +#define WS_DISABLED (0x8000000L) +#define WS_DLGFRAME (0x400000L) +#define WS_GROUP (0x20000L) +#define WS_HSCROLL (0x100000L) +#define WS_ICONIC (0x20000000L) +#define WS_MAXIMIZE (0x1000000L) +#define WS_MAXIMIZEBOX (0x10000L) +#define WS_MINIMIZE (0x20000000L) +#define WS_MINIMIZEBOX (0x20000L) +#define WS_OVERLAPPED (0L) +#define WS_OVERLAPPEDWINDOW (0xcf0000L) +#define WS_POPUP (0x80000000L) +#define WS_POPUPWINDOW (0x80880000L) +#define WS_SIZEBOX (0x40000L) +#define WS_SYSMENU (0x80000L) +#define WS_TABSTOP (0x10000L) +#define WS_THICKFRAME (0x40000L) +#define WS_TILED (0L) +#define WS_TILEDWINDOW (0xcf0000L) +#define WS_VISIBLE (0x10000000L) +#define WS_VSCROLL (0x200000L) +#define MDIS_ALLCHILDSTYLES (0x1) +#define BS_3STATE (0x5L) +#define BS_AUTO3STATE (0x6L) +#define BS_AUTOCHECKBOX (0x3L) +#define BS_AUTORADIOBUTTON (0x9L) +#define BS_BITMAP (0x80L) +#define BS_BOTTOM (0x800L) +#define BS_CENTER (0x300L) +#define BS_CHECKBOX (0x2L) +#define BS_DEFPUSHBUTTON (0x1L) +#define BS_GROUPBOX (0x7L) +#define BS_ICON (0x40L) +#define BS_LEFT (0x100L) +#define BS_LEFTTEXT (0x20L) +#define BS_MULTILINE (0x2000L) +#define BS_NOTIFY (0x4000L) +#define BS_OWNERDRAW (0xbL) +#define BS_PUSHBUTTON (0L) +#define BS_PUSHLIKE (0x1000L) +#define BS_RADIOBUTTON (0x4L) +#define BS_RIGHT (0x200L) +#define BS_RIGHTBUTTON (0x20L) +#define BS_TEXT (0L) +#define BS_TOP (0x400L) +#define BS_USERBUTTON (0x8L) +#define BS_VCENTER (0xc00L) +#define CBS_AUTOHSCROLL (0x40L) +#define CBS_DISABLENOSCROLL (0x800L) +#define CBS_DROPDOWN (0x2L) +#define CBS_DROPDOWNLIST (0x3L) +#define CBS_HASSTRINGS (0x200L) +#define CBS_LOWERCASE (0x4000L) +#define CBS_NOINTEGRALHEIGHT (0x400L) +#define CBS_OEMCONVERT (0x80L) +#define CBS_OWNERDRAWFIXED (0x10L) +#define CBS_OWNERDRAWVARIABLE (0x20L) +#define CBS_SIMPLE (0x1L) +#define CBS_SORT (0x100L) +#define CBS_UPPERCASE (0x2000L) +#define ES_AUTOHSCROLL (0x80L) +#define ES_AUTOVSCROLL (0x40L) +#define ES_CENTER (0x1L) +#define ES_LEFT (0L) +#define ES_LOWERCASE (0x10L) +#define ES_MULTILINE (0x4L) +#define ES_NOHIDESEL (0x100L) +#define ES_NUMBER (0x2000L) +#define ES_OEMCONVERT (0x400L) +#define ES_PASSWORD (0x20L) +#define ES_READONLY (0x800L) +#define ES_RIGHT (0x2L) +#define ES_UPPERCASE (0x8L) +#define ES_WANTRETURN (0x1000L) +#define LBS_DISABLENOSCROLL (0x1000L) +#define LBS_EXTENDEDSEL (0x800L) +#define LBS_HASSTRINGS (0x40L) +#define LBS_MULTICOLUMN (0x200L) +#define LBS_MULTIPLESEL (0x8L) +#define LBS_NODATA (0x2000L) +#define LBS_NOINTEGRALHEIGHT (0x100L) +#define LBS_NOREDRAW (0x4L) +#define LBS_NOSEL (0x4000L) +#define LBS_NOTIFY (0x1L) +#define LBS_OWNERDRAWFIXED (0x10L) +#define LBS_OWNERDRAWVARIABLE (0x20L) +#define LBS_SORT (0x2L) +#define LBS_STANDARD (0xa00003L) +#define LBS_USETABSTOPS (0x80L) +#define LBS_WANTKEYBOARDINPUT (0x400L) +#define SBS_BOTTOMALIGN (0x4L) +#define SBS_HORZ (0L) +#define SBS_LEFTALIGN (0x2L) +#define SBS_RIGHTALIGN (0x4L) +#define SBS_SIZEBOX (0x8L) +#define SBS_SIZEBOXBOTTOMRIGHTALIGN (0x4L) +#define SBS_SIZEBOXTOPLEFTALIGN (0x2L) +#define SBS_SIZEGRIP (0x10L) +#define SBS_TOPALIGN (0x2L) +#define SBS_VERT (0x1L) +#define SS_BITMAP (0xeL) +#define SS_BLACKFRAME (0x7L) +#define SS_BLACKRECT (0x4L) +#define SS_CENTER (0x1L) +#define SS_CENTERIMAGE (0x200L) +#define SS_ENHMETAFILE (0xfL) +#define SS_ETCHEDFRAME (0x12L) +#define SS_ETCHEDHORZ (0x10L) +#define SS_ETCHEDVERT (0x11L) +#define SS_GRAYFRAME (0x8L) +#define SS_GRAYRECT (0x5L) +#define SS_ICON (0x3L) +#define SS_LEFT (0L) +#define SS_LEFTNOWORDWRAP (0xcL) +#define SS_NOPREFIX (0x80L) +#define SS_NOTIFY (0x100L) +#define SS_OWNERDRAW (0xdL) +#define SS_REALSIZEIMAGE (0x800L) +#define SS_RIGHT (0x2L) +#define SS_RIGHTJUST (0x400L) +#define SS_SIMPLE (0xbL) +#define SS_SUNKEN (0x1000L) +#define SS_USERITEM (0xaL) +#define SS_WHITEFRAME (0x9L) +#define SS_WHITERECT (0x6L) +#define DS_3DLOOK (0x4L) +#define DS_ABSALIGN (0x1L) +#define DS_CENTER (0x800L) +#define DS_CENTERMOUSE (0x1000L) +#define DS_CONTEXTHELP (0x2000L) +#define DS_CONTROL (0x400L) +#define DS_FIXEDSYS (0x8L) +#define DS_LOCALEDIT (0x20L) +#define DS_MODALFRAME (0x80L) +#define DS_NOFAILCREATE (0x10L) +#define DS_NOIDLEMSG (0x100L) +#define DS_SETFONT (0x40L) +#define DS_SETFOREGROUND (0x200L) +#define DS_SYSMODAL (0x2L) + +/* CreateWindowEx */ +#define WS_EX_ACCEPTFILES (0x10L) +#define WS_EX_APPWINDOW (0x40000L) +#define WS_EX_CLIENTEDGE (0x200L) +#define WS_EX_CONTEXTHELP (0x400L) +#define WS_EX_CONTROLPARENT (0x10000L) +#define WS_EX_DLGMODALFRAME (0x1L) +#define WS_EX_LEFT (0L) +#define WS_EX_LEFTSCROLLBAR (0x4000L) +#define WS_EX_LTRREADING (0L) +#define WS_EX_MDICHILD (0x40L) +#define WS_EX_NOPARENTNOTIFY (0x4L) +#define WS_EX_OVERLAPPEDWINDOW (0x300L) +#define WS_EX_PALETTEWINDOW (0x188L) +#define WS_EX_RIGHT (0x1000L) +#define WS_EX_RIGHTSCROLLBAR (0L) +#define WS_EX_RTLREADING (0x2000L) +#define WS_EX_STATICEDGE (0x20000L) +#define WS_EX_TOOLWINDOW (0x80L) +#define WS_EX_TOPMOST (0x8L) +#define WS_EX_TRANSPARENT (0x20L) +#define WS_EX_WINDOWEDGE (0x100L) + +/* CreateWindowStation */ +#define WINSTA_ACCESSCLIPBOARD (0x4L) +#define WINSTA_ACCESSGLOBALATOMS (0x20L) +#define WINSTA_CREATEDESKTOP (0x8L) +#define WINSTA_ENUMDESKTOPS (0x1L) +#define WINSTA_ENUMERATE (0x100L) +#define WINSTA_EXITWINDOWS (0x40L) +#define WINSTA_READATTRIBUTES (0x2L) +#define WINSTA_READSCREEN (0x200L) +#define WINSTA_WRITEATTRIBUTES (0x10L) + +/* DdeCallback */ + +/* DdeClientTransaction */ + +/* DdeEnableCallback */ + +/* DdeGetLastError */ + +/* DdeInitialize */ + +/* DdeNameService */ + +/* DebugProc */ +#define WH_CALLWNDPROC (4) +#define WH_CALLWNDPROCRET (12) +#define WH_CBT (5) +#define WH_DEBUG (9) +#define WH_GETMESSAGE (3) +#define WH_JOURNALPLAYBACK (1) +#define WH_JOURNALRECORD (0) +#define WH_KEYBOARD (2) +#define WH_MOUSE (7) +#define WH_MSGFILTER (-1) +#define WH_SHELL (10) +#define WH_SYSMSGFILTER (6) +#define WH_MSGFILTER (-1) +#define WH_FOREGROUNDIDLE (11) + +/* DefineDosDevice */ +#define DDD_RAW_TARGET_PATH (1) +#define DDD_REMOVE_DEFINITION (2) +#define DDD_EXACT_MATCH_ON_REMOVE (4) + +/* DeviceCapbilities */ +#define DC_BINNAMES (12) +#define DC_BINS (6) +#define DC_COPIES (18) +#define DC_DRIVER (11) +#define DC_DATATYPE_PRODUCED (21) +#define DC_DUPLEX (7) +#define DC_EMF_COMPLIANT (20) +#define DC_ENUMRESOLUTIONS (13) +#define DC_EXTRA (9) +#define DC_FIELDS (1) +#define DC_FILEDEPENDENCIES (14) +#define DC_MAXEXTENT (5) +#define DC_MINEXTENT (4) +#define DC_ORIENTATION (17) +#define DC_PAPERNAMES (16) +#define DC_PAPERS (2) +#define DC_PAPERSIZE (3) +#define DC_SIZE (8) +#define DC_TRUETYPE (15) +#define DCTT_BITMAP (0x1L) +#define DCTT_DOWNLOAD (0x2L) +#define DCTT_SUBDEV (0x4L) +#define DC_VERSION (10) +#define DC_BINADJUST (19) +#define DC_DATATYPE_PRODUCED (21) + +/* DeviceIoControl */ + +/* DlgDirList */ +#define DDL_ARCHIVE (32) +#define DDL_DIRECTORY (16) +#define DDL_DRIVES (16384) +#define DDL_EXCLUSIVE (32768) +#define DDL_HIDDEN (2) +#define DDL_READONLY (1) +#define DDL_READWRITE (0) +#define DDL_SYSTEM (4) +#define DDL_POSTMSGS (8192) + +/* DllEntryPoint */ +#define DLL_PROCESS_ATTACH (1) +#define DLL_THREAD_ATTACH (2) +#define DLL_PROCESS_DETACH (0) +#define DLL_THREAD_DETACH (3) + +/* DocumentProperties */ +#define DM_IN_BUFFER (8) +#define DM_MODIFY (8) +#define DM_IN_PROMPT (4) +#define DM_PROMPT (4) +#define DM_OUT_BUFFER (2) +#define DM_COPY (2) +#define DM_UPDATE (1) + +/* DrawAnimatedRects */ +#define IDANI_OPEN (1) +#define IDANI_CLOSE (2) + +/* DrawCaption */ +#define DC_ACTIVE (1) +#define DC_SMALLCAP (2) + +/* DrawEdge */ +#define BDR_RAISEDINNER (4) +#define BDR_SUNKENINNER (8) +#define BDR_RAISEDOUTER (1) +#define BDR_SUNKENOUTER (1) +#define EDGE_BUMP (9) +#define EDGE_ETCHED (6) +#define EDGE_RAISED (5) +#define EDGE_SUNKEN (10) +#define BF_ADJUST (8192) +#define BF_BOTTOM (8) +#define BF_BOTTOMLEFT (9) +#define BF_BOTTOMRIGHT (12) +#define BF_DIAGONAL (16) +#define BF_DIAGONAL_ENDBOTTOMLEFT (25) +#define BF_DIAGONAL_ENDBOTTOMRIGHT (28) +#define BF_DIAGONAL_ENDTOPLEFT (19) +#define BF_DIAGONAL_ENDTOPRIGHT (22) +#define BF_FLAT (16384) +#define BF_LEFT (1) +#define BF_MIDDLE (2048) +#define BF_MONO (32768) +#define BF_RECT (15) +#define BF_RIGHT (4) +#define BF_SOFT (4096) +#define BF_TOP (2) +#define BF_TOPLEFT (3) +#define BF_TOPRIGHT (6) + +/* DrawFrameControl */ +#define DFC_BUTTON (4) +#define DFC_CAPTION (1) +#define DFC_MENU (2) +#define DFC_SCROLL (3) +#define DFCS_BUTTON3STATE (8) +#define DFCS_BUTTONCHECK (0) +#define DFCS_BUTTONPUSH (16) +#define DFCS_BUTTONRADIO (4) +#define DFCS_BUTTONRADIOIMAGE (1) +#define DFCS_BUTTONRADIOMASK (2) +#define DFCS_CAPTIONCLOSE (0) +#define DFCS_CAPTIONHELP (4) +#define DFCS_CAPTIONMAX (2) +#define DFCS_CAPTIONMIN (1) +#define DFCS_CAPTIONRESTORE (3) +#define DFCS_MENUARROW (0) +#define DFCS_MENUBULLET (2) +#define DFCS_MENUCHECK (1) +#define DFCS_SCROLLCOMBOBOX (5) +#define DFCS_SCROLLDOWN (1) +#define DFCS_SCROLLLEFT (2) +#define DFCS_SCROLLRIGHT (3) +#define DFCS_SCROLLSIZEGRIP (8) +#define DFCS_SCROLLUP (0) +#define DFCS_ADJUSTRECT (8192) +#define DFCS_CHECKED (1024) +#define DFCS_FLAT (16384) +#define DFCS_INACTIVE (256) +#define DFCS_MONO (32768) +#define DFCS_PUSHED (512) + +/* DrawIconEx */ +#define DI_COMPAT (4) +#define DI_DEFAULTSIZE (8) +#define DI_IMAGE (2) +#define DI_MASK (1) +#define DI_NORMAL (3) + +/* DrawState */ +#define DST_BITMAP (4) +#define DST_COMPLEX (0) +#define DST_ICON (3) +#define DST_PREFIXTEXT (2) +#define DST_TEXT (1) +#define DSS_NORMAL (0) +#define DSS_UNION (16) +#define DSS_DISABLED (32) +#define DSS_MONO (128) + +/* DrawStatusText */ +#define SBT_NOBORDERS (256) +#define SBT_OWNERDRAW (4096) +#define SBT_POPOUT (512) +#define SBT_RTLREADING (1024) + +/* DrawText, DrawTextEx */ +#define DT_BOTTOM (8) +#define DT_CALCRECT (1024) +#define DT_CENTER (1) +#define DT_EDITCONTROL (8192) +#define DT_END_ELLIPSIS (32768) +#define DT_PATH_ELLIPSIS (16384) +#define DT_EXPANDTABS (64) +#define DT_EXTERNALLEADING (512) +#define DT_LEFT (0) +#define DT_MODIFYSTRING (65536) +#define DT_NOCLIP (256) +#define DT_NOPREFIX (2048) +#define DT_RIGHT (2) +#define DT_RTLREADING (131072) +#define DT_SINGLELINE (32) +#define DT_TABSTOP (128) +#define DT_TOP (0) +#define DT_VCENTER (4) +#define DT_WORDBREAK (16) +#define DT_INTERNAL (4096) + + +/* EditWordBreakProc */ +#define WB_ISDELIMITER (2) +#define WB_LEFT (0) +#define WB_RIGHT (1) + +/* EnableScrollBar */ +#define SB_BOTH (3) +#define SB_CTL (2) +#define SB_HORZ (0) +#define SB_VERT (1) +#define ESB_DISABLE_BOTH (3) +#define ESB_DISABLE_DOWN (2) +#define ESB_DISABLE_LEFT (1) +#define ESB_DISABLE_LTUP (1) +#define ESB_DISABLE_RIGHT (2) +#define ESB_DISABLE_RTDN (2) +#define ESB_DISABLE_UP (1) +#define ESB_ENABLE_BOTH (0) + +/* Scroll Bar notifications*/ +#define SB_LINEUP (0) +#define SB_LINEDOWN (1) +#define SB_LINELEFT (0) +#define SB_LINERIGHT (1) +#define SB_PAGEUP (2) +#define SB_PAGEDOWN (3) +#define SB_PAGELEFT (2) +#define SB_PAGERIGHT (3) +#define SB_THUMBPOSITION (4) +#define SB_THUMBTRACK (5) +#define SB_ENDSCROLL (8) +#define SB_LEFT (6) +#define SB_RIGHT (7) +#define SB_BOTTOM (7) +#define SB_TOP (6) + +/* EnumCalendarInfo */ +#define ENUM_ALL_CALENDARS (-1) + +/* EnumDateFormats */ +#define DATE_SHORTDATE (1) +#define DATE_LONGDATE (2) + +/* EnumDependentServices */ +#define SERVICE_ACTIVE (1) +#define SERVICE_INACTIVE (2) + +/* EnumFontFamExProc */ +#define DEVICE_FONTTYPE (2) +#define RASTER_FONTTYPE (1) +#define TRUETYPE_FONTTYPE (4) + +/* EnumObjects, GetCurrentObject, GetObjectType */ +#define OBJ_BRUSH (2) +#define OBJ_PEN (1) +#define OBJ_PAL (5) +#define OBJ_FONT (6) +#define OBJ_BITMAP (7) +#define OBJ_EXTPEN (11) +#define OBJ_REGION (8) +#define OBJ_DC (3) +#define OBJ_MEMDC (10) +#define OBJ_METAFILE (9) +#define OBJ_METADC (4) +#define OBJ_ENHMETAFILE (13) +#define OBJ_ENHMETADC (12) + +/* EnumPrinters */ + +/* EnumProtocols */ + +/* EnumResLangProc */ +#define RT_ACCELERATOR (MAKEINTRESOURCE(9)) +#define RT_BITMAP (MAKEINTRESOURCE(2)) +#define RT_DIALOG (MAKEINTRESOURCE(5)) +#define RT_FONT (MAKEINTRESOURCE(8)) +#define RT_FONTDIR (MAKEINTRESOURCE(7)) +#define RT_MENU (MAKEINTRESOURCE(4)) +#define RT_RCDATA (MAKEINTRESOURCE(10)) +#define RT_STRING (MAKEINTRESOURCE(6)) +#define RT_MESSAGETABLE (MAKEINTRESOURCE(11)) +#define RT_CURSOR (MAKEINTRESOURCE(1)) +#define RT_GROUP_CURSOR (MAKEINTRESOURCE(12)) +#define RT_ICON (MAKEINTRESOURCE(3)) +#define RT_GROUP_ICON (MAKEINTRESOURCE(13)) +#define RT_VERSION (MAKEINTRESOURCE(16)) + +/* EnumServicesStatus */ +#define SERVICE_WIN32 (48) +#define SERVICE_DRIVER (11) + +/* EnumSystemCodePages */ +#define CP_INSTALLED (1) +#define CP_SUPPORTED (2) + +/* EnumSystemLocales */ +#define LCID_INSTALLED (1) +#define LCID_SUPPORTED (2) + +/* EraseTape */ +#define TAPE_ERASE_LONG (0x1L) +#define TAPE_ERASE_SHORT (0L) + +/* Escape */ +#define SP_ERROR (-1) +#define SP_OUTOFDISK (-4) +#define SP_OUTOFMEMORY (-5) +#define SP_USERABORT (-3) +#define PHYSICALWIDTH (110) +#define PHYSICALHEIGHT (111) +#define PHYSICALOFFSETX (112) +#define PHYSICALOFFSETY (113) +#define SCALINGFACTORX (114) +#define SCALINGFACTORY (115) +#define QUERYESCSUPPORT (8) +#define ABORTDOC (2) +#define ENDDOC (11) +#define GETPHYSPAGESIZE (12) +#define GETPRINTINGOFFSET (13) +#define GETSCALINGFACTOR (14) +#define NEWFRAME (1) +#define NEXTBAND (3) +#define PASSTHROUGH (19) +#define SETABORTPROC (9) +#define STARTDOC (10) + +/* EscapeCommFunction */ +#define CLRDTR (6) +#define CLRRTS (4) +#define SETDTR (5) +#define SETRTS (3) +#define SETXOFF (1) +#define SETXON (2) +#define SETBREAK (8) +#define CLRBREAK (9) + +/* ExitWindowsEx */ +#define EWX_FORCE (4) +#define EWX_LOGOFF (0) +#define EWX_POWEROFF (8) +#define EWX_REBOOT (2) +#define EWX_SHUTDOWN (1) + +/* ExtFloodFill */ +#define FLOODFILLBORDER (0) +#define FLOODFILLSURFACE (1) + +/* ExtTextOut */ +#define ETO_CLIPPED (4) +#define ETO_GLYPH_INDEX (16) +#define ETO_OPAQUE (2) +#define ETO_RTLREADING (128) + +/* FillConsoleOutputAttribute */ +#define FOREGROUND_BLUE (1) +#define FOREGROUND_GREEN (2) +#define FOREGROUND_RED (4) +#define FOREGROUND_INTENSITY (8) +#define BACKGROUND_BLUE (16) +#define BACKGROUND_GREEN (32) +#define BACKGROUND_RED (64) +#define BACKGROUND_INTENSITY (128) + +/* FindFirstChangeNotification */ +#define FILE_NOTIFY_CHANGE_FILE_NAME (1) +#define FILE_NOTIFY_CHANGE_DIR_NAME (2) +#define FILE_NOTIFY_CHANGE_ATTRIBUTES (4) +#define FILE_NOTIFY_CHANGE_SIZE (8) +#define FILE_NOTIFY_CHANGE_LAST_WRITE (16) +#define FILE_NOTIFY_CHANGE_SECURITY (256) + +/* FindFirstPrinterChangeNotification */ + +/* FindNextPrinterNotification */ + +/* FMExtensionProc */ + +/* FoldString */ +#define MAP_FOLDCZONE (16) +#define MAP_FOLDDIGITS (128) +#define MAP_PRECOMPOSED (32) +#define MAP_COMPOSITE (64) + +/* ForegroundIdleProc */ +#define HC_ACTION (0) + +/* FormatMessage */ +#define FORMAT_MESSAGE_ALLOCATE_BUFFER (256) +#define FORMAT_MESSAGE_IGNORE_INSERTS (512) +#define FORMAT_MESSAGE_FROM_STRING (1024) +#define FORMAT_MESSAGE_FROM_HMODULE (2048) +#define FORMAT_MESSAGE_FROM_SYSTEM (4096) +#define FORMAT_MESSAGE_ARGUMENT_ARRAY (8192) +#define FORMAT_MESSAGE_MAX_WIDTH_MASK (255) + +/* GdiComment */ +#define GDICOMMENT_WINDOWS_METAFILE (-2147483647) +#define GDICOMMENT_BEGINGROUP (2) +#define GDICOMMENT_ENDGROUP (3) +#define GDICOMMENT_MULTIFORMATS (1073741828) +#define GDICOMMENT_IDENTIFIER (1128875079) + +/* GenerateConsoleCtrlEvent, HandlerRoutine */ +#define CTRL_C_EVENT (0) +#define CTRL_BREAK_EVENT (1) +#define CTRL_CLOSE_EVENT (2) +#define CTRL_LOGOFF_EVENT (5) +#define CTRL_SHUTDOWN_EVENT (6) + +/* GetAddressByName */ + +/* GetArcDirection */ +#define AD_COUNTERCLOCKWISE (1) +#define AD_CLOCKWISE (2) + +/* GetBinaryTypes */ +#define SCS_32BIT_BINARY (0) +#define SCS_DOS_BINARY (1) +#define SCS_OS216_BINARY (5) +#define SCS_PIF_BINARY (3) +#define SCS_POSIX_BINARY (4) +#define SCS_WOW_BINARY (2) + +/* GetBoundsRect, SetBoundsRect */ +#define DCB_DISABLE (8) +#define DCB_ENABLE (4) +#define DCB_RESET (1) +#define DCB_SET (3) +#define DCB_ACCUMULATE (2) + +/* GetCharacterPlacement, GetFontLanguageInfo */ +#define GCP_DBCS (1) +#define GCP_ERROR (0x8000) +#define GCP_CLASSIN (0x80000L) +#define GCP_DIACRITIC (256) +#define GCP_DISPLAYZWG (0x400000L) +#define GCP_GLYPHSHAPE (16) +#define GCP_JUSTIFY (0x10000L) +#define GCP_JUSTIFYIN (0x200000L) +#define GCP_KASHIDA (1024) +#define GCP_LIGATE (32) +#define GCP_MAXEXTENT (0x100000L) +#define GCP_NEUTRALOVERRIDE (0x2000000L) +#define GCP_NUMERICOVERRIDE (0x1000000L) +#define GCP_NUMERICSLATIN (0x4000000L) +#define GCP_NUMERICSLOCAL (0x8000000L) +#define GCP_REORDER (2) +#define GCP_SYMSWAPOFF (0x800000L) +#define GCP_USEKERNING (8) +#define FLI_GLYPHS (0x40000L) +#define FLI_MASK (0x103b) + +/* GetClassLong, GetClassWord */ +#define GCW_ATOM (-32) +#define GCL_CBCLSEXTRA (-20) +#define GCL_CBWNDEXTRA (-18) +#define GCL_HBRBACKGROUND (-10) +#define GCL_HCURSOR (-12) +#define GCL_HICON (-14) +#define GCL_HICONSM (-34) +#define GCL_HMODULE (-16) +#define GCL_MENUNAME (-8) +#define GCL_STYLE (-26) +#define GCL_WNDPROC (-24) + +/* GetClipboardFormat, SetClipboardData */ +#define CF_BITMAP (2) +#define CF_DIB (8) +#define CF_PALETTE (9) +#define CF_ENHMETAFILE (14) +#define CF_METAFILEPICT (3) +#define CF_OEMTEXT (7) +#define CF_TEXT (1) +#define CF_UNICODETEXT (13) +#define CF_DIF (5) +#define CF_DSPBITMAP (130) +#define CF_DSPENHMETAFILE (142) +#define CF_DSPMETAFILEPICT (131) +#define CF_DSPTEXT (129) +#define CF_GDIOBJFIRST (768) +#define CF_GDIOBJLAST (1023) +#define CF_HDROP (15) +#define CF_LOCALE (16) +#define CF_OWNERDISPLAY (128) +#define CF_PENDATA (10) +#define CF_PRIVATEFIRST (512) +#define CF_PRIVATELAST (767) +#define CF_RIFF (11) +#define CF_SYLK (4) +#define CF_WAVE (12) +#define CF_TIFF (6) + +/* GetCommMask */ +#define EV_BREAK (64) +#define EV_CTS (8) +#define EV_DSR (16) +#define EV_ERR (128) +#define EV_EVENT1 (2048) +#define EV_EVENT2 (4096) +#define EV_PERR (512) +#define EV_RING (256) +#define EV_RLSD (32) +#define EV_RX80FULL (1024) +#define EV_RXCHAR (1) +#define EV_RXFLAG (2) +#define EV_TXEMPTY (4) + +/* GetCommModemStatus */ +#define MS_CTS_ON (0x10L) +#define MS_DSR_ON (0x20L) +#define MS_RING_ON (0x40L) +#define MS_RLSD_ON (0x80L) + +/* GetComputerName */ +#define MAX_COMPUTERNAME_LENGTH (15) + + +/* GetCPInfo */ +#define CP_ACP (0) +#define CP_MACCP (2) +#define CP_OEMCP (1) +#define CP_THREAD_ACP 3 //ACP Current thread's ANSI code page +#define CP_SYMBOL 42 //Symbol code page (42) +#define CP_UTF7 65000 //Translate using UTF-7 +#define CP_UTF8 65001 //Translate using UTF-8 + +/* GetDateFormat */ +#define DATE_SHORTDATE (1) +#define DATE_LONGDATE (2) +#define DATE_USE_ALT_CALENDAR (4) + +/* GetDCEx */ +#define DCX_WINDOW (0x1L) +#define DCX_CACHE (0x2L) +#define DCX_PARENTCLIP (0x20L) +#define DCX_CLIPSIBLINGS (0x10L) +#define DCX_CLIPCHILDREN (0x8L) +#define DCX_NORESETATTRS (0x4L) +#define DCX_LOCKWINDOWUPDATE (0x400L) +#define DCX_EXCLUDERGN (0x40L) +#define DCX_INTERSECTRGN (0x80L) +#define DCX_VALIDATE (0x200000L) +#define DCX_USESTYLE (0x00010000L) +#define DCX_NORECOMPUTE (0x00100000L) +#define DCX_EXCLUDEUPDATE (0x00000100L) +#define DCX_INTERSECTUPDATE (0x00000200L) + +/* GetDeviceCaps */ +#define DRIVERVERSION (0) +#define TECHNOLOGY (2) +#define DT_PLOTTER (0) +#define DT_RASDISPLAY (1) +#define DT_RASPRINTER (2) +#define DT_RASCAMERA (3) +#define DT_CHARSTREAM (4) +#define DT_METAFILE (5) +#define DT_DISPFILE (6) +#define HORZSIZE (4) +#define VERTSIZE (6) +#define HORZRES (8) +#define VERTRES (10) +#define LOGPIXELSX (88) +#define LOGPIXELSY (90) +#define BITSPIXEL (12) +#define PLANES (14) +#define NUMBRUSHES (16) +#define NUMPENS (18) +#define NUMFONTS (22) +#define NUMCOLORS (24) +#define ASPECTX (40) +#define ASPECTY (42) +#define ASPECTXY (44) +#define PDEVICESIZE (26) +#define CLIPCAPS (36) +#define SIZEPALETTE (104) +#define NUMRESERVED (106) +#define COLORRES (108) +#define PHYSICALWIDTH (110) +#define PHYSICALHEIGHT (111) +#define PHYSICALOFFSETX (112) +#define PHYSICALOFFSETY (113) +#define SCALINGFACTORX (114) +#define SCALINGFACTORY (115) +#define VREFRESH (116) +#define DESKTOPHORZRES (118) +#define DESKTOPVERTRES (117) +#define BLTALIGNMENT (119) +#define RASTERCAPS (38) +#define RC_BANDING (2) +#define RC_BITBLT (1) +#define RC_BITMAP64 (8) +#define RC_DI_BITMAP (128) +#define RC_DIBTODEV (512) +#define RC_FLOODFILL (4096) +#define RC_GDI20_OUTPUT (16) +#define RC_PALETTE (256) +#define RC_SCALING (4) +#define RC_STRETCHBLT (2048) +#define RC_STRETCHDIB (8192) +#define CURVECAPS (28) +#define CC_NONE (0) +#define CC_CIRCLES (1) +#define CC_PIE (2) +#define CC_CHORD (4) +#define CC_ELLIPSES (8) +#define CC_WIDE (16) +#define CC_STYLED (32) +#define CC_WIDESTYLED (64) +#define CC_INTERIORS (128) +#define CC_ROUNDRECT (256) +#define LINECAPS (30) +#define LC_NONE (0) +#define LC_POLYLINE (2) +#define LC_MARKER (4) +#define LC_POLYMARKER (8) +#define LC_WIDE (16) +#define LC_STYLED (32) +#define LC_WIDESTYLED (64) +#define LC_INTERIORS (128) +#define POLYGONALCAPS (32) +#define PC_NONE (0) +#define PC_POLYGON (1) +#define PC_RECTANGLE (2) +#define PC_WINDPOLYGON (4) +#define PC_SCANLINE (8) +#define PC_WIDE (16) +#define PC_STYLED (32) +#define PC_WIDESTYLED (64) +#define PC_INTERIORS (128) +#define TEXTCAPS (34) +#define TC_OP_CHARACTER (1) +#define TC_OP_STROKE (2) +#define TC_CP_STROKE (4) +#define TC_CR_90 (8) +#define TC_CR_ANY (16) +#define TC_SF_X_YINDEP (32) +#define TC_SA_DOUBLE (64) +#define TC_SA_INTEGER (128) +#define TC_SA_CONTIN (256) +#define TC_EA_DOUBLE (512) +#define TC_IA_ABLE (1024) +#define TC_UA_ABLE (2048) +#define TC_SO_ABLE (4096) +#define TC_RA_ABLE (8192) +#define TC_VA_ABLE (16384) +#define TC_RESERVED (32768) +#define TC_SCROLLBLT (65536) +#define PC_PATHS (512) + +/* GetDriveType */ +#define DRIVE_REMOVABLE (2) +#define DRIVE_FIXED (3) +#define DRIVE_REMOTE (4) +#define DRIVE_CDROM (5) +#define DRIVE_RAMDISK (6) +#define DRIVE_UNKNOWN (0) +#define DRIVE_NO_ROOT_DIR (1) + +/* GetExceptionCode */ +#define EXCEPTION_ACCESS_VIOLATION (0xc0000005L) +#define EXCEPTION_BREAKPOINT (0x80000003L) +#define EXCEPTION_DATATYPE_MISALIGNMENT (0x80000002L) +#define EXCEPTION_SINGLE_STEP (0x80000004L) +#define EXCEPTION_ARRAY_BOUNDS_EXCEEDED (0xc000008cL) +#define EXCEPTION_FLT_DENORMAL_OPERAND (0xc000008dL) +#define EXCEPTION_FLT_DIVIDE_BY_ZERO (0xc000008eL) +#define EXCEPTION_FLT_INEXACT_RESULT (0xc000008fL) +#define EXCEPTION_FLT_INVALID_OPERATION (0xc0000090L) +#define EXCEPTION_FLT_OVERFLOW (0xc0000091L) +#define EXCEPTION_FLT_STACK_CHECK (0xc0000092L) +#define EXCEPTION_FLT_UNDERFLOW (0xc0000093L) +#define EXCEPTION_INT_DIVIDE_BY_ZERO (0xc0000094L) +#define EXCEPTION_INT_OVERFLOW (0xc0000095L) +#define EXCEPTION_INVALID_HANDLE (0xc0000008L) +#define EXCEPTION_PRIV_INSTRUCTION (0xc0000096L) +#define EXCEPTION_NONCONTINUABLE_EXCEPTION (0xc0000025L) +#define EXCEPTION_NONCONTINUABLE (0x1) +#define EXCEPTION_STACK_OVERFLOW (0xc00000fdL) +#define EXCEPTION_INVALID_DISPOSITION (0xc0000026L) + +/* GetFileType */ +#define FILE_TYPE_UNKNOWN (0) +#define FILE_TYPE_DISK (1) +#define FILE_TYPE_CHAR (2) +#define FILE_TYPE_PIPE (3) + +/* GetGlyphOutline */ +#define GGO_BITMAP (1) +#define GGO_NATIVE (2) +#define GGO_METRICS (0) +#define GGO_GRAY2_BITMAP (4) +#define GGO_GRAY4_BITMAP (5) +#define GGO_GRAY8_BITMAP (6) +#define GDI_ERROR (0xffffffffL) + +/* GetGraphicsMode */ +#define GM_COMPATIBLE (1) +#define GM_ADVANCED (2) + +/* GetHandleInformation */ +#define HANDLE_FLAG_INHERIT (1) +#define HANDLE_FLAG_PROTECT_FROM_CLOSE (2) + +/* GetIconInfo */ +#define IDC_ARROW (MAKEINTRESOURCE(32512)) +#define IDC_IBEAM (MAKEINTRESOURCE(32513)) +#define IDC_WAIT (MAKEINTRESOURCE(32514)) +#define IDC_CROSS (MAKEINTRESOURCE(32515)) +#define IDC_UPARROW (MAKEINTRESOURCE(32516)) +#define IDC_SIZENWSE (MAKEINTRESOURCE(32642)) +#define IDC_SIZENESW (MAKEINTRESOURCE(32643)) +#define IDC_SIZEWE (MAKEINTRESOURCE(32644)) +#define IDC_SIZENS (MAKEINTRESOURCE(32645)) +#define IDC_SIZEALL (MAKEINTRESOURCE(32646)) +#define IDC_NO (MAKEINTRESOURCE(32648)) +#define IDC_APPSTARTING (MAKEINTRESOURCE(32650)) +#define IDC_HELP (MAKEINTRESOURCE(32651)) +#define IDI_APPLICATION (MAKEINTRESOURCE(32512)) +#define IDI_HAND (MAKEINTRESOURCE(32513)) +#define IDI_QUESTION (MAKEINTRESOURCE(32514)) +#define IDI_EXCLAMATION (MAKEINTRESOURCE(32515)) +#define IDI_ASTERISK (MAKEINTRESOURCE(32516)) +#define IDI_WINLOGO (MAKEINTRESOURCE(32517)) +#define IDC_SIZE (MAKEINTRESOURCE(32640)) +#define IDC_ICON (MAKEINTRESOURCE(32641)) + +/* GetMapMode */ +#define MM_ANISOTROPIC (8) +#define MM_HIENGLISH (5) +#define MM_HIMETRIC (3) +#define MM_ISOTROPIC (7) +#define MM_LOENGLISH (4) +#define MM_LOMETRIC (2) +#define MM_TEXT (1) +#define MM_TWIPS (6) + +/* GetMenuDefaultItem */ +#define GMDI_GOINTOPOPUPS (0x2L) +#define GMDI_USEDISABLED (0x1L) + +/* PeekMessage */ +#define PM_NOREMOVE (0) +#define PM_REMOVE (1) +#define PM_NOYIELD (2) + +/* GetNamedPipeHandleState */ +#define PIPE_NOWAIT (1) +#define PIPE_READMODE_MESSAGE (2) + +/* GetNamedPipeInfo */ +#define PIPE_CLIENT_END (0) +#define PIPE_SERVER_END (1) +#define PIPE_TYPE_MESSAGE (4) + +/* GetNextWindow, GetWindow */ +#define GW_HWNDNEXT (2) +#define GW_HWNDPREV (3) +#define GW_CHILD (5) +#define GW_HWNDFIRST (0) +#define GW_HWNDLAST (1) +#define GW_OWNER (4) + +/* GetPath */ +#define PT_MOVETO (6) +#define PT_LINETO (2) +#define PT_BEZIERTO (4) +#define PT_CLOSEFIGURE (1) + +/* GetProcessShutdownParameters */ +#define SHUTDOWN_NORETRY (1) + +/* GetQueueStatus */ +#define QS_ALLEVENTS (191) +#define QS_ALLINPUT (255) +#define QS_HOTKEY (128) +#define QS_INPUT (7) +#define QS_KEY (1) +#define QS_MOUSE (6) +#define QS_MOUSEBUTTON (4) +#define QS_MOUSEMOVE (2) +#define QS_PAINT (32) +#define QS_POSTMESSAGE (8) +#define QS_SENDMESSAGE (64) +#define QS_TIMER (16) + +/* GetScrollInfo, SetScrollInfo */ +#define SIF_ALL (23) +#define SIF_PAGE (2) +#define SIF_POS (4) +#define SIF_RANGE (1) +#define SIF_DISABLENOSCROLL (8) + +/* GetStdHandle */ +#define STD_INPUT_HANDLE (DWORD)(-10) +#define STD_OUTPUT_HANDLE (DWORD)(-11) +#define STD_ERROR_HANDLE (DWORD)(-12) + +/* GetStockObject */ +#define BLACK_BRUSH (4) +#define DKGRAY_BRUSH (3) +#define GRAY_BRUSH (2) +#define HOLLOW_BRUSH (5) +#define LTGRAY_BRUSH (1) +#define NULL_BRUSH (5) +#define WHITE_BRUSH (0) +#define BLACK_PEN (7) +#define NULL_PEN (8) +#define WHITE_PEN (6) +#define ANSI_FIXED_FONT (11) +#define ANSI_VAR_FONT (12) +#define DEVICE_DEFAULT_FONT (14) +#define DEFAULT_GUI_FONT (17) +#define OEM_FIXED_FONT (10) +#define SYSTEM_FONT (13) +#define SYSTEM_FIXED_FONT (16) +#define DEFAULT_PALETTE (15) + +/* GetStringTypeA */ +#define CT_CTYPE1 (1) +#define CT_CTYPE2 (2) +#define CT_CTYPE3 (4) +#define C1_UPPER (1) +#define C1_LOWER (2) +#define C1_DIGIT (4) +#define C1_SPACE (8) +#define C1_PUNCT (16) +#define C1_CNTRL (32) +#define C1_BLANK (64) +#define C1_XDIGIT (128) +#define C1_ALPHA (256) +#define C2_LEFTTORIGHT (1) +#define C2_RIGHTTOLEFT (2) +#define C2_EUROPENUMBER (3) +#define C2_EUROPESEPARATOR (4) +#define C2_EUROPETERMINATOR (5) +#define C2_ARABICNUMBER (6) +#define C2_COMMONSEPARATOR (7) +#define C2_BLOCKSEPARATOR (8) +#define C2_SEGMENTSEPARATOR (9) +#define C2_WHITESPACE (10) +#define C2_OTHERNEUTRAL (11) +#define C2_NOTAPPLICABLE (0) +#define C3_NONSPACING (1) +#define C3_DIACRITIC (2) +#define C3_VOWELMARK (4) +#define C3_SYMBOL (8) +#define C3_KATAKANA (16) +#define C3_HIRAGANA (32) +#define C3_HALFWIDTH (64) +#define C3_FULLWIDTH (128) +#define C3_IDEOGRAPH (256) +#define C3_KASHIDA (512) +#define C3_ALPHA (32768) +#define C3_NOTAPPLICABLE (0) + +/* GetSysColor */ +#define COLOR_3DDKSHADOW (21) +#define COLOR_3DFACE (15) +#define COLOR_3DHILIGHT (20) +#define COLOR_3DLIGHT (22) +#define COLOR_BTNHILIGHT (20) +#define COLOR_3DSHADOW (16) +#define COLOR_ACTIVEBORDER (10) +#define COLOR_ACTIVECAPTION (2) +#define COLOR_APPWORKSPACE (12) +#define COLOR_BACKGROUND (1) +#define COLOR_DESKTOP (1) +#define COLOR_BTNFACE (15) +#define COLOR_BTNHIGHLIGHT (20) +#define COLOR_BTNSHADOW (16) +#define COLOR_BTNTEXT (18) +#define COLOR_CAPTIONTEXT (9) +#define COLOR_GRAYTEXT (17) +#define COLOR_HIGHLIGHT (13) +#define COLOR_HIGHLIGHTTEXT (14) +#define COLOR_INACTIVEBORDER (11) +#define COLOR_INACTIVECAPTION (3) +#define COLOR_INACTIVECAPTIONTEXT (19) +#define COLOR_INFOBK (24) +#define COLOR_INFOTEXT (23) +#define COLOR_MENU (4) +#define COLOR_MENUTEXT (7) +#define COLOR_SCROLLBAR (0) +#define COLOR_WINDOW (5) +#define COLOR_WINDOWFRAME (6) +#define COLOR_WINDOWTEXT (8) + +/* GetSystemMetrics */ +#define SM_CYMIN (29) +#define SM_CXMIN (28) +#define SM_ARRANGE (56) +#define SM_CLEANBOOT (67) +/* The right value for SM_CEMETRICS for NT 3.5 is 75. For Windows 95 + and NT 4.0, it is 76. The meaning is undocumented, anyhow. */ +#define SM_CMETRICS (76) +#define SM_CMOUSEBUTTONS (43) +#define SM_CXBORDER (5) +#define SM_CYBORDER (6) +#define SM_CXCURSOR (13) +#define SM_CYCURSOR (14) +#define SM_CXDLGFRAME (7) +#define SM_CYDLGFRAME (8) +#define SM_CXDOUBLECLK (36) +#define SM_CYDOUBLECLK (37) +#define SM_CXDRAG (68) +#define SM_CYDRAG (69) +#define SM_CXEDGE (45) +#define SM_CYEDGE (46) +#define SM_CXFIXEDFRAME (7) +#define SM_CYFIXEDFRAME (8) +#define SM_CXFRAME (32) +#define SM_CYFRAME (33) +#define SM_CXFULLSCREEN (16) +#define SM_CYFULLSCREEN (17) +#define SM_CXHSCROLL (21) +#define SM_CYHSCROLL (3) +#define SM_CXHTHUMB (10) +#define SM_CXICON (11) +#define SM_CYICON (12) +#define SM_CXICONSPACING (38) +#define SM_CYICONSPACING (39) +#define SM_CXMAXIMIZED (61) +#define SM_CYMAXIMIZED (62) +#define SM_CXMAXTRACK (59) +#define SM_CYMAXTRACK (60) +#define SM_CXMENUCHECK (71) +#define SM_CYMENUCHECK (72) +#define SM_CXMENUSIZE (54) +#define SM_CYMENUSIZE (55) +#define SM_CXMINIMIZED (57) +#define SM_CYMINIMIZED (58) +#define SM_CXMINSPACING (47) +#define SM_CYMINSPACING (48) +#define SM_CXMINTRACK (34) +#define SM_CYMINTRACK (35) +#define SM_CXSCREEN (0) +#define SM_CYSCREEN (1) +#define SM_CXSIZE (30) +#define SM_CYSIZE (31) +#define SM_CXSIZEFRAME (32) +#define SM_CYSIZEFRAME (33) +#define SM_CXSMICON (49) +#define SM_CYSMICON (50) +#define SM_CXSMSIZE (52) +#define SM_CYSMSIZE (53) +#define SM_CXVSCROLL (2) +#define SM_CYHSCROLL (3) +#define SM_CXHSCROLL (21) +#define SM_CYVSCROLL (20) +#define SM_CYVTHUMB (9) +#define SM_CYCAPTION (4) +#define SM_CYKANJIWINDOW (18) +#define SM_CYMENU (15) +#define SM_CYSMCAPTION (51) +#define SM_DBCSENABLED (42) +#define SM_DEBUG (22) +#define SM_MENUDROPALIGNMENT (40) +#define SM_MIDEASTENABLED (74) +#define SM_MOUSEPRESENT (19) +#define SM_MOUSEWHEELPRESENT (75) +#define SM_NETWORK (63) +#define SM_PENWINDOWS (41) +#define SM_SECURE (44) +#define SM_SHOWSOUNDS (70) +#define SM_SLOWMACHINE (73) +#define SM_SWAPBUTTON (23) +#define ARW_BOTTOMLEFT (0L) +#define ARW_BOTTOMRIGHT (0x1L) +#define ARW_HIDE (0x8L) +#define ARW_TOPLEFT (0x2L) +#define ARW_TOPRIGHT (0x3L) +#define ARW_DOWN (0x4L) +#define ARW_LEFT (0L) +#define ARW_RIGHT (0L) +#define ARW_UP (0x4L) + +/* GetSystemPaletteUse */ +#define SYSPAL_NOSTATIC (2) +#define SYSPAL_STATIC (1) +#define SYSPAL_ERROR (0) + +/* GetTapeParameters, SetTapeParameters */ +#define GET_TAPE_MEDIA_INFORMATION (0) +#define GET_TAPE_DRIVE_INFORMATION (1) +#define SET_TAPE_MEDIA_INFORMATION (0) +#define SET_TAPE_DRIVE_INFORMATION (1) + +/* GetTapePosition */ +#define TAPE_ABSOLUTE_POSITION (0L) +#define TAPE_LOGICAL_POSITION (0x1L) + +/* GetTextAlign */ +#define TA_BASELINE (24) +#define TA_BOTTOM (8) +#define TA_TOP (0) +#define TA_CENTER (6) +#define TA_LEFT (0) +#define TA_RIGHT (2) +#define TA_RTLREADING (256) +#define TA_NOUPDATECP (0) +#define TA_UPDATECP (1) +#define VTA_BASELINE (24) +#define VTA_CENTER (6) + +/* GetThreadPriority */ +#define TLS_MINIMUM_AVAILABLE (64) + +/* GetTimeFormat */ +#define TIME_NOMINUTESORSECONDS (1) +#define TIME_NOSECONDS (2) +#define TIME_NOTIMEMARKER (4) +#define TIME_FORCE24HOURFORMAT (8) + +/* GetTimeZoneInformation */ +#define TIME_ZONE_ID_INVALID ((DWORD) -1) +#define TIME_ZONE_ID_UNKNOWN (0) +#define TIME_ZONE_ID_STANDARD (1) +#define TIME_ZONE_ID_DAYLIGHT (2) + +/* GetUserObjectInformation */ +#define UOI_FLAGS (1) +#define UOI_NAME (2) +#define UOI_TYPE (3) + +/* GetWindowLong */ +#define GWL_EXSTYLE (-20) +#define GWL_STYLE (-16) +#define GWL_WNDPROC (-4) +#define GWL_HINSTANCE (-6) +#define GWL_HWNDPARENT (-8) +#define GWL_ID (-12) +#define GWL_USERDATA (-21) +#define DWL_DLGPROC (4) +#define DWL_MSGRESULT (0) +#define DWL_USER (8) + +/* GlobalAlloc, GlobalFlags */ +#define GMEM_FIXED (0) +#define GMEM_MOVEABLE (2) +#define GPTR (64) +#define GHND (66) +#define GMEM_DDESHARE (8192) +#define GMEM_DISCARDABLE (256) +#define GMEM_LOWER (4096) +#define GMEM_NOCOMPACT (16) +#define GMEM_NODISCARD (32) +#define GMEM_NOT_BANKED (4096) +#define GMEM_NOTIFY (16384) +#define GMEM_SHARE (8192) +#define GMEM_ZEROINIT (64) +#define GMEM_DISCARDED (16384) +#define GMEM_INVALID_HANDLE (32768) +#define GMEM_LOCKCOUNT (255) + +/* ImageList_Create */ +#define ILC_COLOR (0) +#define ILC_COLOR4 (4) +#define ILC_COLOR8 (8) +#define ILC_COLOR16 (16) +#define ILC_COLOR24 (24) +#define ILC_COLOR32 (32) +#define ILC_COLORDDB (254) +#define ILC_MASK (1) +#define ILC_PALETTE (2048) + +/* ImageList_Draw, ImageList_DrawEx */ +#define ILD_BLEND25 (2) +#define ILD_BLEND50 (4) +#define ILD_SELECTED (4) +#define ILD_BLEND (4) +#define ILD_FOCUS (2) +#define ILD_MASK (16) +#define ILD_NORMAL (0) +#define ILD_TRANSPARENT (1) +#define CLR_NONE (0xffffffffL) +#define CLR_DEFAULT (0xff000000L) + +/* ImageList_LoadImage */ +#define LR_DEFAULTCOLOR (0) +#define LR_LOADFROMFILE (16) +#define LR_LOADMAP3DCOLORS (4096) +#define LR_LOADTRANSPARENT (32) +#define LR_MONOCHROME (1) + +/* ImmConfigureIME */ +#define IME_CONFIG_GENERAL (1) +#define IME_CONFIG_REGISTERWORD (2) +#define IME_CONFIG_SELECTDICTIONARY (3) + +/* ImmGetConversionList */ +#define GCL_CONVERSION (1) +#define GCL_REVERSECONVERSION (2) +#define GCL_REVERSE_LENGTH (3) + +/* ImmGetGuideLine */ +#define GGL_LEVEL (1) +#define GGL_INDEX (2) +#define GGL_STRING (3) +#define GGL_PRIVATE (4) +#define GL_LEVEL_ERROR (2) +#define GL_LEVEL_FATAL (1) +#define GL_LEVEL_INFORMATION (4) +#define GL_LEVEL_NOGUIDELINE (0) +#define GL_LEVEL_WARNING (3) +#define GL_ID_CANNOTSAVE (17) +#define GL_ID_NOCONVERT (32) +#define GL_ID_NODICTIONARY (16) +#define GL_ID_NOMODULE (1) +#define GL_ID_READINGCONFLICT (35) +#define GL_ID_TOOMANYSTROKE (34) +#define GL_ID_TYPINGERROR (33) +#define GL_ID_UNKNOWN (0) +#define GL_ID_INPUTREADING (36) +#define GL_ID_INPUTRADICAL (37) +#define GL_ID_INPUTCODE (38) +#define GL_ID_CHOOSECANDIDATE (40) +#define GL_ID_REVERSECONVERSION (41) + +/* ImmGetProperty */ +#define IGP_PROPERTY (4) +#define IGP_CONVERSION (8) +#define IGP_SENTENCE (12) +#define IGP_UI (16) +#define IGP_SETCOMPSTR (20) +#define IGP_SELECT (24) +#define IME_PROP_AT_CARET (65536) +#define IME_PROP_SPECIAL_UI (131072) +#define IME_PROP_CANDLIST_START_FROM_1 (262144) +#define IME_PROP_UNICODE (524288) +#define UI_CAP_2700 (1) +#define UI_CAP_ROT90 (2) +#define UI_CAP_ROTANY (4) +#define SCS_CAP_COMPSTR (1) +#define SCS_CAP_MAKEREAD (2) +#define SELECT_CAP_CONVERSION (1) +#define SELECT_CAP_SENTENCE (2) + +/* ImmNotifyIME */ +#define NI_CHANGECANDIDATELIST (19) +#define NI_CLOSECANDIDATE (17) +#define NI_COMPOSITIONSTR (21) +#define NI_OPENCANDIDATE (16) +#define NI_SELECTCANDIDATESTR (18) +#define NI_SETCANDIDATE_PAGESIZE (23) +#define NI_SETCANDIDATE_PAGESTART (22) +#define CPS_CANCEL (4) +#define CPS_COMPLETE (1) +#define CPS_CONVERT (2) +#define CPS_REVERT (3) + +/* ImmSetCompositionString */ +#define SCS_SETSTR (9) +#define SCS_CHANGEATTR (18) +#define SCS_CHANGECLAUSE (36) + +/* ImmUnregisterWord */ +#define IME_REGWORD_STYLE_EUDC (1) +#define IME_REGWORD_STYLE_USER_FIRST 0x80000000 +#define IME_REGWORD_STYLE_USER_LAST (-1) + +/* InitializeSecurityDescriptor */ +#define SECURITY_DESCRIPTOR_REVISION (1) + +/* IsTextUnicode */ +#define IS_TEXT_UNICODE_ASCII16 (1) +#define IS_TEXT_UNICODE_REVERSE_ASCII16 (16) +#define IS_TEXT_UNICODE_STATISTICS (2) +#define IS_TEXT_UNICODE_REVERSE_STATISTICS (32) +#define IS_TEXT_UNICODE_CONTROLS (4) +#define IS_TEXT_UNICODE_REVERSE_CONTROLS (64) +#define IS_TEXT_UNICODE_SIGNATURE (8) +#define IS_TEXT_UNICODE_REVERSE_SIGNATURE (128) +#define IS_TEXT_UNICODE_ILLEGAL_CHARS (256) +#define IS_TEXT_UNICODE_ODD_LENGTH (512) +#define IS_TEXT_UNICODE_NULL_BYTES (4096) +#define IS_TEXT_UNICODE_UNICODE_MASK (15) +#define IS_TEXT_UNICODE_REVERSE_MASK (240) +#define IS_TEXT_UNICODE_NOT_UNICODE_MASK (3840) +#define IS_TEXT_UNICODE_NOT_ASCII_MASK (61440) + +/* JournalPlaybackProc, KeyboardProc */ +#define HC_GETNEXT (1) +#define HC_SKIP (2) +#define HC_SYSMODALOFF (5) +#define HC_SYSMODALON (4) +#define HC_NOREMOVE (3) + +/* keybd_event */ +#define KEYEVENTF_EXTENDEDKEY (1) +#define KEYEVENTF_KEYUP (2) + +/* LoadBitmap */ +#define OBM_BTNCORNERS (32758) +#define OBM_BTSIZE (32761) +#define OBM_CHECK (32760) +#define OBM_CHECKBOXES (32759) +#define OBM_CLOSE (32754) +#define OBM_COMBO (32738) +#define OBM_DNARROW (32752) +#define OBM_DNARROWD (32742) +#define OBM_DNARROWI (32736) +#define OBM_LFARROW (32750) +#define OBM_LFARROWI (32734) +#define OBM_LFARROWD (32740) +#define OBM_MNARROW (32739) +#define OBM_OLD_CLOSE (32767) +#define OBM_OLD_DNARROW (32764) +#define OBM_OLD_LFARROW (32762) +#define OBM_OLD_REDUCE (32757) +#define OBM_OLD_RESTORE (32755) +#define OBM_OLD_RGARROW (32763) +#define OBM_OLD_UPARROW (32765) +#define OBM_OLD_ZOOM (32756) +#define OBM_REDUCE (32749) +#define OBM_REDUCED (32746) +#define OBM_RESTORE (32747) +#define OBM_RESTORED (32744) +#define OBM_RGARROW (32751) +#define OBM_RGARROWD (32741) +#define OBM_RGARROWI (32735) +#define OBM_SIZE (32766) +#define OBM_UPARROW (32753) +#define OBM_UPARROWD (32743) +#define OBM_UPARROWI (32737) +#define OBM_ZOOM (32748) +#define OBM_ZOOMD (32745) + +/* LoadLibraryEx */ +#define DONT_RESOLVE_DLL_REFERENCES (1) +#define LOAD_LIBRARY_AS_DATAFILE (2) +#define LOAD_WITH_ALTERED_SEARCH_PATH (8) + +/* LocalAlloc, LocalFlags */ +#define LPTR (64) +#define LHND (66) +#define NONZEROLHND (2) +#define NONZEROLPTR (0) +#define LMEM_NONZEROLHND (2) +#define LMEM_NONZEROLPTR (0) +#define LMEM_FIXED (0) +#define LMEM_MOVEABLE (2) +#define LMEM_NOCOMPACT (16) +#define LMEM_NODISCARD (32) +#define LMEM_ZEROINIT (64) +#define LMEM_MODIFY (128) +#define LMEM_LOCKCOUNT (255) +#define LMEM_DISCARDABLE (3840) +#define LMEM_DISCARDED (16384) +#define LMEM_INVALID_HANDLE (32768) + +/* LockFileEx */ +#define LOCKFILE_FAIL_IMMEDIATELY (1) +#define LOCKFILE_EXCLUSIVE_LOCK (2) + +/* LogonUser */ + +/* LZCopy, LZInit, LZRead */ + +/* MessageBeep, MessageBox */ +#define MB_USERICON (0x80L) +#define MB_ICONASTERISK (0x40L) +#define MB_ICONEXCLAMATION (0x30L) +#define MB_ICONWARNING (0x30L) +#define MB_ICONERROR (0x10L) +#define MB_ICONHAND (0x10L) +#define MB_ICONQUESTION (0x20L) +#define MB_OK (0L) +#define MB_ABORTRETRYIGNORE (0x2L) +#define MB_APPLMODAL (0L) +#define MB_DEFAULT_DESKTOP_ONLY (0x20000L) +#define MB_HELP (0x4000L) +#define MB_RIGHT (0x80000L) +#define MB_RTLREADING (0x100000L) +#define MB_TOPMOST (0x40000L) +#define MB_DEFBUTTON1 (0L) +#define MB_DEFBUTTON2 (0x100L) +#define MB_DEFBUTTON3 (0x200L) +#define MB_DEFBUTTON4 (0x300L) +#define MB_ICONINFORMATION (0x40L) +#define MB_ICONSTOP (0x10L) +#define MB_OKCANCEL (0x1L) +#define MB_RETRYCANCEL (0x5L) +#define MB_SERVICE_NOTIFICATION (0x40000L) +#define MB_SETFOREGROUND (0x10000L) +#define MB_SYSTEMMODAL (0x1000L) +#define MB_TASKMODAL (0x2000L) +#define MB_YESNO (0x4L) +#define MB_YESNOCANCEL (0x3L) +#define IDABORT (3) +#define IDCANCEL (2) +#define IDCLOSE (8) +#define IDHELP (9) +#define IDIGNORE (5) +#define IDNO (7) +#define IDOK (1) +#define IDRETRY (4) +#define IDYES (6) + +/* MessageProc */ +#define MSGF_DIALOGBOX (0) +#define MSGF_MENU (2) +#define MSGF_NEXTWINDOW (6) +#define MSGF_SCROLLBAR (5) +#define MSGF_MAINLOOP (8) +#define MSGF_USER (4096) + +/* ModifyWorldTransform */ +#define MWT_IDENTITY (1) +#define MWT_LEFTMULTIPLY (2) +#define MWT_RIGHTMULTIPLY (3) + +/* mouse_event */ +#define MOUSEEVENTF_ABSOLUTE (32768) +#define MOUSEEVENTF_MOVE (1) +#define MOUSEEVENTF_LEFTDOWN (2) +#define MOUSEEVENTF_LEFTUP (4) +#define MOUSEEVENTF_RIGHTDOWN (8) +#define MOUSEEVENTF_RIGHTUP (16) +#define MOUSEEVENTF_MIDDLEDOWN (32) +#define MOUSEEVENTF_MIDDLEUP (64) + +/* MoveFileEx */ +#define MOVEFILE_REPLACE_EXISTING (1) +#define MOVEFILE_COPY_ALLOWED (2) +#define MOVEFILE_DELAY_UNTIL_REBOOT (4) + +/* MsgWaitForMultipleObjects, WaitForMultipleObjectsEx */ +#define WAIT_OBJECT_0 (0L) +#define WAIT_ABANDONED_0 (0x80L) +#define WAIT_TIMEOUT (0x102L) +#define WAIT_IO_COMPLETION (0xc0L) +#define WAIT_ABANDONED (0x80L) +#define WAIT_FAILED (0xffffffffL) +#define MAXIMUM_WAIT_OBJECTS (0x40) +#define MAXIMUM_SUSPEND_COUNT (0x7f) + +/* MultiByteToWideChar */ +#define MB_PRECOMPOSED (1) +#define MB_COMPOSITE (2) +#define MB_ERR_INVALID_CHARS (8) +#define MB_USEGLYPHCHARS (4) + +/* NDdeSetTrustedShare */ + +/* NetAccessCheck */ + +/* NetServerEnum */ + +/* NetServiceControl */ + +/* NetUserEnum */ + +/* OpenProcessToken */ + +/* OpenSCManager */ +#define SC_MANAGER_ALL_ACCESS (0xf003fL) +#define SC_MANAGER_CONNECT (1) +#define SC_MANAGER_CREATE_SERVICE (2) +#define SC_MANAGER_ENUMERATE_SERVICE (4) +#define SC_MANAGER_LOCK (8) +#define SC_MANAGER_QUERY_LOCK_STATUS (16) +#define SC_MANAGER_MODIFY_BOOT_CONFIG (32) + +/* PostMessage */ +#define HWND_BROADCAST ((HWND)0xFFFF) + +/* PrepareTape */ +#define TAPE_FORMAT (0x5L) +#define TAPE_LOAD (0L) +#define TAPE_LOCK (0x3L) +#define TAPE_TENSION (0x2L) +#define TAPE_UNLOAD (0x1L) +#define TAPE_UNLOCK (0x4L) + +/* PropertySheet */ +#define IS_PSREBOOTSYSTEM (3) +#define IS_PSRESTARTWINDOWS (2) + +/* PropSheetPageProc */ +#define PSPCB_CREATE (2) +#define PSPCB_RELEASE (1) + +/* PurgeComm */ +#define PURGE_TXABORT (1) +#define PURGE_RXABORT (2) +#define PURGE_TXCLEAR (4) +#define PURGE_RXCLEAR (8) + +/* QueryServiceObjectSecurity */ +#define OWNER_SECURITY_INFORMATION (0x1L) +#define GROUP_SECURITY_INFORMATION (0x2L) +#define DACL_SECURITY_INFORMATION (0x4L) +#define SACL_SECURITY_INFORMATION (0x8L) + +/* ReadEventLog, ReportEvent */ +#define EVENTLOG_FORWARDS_READ (4) +#define EVENTLOG_BACKWARDS_READ (8) +#define EVENTLOG_SEEK_READ (2) +#define EVENTLOG_SEQUENTIAL_READ (1) +#define EVENTLOG_ERROR_TYPE (1) +#define EVENTLOG_WARNING_TYPE (2) +#define EVENTLOG_INFORMATION_TYPE (4) +#define EVENTLOG_AUDIT_SUCCESS (8) +#define EVENTLOG_AUDIT_FAILURE (16) + +/* RedrawWindow */ +#define RDW_ERASE (4) +#define RDW_FRAME (1024) +#define RDW_INTERNALPAINT (2) +#define RDW_INVALIDATE (1) +#define RDW_NOERASE (32) +#define RDW_NOFRAME (2048) +#define RDW_NOINTERNALPAINT (16) +#define RDW_VALIDATE (8) +#define RDW_ERASENOW (512) +#define RDW_UPDATENOW (256) +#define RDW_ALLCHILDREN (128) +#define RDW_NOCHILDREN (64) + +/* RegCreateKey */ +#define HKEY_CLASSES_ROOT ((HKEY)0x80000000) +#define HKEY_CURRENT_USER ((HKEY)0x80000001) +#define HKEY_LOCAL_MACHINE ((HKEY)0x80000002) +#define HKEY_USERS ((HKEY)0x80000003) +#define HKEY_PERFORMANCE_DATA ((HKEY)0x80000004) +#define HKEY_CURRENT_CONFIG ((HKEY)0x80000005) +#define HKEY_DYN_DATA ((HKEY)0x00000006) + +/* RegCreateKeyEx */ + +/* RegEnumValue */ + +/* RegisterHotKey */ +#define MOD_ALT (1) +#define MOD_CONTROL (2) +#define MOD_SHIFT (4) +#define MOD_WIN (8) +#define IDHOT_SNAPDESKTOP (-2) +#define IDHOT_SNAPWINDOW (-1) + +/* RegNotifyChangeKeyValue */ +#define REG_NOTIFY_CHANGE_NAME (0x1L) +#define REG_NOTIFY_CHANGE_ATTRIBUTES (0x2L) +#define REG_NOTIFY_CHANGE_LAST_SET (0x4L) +#define REG_NOTIFY_CHANGE_SECURITY (0x8L) + +/* ScrollWindowEx */ +#define SW_ERASE (4) +#define SW_INVALIDATE (2) +#define SW_SCROLLCHILDREN (1) + +/* SendMessageTimeout */ +#define SMTO_ABORTIFHUNG (2) +#define SMTO_BLOCK (1) +#define SMTO_NORMAL (0) + +/* SetBkMode */ +#define OPAQUE (2) +#define TRANSPARENT (1) + +/* SetDebugErrorLevel */ +#define SLE_ERROR (1) +#define SLE_MINORERROR (2) +#define SLE_WARNING (3) + +/* SetErrorMode */ +#define SEM_FAILCRITICALERRORS (1) +#define SEM_NOALIGNMENTFAULTEXCEPT (4) +#define SEM_NOGPFAULTERRORBOX (2) +#define SEM_NOOPENFILEERRORBOX (32768) + +/* SetICMMode */ +#define ICM_ON (2) +#define ICM_OFF (1) +#define ICM_QUERY (3) + +/* SetJob */ + +/* Locale Information */ +#define LOCALE_ILANGUAGE (1) +#define LOCALE_SLANGUAGE (2) +#define LOCALE_SENGLANGUAGE (4097) +#define LOCALE_SABBREVLANGNAME (3) +#define LOCALE_SNATIVELANGNAME (4) +#define LOCALE_ICOUNTRY (5) +#define LOCALE_SCOUNTRY (6) +#define LOCALE_SENGCOUNTRY (4098) +#define LOCALE_SABBREVCTRYNAME (7) +#define LOCALE_SNATIVECTRYNAME (8) +#define LOCALE_IDEFAULTLANGUAGE (9) +#define LOCALE_IDEFAULTCOUNTRY (10) +#define LOCALE_IDEFAULTANSICODEPAGE (4100) +#define LOCALE_IDEFAULTCODEPAGE (11) +#define LOCALE_SLIST (12) +#define LOCALE_IMEASURE (13) +#define LOCALE_SDECIMAL (14) +#define LOCALE_STHOUSAND (15) +#define LOCALE_SGROUPING (16) +#define LOCALE_IDIGITS (17) +#define LOCALE_ILZERO (18) +#define LOCALE_INEGNUMBER (4112) +#define LOCALE_SCURRENCY (20) +#define LOCALE_SMONDECIMALSEP (22) +#define LOCALE_SMONTHOUSANDSEP (23) +#define LOCALE_SMONGROUPING (24) +#define LOCALE_ICURRDIGITS (25) +#define LOCALE_ICURRENCY (27) +#define LOCALE_INEGCURR (28) +#define LOCALE_SDATE (29) +#define LOCALE_STIME (30) +#define LOCALE_STIMEFORMAT (4099) +#define LOCALE_SSHORTDATE (31) +#define LOCALE_SLONGDATE (32) +#define LOCALE_IDATE (33) +#define LOCALE_ILDATE (34) +#define LOCALE_ITIME (35) +#define LOCALE_ITLZERO (37) +#define LOCALE_IDAYLZERO (38) +#define LOCALE_IMONLZERO (39) +#define LOCALE_S1159 (40) +#define LOCALE_S2359 (41) +#define LOCALE_ICALENDARTYPE (4105) +#define LOCALE_IOPTIONALCALENDAR (4107) +#define LOCALE_IFIRSTDAYOFWEEK (4108) +#define LOCALE_IFIRSTWEEKOFYEAR (4109) +#define LOCALE_SDAYNAME1 (42) +#define LOCALE_SDAYNAME2 (43) +#define LOCALE_SDAYNAME3 (44) +#define LOCALE_SDAYNAME4 (45) +#define LOCALE_SDAYNAME5 (46) +#define LOCALE_SDAYNAME6 (47) +#define LOCALE_SDAYNAME7 (48) +#define LOCALE_SABBREVDAYNAME1 (49) +#define LOCALE_SABBREVDAYNAME2 (50) +#define LOCALE_SABBREVDAYNAME3 (51) +#define LOCALE_SABBREVDAYNAME4 (52) +#define LOCALE_SABBREVDAYNAME5 (53) +#define LOCALE_SABBREVDAYNAME6 (54) +#define LOCALE_SABBREVDAYNAME7 (55) +#define LOCALE_SMONTHNAME1 (56) +#define LOCALE_SMONTHNAME2 (57) +#define LOCALE_SMONTHNAME3 (58) +#define LOCALE_SMONTHNAME4 (59) +#define LOCALE_SMONTHNAME5 (60) +#define LOCALE_SMONTHNAME6 (61) +#define LOCALE_SMONTHNAME7 (62) +#define LOCALE_SMONTHNAME8 (63) +#define LOCALE_SMONTHNAME9 (64) +#define LOCALE_SMONTHNAME10 (65) +#define LOCALE_SMONTHNAME11 (66) +#define LOCALE_SMONTHNAME12 (67) +#define LOCALE_SMONTHNAME13 (4110) +#define LOCALE_SABBREVMONTHNAME1 (68) +#define LOCALE_SABBREVMONTHNAME2 (69) +#define LOCALE_SABBREVMONTHNAME3 (70) +#define LOCALE_SABBREVMONTHNAME4 (71) +#define LOCALE_SABBREVMONTHNAME5 (72) +#define LOCALE_SABBREVMONTHNAME6 (73) +#define LOCALE_SABBREVMONTHNAME7 (74) +#define LOCALE_SABBREVMONTHNAME8 (75) +#define LOCALE_SABBREVMONTHNAME9 (76) +#define LOCALE_SABBREVMONTHNAME10 (77) +#define LOCALE_SABBREVMONTHNAME11 (78) +#define LOCALE_SABBREVMONTHNAME12 (79) +#define LOCALE_SABBREVMONTHNAME13 (4111) +#define LOCALE_SPOSITIVESIGN (80) +#define LOCALE_SNEGATIVESIGN (81) +#define LOCALE_IPOSSIGNPOSN (82) +#define LOCALE_INEGSIGNPOSN (83) +#define LOCALE_IPOSSYMPRECEDES (84) +#define LOCALE_IPOSSEPBYSPACE (85) +#define LOCALE_INEGSYMPRECEDES (86) +#define LOCALE_INEGSEPBYSPACE (87) +#define LOCALE_NOUSEROVERRIDE (0x80000000) + +/* Calendar Type Information */ +#define CAL_ICALINTVALUE (1) +#define CAL_IYEAROFFSETRANGE (3) +#define CAL_SABBREVDAYNAME1 (14) +#define CAL_SABBREVDAYNAME2 (15) +#define CAL_SABBREVDAYNAME3 (16) +#define CAL_SABBREVDAYNAME4 (17) +#define CAL_SABBREVDAYNAME5 (18) +#define CAL_SABBREVDAYNAME6 (19) +#define CAL_SABBREVDAYNAME7 (20) +#define CAL_SABBREVMONTHNAME1 (34) +#define CAL_SABBREVMONTHNAME2 (35) +#define CAL_SABBREVMONTHNAME3 (36) +#define CAL_SABBREVMONTHNAME4 (37) +#define CAL_SABBREVMONTHNAME5 (38) +#define CAL_SABBREVMONTHNAME6 (39) +#define CAL_SABBREVMONTHNAME7 (40) +#define CAL_SABBREVMONTHNAME8 (41) +#define CAL_SABBREVMONTHNAME9 (42) +#define CAL_SABBREVMONTHNAME10 (43) +#define CAL_SABBREVMONTHNAME11 (44) +#define CAL_SABBREVMONTHNAME12 (45) +#define CAL_SABBREVMONTHNAME13 (46) +#define CAL_SCALNAME (2) +#define CAL_SDAYNAME1 (7) +#define CAL_SDAYNAME2 (8) +#define CAL_SDAYNAME3 (9) +#define CAL_SDAYNAME4 (10) +#define CAL_SDAYNAME5 (11) +#define CAL_SDAYNAME6 (12) +#define CAL_SDAYNAME7 (13) +#define CAL_SERASTRING (4) +#define CAL_SLONGDATE (6) +#define CAL_SMONTHNAME1 (21) +#define CAL_SMONTHNAME2 (22) +#define CAL_SMONTHNAME3 (23) +#define CAL_SMONTHNAME4 (24) +#define CAL_SMONTHNAME5 (25) +#define CAL_SMONTHNAME6 (26) +#define CAL_SMONTHNAME7 (27) +#define CAL_SMONTHNAME8 (28) +#define CAL_SMONTHNAME9 (29) +#define CAL_SMONTHNAME10 (30) +#define CAL_SMONTHNAME11 (31) +#define CAL_SMONTHNAME12 (32) +#define CAL_SMONTHNAME13 (33) +#define CAL_SSHORTDATE (5) + +/* SetProcessWorkingSetSize */ + +/* SetPrinter */ + +/* SetService */ + +/* SetStretchBltMode */ +#define BLACKONWHITE (1) +#define COLORONCOLOR (3) +#define HALFTONE (4) +#define STRETCH_ANDSCANS (1) +#define STRETCH_DELETESCANS (3) +#define STRETCH_HALFTONE (4) +#define STRETCH_ORSCANS (2) +#define WHITEONBLACK (2) + +/* SetSystemCursor */ +#define OCR_NORMAL (32512) +#define OCR_IBEAM (32513) +#define OCR_WAIT (32514) +#define OCR_CROSS (32515) +#define OCR_UP (32516) +#define OCR_SIZE (32640) +#define OCR_ICON (32641) +#define OCR_SIZENWSE (32642) +#define OCR_SIZENESW (32643) +#define OCR_SIZEWE (32644) +#define OCR_SIZENS (32645) +#define OCR_SIZEALL (32646) +#define OCR_NO (32648) +#define OCR_APPSTARTING (32650) + +/* SetTapePosition */ +#define TAPE_ABSOLUTE_BLOCK (0x1L) +#define TAPE_LOGICAL_BLOCK (0x2L) +#define TAPE_REWIND (0L) +#define TAPE_SPACE_END_OF_DATA (0x4L) +#define TAPE_SPACE_FILEMARKS (0x6L) +#define TAPE_SPACE_RELATIVE_BLOCKS (0x5L) +#define TAPE_SPACE_SEQUENTIAL_FMKS (0x7L) +#define TAPE_SPACE_SEQUENTIAL_SMKS (0x9L) +#define TAPE_SPACE_SETMARKS (0x8L) + +/* SetUnhandledExceptionFilter */ +#define EXCEPTION_EXECUTE_HANDLER (1) +#define EXCEPTION_CONTINUE_EXECUTION (-1) +#define EXCEPTION_CONTINUE_SEARCH (0) + +/* SetWindowPos, DeferWindowPos */ +#define HWND_BOTTOM ((HWND)1) +#define HWND_NOTOPMOST ((HWND)-2) +#define HWND_TOP ((HWND)0) +#define HWND_TOPMOST ((HWND)-1) +#define SWP_DRAWFRAME (32) +#define SWP_FRAMECHANGED (32) +#define SWP_HIDEWINDOW (128) +#define SWP_NOACTIVATE (16) +#define SWP_NOCOPYBITS (256) +#define SWP_NOMOVE (2) +#define SWP_NOSIZE (1) +#define SWP_NOREDRAW (8) +#define SWP_NOZORDER (4) +#define SWP_SHOWWINDOW (64) +#define SWP_NOOWNERZORDER (512) +#define SWP_NOREPOSITION (512) +#define SWP_NOSENDCHANGING (1024) + +/* SHAddToRecentDocs */ + +/* SHAppBarMessage */ + +/* SHChangeNotify */ + +/* ShellProc */ +#define HSHELL_ACTIVATESHELLWINDOW (3) +#define HSHELL_GETMINRECT (5) +#define HSHELL_LANGUAGE (8) +#define HSHELL_REDRAW (6) +#define HSHELL_TASKMAN (7) +#define HSHELL_WINDOWACTIVATED (4) +#define HSHELL_WINDOWCREATED (1) +#define HSHELL_WINDOWDESTROYED (2) + +/* SHGetFileInfo */ + +/* SHGetSpecialFolderLocation */ + +/* ShowWindow */ +#define SW_HIDE (0) +#define SW_MAXIMIZE (3) +#define SW_MINIMIZE (6) +#define SW_NORMAL (1) +#define SW_RESTORE (9) +#define SW_SHOW (5) +#define SW_SHOWDEFAULT (10) +#define SW_SHOWMAXIMIZED (3) +#define SW_SHOWMINIMIZED (2) +#define SW_SHOWMINNOACTIVE (7) +#define SW_SHOWNA (8) +#define SW_SHOWNOACTIVATE (4) +#define SW_SHOWNORMAL (1) +#define WPF_RESTORETOMAXIMIZED (2) +#define WPF_SETMINPOSITION (1) + +/* Sleep */ +#define INFINITE 0xFFFFFFFF + +/* SystemParametersInfo */ +#define SPI_GETACCESSTIMEOUT (60) +#define SPI_GETANIMATION (72) +#define SPI_GETBEEP (1) +#define SPI_GETBORDER (5) +#define SPI_GETDEFAULTINPUTLANG (89) +#define SPI_GETDRAGFULLWINDOWS (38) +#define SPI_GETFASTTASKSWITCH (35) +#define SPI_GETFILTERKEYS (50) +#define SPI_GETFONTSMOOTHING (74) +#define SPI_GETGRIDGRANULARITY (18) +#define SPI_GETHIGHCONTRAST (66) +#define SPI_GETICONMETRICS (45) +#define SPI_GETICONTITLELOGFONT (31) +#define SPI_GETICONTITLEWRAP (25) +#define SPI_GETKEYBOARDDELAY (22) +#define SPI_GETKEYBOARDPREF (68) +#define SPI_GETKEYBOARDSPEED (10) +#define SPI_GETLOWPOWERACTIVE (83) +#define SPI_GETLOWPOWERTIMEOUT (79) +#define SPI_GETMENUDROPALIGNMENT (27) +#define SPI_GETMINIMIZEDMETRICS (43) +#define SPI_GETMOUSE (3) +#define SPI_GETMOUSEKEYS (54) +#define SPI_GETMOUSETRAILS (94) +#define SPI_GETNONCLIENTMETRICS (41) +#define SPI_GETPOWEROFFACTIVE (84) +#define SPI_GETPOWEROFFTIMEOUT (80) +#define SPI_GETSCREENREADER (70) +#define SPI_GETSCREENSAVEACTIVE (16) +#define SPI_GETSCREENSAVETIMEOUT (14) +#define SPI_GETSERIALKEYS (62) +#define SPI_GETSHOWSOUNDS (56) +#define SPI_GETSOUNDSENTRY (64) +#define SPI_GETSTICKYKEYS (58) +#define SPI_GETTOGGLEKEYS (52) +#define SPI_GETWINDOWSEXTENSION (92) +#define SPI_GETWORKAREA (48) +#define SPI_ICONHORIZONTALSPACING (13) +#define SPI_ICONVERTICALSPACING (24) +#define SPI_LANGDRIVER (12) +#define SPI_SCREENSAVERRUNNING (97) +#define SPI_SETACCESSTIMEOUT (61) +#define SPI_SETANIMATION (73) +#define SPI_SETBEEP (2) +#define SPI_SETBORDER (6) +#define SPI_SETDEFAULTINPUTLANG (90) +#define SPI_SETDESKPATTERN (21) +#define SPI_SETDESKWALLPAPER (20) +#define SPI_SETDOUBLECLICKTIME (32) +#define SPI_SETDOUBLECLKHEIGHT (30) +#define SPI_SETDOUBLECLKWIDTH (29) +#define SPI_SETDRAGFULLWINDOWS (37) +#define SPI_SETDRAGHEIGHT (77) +#define SPI_SETDRAGWIDTH (76) +#define SPI_SETFASTTASKSWITCH (36) +#define SPI_SETFILTERKEYS (51) +#define SPI_SETFONTSMOOTHING (75) +#define SPI_SETGRIDGRANULARITY (19) +#define SPI_SETHANDHELD (78) +#define SPI_SETHIGHCONTRAST (67) +#define SPI_SETICONMETRICS (46) +#define SPI_SETICONTITLELOGFONT (34) +#define SPI_SETICONTITLEWRAP (26) +#define SPI_SETKEYBOARDDELAY (23) +#define SPI_SETKEYBOARDPREF (69) +#define SPI_SETKEYBOARDSPEED (11) +#define SPI_SETLANGTOGGLE (91) +#define SPI_SETLOWPOWERACTIVE (85) +#define SPI_SETLOWPOWERTIMEOUT (81) +#define SPI_SETMENUDROPALIGNMENT (28) +#define SPI_SETMINIMIZEDMETRICS (44) +#define SPI_SETMOUSE (4) +#define SPI_SETMOUSEBUTTONSWAP (33) +#define SPI_SETMOUSEKEYS (55) +#define SPI_SETMOUSETRAILS (93) +#define SPI_SETNONCLIENTMETRICS (42) +#define SPI_SETPENWINDOWS (49) +#define SPI_SETPOWEROFFACTIVE (86) +#define SPI_SETPOWEROFFTIMEOUT (82) +#define SPI_SETSCREENREADER (71) +#define SPI_SETSCREENSAVEACTIVE (17) +#define SPI_SETSCREENSAVETIMEOUT (15) +#define SPI_SETSERIALKEYS (63) +#define SPI_SETSHOWSOUNDS (57) +#define SPI_SETSOUNDSENTRY (65) +#define SPI_SETSTICKYKEYS (59) +#define SPI_SETTOGGLEKEYS (53) +#define SPI_SETWORKAREA (47) +#define SPIF_UPDATEINIFILE (1) +#define SPIF_SENDWININICHANGE (2) +#define SPIF_SENDCHANGE (2) + +/* TrackPopupMenu, TrackPopMenuEx */ +#define TPM_CENTERALIGN (0x4L) +#define TPM_LEFTALIGN (0L) +#define TPM_RIGHTALIGN (0x8L) +#define TPM_LEFTBUTTON (0L) +#define TPM_RIGHTBUTTON (0x2L) +#define TPM_HORIZONTAL (0L) +#define TPM_VERTICAL (0x40L) + +/* TranslateCharsetInfo */ +#define TCI_SRCCHARSET (1) +#define TCI_SRCCODEPAGE (2) +#define TCI_SRCFONTSIG (3) + +/* VerFindFile */ +#define VFFF_ISSHAREDFILE (1) +#define VFF_CURNEDEST (1) +#define VFF_FILEINUSE (2) +#define VFF_BUFFTOOSMALL (4) + +/* VerInstallFile */ +#define VIFF_FORCEINSTALL (1) +#define VIFF_DONTDELETEOLD (2) +#define VIF_TEMPFILE (0x1L) +#define VIF_MISMATCH (0x2L) +#define VIF_SRCOLD (0x4L) +#define VIF_DIFFLANG (0x8L) +#define VIF_DIFFCODEPG (0x10L) +#define VIF_DIFFTYPE (0x20L) +#define VIF_WRITEPROT (0x40L) +#define VIF_FILEINUSE (0x80L) +#define VIF_OUTOFSPACE (0x100L) +#define VIF_ACCESSVIOLATION (0x200L) +#define VIF_SHARINGVIOLATION (0x400L) +#define VIF_CANNOTCREATE (0x800L) +#define VIF_CANNOTDELETE (0x1000L) +#define VIF_CANNOTDELETECUR (0x4000L) +#define VIF_CANNOTRENAME (0x2000L) +#define VIF_OUTOFMEMORY (0x8000L) +#define VIF_CANNOTREADSRC (0x10000L) +#define VIF_CANNOTREADDST (0x20000L) +#define VIF_BUFFTOOSMALL (0x40000L) + +/* WideCharToMultiByte */ +#define WC_COMPOSITECHECK (512) +#define WC_DISCARDNS (16) +#define WC_SEPCHARS (32) +#define WC_DEFAULTCHAR (64) + +/* WinHelp */ +#define HELP_COMMAND (0x102L) +#define HELP_CONTENTS (0x3L) +#define HELP_CONTEXT (0x1L) +#define HELP_CONTEXTPOPUP (0x8L) +#define HELP_FORCEFILE (0x9L) +#define HELP_HELPONHELP (0x4L) +#define HELP_INDEX (0x3L) +#define HELP_KEY (0x101L) +#define HELP_MULTIKEY (0x201L) +#define HELP_SETWINPOS (0x0203L) +#define HELP_PARTIALKEY (0x105L) +#define HELP_QUIT (0x2L) +#define HELP_SETCONTENTS (0x5L) +#define HELP_SETINDEX (0x5L) +#define HELP_CONTEXTMENU (0xa) +#define HELP_FINDER (0xb) +#define HELP_WM_HELP (0xc) +#define HELP_TCARD (0x8000) +#define HELP_TCARD_DATA (0x10) +#define HELP_TCARD_OTHER_CALLER (0x11) + +/* WNetAddConnectino2 */ +#define CONNECT_UPDATE_PROFILE (1) + +/* WNetConnectionDialog, WNetDisconnectDialog, WNetOpenEnum */ +#define RESOURCETYPE_DISK (1) +#define RESOURCETYPE_PRINT (2) +#define RESOURCETYPE_ANY (0) +#define RESOURCE_CONNECTED (1) +#define RESOURCE_GLOBALNET (2) +#define RESOURCE_REMEMBERED (3) +#define RESOURCEUSAGE_CONNECTABLE (1) +#define RESOURCEUSAGE_CONTAINER (2) + +/* WNetGetResourceInformation, WNetGetResourceParent */ +#define WN_BAD_NETNAME (0x43L) +#define WN_EXTENDED_ERROR (0x4b8L) +#define WN_MORE_DATA (0xeaL) +#define WN_NO_NETWORK (0x4c6L) +#define WN_SUCCESS (0L) +#define WN_ACCESS_DENIED (0x5L) +#define WN_BAD_PROVIDER (0x4b4L) +#define WN_NOT_AUTHENTICATED (0x4dcL) + +/* WNetGetUniversalName */ +#define UNIVERSAL_NAME_INFO_LEVEL (1) +#define REMOTE_NAME_INFO_LEVEL (2) + +/* GetExitCodeThread */ +#define STILL_ACTIVE (0x103L) + +/* COMMPROP structure */ +#define SP_SERIALCOMM (0x1L) +#define BAUD_075 (0x1L) +#define BAUD_110 (0x2L) +#define BAUD_134_5 (0x4L) +#define BAUD_150 (0x8L) +#define BAUD_300 (0x10L) +#define BAUD_600 (0x20L) +#define BAUD_1200 (0x40L) +#define BAUD_1800 (0x80L) +#define BAUD_2400 (0x100L) +#define BAUD_4800 (0x200L) +#define BAUD_7200 (0x400L) +#define BAUD_9600 (0x800L) +#define BAUD_14400 (0x1000L) +#define BAUD_19200 (0x2000L) +#define BAUD_38400 (0x4000L) +#define BAUD_56K (0x8000L) +#define BAUD_57600 (0x40000L) +#define BAUD_115200 (0x20000L) +#define BAUD_128K (0x10000L) +#define BAUD_USER (0x10000000L) +#define PST_FAX (0x21L) +#define PST_LAT (0x101L) +#define PST_MODEM (0x6L) +#define PST_NETWORK_BRIDGE (0x100L) +#define PST_PARALLELPORT (0x2L) +#define PST_RS232 (0x1L) +#define PST_RS422 (0x3L) +#define PST_RS423 (0x4L) +#define PST_RS449 (0x5L) +#define PST_SCANNER (0x22L) +#define PST_TCPIP_TELNET (0x102L) +#define PST_UNSPECIFIED (0L) +#define PST_X25 (0x103L) +#define PCF_16BITMODE (0x200L) +#define PCF_DTRDSR (0x1L) +#define PCF_INTTIMEOUTS (0x80L) +#define PCF_PARITY_CHECK (0x8L) +#define PCF_RLSD (0x4L) +#define PCF_RTSCTS (0x2L) +#define PCF_SETXCHAR (0x20L) +#define PCF_SPECIALCHARS (0x100L) +#define PCF_TOTALTIMEOUTS (0x40L) +#define PCF_XONXOFF (0x10L) +#define SP_BAUD (0x2L) +#define SP_DATABITS (0x4L) +#define SP_HANDSHAKING (0x10L) +#define SP_PARITY (0x1L) +#define SP_PARITY_CHECK (0x20L) +#define SP_RLSD (0x40L) +#define SP_STOPBITS (0x8L) +#define DATABITS_5 (1) +#define DATABITS_6 (2) +#define DATABITS_7 (4) +#define DATABITS_8 (8) +#define DATABITS_16 (16) +#define DATABITS_16X (32) +#define STOPBITS_10 (1) +#define STOPBITS_15 (2) +#define STOPBITS_20 (4) +#define PARITY_NONE (256) +#define PARITY_ODD (512) +#define PARITY_EVEN (1024) +#define PARITY_MARK (2048) +#define PARITY_SPACE (4096) +#define COMMPROP_INITIALIZED (0xe73cf52eL) + +/* DCB structure */ +#define CBR_110 (110) +#define CBR_300 (300) +#define CBR_600 (600) +#define CBR_1200 (1200) +#define CBR_2400 (2400) +#define CBR_4800 (4800) +#define CBR_9600 (9600) +#define CBR_14400 (14400) +#define CBR_19200 (19200) +#define CBR_38400 (38400) +#define CBR_56000 (56000) +#define CBR_57600 (57600) +#define CBR_115200 (115200) +#define CBR_128000 (128000) +#define CBR_256000 (256000) +#define DTR_CONTROL_DISABLE (0) +#define DTR_CONTROL_ENABLE (1) +#define DTR_CONTROL_HANDSHAKE (2) +#define RTS_CONTROL_DISABLE (0) +#define RTS_CONTROL_ENABLE (1) +#define RTS_CONTROL_HANDSHAKE (2) +#define RTS_CONTROL_TOGGLE (3) +#define EVENPARITY (2) +#define MARKPARITY (3) +#define NOPARITY (0) +#define ODDPARITY (1) +#define SPACEPARITY (4) +#define ONESTOPBIT (0) +#define ONE5STOPBITS (1) +#define TWOSTOPBITS (2) + +/* Debugging events */ +#define CREATE_PROCESS_DEBUG_EVENT (3) +#define CREATE_THREAD_DEBUG_EVENT (2) +#define EXCEPTION_DEBUG_EVENT (1) +#define EXIT_PROCESS_DEBUG_EVENT (5) +#define EXIT_THREAD_DEBUG_EVENT (4) +#define LOAD_DLL_DEBUG_EVENT (6) +#define OUTPUT_DEBUG_STRING_EVENT (8) +#define UNLOAD_DLL_DEBUG_EVENT (7) +#define RIP_EVENT (9) + +/* PROCESS_HEAP_ENTRY structure */ +#define PROCESS_HEAP_REGION (1) +#define PROCESS_HEAP_UNCOMMITTED_RANGE (2) +#define PROCESS_HEAP_ENTRY_BUSY (4) +#define PROCESS_HEAP_ENTRY_MOVEABLE (16) +#define PROCESS_HEAP_ENTRY_DDESHARE (32) + +/* Win32s */ +#define HINSTANCE_ERROR (32) + +/* WIN32_STREAM_ID structure */ +#define BACKUP_DATA (1) +#define BACKUP_EA_DATA (2) +#define BACKUP_SECURITY_DATA (3) +#define BACKUP_ALTERNATE_DATA (4) +#define BACKUP_LINK (5) +#define STREAM_MODIFIED_WHEN_READ (1) +#define STREAM_CONTAINS_SECURITY (2) + +/* STARTUPINFO structure */ +#define STARTF_USESHOWWINDOW (1) +#define STARTF_USEPOSITION (4) +#define STARTF_USESIZE (2) +#define STARTF_USECOUNTCHARS (8) +#define STARTF_USEFILLATTRIBUTE (16) +#define STARTF_RUNFULLSCREEN (32) +#define STARTF_FORCEONFEEDBACK (64) +#define STARTF_FORCEOFFFEEDBACK (128) +#define STARTF_USESTDHANDLES (256) +#define STARTF_USEHOTKEY (512) + +/* OSVERSIONINFO structure */ +#define VER_PLATFORM_WIN32s (0) +#define VER_PLATFORM_WIN32_WINDOWS (1) +#define VER_PLATFORM_WIN32_NT (2) + +/* PROPSHEETPAGE structure */ +#define MAXPROPPAGES (100) +#define PSP_DEFAULT (0) +#define PSP_DLGINDIRECT (1) +#define PSP_HASHELP (32) +#define PSP_USECALLBACK (128) +#define PSP_USEHICON (2) +#define PSP_USEICONID (4) +#define PSP_USEREFPARENT (64) +#define PSP_USETITLE (8) +#define PSP_RTLREADING (16) + +/* PROPSHEETHEADER structure */ +#define PSH_DEFAULT (0) +#define PSH_HASHELP (512) +#define PSH_MODELESS (1024) +#define PSH_NOAPPLYNOW (128) +#define PSH_PROPSHEETPAGE (8) +#define PSH_PROPTITLE (1) +#define PSH_USECALLBACK (256) +#define PSH_USEHICON (2) +#define PSH_USEICONID (4) +#define PSH_USEPSTARTPAGE (64) +#define PSH_WIZARD (32) +#define PSH_RTLREADING (2048) +#define PSCB_INITIALIZED (1) +#define PSCB_PRECREATE (2) + +/* PSN_APPLY message */ +#define PSNRET_NOERROR (0) +#define PSNRET_INVALID_NOCHANGEPAGE (2) + +/* Property Sheet */ +#define PSBTN_APPLYNOW (4) +#define PSBTN_BACK (0) +#define PSBTN_CANCEL (5) +#define PSBTN_FINISH (2) +#define PSBTN_HELP (6) +#define PSBTN_NEXT (1) +#define PSBTN_OK (3) +#define PSWIZB_BACK (1) +#define PSWIZB_NEXT (2) +#define PSWIZB_FINISH (4) +#define PSWIZB_DISABLEDFINISH (8) +#define ID_PSREBOOTSYSTEM (3) +#define ID_PSRESTARTWINDOWS (2) +#define WIZ_BODYCX (184) +#define WIZ_BODYX (92) +#define WIZ_CXBMP (80) +#define WIZ_CXDLG (276) +#define WIZ_CYDLG (140) + +/* VX_FIXEDFILEINFO structure */ +#define VS_FILE_INFO (MAKEINTRESOURCE(16)) +#define VS_VERSION_INFO (1) +#define VS_FF_DEBUG (0x1L) +#define VS_FF_INFOINFERRED (0x10L) +#define VS_FF_PATCHED (0x4L) +#define VS_FF_PRERELEASE (0x2L) +#define VS_FF_PRIVATEBUILD (0x8L) +#define VS_FF_SPECIALBUILD (0x20L) +#define VOS_UNKNOWN (0L) +#define VOS_DOS (0x10000L) +#define VOS_OS216 (0x20000L) +#define VOS_OS232 (0x30000L) +#define VOS_NT (0x40000L) +#define VOS_DOS_WINDOWS16 (0x10001L) +#define VOS_DOS_WINDOWS32 (0x10004L) +#define VOS_OS216_PM16 (0x20002L) +#define VOS_OS232_PM32 (0x30003L) +#define VOS_NT_WINDOWS32 (0x40004L) +#define VFT_UNKNOWN (0L) +#define VFT_APP (0x1L) +#define VFT_DLL (0x2L) +#define VFT_DRV (0x3L) +#define VFT_FONT (0x4L) +#define VFT_VXD (0x5L) +#define VFT_STATIC_LIB (0x7L) +#define VFT2_UNKNOWN (0L) +#define VFT2_DRV_PRINTER (0x1L) +#define VFT2_DRV_KEYBOARD (0x2L) +#define VFT2_DRV_LANGUAGE (0x3L) +#define VFT2_DRV_DISPLAY (0x4L) +#define VFT2_DRV_MOUSE (0x5L) +#define VFT2_DRV_NETWORK (0x6L) +#define VFT2_DRV_SYSTEM (0x7L) +#define VFT2_DRV_INSTALLABLE (0x8L) +#define VFT2_DRV_SOUND (0x9L) +#define VFT2_FONT_RASTER (0x1L) +#define VFT2_FONT_VECTOR (0x2L) +#define VFT2_FONT_TRUETYPE (0x3L) + +/* PANOSE structure */ +#define PAN_ANY (0) +#define PAN_NO_FIT (1) +#define PAN_FAMILY_TEXT_DISPLAY (2) +#define PAN_FAMILY_SCRIPT (3) +#define PAN_FAMILY_DECORATIVE (4) +#define PAN_FAMILY_PICTORIAL (5) +#define PAN_SERIF_COVE (2) +#define PAN_SERIF_OBTUSE_COVE (3) +#define PAN_SERIF_SQUARE_COVE (4) +#define PAN_SERIF_OBTUSE_SQUARE_COVE (5) +#define PAN_SERIF_SQUARE (6) +#define PAN_SERIF_THIN (7) +#define PAN_SERIF_BONE (8) +#define PAN_SERIF_EXAGGERATED (9) +#define PAN_SERIF_TRIANGLE (10) +#define PAN_SERIF_NORMAL_SANS (11) +#define PAN_SERIF_OBTUSE_SANS (12) +#define PAN_SERIF_PERP_SANS (13) +#define PAN_SERIF_FLARED (14) +#define PAN_SERIF_ROUNDED (15) +#define PAN_WEIGHT_VERY_LIGHT (2) +#define PAN_WEIGHT_LIGHT (3) +#define PAN_WEIGHT_THIN (4) +#define PAN_WEIGHT_BOOK (5) +#define PAN_WEIGHT_MEDIUM (6) +#define PAN_WEIGHT_DEMI (7) +#define PAN_WEIGHT_BOLD (8) +#define PAN_WEIGHT_HEAVY (9) +#define PAN_WEIGHT_BLACK (10) +#define PAN_WEIGHT_NORD (11) +#define PAN_PROP_OLD_STYLE (2) +#define PAN_PROP_MODERN (3) +#define PAN_PROP_EVEN_WIDTH (4) +#define PAN_PROP_EXPANDED (5) +#define PAN_PROP_CONDENSED (6) +#define PAN_PROP_VERY_EXPANDED (7) +#define PAN_PROP_VERY_CONDENSED (8) +#define PAN_PROP_MONOSPACED (9) +#define PAN_CONTRAST_NONE (2) +#define PAN_CONTRAST_VERY_LOW (3) +#define PAN_CONTRAST_LOW (4) +#define PAN_CONTRAST_MEDIUM_LOW (5) +#define PAN_CONTRAST_MEDIUM (6) +#define PAN_CONTRAST_MEDIUM_HIGH (7) +#define PAN_CONTRAST_HIGH (8) +#define PAN_CONTRAST_VERY_HIGH (9) +#define PAN_STROKE_GRADUAL_DIAG (2) +#define PAN_STROKE_GRADUAL_TRAN (3) +#define PAN_STROKE_GRADUAL_VERT (4) +#define PAN_STROKE_GRADUAL_HORZ (5) +#define PAN_STROKE_RAPID_VERT (6) +#define PAN_STROKE_RAPID_HORZ (7) +#define PAN_STROKE_INSTANT_VERT (8) +#define PAN_STRAIGHT_ARMS_HORZ (2) +#define PAN_STRAIGHT_ARMS_WEDGE (3) +#define PAN_STRAIGHT_ARMS_VERT (4) +#define PAN_STRAIGHT_ARMS_SINGLE_SERIF (5) +#define PAN_STRAIGHT_ARMS_DOUBLE_SERIF (6) +#define PAN_BENT_ARMS_HORZ (7) +#define PAN_BENT_ARMS_VERT (9) +#define PAN_BENT_ARMS_WEDGE (8) +#define PAN_BENT_ARMS_SINGLE_SERIF (10) +#define PAN_BENT_ARMS_DOUBLE_SERIF (11) +#define PAN_LETT_NORMAL_CONTACT (2) +#define PAN_LETT_NORMAL_WEIGHTED (3) +#define PAN_LETT_NORMAL_BOXED (4) +#define PAN_LETT_NORMAL_FLATTENED (5) +#define PAN_LETT_NORMAL_ROUNDED (6) +#define PAN_LETT_NORMAL_OFF_CENTER (7) +#define PAN_LETT_NORMAL_SQUARE (8) +#define PAN_LETT_OBLIQUE_CONTACT (9) +#define PAN_LETT_OBLIQUE_WEIGHTED (10) +#define PAN_LETT_OBLIQUE_BOXED (11) +#define PAN_LETT_OBLIQUE_FLATTENED (12) +#define PAN_LETT_OBLIQUE_ROUNDED (13) +#define PAN_LETT_OBLIQUE_OFF_CENTER (14) +#define PAN_LETT_OBLIQUE_SQUARE (15) +#define PAN_MIDLINE_STANDARD_TRIMMED (2) +#define PAN_MIDLINE_STANDARD_POINTED (3) +#define PAN_MIDLINE_STANDARD_SERIFED (4) +#define PAN_MIDLINE_HIGH_TRIMMED (5) +#define PAN_MIDLINE_HIGH_POINTED (6) +#define PAN_MIDLINE_HIGH_SERIFED (7) +#define PAN_MIDLINE_CONSTANT_TRIMMED (8) +#define PAN_MIDLINE_CONSTANT_POINTED (9) +#define PAN_MIDLINE_CONSTANT_SERIFED (10) +#define PAN_MIDLINE_LOW_TRIMMED (11) +#define PAN_MIDLINE_LOW_POINTED (12) +#define PAN_MIDLINE_LOW_SERIFED (13) +#define PAN_XHEIGHT_CONSTANT_SMALL (2) +#define PAN_XHEIGHT_CONSTANT_STD (3) +#define PAN_XHEIGHT_CONSTANT_LARGE (4) +#define PAN_XHEIGHT_DUCKING_SMALL (5) +#define PAN_XHEIGHT_DUCKING_STD (6) +#define PAN_XHEIGHT_DUCKING_LARGE (7) + +/* PALETTENTRY structure */ +#define PC_EXPLICIT (2) +#define PC_NOCOLLAPSE (4) +#define PC_RESERVED (1) + +/* LOGBRUSH structure */ +#define BS_DIBPATTERN (5) +#define BS_DIBPATTERN8X8 (8) +#define BS_DIBPATTERNPT (6) +#define BS_HATCHED (2) +#define BS_HOLLOW (1) +#define BS_NULL (1) +#define BS_PATTERN (3) +#define BS_PATTERN8X8 (7) +#define BS_SOLID (0) + +/* DEVMODE structure */ +#define DM_ORIENTATION (0x1L) +#define DM_PAPERSIZE (0x2L) +#define DM_PAPERLENGTH (0x4L) +#define DM_PAPERWIDTH (0x8L) +#define DM_SCALE (0x10L) +#define DM_COPIES (0x100L) +#define DM_DEFAULTSOURCE (0x200L) +#define DM_PRINTQUALITY (0x400L) +#define DM_COLOR (0x800L) +#define DM_DUPLEX (0x1000L) +#define DM_YRESOLUTION (0x2000L) +#define DM_TTOPTION (0x4000L) +#define DM_COLLATE (0x8000L) +#define DM_FORMNAME (0x10000L) +#define DM_LOGPIXELS (0x20000L) +#define DM_BITSPERPEL (0x40000L) +#define DM_PELSWIDTH (0x80000L) +#define DM_PELSHEIGHT (0x100000L) +#define DM_DISPLAYFLAGS (0x200000L) +#define DM_DISPLAYFREQUENCY (0x400000L) +#define DM_ICMMETHOD (0x800000L) +#define DM_ICMINTENT (0x1000000L) +#define DM_MEDIATYPE (0x2000000L) +#define DM_DITHERTYPE (0x4000000L) +#define DMORIENT_LANDSCAPE (2) +#define DMORIENT_PORTRAIT (1) +#define DMPAPER_LETTER (1) +#define DMPAPER_LEGAL (5) +#define DMPAPER_A4 (9) +#define DMPAPER_CSHEET (24) +#define DMPAPER_DSHEET (25) +#define DMPAPER_ESHEET (26) +#define DMPAPER_LETTERSMALL (2) +#define DMPAPER_TABLOID (3) +#define DMPAPER_LEDGER (4) +#define DMPAPER_STATEMENT (6) +#define DMPAPER_EXECUTIVE (7) +#define DMPAPER_A3 (8) +#define DMPAPER_A4SMALL (10) +#define DMPAPER_A5 (11) +#define DMPAPER_B4 (12) +#define DMPAPER_B5 (13) +#define DMPAPER_FOLIO (14) +#define DMPAPER_QUARTO (15) +#define DMPAPER_10X14 (16) +#define DMPAPER_11X17 (17) +#define DMPAPER_NOTE (18) +#define DMPAPER_ENV_9 (19) +#define DMPAPER_ENV_10 (20) +#define DMPAPER_ENV_11 (21) +#define DMPAPER_ENV_12 (22) +#define DMPAPER_ENV_14 (23) +#define DMPAPER_ENV_DL (27) +#define DMPAPER_ENV_C5 (28) +#define DMPAPER_ENV_C3 (29) +#define DMPAPER_ENV_C4 (30) +#define DMPAPER_ENV_C6 (31) +#define DMPAPER_ENV_C65 (32) +#define DMPAPER_ENV_B4 (33) +#define DMPAPER_ENV_B5 (34) +#define DMPAPER_ENV_B6 (35) +#define DMPAPER_ENV_ITALY (36) +#define DMPAPER_ENV_MONARCH (37) +#define DMPAPER_ENV_PERSONAL (38) +#define DMPAPER_FANFOLD_US (39) +#define DMPAPER_FANFOLD_STD_GERMAN (40) +#define DMPAPER_FANFOLD_LGL_GERMAN (41) +#define DMRES_HIGH (-4) +#define DMRES_MEDIUM (-3) +#define DMRES_LOW (-2) +#define DMRES_DRAFT (-1) +#define DMCOLOR_COLOR (2) +#define DMCOLOR_MONOCHROME (1) +#define DMDUP_SIMPLEX (1) +#define DMDUP_HORIZONTAL (3) +#define DMDUP_VERTICAL (2) +#define DMTT_BITMAP (1) +#define DMTT_DOWNLOAD (2) +#define DMTT_SUBDEV (3) +#define DMCOLLATE_TRUE (1) +#define DMCOLLATE_FALSE (0) +#define DM_GRAYSCALE (1) +#define DM_INTERLACED (2) +#define DMICMMETHOD_NONE (1) +#define DMICMMETHOD_SYSTEM (2) +#define DMICMMETHOD_DRIVER (3) +#define DMICMMETHOD_DEVICE (4) +#define DMICMMETHOD_USER (256) +#define DMICM_SATURATE (1) +#define DMICM_CONTRAST (2) +#define DMICM_COLORMETRIC (3) +#define DMICM_USER (256) +#define DMMEDIA_STANDARD (1) +#define DMMEDIA_GLOSSY (3) +#define DMMEDIA_TRANSPARENCY (2) +#define DMMEDIA_USER (256) +#define DMDITHER_NONE (1) +#define DMDITHER_COARSE (2) +#define DMDITHER_FINE (3) +#define DMDITHER_LINEART (4) +#define DMDITHER_GRAYSCALE (10) +#define DMDITHER_USER (256) + +/* RGNDATAHEADER structure */ +#define RDH_RECTANGLES (1) + +/* TTPOLYGONHEADER structure */ +#define TT_POLYGON_TYPE (24) + +/* TTPOLYCURVE structure */ +#define TT_PRIM_LINE (1) +#define TT_PRIM_QSPLINE (2) + +/* GCP_RESULTS structure */ +#define GCPCLASS_ARABIC (2) +#define GCPCLASS_HEBREW (2) +#define GCPCLASS_LATIN (1) +#define GCPCLASS_LATINNUMBER (5) +#define GCPCLASS_LOCALNUMBER (4) +#define GCPCLASS_LATINNUMERICSEPARATOR (7) +#define GCPCLASS_LATINNUMERICTERMINATOR (6) +#define GCPCLASS_NEUTRAL (3) +#define GCPCLASS_NUMERICSEPARATOR (8) +#define GCPCLASS_PREBOUNDLTR (128) +#define GCPCLASS_PREBOUNDRTL (64) +#define GCPCLASS_POSTBOUNDLTR (32) +#define GCPCLASS_POSTBOUNDRTL (16) +#define GCPGLYPH_LINKBEFORE (32768) +#define GCPGLYPH_LINKAFTER (16384) + +/* RASTERIZER_STATUS structure */ +#define TT_AVAILABLE (1) +#define TT_ENABLED (2) + +/* COLORADJUSTMENT structure */ +#define CA_NEGATIVE (1) +#define CA_LOG_FILTER (2) +#define ILLUMINANT_DEVICE_DEFAULT (0) +#define ILLUMINANT_A (1) +#define ILLUMINANT_B (2) +#define ILLUMINANT_C (3) +#define ILLUMINANT_D50 (4) +#define ILLUMINANT_D55 (5) +#define ILLUMINANT_D65 (6) +#define ILLUMINANT_D75 (7) +#define ILLUMINANT_F2 (8) +#define ILLUMINANT_TUNGSTEN (1) +#define ILLUMINANT_DAYLIGHT (3) +#define ILLUMINANT_FLUORESCENT (8) +#define ILLUMINANT_NTSC (3) + +/* DOCINFO structure */ +#define DI_APPBANDING (1) + +/* EMRMETAHEADER structure */ +#define EMR_HEADER (1) +#define ENHMETA_SIGNATURE (1179469088) + +/* RTF event masks */ +#define ENM_CHANGE (1) +#define ENM_CORRECTTEXT (4194304) +#define ENM_DROPFILES (1048576) +#define ENM_KEYEVENTS (65536) +#define ENM_MOUSEEVENTS (131072) +#define ENM_PROTECTED (2097152) +#define ENM_REQUESTRESIZE (262144) +#define ENM_SCROLL (4) +#define ENM_SELCHANGE (524288) +#define ENM_UPDATE (2) +#define ENM_NONE (0) + +/* RTF styles */ +#define ES_DISABLENOSCROLL (8192) +#define ES_EX_NOCALLOLEINIT (16777216) +#define ES_NOIME (524288) +#define ES_SAVESEL (32768) +#define ES_SELFIME (262144) +#define ES_SUNKEN (16384) +#define ES_VERTICAL (4194304) +#define ES_SELECTIONBAR (16777216) + +/* EM_SETOPTIONS message */ +#define ECOOP_SET (1) +#define ECOOP_OR (2) +#define ECOOP_AND (3) +#define ECOOP_XOR (4) +#define ECO_AUTOWORDSELECTION (1) +#define ECO_AUTOVSCROLL (64) +#define ECO_AUTOHSCROLL (128) +#define ECO_NOHIDESEL (256) +#define ECO_READONLY (2048) +#define ECO_WANTRETURN (4096) +#define ECO_SAVESEL (32768) +#define ECO_SELECTIONBAR (16777216) +#define ECO_VERTICAL (4194304) + +/* EM_SETCHARFORMAT message */ +#define SCF_WORD (2) +#define SCF_SELECTION (1) + +/* EM_STREAMOUT message */ +#define SF_TEXT (1) +#define SF_RTF (2) +#define SF_RTFNOOBJS (3) +#define SF_TEXTIZED (4) +#define SFF_SELECTION (32768) +#define SFF_PLAINRTF (16384) + +/* EM_FINDWORDBREAK message */ +#define WB_CLASSIFY (3) +#define WB_ISDELIMITER (2) +#define WB_LEFT (0) +#define WB_LEFTBREAK (6) +#define WB_PREVBREAK (6) +#define WB_MOVEWORDLEFT (4) +#define WB_MOVEWORDPREV (4) +#define WB_MOVEWORDRIGHT (5) +#define WB_MOVEWORDNEXT (5) +#define WB_RIGHT (1) +#define WB_RIGHTBREAK (7) +#define WB_NEXTBREAK (7) + +/* EM_GETPUNCTUATION message */ +#define PC_LEADING (2) +#define PC_FOLLOWING (1) +#define PC_DELIMITER (4) +#define PC_OVERFLOW (3) + +/* EM_SETWORDWRAPMODE message */ +#define WBF_WORDWRAP (16) +#define WBF_WORDBREAK (32) +#define WBF_OVERFLOW (64) +#define WBF_LEVEL1 (128) +#define WBF_LEVEL2 (256) +#define WBF_CUSTOM (512) +#define WBF_BREAKAFTER (64) +#define WBF_BREAKLINE (32) +#define WBF_ISWHITE (16) + +/* CHARFORMAT structure */ +#define CFM_BOLD (1) +#define CFM_COLOR (1073741824) +#define CFM_FACE (536870912) +#define CFM_ITALIC (2) +#define CFM_OFFSET (268435456) +#define CFM_PROTECTED (16) +#define CFM_SIZE (0x80000000) +#define CFM_STRIKEOUT (8) +#define CFM_UNDERLINE (4) +#define CFE_AUTOCOLOR (1073741824) +#define CFE_BOLD (1) +#define CFE_ITALIC (2) +#define CFE_STRIKEOUT (8) +#define CFE_UNDERLINE (4) +#define CFE_PROTECTED (16) + +/* PARAFORMAT structure */ +#define PFM_ALIGNMENT (8) +#define PFM_NUMBERING (32) +#define PFM_OFFSET (4) +#define PFM_OFFSETINDENT (0x80000000) +#define PFM_RIGHTINDENT (2) +#define PFM_STARTINDENT (1) +#define PFM_TABSTOPS (16) +#define PFN_BULLET (1) +#define PFA_LEFT (1) +#define PFA_RIGHT (2) +#define PFA_CENTER (3) + +/* SELCHANGE structure */ +#define SEL_EMPTY (0) +#define SEL_TEXT (1) +#define SEL_OBJECT (2) +#define SEL_MULTICHAR (4) +#define SEL_MULTIOBJECT (8) + +/* RTF clipboard formats */ +#define CF_RTF "Rich Text Format" +#define CF_RETEXTOBJ "RichEdit Text and Objects" + +/* DRAWITEMSTRUCT structure */ +#define ODT_BUTTON (4) +#define ODT_COMBOBOX (3) +#define ODT_LISTBOX (2) +#define ODT_LISTVIEW (102) +#define ODT_MENU (1) +#define ODT_STATIC (5) +#define ODT_TAB (101) +#define ODT_HEADER (100) +#define ODA_DRAWENTIRE (1) +#define ODA_FOCUS (4) +#define ODA_SELECT (2) +#define ODS_CHECKED (8) +#define ODS_COMBOBOXEDIT (4096) +#define ODS_DEFAULT (32) +#define ODS_DISABLED (4) +#define ODS_FOCUS (16) +#define ODS_GRAYED (2) +#define ODS_SELECTED (1) + +/* Common control window classes */ +#define ANIMATE_CLASSW L"SysAnimate32" +#define HOTKEY_CLASSW L"msctls_hotkey32" +#define PROGRESS_CLASSW L"msctls_progress32" +#define STATUSCLASSNAMEW L"msctls_statusbar32" +#define TOOLBARCLASSNAMEW L"ToolbarWindow32" +#define TOOLTIPS_CLASSW L"tooltips_class32" +#define TRACKBAR_CLASSW L"msctls_trackbar32" +#define UPDOWN_CLASSW L"msctls_updown32" +#define WC_HEADERW L"SysHeader32" +#define WC_LISTVIEWW L"SysListView32" +#define WC_TABCONTROLW L"SysTabControl32" +#define WC_TREEVIEWW L"SysTreeView32" + +/* Common control styles */ +#define CCS_ADJUSTABLE (0x20L) +#define CCS_BOTTOM (0x3L) +#define CCS_NODIVIDER (0x40L) +#define CCS_NOMOVEY (0x2L) +#define CCS_NOPARENTALIGN (0x8L) +#define CCS_NORESIZE (0x4L) +#define CCS_TOP (0x1L) +#define ANIMATE_CLASSA "SysAnimate32" +#define HOTKEY_CLASSA "msctls_hotkey32" +#define PROGRESS_CLASSA "msctls_progress32" +#define STATUSCLASSNAMEA "msctls_statusbar32" +#define TOOLBARCLASSNAMEA "ToolbarWindow32" +#define TOOLTIPS_CLASSA "tooltips_class32" +#define TRACKBAR_CLASSA "msctls_trackbar32" +#define UPDOWN_CLASSA "msctls_updown32" +#define WC_HEADERA "SysHeader32" +#define WC_LISTVIEWA "SysListView32" +#define WC_TABCONTROLA "SysTabControl32" +#define WC_TREEVIEWA "SysTreeView32" +#ifdef UNICODE +#define ANIMATE_CLASS ANIMATE_CLASSW +#define HOTKEY_CLASS HOTKEY_CLASSW +#define PROGRESS_CLASS PROGRESS_CLASSW +#define STATUSCLASSNAME STATUSCLASSNAMEW +#define TOOLBARCLASSNAME TOOLBARCLASSNAMEW +#define TOOLTIPS_CLASS TOOLTIPS_CLASSW +#define TRACKBAR_CLASS TRACKBAR_CLASSW +#define UPDOWN_CLASS UPDOWN_CLASSW +#define WC_HEADER WC_HEADERW +#define WC_LISTVIEW WC_LISTVIEWW +#define WC_TABCONTROL WC_TABCONTROLW +#define WC_TREEVIEW WC_TREEVIEWW +#else +#define ANIMATE_CLASS ANIMATE_CLASSA +#define HOTKEY_CLASS HOTKEY_CLASSA +#define PROGRESS_CLASS PROGRESS_CLASSA +#define STATUSCLASSNAME STATUSCLASSNAMEA +#define TOOLBARCLASSNAME TOOLBARCLASSNAMEA +#define TOOLTIPS_CLASS TOOLTIPS_CLASSA +#define TRACKBAR_CLASS TRACKBAR_CLASSA +#define UPDOWN_CLASS UPDOWN_CLASSA +#define WC_HEADER WC_HEADERA +#define WC_LISTVIEW WC_LISTVIEWA +#define WC_TABCONTROL WC_TABCONTROLA +#define WC_TREEVIEW WC_TREEVIEWA +#endif /* UNICODE */ + +/* Header control styles */ +#define HDS_BUTTONS (2) +#define HDS_HIDDEN (8) +#define HDS_HORZ (0) + +/* HD_ITEM structure */ +#define HDI_BITMAP (16) +#define HDI_FORMAT (4) +#define HDI_HEIGHT (1) +#define HDI_LPARAM (8) +#define HDI_TEXT (2) +#define HDI_WIDTH (1) +#define HDF_CENTER (2) +#define HDF_LEFT (0) +#define HDF_RIGHT (1) +#define HDF_RTLREADING (4) +#define HDF_BITMAP (8192) +#define HDF_OWNERDRAW (32768) +#define HDF_STRING (16384) +#define HDF_JUSTIFYMASK (3) + +/* HD_HITTESTINFO structure */ +#define HHT_NOWHERE (1) +#define HHT_ONDIVIDER (4) +#define HHT_ONDIVOPEN (8) +#define HHT_ONHEADER (2) +#define HHT_TOLEFT (2048) +#define HHT_TORIGHT (1024) + +/* TBADDBITMAP structure */ +#define HINST_COMMCTRL ((HINSTANCE)-1) +#define IDB_STD_LARGE_COLOR (1) +#define IDB_STD_SMALL_COLOR (0) +#define IDB_VIEW_LARGE_COLOR (5) +#define IDB_VIEW_SMALL_COLOR (4) +#define STD_COPY (1) +#define STD_CUT (0) +#define STD_DELETE (5) +#define STD_FILENEW (6) +#define STD_FILEOPEN (7) +#define STD_FILESAVE (8) +#define STD_FIND (12) +#define STD_HELP (11) +#define STD_PASTE (2) +#define STD_PRINT (14) +#define STD_PRINTPRE (9) +#define STD_PROPERTIES (10) +#define STD_REDOW (4) +#define STD_REPLACE (13) +#define STD_UNDO (3) +#define VIEW_LARGEICONS (0) +#define VIEW_SMALLICONS (1) +#define VIEW_LIST (2) +#define VIEW_DETAILS (3) +#define VIEW_SORTNAME (4) +#define VIEW_SORTSIZE (5) +#define VIEW_SORTDATE (6) +#define VIEW_SORTTYPE (7) + +/* Toolbar styles */ +#define TBSTYLE_ALTDRAG (1024) +#define TBSTYLE_TOOLTIPS (256) +#define TBSTYLE_WRAPABLE (512) +#define TBSTYLE_BUTTON (0) +#define TBSTYLE_CHECK (2) +#define TBSTYLE_CHECKGROUP (6) +#define TBSTYLE_GROUP (4) +#define TBSTYLE_SEP (1) + +/* Toolbar states */ +#define TBSTATE_CHECKED (1) +#define TBSTATE_ENABLED (4) +#define TBSTATE_HIDDEN (8) +#define TBSTATE_INDETERMINATE (16) +#define TBSTATE_PRESSED (2) +#define TBSTATE_WRAP (32) + +/* Tooltip styles */ +#define TTS_ALWAYSTIP (1) +#define TTS_NOPREFIX (2) + +/* TOOLINFO structure */ +#define TTF_IDISHWND (1) +#define TTF_CENTERTIP (2) +#define TTF_RTLREADING (4) +#define TTF_SUBCLASS (16) + +/* TTM_SETDELAYTIME message */ +#define TTDT_AUTOMATIC (0) +#define TTDT_AUTOPOP (2) +#define TTDT_INITIAL (3) +#define TTDT_RESHOW (1) + +/* Status window */ +#define SBARS_SIZEGRIP (256) +#define SBARS_SIZEGRIP (256) + +/* DL_DRAGGING message */ +#define DL_MOVECURSOR (3) +#define DL_COPYCURSOR (2) +#define DL_STOPCURSOR (1) + +/* Up-down control styles */ +#define UDS_ALIGNLEFT (8) +#define UDS_ALIGNRIGHT (4) +#define UDS_ARROWKEYS (32) +#define UDS_AUTOBUDDY (16) +#define UDS_HORZ (64) +#define UDS_NOTHOUSANDS (128) +#define UDS_SETBUDDYINT (2) +#define UDS_WRAP (1) + +/* UDM_SETRANGE message */ +#define UD_MAXVAL (32767) +#define UD_MINVAL (-32767) + +/* HKM_GETHOTKEY message */ +#define HOTKEYF_ALT (4) +#define HOTKEYF_CONTROL (2) +#define HOTKEYF_EXT (8) +#define HOTKEYF_SHIFT (1) + +/* HKM_SETRULES message */ +#define HKCOMB_A (8) +#define HKCOMB_C (4) +#define HKCOMB_CA (64) +#define HKCOMB_NONE (1) +#define HKCOMB_S (2) +#define HKCOMB_SA (32) +#define HKCOMB_SC (16) +#define HKCOMB_SCA (128) + +/* Trackbar styles */ +#define TBS_HORZ (0) +#define TBS_VERT (2) +#define TBS_AUTOTICKS (1) +#define TBS_NOTICKS (16) +#define TBS_TOP (4) +#define TBS_BOTTOM (0) +#define TBS_LEFT (4) +#define TBS_RIGHT (0) +#define TBS_BOTH (8) +#define TBS_ENABLESELRANGE (32) +#define TBS_FIXEDLENGTH (64) +#define TBS_NOTHUMB (128) +#define TB_BOTTOM (7) +#define TB_ENDTRACK (8) +#define TB_LINEDOWN (1) +#define TB_LINEUP (0) +#define TB_PAGEDOWN (3) +#define TB_PAGEUP (2) +#define TB_THUMBPOSITION (4) +#define TB_THUMBTRACK (5) +#define TB_TOP (6) + +/* List view styles */ +#define LVS_ALIGNLEFT (2048) +#define LVS_ALIGNTOP (0) +#define LVS_AUTOARRANGE (256) +#define LVS_EDITLABELS (512) +#define LVS_ICON (0) +#define LVS_LIST (3) +#define LVS_NOCOLUMNHEADER (16384) +#define LVS_NOLABELWRAP (128) +#define LVS_NOSCROLL (8192) +#define LVS_NOSORTHEADER (32768) +#define LVS_OWNERDRAWFIXED (1024) +#define LVS_REPORT (1) +#define LVS_SHAREIMAGELISTS (64) +#define LVS_SHOWSELALWAYS (8) +#define LVS_SINGLESEL (4) +#define LVS_SMALLICON (2) +#define LVS_SORTASCENDING (16) +#define LVS_SORTDESCENDING (32) +#define LVS_TYPESTYLEMASK (64512) +#define LVSIL_NORMAL (0) +#define LVSIL_SMALL (1) +#define LVSIL_STATE (2) +#define LVIS_CUT (4) +#define LVIS_DROPHILITED (8) +#define LVIS_FOCUSED (1) +#define LVIS_SELECTED (2) +#define LVIS_OVERLAYMASK (3840) +#define LVIS_STATEIMAGEMASK (61440) +#define LPSTR_TEXTCALLBACKW ((LPWSTR)-1L) +#define LPSTR_TEXTCALLBACKA ((LPSTR)-1L) +#ifdef UNICODE +#define LPSTR_TEXTCALLBACK LPSTR_TEXTCALLBACKW +#else +#define LPSTR_TEXTCALLBACK LPSTR_TEXTCALLBACKA +#endif /* UNICODE */ + +/* LV_ITEM structure */ +#define LVIF_TEXT (1) +#define LVIF_IMAGE (2) +#define LVIF_PARAM (4) +#define LVIF_STATE (8) +#define LVIF_DI_SETITEM (4096) + +/* LVM_GETNEXTITEM structure */ +#define LVNI_ABOVE (256) +#define LVNI_ALL (0) +#define LVNI_BELOW (512) +#define LVNI_TOLEFT (1024) +#define LVNI_TORIGHT (2048) +#define LVNI_CUT (4) +#define LVNI_DROPHILITED (8) +#define LVNI_FOCUSED (1) +#define LVNI_SELECTED (2) + +/* LV_FINDINFO structure */ +#define LVFI_PARAM (1) +#define LVFI_PARTIAL (8) +#define LVFI_STRING (2) +#define LVFI_WRAP (32) +#define LVFI_NEARESTXY (64) + +/* LV_HITTESTINFO structure */ +#define LVHT_ABOVE (8) +#define LVHT_BELOW (16) +#define LVHT_NOWHERE (1) +#define LVHT_ONITEMICON (2) +#define LVHT_ONITEMLABEL (4) +#define LVHT_ONITEMSTATEICON (8) +#define LVHT_TOLEFT (64) +#define LVHT_TORIGHT (32) + +/* LV_COLUMN structure */ +#define LVCF_FMT (1) +#define LVCF_SUBITEM (8) +#define LVCF_TEXT (4) +#define LVCF_WIDTH (2) +#define LVCFMT_CENTER (2) +#define LVCFMT_LEFT (0) +#define LVCFMT_RIGHT (1) + +/* ListView_GetItemRect */ +#define LVIR_BOUNDS (0) +#define LVIR_ICON (1) +#define LVIR_LABEL (2) +#define LVIR_SELECTBOUNDS (3) + +/* LVM_ARRANGE message */ +#define LVA_ALIGNLEFT (1) +#define LVA_ALIGNTOP (2) +#define LVA_DEFAULT (0) +#define LVA_SNAPTOGRID (5) + +/* LVM_SETCOLUMNWIDTH message */ +#define LVSCW_AUTOSIZE (-1) +#define LVSCW_AUTOSIZE_USEHEADER (-2) + +/* Tree View styles */ +#define TVS_DISABLEDRAGDROP (16) +#define TVS_EDITLABELS (8) +#define TVS_HASBUTTONS (1) +#define TVS_HASLINES (2) +#define TVS_LINESATROOT (4) +#define TVS_SHOWSELALWAYS (32) + +/* Tree View states */ +#define TVIS_BOLD (16) +#define TVIS_CUT (4) +#define TVIS_DROPHILITED (8) +#define TVIS_EXPANDED (32) +#define TVIS_EXPANDEDONCE (64) +#define TVIS_FOCUSED (1) +#define TVIS_OVERLAYMASK (3840) +#define TVIS_SELECTED (2) +#define TVIS_STATEIMAGEMASK (61440) +#define TVIS_USERMASK (61440) + +/* TV_ITEM structure */ +#define TVIF_CHILDREN (64) +#define TVIF_HANDLE (16) +#define TVIF_IMAGE (2) +#define TVIF_PARAM (4) +#define TVIF_SELECTEDIMAGE (32) +#define TVIF_STATE (8) +#define TVIF_TEXT (1) +#define I_CHILDRENCALLBACK (-1) +#define I_IMAGECALLBACK (-1) + +/* TV_INSERTSTRUCT structure */ +#define TVI_ROOT ((HTREEITEM)0xFFFF0000) +#define TVI_FIRST ((HTREEITEM)0xFFFF0001) +#define TVI_LAST ((HTREEITEM)0xFFFF0002) +#define TVI_SORT ((HTREEITEM)0xFFFF0003) + +/* TV_HITTESTINFO structure */ +#define TVHT_ABOVE (256) +#define TVHT_BELOW (512) +#define TVHT_NOWHERE (1) +#define TVHT_ONITEM (70) +#define TVHT_ONITEMBUTTON (16) +#define TVHT_ONITEMICON (2) +#define TVHT_ONITEMINDENT (8) +#define TVHT_ONITEMLABEL (4) +#define TVHT_ONITEMRIGHT (32) +#define TVHT_ONITEMSTATEICON (64) +#define TVHT_TOLEFT (2048) +#define TVHT_TORIGHT (1024) + +/* TVM_EXPAND message */ +#define TVE_COLLAPSE (1) +#define TVE_COLLAPSERESET (32768) +#define TVE_EXPAND (2) +#define TVE_TOGGLE (3) + +/* TVM_GETIMAGELIST message */ +#define TVSIL_NORMAL (0) +#define TVSIL_STATE (2) + +/* TVM_GETNEXTITEM message */ +#define TVGN_CARET (9) +#define TVGN_CHILD (4) +#define TVGN_DROPHILITE (8) +#define TVGN_FIRSTVISIBLE (5) +#define TVGN_NEXT (1) +#define TVGN_NEXTVISIBLE (6) +#define TVGN_PARENT (3) +#define TVGN_PREVIOUS (2) +#define TVGN_PREVIOUSVISIBLE (7) +#define TVGN_ROOT (0) + +/* TVN_SELCHANGED message */ +#define TVC_BYKEYBOARD (2) +#define TVC_BYMOUSE (1) +#define TVC_UNKNOWN (0) + +/* Tab control styles */ +#define TCS_BUTTONS (256) +#define TCS_FIXEDWIDTH (1024) +#define TCS_FOCUSNEVER (32768) +#define TCS_FOCUSONBUTTONDOWN (4096) +#define TCS_FORCEICONLEFT (16) +#define TCS_FORCELABELLEFT (32) +#define TCS_MULTILINE (512) +#define TCS_OWNERDRAWFIXED (8192) +#define TCS_RAGGEDRIGHT (2048) +#define TCS_RIGHTJUSTIFY (0) +#define TCS_SINGLELINE (0) +#define TCS_TABS (0) +#define TCS_TOOLTIPS (16384) + +/* TC_ITEM structure */ +#define TCIF_TEXT (1) +#define TCIF_IMAGE (2) +#define TCIF_PARAM (8) +#define TCIF_RTLREADING (4) + +/* TC_HITTESTINFO structure */ +#define TCHT_NOWHERE (1) +#define TCHT_ONITEM (6) +#define TCHT_ONITEMICON (2) +#define TCHT_ONITEMLABEL (4) + +/* Animation control styles */ +#define ACS_AUTOPLAY (4) +#define ACS_CENTER (1) +#define ACS_TRANSPARENT (2) + +/* MODEMDEVCAPS structure */ +#define DIALOPTION_BILLING (64) +#define DIALOPTION_QUIET (128) +#define DIALOPTION_DIALTONE (256) +#define MDMVOLFLAG_LOW (1) +#define MDMVOLFLAG_MEDIUM (2) +#define MDMVOLFLAG_HIGH (4) +#define MDMVOL_LOW (0) +#define MDMVOL_MEDIUM (1) +#define MDMVOL_HIGH (2) +#define MDMSPKRFLAG_OFF (1) +#define MDMSPKRFLAG_DIAL (2) +#define MDMSPKRFLAG_ON (4) +#define MDMSPKRFLAG_CALLSETUP (8) +#define MDMSPKR_OFF (0) +#define MDMSPKR_DIAL (1) +#define MDMSPKR_ON (2) +#define MDMSPKR_CALLSETUP (3) +#define MDM_BLIND_DIAL (512) +#define MDM_CCITT_OVERRIDE (64) +#define MDM_CELLULAR (8) +#define MDM_COMPRESSION (1) +#define MDM_ERROR_CONTROL (2) +#define MDM_FLOWCONTROL_HARD (16) +#define MDM_FLOWCONTROL_SOFT (32) +#define MDM_FORCED_EC (4) +#define MDM_SPEED_ADJUST (128) +#define MDM_TONE_DIAL (256) +#define MDM_V23_OVERRIDE (1024) + +/* Languages */ +#define LANG_BULGARIAN (2) +#define LANG_CHINESE (4) +#define LANG_CROATIAN (26) +#define LANG_CZECH (5) +#define LANG_DANISH (6) +#define LANG_DUTCH (19) +#define LANG_ENGLISH (9) +#define LANG_FINNISH (11) +#define LANG_FRENCH (12) +#define LANG_GERMAN (7) +#define LANG_GREEK (8) +#define LANG_HUNGARIAN (14) +#define LANG_ICELANDIC (15) +#define LANG_ITALIAN (16) +#define LANG_JAPANESE (17) +#define LANG_KOREAN (18) +#define LANG_NEUTRAL (0) +#define LANG_NORWEGIAN (20) +#define LANG_POLISH (21) +#define LANG_PORTUGUESE (22) +#define LANG_ROMANIAN (24) +#define LANG_RUSSIAN (25) +#define LANG_SLOVAK (27) +#define LANG_SLOVENIAN (36) +#define LANG_SPANISH (10) +#define LANG_SWEDISH (29) +#define LANG_TURKISH (31) +#define SUBLANG_CHINESE_SIMPLIFIED (2) +#define SUBLANG_CHINESE_TRADITIONAL (1) +#define SUBLANG_CHINESE_HONGKONG (3) +#define SUBLANG_CHINESE_SINGAPORE (4) +#define SUBLANG_DEFAULT (1) +#define SUBLANG_DUTCH (1) +#define SUBLANG_DUTCH_BELGIAN (2) +#define SUBLANG_ENGLISH_AUS (3) +#define SUBLANG_ENGLISH_CAN (4) +#define SUBLANG_ENGLISH_EIRE (6) +#define SUBLANG_ENGLISH_NZ (5) +#define SUBLANG_ENGLISH_UK (2) +#define SUBLANG_ENGLISH_US (1) +#define SUBLANG_FRENCH (1) +#define SUBLANG_FRENCH_BELGIAN (2) +#define SUBLANG_FRENCH_CANADIAN (3) +#define SUBLANG_FRENCH_SWISS (4) +#define SUBLANG_GERMAN (1) +#define SUBLANG_GERMAN_AUSTRIAN (3) +#define SUBLANG_GERMAN_SWISS (2) +#define SUBLANG_ITALIAN (1) +#define SUBLANG_ITALIAN_SWISS (2) +#define SUBLANG_NEUTRAL (0) +#define SUBLANG_NORWEGIAN_BOKMAL (1) +#define SUBLANG_NORWEGIAN_NYNORSK (2) +#define SUBLANG_PORTUGUESE (2) +#define SUBLANG_PORTUGUESE_BRAZILIAN (1) +#define SUBLANG_SPANISH (1) +#define SUBLANG_SPANISH_MEXICAN (2) +#define SUBLANG_SPANISH_MODERN (3) +#define SUBLANG_SYS_DEFAULT (2) +#define NLS_VALID_LOCALE_MASK (1048575) +#define SORT_DEFAULT (0) +#define SORT_JAPANESE_XJIS (0) +#define SORT_JAPANESE_UNICODE (1) +#define SORT_CHINESE_BIG5 (0) +#define SORT_CHINESE_UNICODE (1) +#define SORT_KOREAN_KSC (0) +#define SORT_KOREAN_UNICODE (1) + +/* SYSTEM_INFO structure */ +#define PROCESSOR_INTEL_386 (386) +#define PROCESSOR_INTEL_486 (486) +#define PROCESSOR_INTEL_PENTIUM (586) +#define PROCESSOR_MIPS_R4000 (4000) +#define PROCESSOR_ALPHA_21064 (21064) + +/* TAPE_GET_DRIVE_PARAMETERS structure */ +#define TAPE_DRIVE_COMPRESSION (131072) +#define TAPE_DRIVE_ECC (65536) +#define TAPE_DRIVE_ERASE_BOP_ONLY (64) +#define TAPE_DRIVE_ERASE_LONG (32) +#define TAPE_DRIVE_ERASE_IMMEDIATE (128) +#define TAPE_DRIVE_ERASE_SHORT (16) +#define TAPE_DRIVE_FIXED (1) +#define TAPE_DRIVE_FIXED_BLOCK (1024) +#define TAPE_DRIVE_INITIATOR (4) +#define TAPE_DRIVE_PADDING (262144) +#define TAPE_DRIVE_GET_ABSOLUTE_BLK (1048576) +#define TAPE_DRIVE_GET_LOGICAL_BLK (2097152) +#define TAPE_DRIVE_REPORT_SMKS (524288) +#define TAPE_DRIVE_SELECT (2) +#define TAPE_DRIVE_SET_EOT_WZ_SIZE (4194304) +#define TAPE_DRIVE_TAPE_CAPACITY (256) +#define TAPE_DRIVE_TAPE_REMAINING (512) +#define TAPE_DRIVE_VARIABLE_BLOCK (2048) +#define TAPE_DRIVE_WRITE_PROTECT (4096) +#define TAPE_DRIVE_ABS_BLK_IMMED (-2147475456) +#define TAPE_DRIVE_ABSOLUTE_BLK (-2147479552) +#define TAPE_DRIVE_END_OF_DATA (-2147418112) +#define TAPE_DRIVE_FILEMARKS (-2147221504) +#define TAPE_DRIVE_LOAD_UNLOAD (-2147483647) +#define TAPE_DRIVE_LOAD_UNLD_IMMED (-2147483616) +#define TAPE_DRIVE_LOCK_UNLOCK (-2147483644) +#define TAPE_DRIVE_LOCK_UNLK_IMMED (-2147483520) +#define TAPE_DRIVE_LOG_BLK_IMMED (-2147450880) +#define TAPE_DRIVE_LOGICAL_BLK (-2147467264) +#define TAPE_DRIVE_RELATIVE_BLKS (-2147352576) +#define TAPE_DRIVE_REVERSE_POSITION (-2143289344) +#define TAPE_DRIVE_REWIND_IMMEDIATE (-2147483640) +#define TAPE_DRIVE_SEQUENTIAL_FMKS (-2146959360) +#define TAPE_DRIVE_SEQUENTIAL_SMKS (-2145386496) +#define TAPE_DRIVE_SET_BLOCK_SIZE (-2147483632) +#define TAPE_DRIVE_SET_COMPRESSION (-2147483136) +#define TAPE_DRIVE_SET_ECC (-2147483392) +#define TAPE_DRIVE_SET_PADDING (-2147482624) +#define TAPE_DRIVE_SET_REPORT_SMKS (-2147481600) +#define TAPE_DRIVE_SETMARKS (-2146435072) +#define TAPE_DRIVE_SPACE_IMMEDIATE (-2139095040) +#define TAPE_DRIVE_TENSION (-2147483646) +#define TAPE_DRIVE_TENSION_IMMED (-2147483584) +#define TAPE_DRIVE_WRITE_FILEMARKS (-2113929216) +#define TAPE_DRIVE_WRITE_LONG_FMKS (-2013265920) +#define TAPE_DRIVE_WRITE_MARK_IMMED (-1879048192) +#define TAPE_DRIVE_WRITE_SETMARKS (-2130706432) +#define TAPE_DRIVE_WRITE_SHORT_FMKS (-2080374784) + +/* OPENFILENAME structure */ +#define OFN_ALLOWMULTISELECT (0x200) +#define OFN_CREATEPROMPT (0x2000) +#define OFN_ENABLEHOOK (0x20) +#define OFN_ENABLETEMPLATE (0x40) +#define OFN_ENABLETEMPLATEHANDLE (0x80) +#define OFN_EXPLORER (0x80000) +#define OFN_EXTENSIONDIFFERENT (0x400) +#define OFN_FILEMUSTEXIST (0x1000) +#define OFN_HIDEREADONLY (0x4) +#define OFN_LONGNAMES (0x200000) +#define OFN_NOCHANGEDIR (0x8) +#define OFN_NODEREFERENCELINKS (0x100000) +#define OFN_NOLONGNAMES (0x40000) +#define OFN_NONETWORKBUTTON (0x20000) +#define OFN_NOREADONLYRETURN (0x8000) +#define OFN_NOTESTFILECREATE (0x10000) +#define OFN_NOVALIDATE (0x100) +#define OFN_OVERWRITEPROMPT (0x2) +#define OFN_PATHMUSTEXIST (0x800) +#define OFN_READONLY (0x1) +#define OFN_SHAREAWARE (0x4000) +#define OFN_SHOWHELP (0x10) + +/* SHAREVISTRING message */ +#define OFN_SHAREFALLTHROUGH (0x2) +#define OFN_SHARENOWARN (0x1) +#define OFN_SHAREWARN (0) + +/* Open/Save notifications */ +#define CDN_INITDONE (0xfffffda7) +#define CDN_SELCHANGE (0xfffffda6) +#define CDN_FOLDERCHANGE (0xfffffda5) +#define CDN_SHAREVIOLATION (0xfffffda4) +#define CDN_HELP (0xfffffda3) +#define CDN_FILEOK (0xfffffda2) +#define CDN_TYPECHANGE (0xfffffda1) + +/* Open/Save messages */ +#define CDM_GETFILEPATH (0x465) +#define CDM_GETFOLDERIDLIST (0x467) +#define CDM_GETFOLDERPATH (0x466) +#define CDM_GETSPEC (0x464) +#define CDM_HIDECONTROL (0x469) +#define CDM_SETCONTROLTEXT (0x468) +#define CDM_SETDEFEXT (0x46a) + +/* CHOOSECOLOR structure */ +#define CC_ENABLEHOOK (0x10) +#define CC_ENABLETEMPLATE (0x20) +#define CC_ENABLETEMPLATEHANDLE (0x40) +#define CC_FULLOPEN (0x2) +#define CC_PREVENTFULLOPEN (0x4) +#define CC_RGBINIT (0x1) +#define CC_SHOWHELP (0x8) +#define CC_SOLIDCOLOR (0x80) + +/* FINDREPLACE structure */ +#define FR_DIALOGTERM (0x40) +#define FR_DOWN (0x1) +#define FR_ENABLEHOOK (0x100) +#define FR_ENABLETEMPLATE (0x200) +#define FR_ENABLETEMPLATEHANDLE (0x2000) +#define FR_FINDNEXT (0x8) +#define FR_HIDEUPDOWN (0x4000) +#define FR_HIDEMATCHCASE (0x8000) +#define FR_HIDEWHOLEWORD (0x10000) +#define FR_MATCHCASE (0x4) +#define FR_NOMATCHCASE (0x800) +#define FR_NOUPDOWN (0x400) +#define FR_NOWHOLEWORD (0x1000) +#define FR_REPLACE (0x10) +#define FR_REPLACEALL (0x20) +#define FR_SHOWHELP (0x80) +#define FR_WHOLEWORD (0x2) + +/* CHOOSEFONT structure */ +#define CF_APPLY (0x200L) +#define CF_ANSIONLY (0x400L) +#define CF_BOTH (0x3) +#define CF_TTONLY (0x40000L) +#define CF_EFFECTS (0x100L) +#define CF_ENABLEHOOK (0x8L) +#define CF_ENABLETEMPLATE (0x10L) +#define CF_ENABLETEMPLATEHANDLE (0x20L) +#define CF_FIXEDPITCHONLY (0x4000L) +#define CF_FORCEFONTEXIST (0x10000L) +#define CF_INITTOLOGFONTSTRUCT (0x40L) +#define CF_LIMITSIZE (0x2000L) +#define CF_NOOEMFONTS (0x800L) +#define CF_NOFACESEL (0x80000L) +#define CF_NOSCRIPTSEL (0x800000L) +#define CF_NOSTYLESEL (0x100000L) +#define CF_NOSIZESEL (0x200000L) +#define CF_NOSIMULATIONS (0x1000L) +#define CF_NOVECTORFONTS (0x800L) +#define CF_NOVERTFONTS (0x1000000L) +#define CF_PRINTERFONTS (0x2) +#define CF_SCALABLEONLY (0x20000L) +#define CF_SCREENFONTS (0x1) +#define CF_SCRIPTSONLY (0x400L) +#define CF_SELECTSCRIPT (0x400000L) +#define CF_SHOWHELP (0x4L) +#define CF_USESTYLE (0x80L) +#define CF_WYSIWYG (0x8000L) +#define BOLD_FONTTYPE (0x100) +#define ITALIC_FONTTYPE (0x200) +#define PRINTER_FONTTYPE (0x4000) +#define REGULAR_FONTTYPE (0x400) +#define SCREEN_FONTTYPE (0x2000) +#define SIMULATED_FONTTYPE (0x8000) + +/* Common dialog messages */ +#define COLOROKSTRINGW L"commdlg_ColorOK" +#define FILEOKSTRINGW L"commdlg_FileNameOK" +#define FINDMSGSTRINGW L"commdlg_FindReplace" +#define HELPMSGSTRINGW L"commdlg_help" +#define LBSELCHSTRINGW L"commdlg_LBSelChangedNotify" +#define SETRGBSTRINGW L"commdlg_SetRGBColor" +#define SHAREVISTRINGW L"commdlg_ShareViolation" +#define COLOROKSTRINGA "commdlg_ColorOK" +#define FILEOKSTRINGA "commdlg_FileNameOK" +#define FINDMSGSTRINGA "commdlg_FindReplace" +#define HELPMSGSTRINGA "commdlg_help" +#define LBSELCHSTRINGA "commdlg_LBSelChangedNotify" +#define SETRGBSTRINGA "commdlg_SetRGBColor" +#define SHAREVISTRINGA "commdlg_ShareViolation" +#ifdef UNICODE +#define COLOROKSTRING COLOROKSTRINGW +#define FILEOKSTRING FILEOKSTRINGW +#define FINDMSGSTRING FINDMSGSTRINGW +#define HELPMSGSTRING HELPMSGSTRINGW +#define LBSELCHSTRING LBSELCHSTRINGW +#define SETRGBSTRING SETRGBSTRINGW +#define SHAREVISTRING SHAREVISTRINGW +#else +#define COLOROKSTRING COLOROKSTRINGA +#define FILEOKSTRING FILEOKSTRINGA +#define FINDMSGSTRING FINDMSGSTRINGA +#define HELPMSGSTRING HELPMSGSTRINGA +#define LBSELCHSTRING LBSELCHSTRINGA +#define SETRGBSTRING SETRGBSTRINGA +#define SHAREVISTRING SHAREVISTRINGA +#endif + +/* LBSELCHSTRING message */ +#define CD_LBSELCHANGE (0) +#define CD_LBSELADD (2) +#define CD_LBSELSUB (1) +#define CD_LBSELNOITEMS (-1) + +/* DEVNAMES structure */ +#define DN_DEFAULTPRN (1) + +/* PRINTDLG structure */ +#define PD_ALLPAGES (0) +#define PD_COLLATE (16) +#define PD_DISABLEPRINTTOFILE (524288) +#define PD_ENABLEPRINTHOOK (4096) +#define PD_ENABLEPRINTTEMPLATE (16384) +#define PD_ENABLEPRINTTEMPLATEHANDLE (65536) +#define PD_ENABLESETUPHOOK (8192) +#define PD_ENABLESETUPTEMPLATE (32768) +#define PD_ENABLESETUPTEMPLATEHANDLE (131072) +#define PD_HIDEPRINTTOFILE (1048576) +#define PD_NOPAGENUMS (8) +#define PD_NOSELECTION (4) +#define PD_NOWARNING (128) +#define PD_PAGENUMS (2) +#define PD_PRINTSETUP (64) +#define PD_PRINTTOFILE (32) +#define PD_RETURNDC (256) +#define PD_RETURNDEFAULT (1024) +#define PD_RETURNIC (512) +#define PD_SELECTION (1) +#define PD_SHOWHELP (2048) +#define PD_USEDEVMODECOPIES (262144) +#define PD_USEDEVMODECOPIESANDCOLLATE (262144) + +/* PAGESETUPDLG structure */ +#define PSD_DEFAULTMINMARGINS (0) +#define PSD_DISABLEMARGINS (16) +#define PSD_DISABLEORIENTATION (256) +#define PSD_DISABLEPAGEPAINTING (524288) +#define PSD_DISABLEPAPER (512) +#define PSD_DISABLEPRINTER (32) +#define PSD_ENABLEPAGEPAINTHOOK (262144) +#define PSD_ENABLEPAGESETUPHOOK (8192) +#define PSD_ENABLEPAGESETUPTEMPLATE (32768) +#define PSD_ENABLEPAGESETUPTEMPLATEHANDLE (131072) +#define PSD_INHUNDREDTHSOFMILLIMETERS (8) +#define PSD_INTHOUSANDTHSOFINCHES (4) +#define PSD_INWININIINTLMEASURE (0) +#define PSD_MARGINS (2) +#define PSD_MINMARGINS (1) +#define PSD_NOWARNING (128) +#define PSD_RETURNDEFAULT (1024) +#define PSD_SHOWHELP (2048) + +/* WM_SHOWWINDOW message */ +#define SW_OTHERUNZOOM (4) +#define SW_OTHERZOOM (2) +#define SW_PARENTCLOSING (1) +#define SW_PARENTOPENING (3) + +/* ImmGetVirtualKey */ +#define VK_PROCESSKEY (229) + +/* Keystroke Message Flags */ +#define KF_ALTDOWN (8192) +#define KF_DLGMODE (2048) +#define KF_EXTENDED (256) +#define KF_MENUMODE (4096) +#define KF_REPEAT (16384) +#define KF_UP (32768) + +/* GetKeyboardLayoutName */ +#define KL_NAMELENGTH (9) + +/* WM_ACTIVATE message */ +#define WA_ACTIVE (1) +#define WA_CLICKACTIVE (2) +#define WA_INACTIVE (0) + +/* WM_ACTIVATE message */ +#define PWR_CRITICALRESUME (3) +#define PWR_SUSPENDREQUEST (1) +#define PWR_SUSPENDRESUME (2) +#define PWR_FAIL (-1) +#define PWR_OK (1) + +/* WM_NOTIFYFORMAT message */ +#define NF_QUERY (3) +#define NF_REQUERY (4) +#define NFR_ANSI (1) +#define NFR_UNICODE (2) + +/* WM_SIZING message */ +#define WMSZ_BOTTOM (6) +#define WMSZ_BOTTOMLEFT (7) +#define WMSZ_BOTTOMRIGHT (8) +#define WMSZ_LEFT (1) +#define WMSZ_RIGHT (2) +#define WMSZ_TOP (3) +#define WMSZ_TOPLEFT (4) +#define WMSZ_TOPRIGHT (5) + +/* WM_MOUSEACTIVATE message */ +#define MA_ACTIVATE (1) +#define MA_ACTIVATEANDEAT (2) +#define MA_NOACTIVATE (3) +#define MA_NOACTIVATEANDEAT (4) + +/* WM_SIZE message */ +#define SIZE_MAXHIDE (4) +#define SIZE_MAXIMIZED (2) +#define SIZE_MAXSHOW (3) +#define SIZE_MINIMIZED (1) +#define SIZE_RESTORED (0) + +/* WM_NCCALCSIZE message */ +#define WVR_ALIGNTOP (16) +#define WVR_ALIGNLEFT (32) +#define WVR_ALIGNBOTTOM (64) +#define WVR_ALIGNRIGHT (128) +#define WVR_HREDRAW (256) +#define WVR_VREDRAW (512) +#define WVR_REDRAW (768) +#define WVR_VALIDRECTS (1024) + +/* WM_NCHITTEST message */ +#define HTBOTTOM (15) +#define HTBOTTOMLEFT (16) +#define HTBOTTOMRIGHT (17) +#define HTCAPTION (2) +#define HTCLIENT (1) +#define HTERROR (-2) +#define HTGROWBOX (4) +#define HTHSCROLL (6) +#define HTLEFT (10) +#define HTMENU (5) +#define HTNOWHERE (0) +#define HTREDUCE (8) +#define HTRIGHT (11) +#define HTSIZE (4) +#define HTSYSMENU (3) +#define HTTOP (12) +#define HTTOPLEFT (13) +#define HTTOPRIGHT (14) +#define HTTRANSPARENT (-1) +#define HTVSCROLL (7) +#define HTZOOM (9) +#define HTBORDER (18) +#define HTMAXBUTTON HTZOOM +#define HTMINBUTTON HTREDUCE + +/* Mouse messages */ +#define MK_CONTROL (8) +#define MK_LBUTTON (1) +#define MK_MBUTTON (16) +#define MK_RBUTTON (2) +#define MK_SHIFT (4) + +/* WNDCLASS structure */ +#define CS_BYTEALIGNCLIENT (4096) +#define CS_BYTEALIGNWINDOW (8192) +#define CS_CLASSDC (64) +#define CS_DBLCLKS (8) +#define CS_GLOBALCLASS (16384) +#define CS_HREDRAW (2) +#define CS_KEYCVTWINDOW (4) +#define CS_NOCLOSE (512) +#define CS_NOKEYCVT (256) +#define CS_OWNDC (32) +#define CS_PARENTDC (128) +#define CS_SAVEBITS (2048) +#define CS_VREDRAW (1) +#define DLGWINDOWEXTRA (30) + +/* ACCEL structure */ +#define FALT (16) +#define FCONTROL (8) +#define FNOINVERT (2) +#define FSHIFT (4) +#define FVIRTKEY (1) + +/* MENUITEMINFO structure */ +#define MIIM_CHECKMARKS (8) +#define MIIM_DATA (32) +#define MIIM_ID (2) +#define MIIM_STATE (1) +#define MIIM_SUBMENU (4) +#define MIIM_TYPE (16) +#define MFT_BITMAP (0x4L) +#define MFT_MENUBARBREAK (0x20L) +#define MFT_MENUBREAK (0x40L) +#define MFT_OWNERDRAW (0x100L) +#define MFT_RADIOCHECK (0x200L) +#define MFT_RIGHTJUSTIFY (0x4000L) +#define MFT_SEPARATOR (0x800L) +#define MFT_STRING (0L) +#define MFS_CHECKED (0x8L) +#define MFS_DEFAULT (0x1000L) +#define MFS_DISABLED (0x3L) +#define MFS_ENABLED (0L) +#define MFS_GRAYED (0x3L) +#define MFS_HILITE (0x80L) +#define MFS_UNCHECKED (0L) +#define MFS_UNHILITE (0L) + +/* SERIALKEYS structure */ +#define SERKF_AVAILABLE (2) +#define SERKF_INDICATOR (4) +#define SERKF_SERIALKEYSON (1) + +/* FILTERKEYS structure */ +#define FKF_AVAILABLE (2) +#define FKF_CLICKON (64) +#define FKF_FILTERKEYSON (1) +#define FKF_HOTKEYACTIVE (4) +#define FKF_HOTKEYSOUND (16) +#define FKF_CONFIRMHOTKEY (8) +#define FKF_INDICATOR (32) + +/* HELPINFO structure */ +#define HELPINFO_MENUITEM (2) +#define HELPINFO_WINDOW (1) + +/* WM_PRINT message */ +#define PRF_CHECKVISIBLE (0x1L) +#define PRF_CHILDREN (0x10L) +#define PRF_CLIENT (0x4L) +#define PRF_ERASEBKGND (0x8L) +#define PRF_NONCLIENT (0x2L) +#define PRF_OWNED (0x20L) + +/* MapWindowPoints */ +#define HWND_DESKTOP ((HWND)0) + +/* WM_SYSCOMMAND message */ +#define SC_CLOSE (61536) +#define SC_CONTEXTHELP (61824) +#define SC_DEFAULT (61792) +#define SC_HOTKEY (61776) +#define SC_HSCROLL (61568) +#define SC_KEYMENU (61696) +#define SC_MAXIMIZE (61488) +#define SC_ZOOM (61488) +#define SC_MINIMIZE (61472) +#define SC_ICON (61472) +#define SC_MONITORPOWER (61808) +#define SC_MOUSEMENU (61584) +#define SC_MOVE (61456) +#define SC_NEXTWINDOW (61504) +#define SC_PREVWINDOW (61520) +#define SC_RESTORE (61728) +#define SC_SCREENSAVE (61760) +#define SC_SIZE (61440) +#define SC_TASKLIST (61744) +#define SC_VSCROLL (61552) + +/* DM_GETDEFID message */ +#define DC_HASDEFID (21323) + +/* WM_GETDLGCODE message */ +#define DLGC_BUTTON (8192) +#define DLGC_DEFPUSHBUTTON (16) +#define DLGC_HASSETSEL (8) +#define DLGC_RADIOBUTTON (64) +#define DLGC_STATIC (256) +#define DLGC_UNDEFPUSHBUTTON (32) +#define DLGC_WANTALLKEYS (4) +#define DLGC_WANTARROWS (1) +#define DLGC_WANTCHARS (128) +#define DLGC_WANTMESSAGE (4) +#define DLGC_WANTTAB (2) + +/* EM_SETMARGINS message */ +#define EC_LEFTMARGIN (1) +#define EC_RIGHTMARGIN (2) +#define EC_USEFONTINFO (65535) + +/* LB_SETCOUNT message */ +#define LB_ERR (-1) +#define LB_ERRSPACE (-2) +#define LB_OKAY (0) + +/* CB_DIR message */ +#define CB_ERR (-1) +#define CB_ERRSPACE (-2) + +/* WM_IME_CONTROL message */ +#define IMC_GETCANDIDATEPOS (7) +#define IMC_GETCOMPOSITIONFONT (9) +#define IMC_GETCOMPOSITIONWINDOW (11) +#define IMC_GETSTATUSWINDOWPOS (15) +#define IMC_CLOSESTATUSWINDOW (33) +#define IMC_OPENSTATUSWINDOW (34) +#define IMC_SETCANDIDATEPOS (8) +#define IMC_SETCOMPOSITIONFONT (10) +#define IMC_SETCOMPOSITIONWINDOW (12) +#define IMC_SETSTATUSWINDOWPOS (16) + +/* WM_IME_CONTROL message */ +#define IMN_CHANGECANDIDATE (3) +#define IMN_CLOSECANDIDATE (4) +#define IMN_CLOSESTATUSWINDOW (1) +#define IMN_GUIDELINE (13) +#define IMN_OPENCANDIDATE (5) +#define IMN_OPENSTATUSWINDOW (2) +#define IMN_SETCANDIDATEPOS (9) +#define IMN_SETCOMPOSITIONFONT (10) +#define IMN_SETCOMPOSITIONWINDOW (11) +#define IMN_SETCONVERSIONMODE (6) +#define IMN_SETOPENSTATUS (8) +#define IMN_SETSENTENCEMODE (7) +#define IMN_SETSTATUSWINDOWPOS (12) +#define IMN_PRIVATE (14) + +/* STICKYKEYS structure */ +#define SKF_AUDIBLEFEEDBACK (64) +#define SKF_AVAILABLE (2) +#define SKF_CONFIRMHOTKEY (8) +#define SKF_HOTKEYACTIVE (4) +#define SKF_HOTKEYSOUND (16) +#define SKF_INDICATOR (32) +#define SKF_STICKYKEYSON (1) +#define SKF_TRISTATE (128) +#define SKF_TWOKEYSOFF (256) + +/* MOUSEKEYS structure */ +#define MKF_AVAILABLE (2) +#define MKF_CONFIRMHOTKEY (8) +#define MKF_HOTKEYACTIVE (4) +#define MKF_HOTKEYSOUND (16) +#define MKF_INDICATOR (32) +#define MKF_MOUSEKEYSON (1) +#define MKF_MODIFIERS (64) +#define MKF_REPLACENUMBERS (128) + +/* SOUNDSENTRY structure */ +#define SSF_AVAILABLE (2) +#define SSF_SOUNDSENTRYON (1) +#define SSTF_BORDER (2) +#define SSTF_CHARS (1) +#define SSTF_DISPLAY (3) +#define SSTF_NONE (0) +#define SSGF_DISPLAY (3) +#define SSGF_NONE (0) +#define SSWF_CUSTOM (4) +#define SSWF_DISPLAY (3) +#define SSWF_NONE (0) +#define SSWF_TITLE (1) +#define SSWF_WINDOW (2) + +/* ACCESSTIMEOUT structure */ +#define ATF_ONOFFFEEDBACK (2) +#define ATF_TIMEOUTON (1) + +/* HIGHCONTRAST structure */ +#define HCF_AVAILABLE (2) +#define HCF_CONFIRMHOTKEY (8) +#define HCF_HIGHCONTRASTON (1) +#define HCF_HOTKEYACTIVE (4) +#define HCF_HOTKEYAVAILABLE (64) +#define HCF_HOTKEYSOUND (16) +#define HCF_INDICATOR (32) + +/* TOGGLEKEYS structure */ +#define TKF_AVAILABLE (2) +#define TKF_CONFIRMHOTKEY (8) +#define TKF_HOTKEYACTIVE (4) +#define TKF_HOTKEYSOUND (16) +#define TKF_TOGGLEKEYSON (1) + +/* Installable Policy */ +#define PP_DISPLAYERRORS (1) + +/* SERVICE_INFO structure */ +#define RESOURCEDISPLAYTYPE_DOMAIN (1) +#define RESOURCEDISPLAYTYPE_FILE (4) +#define RESOURCEDISPLAYTYPE_GENERIC (0) +#define RESOURCEDISPLAYTYPE_GROUP (5) +#define RESOURCEDISPLAYTYPE_SERVER (2) +#define RESOURCEDISPLAYTYPE_SHARE (3) + +/* BITMAPINFOHEADER structure */ +#define BI_RGB (0L) +#define BI_RLE8 (1L) +#define BI_RLE4 (2L) +#define BI_BITFIELDS (3L) + +/* Extensions to OpenGL */ + +/* ChoosePixelFormat */ +#define PFD_DRAW_TO_WINDOW (0x4) +#define PFD_DRAW_TO_BITMAP (0x8) +#define PFD_SUPPORT_GDI (0x10) +#define PFD_SUPPORT_OPENGL (0x20) +#define PFD_DOUBLEBUFFER (0x1) +#define PFD_STEREO (0x2) +#define PFD_DOUBLEBUFFER_DONTCARE (0x40000000) +#define PFD_STEREO_DONTCARE (0x80000000) +#define PFD_TYPE_RGBA (0) +#define PFD_TYPE_COLORINDEX (1) +#define PFD_MAIN_PLANE (0) +#define PFD_OVERLAY_PLANE (1) +#define PFD_UNDERLAY_PLANE (-1) + +/* wglUseFontOutlines */ +#define WGL_FONT_LINES (0) +#define WGL_FONT_POLYGONS (1) + +/* LAYERPLANEDESCRIPTOR structure */ + +/* PIXELFORMATDESCRIPTOR structure */ +#define PFD_GENERIC_FORMAT (0x40) +#define PFD_NEED_PALETTE (0x80) +#define PFD_NEED_SYSTEM_PALETTE (0x100) +#define PFD_SWAP_COPY (0x400) +#define PFD_SWAP_EXCHANGE (0x200) + +/* TEXTMETRIC structure */ +#define TMPF_FIXED_PITCH (0x1) +#define TMPF_VECTOR (0x2) +#define TMPF_TRUETYPE (0x4) +#define TMPF_DEVICE (0x8) + +/* --------------------- old stuff, need to organize! --------------- */ + +/* BEGINNING of windowsx.h stuff from old headers: */ +#define __CRACK_VOID_F(fn,args) (void)(fn args) +#define __CRACK_BOOL_F(fn,args) (BOOL)(fn args) +#define __CRACK_HMENU_F(fn,args) (HMENU)(fn args) +#define __CRACK_HWND_F(fn,args) (HWND)(fn args) +#define __CRACK_LONG_F(fn, args) (LRESULT)(fn args) +#define __CRACK_ZERO_F(fn, args) (fn args,0) +#define GetFirstChild(h) GetTopWindow(h) +#define GetNextSibling(h) GetWindow(h, GW_HWNDNEXT) +#define GetWindowID(h) GetDlgCtrlID(h) +#define SubclassWindow(h, p) (SetWindowLong(h, GWL_WNDPROC, p)) + +#define GET_WM_COMMAND_CMD(w, l) HIWORD(w) +#define GET_WM_COMMAND_ID(w, l) LOWORD(w) +#define GET_WM_CTLCOLOR_HDC(w, l, msg) (HDC)(w) +#define GET_WM_CTLCOLOR_HWND(w, l, msg) (HWND)(l) +#define GET_WM_HSCROLL_CODE(w, l) LOWORD(w) +#define GET_WM_HSCROLL_HWND(w, l) (HWND)(l) +#define GET_WM_HSCROLL_POS(w, l) HIWORD(w) +#define GET_WM_MDIACTIVATE_FACTIVATE(h, a, b) (b == (LONG)h) +#define GET_WM_MDIACTIVATE_HWNDACTIVATE(a, b) (HWND)(b) +#define GET_WM_MDIACTIVATE_HWNDDEACT(a, b) (HWND)(a) +#define GET_WM_VSCROLL_CODE(w, l) LOWORD(w) +#define GET_WM_VSCROLL_HWND(w, l) (HWND)(l) +#define GET_WM_VSCROLL_POS(w, l) HIWORD(w) + +#define FORWARD_WM_CLOSE(h, fn) __CRACK_VOID_F(fn,(h, WM_CLOSE, 0, 0)) +#define FORWARD_WM_COMMAND(h, id, c, n, fn) __CRACK_VOID_F(fn,(h, WM_COMMAND, MAKEWPARAM(id,n), (LPARAM)c)) +#define FORWARD_WM_CREATE(h, p, fn) __CRACK_BOOL_F(fn,(h, WM_CREATE, 0, (LPARAM)p)) +#define FORWARD_WM_DESTROY(h, fn) __CRACK_VOID_F(fn,(h, WM_DESTROY, 0, 0)) +#define FORWARD_WM_ENABLE(h, e, fn) __CRACK_VOID_F(fn,(h, WM_ENABLE, (WPARAM)e, 0)) +#define FORWARD_WM_INITDIALOG(h, c, l, fn) __CRACK_BOOL_F(fn,(h, WM_INITDIALOG, (WPARAM)c, l)) +#define FORWARD_WM_MDICASCADE(h, c, fn) __CRACK_BOOL_F(fn,(h, WM_MDICASCADE, (WPARAM)c, 0)) +#define FORWARD_WM_MDIDESTROY(h, d, fn) __CRACK_VOID_F(fn,(h, WM_MDIDESTROY, (WPARAM)d, 0)) +#define FORWARD_WM_MDIGETACTIVE(h, fn) __CRACK_HWND_F(fn,(h, WM_MDIGETACTIVE, 0, 0)) +#define FORWARD_WM_MDIICONARRANGE(h, fn) __CRACK_VOID_F(fn,(h, WM_MDIICONARRANGE, 0, 0)) +#define FORWARD_WM_MDISETMENU(h, fr, hf, hw, fn) __CRACK_HMENU_F(fn,(h, WM_MDISETMENU, (WPARAM)((fr) ? (hf) : 0), (LPARAM)(hw))) +#define FORWARD_WM_MDITILE(h, c, fn) __CRACK_BOOL_F(fn,(h, WM_MDITILE, (WPARAM)(c), 0)) +#define FORWARD_WM_PAINT(h, fn) __CRACK_VOID_F(fn,(h, WM_PAINT, 0, 0)) +#define FORWARD_WM_QUERYENDSESSION(h, fn) __CRACK_BOOL_F(fn,(h, WM_QUERYENDSESSION, 0, 0)) +#define FORWARD_WM_SIZE(h, state, cx, cy, fn) __CRACK_VOID_F(fn,(h, WM_SIZE, (WPARAM)state, MAKELPARAM(cx, cy))) +#define FORWARD_WM_SYSCOMMAND(h, c, x, y, fn) __CRACK_VOID_F(fn,(h, WM_SYSCOMMAND, (WPARAM)c, MAKELPARAM(x, y))) + +#define HANDLE_WM_CLOSE(h, w, l, fn) __CRACK_ZERO_F(fn,(h)); +#define HANDLE_WM_COMMAND(h, w, l, fn) __CRACK_ZERO_F(fn,(h, SEXT_LOWORD(w), (HWND)l, HIWORD(w))) +#define HANDLE_WM_CREATE(h, w, l, fn) (LRESULT)((fn(h, (CREATESTRUCT *)l)) ? 0 : -1) +#define HANDLE_WM_DESTROY(h, w, l, fn) __CRACK_ZERO_F(fn,(h)) +#define HANDLE_WM_ENABLE(h, w, l, fn) __CRACK_ZERO_F(fn,(h, (BOOL)w)) +#define HANDLE_WM_INITDIALOG(h, w, l, fn) __CRACK_LONG_F(fn,(h, (HWND)w, l)) +#define HANDLE_WM_MDICASCADE(h, w, l, fn) __CRACK_LONG_F(fn, (h, (UINT)w) +#define HANDLE_WM_MDIDESTROY(h, w, l, fn) __CRACK_ZERO_F(fn,(h, (HWND)w)) +#define HANDLE_WM_MDIGETACTIVE(h, w, l, fn) __CRACK_LONG_F(fn,(h)) +#define HANDLE_WM_MDIICONARRANGE(h, w, l, fn) __CRACK_ZERO_F(fn,(h)) +#define HANDLE_WM_MDISETMENU(h, w, l, fn) __CRACK_LONG_F(fn,(h, (BOOL)w, (HMENU)w, (HMENU)l) +#define HANDLE_WM_MDITILE(h, w, l, fn) __CRACK_LONG_F(fn,(h, (UINT)w)) +#define HANDLE_WM_PAINT(h, w, l, fn) __CRACK_ZERO_F(fn,(h)) +#define HANDLE_WM_QUERYENDSESSION(h, w, l, fn) MAKELRESULT(fn(h), 0) +#define HANDLE_WM_SIZE(h, w, l, fn) __CRACK_ZERO_F(fn,(h, (UINT)w, SEXT_LOWORD(l), SEXT_HIWORD(l))) +#define HANDLE_WM_SYSCOMMAND(h, w, l, fn) __CRACK_ZERO_F(fn,(h, (UINT)w, SEXT_LOWORD(l), SEXT_HIWORD(l))) + +/* Totally disgusting! get wParam and lParam from the environment ! */ +#define HANDLE_MSG(h, message, fn) case message: return HANDLE_##message(h, wParam, lParam, fn) + +/* END OF windowsx.h stuff from old headers */ +/* ------------------------------------------------------------------ */ +/* BEGINNING of shellapi.h stuff from old headers */ + +#define SE_ERR_SHARE 26 +#define SE_ERR_ASSOCINCOMPLETE 27 +#define SE_ERR_DDETIMEOUT 28 +#define SE_ERR_DDEFAIL 29 +#define SE_ERR_DDEBUSY 30 +#define SE_ERR_NOASSOC 31 + +/* END OF shellapi.h stuff from old headers */ +/* ------------------------------------------------------------------ */ +/* From ddeml.h in old Cygnus headers */ + +#define XCLASS_BOOL 0x1000 +#define XCLASS_DATA 0x2000 +#define XCLASS_FLAGS 0x4000 +#define XCLASS_MASK 0xfc00 +#define XCLASS_NOTIFICATION 0x8000 +#define XTYPF_NOBLOCK 0x0002 +#define XTYP_ADVDATA 0x4010 +#define XTYP_ADVREQ 0x2022 +#define XTYP_ADVSTART 0x1030 +#define XTYP_ADVSTOP 0x8040 +#define XTYP_CONNECT 0x1062 +#define XTYP_CONNECT_CONFIRM 0x8072 +#define XTYP_DISCONNECT 0x80c2 +#define XTYP_EXECUTE 0x4050 +#define XTYP_POKE 0x4090 +#define XTYP_REQUEST 0x20b0 +#define XTYP_WILDCONNECT 0x20E2 +#define XTYP_REGISTER 0x80A2 +#define XTYP_ERROR 0x8002 +#define XTYP_XACT_COMPLETE 0x8080 +#define XTYP_UNREGISTER 0x80D2 + +#define DMLERR_DLL_USAGE 0x4004 +#define DMLERR_INVALIDPARAMETER 0x4006 +#define DMLERR_NOTPROCESSED 0x4009 +#define DMLERR_POSTMSG_FAILED 0x400c +#define DMLERR_SERVER_DIED 0x400e +#define DMLERR_SYS_ERROR 0x400f +#define DMLERR_BUSY 0x4001 +#define DMLERR_DATAACKTIMEOUT 0x4002 +#define DMLERR_ADVACKTIMEOUT 0x4000 +#define DMLERR_DLL_NOT_INITIALIZED 0x4003 +#define DMLERR_LOW_MEMORY 0x4007 +#define DMLERR_MEMORY_ERROR 0x4008 +#define DMLERR_POKEACKTIMEOUT 0x400b +#define DMLERR_NO_CONV_ESTABLISHED 0x400a +#define DMLERR_REENTRANCY 0x400d +#define DMLERR_UNFOUND_QUEUE_ID 0x4011 +#define DMLERR_UNADVACKTIMEOUT 0x4010 +#define DMLERR_EXECACKTIMEOUT 0x4005 +#define DDE_FACK 0x8000 +#define DDE_FNOTPROCESSED 0x0000 + +#define DNS_REGISTER 0x0001 +#define DNS_UNREGISTER 0x0002 +#define CP_WINANSI 1004 +#define CP_WINUNICODE 1200 +#define EXPENTRY CALLBACK +#define APPCLASS_STANDARD 0x00000000 + +/* End of stuff from ddeml.h in old Cygnus headers */ +/* ----------------------------------------------- */ + +#define BKMODE_LAST (2) + +#define CTLCOLOR_MSGBOX (0) +#define CTLCOLOR_EDIT (1) +#define CTLCOLOR_LISTBOX (2) +#define CTLCOLOR_BTN (3) +#define CTLCOLOR_DLG (4) +#define CTLCOLOR_SCROLLBAR (5) +#define CTLCOLOR_STATIC (6) +#define CTLCOLOR_MAX (7) + +#define META_SETMAPMODE (0x0103L) +#define META_SETWINDOWORG (0x020BL) +#define META_SETWINDOWEXT (0x020CL) + +#define POLYFILL_LAST (2) + + +#define EXCEPTION_CTRL_C + +#define PROCESSOR_ARCHITECTURE_INTEL 0 +#define PROCESSOR_ARCHITECTURE_MIPS 1 +#define PROCESSOR_ARCHITECTURE_ALPHA 2 +#define PROCESSOR_ARCHITECTURE_PPC 3 + +#define FreeModule(h) FreeLibrary(h) +#define MakeProcInstance(p,i) (p) +#define FreeProcInstance(p) (p) + +#define _fmemcpy memcpy + +/* Used by wxwindows. */ +#define SIZEFULLSCREEN SIZE_MAXIMIZED +#define SIZENORMAL SIZE_RESTORED +#define SIZEICONIC SIZE_MINIMIZED +#define NPLOGPALETTE PLOGPALETTE + +/* In the old winnt.h */ +#if 0 +#ifdef __ANAL__ +#define DECLARE_HANDLE(h) struct h##__ { int dummy; }; typedef struct h##__ *h +#else +#define DECLARE_HANDLE(h) typedef void *h +#endif +DECLARE_HANDLE(HANDLE); +#endif + +#ifdef __PPC__ +#define CONTEXT_CONTROL 1L +#define CONTEXT_FLOATING_POINT 2L +#define CONTEXT_INTEGER 4L +#define CONTEXT_DEBUG_REGISTERS 8L + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +#define CONTEXT_DEBUGGER (CONTEXT_FULL) + +#else /* x86 */ +/* The doc refered me to winnt.h, so I had to look... */ +#define SIZE_OF_80387_REGISTERS 80 + +/* Values for contextflags */ +#define CONTEXT_i386 0x10000 +#define CONTEXT_CONTROL (CONTEXT_i386 | 1) +#define CONTEXT_INTEGER (CONTEXT_i386 | 2) +#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4) +#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10) +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) + +/* our own invention */ +#define FLAG_TRACE_BIT 0x100 +#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT) + +#endif + +#define ASCIICHAR AsciiChar +#define FAR + +#define FILTER_TEMP_DUPLICATE_ACCOUNT (0x0001) +#define FILTER_NORMAL_ACCOUNT (0x0002) +#define FILTER_INTERDOMAIN_TRUST_ACCOUNT (0x0008) +#define FILTER_WORKSTATION_TRUST_ACCOUNT (0x0010) +#define FILTER_SERVER_TRUST_ACCOUNT (0x0020) + +#define LOGON32_LOGON_INTERACTIVE (0x02) +#define LOGON32_LOGON_BATCH (0x04) +#define LOGON32_LOGON_SERVICE (0x05) +#define LOGON32_PROVIDER_DEFAULT (0x00) +#define LOGON32_PROVIDER_WINNT35 (0x01) + +#define QID_SYNC 0xFFFFFFFF + + +/* To mark direction in formal parameters list */ + +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef OPTIONAL +#define OPTIONAL +#endif + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* WIN32_LEAN_AND_MEAN */ + +#endif /* _GNU_H_WINDOWS32_DEFINES */ diff --git a/include/devices.h b/include/devices.h new file mode 100644 index 0000000..ada5eb8 --- /dev/null +++ b/include/devices.h @@ -0,0 +1,16 @@ +typedef struct +{ + LPSTR LeftVolumeName; + LPSTR RightVolumeName; + ULONG DefaultVolume; + ULONG Type; + ULONG DeviceType; + char Key[4]; + LPSTR PrototypeName; + PVOID DeferredRoutine; + PVOID ExclusionRoutine; + PVOID DispatchRoutine; + PVOID DevCapsRoutine; + PVOID HwSetVolume; + ULONG IoMethod; +}SOUND_DEVICE_INIT; diff --git a/include/dflat32/classdef.h b/include/dflat32/classdef.h new file mode 100644 index 0000000..086ee49 --- /dev/null +++ b/include/dflat32/classdef.h @@ -0,0 +1,31 @@ +/* ---------------- classdef.h --------------- */ + +#ifndef CLASSDEF_H +#define CLASSDEF_H + +typedef struct classdefs { + DFCLASS base; /* base window class */ + int (*wndproc)(struct window *,enum messages,PARAM,PARAM); + int attrib; +} CLASSDEFS; + +extern CLASSDEFS classdefs[]; + +#define SHADOW 0x0001 +#define MOVEABLE 0x0002 +#define SIZEABLE 0x0004 +#define HASMENUBAR 0x0008 +#define VSCROLLBAR 0x0010 +#define HSCROLLBAR 0x0020 +#define VISIBLE 0x0040 +#define SAVESELF 0x0080 +#define HASTITLEBAR 0x0100 +#define CONTROLBOX 0x0200 +#define MINMAXBOX 0x0400 +#define NOCLIP 0x0800 +#define READONLY 0x1000 +#define MULTILINE 0x2000 +#define HASBORDER 0x4000 +#define HASSTATUSBAR 0x8000 + +#endif diff --git a/include/dflat32/classes.h b/include/dflat32/classes.h new file mode 100644 index 0000000..74fceb9 --- /dev/null +++ b/include/dflat32/classes.h @@ -0,0 +1,56 @@ +/* ----------- classes.h ------------ */ +/* + * Class definition source file + * Make class changes to this source file + * Other source files will adapt + * + * You must add entries to the color tables in + * CONFIG.C for new classes. + * + * Class Name Base Class Processor Attribute + * ------------ --------- --------------- ----------- + */ +ClassDef( NORMAL, -1, NormalProc, 0 ) +ClassDef( APPLICATION, NORMAL, ApplicationProc, VISIBLE | + SAVESELF | + CONTROLBOX ) +ClassDef( TEXTBOX, NORMAL, TextBoxProc, 0 ) +//ClassDef( LISTBOX, TEXTBOX, ListBoxProc, 0 ) +ClassDef( EDITBOX, TEXTBOX, EditBoxProc, 0 ) +ClassDef( MENUBAR, NORMAL, MenuBarProc, NOCLIP ) +ClassDef( POPDOWNMENU, LISTBOX, PopDownProc, SAVESELF | + NOCLIP | + HASBORDER ) +#ifdef INCLUDE_PICTUREBOX +ClassDef( PICTUREBOX, TEXTBOX, PictureProc, 0 ) +#endif +ClassDef( DIALOG, NORMAL, DialogProc, SHADOW | + MOVEABLE | + CONTROLBOX| + HASBORDER | + NOCLIP ) +ClassDef( BOX, NORMAL, BoxProc, HASBORDER ) +//ClassDef( BUTTON, TEXTBOX, ButtonProc, SHADOW ) +//ClassDef( COMBOBOX, EDITBOX, ComboProc, 0 ) +ClassDef( TEXT, TEXTBOX, TextProc, 0 ) +ClassDef( RADIOBUTTON, TEXTBOX, RadioButtonProc, 0 ) +ClassDef( CHECKBOX, TEXTBOX, CheckBoxProc, 0 ) +ClassDef( SPINBUTTON, LISTBOX, SpinButtonProc, 0 ) +ClassDef( ERRORBOX, DIALOG, NULL, SHADOW | + HASBORDER ) +ClassDef( MESSAGEBOX, DIALOG, NULL, SHADOW | + HASBORDER ) +ClassDef( HELPBOX, DIALOG, HelpBoxProc, MOVEABLE | + SAVESELF | + HASBORDER | + NOCLIP | + CONTROLBOX ) +ClassDef( STATUSBAR, TEXTBOX, StatusBarProc, NOCLIP ) + +/* + * ========> Add new classes here <======== + */ + +/* ---------- pseudo classes to create enums, etc. ---------- */ +ClassDef( TITLEBAR, -1, NULL, 0 ) +ClassDef( DUMMY, -1, NULL, HASBORDER ) diff --git a/include/dflat32/commands.h b/include/dflat32/commands.h new file mode 100644 index 0000000..6850ac6 --- /dev/null +++ b/include/dflat32/commands.h @@ -0,0 +1,121 @@ +/* ---------------- commands.h ----------------- */ + +/* + * Command values sent as the first parameter + * in the COMMAND message + * + * Add application-specific commands to this enum + */ + +#ifndef COMMANDS_H +#define COMMANDS_H + +enum commands { + /* --------------- File menu ---------------- */ + ID_OPEN, + ID_NEW, + ID_SAVE, + ID_SAVEAS, + ID_DELETEFILE, + ID_PRINT, + ID_PRINTSETUP, + ID_DOS, + ID_EXIT, + /* --------------- Edit menu ---------------- */ + ID_UNDO, + ID_CUT, + ID_COPY, + ID_PASTE, + ID_PARAGRAPH, + ID_CLEAR, + ID_DELETETEXT, + /* --------------- Search Menu -------------- */ + ID_SEARCH, + ID_REPLACE, + ID_SEARCHNEXT, + /* --------------- Utilities Menu ------------- */ + ID_CALENDAR, + ID_BARCHART, + /* -------------- Options menu -------------- */ + ID_INSERT, + ID_WRAP, + ID_LOG, + ID_TABS, + ID_DISPLAY, + ID_SAVEOPTIONS, + /* --------------- Window menu -------------- */ + ID_CLOSEALL, + ID_WINDOW, + ID_MOREWINDOWS, + /* --------------- Help menu ---------------- */ + ID_HELPHELP, + ID_EXTHELP, + ID_KEYSHELP, + ID_HELPINDEX, + ID_ABOUT, + ID_LOADHELP, + /* --------------- System menu -------------- */ +#ifdef INCLUDE_RESTORE + ID_SYSRESTORE, +#endif + ID_SYSMOVE, + ID_SYSSIZE, +#ifdef INCLUDE_MINIMIZE + ID_SYSMINIMIZE, +#endif +#ifdef INCLUDE_MAXIMIZE + ID_SYSMAXIMIZE, +#endif + ID_SYSCLOSE, + /* ---- FileOpen and SaveAs dialog boxes ---- */ + ID_FILENAME, + ID_FILES, + ID_DRIVE, + ID_PATH, + /* ----- Search and Replace dialog boxes ---- */ + ID_SEARCHFOR, + ID_REPLACEWITH, + ID_MATCHCASE, + ID_REPLACEALL, + /* ----------- Windows dialog box ----------- */ + ID_WINDOWLIST, + /* --------- generic command buttons -------- */ + ID_OK, + ID_CANCEL, + ID_HELP, + /* -------------- TabStops menu ------------- */ + ID_TAB2, + ID_TAB4, + ID_TAB6, + ID_TAB8, + /* ------------ Display dialog box ---------- */ + ID_BORDER, + ID_TITLE, + ID_STATUSBAR, + ID_TEXTURE, + ID_SNOWY, + ID_COLOR, + ID_MONO, + ID_REVERSE, + ID_25LINES, + ID_43LINES, + ID_50LINES, + /* ------------- Log dialog box ------------- */ + ID_LOGLIST, + ID_LOGGING, + /* ------------ HelpBox dialog box ---------- */ + ID_HELPTEXT, + ID_BACK, + ID_PREV, + ID_NEXT, + /* ---------- Print Select dialog box --------- */ + ID_PRINTERPORT, + ID_LEFTMARGIN, + ID_RIGHTMARGIN, + ID_TOPMARGIN, + ID_BOTTOMMARGIN, + /* ----------- InputBox dialog box ------------ */ + ID_INPUTTEXT +}; + +#endif diff --git a/include/dflat32/config.h b/include/dflat32/config.h new file mode 100644 index 0000000..065e197 --- /dev/null +++ b/include/dflat32/config.h @@ -0,0 +1,48 @@ +/* ---------------- config.h -------------- */ + +#ifndef CONFIG_H +#define CONFIG_H + +enum colortypes { + STD_COLOR, + SELECT_COLOR, + FRAME_COLOR, + HILITE_COLOR +}; + +enum grounds { FG, BG }; + +/* ----------- configuration parameters ----------- */ +typedef struct config { + char version[sizeof VERSION]; + BOOL InsertMode; /* Editor insert mode */ + int Tabs; /* Editor tab stops */ + BOOL WordWrap; /* True to word wrap editor */ +#ifdef INCLUDE_WINDOWOPTIONS + BOOL Border; /* True for application window border */ + BOOL Title; /* True for application window title */ + BOOL StatusBar; /* True for appl'n window status bar */ + BOOL Texture; /* True for textured appl window */ +#endif +// int ScreenLines; /* Number of screen lines (25/43/50) */ + char PrinterPort[5]; + int LinesPage; /* Lines per printer page */ + int CharsLine; /* Characters per printer line */ + int LeftMargin; /* Printer margins */ + int RightMargin; + int TopMargin; + int BottomMargin; + unsigned char clr[CLASSCOUNT] [4] [2]; /* Colors */ +} CONFIG; + +extern CONFIG cfg; +extern unsigned char color[CLASSCOUNT] [4] [2]; +extern unsigned char bw[CLASSCOUNT] [4] [2]; +extern unsigned char reverse[CLASSCOUNT] [4] [2]; + +BOOL LoadConfig(void); +void SaveConfig(void); +FILE *OpenConfig(char *); + +#endif + diff --git a/include/dflat32/dflat.h b/include/dflat32/dflat.h new file mode 100644 index 0000000..0d3ec41 --- /dev/null +++ b/include/dflat32/dflat.h @@ -0,0 +1,487 @@ +/* ------------- dflat.h ----------- */ +#ifndef DFLAT_H +#define DFLAT_H + +//#ifdef BUILD_FULL_DFLAT +#define INCLUDE_MULTI_WINDOWS +#define INCLUDE_LOGGING +#define INCLUDE_SHELLDOS +#define INCLUDE_WINDOWOPTIONS +#define INCLUDE_PICTUREBOX +#define INCLUDE_MINIMIZE +#define INCLUDE_MAXIMIZE +#define INCLUDE_RESTORE +#define INCLUDE_EXTENDEDSELECTIONS +//#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef VERSION +#define VERSION "Beta Version 0.3" +#endif + +void *DFcalloc(size_t, size_t); +void *DFmalloc(size_t); +void *DFrealloc(void *, size_t); + + +#define MAXMESSAGES 50 +#define DELAYTICKS 1 +#define FIRSTDELAY 7 +#define DOUBLETICKS 5 + +#define MAXTEXTLEN 65000U /* maximum text buffer */ +#define EDITLEN 1024 /* starting length for multiliner */ +#define ENTRYLEN 256 /* starting length for one-liner */ +#define GROWLENGTH 64 /* buffers grow by this much */ + +#include "system.h" +#include "config.h" +#include "rect.h" +#include "menu.h" +#include "keys.h" +#include "commands.h" +#include "dialbox.h" + +/* ------ integer type for message parameters ----- */ +typedef long PARAM; + +enum Condition +{ + ISRESTORED, ISMINIMIZED, ISMAXIMIZED, ISCLOSING +}; + +typedef struct window +{ + DFCLASS class; /* window class */ + char *title; /* window title */ + int (*wndproc)(struct window *, enum messages, PARAM, PARAM); + + /* ----------------- window colors -------------------- */ + char WindowColors[4][2]; + + /* ---------------- window dimensions ----------------- */ + DFRECT rc; /* window coordinates (0/0 to 79/24) */ + int ht, wd; /* window height and width */ + DFRECT RestoredRC; /* restored condition rect */ + + /* -------------- linked list pointers ---------------- */ + struct window *parent; /* parent window */ + struct window *firstchild; /* first child this parent */ + struct window *lastchild; /* last child this parent */ + struct window *nextsibling; /* next sibling */ + struct window *prevsibling; /* previous sibling */ + struct window *childfocus; /* child that ha(s/d) focus */ + + int attrib; /* Window attributes */ + PCHAR_INFO videosave; /* video save buffer */ + enum Condition condition; /* Restored, Maximized, + Minimized, Closing */ + enum Condition oldcondition;/* previous condition */ + int restored_attrib; /* attributes when restored */ + void *extension; /* menus, dialogs, documents, etc */ + struct window *PrevMouse; + struct window *PrevKeyboard; + struct window *MenuBarWnd;/* menu bar */ + struct window *StatusBar; /* status bar */ + int isHelping; /* > 0 when help is being displayed */ + + /* ----------------- text box fields ------------------ */ + int wlines; /* number of lines of text */ + int wtop; /* text line that is on the top display */ + unsigned char *text; /* window text */ + unsigned int textlen; /* text length */ + int wleft; /* left position in window viewport */ + int textwidth; /* width of longest line in textbox */ + int BlkBegLine; /* beginning line of marked block */ + int BlkBegCol; /* beginning column of marked block */ + int BlkEndLine; /* ending line of marked block */ + int BlkEndCol; /* ending column of marked block */ + int HScrollBox; /* position of horizontal scroll box */ + int VScrollBox; /* position of vertical scroll box */ + unsigned int *TextPointers; /* -> list of line offsets */ + + /* ----------------- list box fields ------------------ */ + int selection; /* current selection */ + BOOL AddMode; /* adding extended selections mode */ + int AnchorPoint;/* anchor point for extended selections */ + int SelectCount;/* count of selected items */ + + /* ----------------- edit box fields ------------------ */ + int CurrCol; /* Current column */ + int CurrLine; /* Current line */ + int WndRow; /* Current window row */ + BOOL TextChanged; /* TRUE if text has changed */ + unsigned char *DeletedText; /* for undo */ + unsigned DeletedLength; /* Length of deleted field */ + BOOL InsertMode; /* TRUE or FALSE for text insert */ + BOOL WordWrapMode; /* TRUE or FALSE for word wrap */ + unsigned int MaxTextLength; /* maximum text length */ + + /* ---------------- dialog box fields ----------------- */ + int ReturnCode; /* return code from a dialog box */ + BOOL Modal; /* True if a modeless dialog box */ + CTLWINDOW *ct; /* control structure */ + struct window *dfocus; /* control window that has focus */ + /* -------------- popdownmenu fields ------------------ */ + MENU *mnu; /* points to menu structure */ + MBAR *holdmenu; /* previous active menu */ + struct window *oldFocus; + + /* --------------- help box fields -------------------- */ + void *firstword; /* -> first in list of key words */ + void *lastword; /* -> last in list of key words */ + void *thisword; /* -> current in list of key words */ + /* -------------- status bar fields ------------------- */ + BOOL TimePosted; /* True if time has been posted */ +#ifdef INCLUDE_PICTUREBOX + /* ------------- picture box fields ------------------- */ + int VectorCount; /* number of vectors in vector list */ + void *VectorList; /* list of picture box vectors */ +#endif +} * DFWINDOW; + +#include "classdef.h" +#include "video.h" + +void LogMessages (DFWINDOW, DFMESSAGE, PARAM, PARAM); +void MessageLog(DFWINDOW); +/* ------- window methods ----------- */ +#define ICONHEIGHT 3 +#define ICONWIDTH 10 +#define WindowHeight(w) ((w)->ht) +#define WindowWidth(w) ((w)->wd) +#define BorderAdj(w) (TestAttribute(w,HASBORDER)?1:0) +#define BottomBorderAdj(w) (TestAttribute(w,HASSTATUSBAR)?1:BorderAdj(w)) +#define TopBorderAdj(w) ((TestAttribute(w,HASTITLEBAR) && \ + TestAttribute(w,HASMENUBAR)) ? \ + 2 : (TestAttribute(w,HASTITLEBAR | \ + HASMENUBAR | HASBORDER) ? 1 : 0)) +#define ClientWidth(w) (WindowWidth(w)-BorderAdj(w)*2) +#define ClientHeight(w) (WindowHeight(w)-TopBorderAdj(w)-\ + BottomBorderAdj(w)) +#define WindowRect(w) ((w)->rc) +#define GetTop(w) (RectTop(WindowRect(w))) +#define GetBottom(w) (RectBottom(WindowRect(w))) +#define GetLeft(w) (RectLeft(WindowRect(w))) +#define GetRight(w) (RectRight(WindowRect(w))) +#define GetClientTop(w) (GetTop(w)+TopBorderAdj(w)) +#define GetClientBottom(w) (GetBottom(w)-BottomBorderAdj(w)) +#define GetClientLeft(w) (GetLeft(w)+BorderAdj(w)) +#define GetClientRight(w) (GetRight(w)-BorderAdj(w)) +#define GetTitle(w) ((w)->title) +#define GetParent(w) ((w)->parent) +#define FirstWindow(w) ((w)->firstchild) +#define LastWindow(w) ((w)->lastchild) +#define NextWindow(w) ((w)->nextsibling) +#define PrevWindow(w) ((w)->prevsibling) +#define GetClass(w) ((w)->class) +#define GetAttribute(w) ((w)->attrib) +#define AddAttribute(w,a) (GetAttribute(w) |= a) +#define ClearAttribute(w,a) (GetAttribute(w) &= ~(a)) +#define TestAttribute(w,a) (GetAttribute(w) & (a)) +#define isHidden(w) (!(GetAttribute(w) & VISIBLE)) +#define SetVisible(w) (GetAttribute(w) |= VISIBLE) +#define ClearVisible(w) (GetAttribute(w) &= ~VISIBLE) +#define gotoxy(w,x,y) cursor(w->rc.lf+(x)+1,w->rc.tp+(y)+1) +BOOL isVisible(DFWINDOW); +DFWINDOW DfCreateWindow(DFCLASS,char *,int,int,int,int,void*,DFWINDOW, + int (*)(struct window *,enum messages,PARAM,PARAM),int); +void AddTitle(DFWINDOW, char *); +void InsertTitle(DFWINDOW, char *); +void DisplayTitle(DFWINDOW, DFRECT *); +void RepaintBorder(DFWINDOW, DFRECT *); +void PaintShadow(DFWINDOW); +void ClearWindow(DFWINDOW, DFRECT *, int); +void writeline(DFWINDOW, char *, int, int, BOOL); +void InitWindowColors(DFWINDOW); + +void SetNextFocus(void); +void SetPrevFocus(void); +void RemoveWindow(DFWINDOW); +void AppendWindow(DFWINDOW); +void ReFocus(DFWINDOW); +void SkipApplicationControls(void); + +BOOL CharInView(DFWINDOW, int, int); +void CreatePath(char *, char *, int, int); +#define SwapVideoBuffer(wnd, ish, fh) swapvideo(wnd, wnd->videosave, ish, fh) +int LineLength(char *); +DFRECT AdjustRectangle(DFWINDOW, DFRECT); +BOOL isDerivedFrom(DFWINDOW, DFCLASS); +DFWINDOW GetAncestor(DFWINDOW); +void PutWindowChar(DFWINDOW,char,int,int); +void PutWindowLine(DFWINDOW, void *,int,int); +#define BaseWndProc(class,wnd,msg,p1,p2) \ + (*classdefs[(classdefs[class].base)].wndproc)(wnd,msg,p1,p2) +#define DefaultWndProc(wnd,msg,p1,p2) \ + (classdefs[wnd->class].wndproc == NULL) ? \ + BaseWndProc(wnd->class,wnd,msg,p1,p2) : \ + (*classdefs[wnd->class].wndproc)(wnd,msg,p1,p2) +struct LinkedList { + DFWINDOW FirstWindow; + DFWINDOW LastWindow; +}; +extern DFWINDOW ApplicationWindow; +extern DFWINDOW inFocus; +extern DFWINDOW CaptureMouse; +extern DFWINDOW CaptureKeyboard; +extern int foreground, background; +extern BOOL WindowMoving; +extern BOOL WindowSizing; +extern BOOL VSliding; +extern BOOL HSliding; +extern char DFlatApplication[]; +extern char *Clipboard; +extern unsigned ClipboardLength; +extern BOOL ClipString; +/* --------- space between menubar labels --------- */ +#define MSPACE 2 +/* --------------- border characters ------------- */ +#define FOCUS_NW (unsigned char) '\xc9' +#define FOCUS_NE (unsigned char) '\xbb' +#define FOCUS_SE (unsigned char) '\xbc' +#define FOCUS_SW (unsigned char) '\xc8' +#define FOCUS_SIDE (unsigned char) '\xba' +#define FOCUS_LINE (unsigned char) '\xcd' +#define NW (unsigned char) '\xda' +#define NE (unsigned char) '\xbf' +#define SE (unsigned char) '\xd9' +#define SW (unsigned char) '\xc0' +#define SIDE (unsigned char) '\xb3' +#define LINE (unsigned char) '\xc4' +#define LEDGE (unsigned char) '\xc3' +#define REDGE (unsigned char) '\xb4' +/* ------------- scroll bar characters ------------ */ +#define UPSCROLLBOX (unsigned char) '\x1e' +#define DOWNSCROLLBOX (unsigned char) '\x1f' +#define LEFTSCROLLBOX (unsigned char) '\x11' +#define RIGHTSCROLLBOX (unsigned char) '\x10' +#define SCROLLBARCHAR (unsigned char) 176 +#define SCROLLBOXCHAR (unsigned char) 178 +/* ------------------ menu characters --------------------- */ +#define CHECKMARK (unsigned char) '\x04' //(SCREENHEIGHT==25?251:4) +#define CASCADEPOINTER (unsigned char) '\x10' +/* ----------------- title bar characters ----------------- */ +#define CONTROLBOXCHAR (unsigned char) '\xf0' +#define MAXPOINTER 24 /* maximize token */ +#define MINPOINTER 25 /* minimize token */ +#define RESTOREPOINTER 18 /* restore token */ +/* --------------- text control characters ---------------- */ +#define APPLCHAR (unsigned char) 176 /* fills application window */ +#define SHORTCUTCHAR '~' /* prefix: shortcut key display */ +#define CHANGECOLOR (unsigned char) 174 /* prefix to change colors */ +#define RESETCOLOR (unsigned char) 175 /* reset colors to default */ +#define LISTSELECTOR 4 /* selected list box entry */ + +/* --------- message prototypes ----------- */ +BOOL DfInitialize (void); +void DfTerminate (void); +void DfPostMessage (DFWINDOW, DFMESSAGE, PARAM, PARAM); +int DfSendMessage (DFWINDOW, DFMESSAGE, PARAM, PARAM); +BOOL DfDispatchMessage (void); +void handshake(void); +SHORT DfGetScreenHeight (void); +SHORT DfGetScreenWidth (void); + +/* ---- standard window message processing prototypes ----- */ +int ApplicationProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int NormalProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int TextBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int ListBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int EditBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int PictureProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int MenuBarProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int PopDownProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int ButtonProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int ComboProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int TextProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int RadioButtonProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int CheckBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int SpinButtonProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int BoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int DialogProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int SystemMenuProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int HelpBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int MessageBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int CancelBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int ErrorBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int YesNoBoxProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int StatusBarProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); +int WatchIconProc(DFWINDOW, DFMESSAGE, PARAM, PARAM); + +/* ------------- normal box prototypes ------------- */ +void SetStandardColor(DFWINDOW); +void SetReverseColor(DFWINDOW); +BOOL isAncestor(DFWINDOW, DFWINDOW); +#define HitControlBox(wnd, p1, p2) \ + (TestAttribute(wnd, CONTROLBOX) && \ + p1 == 2 && p2 == 0) +#define WndForeground(wnd) \ + (wnd->WindowColors [STD_COLOR] [FG]) +#define WndBackground(wnd) \ + (wnd->WindowColors [STD_COLOR] [BG]) +#define FrameForeground(wnd) \ + (wnd->WindowColors [FRAME_COLOR] [FG]) +#define FrameBackground(wnd) \ + (wnd->WindowColors [FRAME_COLOR] [BG]) +#define SelectForeground(wnd) \ + (wnd->WindowColors [SELECT_COLOR] [FG]) +#define SelectBackground(wnd) \ + (wnd->WindowColors [SELECT_COLOR] [BG]) +#define HighlightForeground(wnd) \ + (wnd->WindowColors [HILITE_COLOR] [FG]) +#define HighlightBackground(wnd) \ + (wnd->WindowColors [HILITE_COLOR] [BG]) +#define WindowClientColor(wnd, fg, bg) \ + WndForeground(wnd) = fg, WndBackground(wnd) = bg +#define WindowReverseColor(wnd, fg, bg) \ + SelectForeground(wnd) = fg, SelectBackground(wnd) = bg +#define WindowFrameColor(wnd, fg, bg) \ + FrameForeground(wnd) = fg, FrameBackground(wnd) = bg +#define WindowHighlightColor(wnd, fg, bg) \ + HighlightForeground(wnd) = fg, HighlightBackground(wnd) = bg +/* -------- text box prototypes ---------- */ +#define TextLine(wnd, sel) \ + (wnd->text + *((wnd->TextPointers) + sel)) +void WriteTextLine(DFWINDOW, DFRECT *, int, BOOL); +#define TextBlockMarked(wnd) ( wnd->BlkBegLine || \ + wnd->BlkEndLine || \ + wnd->BlkBegCol || \ + wnd->BlkEndCol) +void MarkTextBlock(DFWINDOW, int, int, int, int); +#define ClearTextBlock(wnd) wnd->BlkBegLine = wnd->BlkEndLine = \ + wnd->BlkBegCol = wnd->BlkEndCol = 0; +#define GetText(w) ((w)->text) +#define GetTextLines(w) ((w)->wlines) +void ClearTextPointers(DFWINDOW); +void BuildTextPointers(DFWINDOW); +int TextLineNumber(DFWINDOW, char *); +/* ------------ Clipboard prototypes ------------- */ +void CopyTextToClipboard(char *); +void CopyToClipboard(DFWINDOW); +#define PasteFromClipboard(wnd) PasteText(wnd,Clipboard,ClipboardLength) +BOOL PasteText(DFWINDOW, char *, unsigned); +void ClearClipboard(void); +/* --------- menu prototypes ---------- */ +int CopyCommand(unsigned char *, unsigned char *, int, int); +void PrepFileMenu(void *, struct Menu *); +void PrepEditMenu(void *, struct Menu *); +void PrepSearchMenu(void *, struct Menu *); +void PrepWindowMenu(void *, struct Menu *); +void BuildSystemMenu(DFWINDOW); +BOOL isActive(MBAR *, int); +char *GetCommandText(MBAR *, int); +BOOL isCascadedCommand(MBAR *,int); +void ActivateCommand(MBAR *,int); +void DeactivateCommand(MBAR *,int); +BOOL GetCommandToggle(MBAR *,int); +void SetCommandToggle(MBAR *,int); +void ClearCommandToggle(MBAR *,int); +void InvertCommandToggle(MBAR *,int); +int BarSelection(int); +/* ------------- list box prototypes -------------- */ +BOOL ItemSelected(DFWINDOW, int); +/* ------------- edit box prototypes ----------- */ +#define CurrChar (TextLine(wnd, wnd->CurrLine)+wnd->CurrCol) +#define WndCol (wnd->CurrCol-wnd->wleft) +#define isMultiLine(wnd) TestAttribute(wnd, MULTILINE) +void DfSearchText(DFWINDOW); +void DfReplaceText(DFWINDOW); +void DfSearchNext(DFWINDOW); +/* --------- message box prototypes -------- */ +DFWINDOW SliderBox(int, char *, char *); +BOOL InputBox(DFWINDOW, char *, char *, char *, int); +BOOL GenericMessage(DFWINDOW, char *, char *, int, + int (*)(struct window *, enum messages, PARAM, PARAM), + char *, char *, int, int, int); +#define DfTestErrorMessage(msg) \ + GenericMessage(NULL, "Error", msg, 2, ErrorBoxProc, \ + Ok, Cancel, ID_OK, ID_CANCEL, TRUE) +#define DfErrorMessage(msg) \ + GenericMessage(NULL, "Error", msg, 1, ErrorBoxProc, \ + Ok, NULL, ID_OK, 0, TRUE) +#define DfMessageBox(ttl, msg) \ + GenericMessage(NULL, ttl, msg, 1, MessageBoxProc, \ + Ok, NULL, ID_OK, 0, TRUE) +#define DfYesNoBox(msg) \ + GenericMessage(NULL, NULL, msg, 2, YesNoBoxProc, \ + Yes, No, ID_OK, ID_CANCEL, TRUE) +#define DfCancelBox(wnd, msg) \ + GenericMessage(wnd, "Wait...", msg, 1, CancelBoxProc, \ + Cancel, NULL, ID_CANCEL, 0, FALSE) +void CloseCancelBox(void); +DFWINDOW MomentaryMessage(char *); +int MsgHeight(char *); +int MsgWidth(char *); + +/* ------------- dialog box prototypes -------------- */ +BOOL DfDialogBox(DFWINDOW, DBOX *, BOOL, + int (*)(struct window *, enum messages, PARAM, PARAM)); +void ClearDialogBoxes(void); +BOOL OpenFileDialogBox(char *, char *); +BOOL SaveAsDialogBox(char *); +void GetDlgListText(DFWINDOW, char *, enum commands); +BOOL DfDlgDirList(DFWINDOW, char *, enum commands, + enum commands, unsigned); +BOOL RadioButtonSetting(DBOX *, enum commands); +void PushRadioButton(DBOX *, enum commands); +void PutItemText(DFWINDOW, enum commands, char *); +void PutComboListText(DFWINDOW, enum commands, char *); +void GetItemText(DFWINDOW, enum commands, char *, int); +char *GetDlgTextString(DBOX *, enum commands, DFCLASS); +void SetDlgTextString(DBOX *, enum commands, char *, DFCLASS); +BOOL CheckBoxSetting(DBOX *, enum commands); +CTLWINDOW *FindCommand(DBOX *, enum commands, int); +DFWINDOW ControlWindow(DBOX *, enum commands); +void SetScrollBars(DFWINDOW); +void SetRadioButton(DBOX *, CTLWINDOW *); +void ControlSetting(DBOX *, enum commands, int, int); +void SetFocusCursor(DFWINDOW); + +#define GetControl(wnd) (wnd->ct) +#define GetDlgText(db, cmd) GetDlgTextString(db, cmd, TEXT) +#define GetDlgTextBox(db, cmd) GetDlgTextString(db, cmd, TEXTBOX) +#define GetEditBoxText(db, cmd) GetDlgTextString(db, cmd, EDITBOX) +#define GetComboBoxText(db, cmd) GetDlgTextString(db, cmd, COMBOBOX) +#define SetDlgText(db, cmd, s) SetDlgTextString(db, cmd, s, TEXT) +#define SetDlgTextBox(db, cmd, s) SetDlgTextString(db, cmd, s, TEXTBOX) +#define SetEditBoxText(db, cmd, s) SetDlgTextString(db, cmd, s, EDITBOX) +#define SetComboBoxText(db, cmd, s) SetDlgTextString(db, cmd, s, COMBOBOX) +#define SetDlgTitle(db, ttl) ((db)->dwnd.title = ttl) +#define SetCheckBox(db, cmd) ControlSetting(db, cmd, CHECKBOX, ON) +#define ClearCheckBox(db, cmd) ControlSetting(db, cmd, CHECKBOX, OFF) +#define EnableButton(db, cmd) ControlSetting(db, cmd, BUTTON, ON) +#define DisableButton(db, cmd) ControlSetting(db, cmd, BUTTON, OFF) + +/* ---- types of vectors that can be in a picture box ------- */ +enum VectTypes {VECTOR, SOLIDBAR, HEAVYBAR, CROSSBAR, LIGHTBAR}; + +/* ------------- picture box prototypes ------------- */ +void DrawVector(DFWINDOW, int, int, int, int); +void DrawBox(DFWINDOW, int, int, int, int); +void DrawBar(DFWINDOW, enum VectTypes, int, int, int, int); +DFWINDOW WatchIcon(void); + +/* ------------- help box prototypes ------------- */ +void LoadHelpFile(void); +void UnLoadHelpFile(void); +BOOL DisplayHelp(DFWINDOW, char *); + +extern char *ClassNames[]; + +void BuildFileName(char *, char *); + +#endif diff --git a/include/dflat32/dflatmsg.h b/include/dflat32/dflatmsg.h new file mode 100644 index 0000000..cfca23e --- /dev/null +++ b/include/dflat32/dflatmsg.h @@ -0,0 +1,100 @@ +/* ----------- dflatmsg.h ------------ */ + +/* + * message foundation file + * make message changes here + * other source files will adapt + */ + +/* -------------- process communication messages ----------- */ +DFlatMsg(DFM_START) /* start message processing */ +DFlatMsg(DFM_STOP) /* stop message processing */ +DFlatMsg(DFM_COMMAND) /* send a command to a window */ +/* -------------- window management messages --------------- */ +DFlatMsg(CREATE_WINDOW) /* create a window */ +DFlatMsg(SHOW_WINDOW) /* show a window */ +DFlatMsg(DFM_HIDE_WINDOW) /* hide a window */ +DFlatMsg(CLOSE_WINDOW) /* delete a window */ +DFlatMsg(SETFOCUS) /* set and clear the focus */ +DFlatMsg(PAINT) /* paint the window's data space*/ +DFlatMsg(BORDER) /* paint the window's border */ +DFlatMsg(TITLE) /* display the window's title */ +DFlatMsg(MOVE) /* move the window */ +DFlatMsg(DFM_SIZE) /* change the window's size */ +#ifdef INCLUDE_MAXIMIZE +DFlatMsg(MAXIMIZE) /* maximize the window */ +#endif +#ifdef INCLUDE_MINIMIZE +DFlatMsg(MINIMIZE) /* minimize the window */ +#endif +DFlatMsg(RESTORE) /* restore the window */ +DFlatMsg(INSIDE_WINDOW) /* test x/y inside a window */ +/* ---------------- clock messages ------------------------- */ +DFlatMsg(CLOCKTICK) /* the clock ticked */ +DFlatMsg(CAPTURE_CLOCK) /* capture clock into a window */ +DFlatMsg(RELEASE_CLOCK) /* release clock to the system */ +/* -------------- keyboard and screen messages ------------- */ +DFlatMsg(KEYBOARD) /* key was pressed */ +DFlatMsg(CAPTURE_KEYBOARD) /* capture keyboard into a window */ +DFlatMsg(RELEASE_KEYBOARD) /* release keyboard to system */ +DFlatMsg(KEYBOARD_CURSOR) /* position the keyboard cursor */ +DFlatMsg(CURRENT_KEYBOARD_CURSOR) /*read the cursor position */ +DFlatMsg(HIDE_CURSOR) /* hide the keyboard cursor */ +DFlatMsg(SHOW_CURSOR) /* display the keyboard cursor */ +DFlatMsg(SAVE_CURSOR) /* save the cursor's configuration*/ +DFlatMsg(RESTORE_CURSOR) /* restore the saved cursor */ +DFlatMsg(SHIFT_CHANGED) /* the shift status changed */ +DFlatMsg(WAITKEYBOARD) /* waits for a key to be released */ + +/* ---------------- mouse messages ------------------------- */ +DFlatMsg(MOUSE_TRAVEL) /* set the mouse travel */ +DFlatMsg(RIGHT_BUTTON) /* right button pressed */ +DFlatMsg(LEFT_BUTTON) /* left button pressed */ +DFlatMsg(DFM_DOUBLE_CLICK) /* left button double-clicked */ +DFlatMsg(DFM_MOUSE_MOVED) /* mouse changed position */ +DFlatMsg(DFM_BUTTON_RELEASED) /* mouse button released */ +DFlatMsg(WAITMOUSE) /* wait until button released */ +DFlatMsg(TESTMOUSE) /* test any mouse button pressed*/ +DFlatMsg(CAPTURE_MOUSE) /* capture mouse into a window */ +DFlatMsg(RELEASE_MOUSE) /* release the mouse to system */ + +/* ---------------- text box messages ---------------------- */ +DFlatMsg(ADDTEXT) /* append text to the text box */ +DFlatMsg(INSERTTEXT) /* insert line of text */ +DFlatMsg(DELETETEXT) /* delete line of text */ +DFlatMsg(CLEARTEXT) /* clear the edit box */ +DFlatMsg(SETTEXT) /* copy text to text buffer */ +DFlatMsg(SCROLL) /* vertical line scroll */ +DFlatMsg(HORIZSCROLL) /* horizontal column scroll */ +DFlatMsg(SCROLLPAGE) /* vertical page scroll */ +DFlatMsg(HORIZPAGE) /* horizontal page scroll */ +DFlatMsg(SCROLLDOC) /* scroll to beginning/end */ +/* ---------------- edit box messages ---------------------- */ +DFlatMsg(GETTEXT) /* get text from an edit box */ +DFlatMsg(SETTEXTLENGTH) /* set maximum text length */ +/* ---------------- menubar messages ----------------------- */ +DFlatMsg(BUILDMENU) /* build the menu display */ +DFlatMsg(MB_SELECTION) /* menubar selection */ +/* ---------------- popdown messages ----------------------- */ +DFlatMsg(BUILD_SELECTIONS) /* build the menu display */ +DFlatMsg(CLOSE_POPDOWN) /* tell parent popdown is closing */ +/* ---------------- list box messages ---------------------- */ +DFlatMsg(LB_SELECTION) /* sent to parent on selection */ +DFlatMsg(LB_CHOOSE) /* sent when user chooses */ +DFlatMsg(LB_CURRENTSELECTION)/* return the current selection */ +DFlatMsg(DFM_LB_GETTEXT) /* return the text of selection */ +DFlatMsg(LB_SETSELECTION) /* sets the listbox selection */ +/* ---------------- dialog box messages -------------------- */ +DFlatMsg(INITIATE_DIALOG) /* begin a dialog */ +DFlatMsg(ENTERFOCUS) /* tell DB control got focus */ +DFlatMsg(LEAVEFOCUS) /* tell DB control lost focus */ +DFlatMsg(ENDDIALOG) /* end a dialog */ +/* ---------------- help box messages ---------------------- */ +DFlatMsg(DISPLAY_HELP) +/* --------------- application window messages ------------- */ +DFlatMsg(ADDSTATUS) +/* --------------- picture box messages -------------------- */ +DFlatMsg(DRAWVECTOR) +DFlatMsg(DRAWBOX) +DFlatMsg(DRAWBAR) + diff --git a/include/dflat32/dialbox.h b/include/dflat32/dialbox.h new file mode 100644 index 0000000..a32119d --- /dev/null +++ b/include/dflat32/dialbox.h @@ -0,0 +1,55 @@ +/* ----------------- dialbox.h ---------------- */ + +#ifndef DIALOG_H +#define DIALOG_H + +#include + +#define MAXCONTROLS 30 +#define MAXRADIOS 20 + +#define OFF FALSE +#define ON TRUE + +/* -------- dialog box and control window structure ------- */ +typedef struct { + char *title; /* window title */ + int x, y; /* relative coordinates */ + int h, w; /* size */ +} DIALOGWINDOW; + +/* ------ one of these for each control window ------- */ +typedef struct { + DIALOGWINDOW dwnd; + DFCLASS class; /* LISTBOX, BUTTON, etc */ + char *itext; /* initialized text */ + int command; /* command code */ + char *help; /* help mnemonic */ + BOOL isetting; /* initially ON or OFF */ + BOOL setting; /* ON or OFF */ + void *wnd; /* window handle */ +} CTLWINDOW; + +/* --------- one of these for each dialog box ------- */ +typedef struct { + char *HelpName; + DIALOGWINDOW dwnd; + CTLWINDOW ctl[MAXCONTROLS+1]; +} DBOX; + +/* -------- macros for dialog box resource compile -------- */ +#define DIALOGBOX(db) DBOX db={ #db, +#define DB_TITLE(ttl,x,y,h,w) {ttl,x,y,h,w},{ +#define CONTROL(ty,tx,x,y,h,w,c) \ + {{NULL,x,y,h,w},ty, \ + (ty==EDITBOX||ty==COMBOBOX?NULL:tx), \ + c,#c,(ty==BUTTON?ON:OFF),OFF,NULL}, + +#define ENDDB {{NULL}} }}; + +#define Cancel " Cancel " +#define Ok " OK " +#define Yes " Yes " +#define No " No " + +#endif diff --git a/include/dflat32/htree.h b/include/dflat32/htree.h new file mode 100644 index 0000000..db25e0a --- /dev/null +++ b/include/dflat32/htree.h @@ -0,0 +1,31 @@ +/* ------------------- htree.h -------------------- */ + +#ifndef HTREE_H +#define HTREE_H + +typedef unsigned int BYTECOUNTER; + +/* ---- Huffman tree structure for building ---- */ +struct htree { + BYTECOUNTER cnt; /* character frequency */ + int parent; /* offset to parent node */ + int right; /* offset to right child node */ + int left; /* offset to left child node */ +}; + +/* ---- Huffman tree structure in compressed file ---- */ +struct htr { + int right; /* offset to right child node */ + int left; /* offset to left child node */ +}; + +extern struct htr *HelpTree; + +void buildtree(void); +FILE *OpenHelpFile(void); +void HelpFilePosition(long *, int *); +void *GetHelpLine(char *); +void SeekHelpLine(long, int); + +#endif + diff --git a/include/dflat32/keys.h b/include/dflat32/keys.h new file mode 100644 index 0000000..51707d8 --- /dev/null +++ b/include/dflat32/keys.h @@ -0,0 +1,119 @@ +/* ----------- keys.h ------------ */ + +#ifndef KEYS_H +#define KEYS_H + +#define OFFSET 0x1000 + +#define RUBOUT 8 /* BACHSPACE KEY */ +#define BELL 7 +#define ESC 27 +#define ALT_BS (197+OFFSET) +#define ALT_DEL (184+OFFSET) +#define SHIFT_DEL (198+OFFSET) +#define CTRL_INS (186+OFFSET) +#define SHIFT_INS (185+OFFSET) +#define SHIFT_F8 (219+OFFSET) +#define F1 (187+OFFSET) +#define F2 (188+OFFSET) +#define F3 (189+OFFSET) +#define F4 (190+OFFSET) +#define F5 (191+OFFSET) +#define F6 (192+OFFSET) +#define F7 (193+OFFSET) +#define F8 (194+OFFSET) +#define F9 (195+OFFSET) +#define F10 (196+OFFSET) +#define CTRL_F1 (222+OFFSET) +#define CTRL_F2 (223+OFFSET) +#define CTRL_F3 (224+OFFSET) +#define CTRL_F4 (225+OFFSET) +#define CTRL_F5 (226+OFFSET) +#define CTRL_F6 (227+OFFSET) +#define CTRL_F7 (228+OFFSET) +#define CTRL_F8 (229+OFFSET) +#define CTRL_F9 (230+OFFSET) +#define CTRL_F10 (231+OFFSET) +#define ALT_F1 (232+OFFSET) +#define ALT_F2 (233+OFFSET) +#define ALT_F3 (234+OFFSET) +#define ALT_F4 (235+OFFSET) +#define ALT_F5 (236+OFFSET) +#define ALT_F6 (237+OFFSET) +#define ALT_F7 (238+OFFSET) +#define ALT_F8 (239+OFFSET) +#define ALT_F9 (240+OFFSET) +#define ALT_F10 (241+OFFSET) +#define HOME (199+OFFSET) +#define UP (200+OFFSET) +#define PGUP (201+OFFSET) +#define BS (203+OFFSET) /* CURSOR LEFT KEY */ +#define FWD (205+OFFSET) /* CURSOR RIGHT KEY */ +#define END (207+OFFSET) +#define DN (208+OFFSET) +#define PGDN (209+OFFSET) +#define INS (210+OFFSET) +#define DEL (211+OFFSET) +#define CTRL_HOME (247+OFFSET) +#define CTRL_PGUP (132+OFFSET) +#define CTRL_BS (243+OFFSET) +#define CTRL_FIVE (143+OFFSET) +#define CTRL_FWD (244+OFFSET) +#define CTRL_END (245+OFFSET) +#define CTRL_PGDN (246+OFFSET) +#define SHIFT_HT (143+OFFSET) +#define ALT_A (158+OFFSET) +#define ALT_B (176+OFFSET) +#define ALT_C (174+OFFSET) +#define ALT_D (160+OFFSET) +#define ALT_E (146+OFFSET) +#define ALT_F (161+OFFSET) +#define ALT_G (162+OFFSET) +#define ALT_H (163+OFFSET) +#define ALT_I (151+OFFSET) +#define ALT_J (164+OFFSET) +#define ALT_K (165+OFFSET) +#define ALT_L (166+OFFSET) +#define ALT_M (178+OFFSET) +#define ALT_N (177+OFFSET) +#define ALT_O (152+OFFSET) +#define ALT_P (153+OFFSET) +#define ALT_Q (144+OFFSET) +#define ALT_R (147+OFFSET) +#define ALT_S (159+OFFSET) +#define ALT_T (148+OFFSET) +#define ALT_U (150+OFFSET) +#define ALT_V (175+OFFSET) +#define ALT_W (145+OFFSET) +#define ALT_X (173+OFFSET) +#define ALT_Y (149+OFFSET) +#define ALT_Z (172+OFFSET) +#define ALT_1 (0xf8+OFFSET) +#define ALT_2 (0xf9+OFFSET) +#define ALT_3 (0xfa+OFFSET) +#define ALT_4 (0xfb+OFFSET) +#define ALT_5 (0xfc+OFFSET) +#define ALT_6 (0xfd+OFFSET) +#define ALT_7 (0xfe+OFFSET) +#define ALT_8 (0xff+OFFSET) +#define ALT_9 (0x80+OFFSET) +#define ALT_0 (0x81+OFFSET) +#define ALT_HYPHEN (130+OFFSET) + +#define RIGHTSHIFT 0x01 +#define LEFTSHIFT 0x02 +#define CTRLKEY 0x04 +#define ALTKEY 0x08 +#define SCROLLLOCK 0x10 +#define NUMLOCK 0x20 +#define CAPSLOCK 0x40 +#define INSERTKEY 0x80 + +struct keys { + int keycode; + char *keylabel; +}; +extern struct keys keys[]; + +#endif + diff --git a/include/dflat32/menu.h b/include/dflat32/menu.h new file mode 100644 index 0000000..28c509a --- /dev/null +++ b/include/dflat32/menu.h @@ -0,0 +1,63 @@ +/* ------------ menu.h ------------- */ + +#ifndef MENU_H +#define MENU_H + +#define MAXPULLDOWNS 15 +#define MAXSELECTIONS 20 +#define MAXCASCADES 3 /* nesting level of cascaded menus */ + +/* ----------- popdown menu selection structure + one for each selection on a popdown menu --------- */ +struct PopDown { + unsigned char *SelectionTitle; /* title of the selection */ + int ActionId; /* the command executed */ + int Accelerator; /* the accelerator key */ + int Attrib; /* INACTIVE | CHECKED | TOGGLE | CASCADED*/ + char *help; /* Help mnemonic */ +}; + +/* ----------- popdown menu structure + one for each popdown menu on the menu bar -------- */ +typedef struct Menu { + char *Title; /* title on the menu bar */ + void (*PrepMenu)(void *, struct Menu *); /* function */ + char *StatusText; /* text for the status bar */ + int CascadeId; /* command id of cascading selection */ + int Selection; /* most recent selection */ + struct PopDown Selections[MAXSELECTIONS+1]; +} MENU; + +/* ----- one for each menu bar ----- */ +typedef struct MenuBar { + int ActiveSelection; + MENU PullDown[MAXPULLDOWNS+1]; +} MBAR; + +/* --------- macros to define a menu bar with + popdowns and selections ------------- */ +#define SEPCHAR "\xc4" +#define DEFMENU(m) MBAR m = {-1,{ +#define POPDOWN(ttl,func,stat) {ttl,func,stat,-1,0,{ +#define CASCADED_POPDOWN(id,func) {NULL,func,NULL,id,0,{ +#define SELECTION(stxt,acc,id,attr) {stxt,acc,id,attr,#acc}, +#define SEPARATOR {SEPCHAR}, +#define ENDPOPDOWN {NULL}}}, +#define ENDMENU {(void *)-1} }}; + +/* -------- menu selection attributes -------- */ +#define INACTIVE 1 +#define CHECKED 2 +#define TOGGLE 4 +#define CASCADED 8 + +/* --------- the standard menus ---------- */ +extern MBAR MainMenu; +extern MBAR SystemMenu; +extern MBAR *ActiveMenuBar; + +int MenuHeight(struct PopDown *); +int MenuWidth(struct PopDown *); + +#endif + diff --git a/include/dflat32/rect.h b/include/dflat32/rect.h new file mode 100644 index 0000000..c4497e1 --- /dev/null +++ b/include/dflat32/rect.h @@ -0,0 +1,24 @@ +/* ----------- rect.h ------------ */ +#ifndef RECT_H +#define RECT_H + +typedef struct { + int lf,tp,rt,bt; +} DFRECT; +#define within(p,v1,v2) ((p)>=(v1)&&(p)<=(v2)) +#define RectTop(r) (r.tp) +#define RectBottom(r) (r.bt) +#define RectLeft(r) (r.lf) +#define RectRight(r) (r.rt) +#define InsideRect(x,y,r) (within((x),RectLeft(r),RectRight(r))\ + && \ + within((y),RectTop(r),RectBottom(r))) +#define ValidRect(r) (RectRight(r) || RectLeft(r) || \ + RectTop(r) || RectBottom(r)) +#define RectWidth(r) (RectRight(r)-RectLeft(r)+1) +#define RectHeight(r) (RectBottom(r)-RectTop(r)+1) +DFRECT subRectangle(DFRECT, DFRECT); +DFRECT ClientRect(void *); +DFRECT RelativeWindowRect(void *, DFRECT); +DFRECT ClipRectangle(void *, DFRECT); +#endif diff --git a/include/dflat32/system.h b/include/dflat32/system.h new file mode 100644 index 0000000..42136c1 --- /dev/null +++ b/include/dflat32/system.h @@ -0,0 +1,99 @@ +/* --------------- system.h -------------- */ +#ifndef SYSTEM_H +#define SYSTEM_H + +//#if MSC | WATCOM +#include +//#else +//#include +//#endif + +#define swap(a,b){int x=a;a=b;b=x;} +/* ------- platform-dependent values ------ */ +#define KEYBOARDPORT 0x60 +#define FREQUENCY 100 +#define COUNT (1193280L / FREQUENCY) +#define ZEROFLAG 0x40 +#define MAXSAVES 50 + +//#define SCREENWIDTH (80) +//#define SCREENHEIGHT (25) + +HANDLE hInput; +HANDLE hOutput; + +SHORT sScreenHeight; +SHORT sScreenWidth; + + +/* ---------- keyboard prototypes -------- */ +int AltConvert(int); +void GetKey(PINPUT_RECORD); +int getshift(void); +BOOL keyhit(void); +void beep(void); + +/* ---------- cursor prototypes -------- */ +void curr_cursor(int *x, int *y); +void cursor(int x, int y); +void hidecursor(void); +void unhidecursor(void); +void savecursor(void); +void restorecursor(void); +void normalcursor(void); +void set_cursor_size(unsigned t); +void videomode(void); +void SwapCursorStack(void); + +/* ------------ timer macros -------------- */ +#define timed_out(timer) (timer==0) +#define set_timer(timer, secs) timer=(secs)*182/10+1 +#define disable_timer(timer) timer = -1 +#define timer_running(timer) (timer > 0) +#define countdown(timer) --timer +#define timer_disabled(timer) (timer == -1) + + +#ifndef TURBOC +#ifndef BCPP +/* ============= Color Macros ============ */ +#define BLACK 0 +#define BLUE 1 +#define GREEN 2 +#define CYAN 3 +#define RED 4 +#define MAGENTA 5 +#define BROWN 6 +#define LIGHTGRAY 7 +#define DARKGRAY 8 +#define LIGHTBLUE 9 +#define LIGHTGREEN 10 +#define LIGHTCYAN 11 +#define LIGHTRED 12 +#define LIGHTMAGENTA 13 +#define YELLOW 14 +#define WHITE 15 +#define keyhit kbhit +#endif +#endif + +typedef enum messages { +#ifdef WATCOM + WATCOMFIX1 = -1, +#endif + #undef DFlatMsg + #define DFlatMsg(m) m, + #include "dflatmsg.h" + MESSAGECOUNT +} DFMESSAGE; + +typedef enum window_class { +#ifdef WATCOM + WATCOMFIX2 = -1, +#endif + #define ClassDef(c,b,p,a) c, + #include "classes.h" + CLASSCOUNT +} DFCLASS; + +#endif diff --git a/include/dflat32/video.h b/include/dflat32/video.h new file mode 100644 index 0000000..cc8996c --- /dev/null +++ b/include/dflat32/video.h @@ -0,0 +1,18 @@ +/* ---------------- video.h ----------------- */ + +#ifndef VIDEO_H +#define VIDEO_H + +#include "rect.h" + +void GetVideo(DFRECT, PCHAR_INFO); +void StoreVideo(DFRECT, PCHAR_INFO); +void wputch(DFWINDOW, int, int, int); +char GetVideoChar(int, int); +void PutVideoChar(int, int, int); +void wputs(DFWINDOW, void *, int, int); +void scroll_window(DFWINDOW, DFRECT, int); + +#define videochar(x,y) (GetVideoChar(x,y) & 0xFF) + +#endif diff --git a/include/errors.h b/include/errors.h new file mode 100644 index 0000000..fbb4023 --- /dev/null +++ b/include/errors.h @@ -0,0 +1,1163 @@ +/* + Errors.h + + Windows32 API error codes + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Scott Christley + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNU_H_WINDOWS32_ERROR +#define _GNU_H_WINDOWS32_ERROR + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// +// Return Code macros +// +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) +#define FAILED(Status) ((HRESULT)(Status)<0) + +// +// Success Codes +// +#define S_OK 0x00000000L +#define S_FALSE 0x00000001L + +/* Numerical order */ + +#define LZERROR_UNKNOWNALG (-8) +#define LZERROR_BADVALUE (-7) +#define LZERROR_GLOBLOCK (-6) +#define LZERROR_GLOBALLOC (-5) +#define LZERROR_WRITE (-4) +#define LZERROR_READ (-3) +#define LZERROR_BADOUTHANDLE (-2) +#define LZERROR_BADINHANDLE (-1) +#define NO_ERROR 0L +#define ERROR_SUCCESS 0L +#define ERROR_INVALID_FUNCTION 1L +#define ERROR_FILE_NOT_FOUND 2L +#define ERROR_PATH_NOT_FOUND 3L +#define ERROR_TOO_MANY_OPEN_FILES 4L +#define ERROR_ACCESS_DENIED 5L +#define ERROR_INVALID_HANDLE 6L +#define ERROR_ARENA_TRASHED 7L +#define ERROR_NOT_ENOUGH_MEMORY 8L +#define ERROR_INVALID_BLOCK 9L +#define ERROR_BAD_ENVIRONMENT 10L +#define ERROR_BAD_FORMAT 11L +#define ERROR_INVALID_ACCESS 12L +#define ERROR_INVALID_DATA 13L +#define ERROR_OUTOFMEMORY 14L +#define ERROR_INVALID_DRIVE 15L +#define ERROR_CURRENT_DIRECTORY 16L +#define ERROR_NOT_SAME_DEVICE 17L +#define ERROR_NO_MORE_FILES 18L +#define ERROR_WRITE_PROTECT 19L +#define ERROR_BAD_UNIT 20L +#define ERROR_NOT_READY 21L +#define ERROR_BAD_COMMAND 22L +#define ERROR_CRC 23L +#define ERROR_BAD_LENGTH 24L +#define ERROR_SEEK 25L +#define ERROR_NOT_DOS_DISK 26L +#define ERROR_SECTOR_NOT_FOUND 27L +#define ERROR_OUT_OF_PAPER 28L +#define ERROR_WRITE_FAULT 29L +#define ERROR_READ_FAULT 30L +#define ERROR_GEN_FAILURE 31L +#define ERROR_SHARING_VIOLATION 32L +#define ERROR_LOCK_VIOLATION 33L +#define ERROR_WRONG_DISK 34L +#define ERROR_SHARING_BUFFER_EXCEEDED 36L +#define ERROR_HANDLE_EOF 38L +#define ERROR_HANDLE_DISK_FULL 39L +#define ERROR_NOT_SUPPORTED 50L +#define ERROR_REM_NOT_LIST 51L +#define ERROR_DUP_NAME 52L +#define ERROR_BAD_NETPATH 53L +#define ERROR_NETWORK_BUSY 54L +#define ERROR_DEV_NOT_EXIST 55L +#define ERROR_TOO_MANY_CMDS 56L +#define ERROR_ADAP_HDW_ERR 57L +#define ERROR_BAD_NET_RESP 58L +#define ERROR_UNEXP_NET_ERR 59L +#define ERROR_BAD_REM_ADAP 60L +#define ERROR_PRINTQ_FULL 61L +#define ERROR_NO_SPOOL_SPACE 62L +#define ERROR_PRINT_CANCELLED 63L +#define ERROR_NETNAME_DELETED 64L +#define ERROR_NETWORK_ACCESS_DENIED 65L +#define ERROR_BAD_DEV_TYPE 66L +#define ERROR_BAD_NET_NAME 67L +#define ERROR_TOO_MANY_NAMES 68L +#define ERROR_TOO_MANY_SESS 69L +#define ERROR_SHARING_PAUSED 70L +#define ERROR_REQ_NOT_ACCEP 71L +#define ERROR_REDIR_PAUSED 72L +#define ERROR_FILE_EXISTS 80L +#define ERROR_CANNOT_MAKE 82L +#define ERROR_FAIL_I24 83L +#define ERROR_OUT_OF_STRUCTURES 84L +#define ERROR_ALREADY_ASSIGNED 85L +#define ERROR_INVALID_PASSWORD 86L +#define ERROR_INVALID_PARAMETER 87L +#define ERROR_NET_WRITE_FAULT 88L +#define ERROR_NO_PROC_SLOTS 89L +#define ERROR_TOO_MANY_SEMAPHORES 100L +#define ERROR_EXCL_SEM_ALREADY_OWNED 101L +#define ERROR_SEM_IS_SET 102L +#define ERROR_TOO_MANY_SEM_REQUESTS 103L +#define ERROR_INVALID_AT_INTERRUPT_TIME 104L +#define ERROR_SEM_OWNER_DIED 105L +#define ERROR_SEM_USER_LIMIT 106L +#define ERROR_DISK_CHANGE 107L +#define ERROR_DRIVE_LOCKED 108L +#define ERROR_BROKEN_PIPE 109L +#define ERROR_OPEN_FAILED 110L +#define ERROR_BUFFER_OVERFLOW 111L +#define ERROR_DISK_FULL 112L +#define ERROR_NO_MORE_SEARCH_HANDLES 113L +#define ERROR_INVALID_TARGET_HANDLE 114L +#define ERROR_INVALID_CATEGORY 117L +#define ERROR_INVALID_VERIFY_SWITCH 118L +#define ERROR_BAD_DRIVER_LEVEL 119L +#define ERROR_CALL_NOT_IMPLEMENTED 120L +#define ERROR_SEM_TIMEOUT 121L +#define ERROR_INSUFFICIENT_BUFFER 122L +#define ERROR_INVALID_NAME 123L +#define ERROR_INVALID_LEVEL 124L +#define ERROR_NO_VOLUME_LABEL 125L +#define ERROR_MOD_NOT_FOUND 126L +#define ERROR_PROC_NOT_FOUND 127L +#define ERROR_WAIT_NO_CHILDREN 128L +#define ERROR_CHILD_NOT_COMPLETE 129L +#define ERROR_DIRECT_ACCESS_HANDLE 130L +#define ERROR_NEGATIVE_SEEK 131L +#define ERROR_SEEK_ON_DEVICE 132L +#define ERROR_IS_JOIN_TARGET 133L +#define ERROR_IS_JOINED 134L +#define ERROR_IS_SUBSTED 135L +#define ERROR_NOT_JOINED 136L +#define ERROR_NOT_SUBSTED 137L +#define ERROR_JOIN_TO_JOIN 138L +#define ERROR_SUBST_TO_SUBST 139L +#define ERROR_JOIN_TO_SUBST 140L +#define ERROR_SUBST_TO_JOIN 141L +#define ERROR_BUSY_DRIVE 142L +#define ERROR_SAME_DRIVE 143L +#define ERROR_DIR_NOT_ROOT 144L +#define ERROR_DIR_NOT_EMPTY 145L +#define ERROR_IS_SUBST_PATH 146L +#define ERROR_IS_JOIN_PATH 147L +#define ERROR_PATH_BUSY 148L +#define ERROR_IS_SUBST_TARGET 149L +#define ERROR_SYSTEM_TRACE 150L +#define ERROR_INVALID_EVENT_COUNT 151L +#define ERROR_TOO_MANY_MUXWAITERS 152L +#define ERROR_INVALID_LIST_FORMAT 153L +#define ERROR_LABEL_TOO_LONG 154L +#define ERROR_TOO_MANY_TCBS 155L +#define ERROR_SIGNAL_REFUSED 156L +#define ERROR_DISCARDED 157L +#define ERROR_NOT_LOCKED 158L +#define ERROR_BAD_THREADID_ADDR 159L +#define ERROR_BAD_ARGUMENTS 160L +#define ERROR_BAD_PATHNAME 161L +#define ERROR_SIGNAL_PENDING 162L +#define ERROR_MAX_THRDS_REACHED 164L +#define ERROR_LOCK_FAILED 167L +#define ERROR_BUSY 170L +#define ERROR_CANCEL_VIOLATION 173L +#define ERROR_ATOMIC_LOCKS_NOT_SUPPORTED 174L +#define ERROR_INVALID_SEGMENT_NUMBER 180L +#define ERROR_INVALID_ORDINAL 182L +#define ERROR_ALREADY_EXISTS 183L +#define ERROR_INVALID_FLAG_NUMBER 186L +#define ERROR_SEM_NOT_FOUND 187L +#define ERROR_INVALID_STARTING_CODESEG 188L +#define ERROR_INVALID_STACKSEG 189L +#define ERROR_INVALID_MODULETYPE 190L +#define ERROR_INVALID_EXE_SIGNATURE 191L +#define ERROR_EXE_MARKED_INVALID 192L +#define ERROR_BAD_EXE_FORMAT 193L +#define ERROR_ITERATED_DATA_EXCEEDS_64k 194L +#define ERROR_INVALID_MINALLOCSIZE 195L +#define ERROR_DYNLINK_FROM_INVALID_RING 196L +#define ERROR_IOPL_NOT_ENABLED 197L +#define ERROR_INVALID_SEGDPL 198L +#define ERROR_AUTODATASEG_EXCEEDS_64k 199L +#define ERROR_RING2SEG_MUST_BE_MOVABLE 200L +#define ERROR_RELOC_CHAIN_XEEDS_SEGLIM 201L +#define ERROR_INFLOOP_IN_RELOC_CHAIN 202L +#define ERROR_ENVVAR_NOT_FOUND 203L +#define ERROR_NO_SIGNAL_SENT 205L +#define ERROR_FILENAME_EXCED_RANGE 206L +#define ERROR_RING2_STACK_IN_USE 207L +#define ERROR_META_EXPANSION_TOO_LONG 208L +#define ERROR_INVALID_SIGNAL_NUMBER 209L +#define ERROR_THREAD_1_INACTIVE 210L +#define ERROR_LOCKED 212L +#define ERROR_TOO_MANY_MODULES 214L +#define ERROR_NESTING_NOT_ALLOWED 215L +#define ERROR_BAD_PIPE 230L +#define ERROR_PIPE_BUSY 231L +#define ERROR_NO_DATA 232L +#define ERROR_PIPE_NOT_CONNECTED 233L +#define ERROR_MORE_DATA 234L +#define ERROR_VC_DISCONNECTED 240L +#define ERROR_INVALID_EA_NAME 254L +#define ERROR_EA_LIST_INCONSISTENT 255L +#define ERROR_NO_MORE_ITEMS 259L +#define ERROR_CANNOT_COPY 266L +#define ERROR_DIRECTORY 267L +#define ERROR_EAS_DIDNT_FIT 275L +#define ERROR_EA_FILE_CORRUPT 276L +#define ERROR_EA_TABLE_FULL 277L +#define ERROR_INVALID_EA_HANDLE 278L +#define ERROR_EAS_NOT_SUPPORTED 282L +#define ERROR_NOT_OWNER 288L +#define ERROR_TOO_MANY_POSTS 298L +#define ERROR_PARTIAL_COPY 299L +#define ERROR_MR_MID_NOT_FOUND 317L +#define ERROR_INVALID_ADDRESS 487L +#define ERROR_ARITHMETIC_OVERFLOW 534L +#define ERROR_PIPE_CONNECTED 535L +#define ERROR_PIPE_LISTENING 536L +#define ERROR_EA_ACCESS_DENIED 994L +#define ERROR_OPERATION_ABORTED 995L +#define ERROR_IO_INCOMPLETE 996L +#define ERROR_IO_PENDING 997L +#define ERROR_NOACCESS 998L +#define ERROR_SWAPERROR 999L +#define ERROR_STACK_OVERFLOW 1001L +#define ERROR_INVALID_MESSAGE 1002L +#define ERROR_CAN_NOT_COMPLETE 1003L +#define ERROR_INVALID_FLAGS 1004L +#define ERROR_UNRECOGNIZED_VOLUME 1005L +#define ERROR_FILE_INVALID 1006L +#define ERROR_FULLSCREEN_MODE 1007L +#define ERROR_NO_TOKEN 1008L +#define ERROR_BADDB 1009L +#define ERROR_BADKEY 1010L +#define ERROR_CANTOPEN 1011L +#define ERROR_CANTREAD 1012L +#define ERROR_CANTWRITE 1013L +#define ERROR_REGISTRY_RECOVERED 1014L +#define ERROR_REGISTRY_CORRUPT 1015L +#define ERROR_REGISTRY_IO_FAILED 1016L +#define ERROR_NOT_REGISTRY_FILE 1017L +#define ERROR_KEY_DELETED 1018L +#define ERROR_NO_LOG_SPACE 1019L +#define ERROR_KEY_HAS_CHILDREN 1020L +#define ERROR_CHILD_MUST_BE_VOLATILE 1021L +#define ERROR_NOTIFY_ENUM_DIR 1022L +#define ERROR_DEPENDENT_SERVICES_RUNNING 1051L +#define ERROR_INVALID_SERVICE_CONTROL 1052L +#define ERROR_SERVICE_REQUEST_TIMEOUT 1053L +#define ERROR_SERVICE_NO_THREAD 1054L +#define ERROR_SERVICE_DATABASE_LOCKED 1055L +#define ERROR_SERVICE_ALREADY_RUNNING 1056L +#define ERROR_INVALID_SERVICE_ACCOUNT 1057L +#define ERROR_SERVICE_DISABLED 1058L +#define ERROR_CIRCULAR_DEPENDENCY 1059L +#define ERROR_SERVICE_DOES_NOT_EXIST 1060L +#define ERROR_SERVICE_CANNOT_ACCEPT_CTRL 1061L +#define ERROR_SERVICE_NOT_ACTIVE 1062L +#define ERROR_FAILED_SERVICE_CONTROLLER_CONNECT 1063L +#define ERROR_EXCEPTION_IN_SERVICE 1064L +#define ERROR_DATABASE_DOES_NOT_EXIST 1065L +#define ERROR_SERVICE_SPECIFIC_ERROR 1066L +#define ERROR_PROCESS_ABORTED 1067L +#define ERROR_SERVICE_DEPENDENCY_FAIL 1068L +#define ERROR_SERVICE_LOGON_FAILED 1069L +#define ERROR_SERVICE_START_HANG 1070L +#define ERROR_INVALID_SERVICE_LOCK 1071L +#define ERROR_SERVICE_MARKED_FOR_DELETE 1072L +#define ERROR_SERVICE_EXISTS 1073L +#define ERROR_ALREADY_RUNNING_LKG 1074L +#define ERROR_SERVICE_DEPENDENCY_DELETED 1075L +#define ERROR_BOOT_ALREADY_ACCEPTED 1076L +#define ERROR_SERVICE_NEVER_STARTED 1077L +#define ERROR_DUPLICATE_SERVICE_NAME 1078L +#define ERROR_END_OF_MEDIA 1100L +#define ERROR_FILEMARK_DETECTED 1101L +#define ERROR_BEGINNING_OF_MEDIA 1102L +#define ERROR_SETMARK_DETECTED 1103L +#define ERROR_NO_DATA_DETECTED 1104L +#define ERROR_PARTITION_FAILURE 1105L +#define ERROR_INVALID_BLOCK_LENGTH 1106L +#define ERROR_DEVICE_NOT_PARTITIONED 1107L +#define ERROR_UNABLE_TO_LOCK_MEDIA 1108L +#define ERROR_UNABLE_TO_UNLOAD_MEDIA 1109L +#define ERROR_MEDIA_CHANGED 1110L +#define ERROR_BUS_RESET 1111L +#define ERROR_NO_MEDIA_IN_DRIVE 1112L +#define ERROR_NO_UNICODE_TRANSLATION 1113L +#define ERROR_DLL_INIT_FAILED 1114L +#define ERROR_SHUTDOWN_IN_PROGRESS 1115L +#define ERROR_NO_SHUTDOWN_IN_PROGRESS 1116L +#define ERROR_IO_DEVICE 1117L +#define ERROR_SERIAL_NO_DEVICE 1118L +#define ERROR_IRQ_BUSY 1119L +#define ERROR_MORE_WRITES 1120L +#define ERROR_COUNTER_TIMEOUT 1121L +#define ERROR_FLOPPY_ID_MARK_NOT_FOUND 1122L +#define ERROR_FLOPPY_WRONG_CYLINDER 1123L +#define ERROR_FLOPPY_UNKNOWN_ERROR 1124L +#define ERROR_FLOPPY_BAD_REGISTERS 1125L +#define ERROR_DISK_RECALIBRATE_FAILED 1126L +#define ERROR_DISK_OPERATION_FAILED 1127L +#define ERROR_DISK_RESET_FAILED 1128L +#define ERROR_EOM_OVERFLOW 1129L +#define ERROR_NOT_ENOUGH_SERVER_MEMORY 1130L +#define ERROR_POSSIBLE_DEADLOCK 1131L +#define ERROR_MAPPED_ALIGNMENT 1132L +#define ERROR_SET_POWER_STATE_VETOED 1140L +#define ERROR_SET_POWER_STATE_FAILED 1141L +#define ERROR_TOO_MANY_LINKS 1142L +#define ERROR_OLD_WIN_VERSION 1150L +#define ERROR_APP_WRONG_OS 1151L +#define ERROR_SINGLE_INSTANCE_APP 1152L +#define ERROR_RMODE_APP 1153L +#define ERROR_INVALID_DLL 1154L +#define ERROR_NO_ASSOCIATION 1155L +#define ERROR_DDE_FAIL 1156L +#define ERROR_DLL_NOT_FOUND 1157L +#define ERROR_BAD_DEVICE 1200L +#define ERROR_CONNECTION_UNAVAIL 1201L +#define ERROR_DEVICE_ALREADY_REMEMBERED 1202L +#define ERROR_NO_NET_OR_BAD_PATH 1203L +#define ERROR_BAD_PROVIDER 1204L +#define ERROR_CANNOT_OPEN_PROFILE 1205L +#define ERROR_BAD_PROFILE 1206L +#define ERROR_NOT_CONTAINER 1207L +#define ERROR_EXTENDED_ERROR 1208L +#define ERROR_INVALID_GROUPNAME 1209L +#define ERROR_INVALID_COMPUTERNAME 1210L +#define ERROR_INVALID_EVENTNAME 1211L +#define ERROR_INVALID_DOMAINNAME 1212L +#define ERROR_INVALID_SERVICENAME 1213L +#define ERROR_INVALID_NETNAME 1214L +#define ERROR_INVALID_SHARENAME 1215L +#define ERROR_INVALID_PASSWORDNAME 1216L +#define ERROR_INVALID_MESSAGENAME 1217L +#define ERROR_INVALID_MESSAGEDEST 1218L +#define ERROR_SESSION_CREDENTIAL_CONFLICT 1219L +#define ERROR_REMOTE_SESSION_LIMIT_EXCEEDED 1220L +#define ERROR_DUP_DOMAINNAME 1221L +#define ERROR_NO_NETWORK 1222L +#define ERROR_CANCELLED 1223L +#define ERROR_USER_MAPPED_FILE 1224L +#define ERROR_CONNECTION_REFUSED 1225L +#define ERROR_GRACEFUL_DISCONNECT 1226L +#define ERROR_ADDRESS_ALREADY_ASSOCIATED 1227L +#define ERROR_ADDRESS_NOT_ASSOCIATED 1228L +#define ERROR_CONNECTION_INVALID 1229L +#define ERROR_CONNECTION_ACTIVE 1230L +#define ERROR_NETWORK_UNREACHABLE 1231L +#define ERROR_HOST_UNREACHABLE 1232L +#define ERROR_PROTOCOL_UNREACHABLE 1233L +#define ERROR_PORT_UNREACHABLE 1234L +#define ERROR_REQUEST_ABORTED 1235L +#define ERROR_CONNECTION_ABORTED 1236L +#define ERROR_RETRY 1237L +#define ERROR_CONNECTION_COUNT_LIMIT 1238L +#define ERROR_LOGIN_TIME_RESTRICTION 1239L +#define ERROR_LOGIN_WKSTA_RESTRICTION 1240L +#define ERROR_INCORRECT_ADDRESS 1241L +#define ERROR_ALREADY_REGISTERED 1242L +#define ERROR_SERVICE_NOT_FOUND 1243L +#define ERROR_NOT_AUTHENTICATED 1244L +#define ERROR_NOT_LOGGED_ON 1245L +#define ERROR_CONTINUE 1246L +#define ERROR_ALREADY_INITIALIZED 1247L +#define ERROR_NO_MORE_DEVICES 1248L +#define ERROR_NOT_ALL_ASSIGNED 1300L +#define ERROR_SOME_NOT_MAPPED 1301L +#define ERROR_NO_QUOTAS_FOR_ACCOUNT 1302L +#define ERROR_LOCAL_USER_SESSION_KEY 1303L +#define ERROR_NULL_LM_PASSWORD 1304L +#define ERROR_UNKNOWN_REVISION 1305L +#define ERROR_REVISION_MISMATCH 1306L +#define ERROR_INVALID_OWNER 1307L +#define ERROR_INVALID_PRIMARY_GROUP 1308L +#define ERROR_NO_IMPERSONATION_TOKEN 1309L +#define ERROR_CANT_DISABLE_MANDATORY 1310L +#define ERROR_NO_LOGON_SERVERS 1311L +#define ERROR_NO_SUCH_LOGON_SESSION 1312L +#define ERROR_NO_SUCH_PRIVILEGE 1313L +#define ERROR_PRIVILEGE_NOT_HELD 1314L +#define ERROR_INVALID_ACCOUNT_NAME 1315L +#define ERROR_USER_EXISTS 1316L +#define ERROR_NO_SUCH_USER 1317L +#define ERROR_GROUP_EXISTS 1318L +#define ERROR_NO_SUCH_GROUP 1319L +#define ERROR_MEMBER_IN_GROUP 1320L +#define ERROR_MEMBER_NOT_IN_GROUP 1321L +#define ERROR_LAST_ADMIN 1322L +#define ERROR_WRONG_PASSWORD 1323L +#define ERROR_ILL_FORMED_PASSWORD 1324L +#define ERROR_PASSWORD_RESTRICTION 1325L +#define ERROR_LOGON_FAILURE 1326L +#define ERROR_ACCOUNT_RESTRICTION 1327L +#define ERROR_INVALID_LOGON_HOURS 1328L +#define ERROR_INVALID_WORKSTATION 1329L +#define ERROR_PASSWORD_EXPIRED 1330L +#define ERROR_ACCOUNT_DISABLED 1331L +#define ERROR_NONE_MAPPED 1332L +#define ERROR_TOO_MANY_LUIDS_REQUESTED 1333L +#define ERROR_LUIDS_EXHAUSTED 1334L +#define ERROR_INVALID_SUB_AUTHORITY 1335L +#define ERROR_INVALID_ACL 1336L +#define ERROR_INVALID_SID 1337L +#define ERROR_INVALID_SECURITY_DESCR 1338L +#define ERROR_BAD_INHERITANCE_ACL 1340L +#define ERROR_SERVER_DISABLED 1341L +#define ERROR_SERVER_NOT_DISABLED 1342L +#define ERROR_INVALID_ID_AUTHORITY 1343L +#define ERROR_ALLOTTED_SPACE_EXCEEDED 1344L +#define ERROR_INVALID_GROUP_ATTRIBUTES 1345L +#define ERROR_BAD_IMPERSONATION_LEVEL 1346L +#define ERROR_CANT_OPEN_ANONYMOUS 1347L +#define ERROR_BAD_VALIDATION_CLASS 1348L +#define ERROR_BAD_TOKEN_TYPE 1349L +#define ERROR_NO_SECURITY_ON_OBJECT 1350L +#define ERROR_CANT_ACCESS_DOMAIN_INFO 1351L +#define ERROR_INVALID_SERVER_STATE 1352L +#define ERROR_INVALID_DOMAIN_STATE 1353L +#define ERROR_INVALID_DOMAIN_ROLE 1354L +#define ERROR_NO_SUCH_DOMAIN 1355L +#define ERROR_DOMAIN_EXISTS 1356L +#define ERROR_DOMAIN_LIMIT_EXCEEDED 1357L +#define ERROR_INTERNAL_DB_CORRUPTION 1358L +#define ERROR_INTERNAL_ERROR 1359L +#define ERROR_GENERIC_NOT_MAPPED 1360L +#define ERROR_BAD_DESCRIPTOR_FORMAT 1361L +#define ERROR_NOT_LOGON_PROCESS 1362L +#define ERROR_LOGON_SESSION_EXISTS 1363L +#define ERROR_NO_SUCH_PACKAGE 1364L +#define ERROR_BAD_LOGON_SESSION_STATE 1365L +#define ERROR_LOGON_SESSION_COLLISION 1366L +#define ERROR_INVALID_LOGON_TYPE 1367L +#define ERROR_CANNOT_IMPERSONATE 1368L +#define ERROR_RXACT_INVALID_STATE 1369L +#define ERROR_RXACT_COMMIT_FAILURE 1370L +#define ERROR_SPECIAL_ACCOUNT 1371L +#define ERROR_SPECIAL_GROUP 1372L +#define ERROR_SPECIAL_USER 1373L +#define ERROR_MEMBERS_PRIMARY_GROUP 1374L +#define ERROR_TOKEN_ALREADY_IN_USE 1375L +#define ERROR_NO_SUCH_ALIAS 1376L +#define ERROR_MEMBER_NOT_IN_ALIAS 1377L +#define ERROR_MEMBER_IN_ALIAS 1378L +#define ERROR_ALIAS_EXISTS 1379L +#define ERROR_LOGON_NOT_GRANTED 1380L +#define ERROR_TOO_MANY_SECRETS 1381L +#define ERROR_SECRET_TOO_LONG 1382L +#define ERROR_INTERNAL_DB_ERROR 1383L +#define ERROR_TOO_MANY_CONTEXT_IDS 1384L +#define ERROR_LOGON_TYPE_NOT_GRANTED 1385L +#define ERROR_NT_CROSS_ENCRYPTION_REQUIRED 1386L +#define ERROR_NO_SUCH_MEMBER 1387L +#define ERROR_INVALID_MEMBER 1388L +#define ERROR_TOO_MANY_SIDS 1389L +#define ERROR_LM_CROSS_ENCRYPTION_REQUIRED 1390L +#define ERROR_NO_INHERITANCE 1391L +#define ERROR_FILE_CORRUPT 1392L +#define ERROR_DISK_CORRUPT 1393L +#define ERROR_NO_USER_SESSION_KEY 1394L +#define ERROR_LICENSE_QUOTA_EXCEEDED 1395L +#define ERROR_INVALID_WINDOW_HANDLE 1400L +#define ERROR_INVALID_MENU_HANDLE 1401L +#define ERROR_INVALID_CURSOR_HANDLE 1402L +#define ERROR_INVALID_ACCEL_HANDLE 1403L +#define ERROR_INVALID_HOOK_HANDLE 1404L +#define ERROR_INVALID_DWP_HANDLE 1405L +#define ERROR_TLW_WITH_WSCHILD 1406L +#define ERROR_CANNOT_FIND_WND_CLASS 1407L +#define ERROR_WINDOW_OF_OTHER_THREAD 1408L +#define ERROR_HOTKEY_ALREADY_REGISTERED 1409L +#define ERROR_CLASS_ALREADY_EXISTS 1410L +#define ERROR_CLASS_DOES_NOT_EXIST 1411L +#define ERROR_CLASS_HAS_WINDOWS 1412L +#define ERROR_INVALID_INDEX 1413L +#define ERROR_INVALID_ICON_HANDLE 1414L +#define ERROR_PRIVATE_DIALOG_INDEX 1415L +#define ERROR_LISTBOX_ID_NOT_FOUND 1416L +#define ERROR_NO_WILDCARD_CHARACTERS 1417L +#define ERROR_CLIPBOARD_NOT_OPEN 1418L +#define ERROR_HOTKEY_NOT_REGISTERED 1419L +#define ERROR_WINDOW_NOT_DIALOG 1420L +#define ERROR_CONTROL_ID_NOT_FOUND 1421L +#define ERROR_INVALID_COMBOBOX_MESSAGE 1422L +#define ERROR_WINDOW_NOT_COMBOBOX 1423L +#define ERROR_INVALID_EDIT_HEIGHT 1424L +#define ERROR_DC_NOT_FOUND 1425L +#define ERROR_INVALID_HOOK_FILTER 1426L +#define ERROR_INVALID_FILTER_PROC 1427L +#define ERROR_HOOK_NEEDS_HMOD 1428L +#define ERROR_GLOBAL_ONLY_HOOK 1429L +#define ERROR_JOURNAL_HOOK_SET 1430L +#define ERROR_HOOK_NOT_INSTALLED 1431L +#define ERROR_INVALID_LB_MESSAGE 1432L +#define ERROR_SETCOUNT_ON_BAD_LB 1433L +#define ERROR_LB_WITHOUT_TABSTOPS 1434L +#define ERROR_DESTROY_OBJECT_OF_OTHER_THREAD 1435L +#define ERROR_CHILD_WINDOW_MENU 1436L +#define ERROR_NO_SYSTEM_MENU 1437L +#define ERROR_INVALID_MSGBOX_STYLE 1438L +#define ERROR_INVALID_SPI_VALUE 1439L +#define ERROR_SCREEN_ALREADY_LOCKED 1440L +#define ERROR_HWNDS_HAVE_DIFF_PARENT 1441L +#define ERROR_NOT_CHILD_WINDOW 1442L +#define ERROR_INVALID_GW_COMMAND 1443L +#define ERROR_INVALID_THREAD_ID 1444L +#define ERROR_NON_MDICHILD_WINDOW 1445L +#define ERROR_POPUP_ALREADY_ACTIVE 1446L +#define ERROR_NO_SCROLLBARS 1447L +#define ERROR_INVALID_SCROLLBAR_RANGE 1448L +#define ERROR_INVALID_SHOWWIN_COMMAND 1449L +#define ERROR_NO_SYSTEM_RESOURCES 1450L +#define ERROR_NONPAGED_SYSTEM_RESOURCES 1451L +#define ERROR_PAGED_SYSTEM_RESOURCES 1452L +#define ERROR_WORKING_SET_QUOTA 1453L +#define ERROR_PAGEFILE_QUOTA 1454L +#define ERROR_COMMITMENT_LIMIT 1455L +#define ERROR_MENU_ITEM_NOT_FOUND 1456L +#define ERROR_EVENTLOG_FILE_CORRUPT 1500L +#define ERROR_EVENTLOG_CANT_START 1501L +#define ERROR_LOG_FILE_FULL 1502L +#define ERROR_EVENTLOG_FILE_CHANGED 1503L +#define RPC_S_INVALID_STRING_BINDING 1700L +#define RPC_S_WRONG_KIND_OF_BINDING 1701L +#define RPC_S_INVALID_BINDING 1702L +#define RPC_S_PROTSEQ_NOT_SUPPORTED 1703L +#define RPC_S_INVALID_RPC_PROTSEQ 1704L +#define RPC_S_INVALID_STRING_UUID 1705L +#define RPC_S_INVALID_ENDPOINT_FORMAT 1706L +#define RPC_S_INVALID_NET_ADDR 1707L +#define RPC_S_NO_ENDPOINT_FOUND 1708L +#define RPC_S_INVALID_TIMEOUT 1709L +#define RPC_S_OBJECT_NOT_FOUND 1710L +#define RPC_S_ALREADY_REGISTERED 1711L +#define RPC_S_TYPE_ALREADY_REGISTERED 1712L +#define RPC_S_ALREADY_LISTENING 1713L +#define RPC_S_NO_PROTSEQS_REGISTERED 1714L +#define RPC_S_NOT_LISTENING 1715L +#define RPC_S_UNKNOWN_MGR_TYPE 1716L +#define RPC_S_UNKNOWN_IF 1717L +#define RPC_S_NO_BINDINGS 1718L +#define RPC_S_NO_PROTSEQS 1719L +#define RPC_S_CANT_CREATE_ENDPOINT 1720L +#define RPC_S_OUT_OF_RESOURCES 1721L +#define RPC_S_SERVER_UNAVAILABLE 1722L +#define RPC_S_SERVER_TOO_BUSY 1723L +#define RPC_S_INVALID_NETWORK_OPTIONS 1724L +#define RPC_S_NO_CALL_ACTIVE 1725L +#define RPC_S_CALL_FAILED 1726L +#define RPC_S_CALL_FAILED_DNE 1727L +#define RPC_S_PROTOCOL_ERROR 1728L +#define RPC_S_UNSUPPORTED_TRANS_SYN 1730L +#define RPC_S_UNSUPPORTED_TYPE 1732L +#define RPC_S_INVALID_TAG 1733L +#define RPC_S_INVALID_BOUND 1734L +#define RPC_S_NO_ENTRY_NAME 1735L +#define RPC_S_INVALID_NAME_SYNTAX 1736L +#define RPC_S_UNSUPPORTED_NAME_SYNTAX 1737L +#define RPC_S_UUID_NO_ADDRESS 1739L +#define RPC_S_DUPLICATE_ENDPOINT 1740L +#define RPC_S_UNKNOWN_AUTHN_TYPE 1741L +#define RPC_S_MAX_CALLS_TOO_SMALL 1742L +#define RPC_S_STRING_TOO_LONG 1743L +#define RPC_S_PROTSEQ_NOT_FOUND 1744L +#define RPC_S_PROCNUM_OUT_OF_RANGE 1745L +#define RPC_S_BINDING_HAS_NO_AUTH 1746L +#define RPC_S_UNKNOWN_AUTHN_SERVICE 1747L +#define RPC_S_UNKNOWN_AUTHN_LEVEL 1748L +#define RPC_S_INVALID_AUTH_IDENTITY 1749L +#define RPC_S_UNKNOWN_AUTHZ_SERVICE 1750L +#define EPT_S_INVALID_ENTRY 1751L +#define EPT_S_CANT_PERFORM_OP 1752L +#define EPT_S_NOT_REGISTERED 1753L +#define RPC_S_NOTHING_TO_EXPORT 1754L +#define RPC_S_INCOMPLETE_NAME 1755L +#define RPC_S_INVALID_VERS_OPTION 1756L +#define RPC_S_NO_MORE_MEMBERS 1757L +#define RPC_S_NOT_ALL_OBJS_UNEXPORTED 1758L +#define RPC_S_INTERFACE_NOT_FOUND 1759L +#define RPC_S_ENTRY_ALREADY_EXISTS 1760L +#define RPC_S_ENTRY_NOT_FOUND 1761L +#define RPC_S_NAME_SERVICE_UNAVAILABLE 1762L +#define RPC_S_INVALID_NAF_ID 1763L +#define RPC_S_CANNOT_SUPPORT 1764L +#define RPC_S_NO_CONTEXT_AVAILABLE 1765L +#define RPC_S_INTERNAL_ERROR 1766L +#define RPC_S_ZERO_DIVIDE 1767L +#define RPC_S_ADDRESS_ERROR 1768L +#define RPC_S_FP_DIV_ZERO 1769L +#define RPC_S_FP_UNDERFLOW 1770L +#define RPC_S_FP_OVERFLOW 1771L +#define RPC_X_NO_MORE_ENTRIES 1772L +#define RPC_X_SS_CHAR_TRANS_OPEN_FAIL 1773L +#define RPC_X_SS_CHAR_TRANS_SHORT_FILE 1774L +#define RPC_X_SS_IN_NULL_CONTEXT 1775L +#define RPC_X_SS_CONTEXT_DAMAGED 1777L +#define RPC_X_SS_HANDLES_MISMATCH 1778L +#define RPC_X_SS_CANNOT_GET_CALL_HANDLE 1779L +#define RPC_X_NULL_REF_POINTER 1780L +#define RPC_X_ENUM_VALUE_OUT_OF_RANGE 1781L +#define RPC_X_BYTE_COUNT_TOO_SMALL 1782L +#define RPC_X_BAD_STUB_DATA 1783L +#define ERROR_INVALID_USER_BUFFER 1784L +#define ERROR_UNRECOGNIZED_MEDIA 1785L +#define ERROR_NO_TRUST_LSA_SECRET 1786L +#define ERROR_NO_TRUST_SAM_ACCOUNT 1787L +#define ERROR_TRUSTED_DOMAIN_FAILURE 1788L +#define ERROR_TRUSTED_RELATIONSHIP_FAILURE 1789L +#define ERROR_TRUST_FAILURE 1790L +#define RPC_S_CALL_IN_PROGRESS 1791L +#define ERROR_NETLOGON_NOT_STARTED 1792L +#define ERROR_ACCOUNT_EXPIRED 1793L +#define ERROR_REDIRECTOR_HAS_OPEN_HANDLES 1794L +#define ERROR_PRINTER_DRIVER_ALREADY_INSTALLED 1795L +#define ERROR_UNKNOWN_PORT 1796L +#define ERROR_UNKNOWN_PRINTER_DRIVER 1797L +#define ERROR_UNKNOWN_PRINTPROCESSOR 1798L +#define ERROR_INVALID_SEPARATOR_FILE 1799L +#define ERROR_INVALID_PRIORITY 1800L +#define ERROR_INVALID_PRINTER_NAME 1801L +#define ERROR_PRINTER_ALREADY_EXISTS 1802L +#define ERROR_INVALID_PRINTER_COMMAND 1803L +#define ERROR_INVALID_DATATYPE 1804L +#define ERROR_INVALID_ENVIRONMENT 1805L +#define RPC_S_NO_MORE_BINDINGS 1806L +#define ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 1807L +#define ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT 1808L +#define ERROR_NOLOGON_SERVER_TRUST_ACCOUNT 1809L +#define ERROR_DOMAIN_TRUST_INCONSISTENT 1810L +#define ERROR_SERVER_HAS_OPEN_HANDLES 1811L +#define ERROR_RESOURCE_DATA_NOT_FOUND 1812L +#define ERROR_RESOURCE_TYPE_NOT_FOUND 1813L +#define ERROR_RESOURCE_NAME_NOT_FOUND 1814L +#define ERROR_RESOURCE_LANG_NOT_FOUND 1815L +#define ERROR_NOT_ENOUGH_QUOTA 1816L +#define RPC_S_NO_INTERFACES 1817L +#define RPC_S_CALL_CANCELLED 1818L +#define RPC_S_BINDING_INCOMPLETE 1819L +#define RPC_S_COMM_FAILURE 1820L +#define RPC_S_UNSUPPORTED_AUTHN_LEVEL 1821L +#define RPC_S_NO_PRINC_NAME 1822L +#define RPC_S_NOT_RPC_ERROR 1823L +#define RPC_S_UUID_LOCAL_ONLY 1824L +#define RPC_S_SEC_PKG_ERROR 1825L +#define RPC_S_NOT_CANCELLED 1826L +#define RPC_X_INVALID_ES_ACTION 1827L +#define RPC_X_WRONG_ES_VERSION 1828L +#define RPC_X_WRONG_STUB_VERSION 1829L +#define RPC_X_INVALID_PIPE_OBJECT 1830L +#define RPC_X_WRONG_PIPE_ORDER 1831L +#define RPC_X_WRONG_PIPE_VERSION 1832L +#define RPC_S_GROUP_MEMBER_NOT_FOUND 1898L +#define EPT_S_CANT_CREATE 1899L +#define RPC_S_INVALID_OBJECT 1900L +#define ERROR_INVALID_TIME 1901L +#define ERROR_INVALID_FORM_NAME 1902L +#define ERROR_INVALID_FORM_SIZE 1903L +#define ERROR_ALREADY_WAITING 1904L +#define ERROR_PRINTER_DELETED 1905L +#define ERROR_INVALID_PRINTER_STATE 1906L +#define ERROR_PASSWORD_MUST_CHANGE 1907L +#define ERROR_DOMAIN_CONTROLLER_NOT_FOUND 1908L +#define ERROR_ACCOUNT_LOCKED_OUT 1909L +#define OR_INVALID_OXID 1910L +#define OR_INVALID_OID 1911L +#define OR_INVALID_SET 1912L +#define RPC_S_SEND_INCOMPLETE 1913L +#define ERROR_INVALID_PIXEL_FORMAT 2000L +#define ERROR_BAD_DRIVER 2001L +#define ERROR_INVALID_WINDOW_STYLE 2002L +#define ERROR_METAFILE_NOT_SUPPORTED 2003L +#define ERROR_TRANSFORM_NOT_SUPPORTED 2004L +#define ERROR_CLIPPING_NOT_SUPPORTED 2005L +#define ERROR_BAD_USERNAME 2202L +#define ERROR_NOT_CONNECTED 2250L +#define ERROR_OPEN_FILES 2401L +#define ERROR_ACTIVE_CONNECTIONS 2402L +#define ERROR_DEVICE_IN_USE 2404L +#define ERROR_UNKNOWN_PRINT_MONITOR 3000L +#define ERROR_PRINTER_DRIVER_IN_USE 3001L +#define ERROR_SPOOL_FILE_NOT_FOUND 3002L +#define ERROR_SPL_NO_STARTDOC 3003L +#define ERROR_SPL_NO_ADDJOB 3004L +#define ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED 3005L +#define ERROR_PRINT_MONITOR_ALREADY_INSTALLED 3006L +#define ERROR_WINS_INTERNAL 4000L +#define ERROR_CAN_NOT_DEL_LOCAL_WINS 4001L +#define ERROR_STATIC_INIT 4002L +#define ERROR_INC_BACKUP 4003L +#define ERROR_FULL_BACKUP 4004L +#define ERROR_REC_NON_EXISTENT 4005L +#define ERROR_RPL_NOT_ALLOWED 4006L +#define ERROR_NO_BROWSER_SERVERS_FOUND 6118L + + +/* HRESULT values for OLE, SHELL and other Interface stuff */ +/* the codes 4000-40ff are reserved for OLE */ +#define NOERROR 0L + +#define E_PENDING 0x8000000AL + + +#define E_NOTIMPL 0x80004001L +#define E_NOINTERFACE 0x80004002L +#define E_POINTER 0x80004003L +#define E_ABORT 0x80004004L +#define E_FAIL 0x80004005L +/* FIXME: E_UNSPEC is not a standard value but it is used by + * FileMoniker, IOleLink and DoDragDrop as a return value. + */ +#define E_UNSPEC E_FAIL + + +#define CO_E_INIT_TLS 0x80004006L +#define CO_E_INIT_SHARED_ALLOCATOR 0x80004007L +#define CO_E_INIT_MEMORY_ALLOCATOR 0x80004008L +#define CO_E_INIT_CLASS_CACHE 0x80004009L +#define CO_E_INIT_RPC_CHANNEL 0x8000400AL +#define CO_E_INIT_TLS_SET_CHANNEL_CONTROL 0x8000400BL +#define CO_E_INIT_TLS_CHANNEL_CONTROL 0x8000400CL +#define CO_E_INIT_UNACCEPTED_USER_ALLOCATOR 0x8000400DL +#define CO_E_INIT_SCM_MUTEX_EXISTS 0x8000400EL +#define CO_E_INIT_SCM_FILE_MAPPING_EXISTS 0x8000400FL +#define CO_E_INIT_SCM_MAP_VIEW_OF_FILE 0x80004010L +#define CO_E_INIT_SCM_EXEC_FAILURE 0x80004011L +#define CO_E_INIT_ONLY_SINGLE_THREADED 0x80004012L + +#define E_UNEXPECTED 0x8000FFFFL + +#define RPC_E_CALL_REJECTED 0x80010001L +#define RPC_E_CALL_CANCELED 0x80010002L +#define RPC_E_CANTPOST_INSENDCALL 0x80010003L +#define RPC_E_CANTCALLOUT_INASYNCCALL 0x80010004L +#define RPC_E_CANTCALLOUT_INEXTERNALCALL 0x80010005L +#define RPC_E_CONNECTION_TERMINATED 0x80010006L +#define RPC_E_SERVER_DIED 0x80010007L +#define RPC_E_CLIENT_DIED 0x80010008L +#define RPC_E_INVALID_DATAPACKET 0x80010009L +#define RPC_E_CANTTRANSMIT_CALL 0x8001000AL +#define RPC_E_CLIENT_CANTMARSHAL_DATA 0x8001000BL +#define RPC_E_CLIENT_CANTUNMARSHAL_DATA 0x8001000CL +#define RPC_E_SERVER_CANTMARSHAL_DATA 0x8001000DL +#define RPC_E_SERVER_CANTUNMARSHAL_DATA 0x8001000EL +#define RPC_E_INVALID_DATA 0x8001000FL +#define RPC_E_INVALID_PARAMETER 0x80010010L +#define RPC_E_CANTCALLOUT_AGAIN 0x80010011L +#define RPC_E_SERVER_DIED_DNE 0x80010012L +#define RPC_E_SYS_CALL_FAILED 0x80010100L +#define RPC_E_OUT_OF_RESOURCES 0x80010101L +#define RPC_E_ATTEMPTED_MULTITHREAD 0x80010102L +#define RPC_E_NOT_REGISTERED 0x80010103L +#define RPC_E_FAULT 0x80010104L +#define RPC_E_SERVERFAULT 0x80010105L +#define RPC_E_CHANGED_MODE 0x80010106L +#define RPC_E_INVALIDMETHOD 0x80010107L +#define RPC_E_DISCONNECTED 0x80010108L +#define RPC_E_RETRY 0x80010109L +#define RPC_E_SERVERCALL_RETRYLATER 0x8001010AL +#define RPC_E_SERVERCALL_REJECTED 0x8001010BL +#define RPC_E_INVALID_CALLDATA 0x8001010CL +#define RPC_E_CANTCALLOUT_ININPUTSYNCCALL 0x8001010DL +#define RPC_E_WRONG_THREAD 0x8001010EL +#define RPC_E_THREAD_NOT_INIT 0x8001010FL +#define RPC_E_VERSION_MISMATCH 0x80010110L +#define RPC_E_INVALID_HEADER 0x80010111L +#define RPC_E_INVALID_EXTENSION 0x80010112L +#define RPC_E_INVALID_IPID 0x80010113L +#define RPC_E_INVALID_OBJECT 0x80010114L +#define RPC_S_CALLPENDING 0x80010115L +#define RPC_S_WAITONTIMER 0x80010116L +#define RPC_E_CALL_COMPLETE 0x80010117L +#define RPC_E_UNSECURE_CALL 0x80010118L +#define RPC_E_TOO_LATE 0x80010119L +#define RPC_E_NO_GOOD_SECURITY_PACKAGES 0x8001011AL +#define RPC_E_ACCESS_DENIED 0x8001011BL +#define RPC_E_REMOTE_DISABLED 0x8001011CL +#define RPC_E_INVALID_OBJREF 0x8001011DL +#define RPC_E_NO_CONTEXT 0x8001011EL +#define RPC_E_TIMEOUT 0x8001011FL +#define RPC_E_NO_SYNC 0x80010120L +#define RPC_E_UNEXPECTED 0x8001FFFFL + +#define DISP_E_UNKNOWNINTERFACE 0x80020001L +#define DISP_E_MEMBERNOTFOUND 0x80020003L +#define DISP_E_PARAMNOTFOUND 0x80020004L +#define DISP_E_TYPEMISMATCH 0x80020005L +#define DISP_E_UNKNOWNNAME 0x80020006L +#define DISP_E_NONAMEDARGS 0x80020007L +#define DISP_E_BADVARTYPE 0x80020008L +#define DISP_E_EXCEPTION 0x80020009L +#define DISP_E_OVERFLOW 0x8002000AL +#define DISP_E_BADINDEX 0x8002000BL +#define DISP_E_UNKNOWNLCID 0x8002000CL +#define DISP_E_ARRAYISLOCKED 0x8002000DL +#define DISP_E_BADPARAMCOUNT 0x8002000EL +#define DISP_E_PARAMNOTOPTIONAL 0x8002000FL +#define DISP_E_BADCALLEE 0x80020010L +#define DISP_E_NOTACOLLECTION 0x80020011L +#define DISP_E_DIVBYZERO 0x80020012L + +#define TYPE_E_BUFFERTOOSMALL 0x80028016L +#define TYPE_E_FIELDNOTFOUND 0x80028017L +#define TYPE_E_INVDATAREAD 0x80028018L +#define TYPE_E_UNSUPFORMAT 0x80028019L +#define TYPE_E_REGISTRYACCESS 0x8002801CL +#define TYPE_E_LIBNOTREGISTERED 0x8002801DL +#define TYPE_E_UNDEFINEDTYPE 0x80028027L +#define TYPE_E_QUALIFIEDNAMEDISALLOWED 0x80028028L +#define TYPE_E_INVALIDSTATE 0x80028029L +#define TYPE_E_WRONGTYPEKIND 0x8002802AL +#define TYPE_E_ELEMENTNOTFOUND 0x8002802BL +#define TYPE_E_AMBIGUOUSNAME 0x8002802CL +#define TYPE_E_NAMECONFLICT 0x8002802DL +#define TYPE_E_UNKNOWNLCID 0x8002802EL +#define TYPE_E_DLLFUNCTIONNOTFOUND 0x8002802FL +#define TYPE_E_BADMODULEKIND 0x800288BDL +#define TYPE_E_SIZETOOBIG 0x800288C5L +#define TYPE_E_DUPLICATEID 0x800288C6L +#define TYPE_E_INVALIDID 0x800288CFL +#define TYPE_E_TYPEMISMATCH 0x80028CA0L +#define TYPE_E_OUTOFBOUNDS 0x80028CA1L +#define TYPE_E_IOERROR 0x80028CA2L +#define TYPE_E_CANTCREATETMPFILE 0x80028CA3L +#define TYPE_E_CANTLOADLIBRARY 0x80029C4AL +#define TYPE_E_INCONSISTENTPROPFUNCS 0x80029C83L +#define TYPE_E_CIRCULARTYPE 0x80029C84L + +#define STG_S_CONVERTED 0x00030200L +#define STG_S_BLOCK 0x00030201L +#define STG_S_RETRYNOW 0x00030202L +#define STG_S_MONITORING 0x00030203L +#define STG_S_MULTIPLEOPENS 0x00030204L +#define STG_S_CONSOLIDATIONFAILED 0x00030205L +#define STG_S_CANNOTCONSOLIDATE 0x00030206L + +#define STG_E_INVALIDFUNCTION 0x80030001L +#define STG_E_FILENOTFOUND 0x80030002L +#define STG_E_PATHNOTFOUND 0x80030003L +#define STG_E_TOOMANYOPENFILES 0x80030004L +#define STG_E_ACCESSDENIED 0x80030005L +#define STG_E_INVALIDHANDLE 0x80030006L +#define STG_E_INSUFFICIENTMEMORY 0x80030008L +#define STG_E_INVALIDPOINTER 0x80030009L +#define STG_E_NOMOREFILES 0x80030012L +#define STG_E_DISKISWRITEPROTECTED 0x80030013L +#define STG_E_SEEKERROR 0x80030019L +#define STG_E_WRITEFAULT 0x8003001DL +#define STG_E_READFAULT 0x8003001EL +#define STG_E_SHAREVIOLATION 0x80030020L +#define STG_E_LOCKVIOLATION 0x80030021L +#define STG_E_FILEALREADYEXISTS 0x80030050L +#define STG_E_INVALIDPARAMETER 0x80030057L +#define STG_E_MEDIUMFULL 0x80030070L +#define STG_E_ABNORMALAPIEXIT 0x800300FAL +#define STG_E_INVALIDHEADER 0x800300FBL +#define STG_E_INVALIDNAME 0x800300FCL +#define STG_E_UNKNOWN 0x800300FDL +#define STG_E_UNIMPLEMENTEDFUNCTION 0x800300FEL +#define STG_E_INVALIDFLAG 0x800300FFL +#define STG_E_INUSE 0x80030100L +#define STG_E_NOTCURRENT 0x80030101L +#define STG_E_REVERTED 0x80030102L +#define STG_E_CANTSAVE 0x80030103L +#define STG_E_OLDFORMAT 0x80030104L +#define STG_E_OLDDLL 0x80030105L +#define STG_E_SHAREREQUIRED 0x80030106L +#define STG_E_NOTFILEBASEDSTORAGE 0x80030107L +#define STG_E_EXTANTMARSHALLINGS 0x80030108L + +#define OLE_S_FIRST 0x00040000L +#define OLE_S_USEREG 0x00040000L +#define OLE_S_STATIC 0x00040001L +#define OLE_S_MAC_CLIPFORMAT 0x00040002L +#define OLE_S_LAST 0x000400FFL + +#define OLE_E_FIRST 0x80040000L +#define OLE_E_OLEVERB 0x80040000L +#define OLE_E_ADVF 0x80040001L +#define OLE_E_ENUM_NOMORE 0x80040002L +#define OLE_E_ADVISENOTSUPPORTED 0x80040003L +#define OLE_E_NOCONNECTION 0x80040004L +#define OLE_E_NOTRUNNING 0x80040005L +#define OLE_E_NOCACHE 0x80040006L +#define OLE_E_BLANK 0x80040007L +#define OLE_E_CLASSDIFF 0x80040008L +#define OLE_E_CANT_GETMONIKER 0x80040009L +#define OLE_E_CANT_BINDTOSOURCE 0x8004000AL +#define OLE_E_STATIC 0x8004000BL +#define OLE_E_PROMPTSAVECANCELLED 0x8004000CL +#define OLE_E_INVALIDRECT 0x8004000DL +#define OLE_E_WRONGCOMPOBJ 0x8004000EL +#define OLE_E_INVALIDHWND 0x8004000FL +#define OLE_E_NOT_INPLACEACTIVE 0x80040010L +#define OLE_E_CANTCONVERT 0x80040011L +#define OLE_E_NOSTORAGE 0x80040012L +#define DV_E_FORMATETC 0x80040064L +#define DV_E_DVTARGETDEVICE 0x80040065L +#define DV_E_STGMEDIUM 0x80040066L +#define DV_E_STATDATA 0x80040067L +#define DV_E_LINDEX 0x80040068L +#define DV_E_TYMED 0x80040069L +#define DV_E_CLIPFORMAT 0x8004006AL +#define DV_E_DVASPECT 0x8004006BL +#define DV_E_DVTARGETDEVICE_SIZE 0x8004006CL +#define DV_E_NOIVIEWOBJECT 0x8004006DL +#define OLE_E_LAST 0x800400FFL + +#define DRAGDROP_S_FIRST 0x00040100L +#define DRAGDROP_S_DROP 0x00040100L +#define DRAGDROP_S_CANCEL 0x00040101L +#define DRAGDROP_S_USEDEFAULTCURSORS 0x00040102L +#define DRAGDROP_S_LAST 0x0004010FL + +#define DRAGDROP_E_FIRST 0x80040100L +#define DRAGDROP_E_NOTREGISTERED 0x80040100L +#define DRAGDROP_E_ALREADYREGISTERED 0x80040101L +#define DRAGDROP_E_INVALIDHWND 0x80040102L +#define DRAGDROP_E_LAST 0x8004010FL + + +#define CLASSFACTORY_S_FIRST 0x00040110L +#define CLASSFACTORY_S_LAST 0x0004011FL + +#define CLASSFACTORY_E_FIRST 0x80040110L +#define CLASS_E_NOAGGREGATION 0x80040110L +#define CLASS_E_CLASSNOTAVAILABLE 0x80040111L +#define CLASS_E_NOTLICENSED 0x80040112L +#define CLASSFACTORY_E_LAST 0x8004011FL + +#define MARSHAL_S_FIRST 0x00040120L +#define MARSHAL_S_LAST 0x0004012FL + +#define MARSHAL_E_FIRST 0x80040120L +#define MARSHAL_E_LAST 0x8004012FL + +#define DATA_S_FIRST 0x00040130L +#define DATA_S_SAMEFORMATETC 0x00040130L +#define DATA_S_LAST 0x0004013FL + +#define DATA_E_FIRST 0x80040130L +#define DATA_E_LAST 0x8004013FL + +#define VIEW_S_FIRST 0x00040140L +#define VIEW_S_ALREADY_FROZEN 0x00040140L +#define VIEW_S_LAST 0x0004014FL + +#define VIEW_E_FIRST 0x80040140L +#define VIEW_E_DRAW 0x80040140L +#define VIEW_E_LAST 0x8004014FL + +#define REGDB_S_FIRST 0x00040150L +#define REGDB_S_LAST 0x0004015FL + +#define REGDB_E_FIRST 0x80040150L +#define REGDB_E_READREGDB 0x80040150L +#define REGDB_E_WRITEREGDB 0x80040151L +#define REGDB_E_KEYMISSING 0x80040152L +#define REGDB_E_INVALIDVALUE 0x80040153L +#define REGDB_E_CLASSNOTREG 0x80040154L +#define REGDB_E_IIDNOTREG 0x80040155L +#define REGDB_E_LAST 0x8004015FL + +#define CACHE_S_FIRST 0x00040170L +#define CACHE_S_FORMATETC_NOTSUPPORTED 0x00040170L +#define CACHE_S_SAMECACHE 0x00040171L +#define CACHE_S_SOMECACHES_NOTUPDATED 0x00040172L +#define CACHE_S_LAST 0x0004017FL + +#define CACHE_E_FIRST 0x80040170L +#define CACHE_E_NOCACHE_UPDATED 0x80040170L +#define CACHE_E_LAST 0x8004017FL + +#define OLEOBJ_S_FIRST 0x00040180L +#define OLEOBJ_S_INVALIDVERB 0x00040180L +#define OLEOBJ_S_CANNOT_DOVERB_NOW 0x00040181L +#define OLEOBJ_S_INVALIDHWND 0x00040182L +#define OLEOBJ_S_LAST 0x0004018FL + +#define OLEOBJ_E_FIRST 0x80040180L +#define OLEOBJ_E_NOVERBS 0x80040180L +#define OLEOBJ_E_INVALIDVERB 0x80040181L +#define OLEOBJ_E_LAST 0x8004018FL + +#define CLIENTSITE_S_FIRST 0x00040190L +#define CLIENTSITE_S_LAST 0x0004019FL + +#define CLIENTSITE_E_FIRST 0x80040190L +#define CLIENTSITE_E_LAST 0x8004019FL + +#define INPLACE_S_FIRST 0x000401A0L +#define INPLACE_S_TRUNCATED 0x000401A0L +#define INPLACE_S_LAST 0x000401AFL + +#define INPLACE_E_FIRST 0x800401A0L +#define INPLACE_E_NOTUNDOABLE 0x800401A0L +#define INPLACE_E_NOTOOLSPACE 0x800401A1L +#define INPLACE_E_LAST 0x800401AFL + +#define ENUM_S_FIRST 0x000401B0L +#define ENUM_S_LAST 0x000401BFL + +#define ENUM_E_FIRST 0x800401B0L +#define ENUM_E_LAST 0x800401BFL + +#define CONVERT10_S_FIRST 0x000401C0L +#define CONVERT10_S_NO_PRESENTATION 0x000401C0L +#define CONVERT10_S_LAST 0x000401CFL + +#define CONVERT10_E_FIRST 0x800401C0L +#define CONVERT10_E_OLESTREAM_GET 0x800401C0L +#define CONVERT10_E_OLESTREAM_PUT 0x800401C1L +#define CONVERT10_E_OLESTREAM_FMT 0x800401C2L +#define CONVERT10_E_OLESTREAM_BITMAP_TO_DIB 0x800401C3L +#define CONVERT10_E_STG_FMT 0x800401C4L +#define CONVERT10_E_STG_NO_STD_STREAM 0x800401C5L +#define CONVERT10_E_STG_DIB_TO_BITMAP 0x800401C6L +#define CONVERT10_E_LAST 0x800401CFL + +#define CLIPBRD_S_FIRST 0x000401D0L +#define CLIPBRD_S_LAST 0x000401DFL + +#define CLIPBRD_E_FIRST 0x800401D0L +#define CLIPBRD_E_LAST 0x800401DFL +#define CLIPBRD_E_CANT_OPEN 0x800401D0L +#define CLIPBRD_E_CANT_EMPTY 0x800401D1L +#define CLIPBRD_E_CANT_SET 0x800401D2L +#define CLIPBRD_E_BAD_DATA 0x800401D3L +#define CLIPBRD_E_CANT_CLOSE 0x800401D4L + +#define MK_S_FIRST 0x000401E0L +#define MK_S_REDUCED_TO_SELF 0x000401E2L +#define MK_S_ME 0x000401E4L +#define MK_S_HIM 0x000401E5L +#define MK_S_US 0x000401E6L +#define MK_S_MONIKERALREADYREGISTERED 0x000401E7L +#define MK_S_LAST 0x000401EFL + +#define MK_E_FIRST 0x800401E0L +#define MK_E_CONNECTMANUALLY 0x800401E0L +#define MK_E_EXCEEDEDDEADLINE 0x800401E1L +#define MK_E_NEEDGENERIC 0x800401E2L +#define MK_E_UNAVAILABLE 0x800401E3L +#define MK_E_SYNTAX 0x800401E4L +#define MK_E_NOOBJECT 0x800401E5L +#define MK_E_INVALIDEXTENSION 0x800401E6L +#define MK_E_INTERMEDIATEINTERFACENOTSUPPORTED 0x800401E7L +#define MK_E_NOTBINDABLE 0x800401E8L +#define MK_E_NOTBOUND 0x800401E9L +#define MK_E_CANTOPENFILE 0x800401EAL +#define MK_E_MUSTBOTHERUSER 0x800401EBL +#define MK_E_NOINVERSE 0x800401ECL +#define MK_E_NOSTORAGE 0x800401EDL +#define MK_E_NOPREFIX 0x800401EEL +#define MK_E_ENUMERATION_FAILED 0x800401EFL +#define MK_E_LAST 0x800401EFL + +#define CO_S_FIRST 0x000401F0L +#define CO_S_LAST 0x000401FFL + +#define CO_E_FIRST 0x800401F0L +#define CO_E_NOTINITIALIZED 0x800401F0L +#define CO_E_ALREADYINITIALIZED 0x800401F1L +#define CO_E_CANTDETERMINECLASS 0x800401F2L +#define CO_E_CLASSSTRING 0x800401F3L +#define CO_E_IIDSTRING 0x800401F4L +#define CO_E_APPNOTFOUND 0x800401F5L +#define CO_E_APPSINGLEUSE 0x800401F6L +#define CO_E_ERRORINAPP 0x800401F7L +#define CO_E_DLLNOTFOUND 0x800401F8L +#define CO_E_ERRORINDLL 0x800401F9L +#define CO_E_WRONGOSFORAPP 0x800401FAL +#define CO_E_OBJNOTREG 0x800401FBL +#define CO_E_OBJISREG 0x800401FCL +#define CO_E_OBJNOTCONNECTED 0x800401FDL +#define CO_E_APPDIDNTREG 0x800401FEL +#define CO_E_RELEASED 0x800401FFL +#define CO_E_LAST 0x800401FFL +#define CO_E_FAILEDTOIMPERSONATE 0x80040200L +#define CO_E_FAILEDTOGETSECCTX 0x80040201L +#define CO_E_FAILEDTOOPENTHREADTOKEN 0x80040202L +#define CO_E_FAILEDTOGETTOKENINFO 0x80040203L +#define CO_E_TRUSTEEDOESNTMATCHCLIENT 0x80040204L +#define CO_E_FAILEDTOQUERYCLIENTBLANKET 0x80040205L +#define CO_E_FAILEDTOSETDACL 0x80040206L +#define CO_E_ACCESSCHECKFAILED 0x80040207L +#define CO_E_NETACCESSAPIFAILED 0x80040208L +#define CO_E_WRONGTRUSTEENAMESYNTAX 0x80040209L +#define CO_E_INVALIDSID 0x8004020AL +#define CO_E_CONVERSIONFAILED 0x8004020BL +#define CO_E_NOMATCHINGSIDFOUND 0x8004020CL +#define CO_E_LOOKUPACCSIDFAILED 0x8004020DL +#define CO_E_NOMATCHINGNAMEFOUND 0x8004020EL +#define CO_E_LOOKUPACCNAMEFAILED 0x8004020FL +#define CO_E_SETSERLHNDLFAILED 0x80040210L +#define CO_E_FAILEDTOGETWINDIR 0x80040211L +#define CO_E_PATHTOOLONG 0x80040212L +#define CO_E_FAILEDTOGENUUID 0x80040213L +#define CO_E_FAILEDTOCREATEFILE 0x80040214L +#define CO_E_FAILEDTOCLOSEHANDLE 0x80040215L +#define CO_E_EXCEEDSYSACLLIMIT 0x80040216L +#define CO_E_ACESINWRONGORDER 0x80040217L +#define CO_E_INCOMPATIBLESTREAMVERSION 0x80040218L +#define CO_E_FAILEDTOOPENPROCESSTOKEN 0x80040219L +#define CO_E_DECODEFAILED 0x8004021AL +#define CO_E_ACNOTINITIALIZED 0x8004021BL + +#define E_ACCESSDENIED 0x80070005L +#define E_HANDLE 0x80070006L +#define E_OUTOFMEMORY 0x8007000EL +#define E_INVALIDARG 0x80070057L + +#define CO_S_NOTALLINTERFACES 0x00080012L + +#define CO_E_CLASS_CREATE_FAILED 0x80080001L +#define CO_E_SCM_ERROR 0x80080002L +#define CO_E_SCM_RPC_FAILURE 0x80080003L +#define CO_E_BAD_PATH 0x80080004L +#define CO_E_SERVER_EXEC_FAILURE 0x80080005L +#define CO_E_OBJSRV_RPC_FAILURE 0x80080006L +#define MK_E_NO_NORMALIZED 0x80080007L +#define CO_E_SERVER_STOPPING 0x80080008L +#define MEM_E_INVALID_ROOT 0x80080009L +#define MEM_E_INVALID_LINK 0x80080010L +#define MEM_E_INVALID_SIZE 0x80080011L + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GNU_H_WINDOWS32_ERROR */ diff --git a/include/excpt.h b/include/excpt.h new file mode 100644 index 0000000..a10c909 --- /dev/null +++ b/include/excpt.h @@ -0,0 +1,121 @@ +/* + * excpt.h + * + * Support for operating system level structured exception handling. + * + * NOTE: This is very preliminary stuff. I am also pretty sure it is + * completely Intel specific. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * Based on code by Mikey + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _EXCPT_H_ +#define _EXCPT_H_ + +#ifndef __STRICT_ANSI__ + +#include + +/* + * NOTE: The constants structs and typedefs below should be defined in the + * Win32 API headers. + */ +#define EH_NONCONTINUABLE 0x01 +#define EH_UNWINDING 0x02 +#define EH_EXIT_UNWIND 0x04 +#define EH_STACK_INVALID 0x08 +#define EH_NESTED_CALL 0x10 + +#ifndef RC_INVOKED + +typedef enum { + ExceptionContinueExecution, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind +} EXCEPTION_DISPOSITION; + + +/* + * End of stuff that should be in the Win32 API files. + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The type of function that is expected as an exception handler to be + * installed with _try1. + */ +typedef EXCEPTION_DISPOSITION (*PEXCEPTION_HANDLER) + (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*); + +/* + * This is not entirely necessary, but it is the structure installed by + * the _try1 primitive below. + */ +typedef struct _EXCEPTION_REGISTRATION +{ + struct _EXCEPTION_REGISTRATION* prev; + PEXCEPTION_HANDLER handler; +} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION; + +typedef EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION_RECORD; +typedef PEXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION_RECORD; + +/* + * A macro which installs the supplied exception handler. + * Push the pointer to the new handler onto the stack, + * then push the pointer to the old registration structure (at fs:0) + * onto the stack, then put a pointer to the new registration + * structure (i.e. the current stack pointer) at fs:0. + */ +#define __try1(pHandler) \ + __asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (pHandler)); + + +/* + * A macro which (dispite its name) *removes* an installed + * exception handler. Should be used only in conjunction with the above + * install routine __try1. + * Move the pointer to the old reg. struct (at the current stack + * position) to fs:0, replacing the pointer we installed above, + * then add 8 to the stack pointer to get rid of the space we + * used when we pushed on our new reg. struct above. Notice that + * the stack must be in the exact state at this point that it was + * after we did _try1 or this will smash things. + */ +#define __except1 \ + __asm__ ("movl (%%esp),%%eax;movl %%eax,%%fs:0;addl $8,%%esp;" \ + : : : "%eax"); + +#ifdef __cplusplus +} +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* Not strict ANSI */ + +#endif /* _EXCPT_H_ not defined */ diff --git a/include/fmifs.h b/include/fmifs.h new file mode 100644 index 0000000..8268b44 --- /dev/null +++ b/include/fmifs.h @@ -0,0 +1,129 @@ +#ifndef _FMIFS_H +#define _FMIFS_H +/* $Id$ + * + * fmifs.h + * + * Copyright (c) 1998 Mark Russinovich + * Systems Internals + * http://www.sysinternals.com + * + * Typedefs and definitions for using chkdsk and formatex + * functions exported by the fmifs.dll library. + * + * --- + * + * 1999-02-18 (Emanuele Aliberti) + * Normalized function names. + * + */ +#ifndef _INC_WINDOWS_ +#include +#endif + +/* Output command */ +typedef +struct +{ + DWORD Lines; + PCHAR Output; + +} TEXTOUTPUT, *PTEXTOUTPUT; + + +/* Callback command types */ +typedef +enum +{ + PROGRESS, + DONEWITHSTRUCTURE, + UNKNOWN2, + UNKNOWN3, + UNKNOWN4, + UNKNOWN5, + INSUFFICIENTRIGHTS, + UNKNOWN7, + UNKNOWN8, + UNKNOWN9, + UNKNOWNA, + DONE, + UNKNOWNC, + UNKNOWND, + OUTPUT, + STRUCTUREPROGRESS + +} CALLBACKCOMMAND; + + +/* FMIFS callback definition */ +typedef +BOOL +(STDCALL * PFMIFSCALLBACK) ( + CALLBACKCOMMAND Command, + DWORD SubAction, + PVOID ActionInfo + ); + +/* Chkdsk command in FMIFS */ +VOID +STDCALL +Chkdsk( + PWCHAR DriveRoot, + PWCHAR Format, + BOOL CorrectErrors, + BOOL Verbose, + BOOL CheckOnlyIfDirty, + BOOL ScanDrive, + PVOID Unused2, + PVOID Unused3, + PFMIFSCALLBACK Callback + ); + +/* ChkdskEx command in FMIFS (not in the original) */ +VOID +STDCALL +ChkDskEx( + PWCHAR DriveRoot, + PWCHAR Format, + BOOL CorrectErrors, + BOOL Verbose, + BOOL CheckOnlyIfDirty, + BOOL ScanDrive, + PVOID Unused2, + PVOID Unused3, + PFMIFSCALLBACK Callback + ); + +/* DiskCopy command in FMIFS */ + +VOID +STDCALL +DiskCopy(VOID); + +/* Enable/Disable volume compression */ +BOOL +STDCALL +EnableVolumeCompression( + PWCHAR DriveRoot, + BOOL Enable + ); + +/* Format command in FMIFS */ + +/* media flags */ +#define FMIFS_HARDDISK 0xC +#define FMIFS_FLOPPY 0x8 + +VOID +STDCALL +FormatEx( + PWCHAR DriveRoot, + DWORD MediaFlag, + PWCHAR Format, + PWCHAR Label, + BOOL QuickFormat, + DWORD ClusterSize, + PFMIFSCALLBACK Callback + ); + +#endif /* ndef _FMIFS_H */ diff --git a/include/freetype/config/ftconfig.h b/include/freetype/config/ftconfig.h new file mode 100644 index 0000000..338e22c --- /dev/null +++ b/include/freetype/config/ftconfig.h @@ -0,0 +1,187 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This header file contains a number of macro definitions that are used */ + /* by the rest of the engine. Most of the macros here are automatically */ + /* determined at compile time, and you should not need to change it to */ + /* port FreeType, except to compile the library with a non-ANSI */ + /* compiler. */ + /* */ + /* Note however that if some specific modifications are needed, we */ + /* advise you to place a modified copy in your build directory. */ + /* */ + /* The build directory is usually `freetype/builds/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /* This ANSI version should stay in `include/freetype/config'. */ + /* */ + /*************************************************************************/ + + +#ifndef FTCONFIG_H +#define FTCONFIG_H + + + /* Include the header file containing all developer build options */ +#include + + + /*************************************************************************/ + /* */ + /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled to suit a specific system. The current */ + /* ones are defaults used to compile FreeType in an ANSI C environment */ + /* (16bit compilers are also supported). Copy this file to your own */ + /* `freetype/builds/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + + /* We use values to know the sizes of the types. */ +#include + + /* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define FT_SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define FT_SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#define FT_SIZEOF_INT 8 +#else +#error "Unsupported number of bytes in `int' type!" +#endif + + /* The number of bytes in a `long' type. */ +#if ULONG_MAX == 0xFFFFFFFF +#define FT_SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define FT_SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + + + /* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + /* UNUSED is a macro used to indicate that a given parameter is not used */ + /* -- this is only used to get rid of unpleasant compiler warnings */ +#ifndef FT_UNUSED +#define FT_UNUSED( arg ) ( (arg) = (arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you are doing. No */ + /* porter should need to mess with them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* IntN types */ + /* */ + /* Used to guarantee the size of some specific integers. */ + /* */ + typedef signed short FT_Int16; + typedef unsigned short FT_UInt16; + +#if FT_SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_UInt32; + +#elif FT_SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_UInt32; + +#else +#error "no 32bit type found -- please check your configuration files" +#endif + +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro in */ + /* `ftoption.h'. */ + /* */ + /* Note that this will produce many -ansi warnings during library */ + /* compilation, and that in many cases, the generated code will be */ + /* neither smaller nor faster! */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define FT_LONG64 +#define FT_INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif /* FT_SIZEOF_LONG == 8 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT +#define LOCAL_DEF static +#define LOCAL_FUNC static +#else +#define LOCAL_DEF extern +#define LOCAL_FUNC /* nothing */ +#endif + +#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT +#define BASE_DEF( x ) static x +#define BASE_FUNC( x ) static x +#else +#define BASE_DEF( x ) extern x +#define BASE_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_DEF +#define FT_EXPORT_DEF( x ) extern x +#endif + +#ifndef FT_EXPORT_FUNC +#define FT_EXPORT_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/include/freetype/config/ftmodule.h b/include/freetype/config/ftmodule.h new file mode 100644 index 0000000..50cc46b --- /dev/null +++ b/include/freetype/config/ftmodule.h @@ -0,0 +1,10 @@ +FT_USE_MODULE(autohint_module_class) +FT_USE_MODULE(cff_driver_class) +FT_USE_MODULE(t1cid_driver_class) +FT_USE_MODULE(psnames_module_class) +FT_USE_MODULE(ft_raster1_renderer_class) +FT_USE_MODULE(sfnt_module_class) +FT_USE_MODULE(ft_smooth_renderer_class) +FT_USE_MODULE(tt_driver_class) +FT_USE_MODULE(t1_driver_class) +FT_USE_MODULE(winfnt_driver_class) diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h new file mode 100644 index 0000000..a7e1f40 --- /dev/null +++ b/include/freetype/config/ftoption.h @@ -0,0 +1,395 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTOPTION_H +#define FTOPTION_H + + + /*************************************************************************/ + /* */ + /* USER-SELECTABLE CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled by developers to enable or disable */ + /* certain aspects of FreeType. This is a default file, where all major */ + /* options are enabled. */ + /* */ + /* Note that if some modifications are required for your build, we */ + /* advise you to put a modified copy of this file in your build */ + /* directory, rather than modifying it in-place. */ + /* */ + /* The build directory is normally `freetype/builds/' and */ + /* contains build or system-specific files that are included in */ + /* priority when building the library. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Convenience functions support */ + /* */ + /* Some functions of the FreeType 2 API are provided as a convenience */ + /* for client applications and developers. However, they are not */ + /* required to build and run the library itself. */ + /* */ + /* By defining this configuration macro, you'll disable the */ + /* compilation of these functions at build time. This can be useful */ + /* to reduce the library's code size when you don't need any of */ + /* these functions. */ + /* */ + /* All convenience functions are declared as such in their */ + /* documentation. */ + /* */ +#undef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS + + + /*************************************************************************/ + /* */ + /* Alternate Glyph Image Format support */ + /* */ + /* By default, the glyph images returned by the FreeType glyph loader */ + /* can either be a pixmap or a vectorial outline defined through */ + /* Bezier control points. When defining the following configuration */ + /* macro, some font drivers will be able to register alternate */ + /* glyph image formats. */ + /* */ + /* Unset this macro if you are sure that you will never use a font */ + /* driver with an alternate glyph format; this will reduce the size of */ + /* the base layer code. */ + /* */ + /* Note that a few Type 1 fonts, as well as Windows `vector' fonts */ + /* use a vector `plotter' format that isn't supported when this */ + /* macro is undefined. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + + /*************************************************************************/ + /* */ + /* Glyph Postscript Names handling */ + /* */ + /* By default, FreeType 2 is compiled with the `PSNames' module. This */ + /* This module is in charge of converting a glyph name string into a */ + /* Unicode value, or return a Macintosh standard glyph name for the */ + /* use with the TrueType `post' table. */ + /* */ + /* Undefine this macro if you do not want `PSNames' compiled in your */ + /* build of FreeType. This has the following effects: */ + /* */ + /* - The TrueType driver will provide its own set of glyph names, */ + /* if you build it to support postscript names in the TrueType */ + /* `post' table. */ + /* */ + /* - The Type 1 driver will not be able to synthetize a Unicode */ + /* charmap out of the glyphs found in the fonts. */ + /* */ + /* You would normally undefine this configuration macro when building */ + /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ + /* */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Postscript Names to Unicode Values support */ + /* */ + /* By default, FreeType 2 is built with the `PSNames' module compiled */ + /* in. Among other things, the module is used to convert a glyph name */ + /* into a Unicode value. This is especially useful in order to */ + /* synthetize on the fly a Unicode charmap from the CFF/Type 1 driver */ + /* through a big table named the `Adobe Glyph List' (AGL). */ + /* */ + /* Undefine this macro if you do not want the Adobe Glyph List */ + /* compiled in your `PSNames' module. The Type 1 driver will not be */ + /* able to synthetize a Unicode charmap out of the glyphs found in the */ + /* fonts. */ + /* */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro. Note that */ + /* this will produce many -ansi warnings during library compilation, and */ + /* that in many cases the generated code will not be smaller or faster! */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* DLL export compilation */ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front OR after the return type of function */ + /* declarations. */ + /* */ + /* Two macros are used within the FreeType source code to define */ + /* exported library functions: FT_EXPORT_DEF and FT_EXPORT_FUNC. */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_FUNC( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_FUNC( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT_DEF and */ + /* FT_EXPORT_FUNC here if you want. If you leave them undefined, they */ + /* will be later automatically defined as `extern return_type' to */ + /* allow normal compilation. */ + /* */ +#undef FT_EXPORT_DEF +#undef FT_EXPORT_FUNC + + + /*************************************************************************/ + /* */ + /* Debug level */ + /* */ + /* FreeType can be compiled in debug or trace mode. In debug mode, */ + /* errors are reported through the `ftdebug' component. In trace */ + /* mode, additional messages are sent to the standard output during */ + /* execution. */ + /* */ + /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ + /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ + /* */ + /* Don't define any of these macros to compile in `release' mode! */ + /* */ +#define FT_DEBUG_LEVEL_ERROR +#define FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Computation Algorithms */ + /* */ + /* Used for debugging, this configuration macro should disappear */ + /* soon. */ + /* */ +#define FT_CONFIG_OPTION_OLD_CALCS + + + /*************************************************************************/ + /* */ + /* The size in bytes of the render pool used by the scan-line converter */ + /* to do all of its work. */ + /* */ + /* This must be greater than 4kByte. */ + /* */ +#define FT_RENDER_POOL_SIZE 16384 + + + /*************************************************************************/ + /* */ + /* FT_MAX_MODULES */ + /* */ + /* The maximum number of modules that can be registered in a single */ + /* FreeType library object. 16 is the default. */ + /* */ +#define FT_MAX_MODULES 16 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a single */ + /* font driver. 8 is the default. */ + /* */ + /* If you don't know what this means, you certainly do not need to */ + /* change this value. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in all formats using the SFNT module (namely */ + /* TrueType & OpenType). */ + /* */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ + /* load and enumerate the glyph Postscript names in a TrueType or */ + /* OpenType file. */ + /* */ + /* Note that when you do not compile the `PSNames' module by undefining */ + /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ + /* contain additional code used to read the PS Names table from a font. */ + /* */ + /* (By default, the module uses `PSNames' to extract glyph names.) */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ + /* access the internal name table in a SFNT-based format like TrueType */ + /* or OpenType. The name table contains various strings used to */ + /* describe the font, like family name, copyright, version, etc. It */ + /* does not contain any glyph name though. */ + /* */ + /* Accessing SFNT names is done through the functions declared in */ + /* `freetype/ftnames.h'. */ + /* */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ + /* a bytecode interpreter in the TrueType driver. Note that there are */ + /* important patent issues related to the use of the interpreter. */ + /* */ + /* By undefining this, you will only compile the code necessary to load */ + /* TrueType glyphs without hinting. */ + /* */ +#undef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */ + /* bytecode interpreter with a huge switch statement, rather than a call */ + /* table. This results in smaller and faster code for a number of */ + /* architectures. */ + /* */ + /* Note however that on some compiler/processor combinations, undefining */ + /* this macro will generate faster, though larger, code. */ + /* */ +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* T1_MAX_STACK_DEPTH is the maximal depth of the token stack used by */ + /* the Type 1 parser (see t1load.c). A minimum of 16 is required. */ + /* */ +#define T1_MAX_STACK_DEPTH 16 + + + /*************************************************************************/ + /* */ + /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */ + /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ + /* required. */ + /* */ +#define T1_MAX_DICT_DEPTH 5 + + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 8 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 32 + + + /*************************************************************************/ + /* */ + /* Define T1_CONFIG_OPTION_DISABLE_HINTER if you want to generate a */ + /* driver with no hinter. This can be useful to debug the parser. */ + /* */ +#undef T1_CONFIG_OPTION_DISABLE_HINTER + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ + /* files into an existing face. Note that if set, the T1 driver will be */ + /* unable to produce kerning distances. */ + /* */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of the Multiple Masters font support in the Type 1 */ + /* driver. */ + /* */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + +#endif /* FTOPTION_H */ + + +/* END */ diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h new file mode 100644 index 0000000..29316c6 --- /dev/null +++ b/include/freetype/freetype.h @@ -0,0 +1,2286 @@ +/***************************************************************************/ +/* */ +/* freetype.h */ +/* */ +/* FreeType high-level API and common types (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FREETYPE_H +#define FREETYPE_H + + + /*************************************************************************/ + /* */ + /* The `raster' component duplicates some of the declarations in */ + /* freetype.h for stand-alone use if _FREETYPE_ isn't defined. */ + /* */ +#define _FREETYPE_ + + + /*************************************************************************/ + /* */ + /* The FREETYPE_MAJOR and FREETYPE_MINOR macros are used to version the */ + /* new FreeType design, which is able to host several kinds of font */ + /* drivers. It starts at 2.0. */ + /* */ +#define FREETYPE_MAJOR 2 +#define FREETYPE_MINOR 0 + + +#include /* read configuration information */ +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Metrics */ + /* */ + /* */ + /* A structure used to model the metrics of a single glyph. Note */ + /* that values are expressed in 26.6 fractional pixel format or in */ + /* font units, depending on context. */ + /* */ + /* */ + /* width :: The glyph's width. */ + /* */ + /* height :: The glyph's height. */ + /* */ + /* horiBearingX :: Horizontal left side bearing. */ + /* */ + /* horiBearingY :: Horizontal top side bearing. */ + /* */ + /* horiAdvance :: Horizontal advance width. */ + /* */ + /* vertBearingX :: Vertical left side bearing. */ + /* */ + /* vertBearingY :: Vertical top side bearing. */ + /* */ + /* vertAdvance :: Vertical advance height. */ + /* */ + typedef struct FT_Glyph_Metrics_ + { + FT_Pos width; /* glyph width */ + FT_Pos height; /* glyph height */ + + FT_Pos horiBearingX; /* left side bearing in horizontal layouts */ + FT_Pos horiBearingY; /* top side bearing in horizontal layouts */ + FT_Pos horiAdvance; /* advance width for horizontal layout */ + + FT_Pos vertBearingX; /* left side bearing in vertical layouts */ + FT_Pos vertBearingY; /* top side bearing in vertical layouts */ + FT_Pos vertAdvance; /* advance height for vertical layout */ + + } FT_Glyph_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Generic_Finalizer */ + /* */ + /* */ + /* Describes a function used to destroy the `client' data of any */ + /* FreeType object. See the description of the FT_Generic type for */ + /* details of usage. */ + /* */ + /* */ + /* The address of the FreeType object which is under finalization. */ + /* Its client data is accessed through its `generic' field. */ + /* */ + typedef void (*FT_Generic_Finalizer)(void* object); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Generic */ + /* */ + /* */ + /* Client applications often need to associate their own data to a */ + /* variety of FreeType core objects. For example, a text layout API */ + /* might want to associate a glyph cache to a given size object. */ + /* */ + /* Most FreeType object contains a `generic' field, of type */ + /* FT_Generic, which usage is left to client applications and font */ + /* servers. */ + /* */ + /* It can be used to store a pointer to client-specific data, as well */ + /* as the address of a `finalizer' function, which will be called by */ + /* FreeType when the object is destroyed (for example, the previous */ + /* client example would put the address of the glyph cache destructor */ + /* in the `finalizer' field). */ + /* */ + /* */ + /* data :: A typeless pointer to any client-specified data. This */ + /* field is completely ignored by the FreeType library. */ + /* */ + /* finalizer :: A pointer to a `generic finalizer' function, which */ + /* will be called when the object is destroyed. If this */ + /* field is set to NULL, no code will be called. */ + /* */ + typedef struct FT_Generic_ + { + void* data; + FT_Generic_Finalizer finalizer; + + } FT_Generic; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bitmap_Size */ + /* */ + /* */ + /* An extremely simple structure used to model the size of a bitmap */ + /* strike (i.e., a bitmap instance of the font for a given */ + /* resolution) in a fixed-size font face. This is used for the */ + /* `available_sizes' field of the FT_Face_Properties structure. */ + /* */ + /* */ + /* height :: The character height in pixels. */ + /* */ + /* width :: The character width in pixels. */ + /* */ + typedef struct FT_Bitmap_Size_ + { + FT_Short height; + FT_Short width; + + } FT_Bitmap_Size; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Library */ + /* */ + /* */ + /* A handle to a FreeType library instance. Each `library' is */ + /* completely independent from the others; it is the `root' of a set */ + /* of objects like fonts, faces, sizes, etc. */ + /* */ + /* It also embeds a system object (see FT_System), as well as a */ + /* scan-line converter object (see FT_Raster). */ + /* */ + /* */ + /* Library objects are created through FT_Init_FreeType(). */ + /* */ + typedef struct FT_LibraryRec_ *FT_Library; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Module */ + /* */ + /* */ + /* A handle to a given FreeType module object. Each module can be a */ + /* font driver, a renderer, or anything else that provides services */ + /* to the formers. */ + /* */ + typedef struct FT_ModuleRec_* FT_Module; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Driver */ + /* */ + /* */ + /* A handle to a given FreeType font driver object. Each font driver */ + /* is able to create faces, sizes, glyph slots, and charmaps from the */ + /* resources whose format it supports. */ + /* */ + /* A driver can support either bitmap, graymap, or scalable font */ + /* formats. */ + /* */ + typedef struct FT_DriverRec_* FT_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Renderer */ + /* */ + /* */ + /* A handle to a given FreeType renderer. A renderer is in charge of */ + /* converting a glyph image to a bitmap, when necessary. Each */ + /* supports a given glyph image format, and one or more target */ + /* surface depths. */ + /* */ + typedef struct FT_RendererRec_* FT_Renderer; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Face */ + /* */ + /* */ + /* A handle to a given driver face object. A face object contains */ + /* all the instance and glyph independent data of a font file */ + /* typeface. */ + /* */ + /* A face object is created from a resource object through the */ + /* new_face() method of a given driver. */ + /* */ + typedef struct FT_FaceRec_* FT_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Size */ + /* */ + /* */ + /* A handle to a given driver size object. Such an object models the */ + /* _resolution_ AND _size_ dependent state of a given driver face */ + /* size. */ + /* */ + /* A size object is always created from a given face object. It is */ + /* discarded automatically by its parent face. */ + /* */ + typedef struct FT_SizeRec_* FT_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphSlot */ + /* */ + /* */ + /* A handle to a given `glyph slot'. A slot is a container where it */ + /* is possible to load any of the glyphs contained within its parent */ + /* face. */ + /* */ + /* A glyph slot is created from a given face object. It is discarded */ + /* automatically by its parent face. */ + /* */ + typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_CharMap */ + /* */ + /* */ + /* A handle to a given character map. A charmap is used to translate */ + /* character codes in a given encoding into glyph indexes for its */ + /* parent's face. Some font formats may provide several charmaps per */ + /* font. */ + /* */ + /* A charmap is created from a given face object. It is discarded */ + /* automatically by its parent face. */ + /* */ + typedef struct FT_CharMapRec_* FT_CharMap; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Encoding */ + /* */ + /* */ + /* An enumeration used to specify encodings supported by charmaps. */ + /* Used in the FT_Select_CharMap() API function. */ + /* */ + /* */ + /* Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */ + /* all character codes must be expressed as FT_Longs. */ + /* */ + typedef enum FT_Encoding_ + { + ft_encoding_none = 0, + ft_encoding_symbol = FT_MAKE_TAG( 's', 'y', 'm', 'b' ), + ft_encoding_unicode = FT_MAKE_TAG( 'u', 'n', 'i', 'c' ), + ft_encoding_latin_2 = FT_MAKE_TAG( 'l', 'a', 't', '2' ), + ft_encoding_sjis = FT_MAKE_TAG( 's', 'j', 'i', 's' ), + ft_encoding_gb2312 = FT_MAKE_TAG( 'g', 'b', ' ', ' ' ), + ft_encoding_big5 = FT_MAKE_TAG( 'b', 'i', 'g', '5' ), + ft_encoding_wansung = FT_MAKE_TAG( 'w', 'a', 'n', 's' ), + ft_encoding_johab = FT_MAKE_TAG( 'j', 'o', 'h', 'a' ), + + ft_encoding_adobe_standard = FT_MAKE_TAG( 'A', 'D', 'O', 'B' ), + ft_encoding_adobe_expert = FT_MAKE_TAG( 'A', 'D', 'B', 'E' ), + ft_encoding_adobe_custom = FT_MAKE_TAG( 'A', 'D', 'B', 'C' ), + + ft_encoding_apple_roman = FT_MAKE_TAG( 'a', 'r', 'm', 'n' ) + + /* other encodings might be defined in the future */ + + } FT_Encoding; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_CharMapRec */ + /* */ + /* */ + /* The base charmap class. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* flags :: A set of bit flags used to describe the charmap. */ + /* Each bit indicates that a given encoding is */ + /* supported. */ + /* */ + /* platform_id :: An ID number describing the platform for the */ + /* following encoding ID. This comes directly from */ + /* the TrueType specification and should be emulated */ + /* for other formats. */ + /* */ + /* encoding_id :: A platform specific encoding number. This also */ + /* comes from the TrueType specification and should be */ + /* emulated similarly. */ + /* */ + /* */ + /* We STRONGLY recommmend emulating a Unicode charmap for drivers */ + /* that do not support TrueType or OpenType. */ + /* */ + typedef struct FT_CharMapRec_ + { + FT_Face face; + FT_Encoding encoding; + FT_UShort platform_id; + FT_UShort encoding_id; + + } FT_CharMapRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S E O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* FreeType base face class */ + /* */ + /* */ + /* FT_FaceRec */ + /* */ + /* */ + /* FreeType root face class structure. A face object models the */ + /* resolution and point-size independent data found in a font file. */ + /* */ + /* */ + /* num_faces :: In the case where the face is located in a */ + /* collection (i.e., a resource which embeds */ + /* several faces), this is the total number of */ + /* faces found in the resource. 1 by default. */ + /* */ + /* face_index :: The index of the face in its resource. */ + /* Usually, this is 0 for all normal font */ + /* formats. It can be more in the case of */ + /* collections (which embed several fonts in a */ + /* single resource/file). */ + /* */ + /* face_flags :: A set of bit flags that give important */ + /* information about the face; see the */ + /* FT_FACE_FLAG_XXX macros for details. */ + /* */ + /* style_flags :: A set of bit flags indicating the style of */ + /* the face (i.e., italic, bold, underline, */ + /* etc). */ + /* */ + /* num_glyphs :: The total number of glyphs in the face. */ + /* */ + /* family_name :: The face's family name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's family (like `Times New */ + /* Roman', `Bodoni', `Garamond', etc). This */ + /* is a least common denominator used to list */ + /* fonts. Some formats (TrueType & OpenType) */ + /* provide localized and Unicode versions of */ + /* this string. Applications should use the */ + /* format specific interface to access them. */ + /* */ + /* style_name :: The face's style name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's style (like `Italic', */ + /* `Bold', `Condensed', etc). Not all font */ + /* formats provide a style name, so this field */ + /* is optional, and can be set to NULL. As */ + /* for `family_name', some formats provide */ + /* localized/Unicode versions of this string. */ + /* Applications should use the format specific */ + /* interface to access them. */ + /* */ + /* num_fixed_sizes :: The number of fixed sizes available in this */ + /* face. This should be set to 0 for scalable */ + /* fonts, unless its resource includes a */ + /* complete set of glyphs (called a `strike') */ + /* for the specified size. */ + /* */ + /* available_sizes :: An array of sizes specifying the available */ + /* bitmap/graymap sizes that are contained in */ + /* in the font resource. Should be set to */ + /* NULL if the field `num_fixed_sizes' is set */ + /* to 0. */ + /* */ + /* num_charmaps :: The total number of character maps in the */ + /* face. */ + /* */ + /* charmaps :: A table of pointers to the face's charmaps */ + /* Used to scan the list of available charmaps */ + /* this table might change after a call to */ + /* FT_Attach_File/Stream (e.g. when it used */ + /* to hook and additional encoding/CMap to */ + /* the face object). */ + /* */ + /* generic :: A field reserved for client uses. See the */ + /* FT_Generic type description. */ + /* */ + /* bbox :: The font bounding box. Coordinates are */ + /* expressed in font units (see units_per_EM). */ + /* The box is large enough to contain any */ + /* glyph from the font. Thus, bbox.yMax can */ + /* be seen as the `maximal ascender', */ + /* bbox.yMin as the `minimal descender', and */ + /* the maximal glyph width is given by */ + /* `bbox.xMax-bbox.xMin' (not to be confused */ + /* with the maximal _advance_width_). Only */ + /* relevant for scalable formats. */ + /* */ + /* units_per_EM :: The number of font units per EM square for */ + /* this face. This is typically 2048 for */ + /* TrueType fonts, 1000 for Type1 fonts, and */ + /* should be set to the (unrealistic) value 1 */ + /* for fixed-sizes fonts. Only relevant for */ + /* scalable formats. */ + /* */ + /* ascender :: The face's ascender is the vertical */ + /* distance from the baseline to the topmost */ + /* point of any glyph in the face. This */ + /* field's value is positive, expressed in */ + /* font units. Some font designs use a value */ + /* different from `bbox.yMax'. Only relevant */ + /* for scalable formats. */ + /* */ + /* descender :: The face's descender is the vertical */ + /* distance from the baseline to the */ + /* bottommost point of any glyph in the face. */ + /* This field's value is positive, expressed */ + /* in font units. Some font designs use a */ + /* value different from `-bbox.yMin'. Only */ + /* relevant for scalable formats. */ + /* */ + /* height :: The face's height is the vertical distance */ + /* from one baseline to the next when writing */ + /* several lines of text. Its value is always */ + /* positive, expressed in font units. The */ + /* value can be computed as */ + /* `ascender+descender+line_gap' where the */ + /* value of `line_gap' is also called */ + /* `external leading'. Only relevant for */ + /* scalable formats. */ + /* */ + /* max_advance_width :: The maximal advance width, in font units, */ + /* for all glyphs in this face. This can be */ + /* used to make word wrapping computations */ + /* faster. Only relevant for scalable */ + /* formats. */ + /* */ + /* max_advance_height :: The maximal advance height, in font units, */ + /* for all glyphs in this face. This is only */ + /* relevant for vertical layouts, and should */ + /* be set to the `height' for fonts that do */ + /* not provide vertical metrics. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_position :: The position, in font units, of the */ + /* underline line for this face. It's the */ + /* center of the underlining stem. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_thickness :: The thickness, in font units, of the */ + /* underline for this face. Only relevant for */ + /* scalable formats. */ + /* */ + /* driver :: A handle to the face's parent driver */ + /* object. */ + /* */ + /* memory :: A handle to the face's parent memory */ + /* object. Used for the allocation of */ + /* subsequent objects. */ + /* */ + /* stream :: A handle to the face's stream. */ + /* */ + /* glyph :: The face's associated glyph slot(s). This */ + /* object is created automatically with a new */ + /* face object. However, certain kinds of */ + /* applications (mainly tools like converters) */ + /* can need more than one slot to ease their */ + /* task. */ + /* */ + /* sizes_list :: The list of child sizes for this face. */ + /* */ + /* max_points :: The maximal number of points used to store */ + /* the vectorial outline of any glyph in this */ + /* face. If this value cannot be known in */ + /* advance, or if the face isn't scalable, */ + /* this should be set to 0. Only relevant for */ + /* scalable formats. */ + /* */ + /* max_contours :: The maximal number of contours used to */ + /* store the vectorial outline of any glyph in */ + /* this face. If this value cannot be known */ + /* in advance, or if the face isn't scalable, */ + /* this should be set to 0. Only relevant for */ + /* scalable formats. */ + /* */ + /* transform_matrix :: A 2x2 matrix of 16.16 coefficients used */ + /* to transform glyph outlines after they are */ + /* loaded from the font. Only used by the */ + /* convenience functions. */ + /* */ + /* transform_delta :: A translation vector used to transform */ + /* glyph outlines after they are loaded from */ + /* the font. Only used by the convenience */ + /* functions. */ + /* */ + /* transform_flags :: Some flags used to classify the transform. */ + /* Only used by the convenience functions. */ + /* */ + typedef struct FT_FaceRec_ + { + FT_Long num_faces; + FT_Long face_index; + + FT_Long face_flags; + FT_Long style_flags; + + FT_Long num_glyphs; + + FT_String* family_name; + FT_String* style_name; + + FT_Int num_fixed_sizes; + FT_Bitmap_Size* available_sizes; + + /* the face's table of available charmaps */ + FT_Int num_charmaps; + FT_CharMap* charmaps; + + FT_Generic generic; + + /* the following are only relevant for scalable outlines */ + FT_BBox bbox; + + FT_UShort units_per_EM; + FT_Short ascender; + FT_Short descender; + FT_Short height; + + FT_Short max_advance_width; + FT_Short max_advance_height; + + FT_Short underline_position; + FT_Short underline_thickness; + + FT_GlyphSlot glyph; + FT_Size size; + + /************************************************************/ + /* The following fields should be considered private and */ + /* rarely, if ever, used directly by client applications. */ + + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_CharMap charmap; + FT_ListRec sizes_list; + + FT_Generic autohint; + void* extensions; + + FT_UShort max_points; + FT_Short max_contours; + + FT_Matrix transform_matrix; + FT_Vector transform_delta; + FT_Int transform_flags; + + } FT_FaceRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_SCALABLE */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face provides */ + /* vectorial outlines (i.e., TrueType or Type1). This doesn't */ + /* prevent embedding of bitmap strikes though, i.e., a given face can */ + /* have both this bit set, and a `num_fixed_sizes' property > 0. */ + /* */ +#define FT_FACE_FLAG_SCALABLE 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_SIZES */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* `fixed sizes', i.e., bitmap strikes for some given pixel sizes. */ + /* See the `num_fixed_sizes' and `available_sizes' face properties */ + /* for more information. */ + /* */ +#define FT_FACE_FLAG_FIXED_SIZES 2 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_WIDTH */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* fixed-width characters (like Courier, Lucida, MonoType, etc.). */ + /* */ +#define FT_FACE_FLAG_FIXED_WIDTH 4 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_SFNT */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face uses the */ + /* `sfnt' storage fomat. For now, this means TrueType or OpenType. */ + /* */ +#define FT_FACE_FLAG_SFNT 8 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_HORIZONTAL */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* horizontal glyph metrics. This should be set for all common */ + /* formats, but who knows. */ + /* */ +#define FT_FACE_FLAG_HORIZONTAL 0x10 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_VERTICAL */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* vertical glyph metrics. If not set, the glyph loader will */ + /* synthetize vertical metrics itself to help display vertical text */ + /* correctly. */ + /* */ +#define FT_FACE_FLAG_VERTICAL 0x20 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_KERNING */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* kerning information. When set, this information can be retrieved */ + /* through the function FT_Get_Kerning(). Note that when unset, this */ + /* function will always return the kerning vector (0,0). */ + /* */ +#define FT_FACE_FLAG_KERNING 0x40 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FAST_GLYPHS */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the glyphs in a given */ + /* font can be retrieved very quickly, and that a glyph cache is thus */ + /* not necessary for any of its child size objects. */ + /* */ + /* This flag should really be set for fixed-size formats like FNT, */ + /* where each glyph bitmap is available directly in binary form */ + /* without any kind of compression. */ + /* */ +#define FT_FACE_FLAG_FAST_GLYPHS 0x80 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the font contains */ + /* multiple masters and is capable of interpolating between them. */ + /* */ +#define FT_FACE_FLAG_MULTIPLE_MASTERS 0x100 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_GLYPH_NAMES */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the font contains */ + /* glyph names that can be retrieved through FT_Get_Glyph_Name(). */ + /* */ +#define FT_FACE_FLAG_GLYPH_NAMES 0x200 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_EXTERNAL_STREAM */ + /* */ + /* */ + /* This bit field is used internally by FreeType to indicate that */ + /* a face's stream was provided by the client application and should */ + /* not be destroyed by FT_Done_Face(). */ + /* */ +#define FT_FACE_FLAG_EXTERNAL_STREAM 0x4000 + + +#define FT_HAS_HORIZONTAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) +#define FT_HAS_VERTICAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_VERTICAL ) +#define FT_HAS_KERNING( face ) \ + ( face->face_flags & FT_FACE_FLAG_KERNING ) +#define FT_IS_SCALABLE( face ) \ + ( face->face_flags & FT_FACE_FLAG_SCALABLE ) +#define FT_IS_SFNT( face ) \ + ( face->face_flags & FT_FACE_FLAG_SFNT ) +#define FT_IS_FIXED_WIDTH( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) +#define FT_HAS_FIXED_SIZES( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) +#define FT_HAS_FAST_GLYPHS( face ) \ + ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS ) +#define FT_HAS_GLYPH_NAMES( face ) \ + ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) + +#define FT_HAS_MULTIPLE_MASTERS( face ) \ + ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_STYLE_FLAG_ITALIC */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face is */ + /* italicized. */ + /* */ +#define FT_STYLE_FLAG_ITALIC 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_STYLE_FLAG_BOLD */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face is */ + /* emboldened. */ + /* */ +#define FT_STYLE_FLAG_BOLD 2 + + + /*************************************************************************/ + /* */ + /* FreeType base size metrics */ + /* */ + /* */ + /* FT_Size_Metrics */ + /* */ + /* */ + /* The size metrics structure returned scaled important distances for */ + /* a given size object. */ + /* */ + /* */ + /* x_ppem :: The character width, expressed in integer pixels. */ + /* This is the width of the EM square expressed in */ + /* pixels, hence the term `ppem' (pixels per EM). */ + /* */ + /* y_ppem :: The character height, expressed in integer pixels. */ + /* This is the height of the EM square expressed in */ + /* pixels, hence the term `ppem' (pixels per EM). */ + /* */ + /* x_scale :: A simple 16.16 fixed point format coefficient used */ + /* to scale horizontal distances expressed in font */ + /* units to fractional (26.6) pixel coordinates. */ + /* */ + /* y_scale :: A simple 16.16 fixed point format coefficient used */ + /* to scale vertical distances expressed in font */ + /* units to fractional (26.6) pixel coordinates. */ + /* */ + /* x_resolution :: The horizontal device resolution for this size */ + /* object, expressed in integer dots per inches */ + /* (dpi). As a convention, fixed font formats set */ + /* this value to 72. */ + /* */ + /* y_resolution :: The vertical device resolution for this size */ + /* object, expressed in integer dots per inches */ + /* (dpi). As a convention, fixed font formats set */ + /* this value to 72. */ + /* */ + /* ascender :: The ascender, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* descender :: The descender, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* height :: The text height, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* max_advance :: Maximum horizontal advance, expressed in 26.6 */ + /* fixed point pixels. Always positive. */ + /* */ + /* */ + /* The values of `ascender', `descender', and `height' are only the */ + /* scaled versions of `face->ascender', `face->descender', and */ + /* `face->height'. */ + /* */ + /* Unfortunately, due to glyph hinting, these values might not be */ + /* exact for certain fonts, they thus must be treated as unreliable */ + /* with an error margin of at least one pixel! */ + /* */ + /* Indeed, the only way to get the exact pixel ascender and descender */ + /* is to render _all_ glyphs. As this would be a definite */ + /* performance hit, it is up to client applications to perform such */ + /* computations. */ + /* */ + typedef struct FT_Size_Metrics_ + { + FT_UShort x_ppem; /* horizontal pixels per EM */ + FT_UShort y_ppem; /* vertical pixels per EM */ + + FT_Fixed x_scale; /* two scales used to convert font units */ + FT_Fixed y_scale; /* to 26.6 frac. pixel coordinates.. */ + + FT_Pos ascender; /* ascender in 26.6 frac. pixels */ + FT_Pos descender; /* descender in 26.6 frac. pixels */ + FT_Pos height; /* text height in 26.6 frac. pixels */ + FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ + + } FT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* FreeType base size class */ + /* */ + /* */ + /* FT_SizeRec */ + /* */ + /* */ + /* FreeType root size class structure. A size object models the */ + /* resolution and pointsize dependent data of a given face. */ + /* */ + /* */ + /* face :: Handle to the parent face object. */ + /* */ + /* generic :: A typeless pointer, which is unused by the FreeType */ + /* library or any of its drivers. It can be used by */ + /* client applications to link their own data to each size */ + /* object. */ + /* */ + /* metrics :: Metrics for this size object. This field is read-only. */ + /* */ + typedef struct FT_SizeRec_ + { + FT_Face face; /* parent face object */ + FT_Generic generic; /* generic pointer for client uses */ + FT_Size_Metrics metrics; /* size metrics */ + + } FT_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SubGlyph */ + /* */ + /* */ + /* The subglyph structure is an internal object used to describe */ + /* subglyphs (for example, in the case of composites). */ + /* */ + /* */ + /* The subglyph implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_SubGlyph_ FT_SubGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphLoader */ + /* */ + /* */ + /* The glyph loader is an internal object used to load several glyphs */ + /* together (for example, in the case of composites). */ + /* */ + /* */ + /* The glyph loader implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_GlyphLoader_ FT_GlyphLoader; + + + /*************************************************************************/ + /* */ + /* FreeType Glyph Slot base class */ + /* */ + /* */ + /* FT_GlyphSlotRec */ + /* */ + /* */ + /* FreeType root glyph slot class structure. A glyph slot is a */ + /* container where individual glyphs can be loaded, be they */ + /* vectorial or bitmap/graymaps. */ + /* */ + /* */ + /* library :: A handle to the FreeType library instance */ + /* this slot belongs to. */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* next :: In some cases (like some font tools), several */ + /* glyph slots per face object can be a good */ + /* thing. As this is rare, the glyph slots are */ + /* listed through a direct, single-linked list */ + /* using its `next' field. */ + /* */ + /* generic :: A typeless pointer which is unused by the */ + /* FreeType library or any of its drivers. It */ + /* can be used by client applications to link */ + /* their own data to each size object. */ + /* */ + /* metrics :: The metrics of the last loaded glyph in the */ + /* slot. The returned values depend on the last */ + /* load flags (see the FT_Load_Glyph() API */ + /* function) and can be expressed either in 26.6 */ + /* fractional pixels or font units. */ + /* */ + /* Note that even when the glyph image is */ + /* transformed, the metrics are not. */ + /* */ + /* linearHoriAdvance :: For scalable formats only, this field holds */ + /* the linearly scaled horizontal advance width */ + /* for the glyph (i.e. the scaled and unhinted */ + /* value of the hori advance). This can be */ + /* important to perform correct WYSIWYG layout */ + /* */ + /* Note that this value is expressed by default */ + /* in 16.16 pixels. However, when the glyph is */ + /* loaded with the FT_LOAD_UNSCALED_LINEAR flag, */ + /* this field contains simply the value of the */ + /* advance in original font units. */ + /* */ + /* linearVertAdvance :: For scalable formats only, this field holds */ + /* the linearly scaled vertical advance height */ + /* for the glyph. See linearHoriAdvance for */ + /* comments. */ + /* */ + /* advance :: This is the transformed advance width for the */ + /* glyph. */ + /* */ + /* format :: This field indicates the format of the image */ + /* contained in the glyph slot. Typically */ + /* ft_glyph_format_bitmap, */ + /* ft_glyph_format_outline, and */ + /* ft_glyph_format_composite, but others are */ + /* possible. */ + /* */ + /* bitmap :: This field is used as a bitmap descriptor */ + /* when the slot format is */ + /* ft_glyph_format_bitmap. Note that the */ + /* address and content of the bitmap buffer can */ + /* change between calls of FT_Load_Glyph() and a */ + /* few other functions. */ + /* */ + /* bitmap_left :: This is the bitmap's left bearing expressed */ + /* in integer pixels. Of course, this is only */ + /* valid if the format is */ + /* ft_glyph_format_bitmap. */ + /* */ + /* bitmap_top :: This is the bitmap's top bearing expressed in */ + /* integer pixels. Remember that this is the */ + /* distance from the baseline to the top-most */ + /* glyph scanline, upwards y-coordinates being */ + /* *positive*. */ + /* */ + /* outline :: The outline descriptor for the current glyph */ + /* image if its format is */ + /* ft_glyph_bitmap_outline. */ + /* */ + /* num_subglyphs :: The number of subglyphs in a composite glyph. */ + /* This format is only valid for the composite */ + /* glyph format, that should normally only be */ + /* loaded with the FT_LOAD_NO_RECURSE flag. */ + /* */ + /* subglyphs :: An array of subglyph descriptors for */ + /* composite glyphs. There are `num_subglyphs' */ + /* elements in there. */ + /* */ + /* control_data :: Certain font drivers can also return the */ + /* control data for a given glyph image (e.g. */ + /* TrueType bytecode, Type 1 charstrings, etc.). */ + /* This field is a pointer to such data. */ + /* */ + /* control_len :: This is the length in bytes of the control */ + /* data. */ + /* */ + /* other :: Really wicked formats can use this pointer to */ + /* present their own glyph image to client apps. */ + /* Note that the app will need to know about the */ + /* image format. */ + /* */ + /* loader :: This is a private object for the glyph slot. */ + /* Do not touch this. */ + /* */ + /* */ + /* If FT_Load_Glyph() is called with default flags (FT_LOAD_DEFAULT), */ + /* the glyph image is loaded in the glyph slot in its native format */ + /* (e.g. a vectorial outline for TrueType and Type 1 formats). */ + /* */ + /* This image can later be converted into a bitmap by calling */ + /* FT_Render_Glyph(). This function finds the current renderer for */ + /* the native image's format then invokes it. */ + /* */ + /* The renderer is in charge of transforming the native image through */ + /* the slot's face transformation fields, then convert it into a */ + /* bitmap that is returned in `slot->bitmap'. */ + /* */ + /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */ + /* to specify the position of the bitmap relative to the current pen */ + /* position (e.g. coordinates [0,0] on the baseline). Of course, */ + /* `slot->format' is also changed to `ft_glyph_format_bitmap' . */ + /* */ + typedef struct FT_GlyphSlotRec_ + { + FT_Library library; + FT_Face face; + FT_GlyphSlot next; + FT_UInt flags; + FT_Generic generic; + + FT_Glyph_Metrics metrics; + FT_Fixed linearHoriAdvance; + FT_Fixed linearVertAdvance; + FT_Vector advance; + + FT_Glyph_Format format; + + FT_Bitmap bitmap; + FT_Int bitmap_left; + FT_Int bitmap_top; + + FT_Outline outline; + + FT_UInt num_subglyphs; + FT_SubGlyph* subglyphs; + + void* control_data; + long control_len; + + void* other; + + /* private fields */ + FT_GlyphLoader* loader; + + } FT_GlyphSlotRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* F U N C T I O N S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_FreeType */ + /* */ + /* */ + /* Initializes a new FreeType library object. The set of drivers */ + /* that are registered by this function is determined at build time. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Init_FreeType( FT_Library* library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_FreeType( FT_Library library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Flags */ + /* */ + /* */ + /* An enumeration used to list the bit flags used within */ + /* FT_Open_Args(). */ + /* */ + /* */ + /* ft_open_memory :: This is a memory-based stream. */ + /* */ + /* ft_open_stream :: Copy the stream from the `stream' field. */ + /* */ + /* ft_open_pathname :: Create a new input stream from a C pathname. */ + /* */ + /* ft_open_driver :: Use the `driver' field. */ + /* */ + /* ft_open_params :: Use the `num_params' & `params' field. */ + /* */ + typedef enum + { + ft_open_memory = 1, + ft_open_stream = 2, + ft_open_pathname = 4, + ft_open_driver = 8, + ft_open_params = 16 + + } FT_Open_Flags; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Parameter */ + /* */ + /* */ + /* A simple structure used to pass more or less generic parameters */ + /* to FT_Open_Face(). */ + /* */ + /* */ + /* tag :: A 4-byte identification tag. */ + /* */ + /* data :: A pointer to the parameter data. */ + /* */ + /* */ + /* The id and function of parameters are driver-specific. */ + /* */ + typedef struct FT_Parameter_ + { + FT_ULong tag; + FT_Pointer data; + + } FT_Parameter; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Args */ + /* */ + /* */ + /* A structure used to indicate how to open a new font file/stream. */ + /* A pointer to such a structure can be used as a parameter for the */ + /* functions FT_Open_Face() & FT_Attach_Stream(). */ + /* */ + /* */ + /* flags :: A set of bit flags indicating how to use the */ + /* structure. */ + /* */ + /* memory_base :: The first byte of the file in memory. */ + /* */ + /* memory_size :: The size in bytes of the file in memory. */ + /* */ + /* pathname :: A pointer to an 8-bit file pathname. */ + /* */ + /* stream :: A handle to a source stream object. */ + /* */ + /* driver :: This field is exclusively used by FT_Open_Face(); */ + /* it simply specifies the font driver to use to open */ + /* the face. If set to 0, FreeType will try to load */ + /* the face with each one of the drivers in its list. */ + /* */ + /* num_params :: The number of extra parameters. */ + /* */ + /* params :: Extra parameters passed to the font driver when */ + /* opening a new face. */ + /* */ + /* */ + /* `stream_type' determines which fields are used to create a new */ + /* input stream. */ + /* */ + /* If it is `ft_stream_memory', a new memory-based stream will be */ + /* created using the memory block specified by `memory_base' and */ + /* `memory_size'. */ + /* */ + /* If it is `ft_stream_pathname', a new stream will be created with */ + /* the `pathname' field, calling the system-specific FT_New_Stream() */ + /* function. */ + /* */ + /* If is is `ft_stream_copy', then the content of `stream' will be */ + /* copied to a new input stream object. The object will be closed */ + /* and destroyed when the face is destroyed itself. Note that this */ + /* means that you should not close the stream before the library */ + /* does! */ + /* */ + typedef struct FT_Open_Args_ + { + FT_Open_Flags flags; + FT_Byte* memory_base; + FT_Long memory_size; + FT_String* pathname; + FT_Stream stream; + FT_Module driver; + FT_Int num_params; + FT_Parameter* params; + + } FT_Open_Args; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_New_Face() can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library, + const char* filepathname, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* file_base :: A pointer to the beginning of the font data. */ + /* */ + /* file_size :: The size of the memory chunk used by the font data. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_New_Memory_Face() can be used to determine and/or check the */ + /* font format of a given font resource. If the `face_index' field */ + /* is negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Memory_Face( FT_Library library, + FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* Opens a face object from a given resource and typeface index using */ + /* an `FT_Open_Args' structure. If the face object doesn't exist, it */ + /* will be created. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* args :: A pointer to an `FT_Open_Args' structure which must */ + /* be filled by the caller. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_Open_Face() can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Open_Face( FT_Library library, + FT_Open_Args* args, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_File */ + /* */ + /* */ + /* `Attaches' a given font file to an existing face. This is usually */ + /* to read additional information for a single face object. For */ + /* example, it is used to read the AFM files that come with Type 1 */ + /* fonts in order to add kerning data and other metrics. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If your font file is in memory, or if you want to provide your */ + /* own input stream object, use FT_Attach_Stream(). */ + /* */ + /* The meaning of the `attach' action (i.e., what really happens when */ + /* the new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Attach_File( FT_Face face, + const char* filepathname ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_Stream */ + /* */ + /* */ + /* This function is similar to FT_Attach_File() with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The meaning of the `attach' (i.e. what really happens when the */ + /* new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Face */ + /* */ + /* */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* */ + /* face :: A handle to a target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* Sets the character dimensions of a given face object. The */ + /* `char_width' and `char_height' values are used for the width and */ + /* height, respectively, expressed in 26.6 fractional points. */ + /* */ + /* If the horizontal or vertical resolution values are zero, a */ + /* default value of 72dpi is used. Similarly, if one of the */ + /* character dimensions is zero, its value is set equal to the other. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* char_width :: The character width, in 26.6 fractional points. */ + /* */ + /* char_height :: The character height, in 26.6 fractional */ + /* points. */ + /* */ + /* horz_resolution :: The horizontal resolution. */ + /* */ + /* vert_resolution :: The vertical resolution. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Char_Size( FT_Face face, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* */ + /* Sets the character dimensions of a given face object. The width */ + /* and height are expressed in integer pixels. */ + /* */ + /* If one of the character dimensions is zero, its value is set equal */ + /* to the other. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* face :: A handle to the target face object where the glyph */ + /* will be loaded. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* FT_Set_Transform. */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Char */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* char_code :: The glyph's character code, according to the */ + /* current charmap used in the face. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If the face has no current charmap, or if the character code */ + /* is not defined in the charmap, this function will return an */ + /* error. */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* FT_Set_Transform(). */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_SCALE */ + /* */ + /* */ + /* A bit field constant, used with FT_Load_Glyph() to indicate that */ + /* the vector outline being loaded should not be scaled to 26.6 */ + /* fractional pixels, but kept in notional units. */ + /* */ +#define FT_LOAD_NO_SCALE 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_HINTING */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the vector outline being loaded should not be fitted to the pixel */ + /* grid but simply scaled to 26.6 fractional pixels. */ + /* */ + /* This flag is ignored if FT_LOAD_NO_SCALE is set. */ + /* */ +#define FT_LOAD_NO_HINTING 2 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_RENDER */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should load the glyph and immediately convert it into */ + /* a bitmap, if necessary, by calling FT_Render_Glyph(). */ + /* */ + /* Note that by default, FT_Load_Glyph() loads the glyph image in its */ + /* native format. */ + /* */ +#define FT_LOAD_RENDER 4 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_BITMAP */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should not load the bitmap or pixmap of a given */ + /* glyph. This is useful when you do not want to load the embedded */ + /* bitmaps of scalable formats, as the native glyph image will be */ + /* loaded, and can then be rendered through FT_Render_Glyph(). */ + /* */ +#define FT_LOAD_NO_BITMAP 8 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_VERTICAL_LAYOUT */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph image should be prepared for vertical layout. This */ + /* basically means that `face.glyph.advance' will correspond to the */ + /* vertical advance height (instead of the default horizontal */ + /* advance width), and that the glyph image will translated to match */ + /* the vertical bearings positions. */ + /* */ +#define FT_LOAD_VERTICAL_LAYOUT 16 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_FORCE_AUTOHINT */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should try to auto-hint the glyphs, even if a driver */ + /* specific hinter is available. */ + /* */ +#define FT_LOAD_FORCE_AUTOHINT 32 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the font driver should try to crop the bitmap (i.e. remove all */ + /* space around its black bits) when loading it. For now, this */ + /* really only works with embedded bitmaps in TrueType fonts. */ + /* */ +#define FT_LOAD_CROP_BITMAP 64 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_PEDANTIC */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should perform a pedantic bytecode */ + /* interpretation. Many popular fonts come with broken glyph */ + /* programs. When this flag is set, loading them will return an */ + /* error. Otherwise, errors are ignored by the loader, sometimes */ + /* resulting in ugly glyphs. */ + /* */ +#define FT_LOAD_PEDANTIC 128 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should ignore the global advance width defined */ + /* in the font. As far as we know, this is only used by the */ + /* X-TrueType font server, in order to deal correctly with the */ + /* incorrect metrics contained in DynaLab's TrueType CJK fonts. */ + /* */ +#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 512 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_RECURSE */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should not load composite glyph recursively. */ + /* Rather, when a composite glyph is encountered, it should set */ + /* the values of `num_subglyphs' and `subglyphs', as well as set */ + /* `face->glyph.format' to ft_glyph_format_composite. */ + /* */ + /* This is for use by the auto-hinter and possibly other tools. */ + /* For nearly all applications, this flags should be left unset */ + /* when invoking FT_Load_Glyph(). */ + /* */ + /* Note that the flag forces the load of unscaled glyphs. */ + /* */ +#define FT_LOAD_NO_RECURSE 1024 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_IGNORE_TRANSFORM */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should not try to transform the loaded glyph */ + /* image. */ + /* */ +#define FT_LOAD_IGNORE_TRANSFORM 2048 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_MONOCHROME */ + /* */ + /* */ + /* Only used with FT_LOAD_RENDER set, it indicates that the returned */ + /* glyph image should be 1-bit monochrome. This really tells the */ + /* glyph loader to use `ft_render_mode_mono' when calling */ + /* FT_Render_Glyph(). */ + /* */ +#define FT_LOAD_MONOCHROME 4096 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_LINEAR_DESIGN */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should return the linearly scaled metrics expressed */ + /* in original font units, instead of the default 16.16 pixel values. */ + /* */ +#define FT_LOAD_LINEAR_DESIGN 8192 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_DEFAULT */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should try to load the glyph normally, i.e., */ + /* embedded bitmaps are favored over outlines, vectors are always */ + /* scaled and grid-fitted. */ + /* */ +#define FT_LOAD_DEFAULT 0 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Transform */ + /* */ + /* */ + /* A function used to set the transformation that is applied to glyph */ + /* images just before they are converted to bitmaps in a glyph slot */ + /* when FT_Render_Glyph() is called. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */ + /* the identity matrix. */ + /* delta :: A pointer to the translation vector. Use 0 for the null */ + /* vector. */ + /* */ + /* */ + /* The transformation is only applied to scalable image formats after */ + /* the glyph has been loaded. It means that hinting is unaltered by */ + /* the transformation and is performed on the character size given in */ + /* the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_DEF( void ) FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Mode */ + /* */ + /* */ + /* An enumeration type that lists the render modes supported by the */ + /* FreeType 2 renderer(s). A renderer is in charge of converting a */ + /* glyph image into a bitmap. */ + /* */ + /* */ + /* ft_render_mode_normal :: This is the default render mode; it */ + /* corresponds to 8-bit anti-aliased */ + /* bitmaps, using 256 levels of gray. */ + /* */ + /* ft_render_mode_mono :: This render mode is used to produce 1-bit */ + /* monochrome bitmaps. */ + /* */ + /* */ + /* There is no render mode to produce 8-bit `monochrome' bitmaps -- */ + /* you have to make the conversion yourself if you need such things */ + /* (besides, FreeType is not a graphics library). */ + /* */ + /* More modes might appear later for specific display modes (e.g. TV, */ + /* LCDs, etc.). They will be supported through the simple addition */ + /* of a renderer module, with no changes to the rest of the engine. */ + /* */ + typedef enum FT_Render_Mode_ + { + ft_render_mode_normal = 0, + ft_render_mode_mono = 1 + + } FT_Render_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Glyph */ + /* */ + /* */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* render_mode :: This is the render mode used to render the glyph */ + /* image into a bitmap. See FT_Render_Mode for a list */ + /* of possible values. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot, + FT_UInt render_mode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Kerning_Mode */ + /* */ + /* */ + /* An enumeration used to specify which kerning values to return in */ + /* FT_Get_Kerning(). */ + /* */ + /* */ + /* ft_kerning_default :: Return scaled and grid-fitted kerning */ + /* distances (value is 0). */ + /* */ + /* ft_kerning_unfitted :: Return scaled but un-grid-fitted kerning */ + /* distances. */ + /* */ + /* ft_kerning_unscaled :: Return the kerning vector in original font */ + /* units. */ + /* */ + typedef enum FT_Kerning_Mode_ + { + ft_kerning_default = 0, + ft_kerning_unfitted, + ft_kerning_unscaled + + } FT_Kerning_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Kerning */ + /* */ + /* */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* kern_mode :: See FT_Kerning_Mode() for more information. */ + /* Determines the scale/dimension of the returned */ + /* kerning vector. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this method. Other layouts, or more sophisticated */ + /* kernings, are out of the scope of this API function -- they can be */ + /* implemented through format-specific interfaces. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector* kerning ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph_Name */ + /* */ + /* */ + /* Retrieves the ASCII name of a given glyph in a face. This only */ + /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* An error is returned if the face doesn't provide glyph names or if */ + /* the glyph index is invalid. In all cases of failure, the first */ + /* byte of `buffer' will be set to 0 to indicate an empty name. */ + /* */ + /* The glyph name is truncated to fit within the buffer if it is too */ + /* long. The returned string is always zero-terminated. */ + /* */ + /* This function is not compiled within the library if the config */ + /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */ + /* `include/freetype/config/ftoptions.h' */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Select_Charmap */ + /* */ + /* */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Charmap */ + /* */ + /* */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if the charmap is not part of */ + /* the face (i.e., if it is not listed in the face->charmaps[] */ + /* table). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT_DEF( FT_UInt ) FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* with maximal accuracy (it uses a 64-bit intermediate integer */ + /* whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */ + /* used to multiply a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* This function has been optimized for the case where the absolute */ + /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ + /* As this happens mainly when scaling from notional units to */ + /* fractional pixels in FreeType, it resulted in noticeable speed */ + /* improvements between versions 2.x and 1.x. */ + /* */ + /* As a conclusion, always try to place a 16.16 factor as the */ + /* _second_ argument of this function; this can make a great */ + /* difference. */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ + /* used to divide a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of the old FT_MulDiv64(). */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_DivFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_DEF( void ) FT_Vector_Transform( FT_Vector* vec, + FT_Matrix* matrix ); + + + +#ifdef __cplusplus + } +#endif + + +#endif /* FREETYPE_H */ + + +/* END */ diff --git a/include/freetype/ftbbox.h b/include/freetype/ftbbox.h new file mode 100644 index 0000000..e144664 --- /dev/null +++ b/include/freetype/ftbbox.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ftbbox.h */ +/* */ +/* FreeType bbox computation (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component has a _single_ role: to compute exact outline bounding */ + /* boxes. */ + /* */ + /* It is separated from the rest of the engine for various technical */ + /* reasons. It may well be integrated in `ftoutln' later. */ + /* */ + /*************************************************************************/ + + +#ifndef FTBBOX_H +#define FTBBOX_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_GetBBox */ + /* */ + /* */ + /* Computes the exact bounding box of an outline. This is slower */ + /* than computing the control box. However, it uses an advanced */ + /* algorithm which returns _very_ quickly when the two boxes */ + /* coincide. Otherwise, the outline Bezier arcs are walked over to */ + /* extract their extrema. */ + /* */ + /* */ + /* outline :: A pointer to the source outline. */ + /* */ + /* */ + /* bbox :: The outline's exact bounding box. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + FT_EXPORT_DEF(FT_Error) FT_Raster_GetBBox( FT_Outline* outline, + FT_BBox* abbox ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTBBOX_H */ + + +/* END */ diff --git a/include/freetype/fterrors.h b/include/freetype/fterrors.h new file mode 100644 index 0000000..9fb8099 --- /dev/null +++ b/include/freetype/fterrors.h @@ -0,0 +1,166 @@ +/***************************************************************************/ +/* */ +/* fterrors.h */ +/* */ +/* FreeType error codes (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the FreeType error enumeration constants */ + /* It can also be used to create an error message table easily with */ + /* something like: */ + /* */ + /* { */ + /* #undef FTERRORS_H */ + /* #define FT_ERRORDEF( e, v, s ) { e, s }, */ + /* #define FT_ERROR_START_LIST { */ + /* #define FT_ERROR_END_LIST { 0, 0 } }; */ + /* */ + /* const struct */ + /* { */ + /* int err_code; */ + /* const char* err_msg */ + /* } ft_errors[] = */ + /* */ + /* #include */ + /* } */ + /* */ + /*************************************************************************/ + + +#ifndef FTERRORS_H +#define FTERRORS_H + + +#ifndef FT_ERRORDEF + +#define FT_ERRORDEF( e, v, s ) e = v, +#define FT_ERROR_START_LIST enum { +#define FT_ERROR_END_LIST FT_Err_Max }; + +#endif /* !FT_ERRORDEF */ + + +#ifdef FT_ERROR_START_LIST + FT_ERROR_START_LIST +#endif + + FT_ERRORDEF( FT_Err_Ok, 0x0000, \ + "no error" ) + FT_ERRORDEF( FT_Err_Cannot_Open_Resource, 0x0001, \ + "can't open stream" ) + FT_ERRORDEF( FT_Err_Unknown_File_Format, 0x0002, \ + "unknown file format" ) + FT_ERRORDEF( FT_Err_Invalid_File_Format, 0x0003, \ + "broken file" ) + + FT_ERRORDEF( FT_Err_Invalid_Argument, 0x0010, \ + "invalid argument" ) + FT_ERRORDEF( FT_Err_Invalid_Handle, 0x0011, \ + "invalid object handle" ) + FT_ERRORDEF( FT_Err_Invalid_Glyph_Index, 0x0012, \ + "invalid glyph index" ) + FT_ERRORDEF( FT_Err_Invalid_Character_Code, 0x0013, \ + "invalid character code" ) + + FT_ERRORDEF( FT_Err_Unimplemented_Feature, 0x0020, \ + "unimplemented feature" ) + FT_ERRORDEF( FT_Err_Invalid_Glyph_Format, 0x0021, \ + "unsupported glyph image format" ) + FT_ERRORDEF( FT_Err_Cannot_Render_Glyph, 0x0022, \ + "cannot render this glyph format" ) + + FT_ERRORDEF( FT_Err_Invalid_Library_Handle, 0x0030, \ + "invalid library handle" ) + FT_ERRORDEF( FT_Err_Invalid_Driver_Handle, 0x0031, \ + "invalid module handle" ) + FT_ERRORDEF( FT_Err_Invalid_Face_Handle, 0x0032, \ + "invalid face handle" ) + FT_ERRORDEF( FT_Err_Invalid_Size_Handle, 0x0033, \ + "invalid size handle" ) + FT_ERRORDEF( FT_Err_Invalid_Slot_Handle, 0x0034, \ + "invalid glyph slot handle" ) + FT_ERRORDEF( FT_Err_Invalid_CharMap_Handle, 0x0035, \ + "invalid charmap handle" ) + FT_ERRORDEF( FT_Err_Invalid_Outline, 0x0036, \ + "invalid outline" ) + FT_ERRORDEF( FT_Err_Invalid_Version, 0x0037, \ + "invalid FreeType version" ) + FT_ERRORDEF( FT_Err_Lower_Module_Version, 0x0038, \ + "module version is too low" ) + + FT_ERRORDEF( FT_Err_Too_Many_Drivers, 0x0040, \ + "too many modules" ) + FT_ERRORDEF( FT_Err_Too_Many_Extensions, 0x0041, \ + "too many extensions" ) + + FT_ERRORDEF( FT_Err_Out_Of_Memory, 0x0050, \ + "out of memory" ) + FT_ERRORDEF( FT_Err_Unlisted_Object, 0x0051, \ + "unlisted object" ) + + FT_ERRORDEF( FT_Err_Invalid_Stream_Handle, 0x0060, \ + "invalid stream handle" ) + FT_ERRORDEF( FT_Err_Cannot_Open_Stream, 0x0061, \ + "cannot open stream" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Seek, 0x0062, \ + "invalid stream seek" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Skip, 0x0063, \ + "invalid stream skip" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Read, 0x0064, \ + "invalid stream read" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Operation, 0x0065, \ + "invalid stream operation" ) + FT_ERRORDEF( FT_Err_Invalid_Frame_Operation, 0x0066, \ + "invalid frame operation" ) + FT_ERRORDEF( FT_Err_Nested_Frame_Access, 0x0067, \ + "nested frame access" ) + FT_ERRORDEF( FT_Err_Invalid_Frame_Read, 0x0068, \ + "invalid frame read" ) + + FT_ERRORDEF( FT_Err_Invalid_Composite, 0x0070, \ + "invalid composite glyph" ) + FT_ERRORDEF( FT_Err_Too_Many_Hints, 0x0071, \ + "too many hints" ) + + FT_ERRORDEF( FT_Err_Raster_Uninitialized, 0x0080, \ + "raster uninitialized" ) + FT_ERRORDEF( FT_Err_Raster_Corrupted, 0x0081, \ + "raster corrupted" ) + FT_ERRORDEF( FT_Err_Raster_Overflow, 0x0082, \ + "raster overflow" ) + FT_ERRORDEF( FT_Err_Raster_Negative_Height, 0x0083, \ + "negative height while rastering" ) + + /* range 0x400 - 0x4FF is reserved for TrueType specific stuff */ + + /* range 0x500 - 0x5FF is reserved for CFF specific stuff */ + + /* range 0x600 - 0x6FF is reserved for Type1 specific stuff */ + +#ifdef FT_ERROR_END_LIST + FT_ERROR_END_LIST +#endif + + +#undef FT_ERROR_START_LIST +#undef FT_ERROR_END_LIST +#undef FT_ERRORDEF + + +#endif /* FTERRORS_H */ + + +/* END */ diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h new file mode 100644 index 0000000..0647c88 --- /dev/null +++ b/include/freetype/ftglyph.h @@ -0,0 +1,422 @@ +/***************************************************************************/ +/* */ +/* ftglyph.h */ +/* */ +/* FreeType convenience functions to handle glyphs (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of several convenience functions */ + /* that can be used by client applications to easily retrieve glyph */ + /* bitmaps and outlines from a given face. */ + /* */ + /* These functions should be optional if you are writing a font server */ + /* or text layout engine on top of FreeType. However, they are pretty */ + /* handy for many other simple uses of the library. */ + /* */ + /*************************************************************************/ + + +#ifndef FTGLYPH_H +#define FTGLYPH_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /* forward declaration to a private type */ + typedef struct FT_Glyph_Class_ FT_Glyph_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphRec */ + /* */ + /* */ + /* The root glyph structure contains a given glyph image plus its */ + /* advance width in 16.16 fixed float format. */ + /* */ + /* */ + /* library :: A handle to the FreeType library object. */ + /* */ + /* clazz :: A pointer to the glyph's class. Private. */ + /* */ + /* format :: The format of the glyph's image. */ + /* */ + /* advance :: A 16.16 vector that gives the glyph's advance width. */ + /* */ + typedef struct FT_GlyphRec_ + { + FT_Library library; + const FT_Glyph_Class* clazz; + FT_Glyph_Format format; + FT_Vector advance; + + } FT_GlyphRec, *FT_Glyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_BitmapGlyphRec */ + /* */ + /* */ + /* A structure used for bitmap glyph images. This really is a */ + /* `sub-class' of `FT_GlyphRec'. */ + /* */ + /* */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* left :: The left-side bearing, i.e., the horizontal distance */ + /* from the current pen position to the left border of the */ + /* glyph bitmap. */ + /* */ + /* top :: The top-side bearing, i.e., the vertical distance from */ + /* the current pen position to the top border of the glyph */ + /* bitmap. This distance is positive for upwards-y! */ + /* */ + /* bitmap :: A descriptor for the bitmap. */ + /* */ + /* */ + /* You can typecast FT_Glyph to FT_BitmapGlyph if you have */ + /* glyph->format == ft_glyph_format_bitmap. This lets you access */ + /* the bitmap's contents easily. */ + /* */ + /* The corresponding pixel buffer is always owned by the BitmapGlyph */ + /* and is thus created and destroyed with it. */ + /* */ + typedef struct FT_BitmapGlyphRec_ + { + FT_GlyphRec root; + FT_Int left; + FT_Int top; + FT_Bitmap bitmap; + + } FT_BitmapGlyphRec, *FT_BitmapGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_OutlineGlyphRec */ + /* */ + /* */ + /* A structure used for outline (vectorial) glyph images. This */ + /* really is a `sub-class' of `FT_GlyphRec'. */ + /* */ + /* */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* outline :: A descriptor for the outline. */ + /* */ + /* */ + /* You can typecast FT_Glyph to FT_OutlineGlyph if you have */ + /* glyph->format == ft_glyph_format_outline. This lets you access */ + /* the outline's content easily. */ + /* */ + /* As the outline is extracted from a glyph slot, its coordinates are */ + /* expressed normally in 26.6 pixels, unless the flag */ + /* FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char(). */ + /* */ + /* The outline's tables are always owned by the object and are */ + /* destroyed with it. */ + /* */ + typedef struct FT_OutlineGlyphRec_ + { + FT_GlyphRec root; + FT_Outline outline; + + } FT_OutlineGlyphRec, *FT_OutlineGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph */ + /* */ + /* */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph* aglyph ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Copy */ + /* */ + /* */ + /* A function used to copy a glyph image. */ + /* */ + /* */ + /* source :: A handle to the source glyph object. */ + /* */ + /* */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_Copy( FT_Glyph source, + FT_Glyph* target ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Transform */ + /* */ + /* */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* matrix :: A pointer to a 2x2 matrix to apply. */ + /* */ + /* delta :: A pointer to a 2d vector to apply. Coordinates are */ + /* expressed in 1/64th of a pixel. */ + /* */ + /* */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + + enum + { + ft_glyph_bbox_pixels = 0, + ft_glyph_bbox_subpixels = 1, + ft_glyph_bbox_gridfit = 2 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Get_CBox */ + /* */ + /* */ + /* Returns the glyph image's bounding box. */ + /* */ + /* */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: A set of bit flags that indicate how to interpret the */ + /* returned bounding box values. */ + /* */ + /* */ + /* box :: The glyph bounding box. Coordinates are expressed in */ + /* 1/64th of pixels if it is grid-fitted. */ + /* */ + /* */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ + /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ + /* Otherwise, coordinates are expressed in integer pixels. */ + /* */ + /* Note that the maximum coordinates are exclusive, which means that */ + /* one can compute the width and height of the glyph image (be it in */ + /* integer or 26.6 pixels) as: */ + /* */ + /* width = bbox.xMax - bbox.xMin; */ + /* height = bbox.yMax - bbox.yMin; */ + /* */ + /* Note also that for 26.6 coordinates, if the */ + /* `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates */ + /* will also be grid-fitted, which corresponds to: */ + /* */ + /* bbox.xMin = FLOOR(bbox.xMin); */ + /* bbox.yMin = FLOOR(bbox.yMin); */ + /* bbox.xMax = CEILING(bbox.xMax); */ + /* bbox.yMax = CEILING(bbox.yMax); */ + /* */ + /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ + /* */ + FT_EXPORT_DEF( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* */ + /* glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* */ + /* render_mode :: A set of bit flags that describe how the data is */ + /* */ + /* */ + /* origin :: A pointer to a vector used to translate the glyph */ + /* image before rendering. Can be 0 (if no */ + /* translation). The origin is expressed in */ + /* 26.6 pixels. */ + /* */ + /* destroy :: A boolean that indicates that the original glyph */ + /* image should be destroyed by this function. It is */ + /* never destroyed in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The glyph image is translated with the `origin' vector before */ + /* rendering. In case of error, it it translated back to its */ + /* original position and the glyph is left untouched. */ + /* */ + /* The first parameter is a pointer to a FT_Glyph handle, that will */ + /* be replaced by this function. Typically, you would use (omitting */ + /* error handling): */ + /* */ + /* */ + /* { */ + /* FT_Glyph glyph; */ + /* FT_BitmapGlyph glyph_bitmap; */ + /* */ + /* */ + /* // load glyph */ + /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ + /* */ + /* // extract glyph image */ + /* error = FT_Get_Glyph( face->glyph, &glyph ); */ + /* */ + /* // convert to a bitmap (default render mode + destroy old) */ + /* if ( glyph->format != ft_glyph_format_bitmap ) */ + /* { */ + /* error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default, */ + /* 0, 1 ); */ + /* if ( error ) // glyph unchanged */ + /* ... */ + /* } */ + /* */ + /* // access bitmap content by typecasting */ + /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ + /* */ + /* // do funny stuff with it, like blitting/drawing */ + /* ... */ + /* */ + /* // discard glyph image (bitmap or not) */ + /* FT_Done_Glyph( glyph ); */ + /* } */ + /* */ + /* */ + /* This function will always fail if the glyph's format isn't */ + /* scalable. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_ULong render_mode, + FT_Vector* origin, + FT_Bool destroy ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Glyph */ + /* */ + /* */ + /* Destroys a given glyph. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT_DEF( void ) FT_Done_Glyph( FT_Glyph glyph ); + + + /* other helpful functions */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT_DEF( void ) FT_Matrix_Multiply( FT_Matrix* a, + FT_Matrix* b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTGLYPH_H */ + + +/* END */ diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h new file mode 100644 index 0000000..4dd1c3d --- /dev/null +++ b/include/freetype/ftimage.h @@ -0,0 +1,1003 @@ +/***************************************************************************/ +/* */ +/* ftimage.h */ +/* */ +/* FreeType glyph image formats and default raster interface */ +/* (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Note: A `raster' is simply a scan-line converter, used to render */ + /* FT_Outlines into FT_Bitmaps. */ + /* */ + /*************************************************************************/ + + +#ifndef FTIMAGE_H +#define FTIMAGE_H + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pos */ + /* */ + /* */ + /* The type FT_Pos is a 32-bit integer used to store vectorial */ + /* coordinates. Depending on the context, these can represent */ + /* distances in integer font units, or 26.6 fixed float pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_Pos; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2D vector; coordinates are of */ + /* the FT_Pos type. */ + /* */ + /* */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + typedef struct FT_Vector_ + { + FT_Pos x; + FT_Pos y; + + } FT_Vector; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pixel_Mode */ + /* */ + /* */ + /* An enumeration type used to describe the format of pixels in a */ + /* given bitmap. Note that additional formats may be added in the */ + /* future. */ + /* */ + /* */ + /* ft_pixel_mode_mono :: A monochrome bitmap (1 bit/pixel). */ + /* */ + /* ft_pixel_mode_grays :: An 8-bit gray-levels bitmap. Note that the */ + /* total number of gray levels is given in the */ + /* `num_grays' field of the FT_Bitmap */ + /* structure. */ + /* */ + /* ft_pixel_mode_pal2 :: A 2-bit paletted bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_pal4 :: A 4-bit paletted bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_pal8 :: An 8-bit paletted bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb15 :: A 15-bit RGB bitmap. Uses 5:5:5 encoding. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb16 :: A 16-bit RGB bitmap. Uses 5:6:5 encoding. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb24 :: A 24-bit RGB bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb32 :: A 32-bit RGB bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* */ + /* Some anti-aliased bitmaps might be embedded in TrueType fonts */ + /* using formats pal2 or pal4, though no fonts presenting those have */ + /* been found to date. */ + /* */ + typedef enum FT_Pixel_Mode_ + { + ft_pixel_mode_none = 0, + ft_pixel_mode_mono, + ft_pixel_mode_grays, + ft_pixel_mode_pal2, + ft_pixel_mode_pal4, + ft_pixel_mode_pal8, + ft_pixel_mode_rgb15, + ft_pixel_mode_rgb16, + ft_pixel_mode_rgb24, + ft_pixel_mode_rgb32, + + ft_pixel_mode_max /* do not remove */ + + } FT_Pixel_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Palette_Mode */ + /* */ + /* */ + /* An enumeration type used to describe the format of a bitmap */ + /* palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */ + /* */ + /* */ + /* ft_palette_mode_rgb :: The palette is an array of 3-bytes RGB */ + /* records. */ + /* */ + /* ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA */ + /* records. */ + /* */ + /* */ + /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */ + /* FreeType, these types are not handled by the library itself. */ + /* */ + typedef enum FT_Palette_Mode_ + { + ft_palette_mode_rgb = 0, + ft_palette_mode_rgba, + + ft_palettte_mode_max /* do not remove */ + + } FT_Palette_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bitmap */ + /* */ + /* */ + /* A structure used to describe a bitmap or pixmap to the raster. */ + /* Note that we now manage pixmaps of various depths through the */ + /* `pixel_mode' field. */ + /* */ + /* */ + /* rows :: The number of bitmap rows. */ + /* */ + /* width :: The number of pixels in bitmap row. */ + /* */ + /* pitch :: The pitch's absolute value is the number of bytes */ + /* taken by one bitmap row, including padding. */ + /* However, the pitch is positive when the bitmap has */ + /* a `down' flow, and negative when it has an `up' */ + /* flow. In all cases, the pitch is an offset to add */ + /* to a bitmap pointer in order to go down one row. */ + /* */ + /* buffer :: A typeless pointer to the bitmap buffer. This */ + /* value should be aligned on 32-bit boundaries in */ + /* most cases. */ + /* */ + /* num_grays :: This field is only used with */ + /* `ft_pixel_mode_grays'; it gives the number of gray */ + /* levels used in the bitmap. */ + /* */ + /* pixel_mode :: The pixel_mode, i.e., how pixel bits are stored. */ + /* */ + /* palette_mode :: This field is only used with paletted pixel modes; */ + /* it indicates how the palette is stored. */ + /* */ + /* palette :: A typeless pointer to the bitmap palette; only */ + /* used for paletted pixel modes. */ + /* */ + /* */ + /* For now, the only pixel mode supported by FreeType are mono and */ + /* grays. However, drivers might be added in the future to support */ + /* more `colorful' options. */ + /* */ + /* When using pixel modes pal2, pal4 and pal8 with a void `palette' */ + /* field, a gray pixmap with respectively 4, 16, and 256 levels of */ + /* gray is assumed. This, in order to be compatible with some */ + /* embedded bitmap formats defined in the TrueType specification. */ + /* */ + /* Note that no font was found presenting such embedded bitmaps, so */ + /* this is currently completely unhandled by the library. */ + /* */ + typedef struct FT_Bitmap_ + { + int rows; + int width; + int pitch; + unsigned char* buffer; + short num_grays; + char pixel_mode; + char palette_mode; + void* palette; + + } FT_Bitmap; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline */ + /* */ + /* */ + /* This structure is used to describe an outline to the scan-line */ + /* converter. */ + /* */ + /* */ + /* n_contours :: The number of contours in the outline. */ + /* */ + /* n_points :: The number of points in the outline. */ + /* */ + /* points :: A pointer to an array of `n_points' FT_Vector */ + /* elements, giving the outline's point coordinates. */ + /* */ + /* tags :: A pointer to an array of `n_points' chars, giving */ + /* giving each outline point's type. If bit 0 is */ + /* unset, the point is 'off' the curve, i.e. a Bezier */ + /* control point, while it is `on' when unset. */ + /* */ + /* Bit 1 is meaningful for `off' points only. If set, */ + /* it indicates a third-order Bezier arc control point; */ + /* and a second-order control point if unset. */ + /* */ + /* contours :: An array of `n_contours' shorts, giving the end */ + /* point of each contour within the outline. For */ + /* example, the first contour is defined by the points */ + /* `0' to `contours[0]', the second one is defined by */ + /* the points `contours[0]+1' to `contours[1]', etc. */ + /* */ + /* flags :: A set of bit flags used to characterize the outline */ + /* and give hints to the scan-converter and hinter on */ + /* how to convert/grid-fit it. See FT_Outline_Flags. */ + /* */ + typedef struct FT_Outline_ + { + short n_contours; /* number of contours in glyph */ + short n_points; /* number of points in the glyph */ + + FT_Vector* points; /* the outline's points */ + char* tags; /* the points flags */ + short* contours; /* the contour end points */ + + int flags; /* outline masks */ + + } FT_Outline; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Flags */ + /* */ + /* */ + /* A simple type used to enumerates the flags in an outline's */ + /* `outline_flags' field. */ + /* */ + /* */ + /* ft_outline_owner :: If set, this flag indicates that the */ + /* outline's field arrays (i.e. */ + /* `points', `flags' & `contours') are */ + /* `owned' by the outline object, and */ + /* should thus be freed when it is */ + /* destroyed. */ + /* */ + /* ft_outline_even_odd_fill :: By default, outlines are filled using */ + /* the non-zero winding rule. If set to */ + /* 1, the outline will be filled using */ + /* the even-odd fill rule (only works */ + /* with the smooth raster). */ + /* */ + /* ft_outline_reverse_fill :: By default, outside contours of an */ + /* outline are oriented in clock-wise */ + /* direction, as defined in the TrueType */ + /* specification. This flag is set if */ + /* the outline uses the opposite */ + /* direction (typically for Type 1 */ + /* fonts). This flag is ignored by the */ + /* scan-converter. However, it is very */ + /* important for the auto-hinter. */ + /* */ + /* ft_outline_ignore_dropouts :: By default, the scan converter will */ + /* try to detect drop-outs in an outline */ + /* and correct the glyph bitmap to */ + /* ensure consistent shape continuity. */ + /* If set, this flag hints the scan-line */ + /* converter to ignore such cases. */ + /* */ + /* ft_outline_high_precision :: This flag indicates that the */ + /* scan-line converter should try to */ + /* convert this outline to bitmaps with */ + /* the highest possible quality. It is */ + /* typically set for small character */ + /* sizes. Note that this is only a */ + /* hint, that might be completely */ + /* ignored by a given scan-converter. */ + /* */ + /* ft_outline_single_pass :: This flag is set to force a given */ + /* scan-converter to only use a single */ + /* pass over the outline to render a */ + /* bitmap glyph image. Normally, it is */ + /* set for very large character sizes. */ + /* It is only a hint, that might be */ + /* completely ignored by a given */ + /* scan-converter. */ + /* */ + typedef enum FT_Outline_Flags_ + { + ft_outline_none = 0, + ft_outline_owner = 1, + ft_outline_even_odd_fill = 2, + ft_outline_reverse_fill = 4, + ft_outline_ignore_dropouts = 8, + ft_outline_high_precision = 256, + ft_outline_single_pass = 512 + + } FT_Outline_Flags; + + +#define FT_CURVE_TAG( flag ) ( flag & 3 ) + +#define FT_Curve_Tag_On 1 +#define FT_Curve_Tag_Conic 0 +#define FT_Curve_Tag_Cubic 2 + +#define FT_Curve_Tag_Touch_X 8 /* reserved for the TrueType hinter */ +#define FT_Curve_Tag_Touch_Y 16 /* reserved for the TrueType hinter */ + +#define FT_Curve_Tag_Touch_Both ( FT_Curve_Tag_Touch_X | \ + FT_Curve_Tag_Touch_Y ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_MoveTo_Func */ + /* */ + /* */ + /* A function pointer type used to describe the signature of a `move */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `move to' is emitted to start a new contour in an outline. */ + /* */ + /* */ + /* to :: A pointer to the target point of the `move to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_MoveTo_Func)( FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_LineTo_Func */ + /* */ + /* */ + /* A function pointer type used to describe the signature of a `line */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `line to' is emitted to indicate a segment in the outline. */ + /* */ + /* */ + /* to :: A pointer to the target point of the `line to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_LineTo_Func)( FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_ConicTo_Func */ + /* */ + /* */ + /* A function pointer type use to describe the signature of a `conic */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `conic to' is emitted to indicate a second-order Bezier arc in */ + /* the outline. */ + /* */ + /* */ + /* control :: An intermediate control point between the last position */ + /* and the new target in `to'. */ + /* */ + /* to :: A pointer to the target end point of the conic arc. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_ConicTo_Func)( FT_Vector* control, + FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_CubicTo_Func */ + /* */ + /* */ + /* A function pointer type used to describe the signature of a `cubic */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `cubic to' is emitted to indicate a third-order Bezier arc. */ + /* */ + /* */ + /* control1 :: A pointer to the first Bezier control point. */ + /* */ + /* control2 :: A pointer to the second Bezier control point. */ + /* */ + /* to :: A pointer to the target end point. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_CubicTo_Func)( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Funcs */ + /* */ + /* */ + /* A structure to hold various function pointers used during outline */ + /* decomposition in order to emit segments, conic, and cubic Beziers, */ + /* as well as `move to' and `close to' operations. */ + /* */ + /* */ + /* move_to :: The `move to' emitter. */ + /* */ + /* line_to :: The segment emitter. */ + /* */ + /* conic_to :: The second-order Bezier arc emitter. */ + /* */ + /* cubic_to :: The third-order Bezier arc emitter. */ + /* */ + /* shift :: The shift that is applied to coordinates before they */ + /* are sent to the emitter. */ + /* */ + /* delta :: The delta that is applied to coordinates before they */ + /* are sent to the emitter, but after the shift. */ + /* */ + /* */ + /* The point coordinates sent to the emitters are the transformed */ + /* version of the original coordinates (this is important for high */ + /* accuracy during scan-conversion). The transformation is simple: */ + /* */ + /* x' = (x << shift) - delta */ + /* y' = (x << shift) - delta */ + /* */ + /* Set the value of `shift' and `delta' to 0 to get the original */ + /* point coordinates. */ + /* */ + typedef struct FT_Outline_Funcs_ + { + FT_Outline_MoveTo_Func move_to; + FT_Outline_LineTo_Func line_to; + FT_Outline_ConicTo_Func conic_to; + FT_Outline_CubicTo_Func cubic_to; + + int shift; + FT_Pos delta; + + } FT_Outline_Funcs; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_IMAGE_TAG */ + /* */ + /* */ + /* This macro converts four letter tags into an unsigned long. */ + /* */ +#define FT_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (unsigned long)_x1 << 24 ) | \ + ( (unsigned long)_x2 << 16 ) | \ + ( (unsigned long)_x3 << 8 ) | \ + (unsigned long)_x4 ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Format */ + /* */ + /* */ + /* An enumeration type used to describe the format of a given glyph */ + /* image. Note that this version of FreeType only supports two image */ + /* formats, even though future font drivers will be able to register */ + /* their own format. */ + /* */ + /* */ + /* ft_glyph_format_composite :: The glyph image is a composite of */ + /* several other images. This glyph */ + /* format is _only_ used with the */ + /* FT_LOAD_FLAG_NO_RECURSE flag (XXX: */ + /* Which is currently unimplemented). */ + /* */ + /* ft_glyph_format_bitmap :: The glyph image is a bitmap, and can */ + /* be described as a FT_Bitmap. */ + /* */ + /* ft_glyph_format_outline :: The glyph image is a vectorial image */ + /* made of bezier control points, and */ + /* can be described as a FT_Outline. */ + /* */ + /* ft_glyph_format_plotter :: The glyph image is a vectorial image */ + /* made of plotter lines (some T1 fonts */ + /* like Hershey contain glyph in this */ + /* format). */ + /* */ + typedef enum FT_Glyph_Format_ + { + ft_glyph_format_none = 0, + ft_glyph_format_composite = FT_IMAGE_TAG( 'c', 'o', 'm', 'p' ), + ft_glyph_format_bitmap = FT_IMAGE_TAG( 'b', 'i', 't', 's' ), + ft_glyph_format_outline = FT_IMAGE_TAG( 'o', 'u', 't', 'l' ), + ft_glyph_format_plotter = FT_IMAGE_TAG( 'p', 'l', 'o', 't' ) + + } FT_Glyph_Format; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** R A S T E R D E F I N I T I O N S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* A raster is a scan converter, in charge of rendering an outline into */ + /* a a bitmap. This section contains the public API for rasters. */ + /* */ + /* Note that in FreeType 2, all rasters are now encapsulated within */ + /* specific modules called `renderers'. See `freetype/ftrender.h' for */ + /* more details on renderers. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster */ + /* */ + /* */ + /* A handle (pointer) to a raster object. Each object can be used */ + /* independently to convert an outline into a bitmap or pixmap. */ + /* */ + typedef struct FT_RasterRec_* FT_Raster; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Span */ + /* */ + /* */ + /* A structure used to model a single span of gray (or black) pixels */ + /* when rendering a monochrome or anti-aliased bitmap. */ + /* */ + /* */ + /* x :: The span's horizontal start position. */ + /* */ + /* len :: The span's length in pixels. */ + /* */ + /* coverage :: The span color/coverage, ranging from 0 (background) */ + /* to 255 (foreground). Only used for anti-aliased */ + /* rendering. */ + /* */ + /* */ + /* This structure is used by the span drawing callback type named */ + /* FT_Raster_Span_Func(), which takes the y-coordinate of the span as */ + /* a parameter. */ + /* */ + /* The coverage value is always between 0 and 255, even if the number */ + /* of gray levels have been set through FT_Set_Gray_Levels(). */ + /* */ + typedef struct FT_Span_ + { + short x; + unsigned short len; + unsigned char coverage; + + } FT_Span; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Span_Func */ + /* */ + /* */ + /* A function used as a call-back by the anti-aliased renderer in */ + /* order to let client applications draw themselves the gray pixel */ + /* spans on each scan line. */ + /* */ + /* */ + /* y :: The scanline's y-coordinate. */ + /* */ + /* count :: The number of spans to draw on this scanline. */ + /* */ + /* spans :: A table of `count' spans to draw on the scanline. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* This callback allows client applications to directly render the */ + /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ + /* */ + /* This can be used to write anti-aliased outlines directly to a */ + /* given background bitmap, and even perform translucency. */ + /* */ + /* Note that the `count' field cannot be greater than a fixed value */ + /* defined by the FT_MAX_GRAY_SPANS configuration macro in */ + /* ftoption.h. By default, this value is set to 32, which means that */ + /* if there are more than 32 spans on a given scanline, the callback */ + /* will be called several times with the same `y' parameter in order */ + /* to draw all callbacks. */ + /* */ + /* Otherwise, the callback is only called once per scan-line, and */ + /* only for those scanlines that do have `gray' pixels on them. */ + /* */ + typedef void (*FT_Raster_Span_Func)( int y, + int count, + FT_Span* spans, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitTest_Func */ + /* */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to test whether a given target pixel is already set to the drawing */ + /* `color'. These tests are crucial to implement drop-out control */ + /* per-se the TrueType spec. */ + /* */ + /* */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef int (*FT_Raster_BitTest_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitSet_Func */ + /* */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to set an individual target pixel. This is crucial to implement */ + /* drop-out control according to the TrueType specification. */ + /* */ + /* */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef void (*FT_Raster_BitSet_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Flag */ + /* */ + /* */ + /* An enumeration to list the bit flags as used in the `flags' field */ + /* of a FT_Raster_Params structure. */ + /* */ + /* */ + /* ft_raster_flag_default :: This value is 0. */ + /* */ + /* ft_raster_flag_aa :: Requests the rendering of an */ + /* anti-aliased glyph bitmap. If unset, a */ + /* monchrome bitmap will be rendered. */ + /* */ + /* ft_raster_flag_direct :: Requests direct rendering over the */ + /* target bitmap. Direct rendering uses */ + /* user-provided callbacks in order to */ + /* perform direct drawing or composition */ + /* over an existing bitmap. If this bit is */ + /* unset, the content of the target bitmap */ + /* *must be zeroed*! */ + /* */ + typedef enum + { + ft_raster_flag_default = 0, + ft_raster_flag_aa = 1, + ft_raster_flag_direct = 2 + + } FT_Raster_Flag; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Params */ + /* */ + /* */ + /* A structure to hold the arguments used by a raster's render */ + /* function. */ + /* */ + /* */ + /* target :: The target bitmap. */ + /* */ + /* source :: A pointer to the source glyph image (e.g. an */ + /* FT_Outline). */ + /* */ + /* flags :: The rendering flags. */ + /* */ + /* gray_spans :: The gray span drawing callback. */ + /* */ + /* black_spans :: The black span drawing callback. */ + /* */ + /* bit_test :: The bit test callback. */ + /* */ + /* bit_set :: The bit set callback. */ + /* */ + /* user :: User-supplied data that is passed to each drawing */ + /* callback. */ + /* */ + /* */ + /* An anti-aliased glyph bitmap is drawn if the ft_raster_flag_aa bit */ + /* flag is set in the `flags' field, otherwise a monochrome bitmap */ + /* will be generated. */ + /* */ + /* If the ft_raster_flag_direct bit flag is set in `flags', the */ + /* raster will call the `gray_spans' callback to draw gray pixel */ + /* spans, in the case of an aa glyph bitmap, it will call */ + /* `black_spans', and `bit_test' and `bit_set' in the case of a */ + /* monochrome bitmap. This allows direct composition over a */ + /* pre-existing bitmap through user-provided callbacks to perform the */ + /* span drawing/composition. */ + /* */ + /* Note that the `bit_test' and `bit_set' callbacks are required when */ + /* rendering a monochrome bitmap, as they are crucial to implement */ + /* correct drop-out control as defined in the TrueType specification. */ + /* */ + typedef struct FT_Raster_Params_ + { + FT_Bitmap* target; + void* source; + int flags; + FT_Raster_Span_Func gray_spans; + FT_Raster_Span_Func black_spans; + FT_Raster_BitTest_Func bit_test; + FT_Raster_BitSet_Func bit_set; + void* user; + + } FT_Raster_Params; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_New_Func */ + /* */ + /* */ + /* A function used to create a new raster object. */ + /* */ + /* */ + /* memory :: A handle to the memory allocator. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* The `memory' parameter is a typeless pointer in order to avoid */ + /* un-wanted dependencies on the rest of the FreeType code. In */ + /* practice, it is a FT_Memory, i.e., a handle to the standard */ + /* FreeType memory allocator. However, this field can be completely */ + /* ignored by a given raster implementation. */ + /* */ + typedef int (*FT_Raster_New_Func)( void* memory, + FT_Raster* raster ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Done_Func */ + /* */ + /* */ + /* A function used to destroy a given raster object. */ + /* */ + /* */ + /* raster :: A handle to the raster object. */ + /* */ + typedef void (*FT_Raster_Done_Func)( FT_Raster raster ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Reset_Func */ + /* */ + /* */ + /* FreeType provides an area of memory called the `render pool', */ + /* available to all registered rasters. This pool can be freely used */ + /* during a given scan-conversion but is shared by all rasters. Its */ + /* content is thus transient. */ + /* */ + /* This function is called each time the render pool changes, or just */ + /* after a new raster object is created. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* pool_base :: The address in memory of the render pool. */ + /* */ + /* pool_size :: The size in bytes of the render pool. */ + /* */ + /* */ + /* Rasters can ignore the render pool and rely on dynamic memory */ + /* allocation if they want to (a handle to the memory allocator is */ + /* passed to the raster constructor). However, this is not */ + /* recommended for efficiency purposes. */ + /* */ + typedef void (*FT_Raster_Reset_Func)( FT_Raster raster, + unsigned char* pool_base, + unsigned long pool_size ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Set_Mode_Func */ + /* */ + /* */ + /* This function is a generic facility to change modes or attributes */ + /* in a given raster. This can be used for debugging purposes, or */ + /* simply to allow implementation-specific `features' in a given */ + /* raster module. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* mode :: A 4-byte tag used to name the mode or property. */ + /* */ + /* args :: A pointer to the new mode/property to use. */ + /* */ + typedef int (*FT_Raster_Set_Mode_Func)( FT_Raster raster, + unsigned long mode, + void* args ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Render_Func */ + /* */ + /* */ + /* Invokes a given raster to scan-convert a given glyph image into a */ + /* target bitmap. */ + /* */ + /* */ + /* raster :: A handle to the raster object. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to store */ + /* the rendering parameters. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* The exact format of the source image depends on the raster's glyph */ + /* format defined in its FT_Raster_Funcs structure. It can be an */ + /* FT_Outline or anything else in order to support a large array of */ + /* glyph formats. */ + /* */ + /* Note also that the render function can fail and return a */ + /* FT_Err_Unimplemented_Feature error code if the raster used does */ + /* not support direct composition. */ + /* */ + /* XXX: For now, the standard raster doesn't support direct */ + /* composition but this should change for the final release (see */ + /* the files demos/src/ftgrays.c and demos/src/ftgrays2.c for */ + /* examples of distinct implementations which support direct */ + /* composition). */ + /* */ + typedef int (*FT_Raster_Render_Func)( FT_Raster raster, + FT_Raster_Params* params ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Funcs */ + /* */ + /* */ + /* A structure used to describe a given raster class to the library. */ + /* */ + /* */ + /* glyph_format :: The supported glyph format for this raster. */ + /* */ + /* raster_new :: The raster constructor. */ + /* */ + /* raster_reset :: Used to reset the render pool within the raster. */ + /* */ + /* raster_render :: A function to render a glyph into a given bitmap. */ + /* */ + /* raster_done :: The raster destructor. */ + /* */ + typedef struct FT_Raster_Funcs_ + { + FT_Glyph_Format glyph_format; + FT_Raster_New_Func raster_new; + FT_Raster_Reset_Func raster_reset; + FT_Raster_Set_Mode_Func raster_set_mode; + FT_Raster_Render_Func raster_render; + FT_Raster_Done_Func raster_done; + + } FT_Raster_Funcs; + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTIMAGE_H */ + + +/* END */ diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h new file mode 100644 index 0000000..db5db04 --- /dev/null +++ b/include/freetype/ftmm.h @@ -0,0 +1,175 @@ +/***************************************************************************/ +/* */ +/* ftmm.h */ +/* */ +/* FreeType Multiple Master font interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTMM_H +#define FTMM_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MM_Axis */ + /* */ + /* */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters fonts. */ + /* */ + /* */ + /* name :: The axis's name. */ + /* */ + /* minimum :: The axis's minimum design coordinate. */ + /* */ + /* maximum :: The axis's maximum design coordinate. */ + /* */ + typedef struct FT_MM_Axis_ + { + FT_String* name; + FT_Long minimum; + FT_Long maximum; + + } FT_MM_Axis; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Multi_Master */ + /* */ + /* */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* font. */ + /* */ + /* */ + /* num_axis :: Number of axes. Cannot exceed 4. */ + /* */ + /* num_designs :: Number of designs; should ne normally 2^num_axis */ + /* even though the Type 1 specification strangely */ + /* allows for intermediate designs to be present. This */ + /* number cannot exceed 16. */ + /* */ + /* axis :: A table of axis descriptors. */ + /* */ + typedef struct FT_Multi_Master_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_MM_Axis axis[T1_MAX_MM_AXIS]; + + } FT_Multi_Master; + + + typedef FT_Error (*FT_Get_MM_Func)( FT_Face face, + FT_Multi_Master* master ); + + typedef FT_Error (*FT_Set_MM_Design_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + typedef FT_Error (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Multi_Master */ + /* */ + /* */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* */ + /* master :: The Multiple Masters descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Design_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through normalized blend coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates (each one must be between 0 */ + /* and 1.0). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Blend_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTMM_H */ + + +/* END */ diff --git a/include/freetype/ftmodule.h b/include/freetype/ftmodule.h new file mode 100644 index 0000000..3c09aa2 --- /dev/null +++ b/include/freetype/ftmodule.h @@ -0,0 +1,274 @@ +/***************************************************************************/ +/* */ +/* ftmodule.h */ +/* */ +/* FreeType modules public interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTMODULE_H +#define FTMODULE_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* module bit flags */ + typedef enum FT_Module_Flags_ + { + ft_module_font_driver = 1, /* this module is a font driver */ + ft_module_renderer = 2, /* this module is a renderer */ + ft_module_hinter = 4, /* this module is a glyph hinter */ + ft_module_styler = 8, /* this module is a styler */ + + ft_module_driver_scalable = 0x100, /* the driver supports scalable */ + /* fonts */ + ft_module_driver_no_outlines = 0x200, /* the driver does not support */ + /* vector outlines */ + ft_module_driver_has_hinter = 0x400 /* the driver provides its own */ + /* hinter */ + + } FT_Module_Flags; + + + typedef void (*FT_Module_Interface)( void ); + + typedef FT_Error (*FT_Module_Constructor)( FT_Module module ); + + typedef void (*FT_Module_Destructor)( FT_Module module ); + + typedef FT_Module_Interface (*FT_Module_Requester)( FT_Module module, + const char* name ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Module_Class */ + /* */ + /* */ + /* The module class descriptor. */ + /* */ + /* */ + /* module_flags :: Bit flags describing the module. */ + /* */ + /* module_size :: The size of one module object/instance in */ + /* bytes. */ + /* */ + /* module_name :: The name of the module. */ + /* */ + /* module_version :: The version, as a 16.16 fixed number */ + /* (major.minor). */ + /* */ + /* module_requires :: The version of FreeType this module requires */ + /* (starts at version 2.0, i.e 0x20000) */ + /* */ + /* module_init :: A function used to initialize (not create) a */ + /* new module object. */ + /* */ + /* module_done :: A function used to finalize (not destroy) a */ + /* given module object */ + /* */ + /* get_interface :: Queries a given module for a specific */ + /* interface by name. */ + /* */ + typedef struct FT_Module_Class_ + { + FT_ULong module_flags; + FT_Int module_size; + const FT_String* module_name; + FT_Fixed module_version; + FT_Fixed module_requires; + + const void* module_interface; + + FT_Module_Constructor module_init; + FT_Module_Destructor module_done; + FT_Module_Requester get_interface; + + } FT_Module_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Module */ + /* */ + /* */ + /* Adds a new module to a given library instance. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module */ + /* */ + /* */ + /* Finds a module by its name. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module handle. 0 if none was found. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT_DEF( FT_Module ) FT_Get_Module( FT_Library library, + const char* module_name ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Module */ + /* */ + /* */ + /* Removes a given module from a library instance. */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* module :: A handle to a module object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Remove_Module( FT_Library library, + FT_Module module ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Library */ + /* */ + /* */ + /* This function is used to create a new FreeType library instance */ + /* from a given memory object. It is thus possible to use libraries */ + /* with distinct memory allocators within the same program. */ + /* */ + /* */ + /* memory :: A handle to the original memory object. */ + /* */ + /* */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Library( FT_Memory memory, + FT_Library* library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_Library( FT_Library library ); + + + + typedef void (*FT_DebugHook_Func)( void* arg ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Debug_Hook */ + /* */ + /* */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* hook_index :: The index of the debug hook. You should use the */ + /* values defined in ftobjs.h, e.g. */ + /* FT_DEBUG_HOOK_TRUETYPE */ + /* */ + /* debug_hook :: The function used to debug the interpreter. */ + /* */ + /* */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT_DEF( void ) FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ); + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Default_Modules */ + /* */ + /* */ + /* Adds the set of default drivers to a given library object. */ + /* This is only useful when you create a library object with */ + /* FT_New_Library() (usually to plug a custom memory manager). */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT_DEF( void ) FT_Add_Default_Modules( FT_Library library ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTMODULE_H */ + + +/* END */ diff --git a/include/freetype/ftnames.h b/include/freetype/ftnames.h new file mode 100644 index 0000000..2969214 --- /dev/null +++ b/include/freetype/ftnames.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ftnames.h */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTNAMES_H +#define FTNAMES_H + + +#include + + + typedef struct FT_SfntName_ + { + FT_UShort platform_id; + FT_UShort encoding_id; + FT_UShort language_id; + FT_UShort name_id; + + FT_Byte* string; + FT_UInt string_len; /* in bytes */ + + } FT_SfntName; + + + FT_EXPORT_DEF( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ); + + FT_EXPORT_DEF( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, + FT_UInt index, + FT_SfntName* aname ); + + +#endif /* FTNAMES_H */ + + +/* END */ diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h new file mode 100644 index 0000000..1e448bd --- /dev/null +++ b/include/freetype/ftoutln.h @@ -0,0 +1,344 @@ +/***************************************************************************/ +/* */ +/* ftoutln.h */ +/* */ +/* Support for the FT_Outline type used to store glyph shapes of */ +/* most scalable font formats (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTOUTLN_H +#define FTOUTLN_H + + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* */ + /* outline :: A pointer to the source target. */ + /* */ + /* interface :: A table of `emitters', i.e,. function pointers called */ + /* during decomposition to indicate path operations. */ + /* */ + /* user :: A typeless pointer which is passed to each emitter */ + /* during the decomposition. It can be used to store */ + /* the state during the decomposition. */ + /* */ + /* */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Decompose( + FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* library :: A handle to the library object from where the */ + /* outline is allocated. Note however that the new */ + /* outline will NOT necessarily be FREED, when */ + /* destroying the library, by FT_Done_FreeType(). */ + /* */ + /* numPoints :: The maximal number of points within the outline. */ + /* */ + /* numContours :: The maximal number of contours within the outline. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + FT_EXPORT_DEF( FT_Error ) FT_Outline_New_Internal( + FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Done( FT_Library library, + FT_Outline* outline ); + + + FT_EXPORT_DEF( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* Returns an outline's `control box'. The control box encloses all */ + /* the outline's points, including Bezier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bezier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* */ + /* */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Copy( FT_Outline* source, + FT_Outline* target ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag `ft_outline_reverse_fill' in */ + /* the outline's `flags' field. */ + /* */ + /* It shouldn't be used by a normal client application, unless it */ + /* knows what it is doing. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Reverse( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! */ + /* */ + /* It will use the raster correponding to the default glyph format. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* bitmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* Renders an outline within a bitmap using the current scan-convert. */ + /* This functions uses an FT_Raster_Params structure as an argument, */ + /* allowing advanced features like direct composition, translucency, */ + /* etc. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* You should know what you are doing and how FT_Raster_Params works */ + /* to use this function. */ + /* */ + /* The field `params.source' will be set to `outline' before the scan */ + /* converter is called, which means that the value you give to it is */ + /* actually ignored. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTOUTLN_H */ + + +/* END */ diff --git a/include/freetype/ftrender.h b/include/freetype/ftrender.h new file mode 100644 index 0000000..fe5acd2 --- /dev/null +++ b/include/freetype/ftrender.h @@ -0,0 +1,191 @@ +/***************************************************************************/ +/* */ +/* ftrender.h */ +/* */ +/* FreeType renderer modules public interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTRENDER_H +#define FTRENDER_H + +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* create a new glyph object */ + typedef FT_Error (*FT_Glyph_Init_Func)( FT_Glyph glyph, + FT_GlyphSlot slot ); + + /* destroys a given glyph object */ + typedef void (*FT_Glyph_Done_Func)( FT_Glyph glyph ); + + typedef void (*FT_Glyph_Transform_Func)( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + typedef void (*FT_Glyph_BBox_Func)( FT_Glyph glyph, + FT_BBox* abbox ); + + typedef FT_Error (*FT_Glyph_Copy_Func)( FT_Glyph source, + FT_Glyph target ); + + typedef FT_Error (*FT_Glyph_Prepare_Func)( FT_Glyph glyph, + FT_GlyphSlot slot ); + + struct FT_Glyph_Class_ + { + FT_UInt glyph_size; + FT_Glyph_Format glyph_format; + FT_Glyph_Init_Func glyph_init; + FT_Glyph_Done_Func glyph_done; + FT_Glyph_Copy_Func glyph_copy; + FT_Glyph_Transform_Func glyph_transform; + FT_Glyph_BBox_Func glyph_bbox; + FT_Glyph_Prepare_Func glyph_prepare; + }; + + + typedef FT_Error (*FTRenderer_render)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_UInt mode, + FT_Vector* origin ); + + typedef FT_Error (*FTRenderer_transform)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ); + + typedef void (*FTRenderer_getCBox)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_BBox* cbox ); + + typedef FT_Error (*FTRenderer_setMode)( FT_Renderer renderer, + FT_ULong mode_tag, + FT_Pointer mode_ptr ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Renderer_Class */ + /* */ + /* */ + /* The renderer module class descriptor. */ + /* */ + /* */ + /* root :: The root FT_Module_Class fields. */ + /* */ + /* glyph_format :: The glyph image format this renderer handles. */ + /* */ + /* render_glyph :: A method used to render the image that is in a */ + /* given glyph slot into a bitmap. */ + /* */ + /* set_mode :: A method used to pass additional parameters. */ + /* */ + /* raster_class :: For `ft_glyph_format_outline' renderers only, this */ + /* is a pointer to its raster's class. */ + /* */ + /* raster :: For `ft_glyph_format_outline' renderers only. this */ + /* is a pointer to the corresponding raster object, */ + /* if any. */ + /* */ + typedef struct FT_Renderer_Class_ + { + FT_Module_Class root; + + FT_Glyph_Format glyph_format; + + FTRenderer_render render_glyph; + FTRenderer_transform transform_glyph; + FTRenderer_getCBox get_glyph_cbox; + FTRenderer_setMode set_mode; + + FT_Raster_Funcs* raster_class; + + } FT_Renderer_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Renderer */ + /* */ + /* */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* */ + /* A renderer handle. 0 if none found. */ + /* */ + /* */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */ + /* renderer by its name, use FT_Get_Module(). */ + /* */ + FT_EXPORT_DEF( FT_Renderer ) FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Renderer */ + /* */ + /* */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* In case of success, the renderer will be used to convert glyph */ + /* images in the renderer's known format into bitmaps. */ + /* */ + /* This doesn't change the current renderer for other formats. */ + /* */ + FT_EXPORT_DEF(FT_Error) FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTRENDER_H */ + + +/* END */ diff --git a/include/freetype/ftsystem.h b/include/freetype/ftsystem.h new file mode 100644 index 0000000..bc74bce --- /dev/null +++ b/include/freetype/ftsystem.h @@ -0,0 +1,101 @@ +/***************************************************************************/ +/* */ +/* ftsystem.h */ +/* */ +/* FreeType low-level system interface definition (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTSYSTEM_H +#define FTSYSTEM_H + + + /*************************************************************************/ + /* */ + /* M E M O R Y M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + typedef struct FT_MemoryRec_* FT_Memory; + + + typedef void* (*FT_Alloc_Func)( FT_Memory memory, + long size ); + + typedef void (*FT_Free_Func)( FT_Memory memory, + void* block ); + + typedef void* (*FT_Realloc_Func)( FT_Memory memory, + long cur_size, + long new_size, + void* block ); + + + struct FT_MemoryRec_ + { + void* user; + FT_Alloc_Func alloc; + FT_Free_Func free; + FT_Realloc_Func realloc; + }; + + + /*************************************************************************/ + /* */ + /* I / O M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + typedef union FT_StreamDesc_ + { + long value; + void* pointer; + + } FT_StreamDesc; + + + typedef struct FT_StreamRec_* FT_Stream; + + + typedef unsigned long (*FT_Stream_IO)( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ); + + typedef void (*FT_Stream_Close)( FT_Stream stream ); + + + struct FT_StreamRec_ + { + unsigned char* base; + unsigned long size; + unsigned long pos; + + FT_StreamDesc descriptor; + FT_StreamDesc pathname; /* ignored by FreeType -- */ + /* useful for debugging */ + FT_Stream_IO read; + FT_Stream_Close close; + + FT_Memory memory; + unsigned char* cursor; + unsigned char* limit; + }; + + +#endif /* FTSYSTEM_H */ + + +/* END */ diff --git a/include/freetype/fttypes.h b/include/freetype/fttypes.h new file mode 100644 index 0000000..ec90906 --- /dev/null +++ b/include/freetype/fttypes.h @@ -0,0 +1,400 @@ +/***************************************************************************/ +/* */ +/* fttypes.h */ +/* */ +/* FreeType simple types definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTTYPES_H +#define FTTYPES_H + + +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bool */ + /* */ + /* */ + /* A typedef of unsigned char, used for simple booleans. */ + /* */ + typedef unsigned char FT_Bool; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FWord */ + /* */ + /* */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + typedef signed short FT_FWord; /* distance in FUnits */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UFWord */ + /* */ + /* */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + typedef unsigned short FT_UFWord; /* unsigned distance */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Char */ + /* */ + /* */ + /* A simple typedef for the _signed_ char type. */ + /* */ + typedef signed char FT_Char; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Byte */ + /* */ + /* */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + typedef unsigned char FT_Byte; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_String */ + /* */ + /* */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + typedef char FT_String; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Short */ + /* */ + /* */ + /* A typedef for signed short. */ + /* */ + typedef signed short FT_Short; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UShort */ + /* */ + /* */ + /* A typedef for unsigned short. */ + /* */ + typedef unsigned short FT_UShort; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Int */ + /* */ + /* */ + /* A typedef for the int type. */ + /* */ + typedef int FT_Int; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UInt */ + /* */ + /* */ + /* A typedef for the unsigned int type. */ + /* */ + typedef unsigned int FT_UInt; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Long */ + /* */ + /* */ + /* A typedef for signed long. */ + /* */ + typedef signed long FT_Long; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ULong */ + /* */ + /* */ + /* A typedef for unsigned long. */ + /* */ + typedef unsigned long FT_ULong; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_F2Dot14 */ + /* */ + /* */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + typedef signed short FT_F2Dot14; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_F26Dot6 */ + /* */ + /* */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_F26Dot6; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like scales */ + /* or matrix coefficients. */ + /* */ + typedef signed long FT_Fixed; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Error */ + /* */ + /* */ + /* The FreeType error code type. A value of 0 is always interpreted */ + /* as a successful operation. */ + /* */ + typedef int FT_Error; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pointer */ + /* */ + /* */ + /* A simple typedef for a typeless pointer. */ + /* */ + typedef void* FT_Pointer; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2D vector unit vector. Uses */ + /* FT_F2Dot14 types. */ + /* */ + /* */ + /* x :: Horizontal coordinate. */ + /* */ + /* y :: Vertical coordinate. */ + /* */ + typedef struct FT_UnitVector_ + { + FT_F2Dot14 x; + FT_F2Dot14 y; + + } FT_UnitVector; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix */ + /* */ + /* */ + /* A simple structure used to store a 2x2 matrix. Coefficients are */ + /* in 16.16 fixed float format. The computation performed is: */ + /* */ + /* { */ + /* x' = x*xx + y*xy */ + /* y' = x*yx + y*yy */ + /* } */ + /* */ + /* */ + /* xx :: Matrix coefficient. */ + /* */ + /* xy :: Matrix coefficient. */ + /* */ + /* yx :: Matrix coefficient. */ + /* */ + /* yy :: Matrix coefficient. */ + /* */ + typedef struct FT_Matrix_ + { + FT_Fixed xx, xy; + FT_Fixed yx, yy; + + } FT_Matrix; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_BBox */ + /* */ + /* */ + /* A structure used to hold an outline's bounding box, i.e., the */ + /* coordinates of its extrema in the horizontal and vertical */ + /* directions. */ + /* */ + /* */ + /* xMin :: The horizontal minimum (left-most). */ + /* */ + /* yMin :: The vertical minimum (bottom-most). */ + /* */ + /* xMax :: The horizontal maximum (right-most). */ + /* */ + /* yMax :: The vertical maximum (top-most). */ + /* */ + typedef struct FT_BBox_ + { + FT_Pos xMin, yMin; + FT_Pos xMax, yMax; + + } FT_BBox; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MAKE_TAG */ + /* */ + /* */ + /* This macro converts four letter tags which are used to label */ + /* TrueType tables into an unsigned long to be used within FreeType. */ + /* */ +#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (FT_ULong)_x1 << 24 ) | \ + ( (FT_ULong)_x2 << 16 ) | \ + ( (FT_ULong)_x3 << 8 ) | \ + (FT_ULong)_x4 ) + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* L I S T M A N A G E M E N T */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListNode */ + /* */ + /* */ + /* Many elements and objects in FreeType are listed through a */ + /* FT_List record (see FT_ListRec). As its name suggests, a */ + /* FT_ListNode is a handle to a single list element. */ + /* */ + typedef struct FT_ListNodeRec_* FT_ListNode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List */ + /* */ + /* */ + /* A handle to a list record (see FT_ListRec). */ + /* */ + typedef struct FT_ListRec_* FT_List; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListNodeRec */ + /* */ + /* */ + /* A structure used to hold a single list element. */ + /* */ + /* */ + /* prev :: The previous element in the list. NULL if first. */ + /* */ + /* next :: The next element in the list. NULL if last. */ + /* */ + /* data :: A typeless pointer to the listed object. */ + /* */ + typedef struct FT_ListNodeRec_ + { + FT_ListNode prev; + FT_ListNode next; + void* data; + + } FT_ListNodeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListRec */ + /* */ + /* */ + /* A structure used to hold a simple doubly-linked list. These are */ + /* used in many parts of FreeType. */ + /* */ + /* */ + /* head :: The head (first element) of doubly-linked list. */ + /* */ + /* tail :: The tail (last element) of doubly-linked list. */ + /* */ + typedef struct FT_ListRec_ + { + FT_ListNode head; + FT_ListNode tail; + + } FT_ListRec; + + +#define FT_IS_EMPTY( list ) ( (list).head == 0 ) + + +#endif /* FTTYPES_H */ + + +/* END */ diff --git a/include/freetype/internal/autohint.h b/include/freetype/internal/autohint.h new file mode 100644 index 0000000..5d35a5d --- /dev/null +++ b/include/freetype/internal/autohint.h @@ -0,0 +1,195 @@ +/***************************************************************************/ +/* */ +/* autohint.h */ +/* */ +/* High-level `autohint' module-specific interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The auto-hinter is used to load and automatically hint glyphs if a */ + /* format-specific hinter isn't available. */ + /* */ + /*************************************************************************/ + + +#ifndef AUTOHINT_H +#define AUTOHINT_H + + + /*************************************************************************/ + /* */ + /* A small technical note regarding automatic hinting in order to */ + /* clarify this module interface. */ + /* */ + /* An automatic hinter might compute two kinds of data for a given face: */ + /* */ + /* - global hints: Usually some metrics that describe global properties */ + /* of the face. It is computed by scanning more or less */ + /* agressively the glyphs in the face, and thus can be */ + /* very slow to compute (even if the size of global */ + /* hints is really small). */ + /* */ + /* - glyph hints: These describe some important features of the glyph */ + /* outline, as well as how to align them. They are */ + /* generally much faster to compute than global hints. */ + /* */ + /* The current FreeType auto-hinter does a pretty good job while */ + /* performing fast computations for both global and glyph hints. */ + /* However, we might be interested in introducing more complex and */ + /* powerful algorithms in the future, like the one described in the John */ + /* D. Hobby paper, which unfortunately requires a lot more horsepower. */ + /* */ + /* Because a sufficiently sophisticated font management system would */ + /* typically implement an LRU cache of opened face objects to reduce */ + /* memory usage, it is a good idea to be able to avoid recomputing */ + /* global hints every time the same face is re-opened. */ + /* */ + /* We thus provide the ability to cache global hints outside of the face */ + /* object, in order to speed up font re-opening time. Of course, this */ + /* feature is purely optional, so most client programs won't even notice */ + /* it. */ + /* */ + /* I initially thought that it would be a good idea to cache the glyph */ + /* hints too. However, my general idea now is that if you really need */ + /* to cache these too, you are simply in need of a new font format, */ + /* where all this information could be stored within the font file and */ + /* decoded on the fly. */ + /* */ + /*************************************************************************/ + + +#include + + + typedef struct FT_AutoHinterRec_ *FT_AutoHinter; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Get_Global_Func */ + /* */ + /* */ + /* Retrieves the global hints computed for a given face object the */ + /* resulting data is dissociated from the face and will survive a */ + /* call to FT_Done_Face(). It must be discarded through the API */ + /* FT_AutoHinter_Done_Global_Func(). */ + /* */ + /* */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* global_hints :: A typeless pointer to the global hints. */ + /* */ + /* global_len :: The size in bytes of the global hints. */ + /* */ + typedef void (*FT_AutoHinter_Get_Global_Func)( + FT_AutoHinter hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Done_Global_Func */ + /* */ + /* */ + /* Discards the global hints retrieved through */ + /* FT_AutoHinter_Get_Global_Func(). This is the only way these hints */ + /* are freed from memory. */ + /* */ + /* */ + /* hinter :: A handle to the auto-hinter module. */ + /* */ + /* global :: A pointer to retrieved global hints to discard. */ + /* */ + typedef void (*FT_AutoHinter_Done_Global_Func)( FT_AutoHinter hinter, + void* global ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Reset_Func */ + /* */ + /* */ + /* This function is used to recompute the global metrics in a given */ + /* font. This is useful when global font data changes (e.g. Multiple */ + /* Masters fonts where blend coordinates change). */ + /* */ + /* */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the face. */ + /* */ + typedef void (*FT_AutoHinter_Reset_Func)( FT_AutoHinter hinter, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Load_Func */ + /* */ + /* */ + /* This function is used to load, scale, and automatically hint a */ + /* glyph from a given face. */ + /* */ + /* */ + /* face :: A handle to the face. */ + /* glyph_index :: The glyph index. */ + /* load_flags :: The load flags. */ + /* */ + /* */ + /* This function is capable of loading composite glyphs by hinting */ + /* each sub-glyph independently (which improves quality). */ + /* */ + /* It will call the font driver with FT_Load_Glyph(), with */ + /* FT_LOAD_NO_SCALE set. */ + /* */ + typedef FT_Error (*FT_AutoHinter_Load_Func)( FT_AutoHinter hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_ULong load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Interface */ + /* */ + /* */ + /* The auto-hinter module's interface. */ + /* */ + typedef struct FT_AutoHinter_Interface + { + FT_AutoHinter_Reset_Func reset_face; + FT_AutoHinter_Load_Func load_glyph; + + FT_AutoHinter_Get_Global_Func get_global_hints; + FT_AutoHinter_Done_Global_Func done_global_hints; + + } FT_AutoHinter_Interface; + + +#endif /* AUTOHINT_H */ + + +/* END */ diff --git a/include/freetype/internal/ftcalc.h b/include/freetype/internal/ftcalc.h new file mode 100644 index 0000000..99b6cfa --- /dev/null +++ b/include/freetype/internal/ftcalc.h @@ -0,0 +1,123 @@ +/***************************************************************************/ +/* */ +/* ftcalc.h */ +/* */ +/* Arithmetic computations (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTCALC_H +#define FTCALC_H + +#include +#include /* for LONG64 */ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef LONG64 + + + typedef INT64 FT_Int64; + +#define ADD_64( x, y, z ) z = (x) + (y) +#define MUL_64( x, y, z ) z = (FT_Int64)(x) * (y) + +#define DIV_64( x, y ) ( (x) / (y) ) + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( z ) + + FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64 l ); + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#else /* LONG64 */ + + + typedef struct FT_Int64_ + { + FT_UInt32 lo; + FT_UInt32 hi; + + } FT_Int64; + + +#define ADD_64( x, y, z ) FT_Add64( &x, &y, &z ) +#define MUL_64( x, y, z ) FT_MulTo64( x, y, &z ) +#define DIV_64( x, y ) FT_Div64by32( &x, y ) + + + FT_EXPORT_DEF( void ) FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ); + + FT_EXPORT_DEF( void ) FT_MulTo64( FT_Int32 x, + FT_Int32 y, + FT_Int64* z ); + + FT_EXPORT_DEF( FT_Int32 ) FT_Div64by32( FT_Int64* x, + FT_Int32 y ); + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( &z ) + + FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64* x ); + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#endif /* LONG64 */ + + +#ifndef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_32( x ) FT_Sqrt32( x ) + + BASE_DEF( FT_Int32 ) FT_Sqrt32( FT_Int32 x ); + +#endif /* !FT_CONFIG_OPTION_OLD_CALCS */ + + + /*************************************************************************/ + /* */ + /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) +#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) +#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) +#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) +#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) + +#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ + : ( -( ( 32 - (x) ) & -64 ) ) ) + + +#ifdef __cplusplus + } +#endif + +#endif /* FTCALC_H */ + + +/* END */ diff --git a/include/freetype/internal/ftdebug.h b/include/freetype/internal/ftdebug.h new file mode 100644 index 0000000..8b1e4dd --- /dev/null +++ b/include/freetype/internal/ftdebug.h @@ -0,0 +1,225 @@ +/***************************************************************************/ +/* */ +/* ftdebug.h */ +/* */ +/* Debugging and logging component (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTDEBUG_H +#define FTDEBUG_H + +#include /* for FT_DEBUG_LEVEL_TRACE, */ + /* FT_DEBUG_LEVEL_ERROR */ + +#ifdef __cplusplus + extern "C" { +#endif + + + /* A very stupid pre-processor trick. See K&R version 2 */ + /* section A12.3 for details... */ + /* */ + /* It is also described in the section `Separate */ + /* Expansion of Macro Arguments' in the info file */ + /* `cpp.info', describing GNU cpp. */ + /* */ +#define FT_CAT( x, y ) x ## y +#define FT_XCAT( x, y ) FT_CAT( x, y ) + + +#ifdef FT_DEBUG_LEVEL_TRACE + + + /* note that not all levels are used currently */ + + typedef enum FT_Trace_ + { + /* the first level must always be `trace_any' */ + trace_any = 0, + + /* base components */ + trace_aaraster, /* anti-aliasing raster (ftgrays.c) */ + trace_calc, /* calculations (ftcalc.c) */ + trace_extend, /* extension manager (ftextend.c) */ + trace_glyph, /* glyph manager (ftglyph.c) */ + trace_io, /* i/o monitoring (ftsystem.c) */ + trace_init, /* initialization (ftinit.c) */ + trace_list, /* list manager (ftlist.c) */ + trace_memory, /* memory manager (ftobjs.c) */ + trace_mm, /* MM interface (ftmm.c) */ + trace_objs, /* base objects (ftobjs.c) */ + trace_outline, /* outline management (ftoutln.c) */ + trace_raster, /* rasterizer (ftraster.c) */ + trace_stream, /* stream manager (ftstream.c) */ + + /* SFNT driver components */ + trace_sfobjs, /* SFNT object handler (sfobjs.c) */ + trace_ttcmap, /* charmap handler (ttcmap.c) */ + trace_ttload, /* basic TrueType tables (ttload.c) */ + trace_ttpost, /* PS table processing (ttpost.c) */ + trace_ttsbit, /* TrueType sbit handling (ttsbit.c) */ + + /* TrueType driver components */ + trace_ttdriver, /* TT font driver (ttdriver.c) */ + trace_ttgload, /* TT glyph loader (ttgload.c) */ + trace_ttinterp, /* bytecode interpreter (ttinterp.c) */ + trace_ttobjs, /* TT objects manager (ttobjs.c) */ + trace_ttpload, /* TT data/program loader (ttpload.c) */ + + /* Type 1 driver components */ + trace_t1driver, + trace_t1gload, + trace_t1hint, + trace_t1load, + trace_t1objs, + + /* experimental Type 1 driver components */ + trace_z1driver, + trace_z1gload, + trace_z1hint, + trace_z1load, + trace_z1objs, + trace_z1parse, + + /* Type 2 driver components */ + trace_t2driver, + trace_t2gload, + trace_t2load, + trace_t2objs, + trace_t2parse, + + /* CID driver components */ + trace_cidafm, + trace_ciddriver, + trace_cidgload, + trace_cidload, + trace_cidobjs, + trace_cidparse, + + /* Windows fonts component */ + trace_winfnt, + + /* the last level must always be `trace_max' */ + trace_max + + } FT_Trace; + + + /* declared in ftdebug.c */ + extern char ft_trace_levels[trace_max]; + + + /*************************************************************************/ + /* */ + /* IMPORTANT! */ + /* */ + /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */ + /* value before using any TRACE macro. */ + /* */ + /*************************************************************************/ + + +#define FT_TRACE( level, varformat ) \ + do \ + { \ + if ( ft_trace_levels[FT_COMPONENT] >= level ) \ + FT_XCAT( FT_Message, varformat ); \ + } while ( 0 ) + + + FT_EXPORT_DEF( void ) FT_SetTraceLevel( FT_Trace component, + char level ); + + +#elif defined( FT_DEBUG_LEVEL_ERROR ) + + +#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */ + + +#else /* release mode */ + + +#define FT_Assert( condition ) do ; while ( 0 ) /* nothing */ + +#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */ +#define FT_ERROR( varformat ) do ; while ( 0 ) /* nothing */ + + +#endif /* FT_DEBUG_LEVEL_TRACE, FT_DEBUG_LEVEL_ERROR */ + + + /*************************************************************************/ + /* */ + /* Define macros and functions that are common to the debug and trace */ + /* modes. */ + /* */ + /* You need vprintf() to be able to compile ftdebug.c. */ + /* */ + /*************************************************************************/ + + +#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_DEBUG_LEVEL_ERROR ) + + +#include "stdio.h" /* for vprintf() */ + + +#define FT_Assert( condition ) \ + do \ + { \ + if ( !( condition ) ) \ + FT_Panic( "assertion failed on line %d of file %s\n", \ + __LINE__, __FILE__ ); \ + } while ( 0 ) + + /* print a message */ + FT_EXPORT_DEF( void ) FT_Message( const char* fmt, ... ); + + /* print a message and exit */ + FT_EXPORT_DEF( void ) FT_Panic( const char* fmt, ... ); + +#define FT_ERROR( varformat ) FT_XCAT( FT_Message, varformat ) + + +#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */ + + + /*************************************************************************/ + /* */ + /* You need two opening resp. closing parentheses! */ + /* */ + /* Example: FT_TRACE0(( "Value is %i", foo )) */ + /* */ + /*************************************************************************/ + +#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat ) +#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat ) +#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat ) +#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat ) +#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat ) +#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat ) +#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat ) +#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTDEBUG_H */ + + +/* END */ diff --git a/include/freetype/internal/ftdriver.h b/include/freetype/internal/ftdriver.h new file mode 100644 index 0000000..592de49 --- /dev/null +++ b/include/freetype/internal/ftdriver.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftdriver.h */ +/* */ +/* FreeType font driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTDRIVER_H +#define FTDRIVER_H + + +#include +#include + + + typedef FT_Error (*FTDriver_initFace)( FT_Stream stream, + FT_Face face, + FT_Int typeface_index, + FT_Int num_params, + FT_Parameter* parameters ); + + typedef void (*FTDriver_doneFace)( FT_Face face ); + + + typedef FT_Error (*FTDriver_initSize)( FT_Size size ); + + typedef void (*FTDriver_doneSize)( FT_Size size ); + + + typedef FT_Error (*FTDriver_initGlyphSlot)( FT_GlyphSlot slot ); + + typedef void (*FTDriver_doneGlyphSlot)( FT_GlyphSlot slot ); + + + typedef FT_Error (*FTDriver_setCharSizes)( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + typedef FT_Error (*FTDriver_setPixelSizes)( FT_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + typedef FT_Error (*FTDriver_loadGlyph)( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ); + + + typedef FT_UInt (*FTDriver_getCharIndex)( FT_CharMap charmap, + FT_Long charcode ); + + typedef FT_Error (*FTDriver_getKerning)( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ); + + + typedef FT_Error (*FTDriver_attachFile)( FT_Face face, + FT_Stream stream ); + + + typedef FT_Error (*FTDriver_getAdvances)( FT_Face face, + FT_UInt first, + FT_UInt count, + FT_Bool vertical, + FT_UShort* advances ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Driver_Class */ + /* */ + /* */ + /* The font driver class. This structure mostly contains pointers to */ + /* driver methods. */ + /* */ + /* */ + /* root :: The parent module. */ + /* */ + /* face_object_size :: The size of a face object in bytes. */ + /* */ + /* size_object_size :: The size of a size object in bytes. */ + /* */ + /* slot_object_size :: The size of a glyph object in bytes. */ + /* */ + /* init_face :: The format-specific face constructor. */ + /* */ + /* done_face :: The format-specific face destructor. */ + /* */ + /* init_size :: The format-specific size constructor. */ + /* */ + /* done_size :: The format-specific size destructor. */ + /* */ + /* init_slot :: The format-specific slot constructor. */ + /* */ + /* done_slot :: The format-specific slot destructor. */ + /* */ + /* set_char_sizes :: A handle to a function used to set the new */ + /* character size in points + resolution. Can be */ + /* set to 0 to indicate default behaviour. */ + /* */ + /* set_pixel_sizes :: A handle to a function used to set the new */ + /* character size in pixels. Can be set to 0 to */ + /* indicate default behaviour. */ + /* */ + /* load_glyph :: A function handle to load a given glyph image */ + /* in a slot. This field is mandatory! */ + /* */ + /* get_char_index :: A function handle to return the glyph index of */ + /* a given character for a given charmap. This */ + /* field is mandatory! */ + /* */ + /* get_kerning :: A function handle to return the unscaled */ + /* kerning for a given pair of glyphs. Can be */ + /* set to 0 if the format doesn't support */ + /* kerning. */ + /* */ + /* attach_file :: This function handle is used to read */ + /* additional data for a face from another */ + /* file/stream. For example, this can be used to */ + /* add data from AFM or PFM files on a Type 1 */ + /* face, or a CIDMap on a CID-keyed face. */ + /* */ + /* get_advances :: A function handle used to return the advances */ + /* of 'count' glyphs, starting at `index'. the */ + /* `vertical' flags must be set when vertical */ + /* advances are queried. The advances buffer is */ + /* caller-allocated. */ + /* */ + /* */ + /* Most function pointers, with the exception of `load_glyph' and */ + /* `get_char_index' can be set to 0 to indicate a default behaviour. */ + /* */ + typedef struct FT_Driver_Class_ + { + FT_Module_Class root; + + FT_Int face_object_size; + FT_Int size_object_size; + FT_Int slot_object_size; + + FTDriver_initFace init_face; + FTDriver_doneFace done_face; + + FTDriver_initSize init_size; + FTDriver_doneSize done_size; + + FTDriver_initGlyphSlot init_slot; + FTDriver_doneGlyphSlot done_slot; + + FTDriver_setCharSizes set_char_sizes; + FTDriver_setPixelSizes set_pixel_sizes; + + FTDriver_loadGlyph load_glyph; + FTDriver_getCharIndex get_char_index; + + FTDriver_getKerning get_kerning; + FTDriver_attachFile attach_file; + + FTDriver_getAdvances get_advances; + + } FT_Driver_Class; + + +#endif /* FTDRIVER_H */ + + +/* END */ diff --git a/include/freetype/internal/ftextend.h b/include/freetype/internal/ftextend.h new file mode 100644 index 0000000..fdd2c6e --- /dev/null +++ b/include/freetype/internal/ftextend.h @@ -0,0 +1,178 @@ +/***************************************************************************/ +/* */ +/* ftextend.h */ +/* */ +/* FreeType extensions implementation (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTEXTEND_H +#define FTEXTEND_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* The extensions don't need to be integrated at compile time into the */ + /* engine, only at link time. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Initializer */ + /* */ + /* */ + /* Each new face object can have several extensions associated with */ + /* it at creation time. This function is used to initialize given */ + /* extension data for a given face. */ + /* */ + /* */ + /* ext :: A typeless pointer to the extension data. */ + /* */ + /* face :: A handle to the source face object the extension is */ + /* associated with. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* In case of error, the initializer should not destroy the extension */ + /* data, as the finalizer will get called later by the function's */ + /* caller. */ + /* */ + typedef FT_Error (*FT_Extension_Initializer)( void* ext, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Finalizer */ + /* */ + /* */ + /* Each new face object can have several extensions associated with */ + /* it at creation time. This function is used to finalize given */ + /* extension data for a given face; it occurs before the face object */ + /* itself is finalized. */ + /* */ + /* */ + /* ext :: A typeless pointer to the extension data. */ + /* */ + /* face :: A handle to the source face object the extension is */ + /* associated with. */ + /* */ + typedef void (*FT_Extension_Finalizer)( void* ext, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Class */ + /* */ + /* */ + /* A simple structure used to describe a given extension to the */ + /* FreeType base layer. An FT_Extension_Class is used as a parameter */ + /* for FT_Register_Extension(). */ + /* */ + /* */ + /* id :: The extension's ID. This is a normal C string that */ + /* is used to uniquely reference the extension's */ + /* interface. */ + /* */ + /* size :: The size in bytes of the extension data that must be */ + /* associated with each face object. */ + /* */ + /* init :: A pointer to the extension data's initializer. */ + /* */ + /* finalize :: A pointer to the extension data's finalizer. */ + /* */ + /* interface :: This pointer can be anything, but should usually */ + /* point to a table of function pointers which implement */ + /* the extension's interface. */ + /* */ + /* offset :: This field is set and used within the base layer and */ + /* should be set to 0 when registering an extension */ + /* through FT_Register_Extension(). It contains an */ + /* offset within the face's extension block for the */ + /* current extension's data. */ + /* */ + typedef struct FT_Extension_Class_ + { + const char* id; + FT_ULong size; + FT_Extension_Initializer init; + FT_Extension_Finalizer finalize; + void* interface; + + FT_ULong offset; + + } FT_Extension_Class; + + + FT_EXPORT_DEF( FT_Error ) FT_Register_Extension( + FT_Driver driver, + FT_Extension_Class* clazz ); + + +#ifdef FT_CONFIG_OPTION_EXTEND_ENGINE + + + /* Initialize the extension component */ + LOCAL_DEF + FT_Error FT_Init_Extensions( FT_Library library ); + + /* Finalize the extension component */ + LOCAL_DEF + FT_Error FT_Done_Extensions( FT_Library library ); + + /* Create an extension within a face object. Called by the */ + /* face object constructor. */ + LOCAL_DEF + FT_Error FT_Create_Extensions( FT_Face face ); + + /* Destroy all extensions within a face object. Called by the */ + /* face object destructor. */ + LOCAL_DEF + FT_Error FT_Destroy_Extensions( FT_Face face ); + + +#endif + + + /* return an extension's data & interface according to its ID */ + FT_EXPORT_DEF( void* ) FT_Get_Extension( + FT_Face face, + const char* extension_id, + void** extension_interface ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTEXTEND_H */ + + +/* END */ diff --git a/include/freetype/internal/ftlist.h b/include/freetype/internal/ftlist.h new file mode 100644 index 0000000..7c6d8ed --- /dev/null +++ b/include/freetype/internal/ftlist.h @@ -0,0 +1,113 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file implements functions relative to list processing. Its */ + /* data structures are defined in `freetype.h'. */ + /* */ + /*************************************************************************/ + + +#ifndef FTLIST_H +#define FTLIST_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + FT_EXPORT_DEF( FT_ListNode ) FT_List_Find( FT_List list, + void* data ); + + FT_EXPORT_DEF( void ) FT_List_Add( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Insert( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Remove( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Up( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Iterator */ + /* */ + /* */ + /* An FT_List iterator function which is called during a list parse */ + /* by FT_List_Iterate(). */ + /* */ + /* */ + /* node :: The current iteration list node. */ + /* */ + /* user :: A typeless pointer passed to FT_List_Iterate(). */ + /* Can be used to point to the iteration's state. */ + /* */ + typedef FT_Error (*FT_List_Iterator)( FT_ListNode node, + void* user ); + + + FT_EXPORT_DEF( FT_Error ) FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Destructor */ + /* */ + /* */ + /* An FT_List iterator function which is called during a list */ + /* finalization by FT_List_Finalize() to destroy all elements in a */ + /* given list. */ + /* */ + /* */ + /* system :: The current system object. */ + /* */ + /* data :: The current object to destroy. */ + /* */ + /* user :: A typeless pointer passed to FT_List_Iterate(). It can */ + /* be used to point to the iteration's state. */ + /* */ + typedef void (*FT_List_Destructor)( FT_Memory memory, + void* data, + void* user ); + + + FT_EXPORT_DEF( void ) FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTLIST_H */ + + +/* END */ diff --git a/include/freetype/internal/ftmemory.h b/include/freetype/internal/ftmemory.h new file mode 100644 index 0000000..da8d3a4 --- /dev/null +++ b/include/freetype/internal/ftmemory.h @@ -0,0 +1,127 @@ +/***************************************************************************/ +/* */ +/* ftmemory.h */ +/* */ +/* The FreeType memory management macros (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTMEMORY_H +#define FTMEMORY_H + + +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SET_ERROR */ + /* */ + /* */ + /* This macro is used to set an implicit `error' variable to a given */ + /* expression's value (usually a function call), and convert it to a */ + /* boolean which is set whenever the value is != 0. */ + /* */ +#undef FT_SET_ERROR +#define FT_SET_ERROR( expression ) \ + ( ( error = (expression) ) != 0 ) + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M E M O R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + BASE_DEF( FT_Error ) FT_Alloc( FT_Memory memory, + FT_Long size, + void** P ); + + BASE_DEF( FT_Error ) FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ); + + BASE_DEF( void ) FT_Free( FT_Memory memory, + void** P ); + + + + /* This `#include' is needed by the MEM_xxx() macros; it should be */ + /* available on all platforms we know of. */ +#include + +#define MEM_Set( dest, byte, count ) memset( dest, byte, count ) + +#define MEM_Copy( dest, source, count ) memcpy( dest, source, count ) + +#define MEM_Move( dest, source, count ) memmove( dest, source, count ) + + + /*************************************************************************/ + /* */ + /* We now support closures to produce completely reentrant code. This */ + /* means the allocation functions now takes an additional argument */ + /* (`memory'). It is a handle to a given memory object, responsible for */ + /* all low-level operations, including memory management and */ + /* synchronisation. */ + /* */ + /* In order to keep our code readable and use the same macros in the */ + /* font drivers and the rest of the library, MEM_Alloc(), ALLOC(), and */ + /* ALLOC_ARRAY() now use an implicit variable, `memory'. It must be */ + /* defined at all locations where a memory operation is queried. */ + /* */ +#define MEM_Alloc( _pointer_, _size_ ) \ + FT_Alloc( memory, _size_, (void**)&(_pointer_) ) + +#define MEM_Alloc_Array( _pointer_, _count_, _type_ ) \ + FT_Alloc( memory, (_count_)*sizeof ( _type_ ), \ + (void**)&(_pointer_) ) + +#define MEM_Realloc( _pointer_, _current_, _size_ ) \ + FT_Realloc( memory, _current_, _size_, (void**)&(_pointer_) ) + +#define MEM_Realloc_Array( _pointer_, _current_, _new_, _type_ ) \ + FT_Realloc( memory, (_current_)*sizeof ( _type_ ), \ + (_new_)*sizeof ( _type_ ), (void**)&(_pointer_) ) + +#define ALLOC( _pointer_, _size_ ) \ + FT_SET_ERROR( MEM_Alloc( _pointer_, _size_ ) ) + +#define REALLOC( _pointer_, _current_, _size_ ) \ + FT_SET_ERROR( MEM_Realloc( _pointer_, _current_, _size_ ) ) + +#define ALLOC_ARRAY( _pointer_, _count_, _type_ ) \ + FT_SET_ERROR( MEM_Alloc( _pointer_, \ + (_count_)*sizeof ( _type_ ) ) ) + +#define REALLOC_ARRAY( _pointer_, _current_, _count_, _type_ ) \ + FT_SET_ERROR( MEM_Realloc( _pointer_, \ + (_current_)*sizeof ( _type_ ), \ + (_count_)*sizeof ( _type_ ) ) ) + +#define FREE( _pointer_ ) FT_Free( memory, (void**)&(_pointer_) ) + + +#endif /* FTMEMORY_H */ + + +/* END */ diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h new file mode 100644 index 0000000..0d0f5d8 --- /dev/null +++ b/include/freetype/internal/ftobjs.h @@ -0,0 +1,532 @@ +/***************************************************************************/ +/* */ +/* ftobjs.h */ +/* */ +/* The FreeType private base classes (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of all internal FreeType classes. */ + /* */ + /*************************************************************************/ + + +#ifndef FTOBJS_H +#define FTOBJS_H + +#include +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* Some generic definitions. */ + /* */ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + +#ifndef UNUSED +#define UNUSED( arg ) ( (arg)=(arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* The min and max functions missing in C. As usual, be careful not to */ + /* write things like MIN( a++, b++ ) to avoid side effects. */ + /* */ +#ifndef MIN +#define MIN( a, b ) ( (a) < (b) ? (a) : (b) ) +#endif + +#ifndef MAX +#define MAX( a, b ) ( (a) > (b) ? (a) : (b) ) +#endif + +#ifndef ABS +#define ABS( a ) ( (a) < 0 ? -(a) : (a) ) +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M O D U L E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ModuleRec */ + /* */ + /* */ + /* A module object instance. */ + /* */ + /* */ + /* clazz :: A pointer to the module's class. */ + /* */ + /* library :: A handle to the parent library object. */ + /* */ + /* memory :: A handle to the memory manager. */ + /* */ + /* generic :: A generic structure for user-level extensibility (?). */ + /* */ + typedef struct FT_ModuleRec_ + { + FT_Module_Class* clazz; + FT_Library library; + FT_Memory memory; + FT_Generic generic; + + } FT_ModuleRec; + + + /* typecast an object to a FT_Module */ +#define FT_MODULE( x ) ((FT_Module)(x)) +#define FT_MODULE_CLASS( x ) FT_MODULE(x)->clazz +#define FT_MODULE_LIBRARY( x ) FT_MODULE(x)->library +#define FT_MODULE_MEMORY( x ) FT_MODULE(x)->memory + +#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_font_driver ) + +#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_renderer ) + +#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_hinter ) + +#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_styler ) + +#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS(x)->module_flags & \ + ft_module_driver_scalable ) + +#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS(x)->module_flags & \ + ft_module_driver_no_outlines ) + +#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS(x)->module_flags & \ + ft_module_driver_has_hinter ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module_Interface */ + /* */ + /* */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + BASE_DEF( const void* ) FT_Get_Module_Interface( FT_Library library, + const char* mod_name ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* a few macros used to perform easy typecasts with minimal brain damage */ + +#define FT_FACE( x ) ((FT_Face)(x)) +#define FT_SIZE( x ) ((FT_Size)(x)) +#define FT_SLOT( x ) ((FT_GlyphSlot)(x)) + +#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver +#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library +#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory + +#define FT_SIZE_FACE( x ) FT_SIZE( x )->face +#define FT_SLOT_FACE( x ) FT_SLOT( x )->face + +#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph +#define FT_FACE_SIZE( x ) FT_FACE( x )->size + + + /* this must be kept exported -- tt will be used later in our own */ + /* high-level caching font manager called SemTex (way after the */ + /* 2.0 release though */ + FT_EXPORT_DEF( FT_Error ) FT_New_Size( FT_Face face, + FT_Size* size ); + + FT_EXPORT_DEF( FT_Error ) FT_Done_Size( FT_Size size ); + + + FT_EXPORT_DEF( FT_Error ) FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ); + + FT_EXPORT_DEF( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** G L Y P H L O A D E R ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 +#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 +#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 +#define FT_SUBGLYPH_FLAG_SCALE 8 +#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 +#define FT_SUBGLYPH_FLAG_2X2 0x80 +#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 + + + enum + { + ft_glyph_own_bitmap = 1 + }; + + + struct FT_SubGlyph_ + { + FT_Int index; + FT_UShort flags; + FT_Int arg1; + FT_Int arg2; + FT_Matrix transform; + }; + + + typedef struct FT_GlyphLoad_ + { + FT_Outline outline; /* outline */ + FT_UInt num_subglyphs; /* number of subglyphs */ + FT_SubGlyph* subglyphs; /* subglyphs */ + FT_Vector* extra_points; /* extra points table */ + + } FT_GlyphLoad; + + + struct FT_GlyphLoader_ + { + FT_Memory memory; + FT_UInt max_points; + FT_UInt max_contours; + FT_UInt max_subglyphs; + FT_Bool use_extra; + + FT_GlyphLoad base; + FT_GlyphLoad current; + + void* other; /* for possible future extension? */ + + }; + + + BASE_DEF( FT_Error ) FT_GlyphLoader_New( FT_Memory memory, + FT_GlyphLoader** aloader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Create_Extra( + FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Points( + FT_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Subglyphs( + FT_GlyphLoader* loader, + FT_UInt n_subs ); + + BASE_DEF( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target, + FT_GlyphLoader* source ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_RENDERER( x ) ((FT_Renderer)( x )) +#define FT_GLYPH( x ) ((FT_Glyph)( x )) +#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x )) +#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x )) + + + typedef struct FT_RendererRec_ + { + FT_ModuleRec root; + FT_Renderer_Class* clazz; + FT_Glyph_Format glyph_format; + const FT_Glyph_Class glyph_class; + + FT_Raster raster; + FT_Raster_Render_Func raster_render; + FTRenderer_render render; + + } FT_RendererRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F O N T D R I V E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* typecast a module into a driver easily */ +#define FT_DRIVER( x ) ((FT_Driver)(x)) + + /* typecast a module as a driver, and get its driver class */ +#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DriverRec */ + /* */ + /* */ + /* The root font driver class. A font driver is responsible for */ + /* managing and loading font files of a given format. */ + /* */ + /* */ + /* root :: Contains the fields of the root module class. */ + /* */ + /* clazz :: A pointer to the font driver's class. Note that */ + /* this is NOT root.clazz. `class' wasn't used */ + /* as it is a reserved word in C++. */ + /* */ + /* faces_list :: The list of faces currently opened by this */ + /* driver. */ + /* */ + /* extensions :: A typeless pointer to the driver's extensions */ + /* registry, if they are supported through the */ + /* configuration macro FT_CONFIG_OPTION_EXTENSIONS. */ + /* */ + /* glyph_loader :: The glyph loader for all faces managed by this */ + /* driver. This object isn't defined for unscalable */ + /* formats. */ + /* */ + typedef struct FT_DriverRec_ + { + FT_ModuleRec root; + FT_Driver_Class* clazz; + + FT_ListRec faces_list; + void* extensions; + + FT_GlyphLoader* glyph_loader; + + } FT_DriverRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** L I B R A R I E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_DEBUG_HOOK_TRUETYPE 0 +#define FT_DEBUG_HOOK_TYPE1 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LibraryRec */ + /* */ + /* */ + /* The FreeType library class. This is the root of all FreeType */ + /* data. Use FT_New_Library() to create a library object, and */ + /* FT_Done_Library() to discard it and all child objects. */ + /* */ + /* */ + /* memory :: The library's memory object. Manages memory */ + /* allocation. */ + /* */ + /* generic :: Client data variable. Used to extend the */ + /* Library class by higher levels and clients. */ + /* */ + /* num_modules :: The number of modules currently registered */ + /* within this library. This is set to 0 for new */ + /* libraries. New modules are added through the */ + /* FT_Add_Module() API function. */ + /* */ + /* modules :: A table used to store handles to the currently */ + /* registered modules. Note that each font driver */ + /* contains a list of its opened faces. */ + /* */ + /* renderers :: The list of renderers currently registered */ + /* within the library. */ + /* */ + /* cur_renderer :: The current outline renderer. This is a */ + /* shortcut used to avoid parsing the list on */ + /* each call to FT_Outline_Render(). It is a */ + /* handle to the current renderer for the */ + /* ft_glyph_format_outline format. */ + /* */ + /* auto_hinter :: XXX */ + /* */ + /* raster_pool :: The raster object's render pool. This can */ + /* ideally be changed dynamically at run-time. */ + /* */ + /* raster_pool_size :: The size of the render pool in bytes. */ + /* */ + /* debug_hooks :: XXX */ + /* */ + typedef struct FT_LibraryRec_ + { + FT_Memory memory; /* library's memory manager */ + + FT_Generic generic; + + FT_UInt num_modules; + FT_Module modules[FT_MAX_MODULES]; /* module objects */ + + FT_ListRec renderers; /* list of renderers */ + FT_Renderer cur_renderer; /* current outline renderer */ + FT_Module auto_hinter; + + FT_Byte* raster_pool; /* scan-line conversion */ + /* render pool */ + FT_ULong raster_pool_size; /* size of render pool in bytes */ + + FT_DebugHook_Func debug_hooks[4]; + + } FT_LibraryRec; + + + BASE_DEF( FT_Renderer ) FT_Lookup_Renderer( FT_Library library, + FT_Glyph_Format format, + FT_ListNode* node ); + + BASE_DEF( FT_Error ) FT_Render_Glyph_Internal( FT_Library library, + FT_GlyphSlot slot, + FT_UInt render_mode ); + + typedef FT_Error (*FT_Glyph_Name_Requester)( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + +#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + FT_EXPORT_DEF( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream astream ); + + FT_EXPORT_DEF( void ) FT_Done_Stream( FT_Stream stream ); + + FT_EXPORT_DEF( FT_Memory ) FT_New_Memory( void ); + + +#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ + + + /* Define default raster's interface. The default raster is located in */ + /* `src/base/ftraster.c' */ + /* */ + /* Client applications can register new rasters through the */ + /* FT_Set_Raster() API. */ + +#ifndef FT_NO_DEFAULT_RASTER + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster; +#endif + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTOBJS_H */ + + +/* END */ diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h new file mode 100644 index 0000000..365f479 --- /dev/null +++ b/include/freetype/internal/ftstream.h @@ -0,0 +1,361 @@ +/***************************************************************************/ +/* */ +/* ftstream.h */ +/* */ +/* Stream handling(specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTSTREAM_H +#define FTSTREAM_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* format of an 8-bit frame_op value = [ xxxxx | e | s ] */ + /* s is set to 1 if the value is signed, */ + /* e is set to 1 if the value is little-endian */ + /* xxxxx is a command */ + +#define FT_FRAME_OP_SHIFT 2 +#define FT_FRAME_OP_SIGNED 1 +#define FT_FRAME_OP_LITTLE 2 +#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT ) + +#define FT_MAKE_FRAME_OP( command, little, sign ) \ + ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign ) + +#define FT_FRAME_OP_END 0 +#define FT_FRAME_OP_START 1 /* start a new frame */ +#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */ +#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */ +#define FT_FRAME_OP_LONG 4 /* read 4-byte value */ +#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */ +#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */ + + + typedef enum FT_Frame_Op_ + { + ft_frame_end = 0, + ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ), + + ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ), + ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ), + + ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ), + ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ), + ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ), + ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ), + + ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ), + ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ), + ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ), + ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ), + + ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ), + ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ), + ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ), + ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ), + + ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ), + ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 ) + + } FT_Frame_Op; + + + typedef struct FT_Frame_Field_ + { + FT_Frame_Op value; + char size; + FT_UShort offset; + + } FT_Frame_Field; + + + /* make-up a FT_Frame_Field out of a structure type and a field name */ +#define FT_FIELD_REF( s, f ) (((s*)0)->f) + +#define FT_FRAME_FIELD( frame_op, struct_type, field ) \ + { \ + frame_op, \ + sizeof ( FT_FIELD_REF( struct_type,field ) ), \ + (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \ + } + +#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 } + +#define FT_FRAME_START( s ) { ft_frame_start, 0, s } +#define FT_FRAME_END { ft_frame_end, 0, 0 } + +#define FT_FRAME_LONG( s, f ) FT_FRAME_FIELD( ft_frame_long_be, s, f ) +#define FT_FRAME_ULONG( s, f ) FT_FRAME_FIELD( ft_frame_ulong_be, s, f ) +#define FT_FRAME_SHORT( s, f ) FT_FRAME_FIELD( ft_frame_short_be, s, f ) +#define FT_FRAME_USHORT( s, f ) FT_FRAME_FIELD( ft_frame_ushort_be, s, f ) +#define FT_FRAME_BYTE( s, f ) FT_FRAME_FIELD( ft_frame_byte, s, f ) +#define FT_FRAME_CHAR( s, f ) FT_FRAME_FIELD( ft_frame_schar, s, f ) + +#define FT_FRAME_LONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_long_le, s, f ) +#define FT_FRAME_ULONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_ulong_le, s, f ) +#define FT_FRAME_SHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_short_le, s, f ) +#define FT_FRAME_USHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_ushort_le, s, f ) + +#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 } +#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 } +#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 } + +#define FT_FRAME_BYTES( struct_type, field, count ) \ + { \ + ft_frame_bytes, \ + count, \ + (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \ + } +#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 } + + + + /*************************************************************************/ + /* */ + /* integer extraction macros -- the `buffer' parameter must ALWAYS be of */ + /* type `char*' or equivalent (1-byte elements). */ + /* */ +#define NEXT_Char( buffer ) \ + ( (signed char)*buffer++ ) +#define NEXT_Byte( buffer ) \ + ( (unsigned char)*buffer++ ) + +#define NEXT_Short( buffer ) \ + ( buffer += 2, \ + ( (short)( (signed char)buffer[-2] << 8 ) | \ + (unsigned char)buffer[-1] ) ) + +#define NEXT_UShort( buffer ) \ + ( (unsigned short)NEXT_Short( buffer ) ) + +#define NEXT_Offset( buffer ) \ + ( buffer += 3, \ + ( ( (long)(signed char)buffer[-3] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-1] ) ) + +#define NEXT_UOffset( buffer ) \ + ( (unsigned long)NEXT_Offset( buffer ) ) + +#define NEXT_Long( buffer ) \ + ( buffer += 4, \ + ( ( (long)(signed char)buffer[-4] << 24 ) | \ + ( (long)(unsigned char)buffer[-3] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-1] ) ) + +#define NEXT_ULong( buffer ) \ + ( (unsigned long)NEXT_Long( buffer ) ) + + +#define NEXT_ShortLE( buffer ) \ + ( buffer += 2, \ + ( (short)( (signed char)buffer[-1] << 8 ) | \ + (unsigned char)buffer[-2] ) ) + +#define NEXT_UShortLE( buffer ) \ + ( (unsigned short)NEXT_ShortLE( buffer ) ) + +#define NEXT_OffsetLE( buffer ) \ + ( buffer += 3, \ + ( ( (long)(signed char)buffer[-1] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-3] ) ) + +#define NEXT_UOffsetLE( buffer ) \ + ( (unsigned long)NEXT_OffsetLE( buffer ) ) + + +#define NEXT_LongLE( buffer ) \ + ( buffer += 4, \ + ( ( (long)(signed char)buffer[-1] << 24 ) | \ + ( (long)(unsigned char)buffer[-2] << 16 ) | \ + ( (long)(unsigned char)buffer[-3] << 8 ) | \ + (long)(unsigned char)buffer[-4] ) ) + +#define NEXT_ULongLE( buffer ) \ + ( (unsigned long)NEXT_LongLE( buffer ) ) + + + /*************************************************************************/ + /* */ + /* Each GET_xxxx() macro uses an implicit `stream' variable. */ + /* */ +#define FT_GET_MACRO( func, type ) ( (type)func( stream ) ) + +#define GET_Char() FT_GET_MACRO( FT_Get_Char, FT_Char ) +#define GET_Byte() FT_GET_MACRO( FT_Get_Char, FT_Byte ) +#define GET_Short() FT_GET_MACRO( FT_Get_Short, FT_Short ) +#define GET_UShort() FT_GET_MACRO( FT_Get_Short, FT_UShort ) +#define GET_Offset() FT_GET_MACRO( FT_Get_Offset, FT_Long ) +#define GET_UOffset() FT_GET_MACRO( FT_Get_Offset, FT_ULong ) +#define GET_Long() FT_GET_MACRO( FT_Get_Long, FT_Long ) +#define GET_ULong() FT_GET_MACRO( FT_Get_Long, FT_ULong ) +#define GET_Tag4() FT_GET_MACRO( FT_Get_Long, FT_ULong ) + +#define GET_ShortLE() FT_GET_MACRO( FT_Get_ShortLE, FT_Short ) +#define GET_UShortLE() FT_GET_MACRO( FT_Get_ShortLE, FT_UShort ) +#define GET_LongLE() FT_GET_MACRO( FT_Get_LongLE, FT_Short ) +#define GET_ULongLE() FT_GET_MACRO( FT_Get_LongLE, FT_Short ) + +#define FT_READ_MACRO( func, type, var ) \ + ( var = (type)func( stream, &error ), \ + error != FT_Err_Ok ) + +#define READ_Byte( var ) FT_READ_MACRO( FT_Read_Char, FT_Byte, var ) +#define READ_Char( var ) FT_READ_MACRO( FT_Read_Char, FT_Char, var ) +#define READ_Short( var ) FT_READ_MACRO( FT_Read_Short, FT_Short, var ) +#define READ_UShort( var ) FT_READ_MACRO( FT_Read_Short, FT_UShort, var ) +#define READ_Offset( var ) FT_READ_MACRO( FT_Read_Offset, FT_Long, var ) +#define READ_UOffset( var ) FT_READ_MACRO( FT_Read_Offset, FT_ULong, var ) +#define READ_Long( var ) FT_READ_MACRO( FT_Read_Long, FT_Long, var ) +#define READ_ULong( var ) FT_READ_MACRO( FT_Read_Long, FT_ULong, var ) + +#define READ_ShortLE( var ) FT_READ_MACRO( FT_Read_ShortLE, FT_Short, var ) +#define READ_UShortLE( var ) FT_READ_MACRO( FT_Read_ShortLE, FT_UShort, var ) +#define READ_LongLE( var ) FT_READ_MACRO( FT_Read_LongLE, FT_Long, var ) +#define READ_ULongLE( var ) FT_READ_MACRO( FT_Read_LongLE, FT_ULong, var ) + + + BASE_DEF( void ) FT_New_Memory_Stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream stream ); + + BASE_DEF( FT_Error ) FT_Seek_Stream( FT_Stream stream, + FT_ULong pos ); + + BASE_DEF( FT_Error ) FT_Skip_Stream( FT_Stream stream, + FT_Long distance ); + + BASE_DEF( FT_Long ) FT_Stream_Pos( FT_Stream stream ); + + + BASE_DEF( FT_Error ) FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ); + + BASE_DEF( FT_Error ) FT_Read_Stream_At( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ); + + BASE_DEF( FT_Error ) FT_Access_Frame( FT_Stream stream, + FT_ULong count ); + + BASE_DEF( void ) FT_Forget_Frame( FT_Stream stream ); + + BASE_DEF( FT_Error ) FT_Extract_Frame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ); + + BASE_DEF( void ) FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ); + + BASE_DEF( FT_Char ) FT_Get_Char( FT_Stream stream ); + + BASE_DEF( FT_Short ) FT_Get_Short( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_Offset( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_Long( FT_Stream stream ); + + BASE_DEF( FT_Short ) FT_Get_ShortLE( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_LongLE( FT_Stream stream ); + + + BASE_DEF( FT_Char ) FT_Read_Char( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Short ) FT_Read_Short( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_Offset( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_Long( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Short ) FT_Read_ShortLE( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_LongLE( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Error ) FT_Read_Fields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ); + + +#define USE_Stream( resource, stream ) \ + FT_SET_ERROR( FT_Open_Stream( resource, stream ) ) + +#define DONE_Stream( stream ) \ + FT_Done_Stream( stream ) + + +#define ACCESS_Frame( size ) \ + FT_SET_ERROR( FT_Access_Frame( stream, size ) ) + +#define FORGET_Frame() \ + FT_Forget_Frame( stream ) + +#define EXTRACT_Frame( size, bytes ) \ + FT_SET_ERROR( FT_Extract_Frame( stream, size, \ + (FT_Byte**)&(bytes) ) ) + +#define RELEASE_Frame( bytes ) \ + FT_Release_Frame( stream, (FT_Byte**)&(bytes) ) + +#define FILE_Seek( position ) \ + FT_SET_ERROR( FT_Seek_Stream( stream, position ) ) + +#define FILE_Skip( distance ) \ + FT_SET_ERROR( FT_Skip_Stream( stream, distance ) ) + +#define FILE_Pos() \ + FT_Stream_Pos( stream ) + +#define FILE_Read( buffer, count ) \ + FT_SET_ERROR( FT_Read_Stream( stream, \ + (FT_Byte*)buffer, \ + count ) ) + +#define FILE_Read_At( position, buffer, count ) \ + FT_SET_ERROR( FT_Read_Stream_At( stream, \ + position, \ + (FT_Byte*)buffer, \ + count ) ) + +#define READ_Fields( fields, object ) \ + ( ( error = FT_Read_Fields( stream, fields, object ) ) != FT_Err_Ok ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTSTREAM_H */ + + +/* END */ diff --git a/include/freetype/internal/psnames.h b/include/freetype/internal/psnames.h new file mode 100644 index 0000000..ed86235 --- /dev/null +++ b/include/freetype/internal/psnames.h @@ -0,0 +1,220 @@ +/***************************************************************************/ +/* */ +/* psnames.h */ +/* */ +/* High-level interface for the `PSNames' module (in charge of */ +/* various functions related to Postscript glyph names conversion). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef PSNAMES_H +#define PSNAMES_H + + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicode_Value_Func */ + /* */ + /* */ + /* A function used to return the Unicode index corresponding to a */ + /* given glyph name. */ + /* */ + /* */ + /* glyph_name :: The glyph name. */ + /* */ + /* */ + /* The Unicode character index resp. the non-Unicode value 0xFFFF if */ + /* the glyph name has no known Unicode meaning. */ + /* */ + /* */ + /* This function is able to map several different glyph names to the */ + /* same Unicode value, according to the rules defined in the Adobe */ + /* Glyph List table. */ + /* */ + /* This function will not be compiled if the configuration macro */ + /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined. */ + /* */ + typedef FT_ULong (*PS_Unicode_Value_Func)( const char* glyph_name ); + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicode_Index_Func */ + /* */ + /* */ + /* A function used to return the glyph index corresponding to a given */ + /* Unicode value. */ + /* */ + /* */ + /* num_glyphs :: The number of glyphs in the face. */ + /* */ + /* glyph_names :: An array of glyph name pointers. */ + /* */ + /* unicode :: The Unicode value. */ + /* */ + /* */ + /* The glyph index resp. 0xFFFF if no glyph corresponds to this */ + /* Unicode value. */ + /* */ + /* */ + /* This function is able to recognize several glyph names per Unicode */ + /* value, according to the Adobe Glyph List. */ + /* */ + /* This function will not be compiled if the configuration macro */ + /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined. */ + /* */ + typedef FT_UInt (*PS_Unicode_Index_Func)( FT_UInt num_glyphs, + const char** glyph_names, + FT_ULong unicode ); + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Macintosh_Name_Func */ + /* */ + /* */ + /* A function used to return the glyph name corresponding to an Apple */ + /* glyph name index. */ + /* */ + /* */ + /* name_index :: The index of the Mac name. */ + /* */ + /* */ + /* The glyph name, or 0 if the index is invalid. */ + /* */ + /* */ + /* This function will not be compiled if the configuration macro */ + /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined. */ + /* */ + typedef const char* (*PS_Macintosh_Name_Func)( FT_UInt name_index ); + + + typedef const char* (*PS_Adobe_Std_Strings_Func)( FT_UInt string_index ); + + + typedef struct PS_UniMap_ + { + FT_UInt unicode; + FT_UInt glyph_index; + + } PS_UniMap; + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicodes */ + /* */ + /* */ + /* A simple table used to map Unicode values to glyph indices. It is */ + /* built by the PS_Build_Unicodes table according to the glyphs */ + /* present in a font file. */ + /* */ + /* */ + /* num_codes :: The number of glyphs in the font that match a given */ + /* Unicode value. */ + /* */ + /* unicodes :: An array of unicode values, sorted in increasing */ + /* order. */ + /* */ + /* gindex :: An array of glyph indices, corresponding to each */ + /* Unicode value. */ + /* */ + /* */ + /* Use the function PS_Lookup_Unicode() to retrieve the glyph index */ + /* corresponding to a given Unicode character code. */ + /* */ + typedef struct PS_Unicodes_ + { + FT_UInt num_maps; + PS_UniMap* maps; + + } PS_Unicodes; + + + typedef FT_Error (*PS_Build_Unicodes_Func)( FT_Memory memory, + FT_UInt num_glyphs, + const char** glyph_names, + PS_Unicodes* unicodes ); + + typedef FT_UInt (*PS_Lookup_Unicode_Func)( PS_Unicodes* unicodes, + FT_UInt unicode ); + + + /*************************************************************************/ + /* */ + /* */ + /* PSNames_Interface */ + /* */ + /* */ + /* This structure defines the PSNames interface. */ + /* */ + /* */ + /* unicode_value :: A function used to convert a glyph name */ + /* into a Unicode character code. */ + /* */ + /* build_unicodes :: A function which builds up the Unicode */ + /* mapping table. */ + /* */ + /* lookup_unicode :: A function used to return the glyph index */ + /* corresponding to a given Unicode */ + /* character. */ + /* */ + /* macintosh_name :: A function used to return the standard */ + /* Apple glyph Postscript name corresponding */ + /* to a given string index (used by the */ + /* TrueType `post' table). */ + /* */ + /* adobe_std_strings :: A function that returns a pointer to a */ + /* Adobe Standard String for a given SID. */ + /* */ + /* adobe_std_encoding :: A table of 256 unsigned shorts that maps */ + /* character codes in the Adobe Standard */ + /* Encoding to SIDs. */ + /* */ + /* adobe_expert_encoding :: A table of 256 unsigned shorts that maps */ + /* character codes in the Adobe Expert */ + /* Encoding to SIDs. */ + /* */ + /* */ + /* `unicode_value' and `unicode_index' will be set to 0 if the */ + /* configuration macro FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is */ + /* undefined. */ + /* */ + /* `macintosh_name' will be set to 0 if the configuration macro */ + /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined. */ + /* */ + typedef struct PSNames_Interface_ + { + PS_Unicode_Value_Func unicode_value; + PS_Build_Unicodes_Func build_unicodes; + PS_Lookup_Unicode_Func lookup_unicode; + PS_Macintosh_Name_Func macintosh_name; + + PS_Adobe_Std_Strings_Func adobe_std_strings; + const unsigned short* adobe_std_encoding; + const unsigned short* adobe_expert_encoding; + + } PSNames_Interface; + + +#endif /* PSNAMES_H */ + + +/* END */ diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h new file mode 100644 index 0000000..380ee93 --- /dev/null +++ b/include/freetype/internal/sfnt.h @@ -0,0 +1,492 @@ +/***************************************************************************/ +/* */ +/* sfnt.h */ +/* */ +/* High-level `sfnt' driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef SFNT_H +#define SFNT_H + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face_Func */ + /* */ + /* */ + /* First part of the SFNT face object initialization. This will find */ + /* the face in a SFNT file or collection, and load its format tag in */ + /* face->format_tag. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* params :: Optional additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType */ + /* collection'. */ + /* */ + /* Once the format tag has been validated by the font driver, it */ + /* should then call the TT_Load_Face_Func() callback to read the rest */ + /* of the SFNT tables in the object. */ + /* */ + typedef + FT_Error (*TT_Init_Face_Func)( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Face_Func */ + /* */ + /* */ + /* Second part of the SFNT face object initialization. This will */ + /* load the common SFNT tables (head, OS/2, maxp, metrics, etc.) in */ + /* the face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* params :: Optional additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function must be called after TT_Init_Face_Func(). */ + /* */ + typedef + FT_Error (*TT_Load_Face_Func)( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face_Func */ + /* */ + /* */ + /* A callback used to delete the common SFNT data from a face. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* This function does NOT destroy the face object. */ + /* */ + typedef + void (*TT_Done_Face_Func)( TT_Face face ); + + + typedef + FT_Module_Interface (*SFNT_Get_Interface_Func)( FT_Module module, + const char* interface ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SFNT_Header_Func */ + /* */ + /* */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType */ + /* collection'. */ + /* */ + /* This function checks that the header is valid by looking at the */ + /* values of `search_range', `entry_selector', and `range_shift'. */ + /* */ + typedef + FT_Error (*TT_Load_SFNT_Header_Func)( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header* sfnt ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory_Func */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be on the first byte after the 4-byte font */ + /* format tag. This is the case just after a call to */ + /* TT_Load_Format_Tag(). */ + /* */ + typedef + FT_Error (*TT_Load_Directory_Func)( TT_Face face, + FT_Stream stream, + SFNT_Header* sfnt ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any_Func */ + /* */ + /* */ + /* Loads any font table into client memory. */ + /* */ + /* */ + /* face :: The face object to look for. */ + /* */ + /* tag :: The tag of table to load. Use the value 0 if you want */ + /* to access the whole font file, else set this parameter */ + /* to a valid TrueType table tag that you can forge with */ + /* the MAKE_TT_TAG macro. */ + /* */ + /* offset :: The starting offset in the table (or the file if */ + /* tag == 0). */ + /* */ + /* length :: The address of the decision variable: */ + /* */ + /* If length == NULL: */ + /* Loads the whole table. Returns an error if */ + /* `offset' == 0! */ + /* */ + /* If *length == 0: */ + /* Exits immediately; returning the length of the given */ + /* table or of the font file, depending on the value of */ + /* `tag'. */ + /* */ + /* If *length != 0: */ + /* Loads the next `length' bytes of table or font, */ + /* starting at offset `offset' (in table or font too). */ + /* */ + /* */ + /* buffer :: The address of target buffer. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Any_Func)( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Image_Func */ + /* */ + /* */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* glyph_index :: The current glyph index. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + typedef + FT_Error (*TT_Load_SBit_Image_Func)( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name_Func */ + /* */ + /* */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* */ + /* index :: The glyph index. */ + /* */ + /* PSname :: The address of a string pointer. Will be NULL in case */ + /* of error, otherwise it is a pointer to the glyph name. */ + /* */ + /* You must not modify the returned string! */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Get_PS_Name_Func)( TT_Face face, + FT_UInt index, + FT_String** PSname ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics_Func */ + /* */ + /* */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Metrics_Func)( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Load_Func */ + /* */ + /* */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* stream :: A handle to the current stream object. */ + /* */ + /* */ + /* cmap :: A pointer to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function assumes that the stream is already in use (i.e., */ + /* opened). In case of error, all partially allocated tables are */ + /* released. */ + /* */ + typedef + FT_Error (*TT_CharMap_Load_Func)( TT_Face face, + TT_CMapTable* cmap, + FT_Stream input ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free_Func */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_CharMap_Free_Func)( TT_Face face, + TT_CMapTable* cmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Table_Func */ + /* */ + /* */ + /* Loads a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function will use `face->goto_table' to seek the stream to */ + /* the start of the table. */ + /* */ + typedef + FT_Error (*TT_Load_Table_Func)( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Table_Func */ + /* */ + /* */ + /* Frees a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + typedef + void (*TT_Free_Table_Func)( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* SFNT_Interface */ + /* */ + /* */ + /* This structure holds pointers to the functions used to load and */ + /* free the basic tables that are required in a `sfnt' font file. */ + /* */ + /* */ + /* Check the various xxx_Func() descriptions for details. */ + /* */ + typedef struct SFNT_Interface_ + { + TT_Goto_Table_Func goto_table; + + TT_Init_Face_Func init_face; + TT_Load_Face_Func load_face; + TT_Done_Face_Func done_face; + SFNT_Get_Interface_Func get_interface; + + TT_Load_Any_Func load_any; + TT_Load_SFNT_Header_Func load_sfnt_header; + TT_Load_Directory_Func load_directory; + + /* these functions are called by `load_face' but they can also */ + /* be called from external modules, if there is a need to do so */ + TT_Load_Table_Func load_header; + TT_Load_Metrics_Func load_metrics; + TT_Load_Table_Func load_charmaps; + TT_Load_Table_Func load_max_profile; + TT_Load_Table_Func load_os2; + TT_Load_Table_Func load_psnames; + + TT_Load_Table_Func load_names; + TT_Free_Table_Func free_names; + + /* optional tables */ + TT_Load_Table_Func load_hdmx; + TT_Free_Table_Func free_hdmx; + + TT_Load_Table_Func load_kerning; + TT_Load_Table_Func load_gasp; + TT_Load_Table_Func load_pclt; + + /* see `ttsbit.h' */ + TT_Load_Table_Func load_sbits; + TT_Load_SBit_Image_Func load_sbit_image; + TT_Free_Table_Func free_sbits; + + /* see `ttpost.h' */ + TT_Get_PS_Name_Func get_psname; + TT_Free_Table_Func free_psnames; + + /* see `ttcmap.h' */ + TT_CharMap_Load_Func load_charmap; + TT_CharMap_Free_Func free_charmap; + + } SFNT_Interface; + + +#endif /* SFNT_H */ + + +/* END */ diff --git a/include/freetype/internal/t1errors.h b/include/freetype/internal/t1errors.h new file mode 100644 index 0000000..58566d8 --- /dev/null +++ b/include/freetype/internal/t1errors.h @@ -0,0 +1,67 @@ +/***************************************************************************/ +/* */ +/* t1errors.h */ +/* */ +/* Type 1 error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1ERRORS_H +#define T1ERRORS_H + + + /************************ error codes declaration **************/ + + /* The error codes are grouped into `classes' used to indicate the */ + /* `level' at which the error happened. */ + /* */ + /* The class is given by an error code's high byte. */ + + + /* ------------- Success is always 0 -------- */ + +#define T1_Err_Ok FT_Err_Ok + + /* ----------- high level API errors -------- */ + +#define T1_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define T1_Err_Invalid_Argument FT_Err_Invalid_Argument +#define T1_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define T1_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define T1_Err_Invalid_Size_Handle FT_Err_Invalid_Size_Handle +#define T1_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define T1_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define T1_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define T1_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define T1_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* ------------- internal errors ------------ */ + +#define T1_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define T1_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* ------------ general glyph outline errors ------ */ + +#define T1_Err_Invalid_Composite FT_Err_Invalid_Composite + +#define T1_Err_Syntax_Error FT_Err_Invalid_File_Format +#define T1_Err_Stack_Underflow FT_Err_Invalid_File_Format +#define T1_Err_Stack_Overflow FT_Err_Invalid_File_Format + + +#endif /* T1ERRORS_H */ + + +/* END */ diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h new file mode 100644 index 0000000..4d41a6b --- /dev/null +++ b/include/freetype/internal/t1types.h @@ -0,0 +1,188 @@ +/***************************************************************************/ +/* */ +/* t1types.h */ +/* */ +/* Basic Type1/Type2 type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1TYPES_H +#define T1TYPES_H + + +#include +#include + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Encoding */ + /* */ + /* */ + /* A structure modeling a custom encoding */ + /* */ + /* */ + /* num_chars :: The number of character codes in the encoding. */ + /* Usually 256. */ + /* */ + /* code_first :: The lowest valid character code in the encoding. */ + /* */ + /* code_last :: The highest valid character code in the encoding. */ + /* */ + /* char_index :: An array of corresponding glyph indices. */ + /* */ + /* char_name :: An array of corresponding glyph names. */ + /* */ + typedef struct T1_Encoding_ + { + FT_Int num_chars; + FT_Int code_first; + FT_Int code_last; + + FT_UShort* char_index; + FT_String** char_name; + + } T1_Encoding; + + + typedef enum T1_EncodingType_ + { + t1_encoding_none = 0, + t1_encoding_array, + t1_encoding_standard, + t1_encoding_expert + + } T1_EncodingType; + + + typedef struct T1_Font_ + { + + /* font info dictionary */ + T1_FontInfo font_info; + + /* private dictionary */ + T1_Private private_dict; + + /* top-level dictionary */ + FT_String* font_name; + + T1_EncodingType encoding_type; + T1_Encoding encoding; + + FT_Byte* subrs_block; + FT_Byte* charstrings_block; + FT_Byte* glyph_names_block; + + FT_Int num_subrs; + FT_Byte** subrs; + FT_Int* subrs_len; + + FT_Int num_glyphs; + FT_String** glyph_names; /* array of glyph names */ + FT_Byte** charstrings; /* array of glyph charstrings */ + FT_Int* charstrings_len; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + FT_BBox font_bbox; + FT_Long font_id; + + FT_Int stroke_width; + + } T1_Font; + + + typedef struct CID_Subrs_ + { + FT_UInt num_subrs; + FT_Byte** code; + + } CID_Subrs; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** ORIGINAL T1_FACE CLASS DEFINITION ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This structure/class is defined here because it is common to the */ + /* following formats: TTF, OpenType-TT, and OpenType-CFF. */ + /* */ + /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */ + /* are not shared between font drivers, and are thus defined normally in */ + /* `ttobjs.h'. */ + /* */ + /*************************************************************************/ + + typedef struct T1_FaceRec_* T1_Face; + typedef struct CID_FaceRec_* CID_Face; + + + typedef struct T1_FaceRec_ + { + FT_FaceRec root; + T1_Font type1; + void* psnames; + void* afm_data; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; + PS_Unicodes unicode_map; + + /* support for Multiple Masters fonts */ + T1_Blend* blend; + + } T1_FaceRec; + + + typedef struct CID_FaceRec_ + { + FT_FaceRec root; + void* psnames; + CID_Info cid; + void* afm_data; + CID_Subrs* subrs; + + } CID_FaceRec; + + +#endif /* T1TYPES_H */ + + +/* END */ diff --git a/include/freetype/internal/t2errors.h b/include/freetype/internal/t2errors.h new file mode 100644 index 0000000..d685220 --- /dev/null +++ b/include/freetype/internal/t2errors.h @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* t2errors.h */ +/* */ +/* OpenType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2ERRORS_H +#define T2ERRORS_H + + + /*************************************************************************/ + /* */ + /* Error codes declaration */ + /* */ + /* The error codes are grouped in `classes' used to indicate the `level' */ + /* at which the error happened. The class is given by an error code's */ + /* high byte. */ + /* */ + /*************************************************************************/ + + + /* Success is always 0. */ + +#define T2_Err_Ok FT_Err_Ok + + /* High level API errors. */ + +#define T2_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define T2_Err_Invalid_Argument FT_Err_Invalid_Argument +#define T2_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define T2_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define T2_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle +#define T2_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define T2_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define T2_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define T2_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define T2_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* Internal errors. */ + +#define T2_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define T2_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* General glyph outline errors. */ + +#define T2_Err_Invalid_Composite FT_Err_Invalid_Composite + + /* Bytecode interpreter error codes. */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define T2_Err_Invalid_Opcode 0x500 +#define T2_Err_Too_Few_Arguments 0x501 +#define T2_Err_Stack_Overflow 0x502 +#define T2_Err_Code_Overflow 0x503 +#define T2_Err_Bad_Argument 0x504 +#define T2_Err_Divide_By_Zero 0x505 +#define T2_Err_Storage_Overflow 0x506 +#define T2_Err_Cvt_Overflow 0x507 +#define T2_Err_Invalid_Reference 0x508 +#define T2_Err_Invalid_Distance 0x509 +#define T2_Err_Interpolate_Twilight 0x50A +#define T2_Err_Debug_OpCode 0x50B +#define T2_Err_ENDF_In_Exec_Stream 0x50C +#define T2_Err_Out_Of_CodeRanges 0x50D +#define T2_Err_Nested_DEFS 0x50E +#define T2_Err_Invalid_CodeRange 0x50F +#define T2_Err_Invalid_Displacement 0x510 +#define T2_Err_Execution_Too_Long 0x511 + +#define T2_Err_Too_Many_Instruction_Defs 0x512 +#define T2_Err_Too_Many_Function_Defs 0x513 + + /* Other TrueType specific error codes. */ + +#define T2_Err_Table_Missing 0x520 +#define T2_Err_Too_Many_Extensions 0x521 +#define T2_Err_Extensions_Unsupported 0x522 +#define T2_Err_Invalid_Extension_Id 0x523 + +#define T2_Err_No_Vertical_Data 0x524 + +#define T2_Err_Max_Profile_Missing 0x530 +#define T2_Err_Header_Table_Missing 0x531 +#define T2_Err_Horiz_Header_Missing 0x532 +#define T2_Err_Locations_Missing 0x533 +#define T2_Err_Name_Table_Missing 0x534 +#define T2_Err_CMap_Table_Missing 0x535 +#define T2_Err_Hmtx_Table_Missing 0x536 +#define T2_Err_OS2_Table_Missing 0x537 +#define T2_Err_Post_Table_Missing 0x538 + +#define T2_Err_Invalid_Horiz_Metrics 0x540 +#define T2_Err_Invalid_CharMap_Format 0x541 +#define T2_Err_Invalid_PPem 0x542 +#define T2_Err_Invalid_Vert_Metrics 0x543 + +#define T2_Err_Could_Not_Find_Context 0x550 + + +#endif /* T2ERRORS_H */ + + +/* END */ diff --git a/include/freetype/internal/t2types.h b/include/freetype/internal/t2types.h new file mode 100644 index 0000000..033f315 --- /dev/null +++ b/include/freetype/internal/t2types.h @@ -0,0 +1,218 @@ +/***************************************************************************/ +/* */ +/* t2types.h */ +/* */ +/* Basic OpenType/CFF type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2TYPES_H +#define T2TYPES_H + + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* CFF_Index */ + /* */ + /* */ + /* A structure used to model a CFF Index table. */ + /* */ + /* */ + /* stream :: XXX */ + /* */ + /* count :: The number of elements in the index. */ + /* */ + /* off_size :: The size in bytes of object offsets in index. */ + /* */ + /* data_offset :: The position of first data byte in the index's */ + /* bytes. */ + /* */ + /* offsets :: XXX */ + /* */ + /* bytes :: If the index is loaded in memory, its bytes. */ + /* */ + typedef struct CFF_Index_ + { + FT_Stream stream; + FT_UInt count; + FT_Byte off_size; + FT_ULong data_offset; + + FT_ULong* offsets; + FT_Byte* bytes; + + } CFF_Index; + + + typedef struct CFF_Font_Dict_ + { + FT_UInt version; + FT_UInt notice; + FT_UInt copyright; + FT_UInt full_name; + FT_UInt family_name; + FT_UInt weight; + FT_Bool is_fixed_pitch; + FT_Fixed italic_angle; + FT_Pos underline_position; + FT_Pos underline_thickness; + FT_Int paint_type; + FT_Int charstring_type; + FT_Matrix font_matrix; + FT_ULong unique_id; + FT_BBox font_bbox; + FT_Pos stroke_width; + FT_ULong charset_offset; + FT_ULong encoding_offset; + FT_ULong charstrings_offset; + FT_ULong private_offset; + FT_ULong private_size; + FT_Long synthetic_base; + FT_UInt embedded_postscript; + FT_UInt base_font_name; + FT_UInt postscript; + + /* these should only be used for the top-level font dictionary */ + FT_UInt cid_registry; + FT_UInt cid_ordering; + FT_ULong cid_supplement; + + FT_Long cid_font_version; + FT_Long cid_font_revision; + FT_Long cid_font_type; + FT_Long cid_count; + FT_ULong cid_uid_base; + FT_ULong cid_fd_array_offset; + FT_ULong cid_fd_select_offset; + FT_UInt cid_font_name; + + } CFF_Font_Dict; + + + typedef struct CFF_Private_ + { + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Pos blue_values[14]; + FT_Pos other_blues[10]; + FT_Pos family_blues[14]; + FT_Pos family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Pos blue_shift; + FT_Pos blue_fuzz; + FT_Pos standard_width; + FT_Pos standard_height; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Pos snap_widths[13]; + FT_Pos snap_heights[13]; + FT_Bool force_bold; + FT_Fixed force_bold_threshold; + FT_Int lenIV; + FT_Int language_group; + FT_Fixed expansion_factor; + FT_Long initial_random_seed; + FT_ULong local_subrs_offset; + FT_Pos default_width; + FT_Pos nominal_width; + + } CFF_Private; + + + typedef struct CFF_FD_Select_ + { + FT_Byte format; + FT_UInt range_count; + + /* that's the table, taken from the file `as is' */ + FT_Byte* data; + FT_UInt data_size; + + /* small cache for format 3 only */ + FT_UInt cache_first; + FT_UInt cache_count; + FT_Byte cache_fd; + + } CFF_FD_Select; + + + /* A SubFont packs a font dict and a private dict together. They are */ + /* needed to support CID-keyed CFF fonts. */ + typedef struct CFF_SubFont_ + { + CFF_Font_Dict font_dict; + CFF_Private private_dict; + + CFF_Index local_subrs_index; + FT_UInt num_local_subrs; + FT_Byte** local_subrs; + + } CFF_SubFont; + + + /* maximum number of sub-fonts in a CID-keyed file */ +#define CFF_MAX_CID_FONTS 16 + + + typedef struct CFF_Font_ + { + FT_Stream stream; + FT_Memory memory; + FT_UInt num_faces; + FT_UInt num_glyphs; + + FT_Byte version_major; + FT_Byte version_minor; + FT_Byte header_size; + FT_Byte absolute_offsize; + + + CFF_Index name_index; + CFF_Index top_dict_index; + CFF_Index string_index; + CFF_Index global_subrs_index; + + /* we don't load the Encoding and CharSet tables */ + + CFF_Index charstrings_index; + CFF_Index font_dict_index; + CFF_Index private_index; + CFF_Index local_subrs_index; + + FT_String* font_name; + FT_UInt num_global_subrs; + FT_Byte** global_subrs; + + CFF_SubFont top_font; + FT_UInt num_subfonts; + CFF_SubFont* subfonts[CFF_MAX_CID_FONTS]; + + CFF_FD_Select fd_select; + + } CFF_Font; + + +#endif /* T2TYPES_H */ + + +/* END */ diff --git a/include/freetype/internal/tterrors.h b/include/freetype/internal/tterrors.h new file mode 100644 index 0000000..b53e9f3 --- /dev/null +++ b/include/freetype/internal/tterrors.h @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* tterrors.h */ +/* */ +/* TrueType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTERRORS_H +#define TTERRORS_H + + + /*************************************************************************/ + /* */ + /* Error codes declaration */ + /* */ + /* The error codes are grouped in `classes' used to indicate the `level' */ + /* at which the error happened. The class is given by an error code's */ + /* high byte. */ + /* */ + /*************************************************************************/ + + + /* Success is always 0. */ + +#define TT_Err_Ok FT_Err_Ok + + /* High level API errors. */ + +#define TT_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define TT_Err_Invalid_Argument FT_Err_Invalid_Argument +#define TT_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define TT_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle +#define TT_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define TT_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define TT_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define TT_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define TT_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* Internal errors. */ + +#define TT_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define TT_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* General glyph outline errors. */ + +#define TT_Err_Too_Many_Ins FT_Err_Too_Many_Hints +#define TT_Err_Invalid_Composite FT_Err_Invalid_Composite + + /* Bytecode interpreter error codes. */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define TT_Err_Invalid_Opcode 0x400 +#define TT_Err_Too_Few_Arguments 0x401 +#define TT_Err_Stack_Overflow 0x402 +#define TT_Err_Code_Overflow 0x403 +#define TT_Err_Bad_Argument 0x404 +#define TT_Err_Divide_By_Zero 0x405 +#define TT_Err_Storage_Overflow 0x406 +#define TT_Err_Cvt_Overflow 0x407 +#define TT_Err_Invalid_Reference 0x408 +#define TT_Err_Invalid_Distance 0x409 +#define TT_Err_Interpolate_Twilight 0x40A +#define TT_Err_Debug_OpCode 0x40B +#define TT_Err_ENDF_In_Exec_Stream 0x40C +#define TT_Err_Out_Of_CodeRanges 0x40D +#define TT_Err_Nested_DEFS 0x40E +#define TT_Err_Invalid_CodeRange 0x40F +#define TT_Err_Invalid_Displacement 0x410 +#define TT_Err_Execution_Too_Long 0x411 +#define TT_Err_Too_Many_Function_Defs 0x412 +#define TT_Err_Too_Many_Instruction_Defs 0x413 + + /* Other TrueType specific error codes. */ + +#define TT_Err_Table_Missing 0x420 +#define TT_Err_Too_Many_Extensions 0x421 +#define TT_Err_Extensions_Unsupported 0x422 +#define TT_Err_Invalid_Extension_Id 0x423 + +#define TT_Err_No_Vertical_Data 0x424 + +#define TT_Err_Max_Profile_Missing 0x430 +#define TT_Err_Header_Table_Missing 0x431 +#define TT_Err_Horiz_Header_Missing 0x432 +#define TT_Err_Locations_Missing 0x433 +#define TT_Err_Name_Table_Missing 0x434 +#define TT_Err_CMap_Table_Missing 0x435 +#define TT_Err_Hmtx_Table_Missing 0x436 +#define TT_Err_OS2_Table_Missing 0x437 +#define TT_Err_Post_Table_Missing 0x438 + +#define TT_Err_Invalid_Horiz_Metrics 0x440 +#define TT_Err_Invalid_CharMap_Format 0x441 +#define TT_Err_Invalid_PPem 0x442 +#define TT_Err_Invalid_Vert_Metrics 0x443 + +#define TT_Err_Could_Not_Find_Context 0x450 + + +#endif /* TTERRORS_H */ + + +/* END */ diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h new file mode 100644 index 0000000..1fd43ce --- /dev/null +++ b/include/freetype/internal/tttypes.h @@ -0,0 +1,1582 @@ +/***************************************************************************/ +/* */ +/* tttypes.h */ +/* */ +/* Basic SFNT/TrueType type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTTYPES_H +#define TTTYPES_H + + +#include + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TTC_Header */ + /* */ + /* */ + /* TrueType collection header. This table contains the offsets of */ + /* the font headers of each distinct TrueType face in the file. */ + /* */ + /* */ + /* tag :: Must be `ttc ' to indicate a TrueType collection. */ + /* */ + /* version :: The version number. */ + /* */ + /* count :: The number of faces in the collection. The */ + /* specification says this should be an unsigned long, but */ + /* we use a signed long since we need the value -1 for */ + /* specific purposes. */ + /* */ + /* offsets :: The offsets of the font headers, one per face. */ + /* */ + typedef struct TTC_Header_ + { + FT_ULong tag; + FT_Fixed version; + FT_Long count; + FT_ULong* offsets; + + } TTC_Header; + + + /*************************************************************************/ + /* */ + /* */ + /* SFNT_Header */ + /* */ + /* */ + /* SFNT file format header. */ + /* */ + /* */ + /* format_tag :: The font format tag. */ + /* */ + /* num_tables :: The number of tables in file. */ + /* */ + /* search_range :: Must be 16*(max power of 2 <= num_tables). */ + /* */ + /* entry_selector :: Must be log2 of search_range/16. */ + /* */ + /* range_shift :: Must be num_tables*16 - search_range. */ + /* */ + typedef struct SFNT_Header_ + { + FT_ULong format_tag; + FT_UShort num_tables; + FT_UShort search_range; + FT_UShort entry_selector; + FT_UShort range_shift; + + } SFNT_Header; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_TableDir */ + /* */ + /* */ + /* This structure models a TrueType table directory. It is used to */ + /* access the various tables of the font face. */ + /* */ + /* */ + /* version :: The version number; starts with 0x00010000. */ + /* */ + /* numTables :: The number of tables. */ + /* */ + /* searchRange :: Unused. */ + /* */ + /* entrySelector :: Unused. */ + /* */ + /* rangeShift :: Unused. */ + /* */ + /* */ + /* This structure is only used during font opening. */ + /* */ + typedef struct TT_TableDir_ + { + FT_Fixed version; /* should be 0x10000 */ + FT_UShort numTables; /* number of tables */ + + FT_UShort searchRange; /* These parameters are only used */ + FT_UShort entrySelector; /* for a dichotomy search in the */ + FT_UShort rangeShift; /* directory. We ignore them. */ + + } TT_TableDir; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Table */ + /* */ + /* */ + /* This structure describes a given table of a TrueType font. */ + /* */ + /* */ + /* Tag :: A four-bytes tag describing the table. */ + /* */ + /* CheckSum :: The table checksum. This value can be ignored. */ + /* */ + /* Offset :: The offset of the table from the start of the TrueType */ + /* font in its resource. */ + /* */ + /* Length :: The table length (in bytes). */ + /* */ + typedef struct TT_Table_ + { + FT_ULong Tag; /* table type */ + FT_ULong CheckSum; /* table checksum */ + FT_ULong Offset; /* table file offset */ + FT_ULong Length; /* table length */ + + } TT_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CMapDir */ + /* */ + /* */ + /* This structure describes the directory of the `cmap' table, */ + /* containing the font's character mappings table. */ + /* */ + /* */ + /* tableVersionNumber :: The version number. */ + /* */ + /* numCMaps :: The number of charmaps in the font. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_CMapDir_ + { + FT_UShort tableVersionNumber; + FT_UShort numCMaps; + + } TT_CMapDir; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CMapDirEntry */ + /* */ + /* */ + /* This structure describes a charmap in a TrueType font. */ + /* */ + /* */ + /* platformID :: An ID used to specify for which platform this */ + /* charmap is defined (FreeType manages all platforms). */ + /* */ + /* encodingID :: A platform-specific ID used to indicate which source */ + /* encoding is used in this charmap. */ + /* */ + /* offset :: The offset of the charmap relative to the start of */ + /* the `cmap' table. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_CMapDirEntry_ + { + FT_UShort platformID; + FT_UShort platformEncodingID; + FT_Long offset; + + } TT_CMapDirEntry; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LongMetrics */ + /* */ + /* */ + /* A structure modeling the long metrics of the `hmtx' and `vmtx' */ + /* TrueType tables. The values are expressed in font units. */ + /* */ + /* */ + /* advance :: The advance width or height for the glyph. */ + /* */ + /* bearing :: The left-side or top-side bearing for the glyph. */ + /* */ + typedef struct TT_LongMetrics_ + { + FT_UShort advance; + FT_Short bearing; + + } TT_LongMetrics; + + + /*************************************************************************/ + /* */ + /* TT_ShortMetrics */ + /* */ + /* */ + /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ + /* tables. */ + /* */ + typedef FT_Short TT_ShortMetrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_NameRec */ + /* */ + /* */ + /* A structure modeling TrueType name records. Name records are used */ + /* to store important strings like family name, style name, */ + /* copyright, etc. in _localized_ versions (i.e., language, encoding, */ + /* etc). */ + /* */ + /* */ + /* platformID :: The ID of the name's encoding platform. */ + /* */ + /* encodingID :: The platform-specific ID for the name's encoding. */ + /* */ + /* languageID :: The platform-specific ID for the name's language. */ + /* */ + /* nameID :: The ID specifying what kind of name this is. */ + /* */ + /* stringLength :: The length of the string in bytes. */ + /* */ + /* stringOffset :: The offset to the string in the `name' table. */ + /* */ + /* string :: A pointer to the string's bytes. Note that these */ + /* are usually UTF-16 encoded characters. */ + /* */ + typedef struct TT_NameRec_ + { + FT_UShort platformID; + FT_UShort encodingID; + FT_UShort languageID; + FT_UShort nameID; + FT_UShort stringLength; + FT_UShort stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + FT_Byte* string; + + } TT_NameRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_NameTable */ + /* */ + /* */ + /* A structure modeling the TrueType name table. */ + /* */ + /* */ + /* format :: The format of the name table. */ + /* */ + /* numNameRecords :: The number of names in table. */ + /* */ + /* storageOffset :: The offset of the name table in the `name' */ + /* TrueType table. */ + /* */ + /* names :: An array of name records. */ + /* */ + /* storage :: The names storage area. */ + /* */ + typedef struct TT_NameTable_ + { + FT_UShort format; + FT_UShort numNameRecords; + FT_UShort storageOffset; + TT_NameRec* names; + FT_Byte* storage; + + } TT_NameTable; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GaspRange */ + /* */ + /* */ + /* A tiny structure used to model a gasp range according to the */ + /* TrueType specification. */ + /* */ + /* */ + /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */ + /* */ + /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */ + /* modes to be used. */ + /* */ + typedef struct TT_GaspRange_ + { + FT_UShort maxPPEM; + FT_UShort gaspFlag; + + } TT_GaspRange; + + +#define TT_GASP_GRIDFIT 0x01 +#define TT_GASP_DOGRAY 0x02 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Gasp */ + /* */ + /* */ + /* A structure modeling the TrueType `gasp' table used to specify */ + /* grid-fitting and anti-aliasing behaviour. */ + /* */ + /* */ + /* version :: The version number. */ + /* */ + /* numRanges :: The number of gasp ranges in table. */ + /* */ + /* gaspRanges :: An array of gasp ranges. */ + /* */ + typedef struct TT_Gasp_ + { + FT_UShort version; + FT_UShort numRanges; + TT_GaspRange* gaspRanges; + + } TT_Gasp; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* A small structure used to model the pre-computed widths of a given */ + /* size. They are found in the `hdmx' table. */ + /* */ + /* */ + /* ppem :: The pixels per EM value at which these metrics apply. */ + /* */ + /* max_width :: The maximum advance width for this metric. */ + /* */ + /* widths :: An array of widths. Note: These are 8-bit bytes. */ + /* */ + typedef struct TT_HdmxRec_ + { + FT_Byte ppem; + FT_Byte max_width; + FT_Byte* widths; + + } TT_HdmxRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Hdmx */ + /* */ + /* */ + /* A structure used to model the `hdmx' table, which contains */ + /* pre-computed widths for a set of given sizes/dimensions. */ + /* */ + /* */ + /* version :: The version number. */ + /* */ + /* num_records :: The number of hdmx records. */ + /* */ + /* records :: An array of hdmx records. */ + /* */ + typedef struct TT_Hdmx_ + { + FT_UShort version; + FT_Short num_records; + TT_HdmxRec* records; + + } TT_Hdmx; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Kern_0_Pair */ + /* */ + /* */ + /* A structure used to model a kerning pair for the kerning table */ + /* format 0. The engine now loads this table if it finds one in the */ + /* font file. */ + /* */ + /* */ + /* left :: The index of the left glyph in pair. */ + /* */ + /* right :: The index of the right glyph in pair. */ + /* */ + /* value :: The kerning distance. A positive value spaces the */ + /* glyphs, a negative one makes them closer. */ + /* */ + typedef struct TT_Kern_0_Pair_ + { + FT_UShort left; /* index of left glyph in pair */ + FT_UShort right; /* index of right glyph in pair */ + FT_FWord value; /* kerning value */ + + } TT_Kern_0_Pair; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** EMBEDDED BITMAPS SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Metrics */ + /* */ + /* */ + /* A structure used to hold the big metrics of a given glyph bitmap */ + /* in a TrueType or OpenType font. These are usually found in the */ + /* `EBDT' (Microsoft) or `bdat' (Apple) table. */ + /* */ + /* */ + /* height :: The glyph height in pixels. */ + /* */ + /* width :: The glyph width in pixels. */ + /* */ + /* horiBearingX :: The horizontal left bearing. */ + /* */ + /* horiBearingY :: The horizontal top bearing. */ + /* */ + /* horiAdvance :: The horizontal advance. */ + /* */ + /* vertBearingX :: The vertical left bearing. */ + /* */ + /* vertBearingY :: The vertical top bearing. */ + /* */ + /* vertAdvance :: The vertical advance. */ + /* */ + typedef struct TT_SBit_Metrics_ + { + FT_Byte height; + FT_Byte width; + + FT_Char horiBearingX; + FT_Char horiBearingY; + FT_Byte horiAdvance; + + FT_Char vertBearingX; + FT_Char vertBearingY; + FT_Byte vertAdvance; + + } TT_SBit_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Small_Metrics */ + /* */ + /* */ + /* A structure used to hold the small metrics of a given glyph bitmap */ + /* in a TrueType or OpenType font. These are usually found in the */ + /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */ + /* */ + /* */ + /* height :: The glyph height in pixels. */ + /* */ + /* width :: The glyph width in pixels. */ + /* */ + /* bearingX :: The left-side bearing. */ + /* */ + /* bearingY :: The top-side bearing. */ + /* */ + /* advance :: The advance width or height. */ + /* */ + typedef struct TT_SBit_Small_Metrics_ + { + FT_Byte height; + FT_Byte width; + + FT_Char bearingX; + FT_Char bearingY; + FT_Byte advance; + + } TT_SBit_Small_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Line_Metrics */ + /* */ + /* */ + /* A structure used to describe the text line metrics of a given */ + /* bitmap strike, for either a horizontal or vertical layout. */ + /* */ + /* */ + /* ascender :: The ascender in pixels. */ + /* */ + /* descender :: The descender in pixels. */ + /* */ + /* max_width :: The maximum glyph width in pixels. */ + /* */ + /* caret_slope_enumerator :: Rise of the caret slope, typically set */ + /* to 1 for non-italic fonts. */ + /* */ + /* caret_slope_denominator :: Rise of the caret slope, typically set */ + /* to 0 for non-italic fonts. */ + /* */ + /* caret_offset :: Offset in pixels to move the caret for */ + /* proper positioning. */ + /* */ + /* min_origin_SB :: Minimum of horiBearingX (resp. */ + /* vertBearingY). */ + /* min_advance_SB :: Minimum of */ + /* */ + /* horizontal advance - */ + /* ( horiBearingX + width ) */ + /* */ + /* resp. */ + /* */ + /* vertical advance - */ + /* ( vertBearingY + height ) */ + /* */ + /* max_before_BL :: Maximum of horiBearingY (resp. */ + /* vertBearingY). */ + /* */ + /* min_after_BL :: Minimum of */ + /* */ + /* horiBearingY - height */ + /* */ + /* resp. */ + /* */ + /* vertBearingX - width */ + /* */ + /* pads :: Unused (to make the size of the record */ + /* a multiple of 32 bits. */ + /* */ + typedef struct TT_SBit_Line_Metrics_ + { + FT_Char ascender; + FT_Char descender; + FT_Byte max_width; + FT_Char caret_slope_numerator; + FT_Char caret_slope_denominator; + FT_Char caret_offset; + FT_Char min_origin_SB; + FT_Char min_advance_SB; + FT_Char max_before_BL; + FT_Char min_after_BL; + FT_Char pads[2]; + + } TT_SBit_Line_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Range */ + /* */ + /* */ + /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* */ + /* first_glyph :: The first glyph index in the range. */ + /* */ + /* last_glyph :: The last glyph index in the range. */ + /* */ + /* index_format :: The format of index table. Valid values are 1 */ + /* to 5. */ + /* */ + /* image_format :: The format of `EBDT' image data. */ + /* */ + /* image_offset :: The offset to image data in `EBDT'. */ + /* */ + /* image_size :: For index formats 2 and 5. This is the size in */ + /* bytes of each glyph bitmap. */ + /* */ + /* big_metrics :: For index formats 2 and 5. This is the big */ + /* metrics for each glyph bitmap. */ + /* */ + /* num_glyphs :: For index formats 4 and 5. This is the number of */ + /* glyphs in the code array. */ + /* */ + /* glyph_offsets :: For index formats 1 and 3. */ + /* */ + /* glyph_codes :: For index formats 4 and 5. */ + /* */ + /* table_offset :: The offset of the index table in the `EBLC' */ + /* table. Only used during strike loading. */ + /* */ + typedef struct TT_SBit_Range + { + FT_UShort first_glyph; + FT_UShort last_glyph; + + FT_UShort index_format; + FT_UShort image_format; + FT_ULong image_offset; + + FT_ULong image_size; + TT_SBit_Metrics metrics; + FT_ULong num_glyphs; + + FT_ULong* glyph_offsets; + FT_UShort* glyph_codes; + + FT_ULong table_offset; + + } TT_SBit_Range; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Strike */ + /* */ + /* */ + /* A structure used describe a given bitmap strike in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* */ + /* num_index_ranges :: The number of index ranges. */ + /* */ + /* index_ranges :: An array of glyph index ranges. */ + /* */ + /* color_ref :: Unused. A color reference? */ + /* */ + /* hori :: The line metrics for horizontal layouts. */ + /* */ + /* vert :: The line metrics for vertical layouts. */ + /* */ + /* start_glyph :: The lowest glyph index for this strike. */ + /* */ + /* end_glyph :: The highest glyph index for this strike. */ + /* */ + /* x_ppem :: The number of horizontal pixels per EM. */ + /* */ + /* y_ppem :: The number of vertical pixels per EM. */ + /* */ + /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */ + /* and 8. */ + /* */ + /* flags :: Is this a vertical or horizontal strike? */ + /* */ + typedef struct TT_SBit_Strike_ + { + FT_Int num_ranges; + TT_SBit_Range* sbit_ranges; + FT_ULong ranges_offset; + + FT_ULong color_ref; + + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + FT_UShort start_glyph; + FT_UShort end_glyph; + + FT_Byte x_ppem; + FT_Byte y_ppem; + + FT_Byte bit_depth; + FT_Char flags; + + } TT_SBit_Strike; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Component */ + /* */ + /* */ + /* A simple structure to describe a compound sbit element. */ + /* */ + /* */ + /* glyph_code :: The element's glyph index. */ + /* */ + /* x_offset :: The element's left bearing. */ + /* */ + /* y_offset :: The element's top bearing. */ + /* */ + typedef struct TT_SBit_Component_ + { + FT_UShort glyph_code; + + FT_Char x_offset; + FT_Char y_offset; + + } TT_SBit_Component; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Scale */ + /* */ + /* */ + /* A structure used describe a given bitmap scaling table, as defined */ + /* in the `EBSC' table. */ + /* */ + /* */ + /* hori :: The horizontal line metrics. */ + /* */ + /* vert :: The vertical line metrics. */ + /* */ + /* x_ppem :: The number of horizontal pixels per EM. */ + /* */ + /* y_ppem :: The number of vertical pixels per EM. */ + /* */ + /* x_ppem_substitute :: Substitution x_ppem value. */ + /* */ + /* y_ppem_substitute :: Substitution y_ppem value. */ + /* */ + typedef struct TT_SBit_Scale_ + { + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + FT_Byte x_ppem; + FT_Byte y_ppem; + + FT_Byte x_ppem_substitute; + FT_Byte y_ppem_substitute; + + } TT_SBit_Scale; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_20 */ + /* */ + /* */ + /* Postscript names sub-table, format 2.0. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* */ + /* num_glyphs :: The number of named glyphs in the table. */ + /* */ + /* num_names :: The number of PS names stored in the table. */ + /* */ + /* glyph_indices :: The indices of the glyphs in the names arrays. */ + /* */ + /* glyph_names :: The PS names not in Mac Encoding. */ + /* */ + typedef struct TT_Post_20_ + { + FT_UShort num_glyphs; + FT_UShort num_names; + FT_UShort* glyph_indices; + FT_Char** glyph_names; + + } TT_Post_20; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_25 */ + /* */ + /* */ + /* Postscript names sub-table, format 2.5. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* */ + /* num_glyphs :: The number of glyphs in the table. */ + /* */ + /* offsets :: An array of signed offsets in a normal Mac */ + /* Postscript name encoding. */ + /* */ + typedef struct TT_Post_25_ + { + FT_UShort num_glyphs; + FT_Char* offsets; + + } TT_Post_25; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_Names */ + /* */ + /* */ + /* Postscript names table, either format 2.0 or 2.5. */ + /* */ + /* */ + /* loaded :: A flag to indicate whether the PS names are loaded. */ + /* */ + /* format_20 :: The sub-table used for format 2.0. */ + /* */ + /* format_25 :: The sub-table used for format 2.5. */ + /* */ + typedef struct TT_Post_Names_ + { + FT_Bool loaded; + + union + { + TT_Post_20 format_20; + TT_Post_25 format_25; + + } names; + + } TT_Post_Names; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** TRUETYPE CHARMAPS SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* format 0 */ + + typedef struct TT_CMap0_ + { + FT_Byte* glyphIdArray; + + } TT_CMap0; + + + /* format 2 */ + + typedef struct TT_CMap2SubHeader_ + { + FT_UShort firstCode; /* first valid low byte */ + FT_UShort entryCount; /* number of valid low bytes */ + FT_Short idDelta; /* delta value to glyphIndex */ + FT_UShort idRangeOffset; /* offset from here to 1st code */ + + } TT_CMap2SubHeader; + + + typedef struct TT_CMap2_ + { + FT_UShort* subHeaderKeys; + /* high byte mapping table */ + /* value = subHeader index * 8 */ + + TT_CMap2SubHeader* subHeaders; + FT_UShort* glyphIdArray; + FT_UShort numGlyphId; /* control value */ + + } TT_CMap2; + + + /* format 4 */ + + typedef struct TT_CMap4Segment_ + { + FT_UShort endCount; + FT_UShort startCount; + FT_Short idDelta; + FT_UShort idRangeOffset; + + } TT_CMap4Segment; + + + typedef struct TT_CMap4_ + { + FT_UShort segCountX2; /* number of segments * 2 */ + FT_UShort searchRange; /* these parameters can be used */ + FT_UShort entrySelector; /* for a binary search */ + FT_UShort rangeShift; + + TT_CMap4Segment* segments; + FT_UShort* glyphIdArray; + FT_UShort numGlyphId; /* control value */ + + TT_CMap4Segment* last_segment; /* last used segment; this is a small */ + /* cache to potentially increase speed */ + } TT_CMap4; + + + /* format 6 */ + + typedef struct TT_CMap6_ + { + FT_UShort firstCode; /* first character code of subrange */ + FT_UShort entryCount; /* number of character codes in subrange */ + + FT_UShort* glyphIdArray; + + } TT_CMap6; + + + typedef struct TT_CMapTable_ TT_CMapTable; + + + typedef + FT_UInt (*TT_CharMap_Func)( TT_CMapTable* charmap, + FT_ULong char_code ); + + + /* charmap table */ + struct TT_CMapTable_ + { + FT_UShort platformID; + FT_UShort platformEncodingID; + FT_UShort format; + FT_UShort length; + FT_UShort version; + + FT_Bool loaded; + FT_ULong offset; + + union + { + TT_CMap0 cmap0; + TT_CMap2 cmap2; + TT_CMap4 cmap4; + TT_CMap6 cmap6; + } c; + + TT_CharMap_Func get_index; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMapRec */ + /* */ + /* */ + /* The TrueType character map object type. */ + /* */ + /* */ + /* root :: The parent character map structure. */ + /* */ + /* cmap :: The used character map. */ + /* */ + typedef struct TT_CharMapRec_ + { + FT_CharMapRec root; + TT_CMapTable cmap; + + } TT_CharMapRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** ORIGINAL TT_FACE CLASS DEFINITION ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This structure/class is defined here because it is common to the */ + /* following formats: TTF, OpenType-TT, and OpenType-CFF. */ + /* */ + /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */ + /* are not shared between font drivers, and are thus defined normally in */ + /* `ttobjs.h'. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Face */ + /* */ + /* */ + /* A handle to a TrueType face/font object. A TT_Face encapsulates */ + /* the resolution and scaling independent parts of a TrueType font */ + /* resource. */ + /* */ + /* */ + /* The TT_Face structure is also used as a `parent class' for the */ + /* OpenType-CFF class (T2_Face). */ + /* */ + typedef struct TT_FaceRec_* TT_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap */ + /* */ + /* */ + /* A handle to a TrueType character mapping object. */ + /* */ + typedef struct TT_CharMapRec_* TT_CharMap; + + + /* a function type used for the truetype bytecode interpreter hooks */ + typedef FT_Error (*TT_Interpreter)( void* exec_context ); + + /* forward declaration */ + typedef struct TT_Loader_ TT_Loader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_Table_Func */ + /* */ + /* */ + /* Seeks a stream to the start of a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* tag :: A 4-byte tag used to name the table. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* length :: The length of the table in bytes. Set to 0 if not */ + /* needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + typedef + FT_Error (*TT_Goto_Table_Func)( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Access_Glyph_Frame_Func */ + /* */ + /* */ + /* Seeks a stream to the start of a given glyph element, and opens a */ + /* frame for it. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* glyph index :: The index of the glyph to access. */ + /* */ + /* offset :: The offset of the glyph according to the */ + /* `locations' table. */ + /* */ + /* byte_count :: The size of the frame in bytes. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function is normally equivalent to FILE_Seek(offset) */ + /* followed by ACCESS_Frame(byte_count) with the loader's stream, but */ + /* alternative formats (e.g. compressed ones) might use something */ + /* different. */ + /* */ + typedef + FT_Error (*TT_Access_Glyph_Frame_Func)( TT_Loader* loader, + FT_UInt glyph_index, + FT_ULong offset, + FT_UInt byte_count ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph_Element_Func */ + /* */ + /* */ + /* Reads one glyph element (its header, a simple glyph, or a */ + /* composite) from the loader's current stream frame. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Glyph_Element_Func)( TT_Loader* loader ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Forget_Glyph_Frame_Func */ + /* */ + /* */ + /* Closes the current loader stream frame for the glyph. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + typedef + void (*TT_Forget_Glyph_Frame_Func)( TT_Loader* loader ); + + + + /*************************************************************************/ + /* */ + /* TrueType Face Type */ + /* */ + /* */ + /* TT_Face */ + /* */ + /* */ + /* The TrueType face class. These objects model the resolution and */ + /* point-size independent data found in a TrueType font file. */ + /* */ + /* */ + /* root :: The base FT_Face structure, managed by the */ + /* base layer. */ + /* */ + /* ttc_header :: The TrueType collection header, used when */ + /* the file is a `ttc' rather than a `ttf'. */ + /* For ordinary font files, the field */ + /* `ttc_header.count' is set to 0. */ + /* */ + /* format_tag :: The font format tag. */ + /* */ + /* num_tables :: The number of TrueType tables in this font */ + /* file. */ + /* */ + /* dir_tables :: The directory of TrueType tables for this */ + /* font file. */ + /* */ + /* header :: The font's font header (`head' table). */ + /* Read on font opening. */ + /* */ + /* horizontal :: The font's horizontal header (`hhea' */ + /* table). This field also contains the */ + /* associated horizontal metrics table */ + /* (`hmtx'). */ + /* */ + /* max_profile :: The font's maximum profile table. Read on */ + /* font opening. Note that some maximum */ + /* values cannot be taken directly from this */ + /* table. We thus define additional fields */ + /* below to hold the computed maxima. */ + /* */ + /* max_components :: The maximum number of glyph components */ + /* required to load any composite glyph from */ + /* this font. Used to size the load stack. */ + /* */ + /* vertical_info :: A boolean which is set when the font file */ + /* contains vertical metrics. If not, the */ + /* value of the `vertical' field is */ + /* undefined. */ + /* */ + /* vertical :: The font's vertical header (`vhea' table). */ + /* This field also contains the associated */ + /* vertical metrics table (`vmtx'), if found. */ + /* IMPORTANT: The contents of this field is */ + /* undefined if the `verticalInfo' field is */ + /* unset. */ + /* */ + /* num_names :: The number of name records within this */ + /* TrueType font. */ + /* */ + /* name_table :: The table of name records (`name'). */ + /* */ + /* os2 :: The font's OS/2 table (`OS/2'). */ + /* */ + /* postscript :: The font's PostScript table (`post' */ + /* table). The PostScript glyph names are */ + /* not loaded by the driver on face opening. */ + /* See the `ttpost' module for more details. */ + /* */ + /* num_charmaps :: The number of character mappings in the */ + /* font. */ + /* */ + /* charmaps :: The array of charmap objects for this font */ + /* file. Note that this field is a typeless */ + /* pointer. The Reason is that the format of */ + /* charmaps varies with the underlying font */ + /* format and cannot be determined here. */ + /* */ + /* goto_table :: A function called by each TrueType table */ + /* loader to position a stream's cursor to */ + /* the start of a given table according to */ + /* its tag. It defaults to TT_Goto_Face but */ + /* can be different for strange formats (e.g. */ + /* Type 42). */ + /* */ + /* access_glyph_frame :: XXX */ + /* */ + /* read_glyph_header :: XXX */ + /* */ + /* read_simple_glyph :: XXX */ + /* */ + /* read_composite_glyph :: XXX */ + /* */ + /* forget_glyph_frame :: XXX */ + /* */ + /* sfnt :: A pointer to the SFNT `driver' interface. */ + /* */ + /* psnames :: A pointer to the `PSNames' module */ + /* interface. */ + /* */ + /* hdmx :: The face's horizontal device metrics */ + /* (`hdmx' table). This table is optional in */ + /* TrueType/OpenType fonts. */ + /* */ + /* gasp :: The grid-fitting and scaling properties */ + /* table (`gasp'). This table is optional in */ + /* TrueType/OpenType fonts. */ + /* */ + /* pclt :: XXX */ + /* */ + /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */ + /* sizes, embedded in this font. */ + /* */ + /* sbit_strikes :: An array of sbit strikes embedded in this */ + /* font. This table is optional in a */ + /* TrueType/OpenType font. */ + /* */ + /* num_sbit_scales :: The number of sbit scales for this font. */ + /* */ + /* sbit_scales :: Array of sbit scales embedded in this */ + /* font. This table is optional in a */ + /* TrueType/OpenType font. */ + /* */ + /* postscript_names :: A table used to store the Postscript names */ + /* of the glyphs for this font. See the */ + /* file `ttconfig.h' for comments on the */ + /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */ + /* */ + /* num_locations :: The number of glyph locations in this */ + /* TrueType file. This should be */ + /* identical to the number of glyphs. */ + /* Ignored for Type 2 fonts. */ + /* */ + /* glyph_locations :: An array of longs. These are offsets to */ + /* glyph data within the `glyf' table. */ + /* Ignored for Type 2 font faces. */ + /* */ + /* font_program_size :: Size in bytecodes of the face's font */ + /* program. 0 if none defined. Ignored for */ + /* Type 2 fonts. */ + /* */ + /* font_program :: The face's font program (bytecode stream) */ + /* executed at load time, also used during */ + /* glyph rendering. Comes from the `fpgm' */ + /* table. Ignored for Type 2 font fonts. */ + /* */ + /* cvt_program_size :: The size in bytecodes of the face's cvt */ + /* program. Ignored for Type 2 fonts. */ + /* */ + /* cvt_program :: The face's cvt program (bytecode stream) */ + /* executed each time an instance/size is */ + /* changed/reset. Comes from the `prep' */ + /* table. Ignored for Type 2 fonts. */ + /* */ + /* cvt_size :: Size of the control value table (in */ + /* entries). Ignored for Type 2 fonts. */ + /* */ + /* cvt :: The face's original control value table. */ + /* Coordinates are expressed in unscaled font */ + /* units. Comes from the `cvt ' table. */ + /* Ignored for Type 2 fonts. */ + /* */ + /* num_kern_pairs :: The number of kerning pairs present in the */ + /* font file. The engine only loads the */ + /* first horizontal format 0 kern table it */ + /* finds in the font file. You should use */ + /* the `ttxkern' structures if you want to */ + /* access other kerning tables. Ignored */ + /* for Type 2 fonts. */ + /* */ + /* kern_table_index :: The index of the kerning table in the font */ + /* kerning directory. Only used by the */ + /* ttxkern extension to avoid data */ + /* duplication. Ignored for Type 2 fonts. */ + /* */ + /* interpreter :: A pointer to the TrueType bytecode */ + /* interpreters field is also used to hook */ + /* the debugger in `ttdebug'. */ + /* */ + /* extra :: XXX */ + /* */ + typedef struct TT_FaceRec_ + { + FT_FaceRec root; + + TTC_Header ttc_header; + + FT_ULong format_tag; + FT_UShort num_tables; + TT_Table* dir_tables; + + TT_Header header; /* TrueType header table */ + TT_HoriHeader horizontal; /* TrueType horizontal header */ + + TT_MaxProfile max_profile; + FT_ULong max_components; + + FT_Bool vertical_info; + TT_VertHeader vertical; /* TT Vertical header, if present */ + + FT_Int num_names; /* number of name records */ + TT_NameTable name_table; /* name table */ + + TT_OS2 os2; /* TrueType OS/2 table */ + TT_Postscript postscript; /* TrueType Postscript table */ + + FT_Int num_charmaps; + TT_CharMap charmaps; /* array of TT_CharMapRec */ + + TT_Goto_Table_Func goto_table; + + TT_Access_Glyph_Frame_Func access_glyph_frame; + TT_Load_Glyph_Element_Func read_glyph_header; + TT_Load_Glyph_Element_Func read_simple_glyph; + TT_Load_Glyph_Element_Func read_composite_glyph; + TT_Forget_Glyph_Frame_Func forget_glyph_frame; + + /* a typeless pointer to the SFNT_Interface table used to load */ + /* the basic TrueType tables in the face object */ + void* sfnt; + + /* a typeless pointer to the PSNames_Interface table used to */ + /* handle glyph names <-> unicode & Mac values */ + void* psnames; + + /***********************************************************************/ + /* */ + /* Optional TrueType/OpenType tables */ + /* */ + /***********************************************************************/ + + /* horizontal device metrics */ + TT_Hdmx hdmx; + + /* grid-fitting and scaling table */ + TT_Gasp gasp; /* the `gasp' table */ + + /* PCL 5 table */ + TT_PCLT pclt; + + /* embedded bitmaps support */ + FT_Int num_sbit_strikes; + TT_SBit_Strike* sbit_strikes; + + FT_Int num_sbit_scales; + TT_SBit_Scale* sbit_scales; + + /* postscript names table */ + TT_Post_Names postscript_names; + + + /***********************************************************************/ + /* */ + /* TrueType-specific fields (ignored by the OTF-Type2 driver) */ + /* */ + /***********************************************************************/ + + /* the glyph locations */ + FT_UShort num_locations; + FT_Long* glyph_locations; + + /* the font program, if any */ + FT_ULong font_program_size; + FT_Byte* font_program; + + /* the cvt program, if any */ + FT_ULong cvt_program_size; + FT_Byte* cvt_program; + + /* the original, unscaled, control value table */ + FT_ULong cvt_size; + FT_Short* cvt; + + /* the format 0 kerning table, if any */ + FT_Int num_kern_pairs; + FT_Int kern_table_index; + TT_Kern_0_Pair* kern_pairs; + + /* A pointer to the bytecode interpreter to use. This is also */ + /* used to hook the debugger for the `ttdebug' utility. */ + TT_Interpreter interpreter; + + + /***********************************************************************/ + /* */ + /* Other tables or fields. This is used by derivative formats like */ + /* OpenType. */ + /* */ + /***********************************************************************/ + + FT_Generic extra; + + } TT_FaceRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GlyphZone */ + /* */ + /* */ + /* A glyph zone is used to load, scale and hint glyph outline */ + /* coordinates. */ + /* */ + /* */ + /* memory :: A handle to the memory manager. */ + /* */ + /* max_points :: The maximal size in points of the zone. */ + /* */ + /* max_contours :: Max size in links contours of thez one. */ + /* */ + /* n_points :: The current number of points in the zone. */ + /* */ + /* n_contours :: The current number of contours in the zone. */ + /* */ + /* org :: The original glyph coordinates (font */ + /* units/scaled). */ + /* */ + /* cur :: The current glyph coordinates (scaled/hinted). */ + /* */ + /* tags :: The point control tags. */ + /* */ + /* contours :: The contours end points. */ + /* */ + typedef struct TT_GlyphZone_ + { + FT_Memory memory; + FT_UShort max_points; + FT_UShort max_contours; + FT_UShort n_points; /* number of points in zone */ + FT_Short n_contours; /* number of contours */ + + FT_Vector* org; /* original point coordinates */ + FT_Vector* cur; /* current point coordinates */ + + FT_Byte* tags; /* current touch flags */ + FT_UShort* contours; /* contour end points */ + + } TT_GlyphZone; + + + /* handle to execution context */ + typedef struct TT_ExecContextRec_* TT_ExecContext; + + /* glyph loader structure */ + struct TT_Loader_ + { + FT_Face face; + FT_Size size; + FT_GlyphSlot glyph; + FT_GlyphLoader* gloader; + + FT_ULong load_flags; + FT_UInt glyph_index; + + FT_Stream stream; + FT_Int byte_len; + + FT_Short n_contours; + FT_BBox bbox; + FT_Int left_bearing; + FT_Int advance; + FT_Bool preserve_pps; + FT_Vector pp1; + FT_Vector pp2; + + FT_ULong glyf_offset; + + /* the zone where we load our glyphs */ + TT_GlyphZone base; + TT_GlyphZone zone; + + TT_ExecContext exec; + FT_Byte* instructions; + FT_ULong ins_pos; + + /* for possible extensibility in other formats */ + void* other; + + }; + + +#endif /* TTTYPES_H */ + + +/* END */ diff --git a/include/freetype/t1tables.h b/include/freetype/t1tables.h new file mode 100644 index 0000000..323e013 --- /dev/null +++ b/include/freetype/t1tables.h @@ -0,0 +1,235 @@ +/***************************************************************************/ +/* */ +/* t1tables.h */ +/* */ +/* Basic Type 1/Type 2 tables definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1TABLES_H +#define T1TABLES_H + + +#include + + + /* Note that we separate font data in T1_FontInfo and T1_Private */ + /* structures in order to support Multiple Master fonts. */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_FontInfo */ + /* */ + /* */ + /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */ + /* that for Multiple Master fonts, each instance has its own */ + /* FontInfo. */ + /* */ + typedef struct T1_FontInfo + { + FT_String* version; + FT_String* notice; + FT_String* full_name; + FT_String* family_name; + FT_String* weight; + FT_Long italic_angle; + FT_Bool is_fixed_pitch; + FT_Short underline_position; + FT_UShort underline_thickness; + + } T1_FontInfo; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Private */ + /* */ + /* */ + /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */ + /* that for Multiple Master fonts, each instance has its own Private */ + /* dict. */ + /* */ + typedef struct T1_Private + { + FT_Int unique_id; + FT_Int lenIV; + + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Short blue_values[14]; + FT_Short other_blues[10]; + + FT_Short family_blues [14]; + FT_Short family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Int blue_shift; + FT_Int blue_fuzz; + + FT_UShort standard_width[1]; + FT_UShort standard_height[1]; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Bool force_bold; + FT_Bool round_stem_up; + + FT_Short snap_widths [13]; /* reserve one place for the std */ + FT_Short snap_heights[13]; /* reserve one place for the std */ + + FT_Long language_group; + FT_Long password; + + FT_Short min_feature[2]; + + } T1_Private; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Blend_Flags */ + /* */ + /* */ + /* A set of flags used to indicate which fields are present in a */ + /* given blen dictionary (font info or private). Used to support */ + /* Multiple Masters fonts. */ + /* */ + typedef enum + { + /* required fields in a FontInfo blend dictionary */ + t1_blend_underline_position = 0, + t1_blend_underline_thickness, + t1_blend_italic_angle, + + /* required fields in a Private blend dictionary */ + t1_blend_blue_values, + t1_blend_other_blues, + t1_blend_standard_width, + t1_blend_standard_height, + t1_blend_stem_snap_widths, + t1_blend_stem_snap_heights, + t1_blend_blue_scale, + t1_blend_blue_shift, + t1_blend_family_blues, + t1_blend_family_other_blues, + t1_blend_force_bold, + + /* never remove */ + t1_blend_max + + } T1_Blend_Flags; + + + /* maximum number of Multiple Masters designs, as defined in the spec */ +#define T1_MAX_MM_DESIGNS 16 + + /* maximum number of Multiple Masters axes, as defined in the spec */ +#define T1_MAX_MM_AXIS 4 + + /* maximum number of elements in a design map */ +#define T1_MAX_MM_MAP_POINTS 20 + + + /* this structure is used to store the BlendDesignMap entry for an axis */ + typedef struct T1_DesignMap_ + { + FT_Byte num_points; + FT_Fixed* design_points; + FT_Fixed* blend_points; + + } T1_DesignMap; + + + typedef struct T1_Blend_ + { + FT_UInt num_designs; + FT_UInt num_axis; + + FT_String* axis_names[T1_MAX_MM_AXIS]; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; + T1_DesignMap design_map[T1_MAX_MM_AXIS]; + + FT_Fixed* weight_vector; + FT_Fixed* default_weight_vector; + + T1_FontInfo* font_infos[T1_MAX_MM_DESIGNS + 1]; + T1_Private* privates [T1_MAX_MM_DESIGNS + 1]; + + FT_ULong blend_bitflags; + + } T1_Blend; + + + typedef struct CID_FontDict_ + { + T1_Private private_dict; + + FT_UInt len_buildchar; + FT_Fixed forcebold_threshold; + FT_Pos stroke_width; + FT_Fixed expansion_factor; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + + FT_UInt num_subrs; + FT_ULong subrmap_offset; + FT_Int sd_bytes; + + } CID_FontDict; + + + typedef struct CID_Info_ + { + FT_String* cid_font_name; + FT_Fixed cid_version; + FT_Int cid_font_type; + + FT_String* registry; + FT_String* ordering; + FT_Int supplement; + + T1_FontInfo font_info; + FT_BBox font_bbox; + FT_ULong uid_base; + + FT_Int num_xuid; + FT_ULong xuid[16]; + + + FT_ULong cidmap_offset; + FT_Int fd_bytes; + FT_Int gd_bytes; + FT_ULong cid_count; + + FT_Int num_dicts; + CID_FontDict* font_dicts; + + FT_ULong data_offset; + + } CID_Info; + + +#endif /* T1TABLES_H */ + + +/* END */ diff --git a/include/freetype/ttnameid.h b/include/freetype/ttnameid.h new file mode 100644 index 0000000..4890242 --- /dev/null +++ b/include/freetype/ttnameid.h @@ -0,0 +1,698 @@ +/***************************************************************************/ +/* */ +/* ttmakeid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTNAMEID_H +#define TTNAMEID_H + + + /*************************************************************************/ + /* */ + /* Possible values for the `platform' identifier code in the name */ + /* records of the TTF `name' table. */ + /* */ +#define TT_PLATFORM_APPLE_UNICODE 0 +#define TT_PLATFORM_MACINTOSH 1 +#define TT_PLATFORM_ISO 2 /* deprecated */ +#define TT_PLATFORM_MICROSOFT 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_APPLE_UNICODE. */ + /* */ +#define TT_APPLE_ID_DEFAULT 0 +#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ +#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ +#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_MACINTOSH. */ + /* */ +#define TT_MAC_ID_ROMAN 0 +#define TT_MAC_ID_JAPANESE 1 +#define TT_MAC_ID_TRADITIONAL_CHINESE 2 +#define TT_MAC_ID_KOREAN 3 +#define TT_MAC_ID_ARABIC 4 +#define TT_MAC_ID_HEBREW 5 +#define TT_MAC_ID_GREEK 6 +#define TT_MAC_ID_RUSSIAN 7 +#define TT_MAC_ID_RSYMBOL 8 +#define TT_MAC_ID_DEVANAGARI 9 +#define TT_MAC_ID_GURMUKHI 10 +#define TT_MAC_ID_GUJARATI 11 +#define TT_MAC_ID_ORIYA 12 +#define TT_MAC_ID_BENGALI 13 +#define TT_MAC_ID_TAMIL 14 +#define TT_MAC_ID_TELUGU 15 +#define TT_MAC_ID_KANNADA 16 +#define TT_MAC_ID_MALAYALAM 17 +#define TT_MAC_ID_SINHALESE 18 +#define TT_MAC_ID_BURMESE 19 +#define TT_MAC_ID_KHMER 20 +#define TT_MAC_ID_THAI 21 +#define TT_MAC_ID_LAOTIAN 22 +#define TT_MAC_ID_GEORGIAN 23 +#define TT_MAC_ID_ARMENIAN 24 +#define TT_MAC_ID_MALDIVIAN 25 +#define TT_MAC_ID_SIMPLIFIED_CHINESE 25 +#define TT_MAC_ID_TIBETAN 26 +#define TT_MAC_ID_MONGOLIAN 27 +#define TT_MAC_ID_GEEZ 28 +#define TT_MAC_ID_SLAVIC 29 +#define TT_MAC_ID_VIETNAMESE 30 +#define TT_MAC_ID_SINDHI 31 +#define TT_MAC_ID_UNINTERP 32 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_ISO. */ + /* */ + /* This use is now deprecated. */ + /* */ +#define TT_ISO_ID_7BIT_ASCII 0 +#define TT_ISO_ID_10646 1 +#define TT_ISO_ID_8859_1 2 + + + /*************************************************************************/ + /* */ + /* possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_MICROSOFT. */ + /* */ +#define TT_MS_ID_SYMBOL_CS 0 +#define TT_MS_ID_UNICODE_CS 1 +#define TT_MS_ID_SJIS 2 +#define TT_MS_ID_GB2312 3 +#define TT_MS_ID_BIG_5 4 +#define TT_MS_ID_WANSUNG 5 +#define TT_MS_ID_JOHAB 6 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MACINTOSH. */ + /* */ + /* The canonical source for the Apple assigned Language ID's is at */ + /* */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */ + /* */ +#define TT_MAC_LANGID_ENGLISH 0 +#define TT_MAC_LANGID_FRENCH 1 +#define TT_MAC_LANGID_GERMAN 2 +#define TT_MAC_LANGID_ITALIAN 3 +#define TT_MAC_LANGID_DUTCH 4 +#define TT_MAC_LANGID_SWEDISH 5 +#define TT_MAC_LANGID_SPANISH 6 +#define TT_MAC_LANGID_DANISH 7 +#define TT_MAC_LANGID_PORTUGUESE 8 +#define TT_MAC_LANGID_NORWEGIAN 9 +#define TT_MAC_LANGID_HEBREW 10 +#define TT_MAC_LANGID_JAPANESE 11 +#define TT_MAC_LANGID_ARABIC 12 +#define TT_MAC_LANGID_FINNISH 13 +#define TT_MAC_LANGID_GREEK 14 +#define TT_MAC_LANGID_ICELANDIC 15 +#define TT_MAC_LANGID_MALTESE 16 +#define TT_MAC_LANGID_TURKISH 17 +#define TT_MAC_LANGID_CROATIAN 18 +#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 +#define TT_MAC_LANGID_URDU 20 +#define TT_MAC_LANGID_HINDI 21 +#define TT_MAC_LANGID_THAI 22 +#define TT_MAC_LANGID_KOREAN 23 +#define TT_MAC_LANGID_LITHUANIAN 24 +#define TT_MAC_LANGID_POLISH 25 +#define TT_MAC_LANGID_HUNGARIAN 26 +#define TT_MAC_LANGID_ESTONIAN 27 +#define TT_MAC_LANGID_LETTISH 28 +#define TT_MAC_LANGID_SAAMISK 29 +#define TT_MAC_LANGID_FAEROESE 30 +#define TT_MAC_LANGID_FARSI 31 +#define TT_MAC_LANGID_RUSSIAN 32 +#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 +#define TT_MAC_LANGID_FLEMISH 34 +#define TT_MAC_LANGID_IRISH 35 +#define TT_MAC_LANGID_ALBANIAN 36 +#define TT_MAC_LANGID_ROMANIAN 37 +#define TT_MAC_LANGID_CZECH 38 +#define TT_MAC_LANGID_SLOVAK 39 +#define TT_MAC_LANGID_SLOVENIAN 40 +#define TT_MAC_LANGID_YIDDISH 41 +#define TT_MAC_LANGID_SERBIAN 42 +#define TT_MAC_LANGID_MACEDONIAN 43 +#define TT_MAC_LANGID_BULGARIAN 44 +#define TT_MAC_LANGID_UKRAINIAN 45 +#define TT_MAC_LANGID_BYELORUSSIAN 46 +#define TT_MAC_LANGID_UZBEK 47 +#define TT_MAC_LANGID_KAZAKH 48 +#define TT_MAC_LANGID_AZERBAIJANI 49 +#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 +#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 +#define TT_MAC_LANGID_ARMENIAN 51 +#define TT_MAC_LANGID_GEORGIAN 52 +#define TT_MAC_LANGID_MOLDAVIAN 53 +#define TT_MAC_LANGID_KIRGHIZ 54 +#define TT_MAC_LANGID_TAJIKI 55 +#define TT_MAC_LANGID_TURKMEN 56 +#define TT_MAC_LANGID_MONGOLIAN 57 +#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 +#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 +#define TT_MAC_LANGID_PASHTO 59 +#define TT_MAC_LANGID_KURDISH 60 +#define TT_MAC_LANGID_KASHMIRI 61 +#define TT_MAC_LANGID_SINDHI 62 +#define TT_MAC_LANGID_TIBETAN 63 +#define TT_MAC_LANGID_NEPALI 64 +#define TT_MAC_LANGID_SANSKRIT 65 +#define TT_MAC_LANGID_MARATHI 66 +#define TT_MAC_LANGID_BENGALI 67 +#define TT_MAC_LANGID_ASSAMESE 68 +#define TT_MAC_LANGID_GUJARATI 69 +#define TT_MAC_LANGID_PUNJABI 70 +#define TT_MAC_LANGID_ORIYA 71 +#define TT_MAC_LANGID_MALAYALAM 72 +#define TT_MAC_LANGID_KANNADA 73 +#define TT_MAC_LANGID_TAMIL 74 +#define TT_MAC_LANGID_TELUGU 75 +#define TT_MAC_LANGID_SINHALESE 76 +#define TT_MAC_LANGID_BURMESE 77 +#define TT_MAC_LANGID_KHMER 78 +#define TT_MAC_LANGID_LAO 79 +#define TT_MAC_LANGID_VIETNAMESE 80 +#define TT_MAC_LANGID_INDONESIAN 81 +#define TT_MAC_LANGID_TAGALOG 82 +#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 +#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 +#define TT_MAC_LANGID_AMHARIC 85 +#define TT_MAC_LANGID_TIGRINYA 86 +#define TT_MAC_LANGID_GALLA 87 +#define TT_MAC_LANGID_SOMALI 88 +#define TT_MAC_LANGID_SWAHILI 89 +#define TT_MAC_LANGID_RUANDA 90 +#define TT_MAC_LANGID_RUNDI 91 +#define TT_MAC_LANGID_CHEWA 92 +#define TT_MAC_LANGID_MALAGASY 93 +#define TT_MAC_LANGID_ESPERANTO 94 +#define TT_MAC_LANGID_WELSH 128 +#define TT_MAC_LANGID_BASQUE 129 +#define TT_MAC_LANGID_CATALAN 130 +#define TT_MAC_LANGID_LATIN 131 +#define TT_MAC_LANGID_QUECHUA 132 +#define TT_MAC_LANGID_GUARANI 133 +#define TT_MAC_LANGID_AYMARA 134 +#define TT_MAC_LANGID_TATAR 135 +#define TT_MAC_LANGID_UIGHUR 136 +#define TT_MAC_LANGID_DZONGKHA 137 +#define TT_MAC_LANGID_JAVANESE 138 +#define TT_MAC_LANGID_SUNDANESE 139 + + +#if 0 /* these seem to be errors that have been dropped */ + +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 + +#endif + + + /* The following codes are new as of 2000-03-10 */ +#define TT_MAC_LANGID_GALICIAN 140 +#define TT_MAC_LANGID_AFRIKAANS 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 144 +#define TT_MAC_LANGID_MANX_GAELIC 145 +#define TT_MAC_LANGID_IRISH_GAELIC 146 +#define TT_MAC_LANGID_TONGAN 147 +#define TT_MAC_LANGID_GREEK_POLYTONIC 148 +#define TT_MAC_LANGID_GREELANDIC 149 +#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MICROSOFT. */ + /* */ + /* The canonical source for the MS assigned LCID's is at */ + /* */ + /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */ + /* */ +#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 +#define TT_MS_LANGID_ARABIC_IRAQ 0x0801 +#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01 +#define TT_MS_LANGID_ARABIC_LIBYA 0x1001 +#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 +#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 +#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01 +#define TT_MS_LANGID_ARABIC_OMAN 0x2001 +#define TT_MS_LANGID_ARABIC_YEMEN 0x2401 +#define TT_MS_LANGID_ARABIC_SYRIA 0x2801 +#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01 +#define TT_MS_LANGID_ARABIC_LEBANON 0x3001 +#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 +#define TT_MS_LANGID_ARABIC_UAE 0x3801 +#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01 +#define TT_MS_LANGID_ARABIC_QATAR 0x4001 +#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 +#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 +#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 +#define TT_MS_LANGID_CHINESE_PRC 0x0804 +#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04 +#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 +#define TT_MS_LANGID_CHINESE_MACAU 0x1404 +#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 +#define TT_MS_LANGID_DANISH_DENMARK 0x0406 +#define TT_MS_LANGID_GERMAN_GERMANY 0x0407 +#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 +#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07 +#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 +#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 +#define TT_MS_LANGID_GREEK_GREECE 0x0408 +#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 +#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 +#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09 +#define TT_MS_LANGID_ENGLISH_CANADA 0x1009 +#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 +#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 +#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09 +#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 +#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 +#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 +#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09 +#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 +#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 +#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a +#define TT_MS_LANGID_SPANISH_MEXICO 0x080a +#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a +#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a +#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a +#define TT_MS_LANGID_SPANISH_PANAMA 0x180a +#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a +#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a +#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a +#define TT_MS_LANGID_SPANISH_PERU 0x280a +#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a +#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a +#define TT_MS_LANGID_SPANISH_CHILE 0x340a +#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a +#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a +#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a +#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a +#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a +#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a +#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a +#define TT_MS_LANGID_FINNISH_FINLAND 0x040b +#define TT_MS_LANGID_FRENCH_FRANCE 0x040c +#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c +#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c +#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c +#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c +#define TT_MS_LANGID_FRENCH_MONACO 0x180c +#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d +#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e +#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f +#define TT_MS_LANGID_ITALIAN_ITALY 0x0410 +#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 +#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 +#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 +#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 +#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 +#define TT_MS_LANGID_POLISH_POLAND 0x0415 +#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 +#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 +#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 +#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 +#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 +#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 +#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 +#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a +#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a +#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a +#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b +#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c +#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d +#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d +#define TT_MS_LANGID_THAI_THAILAND 0x041e +#define TT_MS_LANGID_TURKISH_TURKEY 0x041f +#define TT_MS_LANGID_URDU_PAKISTAN 0x0420 +#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 +#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 +#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 +#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 +#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 +#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 +#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 +#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0428 +#define TT_MS_LANGID_FARSI_IRAN 0x0429 +#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a +#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b +#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c +#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c +#define TT_MS_LANGID_BASQUE_SPAIN 0x042d +#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e +#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f +#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 +#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 +#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 +#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 +#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 +#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 +#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 +#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 +#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 +#define TT_MS_LANGID_HINDI_INDIA 0x0439 +#define TT_MS_LANGID_MALTESE_MALTA 0x043a +#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e +#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e +#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f +#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 +#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 +#define TT_MS_LANGID_BENGALI_INDIA 0x0445 +#define TT_MS_LANGID_PUNJABI_INDIA 0x0446 +#define TT_MS_LANGID_GUJARATI_INDIA 0x0447 +#define TT_MS_LANGID_ORIYA_INDIA 0x0448 +#define TT_MS_LANGID_TAMIL_INDIA 0x0449 +#define TT_MS_LANGID_TELUGU_INDIA 0x044a +#define TT_MS_LANGID_KANNADA_INDIA 0x044b +#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c +#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d +#define TT_MS_LANGID_MARATHI_INDIA 0x044e +#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f +#define TT_MS_LANGID_KONKANI_INDIA 0x0457 + + + /*************************************************************************/ + /* */ + /* Possible values of the `name' identifier field in the name records of */ + /* the TTF `name' table. These values are platform independent. */ + /* */ +#define TT_NAME_ID_COPYRIGHT 0 +#define TT_NAME_ID_FONT_FAMILY 1 +#define TT_NAME_ID_FONT_SUBFAMILY 2 +#define TT_NAME_ID_UNIQUE_ID 3 +#define TT_NAME_ID_FULL_NAME 4 +#define TT_NAME_ID_VERSION_STRING 5 +#define TT_NAME_ID_PS_NAME 6 +#define TT_NAME_ID_TRADEMARK 7 + +/* the following values are from the OpenType spec */ +#define TT_NAME_ID_MANUFACTURER 8 +#define TT_NAME_ID_DESIGNER 9 +#define TT_NAME_ID_DESCRIPTION 10 +#define TT_NAME_ID_VENDOR_URL 11 +#define TT_NAME_ID_DESIGNER_URL 12 +#define TT_NAME_ID_LICENSE 13 +#define TT_NAME_ID_LICENSE_URL 14 +/* number 15 is reserved */ +#define TT_NAME_ID_PREFERRED_FAMILY 16 +#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 +#define TT_NAME_ID_MAC_FULL_NAME 18 + +/* The following code is new as of 2000-01-21 */ +#define TT_NAME_ID_SAMPLE_TEXT 19 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ + /* */ + /* Updated 02-Jul-2000. */ + /* */ + + /* General Scripts Area */ + + /* Bit 0 C0 Controls and Basic Latin */ +#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ + /* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+00A0-U+00FF */ + /* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ + /* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ + /* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ + /* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ + /* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ + /* Bit 7 Greek */ +#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ + /* Bit 8 is reserved (was: Greek Symbols and Coptic) */ + /* Bit 9 Cyrillic */ +#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ + /* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ + /* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ + /* Bit 12 is reserved (was: Hebrew Extended) */ + /* Bit 13 Arabic */ +#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ + /* Bit 14 is reserved (was: Arabic Extended) */ + /* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ + /* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ + /* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ + /* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ + /* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ + /* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ + /* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ + /* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ + /* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ + /* Bit 24 Thai */ +#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ + /* Bit 25 Lao */ +#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ + /* Bit 26 Georgian */ +#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ + /* Bit 27 is reserved (was Georgian Extended) */ + /* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ + /* Bit 29 Latin Extended Additional */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ + /* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ + + /* Symbols Area */ + + /* Bit 31 General Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ + /* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ + /* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ + /* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ + /* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ + /* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ + /* Bit 37 Arrows */ +#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ + /* Bit 38 Mathematical Operators */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ + /* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ + /* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ + /* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ + /* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ + /* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ + /* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ + /* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ + /* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ + /* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ + + /* CJK Phonetics and Symbols Area */ + + /* Bit 48 CJK Symbols And Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ + /* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ + /* Bit 50 Katakana */ +#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ + /* Bit 51 Bopomofo + Extended Bopomofo */ +#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ + /* U+31A0-U+31BF */ + /* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ + /* Bit 53 CJK Miscellaneous */ +#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */ + /* Bit 54 Enclosed CJK Letters And Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ + /* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ + + /* Hangul Syllables Area */ + + /* Bit 56 Hangul */ +#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ + + /* Surrogates Area */ + + /* Bit 57 Surrogates */ +#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DFFF */ + /* Bit 58 is reserved for Unicode SubRanges */ + + /* CJK Ideographs Area */ + + /* Bit 59 CJK Unified Ideographs + */ + /* CJK Radical Supplement + */ + /* Kangxi Radicals + */ + /* Ideographic Description + */ + /* CJK Unified Ideographs Extension A */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ + /* U+2E80-U+2EFF */ + /* U+2F00-U+2FDF */ + /* U+2FF0-U+2FFF */ + /* U+34E0-U+4DB5 */ + + /* Private Use Area */ + + /* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ + + /* Compatibility Area and Specials */ + + /* Bit 61 CJK Compatibility Ideographs */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+F900-U+FAFF */ + /* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ + /* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ + /* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ + /* Bit 65 CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE30-U+FE4F */ + /* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ + /* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ + /* Bit 68 Halfwidth And Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ + /* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ + /* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FCF */ + /* Bit 71 Syriac */ +#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ + /* Bit 72 Thaana */ +#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ + /* Bit 73 Sinhala */ +#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ + /* Bit 74 Myanmar */ +#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ + /* Bit 75 Ethiopic */ +#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+12BF */ + /* Bit 76 Cherokee */ +#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ + /* Bit 77 Canadian Aboriginal Syllabics */ +#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+14DF */ + /* Bit 78 Ogham */ +#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ + /* Bit 79 Runic */ +#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ + /* Bit 80 Khmer */ +#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ + /* Bit 81 Mongolian */ +#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ + /* Bit 82 Braille */ +#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ + /* Bit 83 Yi + Yi Radicals */ +#define TT_UCR_YI (1L << 19) /* U+A000-U+A48C */ + /* U+A490-U+A4CF */ + + + /*************************************************************************/ + /* */ + /* Some compilers have a very limited length of identifiers. */ + /* */ +#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) +#define HAVE_LIMIT_ON_IDENTS +#endif + + +#ifndef HAVE_LIMIT_ON_IDENTS + + + /*************************************************************************/ + /* */ + /* Here some alias #defines in order to be clearer. */ + /* */ + /* These are not always #defined to stay within the 31 character limit */ + /* which some compilers have. */ + /* */ + /* Credits go to Dave Hoo for pointing out that modern */ + /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ + /* If you get a warning with such a compiler, use the -i40 switch. */ + /* */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ + TT_UCR_ARABIC_PRESENTATIONS_A +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ + TT_UCR_ARABIC_PRESENTATIONS_B + +#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ + TT_UCR_COMBINING_DIACRITICS +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ + TT_UCR_COMBINING_DIACRITICS_SYMB + + +#endif /* !HAVE_LIMIT_ON_IDENTS */ + + +#endif /* TTNAMEID_H */ + + +/* END */ diff --git a/include/freetype/tttables.h b/include/freetype/tttables.h new file mode 100644 index 0000000..27c46f3 --- /dev/null +++ b/include/freetype/tttables.h @@ -0,0 +1,583 @@ +/***************************************************************************/ +/* */ +/* tttables.h */ +/* */ +/* Basic SFNT/TrueType tables definitions and interface */ +/* (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTTABLES_H +#define TTTABLES_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Header */ + /* */ + /* */ + /* A structure used to model a TrueType font header table. All */ + /* fields follow the TrueType specification. */ + /* */ + typedef struct TT_Header_ + { + FT_Fixed Table_Version; + FT_Fixed Font_Revision; + + FT_Long CheckSum_Adjust; + FT_Long Magic_Number; + + FT_UShort Flags; + FT_UShort Units_Per_EM; + + FT_Long Created [2]; + FT_Long Modified[2]; + + FT_Short xMin; + FT_Short yMin; + FT_Short xMax; + FT_Short yMax; + + FT_UShort Mac_Style; + FT_UShort Lowest_Rec_PPEM; + + FT_Short Font_Direction; + FT_Short Index_To_Loc_Format; + FT_Short Glyph_Data_Format; + + } TT_Header; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HoriHeader */ + /* */ + /* */ + /* A structure used to model a TrueType horizontal header, the `hhea' */ + /* table, as well as the corresponding horizontal metrics table, */ + /* i.e., the `hmtx' table. */ + /* */ + /* */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of all */ + /* glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoAscender' field */ + /* of the OS/2 table instead if you want */ + /* the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the distance */ + /* from the baseline to the bottom-most of */ + /* all glyph points found in the font. It */ + /* is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Width_Max :: This field is the maximum of all advance */ + /* widths found in the font. It can be */ + /* used to compute the maximum width of an */ + /* arbitrary string of text. */ + /* */ + /* min_Left_Side_Bearing :: The minimum left side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Right_Side_Bearing :: The minimum right side bearing of all */ + /* glyphs within the font. */ + /* */ + /* xMax_Extent :: The maximum horizontal extent (i.e., the */ + /* `width' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* Reserved :: 10 reserved bytes. */ + /* */ + /* metric_Data_Format :: Always 0. */ + /* */ + /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */ + /* table -- this value can be smaller than */ + /* the total number of glyphs in the font. */ + /* */ + /* long_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_HoriHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Width_Max; /* advance width maximum */ + + FT_Short min_Left_Side_Bearing; /* minimum left-sb */ + FT_Short min_Right_Side_Bearing; /* minimum right-sb */ + FT_Short xMax_Extent; /* xmax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_HMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_HoriHeader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_VertHeader */ + /* */ + /* */ + /* A structure used to model a TrueType vertical header, the `vhea' */ + /* table, as well as the corresponding vertical metrics table, i.e., */ + /* the `vmtx' table. */ + /* */ + /* */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of */ + /* all glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoAscender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the */ + /* distance from the baseline to the */ + /* bottom-most of all glyph points found */ + /* in the font. It is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Height_Max :: This field is the maximum of all */ + /* advance heights found in the font. It */ + /* can be used to compute the maximum */ + /* height of an arbitrary string of text. */ + /* */ + /* min_Top_Side_Bearing :: The minimum top side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */ + /* glyphs within the font. */ + /* */ + /* yMax_Extent :: The maximum vertical extent (i.e., the */ + /* `height' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* Reserved :: 10 reserved bytes. */ + /* */ + /* metric_Data_Format :: Always 0. */ + /* */ + /* number_Of_HMetrics :: Number of VMetrics entries in the */ + /* `vmtx' table -- this value can be */ + /* smaller than the total number of glyphs */ + /* in the font. */ + /* */ + /* long_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_VertHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Height_Max; /* advance height maximum */ + + FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + FT_Short yMax_Extent; /* xmax or ymax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_VMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' or `VMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_VertHeader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_OS2 */ + /* */ + /* */ + /* A structure used to model a TrueType OS/2 table. This is the long */ + /* table version. All fields comply to the TrueType specification. */ + /* */ + /* Note that we now support old Mac fonts which do not include an */ + /* OS/2 table. In this case, the `version' field is always set to */ + /* 0xFFFF. */ + /* */ + typedef struct TT_OS2_ + { + FT_UShort version; /* 0x0001 - more or 0xFFFF */ + FT_Short xAvgCharWidth; + FT_UShort usWeightClass; + FT_UShort usWidthClass; + FT_Short fsType; + FT_Short ySubscriptXSize; + FT_Short ySubscriptYSize; + FT_Short ySubscriptXOffset; + FT_Short ySubscriptYOffset; + FT_Short ySuperscriptXSize; + FT_Short ySuperscriptYSize; + FT_Short ySuperscriptXOffset; + FT_Short ySuperscriptYOffset; + FT_Short yStrikeoutSize; + FT_Short yStrikeoutPosition; + FT_Short sFamilyClass; + + FT_Byte panose[10]; + + FT_ULong ulUnicodeRange1; /* Bits 0-31 */ + FT_ULong ulUnicodeRange2; /* Bits 32-63 */ + FT_ULong ulUnicodeRange3; /* Bits 64-95 */ + FT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + FT_Char achVendID[4]; + + FT_UShort fsSelection; + FT_UShort usFirstCharIndex; + FT_UShort usLastCharIndex; + FT_Short sTypoAscender; + FT_Short sTypoDescender; + FT_Short sTypoLineGap; + FT_UShort usWinAscent; + FT_UShort usWinDescent; + + /* only version 1 tables: */ + + FT_ULong ulCodePageRange1; /* Bits 0-31 */ + FT_ULong ulCodePageRange2; /* Bits 32-63 */ + + /* only version 2 tables: */ + + FT_Short sxHeight; + FT_Short sCapHeight; + FT_UShort usDefaultChar; + FT_UShort usBreakChar; + FT_UShort usMaxContext; + + } TT_OS2; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Postscript */ + /* */ + /* */ + /* A structure used to model a TrueType Postscript table. All fields */ + /* comply to the TrueType table. This structure does not reference */ + /* the Postscript glyph names, which can be nevertheless accessed */ + /* with the `ttpost' module. */ + /* */ + typedef struct TT_Postscript_ + { + FT_Fixed FormatType; + FT_Fixed italicAngle; + FT_Short underlinePosition; + FT_Short underlineThickness; + FT_ULong isFixedPitch; + FT_ULong minMemType42; + FT_ULong maxMemType42; + FT_ULong minMemType1; + FT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ttpost.c file. */ + + } TT_Postscript; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_PCLT */ + /* */ + /* */ + /* A structure used to model a TrueType PCLT table. All fields */ + /* comply to the TrueType table. */ + /* */ + typedef struct TT_PCLT_ + { + FT_Fixed Version; + FT_ULong FontNumber; + FT_UShort Pitch; + FT_UShort xHeight; + FT_UShort Style; + FT_UShort TypeFamily; + FT_UShort CapHeight; + FT_UShort SymbolSet; + FT_Char TypeFace[16]; + FT_Char CharacterComplement[8]; + FT_Char FileName[6]; + FT_Char StrokeWeight; + FT_Char WidthType; + FT_Byte SerifStyle; + FT_Byte Reserved; + + } TT_PCLT; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_MaxProfile */ + /* */ + /* */ + /* The maximum profile is a table containing many max values which */ + /* can be used to pre-allocate arrays. This ensures that no memory */ + /* allocation occurs during a glyph load. */ + /* */ + /* */ + /* version :: The version number. */ + /* */ + /* numGlyphs :: The number of glyphs in this TrueType */ + /* font. */ + /* */ + /* maxPoints :: The maximum number of points in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositePoints'. */ + /* */ + /* maxContours :: The maximum number of contours in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositeContours'. */ + /* */ + /* maxCompositePoints :: The maximum number of points in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxPoints'. */ + /* */ + /* maxCompositeContours :: The maximum number of contours in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxContours'. */ + /* */ + /* maxZones :: The maximum number of zones used for */ + /* glyph hinting. */ + /* */ + /* maxTwilightPoints :: The maximum number of points in the */ + /* twilight zone used for glyph hinting. */ + /* */ + /* maxStorage :: The maximum number of elements in the */ + /* storage area used for glyph hinting. */ + /* */ + /* maxFunctionDefs :: The maximum number of function */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxInstructionDefs :: The maximum number of instruction */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxStackElements :: The maximum number of stack elements used */ + /* during bytecode interpretation. */ + /* */ + /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */ + /* used for glyph hinting. */ + /* */ + /* maxComponentElements :: An obscure value related to composite */ + /* glyphs definitions. */ + /* */ + /* maxComponentDepth :: An obscure value related to composite */ + /* glyphs definitions. Probably the maximum */ + /* number of simple glyphs in a composite. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_MaxProfile_ + { + FT_Fixed version; + FT_UShort numGlyphs; + FT_UShort maxPoints; + FT_UShort maxContours; + FT_UShort maxCompositePoints; + FT_UShort maxCompositeContours; + FT_UShort maxZones; + FT_UShort maxTwilightPoints; + FT_UShort maxStorage; + FT_UShort maxFunctionDefs; + FT_UShort maxInstructionDefs; + FT_UShort maxStackElements; + FT_UShort maxSizeOfInstructions; + FT_UShort maxComponentElements; + FT_UShort maxComponentDepth; + + } TT_MaxProfile; + + + typedef enum + { + ft_sfnt_head = 0, + ft_sfnt_maxp = 1, + ft_sfnt_os2 = 2, + ft_sfnt_hhea = 3, + ft_sfnt_vhea = 4, + ft_sfnt_post = 5, + ft_sfnt_pclt = 6, + + sfnt_max /* don't remove */ + + } FT_Sfnt_Tag; + + + /* internal use only */ + typedef void* (*FT_Get_Sfnt_Table_Func)( FT_Face face, + FT_Sfnt_Tag tag ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_Table */ + /* */ + /* */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* */ + /* face :: A handle to the source. */ + /* */ + /* tag :: The index of the SFNT table. */ + /* */ + /* */ + /* A type-less pointer to the table. This will be 0 in case of */ + /* error, or if the corresponding table was not found *OR* loaded */ + /* from the file. */ + /* */ + /* */ + /* The table is owned by the face object and disappears with it. */ + /* */ + /* This function is only useful to access SFNT tables that are loaded */ + /* by the sfnt/truetype/opentype drivers. See FT_Sfnt_tag for a */ + /* list. */ + /* */ + /* You can load any table using the (internal) SFNT_Interface */ + /* structure -- this is available via FT_Get_Module_Interface(). */ + /* */ + FT_EXPORT_DEF( void* ) FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ); + +#ifdef __cplusplus + } +#endif + + +#endif /* TTTABLES_H */ + + +/* END */ diff --git a/include/freetype/tttags.h b/include/freetype/tttags.h new file mode 100644 index 0000000..9de9810 --- /dev/null +++ b/include/freetype/tttags.h @@ -0,0 +1,66 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType tables (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTAGS_H +#define TTAGS_H + + +#include /* for MAKE_TT_TAG() */ + + +#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' ) +#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' ) +#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' ) +#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' ) +#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' ) +#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' ) +#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' ) +#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' ) +#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' ) +#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' ) +#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' ) +#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' ) +#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' ) +#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) +#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' ) +#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' ) +#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' ) +#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' ) +#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' ) +#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' ) +#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' ) +#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' ) +#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' ) +#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' ) +#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' ) +#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' ) +#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) +#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' ) +#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' ) +#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' ) +#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) +#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) +#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' ) +#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' ) +#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' ) +#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' ) + +#endif /* TTAGS_H */ + + +/* END */ diff --git a/include/funcs.h b/include/funcs.h new file mode 100644 index 0000000..1d0902f --- /dev/null +++ b/include/funcs.h @@ -0,0 +1,7594 @@ +/* + Functions.h + + Declarations for all the Windows32 API Functions + + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + + Author: Scott Christley + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNU_H_WINDOWS32_FUNCTIONS +#define _GNU_H_WINDOWS32_FUNCTIONS + +#ifndef WIN32_LEAN_AND_MEAN + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These functions were a real pain, having to figure out which + had Unicode/Ascii versions and which did not */ + +#ifndef UNICODE_ONLY +#include +#endif /* !UNICODE_ONLY */ + +#ifndef ANSI_ONLY +#include +#endif /* !ANSI_ONLY */ + +/* Define the approprate declaration based upon UNICODE or ASCII */ + +/* UNICODE */ +#ifdef UNICODE + +#define RegConnectRegistry RegConnectRegistryW +#define RegCreateKey RegCreateKeyW +#define RegCreateKeyEx RegCreateKeyExW +#define RegDeleteKey RegDeleteKeyW +#define RegDeleteValue RegDeleteValueW +#define RegEnumKey RegEnumKeyW +#define RegEnumKeyEx RegEnumKeyExW +#define RegEnumValue RegEnumValueW +#define RegLoadKey RegLoadKeyW +#define RegOpenKey RegOpenKeyW +#define RegOpenKeyEx RegOpenKeyExW +#define RegQueryInfoKey RegQueryInfoKeyW +#define RegQueryValue RegQueryValueW +#define RegQueryMultipleValues RegQueryMultipleValuesW +#define RegQueryValueEx RegQueryValueExW +#define RegReplaceKey RegReplaceKeyW +#define RegRestoreKey RegRestoreKeyW +#define RegSaveKey RegSaveKeyW +#define RegSetValue RegSetValueW +#define RegSetValueEx RegSetValueExW +#define AbortSystemShutdown AbortSystemShutdownW +#define InitiateSystemShutdown InitiateSystemShutdownW +#define RegUnLoadKey RegUnLoadKeyW +#define SetProp SetPropW +#define GetProp GetPropW +#define RemoveProp RemovePropW +#define EnumPropsEx EnumPropsExW +#define EnumProps EnumPropsW +#define SetWindowText SetWindowTextW +#define GetWindowText GetWindowTextW +#define GetWindowTextLength GetWindowTextLengthW +#define MessageBox MessageBoxW +#define MessageBoxEx MessageBoxExW +#define MessageBoxIndirect MessageBoxIndirectW +#define GetWindowLong GetWindowLongW +#define SetWindowLong SetWindowLongW +#define GetClassLong GetClassLongW +#define SetClassLong SetClassLongW +#define FindWindow FindWindowW +#define FindWindowEx FindWindowExW +#define GetClassName GetClassNameW +#define SetWindowsHookEx SetWindowsHookExW +#define LoadBitmap LoadBitmapW +#define LoadCursor LoadCursorW +#define LoadCursorFromFile LoadCursorFromFileW +#define LoadIcon LoadIconW +#define LoadImage LoadImageW +#define LoadString LoadStringW +#define IsDialogMessage IsDialogMessageW +#define DlgDirList DlgDirListW +#define DlgDirSelectEx DlgDirSelectExW +#define DlgDirListComboBox DlgDirListComboBoxW +#define DlgDirSelectComboBoxEx DlgDirSelectComboBoxExW +#define DefFrameProc DefFrameProcW +#define DefMDIChildProc DefMDIChildProcW +#define CreateMDIWindow CreateMDIWindowW +#define WinHelp WinHelpW +#define ChangeDisplaySettings ChangeDisplaySettingsW +#define EnumDisplaySettings EnumDisplaySettingsW +#define SystemParametersInfo SystemParametersInfoW +#define AddFontResource AddFontResourceW +#define CopyMetaFile CopyMetaFileW +#define CreateDC CreateDCW +#define CreateFontIndirect CreateFontIndirectW +#define CreateFont CreateFontW +#define CreateIC CreateICW +#define CreateMetaFile CreateMetaFileW +#define CreateScalableFontResource CreateScalableFontResourceW +#define DeviceCapabilities DeviceCapabilitiesW +#define EnumFontFamiliesEx EnumFontFamiliesExW +#define EnumFontFamilies EnumFontFamiliesW +#define EnumFonts EnumFontsW +#define GetCharWidth GetCharWidthW +#define GetCharWidth32 GetCharWidth32W +#define GetCharWidthFloat GetCharWidthFloatW +#define GetCharABCWidths GetCharABCWidthsW +#define GetCharABCWidthsFloat GetCharABCWidthsFloatW +#define GetGlyphOutline GetGlyphOutlineW +#define GetMetaFile GetMetaFileW +#define GetOutlineTextMetrics GetOutlineTextMetricsW +#define GetTextExtentPoint GetTextExtentPointW +#define GetTextExtentPoint32 GetTextExtentPoint32W +#define GetTextExtentExPoint GetTextExtentExPointW +#define GetCharacterPlacement GetCharacterPlacementW +#define ResetDC ResetDCW +#define RemoveFontResource RemoveFontResourceW +#define CopyEnhMetaFile CopyEnhMetaFileW +#define CreateEnhMetaFile CreateEnhMetaFileW +#define GetEnhMetaFile GetEnhMetaFileW +#define GetEnhMetaFileDescription GetEnhMetaFileDescriptionW +#define GetTextMetrics GetTextMetricsW +#define StartDoc StartDocW +#define GetObject GetObjectW +#define TextOut TextOutW +#define ExtTextOut ExtTextOutW +#define PolyTextOut PolyTextOutW +#define GetTextFace GetTextFaceW +#define GetKerningPairs GetKerningPairsW +#define GetLogColorSpace GetLogColorSpaceW +#define CreateColorSpace CreateColorSpaceW +#define GetICMProfile GetICMProfileW +#define SetICMProfile SetICMProfileW +#define UpdateICMRegKey UpdateICMRegKeyW +#define EnumICMProfiles EnumICMProfilesW +#define CreatePropertySheetPage CreatePropertySheetPageW +#define PropertySheet PropertySheetW +#define ImageList_LoadImage ImageList_LoadImageW +#define CreateStatusWindow CreateStatusWindowW +#define DrawStatusText DrawStatusTextW +#define GetOpenFileName GetOpenFileNameW +#define GetSaveFileName GetSaveFileNameW +#define GetFileTitle GetFileTitleW +#define ChooseColor ChooseColorW +#define FindText FindTextW +#define ReplaceText ReplaceTextW +#define ChooseFont ChooseFontW +#define PrintDlg PrintDlgW +#define PageSetupDlg PageSetupDlgW +#define DefWindowProc DefWindowProcW +#define CallWindowProc CallWindowProcW +#define RegisterClass RegisterClassW +#define UnregisterClass UnregisterClassW +#define GetClassInfo GetClassInfoW +#define RegisterClassEx RegisterClassExW +#define GetClassInfoEx GetClassInfoExW +#define CreateWindowEx CreateWindowExW +#define CreateWindow CreateWindowW +#define CreateDialogParam CreateDialogParamW +#define CreateDialogIndirectParam CreateDialogIndirectParamW +#define CreateDialog CreateDialogW +#define CreateDialogIndirect CreateDialogIndirectW +#define DialogBoxParam DialogBoxParamW +#define DialogBoxIndirectParam DialogBoxIndirectParamW +#define DialogBox DialogBoxW +#define DialogBoxIndirect DialogBoxIndirectW +#define RegisterClipboardFormat RegisterClipboardFormatW +#define SetDlgItemText SetDlgItemTextW +#define GetDlgItemText GetDlgItemTextW +#define SendDlgItemMessage SendDlgItemMessageW +#define DefDlgProc DefDlgProcW +#define CallMsgFilter CallMsgFilterW +#define GetClipboardFormatName GetClipboardFormatNameW +#define CharToOem CharToOemW +#define OemToChar OemToCharW +#define CharToOemBuff CharToOemBuffW +#define OemToCharBuff OemToCharBuffW +#define CharUpper CharUpperW +#define CharUpperBuff CharUpperBuffW +#define CharLower CharLowerW +#define CharLowerBuff CharLowerBuffW +#define CharNext CharNextW +#define CharPrev CharPrevW +#define IsCharAlpha IsCharAlphaW +#define IsCharAlphaNumeric IsCharAlphaNumericW +#define IsCharUpper IsCharUpperW +#define IsCharLower IsCharLowerW +#define GetKeyNameText GetKeyNameTextW +#define VkKeyScan VkKeyScanW +#define VkKeyScanEx VkKeyScanExW +#define MapVirtualKey MapVirtualKeyW +#define MapVirtualKeyEx MapVirtualKeyExW +#define LoadAccelerators LoadAcceleratorsW +#define CreateAcceleratorTable CreateAcceleratorTableW +#define CopyAcceleratorTable CopyAcceleratorTableW +#define TranslateAccelerator TranslateAcceleratorW +#define LoadMenu LoadMenuW +#define LoadMenuIndirect LoadMenuIndirectW +#define ChangeMenu ChangeMenuW +#define GetMenuString GetMenuStringW +#define InsertMenu InsertMenuW +#define AppendMenu AppendMenuW +#define ModifyMenu ModifyMenuW +#define InsertMenuItem InsertMenuItemW +#define GetMenuItemInfo GetMenuItemInfoW +#define SetMenuItemInfo SetMenuItemInfoW +#define DrawText DrawTextW +#define DrawTextEx DrawTextExW +#define GrayString GrayStringW +#define DrawState DrawStateW +#define TabbedTextOut TabbedTextOutW +#define GetTabbedTextExtent GetTabbedTextExtentW +#define GetVersionEx GetVersionExW +#define wvsprintf wvsprintfW +#define wsprintf wsprintfW +#define LoadKeyboardLayout LoadKeyboardLayoutW +#define GetKeyboardLayoutName GetKeyboardLayoutNameW +#define CreateDesktop CreateDesktopW +#define OpenDesktop OpenDesktopW +#define EnumDesktops EnumDesktopsW +#define CreateWindowStation CreateWindowStationW +#define OpenWindowStation OpenWindowStationW +#define EnumWindowStations EnumWindowStationsW +#define IsBadStringPtr IsBadStringPtrW +#define LookupAccountSid LookupAccountSidW +#define LookupAccountName LookupAccountNameW +#define LookupPrivilegeValue LookupPrivilegeValueW +#define LookupPrivilegeName LookupPrivilegeNameW +#define LookupPrivilegeDisplayName LookupPrivilegeDisplayNameW +#define BuildCommDCB BuildCommDCBW +#define BuildCommDCBAndTimeouts BuildCommDCBAndTimeoutsW +#define CommConfigDialog CommConfigDialogW +#define GetDefaultCommConfig GetDefaultCommConfigW +#define SetDefaultCommConfig SetDefaultCommConfigW +#define GetComputerName GetComputerNameW +#define SetComputerName SetComputerNameW +#define GetUserName GetUserNameW +#define CreateMailslot CreateMailslotW +#define FormatMessage FormatMessageW +#define GetEnvironmentStrings GetEnvironmentStringsW +#define FreeEnvironmentStrings FreeEnvironmentStringsW +#define lstrcmp lstrcmpW +#define lstrcmpi lstrcmpiW +#define lstrcpyn lstrcpynW +#define lstrcpy lstrcpyW +#define lstrcat lstrcatW +#define lstrlen lstrlenW +#define GetBinaryType GetBinaryTypeW +#define GetShortPathName GetShortPathNameW +#define SetFileSecurity SetFileSecurityW +#define GetFileSecurity GetFileSecurityW +#define FindFirstChangeNotification FindFirstChangeNotificationW +#define AccessCheckAndAuditAlarm AccessCheckAndAuditAlarmW +#define ObjectOpenAuditAlarm ObjectOpenAuditAlarmW +#define ObjectPrivilegeAuditAlarm ObjectPrivilegeAuditAlarmW +#define ObjectCloseAuditAlarm ObjectCloseAuditAlarmW +#define PrivilegedServiceAuditAlarm PrivilegedServiceAuditAlarmW +#define OpenEventLog OpenEventLogW +#define RegisterEventSource RegisterEventSourceW +#define OpenBackupEventLog OpenBackupEventLogW +#define ReadEventLog ReadEventLogW +#define ReportEvent ReportEventW +#define CreateProcess CreateProcessW +#define FatalAppExit FatalAppExitW +#define GetStartupInfo GetStartupInfoW +#define GetEnvironmentVariable GetEnvironmentVariableW +#define GetCommandLine GetCommandLineW +#define SetEnvironmentVariable SetEnvironmentVariableW +#define ExpandEnvironmentStrings ExpandEnvironmentStringsW +#define OutputDebugString OutputDebugStringW +#define FindResource FindResourceW +#define FindResourceEx FindResourceExW +#define EnumResourceTypes EnumResourceTypesW +#define EnumResourceNames EnumResourceNamesW +#define EnumResourceLanguages EnumResourceLanguagesW +#define BeginUpdateResource BeginUpdateResourceW +#define UpdateResource UpdateResourceW +#define EndUpdateResource EndUpdateResourceW +#define GlobalAddAtom GlobalAddAtomW +#define GlobalFindAtom GlobalFindAtomW +#define GlobalGetAtomName GlobalGetAtomNameW +#define AddAtom AddAtomW +#define FindAtom FindAtomW +#define GetAtomName GetAtomNameW +#define GetProfileInt GetProfileIntW +#define GetProfileString GetProfileStringW +#define WriteProfileString WriteProfileStringW +#define GetProfileSection GetProfileSectionW +#define WriteProfileSection WriteProfileSectionW +#define GetPrivateProfileInt GetPrivateProfileIntW +#define GetPrivateProfileString GetPrivateProfileStringW +#define WritePrivateProfileString WritePrivateProfileStringW +#define GetPrivateProfileSection GetPrivateProfileSectionW +#define WritePrivateProfileSection WritePrivateProfileSectionW +#define GetDriveType GetDriveTypeW +#define GetSystemDirectory GetSystemDirectoryW +#define GetTempPath GetTempPathW +#define GetTempFileName GetTempFileNameW +#define GetWindowsDirectory GetWindowsDirectoryW +#define SetCurrentDirectory SetCurrentDirectoryW +#define GetCurrentDirectory GetCurrentDirectoryW +#define GetDiskFreeSpace GetDiskFreeSpaceW +#define GetDiskFreeSpaceEx GetDiskFreeSpaceExW +#define CreateDirectory CreateDirectoryW +#define CreateDirectoryEx CreateDirectoryExW +#define RemoveDirectory RemoveDirectoryW +#define GetFullPathName GetFullPathNameW +#define DefineDosDevice DefineDosDeviceW +#define QueryDosDevice QueryDosDeviceW +#define CreateFile CreateFileW +#define SetFileAttributes SetFileAttributesW +#define GetFileAttributes GetFileAttributesW +#define GetCompressedFileSize GetCompressedFileSizeW +#define DeleteFile DeleteFileW +#define FindFirstFileEx FindFirstFileExW +#define FindFirstFile FindFirstFileW +#define FindNextFile FindNextFileW +#define SearchPath SearchPathW +#define CopyFile CopyFileW +#define MoveFile MoveFileW +#define MoveFileEx MoveFileExW +#define CreateNamedPipe CreateNamedPipeW +#define GetNamedPipeHandleState GetNamedPipeHandleStateW +#define CallNamedPipe CallNamedPipeW +#define WaitNamedPipe WaitNamedPipeW +#define SetVolumeLabel SetVolumeLabelW +#define GetVolumeInformation GetVolumeInformationW +#define ClearEventLog ClearEventLogW +#define BackupEventLog BackupEventLogW +#define CreateMutex CreateMutexW +#define OpenMutex OpenMutexW +#define CreateEvent CreateEventW +#define OpenEvent OpenEventW +#define CreateSemaphore CreateSemaphoreW +#define OpenSemaphore OpenSemaphoreW +#define CreateFileMapping CreateFileMappingW +#define OpenFileMapping OpenFileMappingW +#define GetLogicalDriveStrings GetLogicalDriveStringsW +#define LoadLibrary LoadLibraryW +#define LoadLibraryEx LoadLibraryExW +#define GetModuleFileName GetModuleFileNameW +#define GetModuleHandle GetModuleHandleW +#define GetUserObjectInformation GetUserObjectInformationW +#define SetUserObjectInformation SetUserObjectInformationW +#define RegisterWindowMessage RegisterWindowMessageW +#define GetMessage GetMessageW +#define DispatchMessage DispatchMessageW +#define PeekMessage PeekMessageW +#define SendMessage SendMessageW +#define SendMessageTimeout SendMessageTimeoutW +#define SendNotifyMessage SendNotifyMessageW +#define SendMessageCallback SendMessageCallbackW +#define PostMessage PostMessageW +#define PostThreadMessage PostThreadMessageW +#define VerFindFile VerFindFileW +#define VerInstallFile VerInstallFileW +#define GetFileVersionInfoSize GetFileVersionInfoSizeW +#define GetFileVersionInfo GetFileVersionInfoW +#define VerLanguageName VerLanguageNameW +#define VerQueryValue VerQueryValueW +#define CompareString CompareStringW +#define LCMapString LCMapStringW +#define GetLocaleInfo GetLocaleInfoW +#define SetLocaleInfo SetLocaleInfoW +#define GetTimeFormat GetTimeFormatW +#define GetDateFormat GetDateFormatW +#define GetNumberFormat GetNumberFormatW +#define GetCurrencyFormat GetCurrencyFormatW +#define EnumCalendarInfo EnumCalendarInfoW +#define EnumTimeFormats EnumTimeFormatsW +#define FoldString FoldStringW +#define EnumSystemCodePages EnumSystemCodePagesW +#define EnumSystemLocales EnumSystemLocalesW +#define GetStringTypeEx GetStringTypeExW +#define EnumDateFormats EnumDateFormatsW +#define GetConsoleTitle GetConsoleTitleW +#define ScrollConsoleScreenBuffer ScrollConsoleScreenBufferW +#define SetConsoleTitle SetConsoleTitleW +#define ReadConsole ReadConsoleW +#define WriteConsole WriteConsoleW +#define PeekConsoleInput PeekConsoleInputW +#define ReadConsoleInput ReadConsoleInputW +#define WriteConsoleInput WriteConsoleInputW +#define ReadConsoleOutput ReadConsoleOutputW +#define WriteConsoleOutput WriteConsoleOutputW +#define ReadConsoleOutputCharacter ReadConsoleOutputCharacterW +#define WriteConsoleOutputCharacter WriteConsoleOutputCharacterW +#define FillConsoleOutputCharacter FillConsoleOutputCharacterW +#define WNetGetProviderName WNetGetProviderNameW +#define WNetGetNetworkInformation WNetGetNetworkInformationW +#define WNetGetLastError WNetGetLastErrorW +#define MultinetGetConnectionPerformance MultinetGetConnectionPerformanceW +#define WNetConnectionDialog1 WNetConnectionDialog1W +#define WNetDisconnectDialog1 WNetDisconnectDialog1W +#define WNetOpenEnum WNetOpenEnumW +#define WNetEnumResource WNetEnumResourceW +#define WNetGetUniversalName WNetGetUniversalNameW +#define WNetGetUser WNetGetUserW +#define WNetAddConnection WNetAddConnectionW +#define WNetAddConnection2 WNetAddConnection2W +#define WNetAddConnection3 WNetAddConnection3W +#define WNetCancelConnection WNetCancelConnectionW +#define WNetCancelConnection2 WNetCancelConnection2W +#define WNetGetConnection WNetGetConnectionW +#define WNetUseConnection WNetUseConnectionW +#define WNetSetConnection WNetSetConnectionW +#define CreateService CreateServiceW +#define ChangeServiceConfig ChangeServiceConfigW +#define EnumDependentServices EnumDependentServicesW +#define EnumServicesStatus EnumServicesStatusW +#define GetServiceKeyName GetServiceKeyNameW +#define GetServiceDisplayName GetServiceDisplayNameW +#define OpenSCManager OpenSCManagerW +#define OpenService OpenServiceW +#define QueryServiceConfig QueryServiceConfigW +#define QueryServiceLockStatus QueryServiceLockStatusW +#define RegisterServiceCtrlHandler RegisterServiceCtrlHandlerW +#define StartServiceCtrlDispatcher StartServiceCtrlDispatcherW +#define StartService StartServiceW +#define DragQueryFile DragQueryFileW +#define ExtractAssociatedIcon ExtractAssociatedIconW +#define ExtractIcon ExtractIconW +#define FindExecutable FindExecutableW +#define ShellAbout ShellAboutW +#define ShellExecute ShellExecuteW +#define DdeCreateStringHandle DdeCreateStringHandleW +#define DdeInitialize DdeInitializeW +#define DdeQueryString DdeQueryStringW +#define LogonUser LogonUserW +#define CreateProcessAsUser CreateProcessAsUserW + +/* ASCII */ +#else + +#define RegConnectRegistry RegConnectRegistryA +#define RegCreateKey RegCreateKeyA +#define RegCreateKeyEx RegCreateKeyExA +#define RegDeleteKey RegDeleteKeyA +#define RegDeleteValue RegDeleteValueA +#define RegEnumKey RegEnumKeyA +#define RegEnumKeyEx RegEnumKeyExA +#define RegEnumValue RegEnumValueA +#define RegLoadKey RegLoadKeyA +#define RegOpenKey RegOpenKeyA +#define RegOpenKeyEx RegOpenKeyExA +#define RegQueryInfoKey RegQueryInfoKeyA +#define RegQueryValue RegQueryValueA +#define RegQueryMultipleValues RegQueryMultipleValuesA +#define RegQueryValueEx RegQueryValueExA +#define RegReplaceKey RegReplaceKeyA +#define RegRestoreKey RegRestoreKeyA +#define RegSaveKey RegSaveKeyA +#define RegSetValue RegSetValueA +#define RegSetValueEx RegSetValueExA +#define AbortSystemShutdown AbortSystemShutdownA +#define InitiateSystemShutdown InitiateSystemShutdownA +#define RegUnLoadKey RegUnLoadKeyA +#define LoadIcon LoadIconA +#define LoadImage LoadImageA +#define LoadString LoadStringA +#define IsDialogMessage IsDialogMessageA +#define DlgDirList DlgDirListA +#define DlgDirSelectEx DlgDirSelectExA +#define DlgDirListComboBox DlgDirListComboBoxA +#define DlgDirSelectComboBoxEx DlgDirSelectComboBoxExA +#define DefFrameProc DefFrameProcA +#define DefMDIChildProc DefMDIChildProcA +#define CreateMDIWindow CreateMDIWindowA +#define WinHelp WinHelpA +#define ChangeDisplaySettings ChangeDisplaySettingsA +#define EnumDisplaySettings EnumDisplaySettingsA +#define SystemParametersInfo SystemParametersInfoA +#define GetWindowLong GetWindowLongA +#define SetWindowLong SetWindowLongA +#define GetClassLong GetClassLongA +#define SetClassLong SetClassLongA +#define FindWindow FindWindowA +#define FindWindowEx FindWindowExA +#define GetClassName GetClassNameA +#define SetWindowsHookEx SetWindowsHookExA +#define LoadBitmap LoadBitmapA +#define LoadCursor LoadCursorA +#define LoadCursorFromFile LoadCursorFromFileA +#define SetProp SetPropA +#define GetProp GetPropA +#define RemoveProp RemovePropA +#define EnumPropsEx EnumPropsExA +#define EnumProps EnumPropsA +#define SetWindowText SetWindowTextA +#define GetWindowText GetWindowTextA +#define GetWindowTextLength GetWindowTextLengthA +#define MessageBox MessageBoxA +#define MessageBoxEx MessageBoxExA +#define MessageBoxIndirect MessageBoxIndirectA +#define AddFontResource AddFontResourceA +#define CopyMetaFile CopyMetaFileA +#define CreateDC CreateDCA +#define CreateFontIndirect CreateFontIndirectA +#define CreateFont CreateFontA +#define CreateIC CreateICA +#define CreateMetaFile CreateMetaFileA +#define CreateScalableFontResource CreateScalableFontResourceA +#define DeviceCapabilities DeviceCapabilitiesA +#define EnumFontFamiliesEx EnumFontFamiliesExA +#define EnumFontFamilies EnumFontFamiliesA +#define EnumFonts EnumFontsA +#define GetCharWidth GetCharWidthA +#define GetCharWidth32 GetCharWidth32A +#define GetCharWidthFloat GetCharWidthFloatA +#define GetCharABCWidths GetCharABCWidthsA +#define GetCharABCWidthsFloat GetCharABCWidthsFloatA +#define GetGlyphOutline GetGlyphOutlineA +#define GetMetaFile GetMetaFileA +#define GetOutlineTextMetrics GetOutlineTextMetricsA +#define GetTextExtentPoint GetTextExtentPointA +#define GetTextExtentPoint32 GetTextExtentPoint32A +#define GetTextExtentExPoint GetTextExtentExPointA +#define GetCharacterPlacement GetCharacterPlacementA +#define ResetDC ResetDCA +#define RemoveFontResource RemoveFontResourceA +#define CopyEnhMetaFile CopyEnhMetaFileA +#define CreateEnhMetaFile CreateEnhMetaFileA +#define GetEnhMetaFile GetEnhMetaFileA +#define GetEnhMetaFileDescription GetEnhMetaFileDescriptionA +#define GetTextMetrics GetTextMetricsA +#define StartDoc StartDocA +#define GetObject GetObjectA +#define TextOut TextOutA +#define ExtTextOut ExtTextOutA +#define PolyTextOut PolyTextOutA +#define GetTextFace GetTextFaceA +#define GetKerningPairs GetKerningPairsA +#define GetLogColorSpace GetLogColorSpaceA +#define CreateColorSpace CreateColorSpaceA +#define GetICMProfile GetICMProfileA +#define SetICMProfile SetICMProfileA +#define UpdateICMRegKey UpdateICMRegKeyA +#define EnumICMProfiles EnumICMProfilesA +#define CreatePropertySheetPage CreatePropertySheetPageA +#define PropertySheet PropertySheetA +#define ImageList_LoadImage ImageList_LoadImageA +#define CreateStatusWindow CreateStatusWindowA +#define DrawStatusText DrawStatusTextA +#define GetOpenFileName GetOpenFileNameA +#define GetSaveFileName GetSaveFileNameA +#define GetFileTitle GetFileTitleA +#define ChooseColor ChooseColorA +#define FindText FindTextA +#define ReplaceText ReplaceTextA +#define ChooseFont ChooseFontA +#define PrintDlg PrintDlgA +#define PageSetupDlg PageSetupDlgA +#define DefWindowProc DefWindowProcA +#define CallWindowProc CallWindowProcA +#define RegisterClass RegisterClassA +#define UnregisterClass UnregisterClassA +#define GetClassInfo GetClassInfoA +#define RegisterClassEx RegisterClassExA +#define GetClassInfoEx GetClassInfoExA +#define CreateWindowEx CreateWindowExA +#define CreateWindow CreateWindowA +#define CreateDialogParam CreateDialogParamA +#define CreateDialogIndirectParam CreateDialogIndirectParamA +#define CreateDialog CreateDialogA +#define CreateDialogIndirect CreateDialogIndirectA +#define CreateWaitableTimer CreateWaitableTimerA +#define DialogBoxParam DialogBoxParamA +#define DialogBoxIndirectParam DialogBoxIndirectParamA +#define DialogBox DialogBoxA +#define DialogBoxIndirect DialogBoxIndirectA +#define RegisterClipboardFormat RegisterClipboardFormatA +#define SetDlgItemText SetDlgItemTextA +#define GetDlgItemText GetDlgItemTextA +#define SendDlgItemMessage SendDlgItemMessageA +#define DefDlgProc DefDlgProcA +#define CallMsgFilter CallMsgFilterA +#define GetClipboardFormatName GetClipboardFormatNameA +#define CharToOem CharToOemA +#define OemToChar OemToCharA +#define CharToOemBuff CharToOemBuffA +#define OemToCharBuff OemToCharBuffA +#define CharUpper CharUpperA +#define CharUpperBuff CharUpperBuffA +#define CharLower CharLowerA +#define CharLowerBuff CharLowerBuffA +#define CharNext CharNextA +#define CharPrev CharPrevA +#define IsCharAlpha IsCharAlphaA +#define IsCharAlphaNumeric IsCharAlphaNumericA +#define IsCharUpper IsCharUpperA +#define IsCharLower IsCharLowerA +#define GetKeyNameText GetKeyNameTextA +#define VkKeyScan VkKeyScanA +#define VkKeyScanEx VkKeyScanExA +#define MapVirtualKey MapVirtualKeyA +#define MapVirtualKeyEx MapVirtualKeyExA +#define LoadAccelerators LoadAcceleratorsA +#define CreateAcceleratorTable CreateAcceleratorTableA +#define CopyAcceleratorTable CopyAcceleratorTableA +#define TranslateAccelerator TranslateAcceleratorA +#define LoadMenu LoadMenuA +#define LoadMenuIndirect LoadMenuIndirectA +#define ChangeMenu ChangeMenuA +#define GetMenuString GetMenuStringA +#define InsertMenu InsertMenuA +#define AppendMenu AppendMenuA +#define ModifyMenu ModifyMenuA +#define InsertMenuItem InsertMenuItemA +#define GetMenuItemInfo GetMenuItemInfoA +#define SetMenuItemInfo SetMenuItemInfoA +#define DrawText DrawTextA +#define DrawTextEx DrawTextExA +#define GrayString GrayStringA +#define DrawState DrawStateA +#define TabbedTextOut TabbedTextOutA +#define GetTabbedTextExtent GetTabbedTextExtentA +#define GetVersionEx GetVersionExA +#define wvsprintf wvsprintfA +#define wsprintf wsprintfA +#define LoadKeyboardLayout LoadKeyboardLayoutA +#define GetKeyboardLayoutName GetKeyboardLayoutNameA +#define CreateDesktop CreateDesktopA +#define OpenDesktop OpenDesktopA +#define EnumDesktops EnumDesktopsA +#define CreateWindowStation CreateWindowStationA +#define OpenWindowStation OpenWindowStationA +#define EnumWindowStations EnumWindowStationsA +#define IsBadStringPtr IsBadStringPtrA +#define LookupAccountSid LookupAccountSidA +#define LookupAccountName LookupAccountNameA +#define LookupPrivilegeValue LookupPrivilegeValueA +#define LookupPrivilegeName LookupPrivilegeNameA +#define LookupPrivilegeDisplayName LookupPrivilegeDisplayNameA +#define BuildCommDCB BuildCommDCBA +#define BuildCommDCBAndTimeouts BuildCommDCBAndTimeoutsA +#define CommConfigDialog CommConfigDialogA +#define GetDefaultCommConfig GetDefaultCommConfigA +#define SetDefaultCommConfig SetDefaultCommConfigA +#define GetComputerName GetComputerNameA +#define SetComputerName SetComputerNameA +#define GetUserName GetUserNameA +#define CreateMailslot CreateMailslotA +#define FormatMessage FormatMessageA +#define GetEnvironmentStrings GetEnvironmentStringsA +#define FreeEnvironmentStrings FreeEnvironmentStringsA +#define lstrcmp lstrcmpA +#define lstrcmpi lstrcmpiA +#define lstrcpyn lstrcpynA +#define lstrcpy lstrcpyA +#define lstrcat lstrcatA +#define lstrlen lstrlenA +#define GetBinaryType GetBinaryTypeA +#define GetShortPathName GetShortPathNameA +#define SetFileSecurity SetFileSecurityA +#define GetFileSecurity GetFileSecurityA +#define FindFirstChangeNotification FindFirstChangeNotificationA +#define AccessCheckAndAuditAlarm AccessCheckAndAuditAlarmA +#define ObjectOpenAuditAlarm ObjectOpenAuditAlarmA +#define ObjectPrivilegeAuditAlarm ObjectPrivilegeAuditAlarmA +#define ObjectCloseAuditAlarm ObjectCloseAuditAlarmA +#define PrivilegedServiceAuditAlarm PrivilegedServiceAuditAlarmA +#define OpenEventLog OpenEventLogA +#define RegisterEventSource RegisterEventSourceA +#define OpenBackupEventLog OpenBackupEventLogA +#define ReadEventLog ReadEventLogA +#define ReportEvent ReportEventA +#define CreateProcess CreateProcessA +#define FatalAppExit FatalAppExitA +#define GetStartupInfo GetStartupInfoA +#define GetCommandLine GetCommandLineA +#define GetEnvironmentVariable GetEnvironmentVariableA +#define SetEnvironmentVariable SetEnvironmentVariableA +#define ExpandEnvironmentStrings ExpandEnvironmentStringsA +#define OutputDebugString OutputDebugStringA +#define FindResource FindResourceA +#define FindResourceEx FindResourceExA +#define EnumResourceTypes EnumResourceTypesA +#define EnumResourceNames EnumResourceNamesA +#define EnumResourceLanguages EnumResourceLanguagesA +#define BeginUpdateResource BeginUpdateResourceA +#define UpdateResource UpdateResourceA +#define EndUpdateResource EndUpdateResourceA +#define GlobalAddAtom GlobalAddAtomA +#define GlobalFindAtom GlobalFindAtomA +#define GlobalGetAtomName GlobalGetAtomNameA +#define AddAtom AddAtomA +#define FindAtom FindAtomA +#define GetProfileInt GetProfileIntA +#define GetAtomName GetAtomNameA +#define GetProfileString GetProfileStringA +#define WriteProfileString WriteProfileStringA +#define GetProfileSection GetProfileSectionA +#define WriteProfileSection WriteProfileSectionA +#define GetPrivateProfileInt GetPrivateProfileIntA +#define GetPrivateProfileString GetPrivateProfileStringA +#define WritePrivateProfileString WritePrivateProfileStringA +#define GetPrivateProfileSection GetPrivateProfileSectionA +#define WritePrivateProfileSection WritePrivateProfileSectionA +#define GetDriveType GetDriveTypeA +#define GetSystemDirectory GetSystemDirectoryA +#define GetTempPath GetTempPathA +#define GetTempFileName GetTempFileNameA +#define GetWindowsDirectory GetWindowsDirectoryA +#define SetCurrentDirectory SetCurrentDirectoryA +#define GetCurrentDirectory GetCurrentDirectoryA +#define GetDiskFreeSpace GetDiskFreeSpaceA +#define GetDiskFreeSpaceEx GetDiskFreeSpaceExA +#define CreateDirectory CreateDirectoryA +#define CreateDirectoryEx CreateDirectoryExA +#define RemoveDirectory RemoveDirectoryA +#define GetFullPathName GetFullPathNameA +#define DefineDosDevice DefineDosDeviceA +#define QueryDosDevice QueryDosDeviceA +#define CreateFile CreateFileA +#define SetFileAttributes SetFileAttributesA +#define GetFileAttributes GetFileAttributesA +#define GetCompressedFileSize GetCompressedFileSizeA +#define DeleteFile DeleteFileA +#define FindFirstFileEx FindFirstFileExA +#define FindFirstFile FindFirstFileA +#define FindNextFile FindNextFileA +#define SearchPath SearchPathA +#define CopyFile CopyFileA +#define MoveFile MoveFileA +#define MoveFileEx MoveFileExA +#define CreateNamedPipe CreateNamedPipeA +#define GetNamedPipeHandleState GetNamedPipeHandleStateA +#define CallNamedPipe CallNamedPipeA +#define WaitNamedPipe WaitNamedPipeA +#define SetVolumeLabel SetVolumeLabelA +#define GetVolumeInformation GetVolumeInformationA +#define ClearEventLog ClearEventLogA +#define BackupEventLog BackupEventLogA +#define CreateMutex CreateMutexA +#define OpenMutex OpenMutexA +#define CreateEvent CreateEventA +#define OpenEvent OpenEventA +#define CreateSemaphore CreateSemaphoreA +#define OpenSemaphore OpenSemaphoreA +#define CreateFileMapping CreateFileMappingA +#define OpenFileMapping OpenFileMappingA +#define GetLogicalDriveStrings GetLogicalDriveStringsA +#define LoadLibrary LoadLibraryA +#define LoadLibraryEx LoadLibraryExA +#define GetModuleFileName GetModuleFileNameA +#define GetModuleHandle GetModuleHandleA +#define GetUserObjectInformation GetUserObjectInformationA +#define SetUserObjectInformation SetUserObjectInformationA +#define RegisterWindowMessage RegisterWindowMessageA +#define GetMessage GetMessageA +#define DispatchMessage DispatchMessageA +#define PeekMessage PeekMessageA +#define SendMessage SendMessageA +#define SendMessageTimeout SendMessageTimeoutA +#define SendNotifyMessage SendNotifyMessageA +#define SendMessageCallback SendMessageCallbackA +#define PostMessage PostMessageA +#define PostThreadMessage PostThreadMessageA +#define VerFindFile VerFindFileA +#define VerInstallFile VerInstallFileA +#define GetFileVersionInfoSize GetFileVersionInfoSizeA +#define GetFileVersionInfo GetFileVersionInfoA +#define VerLanguageName VerLanguageNameA +#define VerQueryValue VerQueryValueA +#define CompareString CompareStringA +#define LCMapString LCMapStringA +#define GetLocaleInfo GetLocaleInfoA +#define SetLocaleInfo SetLocaleInfoA +#define GetTimeFormat GetTimeFormatA +#define GetDateFormat GetDateFormatA +#define GetNumberFormat GetNumberFormatA +#define GetCurrencyFormat GetCurrencyFormatA +#define EnumCalendarInfo EnumCalendarInfoA +#define EnumTimeFormats EnumTimeFormatsA +#define FoldString FoldStringA +#define EnumSystemCodePages EnumSystemCodePagesA +#define EnumSystemLocales EnumSystemLocalesA +#define GetStringTypeEx GetStringTypeExA +#define EnumDateFormats EnumDateFormatsA +#define GetConsoleTitle GetConsoleTitleA +#define ScrollConsoleScreenBuffer ScrollConsoleScreenBufferA +#define SetConsoleTitle SetConsoleTitleA +#define ReadConsole ReadConsoleA +#define WriteConsole WriteConsoleA +#define PeekConsoleInput PeekConsoleInputA +#define ReadConsoleInput ReadConsoleInputA +#define WriteConsoleInput WriteConsoleInputA +#define ReadConsoleOutput ReadConsoleOutputA +#define WriteConsoleOutput WriteConsoleOutputA +#define ReadConsoleOutputCharacter ReadConsoleOutputCharacterA +#define WriteConsoleOutputCharacter WriteConsoleOutputCharacterA +#define FillConsoleOutputCharacter FillConsoleOutputCharacterA +#define MultinetGetConnectionPerformance MultinetGetConnectionPerformanceA +#define WNetGetLastError WNetGetLastErrorA +#define WNetGetProviderName WNetGetProviderNameA +#define WNetGetNetworkInformation WNetGetNetworkInformationA +#define WNetConnectionDialog1 WNetConnectionDialog1A +#define WNetDisconnectDialog1 WNetDisconnectDialog1A +#define WNetOpenEnum WNetOpenEnumA +#define WNetEnumResource WNetEnumResourceA +#define WNetGetUniversalName WNetGetUniversalNameA +#define WNetGetUser WNetGetUserA +#define WNetAddConnection WNetAddConnectionA +#define WNetAddConnection2 WNetAddConnection2A +#define WNetAddConnection3 WNetAddConnection3A +#define WNetCancelConnection WNetCancelConnectionA +#define WNetCancelConnection2 WNetCancelConnection2A +#define WNetGetConnection WNetGetConnectionA +#define WNetUseConnection WNetUseConnectionA +#define WNetSetConnection WNetSetConnectionA +#define OpenService OpenServiceA +#define QueryServiceConfig QueryServiceConfigA +#define QueryServiceLockStatus QueryServiceLockStatusA +#define RegisterServiceCtrlHandler RegisterServiceCtrlHandlerA +#define StartServiceCtrlDispatcher StartServiceCtrlDispatcherA +#define StartService StartServiceA +#define ChangeServiceConfig ChangeServiceConfigA +#define CreateService CreateServiceA +#define EnumDependentServices EnumDependentServicesA +#define EnumServicesStatus EnumServicesStatusA +#define GetServiceKeyName GetServiceKeyNameA +#define GetServiceDisplayName GetServiceDisplayNameA +#define OpenSCManager OpenSCManagerA +#define DragQueryFile DragQueryFileA +#define ExtractAssociatedIcon ExtractAssociatedIconA +#define ExtractIcon ExtractIconA +#define FindExecutable FindExecutableA +#define ShellAbout ShellAboutA +#define ShellExecute ShellExecuteA +#define DdeCreateStringHandle DdeCreateStringHandleA +#define DdeInitialize DdeInitializeA +#define DdeQueryString DdeQueryStringA +#define LogonUser LogonUserA +#define CreateProcessAsUser CreateProcessAsUserA + +#endif /* UNICODE and ASCII defines */ + + HWND STDCALL GetAncestor(HWND hWnd, UINT GaFlags); +WINBOOL STDCALL AbnormalTermination(VOID); +int STDCALL AbortDoc(HDC); +WINBOOL STDCALL AbortPath(HDC); +WINBOOL STDCALL AbortPrinter(HANDLE); +WINBOOL CALLBACK AbortProc(HDC, int); +WINBOOL STDCALL AbortSystemShutdown(LPTSTR); +WINBOOL STDCALL AccessCheck( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + HANDLE ClientToken, + DWORD DesiredAccess, + PGENERIC_MAPPING GenericMapping, + PPRIVILEGE_SET PrivilegeSet, + LPDWORD PrivilegeSetLength, + LPDWORD GrantedAccess, + LPBOOL AccessStatus + ); + +WINBOOL STDCALL AccessCheckAndAuditAlarm( + LPCTSTR SubsystemName, + LPVOID HandleId, + LPTSTR ObjectTypeName, + LPTSTR ObjectName, + PSECURITY_DESCRIPTOR SecurityDescriptor, + DWORD DesiredAccess, + PGENERIC_MAPPING GenericMapping, + WINBOOL ObjectCreation, + LPDWORD GrantedAccess, + LPBOOL AccessStatus, + LPBOOL pfGenerateOnClose + ); + +#ifndef __NTDRIVER__ +LONG +STDCALL +InterlockedIncrement( + LPLONG lpAddend + ); + +LONG +STDCALL +InterlockedDecrement( + LPLONG lpAddend + ); + +LONG +STDCALL +InterlockedExchange( + LPLONG Target, + LONG Value + ); + +PVOID +STDCALL +InterlockedCompareExchange( + PVOID *Destination, + PVOID Exchange, + PVOID Comperand + ); +#endif + +WINBOOL +STDCALL +FreeResource( + HGLOBAL hResData + ); + +LPVOID +STDCALL +LockResource( + HGLOBAL hResData + ); + +int +STDCALL +WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nShowCmd + ); + +WINBOOL +STDCALL +FreeLibrary( + HINSTANCE hLibModule + ); + + +VOID +STDCALL +FreeLibraryAndExitThread( + HMODULE hLibModule, + DWORD dwExitCode + ); + +WINBOOL +STDCALL +DisableThreadLibraryCalls( + HMODULE hLibModule + ); + +FARPROC +STDCALL +GetProcAddress( + HINSTANCE hModule, + LPCSTR lpProcName + ); + +DWORD +STDCALL +GetVersion( VOID ); + +HGLOBAL +STDCALL +GlobalAlloc( + UINT uFlags, + DWORD dwBytes + ); + +HGLOBAL +GlobalDiscard( + HGLOBAL hglbMem + ); + +HGLOBAL +STDCALL +GlobalReAlloc( + HGLOBAL hMem, + DWORD dwBytes, + UINT uFlags + ); + +DWORD +STDCALL +GlobalSize( + HGLOBAL hMem + ); + +UINT +STDCALL +GlobalFlags( + HGLOBAL hMem + ); + + +LPVOID +STDCALL +GlobalLock( + HGLOBAL hMem + ); + +HGLOBAL +STDCALL +GlobalHandle( + LPCVOID pMem + ); + + +WINBOOL +STDCALL +GlobalUnlock( + HGLOBAL hMem + ); + + +HGLOBAL +STDCALL +GlobalFree( + HGLOBAL hMem + ); + +UINT +STDCALL +GlobalCompact( + DWORD dwMinFree + ); + + +VOID +STDCALL +GlobalFix( + HGLOBAL hMem + ); + + +VOID +STDCALL +GlobalUnfix( + HGLOBAL hMem + ); + + +LPVOID +STDCALL +GlobalWire( + HGLOBAL hMem + ); + + +WINBOOL +STDCALL +GlobalUnWire( + HGLOBAL hMem + ); + + +VOID +STDCALL +GlobalMemoryStatus( + LPMEMORYSTATUS lpBuffer + ); + + +HLOCAL +STDCALL +LocalAlloc( + UINT uFlags, + UINT uBytes + ); + +HLOCAL +LocalDiscard( + HLOCAL hlocMem + ); + +HLOCAL +STDCALL +LocalReAlloc( + HLOCAL hMem, + UINT uBytes, + UINT uFlags + ); + + +LPVOID +STDCALL +LocalLock( + HLOCAL hMem + ); + + +HLOCAL +STDCALL +LocalHandle( + LPCVOID pMem + ); + + +WINBOOL +STDCALL +LocalUnlock( + HLOCAL hMem + ); + + +UINT +STDCALL +LocalSize( + HLOCAL hMem + ); + + +UINT +STDCALL +LocalFlags( + HLOCAL hMem + ); + + +HLOCAL +STDCALL +LocalFree( + HLOCAL hMem + ); + + +UINT +STDCALL +LocalShrink( + HLOCAL hMem, + UINT cbNewSize + ); + + +UINT +STDCALL +LocalCompact( + UINT uMinFree + ); + + +WINBOOL +STDCALL +FlushInstructionCache( + HANDLE hProcess, + LPCVOID lpBaseAddress, + DWORD dwSize + ); + + +LPVOID +STDCALL +VirtualAlloc( + LPVOID lpAddress, + DWORD dwSize, + DWORD flAllocationType, + DWORD flProtect + ); + + +WINBOOL +STDCALL +VirtualFree( + LPVOID lpAddress, + DWORD dwSize, + DWORD dwFreeType + ); + + +WINBOOL +STDCALL +VirtualProtect( + LPVOID lpAddress, + DWORD dwSize, + DWORD flNewProtect, + PDWORD lpflOldProtect + ); + + +DWORD +STDCALL +VirtualQuery( + LPCVOID lpAddress, + PMEMORY_BASIC_INFORMATION lpBuffer, + DWORD dwLength + ); + + +WINBOOL +STDCALL +VirtualProtectEx( + HANDLE hProcess, + LPVOID lpAddress, + DWORD dwSize, + DWORD flNewProtect, + PDWORD lpflOldProtect + ); + + +DWORD +STDCALL +VirtualQueryEx( + HANDLE hProcess, + LPCVOID lpAddress, + PMEMORY_BASIC_INFORMATION lpBuffer, + DWORD dwLength + ); + + +HANDLE +STDCALL +HeapCreate( + DWORD flOptions, + DWORD dwInitialSize, + DWORD dwMaximumSize + ); + +WINBOOL +STDCALL +HeapDestroy( + HANDLE hHeap + ); + +LPVOID +STDCALL +HeapAlloc( + HANDLE hHeap, + DWORD dwFlags, + DWORD dwBytes + ); + +LPVOID +STDCALL +HeapReAlloc( + HANDLE hHeap, + DWORD dwFlags, + LPVOID lpMem, + DWORD dwBytes + ); + +WINBOOL +STDCALL +HeapFree( + HANDLE hHeap, + DWORD dwFlags, + LPVOID lpMem + ); + +DWORD +STDCALL +HeapSize( + HANDLE hHeap, + DWORD dwFlags, + LPCVOID lpMem + ); + +WINBOOL +STDCALL +HeapValidate( + HANDLE hHeap, + DWORD dwFlags, + LPCVOID lpMem + ); + +UINT +STDCALL +HeapCompact( + HANDLE hHeap, + DWORD dwFlags + ); + +HANDLE +STDCALL +GetProcessHeap( VOID ); + +DWORD +STDCALL +GetProcessHeaps( + DWORD NumberOfHeaps, + PHANDLE ProcessHeaps + ); + +DWORD +STDCALL +GetProcessVersion ( + DWORD ProcessId + ); + +WINBOOL +STDCALL +HeapLock( + HANDLE hHeap + ); + +WINBOOL +STDCALL +HeapUnlock( + HANDLE hHeap + ); + +WINBOOL +STDCALL +HeapWalk( + HANDLE hHeap, + LPPROCESS_HEAP_ENTRY lpEntry + ); + +WINBOOL +STDCALL +GetProcessAffinityMask( + HANDLE hProcess, + LPDWORD lpProcessAffinityMask, + LPDWORD lpSystemAffinityMask + ); + +WINBOOL +STDCALL +GetProcessTimes( + HANDLE hProcess, + LPFILETIME lpCreationTime, + LPFILETIME lpExitTime, + LPFILETIME lpKernelTime, + LPFILETIME lpUserTime + ); + +WINBOOL +STDCALL +GetProcessWorkingSetSize( + HANDLE hProcess, + LPDWORD lpMinimumWorkingSetSize, + LPDWORD lpMaximumWorkingSetSize + ); + +WINBOOL +STDCALL +SetProcessWorkingSetSize( + HANDLE hProcess, + DWORD dwMinimumWorkingSetSize, + DWORD dwMaximumWorkingSetSize + ); + +HANDLE +STDCALL +OpenProcess( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + DWORD dwProcessId + ); + +HANDLE +STDCALL +GetCurrentProcess( + VOID + ); + +DWORD +STDCALL +GetCurrentProcessId( + VOID + ); + +VOID +STDCALL +ExitProcess( + UINT uExitCode + ) __attribute__ ((noreturn)); + +WINBOOL +STDCALL +TerminateProcess( + HANDLE hProcess, + UINT uExitCode + ); + +WINBOOL +STDCALL +GetExitCodeProcess( + HANDLE hProcess, + LPDWORD lpExitCode + ); + +VOID +STDCALL +FatalExit( + int ExitCode + ); + +VOID +STDCALL +RaiseException( + DWORD dwExceptionCode, + DWORD dwExceptionFlags, + DWORD nNumberOfArguments, + CONST DWORD *lpArguments + ); + +LONG +STDCALL +UnhandledExceptionFilter( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +/* + TODO: what is TOP_LEVEL_EXCEPTION_FILTER? +LPTOP_LEVEL_EXCEPTION_FILTER +STDCALL +SetUnhandledExceptionFilter( + LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter + ); +*/ + + +HANDLE +STDCALL +CreateThread( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId + ); + + +HANDLE +STDCALL +CreateRemoteThread( + HANDLE hProcess, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId + ); + + +HANDLE +STDCALL +GetCurrentThread( + VOID + ); + + +DWORD +STDCALL +GetCurrentThreadId( + VOID + ); + + +DWORD +STDCALL +SetThreadAffinityMask( + HANDLE hThread, + DWORD dwThreadAffinityMask + ); + + +WINBOOL +STDCALL +SetThreadPriority( + HANDLE hThread, + int nPriority + ); + + +int +STDCALL +GetThreadPriority( + HANDLE hThread + ); + + +WINBOOL +STDCALL +GetThreadTimes( + HANDLE hThread, + LPFILETIME lpCreationTime, + LPFILETIME lpExitTime, + LPFILETIME lpKernelTime, + LPFILETIME lpUserTime + ); + + +VOID +STDCALL +ExitThread( + DWORD dwExitCode + ); + + +WINBOOL +STDCALL +TerminateThread( + HANDLE hThread, + DWORD dwExitCode + ); + + +WINBOOL +STDCALL +GetExitCodeThread( + HANDLE hThread, + LPDWORD lpExitCode + ); + +WINBOOL +STDCALL +GetThreadSelectorEntry( + HANDLE hThread, + DWORD dwSelector, + LPLDT_ENTRY lpSelectorEntry + ); + + +DWORD +STDCALL +GetLastError( + VOID + ); + + +VOID +STDCALL +SetLastError( + DWORD dwErrCode + ); + + +WINBOOL +STDCALL +GetOverlappedResult( + HANDLE hFile, + LPOVERLAPPED lpOverlapped, + LPDWORD lpNumberOfBytesTransferred, + WINBOOL bWait + ); + + +HANDLE +STDCALL +CreateIoCompletionPort( + HANDLE FileHandle, + HANDLE ExistingCompletionPort, + DWORD CompletionKey, + DWORD NumberOfConcurrentThreads + ); + + +WINBOOL +STDCALL +GetQueuedCompletionStatus( + HANDLE CompletionPort, + LPDWORD lpNumberOfBytesTransferred, + LPDWORD lpCompletionKey, + LPOVERLAPPED *lpOverlapped, + DWORD dwMilliseconds + ); + +UINT +STDCALL +SetErrorMode( + UINT uMode + ); + + +WINBOOL +STDCALL +ReadProcessMemory( + HANDLE hProcess, + LPCVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead + ); + + +WINBOOL +STDCALL +WriteProcessMemory( + HANDLE hProcess, + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesWritten + ); + + +WINBOOL +STDCALL +GetThreadContext( + HANDLE hThread, + LPCONTEXT lpContext + ); + + +WINBOOL +STDCALL +SetThreadContext( + HANDLE hThread, + CONST CONTEXT *lpContext + ); + + +DWORD +STDCALL +SuspendThread( + HANDLE hThread + ); + + +DWORD +STDCALL +ResumeThread( + HANDLE hThread + ); + + +VOID +STDCALL +DebugBreak( + VOID + ); + + +WINBOOL +STDCALL +WaitForDebugEvent( + LPDEBUG_EVENT lpDebugEvent, + DWORD dwMilliseconds + ); + + +WINBOOL +STDCALL +ContinueDebugEvent( + DWORD dwProcessId, + DWORD dwThreadId, + DWORD dwContinueStatus + ); + + +WINBOOL +STDCALL +DebugActiveProcess( + DWORD dwProcessId + ); + + +VOID +STDCALL +InitializeCriticalSection( + LPCRITICAL_SECTION lpCriticalSection + ); + + +VOID +STDCALL +EnterCriticalSection( + LPCRITICAL_SECTION lpCriticalSection + ); + + +VOID +STDCALL +LeaveCriticalSection( + LPCRITICAL_SECTION lpCriticalSection + ); + + +VOID +STDCALL +DeleteCriticalSection( + LPCRITICAL_SECTION lpCriticalSection + ); + + +WINBOOL +STDCALL +SetEvent( + HANDLE hEvent + ); + + +WINBOOL +STDCALL +ResetEvent( + HANDLE hEvent + ); + + +WINBOOL +STDCALL +PulseEvent( + HANDLE hEvent + ); + + +WINBOOL +STDCALL +ReleaseSemaphore( + HANDLE hSemaphore, + LONG lReleaseCount, + LPLONG lpPreviousCount + ); + + +WINBOOL +STDCALL +ReleaseMutex( + HANDLE hMutex + ); + + +DWORD +STDCALL +WaitForSingleObject( + HANDLE hHandle, + DWORD dwMilliseconds + ); + + +DWORD +STDCALL +WaitForMultipleObjects( + DWORD nCount, + CONST HANDLE *lpHandles, + WINBOOL bWaitAll, + DWORD dwMilliseconds + ); + + +VOID +STDCALL +Sleep( + DWORD dwMilliseconds + ); + + +HGLOBAL +STDCALL +LoadResource( + HINSTANCE hModule, + HRSRC hResInfo + ); + + +DWORD +STDCALL +SizeofResource( + HINSTANCE hModule, + HRSRC hResInfo + ); + + + +ATOM +STDCALL +GlobalDeleteAtom( + ATOM nAtom + ); + + +WINBOOL +STDCALL +InitAtomTable( + DWORD nSize + ); + + +ATOM +STDCALL +DeleteAtom( + ATOM nAtom + ); + + +UINT +STDCALL +SetHandleCount( + UINT uNumber + ); + + +DWORD +STDCALL +GetLogicalDrives( + VOID + ); + + +WINBOOL +STDCALL +LockFile( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh + ); + + +WINBOOL +STDCALL +UnlockFile( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh + ); + + +WINBOOL +STDCALL +LockFileEx( + HANDLE hFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped + ); + +WINBOOL +STDCALL +UnlockFileEx( + HANDLE hFile, + DWORD dwReserved, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh, + LPOVERLAPPED lpOverlapped + ); + +WINBOOL +STDCALL +GetFileInformationByHandle( + HANDLE hFile, + LPBY_HANDLE_FILE_INFORMATION lpFileInformation + ); + + +DWORD +STDCALL +GetFileType( + HANDLE hFile + ); + + +DWORD +STDCALL +GetFileSize( + HANDLE hFile, + LPDWORD lpFileSizeHigh + ); + + +HANDLE +STDCALL +GetStdHandle( + DWORD nStdHandle + ); + + +WINBOOL +STDCALL +SetStdHandle( + DWORD nStdHandle, + HANDLE hHandle + ); + + +WINBOOL +STDCALL +WriteFile( + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + LPOVERLAPPED lpOverlapped + ); + + +WINBOOL +STDCALL +ReadFile( + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped + ); + + +WINBOOL +STDCALL +FlushFileBuffers( + HANDLE hFile + ); + + +WINBOOL +STDCALL +DeviceIoControl( + HANDLE hDevice, + DWORD dwIoControlCode, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + + +WINBOOL +STDCALL +SetEndOfFile( + HANDLE hFile + ); + + +DWORD +STDCALL +SetFilePointer( + HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod + ); + + +WINBOOL +STDCALL +FindClose( + HANDLE hFindFile + ); + + +WINBOOL +STDCALL +GetFileTime( + HANDLE hFile, + LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, + LPFILETIME lpLastWriteTime + ); + + +WINBOOL +STDCALL +SetFileTime( + HANDLE hFile, + CONST FILETIME *lpCreationTime, + CONST FILETIME *lpLastAccessTime, + CONST FILETIME *lpLastWriteTime + ); + + +WINBOOL +STDCALL +CloseHandle( + HANDLE hObject + ); + + +WINBOOL +STDCALL +DuplicateHandle( + HANDLE hSourceProcessHandle, + HANDLE hSourceHandle, + HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + DWORD dwOptions + ); + + +WINBOOL +STDCALL +GetHandleInformation( + HANDLE hObject, + LPDWORD lpdwFlags + ); + + +WINBOOL +STDCALL +SetHandleInformation( + HANDLE hObject, + DWORD dwMask, + DWORD dwFlags + ); + +DWORD +STDCALL +LoadModule( + LPCSTR lpModuleName, + LPVOID lpParameterBlock + ); + + +UINT +STDCALL +WinExec( + LPCSTR lpCmdLine, + UINT uCmdShow + ); + + +WINBOOL +STDCALL +ClearCommBreak( + HANDLE hFile + ); + + +WINBOOL +STDCALL +ClearCommError( + HANDLE hFile, + LPDWORD lpErrors, + LPCOMSTAT lpStat + ); + + +WINBOOL +STDCALL +SetupComm( + HANDLE hFile, + DWORD dwInQueue, + DWORD dwOutQueue + ); + + +WINBOOL +STDCALL +EscapeCommFunction( + HANDLE hFile, + DWORD dwFunc + ); + + +WINBOOL +STDCALL +GetCommConfig( + HANDLE hCommDev, + LPCOMMCONFIG lpCC, + LPDWORD lpdwSize + ); + + +WINBOOL +STDCALL +GetCommMask( + HANDLE hFile, + LPDWORD lpEvtMask + ); + + +WINBOOL +STDCALL +GetCommProperties( + HANDLE hFile, + LPCOMMPROP lpCommProp + ); + + +WINBOOL +STDCALL +GetCommModemStatus( + HANDLE hFile, + LPDWORD lpModemStat + ); + + +WINBOOL +STDCALL +GetCommState( + HANDLE hFile, + LPDCB lpDCB + ); + + +WINBOOL +STDCALL +GetCommTimeouts( + HANDLE hFile, + LPCOMMTIMEOUTS lpCommTimeouts + ); + + +WINBOOL +STDCALL +PurgeComm( + HANDLE hFile, + DWORD dwFlags + ); + + +WINBOOL +STDCALL +SetCommBreak( + HANDLE hFile + ); + + +WINBOOL +STDCALL +SetCommConfig( + HANDLE hCommDev, + LPCOMMCONFIG lpCC, + DWORD dwSize + ); + + +WINBOOL +STDCALL +SetCommMask( + HANDLE hFile, + DWORD dwEvtMask + ); + + +WINBOOL +STDCALL +SetCommState( + HANDLE hFile, + LPDCB lpDCB + ); + + +WINBOOL +STDCALL +SetCommTimeouts( + HANDLE hFile, + LPCOMMTIMEOUTS lpCommTimeouts + ); + + +WINBOOL +STDCALL +TransmitCommChar( + HANDLE hFile, + char cChar + ); + + +WINBOOL +STDCALL +WaitCommEvent( + HANDLE hFile, + LPDWORD lpEvtMask, + LPOVERLAPPED lpOverlapped + ); + + + +DWORD +STDCALL +SetTapePosition( + HANDLE hDevice, + DWORD dwPositionMethod, + DWORD dwPartition, + DWORD dwOffsetLow, + DWORD dwOffsetHigh, + WINBOOL bImmediate + ); + + +DWORD +STDCALL +GetTapePosition( + HANDLE hDevice, + DWORD dwPositionType, + LPDWORD lpdwPartition, + LPDWORD lpdwOffsetLow, + LPDWORD lpdwOffsetHigh + ); + + +DWORD +STDCALL +PrepareTape( + HANDLE hDevice, + DWORD dwOperation, + WINBOOL bImmediate + ); + +BOOL +STDCALL +ProcessIdToSessionId( + DWORD dwProcessId, + DWORD* pSessionId + ); + +DWORD +STDCALL +EraseTape( + HANDLE hDevice, + DWORD dwEraseType, + WINBOOL bImmediate + ); + + +DWORD +STDCALL +CreateTapePartition( + HANDLE hDevice, + DWORD dwPartitionMethod, + DWORD dwCount, + DWORD dwSize + ); + + +DWORD +STDCALL +WriteTapemark( + HANDLE hDevice, + DWORD dwTapemarkType, + DWORD dwTapemarkCount, + WINBOOL bImmediate + ); + + +DWORD +STDCALL +GetTapeStatus( + HANDLE hDevice + ); + + +DWORD +STDCALL +GetTapeParameters( + HANDLE hDevice, + DWORD dwOperation, + LPDWORD lpdwSize, + LPVOID lpTapeInformation + ); + +DWORD +STDCALL +SetTapeParameters( + HANDLE hDevice, + DWORD dwOperation, + LPVOID lpTapeInformation + ); + +WINBOOL +STDCALL +Beep( + DWORD dwFreq, + DWORD dwDuration + ); + + +VOID +STDCALL +OpenSound( + VOID + ); + + +VOID +STDCALL +CloseSound( + VOID + ); + + +VOID +STDCALL +StartSound( + VOID + ); + + +VOID +STDCALL +StopSound( + VOID + ); + + +DWORD +STDCALL +WaitSoundState( + DWORD nState + ); + + +DWORD +STDCALL +SyncAllVoices( + VOID + ); + + +DWORD +STDCALL +CountVoiceNotes( + DWORD nVoice + ); + + +LPDWORD +STDCALL +GetThresholdEvent( + VOID + ); + + +DWORD +STDCALL +GetThresholdStatus( + VOID + ); + + +DWORD +STDCALL +SetSoundNoise( + DWORD nSource, + DWORD nDuration + ); + + +DWORD +STDCALL +SetVoiceAccent( + DWORD nVoice, + DWORD nTempo, + DWORD nVolume, + DWORD nMode, + DWORD nPitch + ); + + +DWORD +STDCALL +SetVoiceEnvelope( + DWORD nVoice, + DWORD nShape, + DWORD nRepeat + ); + + +DWORD +STDCALL +SetVoiceNote( + DWORD nVoice, + DWORD nValue, + DWORD nLength, + DWORD nCdots + ); + + +DWORD +STDCALL +SetVoiceQueueSize( + DWORD nVoice, + DWORD nBytes + ); + + +DWORD +STDCALL +SetVoiceSound( + DWORD nVoice, + DWORD Frequency, + DWORD nDuration + ); + + +DWORD +STDCALL +SetVoiceThreshold( + DWORD nVoice, + DWORD nNotes + ); + + +int +STDCALL +MulDiv( + int nNumber, + int nNumerator, + int nDenominator + ); + + +VOID +STDCALL +GetSystemTime( + LPSYSTEMTIME lpSystemTime + ); + +VOID +STDCALL +GetSystemTimeAsFileTime ( + LPFILETIME lpSystemTimeAsFileTime + ); + +WINBOOL +STDCALL +SetSystemTime( + CONST SYSTEMTIME *lpSystemTime + ); + + +VOID +STDCALL +GetLocalTime( + LPSYSTEMTIME lpSystemTime + ); + + +WINBOOL +STDCALL +SetLocalTime( + CONST SYSTEMTIME *lpSystemTime + ); + + +VOID +STDCALL +GetSystemInfo( + LPSYSTEM_INFO lpSystemInfo + ); + +WINBOOL +STDCALL +SystemTimeToTzSpecificLocalTime( + LPTIME_ZONE_INFORMATION lpTimeZoneInformation, + LPSYSTEMTIME lpUniversalTime, + LPSYSTEMTIME lpLocalTime + ); + + +DWORD +STDCALL +GetTimeZoneInformation( + LPTIME_ZONE_INFORMATION lpTimeZoneInformation + ); + + +WINBOOL +STDCALL +SetTimeZoneInformation( + CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation + ); + +WINBOOL +STDCALL +SystemTimeToFileTime( + CONST SYSTEMTIME *lpSystemTime, + LPFILETIME lpFileTime + ); + + +WINBOOL +STDCALL +FileTimeToLocalFileTime( + CONST FILETIME *lpFileTime, + LPFILETIME lpLocalFileTime + ); + + +WINBOOL +STDCALL +LocalFileTimeToFileTime( + CONST FILETIME *lpLocalFileTime, + LPFILETIME lpFileTime + ); + + +WINBOOL +STDCALL +FileTimeToSystemTime( + CONST FILETIME *lpFileTime, + LPSYSTEMTIME lpSystemTime + ); + + +LONG +STDCALL +CompareFileTime( + CONST FILETIME *lpFileTime1, + CONST FILETIME *lpFileTime2 + ); + + +WINBOOL +STDCALL +FileTimeToDosDateTime( + CONST FILETIME *lpFileTime, + LPWORD lpFatDate, + LPWORD lpFatTime + ); + + +WINBOOL +STDCALL +DosDateTimeToFileTime( + WORD wFatDate, + WORD wFatTime, + LPFILETIME lpFileTime + ); + + +DWORD +STDCALL +GetTickCount( + VOID + ); + + +WINBOOL +STDCALL +SetSystemTimeAdjustment( + DWORD dwTimeAdjustment, + WINBOOL bTimeAdjustmentDisabled + ); + + +WINBOOL +STDCALL +GetSystemTimeAdjustment( + PDWORD lpTimeAdjustment, + PDWORD lpTimeIncrement, + PWINBOOL lpTimeAdjustmentDisabled + ); + + +WINBOOL +STDCALL +CreatePipe( + PHANDLE hReadPipe, + PHANDLE hWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize + ); + + +WINBOOL +STDCALL +ConnectNamedPipe( + HANDLE hNamedPipe, + LPOVERLAPPED lpOverlapped + ); + + +WINBOOL +STDCALL +DisconnectNamedPipe( + HANDLE hNamedPipe + ); + + +WINBOOL +STDCALL +SetNamedPipeHandleState( + HANDLE hNamedPipe, + LPDWORD lpMode, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout + ); + + +WINBOOL +STDCALL +GetNamedPipeInfo( + HANDLE hNamedPipe, + LPDWORD lpFlags, + LPDWORD lpOutBufferSize, + LPDWORD lpInBufferSize, + LPDWORD lpMaxInstances + ); + + +WINBOOL +STDCALL +PeekNamedPipe( + HANDLE hNamedPipe, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage + ); + + +WINBOOL +STDCALL +TransactNamedPipe( + HANDLE hNamedPipe, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + LPOVERLAPPED lpOverlapped + ); + + + +WINBOOL +STDCALL +GetMailslotInfo( + HANDLE hMailslot, + LPDWORD lpMaxMessageSize, + LPDWORD lpNextSize, + LPDWORD lpMessageCount, + LPDWORD lpReadTimeout + ); + + +WINBOOL +STDCALL +SetMailslotInfo( + HANDLE hMailslot, + DWORD lReadTimeout + ); + + +LPVOID +STDCALL +MapViewOfFile( + HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + DWORD dwNumberOfBytesToMap + ); + + +WINBOOL +STDCALL +FlushViewOfFile( + LPCVOID lpBaseAddress, + DWORD dwNumberOfBytesToFlush + ); + + +WINBOOL +STDCALL +UnmapViewOfFile( + LPVOID lpBaseAddress + ); + +HFILE +STDCALL +OpenFile( + LPCSTR lpFileName, + LPOFSTRUCT lpReOpenBuff, + UINT uStyle + ); + + +HFILE +STDCALL +_lopen( + LPCSTR lpPathName, + int iReadWrite + ); + + +HFILE +STDCALL +_lcreat( + LPCSTR lpPathName, + int iAttribute + ); + + +UINT +STDCALL +_lread( + HFILE hFile, + LPVOID lpBuffer, + UINT uBytes + ); + + +UINT +STDCALL +_lwrite( + HFILE hFile, + LPCSTR lpBuffer, + UINT uBytes + ); + + +long +STDCALL +_hread( + HFILE hFile, + LPVOID lpBuffer, + long lBytes + ); + + +long +STDCALL +_hwrite( + HFILE hFile, + LPCSTR lpBuffer, + long lBytes + ); + + +HFILE +STDCALL +_lclose( + HFILE hFile + ); + + +LONG +STDCALL +_llseek( + HFILE hFile, + LONG lOffset, + int iOrigin + ); + + +WINBOOL +STDCALL +IsTextUnicode( + CONST LPVOID lpBuffer, + int cb, + LPINT lpi + ); + + +DWORD +STDCALL +TlsAlloc( + VOID + ); + +LPVOID +STDCALL +TlsGetValue( + DWORD dwTlsIndex + ); + + +WINBOOL +STDCALL +TlsSetValue( + DWORD dwTlsIndex, + LPVOID lpTlsValue + ); + + +WINBOOL +STDCALL +TlsFree( + DWORD dwTlsIndex + ); + +DWORD +STDCALL +SleepEx( + DWORD dwMilliseconds, + WINBOOL bAlertable + ); + + +DWORD +STDCALL +WaitForSingleObjectEx( + HANDLE hHandle, + DWORD dwMilliseconds, + WINBOOL bAlertable + ); + + +DWORD +STDCALL +WaitForMultipleObjectsEx( + DWORD nCount, + CONST HANDLE *lpHandles, + WINBOOL bWaitAll, + DWORD dwMilliseconds, + WINBOOL bAlertable + ); + + +WINBOOL +STDCALL +ReadFileEx( + HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPOVERLAPPED lpOverlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine + ); + + +WINBOOL +STDCALL +WriteFileEx( + HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPOVERLAPPED lpOverlapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine + ); + + +WINBOOL +STDCALL +BackupRead( + HANDLE hFile, + LPBYTE lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + WINBOOL bAbort, + WINBOOL bProcessSecurity, + LPVOID *lpContext + ); + + +WINBOOL +STDCALL +BackupSeek( + HANDLE hFile, + DWORD dwLowBytesToSeek, + DWORD dwHighBytesToSeek, + LPDWORD lpdwLowByteSeeked, + LPDWORD lpdwHighByteSeeked, + LPVOID *lpContext + ); + + +WINBOOL +STDCALL +BackupWrite( + HANDLE hFile, + LPBYTE lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + WINBOOL bAbort, + WINBOOL bProcessSecurity, + LPVOID *lpContext + ); + +WINBOOL +STDCALL +SetProcessShutdownParameters( + DWORD dwLevel, + DWORD dwFlags + ); + + +WINBOOL +STDCALL +GetProcessShutdownParameters( + LPDWORD lpdwLevel, + LPDWORD lpdwFlags + ); + + +VOID +STDCALL +SetFileApisToOEM( VOID ); + + +VOID +STDCALL +SetFileApisToANSI( VOID ); + + +WINBOOL +STDCALL +AreFileApisANSI( VOID ); + +WINBOOL +STDCALL +CloseEventLog ( + HANDLE hEventLog + ); + + +WINBOOL +STDCALL +DeregisterEventSource ( + HANDLE hEventLog + ); + + +WINBOOL +STDCALL +NotifyChangeEventLog ( + HANDLE hEventLog, + HANDLE hEvent + ); + + +WINBOOL +STDCALL +GetNumberOfEventLogRecords ( + HANDLE hEventLog, + PDWORD NumberOfRecords + ); + + +WINBOOL +STDCALL +GetOldestEventLogRecord ( + HANDLE hEventLog, + PDWORD OldestRecord + ); + +WINBOOL +STDCALL +DuplicateToken( + HANDLE ExistingTokenHandle, + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + PHANDLE DuplicateTokenHandle + ); + + +WINBOOL +STDCALL +GetKernelObjectSecurity ( + HANDLE Handle, + SECURITY_INFORMATION RequestedInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD nLength, + LPDWORD lpnLengthNeeded + ); + + +WINBOOL +STDCALL +ImpersonateNamedPipeClient( + HANDLE hNamedPipe + ); + + +WINBOOL +STDCALL +ImpersonateLoggedOnUser( + HANDLE hToken + ); + + +WINBOOL +STDCALL +ImpersonateSelf( + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel + ); + + + +WINBOOL +STDCALL +RevertToSelf ( + VOID + ); + + +WINBOOL +STDCALL +SetThreadToken ( + PHANDLE Thread, + HANDLE Token + ); + + +WINBOOL +STDCALL +AccessCheck ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + HANDLE ClientToken, + DWORD DesiredAccess, + PGENERIC_MAPPING GenericMapping, + PPRIVILEGE_SET PrivilegeSet, + LPDWORD PrivilegeSetLength, + LPDWORD GrantedAccess, + LPBOOL AccessStatus + ); + + + +WINBOOL +STDCALL +OpenProcessToken ( + HANDLE ProcessHandle, + DWORD DesiredAccess, + PHANDLE TokenHandle + ); + + + +WINBOOL +STDCALL +OpenThreadToken ( + HANDLE ThreadHandle, + DWORD DesiredAccess, + WINBOOL OpenAsSelf, + PHANDLE TokenHandle + ); + + + +WINBOOL +STDCALL +GetTokenInformation ( + HANDLE TokenHandle, + TOKEN_INFORMATION_CLASS TokenInformationClass, + LPVOID TokenInformation, + DWORD TokenInformationLength, + PDWORD ReturnLength + ); + + + +WINBOOL +STDCALL +SetTokenInformation ( + HANDLE TokenHandle, + TOKEN_INFORMATION_CLASS TokenInformationClass, + LPVOID TokenInformation, + DWORD TokenInformationLength + ); + + + +WINBOOL +STDCALL +AdjustTokenPrivileges ( + HANDLE TokenHandle, + WINBOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, + DWORD BufferLength, + PTOKEN_PRIVILEGES PreviousState, + PDWORD ReturnLength + ); + + + +WINBOOL +STDCALL +AdjustTokenGroups ( + HANDLE TokenHandle, + WINBOOL ResetToDefault, + PTOKEN_GROUPS NewState, + DWORD BufferLength, + PTOKEN_GROUPS PreviousState, + PDWORD ReturnLength + ); + + + +WINBOOL +STDCALL +PrivilegeCheck ( + HANDLE ClientToken, + PPRIVILEGE_SET RequiredPrivileges, + LPBOOL pfResult + ); + + + +WINBOOL +STDCALL +IsValidSid ( + PSID pSid + ); + + + +WINBOOL +STDCALL +EqualSid ( + PSID pSid1, + PSID pSid2 + ); + + + +WINBOOL +STDCALL +EqualPrefixSid ( + PSID pSid1, + PSID pSid2 + ); + + + +DWORD +STDCALL +GetSidLengthRequired ( + UCHAR nSubAuthorityCount + ); + + + +WINBOOL +STDCALL +AllocateAndInitializeSid ( + PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, + BYTE nSubAuthorityCount, + DWORD nSubAuthority0, + DWORD nSubAuthority1, + DWORD nSubAuthority2, + DWORD nSubAuthority3, + DWORD nSubAuthority4, + DWORD nSubAuthority5, + DWORD nSubAuthority6, + DWORD nSubAuthority7, + PSID *pSid + ); + + +PVOID +STDCALL +FreeSid( + PSID pSid + ); + + +WINBOOL +STDCALL +InitializeSid ( + PSID Sid, + PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, + BYTE nSubAuthorityCount + ); + + + +PSID_IDENTIFIER_AUTHORITY +STDCALL +GetSidIdentifierAuthority ( + PSID pSid + ); + + + +PDWORD +STDCALL +GetSidSubAuthority ( + PSID pSid, + DWORD nSubAuthority + ); + + + +PUCHAR +STDCALL +GetSidSubAuthorityCount ( + PSID pSid + ); + + + +DWORD +STDCALL +GetLengthSid ( + PSID pSid + ); + + + +WINBOOL +STDCALL +CopySid ( + DWORD nDestinationSidLength, + PSID pDestinationSid, + PSID pSourceSid + ); + + + +WINBOOL +STDCALL +AreAllAccessesGranted ( + DWORD GrantedAccess, + DWORD DesiredAccess + ); + + + +WINBOOL +STDCALL +AreAnyAccessesGranted ( + DWORD GrantedAccess, + DWORD DesiredAccess + ); + + + +VOID +STDCALL +MapGenericMask ( + PDWORD AccessMask, + PGENERIC_MAPPING GenericMapping + ); + + + +WINBOOL +STDCALL +IsValidAcl ( + PACL pAcl + ); + + + +WINBOOL +STDCALL +InitializeAcl ( + PACL pAcl, + DWORD nAclLength, + DWORD dwAclRevision + ); + + + +WINBOOL +STDCALL +GetAclInformation ( + PACL pAcl, + LPVOID pAclInformation, + DWORD nAclInformationLength, + ACL_INFORMATION_CLASS dwAclInformationClass + ); + + + +WINBOOL +STDCALL +SetAclInformation ( + PACL pAcl, + LPVOID pAclInformation, + DWORD nAclInformationLength, + ACL_INFORMATION_CLASS dwAclInformationClass + ); + + + +WINBOOL +STDCALL +AddAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD dwStartingAceIndex, + LPVOID pAceList, + DWORD nAceListLength + ); + + + +WINBOOL +STDCALL +DeleteAce ( + PACL pAcl, + DWORD dwAceIndex + ); + + + +WINBOOL +STDCALL +GetAce ( + PACL pAcl, + DWORD dwAceIndex, + LPVOID *pAce + ); + + + +WINBOOL +STDCALL +AddAccessAllowedAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD AccessMask, + PSID pSid + ); + + + +WINBOOL +STDCALL +AddAccessDeniedAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD AccessMask, + PSID pSid + ); + + + +WINBOOL +STDCALL +AddAuditAccessAce( + PACL pAcl, + DWORD dwAceRevision, + DWORD dwAccessMask, + PSID pSid, + WINBOOL bAuditSuccess, + WINBOOL bAuditFailure + ); + + + +WINBOOL +STDCALL +FindFirstFreeAce ( + PACL pAcl, + LPVOID *pAce + ); + + + +WINBOOL +STDCALL +InitializeSecurityDescriptor ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD dwRevision + ); + + + +WINBOOL +STDCALL +IsValidSecurityDescriptor ( + PSECURITY_DESCRIPTOR pSecurityDescriptor + ); + + + +DWORD +STDCALL +GetSecurityDescriptorLength ( + PSECURITY_DESCRIPTOR pSecurityDescriptor + ); + + + +WINBOOL +STDCALL +GetSecurityDescriptorControl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL pControl, + LPDWORD lpdwRevision + ); + + + +WINBOOL +STDCALL +SetSecurityDescriptorDacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + WINBOOL bDaclPresent, + PACL pDacl, + WINBOOL bDaclDefaulted + ); + + + +WINBOOL +STDCALL +GetSecurityDescriptorDacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + LPBOOL lpbDaclPresent, + PACL *pDacl, + LPBOOL lpbDaclDefaulted + ); + + + +WINBOOL +STDCALL +SetSecurityDescriptorSacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + WINBOOL bSaclPresent, + PACL pSacl, + WINBOOL bSaclDefaulted + ); + + + +WINBOOL +STDCALL +GetSecurityDescriptorSacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + LPBOOL lpbSaclPresent, + PACL *pSacl, + LPBOOL lpbSaclDefaulted + ); + + + +WINBOOL +STDCALL +SetSecurityDescriptorOwner ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID pOwner, + WINBOOL bOwnerDefaulted + ); + + + +WINBOOL +STDCALL +GetSecurityDescriptorOwner ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID *pOwner, + LPBOOL lpbOwnerDefaulted + ); + + + +WINBOOL +STDCALL +SetSecurityDescriptorGroup ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID pGroup, + WINBOOL bGroupDefaulted + ); + + + +WINBOOL +STDCALL +GetSecurityDescriptorGroup ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID *pGroup, + LPBOOL lpbGroupDefaulted + ); + + + +WINBOOL +STDCALL +CreatePrivateObjectSecurity ( + PSECURITY_DESCRIPTOR ParentDescriptor, + PSECURITY_DESCRIPTOR CreatorDescriptor, + PSECURITY_DESCRIPTOR * NewDescriptor, + WINBOOL IsDirectoryObject, + HANDLE Token, + PGENERIC_MAPPING GenericMapping + ); + + + +WINBOOL +STDCALL +SetPrivateObjectSecurity ( + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ModificationDescriptor, + PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, + PGENERIC_MAPPING GenericMapping, + HANDLE Token + ); + + + +WINBOOL +STDCALL +GetPrivateObjectSecurity ( + PSECURITY_DESCRIPTOR ObjectDescriptor, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR ResultantDescriptor, + DWORD DescriptorLength, + PDWORD ReturnLength + ); + + + +WINBOOL +STDCALL +DestroyPrivateObjectSecurity ( + PSECURITY_DESCRIPTOR * ObjectDescriptor + ); + + + +WINBOOL +STDCALL +MakeSelfRelativeSD ( + PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, + PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, + LPDWORD lpdwBufferLength + ); + + + +WINBOOL +STDCALL +MakeAbsoluteSD ( + PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, + PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, + LPDWORD lpdwAbsoluteSecurityDescriptorSize, + PACL pDacl, + LPDWORD lpdwDaclSize, + PACL pSacl, + LPDWORD lpdwSaclSize, + PSID pOwner, + LPDWORD lpdwOwnerSize, + PSID pPrimaryGroup, + LPDWORD lpdwPrimaryGroupSize + ); + + + +WINBOOL +STDCALL +SetKernelObjectSecurity ( + HANDLE Handle, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR SecurityDescriptor + ); + + +WINBOOL +STDCALL +FindNextChangeNotification( + HANDLE hChangeHandle + ); + + +WINBOOL +STDCALL +FindCloseChangeNotification( + HANDLE hChangeHandle + ); + + +WINBOOL +STDCALL +VirtualLock( + LPVOID lpAddress, + DWORD dwSize + ); + + +WINBOOL +STDCALL +VirtualUnlock( + LPVOID lpAddress, + DWORD dwSize + ); + + +LPVOID +STDCALL +MapViewOfFileEx( + HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + DWORD dwNumberOfBytesToMap, + LPVOID lpBaseAddress + ); + + +WINBOOL +STDCALL +SetPriorityClass( + HANDLE hProcess, + DWORD dwPriorityClass + ); + + +DWORD +STDCALL +GetPriorityClass( + HANDLE hProcess + ); + + +WINBOOL +STDCALL +IsBadReadPtr( + CONST VOID *lp, + UINT ucb + ); + + +WINBOOL +STDCALL +IsBadWritePtr( + LPVOID lp, + UINT ucb + ); + + +WINBOOL +STDCALL +IsBadHugeReadPtr( + CONST VOID *lp, + UINT ucb + ); + + +WINBOOL +STDCALL +IsBadHugeWritePtr( + LPVOID lp, + UINT ucb + ); + + +WINBOOL +STDCALL +IsBadCodePtr( + FARPROC lpfn + ); + +WINBOOL +STDCALL +AllocateLocallyUniqueId( + PLUID Luid + ); + + +WINBOOL +STDCALL +QueryPerformanceCounter( + LARGE_INTEGER *lpPerformanceCount + ); + + +WINBOOL +STDCALL +QueryPerformanceFrequency( + LARGE_INTEGER *lpFrequency + ); + +VOID +STDCALL +MoveMemory ( + PVOID Destination, + CONST VOID *Source, + DWORD Length + ); + +VOID +STDCALL +FillMemory ( + PVOID Destination, + DWORD Length, + BYTE Fill + ); + +VOID +STDCALL +ZeroMemory ( + PVOID Destination, + DWORD Length + ); + +/* The memory functions don't seem to be defined in the libraries, so + define macro versions as well. */ +#define MoveMemory(t, s, c) memmove ((t), (s), (c)) +#define FillMemory(p, c, v) memset ((p), (v), (c)) +#define ZeroMemory(p, c) memset ((p), 0, (c)) + +#ifdef WINNT351 +WINBOOL +STDCALL +ActivateKeyboardLayout( + HKL hkl, + UINT Flags); +#else +HKL +STDCALL +ActivateKeyboardLayout( + HKL hkl, + UINT Flags); +#endif /* WIN95 */ + + +int +STDCALL +ToUnicodeEx( + UINT wVirtKey, + UINT wScanCode, + PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags, + HKL dwhkl); + + +WINBOOL +STDCALL +UnloadKeyboardLayout( + HKL hkl); + + +UINT +STDCALL +GetKeyboardLayoutList( + int nBuff, + HKL *lpList); + + +HKL +STDCALL +GetKeyboardLayout( + DWORD dwLayout + ); + + +HDESK +STDCALL +OpenInputDesktop( + DWORD dwFlags, + WINBOOL fInherit, + DWORD dwDesiredAccess); + +WINBOOL +STDCALL +EnumDesktopWindows( + HDESK hDesktop, + ENUMWINDOWSPROC lpfn, + LPARAM lParam); + + +WINBOOL +STDCALL +SwitchDesktop( + HDESK hDesktop); + + +WINBOOL +STDCALL +SetThreadDesktop( + HDESK hDesktop); + + +WINBOOL +STDCALL +CloseDesktop( + HDESK hDesktop); + + +HDESK +STDCALL +GetThreadDesktop( + DWORD dwThreadId); + + +WINBOOL +STDCALL +CloseWindowStation( + HWINSTA hWinSta); + + +WINBOOL +STDCALL +SetProcessWindowStation( + HWINSTA hWinSta); + + +HWINSTA +STDCALL +GetProcessWindowStation( + VOID); + + +WINBOOL +STDCALL +SetUserObjectSecurity( + HANDLE hObj, + PSECURITY_INFORMATION pSIRequested, + PSECURITY_DESCRIPTOR pSID); + + +WINBOOL +STDCALL +GetUserObjectSecurity( + HANDLE hObj, + PSECURITY_INFORMATION pSIRequested, + PSECURITY_DESCRIPTOR pSID, + DWORD nLength, + LPDWORD lpnLengthNeeded); + + +WINBOOL +STDCALL +TranslateMessage( + CONST MSG *lpMsg); + +WINBOOL +STDCALL +SetMessageQueue( + int cMessagesMax); + +WINBOOL +STDCALL +RegisterHotKey( + HWND hWnd , + int anID, + UINT fsModifiers, + UINT vk); + + +WINBOOL +STDCALL +UnregisterHotKey( + HWND hWnd, + int anID); + + +WINBOOL +STDCALL +ExitWindowsEx( + UINT uFlags, + DWORD dwReserved); + + +WINBOOL +STDCALL +SwapMouseButton( + WINBOOL fSwap); + + +DWORD +STDCALL +GetMessagePos( + VOID); + + +LONG +STDCALL +GetMessageTime( + VOID); + + +LPARAM +STDCALL +GetMessageExtraInfo( + VOID); + + +LPARAM +STDCALL +SetMessageExtraInfo( + LPARAM lParam); + + +long +STDCALL +BroadcastSystemMessage( + DWORD, + LPDWORD, + UINT, + WPARAM, + LPARAM); + +WINBOOL +STDCALL +AttachThreadInput( + DWORD idAttach, + DWORD idAttachTo, + WINBOOL fAttach); + + +WINBOOL +STDCALL +ReplyMessage( + LRESULT lResult); + + +WINBOOL +STDCALL +WaitMessage( + VOID); + + +DWORD +STDCALL +WaitForInputIdle( + HANDLE hProcess, + DWORD dwMilliseconds); + + +VOID +STDCALL +PostQuitMessage( + int nExitCode); + +WINBOOL +STDCALL +InSendMessage( + VOID); + + +UINT +STDCALL +GetDoubleClickTime( + VOID); + + +WINBOOL +STDCALL +SetDoubleClickTime( + UINT); + + +WINBOOL +STDCALL +IsWindow( + HWND hWnd); + + +WINBOOL +STDCALL +IsMenu( + HMENU hMenu); + + +WINBOOL +STDCALL +IsChild( + HWND hWndParent, + HWND hWnd); + + +WINBOOL +STDCALL +DestroyWindow( + HWND hWnd); + + +WINBOOL +STDCALL +ShowWindow( + HWND hWnd, + int nCmdShow); + + +WINBOOL +STDCALL +ShowWindowAsync( + HWND hWnd, + int nCmdShow); + + +WINBOOL +STDCALL +FlashWindow( + HWND hWnd, + WINBOOL bInvert); + + +WINBOOL +STDCALL +ShowOwnedPopups( + HWND hWnd, + WINBOOL fShow); + + +WINBOOL +STDCALL +OpenIcon( + HWND hWnd); + + +WINBOOL +STDCALL +CloseWindow( + HWND hWnd); + + +WINBOOL +STDCALL +MoveWindow( + HWND hWnd, + int X, + int Y, + int nWidth, + int nHeight, + WINBOOL bRepaint); + + +WINBOOL +STDCALL +SetWindowPos( + HWND hWnd, + HWND hWndInsertAfter , + int X, + int Y, + int cx, + int cy, + UINT uFlags); + + +WINBOOL +STDCALL +GetWindowPlacement( + HWND hWnd, + WINDOWPLACEMENT *lpwndpl); + + +WINBOOL +STDCALL +SetWindowPlacement( + HWND hWnd, + CONST WINDOWPLACEMENT *lpwndpl); + + +HDWP +STDCALL +BeginDeferWindowPos( + int nNumWindows); + + +HDWP +STDCALL +DeferWindowPos( + HDWP hWinPosInfo, + HWND hWnd, + HWND hWndInsertAfter, + int x, + int y, + int cx, + int cy, + UINT uFlags); + + +WINBOOL +STDCALL +EndDeferWindowPos( + HDWP hWinPosInfo); + + +WINBOOL +STDCALL +IsWindowVisible( + HWND hWnd); + + +WINBOOL +STDCALL +IsIconic( + HWND hWnd); + + +WINBOOL +STDCALL +AnyPopup( + VOID); + + +WINBOOL +STDCALL +BringWindowToTop( + HWND hWnd); + + +WINBOOL +STDCALL +IsZoomed( + HWND hWnd); + + +WINBOOL +STDCALL +EndDialog( + HWND hDlg, + int nResult); + + +HWND +STDCALL +GetDlgItem( + HWND hDlg, + int nIDDlgItem); + + +WINBOOL +STDCALL +SetDlgItemInt( + HWND hDlg, + int nIDDlgItem, + UINT uValue, + WINBOOL bSigned); + + +UINT +STDCALL +GetDlgItemInt( + HWND hDlg, + int nIDDlgItem, + WINBOOL *lpTranslated, + WINBOOL bSigned); + + +WINBOOL +STDCALL +CheckDlgButton( + HWND hDlg, + int nIDButton, + UINT uCheck); + + +WINBOOL +STDCALL +CheckRadioButton( + HWND hDlg, + int nIDFirstButton, + int nIDLastButton, + int nIDCheckButton); + + +UINT +STDCALL +IsDlgButtonChecked( + HWND hDlg, + int nIDButton); + + +HWND +STDCALL +GetNextDlgGroupItem( + HWND hDlg, + HWND hCtl, + WINBOOL bPrevious); + + +HWND +STDCALL +GetNextDlgTabItem( + HWND hDlg, + HWND hCtl, + WINBOOL bPrevious); + + +int +STDCALL +GetDlgCtrlID( + HWND hWnd); + + +LONG +STDCALL +GetDialogBaseUnits(VOID); + +WINBOOL +STDCALL +OpenClipboard( + HWND hWndNewOwner); + + +WINBOOL +STDCALL +CloseClipboard( + VOID); + + +HWND +STDCALL +GetClipboardOwner( + VOID); + + +HWND +STDCALL +SetClipboardViewer( + HWND hWndNewViewer); + + +HWND +STDCALL +GetClipboardViewer( + VOID); + + +WINBOOL +STDCALL +ChangeClipboardChain( + HWND hWndRemove, + HWND hWndNewNext); + + +HANDLE +STDCALL +SetClipboardData( + UINT uFormat, + HANDLE hMem); + + +HANDLE +STDCALL +GetClipboardData( + UINT uFormat); + + + +int +STDCALL +CountClipboardFormats( + VOID); + + +UINT +STDCALL +EnumClipboardFormats( + UINT format); + + +WINBOOL +STDCALL +EmptyClipboard( + VOID); + + +WINBOOL +STDCALL +IsClipboardFormatAvailable( + UINT format); + + +int +STDCALL +GetPriorityClipboardFormat( + UINT *paFormatPriorityList, + int cFormats); + + +HWND +STDCALL +GetOpenClipboardWindow( + VOID); + + +/* Despite the A these are ASCII functions! */ +LPSTR +STDCALL +CharNextExA( + WORD CodePage, + LPCSTR lpCurrentChar, + DWORD dwFlags); + + +LPSTR +STDCALL +CharPrevExA( + WORD CodePage, + LPCSTR lpStart, + LPCSTR lpCurrentChar, + DWORD dwFlags); + + +HWND +STDCALL +SetFocus( + HWND hWnd); + + +HWND +STDCALL +GetActiveWindow( + VOID); + + +HWND +STDCALL +GetFocus( + VOID); + + +UINT +STDCALL +GetKBCodePage( + VOID); + + +SHORT +STDCALL +GetKeyState( + int nVirtKey); + + +SHORT +STDCALL +GetAsyncKeyState( + int vKey); + + +WINBOOL +STDCALL +GetKeyboardState( + PBYTE lpKeyState); + + +WINBOOL +STDCALL +SetKeyboardState( + LPBYTE lpKeyState); + + +int +STDCALL +GetKeyboardType( + int nTypeFlag); + + +int +STDCALL +ToAscii( + UINT uVirtKey, + UINT uScanCode, + PBYTE lpKeyState, + LPWORD lpChar, + UINT uFlags); + + +int +STDCALL +ToAsciiEx( + UINT uVirtKey, + UINT uScanCode, + PBYTE lpKeyState, + LPWORD lpChar, + UINT uFlags, + HKL dwhkl); + + +int +STDCALL +ToUnicode( + UINT wVirtKey, + UINT wScanCode, + PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags); + + +DWORD +STDCALL +OemKeyScan( + WORD wOemChar); + + +VOID +STDCALL +keybd_event( + BYTE bVk, + BYTE bScan, + DWORD dwFlags, + DWORD dwExtraInfo); + + +VOID +STDCALL +mouse_event( + DWORD dwFlags, + DWORD dx, + DWORD dy, + DWORD cButtons, + DWORD dwExtraInfo); + +WINBOOL +STDCALL +GetInputState( + VOID); + + +DWORD +STDCALL +GetQueueStatus( + UINT flags); + + +HWND +STDCALL +GetCapture( + VOID); + + +HWND +STDCALL +SetCapture( + HWND hWnd); + + +WINBOOL +STDCALL +ReleaseCapture( + VOID); + + +DWORD +STDCALL +MsgWaitForMultipleObjects( + DWORD nCount, + LPHANDLE pHandles, + WINBOOL fWaitAll, + DWORD dwMilliseconds, + DWORD dwWakeMask); + + +UINT +STDCALL +SetTimer( + HWND hWnd , + UINT nIDEvent, + UINT uElapse, + TIMERPROC lpTimerFunc); + + +WINBOOL +STDCALL +SetWaitableTimer(HANDLE hTimer, + const LARGE_INTEGER *pDueTime, + LONG lPeriod, + PTIMERAPCROUTINE pfnCompletionRoutine, + LPVOID lpArgToCompletionRoutine, + WINBOOL fResume); + + +WINBOOL +STDCALL +KillTimer( + HWND hWnd, + UINT uIDEvent); + + +WINBOOL +STDCALL +IsWindowUnicode( + HWND hWnd); + + +WINBOOL +STDCALL +EnableWindow( + HWND hWnd, + WINBOOL bEnable); + + +WINBOOL +STDCALL +IsWindowEnabled( + HWND hWnd); + + +WINBOOL +STDCALL +DestroyAcceleratorTable( + HACCEL hAccel); + +int +STDCALL +GetSystemMetrics( + int nIndex); + +HMENU +STDCALL +GetMenu( + HWND hWnd); + + +WINBOOL +STDCALL +SetMenu( + HWND hWnd, + HMENU hMenu); + + +WINBOOL +STDCALL +HiliteMenuItem( + HWND hWnd, + HMENU hMenu, + UINT uIDHiliteItem, + UINT uHilite); + + +UINT +STDCALL +GetMenuState( + HMENU hMenu, + UINT uId, + UINT uFlags); + + +WINBOOL +STDCALL +DrawMenuBar( + HWND hWnd); + + +HMENU +STDCALL +GetSystemMenu( + HWND hWnd, + WINBOOL bRevert); + + +HMENU +STDCALL +CreateMenu( + VOID); + + +HMENU +STDCALL +CreatePopupMenu( + VOID); + + +WINBOOL +STDCALL +DestroyMenu( + HMENU hMenu); + + +DWORD +STDCALL +CheckMenuItem( + HMENU hMenu, + UINT uIDCheckItem, + UINT uCheck); + + +WINBOOL +STDCALL +EnableMenuItem( + HMENU hMenu, + UINT uIDEnableItem, + UINT uEnable); + + +HMENU +STDCALL +GetSubMenu( + HMENU hMenu, + int nPos); + + +UINT +STDCALL +GetMenuItemID( + HMENU hMenu, + int nPos); + + +int +STDCALL +GetMenuItemCount( + HMENU hMenu); + +WINBOOL +STDCALL RemoveMenu( + HMENU hMenu, + UINT uPosition, + UINT uFlags); + + +WINBOOL +STDCALL +DeleteMenu( + HMENU hMenu, + UINT uPosition, + UINT uFlags); + + +WINBOOL +STDCALL +SetMenuItemBitmaps( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + HBITMAP hBitmapUnchecked, + HBITMAP hBitmapChecked); + + +LONG +STDCALL +GetMenuCheckMarkDimensions( + VOID); + + +WINBOOL +STDCALL +TrackPopupMenu( + HMENU hMenu, + UINT uFlags, + int x, + int y, + int nReserved, + HWND hWnd, + CONST RECT *prcRect); + +UINT +STDCALL +GetMenuDefaultItem( + HMENU hMenu, + UINT fByPos, + UINT gmdiFlags); + +WINBOOL +STDCALL +SetMenuDefaultItem( + HMENU hMenu, + UINT uItem, + UINT fByPos); + +WINBOOL +STDCALL +GetMenuItemRect(HWND hWnd, + HMENU hMenu, + UINT uItem, + LPRECT lprcItem); + +int +STDCALL +MenuItemFromPoint(HWND hWnd, + HMENU hMenu, + POINT ptScreen); + + +DWORD +STDCALL +DragObject(HWND, HWND, UINT, DWORD, HCURSOR); + + +WINBOOL +STDCALL +DragDetect(HWND hwnd, + POINT pt); + + +WINBOOL +STDCALL +DrawIcon( + HDC hDC, + int X, + int Y, + HICON hIcon); + +WINBOOL +STDCALL +UpdateWindow( + HWND hWnd); + + +HWND +STDCALL +SetActiveWindow( + HWND hWnd); + + +HWND +STDCALL +GetForegroundWindow( + VOID); + +WINBOOL +STDCALL +PaintDesktop(HDC hdc); + + +WINBOOL +STDCALL +SetForegroundWindow( + HWND hWnd); + + +HWND +STDCALL +WindowFromDC( + HDC hDC); + + +HDC +STDCALL +GetDC( + HWND hWnd); + + +HDC +STDCALL +GetDCEx( + HWND hWnd , + HRGN hrgnClip, + DWORD flags); + + +HDC +STDCALL +GetWindowDC( + HWND hWnd); + + +int +STDCALL +ReleaseDC( + HWND hWnd, + HDC hDC); + + +HDC +STDCALL +BeginPaint( + HWND hWnd, + LPPAINTSTRUCT lpPaint); + + +WINBOOL +STDCALL +EndPaint( + HWND hWnd, + CONST PAINTSTRUCT *lpPaint); + + +WINBOOL +STDCALL +GetUpdateRect( + HWND hWnd, + LPRECT lpRect, + WINBOOL bErase); + + +int +STDCALL +GetUpdateRgn( + HWND hWnd, + HRGN hRgn, + WINBOOL bErase); + + +int +STDCALL +SetWindowRgn( + HWND hWnd, + HRGN hRgn, + WINBOOL bRedraw); + + +int +STDCALL +GetWindowRgn( + HWND hWnd, + HRGN hRgn); + + +int +STDCALL +ExcludeUpdateRgn( + HDC hDC, + HWND hWnd); + + +WINBOOL +STDCALL +InvalidateRect( + HWND hWnd , + CONST RECT *lpRect, + WINBOOL bErase); + + +WINBOOL +STDCALL +ValidateRect( + HWND hWnd , + CONST RECT *lpRect); + + +WINBOOL +STDCALL +InvalidateRgn( + HWND hWnd, + HRGN hRgn, + WINBOOL bErase); + + +WINBOOL +STDCALL +ValidateRgn( + HWND hWnd, + HRGN hRgn); + + +WINBOOL +STDCALL +RedrawWindow( + HWND hWnd, + CONST RECT *lprcUpdate, + HRGN hrgnUpdate, + UINT flags); + + +WINBOOL +STDCALL +LockWindowUpdate( + HWND hWndLock); + + +WINBOOL +STDCALL +ScrollWindow( + HWND hWnd, + int XAmount, + int YAmount, + CONST RECT *lpRect, + CONST RECT *lpClipRect); + + +WINBOOL +STDCALL +ScrollDC( + HDC hDC, + int dx, + int dy, + CONST RECT *lprcScroll, + CONST RECT *lprcClip , + HRGN hrgnUpdate, + LPRECT lprcUpdate); + + +int +STDCALL +ScrollWindowEx( + HWND hWnd, + int dx, + int dy, + CONST RECT *prcScroll, + CONST RECT *prcClip , + HRGN hrgnUpdate, + LPRECT prcUpdate, + UINT flags); + + +int +STDCALL +SetScrollPos( + HWND hWnd, + int nBar, + int nPos, + WINBOOL bRedraw); + + +int +STDCALL +GetScrollPos( + HWND hWnd, + int nBar); + + +WINBOOL +STDCALL +SetScrollRange( + HWND hWnd, + int nBar, + int nMinPos, + int nMaxPos, + WINBOOL bRedraw); + + +WINBOOL +STDCALL +GetScrollRange( + HWND hWnd, + int nBar, + LPINT lpMinPos, + LPINT lpMaxPos); + + +WINBOOL +STDCALL +ShowScrollBar( + HWND hWnd, + int wBar, + WINBOOL bShow); + + +WINBOOL +STDCALL +EnableScrollBar( + HWND hWnd, + UINT wSBflags, + UINT wArrows); + + +WINBOOL +STDCALL +GetClientRect( + HWND hWnd, + LPRECT lpRect); + + +WINBOOL +STDCALL +GetWindowRect( + HWND hWnd, + LPRECT lpRect); + + +WINBOOL +STDCALL +AdjustWindowRect( + LPRECT lpRect, + DWORD dwStyle, + WINBOOL bMenu); + + +WINBOOL +STDCALL +AdjustWindowRectEx( + LPRECT lpRect, + DWORD dwStyle, + WINBOOL bMenu, + DWORD dwExStyle); + +WINBOOL +STDCALL +SetWindowContextHelpId(HWND, DWORD); + +DWORD +STDCALL +GetWindowContextHelpId(HWND); + +WINBOOL +STDCALL +SetMenuContextHelpId(HMENU, DWORD); + +DWORD +STDCALL +GetMenuContextHelpId(HMENU); + + +WINBOOL +STDCALL +MessageBeep( + UINT uType); + + +int +STDCALL +ShowCursor( + WINBOOL bShow); + + +WINBOOL +STDCALL +SetCursorPos( + int X, + int Y); + + +HCURSOR +STDCALL +SetCursor( + HCURSOR hCursor); + + +WINBOOL +STDCALL +GetCursorPos( + LPPOINT lpPoint); + + +WINBOOL +STDCALL +ClipCursor( + CONST RECT *lpRect); + + +WINBOOL +STDCALL +GetClipCursor( + LPRECT lpRect); + + +HCURSOR +STDCALL +GetCursor( + VOID); + + +WINBOOL +STDCALL +CreateCaret( + HWND hWnd, + HBITMAP hBitmap , + int nWidth, + int nHeight); + + +UINT +STDCALL +GetCaretBlinkTime( + VOID); + + +WINBOOL +STDCALL +SetCaretBlinkTime( + UINT uMSeconds); + + +WINBOOL +STDCALL +DestroyCaret( + VOID); + + +WINBOOL +STDCALL +HideCaret( + HWND hWnd); + + +WINBOOL +STDCALL +ShowCaret( + HWND hWnd); + + +WINBOOL +STDCALL +SetCaretPos( + int X, + int Y); + + +WINBOOL +STDCALL +GetCaretPos( + LPPOINT lpPoint); + + +WINBOOL +STDCALL +ClientToScreen( + HWND hWnd, + LPPOINT lpPoint); + + +WINBOOL +STDCALL +ScreenToClient( + HWND hWnd, + LPPOINT lpPoint); + + +int +STDCALL +MapWindowPoints( + HWND hWndFrom, + HWND hWndTo, + LPPOINT lpPoints, + UINT cPoints); + + +HWND +STDCALL +WindowFromPoint( + POINT Point); + + +HWND +STDCALL +ChildWindowFromPoint( + HWND hWndParent, + POINT Point); + + +DWORD +STDCALL +GetSysColor( + int nIndex); + + +HBRUSH +STDCALL +GetSysColorBrush( + int nIndex); + + +WINBOOL +STDCALL +SetSysColors( + int cElements, + CONST INT * lpaElements, + CONST COLORREF * lpaRgbValues); + + +WINBOOL +STDCALL +DrawFocusRect( + HDC hDC, + CONST RECT * lprc); + + +int +STDCALL +FillRect( + HDC hDC, + CONST RECT *lprc, + HBRUSH hbr); + + +int +STDCALL +FrameRect( + HDC hDC, + CONST RECT *lprc, + HBRUSH hbr); + + +WINBOOL +STDCALL +InvertRect( + HDC hDC, + CONST RECT *lprc); + + +WINBOOL +STDCALL +SetRect( + LPRECT lprc, + int xLeft, + int yTop, + int xRight, + int yBottom); + + +WINBOOL +STDCALL +SetRectEmpty( + LPRECT lprc); + + +WINBOOL +STDCALL +CopyRect( + LPRECT lprcDst, + CONST RECT *lprcSrc); + + +WINBOOL +STDCALL +InflateRect( + LPRECT lprc, + int dx, + int dy); + + +WINBOOL +STDCALL +IntersectRect( + LPRECT lprcDst, + CONST RECT *lprcSrc1, + CONST RECT *lprcSrc2); + + +WINBOOL +STDCALL +UnionRect( + LPRECT lprcDst, + CONST RECT *lprcSrc1, + CONST RECT *lprcSrc2); + + +WINBOOL +STDCALL +SubtractRect( + LPRECT lprcDst, + CONST RECT *lprcSrc1, + CONST RECT *lprcSrc2); + + +WINBOOL +STDCALL +OffsetRect( + LPRECT lprc, + int dx, + int dy); + + +WINBOOL +STDCALL +IsRectEmpty( + CONST RECT *lprc); + + +WINBOOL +STDCALL +EqualRect( + CONST RECT *lprc1, + CONST RECT *lprc2); + + +WINBOOL +STDCALL +PtInRect( + CONST RECT *lprc, + POINT pt); + + +WORD +STDCALL +GetWindowWord( + HWND hWnd, + int nIndex); + + +WORD +STDCALL +SetWindowWord( + HWND hWnd, + int nIndex, + WORD wNewWord); + + +WORD +STDCALL +GetClassWord( + HWND hWnd, + int nIndex); + + +WORD +STDCALL +SetClassWord( + HWND hWnd, + int nIndex, + WORD wNewWord); + +HWND +STDCALL +GetDesktopWindow( + VOID); + + +HWND +STDCALL +GetParent( + HWND hWnd); + + +HWND +STDCALL +SetParent( + HWND hWndChild, + HWND hWndNewParent); + + +WINBOOL +STDCALL +EnumChildWindows( + HWND hWndParent, + ENUMWINDOWSPROC lpEnumFunc, + LPARAM lParam); + + +WINBOOL +STDCALL +EnumWindows( + ENUMWINDOWSPROC lpEnumFunc, + LPARAM lParam); + + +WINBOOL +STDCALL +EnumThreadWindows( + DWORD dwThreadId, + ENUMWINDOWSPROC lpfn, + LPARAM lParam); + +HWND +STDCALL +GetTopWindow( + HWND hWnd); + + +DWORD +STDCALL +GetWindowThreadProcessId( + HWND hWnd, + LPDWORD lpdwProcessId); + + +HWND +STDCALL +GetLastActivePopup( + HWND hWnd); + + +HWND +STDCALL +GetWindow( + HWND hWnd, + UINT uCmd); + +WINBOOL +STDCALL +UnhookWindowsHook( + int nCode, + HOOKPROC pfnFilterProc); + +WINBOOL +STDCALL +UnhookWindowsHookEx( + HHOOK hhk); + + +LRESULT +STDCALL +CallNextHookEx( + HHOOK hhk, + int nCode, + WPARAM wParam, + LPARAM lParam); + + +WINBOOL +STDCALL +CheckMenuRadioItem(HMENU, UINT, UINT, UINT, UINT); + +HCURSOR +STDCALL +CreateCursor( + HINSTANCE hInst, + int xHotSpot, + int yHotSpot, + int nWidth, + int nHeight, + CONST VOID *pvANDPlane, + CONST VOID *pvXORPlane); + + +WINBOOL +STDCALL +DestroyCursor( + HCURSOR hCursor); + + +WINBOOL +STDCALL +SetSystemCursor( + HCURSOR hcur, + DWORD anID); + + +HICON +STDCALL +CreateIcon( + HINSTANCE hInstance, + int nWidth, + int nHeight, + BYTE cPlanes, + BYTE cBitsPixel, + CONST BYTE *lpbANDbits, + CONST BYTE *lpbXORbits); + + +WINBOOL +STDCALL +DestroyIcon( + HICON hIcon); + + +int +STDCALL +LookupIconIdFromDirectory( + PBYTE presbits, + WINBOOL fIcon); + + +int +STDCALL +LookupIconIdFromDirectoryEx( + PBYTE presbits, + WINBOOL fIcon, + int cxDesired, + int cyDesired, + UINT Flags); + + +HICON +STDCALL +CreateIconFromResource( + PBYTE presbits, + DWORD dwResSize, + WINBOOL fIcon, + DWORD dwVer); + + +HICON +STDCALL +CreateIconFromResourceEx( + PBYTE presbits, + DWORD dwResSize, + WINBOOL fIcon, + DWORD dwVer, + int cxDesired, + int cyDesired, + UINT Flags); + + +HICON +STDCALL +CopyImage( + HANDLE, + UINT, + int, + int, + UINT); + + +HICON +STDCALL +CreateIconIndirect( + PICONINFO piconinfo); + + +HICON +STDCALL +CopyIcon( + HICON hIcon); + + +WINBOOL +STDCALL +GetIconInfo( + HICON hIcon, + PICONINFO piconinfo); + + +WINBOOL +STDCALL +MapDialogRect( + HWND hDlg, + LPRECT lpRect); + +int +STDCALL +SetScrollInfo(HWND, int, LPCSCROLLINFO, WINBOOL); + +WINBOOL +STDCALL +GetScrollInfo(HWND, int, LPSCROLLINFO); + +WINBOOL +STDCALL +TranslateMDISysAccel( + HWND hWndClient, + LPMSG lpMsg); + + +UINT +STDCALL +ArrangeIconicWindows( + HWND hWnd); + +WORD +STDCALL +TileWindows(HWND hwndParent, UINT wHow, CONST RECT * lpRect, UINT cKids, const HWND *lpKids); + +WORD +STDCALL +CascadeWindows(HWND hwndParent, UINT wHow, CONST RECT * lpRect, UINT cKids, const HWND *lpKids); + + +VOID +STDCALL +SetLastErrorEx( + DWORD dwErrCode, + DWORD dwType + ); + + +VOID +STDCALL +SetDebugErrorLevel( + DWORD dwLevel + ); + +WINBOOL +STDCALL +DrawEdge(HDC hdc, LPRECT qrc, UINT edge, UINT grfFlags); + +WINBOOL STDCALL +DrawFrameControl(HDC, LPRECT, UINT, UINT); + +WINBOOL +STDCALL +DrawCaption( + HWND hwnd, + HDC hdc, + LPRECT lprc, + UINT uFlags); + +WINBOOL +STDCALL +DrawAnimatedRects(HWND hwnd, int idAni, CONST RECT * lprcFrom, CONST RECT * lprcTo); + +WINBOOL +STDCALL +TrackPopupMenuEx(HMENU, UINT, int, int, HWND, LPTPMPARAMS); + +HWND +STDCALL +ChildWindowFromPointEx(HWND, POINT, UINT); + +WINBOOL +STDCALL +DrawIconEx(HDC hdc, int xLeft, int yTop, + HICON hIcon, int cxWidth, int cyWidth, + UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags); + +WINBOOL +STDCALL +AnimatePalette(HPALETTE, UINT, UINT, CONST PALETTEENTRY *); + +WINBOOL +STDCALL +Arc(HDC, int, int, int, int, int, int, int, int); + +WINBOOL +STDCALL +BitBlt(HDC, int, int, int, int, HDC, int, int, DWORD); + +WINBOOL +STDCALL +CancelDC(HDC); + +WINBOOL +STDCALL +Chord(HDC, int, int, int, int, int, int, int, int); + +HMETAFILE +STDCALL +CloseMetaFile(HDC); + +int +STDCALL +CombineRgn(HRGN, HRGN, HRGN, int); + +HBITMAP +STDCALL +CreateBitmap(int, int, UINT, UINT, CONST VOID *); + +HBITMAP +STDCALL +CreateBitmapIndirect(CONST BITMAP *); + +HBRUSH +STDCALL +CreateBrushIndirect(CONST LOGBRUSH *); + +HBITMAP +STDCALL +CreateCompatibleBitmap(HDC, int, int); + +HBITMAP +STDCALL +CreateDiscardableBitmap(HDC, int, int); + +HDC +STDCALL +CreateCompatibleDC(HDC); + +HBITMAP +STDCALL +CreateDIBitmap(HDC, CONST BITMAPINFOHEADER *, DWORD, CONST VOID *, CONST BITMAPINFO *, UINT); + +HBRUSH +STDCALL +CreateDIBPatternBrush(HGLOBAL, UINT); + +HBRUSH +STDCALL +CreateDIBPatternBrushPt(CONST VOID *, UINT); + +HRGN +STDCALL +CreateEllipticRgn(int, int, int, int); + +HRGN +STDCALL +CreateEllipticRgnIndirect(CONST RECT *); + +HBRUSH +STDCALL +CreateHatchBrush(int, COLORREF); + +HPALETTE +STDCALL +CreatePalette(CONST LOGPALETTE *); + +HPEN +STDCALL +CreatePen(int, int, COLORREF); + +HPEN +STDCALL +CreatePenIndirect(CONST LOGPEN *); + +HRGN +STDCALL +CreatePolyPolygonRgn(CONST POINT *, CONST INT *, int, int); + +HBRUSH +STDCALL +CreatePatternBrush(HBITMAP); + +HRGN +STDCALL +CreateRectRgn(int, int, int, int); + +HRGN +STDCALL +CreateRectRgnIndirect(CONST RECT *); + +HRGN +STDCALL +CreateRoundRectRgn(int, int, int, int, int, int); + +HBRUSH +STDCALL +CreateSolidBrush(COLORREF); + +WINBOOL +STDCALL +DeleteDC(HDC); + +WINBOOL +STDCALL +DeleteMetaFile(HMETAFILE); + +WINBOOL +STDCALL +DeleteObject(HGDIOBJ); + +int +STDCALL +DrawEscape(HDC, int, int, LPCSTR); + +WINBOOL +STDCALL +Ellipse(HDC, int, int, int, int); + +int +STDCALL +EnumObjects(HDC, int, ENUMOBJECTSPROC, LPARAM); + +WINBOOL +STDCALL +EqualRgn(HRGN, HRGN); + +int +STDCALL +Escape(HDC, int, int, LPCSTR, LPVOID); + +int +STDCALL +ExtEscape(HDC, int, int, LPCSTR, int, LPSTR); + +int +STDCALL +ExcludeClipRect(HDC, int, int, int, int); + +HRGN +STDCALL +ExtCreateRegion(CONST XFORM *, DWORD, CONST RGNDATA *); + +WINBOOL +STDCALL +ExtFloodFill(HDC, int, int, COLORREF, UINT); + +WINBOOL +STDCALL +FillRgn(HDC, HRGN, HBRUSH); + +WINBOOL +STDCALL +FloodFill(HDC, int, int, COLORREF); + +WINBOOL +STDCALL +FrameRgn(HDC, HRGN, HBRUSH, int, int); + +WINBOOL +STDCALL +GdiDllInitialize (HANDLE, DWORD, LPVOID); + +VOID +STDCALL +GdiProcessSetup (VOID); + +int +STDCALL +GetROP2(HDC); + +WINBOOL +STDCALL +GetAspectRatioFilterEx(HDC, LPSIZE); + +COLORREF +STDCALL +GetBkColor(HDC); + +int +STDCALL +GetBkMode(HDC); + +LONG +STDCALL +GetBitmapBits(HBITMAP, LONG, LPVOID); + +WINBOOL +STDCALL +GetBitmapDimensionEx(HBITMAP, LPSIZE); + +UINT +STDCALL +GetBoundsRect(HDC, LPRECT, UINT); + +WINBOOL +STDCALL +GetBrushOrgEx(HDC, LPPOINT); + +int +STDCALL +GetClipBox(HDC, LPRECT); + +int +STDCALL +GetClipRgn(HDC, HRGN); + +int +STDCALL +GetMetaRgn(HDC, HRGN); + +HGDIOBJ +STDCALL +GetCurrentObject(HDC, UINT); + +WINBOOL +STDCALL +GetCurrentPositionEx(HDC, LPPOINT); + +int +STDCALL +GetDeviceCaps(HDC, int); + +int +STDCALL +GetDIBits(HDC, HBITMAP, UINT, UINT, LPVOID, LPBITMAPINFO, UINT); + +DWORD +STDCALL +GetFontData(HDC, DWORD, DWORD, LPVOID, DWORD); + +int +STDCALL +GetGraphicsMode(HDC); + +int +STDCALL +GetMapMode(HDC); + +UINT +STDCALL +GetMetaFileBitsEx(HMETAFILE, UINT, LPVOID); + +COLORREF +STDCALL +GetNearestColor(HDC, COLORREF); + +UINT +STDCALL +GetNearestPaletteIndex(HPALETTE, COLORREF); + +DWORD +STDCALL +GetObjectType(HGDIOBJ h); + +UINT +STDCALL +GetPaletteEntries(HPALETTE, UINT, UINT, LPPALETTEENTRY); + +COLORREF +STDCALL +GetPixel(HDC, int, int); + +int +STDCALL +GetPixelFormat(HDC); + +int +STDCALL +GetPolyFillMode(HDC); + +WINBOOL +STDCALL +GetRasterizerCaps(LPRASTERIZER_STATUS, UINT); + +DWORD +STDCALL +GetRegionData(HRGN, DWORD, LPRGNDATA); + +int +STDCALL +GetRgnBox(HRGN, LPRECT); + +HGDIOBJ +STDCALL +GetStockObject(int); + +int +STDCALL +GetStretchBltMode(HDC); + +UINT +STDCALL +GetSystemPaletteEntries(HDC, UINT, UINT, LPPALETTEENTRY); + +UINT +STDCALL +GetSystemPaletteUse(HDC); + +int +STDCALL +GetTextCharacterExtra(HDC); + +UINT +STDCALL +GetTextAlign(HDC); + +COLORREF +STDCALL +GetTextColor(HDC); + +int +STDCALL +GetTextCharset(HDC hdc); + +int +STDCALL +GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE lpSig, DWORD dwFlags); + +WINBOOL +STDCALL +TranslateCharsetInfo( DWORD *lpSrc, LPCHARSETINFO lpCs, DWORD dwFlags); + +DWORD +STDCALL +GetFontLanguageInfo( HDC ); + +WINBOOL +STDCALL +GetViewportExtEx(HDC, LPSIZE); + +WINBOOL +STDCALL +GetViewportOrgEx(HDC, LPPOINT); + +WINBOOL +STDCALL +GetWindowExtEx(HDC, LPSIZE); + +WINBOOL +STDCALL +GetWindowOrgEx(HDC, LPPOINT); + +int +STDCALL +IntersectClipRect(HDC, int, int, int, int); + +WINBOOL +STDCALL +InvertRgn(HDC, HRGN); + +WINBOOL +STDCALL +LineDDA(int, int, int, int, LINEDDAPROC, LPARAM); + +WINBOOL +STDCALL +LineTo(HDC, int, int); + +WINBOOL +STDCALL +MaskBlt(HDC, int, int, int, int, + HDC, int, int, HBITMAP, int, int, DWORD); + +WINBOOL +STDCALL +PlgBlt(HDC, CONST POINT *, HDC, int, int, int, + int, HBITMAP, int, int); + +int +STDCALL +OffsetClipRgn(HDC, int, int); + +int +STDCALL +OffsetRgn(HRGN, int, int); + +WINBOOL +STDCALL +PatBlt(HDC, int, int, int, int, DWORD); + +WINBOOL +STDCALL +Pie(HDC, int, int, int, int, int, int, int, int); + +WINBOOL +STDCALL +PlayMetaFile(HDC, HMETAFILE); + +WINBOOL +STDCALL +PaintRgn(HDC, HRGN); + +WINBOOL +STDCALL +PolyPolygon(HDC, CONST POINT *, CONST INT *, int); + +WINBOOL +STDCALL +PtInRegion(HRGN, int, int); + +WINBOOL +STDCALL +PtVisible(HDC, int, int); + +WINBOOL +STDCALL +RectInRegion(HRGN, CONST RECT *); + +WINBOOL +STDCALL +RectVisible(HDC, CONST RECT *); + +WINBOOL +STDCALL +Rectangle(HDC, int, int, int, int); + +WINBOOL +STDCALL +RestoreDC(HDC, int); + +UINT +STDCALL +RealizePalette(HDC); + +WINBOOL +STDCALL +RoundRect(HDC, int, int, int, int, int, int); + +WINBOOL +STDCALL +ResizePalette(HPALETTE, UINT); + +int +STDCALL +SaveDC(HDC); + +int +STDCALL +SelectClipRgn(HDC, HRGN); + +int +STDCALL +ExtSelectClipRgn(HDC, HRGN, int); + +int +STDCALL +SetMetaRgn(HDC); + +HGDIOBJ +STDCALL +SelectObject(HDC, HGDIOBJ); + +HPALETTE +STDCALL +SelectPalette(HDC, HPALETTE, WINBOOL); + +COLORREF +STDCALL +SetBkColor(HDC, COLORREF); + +int +STDCALL +SetBkMode(HDC, int); + +LONG +STDCALL +SetBitmapBits(HBITMAP, DWORD, CONST VOID *); + +UINT +STDCALL +SetBoundsRect(HDC, CONST RECT *, UINT); + +int +STDCALL +SetDIBits(HDC, HBITMAP, UINT, UINT, CONST VOID *, CONST BITMAPINFO *, UINT); + +int +STDCALL +SetDIBitsToDevice(HDC, int, int, DWORD, DWORD, int, + int, UINT, UINT, CONST VOID *, CONST BITMAPINFO *, UINT); + +DWORD +STDCALL +SetMapperFlags(HDC, DWORD); + +int +STDCALL +SetGraphicsMode(HDC hdc, int iMode); + +int +STDCALL +SetMapMode(HDC, int); + +HMETAFILE +STDCALL +SetMetaFileBitsEx(UINT, CONST BYTE *); + +UINT +STDCALL +SetPaletteEntries(HPALETTE, UINT, UINT, CONST PALETTEENTRY *); + +COLORREF +STDCALL +SetPixel(HDC, int, int, COLORREF); + +WINBOOL +STDCALL +SetPixelV(HDC, int, int, COLORREF); + +int +STDCALL +SetPolyFillMode(HDC, int); + +WINBOOL +STDCALL +StretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD); + +WINBOOL +STDCALL +SetRectRgn(HRGN, int, int, int, int); +int +STDCALL +StretchDIBits(HDC, int, int, int, int, int, int, int, int, CONST + VOID *, CONST BITMAPINFO *, UINT, DWORD); + +int +STDCALL +SetROP2(HDC, int); + +int +STDCALL +SetStretchBltMode(HDC, int); + +UINT +STDCALL +SetSystemPaletteUse(HDC, UINT); + +int +STDCALL +SetTextCharacterExtra(HDC, int); + +COLORREF +STDCALL +SetTextColor(HDC, COLORREF); + +UINT +STDCALL +SetTextAlign(HDC, UINT); + +WINBOOL +STDCALL +SetTextJustification(HDC, int, int); + +WINBOOL +STDCALL +UpdateColors(HDC); + +WINBOOL +STDCALL +PlayMetaFileRecord(HDC, LPHANDLETABLE, LPMETARECORD, UINT); + +WINBOOL +STDCALL +EnumMetaFile(HDC, HMETAFILE, ENUMMETAFILEPROC, LPARAM); + +HENHMETAFILE +STDCALL +CloseEnhMetaFile(HDC); + +WINBOOL +STDCALL +DeleteEnhMetaFile(HENHMETAFILE); + +WINBOOL +STDCALL +EnumEnhMetaFile(HDC, HENHMETAFILE, ENHMETAFILEPROC, + LPVOID, CONST RECT *); + +UINT +STDCALL +GetEnhMetaFileHeader(HENHMETAFILE, UINT, LPENHMETAHEADER ); + +UINT +STDCALL +GetEnhMetaFilePaletteEntries(HENHMETAFILE, UINT, LPPALETTEENTRY ); + +UINT +STDCALL +GetWinMetaFileBits(HENHMETAFILE, UINT, LPBYTE, INT, HDC); + +WINBOOL +STDCALL +PlayEnhMetaFile(HDC, HENHMETAFILE, CONST RECT *); + +WINBOOL +STDCALL +PlayEnhMetaFileRecord(HDC, LPHANDLETABLE, CONST ENHMETARECORD *, UINT); + +HENHMETAFILE +STDCALL +SetEnhMetaFileBits(UINT, CONST BYTE *); + +#if 0 +HENHMETAFILE +STDCALL +SetWinMetaFileBits(UINT, CONST BYTE *, HDC, CONST METAFILEPICT *); +#endif + +WINBOOL +STDCALL +GdiComment(HDC, UINT, CONST BYTE *); + +WINBOOL +STDCALL +AngleArc(HDC, int, int, DWORD, FLOAT, FLOAT); + +WINBOOL +STDCALL +PolyPolyline(HDC, CONST POINT *, CONST DWORD *, DWORD); + +WINBOOL +STDCALL +GetWorldTransform(HDC, LPXFORM); + +WINBOOL +STDCALL +SetWorldTransform(HDC, CONST XFORM *); + +WINBOOL +STDCALL +ModifyWorldTransform(HDC, CONST XFORM *, DWORD); + +WINBOOL +STDCALL +CombineTransform(LPXFORM, CONST XFORM *, CONST XFORM *); + +HBITMAP +STDCALL +CreateDIBSection(HDC, CONST BITMAPINFO *, UINT, VOID *, HANDLE, DWORD); + +UINT +STDCALL +GetDIBColorTable(HDC, UINT, UINT, RGBQUAD *); + +UINT +STDCALL +SetDIBColorTable(HDC, UINT, UINT, CONST RGBQUAD *); + +WINBOOL +STDCALL +SetColorAdjustment(HDC, CONST COLORADJUSTMENT *); + +WINBOOL +STDCALL +GetColorAdjustment(HDC, LPCOLORADJUSTMENT); + +HPALETTE +STDCALL +CreateHalftonePalette(HDC); + +int +STDCALL +EndDoc(HDC); + +int +STDCALL +StartPage(HDC); + +int +STDCALL +EndPage(HDC); + +int +STDCALL +AbortDoc(HDC); + +int +STDCALL +SetAbortProc(HDC, ABORTPROC); + +WINBOOL +STDCALL +AbortPath(HDC); + +WINBOOL +STDCALL +ArcTo(HDC, int, int, int, int, int, int,int, int); + +WINBOOL +STDCALL +BeginPath(HDC); + +WINBOOL +STDCALL +CloseFigure(HDC); + +WINBOOL +STDCALL +EndPath(HDC); + +WINBOOL +STDCALL +FillPath(HDC); + +WINBOOL +STDCALL +FlattenPath(HDC); + +int +STDCALL +GetPath(HDC, LPPOINT, LPBYTE, int); + +HRGN +STDCALL +PathToRegion(HDC); + +WINBOOL +STDCALL +PolyDraw(HDC, CONST POINT *, CONST BYTE *, int); + +WINBOOL +STDCALL +SelectClipPath(HDC, int); + +int +STDCALL +SetArcDirection(HDC, int); + +WINBOOL +STDCALL +SetMiterLimit(HDC, FLOAT, PFLOAT); + +WINBOOL +STDCALL +StrokeAndFillPath(HDC); + +WINBOOL +STDCALL +StrokePath(HDC); + +WINBOOL +STDCALL +WidenPath(HDC); + +HPEN +STDCALL +ExtCreatePen(DWORD, DWORD, CONST LOGBRUSH *, DWORD, CONST DWORD *); + +WINBOOL +STDCALL +GetMiterLimit(HDC, PFLOAT); + +int +STDCALL +GetArcDirection(HDC); + +WINBOOL +STDCALL +MoveToEx(HDC, int, int, LPPOINT); + +HRGN +STDCALL +CreatePolygonRgn(CONST POINT *, int, int); + +WINBOOL +STDCALL +DPtoLP(HDC, LPPOINT, int); + +WINBOOL +STDCALL +LPtoDP(HDC, LPPOINT, int); + +WINBOOL +STDCALL +Polygon(HDC, CONST POINT *, int); + +WINBOOL +STDCALL +Polyline(HDC, CONST POINT *, int); + +WINBOOL +STDCALL +PolyBezier(HDC, CONST POINT *, DWORD); + +WINBOOL +STDCALL +PolyBezierTo(HDC, CONST POINT *, DWORD); + +WINBOOL +STDCALL +PolylineTo(HDC, CONST POINT *, DWORD); + +WINBOOL +STDCALL +SetViewportExtEx(HDC, int, int, LPSIZE); + +WINBOOL +STDCALL +SetViewportOrgEx(HDC, int, int, LPPOINT); + +WINBOOL +STDCALL +SetWindowExtEx(HDC, int, int, LPSIZE); + +WINBOOL +STDCALL +SetWindowOrgEx(HDC, int, int, LPPOINT); + +WINBOOL +STDCALL +OffsetViewportOrgEx(HDC, int, int, LPPOINT); + +WINBOOL +STDCALL +OffsetWindowOrgEx(HDC, int, int, LPPOINT); + +WINBOOL +STDCALL +ScaleViewportExtEx(HDC, int, int, int, int, LPSIZE); + +WINBOOL +STDCALL +ScaleWindowExtEx(HDC, int, int, int, int, LPSIZE); + +WINBOOL +STDCALL +SetBitmapDimensionEx(HBITMAP, int, int, LPSIZE); + +WINBOOL +STDCALL +SetBrushOrgEx(HDC, int, int, LPPOINT); + +WINBOOL +STDCALL +GetDCOrgEx(HDC,LPPOINT); + +WINBOOL +STDCALL +FixBrushOrgEx(HDC,int,int,LPPOINT); + +WINBOOL +STDCALL +UnrealizeObject(HGDIOBJ); + +WINBOOL +STDCALL +GdiFlush(void); + +DWORD +STDCALL +GdiSetBatchLimit(DWORD); + +DWORD +STDCALL +GdiGetBatchLimit(void); + +int +STDCALL +SetICMMode(HDC, int); + +WINBOOL +STDCALL +CheckColorsInGamut(HDC,LPVOID,LPVOID,DWORD); + +HANDLE +STDCALL +GetColorSpace(HDC); + +WINBOOL +STDCALL +SetColorSpace(HDC,HCOLORSPACE); + +WINBOOL +STDCALL +DeleteColorSpace(HCOLORSPACE); + +WINBOOL +STDCALL +GetDeviceGammaRamp(HDC,LPVOID); + +WINBOOL +STDCALL +SetDeviceGammaRamp(HDC,LPVOID); + +WINBOOL +STDCALL +ColorMatchToTarget(HDC,HDC,DWORD); + +HPROPSHEETPAGE +STDCALL +CreatePropertySheetPageA(LPCPROPSHEETPAGE lppsp); + +WINBOOL +STDCALL +DestroyPropertySheetPage(HPROPSHEETPAGE hPSPage); + +void +STDCALL +InitCommonControls(void); + +#define ImageList_AddIcon(himl, hicon) ImageList_ReplaceIcon(himl, -1, hicon) + +HIMAGELIST +STDCALL +ImageList_Create(int cx, int cy, UINT flags, + int cInitial, int cGrow); + +WINBOOL +STDCALL +ImageList_Destroy(HIMAGELIST himl); + +int +STDCALL +ImageList_GetImageCount(HIMAGELIST himl); + +int +STDCALL +ImageList_Add(HIMAGELIST himl, HBITMAP hbmImage, + HBITMAP hbmMask); + +int +STDCALL +ImageList_ReplaceIcon(HIMAGELIST himl, int i, HICON hicon); + +COLORREF +STDCALL +ImageList_SetBkColor(HIMAGELIST himl, COLORREF clrBk); + +COLORREF +STDCALL +ImageList_GetBkColor(HIMAGELIST himl); + +WINBOOL +STDCALL +ImageList_SetOverlayImage(HIMAGELIST himl, int iImage, + int iOverlay); + +WINBOOL +STDCALL +ImageList_Draw(HIMAGELIST himl, int i, HDC hdcDst, int x, int y, UINT fStyle); + +WINBOOL +STDCALL +ImageList_Replace(HIMAGELIST himl, int i, HBITMAP hbmImage, HBITMAP hbmMask); + +int +STDCALL +ImageList_AddMasked(HIMAGELIST himl, HBITMAP hbmImage, COLORREF crMask); + +WINBOOL +STDCALL +ImageList_DrawEx(HIMAGELIST himl, int i, HDC hdcDst, int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle); + +WINBOOL +STDCALL +ImageList_Remove(HIMAGELIST himl, int i); + +HICON +STDCALL +ImageList_GetIcon(HIMAGELIST himl, int i, UINT flags); + +WINBOOL +STDCALL +ImageList_BeginDrag(HIMAGELIST himlTrack, int iTrack, int dxHotspot, int dyHotspot); + +void +STDCALL +ImageList_EndDrag(void); + +WINBOOL +STDCALL +ImageList_DragEnter(HWND hwndLock, int x, int y); + +WINBOOL +STDCALL +ImageList_DragLeave(HWND hwndLock); + +WINBOOL +STDCALL +ImageList_DragMove(int x, int y); + +WINBOOL +STDCALL +ImageList_SetDragCursorImage(HIMAGELIST himlDrag, int iDrag, int dxHotspot, int dyHotspot); + +WINBOOL +STDCALL +ImageList_DragShowNolock(WINBOOL fShow); + +HIMAGELIST +STDCALL +ImageList_GetDragImage(POINT * ppt,POINT * pptHotspot); + +WINBOOL +STDCALL +ImageList_GetIconSize(HIMAGELIST himl, int *cx, int *cy); + +WINBOOL +STDCALL +ImageList_SetIconSize(HIMAGELIST himl, int cx, int cy); + +WINBOOL +STDCALL +ImageList_GetImageInfo(HIMAGELIST himl, int i, IMAGEINFO * pImageInfo); + +HIMAGELIST +STDCALL +ImageList_Merge(HIMAGELIST himl1, int i1, HIMAGELIST himl2, int i2, int dx, int dy); + +HWND +STDCALL +CreateToolbarEx(HWND hwnd, DWORD ws, UINT wID, int nBitmaps, + HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons, + int iNumButtons, int dxButton, int dyButton, + int dxBitmap, int dyBitmap, UINT uStructSize); + +HBITMAP +STDCALL +CreateMappedBitmap(HINSTANCE hInstance, int idBitmap, + UINT wFlags, LPCOLORMAP lpColorMap, + int iNumMaps); + + +void +STDCALL +MenuHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu, HINSTANCE hInst, HWND hwndStatus, UINT *lpwIDs); + +WINBOOL +STDCALL +ShowHideMenuCtl(HWND hWnd, UINT uFlags, LPINT lpInfo); + +void +STDCALL +GetEffectiveClientRect(HWND hWnd, LPRECT lprc, LPINT lpInfo); + +WINBOOL +STDCALL +MakeDragList(HWND hLB); + +void +STDCALL +DrawInsert(HWND handParent, HWND hLB, int nItem); + +int +STDCALL +LBItemFromPt(HWND hLB, POINT pt, WINBOOL bAutoScroll); + +HWND +STDCALL +CreateUpDownControl(DWORD dwStyle, int x, int y, int cx, int cy, + HWND hParent, int nID, HINSTANCE hInst, + HWND hBuddy, + int nUpper, int nLower, int nPos); + +DWORD +STDCALL +CommDlgExtendedError(VOID); + +/* Animation controls */ + +#define Animate_Create(hwndP, id, dwStyle, hInstance) CreateWindow(ANIMATE_CLASS, NULL, dwStyle, 0, 0, 0, 0, hwndP, (HMENU)(id), hInstance, NULL) + +#define Animate_Open(hwnd, szName) SendMessage(hwnd, ACM_OPEN, 0, (LPARAM)(LPTSTR)(szName)) + +#define Animate_Play(hwnd, from, to, rep) SendMessage(hwnd, ACM_PLAY, (WPARAM)(UINT)(rep), (LPARAM)MAKELONG(from, to)) + +#define Animate_Stop(hwnd) SendMessage(hwnd, ACM_STOP, 0, 0) + +#define Animate_Close(hwnd) Animate_Open(hwnd, NULL) + +#define Animate_Seek(hwnd, frame) Animate_Play(hwnd, frame, frame, 1) + +/* Property sheet macros */ + +#define PropSheet_AddPage(hPropSheetDlg, hpage) SendMessage(hPropSheetDlg, PSM_ADDPAGE, 0, (LPARAM)(HPROPSHEETPAGE)hpage) + +#define PropSheet_Apply(hPropSheetDlg) SendMessage(hPropSheetDlg, PSM_APPLY, 0, 0) + +#define PropSheet_CancelToClose(hPropSheetDlg) SendMessage(hPropSheetDlg, PSM_CANCELTOCLOSE, 0, 0) + +#define PropSheet_Changed(hPropSheetDlg, hwndPage) SendMessage(hPropSheetDlg, PSM_CHANGED, (WPARAM)(HWND)hwndPage, 0) + +#define PropSheet_GetCurrentPageHwnd(hDlg) SendMessage(hDlg, PSM_GETCURRENTPAGEHWND, 0, 0) + +#define PropSheet_GetTabControl(hPropSheetDlg) SendMessage(hPropSheetDlg, PSM_GETTABCONTROL, 0, 0) + +#define PropSheet_IsDialogMessage(hDlg, pMsg) SendMessage(hDlg, PSM_ISDIALOGMESSAGE, 0, (LPARAM)pMsg) + +#define PropSheet_PressButton(hPropSheetDlg, iButton) SendMessage(hPropSheetDlg, PSM_PRESSBUTTON, (WPARAM)(int)iButton, 0) + +#define PropSheet_QuerySiblings(hPropSheetDlg, param1, param2) SendMessage(hPropSheetDlg, PSM_QUERYSIBLINGS, (WPARAM)param1, (LPARAM)param2) + +#define PropSheet_RebootSystem(hPropSheetDlg) SendMessage(hPropSheetDlg, PSM_REBOOTSYSTEM, 0, 0) + +#define PropSheet_RemovePage(hPropSheetDlg, index, hpage) SendMessage(hPropSheetDlg, PSM_REMOVEPAGE, (WPARAM)(int)index, (LPARAM)(HPROPSHEETPAGE)hpage) + +#define PropSheet_RestartWindows(hPropSheetDlg) SendMessage(hPropSheetDlg, PSM_RESTARTWINDOWS, 0, 0) + +#define PropSheet_SetCurSel(hPropSheetDlg, hpage, index) SendMessage(hPropSheetDlg, PSM_SETCURSEL, (WPARAM)(int)index, (LPARAM)(HPROPSHEETPAGE)hpage) + +#define PropSheet_SetCurSelByID(hPropSheetDlg, id) SendMessage(hPropSheetDlg, PSM_SETCURSELID, 0, (LPARAM)(int)id) + +#define PropSheet_SetFinishText(hPropSheetDlg, lpszText) SendMessage(hPropSheetDlg, PSM_SETFINISHTEXT, 0, (LPARAM)(LPTSTR)lpszText) + +#define PropSheet_SetTitle(hPropSheetDlg, dwStyle, lpszText) SendMessage(hPropSheetDlg, PSM_SETTITLE, (WPARAM)(DWORD)dwStyle, (LPARAM)(LPCTSTR)lpszText) + +#define PropSheet_SetWizButtons(hPropSheetDlg, dwFlags) SendMessage(hPropSheetDlg, PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)dwFlags) + +#define PropSheet_UnChanged(hPropSheetDlg, hwndPage) SendMessage(hPropSheetDlg, PSM_UNCHANGED, (WPARAM)(HWND)hwndPage, 0) + +/* Header control */ +#define Header_DeleteItem(hwndHD, index) (BOOL)SendMessage((hwndHD), HDM_DELETEITEM, (WPARAM)(int)(index), 0L) + +#define Header_GetItem(hwndHD, index, phdi) (BOOL)SendMessage((hwndHD), HDM_GETITEM, (WPARAM)(int)(index), (LPARAM)(HD_ITEM FAR*)(phdi)) + +#define Header_GetItemCount(hwndHD) (int)SendMessage((hwndHD), HDM_GETITEMCOUNT, 0, 0L) + +#define Header_InsertItem(hwndHD, index, phdi) (int)SendMessage((hwndHD), HDM_INSERTITEM, (WPARAM)(int)(index), (LPARAM)(const HD_ITEM FAR*)(phdi)) + +#define Header_Layout(hwndHD, playout) (BOOL)SendMessage((hwndHD), HDM_LAYOUT, 0, (LPARAM)(HD_LAYOUT FAR*)(playout)) + +#define Header_SetItem(hwndHD, index, phdi) (BOOL)SendMessage((hwndHD), HDM_SETITEM, (WPARAM)(int)(index), (LPARAM)(const HD_ITEM FAR*)(phdi)) + +/* List View */ +#define ListView_Arrange(hwndLV, code) SendMessage((hwndLV), LVM_ARRANGE, (WPARAM)(UINT)(code), 0) + +#define ListView_CreateDragImage(hwnd, i, lpptUpLeft) SendMessage((hwnd), LVM_CREATEDRAGIMAGE, (WPARAM)(int)(i), (LPARAM)(LPPOINT)(lpptUpLeft)) + +#define ListView_DeleteAllItems(hwnd) SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0) + +#define ListView_DeleteColumn(hwnd, iCol) SendMessage((hwnd), LVM_DELETECOLUMN, (WPARAM)(int)(iCol), 0) + +#define ListView_DeleteItem(hwnd, iItem) SendMessage(hwnd, LVM_DELETEITEM, (WPARAM)(int)iItem, 0) + +#define ListView_EditLabel(hwndLV, i) SendMessage((hwndLV), LVM_EDITLABEL, (WPARAM)(int)i, 0) + +#define ListView_EnsureVisible(hwndLV, i, fPartialOK) SendMessage(hwndLV, LVM_ENSUREVISIBLE, (WPARAM)(int)i, MAKELPARAM((fPartialOK), 0)) + +#define ListView_FindItem(hwnd, iStart, plvfi) SendMessage(hwnd, LVM_FINDITEM, (WPARAM)(int)iStart, (LPARAM)(const LV_FINDINFO *)plvfi) + +#define ListView_GetBkColor(hwnd) SendMessage((HWND)hwnd, LVM_GETBKCOLOR, 0, 0) + +#define ListView_GetCallbackMask(hwnd) SendMessage(hwnd, LVM_GETCALLBACKMASK, 0, 0) + +#define ListView_GetColumn(hwnd, iCol, pcol) SendMessage((hwnd), LVM_GETCOLUMN, (WPARAM)(int)(iCol), (LPARAM)(LV_COLUMN *)(pcol)) + +#define ListView_GetColumnWidth(hwnd, iCol) SendMessage((hwnd), LVM_GETCOLUMNWIDTH, (WPARAM)(int)(iCol), 0) + +#define ListView_GetCountPerPage(hwndLV) SendMessage((hwndLV), LVM_GETCOUNTPERPAGE, 0, 0) + +#define ListView_GetEditControl(hwndLV) SendMessage((hwndLV), LVM_GETEDITCONTROL, 0, 0) + +#define ListView_GetImageList(hwnd, iImageList) SendMessage(hwnd, LVM_GETIMAGELIST, (WPARAM)(INT)iImageList, 0) + +#define ListView_GetISearchString(hwndLV, lpsz) SendMessage((hwndLV), LVM_GETISEARCHSTRING, 0, (LPARAM)(LPTSTR)lpsz) + +#define ListView_GetItem(hwnd, pitem) SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)(LV_ITEM *)(pitem)) + +#define ListView_GetItemCount(hwnd) SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0) + +#define ListView_GetItemPosition(hwndLV, i, ppt) SendMessage(hwndLV, LVM_GETITEMPOSITION, (WPARAM)(int)i, (LPARAM)(POINT *)ppt) + +#define ListView_GetItemRect(hwnd, i, prc, code) SendMessage(hwnd, LVM_GETITEMRECT, (WPARAM)(int)i, ((prc) ? (((RECT *)(prc))->left = (code), (LPARAM)(RECT *)(prc)) : (LPARAM)(RECT *)NULL)) + +#define ListView_GetItemSpacing(hwndLV, fSmall) SendMessage((hwndLV), LVM_GETITEMSPACING, fSmall, 0) + +#define ListView_GetItemState(hwndLV, i, mask) SendMessage((hwndLV), LVM_GETITEMSTATE, (WPARAM)i, (LPARAM)mask) + +#define ListView_GetItemText(hwndLV, i, iSubItem_, pszText_, cchTextMax_) { LV_ITEM _gnu_lvi;_gnu_lvi.iSubItem = iSubItem_;_gnu_lvi.cchTextMax = cchTextMax_;_gnu_lvi.pszText = pszText_;SendMessage((hwndLV), LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)(LV_ITEM *)&_gnu_lvi);} + +#define ListView_GetNextItem(hwnd, iStart, flags) SendMessage(hwnd, LVM_GETNEXTITEM, (WPARAM)(int)iStart, (LPARAM)flags) + +#define ListView_GetOrigin(hwndLV, ppt) SendMessage((hwndLV), LVM_GETORIGIN, (WPARAM)0, (LPARAM)(POINT *)(ppt)) + +#define ListView_GetSelectedCount(hwndLV) SendMessage((hwndLV), LVM_GETSELECTEDCOUNT, 0, 0) + +#define ListView_GetStringWidth(hwndLV, psz) SendMessage(hwndLV, LVM_GETSTRINGWIDTH, 0, (LPARAM)(LPCTSTR)psz) + +#define ListView_GetTextBkColor(hwnd) SendMessage((hwnd), LVM_GETTEXTBKCOLOR, 0, 0) + +#define ListView_GetTextColor(hwnd) SendMessage((hwnd), LVM_GETTEXTCOLOR, 0, 0) + +#define ListView_GetTopIndex(hwndLV) SendMessage((hwndLV), LVM_GETTOPINDEX, 0, 0) + +#define ListView_GetViewRect(hwnd, prc) SendMessage((hwnd), LVM_GETVIEWRECT, 0, (LPARAM)(RECT *)(prc)) + +#define ListView_HitTest(hwndLV, pinfo) SendMessage(hwndLV, LVM_HITTEST, 0, (LPARAM)(LV_HITTESTINFO *)pinfo) + +#define ListView_InsertColumn(hwnd, iCol, pcol) SendMessage((hwnd), LVM_INSERTCOLUMN, (WPARAM)(int)(iCol), (LPARAM)(const LV_COLUMN *)(pcol)) + +#define ListView_InsertItem(hwnd, pitem) SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM *)pitem) + +#define ListView_RedrawItems(hwndLV, iFirst, iLast) SendMessage((hwndLV), LVM_REDRAWITEMS, (WPARAM)(int)iFirst, (LPARAM)(int)iLast) + +#define ListView_Scroll(hwndLV, dx, dy) SendMessage((hwndLV), LVM_SCROLL, (WPARAM)(int)dx, (LPARAM)(int)dy) + +#define ListView_SetBkColor(hwnd, clrBk) SendMessage(hwnd, LVM_SETBKCOLOR, 0, (LPARAM)(COLORREF)clrBk) + +#define ListView_SetCallbackMask(hwnd, mask) SendMessage(hwnd, LVM_SETCALLBACKMASK, (WPARAM)(UINT)(mask), 0) + +#define ListView_SetColumn(hwnd, iCol, pcol) SendMessage((hwnd), LVM_SETCOLUMN, (WPARAM)(int)(iCol), (LPARAM)(const LV_COLUMN *)(pcol)) + +#define ListView_SetColumnWidth(hwnd, iCol, cx) SendMessage((hwnd), LVM_SETCOLUMNWIDTH, (WPARAM)(int)(iCol), MAKELPARAM((cx), 0)) + + +#define ListView_SetImageList(hwnd, himl, iImageList) SendMessage(hwnd, LVM_SETIMAGELIST, (WPARAM)(iImageList), (LPARAM)(UINT)(HIMAGELIST)(himl)) + +#define ListView_SetItem(hwnd, pitem) SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)(const LV_ITEM *)pitem) + +#define ListView_SetItemCount(hwndLV, cItems) SendMessage((hwndLV), LVM_SETITEMCOUNT, (WPARAM)cItems, 0) + +#define ListView_SetItemPosition(hwndLV, i, x, y) SendMessage(hwndLV, LVM_SETITEMPOSITION, (WPARAM)(int)(i), MAKELPARAM((x), (y))) + +#define ListView_SetItemPosition32(hwndLV, i, x, y) { POINT ptNewPos = {x,y}; SendMessage((hwndLV), LVM_SETITEMPOSITION32, (WPARAM)(int)(i), (LPARAM)&ptNewPos); } + +#define ListView_SetItemState(hwndLV, i, data, mask) { LV_ITEM _gnu_lvi; _gnu_lvi.stateMask = mask; _gnu_lvi.state = data; SendMessage((hwndLV), LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)(LV_ITEM *)&_gnu_lvi);} + +#define ListView_SetItemText(hwndLV, i, iSubItem_, pszText_) { LV_ITEM _gnu_lvi; _gnu_lvi.iSubItem = iSubItem_; _gnu_lvi.pszText = pszText_; SendMessage((hwndLV), LVM_SETITEMTEXT, (WPARAM)i, (LPARAM)(LV_ITEM *)&_gnu_lvi);} + +#define ListView_SetTextBkColor(hwnd, clrTextBk) SendMessage((hwnd), LVM_SETTEXTBKCOLOR, 0, (LPARAM)(COLORREF)(clrTextBk)) + +#define ListView_SetTextColor(hwnd, clrText) SendMessage((hwnd), LVM_SETTEXTCOLOR, 0, (LPARAM)(COLORREF)(clrText)) + +#define ListView_SortItems(hwndLV, _pfnCompare, _lPrm) SendMessage((hwndLV), LVM_SORTITEMS, (WPARAM)(LPARAM)_lPrm, (LPARAM)(PFNLVCOMPARE)_pfnCompare) + +#define ListView_Update(hwndLV, i) SendMessage((hwndLV), LVM_UPDATE, (WPARAM)i, 0) + +/* Tree View */ +#define TreeView_InsertItem(hwnd, lpis) SendMessage((hwnd), TVM_INSERTITEM, 0, (LPARAM)(LPTV_INSERTSTRUCT)(lpis)) + +#define TreeView_DeleteItem(hwnd, hitem) SendMessage((hwnd), TVM_DELETEITEM, 0, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_DeleteAllItems(hwnd) SendMessage((hwnd), TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT) + +#define TreeView_Expand(hwnd, hitem, code) SendMessage((hwnd), TVM_EXPAND, (WPARAM)code, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_GetItemRect(hwnd, hitem, prc, code) SendMessage((hwnd), TVM_GETITEMRECT, (WPARAM)(code), (LPARAM)(RECT *)(prc))) + +#define TreeView_GetCount(hwnd) SendMessage((hwnd), TVM_GETCOUNT, 0, 0) + +#define TreeView_GetIndent(hwnd) SendMessage((hwnd), TVM_GETINDENT, 0, 0) + +#define TreeView_SetIndent(hwnd, indent) SendMessage((hwnd), TVM_SETINDENT, (WPARAM)indent, 0) + +#define TreeView_GetImageList(hwnd, iImage) SendMessage((hwnd), TVM_GETIMAGELIST, iImage, 0) + +#define TreeView_SetImageList(hwnd, himl, iImage) SendMessage((hwnd), TVM_SETIMAGELIST, iImage, (LPARAM)(UINT)(HIMAGELIST)(himl)) + +#define TreeView_GetNextItem(hwnd, hitem, code) SendMessage((hwnd), TVM_GETNEXTITEM, (WPARAM)code, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_GetChild(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_CHILD) + +#define TreeView_GetNextSibling(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_NEXT) + +#define TreeView_GetPrevSibling(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_PREVIOUS) + +#define TreeView_GetParent(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_PARENT) + +#define TreeView_GetFirstVisible(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_FIRSTVISIBLE) + +#define TreeView_GetNextVisible(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_NEXTVISIBLE) + +#define TreeView_GetPrevVisible(hwnd, hitem) TreeView_GetNextItem(hwnd, hitem, TVGN_PREVIOUSVISIBLE) + +#define TreeView_GetSelection(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_CARET) + +#define TreeView_GetDropHilight(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_DROPHILITE) + +#define TreeView_GetRoot(hwnd) TreeView_GetNextItem(hwnd, NULL, TVGN_ROOT) + +#define TreeView_Select(hwnd, hitem, code) SendMessage((hwnd), TVM_SELECTITEM, (WPARAM)code, (LPARAM)(HTREEITEM)(hitem)) + + +#define TreeView_SelectItem(hwnd, hitem) TreeView_Select(hwnd, hitem, TVGN_CARET) + +#define TreeView_SelectDropTarget(hwnd, hitem) TreeView_Select(hwnd, hitem, TVGN_DROPHILITE) + +#define TreeView_SelectSetFirstVisible(hwnd, hitem) TreeView_Select(hwnd, hitem, TVGN_FIRSTVISIBLE) + +#define TreeView_GetItem(hwnd, pitem) SendMessage((hwnd), TVM_GETITEM, 0, (LPARAM)(TV_ITEM *)(pitem)) + +#define TreeView_SetItem(hwnd, pitem) SendMessage((hwnd), TVM_SETITEM, 0, (LPARAM)(const TV_ITEM *)(pitem)) + +#define TreeView_EditLabel(hwnd, hitem) SendMessage((hwnd), TVM_EDITLABEL, 0, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_GetEditControl(hwnd) SendMessage((hwnd), TVM_GETEDITCONTROL, 0, 0) + +#define TreeView_GetVisibleCount(hwnd) SendMessage((hwnd), TVM_GETVISIBLECOUNT, 0, 0) + +#define TreeView_HitTest(hwnd, lpht) SendMessage((hwnd), TVM_HITTEST, 0, (LPARAM)(LPTV_HITTESTINFO)(lpht)) + +#define TreeView_CreateDragImage(hwnd, hitem) SendMessage((hwnd), TVM_CREATEDRAGIMAGE, 0, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_SortChildren(hwnd, hitem, recurse) SendMessage((hwnd), TVM_SORTCHILDREN, (WPARAM)recurse, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_EnsureVisible(hwnd, hitem) SendMessage((hwnd), TVM_ENSUREVISIBLE, 0, (LPARAM)(HTREEITEM)(hitem)) + +#define TreeView_SortChildrenCB(hwnd, psort, recurse) SendMessage((hwnd), TVM_SORTCHILDRENCB, (WPARAM)recurse, (LPARAM)(LPTV_SORTCB)(psort)) + +#define TreeView_EndEditLabelNow(hwnd, fCancel) SendMessage((hwnd), TVM_ENDEDITLABELNOW, (WPARAM)fCancel, 0) + +#define TreeView_GetISearchString(hwndTV, lpsz) SendMessage((hwndTV), TVM_GETISEARCHSTRING, 0, (LPARAM)(LPTSTR)lpsz) + + +/* Tab control */ +#define TabCtrl_GetImageList(hwnd) SendMessage((hwnd), TCM_GETIMAGELIST, 0, 0) + +#define TabCtrl_SetImageList(hwnd, himl) SendMessage((hwnd), TCM_SETIMAGELIST, 0, (LPARAM)(UINT)(HIMAGELIST)(himl)) + +#define TabCtrl_GetItemCount(hwnd) SendMessage((hwnd), TCM_GETITEMCOUNT, 0, 0) + +#define TabCtrl_GetItem(hwnd, iItem, pitem) SendMessage((hwnd), TCM_GETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem)) + +#define TabCtrl_SetItem(hwnd, iItem, pitem) SendMessage((hwnd), TCM_SETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem)) + +#define TabCtrl_InsertItem(hwnd, iItem, pitem) SendMessage((hwnd), TCM_INSERTITEM, (WPARAM)(int)iItem, (LPARAM)(const TC_ITEM *)(pitem)) + +#define TabCtrl_DeleteItem(hwnd, i) SendMessage((hwnd), TCM_DELETEITEM, (WPARAM)(int)(i), 0) + +#define TabCtrl_DeleteAllItems(hwnd) SendMessage((hwnd), TCM_DELETEALLITEMS, 0, 0) + +#define TabCtrl_GetItemRect(hwnd, i, prc) SendMessage((hwnd), TCM_GETITEMRECT, (WPARAM)(int)(i), (LPARAM)(RECT *)(prc)) + +#define TabCtrl_GetCurSel(hwnd) SendMessage((hwnd), TCM_GETCURSEL, 0, 0) + +#define TabCtrl_SetCurSel(hwnd, i) SendMessage((hwnd), TCM_SETCURSEL, (WPARAM)i, 0) + +#define TabCtrl_HitTest(hwndTC, pinfo) SendMessage((hwndTC), TCM_HITTEST, 0, (LPARAM)(TC_HITTESTINFO *)(pinfo)) + +#define TabCtrl_SetItemExtra(hwndTC, cb) SendMessage((hwndTC), TCM_SETITEMEXTRA, (WPARAM)(cb), 0) + +#define TabCtrl_AdjustRect(hwnd, bLarger, prc) SendMessage(hwnd, TCM_ADJUSTRECT, (WPARAM)(WINBOOL)bLarger, (LPARAM)(RECT *)prc) + +#define TabCtrl_SetItemSize(hwnd, x, y) SendMessage((hwnd), TCM_SETITEMSIZE, 0, MAKELPARAM(x,y)) + +#define TabCtrl_RemoveImage(hwnd, i) SendMessage((hwnd), TCM_REMOVEIMAGE, i, 0) + +#define TabCtrl_SetPadding(hwnd, cx, cy) SendMessage((hwnd), TCM_SETPADDING, 0, MAKELPARAM(cx, cy)) + +#define TabCtrl_GetRowCount(hwnd) SendMessage((hwnd), TCM_GETROWCOUNT, 0, 0) + +#define TabCtrl_GetToolTips(hwnd) SendMessage((hwnd), TCM_GETTOOLTIPS, 0, 0) + +#define TabCtrl_SetToolTips(hwnd, hwndTT) SendMessage((hwnd), TCM_SETTOOLTIPS, (WPARAM)hwndTT, 0) + +#define TabCtrl_GetCurFocus(hwnd) SendMessage((hwnd), TCM_GETCURFOCUS, 0, 0) + +#define TabCtrl_SetCurFocus(hwnd, i) SendMessage((hwnd),TCM_SETCURFOCUS, i, 0) + +#define CommDlg_OpenSave_GetSpecA(_hdlg, _psz, _cbmax) SNDMSG(_hdlg, CDM_GETSPEC, (WPARAM)_cbmax, (LPARAM)(LPSTR)_psz) + +#define CommDlg_OpenSave_GetSpecW(_hdlg, _psz, _cbmax) SNDMSG(_hdlg, CDM_GETSPEC, (WPARAM)_cbmax, (LPARAM)(LPWSTR)_psz) + +#ifdef UNICODE +#define CommDlg_OpenSave_GetSpec CommDlg_OpenSave_GetSpecW +#else +#define CommDlg_OpenSave_GetSpec CommDlg_OpenSave_GetSpecA +#endif /* !UNICODE */ + +#define CommDlg_OpenSave_GetFilePathA(_hdlg, _psz, _cbmax) SNDMSG(_hdlg, CDM_GETFILEPATH, (WPARAM)_cbmax, (LPARAM)(LPSTR)_psz) + +#define CommDlg_OpenSave_GetFilePathW(_hdlg, _psz, _cbmax) SNDMSG(_hdlg, CDM_GETFILEPATH, (WPARAM)_cbmax, (LPARAM)(LPWSTR)_psz) + +#ifdef UNICODE +#define CommDlg_OpenSave_GetFilePath CommDlg_OpenSave_GetFilePathW +#else +#define CommDlg_OpenSave_GetFilePath CommDlg_OpenSave_GetFilePathA +#endif /* !UNICODE */ + +#define CommDlg_OpenSave_GetFolderPathA(_hdlg, _psz, _cbmax) SNDMSG(_hdlg, CDM_GETFOLDERPATH, (WPARAM)_cbmax, (LPARAM)(LPSTR)_psz) + +#define CommDlg_OpenSave_GetFolderPathW(_hdlg, _psz, _cbmax) SNDMSG(_hdlg, CDM_GETFOLDERPATH, (WPARAM)_cbmax, (LPARAM)(LPWSTR)_psz) + +#ifdef UNICODE +#define CommDlg_OpenSave_GetFolderPath CommDlg_OpenSave_GetFolderPathW +#else +#define CommDlg_OpenSave_GetFolderPath CommDlg_OpenSave_GetFolderPathA +#endif /* !UNICODE */ + +#define CommDlg_OpenSave_GetFolderIDList(_hdlg, _pidl, _cbmax) SNDMSG(_hdlg, CDM_GETFOLDERIDLIST, (WPARAM)_cbmax, (LPARAM)(LPVOID)_pidl) + +#define CommDlg_OpenSave_SetControlText(_hdlg, _id, _text) SNDMSG(_hdlg, CDM_SETCONTROLTEXT, (WPARAM)_id, (LPARAM)(LPSTR)_text) + +#define CommDlg_OpenSave_HideControl(_hdlg, _id) SNDMSG(_hdlg, CDM_HIDECONTROL, (WPARAM)_id, 0) + +#define CommDlg_OpenSave_SetDefExt(_hdlg, _pszext) SNDMSG(_hdlg, CDM_SETDEFEXT, 0, (LPARAM)(LPSTR)_pszext) + +LONG +STDCALL +RegCloseKey ( + HKEY hKey + ); + +LONG +STDCALL +RegSetKeySecurity ( + HKEY hKey, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor + ); + +LONG +STDCALL +RegFlushKey ( + HKEY hKey + ); + +LONG +STDCALL +RegGetKeySecurity ( + HKEY hKey, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + LPDWORD lpcbSecurityDescriptor + ); + +LONG +STDCALL +RegNotifyChangeKeyValue ( + HKEY hKey, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter, + HANDLE hEvent, + WINBOOL fAsynchronus + ); + +WINBOOL +STDCALL +IsValidCodePage( + UINT CodePage); + + +UINT +STDCALL +GetACP(void); + + +UINT +STDCALL +GetOEMCP(void); + + +WINBOOL +STDCALL +GetCPInfo(UINT, LPCPINFO); + + +WINBOOL +STDCALL +IsDBCSLeadByte( + BYTE TestChar); + + +WINBOOL +STDCALL +IsDBCSLeadByteEx( + UINT CodePage, + BYTE TestChar); + + +int +STDCALL +MultiByteToWideChar( + UINT CodePage, + DWORD dwFlags, + LPCSTR lpMultiByteStr, + int cchMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar); + + +int +STDCALL +WideCharToMultiByte( + UINT CodePage, + DWORD dwFlags, + LPCWSTR lpWideCharStr, + int cchWideChar, + LPSTR lpMultiByteStr, + int cchMultiByte, + LPCSTR lpDefaultChar, + LPBOOL lpUsedDefaultChar); + +WINBOOL +STDCALL +IsValidLocale( + LCID Locale, + DWORD dwFlags); + + +LCID +STDCALL +ConvertDefaultLocale( + LCID Locale); + + +LCID +STDCALL +GetThreadLocale(void); + + +WINBOOL +STDCALL +SetThreadLocale( + LCID Locale + ); + + +LANGID +STDCALL +GetSystemDefaultLangID(void); + + +LANGID +STDCALL +GetUserDefaultLangID(void); + + +LCID +STDCALL +GetSystemDefaultLCID(void); + + +LCID +STDCALL +GetUserDefaultLCID(void); + + +WINBOOL +STDCALL +ReadConsoleOutputAttribute( + HANDLE hConsoleOutput, + LPWORD lpAttribute, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfAttrsRead + ); + + +WINBOOL +STDCALL +WriteConsoleOutputAttribute( + HANDLE hConsoleOutput, + CONST WORD *lpAttribute, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfAttrsWritten + ); + + +WINBOOL +STDCALL +FillConsoleOutputAttribute( + HANDLE hConsoleOutput, + WORD wAttribute, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfAttrsWritten + ); + + +WINBOOL +STDCALL +GetConsoleMode( + HANDLE hConsoleHandle, + LPDWORD lpMode + ); + + +WINBOOL +STDCALL +GetNumberOfConsoleInputEvents( + HANDLE hConsoleInput, + LPDWORD lpNumberOfEvents + ); + + +WINBOOL +STDCALL +GetConsoleScreenBufferInfo( + HANDLE hConsoleOutput, + PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo + ); + + +COORD +STDCALL +GetLargestConsoleWindowSize( + HANDLE hConsoleOutput + ); + + +WINBOOL +STDCALL +GetConsoleCursorInfo( + HANDLE hConsoleOutput, + PCONSOLE_CURSOR_INFO lpConsoleCursorInfo + ); + + +WINBOOL +STDCALL +GetNumberOfConsoleMouseButtons( + LPDWORD lpNumberOfMouseButtons + ); + + +WINBOOL +STDCALL +SetConsoleMode( + HANDLE hConsoleHandle, + DWORD dwMode + ); + + +WINBOOL +STDCALL +SetConsoleActiveScreenBuffer( + HANDLE hConsoleOutput + ); + + +WINBOOL +STDCALL +FlushConsoleInputBuffer( + HANDLE hConsoleInput + ); + + +WINBOOL +STDCALL +SetConsoleScreenBufferSize( + HANDLE hConsoleOutput, + COORD dwSize + ); + + +WINBOOL +STDCALL +SetConsoleCursorPosition( + HANDLE hConsoleOutput, + COORD dwCursorPosition + ); + + +WINBOOL +STDCALL +SetConsoleCursorInfo( + HANDLE hConsoleOutput, + CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo + ); + +WINBOOL +STDCALL +SetConsoleWindowInfo( + HANDLE hConsoleOutput, + WINBOOL bAbsolute, + CONST SMALL_RECT *lpConsoleWindow + ); + + +WINBOOL +STDCALL +SetConsoleTextAttribute( + HANDLE hConsoleOutput, + WORD wAttributes + ); + + +WINBOOL +STDCALL +SetConsoleCtrlHandler( + PHANDLER_ROUTINE HandlerRoutine, + WINBOOL Add + ); + + +WINBOOL +STDCALL +GenerateConsoleCtrlEvent( + DWORD dwCtrlEvent, + DWORD dwProcessGroupId + ); + + +WINBOOL +STDCALL +AllocConsole( VOID ); + + +WINBOOL +STDCALL +FreeConsole( VOID ); + + + +HANDLE +STDCALL +CreateConsoleScreenBuffer( + DWORD dwDesiredAccess, + DWORD dwShareMode, + CONST SECURITY_ATTRIBUTES *lpSecurityAttributes, + DWORD dwFlags, + LPVOID lpScreenBufferData + ); + + +UINT +STDCALL +GetConsoleCP( VOID ); + + +WINBOOL +STDCALL +SetConsoleCP( + UINT wCodePageID + ); + + +UINT +STDCALL +GetConsoleOutputCP( VOID ); + + +WINBOOL +STDCALL +SetConsoleOutputCP( + UINT wCodePageID + ); + +DWORD STDCALL +WNetConnectionDialog( + HWND hwnd, + DWORD dwType + ); + +DWORD STDCALL +WNetDisconnectDialog( + HWND hwnd, + DWORD dwType + ); + +DWORD STDCALL +WNetCloseEnum( + HANDLE hEnum + ); + +WINBOOL +STDCALL +CloseServiceHandle( + SC_HANDLE hSCObject + ); + + +WINBOOL +STDCALL +ControlService( + SC_HANDLE hService, + DWORD dwControl, + LPSERVICE_STATUS lpServiceStatus + ); + +WINBOOL +STDCALL +DeleteService( + SC_HANDLE hService + ); + +SC_LOCK +STDCALL +LockServiceDatabase( + SC_HANDLE hSCManager + ); + + +WINBOOL +STDCALL +NotifyBootConfigStatus( + WINBOOL BootAcceptable + ); + +WINBOOL +STDCALL +QueryServiceObjectSecurity( + SC_HANDLE hService, + SECURITY_INFORMATION dwSecurityInformation, + PSECURITY_DESCRIPTOR lpSecurityDescriptor, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ); + + +WINBOOL +STDCALL +QueryServiceStatus( + SC_HANDLE hService, + LPSERVICE_STATUS lpServiceStatus + ); + +WINBOOL +STDCALL +SetServiceObjectSecurity( + SC_HANDLE hService, + SECURITY_INFORMATION dwSecurityInformation, + PSECURITY_DESCRIPTOR lpSecurityDescriptor + ); + + +WINBOOL +STDCALL +SetServiceStatus( + SERVICE_STATUS_HANDLE hServiceStatus, + LPSERVICE_STATUS lpServiceStatus + ); + +WINBOOL +STDCALL +UnlockServiceDatabase( + SC_LOCK ScLock + ); + +/* Extensions to OpenGL */ + +int STDCALL +ChoosePixelFormat(HDC, CONST PIXELFORMATDESCRIPTOR *); + +int STDCALL +DescribePixelFormat(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); + +UINT STDCALL +GetEnhMetaFilePixelFormat(HENHMETAFILE, DWORD, + CONST PIXELFORMATDESCRIPTOR *); + +int STDCALL +GetPixelFormat(HDC); + +WINBOOL STDCALL +SetPixelFormat(HDC, int, CONST PIXELFORMATDESCRIPTOR *); + +WINBOOL STDCALL +SwapBuffers(HDC); + +HGLRC STDCALL +wglCreateContext(HDC); + +HGLRC STDCALL +wglCreateLayerContext(HDC, int); + +WINBOOL STDCALL +wglCopyContext(HGLRC, HGLRC, UINT); + +WINBOOL STDCALL +wglDeleteContext(HGLRC); + +WINBOOL STDCALL +wglDescribeLayerPlane(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR); + +HGLRC STDCALL +wglGetCurrentContext(VOID); + +HDC STDCALL +wglGetCurrentDC(VOID); + +int STDCALL +wglGetLayerPaletteEntries(HDC, int, int, int, CONST COLORREF *); + +PROC STDCALL +wglGetProcAddress(LPCSTR); + +WINBOOL STDCALL +wglMakeCurrent(HDC, HGLRC); + +WINBOOL STDCALL +wglRealizeLayerPalette(HDC, int, WINBOOL); + +int STDCALL +wglSetLayerPaletteEntries(HDC, int, int, int, CONST COLORREF *); + +WINBOOL STDCALL +wglShareLists(HGLRC, HGLRC); + +WINBOOL STDCALL +wglSwapLayerBuffers(HDC, UINT); + +/* + Why are these different between ANSI and UNICODE? + There doesn't seem to be any difference. + */ + +#ifdef UNICODE +#define wglUseFontBitmaps wglUseFontBitmapsW +#define wglUseFontOutlines wglUseFontOutlinesW +#else +#define wglUseFontBitmaps wglUseFontBitmapsA +#define wglUseFontOutlines wglUseFontOutlinesA +#endif /* !UNICODE */ + +/* ------------------------------------- */ +/* From shellapi.h in old Cygnus headers */ + +WINBOOL WINAPI +DragQueryPoint (HDROP, LPPOINT); + +void WINAPI +DragFinish (HDROP); + +void WINAPI +DragAcceptFiles (HWND, WINBOOL); + +HICON WINAPI +DuplicateIcon (HINSTANCE, HICON); + +/* end of stuff from shellapi.h in old Cygnus headers */ +/* -------------------------------------------------- */ +/* From ddeml.h in old Cygnus headers */ + +HCONV WINAPI DdeConnect (DWORD, HSZ, HSZ, CONVCONTEXT *); +WINBOOL WINAPI DdeDisconnect (HCONV); +WINBOOL WINAPI DdeFreeDataHandle (HDDEDATA); +DWORD WINAPI DdeGetData (HDDEDATA, BYTE *, DWORD, DWORD); +UINT WINAPI DdeGetLastError (DWORD); +HDDEDATA WINAPI DdeNameService (DWORD, HSZ, HSZ, UINT); +WINBOOL WINAPI DdePostAdvise (DWORD, HSZ, HSZ); +HCONV WINAPI DdeReconnect (HCONV); +WINBOOL WINAPI DdeUninitialize (DWORD); +int WINAPI DdeCmpStringHandles (HSZ, HSZ); +HDDEDATA WINAPI DdeCreateDataHandle (DWORD, LPBYTE, DWORD, DWORD, HSZ, + UINT, UINT); + +/* end of stuff from ddeml.h in old Cygnus headers */ +/* ----------------------------------------------- */ + +DWORD STDCALL NetUserEnum (LPWSTR, DWORD, DWORD, LPBYTE*, DWORD, LPDWORD, + LPDWORD, LPDWORD); +DWORD STDCALL NetApiBufferFree (LPVOID); +DWORD STDCALL NetUserGetInfo (LPWSTR, LPWSTR, DWORD, LPBYTE); +DWORD STDCALL NetGetDCName (LPWSTR, LPWSTR, LPBYTE*); +DWORD STDCALL NetGroupEnum (LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, + LPDWORD, LPDWORD); +DWORD STDCALL NetLocalGroupEnum (LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, + LPDWORD, LPDWORD); + + +VOID CopyMemory(PVOID Destination, CONST VOID* Source, DWORD Length); + +DWORD STDCALL GetCurrentTime(VOID); + +void WINAPI +SHAddToRecentDocs (UINT, LPCVOID); + +LPITEMIDLIST WINAPI +SHBrowseForFolder (LPBROWSEINFO); + +void WINAPI +SHChangeNotify (LONG, UINT, LPCVOID, LPCVOID); + +int WINAPI +SHFileOperation (LPSHFILEOPSTRUCT); + +void WINAPI +SHFreeNameMappings (HANDLE); + +/* Define when SHELLFOLDER is defined. +HRESULT WINAPI +SHGetDataFromIDList (LPSHELLFOLDER, LPCITEMIDLIST, int, PVOID, int); + +HRESULT WINAPI +SHGetDesktopFolder (LPSHELLFOLDER); +*/ + +DWORD WINAPI +SHGetFileInfo (LPCTSTR, DWORD, SHFILEINFO FAR *, UINT, UINT); + +/* Define when IUnknown is defined. +HRESULT WINAPI +SHGetInstanceExplorer (IUnknown **); +*/ + +/* Define when MALLOC is defined. +HRESULT WINAPI +SHGetMalloc (LPMALLOC *); +*/ + +WINBOOL WINAPI +SHGetPathFromIDList (LPCITEMIDLIST, LPTSTR); + +HRESULT WINAPI +SHGetSpecialFolderLocation (HWND, int, LPITEMIDLIST *); + +/* Define when REFCLSID is defined. +HRESULT WINAPI +SHLoadInProc (REFCLSID); +*/ + +/* Win32 Fibers */ + +typedef +VOID (WINAPI *PFIBER_START_ROUTINE) ( + IN LPVOID lpFiberArgument + ); +typedef PFIBER_START_ROUTINE LPFIBER_START_ROUTINE; + +LPVOID +STDCALL +ConvertThreadToFiber ( + LPVOID lpArgument + ); +LPVOID +STDCALL +CreateFiber ( + DWORD dwStackSize, + LPFIBER_START_ROUTINE lpStartAddress, + LPVOID lpArgument + ); +VOID +STDCALL +DeleteFiber( + LPVOID lpFiber + ); +PVOID +STDCALL +GetCurrentFiber ( + VOID + ); +PVOID +STDCALL +GetFiberData ( + VOID + ); +VOID +STDCALL +SwitchToFiber ( + LPVOID lpFiber + ); + + +WINBOOL STDCALL +RegisterServicesProcess(DWORD ServicesProcessId); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* WIN32_LEAN_AND_MEAN */ + +#endif /* _GNU_H_WINDOWS32_FUNCTIONS */ diff --git a/include/getopt.h b/include/getopt.h new file mode 100644 index 0000000..43dc804 --- /dev/null +++ b/include/getopt.h @@ -0,0 +1,53 @@ +/* temporary header for getopt. Please remove this file when MingW ships with + its own */ + +#ifndef __GETOPT_H_INCLUDED +#define __GETOPT_H_INCLUDED + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern char *optarg; +extern int optind, opterr, optopt; + +#define no_argument (0) +#define required_argument (1) +#define optional_argument (2) + +struct option +{ + const char *name; + int has_arg; + int *flag; + int val; +}; + +extern int getopt(int, char * const [], const char *); + +extern int getopt_long +( + int, + char * const [], + const char *, + const struct option *, + int * +); + +extern int getopt_long_only +( + int, + char * const [], + const char *, + const struct option *, + int * +); + +#ifdef __cplusplus +} +#endif + +#endif /* __GETOPT_H_INCLUDED */ + +/* EOF */ diff --git a/include/in.h b/include/in.h new file mode 100644 index 0000000..a6d0b85 --- /dev/null +++ b/include/in.h @@ -0,0 +1,491 @@ +unsigned int wavelength=3891; + +unsigned char wave[]={ +0x52,0x49,0x46,0x46,0x2b,0xf,0x0,0x0, +0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20, +0x10,0x0,0x0,0x0,0x1,0x0,0x1,0x0, +0x22,0x56,0x0,0x0,0x22,0x56,0x0,0x0, +0x1,0x0,0x8,0x0,0x64,0x61,0x74,0x61, +0x7,0xf,0x0,0x0,0x80,0xce,0xb2,0x53, +0x2e,0x75,0xca,0xbb,0x5d,0x2c,0x6a,0xc4, +0xc2,0x68,0x2c,0x5f,0xbd,0xc8,0x74,0x2e, +0x51,0xad,0xd0,0x8a,0x36,0x3f,0x98,0xd2, +0xa2,0x46,0x33,0x81,0xcd,0xb5,0x58,0x2d, +0x67,0xbe,0xc8,0x78,0x30,0x49,0xa3,0xd2, +0x9b,0x43,0x34,0x80,0xcc,0xb9,0x60,0x2c, +0x5e,0xb6,0xce,0x89,0x39,0x3b,0x8b,0xce, +0xb4,0x5c,0x2d,0x5e,0xb6,0xce,0x89,0x39, +0x3a,0x8b,0xce,0xb7,0x62,0x2d,0x54,0xaa, +0xd1,0x9b,0x46,0x31,0x74,0xc2,0xc7,0x7b, +0x34,0x41,0x94,0xcf,0xb3,0x61,0x2e,0x53, +0xa6,0xd1,0xa3,0x4f,0x2e,0x65,0xb7,0xce, +0x90,0x41,0x33,0x78,0xc3,0xc8,0x83,0x3a, +0x38,0x80,0xc6,0xc4,0x7d,0x36,0x3c,0x86, +0xc9,0xc0,0x76,0x34,0x40,0x8d,0xcb,0xbe, +0x74,0x34,0x3e,0x87,0xc9,0xc1,0x78,0x36, +0x3b,0x83,0xc7,0xc4,0x7e,0x39,0x39,0x7d, +0xc2,0xc9,0x8a,0x42,0x32,0x6a,0xb6,0xce, +0x9c,0x4f,0x2e,0x5b,0xa8,0xd0,0xab,0x5d, +0x2f,0x49,0x94,0xcb,0xbe,0x78,0x39,0x38, +0x77,0xbd,0xcc,0x95,0x4a,0x2f,0x5c,0xa7, +0xcf,0xb0,0x68,0x33,0x40,0x83,0xc3,0xc9, +0x8e,0x47,0x30,0x5c,0xa6,0xcf,0xb2,0x6b, +0x34,0x3e,0x7e,0xbf,0xcc,0x99,0x51,0x2f, +0x4f,0x96,0xcb,0xc1,0x81,0x40,0x32,0x64, +0xab,0xcf,0xb0,0x6c,0x36,0x39,0x74,0xb7, +0xce,0xa7,0x61,0x32,0x40,0x80,0xbe,0xcc, +0x9d,0x56,0x30,0x48,0x88,0xc3,0xca,0x99, +0x54,0x30,0x47,0x88,0xc2,0xca,0x98,0x55, +0x30,0x47,0x87,0xc1,0xca,0x9a,0x58,0x31, +0x42,0x80,0xbb,0xcd,0xa5,0x63,0x34,0x3b, +0x73,0xb3,0xce,0xb1,0x6f,0x39,0x36,0x66, +0xa6,0xcc,0xbe,0x84,0x47,0x30,0x50,0x8f, +0xc4,0xc9,0x9b,0x5c,0x33,0x3f,0x77,0xb4, +0xce,0xb2,0x77,0x40,0x32,0x57,0x96,0xc6, +0xc7,0x99,0x5a,0x33,0x3e,0x73,0xb0,0xcd, +0xb7,0x7e,0x45,0x31,0x4e,0x88,0xbe,0xcc, +0xa9,0x6c,0x3b,0x34,0x5d,0x99,0xc7,0xc7, +0x99,0x5d,0x35,0x3a,0x69,0xa3,0xca,0xc3, +0x93,0x58,0x33,0x3c,0x6e,0xa8,0xcb,0xc0, +0x8f,0x54,0x33,0x3f,0x6f,0xa8,0xcb,0xc1, +0x91,0x58,0x34,0x3b,0x69,0xa3,0xc9,0xc5, +0x98,0x5f,0x37,0x38,0x61,0x99,0xc4,0xc9, +0xa5,0x6d,0x3e,0x33,0x52,0x88,0xba,0xcc, +0xb3,0x80,0x4b,0x32,0x44,0x76,0xac,0xca, +0xc2,0x96,0x5f,0x38,0x36,0x5b,0x91,0xbf, +0xcb,0xaf,0x7b,0x49,0x32,0x44,0x75,0xa9, +0xc9,0xc4,0x9d,0x68,0x3d,0x34,0x50,0x83, +0xb5,0xcb,0xbc,0x8f,0x59,0x37,0x38,0x5d, +0x91,0xbd,0xcb,0xb6,0x85,0x53,0x35,0x3a, +0x60,0x94,0xbe,0xcb,0xb3,0x83,0x51,0x34, +0x3c,0x62,0x95,0xbe,0xcb,0xb6,0x87,0x56, +0x37,0x39,0x5a,0x8c,0xb9,0xcb,0xbb,0x90, +0x5d,0x3a,0x35,0x52,0x80,0xb0,0xc9,0xc3, +0x9f,0x6e,0x44,0x33,0x43,0x6d,0x9f,0xc2, +0xc9,0xaf,0x81,0x53,0x37,0x39,0x57,0x85, +0xb2,0xc9,0xc2,0x9f,0x6e,0x45,0x34,0x41, +0x68,0x98,0xbe,0xca,0xb8,0x8e,0x61,0x3d, +0x34,0x49,0x72,0xa1,0xc2,0xc9,0xb2,0x88, +0x5a,0x3b,0x36,0x4e,0x7a,0xa6,0xc4,0xc8, +0xb0,0x85,0x59,0x3b,0x36,0x4d,0x76,0xa3, +0xc3,0xc9,0xb3,0x89,0x5d,0x3d,0x35,0x49, +0x70,0x9c,0xbe,0xc9,0xba,0x96,0x6a,0x44, +0x35,0x40,0x61,0x8d,0xb4,0xc8,0xc2,0xa4, +0x7a,0x51,0x38,0x38,0x4f,0x78,0xa2,0xc0, +0xc9,0xb8,0x93,0x68,0x45,0x35,0x3f,0x5f, +0x89,0xaf,0xc6,0xc6,0xad,0x86,0x5e,0x3f, +0x35,0x43,0x66,0x8f,0xb4,0xc7,0xc3,0xa9, +0x81,0x58,0x3d,0x36,0x46,0x67,0x8f,0xb4, +0xc7,0xc4,0xab,0x85,0x5d,0x3f,0x36,0x43, +0x63,0x8a,0xb0,0xc5,0xc6,0xb1,0x8e,0x66, +0x46,0x36,0x3c,0x56,0x7d,0xa2,0xbf,0xc8, +0xbc,0x9c,0x77,0x51,0x3a,0x37,0x48,0x69, +0x8f,0xb2,0xc5,0xc5,0xb2,0x8f,0x69,0x48, +0x37,0x3b,0x51,0x75,0x9b,0xba,0xc7,0xc1, +0xaa,0x86,0x62,0x44,0x37,0x3d,0x55,0x79, +0x9d,0xba,0xc7,0xc1,0xa8,0x85,0x61,0x44, +0x37,0x3c,0x54,0x75,0x99,0xb7,0xc6,0xc3, +0xae,0x8e,0x69,0x4a,0x39,0x3a,0x4c,0x6b, +0x8f,0xaf,0xc3,0xc6,0xb8,0x9c,0x79,0x57, +0x3f,0x37,0x41,0x59,0x7c,0x9e,0xb9,0xc6, +0xc2,0xad,0x8e,0x6c,0x4d,0x3b,0x38,0x46, +0x61,0x82,0xa4,0xbc,0xc7,0xc0,0xaa,0x8a, +0x68,0x4b,0x3a,0x39,0x48,0x62,0x84,0xa4, +0xbc,0xc6,0xc1,0xad,0x8d,0x6d,0x4f,0x3c, +0x38,0x44,0x5d,0x7d,0x9d,0xb6,0xc5,0xc4, +0xb5,0x99,0x79,0x5b,0x43,0x38,0x3d,0x50, +0x6c,0x8c,0xab,0xbf,0xc6,0xbf,0xaa,0x8d, +0x6e,0x52,0x3e,0x38,0x41,0x56,0x73,0x92, +0xae,0xc1,0xc6,0xbc,0xa5,0x87,0x6a,0x4f, +0x3d,0x39,0x41,0x57,0x73,0x92,0xad,0xbf, +0xc5,0xbe,0xa9,0x8d,0x70,0x53,0x40,0x39, +0x3f,0x50,0x6b,0x88,0xa5,0xba,0xc5,0xc2, +0xb3,0x9a,0x7e,0x61,0x49,0x3b,0x3a,0x46, +0x5b,0x78,0x94,0xae,0xbf,0xc5,0xbe,0xad, +0x93,0x77,0x5b,0x46,0x3b,0x3b,0x47,0x5b, +0x77,0x92,0xac,0xbe,0xc5,0xc0,0xb1,0x9a, +0x7e,0x63,0x4c,0x3e,0x3a,0x41,0x52,0x6a, +0x85,0x9f,0xb4,0xc1,0xc4,0xbc,0xab,0x93, +0x79,0x5f,0x4a,0x3d,0x3a,0x42,0x53,0x6a, +0x82,0x9c,0xb1,0xc0,0xc4,0xbf,0xb0,0x9a, +0x80,0x68,0x51,0x42,0x3a,0x3d,0x48,0x5c, +0x73,0x8d,0xa4,0xb7,0xc2,0xc3,0xbc,0xac, +0x96,0x7e,0x67,0x51,0x42,0x3b,0x3d,0x48, +0x5a,0x70,0x88,0x9f,0xb2,0xbf,0xc3,0xbf, +0xb3,0xa1,0x89,0x72,0x5c,0x4a,0x3e,0x3b, +0x3f,0x4c,0x5e,0x75,0x8a,0xa1,0xb3,0xbf, +0xc3,0xbf,0xb5,0xa3,0x8e,0x77,0x61,0x4e, +0x41,0x3b,0x3d,0x46,0x55,0x69,0x80,0x95, +0xa9,0xb8,0xc1,0xc3,0xbd,0xb0,0x9f,0x8a, +0x75,0x61,0x4e,0x42,0x3c,0x3d,0x44,0x52, +0x65,0x7a,0x8e,0xa2,0xb2,0xbd,0xc2,0xc0, +0xb8,0xaa,0x98,0x83,0x6f,0x5c,0x4c,0x41, +0x3c,0x3d,0x45,0x52,0x63,0x77,0x8b,0x9e, +0xaf,0xbb,0xc1,0xc1,0xbc,0xb1,0xa1,0x8f, +0x7b,0x67,0x56,0x48,0x3f,0x3c,0x3f,0x47, +0x54,0x65,0x77,0x8a,0x9d,0xad,0xb9,0xc0, +0xc2,0xbe,0xb5,0xa7,0x97,0x83,0x72,0x60, +0x50,0x45,0x3e,0x3d,0x40,0x49,0x56,0x66, +0x78,0x8a,0x9c,0xab,0xb7,0xbf,0xc1,0xbf, +0xb8,0xac,0x9d,0x8c,0x7b,0x6a,0x59,0x4c, +0x43,0x3d,0x3d,0x42,0x4b,0x57,0x67,0x79, +0x89,0x9a,0xa8,0xb5,0xbd,0xc1,0xc0,0xbb, +0xb1,0xa5,0x95,0x84,0x74,0x63,0x56,0x4a, +0x42,0x3e,0x3e,0x43,0x4b,0x57,0x66,0x75, +0x85,0x95,0xa4,0xb0,0xba,0xbf,0xc0,0xbe, +0xb7,0xad,0xa0,0x92,0x81,0x72,0x63,0x55, +0x4a,0x42,0x3e,0x3e,0x42,0x48,0x53,0x60, +0x6e,0x7e,0x8d,0x9b,0xa9,0xb4,0xbb,0xbf, +0xc0,0xbd,0xb7,0xad,0xa1,0x93,0x84,0x75, +0x67,0x5a,0x4f,0x46,0x40,0x3e,0x3f,0x44, +0x4b,0x56,0x63,0x71,0x80,0x8d,0x9a,0xa7, +0xb1,0xb9,0xbe,0xc0,0xbe,0xb9,0xb2,0xa7, +0x9c,0x8e,0x80,0x73,0x65,0x59,0x4f,0x47, +0x41,0x3f,0x3f,0x43,0x49,0x53,0x5d,0x69, +0x76,0x84,0x91,0x9e,0xa9,0xb3,0xba,0xbe, +0xbf,0xbe,0xba,0xb3,0xaa,0xa0,0x93,0x86, +0x7a,0x6d,0x60,0x55,0x4d,0x46,0x41,0x3f, +0x40,0x44,0x49,0x51,0x5c,0x66,0x72,0x80, +0x8b,0x97,0xa2,0xac,0xb4,0xba,0xbd,0xbe, +0xbd,0xb9,0xb4,0xab,0xa1,0x96,0x8b,0x80, +0x73,0x68,0x5d,0x52,0x4b,0x45,0x41,0x40, +0x41,0x44,0x49,0x50,0x58,0x63,0x6e,0x7a, +0x85,0x90,0x9b,0xa5,0xae,0xb5,0xba,0xbd, +0xbe,0xbd,0xba,0xb4,0xae,0xa5,0x9b,0x91, +0x85,0x7b,0x70,0x65,0x5b,0x53,0x4b,0x46, +0x42,0x41,0x41,0x43,0x47,0x4c,0x54,0x5d, +0x67,0x71,0x7c,0x86,0x90,0x9a,0xa3,0xac, +0xb3,0xb8,0xbb,0xbd,0xbd,0xbb,0xb7,0xb2, +0xac,0xa3,0x9b,0x91,0x87,0x7d,0x72,0x69, +0x5f,0x57,0x50,0x4a,0x45,0x42,0x41,0x42, +0x43,0x47,0x4c,0x53,0x5b,0x63,0x6c,0x76, +0x80,0x88,0x93,0x9c,0xa4,0xab,0xb1,0xb6, +0xba,0xbc,0xbd,0xbc,0xb9,0xb5,0xb0,0xaa, +0xa2,0x9a,0x91,0x87,0x80,0x76,0x6c,0x63, +0x5c,0x55,0x4e,0x49,0x45,0x43,0x42,0x42, +0x44,0x47,0x4b,0x50,0x57,0x5e,0x66,0x6f, +0x78,0x80,0x89,0x92,0x9a,0xa2,0xa8,0xae, +0xb4,0xb7,0xba,0xbc,0xbc,0xbb,0xb8,0xb5, +0xb0,0xab,0xa4,0x9d,0x95,0x8d,0x85,0x7c, +0x74,0x6c,0x64,0x5c,0x56,0x51,0x4c,0x48, +0x45,0x43,0x43,0x43,0x45,0x48,0x4b,0x50, +0x56,0x5d,0x63,0x6b,0x73,0x7b,0x82,0x8a, +0x92,0x99,0xa0,0xa7,0xac,0xb1,0xb5,0xb8, +0xba,0xbb,0xbb,0xba,0xb8,0xb4,0xb1,0xac, +0xa6,0xa0,0x9a,0x92,0x8b,0x83,0x7c,0x75, +0x6d,0x66,0x60,0x5a,0x54,0x4f,0x4b,0x48, +0x45,0x44,0x43,0x44,0x45,0x47,0x4a,0x4e, +0x53,0x58,0x5e,0x64,0x6b,0x72,0x79,0x80, +0x87,0x8d,0x94,0x9b,0xa1,0xa6,0xac,0xaf, +0xb3,0xb6,0xb8,0xba,0xba,0xba,0xb9,0xb7, +0xb4,0xb0,0xad,0xa8,0xa2,0x9d,0x97,0x90, +0x8a,0x83,0x7d,0x76,0x70,0x69,0x64,0x5d, +0x59,0x53,0x50,0x4c,0x49,0x47,0x45,0x44, +0x44,0x45,0x46,0x48,0x4b,0x4f,0x52,0x57, +0x5c,0x61,0x67,0x6c,0x72,0x79,0x80,0x85, +0x8b,0x91,0x96,0x9c,0xa2,0xa7,0xab,0xaf, +0xb2,0xb5,0xb7,0xb8,0xb9,0xb9,0xb9,0xb8, +0xb6,0xb4,0xb1,0xae,0xaa,0xa6,0xa1,0x9c, +0x96,0x91,0x8c,0x86,0x80,0x7a,0x75,0x6f, +0x6a,0x64,0x5f,0x5b,0x56,0x52,0x4f,0x4c, +0x4a,0x48,0x46,0x46,0x45,0x46,0x47,0x48, +0x4a,0x4c,0x4f,0x52,0x56,0x5a,0x5e,0x63, +0x68,0x6e,0x72,0x78,0x7d,0x82,0x88,0x8c, +0x92,0x97,0x9b,0xa0,0xa4,0xa8,0xac,0xaf, +0xb1,0xb3,0xb6,0xb7,0xb8,0xb8,0xb8,0xb7, +0xb6,0xb5,0xb3,0xb0,0xad,0xaa,0xa7,0xa3, +0x9f,0x9b,0x97,0x92,0x8c,0x87,0x82,0x7f, +0x7a,0x75,0x70,0x6b,0x66,0x62,0x5e,0x5a, +0x56,0x54,0x51,0x4e,0x4c,0x4a,0x49,0x47, +0x47,0x47,0x47,0x47,0x48,0x4a,0x4b,0x4d, +0x50,0x53,0x55,0x59,0x5d,0x61,0x64,0x68, +0x6d,0x71,0x76,0x7b,0x7f,0x82,0x87,0x8b, +0x90,0x95,0x98,0x9c,0xa0,0xa3,0xa7,0xaa, +0xad,0xaf,0xb1,0xb3,0xb4,0xb5,0xb6,0xb7, +0xb7,0xb6,0xb6,0xb5,0xb3,0xb2,0xb0,0xad, +0xab,0xa8,0xa5,0xa2,0x9e,0x9a,0x96,0x93, +0x8e,0x8a,0x86,0x81,0x7f,0x7a,0x76,0x72, +0x6d,0x6a,0x65,0x62,0x5e,0x5b,0x58,0x55, +0x53,0x50,0x4e,0x4c,0x4b,0x4a,0x49,0x48, +0x48,0x48,0x49,0x49,0x4a,0x4b,0x4d,0x4f, +0x51,0x54,0x56,0x59,0x5c,0x5f,0x63,0x66, +0x6a,0x6e,0x72,0x76,0x7a,0x7e,0x80,0x85, +0x89,0x8d,0x90,0x94,0x98,0x9c,0x9f,0xa2, +0xa5,0xa7,0xaa,0xac,0xae,0xb0,0xb2,0xb3, +0xb4,0xb5,0xb5,0xb5,0xb5,0xb5,0xb4,0xb3, +0xb2,0xb0,0xaf,0xad,0xab,0xa8,0xa6,0xa3, +0xa0,0x9d,0x9a,0x96,0x93,0x8f,0x8c,0x88, +0x84,0x80,0x7e,0x7a,0x76,0x72,0x6f,0x6b, +0x68,0x65,0x62,0x5f,0x5c,0x59,0x57,0x54, +0x52,0x50,0x4f,0x4d,0x4c,0x4b,0x4a,0x4a, +0x4a,0x4a,0x4a,0x4a,0x4b,0x4c,0x4d,0x4f, +0x50,0x52,0x54,0x56,0x59,0x5c,0x5e,0x61, +0x64,0x67,0x6a,0x6d,0x71,0x74,0x77,0x7b, +0x7f,0x81,0x84,0x88,0x8b,0x8e,0x92,0x95, +0x98,0x9b,0x9e,0xa1,0xa3,0xa5,0xa8,0xaa, +0xac,0xad,0xaf,0xb0,0xb1,0xb2,0xb3,0xb3, +0xb3,0xb3,0xb3,0xb3,0xb2,0xb2,0xb1,0xb0, +0xae,0xac,0xab,0xa9,0xa7,0xa4,0xa2,0xa0, +0x9d,0x9a,0x97,0x95,0x91,0x8f,0x8b,0x89, +0x85,0x82,0x80,0x7d,0x79,0x76,0x73,0x70, +0x6d,0x6a,0x68,0x65,0x62,0x5f,0x5d,0x5b, +0x59,0x56,0x55,0x53,0x51,0x50,0x4f,0x4e, +0x4d,0x4c,0x4c,0x4c,0x4b,0x4b,0x4c,0x4c, +0x4d,0x4e,0x4e,0x50,0x51,0x53,0x54,0x56, +0x58,0x5a,0x5b,0x5d,0x60,0x63,0x65,0x68, +0x6a,0x6d,0x70,0x73,0x76,0x78,0x7c,0x7f, +0x80,0x84,0x87,0x89,0x8c,0x8f,0x92,0x94, +0x97,0x99,0x9c,0x9e,0xa0,0xa2,0xa5,0xa6, +0xa8,0xaa,0xab,0xad,0xae,0xaf,0xaf,0xb0, +0xb1,0xb1,0xb2,0xb2,0xb2,0xb1,0xb1,0xb1, +0xb0,0xaf,0xae,0xad,0xac,0xab,0xa9,0xa8, +0xa5,0xa4,0xa2,0xa0,0x9e,0x9c,0x99,0x97, +0x95,0x92,0x90,0x8d,0x8b,0x88,0x86,0x82, +0x80,0x7e,0x7b,0x78,0x76,0x73,0x71,0x6e, +0x6c,0x69,0x67,0x65,0x63,0x60,0x5e,0x5d, +0x5b,0x59,0x57,0x56,0x54,0x53,0x52,0x51, +0x50,0x50,0x4f,0x4e,0x4e,0x4e,0x4d,0x4d, +0x4e,0x4e,0x4e,0x4f,0x4f,0x50,0x51,0x52, +0x53,0x54,0x56,0x57,0x58,0x5a,0x5c,0x5e, +0x60,0x62,0x63,0x65,0x67,0x6a,0x6c,0x6f, +0x71,0x73,0x75,0x78,0x7a,0x7d,0x7f,0x80, +0x83,0x85,0x88,0x8a,0x8c,0x8f,0x91,0x93, +0x95,0x97,0x99,0x9b,0x9d,0x9f,0xa1,0xa2, +0xa4,0xa5,0xa7,0xa8,0xa9,0xaa,0xab,0xac, +0xad,0xae,0xae,0xaf,0xaf,0xaf,0xaf,0xaf, +0xaf,0xaf,0xaf,0xae,0xae,0xad,0xad,0xac, +0xab,0xaa,0xa9,0xa8,0xa7,0xa5,0xa4,0xa3, +0xa1,0x9f,0x9e,0x9c,0x9a,0x98,0x96,0x95, +0x92,0x91,0x8e,0x8c,0x8a,0x88,0x86,0x84, +0x81,0x80,0x7e,0x7c,0x7a,0x78,0x75,0x73, +0x71,0x6f,0x6d,0x6b,0x6a,0x67,0x66,0x64, +0x63,0x61,0x5f,0x5e,0x5c,0x5b,0x5a,0x58, +0x57,0x56,0x55,0x54,0x53,0x53,0x52,0x51, +0x51,0x50,0x50,0x50,0x50,0x50,0x50,0x50, +0x50,0x50,0x51,0x51,0x52,0x53,0x53,0x54, +0x55,0x56,0x57,0x58,0x59,0x5a,0x5c,0x5d, +0x5f,0x60,0x61,0x63,0x64,0x66,0x68,0x69, +0x6c,0x6d,0x6f,0x71,0x73,0x74,0x77,0x78, +0x7a,0x7c,0x7e,0x80,0x81,0x83,0x84,0x87, +0x88,0x8a,0x8c,0x8e,0x8f,0x92,0x93,0x94, +0x96,0x98,0x99,0x9b,0x9d,0x9e,0x9f,0xa0, +0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9, +0xa9,0xaa,0xaa,0xab,0xac,0xac,0xac,0xac, +0xad,0xad,0xad,0xad,0xad,0xac,0xac,0xac, +0xac,0xab,0xab,0xaa,0xaa,0xa9,0xa8,0xa7, +0xa6,0xa6,0xa5,0xa4,0xa2,0xa1,0xa0,0x9f, +0x9e,0x9d,0x9b,0x99,0x98,0x97,0x95,0x94, +0x93,0x90,0x8f,0x8d,0x8c,0x8a,0x89,0x87, +0x86,0x83,0x82,0x80,0x80,0x7e,0x7c,0x7b, +0x79,0x78,0x76,0x75,0x72,0x71,0x6f,0x6e, +0x6c,0x6b,0x6a,0x68,0x67,0x66,0x64,0x63, +0x62,0x61,0x60,0x5e,0x5d,0x5c,0x5b,0x5a, +0x59,0x59,0x58,0x57,0x56,0x56,0x55,0x55, +0x54,0x54,0x54,0x53,0x53,0x53,0x53,0x53, +0x53,0x53,0x53,0x53,0x53,0x54,0x54,0x54, +0x55,0x55,0x56,0x56,0x56,0x57,0x58,0x59, +0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60, +0x61,0x62,0x64,0x64,0x65,0x67,0x68,0x69, +0x6b,0x6c,0x6e,0x6f,0x70,0x71,0x73,0x74, +0x76,0x77,0x79,0x7a,0x7c,0x7d,0x7e,0x80, +0x80,0x82,0x83,0x85,0x86,0x88,0x89,0x8a, +0x8b,0x8d,0x8e,0x90,0x91,0x92,0x93,0x94, +0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d, +0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3,0xa4, +0xa5,0xa5,0xa6,0xa6,0xa7,0xa7,0xa8,0xa8, +0xa8,0xa9,0xa9,0xa9,0xa9,0xa9,0xaa,0xaa, +0xaa,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa8, +0xa8,0xa8,0xa7,0xa7,0xa6,0xa6,0xa5,0xa4, +0xa4,0xa3,0xa2,0xa1,0xa1,0xa0,0x9f,0x9e, +0x9d,0x9d,0x9c,0x9a,0x99,0x99,0x97,0x96, +0x95,0x94,0x93,0x92,0x90,0x8f,0x8e,0x8d, +0x8c,0x8a,0x89,0x88,0x87,0x85,0x84,0x83, +0x81,0x80,0x80,0x7f,0x7d,0x7d,0x7b,0x7a, +0x78,0x77,0x76,0x75,0x74,0x73,0x71,0x70, +0x6f,0x6e,0x6c,0x6c,0x6b,0x69,0x68,0x68, +0x66,0x65,0x65,0x64,0x63,0x62,0x61,0x60, +0x5f,0x5f,0x5e,0x5d,0x5d,0x5c,0x5b,0x5b, +0x5a,0x5a,0x59,0x59,0x58,0x58,0x58,0x57, +0x57,0x57,0x57,0x57,0x56,0x56,0x56,0x56, +0x56,0x56,0x56,0x57,0x57,0x57,0x57,0x57, +0x58,0x58,0x58,0x59,0x59,0x5a,0x5a,0x5a, +0x5b,0x5c,0x5c,0x5d,0x5d,0x5e,0x5f,0x5f, +0x60,0x61,0x62,0x63,0x64,0x64,0x65,0x66, +0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e, +0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76, +0x77,0x78,0x7a,0x7b,0x7c,0x7d,0x7e,0x80, +0x80,0x81,0x81,0x83,0x84,0x85,0x86,0x87, +0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, +0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x96, +0x98,0x98,0x99,0x9a,0x9b,0x9b,0x9c,0x9d, +0x9d,0x9e,0x9f,0x9f,0xa0,0xa0,0xa1,0xa1, +0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,0xa4, +0xa5,0xa5,0xa5,0xa5,0xa5,0xa5,0xa6,0xa6, +0xa6,0xa6,0xa6,0xa6,0xa6,0xa5,0xa5,0xa5, +0xa5,0xa5,0xa5,0xa4,0xa4,0xa4,0xa3,0xa3, +0xa3,0xa2,0xa2,0xa1,0xa1,0xa0,0xa0,0x9f, +0x9f,0x9e,0x9e,0x9d,0x9d,0x9c,0x9b,0x9a, +0x9a,0x99,0x98,0x97,0x97,0x96,0x95,0x95, +0x93,0x93,0x92,0x91,0x90,0x8f,0x8e,0x8d, +0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86, +0x85,0x84,0x83,0x82,0x81,0x80,0x80,0x80, +0x7e,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78, +0x77,0x76,0x75,0x74,0x74,0x73,0x72,0x71, +0x70,0x70,0x6e,0x6e,0x6d,0x6c,0x6b,0x6a, +0x6a,0x69,0x68,0x67,0x67,0x66,0x65,0x65, +0x64,0x64,0x63,0x62,0x62,0x62,0x61,0x61, +0x60,0x60,0x5f,0x5f,0x5e,0x5e,0x5d,0x5d, +0x5d,0x5d,0x5c,0x5c,0x5c,0x5c,0x5b,0x5b, +0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, +0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, +0x5b,0x5c,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d, +0x5e,0x5e,0x5e,0x5f,0x5f,0x60,0x60,0x60, +0x61,0x61,0x62,0x62,0x63,0x63,0x64,0x64, +0x65,0x65,0x66,0x67,0x67,0x68,0x69,0x69, +0x6a,0x6b,0x6b,0x6c,0x6d,0x6d,0x6e,0x6f, +0x70,0x70,0x71,0x72,0x73,0x73,0x74,0x75, +0x76,0x77,0x77,0x78,0x79,0x7a,0x7b,0x7b, +0x7c,0x7d,0x7e,0x7e,0x80,0x80,0x80,0x81, +0x82,0x82,0x83,0x84,0x85,0x85,0x86,0x87, +0x88,0x88,0x89,0x8a,0x8b,0x8b,0x8c,0x8d, +0x8d,0x8e,0x8f,0x90,0x90,0x91,0x92,0x92, +0x93,0x93,0x94,0x95,0x95,0x96,0x96,0x97, +0x97,0x98,0x99,0x99,0x99,0x9a,0x9a,0x9b, +0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9d,0x9e, +0x9e,0x9e,0x9e,0x9f,0x9f,0x9f,0x9f,0xa0, +0xa0,0xa0,0xa0,0xa0,0xa0,0xa1,0xa1,0xa1, +0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1,0xa1, +0xa1,0xa1,0xa1,0xa1,0xa0,0xa0,0xa0,0xa0, +0xa0,0xa0,0x9f,0x9f,0x9f,0x9f,0x9f,0x9e, +0x9e,0x9e,0x9d,0x9d,0x9d,0x9c,0x9c,0x9c, +0x9b,0x9b,0x9a,0x9a,0x9a,0x99,0x99,0x98, +0x98,0x97,0x97,0x96,0x96,0x95,0x95,0x94, +0x94,0x93,0x93,0x92,0x92,0x91,0x90,0x90, +0x8f,0x8f,0x8e,0x8d,0x8d,0x8c,0x8c,0x8b, +0x8a,0x8a,0x89,0x88,0x88,0x87,0x87,0x86, +0x85,0x85,0x84,0x83,0x83,0x82,0x81,0x81, +0x80,0x80,0x80,0x7f,0x7e,0x7e,0x7d,0x7d, +0x7c,0x7b,0x7a,0x7a,0x79,0x79,0x78,0x78, +0x77,0x76,0x75,0x75,0x74,0x74,0x73,0x73, +0x72,0x72,0x71,0x71,0x70,0x6f,0x6f,0x6e, +0x6e,0x6d,0x6d,0x6c,0x6c,0x6b,0x6b,0x6a, +0x6a,0x69,0x69,0x69,0x68,0x68,0x68,0x67, +0x67,0x66,0x66,0x65,0x65,0x65,0x65,0x64, +0x64,0x64,0x63,0x63,0x63,0x63,0x62,0x62, +0x62,0x62,0x62,0x61,0x61,0x61,0x61,0x61, +0x61,0x61,0x60,0x60,0x60,0x60,0x60,0x60, +0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60, +0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x61, +0x61,0x61,0x61,0x61,0x61,0x62,0x62,0x62, +0x62,0x62,0x63,0x63,0x63,0x63,0x64,0x64, +0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66, +0x66,0x67,0x67,0x67,0x68,0x68,0x69,0x69, +0x69,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c, +0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x70, +0x70,0x71,0x71,0x72,0x72,0x73,0x73,0x74, +0x74,0x75,0x75,0x76,0x76,0x77,0x77,0x78, +0x78,0x79,0x79,0x7a,0x7a,0x7b,0x7b,0x7c, +0x7c,0x7d,0x7d,0x7e,0x7e,0x7f,0x80,0x80, +0x80,0x80,0x81,0x81,0x82,0x82,0x83,0x83, +0x84,0x84,0x84,0x85,0x85,0x86,0x86,0x87, +0x87,0x88,0x88,0x89,0x89,0x8a,0x8a,0x8b, +0x8b,0x8b,0x8c,0x8c,0x8d,0x8d,0x8e,0x8e, +0x8e,0x8e,0x8f,0x8f,0x90,0x90,0x91,0x91, +0x91,0x92,0x92,0x92,0x93,0x93,0x93,0x94, +0x94,0x94,0x94,0x95,0x95,0x95,0x96,0x96, +0x96,0x96,0x97,0x97,0x97,0x97,0x98,0x98, +0x98,0x98,0x98,0x99,0x99,0x99,0x99,0x99, +0x99,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, +0x9a,0x9a,0x9a,0x9b,0x9b,0x9b,0x9b,0x9b, +0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b,0x9b, +0x9b,0x9b,0x9b,0x9b,0x9b,0x9a,0x9a,0x9a, +0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a,0x9a, +0x99,0x99,0x99,0x99,0x99,0x99,0x98,0x98, +0x98,0x98,0x98,0x98,0x97,0x97,0x97,0x97, +0x96,0x96,0x96,0x96,0x96,0x95,0x95,0x95, +0x94,0x94,0x94,0x94,0x94,0x93,0x93,0x93, +0x92,0x92,0x92,0x91,0x91,0x91,0x90,0x90, +0x90,0x90,0x8f,0x8f,0x8e,0x8e,0x8e,0x8e, +0x8d,0x8d,0x8c,0x8c,0x8c,0x8b,0x8b,0x8b, +0x8a,0x8a,0x89,0x89,0x89,0x89,0x88,0x88, +0x87,0x87,0x86,0x86,0x86,0x85,0x85,0x85, +0x84,0x84,0x84,0x83,0x83,0x82,0x82,0x82, +0x81,0x81,0x80,0x80,0x80,0x80,0x80,0x80, +0x7f,0x7f,0x7f,0x7e,0x7e,0x7d,0x7d,0x7d, +0x7c,0x7c,0x7b,0x7b,0x7b,0x7b,0x7a,0x7a, +0x79,0x79,0x79,0x78,0x78,0x77,0x77,0x77, +0x77,0x76,0x76,0x75,0x75,0x75,0x75,0x74, +0x74,0x74,0x73,0x73,0x73,0x72,0x72,0x72, +0x72,0x71,0x71,0x71,0x70,0x70,0x70,0x6f, +0x6f,0x6f,0x6f,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6d,0x6d,0x6d,0x6d,0x6c,0x6c,0x6c,0x6c, +0x6c,0x6b,0x6b,0x6b,0x6b,0x6b,0x6a,0x6a, +0x6a,0x6a,0x6a,0x6a,0x6a,0x69,0x69,0x69, +0x69,0x69,0x69,0x69,0x69,0x68,0x68,0x68, +0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68, +0x68,0x67,0x67,0x67,0x67,0x67,0x67,0x67, +0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67, +0x67,0x67,0x67,0x67,0x67,0x67,0x67,0x67, +0x67,0x67,0x67,0x67,0x68,0x68,0x68,0x68, +0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x68, +0x68,0x69,0x69,0x69,0x69,0x69,0x69,0x69, +0x69,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a,0x6a, +0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6c,0x6c, +0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6d,0x6d, +0x6d,0x6e,0x6e,0x6e,0x6e,0x6e,0x6f,0x6f, +0x6f,0x6f,0x6f,0x70,0x70,0x70,0x70,0x71, +0x71,0x71,0x71,0x72,0x72,0x72,0x72,0x73, +0x73,0x73,0x73,0x73,0x74,0x74,0x74,0x74, +0x75,0x75,0x75,0x76,0x76,0x76,0x76,0x77, +0x77,0x77,0x77,0x77,0x78,0x78,0x79,0x79, +0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7a,0x7b, +0x7b,0x7b,0x7c,0x7c,0x7c,0x7c,0x7c,0x7d, +0x7d,0x7d,0x7e,0x7e,0x7e,0x7e,0x7f,0x7f, +0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80, +0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x82, +0x82,0x82,0x83,0x83,0x83,0x83,0x84,0x84, +0x84,0x84,0x84,0x85,0x85,0x85,0x86,0x86, +0x86,0x86,0x87,0x87,0x87,0x87,0x87,0x88, +0x88,0x88,0x88,0x88,0x89,0x89,0x89,0x89, +0x89,0x89,0x8a,0x8a,0x8a,0x8a,0x8b,0x8b, +0x8b,0x8b,0x8b,0x8b,0x8b,0x8c,0x8c,0x8c, +0x8c,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, +0x8d,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8e, +0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f,0x8f, +0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, +0x90,0x90,0x90,0x91,0x91,0x91,0x91,0x91, +0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, +0x92,0x91,0x92,0x92,0x92,0x92,0x92,0x92, +0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, +0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, +0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, +0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, +0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x92, +0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, +0x91,0x91,0x91,0x91,0x91,0x91,0x91,0x91, +0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, +0x90,0x90,0x90,0x90,0x8f,0x8f,0x8f,0x8f, +0x8f,0x8f,0x8f,0x8f,0x8f,0x8e,0x8e,0x8e, +0x8e,0x8e,0x8e,0x8e,0x8e,0x8e,0x8d,0x8d, +0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8c, +0x8c,0x8c,0x8c,0x8c,0x8c,0x8c,0x8b,0x8b, +0x8b,0x8b,0x8b,0x8b,0x8b,0x8a,0x8a,0x8a, +0x8a,0x8a,0x8a,0x8a,0x89,0x89,0x89,0x89, +0x89,0x89,0x88,0x88,0x88,0x88,0x88,0x88, +0x88,0x87,0x87,0x87,0x87,0x87,0x86,0x86, +0x86,0x86,0x86,0x86,0x86,0x86,0x85,0x85, +0x85,0x85,0x85,0x84,0x84,0x84,0x84,0x84, +0x84,0x84,0x84,0x83,0x83,0x83,0x83,0x83, +0x83,0x82,0x82,0x82,0x82,0x82,0x81,0x81, +0x81,0x81,0x81,0x81,0x81,0x81,0x80,0x80, +0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, +0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7f,0x7f, +0x7f,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7d, +0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, +0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, +0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d, +0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7d, +0x7d,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e,0x7e, +0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f, +0x7f,0x7f,0x80,0x80,0x80,0x80,0x80,0x80, +}; diff --git a/include/kernel32/cptable.h b/include/kernel32/cptable.h new file mode 100644 index 0000000..cbc2d3e --- /dev/null +++ b/include/kernel32/cptable.h @@ -0,0 +1,127 @@ +/* + * nls/cptable.h + */ + +#ifndef __NLS_CPTABLE_H +#define __NLS_CPTABLE_H + +#undef WIN32_LEAN_AND_MEAN +#include +#include + + +#define CODEPAGE_ANSI 1 +#define CODEPAGE_OEM 2 +#define CODEPAGE_MAC 3 +#define CODEPAGE_EBCDIC 4 +#define CODEPAGE_DBCS 0x10 + + + +typedef struct __CURRENCYFMTA +{ + UINT NumDigits; + UINT LeadingZero; + UINT Grouping; + LPSTR lpDecimalSep; + LPSTR lpThousandSep; + UINT NegativeOrder; + UINT PositiveOrder; + LPSTR lpCurrencySymbol; +} CURRENCYFMTA, *PCURRENCYFMTA, *LPCURRENCYFMTA; + +typedef struct __CURRENCYFMTW +{ + UINT NumDigits; + UINT LeadingZero; + UINT Grouping; + LPWSTR lpDecimalSep; + LPWSTR lpThousandSep; + UINT NegativeOrder; + UINT PositiveOrder; + LPWSTR lpCurrencySymbol; +} CURRENCYFMTW, *PCURRENCYFMTW, *LPCURRENCYFMTW; + +typedef struct __NUMBERFMTA +{ + UINT NumDigits; + UINT LeadingZero; + UINT Grouping; + LPSTR lpDecimalSep; + LPSTR lpThousandSep; + UINT NegativeOrder; +} NUMBERFMTA, *PNUMBERFMTA, *LPNUMBERFMTA; + +typedef struct __NUMBERFMTW +{ + UINT NumDigits; + UINT LeadingZero; + UINT Grouping; + LPWSTR lpDecimalSep; + LPWSTR lpThousandSep; + UINT NegativeOrder; +} NUMBERFMTW, *PNUMBERFMTW, *LPNUMBERFMTW; + +typedef struct __CODEPAGE +{ + struct __CODEPAGE *Next; + INT Id; + DWORD Flags; + WCHAR **ToUnicode; + WCHAR **ToUnicodeGlyph; + CHAR ***FromUnicode; + LPCPINFO Info; +} CODEPAGE, *PCODEPAGE; + +extern PCODEPAGE __CPFirst; + +extern CODEPAGE __CP37; +extern CODEPAGE __CP437; +extern CODEPAGE __CP500; +extern CODEPAGE __CP737; +extern CODEPAGE __CP775; +extern CODEPAGE __CP850; +extern CODEPAGE __CP852; +extern CODEPAGE __CP855; +extern CODEPAGE __CP857; +extern CODEPAGE __CP860; +extern CODEPAGE __CP861; +extern CODEPAGE __CP863; +extern CODEPAGE __CP865; +extern CODEPAGE __CP866; +extern CODEPAGE __CP869; +extern CODEPAGE __CP875; +extern CODEPAGE __CP1026; +extern CODEPAGE __CP1250; +extern CODEPAGE __CP1251; +extern CODEPAGE __CP1252; +extern CODEPAGE __CP1253; +extern CODEPAGE __CP1254; +extern CODEPAGE __CP1255; +extern CODEPAGE __CP1256; +extern CODEPAGE __CP1257; +extern CODEPAGE __CP1258; +extern CODEPAGE __CP10000; +extern CODEPAGE __CP10006; +extern CODEPAGE __CP10007; +extern CODEPAGE __CP10029; +extern CODEPAGE __CP10079; +extern CODEPAGE __CP10081; + +extern CPINFO __CPGenInfo; + +extern WCHAR __ASCII_00[32]; +extern WCHAR __ASCII_20[32]; +extern WCHAR __ASCII_40[32]; +extern WCHAR __ASCII_60[32]; + +extern CHAR __ASCII_0000[32]; +extern CHAR __ASCII_0020[32]; +extern CHAR __ASCII_0040[32]; +extern CHAR __ASCII_0060[32]; + +extern WCHAR __NULL_00[32]; +extern CHAR __NULL_0000[32]; +extern CHAR *__NULL_00XX[32]; + +#endif \ No newline at end of file diff --git a/include/kernel32/error.h b/include/kernel32/error.h new file mode 100644 index 0000000..384a280 --- /dev/null +++ b/include/kernel32/error.h @@ -0,0 +1,12 @@ +#ifndef _INCLUDE_KERNEL32_H +#define _INCLUDE_KERNEL32_H +/* $Id$ */ +#include +#define NTOS_MODE_USER +#include +DWORD +STDCALL +SetLastErrorByStatus ( + NTSTATUS Status + ); +#endif /* _INCLUDE_KERNEL32_H */ diff --git a/include/kernel32/heap.h b/include/kernel32/heap.h new file mode 100644 index 0000000..6a1de98 --- /dev/null +++ b/include/kernel32/heap.h @@ -0,0 +1,108 @@ +/* + * kernel/heap.c + * Copyright (C) 1996, Onno Hovers, All rights reserved + * Adapted for the ReactOS system libraries by David Welch (welch@mcmail.com) + * todo: __processheap should be part of peb. + */ + +#ifndef __INCLUDE_KERNEL32_HEAP_H +#define __INCLUDE_KERNEL32_HEAP_H + +/* System wide includes ****************************************************/ +#include + +/* System library's private includes ***************************************/ + +#include + +/* definitions */ +#define HEAP_ADMIN_SIZE (sizeof(HEAP_BLOCK)) +#define HEAP_FRAG_ADMIN_SIZE (sizeof(HEAP_FRAGMENT)) +#define HEAP_ROUNDVAL (2*(HEAP_ADMIN_SIZE)-1) +#define HEAP_FRAGMENT_THRESHOLD 256 + +#define SIZE_TOTAL(s) ROUNDUP((s)+HEAP_ADMIN_SIZE,8) +#define SIZE_ROUND(s) ROUNDUP((s),8) + +#define HEAP_FRAG_MAGIC 0x10 +#define HEAP_ALLOC_MASK 0xF0000000 +#define HEAP_FREE_MASK 0x80000000 +#define HEAP_SIZE_MASK 0x0FFFFFFF +#define HEAP_FREE_TAG 0x80000000 /* free region */ +#define HEAP_NORMAL_TAG 0x30000000 /* normal allocation */ +#define HEAP_MOVEABLE_TAG 0x50000000 /* moveable handle */ +#define HEAP_SUB_TAG 0x70000000 /* suballocated for fragments */ + +#define HEAP_ISFREE(p) ((((PHEAP_BLOCK)p)->Size) & HEAP_FREE_MASK) +#define HEAP_ISALLOC(p) (((((PHEAP_BLOCK)p)->Size) & HEAP_FREE_MASK)==0) +#define HEAP_ISFRAG(p) ((((PHEAP_FRAGMENT)p)->Magic)==HEAP_FRAG_MAGIC) +#define HEAP_ISNORMAL(p) (((((PHEAP_BLOCK)p)->Size) & HEAP_ALLOC_MASK)\ + ==HEAP_NORMAL_TAG) +#define HEAP_ISSUB(p) (((((PHEAP_BLOCK)p)->Size) & HEAP_ALLOC_MASK)\ + ==HEAP_SUB_TAG) +#define HEAP_ISOLD(p) (((((PHEAP_BLOCK)p)->Size) & HEAP_ALLOC_MASK)\ + ==HEAP_MOVEABLE_TAG) + +#define HEAP_SIZE(p) ((((PHEAP_BLOCK)p)->Size) & HEAP_SIZE_MASK ) +#define HEAP_RSIZE(p) SIZE_ROUND(HEAP_SIZE(p)) +#define HEAP_TSIZE(p) SIZE_TOTAL(HEAP_SIZE(p)) +#define HEAP_PREVSIZE(p) ((((PHEAP_BLOCK)p)->PrevSize) & HEAP_SIZE_MASK ) +#define HEAP_FRAG_SIZE(p) (((PHEAP_FRAGMENT)p)->Size) + +#define HEAP_PREV(p) ((PHEAP_BLOCK)(((LPVOID)(p))-HEAP_PREVSIZE(p))) +#define HEAP_NEXT(p) ((PHEAP_BLOCK)(((LPVOID)(p))+HEAP_TSIZE(p))) + +typedef struct __HEAP_BLOCK +{ + ULONG Size; /* this is relative to Data */ + ULONG PrevSize; /* p - p->PrevSize is the previous block */ +} HEAP_BLOCK, *PHEAP_BLOCK; + +struct __HEAP_SUBALLOC; + +typedef struct __HEAP_FRAGMENT +{ + UCHAR Magic; + UCHAR Number; + ULONG Size; + struct __HEAP_SUBALLOC *Sub; + + /* this is only used in free blocks */ + struct __HEAP_FRAGMENT *FreeNext; + struct __HEAP_FRAGMENT *FreePrev; +} HEAP_FRAGMENT, *PHEAP_FRAGMENT, *LPHEAP_FRAGMENT; + +typedef struct __HEAP_SUBALLOC +{ + ULONG Magic; + ULONG NumberFree; + struct __HEAP_SUBALLOC *Next; + + struct __HEAP_SUBALLOC *Prev; + struct __HEAP_FRAGMENT *FirstFree; + struct __HEAP_BUCKET *Bucket; + ULONG Bitmap; +} HEAP_SUBALLOC, *PHEAP_SUBALLOC, *LPHEAP_SUBALLOC; + +typedef struct __HEAP_BUCKET +{ + struct __HEAP_SUBALLOC *FirstFree; + ULONG Size; + ULONG Number; + ULONG TotalSize; +} HEAP_BUCKET, *PHEAP_BUCKET, *LPHEAP_BUCKET; + +typedef struct __HEAP +{ + ULONG Magic; + LPVOID End; + ULONG Flags; + CRITICAL_SECTION Synchronize; + HEAP_BUCKET Bucket[8]; + struct __HEAP *NextHeap; + LPVOID LastBlock; + /* this has to aligned on an 8 byte boundary */ + HEAP_BLOCK Start __attribute__((aligned (8))); +} HEAP, *PHEAP; + +#endif /* __INCLUDE_KERNEL32_HEAP_H */ diff --git a/include/kernel32/kernel32.h b/include/kernel32/kernel32.h new file mode 100644 index 0000000..1db3e0f --- /dev/null +++ b/include/kernel32/kernel32.h @@ -0,0 +1,45 @@ +#ifndef _INCLUDE_KERNEL32_KERNEL32_H +#define _INCLUDE_KERNEL32_KERNEL32_H + +#include + +#define UNIMPLEMENTED DbgPrint("%s at %s:%d is unimplemented\n",__FUNCTION__,__FILE__,__LINE__); + +#ifdef NDEBUG +#define DPRINT(args...) +#define CHECKPOINT +#else +#define DPRINT(args...) do { DbgPrint("(KERNEL32:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT do { DbgPrint("(KERNEL32:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0); +#endif + +#define DPRINT1(args...) do { DbgPrint("(KERNEL32:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT1 do { DbgPrint("(KERNEL32:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0); + +#define MAGIC(c1,c2,c3,c4) ((c1) + ((c2)<<8) + ((c3)<<16) + ((c4)<<24)) + +#define MAGIC_HEAP MAGIC( 'H','E','A','P' ) + +#define ROUNDUP(a,b) ((((a)+(b)-1)/(b))*(b)) +#define ROUNDDOWN(a,b) (((a)/(b))*(b)) + +#ifndef FIELD_OFFSET +#define FIELD_OFFSET(type,fld) ((LONG)&(((type *)0)->fld)) +#endif + +/* GLOBAL VARIABLES **********************************************************/ + +extern WINBOOL bIsFileApiAnsi; +extern HANDLE hProcessHeap; +extern HANDLE hBaseDir; + +extern CRITICAL_SECTION DllLock; + +/* FUNCTION PROTOTYPES *******************************************************/ + +BOOLEAN STDCALL IsConsoleHandle(HANDLE Handle); + +WINBOOL STDCALL CloseConsoleHandle(HANDLE Handle); + +#endif /* ndef _INCLUDE_KERNEL32_KERNEL32_H */ + diff --git a/include/kernel32/lctable.h b/include/kernel32/lctable.h new file mode 100644 index 0000000..17ceff8 --- /dev/null +++ b/include/kernel32/lctable.h @@ -0,0 +1,36 @@ +/* + * nls/lctable.h + */ + + + +#ifndef __NLS_LCTABLE_H +#define __NLS_LCTABLE_H + + +struct __CODEPAGE; + +#ifdef WIN32_LEAN_AND_MEAN + typedef DWORD LCID; +#endif + +#define LOCALE_ARRAY 200 +typedef struct __LOCALE +{ + LCID Id; + LPSTR AbbrName; + LPWSTR *Info0; + LPWSTR *Info1; + LPWSTR *ShortDateFormat; + LPWSTR *LongDateFormat; + LPWSTR *TimeFormat; + struct __CODEPAGE *AnsiCodePage; + struct __CODEPAGE *OemCodePage; +} LOCALE, *PLOCALE, *LPLOCALE; + +extern LOCALE __Locale[LOCALE_ARRAY]; +extern PLOCALE __UserLocale; + +extern BOOL __LocaleInit(VOID); + +#endif \ No newline at end of file diff --git a/include/kernel32/nls.h b/include/kernel32/nls.h new file mode 100644 index 0000000..2d6766a --- /dev/null +++ b/include/kernel32/nls.h @@ -0,0 +1,26 @@ +/* + * win32/nls.h + * + * National Language Support definitions + * + * Copyright (C) 1996 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include + diff --git a/include/kernel32/proc.h b/include/kernel32/proc.h new file mode 100644 index 0000000..3931744 --- /dev/null +++ b/include/kernel32/proc.h @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include/kernel32/process.h + * PURPOSE: Include file for lib/kernel32/proc.c + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + + +#include +#include + + +typedef +DWORD +(*WaitForInputIdleType)( + HANDLE hProcess, + DWORD dwMilliseconds); + + + diff --git a/include/kernel32/process.h b/include/kernel32/process.h new file mode 100644 index 0000000..2ffe32c --- /dev/null +++ b/include/kernel32/process.h @@ -0,0 +1,63 @@ + +#ifndef __PEB_DEFINED +#define __PEB_DEFINED + +#include "heap.h" + +typedef void* HANDLE_TABLE; + +typedef struct _pPebInfo { + LPWSTR lpCommandLine; + DWORD cb; + HANDLE hStdInput; //18 + HANDLE hStdOutput; + HANDLE hStdError; + LPWSTR lpEnvironment; + DWORD dwX; + DWORD dwY; + DWORD dwXSize; + DWORD dwYSize; + DWORD dwXCountChars; + DWORD dwYCountChars; + DWORD dwFillAttribute; + DWORD dwFlags; + DWORD wShowWindow; + LPTSTR lpTitle; + LPTSTR lpDesktop; + LPTSTR reserved; + DWORD cbReserved2; + LPTSTR lpReserved1; +} PEBINFO; + +typedef struct _NT_PEB +{ + + LONG ImageBaseAddress; + void *HeapIndex; + DWORD dwTlsBits[2]; // tls in use bits + WORD NumberOfProcessors; + WORD NtGlobalFlag; + DWORD dwCriticalSectionTimeout; + DWORD dwHeapReserve; + DWORD dwHeapCommit; + DWORD dwHeapDecommitFreeBlockThreshold; + DWORD dwNumberOfHeaps; + DWORD dwMaxiumNumberOfHeaps; + PEBINFO *pPebInfo; + HEAP *pProcessHeap; + HANDLE_TABLE htGDISharedHandleTable; + ATOMTABLE LocalAtomTable; + CRITICAL_SECTION *pCriticalSection; + WORD wMajorVersion; + WORD wMinorVersion; + WORD wBuildNumber; + WORD wPlatformId; + +} NT_PEB; + +NT_PEB *GetPeb() +{ + return NULL; +} + +#endif diff --git a/include/kernel32/thread.h b/include/kernel32/thread.h new file mode 100644 index 0000000..13dc1e6 --- /dev/null +++ b/include/kernel32/thread.h @@ -0,0 +1,15 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include/kernel32/thread.h + * PURPOSE: Include file for lib/kernel32/thread.c + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ +#include +#include +PTEB GetTeb(VOID); + + + diff --git a/include/kernel32/winnls.h b/include/kernel32/winnls.h new file mode 100644 index 0000000..b293529 --- /dev/null +++ b/include/kernel32/winnls.h @@ -0,0 +1,427 @@ +#ifndef __WINE_WINNLS_H +#define __WINE_WINNLS_H + +/* flags to GetLocaleInfo */ +//#define LOCALE_NOUSEROVERRIDE 0x80000000 +#define LOCALE_USE_CP_ACP 0x40000000 + +#define LOCALE_LOCALEINFOFLAGSMASK 0xC0000000 + +/* When adding new defines, don't forget to add an entry to the + * locale2id map in misc/ole2nls.c + */ +#define LOCALE_SNATIVEDIGITS 0x00000013 +#define LOCALE_SINTLSYMBOL 0x00000015 +#define LOCALE_SISO639LANGNAME 0x00000059 +#define LOCALE_SISO3166CTRYNAME 0x0000005A +#define LOCALE_IDEFAULTMACCODEPAGE 0x00001011 +#define LOCALE_IINTLCURRDIGITS 0x0000001A +#define LOCALE_ITIMEMARKPOSN 0x00001005 +#define LOCALE_ICENTURY 0x00000024 +#define LOCALE_FONTSIGNATURE 0x00000058 +#if 0 +#define LOCALE_ILANGUAGE 0x00000001 +#define LOCALE_SLANGUAGE 0x00000002 +#define LOCALE_SENGLANGUAGE 0x00001001 +#define LOCALE_SABBREVLANGNAME 0x00000003 +#define LOCALE_SNATIVELANGNAME 0x00000004 +#define LOCALE_ICOUNTRY 0x00000005 +#define LOCALE_SCOUNTRY 0x00000006 +#define LOCALE_SENGCOUNTRY 0x00001002 +#define LOCALE_SABBREVCTRYNAME 0x00000007 +#define LOCALE_SNATIVECTRYNAME 0x00000008 +#define LOCALE_IDEFAULTLANGUAGE 0x00000009 +#define LOCALE_IDEFAULTCOUNTRY 0x0000000A +#define LOCALE_IDEFAULTCODEPAGE 0x0000000B +#define LOCALE_IDEFAULTANSICODEPAGE 0x00001004 +#define LOCALE_SLIST 0x0000000C +#define LOCALE_IMEASURE 0x0000000D +#define LOCALE_SDECIMAL 0x0000000E +#define LOCALE_STHOUSAND 0x0000000F +#define LOCALE_SGROUPING 0x00000010 +#define LOCALE_IDIGITS 0x00000011 +#define LOCALE_ILZERO 0x00000012 +#define LOCALE_INEGNUMBER 0x00001010 +#define LOCALE_SCURRENCY 0x00000014 +#define LOCALE_SMONDECIMALSEP 0x00000016 +#define LOCALE_SMONTHOUSANDSEP 0x00000017 +#define LOCALE_SMONGROUPING 0x00000018 +#define LOCALE_ICURRDIGITS 0x00000019 +#define LOCALE_ICURRENCY 0x0000001B +#define LOCALE_INEGCURR 0x0000001C +#define LOCALE_SDATE 0x0000001D +#define LOCALE_STIME 0x0000001E +#define LOCALE_SSHORTDATE 0x0000001F +#define LOCALE_SLONGDATE 0x00000020 +#define LOCALE_STIMEFORMAT 0x00001003 +#define LOCALE_IDATE 0x00000021 +#define LOCALE_ILDATE 0x00000022 +#define LOCALE_ITIME 0x00000023 +#define LOCALE_ITLZERO 0x00000025 +#define LOCALE_IDAYLZERO 0x00000026 +#define LOCALE_IMONLZERO 0x00000027 +#define LOCALE_S1159 0x00000028 +#define LOCALE_S2359 0x00000029 +#define LOCALE_ICALENDARTYPE 0x00001009 +#define LOCALE_IOPTIONALCALENDAR 0x0000100B +#define LOCALE_IFIRSTDAYOFWEEK 0x0000100C +#define LOCALE_IFIRSTWEEKOFYEAR 0x0000100D +#define LOCALE_SDAYNAME1 0x0000002A +#define LOCALE_SDAYNAME2 0x0000002B +#define LOCALE_SDAYNAME3 0x0000002C +#define LOCALE_SDAYNAME4 0x0000002D +#define LOCALE_SDAYNAME5 0x0000002E +#define LOCALE_SDAYNAME6 0x0000002F +#define LOCALE_SDAYNAME7 0x00000030 +#define LOCALE_SABBREVDAYNAME1 0x00000031 +#define LOCALE_SABBREVDAYNAME2 0x00000032 +#define LOCALE_SABBREVDAYNAME3 0x00000033 +#define LOCALE_SABBREVDAYNAME4 0x00000034 +#define LOCALE_SABBREVDAYNAME5 0x00000035 +#define LOCALE_SABBREVDAYNAME6 0x00000036 +#define LOCALE_SABBREVDAYNAME7 0x00000037 +#define LOCALE_SMONTHNAME1 0x00000038 +#define LOCALE_SMONTHNAME2 0x00000039 +#define LOCALE_SMONTHNAME3 0x0000003A +#define LOCALE_SMONTHNAME4 0x0000003B +#define LOCALE_SMONTHNAME5 0x0000003C +#define LOCALE_SMONTHNAME6 0x0000003D +#define LOCALE_SMONTHNAME7 0x0000003E +#define LOCALE_SMONTHNAME8 0x0000003F +#define LOCALE_SMONTHNAME9 0x00000040 +#define LOCALE_SMONTHNAME10 0x00000041 +#define LOCALE_SMONTHNAME11 0x00000042 +#define LOCALE_SMONTHNAME12 0x00000043 +#define LOCALE_SMONTHNAME13 0x0000100E +#define LOCALE_SABBREVMONTHNAME1 0x00000044 +#define LOCALE_SABBREVMONTHNAME2 0x00000045 +#define LOCALE_SABBREVMONTHNAME3 0x00000046 +#define LOCALE_SABBREVMONTHNAME4 0x00000047 +#define LOCALE_SABBREVMONTHNAME5 0x00000048 +#define LOCALE_SABBREVMONTHNAME6 0x00000049 +#define LOCALE_SABBREVMONTHNAME7 0x0000004A +#define LOCALE_SABBREVMONTHNAME8 0x0000004B +#define LOCALE_SABBREVMONTHNAME9 0x0000004C +#define LOCALE_SABBREVMONTHNAME10 0x0000004D +#define LOCALE_SABBREVMONTHNAME11 0x0000004E +#define LOCALE_SABBREVMONTHNAME12 0x0000004F +#define LOCALE_SABBREVMONTHNAME13 0x0000100F +#define LOCALE_SPOSITIVESIGN 0x00000050 +#define LOCALE_SNEGATIVESIGN 0x00000051 +#define LOCALE_IPOSSIGNPOSN 0x00000052 +#define LOCALE_INEGSIGNPOSN 0x00000053 +#define LOCALE_IPOSSYMPRECEDES 0x00000054 +#define LOCALE_IPOSSEPBYSPACE 0x00000055 +#define LOCALE_INEGSYMPRECEDES 0x00000056 +#define LOCALE_INEGSEPBYSPACE 0x00000057 +#endif + +#if 0 +#define NORM_IGNORECASE 1 +#define NORM_IGNORENONSPACE 2 +#define NORM_IGNORESYMBOLS 4 +#define NORM_STRINGSORT 0x1000 +#define NORM_IGNOREKANATYPE 0x00010000 +#define NORM_IGNOREWIDTH 0x00020000 +#endif + +#if 0 +#define CP_ACP 0 //ANSI code page +#define CP_OEMCP 1 //OEM code page +#define CP_MACCP 2 //Macintosh code page +#define CP_THREAD_ACP 3 //ACP Current thread's ANSI code page +#define CP_SYMBOL 42 //Symbol code page (42) +#define CP_UTF7 65000 //Translate using UTF-7 +#define CP_UTF8 65001 //Translate using UTF-8 +#endif + +#if 0 +#define WC_DEFAULTCHECK 0x00000100 +#define WC_COMPOSITECHECK 0x00000200 +#define WC_DISCARDNS 0x00000010 +#define WC_SEPCHARS 0x00000020 +#define WC_DEFAULTCHAR 0x00000040 +#endif + +#if 0 +#define MAKELCID(l, s) (MAKELONG(l, s)) + +#define MAKELANGID(p, s) ((((WORD)(s))<<10) | (WORD)(p)) +#define PRIMARYLANGID(l) ((WORD)(l) & 0x3ff) +#define SUBLANGID(l) ((WORD)(l) >> 10) +#endif + +#if 0 +#define LANG_SYSTEM_DEFAULT (MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT)) +#define LANG_USER_DEFAULT (MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)) +#define LOCALE_SYSTEM_DEFAULT (MAKELCID(LANG_SYSTEM_DEFAULT, SORT_DEFAULT)) +#define LOCALE_USER_DEFAULT (MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT)) +#define LOCALE_NEUTRAL (MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT)) +#endif + +/* Language IDs (were in winnt.h, for some reason) */ + + +/* Language IDs */ + +/* FIXME: are the symbolic names correct for LIDs: 0x17, 0x20, 0x28, + * 0x2a, 0x2b, 0x2c, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + * 0x37, 0x39, 0x3a, 0x3b, 0x3c, 0x3e, 0x3f, 0x41, 0x43, 0x44, + * 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, + * 0x4f, 0x57 + */ +#define LANG_CATALAN 0x03 +#define LANG_THAI 0x1e +/* non standard; keep the number high enough (but < 0xff) */ +#define LANG_ESPERANTO 0x8f +#if 0 +#define LANG_NEUTRAL 0x00 +#define LANG_AFRIKAANS 0x36 +#define LANG_ALBANIAN 0x1c +#define LANG_ARABIC 0x01 +#define LANG_ARMENIAN 0x2b +#define LANG_ASSAMESE 0x4d +#define LANG_AZERI 0x2c +#define LANG_BASQUE 0x2d +#define LANG_BENGALI 0x45 +#define LANG_BULGARIAN 0x02 +#define LANG_BYELORUSSIAN 0x23 +#define LANG_CHINESE 0x04 +#define LANG_SERBO_CROATIAN 0x1a +#define LANG_CROATIAN LANG_SERBO_CROATIAN +#define LANG_SERBIAN LANG_SERBO_CROATIAN +#define LANG_CZECH 0x05 +#define LANG_DANISH 0x06 +#define LANG_DUTCH 0x13 +#define LANG_ENGLISH 0x09 +#define LANG_ESTONIAN 0x25 +#define LANG_FAEROESE 0x38 +#define LANG_FARSI 0x29 +#define LANG_FINNISH 0x0b +#define LANG_FRENCH 0x0c +#define LANG_GAELIC 0x3c +#define LANG_GEORGIAN 0x37 +#define LANG_GERMAN 0x07 +#define LANG_GREEK 0x08 +#define LANG_GUJARATI 0x47 +#define LANG_HEBREW 0x0D +#define LANG_HINDI 0x39 +#define LANG_HUNGARIAN 0x0e +#define LANG_ICELANDIC 0x0f +#define LANG_INDONESIAN 0x21 +#define LANG_ITALIAN 0x10 +#define LANG_JAPANESE 0x11 +#define LANG_KANNADA 0x4b +#define LANG_KAZAKH 0x3f +#define LANG_KONKANI 0x57 +#define LANG_KOREAN 0x12 +#define LANG_LATVIAN 0x26 +#define LANG_LITHUANIAN 0x27 +#define LANG_MACEDONIAN 0x2f +#define LANG_MALAY 0x3e +#define LANG_MALAYALAM 0x4c +#define LANG_MALTESE 0x3a +#define LANG_MAORI 0x28 +#define LANG_MARATHI 0x4e +#define LANG_NORWEGIAN 0x14 +#define LANG_ORIYA 0x48 +#define LANG_POLISH 0x15 +#define LANG_PORTUGUESE 0x16 +#define LANG_PUNJABI 0x46 +#define LANG_RHAETO_ROMANCE 0x17 +#define LANG_ROMANIAN 0x18 +#define LANG_RUSSIAN 0x19 +#define LANG_SAAMI 0x3b +#define LANG_SANSKRIT 0x4f +#define LANG_SLOVAK 0x1b +#define LANG_SLOVENIAN 0x24 +#define LANG_SORBIAN 0x2e +#define LANG_SPANISH 0x0a +#define LANG_SUTU 0x30 +#define LANG_SWAHILI 0x41 +#define LANG_SWEDISH 0x1d +#define LANG_TAMIL 0x49 +#define LANG_TATAR 0x44 +#define LANG_TELUGU 0x4a +#define LANG_TSONGA 0x31 +#define LANG_TSWANA 0x32 +#define LANG_TURKISH 0x1f +#define LANG_UKRAINIAN 0x22 +#define LANG_URDU 0x20 +#define LANG_UZBEK 0x43 +#define LANG_VENDA 0x33 +#define LANG_VIETNAMESE 0x2a +#define LANG_XHOSA 0x34 +#define LANG_ZULU 0x35 +#endif + +/* Sublanguage definitions */ +//#define SUBLANG_NEUTRAL 0x00 /* language neutral */ +//#define SUBLANG_DEFAULT 0x01 /* user default */ +//#define SUBLANG_SYS_DEFAULT 0x02 /* system default */ + +#define SUBLANG_ARABIC 0x01 +#define SUBLANG_ARABIC_IRAQ 0x02 +#define SUBLANG_ARABIC_EGYPT 0x03 +#define SUBLANG_ARABIC_LIBYA 0x04 +#define SUBLANG_ARABIC_ALGERIA 0x05 +#define SUBLANG_ARABIC_MOROCCO 0x06 +#define SUBLANG_ARABIC_TUNISIA 0x07 +#define SUBLANG_ARABIC_OMAN 0x08 +#define SUBLANG_ARABIC_YEMEN 0x09 +#define SUBLANG_ARABIC_SYRIA 0x0a +#define SUBLANG_ARABIC_JORDAN 0x0b +#define SUBLANG_ARABIC_LEBANON 0x0c +#define SUBLANG_ARABIC_KUWAIT 0x0d +#define SUBLANG_ARABIC_UAE 0x0e +#define SUBLANG_ARABIC_BAHRAIN 0x0f +#define SUBLANG_ARABIC_QATAR 0x10 +//#define SUBLANG_CHINESE_TRADITIONAL 0x01 +//#define SUBLANG_CHINESE_SIMPLIFIED 0x02 +//#define SUBLANG_CHINESE_HONGKONG 0x03 +//#define SUBLANG_CHINESE_SINGAPORE 0x04 +#define SUBLANG_CHINESE_MACAU 0x05 +//#define SUBLANG_DUTCH 0x01 +//#define SUBLANG_DUTCH_BELGIAN 0x02 +#define SUBLANG_DUTCH_SURINAM 0x03 +//#define SUBLANG_ENGLISH_US 0x01 +//#define SUBLANG_ENGLISH_UK 0x02 +//#define SUBLANG_ENGLISH_AUS 0x03 +//#define SUBLANG_ENGLISH_CAN 0x04 +//#define SUBLANG_ENGLISH_NZ 0x05 +//#define SUBLANG_ENGLISH_EIRE 0x06 +#define SUBLANG_ENGLISH_SAFRICA 0x07 +#define SUBLANG_ENGLISH_JAMAICA 0x08 +#define SUBLANG_ENGLISH_CARRIBEAN 0x09 +#define SUBLANG_ENGLISH_BELIZE 0x0a +#define SUBLANG_ENGLISH_TRINIDAD 0x0b +#define SUBLANG_ENGLISH_ZIMBABWE 0x0c +#define SUBLANG_ENGLISH_PHILIPPINES 0x0d +//#define SUBLANG_FRENCH 0x01 +//#define SUBLANG_FRENCH_BELGIAN 0x02 +//#define SUBLANG_FRENCH_CANADIAN 0x03 +//#define SUBLANG_FRENCH_SWISS 0x04 +#define SUBLANG_FRENCH_LUXEMBOURG 0x05 +#define SUBLANG_FRENCH_MONACO 0x06 +//#define SUBLANG_GERMAN 0x01 +//#define SUBLANG_GERMAN_SWISS 0x02 +//#define SUBLANG_GERMAN_AUSTRIAN 0x03 +#define SUBLANG_GERMAN_LUXEMBOURG 0x04 +#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +//#define SUBLANG_ITALIAN 0x01 +//#define SUBLANG_ITALIAN_SWISS 0x02 +#define SUBLANG_KOREAN 0x01 +#define SUBLANG_KOREAN_JOHAB 0x02 +//#define SUBLANG_NORWEGIAN_BOKMAL 0x01 +//#define SUBLANG_NORWEGIAN_NYNORSK 0x02 +//#define SUBLANG_PORTUGUESE 0x02 +//#define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 +//#define SUBLANG_SPANISH 0x01 +//#define SUBLANG_SPANISH_MEXICAN 0x02 +//#define SUBLANG_SPANISH_MODERN 0x03 +#define SUBLANG_SPANISH_GUATEMALA 0x04 +#define SUBLANG_SPANISH_COSTARICA 0x05 +#define SUBLANG_SPANISH_PANAMA 0x06 +#define SUBLANG_SPANISH_DOMINICAN 0x07 +#define SUBLANG_SPANISH_VENEZUELA 0x08 +#define SUBLANG_SPANISH_COLOMBIA 0x09 +#define SUBLANG_SPANISH_PERU 0x0a +#define SUBLANG_SPANISH_ARGENTINA 0x0b +#define SUBLANG_SPANISH_ECUADOR 0x0c +#define SUBLANG_SPANISH_CHILE 0x0d +#define SUBLANG_SPANISH_URUGUAY 0x0e +#define SUBLANG_SPANISH_PARAGUAY 0x0f +#define SUBLANG_SPANISH_BOLIVIA 0x10 +#define SUBLANG_SPANISH_EL_SALVADOR 0x11 +#define SUBLANG_SPANISH_HONDURAS 0x12 +#define SUBLANG_SPANISH_NICARAGUA 0x13 +#define SUBLANG_SPANISH_PUERTO_RICO 0x14 +/* FIXME: I don't know the symbolic names for those */ +#define SUBLANG_ROMANIAN 0x01 +#define SUBLANG_ROMANIAN_MOLDAVIA 0x02 +#define SUBLANG_RUSSIAN 0x01 +#define SUBLANG_RUSSIAN_MOLDAVIA 0x02 +#define SUBLANG_CROATIAN 0x01 +#define SUBLANG_SERBIAN 0x02 +#define SUBLANG_SERBIAN_LATIN 0x03 +#define SUBLANG_SWEDISH 0x01 +#define SUBLANG_SWEDISH_FINLAND 0x02 +#define SUBLANG_LITHUANIAN 0x01 +#define SUBLANG_LITHUANIAN_CLASSIC 0x02 +#define SUBLANG_AZERI 0x01 +#define SUBLANG_AZERI_CYRILLIC 0x02 +#define SUBLANG_GAELIC 0x01 +#define SUBLANG_GAELIC_SCOTTISH 0x02 +#define SUBLANG_MALAY 0x01 +#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +#define SUBLANG_UZBEK 0x01 +#define SUBLANG_UZBEK_CYRILLIC 0x02 + +/* Sort definitions */ +//#define SORT_DEFAULT 0x0 +//#define SORT_JAPANESE_XJIS 0x0 +//#define SORT_JAPANESE_UNICODE 0x1 +//#define SORT_CHINESE_BIG5 0x0 +//#define SORT_CHINESE_UNICODE 0x1 +//#define SORT_KOREAN_KSC 0x0 +//#define SORT_KOREAN_UNICODE 0x1 + + +/* Locale Dependent Mapping Flags */ +#if 0 +#define LCMAP_LOWERCASE 0x00000100 /* lower case letters */ +#define LCMAP_UPPERCASE 0x00000200 /* upper case letters */ +#define LCMAP_SORTKEY 0x00000400 /* WC sort key (normalize) */ +#define LCMAP_BYTEREV 0x00000800 /* byte reversal */ +#endif + +//#define SORT_STRINGSORT 0x00001000 /* take punctuation into account */ + +#if 0 +#define LCMAP_HIRAGANA 0x00100000 /* map katakana to hiragana */ +#define LCMAP_KATAKANA 0x00200000 /* map hiragana to katakana */ +#define LCMAP_HALFWIDTH 0x00400000 /* map double byte to single byte */ +#define LCMAP_FULLWIDTH 0x00800000 /* map single byte to double byte */ +#endif + +/* Date Flags for GetDateFormat. */ +#if 0 +#define DATE_SHORTDATE 0x00000001 /* use short date picture */ +#define DATE_LONGDATE 0x00000002 /* use long date picture */ +#define DATE_USE_ALT_CALENDAR 0x00000004 /* use alternate calendar */ + /* alt. calendar support is broken anyway */ +#endif + +#if 0 +#define TIME_FORCE24HOURFORMAT 0x00000008 /* force 24 hour format*/ +#define TIME_NOTIMEMARKER 0x00000004 /* show no AM/PM */ +#define TIME_NOSECONDS 0x00000002 /* show no seconds */ +#define TIME_NOMINUTESORSECONDS 0x0000001 /* show no minutes either */ +#endif + +/* internal flags for GetDateFormat system */ +#define DATE_DATEVARSONLY 0x00000100 /* only date stuff: yMdg */ +#define TIME_TIMEVARSONLY 0x00000200 /* only time stuff: hHmst */ +/* use this in a WineLib program if you really want all types */ +#define LOCALE_TIMEDATEBOTH 0x00000300 /* full set */ + +/* Prototypes for Unicode case conversion routines */ +WCHAR towupper(WCHAR); +WCHAR towlower(WCHAR); + +#if 0 +/* Definitions for IsTextUnicode() function */ +#define IS_TEXT_UNICODE_ASCII16 0x0001 +#define IS_TEXT_UNICODE_SIGNATURE 0x0008 +#define IS_TEXT_UNICODE_REVERSE_ASCII16 0x0010 +#define IS_TEXT_UNICODE_REVERSE_SIGNATURE 0x0080 +#define IS_TEXT_UNICODE_ILLEGAL_CHARS 0x0100 +#define IS_TEXT_UNICODE_ODD_LENGTH 0x0200 +#endif + +/* Tests that we currently implement */ +#define ITU_IMPLEMENTED_TESTS \ + IS_TEXT_UNICODE_SIGNATURE| \ + IS_TEXT_UNICODE_ODD_LENGTH + +#endif /* __WINE_WINNLS_H */ diff --git a/include/libc/atexit.h b/include/libc/atexit.h new file mode 100644 index 0000000..b3a9f01 --- /dev/null +++ b/include/libc/atexit.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_atexit_h__ +#define __dj_include_libc_dosexec_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +struct __atexit { + struct __atexit *__next; + void (*__function)(void); +}; + +extern struct __atexit *__atexit_ptr; + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_dosexec_h__ */ diff --git a/include/libc/file.h b/include/libc/file.h new file mode 100644 index 0000000..c27d89c --- /dev/null +++ b/include/libc/file.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#ifndef __dj_include_libc_file_h__ +#define __dj_include_libc_file_h__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +#ifndef _IORMONCL +#define _IORMONCL 004000 /* remove on close, for temp files */ +#endif +/* if _flag & _IORMONCL, ._name_to_remove needs freeing */ + +#ifndef _IOUNGETC +#define _IOUNGETC 010000 /* there is an ungetc'ed character in the buffer */ +#endif + +int __set_errno(int err); + +char __is_text_file(FILE *p); + +int __fileno_alloc(void *hFile, int mode); + +int _doprnt(const char *fmt, va_list args, FILE *f); +int _doscan(FILE *iop, const char *fmt, void **argp); +int _dowscan(FILE *iop, const wchar_t *fmt, void **argp); + + +int __fileno_dup2( int handle1, int handle2 ); +int __fileno_setmode(int _fd, int _newmode); +int __fileno_close(int _fd); + + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_file_h__ */ diff --git a/include/libc/ieee.h b/include/libc/ieee.h new file mode 100644 index 0000000..f501b4f --- /dev/null +++ b/include/libc/ieee.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_ieee_h__ +#define __dj_include_libc_ieee_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +typedef struct { + unsigned mantissa:23; + unsigned exponent:8; + unsigned sign:1; +} float_t; + +typedef struct { + unsigned mantissal:32; + unsigned mantissah:20; + unsigned exponent:11; + unsigned sign:1; +} double_t; + +typedef struct { + unsigned mantissal:32; + unsigned mantissah:32; + unsigned exponent:15; + unsigned sign:1; +} long_double_t; + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_ieee_h__ */ diff --git a/include/lsass/lsass.h b/include/lsass/lsass.h new file mode 100644 index 0000000..a276837 --- /dev/null +++ b/include/lsass/lsass.h @@ -0,0 +1,130 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include/lsass/lsass.h + * PURPOSE: LSASS API declarations + * UPDATE HISTORY: + * Created 05/08/00 + */ + +#ifndef __INCLUDE_LSASS_LSASS_H +#define __INCLUDE_LSASS_LSASS_H + +#include +#include +#include + +#define LSASS_REQUEST_REGISTER_LOGON_PROCESS (1) +#define LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE (2) +#define LSASS_REQUEST_DEREGISTER_LOGON_PROCESS (3) +#define LSASS_REQUEST_LOGON_USER (4) +#define LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE (5) +#define LSASS_REQUEST_MAXIMUM (6) + +typedef struct _LSASS_LOOKUP_AUTHENTICATION_PACKAGE_REQUEST +{ + ULONG PackageNameLength; + WCHAR PackageName[0]; +} LSASS_LOOKUP_AUTHENTICATION_PACKAGE_REQUEST, + *PLSASS_LOOKUP_AUTHENTICATION_PACKAGE_REQUEST; + +typedef struct _LSASS_LOOKUP_AUTHENTICATION_PACKAGE_REPLY +{ + ULONG Package; +} LSASS_LOOKUP_AUTHENTICATION_PACKAGE_REPLY, + *PLSASS_LOOKUP_AUTHENTICATION_PACKAGE_REPLY; + +typedef struct _LSASS_DEREGISTER_LOGON_PROCESS_REQUEST +{ +} LSASS_DEREGISTER_LOGON_PROCESS_REQUEST, + *PLSASS_DEREGISTER_LOGON_PROCES_REQUEST; + +typedef struct _LSASS_DEREGISTER_LOGON_PROCESS_REPLY +{ +} LSASS_DEREGISTER_LOGON_PROCESS_REPLY, + *PLSASS_DEREGISTER_LOGON_PROCESS_REPLY; + +typedef struct _LSASS_CALL_AUTHENTICATION_PACKAGE_REQUEST +{ + ULONG AuthenticationPackage; + ULONG InBufferLength; + UCHAR InBuffer[0]; +} LSASS_CALL_AUTHENTICATION_PACKAGE_REQUEST, +*PLSASS_CALL_AUTHENTICATION_PACKAGE_REQUEST; + +typedef struct _LSASS_CALL_AUTHENTICATION_PACKAGE_REPLY +{ + ULONG OutBufferLength; + UCHAR OutBuffer[0]; +} LSASS_CALL_AUTHENTICATION_PACKAGE_REPLY, +*PLSASS_CALL_AUTHENTICATION_PACKAGE_REPLY; + +typedef struct _LSASS_LOGON_USER_REQUEST +{ + ULONG OriginNameLength; + PWSTR OriginName; + SECURITY_LOGON_TYPE LogonType; + ULONG AuthenticationPackage; + PVOID AuthenticationInformation; + ULONG AuthenticationInformationLength; + ULONG LocalGroupsCount; + PSID_AND_ATTRIBUTES LocalGroups; + TOKEN_SOURCE SourceContext; + UCHAR Data[1]; +} LSASS_LOGON_USER_REQUEST, *PLSASS_LOGON_USER_REQUEST; + +typedef struct _LSASS_LOGON_USER_REPLY +{ + PVOID ProfileBuffer; + ULONG ProfileBufferLength; + LUID LogonId; + HANDLE Token; + QUOTA_LIMITS Quotas; + NTSTATUS SubStatus; + UCHAR Data[1]; +} LSASS_LOGON_USER_REPLY, *PLSASS_LOGON_USER_REPLY; + +typedef struct _LSASS_REGISTER_LOGON_PROCESS_REQUEST +{ + ULONG Length; + WCHAR LogonProcessNameBuffer[127]; +} LSASS_REGISTER_LOGON_PROCESS_REQUEST, *PLSASS_REGISTER_LOGON_PROCESS_REQUEST; + +typedef struct _LSASS_REGISTER_LOGON_PROCESS_REPLY +{ + LSA_OPERATIONAL_MODE OperationalMode; +} LSASS_REGISTER_LOGON_PROCESS_REPLY, *PLSASS_REGISTER_LOGON_PROCESS_REPLY; + +typedef struct _LSASS_REQUEST +{ + LPC_MESSAGE_HEADER Header; + ULONG Type; + union + { + LSASS_REGISTER_LOGON_PROCESS_REQUEST RegisterLogonProcessRequest; + LSASS_LOGON_USER_REQUEST LogonUserRequest; + LSASS_CALL_AUTHENTICATION_PACKAGE_REQUEST + CallAuthenticationPackageRequest; + LSASS_DEREGISTER_LOGON_PROCESS_REPLY DeregisterLogonProcessRequest; + LSASS_LOOKUP_AUTHENTICATION_PACKAGE_REQUEST + LookupAuthenticationPackageRequest; + } d; +} LSASS_REQUEST, *PLSASS_REQUEST; + +typedef struct _LSASS_REPLY +{ + LPC_MESSAGE_HEADER Header; + NTSTATUS Status; + union + { + LSASS_REGISTER_LOGON_PROCESS_REPLY RegisterLogonProcessReply; + LSASS_LOGON_USER_REPLY LogonUserReply; + LSASS_CALL_AUTHENTICATION_PACKAGE_REPLY CallAuthenticationPackageReply; + LSASS_DEREGISTER_LOGON_PROCESS_REPLY DeregisterLogonProcessReply; + LSASS_LOOKUP_AUTHENTICATION_PACKAGE_REPLY + LookupAuthenticationPackageReply; + } d; +} LSASS_REPLY, *PLSASS_REPLY; + +#endif /* __INCLUDE_LSASS_LSASS_H */ diff --git a/include/lsass/ntsecapi.h b/include/lsass/ntsecapi.h new file mode 100644 index 0000000..837c50a --- /dev/null +++ b/include/lsass/ntsecapi.h @@ -0,0 +1,32 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include/lsass/ntsecpai.h + * PURPOSE: LSASS API declarations + * UPDATE HISTORY: + * Created 05/08/00 + */ + +#ifndef __INCLUDE_LSASS_NTSECAPI_H +#define __INCLUDE_LSASS_NTSECAPI_H + +#define SECURITY_LOGON_INTERACTIVE (2) +#define SECURITY_LOGON_NETWORK (3) +#define SECURITY_LOGON_BATCH (4) +#define SECURITY_LOGON_SERVICE (5) +#define SECURITY_LOGON_PROXY (6) +#define SECURITY_LOGON_UNLOCK (7) + +typedef ULONG SECURITY_LOGON_TYPE; + +typedef struct _LSA_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} LSA_STRING, *PLSA_STRING; + +typedef ULONG LSA_OPERATIONAL_MODE, *PLSA_OPERATIONAL_MODE; + +#endif /* __INCLUDE_LSASS_NTSECAPI_H */ diff --git a/include/messages.h b/include/messages.h new file mode 100644 index 0000000..a2e5745 --- /dev/null +++ b/include/messages.h @@ -0,0 +1,1099 @@ +/* + Messages.h + + Windows32 API message definitions + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Scott Christley + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +/* WARNING: This file is automatically generated. */ + +#ifndef _GNU_H_WINDOWS32_MESSAGES +#define _GNU_H_WINDOWS32_MESSAGES + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Application bar */ + +/* Application bar notifications */ + +/* Animation Control */ +#define ACM_OPENW (1127) +#define ACM_OPENA (1124) +#ifdef UNICODE +#define ACM_OPEN ACM_OPENW +#else +#define ACM_OPEN ACM_OPENA +#endif /* UNICODE */ +#define ACM_PLAY (1125) +#define ACM_STOP (1126) +#define ACN_START (1) +#define ACN_STOP (2) + +/* Buttons */ +#define BM_CLICK (245) +#define BM_GETCHECK (240) +#define BM_GETIMAGE (246) +#define BM_GETSTATE (242) +#define BM_SETCHECK (241) +#define BM_SETIMAGE (247) +#define BM_SETSTATE (243) +#define BM_SETSTYLE (244) +#define BN_CLICKED (0) +#define BN_DBLCLK (5) +#define BN_DISABLE (4) +#define BN_DOUBLECLICKED (5) +#define BN_HILITE (2) +#define BN_KILLFOCUS (7) +#define BN_PAINT (1) +#define BN_PUSHED (2) +#define BN_SETFOCUS (6) +#define BN_UNHILITE (3) +#define BN_UNPUSHED (3) + +/* Combo Box */ +#define CB_ADDSTRING (323) +#define CB_DELETESTRING (324) +#define CB_DIR (325) +#define CB_FINDSTRING (332) +#define CB_FINDSTRINGEXACT (344) +#define CB_GETCOUNT (326) +#define CB_GETCURSEL (327) +#define CB_GETDROPPEDCONTROLRECT (338) +#define CB_GETDROPPEDSTATE (343) +#define CB_GETDROPPEDWIDTH (351) +#define CB_GETEDITSEL (320) +#define CB_GETEXTENDEDUI (342) +#define CB_GETHORIZONTALEXTENT (349) +#define CB_GETITEMDATA (336) +#define CB_GETITEMHEIGHT (340) +#define CB_GETLBTEXT (328) +#define CB_GETLBTEXTLEN (329) +#define CB_GETLOCALE (346) +#define CB_GETTOPINDEX (347) +#define CB_INITSTORAGE (353) +#define CB_INSERTSTRING (330) +#define CB_LIMITTEXT (321) +#define CB_RESETCONTENT (331) +#define CB_SELECTSTRING (333) +#define CB_SETCURSEL (334) +#define CB_SETDROPPEDWIDTH (352) +#define CB_SETEDITSEL (322) +#define CB_SETEXTENDEDUI (341) +#define CB_SETHORIZONTALEXTENT (350) +#define CB_SETITEMDATA (337) +#define CB_SETITEMHEIGHT (339) +#define CB_SETLOCALE (345) +#define CB_SETTOPINDEX (348) +#define CB_SHOWDROPDOWN (335) + +/* Combo Box notifications */ +#define CBN_CLOSEUP (8) +#define CBN_DBLCLK (2) +#define CBN_DROPDOWN (7) +#define CBN_EDITCHANGE (5) +#define CBN_EDITUPDATE (6) +#define CBN_ERRSPACE (-1) +#define CBN_KILLFOCUS (4) +#define CBN_SELCHANGE (1) +#define CBN_SELENDCANCEL (10) +#define CBN_SELENDOK (9) +#define CBN_SETFOCUS (3) + +/* Control Panel */ + +/* Device messages */ + +/* Drag list box */ +#define DL_BEGINDRAG (1157) +#define DL_CANCELDRAG (1160) +#define DL_DRAGGING (1158) +#define DL_DROPPED (1159) + +/* Default push button */ +#define DM_GETDEFID (1024) +#define DM_REPOSITION (1026) +#define DM_SETDEFID (1025) + +/* RTF control */ +#define EM_CANPASTE (1074) +#define EM_CANUNDO (198) +#define EM_CHARFROMPOS (215) +#define EM_DISPLAYBAND (1075) +#define EM_EMPTYUNDOBUFFER (205) +#define EM_EXGETSEL (1076) +#define EM_EXLIMITTEXT (1077) +#define EM_EXLINEFROMCHAR (1078) +#define EM_EXSETSEL (1079) +#define EM_FINDTEXT (1080) +#define EM_FINDTEXTEX (1103) +#define EM_FINDWORDBREAK (1100) +#define EM_FMTLINES (200) +#define EM_FORMATRANGE (1081) +#define EM_GETCHARFORMAT (1082) +#define EM_GETEVENTMASK (1083) +#define EM_GETFIRSTVISIBLELINE (206) +#define EM_GETHANDLE (189) +#define EM_GETLIMITTEXT (213) +#define EM_GETLINE (196) +#define EM_GETLINECOUNT (186) +#define EM_GETMARGINS (212) +#define EM_GETMODIFY (184) +#define EM_GETIMECOLOR (1129) +#define EM_GETIMEOPTIONS (1131) +#define EM_GETOPTIONS (1102) +#define EM_GETOLEINTERFACE (1084) +#define EM_GETPARAFORMAT (1085) +#define EM_GETPASSWORDCHAR (210) +#define EM_GETPUNCTUATION (1125) +#define EM_GETRECT (178) +#define EM_GETSEL (176) +#define EM_GETSELTEXT (1086) +#define EM_GETTEXTRANGE (1099) +#define EM_GETTHUMB (190) +#define EM_GETWORDBREAKPROC (209) +#define EM_GETWORDBREAKPROCEX (1104) +#define EM_GETWORDWRAPMODE (1127) +#define EM_HIDESELECTION (1087) +#define EM_LIMITTEXT (197) +#define EM_LINEFROMCHAR (201) +#define EM_LINEINDEX (187) +#define EM_LINELENGTH (193) +#define EM_LINESCROLL (182) +#define EM_PASTESPECIAL (1088) +#define EM_POSFROMCHAR (214) +#define EM_REPLACESEL (194) +#define EM_REQUESTRESIZE (1089) +#define EM_SCROLL (181) +#define EM_SCROLLCARET (183) +#define EM_SELECTIONTYPE (1090) +#define EM_SETBKGNDCOLOR (1091) +#define EM_SETCHARFORMAT (1092) +#define EM_SETEVENTMASK (1093) +#define EM_SETHANDLE (188) +#define EM_SETIMECOLOR (1128) +#define EM_SETIMEOPTIONS (1130) +#define EM_SETLIMITTEXT (197) +#define EM_SETMARGINS (211) +#define EM_SETMODIFY (185) +#define EM_SETOLECALLBACK (1094) +#define EM_SETOPTIONS (1101) +#define EM_SETPARAFORMAT (1095) +#define EM_SETPASSWORDCHAR (204) +#define EM_SETPUNCTUATION (1124) +#define EM_SETREADONLY (207) +#define EM_SETRECT (179) +#define EM_SETRECTNP (180) +#define EM_SETSEL (177) +#define EM_SETTABSTOPS (203) +#define EM_SETTARGETDEVICE (1096) +#define EM_SETWORDBREAKPROC (208) +#define EM_SETWORDBREAKPROCEX (1105) +#define EM_SETWORDWRAPMODE (1126) +#define EM_STREAMIN (1097) +#define EM_STREAMOUT (1098) +#define EM_UNDO (199) + +/* Edit control */ +#define EN_CHANGE (768) +#define EN_CORRECTTEXT (1797) +#define EN_DROPFILES (1795) +#define EN_ERRSPACE (1280) +#define EN_HSCROLL (1537) +#define EN_IMECHANGE (1799) +#define EN_KILLFOCUS (512) +#define EN_MAXTEXT (1281) +#define EN_MSGFILTER (1792) +#define EN_OLEOPFAILED (1801) +#define EN_PROTECTED (1796) +#define EN_REQUESTRESIZE (1793) +#define EN_SAVECLIPBOARD (1800) +#define EN_SELCHANGE (1794) +#define EN_SETFOCUS (256) +#define EN_STOPNOUNDO (1798) +#define EN_UPDATE (1024) +#define EN_VSCROLL (1538) + +/* File Manager extensions */ + +/* File Manager extensions DLL events */ + +/* Header control */ +#define HDM_DELETEITEM (4610) +#define HDM_GETITEMW (4619) +#define HDM_INSERTITEMW (4618) +#define HDM_SETITEMW (4620) +#define HDM_GETITEMA (4611) +#define HDM_INSERTITEMA (4609) +#define HDM_SETITEMA (4612) +#ifdef UNICODE +#define HDM_GETITEM HDM_GETITEMW +#define HDM_INSERTITEM HDM_INSERTITEMW +#define HDM_SETITEM HDM_SETITEMW +#else +#define HDM_GETITEM HDM_GETITEMA +#define HDM_INSERTITEM HDM_INSERTITEMA +#define HDM_SETITEM HDM_SETITEMA +#endif /* UNICODE */ +#define HDM_GETITEMCOUNT (4608) +#define HDM_HITTEST (4614) +#define HDM_LAYOUT (4613) + +/* Header control notifications */ +#define HDN_BEGINTRACKW (-326) +#define HDN_DIVIDERDBLCLICKW (-325) +#define HDN_ENDTRACKW (-327) +#define HDN_ITEMCHANGEDW (-321) +#define HDN_ITEMCHANGINGW (-320) +#define HDN_ITEMCLICKW (-322) +#define HDN_ITEMDBLCLICKW (-323) +#define HDN_TRACKW (-328) +#define HDN_BEGINTRACKA (-306) +#define HDN_DIVIDERDBLCLICKA (-305) +#define HDN_ENDTRACKA (-307) +#define HDN_ITEMCHANGEDA (-301) +#define HDN_ITEMCHANGINGA (-300) +#define HDN_ITEMCLICKA (-302) +#define HDN_ITEMDBLCLICKA (-303) +#define HDN_TRACKA (-308) +#ifdef UNICODE +#define HDN_BEGINTRACK HDN_BEGINTRACKW +#define HDN_DIVIDERDBLCLICK HDN_DIVIDERDBLCLICKW +#define HDN_ENDTRACK HDN_ENDTRACKW +#define HDN_ITEMCHANGED HDN_ITEMCHANGEDW +#define HDN_ITEMCHANGING HDN_ITEMCHANGINGW +#define HDN_ITEMCLICK HDN_ITEMCLICKW +#define HDN_ITEMDBLCLICK HDN_ITEMDBLCLICKW +#define HDN_TRACK HDN_TRACKW +#else +#define HDN_BEGINTRACK HDN_BEGINTRACKA +#define HDN_DIVIDERDBLCLICK HDN_DIVIDERDBLCLICKA +#define HDN_ENDTRACK HDN_ENDTRACKA +#define HDN_ITEMCHANGED HDN_ITEMCHANGEDA +#define HDN_ITEMCHANGING HDN_ITEMCHANGINGA +#define HDN_ITEMCLICK HDN_ITEMCLICKA +#define HDN_ITEMDBLCLICK HDN_ITEMDBLCLICKA +#define HDN_TRACK HDN_TRACKA +#endif /* UNICODE */ + +/* Hot key control */ +#define HKM_GETHOTKEY (1026) +#define HKM_SETHOTKEY (1025) +#define HKM_SETRULES (1027) + +/* List box */ +#define LB_ADDFILE (406) +#define LB_ADDSTRING (384) +#define LB_DELETESTRING (386) +#define LB_DIR (397) +#define LB_FINDSTRING (399) +#define LB_FINDSTRINGEXACT (418) +#define LB_GETANCHORINDEX (413) +#define LB_GETCARETINDEX (415) +#define LB_GETCOUNT (395) +#define LB_GETCURSEL (392) +#define LB_GETHORIZONTALEXTENT (403) +#define LB_GETITEMDATA (409) +#define LB_GETITEMHEIGHT (417) +#define LB_GETITEMRECT (408) +#define LB_GETLOCALE (422) +#define LB_GETSEL (391) +#define LB_GETSELCOUNT (400) +#define LB_GETSELITEMS (401) +#define LB_GETTEXT (393) +#define LB_GETTEXTLEN (394) +#define LB_GETTOPINDEX (398) +#define LB_INITSTORAGE (424) +#define LB_INSERTSTRING (385) +#define LB_ITEMFROMPOINT (425) +#define LB_RESETCONTENT (388) +#define LB_SELECTSTRING (396) +#define LB_SELITEMRANGE (411) +#define LB_SELITEMRANGEEX (387) +#define LB_SETANCHORINDEX (412) +#define LB_SETCARETINDEX (414) +#define LB_SETCOLUMNWIDTH (405) +#define LB_SETCOUNT (423) +#define LB_SETCURSEL (390) +#define LB_SETHORIZONTALEXTENT (404) +#define LB_SETITEMDATA (410) +#define LB_SETITEMHEIGHT (416) +#define LB_SETLOCALE (421) +#define LB_SETSEL (389) +#define LB_SETTABSTOPS (402) +#define LB_SETTOPINDEX (407) + +/* List box notifications */ +#define LBN_DBLCLK (2) +#define LBN_ERRSPACE (-2) +#define LBN_KILLFOCUS (5) +#define LBN_SELCANCEL (3) +#define LBN_SELCHANGE (1) +#define LBN_SETFOCUS (4) + +/* List view control */ +#define LVM_ARRANGE (4118) +#define LVM_CREATEDRAGIMAGE (4129) +#define LVM_DELETEALLITEMS (4105) +#define LVM_DELETECOLUMN (4124) +#define LVM_DELETEITEM (4104) +#define LVM_ENSUREVISIBLE (4115) +#define LVM_GETBKCOLOR (4096) +#define LVM_GETCALLBACKMASK (4106) +#define LVM_GETCOLUMNWIDTH (4125) +#define LVM_GETCOUNTPERPAGE (4136) +#define LVM_GETEDITCONTROL (4120) +#define LVM_GETIMAGELIST (4098) +#define LVM_EDITLABELW (4214) +#define LVM_FINDITEMW (4179) +#define LVM_GETCOLUMNW (4191) +#define LVM_GETISEARCHSTRINGW (4213) +#define LVM_GETITEMW (4171) +#define LVM_GETITEMTEXTW (4211) +#define LVM_GETSTRINGWIDTHW (4183) +#define LVM_INSERTCOLUMNW (4193) +#define LVM_INSERTITEMW (4173) +#define LVM_SETCOLUMNW (4192) +#define LVM_SETITEMW (4172) +#define LVM_SETITEMTEXTW (4212) +#define LVM_EDITLABELA (4119) +#define LVM_FINDITEMA (4109) +#define LVM_GETCOLUMNA (4121) +#define LVM_GETISEARCHSTRINGA (4148) +#define LVM_GETITEMA (4101) +#define LVM_GETITEMTEXTA (4141) +#define LVM_GETSTRINGWIDTHA (4113) +#define LVM_INSERTCOLUMNA (4123) +#define LVM_INSERTITEMA (4103) +#define LVM_SETCOLUMNA (4122) +#define LVM_SETITEMA (4102) +#define LVM_SETITEMTEXTA (4142) +#ifdef UNICODE +#define LVM_EDITLABEL LVM_EDITLABELW +#define LVM_FINDITEM LVM_FINDITEMW +#define LVM_GETCOLUMN LVM_GETCOLUMNW +#define LVM_GETISEARCHSTRING LVM_GETISEARCHSTRINGW +#define LVM_GETITEM LVM_GETITEMW +#define LVM_GETITEMTEXT LVM_GETITEMTEXTW +#define LVM_GETSTRINGWIDTH LVM_GETSTRINGWIDTHW +#define LVM_INSERTCOLUMN LVM_INSERTCOLUMNW +#define LVM_INSERTITEM LVM_INSERTITEMW +#define LVM_SETCOLUMN LVM_SETCOLUMNW +#define LVM_SETITEM LVM_SETITEMW +#define LVM_SETITEMTEXT LVM_SETITEMTEXTW +#else +#define LVM_EDITLABEL LVM_EDITLABELA +#define LVM_FINDITEM LVM_FINDITEMA +#define LVM_GETCOLUMN LVM_GETCOLUMNA +#define LVM_GETISEARCHSTRING LVM_GETISEARCHSTRINGA +#define LVM_GETITEM LVM_GETITEMA +#define LVM_GETITEMTEXT LVM_GETITEMTEXTA +#define LVM_GETSTRINGWIDTH LVM_GETSTRINGWIDTHA +#define LVM_INSERTCOLUMN LVM_INSERTCOLUMNA +#define LVM_INSERTITEM LVM_INSERTITEMA +#define LVM_SETCOLUMN LVM_SETCOLUMNA +#define LVM_SETITEM LVM_SETITEMA +#define LVM_SETITEMTEXT LVM_SETITEMTEXTA +#endif /* UNICODE */ +#define LVM_GETITEMCOUNT (4100) +#define LVM_GETITEMPOSITION (4112) +#define LVM_GETITEMRECT (4110) +#define LVM_GETITEMSPACING (4147) +#define LVM_GETITEMSTATE (4140) +#define LVM_GETNEXTITEM (4108) +#define LVM_GETORIGIN (4137) +#define LVM_GETSELECTEDCOUNT (4146) +#define LVM_GETTEXTBKCOLOR (4133) +#define LVM_GETTEXTCOLOR (4131) +#define LVM_GETTOPINDEX (4135) +#define LVM_GETVIEWRECT (4130) +#define LVM_HITTEST (4114) +#define LVM_REDRAWITEMS (4117) +#define LVM_SCROLL (4116) +#define LVM_SETBKCOLOR (4097) +#define LVM_SETCALLBACKMASK (4107) +#define LVM_SETCOLUMNWIDTH (4126) +#define LVM_SETIMAGELIST (4099) +#define LVM_SETITEMCOUNT (4143) +#define LVM_SETITEMPOSITION (4111) +#define LVM_SETITEMPOSITION32 (4145) +#define LVM_SETITEMSTATE (4139) +#define LVM_SETTEXTBKCOLOR (4134) +#define LVM_SETTEXTCOLOR (4132) +#define LVM_SORTITEMS (4144) +#define LVM_UPDATE (4138) + +/* List view control notifications */ +#define LVN_BEGINDRAG (-109) +#define LVN_BEGINRDRAG (-111) +#define LVN_COLUMNCLICK (-108) +#define LVN_DELETEALLITEMS (-104) +#define LVN_DELETEITEM (-103) +#define LVN_BEGINLABELEDITW (-175) +#define LVN_ENDLABELEDITW (-176) +#define LVN_GETDISPINFOW (-177) +#define LVN_SETDISPINFOW (-178) +#define LVN_BEGINLABELEDITA (-105) +#define LVN_ENDLABELEDITA (-106) +#define LVN_GETDISPINFOA (-150) +#define LVN_SETDISPINFOA (-151) +#ifdef UNICODE +#define LVN_BEGINLABELEDIT LVN_BEGINLABELEDITW +#define LVN_ENDLABELEDIT LVN_ENDLABELEDITW +#define LVN_GETDISPINFO LVN_GETDISPINFOW +#define LVN_SETDISPINFO LVN_SETDISPINFOW +#else +#define LVN_BEGINLABELEDIT LVN_BEGINLABELEDITA +#define LVN_ENDLABELEDIT LVN_ENDLABELEDITA +#define LVN_GETDISPINFO LVN_GETDISPINFOA +#define LVN_SETDISPINFO LVN_SETDISPINFOA +#endif /* UNICODE */ +#define LVN_INSERTITEM (-102) +#define LVN_ITEMCHANGED (-101) +#define LVN_ITEMCHANGING (-100) +#define LVN_KEYDOWN (-155) + +/* Control notification */ +#define NM_CLICK (-2) +#define NM_DBLCLK (-3) +#define NM_KILLFOCUS (-8) +#define NM_OUTOFMEMORY (-1) +#define NM_RCLICK (-5) +#define NM_RDBLCLK (-6) +#define NM_RETURN (-4) +#define NM_SETFOCUS (-7) + +/* Power status */ + +/* Progress bar control */ +#define PBM_DELTAPOS (1027) +#define PBM_SETPOS (1026) +#define PBM_SETRANGE (1025) +#define PBM_SETSTEP (1028) +#define PBM_STEPIT (1029) + +/* Property sheets */ +#define PSM_ADDPAGE (1127) +#define PSM_APPLY (1134) +#define PSM_CANCELTOCLOSE (1131) +#define PSM_CHANGED (1128) +#define PSM_GETTABCONTROL (1140) +#define PSM_GETCURRENTPAGEHWND (1142) +#define PSM_ISDIALOGMESSAGE (1141) +#define PSM_PRESSBUTTON (1137) +#define PSM_QUERYSIBLINGS (1132) +#define PSM_REBOOTSYSTEM (1130) +#define PSM_REMOVEPAGE (1126) +#define PSM_RESTARTWINDOWS (1129) +#define PSM_SETCURSEL (1125) +#define PSM_SETCURSELID (1138) +#define PSM_SETFINISHTEXTW (1145) +#define PSM_SETTITLEW (1144) +#define PSM_SETFINISHTEXTA (1139) +#define PSM_SETTITLEA (1135) +#ifdef UNICODE +#define PSM_SETFINISHTEXT PSM_SETFINISHTEXTW +#define PSM_SETTITLE PSM_SETTITLEW +#else +#define PSM_SETFINISHTEXT PSM_SETFINISHTEXTA +#define PSM_SETTITLE PSM_SETTITLEA +#endif /* UNICODE */ +#define PSM_SETWIZBUTTONS (1136) +#define PSM_UNCHANGED (1133) + +/* Property sheet notifications */ +#define PSN_APPLY (-202) +#define PSN_HELP (-205) +#define PSN_KILLACTIVE (-201) +#define PSN_QUERYCANCEL (-209) +#define PSN_RESET (-203) +#define PSN_SETACTIVE (-200) +#define PSN_WIZBACK (-206) +#define PSN_WIZFINISH (-208) +#define PSN_WIZNEXT (-207) + +/* Status window */ +#define SB_GETBORDERS (1031) +#define SB_GETPARTS (1030) +#define SB_GETRECT (1034) +#define SB_GETTEXTW (1037) +#define SB_GETTEXTLENGTHW (1036) +#define SB_SETTEXTW (1035) +#define SB_GETTEXTA (1026) +#define SB_GETTEXTLENGTHA (1027) +#define SB_SETTEXTA (1025) +#ifdef UNICODE +#define SB_GETTEXT SB_GETTEXTW +#define SB_GETTEXTLENGTH SB_GETTEXTLENGTHW +#define SB_SETTEXT SB_SETTEXTW +#else +#define SB_GETTEXT SB_GETTEXTA +#define SB_GETTEXTLENGTH SB_GETTEXTLENGTHA +#define SB_SETTEXT SB_SETTEXTA +#endif /* UNICODE */ +#define SB_SETMINHEIGHT (1032) +#define SB_SETPARTS (1028) +#define SB_SIMPLE (1033) + +/* Scroll bar control */ +#define SBM_ENABLE_ARROWS (228) +#define SBM_GETPOS (225) +#define SBM_GETRANGE (227) +#define SBM_GETSCROLLINFO (234) +#define SBM_SETPOS (224) +#define SBM_SETRANGE (226) +#define SBM_SETRANGEREDRAW (230) +#define SBM_SETSCROLLINFO (233) + +/* Static control */ +#define STM_GETICON (369) +#define STM_GETIMAGE (371) +#define STM_SETICON (368) +#define STM_SETIMAGE (370) + +/* Static control notifications */ +#define STN_CLICKED (0) +#define STN_DBLCLK (1) +#define STN_DISABLE (3) +#define STN_ENABLE (2) + +/* Toolbar control */ +#define TB_ADDBITMAP (1043) +#define TB_ADDBUTTONS (1044) +#define TB_AUTOSIZE (1057) +#define TB_BUTTONCOUNT (1048) +#define TB_BUTTONSTRUCTSIZE (1054) +#define TB_CHANGEBITMAP (1067) +#define TB_CHECKBUTTON (1026) +#define TB_COMMANDTOINDEX (1049) +#define TB_CUSTOMIZE (1051) +#define TB_DELETEBUTTON (1046) +#define TB_ENABLEBUTTON (1025) +#define TB_GETBITMAP (1068) +#define TB_GETBITMAPFLAGS (1065) +#define TB_GETBUTTON (1047) +#define TB_ADDSTRINGW (1101) +#define TB_GETBUTTONTEXTW (1099) +#define TB_SAVERESTOREW (1100) +#define TB_ADDSTRINGA (1052) +#define TB_GETBUTTONTEXTA (1069) +#define TB_SAVERESTOREA (1050) +#ifdef UNICODE +#define TB_ADDSTRING TB_ADDSTRINGW +#define TB_GETBUTTONTEXT TB_GETBUTTONTEXTW +#define TB_SAVERESTORE TB_SAVERESTOREW +#else +#define TB_ADDSTRING TB_ADDSTRINGA +#define TB_GETBUTTONTEXT TB_GETBUTTONTEXTA +#define TB_SAVERESTORE TB_SAVERESTOREA +#endif /* UNICODE */ +#define TB_GETITEMRECT (1053) +#define TB_GETROWS (1064) +#define TB_GETSTATE (1042) +#define TB_GETTOOLTIPS (1059) +#define TB_HIDEBUTTON (1028) +#define TB_INDETERMINATE (1029) +#define TB_INSERTBUTTON (1045) +#define TB_ISBUTTONCHECKED (1034) +#define TB_ISBUTTONENABLED (1033) +#define TB_ISBUTTONHIDDEN (1036) +#define TB_ISBUTTONINDETERMINATE (1037) +#define TB_ISBUTTONPRESSED (1035) +#define TB_PRESSBUTTON (1027) +#define TB_SETBITMAPSIZE (1056) +#define TB_SETBUTTONSIZE (1055) +#define TB_SETCMDID (1066) +#define TB_SETPARENT (1061) +#define TB_SETROWS (1063) +#define TB_SETSTATE (1041) +#define TB_SETTOOLTIPS (1060) + +/* Track bar control */ +#define TBM_CLEARSEL (1043) +#define TBM_CLEARTICS (1033) +#define TBM_GETCHANNELRECT (1050) +#define TBM_GETLINESIZE (1048) +#define TBM_GETNUMTICS (1040) +#define TBM_GETPAGESIZE (1046) +#define TBM_GETPOS (1024) +#define TBM_GETPTICS (1038) +#define TBM_GETRANGEMAX (1026) +#define TBM_GETRANGEMIN (1025) +#define TBM_GETSELEND (1042) +#define TBM_GETSELSTART (1041) +#define TBM_GETTHUMBLENGTH (1052) +#define TBM_GETTHUMBRECT (1049) +#define TBM_GETTIC (1027) +#define TBM_GETTICPOS (1039) +#define TBM_SETLINESIZE (1047) +#define TBM_SETPAGESIZE (1045) +#define TBM_SETPOS (1029) +#define TBM_SETRANGE (1030) +#define TBM_SETRANGEMAX (1032) +#define TBM_SETRANGEMIN (1031) +#define TBM_SETSEL (1034) +#define TBM_SETSELEND (1036) +#define TBM_SETSELSTART (1035) +#define TBM_SETTHUMBLENGTH (1051) +#define TBM_SETTIC (1028) +#define TBM_SETTICFREQ (1044) + +/* Tool bar control notifications */ +#define TBN_BEGINADJUST (-703) +#define TBN_BEGINDRAG (-701) +#define TBN_CUSTHELP (-709) +#define TBN_ENDADJUST (-704) +#define TBN_ENDDRAG (-702) +#define TBN_GETBUTTONINFOW (-720) +#define TBN_GETBUTTONINFOA (-700) +#ifdef UNICODE +#define TBN_GETBUTTONINFO TBN_GETBUTTONINFOW +#else +#define TBN_GETBUTTONINFO TBN_GETBUTTONINFOA +#endif /* UNICODE */ +#define TBN_QUERYDELETE (-707) +#define TBN_QUERYINSERT (-706) +#define TBN_RESET (-705) +#define TBN_TOOLBARCHANGE (-708) + +/* Tab control */ +#define TCM_ADJUSTRECT (4904) +#define TCM_DELETEALLITEMS (4873) +#define TCM_DELETEITEM (4872) +#define TCM_GETCURFOCUS (4911) +#define TCM_GETCURSEL (4875) +#define TCM_GETIMAGELIST (4866) +#define TCM_GETITEMW (4924) +#define TCM_INSERTITEMW (4926) +#define TCM_SETITEMW (4925) +#define TCM_GETITEMA (4869) +#define TCM_INSERTITEMA (4871) +#define TCM_SETITEMA (4870) +#ifdef UNICODE +#define TCM_GETITEM TCM_GETITEM +#define TCM_INSERTITEM TCM_INSERTITEMW +#define TCM_SETITEM TCM_SETITEMW +#else +#define TCM_GETITEM TCM_GETITEMA +#define TCM_INSERTITEM TCM_INSERTITEMA +#define TCM_SETITEM TCM_SETITEMA +#endif /* UNICODE */ +#define TCM_GETITEMCOUNT (4868) +#define TCM_GETITEMRECT (4874) +#define TCM_GETROWCOUNT (4908) +#define TCM_GETTOOLTIPS (4909) +#define TCM_HITTEST (4877) +#define TCM_REMOVEIMAGE (4906) +#define TCM_SETCURFOCUS (4912) +#define TCM_SETCURSEL (4876) +#define TCM_SETIMAGELIST (4867) +#define TCM_SETITEMEXTRA (4878) +#define TCM_SETITEMSIZE (4905) +#define TCM_SETPADDING (4907) +#define TCM_SETTOOLTIPS (4910) + +/* Tab control notifications */ +#define TCN_KEYDOWN (-550) +#define TCN_SELCHANGE (-551) +#define TCN_SELCHANGING (-552) + +/* Tool tip control */ +#define TTM_ACTIVATE (1025) +#define TTM_ADDTOOLW (1074) +#define TTM_DELTOOLW (1075) +#define TTM_ENUMTOOLSW (1082) +#define TTM_GETCURRENTTOOLW (1083) +#define TTM_GETTEXTW (1080) +#define TTM_GETTOOLINFOW (1077) +#define TTM_HITTESTW (1079) +#define TTM_NEWTOOLRECTW (1076) +#define TTM_SETTOOLINFOW (1078) +#define TTM_UPDATETIPTEXTW (1081) +#define TTM_ADDTOOLA (1028) +#define TTM_DELTOOLA (1029) +#define TTM_ENUMTOOLSA (1038) +#define TTM_GETCURRENTTOOLA (1039) +#define TTM_GETTEXTA (1035) +#define TTM_GETTOOLINFOA (1032) +#define TTM_HITTESTA (1034) +#define TTM_NEWTOOLRECTA (1030) +#define TTM_SETTOOLINFOA (1033) +#define TTM_UPDATETIPTEXTA (1036) +#ifdef UNICODE +#define TTM_ADDTOOL TTM_ADDTOOLW +#define TTM_DELTOOL TTM_DELTOOLW +#define TTM_ENUMTOOLS TTM_ENUMTOOLSW +#define TTM_GETCURRENTTOOL TTM_GETCURRENTTOOLW +#define TTM_GETTEXT TTM_GETTEXTW +#define TTM_GETTOOLINFO TTM_GETTOOLINFOW +#define TTM_HITTEST TTM_HITTESTW +#define TTM_NEWTOOLRECT TTM_NEWTOOLRECTW +#define TTM_SETTOOLINFO TTM_SETTOOLINFOW +#define TTM_UPDATETIPTEXT TTM_UPDATETIPTEXTW +#else +#define TTM_ADDTOOL TTM_ADDTOOLA +#define TTM_DELTOOL TTM_DELTOOLA +#define TTM_ENUMTOOLS TTM_ENUMTOOLSA +#define TTM_GETCURRENTTOOL TTM_GETCURRENTTOOLA +#define TTM_GETTEXT TTM_GETTEXTA +#define TTM_GETTOOLINFO TTM_GETTOOLINFOA +#define TTM_HITTEST TTM_HITTESTA +#define TTM_NEWTOOLRECT TTM_NEWTOOLRECTA +#define TTM_SETTOOLINFO TTM_SETTOOLINFOA +#define TTM_UPDATETIPTEXT TTM_UPDATETIPTEXTA +#endif /* UNICODE */ +#define TTM_GETTOOLCOUNT (1037) +#define TTM_RELAYEVENT (1031) +#define TTM_SETDELAYTIME (1027) +#define TTM_WINDOWFROMPOINT (1040) + +/* Tool tip control notification */ +#define TTN_NEEDTEXTW (-530) +#define TTN_NEEDTEXTA (-520) +#ifdef UNICODE +#define TTN_NEEDTEXT TTN_NEEDTEXTW +#else +#define TTN_NEEDTEXT TTN_NEEDTEXTA +#endif /* UNICODE */ +#define TTN_POP (-522) +#define TTN_SHOW (-521) + +/* Tree view control */ +#define TVM_CREATEDRAGIMAGE (4370) +#define TVM_DELETEITEM (4353) +#define TVM_ENDEDITLABELNOW (4374) +#define TVM_ENSUREVISIBLE (4372) +#define TVM_EXPAND (4354) +#define TVM_GETCOUNT (4357) +#define TVM_GETEDITCONTROL (4367) +#define TVM_GETIMAGELIST (4360) +#define TVM_GETINDENT (4358) +#define TVM_GETITEMRECT (4356) +#define TVM_GETNEXTITEM (4362) +#define TVM_GETVISIBLECOUNT (4368) +#define TVM_HITTEST (4369) +#define TVM_EDITLABELW (4417) +#define TVM_GETISEARCHSTRINGW (4416) +#define TVM_GETITEMW (4414) +#define TVM_INSERTITEMW (4402) +#define TVM_SETITEMW (4415) +#define TVM_EDITLABELA (4366) +#define TVM_GETISEARCHSTRINGA (4375) +#define TVM_GETITEMA (4364) +#define TVM_INSERTITEMA (4352) +#define TVM_SETITEMA (4365) +#ifdef UNICODE +#define TVM_EDITLABEL TVM_EDITLABELW +#define TVM_GETISEARCHSTRING TVM_GETISEARCHSTRINGW +#define TVM_GETITEM TVM_GETITEMW +#define TVM_INSERTITEM TVM_INSERTITEMW +#define TVM_SETITEM TVM_SETITEMW +#else +#define TVM_EDITLABEL TVM_EDITLABELA +#define TVM_GETISEARCHSTRING TVM_GETISEARCHSTRINGA +#define TVM_GETITEM TVM_GETITEMA +#define TVM_INSERTITEM TVM_INSERTITEMA +#define TVM_SETITEM TVM_SETITEMA +#endif /* UNICODE */ +#define TVM_SELECTITEM (4363) +#define TVM_SETIMAGELIST (4361) +#define TVM_SETINDENT (4359) +#define TVM_SORTCHILDREN (4371) +#define TVM_SORTCHILDRENCB (4373) + +/* Tree view control notification */ +#define TVN_KEYDOWN (-412) +#define TVN_BEGINDRAGW (-456) +#define TVN_BEGINLABELEDITW (-459) +#define TVN_BEGINRDRAGW (-457) +#define TVN_DELETEITEMW (-458) +#define TVN_ENDLABELEDITW (-460) +#define TVN_GETDISPINFOW (-452) +#define TVN_ITEMEXPANDEDW (-455) +#define TVN_ITEMEXPANDINGW (-454) +#define TVN_SELCHANGEDW (-451) +#define TVN_SELCHANGINGW (-450) +#define TVN_SETDISPINFOW (-453) +#define TVN_BEGINDRAGA (-407) +#define TVN_BEGINLABELEDITA (-410) +#define TVN_BEGINRDRAGA (-408) +#define TVN_DELETEITEMA (-409) +#define TVN_ENDLABELEDITA (-411) +#define TVN_GETDISPINFOA (-403) +#define TVN_ITEMEXPANDEDA (-406) +#define TVN_ITEMEXPANDINGA (-405) +#define TVN_SELCHANGEDA (-402) +#define TVN_SELCHANGINGA (-401) +#define TVN_SETDISPINFOA (-404) +#ifdef UNICODE +#define TVN_BEGINDRAG TVN_BEGINDRAGW +#define TVN_BEGINLABELEDIT TVN_BEGINLABELEDITW +#define TVN_BEGINRDRAG TVN_BEGINRDRAGW +#define TVN_DELETEITEM TVN_DELETEITEMW +#define TVN_ENDLABELEDIT TVN_ENDLABELEDITW +#define TVN_GETDISPINFO TVN_GETDISPINFOW +#define TVN_ITEMEXPANDED TVN_ITEMEXPANDEDW +#define TVN_ITEMEXPANDING TVN_ITEMEXPANDINGW +#define TVN_SELCHANGED TVN_SELCHANGEDW +#define TVN_SELCHANGING TVN_SELCHANGINGW +#define TVN_SETDISPINFO TVN_SETDISPINFOW +#else +#define TVN_BEGINDRAG TVN_BEGINDRAGA +#define TVN_BEGINLABELEDIT TVN_BEGINLABELEDITA +#define TVN_BEGINRDRAG TVN_BEGINRDRAGA +#define TVN_DELETEITEM TVN_DELETEITEMA +#define TVN_ENDLABELEDIT TVN_ENDLABELEDITA +#define TVN_GETDISPINFO TVN_GETDISPINFOA +#define TVN_ITEMEXPANDED TVN_ITEMEXPANDEDA +#define TVN_ITEMEXPANDING TVN_ITEMEXPANDINGA +#define TVN_SELCHANGED TVN_SELCHANGEDA +#define TVN_SELCHANGING TVN_SELCHANGINGA +#define TVN_SETDISPINFO TVN_SETDISPINFOA +#endif /* UNICODE */ + +/* Up/down control */ +#define UDM_GETACCEL (1132) +#define UDM_GETBASE (1134) +#define UDM_GETBUDDY (1130) +#define UDM_GETPOS (1128) +#define UDM_GETRANGE (1126) +#define UDM_SETACCEL (1131) +#define UDM_SETBASE (1133) +#define UDM_SETBUDDY (1129) +#define UDM_SETPOS (1127) +#define UDM_SETRANGE (1125) + +/* Up/down control notification */ +#define UDN_DELTAPOS (-722) + +/* Window messages */ + +#define WM_ACTIVATE (6) +#define WM_ACTIVATEAPP (28) +#define WM_ASKCBFORMATNAME (780) +#define WM_CANCELJOURNAL (75) +#define WM_CANCELMODE (31) +#define WM_CAPTURECHANGED (533) +#define WM_CHANGECBCHAIN (781) +#define WM_CHAR (258) +#define WM_CHARTOITEM (47) +#define WM_CHILDACTIVATE (34) +#define WM_CHOOSEFONT_GETLOGFONT (1025) +#define WM_CHOOSEFONT_SETLOGFONT (1125) +#define WM_CHOOSEFONT_SETFLAGS (1126) +#define WM_CLEAR (771) +#define WM_CLOSE (16) +#define WM_COMMAND (273) +#define WM_COMPACTING (65) +#define WM_COMPAREITEM (57) +#define WM_CONTEXTMENU (123) +#define WM_COPY (769) +#define WM_COPYDATA (74) +#define WM_CREATE (1) +#define WM_CTLCOLORBTN (309) +#define WM_CTLCOLORDLG (310) +#define WM_CTLCOLOREDIT (307) +#define WM_CTLCOLORLISTBOX (308) +#define WM_CTLCOLORMSGBOX (306) +#define WM_CTLCOLORSCROLLBAR (311) +#define WM_CTLCOLORSTATIC (312) +#define WM_CUT (768) +#define WM_DEADCHAR (259) +#define WM_DELETEITEM (45) +#define WM_DESTROY (2) +#define WM_DESTROYCLIPBOARD (775) +#define WM_DEVICECHANGE (537) +#define WM_DEVMODECHANGE (27) +#define WM_DISPLAYCHANGE (126) +#define WM_DRAWCLIPBOARD (776) +#define WM_DRAWITEM (43) +#define WM_DROPFILES (563) +#define WM_DROPOBJECT (544) +#define WM_ENABLE (10) +#define WM_ENDSESSION (22) +#define WM_ENTERIDLE (289) +#define WM_ENTERMENULOOP (529) +#define WM_ENTERSIZEMOVE (561) +#define WM_ERASEBKGND (20) +#define WM_EXITMENULOOP (530) +#define WM_EXITSIZEMOVE (562) +#define WM_FONTCHANGE (29) +#define WM_GETDLGCODE (135) +#define WM_GETFONT (49) +#define WM_GETHOTKEY (51) +#define WM_GETICON (127) +#define WM_GETMINMAXINFO (36) +#define WM_GETTEXT (13) +#define WM_GETTEXTLENGTH (14) +#define WM_HELP (83) +#define WM_HOTKEY (786) +#define WM_HSCROLL (276) +#define WM_HSCROLLCLIPBOARD (782) +#define WM_ICONERASEBKGND (39) +#define WM_IME_CHAR (646) +#define WM_IME_COMPOSITION (271) +#define WM_IME_COMPOSITIONFULL (644) +#define WM_IME_CONTROL (643) +#define WM_IME_ENDCOMPOSITION (270) +#define WM_IME_KEYDOWN (656) +#define WM_IME_KEYUP (657) +#define WM_IME_NOTIFY (642) +#define WM_IME_SELECT (645) +#define WM_IME_SETCONTEXT (641) +#define WM_IME_STARTCOMPOSITION (269) +#define WM_INITDIALOG (272) +#define WM_INITMENU (278) +#define WM_INITMENUPOPUP (279) +#define WM_INPUTLANGCHANGE (81) +#define WM_INPUTLANGCHANGEREQUEST (80) +#define WM_KEYDOWN (256) +#define WM_KEYUP (257) +#define WM_KILLFOCUS (8) +#define WM_LBUTTONDBLCLK (515) +#define WM_LBUTTONDOWN (513) +#define WM_LBUTTONUP (514) +#define WM_MBUTTONDBLCLK (521) +#define WM_MBUTTONDOWN (519) +#define WM_MBUTTONUP (520) +#define WM_MDIACTIVATE (546) +#define WM_MDICASCADE (551) +#define WM_MDICREATE (544) +#define WM_MDIDESTROY (545) +#define WM_MDIGETACTIVE (553) +#define WM_MDIICONARRANGE (552) +#define WM_MDIMAXIMIZE (549) +#define WM_MDINEXT (548) +#define WM_MDIREFRESHMENU (564) +#define WM_MDIRESTORE (547) +#define WM_MDISETMENU (560) +#define WM_MDITILE (550) +#define WM_MEASUREITEM (44) +#define WM_MENUCHAR (288) +#define WM_MENUSELECT (287) +#define WM_MOUSEACTIVATE (33) +#define WM_MOUSEMOVE (512) +#define WM_MOUSEWHEEL (522) +#define WM_MOVE (3) +#define WM_MOVING (534) +#define WM_NCACTIVATE (134) +#define WM_NCCALCSIZE (131) +#define WM_NCCREATE (129) +#define WM_NCDESTROY (130) +#define WM_NCHITTEST (132) +#define WM_NCLBUTTONDBLCLK (163) +#define WM_NCLBUTTONDOWN (161) +#define WM_NCLBUTTONUP (162) +#define WM_NCMBUTTONDBLCLK (169) +#define WM_NCMBUTTONDOWN (167) +#define WM_NCMBUTTONUP (168) +#define WM_NCMOUSEMOVE (160) +#define WM_NCPAINT (133) +#define WM_NCRBUTTONDBLCLK (166) +#define WM_NCRBUTTONDOWN (164) +#define WM_NCRBUTTONUP (165) +#define WM_NEXTDLGCTL (40) +#define WM_NOTIFY (78) +#define WM_NOTIFYFORMAT (85) +#define WM_NULL (0) +#define WM_PAINT (15) +#define WM_PAINTCLIPBOARD (777) +#define WM_PAINTICON (38) +#define WM_PALETTECHANGED (785) +#define WM_PALETTEISCHANGING (784) +#define WM_PARENTNOTIFY (528) +#define WM_PASTE (770) +#define WM_PENWINFIRST (896) +#define WM_PENWINLAST (911) +#define WM_POWER (72) +#define WM_POWERBROADCAST (536) +#define WM_PRINT (791) +#define WM_PRINTCLIENT (792) +#define WM_PSD_ENVSTAMPRECT (1029) +#define WM_PSD_FULLPAGERECT (1025) +#define WM_PSD_GREEKTEXTRECT (1028) +#define WM_PSD_MARGINRECT (1027) +#define WM_PSD_MINMARGINRECT (1026) +#define WM_PSD_PAGESETUPDLG (1024) +#define WM_PSD_YAFULLPAGERECT (1030) +#define WM_QUERYDRAGICON (55) +#define WM_QUERYDROPOBJECT (555) +#define WM_QUERYENDSESSION (17) +#define WM_QUERYNEWPALETTE (783) +#define WM_QUERYOPEN (19) +#define WM_QUEUESYNC (35) +#define WM_QUIT (18) +#define WM_RBUTTONDBLCLK (518) +#define WM_RBUTTONDOWN (516) +#define WM_RBUTTONUP (517) +#define WM_RENDERALLFORMATS (774) +#define WM_RENDERFORMAT (773) +#define WM_SETCURSOR (32) +#define WM_SETFOCUS (7) +#define WM_SETFONT (48) +#define WM_SETHOTKEY (50) +#define WM_SETICON (128) +#define WM_SETREDRAW (11) +#define WM_SETTEXT (12) +#define WM_SETTINGCHANGE (26) +#define WM_SHOWWINDOW (24) +#define WM_SIZE (5) +#define WM_SIZECLIPBOARD (779) +#define WM_SIZING (532) +#define WM_SPOOLERSTATUS (42) +#define WM_STYLECHANGED (125) +#define WM_STYLECHANGING (124) +#define WM_SYNCPAINT (136) +#define WM_SYSCHAR (262) +#define WM_SYSCOLORCHANGE (21) +#define WM_SYSCOMMAND (274) +#define WM_SYSDEADCHAR (263) +#define WM_SYSKEYDOWN (260) +#define WM_SYSKEYUP (261) +#define WM_TCARD (82) +#define WM_TIMECHANGE (30) +#define WM_TIMER (275) +#define WM_UNDO (772) +#define WM_USER (1024) +#define WM_USERCHANGED (84) +#define WM_VKEYTOITEM (46) +#define WM_VSCROLL (277) +#define WM_VSCROLLCLIPBOARD (778) +#define WM_WINDOWPOSCHANGED (71) +#define WM_WINDOWPOSCHANGING (70) +#define WM_WININICHANGE (26) + +/* Window message ranges */ +#define WM_KEYFIRST (256) +#define WM_KEYLAST (264) +#define WM_MOUSEFIRST (512) +#define WM_MOUSELAST (521) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GNU_H_WINDOWS32_MESSAGES */ diff --git a/include/msvcrt/alloc.h b/include/msvcrt/alloc.h new file mode 100644 index 0000000..3a97961 --- /dev/null +++ b/include/msvcrt/alloc.h @@ -0,0 +1,85 @@ +/* + * alloc.h + * + * Memory management functions. Because most of these functions are + * actually declared in stdlib.h I have decided to simply include that + * header file. This file is included by malloc.h. My head hurts... + * + * NOTE: In the version of the Standard C++ Library from Cygnus there + * is also an alloc.h which needs to be on your include path. Most of + * the time I think the most sensible option would be to get rid of + * this file. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _ALLOC_H_ +#define _ALLOC_H_ + +#include + +#ifndef RC_INVOKED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The structure used to walk through the heap with _heapwalk. + * TODO: This is a guess at the internals of this structure. + */ +typedef struct _heapinfo +{ + void* ptr; + unsigned int size; + int in_use; +} _HEAPINFO; + +int _heapwalk (_HEAPINFO* pHeapinfo); + +#ifdef __GNUC__ +#ifdef USE_C_ALLOCA +void * C_alloca(size_t size); +#define _alloca(x) C_alloca(x) +#else /* USE_C_ALLOCA */ +#define _alloca(x) __builtin_alloca(x) +#endif /* USE_C_ALLOCA */ +#else /* __GNUC__ */ +void * _alloca(size_t size); +#endif /* __GNUC__ */ + +#ifndef _NO_OLDNAMES +#define heapwalk(x) _heapwalk(x) +#define alloca(s) _alloca(s) +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* Not _ALLOC_H_ */ + +#endif /* Not __STRICT_ANSI__ */ + diff --git a/include/msvcrt/assert.h b/include/msvcrt/assert.h new file mode 100644 index 0000000..8d85fcf --- /dev/null +++ b/include/msvcrt/assert.h @@ -0,0 +1,69 @@ +/* + * assert.h + * + * Define the assert macro for debug output. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NDEBUG + +/* + * If not debugging, assert does nothing. + */ +#define assert(x) ((void)0); + +#else /* debugging enabled */ + +/* + * CRTDLL nicely supplies a function which does the actual output and + * call to abort. + */ +#ifndef __ATTRIB_NORETURN +#ifdef __GNUC__ +#define _ATTRIB_NORETURN __attribute__ ((noreturn)) +#else /* Not __GNUC__ */ +#define _ATTRIB_NORETURN +#endif /* __GNUC__ */ +#endif + +void _assert (const char* szExpression, const char* szFileName, int nLine) +_ATTRIB_NORETURN +; + +/* + * Definition of the assert macro. + */ +#define assert(x) if(!(x)) _assert( #x , __FILE__, __LINE__); +#endif /* NDEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/msvcrt/conio.h b/include/msvcrt/conio.h new file mode 100644 index 0000000..db012be --- /dev/null +++ b/include/msvcrt/conio.h @@ -0,0 +1,67 @@ +/* + * conio.h + * + * Low level console I/O functions. Pretty please try to use the ANSI + * standard ones if you are writing new code. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _CONIO_H_ +#define _CONIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +char* _cgets (char* szBuffer); +int _cprintf (const char* szFormat, ...); +int _cputs (const char* szString); +int _cscanf (char* szFormat, ...); + +int _getch (void); +int _getche (void); +int _kbhit (void); +int _putch (int cPut); +int _ungetch (int cUnget); + + +#ifndef _NO_OLDNAMES + +#define getch _getch +#define getche _getche +#define kbhit _kbhit +#define putch(cPut) _putch(cPut) +#define ungetch(cUnget) _ungetch(cUnget) + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _CONIO_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/ctype.h b/include/msvcrt/ctype.h new file mode 100644 index 0000000..c610ba9 --- /dev/null +++ b/include/msvcrt/ctype.h @@ -0,0 +1,139 @@ +/* + * ctype.h + * + * Functions for testing character types and converting characters. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _CTYPE_H_ +#define _CTYPE_H_ + +#define __need_wchar_t +#define __need_wint_t +#include + + +/* + * The following flags are used to tell iswctype and _isctype what character + * types you are looking for. + */ +#define _UPPER 0x0001 +#define _LOWER 0x0002 +#define _DIGIT 0x0004 +#define _SPACE 0x0008 +#define _PUNCT 0x0010 +#define _CONTROL 0x0020 +#define _BLANK 0x0040 +#define _HEX 0x0080 + +#define _ALPHA 0x0103 +#define _LEADBYTE 0x8000 + + +#ifdef __cplusplus +extern "C" { +#endif + +int isalnum(int c); +int isalpha(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); + +#ifndef __STRICT_ANSI__ +int _isctype (unsigned int c, int ctypeFlags); +#endif + +int tolower(int c); +int toupper(int c); + +/* + * NOTE: The above are not old name type wrappers, but functions exported + * explicitly by MSVCRT. However, underscored versions are also exported. + */ +#ifndef __STRICT_ANSI__ +int _tolower(int c); +int _toupper(int c); +#endif + +#ifndef WEOF +#define WEOF (wchar_t)(0xFFFF) +#endif + +/* + * TODO: MB_CUR_MAX should be defined here (if not already defined, since + * it should also be defined in stdlib.h). It is supposed to be the + * maximum number of bytes in a multi-byte character in the current + * locale. Perhaps accessible through the __mb_curr_max_dll entry point, + * but I think (again) that that is a variable pointer, which leads to + * problems under the current Cygwin compiler distribution. + */ + +typedef int wctype_t; + +/* Wide character equivalents */ +int iswalnum(wint_t wc); +int iswalpha(wint_t wc); +int iswascii(wint_t wc); +int iswcntrl(wint_t wc); +int iswctype(wint_t wc, wctype_t wctypeFlags); +int is_wctype(wint_t wc, wctype_t wctypeFlags); /* Obsolete! */ +int iswdigit(wint_t wc); +int iswgraph(wint_t wc); +int iswlower(wint_t wc); +int iswprint(wint_t wc); +int iswpunct(wint_t wc); +int iswspace(wint_t wc); +int iswupper(wint_t wc); +int iswxdigit(wint_t wc); + +wchar_t towlower(wchar_t c); +wchar_t towupper(wchar_t c); + +int isleadbyte (int c); + +#ifndef __STRICT_ANSI__ +int __isascii (int c); +int __toascii (int c); +int __iscsymf (int c); /* Valid first character in C symbol */ +int __iscsym (int c); /* Valid character in C symbol (after first) */ + +#ifndef _NO_OLDNAMES +#define isascii(c) __isascii(c) +#define toascii(c) _toascii(c) +#define iscsymf(c) __iscsymf(c) +#define iscsym(c) __iscsym(c) +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not _CTYPE_H_ */ diff --git a/include/msvcrt/dir.h b/include/msvcrt/dir.h new file mode 100644 index 0000000..97e52d2 --- /dev/null +++ b/include/msvcrt/dir.h @@ -0,0 +1,148 @@ +/* + * dir.h + * + * Functions for working with directories and path names. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _DIR_H_ +#define _DIR_H_ + +#include /* To get FILENAME_MAX... ugly. */ +#include /* To get time_t. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Attributes of files as returned by _findfirst et al. + */ +#define _A_NORMAL 0x00000000 +#define _A_RDONLY 0x00000001 +#define _A_HIDDEN 0x00000002 +#define _A_SYSTEM 0x00000004 +#define _A_VOLID 0x00000008 +#define _A_SUBDIR 0x00000010 +#define _A_ARCH 0x00000020 + +#ifndef _FSIZE_T_DEFINED +typedef unsigned long _fsize_t; +#define _FSIZE_T_DEFINED +#endif + +/* + * The following structures are filled in by _findfirst or _findnext when + * they succeed in finding a match. + */ +struct _finddata_t +{ + unsigned attrib; /* Attributes, see constants above. */ + time_t time_create; + time_t time_access; /* always midnight local time */ + time_t time_write; + _fsize_t size; + char name[FILENAME_MAX]; /* may include spaces. */ +}; + +struct _finddatai64_t +{ + unsigned attrib; /* Attributes, see constants above. */ + time_t time_create; + time_t time_access; /* always midnight local time */ + time_t time_write; + __int64 size; + char name[FILENAME_MAX]; /* may include spaces. */ +}; + +struct _wfinddata_t +{ + unsigned attrib; /* Attributes, see constants above. */ + time_t time_create; + time_t time_access; /* always midnight local time */ + time_t time_write; + _fsize_t size; + wchar_t name[FILENAME_MAX]; /* may include spaces. */ +}; + +struct _wfinddatai64_t +{ + unsigned attrib; /* Attributes, see constants above. */ + time_t time_create; + time_t time_access; /* always midnight local time */ + time_t time_write; + __int64 size; + wchar_t name[FILENAME_MAX]; /* may include spaces. */ +}; + +/* + * Functions for searching for files. _findfirst returns -1 if no match + * is found. Otherwise it returns a handle to be used in _findnext and + * _findclose calls. _findnext also returns -1 if no match could be found, + * and 0 if a match was found. Call _findclose when you are finished. + */ +int _findclose (int nHandle); +int _findfirst (const char* szFilespec, struct _finddata_t* find); +int _findfirsti64 (const char* szFilespec, struct _finddatai64_t* find); +int _findnext (int nHandle, struct _finddata_t* find); +int _findnexti64 (int nHandle, struct _finddatai64_t* find); + +int _chdir (const char* szPath); +char* _getcwd (char* caBuffer, int nBufferSize); +int _mkdir (const char* szPath); +char* _mktemp (char* szTemplate); +int _rmdir (const char* szPath); + + +/* Wide character versions */ +int _wfindfirst(const wchar_t *_name, struct _wfinddata_t *result); +int _wfindfirsti64(const wchar_t *_name, struct _wfinddatai64_t *result); +int _wfindnext(int handle, struct _wfinddata_t *result); +int _wfindnexti64(int handle, struct _wfinddatai64_t *result); + +int _wchdir(const wchar_t *szPath); +wchar_t* _wgetcwd(wchar_t *buffer, int maxlen); +int _wmkdir(const wchar_t *_path); +wchar_t* _wmktemp (wchar_t *_template); +int _wrmdir(const wchar_t *_path); + + +#ifndef _NO_OLDNAMES + +int chdir (const char* szPath); +char* getcwd (char* caBuffer, int nBufferSize); +int mkdir (const char* szPath); +char* mktemp (char* szTemplate); +int rmdir (const char* szPath); + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _DIR_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/direct.h b/include/msvcrt/direct.h new file mode 100644 index 0000000..e1849ec --- /dev/null +++ b/include/msvcrt/direct.h @@ -0,0 +1,46 @@ +#ifndef _DIRECT_H_ +#define _DIRECT_H_ + +#ifndef _WCHAR_T_ +typedef unsigned short wchar_t; +#define _WCHAR_T_ +#endif + +#ifndef _SIZE_T_ +typedef unsigned int size_t; +#define _SIZE_T_ +#endif + +struct _diskfree_t { + unsigned short total_clusters; + unsigned short avail_clusters; + unsigned short sectors_per_cluster; + unsigned short bytes_per_sector; +}; + +unsigned int _getdiskfree(unsigned int _drive, struct _diskfree_t *_diskspace); + +int _chdrive( int drive ); +int _getdrive( void ); + +char *_getcwd( char *buffer, int maxlen ); +char *_getdcwd (int nDrive, char* caBuffer, int nBufLen); + +int _chdir(const char *_path); +int _mkdir(const char *_path); +int _rmdir(const char *_path); + +#define chdir _chdir +#define getcwd _getcwd +#define mkdir _mkdir +#define rmdir _rmdir + + +wchar_t *_wgetcwd( wchar_t *buffer, int maxlen ); +wchar_t *_wgetdcwd (int nDrive, wchar_t* caBuffer, int nBufLen); + +int _wchdir(const wchar_t *_path); +int _wmkdir(const wchar_t *_path); +int _wrmdir(const wchar_t *_path); + +#endif diff --git a/include/msvcrt/errno.h b/include/msvcrt/errno.h new file mode 100644 index 0000000..9fae110 --- /dev/null +++ b/include/msvcrt/errno.h @@ -0,0 +1,120 @@ +/* + * errno.h + * + * Error numbers and access to error reporting. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Error numbers. + * TODO: Can't be sure of some of these assignments, I guessed from the + * names given by strerror and the defines in the Cygnus errno.h. A lot + * of the names from the Cygnus errno.h are not represented, and a few + * of the descriptions returned by strerror do not obviously match + * their error naming. + */ +#define EPERM 1 /* Operation not permitted */ +#define ENOFILE 2 /* No such file or directory */ +#define ENOENT 2 +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted function call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Resource temporarily unavailable */ +#define ENOMEM 12 /* Not enough space */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +/* 15 - Unknown Error */ +#define EBUSY 16 /* strerror reports "Resource device" */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Improper link (cross-device link?) */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate I/O control operation */ +/* 26 - Unknown Error */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Invalid seek (seek on a pipe?) */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Domain error (math functions) */ +#define ERANGE 34 /* Result too large (possibly too small) */ +/* 35 - Unknown Error */ +#define EDEADLOCK 36 /* Resource deadlock avoided (non-Cyg) */ +#define EDEADLK 36 +/* 37 - Unknown Error */ +#define ENAMETOOLONG 38 /* Filename too long (91 in Cyg?) */ +#define ENOLCK 39 /* No locks available (46 in Cyg?) */ +#define ENOSYS 40 /* Function not implemented (88 in Cyg?) */ +#define ENOTEMPTY 41 /* Directory not empty (90 in Cyg?) */ +#define EILSEQ 42 /* Illegal byte sequence */ + +/* + * NOTE: ENAMETOOLONG and ENOTEMPTY conflict with definitions in the + * sockets.h header provided with windows32api-0.1.2. + * You should go and put an #if 0 ... #endif around the whole block + * of errors (look at the comment above them). + */ + +/* + * Definitions of macros for the 'variables' errno, _doserrno, sys_nerr and + * sys_errlist. + */ +int* _errno(void); +#define errno (*_errno()) + +int* __doserrno(void); +#define _doserrno (*__doserrno()) + +/* One of the MSVCRTxx libraries */ + +extern int* __imp__sys_nerr; +#ifndef sys_nerr +#define sys_nerr (*__imp__sys_nerr) +#endif + +extern char** __imp__sys_errlist; +#ifndef sys_errlist +#define sys_errlist (__imp__sys_errlist) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/msvcrt/fcntl.h b/include/msvcrt/fcntl.h new file mode 100644 index 0000000..8e7491c --- /dev/null +++ b/include/msvcrt/fcntl.h @@ -0,0 +1,127 @@ +/* + * fcntl.h + * + * Access constants for _open. Note that the permissions constants are + * in sys/stat.h (ick). + * + * This code is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* added _O_RANDOM_O_SEQUENTIAL _O_SHORT_LIVED*/ +/* changed fmode_dll */ + +#ifndef _FCNTL_H_ +#define _FCNTL_H_ + +/* + * It appears that fcntl.h should include io.h for compatibility... + */ +#include + +/* + * This variable determines the default file mode. + * TODO: Which flags work? + */ +#if 0 +#if __MSVCRT__ +extern unsigned int* __imp__fmode; +#define _fmode (*__imp__fmode) +#else +/* CRTDLL */ +extern unsigned int* _fmode_dll; +#define _fmode (*_fmode_dll) +#endif +#endif /* 0 */ + +/* + * NOTE: This is the correct definition to build crtdll. + * It is NOT valid outside of crtdll. + */ +extern unsigned int* _fmode_dll; +extern unsigned int _fmode; + + +/* Specifiy one of these flags to define the access mode. */ +#define _O_RDONLY 0 +#define _O_WRONLY 1 +#define _O_RDWR 2 + +/* Mask for access mode bits in the _open flags. */ +#define _O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) + +#define _O_APPEND 0x0008 /* Writes will add to the end of the file. */ +#define _O_CREAT 0x0100 /* Create the file if it does not exist. */ +#define _O_TRUNC 0x0200 /* Truncate the file if it does exist. */ +#define _O_EXCL 0x0400 /* Open only if the file does not exist. */ + +/* NOTE: Text is the default even if the given _O_TEXT bit is not on. */ +#define _O_TEXT 0x4000 /* CR-LF in file becomes LF in memory. */ +#define _O_BINARY 0x8000 /* Input and output is not translated. */ +#define _O_RAW _O_BINARY + +#define _O_TEMPORARY 0x0040 /* Make the file dissappear after closing. + * WARNING: Even if not created by _open! */ +#define _O_NOINHERIT 0x0080 + + +#define _O_RANDOM 0x0010 +#define _O_SEQUENTIAL _O_RANDOM +#define _O_SHORT_LIVED 0x1000 + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +/* POSIX/Non-ANSI names for increased portability */ +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_RDWR _O_RDWR +#define O_ACCMODE _O_ACCMODE +#define O_APPEND _O_APPEND +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC +#define O_EXCL _O_EXCL +#define O_TEXT _O_TEXT +#define O_BINARY _O_BINARY +#define O_TEMPORARY _O_TEMPORARY +#define O_NOINHERIT _O_NOINHERIT + +#define O_RANDOM _O_RANDOM +#define O_SEQUENTIAL _O_RANDOM +#define O_SHORT_LIVED _O_SHORT_LIVED + +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +extern "C" { +#endif + +int _setmode (int nHandle, int nAccessMode); + +#ifndef _NO_OLDNAMES +int setmode (int nHandle, int nAccessMode); +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not __STRICT_ANSI__ */ +#endif /* Not _FCNTL_H_ */ diff --git a/include/msvcrt/float.h b/include/msvcrt/float.h new file mode 100644 index 0000000..4c4304a --- /dev/null +++ b/include/msvcrt/float.h @@ -0,0 +1,199 @@ +/* + * float.h + * + * Constants related to floating point arithmetic. + * + * Also included here are some non-ANSI bits for accessing the floating + * point controller. + * + * NOTE: GCC provides float.h, and it is probably more accurate than this, + * but it doesn't include the non-standard stuff for accessing the + * fp controller. (TODO: Move those bits elsewhere?) Thus it is + * probably not a good idea to use the GCC supplied version instead + * of this header. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _FLOAT_H_ +#define _FLOAT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define FLT_ROUNDS 1 +#define FLT_GUARD 1 +#define FLT_NORMALIZE 1 + +/* + * The characteristics of float. + */ + +/* The radix for floating point representation. */ +#define FLT_RADIX 2 + +/* Decimal digits of precision. */ +#define FLT_DIG 6 + +/* Smallest number such that 1+x != 1 */ +#define FLT_EPSILON 1.19209290e-07F + +/* The number of base FLT_RADIX digits in the mantissa. */ +#define FLT_MANT_DIG 24 + +/* The maximum floating point number. */ +#define FLT_MAX 3.40282347e+38F + +/* Maximum n such that FLT_RADIX^n - 1 is representable. */ +#define FLT_MAX_EXP 128 + +/* Maximum n such that 10^n is representable. */ +#define FLT_MAX_10_EXP 38 + +/* Minimum normalized floating-point number. */ +#define FLT_MIN 1.17549435e-38F + +/* Minimum n such that FLT_RADIX^n is a normalized number. */ +#define FLT_MIN_EXP (-125) + +/* Minimum n such that 10^n is a normalized number. */ +#define FLT_MIN_10_EXP (-37) + + +/* + * The characteristics of double. + */ +#define DBL_DIG 15 +#define DBL_EPSILON 1.1102230246251568e-16 +#define DBL_MANT_DIG 53 +#define DBL_MAX 1.7976931348623157e+308 +#define DBL_MAX_EXP 1024 +#define DBL_MAX_10_EXP 308 +#define DBL_MIN 2.2250738585072014e-308 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN_10_EXP (-307) + + +/* + * The characteristics of long double. + * NOTE: long double is the same as double. + */ +#define LDBL_DIG 15 +#define LDBL_EPSILON 1.1102230246251568e-16L +#define LDBL_MANT_DIG 53 +#define LDBL_MAX 1.7976931348623157e+308L +#define LDBL_MAX_EXP 1024 +#define LDBL_MAX_10_EXP 308 +#define LDBL_MIN 2.2250738585072014e-308L +#define LDBL_MIN_EXP (-1021) +#define LDBL_MIN_10_EXP (-307) + + +/* + * Functions and definitions for controlling the FPU. + */ +#ifndef __STRICT_ANSI__ + +/* TODO: These constants are only valid for x86 machines */ + +/* Control word masks for unMask */ +#define _MCW_EM 0x0008001F /* Error masks */ +#define _MCW_IC 0x00040000 /* Infinity */ +#define _MCW_RC 0x00000300 /* Rounding */ +#define _MCW_PC 0x00030000 /* Precision */ + +/* Control word values for unNew (use with related unMask above) */ +#define _EM_INVALID 0x00000010 +#define _EM_DENORMAL 0x00080000 +#define _EM_ZERODIVIDE 0x00000008 +#define _EM_OVERFLOW 0x00000004 +#define _EM_UNDERFLOW 0x00000002 +#define _EM_INEXACT 0x00000001 +#define _IC_AFFINE 0x00040000 +#define _IC_PROJECTIVE 0x00000000 +#define _RC_CHOP 0x00000300 +#define _RC_UP 0x00000200 +#define _RC_DOWN 0x00000100 +#define _RC_NEAR 0x00000000 +#define _PC_24 0x00020000 +#define _PC_53 0x00010000 +#define _PC_64 0x00000000 + + +/* Set the FPU control word as cw = (cw & ~unMask) | (unNew & unMask), + * i.e. change the bits in unMask to have the values they have in unNew, + * leaving other bits unchanged. */ +unsigned int _controlfp (unsigned int unNew, unsigned int unMask); +unsigned int _control87 (unsigned int unNew, unsigned int unMask); + + +unsigned int _clearfp (void); /* Clear the FPU status word */ +unsigned int _statusfp (void); /* Report the FPU status word */ +#define _clear87 _clearfp +#define _status87 _statusfp + +void _fpreset (void); /* Reset the FPU */ + +/* Global 'variable' for the current floating point error code. */ +extern int * __fpecode(void); +#define _fpecode (*(__fpecode())) + +/* + * IEEE recommended functions + */ + +double _chgsign (double x); +double _copysign (double dTo, double dFrom); +double _logb (double x); +double _nextafter (double x, double y); +double _scalb (double x, long n); + +/* Return values for fpclass. */ +#define _FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */ +#define _FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */ +#define _FPCLASS_NINF 0x0004 /* Negative Infinity */ +#define _FPCLASS_NN 0x0008 /* Negative Normal */ +#define _FPCLASS_ND 0x0010 /* Negative Denormal */ +#define _FPCLASS_NZ 0x0020 /* Negative Zero */ +#define _FPCLASS_PZ 0x0040 /* Positive Zero */ +#define _FPCLASS_PD 0x0080 /* Positive Denormal */ +#define _FPCLASS_PN 0x0100 /* Positive Normal */ +#define _FPCLASS_PINF 0x0200 /* Positive Infinity */ + +int _finite (double x); +int _fpclass (double x); +int _isnan (double x); +int _isinf (double x); // not exported + +int _isnanl (long double x); // not exported +int _isinfl (long double x); // not exported + +#define isnan(x) _isnan(x) +#define isinf(x) _isinf(x) + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _FLOAT_H_ */ diff --git a/include/msvcrt/internal/atexit.h b/include/msvcrt/internal/atexit.h new file mode 100644 index 0000000..b3a9f01 --- /dev/null +++ b/include/msvcrt/internal/atexit.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_atexit_h__ +#define __dj_include_libc_dosexec_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +struct __atexit { + struct __atexit *__next; + void (*__function)(void); +}; + +extern struct __atexit *__atexit_ptr; + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_dosexec_h__ */ diff --git a/include/msvcrt/internal/console.h b/include/msvcrt/internal/console.h new file mode 100644 index 0000000..6855779 --- /dev/null +++ b/include/msvcrt/internal/console.h @@ -0,0 +1,12 @@ +/* console.h */ + +#ifndef __MSVCRT_INTERNAL_CONSOLE_H +#define __MSVCRT_INTERNAL_CONSOLE_H + +extern int char_avail; +extern int ungot_char; + +#endif /* __MSVCRT_INTERNAL_CONSOLE_H */ + +/* EOF */ + diff --git a/include/msvcrt/internal/file.h b/include/msvcrt/internal/file.h new file mode 100644 index 0000000..cb17b08 --- /dev/null +++ b/include/msvcrt/internal/file.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#ifndef __dj_include_libc_file_h__ +#define __dj_include_libc_file_h__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +#ifndef _IORMONCL +#define _IORMONCL 004000 /* remove on close, for temp files */ +#endif +/* if _flag & _IORMONCL, ._name_to_remove needs freeing */ + +#ifndef _IOUNGETC +#define _IOUNGETC 010000 /* there is an ungetc'ed character in the buffer */ +#endif + + +// might need check for IO_APPEND aswell +#define OPEN4WRITING(f) ((((f)->_flag & _IOWRT) == _IOWRT ) ) + +#define OPEN4READING(f) ((((f)->_flag & _IOREAD) == _IOREAD ) ) + +// might need check for IO_APPEND aswell +#define WRITE_STREAM(f) ((((f)->_flag & _IOWRT) == _IOWRT ) ) + +#define READ_STREAM(f) ((((f)->_flag & _IOREAD) == _IOREAD ) ) + + +char __validfp (FILE *f); + +int __set_errno(int err); +int __set_doserrno (int error); + +void *filehnd(int fn); + +char __is_text_file(FILE *p); + +int __fileno_alloc(void *hFile, int mode); + +int _doprnt(const char *fmt, va_list args, FILE *f); +int _doscan(FILE *iop, const char *fmt, va_list argp); + + +int __fileno_dup2( int handle1, int handle2 ); +int __fileno_getmode(int _fd); +int __fileno_setmode(int _fd, int _newmode); +int __fileno_close(int _fd); + +void sigabort_handler(int sig); + +#include + +void UnixTimeToFileTime( time_t unix_time, FILETIME *filetime, DWORD remainder ); +time_t FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ); + + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + + +#define __FILE_REC_MAX 20 +typedef struct __file_rec +{ + struct __file_rec *next; + int count; + FILE *files[__FILE_REC_MAX]; +} __file_rec; + +extern __file_rec *__file_rec_list; + + +#ifdef __cplusplus +} +#endif + + +#endif /* __dj_include_libc_file_h__ */ + + + diff --git a/include/msvcrt/internal/ieee.h b/include/msvcrt/internal/ieee.h new file mode 100644 index 0000000..788908b --- /dev/null +++ b/include/msvcrt/internal/ieee.h @@ -0,0 +1,25 @@ +#ifndef _IEEE_H +#define _IEEE_H + +typedef struct { + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int sign:1; +} float_t; + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; +} double_t; + +typedef struct { + unsigned int mantissal:32; + unsigned int mantissah:32; + unsigned int exponent:15; + unsigned int sign:1; + unsigned int empty:16; +} long_double_t; + +#endif diff --git a/include/msvcrt/internal/rterror.h b/include/msvcrt/internal/rterror.h new file mode 100644 index 0000000..6979abe --- /dev/null +++ b/include/msvcrt/internal/rterror.h @@ -0,0 +1,29 @@ +/* rterror.h */ + +#ifndef __MSVCRT_INTERNAL_RTERROR_H +#define __MSVCRT_INTERNAL_RTERROR_H + +#define _RT_STACK 0 /* stack overflow */ +#define _RT_NULLPTR 1 /* null pointer assignment */ +#define _RT_FLOAT 2 /* floating point not loaded */ +#define _RT_INTDIV 3 /* integer divide by 0 */ +#define _RT_SPACEARG 4 /* not enough space for arguments */ +#define _RT_SPACEENV 5 /* not enough space for environment */ +#define _RT_ABORT 6 /* abnormal program termination */ +#define _RT_THREAD 7 /* not enough space for thread data */ +#define _RT_LOCK 8 /* unexpected multi-thread lock error */ +#define _RT_HEAP 9 /* unexpected heap error */ +#define _RT_OPENCON 10 /* unable to open console device */ +#define _RT_NONCONT 11 /* non-continuable exception */ +#define _RT_INVALDISP 12 /* invalid disposition of exception */ +#define _RT_ONEXIT 13 /* insufficient heap to allocate + * initial table of function pointers + * used by _onexit()/atexit(). */ +#define _RT_PUREVIRT 14 /* pure virtual function call attempted + * (C++ error) */ +#define _RT_STDIOINIT 15 /* not enough space for stdio initialization */ +#define _RT_LOWIOINIT 16 /* not enough space for lowio initialization */ + +void _amsg_exit (int errnum); + +#endif /* __MSVCRT_INTERNAL_RTERROR_H */ diff --git a/include/msvcrt/internal/stdio.h b/include/msvcrt/internal/stdio.h new file mode 100644 index 0000000..b272136 --- /dev/null +++ b/include/msvcrt/internal/stdio.h @@ -0,0 +1,12 @@ +/* stdio.h */ + +#ifndef __MSVCRT_INTERNAL_STDIO_H +#define __MSVCRT_INTERNAL_STDIO_H + +int __vfscanf (FILE *s, const char *format, va_list argptr); +int __vscanf (const char *format, va_list arg); +int __vsscanf (const char *s,const char *format,va_list arg); + +#endif /* __MSVCRT_INTERNAL_STDIO_H */ + +/* EOF */ diff --git a/include/msvcrt/internal/tls.h b/include/msvcrt/internal/tls.h new file mode 100644 index 0000000..bbc21e9 --- /dev/null +++ b/include/msvcrt/internal/tls.h @@ -0,0 +1,38 @@ +/* tls.h */ + +#ifndef __MSVCRT_INTERNAL_TLS_H +#define __MSVCRT_INTERNAL_TLS_H + +#include + +typedef struct _ThreadData +{ + int terrno; /* *nix error code */ + unsigned long tdoserrno; /* Win32 error code (for I/O only) */ + unsigned long long tnext; /* used by rand/srand */ + + char *lasttoken; /* used by strtok */ + wchar_t *wlasttoken; /* used by wcstok */ + + + int fpecode; /* fp exception code */ + + /* qsort variables */ + int (*qcmp)(const void *, const void *); /* the comparison routine */ + int qsz; /* size of each record */ + int thresh; /* THRESHold in chars */ + int mthresh; /* MTHRESHold in chars */ + +} THREADDATA, *PTHREADDATA; + + +int CreateThreadData(void); +void DestroyThreadData(void); + +void FreeThreadData(PTHREADDATA ptd); +PTHREADDATA GetThreadData(void); + +#endif /* __MSVCRT_INTERNAL_TLS_H */ + +/* EOF */ + diff --git a/include/msvcrt/io.h b/include/msvcrt/io.h new file mode 100644 index 0000000..d91817e --- /dev/null +++ b/include/msvcrt/io.h @@ -0,0 +1,155 @@ +/* + * io.h + * + * System level I/O functions and types. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* added D_OK */ +/* changed get_osfhandle and open_osfhandle */ +/* added fileno as macro */ +#ifndef _IO_H_ +#define _IO_H_ + +#ifndef __STRICT_ANSI__ + +#include + +#include + + +/* We need the definition of FILE anyway... */ +#include + +/* MSVC's io.h contains the stuff from dir.h, so I will too. + * NOTE: This also defines off_t, the file offset type, through + * and inclusion of sys/types.h */ +#include + +/* TODO: Maximum number of open handles has not been tested, I just set + * it the same as FOPEN_MAX. */ +#define HANDLE_MAX FOPEN_MAX + + +/* Some defines for _access nAccessMode (MS doesn't define them, but + * it doesn't seem to hurt to add them). */ +#define F_OK 0 /* Check for file existence */ +#define W_OK 2 /* Check for write permission */ +#define R_OK 4 /* Check for read permission */ +/* TODO: Is this safe? X_OK not supported directly... */ +#define X_OK R_OK /* Check for execute permission */ +#define D_OK 0x10 + + + +#ifdef __cplusplus +extern "C" { +#endif + +int _access (const char* szFileName, int nAccessMode); +int _chmod (const char* szPath, int nMode); +int _chsize (int nHandle, long lnNewSize); +int _close (int nHandle); +int _commit(int _fd); +int _creat (const char* szFileName, int nAccessMode); +int _dup (int nHandle); +int _dup2 (int nOldHandle, int nNewHandle); +long _filelength (int nHandle); +__int64 _filelengthi64(int nHandle); +int _fileno (FILE* fileGetHandle); +void* _get_osfhandle (int nHandle); +int _isatty (int nHandle); + +/* In a very odd turn of events this function is excluded from those + * files which define _STREAM_COMPAT. This is required in order to + * build GNU libio because of a conflict with _eof in streambuf.h + * line 107. Actually I might just be able to change the name of + * the enum member in streambuf.h... we'll see. TODO */ +#ifndef _STREAM_COMPAT +int _eof (int nHandle); +#endif + +/* LK_... locking commands defined in sys/locking.h. */ +int _locking (int nHandle, int nCmd, long lnLockRegionLength); + +off_t _lseek(int _fd, off_t _offset, int _whence); +__int64 _lseeki64(int _fildes, __int64 _offset, int _whence); +int _open (const char* szFileName, int nFlags, ...); +int _open_osfhandle (void *lnOSHandle, int nFlags); +int _pipe (int *naHandles, unsigned int unSize, int nMode); +size_t _read(int _fd, void *_buf, size_t _nbyte); + +/* SH_... flags for nFlag defined in share.h */ +int _sopen (char* szFileName, int nAccess, int nFlag, int nMode); + +long _tell(int nHandle); +__int64 _telli64(int nHandle); +unsigned _umask(unsigned unMode); +int _unlink(const char* szFileName); +size_t _write(int _fd, const void *_buf, size_t _nbyte); + + +/* wide character functions */ +int _waccess(const wchar_t *_path, int _amode); +int _wchmod(const wchar_t *filename, int mode); +int _wcreat(const wchar_t *filename, int mode); + +int _wopen(const wchar_t *_path, int _oflag,...); +int _wsopen(wchar_t *path, int access, int shflag, int mode); +int _wunlink(const wchar_t *filename); + + +#ifndef _NO_OLDNAMES +/* + * Non-underscored versions of non-ANSI functions to improve portability. + * These functions live in libmoldname.a. + */ + +#define access _access +#define chmod _chmod +#define chsize _chsize +#define close _close +#define creat _creat +#define dup _dup +#define dup2 _dup2 +#define eof _eof +#define filelength _filelength +#define fileno(f) ((f)->_file) +#define isatty _isatty +#define lseek _lseek +#define open _open +#define read _read +#define sopen(path,access,shflag,mode) _open((path), (access)|(shflag), (mode)) +#define tell(file) _lseek(_file, 0, SEEK_CUR) +#define umask _umask +#define unlink _unlink +#define write _write + +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not strict ANSI */ + +#endif /* _IO_H_ not defined */ diff --git a/include/msvcrt/locale.h b/include/msvcrt/locale.h new file mode 100644 index 0000000..8a6e7d4 --- /dev/null +++ b/include/msvcrt/locale.h @@ -0,0 +1,84 @@ +/* + * locale.h + * + * Functions and types for localization (ie. changing the appearance of + * output based on the standards of a certain country). + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _LOCALE_H_ +#define _LOCALE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NOTE: I have tried to test this, but I am limited by my knowledge of + * locale issues. The structure does not bomb if you look at the + * values, and 'decimal_point' even seems to be correct. But the + * rest of the values are, by default, not particularly useful + * (read meaningless and not related to the international settings + * of the system). + */ + +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 + +/* + * The structure returned by 'localeconv'. + */ +struct lconv +{ + char* decimal_point; + char* thousands_sep; + char* grouping; + char* int_curr_symbol; + char* currency_symbol; + char* mon_decimal_point; + char* mon_thousands_sep; + char* mon_grouping; + char* positive_sign; + char* negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; +}; + +char* setlocale (int nCategory, const char* locale); +struct lconv* localeconv (void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/msvcrt/malloc.h b/include/msvcrt/malloc.h new file mode 100644 index 0000000..b907c22 --- /dev/null +++ b/include/msvcrt/malloc.h @@ -0,0 +1,53 @@ +/* + * malloc.h + * + * Support for programs which want to use malloc.h to get memory management + * functions. Unless you absolutely need some of these functions and they are + * not in the ANSI headers you should use the ANSI standard header files + * instead. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _MALLOC_H_ +#define _MALLOC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void * _expand( void *memblock, size_t size ); +int _heapchk (void); /* Verify heap integrety. */ +int _heapmin (void); /* Return unused heap to the OS. */ +int _heapset (unsigned int unFill); +size_t _msize (void* pBlock); + +#ifdef __cplusplus +} +#endif + +#endif /* Not _MALLOC_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/math.h b/include/msvcrt/math.h new file mode 100644 index 0000000..9afe1df --- /dev/null +++ b/include/msvcrt/math.h @@ -0,0 +1,161 @@ +/* + * math.h + * + * Mathematical functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +// added modfl + +#ifndef _MATH_H_ +#define _MATH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * HUGE_VAL is returned by strtod when the value would overflow the + * representation of 'double'. There are other uses as well. + * + * __imp__HUGE is a pointer to the actual variable _HUGE in + * MSVCRT.DLL. If we used _HUGE directly we would get a pointer + * to a thunk function. + * + * NOTE: The CRTDLL version uses _HUGE_dll instead. + */ +#if __MSVCRT__ +extern double* __imp__HUGE; +#define HUGE_VAL (*__imp__HUGE) +#else +/* CRTDLL */ +extern double* _HUGE_dll; +#define HUGE_VAL (*_HUGE_dll) +#endif + + +struct _exception +{ + int type; + char *name; + double arg1; + double arg2; + double retval; +}; + +/* + * Types for the above _exception structure. + */ + +#define _DOMAIN 1 /* domain error in argument */ +#define _SING 2 /* singularity */ +#define _OVERFLOW 3 /* range overflow */ +#define _UNDERFLOW 4 /* range underflow */ +#define _TLOSS 5 /* total loss of precision */ +#define _PLOSS 6 /* partial loss of precision */ + +/* + * Exception types with non-ANSI names for compatibility. + */ + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +#define DOMAIN _DOMAIN +#define SING _SING +#define OVERFLOW _OVERFLOW +#define UNDERFLOW _UNDERFLOW +#define TLOSS _TLOSS +#define PLOSS _PLOSS + +#endif /* Not _NO_OLDNAMES */ +#endif /* Not __STRICT_ANSI__ */ + + +double sin (double x); +double cos (double x); +double tan (double x); +double sinh (double x); +double cosh (double x); +double tanh (double x); +double asin (double x); +double acos (double x); +double atan (double x); +double atan2 (double y, double x); +double exp (double x); +double log (double x); +double log10 (double x); +double pow (double x, double y); +long double powl (long double x,long double y); +double sqrt (double x); +double ceil (double x); +double floor (double x); +double fabs (double x); +double ldexp (double x, int n); +double frexp (double x, int* exp); +double modf (double x, double* ip); +long double modfl (long double x,long double* ip); +double fmod (double x, double y); + + +#ifndef __STRICT_ANSI__ + +/* Complex number (for cabs) */ +struct _complex +{ + double x; /* Real part */ + double y; /* Imaginary part */ +}; + +double _cabs (struct _complex x); +double _hypot (double x, double y); +double _j0 (double x); +double _j1 (double x); +double _jn (int n, double x); +double _y0 (double x); +double _y1 (double x); +double _yn (int n, double x); + +#ifndef _NO_OLDNAMES + +/* + * Non-underscored versions of non-ANSI functions. These reside in + * liboldnames.a. Provided for extra portability. + */ +double cabs (struct _complex x); +double hypot (double x, double y); +double j0 (double x); +double j1 (double x); +double jn (int n, double x); +double y0 (double x); +double y1 (double x); +double yn (int n, double x); + +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not _MATH_H_ */ + diff --git a/include/msvcrt/mbctype.h b/include/msvcrt/mbctype.h new file mode 100644 index 0000000..686b363 --- /dev/null +++ b/include/msvcrt/mbctype.h @@ -0,0 +1,49 @@ +#ifndef _MBCTYPE_H +#define _MBCTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#define _MS 0x01 +//#define _MP 0x02 +//#define _M1 0x04 +//#define _M2 0x08 + +#define _MBC_SINGLE 0 +#define _MBC_LEAD 1 +#define _MBC_TRAIL 2 +#define _MBC_ILLEGAL -1 + +#define _MB_CP_SBCS 0 +#define _MB_CP_OEM -2 +#define _MB_CP_ANSI -3 +#define _MB_CP_LOCALE -4 + +#define _KNJ_M ((char)0x01) /* Non-punctuation of Kana-set */ +#define _KNJ_P ((char)0x02) /* Punctuation of Kana-set */ +#define _KNJ_1 ((char)0x04) /* Legal 1st byte of double byte stream */ +#define _KNJ_2 ((char)0x08) /* Legal 2nd btye of double byte stream */ + + +#define ___ 0 +#define _1_ _KNJ_1 /* Legal 1st byte of double byte code */ +#define __2 _KNJ_2 /* Legal 2nd byte of double byte code */ +#define _M_ _KNJ_M /* Non-puntuation in Kana-set */ +#define _P_ _KNJ_P /* Punctuation of Kana-set */ +#define _12 (_1_|__2) +#define _M2 (_M_|__2) +#define _P2 (_P_|__2) + +extern char _jctype[257]; + + +int _ismbbkalnum( unsigned int c ); +int _ismbbkana( unsigned char c ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/msvcrt/mbstring.h b/include/msvcrt/mbstring.h new file mode 100644 index 0000000..a7bc5ba --- /dev/null +++ b/include/msvcrt/mbstring.h @@ -0,0 +1,108 @@ +#ifndef _MBSTRING_H_ +#define _MBSTRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +size_t _mbstrlen(const char *str); + + + + +int _mbbtype(unsigned char c, int type); +int _mbsbtype( const unsigned char *str, size_t n ); + +unsigned int _mbbtombc(unsigned int c); +unsigned int _mbctombb(unsigned int c); + +unsigned char * _mbscat(unsigned char *dst, const unsigned char *src); +unsigned char * _mbschr(unsigned char *str, unsigned char* c); +int _mbscmp(const unsigned char *, const unsigned char *); +int _mbscoll(const unsigned char *, const unsigned char *); +unsigned char * _mbscpy(unsigned char *, const unsigned char *); +size_t _mbscspn(const unsigned char *, const unsigned char *); +unsigned char * _mbsdup(const unsigned char *str); +int _mbsicmp(const unsigned char *, const unsigned char *); +int _mbsicoll(const unsigned char *, const unsigned char *); +size_t _mbslen(const unsigned char *str); + +unsigned char * _mbsncat(unsigned char *, const unsigned char *, size_t); +unsigned char * _mbsnbcat(unsigned char *, const unsigned char *, size_t); + + +int _mbsncmp(const unsigned char *, const unsigned char *, size_t); +int _mbsnbcmp(const unsigned char *, const unsigned char *, size_t); + +int _mbsncoll(const unsigned char *, const unsigned char *, size_t); +int _mbsnbcoll(const unsigned char *, const unsigned char *, size_t); + + +unsigned char * _mbsncpy(unsigned char *, const unsigned char *, size_t); +unsigned char * _mbsnbcpy(unsigned char *, const unsigned char *, size_t); + +int _mbsnicmp(const unsigned char *, const unsigned char *, size_t); +int _mbsnbicmp(const unsigned char *, const unsigned char *, size_t); + +int _mbsnicoll(const unsigned char *, const unsigned char *, size_t); +int _mbsnbicoll(const unsigned char *, const unsigned char *, size_t); + +unsigned char * _mbsnset(unsigned char *, unsigned int, size_t); +unsigned char * _mbsnbset(unsigned char *, unsigned int, size_t); + +size_t _mbsnccnt(const unsigned char *, size_t); + + +unsigned char * _mbspbrk(const unsigned char *, const unsigned char *); +unsigned char * _mbsrchr(const unsigned char *, unsigned int); +unsigned char * _mbsrev(unsigned char *); +unsigned char * _mbsset(unsigned char *, unsigned int); +size_t _mbsspn(const unsigned char *, const unsigned char *); + +unsigned char * _mbsstr(const unsigned char *, const unsigned char *); +unsigned char * _mbstok(unsigned char *, unsigned char *); + +unsigned char * _mbslwr(unsigned char *str); +unsigned char * _mbsupr(unsigned char *str); + +size_t _mbclen(const unsigned char *); +void _mbccpy(unsigned char *, const unsigned char *); + +/* tchar routines */ + +unsigned char * _mbsdec(const unsigned char *, const unsigned char *); +unsigned char * _mbsinc(const unsigned char *); +size_t _mbsnbcnt(const unsigned char *, size_t); +unsigned int _mbsnextc (const unsigned char *); +unsigned char * _mbsninc(const unsigned char *, size_t); +unsigned char * _mbsspnp(const unsigned char *, const unsigned char *); + +/* character routines */ + +int _ismbcalnum(unsigned int c); +int _ismbcalpha(unsigned int c); +int _ismbcdigit(unsigned int c); +int _ismbcgraph(unsigned int c); +int _ismbclegal(unsigned int c); +int _ismbclower(unsigned int c); +int _ismbcprint(unsigned int c); +int _ismbcpunct(unsigned int c); +int _ismbcspace(unsigned int c); +int _ismbcupper(unsigned int c); + +unsigned int _mbctolower(unsigned int); +unsigned int _mbctoupper(unsigned int); + + +int _ismbblead( unsigned int c); +int _ismbbtrail( unsigned int c); +int _ismbslead( const unsigned char *s, const unsigned char *c); +int _ismbstrail( const unsigned char *s, const unsigned char *c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/msvcrt/msvcrtdbg.h b/include/msvcrt/msvcrtdbg.h new file mode 100644 index 0000000..3916f9a --- /dev/null +++ b/include/msvcrt/msvcrtdbg.h @@ -0,0 +1,43 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/msvcrt/msvcrtdbg.h + * PURPOSE: Useful debugging macros + * PROGRAMMER: + * UPDATE HISTORY: + * + */ + +/* + * NOTE: Define NDEBUG before including this header to disable debugging + * macros + */ + +#ifndef __MSVCRT_DEBUG +#define __MSVCRT_DEBUG + +#include + +#if 0 +#ifdef NDEBUG +#undef NDEBUG +#endif +#endif + +#ifdef DBG +#define DPRINT1(args...) do { DbgPrint("(MSVCRT:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT1 do { DbgPrint("MSVCRT:%s:%d\n",__FILE__,__LINE__); } while(0); +#else +#define DPRINT1(args...) +#define CHECKPOINT1 +#endif + +#if !defined(NDEBUG) && defined(DBG) +#define DPRINT(args...) do { DbgPrint("(MSVCRT:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT do { DbgPrint("MSVCRT:%s:%d\n",__FILE__,__LINE__); } while(0); +#else +#define DPRINT(args...) +#define CHECKPOINT +#endif /* NDEBUG */ + +#endif /* __MSVCRT_DEBUG */ diff --git a/include/msvcrt/process.h b/include/msvcrt/process.h new file mode 100644 index 0000000..15f4851 --- /dev/null +++ b/include/msvcrt/process.h @@ -0,0 +1,160 @@ +/* + * process.h + * + * Function calls for spawning child processes. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* changed second argument of cwait from nPID to hProc */ + +#ifndef _PROCESS_H_ +#define _PROCESS_H_ + +#ifndef __STRICT_ANSI__ + +#ifdef __cplusplus +extern "C" { +#endif + +void _cexit(void); +void _c_exit(void); + +/* + * Constants for cwait actions. + * Obsolete for Win32. + */ +#define _WAIT_CHILD 0 +#define _WAIT_GRANDCHILD 1 + +#ifndef _NO_OLDNAMES +#define WAIT_CHILD _WAIT_CHILD +#define WAIT_GRANDCHILD _WAIT_GRANDCHILD +#endif /* Not _NO_OLDNAMES */ + +int _cwait (int* pnStatus, int hProc, int nAction); + +int _getpid(void); + +int _execl (const char* szPath, const char* szArgv0, ...); +int _execle (const char* szPath, const char* szArgv0, ...); +int _execlp (const char* szPath, const char* szArgv0, ...); +int _execlpe (const char* szPath, const char* szArgv0, ...); +int _execv (const char* szPath, char* const* szaArgv); +int _execve (const char* szPath, char* const* szaArgv, char* const* szaEnv); +int _execvp (const char* szPath, char* const* szaArgv); +int _execvpe (const char* szPath, char* const* szaArgv, char* const* szaEnv); + + +/* + * Mode constants for spawn functions. + */ +#define _P_WAIT 0 +#define _P_NOWAIT 1 +#define _P_OVERLAY 2 +#define _OLD_P_OVERLAY _P_OVERLAY +#define _P_NOWAITO 3 +#define _P_DETACH 4 + +#ifndef _NO_OLDNAMES +#define P_WAIT _P_WAIT +#define P_NOWAIT _P_NOWAIT +#define P_OVERLAY _P_OVERLAY +#define OLD_P_OVERLAY _OLD_P_OVERLAY +#define P_NOWAITO _P_NOWAITO +#define P_DETACH _P_DETACH +#endif /* Not _NO_OLDNAMES */ + +int _spawnl (int nMode, const char* szPath, const char* szArgv0, ...); +int _spawnle (int nMode, const char* szPath, const char* szArgv0,...); +int _spawnlp (int nMode, const char* szPath, const char* szArgv0,...); +int _spawnlpe (int nMode, const char* szPath, const char* szArgv0,...); +int _spawnv (int nMode, const char* szPath, char* const* szaArgv); +int _spawnve (int nMode, const char* szPath, char* const* szaArgv, char* const* szaEnv); +int _spawnvp (int nMode, const char* szPath, char* const* szaArgv); +int _spawnvpe (int nMode, const char* szPath, char* const* szaArgv, char* const* szaEnv); +/* + * The functions _beginthreadex and _endthreadex are not provided by CRTDLL. + * They are provided by MSVCRT. + * + * NOTE: Apparently _endthread calls CloseHandle on the handle of the thread, + * making for race conditions if you are not careful. Basically you have to + * make sure that no-one is going to do *anything* with the thread handle + * after the thread calls _endthread or returns from the thread function. + * + * NOTE: No old names for these functions. Use the underscore. + */ +unsigned long + _beginthread (void (__cdecl *pfuncStart)(void *), + unsigned unStackSize, void* pArgList); +void _endthread (void); + +#if __MSVCRT__ +unsigned long + _beginthreadex (void *pSecurity, unsigned unStackSize, + unsigned (__stdcall *pfuncStart)(void*), void* pArgList, + unsigned unInitFlags, unsigned* pThreadAddr); +void _endthreadex (unsigned unExitCode); +#endif + + +void *_loaddll (char *name); +int _unloaddll(void *handle); + +unsigned long __threadid(void); +#define _threadid __threadid() +void * __threadhandle(void); + + +#ifndef _NO_OLDNAMES + +#define cwait _cwait +#define getpid _getpid +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execlpe _execlpe + +#define execv _execv +#define execve _execve +#define execvp _execvp +#define execvpe _execvpe + +#define spawnl _spawnl +#define spawnle _spawnle +#define spawnlp _spawnlp +#define spawnlpe _spawnlpe + +#define spawnv _spawnv +#define spawnve _spawnve +#define spawnvp _spawnvp +#define spawnvpe _spawnvpe + + +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not __STRICT_ANSI__ */ + +#endif /* _PROCESS_H_ not defined */ diff --git a/include/msvcrt/search.h b/include/msvcrt/search.h new file mode 100644 index 0000000..b42c4d0 --- /dev/null +++ b/include/msvcrt/search.h @@ -0,0 +1,35 @@ + +#ifndef _SEARCH_H_ +#define _SEARCH_H_ + +//char *key +//void *data + +//enum { FIND, ENTER } ACTION; +//enum { preorder, postorder, endorder, leaf } VISIT; + +#include +#include + + +//The Single UNIX ® Specification, Version 2 Copyright © 1997 The Open Group + +//int hcreate(size_t); +//void hdestroy(void); +//ENTRY *hsearch(ENTRY, ACTION); +//void insque(void *, void *); +void *_lfind(const void *, const void *, size_t *, + size_t, int (*)(const void *, const void *)); +void *_lsearch(const void *, void *, size_t *, + size_t, int (*)(const void *, const void *)); +//void remque(void *); +//void *tdelete(const void *, void **, +// int(*)(const void *, const void *)); +//void *tfind(const void *, void *const *, +// int(*)(const void *, const void *)); +//void *tsearch(const void *, void **, +// int(*)(const void *, const void *)); +//void twalk(const void *, +// void (*)(const void *, VISIT, int )); + +#endif diff --git a/include/msvcrt/share.h b/include/msvcrt/share.h new file mode 100644 index 0000000..8e3af3f --- /dev/null +++ b/include/msvcrt/share.h @@ -0,0 +1,17 @@ +#ifndef _include_share_h_ +#define _include_share_h_ + + +#define SH_COMPAT 0x0000 +#define SH_DENYRW 0x0010 +#define SH_DENYWR 0x0020 +#define SH_DENYRD 0x0030 +#define SH_DENYNO 0x0040 + +#define _SH_COMPAT SH_COMPAT +#define _SH_DENYRW SH_DENYRW +#define _SH_DENYWR SH_DENYWR +#define _SH_DENYRD SH_DENYRD +#define _SH_DENYNO SH_DENYNO + +#endif diff --git a/include/msvcrt/signal.h b/include/msvcrt/signal.h new file mode 100644 index 0000000..05b2aac --- /dev/null +++ b/include/msvcrt/signal.h @@ -0,0 +1,111 @@ +/* + * signal.h + * + * A way to set handlers for exceptional conditions (also known as signals). + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* added some extra signal constants */ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The prototypes (below) are the easy part. The hard part is figuring + * out what signals are available and what numbers they are assigned + * along with appropriate values of SIG_DFL and SIG_IGN. + */ + +/* + * A pointer to a signal handler function. A signal handler takes a + * single int, which is the signal it handles. + */ +typedef void (*_p_sig_fn_t)(int nSig); + +/* + * These are special values of signal handler pointers which are + * used to send a signal to the default handler (SIG_DFL), ignore + * the signal (SIG_IGN), or indicate an error return (SIG_ERR). + */ +#define SIG_DFL ((_p_sig_fn_t) 0) +#define SIG_IGN ((_p_sig_fn_t) 1) +#define SIG_ERR ((_p_sig_fn_t) -1) + +/* + * The actual signal values. Using other values with signal + * produces a SIG_ERR return value. + * + * NOTE: SIGINT is produced when the user presses Ctrl-C. + * SIGILL has not been tested. + * SIGFPE doesn't seem to work? + * SIGSEGV does not catch writing to a NULL pointer (that shuts down + * your app; can you say "segmentation violation core dump"?). + * SIGTERM comes from what kind of termination request exactly? + * SIGBREAK is indeed produced by pressing Ctrl-Break. + * SIGABRT is produced by calling abort. + * TODO: The above results may be related to not installing an appropriate + * structured exception handling frame. Results may be better if I ever + * manage to get the SEH stuff down. + */ +#define SIGINT 2 /* Interactive attention */ +#define SIGILL 4 /* Illegal instruction */ +#define SIGFPE 8 /* Floating point error */ +#define SIGSEGV 11 /* Segmentation violation */ +#define SIGTERM 15 /* Termination request */ +#define SIGBREAK 21 /* Control-break */ +#define SIGABRT 22 /* Abnormal termination (abort) */ + +#define SIGALRM 293 +#define SIGHUP 294 +/* SIGINT is ansi */ +#define SIGKILL 296 +#define SIGPIPE 297 +#define SIGQUIT 298 +#define SIGUSR1 299 +#define SIGUSR2 300 + +#define SIGNOFP 301 +#define SIGTRAP 302 +#define SIGTIMR 303 /* Internal for setitimer (SIGALRM, SIGPROF) */ +#define SIGPROF 304 +#define SIGMAX 320 + +/* + * Call signal to set the signal handler for signal sig to the + * function pointed to by handler. Returns a pointer to the + * previous handler, or SIG_ERR if an error occurs. Initially + * unhandled signals defined above will return SIG_DFL. + */ +_p_sig_fn_t signal(int sig, _p_sig_fn_t func); + +/* + * Raise the signal indicated by sig. Returns non-zero on success. + */ +int raise (int sig); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/msvcrt/stdarg.h b/include/msvcrt/stdarg.h new file mode 100644 index 0000000..77694ae --- /dev/null +++ b/include/msvcrt/stdarg.h @@ -0,0 +1,114 @@ +/* + * stdarg.h + * + * Provides facilities for stepping through a list of function arguments of + * an unknown number and type. + * + * NOTE: Gcc should provide stdarg.h, and I believe their version will work + * with crtdll. If necessary I think you can replace this with the GCC + * stdarg.h (or is it vararg.h). + * + * Note that the type used in va_arg is supposed to match the actual type + * *after default promotions*. Thus, va_arg (..., short) is not valid. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +/* + * Don't do any of this stuff for the resource compiler. + */ +#ifndef RC_INVOKED + +/* + * I was told that Win NT likes this. + */ +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED +#endif + +#ifndef _VA_LIST +#define _VA_LIST +typedef char* va_list; +#endif + + +/* + * Amount of space required in an argument list (ie. the stack) for an + * argument of type t. + */ +#define __va_argsiz(t) \ + (((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int)) + + +/* + * Start variable argument list processing by setting AP to point to the + * argument after pN. + */ +#ifdef __GNUC__ +/* + * In GNU the stack is not necessarily arranged very neatly in order to + * pack shorts and such into a smaller argument list. Fortunately a + * neatly arranged version is available through the use of __builtin_next_arg. + */ +#ifndef va_start +#define va_start(ap, pN) \ + ((ap) = ((va_list) __builtin_next_arg(pN))) +#endif +#else +/* + * For a simple minded compiler this should work (it works in GNU too for + * vararg lists that don't follow shorts and such). + */ +#define va_start(ap, pN) \ + ((ap) = ((va_list) (&pN) + __va_argsiz(pN))) +#endif + + +/* + * End processing of variable argument list. In this case we do nothing. + */ +#ifndef va_end +#define va_end(ap) ((void)0) +#endif + + +/* + * Increment ap to the next argument in the list while returing a + * pointer to what ap pointed to first, which is of type t. + * + * We cast to void* and then to t* because this avoids a warning about + * increasing the alignment requirement. + */ + +#ifndef va_arg +#define va_arg(ap, t) \ + (((ap) = (ap) + __va_argsiz(t)), \ + *((t*) (void*) ((ap) - __va_argsiz(t)))) +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* not _STDARG_H_ */ + diff --git a/include/msvcrt/stddef.h b/include/msvcrt/stddef.h new file mode 100644 index 0000000..c735d28 --- /dev/null +++ b/include/msvcrt/stddef.h @@ -0,0 +1,174 @@ +/* + * stddef.h + * + * Standard type definitions provided by the C library. + * + * NOTE: Actually supplied by the compiler (correct?). As such, GCC + * supplies a version of this header file. Unfortunately, GCC's + * version is all tied up with the way other headers for the + * GNU C library are implemented (or vice-versa), in a similar + * way to how the other Mingw32 headers are dependent on + * certain internals of this file. It is not clear to me whether + * you can safely use the GCC version in place of this version. + * TODO: Line up usage in other header files to work with GCC + * stddef.h. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + + +#ifndef __MSVCRT_STDDEF_H_ + +/* + * Any one of these symbols __need_* means that a standard header file + * wants us just to define one data type. So don't define + * the symbols that indicate this file's entire job has been done. + */ +#if (!defined(__need_wchar_t) && !defined(__need_wint_t) \ + && !defined(__need_size_t) && !defined(__need_ptrdiff_t) \ + && !defined(__need_NULL)) +#define __MSVCRT_STDDEF_H_ +#endif + +/* + * NOTE: The following typedefs are done using __xxx_TYPE__ defines followed + * by typedefs using those defines. I have chosen to do it this way because + * GCC supplies definitions for __xxx_TYPE__ macros and if, for example, your + * size_t is typedef'ed differently from what GCC expects it will give you + * warnings when you prototype functions like memcmp and memcpy. The values + * for __xxx_TYPE__ in this header file are the same as those given by GCC. + * Those values appear to work with the MSVCRT functions. + */ + +/* + * Signed type of difference of two pointers. + */ + +/* Define this type if we are doing the whole job, or if we want this type + * in particular. */ +#if defined (__MSVCRT_STDDEF_H_) || defined (__need_ptrdiff_t) + +#ifndef _PTRDIFF_T_ +#define _PTRDIFF_T_ +#ifndef __PTRDIFF_TYPE__ +#define __PTRDIFF_TYPE__ int +#endif +typedef __PTRDIFF_TYPE__ ptrdiff_t; +#endif + +/* If this symbol has done its job, get rid of it. */ +#undef __need_ptrdiff_t + +#endif /* __MSVCRT_STDDEF_H_ or __need_ptrdiff_t. */ + +/* + * Unsigned type of `sizeof' something. + */ + + +/* Define this type if we are doing the whole job, + * or if we want this type in particular. */ +#if defined (__MSVCRT_STDDEF_H_) || defined (__need_size_t) + +#ifndef _SIZE_T_ +#define _SIZE_T_ +#define SIZE_T_DEFINED +#define _SIZE_T +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ unsigned int +#endif +typedef __SIZE_TYPE__ size_t; +#endif + +#undef __need_size_t + +#endif /* __MSVCRT_STDDEF_H_ or __need_size_t. */ + +/* Wide character type. + Locale-writers should change this as necessary to + be big enough to hold unique values not between 0 and 127, + and not (wchar_t) -1, for each defined multibyte character. */ + +/* Define this type if we are doing the whole job, + or if we want this type in particular. */ +#if defined (__MSVCRT_STDDEF_H_) || defined (__need_wchar_t) + +#ifndef _WCHAR_T_ +#define _WCHAR_T_ +#define _WCHAR_T +#define _WCHAR_T_DEFINED +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ short unsigned int +#endif +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif /* C++ */ +#endif /* wchar_t not already defined */ + +#undef __need_wchar_t + +#endif /* __MSVCRT_STDDEF_H_ or __need_wchar_t. */ + +/* + * wint_t, the equivalent of int in wchar ctype functions. + */ +#if defined (__MSVCRT_STDDEF_H_) || defined (__need_wint_t) + +#ifndef _WINT_T_ +#define _WINT_T_ +#define _WINT_T /* To satisfy libstdc++ */ +#ifndef __WINT_TYPE__ +#define __WINT_TYPE__ short int +#endif /* Not defined __WINT_TYPE__ */ + +typedef __WINT_TYPE__ wint_t; +#endif /* Not defined _WINT_T_ */ + +#undef __need_wint_t + +#endif /* __MSVCRT_STDDEF_H_ or __need_wint_t. */ + + +/* + * A null pointer constant. + */ + +#if defined (__MSVCRT_STDDEF_H_) || defined (__need_NULL) + +#undef NULL +#define NULL (0) +#endif /* __MSVCRT_STDDEF_H_ or __need_NULL */ + +#undef __need_NULL + + +/* + * Offsetof, a macro for finding the offset of a member in a structure. + * Works by returning the 'address' of the MEMBER of a TYPE struct at address + * zero. + */ + +#if defined (__MSVCRT_STDDEF_H_) +#define offsetof(TYPE, MEMBER) ((size_t) &( ((TYPE *) 0)->MEMBER )) +#endif /* __MSVCRT_STDDEF_H_ */ + + +#endif /* not __MSVCRT_STDDEF_H_ */ diff --git a/include/msvcrt/stdio.h b/include/msvcrt/stdio.h new file mode 100644 index 0000000..ce8956a --- /dev/null +++ b/include/msvcrt/stdio.h @@ -0,0 +1,375 @@ +/* + * stdio.h + * + * Definitions of types and prototypes of functions for standard input and + * output. + * + * NOTE: The file manipulation functions provided by Microsoft seem to + * work with either slash (/) or backslash (\) as the path separator. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* implemented clearerr feof ferror perror as macros */ +/* added _IOCOMMIT */ +/* added filbuf and flsbuf and fwalk */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define __need_size_t +#define __need_NULL +#define __need_wchar_t +#define __need_wint_t +#include + + +/* Some flags for the iobuf structure provided by djgpp stdio.h */ +#define _IOREAD 0x000010 +#define _IOWRT 0x000020 +#define _IOMYBUF 0x000040 +#define _IOEOF 0x000100 +#define _IOERR 0x000200 +#define _IOSTRG 0x000400 + +#define _IOAPPEND 0x002000 +#define _IORMONCL 0x004000 /* remove on close, for temp files */ +/* if _flag & _IORMONCL, ._name_to_remove needs freeing */ +#define _IOUNGETC 0x010000 /* there is an ungetc'ed character in the buffer */ +#define _IOCOMMIT 0x008000 + +#define _IODIRTY 0x000080 +#define _IOAHEAD 0x000008 +#define _IORW (_IOREAD | _IOWRITE ) + + +/* + * I used to include stdarg.h at this point, in order to allow for the + * functions later on in the file which use va_list. That conflicts with + * using stdio.h and varargs.h in the same file, so I do the typedef myself. + */ +//#ifndef _VA_LIST +//#define _VA_LIST +//typedef char* va_list; +//#endif +#include + +/* + * FILE should be used as a pointer to an opaque data type. Do not rely on + * anything else, especially the size or contents of this structure! + */ +#ifndef _FILE_DEFINED +typedef struct { + char *_ptr; + int _cnt; + char *_base; + int _flag; + int _file; + int _ungotchar; + int _bufsiz; + char *_name_to_remove; +} FILE; +#define _FILE_DEFINED +#endif + +//#define _fillsize _bufsiz + +/* + * The three standard file pointers provided by the run time library. + * NOTE: These will go to the bit-bucket silently in GUI applications! + */ +extern FILE _iob[]; /* an array of FILE */ +#define stdin (&_iob[0]) +#define stdout (&_iob[1]) +#define stderr (&_iob[2]) +#define stdaux (&_iob[3]) +#define stdprn (&_iob[4]) + +/* Returned by various functions on end of file condition or error. */ +#define EOF (-1) + + +/* + * The maximum length of a file name. You should use GetVolumeInformation + * instead of this constant. But hey, this works. + * + * NOTE: This is used in the structure _finddata_t (see dir.h) so changing it + * is probably not a good idea. + */ +#define FILENAME_MAX (260) + +/* + * The maximum number of files that may be open at once. I have set this to + * a conservative number. The actual value may be higher. + */ +#define FOPEN_MAX (20) + + +/* + * File Operations + */ +FILE* _fdopen(int handle, char *mode); +FILE* _wfdopen(int handle, wchar_t *mode); + +FILE* fopen (const char* szFileName, const char* szMode); +FILE* _wfopen(const wchar_t *file, const wchar_t *mode); + +FILE* freopen(const char* szNewFileName, const char* szNewMode, + FILE* fileChangeAssociation); +FILE* _wfreopen(const wchar_t *file, const wchar_t *mode, FILE *f); + +FILE* _fsopen(const char *file, const char *mode, int shflag); +FILE* _wfsopen(const wchar_t *file, const wchar_t *mode, int shflag); + +int fflush(FILE* fileFlush); +int fclose(FILE* fileClose); +#define fcloseall _fcloseall +int remove(const char* szFileName); +int _wremove(const wchar_t* szFileName); +int rename(const char* szOldFileName, const char* szNewFileName); +int _wrename(const wchar_t *oldName, const wchar_t *newName); +FILE* tmpfile(void); + +int _filbuf(FILE *f); +int _flsbuf(int c, FILE *f); +void _fwalk(void (*func)(FILE *)); // not exported +int _fcloseall(void); + + +/* + * The maximum size of name (including NUL) that will be put in the user + * supplied buffer caName. + * NOTE: This has not been determined by experiment, but based on the + * maximum file name length above it is probably reasonable. I could be + * wrong... + */ +#define L_tmpnam (260) + +char* tmpnam (char caName[]); +wchar_t* _wtmpnam(wchar_t *s); + +char* _tempnam (const char *szDir, const char *szPfx); +wchar_t *_wtempnam(const wchar_t *dir,const wchar_t *prefix); + +#ifndef _NO_OLDNAMES +#define tempnam _tempnam +#endif /* Not _NO_OLDNAMES */ + +/* + * The three possible buffering mode (nMode) values for setvbuf. + * NOTE: _IOFBF works, but _IOLBF seems to work like unbuffered... + * maybe I'm testing it wrong? + */ +#define _IOFBF 0 /* fully buffered */ +#define _IOLBF 1 /* line buffered */ +#define _IONBF 2 /* unbuffered */ + +int setvbuf (FILE* fileSetBuffer, char* caBuffer, int nMode, + size_t sizeBuffer); + + +/* + * The buffer size as used by setbuf such that it is equivalent to + * (void) setvbuf(fileSetBuffer, caBuffer, _IOFBF, BUFSIZ). + */ +#define BUFSIZ 512 + +void setbuf (FILE* fileSetBuffer, char* caBuffer); + +/* + * Pipe Operations + */ + +int _pclose (FILE* pipeClose); +FILE* _popen (const char* szPipeName, const char* szMode); +FILE* _wpopen (const wchar_t *cm, const wchar_t *md); + +#define popen _popen +#define pclose _pclose + +/* Wide character version */ +FILE* _wpopen (const wchar_t* szPipeName, const wchar_t* szMode); + +/* + * Formatted Output + */ + +int fprintf (FILE* filePrintTo, const char* szFormat, ...); +int printf (const char* szFormat, ...); +int sprintf (char* caBuffer, const char* szFormat, ...); +int vfprintf (FILE* filePrintTo, const char* szFormat, va_list varg); +int vprintf (const char* szFormat, va_list varg); +int vsprintf (char* caBuffer, const char* szFormat, va_list varg); + +/* Wide character versions */ +int fwprintf (FILE* filePrintTo, const wchar_t* wsFormat, ...); +int wprintf (const wchar_t* wsFormat, ...); +int swprintf (wchar_t* wcaBuffer, const wchar_t* wsFormat, ...); +int vfwprintf (FILE* filePrintTo, const wchar_t* wsFormat, va_list varg); +int vwprintf (const wchar_t* wsFormat, va_list varg); +int vswprintf (wchar_t* wcaBuffer, const wchar_t* wsFormat, va_list varg); + +/* + * Formatted Input + */ + +int fscanf (FILE* fileReadFrom, const char* szFormat, ...); +int scanf (const char* szFormat, ...); +int sscanf (const char* szReadFrom, const char* szFormat, ...); + +/* Wide character versions */ +int fwscanf (FILE* fileReadFrom, const wchar_t* wsFormat, ...); +int wscanf (const wchar_t* wsFormat, ...); +int swscanf (const wchar_t* wsReadFrom, const wchar_t* wsFormat, ...); + +/* + * Character Input and Output Functions + */ + +int fgetc (FILE* fileRead); +char* fgets (char* caBuffer, int nBufferSize, FILE* fileRead); +int fputc (int c, FILE* fileWrite); +int fputs (const char* szOutput, FILE* fileWrite); +int getc (FILE* fileRead); +int getchar (void); +char* gets (char* caBuffer); /* Unsafe: how does gets know how long the + * buffer is? */ +int putc (int c, FILE* fileWrite); +int putchar (int c); +int puts (const char* szOutput); +int ungetc (int c, FILE* fileWasRead); + +/* Wide character versions */ +wint_t fgetwc (FILE* fileRead); +wint_t fputwc (wchar_t wc, FILE* fileWrite); +wint_t getwc (FILE *fileRead); +wint_t putwc (wint_t wc, FILE* fileWrite); +wint_t putwchar (wint_t c); +int _putws (const wchar_t* ws); +wint_t ungetwc (wchar_t wc, FILE* fileWasRead); + +wint_t _filwbuf(FILE *f); +wint_t _flswbuf(wchar_t c, FILE *f); + +/* + * Not exported by CRTDLL.DLL included for reference purposes. + */ +#if 0 +wchar_t* fgetws (wchar_t* wcaBuffer, int nBufferSize, FILE* fileRead); +int fputws (const wchar_t* wsOutput, FILE* fileWrite); +int getwc (FILE* fileRead); +int getwchar (); +wchar_t* getws (wchar_t* wcaBuffer); +#endif /* 0 */ + +/* NOTE: putchar has no wide char equivalent even in tchar.h */ + + +/* + * Direct Input and Output Functions + */ + +size_t fread (void* pBuffer, size_t sizeObject, size_t sizeObjCount, + FILE* fileRead); +size_t fwrite (const void* pObjArray, size_t sizeObject, size_t sizeObjCount, + FILE* fileWrite); + + +/* + * File Positioning Functions + */ + +/* Constants for nOrigin indicating the position relative to which fseek + * sets the file position. Enclosed in ifdefs because io.h could also + * define them. (Though not anymore since io.h includes this file now.) */ +#ifndef SEEK_SET +#define SEEK_SET (0) +#endif + +#ifndef SEEK_CUR +#define SEEK_CUR (1) +#endif + +#ifndef SEEK_END +#define SEEK_END (2) +#endif + +int fseek (FILE* fileSetPosition, long lnOffset, int nOrigin); +long ftell (FILE* fileGetPosition); +void rewind (FILE* fileRewind); + +/* + * An opaque data type used for storing file positions... The contents of + * this type are unknown, but we (the compiler) need to know the size + * because the programmer using fgetpos and fsetpos will be setting aside + * storage for fpos_t structres. Actually I tested using a byte array and + * it is fairly evident that the fpos_t type is a long (in CRTDLL.DLL). + * Perhaps an unsigned long? TODO? + */ +typedef long fpos_t; + +int fgetpos (FILE* fileGetPosition, fpos_t* pfpos); +int fsetpos (FILE* fileSetPosition, const fpos_t* pfpos); + + +/* + * Error Functions + */ +#if 0 +void clearerr (FILE* fileClearErrors); +int feof (FILE* fileIsAtEnd); +int ferror (FILE* fileIsError); +void perror (const char* szErrorMessage); + +#endif +void _wperror(const wchar_t *s); + + +#define clearerr(f) (((f)->_flag) &= ~(_IOERR|_IOEOF)) +#define feof(f) (((f)->_flag&_IOEOF)!=0) +#define ferror(f) (((f)->_flag&_IOERR)!=0) +#define perror(s) (fprintf(stderr, "%s: %s\n", (s), _strerror(NULL))) +/* + * Non ANSI functions + */ + +#ifndef __STRICT_ANSI__ +int _fgetchar (void); +int _fputchar (int c); +FILE* _fdopen (int nHandle, char* szMode); + +#ifndef _NO_OLDNAMES +#define fgetchar _fgetchar +#define fputchar _fputchar +#define fdopen _fdopen +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _STDIO_H_ */ diff --git a/include/msvcrt/stdlib.h b/include/msvcrt/stdlib.h new file mode 100644 index 0000000..dc60319 --- /dev/null +++ b/include/msvcrt/stdlib.h @@ -0,0 +1,232 @@ +/* + * stdlib.h + * + * Definitions for common types, variables, and functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* added splitpath */ +/* changed definition of environ and argc */ +/* moved prototype for swab from string.h to stdlib.h */ +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This seems like a convenient place to declare these variables, which + * give programs using WinMain (or main for that matter) access to main-ish + * argc and argv. environ is a pointer to a table of environment variables. + * NOTE: Strings in _argv and environ are ANSI strings. + */ +extern int* __argc_dll; +extern char*** __argv_dll; +extern char*** _environ_dll; +#define __argc (*__argc_dll) +#define __argv (*__argv_dll) +#define _environ (*_environ_dll) + + +#define __need_size_t +#define __need_wchar_t +#define __need_NULL +#include + +#include + +#ifndef __ATTRIB_NORETURN +#ifdef __GNUC__ +#define _ATTRIB_NORETURN __attribute__ ((noreturn)) +#ifndef __int64 +#define __int64 long long +#endif /* Not __int64 */ +#else /* Not __GNUC__ */ +#define _ATTRIB_NORETURN +#endif /* __GNUC__ */ +#endif + +double atof (const char* szNumber); +int atoi (const char* szNumber); +long atol (const char* szNumber); + + +double strtod (const char* szNumber, char** pszAfterNumber); +double wcstod (const wchar_t* wsNumber, wchar_t** pwsAfterNumber); +long strtol (const char* szNumber, char** pszAfterNumber, int nBase); +long wcstol (const wchar_t* wsNumber, wchar_t** pwsAfterNumber, int nBase); + +unsigned long strtoul (const char* szNumber, char** pszAfterNumber, + int nBase); +unsigned long wcstoul (const wchar_t* wsNumber, wchar_t** pwsAfterNumber, + int nBase); + +size_t wcstombs (char* mbsDest, const wchar_t* wsConvert, size_t size); +int wctomb (char* mbDest, wchar_t wc); + +int mblen (const char* mbs, size_t sizeString); +size_t mbstowcs (wchar_t* wcaDest, const char* mbsConvert, + size_t size); +int mbtowc (wchar_t* wcDest, const char* mbConvert, size_t size); + + +/* + * RAND_MAX is the maximum value that may be returned by rand. + * The minimum is zero. + */ +#define RAND_MAX 0x7FFF + +int rand (void); +void srand (unsigned int nSeed); + + +void* calloc (size_t sizeObjCnt, size_t sizeObject); +void* malloc (size_t sizeObject); +void* realloc (void* pObject, size_t sizeNew); +void free (void* pObject); + +/* These values may be used as exit status codes. */ +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE -1 + +void abort (void) _ATTRIB_NORETURN; +void exit (int nStatus) _ATTRIB_NORETURN; +int atexit (void (*pfuncExitProcessing)(void)); + +int system (const char* szCommand); // impl in process +char* getenv (const char* szVarName); +wchar_t* _wgetenv (const wchar_t* szVarName); + +typedef int (*_pfunccmp_t)(const void*, const void*); + +void* bsearch (const void* pKey, const void* pBase, size_t cntObjects, + size_t sizeObject, _pfunccmp_t pfuncCmp); +void qsort (const void* pBase, size_t cntObjects, size_t sizeObject, + _pfunccmp_t pfuncCmp); + +int abs (int n); +long labs (long n); + +/* + * div_t and ldiv_t are structures used to return the results of div and + * ldiv. + * + * NOTE: div and ldiv appear not to work correctly unless + * -fno-pcc-struct-return is specified. This is included in the + * mingw32 specs file. + */ +typedef struct { int quot, rem; } div_t; +typedef struct { long quot, rem; } ldiv_t; +typedef struct { long long quot, rem; } lldiv_t; + +div_t div (int nNumerator, int nDenominator); +ldiv_t ldiv (long lNumerator, long lDenominator); +lldiv_t lldiv (long long lNumerator, long long lDenominator); + + +#ifndef __STRICT_ANSI__ + +/* + * NOTE: Officially the three following functions are obsolete. The Win32 API + * functions SetErrorMode, Beep and Sleep are their replacements. + */ +void _beep (unsigned int, unsigned int); +void _seterrormode (int nMode); +void _sleep (unsigned long ulTime); + +void _exit (int nStatus) _ATTRIB_NORETURN; + +int _putenv (const char *val); +int _wputenv(const wchar_t *val); +void _searchenv (const char *file, const char *var, char *path); +void _wsearchenv (const wchar_t *file, const wchar_t *var, wchar_t *path); + +void _makepath( char *path, const char *drive, const char *dir, + const char *fname, const char *ext ); +void _wmakepath( wchar_t *path, const wchar_t *drive, const wchar_t *dir, + const wchar_t *fname, const wchar_t *ext ); +void _splitpath( const char *path, char *drive, char *dir, + char *fname, char *ext ); +char* _fullpath( char* caBuf, const char* szPath, size_t sizeMax ); +wchar_t *_wfullpath( wchar_t *absPath, const wchar_t *relPath, size_t maxLength ); + +char* _itoa (int nValue, char* sz, int nRadix); +char* _i64toa(__int64 value, char *string, int radix); +char* _ltoa (long lnValue, char* sz, int nRadix); +char* _ultoa(unsigned long value, char *string, int radix); +char* _ui64toa(unsigned __int64 value, char *string, int radix); + +wchar_t* _itow (int nValue, wchar_t* sz, int nRadix); +wchar_t* _i64tow(__int64 value, wchar_t *string, int radix); +wchar_t* _ltow (long lnValue, wchar_t* sz, int nRadix); +wchar_t* _ultow(unsigned long value, wchar_t *string, int radix); +wchar_t* _ui64tow(unsigned __int64 value, wchar_t *string, int radix); + +char* _ecvt (double dValue, int nDig, int* pnDec, int* pnSign); +char* _fcvt (double dValue, int nDig, int* pnDec, int* pnSign); +char* _gcvt (double dValue, int nDec, char* caBuf); + +void _swab (const char* caFrom, char* caTo, size_t sizeToCopy); + +unsigned int _rotl( unsigned int value, int shift ); +unsigned int _rotr( unsigned int value, int shift ); +unsigned long _lrotl( unsigned long value, int shift ); +unsigned long _lrotr( unsigned long value, int shift ); + +__int64 _atoi64(const char *szNumber); + +int _wtoi( const wchar_t *str ); +__int64 _wtoi64(const wchar_t *str); +long _wtol( const wchar_t *str ); + + +#ifndef _NO_OLDNAMES +#define beep _beep +#define seterrormode _seterrormode +#define sleep _sleep +#define putenv _putenv +#define searchenv _searchenv +#define splitpath _splitpath + +#define itoa _itoa +#define ltoa _ltoa + +#define ecvt _ecvt +#define fcvt _fcvt +#define gcvt _gcvt + +#define swab _swab +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +/* + * Undefine the no return attribute used in some function definitions + */ +#undef _ATTRIB_NORETURN + +#ifdef __cplusplus +} +#endif + +#endif /* _STDLIB_H_ */ diff --git a/include/msvcrt/string.h b/include/msvcrt/string.h new file mode 100644 index 0000000..80050af --- /dev/null +++ b/include/msvcrt/string.h @@ -0,0 +1,194 @@ +/* + * string.h + * + * Definitions for memory and string functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +/* changed prototype for _strerror */ +/* moved prototype for swab from string.h to stdlib.h */ + + +#ifndef _STRING_H_ +#define _STRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Define size_t, wchar_t and NULL + */ +#define __need_size_t +#define __need_wchar_t +#define __need_NULL +#include + +char * ___strtok; // removed extern specifier 02-06-98, BD + +/* + * Prototypes of the ANSI Standard C library string functions. + */ +void* memchr (const void* p, int cSearchFor, size_t sizeSearch); +int memcmp (const void* p1, const void* p2, size_t sizeSearch); +void* memcpy (void* pCopyTo, const void* pSource, size_t sizeSource); +void* memmove (void* pMoveTo, const void* pSource, size_t sizeSource); +void* memset (void* p, int cFill, size_t sizeRepeatCount); +char* strcat (char* szAddTo, const char* szAdd); +char* strchr (const char* szSearch, int cFor); +int strcmp (const char* sz1, const char* sz2); +int strcoll (const char* sz1, const char* sz2); /* Compare using locale */ +char* strcpy (char* szCopyTo, const char* szSource); +size_t strcspn (const char* szGetPrefix, const char* szNotIncluding); +char* strerror (int nError); /* NOTE: NOT an old name wrapper. */ +char * _strerror(const char *s); +size_t strlen (const char* sz); +size_t strnlen (const char* sz, size_t count); // not exported +char* strncat (char* szAddTo, const char* szAdd, size_t sizeMaxAdd); +int strncmp (const char* sz1, const char* sz2, size_t sizeMaxCompare); +char* strncpy (char* szCopyTo, const char* szSource, size_t sizeMaxCopy); +char* strpbrk (const char* szSearch, const char* szAnyOf); +char* strrchr (const char* szSearch, int cFor); +size_t strspn (const char* szGetPrefix, const char *szIncluding); +char* strstr (const char* szSearch, const char *szFor); +char* strtok (char* szTokenize, const char* szDelimiters); +size_t strxfrm (char* szTransformed, const char *szSource, + size_t sizeTransform); + +#ifndef __STRICT_ANSI__ +/* + * Extra non-ANSI functions provided by the CRTDLL library + */ +void* _memccpy (void* pCopyTo, const void* pSource, int cTerminator, + size_t sizeMaxCopy); +int _memicmp (const void* p1, const void* p2, size_t sizeSearch); +char* _strdup (const char *szDuplicate); +int _strcmpi (const char* sz1, const char* sz2); +int _stricmp (const char* sz1, const char* sz2); +int _stricoll (const char* sz1, const char* sz2); +char* _strlwr (char* szToConvert); +int _strnicmp (const char* sz1, const char* sz2, + size_t sizeMaxCompare); +char* _strnset (char* szToFill, int cFill, size_t sizeMaxFill); +char* _strrev (char* szToReverse); +char* _strset (char* szToFill, int cFill); +char* _strupr (char* szToConvert); + + +#endif /* Not __STRICT_ANSI__ */ + + +/* + * Unicode versions of the standard calls. + */ +wchar_t* wcscat (wchar_t* wsAddTo, const wchar_t* wsAdd); +wchar_t* wcschr (const wchar_t* wsSearch, wchar_t wcFor); +int wcscmp (const wchar_t* ws1, const wchar_t* ws2); +int wcscoll (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* wcscpy (wchar_t* wsCopyTo, const wchar_t* wsSource); +size_t wcscspn (const wchar_t* wsGetPrefix, const wchar_t* wsNotIncluding); +/* Note: No wcserror in CRTDLL. */ +size_t wcslen (const wchar_t* ws); +wchar_t* wcsncat (wchar_t* wsAddTo, const wchar_t* wsAdd, size_t sizeMaxAdd); +int wcsncmp(const wchar_t* ws1, const wchar_t* ws2, size_t sizeMaxCompare); +wchar_t* wcsncpy(wchar_t* wsCopyTo, const wchar_t* wsSource, + size_t sizeMaxCopy); +wchar_t* wcspbrk(const wchar_t* wsSearch, const wchar_t* wsAnyOf); +wchar_t* wcsrchr(const wchar_t* wsSearch, wchar_t wcFor); +size_t wcsspn(const wchar_t* wsGetPrefix, const wchar_t* wsIncluding); +wchar_t* wcsstr(const wchar_t* wsSearch, const wchar_t* wsFor); +wchar_t* wcstok(wchar_t* wsTokenize, const wchar_t* wsDelimiters); +size_t wcsxfrm(wchar_t* wsTransformed, const wchar_t *wsSource, + size_t sizeTransform); + + +#ifndef __STRICT_ANSI__ +/* + * Unicode versions of non-ANSI functions provided by CRTDLL. + */ + +/* NOTE: _wcscmpi not provided by CRTDLL, this define is for portability */ +#define _wcscmpi _wcsicmp + +wchar_t* _wcsdup (const wchar_t* wsToDuplicate); +int _wcsicmp (const wchar_t* ws1, const wchar_t* ws2); +int _wcsicoll (const wchar_t* ws1, const wchar_t* ws2); +int _wcsncoll (const wchar_t *s1, const wchar_t *s2, size_t c); +int _wcsnicoll (const wchar_t *s1, const wchar_t *s2, size_t c); +wchar_t* _wcslwr (wchar_t* wsToConvert); +int _wcsnicmp (const wchar_t* ws1, const wchar_t* ws2, + size_t sizeMaxCompare); +wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill); +wchar_t* _wcsrev (wchar_t* wsToReverse); +wchar_t* _wcsset (wchar_t* wsToFill, wchar_t wcToFill); +wchar_t* _wcsupr (wchar_t* wsToConvert); + +#endif /* Not __STRICT_ANSI__ */ + + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +/* + * Non-underscored versions of non-ANSI functions. They live in liboldnames.a + * and provide a little extra portability. Also a few extra UNIX-isms like + * strcasecmp. + */ + +void* memccpy (void* pCopyTo, const void* pSource, int cTerminator, + size_t sizeMaxCopy); +int memicmp (const void* p1, const void* p2, size_t sizeSearch); +#define strdup(szDuplicate) _strdup(szDuplicate) +int strcmpi (const char* sz1, const char* sz2); +int stricmp (const char* sz1, const char* sz2); +int strcasecmp (const char* sz1, const char* sz2); +int stricoll (const char* sz1, const char* sz2); +char* strlwr (char* szToConvert); +int strnicmp (const char* sz1, const char* sz2, size_t sizeMaxCompare); +int strncasecmp (const char* sz1, const char* sz2, size_t sizeMaxCompare); +char* strnset (char* szToFill, int cFill, size_t sizeMaxFill); +char* strrev (char* szToReverse); +char* strset (char* szToFill, int cFill); +char* strupr (char* szToConvert); + + +/* NOTE: There is no _wcscmpi, but this is for compatibility. */ +int wcscmpi (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* wcsdup (const wchar_t* wsToDuplicate); +int wcsicmp (const wchar_t* ws1, const wchar_t* ws2); +int wcsicoll (const wchar_t* ws1, const wchar_t* ws2); +wchar_t* wcslwr (wchar_t* wsToConvert); +int wcsnicmp (const wchar_t* ws1, const wchar_t* ws2, + size_t sizeMaxCompare); +wchar_t* wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill); +wchar_t* wcsrev (wchar_t* wsToReverse); +wchar_t* wcsset (wchar_t* wsToFill, wchar_t wcToFill); +wchar_t* wcsupr (wchar_t* wsToConvert); + +#endif /* Not _NO_OLDNAMES */ +#endif /* Not strict ANSI */ + +#endif + +#ifdef __cplusplus +extern "C" } +#endif diff --git a/include/msvcrt/sys/fcntl.h b/include/msvcrt/sys/fcntl.h new file mode 100644 index 0000000..19a67bc --- /dev/null +++ b/include/msvcrt/sys/fcntl.h @@ -0,0 +1,8 @@ +/* + * This file is part of the Mingw32 package. + * + * This fcntl.h maps to the root fcntl.h + */ +#ifndef __STRICT_ANSI__ +#include +#endif diff --git a/include/msvcrt/sys/file.h b/include/msvcrt/sys/file.h new file mode 100644 index 0000000..9b8cc98 --- /dev/null +++ b/include/msvcrt/sys/file.h @@ -0,0 +1,9 @@ +/* + * This file is part of the Mingw32 package. + * + * This file.h maps to the root fcntl.h + * TODO? + */ +#ifndef __STRICT_ANSI__ +#include +#endif diff --git a/include/msvcrt/sys/locking.h b/include/msvcrt/sys/locking.h new file mode 100644 index 0000000..d279c6d --- /dev/null +++ b/include/msvcrt/sys/locking.h @@ -0,0 +1,38 @@ +/* + * locking.h + * + * Constants for the mode parameter of the locking function. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _LOCKING_H_ +#define _LOCKING_H_ + +/* + * TODO: Define LK_... constants. + */ + +#endif /* Not _LOCKING_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/sys/stat.h b/include/msvcrt/sys/stat.h new file mode 100644 index 0000000..997ace7 --- /dev/null +++ b/include/msvcrt/sys/stat.h @@ -0,0 +1,142 @@ +/* + * stat.h + * + * Symbolic constants for opening and creating files, also stat, fstat and + * chmod functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _STAT_H_ +#define _STAT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _WCHAR_T_ +#define _WCHAR_T_ +#define _WCHAR_T +#define _WCHAR_T_DEFINED +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ short unsigned int +#endif +#ifndef __cplusplus +typedef __WCHAR_TYPE__ wchar_t; +#endif /* C++ */ +#endif /* wchar_t not already defined */ + + +/* + * Constants for the stat st_mode member. + */ +#define S_IFIFO 0x1000 /* FIFO */ +#define S_IFCHR 0x2000 /* Character */ +#define S_IFBLK 0x3000 /* Block */ +#define S_IFDIR 0x4000 /* Directory */ +#define S_IFREG 0x8000 /* Regular */ + +#define S_IFMT 0xF000 /* File type mask */ + +#define S_IEXEC 0x0040 +#define S_IWRITE 0x0080 +#define S_IREAD 0x0100 + +#define S_ISDIR(m) ((m) & S_IFDIR) +#define S_ISFIFO(m) ((m) & S_IFIFO) +#define S_ISCHR(m) ((m) & S_IFCHR) +#define S_ISBLK(m) ((m) & S_IFBLK) +#define S_ISREG(m) ((m) & S_IFREG) + +#define S_IRWXU (S_IREAD | S_IWRITE | S_IEXEC) +#define S_IXUSR S_IEXEC +#define S_IWUSR S_IWRITE +#define S_IRUSR S_IREAD + +#define _S_IEXEC S_IEXEC +#define _S_IREAD S_IREAD +#define _S_IWRITE S_IWRITE + +/* + * The structure manipulated and returned by stat and fstat. + * + * NOTE: If called on a directory the values in the time fields are not only + * invalid, they will cause localtime et. al. to return NULL. And calling + * asctime with a NULL pointer causes an Invalid Page Fault. So watch it! + */ +struct stat +{ + long st_dev; /* Equivalent to drive number 0=A 1=B ... */ + short st_ino; /* Always zero ? */ + short st_mode; /* See above constants */ + short st_nlink; /* Number of links. */ + int st_uid; /* User: Maybe significant on NT ? */ + short st_gid; /* Group: Ditto */ + short st_rdev; /* Seems useless (not even filled in) */ + long st_size; /* File size in bytes */ + time_t st_atime; /* Accessed date (always 00:00 hrs local + * on FAT) */ + time_t st_mtime; /* Modified time */ + time_t st_ctime; /* Creation time */ +}; + +struct _stati64 +{ + short st_dev; /* Equivalent to drive number 0=A 1=B ... */ + short st_ino; /* Always zero ? */ + short st_mode; /* See above constants */ + short st_nlink; /* Number of links. */ + int st_uid; /* User: Maybe significant on NT ? */ + short st_gid; /* Group: Ditto */ + short st_rdev; /* Seems useless (not even filled in) */ + __int64 st_size; /* File size in bytes */ + time_t st_atime; /* Accessed date (always 00:00 hrs local + * on FAT) */ + time_t st_mtime; /* Modified time */ + time_t st_ctime; /* Creation time */ +}; + +int _fstat (int nFileNo, struct stat* pstat); +__int64 _fstati64 (int nFileNo, struct _stati64* pstat); +int _stat (const char* szPath, struct stat* pstat); +__int64 _stati64 (const char* szPath, struct _stati64* pstat); +int _wstat (const wchar_t* szPath, struct stat* pstat); +__int64 _wstati64 (const wchar_t* szPath, struct _stati64* pstat); + +#ifndef _NO_OLDNAMES + +#define fstat(nFileNo, pstat) _fstat(nFileNo, pstat) +#define stat(szPath,pstat) _stat(szPath,pstat) + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _STAT_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/sys/time.h b/include/msvcrt/sys/time.h new file mode 100644 index 0000000..27d64df --- /dev/null +++ b/include/msvcrt/sys/time.h @@ -0,0 +1,3 @@ + +#include + diff --git a/include/msvcrt/sys/timeb.h b/include/msvcrt/sys/timeb.h new file mode 100644 index 0000000..85e57ed --- /dev/null +++ b/include/msvcrt/sys/timeb.h @@ -0,0 +1,60 @@ +/* + * timeb.h + * + * Support for the UNIX System V ftime system call. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _TIMEB_H_ +#define _TIMEB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * TODO: Structure not tested. + */ +struct timeb +{ + long time; + short millitm; + short _timezone; + short dstflag; +}; + +/* TODO: Not tested. */ +void _ftime (struct timeb* timebBuffer); + +#ifndef _NO_OLDNAMES +void ftime (struct timeb* timebBuffer); +#endif /* Not _NO_OLDNAMES */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not _TIMEB_H_ */ + +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/sys/types.h b/include/msvcrt/sys/types.h new file mode 100644 index 0000000..234e1d0 --- /dev/null +++ b/include/msvcrt/sys/types.h @@ -0,0 +1,82 @@ +/* + * types.h + * + * The definition of constants, data types and global variables. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#ifdef __GNUC__ +#undef __int64 +#define __int64 long long +#endif + +#ifndef _TIME_T_ +#define _TIME_T_ +typedef long time_t; +#endif + + +#ifndef __STRICT_ANSI__ + +#ifndef _OFF_T_DEFINED +typedef long _off_t; + +#ifndef _NO_OLDNAMES +#define off_t _off_t +#endif + +#define _OFF_T_DEFINED + +#endif /* Not _OFF_T_DEFINED */ + + +#ifndef _DEV_T_DEFINED +typedef short _dev_t; + +#ifndef _NO_OLDNAMES +#define dev_t _dev_t +#endif + +#define _DEV_T_DEFINED + +#endif /* Not _DEV_T_DEFINED */ + + +#ifndef _INO_T_DEFINED +typedef short _ino_t; + +#ifndef _NO_OLDNAMES +#define ino_t _ino_t +#endif + +#define _INO_T_DEFINED + +#endif /* Not _INO_T_DEFINED */ + + +#endif /* Not __STRICT_ANSI__ */ + + +#endif /* Not _TYPES_H_ */ diff --git a/include/msvcrt/sys/unistd.h b/include/msvcrt/sys/unistd.h new file mode 100644 index 0000000..21f6fd1 --- /dev/null +++ b/include/msvcrt/sys/unistd.h @@ -0,0 +1,9 @@ +/* + * This file is part of the Mingw32 package. + * + * unistd.h maps (roughly) to io.h + */ +#ifndef __STRICT_ANSI__ +#include +#endif + diff --git a/include/msvcrt/sys/utime.h b/include/msvcrt/sys/utime.h new file mode 100644 index 0000000..a2d162d --- /dev/null +++ b/include/msvcrt/sys/utime.h @@ -0,0 +1,75 @@ +/* + * utime.h + * + * Support for the utime function. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef __STRICT_ANSI__ + +#ifndef _UTIME_H_ +#define _UTIME_H_ + +#define __need_wchar_t +#define __need_size_t +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Structure used by _utime function. + */ +struct _utimbuf +{ + time_t actime; /* Access time */ + time_t modtime; /* Modification time */ +}; + +int _utime (const char* szFileName, struct _utimbuf* pTimes); +int _futime (int nHandle, struct _utimbuf *pTimes); + +/* Wide character version */ +int _wutime (const wchar_t *szFileName, struct _utimbuf *times); + +#ifndef _NO_OLDNAMES + +/* NOTE: Must be the same as _utimbuf above. */ +struct utimbuf +{ + time_t actime; + time_t modtime; +}; + +int utime (const char* szFileName, struct utimbuf* pTimes); + +#endif /* Not _NO_OLDNAMES */ + + +#ifdef __cplusplus +} +#endif + +#endif /* Not _UTIME_H_ */ +#endif /* Not __STRICT_ANSI__ */ diff --git a/include/msvcrt/time.h b/include/msvcrt/time.h new file mode 100644 index 0000000..ca4df43 --- /dev/null +++ b/include/msvcrt/time.h @@ -0,0 +1,126 @@ +/* + * time.h + * + * Date and time functions and types. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +/* Appropriated for Reactos Crtdll by Ariadne */ +#ifndef _TIME_H_ +#define _TIME_H_ + +#define __need_wchar_t +#define __need_size_t +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Number of clock ticks per second. A clock tick is the unit by which + * processor time is measured and is returned by 'clock'. + */ +#define CLOCKS_PER_SEC 1000.0 +#define CLK_TICK CLOCKS_PER_SEC + +/* + * A type for measuring processor time (in clock ticks). + */ +#ifndef _CLOCK_T_ +#define _CLOCK_T_ +typedef long clock_t; +#endif + +/* + * Need a definition of time_t. + */ +#include + +/* + * A type for storing the current time and date. This is the number of + * seconds since midnight Jan 1, 1970. + * NOTE: Normally this is defined by the above include of sys/types.h + */ +#ifndef _TIME_T_ +#define _TIME_T_ +typedef long time_t; +#endif + +/* + * A structure for storing all kinds of useful information about the + * current (or another) time. + */ +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + char *tm_zone; + int tm_gmtoff; +}; + + + +clock_t clock (void); +time_t time (time_t* tp); +double difftime (time_t t2, time_t t1); +time_t mktime (struct tm* tmsp); + +/* + * These functions write to and return pointers to static buffers that may + * be overwritten by other function calls. Yikes! + * + * NOTE: localtime, and perhaps the others of the four functions grouped + * below may return NULL if their argument is not 'acceptable'. Also note + * that calling asctime with a NULL pointer will produce an Invalid Page + * Fault and crap out your program. Guess how I know. Hint: stat called on + * a directory gives 'invalid' times in st_atime etc... + */ +char* asctime (const struct tm* tmsp); +wchar_t* _wasctime(const struct tm *timeptr); +char* ctime (const time_t* tp); +wchar_t* _wctime(const time_t * const timep); +struct tm* gmtime (const time_t* tm); +struct tm* localtime (const time_t* tm); + +char* _strdate(const char *datestr); +wchar_t* _wstrdate(const wchar_t *datestr); + +size_t strftime (char* caBuffer, size_t sizeMax, const char* szFormat, + const struct tm* tpPrint); + +size_t wcsftime (wchar_t* wcaBuffer, size_t sizeMax, + const wchar_t* wsFormat, const struct tm* tpPrint); + +char* _strtime(char* buf); +wchar_t* _wstrtime(wchar_t* buf); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/msvcrt/wchar.h b/include/msvcrt/wchar.h new file mode 100644 index 0000000..6699c37 --- /dev/null +++ b/include/msvcrt/wchar.h @@ -0,0 +1,32 @@ +/* + * wchar.h + * + * Defines of all functions for supporting wide characters. Actually it + * just includes all those headers, which is not a good thing to do from a + * processing time point of view, but it does mean that everything will be + * in sync. + * + * This file is part of the Mingw32 package. + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include +#include +#include +#include + diff --git a/include/napi/core.h b/include/napi/core.h new file mode 100644 index 0000000..ca13d20 --- /dev/null +++ b/include/napi/core.h @@ -0,0 +1,35 @@ +#ifndef __INCLUDE_NAPI_CORE_H +#define __INCLUDE_NAPI_CORE_H + +#include "../ntoskrnl/include/internal/ke.h" + +#define MM_CORE_DUMP_HEADER_MAGIC (0xdeafbead) +#define MM_CORE_DUMP_HEADER_VERSION (0x1) +#define MM_CORE_DUMP_TYPE_MINIMAL (0x1) +#define MM_CORE_DUMP_TYPE_FULL (0x2) + +typedef struct _MM_CORE_DUMP_HEADER +{ + ULONG Magic; + ULONG Version; + ULONG Type; + KTRAP_FRAME TrapFrame; + ULONG BugCheckCode; + ULONG BugCheckParameters[4]; + PVOID FaultingStackBase; + ULONG FaultingStackSize; + ULONG PhysicalMemorySize; +} MM_CORE_DUMP_HEADER, *PMM_CORE_DUMP_HEADER; + +typedef struct _MM_DUMP_POINTERS +{ + PVOID Context; + NTSTATUS (*DeviceInit)(PVOID Context); + NTSTATUS (*DeviceWrite)(PVOID Context, ULONG Block, PMDL Mdl); + NTSTATUS (*DeviceFinish)(PVOID Context); +} MM_DUMP_POINTERS, *PMM_DUMP_POINTERS; + +#define FSCTL_GET_DUMP_BLOCK_MAP (('R' << 24) | 0xF1) +#define IOCTL_GET_DUMP_POINTERS (('R' << 24) | 0xF2) + +#endif /* __INCLUDE_NAPI_CORE_H */ diff --git a/include/napi/dbg.h b/include/napi/dbg.h new file mode 100644 index 0000000..e2a51a6 --- /dev/null +++ b/include/napi/dbg.h @@ -0,0 +1,63 @@ +#ifndef __INCLUDE_NAPI_DBG_H +#define __INCLUDE_NAPI_DBG_H + +#include + +#define DBG_EVENT_EXCEPTION (1) +#define DBG_EVENT_CREATE_THREAD (2) +#define DBG_EVENT_CREATE_PROCESS (3) +#define DBG_EVENT_EXIT_THREAD (4) +#define DBG_EVENT_EXIT_PROCESS (5) +#define DBG_EVENT_LOAD_DLL (6) +#define DBG_EVENT_UNLOAD_DLL (7) + +typedef struct _LPC_DBG_MESSAGE +{ + LPC_MESSAGE_HEADER Header; + ULONG Type; + ULONG Status; + union + { + struct + { + EXCEPTION_RECORD ExceptionRecord; + ULONG FirstChance; + } Exception; + struct + { + ULONG Reserved; + PVOID StartAddress; + } CreateThread; + struct + { + ULONG Reserved; + HANDLE FileHandle; + PVOID Base; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + ULONG Reserved2; + PVOID EntryPoint; + } CreateProcess; + struct + { + ULONG ExitCode; + } ExitThread; + struct + { + ULONG ExitCode; + } ExitProcess; + struct + { + HANDLE FileHandle; + PVOID Base; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + } LoadDll; + struct + { + PVOID Base; + } UnloadDll; + } Data; +} LPC_DBG_MESSAGE, *PLPC_DBG_MESSAGE; + +#endif /* __INCLUDE_NAPI_DBG_H */ diff --git a/include/napi/i386/segment.h b/include/napi/i386/segment.h new file mode 100644 index 0000000..6034b60 --- /dev/null +++ b/include/napi/i386/segment.h @@ -0,0 +1,353 @@ +#ifndef _ASM_SEGMENT_H +#define _ASM_SEGMENT_H + +#define KERNEL_CS (0x8) +#define KERNEL_DS (0x10) +#define USER_CS (0x18 + 0x3) +#define USER_DS (0x20 + 0x3) +#define RESERVED_FOR_TSS (0x28) +#define PCR_SELECTOR (0x30) +#define TEB_SELECTOR (0x38 + 0x3) + +//#define USER_CS (0x8+0x3) +//#define USER_DS (0x10+0x3) +//#define ZERO_DS 0x18 +//#define KERNEL_CS 0x20 +//#define KERNEL_DS 0x28 + +#ifndef __ASSEMBLY__ + +/* + * Uh, these should become the main single-value transfer routines.. + * They automatically use the right size if we just have the right + * pointer type.. + */ +#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))) +#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))) + +/* + * This is a silly but good way to make sure that + * the __put_user function is indeed always optimized, + * and that we use the correct sizes.. + */ +extern int bad_user_access_length(void); + +/* + * dummy pointer type structure.. gcc won't try to do something strange + * this way.. + */ +struct __segment_dummy { unsigned long a[100]; }; +#define __sd(x) ((struct __segment_dummy *) (x)) +#define __const_sd(x) ((const struct __segment_dummy *) (x)) + +static inline void __put_user(unsigned long x, void * y, int size) +{ + switch (size) { + case 1: + __asm__ ("movb %b1,%%fs:%0" \ + :"=m" (*__sd(y)) \ + :"iq" ((unsigned char) x), "m" (*__sd(y))); + break; + case 2: + __asm__ ("movw %w1,%%fs:%0" \ + :"=m" (*__sd(y)) \ + :"ir" ((unsigned short) x), "m" (*__sd(y))); + break; + case 4: + __asm__ ("movl %1,%%fs:%0" \ + :"=m" (*__sd(y)) \ + :"ir" (x), "m" (*__sd(y))); + break; + default: + bad_user_access_length(); + } +} + +static inline unsigned long __get_user(const void * y, int size) +{ + unsigned long result; + + switch (size) { + case 1: + __asm__ ("movb %%fs:%1,%b0" \ + :"=q" (result) \ + :"m" (*__const_sd(y))); + return (unsigned char) result; + case 2: + __asm__ ("movw %%fs:%1,%w0" \ + :"=r" (result) \ + :"m" (*__const_sd(y))); + return (unsigned short) result; + case 4: + __asm__ ("movl %%fs:%1,%0" \ + :"=r" (result) \ + :"m" (*__const_sd(y))); + return result; + default: + return bad_user_access_length(); + } +} + +static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n) +{ + __asm__ volatile + (" cld \ + push %%es \ + push %%fs \ + cmpl $3,%0 \ + pop %%es \ + jbe 1f \ + movl %%edi,%%ecx \ + negl %%ecx \ + andl $3,%%ecx \ + subl %%ecx,%0 \ + rep; movsb \ + movl %0,%%ecx \ + shrl $2,%%ecx \ + rep; movsl \ + andl $3,%0 \ + 1: movl %0,%%ecx \ + rep; movsb \ + pop %%es" \ + :"=abd" (n) \ + :"0" (n),"D" ((long) to),"S" ((long) from) \ + :"cx","di","si"); +} + +static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n) +{ + switch (n) { + case 0: + return; + case 1: + __put_user(*(const char *) from, (char *) to, 1); + return; + case 2: + __put_user(*(const short *) from, (short *) to, 2); + return; + case 3: + __put_user(*(const short *) from, (short *) to, 2); + __put_user(*(2+(const char *) from), 2+(char *) to, 1); + return; + case 4: + __put_user(*(const int *) from, (int *) to, 4); + return; + case 8: + __put_user(*(const int *) from, (int *) to, 4); + __put_user(*(1+(const int *) from), 1+(int *) to, 4); + return; + case 12: + __put_user(*(const int *) from, (int *) to, 4); + __put_user(*(1+(const int *) from), 1+(int *) to, 4); + __put_user(*(2+(const int *) from), 2+(int *) to, 4); + return; + case 16: + __put_user(*(const int *) from, (int *) to, 4); + __put_user(*(1+(const int *) from), 1+(int *) to, 4); + __put_user(*(2+(const int *) from), 2+(int *) to, 4); + __put_user(*(3+(const int *) from), 3+(int *) to, 4); + return; + } +#define COMMON(x) \ +__asm__("cld\n\t" \ + "push %%es\n\t" \ + "push %%fs\n\t" \ + "pop %%es\n\t" \ + "rep ; movsl\n\t" \ + x \ + "pop %%es" \ + : /* no outputs */ \ + :"c" (n/4),"D" ((long) to),"S" ((long) from) \ + :"cx","di","si") + + switch (n % 4) { + case 0: + COMMON(""); + return; + case 1: + COMMON("movsb\n\t"); + return; + case 2: + COMMON("movsw\n\t"); + return; + case 3: + COMMON("movsw\n\tmovsb\n\t"); + return; + } +#undef COMMON +} + +static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n) +{ + __asm__ volatile + (" cld \ + cmpl $3,%0 \ + jbe 1f \ + movl %%edi,%%ecx \ + negl %%ecx \ + andl $3,%%ecx \ + subl %%ecx,%0 \ + fs; rep; movsb \ + movl %0,%%ecx \ + shrl $2,%%ecx \ + fs; rep; movsl \ + andl $3,%0 \ + 1: movl %0,%%ecx \ + fs; rep; movsb" + :"=abd" (n) + :"0" (n),"D" ((long) to),"S" ((long) from) + :"cx","di","si", "memory"); +} + +static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n) +{ + switch (n) { + case 0: + return; + case 1: + *(char *)to = __get_user((const char *) from, 1); + return; + case 2: + *(short *)to = __get_user((const short *) from, 2); + return; + case 3: + *(short *) to = __get_user((const short *) from, 2); + *((char *) to + 2) = __get_user(2+(const char *) from, 1); + return; + case 4: + *(int *) to = __get_user((const int *) from, 4); + return; + case 8: + *(int *) to = __get_user((const int *) from, 4); + *(1+(int *) to) = __get_user(1+(const int *) from, 4); + return; + case 12: + *(int *) to = __get_user((const int *) from, 4); + *(1+(int *) to) = __get_user(1+(const int *) from, 4); + *(2+(int *) to) = __get_user(2+(const int *) from, 4); + return; + case 16: + *(int *) to = __get_user((const int *) from, 4); + *(1+(int *) to) = __get_user(1+(const int *) from, 4); + *(2+(int *) to) = __get_user(2+(const int *) from, 4); + *(3+(int *) to) = __get_user(3+(const int *) from, 4); + return; + } +#define COMMON(x) \ +__asm__("cld\n\t" \ + "rep ; fs ; movsl\n\t" \ + x \ + : /* no outputs */ \ + :"c" (n/4),"D" ((long) to),"S" ((long) from) \ + :"cx","di","si","memory") + + switch (n % 4) { + case 0: + COMMON(""); + return; + case 1: + COMMON("fs ; movsb"); + return; + case 2: + COMMON("fs ; movsw"); + return; + case 3: + COMMON("fs ; movsw\n\tfs ; movsb"); + return; + } +#undef COMMON +} + +#define memcpy_fromfs(to, from, n) \ +(__builtin_constant_p(n) ? \ + __constant_memcpy_fromfs((to),(from),(n)) : \ + __generic_memcpy_fromfs((to),(from),(n))) + +#define memcpy_tofs(to, from, n) \ +(__builtin_constant_p(n) ? \ + __constant_memcpy_tofs((to),(from),(n)) : \ + __generic_memcpy_tofs((to),(from),(n))) + +/* + * These are deprecated.. + * + * Use "put_user()" and "get_user()" with the proper pointer types instead. + */ + +#define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1) +#define get_fs_word(addr) __get_user((const unsigned short *)(addr),2) +#define get_fs_long(addr) __get_user((const unsigned int *)(addr),4) + +#define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1) +#define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2) +#define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4) + +#ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE + +static inline unsigned short get_user_word(const short *addr) +{ + return __get_user(addr, 2); +} + +static inline unsigned char get_user_byte(const char * addr) +{ + return __get_user(addr,1); +} + +static inline unsigned long get_user_long(const int *addr) +{ + return __get_user(addr, 4); +} + +static inline void put_user_byte(char val,char *addr) +{ + __put_user(val, addr, 1); +} + +static inline void put_user_word(short val,short * addr) +{ + __put_user(val, addr, 2); +} + +static inline void put_user_long(unsigned long val,int * addr) +{ + __put_user(val, addr, 4); +} + +#endif + +/* + * Someone who knows GNU asm better than I should double check the following. + * It seems to work, but I don't know if I'm doing something subtly wrong. + * --- TYT, 11/24/91 + * [ nothing wrong here, Linus: I just changed the ax to be any reg ] + */ + +static inline unsigned long get_fs(void) +{ + unsigned long _v; + __asm__("mov %%fs,%w0":"=r" (_v):"0" (0)); + return _v; +} + +static inline unsigned long get_ds(void) +{ + unsigned long _v; + __asm__("mov %%ds,%w0":"=r" (_v):"0" (0)); + return _v; +} + +static inline void set_fs(unsigned long val) +{ + __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val)); +} + +static inline void set_ds(unsigned long val) +{ + __asm__ __volatile__("mov %w0,%%ds": /* no output */ :"r" (val)); +} + + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_SEGMENT_H */ diff --git a/include/napi/lpc.h b/include/napi/lpc.h new file mode 100644 index 0000000..2ee48ce --- /dev/null +++ b/include/napi/lpc.h @@ -0,0 +1,197 @@ +#ifndef __INCLUDE_NAPI_LPC_H +#define __INCLUDE_NAPI_LPC_H + +#include + +#define MAX_MESSAGE_DATA (0x130) + +typedef enum +{ + UNUSED_MSG_TYPE = 0x0, /* ReactOS */ + LPC_NEW_MESSAGE = 0x0, /* NT */ + LPC_REQUEST = 0x1, + LPC_REPLY = 0x2, + LPC_DATAGRAM = 0x3, + LPC_LOST_REPLY = 0x4, + LPC_PORT_CLOSED = 0x5, + LPC_CLIENT_DIED = 0x6, + LPC_EXCEPTION = 0x7, + LPC_DEBUG_EVENT = 0x8, + LPC_ERROR_EVENT = 0x9, + LPC_CONNECTION_REQUEST = 0xa, + LPC_CONNECTION_REFUSED = 0xb + +} LPC_TYPE, *PLPC_TYPE; + +typedef struct _LPC_SECTION_WRITE +{ + ULONG Length; + HANDLE SectionHandle; + ULONG SectionOffset; + ULONG ViewSize; + PVOID ViewBase; + PVOID TargetViewBase; +} LPC_SECTION_WRITE, *PLPC_SECTION_WRITE; + +typedef struct _LPC_SECTION_READ +{ + ULONG Length; + ULONG ViewSize; + PVOID ViewBase; +} LPC_SECTION_READ, *PLPC_SECTION_READ; + +typedef struct _LPC_MESSAGE_HEADER +{ + USHORT DataSize; + USHORT MessageSize; +// LPC_TYPE MessageType; + USHORT MessageType; + USHORT VirtualRangesOffset; + CLIENT_ID Cid; + ULONG MessageId; + ULONG SharedSectionSize; +} LPC_MESSAGE_HEADER, *PLPC_MESSAGE_HEADER; + +typedef struct _LPC_TERMINATION_MESSAGE +{ + LPC_MESSAGE_HEADER Header; + TIME CreationTime; +} LPC_TERMINATION_MESSAGE, *PLPC_TERMINATION_MESSAGE; + +typedef struct _LPC_DEBUG_MESSAGE +{ + LPC_MESSAGE_HEADER Header; + ULONG EventCode; + ULONG Status; + union { + struct { + EXCEPTION_RECORD ExceptionRecord; + ULONG FirstChance; + } Exception; + struct { + ULONG Reserved; + PVOID StartAddress; + } CreateThread; + struct { + ULONG Reserved; + HANDLE FileHandle; + PVOID Base; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + ULONG Reserved2; + PVOID EntryPoint; + } CreateProcess; + struct { + ULONG ExitCode; + } ExitThread; + struct { + ULONG ExitCode; + } ExitProcess; + struct { + HANDLE FileHandle; + PVOID Base; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + } LoadDll; + struct { + PVOID Base; + } UnloadDll; +#ifdef ANONYMOUSUNIONS + }; +#else + } u; +#endif +} LPC_DEBUG_MESSAGE, * PLPC_DEBUG_MESSAGE; + +typedef LPC_MESSAGE_HEADER LPC_MESSAGE, *PLPC_MESSAGE; + +typedef struct _LPC_MAX_MESSAGE +{ + LPC_MESSAGE_HEADER Header; + BYTE Data[MAX_MESSAGE_DATA]; +} LPC_MAX_MESSAGE, *PLPC_MAX_MESSAGE; + +#define PORT_MESSAGE_TYPE(m) (LPC_TYPE)((m).Header.MessageType) + +#ifndef __USE_NT_LPC__ +NTSTATUS STDCALL NtAcceptConnectPort (PHANDLE PortHandle, + HANDLE NamedPortHandle, + PLPC_MESSAGE ServerReply, + BOOLEAN AcceptIt, + PLPC_SECTION_WRITE WriteMap, + PLPC_SECTION_READ ReadMap); +#else +NTSTATUS STDCALL NtAcceptConnectPort (PHANDLE PortHandle, + ULONG PortIdentifier, + PLPC_MESSAGE ServerReply, + BOOLEAN AcceptIt, + PLPC_SECTION_WRITE WriteMap, + PLPC_SECTION_READ ReadMap); +#endif /* ndef __USE_NT_LPC__ */ + +NTSTATUS STDCALL NtCompleteConnectPort (HANDLE PortHandle); + +NTSTATUS STDCALL NtConnectPort(PHANDLE PortHandle, + PUNICODE_STRING PortName, + PSECURITY_QUALITY_OF_SERVICE SecurityQos, + PLPC_SECTION_WRITE SectionInfo, + PLPC_SECTION_READ MapInfo, + PULONG MaxMessageSize, + PVOID ConnectInfo, + PULONG ConnectInfoLength); + +NTSTATUS STDCALL NtReplyWaitReplyPort (HANDLE PortHandle, + PLPC_MESSAGE ReplyMessage); + +NTSTATUS STDCALL NtCreatePort(PHANDLE PortHandle, + POBJECT_ATTRIBUTES ObjectAttributes, + ULONG MaxConnectInfoLength, + ULONG MaxDataLength, + ULONG NPMessageQueueSize OPTIONAL); + +NTSTATUS STDCALL NtCreateWaitablePort(PHANDLE PortHandle, + POBJECT_ATTRIBUTES ObjectAttributes, + ULONG MaxConnectInfoLength, + ULONG MaxDataLength, + ULONG NPMessageQueueSize OPTIONAL); + +NTSTATUS STDCALL NtImpersonateClientOfPort (HANDLE PortHandle, + PLPC_MESSAGE ClientMessage); + +NTSTATUS STDCALL NtListenPort (HANDLE PortHandle, + PLPC_MESSAGE LpcMessage); + +NTSTATUS STDCALL NtQueryInformationPort (HANDLE PortHandle, + CINT PortInformationClass, + PVOID PortInformation, + ULONG PortInformationLength, + PULONG ReturnLength); +NTSTATUS STDCALL NtReplyPort (HANDLE PortHandle, + PLPC_MESSAGE LpcReply); +NTSTATUS STDCALL NtReplyWaitReceivePort (HANDLE PortHandle, + PULONG PortId, + PLPC_MESSAGE MessageReply, + PLPC_MESSAGE MessageRequest); +NTSTATUS STDCALL NtRequestPort (HANDLE PortHandle, + PLPC_MESSAGE LpcMessage); + +NTSTATUS STDCALL NtRequestWaitReplyPort (HANDLE PortHandle, + PLPC_MESSAGE LpcReply, + PLPC_MESSAGE LpcRequest); + +NTSTATUS STDCALL NtReadRequestData (HANDLE PortHandle, + PLPC_MESSAGE Message, + ULONG Index, + PVOID Buffer, + ULONG BufferLength, + PULONG ReturnLength); + +NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle, + PLPC_MESSAGE Message, + ULONG Index, + PVOID Buffer, + ULONG BufferLength, + PULONG ReturnLength); + + +#endif /* __INCLUDE_NAPI_LPC_H */ diff --git a/include/napi/npipe.h b/include/napi/npipe.h new file mode 100644 index 0000000..b89972f --- /dev/null +++ b/include/napi/npipe.h @@ -0,0 +1,196 @@ +#ifndef __INCLUDE_NAPI_NPIPE_H +#define __INCLUDE_NAPI_NPIPE_H + +#include + +/* + * FUNCTION: ZwCreateNamedPipeFile creates named pipe + * ARGUMENTS: + * NamedPipeFileHandle (OUT) = Caller supplied storage for the + * resulting handle + * DesiredAccess = Specifies the type of access that the caller + * requires to the file boject + * ObjectAttributes = Points to a structure that specifies the + * object attributes. + * IoStatusBlock = Points to a variable that receives the final + * completion status and information + * ShareAccess = Specifies the limitations on sharing of the file. + * This parameter can be zero or any compatible + * combination of the following flags + * FILE_SHARE_READ + * FILE_SHARE_WRITE + * CreateDisposition = Specifies what to do depending on whether + * the file already exists. This must be one of + * the following values + * FILE_OPEN + * FILE_CREATE + * FILE_OPEN_IF + * CreateOptions = Specifies the options to be applied when + * creating or opening the file, as a compatible + * combination of the following flags + * FILE_WRITE_THROUGH + * FILE_SYNCHRONOUS_IO_ALERT + * FILE_SYNCHRONOUS_IO_NONALERT + * TypeMessage = Specifies whether the data written to the pipe is + * interpreted as a sequence of messages or as a + * stream of bytes + * ReadModeMessage = Specifies whether the data read from the pipe + * is interpreted as a sequence of messages or as + * a stream of bytes + * NonBlocking = Specifies whether non-blocking mode is enabled + * MaxInstances = Specifies the maximum number of instancs that can + * be created for this pipe + * InBufferSize = Specifies the number of bytes to reserve for the + * input buffer + * OutBufferSize = Specifies the number of bytes to reserve for the + * output buffer + * DefaultTimeout = Optionally points to a variable that specifies + * the default timeout value in units of + * 100-nanoseconds. + * REMARKS: This funciton maps to the win32 function CreateNamedPipe + * RETURNS: + * Status + */ + +NTSTATUS STDCALL NtCreateNamedPipeFile(OUT PHANDLE NamedPipeFileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN BOOLEAN WriteModeMessage, + IN BOOLEAN ReadModeMessage, + IN BOOLEAN NonBlocking, + IN ULONG MaxInstances, + IN ULONG InBufferSize, + IN ULONG OutBufferSize, + IN PLARGE_INTEGER DefaultTimeOut); +NTSTATUS STDCALL ZwCreateNamedPipeFile(OUT PHANDLE NamedPipeFileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN BOOLEAN WriteModeMessage, + IN BOOLEAN ReadModeMessage, + IN BOOLEAN NonBlocking, + IN ULONG MaxInstances, + IN ULONG InBufferSize, + IN ULONG OutBufferSize, + IN PLARGE_INTEGER DefaultTimeOut); + +#define FSCTL_PIPE_ASSIGN_EVENT \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_DISCONNECT \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_LISTEN \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_PEEK \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 3, METHOD_BUFFERED, FILE_READ_DATA) + +#define FSCTL_PIPE_QUERY_EVENT \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_TRANSCEIVE \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 5, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) + +#define FSCTL_PIPE_WAIT \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_IMPERSONATE \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_SET_CLIENT_PROCESS \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_QUERY_CLIENT_PROCESS \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_GET_STATE \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_SET_STATE \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 11, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define FSCTL_PIPE_INTERNAL_READ \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2045, METHOD_BUFFERED, FILE_READ_DATA) + +#define FSCTL_PIPE_INTERNAL_WRITE \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2046, METHOD_BUFFERED, FILE_WRITE_DATA) + +#define FSCTL_PIPE_INTERNAL_TRANSCEIVE \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2047, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) + +#define FSCTL_PIPE_INTERNAL_READ_OVFLOW \ + CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2048, METHOD_BUFFERED, FILE_READ_DATA) + + +typedef struct _NPFS_WAIT_PIPE +{ + LARGE_INTEGER Timeout; +} NPFS_WAIT_PIPE, *PNPFS_WAIT_PIPE; + +typedef struct _NPFS_LISTEN +{ +} NPFS_LISTEN, *PNPFS_LISTEN; + +typedef struct _NPFS_SET_STATE +{ + BOOLEAN WriteModeMessage; + BOOLEAN ReadModeMessage; + BOOLEAN NonBlocking; + ULONG InBufferSize; + ULONG OutBufferSize; + LARGE_INTEGER Timeout; +} NPFS_SET_STATE, *PNPFS_SET_STATE; + +typedef struct _NPFS_GET_STATE +{ + BOOLEAN WriteModeMessage; + BOOLEAN ReadModeMessage; + BOOLEAN NonBlocking; + ULONG InBufferSize; + ULONG OutBufferSize; + LARGE_INTEGER Timeout; +} NPFS_GET_STATE, *PNPFS_GET_STATE; + +typedef struct _FILE_PIPE_PEEK_BUFFER +{ + ULONG NamedPipeState; + ULONG ReadDataAvailable; + ULONG NumberOfMessages; + ULONG MessageLength; + CHAR Data[1]; +} FILE_PIPE_PEEK_BUFFER, *PFILE_PIPE_PEEK_BUFFER; + +#define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000 +#define FILE_PIPE_MESSAGE_TYPE 0x00000001 + +#define FILE_PIPE_BYTE_STREAM_MODE 0x00000000 +#define FILE_PIPE_MESSAGE_MODE 0x00000001 + +#define FILE_PIPE_QUEUE_OPERATION 0x00000000 +#define FILE_PIPE_COMPLETE_OPERATION 0x00000001 + +#define FILE_PIPE_INBOUND 0x00000000 +#define FILE_PIPE_OUTBOUND 0x00000001 +#define FILE_PIPE_FULL_DUPLEX 0x00000002 + +#define FILE_PIPE_DISCONNECTED_STATE 0x00000001 +#define FILE_PIPE_LISTENING_STATE 0x00000002 +#define FILE_PIPE_CONNECTED_STATE 0x00000003 +#define FILE_PIPE_CLOSING_STATE 0x00000004 + +#define FILE_PIPE_CLIENT_END 0x00000000 +#define FILE_PIPE_SERVER_END 0x00000001 + +#define FILE_PIPE_READ_DATA 0x00000000 +#define FILE_PIPE_WRITE_SPACE 0x00000001 + + +#endif /* __INCLUDE_NAPI_NPIPE_H */ diff --git a/include/napi/shared_data.h b/include/napi/shared_data.h new file mode 100644 index 0000000..2387273 --- /dev/null +++ b/include/napi/shared_data.h @@ -0,0 +1,68 @@ +#ifndef __INCLUDE_NAPI_SHARED_DATA_H +#define __INCLUDE_NAPI_SHARED_DATA_H + +#define PROCESSOR_FEATURES_MAX 64 + +typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE +{ + StandardDesign, + NEC98x86, + EndAlternatives +} ALTERNATIVE_ARCHITECTURE_TYPE; + + +typedef struct _KUSER_SHARED_DATA +{ + volatile ULONG TickCountLow; + ULONG TickCountMultiplier; + volatile KSYSTEM_TIME InterruptTime; + volatile KSYSTEM_TIME SystemTime; + volatile KSYSTEM_TIME TimeZoneBias; + USHORT ImageNumberLow; + USHORT ImageNumberHigh; + WCHAR NtSystemRoot[260]; + ULONG DosDeviceMap; + ULONG CryptoExponent; + ULONG TimeZoneId; + UCHAR DosDeviceDriveType[32]; + NT_PRODUCT_TYPE NtProductType; + BOOLEAN ProductTypeIsValid; + ULONG NtMajorVersion; + ULONG NtMinorVersion; + BOOLEAN ProcessorFeatures[PROCESSOR_FEATURES_MAX]; + + // NT5 / Win2k specific ?? + ULONG Reserved1; + ULONG Reserved3; + volatile ULONG TimeSlip; + ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; + ULONG SuiteMask; +#ifdef REMOTE_BOOT + ULONG SystemFlags; + UCHAR RemoteBootServerPath[260]; +#endif + BOOLEAN KdDebuggerEnabled; +} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; + +/* Values for DosDeviceDriveType */ +#define DOSDEVICE_DRIVE_UNKNOWN 0 +#define DOSDEVICE_DRIVE_CALCULATE 1 +#define DOSDEVICE_DRIVE_REMOVABLE 2 +#define DOSDEVICE_DRIVE_FIXED 3 +#define DOSDEVICE_DRIVE_REMOTE 4 +#define DOSDEVICE_DRIVE_CDROM 5 +#define DOSDEVICE_DRIVE_RAMDISK 6 + + +#define KERNEL_SHARED_DATA (0xFFDF0000) +#define USER_SHARED_DATA (0x7FFE0000) + +#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) +#define KI_USER_SHARED_DATA (0xFFDF0000) +#define SharedUserData ((KUSER_SHARED_DATA * const)KI_USER_SHARED_DATA) +#else +#define SharedUserData ((KUSER_SHARED_DATA * const)USER_SHARED_DATA) +#endif + + +#endif /* __INCLUDE_NAPI_SHARED_DATA_H */ diff --git a/include/napi/teb.h b/include/napi/teb.h new file mode 100644 index 0000000..05962c2 --- /dev/null +++ b/include/napi/teb.h @@ -0,0 +1,233 @@ +/* TEB/PEB parameters */ +#ifndef __INCLUDE_INTERNAL_TEB +#define __INCLUDE_INTERNAL_TEB + +#include + +typedef struct _CLIENT_ID +{ + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + +typedef struct _CURDIR +{ + UNICODE_STRING DosPath; + PVOID Handle; +} CURDIR, *PCURDIR; + +typedef struct RTL_DRIVE_LETTER_CURDIR +{ + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + UNICODE_STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + +typedef struct _PEB_FREE_BLOCK +{ + struct _PEB_FREE_BLOCK* Next; + ULONG Size; +} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; + +/* RTL_USER_PROCESS_PARAMETERS.Flags */ +#define PPF_NORMALIZED (1) + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + ULONG AllocationSize; + ULONG Size; + ULONG Flags; + ULONG DebugFlags; + HANDLE hConsole; + ULONG ProcessGroup; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; + UNICODE_STRING CurrentDirectoryName; + HANDLE CurrentDirectoryHandle; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PWSTR Environment; + ULONG dwX; + ULONG dwY; + ULONG dwXSize; + ULONG dwYSize; + ULONG dwXCountChars; + ULONG dwYCountChars; + ULONG dwFillAttribute; + ULONG dwFlags; + ULONG wShowWindow; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeInfo; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +#define PEB_BASE (0x7FFDF000) + +typedef struct _PEB_LDR_DATA +{ + ULONG Length; + BOOLEAN Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef VOID STDCALL (*PPEBLOCKROUTINE)(PVOID); + +typedef struct _PEB +{ + UCHAR InheritedAddressSpace; // 00h + UCHAR ReadImageFileExecOptions; // 01h + UCHAR BeingDebugged; // 02h + UCHAR Spare; // 03h + PVOID Mutant; // 04h + PVOID ImageBaseAddress; // 08h + PPEB_LDR_DATA Ldr; // 0Ch + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 10h + PVOID SubSystemData; // 14h + PVOID ProcessHeap; // 18h + PVOID FastPebLock; // 1Ch + PPEBLOCKROUTINE FastPebLockRoutine; // 20h + PPEBLOCKROUTINE FastPebUnlockRoutine; // 24h + ULONG EnvironmentUpdateCount; // 28h + PVOID* KernelCallbackTable; // 2Ch + PVOID EventLogSection; // 30h + PVOID EventLog; // 34h + PPEB_FREE_BLOCK FreeList; // 38h + ULONG TlsExpansionCounter; // 3Ch + PVOID TlsBitmap; // 40h + ULONG TlsBitmapBits[0x2]; // 44h + PVOID ReadOnlySharedMemoryBase; // 4Ch + PVOID ReadOnlySharedMemoryHeap; // 50h + PVOID* ReadOnlyStaticServerData; // 54h + PVOID AnsiCodePageData; // 58h + PVOID OemCodePageData; // 5Ch + PVOID UnicodeCaseTableData; // 60h + ULONG NumberOfProcessors; // 64h + ULONG NtGlobalFlag; // 68h + UCHAR Spare2[0x4]; // 6Ch + LARGE_INTEGER CriticalSectionTimeout; // 70h + ULONG HeapSegmentReserve; // 78h + ULONG HeapSegmentCommit; // 7Ch + ULONG HeapDeCommitTotalFreeThreshold; // 80h + ULONG HeapDeCommitFreeBlockThreshold; // 84h + ULONG NumberOfHeaps; // 88h + ULONG MaximumNumberOfHeaps; // 8Ch + PVOID** ProcessHeaps; // 90h + PVOID GdiSharedHandleTable; // 94h + PVOID ProcessStarterHelper; // 98h + PVOID GdiDCAttributeList; // 9Ch + PVOID LoaderLock; // A0h + ULONG OSMajorVersion; // A4h + ULONG OSMinorVersion; // A8h + ULONG OSBuildNumber; // ACh + ULONG OSPlatformId; // B0h + ULONG ImageSubSystem; // B4h + ULONG ImageSubSystemMajorVersion; // B8h + ULONG ImageSubSystemMinorVersion; // C0h + ULONG GdiHandleBuffer[0x22]; // C4h +} PEB, *PPEB; + + +typedef struct _NT_TIB { + struct _EXCEPTION_REGISTRATION_RECORD* ExceptionList; // 00h + PVOID StackBase; // 04h + PVOID StackLimit; // 08h + PVOID SubSystemTib; // 0Ch + union { + PVOID FiberData; // 10h + ULONG Version; // 10h + } Fib; + PVOID ArbitraryUserPointer; // 14h + struct _NT_TIB *Self; // 18h +} NT_TIB, *PNT_TIB; + +typedef struct _GDI_TEB_BATCH +{ + ULONG Offset; + ULONG HDC; + ULONG Buffer[0x136]; +} GDI_TEB_BATCH, *PGDI_TEB_BATCH; + +typedef struct _TEB +{ + NT_TIB Tib; // 00h + PVOID EnvironmentPointer; // 1Ch + CLIENT_ID Cid; // 20h + PVOID ActiveRpcInfo; // 28h + PVOID ThreadLocalStoragePointer; // 2Ch + PPEB Peb; // 30h + ULONG LastErrorValue; // 34h + ULONG CountOfOwnedCriticalSections; // 38h + PVOID CsrClientThread; // 3Ch + struct _W32THREAD* Win32ThreadInfo; // 40h + ULONG Win32ClientInfo[0x1F]; // 44h + PVOID WOW32Reserved; // C0h + ULONG CurrentLocale; // C4h + ULONG FpSoftwareStatusRegister; // C8h + PVOID SystemReserved1[0x36]; // CCh + PVOID Spare1; // 1A4h + LONG ExceptionCode; // 1A8h + ULONG SpareBytes1[0x28]; // 1ACh + PVOID SystemReserved2[0xA]; // 1D4h +// GDI_TEB_BATCH GdiTebBatch; // 1FCh + ULONG gdiRgn; // 6DCh + ULONG gdiPen; // 6E0h + ULONG gdiBrush; // 6E4h + CLIENT_ID RealClientId; // 6E8h + PVOID GdiCachedProcessHandle; // 6F0h + ULONG GdiClientPID; // 6F4h + ULONG GdiClientTID; // 6F8h + PVOID GdiThreadLocaleInfo; // 6FCh + PVOID UserReserved[5]; // 700h + PVOID glDispatchTable[0x118]; // 714h + ULONG glReserved1[0x1A]; // B74h + PVOID glReserved2; // BDCh + PVOID glSectionInfo; // BE0h + PVOID glSection; // BE4h + PVOID glTable; // BE8h + PVOID glCurrentRC; // BECh + PVOID glContext; // BF0h + NTSTATUS LastStatusValue; // BF4h + UNICODE_STRING StaticUnicodeString; // BF8h + WCHAR StaticUnicodeBuffer[0x105]; // C00h + PVOID DeallocationStack; // E0Ch + PVOID TlsSlots[0x40]; // E10h + LIST_ENTRY TlsLinks; // F10h + PVOID Vdm; // F18h + PVOID ReservedForNtRpc; // F1Ch + PVOID DbgSsReserved[0x2]; // F20h + ULONG HardErrorDisabled; // F28h + PVOID Instrumentation[0x10]; // F2Ch + PVOID WinSockData; // F6Ch + ULONG GdiBatchCount; // F70h + ULONG Spare2; // F74h + ULONG Spare3; // F78h + ULONG Spare4; // F7Ch + PVOID ReservedForOle; // F80h + ULONG WaitingOnLoaderLock; // F84h + PVOID WineDebugInfo; // Needed for WINE DLL's +} TEB, *PTEB; + + +#define NtCurrentPeb() (NtCurrentTeb()->Peb) + +static inline PTEB NtCurrentTeb(VOID) +{ + int x; + + __asm__ __volatile__("movl %%fs:0x18, %0\n\t" + : "=r" (x) /* can't have two memory operands */ + : /* no inputs */ + ); + + return((PTEB)x); +} + + + +#endif /* __INCLUDE_INTERNAL_TEB */ diff --git a/include/napi/types.h b/include/napi/types.h new file mode 100644 index 0000000..694ae40 --- /dev/null +++ b/include/napi/types.h @@ -0,0 +1,108 @@ +#ifndef __INCLUDE_NAPI_TYPES_H +#define __INCLUDE_NAPI_TYPES_H + +// these should be moved to a file like ntdef.h + +typedef const int CINT; + +typedef LONG NTSTATUS, *PNTSTATUS; + +typedef ULONG DEVICE_TYPE; + + + + + +enum +{ + DIRECTORY_QUERY, + DIRECTORY_TRAVERSE, + DIRECTORY_CREATE_OBJECT, + DIRECTORY_CREATE_SUBDIRECTORY, + DIRECTORY_ALL_ACCESS, +}; + +/* + * General type for status information + */ +//typedef LONG NTSTATUS; + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef enum _SECTION_INHERIT { + ViewShare = 1, + ViewUnmap = 2 +} SECTION_INHERIT; + +typedef enum _NT_PRODUCT_TYPE +{ + NtProductWinNt = 1, + NtProductLanManNt, + NtProductServer +} NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; + +/* File information for IRP_MJ_QUERY_INFORMATION (and SET) */ +typedef enum _FILE_INFORMATION_CLASS +{ + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileCopyOnWriteInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileOleClassIdInformation, + FileOleStateBitsInformation, + FileNetworkOpenInformation, + FileObjectIdInformation, + FileOleAllInformation, + FileOleDirectoryInformation, + FileContentIndexInformation, + FileInheritContentIndexInformation, + FileOleInformation, + FileMaximumInformation, +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +typedef ULONG WAIT_TYPE; +typedef USHORT CSHORT; + + +#if 0 +typedef struct _TIME { + DWORD LowPart; + LONG HighPart; +} TIME, *PTIME; +#endif + +typedef ULARGE_INTEGER TIME, *PTIME; + +#endif /* __INCLUDE_NAPI_TYPES_H */ diff --git a/include/napi/win32.h b/include/napi/win32.h new file mode 100644 index 0000000..948d28e --- /dev/null +++ b/include/napi/win32.h @@ -0,0 +1,24 @@ +#ifndef __INCLUDE_NAPI_WIN32_H +#define __INCLUDE_NAPI_WIN32_H + +typedef struct _W32THREAD +{ + PVOID MessageQueue; + FAST_MUTEX WindowListLock; + LIST_ENTRY WindowListHead; + struct _DESKTOP_OBJECT* Desktop; +} __attribute__((packed)) W32THREAD, *PW32THREAD; + +typedef struct _W32PROCESS +{ + FAST_MUTEX ClassListLock; + LIST_ENTRY ClassListHead; + struct _WINSTATION_OBJECT* WindowStation; +} W32PROCESS, *PW32PROCESS; + +PW32THREAD STDCALL +PsGetWin32Thread(VOID); +PW32PROCESS STDCALL +PsGetWin32Process(VOID); + +#endif /* __INCLUDE_NAPI_WIN32_H */ diff --git a/include/net/miniport.h b/include/net/miniport.h new file mode 100644 index 0000000..533a8ff --- /dev/null +++ b/include/net/miniport.h @@ -0,0 +1,849 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/net/miniport.h + * PURPOSE: Type definitions available only to NDIS miniport drivers + */ +#ifndef __MINIPORT_H +#define __MINIPORT_H + +#ifdef _MSC_VER +#include +#else /* _MSC_VER */ +#include +#endif /* _MSC_VER */ + +/* Base types */ + +#define IN +#define OUT +#define OPTIONAL + +#define ANYSIZE_ARRAY 1 + +#define CONST const + +#ifdef _MSC_VER + +#ifdef i386 +#define STDCALL _stdcall +#define CDECL _cdecl +#else /* i386 */ +#define STDCALL +#define CDECL +#endif /* i386 */ + +#else /* _MSC_VER */ + +#ifdef i386 +#define STDCALL __attribute__ ((stdcall)) +#define CDECL __attribute__ ((cdecl)) +#else /* i386 */ +#define STDCALL +#define CDECL +#endif /* i386 */ + +#endif /* _MSC_VER */ + +typedef void VOID, *PVOID; +typedef char CHAR, *PCHAR; +typedef unsigned char UCHAR, *PUCHAR; +typedef short SHORT, *PSHORT; +typedef unsigned short USHORT, *PUSHORT; +typedef long LONG,*PLONG; +typedef unsigned long ULONG,*PULONG; +typedef double DOUBLE, *PDOUBLE; +typedef struct _QUAD { + double DoNotUseThisField; +} QUAD,*PQUAD; +typedef QUAD UQUAD, *PUQUAD; +typedef signed int INT, *PINT; +typedef unsigned int UINT, *PUINT; +typedef double LONGLONG, *PLONGLONG; +typedef double ULONGLONG, *PULONGLONG; + +typedef UCHAR BOOLEAN, *PBOOLEAN; +typedef ULONG DWORD, *PDWORD; + +/* Cardinal types */ +typedef CHAR CCHAR, *PCCHAR; +typedef SHORT CSHORT, *PCSHORT; +typedef ULONG CLONG, *PCLONG; + +/* UNICODE (wide character) types */ +#ifndef __cplusplus +typedef short unsigned int wchar_t; +#endif /* __cplusplus */ +typedef wchar_t WCHAR; +typedef WCHAR *PWCHAR; +typedef WCHAR *LPWCH, *PWCH; +typedef CONST WCHAR *LPCWCH, *PCWCH; +typedef WCHAR *NWPSTR; +typedef WCHAR *LPWSTR, *PWSTR; +typedef CONST WCHAR *LPCWSTR, *PCWSTR; + +/* ANSI (multi-byte character) types */ +typedef CHAR *LPCH, *PCH; +typedef CONST CHAR *LPCCH, *PCCH; +typedef CHAR *NPSTR; +typedef CHAR *LPSTR, *PSTR; +typedef CONST CHAR *LPCSTR, *PCSTR; + +/* Neutral ANSI/UNICODE types */ +#ifdef UNICODE + +typedef WCHAR TCHAR, *PTCHAR; +typedef WCHAR TUCHAR, *PTUCHAR; + +typedef LPWSTR LPTCH, PTCH; +typedef LPWSTR PTSTR, LPTSTR; +typedef LPCWSTR LPCTSTR; +typedef LPWSTR LP; +#define _TEXT(string) L##string +#define _T(string) L##string + +#else /* UNICODE */ + +typedef CHAR TCHAR, *PTCHAR; +typedef UCHAR TUCHAR, *PTUCHAR; + +typedef LPSTR LPTCH, PTCH; +typedef LPSTR PTSTR, LPTSTR; +typedef LPCSTR LPCTSTR; +#define _TEXT(string) string +#define _T(string) string + +#endif /* UNICODE */ + +#define TEXT(string) __TEXT(string) + + +typedef union _LARGE_INTEGER { + struct { + ULONG LowPart; + LONG HighPart; + }; + struct { + ULONG LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; +} LARGE_INTEGER; + +typedef LARGE_INTEGER *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER { + struct { + ULONG LowPart; + ULONG HighPart; + }; + struct { + ULONG LowPart; + ULONG HighPart; + } u; + ULONGLONG QuadPart; +} ULARGE_INTEGER; + +typedef ULARGE_INTEGER *PULARGE_INTEGER; + + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; + + + +/* NT status type and macros for checking status */ +typedef LONG NTSTATUS; +typedef NTSTATUS *PNTSTATUS; + +#ifdef _MSC_VER +#define NT_SUCCESS(Status) ((ULONG)(Status) >= 0) +#endif /* _MSC_VER */ +#define NT_INFORMATION(Status) ((ULONG)(Status) >> 30 == 1) +#define NT_WARNING(Status) ((ULONG)(Status) >> 30 == 2) +#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3) + +#define APPLICATION_ERROR_MASK 0x20000000 +#define ERROR_SEVERITY_SUCCESS 0x00000000 +#define ERROR_SEVERITY_INFORMATIONAL 0x40000000 +#define ERROR_SEVERITY_WARNING 0x80000000 +#define ERROR_SEVERITY_ERROR 0xC0000000 + + + +/* Basic constants */ + +#define FALSE 0 +#define TRUE 1 + +#define NULL ((PVOID)0) + + + +/* Counted strings */ + +typedef struct _STRING +{ + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +} STRING, *PSTRING; + +typedef STRING ANSI_STRING, *PANSI_STRING; +typedef STRING OEM_STRING, *POEM_STRING; + +#define ANSI_NULL ((CHAR)0) + +typedef struct _CSTRING +{ + USHORT Length; + USHORT MaximumLength; + CONST CHAR *Buffer; +} CSTRING, *PCSTRING; + +typedef CSTRING CANSI_STRING, *PCANSI_STRING; + + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _CUNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + CONST PWSTR Buffer; +} CUNICODE_STRING, *PCUNICODE_STRING; + +#define UNICODE_NULL ((WCHAR)0) + + + +/* Linked lists */ + +typedef struct _LIST_ENTRY +{ + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _SINGLE_LIST_ENTRY +{ + struct _SINGLE_LIST_ENTRY *Next; +} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; + + +/* + * VOID InitializeListHead( + * PLIST_ENTRY ListHead); + */ +#define InitializeListHead(ListHead) \ +{ \ + (ListHead)->Flink = (ListHead); \ + (ListHead)->Blink = (ListHead); \ +} + + +/* + * VOID InsertHeadList( + * LIST_ENTRY ListHead, + * PLIST_ENTRY Entry); + */ +#define InsertHeadList(ListHead, ListEntry) \ +{ \ + PLIST_ENTRY OldFlink; \ + OldFlink = (ListHead)->Flink; \ + (ListEntry)->Flink = OldFlink; \ + (ListEntry)->Blink = (ListHead); \ + OldFlink->Blink = (ListEntry); \ + (ListHead)->Flink = (ListEntry); \ +} + + +/* + * VOID InsertTailList( + * PLIST_ENTRY ListHead, + * PLIST_ENTRY Entry); + */ +#define InsertTailList(ListHead, ListEntry) \ +{ \ + PLIST_ENTRY OldBlink; \ + OldBlink = (ListHead)->Blink; \ + (ListEntry)->Flink = (ListHead); \ + (ListEntry)->Blink = OldBlink; \ + OldBlink->Flink = (ListEntry); \ + (ListHead)->Blink = (ListEntry); \ +} + +/* + * BOOLEAN IsListEmpty( + * PLIST_ENTRY ListHead); + */ +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + + +/* + * PSINGLE_LIST_ENTRY PopEntryList( + * PSINGLE_LIST_ENTRY ListHead); + */ +#define PopEntryList(ListHead) \ + (ListHead)->Next; \ +{ \ + PSINGLE_LIST_ENTRY FirstEntry; \ + \ + FirstEntry = (ListHead)->Next; \ + if (FirstEntry != NULL) \ + { \ + (ListHead)->Next = FirstEntry->Next; \ + } \ +} + + +/* + * VOID PushEntryList( + * PSINGLE_LIST_ENTRY ListHead, + * PSINGLE_LIST_ENTRY Entry); + */ +#define PushEntryList(ListHead, Entry) \ + (Entry)->Next = (ListHead)->Next; \ + (ListHead)->Next = (Entry) + + +/* + * VOID RemoveEntryList( + * PLIST_ENTRY Entry); + */ +#define RemoveEntryList(ListEntry) \ +{ \ + PLIST_ENTRY OldFlink; \ + PLIST_ENTRY OldBlink; \ + OldFlink = (ListEntry)->Flink; \ + OldBlink = (ListEntry)->Blink; \ + OldFlink->Blink = OldBlink; \ + OldBlink->Flink = OldFlink; \ +} + + +/* + * PLIST_ENTRY RemoveHeadList( + * PLIST_ENTRY ListHead); + */ +#define RemoveHeadList(ListHead) \ + (ListHead)->Flink; \ +{ \ + RemoveEntryList((ListHead)->Flink) \ +} + + +/* + * PLIST_ENTRY RemoveTailList( + * PLIST_ENTRY ListHead); + */ +#define RemoveTailList(ListHead) \ + (ListHead)->Blink; \ +{ \ + RemoveEntryList((ListHead)->Blink) \ +} + + +/* Hardware */ + +typedef UCHAR KIRQL, *PKIRQL; + +typedef struct _KSPIN_LOCK +{ + ULONG Lock; +} KSPIN_LOCK, *PKSPIN_LOCK; + + +typedef struct _ADAPTER_OBJECT *PADAPTER_OBJECT; +typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT; +typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; +typedef struct _FILE_OBJECT *PFILE_OBJECT; + +typedef struct _KINTERRUPT *PKINTERRUPT; + + +/* Memory Descriptor List */ +typedef struct _MDL { + struct _MDL *Next; + CSHORT Size; + CSHORT MdlFlags; + struct _EPROCESS *Process; + PVOID MappedSystemVa; + PVOID StartVa; + ULONG ByteCount; + ULONG ByteOffset; +} MDL, *PMDL; + +#define MDL_MAPPED_TO_SYSTEM_VA 0x0001 +#define MDL_PAGES_LOCKED 0x0002 +#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 +#define MDL_ALLOCATED_FIXED_SIZE 0x0008 +#define MDL_PARTIAL 0x0010 +#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 +#define MDL_IO_PAGE_READ 0x0040 +#define MDL_WRITE_OPERATION 0x0080 +#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100 +#define MDL_LOCK_HELD 0x0200 +#define MDL_PHYSICAL_VIEW 0x0400 +#define MDL_IO_SPACE 0x0800 +#define MDL_NETWORK_HEADER 0x1000 +#define MDL_MAPPING_CAN_FAIL 0x2000 +#define MDL_ALLOCATED_MUST_SUCCEED 0x4000 + + +#define MDL_MAPPING_FLAGS (MDL_MAPPED_TO_SYSTEM_VA | \ + MDL_PAGES_LOCKED | \ + MDL_SOURCE_IS_NONPAGED_POOL | \ + MDL_PARTIAL_HAS_BEEN_MAPPED | \ + MDL_PARENT_MAPPED_SYSTEM_VA | \ + MDL_LOCK_HELD | \ + MDL_SYSTEM_VA | \ + MDL_IO_SPACE ) + + +typedef struct _DISPATCHER_HEADER +{ + UCHAR Type; + UCHAR Absolute; + UCHAR Size; + UCHAR Inserted; + LONG SignalState; + LIST_ENTRY WaitListHead; +} DISPATCHER_HEADER; + +typedef struct _KEVENT +{ + DISPATCHER_HEADER Header; +} KEVENT, *PKEVENT; + + +typedef struct _KTIMER +{ + DISPATCHER_HEADER Header; + ULARGE_INTEGER DueTime; + LIST_ENTRY TimerListEntry; + struct _KDPC *Dpc; + LONG Period; +} KTIMER, *PKTIMER; + + +typedef enum _KDPC_IMPORTANCE +{ + LowImportance, + MediumImportance, + HighImportance +} KDPC_IMPORTANCE; + +/* Forward declaration */ +struct _KDPC; + +typedef VOID (*PKDEFERRED_ROUTINE)( + IN struct _KDPC *Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2); + +/* Deferred Procedure Call */ + +typedef struct _KDPC { + CSHORT Type; + UCHAR Number; + UCHAR Importance; + LIST_ENTRY DpcListEntry; + PKDEFERRED_ROUTINE DeferredRoutine; + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + PULONG Lock; +} KDPC, *PKDPC; + + +typedef enum _INTERFACE_TYPE +{ + InterfaceTypeUndefined = -1, + Internal, + Isa, + Eisa, + MicroChannel, + TurboChannel, + PCIBus, + VMEBus, + NuBus, + PCMCIABus, + CBus, + MPIBus, + MPSABus, + ProcessorInternal, + InternalPowerBus, + PNPISABus, + MaximumInterfaceType +} INTERFACE_TYPE, *PINTERFACE_TYPE; + + +typedef enum _DMA_WIDTH +{ + Width8Bits, + Width16Bits, + Width32Bits, + MaximumDmaWidth +} DMA_WIDTH, *PDMA_WIDTH; + +typedef enum _DMA_SPEED +{ + Compatible, + TypeA, + TypeB, + TypeC, + TypeF, + MaximumDmaSpeed +} DMA_SPEED, *PDMA_SPEED; + + +typedef enum _KINTERRUPT_MODE +{ + LevelSensitive, + Latched +} KINTERRUPT_MODE; + + +typedef struct _DMA_CONFIGURATION_BYTE0 +{ + UCHAR Channel:3; + UCHAR Reserved:3; + UCHAR Shared:1; + UCHAR MoreEntries:1; +} DMA_CONFIGURATION_BYTE0; + +typedef struct _DMA_CONFIGURATION_BYTE1 +{ + UCHAR Reserved0:2; + UCHAR TransferSize:2; + UCHAR Timing:2; + UCHAR Reserved1:2; +} DMA_CONFIGURATION_BYTE1; + + +typedef struct _CM_MCA_POS_DATA +{ + USHORT AdapterId; + UCHAR PosData1; + UCHAR PosData2; + UCHAR PosData3; + UCHAR PosData4; +} CM_MCA_POS_DATA, *PCM_MCA_POS_DATA; + +typedef struct _EISA_MEMORY_TYPE +{ + UCHAR ReadWrite:1; + UCHAR Cached:1; + UCHAR Reserved0:1; + UCHAR Type:2; + UCHAR Shared:1; + UCHAR Reserved1:1; + UCHAR MoreEntries:1; +} EISA_MEMORY_TYPE, *PEISA_MEMORY_TYPE; + +typedef struct _EISA_MEMORY_CONFIGURATION +{ + EISA_MEMORY_TYPE ConfigurationByte; + UCHAR DataSize; + USHORT AddressLowWord; + UCHAR AddressHighByte; + USHORT MemorySize; +} EISA_MEMORY_CONFIGURATION, *PEISA_MEMORY_CONFIGURATION; + + +typedef struct _EISA_IRQ_DESCRIPTOR +{ + UCHAR Interrupt:4; + UCHAR Reserved:1; + UCHAR LevelTriggered:1; + UCHAR Shared:1; + UCHAR MoreEntries:1; +} EISA_IRQ_DESCRIPTOR, *PEISA_IRQ_DESCRIPTOR; + +typedef struct _EISA_IRQ_CONFIGURATION +{ + EISA_IRQ_DESCRIPTOR ConfigurationByte; + UCHAR Reserved; +} EISA_IRQ_CONFIGURATION, *PEISA_IRQ_CONFIGURATION; + +typedef struct _EISA_DMA_CONFIGURATION +{ + DMA_CONFIGURATION_BYTE0 ConfigurationByte0; + DMA_CONFIGURATION_BYTE1 ConfigurationByte1; +} EISA_DMA_CONFIGURATION, *PEISA_DMA_CONFIGURATION; + + +typedef struct _EISA_PORT_DESCRIPTOR +{ + UCHAR NumberPorts:5; + UCHAR Reserved:1; + UCHAR Shared:1; + UCHAR MoreEntries:1; +} EISA_PORT_DESCRIPTOR, *PEISA_PORT_DESCRIPTOR; + +typedef struct _EISA_PORT_CONFIGURATION +{ + EISA_PORT_DESCRIPTOR Configuration; + USHORT PortAddress; +} EISA_PORT_CONFIGURATION, *PEISA_PORT_CONFIGURATION; + +typedef struct _CM_EISA_SLOT_INFORMATION +{ + UCHAR ReturnCode; + UCHAR ReturnFlags; + UCHAR MajorRevision; + UCHAR MinorRevision; + USHORT Checksum; + UCHAR NumberFunctions; + UCHAR FunctionInformation; + ULONG CompressedId; +} CM_EISA_SLOT_INFORMATION, *PCM_EISA_SLOT_INFORMATION; + +typedef struct _CM_EISA_FUNCTION_INFORMATION +{ + ULONG CompressedId; + UCHAR IdSlotFlags1; + UCHAR IdSlotFlags2; + UCHAR MinorRevision; + UCHAR MajorRevision; + UCHAR Selections[26]; + UCHAR FunctionFlags; + UCHAR TypeString[80]; + EISA_MEMORY_CONFIGURATION EisaMemory[9]; + EISA_IRQ_CONFIGURATION EisaIrq[7]; + EISA_DMA_CONFIGURATION EisaDma[4]; + EISA_PORT_CONFIGURATION EisaPort[20]; + UCHAR InitializationData[60]; +} CM_EISA_FUNCTION_INFORMATION, *PCM_EISA_FUNCTION_INFORMATION; + + +typedef struct _CM_PARTIAL_RESOURCE_DESCRIPTOR +{ + UCHAR Type; + UCHAR ShareDisposition; + USHORT Flags; + union { + struct { + PHYSICAL_ADDRESS Start; + ULONG Length; + } Generic; + + struct { + PHYSICAL_ADDRESS Start; + ULONG Length; + } Port; + + struct { + ULONG Level; + ULONG Vector; + ULONG Affinity; + } Interrupt; + + struct { + PHYSICAL_ADDRESS Start; + ULONG Length; + } Memory; + + struct { + ULONG Channel; + ULONG Port; + ULONG Reserved1; + } Dma; + + struct { + ULONG Data[3]; + } DevicePrivate; + + struct { + ULONG Start; + ULONG Length; + ULONG Reserved; + } BusNumber; + + struct { + ULONG DataSize; + ULONG Reserved1; + ULONG Reserved2; + } DeviceSpecificData; + } u; +} CM_PARTIAL_RESOURCE_DESCRIPTOR, *PCM_PARTIAL_RESOURCE_DESCRIPTOR; + +typedef struct _CM_PARTIAL_RESOURCE_LIST +{ + USHORT Version; + USHORT Revision; + ULONG Count; + CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; +} CM_PARTIAL_RESOURCE_LIST, *PCM_PARTIAL_RESOURCE_LIST; + +typedef struct _CM_FULL_RESOURCE_DESCRIPTOR +{ + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + CM_PARTIAL_RESOURCE_LIST PartialResourceList; +} CM_FULL_RESOURCE_DESCRIPTOR, *PCM_FULL_RESOURCE_DESCRIPTOR; + +typedef struct _CM_RESOURCE_LIST +{ + ULONG Count; + CM_FULL_RESOURCE_DESCRIPTOR List[1]; +} CM_RESOURCE_LIST, *PCM_RESOURCE_LIST; + + + +/* Operating System services */ + +/* Debugging */ + +ULONG CDECL DbgPrint( + PCH Format, + ...); + +#ifdef DBG + +VOID +STDCALL +RtlAssert( + PVOID FailedAssertion, + PVOID FileName, + ULONG LineNumber, + PCHAR Message); + +#define ASSERT(exp) \ + if (!(exp)) \ + RtlAssert(#exp, __FILE__, __LINE__, NULL) + +#define ASSERTMSG(msg, exp) \ + if (!(exp)) \ + RtlAssert(#exp, __FILE__, __LINE__, msg) + +#else /* DBG */ + +#define ASSERT(exp) +#define ASSERTMSG(msg, exp) + +#endif /* DBG */ + + +/* Runtime library */ + +#define RtlEqualMemory(Destination,Source,Length) (!memcmp((Destination), (Source), (Length))) +#define RtlMoveMemory(Destination,Source,Length) memmove((Destination), (Source), (Length)) +#define RtlCopyMemory(Destination,Source,Length) memcpy((Destination), (Source), (Length)) +#define RtlFillMemory(Destination,Length,Fill) memset((Destination), (Fill),(Length)) +#define RtlZeroMemory(Destination,Length) memset((Destination), 0, (Length)) + + +/* Core kernel functions */ + +VOID +STDCALL +KeStallExecutionProcessor( + ULONG MicroSeconds); + + +/* I/O functions */ + +VOID +STDCALL +READ_PORT_BUFFER_UCHAR( + PUCHAR Port, + PUCHAR Value, + ULONG Count); + +VOID +STDCALL +READ_PORT_BUFFER_ULONG( + PULONG Port, + PULONG Value, + ULONG Count); + +VOID +STDCALL +READ_PORT_BUFFER_USHORT( + PUSHORT Port, + PUSHORT Value, + ULONG Count); + +UCHAR +STDCALL +READ_PORT_UCHAR( + PUCHAR Port); + +ULONG +STDCALL +READ_PORT_ULONG( + PULONG Port); + +USHORT +STDCALL +READ_PORT_USHORT( + PUSHORT Port); + +VOID +STDCALL +WRITE_PORT_BUFFER_UCHAR( + PUCHAR Port, + PUCHAR Value, + ULONG Count); + +VOID +STDCALL +WRITE_PORT_BUFFER_ULONG( + PULONG Port, + PULONG Value, + ULONG Count); + +VOID +STDCALL +WRITE_PORT_BUFFER_USHORT( + PUSHORT Port, + PUSHORT Value, + ULONG Count); + +VOID +STDCALL +WRITE_PORT_UCHAR( + PUCHAR Port, + UCHAR Value); + +VOID +STDCALL +WRITE_PORT_ULONG( + PULONG Port, + ULONG Value); + +VOID +STDCALL +WRITE_PORT_USHORT( + PUSHORT Port, + USHORT Value); + +VOID +STDCALL +WRITE_REGISTER_UCHAR( + PUCHAR Register, + UCHAR Value); + +VOID +STDCALL +WRITE_REGISTER_ULONG( + PULONG Register, + ULONG Value); + +VOID +STDCALL +WRITE_REGISTER_USHORT( + PUSHORT Register, + USHORT Value); + +#endif /* __MINIPORT_H */ + +/* EOF */ diff --git a/include/net/ndis.h b/include/net/ndis.h new file mode 100644 index 0000000..a018457 --- /dev/null +++ b/include/net/ndis.h @@ -0,0 +1,5610 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/net/ndis.h + * PURPOSE: Structures used by NDIS drivers + * DEFINES: i386 - Target platform is i386 + * NDIS_WRAPPER - Define only for NDIS wrapper library + * NDIS_MINIPORT_DRIVER - Define only for NDIS miniport drivers + * BINARY_COMPATIBLE - 0 = Use macros for some features + * - 1 = Use imports for features not available + * NDIS40 - Use NDIS 4.0 structures by default + * NDIS50 - Use NDIS 5.0 structures by default + */ +#ifndef __NDIS_H +#define __NDIS_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifdef NDIS50 +#undef NDIS40 +#define NDIS40 +#endif + + +/* Windows 9x compatibillity for miniports on x86 platform */ +#ifndef BINARY_COMPATIBLE +#if defined(NDIS_MINIPORT_DRIVER) && defined(i386) +#define BINARY_COMPATIBLE 1 +#else +#define BINARY_COMPATIBLE 0 +#endif +#endif + +#ifndef UNALIGNED +#define UNALIGNED +#endif + +#ifndef FASTCALL +#define FASTCALL __attribute__((fastcall)) +#endif + +/* The NDIS library export functions. NDIS miniport drivers import functions */ +#ifdef NDIS_WRAPPER + +#ifdef _MSC_VER +#define EXPIMP __declspec(dllexport) +#else +#define EXPIMP STDCALL +#endif + +#else /* NDIS_WRAPPER */ + +#ifdef _MSC_VER +#define EXPIMP __declspec(dllimport) +#else +#define EXPIMP STDCALL +#endif + +#endif /* NDIS_WRAPPER */ + + + +#ifdef NDIS_MINIPORT_DRIVER + +#include "miniport.h" + +#else /* NDIS_MINIPORT_DRIVER */ + +#ifdef _MSC_VER +#include + +typedef ULONG ULONG_PTR, *PULONG_PTR; + +#else /* _MSC_VER */ +#include + +/* FIXME: Missed some definitions in there */ + +typedef struct _DMA_CONFIGURATION_BYTE0 +{ + UCHAR Channel:3; + UCHAR Reserved:3; + UCHAR Shared:1; + UCHAR MoreEntries:1; +} DMA_CONFIGURATION_BYTE0; + +typedef struct _DMA_CONFIGURATION_BYTE1 +{ + UCHAR Reserved0:2; + UCHAR TransferSize:2; + UCHAR Timing:2; + UCHAR Reserved1:2; +} DMA_CONFIGURATION_BYTE1; + + +typedef struct _EISA_MEMORY_TYPE +{ + UCHAR ReadWrite:1; + UCHAR Cached:1; + UCHAR Reserved0:1; + UCHAR Type:2; + UCHAR Shared:1; + UCHAR Reserved1:1; + UCHAR MoreEntries:1; +} EISA_MEMORY_TYPE, *PEISA_MEMORY_TYPE; + +typedef struct _EISA_MEMORY_CONFIGURATION +{ + EISA_MEMORY_TYPE ConfigurationByte; + UCHAR DataSize; + USHORT AddressLowWord; + UCHAR AddressHighByte; + USHORT MemorySize; +} EISA_MEMORY_CONFIGURATION, *PEISA_MEMORY_CONFIGURATION; + + +typedef struct _EISA_IRQ_DESCRIPTOR +{ + UCHAR Interrupt:4; + UCHAR Reserved:1; + UCHAR LevelTriggered:1; + UCHAR Shared:1; + UCHAR MoreEntries:1; +} EISA_IRQ_DESCRIPTOR, *PEISA_IRQ_DESCRIPTOR; + +typedef struct _EISA_IRQ_CONFIGURATION +{ + EISA_IRQ_DESCRIPTOR ConfigurationByte; + UCHAR Reserved; +} EISA_IRQ_CONFIGURATION, *PEISA_IRQ_CONFIGURATION; + +typedef struct _EISA_DMA_CONFIGURATION +{ + DMA_CONFIGURATION_BYTE0 ConfigurationByte0; + DMA_CONFIGURATION_BYTE1 ConfigurationByte1; +} EISA_DMA_CONFIGURATION, *PEISA_DMA_CONFIGURATION; + + +typedef struct _EISA_PORT_DESCRIPTOR +{ + UCHAR NumberPorts:5; + UCHAR Reserved:1; + UCHAR Shared:1; + UCHAR MoreEntries:1; +} EISA_PORT_DESCRIPTOR, *PEISA_PORT_DESCRIPTOR; + +typedef struct _EISA_PORT_CONFIGURATION +{ + EISA_PORT_DESCRIPTOR Configuration; + USHORT PortAddress; +} EISA_PORT_CONFIGURATION, *PEISA_PORT_CONFIGURATION; + +typedef struct _CM_EISA_SLOT_INFORMATION +{ + UCHAR ReturnCode; + UCHAR ReturnFlags; + UCHAR MajorRevision; + UCHAR MinorRevision; + USHORT Checksum; + UCHAR NumberFunctions; + UCHAR FunctionInformation; + ULONG CompressedId; +} CM_EISA_SLOT_INFORMATION, *PCM_EISA_SLOT_INFORMATION; + +typedef struct _CM_EISA_FUNCTION_INFORMATION +{ + ULONG CompressedId; + UCHAR IdSlotFlags1; + UCHAR IdSlotFlags2; + UCHAR MinorRevision; + UCHAR MajorRevision; + UCHAR Selections[26]; + UCHAR FunctionFlags; + UCHAR TypeString[80]; + EISA_MEMORY_CONFIGURATION EisaMemory[9]; + EISA_IRQ_CONFIGURATION EisaIrq[7]; + EISA_DMA_CONFIGURATION EisaDma[4]; + EISA_PORT_CONFIGURATION EisaPort[20]; + UCHAR InitializationData[60]; +} CM_EISA_FUNCTION_INFORMATION, *PCM_EISA_FUNCTION_INFORMATION; + +#endif /* _MSC_VER */ + +/* FIXME: Missed some definitions in there */ + +typedef CONST CHAR *PCSTR; + +#endif /* NDIS_MINIPORT_DRIVER */ + +#include "netevent.h" +#include "ndisoid.h" +#include "ntddndis.h" + + +#if defined(NDIS_MINIPORT_DRIVER) || !defined(_MSC_VER) + +#ifndef _GUID_DEFINED +#define _GUID_DEFINED + +typedef struct _GUID { + ULONG Data1; + USHORT Data2; + USHORT Data3; + UCHAR Data4[8]; +} GUID; + +#endif /* _GUID_DEFINED */ + +#endif /* NDIS_MINIPORT_DRIVER || _MSC_VER */ + + +/* NDIS base types */ + +typedef struct _NDIS_SPIN_LOCK +{ + KSPIN_LOCK SpinLock; + KIRQL OldIrql; +} NDIS_SPIN_LOCK, * PNDIS_SPIN_LOCK; + +typedef struct _NDIS_EVENT +{ + KEVENT Event; +} NDIS_EVENT, *PNDIS_EVENT; + +typedef PVOID NDIS_HANDLE, *PNDIS_HANDLE; +typedef int NDIS_STATUS, *PNDIS_STATUS; + +typedef UNICODE_STRING NDIS_STRING, *PNDIS_STRING; + +typedef PCSTR NDIS_ANSI_STRING, *PNDIS_ANSI_STRING; + +typedef MDL NDIS_BUFFER, *PNDIS_BUFFER; + +/* NDIS_STATUS constants */ +#define NDIS_STATUS_SUCCESS ((NDIS_STATUS)STATUS_SUCCESS) +#define NDIS_STATUS_PENDING ((NDIS_STATUS)STATUS_PENDING) +#define NDIS_STATUS_NOT_RECOGNIZED ((NDIS_STATUS)0x00010001L) +#define NDIS_STATUS_NOT_COPIED ((NDIS_STATUS)0x00010002L) +#define NDIS_STATUS_NOT_ACCEPTED ((NDIS_STATUS)0x00010003L) +#define NDIS_STATUS_CALL_ACTIVE ((NDIS_STATUS)0x00010007L) + +#define NDIS_STATUS_ONLINE ((NDIS_STATUS)0x40010003L) +#define NDIS_STATUS_RESET_START ((NDIS_STATUS)0x40010004L) +#define NDIS_STATUS_RESET_END ((NDIS_STATUS)0x40010005L) +#define NDIS_STATUS_RING_STATUS ((NDIS_STATUS)0x40010006L) +#define NDIS_STATUS_CLOSED ((NDIS_STATUS)0x40010007L) +#define NDIS_STATUS_WAN_LINE_UP ((NDIS_STATUS)0x40010008L) +#define NDIS_STATUS_WAN_LINE_DOWN ((NDIS_STATUS)0x40010009L) +#define NDIS_STATUS_WAN_FRAGMENT ((NDIS_STATUS)0x4001000AL) +#define NDIS_STATUS_MEDIA_CONNECT ((NDIS_STATUS)0x4001000BL) +#define NDIS_STATUS_MEDIA_DISCONNECT ((NDIS_STATUS)0x4001000CL) +#define NDIS_STATUS_HARDWARE_LINE_UP ((NDIS_STATUS)0x4001000DL) +#define NDIS_STATUS_HARDWARE_LINE_DOWN ((NDIS_STATUS)0x4001000EL) +#define NDIS_STATUS_INTERFACE_UP ((NDIS_STATUS)0x4001000FL) +#define NDIS_STATUS_INTERFACE_DOWN ((NDIS_STATUS)0x40010010L) +#define NDIS_STATUS_MEDIA_BUSY ((NDIS_STATUS)0x40010011L) +#define NDIS_STATUS_WW_INDICATION ((NDIS_STATUS)0x40010012L) +#define NDIS_STATUS_TAPI_INDICATION ((NDIS_STATUS)0x40010080L) + +#define NDIS_STATUS_NOT_RESETTABLE ((NDIS_STATUS)0x80010001L) +#define NDIS_STATUS_SOFT_ERRORS ((NDIS_STATUS)0x80010003L) +#define NDIS_STATUS_HARD_ERRORS ((NDIS_STATUS)0x80010004L) +#define NDIS_STATUS_BUFFER_OVERFLOW ((NDIS_STATUS)STATUS_BUFFER_OVERFLOW) + +#define NDIS_STATUS_FAILURE ((NDIS_STATUS)STATUS_UNSUCCESSFUL) +#define NDIS_STATUS_RESOURCES ((NDIS_STATUS)STATUS_INSUFFICIENT_RESOURCES) +#define NDIS_STATUS_CLOSING ((NDIS_STATUS)0xC0010002L) +#define NDIS_STATUS_BAD_VERSION ((NDIS_STATUS)0xC0010004L) +#define NDIS_STATUS_BAD_CHARACTERISTICS ((NDIS_STATUS)0xC0010005L) +#define NDIS_STATUS_ADAPTER_NOT_FOUND ((NDIS_STATUS)0xC0010006L) +#define NDIS_STATUS_OPEN_FAILED ((NDIS_STATUS)0xC0010007L) +#define NDIS_STATUS_DEVICE_FAILED ((NDIS_STATUS)0xC0010008L) +#define NDIS_STATUS_MULTICAST_FULL ((NDIS_STATUS)0xC0010009L) +#define NDIS_STATUS_MULTICAST_EXISTS ((NDIS_STATUS)0xC001000AL) +#define NDIS_STATUS_MULTICAST_NOT_FOUND ((NDIS_STATUS)0xC001000BL) +#define NDIS_STATUS_REQUEST_ABORTED ((NDIS_STATUS)0xC001000CL) +#define NDIS_STATUS_RESET_IN_PROGRESS ((NDIS_STATUS)0xC001000DL) +#define NDIS_STATUS_CLOSING_INDICATING ((NDIS_STATUS)0xC001000EL) +#define NDIS_STATUS_NOT_SUPPORTED ((NDIS_STATUS)STATUS_NOT_SUPPORTED) +#define NDIS_STATUS_INVALID_PACKET ((NDIS_STATUS)0xC001000FL) +#define NDIS_STATUS_OPEN_LIST_FULL ((NDIS_STATUS)0xC0010010L) +#define NDIS_STATUS_ADAPTER_NOT_READY ((NDIS_STATUS)0xC0010011L) +#define NDIS_STATUS_ADAPTER_NOT_OPEN ((NDIS_STATUS)0xC0010012L) +#define NDIS_STATUS_NOT_INDICATING ((NDIS_STATUS)0xC0010013L) +#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) +#define NDIS_STATUS_INVALID_DATA ((NDIS_STATUS)0xC0010015L) +#define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) +#define NDIS_STATUS_INVALID_OID ((NDIS_STATUS)0xC0010017L) +#define NDIS_STATUS_ADAPTER_REMOVED ((NDIS_STATUS)0xC0010018L) +#define NDIS_STATUS_UNSUPPORTED_MEDIA ((NDIS_STATUS)0xC0010019L) +#define NDIS_STATUS_GROUP_ADDRESS_IN_USE ((NDIS_STATUS)0xC001001AL) +#define NDIS_STATUS_FILE_NOT_FOUND ((NDIS_STATUS)0xC001001BL) +#define NDIS_STATUS_ERROR_READING_FILE ((NDIS_STATUS)0xC001001CL) +#define NDIS_STATUS_ALREADY_MAPPED ((NDIS_STATUS)0xC001001DL) +#define NDIS_STATUS_RESOURCE_CONFLICT ((NDIS_STATUS)0xC001001EL) +#define NDIS_STATUS_NO_CABLE ((NDIS_STATUS)0xC001001FL) + +#define NDIS_STATUS_INVALID_SAP ((NDIS_STATUS)0xC0010020L) +#define NDIS_STATUS_SAP_IN_USE ((NDIS_STATUS)0xC0010021L) +#define NDIS_STATUS_INVALID_ADDRESS ((NDIS_STATUS)0xC0010022L) +#define NDIS_STATUS_VC_NOT_ACTIVATED ((NDIS_STATUS)0xC0010023L) +#define NDIS_STATUS_DEST_OUT_OF_ORDER ((NDIS_STATUS)0xC0010024L) +#define NDIS_STATUS_VC_NOT_AVAILABLE ((NDIS_STATUS)0xC0010025L) +#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE ((NDIS_STATUS)0xC0010026L) +#define NDIS_STATUS_INCOMPATABLE_QOS ((NDIS_STATUS)0xC0010027L) +#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED ((NDIS_STATUS)0xC0010028L) +#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION ((NDIS_STATUS)0xC0010029L) + +#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR ((NDIS_STATUS)0xC0011000L) + + +/* NDIS error codes for error logging */ + +#define NDIS_ERROR_CODE ULONG + +#define NDIS_ERROR_CODE_RESOURCE_CONFLICT EVENT_NDIS_RESOURCE_CONFLICT +#define NDIS_ERROR_CODE_OUT_OF_RESOURCES EVENT_NDIS_OUT_OF_RESOURCE +#define NDIS_ERROR_CODE_HARDWARE_FAILURE EVENT_NDIS_HARDWARE_FAILURE +#define NDIS_ERROR_CODE_ADAPTER_NOT_FOUND EVENT_NDIS_ADAPTER_NOT_FOUND +#define NDIS_ERROR_CODE_INTERRUPT_CONNECT EVENT_NDIS_INTERRUPT_CONNECT +#define NDIS_ERROR_CODE_DRIVER_FAILURE EVENT_NDIS_DRIVER_FAILURE +#define NDIS_ERROR_CODE_BAD_VERSION EVENT_NDIS_BAD_VERSION +#define NDIS_ERROR_CODE_TIMEOUT EVENT_NDIS_TIMEOUT +#define NDIS_ERROR_CODE_NETWORK_ADDRESS EVENT_NDIS_NETWORK_ADDRESS +#define NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION EVENT_NDIS_UNSUPPORTED_CONFIGURATION +#define NDIS_ERROR_CODE_INVALID_VALUE_FROM_ADAPTER EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER +#define NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER +#define NDIS_ERROR_CODE_BAD_IO_BASE_ADDRESS EVENT_NDIS_BAD_IO_BASE_ADDRESS +#define NDIS_ERROR_CODE_RECEIVE_SPACE_SMALL EVENT_NDIS_RECEIVE_SPACE_SMALL +#define NDIS_ERROR_CODE_ADAPTER_DISABLED EVENT_NDIS_ADAPTER_DISABLED + + +/* Memory allocation flags. Used by Ndis(Allocate|Free)Memory */ +#define NDIS_MEMORY_CONTIGUOUS 0x00000001 +#define NDIS_MEMORY_NONCACHED 0x00000002 + +/* NIC attribute flags. Used by NdisMSetAttributes(Ex) */ +#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001 +#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002 +#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004 +#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008 +#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010 + + + +#define MAXIMUM_PROCESSORS 32 + + + +/* Lock */ + +typedef union _NDIS_RW_LOCK_REFCOUNT +{ + UINT RefCount; + UCHAR cacheLine[16]; +} NDIS_RW_LOCK_REFCOUNT; + +typedef struct _NDIS_RW_LOCK +{ + union + { + struct + { + KSPIN_LOCK SpinLock; + PVOID Context; + } s; + UCHAR Reserved[16]; + } u; + + NDIS_RW_LOCK_REFCOUNT RefCount[MAXIMUM_PROCESSORS]; +} NDIS_RW_LOCK, *PNDIS_RW_LOCK; + +typedef struct _LOCK_STATE +{ + USHORT LockState; + KIRQL OldIrql; +} LOCK_STATE, *PLOCK_STATE; + + + +/* Timer */ + +typedef VOID (*PNDIS_TIMER_FUNCTION)( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +typedef struct _NDIS_TIMER +{ + KTIMER Timer; + KDPC Dpc; +} NDIS_TIMER, *PNDIS_TIMER; + + + +/* Hardware */ + +typedef CM_MCA_POS_DATA NDIS_MCA_POS_DATA, *PNDIS_MCA_POS_DATA; +typedef CM_EISA_SLOT_INFORMATION NDIS_EISA_SLOT_INFORMATION, *PNDIS_EISA_SLOT_INFORMATION; +typedef CM_EISA_FUNCTION_INFORMATION NDIS_EISA_FUNCTION_INFORMATION, *PNDIS_EISA_FUNCTION_INFORMATION; +typedef CM_PARTIAL_RESOURCE_LIST NDIS_RESOURCE_LIST, *PNDIS_RESOURCE_LIST; + +/* Hardware status codes (OID_GEN_HARDWARE_STATUS) */ +typedef enum _NDIS_HARDWARE_STATUS +{ + NdisHardwareStatusReady, + NdisHardwareStatusInitializing, + NdisHardwareStatusReset, + NdisHardwareStatusClosing, + NdisHardwareStatusNotReady +} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS; + +/* OID_GEN_GET_TIME_CAPS */ +typedef struct _GEN_GET_TIME_CAPS +{ + ULONG Flags; + ULONG ClockPrecision; +} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS; + +/* Flag bits */ +#define READABLE_LOCAL_CLOCK 0x00000001 +#define CLOCK_NETWORK_DERIVED 0x00000002 +#define CLOCK_PRECISION 0x00000004 +#define RECEIVE_TIME_INDICATION_CAPABLE 0x00000008 +#define TIMED_SEND_CAPABLE 0x00000010 +#define TIME_STAMP_CAPABLE 0x00000020 + +/* OID_GEN_GET_NETCARD_TIME */ +typedef struct _GEN_GET_NETCARD_TIME +{ + ULONGLONG ReadTime; +} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME; + +/* NDIS driver medium (OID_GEN_MEDIA_SUPPORTED / OID_GEN_MEDIA_IN_USE) */ +typedef enum _NDIS_MEDIUM +{ + NdisMedium802_3, + NdisMedium802_5, + NdisMediumFddi, + NdisMediumWan, + NdisMediumLocalTalk, + NdisMediumDix, /* Defined for convenience, not a real medium */ + NdisMediumArcnetRaw, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMediumWirelessWan, + NdisMediumIrda, + NdisMediumBpc, + NdisMediumCoWan, + NdisMedium1394, + NdisMediumMax +} NDIS_MEDIUM, *PNDIS_MEDIUM; + +/* NDIS packet filter bits (OID_GEN_CURRENT_PACKET_FILTER) */ +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00001000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000 + +/* NDIS protocol option bits (OID_GEN_PROTOCOL_OPTIONS) */ +#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001 +#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002 +#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004 + +/* NDIS MAC option bits (OID_GEN_MAC_OPTIONS) */ +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +/* State of the LAN media (OID_GEN_MEDIA_CONNECT_STATUS) */ +typedef enum _NDIS_MEDIA_STATE +{ + NdisMediaStateConnected, + NdisMediaStateDisconnected +} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE; + +/* OID_GEN_SUPPORTED_GUIDS */ +typedef struct _NDIS_GUID +{ + GUID Guid; + union + { + NDIS_OID Oid; + NDIS_STATUS Status; + } u; + ULONG Size; + ULONG Flags; +} NDIS_GUID, *PNDIS_GUID; + +#define NDIS_GUID_TO_OID 0x00000001 +#define NDIS_GUID_TO_STATUS 0x00000002 +#define NDIS_GUID_ANSI_STRING 0x00000004 +#define NDIS_GUID_UNICODE_STRING 0x00000008 +#define NDIS_GUID_ARRAY 0x00000010 + + + +typedef struct _NDIS_PACKET_POOL +{ + NDIS_SPIN_LOCK SpinLock; + struct _NDIS_PACKET *FreeList; + UINT PacketLength; + UCHAR Buffer[1]; +} NDIS_PACKET_POOL, * PNDIS_PACKET_POOL; + +typedef struct _NDIS_PACKET_PRIVATE +{ + UINT PhysicalCount; + UINT TotalLength; + PNDIS_BUFFER Head; + PNDIS_BUFFER Tail; + PNDIS_PACKET_POOL Pool; + UINT Count; + ULONG Flags; /* See fPACKET_xxx bits below */ + BOOLEAN ValidCounts; + UCHAR NdisPacketFlags; + USHORT NdisPacketOobOffset; +} NDIS_PACKET_PRIVATE, * PNDIS_PACKET_PRIVATE; + +#define fPACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40 +#define fPACKET_ALLOCATED_BY_NDIS 0x80 + +typedef struct _NDIS_PACKET { + NDIS_PACKET_PRIVATE Private; + union { + struct { + UCHAR MiniportReserved[2*sizeof(PVOID)]; + UCHAR WrapperReserved[2*sizeof(PVOID)]; + } s1; + struct { + UCHAR MiniportReservedEx[3*sizeof(PVOID)]; + UCHAR WrapperReservedEx[sizeof(PVOID)]; + } s2; + struct { + UCHAR MacReserved[4*sizeof(PVOID)]; + } s3; + } u; + ULONG_PTR Reserved[2]; + UCHAR ProtocolReserved[1]; +} NDIS_PACKET, *PNDIS_PACKET, **PPNDIS_PACKET; + +typedef struct _NDIS_PACKET_OOB_DATA { + union { + ULONGLONG TimeToSend; + ULONGLONG TimeSent; + } u; + ULONGLONG TimeReceived; + UINT HeaderSize; + UINT SizeMediaSpecificInfo; + PVOID MediaSpecificInformation; + NDIS_STATUS Status; +} NDIS_PACKET_OOB_DATA, *PNDIS_PACKET_OOB_DATA; + +typedef struct _NDIS_PM_PACKET_PATTERN +{ + ULONG Priority; + ULONG Reserved; + ULONG MaskSize; + ULONG PatternOffset; + ULONG PatternSize; + ULONG PatternFlags; +} NDIS_PM_PACKET_PATTERN, *PNDIS_PM_PACKET_PATTERN; + + +/* Request types used by NdisRequest */ +typedef enum _NDIS_REQUEST_TYPE +{ + NdisRequestQueryInformation, + NdisRequestSetInformation, + NdisRequestQueryStatistics, + NdisRequestOpen, + NdisRequestClose, + NdisRequestSend, + NdisRequestTransferData, + NdisRequestReset, + NdisRequestGeneric1, + NdisRequestGeneric2, + NdisRequestGeneric3, + NdisRequestGeneric4 +} NDIS_REQUEST_TYPE, *PNDIS_REQUEST_TYPE; + +typedef struct _NDIS_REQUEST { + UCHAR MacReserved[16]; + NDIS_REQUEST_TYPE RequestType; + union _DATA { + struct QUERY_INFORMATION { + NDIS_OID Oid; + PVOID InformationBuffer; + UINT InformationBufferLength; + UINT BytesWritten; + UINT BytesNeeded; + } QUERY_INFORMATION; + struct SET_INFORMATION { + NDIS_OID Oid; + PVOID InformationBuffer; + UINT InformationBufferLength; + UINT BytesRead; + UINT BytesNeeded; + } SET_INFORMATION; + } DATA; +} NDIS_REQUEST, *PNDIS_REQUEST; + + + +/* Wide Area Networks definitions */ + +typedef struct _NDIS_WAN_PACKET +{ + LIST_ENTRY WanPacketQueue; + PUCHAR CurrentBuffer; + ULONG CurrentLength; + PUCHAR StartBuffer; + PUCHAR EndBuffer; + PVOID ProtocolReserved1; + PVOID ProtocolReserved2; + PVOID ProtocolReserved3; + PVOID ProtocolReserved4; + PVOID MacReserved1; + PVOID MacReserved2; + PVOID MacReserved3; + PVOID MacReserved4; +} NDIS_WAN_PACKET, *PNDIS_WAN_PACKET; + + + +/* DMA channel information */ + +typedef struct _NDIS_DMA_DESCRIPTION +{ + BOOLEAN DemandMode; + BOOLEAN AutoInitialize; + BOOLEAN DmaChannelSpecified; + DMA_WIDTH DmaWidth; + DMA_SPEED DmaSpeed; + ULONG DmaPort; + ULONG DmaChannel; +} NDIS_DMA_DESCRIPTION, *PNDIS_DMA_DESCRIPTION; + +typedef struct _NDIS_DMA_BLOCK +{ + PVOID MapRegisterBase; + KEVENT AllocationEvent; + PADAPTER_OBJECT SystemAdapterObject; + BOOLEAN InProgress; +} NDIS_DMA_BLOCK, *PNDIS_DMA_BLOCK; + + +/* Possible hardware architecture */ +typedef enum _NDIS_INTERFACE_TYPE +{ + NdisInterfaceInternal = Internal, + NdisInterfaceIsa = Isa, + NdisInterfaceEisa = Eisa, + NdisInterfaceMca = MicroChannel, + NdisInterfaceTurboChannel = TurboChannel, + NdisInterfacePci = PCIBus, + NdisInterfacePcMcia = PCMCIABus +} NDIS_INTERFACE_TYPE, *PNDIS_INTERFACE_TYPE; + +#define NdisInterruptLevelSensitive LevelSensitive +#define NdisInterruptLatched Latched +typedef KINTERRUPT_MODE NDIS_INTERRUPT_MODE, *PNDIS_INTERRUPT_MODE; + + +typedef enum _NDIS_PARAMETER_TYPE +{ + NdisParameterInteger, + NdisParameterHexInteger, + NdisParameterString, + NdisParameterMultiString +} NDIS_PARAMETER_TYPE, *PNDIS_PARAMETER_TYPE; + +typedef struct _NDIS_CONFIGURATION_PARAMETER +{ + NDIS_PARAMETER_TYPE ParameterType; + union + { + ULONG IntegerData; + NDIS_STRING StringData; + } ParameterData; +} NDIS_CONFIGURATION_PARAMETER, *PNDIS_CONFIGURATION_PARAMETER; + + +typedef PHYSICAL_ADDRESS NDIS_PHYSICAL_ADDRESS, *PNDIS_PHYSICAL_ADDRESS; + +typedef struct _NDIS_PHYSICAL_ADDRESS_UNIT +{ + NDIS_PHYSICAL_ADDRESS PhysicalAddress; + UINT Length; +} NDIS_PHYSICAL_ADDRESS_UNIT, *PNDIS_PHYSICAL_ADDRESS_UNIT; + + +typedef VOID (*ADAPTER_SHUTDOWN_HANDLER)( + IN PVOID ShutdownContext); + + + +#ifdef NDIS_WRAPPER + +typedef struct _OID_LIST OID_LIST, *POID_LIST; + +/* PnP state */ + +typedef enum _NDIS_PNP_DEVICE_STATE +{ + NdisPnPDeviceAdded, + NdisPnPDeviceStarted, + NdisPnPDeviceQueryStopped, + NdisPnPDeviceStopped, + NdisPnPDeviceQueryRemoved, + NdisPnPDeviceRemoved, + NdisPnPDeviceSurpriseRemoved +} NDIS_PNP_DEVICE_STATE; + +#define NDIS_DEVICE_NOT_STOPPABLE 0x00000001 +#define NDIS_DEVICE_NOT_REMOVEABLE 0x00000002 +#define NDIS_DEVICE_NOT_SUSPENDABLE 0x00000004 +#define NDIS_DEVICE_DISABLE_PM 0x00000008 +#define NDIS_DEVICE_DISABLE_WAKE_UP 0x00000010 +#define NDIS_DEVICE_DISABLE_WAKE_ON_RECONNECT 0x00000020 + +#endif /* NDIS_WRAPPER */ + + +#ifdef NDIS50 + +typedef struct _ATM_ADDRESS ATM_ADDRESS, *PATM_ADDRESS; + + +/* OID_GEN_NETWORK_LAYER_ADDRESSES */ +typedef struct _NETWORK_ADDRESS +{ + USHORT AddressLength; + USHORT AddressType; + UCHAR Address[1]; +} NETWORK_ADDRESS, *PNETWORK_ADDRESS; + +typedef struct _NETWORK_ADDRESS_LIST +{ + LONG AddressCount; + USHORT AddressType; + NETWORK_ADDRESS Address[1]; +} NETWORK_ADDRESS_LIST, *PNETWORK_ADDRESS_LIST; + +/* Protocol types supported by NDIS */ +#define NDIS_PROTOCOL_ID_DEFAULT 0x00 +#define NDIS_PROTOCOL_ID_TCP_IP 0x02 +#define NDIS_PROTOCOL_ID_IPX 0x06 +#define NDIS_PROTOCOL_ID_NBF 0x07 +#define NDIS_PROTOCOL_ID_MAX 0x0F +#define NDIS_PROTOCOL_ID_MASK 0x0F + +/* OID_GEN_TRANSPORT_HEADER_OFFSET */ +typedef struct _TRANSPORT_HEADER_OFFSET +{ + USHORT ProtocolType; + USHORT HeaderOffset; +} TRANSPORT_HEADER_OFFSET, *PTRANSPORT_HEADER_OFFSET; + + +/* OID_GEN_CO_LINK_SPEED / OID_GEN_CO_MINIMUM_LINK_SPEED */ +typedef struct _NDIS_CO_LINK_SPEED +{ + ULONG Outbound; + ULONG Inbound; +} NDIS_CO_LINK_SPEED, *PNDIS_CO_LINK_SPEED; + + +typedef enum _NDIS_AF +{ + CO_ADDRESS_FAMILY_Q2931 = 1, + CO_ADDRESS_FAMILY_SPANS, +} NDIS_AF, *PNDIS_AF; + +typedef struct +{ + NDIS_AF AddressFamily; + ULONG MajorVersion; + ULONG MinorVersion; +} CO_ADDRESS_FAMILY, *PCO_ADDRESS_FAMILY; + +typedef enum +{ + BestEffortService, + PredictiveService, + GuaranteedService +} GUARANTEE; + +typedef struct _CO_FLOW_PARAMETERS +{ + ULONG TokenRate; /* In Bytes/sec */ + ULONG TokenBucketSize; /* In Bytes */ + ULONG PeakBandwidth; /* In Bytes/sec */ + ULONG Latency; /* In microseconds */ + ULONG DelayVariation; /* In microseconds */ + GUARANTEE LevelOfGuarantee; /* Guaranteed, Predictive or Best Effort */ + ULONG CostOfCall; /* Reserved for future use, */ + /* must be set to 0 now */ + ULONG NetworkAvailability; /* read-only: 1 if accessible, 0 if not */ + ULONG MaxSduSize; /* In Bytes */ +} CO_FLOW_PARAMETERS, *PCO_FLOW_PARAMETERS; + +typedef struct _CO_SPECIFIC_PARAMETERS +{ + ULONG ParamType; + ULONG Length; + UCHAR Parameters[1]; +} CO_SPECIFIC_PARAMETERS, *PCO_SPECIFIC_PARAMETERS; + +typedef struct _CO_CALL_MANAGER_PARAMETERS { + CO_FLOW_PARAMETERS Transmit; + CO_FLOW_PARAMETERS Receive; + CO_SPECIFIC_PARAMETERS CallMgrSpecific; +} CO_CALL_MANAGER_PARAMETERS, *PCO_CALL_MANAGER_PARAMETERS; + +typedef struct _CO_MEDIA_PARAMETERS +{ + ULONG Flags; + ULONG ReceivePriority; + ULONG ReceiveSizeHint; + CO_SPECIFIC_PARAMETERS MediaSpecific; +} CO_MEDIA_PARAMETERS, *PCO_MEDIA_PARAMETERS; + +/* Definitions for the flags in CO_MEDIA_PARAMETERS */ +#define RECEIVE_TIME_INDICATION 0x00000001 +#define USE_TIME_STAMPS 0x00000002 +#define TRANSMIT_VC 0x00000004 +#define RECEIVE_VC 0x00000008 +#define INDICATE_ERRED_PACKETS 0x00000010 +#define INDICATE_END_OF_TX 0x00000020 +#define RESERVE_RESOURCES_VC 0x00000040 +#define ROUND_DOWN_FLOW 0x00000080 +#define ROUND_UP_FLOW 0x00000100 + +typedef struct _CO_CALL_PARAMETERS +{ + ULONG Flags; + PCO_CALL_MANAGER_PARAMETERS CallMgrParameters; + PCO_MEDIA_PARAMETERS MediaParameters; +} CO_CALL_PARAMETERS, *PCO_CALL_PARAMETERS; + +typedef struct _CO_SAP { + ULONG SapType; + ULONG SapLength; + UCHAR Sap[1]; +} CO_SAP, *PCO_SAP; + +typedef struct _NDIS_IPSEC_PACKET_INFO +{ + union + { + struct + { + NDIS_HANDLE OffloadHandle; + NDIS_HANDLE NextOffloadHandle; + } Transmit; + + struct + { + ULONG SA_DELETE_REQ:1; + ULONG CRYPTO_DONE:1; + ULONG NEXT_CRYPTO_DONE:1; + ULONG CryptoStatus; + } Receive; + } u; +} NDIS_IPSEC_PACKET_INFO, *PNDIS_IPSEC_PACKET_INFO; + + +/* Plug and play and power management */ + +/* PnP and PM event codes */ +typedef enum _NET_PNP_EVENT_CODE +{ + NetEventSetPower, + NetEventQueryPower, + NetEventQueryRemoveDevice, + NetEventCancelRemoveDevice, + NetEventReconfigure, + NetEventBindList, + NetEventBindsComplete, + NetEventPnPCapabilities, + NetEventMaximum +} NET_PNP_EVENT_CODE, *PNET_PNP_EVENT_CODE; + +/* Networking PnP event indication structure */ +typedef struct _NET_PNP_EVENT +{ + /* Event code */ + NET_PNP_EVENT_CODE NetEvent; + /* Event specific data */ + PVOID Buffer; + /* Length of event specific data */ + ULONG BufferLength; + + /* Reserved areas */ + ULONG_PTR NdisReserved[4]; + ULONG_PTR TransportReserved[4]; + ULONG_PTR TdiReserved[4]; + ULONG_PTR TdiClientReserved[4]; +} NET_PNP_EVENT, *PNET_PNP_EVENT; + +/* Device power state structure */ +typedef enum _NET_DEVICE_POWER_STATE +{ + NetDeviceStateUnspecified = 0, + NetDeviceStateD0, + NetDeviceStateD1, + NetDeviceStateD2, + NetDeviceStateD3, + NetDeviceStateMaximum +} NET_DEVICE_POWER_STATE, *PNET_DEVICE_POWER_STATE; + + + +/* Call Manager */ + +typedef NDIS_STATUS (*CO_CREATE_VC_HANDLER)( + IN NDIS_HANDLE ProtocolAfContext, + IN NDIS_HANDLE NdisVcHandle, + OUT PNDIS_HANDLE ProtocolVcContext); + +typedef NDIS_STATUS (*CO_DELETE_VC_HANDLER)( + IN NDIS_HANDLE ProtocolVcContext); + +typedef NDIS_STATUS (*CO_REQUEST_HANDLER)( + IN NDIS_HANDLE ProtocolAfContext, + IN NDIS_HANDLE ProtocolVcContext OPTIONAL, + IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, + IN OUT PNDIS_REQUEST NdisRequest); + +typedef VOID (*CO_REQUEST_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolAfContext OPTIONAL, + IN NDIS_HANDLE ProtocolVcContext OPTIONAL, + IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, + IN PNDIS_REQUEST NdisRequest); + + +typedef NDIS_STATUS (*CM_OPEN_AF_HANDLER)( + IN NDIS_HANDLE CallMgrBindingContext, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN NDIS_HANDLE NdisAfHandle, + OUT PNDIS_HANDLE CallMgrAfContext + ); + +typedef +NDIS_STATUS +(*CM_CLOSE_AF_HANDLER)( + IN NDIS_HANDLE CallMgrAfContext + ); + +typedef +NDIS_STATUS +(*CM_REG_SAP_HANDLER)( + IN NDIS_HANDLE CallMgrAfContext, + IN PCO_SAP Sap, + IN NDIS_HANDLE NdisSapHandle, + OUT PNDIS_HANDLE CallMgrSapContext + ); + +typedef +NDIS_STATUS +(*CM_DEREG_SAP_HANDLER)( + IN NDIS_HANDLE CallMgrSapContext + ); + +typedef +NDIS_STATUS +(*CM_MAKE_CALL_HANDLER)( + IN NDIS_HANDLE CallMgrVcContext, + IN OUT PCO_CALL_PARAMETERS CallParameters, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + OUT PNDIS_HANDLE CallMgrPartyContext OPTIONAL + ); + +typedef +NDIS_STATUS +(*CM_CLOSE_CALL_HANDLER)( + IN NDIS_HANDLE CallMgrVcContext, + IN NDIS_HANDLE CallMgrPartyContext OPTIONAL, + IN PVOID CloseData OPTIONAL, + IN UINT Size OPTIONAL + ); + +typedef +VOID +(*CM_INCOMING_CALL_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE CallMgrVcContext, + IN PCO_CALL_PARAMETERS CallParameters + ); + +typedef +NDIS_STATUS +(*CM_ADD_PARTY_HANDLER)( + IN NDIS_HANDLE CallMgrVcContext, + IN OUT PCO_CALL_PARAMETERS CallParameters, + IN NDIS_HANDLE NdisPartyHandle, + OUT PNDIS_HANDLE CallMgrPartyContext + ); + +typedef +NDIS_STATUS +(*CM_DROP_PARTY_HANDLER)( + IN NDIS_HANDLE CallMgrPartyContext, + IN PVOID CloseData OPTIONAL, + IN UINT Size OPTIONAL + ); + +typedef +VOID +(*CM_ACTIVATE_VC_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE CallMgrVcContext, + IN PCO_CALL_PARAMETERS CallParameters + ); + +typedef +VOID +(*CM_DEACTIVATE_VC_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE CallMgrVcContext + ); + +typedef +NDIS_STATUS +(*CM_MODIFY_CALL_QOS_HANDLER)( + IN NDIS_HANDLE CallMgrVcContext, + IN PCO_CALL_PARAMETERS CallParameters + ); + +typedef struct _NDIS_CALL_MANAGER_CHARACTERISTICS +{ + UCHAR MajorVersion; + UCHAR MinorVersion; + + USHORT Filler; + UINT Reserved; + + CO_CREATE_VC_HANDLER CmCreateVcHandler; + CO_DELETE_VC_HANDLER CmDeleteVcHandler; + CM_OPEN_AF_HANDLER CmOpenAfHandler; + CM_CLOSE_AF_HANDLER CmCloseAfHandler; + CM_REG_SAP_HANDLER CmRegisterSapHandler; + CM_DEREG_SAP_HANDLER CmDeregisterSapHandler; + CM_MAKE_CALL_HANDLER CmMakeCallHandler; + CM_CLOSE_CALL_HANDLER CmCloseCallHandler; + CM_INCOMING_CALL_COMPLETE_HANDLER CmIncomingCallCompleteHandler; + CM_ADD_PARTY_HANDLER CmAddPartyHandler; + CM_DROP_PARTY_HANDLER CmDropPartyHandler; + CM_ACTIVATE_VC_COMPLETE_HANDLER CmActivateVcCompleteHandler; + CM_DEACTIVATE_VC_COMPLETE_HANDLER CmDeactivateVcCompleteHandler; + CM_MODIFY_CALL_QOS_HANDLER CmModifyCallQoSHandler; + CO_REQUEST_HANDLER CmRequestHandler; + CO_REQUEST_COMPLETE_HANDLER CmRequestCompleteHandler; +} NDIS_CALL_MANAGER_CHARACTERISTICS, *PNDIS_CALL_MANAGER_CHARACTERISTICS; + + + +/* Call Manager clients */ + +typedef VOID (*CL_OPEN_AF_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolAfContext, + IN NDIS_HANDLE NdisAfHandle); + +typedef VOID (*CL_CLOSE_AF_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolAfContext); + +typedef VOID (*CL_REG_SAP_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolSapContext, + IN PCO_SAP Sap, + IN NDIS_HANDLE NdisSapHandle); + +typedef VOID (*CL_DEREG_SAP_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolSapContext); + +typedef VOID (*CL_MAKE_CALL_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolVcContext, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN PCO_CALL_PARAMETERS CallParameters); + +typedef VOID (*CL_MODIFY_CALL_QOS_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolVcContext, + IN PCO_CALL_PARAMETERS CallParameters); + +typedef VOID (*CL_CLOSE_CALL_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolVcContext, + IN NDIS_HANDLE ProtocolPartyContext OPTIONAL); + +typedef VOID (*CL_ADD_PARTY_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolPartyContext, + IN NDIS_HANDLE NdisPartyHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +typedef VOID (*CL_DROP_PARTY_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolPartyContext); + +typedef NDIS_STATUS (*CL_INCOMING_CALL_HANDLER)( + IN NDIS_HANDLE ProtocolSapContext, + IN NDIS_HANDLE ProtocolVcContext, + IN OUT PCO_CALL_PARAMETERS CallParameters); + +typedef VOID (*CL_INCOMING_CALL_QOS_CHANGE_HANDLER)( + IN NDIS_HANDLE ProtocolVcContext, + IN PCO_CALL_PARAMETERS CallParameters); + +typedef VOID (*CL_INCOMING_CLOSE_CALL_HANDLER)( + IN NDIS_STATUS CloseStatus, + IN NDIS_HANDLE ProtocolVcContext, + IN PVOID CloseData OPTIONAL, + IN UINT Size OPTIONAL); + +typedef VOID (*CL_INCOMING_DROP_PARTY_HANDLER)( + IN NDIS_STATUS DropStatus, + IN NDIS_HANDLE ProtocolPartyContext, + IN PVOID CloseData OPTIONAL, + IN UINT Size OPTIONAL); + +typedef VOID (*CL_CALL_CONNECTED_HANDLER)( + IN NDIS_HANDLE ProtocolVcContext); + + +typedef struct _NDIS_CLIENT_CHARACTERISTICS +{ + UCHAR MajorVersion; + UCHAR MinorVersion; + + USHORT Filler; + UINT Reserved; + + CO_CREATE_VC_HANDLER ClCreateVcHandler; + CO_DELETE_VC_HANDLER ClDeleteVcHandler; + CO_REQUEST_HANDLER ClRequestHandler; + CO_REQUEST_COMPLETE_HANDLER ClRequestCompleteHandler; + CL_OPEN_AF_COMPLETE_HANDLER ClOpenAfCompleteHandler; + CL_CLOSE_AF_COMPLETE_HANDLER ClCloseAfCompleteHandler; + CL_REG_SAP_COMPLETE_HANDLER ClRegisterSapCompleteHandler; + CL_DEREG_SAP_COMPLETE_HANDLER ClDeregisterSapCompleteHandler; + CL_MAKE_CALL_COMPLETE_HANDLER ClMakeCallCompleteHandler; + CL_MODIFY_CALL_QOS_COMPLETE_HANDLER ClModifyCallQoSCompleteHandler; + CL_CLOSE_CALL_COMPLETE_HANDLER ClCloseCallCompleteHandler; + CL_ADD_PARTY_COMPLETE_HANDLER ClAddPartyCompleteHandler; + CL_DROP_PARTY_COMPLETE_HANDLER ClDropPartyCompleteHandler; + CL_INCOMING_CALL_HANDLER ClIncomingCallHandler; + CL_INCOMING_CALL_QOS_CHANGE_HANDLER ClIncomingCallQoSChangeHandler; + CL_INCOMING_CLOSE_CALL_HANDLER ClIncomingCloseCallHandler; + CL_INCOMING_DROP_PARTY_HANDLER ClIncomingDropPartyHandler; + CL_CALL_CONNECTED_HANDLER ClCallConnectedHandler; +} NDIS_CLIENT_CHARACTERISTICS, *PNDIS_CLIENT_CHARACTERISTICS; + +#endif /* NDIS50 */ + + + +/* NDIS protocol structures */ + +/* Prototypes for NDIS 3.0 protocol characteristics */ + +typedef VOID (*OPEN_ADAPTER_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus); + +typedef VOID (*CLOSE_ADAPTER_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status); + +typedef VOID (*RESET_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS Status); + +typedef VOID (*REQUEST_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS Status); + +typedef VOID (*STATUS_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize); + +typedef VOID (*STATUS_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext); + +typedef VOID (*SEND_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status); + +typedef VOID (*WAN_SEND_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_WAN_PACKET Packet, + IN NDIS_STATUS Status); + +typedef VOID (*TRANSFER_DATA_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred); + +typedef VOID (*WAN_TRANSFER_DATA_COMPLETE_HANDLER)( + VOID); + +typedef NDIS_STATUS (*RECEIVE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookAheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +typedef NDIS_STATUS (*WAN_RECEIVE_HANDLER)( + IN NDIS_HANDLE NdisLinkHandle, + IN PUCHAR Packet, + IN ULONG PacketSize); + +typedef VOID (*RECEIVE_COMPLETE_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext); + + +/* Protocol characteristics for NDIS 3.0 protocols */ +#ifdef _MSC_VER +typedef struct _NDIS30_PROTOCOL_CHARACTERISTICS +{ + UCHAR MajorNdisVersion; + UCHAR MinorNdisVersion; + union + { + UINT Reserved; + UINT Flags; + } u1; + OPEN_ADAPTER_COMPLETE_HANDLER OpenAdapterCompleteHandler; + CLOSE_ADAPTER_COMPLETE_HANDLER CloseAdapterCompleteHandler; + union + { + SEND_COMPLETE_HANDLER SendCompleteHandler; + WAN_SEND_COMPLETE_HANDLER WanSendCompleteHandler; + } u2; + union + { + TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler; + WAN_TRANSFER_DATA_COMPLETE_HANDLER WanTransferDataCompleteHandler; + } u3; + + RESET_COMPLETE_HANDLER ResetCompleteHandler; + REQUEST_COMPLETE_HANDLER RequestCompleteHandler; + union + { + RECEIVE_HANDLER ReceiveHandler; + WAN_RECEIVE_HANDLER WanReceiveHandler; + } u4; + RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler; + STATUS_HANDLER StatusHandler; + STATUS_COMPLETE_HANDLER StatusCompleteHandler; + NDIS_STRING Name; +} NDIS30_PROTOCOL_CHARACTERISTICS; +typedef NDIS30_PROTOCOL_CHARACTERISTICS NDIS30_PROTOCOL_CHARACTERISTICS_S; +#else +#define NDIS30_PROTOCOL_CHARACTERISTICS \ + UCHAR MajorNdisVersion; \ + UCHAR MinorNdisVersion; \ + union \ + { \ + UINT Reserved; \ + UINT Flags; \ + } u1; \ + OPEN_ADAPTER_COMPLETE_HANDLER OpenAdapterCompleteHandler; \ + CLOSE_ADAPTER_COMPLETE_HANDLER CloseAdapterCompleteHandler; \ + union \ + { \ + SEND_COMPLETE_HANDLER SendCompleteHandler; \ + WAN_SEND_COMPLETE_HANDLER WanSendCompleteHandler; \ + } u2; \ + union \ + { \ + TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler; \ + WAN_TRANSFER_DATA_COMPLETE_HANDLER WanTransferDataCompleteHandler; \ + } u3; \ + RESET_COMPLETE_HANDLER ResetCompleteHandler; \ + REQUEST_COMPLETE_HANDLER RequestCompleteHandler; \ + union \ + { \ + RECEIVE_HANDLER ReceiveHandler; \ + WAN_RECEIVE_HANDLER WanReceiveHandler; \ + } u4; \ + RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler; \ + STATUS_HANDLER StatusHandler; \ + STATUS_COMPLETE_HANDLER StatusCompleteHandler; \ + NDIS_STRING Name; +typedef struct _NDIS30_PROTOCOL_CHARACTERISTICS_S +{ + NDIS30_PROTOCOL_CHARACTERISTICS; +} NDIS30_PROTOCOL_CHARACTERISTICS_S, *PNDIS30_PROTOCOL_CHARACTERISTICS_S; +#endif + +/* Prototypes for NDIS 4.0 protocol characteristics */ + +typedef INT (*RECEIVE_PACKET_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_PACKET Packet); + +typedef VOID (*BIND_HANDLER)( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE BindContext, + IN PNDIS_STRING DeviceName, + IN PVOID SystemSpecific1, + IN PVOID SystemSpecific2); + +typedef VOID (*UNBIND_HANDLER)( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE UnbindContext); + +typedef VOID (*TRANSLATE_HANDLER)( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ProtocolBindingContext, + OUT PNET_PNP_ID IdList, + IN ULONG IdListLength, + OUT PULONG BytesReturned); + +typedef VOID (*UNLOAD_PROTOCOL_HANDLER)( + VOID); + + +/* Protocol characteristics for NDIS 4.0 protocols */ +#ifdef _MSC_VER +typedef struct _NDIS40_PROTOCOL_CHARACTERISTICS +{ + NDIS30_PROTOCOL_CHARACTERISTICS; + + RECEIVE_PACKET_HANDLER ReceivePacketHandler; + BIND_HANDLER BindAdapterHandler; + UNBIND_HANDLER UnbindAdapterHandler; + TRANSLATE_HANDLER TranslateHandler; + UNLOAD_PROTOCOL_HANDLER UnloadHandler; +} NDIS40_PROTOCOL_CHARACTERISTICS; +typedef NDIS40_PROTOCOL_CHARACTERISTICS NDIS40_PROTOCOL_CHARACTERISTICS_S; +#else +#define NDIS40_PROTOCOL_CHARACTERISTICS \ + NDIS30_PROTOCOL_CHARACTERISTICS; \ + RECEIVE_PACKET_HANDLER ReceivePacketHandler; \ + BIND_HANDLER BindAdapterHandler; \ + UNBIND_HANDLER UnbindAdapterHandler; \ + TRANSLATE_HANDLER TranslateHandler; \ + UNLOAD_PROTOCOL_HANDLER UnloadHandler; +typedef struct _NDIS40_PROTOCOL_CHARACTERISTICS_S +{ + NDIS40_PROTOCOL_CHARACTERISTICS; +} NDIS40_PROTOCOL_CHARACTERISTICS_S, *PNDIS40_PROTOCOL_CHARACTERISTICS_S; +#endif + + +/* Prototypes for NDIS 5.0 protocol characteristics */ + +#ifdef NDIS50 + +typedef VOID (*CO_SEND_COMPLETE_HANDLER)( + IN NDIS_STATUS Status, + IN NDIS_HANDLE ProtocolVcContext, + IN PNDIS_PACKET Packet); + +typedef VOID (*CO_STATUS_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE ProtocolVcContext OPTIONAL, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize); + +typedef UINT (*CO_RECEIVE_PACKET_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN NDIS_HANDLE ProtocolVcContext, + IN PNDIS_PACKET Packet); + +typedef VOID (*CO_AF_REGISTER_NOTIFY_HANDLER)( + IN NDIS_HANDLE ProtocolBindingContext, + IN PCO_ADDRESS_FAMILY AddressFamily); + +#ifdef _MSC_VER +typedef struct _NDIS50_PROTOCOL_CHARACTERISTICS +{ + NDIS40_PROTOCOL_CHARACTERISTICS; + + PVOID ReservedHandlers[4]; + + CO_SEND_COMPLETE_HANDLER CoSendCompleteHandler; + CO_STATUS_HANDLER CoStatusHandler; + CO_RECEIVE_PACKET_HANDLER CoReceivePacketHandler; + CO_AF_REGISTER_NOTIFY_HANDLER CoAfRegisterNotifyHandler; +} NDIS50_PROTOCOL_CHARACTERISTICS; +typedef NDIS50_PROTOCOL_CHARACTERISTICS NDIS50_PROTOCOL_CHARACTERISTICS_S; +#else +#define NDIS50_PROTOCOL_CHARACTERISTICS \ + NDIS40_PROTOCOL_CHARACTERISTICS; \ + PVOID ReservedHandlers[4]; \ + CO_SEND_COMPLETE_HANDLER CoSendCompleteHandler; \ + CO_STATUS_HANDLER CoStatusHandler; \ + CO_RECEIVE_PACKET_HANDLER CoReceivePacketHandler; \ + CO_AF_REGISTER_NOTIFY_HANDLER CoAfRegisterNotifyHandler; +typedef struct _NDIS50_PROTOCOL_CHARACTERISTICS_S +{ + NDIS50_PROTOCOL_CHARACTERISTICS; +} NDIS50_PROTOCOL_CHARACTERISTICS_S, *PNDIS50_PROTOCOL_CHARACTERISTICS_S; +#endif +#endif /* NDIS50 */ + + +#ifndef NDIS50 +#ifndef NDIS40 +typedef struct _NDIS_PROTOCOL_CHARACTERISTICS +{ + NDIS30_PROTOCOL_CHARACTERISTICS; +} NDIS_PROTOCOL_CHARACTERISTICS; +#else /* NDIS40 */ +typedef struct _NDIS_PROTOCOL_CHARACTERISTICS +{ + NDIS40_PROTOCOL_CHARACTERISTICS; +} NDIS_PROTOCOL_CHARACTERISTICS; +#endif /* NDIS40 */ +#else /* NDIS50 */ +typedef struct _NDIS_PROTOCOL_CHARACTERISTICS +{ + NDIS50_PROTOCOL_CHARACTERISTICS; +} NDIS_PROTOCOL_CHARACTERISTICS; +#endif /* NDIS50 */ + +typedef NDIS_PROTOCOL_CHARACTERISTICS *PNDIS_PROTOCOL_CHARACTERISTICS; + + + +/* Buffer management routines */ + +VOID +EXPIMP +NdisAllocateBuffer( + OUT PNDIS_STATUS Status, + OUT PNDIS_BUFFER *Buffer, + IN NDIS_HANDLE PoolHandle, + IN PVOID VirtualAddress, + IN UINT Length); + +VOID +EXPIMP +NdisAllocateBufferPool( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE PoolHandle, + IN UINT NumberOfDescriptors); + +VOID +EXPIMP +NdisAllocatePacket( + OUT PNDIS_STATUS Status, + OUT PNDIS_PACKET *Packet, + IN NDIS_HANDLE PoolHandle); + +VOID +EXPIMP +NdisAllocatePacketPool( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE PoolHandle, + IN UINT NumberOfDescriptors, + IN UINT ProtocolReservedLength); + +VOID +EXPIMP +NdisCopyBuffer( + OUT PNDIS_STATUS Status, + OUT PNDIS_BUFFER *Buffer, + IN NDIS_HANDLE PoolHandle, + IN PVOID MemoryDescriptor, + IN UINT Offset, + IN UINT Length); + +VOID +EXPIMP +NdisCopyFromPacketToPacket( + IN PNDIS_PACKET Destination, + IN UINT DestinationOffset, + IN UINT BytesToCopy, + IN PNDIS_PACKET Source, + IN UINT SourceOffset, + OUT PUINT BytesCopied); + +VOID +EXPIMP +NdisDprAllocatePacket( + OUT PNDIS_STATUS Status, + OUT PNDIS_PACKET *Packet, + IN NDIS_HANDLE PoolHandle); + +VOID +EXPIMP +NdisDprAllocatePacketNonInterlocked( + OUT PNDIS_STATUS Status, + OUT PNDIS_PACKET *Packet, + IN NDIS_HANDLE PoolHandle); + +VOID +EXPIMP +NdisDprFreePacket( + IN PNDIS_PACKET Packet); + +VOID +EXPIMP +NdisDprFreePacketNonInterlocked( + IN PNDIS_PACKET Packet); + +VOID +EXPIMP +NdisFreeBufferPool( + IN NDIS_HANDLE PoolHandle); + +VOID +EXPIMP +NdisFreePacket( + IN PNDIS_PACKET Packet); + +VOID +EXPIMP +NdisFreePacketPool( + IN NDIS_HANDLE PoolHandle); + +VOID +EXPIMP +NdisReturnPackets( + IN PNDIS_PACKET *PacketsToReturn, + IN UINT NumberOfPackets); + +VOID +EXPIMP +NdisUnchainBufferAtBack( + IN OUT PNDIS_PACKET Packet, + OUT PNDIS_BUFFER *Buffer); + +VOID +EXPIMP +NdisUnchainBufferAtFront( + IN OUT PNDIS_PACKET Packet, + OUT PNDIS_BUFFER *Buffer); + +#if BINARY_COMPATIBLE + +VOID +EXPIMP +NdisAdjustBufferLength( + IN PNDIS_BUFFER Buffer, + IN UINT Length); + +ULONG +EXPIMP +NDIS_BUFFER_TO_SPAN_PAGES( + IN PNDIS_BUFFER Buffer); + +VOID +EXPIMP +NdisFreeBuffer( + IN PNDIS_BUFFER Buffer); + +VOID +EXPIMP +NdisGetBufferPhysicalArraySize( + IN PNDIS_BUFFER Buffer, + OUT PUINT ArraySize); + +VOID +EXPIMP +NdisGetFirstBufferFromPacket( + IN PNDIS_PACKET _Packet, + OUT PNDIS_BUFFER *_FirstBuffer, + OUT PVOID *_FirstBufferVA, + OUT PUINT _FirstBufferLength, + OUT PUINT _TotalBufferLength); + +VOID +EXPIMP +NdisQueryBuffer( + IN PNDIS_BUFFER Buffer, + OUT PVOID *VirtualAddress OPTIONAL, + OUT PUINT Length); + +VOID +EXPIMP +NdisQueryBufferOffset( + IN PNDIS_BUFFER Buffer, + OUT PUINT Offset, + OUT PUINT Length); + +#else /* BINARY_COMPATIBLE */ + +/* + * PVOID NdisAdjustBufferLength( + * IN PNDIS_BUFFER Buffer, + * IN UINT Length); + */ +#define NdisAdjustBufferLength(Buffer, \ + Length) \ +{ \ + (Buffer)->ByteCount = (Length); \ +} + + +/* + * ULONG NDIS_BUFFER_TO_SPAN_PAGES( + * IN PNDIS_BUFFER Buffer); + */ +#define NDIS_BUFFER_TO_SPAN_PAGES(Buffer) \ +( \ + MmGetMdlByteCount(Buffer) == 0 ? \ + 1 : \ + ADDRESS_AND_SIZE_TO_SPAN_PAGES( \ + MmGetMdlVirtualAddress(Buffer), \ + MmGetMdlByteCount(Buffer)) \ +) + + +#if 0 + +/* + * VOID NdisFreeBuffer( + * IN PNDIS_BUFFER Buffer); + */ +#define NdisFreeBuffer(Buffer) \ +{ \ + IoFreeMdl(Buffer) /* ??? */ \ +} + +#else + +VOID +EXPIMP +NdisFreeBuffer( + IN PNDIS_BUFFER Buffer); + +#endif + + +/* + * VOID NdisGetBufferPhysicalArraySize( + * IN PNDIS_BUFFER Buffer, + * OUT PUINT ArraySize); + */ +#define NdisGetBufferPhysicalArraySize(Buffer, \ + ArraySize) \ +{ \ +} + + +/* + * VOID NdisGetFirstBufferFromPacket( + * IN PNDIS_PACKET _Packet, + * OUT PNDIS_BUFFER * _FirstBuffer, + * OUT PVOID * _FirstBufferVA, + * OUT PUINT _FirstBufferLength, + * OUT PUINT _TotalBufferLength) + */ +#define NdisGetFirstBufferFromPacket(Packet, \ + FirstBuffer, \ + FirstBufferVA, \ + FirstBufferLength, \ + TotalBufferLength) \ +{ \ + PNDIS_BUFFER _Buffer; \ + \ + _Buffer = (Packet)->Private.Head; \ + *(FirstBuffer) = _Buffer; \ + *(FirstBufferVA) = MmGetMdlVirtualAddress(_Buffer); \ + if (_Buffer != NULL) { \ + *(FirstBufferLength) = MmGetMdlByteCount(_Buffer); \ + _Buffer = _Buffer->Next; \ + } else \ + *(FirstBufferLength) = 0; \ + *(TotalBufferLength) = *(FirstBufferLength); \ + while (_Buffer != NULL) { \ + *(TotalBufferLength) += MmGetMdlByteCount(_Buffer); \ + _Buffer = _Buffer->Next; \ + } \ +} + +/* + * VOID NdisQueryBuffer( + * IN PNDIS_BUFFER Buffer, + * OUT PVOID *VirtualAddress OPTIONAL, + * OUT PUINT Length) + */ +#define NdisQueryBuffer(Buffer, \ + VirtualAddress, \ + Length) \ +{ \ + if (VirtualAddress) \ + *((PVOID*)VirtualAddress) = MmGetSystemAddressForMdl(Buffer); \ + \ + *((PUINT)Length) = MmGetMdlByteCount(Buffer); \ +} + + +/* + * VOID NdisQueryBufferOffset( + * IN PNDIS_BUFFER Buffer, + * OUT PUINT Offset, + * OUT PUINT Length); + */ +#define NdisQueryBufferOffset(Buffer, \ + Offset, \ + Length) \ +{ \ + *((PUINT)Offset) = MmGetMdlByteOffset(Buffer); \ + *((PUINT)Length) = MmGetMdlByteCount(Buffer); \ +} + +#endif /* BINARY_COMPATIBLE */ + + +/* + * PVOID NDIS_BUFFER_LINKAGE( + * IN PNDIS_BUFFER Buffer); + */ +#define NDIS_BUFFER_LINKAGE(Buffer) \ +{ \ + (Buffer)->Next; \ +} + + +/* + * VOID NdisChainBufferAtBack( + * IN OUT PNDIS_PACKET Packet, + * IN OUT PNDIS_BUFFER Buffer) + */ +#define NdisChainBufferAtBack(Packet, \ + Buffer) \ +{ \ + PNDIS_BUFFER NdisBuffer = (Buffer); \ + \ + while (NdisBuffer->Next != NULL) \ + NdisBuffer = NdisBuffer->Next; \ + \ + NdisBuffer->Next = NULL; \ + \ + if ((Packet)->Private.Head != NULL) \ + (Packet)->Private.Tail->Next = (Buffer); \ + else \ + (Packet)->Private.Head = (Buffer); \ + \ + (Packet)->Private.Tail = NdisBuffer; \ + (Packet)->Private.ValidCounts = FALSE; \ +} + + +/* + * VOID NdisChainBufferAtFront( + * IN OUT PNDIS_PACKET Packet, + * IN OUT PNDIS_BUFFER Buffer) + */ +#define NdisChainBufferAtFront(Packet, \ + Buffer) \ +{ \ + PNDIS_BUFFER _NdisBuffer = (Buffer); \ + \ + while (_NdisBuffer->Next != NULL) \ + _NdisBuffer = _NdisBuffer->Next; \ + \ + if ((Packet)->Private.Head == NULL) \ + (Packet)->Private.Tail = _NdisBuffer; \ + \ + _NdisBuffer->Next = (Packet)->Private.Head; \ + (Packet)->Private.Head = (Buffer); \ + (Packet)->Private.ValidCounts = FALSE; \ +} + + +/* + * VOID NdisGetNextBuffer( + * IN PNDIS_BUFFER CurrentBuffer, + * OUT PNDIS_BUFFER * NextBuffer) + */ +#define NdisGetNextBuffer(CurrentBuffer, \ + NextBuffer) \ +{ \ + *(NextBuffer) = (CurrentBuffer)->Next; \ +} + + +/* + * UINT NdisGetPacketFlags( + * IN PNDIS_PACKET Packet); + */ +#define NdisGetPacketFlags(Packet) \ +{ \ + (Packet)->Private.Flags; \ +} + + +/* + * UINT NDIS_GET_PACKET_HEADER_SIZE( + * IN PNDIS_PACKET Packet); + */ +#define NDIS_GET_PACKET_HEADER_SIZE(Packet) \ +{ \ +} + + +/* + * VOID NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO( + * IN PNDIS_PACKET Packet, + * IN PPVOID pMediaSpecificInfo, + * IN PUINT pSizeMediaSpecificInfo); + */ +#define NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, \ + pMediaSpecificInfo, \ + pSizeMediaSpecificInfo) \ +{ \ +} + + +/* + * VOID NDIS_STATUS NDIS_GET_PACKET_STATUS( + * IN PNDIS_PACKET Packet); + */ +#define NDIS_GET_PACKET_STATUS (Packet) \ +{ \ +} + + +/* + * ULONGLONG NDIS_GET_PACKET_TIME_RECEIVED( + * IN PNDIS_PACKET Packet); + */ +#define NDIS_GET_PACKET_TIME_RECEIVED(Packet) \ +{ \ +} + + +/* + * ULONGLONG NDIS_GET_PACKET_TIME_SENT( + * IN PNDIS_PACKET Packet); + */ +#define NDIS_GET_PACKET_TIME_SENT(Packet) \ +{ \ +} + + +/* + * ULONGLONG NDIS_GET_PACKET_TIME_TO_SEND( + * IN PNDIS_PACKET Packet); + */ +#define NDIS_GET_PACKET_TIME_TO_SEND(Packet) \ +{ \ +} + + +/* + * PNDIS_PACKET_OOB_DATA NDIS_OOB_DATA_FROM_PACKET( + * IN PNDIS_PACKET _Packet); + */ +#define NDIS_OOB_DATA_FROM_PACKET(_Packet) \ +{ \ +} + + +/* + * VOID NdisQueryPacket( + * IN PNDIS_PACKET Packet, + * OUT PUINT PhysicalBufferCount OPTIONAL, + * OUT PUINT BufferCount OPTIONAL, + * OUT PNDIS_BUFFER *FirstBuffer OPTIONAL, + * OUT PUINT TotalPacketLength OPTIONAL); + */ +#define NdisQueryPacket(Packet, \ + PhysicalBufferCount, \ + BufferCount, \ + FirstBuffer, \ + TotalPacketLength) \ +{ \ + if (FirstBuffer) \ + *((PNDIS_BUFFER*)FirstBuffer) = (Packet)->Private.Head; \ + if ((TotalPacketLength) || (BufferCount) || (PhysicalBufferCount)) { \ + if (!(Packet)->Private.ValidCounts) { \ + UINT _Offset; \ + UINT _PacketLength; \ + PNDIS_BUFFER _NdisBuffer; \ + UINT _PhysicalBufferCount = 0; \ + UINT _TotalPacketLength = 0; \ + UINT _Count = 0; \ + \ + for (_NdisBuffer = (Packet)->Private.Head; \ + _NdisBuffer != (PNDIS_BUFFER)NULL; \ + _NdisBuffer = _NdisBuffer->Next) { \ + _PhysicalBufferCount += NDIS_BUFFER_TO_SPAN_PAGES(_NdisBuffer); \ + NdisQueryBufferOffset(_NdisBuffer, &_Offset, &_PacketLength); \ + _TotalPacketLength += _PacketLength; \ + _Count++; \ + } \ + (Packet)->Private.PhysicalCount = _PhysicalBufferCount; \ + (Packet)->Private.TotalLength = _TotalPacketLength; \ + (Packet)->Private.Count = _Count; \ + (Packet)->Private.ValidCounts = TRUE; \ + } \ + \ + if (PhysicalBufferCount) \ + *((PUINT)PhysicalBufferCount) = (Packet)->Private.PhysicalCount; \ + \ + if (BufferCount) \ + *((PUINT)BufferCount) = (Packet)->Private.Count; \ + \ + if (TotalPacketLength) \ + *((PUINT)TotalPacketLength) = (Packet)->Private.TotalLength; \ + } \ +} + + +/* + * VOID NdisRecalculatePacketCounts( + * IN OUT PNDIS_PACKET Packet); + */ +#define NdisRecalculatePacketCounts(Packet) \ +{ \ +} + +VOID +EXPIMP +NdisReinitializePacket( + IN OUT PNDIS_PACKET Packet); + + +/* + * VOID NdisSetPacketFlags( + * IN PNDIS_PACKET Packet, + * IN UINT Flags); + */ +#define NdisSetPacketFlags(Packet, Flags) \ + (Packet)->Private.Flags = (Flags); + + +/* + * NDIS_SET_PACKET_HEADER_SIZE( + * IN PNDIS_PACKET Packet, + * IN UINT HdrSize); + */ +#define NDIS_SET_PACKET_HEADER_SIZE(Packet, \ + HdrSize) \ +{ \ +} + + +/* + * NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO( + * IN PNDIS_PACKET Packet, + * IN PVOID MediaSpecificInfo, + * IN UINT SizeMediaSpecificInfo); + */ +#define NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(Packet, \ + MediaSpecificInfo, \ + SizeMediaSpecificInfo) \ +{ \ +} + + +/* + * NDIS_SET_PACKET_STATUS( + * IN PNDIS_PACKET Packet, + * IN NDIS_STATUS Status); + */ +#define NDIS_SET_PACKET_STATUS(Packet, \ + Status) \ +{ \ +} + + +/* + * NDIS_SET_PACKET_TIME_RECEIVED( + * IN PNDIS_PACKET Packet, + * IN ULONGLONG TimeReceived); + */ +#define NDIS_SET_PACKET_TIME_RECEIVED(Packet) \ + TimeReceived) \ +{ \ +} + + +/* + * NDIS_SET_PACKET_TIME_SENT( + * IN PNDIS_PACKET Packet, + * IN ULONGLONG TimeSent); + */ +#define NDIS_SET_PACKET_TIME_SENT(Packet, \ + TimeSent) \ +{ \ +} + + +/* + * + * NDIS_SET_PACKET_TIME_TO_SEND( + * IN PNDIS_PACKET Packet, + * IN ULONGLONG TimeToSend); + */ +#define NDIS_SET_PACKET_TIME_TO_SEND(Packet, \ + TimeToSend) \ +{ \ +} + + +/* + * VOID NdisSetSendFlags( + * IN PNDIS_PACKET Packet, + * IN UINT Flags); + */ +#define NdisSetSendFlags(Packet, Flags)( \ + NdisSetPacketFlags((Packet), (Flags))) + + + +/* Memory management routines */ + +VOID +EXPIMP +NdisCreateLookaheadBufferFromSharedMemory( + IN PVOID pSharedMemory, + IN UINT LookaheadLength, + OUT PVOID *pLookaheadBuffer); + +VOID +EXPIMP +NdisDestroyLookaheadBufferFromSharedMemory( + IN PVOID pLookaheadBuffer); + +VOID +EXPIMP +NdisMoveFromMappedMemory( + OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length); + +VOID +EXPIMP +NdisMoveMappedMemory( + OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length); + +VOID +EXPIMP +NdisMoveToMappedMemory( + OUT PVOID Destination, + IN PVOID Source, + IN ULONG Length); + +VOID +EXPIMP +NdisMUpdateSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +NDIS_STATUS +EXPIMP +NdisAllocateMemory( + OUT PVOID *VirtualAddress, + IN UINT Length, + IN UINT MemoryFlags, + IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress); + +VOID +EXPIMP +NdisFreeMemory( + IN PVOID VirtualAddress, + IN UINT Length, + IN UINT MemoryFlags); + +VOID +EXPIMP +NdisImmediateReadSharedMemory( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SharedMemoryAddress, + OUT PUCHAR Buffer, + IN ULONG Length); + +VOID +EXPIMP +NdisImmediateWriteSharedMemory( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SharedMemoryAddress, + IN PUCHAR Buffer, + IN ULONG Length); + +VOID +EXPIMP +NdisMAllocateSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +NDIS_STATUS +EXPIMP +NdisMAllocateSharedMemoryAsync( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID Context); + +VOID +EXPIMP +NdisMFreeSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +VOID +EXPIMP +NdisUpdateSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + + +/* + * ULONG NdisGetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define NdisGetPhysicalAddressHigh(PhysicalAddress) \ + ((PhysicalAddress).HighPart) + +/* + * VOID NdisSetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define NdisSetPhysicalAddressHigh(PhysicalAddress, Value) \ + ((PhysicalAddress).HighPart) = (Value) + +/* + * ULONG NdisGetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define NdisGetPhysicalAddressLow(PhysicalAddress) \ + ((PhysicalAddress).LowPart) + + +/* + * VOID NdisSetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define NdisSetPhysicalAddressLow(PhysicalAddress, Value) \ + ((PhysicalAddress).LowPart) = (Value) + +/* + * VOID NDIS_PHYSICAL_ADDRESS_CONST( + * IN ULONG Low, + * IN LONG High); + */ +#define NDIS_PHYSICAL_ADDRESS_CONST(Low, High) \ + { {(ULONG)(Low), (LONG)(High)} } + + +/* + * VOID NdisMoveMemory( + * OUT PVOID Destination, + * IN PVOID Source, + * IN ULONG Length); + */ +#define NdisMoveMemory(Destination, Source, Length) \ + RtlCopyMemory(Destination, Source, Length) + + +/* + * VOID NdisRetrieveUlong( + * IN PULONG DestinationAddress, + * IN PULONG SourceAddress); + */ +#define NdisRetrieveUlong(DestinationAddress, SourceAddress) \ + RtlRetrieveUlong(DestinationAddress, SourceAddress) + + +/* + * VOID NdisStoreUlong( + * IN PULONG DestinationAddress, + * IN ULONG Value); + */ +#define NdisStoreUlong(DestinationAddress, Value) \ + RtlStoreUlong(DestinationAddress, Value) + + +/* + * VOID NdisZeroMemory( + * IN PVOID Destination, + * IN ULONG Length) + */ +#define NdisZeroMemory(Destination, Length) \ + RtlZeroMemory(Destination, Length) + + + +// +// System processor count +// + +CCHAR +EXPIMP +NdisSystemProcessorCount( + VOID + ); + +VOID +EXPIMP +NdisImmediateReadPortUchar( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + OUT PUCHAR Data + ); + +VOID +EXPIMP +NdisImmediateReadPortUshort( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + OUT PUSHORT Data + ); + +VOID +EXPIMP +NdisImmediateReadPortUlong( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + OUT PULONG Data + ); + +VOID +EXPIMP +NdisImmediateWritePortUchar( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + IN UCHAR Data + ); + +VOID +EXPIMP +NdisImmediateWritePortUshort( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + IN USHORT Data + ); + +VOID +EXPIMP +NdisImmediateWritePortUlong( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG Port, + IN ULONG Data + ); + +VOID +EXPIMP +NdisImmediateReadSharedMemory( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SharedMemoryAddress, + IN PUCHAR Buffer, + IN ULONG Length + ); + +VOID +EXPIMP +NdisImmediateWriteSharedMemory( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SharedMemoryAddress, + IN PUCHAR Buffer, + IN ULONG Length + ); + +ULONG +EXPIMP +NdisImmediateReadPciSlotInformation( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SlotNumber, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length + ); + +ULONG +EXPIMP +NdisImmediateWritePciSlotInformation( + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SlotNumber, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length + ); + +/* String management routines */ + +#if BINARY_COMPATIBLE + +NDIS_STATUS +EXPIMP +NdisAnsiStringToUnicodeString( + IN OUT PNDIS_STRING DestinationString, + IN PNDIS_ANSI_STRING SourceString); + +BOOLEAN +EXPIMP +NdisEqualString( + IN PNDIS_STRING String1, + IN PNDIS_STRING String2, + IN BOOLEAN CaseInsensitive); + +VOID +EXPIMP +NdisInitAnsiString( + IN OUT PNDIS_ANSI_STRING DestinationString, + IN PCSTR SourceString); + +VOID +EXPIMP +NdisInitUnicodeString( + IN OUT PNDIS_STRING DestinationString, + IN PCWSTR SourceString); + +NDIS_STATUS +EXPIMP +NdisUnicodeStringToAnsiString( + IN OUT PNDIS_ANSI_STRING DestinationString, + IN PNDIS_STRING SourceString); + +#else /* BINARY_COMPATIBLE */ + +/* + * NDIS_STATUS NdisAnsiStringToUnicodeString( + * IN OUT PNDIS_STRING DestinationString, + * IN PNDIS_ANSI_STRING SourceString); + */ +#define NdisAnsiStringToUnicodeString(DestinationString, \ + SourceString) \ + RtlAnsiStringToUnicodeString((DestinationString), (SourceString), FALSE) + +/* + * BOOLEAN NdisEqualString( + * IN PNDIS_STRING String1, + * IN PNDIS_STRING String2, + * IN BOOLEAN CaseInsensitive) + */ +#define NdisEqualString(String1, \ + String2, \ + CaseInsensitive) \ + RtlEqualUnicodeString((String1), (String2), (CaseInsensitive)) + +/* + * VOID NdisInitAnsiString( + * IN OUT PNDIS_ANSI_STRING DestinationString, + * IN PCSTR SourceString) + */ +#define NdisInitAnsiString(DestinationString, \ + SourceString) \ + RtlInitString((DestinationString), (SourceString)) + +/* + * VOID NdisInitUnicodeString( + * IN OUT PNDIS_STRING DestinationString, + * IN PCWSTR SourceString) + */ +#define NdisInitUnicodeString(DestinationString, \ + SourceString) \ + RtlInitUnicodeString((DestinationString), (SourceString)) + +/* + * NDIS_STATUS NdisUnicodeStringToAnsiString( + * IN OUT PNDIS_ANSI_STRING DestinationString, + * IN PNDIS_STRING SourceString) + */ +#define NdisUnicodeStringToAnsiString(DestinationString, \ + SourceString) \ + RtlUnicodeStringToAnsiString((DestinationString), (SourceString), FALSE) + +#endif /* BINARY_COMPATIBLE */ + +#define NdisFreeString(_s) NdisFreeMemory((s).Buffer, (s).MaximumLength, 0) +#define NdisPrintString(_s) DbgPrint("%ls", (s).Buffer) + + + +/* I/O routines */ + +/* + * VOID NdisRawReadPortBufferUchar( + * IN ULONG Port, + * OUT PUCHAR Buffer, + * IN ULONG Length); + */ +#define NdisRawReadPortBufferUchar(Port, Buffer, Length) \ + READ_PORT_BUFFER_UCHAR((PUCHAR)(Port), (PUCHAR)(Buffer), (Length)) + +/* + * VOID NdisRawReadPortBufferUlong( + * IN ULONG Port, + * OUT PULONG Buffer, + * IN ULONG Length); + */ +#define NdisRawReadPortBufferUlong(Port, Buffer, Length) \ + READ_PORT_BUFFER_ULONG((PULONG)(Port), (PULONG)(Buffer), (Length)) + +/* + * VOID NdisRawReadPortBufferUshort( + * IN ULONG Port, + * OUT PUSHORT Buffer, + * IN ULONG Length); + */ +#define NdisRawReadPortBufferUshort(Port, Buffer, Length) \ + READ_PORT_BUFFER_USHORT((PUSHORT)(Port), (PUSHORT)(Buffer), (Length)) + + +/* + * VOID NdisRawReadPortUchar( + * IN ULONG Port, + * OUT PUCHAR Data); + */ +#define NdisRawReadPortUchar(Port, Data) \ + *(Data) = READ_PORT_UCHAR((PUCHAR)(Port)) + +/* + * VOID NdisRawReadPortUlong( + * IN ULONG Port, + * OUT PULONG Data); + */ +#define NdisRawReadPortUlong(Port, Data) \ + *(Data) = READ_PORT_ULONG((PULONG)(Port)) + +/* + * VOID NdisRawReadPortUshort( + * IN ULONG Port, + * OUT PUSHORT Data); + */ +#define NdisRawReadPortUshort(Port, Data) \ + *(Data) = READ_PORT_USHORT((PUSHORT)(Port)) + + +/* + * VOID NdisRawWritePortBufferUchar( + * IN ULONG Port, + * IN PUCHAR Buffer, + * IN ULONG Length); + */ +#define NdisRawWritePortBufferUchar(Port, Buffer, Length) \ + WRITE_PORT_BUFFER_UCHAR((PUCHAR)(Port), (PUCHAR)(Buffer), (Length)) + +/* + * VOID NdisRawWritePortBufferUlong( + * IN ULONG Port, + * IN PULONG Buffer, + * IN ULONG Length); + */ +#define NdisRawWritePortBufferUlong(Port, Buffer, Length) \ + WRITE_PORT_BUFFER_ULONG((PULONG)(Port), (PULONG)(Buffer), (Length)) + +/* + * VOID NdisRawWritePortBufferUshort( + * IN ULONG Port, + * IN PUSHORT Buffer, + * IN ULONG Length); + */ +#define NdisRawWritePortBufferUshort(Port, Buffer, Length) \ + WRITE_PORT_BUFFER_USHORT((PUSHORT)(Port), (PUSHORT)(Buffer), (Length)) + + +/* + * VOID NdisRawWritePortUchar( + * IN ULONG Port, + * IN UCHAR Data); + */ +#define NdisRawWritePortUchar(Port, Data) \ + WRITE_PORT_UCHAR((PUCHAR)(Port), (UCHAR)(Data)) + +/* + * VOID NdisRawWritePortUlong( + * IN ULONG Port, + * IN ULONG Data); + */ +#define NdisRawWritePortUlong(Port, Data) \ + WRITE_PORT_ULONG((PULONG)(Port), (ULONG)(Data)) + +/* + * VOID NdisRawWritePortUshort( + * IN ULONG Port, + * IN USHORT Data); + */ +#define NdisRawWritePortUshort(Port, Data) \ + WRITE_PORT_USHORT((PUSHORT)(Port), (USHORT)(Data)) + + +/* + * VOID NdisReadRegisterUchar( + * IN PUCHAR Register, + * OUT PUCHAR Data); + */ +#define NdisReadRegisterUchar(Register, Data) \ + *((PUCHAR)(Data)) = *(Register) + +/* + * VOID NdisReadRegisterUlong( + * IN PULONG Register, + * OUT PULONG Data); + */ +#define NdisReadRegisterUlong(Register, Data) \ + *((PULONG)(Data)) = *(Register) + +/* + * VOID NdisReadRegisterUshort( + * IN PUSHORT Register, + * OUT PUSHORT Data); + */ +#define NdisReadRegisterUshort(Register, Data) \ + *((PUSHORT)(Data)) = *(Register) + + +/* + * VOID NdisReadRegisterUchar( + * IN PUCHAR Register, + * IN UCHAR Data); + */ +#define NdisWriteRegisterUchar(Register, Data) \ + WRITE_REGISTER_UCHAR((Register), (Data)) + +/* + * VOID NdisReadRegisterUlong( + * IN PULONG Register, + * IN ULONG Data); + */ +#define NdisWriteRegisterUlong(Register, Data) \ + WRITE_REGISTER_ULONG((Register), (Data)) + +/* + * VOID NdisReadRegisterUshort( + * IN PUSHORT Register, + * IN USHORT Data); + */ +#define NdisWriteRegisterUshort(Register, Data) \ + WRITE_REGISTER_USHORT((Register), (Data)) + + +/* Linked lists */ + +VOID +EXPIMP +NdisInitializeListHead( + IN PLIST_ENTRY ListHead); + +VOID +EXPIMP +NdisInterlockedAddUlong( + IN PULONG Addend, + IN ULONG Increment, + IN PNDIS_SPIN_LOCK SpinLock); + +PLIST_ENTRY +EXPIMP +NdisInterlockedInsertHeadList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PNDIS_SPIN_LOCK SpinLock); + +PLIST_ENTRY +EXPIMP +NdisInterlockedInsertTailList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PNDIS_SPIN_LOCK SpinLock); + +PLIST_ENTRY +EXPIMP +NdisInterlockedRemoveHeadList( + IN PLIST_ENTRY ListHead, + IN PNDIS_SPIN_LOCK SpinLock); + + +VOID +EXPIMP +NdisCloseConfiguration( + IN NDIS_HANDLE ConfigurationHandle); + +VOID +EXPIMP +NdisReadConfiguration( + OUT PNDIS_STATUS Status, + OUT PNDIS_CONFIGURATION_PARAMETER *ParameterValue, + IN NDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING Keyword, + IN NDIS_PARAMETER_TYPE ParameterType); + +VOID +EXPIMP +NdisWriteConfiguration( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PNDIS_STRING Keyword, + IN PNDIS_CONFIGURATION_PARAMETER *ParameterValue); + +/* +VOID +EXPIMP +NdisWriteErrorLogEntry( + IN NDIS_HANDLE NdisAdapterHandle, + IN NDIS_ERROR_CODE ErrorCode, + IN ULONG NumberOfErrorValues, + IN ULONG ...); +*/ + + + +/* + * VOID NdisStallExecution( + * IN UINT MicrosecondsToStall) + */ +#define NdisStallExecution(MicroSecondsToStall) \ + KeStallExecutionProcessor(MicroSecondsToStall) + + +#define NdisZeroMappedMemory(Destination,Length) RtlZeroMemory(Destination,Length) +/* moved to ndis/memory.c by robd +#define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length) + */ +/* moved to ndis/control.c by robd +#define NdisReinitializePacket(Packet) \ +{ \ + (Packet)->Private.Head = (PNDIS_BUFFER)NULL; \ + (Packet)->Private.ValidCounts = FALSE; \ +} + */ +VOID +EXPIMP +NdisInitializeEvent( + IN PNDIS_EVENT Event +); + +VOID +EXPIMP +NdisSetEvent( + IN PNDIS_EVENT Event +); + +VOID +EXPIMP +NdisResetEvent( + IN PNDIS_EVENT Event +); + +BOOLEAN +EXPIMP +NdisWaitEvent( + IN PNDIS_EVENT Event, + IN UINT msToWait +); + + +/* NDIS helper macros */ + +/* + * NDIS_INIT_FUNCTION(FunctionName) + */ +#define NDIS_INIT_FUNCTION(FunctionName) \ + alloc_text(init, FunctionName) + +/* + * NDIS_PAGABLE_FUNCTION(FunctionName) + */ +#define NDIS_PAGABLE_FUNCTION(FunctionName) \ + alloc_text(page, FunctionName) + + + +/* NDIS 4.0 extensions */ + +#ifdef NDIS40 + +VOID +EXPIMP +NdisMFreeSharedMemory( + IN NDIS_HANDLE MiniportAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +VOID +EXPIMP +NdisMWanIndicateReceive( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisLinkContext, + IN PUCHAR PacketBuffer, + IN UINT PacketSize); + +VOID +EXPIMP +NdisMWanIndicateReceiveComplete( + IN NDIS_HANDLE MiniportAdapterHandle); + +VOID +EXPIMP +NdisMWanSendComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_WAN_PACKET Packet, + IN NDIS_STATUS Status); + +NDIS_STATUS +EXPIMP +NdisPciAssignResources( + IN NDIS_HANDLE NdisMacHandle, + IN NDIS_HANDLE NdisWrapperHandle, + IN NDIS_HANDLE WrapperConfigurationContext, + IN ULONG SlotNumber, + OUT PNDIS_RESOURCE_LIST *AssignedResources); + +VOID +EXPIMP +NdisReadEisaSlotInformationEx( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + OUT PUINT SlotNumber, + OUT PNDIS_EISA_FUNCTION_INFORMATION *EisaData, + OUT PUINT NumberOfFunctions); + +VOID +EXPIMP +NdisReadMcaPosInformation( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PUINT ChannelNumber, + OUT PNDIS_MCA_POS_DATA McaData); + +#endif /* NDIS40 */ + + +#if USE_KLOCKS + +#define DISPATCH_LEVEL 2 + +#define NdisAllocateSpinLock(_SpinLock) KeInitializeSpinLock(&(_SpinLock)->SpinLock) + +#define NdisFreeSpinLock(_SpinLock) + +#define NdisAcquireSpinLock(_SpinLock) KeAcquireSpinLock(&(_SpinLock)->SpinLock, &(_SpinLock)->OldIrql) + +#define NdisReleaseSpinLock(_SpinLock) KeReleaseSpinLock(&(_SpinLock)->SpinLock,(_SpinLock)->OldIrql) + +#define NdisDprAcquireSpinLock(_SpinLock) \ +{ \ + KeAcquireSpinLockAtDpcLevel(&(_SpinLock)->SpinLock); \ + (_SpinLock)->OldIrql = DISPATCH_LEVEL; \ +} + +#define NdisDprReleaseSpinLock(_SpinLock) KeReleaseSpinLockFromDpcLevel(&(_SpinLock)->SpinLock) + +#else + +// +// Ndis Spin Locks +// + +VOID +EXPIMP +NdisAllocateSpinLock( + IN PNDIS_SPIN_LOCK SpinLock + ); + + +VOID +EXPIMP +NdisFreeSpinLock( + IN PNDIS_SPIN_LOCK SpinLock + ); + + +VOID +EXPIMP +NdisAcquireSpinLock( + IN PNDIS_SPIN_LOCK SpinLock + ); + + +VOID +EXPIMP +NdisReleaseSpinLock( + IN PNDIS_SPIN_LOCK SpinLock + ); + + +VOID +EXPIMP +NdisDprAcquireSpinLock( + IN PNDIS_SPIN_LOCK SpinLock + ); + + +VOID +EXPIMP +NdisDprReleaseSpinLock( + IN PNDIS_SPIN_LOCK SpinLock + ); + +#endif + +VOID +EXPIMP +NdisGetCurrentSystemTime( + PLONGLONG pSystemTime + ); + + +/* NDIS 5.0 extensions */ + +#ifdef NDIS50 + +VOID +EXPIMP +NdisAcquireReadWriteLock( + IN PNDIS_RW_LOCK Lock, + IN BOOLEAN fWrite, + IN PLOCK_STATE LockState); + +NDIS_STATUS +EXPIMP +NdisAllocateMemoryWithTag( + OUT PVOID *VirtualAddress, + IN UINT Length, + IN ULONG Tag); + +VOID +EXPIMP +NdisAllocatePacketPoolEx( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE PoolHandle, + IN UINT NumberOfDescriptors, + IN UINT NumberOfOverflowDescriptors, + IN UINT ProtocolReservedLength); + +ULONG +EXPIMP +NdisBufferLength( + IN PNDIS_BUFFER Buffer); + +PVOID +EXPIMP +NdisBufferVirtualAddress( + IN PNDIS_BUFFER Buffer); + +VOID +EXPIMP +NdisCompletePnPEvent( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN PNET_PNP_EVENT NetPnPEvent); + +VOID +EXPIMP +NdisConvertStringToAtmAddress( + OUT PNDIS_STATUS Status, + IN PNDIS_STRING String, + OUT PATM_ADDRESS AtmAddress); + +VOID +EXPIMP +NdisGetCurrentProcessorCounts( + OUT PULONG pIdleCount, + OUT PULONG pKernelAndUser, + OUT PULONG pIndex); + +VOID +EXPIMP +NdisGetDriverHandle( + IN PNDIS_HANDLE NdisBindingHandle, + OUT PNDIS_HANDLE NdisDriverHandle); + +PNDIS_PACKET +EXPIMP +NdisGetReceivedPacket( + IN PNDIS_HANDLE NdisBindingHandle, + IN PNDIS_HANDLE MacContext); + +VOID +EXPIMP +NdisGetSystemUptime( + OUT PULONG pSystemUpTime); + +VOID +EXPIMP +NdisInitializeReadWriteLock( + IN PNDIS_RW_LOCK Lock); + +LONG +EXPIMP +NdisInterlockedDecrement( + IN PLONG Addend); + +LONG +EXPIMP +NdisInterlockedIncrement( + IN PLONG Addend); + +PSINGLE_LIST_ENTRY +EXPIMP +NdisInterlockedPopEntrySList( + IN PSLIST_HEADER ListHead, + IN PKSPIN_LOCK Lock); + +PSINGLE_LIST_ENTRY +EXPIMP +NdisInterlockedPushEntrySList( + IN PSLIST_HEADER ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock); + + +NDIS_STATUS +EXPIMP +NdisMDeregisterDevice( + IN NDIS_HANDLE NdisDeviceHandle); + +VOID +EXPIMP +NdisMGetDeviceProperty( + IN NDIS_HANDLE MiniportAdapterHandle, + IN OUT PDEVICE_OBJECT *PhysicalDeviceObject OPTIONAL, + IN OUT PDEVICE_OBJECT *FunctionalDeviceObject OPTIONAL, + IN OUT PDEVICE_OBJECT *NextDeviceObject OPTIONAL, + IN OUT PCM_RESOURCE_LIST *AllocatedResources OPTIONAL, + IN OUT PCM_RESOURCE_LIST *AllocatedResourcesTranslated OPTIONAL); + +NDIS_STATUS +EXPIMP +NdisMInitializeScatterGatherDma( + IN NDIS_HANDLE MiniportAdapterHandle, + IN BOOLEAN Dma64BitAddresses, + IN ULONG MaximumPhysicalMapping); + +NDIS_STATUS +EXPIMP +NdisMPromoteMiniport( + IN NDIS_HANDLE MiniportAdapterHandle); + +NDIS_STATUS +EXPIMP +NdisMQueryAdapterInstanceName( + OUT PNDIS_STRING AdapterInstanceName, + IN NDIS_HANDLE MiniportAdapterHandle); + +NDIS_STATUS +EXPIMP +NdisMRegisterDevice( + IN NDIS_HANDLE NdisWrapperHandle, + IN PNDIS_STRING DeviceName, + IN PNDIS_STRING SymbolicName, + IN PDRIVER_DISPATCH MajorFunctions[], + OUT PDEVICE_OBJECT *pDeviceObject, + OUT NDIS_HANDLE *NdisDeviceHandle); + +VOID +EXPIMP +NdisMRegisterUnloadHandler( + IN NDIS_HANDLE NdisWrapperHandle, + IN PDRIVER_UNLOAD UnloadHandler); + +NDIS_STATUS +EXPIMP +NdisMRemoveMiniport( + IN NDIS_HANDLE MiniportAdapterHandle); + +NDIS_STATUS +EXPIMP +NdisMSetMiniportSecondary( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE PrimaryMiniportAdapterHandle); + +VOID +EXPIMP +NdisOpenConfigurationKeyByIndex( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ConfigurationHandle, + IN ULONG Index, + OUT PNDIS_STRING KeyName, + OUT PNDIS_HANDLE KeyHandle); + +VOID +EXPIMP +NdisOpenConfigurationKeyByName( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING SubKeyName, + OUT PNDIS_HANDLE SubKeyHandle); + +UINT +EXPIMP +NdisPacketPoolUsage( + IN NDIS_HANDLE PoolHandle); + +NDIS_STATUS +EXPIMP +NdisQueryAdapterInstanceName( + OUT PNDIS_STRING AdapterInstanceName, + IN NDIS_HANDLE NdisBindingHandle); + +VOID +EXPIMP +NdisQueryBufferSafe( + IN PNDIS_BUFFER Buffer, + OUT PVOID *VirtualAddress OPTIONAL, + OUT PUINT Length, + IN UINT Priority); + +ULONG +EXPIMP +NdisReadPcmciaAttributeMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length); + +VOID +EXPIMP +NdisReleaseReadWriteLock( + IN PNDIS_RW_LOCK Lock, + IN PLOCK_STATE LockState); + + +NDIS_STATUS +EXPIMP +NdisWriteEventLogEntry( + IN PVOID LogHandle, + IN NDIS_STATUS EventCode, + IN ULONG UniqueEventValue, + IN USHORT NumStrings, + IN PVOID StringsList OPTIONAL, + IN ULONG DataSize, + IN PVOID Data OPTIONAL); + +ULONG +EXPIMP +NdisWritePcmciaAttributeMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Offset, + IN PVOID Buffer, + IN ULONG Length); + + +/* Connectionless services */ + +NDIS_STATUS +EXPIMP +NdisClAddParty( + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE ProtocolPartyContext, + IN OUT PCO_CALL_PARAMETERS CallParameters, + OUT PNDIS_HANDLE NdisPartyHandle); + +NDIS_STATUS +EXPIMP +NdisClCloseAddressFamily( + IN NDIS_HANDLE NdisAfHandle); + +NDIS_STATUS +EXPIMP +NdisClCloseCall( + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN PVOID Buffer OPTIONAL, + IN UINT Size); + +NDIS_STATUS +EXPIMP +NdisClDeregisterSap( + IN NDIS_HANDLE NdisSapHandle); + +NDIS_STATUS +EXPIMP +NdisClDropParty( + IN NDIS_HANDLE NdisPartyHandle, + IN PVOID Buffer OPTIONAL, + IN UINT Size); + +VOID +EXPIMP +NdisClIncomingCallComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +NDIS_STATUS +EXPIMP +NdisClMakeCall( + IN NDIS_HANDLE NdisVcHandle, + IN OUT PCO_CALL_PARAMETERS CallParameters, + IN NDIS_HANDLE ProtocolPartyContext OPTIONAL, + OUT PNDIS_HANDLE NdisPartyHandle OPTIONAL); + +NDIS_STATUS +EXPIMP +NdisClModifyCallQoS( + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + + +NDIS_STATUS +EXPIMP +NdisClOpenAddressFamily( + IN NDIS_HANDLE NdisBindingHandle, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN NDIS_HANDLE ProtocolAfContext, + IN PNDIS_CLIENT_CHARACTERISTICS ClCharacteristics, + IN UINT SizeOfClCharacteristics, + OUT PNDIS_HANDLE NdisAfHandle); + +NDIS_STATUS +EXPIMP +NdisClRegisterSap( + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE ProtocolSapContext, + IN PCO_SAP Sap, + OUT PNDIS_HANDLE NdisSapHandle); + + +/* Call Manager services */ + +NDIS_STATUS +EXPIMP +NdisCmActivateVc( + IN NDIS_HANDLE NdisVcHandle, + IN OUT PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisCmAddPartyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisPartyHandle, + IN NDIS_HANDLE CallMgrPartyContext OPTIONAL, + IN PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisCmCloseAddressFamilyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisAfHandle); + +VOID +EXPIMP +NdisCmCloseCallComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL); + +NDIS_STATUS +EXPIMP +NdisCmDeactivateVc( + IN NDIS_HANDLE NdisVcHandle); + +VOID +EXPIMP +NdisCmDeregisterSapComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisSapHandle); + +VOID +EXPIMP +NdisCmDispatchCallConnected( + IN NDIS_HANDLE NdisVcHandle); + +NDIS_STATUS +EXPIMP +NdisCmDispatchIncomingCall( + IN NDIS_HANDLE NdisSapHandle, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisCmDispatchIncomingCallQoSChange( + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisCmDispatchIncomingCloseCall( + IN NDIS_STATUS CloseStatus, + IN NDIS_HANDLE NdisVcHandle, + IN PVOID Buffer OPTIONAL, + IN UINT Size); + +VOID +EXPIMP +NdisCmDispatchIncomingDropParty( + IN NDIS_STATUS DropStatus, + IN NDIS_HANDLE NdisPartyHandle, + IN PVOID Buffer OPTIONAL, + IN UINT Size); + +VOID +EXPIMP +NdisCmDropPartyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisPartyHandle); + +VOID +EXPIMP +NdisCmMakeCallComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN NDIS_HANDLE CallMgrPartyContext OPTIONAL, + IN PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisCmModifyCallQoSComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisCmOpenAddressFamilyComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE CallMgrAfContext); + +NDIS_STATUS +EXPIMP +NdisCmRegisterAddressFamily( + IN NDIS_HANDLE NdisBindingHandle, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN PNDIS_CALL_MANAGER_CHARACTERISTICS CmCharacteristics, + IN UINT SizeOfCmCharacteristics); + +VOID +EXPIMP +NdisCmRegisterSapComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisSapHandle, + IN NDIS_HANDLE CallMgrSapContext); + + +NDIS_STATUS +EXPIMP +NdisMCmActivateVc( + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +NDIS_STATUS +EXPIMP +NdisMCmCreateVc( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE MiniportVcContext, + OUT PNDIS_HANDLE NdisVcHandle); + +NDIS_STATUS +EXPIMP +NdisMCmDeactivateVc( + IN NDIS_HANDLE NdisVcHandle); + +NDIS_STATUS +EXPIMP +NdisMCmDeleteVc( + IN NDIS_HANDLE NdisVcHandle); + +NDIS_STATUS +EXPIMP +NdisMCmRegisterAddressFamily( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PCO_ADDRESS_FAMILY AddressFamily, + IN PNDIS_CALL_MANAGER_CHARACTERISTICS CmCharacteristics, + IN UINT SizeOfCmCharacteristics); + +NDIS_STATUS +EXPIMP +NdisMCmRequest( + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN OUT PNDIS_REQUEST NdisRequest); + + +/* Connection-oriented services */ + +NDIS_STATUS +EXPIMP +NdisCoCreateVc( + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE NdisAfHandle OPTIONAL, + IN NDIS_HANDLE ProtocolVcContext, + IN OUT PNDIS_HANDLE NdisVcHandle); + +NDIS_STATUS +EXPIMP +NdisCoDeleteVc( + IN NDIS_HANDLE NdisVcHandle); + +NDIS_STATUS +EXPIMP +NdisCoRequest( + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE NdisAfHandle OPTIONAL, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN OUT PNDIS_REQUEST NdisRequest); + +VOID +EXPIMP +NdisCoRequestComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisAfHandle, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_HANDLE NdisPartyHandle OPTIONAL, + IN PNDIS_REQUEST NdisRequest); + +VOID +EXPIMP +NdisCoSendPackets( + IN NDIS_HANDLE NdisVcHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + + +VOID +EXPIMP +NdisMCoActivateVcComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PCO_CALL_PARAMETERS CallParameters); + +VOID +EXPIMP +NdisMCoDeactivateVcComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle); + +VOID +EXPIMP +NdisMCoIndicateReceivePacket( + IN NDIS_HANDLE NdisVcHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + +VOID +EXPIMP +NdisMCoIndicateStatus( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisVcHandle OPTIONAL, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer OPTIONAL, + IN ULONG StatusBufferSize); + +VOID +EXPIMP +NdisMCoReceiveComplete( + IN NDIS_HANDLE MiniportAdapterHandle); + +VOID +EXPIMP +NdisMCoRequestComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_REQUEST Request); + +VOID +EXPIMP +NdisMCoSendComplete( + IN NDIS_STATUS Status, + IN NDIS_HANDLE NdisVcHandle, + IN PNDIS_PACKET Packet); + + +/* NDIS 5.0 extensions for intermediate drivers */ + +VOID +EXPIMP +NdisIMAssociateMiniport( + IN NDIS_HANDLE DriverHandle, + IN NDIS_HANDLE ProtocolHandle); + +NDIS_STATUS +EXPIMP +NdisIMCancelInitializeDeviceInstance( + IN NDIS_HANDLE DriverHandle, + IN PNDIS_STRING DeviceInstance); + +VOID +EXPIMP +NdisIMCopySendCompletePerPacketInfo( + IN PNDIS_PACKET DstPacket, + IN PNDIS_PACKET SrcPacket); + +VOID +EXPIMP +NdisIMCopySendPerPacketInfo( + IN PNDIS_PACKET DstPacket, + IN PNDIS_PACKET SrcPacket); + +VOID +EXPIMP +NdisIMDeregisterLayeredMiniport( + IN NDIS_HANDLE DriverHandle); + +NDIS_HANDLE +EXPIMP +NdisIMGetBindingContext( + IN NDIS_HANDLE NdisBindingHandle); + +NDIS_HANDLE +EXPIMP +NdisIMGetDeviceContext( + IN NDIS_HANDLE MiniportAdapterHandle); + +NDIS_STATUS +EXPIMP +NdisIMInitializeDeviceInstanceEx( + IN NDIS_HANDLE DriverHandle, + IN PNDIS_STRING DriverInstance, + IN NDIS_HANDLE DeviceContext OPTIONAL); + +#endif /* NDIS50 */ + + + +/* Prototypes for NDIS_MINIPORT_CHARACTERISTICS */ + +typedef BOOLEAN (*W_CHECK_FOR_HANG_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext); + +typedef VOID (*W_DISABLE_INTERRUPT_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext); + +typedef VOID (*W_ENABLE_INTERRUPT_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext); + +typedef VOID (*W_HALT_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext); + +typedef VOID (*W_HANDLE_INTERRUPT_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext); + +typedef NDIS_STATUS (*W_INITIALIZE_HANDLER)( + OUT PNDIS_STATUS OpenErrorStatus, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE WrapperConfigurationContext); + +typedef VOID (*W_ISR_HANDLER)( + OUT PBOOLEAN InterruptRecognized, + OUT PBOOLEAN QueueMiniportHandleInterrupt, + IN NDIS_HANDLE MiniportAdapterContext); + +typedef NDIS_STATUS (*W_QUERY_INFORMATION_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesWritten, + OUT PULONG BytesNeeded); + +typedef NDIS_STATUS (*W_RECONFIGURE_HANDLER)( + OUT PNDIS_STATUS OpenErrorStatus, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE WrapperConfigurationContext); + +typedef NDIS_STATUS (*W_RESET_HANDLER)( + OUT PBOOLEAN AddressingReset, + IN NDIS_HANDLE MiniportAdapterContext); + +typedef NDIS_STATUS (*W_SEND_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags); + +typedef NDIS_STATUS (*WM_SEND_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE NdisLinkHandle, + IN PNDIS_WAN_PACKET Packet); + +typedef NDIS_STATUS (*W_SET_INFORMATION_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesRead, + OUT PULONG BytesNeeded); + +typedef NDIS_STATUS (*W_TRANSFER_DATA_HANDLER)( + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred, + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer); + +typedef NDIS_STATUS (*WM_TRANSFER_DATA_HANDLER)( + VOID); + + + +/* NDIS structures available only to miniport drivers */ + +/* Technology specific defines */ + +#define DECLARE_UNKNOWN_STRUCT(BaseName) \ + typedef struct _##BaseName BaseName, *P##BaseName; + +#define DECLARE_UNKNOWN_PROTOTYPE(Name) \ + typedef VOID (*##Name)(VOID); + + +/* ARCnet */ + +typedef struct _ARC_BUFFER_LIST +{ + PVOID Buffer; + UINT Size; + UINT BytesLeft; + struct _ARC_BUFFER_LIST *Next; +} ARC_BUFFER_LIST, *PARC_BUFFER_LIST; + +DECLARE_UNKNOWN_STRUCT(ARC_FILTER) + + +VOID +EXPIMP +ArcFilterDprIndicateReceive( + IN PARC_FILTER Filter, + IN PUCHAR pRawHeader, + IN PUCHAR pData, + IN UINT Length); + +VOID +EXPIMP +ArcFilterDprIndicateReceiveComplete( + IN PARC_FILTER Filter); + + +/* Ethernet */ + +#define ETH_LENGTH_OF_ADDRESS 6 + +DECLARE_UNKNOWN_STRUCT(ETH_BINDING_INFO); + +DECLARE_UNKNOWN_PROTOTYPE(ETH_ADDRESS_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(ETH_FILTER_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(ETH_DEFERRED_CLOSE) + +typedef struct _ETH_FILTER +{ + PNDIS_SPIN_LOCK Lock; + CHAR (*MCastAddressBuf)[ETH_LENGTH_OF_ADDRESS]; + struct _NDIS_MINIPORT_BLOCK *Miniport; + UINT CombinedPacketFilter; + PETH_BINDING_INFO OpenList; + ETH_ADDRESS_CHANGE AddressChangeAction; + ETH_FILTER_CHANGE FilterChangeAction; + ETH_DEFERRED_CLOSE CloseAction; + UINT MaxMulticastAddresses; + UINT NumAddresses; + UCHAR AdapterAddress[ETH_LENGTH_OF_ADDRESS]; + UINT OldCombinedPacketFilter; + CHAR (*OldMCastAddressBuf)[ETH_LENGTH_OF_ADDRESS]; + UINT OldNumAddresses; + PETH_BINDING_INFO DirectedList; + PETH_BINDING_INFO BMList; + PETH_BINDING_INFO MCastSet; +#if 0 +#ifdef NDIS_WRAPPER + UINT NumOpens; + NDIS_RW_LOCK BindListLock; +#endif +#endif +} ETH_FILTER, *PETH_FILTER; + + +NDIS_STATUS +EXPIMP +EthChangeFilterAddresses( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT AddressCount, + IN CHAR Addresses[] [ETH_LENGTH_OF_ADDRESS], + IN BOOLEAN Set); + +BOOLEAN +EXPIMP +EthCreateFilter( + IN UINT MaximumMulticastAddresses, + IN ETH_ADDRESS_CHANGE AddressChangeAction, + IN ETH_FILTER_CHANGE FilterChangeAction, + IN ETH_DEFERRED_CLOSE CloseAction, + IN PUCHAR AdapterAddress, + IN PNDIS_SPIN_LOCK Lock, + OUT PETH_FILTER *Filter); + +VOID +EXPIMP +EthDeleteFilter( + IN PETH_FILTER Filter); + +NDIS_STATUS +EXPIMP +EthDeleteFilterOpenAdapter( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest); + +NDIS_STATUS +EXPIMP +EthFilterAdjust( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT FilterClasses, + IN BOOLEAN Set); + +VOID +EXPIMP +EthFilterIndicateReceive( + IN PETH_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +VOID +EXPIMP +EthFilterIndicateReceiveComplete( + IN PETH_FILTER Filter); + +BOOLEAN +EXPIMP +EthNoteFilterOpenAdapter( + IN PETH_FILTER Filter, + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE NdisBindingContext, + OUT PNDIS_HANDLE NdisFilterHandle); + +UINT +EXPIMP +EthNumberOfOpenFilterAddresses( + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle); + +VOID +EXPIMP +EthQueryGlobalFilterAddresses ( + OUT PNDIS_STATUS Status, + IN PETH_FILTER Filter, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray[] [ETH_LENGTH_OF_ADDRESS]); + +VOID +EXPIMP +EthQueryOpenFilterAddresses( + OUT PNDIS_STATUS Status, + IN PETH_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray[] [ETH_LENGTH_OF_ADDRESS]); + +BOOLEAN +EXPIMP +EthShouldAddressLoopBack( + IN PETH_FILTER Filter, + IN CHAR Address[ETH_LENGTH_OF_ADDRESS]); + + +/* FDDI */ + +#define FDDI_LENGTH_OF_LONG_ADDRESS 6 +#define FDDI_LENGTH_OF_SHORT_ADDRESS 2 + +DECLARE_UNKNOWN_STRUCT(FDDI_FILTER) + +DECLARE_UNKNOWN_PROTOTYPE(FDDI_ADDRESS_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(FDDI_FILTER_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(FDDI_DEFERRED_CLOSE) + + +NDIS_STATUS +EXPIMP +FddiChangeFilterLongAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT AddressCount, + IN CHAR Addresses[] [FDDI_LENGTH_OF_LONG_ADDRESS], + IN BOOLEAN Set); + +NDIS_STATUS +EXPIMP +FddiChangeFilterShortAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT AddressCount, + IN CHAR Addresses[] [FDDI_LENGTH_OF_SHORT_ADDRESS], + IN BOOLEAN Set); + +BOOLEAN +EXPIMP +FddiCreateFilter( + IN UINT MaximumMulticastLongAddresses, + IN UINT MaximumMulticastShortAddresses, + IN FDDI_ADDRESS_CHANGE AddressChangeAction, + IN FDDI_FILTER_CHANGE FilterChangeAction, + IN FDDI_DEFERRED_CLOSE CloseAction, + IN PUCHAR AdapterLongAddress, + IN PUCHAR AdapterShortAddress, + IN PNDIS_SPIN_LOCK Lock, + OUT PFDDI_FILTER *Filter); + +VOID +EXPIMP +FddiDeleteFilter( + IN PFDDI_FILTER Filter); + +NDIS_STATUS +EXPIMP +FddiDeleteFilterOpenAdapter( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest); + +NDIS_STATUS +EXPIMP +FddiFilterAdjust( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT FilterClasses, + IN BOOLEAN Set); + +VOID +EXPIMP +FddiFilterIndicateReceive( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN UINT AddressLength, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +VOID +EXPIMP +FddiFilterIndicateReceiveComplete( + IN PFDDI_FILTER Filter); + +BOOLEAN +EXPIMP +FddiNoteFilterOpenAdapter( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE NdisBindingContext, + OUT PNDIS_HANDLE NdisFilterHandle); + +UINT +EXPIMP +FddiNumberOfOpenFilterLongAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle); + +UINT +EXPIMP +FddiNumberOfOpenFilterShortAddresses( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle); + +VOID +EXPIMP +FddiQueryGlobalFilterLongAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray[] [FDDI_LENGTH_OF_LONG_ADDRESS]); + +VOID +EXPIMP +FddiQueryGlobalFilterShortAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray[] [FDDI_LENGTH_OF_SHORT_ADDRESS]); + +VOID +EXPIMP +FddiQueryOpenFilterLongAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray[] [FDDI_LENGTH_OF_LONG_ADDRESS]); + +VOID +EXPIMP +FddiQueryOpenFilterShortAddresses( + OUT PNDIS_STATUS Status, + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN UINT SizeOfArray, + OUT PUINT NumberOfAddresses, + IN OUT CHAR AddressArray[] [FDDI_LENGTH_OF_SHORT_ADDRESS]); + +BOOLEAN +EXPIMP +FddiShouldAddressLoopBack( + IN PFDDI_FILTER Filter, + IN CHAR Address[], + IN UINT LengthOfAddress); + + +/* Token Ring */ + +#define TR_LENGTH_OF_FUNCTIONAL 4 +#define TR_LENGTH_OF_ADDRESS 6 + +DECLARE_UNKNOWN_STRUCT(TR_FILTER) + +DECLARE_UNKNOWN_PROTOTYPE(TR_ADDRESS_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(TR_GROUP_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(TR_FILTER_CHANGE) +DECLARE_UNKNOWN_PROTOTYPE(TR_DEFERRED_CLOSE) + + +NDIS_STATUS +EXPIMP +TrChangeFunctionalAddress( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN CHAR FunctionalAddressArray[TR_LENGTH_OF_FUNCTIONAL], + IN BOOLEAN Set); + +NDIS_STATUS +EXPIMP +TrChangeGroupAddress( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN CHAR GroupAddressArray[TR_LENGTH_OF_FUNCTIONAL], + IN BOOLEAN Set); + +BOOLEAN +EXPIMP +TrCreateFilter( + IN TR_ADDRESS_CHANGE AddressChangeAction, + IN TR_GROUP_CHANGE GroupChangeAction, + IN TR_FILTER_CHANGE FilterChangeAction, + IN TR_DEFERRED_CLOSE CloseAction, + IN PUCHAR AdapterAddress, + IN PNDIS_SPIN_LOCK Lock, + OUT PTR_FILTER *Filter); + +VOID +EXPIMP +TrDeleteFilter( + IN PTR_FILTER Filter); + +NDIS_STATUS +EXPIMP +TrDeleteFilterOpenAdapter ( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest); + +NDIS_STATUS +EXPIMP +TrFilterAdjust( + IN PTR_FILTER Filter, + IN NDIS_HANDLE NdisFilterHandle, + IN PNDIS_REQUEST NdisRequest, + IN UINT FilterClasses, + IN BOOLEAN Set); + +VOID +EXPIMP +TrFilterIndicateReceive( + IN PTR_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +VOID +EXPIMP +TrFilterIndicateReceiveComplete( + IN PTR_FILTER Filter); + +BOOLEAN +EXPIMP +TrNoteFilterOpenAdapter( + IN PTR_FILTER Filter, + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE NdisBindingContext, + OUT PNDIS_HANDLE NdisFilterHandle); + +BOOLEAN +EXPIMP +TrShouldAddressLoopBack( + IN PTR_FILTER Filter, + IN CHAR DestinationAddress[TR_LENGTH_OF_ADDRESS], + IN CHAR SourceAddress[TR_LENGTH_OF_ADDRESS]); + + + +#ifdef _MSC_VER +typedef struct _NDIS30_MINIPORT_CHARACTERISTICS +{ + UCHAR MajorNdisVersion; + UCHAR MinorNdisVersion; + UINT Reserved; + W_CHECK_FOR_HANG_HANDLER CheckForHangHandler; + W_DISABLE_INTERRUPT_HANDLER DisableInterruptHandler; + W_ENABLE_INTERRUPT_HANDLER EnableInterruptHandler; + W_HALT_HANDLER HaltHandler; + W_HANDLE_INTERRUPT_HANDLER HandleInterruptHandler; + W_INITIALIZE_HANDLER InitializeHandler; + W_ISR_HANDLER ISRHandler; + W_QUERY_INFORMATION_HANDLER QueryInformationHandler; + W_RECONFIGURE_HANDLER ReconfigureHandler; + W_RESET_HANDLER ResetHandler; + union + { + W_SEND_HANDLER SendHandler; + WM_SEND_HANDLER WanSendHandler; + } u1; + W_SET_INFORMATION_HANDLER SetInformationHandler; + union + { + W_TRANSFER_DATA_HANDLER TransferDataHandler; + WM_TRANSFER_DATA_HANDLER WanTransferDataHandler; + } u2; +} NDIS30_MINIPORT_CHARACTERISTICS; +typedef NDIS30_MINIPORT_CHARACTERISTICS NDIS30_MINIPORT_CHARACTERISTICS_S; +#else +#define NDIS30_MINIPORT_CHARACTERISTICS \ + UCHAR MajorNdisVersion; \ + UCHAR MinorNdisVersion; \ + UINT Reserved; \ + W_CHECK_FOR_HANG_HANDLER CheckForHangHandler; \ + W_DISABLE_INTERRUPT_HANDLER DisableInterruptHandler; \ + W_ENABLE_INTERRUPT_HANDLER EnableInterruptHandler; \ + W_HALT_HANDLER HaltHandler; \ + W_HANDLE_INTERRUPT_HANDLER HandleInterruptHandler; \ + W_INITIALIZE_HANDLER InitializeHandler; \ + W_ISR_HANDLER ISRHandler; \ + W_QUERY_INFORMATION_HANDLER QueryInformationHandler; \ + W_RECONFIGURE_HANDLER ReconfigureHandler; \ + W_RESET_HANDLER ResetHandler; \ + union \ + { \ + W_SEND_HANDLER SendHandler; \ + WM_SEND_HANDLER WanSendHandler; \ + } u1; \ + W_SET_INFORMATION_HANDLER SetInformationHandler; \ + union \ + { \ + W_TRANSFER_DATA_HANDLER TransferDataHandler; \ + WM_TRANSFER_DATA_HANDLER WanTransferDataHandler; \ + } u2; +typedef struct _NDIS30_MINIPORT_CHARACTERISTICS_S +{ + NDIS30_MINIPORT_CHARACTERISTICS; +} NDIS30_MINIPORT_CHARACTERISTICS_S, *PSNDIS30_MINIPORT_CHARACTERISTICS_S; +#endif + +/* Extensions for NDIS 4.0 miniports */ + +typedef VOID (*W_SEND_PACKETS_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + +#ifdef NDIS40 + +typedef VOID (*W_RETURN_PACKET_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet); + +typedef VOID (*W_ALLOCATE_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PVOID VirtualAddress, + IN PNDIS_PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG Length, + IN PVOID Context); + +#ifdef _MSC_VER +typedef struct _NDIS40_MINIPORT_CHARACTERISTICS +{ + NDIS30_MINIPORT_CHARACTERISTICS; + + W_RETURN_PACKET_HANDLER ReturnPacketHandler; + W_SEND_PACKETS_HANDLER SendPacketsHandler; + W_ALLOCATE_COMPLETE_HANDLER AllocateCompleteHandler; +} NDIS40_MINIPORT_CHARACTERISTICS; +typedef NDIS40_MINIPORT_CHARACTERISTICS NDIS40_MINIPORT_CHARACTERISTICS_S; +#else +#define NDIS40_MINIPORT_CHARACTERISTICS \ + NDIS30_MINIPORT_CHARACTERISTICS; \ + W_RETURN_PACKET_HANDLER ReturnPacketHandler; \ + W_SEND_PACKETS_HANDLER SendPacketsHandler; \ + W_ALLOCATE_COMPLETE_HANDLER AllocateCompleteHandler; +typedef struct _NDIS40_MINIPORT_CHARACTERISTICS_S +{ + NDIS40_MINIPORT_CHARACTERISTICS; +} NDIS40_MINIPORT_CHARACTERISTICS_S, *PSNDIS40_MINIPORT_CHARACTERISTICS_S; +#endif + +#endif /* NDIS40 */ + +/* Extensions for NDIS 5.0 miniports */ + +#ifdef NDIS50 + +typedef NDIS_STATUS (*W_CO_CREATE_VC_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE NdisVcHandle, + OUT PNDIS_HANDLE MiniportVcContext); + +typedef NDIS_STATUS (*W_CO_DELETE_VC_HANDLER)( + IN NDIS_HANDLE MiniportVcContext); + +typedef NDIS_STATUS (*W_CO_ACTIVATE_VC_HANDLER)( + IN NDIS_HANDLE MiniportVcContext, + IN OUT PCO_CALL_PARAMETERS CallParameters); + +typedef NDIS_STATUS (*W_CO_DEACTIVATE_VC_HANDLER)( + IN NDIS_HANDLE MiniportVcContext); + +typedef VOID (*W_CO_SEND_PACKETS_HANDLER)( + IN NDIS_HANDLE MiniportVcContext, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + +typedef NDIS_STATUS (*W_CO_REQUEST_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_HANDLE MiniportVcContext OPTIONAL, + IN OUT PNDIS_REQUEST NdisRequest); + +#ifdef _MSC_VER +typedef struct _NDIS50_MINIPORT_CHARACTERISTICS +{ + NDIS40_MINIPORT_CHARACTERISTICS; + + W_CO_CREATE_VC_HANDLER CoCreateVcHandler; + W_CO_DELETE_VC_HANDLER CoDeleteVcHandler; + W_CO_ACTIVATE_VC_HANDLER CoActivateVcHandler; + W_CO_DEACTIVATE_VC_HANDLER CoDeactivateVcHandler; + W_CO_SEND_PACKETS_HANDLER CoSendPacketsHandler; + W_CO_REQUEST_HANDLER CoRequestHandler; +} NDIS50_MINIPORT_CHARACTERISTICS; +typedef NDIS50_MINIPORT_CHARACTERISTICS NDIS50_MINIPORT_CHARACTERISTICS_S; +#else +#define NDIS50_MINIPORT_CHARACTERISTICS \ + NDIS40_MINIPORT_CHARACTERISTICS; \ + W_CO_CREATE_VC_HANDLER CoCreateVcHandler; \ + W_CO_DELETE_VC_HANDLER CoDeleteVcHandler; \ + W_CO_ACTIVATE_VC_HANDLER CoActivateVcHandler; \ + W_CO_DEACTIVATE_VC_HANDLER CoDeactivateVcHandler; \ + W_CO_SEND_PACKETS_HANDLER CoSendPacketsHandler; \ + W_CO_REQUEST_HANDLER CoRequestHandler; +typedef struct _NDIS50_MINIPORT_CHARACTERISTICS_S +{ + NDIS50_MINIPORT_CHARACTERISTICS; +} NDIS50_MINIPORT_CHARACTERISTICS_S, *PSNDIS50_MINIPORT_CHARACTERISTICS_S; +#endif + +#endif /* NDIS50 */ + + +#ifndef NDIS50 +#ifndef NDIS40 +typedef struct _NDIS_MINIPORT_CHARACTERISTICS +{ + NDIS30_MINIPORT_CHARACTERISTICS; +} NDIS_MINIPORT_CHARACTERISTICS; +#else /* NDIS40 */ +typedef struct _NDIS_MINIPORT_CHARACTERISTICS +{ + NDIS40_MINIPORT_CHARACTERISTICS; +} NDIS_MINIPORT_CHARACTERISTICS; +#endif /* NDIS40 */ +#else /* NDIS50 */ +typedef struct _NDIS_MINIPORT_CHARACTERISTICS +{ + NDIS50_MINIPORT_CHARACTERISTICS; +} NDIS_MINIPORT_CHARACTERISTICS; +#endif /* NDIS50 */ + +typedef NDIS_MINIPORT_CHARACTERISTICS *PNDIS_MINIPORT_CHARACTERISTICS; + + + +typedef NDIS_STATUS (*SEND_HANDLER)( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_PACKET Packet); + +typedef NDIS_STATUS (*TRANSFER_DATA_HANDLER)( + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE MacReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer, + OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred); + +typedef NDIS_STATUS (*RESET_HANDLER)( + IN NDIS_HANDLE MacBindingHandle); + +typedef NDIS_STATUS (*REQUEST_HANDLER)( + IN NDIS_HANDLE MacBindingHandle, + IN PNDIS_REQUEST NdisRequest); + + + +/* Structures available only to full MAC drivers */ + +typedef BOOLEAN (*PNDIS_INTERRUPT_SERVICE)( + IN PVOID InterruptContext); + +typedef VOID (*PNDIS_DEFERRED_PROCESSING)( + IN PVOID SystemSpecific1, + IN PVOID InterruptContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +typedef struct _NDIS_INTERRUPT +{ + PKINTERRUPT InterruptObject; + KSPIN_LOCK DpcCountLock; + PNDIS_INTERRUPT_SERVICE MacIsr; + PNDIS_DEFERRED_PROCESSING MacDpc; + KDPC InterruptDpc; + PVOID InterruptContext; + UCHAR DpcCount; + BOOLEAN Removing; + /* Used to tell when all DPCs for the adapter are completed */ + KEVENT DpcsCompletedEvent; +} NDIS_INTERRUPT, *PNDIS_INTERRUPT; + + +/* NDIS adapter information */ + +typedef NDIS_STATUS (*PNDIS_ACTIVATE_CALLBACK)( + IN NDIS_HANDLE NdisAdatperHandle, + IN NDIS_HANDLE MacAdapterContext, + IN ULONG DmaChannel); + +typedef struct _NDIS_PORT_DESCRIPTOR +{ + ULONG InitialPort; + ULONG NumberOfPorts; + PVOID * PortOffset; +} NDIS_PORT_DESCRIPTOR, *PNDIS_PORT_DESCRIPTOR; + +typedef struct _NDIS_ADAPTER_INFORMATION +{ + ULONG DmaChannel; + BOOLEAN Master; + BOOLEAN Dma32BitAddresses; + PNDIS_ACTIVATE_CALLBACK ActivateCallback; + NDIS_INTERFACE_TYPE AdapterType; + ULONG PhysicalMapRegistersNeeded; + ULONG MaximumPhysicalMapping; + ULONG NumberOfPortDescriptors; + NDIS_PORT_DESCRIPTOR PortDescriptors[1]; +} NDIS_ADAPTER_INFORMATION, *PNDIS_ADAPTER_INFORMATION; + + +/* Prototypes for NDIS_MAC_CHARACTERISTICS */ + +typedef NDIS_STATUS (*OPEN_ADAPTER_HANDLER)( + OUT PNDIS_STATUS OpenErrorStatus, + OUT NDIS_HANDLE * MacBindingHandle, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_HANDLE MacAdapterContext, + IN UINT OpenOptions, + IN PSTRING AddressingInformation OPTIONAL); + +typedef NDIS_STATUS (*CLOSE_ADAPTER_HANDLER)( + IN NDIS_HANDLE MacBindingHandle); + +typedef NDIS_STATUS (*WAN_TRANSFER_DATA_HANDLER)( + VOID); + +typedef NDIS_STATUS (*QUERY_GLOBAL_STATISTICS_HANDLER)( + IN NDIS_HANDLE MacAdapterContext, + IN PNDIS_REQUEST NdisRequest); + +typedef VOID (*UNLOAD_MAC_HANDLER)( + IN NDIS_HANDLE MacMacContext); + +typedef NDIS_STATUS (*ADD_ADAPTER_HANDLER)( + IN NDIS_HANDLE MacMacContext, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PNDIS_STRING AdapterName); + +typedef VOID (*REMOVE_ADAPTER_HANDLER)( + IN NDIS_HANDLE MacAdapterContext); + +typedef struct _NDIS_MAC_CHARACTERISTICS +{ + UCHAR MajorNdisVersion; + UCHAR MinorNdisVersion; + UINT Reserved; + OPEN_ADAPTER_HANDLER OpenAdapterHandler; + CLOSE_ADAPTER_HANDLER CloseAdapterHandler; + SEND_HANDLER SendHandler; + TRANSFER_DATA_HANDLER TransferDataHandler; + RESET_HANDLER ResetHandler; + REQUEST_HANDLER RequestHandler; + QUERY_GLOBAL_STATISTICS_HANDLER QueryGlobalStatisticsHandler; + UNLOAD_MAC_HANDLER UnloadMacHandler; + ADD_ADAPTER_HANDLER AddAdapterHandler; + REMOVE_ADAPTER_HANDLER RemoveAdapterHandler; + NDIS_STRING Name; +} NDIS_MAC_CHARACTERISTICS, *PNDIS_MAC_CHARACTERISTICS; + +typedef NDIS_MAC_CHARACTERISTICS NDIS_WAN_MAC_CHARACTERISTICS; +typedef NDIS_WAN_MAC_CHARACTERISTICS *PNDIS_WAN_MAC_CHARACTERISTICS; + + + +VOID +EXPIMP +NdisAllocateSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +VOID +EXPIMP +NdisCompleteCloseAdapter( + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_STATUS Status); + +VOID +EXPIMP +NdisCompleteOpenAdapter( + IN NDIS_HANDLE NdisBindingContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenErrorStatus); + +NDIS_STATUS +EXPIMP +NdisDeregisterAdapter( + IN NDIS_HANDLE NdisAdapterHandle); + +VOID +EXPIMP +NdisDeregisterAdapterShutdownHandler( + IN NDIS_HANDLE NdisAdapterHandle); + +VOID +EXPIMP +NdisFreeSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +VOID +EXPIMP +NdisInitializeInterrupt( + OUT PNDIS_STATUS Status, + IN OUT PNDIS_INTERRUPT Interrupt, + IN NDIS_HANDLE NdisAdapterHandle, + IN PNDIS_INTERRUPT_SERVICE InterruptServiceRoutine, + IN PVOID InterruptContext, + IN PNDIS_DEFERRED_PROCESSING DeferredProcessingRoutine, + IN UINT InterruptVector, + IN UINT InterruptLevel, + IN BOOLEAN SharedInterrupt, + IN NDIS_INTERRUPT_MODE InterruptMode); + +VOID +EXPIMP +NdisMapIoSpace( + OUT PNDIS_STATUS Status, + OUT PVOID *VirtualAddress, + IN NDIS_HANDLE NdisAdapterHandle, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT Length); + +NDIS_STATUS +EXPIMP +NdisRegisterAdapter( + OUT PNDIS_HANDLE NdisAdapterHandle, + IN NDIS_HANDLE NdisMacHandle, + IN NDIS_HANDLE MacAdapterContext, + IN NDIS_HANDLE WrapperConfigurationContext, + IN PNDIS_STRING AdapterName, + IN PVOID AdapterInformation); + +VOID +EXPIMP +NdisRegisterAdapterShutdownHandler( + IN NDIS_HANDLE NdisAdapterHandle, + IN PVOID ShutdownContext, + IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler); + +VOID +EXPIMP +NdisRegisterMac( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE NdisMacHandle, + IN NDIS_HANDLE NdisWrapperHandle, + IN NDIS_HANDLE MacMacContext, + IN PNDIS_MAC_CHARACTERISTICS MacCharacteristics, + IN UINT CharacteristicsLength); + +VOID +EXPIMP +NdisReleaseAdapterResources( + IN NDIS_HANDLE NdisAdapterHandle); + +VOID +EXPIMP +NdisRemoveInterrupt( + IN PNDIS_INTERRUPT Interrupt); + + + +typedef struct _NDIS_MAC_BLOCK NDIS_MAC_BLOCK, *PNDIS_MAC_BLOCK; +typedef struct _NDIS_ADAPTER_BLOCK NDIS_ADAPTER_BLOCK, *PNDIS_ADAPTER_BLOCK; +typedef struct _NDIS_MINIPORT_BLOCK NDIS_MINIPORT_BLOCK, *PNDIS_MINIPORT_BLOCK; +typedef struct _NDIS_PROTOCOL_BLOCK NDIS_PROTOCOL_BLOCK, *PNDIS_PROTOCOL_BLOCK; +typedef struct _NDIS_OPEN_BLOCK NDIS_OPEN_BLOCK, *PNDIS_OPEN_BLOCK; +typedef struct _NDIS_M_DRIVER_BLOCK NDIS_M_DRIVER_BLOCK, *PNDIS_M_DRIVER_BLOCK; +typedef struct _NDIS_AF_LIST NDIS_AF_LIST, *PNDIS_AF_LIST; +typedef struct _NULL_FILTER NULL_FILTER, *PNULL_FILTER; + + +typedef struct _REFERENCE +{ + KSPIN_LOCK SpinLock; + USHORT ReferenceCount; + BOOLEAN Closing; +} REFERENCE, *PREFERENCE; + +typedef struct _NDIS_MINIPORT_INTERRUPT +{ + PKINTERRUPT InterruptObject; + KSPIN_LOCK DpcCountLock; + PVOID MiniportIdField; + W_ISR_HANDLER MiniportIsr; + W_HANDLE_INTERRUPT_HANDLER MiniportDpc; + KDPC InterruptDpc; + PNDIS_MINIPORT_BLOCK Miniport; + + UCHAR DpcCount; + BOOLEAN Filler1; + + KEVENT DpcsCompletedEvent; + + BOOLEAN SharedInterrupt; + BOOLEAN IsrRequested; +} NDIS_MINIPORT_INTERRUPT, *PNDIS_MINIPORT_INTERRUPT; + +typedef struct _NDIS_MINIPORT_TIMER +{ + KTIMER Timer; + KDPC Dpc; + PNDIS_TIMER_FUNCTION MiniportTimerFunction; + PVOID MiniportTimerContext; + PNDIS_MINIPORT_BLOCK Miniport; + struct _NDIS_MINIPORT_TIMER *NextDeferredTimer; +} NDIS_MINIPORT_TIMER, *PNDIS_MINIPORT_TIMER; + + +typedef struct _MAP_REGISTER_ENTRY +{ + PVOID MapRegister; + BOOLEAN WriteToDevice; +} MAP_REGISTER_ENTRY, *PMAP_REGISTER_ENTRY; + + +typedef enum _NDIS_WORK_ITEM_TYPE +{ + NdisWorkItemRequest, + NdisWorkItemSend, + NdisWorkItemReturnPackets, + NdisWorkItemResetRequested, + NdisWorkItemResetInProgress, + NdisWorkItemHalt, + NdisWorkItemSendLoopback, + NdisWorkItemMiniportCallback, + NdisMaxWorkItems +} NDIS_WORK_ITEM_TYPE, *PNDIS_WORK_ITEM_TYPE; + +#define NUMBER_OF_WORK_ITEM_TYPES NdisMaxWorkItems +#define NUMBER_OF_SINGLE_WORK_ITEMS 6 + +typedef struct _NDIS_MINIPORT_WORK_ITEM +{ + SINGLE_LIST_ENTRY Link; + NDIS_WORK_ITEM_TYPE WorkItemType; + PVOID WorkItemContext; + BOOLEAN Allocated; + NDIS_HANDLE Initiator; +} NDIS_MINIPORT_WORK_ITEM, *PNDIS_MINIPORT_WORK_ITEM; + + +typedef struct _NDIS_BIND_PATHS +{ + UINT Number; + NDIS_STRING Paths[1]; +} NDIS_BIND_PATHS, *PNDIS_BIND_PATHS; + +typedef struct _FILTERDBS +{ + union + { + PETH_FILTER EthDB; + PNULL_FILTER NullDB; + } u; + PTR_FILTER TrDB; + PFDDI_FILTER FddiDB; + PARC_FILTER ArcDB; +} FILTERDBS, *PFILTERDBS; + + +typedef VOID (*ETH_RCV_COMPLETE_HANDLER)( + IN PETH_FILTER Filter); + +typedef VOID (*ETH_RCV_INDICATE_HANDLER)( + IN PETH_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +typedef VOID (*FDDI_RCV_COMPLETE_HANDLER)( + IN PFDDI_FILTER Filter); + +typedef VOID (*FDDI_RCV_INDICATE_HANDLER)( + IN PFDDI_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PCHAR Address, + IN UINT AddressLength, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +typedef VOID (*FILTER_PACKET_INDICATION_HANDLER)( + IN NDIS_HANDLE Miniport, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + +typedef VOID (*TR_RCV_COMPLETE_HANDLER)( + IN PTR_FILTER Filter); + +typedef VOID (*TR_RCV_INDICATE_HANDLER)( + IN PTR_FILTER Filter, + IN NDIS_HANDLE MacReceiveContext, + IN PVOID HeaderBuffer, + IN UINT HeaderBufferSize, + IN PVOID LookaheadBuffer, + IN UINT LookaheadBufferSize, + IN UINT PacketSize); + +typedef VOID (*WAN_RCV_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisLinkContext); + +typedef VOID (*WAN_RCV_HANDLER)( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE NdisLinkContext, + IN PUCHAR Packet, + IN ULONG PacketSize); + +typedef VOID (FASTCALL *NDIS_M_DEQUEUE_WORK_ITEM)( + IN PNDIS_MINIPORT_BLOCK Miniport, + IN NDIS_WORK_ITEM_TYPE WorkItemType, + OUT PVOID *WorkItemContext); + +typedef VOID (FASTCALL *NDIS_M_PROCESS_DEFERRED)( + IN PNDIS_MINIPORT_BLOCK Miniport); + +typedef NDIS_STATUS (FASTCALL *NDIS_M_QUEUE_NEW_WORK_ITEM)( + IN PNDIS_MINIPORT_BLOCK Miniport, + IN NDIS_WORK_ITEM_TYPE WorkItemType, + IN PVOID WorkItemContext); + +typedef NDIS_STATUS (FASTCALL *NDIS_M_QUEUE_WORK_ITEM)( + IN PNDIS_MINIPORT_BLOCK Miniport, + IN NDIS_WORK_ITEM_TYPE WorkItemType, + IN PVOID WorkItemContext); + +typedef VOID (*NDIS_M_REQ_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status); + +typedef VOID (*NDIS_M_RESET_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status, + IN BOOLEAN AddressingReset); + +typedef VOID (*NDIS_M_SEND_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status); + +typedef VOID (*NDIS_M_SEND_RESOURCES_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle); + +typedef BOOLEAN (FASTCALL *NDIS_M_START_SENDS)( + IN PNDIS_MINIPORT_BLOCK Miniport); + +typedef VOID (*NDIS_M_STATUS_HANDLER)( + IN NDIS_HANDLE MiniportHandle, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize); + +typedef VOID (*NDIS_M_STS_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle); + +typedef VOID (*NDIS_M_TD_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PNDIS_PACKET Packet, + IN NDIS_STATUS Status, + IN UINT BytesTransferred); + +typedef VOID (*NDIS_WM_SEND_COMPLETE_HANDLER)( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PVOID Packet, + IN NDIS_STATUS Status); + + +#ifdef NDIS_WRAPPER + +#define ARC_SEND_BUFFERS 8 +#define ARC_HEADER_SIZE 4 + +typedef struct _NDIS_ARC_BUF +{ + NDIS_HANDLE ArcnetBufferPool; + PUCHAR ArcnetLookaheadBuffer; + UINT NumFree; + ARC_BUFFER_LIST ArcnetBuffers[ARC_SEND_BUFFERS]; +} NDIS_ARC_BUF, *PNDIS_ARC_BUF; + +#define NDIS_MINIPORT_WORK_QUEUE_SIZE 10 + +typedef struct _NDIS_LOG +{ + PNDIS_MINIPORT_BLOCK Miniport; + KSPIN_LOCK LogLock; + PIRP Irp; + UINT TotalSize; + UINT CurrentSize; + UINT InPtr; + UINT OutPtr; + UCHAR LogBuf[1]; +} NDIS_LOG, *PNDIS_LOG; + +#endif /* NDIS_WRAPPER */ + + +struct _NDIS_ADAPTER_BLOCK +{ + PDEVICE_OBJECT DeviceObject; + PNDIS_MAC_BLOCK MacHandle; + NDIS_HANDLE MacAdapterContext; + NDIS_STRING AdapterName; + PNDIS_OPEN_BLOCK OpenQueue; + PNDIS_ADAPTER_BLOCK NextAdapter; + REFERENCE Ref; + PVOID BusDataContext; + BOOLEAN BeingRemoved; + UCHAR Flags; + PCM_RESOURCE_LIST Resources; + PNDIS_STRING pAdapterInstanceName; + PVOID WrapperContext; + + ULONG BusNumber; + NDIS_INTERFACE_TYPE BusType; + ULONG ChannelNumber; + NDIS_INTERFACE_TYPE AdapterType; + BOOLEAN Master; + UCHAR AssignedProcessor; + ULONG PhysicalMapRegistersNeeded; + ULONG MaximumPhysicalMapping; + ULONG InitialPort; + ULONG NumberOfPorts; + PUCHAR InitialPortMapping; + BOOLEAN InitialPortMapped; + PUCHAR PortOffset; + PMAP_REGISTER_ENTRY MapRegisters; + + KEVENT AllocationEvent; + UINT CurrentMapRegister; + PADAPTER_OBJECT SystemAdapterObject; +#if 0 +#ifdef NDIS_WRAPPER + ULONG BusId; + ULONG SlotNumber; + NDIS_STRING BaseName; + PDEVICE_OBJECT PhysicalDeviceObject; + PDEVICE_OBJECT NextDeviceObject; + PCM_RESOURCE_LIST AllocatedResources; + PCM_RESOURCE_LIST AllocatedResourcesTranslated; + NDIS_EVENT OpenReadyEvent; + NDIS_PNP_DEVICE_STATE PnPDeviceState; + PGET_SET_DEVICE_DATA SetBusData; + PGET_SET_DEVICE_DATA GetBusData; + POID_LIST OidList; + ULONG PnPCapabilities; +#endif /* NDIS_WRAPPER */ +#endif +}; + + +struct _NDIS_MINIPORT_BLOCK +{ + ULONG NullValue; + PNDIS_MINIPORT_BLOCK NextMiniport; + PNDIS_M_DRIVER_BLOCK DriverHandle; + NDIS_HANDLE MiniportAdapterContext; + UNICODE_STRING MiniportName; + PNDIS_BIND_PATHS BindPaths; + NDIS_HANDLE OpenQueue; + REFERENCE Ref; + NDIS_HANDLE DeviceContext; + UCHAR Padding1; + + UCHAR LockAcquired; + UCHAR PmodeOpens; + UCHAR AssignedProcessor; + KSPIN_LOCK Lock; + PNDIS_REQUEST MediaRequest; + PNDIS_MINIPORT_INTERRUPT Interrupt; + ULONG Flags; + ULONG PnPFlags; + + LIST_ENTRY PacketList; + PNDIS_PACKET FirstPendingPacket; + PNDIS_PACKET ReturnPacketsQueue; + ULONG RequestBuffer; + PVOID SetMCastBuffer; + PNDIS_MINIPORT_BLOCK PrimaryMiniport; + PVOID WrapperContext; + + PVOID BusDataContext; + ULONG PnPCapabilities; + PCM_RESOURCE_LIST Resources; + NDIS_TIMER WakeUpDpcTimer; + UNICODE_STRING BaseName; + UNICODE_STRING SymbolicLinkName; + + ULONG CheckForHangSeconds; + USHORT CFHangTicks; + USHORT CFHangCurrentTick; + NDIS_STATUS ResetStatus; + NDIS_HANDLE ResetOpen; + FILTERDBS FilterDbs; + + FILTER_PACKET_INDICATION_HANDLER PacketIndicateHandler; + NDIS_M_SEND_COMPLETE_HANDLER SendCompleteHandler; + NDIS_M_SEND_RESOURCES_HANDLER SendResourcesHandler; + NDIS_M_RESET_COMPLETE_HANDLER ResetCompleteHandler; + + NDIS_MEDIUM MediaType; + ULONG BusNumber; + NDIS_INTERFACE_TYPE BusType; + NDIS_INTERFACE_TYPE AdapterType; + PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT PhysicalDeviceObject; + PDEVICE_OBJECT NextDeviceObject; + + PMAP_REGISTER_ENTRY MapRegisters; + PNDIS_AF_LIST CallMgrAfList; + PVOID MiniportThread; + PVOID SetInfoBuf; + USHORT SetInfoBufLen; + USHORT MaxSendPackets; + NDIS_STATUS FakeStatus; + PVOID LockHandler; + PUNICODE_STRING pAdapterInstanceName; + PADAPTER_OBJECT SystemAdapterObject; + UINT MacOptions; + PNDIS_REQUEST PendingRequest; + UINT MaximumLongAddresses; + UINT MaximumShortAddresses; + UINT CurrentLookahead; + UINT MaximumLookahead; + + W_HANDLE_INTERRUPT_HANDLER HandleInterruptHandler; + W_DISABLE_INTERRUPT_HANDLER DisableInterruptHandler; + W_ENABLE_INTERRUPT_HANDLER EnableInterruptHandler; + W_SEND_PACKETS_HANDLER SendPacketsHandler; + NDIS_M_START_SENDS DeferredSendHandler; + + ETH_RCV_INDICATE_HANDLER EthRxIndicateHandler; + TR_RCV_INDICATE_HANDLER TrRxIndicateHandler; + FDDI_RCV_INDICATE_HANDLER FddiRxIndicateHandler; + + ETH_RCV_COMPLETE_HANDLER EthRxCompleteHandler; + TR_RCV_COMPLETE_HANDLER TrRxCompleteHandler; + FDDI_RCV_COMPLETE_HANDLER FddiRxCompleteHandler; + + NDIS_M_STATUS_HANDLER StatusHandler; + NDIS_M_STS_COMPLETE_HANDLER StatusCompleteHandler; + NDIS_M_TD_COMPLETE_HANDLER TDCompleteHandler; + NDIS_M_REQ_COMPLETE_HANDLER QueryCompleteHandler; + NDIS_M_REQ_COMPLETE_HANDLER SetCompleteHandler; + + NDIS_WM_SEND_COMPLETE_HANDLER WanSendCompleteHandler; + WAN_RCV_HANDLER WanRcvHandler; + WAN_RCV_COMPLETE_HANDLER WanRcvCompleteHandler; +#if 0 +#ifdef NDIS_WRAPPER + SINGLE_LIST_ENTRY WorkQueue[NUMBER_OF_WORK_ITEM_TYPES]; + SINGLE_LIST_ENTRY SingleWorkItems[NUMBER_OF_SINGLE_WORK_ITEMS]; + PNDIS_MAC_BLOCK FakeMac; + UCHAR SendFlags; + UCHAR TrResetRing; + UCHAR ArcnetAddress; + + union + { + PNDIS_ARC_BUF ArcBuf; + PVOID BusInterface; + } u1; + + ULONG ChannelNumber; + PNDIS_LOG Log; + ULONG BusId; + ULONG SlotNumber; + PCM_RESOURCE_LIST AllocatedResources; + PCM_RESOURCE_LIST AllocatedResourcesTranslated; + SINGLE_LIST_ENTRY PatternList; + NDIS_PNP_CAPABILITIES PMCapabilities; +#if 0 + DEVICE_CAPABILITIES DeviceCaps; +#endif + ULONG WakeUpEnable; +#if 0 + DEVICE_POWER_STATE CurrentDeviceState; +#endif + PIRP pIrpWaitWake; +#if 0 + SYSTEM_POWER_STATE WaitWakeSystemState; +#endif + LARGE_INTEGER VcIndex; + KSPIN_LOCK VcCountLock; + LIST_ENTRY WmiEnabledVcs; + PNDIS_GUID pNdisGuidMap; + PNDIS_GUID pCustomGuidMap; + USHORT VcCount; + USHORT cNdisGuidMap; + USHORT cCustomGuidMap; + USHORT CurrentMapRegister; + PKEVENT AllocationEvent; + USHORT PhysicalMapRegistersNeeded; + USHORT SGMapRegistersNeeded; + ULONG MaximumPhysicalMapping; + + NDIS_TIMER MediaDisconnectTimer; + USHORT MediaDisconnectTimeOut; + USHORT InstanceNumber; + NDIS_EVENT OpenReadyEvent; + NDIS_PNP_DEVICE_STATE PnPDeviceState; + NDIS_PNP_DEVICE_STATE OldPnPDeviceState; +#if 0 + PGET_SET_DEVICE_DATA SetBusData; + PGET_SET_DEVICE_DATA GetBusData; +#endif + POID_LIST OidList; + KDPC DeferredDpc; +#if 0 + NDIS_STATS NdisStats; +#endif + PNDIS_PACKET IndicatedPacket[MAXIMUM_PROCESSORS]; + PKEVENT RemoveReadyEvent; + PKEVENT AllOpensClosedEvent; + PKEVENT AllRequestsCompletedEvent; + ULONG InitTimeMs; + NDIS_MINIPORT_WORK_ITEM WorkItemBuffer[NUMBER_OF_SINGLE_WORK_ITEMS]; + PNDIS_MINIPORT_TIMER TimerQueue; + ULONG DriverVerifyFlags; + + PNDIS_MINIPORT_BLOCK NextGlobalMiniport; + USHORT InternalResetCount; + USHORT MiniportResetCount; + USHORT MediaSenseConnectCount; + USHORT MediaSenseDisconnectCount; + PNDIS_PACKET *xPackets; + ULONG UserModeOpenReferences; +#endif /* NDIS_WRAPPER */ +#endif +}; + + +/* Handler prototypes for NDIS_OPEN_BLOCK */ + +typedef NDIS_STATUS (*WAN_SEND_HANDLER)( + IN NDIS_HANDLE MacBindingHandle, + IN NDIS_HANDLE LinkHandle, + IN PVOID Packet); + +/* NDIS 4.0 extension */ + +typedef VOID (*SEND_PACKETS_HANDLER)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + + +struct _NDIS_OPEN_BLOCK +{ + PNDIS_MAC_BLOCK MacHandle; + NDIS_HANDLE MacBindingHandle; + PNDIS_ADAPTER_BLOCK AdapterHandle; + PNDIS_PROTOCOL_BLOCK ProtocolHandle; + NDIS_HANDLE ProtocolBindingContext; + PNDIS_OPEN_BLOCK AdapterNextOpen; + PNDIS_OPEN_BLOCK ProtocolNextOpen; + PNDIS_OPEN_BLOCK NextGlobalOpen; + BOOLEAN Closing; + BOOLEAN Unbinding; + BOOLEAN NoProtRsvdOnRcvPkt; + BOOLEAN ProcessingOpens; + PNDIS_STRING BindDeviceName; + KSPIN_LOCK SpinLock; + PNDIS_STRING RootDeviceName; + + union + { + SEND_HANDLER SendHandler; + WAN_SEND_HANDLER WanSendHandler; + } u1; + TRANSFER_DATA_HANDLER TransferDataHandler; + + SEND_COMPLETE_HANDLER SendCompleteHandler; + TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler; + RECEIVE_HANDLER ReceiveHandler; + RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler; + + union + { + RECEIVE_HANDLER PostNt31ReceiveHandler; + WAN_RECEIVE_HANDLER WanReceiveHandler; + } u2; + RECEIVE_COMPLETE_HANDLER PostNt31ReceiveCompleteHandler; + + RECEIVE_PACKET_HANDLER ReceivePacketHandler; + SEND_PACKETS_HANDLER SendPacketsHandler; + + RESET_HANDLER ResetHandler; + REQUEST_HANDLER RequestHandler; + RESET_COMPLETE_HANDLER ResetCompleteHandler; + STATUS_HANDLER StatusHandler; + STATUS_COMPLETE_HANDLER StatusCompleteHandler; + REQUEST_COMPLETE_HANDLER RequestCompleteHandler; +}; + + + +/* Routines for NDIS miniport drivers */ + +VOID +EXPIMP +NdisInitializeWrapper( + OUT PNDIS_HANDLE NdisWrapperHandle, + IN PVOID SystemSpecific1, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +NDIS_STATUS +EXPIMP +NdisMAllocateMapRegisters( + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT DmaChannel, + IN BOOLEAN Dma32BitAddresses, + IN ULONG PhysicalMapRegistersNeeded, + IN ULONG MaximumPhysicalMapping); + +/* + * VOID NdisMArcIndicateReceive( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN PUCHAR HeaderBuffer, + * IN PUCHAR DataBuffer, + * IN UINT Length); + */ +#define NdisMArcIndicateReceive(MiniportAdapterHandle, \ + HeaderBuffer, \ + DataBuffer, \ + Length) \ +{ \ + ArcFilterDprIndicateReceive( \ + (((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->FilterDbs.ArcDB), \ + (HeaderBuffer), \ + (DataBuffer), \ + (Length)); \ +} + +/* + * VOID NdisMArcIndicateReceiveComplete( + * IN NDIS_HANDLE MiniportAdapterHandle); + */ +#define NdisMArcIndicateReceiveComplete(MiniportAdapterHandle) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->ArcRxCompleteHandler)( \ + ((PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle)->FilterDbs.ArcDB); \ +} + +VOID +EXPIMP +NdisMCloseLog( + IN NDIS_HANDLE LogHandle); + +NDIS_STATUS +EXPIMP +NdisMCreateLog( + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT Size, + OUT PNDIS_HANDLE LogHandle); + +VOID +EXPIMP +NdisMDeregisterAdapterShutdownHandler( + IN NDIS_HANDLE MiniportHandle); + +VOID +EXPIMP +NdisMDeregisterInterrupt( + IN PNDIS_MINIPORT_INTERRUPT Interrupt); + +VOID +EXPIMP +NdisMDeregisterIoPortRange( + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InitialPort, + IN UINT NumberOfPorts, + IN PVOID PortOffset); + +/* + * VOID NdisMEthIndicateReceive( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN NDIS_HANDLE MiniportReceiveContext, + * IN PVOID HeaderBuffer, + * IN UINT HeaderBufferSize, + * IN PVOID LookaheadBuffer, + * IN UINT LookaheadBufferSize, + * IN UINT PacketSize); + */ +#define NdisMEthIndicateReceive(MiniportAdapterHandle, \ + MiniportReceiveContext, \ + HeaderBuffer, \ + HeaderBufferSize, \ + LookaheadBuffer, \ + LookaheadBufferSize, \ + PacketSize) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->EthRxIndicateHandler)( \ + (((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->FilterDbs.u.EthDB), \ + (MiniportReceiveContext), \ + (HeaderBuffer), \ + (HeaderBuffer), \ + (HeaderBufferSize), \ + (LookaheadBuffer), \ + (LookaheadBufferSize), \ + (PacketSize)); \ +} + +/* + * VOID NdisMEthIndicateReceiveComplete( + * IN NDIS_HANDLE MiniportAdapterHandle); + */ +#define NdisMEthIndicateReceiveComplete(MiniportAdapterHandle) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->EthRxCompleteHandler)( \ + ((PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle)->FilterDbs.u.EthDB); \ +} + +/* + * VOID NdisMFddiIndicateReceive( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN NDIS_HANDLE MiniportReceiveContext, + * IN PVOID HeaderBuffer, + * IN UINT HeaderBufferSize, + * IN PVOID LookaheadBuffer, + * IN UINT LookaheadBufferSize, + * IN UINT PacketSize); + */ +#define NdisMFddiIndicateReceive(MiniportAdapterHandle, \ + MiniportReceiveContext, \ + HeaderBuffer, \ + HeaderBufferSize, \ + LookaheadBuffer, \ + LookaheadBufferSize, \ + PacketSize) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->FddiRxIndicateHandler)( \ + (((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->FilterDbs.FddiDB), \ + (MiniportReceiveContext), \ + (PUCHAR)(HeaderBuffer) + 1, \ + (((*(PUCHAR*)(HeaderBuffer)) & 0x40) ? \ + FDDI_LENGTH_OF_LONG_ADDRESS : \ + FDDI_LENGTH_OF_SHORT_ADDRESS), \ + (HeaderBuffer), \ + (HeaderBufferSize), \ + (LookaheadBuffer), \ + (LookaheadBufferSize), \ + (PacketSize)); \ +} + +/* + * VOID NdisMFddiIndicateReceiveComplete( + * IN NDIS_HANDLE MiniportAdapterHandle); + */ +#define NdisMFddiIndicateReceiveComplete(MiniportAdapterHandle) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->FddiRxCompleteHandler)( \ + ((PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle)->FilterDbs.FddiDB); \ +} + +VOID +EXPIMP +NdisMFlushLog( + IN NDIS_HANDLE LogHandle); + +VOID +EXPIMP +NdisMFreeMapRegisters( + IN NDIS_HANDLE MiniportAdapterHandle); + +VOID +EXPIMP +NdisMIndicateStatus( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS GeneralStatus, + IN PVOID StatusBuffer, + IN UINT StatusBufferSize); + +VOID +EXPIMP +NdisMIndicateStatusComplete( + IN NDIS_HANDLE MiniportAdapterHandle); + +/* + * VOID NdisMInitializeWrapper( + * OUT PNDIS_HANDLE NdisWrapperHandle, + * IN PVOID SystemSpecific1, + * IN PVOID SystemSpecific2, + * IN PVOID SystemSpecific3); + */ +#define NdisMInitializeWrapper(NdisWrapperHandle, \ + SystemSpecific1, \ + SystemSpecific2, \ + SystemSpecific3) \ + NdisInitializeWrapper((NdisWrapperHandle), \ + (SystemSpecific1), \ + (SystemSpecific2), \ + (SystemSpecific3)) + +NDIS_STATUS +EXPIMP +NdisMMapIoSpace( + OUT PVOID * VirtualAddress, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT Length); + +VOID +EXPIMP +NdisMQueryInformationComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status); + +VOID +EXPIMP +NdisMRegisterAdapterShutdownHandler( + IN NDIS_HANDLE MiniportHandle, + IN PVOID ShutdownContext, + IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler); + +NDIS_STATUS +EXPIMP +NdisMRegisterInterrupt( + OUT PNDIS_MINIPORT_INTERRUPT Interrupt, + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InterruptVector, + IN UINT InterruptLevel, + IN BOOLEAN RequestIsr, + IN BOOLEAN SharedInterrupt, + IN NDIS_INTERRUPT_MODE InterruptMode); + +NDIS_STATUS +EXPIMP +NdisMRegisterIoPortRange( + OUT PVOID * PortOffset, + IN NDIS_HANDLE MiniportAdapterHandle, + IN UINT InitialPort, + IN UINT NumberOfPorts); + +NDIS_STATUS +EXPIMP +NdisMRegisterMiniport( + IN NDIS_HANDLE NdisWrapperHandle, + IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics, + IN UINT CharacteristicsLength); + + +#ifndef NDIS_WRAPPER + +/* + * VOID NdisMResetComplete( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN NDIS_STATUS Status, + * IN BOOLEAN AddressingReset); + */ +#define NdisMResetComplete(MiniportAdapterHandle, \ + Status, \ + AddressingReset) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->ResetCompleteHandler)( \ + MiniportAdapterHandle, Status, AddressingReset); \ +} + +/* + * VOID NdisMSendComplete( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN PNDIS_PACKET Packet, + * IN NDIS_STATUS Status); + */ +#define NdisMSendComplete(MiniportAdapterHandle, \ + Packet, \ + Status) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SendCompleteHandler)( \ + MiniportAdapterHandle, Packet, Status); \ +} + +/* + * VOID NdisMSendResourcesAvailable( + * IN NDIS_HANDLE MiniportAdapterHandle); + */ +#define NdisMSendResourcesAvailable(MiniportAdapterHandle) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->SendResourcesHandler)( \ + MiniportAdapterHandle); \ +} + +/* + * VOID NdisMTransferDataComplete( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN PNDIS_PACKET Packet, + * IN NDIS_STATUS Status, + * IN UINT BytesTransferred); + */ +#define NdisMTransferDataComplete(MiniportAdapterHandle, \ + Packet, \ + Status, \ + BytesTransferred) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->TDCompleteHandler)( \ + MiniportAdapterHandle, Packet, Status, BytesTransferred) \ +} + +#endif /* NDIS_WRAPPER */ + + +VOID +EXPIMP +NdisMSetAttributes( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE MiniportAdapterContext, + IN BOOLEAN BusMaster, + IN NDIS_INTERFACE_TYPE AdapterType); + +VOID +EXPIMP +NdisMSetAttributesEx( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE MiniportAdapterContext, + IN UINT CheckForHangTimeInSeconds OPTIONAL, + IN ULONG AttributeFlags, + IN NDIS_INTERFACE_TYPE AdapterType); + +VOID +EXPIMP +NdisMSetInformationComplete( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_STATUS Status); + +VOID +EXPIMP +NdisMSleep( + IN ULONG MicrosecondsToSleep); + +BOOLEAN +EXPIMP +NdisMSynchronizeWithInterrupt( + IN PNDIS_MINIPORT_INTERRUPT Interrupt, + IN PVOID SynchronizeFunction, + IN PVOID SynchronizeContext); + +/* + * VOID NdisMTrIndicateReceive( + * IN NDIS_HANDLE MiniportAdapterHandle, + * IN NDIS_HANDLE MiniportReceiveContext, + * IN PVOID HeaderBuffer, + * IN UINT HeaderBufferSize, + * IN PVOID LookaheadBuffer, + * IN UINT LookaheadBufferSize, + * IN UINT PacketSize); + */ +#define NdisMTrIndicateReceive(MiniportAdapterHandle, \ + MiniportReceiveContext, \ + HeaderBuffer, \ + HeaderBufferSize, \ + LookaheadBuffer, \ + LookaheadBufferSize, \ + PacketSize) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->TrRxIndicateHandler)( \ + (((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->FilterDbs.TrDB), \ + (MiniportReceiveContext), \ + (HeaderBuffer), \ + (HeaderBuffer), \ + (HeaderBufferSize), \ + (LookaheadBuffer), \ + (LookaheadBufferSize), \ + (PacketSize)); \ +} + +/* + * VOID NdisMTrIndicateReceiveComplete( + * IN NDIS_HANDLE MiniportAdapterHandle); + */ +#define NdisMTrIndicateReceiveComplete(MiniportAdapterHandle) \ +{ \ + (*((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->TrRxCompleteHandler)( \ + ((PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle)->FilterDbs.TrDB); \ +} + +NDIS_STATUS +EXPIMP +NdisMWriteLogData( + IN NDIS_HANDLE LogHandle, + IN PVOID LogBuffer, + IN UINT LogBufferSize); + +VOID +EXPIMP +NdisMQueryAdapterResources( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE WrapperConfigurationContext, + OUT PNDIS_RESOURCE_LIST ResourceList, + IN OUT PUINT BufferSize); + +VOID +EXPIMP +NdisTerminateWrapper( + IN NDIS_HANDLE NdisWrapperHandle, + IN PVOID SystemSpecific); + +VOID +EXPIMP +NdisMUnmapIoSpace( + IN NDIS_HANDLE MiniportAdapterHandle, + IN PVOID VirtualAddress, + IN UINT Length); + + + +/* NDIS intermediate miniport structures */ + +typedef VOID (*W_MINIPORT_CALLBACK)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PVOID CallbackContext); + + + +/* Routines for intermediate miniport drivers */ + +NDIS_STATUS +EXPIMP +NdisIMDeInitializeDeviceInstance( + IN NDIS_HANDLE NdisMiniportHandle); + +NDIS_STATUS +EXPIMP +NdisIMInitializeDeviceInstance( + IN NDIS_HANDLE DriverHandle, + IN PNDIS_STRING DeviceInstance); + +NDIS_STATUS +EXPIMP +NdisIMQueueMiniportCallback( + IN NDIS_HANDLE MiniportAdapterHandle, + IN W_MINIPORT_CALLBACK CallbackRoutine, + IN PVOID CallbackContext); + +NDIS_STATUS +EXPIMP +NdisIMRegisterLayeredMiniport( + IN NDIS_HANDLE NdisWrapperHandle, + IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics, + IN UINT CharacteristicsLength, + OUT PNDIS_HANDLE DriverHandle); + +VOID +EXPIMP +NdisIMRevertBack( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE SwitchHandle); + +BOOLEAN +EXPIMP +NdisIMSwitchToMiniport( + IN NDIS_HANDLE MiniportAdapterHandle, + OUT PNDIS_HANDLE SwitchHandle); + + +/* Functions obsoleted by NDIS 5.0 */ + +VOID +EXPIMP +NdisFreeDmaChannel( + IN PNDIS_HANDLE NdisDmaHandle); + +VOID +EXPIMP +NdisFreeSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +NDIS_STATUS +EXPIMP +NdisIMQueueMiniportCallback( + IN NDIS_HANDLE MiniportAdapterHandle, + IN W_MINIPORT_CALLBACK CallbackRoutine, + IN PVOID CallbackContext); + +VOID +EXPIMP +NdisIMRevertBack( + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE SwitchHandle); + +BOOLEAN +EXPIMP +NdisIMSwitchToMiniport( + IN NDIS_HANDLE MiniportAdapterHandle, + OUT PNDIS_HANDLE SwitchHandle); + +VOID +EXPIMP +NdisSetupDmaTransfer( + OUT PNDIS_STATUS Status, + IN PNDIS_HANDLE NdisDmaHandle, + IN PNDIS_BUFFER Buffer, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice); + +NTSTATUS +EXPIMP +NdisUpcaseUnicodeString( + OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString); + +VOID +EXPIMP +NdisUpdateSharedMemory( + IN NDIS_HANDLE NdisAdapterHandle, + IN ULONG Length, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + + +/* Routines for NDIS protocol drivers */ + +#if BINARY_COMPATIBLE + +VOID +EXPIMP +NdisRequest( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN PNDIS_REQUEST NdisRequest); + +VOID +EXPIMP +NdisReset( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle); + +VOID +EXPIMP +NdisSend( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN PNDIS_PACKET Packet); + +VOID +EXPIMP +NdisSendPackets( + IN NDIS_HANDLE NdisBindingHandle, + IN PPNDIS_PACKET PacketArray, + IN UINT NumberOfPackets); + +VOID +EXPIMP +NdisTransferData( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE MacReceiveContext, + IN UINT ByteOffset, + IN UINT BytesToTransfer, + IN OUT PNDIS_PACKET Packet, + OUT PUINT BytesTransferred); + +#else /* BINARY_COMPATIBLE */ + +#define NdisRequest(Status, \ + NdisBindingHandle, \ + NdisRequest) \ +{ \ + *(Status) = (((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->RequestHandler)( \ + ((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->MacBindingHandle, (NdisRequest)); \ +} + +#define NdisReset(Status, \ + NdisBindingHandle) \ +{ \ + *(Status) = (((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->ResetHandler)( \ + ((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->MacBindingHandle); \ +} + +#define NdisSend(Status, \ + NdisBindingHandle, \ + Packet) \ +{ \ + *(Status) = (((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->u1.SendHandler)( \ + ((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->MacBindingHandle, (Packet)); \ +} + +#define NdisSendPackets(NdisBindingHandle, \ + PacketArray, \ + NumberOfPackets) \ +{ \ + (((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->SendPacketsHandler)( \ + (PNDIS_OPEN_BLOCK)(NdisBindingHandle), (PacketArray), (NumberOfPackets)); \ +} + +#define NdisTransferData(Status, \ + NdisBindingHandle, \ + MacReceiveContext, \ + ByteOffset, \ + BytesToTransfer, \ + Packet, \ + BytesTransferred) \ +{ \ + *(Status) = (((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->TransferDataHandler)( \ + ((PNDIS_OPEN_BLOCK)(NdisBindingHandle))->MacBindingHandle, \ + (MacReceiveContext), \ + (ByteOffset), \ + (BytesToTransfer), \ + (Packet), \ + (BytesTransferred)); \ +} + +#endif /* BINARY_COMPATIBLE */ + + +VOID +EXPIMP +NdisCloseAdapter( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisBindingHandle); + +VOID +EXPIMP +NdisCompleteBindAdapter( + IN NDIS_HANDLE BindAdapterContext, + IN NDIS_STATUS Status, + IN NDIS_STATUS OpenStatus); + +VOID +EXPIMP +NdisCompleteUnbindAdapter( + IN NDIS_HANDLE UnbindAdapterContext, + IN NDIS_STATUS Status); + +VOID +EXPIMP +NdisDeregisterProtocol( + OUT PNDIS_STATUS Status, + IN NDIS_HANDLE NdisProtocolHandle); + +VOID +EXPIMP +NdisOpenAdapter( + OUT PNDIS_STATUS Status, + OUT PNDIS_STATUS OpenErrorStatus, + OUT PNDIS_HANDLE NdisBindingHandle, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE NdisProtocolHandle, + IN NDIS_HANDLE ProtocolBindingContext, + IN PNDIS_STRING AdapterName, + IN UINT OpenOptions, + IN PSTRING AddressingInformation); + +VOID +EXPIMP +NdisOpenProtocolConfiguration( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE ConfigurationHandle, + IN PNDIS_STRING ProtocolSection); + +NDIS_STATUS +EXPIMP +NdisQueryReceiveInformation( + IN NDIS_HANDLE NdisBindingHandle, + IN NDIS_HANDLE MacContext, + OUT PLONGLONG TimeSent OPTIONAL, + OUT PLONGLONG TimeReceived OPTIONAL, + IN PUCHAR Buffer, + IN UINT BufferSize, + OUT PUINT SizeNeeded); + +VOID +EXPIMP +NdisRegisterProtocol( + OUT PNDIS_STATUS Status, + OUT PNDIS_HANDLE NdisProtocolHandle, + IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics, + IN UINT CharacteristicsLength); + +VOID +EXPIMP +NdisReturnPackets( + IN PNDIS_PACKET *PacketsToReturn, + IN UINT NumberOfPackets); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* __NDIS_H */ + +/* EOF */ diff --git a/include/net/ndisoid.h b/include/net/ndisoid.h new file mode 100644 index 0000000..121475c --- /dev/null +++ b/include/net/ndisoid.h @@ -0,0 +1,410 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/net/ndisoid.h + * PURPOSE: NDIS Object ID constants + */ +#ifndef __NDISOID_H +#define __NDISOID_H + + +typedef ULONG NDIS_OID, *PNDIS_OID; + +/* Self-contained variable data structure */ +typedef struct _NDIS_VAR_DATA_DESC +{ + USHORT Length; /* Number of bytes of data */ + USHORT MaximumLength; /* Number of bytes available */ + LONG Offset; /* Offset of data relative to the descriptor */ +} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC; + + + +/* NDIS 4.0 structures */ + +/* Structure used by TRANSLATE_NAME IOCTL */ +typedef struct _NET_PNP_ID +{ + ULONG ClassId; + ULONG Token; +} NET_PNP_ID, *PNET_PNP_ID; + + +typedef struct _NET_PNP_TRANSLATE_LIST +{ + ULONG BytesNeeded; + NET_PNP_ID IdArray[ANYSIZE_ARRAY]; +} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST; + + + +/* Generel objects */ + +/* General operational characteristics */ + +/* Mandatory */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 + +/* Optional */ +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 + +/* General statistics */ + +/* Mandatory */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E + + +/* Ethernet objects */ + +/* Ethernet operational characteristics */ + +/* Mandatory */ +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 + +/* Optional */ +#define OID_802_3_MAC_OPTIONS 0x01010105 + +/* Ethernet statistics */ + +/* Mandatory */ +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 + +/* Optional */ +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + + +/* Token Ring objects */ + +/* Token Ring operational characteristics */ + +/* Mandatory */ +#define OID_802_5_PERMANENT_ADDRESS 0x02010101 +#define OID_802_5_CURRENT_ADDRESS 0x02010102 +#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103 +#define OID_802_5_CURRENT_GROUP 0x02010104 +#define OID_802_5_LAST_OPEN_STATUS 0x02010105 +#define OID_802_5_CURRENT_RING_STATUS 0x02010106 +#define OID_802_5_CURRENT_RING_STATE 0x02010107 + +/* Token Ring statistics */ + +/* Mandatory */ +#define OID_802_5_LINE_ERRORS 0x02020101 +#define OID_802_5_LOST_FRAMES 0x02020102 +#define OID_802_5_BURST_ERRORS 0x02020201 +#define OID_802_5_AC_ERRORS 0x02020202 +#define OID_802_5_ABORT_DELIMETERS 0x02020203 +#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204 +#define OID_802_5_FREQUENCY_ERRORS 0x02020205 +#define OID_802_5_TOKEN_ERRORS 0x02020206 +#define OID_802_5_INTERNAL_ERRORS 0x02020207 + + +/* FDDI objects */ + +/* FDDI operational characteristics */ + +/* Mandatory */ +#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101 +#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102 +#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103 +#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104 +#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105 +#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106 +#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107 +#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108 + +/* FDDI statistics */ + +/* Mandatory */ +#define OID_FDDI_ATTACHMENT_TYPE 0x03020101 +#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102 +#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103 +#define OID_FDDI_FRAME_ERRORS 0x03020104 +#define OID_FDDI_FRAMES_LOST 0x03020105 +#define OID_FDDI_RING_MGT_STATE 0x03020106 +#define OID_FDDI_LCT_FAILURES 0x03020107 +#define OID_FDDI_LEM_REJECTS 0x03020108 +#define OID_FDDI_LCONNECTION_STATE 0x03020109 + + +/* LocalTalk objects */ + +/* LocalTalk operational characteristics */ + +/* Mandatory */ +#define OID_LTALK_CURRENT_NODE_ID 0x05010102 + +/* LocalTalk statistics */ + +/* Mandatory */ +#define OID_LTALK_IN_BROADCASTS 0x05020101 +#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102 + +/* Optional */ +#define OID_LTALK_OUT_NO_HANDLERS 0x05020201 +#define OID_LTALK_COLLISIONS 0x05020202 +#define OID_LTALK_DEFERS 0x05020203 +#define OID_LTALK_NO_DATA_ERRORS 0x05020204 +#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205 +#define OID_LTALK_FCS_ERRORS 0x05020206 + + +/* ARCNET objects */ + +/* ARCNET operational characteristics */ + +/* Mandatory */ +#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101 +#define OID_ARCNET_CURRENT_ADDRESS 0x06010102 + +/* ARCNET statistics */ + +/* Optional */ +#define OID_ARCNET_RECONFIGURATIONS 0x06020201 + + +/* WAN objects */ + +/* Mandatory */ +#define OID_WAN_PERMANENT_ADDRESS 0x04010101 +#define OID_WAN_CURRENT_ADDRESS 0x04010102 +#define OID_WAN_QUALITY_OF_SERVICE 0x04010103 +#define OID_WAN_PROTOCOL_TYPE 0x04010104 +#define OID_WAN_MEDIUM_SUBTYPE 0x04010105 +#define OID_WAN_HEADER_FORMAT 0x04010106 +#define OID_WAN_GET_INFO 0x04010107 +#define OID_WAN_SET_LINK_INFO 0x04010108 +#define OID_WAN_GET_LINK_INFO 0x04010109 +#define OID_WAN_LINE_COUNT 0x0401010A +#define OID_WAN_PROTOCOL_CAPS 0x0401010B +#define OID_WAN_GET_BRIDGE_INFO 0x0401020A +#define OID_WAN_SET_BRIDGE_INFO 0x0401020B + +/* Optional */ +#define OID_WAN_GET_COMP_INFO 0x0401020C +#define OID_WAN_SET_COMP_INFO 0x0401020D +#define OID_WAN_GET_STATS_INFO 0x0401020E + + +/* TAPI objects */ + +/* Madatory */ +#define OID_TAPI_ANSWER 0x07030102 +#define OID_TAPI_CLOSE 0x07030103 +#define OID_TAPI_CLOSE_CALL 0x07030104 +#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105 +#define OID_TAPI_DROP 0x07030109 +#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A +#define OID_TAPI_GET_ADDRESS_ID 0x0703010B +#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C +#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D +#define OID_TAPI_GET_CALL_INFO 0x0703010E +#define OID_TAPI_GET_CALL_STATUS 0x0703010F +#define OID_TAPI_GET_DEV_CAPS 0x07030110 +#define OID_TAPI_GET_DEV_CONFIG 0x07030111 +#define OID_TAPI_GET_ID 0x07030113 +#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114 +#define OID_TAPI_MAKE_CALL 0x07030115 +#define OID_TAPI_OPEN 0x07030117 +#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118 +#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119 +#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D +#define OID_TAPI_SET_CALL_PARAMS 0x0703011E +#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F +#define OID_TAPI_SET_MEDIA_MODE 0x07030121 +#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122 + +/* Optional */ +#define OID_TAPI_ACCEPT 0x07030101 +#define OID_TAPI_CONFIG_DIALOG 0x07030106 +#define OID_TAPI_DEV_SPECIFIC 0x07030107 +#define OID_TAPI_DIAL 0x07030108 +#define OID_TAPI_GET_EXTENSION_ID 0x07030112 +#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116 +#define OID_TAPI_SET_DEV_CONFIG 0x07030120 +#define OID_TAPI_SECURE_CALL 0x0703011A +#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B +#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C + + +/* Wireless objects */ + +/* Mandatory */ +#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101 +#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102 +#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103 +#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104 +#define OID_WW_GEN_INDICATION_REQUEST 0x09010105 +#define OID_WW_GEN_DEVICE_INFO 0x09010106 +#define OID_WW_GEN_OPERATION_MODE 0x09010107 +#define OID_WW_GEN_LOCK_STATUS 0x09010108 +#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109 +#define OID_WW_GEN_NETWORK_ID 0x0901010A +#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B +#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C +#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D +#define OID_WW_GEN_BASESTATION_ID 0x0901010E +#define OID_WW_GEN_CHANNEL_ID 0x0901010F +#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110 +#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111 +#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112 +#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113 +#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114 +#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115 +#define OID_WW_GEN_LATENCY 0x09010116 +#define OID_WW_GEN_BATTERY_LEVEL 0x09010117 +#define OID_WW_GEN_EXTERNAL_POWER 0x09010118 + +/* Optional */ +#define OID_WW_GEN_PING_ADDRESS 0x09010201 +#define OID_WW_GEN_RSSI 0x09010202 +#define OID_WW_GEN_SIM_STATUS 0x09010203 +#define OID_WW_GEN_ENABLE_SIM_PIN 0x09010204 +#define OID_WW_GEN_CHANGE_SIM_PIN 0x09010205 +#define OID_WW_GEN_SIM_PUK 0x09010206 +#define OID_WW_GEN_SIM_EXCEPTION 0x09010207 + +/* Metricom OIDs */ +#define OID_WW_MET_FUNCTION 0x09190101 + +/* DataTac OIDs */ +#define OID_WW_TAC_COMPRESSION 0x09150101 + +#define OID_WW_TAC_SET_CONFIG 0x09150102 +#define OID_WW_TAC_GET_STATUS 0x09150103 +#define OID_WW_TAC_USER_HEADER 0x09150104 + +/* Ardis OIDs */ + +#define OID_WW_ARD_SNDCP 0x09110101 +#define OID_WW_ARD_TMLY_MSG 0x09110102 +#define OID_WW_ARD_DATAGRAM 0x09110103 + +/* CDPD OIDs */ + +#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E +#define OID_WW_CDPD_TEI 0x090D010F +#define OID_WW_CDPD_RSSI 0x090D0110 + +#define OID_WW_CDPD_CS_SERVICE_PREFERENCE 0x090D0111 +#define OID_WW_CDPD_CS_SERVICE_STATUS 0x090D0112 +#define OID_WW_CDPD_CS_INFO 0x090D0113 +#define OID_WW_CDPD_CS_SUSPEND 0x090D0114 +#define OID_WW_CDPD_CS_DEFAULT_DIAL_CODE 0x090D0115 +#define OID_WW_CDPD_CS_CALLBACK 0x090D0116 +#define OID_WW_CDPD_CS_SID_LIST 0x090D0117 +#define OID_WW_CDPD_CS_CONFIGURATION 0x090D0118 + +/* Pinpoint OIDs */ + +#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101 +#define OID_WW_PIN_LAST_LOCATION 0x09090102 +#define OID_WW_PIN_LOC_FIX 0x09090103 + +/* Mobitex OIDs */ +#define OID_WW_MBX_SUBADDR 0x09050101 +/* OID 0x09050102 is reserved and may not be used */ +#define OID_WW_MBX_FLEXLIST 0x09050103 +#define OID_WW_MBX_GROUPLIST 0x09050104 +#define OID_WW_MBX_TRAFFIC_AREA 0x09050105 +#define OID_WW_MBX_LIVE_DIE 0x09050106 +#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107 + + +/* Connection-oriented objects */ + +/* Connection-oriented operational characteristics */ + +/* Mandatory */ +#define OID_GEN_CO_SUPPORTED_LIST OID_GEN_SUPPORTED_LIST +#define OID_GEN_CO_HARDWARE_STATUS OID_GEN_HARDWARE_STATUS +#define OID_GEN_CO_MEDIA_SUPPORTED OID_GEN_MEDIA_SUPPORTED +#define OID_GEN_CO_MEDIA_IN_USE OID_GEN_MEDIA_IN_USE +#define OID_GEN_CO_LINK_SPEED OID_GEN_LINK_SPEED +#define OID_GEN_CO_VENDOR_ID OID_GEN_VENDOR_ID +#define OID_GEN_CO_VENDOR_DESCRIPTION OID_GEN_VENDOR_DESCRIPTION +#define OID_GEN_CO_DRIVER_VERSION OID_GEN_DRIVER_VERSION +#define OID_GEN_CO_PROTOCOL_OPTIONS OID_GEN_PROTOCOL_OPTIONS +#define OID_GEN_CO_MAC_OPTIONS OID_GEN_MAC_OPTIONS +#define OID_GEN_CO_MEDIA_CONNECT_STATUS OID_GEN_MEDIA_CONNECT_STATUS +#define OID_GEN_CO_VENDOR_DRIVER_VERSION OID_GEN_VENDOR_DRIVER_VERSION + +/* Optional */ +#define OID_GEN_CO_SUPPORTED_GUIDS OID_GEN_SUPPORTED_GUIDS +#define OID_GEN_CO_GET_TIME_CAPS OID_GEN_GET_TIME_CAPS +#define OID_GEN_CO_GET_NETCARD_TIME OID_GEN_GET_NETCARD_TIME +#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x00020120 + +/* Connection-oriented statistics */ + +#define OID_GEN_CO_XMIT_PDUS_OK OID_GEN_XMIT_OK +#define OID_GEN_CO_RCV_PDUS_OK OID_GEN_RCV_OK +#define OID_GEN_CO_XMIT_PDUS_ERROR OID_GEN_XMIT_ERROR +#define OID_GEN_CO_RCV_PDUS_ERROR OID_GEN_RCV_ERROR +#define OID_GEN_CO_RCV_PDUS_NO_BUFFER OID_GEN_RCV_NO_BUFFER +#define OID_GEN_CO_RCV_CRC_ERROR OID_GEN_RCV_CRC_ERROR +#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH OID_GEN_TRANSMIT_QUEUE_LENGTH +#define OID_GEN_CO_BYTES_XMIT OID_GEN_DIRECTED_BYTES_XMIT +#define OID_GEN_CO_BYTES_RCV OID_GEN_DIRECTED_BYTES_RCV +#define OID_GEN_CO_NETCARD_LOAD OID_GEN_NETCARD_LOAD +#define OID_GEN_CO_DEVICE_PROFILE OID_GEN_DEVICE_PROFILE +#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020221 + +#endif /* __NDISOID_H */ + +/* EOF */ diff --git a/include/net/netevent.h b/include/net/netevent.h new file mode 100644 index 0000000..922d429 --- /dev/null +++ b/include/net/netevent.h @@ -0,0 +1,16 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/net/netevent.h + * PURPOSE: Network event constants + */ +#ifndef __NETEVENT_H +#define __NETEVENT_H + +#define EVENT_TRANSPORT_REGISTER_FAILED 0xC000232CL + +#define EVENT_TRANSPORT_ADAPTER_NOT_FOUND 0xC000232EL + +#endif /* __NETEVENT_H */ + +/* EOF */ diff --git a/include/net/ntddndis.h b/include/net/ntddndis.h new file mode 100644 index 0000000..e3d6a82 --- /dev/null +++ b/include/net/ntddndis.h @@ -0,0 +1,35 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS library + * FILE: include/net/ntddndis.h + * PURPOSE: Structures for accessing NDIS devices + */ +#ifndef __NTDDNDIS_H +#define __NIDDNDIS_H + +typedef enum _NDIS_DEVICE_POWER_STATE +{ + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +} NDIS_DEVICE_POWER_STATE, *PNDIS_DEVICE_POWER_STATE; + +typedef struct _NDIS_PM_WAKE_UP_CAPABILITIES +{ + NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +} NDIS_PM_WAKE_UP_CAPABILITIES, *PNDIS_PM_WAKE_UP_CAPABILITIES; + +typedef struct _NDIS_PNP_CAPABILITIES +{ + ULONG Flags; + NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +} NDIS_PNP_CAPABILITIES, *PNDIS_PNP_CAPABILITIES; + +#endif /* __NTDDNDIS_H */ + +/* EOF */ diff --git a/include/net/tdi.h b/include/net/tdi.h new file mode 100644 index 0000000..183a652 --- /dev/null +++ b/include/net/tdi.h @@ -0,0 +1,644 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TDI library + * FILE: include/net/tdi.h + * PURPOSE: TDI definitions for user mode clients + */ +#ifndef __TDI_H +#define __TDI_H + +/* FIXME: Missed some definitions in ntddk.h */ + +/* Could be defined elsewhere */ +//#ifndef INT +//typedef signed int INT, *PINT; +//#endif + + + +/* Basic types */ + +typedef LONG TDI_STATUS; +typedef PVOID CONNECTION_CONTEXT; + + + +/* TDI status codes */ + +#define TDI_SUCCESS STATUS_SUCCESS +#define TDI_NO_RESOURCES STATUS_INSUFFICIENT_RESOURCES +#define TDI_ADDR_IN_USE STATUS_ADDRESS_ALREADY_EXISTS +#define TDI_BAD_ADDR STATUS_INVALID_ADDRESS_COMPONENT +#define TDI_NO_FREE_ADDR STATUS_TOO_MANY_ADDRESSES +#define TDI_ADDR_INVALID STATUS_INVALID_ADDRESS +#define TDI_ADDR_DELETED STATUS_ADDRESS_CLOSED +#define TDI_BUFFER_OVERFLOW STATUS_BUFFER_OVERFLOW +#define TDI_BAD_EVENT_TYPE STATUS_INVALID_PARAMETER +#define TDI_BAD_OPTION STATUS_INVALID_PARAMETER +#define TDI_CONN_REFUSED STATUS_CONNECTION_REFUSED +#define TDI_INVALID_CONNECTION STATUS_CONNECTION_INVALID +#define TDI_ALREADY_ASSOCIATED STATUS_ADDRESS_ALREADY_ASSOCIATED +#define TDI_NOT_ASSOCIATED STATUS_ADDRESS_NOT_ASSOCIATED +#define TDI_CONNECTION_ACTIVE STATUS_CONNECTION_ACTIVE +#define TDI_CONNECTION_ABORTED STATUS_CONNECTION_ABORTED +#define TDI_CONNECTION_RESET STATUS_CONNECTION_RESET +#define TDI_TIMED_OUT STATUS_IO_TIMEOUT +#define TDI_GRACEFUL_DISC STATUS_GRACEFUL_DISCONNECT +#define TDI_NOT_ACCEPTED STATUS_DATA_NOT_ACCEPTED +#define TDI_MORE_PROCESSING STATUS_MORE_PROCESSING_REQUIRED +#define TDI_INVALID_STATE STATUS_INVALID_DEVICE_STATE +#define TDI_INVALID_PARAMETER STATUS_INVALID_PARAMETER +#define TDI_DEST_NET_UNREACH STATUS_NETWORK_UNREACHABLE +#define TDI_DEST_HOST_UNREACH STATUS_HOST_UNREACHABLE +#define TDI_DEST_UNREACHABLE TDI_DEST_HOST_UNREACH +#define TDI_DEST_PROT_UNREACH STATUS_PROTOCOL_UNREACHABLE +#define TDI_DEST_PORT_UNREACH STATUS_PORT_UNREACHABLE +#define TDI_INVALID_QUERY STATUS_INVALID_DEVICE_REQUEST +#define TDI_REQ_ABORTED STATUS_REQUEST_ABORTED +#define TDI_BUFFER_TOO_SMALL STATUS_BUFFER_TOO_SMALL +#define TDI_CANCELLED STATUS_CANCELLED +#define TDI_BUFFER_TOO_BIG STATUS_INVALID_BUFFER_SIZE +#define TDI_INVALID_REQUEST STATUS_INVALID_DEVICE_REQUEST +#define TDI_PENDING STATUS_PENDING +#define TDI_ITEM_NOT_FOUND STATUS_OBJECT_NAME_NOT_FOUND + +#define TDI_OPTION_EOL 0 +#define TDI_ADDRESS_OPTION_REUSE 1 +#define TDI_ADDRESS_OPTION_DHCP 2 + + + +/* TDI IOCTL codes */ + +#define TDI_CONTROL_CODE(Request, Method) \ + CTL_CODE(FILE_DEVICE_TRANSPORT, Request, Method, FILE_ANY_ACCESS) + +#define IOCTL_TDI_ACCEPT TDI_CONTROL_CODE(0, METHOD_BUFFERED) +#define IOCTL_TDI_CONNECT TDI_CONTROL_CODE(1, METHOD_BUFFERED) +#define IOCTL_TDI_DISCONNECT TDI_CONTROL_CODE(2, METHOD_BUFFERED) +#define IOCTL_TDI_LISTEN TDI_CONTROL_CODE(3, METHOD_BUFFERED) +#define IOCTL_TDI_QUERY_INFORMATION TDI_CONTROL_CODE(4, METHOD_OUT_DIRECT) +#define IOCTL_TDI_RECEIVE TDI_CONTROL_CODE(5, METHOD_OUT_DIRECT) +#define IOCTL_TDI_RECEIVE_DATAGRAM TDI_CONTROL_CODE(6, METHOD_OUT_DIRECT) +#define IOCTL_TDI_SEND TDI_CONTROL_CODE(7, METHOD_IN_DIRECT) +#define IOCTL_TDI_SEND_DATAGRAM TDI_CONTROL_CODE(8, METHOD_IN_DIRECT) +#define IOCTL_TDI_SET_EVENT_HANDLER TDI_CONTROL_CODE(9, METHOD_BUFFERED) +#define IOCTL_TDI_SET_INFORMATION TDI_CONTROL_CODE(10, METHOD_IN_DIRECT) +#define IOCTL_TDI_ASSOCIATE_ADDRESS TDI_CONTROL_CODE(11, METHOD_BUFFERED) +#define IOCTL_TDI_DISASSOCIATE_ADDRESS TDI_CONTROL_CODE(12, METHOD_BUFFERED) +#define IOCTL_TDI_ACTION TDI_CONTROL_CODE(13, METHOD_OUT_DIRECT) + + + +/* TDI transport driver dispatch routines */ + +NTSTATUS TdiDispatchCleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS TdiDispatchClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS TdiDispatchCreate( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS TdiDispatchDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp); + +BOOLEAN TdiDispatchFastDeviceControl( + IN PFILE_OBJECT FileObject, + IN BOOLEAN Wait, + IN PVOID InputBuffer, + IN ULONG InputBufferLength, + IN OUT PVOID OutputBuffer, + IN ULONG OutputBufferLength, + IN ULONG IoControlCode, + OUT PIO_STATUS_BLOCK IoStatus); + +NTSTATUS TdiDispatchInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + + +/* TDI structures */ + +typedef struct _TDI_CONNECTION_INFORMATION +{ + LONG UserDataLength; + PVOID UserData; + LONG OptionsLength; + PVOID Options; + LONG RemoteAddressLength; + PVOID RemoteAddress; +} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION; + +typedef struct _TDI_REQUEST +{ + union { + HANDLE AddressHandle; + CONNECTION_CONTEXT ConnectionContext; + HANDLE ControlChannel; + } Handle; + PVOID RequestNotifyObject; + PVOID RequestContext; + TDI_STATUS TdiStatus; +} TDI_REQUEST, *PTDI_REQUEST; + +typedef struct _TDI_REQUEST_STATUS +{ + TDI_STATUS Status; + PVOID RequestContext; + ULONG BytesTransferred; +} TDI_REQUEST_STATUS, *PTDI_REQUEST_STATUS; + + +typedef struct _TA_ADDRESS +{ + USHORT AddressLength; + USHORT AddressType; + UCHAR Address[1]; +} TA_ADDRESS, *PTA_ADDRESS; + +#define TDI_ADDRESS_TYPE_UNSPEC 0 +#define TDI_ADDRESS_TYPE_UNIX 1 +#define TDI_ADDRESS_TYPE_IP 2 +#define TDI_ADDRESS_TYPE_IMPLINK 3 +#define TDI_ADDRESS_TYPE_PUP 4 +#define TDI_ADDRESS_TYPE_CHAOS 5 +#define TDI_ADDRESS_TYPE_NS 6 +#define TDI_ADDRESS_TYPE_IPX 6 +#define TDI_ADDRESS_TYPE_NBS 7 +#define TDI_ADDRESS_TYPE_ECMA 8 +#define TDI_ADDRESS_TYPE_DATAKIT 9 +#define TDI_ADDRESS_TYPE_CCITT 10 +#define TDI_ADDRESS_TYPE_SNA 11 +#define TDI_ADDRESS_TYPE_DECnet 12 +#define TDI_ADDRESS_TYPE_DLI 13 +#define TDI_ADDRESS_TYPE_LAT 14 +#define TDI_ADDRESS_TYPE_HYLINK 15 +#define TDI_ADDRESS_TYPE_APPLETALK 16 +#define TDI_ADDRESS_TYPE_NETBIOS 17 +#define TDI_ADDRESS_TYPE_8022 18 +#define TDI_ADDRESS_TYPE_OSI_TSAP 19 +#define TDI_ADDRESS_TYPE_NETONE 20 +#define TDI_ADDRESS_TYPE_VNS 21 +#define TDI_ADDRESS_TYPE_NETBIOS_EX 22 + + +#define TdiTransportAddress "TransportAddress" +#define TdiConnectionContext "ConnectionContext" +#define TDI_TRANSPORT_ADDRESS_LENGTH (sizeof(TdiTransportAddress) - 1) +#define TDI_CONNECTION_CONTEXT_LENGTH (sizeof(TdiConnectionContext) - 1) + + +typedef struct _TRANSPORT_ADDRESS +{ + LONG TAAddressCount; + TA_ADDRESS Address[1]; +} TRANSPORT_ADDRESS, *PTRANSPORT_ADDRESS; + +typedef struct _TDI_ADDRESS_INFO +{ + ULONG ActivityCount; + TRANSPORT_ADDRESS Address; +} TDI_ADDRESS_INFO, *PTDI_ADDRESS_INFO; + +typedef struct _TDI_ACTION_HEADER +{ + ULONG TransportId; + USHORT ActionCode; + USHORT Reserved; +} TDI_ACTION_HEADER, *PTDI_ACTION_HEADER; + +typedef struct _TDI_ADDRESS_8022 +{ + UCHAR MACAddress[6]; +} TDI_ADDRESS_8022, *PTDI_ADDRESS_8022; + +typedef struct _TDI_ADDRESS_APPLETALK +{ + USHORT Network; + UCHAR Node; + UCHAR Socket; +} TDI_ADDRESS_APPLETALK, *PTDI_ADDRESS_APPLETALK; + +#define TDI_ADDRESS_LENGTH_APPLETALK sizeof(TDI_ADDRESS_APPLETALK) + +typedef struct _TDI_ADDRESS_IP +{ + USHORT sin_port; + ULONG in_addr; + UCHAR sin_zero[8]; +} TDI_ADDRESS_IP, *PTDI_ADDRESS_IP; + +#define TDI_ADDRESS_LENGTH_IP sizeof(TDI_ADDRESS_IP) + +typedef struct _TDI_ADDRESS_IPX +{ + ULONG NetworkAddress; + UCHAR NodeAddress[6]; + USHORT Socket; +} TDI_ADDRESS_IPX, *PTDI_ADDRESS_IPX; + +#define TDI_ADDRESS_LENGTH_IPX sizeof(TDI_ADDRESS_IPX) + +typedef struct _TDI_ADDRESS_NETBIOS +{ + USHORT NetbiosNameType; + UCHAR NetbiosName[16]; +} TDI_ADDRESS_NETBIOS, *PTDI_ADDRESS_NETBIOS; + +#define TDI_ADDRESS_NETBIOS_TYPE_UNIQUE 0x0000 +#define TDI_ADDRESS_NETBIOS_TYPE_GROUP 0x0001 +#define TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE 0x0002 +#define TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP 0x0003 + +#define TDI_ADDRESS_LENGTH_NETBIOS sizeof(TDI_ADDRESS_NETBIOS) + +typedef struct _TDI_ADDRESS_NETBIOS_EX +{ + UCHAR EndpointName[16]; + TDI_ADDRESS_NETBIOS NetbiosAddress; +} TDI_ADDRESS_NETBIOS_EX, *PTDI_ADDRESS_NETBIOS_EX; + +#define TDI_ADDRESS_LENGTH_NETBIOS_EX sizeof(TDI_ADDRESS_NETBIOS_EX) + +typedef struct _TDI_ADDRESS_NETONE +{ + USHORT NetoneNameType; + UCHAR NetoneName[20]; +} TDI_ADDRESS_NETONE, *PTDI_ADDRESS_NETONE; + +#define TDI_ADDRESS_NETONE_TYPE_UNIQUE 0x0000 +#define TDI_ADDRESS_NETONE_TYPE_ROTORED 0x0001 + +#define TDI_ADDRESS_LENGTH_NETONE sizeof(TDI_ADDRESS_NETONE) + +typedef struct _TDI_ADDRESS_NS +{ + ULONG NetworkAddress; + UCHAR NodeAddress[6]; + USHORT Socket; +} TDI_ADDRESS_NS, *PTDI_ADDRESS_NS; + +#define TDI_ADDRESS_LENGTH_NS sizeof(TDI_ADDRESS_NS) + +#define ISO_MAX_ADDR_LENGTH 64 + +#define ISO_HIERARCHICAL 0 +#define ISO_NON_HIERARCHICAL 1 + +typedef struct _TDI_ADDRESS_OSI_TSAP +{ + USHORT tp_addr_type; + USHORT tp_taddr_len; + USHORT tp_tsel_len; + UCHAR tp_addr[ISO_MAX_ADDR_LENGTH]; +} TDI_ADDRESS_OSI_TSAP, *PTDI_ADDRESS_OSI_TSAP; + +#define TDI_ADDRESS_LENGTH_OSI_TSAP sizeof(TDI_ADDRESS_OSI_TSAP) + +typedef struct _TDI_ADDRESS_VNS +{ + UCHAR net_address[4]; + UCHAR subnet_addr[2]; + UCHAR port[2]; + UCHAR hops; + UCHAR filler[5]; +} TDI_ADDRESS_VNS, *PTDI_ADDRESS_VNS; + +#define TDI_ADDRESS_LENGTH_VNS sizeof(TDI_ADDRESS_VNS) + + +/* TDI request structures */ + +typedef struct _TDI_CONNECT_REQUEST +{ + TDI_REQUEST Request; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; + PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; + LARGE_INTEGER Timeout; +} TDI_REQUEST_CONNECT, *PTDI_REQUEST_CONNECT; + +typedef struct _TDI_REQUEST_ACCEPT +{ + TDI_REQUEST Request; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; + PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; +} TDI_REQUEST_ACCEPT, *PTDI_REQUEST_ACCEPT; + +typedef struct _TDI_REQUEST_LISTEN +{ + TDI_REQUEST Request; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; + PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; + USHORT ListenFlags; +} TDI_REQUEST_LISTEN, *PTDI_REQUEST_LISTEN; + +typedef struct _TDI_DISCONNECT_REQUEST +{ + TDI_REQUEST Request; + LARGE_INTEGER Timeout; +} TDI_REQUEST_DISCONNECT, *PTDI_REQUEST_DISCONNECT; + +typedef struct _TDI_REQUEST_SEND +{ + TDI_REQUEST Request; + USHORT SendFlags; +} TDI_REQUEST_SEND, *PTDI_REQUEST_SEND; + +typedef struct _TDI_REQUEST_RECEIVE +{ + TDI_REQUEST Request; + USHORT ReceiveFlags; +} TDI_REQUEST_RECEIVE, *PTDI_REQUEST_RECEIVE; + +typedef struct _TDI_REQUEST_SEND_DATAGRAM +{ + TDI_REQUEST Request; + PTDI_CONNECTION_INFORMATION SendDatagramInformation; +} TDI_REQUEST_SEND_DATAGRAM, *PTDI_REQUEST_SEND_DATAGRAM; + +typedef struct _TDI_REQUEST_RECEIVE_DATAGRAM +{ + TDI_REQUEST Request; + PTDI_CONNECTION_INFORMATION ReceiveDatagramInformation; + PTDI_CONNECTION_INFORMATION ReturnInformation; + USHORT ReceiveFlags; +} TDI_REQUEST_RECEIVE_DATAGRAM, *PTDI_REQUEST_RECEIVE_DATAGRAM; + +typedef struct _TDI_REQUEST_SET_EVENT +{ + TDI_REQUEST Request; + LONG EventType; + PVOID EventHandler; + PVOID EventContext; +} TDI_REQUEST_SET_EVENT_HANDLER, *PTDI_REQUEST_SET_EVENT_HANDLER; + +#define TDI_RECEIVE_BROADCAST 0x00000004 +#define TDI_RECEIVE_MULTICAST 0x00000008 +#define TDI_RECEIVE_PARTIAL 0x00000010 +#define TDI_RECEIVE_NORMAL 0x00000020 +#define TDI_RECEIVE_EXPEDITED 0x00000040 +#define TDI_RECEIVE_PEEK 0x00000080 +#define TDI_RECEIVE_NO_RESPONSE_EXP 0x00000100 +#define TDI_RECEIVE_COPY_LOOKAHEAD 0x00000200 +#define TDI_RECEIVE_ENTIRE_MESSAGE 0x00000400 +#define TDI_RECEIVE_AT_DISPATCH_LEVEL 0x00000800 + +/* Listen flags */ +#define TDI_QUERY_ACCEPT 0x00000001 + +/* Options used for both SendOptions and ReceiveIndicators */ +#define TDI_SEND_EXPEDITED 0x0020 +#define TDI_SEND_PARTIAL 0x0040 +#define TDI_SEND_NO_RESPONSE_EXPECTED 0x0080 +#define TDI_SEND_NON_BLOCKING 0x0100 + +/* Disconnect Flags */ +#define TDI_DISCONNECT_WAIT 0x0001 +#define TDI_DISCONNECT_ABORT 0x0002 +#define TDI_DISCONNECT_RELEASE 0x0004 + +/* TdiRequest structure for TdiQueryInformation request */ +typedef struct _TDI_REQUEST_QUERY_INFORMATION +{ + TDI_REQUEST Request; + ULONG QueryType; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; +} TDI_REQUEST_QUERY_INFORMATION, *PTDI_REQUEST_QUERY_INFORMATION; + +/* TdiRequest structure for TdiSetInformation request */ +typedef struct _TDI_REQUEST_SET_INFORMATION +{ + TDI_REQUEST Request; + ULONG SetType; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; +} TDI_REQUEST_SET_INFORMATION, *PTDI_REQUEST_SET_INFORMATION; + +typedef union _TDI_REQUEST_TYPE +{ + TDI_REQUEST_ACCEPT TdiAccept; + TDI_REQUEST_CONNECT TdiConnect; + TDI_REQUEST_DISCONNECT TdiDisconnect; + TDI_REQUEST_LISTEN TdiListen; + TDI_REQUEST_QUERY_INFORMATION TdiQueryInformation; + TDI_REQUEST_RECEIVE TdiReceive; + TDI_REQUEST_RECEIVE_DATAGRAM TdiReceiveDatagram; + TDI_REQUEST_SEND TdiSend; + TDI_REQUEST_SEND_DATAGRAM TdiSendDatagram; + TDI_REQUEST_SET_EVENT_HANDLER TdiSetEventHandler; + TDI_REQUEST_SET_INFORMATION TdiSetInformation; +} TDI_REQUEST_TYPE, *PTDI_REQUEST_TYPE; + + + +/* Query information types */ + +/* Generic query info types that must be supported by all transports */ +#define TDI_QUERY_BROADCAST_ADDRESS 0x00000001 +#define TDI_QUERY_PROVIDER_INFO 0x00000002 +#define TDI_QUERY_ADDRESS_INFO 0x00000003 +#define TDI_QUERY_CONNECTION_INFO 0x00000004 +#define TDI_QUERY_PROVIDER_STATISTICS 0x00000005 +#define TDI_QUERY_DATAGRAM_INFO 0x00000006 +#define TDI_QUERY_DATA_LINK_ADDRESS 0x00000007 +#define TDI_QUERY_NETWORK_ADDRESS 0x00000008 +#define TDI_QUERY_MAX_DATAGRAM_INFO 0x00000009 + +/* Netbios specific query information types */ +#define TDI_QUERY_ADAPTER_STATUS 0x00000100 +#define TDI_QUERY_SESSION_STATUS 0x00000200 +#define TDI_QUERY_FIND_NAME 0x00000300 + +typedef struct _TA_APPLETALK_ADDR +{ + LONG TAAddressCount; + struct _AddrAtalk { + USHORT AddressLength; + USHORT AddressType; + TDI_ADDRESS_APPLETALK Address[1]; + } Address[1]; +} TA_APPLETALK_ADDRESS, *PTA_APPLETALK_ADDRESS; + +typedef struct _TA_ADDRESS_IP +{ + LONG TAAddressCount; + struct _AddrIp { + USHORT AddressLength; + USHORT AddressType; + TDI_ADDRESS_IP Address[1]; + } Address[1]; +} TA_ADDRESS_IP, *PTA_ADDRESS_IP; + +typedef struct _TA_ADDRESS_IPX +{ + LONG TAAddressCount; + struct _AddrIpx { + USHORT AddressLength; + USHORT AddressType; + TDI_ADDRESS_IPX Address[1]; + } Address[1]; +} TA_IPX_ADDRESS, *PTA_IPX_ADDRESS; + +typedef struct _TA_NETBIOS_ADDRESS +{ + LONG TAAddressCount; + struct _Addr{ + USHORT AddressLength; + USHORT AddressType; + TDI_ADDRESS_NETBIOS Address[1]; + } Address[1]; +} TA_NETBIOS_ADDRESS, *PTA_NETBIOS_ADDRESS; + +typedef struct _TA_ADDRESS_NS +{ + LONG TAAddressCount; + struct _AddrNs { + USHORT AddressLength; + USHORT AddressType; + TDI_ADDRESS_NS Address[1]; + } Address[1]; +} TA_NS_ADDRESS, *PTA_NS_ADDRESS; + +typedef struct _TA_ADDRESS_VNS +{ + LONG TAAddressCount; + struct _AddrVns { + USHORT AddressLength; + USHORT AddressType; + TDI_ADDRESS_VNS Address[1]; + } Address[1]; +} TA_VNS_ADDRESS, *PTA_VNS_ADDRESS; + + +/* Structures used for TdiQueryInformation and TdiSetInformation */ + +typedef struct _TDI_ENDPOINT_INFO +{ + ULONG State; + ULONG Event; + ULONG TransmittedTsdus; + ULONG ReceivedTsdus; + ULONG TransmissionErrors; + ULONG ReceiveErrors; + ULONG MinimumLookaheadData; + ULONG MaximumLookaheadData; + ULONG PriorityLevel; + ULONG SecurityLevel; + ULONG SecurityCompartment; +} TDI_ENDPOINT_INFO, *PTDI_ENDPOINT_INFO; + +typedef struct _TDI_CONNECTION_INFO +{ + ULONG State; + ULONG Event; + ULONG TransmittedTsdus; + ULONG ReceivedTsdus; + ULONG TransmissionErrors; + ULONG ReceiveErrors; + LARGE_INTEGER Throughput; + LARGE_INTEGER Delay; + ULONG SendBufferSize; + ULONG ReceiveBufferSize; + BOOLEAN Unreliable; +} TDI_CONNECTION_INFO, *PTDI_CONNECTION_INFO; + +typedef struct _TDI_DATAGRAM_INFO +{ + ULONG MaximumDatagramBytes; + ULONG MaximumDatagramCount; +} TDI_DATAGRAM_INFO, *PTDI_DATAGRAM_INFO; + +typedef struct _TDI_MAX_DATAGRAM_INFO +{ + ULONG MaxDatagramSize; +} TDI_MAX_DATAGRAM_INFO, *PTDI_MAX_DATAGRAM_INFO; + +typedef struct _TDI_PROVIDER_INFO +{ + ULONG Version; + ULONG MaxSendSize; + ULONG MaxConnectionUserData; + ULONG MaxDatagramSize; + ULONG ServiceFlags; + ULONG MinimumLookaheadData; + ULONG MaximumLookaheadData; + ULONG NumberOfResources; + LARGE_INTEGER StartTime; +} TDI_PROVIDER_INFO, *PTDI_PROVIDER_INFO; + +#define TDI_SERVICE_CONNECTION_MODE 0x00000001 +#define TDI_SERVICE_ORDERLY_RELEASE 0x00000002 +#define TDI_SERVICE_CONNECTIONLESS_MODE 0x00000004 +#define TDI_SERVICE_ERROR_FREE_DELIVERY 0x00000008 +#define TDI_SERVICE_SECURITY_LEVEL 0x00000010 +#define TDI_SERVICE_BROADCAST_SUPPORTED 0x00000020 +#define TDI_SERVICE_MULTICAST_SUPPORTED 0x00000040 +#define TDI_SERVICE_DELAYED_ACCEPTANCE 0x00000080 +#define TDI_SERVICE_EXPEDITED_DATA 0x00000100 +#define TDI_SERVICE_INTERNAL_BUFFERING 0x00000200 +#define TDI_SERVICE_ROUTE_DIRECTED 0x00000400 +#define TDI_SERVICE_NO_ZERO_LENGTH 0x00000800 +#define TDI_SERVICE_POINT_TO_POINT 0x00001000 +#define TDI_SERVICE_MESSAGE_MODE 0x00002000 +#define TDI_SERVICE_HALF_DUPLEX 0x00004000 + +typedef struct _TDI_PROVIDER_RESOURCE_STATS +{ + ULONG ResourceId; + ULONG MaximumResourceUsed; + ULONG AverageResourceUsed; + ULONG ResourceExhausted; +} TDI_PROVIDER_RESOURCE_STATS, *PTDI_PROVIDER_RESOURCE_STATS; + +typedef struct _TDI_PROVIDER_STATISTICS +{ + ULONG Version; + ULONG OpenConnections; + ULONG ConnectionsAfterNoRetry; + ULONG ConnectionsAfterRetry; + ULONG LocalDisconnects; + ULONG RemoteDisconnects; + ULONG LinkFailures; + ULONG AdapterFailures; + ULONG SessionTimeouts; + ULONG CancelledConnections; + ULONG RemoteResourceFailures; + ULONG LocalResourceFailures; + ULONG NotFoundFailures; + ULONG NoListenFailures; + ULONG DatagramsSent; + LARGE_INTEGER DatagramBytesSent; + ULONG DatagramsReceived; + LARGE_INTEGER DatagramBytesReceived; + ULONG PacketsSent; + ULONG PacketsReceived; + ULONG DataFramesSent; + LARGE_INTEGER DataFrameBytesSent; + ULONG DataFramesReceived; + LARGE_INTEGER DataFrameBytesReceived; + ULONG DataFramesResent; + LARGE_INTEGER DataFrameBytesResent; + ULONG DataFramesRejected; + LARGE_INTEGER DataFrameBytesRejected; + ULONG ResponseTimerExpirations; + ULONG AckTimerExpirations; + ULONG MaximumSendWindow; + ULONG AverageSendWindow; + ULONG PiggybackAckQueued; + ULONG PiggybackAckTimeouts; + LARGE_INTEGER WastedPacketSpace; + ULONG WastedSpacePackets; + ULONG NumberOfResources; + TDI_PROVIDER_RESOURCE_STATS Resources[1]; +} TDI_PROVIDER_STATISTICS, *PTDI_PROVIDER_STATISTICS; + +#endif /* __TDI_H */ + +/* EOF */ diff --git a/include/net/tdiinfo.h b/include/net/tdiinfo.h new file mode 100644 index 0000000..c734daa --- /dev/null +++ b/include/net/tdiinfo.h @@ -0,0 +1,96 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TDI library + * FILE: include/net/tdiinfo.h + * PURPOSE: TDI definitions for Tdi(Query/Set)InformationEx + */ +#ifndef __TDIINFO_H +#define __TDIINFO_H + +typedef struct TDIEntityID +{ + ULONG tei_entity; + ULONG tei_instance; +} TDIEntityID; + +typedef struct TDIObjectID +{ + TDIEntityID toi_entity; + ULONG toi_class; + ULONG toi_type; + ULONG toi_id; +} TDIObjectID; + +#define CONTEXT_SIZE 16 + +#define MAX_TDI_ENTITIES 512 + +#define INFO_CLASS_GENERIC 0x100 +#define INFO_CLASS_PROTOCOL 0x200 +#define INFO_CLASS_IMPLEMENTATION 0x300 + +#define INFO_TYPE_PROVIDER 0x100 +#define INFO_TYPE_ADDRESS_OBJECT 0x200 +#define INFO_TYPE_CONNECTION 0x300 + + +#define ENTITY_LIST_ID 0 + +#define GENERIC_ENTITY 0 + + +#define IF_ENTITY 0x200 + +#define AT_ENTITY 0x280 + +#define CO_NL_ENTITY 0x300 +#define CL_NL_ENTITY 0x301 + +#define ER_ENTITY 0x380 + +#define CO_TL_ENTITY 0x400 +#define CL_TL_ENTITY 0x401 + + +/* IDs supported by all entities */ + +#define ENTITY_TYPE_ID 1 + + +#define IF_GENERIC 0x200 +#define IF_MIB 0x202 + +#define AT_ARP 0x280 +#define AT_NULL 0x282 + +#define CL_NL_IPX 0x301 +#define CL_NL_IP 0x303 + +#define ER_ICMP 0x380 + +#define CO_TL_NBF 0x400 +#define CO_TL_SPX 0x402 +#define CO_TL_TCP 0x404 +#define CO_TL_SPP 0x406 + +#define CL_TL_NBF 0x401 +#define CL_TL_UDP 0x403 + +/* TCP specific structures */ + +typedef struct _TCP_REQUEST_QUERY_INFORMATION_EX +{ + TDIObjectID ID; + UCHAR Context[CONTEXT_SIZE]; +} TCP_REQUEST_QUERY_INFORMATION_EX, *PTCP_REQUEST_QUERY_INFORMATION_EX; + +typedef struct _TCP_REQUEST_SET_INFORMATION_EX +{ + TDIObjectID ID; + UINT BufferSize; + UCHAR Buffer[1]; +} TCP_REQUEST_SET_INFORMATION_EX, *PTCP_REQUEST_SET_INFORMATION_EX; + +#endif /* __TDIINFO_H */ + +/* EOF */ diff --git a/include/net/tdikrnl.h b/include/net/tdikrnl.h new file mode 100644 index 0000000..abfc4cb --- /dev/null +++ b/include/net/tdikrnl.h @@ -0,0 +1,804 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS TDI library + * FILE: include/net/tdikrnl.h + * PURPOSE: TDI definitions for kernel mode drivers + */ +#ifndef __TDIKRNL_H +#define __TDIKRNL_H + +#include "tdi.h" + +#ifndef STDCALL +#define STDCALL +#endif + +typedef struct _TDI_REQUEST_KERNEL +{ + ULONG RequestFlags; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; + PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; + PVOID RequestSpecific; +} TDI_REQUEST_KERNEL, *PTDI_REQUEST_KERNEL; + +/* Request codes */ +#define TDI_ASSOCIATE_ADDRESS 0x01 +#define TDI_DISASSOCIATE_ADDRESS 0x02 +#define TDI_CONNECT 0x03 +#define TDI_LISTEN 0x04 +#define TDI_ACCEPT 0x05 +#define TDI_DISCONNECT 0x06 +#define TDI_SEND 0x07 +#define TDI_RECEIVE 0x08 +#define TDI_SEND_DATAGRAM 0x09 +#define TDI_RECEIVE_DATAGRAM 0x0A +#define TDI_SET_EVENT_HANDLER 0x0B +#define TDI_QUERY_INFORMATION 0x0C +#define TDI_SET_INFORMATION 0x0D +#define TDI_ACTION 0x0E + +#define TDI_DIRECT_SEND 0x27 +#define TDI_DIRECT_SEND_DATAGRAM 0x29 + + +#define TDI_TRANSPORT_ADDRESS_FILE 1 +#define TDI_CONNECTION_FILE 2 +#define TDI_CONTROL_CHANNEL_FILE 3 + +/* Internal TDI IOCTLS */ +#define IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER TDI_CONTROL_CODE(0x80, METHOD_NEITHER) +#define IOCTL_TDI_QUERY_DIRECT_SENDDG_HANDLER TDI_CONTROL_CODE(0x81, METHOD_NEITHER) + +/* TdiAssociateAddress */ +typedef struct _TDI_REQUEST_KERNEL_ASSOCIATE +{ + HANDLE AddressHandle; +} TDI_REQUEST_KERNEL_ASSOCIATE, *PTDI_REQUEST_KERNEL_ASSOCIATE; + +/* TdiDisassociateAddress */ +typedef TDI_REQUEST_KERNEL TDI_REQUEST_KERNEL_DISASSOCIATE, + *PTDI_REQUEST_KERNEL_DISASSOCIATE; + +/* TdiAccept */ +typedef struct _TDI_REQUEST_KERNEL_ACCEPT +{ + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; + PTDI_CONNECTION_INFORMATION ReturnConnectionInformation; +} TDI_REQUEST_KERNEL_ACCEPT, *PTDI_REQUEST_KERNEL_ACCEPT; + +/* TdiReceive */ +typedef struct _TDI_REQUEST_KERNEL_RECEIVE +{ + ULONG ReceiveLength; + ULONG ReceiveFlags; +} TDI_REQUEST_KERNEL_RECEIVE, *PTDI_REQUEST_KERNEL_RECEIVE; + +/* TdiReceiveDatagram */ +typedef struct _TDI_REQUEST_KERNEL_RECEIVEDG +{ + ULONG ReceiveLength; + PTDI_CONNECTION_INFORMATION ReceiveDatagramInformation; + PTDI_CONNECTION_INFORMATION ReturnDatagramInformation; + ULONG ReceiveFlags; +} TDI_REQUEST_KERNEL_RECEIVEDG, *PTDI_REQUEST_KERNEL_RECEIVEDG; + +/* TdiSend */ +typedef struct _TDI_REQUEST_KERNEL_SEND +{ + ULONG SendLength; + ULONG SendFlags; +} TDI_REQUEST_KERNEL_SEND, *PTDI_REQUEST_KERNEL_SEND; + +/* TdiSendDatagram */ +typedef struct _TDI_REQUEST_KERNEL_SENDDG +{ + ULONG SendLength; + PTDI_CONNECTION_INFORMATION SendDatagramInformation; +} TDI_REQUEST_KERNEL_SENDDG, *PTDI_REQUEST_KERNEL_SENDDG; + +/* TdiSetEventHandler */ +typedef struct _TDI_REQUEST_KERNEL_SET_EVENT +{ + LONG EventType; + PVOID EventHandler; + PVOID EventContext; +} TDI_REQUEST_KERNEL_SET_EVENT, *PTDI_REQUEST_KERNEL_SET_EVENT; + +/* TdiQueryInformation */ +typedef struct _TDI_REQUEST_KERNEL_QUERY_INFO +{ + LONG QueryType; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; +} TDI_REQUEST_KERNEL_QUERY_INFORMATION, *PTDI_REQUEST_KERNEL_QUERY_INFORMATION; + +/* TdiSetInformation */ +typedef struct _TDI_REQUEST_KERNEL_SET_INFO +{ + LONG SetType; + PTDI_CONNECTION_INFORMATION RequestConnectionInformation; +} TDI_REQUEST_KERNEL_SET_INFORMATION, *PTDI_REQUEST_KERNEL_SET_INFORMATION; + + +/* Event types */ +#define TDI_EVENT_CONNECT 0 +#define TDI_EVENT_DISCONNECT 1 +#define TDI_EVENT_ERROR 2 +#define TDI_EVENT_RECEIVE 3 +#define TDI_EVENT_RECEIVE_DATAGRAM 4 +#define TDI_EVENT_RECEIVE_EXPEDITED 5 +#define TDI_EVENT_SEND_POSSIBLE 6 +#define TDI_EVENT_CHAINED_RECEIVE 7 +#define TDI_EVENT_CHAINED_RECEIVE_DATAGRAM 8 +#define TDI_EVENT_CHAINED_RECEIVE_EXPEDITED 9 + +typedef NTSTATUS (*PTDI_IND_CONNECT)( + IN PVOID TdiEventContext, + IN LONG RemoteAddressLength, + IN PVOID RemoteAddress, + IN LONG UserDataLength, + IN PVOID UserData, + IN LONG OptionsLength, + IN PVOID Options, + OUT CONNECTION_CONTEXT *ConnectionContext, + OUT PIRP *AcceptIrp); + +NTSTATUS STDCALL TdiDefaultConnectHandler( + IN PVOID TdiEventContext, + IN LONG RemoteAddressLength, + IN PVOID RemoteAddress, + IN LONG UserDataLength, + IN PVOID UserData, + IN LONG OptionsLength, + IN PVOID Options, + OUT CONNECTION_CONTEXT *ConnectionContext, + OUT PIRP *AcceptIrp); + +typedef NTSTATUS (*PTDI_IND_DISCONNECT)( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN LONG DisconnectDataLength, + IN PVOID DisconnectData, + IN LONG DisconnectInformationLength, + IN PVOID DisconnectInformation, + IN ULONG DisconnectFlags); + +NTSTATUS STDCALL TdiDefaultDisconnectHandler( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN LONG DisconnectDataLength, + IN PVOID DisconnectData, + IN LONG DisconnectInformationLength, + IN PVOID DisconnectInformation, + IN ULONG DisconnectFlags); + +typedef NTSTATUS (*PTDI_IND_ERROR)( + IN PVOID TdiEventContext, + IN NTSTATUS Status); + +NTSTATUS STDCALL TdiDefaultErrorHandler( + IN PVOID TdiEventContext, + IN NTSTATUS Status); + +typedef NTSTATUS (*PTDI_IND_RECEIVE)( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket); + +NTSTATUS STDCALL TdiDefaultReceiveHandler( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket); + +typedef NTSTATUS (*PTDI_IND_RECEIVE_DATAGRAM)( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket); + +NTSTATUS STDCALL TdiDefaultRcvDatagramHandler( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket); + +typedef NTSTATUS (*PTDI_IND_RECEIVE_EXPEDITED)( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket); + +NTSTATUS STDCALL TdiDefaultRcvExpeditedHandler( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG BytesIndicated, + IN ULONG BytesAvailable, + OUT ULONG *BytesTaken, + IN PVOID Tsdu, + OUT PIRP *IoRequestPacket); + +typedef NTSTATUS (*PTDI_IND_CHAINED_RECEIVE)( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor); + +NTSTATUS STDCALL TdiDefaultChainedReceiveHandler( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor); + +typedef NTSTATUS (*PTDI_IND_CHAINED_RECEIVE_DATAGRAM)( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG ReceiveDatagramLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor); + +NTSTATUS STDCALL TdiDefaultChainedRcvDatagramHandler( + IN PVOID TdiEventContext, + IN LONG SourceAddressLength, + IN PVOID SourceAddress, + IN LONG OptionsLength, + IN PVOID Options, + IN ULONG ReceiveDatagramFlags, + IN ULONG ReceiveDatagramLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor); + +typedef NTSTATUS (*PTDI_IND_CHAINED_RECEIVE_EXPEDITED)( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor); + +NTSTATUS STDCALL TdiDefaultChainedRcvExpeditedHandler( + IN PVOID TdiEventContext, + IN CONNECTION_CONTEXT ConnectionContext, + IN ULONG ReceiveFlags, + IN ULONG ReceiveLength, + IN ULONG StartingOffset, + IN PMDL Tsdu, + IN PVOID TsduDescriptor); + +typedef NTSTATUS (*PTDI_IND_SEND_POSSIBLE)( + IN PVOID TdiEventContext, + IN PVOID ConnectionContext, + IN ULONG BytesAvailable); + +NTSTATUS STDCALL TdiDefaultSendPossibleHandler( + IN PVOID TdiEventContext, + IN PVOID ConnectionContext, + IN ULONG BytesAvailable); + + + +/* Macros and functions to build IRPs */ + +#define TdiBuildBaseIrp( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, IrpSp, Minor) \ +{ \ + IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; \ + IrpSp->MinorFunction = (Minor); \ + IrpSp->DeviceObject = (DevObj); \ + IrpSp->FileObject = (FileObj); \ + \ + if (CompRoutine) \ + IoSetCompletionRoutine(Irp, CompRoutine, Contxt, TRUE, TRUE, TRUE) \ + else \ + IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE); \ +} + +/* + * VOID TdiBuildAccept( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PTDI_CONNECTION_INFORMATION RequestConnectionInfo, + * OUT PTDI_CONNECTION_INFORMATION ReturnConnectionInfo); + */ +#define TdiBuildAccept( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + RequestConnectionInfo, ReturnConnectionInfo) \ + { \ + PTDI_REQUEST_KERNEL_ACCEPT _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_ACCEPT); \ + \ + _Request = (PTDI_REQUEST_KERNEL_ACCEPT)&_IrpSp->Parameters; \ + _Request->RequestConnectionInformation = (RequestConnectionInfo); \ + _Request->ReturnConnectionInformation = (ReturnConnectionInfo); \ +} + +/* + * VOID TdiBuildAction( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PMDL MdlAddr); + */ +#define TdiBuildAction( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr) \ +{ \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_ACTION); \ + \ + (Irp)->MdlAddress = (MdlAddr); \ +} + +/* + * VOID TdiBuildAssociateAddress( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN HANDLE AddrHandle); + */ +#define TdiBuildAssociateAddress( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, AddrHandle) \ +{ \ + PTDI_REQUEST_KERNEL_ASSOCIATE _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_ASSOCIATE_ADDRESS); \ + \ + _Request = (PTDI_REQUEST_KERNEL_ASSOCIATE)&_IrpSp->Parameters; \ + _Request->AddressHandle = (HANDLE)(AddrHandle); \ +} + +/* + * VOID TdiBuildConnect( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PLARGE_INTEGER Time, + * IN PTDI_CONNECTION_INFORMATION RequestConnectionInfo, + * OUT PTDI_CONNECTION_INFORMATION ReturnConnectionInfo); + */ +#define TdiBuildConnect( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + Time, RequestConnectionInfo, ReturnConnectionInfo) \ +{ \ + PTDI_REQUEST_KERNEL _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_CONNECT); \ + \ + _Request = (PTDI_REQUEST_KERNEL)&_IrpSp->Parameters; \ + _Request->RequestConnectionInformation = (RequestConnectionInfo); \ + _Request->ReturnConnectionInformation = (ReturnConnectionInfo); \ + _Request->RequestSpecific = (PVOID)(Time); \ +} + +/* + * VOID TdiBuildDisassociateAddress( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt); + */ +#define TdiBuildDisassociateAddress( \ + Irp, DevObj, FileObj, CompRoutine, Contxt) \ +{ \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_DISASSOCIATE_ADDRESS); \ +} + +/* + * VOID TdiBuildDisconnect( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PLARGE_INTEGER Time, + * IN PULONG Flags, + * IN PTDI_CONNECTION_INFORMATION RequestConnectionInfo, + * OUT PTDI_CONNECTION_INFORMATION ReturnConnectionInfo); + */ +#define TdiBuildDisconnect( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, Time, \ + Flags, RequestConnectionInfo, ReturnConnectionInfo) \ +{ \ + PTDI_REQUEST_KERNEL _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_DISCONNECT); \ + \ + _Request = (PTDI_REQUEST_KERNEL)&_IrpSp->Parameters; \ + _Request->RequestConnectionInformation = (RequestConnectionInfo); \ + _Request->ReturnConnectionInformation = (ReturnConnectionInfo); \ + _Request->RequestSpecific = (PVOID)(Time); \ + _Request->RequestFlags = (Flags); \ +} + +/* + * PIRP TdiBuildInternalDeviceControlIrp( + * IN CCHAR IrpSubFunction, + * IN PDEVICE_OBJECT DeviceObject, + * IN PFILE_OBJECT FileObject, + * IN PKEVENT Event, + * IN PIO_STATUS_BLOCK IoStatusBlock); + */ +#define TdiBuildInternalDeviceControlIrp( \ + IrpSubFunction, DeviceObject, \ + FileObject, Event, IoStatusBlock) \ + IoBuildDeviceIoControlRequest( \ + 0x00000003, DeviceObject, \ + NULL, 0, NULL, 0, \ + TRUE, Event, IoStatusBlock) + +/* + * VOID TdiBuildListen( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN ULONG Flags, + * IN PTDI_CONNECTION_INFORMATION RequestConnectionInfo, + * OUT PTDI_CONNECTION_INFORMATION ReturnConnectionInfo); + */ +#define TdiBuildListen( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + Flags, RequestConnectionInfo, ReturnConnectionInfo) \ +{ \ + PTDI_REQUEST_KERNEL _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_LISTEN); \ + \ + _Request = (PTDI_REQUEST_KERNEL)&_IrpSp->Parameters; \ + _Request->RequestConnectionInformation = (RequestConnectionInfo); \ + _Request->ReturnConnectionInformation = (ReturnConnectionInfo); \ + _Request->RequestFlags = (Flags); \ +} + +VOID STDCALL TdiBuildNetbiosAddress( + IN PUCHAR NetbiosName, + IN BOOLEAN IsGroupName, + IN OUT PTA_NETBIOS_ADDRESS NetworkName); + +NTSTATUS STDCALL TdiBuildNetbiosAddressEa( + IN PUCHAR Buffer, + IN BOOLEAN IsGroupName, + IN PUCHAR NetbiosName); + +/* + * VOID TdiBuildQueryInformation( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN UINT QType, + * IN PMDL MdlAddr); + */ +#define TdiBuildQueryInformation( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, QType, MdlAddr) \ +{ \ + PTDI_REQUEST_KERNEL_QUERY_INFORMATION _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_QUERY_INFORMATION); \ + \ + _Request = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&_IrpSp->Parameters; \ + _Request->RequestConnectionInformation = NULL; \ + _Request->QueryType = (ULONG)(QType); \ + (Irp)->MdlAddress = (MdlAddr); \ +} + +/* + * VOID TdiBuildReceive( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PMDL MdlAddr, + * IN ULONG InFlags, + * IN ULONG ReceiveLen); + */ +#define TdiBuildReceive( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + MdlAddr, InFlags, ReceiveLen) \ +{ \ + PTDI_REQUEST_KERNEL_RECEIVE _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_RECEIVE); \ + \ + _Request = (PTDI_REQUEST_KERNEL_RECEIVE)&_IrpSp->Parameters; \ + _Request->ReceiveFlags = (InFlags); \ + _Request->ReceiveLength = (ReceiveLen); \ + (Irp)->MdlAddress = (MdlAddr); \ +} + +/* + * VOID TdiBuildReceiveDatagram( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PMDL MdlAddr, + * IN ULONG ReceiveLen, + * IN PTDI_CONNECTION_INFORMATION ReceiveDatagramInfo, + * OUT PTDI_CONNECTION_INFORMATION ReturnInfo, + * ULONG InFlags); + */ +#define TdiBuildReceiveDatagram( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, MdlAddr, \ + ReceiveLen, ReceiveDatagramInfo, ReturnInfo, InFlags) \ +{ \ + PTDI_REQUEST_KERNEL_RECEIVEDG _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_RECEIVE_DATAGRAM); \ + \ + _Request = (PTDI_REQUEST_KERNEL_RECEIVEDG)&_IrpSp->Parameters; \ + _Request->ReceiveDatagramInformation = (ReceiveDatagramInfo); \ + _Request->ReturnDatagramInformation = (ReturnInfo); \ + _Request->ReceiveLength = (ReceiveLen); \ + _Request->ReceiveFlags = (InFlags); \ + (Irp)->MdlAddress = (MdlAddr); \ +} + +/* + * VOID TdiBuildSend( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PMDL MdlAddr, + * IN ULONG InFlags, + * IN ULONG SendLen); + */ +#define TdiBuildSend( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + MdlAddr, InFlags, SendLen) \ +{ \ + PTDI_REQUEST_KERNEL_SEND _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_SEND); \ + \ + _Request = (PTDI_REQUEST_KERNEL_SEND)&_IrpSp->Parameters; \ + _Request->SendFlags = (InFlags); \ + _Request->SendLength = (SendLen); \ + (Irp)->MdlAddress = (MdlAddr); \ +} + +/* + * VOID TdiBuildSendDatagram( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN PMDL MdlAddr, + * IN ULONG SendLen, + * IN PTDI_CONNECTION_INFORMATION SendDatagramInfo); + */ +#define TdiBuildSendDatagram( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + MdlAddr, SendLen, SendDatagramInfo) \ +{ \ + PTDI_REQUEST_KERNEL_SENDDG _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_SEND_DATAGRAM); \ + \ + _Request = (PTDI_REQUEST_KERNEL_SENDDG)&_IrpSp->Parameters; \ + _Request->SendDatagramInformation = (SendDatagramInfo); \ + _Request->SendLength = (SendLen); \ + (Irp)->MdlAddress = (MdlAddr); \ +} + +/* + * VOID TdiBuildSetEventHandler( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN INT InEventType, + * IN PVOID InEventHandler, + * IN PVOID InEventContext); + */ +#define TdiBuildSetEventHandler( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, \ + InEventType, InEventHandler, InEventContext) \ +{ \ + PTDI_REQUEST_KERNEL_SET_EVENT _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_SET_EVENT_HANDLER); \ + \ + _Request = (PTDI_REQUEST_KERNEL_SET_EVENT)&_IrpSp->Parameters; \ + _Request->EventType = (InEventType); \ + _Request->EventHandler = (PVOID)(InEventHandler); \ + _Request->EventContext = (PVOID)(InEventContext); \ +} + +/* + * VOID TdiBuildSetInformation( + * IN PIRP Irp, + * IN PDEVICE_OBJECT DevObj, + * IN PFILE_OBJECT FileObj, + * IN PVOID CompRoutine, + * IN PVOID Contxt, + * IN UINT SType, + * IN PMDL MdlAddr); + */ +#define TdiBuildSetInformation( \ + Irp, DevObj, FileObj, CompRoutine, Contxt, SType, MdlAddr) \ +{ \ + PTDI_REQUEST_KERNEL_SET_INFORMATION _Request; \ + PIO_STACK_LOCATION _IrpSp; \ + \ + _IrpSp = IoGetNextIrpStackLocation(Irp); \ + \ + TdiBuildBaseIrp(Irp, DevObj, FileObj, CompRoutine, \ + Contxt, _IrpSp, TDI_SET_INFORMATION); \ + \ + _Request = (PTDI_REQUEST_KERNEL_SET_INFORMATION)&_IrpSp->Parameters; \ + _Request->RequestConnectionInformation = NULL; \ + _Request->SetType = (ULONG)(SType); \ + (Irp)->MdlAddress = (MdlAddr); \ +} + + + +/* TDI functions */ + +/* + * VOID TdiCompleteRequest( + * IN PIRP Irp, + * IN NTSTATUS Status); + */ +#define TdiCompleteRequest(Irp, Status) \ +{ \ + (Irp)->IoStatus.Status = (Status); \ + IoCompleteRequest((Irp), IO_NETWORK_INCREMENT); \ +} + +NTSTATUS STDCALL TdiCopyBufferToMdl( + IN PVOID SourceBuffer, + IN ULONG SourceOffset, + IN ULONG SourceBytesToCopy, + IN PMDL DestinationMdlChain, + IN ULONG DestinationOffset, + IN PULONG BytesCopied); + +/* + * VOID TdiCopyLookaheadData( + * IN PVOID Destination, + * IN PVOID Source, + * IN ULONG Length, + * IN ULONG ReceiveFlags); + */ +#define TdiCopyLookaheadData(Destination, Source, Length, ReceiveFlags) \ + RtlCopyMemory(Destination, Source, Length) + +NTSTATUS STDCALL TdiCopyMdlToBuffer( + IN PMDL SourceMdlChain, + IN ULONG SourceOffset, + IN PVOID DestinationBuffer, + IN ULONG DestinationOffset, + IN ULONG DestinationBufferSize, + OUT PULONG BytesCopied); + +VOID STDCALL TdiMapBuffer( + IN PMDL MdlChain); + +NTSTATUS STDCALL TdiMapUserRequest( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp); + +VOID STDCALL TdiReturnChainedReceives( + IN PVOID *TsduDescriptors, + IN ULONG NumberOfTsdus); + +VOID STDCALL TdiUnmapBuffer( + IN PMDL MdlChain); + +#endif /* __TDIKRNL_H */ + +/* EOF */ diff --git a/include/ntddk.h b/include/ntddk.h new file mode 100644 index 0000000..4fed7b0 --- /dev/null +++ b/include/ntddk.h @@ -0,0 +1,5 @@ + +/* (RJJ) some programs look for the DDK header here... */ + +#include + diff --git a/include/ntdll/.cvsignore b/include/ntdll/.cvsignore new file mode 100644 index 0000000..342f4ca --- /dev/null +++ b/include/ntdll/.cvsignore @@ -0,0 +1 @@ +napi.h diff --git a/include/ntdll/base.h b/include/ntdll/base.h new file mode 100644 index 0000000..8d45888 --- /dev/null +++ b/include/ntdll/base.h @@ -0,0 +1 @@ +#define NTDLL_BASE (0x77f60000) diff --git a/include/ntdll/csr.h b/include/ntdll/csr.h new file mode 100644 index 0000000..83645fa --- /dev/null +++ b/include/ntdll/csr.h @@ -0,0 +1,38 @@ +/* $Id$ + * + */ + +#ifndef __INCLUDE_NTDLL_CSR_H +#define __INCLUDE_NTDLL_CSR_H + +#include + +extern HANDLE WindowsApiPort; /* lpc.c */ + + +NTSTATUS STDCALL CsrClientConnectToServer(VOID); +NTSTATUS STDCALL CsrClientCallServer(PCSRSS_API_REQUEST Request, + PCSRSS_API_REPLY Reply OPTIONAL, + ULONG Length, + ULONG ReplyLength); +NTSTATUS STDCALL CsrIdentifyAlertableThread(VOID); +NTSTATUS STDCALL CsrNewThread(VOID); +NTSTATUS STDCALL CsrSetPriorityClass(HANDLE Process, + PULONG PriorityClass); +VOID STDCALL CsrProbeForRead(IN CONST PVOID Address, + IN ULONG Length, + IN ULONG Alignment); +VOID STDCALL CsrProbeForWrite(IN CONST PVOID Address, + IN ULONG Length, + IN ULONG Alignment); +NTSTATUS STDCALL +CsrCaptureParameterBuffer(PVOID ParameterBuffer, + ULONG ParameterBufferSize, + PVOID* ClientAddress, + PVOID* ServerAddress); +NTSTATUS STDCALL +CsrReleaseParameterBuffer(PVOID ClientAddress); + +#endif /* __INCLUDE_NTDLL_CSR_H */ + +/* EOF */ diff --git a/include/ntdll/dbg.h b/include/ntdll/dbg.h new file mode 100644 index 0000000..3ac7a75 --- /dev/null +++ b/include/ntdll/dbg.h @@ -0,0 +1,39 @@ +/* $Id$ + * + */ + +#ifndef __INCLUDE_NTDLL_DBG_H +#define __INCLUDE_NTDLL_DBG_H + +NTSTATUS +STDCALL +DbgSsInitialize ( + HANDLE ReplyPort, + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3 + ); + +NTSTATUS +STDCALL +DbgUiConnectToDbg ( + VOID + ); + +NTSTATUS +STDCALL +DbgUiContinue ( + PCLIENT_ID ClientId, + ULONG ContinueStatus + ); + +NTSTATUS +STDCALL +DbgUiWaitStateChange ( + ULONG Unknown1, + ULONG Unknown2 + ); + +#endif /* __INCLUDE_NTDLL_DBG_H */ + +/* EOF */ diff --git a/include/ntdll/ldr.h b/include/ntdll/ldr.h new file mode 100644 index 0000000..85c0752 --- /dev/null +++ b/include/ntdll/ldr.h @@ -0,0 +1,135 @@ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_LDR_H +#define __NTOSKRNL_INCLUDE_INTERNAL_LDR_H + +#include +#include + +typedef NTSTATUS STDCALL (*PEPFUNC)(PPEB); + +/* Type for a DLL's entry point */ +typedef BOOL STDCALL +(* PDLLMAIN_FUNC)(HANDLE hInst, + ULONG ul_reason_for_call, + LPVOID lpReserved); + +typedef struct _LDR_MODULE +{ + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; // not used + LIST_ENTRY InInitializationOrderModuleList; // not used + PVOID BaseAddress; + ULONG EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + HANDLE SectionHandle; + ULONG CheckSum; + ULONG TimeDateStamp; +#ifdef KDBG + IMAGE_SYMBOL_INFO SymbolInfo; +#endif /* KDBG */ +} LDR_MODULE, *PLDR_MODULE; + +typedef struct _LDR_SYMBOL_INFO { + PLDR_MODULE ModuleObject; + ULONG_PTR ImageBase; + PVOID SymbolsBuffer; + ULONG SymbolsBufferLength; + PVOID SymbolStringsBuffer; + ULONG SymbolStringsBufferLength; +} LDR_SYMBOL_INFO, *PLDR_SYMBOL_INFO; + + +#define RVA(m, b) ((ULONG)b + m) + + +typedef struct _MODULE_ENTRY +{ + ULONG Unknown0; + ULONG Unknown1; + PVOID BaseAddress; + ULONG SizeOfImage; + ULONG Flags; + USHORT Unknown2; + USHORT Unknown3; + SHORT LoadCount; + USHORT PathLength; + CHAR ModuleName[256]; +} MODULE_ENTRY, *PMODULE_ENTRY; + +typedef struct _MODULE_INFORMATION +{ + ULONG ModuleCount; + MODULE_ENTRY ModuleEntry[1]; +} MODULE_INFORMATION, *PMODULE_INFORMATION; + +#ifdef KDBG + +VOID +LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule); + +#endif + +PEPFUNC LdrPEStartup (PVOID ImageBase, + HANDLE SectionHandle, + PLDR_MODULE* Module, + PWSTR FullDosName); +NTSTATUS LdrMapSections(HANDLE ProcessHandle, + PVOID ImageBase, + HANDLE SectionHandle, + PIMAGE_NT_HEADERS NTHeaders); +NTSTATUS LdrMapNTDllForProcess(HANDLE ProcessHandle, + PHANDLE NTDllSectionHandle); + + +NTSTATUS STDCALL +LdrDisableThreadCalloutsForDll(IN PVOID BaseAddress); + +NTSTATUS STDCALL +LdrGetDllHandle(IN ULONG Unknown1, + IN ULONG Unknown2, + IN PUNICODE_STRING DllName, + OUT PVOID *BaseAddress); + +NTSTATUS STDCALL +LdrFindEntryForAddress(PVOID Address, + PLDR_MODULE *Module); + +NTSTATUS STDCALL +LdrGetProcedureAddress(IN PVOID BaseAddress, + IN PANSI_STRING Name, + IN ULONG Ordinal, + OUT PVOID *ProcedureAddress); + +VOID STDCALL +LdrInitializeThunk(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4); + +NTSTATUS STDCALL +LdrLoadDll(IN PWSTR SearchPath OPTIONAL, + IN ULONG LoadFlags, + IN PUNICODE_STRING Name, + OUT PVOID *BaseAddress OPTIONAL); + +NTSTATUS STDCALL +LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTIONAL, + IN ULONG Size OPTIONAL, + OUT PULONG ReturnedSize); + +NTSTATUS STDCALL +LdrShutdownProcess(VOID); + +NTSTATUS STDCALL +LdrShutdownThread(VOID); + +NTSTATUS STDCALL +LdrUnloadDll(IN PVOID BaseAddress); + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_LDR_H */ + +/* EOF */ diff --git a/include/ntdll/ntdll.h b/include/ntdll/ntdll.h new file mode 100644 index 0000000..83eb715 --- /dev/null +++ b/include/ntdll/ntdll.h @@ -0,0 +1,28 @@ + +#include + +#define UNIMPLEMENTED DbgPrint("%s in %s:%d is unimplemented\n",__FUNCTION__,__FILE__,__LINE__); + +#ifndef NASSERT +#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); for(;;);} +#else +#define assert(x) +#endif + +#ifdef NDEBUG +#define DPRINT(args...) +#define CHECKPOINT +#else +#define DPRINT(args...) do { DbgPrint("(NTDLL:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT do { DbgPrint("(NTDLL:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0); +#endif + +#define DPRINT1(args...) do { DbgPrint("(NTDLL:%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT1 do { DbgPrint("(NTDLL:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0); + +#define ROUNDUP(a,b) ((((a)+(b)-1)/(b))*(b)) +#define ROUNDDOWN(a,b) (((a)/(b))*(b)) + +#define MAGIC(c1,c2,c3,c4) ((c1) + ((c2)<<8) + ((c3)<<16) + ((c4)<<24)) + +#define MAGIC_HEAP MAGIC( 'H','E','A','P' ) diff --git a/include/ntdll/pagesize.h b/include/ntdll/pagesize.h new file mode 100644 index 0000000..90eb8fc --- /dev/null +++ b/include/ntdll/pagesize.h @@ -0,0 +1,7 @@ +/* + * + */ + +#ifdef i386 +#define PAGE_SIZE (4096) +#endif diff --git a/include/ntdll/registry.h b/include/ntdll/registry.h new file mode 100644 index 0000000..33e9021 --- /dev/null +++ b/include/ntdll/registry.h @@ -0,0 +1,6 @@ + +NTSTATUS +RtlpGetRegistryHandle(ULONG RelativeTo, + PWSTR Path, + BOOLEAN Create, + PHANDLE KeyHandle); diff --git a/include/ntdll/rtl.h b/include/ntdll/rtl.h new file mode 100644 index 0000000..97c0da2 --- /dev/null +++ b/include/ntdll/rtl.h @@ -0,0 +1,616 @@ +/* $Id$ + * + */ + +#ifndef __INCLUDE_NTDLL_RTL_H +#define __INCLUDE_NTDLL_RTL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _DEBUG_BUFFER +{ + HANDLE SectionHandle; + PVOID SectionBase; + PVOID RemoteSectionBase; + ULONG SectionBaseDelta; + HANDLE EventPairHandle; + ULONG Unknown[2]; + HANDLE RemoteThreadHandle; + ULONG InfoClassMask; + ULONG SizeOfInfo; + ULONG AllocatedSize; + ULONG SectionSize; + PVOID ModuleInformation; + PVOID BackTraceInformation; + PVOID HeapInformation; + PVOID LockInformation; + PVOID Reserved[8]; +} DEBUG_BUFFER, *PDEBUG_BUFFER; + +typedef struct _CRITICAL_SECTION_DEBUG { + WORD Type; + WORD CreatorBackTraceIndex; + struct _CRITICAL_SECTION *CriticalSection; + LIST_ENTRY ProcessLocksList; + DWORD EntryCount; + DWORD ContentionCount; + DWORD Depth; + PVOID OwnerBackTrace[ 5 ]; +} CRITICAL_SECTION_DEBUG, *PCRITICAL_SECTION_DEBUG; + +typedef struct _CRITICAL_SECTION { + PCRITICAL_SECTION_DEBUG DebugInfo; + LONG LockCount; + LONG RecursionCount; + HANDLE OwningThread; + HANDLE LockSemaphore; + DWORD Reserved; +} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; + +typedef struct _RTL_PROCESS_INFO +{ + ULONG Size; + HANDLE ProcessHandle; + HANDLE ThreadHandle; + CLIENT_ID ClientId; + SECTION_IMAGE_INFORMATION ImageInfo; +} RTL_PROCESS_INFO, *PRTL_PROCESS_INFO; + +typedef struct _RTL_RESOURCE +{ + CRITICAL_SECTION Lock; + HANDLE SharedSemaphore; + ULONG SharedWaiters; + HANDLE ExclusiveSemaphore; + ULONG ExclusiveWaiters; + LONG NumberActive; + HANDLE OwningThread; + ULONG TimeoutBoost; /* ?? */ + PVOID DebugInfo; /* ?? */ +} RTL_RESOURCE, *PRTL_RESOURCE; + +typedef struct _RTL_HANDLE +{ + struct _RTL_HANDLE *Next; /* pointer to next free handle */ +} RTL_HANDLE, *PRTL_HANDLE; + +typedef struct _RTL_HANDLE_TABLE +{ + ULONG TableSize; /* maximum number of handles */ + ULONG HandleSize; /* size of handle in bytes */ + PRTL_HANDLE Handles; /* pointer to handle array */ + PRTL_HANDLE Limit; /* limit of pointers */ + PRTL_HANDLE FirstFree; /* pointer to first free handle */ + PRTL_HANDLE LastUsed; /* pointer to last allocated handle */ +} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE; + + +#define HEAP_BASE (0xa0000000) + +/* RtlQueryProcessDebugInformation */ +#define PDI_MODULES 0x01 /* The loaded modules of the process */ +#define PDI_BACKTRACE 0x02 /* The heap stack back traces */ +#define PDI_HEAPS 0x04 /* The heaps of the process */ +#define PDI_HEAP_TAGS 0x08 /* The heap tags */ +#define PDI_HEAP_BLOCKS 0x10 /* The heap blocks */ +#define PDI_LOCKS 0x20 /* The locks created by the process */ + +VOID +STDCALL +RtlDeleteCriticalSection ( + PCRITICAL_SECTION CriticalSection + ); + +VOID +STDCALL +RtlEnterCriticalSection ( + PCRITICAL_SECTION CriticalSection + ); + +NTSTATUS +STDCALL +RtlInitializeCriticalSection ( + PCRITICAL_SECTION CriticalSection + ); + +VOID +STDCALL +RtlLeaveCriticalSection ( + PCRITICAL_SECTION CriticalSection + ); + +BOOLEAN +STDCALL +RtlTryEnterCriticalSection ( + PCRITICAL_SECTION CriticalSection + ); + +DWORD +STDCALL +RtlCompactHeap ( + HANDLE heap, + DWORD flags + ); + +PDEBUG_BUFFER STDCALL +RtlCreateQueryDebugBuffer(IN ULONG Size, + IN BOOLEAN EventPair); + +NTSTATUS STDCALL +RtlDestroyQueryDebugBuffer(IN PDEBUG_BUFFER DebugBuffer); + +BOOLEAN +STDCALL +RtlEqualComputerName ( + IN PUNICODE_STRING ComputerName1, + IN PUNICODE_STRING ComputerName2 + ); + +BOOLEAN +STDCALL +RtlEqualDomainName ( + IN PUNICODE_STRING DomainName1, + IN PUNICODE_STRING DomainName2 + ); + +VOID +STDCALL +RtlEraseUnicodeString ( + IN PUNICODE_STRING String + ); + +NTSTATUS +STDCALL +RtlLargeIntegerToChar ( + IN PLARGE_INTEGER Value, + IN ULONG Base, + IN ULONG Length, + IN OUT PCHAR String + ); + + +/* Path functions */ + +ULONG +STDCALL +RtlDetermineDosPathNameType_U ( + PWSTR Path + ); + +BOOLEAN +STDCALL +RtlDoesFileExists_U ( + PWSTR FileName + ); + +BOOLEAN +STDCALL +RtlDosPathNameToNtPathName_U ( + PWSTR dosname, + PUNICODE_STRING ntname, + PWSTR *shortname, + PCURDIR nah + ); + +ULONG +STDCALL +RtlDosSearchPath_U ( + WCHAR *sp, + WCHAR *name, + WCHAR *ext, + ULONG buf_sz, + WCHAR *buffer, + WCHAR **shortname + ); + +ULONG +STDCALL +RtlGetCurrentDirectory_U ( + ULONG MaximumLength, + PWSTR Buffer + ); + +ULONG +STDCALL +RtlGetFullPathName_U ( + WCHAR *dosname, + ULONG size, + WCHAR *buf, + WCHAR **shortname + ); + +ULONG +STDCALL +RtlGetLongestNtPathLength ( + VOID + ); + +ULONG STDCALL RtlGetNtGlobalFlags(VOID); + +BOOLEAN STDCALL RtlGetNtProductType(PNT_PRODUCT_TYPE ProductType); + +ULONG +STDCALL +RtlGetProcessHeaps ( + ULONG HeapCount, + HANDLE *HeapArray + ); + +ULONG +STDCALL +RtlIsDosDeviceName_U ( + PWSTR DeviceName + ); + +NTSTATUS +STDCALL +RtlSetCurrentDirectory_U ( + PUNICODE_STRING name + ); + +/* Environment functions */ +VOID +STDCALL +RtlAcquirePebLock ( + VOID + ); + +VOID +STDCALL +RtlReleasePebLock ( + VOID + ); + +NTSTATUS +STDCALL +RtlCreateEnvironment ( + BOOLEAN Inherit, + PWSTR *Environment + ); + +VOID +STDCALL +RtlDestroyEnvironment ( + PWSTR Environment + ); + +NTSTATUS +STDCALL +RtlExpandEnvironmentStrings_U ( + PWSTR Environment, + PUNICODE_STRING Source, + PUNICODE_STRING Destination, + PULONG Length + ); + +NTSTATUS +STDCALL +RtlQueryEnvironmentVariable_U ( + PWSTR Environment, + PUNICODE_STRING Name, + PUNICODE_STRING Value + ); + +NTSTATUS STDCALL +RtlQueryProcessDebugInformation(IN ULONG ProcessId, + IN ULONG DebugInfoClassMask, + IN OUT PDEBUG_BUFFER DebugBuffer); + +VOID +STDCALL +RtlSetCurrentEnvironment ( + PWSTR NewEnvironment, + PWSTR *OldEnvironment + ); + +NTSTATUS +STDCALL +RtlSetEnvironmentVariable ( + PWSTR *Environment, + PUNICODE_STRING Name, + PUNICODE_STRING Value + ); + +NTSTATUS +STDCALL +RtlCreateUserThread ( + IN HANDLE ProcessHandle, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN BOOLEAN CreateSuspended, + IN LONG StackZeroBits, + IN OUT PULONG StackReserve, + IN OUT PULONG StackCommit, + IN PTHREAD_START_ROUTINE StartAddress, + IN PVOID Parameter, + IN OUT PHANDLE ThreadHandle, + IN OUT PCLIENT_ID ClientId + ); + +NTSTATUS +STDCALL +RtlFreeUserThreadStack ( + IN HANDLE ProcessHandle, + IN HANDLE ThreadHandle + ); + +NTSTATUS +STDCALL +RtlCreateUserProcess ( + IN PUNICODE_STRING ImageFileName, + IN ULONG Attributes, + IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + IN PSECURITY_DESCRIPTOR ProcessSecutityDescriptor OPTIONAL, + IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, + IN HANDLE ParentProcess OPTIONAL, + IN BOOLEAN CurrentDirectory, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL, + OUT PRTL_PROCESS_INFO ProcessInfo + ); + +NTSTATUS +STDCALL +RtlCreateProcessParameters ( + OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, + IN PUNICODE_STRING ImagePathName OPTIONAL, + IN PUNICODE_STRING DllPath OPTIONAL, + IN PUNICODE_STRING CurrentDirectory OPTIONAL, + IN PUNICODE_STRING CommandLine OPTIONAL, + IN PWSTR Environment OPTIONAL, + IN PUNICODE_STRING WindowTitle OPTIONAL, + IN PUNICODE_STRING DesktopInfo OPTIONAL, + IN PUNICODE_STRING ShellInfo OPTIONAL, + IN PUNICODE_STRING RuntimeInfo OPTIONAL + ); + +PRTL_USER_PROCESS_PARAMETERS +STDCALL +RtlDeNormalizeProcessParams ( + IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +VOID +STDCALL +RtlDestroyProcessParameters ( + IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +PRTL_USER_PROCESS_PARAMETERS +STDCALL +RtlNormalizeProcessParams ( + IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters + ); + +NTSTATUS +STDCALL +RtlLocalTimeToSystemTime ( + PLARGE_INTEGER LocalTime, + PLARGE_INTEGER SystemTime + ); + +NTSTATUS +STDCALL +RtlSystemTimeToLocalTime ( + PLARGE_INTEGER SystemTime, + PLARGE_INTEGER LocalTime + ); + +VOID STDCALL +RtlTimeToElapsedTimeFields(IN PLARGE_INTEGER Time, + OUT PTIME_FIELDS TimeFields); + +VOID +STDCALL +RtlRaiseStatus ( + IN NTSTATUS Status + ); + + +/* resource functions */ + +BOOLEAN +STDCALL +RtlAcquireResourceExclusive ( + IN PRTL_RESOURCE Resource, + IN BOOLEAN Wait + ); + +BOOLEAN +STDCALL +RtlAcquireResourceShared ( + IN PRTL_RESOURCE Resource, + IN BOOLEAN Wait + ); + +VOID +STDCALL +RtlConvertExclusiveToShared ( + IN PRTL_RESOURCE Resource + ); + +VOID +STDCALL +RtlConvertSharedToExclusive ( + IN PRTL_RESOURCE Resource + ); + +VOID +STDCALL +RtlDeleteResource ( + IN PRTL_RESOURCE Resource + ); + +VOID +STDCALL +RtlDumpResource ( + IN PRTL_RESOURCE Resource + ); + +VOID +STDCALL +RtlInitializeResource ( + IN PRTL_RESOURCE Resource + ); + +VOID +STDCALL +RtlReleaseResource ( + IN PRTL_RESOURCE Resource + ); + +/* handle table functions */ + +PRTL_HANDLE +STDCALL +RtlAllocateHandle ( + IN PRTL_HANDLE_TABLE HandleTable, + IN OUT PULONG Index + ); + +VOID +STDCALL +RtlDestroyHandleTable ( + IN PRTL_HANDLE_TABLE HandleTable + ); + +BOOLEAN +STDCALL +RtlFreeHandle ( + IN PRTL_HANDLE_TABLE HandleTable, + IN PRTL_HANDLE Handle + ); + +VOID +STDCALL +RtlInitializeHandleTable ( + IN ULONG TableSize, + IN ULONG HandleSize, + IN PRTL_HANDLE_TABLE HandleTable + ); + +BOOLEAN +STDCALL +RtlIsValidHandle ( + IN PRTL_HANDLE_TABLE HandleTable, + IN PRTL_HANDLE Handle + ); + +BOOLEAN +STDCALL +RtlIsValidIndexHandle ( + IN PRTL_HANDLE_TABLE HandleTable, + IN OUT PRTL_HANDLE *Handle, + IN ULONG Index + ); + +NTSTATUS +STDCALL +RtlImpersonateSelf ( + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel + ); + +NTSTATUS +STDCALL +RtlpNtCreateKey ( + OUT HANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Unused1, + OUT PULONG Disposition, + IN ULONG Unused2 + ); + +NTSTATUS +STDCALL +RtlpNtEnumerateSubKey ( + IN HANDLE KeyHandle, + OUT PUNICODE_STRING SubKeyName, + IN ULONG Index, + IN ULONG Unused + ); + +NTSTATUS +STDCALL +RtlpNtMakeTemporaryKey ( + IN HANDLE KeyHandle + ); + +NTSTATUS +STDCALL +RtlpNtOpenKey ( + OUT HANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Unused + ); + +NTSTATUS +STDCALL +RtlpNtQueryValueKey ( + IN HANDLE KeyHandle, + OUT PULONG Type OPTIONAL, + OUT PVOID Data OPTIONAL, + IN OUT PULONG DataLength OPTIONAL, + IN ULONG Unused + ); + +NTSTATUS +STDCALL +RtlpNtSetValueKey ( + IN HANDLE KeyHandle, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataLength + ); + +#ifndef __NTDRIVER__ +LONG +STDCALL +InterlockedIncrement ( + PLONG Addend + ); + +LONG +STDCALL +InterlockedDecrement ( + PLONG lpAddend + ); + +LONG +STDCALL +InterlockedExchange ( + PLONG Target, + LONG Value + ); + +PVOID +STDCALL +InterlockedCompareExchange ( + PVOID *Destination, + PVOID Exchange, + PVOID Comperand + ); + +LONG +STDCALL +InterlockedExchangeAdd ( + PLONG Addend, + LONG Increment + ); + + +#endif /* __NTDRIVER__ */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __INCLUDE_NTDLL_RTL_H */ + +/* EOF */ diff --git a/include/ntdll/trace.h b/include/ntdll/trace.h new file mode 100644 index 0000000..54f4d0d --- /dev/null +++ b/include/ntdll/trace.h @@ -0,0 +1,18 @@ +#ifndef __INCLUDE_NTDLL_TRACE_H +#define __INCLUDE_NTDLL_TRACE_H + +typedef struct _NTDLL_TRACE_TABLE +{ + CHAR Flags[4096]; +} NTDLL_TABLE_TABLE, *PNTDLL_TABLE_TRACE; + +#define TRACE_NTDLL (1) +#define TRACE_KERNEL32 (2) +#define TRACE_CRTDLL (3) + +VOID +RtlPrintTrace(ULONG Flag, PCH Format, ...); + +#define TPRINTF(F, X...) RtlPrintTrace(F, ## X) + +#endif /* __INCLUDE_NTDLL_TRACE_H */ diff --git a/include/ntos.h b/include/ntos.h new file mode 100644 index 0000000..25a6af8 --- /dev/null +++ b/include/ntos.h @@ -0,0 +1,75 @@ +#ifndef _NTOS_H +#define _NTOS_H +/* $Id$ */ + +#if defined(NTOS_MODE_USER) +// include windows.h before ntddk.h to get user mode prototype for InterlockedXxx functions +#include +#include +#include "ntos/types.h" +#include "ntos/cdrom.h" +#include "ntos/console.h" +#include "ntos/disk.h" +#include "ntos/except.h" +#include "ntos/file.h" +#include "ntos/gditypes.h" +#include "ntos/heap.h" +#include "ntos/kdbgsyms.h" +#include "ntos/keyboard.h" +#include "ntos/minmax.h" +#include "ntos/mm.h" +#include "ntos/ntdef.h" +#include "ntos/port.h" +#include "ntos/ps.h" +#include "ntos/registry.h" +#include "ntos/security.h" +#include "ntos/synch.h" +#include "ntos/time.h" +#include "napi/i386/segment.h" +#include "napi/types.h" +#include "napi/core.h" +#include "napi/dbg.h" +#include "napi/lpc.h" +#include "napi/npipe.h" +#include "napi/shared_data.h" +#include "napi/win32.h" +#include "ntdll/csr.h" +#include "ntdll/dbg.h" +#include "ntdll/ldr.h" +#include "ntdll/registry.h" +#include "ntdll/rtl.h" +#include "ntdll/trace.h" +#include "kernel32/error.h" +#else // Assume kernel mode +#include +#include +#include "ntos/types.h" +#include "ntos/cdrom.h" +#include "ntos/console.h" +#include "ntos/disk.h" +#include "ntos/except.h" +#include "ntos/file.h" +#include "ntos/gditypes.h" +#include "ntos/heap.h" +#include "ntos/kdbgsyms.h" +#include "ntos/keyboard.h" +#include "ntos/minmax.h" +#include "ntos/mm.h" +#include "ntos/ntdef.h" +#include "ntos/port.h" +#include "ntos/ps.h" +#include "ntos/registry.h" +#include "ntos/security.h" +#include "ntos/synch.h" +#include "ntos/time.h" +#include "napi/i386/segment.h" +#include "napi/types.h" +#include "napi/core.h" +#include "napi/dbg.h" +#include "napi/lpc.h" +#include "napi/npipe.h" +#include "napi/shared_data.h" +#include "napi/win32.h" +#endif + +#endif /* ndef _NTOS_H */ diff --git a/include/ntos/cdrom.h b/include/ntos/cdrom.h new file mode 100644 index 0000000..c1a5c2a --- /dev/null +++ b/include/ntos/cdrom.h @@ -0,0 +1,44 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/cdrom.h + * PURPOSE: CD-ROM related definitions used by all the parts of the system + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 10/04/2002: Created + */ + +#ifndef __INCLUDE_NTOS_CDROM_H +#define __INCLUDE_NTOS_CDROM_H + +#define IOCTL_CDROM_READ_TOC CTL_CODE(FILE_DEVICE_CD_ROM, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_LAST_SESSION CTL_CODE(FILE_DEVICE_CD_ROM, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(FILE_DEVICE_CD_ROM, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define MAXIMUM_NUMBER_TRACKS 100 +#define MAXIMUM_CDROM_SIZE 804 + +typedef struct _TRACK_DATA { + UCHAR Reserved; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, *PTRACK_DATA; + +typedef struct _CDROM_TOC { + UCHAR Length[2]; + UCHAR FirstTrack; + UCHAR LastTrack; + TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; +} CDROM_TOC, *PCDROM_TOC; + +#define CDROM_TOC_SIZE sizeof(CDROM_TOC) + + + +#endif /* __INCLUDE_NTOS_CDROM_H */ + +/* EOF */ diff --git a/include/ntos/console.h b/include/ntos/console.h new file mode 100644 index 0000000..294d003 --- /dev/null +++ b/include/ntos/console.h @@ -0,0 +1,54 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/console.h + * PURPOSE: Console declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_CONSOLE_H +#define __INCLUDE_CONSOLE_H + +/* GetConsoleMode */ +#define ENABLE_LINE_INPUT (0x02) +#define ENABLE_ECHO_INPUT (0x04) +#define ENABLE_PROCESSED_INPUT (0x01) +#define ENABLE_WINDOW_INPUT (0x08) +#define ENABLE_MOUSE_INPUT (0x0f) +#define CONSOLE_INPUT_MODE_VALID (0x0f) +#define ENABLE_PROCESSED_OUTPUT (0x01) +#define ENABLE_WRAP_AT_EOL_OUTPUT (0x02) +#define CONSOLE_OUTPUT_MODE_VALID (0x03) + +typedef struct _CONSOLE_SCREEN_BUFFER_INFO { + COORD dwSize; + COORD dwCursorPosition; + WORD wAttributes; + SMALL_RECT srWindow; + COORD dwMaximumWindowSize; +} CONSOLE_SCREEN_BUFFER_INFO, *PCONSOLE_SCREEN_BUFFER_INFO ; + +typedef struct _CONSOLE_CURSOR_INFO { + DWORD dwSize; + BOOL bVisible; +} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO; + +typedef struct _CONSOLE_FONT_INFO { + DWORD nFont; + COORD dwFontSize; +} CONSOLE_FONT_INFO, *PCONSOLE_FONT_INFO; + +typedef struct _CONSOLE_SELECTION_INFO { + DWORD dwFlags; + COORD dwSelectionAnchor; + SMALL_RECT srSelection; +} CONSOLE_SELECTION_INFO, *PCONSOLE_SELECTION_INFO; + +#endif /* __INCLUDE_CONSOLE_H */ + + + diff --git a/include/ntos/disk.h b/include/ntos/disk.h new file mode 100644 index 0000000..4e16cbd --- /dev/null +++ b/include/ntos/disk.h @@ -0,0 +1,160 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/disk.h + * PURPOSE: Disk related definitions used by all the parts of the system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + +#ifndef __INCLUDE_DISK_H +#define __INCLUDE_DISK_H + + +#define IOCTL_DISK_GET_DRIVE_GEOMETRY CTL_CODE(FILE_DEVICE_DISK, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_GET_PARTITION_INFO CTL_CODE(FILE_DEVICE_DISK, 1, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DISK_SET_PARTITION_INFO CTL_CODE(FILE_DEVICE_DISK, 2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_GET_DRIVE_LAYOUT CTL_CODE(FILE_DEVICE_DISK, 3, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DISK_SET_DRIVE_LAYOUT CTL_CODE(FILE_DEVICE_DISK, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_VERIFY CTL_CODE(FILE_DEVICE_DISK, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_FORMAT_TRACKS CTL_CODE(FILE_DEVICE_DISK, 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_REASSIGN_BLOCKS CTL_CODE(FILE_DEVICE_DISK, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_PERFORMANCE CTL_CODE(FILE_DEVICE_DISK, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_IS_WRITABLE CTL_CODE(FILE_DEVICE_DISK, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_LOGGING CTL_CODE(FILE_DEVICE_DISK, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_FORMAT_TRACKS_EX CTL_CODE(FILE_DEVICE_DISK, 11, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_HISTOGRAM_STRUCTURE CTL_CODE(FILE_DEVICE_DISK, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_HISTOGRAM_DATA CTL_CODE(FILE_DEVICE_DISK, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_HISTOGRAM_RESET CTL_CODE(FILE_DEVICE_DISK, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_REQUEST_STRUCTURE CTL_CODE(FILE_DEVICE_DISK, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_REQUEST_DATA CTL_CODE(FILE_DEVICE_DISK, 16, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +#define PARTITION_ENTRY_UNUSED 0x00 +#define PARTITION_FAT_12 0x01 +#define PARTITION_XENIX_1 0x02 +#define PARTITION_XENIX_2 0x03 +#define PARTITION_FAT_16 0x04 +#define PARTITION_EXTENDED 0x05 +#define PARTITION_HUGE 0x06 +#define PARTITION_IFS 0x07 +#define PARTITION_FAT32 0x0B +#define PARTITION_FAT32_XINT13 0x0C +#define PARTITION_XINT13 0x0E +#define PARTITION_XINT13_EXTENDED 0x0F +#define PARTITION_PREP 0x41 +#define PARTITION_LDM 0x42 +#define PARTITION_UNIX 0x63 + +#define PARTITION_NTFT 0x80 +#define VALID_NTFT 0xC0 + +#if 0 +#define PTEmpty 0x00 +#define PTDOS3xPrimary 0x01 +#define PTXENIXRoot 0x02 +#define PTXENIXUsr 0x03 +#define PTOLDDOS16Bit 0x04 +#define PTDosExtended 0x05 +#define PTDos5xPrimary 0x06 +#define PTIfs 0x07 // e.g.: HPFS, NTFS, etc +#define PTAIX 0x08 +#define PTAIXBootable 0x09 +#define PTOS2BootMgr 0x0A +#define PTWin95FAT32 0x0B +#define PTWin95FAT32LBA 0x0C +#define PTWin95FAT16LBA 0x0E +#define PTWin95ExtendedLBA 0x0F +#define PTVenix286 0x40 +#define PTNovell 0x51 +#define PTMicroport 0x52 +#define PTGnuHurd 0x63 +#define PTNetware286 0x64 +#define PTNetware386 0x65 +#define PTPCIX 0x75 +#define PTOldMinix 0x80 +#define PTMinix 0x81 +#define PTLinuxSwap 0x82 +#define PTLinuxExt2 0x83 +#define PTAmoeba 0x93 +#define PTAmoebaBBT 0x94 +#define PTBSD 0xA5 +#define PTBSDIFS 0xB7 +#define PTBSDISwap 0xB8 +#define PTSyrinx 0xC7 +#define PTCPM 0xDB +#define PTDOSAccess 0xE1 +#define PTDOSRO 0xE3 +#define PTDOSSecondary 0xF2 +#define PTBBT 0xFF +#endif + +#define IsRecognizedPartition(P) \ + ((P) == PARTITION_FAT_12 || \ + (P) == PARTITION_FAT_16 || \ + (P) == PARTITION_HUGE || \ + (P) == PARTITION_IFS || \ + (P) == PARTITION_FAT32 || \ + (P) == PARTITION_FAT32_XINT13 || \ + (P) == PARTITION_XINT13) + +#define IsContainerPartition(P) \ + ((P) == PARTITION_EXTENDED || \ + (P) == PARTITION_XINT13_EXTENDED) + + +typedef enum _MEDIA_TYPE +{ + Unknown, + F5_1Pt2_512, + F3_1Pt44_512, + F3_2Pt88_512, + F3_20Pt8_512, + F3_720_512, + F5_360_512, + F5_320_512, + F5_320_1024, + F5_180_512, + F5_160_512, + RemovableMedia, + FixedMedia +} MEDIA_TYPE; + +typedef struct _PARTITION_INFORMATION +{ + LARGE_INTEGER StartingOffset; + LARGE_INTEGER PartitionLength; + DWORD HiddenSectors; + DWORD PartitionNumber; + BYTE PartitionType; + BOOLEAN BootIndicator; + BOOLEAN RecognizedPartition; + BOOLEAN RewritePartition; +} PARTITION_INFORMATION, *PPARTITION_INFORMATION; + +typedef struct _DRIVE_LAYOUT_INFORMATION +{ + DWORD PartitionCount; + DWORD Signature; + PARTITION_INFORMATION PartitionEntry[1]; +} DRIVE_LAYOUT_INFORMATION, *PDRIVE_LAYOUT_INFORMATION; + +typedef struct _SET_PARTITION_INFORMATION +{ + ULONG PartitionType; +} SET_PARTITION_INFORMATION, *PSET_PARTITION_INFORMATION; + +typedef struct _DISK_GEOMETRY +{ + LARGE_INTEGER Cylinders; + MEDIA_TYPE MediaType; + DWORD TracksPerCylinder; + DWORD SectorsPerTrack; + DWORD BytesPerSector; +} DISK_GEOMETRY, *PDISK_GEOMETRY; + +#endif /* __INCLUDE_DISK_H */ + +/* EOF */ diff --git a/include/ntos/except.h b/include/ntos/except.h new file mode 100644 index 0000000..c34b62d --- /dev/null +++ b/include/ntos/except.h @@ -0,0 +1,145 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/except.h + * PURPOSE: Exception handling structures + * PROGRAMMER: Casper S. Hornstrup + */ + +#ifndef __INCLUDE_EXCEPT_H +#define __INCLUDE_EXCEPT_H + +typedef enum { + ExceptionContinueExecution = 0, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind, + ExceptionDismiss // ??? +} EXCEPTION_DISPOSITION; + + +struct _EXCEPTION_RECORD; +struct _EXCEPTION_REGISTRATION; + +/* + * The type of function that is expected as an exception handler to be + * installed with _try1. + */ +typedef EXCEPTION_DISPOSITION CDECL (*PEXCEPTION_HANDLER)( + struct _EXCEPTION_RECORD* ExceptionRecord, + struct _EXCEPTION_REGISTRATION* ExceptionRegistration, + PCONTEXT Context, + PVOID DispatcherContext); + + +#define EXCEPTION_MAXIMUM_PARAMETERS (15) + +typedef struct _EXCEPTION_RECORD { + DWORD ExceptionCode; + DWORD ExceptionFlags; + struct _EXCEPTION_RECORD *ExceptionRecord; + PVOID ExceptionAddress; + DWORD NumberParameters; + DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD, *PEXCEPTION_RECORD, *LPEXCEPTION_RECORD; + +/* ExceptionFlags */ +#ifndef _GNU_H_WINDOWS32_DEFINES +#ifdef __NTOSKRNL__ +#define EXCEPTION_NONCONTINUABLE 0x01 +#endif /* __NTOSKRNL__ */ +#endif /* _GNU_H_WINDOWS32_DEFINES */ +#define EXCEPTION_UNWINDING 0x02 +#define EXCEPTION_EXIT_UNWIND 0x04 +#define EXCEPTION_STACK_INVALID 0x08 +#define EXCEPTION_NESTED_CALL 0x10 + + +typedef struct _EXCEPTION_POINTERS { + PEXCEPTION_RECORD ExceptionRecord; + PCONTEXT ContextRecord; +} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS, *LPEXCEPTION_POINTERS; + + +typedef struct _EXCEPTION_REGISTRATION +{ + struct _EXCEPTION_REGISTRATION* prev; + PEXCEPTION_HANDLER handler; +} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION; + +typedef EXCEPTION_REGISTRATION EXCEPTION_REGISTRATION_RECORD; +typedef PEXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION_RECORD; + + +/* + * A macro which installs the supplied exception handler. + * Push the pointer to the new handler onto the stack, + * then push the pointer to the old registration structure (at fs:0) + * onto the stack, then put a pointer to the new registration + * structure (i.e. the current stack pointer) at fs:0. + */ +#define __try1(pHandler) \ + __asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (pHandler)); + + +/* + * A macro which (dispite its name) *removes* an installed + * exception handler. Should be used only in conjunction with the above + * install routine __try1. + * Move the pointer to the old reg. struct (at the current stack + * position) to fs:0, replacing the pointer we installed above, + * then add 8 to the stack pointer to get rid of the space we + * used when we pushed on our new reg. struct above. Notice that + * the stack must be in the exact state at this point that it was + * after we did _try1 or this will smash things. + */ +#define __except1 \ + __asm__ ("movl (%%esp),%%eax;movl %%eax,%%fs:0;addl $8,%%esp;" \ + : : : "%eax"); + + +#if 1 + +// Runtime DLL structures + +#ifndef _GNU_H_WINDOWS32_DEFINES +#ifdef __NTOSKRNL__ +#define EXCEPTION_EXECUTE_HANDLER 1 +#define EXCEPTION_CONTINUE_SEARCH 0 +#define EXCEPTION_CONTINUE_EXECUTION -1 +#endif /* __NTOSKRNL__ */ +#endif /* _GNU_H_WINDOWS32_DEFINES */ + +// Functions of the following prototype return one of the above constants +typedef DWORD CDECL (*PSCOPE_EXCEPTION_FILTER)(VOID); +typedef VOID CDECL (*PSCOPE_EXCEPTION_HANDLER)(VOID); + +typedef struct _SCOPETABLE_ENTRY +{ + DWORD PreviousTryLevel; + PSCOPE_EXCEPTION_FILTER FilterRoutine; + PSCOPE_EXCEPTION_HANDLER HandlerRoutine; +} SCOPETABLE_ENTRY, *PSCOPETABLE_ENTRY; + +/* + Other structures preceeding this structure: + ULONG_PTR StandardESPInFrame; + LPEXCEPTION_POINTERS ExceptionPointers; + */ +typedef struct _RTL_EXCEPTION_REGISTRATION_I386 +{ + EXCEPTION_REGISTRATION OS; + PSCOPETABLE_ENTRY ScopeTable; + DWORD TryLevel; + /* Value of EBP before the EXCEPTION_REGISTRATION was created */ + ULONG_PTR Ebp; +} RTL_EXCEPTION_REGISTRATION_I386, *PRTL_EXCEPTION_REGISTRATION_I386; + +#define TRYLEVEL_NONE -1 + +typedef RTL_EXCEPTION_REGISTRATION_I386 RTL_EXCEPTION_REGISTRATION; +typedef PRTL_EXCEPTION_REGISTRATION_I386 PRTL_EXCEPTION_REGISTRATION; + +#endif + +#endif /* __INCLUDE_EXCEPT_H */ diff --git a/include/ntos/file.h b/include/ntos/file.h new file mode 100644 index 0000000..eed866d --- /dev/null +++ b/include/ntos/file.h @@ -0,0 +1,116 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ps.h + * PURPOSE: Filesystem declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_FILE_H +#define __INCLUDE_FILE_H + +#define GENERIC_READ (0x80000000L) +#define GENERIC_WRITE (0x40000000L) +#define FILE_READ_DATA ( 0x0001 ) /* file & pipe */ +#define FILE_LIST_DIRECTORY ( 0x0001 ) /* directory */ + +#define FILE_WRITE_DATA ( 0x0002 ) /* file & pipe */ +#define FILE_ADD_FILE ( 0x0002 ) /* directory */ + +#define FILE_APPEND_DATA ( 0x0004 ) /* file */ +#define FILE_ADD_SUBDIRECTORY ( 0x0004 ) /* directory */ +#define FILE_CREATE_PIPE_INSTANCE ( 0x0004 ) /* named pipe */ + +#define FILE_READ_EA ( 0x0008 ) /* file & directory */ +#define FILE_READ_PROPERTIES FILE_READ_EA + +#define FILE_WRITE_EA ( 0x0010 ) /* file & directory */ +#define FILE_WRITE_PROPERTIES FILE_WRITE_EA + +#define FILE_EXECUTE ( 0x0020 ) /* file */ +#define FILE_TRAVERSE ( 0x0020 ) /* directory */ + +#define FILE_DELETE_CHILD ( 0x0040 ) /* directory */ + +#define FILE_READ_ATTRIBUTES ( 0x0080 ) /* all */ + +#define FILE_WRITE_ATTRIBUTES ( 0x0100 ) /* all */ + +#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF) + +#define FILE_GENERIC_READ (STANDARD_RIGHTS_READ |\ + FILE_READ_DATA |\ + FILE_READ_ATTRIBUTES |\ + FILE_READ_EA |\ + SYNCHRONIZE) + + +#define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE |\ + FILE_WRITE_DATA |\ + FILE_WRITE_ATTRIBUTES |\ + FILE_WRITE_EA |\ + FILE_APPEND_DATA |\ + SYNCHRONIZE) + + +#define FILE_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE |\ + FILE_READ_ATTRIBUTES |\ + FILE_EXECUTE |\ + SYNCHRONIZE) + +#define FILE_SHARE_DELETE (4) +#define FILE_SHARE_READ (1) +#define FILE_SHARE_WRITE (2) +#define CONSOLE_TEXTMODE_BUFFER (1) +#define CREATE_NEW (1) +#define CREATE_ALWAYS (2) +#define OPEN_EXISTING (3) +#define OPEN_ALWAYS (4) +#define TRUNCATE_EXISTING (5) +#define FILE_ATTRIBUTE_ARCHIVE (32) +#define FILE_ATTRIBUTE_COMPRESSED (2048) +#define FILE_ATTRIBUTE_DEVICE (64) +#define FILE_ATTRIBUTE_NORMAL (128) +#define FILE_ATTRIBUTE_DIRECTORY (16) +#define FILE_ATTRIBUTE_ENCRYPTED (16384) +#define FILE_ATTRIBUTE_HIDDEN (2) +#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED (8192) +#define FILE_ATTRIBUTE_OFFLINE (4096) +#define FILE_ATTRIBUTE_READONLY (1) +#define FILE_ATTRIBUTE_REPARSE_POINT (1024) +#define FILE_ATTRIBUTE_SPARSE_FILE (512) +#define FILE_ATTRIBUTE_SYSTEM (4) +#define FILE_ATTRIBUTE_TEMPORARY (256) +#define FILE_ATTRIBUTE_VALID_FLAGS (0x00007fb7) +#define FILE_ATTRIBUTE_VALID_SET_FLAGS (0x000031a7) +#define FILE_FLAG_WRITE_THROUGH (0x80000000) +#define FILE_FLAG_OVERLAPPED (0x40000000) +#define FILE_FLAG_NO_BUFFERING (0x20000000) +#define FILE_FLAG_RANDOM_ACCESS (0x10000000) +#define FILE_FLAG_SEQUENTIAL_SCAN (0x08000000) +#define FILE_FLAG_DELETE_ON_CLOSE (0x04000000) +#define FILE_FLAG_BACKUP_SEMANTICS (0x02000000) +#define FILE_FLAG_POSIX_SEMANTICS (0x01000000) + +/* GetVolumeInformation */ +#define FS_CASE_IS_PRESERVED (2) +#define FS_CASE_SENSITIVE (1) +#define FS_UNICODE_STORED_ON_DISK (4) +#define FS_PERSISTENT_ACLS (8) +#define FS_FILE_COMPRESSION (16) +#define FS_VOL_IS_COMPRESSED (32768) + +/* NtQueryVolumeInformationFile */ +#define FILE_CASE_SENSITIVE_SEARCH (0x00000001) +#define FILE_CASE_PRESERVED_NAMES (0x00000002) +#define FILE_UNICODE_ON_DISK (0x00000004) +#define FILE_PERSISTENT_ACLS (0x00000008) +#define FILE_FILE_COMPRESSION (0x00000010) +#define FILE_VOLUME_IS_COMPRESSED (0x00008000) + + +#endif /* __INCLUDE_FILE_H */ diff --git a/include/ntos/gditypes.h b/include/ntos/gditypes.h new file mode 100644 index 0000000..180fd40 --- /dev/null +++ b/include/ntos/gditypes.h @@ -0,0 +1,91 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/gditypes.h + * PURPOSE: Common GDI definitions + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 25/06/2001: Created +*/ + +#ifndef __INCLUDE_NTOS_GDITYPES_H +#define __INCLUDE_NTOS_GDITYPES_H + +#define CCHDEVICENAME (32) +#define CCHFORMNAME (32) + +typedef struct _devicemodeA +{ + BYTE dmDeviceName[CCHDEVICENAME]; + WORD dmSpecVersion; + WORD dmDriverVersion; + WORD dmSize; + WORD dmDriverExtra; + DWORD dmFields; + short dmOrientation; + short dmPaperSize; + short dmPaperLength; + short dmPaperWidth; + short dmScale; + short dmCopies; + short dmDefaultSource; + short dmPrintQuality; + short dmColor; + short dmDuplex; + short dmYResolution; + short dmTTOption; + short dmCollate; + BYTE dmFormName[CCHFORMNAME]; + WORD dmLogPixels; + DWORD dmBitsPerPel; + DWORD dmPelsWidth; + DWORD dmPelsHeight; + DWORD dmDisplayFlags; + DWORD dmDisplayFrequency; + DWORD dmICMMethod; + DWORD dmICMIntent; + DWORD dmMediaType; + DWORD dmDitherType; + DWORD dmICCManufacturer; + DWORD dmICCModel; +} DEVMODEA,*LPDEVMODEA,*PDEVMODEA; + +typedef struct _devicemodeW +{ + WCHAR dmDeviceName[CCHDEVICENAME]; + WORD dmSpecVersion; + WORD dmDriverVersion; + WORD dmSize; + WORD dmDriverExtra; + DWORD dmFields; + short dmOrientation; + short dmPaperSize; + short dmPaperLength; + short dmPaperWidth; + short dmScale; + short dmCopies; + short dmDefaultSource; + short dmPrintQuality; + short dmColor; + short dmDuplex; + short dmYResolution; + short dmTTOption; + short dmCollate; + WCHAR dmFormName[CCHFORMNAME]; + WORD dmLogPixels; + DWORD dmBitsPerPel; + DWORD dmPelsWidth; + DWORD dmPelsHeight; + DWORD dmDisplayFlags; + DWORD dmDisplayFrequency; + DWORD dmICMMethod; + DWORD dmICMIntent; + DWORD dmMediaType; + DWORD dmDitherType; + DWORD dmICCManufacturer; + DWORD dmICCModel; +} DEVMODEW,*LPDEVMODEW,*PDEVMODEW; + +#endif /* __INCLUDE_NTOS_GDITYPES_H */ + +/* EOF */ diff --git a/include/ntos/heap.h b/include/ntos/heap.h new file mode 100644 index 0000000..5efac19 --- /dev/null +++ b/include/ntos/heap.h @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/heap.h + * PURPOSE: Heap declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_HEAP_H +#define __INCLUDE_HEAP_H + +/* HeapAlloc, HeapReAlloc */ +#define HEAP_GENERATE_EXCEPTIONS (4) +#define HEAP_NO_SERIALIZE (1) +#define HEAP_ZERO_MEMORY (8) +#define HEAP_REALLOC_IN_PLACE_ONLY (16) +#define HEAP_GROWABLE (32) +#define HEAP_NO_VALLOC (64) + +#endif /* __INCLUDE_HEAP_H */ diff --git a/include/ntos/kdbgsyms.h b/include/ntos/kdbgsyms.h new file mode 100644 index 0000000..79c19ec --- /dev/null +++ b/include/ntos/kdbgsyms.h @@ -0,0 +1,46 @@ + +#ifndef __KDBGSYMS_H +#define __KDBGSYMS_H + +#include + +#define ST_FILENAME 0x00 +#define ST_FUNCTION 0x01 +#define ST_LINENUMBER 0x02 + +typedef struct _SYMBOL +{ + struct _SYMBOL *Next; + /* Address relative to module base address */ + ULONG RelativeAddress; + ULONG SymbolType; + ANSI_STRING Name; + ULONG LineNumber; +} SYMBOL, *PSYMBOL; + +typedef struct _SYMBOL_TABLE +{ + ULONG SymbolCount; + PSYMBOL Symbols; +} SYMBOL_TABLE, *PSYMBOL_TABLE; + +typedef struct _IMAGE_SYMBOL_INFO +{ + SYMBOL_TABLE FileNameSymbols; + SYMBOL_TABLE FunctionSymbols; + SYMBOL_TABLE LineNumberSymbols; + ULONG_PTR ImageBase; + ULONG_PTR ImageSize; + PVOID FileBuffer; + PVOID SymbolsBase; + ULONG SymbolsLength; + PVOID SymbolStringsBase; + ULONG SymbolStringsLength; +} IMAGE_SYMBOL_INFO, *PIMAGE_SYMBOL_INFO; + +#define AreSymbolsParsed(si)((si)->FileNameSymbols.Symbols \ + || (si)->FunctionSymbols.Symbols \ + || (si)->LineNumberSymbols.Symbols) + +#endif + diff --git a/include/ntos/keyboard.h b/include/ntos/keyboard.h new file mode 100644 index 0000000..2945a73 --- /dev/null +++ b/include/ntos/keyboard.h @@ -0,0 +1,213 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/keyboard.h + * PURPOSE: Keyboard declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_KEYBOARD_H +#define __INCLUDE_KEYBOARD_H + +#include + +/* KEY_EVENT_RECORD structure */ +#define CAPSLOCK_ON (128) +#define ENHANCED_KEY (256) +#define LEFT_ALT_PRESSED (2) +#define LEFT_CTRL_PRESSED (8) +#define NUMLOCK_ON (32) +#define RIGHT_ALT_PRESSED (1) +#define RIGHT_CTRL_PRESSED (4) +#define SCROLLLOCK_ON (64) +#define SHIFT_PRESSED (16) + +/* MOUSE_EVENT_RECORD structure */ +#define FROM_LEFT_1ST_BUTTON_PRESSED (1) +#define RIGHTMOST_BUTTON_PRESSED (2) +#define FROM_LEFT_2ND_BUTTON_PRESSED (4) +#define FROM_LEFT_3RD_BUTTON_PRESSED (8) +#define FROM_LEFT_4TH_BUTTON_PRESSED (16) +#define DOUBLE_CLICK (2) +#define MOUSE_MOVED (1) + +/* INPUT_RECORD structure */ +#define KEY_EVENT (1) +#define MOUSE_EVENT (2) +#define WINDOW_BUFFER_SIZE_EVENT (4) +#define MENU_EVENT (8) +#define FOCUS_EVENT (16) + + +typedef struct _KEY_EVENT_RECORD { + BOOL bKeyDown; + WORD wRepeatCount; + WORD wVirtualKeyCode; + WORD wVirtualScanCode; + union { + WCHAR UnicodeChar; + CHAR AsciiChar; + } uChar; + DWORD dwControlKeyState; +} KEY_EVENT_RECORD PACKED; + +typedef struct _MOUSE_EVENT_RECORD { + COORD dwMousePosition; + DWORD dwButtonState; + DWORD dwControlKeyState; + DWORD dwEventFlags; +} MOUSE_EVENT_RECORD; + +typedef struct _WINDOW_BUFFER_SIZE_RECORD { + COORD dwSize; +} WINDOW_BUFFER_SIZE_RECORD; + +typedef struct _MENU_EVENT_RECORD { + UINT dwCommandId; +} MENU_EVENT_RECORD, *PMENU_EVENT_RECORD; + +typedef struct _FOCUS_EVENT_RECORD { + BOOL bSetFocus; +} FOCUS_EVENT_RECORD; + +typedef struct _INPUT_RECORD { + WORD EventType; + union { +#ifndef __cplus_plus + /* this will be the wrong size in c++ */ + KEY_EVENT_RECORD KeyEvent; +#endif + MOUSE_EVENT_RECORD MouseEvent; + WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; + MENU_EVENT_RECORD MenuEvent; + FOCUS_EVENT_RECORD FocusEvent; + } Event; +} INPUT_RECORD, *PINPUT_RECORD; + +/* Virtual Key codes */ +#define VK_LBUTTON (1) +#define VK_RBUTTON (2) +#define VK_CANCEL (3) +#define VK_MBUTTON (4) +#define VK_BACK (8) +#define VK_TAB (9) +#define VK_CLEAR (12) +#define VK_RETURN (13) +#define VK_SHIFT (16) +#define VK_CONTROL (17) +#define VK_MENU (18) +#define VK_PAUSE (19) +#define VK_CAPITAL (20) +#define VK_ESCAPE (27) +#define VK_SPACE (32) +#define VK_PRIOR (33) +#define VK_NEXT (34) +#define VK_END (35) +#define VK_HOME (36) +#define VK_LEFT (37) +#define VK_UP (38) +#define VK_RIGHT (39) +#define VK_DOWN (40) +#define VK_SELECT (41) +#define VK_PRINT (42) +#define VK_EXECUTE (43) +#define VK_SNAPSHOT (44) +#define VK_INSERT (45) +#define VK_DELETE (46) +#define VK_HELP (47) +#define VK_0 (48) +#define VK_1 (49) +#define VK_2 (50) +#define VK_3 (51) +#define VK_4 (52) +#define VK_5 (53) +#define VK_6 (54) +#define VK_7 (55) +#define VK_8 (56) +#define VK_9 (57) +#define VK_A (65) +#define VK_B (66) +#define VK_C (67) +#define VK_D (68) +#define VK_E (69) +#define VK_F (70) +#define VK_G (71) +#define VK_H (72) +#define VK_I (73) +#define VK_J (74) +#define VK_K (75) +#define VK_L (76) +#define VK_M (77) +#define VK_N (78) +#define VK_O (79) +#define VK_P (80) +#define VK_Q (81) +#define VK_R (82) +#define VK_S (83) +#define VK_T (84) +#define VK_U (85) +#define VK_V (86) +#define VK_W (87) +#define VK_X (88) +#define VK_Y (89) +#define VK_Z (90) +#define VK_NUMPAD0 (96) +#define VK_NUMPAD1 (97) +#define VK_NUMPAD2 (98) +#define VK_NUMPAD3 (99) +#define VK_NUMPAD4 (100) +#define VK_NUMPAD5 (101) +#define VK_NUMPAD6 (102) +#define VK_NUMPAD7 (103) +#define VK_NUMPAD8 (104) +#define VK_NUMPAD9 (105) +#define VK_MULTIPLY (106) +#define VK_ADD (107) +#define VK_SEPARATOR (108) +#define VK_SUBTRACT (109) +#define VK_DECIMAL (110) +#define VK_DIVIDE (111) +#define VK_F1 (112) +#define VK_F2 (113) +#define VK_F3 (114) +#define VK_F4 (115) +#define VK_F5 (116) +#define VK_F6 (117) +#define VK_F7 (118) +#define VK_F8 (119) +#define VK_F9 (120) +#define VK_F10 (121) +#define VK_F11 (122) +#define VK_F12 (123) +#define VK_F13 (124) +#define VK_F14 (125) +#define VK_F15 (126) +#define VK_F16 (127) +#define VK_F17 (128) +#define VK_F18 (129) +#define VK_F19 (130) +#define VK_F20 (131) +#define VK_F21 (132) +#define VK_F22 (133) +#define VK_F23 (134) +#define VK_F24 (135) + +/* GetAsyncKeyState */ +#define VK_NUMLOCK (144) +#define VK_SCROLL (145) +#define VK_LSHIFT (160) +#define VK_LCONTROL (162) +#define VK_LMENU (164) +#define VK_RSHIFT (161) +#define VK_RCONTROL (163) +#define VK_RMENU (165) + + +#endif /* __INCLUDE_KEYBOARD_H */ + + + diff --git a/include/ntos/minmax.h b/include/ntos/minmax.h new file mode 100644 index 0000000..37d9ff3 --- /dev/null +++ b/include/ntos/minmax.h @@ -0,0 +1,7 @@ +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif diff --git a/include/ntos/mm.h b/include/ntos/mm.h new file mode 100644 index 0000000..7ed75b4 --- /dev/null +++ b/include/ntos/mm.h @@ -0,0 +1,63 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/mm.h + * PURPOSE: Memory managment declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_MM_H +#define __INCLUDE_MM_H + +#if 0 +#define SEC_COMMIT (134217728) +#define SEC_IMAGE (16777216) +#define SEC_NOCACHE (268435456) +#define SEC_RESERVE (67108864) +#else +#define SEC_BASED (0x00200000) +#define SEC_NO_CHANGE (0x00400000) +#define SEC_IMAGE (0x01000000) +#define SEC_VLM (0x02000000) +#define SEC_RESERVE (0x04000000) +#define SEC_COMMIT (0x08000000) +#define SEC_NOCACHE (0x10000000) +#endif +#define PAGE_READONLY (2) +#define PAGE_READWRITE (4) +#define PAGE_WRITECOPY (8) +#define PAGE_EXECUTE (16) +#define PAGE_EXECUTE_READ (32) +#define PAGE_EXECUTE_READWRITE (64) +#define PAGE_EXECUTE_WRITECOPY (128) +#define PAGE_GUARD (256) +#define PAGE_NOACCESS (1) +#define PAGE_NOCACHE (512) +#define MEM_COMMIT (4096) +#define MEM_FREE (65536) +#define MEM_RESERVE (8192) +#define MEM_IMAGE (16777216) +#define MEM_MAPPED (262144) +#define MEM_PRIVATE (131072) +#define MEM_DECOMMIT (16384) +#define MEM_RELEASE (32768) +#define MEM_TOP_DOWN (1048576) +#define EXCEPTION_GUARD_PAGE (0x80000001L) +#define SECTION_EXTEND_SIZE (0x10) +#define SECTION_MAP_EXECUTE (0x8) +#define SECTION_MAP_READ (0x4) +#define SECTION_MAP_WRITE (0x2) +#define SECTION_QUERY (0x1) +#define SECTION_ALL_ACCESS (0xf001fL) + +#define FILE_MAP_ALL_ACCESS (0xf001fL) +#define FILE_MAP_READ (4) +#define FILE_MAP_WRITE (2) +#define FILE_MAP_COPY (1) + + +#endif /* __INCLUDE_MM_H */ diff --git a/include/ntos/ntdef.h b/include/ntos/ntdef.h new file mode 100644 index 0000000..c3356c8 --- /dev/null +++ b/include/ntos/ntdef.h @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntdef.h + * PURPOSE: Defines used by all the parts of the system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + +#ifndef __INCLUDE_NTDEF_H +#define __INCLUDE_NTDEF_H + +#define ANYSIZE_ARRAY (1) + +#define DELETE (0x00010000L) +#define READ_CONTROL (0x00020000L) +#define SYNCHRONIZE (0x00100000L) + +#define DUPLICATE_CLOSE_SOURCE (1) +#define DUPLICATE_SAME_ACCESS (2) + +#define PACKED __attribute__((packed)) + +#define INVALID_HANDLE_VALUE ((HANDLE)-1) + +#define EX_MAXIMUM_WAIT_OBJECTS (64) + +#endif /* __INCLUDE_NTDEF_H */ diff --git a/include/ntos/port.h b/include/ntos/port.h new file mode 100644 index 0000000..34eda0c --- /dev/null +++ b/include/ntos/port.h @@ -0,0 +1,23 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/port.h + * PURPOSE: Port declarations used by all the parts of the + * system + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 02/02/2001: Created + */ + +#ifndef __INCLUDE_PORT_H +#define __INCLUDE_PORT_H + + +/* Port Object Access */ + +#define PORT_ALL_ACCESS (0x1) + +#endif /* __INCLUDE_PORT_H */ + +/* EOF */ diff --git a/include/ntos/ps.h b/include/ntos/ps.h new file mode 100644 index 0000000..c9e8171 --- /dev/null +++ b/include/ntos/ps.h @@ -0,0 +1,78 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/ps.h + * PURPOSE: Process/thread declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_PS_H +#define __INCLUDE_PS_H + +/* Thread access rights */ +#define THREAD_TERMINATE (0x0001L) +#define THREAD_SUSPEND_RESUME (0x0002L) +#define THREAD_GET_CONTEXT (0x0008L) +#define THREAD_SET_CONTEXT (0x0010L) +#define THREAD_SET_INFORMATION (0x0020L) +#define THREAD_QUERY_INFORMATION (0x0040L) +#define THREAD_SET_THREAD_TOKEN (0x0080L) +#define THREAD_IMPERSONATE (0x0100L) +#define THREAD_DIRECT_IMPERSONATION (0x0200L) + +#define THREAD_ALL_ACCESS (0x1f03ffL) +#define THREAD_READ (0x020048L) +#define THREAD_WRITE (0x020037L) +#define THREAD_EXECUTE (0x120000L) + +/* Process access rights */ +#define PROCESS_TERMINATE (0x0001L) +#define PROCESS_CREATE_THREAD (0x0002L) +#define PROCESS_SET_SESSIONID (0x0004L) +#define PROCESS_VM_OPERATION (0x0008L) +#define PROCESS_VM_READ (0x0010L) +#define PROCESS_VM_WRITE (0x0020L) +#define PROCESS_DUP_HANDLE (0x0040L) +#define PROCESS_CREATE_PROCESS (0x0080L) +#define PROCESS_SET_QUOTA (0x0100L) +#define PROCESS_SET_INFORMATION (0x0200L) +#define PROCESS_QUERY_INFORMATION (0x0400L) + +#define PROCESS_ALL_ACCESS (0x1f0fffL) +#define PROCESS_READ (0x020410L) +#define PROCESS_WRITE (0x020bebL) +#define PROCESS_EXECUTE (0x120000L) + +/* Thread priorities */ +#define THREAD_PRIORITY_ABOVE_NORMAL (1) +#define THREAD_PRIORITY_BELOW_NORMAL (-1) +#define THREAD_PRIORITY_HIGHEST (2) +#define THREAD_PRIORITY_IDLE (-15) +#define THREAD_PRIORITY_LOWEST (-2) +#define THREAD_PRIORITY_NORMAL (0) +#define THREAD_PRIORITY_TIME_CRITICAL (15) +#define THREAD_PRIORITY_ERROR_RETURN (2147483647) + +/* CreateProcess */ +#define CREATE_DEFAULT_ERROR_MODE (67108864) +#define CREATE_NEW_CONSOLE (16) +#define CREATE_NEW_PROCESS_GROUP (512) +#define CREATE_SEPARATE_WOW_VDM (2048) +#define CREATE_SUSPENDED (4) +#define CREATE_UNICODE_ENVIRONMENT (1024) +#define DEBUG_PROCESS (1) +#define DEBUG_ONLY_THIS_PROCESS (2) +#define DETACHED_PROCESS (8) +#define HIGH_PRIORITY_CLASS (128) +#define IDLE_PRIORITY_CLASS (64) +#define NORMAL_PRIORITY_CLASS (32) +#define REALTIME_PRIORITY_CLASS (256) + +/* ResumeThread / SuspendThread */ +#define MAXIMUM_SUSPEND_COUNT (0x7f) + +#endif /* __INCLUDE_PS_H */ diff --git a/include/ntos/registry.h b/include/ntos/registry.h new file mode 100644 index 0000000..c714dde --- /dev/null +++ b/include/ntos/registry.h @@ -0,0 +1,55 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/registry.h + * PURPOSE: Registry declarations used by all the parts of the + * system + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 25/01/2001: Created + */ + +#ifndef __INCLUDE_NTOS_REGISTRY_H +#define __INCLUDE_NTOS_REGISTRY_H + +/* Key access rights */ +#define KEY_QUERY_VALUE (1) +#define KEY_SET_VALUE (2) +#define KEY_CREATE_SUB_KEY (4) +#define KEY_ENUMERATE_SUB_KEYS (8) +#define KEY_NOTIFY (16) +#define KEY_CREATE_LINK (32) + +#define KEY_READ (0x20019L) +#define KEY_WRITE (0x20006L) +#define KEY_EXECUTE (0x20019L) +#define KEY_ALL_ACCESS (0xf003fL) + +/* Key create options */ +#define REG_OPTION_NON_VOLATILE (0x0L) +#define REG_OPTION_VOLATILE (0x1L) +#define REG_OPTION_CREATE_LINK (0x2L) +#define REG_OPTION_BACKUP_RESTORE (0x8L) +#define REG_OPTION_OPEN_LINK (0x8L) + +/* Key create/open disposition */ +#define REG_CREATED_NEW_KEY (0x1L) +#define REG_OPENED_EXISTING_KEY (0x2L) + +/* Value types */ +#define REG_NONE (0) +#define REG_SZ (1) +#define REG_EXPAND_SZ (2) +#define REG_BINARY (3) +#define REG_DWORD (4) +#define REG_DWORD_LITTLE_ENDIAN (4) +#define REG_DWORD_BIG_ENDIAN (5) +#define REG_LINK (6) +#define REG_MULTI_SZ (7) +#define REG_RESOURCE_LIST (8) +#define REG_FULL_RESOURCE_DESCRIPTOR (9) +#define REG_RESOURCE_REQUIREMENTS_LIST (10) + + +#endif /* __INCLUDE_NTOS_REGISTRY_H */ diff --git a/include/ntos/security.h b/include/ntos/security.h new file mode 100644 index 0000000..c88df82 --- /dev/null +++ b/include/ntos/security.h @@ -0,0 +1,344 @@ +#ifndef __INCLUDE_SECURITY_H +#define __INCLUDE_SECURITY_H + +#include +#include + +/* SID Auhority */ +#define SECURITY_NULL_SID_AUTHORITY {0,0,0,0,0,0} +#define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1} +#define SECURITY_LOCAL_SID_AUTHORITY {0,0,0,0,0,2} +#define SECURITY_CREATOR_SID_AUTHORITY {0,0,0,0,0,3} +#define SECURITY_NON_UNIQUE_AUTHORITY {0,0,0,0,0,4} +#define SECURITY_NT_AUTHORITY {0,0,0,0,0,5} + +/* SID */ +#define SECURITY_NULL_RID (0L) +#define SECURITY_WORLD_RID (0L) +#define SECURITY_LOCAL_RID (0L) +#define SECURITY_CREATOR_OWNER_RID (0L) +#define SECURITY_CREATOR_GROUP_RID (0x1L) +#define SECURITY_CREATOR_OWNER_SERVER_RID (0x2L) +#define SECURITY_CREATOR_GROUP_SERVER_RID (0x3L) +#define SECURITY_DIALUP_RID (0x1L) +#define SECURITY_NETWORK_RID (0x2L) +#define SECURITY_BATCH_RID (0x3L) +#define SECURITY_INTERACTIVE_RID (0x4L) +#define SECURITY_LOGON_IDS_RID (0x5L) +#define SECURITY_LOGON_IDS_RID_COUNT (0x3L) +#define SECURITY_SERVICE_RID (0x6L) +#define SECURITY_ANONYMOUS_LOGON_RID (0x7L) +#define SECURITY_PROXY_RID (0x8L) +#define SECURITY_ENTERPRISE_CONTROLLERS_RID (0x9L) +#define SECURITY_SERVER_LOGON_RID SECURITY_ENTERPRISE_CONTROLLERS_RID +#define SECURITY_PRINCIPAL_SELF_RID (0xAL) +#define SECURITY_AUTHENTICATED_USER_RID (0xBL) +#define SECURITY_RESTRICTED_CODE_RID (0xCL) +#define SECURITY_LOCAL_SYSTEM_RID (0x12L) +#define SECURITY_NT_NON_UNIQUE_RID (0x15L) +#define SECURITY_BUILTIN_DOMAIN_RID (0x20L) +#define DOMAIN_USER_RID_ADMIN (0x1F4L) +#define DOMAIN_USER_RID_GUEST (0x1F5L) +#define DOMAIN_GROUP_RID_ADMINS (0x200L) +#define DOMAIN_GROUP_RID_USERS (0x201L) +#define DOMAIN_ALIAS_RID_ADMINS (0x220L) +#define DOMAIN_ALIAS_RID_USERS (0x221L) +#define DOMAIN_ALIAS_RID_GUESTS (0x222L) +#define DOMAIN_ALIAS_RID_POWER_USERS (0x223L) +#define DOMAIN_ALIAS_RID_ACCOUNT_OPS (0x224L) +#define DOMAIN_ALIAS_RID_SYSTEM_OPS (0x225L) +#define DOMAIN_ALIAS_RID_PRINT_OPS (0x226L) +#define DOMAIN_ALIAS_RID_BACKUP_OPS (0x227L) +#define DOMAIN_ALIAS_RID_REPLICATOR (0x228L) + +/* Privileges */ +#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L) +#define SE_CREATE_TOKEN_PRIVILEGE (2L) +#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L) +#define SE_LOCK_MEMORY_PRIVILEGE (4L) +#define SE_INCREASE_QUOTA_PRIVILEGE (5L) +#define SE_UNSOLICITED_INPUT_PRIVILEGE (6L) /* unused */ +#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L) +#define SE_TCB_PRIVILEGE (7L) +#define SE_SECURITY_PRIVILEGE (8L) +#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L) +#define SE_LOAD_DRIVER_PRIVILEGE (10L) +#define SE_SYSTEM_PROFILE_PRIVILEGE (11L) +#define SE_SYSTEMTIME_PRIVILEGE (12L) +#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L) +#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L) +#define SE_CREATE_PAGEFILE_PRIVILEGE (15L) +#define SE_CREATE_PERMANENT_PRIVILEGE (16L) +#define SE_BACKUP_PRIVILEGE (17L) +#define SE_RESTORE_PRIVILEGE (18L) +#define SE_SHUTDOWN_PRIVILEGE (19L) +#define SE_DEBUG_PRIVILEGE (20L) +#define SE_AUDIT_PRIVILEGE (21L) +#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L) +#define SE_CHANGE_NOTIFY_PRIVILEGE (23L) +#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L) +#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_REMOTE_SHUTDOWN_PRIVILEGE + +#if 0 +/* Security descriptor control. */ +#define SECURITY_DESCRIPTOR_REVISION (1) +#define SECURITY_DESCRIPTOR_MIN_LENGTH (20) +#define SE_OWNER_DEFAULTED (1) +#define SE_GROUP_DEFAULTED (2) +#define SE_DACL_PRESENT (4) +#define SE_DACL_DEFAULTED (8) +#define SE_SACL_PRESENT (16) +#define SE_SACL_DEFAULTED (32) +#define SE_SELF_RELATIVE (32768) +#endif + +/* ACCESS_MASK */ +#define MAXIMUM_ALLOWED (0x2000000L) +#define GENERIC_ALL (0x10000000L) +#define GENERIC_EXECUTE (0x20000000L) + +#define SECURITY_STATIC_TRACKING (0) +#define SECURITY_DYNAMIC_TRACKING (1) + +/* Standard rights */ +#define STANDARD_RIGHTS_REQUIRED (0xf0000L) +#define STANDARD_RIGHTS_WRITE (0x20000L) +#define STANDARD_RIGHTS_READ (0x20000L) +#define STANDARD_RIGHTS_EXECUTE (0x20000L) +#define STANDARD_RIGHTS_ALL (0x1f0000L) +#define SPECIFIC_RIGHTS_ALL (0xffffL) + +/* Token rights */ +#define TOKEN_ASSIGN_PRIMARY (0x0001L) +#define TOKEN_DUPLICATE (0x0002L) +#define TOKEN_IMPERSONATE (0x0004L) +#define TOKEN_QUERY (0x0008L) +#define TOKEN_QUERY_SOURCE (0x0010L) +#define TOKEN_ADJUST_PRIVILEGES (0x0020L) +#define TOKEN_ADJUST_GROUPS (0x0040L) +#define TOKEN_ADJUST_DEFAULT (0x0080L) + +#define TOKEN_ALL_ACCESS (0xf00ffL) +#define TOKEN_READ (0x20008L) +#define TOKEN_WRITE (0x200e0L) +#define TOKEN_EXECUTE (0x20000L) + +typedef BOOL SECURITY_CONTEXT_TRACKING_MODE; + +typedef ULONG SECURITY_INFORMATION, *PSECURITY_INFORMATION; + +typedef enum _TOKEN_INFORMATION_CLASS +{ + TokenUser = 1, + TokenGroups, + TokenPrivileges, + TokenOwner, + TokenPrimaryGroup, + TokenDefaultDacl, + TokenSource, + TokenType, + TokenImpersonationLevel, + TokenStatistics +} TOKEN_INFORMATION_CLASS; + +typedef ULONG SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL; + +#define SecurityAnonymous ((SECURITY_IMPERSONATION_LEVEL)1) +#define SecurityIdentification ((SECURITY_IMPERSONATION_LEVEL)2) +#define SecurityImpersonation ((SECURITY_IMPERSONATION_LEVEL)3) +#define SecurityDelegation ((SECURITY_IMPERSONATION_LEVEL)4) + +typedef ULONG TOKEN_TYPE, *PTOKEN_TYPE; + +#define TokenPrimary ((TOKEN_TYPE)1) +#define TokenImpersonation ((TOKEN_TYPE)2) + +//typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, *PSECURITY_CONTEXT_TRACKING_MODE; + +//#define SECURITY_DYNAMIC_TRACKING (TRUE) +//#define SECURITY_STATIC_TRACKING (FALSE) + +typedef ULONG ACCESS_MASK, *PACCESS_MASK; +typedef ULONG ACCESS_MODE, *PACCESS_MODE; + +typedef struct _SECURITY_QUALITY_OF_SERVICE +{ + ULONG Length; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode; + BOOLEAN EffectiveOnly; +} SECURITY_QUALITY_OF_SERVICE; + +typedef SECURITY_QUALITY_OF_SERVICE* PSECURITY_QUALITY_OF_SERVICE; + +typedef struct _ACE_HEADER +{ + BYTE AceType; + BYTE AceFlags; + WORD AceSize; +} ACE_HEADER, *PACE_HEADER; + +typedef struct +{ + ACE_HEADER Header; + ACCESS_MASK AccessMask; +} ACE, *PACE; + +typedef struct _SID_IDENTIFIER_AUTHORITY +{ + BYTE Value[6]; +} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; + +typedef struct _SID +{ + UCHAR Revision; + UCHAR SubAuthorityCount; + SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + ULONG SubAuthority[1]; +} SID, *PSID; + +typedef struct _ACL +{ + UCHAR AclRevision; + UCHAR Sbz1; + USHORT AclSize; + USHORT AceCount; + USHORT Sbz2; +} ACL, *PACL; + +typedef struct _ACL_REVISION_INFORMATION +{ + ULONG AclRevision; +} ACL_REVISION_INFORMATION, *PACL_REVISION_INFORMATION; + +typedef struct _ACL_SIZE_INFORMATION +{ + ULONG AceCount; + ULONG AclBytesInUse; + ULONG AclBytesFree; +} ACL_SIZE_INFORMATION, *PACL_SIZE_INFORMATION; + +typedef enum _ACL_INFORMATION_CLASS +{ + AclRevisionInformation = 1, + AclSizeInformation +} ACL_INFORMATION_CLASS; + +typedef USHORT SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL; + +typedef struct _SECURITY_DESCRIPTOR_CONTEXT +{ +} SECURITY_DESCRIPTOR_CONTEXT, *PSECURITY_DESCRIPTOR_CONTEXT; + +typedef LARGE_INTEGER LUID, *PLUID; + +typedef struct _SECURITY_DESCRIPTOR +{ + UCHAR Revision; + UCHAR Sbz1; + SECURITY_DESCRIPTOR_CONTROL Control; + PSID Owner; + PSID Group; + PACL Sacl; + PACL Dacl; +} SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR; + +typedef struct _LUID_AND_ATTRIBUTES +{ + LUID Luid; + DWORD Attributes; +} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES; + +typedef struct _TOKEN_SOURCE +{ + CHAR SourceName[8]; + LUID SourceIdentifier; +} TOKEN_SOURCE, *PTOKEN_SOURCE; + +typedef struct _TOKEN_CONTROL +{ + LUID TokenId; + LUID AuthenticationId; + LUID ModifiedId; + TOKEN_SOURCE TokenSource; +} TOKEN_CONTROL, *PTOKEN_CONTROL; + +typedef struct _SID_AND_ATTRIBUTES +{ + PSID Sid; + DWORD Attributes; +} SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES; + +typedef SID_AND_ATTRIBUTES SID_AND_ATTRIBUTES_ARRAY[ANYSIZE_ARRAY]; +typedef SID_AND_ATTRIBUTES_ARRAY *PSID_AND_ATTRIBUTES_ARRAY; + +typedef struct _TOKEN_USER +{ + SID_AND_ATTRIBUTES User; +} TOKEN_USER, *PTOKEN_USER; + +typedef struct _TOKEN_PRIMARY_GROUP +{ + PSID PrimaryGroup; +} TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP; + +typedef struct _TOKEN_GROUPS +{ + DWORD GroupCount; + SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; +} TOKEN_GROUPS, *PTOKEN_GROUPS, *LPTOKEN_GROUPS; + +typedef struct _TOKEN_PRIVILEGES +{ + DWORD PrivilegeCount; + LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; +} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES, *LPTOKEN_PRIVILEGES; + +typedef struct _TOKEN_OWNER +{ + PSID Owner; +} TOKEN_OWNER, *PTOKEN_OWNER; + +typedef struct _TOKEN_DEFAULT_DACL +{ + PACL DefaultDacl; +} TOKEN_DEFAULT_DACL, *PTOKEN_DEFAULT_DACL; + +typedef struct _TOKEN_STATISTICS +{ + LUID TokenId; + LUID AuthenticationId; + LARGE_INTEGER ExpirationTime; + TOKEN_TYPE TokenType; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + DWORD DynamicCharged; + DWORD DynamicAvailable; + DWORD GroupCount; + DWORD PrivilegeCount; + LUID ModifiedId; +} TOKEN_STATISTICS, *PTOKEN_STATISTICS; + +typedef struct _GENERIC_MAPPING +{ + ACCESS_MASK GenericRead; + ACCESS_MASK GenericWrite; + ACCESS_MASK GenericExecute; + ACCESS_MASK GenericAll; +} GENERIC_MAPPING, *PGENERIC_MAPPING; + +typedef struct _PRIVILEGE_SET +{ + DWORD PrivilegeCount; + DWORD Control; + LUID_AND_ATTRIBUTES Privilege[ANYSIZE_ARRAY]; +} PRIVILEGE_SET, *PPRIVILEGE_SET, *LPPRIVILEGE_SET; + +typedef struct _SECURITY_ATTRIBUTES +{ + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; + + +#endif /* __INCLUDE_SECURITY_H */ diff --git a/include/ntos/synch.h b/include/ntos/synch.h new file mode 100644 index 0000000..85d1a3b --- /dev/null +++ b/include/ntos/synch.h @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/ntos/synch.h + * PURPOSE: Synchronization declarations used by all the parts of the + * system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + +#ifndef __INCLUDE_SYNCH_H +#define __INCLUDE_SYNCH_H + + +#define EVENT_ALL_ACCESS (0x1f0003L) +#define EVENT_QUERY_STATE (1) +#define EVENT_MODIFY_STATE (2) +#define EVENT_PAIR_ALL_ACCESS (0x1f0000L) +#define MUTEX_ALL_ACCESS (0x1f0001L) +#define MUTEX_QUERY_STATE (1) +#define MUTANT_ALL_ACCESS (0x1f0001L) +#define MUTANT_QUERY_STATE (1) +#define SEMAPHORE_ALL_ACCESS (0x1f0003L) +#define SEMAPHORE_QUERY_STATE (1) +#define SEMAPHORE_MODIFY_STATE (2) +#define TIMER_ALL_ACCESS (0x1f0003L) +#define TIMER_QUERY_STATE (1) +#define TIMER_MODIFY_STATE (2) + + +#endif /* __INCLUDE_SYNCH_H */ diff --git a/include/ntos/time.h b/include/ntos/time.h new file mode 100644 index 0000000..8387a89 --- /dev/null +++ b/include/ntos/time.h @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/time.h + * PURPOSE: Time declarations used by all the parts of the system + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 27/06/00: Created + */ + + +#ifndef __INCLUDE_NTOS_TIME_H +#define __INCLUDE_NTOS_TIME_H + +#include + +typedef struct _SYSTEMTIME +{ + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; + +typedef struct _TIME_ZONE_INFORMATION +{ + LONG Bias; + WCHAR StandardName[32]; + SYSTEMTIME StandardDate; + LONG StandardBias; + WCHAR DaylightName[32]; + SYSTEMTIME DaylightDate; + LONG DaylightBias; +} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION; + +#endif /* __INCLUDE_NTOS_TIME_H */ diff --git a/include/ntos/types.h b/include/ntos/types.h new file mode 100644 index 0000000..ebdf60f --- /dev/null +++ b/include/ntos/types.h @@ -0,0 +1,432 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/types.h + * PURPOSE: Types used by all the parts of the system + * PROGRAMMER: David Welch + * DEFINES: _WIN64: 64-bit architecture + * _WIN32: 32-bit architecture (default) + * UPDATE HISTORY: + * 27/06/00: Created + * 01/05/01: Portabillity changes + */ + +#ifndef __INCLUDE_TYPES_H +#define __INCLUDE_TYPES_H + +/* Fixed precision types */ +typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +typedef signed int INT32, *PINT32; +typedef signed long long INT64, *PINT64; +typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32; +typedef unsigned long long UINT64, *PUINT64; + +typedef signed long int LONG32, *PLONG32; +typedef unsigned long int ULONG32, *PULONG32; +typedef unsigned long int DWORD32, *PDWORD32; + + +#ifdef _WIN64 + +/* 64-bit architecture */ + +typedef INT64 INT, *PINT; +typedef LONG64 LONG, *PLONG; +typedef DWORD64 DWORD, *PDWORD; +typedef UINT64 UINT, *PUINT; +typedef ULONG64 ULONG, *PULONG; + +/* Pointer precision types */ +typedef long long INT_PTR, *PINT_PTR; +typedef unsigned long long UINT_PTR, *PUINT_PTR; +typedef long long LONG_PTR, *PLONG_PTR; +typedef unsigned long long ULONG_PTR, *PULONG_PTR; +typedef unsigned long long HANDLE_PTR; +typedef unsigned int UHALF_PTR, *PUHALF_PTR; +typedef int HALF_PTR, *PHALF_PTR; + +#else /* _WIN64 */ + +/* 32-bit architecture */ + +typedef INT32 INT, *PINT; +typedef LONG32 LONG, *PLONG; +typedef DWORD32 DWORD, *PDWORD; +typedef UINT32 UINT, *PUINT; +typedef ULONG32 ULONG, *PULONG; + + +/* Pointer precision types */ +typedef int INT_PTR, *PINT_PTR; +typedef unsigned int UINT_PTR, *PUINT_PTR; +typedef long LONG_PTR, *PLONG_PTR; +typedef unsigned long ULONG_PTR, *PULONG_PTR; +typedef unsigned short UHALF_PTR, *PUHALF_PTR; +typedef short HALF_PTR, *PHALF_PTR; +typedef unsigned long HANDLE_PTR; + +#endif /* _WIN64 */ + +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; + +typedef long long LONG64, *PLONG64; + +typedef unsigned long long ULONG64, *PULONG64; +typedef unsigned long long DWORD64, *PDWORD64; + + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned short WCHAR; +typedef unsigned short WORD; +typedef int BOOL; +typedef unsigned char BOOLEAN; +typedef BOOLEAN* PBOOLEAN; +typedef unsigned short *LPWSTR; +typedef unsigned short *PWSTR; +typedef unsigned char *PUCHAR; +typedef unsigned short *PUSHORT; +typedef void *PVOID; +typedef unsigned char BYTE; +typedef void *LPVOID; +typedef float *PFLOAT; +typedef unsigned short *PWCH; +typedef unsigned short *PWORD; + +typedef long long LONGLONG; +typedef unsigned long long ULONGLONG; +typedef long long *PLONGLONG; +typedef unsigned long long *PULONGLONG; + +/* Check VOID before defining CHAR, SHORT */ +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef short SHORT; +#endif + +typedef CHAR *PCHAR; +typedef CHAR *PCH; +typedef void *HANDLE; +typedef char CCHAR; +typedef CCHAR *PCCHAR; + + +#define FALSE 0 +#define TRUE 1 + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void*)0) +#endif /* __cplusplus */ +#endif /* NULL */ + +typedef const unsigned short *PCWSTR; + +typedef char* PCSZ; + +typedef union _LARGE_INTEGER +{ + struct + { + DWORD LowPart; + LONG HighPart; + } u; +#ifdef ANONYMOUSUNIONS + struct + { + DWORD LowPart; + LONG HighPart; + }; +#endif /* ANONYMOUSUNIONS */ + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER +{ + struct + { + DWORD LowPart; + DWORD HighPart; + } u; +#ifdef ANONYMOUSUNIONS + struct + { + DWORD LowPart; + DWORD HighPart; + }; +#endif /* ANONYMOUSUNIONS */ + ULONGLONG QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME, *LPFILETIME, *PFILETIME; + +#define CONST const + +#ifdef i386 +#define STDCALL __attribute__ ((stdcall)) +#define CDECL __attribute((cdecl)) +#define CALLBACK WINAPI +#define PASCAL WINAPI +#else +#define STDCALL +#define CDECL +#define CALLBACK +#define PASCAL +#endif + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _SINGLE_LIST_ENTRY { + struct _SINGLE_LIST_ENTRY *Next; +} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; + +typedef DWORD STDCALL (*PTHREAD_START_ROUTINE) (LPVOID); +typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; + +typedef unsigned short *PWCHAR; + +#ifdef __PPC__ +#define CONTEXT_CONTROL 1L +#define CONTEXT_FLOATING_POINT 2L +#define CONTEXT_INTEGER 4L +#define CONTEXT_DEBUG_REGISTERS 8L + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER) +#define CONTEXT_DEBUGGER (CONTEXT_FULL) + +#else /* x86 */ +/* The doc refered me to winnt.h, so I had to look... */ +#define SIZE_OF_80387_REGISTERS 80 + +/* Values for contextflags */ +#define CONTEXT_i386 0x10000 +#define CONTEXT_CONTROL (CONTEXT_i386 | 1) +#define CONTEXT_INTEGER (CONTEXT_i386 | 2) +#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4) +#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10) +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) + +/* our own invention */ +#define FLAG_TRACE_BIT 0x100 +#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT) + +#endif + +typedef struct _FLOATING_SAVE_AREA { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + BYTE RegisterArea[80]; + DWORD Cr0NpxState; +} FLOATING_SAVE_AREA; + +typedef struct _CONTEXT_X86 { + DWORD ContextFlags; + + DWORD Dr0; + DWORD Dr1; + DWORD Dr2; + DWORD Dr3; + DWORD Dr6; + DWORD Dr7; + + FLOATING_SAVE_AREA FloatSave; + + DWORD SegGs; + DWORD SegFs; + DWORD SegEs; + DWORD SegDs; + + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Edx; + DWORD Ecx; + DWORD Eax; + + DWORD Ebp; + DWORD Eip; + DWORD SegCs; + DWORD EFlags; + DWORD Esp; + DWORD SegSs; +} CONTEXT_X86, *PCONTEXT_X86, *LPCONTEXT_X86; + +typedef struct _CONTEXT_PPC + { + /* Floating point registers returned when CONTEXT_FLOATING_POINT is set */ + double Fpr0; + double Fpr1; + double Fpr2; + double Fpr3; + double Fpr4; + double Fpr5; + double Fpr6; + double Fpr7; + double Fpr8; + double Fpr9; + double Fpr10; + double Fpr11; + double Fpr12; + double Fpr13; + double Fpr14; + double Fpr15; + double Fpr16; + double Fpr17; + double Fpr18; + double Fpr19; + double Fpr20; + double Fpr21; + double Fpr22; + double Fpr23; + double Fpr24; + double Fpr25; + double Fpr26; + double Fpr27; + double Fpr28; + double Fpr29; + double Fpr30; + double Fpr31; + double Fpscr; + + /* Integer registers returned when CONTEXT_INTEGER is set. */ + DWORD Gpr0; + DWORD Gpr1; + DWORD Gpr2; + DWORD Gpr3; + DWORD Gpr4; + DWORD Gpr5; + DWORD Gpr6; + DWORD Gpr7; + DWORD Gpr8; + DWORD Gpr9; + DWORD Gpr10; + DWORD Gpr11; + DWORD Gpr12; + DWORD Gpr13; + DWORD Gpr14; + DWORD Gpr15; + DWORD Gpr16; + DWORD Gpr17; + DWORD Gpr18; + DWORD Gpr19; + DWORD Gpr20; + DWORD Gpr21; + DWORD Gpr22; + DWORD Gpr23; + DWORD Gpr24; + DWORD Gpr25; + DWORD Gpr26; + DWORD Gpr27; + DWORD Gpr28; + DWORD Gpr29; + DWORD Gpr30; + DWORD Gpr31; + + DWORD Cr; /* Condition register */ + DWORD Xer; /* Fixed point exception register */ + + /* The following are set when CONTEXT_CONTROL is set. */ + DWORD Msr; /* Machine status register */ + DWORD Iar; /* Instruction address register */ + DWORD Lr; /* Link register */ + DWORD Ctr; /* Control register */ + + /* Control which context values are returned */ + DWORD ContextFlags; + DWORD Fill[3]; + + /* Registers returned if CONTEXT_DEBUG_REGISTERS is set. */ + DWORD Dr0; /* Breakpoint Register 1 */ + DWORD Dr1; /* Breakpoint Register 2 */ + DWORD Dr2; /* Breakpoint Register 3 */ + DWORD Dr3; /* Breakpoint Register 4 */ + DWORD Dr4; /* Breakpoint Register 5 */ + DWORD Dr5; /* Breakpoint Register 6 */ + DWORD Dr6; /* Debug Status Register */ + DWORD Dr7; /* Debug Control Register */ +} CONTEXT_PPC, *PCONTEXT_PPC, *LPCONTEXT_PPC; + +#ifdef __i386__ + +typedef CONTEXT_X86 CONTEXT; +typedef PCONTEXT_X86 PCONTEXT; +typedef LPCONTEXT_X86 LPCONTEXT; + +#else /* __ppc__ */ + +typedef CONTEXT_PPC CONTEXT; +typedef PCONTEXT_PPC PCONTEXT; +typedef LPCONTEXT_PPC LPCONTEXT; + +#endif + +typedef HANDLE *PHANDLE; + +typedef struct value_ent { + LPWSTR ve_valuename; + DWORD ve_valuelen; + DWORD ve_valueptr; + DWORD ve_type; +} WVALENT, *PWVALENT; + + +typedef const void *LPCVOID; +typedef BYTE *LPBYTE, *PBYTE; + +typedef BOOL *PBOOL; + +typedef DWORD LCID; +typedef DWORD *PLCID; + +typedef const char *LPCSTR; + +typedef char *LPSTR; + +typedef const unsigned short *LPCWSTR; + +typedef unsigned short RTL_ATOM; +typedef unsigned short *PRTL_ATOM; +typedef WORD ATOM; + +typedef struct _COORD { + SHORT X; + SHORT Y; +} COORD; + +typedef struct _SMALL_RECT { + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; +} SMALL_RECT, *PSMALL_RECT; + + +typedef VOID STDCALL +(*PTIMERAPCROUTINE)( + LPVOID lpArgToCompletionRoutine, + DWORD dwTimerLowValue, + DWORD dwTimerHighValue + ); + +#include "except.h" + +#endif /* __INCLUDE_TYPES_H */ diff --git a/include/ole32/basetyps.h b/include/ole32/basetyps.h new file mode 100644 index 0000000..b98ded1 --- /dev/null +++ b/include/ole32/basetyps.h @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include\ole32\basetyps.h + * PURPOSE: Base type and interface macros + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 05/01/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#ifndef _BASETYPS +#define _BASETYPS + +#include + + +#endif + diff --git a/include/ole32/guiddef.h b/include/ole32/guiddef.h new file mode 100644 index 0000000..9e10326 --- /dev/null +++ b/include/ole32/guiddef.h @@ -0,0 +1,183 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include\ole32\guiddef.h + * PURPOSE: Guid definition macros + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 05/01/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#ifndef _GUIDDEF_H +#define _GUIDDEF_H + +#include + + +#ifndef EXTERN_C + #ifdef __cplusplus + #define EXTERN_C extern "C" + #else + #define EXTERN_C extern + #endif +#endif + + +// guid definition +#ifndef _GUID_DEFINED + #define _GUID_DEFINED + typedef struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; + } GUID; + typedef GUID* LPGUID; + typedef const GUID* LPCGUID; +#endif + + +// guid definition macro +#ifdef DEFINE_GUID + #undef DEFINE_GUID +#endif + +#ifdef INITGUID + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}} +#else + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + const GUID name +#endif +#define DEFINE_OLEGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46) + + +// IID section +typedef GUID IID; +typedef IID* LPIID; +#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) + + +// CLSID section +typedef GUID CLSID; +typedef CLSID* LPCLSID; +#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) + +// FMTID +typedef GUID FMTID; +typedef FMTID* LPFMTID; +#define IsEqualFMTID(rfmtid1, rfmtid2) IsEqualGUID(rfmtid1, rfmtid2) + + +// REFGUID section +#ifndef _REFGUID_DEFINED + #define _REFGUID_DEFINED + #ifdef __cplusplus + #define REFGUID const GUID & + #else + #define REFGUID const GUID * + #endif +#endif + +// REFIID section +#ifndef _REFIID_DEFINED + #define _REFIID_DEFINED + #ifdef __cplusplus + #define REFIID const IID & + #else + #define REFIID const IID * + #endif +#endif + +// REFCLSID section +#ifndef _REFCLSID_DEFINED + #define _REFCLSID_DEFINED + #ifdef __cplusplus + #define REFCLSID const IID & + #else + #define REFCLSID const IID * + #endif +#endif + +// REFFMTID section +#ifndef _REFFMTID_DEFINED + #define _REFFMTID_DEFINED + #ifdef __cplusplus + #define REFFMTID const IID & + #else + #define REFFMTID const IID * + #endif +#endif + + +// compare functions for GUID +#ifdef __cplusplus + // cpp versions + __inline int InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2) + { + return(((unsigned long *) &rguid1)[0] == ((unsigned long *) &rguid2)[0] && + ((unsigned long *) &rguid1)[1] == ((unsigned long *) &rguid2)[1] && + ((unsigned long *) &rguid1)[2] == ((unsigned long *) &rguid2)[2] && + ((unsigned long *) &rguid1)[3] == ((unsigned long *) &rguid2)[3]); + } + __inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) + { + return !memcmp(&rguid1, &rguid2, sizeof(GUID)); + } +#else + // c versions + #define InlineIsEqualGUID(rguid1, rguid2) \ + (((unsigned long *) rguid1)[0] == ((unsigned long *) rguid2)[0] && \ + ((unsigned long *) rguid1)[1] == ((unsigned long *) rguid2)[1] && \ + ((unsigned long *) rguid1)[2] == ((unsigned long *) rguid2)[2] && \ + ((unsigned long *) rguid1)[3] == ((unsigned long *) rguid2)[3]) + + #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID))) +#endif + +// use the inline version??? +#ifdef __INLINE_ISEQUAL_GUID + #define IsEqualGUID(rguid1, rguid2) InlineIsEqualGUID(rguid1, rguid2) +#endif + + +// compare functions for IID CLSID +#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) +#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) + +// c++ helper functions +#if !defined _SYS_GUID_OPERATOR_EQ_ && !defined _NO_SYS_GUID_OPERATOR_EQ_ + #define _SYS_GUID_OPERATOR_EQ_ + #ifdef __cplusplus + __inline int operator==(REFGUID guidOne, REFGUID guidTwo) + { + return IsEqualGUID(guidOne ,guidTwo); + } + + __inline int operator!=(REFGUID guidOne, REFGUID guidTwo) + { + return !(guidOne == guidTwo); + } + #endif +#endif + +#endif diff --git a/include/ole32/obj_base.h b/include/ole32/obj_base.h new file mode 100644 index 0000000..da69ab5 --- /dev/null +++ b/include/ole32/obj_base.h @@ -0,0 +1,680 @@ +/* + * This file defines the macros and types necessary to define COM interfaces, + * and the three most basic COM interfaces: IUnknown, IMalloc and IClassFactory. + */ + +#ifndef __WINE_WINE_OBJ_BASE_H +#define __WINE_WINE_OBJ_BASE_H + +/***************************************************************************** + * define ICOM_MSVTABLE_COMPAT + * to implement the microsoft com vtable compatibility workaround for g++. + * + * NOTE: Turning this option on will produce a winelib that is incompatible + * with the binary emulator. + * + * If the compiler supports the com_interface attribute, leave this off, and + * define the ICOM_USE_COM_INTERFACE_ATTRIBUTE macro below. This may also + * require the addition of the -vtable-thunks option for g++. + * + * If you aren't interested in Winelib C++ compatibility at all, leave both + * options off. + * + * The preferable method for using ICOM_USE_COM_INTERFACE_ATTRIBUTE macro + * would be to define it only for your Winelib application. This allows you + * to have both binary and Winelib compatibility for C and C++ at the same + * time :) + */ +/* #define ICOM_MSVTABLE_COMPAT 1 */ +/* #define ICOM_USE_COM_INTERFACE_ATTRIBUTE 1 */ + +/***************************************************************************** + * Defines the basic types + */ +#include "wtypes.h" +#include "guiddef.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef NONAMELESSSTRUCT +#define LISet32(li, v) ((li).HighPart = (v) < 0 ? -1 : 0, (li).LowPart = (v)) +#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v)) +#else +#define LISet32(li, v) ((li).s.HighPart = (v) < 0 ? -1 : 0, (li).s.LowPart = (v)) +#define ULISet32(li, v) ((li).s.HighPart = 0, (li).s.LowPart = (v)) +#endif + +/***************************************************************************** + * GUID API + */ +HRESULT WINAPI StringFromCLSID16(REFCLSID id, LPOLESTR16*); +HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR*); + +HRESULT WINAPI CLSIDFromString16(LPCOLESTR16, CLSID *); +HRESULT WINAPI CLSIDFromString(LPCOLESTR, CLSID *); + +HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid); +HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid); + +HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID); + + +INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax); + + +/***************************************************************************** + * Macros to define a COM interface + */ +/* + * The goal of the following set of definitions is to provide a way to use the same + * header file definitions to provide both a C interface and a C++ object oriented + * interface to COM interfaces. The type of interface is selected automatically + * depending on the language but it is always possible to get the C interface in C++ + * by defining CINTERFACE. + * + * It is based on the following assumptions: + * - all COM interfaces derive from IUnknown, this should not be a problem. + * - the header file only defines the interface, the actual fields are defined + * separately in the C file implementing the interface. + * + * The natural approach to this problem would be to make sure we get a C++ class and + * virtual methods in C++ and a structure with a table of pointer to functions in C. + * Unfortunately the layout of the virtual table is compiler specific, the layout of + * g++ virtual tables is not the same as that of an egcs virtual table which is not the + * same as that generated by Visual C+. There are workarounds to make the virtual tables + * compatible via padding but unfortunately the one which is imposed to the WINE emulator + * by the Windows binaries, i.e. the Visual C++ one, is the most compact of all. + * + * So the solution I finally adopted does not use virtual tables. Instead I use inline + * non virtual methods that dereference the method pointer themselves and perform the call. + * + * Let's take Direct3D as an example: + * + * #define ICOM_INTERFACE IDirect3D + * #define IDirect3D_METHODS \ + * ICOM_METHOD1(HRESULT,Initialize, REFIID,) \ + * ICOM_METHOD2(HRESULT,EnumDevices, LPD3DENUMDEVICESCALLBACK,, LPVOID,) \ + * ICOM_METHOD2(HRESULT,CreateLight, LPDIRECT3DLIGHT*,, IUnknown*,) \ + * ICOM_METHOD2(HRESULT,CreateMaterial,LPDIRECT3DMATERIAL*,, IUnknown*,) \ + * ICOM_METHOD2(HRESULT,CreateViewport,LPDIRECT3DVIEWPORT*,, IUnknown*,) \ + * ICOM_METHOD2(HRESULT,FindDevice, LPD3DFINDDEVICESEARCH,, LPD3DFINDDEVICERESULT,) + * #define IDirect3D_IMETHODS \ + * IUnknown_IMETHODS \ + * IDirect3D_METHODS + * ICOM_DEFINE(IDirect3D,IUnknown) + * #undef ICOM_INTERFACE + * + * #ifdef ICOM_CINTERFACE + * // *** IUnknown methods *** // + * #define IDirect3D_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) + * #define IDirect3D_AddRef(p) ICOM_CALL (AddRef,p) + * #define IDirect3D_Release(p) ICOM_CALL (Release,p) + * // *** IDirect3D methods *** // + * #define IDirect3D_Initialize(p,a) ICOM_CALL1(Initialize,p,a) + * #define IDirect3D_EnumDevices(p,a,b) ICOM_CALL2(EnumDevice,p,a,b) + * #define IDirect3D_CreateLight(p,a,b) ICOM_CALL2(CreateLight,p,a,b) + * #define IDirect3D_CreateMaterial(p,a,b) ICOM_CALL2(CreateMaterial,p,a,b) + * #define IDirect3D_CreateViewport(p,a,b) ICOM_CALL2(CreateViewport,p,a,b) + * #define IDirect3D_FindDevice(p,a,b) ICOM_CALL2(FindDevice,p,a,b) + * #endif + * + * Comments: + * - The ICOM_INTERFACE macro is used in the ICOM_METHOD macros to define the type of the 'this' + * pointer. Defining this macro here saves us the trouble of having to repeat the interface + * name everywhere. Note however that because of the way macros work, a macro like ICOM_METHOD1 + * cannot use 'ICOM_INTERFACE##_VTABLE' because this would give 'ICOM_INTERFACE_VTABLE' and not + * 'IDirect3D_VTABLE'. + * - ICOM_METHODS defines the methods specific to this interface. It is then aggregated with the + * inherited methods to form ICOM_IMETHODS. + * - ICOM_IMETHODS defines the list of methods that are inheritable from this interface. It must + * be written manually (rather than using a macro to generate the equivalent code) to avoid + * macro recursion (which compilers don't like). + * - The ICOM_DEFINE finally declares all the structures necessary for the interface. We have to + * explicitly use the interface name for macro expansion reasons again. + * Inherited methods are inherited in C by using the IDirect3D_METHODS macro and the parent's + * Xxx_IMETHODS macro. In C++ we need only use the IDirect3D_METHODS since method inheritance + * is taken care of by the language. + * - In C++ the ICOM_METHOD macros generate a function prototype and a call to a function pointer + * method. This means using once 't1 p1, t2 p2, ...' and once 'p1, p2' without the types. The + * only way I found to handle this is to have one ICOM_METHOD macro per number of parameters and + * to have it take only the type information (with const if necessary) as parameters. + * The 'undef ICOM_INTERFACE' is here to remind you that using ICOM_INTERFACE in the following + * macros will not work. This time it's because the ICOM_CALL macro expansion is done only once + * the 'IDirect3D_Xxx' macro is expanded. And by that time ICOM_INTERFACE will be long gone + * anyway. + * - You may have noticed the double commas after each parameter type. This allows you to put the + * name of that parameter which I think is good for documentation. It is not required and since + * I did not know what to put there for this example (I could only find doc about IDirect3D2), + * I left them blank. + * - Finally the set of 'IDirect3D_Xxx' macros is a standard set of macros defined to ease access + * to the interface methods in C. Unfortunately I don't see any way to avoid having to duplicate + * the inherited method definitions there. This time I could have used a trick to use only one + * macro whatever the number of parameters but I prefered to have it work the same way as above. + * - You probably have noticed that we don't define the fields we need to actually implement this + * interface: reference count, pointer to other resources and miscellaneous fields. That's + * because these interfaces are just that: interfaces. They may be implemented more than once, in + * different contexts and sometimes not even in Wine. Thus it would not make sense to impose + * that the interface contains some specific fields. + * + * + * In C this gives: + * typedef struct IDirect3DVtbl IDirect3DVtbl; + * struct IDirect3D { + * IDirect3DVtbl* lpVtbl; + * }; + * struct IDirect3DVtbl { + * HRESULT (*QueryInterface)(IDirect3D* me, REFIID riid, LPVOID* ppvObj); + * ULONG (*QueryInterface)(IDirect3D* me); + * ULONG (*QueryInterface)(IDirect3D* me); + * HRESULT (*Initialize)(IDirect3D* me, REFIID a); + * HRESULT (*EnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b); + * HRESULT (*CreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b); + * HRESULT (*CreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b); + * HRESULT (*CreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b); + * HRESULT (*FindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b); + * }; + * + * #ifdef ICOM_CINTERFACE + * // *** IUnknown methods *** // + * #define IDirect3D_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) + * #define IDirect3D_AddRef(p) (p)->lpVtbl->AddRef(p) + * #define IDirect3D_Release(p) (p)->lpVtbl->Release(p) + * // *** IDirect3D methods *** // + * #define IDirect3D_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) + * #define IDirect3D_EnumDevices(p,a,b) (p)->lpVtbl->EnumDevice(p,a,b) + * #define IDirect3D_CreateLight(p,a,b) (p)->lpVtbl->CreateLight(p,a,b) + * #define IDirect3D_CreateMaterial(p,a,b) (p)->lpVtbl->CreateMaterial(p,a,b) + * #define IDirect3D_CreateViewport(p,a,b) (p)->lpVtbl->CreateViewport(p,a,b) + * #define IDirect3D_FindDevice(p,a,b) (p)->lpVtbl->FindDevice(p,a,b) + * #endif + * + * Comments: + * - IDirect3D only contains a pointer to the IDirect3D virtual/jump table. This is the only thing + * the user needs to know to use the interface. Of course the structure we will define to + * implement this interface will have more fields but the first one will match this pointer. + * - The code generated by ICOM_DEFINE defines both the structure representing the interface and + * the structure for the jump table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to + * automatically repeat the prototypes of all the inherited methods and then uses IDirect3D_METHODS + * to define the IDirect3D methods. + * - Each method is declared as a pointer to function field in the jump table. The implementation + * will fill this jump table with appropriate values, probably using a static variable, and + * initialize the lpVtbl field to point to this variable. + * - The IDirect3D_Xxx macros then just derefence the lpVtbl pointer and use the function pointer + * corresponding to the macro name. This emulates the behavior of a virtual table and should be + * just as fast. + * - This C code should be quite compatible with the Windows headers both for code that uses COM + * interfaces and for code implementing a COM interface. + * + * + * And in C++ (with gcc's g++): + * + * typedef struct IDirect3D: public IUnknown { + * private: HRESULT (*Initialize)(IDirect3D* me, REFIID a); + * public: inline HRESULT Initialize(REFIID a) { return ((IDirect3D*)t.lpVtbl)->Initialize(this,a); }; + * private: HRESULT (*EnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b); + * public: inline HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK a, LPVOID b) + * { return ((IDirect3D*)t.lpVtbl)->EnumDevices(this,a,b); }; + * private: HRESULT (*freateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b); + * public: inline HRESULT CreateLight(LPDIRECT3DLIGHT* a, IUnknown* b) + * { return ((IDirect3D*)t.lpVtbl)->CreateLight(this,a,b); }; + * private: HRESULT (*CreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b); + * public: inline HRESULT CreateMaterial(LPDIRECT3DMATERIAL* a, IUnknown* b) + * { return ((IDirect3D*)t.lpVtbl)->CreateMaterial(this,a,b); }; + * private: HRESULT (*CreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b); + * public: inline HRESULT CreateViewport(LPDIRECT3DVIEWPORT* a, IUnknown* b) + * { return ((IDirect3D*)t.lpVtbl)->CreateViewport(this,a,b); }; + * private: HRESULT (*FindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b); + * public: inline HRESULT FindDevice(LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b) + * { return ((IDirect3D*)t.lpVtbl)->FindDevice(this,a,b); }; + * }; + * + * Comments: + * - In C++ IDirect3D does double duty as both the virtual/jump table and as the interface + * definition. The reason for this is to avoid having to duplicate the mehod definitions: once + * to have the function pointers in the jump table and once to have the methods in the interface + * class. Here one macro can generate both. This means though that the first pointer, t.lpVtbl + * defined in IUnknown, must be interpreted as the jump table pointer if we interpret the + * structure as the the interface class, and as the function pointer to the QueryInterface + * method, t.QueryInterface, if we interpret the structure as the jump table. Fortunately this + * gymnastic is entirely taken care of in the header of IUnknown. + * - Of course in C++ we use inheritance so that we don't have to duplicate the method definitions. + * - Since IDirect3D does double duty, each ICOM_METHOD macro defines both a function pointer and + * a non-vritual inline method which dereferences it and calls it. This way this method behaves + * just like a virtual method but does not create a true C++ virtual table which would break the + * structure layout. If you look at the implementation of these methods you'll notice that they + * would not work for void functions. We have to return something and fortunately this seems to + * be what all the COM methods do (otherwise we would need another set of macros). + * - Note how the ICOM_METHOD generates both function prototypes mixing types and formal parameter + * names and the method invocation using only the formal parameter name. This is the reason why + * we need different macros to handle different numbers of parameters. + * - Finally there is no IDirect3D_Xxx macro. These are not needed in C++ unless the CINTERFACE + * macro is defined in which case we would not be here. + * - This C++ code works well for code that just uses COM interfaces. But it will not work with + * C++ code implement a COM interface. That's because such code assumes the interface methods + * are declared as virtual C++ methods which is not the case here. + * + * + * Implementing a COM interface. + * + * This continues the above example. This example assumes that the implementation is in C. + * + * typedef struct _IDirect3D { + * void* lpVtbl; + * // ... + * + * } _IDirect3D; + * + * static ICOM_VTABLE(IDirect3D) d3dvt; + * + * // implement the IDirect3D methods here + * + * int IDirect3D_QueryInterface(IDirect3D* me) + * { + * ICOM_THIS(IDirect3D,me); + * // ... + * } + * + * // ... + * + * static ICOM_VTABLE(IDirect3D) d3dvt = { + * ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + * IDirect3D_QueryInterface, + * IDirect3D_Add, + * IDirect3D_Add2, + * IDirect3D_Initialize, + * IDirect3D_SetWidth + * }; + * + * Comments: + * - We first define what the interface really contains. This is th e_IDirect3D structure. The + * first field must of course be the virtual table pointer. Everything else is free. + * - Then we predeclare our static virtual table variable, we will need its address in some + * methods to initialize the virtual table pointer of the returned interface objects. + * - Then we implement the interface methods. To match what has been declared in the header file + * they must take a pointer to a IDirect3D structure and we must cast it to an _IDirect3D so that + * we can manipulate the fields. This is performed by the ICOM_THIS macro. + * - Finally we initialize the virtual table. + */ + + + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define ICOM_CINTERFACE 1 +#endif + +#ifndef ICOM_CINTERFACE +/* C++ interface */ + +#define ICOM_METHOD(ret,xfn) \ + public: virtual ret CALLBACK (xfn)(void) = 0; +#define ICOM_METHOD1(ret,xfn,ta,na) \ + public: virtual ret CALLBACK (xfn)(ta a) = 0; +#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b) = 0; +#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c) = 0; +#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d) = 0; +#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e) = 0; +#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f) = 0; +#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g) = 0; +#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h) = 0; +#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i) = 0; +#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j) = 0; +#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \ + public: virtual ret CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k) = 0; + + +#define ICOM_VMETHOD(xfn) \ + public: virtual void CALLBACK (xfn)(void) = 0; +#define ICOM_VMETHOD1(xfn,ta,na) \ + public: virtual void CALLBACK (xfn)(ta a) = 0; +#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \ + public: virtual void CALLBACK (xfn)(ta a,tb b) = 0; +#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c) = 0; +#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d) = 0; +#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e) = 0; +#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f) = 0; +#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g) = 0; +#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h) = 0; +#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i) = 0; +#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i, tj j) = 0; +#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \ + public: virtual void CALLBACK (xfn)(ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i, tj j, tk k) = 0; + + +#ifdef ICOM_USE_COM_INTERFACE_ATTRIBUTE + +#define ICOM_DEFINE(iface,ibase) \ + typedef struct iface: public ibase { \ + iface##_METHODS \ + } __attribute__ ((com_interface)); + +#else + +#define ICOM_DEFINE(iface,ibase) \ + typedef struct iface: public ibase { \ + iface##_METHODS \ + }; + +#endif /* ICOM_USE_COM_INTERFACE_ATTRIBUTE */ + +#define ICOM_VTBL(iface) (iface) + +#else +/* C interface */ + +#define ICOM_METHOD(ret,xfn) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me); +#define ICOM_METHOD1(ret,xfn,ta,na) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a); +#define ICOM_METHOD2(ret,xfn,ta,na,tb,nb) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b); +#define ICOM_METHOD3(ret,xfn,ta,na,tb,nb,tc,nc) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c); +#define ICOM_METHOD4(ret,xfn,ta,na,tb,nb,tc,nc,td,nd) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d); +#define ICOM_METHOD5(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e); +#define ICOM_METHOD6(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f); +#define ICOM_METHOD7(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g); +#define ICOM_METHOD8(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h); +#define ICOM_METHOD9(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i); +#define ICOM_METHOD10(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j); +#define ICOM_METHOD11(ret,xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,tk,nk) \ + ret CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k); + +#define ICOM_VMETHOD(xfn) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me); +#define ICOM_VMETHOD1(xfn,ta,na) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a); +#define ICOM_VMETHOD2(xfn,ta,na,tb,nb) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b); +#define ICOM_VMETHOD3(xfn,ta,na,tb,nb,tc,nc) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c); +#define ICOM_VMETHOD4(xfn,ta,na,tb,nb,tc,nc,td,nd) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d); +#define ICOM_VMETHOD5(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e); +#define ICOM_VMETHOD6(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f); +#define ICOM_VMETHOD7(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g); +#define ICOM_VMETHOD8(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,nh) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h); +#define ICOM_VMETHOD9(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ni) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i); +#define ICOM_VMETHOD10(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,nj) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j); +#define ICOM_VMETHOD11(xfn,ta,na,tb,nb,tc,nc,td,nd,te,ne,tf,nf,tg,ng,th,nh,ti,ni,tj,nj,nk) \ + void CALLBACK (*xfn)(ICOM_INTERFACE* me,ta a,tb b,tc c,td d,te e,tf f,tg g,th h,ti i,tj j,tk k); + + +#define ICOM_VTABLE(iface) iface##Vtbl +#define ICOM_VFIELD(iface) ICOM_VTABLE(iface)* lpVtbl +#define ICOM_VTBL(iface) (iface)->lpVtbl + +#ifdef ICOM_MSVTABLE_COMPAT +#define ICOM_DEFINE(iface,ibase) \ + typedef struct ICOM_VTABLE(iface) ICOM_VTABLE(iface); \ + struct iface { \ + const ICOM_VFIELD(iface); \ + }; \ + struct ICOM_VTABLE(iface) { \ + long dummyRTTI1; \ + long dummyRTTI2; \ + ibase##_IMETHODS \ + iface##_METHODS \ + }; +#define ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE 0,0, + +#else +#define ICOM_DEFINE(iface,ibase) \ + typedef struct ICOM_VTABLE(iface) ICOM_VTABLE(iface); \ + struct iface { \ + const ICOM_VFIELD(iface); \ + }; \ + struct ICOM_VTABLE(iface) { \ + ibase##_IMETHODS \ + iface##_METHODS \ + }; +#define ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE +#endif /* ICOM_MSVTABLE_COMPAT */ + + +#define ICOM_THIS(impl,iface) impl* const This=(impl*)iface +#define ICOM_CTHIS(impl,iface) const impl* const This=(const impl*)iface + +#endif /*ICOM_CINTERFACE */ + +#define ICOM_CALL(xfn, p) ICOM_VTBL(p)->xfn(p) +#define ICOM_CALL1(xfn, p,a) ICOM_VTBL(p)->xfn(p,a) +#define ICOM_CALL2(xfn, p,a,b) ICOM_VTBL(p)->xfn(p,a,b) +#define ICOM_CALL3(xfn, p,a,b,c) ICOM_VTBL(p)->xfn(p,a,b,c) +#define ICOM_CALL4(xfn, p,a,b,c,d) ICOM_VTBL(p)->xfn(p,a,b,c,d) +#define ICOM_CALL5(xfn, p,a,b,c,d,e) ICOM_VTBL(p)->xfn(p,a,b,c,d,e) +#define ICOM_CALL6(xfn, p,a,b,c,d,e,f) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f) +#define ICOM_CALL7(xfn, p,a,b,c,d,e,f,g) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g) +#define ICOM_CALL8(xfn, p,a,b,c,d,e,f,g,h) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h) +#define ICOM_CALL9(xfn, p,a,b,c,d,e,f,g,h,i) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i) +#define ICOM_CALL10(xfn, p,a,b,c,d,e,f,g,h,i,j) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i,j) +#define ICOM_CALL11(xfn, p,a,b,c,d,e,f,g,h,i,j,k) ICOM_VTBL(p)->xfn(p,a,b,c,d,e,f,g,h,i,j,k) + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0); +typedef struct IClassFactory IClassFactory, *LPCLASSFACTORY; + +DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0); +typedef struct IMalloc IMalloc,*LPMALLOC; + +DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0); +typedef struct IUnknown IUnknown, *LPUNKNOWN; + + +/***************************************************************************** + * IUnknown interface + */ +#define ICOM_INTERFACE IUnknown +#define IUnknown_IMETHODS \ + ICOM_METHOD2(HRESULT,QueryInterface,REFIID,riid, LPVOID*,ppvObj) \ + ICOM_METHOD (ULONG,AddRef) \ + ICOM_METHOD (ULONG,Release) +#ifdef ICOM_CINTERFACE +typedef struct ICOM_VTABLE(IUnknown) ICOM_VTABLE(IUnknown); +struct IUnknown { + ICOM_VFIELD(IUnknown); +#if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE) +} __attribute__ ((com_interface)); +#else +}; +#endif /* ICOM_US_COM_INTERFACE_ATTRIBUTE */ + +struct ICOM_VTABLE(IUnknown) { +#ifdef ICOM_MSVTABLE_COMPAT + long dummyRTTI1; + long dummyRTTI2; +#endif /* ICOM_MSVTABLE_COMPAT */ + +#else /* ICOM_CINTERFACE */ +struct IUnknown { + +#endif /* ICOM_CINTERFACE */ + + ICOM_METHOD2(HRESULT,QueryInterface,REFIID,riid, LPVOID*,ppvObj) + ICOM_METHOD (ULONG,AddRef) + ICOM_METHOD (ULONG,Release) +#if defined(ICOM_USE_COM_INTERFACE_ATTRIBUTE) +} __attribute__ ((com_interface)); +#else +}; +#endif /* ICOM_US_COM_INTERFACE_ATTRIBUTE */ + +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IUnknown_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IUnknown_AddRef(p) ICOM_CALL (AddRef,p) +#define IUnknown_Release(p) ICOM_CALL (Release,p) + +/***************************************************************************** + * IClassFactory interface + */ +#define ICOM_INTERFACE IClassFactory +#define IClassFactory_METHODS \ + ICOM_METHOD3(HRESULT,CreateInstance, LPUNKNOWN,pUnkOuter, REFIID,riid, LPVOID*,ppvObject) \ + ICOM_METHOD1(HRESULT,LockServer, BOOL,fLock) +#define IClassFactory_IMETHODS \ + IUnknown_IMETHODS \ + IClassFactory_METHODS +ICOM_DEFINE(IClassFactory,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IClassFactory_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IClassFactory_AddRef(p) ICOM_CALL (AddRef,p) +#define IClassFactory_Release(p) ICOM_CALL (Release,p) +/*** IClassFactory methods ***/ +#define IClassFactory_CreateInstance(p,a,b,c) ICOM_CALL3(CreateInstance,p,a,b,c) +#define IClassFactory_LockServer(p,a) ICOM_CALL1(LockServer,p,a) + + +/***************************************************************************** + * IMalloc interface + */ +#define ICOM_INTERFACE IMalloc +#define IMalloc_METHODS \ + ICOM_METHOD1 (LPVOID,Alloc, DWORD,cb) \ + ICOM_METHOD2 (LPVOID,Realloc, LPVOID,pv, DWORD,cb) \ + ICOM_VMETHOD1( Free, LPVOID,pv) \ + ICOM_METHOD1(DWORD, GetSize, LPVOID,pv) \ + ICOM_METHOD1(INT, DidAlloc, LPVOID,pv) \ + ICOM_METHOD (VOID, HeapMinimize) +#define IMalloc_IMETHODS \ + IUnknown_IMETHODS \ + IMalloc_METHODS +ICOM_DEFINE(IMalloc,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IMalloc_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IMalloc_AddRef(p) ICOM_CALL (AddRef,p) +#define IMalloc_Release(p) ICOM_CALL (Release,p) +/*** IMalloc methods ***/ +#define IMalloc_Alloc(p,a) ICOM_CALL1(Alloc,p,a) +#define IMalloc_Realloc(p,a,b) ICOM_CALL2(Realloc,p,a,b) +#define IMalloc_Free(p,a) ICOM_CALL1(Free,p,a) +#define IMalloc_GetSize(p,a) ICOM_CALL1(GetSize,p,a) +#define IMalloc_DidAlloc(p,a) ICOM_CALL1(DidAlloc,p,a) +#define IMalloc_HeapMinimize(p) ICOM_CALL (HeapMinimize,p) + +/* values passed to CoGetMalloc */ +#define MEMCTX_TASK 1 /* private task memory */ +#define MEMCTX_SHARED 2 /* shared memory */ +#ifdef _MAC +#define MEMCTX_MACSYSTEM 3 /* system heap on mac */ +#endif +/* mainly for internal use... */ +#define MEMCTX_UNKNOWN -1 +#define MEMCTX_SAME -2 + +HRESULT WINAPI CoGetMalloc(DWORD dwMemContext,LPMALLOC* lpMalloc); + +LPVOID WINAPI CoTaskMemAlloc(ULONG size); + +void WINAPI CoTaskMemFree(LPVOID ptr); + +/* FIXME: unimplemented */ +LPVOID WINAPI CoTaskMemRealloc(LPVOID ptr, ULONG size); + + +/***************************************************************************** + * Additional API + */ + +typedef enum tagCOINIT +{ + COINIT_APARTMENTTHREADED = 0x2, /* Apartment model */ + COINIT_MULTITHREADED = 0x0, /* OLE calls objects on any thread */ + COINIT_DISABLE_OLE1DDE = 0x4, /* Don't use DDE for Ole1 support */ + COINIT_SPEED_OVER_MEMORY = 0x8 /* Trade memory for speed */ +} COINIT; + +HRESULT WINAPI CoCreateGuid(GUID* pguid); + +HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree); + +VOID WINAPI CoFreeAllLibraries(VOID); + +VOID WINAPI CoFreeLibrary(HINSTANCE hLibrary); + +VOID WINAPI CoFreeUnusedLibraries(VOID); + +HRESULT WINAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv); + +HRESULT WINAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, REFIID iid, LPVOID *ppv); + +HRESULT WINAPI CoInitialize(LPVOID lpReserved); +HRESULT WINAPI CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit); + +VOID WINAPI CoUninitialize(VOID); + +/* FIXME: not implemented */ +BOOL WINAPI CoIsOle1Class(REFCLSID rclsid); + +HRESULT WINAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases); + +/* class registration flags; passed to CoRegisterClassObject */ +typedef enum tagREGCLS +{ + REGCLS_SINGLEUSE = 0, + REGCLS_MULTIPLEUSE = 1, + REGCLS_MULTI_SEPARATE = 2, + REGCLS_SUSPENDED = 4 +} REGCLS; + +HRESULT WINAPI CoRegisterClassObject(REFCLSID rclsid,LPUNKNOWN pUnk,DWORD dwClsContext,DWORD flags,LPDWORD lpdwRegister); + +HRESULT WINAPI CoRevokeClassObject(DWORD dwRegister); + +BOOL WINAPI IsValidInterface( + LPUNKNOWN punk); + +HRESULT WINAPI GetClassFile(LPOLESTR filePathName,CLSID *pclsid); + + +/***************************************************************************** + * COM Server dll - exports + */ +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv); +HRESULT WINAPI DllCanUnloadNow(VOID); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __WINE_WINE_OBJ_BASE_H */ diff --git a/include/ole32/obj_cache.h b/include/ole32/obj_cache.h new file mode 100644 index 0000000..cca4e18 --- /dev/null +++ b/include/ole32/obj_cache.h @@ -0,0 +1,116 @@ +/* + * Defines the COM interfaces and APIs related to structured data storage. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_CACHE_H +#define __WINE_WINE_OBJ_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Declare the structures + */ + + +/***************************************************************************** + * Predeclare the interfaces + */ + +DEFINE_OLEGUID(IID_IOleCache, 0x0000011eL, 0, 0); +typedef struct IOleCache IOleCache, *LPOLECACHE; + +DEFINE_OLEGUID(IID_IOleCache2, 0x00000128L, 0, 0); +typedef struct IOleCache2 IOleCache2, *LPOLECACHE2; + +DEFINE_OLEGUID(IID_IOleCacheControl, 0x00000129L, 0, 0); +typedef struct IOleCacheControl IOleCacheControl, *LPOLECACHECONTROL; + +/***************************************************************************** + * IOleCache interface + */ +#define ICOM_INTERFACE IOleCache +#define IOleCache_METHODS \ + ICOM_METHOD3(HRESULT,Cache, FORMATETC*,pformatetc, DWORD,advf, DWORD*, pdwConnection) \ + ICOM_METHOD1(HRESULT,Uncache, DWORD,dwConnection) \ + ICOM_METHOD1(HRESULT,EnumCache, IEnumSTATDATA**,ppenumSTATDATA) \ + ICOM_METHOD1(HRESULT,InitCache, IDataObject*,pDataObject) \ + ICOM_METHOD3(HRESULT,SetData, FORMATETC*,pformatetc, STGMEDIUM*,pmedium, BOOL,fRelease) +#define IOleCache_IMETHODS \ + IUnknown_IMETHODS \ + IOleCache_METHODS +ICOM_DEFINE(IOleCache,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleCache_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleCache_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleCache_Release(p) ICOM_CALL (Release,p) +/*** IOleCache methods ***/ +#define IOleCache_Cache(p,a,b,c) ICOM_CALL3(Cache,p,a,b,c) +#define IOleCache_Uncache(p,a) ICOM_CALL1(Uncache,p,a) +#define IOleCache_EnumCache(p,a) ICOM_CALL1(EnumCache,p,a) +#define IOleCache_InitCache(p,a) ICOM_CALL1(InitCache,p,a) +#define IOleCache_SetData(p,a,b,c) ICOM_CALL3(SetData,p,a,b,c) + + +/***************************************************************************** + * IOleCache2 interface + */ +#define ICOM_INTERFACE IOleCache2 +#define IOleCache2_METHODS \ + ICOM_METHOD3(HRESULT,UpdateCache, LPDATAOBJECT,pDataObject, DWORD,grfUpdf, LPVOID,pReserved) \ + ICOM_METHOD1(HRESULT,DiscardCache, DWORD,dwDiscardOptions) +#define IOleCache2_IMETHODS \ + IOleCache_IMETHODS \ + IOleCache2_METHODS +ICOM_DEFINE(IOleCache2,IOleCache) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleCache2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleCache2_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleCache2_Release(p) ICOM_CALL (Release,p) +/*** IOleCache methods ***/ +#define IOleCache2_Cache(p,a,b,c) ICOM_CALL3(Cache,p,a,b,c) +#define IOleCache2_Uncache(p,a) ICOM_CALL1(Uncache,p,a) +#define IOleCache2_EnumCache(p,a) ICOM_CALL1(EnumCache,p,a) +#define IOleCache2_InitCache(p,a) ICOM_CALL1(InitCache,p,a) +#define IOleCache2_SetData(p,a,b,c) ICOM_CALL3(SetData,p,a,b,c) +/*** IOleCache2 methods ***/ +#define IOleCache2_UpdateCache(p,a,b,c) ICOM_CALL3(UpdateCache,p,a,b,c) +#define IOleCache2_DiscardCache(p,a) ICOM_CALL1(DiscardCache,p,a) + + +/***************************************************************************** + * IOleCacheControl interface + */ +#define ICOM_INTERFACE IOleCacheControl +#define IOleCacheControl_METHODS \ + ICOM_METHOD1(HRESULT,OnRun, LPDATAOBJECT,pDataObject) \ + ICOM_METHOD (HRESULT,OnStop) +#define IOleCacheControl_IMETHODS \ + IUnknown_IMETHODS \ + IOleCacheControl_METHODS +ICOM_DEFINE(IOleCacheControl,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleCacheControl_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleCacheControl_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleCacheControl_Release(p) ICOM_CALL (Release,p) +/*** IOleCacheControl methods ***/ +#define IOleCacheControl_OnRun(p,a) ICOM_CALL1(UpdateCache,p,a) +#define IOleCacheControl_OnStop(p) ICOM_CALL (OnStop,p) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_CONTROL_H */ + + diff --git a/include/ole32/obj_channel.h b/include/ole32/obj_channel.h new file mode 100644 index 0000000..843f53e --- /dev/null +++ b/include/ole32/obj_channel.h @@ -0,0 +1,181 @@ +/* + * Defines undocumented Microsoft COM interfaces and APIs seemingly related to some 'channel' notion. + */ + +#ifndef __WINE_WINE_OBJ_CHANNEL_H +#define __WINE_WINE_OBJ_CHANNEL_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID (IID_IChannelHook, 0x1008c4a0L, 0x7613, 0x11cf, 0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4); +typedef struct IChannelHook IChannelHook,*LPCHANNELHOOK; + +DEFINE_GUID (IID_IPSFactoryBuffer, 0xd5f569d0L, 0x593b, 0x101a, 0xb5, 0x69, 0x08, 0x00, 0x2b, 0x2d, 0xbf, 0x7a); +typedef struct IPSFactoryBuffer IPSFactoryBuffer,*LPPSFACTORYBUFFER; + +DEFINE_GUID (IID_IRpcChannelBuffer, 0xd5f56b60L, 0x593b, 0x101a, 0xb5, 0x69, 0x08, 0x00, 0x2b, 0x2d, 0xbf, 0x7a); +typedef struct IRpcChannelBuffer IRpcChannelBuffer,*LPRPCCHANNELBUFFER; + +DEFINE_GUID (IID_IRpcProxyBuffer, 0xd5f56a34L, 0x593b, 0x101a, 0xb5, 0x69, 0x08, 0x00, 0x2b, 0x2d, 0xbf, 0x7a); +typedef struct IRpcProxyBuffer IRpcProxyBuffer,*LPRPCPROXYBUFFER; + +DEFINE_GUID (IID_IRpcStubBuffer, 0xd5f56afcL, 0x593b, 0x101a, 0xb5, 0x69, 0x08, 0x00, 0x2b, 0x2d, 0xbf, 0x7a); +typedef struct IRpcStubBuffer IRpcStubBuffer,*LPRPCSTUBBUFFER; + + +/***************************************************************************** + * IChannelHook interface + */ +#define ICOM_INTERFACE IChannelHook +#define IChannelHook_METHODS \ + ICOM_VMETHOD3(ClientGetSize, REFGUID,uExtent, REFIID,riid, ULONG*,pDataSize) \ + ICOM_VMETHOD4(ClientFillBuffer, REFGUID,uExtent, REFIID,riid, ULONG*,pDataSize, void*,pDataBuffer) \ + ICOM_VMETHOD6(ClientNotify, REFGUID,uExtent, REFIID,riid, ULONG,cbDataSize, void*,pDataBuffer, DWORD,lDataRep, HRESULT,hrFault) \ + ICOM_VMETHOD5(ServerNotify, REFGUID,uExtent, REFIID,riid, ULONG,cbDataSize, void*,pDataBuffer, DWORD,lDataRep) \ + ICOM_VMETHOD4(ServerGetSize, REFGUID,uExtent, REFIID,riid, HRESULT,hrFault, ULONG*,pDataSize) \ + ICOM_VMETHOD5(ServerFillBuffer, REFGUID,uExtent, REFIID,riid, ULONG*,pDataSize, void*,pDataBuffer, HRESULT,hrFault) +#define IChannelHook_IMETHODS \ + IUnknown_IMETHODS \ + IChannelHook_METHODS +ICOM_DEFINE(IChannelHook,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IChannelHook_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IChannelHook_AddRef(p) ICOM_CALL (AddRef,p) +#define IChannelHook_Release(p) ICOM_CALL (Release,p) +/*** IChannelHook methods ***/ +#define IChannelHook_ClientGetSize(p,a,b,c) ICOM_CALL(ClientGetSize,p,a,b,c) +#define IChannelHook_ClientFillBuffer(p,a,b,c,d) ICOM_CALL(ClientFillBuffer,p,a,b,c,d) +#define IChannelHook_ClientNotify(p,a,b,c,d,e,f) ICOM_CALL(ClientNotify,p,a,b,c,d,e,f) +#define IChannelHook_ServerNotify(p,a,b,c,d,e) ICOM_CALL(ServerNotify,p,a,b,c,d,e) +#define IChannelHook_ServerGetSize(p,a,b,c,d) ICOM_CALL(ServerGetSize,p,a,b,c,d) +#define IChannelHook_ServerFillBuffer(p,a,b,c,d,e) ICOM_CALL(ServerFillBuffer,p,a,b,c,d,e) + + +/***************************************************************************** + * IPSFactoryBuffer interface + */ +#define ICOM_INTERFACE IPSFactoryBuffer +#define IPSFactoryBuffer_METHODS \ + ICOM_METHOD4(HRESULT,CreateProxy, IUnknown*,pUnkOuter, REFIID,riid, IRpcProxyBuffer**,ppProxy, void**,ppv) \ + ICOM_METHOD3(HRESULT,CreateStub, REFIID,riid, IUnknown*,pUnkServer, IRpcStubBuffer**,ppStub) +#define IPSFactoryBuffer_IMETHODS \ + IUnknown_IMETHODS \ + IPSFactoryBuffer_METHODS +ICOM_DEFINE(IPSFactoryBuffer,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPSFactoryBuffer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPSFactoryBuffer_AddRef(p) ICOM_CALL (AddRef,p) +#define IPSFactoryBuffer_Release(p) ICOM_CALL (Release,p) +/*** IPSFactoryBuffer methods ***/ +#define IPSFactoryBuffer_CreateProxy(p,a,b,c,d) ICOM_CALL4(CreateProxy,p,a,b,c,d) +#define IPSFactoryBuffer_CreateStub(p,a,b,c) ICOM_CALL3(CreateStub,p,a,b,c) + + +/***************************************************************************** + * IRpcChannelBuffer interface + */ +typedef unsigned long RPCOLEDATAREP; + +typedef struct tagRPCOLEMESSAGE +{ + void* reserved1; + RPCOLEDATAREP dataRepresentation; + void* Buffer; + ULONG cbBuffer; + ULONG iMethod; + void* reserved2[5]; + ULONG rpcFlags; +} RPCOLEMESSAGE, *PRPCOLEMESSAGE; + +#define ICOM_INTERFACE IRpcChannelBuffer +#define IRpcChannelBuffer_METHODS \ + ICOM_METHOD2(HRESULT,GetBuffer, RPCOLEMESSAGE*,pMessage, REFIID,riid) \ + ICOM_METHOD2(HRESULT,SendReceive, RPCOLEMESSAGE*,pMessage, ULONG*,pStatus) \ + ICOM_METHOD1(HRESULT,FreeBuffer, RPCOLEMESSAGE*,pMessage) \ + ICOM_METHOD2(HRESULT,GetDestCtx, DWORD*,pdwDestContext, void**,ppvDestContext) \ + ICOM_METHOD (HRESULT,IsConnected) +#define IRpcChannelBuffer_IMETHODS \ + IUnknown_IMETHODS \ + IRpcChannelBuffer_METHODS +ICOM_DEFINE(IRpcChannelBuffer,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IRpcChannelBuffer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IRpcChannelBuffer_AddRef(p) ICOM_CALL (AddRef,p) +#define IRpcChannelBuffer_Release(p) ICOM_CALL (Release,p) +/*** IRpcChannelBuffer methods ***/ +#define IRpcChannelBuffer_GetBuffer(p,a,b) ICOM_CALL2(GetBuffer,p,a,b) +#define IRpcChannelBuffer_SendReceive(p,a,b) ICOM_CALL2(SendReceive,p,a,b) +#define IRpcChannelBuffer_FreeBuffer(p,a) ICOM_CALL1(FreeBuffer,p,a) +#define IRpcChannelBuffer_GetDestCtx(p,a,b) ICOM_CALL2(GetDestCtx,p,a,b) +#define IRpcChannelBuffer_IsConnected(p) ICOM_CALL (IsConnected,p) + + +/***************************************************************************** + * IRpcProxyBuffer interface + */ +#define ICOM_INTERFACE IRpcProxyBuffer +#define IRpcProxyBuffer_METHODS \ + ICOM_METHOD1(HRESULT,Connect, IRpcChannelBuffer*,pRpcChannelBuffer) \ + ICOM_VMETHOD( Disconnect) +#define IRpcProxyBuffer_IMETHODS \ + IUnknown_IMETHODS \ + IRpcProxyBuffer_METHODS +ICOM_DEFINE(IRpcProxyBuffer,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IRpcProxyBuffer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IRpcProxyBuffer_AddRef(p) ICOM_CALL (AddRef,p) +#define IRpcProxyBuffer_Release(p) ICOM_CALL (Release,p) +/*** IRpcProxyBuffer methods ***/ +#define IRpcProxyBuffer_Connect(p,a) ICOM_CALL2(Connect,p,a) +#define IRpcProxyBuffer_Disconnect(p) ICOM_CALL (Disconnect,p) + + +/***************************************************************************** + * IRpcStubBuffer interface + */ +#define ICOM_INTERFACE IRpcStubBuffer +#define IRpcStubBuffer_METHODS \ + ICOM_METHOD1 (HRESULT, Connect, IUnknown*,pUnkServer) \ + ICOM_VMETHOD ( Disconnect) \ + ICOM_METHOD2 (HRESULT, Invoke, RPCOLEMESSAGE*,_prpcmsg, IRpcChannelBuffer*,_pRpcChannelBuffer) \ + ICOM_METHOD1 (LPRPCCHANNELBUFFER,IsIIDSupported, REFIID,riid) \ + ICOM_METHOD (ULONG, CountRefs) \ + ICOM_METHOD1 (HRESULT, DebugServerQueryInterface, void**,ppv) \ + ICOM_VMETHOD1( DebugServerRelease, void*,pv) +#define IRpcStubBuffer_IMETHODS \ + IUnknown_IMETHODS \ + IRpcStubBuffer_METHODS +ICOM_DEFINE(IRpcStubBuffer,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IRpcStubBuffer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IRpcStubBuffer_AddRef(p) ICOM_CALL (AddRef,p) +#define IRpcStubBuffer_Release(p) ICOM_CALL (Release,p) +/*** IRpcStubBuffer methods ***/ +#define IRpcStubBuffer_Connect(p,a) ICOM_CALL1(Connect,p,a) +#define IRpcStubBuffer_Disconnect(p) ICOM_CALL (Disconnect,p) +#define IRpcStubBuffer_Invoke(p,a,b) ICOM_CALL2(Invoke,p,a,b) +#define IRpcStubBuffer_IsIIDSupported(p,a) ICOM_CALL1(IsIIDSupported,p,a) +#define IRpcStubBuffer_CountRefs(p) ICOM_CALL (CountRefs,p) +#define IRpcStubBuffer_DebugServerQueryInterface(p,a) ICOM_CALL1(DebugServerQueryInterface,p,a) +#define IRpcStubBuffer_DebugServerRelease(p,a) ICOM_CALL1(DebugServerRelease,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_CHANNEL_H */ diff --git a/include/ole32/obj_clientserver.h b/include/ole32/obj_clientserver.h new file mode 100644 index 0000000..8c01cbd --- /dev/null +++ b/include/ole32/obj_clientserver.h @@ -0,0 +1,258 @@ +/* + * Defines the COM interfaces and APIs related to client/server aspects. + */ + +#ifndef __WINE_WINE_OBJ_CLIENTSERVER_H +#define __WINE_WINE_OBJ_CLIENTSERVER_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IClientSecurity, 0x0000013dL, 0, 0); +typedef struct IClientSecurity IClientSecurity,*LPCLIENTSECURITY; + +DEFINE_OLEGUID(IID_IExternalConnection, 0x00000019L, 0, 0); +typedef struct IExternalConnection IExternalConnection,*LPEXTERNALCONNECTION; + +DEFINE_OLEGUID(IID_IMessageFilter, 0x00000016L, 0, 0); +typedef struct IMessageFilter IMessageFilter,*LPMESSAGEFILTER; + +DEFINE_OLEGUID(IID_IServerSecurity, 0x0000013eL, 0, 0); +typedef struct IServerSecurity IServerSecurity,*LPSERVERSECURITY; + + +/***************************************************************************** + * IClientSecurity interface + */ +typedef struct tagSOLE_AUTHENTICATION_SERVICE +{ + DWORD dwAuthnSvc; + DWORD dwAuthzSvc; + OLECHAR* pPrincipalName; + HRESULT hr; +} SOLE_AUTHENTICATION_SERVICE, *PSOLE_AUTHENTICATION_SERVICE; + +typedef enum tagEOLE_AUTHENTICATION_CAPABILITIES +{ + EOAC_NONE = 0x0, + EOAC_MUTUAL_AUTH = 0x1, + EOAC_SECURE_REFS = 0x2, + EOAC_ACCESS_CONTROL = 0x4 +} EOLE_AUTHENTICATION_CAPABILITIES; + +#define ICOM_INTERFACE IClientSecurity +#define IClientSecurity_METHODS \ + ICOM_METHOD8(HRESULT,QueryBlanket, IUnknown*,pProxy, DWORD*,pAuthnSvc, DWORD*,pAuthzSvc, OLECHAR**,pServerPrincName, DWORD*,pAuthnLevel, DWORD*,pImpLevel, void**,pAuthInfo, DWORD*,pCapabilites) \ + ICOM_METHOD8(HRESULT,SetBlanket, IUnknown*,pProxy, DWORD,pAuthnSvc, DWORD,pAuthzSvc, OLECHAR*,pServerPrincName, DWORD,pAuthnLevel, DWORD,pImpLevel, void*,pAuthInfo, DWORD,pCapabilites) \ + ICOM_METHOD2(HRESULT,CopyProxy, IUnknown*,pProxy, IUnknown**,ppCopy) +#define IClientSecurity_IMETHODS \ + IUnknown_IMETHODS \ + IClientSecurity_METHODS +ICOM_DEFINE(IClientSecurity,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IClientSecurity_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IClientSecurity_AddRef(p) ICOM_CALL (AddRef,p) +#define IClientSecurity_Release(p) ICOM_CALL (Release,p) +/*** IClientSecurity methods ***/ +#define IClientSecurity_QueryBlanket(p,a,b,c,d,e,f,g,h) ICOM_CALL8(QueryBlanket,p,a,b,c,d,e,f,g,h) +#define IClientSecurity_SetBlanket(p,a,b,c,d,e,f,g,h) ICOM_CALL8(SetBlanket,p,a,b,c,d,e,f,g,h) +#define IClientSecurity_CopyProxy(p,a,b) ICOM_CALL2(CopyProxy,p,a,b) + + +/***************************************************************************** + * IExternalConnection interface + */ +typedef enum tagEXTCONN +{ + EXTCONN_STRONG = 0x1, + EXTCONN_WEAK = 0x2, + EXTCONN_CALLABLE = 0x4 +} EXTCONN; + +#define ICOM_INTERFACE IExternalConnection +#define IExternalConnection_METHODS \ + ICOM_METHOD2(DWORD,AddConnection, DWORD,extconn, DWORD,reserved) \ + ICOM_METHOD3(DWORD,ReleaseConnection, DWORD,extconn, DWORD,reserved, BOOL,fLastReleaseCloses) +#define IExternalConnection_IMETHODS \ + IUnknown_IMETHODS \ + IExternalConnection_METHODS +ICOM_DEFINE(IExternalConnection,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IExternalConnection_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IExternalConnection_AddRef(p) ICOM_CALL (AddRef,p) +#define IExternalConnection_Release(p) ICOM_CALL (Release,p) +/*** IExternalConnection methods ***/ +#define IExternalConnection_AddConnection(p,a,b) ICOM_CALL8(AddConnection,p,a,b) +#define IExternalConnection_ReleaseConnection(p,a,b,c) ICOM_CALL8(ReleaseConnection,p,a,b,c) + + +HRESULT WINAPI CoDisconnectObject(LPUNKNOWN lpUnk, DWORD reserved); + + +/***************************************************************************** + * IMessageFilter interface + */ +typedef enum tagCALLTYPE +{ + CALLTYPE_TOPLEVEL = 1, + CALLTYPE_NESTED = 2, + CALLTYPE_ASYNC = 3, + CALLTYPE_TOPLEVEL_CALLPENDING = 4, + CALLTYPE_ASYNC_CALLPENDING = 5 +} CALLTYPE; + +typedef enum tagSERVERCALL +{ + SERVERCALL_ISHANDLED = 0, + SERVERCALL_REJECTED = 1, + SERVERCALL_RETRYLATER = 2 +} SERVERCALL; + +typedef enum tagPENDINGTYPE +{ + PENDINGTYPE_TOPLEVEL = 1, + PENDINGTYPE_NESTED = 2 +} PENDINGTYPE; + +typedef enum tagPENDINGMSG +{ + PENDINGMSG_CANCELCALL = 0, + PENDINGMSG_WAITNOPROCESS = 1, + PENDINGMSG_WAITDEFPROCESS = 2 +} PENDINGMSG; + +typedef struct tagINTERFACEINFO +{ + IUnknown* pUnk; + IID iid; + WORD wMethod; +} INTERFACEINFO,*LPINTERFACEINFO; + +#if 0 +#define ICOM_INTERFACE IMessageFilter +#define IMessageFilter_METHODS \ + ICOM_METHOD4(DWORD,HandleInComingCall, DWORD,dwCallType, HTASK,htaskCaller, DWORD,dwTickCount, LPINTERFACEINFO,lpInterfaceInfo) \ + ICOM_METHOD3(DWORD,RetryRejectedCall, HTASK,htaskCallee, DWORD,dwTickCount, DWORD,dwRejectType) \ + ICOM_METHOD3(DWORD,MessagePending, HTASK,htaskCallee, DWORD,dwTickCount, DWORD,dwRejectType) +#define IMessageFilter_IMETHODS \ + IUnknown_IMETHODS \ + IMessageFilter_METHODS +ICOM_DEFINE(IMessageFilter,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IMessageFilter_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IMessageFilter_AddRef(p) ICOM_CALL (AddRef,p) +#define IMessageFilter_Release(p) ICOM_CALL (Release,p) +/*** IMessageFilter methods ***/ +#define IMessageFilter_HandleInComingCall(p,a,b,c,d) ICOM_CALL4(HandleInComingCall,p,a,b,c,d) +#define IMessageFilter_RetryRejectedCall(p,a,b,c) ICOM_CALL3(RetryRejectedCall,p,a,b,c) +#define IMessageFilter_MessagePending(p,a,b,c) ICOM_CALL3(MessagePending,p,a,b,c) + + +HRESULT WINAPI CoRegisterMessageFilter16(LPMESSAGEFILTER lpMessageFilter,LPMESSAGEFILTER *lplpMessageFilter); +HRESULT WINAPI CoRegisterMessageFilter(LPMESSAGEFILTER lpMessageFilter,LPMESSAGEFILTER *lplpMessageFilter); +#endif + +/***************************************************************************** + * IServerSecurity interface + */ +#define ICOM_INTERFACE IServerSecurity +#define IServerSecurity_METHODS \ + ICOM_METHOD7(HRESULT,QueryBlanket, DWORD*,pAuthnSvc, DWORD*,pAuthzSvc, OLECHAR**,pServerPrincName, DWORD*,pAuthnLevel, DWORD*,pImpLevel, void**,pPrivs, DWORD*,pCapabilities) \ + ICOM_METHOD (HRESULT,ImpersonateClient) \ + ICOM_METHOD (HRESULT,RevertToSelf) \ + ICOM_METHOD (BOOL, IsImpersonating) +#define IServerSecurity_IMETHODS \ + IUnknown_IMETHODS \ + IServerSecurity_METHODS +ICOM_DEFINE(IServerSecurity,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IServerSecurity_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IServerSecurity_AddRef(p) ICOM_CALL (AddRef,p) +#define IServerSecurity_Release(p) ICOM_CALL (Release,p) +/*** IServerSecurity methods ***/ +#define IServerSecurity_QueryBlanket(p,a,b,c,d,e,f,g) ICOM_CALL7(QueryBlanket,p,a,b,c,d,e,f,g) +#define IServerSecurity_ImpersonateClient(p) ICOM_CALL (ImpersonateClient,p) +#define IServerSecurity_RevertToSelf(p) ICOM_CALL (RevertToSelf,p) +#define IServerSecurity_IsImpersonating(p) ICOM_CALL (IsImpersonating,p) + + +/***************************************************************************** + * Additional client API + */ +#if 0 +/* FIXME: not implemented */ +HRESULT WINAPI CoCopyProxy(IUnknown* pProxy, IUnknown** ppCopy); + +/* FIXME: not implemented */ +HRESULT WINAPI CoQueryProxyBlanket(IUnknown* pProxy, DWORD* pwAuthnSvc, DWORD* pAuthzSvc, OLECHAR** pServerPrincName, DWORD* pAuthnLevel, DWORD* pImpLevel, RPC_AUTH_IDENTITY_HANDLE* pAuthInfo, DWORD* pCapabilites); + +/* FIXME: not implemented */ +HRESULT WINAPI CoSetProxyBlanket(IUnknown* pProxy, DWORD dwAuthnSvc, DWORD dwAuthzSvc, OLECHAR* pServerPrincName, DWORD dwAuthnLevel, DWORD dwImpLevel, RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities); +#endif + +/***************************************************************************** + * Additional server API + */ + +#if 0 +/* FIXME: not implemented */ +ULONG WINAPI CoAddRefServerProcess(void); + +/* FIXME: not implemented */ +HRESULT WINAPI CoImpersonateClient(void); + +/* FIXME: not implemented */ +HRESULT WINAPI CoQueryClientBlanket(DWORD* pAuthnSvc, DWORD* pAuthzSvc, OLECHAR16** pServerPrincName, DWORD* pAuthnLevel, DWORD* pImpLevel, RPC_AUTHZ_HANDLE* pPrivs, DWORD* pCapabilities); + +/* FIXME: not implemented */ +HRESULT WINAPI CoReleaseServerProcess(void); + +/* FIXME: not implemented */ +HRESULT WINAPI CoRevertToSelf(void); + +/* FIXME: not implemented */ +HRESULT WINAPI CoSuspendClassObjects(void); +#endif + +/***************************************************************************** + * Additional API + */ + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetCallContext(REFIID riid, void** ppInterface); + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID* pClsid); + +/* FIXME: not implemented */ +HRESULT WINAPI CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc, LONG cAuthSvc, SOLE_AUTHENTICATION_SERVICE* asAuthSvc, void* pReserved1, DWORD dwAuthnLevel, DWORD dwImpLevel, void* pReserved2, DWORD dwCapabilities, void* pReserved3); + +/* FIXME: not implemented */ +BOOL WINAPI CoIsHandlerConnected(LPUNKNOWN pUnk); + +/* FIXME: not implemented */ +HRESULT WINAPI CoQueryAuthenticationServices(DWORD* pcAuthSvc, SOLE_AUTHENTICATION_SERVICE** asAuthSvc); + +/* FIXME: not implemented */ +HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid); + +/* FIXME: not implemented */ +HRESULT WINAPI CoResumeClassObjects(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_CLIENTSERVER_H */ diff --git a/include/ole32/obj_commdlgbrowser.h b/include/ole32/obj_commdlgbrowser.h new file mode 100644 index 0000000..ac3cec1 --- /dev/null +++ b/include/ole32/obj_commdlgbrowser.h @@ -0,0 +1,43 @@ +/************************************************************ + * ICommDlgBrowser + */ + +#ifndef __WINE_WINE_OBJ_COMMDLGBROWSER_H +#define __WINE_WINE_OBJ_COMMDLGBROWSER_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +typedef struct ICommDlgBrowser ICommDlgBrowser, *LPCOMMDLGBROWSER; + +/* for OnStateChange*/ +#define CDBOSC_SETFOCUS 0x00000000 +#define CDBOSC_KILLFOCUS 0x00000001 +#define CDBOSC_SELCHANGE 0x00000002 +#define CDBOSC_RENAME 0x00000003 + + +#define ICOM_INTERFACE ICommDlgBrowser +#define ICommDlgBrowser_METHODS \ + ICOM_METHOD1(HRESULT, OnDefaultCommand, IShellView*, IShellView) \ + ICOM_METHOD2(HRESULT, OnStateChange, IShellView*, IShellView, ULONG, uChange) \ + ICOM_METHOD2(HRESULT, IncludeObject, IShellView*, IShellView, LPCITEMIDLIST, pidl) +#define ICommDlgBrowser_IMETHODS \ + IUnknown_IMETHODS \ + ICommDlgBrowser_METHODS +ICOM_DEFINE(ICommDlgBrowser,IUnknown) +#undef ICOM_INTERFACE + +#define ICommDlgBrowser_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ICommDlgBrowser_AddRef(p) ICOM_CALL(AddRef,p) +#define ICommDlgBrowser_Release(p) ICOM_CALL(Release,p) +#define ICommDlgBrowser_OnDefaultCommand(p,a) ICOM_CALL1(OnDefaultCommand,p,a) +#define ICommDlgBrowser_OnStateChange(p,a,b) ICOM_CALL2(OnStateChange,p,a,b) +#define ICommDlgBrowser_IncludeObject(p,a,b) ICOM_CALL2(IncludeObject,p,a,b) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_COMMDLGBROWSER_H */ diff --git a/include/ole32/obj_connection.h b/include/ole32/obj_connection.h new file mode 100644 index 0000000..0dd92eb --- /dev/null +++ b/include/ole32/obj_connection.h @@ -0,0 +1,145 @@ +/* + * Defines the COM interfaces and APIs related to structured data storage. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_CONNECTION_H +#define __WINE_WINE_OBJ_CONNECTION_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Declare the structures + */ + +typedef struct tagCONNECTDATA +{ + IUnknown *pUnk; + DWORD dwCookie; +} CONNECTDATA, *LPCONNECTDATA; + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IConnectionPoint, 0xb196b286, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IConnectionPoint IConnectionPoint, *LPCONNECTIONPOINT; + +DEFINE_GUID(IID_IConnectionPointContainer, 0xb196b284, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IConnectionPointContainer IConnectionPointContainer, *LPCONNECTIONPOINTCONTAINER; + +DEFINE_GUID(IID_IEnumConnections, 0xb196b287, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IEnumConnections IEnumConnections, *LPENUMCONNECTIONS; + +DEFINE_GUID(IID_IEnumConnectionPoints, 0xb196b285, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IEnumConnectionPoints IEnumConnectionPoints, *LPENUMCONNECTIONPOINTS; + +/***************************************************************************** + * IConnectionPoint interface + */ +#define ICOM_INTERFACE IConnectionPoint +#define IConnectionPoint_METHODS \ + ICOM_METHOD1(HRESULT,GetConnectionInterface, IID*,pIID) \ + ICOM_METHOD1(HRESULT,GetConnectionPointContainer, IConnectionPointContainer**,ppCPC) \ + ICOM_METHOD2(HRESULT,Advise, IUnknown*,pUnkSink, DWORD*,pdwCookie) \ + ICOM_METHOD1(HRESULT,Unadvise, DWORD,dwCookie) \ + ICOM_METHOD1(HRESULT,EnumConnections, IEnumConnections**,ppEnum) +#define IConnectionPoint_IMETHODS \ + IUnknown_IMETHODS \ + IConnectionPoint_METHODS +ICOM_DEFINE(IConnectionPoint,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IConnectionPoint_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IConnectionPoint_AddRef(p) ICOM_CALL (AddRef,p) +#define IConnectionPoint_Release(p) ICOM_CALL (Release,p) +/*** IConnectionPointContainer methods ***/ +#define IConnectionPoint_GetConnectionInterface(p,a) ICOM_CALL1(GetConnectionInterface,p,a) +#define IConnectionPoint_GetConnectionPointContainer(p,a) ICOM_CALL1(GetConnectionPointContainer,p,a) +#define IConnectionPoint_Advise(p,a,b) ICOM_CALL2(Advise,p,a,b) +#define IConnectionPoint_Unadvise(p,a) ICOM_CALL1(Unadvise,p,a) +#define IConnectionPoint_EnumConnections(p,a) ICOM_CALL1(EnumConnections,p,a) + + +/***************************************************************************** + * IConnectionPointContainer interface + */ +#define ICOM_INTERFACE IConnectionPointContainer +#define IConnectionPointContainer_METHODS \ + ICOM_METHOD1(HRESULT,EnumConnectionPoints, IEnumConnectionPoints**,ppEnum) \ + ICOM_METHOD2(HRESULT,FindConnectionPoint, REFIID,riid, IConnectionPoint**,ppCP) +#define IConnectionPointContainer_IMETHODS \ + IUnknown_IMETHODS \ + IConnectionPointContainer_METHODS +ICOM_DEFINE(IConnectionPointContainer,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IConnectionPointContainer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IConnectionPointContainer_AddRef(p) ICOM_CALL (AddRef,p) +#define IConnectionPointContainer_Release(p) ICOM_CALL (Release,p) +/*** IConnectionPointContainer methods ***/ +#define IConnectionPointContainer_EnumConnectionPoints(p,a) ICOM_CALL1(EnumConnectionPoints,p,a) +#define IConnectionPointContainer_FindConnectionPoint(p,a,b) ICOM_CALL2(FindConnectionPoint,p,a,b) + + +/***************************************************************************** + * IEnumConnections interface + */ +#define ICOM_INTERFACE IEnumConnections +#define IEnumConnections_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,cConnections, LPCONNECTDATA,rgcd, ULONG*,pcFectched) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,cConnections) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumConnections**,ppEnum) +#define IEnumConnections_IMETHODS \ + IUnknown_IMETHODS \ + IEnumConnections_METHODS +ICOM_DEFINE(IEnumConnections,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumConnections_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumConnections_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumConnections_Release(p) ICOM_CALL (Release,p) +/*** IConnectionPointContainer methods ***/ +#define IEnumConnections_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumConnections_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumConnections_Reset(p) ICOM_CALL (Reset,p) +#define IEnumConnections_Clone(p,a) ICOM_CALL1(Clone,p,a) + +/***************************************************************************** + * IEnumConnectionPoints interface + */ +#define ICOM_INTERFACE IEnumConnectionPoints +#define IEnumConnectionPoints_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,cConnections, LPCONNECTIONPOINT*,ppCP, ULONG*,pcFectched) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,cConnections) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumConnections**,ppEnum) +#define IEnumConnectionPoints_IMETHODS \ + IUnknown_IMETHODS \ + IEnumConnectionPoints_METHODS +ICOM_DEFINE(IEnumConnectionPoints,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumConnectionPoints_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumConnectionPoints_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumConnectionPoints_Release(p) ICOM_CALL (Release,p) +/*** IConnectionPointContainer methods ***/ +#define IEnumConnectionPoints_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumConnectionPoints_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumConnectionPoints_Reset(p) ICOM_CALL (Reset,p) +#define IEnumConnectionPoints_Clone(p,a) ICOM_CALL1(Clone,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_CONTROL_H */ + + diff --git a/include/ole32/obj_contextmenu.h b/include/ole32/obj_contextmenu.h new file mode 100644 index 0000000..30e8538 --- /dev/null +++ b/include/ole32/obj_contextmenu.h @@ -0,0 +1,125 @@ +/************************************************************ + * IContextMenu + * + * Undocumented: + * word95 gets a IContextMenu Interface and calls HandleMenuMsg() + * whitch should only a member of IContextMenu2. + */ + +#ifndef __WINE_WINE_OBJ_CONTEXTMENU_H +#define __WINE_WINE_OBJ_CONTEXTMENU_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +typedef struct IContextMenu IContextMenu, *LPCONTEXTMENU; + +/* QueryContextMenu uFlags */ +#define CMF_NORMAL 0x00000000 +#define CMF_DEFAULTONLY 0x00000001 +#define CMF_VERBSONLY 0x00000002 +#define CMF_EXPLORE 0x00000004 +#define CMF_NOVERBS 0x00000008 +#define CMF_CANRENAME 0x00000010 +#define CMF_NODEFAULT 0x00000020 +#define CMF_INCLUDESTATIC 0x00000040 +#define CMF_RESERVED 0xffff0000 /* View specific */ + +/* GetCommandString uFlags */ +#define GCS_VERBA 0x00000000 /* canonical verb */ +#define GCS_HELPTEXTA 0x00000001 /* help text (for status bar) */ +#define GCS_VALIDATEA 0x00000002 /* validate command exists */ +#define GCS_VERBW 0x00000004 /* canonical verb (unicode) */ +#define GCS_HELPTEXTW 0x00000005 /* help text (unicode version) */ +#define GCS_VALIDATEW 0x00000006 /* validate command exists (unicode) */ +#define GCS_UNICODE 0x00000004 /* for bit testing - Unicode string */ + +#define GCS_VERB GCS_VERBA +#define GCS_HELPTEXT GCS_HELPTEXTA +#define GCS_VALIDATE GCS_VALIDATEA + +#define CMDSTR_NEWFOLDERA "NewFolder" +#define CMDSTR_VIEWLISTA "ViewList" +#define CMDSTR_VIEWDETAILSA "ViewDetails" +static const WCHAR CMDSTR_NEWFOLDERW[] = {'N','e','w','F','o','l','d','e','r',0}; +static const WCHAR CMDSTR_VIEWLISTW [] = {'V','i','e','w','L','i','s','t',0}; +static const WCHAR CMDSTR_VIEWDETAILSW[] = {'V','i','e','w','D','e','t','a','i','l','s',0}; + +#define CMDSTR_NEWFOLDER CMDSTR_NEWFOLDERA +#define CMDSTR_VIEWLIST CMDSTR_VIEWLISTA +#define CMDSTR_VIEWDETAILS CMDSTR_VIEWDETAILSA + +#define CMIC_MASK_HOTKEY SEE_MASK_HOTKEY +#define CMIC_MASK_ICON SEE_MASK_ICON +#define CMIC_MASK_FLAG_NO_UI SEE_MASK_FLAG_NO_UI +#define CMIC_MASK_UNICODE SEE_MASK_UNICODE +#define CMIC_MASK_NO_CONSOLE SEE_MASK_NO_CONSOLE +#define CMIC_MASK_HASLINKNAME SEE_MASK_HASLINKNAME +#define CMIC_MASK_FLAG_SEP_VDM SEE_MASK_FLAG_SEPVDM +#define CMIC_MASK_HASTITLE SEE_MASK_HASTITLE +#define CMIC_MASK_ASYNCOK SEE_MASK_ASYNCOK + +#define CMIC_MASK_PTINVOKE 0x20000000 + +/*NOTE: When SEE_MASK_HMONITOR is set, hIcon is treated as hMonitor */ +typedef struct tagCMINVOKECOMMANDINFO +{ DWORD cbSize; /* sizeof(CMINVOKECOMMANDINFO) */ + DWORD fMask; /* any combination of CMIC_MASK_* */ + HWND hwnd; /* might be NULL (indicating no owner window) */ + LPCSTR lpVerb; /* either a string or MAKEINTRESOURCE(idOffset) */ + LPCSTR lpParameters; /* might be NULL (indicating no parameter) */ + LPCSTR lpDirectory; /* might be NULL (indicating no specific directory) */ + INT nShow; /* one of SW_ values for ShowWindow() API */ + + DWORD dwHotKey; + HANDLE hIcon; +} CMINVOKECOMMANDINFO, *LPCMINVOKECOMMANDINFO; + +typedef struct tagCMInvokeCommandInfoEx +{ DWORD cbSize; /* must be sizeof(CMINVOKECOMMANDINFOEX) */ + DWORD fMask; /* any combination of CMIC_MASK_* */ + HWND hwnd; /* might be NULL (indicating no owner window) */ + LPCSTR lpVerb; /* either a string or MAKEINTRESOURCE(idOffset) */ + LPCSTR lpParameters; /* might be NULL (indicating no parameter) */ + LPCSTR lpDirectory; /* might be NULL (indicating no specific directory) */ + INT nShow; /* one of SW_ values for ShowWindow() API */ + + DWORD dwHotKey; + + HANDLE hIcon; + LPCSTR lpTitle; /* For CreateProcess-StartupInfo.lpTitle */ + LPCWSTR lpVerbW; /* Unicode verb (for those who can use it) */ + LPCWSTR lpParametersW; /* Unicode parameters (for those who can use it) */ + LPCWSTR lpDirectoryW; /* Unicode directory (for those who can use it) */ + LPCWSTR lpTitleW; /* Unicode title (for those who can use it) */ + POINT ptInvoke; /* Point where it's invoked */ + +} CMINVOKECOMMANDINFOEX, *LPCMINVOKECOMMANDINFOEX; + +#define ICOM_INTERFACE IContextMenu +#define IContextMenu_METHODS \ + ICOM_METHOD5(HRESULT, QueryContextMenu, HMENU, hmenu, UINT, indexMenu, UINT, idCmdFirst, UINT, idCmdLast, UINT, uFlags) \ + ICOM_METHOD1(HRESULT, InvokeCommand, LPCMINVOKECOMMANDINFO, lpici) \ + ICOM_METHOD5(HRESULT, GetCommandString, UINT, idCmd, UINT, uType, UINT*, pwReserved, LPSTR, pszName, UINT, cchMax) \ + ICOM_METHOD3(HRESULT, HandleMenuMsg, UINT, uMsg, WPARAM, wParam, LPARAM, lParam) \ + void * guard; /*possibly another nasty entry from ContextMenu3 ?*/ +#define IContextMenu_IMETHODS \ + IUnknown_IMETHODS \ + IContextMenu_METHODS +ICOM_DEFINE(IContextMenu,IUnknown) +#undef ICOM_INTERFACE + +#define IContextMenu_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IContextMenu_AddRef(p) ICOM_CALL(AddRef,p) +#define IContextMenu_Release(p) ICOM_CALL(Release,p) +#define IContextMenu_QueryContextMenu(p,a,b,c,d,e) ICOM_CALL5(QueryContextMenu,p,a,b,c,d,e) +#define IContextMenu_InvokeCommand(p,a) ICOM_CALL1(InvokeCommand,p,a) +#define IContextMenu_GetCommandString(p,a,b,c,d,e) ICOM_CALL5(GetCommandString,p,a,b,c,d,e) +#define IContextMenu_HandleMenuMsg(p,a,b,c) ICOM_CALL3(HandleMenuMsg,p,a,b,c) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_CONTEXTMENU_H */ diff --git a/include/ole32/obj_control.h b/include/ole32/obj_control.h new file mode 100644 index 0000000..e08d307 --- /dev/null +++ b/include/ole32/obj_control.h @@ -0,0 +1,458 @@ +/* + * Defines the COM interfaces and APIs related to structured data storage. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_CONTROL_H +#define __WINE_WINE_OBJ_CONTROL_H + +struct tagMSG; + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Declare the structures + */ +typedef enum tagGUIDKIND +{ + GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1 +} GUIDKIND; + +typedef enum tagREADYSTATE +{ + READYSTATE_UNINITIALIZED = 0, + READYSTATE_LOADING = 1, + READYSTATE_LOADED = 2, + READYSTATE_INTERACTIVE = 3, + READYSTATE_COMPLETE = 4 +} READYSTATE; + +typedef struct tagExtentInfo +{ + ULONG cb; + DWORD dwExtentMode; + SIZEL sizelProposed; +} DVEXTENTINFO; + +typedef struct tagVARIANT_BLOB +{ + DWORD clSize; + DWORD rpcReserved; + ULONGLONG ahData[1]; +} wireVARIANT_BLOB; + +typedef struct tagUserVARIANT +{ + wireVARIANT_BLOB pVarBlob; +} UserVARIANT; + +typedef struct tagLICINFO +{ + LONG cbLicInfo; + BOOL fRuntimeKeyAvail; + BOOL fLicVerified; +} LICINFO, *LPLICINFO; + +typedef struct tagCONTROLINFO +{ + ULONG cb; + HACCEL hAccel; + USHORT cAccel; + DWORD dwFlags; +} CONTROLINFO, *LPCONTROLINFO; + +typedef enum tagCTRLINFO +{ + CTRLINFO_EATS_RETURN = 1, + CTRLINFO_EATS_ESCAPE = 2 +} CTRLINFO; + +typedef struct tagPOINTF +{ + FLOAT x; + FLOAT y; +} POINTF, *LPPOINTF; + +typedef enum tagXFORMCOORDS +{ + XFORMCOORDS_POSITION = 0x1, + XFORMCOORDS_SIZE = 0x2, + XFORMCOORDS_HIMETRICTOCONTAINER = 0x4, + XFORMCOORDS_CONTAINERTOHIMETRIC = 0x8 +} XFORMCOORDS; + +typedef enum tagACTIVATEFLAGS +{ + ACTIVATE_WINDOWLESS = 1 +} ACTIVATE_FLAGS; + +typedef enum tagOLEDCFLAGS +{ + OLEDC_NODRAW = 0x1, + OLEDC_PAINTBKGND = 0x2, + OLEDC_OFFSCREEN = 0x4 +} OLEDCFLAGS; + +typedef enum tagDVASPECT2 +{ + DVASPECT_OPAQUE = 16, + DVASPECT_TRANSPARENT = 32 +} DVASPECT2; + +typedef enum tagHITRESULT +{ + HITRESULT_OUTSIDE = 0, + HITRESULT_TRANSPARENT = 1, + HITRESULT_CLOSE = 2, + HITRESULT_HIT = 3 +} HITRESULT; + +typedef enum tagAspectInfoFlag +{ + DVASPECTINFOFLAG_CANOPTIMIZE = 1 +} DVASPECTINFOFLAG; + +typedef struct tagAspectInfo +{ + ULONG cb; + DWORD dwFlags; +} DVASPECTINFO; + +typedef enum tagVIEWSTATUS +{ + VIEWSTATUS_OPAQUE = 1, + VIEWSTATUS_SOLIDBKGND = 2, + VIEWSTATUS_DVASPECTOPAQUE = 4, + VIEWSTATUS_DVASPECTTRANSPARENT = 8 +} VIEWSTATUS; + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IOleControl, 0xb196b288, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IOleControl IOleControl, *LPOLECONTROL; + +DEFINE_GUID(IID_IOleControlSite, 0xb196b289, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IOleControlSite IOleControlSite, *LPOLECONTROLSITE; + +DEFINE_GUID(IID_IOleInPlaceSiteEx, 0x9c2cad80L, 0x3424, 0x11cf, 0xb6, 0x70, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8); +typedef struct IOleInPlaceSiteEx IOleInPlaceSiteEx, *LPOLEINPLACESITEEX; + +DEFINE_OLEGUID(IID_IOleInPlaceSiteWindowless, 0x00000000L, 0, 0); /* FIXME - NEED GUID */ +typedef struct IOleInPlaceSiteWindowless IOleInPlaceSiteWindowless, *LPOLEINPLACESITEWINDOWLESS; + +DEFINE_OLEGUID(IID_IOleInPlaceObjectWindowless, 0x00000000L, 0, 0); /* FIXME - NEED GUID */ +typedef struct IOleInPlaceObjectWindowless IOleInPlaceObjectWindowless, *LPOLEINPLACEOBJECTWINDOWLESS; + +DEFINE_GUID(IID_IClassFactory2, 0xb196b28f, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IClassFactory2 IClassFactory2, *LPCLASSFACTORY2; + +DEFINE_GUID(IID_IViewObjectEx, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); /* FIXME need GUID */ +typedef struct IViewObjectEx IViewObjectEx, *LPVIEWOBJECTEX; + +DEFINE_GUID(IID_IProvideClassInfo, 0xb196b283, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IProvideClassInfo IProvideClassInfo, *LPPROVIDECLASSINFO; + +DEFINE_GUID(IID_IProvideClassInfo2, 0xa6bc3ac0, 0xdbaa, 0x11ce, 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51); +typedef struct IProvideClassInfo2 IProvideClassInfo2, *LPPROVIDECLASSINFO2; + +/***************************************************************************** + * IOleControl interface + */ +#define ICOM_INTERFACE IOleControl +#define IOleControl_METHODS \ + ICOM_METHOD1(HRESULT,GetControlInfo, CONTROLINFO*,pCI) \ + ICOM_METHOD1(HRESULT,OnMnemonic, struct tagMSG*,pMsg) \ + ICOM_METHOD1(HRESULT,OnAmbientPropertyChange, DISPID,dispID) \ + ICOM_METHOD1(HRESULT,FreezeEvents, BOOL,bFreeze) +#define IOleControl_IMETHODS \ + IUnknown_IMETHODS \ + IOleControl_METHODS +ICOM_DEFINE(IOleControl,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleControl_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleControl_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleControl_Release(p) ICOM_CALL (Release,p) +/*** IOleControl methods ***/ +#define IOleControl_GetControlInfo(p,a) ICOM_CALL1(GetControlInfo,p,a) +#define IOleControl_OnMnemonic(p,a) ICOM_CALL1(OnMnemonic,p,a) +#define IOleControl_OnAmbientPropertyChange(p,a) ICOM_CALL1(OnAmbientPropertyChange,p,a) +#define IOleControl_FreezeEvents(p,a) ICOM_CALL1(FreezeEvents,p,a) + + +/***************************************************************************** + * IOleControlSite interface + */ +#define ICOM_INTERFACE IOleControlSite +#define IOleControlSite_METHODS \ + ICOM_METHOD (HRESULT,OnControlInfoChanged) \ + ICOM_METHOD1(HRESULT,LockInPlaceActive, BOOL,fLock) \ + ICOM_METHOD1(HRESULT,GetExtendedControl, IDispatch**,ppDisp) \ + ICOM_METHOD3(HRESULT,TransformCoords, POINTL*,pPtlHimetric, POINTF*,pPtfContainer, DWORD,dwFlags) \ + ICOM_METHOD2(HRESULT,TranslateAccelerator, struct tagMSG*,pMsg, DWORD,grfModifiers) \ + ICOM_METHOD1(HRESULT,OnFocus, BOOL,fGotFocus) \ + ICOM_METHOD (HRESULT,ShowPropertyFrame) +#define IOleControlSite_IMETHODS \ + IUnknown_IMETHODS \ + IOleControlSite_METHODS +ICOM_DEFINE(IOleControlSite,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleControlSite_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleControlSite_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleControlSite_Release(p) ICOM_CALL (Release,p) +/*** IOleControlSite methods ***/ +#define IOleControlSite_OnControlInfoChanged(p) ICOM_CALL1(OnControlInfoChanged,p) +#define IOleControlSite_LockInPlaceActive(p,a) ICOM_CALL1(LockInPlaceActive,p,a) +#define IOleControlSite_GetExtendedControl(p,a) ICOM_CALL1(GetExtendedControl,p,a) +#define IOleControlSite_TransformCoords(p,a,b,c) ICOM_CALL1(TransformCoords,p,a,b,c) +#define IOleControlSite_TranslateAccelerator(p,a,b) ICOM_CALL1(TranslateAccelerator,p,a,b) +#define IOleControlSite_OnFocus(p,a) ICOM_CALL1(OnFocus,p,a) +#define IOleControlSite_ShowPropertyFrame(p) ICOM_CALL1(ShowPropertyFrame,p) + + +/***************************************************************************** + * IOleInPlaceSiteEx interface + */ +#define ICOM_INTERFACE IOleInPlaceSiteEx +#define IOleInPlaceSiteEx_METHODS \ + ICOM_METHOD2(HRESULT,OnInPlaceActivateEx, BOOL*,pfNoRedraw, DWORD,dwFlags) \ + ICOM_METHOD1(HRESULT,OnInPlaceDeactivateEx, BOOL,fNoRedraw) \ + ICOM_METHOD (HRESULT,RequestUIActivate) +#define IOleInPlaceSiteEx_IMETHODS \ + IOleInPlaceSite_IMETHODS \ + IOleInPlaceSiteEx_METHODS +ICOM_DEFINE(IOleInPlaceSiteEx,IOleInPlaceSite) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceSiteEx_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceSiteEx_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceSiteEx_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceSiteEx_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceSiteEx_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceSite methods ***/ +#define IOleInPlaceSiteEx_CanInPlaceActivate(p) ICOM_CALL (CanInPlaceActivate,p) +#define IOleInPlaceSiteEx_OnInPlaceActivate(p) ICOM_CALL (OnInPlaceActivate,p) +#define IOleInPlaceSiteEx_OnUIActivate(p) ICOM_CALL (OnUIActivate,p) +#define IOleInPlaceSiteEx_GetWindowContext(p,a,b,c,d,e) ICOM_CALL5(GetWindowContext,p,a,b,c,d,e) +#define IOleInPlaceSiteEx_Scroll(p,a) ICOM_CALL1(Scroll,p,a) +#define IOleInPlaceSiteEx_OnUIDeactivate(p,a) ICOM_CALL1(OnUIDeactivate,p,a) +#define IOleInPlaceSiteEx_OnInPlaceDeactivate(p) ICOM_CALL (OnInPlaceDeactivate,p) +#define IOleInPlaceSiteEx_DiscardUndoState(p) ICOM_CALL (DiscardUndoState,p) +#define IOleInPlaceSiteEx_DeactivateAndUndo(p) ICOM_CALL (DeactivateAndUndo,p) +#define IOleInPlaceSiteEx_OnPosRectChange(p,a) ICOM_CALL1(OnPosRectChange,p,a) +/*** IOleInPlaceSiteEx methods ***/ +#define IOleInPlaceSiteEx_OnInPlaceActivateEx(p,a,b) ICOM_CALL2(OnInPlaceActivateEx,p,a,b) +#define IOleInPlaceSiteEx_OnInPlaceDeactivateEx(p,a) ICOM_CALL1(OnInPlaceDeactivateEx,p,a) +#define IOleInPlaceSiteEx_RequestUIActivate(p) ICOM_CALL (RequestUIActivate,p) + + +/***************************************************************************** + * IOleInPlaceSiteWindowless interface + */ +#define ICOM_INTERFACE IOleInPlaceSiteWindowless +#define IOleInPlaceSiteWindowless_METHODS \ + ICOM_METHOD (HRESULT,CanWindowlessActivate) \ + ICOM_METHOD (HRESULT,GetCapture) \ + ICOM_METHOD1(HRESULT,SetCapture, BOOL,fCapture) \ + ICOM_METHOD (HRESULT,GetFocus) \ + ICOM_METHOD1(HRESULT,SetFocus, BOOL,fFocus) \ + ICOM_METHOD3(HRESULT,GetDC, LPCRECT,pRect, DWORD,grfFlags, HDC*,phDC) \ + ICOM_METHOD1(HRESULT,ReleaseDC, HDC,hDC) \ + ICOM_METHOD2(HRESULT,InvalidateRect, LPCRECT,pRect, BOOL,fErase) \ + ICOM_METHOD2(HRESULT,InvalidateRgn, HRGN,hRgn, BOOL,fErase) \ + ICOM_METHOD4(HRESULT,ScrollRect, INT,dx, INT,dy, LPCRECT,pRectScroll, LPCRECT,pRectClip) \ + ICOM_METHOD1(HRESULT,AdjustRect, LPRECT,prc) \ + ICOM_METHOD4(HRESULT,OnDefWindowMessage, UINT,msg, WPARAM,wParam, LPARAM,lParam, LRESULT*,plResult) +#define IOleInPlaceSiteWindowless_IMETHODS \ + IOleInPlaceSite_IMETHODS \ + IOleInPlaceSiteWindowless_METHODS +ICOM_DEFINE(IOleInPlaceSiteWindowless,IOleInPlaceSite) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceSiteWindowless_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceSiteWindowless_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceSiteWindowless_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceSiteWindowless_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceSiteWindowless_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceSitemethods ***/ +#define IOleInPlaceSiteWindowless_CanInPlaceActivate(p) ICOM_CALL (CanInPlaceActivate,p) +#define IOleInPlaceSiteWindowless_OnInPlaceActivate(p) ICOM_CALL (OnInPlaceActivate,p) +#define IOleInPlaceSiteWindowless_OnUIActivate(p) ICOM_CALL (OnUIActivate,p) +#define IOleInPlaceSiteWindowless_GetWindowContext(p,a,b,c,d,e) ICOM_CALL5(GetWindowContext,p,a,b,c,d,e) +#define IOleInPlaceSiteWindowless_Scroll(p,a) ICOM_CALL1(Scroll,p,a) +#define IOleInPlaceSiteWindowless_OnUIDeactivate(p,a) ICOM_CALL1(OnUIDeactivate,p,a) +#define IOleInPlaceSiteWindowless_OnInPlaceDeactivate(p) ICOM_CALL (OnInPlaceDeactivate,p) +#define IOleInPlaceSiteWindowless_DiscardUndoState(p) ICOM_CALL (DiscardUndoState,p) +#define IOleInPlaceSiteWindowless_DeactivateAndUndo(p) ICOM_CALL (DeactivateAndUndo,p) +#define IOleInPlaceSiteWindowless_OnPosRectChange(p,a) ICOM_CALL1(OnPosRectChange,p,a) +/*** IOleInPlaceSitemethods ***/ +#define IOleInPlaceSiteWindowless_CanWindowlessActivate(p) ICOM_CALL (CanInPlaceActivate,p) +#define IOleInPlaceSiteWindowless_GetCapture(p) ICOM_CALL (OnInPlaceActivate,p) +#define IOleInPlaceSiteWindowless_SetCapture(p,a) ICOM_CALL1(OnUIActivate,p,a) +#define IOleInPlaceSiteWindowless_GetFocus(p) ICOM_CALL (GetWindowContext,p) +#define IOleInPlaceSiteWindowless_SetFocus(p,a) ICOM_CALL1(Scroll,p,a) +#define IOleInPlaceSiteWindowless_GetDC(p,a,b,c) ICOM_CALL3(OnUIDeactivate,p,a,b,c) +#define IOleInPlaceSiteWindowless_ReleaseDC(p,a) ICOM_CALL1(OnInPlaceDeactivate,p,a) +#define IOleInPlaceSiteWindowless_InvalidateRect(p,a,b) ICOM_CALL2(DiscardUndoState,p,a,b) +#define IOleInPlaceSiteWindowless_InvalidateRgn(p,a,b) ICOM_CALL2(DeactivateAndUndo,p,a,b) +#define IOleInPlaceSiteWindowless_ScrollRect(p,a,b,c,d) ICOM_CALL4(OnPosRectChange,p,a,b,c,d) +#define IOleInPlaceSiteWindowless_AdjustRect(p,a) ICOM_CALL1(OnPosRectChange,p,a) +#define IOleInPlaceSiteWindowless_OnDefWindowMessage(p,a,b,c,d) ICOM_CALL4(OnPosRectChange,p,a,b,c,d) + + +/***************************************************************************** + * IOleInPlaceObjectWindowless interface + */ +#define ICOM_INTERFACE IOleInPlaceObjectWindowless +#define IOleInPlaceObjectWindowless_METHODS \ + ICOM_METHOD4(HRESULT,OnWindowMessage, UINT,msg, WPARAM,wParam, LPARAM,lParam, LRESULT*,plResult) \ + ICOM_METHOD1(HRESULT,GetDropTarget, IDropTarget**,ppDropTarget) +#define IOleInPlaceObjectWindowless_IMETHODS \ + IOleInPlaceObject_IMETHODS \ + IOleInPlaceObjectWindowless_METHODS +ICOM_DEFINE(IOleInPlaceObjectWindowless,IOleInPlaceObject) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceObjectWindowless_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceObjectWindowless_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceObjectWindowless_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceObjectWindowless_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceObjectWindowless_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceObject methods ***/ +#define IOleInPlaceObjectWindowless_InPlaceDeactivate(p) ICOM_CALL (InPlaceDeactivate,p) +#define IOleInPlaceObjectWindowless_UIDeactivate(p) ICOM_CALL (UIDeactivate,p) +#define IOleInPlaceObjectWindowless_SetObjectRects(p,a,b) ICOM_CALL2(SetObjectRects,p,a,b) +#define IOleInPlaceObjectWindowless_ReactivateAndUndo(p) ICOM_CALL (ReactivateAndUndo,p) +/*** IOleInPlaceObjectWindowless methods ***/ +#define IOleInPlaceObjectWindowless_OnWindowMessage(p,a,b,c,d) ICOM_CALL4(OnWindowMessage,p,a,b,c,d) +#define IOleInPlaceObjectWindowless_GetDropTarget(p,a) ICOM_CALL1(GetDropTarget,p,a) + + +/***************************************************************************** + * IClassFactory2 interface + */ +#define ICOM_INTERFACE IClassFactory2 +#define IClassFactory2_METHODS \ + ICOM_METHOD1(HRESULT,GetLicInfo, LICINFO*,pLicInfo) \ + ICOM_METHOD2(HRESULT,RequestLicKey, DWORD,dwReserved, BSTR*,pBstrKey) \ + ICOM_METHOD5(HRESULT,CreateInstanceLic, IUnknown*,pUnkOuter, IUnknown*,pUnkReserved, REFIID,riid, BSTR,bstrKey, PVOID*,ppvObj) +#define IClassFactory2_IMETHODS \ + IClassFactory_IMETHODS \ + IClassFactory2_METHODS +ICOM_DEFINE(IClassFactory2,IClassFactory) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IClassFactory2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IClassFactory2_AddRef(p) ICOM_CALL (AddRef,p) +#define IClassFactory2_Release(p) ICOM_CALL (Release,p) +/*** IClassFactory methods ***/ +#define IClassFactory2_CreateInstance(p,a,b,c) ICOM_CALL3(CreateInstance,p,a,b,c) +#define IClassFactory2_LockServer(p,a) ICOM_CALL1(LockServer,p,a) +/*** IClassFactory2 methods ***/ +#define IClassFactory2_GetLicInfo(p,a) ICOM_CALL1(GetLicInfo,p,a) +#define IClassFactory2_RequestLicKey(p,a,b) ICOM_CALL2(RequestLicKey,p,a,b) +#define IClassFactory2_CreateInstanceLic(p,a,b,c,d,e) ICOM_CALL5(CreateInstanceLic,p,a,b,c,d,e) + + +/***************************************************************************** + * IViewObject interface + */ +#define ICOM_INTERFACE IViewObjectEx +#define IViewObjectEx_METHODS \ + ICOM_METHOD2(HRESULT,GetRect, DWORD,dwAspect, LPRECTL,pRect) \ + ICOM_METHOD1(HRESULT,GetViewStatus, DWORD*,pdwStatus) \ + ICOM_METHOD5(HRESULT,QueryHitPoint, DWORD,dwAspect, LPCRECT,pRectBounds, POINT,ptlLoc, LONG,lCloseHint, DWORD*,pHitResult) \ + ICOM_METHOD5(HRESULT,QueryHitRect, DWORD,dwAspect, LPCRECT,pRectBounds, LPCRECT,pRectLoc, LONG,lCloseHint, DWORD*,pHitResult) \ + ICOM_METHOD6(HRESULT,GetNaturalExtent, DWORD,dwAspect, LONG,lindex, DVTARGETDEVICE*,ptd, HDC,hicTargetDev, DVEXTENTINFO*,pExtentInfo, LPSIZEL,pSizel) +#define IViewObjectEx_IMETHODS \ + IViewObject2_IMETHODS \ + IViewObjectEx_METHODS +ICOM_DEFINE(IViewObjectEx,IViewObject2) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IViewObjectEx_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IViewObjectEx_AddRef(p) ICOM_CALL (AddRef,p) +#define IViewObjectEx_Release(p) ICOM_CALL (Release,p) +/*** IViewObject methods ***/ +#define IViewObjectEx_Draw(p,a,b,c,d,e,f,g,h,i,j) ICOM_CALL10(Draw,p,a,b,c,d,e,f,g,h,i,j) +#define IViewObjectEx_GetColorSet(p,a,b,c,d,e,f) ICOM_CALL6(GetColorSet,p,a,b,c,d,e,f) +#define IViewObjectEx_Freeze(p,a,b,c,d) ICOM_CALL4(Freeze,p,a,b,c,d) +#define IViewObjectEx_Unfreeze(p,a) ICOM_CALL1(Unfreeze,p,a) +#define IViewObjectEx_SetAdvise(p,a,b,c) ICOM_CALL3(SetAdvise,p,a,b,c) +#define IViewObjectEx_GetAdvise(p,a,b,c) ICOM_CALL3(GetAdvise,p,a,b,c) +/*** IViewObject2 methods ***/ +#define IViewObjectEx_GetExtent(p,a,b,c,d) ICOM_CALL4(GetExtent,p,a,b,c,d) +/*** IViewObjectEx methods ***/ +#define IViewObjectEx_GetRect(p,a,b) ICOM_CALL2(GetRect,p,a,b) +#define IViewObjectEx_GetViewStatus(p,a) ICOM_CALL1(GetViewStatus,p,a) +#define IViewObjectEx_QueryHitPoint(p,a,b,c,d,e) ICOM_CALL5(QueryHitPoint,p,a,b,c,d,e) +#define IViewObjectEx_QueryHitRect(p,a,b,c,d,e) ICOM_CALL5(QueryHitRect,p,a,b,c,d,e) +#define IViewObjectEx_GetNaturalExtent(p,a,b,c,d,e,f) ICOM_CALL6(GetNaturalExtent,p,a,b,c,d,e,f) + + +/***************************************************************************** + * IProvideClassInfo interface + */ +#ifdef __WINE__ +#undef GetClassInfo +#endif + +#define ICOM_INTERFACE IProvideClassInfo +#define IProvideClassInfo_METHODS \ + ICOM_METHOD1(HRESULT,GetClassInfo, ITypeInfo**,ppTI) +#define IProvideClassInfo_IMETHODS \ + IUnknown_IMETHODS \ + IProvideClassInfo_METHODS +ICOM_DEFINE(IProvideClassInfo,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IProvideClassInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IProvideClassInfo_AddRef(p) ICOM_CALL (AddRef,p) +#define IProvideClassInfo_Release(p) ICOM_CALL (Release,p) +/*** IProvideClassInfo methods ***/ +#define IProvideClassInfo_GetClassInfo(p,a) ICOM_CALL1(GetClassInfo,p,a) + + + +/***************************************************************************** + * IProvideClassInfo2 interface + */ +#define ICOM_INTERFACE IProvideClassInfo2 +#define IProvideClassInfo2_METHODS \ + ICOM_METHOD2(HRESULT,GetGUID, DWORD,dwGuidKind, GUID*,pGUID) +#define IProvideClassInfo2_IMETHODS \ + IProvideClassInfo_IMETHODS \ + IProvideClassInfo2_METHODS +ICOM_DEFINE(IProvideClassInfo2,IProvideClassInfo) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IProvideClassInfo2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IProvideClassInfo2_AddRef(p) ICOM_CALL (AddRef,p) +#define IProvideClassInfo2_Release(p) ICOM_CALL (Release,p) +/*** IProvideClassInfo methods ***/ +#define IProvideClassInfo2_GetClassInfo(p,a) ICOM_CALL1(GetClassInfo,p,a) +/*** IProvideClassInfo2 methods ***/ +#define IProvideClassInfo2_GetGUID(p,a,b) ICOM_CALL2(GetGUID,p,a,b) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_CONTROL_H */ diff --git a/include/ole32/obj_dataobject.h b/include/ole32/obj_dataobject.h new file mode 100644 index 0000000..25fca2d --- /dev/null +++ b/include/ole32/obj_dataobject.h @@ -0,0 +1,323 @@ +/* + * Defines the COM interfaces and APIs related to IDataObject. + * + */ + +#ifndef __WINE_WINE_OBJ_DATAOBJECT_H +#define __WINE_WINE_OBJ_DATAOBJECT_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the structures + */ +typedef enum tagDATADIR +{ + DATADIR_GET = 1, + DATADIR_SET = 2 +} DATADIR; + +typedef struct DVTARGETDEVICE16 DVTARGETDEVICE16, *LPDVTARGETDEVICE16; +typedef struct DVTARGETDEVICE DVTARGETDEVICE, *LPDVTARGETDEVICE; + +typedef struct FORMATETC16 FORMATETC16, *LPFORMATETC16; +typedef struct FORMATETC FORMATETC, *LPFORMATETC; + +typedef struct STGMEDIUM STGMEDIUM, *LPSTGMEDIUM; + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IAdviseSink, 0x0000010fL, 0, 0); +typedef struct IAdviseSink IAdviseSink,*LPADVISESINK; + +DEFINE_OLEGUID(IID_IAdviseSink2, 0x00000125L, 0, 0); +typedef struct IAdviseSink2 IAdviseSink2,*LPADVISESINK2; + +DEFINE_OLEGUID(IID_IDataAdviseHolder, 0x00000110L, 0, 0); +typedef struct IDataAdviseHolder IDataAdviseHolder,*LPDATAADVISEHOLDER; + +DEFINE_OLEGUID(IID_IDataObject, 0x0000010EL, 0, 0); +typedef struct IDataObject IDataObject,*LPDATAOBJECT; + +DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103L, 0, 0); +typedef struct IEnumFORMATETC IEnumFORMATETC,*LPENUMFORMATETC; + +DEFINE_OLEGUID(IID_IEnumSTATDATA, 0x00000105L, 0, 0); +typedef struct IEnumSTATDATA IEnumSTATDATA,*LPENUMSTATDATA; + + +/***************************************************************************** + * DVTARGETDEVICE structure + */ +struct DVTARGETDEVICE +{ + DWORD tdSize; + WORD tdDriverNameOffset; + WORD tdDeviceNameOffset; + WORD tdPortNameOffset; + WORD tdExtDevmodeOffset; + BYTE tdData[1]; +}; + + +/***************************************************************************** + * FORMATETC structure + */ +/* wished data format */ +struct FORMATETC +{ + CLIPFORMAT cfFormat; + DVTARGETDEVICE* ptd; + DWORD dwAspect; + LONG lindex; + DWORD tymed; +}; + + +/***************************************************************************** + * STGMEDIUM structure + */ +typedef enum tagTYMED +{ + TYMED_HGLOBAL = 1, + TYMED_FILE = 2, + TYMED_ISTREAM = 4, + TYMED_ISTORAGE = 8, + TYMED_GDI = 16, + TYMED_MFPICT = 32, + TYMED_ENHMF = 64, + TYMED_NULL = 0 +} TYMED; + +typedef struct tagRemSTGMEDIUM +{ + DWORD tymed; + DWORD dwHandleType; + unsigned long pData; + unsigned long pUnkForRelease; + unsigned long cbData; + BYTE data[1]; +} RemSTGMEDIUM; + +/* dataobject as answer to a request */ +struct STGMEDIUM +{ + DWORD tymed; + union { + HBITMAP hBitmap; + HMETAFILEPICT hMetaFilePict; + HENHMETAFILE hEnhMetaFile; + HGLOBAL hGlobal; + LPOLESTR lpszFileName; + IStream *pstm; + IStorage *pstg; + } u; + IUnknown *pUnkForRelease; +}; + +typedef enum tagADVF +{ + ADVF_NODATA = 1, + ADVF_PRIMEFIRST = 2, + ADVF_ONLYONCE = 4, + ADVF_DATAONSTOP = 64, + ADVFCACHE_NOHANDLER = 8, + ADVFCACHE_FORCEBUILTIN = 16, + ADVFCACHE_ONSAVE = 32 +} ADVF; + +typedef struct tagSTATDATA +{ + FORMATETC formatetc; + DWORD advf; + IAdviseSink *pAdvSink; + DWORD dwConnection; +} STATDATA, *LPSTATDATA; + +/***************************************************************************** + * IAdviseSink interface + */ +#define ICOM_INTERFACE IAdviseSink +#define IAdviseSink_METHODS \ + ICOM_VMETHOD2(OnDataChange, FORMATETC*,pFormatetc, STGMEDIUM*,pStgmed) \ + ICOM_VMETHOD2(OnViewChange, DWORD,dwAspect, LONG,lindex) \ + ICOM_VMETHOD1(OnRename, IMoniker*,pmk) \ + ICOM_VMETHOD (OnSave) \ + ICOM_VMETHOD (OnClose) +#define IAdviseSink_IMETHODS \ + IUnknown_IMETHODS \ + IAdviseSink_METHODS +ICOM_DEFINE(IAdviseSink,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IAdviseSink_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IAdviseSink_AddRef(p) ICOM_CALL (AddRef,p) +#define IAdviseSink_Release(p) ICOM_CALL (Release,p) +/*** IAdviseSink methods ***/ +#define IAdviseSink_OnDataChange(p,a,b) ICOM_CALL2(OnDataChange,p,a,b) +#define IAdviseSink_OnViewChange(p,a,b) ICOM_CALL2(OnViewChange,p,a,b) +#define IAdviseSink_OnRename(p,a) ICOM_CALL1(OnRename,p,a) +#define IAdviseSink_OnSave(p) ICOM_CALL (OnSave,p) +#define IAdviseSink_OnClose(p) ICOM_CALL (OnClose,p) + + +/***************************************************************************** + * IAdviseSink2 interface + */ +#define ICOM_INTERFACE IAdviseSink2 +#define IAdviseSink2_METHODS \ + ICOM_VMETHOD1(OnLinkSrcChange, IMoniker*,pmk) +#define IAdviseSink2_IMETHODS \ + IAdviseSink_IMETHODS \ + IAdviseSink2_METHODS +ICOM_DEFINE(IAdviseSink2,IAdviseSink) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IAdviseSink2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IAdviseSink2_AddRef(p) ICOM_CALL (AddRef,p) +#define IAdviseSink2_Release(p) ICOM_CALL (Release,p) +/*** IAdviseSink methods ***/ +#define IAdviseSink2_OnDataChange(p,a,b) ICOM_CALL2(IAdviseSink,OnDataChange,p,a,b) +#define IAdviseSink2_OnViewChange(p,a,b) ICOM_CALL2(IAdviseSink,OnViewChange,p,a,b) +#define IAdviseSink2_OnRename(p,a) ICOM_CALL1(IAdviseSink,OnRename,p,a) +#define IAdviseSink2_OnSave(p) ICOM_CALL (IAdviseSink,OnSave,p) +#define IAdviseSink2_OnClose(p) ICOM_CALL (IAdviseSink,OnClose,p) +/*** IAdviseSink2 methods ***/ +#define IAdviseSink2_OnLinkSrcChange(p,a) ICOM_CALL(OnLinkSrcChange,p,a) + + +/***************************************************************************** + * IDataAdviseHolder interface + */ +#define ICOM_INTERFACE IDataAdviseHolder +#define IDataAdviseHolder_METHODS \ + ICOM_METHOD5(HRESULT,Advise, IDataObject*,pDataObject, FORMATETC*,pFetc, DWORD,advf, IAdviseSink*,pAdvise, DWORD*,pdwConnection) \ + ICOM_METHOD1(HRESULT,Unadvise, DWORD,dwConnection) \ + ICOM_METHOD1(HRESULT,EnumAdvise, IEnumSTATDATA**,ppenumAdvise) \ + ICOM_METHOD3(HRESULT,SendOnDataChange, IDataObject*,pDataObject, DWORD,dwReserved, DWORD,advf) +#define IDataAdviseHolder_IMETHODS \ + IUnknown_IMETHODS \ + IDataAdviseHolder_METHODS +ICOM_DEFINE(IDataAdviseHolder,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDataAdviseHolder_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDataAdviseHolder_AddRef(p) ICOM_CALL (AddRef,p) +#define IDataAdviseHolder_Release(p) ICOM_CALL (Release,p) +/*** IDataAdviseHolder methods ***/ +#define IDataAdviseHolder_Advise(p,a,b,c,d,e) ICOM_CALL5(Advise,p,a,b,c,d,e) +#define IDataAdviseHolder_Unadvise(p,a) ICOM_CALL1(Unadvise,p,a) +#define IDataAdviseHolder_EnumAdvise(p,a) ICOM_CALL1(EnumAdvise,p,a) +#define IDataAdviseHolder_SendOnDataChange(p,a,b,c) ICOM_CALL3(SendOnDataChange,p,a,b,c) + +/* FIXME: not implemented */ +HRESULT WINAPI CreateDataAdviseHolder(LPDATAADVISEHOLDER* ppDAHolder); + + +/***************************************************************************** + * IDataObject interface + */ +#define ICOM_INTERFACE IDataObject +#define IDataObject_METHODS \ + ICOM_METHOD2(HRESULT,GetData, LPFORMATETC,pformatetcIn, STGMEDIUM*,pmedium) \ + ICOM_METHOD2(HRESULT,GetDataHere, LPFORMATETC,pformatetc, STGMEDIUM*,pmedium) \ + ICOM_METHOD1(HRESULT,QueryGetData, LPFORMATETC,pformatetc) \ + ICOM_METHOD2(HRESULT,GetCanonicalFormatEtc, LPFORMATETC,pformatectIn, LPFORMATETC,pformatetcOut) \ + ICOM_METHOD3(HRESULT,SetData, LPFORMATETC,pformatetc, STGMEDIUM*,pmedium, BOOL,fRelease) \ + ICOM_METHOD2(HRESULT,EnumFormatEtc, DWORD,dwDirection, IEnumFORMATETC**,ppenumFormatEtc) \ + ICOM_METHOD4(HRESULT,DAdvise, FORMATETC*,pformatetc, DWORD,advf, IAdviseSink*,pAdvSink, DWORD*,pdwConnection) \ + ICOM_METHOD1(HRESULT,DUnadvise, DWORD,dwConnection) \ + ICOM_METHOD1(HRESULT,EnumDAdvise, IEnumSTATDATA**,ppenumAdvise) +#define IDataObject_IMETHODS \ + IUnknown_IMETHODS \ + IDataObject_METHODS +ICOM_DEFINE(IDataObject,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDataObject_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDataObject_AddRef(p) ICOM_CALL (AddRef,p) +#define IDataObject_Release(p) ICOM_CALL (Release,p) +/*** IDataObject methods ***/ +#define IDataObject_GetData(p,a,b) ICOM_CALL2(GetData,p,a,b) +#define IDataObject_GetDataHere(p,a,b) ICOM_CALL2(GetDataHere,p,a,b) +#define IDataObject_QueryGetData(p,a) ICOM_CALL1(QueryGetData,p,a) +#define IDataObject_GetCanonicalFormatEtc(p,a,b) ICOM_CALL2(GetCanonicalFormatEtc,p,a,b) +#define IDataObject_SetData(p,a,b,c) ICOM_CALL3(SetData,p,a,b,c) +#define IDataObject_EnumFormatEtc(p,a,b) ICOM_CALL2(EnumFormatEtc,p,a,b) +#define IDataObject_DAdvise(p,a,b,c,d) ICOM_CALL4(DAdvise,p,a,b,c,d) +#define IDataObject_DUnadvise(p,a) ICOM_CALL1(DUnadvise,p,a) +#define IDataObject_EnumDAdvise(p,a) ICOM_CALL1(EnumDAdvise,p,a) + + +/***************************************************************************** + * IEnumFORMATETC interface + */ +#define ICOM_INTERFACE IEnumFORMATETC +#define IEnumFORMATETC_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, FORMATETC*,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumFORMATETC**,ppenum) +#define IEnumFORMATETC_IMETHODS \ + IUnknown_IMETHODS \ + IEnumFORMATETC_METHODS +ICOM_DEFINE(IEnumFORMATETC,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumFORMATETC_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumFORMATETC_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumFORMATETC_Release(p) ICOM_CALL (Release,p) +/*** IEnumFORMATETC methods ***/ +#define IEnumFORMATETC_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumFORMATETC_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumFORMATETC_Reset(p) ICOM_CALL (Reset,p) +#define IEnumFORMATETC_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * IEnumSTATDATA interface + */ +#define ICOM_INTERFACE IEnumSTATDATA +#define IEnumSTATDATA_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, STATDATA*,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumSTATDATA**,ppenum) +#define IEnumSTATDATA_IMETHODS \ + IUnknown_IMETHODS \ + IEnumSTATDATA_METHODS +ICOM_DEFINE(IEnumSTATDATA,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumSTATDATA_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumSTATDATA_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumSTATDATA_Release(p) ICOM_CALL (Release,p) +/*** IEnumSTATDATA methods ***/ +#define IEnumSTATDATA_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumSTATDATA_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumSTATDATA_Reset(p) ICOM_CALL (Reset,p) +#define IEnumSTATDATA_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * Additional API + */ + +/* FIXME: not implemented */ +HRESULT WINAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid, REFIID iid, LPVOID* ppv); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_DATAOBJECT_H */ diff --git a/include/ole32/obj_dockingwindowframe.h b/include/ole32/obj_dockingwindowframe.h new file mode 100644 index 0000000..da94b8d --- /dev/null +++ b/include/ole32/obj_dockingwindowframe.h @@ -0,0 +1,45 @@ +/************************************************************ + * IDockingWindowFrame + */ + +#ifndef __WINE_WINE_OBJ_DOCKINGWINDOWFRAME_H +#define __WINE_WINE_OBJ_DOCKINGWINDOWFRAME_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +typedef struct IDockingWindowFrame IDockingWindowFrame, *LPDOCKINGWINDOWFRAME; +DEFINE_GUID (IID_IDockingWindowFrame, 0x47D2657AL, 0x7B27, 0x11D0, 0x8C, 0xA9, 0x00, 0xA0, 0xC9, 0x2D, 0xBF, 0xE8); + +#define DWFRF_NORMAL 0x0000 /* femove toolbar flags*/ +#define DWFRF_DELETECONFIGDATA 0x0001 +#define DWFAF_HIDDEN 0x0001 /* add tolbar*/ + +#define ICOM_INTERFACE IDockingWindowFrame +#define IDockingWindowFrame_METHODS \ + ICOM_METHOD3(HRESULT, AddToolbar, IUnknown*, punkSrc, LPCWSTR, pwszItem, DWORD, dwAddFlags) \ + ICOM_METHOD2(HRESULT, RemoveToolbar, IUnknown*, punkSrc, DWORD, dwRemoveFlags) \ + ICOM_METHOD3(HRESULT, FindToolbar, LPCWSTR, pwszItem, REFIID, riid, LPVOID*, ppvObj) +#define IDockingWindowFrame_IMETHODS \ + IOleWindow_IMETHODS \ + IDockingWindowFrame_METHODS +ICOM_DEFINE(IDockingWindowFrame,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDockingWindowFrame_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDockingWindowFrame_AddRef(p) ICOM_CALL(AddRef,p) +#define IDockingWindowFrame_Release(p) ICOM_CALL(Release,p) +/*** IDockingWindowFrame methods ***/ +#define IDockingWindowFrame_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IDockingWindowFrame_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +#define IDockingWindowFrame_AddToolbar(p,a,b,c) ICOM_CALL3(AddToolbar,p,a,b,c) +#define IDockingWindowFrame_RemoveToolbar(p,a,b) ICOM_CALL2(RemoveToolbar,p,a,b) +#define IDockingWindowFrame_FindToolbar(p,a,b,c) ICOM_CALL3(FindToolbar,p,a,b,c) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_DOCKINGWINDOWFRAME_H */ diff --git a/include/ole32/obj_dragdrop.h b/include/ole32/obj_dragdrop.h new file mode 100644 index 0000000..3410be5 --- /dev/null +++ b/include/ole32/obj_dragdrop.h @@ -0,0 +1,91 @@ +/* + * Defines the COM interfaces and APIs related to OLE Drag and Drop. + */ + +#ifndef __WINE_WINE_OBJ_DRAGDROP_H +#define __WINE_WINE_OBJ_DRAGDROP_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IDropSource, 0x00000121L, 0, 0); +typedef struct IDropSource IDropSource,*LPDROPSOURCE; + +DEFINE_OLEGUID(IID_IDropTarget, 0x00000122L, 0, 0); +typedef struct IDropTarget IDropTarget,*LPDROPTARGET; + +/***************************************************************************** + * DROPEFFECT enumeration + */ +#define MK_ALT (0x20) +#define DROPEFFECT_NONE 0 +#define DROPEFFECT_COPY 1 +#define DROPEFFECT_MOVE 2 +#define DROPEFFECT_LINK 4 +#define DROPEFFECT_SCROLL 0x80000000 +#define DD_DEFSCROLLINSET 11 +#define DD_DEFSCROLLDELAY 50 +#define DD_DEFSCROLLINTERVAL 50 +#define DD_DEFDRAGDELAY 50 +#define DD_DEFDRAGMINDIST 2 + +/***************************************************************************** + * IDropSource interface + */ +#define ICOM_INTERFACE IDropSource +#define IDropSource_METHODS \ + ICOM_METHOD2(HRESULT, QueryContinueDrag, BOOL, fEscapePressed, DWORD, grfKeyState) \ + ICOM_METHOD1(HRESULT, GiveFeedback, DWORD, dwEffect) +#define IDropSource_IMETHODS \ + IUnknown_IMETHODS \ + IDropSource_METHODS +ICOM_DEFINE(IDropSource,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDropSource_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDropSource_AddRef(p) ICOM_CALL (AddRef,p) +#define IDropSource_Release(p) ICOM_CALL (Release,p) +/*** IDropSource methods ***/ +#define IDropSource_QueryContinueDrag(p,a,b) ICOM_CALL2(QueryContinueDrag,p,a,b) +#define IDropSource_GiveFeedback(p,a) ICOM_CALL1(GiveFeedback,p,a) + +/***************************************************************************** + * IDropTarget interface + */ +#define ICOM_INTERFACE IDropTarget +#define IDropTarget_METHODS \ + ICOM_METHOD4(HRESULT, DragEnter, IDataObject*, pDataObject, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect) \ + ICOM_METHOD3(HRESULT, DragOver, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect) \ + ICOM_METHOD(HRESULT, DragLeave) \ + ICOM_METHOD4(HRESULT, Drop, IDataObject*, pDataObject, DWORD, grfKeyState, POINTL, pt, DWORD*, pdwEffect) +#define IDropTarget_IMETHODS \ + IUnknown_IMETHODS \ + IDropTarget_METHODS +ICOM_DEFINE(IDropTarget,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDropTarget_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDropTarget_AddRef(p) ICOM_CALL (AddRef,p) +#define IDropTarget_Release(p) ICOM_CALL (Release,p) +/*** IDropTarget methods ***/ +#define IDropTarget_DragEnter(p,a,b,c,d) ICOM_CALL4(DragEnter,p,a,b,c,d) +#define IDropTarget_DragOver(p,a,b,c) ICOM_CALL3(DragOver,p,a,b,c) +#define IDropTarget_DragLeave(p) ICOM_CALL(DragLeave,p) +#define IDropTarget_Drop(p,a,b,c,d) ICOM_CALL4(Drop,p,a,b,c,d) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_DRAGDROP_H */ + + + + + diff --git a/include/ole32/obj_enumidlist.h b/include/ole32/obj_enumidlist.h new file mode 100644 index 0000000..d27da2c --- /dev/null +++ b/include/ole32/obj_enumidlist.h @@ -0,0 +1,45 @@ +/* + * Defines the COM interfaces and APIs related to EnumIDList + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_ENUMIDLIST_H +#define __WINE_WINE_OBJ_ENUMIDLIST_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +typedef struct IEnumIDList IEnumIDList, *LPENUMIDLIST; + +#define ICOM_INTERFACE IEnumIDList +#define IEnumIDList_METHODS \ + ICOM_METHOD3(HRESULT, Next, ULONG, celt, LPITEMIDLIST*, rgelt, ULONG*, pceltFetched) \ + ICOM_METHOD1(HRESULT, Skip, ULONG, celt) \ + ICOM_METHOD (HRESULT, Reset) \ + ICOM_METHOD1(HRESULT, Clone, IEnumIDList**, ppenum) +#define IEnumIDList_IMETHODS \ + IUnknown_IMETHODS \ + IEnumIDList_METHODS +ICOM_DEFINE(IEnumIDList,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumIDList_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumIDList_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumIDList_Release(p) ICOM_CALL (Release,p) +/*** IEnumIDList methods ***/ +#define IEnumIDList_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumIDList_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumIDList_Reset(p) ICOM_CALL(Reset,p) +#define IEnumIDList_Clone(p,a) ICOM_CALL1(Clone,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_ENUMIDLIST_H */ diff --git a/include/ole32/obj_errorinfo.h b/include/ole32/obj_errorinfo.h new file mode 100644 index 0000000..2e3e816 --- /dev/null +++ b/include/ole32/obj_errorinfo.h @@ -0,0 +1,94 @@ +/* + * Defines the COM interfaces and APIs related to ErrorInfo + */ + +#ifndef __WINE_WINE_OBJ_ERRORINFO_H +#define __WINE_WINE_OBJ_ERRORINFO_H + +DEFINE_GUID(IID_IErrorInfo,0x1CF2B120,0x547D,0x101B,0x8E,0x65,0x08,0x00,0x2B,0x2B,0xD1,0x19); +typedef struct IErrorInfo IErrorInfo,*LPERRORINFO; + +DEFINE_GUID(IID_ICreateErrorInfo,0x22F03340,0x547D,0x101B,0x8E,0x65,0x08,0x00,0x2B,0x2B,0xD1,0x19); +typedef struct ICreateErrorInfo ICreateErrorInfo,*LPCREATEERRORINFO; + +DEFINE_GUID(IID_ISupportErrorInfo,0xDF0B3D60,0x547D,0x101B,0x8E,0x65,0x08,0x00,0x2B,0x2B,0xD1,0x19); +typedef struct ISupportErrorInfo ISupportErrorInfo,*LPSUPPORTERRORINFO; + +/***************************************************************************** + * IErrorInfo + */ +#define ICOM_INTERFACE IErrorInfo +#define IErrorInfo_METHODS \ + ICOM_METHOD1(HRESULT, GetGUID, GUID * , pGUID) \ + ICOM_METHOD1(HRESULT, GetSource, BSTR* ,pBstrSource) \ + ICOM_METHOD1(HRESULT, GetDescription, BSTR*, pBstrDescription) \ + ICOM_METHOD1(HRESULT, GetHelpFile, BSTR*, pBstrHelpFile) \ + ICOM_METHOD1(HRESULT, GetHelpContext, DWORD*, pdwHelpContext) + +#define IErrorInfo_IMETHODS \ + IUnknown_IMETHODS \ + IErrorInfo_METHODS +ICOM_DEFINE(IErrorInfo, IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IErrorInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IErrorInfo_AddRef(p) ICOM_CALL (AddRef,p) +#define IErrorInfo_Release(p) ICOM_CALL (Release,p) +/*** IErrorInfo methods ***/ +#define IErrorInfo_GetGUID(p,a) ICOM_CALL1 (GetGUID,p,a) +#define IErrorInfo_GetSource(p,a) ICOM_CALL1 (GetSource,p,a) +#define IErrorInfo_GetDescription(p,a) ICOM_CALL1 (GetDescription,p,a) +#define IErrorInfo_GetHelpFile(p,a) ICOM_CALL1 (GetHelpFile,p,a) +#define IErrorInfo_GetHelpContext(p,a) ICOM_CALL1 (GetHelpContext,p,a) + +/***************************************************************************** + * ICreateErrorInfo + */ +#define ICOM_INTERFACE ICreateErrorInfo +#define ICreateErrorInfo_METHODS \ + ICOM_METHOD1(HRESULT, SetGUID, REFGUID, rguid) \ + ICOM_METHOD1(HRESULT, SetSource, LPOLESTR, szSource) \ + ICOM_METHOD1(HRESULT, SetDescription, LPOLESTR, szDescription) \ + ICOM_METHOD1(HRESULT, SetHelpFile, LPOLESTR, szHelpFile) \ + ICOM_METHOD1(HRESULT, SetHelpContext, DWORD, dwHelpContext) + +#define ICreateErrorInfo_IMETHODS \ + IUnknown_IMETHODS \ + ICreateErrorInfo_METHODS +ICOM_DEFINE(ICreateErrorInfo, IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ICreateErrorInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ICreateErrorInfo_AddRef(p) ICOM_CALL (AddRef,p) +#define ICreateErrorInfo_Release(p) ICOM_CALL (Release,p) +/*** ICreateErrorInfo methods ***/ +#define ICreateErrorInfo_SetGUID(p,a) ICOM_CALL1 (SetGUID,p,a) +#define ICreateErrorInfo_SetSource(p,a) ICOM_CALL1 (SetSource,p,a) +#define ICreateErrorInfo_SetDescription(p,a) ICOM_CALL1 (SetDescription,p,a) +#define ICreateErrorInfo_SetHelpFile(p,a) ICOM_CALL1 (SetHelpFile,p,a) +#define ICreateErrorInfo_SetHelpContext(p,a) ICOM_CALL1 (SetHelpContext,p,a) + +/***************************************************************************** + * ISupportErrorInfo + */ +#define ICOM_INTERFACE ISupportErrorInfo +#define ISupportErrorInfo_METHODS \ + ICOM_METHOD1(HRESULT, InterfaceSupportsErrorInfo, REFIID, riid ) + +#define ISupportErrorInfo_IMETHODS \ + IUnknown_IMETHODS \ + ISupportErrorInfo_METHODS +ICOM_DEFINE(ISupportErrorInfo, IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ISupportErrorInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ISupportErrorInfo_AddRef(p) ICOM_CALL (AddRef,p) +#define ISupportErrorInfo_Release(p) ICOM_CALL (Release,p) +/*** ISupportErrorInfo methods ***/ +#define ISupportErrorInfo_InterfaceSupportsErrorInfo(p,a) ICOM_CALL1 (InterfaceSupportsErrorInfo,p,a) + + +#endif /* __WINE_WINE_OBJ_ERRORINFO_H */ diff --git a/include/ole32/obj_extracticon.h b/include/ole32/obj_extracticon.h new file mode 100644 index 0000000..f8e96a9 --- /dev/null +++ b/include/ole32/obj_extracticon.h @@ -0,0 +1,51 @@ +/************************************************************ + * IExtractIconA + */ + +#ifndef __WINE_WINE_OBJ_EXTRACTICON_H +#define __WINE_WINE_OBJ_EXTRACTICON_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +#define IID_IExtractIcon WINELIB_NAME_AW(IID_IExtractIcon) + +typedef struct IExtractIconA IExtractIconA,*LPEXTRACTICONA; +#define LPEXTRACTICON WINELIB_NAME_AW(LPEXTRACTICON) + +/* GetIconLocation() input flags*/ +#define GIL_OPENICON 0x0001 /* allows containers to specify an "open" look */ +#define GIL_FORSHELL 0x0002 /* icon is to be displayed in a ShellFolder */ +#define GIL_ASYNC 0x0020 /* this is an async extract, return E_ASYNC */ + +/* GetIconLocation() return flags */ +#define GIL_SIMULATEDOC 0x0001 /* simulate this document icon for this */ +#define GIL_PERINSTANCE 0x0002 /* icons from this class are per instance (each file has its own) */ +#define GIL_PERCLASS 0x0004 /* icons from this class per class (shared for all files of this type) */ +#define GIL_NOTFILENAME 0x0008 /* location is not a filename, must call ::ExtractIcon */ +#define GIL_DONTCACHE 0x0010 /* this icon should not be cached */ + + +#define ICOM_INTERFACE IExtractIconA +#define IExtractIconA_METHODS \ + ICOM_METHOD5(HRESULT, GetIconLocation, UINT, uFlags, LPSTR, szIconFile, UINT, cchMax, INT*, piIndex, UINT *, pwFlags) \ + ICOM_METHOD5(HRESULT, Extract, LPCSTR, pszFile, UINT, nIconIndex, HICON*, phiconLarge, HICON*, phiconSmall, UINT, nIconSize) +#define IExtractIconA_IMETHODS \ + IUnknown_IMETHODS \ + IExtractIconA_METHODS +ICOM_DEFINE(IExtractIconA,IUnknown) +#undef ICOM_INTERFACE + +#define IExtractIconA_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IExtractIconA_AddRef(p) ICOM_CALL(AddRef,p) +#define IExtractIconA_Release(p) ICOM_CALL(Release,p) +#define IExtractIconA_GetIconLocation(p,a,b,c,d,e) ICOM_CALL5(GetIconLocation,p,a,b,c,d,e) +#define IExtractIconA_Extract(p,a,b,c,d,e) ICOM_CALL5(Extract,p,a,b,c,d,e) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_EXTRACTICON_H */ + diff --git a/include/ole32/obj_inplace.h b/include/ole32/obj_inplace.h new file mode 100644 index 0000000..344238b --- /dev/null +++ b/include/ole32/obj_inplace.h @@ -0,0 +1,482 @@ +/* + * Defines the COM interfaces and APIs related to structured data storage. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_INPLACE_H +#define __WINE_WINE_OBJ_INPLACE_H + +struct tagMSG; + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the structures + */ +typedef struct tagOleMenuGroupWidths +{ + LONG width[ 6 ]; +} OLEMENUGROUPWIDTHS, *LPOLEMENUGROUPWIDTHS; + + +typedef struct tagOleInPlaceFrameInfo +{ + UINT cb; + BOOL fMDIApp; + HWND hwndFrame; + HACCEL haccel; + UINT cAccelEntries; +} OLEINPLACEFRAMEINFO, *LPOLEINPLACEFRAMEINFO; + +typedef enum tagOLEGETMONIKER +{ + OLEGETMONIKER_ONLYIFTHERE = 1, + OLEGETMONIKER_FORCEASSIGN = 2, + OLEGETMONIKER_UNASSIGN = 3, + OLEGETMONIKER_TEMPFORUSER = 4 +} OLEGETMONIKER; + +typedef enum tagOLERENDER +{ + OLERENDER_NONE = 0, + OLERENDER_DRAW = 1, + OLERENDER_FORMAT = 2, + OLERENDER_ASIS = 3 +} OLERENDER; + +typedef enum tagUSERCLASSTYPE +{ + USERCLASSTYPE_FULL = 1, + USERCLASSTYPE_SHORT = 2, + USERCLASSTYPE_APPNAME = 3 +} USERCLASSTYPE; + +typedef enum tagOLECLOSE +{ + OLECLOSE_SAVEIFDIRTY = 1, + OLECLOSE_NOSAVE = 2, + OLECLOSE_PROMPTSAVE = 3 +} OLECLOSE; + +typedef enum tagOLEUPDATE +{ + OLEUPDATE_ALWAYS = 1, + OLEUPDATE_ONCALL = 3 +} OLEUPDATE, *LPOLEUPDATE; + +typedef struct tagOLEVERB +{ + LONG lVerb; + LPOLESTR lpszVerbName; + DWORD fuFlags; + DWORD grfAttribs; +} OLEVERB, *LPOLEVERB; + +typedef enum tagOLELINKBIND +{ + OLELINKBIND_EVENIFCLASSDIFF = 1 +} OLELINKBIND; + +typedef enum tagOLEWHICHMK +{ + OLEWHICHMK_CONTAINER = 1, + OLEWHICHMK_OBJREL = 2, + OLEWHICHMK_OBJFULL = 3 +} OLEWHICHMK; + +typedef enum tagBINDSPEED +{ + BINDSPEED_INDEFINITE = 1, + BINDSPEED_MODERATE = 2, + BINDSPEED_IMMEDIATE = 3 +} BINDSPEED; + +typedef enum tagOLECONTF +{ + OLECONTF_EMBEDDINGS = 1, + OLECONTF_LINKS = 2, + OLECONTF_OTHERS = 4, + OLECONTF_OLNYUSER = 8, + OLECONTF_ONLYIFRUNNING = 16 +} OLECONTF; + +typedef HGLOBAL HOLEMENU; +typedef LPRECT LPBORDERWIDTHS; +typedef LPCRECT LPCBORDERWIDTHS; + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IOleWindow, 0x00000114L, 0, 0); +typedef struct IOleWindow IOleWindow, *LPOLEWINDOW; + +DEFINE_OLEGUID(IID_IOleInPlaceObject, 0x00000113L, 0, 0); +typedef struct IOleInPlaceObject IOleInPlaceObject, *LPOLEINPLACEOBJECT; + +DEFINE_OLEGUID(IID_IOleInPlaceActiveObject, 0x00000117L, 0, 0); +typedef struct IOleInPlaceActiveObject IOleInPlaceActiveObject, *LPOLEINPLACEACTIVEOBJECT; + +DEFINE_OLEGUID(IID_IOleInPlaceUIWindow, 0x00000115L, 0, 0); +typedef struct IOleInPlaceUIWindow IOleInPlaceUIWindow, *LPOLEINPLACEUIWINDOW; + +DEFINE_OLEGUID(IID_IOleInPlaceFrame, 0x00000116L, 0, 0); +typedef struct IOleInPlaceFrame IOleInPlaceFrame, *LPOLEINPLACEFRAME; + +DEFINE_OLEGUID(IID_IOleInPlaceSite, 0x00000119L, 0, 0); +typedef struct IOleInPlaceSite IOleInPlaceSite, *LPOLEINPLACESITE; + +DEFINE_OLEGUID(IID_IOleClientSite, 0x00000118L, 0, 0); +typedef struct IOleClientSite IOleClientSite, *LPOLECLIENTSITE; + +DEFINE_OLEGUID(IID_IOleContainer, 0x0000011bL, 0, 0); +typedef struct IOleContainer IOleContainer, *LPOLECONTAINER; + +DEFINE_OLEGUID(IID_IParseDisplayName, 0x0000011aL, 0, 0); +typedef struct IParseDisplayName IParseDisplayName, *LPPARSEDISPLAYNAME; + +DEFINE_OLEGUID(IID_IOleItemContainer, 0x0000011cL, 0, 0); +typedef struct IOleItemContainer IOleItemContainer, *LPOLEITEMCONTAINER; + +DEFINE_OLEGUID(IID_IOleLink, 0x0000011dL, 0, 0); +typedef struct IOleLink IOleLink, *LPOLELINK; + +/***************************************************************************** + * IOleWindow interface + */ +#define ICOM_INTERFACE IOleWindow +#define IOleWindow_METHODS \ + ICOM_METHOD1(HRESULT,GetWindow, HWND*,phwnd) \ + ICOM_METHOD1(HRESULT,ContextSensitiveHelp, BOOL,fEnterMode) +#define IOleWindow_IMETHODS \ + IUnknown_IMETHODS \ + IOleWindow_METHODS +ICOM_DEFINE(IOleWindow,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleWindow_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleWindow_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleWindow_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleWindow_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleWindow_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) + + +/***************************************************************************** + * IOleInPlaceObject interface + */ +#define ICOM_INTERFACE IOleInPlaceObject +#define IOleInPlaceObject_METHODS \ + ICOM_METHOD (HRESULT,InPlaceDeactivate) \ + ICOM_METHOD (HRESULT,UIDeactivate) \ + ICOM_METHOD2(HRESULT,SetObjectRects, LPCRECT,lprcPosRect, LPCRECT,lprcClipRect) \ + ICOM_METHOD (HRESULT,ReactivateAndUndo) +#define IOleInPlaceObject_IMETHODS \ + IOleWindow_IMETHODS \ + IOleInPlaceObject_METHODS +ICOM_DEFINE(IOleInPlaceObject,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceObject_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceObject_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceObject_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceObject_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceObject_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceObject methods ***/ +#define IOleInPlaceObject_InPlaceDeactivate(p) ICOM_CALL (InPlaceDeactivate,p) +#define IOleInPlaceObject_UIDeactivate(p) ICOM_CALL (UIDeactivate,p) +#define IOleInPlaceObject_SetObjectRects(p,a,b) ICOM_CALL2(SetObjectRects,p,a,b) +#define IOleInPlaceObject_ReactivateAndUndo(p) ICOM_CALL (ReactivateAndUndo,p) + +/***************************************************************************** + * IOleInPlaceActiveObject interface + */ +#define ICOM_INTERFACE IOleInPlaceActiveObject +#define IOleInPlaceActiveObject_METHODS \ + ICOM_METHOD1(HRESULT,TranslateAccelerator, struct tagMSG*,lpmsg) \ + ICOM_METHOD1(HRESULT,OnFrameWindowActivate, BOOL,fActivate) \ + ICOM_METHOD1(HRESULT,OnDocWindowActivate, BOOL,fActivate) \ + ICOM_METHOD3(HRESULT,ResizeBorder, LPCRECT,prcBorder, IOleInPlaceUIWindow*,pUIWindow, BOOL,fWindowFrame) \ + ICOM_METHOD1(HRESULT,EnableModeless, BOOL,fEnable) +#define IOleInPlaceActiveObject_IMETHODS \ + IOleWindow_IMETHODS \ + IOleInPlaceActiveObject_METHODS +ICOM_DEFINE(IOleInPlaceActiveObject,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceActiveObject_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceActiveObject_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceActiveObject_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceActiveObject_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceActiveObject_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceActiveObject methods ***/ +#define IOleInPlaceActiveObject_TranslateAccelerator(p,a) ICOM_CALL1(TranslateAccelerator,p,a) +#define IOleInPlaceActiveObject_OnFrameWindowActivate(p,a) ICOM_CALL1(OnFrameWindowActivate,p,a) +#define IOleInPlaceActiveObject_OnDocWindowActivate(p,a) ICOM_CALL1(OnDocWindowActivate,p,a) +#define IOleInPlaceActiveObject_ResizeBorder(p,a,b,c) ICOM_CALL3(ResizeBorder,p,a,b,c) +#define IOleInPlaceActiveObject_EnableModeless(p,a) ICOM_CALL1(EnableModeless,p,a) + +/***************************************************************************** + * IOleInPlaceUIWindow interface + */ +#define ICOM_INTERFACE IOleInPlaceUIWindow +#define IOleInPlaceUIWindow_METHODS \ + ICOM_METHOD1(HRESULT,GetBorder, LPRECT,lprectBorder) \ + ICOM_METHOD1(HRESULT,RequestBorderSpace, LPCBORDERWIDTHS,pborderwidths) \ + ICOM_METHOD1(HRESULT,SetBorderSpace, LPCBORDERWIDTHS,pborderwidths) \ + ICOM_METHOD2(HRESULT,SetActiveObject, IOleInPlaceActiveObject*,pActiveObject, LPCOLESTR,pszObjName) +#define IOleInPlaceUIWindow_IMETHODS \ + IOleWindow_IMETHODS \ + IOleInPlaceUIWindow_METHODS +ICOM_DEFINE(IOleInPlaceUIWindow,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceUIWindow_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceUIWindow_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceUIWindow_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceUIWindow_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceUIWindow_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceUIWindow methods ***/ +#define IOleInPlaceUIWindow_GetBorder(p,a) ICOM_CALL1(GetBorder,p,a) +#define IOleInPlaceUIWindow_RequestBorderSpace(p,a) ICOM_CALL1(RequestBorderSpace,p,a) +#define IOleInPlaceUIWindow_SetBorderSpace(p,a) ICOM_CALL1(SetBorderSpace,p,a) +#define IOleInPlaceUIWindow_SetActiveObject(p,a,b) ICOM_CALL2(SetActiveObject,p,a,b) + + +/***************************************************************************** + * IOleInPlaceFrame interface + */ +#define ICOM_INTERFACE IOleInPlaceFrame +#define IOleInPlaceFrame_METHODS \ + ICOM_METHOD2 (HRESULT,InsertMenus, HMENU,hemnuShared, LPOLEMENUGROUPWIDTHS,lpMenuWidths) \ + ICOM_METHOD3 (HRESULT,SetMenu, HMENU,hemnuShared, HOLEMENU,holemenu, HWND,hwndActiveObject) \ + ICOM_METHOD1 (HRESULT,RemoveMenus, HMENU,hemnuShared) \ + ICOM_METHOD1 (HRESULT,SetStatusText, LPCOLESTR,pszStatusText) \ + ICOM_METHOD1 (HRESULT,EnableModeless, BOOL,fEnable) \ + ICOM_METHOD2 (HRESULT,TranslateAccelerator, struct tagMSG*,lpmsg, WORD,wID) +#define IOleInPlaceFrame_IMETHODS \ + IOleInPlaceUIWindow_IMETHODS \ + IOleInPlaceFrame_METHODS +ICOM_DEFINE(IOleInPlaceFrame,IOleInPlaceUIWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceFrame_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceFrame_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceFrame_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceFrame_GetWindow ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceFrame_ContextSensitiveHelp ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceUIWindow methods ***/ +#define IOleInPlaceFrame_GetBorder ICOM_CALL1(GetBorder,p,a) +#define IOleInPlaceFrame_RequestBorderSpace ICOM_CALL1(RequestBorderSpace,p,a) +#define IOleInPlaceFrame_SetBorderSpace ICOM_CALL1(SetBorderSpace,p,a) +#define IOleInPlaceFrame_SetActiveObject ICOM_CALL2(SetActiveObject,p,a,b) +/*** IOleInPlaceFrame methods ***/ +#define IOleInPlaceFrame_InsertMenus ICOM_CALL2(InsertMenus,p,a,b) +#define IOleInPlaceFrame_SetMenu ICOM_CALL3(SetMenu,p,a,b,c) +#define IOleInPlaceFrame_RemoveMenus ICOM_CALL1(RemoveMenus,p,a) +#define IOleInPlaceFrame_SetStatusText ICOM_CALL1(SetStatusText,p,a) +#define IOleInPlaceFrame_EnableModeless ICOM_CALL1(EnableModeless,p,a) +#define IOleInPlaceFrame_TranslateAccelerator ICOM_CALL2(TranslateAccelerator,p,a,b) + + +/***************************************************************************** + * IOleInPlaceSite interface + */ +#define ICOM_INTERFACE IOleInPlaceSite +#define IOleInPlaceSite_METHODS \ + ICOM_METHOD (HRESULT,CanInPlaceActivate) \ + ICOM_METHOD (HRESULT,OnInPlaceActivate) \ + ICOM_METHOD (HRESULT,OnUIActivate) \ + ICOM_METHOD5(HRESULT,GetWindowContext, IOleInPlaceFrame**,ppFrame, IOleInPlaceUIWindow**,ppDoc, LPRECT,lprcPosRect, LPRECT,lprcClipRect, LPOLEINPLACEFRAMEINFO,lpFrameInfo) \ + ICOM_METHOD1(HRESULT,Scroll, SIZE,scrollExtant) \ + ICOM_METHOD1(HRESULT,OnUIDeactivate, BOOL,fUndoable) \ + ICOM_METHOD (HRESULT,OnInPlaceDeactivate) \ + ICOM_METHOD (HRESULT,DiscardUndoState) \ + ICOM_METHOD (HRESULT,DeactivateAndUndo) \ + ICOM_METHOD1(HRESULT,OnPosRectChange, LPCRECT,lprcPosRect) +#define IOleInPlaceSite_IMETHODS \ + IOleWindow_IMETHODS \ + IOleInPlaceSite_METHODS +ICOM_DEFINE(IOleInPlaceSite,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleInPlaceSite_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleInPlaceSite_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleInPlaceSite_Release(p) ICOM_CALL (Release,p) +/*** IOleWindow methods ***/ +#define IOleInPlaceSite_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IOleInPlaceSite_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +/*** IOleInPlaceSite methods ***/ +#define IOleInPlaceSite_CanInPlaceActivate(p) ICOM_CALL (CanInPlaceActivate,p) +#define IOleInPlaceSite_OnInPlaceActivate(p) ICOM_CALL (OnInPlaceActivate,p) +#define IOleInPlaceSite_OnUIActivate(p) ICOM_CALL (OnUIActivate,p) +#define IOleInPlaceSite_GetWindowContext(p,a,b,c,d,e) ICOM_CALL5(GetWindowContext,p,a,b,c,d,e) +#define IOleInPlaceSite_Scroll(p,a) ICOM_CALL1(Scroll,p,a) +#define IOleInPlaceSite_OnUIDeactivate(p,a) ICOM_CALL1(OnUIDeactivate,p,a) +#define IOleInPlaceSite_OnInPlaceDeactivate(p) ICOM_CALL (OnInPlaceDeactivate,p) +#define IOleInPlaceSite_DiscardUndoState(p) ICOM_CALL (DiscardUndoState,p) +#define IOleInPlaceSite_DeactivateAndUndo(p) ICOM_CALL (DeactivateAndUndo,p) +#define IOleInPlaceSite_OnPosRectChange(p,a) ICOM_CALL1(OnPosRectChange,p,a) + + +/***************************************************************************** + * IOleClientSite interface + */ +#define ICOM_INTERFACE IOleClientSite +#define IOleClientSite_METHODS \ + ICOM_METHOD (HRESULT,SaveObject) \ + ICOM_METHOD3(HRESULT,GetMoniker, DWORD,dwAssign, DWORD,dwWhichMoniker, IMoniker**,ppmk) \ + ICOM_METHOD1(HRESULT,GetContainer, IOleContainer**,ppContainer) \ + ICOM_METHOD (HRESULT,ShowObject) \ + ICOM_METHOD1(HRESULT,OnShowWindow, BOOL,fShow) \ + ICOM_METHOD (HRESULT,RequestNewObjectLayout) +#define IOleClientSite_IMETHODS \ + IUnknown_IMETHODS \ + IOleClientSite_METHODS +ICOM_DEFINE(IOleClientSite,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleClientSite_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleClientSite_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleClientSite_Release(p) ICOM_CALL (Release,p) +/*** IOleClientSite methods ***/ +#define IOleClientSite_SaveObject(p) ICOM_CALL (SaveObject,p) +#define IOleClientSite_GetMoniker(p,a,b,c) ICOM_CALL3(GetMoniker,p,a,b,c) +#define IOleClientSite_GetContainer(p,a) ICOM_CALL1(GetContainer,p,a) +#define IOleClientSite_ShowObject(p) ICOM_CALL (ShowObject,p) +#define IOleClientSite_OnShowWindow(p,a) ICOM_CALL1(OnShowWindow,p,a) +#define IOleClientSite_RequestNewObjectLayout(p) ICOM_CALL (RequestNewObjectLayout(p) + + +/***************************************************************************** + * IParseDisplayName interface + */ +#define ICOM_INTERFACE IParseDisplayName +#define IParseDisplayName_METHODS \ + ICOM_METHOD4(HRESULT,ParseDisplayName, IBindCtx*,pbc, LPOLESTR,pszDisplayName, ULONG*,pchEaten, IMoniker**,ppmkOut) +#define IParseDisplayName_IMETHODS \ + IUnknown_IMETHODS \ + IParseDisplayName_METHODS +ICOM_DEFINE(IParseDisplayName,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IParseDisplayName_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IParseDisplayName_AddRef(p) ICOM_CALL (AddRef,p) +#define IParseDisplayName_Release(p) ICOM_CALL (Release,p) +/*** IParseDisplayName methods ***/ +#define IParseDisplayName_ParseDisplayName(p,a,b,c,d) ICOM_CALL4(ParseDisplayName,p,a,b,c,d) + + +/***************************************************************************** + * IOleContainer interface + */ +#define ICOM_INTERFACE IOleContainer +#define IOleContainer_METHODS \ + ICOM_METHOD2(HRESULT,EnumObjects, DWORD,grfFlags, IEnumUnknown**,ppenum) \ + ICOM_METHOD1(HRESULT,LockContainer, BOOL,fLock) +#define IOleContainer_IMETHODS \ + IParseDisplayName_IMETHODS \ + IOleContainer_METHODS +ICOM_DEFINE(IOleContainer,IParseDisplayName) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleContainer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleContainer_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleContainer_Release(p) ICOM_CALL (Release,p) +/*** IParseDisplayName methods ***/ +#define IOleContainer_ParseDisplayName(p,a,b,c,d) ICOM_CALL4(ParseDisplayName,p,a,b,c,d) +/*** IOleClientSite methods ***/ +#define IOleContainer_EnumObjects(p,a,b) ICOM_CALL (EnumObjects,p,a,b) +#define IOleContainer_LockContainer(p,a) ICOM_CALL3(LockContainer,p,a) + + +/***************************************************************************** + * IOleItemContainer interface + */ +#ifdef __WINE__ +#undef GetObject +#endif + +#define ICOM_INTERFACE IOleItemContainer +#define IOleItemContainer_METHODS \ + ICOM_METHOD5(HRESULT,GetObject, LPOLESTR,pszItem, DWORD,dwSpeedNeeded, IBindCtx*,pbc, REFIID,riid, void**,ppvObject) \ + ICOM_METHOD4(HRESULT,GetObjectStorage, LPOLESTR,pszItem, IBindCtx*,pbc, REFIID,riid, void**,ppvStorage) \ + ICOM_METHOD1(HRESULT,IsRunning, LPOLESTR,pszItem) +#define IOleItemContainer_IMETHODS \ + IOleContainer_IMETHODS \ + IOleItemContainer_METHODS +ICOM_DEFINE(IOleItemContainer,IOleContainer) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleItemContainer_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleItemContainer_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleItemContainer_Release(p) ICOM_CALL (Release,p) +/*** IParseDisplayName methods ***/ +#define IOleItemContainer_GetObject(p,a,b,c,d,e) ICOM_CALL5(GetObject,p,a,b,c,d,e) +#define IOleItemContainer_GetObjectStorage(p,a,b,c,d) ICOM_CALL4(GetObjectStorage,p,a,b,c,d) +#define IOleItemContainer_IsRunning(p,a) ICOM_CALL1(IsRunning,p,a) + + +/***************************************************************************** + * IOleItemContainer interface + */ +#define ICOM_INTERFACE IOleLink +#define IOleLink_METHODS \ + ICOM_METHOD1(HRESULT,SetUpdateOptions, DWORD,dwUpdateOpt) \ + ICOM_METHOD1(HRESULT,GetUpdateOptions, DWORD*,pdwUpdateOpt) \ + ICOM_METHOD2(HRESULT,SetSourceMoniker, IMoniker*,pmk, REFCLSID,rclsid) \ + ICOM_METHOD1(HRESULT,GetSourceMoniker, IMoniker**,ppmk) \ + ICOM_METHOD1(HRESULT,SetSourceDisplayName, LPCOLESTR,pszStatusText) \ + ICOM_METHOD1(HRESULT,GetSourceDisplayName, LPOLESTR*,ppszDisplayName) \ + ICOM_METHOD2(HRESULT,BindToSource, DWORD,bindflags, IBindCtx*,pbc) \ + ICOM_METHOD (HRESULT,BindIfRunning) \ + ICOM_METHOD1(HRESULT,GetBoundSource, IUnknown**,ppunk) \ + ICOM_METHOD (HRESULT,UnBindSource) \ + ICOM_METHOD1(HRESULT,Update, IBindCtx*,pbc) +#define IOleLink_IMETHODS \ + IUnknown_IMETHODS \ + IOleLink_METHODS +ICOM_DEFINE(IOleLink,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleLink_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleLink_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleLink_Release(p) ICOM_CALL (Release,p) +/*** IOleLink methods ***/ +#define IOleLink_SetUpdateOptions(p,a) ICOM_CALL1(SetUpdateOptions,p,a) +#define IOleLink_GetUpdateOptions(p,a) ICOM_CALL1(GetUpdateOptions,p,a) +#define IOleLink_SetSourceMoniker(p,a,b) ICOM_CALL2(SetSourceMoniker,p,a,b) +#define IOleLink_GetSourceMoniker(p,a) ICOM_CALL1(GetSourceMoniker,p,a) +#define IOleLink_SetSourceDisplayName(p,a) ICOM_CALL1(SetSourceDisplayName,p,a) +#define IOleLink_GetSourceDisplayName(p,a) ICOM_CALL1(GetSourceDisplayName,p,a) +#define IOleLink_BindToSource(p,a,b) ICOM_CALL2(BindToSource,p,a,b) +#define IOleLink_BindIfRunning(p) ICOM_CALL (BindIfRunning,p) +#define IOleLink_GetBoundSource(p,a) ICOM_CALL1(GetBoundSource,p,a) +#define IOleLink_UnBindSource(p) ICOM_CALL (UnBindSource,p) +#define IOleLink_Update(p,a) ICOM_CALL1(Update,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_INPLACE_H */ + + diff --git a/include/ole32/obj_marshal.h b/include/ole32/obj_marshal.h new file mode 100644 index 0000000..e365618 --- /dev/null +++ b/include/ole32/obj_marshal.h @@ -0,0 +1,111 @@ +/* + * Defines the COM interfaces and APIs that allow an interface to + * specify a custom marshaling for its objects. + */ + +#ifndef __WINE_WINE_OBJ_MARSHAL_H +#define __WINE_WINE_OBJ_MARSHAL_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IMarshal, 0x00000003L, 0, 0); +typedef struct IMarshal IMarshal,*LPMARSHAL; + +DEFINE_OLEGUID(IID_IStdMarshalInfo, 0x00000018L, 0, 0); +typedef struct IStdMarshalInfo IStdMarshalInfo,*LPSTDMARSHALINFO; + + +/***************************************************************************** + * IMarshal interface + */ +#define ICOM_INTERFACE IMarshal +#define IMarshal_METHODS \ + ICOM_METHOD6(HRESULT,GetUnmarshalClass, REFIID,riid, void*,pv, DWORD,dwDestContext, void*,pvDestContext, DWORD,mshlflags, CLSID*,pCid) \ + ICOM_METHOD6(HRESULT,GetMarshalSizeMax, REFIID,riid, void*,pv, DWORD,dwDestContext, void*,pvDestContext, DWORD,mshlflags, DWORD*,pSize) \ + ICOM_METHOD6(HRESULT,MarshalInterface, IStream*,pStm, REFIID,riid, void*,pv, DWORD,dwDestContext, void*,pvDestContext, DWORD,mshlflags) \ + ICOM_METHOD3(HRESULT,UnmarshalInterface, IStream*,pStm, REFIID,riid, void**,ppv) \ + ICOM_METHOD1(HRESULT,ReleaseMarshalData, IStream*,pStm) \ + ICOM_METHOD1(HRESULT,DisconnectObject, DWORD,dwReserved) +#define IMarshal_IMETHODS \ + IUnknown_IMETHODS \ + IMarshal_METHODS +ICOM_DEFINE(IMarshal,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IMarshal_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IMarshal_AddRef(p) ICOM_CALL (AddRef,p) +#define IMarshal_Release(p) ICOM_CALL (Release,p) +/*** IMarshal methods ***/ +#define IMarshal_GetUnmarshalClass(p,a,b,c,d,e,f) ICOM_CALL6(GetUnmarshalClass,p,a,b,c,d,e,f) +#define IMarshal_GetMarshalSizeMax(p,a,b,c,d,e,f) ICOM_CALL6(GetMarshalSizeMax,p,a,b,c,d,e,f) +#define IMarshal_MarshalInterface(p,a,b,c,d,e,f) ICOM_CALL6(MarshalInterface,p,a,b,c,d,e,f) +#define IMarshal_UnmarshalInterface(p,a,b,c) ICOM_CALL3(UnmarshalInterface,p,a,b,c) +#define IMarshal_ReleaseMarshalData(p,a) ICOM_CALL1(ReleaseMarshalData,p,a) +#define IMarshal_DisconnectObject(p,a) ICOM_CALL1(DisconnectObject,p,a) + + +/***************************************************************************** + * IStdMarshalInfo interface + */ +#define ICOM_INTERFACE IStdMarshalInfo +#define IStdMarshalInfo_METHODS \ + ICOM_METHOD3(HRESULT,GetClassForHandler, DWORD,dwDestContext, void*,pvDestContext, CLSID*,pClsid) +#define IStdMarshalInfo_IMETHODS \ + IUnknown_IMETHODS \ + IStdMarshalInfo_METHODS +ICOM_DEFINE(IStdMarshalInfo,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IStdMarshalInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IStdMarshalInfo_AddRef(p) ICOM_CALL (AddRef,p) +#define IStdMarshalInfo_Release(p) ICOM_CALL (Release,p) +/*** IStdMarshalInfo methods ***/ +#define IStdMarshalInfo_GetClassForHandler(p,a,b,c) ICOM_CALL3(GetClassForHandler,p,a,b,c) + + +/***************************************************************************** + * Additional marshalling API + */ + +/* FIXME: not implemented */ +HRESULT WINAPI CoCreateFreeThreadedMarshaler(LPUNKNOWN punkOuter, LPUNKNOWN* ppunkMarshal); + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID iid, LPVOID* ppv); + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetMarshalSizeMax(ULONG* pulSize, REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags); + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, LPMARSHAL* ppMarshal); + +/* FIXME: not implemented */ +HRESULT WINAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult); + +/* FIXME: not implemented */ +HRESULT WINAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags); + +/* FIXME: not implemented */ +HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM* ppStm); + +/* FIXME: not implemented */ +HRESULT WINAPI CoReleaseMarshalData(LPSTREAM pStm); + +/* FIXME: not implemented */ +HRESULT WINAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT* phresult); + +/* FIXME: not implemented */ +HRESULT WINAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID* ppv); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_MARSHAL_H */ diff --git a/include/ole32/obj_misc.h b/include/ole32/obj_misc.h new file mode 100644 index 0000000..0a312c1 --- /dev/null +++ b/include/ole32/obj_misc.h @@ -0,0 +1,192 @@ +/* + * Defines miscellaneous COM interfaces and APIs defined in objidl.h. + * These did not really fit into the other categories, whould have + * required their own specific category or are too rarely used to be + * put in 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_MISC_H +#define __WINE_WINE_OBJ_MISC_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IEnumString, 0x00000101L, 0, 0); +typedef struct IEnumString IEnumString,*LPENUMSTRING; + +DEFINE_OLEGUID(IID_IEnumUnknown, 0x00000100L, 0, 0); +typedef struct IEnumUnknown IEnumUnknown,*LPENUMUNKNOWN; + +DEFINE_OLEGUID(IID_IMallocSpy, 0x0000001dL, 0, 0); +typedef struct IMallocSpy IMallocSpy,*LPMALLOCSPY; + +DEFINE_OLEGUID(IID_IMultiQI, 0x00000020L, 0, 0); +typedef struct IMultiQI IMultiQI,*LPMULTIQI; + + +/***************************************************************************** + * IEnumString interface + */ +#define ICOM_INTERFACE IEnumString +#define IEnumString_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, LPOLESTR*,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT, Clone, IEnumString**, ppenum) +#define IEnumString_IMETHODS \ + IUnknown_IMETHODS \ + IEnumString_METHODS +ICOM_DEFINE(IEnumString,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumString_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumString_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumString_Release(p) ICOM_CALL (Release,p) +/*** IEnumString methods ***/ +#define IEnumString_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumString_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumString_Reset(p) ICOM_CALL (Reset,p) +#define IEnumString_Clone(p,a) ICOM_CALL1(Clone,p,a) + + + +/***************************************************************************** + * IEnumUnknown interface + */ +#define ICOM_INTERFACE IEnumUnknown +#define IEnumUnknown_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, IUnknown**,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumUnknown**,ppenum) +#define IEnumUnknown_IMETHODS \ + IUnknown_IMETHODS \ + IEnumUnknown_METHODS +ICOM_DEFINE(IEnumUnknown,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumUnknown_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumUnknown_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumUnknown_Release(p) ICOM_CALL (Release,p) +/*** IEnumUnknown methods ***/ +#define IEnumUnknown_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumUnknown_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumUnknown_Reset(p) ICOM_CALL (Reset,p) +#define IEnumUnknown_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * IMallocSpy interface + */ +#define ICOM_INTERFACE IMallocSpy +#define IMallocSpy_METHODS \ + ICOM_METHOD1 (ULONG,PreAlloc, ULONG,cbRequest) \ + ICOM_VMETHOD1( PostAlloc, void*,pActual) \ + ICOM_METHOD2 (PVOID,PreFree, void*,pRequest, BOOL,fSpyed) \ + ICOM_VMETHOD1( PostFree, BOOL,fSpyed) \ + ICOM_METHOD4 (ULONG,PreRealloc, void*,pRequest, ULONG,cbRequest, void**,ppNewRequest, BOOL,fSpyed) \ + ICOM_METHOD2 (PVOID,PostRealloc, void*,pActual, BOOL,fSpyed) \ + ICOM_METHOD2 (PVOID,PreGetSize, void*,pRequest, BOOL,fSpyed) \ + ICOM_METHOD2 (ULONG,PostGetSize, ULONG,cbActual, BOOL,fSpyed) \ + ICOM_METHOD2 (PVOID,PreDidAlloc, void*,pRequest, BOOL,fSpyed) \ + ICOM_METHOD3 (int, PostDidAlloc, void*,pRequest, BOOL,fSpyed, int,fActual) \ + ICOM_METHOD (int, PreHeapMinimize) \ + ICOM_METHOD (int, PostHeapMinimize) +#define IMallocSpy_IMETHODS \ + IUnknown_IMETHODS \ + IMallocSpy_METHODS +ICOM_DEFINE(IMallocSpy,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IMallocSpy_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IMallocSpy_AddRef(p) ICOM_CALL (AddRef,p) +#define IMallocSpy_Release(p) ICOM_CALL (Release,p) +/*** IMallocSpy methods ***/ +#define IMallocSpy_PreAlloc(p,a) ICOM_CALL1(PreAlloc,p,a) +#define IMallocSpy_PostAlloc(p,a) ICOM_CALL1(PostAlloc,p,a) +#define IMallocSpy_PreFree(p,a,b) ICOM_CALL2(PreFree,p,a,b) +#define IMallocSpy_PostFree(p,a) ICOM_CALL1(PostFree,p,a) +#define IMallocSpy_PreRealloc(p,a,b,c,d) ICOM_CALL4(PreRealloc,p,a,b,c,d) +#define IMallocSpy_PostRealloc(p,a,b) ICOM_CALL2(PostRealloc,p,a,b) +#define IMallocSpy_PreGetSize(p,a,b) ICOM_CALL2(PreGetSize,p,a,b) +#define IMallocSpy_PostGetSize(p,a,b) ICOM_CALL2(PostGetSize,p,a,b) +#define IMallocSpy_PreDidAlloc(p,a,b) ICOM_CALL2(PreDidAlloc,p,a,b) +#define IMallocSpy_PostDidAlloc(p,a,b,c) ICOM_CALL3(PostDidAlloc,p,a,b,c) +#define IMallocSpy_PreHeapMinimize(p) ICOM_CALL (PreHeapMinimize,p) +#define IMallocSpy_PostHeapMinimize(p) ICOM_CALL (PostHeapMinimize,p) + +/* FIXME: not implemented */ +HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy); + +/* FIXME: not implemented */ +HRESULT WINAPI CoRevokeMallocSpy(void); + +HRESULT WINAPI CoFileTimeNow(FILETIME* lpFileTime); + + +/***************************************************************************** + * IMultiQI interface + */ +typedef struct tagMULTI_QI +{ + const IID* pIID; + IUnknown* pItf; + HRESULT hr; +} MULTI_QI; + +#define ICOM_INTERFACE IMultiQI +#define IMultiQI_METHODS \ + ICOM_METHOD2(HRESULT,QueryMultipleInterfaces, ULONG,cMQIs, MULTI_QI*,pMQIs) +#define IMultiQI_IMETHODS \ + IUnknown_IMETHODS \ + IMultiQI_METHODS +ICOM_DEFINE(IMultiQI,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IMultiQI_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IMultiQI_AddRef(p) ICOM_CALL (AddRef,p) +#define IMultiQI_Release(p) ICOM_CALL (Release,p) +/*** IMultiQI methods ***/ +#define IMultiQI_QueryMultipleInterfaces(p,a,b) ICOM_CALL2(QueryMultipleInterfaces,p,a,b) + + +/***************************************************************************** + * Additional API + */ + +DWORD WINAPI CoBuildVersion(void); + +DWORD WINAPI CoGetCurrentProcess(void); + +/* FIXME: unimplemented */ +HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew); + +/* FIXME: unimplemented */ +HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew); + +HRESULT WINAPI CoCreateInstance( + REFCLSID rclsid, + LPUNKNOWN pUnkOuter, + DWORD dwClsContext, + REFIID iid, + LPVOID *ppv); + +HRESULT WINAPI CoCreateInstanceEx(REFCLSID rclsid, + LPUNKNOWN pUnkOuter, + DWORD dwClsContext, + COSERVERINFO* pServerInfo, + ULONG cmq, + MULTI_QI* pResults); +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_MISC_H */ diff --git a/include/ole32/obj_moniker.h b/include/ole32/obj_moniker.h new file mode 100644 index 0000000..a08a7e9 --- /dev/null +++ b/include/ole32/obj_moniker.h @@ -0,0 +1,350 @@ +/* + * Defines the COM interfaces and APIs related to the moniker functionality. + */ +#ifndef __WINE_WINE_OBJ_MONIKER_H +#define __WINE_WINE_OBJ_MONIKER_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IBindCtx,0xe,0,0); +typedef struct IBindCtx IBindCtx,*LPBINDCTX; +typedef LPBINDCTX LPBC; + +DEFINE_OLEGUID(IID_IClassActivator, 0x00000140L, 0, 0); +typedef struct IClassActivator IClassActivator,*LPCLASSACTIVATOR; + +DEFINE_OLEGUID(IID_IEnumMoniker, 0x00000102L, 0, 0); +typedef struct IEnumMoniker IEnumMoniker,*LPENUMMONIKER; + +DEFINE_OLEGUID(IID_IMoniker, 0x0000000fL, 0, 0); +typedef struct IMoniker IMoniker,*LPMONIKER; + +DEFINE_GUID (IID_IROTData, 0xf29f6bc0L, 0x5021, 0x11ce, 0xaa, 0x15, 0x00, 0x00, 0x69, 0x01, 0x29, 0x3f); +typedef struct IROTData IROTData,*LPROTDATA; + +DEFINE_OLEGUID(IID_IRunnableObject, 0x00000126L, 0, 0); +typedef struct IRunnableObject IRunnableObject,*LPRUNNABLEOBJECT; + +DEFINE_OLEGUID(IID_IRunningObjectTable, 0x00000010L, 0, 0); +typedef struct IRunningObjectTable IRunningObjectTable,*LPRUNNINGOBJECTTABLE; + +DEFINE_GUID( CLSID_FileMoniker,0x00000303,0,0,0xc0,0,0,0,0,0,0,0x46); + +DEFINE_GUID( CLSID_ItemMoniker,0x00000304,0,0,0xc0,0,0,0,0,0,0,0x46); + +DEFINE_GUID( CLSID_AntiMoniker,0x00000305,0,0,0xc0,0,0,0,0,0,0,0x46); + +DEFINE_GUID( CLSID_CompositeMoniker,0x00000309,0,0,0xc0,0,0,0,0,0,0,0x46); + +/********************************************************************************* + * BIND_OPTS and BIND_OPTS2 structures definition + * These structures contain parameters used during a moniker-binding operation. + *********************************************************************************/ +typedef struct tagBIND_OPTS +{ + DWORD cbStruct; + DWORD grfFlags; + DWORD grfMode; + DWORD dwTickCountDeadline; +} BIND_OPTS, * LPBIND_OPTS; + +typedef struct tagBIND_OPTS2 +{ + DWORD cbStruct; + DWORD grfFlags; + DWORD grfMode; + DWORD dwTickCountDeadline; + DWORD dwTrackFlags; + DWORD dwClassContext; + LCID locale; + COSERVERINFO* pServerInfo; +} BIND_OPTS2, * LPBIND_OPTS2; + +/***************************************************************************** + * IBindCtx interface + */ +#define ICOM_INTERFACE IBindCtx +#define IBindCtx_METHODS \ + ICOM_METHOD1 (HRESULT, RegisterObjectBound, IUnknown*,punk) \ + ICOM_METHOD1 (HRESULT, RevokeObjectBound, IUnknown*,punk) \ + ICOM_METHOD (HRESULT, ReleaseBoundObjects) \ + ICOM_METHOD1 (HRESULT, SetBindOptions, LPBIND_OPTS2,pbindopts) \ + ICOM_METHOD1 (HRESULT, GetBindOptions, LPBIND_OPTS2,pbindopts) \ + ICOM_METHOD1 (HRESULT, GetRunningObjectTable,IRunningObjectTable**,pprot) \ + ICOM_METHOD2 (HRESULT, RegisterObjectParam, LPOLESTR,pszkey, IUnknown*,punk) \ + ICOM_METHOD2 (HRESULT, GetObjectParam, LPOLESTR,pszkey, IUnknown**,punk) \ + ICOM_METHOD1 (HRESULT, EnumObjectParam, IEnumString**,ppenum) \ + ICOM_METHOD1 (HRESULT, RevokeObjectParam, LPOLESTR,pszkey) +#define IBindCtx_IMETHODS \ + IUnknown_IMETHODS \ + IBindCtx_METHODS +ICOM_DEFINE(IBindCtx,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IBindCtx_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IBindCtxr_AddRef(p) ICOM_CALL (AddRef,p) +#define IBindCtx_Release(p) ICOM_CALL (Release,p) +/* IBindCtx methods*/ +#define IBindCtx_RegisterObjectBound(p,a) ICOM_CALL1(RegisterObjectBound,p,a) +#define IBindCtx_RevokeObjectBound(p,a) ICOM_CALL1(RevokeObjectBound,p,a) +#define IBindCtx_ReleaseBoundObjects(p) ICOM_CALL (ReleaseBoundObjects,p) +#define IBindCtx_SetBindOptions(p,a) ICOM_CALL1(SetBindOptions,p,a) +#define IBindCtx_GetBindOptions(p,a) ICOM_CALL1(GetBindOptions,p,a) +#define IBindCtx_GetRunningObjectTable(p,a) ICOM_CALL1(GetRunningObjectTable,p,a) +#define IBindCtx_RegisterObjectParam(p,a,b) ICOM_CALL2(RegisterObjectParam,p,a,b) +#define IBindCtx_GetObjectParam(p,a,b) ICOM_CALL2(GetObjectParam,p,a,b) +#define IBindCtx_EnumObjectParam(p,a) ICOM_CALL1(EnumObjectParam,p,a) +#define IBindCtx_RevokeObjectParam(p,a) ICOM_CALL1(RevokeObjectParam,p,a) + +HRESULT WINAPI CreateBindCtx16(DWORD reserved, LPBC* ppbc); +HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC* ppbc); + +/***************************************************************************** + * IClassActivator interface + */ +#define ICOM_INTERFACE IClassActivator +#define IClassActivator_METHODS \ + ICOM_METHOD5(HRESULT,GetClassObject, REFCLSID,rclsid, DWORD,dwClassContext, LCID,locale, REFIID,riid, void**,ppv) +#define IClassActivator_IMETHODS \ + IUnknown_IMETHODS \ + IClassActivator_METHODS +ICOM_DEFINE(IClassActivator,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IClassActivator_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IClassActivator_AddRef(p) ICOM_CALL (AddRef,p) +#define IClassActivator_Release(p) ICOM_CALL (Release,p) +/*** IClassActivator methods ***/ +#define IClassActivator_GetClassObject(p,a,b,c,d,e) ICOM_CALL5(GetClassObject,p,a,b,c,d,e) + + +/***************************************************************************** + * IEnumMoniker interface + */ +#define ICOM_INTERFACE IEnumMoniker +#define IEnumMoniker_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, IMoniker**,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumMoniker**,ppenum) +#define IEnumMoniker_IMETHODS \ + IUnknown_IMETHODS \ + IEnumMoniker_METHODS +ICOM_DEFINE(IEnumMoniker,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumMoniker_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumMoniker_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumMoniker_Release(p) ICOM_CALL (Release,p) +/*** IEnumMoniker methods ***/ +#define IEnumMoniker_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumMoniker_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumMoniker_Reset(p) ICOM_CALL (Reset,p) +#define IEnumMoniker_Clone(p,a) ICOM_CALL1(Clone,p,a) + +/***************************************************************************** + * IMoniker interface + */ + +typedef enum tagMKSYS +{ + MKSYS_NONE = 0, + MKSYS_GENERICCOMPOSITE = 1, + MKSYS_FILEMONIKER = 2, + MKSYS_ANTIMONIKER = 3, + MKSYS_ITEMMONIKER = 4, + MKSYS_POINTERMONIKER = 5, + MKSYS_CLASSMONIKER = 7 +} MKSYS; + +typedef enum tagMKREDUCE +{ + MKRREDUCE_ONE = 3 << 16, + MKRREDUCE_TOUSER = 2 << 16, + MKRREDUCE_THROUGHUSER = 1 << 16, + MKRREDUCE_ALL = 0 +} MKRREDUCE; + +#define ICOM_INTERFACE IMoniker +#define IMoniker_METHODS \ + ICOM_METHOD4(HRESULT,BindToObject, IBindCtx*,pbc, IMoniker*,pmkToLeft, REFIID,riidResult, void**,ppvResult) \ + ICOM_METHOD4(HRESULT,BindToStorage, IBindCtx*,pbc, IMoniker*,pmkToLeft, REFIID,riid, void**,ppvObj) \ + ICOM_METHOD4(HRESULT,Reduce, IBindCtx*,pbc, DWORD,dwReduceHowFar, IMoniker**,ppmkToLeft, IMoniker**,ppmkReduced) \ + ICOM_METHOD3(HRESULT,ComposeWith, IMoniker*,pmkRight, BOOL,fOnlyIfNotGeneric, IMoniker**,ppmkComposite) \ + ICOM_METHOD2(HRESULT,Enum, BOOL,fForward, IEnumMoniker**,ppenumMoniker) \ + ICOM_METHOD1(HRESULT,IsEqual, IMoniker*,pmkOtherMoniker) \ + ICOM_METHOD1(HRESULT,Hash, DWORD*,pdwHash) \ + ICOM_METHOD3(HRESULT,IsRunning, IBindCtx*,pbc, IMoniker*,pmkToLeft, IMoniker*,pmkNewlyRunning) \ + ICOM_METHOD3(HRESULT,GetTimeOfLastChange, IBindCtx*,pbc, IMoniker*,pmkToLeft, FILETIME*,pFileTime) \ + ICOM_METHOD1(HRESULT,Inverse, IMoniker**,ppmk) \ + ICOM_METHOD2(HRESULT,CommonPrefixWith, IMoniker*,pmkOtherMoniker, IMoniker**,ppmkPrefix) \ + ICOM_METHOD2(HRESULT,RelativePathTo, IMoniker*,pmkOther, IMoniker**,ppmkRelPath) \ + ICOM_METHOD3(HRESULT,GetDisplayName, IBindCtx*,pbc, IMoniker*,pmkToLeft, LPOLESTR*,ppszDisplayName) \ + ICOM_METHOD5(HRESULT,ParseDisplayName, IBindCtx*,pbc, IMoniker*,pmkToLeft, LPOLESTR,pszDisplayName, ULONG*,pchEaten, IMoniker**,ppmkOut) \ + ICOM_METHOD1(HRESULT,IsSystemMoniker, DWORD*,pdwMksys) +#define IMoniker_IMETHODS \ + IPersistStream_IMETHODS \ + IMoniker_METHODS +ICOM_DEFINE(IMoniker,IPersistStream) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IMoniker_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IMoniker_AddRef(p) ICOM_CALL (AddRef,p) +#define IMoniker_Release(p) ICOM_CALL (Release,p) + +/*** IPersist methods ***/ +#define IMoniker_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistStream methods ***/ +#define IMoniker_IsDirty(p) ICOM_CALL (IsDirty,p) +#define IMoniker_Load(p,a) ICOM_CALL1(Load,p,a) +#define IMoniker_Save(p,a,b) ICOM_CALL2(Save,p,a,b) +#define IMoniker_GetSizeMax(p,a) ICOM_CALL1(GetSizeMax,p,a) +/*** IMoniker methods ***/ +#define IMoniker_BindToObject(p,a,b,c,d) ICOM_CALL4(BindToObject,p,a,b,c,d) +#define IMoniker_BindToStorage(p,a,b,c,d) ICOM_CALL4(BindToStorage,p,a,b,c,d) +#define IMoniker_Reduce(p,a,b,c,d) ICOM_CALL4(Reduce,p,a,b,c,d) +#define IMoniker_ComposeWith(p,a,b,c) ICOM_CALL3(ComposeWith,p,a,b,c) +#define IMoniker_Enum(p,a,b) ICOM_CALL2(Enum,p,a,b) +#define IMoniker_IsEqual(p,a) ICOM_CALL1(IsEqual,p,a) +#define IMoniker_Hash(p,a) ICOM_CALL1(Hash,p,a) +#define IMoniker_IsRunning(p,a,b,c) ICOM_CALL3(IsRunning,p,a,b,c) +#define IMoniker_GetTimeOfLastChange(p,a,b,c) ICOM_CALL3(GetTimeOfLastChange,p,a,b,c) +#define IMoniker_Inverse(p,a) ICOM_CALL1(Inverse,p,a) +#define IMoniker_CommonPrefixWith(p,a,b) ICOM_CALL2(CommonPrefixWith,p,a,b) +#define IMoniker_RelativePathTo(p,a,b) ICOM_CALL2(RelativePathTo,p,a,b) +#define IMoniker_GetDisplayName(p,a,b,c) ICOM_CALL3(GetDisplayName,p,a,b,c) +#define IMoniker_ParseDisplayName(p,a,b,c,d,e) ICOM_CALL5(ParseDisplayName,p,a,b,c,d,e) +#define IMoniker_IsSystemMoniker(p,a) ICOM_CALL1(IsSystemMoniker,p,a) + +HRESULT WINAPI CreateFileMoniker16(LPCOLESTR16 lpszPathName, LPMONIKER* ppmk); +HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER* ppmk); + +HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim, LPCOLESTR lpszItem, LPMONIKER* ppmk); +HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR lpszItem, LPMONIKER* ppmk); + +HRESULT WINAPI CreateAntiMoniker(LPMONIKER * ppmk); + +HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite); + +/* FIXME: not implemented */ +HRESULT WINAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID* ppvResult); + +/* FIXME: not implemented */ +HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, LPMONIKER* ppmk); + +/* FIXME: not implemented */ +HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER* ppmk); + +/* FIXME: not implemented */ +HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon); +/***************************************************************************** + * IROTData interface + */ +#define ICOM_INTERFACE IROTData +#define IROTData_METHODS \ + ICOM_METHOD3(HRESULT,GetComparisonData, BYTE*,pbData, ULONG,cbMax, ULONG*,pcbData) +#define IROTData_IMETHODS \ + IUnknown_IMETHODS \ + IROTData_METHODS +ICOM_DEFINE(IROTData,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IROTData_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IROTData_AddRef(p) ICOM_CALL (AddRef,p) +#define IROTData_Release(p) ICOM_CALL (Release,p) +/*** IROTData methods ***/ +#define IROTData_GetComparisonData(p,a,b,c) ICOM_CALL3(GetComparisonData,p,a,b,c) + +#define ICOM_THIS_From_IROTData(class, name) class* This = (class*)(((char*)name)-sizeof(void*)) + +/***************************************************************************** + * IRunnableObject interface + */ +#define ICOM_INTERFACE IRunnableObject +#define IRunnableObject_METHODS \ + ICOM_METHOD1(HRESULT,GetRunningClass, LPCLSID,lpClsid) \ + ICOM_METHOD1(HRESULT,Run, IBindCtx*,pbc) \ + ICOM_METHOD (BOOL,IsRunning) \ + ICOM_METHOD2(HRESULT,LockRunning, BOOL,fLock, BOOL,fLastUnlockCloses) \ + ICOM_METHOD1(HRESULT,SetContainedObject, BOOL,fContained) +#define IRunnableObject_IMETHODS \ + IUnknown_IMETHODS \ + IRunnableObject_METHODS +ICOM_DEFINE(IRunnableObject,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IRunnableObject_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IRunnableObject_AddRef(p) ICOM_CALL (AddRef,p) +#define IRunnableObject_Release(p) ICOM_CALL (Release,p) +/*** IRunnableObject methods ***/ +#define IRunnableObject_GetRunningClass(p,a) ICOM_CALL1(GetRunningClass,p,a) +#define IRunnableObject_Run(p,a) ICOM_CALL1(Run,p,a) +#define IRunnableObject_IsRunning(p) ICOM_CALL (IsRunning,p) +#define IRunnableObject_LockRunning(p,a,b) ICOM_CALL2(LockRunning,p,a,b) +#define IRunnableObject_SetContainedObject(p,a) ICOM_CALL1(SetContainedObject,p,a) + + +/***************************************************************************** + * IRunningObjectTable interface + */ +#ifdef __WINE__ +#undef GetObject +#endif + +#define ICOM_INTERFACE IRunningObjectTable +#define IRunningObjectTable_METHODS \ + ICOM_METHOD4(HRESULT,Register, DWORD,grfFlags, IUnknown*,punkObject, IMoniker*,pmkObjectName, DWORD*,pdwRegister) \ + ICOM_METHOD1(HRESULT,Revoke, DWORD,dwRegister) \ + ICOM_METHOD1(HRESULT,IsRunning, IMoniker*,pmkObjectName) \ + ICOM_METHOD2(HRESULT,GetObject, IMoniker*,pmkObjectName, IUnknown**,ppunkObject) \ + ICOM_METHOD2(HRESULT,NoteChangeTime, DWORD,dwRegister, FILETIME*,pfiletime) \ + ICOM_METHOD2(HRESULT,GetTimeOfLastChange, IMoniker*,pmkObjectName, FILETIME*,pfiletime) \ + ICOM_METHOD1(HRESULT,EnumRunning, IEnumMoniker**,ppenumMoniker) +#define IRunningObjectTable_IMETHODS \ + IUnknown_IMETHODS \ + IRunningObjectTable_METHODS +ICOM_DEFINE(IRunningObjectTable,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IRunningObjectTable_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IRunningObjectTable_AddRef(p) ICOM_CALL (AddRef,p) +#define IRunningObjectTable_Release(p) ICOM_CALL (Release,p) +/*** IRunningObjectTable methods ***/ +#define IRunningObjectTable_Register(p,a,b,c,d) ICOM_CALL4(Register,p,a,b,c,d) +#define IRunningObjectTable_Revoke(p,a) ICOM_CALL1(Revoke,p,a) +#define IRunningObjectTable_IsRunning(p,a) ICOM_CALL1(IsRunning,p,a) +#define IRunningObjectTable_GetObject(p,a,b) ICOM_CALL2(GetObject,p,a,b) +#define IRunningObjectTable_NoteChangeTime(p,a,b) ICOM_CALL2(NoteChangeTime,p,a,b) +#define IRunningObjectTable_GetTimeOfLastChange(p,a,b) ICOM_CALL2(GetTimeOfLastChange,p,a,b) +#define IRunningObjectTable_EnumRunning(p,a) ICOM_CALL1(EnumRunning,p,a) + +HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot); +HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot); + +/***************************************************************************** + * Additional API + */ + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetInstanceFromFile(COSERVERINFO* pServerInfo, CLSID* pClsid, IUnknown* punkOuter, DWORD dwClsCtx, DWORD grfMode, OLECHAR* pwszName, DWORD dwCount, MULTI_QI* pResults); + +/* FIXME: not implemented */ +HRESULT WINAPI CoGetInstanceFromIStorage(COSERVERINFO* pServerInfo, CLSID* pClsid, IUnknown* punkOuter, DWORD dwClsCtx, IStorage* pstg, DWORD dwCount, MULTI_QI* pResults); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_MONIKER_H */ diff --git a/include/ole32/obj_oleaut.h b/include/ole32/obj_oleaut.h new file mode 100644 index 0000000..04c5c0c --- /dev/null +++ b/include/ole32/obj_oleaut.h @@ -0,0 +1,824 @@ +/* + * Defines the COM interfaces and APIs related to OLE automation support. + */ + +#ifndef __WINE_WINE_OBJ_OLEAUT_H +#define __WINE_WINE_OBJ_OLEAUT_H + + +DEFINE_OLEGUID(IID_StdOle, 0x00020430,0,0); + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IDispatch, 0x00020400,0,0); +typedef struct IDispatch IDispatch,*LPDISPATCH; + +DEFINE_OLEGUID(IID_ITypeInfo, 0x00020401,0,0); +typedef struct ITypeInfo ITypeInfo,*LPTYPEINFO; + +DEFINE_OLEGUID(IID_ITypeLib, 0x00020402,0,0); +typedef struct ITypeLib ITypeLib,*LPTYPELIB; + +DEFINE_OLEGUID(IID_ITypeComp, 0x00020403,0,0); +typedef struct ITypeComp ITypeComp,*LPTYPECOMP; + +DEFINE_OLEGUID(IID_IEnumVARIANT, 0x00020404,0,0); +typedef struct IEnumVARIANT IEnumVARIANT,*LPENUMVARIANT; + +DEFINE_OLEGUID(IID_ICreateTypeInfo, 0x00020405,0,0); +typedef struct ICreateTypeInfo ICreateTypeInfo,*LPCREATETYPEINFO; + +DEFINE_OLEGUID(IID_ICreateTypeLib, 0x00020406,0,0); +typedef struct ICreateTypeLib ICreateTypeLib,*LPCREATETYPELIB; + +DEFINE_OLEGUID(IID_ICreateTypeInfo2,0x0002040E,0,0); +typedef struct ICreateTypeInfo2 ICreateTypeInfo2,*LPCREATETYPEINFO2; + +DEFINE_OLEGUID(IID_ICreateTypeLib2, 0x0002040F,0,0); +typedef struct ICreateTypeLib2 ICreateTypeLib2,*LPCREATETYPELIB2; + +DEFINE_OLEGUID(IID_ITypeChangeEvents,0x00020410,0,0); +typedef struct ITypeChangeEvents ITypeChangeEvents,*LPTYPECHANGEEVENTS; + +DEFINE_OLEGUID(IID_ITypeLib2, 0x00020411,0,0); +typedef struct ITypeLib2 ITypeLib2,*LPTYPELIB2; + +DEFINE_OLEGUID(IID_ITypeInfo2, 0x00020412,0,0); +typedef struct ITypeInfo2 ITypeInfo2,*LPTYPEINFO2; + +/***************************************************************************** + * Automation data types + */ + +/***************************************************************** + * SafeArray defines and structs + */ + +#define FADF_AUTO ( 0x1 ) +#define FADF_STATIC ( 0x2 ) +#define FADF_EMBEDDED ( 0x4 ) +#define FADF_FIXEDSIZE ( 0x10 ) +#define FADF_RECORD ( 0x20 ) +#define FADF_HAVEIID ( 0x40 ) +#define FADF_HAVEVARTYPE ( 0x80 ) +#define FADF_BSTR ( 0x100 ) +#define FADF_UNKNOWN ( 0x200 ) +#define FADF_DISPATCH ( 0x400 ) +#define FADF_VARIANT ( 0x800 ) +#define FADF_RESERVED ( 0xf008 ) + +/* Undocumented flags */ +#define FADF_CREATEVECTOR ( 0x2000 ) /* set when the safe array is created using SafeArrayCreateVector */ + + +typedef struct tagSAFEARRAYBOUND +{ + ULONG cElements; /* Number of elements in dimension */ + LONG lLbound; /* Lower bound of dimension */ +} SAFEARRAYBOUND; + +typedef struct tagSAFEARRAY +{ + USHORT cDims; /* Count of array dimension */ + USHORT fFeatures; /* Flags describing the array */ + ULONG cbElements; /* Size of each element */ + ULONG cLocks; /* Number of lock on array */ + PVOID pvData; /* Pointer to data valid when cLocks > 0 */ + SAFEARRAYBOUND rgsabound[ 1 ]; /* One bound for each dimension */ +} SAFEARRAY, *LPSAFEARRAY; + +typedef enum tagCALLCONV { + CC_CDECL = 1, + CC_MSCPASCAL = CC_CDECL + 1, + CC_PASCAL = CC_MSCPASCAL, + CC_MACPASCAL = CC_PASCAL + 1, + CC_STDCALL = CC_MACPASCAL + 1, + CC_RESERVED = CC_STDCALL + 1, + CC_SYSCALL = CC_RESERVED + 1, + CC_MPWCDECL = CC_SYSCALL + 1, + CC_MPWPASCAL = CC_MPWCDECL + 1, + CC_MAX = CC_MPWPASCAL + 1 +} CALLCONV; + +typedef CY CURRENCY; + +/* + * Declarations of the VARIANT structure and the VARIANT APIs. + */ +/* S_OK : Success. + * DISP_E_BADVARTYPE : The variant type vt in not a valid type of variant. + * DISP_E_OVERFLOW : The data pointed to by pvarSrc does not fit in the destination type. + * DISP_E_TYPEMISMATCH : The variant type vt is not a valid type of variant. + * E_INVALIDARG : One argument is invalid. + * * E_OUTOFMEMORY : Memory could not be allocated for the conversion. + * DISP_E_ARRAYISLOCKED : The variant contains an array that is locked. + */ + +typedef struct tagVARIANT VARIANT, *LPVARIANT; +typedef struct tagVARIANT VARIANTARG, *LPVARIANTARG; + +struct tagVARIANT { + VARTYPE vt; + WORD wReserved1; + WORD wReserved2; + WORD wReserved3; + union /* DUMMYUNIONNAME */ + { + /* By value. */ + CHAR cVal; + USHORT uiVal; + ULONG ulVal; + INT intVal; + UINT uintVal; + BYTE bVal; + short iVal; + long lVal; + float fltVal; + double dblVal; + VARIANT_BOOL boolVal; + SCODE scode; + DATE date; + BSTR bstrVal; + CY cyVal; + /* FIXME: This is not supposed to be at this level + * See bug #181 in bugzilla + * DECIMAL decVal; + */ + IUnknown* punkVal; + IDispatch* pdispVal; + SAFEARRAY* parray; + + /* By reference */ + CHAR* pcVal; + USHORT* puiVal; + ULONG* pulVal; + INT* pintVal; + UINT* puintVal; + BYTE* pbVal; + short* piVal; + long* plVal; + float* pfltVal; + double* pdblVal; + VARIANT_BOOL* pboolVal; + SCODE* pscode; + DATE* pdate; + BSTR* pbstrVal; + VARIANT* pvarVal; + PVOID byref; + CY* pcyVal; + DECIMAL* pdecVal; + IUnknown** ppunkVal; + IDispatch** ppdispVal; + SAFEARRAY** pparray; + } DUMMYUNIONNAME; +}; + + +typedef LONG DISPID; +typedef DWORD HREFTYPE; +typedef DISPID MEMBERID; + +#define DISPATCH_METHOD 0x1 +#define DISPATCH_PROPERTYGET 0x2 +#define DISPATCH_PROPERTYPUT 0x4 +#define DISPATCH_PROPERTYPUTREF 0x8 + +#define DISPID_UNKNOWN ( -1 ) +#define DISPID_VALUE ( 0 ) +#define DISPID_PROPERTYPUT ( -3 ) +#define DISPID_NEWENUM ( -4 ) +#define DISPID_EVALUATE ( -5 ) +#define DISPID_CONSTRUCTOR ( -6 ) +#define DISPID_DESTRUCTOR ( -7 ) +#define DISPID_COLLECT ( -8 ) + +#define MEMBERID_NIL DISPID_UNKNOWN + +#define IMPLTYPEFLAG_FDEFAULT (0x1) +#define IMPLTYPEFLAG_FSOURCE (0x2) +#define IMPLTYPEFLAG_FRESTRICTED (0x4) +#define IMPLTYPEFLAG_FDEFAULTVTABLE (0x8) + +typedef struct tagDISPPARAMS +{ + VARIANTARG* rgvarg; + DISPID* rgdispidNamedArgs; + UINT cArgs; + UINT cNamedArgs; +} DISPPARAMS; + +typedef struct tagEXCEPINFO +{ + WORD wCode; + WORD wReserved; + BSTR bstrSource; + BSTR bstrDescription; + BSTR bstrHelpFile; + DWORD dwHelpContext; + PVOID pvReserved; + HRESULT __stdcall (*pfnDeferredFillIn)(struct tagEXCEPINFO *); + SCODE scode; +} EXCEPINFO, * LPEXCEPINFO; + +typedef struct tagIDLDESC +{ + ULONG dwReserved; + USHORT wIDLFlags; +} IDLDESC; + +typedef struct tagPARAMDESCEX +{ + ULONG cBytes; + VARIANTARG varDefaultValue; +} PARAMDESCEX, *LPPARAMDESCEX; + +typedef struct tagPARAMDESC +{ + LPPARAMDESCEX pparamdescex; + USHORT wParamFlags; +} PARAMDESC; + +#define PARAMFLAG_NONE (0x00) +#define PARAMFLAG_FIN (0x01) +#define PARAMFLAG_FOUT (0x02) +#define PARAMFLAG_FLCID (0x04) +#define PARAMFLAG_FRETVAL (0x08) +#define PARAMFLAG_FOPT (0x10) +#define PARAMFLAG_FHASDEFAULT (0x20) + + +typedef struct tagTYPEDESC +{ + union { + struct tagTYPEDESC *lptdesc; + struct tagARRAYDESC *lpadesc; + HREFTYPE hreftype; + } DUMMYUNIONNAME; + VARTYPE vt; +} TYPEDESC; + +typedef struct tagELEMDESC +{ + TYPEDESC tdesc; + union { + IDLDESC idldesc; + PARAMDESC paramdesc; + } DUMMYUNIONNAME; +} ELEMDESC, *LPELEMDESC; + +typedef enum tagTYPEKIND +{ + TKIND_ENUM = 0, + TKIND_RECORD = 1, + TKIND_MODULE = 2, + TKIND_INTERFACE = 3, + TKIND_DISPATCH = 4, + TKIND_COCLASS = 5, + TKIND_ALIAS = 6, + TKIND_UNION = 7, + TKIND_MAX = 8 +} TYPEKIND; + +typedef struct tagTYPEATTR +{ + GUID guid; + LCID lcid; + DWORD dwReserved; + MEMBERID memidConstructor; + MEMBERID memidDestructor; + LPOLESTR lpstrSchema; + ULONG cbSizeInstance; + TYPEKIND typekind; + WORD cFuncs; + WORD cVars; + WORD cImplTypes; + WORD cbSizeVft; + WORD cbAlignment; + WORD wTypeFlags; + WORD wMajorVerNum; + WORD wMinorVerNum; + TYPEDESC tdescAlias; + IDLDESC idldescType; +} TYPEATTR, *LPTYPEATTR; + +#define TYPEFLAG_NONE (0x00) +#define TYPEFLAG_FAPPOBJECT (0x01) +#define TYPEFLAG_FCANCREATE (0x02) +#define TYPEFLAG_FLICENSED (0x04) +#define TYPEFLAG_FPREDECLID (0x08) +#define TYPEFLAG_FHIDDEN (0x0f) +#define TYPEFLAG_FCONTROL (0x20) +#define TYPEFLAG_FDUAL (0x40) +#define TYPEFLAG_FNONEXTENSIBLE (0x80) +#define TYPEFLAG_FOLEAUTOMATION (0x100) +#define TYPEFLAG_FRESTRICTED (0x200) +#define TYPEFLAG_FAGGREGATABLE (0x400) +#define TYPEFLAG_FREPLACEABLE (0x800) +#define TYPEFLAG_FDISPATCHABLE (0x1000) +#define TYPEFLAG_FREVERSEBIND (0x2000) +#define TYPEFLAG_FPROXY (0x4000) +#define TYPEFLAG_DEFAULTFILTER (0x8000) +#define TYPEFLAG_COCLASSATTRIBUTES (0x63f) +#define TYPEFLAG_INTERFACEATTRIBUTES (0x7bd0) +#define TYPEFLAG_DISPATCHATTRIBUTES (0x5a90) +#define TYPEFLAG_ALIASATTRIBUTES (0x210) +#define TYPEFLAG_MODULEATTRIBUTES (0x210) +#define TYPEFLAG_ENUMATTRIBUTES (0x210) +#define TYPEFLAG_RECORDATTRIBUTES (0x210) +#define TYPEFLAG_UNIONATTRIBUTES (0x210) + +typedef struct tagARRAYDESC +{ + TYPEDESC tdescElem; + USHORT cDims; + SAFEARRAYBOUND rgbounds[1]; +} ARRAYDESC; + +typedef enum tagFUNCKIND +{ + FUNC_VIRTUAL = 0, + FUNC_PUREVIRTUAL = 1, + FUNC_NONVIRTUAL = 2, + FUNC_STATIC = 3, + FUNC_DISPATCH = 4 +} FUNCKIND; + +typedef enum tagINVOKEKIND +{ + INVOKE_FUNC = 1, + INVOKE_PROPERTYGET = 2, + INVOKE_PROPERTYPUT = 3, + INVOKE_PROPERTYPUTREF = 4 +} INVOKEKIND; + +typedef struct tagFUNCDESC +{ + MEMBERID memid; + SCODE *lprgscode; + ELEMDESC *lprgelemdescParam; + FUNCKIND funckind; + INVOKEKIND invkind; + CALLCONV callconv; + SHORT cParams; + SHORT cParamsOpt; + SHORT oVft; + SHORT cScodes; + ELEMDESC elemdescFunc; + WORD wFuncFlags; +} FUNCDESC, *LPFUNCDESC; + +typedef enum tagVARKIND +{ + VAR_PERINSTANCE = 0, + VAR_STATIC = 1, + VAR_CONST = 2, + VAR_DISPATCH = 3 +} VARKIND; + +typedef struct tagVARDESC +{ + MEMBERID memid; + LPOLESTR lpstrSchema; + union { + ULONG oInst; + VARIANT *lpvarValue; + } DUMMYUNIONNAME; + ELEMDESC elemdescVar; + WORD wVarFlags; + VARKIND varkind; +} VARDESC, *LPVARDESC; + +typedef enum tagSYSKIND +{ + SYS_WIN16 = 0, + SYS_WIN32 = 1, + SYS_MAC = 2 +} SYSKIND; + +typedef enum tagLIBFLAGS +{ + LIBFLAG_FRESTRICTED = 0x1, + LIBFLAG_FCONTROL = 0x2, + LIBFLAG_FHIDDEN = 0x4, + LIBFLAG_FHASDISKIMAGE = 0x8 +} LIBFLAGS; + +typedef struct tagTLIBATTR +{ + GUID guid; + LCID lcid; + SYSKIND syskind; + WORD wMajorVerNum; + WORD wMinorVerNum; + WORD wLibFlags; +} TLIBATTR, *LPTLIBATTR; + +typedef enum tagDESCKIND +{ + DESCKIND_NONE = 0, + DESCKIND_FUNCDESC = 1, + DESCKIND_VARDESC = 2, + DESCKIND_TYPECOMP = 3, + DESCKIND_IMPLICITAPPOBJ = 4, + DESCKIND_MAX = 6 +} DESCKIND; + +typedef union tagBINDPTR +{ + FUNCDESC *lpfuncdesc; + VARDESC *lpvardesc; + ITypeComp *lptcomp; +} BINDPTR, *LPBINDPTR; + +typedef enum tagVARFLAGS +{ + VARFLAG_FREADONLY = 0x1, + VARFLAG_FSOURCE = 0x2, + VARFLAG_FBINDABLE = 0x4, + VARFLAG_FREQUESTEDIT = 0x8, + VARFLAG_FDISPLAYBIND = 0x10, + VARFLAG_FDEFAULTBIND = 0x20, + VARFLAG_FHIDDEN = 0x40, + VARFLAG_FRESTRICTED = 0x80, + VARFLAG_FDEFAULTCOLLELEM = 0x100, + VARFLAG_FUIDEFAULT = 0x200, + VARFLAG_FNONBROWSABLE = 0x400, + VARFLAG_FREPLACEABLE = 0x800, + VARFLAG_FIMMEDIATEBIND = 0x1000 +} VARFLAGS; + + +/* + * Data types for Variants. + */ + +enum VARENUM { + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_PTR = 26, + VT_SAFEARRAY = 27, + VT_CARRAY = 28, + VT_USERDEFINED = 29, + VT_LPSTR = 30, + VT_LPWSTR = 31, + VT_RECORD = 36, + VT_FILETIME = 64, + VT_BLOB = 65, + VT_STREAM = 66, + VT_STORAGE = 67, + VT_STREAMED_OBJECT = 68, + VT_STORED_OBJECT = 69, + VT_BLOB_OBJECT = 70, + VT_CF = 71, + VT_CLSID = 72, + VT_VECTOR = 0x1000, + VT_ARRAY = 0x2000, + VT_BYREF = 0x4000, + VT_RESERVED = 0x8000, + VT_ILLEGAL = 0xffff, + VT_ILLEGALMASKED = 0xfff, + VT_TYPEMASK = 0xfff +}; + +/* the largest valide type + */ +#define VT_MAXVALIDTYPE VT_CLSID + + +/* + * Declarations of the VARIANT structure and the VARIANT APIs. + */ + +/* S_OK : Success. + * DISP_E_BADVARTYPE : The variant type vt in not a valid type of variant. + * DISP_E_OVERFLOW : The data pointed to by pvarSrc does not fit in the destination type. + * DISP_E_TYPEMISMATCH : The variant type vt is not a valid type of variant. + * E_INVALIDARG : One argument is invalid. + * E_OUTOFMEMORY : Memory could not be allocated for the conversion. + * DISP_E_ARRAYISLOCKED : The variant contains an array that is locked. + */ + + +typedef struct tagCUSTDATAITEM { + GUID guid; + VARIANTARG varValue; +} CUSTDATAITEM, *LPCUSTDATAITEM; + +typedef struct tagCUSTDATA { + INT cCustData; + LPCUSTDATAITEM prgCustData; /* count cCustdata */ +} CUSTDATA, *LPCUSTDATA; + + + +/***************************************************************************** + * IDispatch interface + */ +#define ICOM_INTERFACE IDispatch +#define IDispatch_METHODS \ + ICOM_METHOD1(HRESULT, GetTypeInfoCount, UINT*, pctinfo) \ + ICOM_METHOD3(HRESULT, GetTypeInfo, UINT, iTInfo, LCID, lcid, ITypeInfo**, ppTInfo) \ + ICOM_METHOD5(HRESULT, GetIDsOfNames, REFIID, riid, LPOLESTR*, rgszNames, UINT, cNames, LCID, lcid, DISPID*, rgDispId) \ + ICOM_METHOD8(HRESULT, Invoke, DISPID, dispIdMember, REFIID, riid, LCID, lcid, WORD, wFlags, DISPPARAMS*, pDispParams, VARIANT*, pVarResult, EXCEPINFO*, pExepInfo, UINT*, puArgErr) +#define IDispatch_IMETHODS \ + IUnknown_IMETHODS \ + IDispatch_METHODS +ICOM_DEFINE(IDispatch,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IDispatch_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IDispatch_AddRef(p) ICOM_CALL (AddRef,p) +#define IDispatch_Release(p) ICOM_CALL (Release,p) +/*** IDispatch methods ***/ +#define IDispatch_GetTypeInfoCount(p,a) ICOM_CALL1 (GetTypeInfoCount,p,a) +#define IDispatch_GetTypeInfo(p,a,b,c) ICOM_CALL3 (GetTypeInfo,p,a,b,c) +#define IDispatch_GetIDsOfNames(p,a,b,c,d,e) ICOM_CALL5 (GetIDsOfNames,p,a,b,c,d,e) +#define IDispatch_Invoke(p,a,b,c,d,e,f,g,h) ICOM_CALL8 (Invoke,p,a,b,c,d,e,f,g,h) + + +/***************************************************************************** + * ITypeInfo interface + */ +#define ICOM_INTERFACE ITypeInfo +#define ITypeInfo_METHODS \ + ICOM_METHOD1(HRESULT,GetTypeAttr, TYPEATTR**,ppTypeAttr) \ + ICOM_METHOD1(HRESULT,GetTypeComp, ITypeComp**,ppTComp) \ + ICOM_METHOD2(HRESULT,GetFuncDesc, UINT,index, FUNCDESC**,ppFuncDesc) \ + ICOM_METHOD2(HRESULT,GetVarDesc, UINT,index, VARDESC**,ppVarDesc) \ + ICOM_METHOD4(HRESULT,GetNames, MEMBERID,memid, BSTR*,rgBstrNames, UINT,cMaxNames, UINT*,pcNames) \ + ICOM_METHOD2(HRESULT,GetRefTypeOfImplType, UINT,index, HREFTYPE*, pRefType) \ + ICOM_METHOD2(HRESULT,GetImplTypeFlags, UINT,index, INT*,pImplTypeFlags)\ + ICOM_METHOD3(HRESULT,GetIDsOfNames, LPOLESTR*,rgszNames, UINT,cNames, MEMBERID*,pMemId) \ + ICOM_METHOD7(HRESULT,Invoke, PVOID,pvInstance, MEMBERID,memid, WORD,wFlags, DISPPARAMS*,pDispParams, VARIANT*,pVarResult, EXCEPINFO*,pExcepInfo, UINT*,puArgErr) \ + ICOM_METHOD5(HRESULT,GetDocumentation, MEMBERID,memid, BSTR*,pBstrName, BSTR*,pBstrDocString, DWORD*,pdwHelpContext, BSTR*,pBstrHelpFile) \ + ICOM_METHOD5(HRESULT,GetDllEntry, MEMBERID,memid, INVOKEKIND,invKind, BSTR*,pBstrDllName, BSTR*,pBstrName, WORD*,pwOrdinal) \ + ICOM_METHOD2(HRESULT,GetRefTypeInfo, HREFTYPE,hRefType, ITypeInfo**,ppTInfo) \ + ICOM_METHOD3(HRESULT,AddressOfMember, MEMBERID,memid, INVOKEKIND,invKind, PVOID*,ppv) \ + ICOM_METHOD3(HRESULT,CreateInstance, IUnknown*,pUnkOuter, REFIID,riid, PVOID*,ppvObj) \ + ICOM_METHOD2(HRESULT,GetMops, MEMBERID,memid, BSTR*,pBstrMops) \ + ICOM_METHOD2(HRESULT,GetContainingTypeLib, ITypeLib**,ppTLib, UINT*,pIndex) \ + ICOM_METHOD1(HRESULT,ReleaseTypeAttr, TYPEATTR*,pTypeAttr) \ + ICOM_METHOD1(HRESULT,ReleaseFuncDesc, FUNCDESC*,pFuncDesc) \ + ICOM_METHOD1(HRESULT,ReleaseVarDesc, VARDESC*,pVarDesc) + +#define ITypeInfo_IMETHODS \ + IUnknown_IMETHODS \ + ITypeInfo_METHODS +ICOM_DEFINE(ITypeInfo,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ITypeInfo_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ITypeInfo_AddRef(p) ICOM_CALL (AddRef,p) +#define ITypeInfo_Release(p) ICOM_CALL (Release,p) +/*** ITypeInfo methods ***/ +#define ITypeInfo_GetTypeAttr(p,a) ICOM_CALL1(GetTypeAttr,p,a) +#define ITypeInfo_GetTypeComp(p,a) ICOM_CALL1(GetTypeComp,p,a) +#define ITypeInfo_GetFuncDesc(p,a,b) ICOM_CALL2(GetFuncDesc,p,a,b) +#define ITypeInfo_GetVarDesc(p,a,b) ICOM_CALL2(GetVarDesc,p,a,b) +#define ITypeInfo_GetNames(p,a,b,c,d) ICOM_CALL4(GetNames,p,a,b,c,d) +#define ITypeInfo_GetRefTypeOfImplType(p,a,b) ICOM_CALL2(GetRefTypeOfImplType,p,a,b) +#define ITypeInfo_GetImplTypeFlags(p,a,b) ICOM_CALL2(GetImplTypeFlags,p,a,b) +#define ITypeInfo_GetIDsOfNames(p,a,b,c) ICOM_CALL3(GetIDsOfNames,p,a,b,c) +#define ITypeInfo_Invoke(p,a,b,c,d,e,f,g) ICOM_CALL7(Invoke,p,a,b,c,d,e,f,g) +#define ITypeInfo_GetDocumentation(p,a,b,c,d,e) ICOM_CALL5(GetDocumentation,p,a,b,c,d,e) +#define ITypeInfo_GetDllEntry(p,a,b,c,d,e) ICOM_CALL5(GetDllEntry,p,a,b,c,d,e) +#define ITypeInfo_GetRefTypeInfo(p,a,b) ICOM_CALL2(GetRefTypeInfo,p,a,b) +#define ITypeInfo_AddressOfMember(p,a,b,c) ICOM_CALL3(AddressOfMember,p,a,b,c) +#define ITypeInfo_CreateInstance(p,a,b,c) ICOM_CALL3(CreateInstance,p,a,b,c) +#define ITypeInfo_GetMops(p,a,b) ICOM_CALL2(GetMops,p,a,b) +#define ITypeInfo_GetContainingTypeLib(p,a,b) ICOM_CALL2(GetContainingTypeLib,p,a,b) +#define ITypeInfo_ReleaseTypeAttr(p,a) ICOM_CALL1(ReleaseTypeAttr,p,a) +#define ITypeInfo_ReleaseFuncDesc(p,a) ICOM_CALL1(ReleaseFuncDesc,p,a) +#define ITypeInfo_ReleaseVarDesc(p,a) ICOM_CALL1(ReleaseVarDesc,p,a) + + +/***************************************************************************** + * ITypeInfo2 interface + */ +#define ICOM_INTERFACE ITypeInfo2 +#define ITypeInfo2_METHODS \ + ICOM_METHOD1(HRESULT, GetTypeKind, TYPEKIND*, pTypeKind) \ + ICOM_METHOD1(HRESULT, GetTypeFlags, UINT*, pTypeFlags) \ + ICOM_METHOD3(HRESULT, GetFuncIndexOfMemId, MEMBERID, memid, INVOKEKIND,\ + invKind, UINT*, pFuncIndex) \ + ICOM_METHOD2(HRESULT, GetVarIndexOfMemId, MEMBERID, memid, UINT*, \ + pVarIndex) \ + ICOM_METHOD2(HRESULT, GetCustData, REFGUID, guid, VARIANT*, pVarVal) \ + ICOM_METHOD3(HRESULT, GetFuncCustData, UINT, index, REFGUID, guid,\ + VARIANT*, pVarVal) \ + ICOM_METHOD4(HRESULT, GetParamCustData, UINT, indexFunc, UINT,\ + indexParam, REFGUID, guid, VARIANT*, pVarVal) \ + ICOM_METHOD3(HRESULT, GetVarCustData, UINT, index, REFGUID, guid,\ + VARIANT*, pVarVal) \ + ICOM_METHOD3(HRESULT, GetImplTypeCustData, UINT, index, REFGUID, guid,\ + VARIANT*, pVarVal) \ + ICOM_METHOD5(HRESULT, GetDocumentation2, MEMBERID, memid, LCID, lcid,\ + BSTR*, pbstrHelpString, DWORD*, pdwHelpStringContext,\ + BSTR*, pbstrHelpStringDll) \ + ICOM_METHOD1(HRESULT, GetAllCustData, CUSTDATA*, pCustData) \ + ICOM_METHOD2(HRESULT, GetAllFuncCustData, UINT, index, CUSTDATA*,\ + pCustData)\ + ICOM_METHOD3(HRESULT, GetAllParamCustData, UINT, indexFunc, UINT,\ + indexParam, CUSTDATA*, pCustData) \ + ICOM_METHOD2(HRESULT, GetAllVarCustData, UINT, index, CUSTDATA*,\ + pCustData) \ + ICOM_METHOD2(HRESULT, GetAllImplTypeCustData, UINT, index, CUSTDATA*,\ + pCustData) + +#define ITypeInfo2_IMETHODS \ + IUnknown_IMETHODS \ + ITypeInfo_METHODS \ + ITypeInfo2_METHODS +ICOM_DEFINE(ITypeInfo2,ITypeInfo) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ITypeInfo2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ITypeInfo2_AddRef(p) ICOM_CALL (AddRef,p) +#define ITypeInfo2_Release(p) ICOM_CALL (Release,p) +/*** ITypeInfo methods ***/ +#define ITypeInfo2_GetTypeAttr(p,a) ICOM_CALL1(GetTypeAttr,p,a) +#define ITypeInfo2_GetTypeComp(p,a) ICOM_CALL1(GetTypeComp,p,a) +#define ITypeInfo2_GetFuncDesc(p,a,b) ICOM_CALL2(GetFuncDesc,p,a,b) +#define ITypeInfo2_GetVarDesc(p,a,b) ICOM_CALL2(GetVarDesc,p,a,b) +#define ITypeInfo2_GetNames(p,a,b,c,d) ICOM_CALL4(GetNames,p,a,b,c,d) +#define ITypeInfo2_GetRefTypeOfImplType(p,a,b) ICOM_CALL2(GetRefTypeOfImplType,p,a,b) +#define ITypeInfo2_GetImplTypeFlags(p,a,b) ICOM_CALL2(GetImplTypeFlags,p,a,b) +#define ITypeInfo2_GetIDsOfNames(p,a,b,c) ICOM_CALL3(GetIDsOfNames,p,a,b,c) +#define ITypeInfo2_Invoke(p,a,b,c,d,e,f,g) ICOM_CALL7(Invoke,p,a,b,c,d,e,f,g) +#define ITypeInfo2_GetDocumentation(p,a,b,c,d,e) ICOM_CALL5(GetDocumentation,p,a,b,c,d,e) +#define ITypeInfo2_GetDllEntry(p,a,b,c,d,e) ICOM_CALL5(GetDllEntry,p,a,b,c,d,e) +#define ITypeInfo2_GetRefTypeInfo(p,a,b) ICOM_CALL2(GetRefTypeInfo,p,a,b) +#define ITypeInfo2_AddressOfMember(p,a,b,c) ICOM_CALL3(AddressOfMember,p,a,b,c) +#define ITypeInfo2_CreateInstance(p,a,b,c) ICOM_CALL3(CreateInstance,p,a,b,c) +#define ITypeInfo2_GetMops(p,a,b) ICOM_CALL2(GetMops,p,a,b) +#define ITypeInfo2_GetContainingTypeLib(p,a,b) ICOM_CALL2(GetContainingTypeLib,p,a,b) +#define ITypeInfo2_ReleaseTypeAttr(p,a) ICOM_CALL1(ReleaseTypeAttr,p,a) +#define ITypeInfo2_ReleaseFuncDesc(p,a) ICOM_CALL1(ReleaseFuncDesc,p,a) +#define ITypeInfo2_ReleaseVarDesc(p,a) ICOM_CALL1(ReleaseVarDesc,p,a) +/*** ITypeInfo2 methods ***/ +#define ITypeInfo2_GetTypeKind(p,a) ICOM_CALL1(GetTypeKind,p,a) +#define ITypeInfo2_GetTypeFlags(p,a) ICOM_CALL1(GetTypeFlags,p,a) +#define ITypeInfo2_GetFuncIndexOfMemId(p,a,b,c) ICOM_CALL3(GetFuncIndexOfMemId,p,a,b,c) +#define ITypeInfo2_GetVarIndexOfMemId(p,a,b) ICOM_CALL2(GetVarIndexOfMemId,p,a,b) +#define ITypeInfo2_GetCustData(p,a,b) ICOM_CALL2(GetCustData,p,a,b) +#define ITypeInfo2_GetFuncCustData(p,a,b,c) ICOM_CALL3(GetFuncCustData,p,a,b,c) +#define ITypeInfo2_GetParamCustData(p,a,b,c,d) ICOM_CALL4(GetParamCustData,p,a,b,c,d) +#define ITypeInfo2_GetVarCustData(p,a,b,c) ICOM_CALL3(GetVarCustData,p,a,b,c) +#define ITypeInfo2_GetImplTypeCustData(p,a,b,c) ICOM_CALL3(GetImplTypeCustData,p,a,b,c) +#define ITypeInfo2_GetDocumentation2(p,a,b,c,d,e) ICOM_CALL5(GetDocumentation2,p,a,b,c,d,e) +#define ITypeInfo2_GetAllCustData(p,a) ICOM_CALL1(GetAllCustData,p,a) +#define ITypeInfo2_GetAllFuncCustData(p,a,b) ICOM_CALL2(GetAllFuncCustData,p,a,b) +#define ITypeInfo2_GetAllParamCustData(p,a,b,c) ICOM_CALL3(GetAllParamCustData,p,a,b,c) +#define ITypeInfo2_GetAllVarCustData(p,a,b) ICOM_CALL2(GetAllVarCustData,p,a,b) +#define ITypeInfo2_GetAllImplTypeCustData(p,a,b) ICOM_CALL2(GetAllImplTypeCustData,p,a,b) + +/***************************************************************************** + * ITypeLib interface + */ +#define ICOM_INTERFACE ITypeLib +#define ITypeLib_METHODS \ + ICOM_METHOD (UINT,GetTypeInfoCount) \ + ICOM_METHOD2(HRESULT,GetTypeInfo, UINT,index, ITypeInfo**,ppTInfo) \ + ICOM_METHOD2(HRESULT,GetTypeInfoType, UINT,index, TYPEKIND*,pTKind) \ + ICOM_METHOD2(HRESULT,GetTypeInfoOfGuid, REFGUID,guid, ITypeInfo**,ppTinfo) \ + ICOM_METHOD1(HRESULT,GetLibAttr, TLIBATTR**,ppTLibAttr) \ + ICOM_METHOD1(HRESULT,GetTypeComp, ITypeComp**,ppTComp) \ + ICOM_METHOD5(HRESULT,GetDocumentation, INT,index, BSTR*,pBstrName, BSTR*,pBstrDocString, DWORD*,pdwHelpContext, BSTR*,pBstrHelpFile) \ + ICOM_METHOD3(HRESULT,IsName, LPOLESTR,szNameBuf, ULONG,lHashVal, BOOL*,bfName) \ + ICOM_METHOD5(HRESULT,FindName, LPOLESTR,szNameBuf, ULONG,lHashVal, ITypeInfo**,ppTInfo, MEMBERID*,rgMemId, USHORT*,pcFound) \ + ICOM_METHOD1(VOID,ReleaseTLibAttr, TLIBATTR*,pTLibAttr) +#define ITypeLib_IMETHODS \ + IUnknown_IMETHODS \ + ITypeLib_METHODS +ICOM_DEFINE(ITypeLib,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ITypeLib_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ITypeLib_AddRef(p) ICOM_CALL (AddRef,p) +#define ITypeLib_Release(p) ICOM_CALL (Release,p) +/*** ITypeLib methods ***/ +#define ITypeLib_GetTypeInfoCount(p) ICOM_CALL (GetTypeInfoCount,p) +#define ITypeLib_GetTypeInfo(p,a,b) ICOM_CALL2(GetTypeInfo,p,a,b) +#define ITypeLib_GetTypeInfoType(p,a,b) ICOM_CALL2(GetTypeInfoType,p,a,b) +#define ITypeLib_GetTypeInfoOfGuid(p,a,b) ICOM_CALL2(GetTypeInfoOfGuid,p,a,b) +#define ITypeLib_GetLibAttr(p,a) ICOM_CALL1(GetLibAttr,p,a) +#define ITypeLib_GetTypeComp(p,a) ICOM_CALL1(GetTypeComp,p,a) +#define ITypeLib_GetDocumentation(p,a,b,c,d,e) ICOM_CALL5(GetDocumentation,p,a,b,c,d,e) +#define ITypeLib_IsName(p,a,b,c) ICOM_CALL3(IsName,p,a,b,c) +#define ITypeLib_FindName(p,a,b,c,d,e) ICOM_CALL5(FindName,p,a,b,c,d,e) +#define ITypeLib_ReleaseTLibAttr(p,a) ICOM_CALL1(ReleaseTLibAttr,p,a) + + +/***************************************************************************** + * ITypeLib2 interface + */ +#define ICOM_INTERFACE ITypeLib2 +#define ITypeLib2_METHODS \ + ICOM_METHOD2(HRESULT, GetCustData, REFGUID, guid, VARIANT*, pVarVal) \ + ICOM_METHOD2(HRESULT, GetLibStatistics, ULONG *, pcUniqueNames, ULONG*,pcchUniqueNames) \ + ICOM_METHOD5(HRESULT, GetDocumentation2, INT, index, LCID, lcid,BSTR*, pbstrHelpString, DWORD*, pdwHelpStringContext, BSTR*, strHelpStringDll) \ + ICOM_METHOD1(HRESULT, GetAllCustData, CUSTDATA *, pCustData) +#define ITypeLib2_IMETHODS \ + IUnknown_IMETHODS \ + ITypeLib_IMETHODS \ + ITypeLib2_METHODS +ICOM_DEFINE(ITypeLib2,ITypeLib) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ITypeLib2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ITypeLib2_AddRef(p) ICOM_CALL (AddRef,p) +#define ITypeLib2_Release(p) ICOM_CALL (Release,p) +/*** ITypeLib methods ***/ +#define ITypeLib2_GetTypeInfoCount(p) ICOM_CALL (GetTypeInfoCount,p) +#define ITypeLib2_GetTypeInfo(p,a,b) ICOM_CALL2(GetTypeInfo,p,a,b) +#define ITypeLib2_GetTypeInfoType(p,a,b) ICOM_CALL2(GetTypeInfoType,p,a,b) +#define ITypeLib2_GetTypeInfoOfGuid(p,a,b) ICOM_CALL2(GetTypeInfoOfGuid,p,a,b) +#define ITypeLib2_GetLibAttr(p,a) ICOM_CALL1(GetLibAttr,p,a) +#define ITypeLib2_GetTypeComp(p,a) ICOM_CALL1(GetTypeComp,p,a) +#define ITypeLib2_GetDocumentation(p,a,b,c,d,e) ICOM_CALL5(GetDocumentation,p,a,b,c,d,e) +#define ITypeLib2_IsName(p,a,b,c) ICOM_CALL3(IsName,p,a,b,c) +#define ITypeLib2_FindName(p,a,b,c,d,e) ICOM_CALL5(FindName,p,a,b,c,d,e) +#define ITypeLib2_ReleaseTLibAttr(p,a) ICOM_CALL1(ReleaseTLibAttr,p,a) +/*** ITypeLib2 methods ***/ +#define ITypeLib2_GetCustData(p,a,b) ICOM_CALL2(GetCustData,p,a,b) +#define ITypeLib2_GetLibStatistics(p,a,b) ICOM_CALL2(GetLibStatistics,p,a,b) +#define ITypeLib2_GetDocumentation2(p,a,b,c,d,e,f) ICOM_CALL5(GetDocumentation2,p,a,b,c,d,e) +#define ITypeLib2_GetAllCustData(p,a) ICOM_CALL1(GetAllCustData,p,a) + +/***************************************************************************** + * ITypeComp interface + */ +#define ICOM_INTERFACE ITypeComp +#define ITypeComp_METHODS \ + ICOM_METHOD6(HRESULT,Bind, LPOLESTR,szName, ULONG,lHashVal, WORD,wFlags, ITypeInfo**,ppTInfo, DESCKIND*,pDescKind, BINDPTR*,pBindPtr) \ + ICOM_METHOD4(HRESULT,BindType, LPOLESTR,szName, ULONG,lHashVal, ITypeInfo**,ppTInfo, ITypeComp**,ppTComp) +#define ITypeComp_IMETHODS \ + IUnknown_IMETHODS \ + ITypeComp_METHODS +ICOM_DEFINE(ITypeComp,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ITypeComp_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ITypeComp_AddRef(p) ICOM_CALL (AddRef,p) +#define ITypeComp_Release(p) ICOM_CALL (Release,p) +/*** ITypeComp methods ***/ +#define ITypeComp_Bind(p,a,b,c,d,e,f) ICOM_CALL6(Bind,p,a,b,c,d,e,f) +#define ITypeComp_BindType(p,a,b,c,d) ICOM_CALL4(BindType,p,a,b,c,d) + +/***************************************************************************** + * IEnumVARIANT interface + */ +#define ICOM_INTERFACE IEnumVARIANT +#define IEnumVARIANT_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, VARIANT*,rgVar, ULONG*,pCeltFetched) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumVARIANT**,ppEnum) +#define IEnumVARIANT_IMETHODS \ + IUnknown_IMETHODS \ + IEnumVARIANT_METHODS +ICOM_DEFINE(IEnumVARIANT,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumVARIANT_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumVARIANT_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumVARIANT_Release(p) ICOM_CALL (Release,p) +/*** IEnumVARIANT methods ***/ +#define IEnumVARIANT_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumVARIANT_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumVARIANT_Reset(p) ICOM_CALL (Reset,p) +#define IEnumVARIANT_Clone(p,a) ICOM_CALL1(Clone,p,a) + +#endif /* __WINE_WINE_OBJ_OLEAUT_H */ + diff --git a/include/ole32/obj_olefont.h b/include/ole32/obj_olefont.h new file mode 100644 index 0000000..c0edcf4 --- /dev/null +++ b/include/ole32/obj_olefont.h @@ -0,0 +1,119 @@ +/* + * Defines the COM interfaces and APIs related to OLE font support. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_OLEFONT_H +#define __WINE_WINE_OBJ_OLEFONT_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IFont, 0xBEF6E002, 0xA874, 0x101A, 0x8B, 0xBA, 0x00, 0xAA, 0x00, 0x30, 0x0C, 0xAB); +typedef struct IFont IFont,*LPFONT; + +DEFINE_GUID(IID_IFontDisp, 0xBEF6E003, 0xA874, 0x101A, 0x8B, 0xBA, 0x00, 0xAA, 0x00, 0x30, 0x0C, 0xAB); +typedef struct IFontDisp IFontDisp,*LPFONTDISP; + +typedef TEXTMETRICW TEXTMETRICOLE; + +/***************************************************************************** + * IFont interface + */ +#define ICOM_INTERFACE IFont +#define IFont_METHODS \ + ICOM_METHOD1(HRESULT, get_Name, BSTR*, pname) \ + ICOM_METHOD1(HRESULT, put_Name, BSTR, name) \ + ICOM_METHOD1(HRESULT, get_Size, CY*, psize) \ + ICOM_METHOD1(HRESULT, put_Size, CY, size) \ + ICOM_METHOD1(HRESULT, get_Bold, BOOL*, pbold) \ + ICOM_METHOD1(HRESULT, put_Bold, BOOL, bold) \ + ICOM_METHOD1(HRESULT, get_Italic, BOOL*, pitalic) \ + ICOM_METHOD1(HRESULT, put_Italic, BOOL, italic) \ + ICOM_METHOD1(HRESULT, get_Underline, BOOL*, punderline) \ + ICOM_METHOD1(HRESULT, put_Underline, BOOL, underline) \ + ICOM_METHOD1(HRESULT, get_Strikethrough, BOOL*, pstrikethrough) \ + ICOM_METHOD1(HRESULT, put_Strikethrough, BOOL, strikethrough) \ + ICOM_METHOD1(HRESULT, get_Weight, short*, pweight) \ + ICOM_METHOD1(HRESULT, put_Weight, short, weight) \ + ICOM_METHOD1(HRESULT, get_Charset, short*, pcharset) \ + ICOM_METHOD1(HRESULT, put_Charset, short, charset) \ + ICOM_METHOD1(HRESULT, get_hFont, HFONT*, phfont) \ + ICOM_METHOD1(HRESULT, Clone, IFont**, ppfont) \ + ICOM_METHOD1(HRESULT, IsEqual, IFont*, pFontOther) \ + ICOM_METHOD2(HRESULT, SetRatio, long, cyLogical, long, cyHimetric) \ + ICOM_METHOD1(HRESULT, QueryTextMetrics, TEXTMETRICOLE*, ptm) \ + ICOM_METHOD1(HRESULT, AddRefHfont, HFONT, hfont) \ + ICOM_METHOD1(HRESULT, ReleaseHfont, HFONT, hfont) \ + ICOM_METHOD1(HRESULT, SetHdc, HDC, hdc) +#define IFont_IMETHODS \ + IUnknown_IMEHTODS \ + IFont_METHODS +ICOM_DEFINE(IFont,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IFont_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IFont_AddRef(p) ICOM_CALL (AddRef,p) +#define IFont_Release(p) ICOM_CALL (Release,p) +/*** IFont methods ***/ +#define IFont_getName(p,a) ICOM_CALL1(get_Name,p,a) +#define IFont_putName(p,a) ICOM_CALL1(put_Name,p,a) +#define IFont_get_Size(p,a) ICOM_CALL1(get_Size,p,a) +#define IFont_put_Size(p,a) ICOM_CALL1(put_Size,p,a) +#define IFont_get_Bold(p,a) ICOM_CALL1(get_Bold,a) +#define IFont_put_Bold(p,a) ICOM_CALL1(put_Bold,a) +#define IFont_get_Italic(p,a) ICOM_CALL1(get_Italic,a) +#define IFont_put_Italic(p,a) ICOM_CALL1(put_Italic,a) +#define IFont_get_Underline(p,a) ICOM_CALL1(get_Underline,a) +#define IFont_put_Underline(p,a) ICOM_CALL1(put_Underline,a) +#define IFont_get_Strikethrough(p,a) ICOM_CALL1(get_Strikethrough,a) +#define IFont_put_Strikethrough(p,a) ICOM_CALL1(put_Strikethrough,a) +#define IFont_get_Weight(p,a) ICOM_CALL1(get_Weight,a) +#define IFont_put_Weight(p,a) ICOM_CALL1(put_Weight,a) +#define IFont_get_Charset(p,a) ICOM_CALL1(get_Charset,a) +#define IFont_put_Charset(p,a) ICOM_CALL1(put_Charset,a) +#define IFont_get_hFont(p,a) ICOM_CALL1(get_hFont,a) +#define IFont_put_hFont(p,a) ICOM_CALL1(put_hFont,a) +#define IFont_Clone(p,a) ICOM_CALL1(Clone,a) +#define IFont_IsEqual(p,a) ICOM_CALL1(IsEqual,a) +#define IFont_SetRatio(p,a,b) ICOM_CALL2(SetRatio,a,b) +#define IFont_QueryTextMetrics(p,a) ICOM_CALL1(QueryTextMetrics,a) +#define IFont_AddRefHfont(p,a) ICOM_CALL1(AddRefHfont,a) +#define IFont_ReleaseHfont(p,a) ICOM_CALL1(ReleaseHfont,a) +#define IFont_SetHdc(p,a) ICOM_CALL1(SetHdc,a) + +/***************************************************************************** + * IFont interface + */ +#define ICOM_INTERFACE IFontDisp +#define IFontDisp_METHODS +#define IFontDisp_IMETHODS \ + IUnknown_IMETHODS \ + IFontDisp_METHODS +ICOM_DEFINE(IFontDisp,IDispatch) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IFontDisp_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IFontDisp_AddRef(p) ICOM_CALL (AddRef,p) +#define IFontDisp_Release(p) ICOM_CALL (Release,p) +/*** IDispatch methods ***/ +#define IFontDisp_GetTypeInfoCount(p,a) ICOM_CALL1 (GetTypeInfoCount,p,a) +#define IFontDisp_GetTypeInfo(p,a,b,c) ICOM_CALL3 (GetTypeInfo,p,b,c) +#define IFontDisp_GetIDsOfNames(p,a,b,c,d,e) ICOM_CALL5 (GetIDsOfNames,p,a,b,c,d,e) +#define IFontDisp_Invoke(p,a,b,c,d,e,f,g,h) ICOM_CALL8 (Invoke,p,a,b,c,d,e,f,g,h) +/*** IFontDisp methods ***/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_OLEFONT_H */ + + diff --git a/include/ole32/obj_oleobj.h b/include/ole32/obj_oleobj.h new file mode 100644 index 0000000..fa6df7e --- /dev/null +++ b/include/ole32/obj_oleobj.h @@ -0,0 +1,196 @@ +/* + * Defines IOleObject COM and other oleidl.h interfaces + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_OLEOBJ_H +#define __WINE_WINE_OBJ_OLEOBJ_H + +struct tagMSG; +struct tagLOGPALETTE; + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Declare the structures + */ +typedef struct tagOBJECTDESCRIPTOR +{ + ULONG cbSize; + CLSID clsid; + DWORD dwDrawAspect; + SIZEL sizel; + POINTL pointl; + DWORD dwStatus; + DWORD dwFullUserTypeName; + DWORD dwSrcOfCopy; +} OBJECTDESCRIPTOR, *LPOBJECTDESCRIPTOR; + +typedef enum tagOLEMISC +{ + OLEMISC_RECOMPOSEONRESIZE = 0x1, + OLEMISC_ONLYICONIC = 0x2, + OLEMISC_INSERTNOTREPLACE = 0x4, + OLEMISC_STATIC = 0x8, + OLEMISC_CANTLINKINSIDE = 0x10, + OLEMISC_CANLINKBYOLE1 = 0x20, + OLEMISC_ISLINKOBJECT = 0x40, + OLEMISC_INSIDEOUT = 0x80, + OLEMISC_ACTIVATEWHENVISIBLE = 0x100, + OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200, + OLEMISC_INVISIBLEATRUNTIME = 0x400, + OLEMISC_ALWAYSRUN = 0x800, + OLEMISC_ACTSLIKEBUTTON = 0x1000, + OLEMISC_ACTSLIKELABEL = 0x2000, + OLEMISC_NOUIACTIVATE = 0x4000, + OLEMISC_ALIGNABLE = 0x8000, + OLEMISC_SIMPLEFRAME = 0x10000, + OLEMISC_SETCLIENTSITEFIRST = 0x20000, + OLEMISC_IMEMODE = 0x40000, + OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000, + OLEMISC_WANTSTOMENUMERGE = 0x100000, + OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000 +} OLEMISC; + +typedef enum tagOLEVERBATTRIB +{ + OLEVERBATTRIB_NEVERDIRTIES = 1, + OLEVERBATTRIB_ONCONTAINERMENU = 2 +} OLEVERBATTRIB; + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IOleObject, 0x00000112L, 0, 0); +typedef struct IOleObject IOleObject, *LPOLEOBJECT; + +DEFINE_OLEGUID(IID_IOleAdviseHolder, 0x00000111L, 0, 0); +typedef struct IOleAdviseHolder IOleAdviseHolder, *LPOLEADVISEHOLDER; + +DEFINE_OLEGUID(IID_IEnumOLEVERB, 0x00000104L, 0, 0); +typedef struct IEnumOLEVERB IEnumOLEVERB, *LPENUMOLEVERB; + +/***************************************************************************** + * IOleObject interface + */ +#define ICOM_INTERFACE IOleObject +#define IOleObject_METHODS \ + ICOM_METHOD1(HRESULT,SetClientSite, IOleClientSite*,pClientSite) \ + ICOM_METHOD1(HRESULT,GetClientSite, IOleClientSite**,ppClientSite) \ + ICOM_METHOD2(HRESULT,SetHostNames, LPCOLESTR,szContainerApp, LPCOLESTR,szContainerObj) \ + ICOM_METHOD1(HRESULT,Close, DWORD,dwSaveOption) \ + ICOM_METHOD2(HRESULT,SetMoniker, DWORD,dwWhichMoniker, IMoniker*,pmk) \ + ICOM_METHOD3(HRESULT,GetMoniker, DWORD,dwAssign, DWORD,dwWhichMoniker, IMoniker**,ppmk) \ + ICOM_METHOD3(HRESULT,InitFromData, IDataObject*,pDataObject, BOOL,fCreation, DWORD,dwReserved) \ + ICOM_METHOD2(HRESULT,GetClipboardData, DWORD,dwReserved, IDataObject**,ppDataObject) \ + ICOM_METHOD6(HRESULT,DoVerb, LONG,iVerb, struct tagMSG*,lpmsg, IOleClientSite*,pActiveSite, LONG,lindex, HWND,hwndParent, LPCRECT,lprcPosRect) \ + ICOM_METHOD1(HRESULT,EnumVerbs, IEnumOLEVERB**,ppEnumOleVerb) \ + ICOM_METHOD (HRESULT,Update) \ + ICOM_METHOD (HRESULT,IsUpToDate) \ + ICOM_METHOD1(HRESULT,GetUserClassID, CLSID*,pClsid) \ + ICOM_METHOD2(HRESULT,GetUserType, DWORD,dwFormOfType, LPOLESTR*,pszUserType) \ + ICOM_METHOD2(HRESULT,SetExtent, DWORD,dwDrawAspect, SIZEL*,psizel) \ + ICOM_METHOD2(HRESULT,GetExtent, DWORD,dwDrawAspect, SIZEL*,psizel) \ + ICOM_METHOD2(HRESULT,Advise, IAdviseSink*,pAdvSink, DWORD*,pdwConnection) \ + ICOM_METHOD1(HRESULT,Unadvise, DWORD,dwConnection) \ + ICOM_METHOD1(HRESULT,EnumAdvise, IEnumSTATDATA**,ppenumAdvise) \ + ICOM_METHOD2(HRESULT,GetMiscStatus, DWORD,dwAspect, DWORD*,pdwStatus) \ + ICOM_METHOD1(HRESULT,SetColorScheme, struct tagLOGPALETTE*,pLogpal) +#define IOleObject_IMETHODS \ + IUnknown_IMETHODS \ + IOleObject_METHODS +ICOM_DEFINE(IOleObject,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleObject_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleObject_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleObject_Release(p) ICOM_CALL (Release,p) +/*** IOleObject methods ***/ +#define IOleObject_SetClientSite(p,a) ICOM_CALL1(SetClientSite,p,a) +#define IOleObject_GetClientSite(p,a,b) ICOM_CALL1(GetClientSite,p,a) +#define IOleObject_SetHostNames(p,a,b) ICOM_CALL2(SetHostNames,p,a,b) +#define IOleObject_Close(p,a,b) ICOM_CALL1(Close,p,a) +#define IOleObject_SetMoniker(p,a,b) ICOM_CALL2(SetMoniker,p,a,b) +#define IOleObject_GetMoniker(p,a,b) ICOM_CALL3(GetMoniker,p,a,b,c) +#define IOleObject_InitFromData(p,a,b) ICOM_CALL3(InitFromData,p,a,b,c) +#define IOleObject_GetClipboardData(p,a,b) ICOM_CALL2(GetClipboardData,p,a,b) +#define IOleObject_DoVerb(p,a,b) ICOM_CALL6(DoVerb,p,a,b,c,d,e,f) +#define IOleObject_EnumVerbs(p,a,b) ICOM_CALL1(EnumVerbs,p,a) +#define IOleObject_Update(p,a,b) ICOM_CALL (Update,p) +#define IOleObject_IsUpToDate(p,a,b) ICOM_CALL (IsUpToDate,p) +#define IOleObject_GetUserClassID(p,a,b) ICOM_CALL1(GetUserClassID,p,a) +#define IOleObject_GetUserType(p,a,b) ICOM_CALL2(GetUserType,p,a,b) +#define IOleObject_SetExtent(p,a,b) ICOM_CALL2(SetExtent,p,a,b) +#define IOleObject_GetExtent(p,a,b) ICOM_CALL2(GetExtent,p,a,b) +#define IOleObject_Advise(p,a,b) ICOM_CALL2(Advise,p,a,b) +#define IOleObject_Unadvise(p,a,b) ICOM_CALL1(Unadvise,p,a) +#define IOleObject_EnumAdvise(p,a,b) ICOM_CALL1(EnumAdvise,p,a) +#define IOleObject_GetMiscStatus(p,a,b) ICOM_CALL2(GetMiscStatus,p,a,b) +#define IOleObject_SetColorScheme(p,a,b) ICOM_CALL1(SetColorScheme,p,a) + + +/***************************************************************************** + * IOleAdviseHolder interface + */ +#define ICOM_INTERFACE IOleAdviseHolder +#define IOleAdviseHolder_METHODS \ + ICOM_METHOD2(HRESULT,Advise, IAdviseSink*,pAdvise, DWORD*,pdwConnection) \ + ICOM_METHOD1(HRESULT,Unadvise, DWORD,dwConnection) \ + ICOM_METHOD1(HRESULT,EnumAdvise, IEnumSTATDATA**,ppenumAdvise) \ + ICOM_METHOD1(HRESULT,SendOnRename, IMoniker*,pmk) \ + ICOM_METHOD (HRESULT,SendOnSave) \ + ICOM_METHOD (HRESULT,SendOnClose) +#define IOleAdviseHolder_IMETHODS \ + IUnknown_IMETHODS \ + IOleAdviseHolder_METHODS +ICOM_DEFINE(IOleAdviseHolder,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleAdviseHolder_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleAdviseHolder_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleAdviseHolder_Release(p) ICOM_CALL (Release,p) +/*** IOleAdviseHolder methods ***/ +#define IOleAdviseHolder_Advise(p,a,b) ICOM_CALL2(Advise,p,a,b) +#define IOleAdviseHolder_Unadvise(p,a) ICOM_CALL1(Unadvise,p,a) +#define IOleAdviseHolder_EnumAdvise(p,a) ICOM_CALL1(EnumAdvise,p,a) +#define IOleAdviseHolder_SendOnRename(p,a) ICOM_CALL1(SendOnRename,p,a) +#define IOleAdviseHolder_SendOnSave(p) ICOM_CALL (SendOnSave,p) +#define IOleAdviseHolder_SendOnClose(p) ICOM_CALL (SendOnClose,p) + + +/***************************************************************************** + * IEnumOLEVERB interface + */ +#define ICOM_INTERFACE IEnumOLEVERB +#define IEnumOLEVERB_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, LPOLEVERB,rgelt, ULONG*,pceltFetched) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumOLEVERB**,ppenum) +#define IEnumOLEVERB_IMETHODS \ + IUnknown_IMETHODS \ + IEnumOLEVERB_METHODS +ICOM_DEFINE(IEnumOLEVERB,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumOLEVERB_QueryInterface(p,a,b) ICOM_ICALL2(IUnknown,QueryInterface,p,a,b) +#define IEnumOLEVERB_AddRef(p) ICOM_ICALL (IUnknown,AddRef,p) +#define IEnumOLEVERB_Release(p) ICOM_ICALL (IUnknown,Release,p) +/*** IEnumOLEVERB methods ***/ +#define IEnumOLEVERB_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumOLEVERB_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumOLEVERB_Reset(p,a) ICOM_CALL (Reset,p) +#define IEnumOLEVERB_Clone(p,a) ICOM_CALL1(Clone,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_OLEOBJ_H */ + diff --git a/include/ole32/obj_oleundo.h b/include/ole32/obj_oleundo.h new file mode 100644 index 0000000..b52fbe2 --- /dev/null +++ b/include/ole32/obj_oleundo.h @@ -0,0 +1,289 @@ +/* + * Defines the COM interfaces and APIs from ocidl.h which pertain to Undo/Redo + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_OLEUNDO_H +#define __WINE_WINE_OBJ_OLEUNDO_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IQuickActivate, 0xcf51ed10, 0x62fe, 0x11cf, 0xbf, 0x86, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0x36); +typedef struct IQuickActivate IQuickActivate,*LPQUICKACTIVATE; + +DEFINE_GUID(IID_IPointerInactive, 0x55980ba0, 0x35aa, 0x11cf, 0xb6, 0x71, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8); +typedef struct IPointerInactive IPointerInactive,*LPPOINTERINACTIVE; + +DEFINE_GUID(IID_IAdviseSinkEx, 0x3af24290, 0x0c96, 0x11ce, 0xa0, 0xcf, 0x00, 0xaa, 0x00, 0x60, 0x0a, 0xb8); +typedef struct IAdviseSinkEx IAdviseSinkEx,*LPADVISESINKEX; + +DEFINE_GUID(IID_IOleUndoManager, 0xd001f200, 0xef97, 0x11ce, 0x9b, 0xc9, 0x00, 0xaa, 0x00, 0x60, 0x8e, 0x01); +typedef struct IOleUndoManager IOleUndoManager,*LPOLEUNDOMANAGER; + +DEFINE_GUID(IID_IOleUndoUnit, 0x894ad3b0, 0xef97, 0x11ce, 0x9b, 0xc9, 0x00, 0xaa, 0x00, 0x60, 0x8e, 0x01); +typedef struct IOleUndoUnit IOleUndoUnit,*LPOLEUNDOUNIT; + +DEFINE_GUID(IID_IOleParentUndoUnit, 0xa1faf330, 0xef97, 0x11ce, 0x9b, 0xc9, 0x00, 0xaa, 0x00, 0x60, 0x8e, 0x01); +typedef struct IOleParentUndoUnit IOleParentUndoUnit,*LPOLEPARENTUNDOUNIT; + +DEFINE_GUID(IID_IEnumOleUndoUnits, 0xb3e7c340, 0xef97, 0x11ce, 0x9b, 0xc9, 0x00, 0xaa, 0x00, 0x60, 0x8e, 0x01); +typedef struct IEnumOleUndoUnits IEnumOleUndoUnits,*LPENUMOLEUNDOUNITS; + +/***************************************************************************** + * Declare the structures + */ +typedef enum tagQACONTAINERFLAGS +{ + QACONTAINER_SHOWHATCHING = 0x1, + QACONTAINER_SHOWGRABHANDLES = 0x2, + QACONTAINER_USERMODE = 0x4, + QACONTAINER_DISPLAYASDEFAULT = 0x8, + QACONTAINER_UIDEAD = 0x10, + QACONTAINER_AUTOCLIP = 0x20, + QACONTAINER_MESSAGEREFLECT = 0x40, + QACONTAINER_SUPPORTSMNEMONICS = 0x80 +} QACONTAINERFLAGS; + +typedef DWORD OLE_COLOR; + +typedef struct tagQACONTROL +{ + ULONG cbSize; + DWORD dwMiscStatus; + DWORD dwViewStatus; + DWORD dwEventCookie; + DWORD dwPropNotifyCookie; + DWORD dwPointerActivationPolicy; +} QACONTROL; + +typedef struct tagQACONTAINER +{ + ULONG cbSize; + IOleClientSite *pClientSite; + IAdviseSinkEx *pAdviseSink; + IPropertyNotifySink *pPropertyNotifySink; + IUnknown *pUnkEventSink; + DWORD dwAmbientFlags; + OLE_COLOR colorFore; + OLE_COLOR colorBack; + IFont *pFont; + IOleUndoManager *pUndoMgr; + DWORD dwAppearance; + LONG lcid; + HPALETTE hpal; + struct IBindHost *pBindHost; +} QACONTAINER; + +/***************************************************************************** + * IQuickActivate interface + */ +#define ICOM_INTERFACE IQuickActivate +#define IQuickActivate_METHODS \ + ICOM_METHOD2(HRESULT,QuickActivate, QACONTAINER*,pQaContainer, QACONTROL*,pQaControl) \ + ICOM_METHOD1(HRESULT,SetContentExtent, LPSIZEL,pSizel) \ + ICOM_METHOD1(HRESULT,GetContentExtent, LPSIZEL,pSizel) +#define IQuickActivate_IMETHODS \ + IUnknown_IMETHODS \ + IQuickActivate_METHODS +ICOM_DEFINE(IQuickActivate,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IQuickActivate_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IQuickActivate_AddRef(p) ICOM_CALL (AddRef,p) +#define IQuickActivate_Release(p) ICOM_CALL (Release,p) +/*** IQuickActivate methods ***/ +#define IQuickActivate_QuickActivate(p,a,b) ICOM_CALL2(QuickActivate,p,a,b) +#define IQuickActivate_SetContentExtent(p,a) ICOM_CALL1(SetContentExtent,p,a) +#define IQuickActivate_GetContentExtent(p,a) ICOM_CALL1(GetContentExtent,p,a) + + +/***************************************************************************** + * IPointerInactive interface + */ +#define ICOM_INTERFACE IPointerInactive +#define IPointerInactive_METHODS \ + ICOM_METHOD1(HRESULT,GetActivationPolicy, DWORD*,pdwPolicy) \ + ICOM_METHOD4(HRESULT,OnInactiveMouseMove, LPCRECT,pRectBounds, LONG,x, LONG,y, DWORD,grfKeyState) \ + ICOM_METHOD5(HRESULT,OnInactiveSetCursor, LPCRECT,pRectBounds, LONG,x, LONG,y, DWORD,dwMouseMsg, BOOL,fSetAlways) +#define IPointerInactive_IMETHODS \ + IUnknown_IMETHODS \ + IPointerInactive_METHODS +ICOM_DEFINE(IPointerInactive,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPointerInactive_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPointerInactive_AddRef(p) ICOM_CALL (AddRef,p) +#define IPointerInactive_Release(p) ICOM_CALL (Release,p) +/*** IPointerInactive methods ***/ +#define IPointerInactive_GetActivationPolicy(p,a) ICOM_CALL1(GetActivationPolicy,p,a) +#define IPointerInactive_OnInactiveMoveMouse(p,a,b,c,d) ICOM_CALL4(OnInactiveMoveMouse,p,a,b,c,d) +#define IPointerInactive_OnInactiveSetCursor(p,a,b,c,d,e) ICOM_CALL5(OnInactiveSetCursor,p,a,b,d,e) + + +/***************************************************************************** + * IAdviseSinkEx interface + */ +#define ICOM_INTERFACE IAdviseSinkEx +#define IAdviseSinkEx_METHODS \ + ICOM_METHOD1(HRESULT,OnViewStatusChange, DWORD,dwViewStatus) +#define IAdviseSinkEx_IMETHODS \ + IAdviseSink_IMETHODS \ + IAdviseSinkEx_METHODS +ICOM_DEFINE(IAdviseSinkEx,IAdviseSink) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IAdviseSinkEx_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IAdviseSinkEx_AddRef(p) ICOM_CALL (AddRef,p) +#define IAdviseSinkEx_Release(p) ICOM_CALL (Release,p) +/*** IAdviseSink methods ***/ +#define IAdviseSinkEx_OnDataChange(p,a,b) ICOM_CALL2(OnDataChange,p,a,b) +#define IAdviseSinkEx_OnViewChange(p,a,b) ICOM_CALL2(OnViewChange,p,a,b) +#define IAdviseSinkEx_OnRename(p,a) ICOM_CALL1(OnRename,p,a) +#define IAdviseSinkEx_OnSave(p) ICOM_CALL (OnSave,p) +#define IAdviseSinkEx_OnClose(p) ICOM_CALL (OnClose,p) +/*** IAdviseSinkEx methods ***/ +#define IAdviseSinkEx_OnViewStatusChange(p,a) ICOM_CALL1(OnViewStatusChange,p,a) + + +/***************************************************************************** + * IOleUndoManager interface + */ +#define ICOM_INTERFACE IOleUndoManager +#define IOleUndoManager_METHODS \ + ICOM_METHOD1(HRESULT,Open, IOleParentUndoUnit*,pPUU) \ + ICOM_METHOD2(HRESULT,Close, IOleParentUndoUnit*,pPUU, BOOL,fCommit) \ + ICOM_METHOD1(HRESULT,Add, IOleUndoUnit*,pUU) \ + ICOM_METHOD1(HRESULT,GetOpenParentState, DWORD*,pdwState) \ + ICOM_METHOD1(HRESULT,DiscardFrom, IOleUndoUnit*,pUU) \ + ICOM_METHOD1(HRESULT,UndoTo, IOleUndoUnit*,pUU) \ + ICOM_METHOD1(HRESULT,RedoTo, IOleUndoUnit*,pUU) \ + ICOM_METHOD1(HRESULT,EnumUndoable, IEnumOleUndoUnits**,ppEnum) \ + ICOM_METHOD1(HRESULT,EnumRedoable, IEnumOleUndoUnits**,ppEnum) \ + ICOM_METHOD1(HRESULT,GetLastUndoDescription, BSTR*,pBstr) \ + ICOM_METHOD1(HRESULT,GetLastRedoDescription, BSTR*,pBstr) \ + ICOM_METHOD1(HRESULT,Enable, BOOL,fEnable) +#define IOleUndoManager_IMETHODS \ + IUnknown_IMETHODS \ + IOleUndoManager_METHODS +ICOM_DEFINE(IOleUndoManager,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleUndoManager_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleUndoManager_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleUndoManager_Release(p) ICOM_CALL (Release,p) +/*** IOleUndoManager methods ***/ +#define IOleUndoManager_Open(p,a) ICOM_CALL1(Open,p,a) +#define IOleUndoManager_Close(p,a,b) ICOM_CALL2(Close,p,a,b) +#define IOleUndoManager_Add(p,a) ICOM_CALL1(Add,p,a) +#define IOleUndoManager_GetOpenParentState(p,a) ICOM_CALL1(GetOpenParentState,p,a) +#define IOleUndoManager_DiscardFrom(p,a) ICOM_CALL1(DiscardFrom,p,a) +#define IOleUndoManager_UndoTo(p,a) ICOM_CALL1(UndoTo,p,a) +#define IOleUndoManager_RedoTo(p,a) ICOM_CALL1(RedoTo,p,a) +#define IOleUndoManager_EnumUndoable(p,a) ICOM_CALL1(EnumUndoable,p,a) +#define IOleUndoManager_EnumRedoable(p,a) ICOM_CALL1(EnumRedoable,p,a) +#define IOleUndoManager_GetLastUndoDescription(p,a) ICOM_CALL1(GetLastUndoDescription,p,a) +#define IOleUndoManager_GetLastRedoDescription(p,a) ICOM_CALL1(GetLastRedoDescription,p,a) +#define IOleUndoManager_Enable(p,a) ICOM_CALL1(Enable,p,a) + + +/***************************************************************************** + * IOleUndoUnit interface + */ +#define ICOM_INTERFACE IOleUndoUnit +#define IOleUndoUnit_METHODS \ + ICOM_METHOD1(HRESULT,Do, IOleUndoManager*,pUndoManager) \ + ICOM_METHOD1(HRESULT,GetDescription, BSTR*,pBstr) \ + ICOM_METHOD2(HRESULT,GetUnitType, CLSID*,pClsid, LONG*,plID) \ + ICOM_METHOD (HRESULT,OnNextAdd) +#define IOleUndoUnit_IMETHODS \ + IUnknown_IMETHODS \ + IOleUndoUnit_METHODS +ICOM_DEFINE(IOleUndoUnit,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleUndoUnit_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleUndoUnit_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleUndoUnit_Release(p) ICOM_CALL (Release,p) +/*** IOleUndoUnit methods ***/ +#define IOleUndoUnit_Do(p,a) ICOM_CALL1(Do,p,a) +#define IOleUndoUnit_GetDescription(p,a) ICOM_CALL1(GetDescription,p,a) +#define IOleUndoUnit_GetUnitType(p,a,b) ICOM_CALL2(GetUnitType,p,a,b) +#define IOleUndoUnit_OnNextAdd(p) ICOM_CALL (OnNextAdd,p) + + + +/***************************************************************************** + * IOleUndoUnit interface + */ +#define ICOM_INTERFACE IOleParentUndoUnit +#define IOleParentUndoUnit_METHODS \ + ICOM_METHOD1(HRESULT,Open, IOleParentUndoUnit*,pPUU) \ + ICOM_METHOD2(HRESULT,Close, IOleParentUndoUnit*,pPUU, BOOL,fCommit) \ + ICOM_METHOD1(HRESULT,Add, IOleUndoUnit*,pUU) \ + ICOM_METHOD1(HRESULT,FindUnit, IOleUndoUnit*,pUU) \ + ICOM_METHOD1(HRESULT,GetParentState, DWORD*,pdwState) +#define IOleParentUndoUnit_IMETHODS \ + IOleUndoUnit_IMETHODS \ + IOleParentUndoUnit_METHODS +ICOM_DEFINE(IOleParentUndoUnit,IOleUndoUnit) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IOleParentUndoUnit_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IOleParentUndoUnit_AddRef(p) ICOM_CALL (AddRef,p) +#define IOleParentUndoUnit_Release(p) ICOM_CALL (Release,p) +/*** IOleUndoUnit methods ***/ +#define IOleParentUndoUnit_Do(p,a) ICOM_CALL1(Do,p,a) +#define IOleParentUndoUnit_GetDescription(p,a) ICOM_CALL1(GetDescription,p,a) +#define IOleParentUndoUnit_GetUnitType(p,a,b) ICOM_CALL2(GetUnitType,p,a,b) +#define IOleParentUndoUnit_OnNextAdd(p) ICOM_CALL (OnNextAdd,p) +/*** IOleParentUndoUnit methods ***/ +#define IOleParentUndoUnit_Open(p,a) ICOM_CALL1(Open,p,a) +#define IOleParentUndoUnit_Close(p,a,b) ICOM_CALL2(Close,p,a,b) +#define IOleParentUndoUnit_Add(p,a) ICOM_CALL1(Add,p,a) +#define IOleParentUndoUnit_FindUnit(p,a) ICOM_CALL1(FindUnit,p,a) +#define IOleParentUndoUnit_GetParentState(p,a,b) ICOM_CALL1(GetParentState,p,a) + + +/***************************************************************************** + * IEnumOleUndoUnits interface + */ +#define ICOM_INTERFACE IEnumOleUndoUnits +#define IEnumOleUndoUnits_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,cElt, IOleUndoUnit**,rgElt, ULONG*,pcEltFetched) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,cElt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumOleUndoUnits**,ppEnum) +#define IEnumOleUndoUnits_IMETHODS \ + IUnknown_IMETHODS \ + IEnumOleUndoUnits_METHODS +ICOM_DEFINE(IEnumOleUndoUnits,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumOleUndoUnits_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumOleUndoUnits_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumOleUndoUnits_Release(p) ICOM_CALL (Release,p) +/*** IEnumOleUndoUnits methods ***/ +#define IEnumOleUndoUnits_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumOleUndoUnits_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumOleUndoUnits_Reset(p,a) ICOM_CALL (Reset,p,a) +#define IEnumOleUndoUnits_Clone(p,a) ICOM_CALL1(Clone,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_OLEUNDO_H */ + diff --git a/include/ole32/obj_oleview.h b/include/ole32/obj_oleview.h new file mode 100644 index 0000000..b79deec --- /dev/null +++ b/include/ole32/obj_oleview.h @@ -0,0 +1,94 @@ +/* + * Defines the COM interfaces and APIs related to ViewObject + * + */ + +#ifndef __WINE_WINE_OBJ_OLEVIEW_H +#define __WINE_WINE_OBJ_OLEVIEW_H + +struct tagLOGPALETTE; + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Declare the structures + */ + + +/***************************************************************************** + * Predeclare the interfaces + */ + +DEFINE_OLEGUID(IID_IViewObject, 0x0000010dL, 0, 0); +typedef struct IViewObject IViewObject, *LPVIEWOBJECT; + +DEFINE_OLEGUID(IID_IViewObject2, 0x00000127L, 0, 0); +typedef struct IViewObject2 IViewObject2, *LPVIEWOBJECT2; + +/***************************************************************************** + * IViewObject interface + */ +typedef BOOL CALLBACK (*IVO_ContCallback)(DWORD); + +#define ICOM_INTERFACE IViewObject +#define IViewObject_METHODS \ + ICOM_METHOD10(HRESULT,Draw, DWORD,dwDrawAspect, LONG,lindex, void*,pvAspect, DVTARGETDEVICE*,ptd, HDC,hdcTargetDev, HDC,hdcDraw, LPCRECTL,lprcBounds, LPCRECTL,lprcWBounds, IVO_ContCallback, pfnContinue, DWORD,dwContinue) \ + ICOM_METHOD6(HRESULT,GetColorSet, DWORD,dwDrawAspect, LONG,lindex, void*,pvAspect, DVTARGETDEVICE*,ptd, HDC,hicTargetDevice, struct tagLOGPALETTE**,ppColorSet) \ + ICOM_METHOD4(HRESULT,Freeze, DWORD,dwDrawAspect, LONG,lindex, void*,pvAspect, DWORD*,pdwFreeze) \ + ICOM_METHOD1(HRESULT,Unfreeze, DWORD,dwFreeze) \ + ICOM_METHOD3(HRESULT,SetAdvise, DWORD,aspects, DWORD,advf, IAdviseSink*,pAdvSink) \ + ICOM_METHOD3(HRESULT,GetAdvise, DWORD*,pAspects, DWORD*,pAdvf, IAdviseSink**,ppAdvSink) +#define IViewObject_IMETHODS \ + IUnknown_IMETHODS \ + IViewObject_METHODS +ICOM_DEFINE(IViewObject,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IViewObject_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IViewObject_AddRef(p) ICOM_CALL (AddRef,p) +#define IViewObject_Release(p) ICOM_CALL (Release,p) +/*** IViewObject methods ***/ +#define IViewObject_Draw(p,a,b,c,d,e,f,g,h,i,j) ICOM_CALL10(Draw,p,a,b,c,d,e,f,g,h,i,j) +#define IViewObject_GetColorSet(p,a,b,c,d,e,f) ICOM_CALL6(GetColorSet,p,a,b,c,d,e,f) +#define IViewObject_Freeze(p,a,b,c,d) ICOM_CALL4(Freeze,p,a,b,c,d) +#define IViewObject_Unfreeze(p,a) ICOM_CALL1(Unfreeze,p,a) +#define IViewObject_SetAdvise(p,a,b,c) ICOM_CALL3(SetAdvise,p,a,b,c) +#define IViewObject_GetAdvise(p,a,b,c) ICOM_CALL3(GetAdvise,p,a,b,c) + + + +/***************************************************************************** + * IViewObject2 interface + */ +#define ICOM_INTERFACE IViewObject2 +#define IViewObject2_METHODS \ + ICOM_METHOD4(HRESULT,GetExtent, DWORD,dwDrawAspect, LONG,lindex, DVTARGETDEVICE*,ptd, LPSIZEL,lpsizel) +#define IViewObject2_IMETHODS \ + IViewObject_IMETHODS \ + IViewObject2_METHODS +ICOM_DEFINE(IViewObject2,IViewObject) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IViewObject2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IViewObject2_AddRef(p) ICOM_CALL (AddRef,p) +#define IViewObject2_Release(p) ICOM_CALL (Release,p) +/*** IViewObject methods ***/ +#define IViewObject2_Draw(p,a,b,c,d,e,f,g,h,i,j) ICOM_CALL10(Draw,p,a,b,c,d,e,f,g,h,i,j) +#define IViewObject2_GetColorSet(p,a,b,c,d,e,f) ICOM_CALL6(GetColorSet,p,a,b,c,d,e,f) +#define IViewObject2_Freeze(p,a,b,c,d) ICOM_CALL4(Freeze,p,a,b,c,d) +#define IViewObject2_Unfreeze(p,a) ICOM_CALL1(Unfreeze,p,a) +#define IViewObject2_SetAdvise(p,a,b,c) ICOM_CALL3(SetAdvise,p,a,b,c) +#define IViewObject2_GetAdvise(p,a,b,c) ICOM_CALL3(GetAdvise,p,a,b,c) +/*** IViewObject2 methods ***/ +#define IViewObject2_GetExtent(p,a,b,c,d) ICOM_CALL4(GetExtent,p,a,b,c,d) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_OLEVIEW_H */ + diff --git a/include/ole32/obj_picture.h b/include/ole32/obj_picture.h new file mode 100644 index 0000000..2e2d55c --- /dev/null +++ b/include/ole32/obj_picture.h @@ -0,0 +1,108 @@ +/* + * Defines the COM interfaces and APIs related to OLE picture support. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_PICTURE_H +#define __WINE_WINE_OBJ_PICTURE_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the structures + */ +typedef UINT OLE_HANDLE; +typedef LONG OLE_XPOS_HIMETRIC; +typedef LONG OLE_YPOS_HIMETRIC; +typedef LONG OLE_XSIZE_HIMETRIC; +typedef LONG OLE_YSIZE_HIMETRIC; + + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IPicture, 0x7bf80980, 0xbf32, 0x101a, 0x8b, 0xbb, 0x00, 0xAA, 0x00, 0x30, 0x0C, 0xAB); +typedef struct IPicture IPicture, *LPPICTURE; + +DEFINE_GUID(IID_IPictureDisp, 0x7bf80981, 0xbf32, 0x101a, 0x8b, 0xbb, 0x00, 0xAA, 0x00, 0x30, 0x0C, 0xAB); +typedef struct IPictureDisp IPictureDisp, *LPPICTUREDISP; + +/***************************************************************************** + * IPicture interface + */ +#define ICOM_INTERFACE IPicture +#define IPicture_METHODS \ + ICOM_METHOD1(HRESULT,get_Handle, OLE_HANDLE*,pHandle) \ + ICOM_METHOD1(HRESULT,get_hPal, OLE_HANDLE*,phPal) \ + ICOM_METHOD1(HRESULT,get_Type, SHORT*,pType) \ + ICOM_METHOD1(HRESULT,get_Width, OLE_XSIZE_HIMETRIC*,pWidth) \ + ICOM_METHOD1(HRESULT,get_Height, OLE_YSIZE_HIMETRIC*,pHeight) \ + ICOM_METHOD10(HRESULT,Render, HDC,hdc, LONG,x, LONG,y, LONG,cx, LONG,cy, OLE_XPOS_HIMETRIC,xSrc, OLE_YPOS_HIMETRIC,ySrc, OLE_XSIZE_HIMETRIC,cxSrc, OLE_YSIZE_HIMETRIC,cySrc, LPCRECT,pRcWBounds) \ + ICOM_METHOD1(HRESULT,set_hPal, OLE_HANDLE,hPal) \ + ICOM_METHOD1(HRESULT,get_CurDC, HDC*,phDC) \ + ICOM_METHOD3(HRESULT,SelectPicture, HDC,hDCIn, HDC*,phDCOut, OLE_HANDLE*,phBmpOut) \ + ICOM_METHOD1(HRESULT,get_KeepOriginalFormat, BOOL*,pKeep) \ + ICOM_METHOD1(HRESULT,put_KeepOriginalFormat, BOOL,Keep) \ + ICOM_METHOD (HRESULT,PictureChanged) \ + ICOM_METHOD3(HRESULT,SaveAsFile, LPSTREAM,pStream, BOOL,fSaveMemCopy, LONG*,pCbSize) \ + ICOM_METHOD1(HRESULT,get_Attributes, DWORD*,pDwAttr) +#define IPicture_IMETHODS \ + IUnknown_IMETHODS \ + IPicture_METHODS +ICOM_DEFINE(IPicture,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPicture_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPicture_AddRef(p) ICOM_CALL (AddRef,p) +#define IPicture_Release(p) ICOM_CALL (Release,p) +/*** IPicture methods ***/ +#define IPicture_get_Handle(p,a) ICOM_CALL1(get_Handle,p,a) +#define IPicture_get_hPal(p,a) ICOM_CALL1(get_hPal,p,a) +#define IPicture_get_Type(p,a) ICOM_CALL1(get_Type,p,a) +#define IPicture_get_Width(p,a) ICOM_CALL1(get_Width,p,a) +#define IPicture_get_Height(p,a) ICOM_CALL1(get_Height,p,a) +#define IPicture_Render(p,a,b,c,d,e,f,g,h,i,j) ICOM_CALL10(Render,p,a,b,c,d,e,f,g,h,i,j) +#define IPicture_set_hPal(p,a) ICOM_CALL1(set_hPal,p,a) +#define IPicture_get_CurDC(p,a) ICOM_CALL1(get_CurDC,p,a) +#define IPicture_SelectPicture(p,a,b,c) ICOM_CALL3(SelectPicture,p,a,b,c) +#define IPicture_get_KeepOriginalFormat(p,a) ICOM_CALL1(get_KeepOriginalFormat,p,a) +#define IPicture_put_KeepOriginalFormat(p,a) ICOM_CALL1(put_KeepOriginalFormat,p,a) +#define IPicture_PictureChanged(p) ICOM_CALL (PictureChanged,p) +#define IPicture_SaveAsFile(p,a,b,c) ICOM_CALL3(SaveAsFile,p,a,b,c) +#define IPicture_get_Attributes(p,a) ICOM_CALL1(get_Attributes,p,a) + + +/***************************************************************************** + * IPictureDisp interface + */ +#define ICOM_INTERFACE IPictureDisp +#define IPictureDisp_METHODS +#define IPictureDisp_IMETHODS \ + IDispatch_IMETHODS \ + IPictureDisp_METHODS +ICOM_DEFINE(IPictureDisp,IDispatch) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPictureDisp_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPictureDisp_AddRef(p) ICOM_CALL (AddRef,p) +#define IPictureDisp_Release(p) ICOM_CALL (Release,p) +/*** IDispatch methods ***/ +#define IPictureDisp_GetTypeInfoCount(p,a) ICOM_CALL1 (GetTypeInfoCount,p,a) +#define IPictureDisp_GetTypeInfo(p,a,b,c) ICOM_CALL3 (GetTypeInfo,p,b,c) +#define IPictureDisp_GetIDsOfNames(p,a,b,c,d,e) ICOM_CALL5 (GetIDsOfNames,p,a,b,c,d,e) +#define IPictureDisp_Invoke(p,a,b,c,d,e,f,g,h) ICOM_CALL8 (Invoke,p,a,b,c,d,e,f,g,h) +/*** IPictureDisp methods ***/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_PICTURE_H */ + + diff --git a/include/ole32/obj_property.h b/include/ole32/obj_property.h new file mode 100644 index 0000000..8ab92ab --- /dev/null +++ b/include/ole32/obj_property.h @@ -0,0 +1,413 @@ +/* + * Defines the COM interfaces and APIs from ocidl.h related to property + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_PROPERTY_H +#define __WINE_WINE_OBJ_PROPERTY_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Declare the structures + */ +typedef struct tagPROPPAGEINFO +{ + ULONG cb; + LPOLESTR pszTitle; + SIZE size; + LPOLESTR pszDocString; + LPOLESTR pszHelpFile; + DWORD dwHelpContext; +} PROPPAGEINFO, *LPPROPPAGEINFO; + +typedef enum tagPROPPAGESTATUS +{ + PROPPAGESTATUS_DIRTY = 0x1, + PROPPAGESTATUS_VALIDATE = 0x2, + PROPPAGESTATUS_CLEAN = 0x4 +} PROPPAGESTATUS; + +typedef struct tagCAUUID +{ + ULONG cElems; + GUID* pElems; +} CAUUID, *LPCAUUID; + +typedef struct tagCALPOLESTR +{ + ULONG cElems; + LPOLESTR *pElems; +} CALPOLESTR, *LPCALPOLESTR; + +typedef struct tagCADWORD +{ + ULONG cElems; + DWORD *pElems; +} CADWORD, *LPCADWORD; + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IPropertyPage, 0xb196b28dL, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IPropertyPage IPropertyPage, *LPPROPERTYPAGE; + +DEFINE_GUID(IID_IPropertyPage2, 0x01e44665L, 0x24ac, 0x101b, 0x84, 0xed, 0x08, 0x00, 0x2b, 0x2e, 0xc7, 0x13); +typedef struct IPropertyPage2 IPropertyPage2, *LPPROPERTYPAGE2; + +DEFINE_GUID(IID_IPropertyPageSite, 0xb196b28cL, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IPropertyPageSite IPropertyPageSite, *LPPROPERTYPAGESITE; + +DEFINE_GUID(IID_IPropertyNotifySink, 0x9bfbbc02L, 0xeff1, 0x101a, 0x84, 0xed, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IPropertyNotifySink IPropertyNotifySink, *LPPROPERTYNOTIFYSINK; + +DEFINE_GUID(IID_ISimpleFrameSite, 0x742b0e01L, 0x14e6, 0x101b, 0x91, 0x4e, 0x00, 0xaa, 0x00, 0x30, 0x0c, 0xab); +typedef struct ISimpleFrameSite ISimpleFrameSite, *LPSIMPLEFRAMESITE; + +DEFINE_GUID(IID_IPersistStreamInit, 0x7fd52380L, 0x4e07, 0x101b, 0xae, 0x2d, 0x08, 0x00, 0x2b, 0x2e, 0xc7, 0x13); +typedef struct IPersistStreamInit IPersistStreamInit,*LPPERSISTSTREAMINIT; + +DEFINE_GUID(IID_IPersistMemory, 0xbd1ae5e0L, 0xa6ae, 0x11ce, 0xbd, 0x37, 0x50, 0x42, 0x00, 0xc1, 0x00, 0x00); +typedef struct IPersistMemory IPersistMemory,*LPPERSISTMEMORY; + +DEFINE_GUID(IID_IPersistPropertyBag, 0x37d84f60, 0x42cb, 0x11ce, 0x81, 0x35, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51); +typedef struct IPersistPropertyBag IPersistPropertyBag,*LPPERSISTPROPERTYBAG; + +DEFINE_GUID(IID_IErrorLog, 0x3127ca40L, 0x446e, 0x11ce, 0x81, 0x35, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51); +typedef struct IErrorLog IErrorLog,*LPERRORLOG; + +DEFINE_GUID(IID_IPropertyBag, 0x55272a00L, 0x42cb, 0x11ce, 0x81, 0x35, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51); +typedef struct IPropertyBag IPropertyBag,*LPPROPERTYBAG; + +DEFINE_GUID(IID_ISpecifyPropertyPages, 0xb196b28b, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct ISpecifyPropertyPages ISpecifyPropertyPages,*LPSPECIFYPROPERTYPAGES; + +DEFINE_GUID(IID_IPerPropertyBrowsing, 0xb196b28b, 0xbab4, 0x101a, 0xb6, 0x9c, 0x00, 0xaa, 0x00, 0x34, 0x1d, 0x07); +typedef struct IPerPropertyBrowsing IPerPropertyBrowsing,*LPPERPROPERTYBROWSING; + + +/***************************************************************************** + * IPropertPage interface + */ +#define ICOM_INTERFACE IPropertyPage +#define IPropertyPage_METHODS \ + ICOM_METHOD1(HRESULT,SetPageSite, IPropertyPageSite*,pPageSite) \ + ICOM_METHOD3(HRESULT,Activate, HWND,hWndParent, LPCRECT,pRect, BOOL,bModal) \ + ICOM_METHOD (HRESULT,Deactivate) \ + ICOM_METHOD1(HRESULT,GetPageInfo, PROPPAGEINFO*,pPageInfo) \ + ICOM_METHOD2(HRESULT,SetObjects, ULONG,cObjects, IUnknown**,ppUnk) \ + ICOM_METHOD1(HRESULT,Show, UINT,nCmdShow) \ + ICOM_METHOD1(HRESULT,Move, LPCRECT,pRect) \ + ICOM_METHOD (HRESULT,IsPageDirty) \ + ICOM_METHOD (HRESULT,Apply) \ + ICOM_METHOD1(HRESULT,Help, LPCOLESTR,pszHelpDir) \ + ICOM_METHOD1(HRESULT,TranslateAccelerator, MSG*,pMsg) +#define IPropertyPage_IMETHODS \ + IUnknown_IMETHODS \ + IPropertyPage_METHODS +ICOM_DEFINE(IPropertyPage,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertyPage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertyPage_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertyPage_Release(p) ICOM_CALL (Release,p) +/*** IPropertyPage methods ***/ +#define IPropertyPage_SetPageSite(p,a) ICOM_CALL1(SetPageSite,p,a) +#define IPropertyPage_Activate(p,a,b,c) ICOM_CALL3(Activate,p,a,b,c) +#define IPropertyPage_Deactivate(p) ICOM_CALL (Deactivate,p) +#define IPropertyPage_GetPageInfo(p,a) ICOM_CALL1(GetPageInfo,p,a) +#define IPropertyPage_SetObjects(p,a,b) ICOM_CALL2(SetObjects,p,a,b) +#define IPropertyPage_Show(p,a) ICOM_CALL1(Show,p,a) +#define IPropertyPage_Move(p,a) ICOM_CALL1(Move,p,a) +#define IPropertyPage_IsPageDirty(p) ICOM_CALL (IsPageDirty,p) +#define IPropertyPage_Apply(p) ICOM_CALL (Apply,p) +#define IPropertyPage_Help(p,a) ICOM_CALL1(Help,p,a) +#define IPropertyPage_TranslateAccelerator(p,a) ICOM_CALL1(TranslateAccelerator,p,a) + + +/***************************************************************************** + * IPropertPage2 interface + */ +#define ICOM_INTERFACE IPropertyPage2 +#define IPropertyPage2_METHODS \ + ICOM_METHOD1(HRESULT,EditProperty, DISPID,dispID) +#define IPropertyPage2_IMETHODS \ + IPropertyPage_IMETHODS \ + IPropertyPage2_METHODS +ICOM_DEFINE(IPropertyPage2,IPropertyPage) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertyPage2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertyPage2_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertyPage2_Release(p) ICOM_CALL (Release,p) +/*** IPropertyPage methods ***/ +#define IPropertyPage2_SetPageSite(p,a) ICOM_CALL1(SetPageSite,p,a) +#define IPropertyPage2_Activate(p,a,b,c) ICOM_CALL3(Activate,p,a,b,c) +#define IPropertyPage2_Deactivate(p) ICOM_CALL (Deactivate,p) +#define IPropertyPage2_GetPageInfo(p,a) ICOM_CALL1(GetPageInfo,p,a) +#define IPropertyPage2_SetObjects(p,a,b) ICOM_CALL2(SetObjects,p,a,b) +#define IPropertyPage2_Show(p,a) ICOM_CALL1(Show,p,a) +#define IPropertyPage2_Move(p,a) ICOM_CALL1(Move,p,a) +#define IPropertyPage2_IsPageDirty(p) ICOM_CALL (IsPageDirty,p) +#define IPropertyPage2_Apply(p) ICOM_CALL (Apply,p) +#define IPropertyPage2_Help(p,a) ICOM_CALL1(Help,p,a) +#define IPropertyPage2_TranslateAccelerator(p,a) ICOM_CALL1(TranslateAccelerator,p,a) +/*** IPropertyPage2 methods ***/ +#define IPropertyPage2_EditProperty(p,a) ICOM_CALL1(EditProperty,p,a) + + +/***************************************************************************** + * IPropertPageSite interface + */ +#define ICOM_INTERFACE IPropertyPageSite +#define IPropertyPageSite_METHODS \ + ICOM_METHOD1(HRESULT,OnStatusChange, DWORD,dwFlags) \ + ICOM_METHOD1(HRESULT,GetLocaleID, LCID*,pLocaleID) \ + ICOM_METHOD1(HRESULT,GetPageContainer, IUnknown**,ppUnk) \ + ICOM_METHOD1(HRESULT,TranslateAccelerator, MSG*,pMsg) +#define IPropertyPageSite_IMETHODS \ + IUnknown_IMETHODS \ + IPropertyPageSite_METHODS +ICOM_DEFINE(IPropertyPageSite,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertyPageSite_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertyPageSite_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertyPageSite_Release(p) ICOM_CALL (Release,p) +/*** IPropertyPageSite methods ***/ +#define IPropertyPageSite_OnStatusChange(p,a) ICOM_CALL1(OnStatusChange,p,a) +#define IPropertyPageSite_GetLocaleID(p,a) ICOM_CALL1(GetLocaleID,p,a) +#define IPropertyPageSite_GetPageContainer(p,a) ICOM_CALL1(GetPageContainer,p,a) +#define IPropertyPageSite_TranslateAccelerator(p,a) ICOM_CALL1(TranslateAccelerator,p,a) + + +/***************************************************************************** + * IPropertyNotifySink interface + */ +#define ICOM_INTERFACE IPropertyNotifySink +#define IPropertyNotifySink_METHODS \ + ICOM_METHOD1(HRESULT,OnChanged, DISPID,dispID) \ + ICOM_METHOD1(HRESULT,OnRequestEdit, DISPID,dispID) +#define IPropertyNotifySink_IMETHODS \ + IUnknown_IMETHODS \ + IPropertyNotifySink_METHODS +ICOM_DEFINE(IPropertyNotifySink,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertyNotifySink_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertyNotifySink_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertyNotifySink_Release(p) ICOM_CALL (Release,p) +/*** IPropertyNotifySink methods ***/ +#define IPropertyNotifySink_OnChanged(p,a) ICOM_CALL1(OnChanged,p,a) +#define IPropertyNotifySink_OnRequestEdit(p,a) ICOM_CALL1(OnRequestEdit,p,a) + + +/***************************************************************************** + * IPropertyNotifySink interface + */ +#define ICOM_INTERFACE ISimpleFrameSite +#define ISimpleFrameSite_METHODS \ + ICOM_METHOD6(HRESULT,PreMessageFilter, HWND,hWnd, UINT,msg, WPARAM,wp, LPARAM,lp, LRESULT*,plResult, DWORD*,pwdCookie) \ + ICOM_METHOD6(HRESULT,PostMessageFilter, HWND,hWnd, UINT,msg, WPARAM,wp, LPARAM,lp, LRESULT*,plResult, DWORD,pwdCookie) +#define ISimpleFrameSite_IMETHODS \ + IUnknown_IMETHODS \ + ISimpleFrameSite_METHODS +ICOM_DEFINE(ISimpleFrameSite,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ISimpleFrameSite_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ISimpleFrameSite_AddRef(p) ICOM_CALL (AddRef,p) +#define ISimpleFrameSite_Release(p) ICOM_CALL (Release,p) +/*** IPropertyNotifySink methods ***/ +#define ISimpleFrameSite_PreMessageFilter(p,a,b,c,d,e,f) ICOM_CALL1(PreMessageFilter,p,a,b,c,d,e,f) +#define ISimpleFrameSite_PostMessageFilter(p,a,b,c,d,e,f) ICOM_CALL1(PostMessageFilter,p,a,b,c,d,e,f) + + +/***************************************************************************** + * IPersistStreamInit interface + */ +#define ICOM_INTERFACE IPersistStreamInit +#define IPersistStreamInit_METHODS \ + ICOM_METHOD (HRESULT,IsDirty) \ + ICOM_METHOD1(HRESULT,Load, LPSTREAM,pStm) \ + ICOM_METHOD2(HRESULT,Save, LPSTREAM,pStm, BOOL,fClearDirty) \ + ICOM_METHOD1(HRESULT,GetSizeMax, ULARGE_INTEGER*,pcbSize) \ + ICOM_METHOD (HRESULT,InitNew) +#define IPersistStreamInit_IMETHODS \ + IPersist_IMETHODS \ + IPersistStreamInit_METHODS +ICOM_DEFINE(IPersistStreamInit,IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistStreamInit_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistStreamInit_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistStreamInit_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistStreamInit_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistStreamInit methods ***/ +#define IPersistStreamInit_IsDirty(p) ICOM_CALL (IsDirty,p) +#define IPersistStreamInit_Load(p,a) ICOM_CALL1(Load,p,a) +#define IPersistStreamInit_Save(p,a,b) ICOM_CALL2(Save,p,a,b) +#define IPersistStreamInit_GetSizeMax(p,a) ICOM_CALL1(GetSizeMax,p,a) +#define IPersistStreamInit_InitNew(p) ICOM_CALL (InitNew,p) + + +/***************************************************************************** + * IPersistMemory interface + */ +#define ICOM_INTERFACE IPersistMemory +#define IPersistMemory_METHODS \ + ICOM_METHOD (HRESULT,IsDirty) \ + ICOM_METHOD2(HRESULT,Load, LPVOID,pMem, ULONG,cbSize) \ + ICOM_METHOD3(HRESULT,Save, LPVOID,pMem, BOOL,fClearDirty, ULONG,cbSize) \ + ICOM_METHOD1(HRESULT,GetSizeMax, ULONG*,pCbSize) \ + ICOM_METHOD (HRESULT,InitNew) +#define IPersistMemory_IMETHODS \ + IPersist_IMETHODS \ + IPersistMemory_METHODS +ICOM_DEFINE(IPersistMemory,IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistMemory_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistMemory_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistMemory_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistMemory_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistMemory methods ***/ +#define IPersistMemory_IsDirty(p) ICOM_CALL (IsDirty,p) +#define IPersistMemory_Load(p,a,b) ICOM_CALL2(Load,p,a,b) +#define IPersistMemory_Save(p,a,b,c) ICOM_CALL3(Save,p,a,b,c) +#define IPersistMemory_GetSizeMax(p,a) ICOM_CALL1(GetSizeMax,p,a) +#define IPersistMemory_InitNew(p) ICOM_CALL (InitNew,p) + + +/***************************************************************************** + * IPersistPropertyBag interface + */ +#define ICOM_INTERFACE IPersistPropertyBag +#define IPersistPropertyBag_METHODS \ + ICOM_METHOD (HRESULT,InitNew) \ + ICOM_METHOD2(HRESULT,Load, IPropertyBag*,pPropBag, IErrorLog*,pErrorLog) \ + ICOM_METHOD3(HRESULT,Save, IPropertyBag*,pPropBag, BOOL,fClearDirty, BOOL,fSaveAllProperties) +#define IPersistPropertyBag_IMETHODS \ + IPersist_IMETHODS \ + IPersistPropertyBag_METHODS +ICOM_DEFINE(IPersistPropertyBag,IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistPropertyBag_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistPropertyBag_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistPropertyBag_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistPropertyBag_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistPropertyBag methods ***/ +#define IPersistPropertyBag_InitNew(p) ICOM_CALL (InitNew,p) +#define IPersistPropertyBag_Load(p,a,b) ICOM_CALL2(Load,p,a,b) +#define IPersistPropertyBag_Save(p,a,b,c) ICOM_CALL3(Save,p,a,b,c) + + +/***************************************************************************** + * IErrorLog interface + */ +#define ICOM_INTERFACE IErrorLog +#define IErrorLog_METHODS \ + ICOM_METHOD2(HRESULT,AddError, LPCOLESTR,pszPropName, EXCEPINFO*,pExcepInfo) +#define IErrorLog_IMETHODS \ + IUnknown_IMETHODS \ + IErrorLog_METHODS +ICOM_DEFINE(IErrorLog,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IErrorLog_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IErrorLog_AddRef(p) ICOM_CALL (AddRef,p) +#define IErrorLog_Release(p) ICOM_CALL (Release,p) +/*** IErrorLog methods ***/ +#define IErrorLog_AddError(p,a,b) ICOM_CALL2(GetClassID,p,a,b) + + +/***************************************************************************** + * IPropertyBag interface + */ +#define ICOM_INTERFACE IPropertyBag +#define IPropertyBag_METHODS \ + ICOM_METHOD3(HRESULT,Read, LPCOLESTR,pszPropName, VARIANT*,pVar, IErrorLog*,pErrorLog) \ + ICOM_METHOD2(HRESULT,Write, LPCOLESTR,pszPropName, VARIANT*,pVar) +#define IPropertyBag_IMETHODS \ + IUnknown_IMETHODS \ + IPropertyBag_METHODS +ICOM_DEFINE(IPropertyBag,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertyBag_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertyBag_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertyBag_Release(p) ICOM_CALL (Release,p) +/*** IPropertyBag methods ***/ +#define IPropertyBag_Read(p,a,b,c) ICOM_CALL3(Read,p,a,b,c) +#define IPropertyBag_Write(p,a,b) ICOM_CALL2(Write,p,a,b) + + +/***************************************************************************** + * ISpecifyPropertyPages interface + */ +#define ICOM_INTERFACE ISpecifyPropertyPages +#define ISpecifyPropertyPages_METHODS \ + ICOM_METHOD1(HRESULT,GetPages, CAUUID*,pPages) +#define ISpecifyPropertyPages_IMETHODS \ + IUnknown_IMETHODS \ + ISpecifyPropertyPages_METHODS +ICOM_DEFINE(ISpecifyPropertyPages,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ISpecifyPropertyPages_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ISpecifyPropertyPages_AddRef(p) ICOM_CALL (AddRef,p) +#define ISpecifyPropertyPages_Release(p) ICOM_CALL (Release,p) +/*** ISpecifyPropertyPages methods ***/ +#define ISpecifyPropertyPages_GetPages(p,a) ICOM_CALL3(GetPages,p,a) + + +/***************************************************************************** + * IPerPropertyBrowsing interface + */ +#define ICOM_INTERFACE IPerPropertyBrowsing +#define IPerPropertyBrowsing_METHODS \ + ICOM_METHOD2(HRESULT,GetDisplayString, DISPID,dispID, BSTR*,pBstr) \ + ICOM_METHOD2(HRESULT,MapPropertyToPage, DISPID,dispID, CLSID*,pClsid) \ + ICOM_METHOD3(HRESULT,GetPredefinedStrings, DISPID,dispID, CALPOLESTR*,pCaStringsOut, CADWORD*,pCaCookiesOut) \ + ICOM_METHOD3(HRESULT,GetPredefinedValue, DISPID,dispID, DWORD,dwCookie, VARIANT*,pVarOut) +#define IPerPropertyBrowsing_IMETHODS \ + IUnknown_IMETHODS \ + IPerPropertyBrowsing_METHODS +ICOM_DEFINE(IPerPropertyBrowsing,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPerPropertyBrowsing_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPerPropertyBrowsing_AddRef(p) ICOM_CALL (AddRef,p) +#define IPerPropertyBrowsing_Release(p) ICOM_CALL (Release,p) +/*** IPerPropertyBrowsing methods ***/ +#define IPerPropertyBrowsing_GetDisplayString(p,a,b) ICOM_CALL2(GetDisplayString,p,a,b) +#define IPerPropertyBrowsing_MapPropertyToPage(p,a,b) ICOM_CALL2(MapPropertyToPage,p,a,b) +#define IPerPropertyBrowsing_GetPredefinedStrings(p,a,b,c) ICOM_CALL3(GetPredefinedStrings,p,a,b,c) +#define IPerPropertyBrowsing_GetPredefinedValue(p,a,b,c) ICOM_CALL3(GetPredefinedValue,p,a,b,c) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_PROPERTY_H */ + diff --git a/include/ole32/obj_propertystorage.h b/include/ole32/obj_propertystorage.h new file mode 100644 index 0000000..5236ff9 --- /dev/null +++ b/include/ole32/obj_propertystorage.h @@ -0,0 +1,438 @@ +/* + * Defines the COM interfaces and APIs related to saving properties to file. + */ + +#ifndef __WINE_WINE_OBJ_PROPERTYSTORAGE_H +#define __WINE_WINE_OBJ_PROPERTYSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IEnumSTATPROPSETSTG, 0x0000013bL, 0, 0); +typedef struct IEnumSTATPROPSETSTG IEnumSTATPROPSETSTG,*LPENUMSTATPROPSETSTG; + +DEFINE_OLEGUID(IID_IEnumSTATPROPSTG, 0x00000139L, 0, 0); +typedef struct IEnumSTATPROPSTG IEnumSTATPROPSTG,*LPENUMSTATPROPSTG; + +DEFINE_OLEGUID(IID_IPropertySetStorage, 0x0000013aL, 0, 0); +typedef struct IPropertySetStorage IPropertySetStorage,*LPPROPERTYSETSTORAGE; + +DEFINE_OLEGUID(IID_IPropertyStorage, 0x00000138L, 0, 0); +typedef struct IPropertyStorage IPropertyStorage,*LPPROPERTYSTORAGE; + + +/***************************************************************************** + * Predeclare the structures + */ + +typedef struct tagSTATPROPSETSTG STATPROPSETSTG; +typedef struct tagSTATPROPSTG STATPROPSTG; + +extern const FMTID FMTID_SummaryInformation; +extern const FMTID FMTID_DocSummaryInformation; +extern const FMTID FMTID_UserDefinedProperties; + +/***************************************************************************** + * PROPSPEC structure + */ + +/* Reserved global Property IDs */ +#define PID_DICTIONARY ( 0 ) + +#define PID_CODEPAGE ( 0x1 ) + +#define PID_FIRST_USABLE ( 0x2 ) + +#define PID_FIRST_NAME_DEFAULT ( 0xfff ) + +#define PID_LOCALE ( 0x80000000 ) + +#define PID_MODIFY_TIME ( 0x80000001 ) + +#define PID_SECURITY ( 0x80000002 ) + +#define PID_ILLEGAL ( 0xffffffff ) + +/* Property IDs for the SummaryInformation Property Set */ + +#define PIDSI_TITLE 0x00000002L /* VT_LPSTR */ +#define PIDSI_SUBJECT 0x00000003L /* VT_LPSTR */ +#define PIDSI_AUTHOR 0x00000004L /* VT_LPSTR */ +#define PIDSI_KEYWORDS 0x00000005L /* VT_LPSTR */ +#define PIDSI_COMMENTS 0x00000006L /* VT_LPSTR */ +#define PIDSI_TEMPLATE 0x00000007L /* VT_LPSTR */ +#define PIDSI_LASTAUTHOR 0x00000008L /* VT_LPSTR */ +#define PIDSI_REVNUMBER 0x00000009L /* VT_LPSTR */ +#define PIDSI_EDITTIME 0x0000000aL /* VT_FILETIME (UTC) */ +#define PIDSI_LASTPRINTED 0x0000000bL /* VT_FILETIME (UTC) */ +#define PIDSI_CREATE_DTM 0x0000000cL /* VT_FILETIME (UTC) */ +#define PIDSI_LASTSAVE_DTM 0x0000000dL /* VT_FILETIME (UTC) */ +#define PIDSI_PAGECOUNT 0x0000000eL /* VT_I4 */ +#define PIDSI_WORDCOUNT 0x0000000fL /* VT_I4 */ +#define PIDSI_CHARCOUNT 0x00000010L /* VT_I4 */ +#define PIDSI_THUMBNAIL 0x00000011L /* VT_CF */ +#define PIDSI_APPNAME 0x00000012L /* VT_LPSTR */ +#define PIDSI_DOC_SECURITY 0x00000013L /* VT_I4 */ +#define PRSPEC_INVALID ( 0xffffffff ) + + +#define PRSPEC_LPWSTR ( 0 ) +#define PRSPEC_PROPID ( 1 ) + +typedef struct tagPROPSPEC +{ + ULONG ulKind; + union + { + PROPID propid; + LPOLESTR lpwstr; + } u; +} PROPSPEC; + + +/***************************************************************************** + * STATPROPSETSTG structure + */ +/* Macros for parsing the OS Version of the Property Set Header */ +#define PROPSETHDR_OSVER_KIND(dwOSVer) HIWORD( (dwOSVer) ) +#define PROPSETHDR_OSVER_MAJOR(dwOSVer) LOBYTE(LOWORD( (dwOSVer) )) +#define PROPSETHDR_OSVER_MINOR(dwOSVer) HIBYTE(LOWORD( (dwOSVer) )) +#define PROPSETHDR_OSVERSION_UNKNOWN 0xFFFFFFFF + +struct tagSTATPROPSETSTG +{ + FMTID fmtid; + CLSID clsid; + DWORD grfFlags; + FILETIME mtime; + FILETIME ctime; + FILETIME atime; + DWORD dwOSVersion; +}; + + +/***************************************************************************** + * STATPROPSTG structure + */ +struct tagSTATPROPSTG +{ + LPOLESTR lpwstrName; + PROPID propid; + VARTYPE vt; +}; + + +/***************************************************************************** + * IEnumSTATPROPSETSTG interface + */ +#define ICOM_INTERFACE IEnumSTATPROPSETSTG +#define IEnumSTATPROPSETSTG_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, STATPROPSETSTG*,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumSTATPROPSETSTG**,ppenum) +#define IEnumSTATPROPSETSTG_IMETHODS \ + IUnknown_IMETHODS \ + IEnumSTATPROPSETSTG_METHODS +ICOM_DEFINE(IEnumSTATPROPSETSTG,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumSTATPROPSETSTG_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumSTATPROPSETSTG_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumSTATPROPSETSTG_Release(p) ICOM_CALL (Release,p) +/*** IEnumSTATPROPSETSTG methods ***/ +#define IEnumSTATPROPSETSTG_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumSTATPROPSETSTG_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumSTATPROPSETSTG_Reset(p) ICOM_CALL (Reset,p) +#define IEnumSTATPROPSETSTG_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * IEnumSTATPROPSTG interface + */ +#define ICOM_INTERFACE IEnumSTATPROPSTG +#define IEnumSTATPROPSTG_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, STATPROPSTG*,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumSTATPROPSTG**,ppenum) +#define IEnumSTATPROPSTG_IMETHODS \ + IUnknown_IMETHODS \ + IEnumSTATPROPSTG_METHODS +ICOM_DEFINE(IEnumSTATPROPSTG,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumSTATPROPSTG_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumSTATPROPSTG_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumSTATPROPSTG_Release(p) ICOM_CALL (Release,p) +/*** IEnumSTATPROPSTG methods ***/ +#define IEnumSTATPROPSTG_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumSTATPROPSTG_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumSTATPROPSTG_Reset(p) ICOM_CALL (Reset,p) +#define IEnumSTATPROPSTG_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * IPropertySetStorage interface + */ +#define ICOM_INTERFACE IPropertySetStorage +#define IPropertySetStorage_METHODS \ + ICOM_METHOD5(HRESULT,Create, REFFMTID,rfmtid, const CLSID*,pclsid, DWORD,grfFlags, DWORD,grfMode, IPropertyStorage**,ppprstg) \ + ICOM_METHOD3(HRESULT,Open, REFFMTID,rfmtid, DWORD,grfMode, IPropertyStorage**,ppprstg) \ + ICOM_METHOD1(HRESULT,Delete, REFFMTID,rfmtid) \ + ICOM_METHOD1(HRESULT,Enum, IEnumSTATPROPSETSTG**,ppenum) +#define IPropertySetStorage_IMETHODS \ + IUnknown_IMETHODS \ + IPropertySetStorage_METHODS +ICOM_DEFINE(IPropertySetStorage,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertySetStorage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertySetStorage_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertySetStorage_Release(p) ICOM_CALL (Release,p) +/*** IPropertySetStorage methods ***/ +#define IPropertySetStorage_Create(p,a,b,c,d,e) ICOM_CALL5(Create,p,a,b,c,d,e) +#define IPropertySetStorage_Open(p,a,b,c) ICOM_CALL3(Open,p,a,b,c) +#define IPropertySetStorage_Delete(p,a) ICOM_CALL1(Delete,p,a) +#define IPropertySetStorage_Enum(p,a) ICOM_CALL1(Enum,p,a) + + +/***************************************************************************** + * IPropertyStorage interface + */ +typedef struct tagPROPVARIANT PROPVARIANT,*LPPROPVARIANT; + +/* Flags for IPropertySetStorage::Create */ +#define PROPSETFLAG_DEFAULT ( 0 ) +#define PROPSETFLAG_NONSIMPLE ( 1 ) +#define PROPSETFLAG_ANSI ( 2 ) + +typedef struct tagCAUB +{ + ULONG cElems; + unsigned char *pElems; +} CAUB; + +typedef struct tagCAI +{ + ULONG cElems; + short *pElems; +} CAI; + +typedef struct tagCAUI +{ + ULONG cElems; + USHORT *pElems; +} CAUI; + +typedef struct tagCAL +{ + ULONG cElems; + long *pElems; +} CAL; + +typedef struct tagCAUL +{ + ULONG cElems; + ULONG *pElems; +} CAUL; + +typedef struct tagCAFLT +{ + ULONG cElems; + float *pElems; +} CAFLT; + +typedef struct tagCADBL +{ + ULONG cElems; + double *pElems; +} CADBL; + +typedef struct tagCACY +{ + ULONG cElems; + CY *pElems; +} CACY; + +typedef struct tagCADATE +{ + ULONG cElems; + DATE *pElems; +} CADATE; + +typedef struct tagCABSTR +{ + ULONG cElems; + BSTR *pElems; +} CABSTR; + +typedef struct tagCABOOL +{ + ULONG cElems; + VARIANT_BOOL *pElems; +} CABOOL; + +typedef struct tagCASCODE +{ + ULONG cElems; + SCODE *pElems; +} CASCODE; + +typedef struct tagCAPROPVARIANT +{ + ULONG cElems; + PROPVARIANT *pElems; +} CAPROPVARIANT; + +typedef struct tagCAH +{ + ULONG cElems; + LARGE_INTEGER *pElems; +} CAH; + +typedef struct tagCAUH +{ + ULONG cElems; + ULARGE_INTEGER *pElems; +} CAUH; + +typedef struct tagCALPSTR +{ + ULONG cElems; + LPSTR *pElems; +} CALPSTR; + +typedef struct tagCALPWSTR +{ + ULONG cElems; + LPWSTR *pElems; +} CALPWSTR; + +typedef struct tagCAFILETIME +{ + ULONG cElems; + FILETIME *pElems; +} CAFILETIME; + +typedef struct tagCACLIPDATA +{ + ULONG cElems; + CLIPDATA *pElems; +} CACLIPDATA; + +typedef struct tagCACLSID +{ + ULONG cElems; + CLSID *pElems; +} CACLSID; + +struct tagPROPVARIANT +{ + VARTYPE vt; + WORD wReserved1; + WORD wReserved2; + WORD wReserved3; + union + { + /* Empty union arm */ + UCHAR bVal; + short iVal; + USHORT uiVal; + VARIANT_BOOL boolVal; +#ifndef __cplusplus + /* FIXME: bool is reserved in C++, how can we deal with that ? */ + _VARIANT_BOOL bool; +#endif + long lVal; + ULONG ulVal; + float fltVal; + SCODE scode; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + double dblVal; + CY cyVal; + DATE date; + FILETIME filetime; + CLSID *puuid; + BLOB blob; + CLIPDATA *pclipdata; + IStream *pStream; + IStorage *pStorage; + BSTR bstrVal; + LPSTR pszVal; + LPWSTR pwszVal; + CAUB caub; + CAI cai; + CAUI caui; + CABOOL cabool; + CAL cal; + CAUL caul; + CAFLT caflt; + CASCODE cascode; + CAH cah; + CAUH cauh; + CADBL cadbl; + CACY cacy; + CADATE cadate; + CAFILETIME cafiletime; + CACLSID cauuid; + CACLIPDATA caclipdata; + CABSTR cabstr; + CALPSTR calpstr; + CALPWSTR calpwstr; + CAPROPVARIANT capropvar; + } u; +}; + + +#define ICOM_INTERFACE IPropertyStorage +#define IPropertyStorage_METHODS \ + ICOM_METHOD3(HRESULT,ReadMultiple, ULONG,cpspec, const PROPSPEC*,rgpspec, PROPVARIANT*,rgpropvar) \ + ICOM_METHOD4(HRESULT,WriteMultiple, ULONG,cpspec, const PROPSPEC*,rgpspec, const PROPVARIANT*,rgpropvar, PROPID,propidNameFirst) \ + ICOM_METHOD2(HRESULT,DeleteMultiple, ULONG,cpspec, const PROPSPEC*,rgpspec) \ + ICOM_METHOD2(HRESULT,ReadPropertyNames, const PROPID*,rgpropid, LPOLESTR*,rglpwstrName) \ + ICOM_METHOD3(HRESULT,WritePropertyNames, ULONG,cpropid, const PROPID*,rgpropid, LPOLESTR*,rglpwstrName) \ + ICOM_METHOD2(HRESULT,DeletePropertyNames, ULONG,cpropid, const PROPID*,rgpropid) \ + ICOM_METHOD1(HRESULT,Commit, DWORD,grfCommitFlags) \ + ICOM_METHOD (HRESULT,Revert) \ + ICOM_METHOD1(HRESULT,Enum, IEnumSTATPROPSTG**,ppenum) \ + ICOM_METHOD3(HRESULT,SetTimes, const FILETIME*,pctime, const FILETIME*,patime, const FILETIME*,pmtime) \ + ICOM_METHOD1(HRESULT,SetClass, REFCLSID,clsid) \ + ICOM_METHOD1(HRESULT,Stat, STATPROPSETSTG*,pstatpsstg) +#define IPropertyStorage_IMETHODS \ + IUnknown_IMETHODS \ + IPropertyStorage_METHODS +ICOM_DEFINE(IPropertyStorage,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPropertyStorage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPropertyStorage_AddRef(p) ICOM_CALL (AddRef,p) +#define IPropertyStorage_Release(p) ICOM_CALL (Release,p) +/*** IPropertyStorage methods ***/ +#define IPropertyStorage_ReadMultiple(p,a,b,c) ICOM_CALL3(ReadMultiple,p,a,b,c) +#define IPropertyStorage_WriteMultiple(p,a,b,c,d) ICOM_CALL4(WriteMultiple,p,a,b,c,d) +#define IPropertyStorage_DeleteMultiple(p,a,b) ICOM_CALL2(DeleteMultiple,p,a,b) +#define IPropertyStorage_ReadPropertyNames(p,a,b) ICOM_CALL2(ReadPropertyNames,p,a,b) +#define IPropertyStorage_WritePropertyNames(p,a,b,c) ICOM_CALL3(WritePropertyNames,p,a,b,c) +#define IPropertyStorage_DeletePropertyNames(p,a,b) ICOM_CALL2(DeletePropertyNames,p,a,b) +#define IPropertyStorage_Commit(p,a) ICOM_CALL1(Commit,p,a) +#define IPropertyStorage_Revert(p) ICOM_CALL (Revert,p) +#define IPropertyStorage_Enum(p,a) ICOM_CALL1(Enum,p,a) +#define IPropertyStorage_SetTimes(p,a,b,c) ICOM_CALL3(SetTimes,p,a,b,c) +#define IPropertyStorage_SetClass(p,a) ICOM_CALL1(SetClass,p,a) +#define IPropertyStorage_Stat(p,a) ICOM_CALL1(Stat,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_PROPERTYSTORAGE_H */ diff --git a/include/ole32/obj_queryassociations.h b/include/ole32/obj_queryassociations.h new file mode 100644 index 0000000..257d9f2 --- /dev/null +++ b/include/ole32/obj_queryassociations.h @@ -0,0 +1,94 @@ +/************************************************************ + * IQueryAssociations + */ + +#ifndef __WINE_WINE_OBJ_QUERYASSOCIATIONS_H +#define __WINE_WINE_OBJ_QUERYASSOCIATIONS_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +DEFINE_GUID(IID_IQueryAssociations, 0xc46ca590, 0x3c3f, 0x11d2, 0xbe, 0xe6, 0x00, 0x00, 0xf8, 0x05, 0xca, 0x57); + +typedef struct IQueryAssociations IQueryAssociations,*LPQUERYASSOCIATIONS; + +#define ASSOCF_INIT_BYEXENAME 0x00000002 +#define ASSOCF_OPEN_BYEXENAME 0x00000002 +#define ASSOCF_INIT_DEFAULTTOSTAR 0x00000004 +#define ASSOCF_INIT_DEFAULTTOFOLDER 0x00000008 +#define ASSOCF_NOUSERSETTINGS 0x00000010 +#define ASSOCF_NOTRUNCATE 0x00000020 +#define ASSOCF_VERIFY 0x00000040 +#define ASSOCF_REMAPRUNDLL 0x00000080 +#define ASSOCF_NOFIXUPS 0x00000100 +#define ASSOCF_IGNOREBASECLASS 0x00000200 + +typedef DWORD ASSOCF; + +typedef enum +{ + ASSOCSTR_COMMAND = 1, + ASSOCSTR_EXECUTABLE, + ASSOCSTR_FRIENDLYDOCNAME, + ASSOCSTR_FRIENDLYAPPNAME, + ASSOCSTR_NOOPEN, + ASSOCSTR_SHELLNEWVALUE, + ASSOCSTR_DDECOMMAND, + ASSOCSTR_DDEIFEXEC, + ASSOCSTR_DDEAPPLICATION, + ASSOCSTR_DDETOPIC, + ASSOCSTR_MAX +} ASSOCSTR; + +typedef enum +{ + ASSOCKEY_SHELLEXECCLASS = 1, + ASSOCKEY_APP, + ASSOCKEY_CLASS, + ASSOCKEY_BASECLASS, + ASSOCKEY_MAX +} ASSOCKEY; + +typedef enum +{ + ASSOCDATA_MSIDESCRIPTOR = 1, + ASSOCDATA_NOACTIVATEHANDLER, + ASSOCDATA_QUERYCLASSSTORE, + ASSOCDATA_HASPERUSERASSOC, + ASSOCDATA_MAX +} ASSOCDATA; + +typedef enum +{ + ASSOCENUM_NONE +} ASSOCENUM; + +#define ICOM_INTERFACE IQueryAssociations +#define IQueryAssociations_METHODS \ + ICOM_METHOD4 (HRESULT, Init, ASSOCF, flags, LPCWSTR, pszAssoc, HKEY, hkProgid, HWND, hwnd) \ + ICOM_METHOD5 (HRESULT, GetString, ASSOCF, flags, ASSOCSTR, str, LPCWSTR, pszExtra, LPWSTR, pszOut, DWORD*, pcchOut) \ + ICOM_METHOD4 (HRESULT, GetKey, ASSOCF, flags, ASSOCKEY, key, LPCWSTR, pszExtra, HKEY*, phkeyOut) \ + ICOM_METHOD5 (HRESULT, GetData, ASSOCF, flags, ASSOCDATA, data, LPCWSTR, pszExtra, LPVOID, pvOut, DWORD*, pcbOut) \ + ICOM_METHOD5 (HRESULT, GetEnum, ASSOCF, flags, ASSOCENUM, assocenum, LPCWSTR, pszExtra, REFIID, riid, LPVOID*, ppvOut) +#define IQueryAssociations_IMETHODS \ + IUnknown_IMETHODS \ + IQueryAssociations_METHODS +ICOM_DEFINE(IQueryAssociations,IUnknown) +#undef ICOM_INTERFACE + +#define IQueryAssociations_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IQueryAssociations_AddRef(p) ICOM_CALL(AddRef,p) +#define IQueryAssociations_Release(p) ICOM_CALL(Release,p) +#define IQueryAssociations_Init(p,a,b,c,d) ICOM_CALL4(Init,p,a,b,c,d) +#define IQueryAssociations_GetString(p,a,b,c,d,e) ICOM_CALL5(GetString,p,a,b,c,d,e) +#define IQueryAssociations_GetKey(p,a,b,c,d) ICOM_CALL4(GetKey,p,a,b,c,d) +#define IQueryAssociations_GetData(p,a,b,c,d,e) ICOM_CALL5(GetData,p,a,b,c,d,e) +#define IQueryAssociations_GetEnum(p,a,b,c,d,e) ICOM_CALL5(GetEnum,p,a,b,c,d,e) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_QUERYASSOCIATIONS_H */ + diff --git a/include/ole32/obj_serviceprovider.h b/include/ole32/obj_serviceprovider.h new file mode 100644 index 0000000..0aef481 --- /dev/null +++ b/include/ole32/obj_serviceprovider.h @@ -0,0 +1,47 @@ +/* + * Defines the COM interfaces and APIs related to IServiceProvider + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_SERVICEPROVIDER_H +#define __WINE_WINE_OBJ_SERVICEPROVIDER_H + +#include "wine/obj_base.h" +#include "winbase.h" + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_IServiceProvider, 0x6d5140c1, 0x7436, 0x11ce, 0x80, 0x34, 0x00, 0xaa, 0x00, 0x60, 0x09, 0xfa); +typedef struct IServiceProvider IServiceProvider, *LPSERVICEPROVIDER; + + +/***************************************************************************** + * IServiceProvider interface + */ +#define ICOM_INTERFACE IServiceProvider +#define IServiceProvider_METHODS \ + ICOM_METHOD3( HRESULT, QueryService, REFGUID, guidService, REFIID, riid, void**, ppv) +#define IServiceProvider_IMETHODS \ + IUnknown_IMETHODS \ + IServiceProvider_METHODS +ICOM_DEFINE(IServiceProvider,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IServiceProvider_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IServiceProvider_AddRef(p) ICOM_CALL (AddRef,p) +#define IServiceProvider_Release(p) ICOM_CALL (Release,p) +/*** IServiceProvider methods ***/ +#define IServiceProvider_QueryService(p,a,b,c) ICOM_CALL3(QueryService,p,a,b,c) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_SERVICEPROVIDER_H */ diff --git a/include/ole32/obj_shellbrowser.h b/include/ole32/obj_shellbrowser.h new file mode 100644 index 0000000..d3f902f --- /dev/null +++ b/include/ole32/obj_shellbrowser.h @@ -0,0 +1,99 @@ +/************************************************************ + * IShellBrowser + */ + +#ifndef __WINE_WINE_OBJ_SHELLBROWSER_H +#define __WINE_WINE_OBJ_SHELLBROWSER_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/* it's ok commented out, see obj_shellview.h + typedef struct IShellBrowser IShellBrowser, *LPSHELLBROWSER; +*/ + +#define SID_SShellBrowser IID_IShellBrowser + +DEFINE_GUID(SID_STopLevelBrowser, 0x4C96BE40L, 0x915C, 0x11CF, 0x99, 0xD3, 0x00, 0xAA, 0x00, 0x4A, 0xE8, 0x37); + +/* targets for GetWindow/SendControlMsg */ +#define FCW_STATUS 0x0001 +#define FCW_TOOLBAR 0x0002 +#define FCW_TREE 0x0003 +#define FCW_INTERNETBAR 0x0006 +#define FCW_PROGRESS 0x0008 + +/* wFlags for BrowseObject*/ +#define SBSP_DEFBROWSER 0x0000 +#define SBSP_SAMEBROWSER 0x0001 +#define SBSP_NEWBROWSER 0x0002 + +#define SBSP_DEFMODE 0x0000 +#define SBSP_OPENMODE 0x0010 +#define SBSP_EXPLOREMODE 0x0020 + +#define SBSP_ABSOLUTE 0x0000 +#define SBSP_RELATIVE 0x1000 +#define SBSP_PARENT 0x2000 +#define SBSP_NAVIGATEBACK 0x4000 +#define SBSP_NAVIGATEFORWARD 0x8000 + +#define SBSP_ALLOW_AUTONAVIGATE 0x10000 + +#define SBSP_INITIATEDBYHLINKFRAME 0x80000000 +#define SBSP_REDIRECT 0x40000000 +#define SBSP_WRITENOHISTORY 0x08000000 + +/* uFlage for SetToolbarItems */ +#define FCT_MERGE 0x0001 +#define FCT_CONFIGABLE 0x0002 +#define FCT_ADDTOEND 0x0004 + +#define ICOM_INTERFACE IShellBrowser +#define IShellBrowser_METHODS \ + ICOM_METHOD2(HRESULT, InsertMenusSB, HMENU, hmenuShared, LPOLEMENUGROUPWIDTHS, lpMenuWidths) \ + ICOM_METHOD3(HRESULT, SetMenuSB, HMENU, hmenuShared, HOLEMENU, holemenuReserved, HWND, hwndActiveObject) \ + ICOM_METHOD1(HRESULT, RemoveMenusSB, HMENU, hmenuShared) \ + ICOM_METHOD1(HRESULT, SetStatusTextSB, LPCOLESTR, lpszStatusText) \ + ICOM_METHOD1(HRESULT, EnableModelessSB, BOOL, fEnable) \ + ICOM_METHOD2(HRESULT, TranslateAcceleratorSB, LPMSG, lpmsg, WORD, wID) \ + ICOM_METHOD2(HRESULT, BrowseObject, LPCITEMIDLIST, pidl, UINT, wFlags) \ + ICOM_METHOD2(HRESULT, GetViewStateStream, DWORD, grfMode, LPSTREAM*, ppStrm) \ + ICOM_METHOD2(HRESULT, GetControlWindow, UINT, id, HWND*, lphwnd) \ + ICOM_METHOD5(HRESULT, SendControlMsg, UINT, id, UINT, uMsg, WPARAM, wParam, LPARAM, lParam, LRESULT*, pret) \ + ICOM_METHOD1(HRESULT, QueryActiveShellView, IShellView**, IShellView) \ + ICOM_METHOD1(HRESULT, OnViewWindowActive, IShellView*, IShellView) \ + ICOM_METHOD3(HRESULT, SetToolbarItems, LPTBBUTTON, lpButtons, UINT, nButtons, UINT, uFlags) +#define IShellBrowser_IMETHODS \ + IOleWindow_IMETHODS \ + IShellBrowser_METHODS +ICOM_DEFINE(IShellBrowser,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellBrowser_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellBrowser_AddRef(p) ICOM_CALL(AddRef,p) +#define IShellBrowser_Release(p) ICOM_CALL(Release,p) +/*** IShellBrowser methods ***/ +#define IShellBrowser_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IShellBrowser_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +#define IShellBrowser_InsertMenusSB(p,a,b) ICOM_CALL2(InsertMenusSB,p,a,b) +#define IShellBrowser_SetMenuSB(p,a,b,c) ICOM_CALL3(SetMenuSB,p,a,b,c) +#define IShellBrowser_RemoveMenusSB(p,a) ICOM_CALL1(RemoveMenusSB,p,a) +#define IShellBrowser_SetStatusTextSB(p,a) ICOM_CALL1(SetStatusTextSB,p,a) +#define IShellBrowser_EnableModelessSB(p,a) ICOM_CALL1(EnableModelessSB,p,a) +#define IShellBrowser_TranslateAcceleratorSB(p,a,b) ICOM_CALL2(TranslateAcceleratorSB,p,a,b) +#define IShellBrowser_BrowseObject(p,a,b) ICOM_CALL2(BrowseObject,p,a,b) +#define IShellBrowser_GetViewStateStream(p,a,b) ICOM_CALL2(GetViewStateStream,p,a,b) +#define IShellBrowser_GetControlWindow(p,a,b) ICOM_CALL2(GetControlWindow,p,a,b) +#define IShellBrowser_SendControlMsg(p,a,b,c,d,e) ICOM_CALL5(SendControlMsg,p,a,b,c,d,e) +#define IShellBrowser_QueryActiveShellView(p,a) ICOM_CALL1(QueryActiveShellView,p,a) +#define IShellBrowser_OnViewWindowActive(p,a) ICOM_CALL1(OnViewWindowActive,p,a) +#define IShellBrowser_SetToolbarItems(p,a,b,c) ICOM_CALL3(SetToolbarItems,p,a,b,c) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_SHELLBROWSER_H */ diff --git a/include/ole32/obj_shellextinit.h b/include/ole32/obj_shellextinit.h new file mode 100644 index 0000000..3bac3a1 --- /dev/null +++ b/include/ole32/obj_shellextinit.h @@ -0,0 +1,34 @@ +/************************************************************ + * IShellExtInit + */ + +#ifndef __WINE_WINE_OBJ_SHELLEXTINIT_H +#define __WINE_WINE_OBJ_SHELLEXTINIT_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +typedef struct IShellExtInit IShellExtInit, *LPSHELLEXTINIT; + +#define ICOM_INTERFACE IShellExtInit +#define IShellExtInit_METHODS \ + ICOM_METHOD3(HRESULT, Initialize, LPCITEMIDLIST, pidlFolder, LPDATAOBJECT, lpdobj, HKEY, hkeyProgID) +#define IShellExtInit_IMETHODS \ + IUnknown_IMETHODS \ + IShellExtInit_METHODS +ICOM_DEFINE(IShellExtInit,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellExtInit_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellExtInit_AddRef(p) ICOM_CALL(AddRef,p) +#define IShellExtInit_Release(p) ICOM_CALL(Release,p) +/*** IShellExtInit methods ***/ +#define IShellExtInit_Initialize(p,a,b,c) ICOM_CALL3(Initialize,p,a,b,c) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_SHELLEXTINIT_H */ diff --git a/include/ole32/obj_shellfolder.h b/include/ole32/obj_shellfolder.h new file mode 100644 index 0000000..0a25403 --- /dev/null +++ b/include/ole32/obj_shellfolder.h @@ -0,0 +1,356 @@ +/* + * Defines the COM interfaces and APIs related to IShellFolder + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_SHELLFOLDER_H +#define __WINE_WINE_OBJ_SHELLFOLDER_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/**************************************************************************** +* STRRET +*/ +#define STRRET_WSTR 0x0000 +#define STRRET_ASTR 0x0003 + +#define STRRET_OFFSETA 0x0001 +#define STRRET_OFFSETW 0x0004 +#define STRRET_OFFSET WINELIB_NAME_AW(STRRET_OFFSET) + +#define STRRET_CSTRA 0x0002 +#define STRRET_CSTRW 0x0005 +#define STRRET_CSTR WINELIB_NAME_AW(STRRET_CSTR) + +typedef struct _STRRET +{ UINT uType; /* STRRET_xxx */ + union + { LPWSTR pOleStr; /* OLESTR that will be freed */ + LPSTR pStr; + UINT uOffset; /* OffsetINT32o SHITEMID (ANSI) */ + char cStr[MAX_PATH]; /* Buffer to fill in */ + WCHAR cStrW[MAX_PATH]; + } DUMMYUNIONNAME; +} STRRET,*LPSTRRET; + +/***************************************************************************** + * Predeclare the interfaces + */ +typedef struct IShellFolder IShellFolder, *LPSHELLFOLDER; + +typedef struct IPersistFolder IPersistFolder, *LPPERSISTFOLDER; + +DEFINE_GUID(IID_IPersistFolder2, 0x1ac3d9f0L, 0x175C, 0x11D1, 0x95, 0xBE, 0x00, 0x60, 0x97, 0x97, 0xEA, 0x4F); +typedef struct IPersistFolder2 IPersistFolder2, *LPPERSISTFOLDER2; + +DEFINE_GUID(IID_IShellFolder2, 0xB82C5AA8, 0xA41B, 0x11D2, 0xBE, 0x32, 0x0, 0xc0, 0x4F, 0xB9, 0x36, 0x61); +typedef struct IShellFolder2 IShellFolder2, *LPSHELLFOLDER2; + +DEFINE_GUID(IID_IEnumExtraSearch, 0xE700BE1, 0x9DB6, 0x11D1, 0xA1, 0xCE, 0x0, 0xc0, 0x4F, 0xD7, 0x5D, 0x13); +typedef struct IEnumExtraSearch IEnumExtraSearch, *LPENUMEXTRASEARCH; + +/***************************************************************************** + * IEnumExtraSearch interface + */ + +typedef struct +{ + GUID guidSearch; + WCHAR wszFriendlyName[80]; + WCHAR wszMenuText[80]; + WCHAR wszHelpText[MAX_PATH]; + WCHAR wszUrl[2084]; + WCHAR wszIcon[MAX_PATH+10]; + WCHAR wszGreyIcon[MAX_PATH+10]; + WCHAR wszClrIcon[MAX_PATH+10]; +} EXTRASEARCH,* LPEXTRASEARCH; + +#define ICOM_INTERFACE IEnumExtraSearch +#define IEnumExtraSearch_METHODS \ + ICOM_METHOD3(HRESULT, Next, ULONG, celt, LPEXTRASEARCH*, rgelt, ULONG*, pceltFetched) \ + ICOM_METHOD1(HRESULT, Skip, ULONG, celt) \ + ICOM_METHOD (HRESULT, Reset) \ + ICOM_METHOD1(HRESULT, Clone, IEnumExtraSearch**, ppenum) +#define IEnumExtraSearch_IMETHODS \ + IUnknown_IMETHODS \ + IEnumExtraSearch_METHODS +ICOM_DEFINE(IEnumExtraSearch,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumIDList_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumIDList_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumIDList_Release(p) ICOM_CALL (Release,p) +/*** IEnumIDList methods ***/ +#define IEnumIDList_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumIDList_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumIDList_Reset(p) ICOM_CALL(Reset,p) +#define IEnumIDList_Clone(p,a) ICOM_CALL1(Clone,p,a) + +/***************************************************************************** + * IShellFolder::GetDisplayNameOf/SetNameOf uFlags + */ +typedef enum +{ SHGDN_NORMAL = 0, /* default (display purpose) */ + SHGDN_INFOLDER = 1, /* displayed under a folder (relative)*/ + SHGDN_FORPARSING = 0x8000 /* for ParseDisplayName or path */ +} SHGNO; + +/***************************************************************************** + * IShellFolder::EnumObjects + */ +typedef enum tagSHCONTF +{ SHCONTF_FOLDERS = 32, /* for shell browser */ + SHCONTF_NONFOLDERS = 64, /* for default view */ + SHCONTF_INCLUDEHIDDEN = 128 /* for hidden/system objects */ +} SHCONTF; + +/***************************************************************************** + * IShellFolder::GetAttributesOf flags + */ +#define SFGAO_CANCOPY DROPEFFECT_COPY /* Objects can be copied */ +#define SFGAO_CANMOVE DROPEFFECT_MOVE /* Objects can be moved */ +#define SFGAO_CANLINK DROPEFFECT_LINK /* Objects can be linked */ +#define SFGAO_CANRENAME 0x00000010L /* Objects can be renamed */ +#define SFGAO_CANDELETE 0x00000020L /* Objects can be deleted */ +#define SFGAO_HASPROPSHEET 0x00000040L /* Objects have property sheets */ +#define SFGAO_DROPTARGET 0x00000100L /* Objects are drop target */ +#define SFGAO_CAPABILITYMASK 0x00000177L +#define SFGAO_LINK 0x00010000L /* Shortcut (link) */ +#define SFGAO_SHARE 0x00020000L /* shared */ +#define SFGAO_READONLY 0x00040000L /* read-only */ +#define SFGAO_GHOSTED 0x00080000L /* ghosted icon */ +#define SFGAO_HIDDEN 0x00080000L /* hidden object */ +#define SFGAO_DISPLAYATTRMASK 0x000F0000L +#define SFGAO_FILESYSANCESTOR 0x10000000L /* It contains file system folder */ +#define SFGAO_FOLDER 0x20000000L /* It's a folder. */ +#define SFGAO_FILESYSTEM 0x40000000L /* is a file system thing (file/folder/root) */ +#define SFGAO_HASSUBFOLDER 0x80000000L /* Expandable in the map pane */ +#define SFGAO_CONTENTSMASK 0x80000000L +#define SFGAO_VALIDATE 0x01000000L /* invalidate cached information */ +#define SFGAO_REMOVABLE 0x02000000L /* is this removeable media? */ +#define SFGAO_BROWSABLE 0x08000000L /* is in-place browsable */ +#define SFGAO_NONENUMERATED 0x00100000L /* is a non-enumerated object */ +#define SFGAO_NEWCONTENT 0x00200000L /* should show bold in explorer tree */ + +/************************************************************************ + * + * FOLDERSETTINGS +*/ + +typedef LPBYTE LPVIEWSETTINGS; + +/* NB Bitfields. */ +/* FWF_DESKTOP implies FWF_TRANSPARENT/NOCLIENTEDGE/NOSCROLL */ +typedef enum +{ FWF_AUTOARRANGE = 0x0001, + FWF_ABBREVIATEDNAMES = 0x0002, + FWF_SNAPTOGRID = 0x0004, + FWF_OWNERDATA = 0x0008, + FWF_BESTFITWINDOW = 0x0010, + FWF_DESKTOP = 0x0020, + FWF_SINGLESEL = 0x0040, + FWF_NOSUBFOLDERS = 0x0080, + FWF_TRANSPARENT = 0x0100, + FWF_NOCLIENTEDGE = 0x0200, + FWF_NOSCROLL = 0x0400, + FWF_ALIGNLEFT = 0x0800, + FWF_SINGLECLICKACTIVATE=0x8000 /* TEMPORARY -- NO UI FOR THIS */ +} FOLDERFLAGS; + +typedef enum +{ FVM_ICON = 1, + FVM_SMALLICON = 2, + FVM_LIST = 3, + FVM_DETAILS = 4 +} FOLDERVIEWMODE; + +typedef struct +{ UINT ViewMode; /* View mode (FOLDERVIEWMODE values) */ + UINT fFlags; /* View options (FOLDERFLAGS bits) */ +} FOLDERSETTINGS, *LPFOLDERSETTINGS; + +typedef const FOLDERSETTINGS * LPCFOLDERSETTINGS; + +/************************************************************************ + * Desktopfolder + */ + +extern IShellFolder * pdesktopfolder; + +DWORD WINAPI SHGetDesktopFolder(IShellFolder * *); + +/***************************************************************************** + * IShellFolder interface + */ +#define ICOM_INTERFACE IShellFolder +#define IShellFolder_METHODS \ + ICOM_METHOD6( HRESULT, ParseDisplayName, HWND, hwndOwner,LPBC, pbcReserved, LPOLESTR, lpszDisplayName, ULONG *, pchEaten, LPITEMIDLIST *, ppidl, ULONG *, pdwAttributes) \ + ICOM_METHOD3( HRESULT, EnumObjects, HWND, hwndOwner, DWORD, grfFlags, LPENUMIDLIST *, ppenumIDList)\ + ICOM_METHOD4( HRESULT, BindToObject, LPCITEMIDLIST, pidl, LPBC, pbcReserved, REFIID, riid, LPVOID *, ppvOut)\ + ICOM_METHOD4( HRESULT, BindToStorage, LPCITEMIDLIST, pidl, LPBC, pbcReserved, REFIID, riid, LPVOID *, ppvObj)\ + ICOM_METHOD3( HRESULT, CompareIDs, LPARAM, lParam, LPCITEMIDLIST, pidl1, LPCITEMIDLIST, pidl2)\ + ICOM_METHOD3( HRESULT, CreateViewObject, HWND, hwndOwner, REFIID, riid, LPVOID *, ppvOut)\ + ICOM_METHOD3( HRESULT, GetAttributesOf, UINT, cidl, LPCITEMIDLIST *, apidl, ULONG *, rgfInOut)\ + ICOM_METHOD6( HRESULT, GetUIObjectOf, HWND, hwndOwner, UINT, cidl, LPCITEMIDLIST *, apidl, REFIID, riid, UINT *, prgfInOut, LPVOID *, ppvOut)\ + ICOM_METHOD3( HRESULT, GetDisplayNameOf, LPCITEMIDLIST, pidl, DWORD, uFlags, LPSTRRET, lpName)\ + ICOM_METHOD5( HRESULT, SetNameOf, HWND, hwndOwner, LPCITEMIDLIST, pidl,LPCOLESTR, lpszName, DWORD, uFlags,LPITEMIDLIST *, ppidlOut) +#define IShellFolder_IMETHODS \ + IUnknown_IMETHODS \ + IShellFolder_METHODS +ICOM_DEFINE(IShellFolder,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellFolder_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellFolder_AddRef(p) ICOM_CALL (AddRef,p) +#define IShellFolder_Release(p) ICOM_CALL (Release,p) +/*** IShellFolder methods ***/ +#define IShellFolder_ParseDisplayName(p,a,b,c,d,e,f) ICOM_CALL6(ParseDisplayName,p,a,b,c,d,e,f) +#define IShellFolder_EnumObjects(p,a,b,c) ICOM_CALL3(EnumObjects,p,a,b,c) +#define IShellFolder_BindToObject(p,a,b,c,d) ICOM_CALL4(BindToObject,p,a,b,c,d) +#define IShellFolder_BindToStorage(p,a,b,c,d) ICOM_CALL4(BindToStorage,p,a,b,c,d) +#define IShellFolder_CompareIDs(p,a,b,c) ICOM_CALL3(CompareIDs,p,a,b,c) +#define IShellFolder_CreateViewObject(p,a,b,c) ICOM_CALL3(CreateViewObject,p,a,b,c) +#define IShellFolder_GetAttributesOf(p,a,b,c) ICOM_CALL3(GetAttributesOf,p,a,b,c) +#define IShellFolder_GetUIObjectOf(p,a,b,c,d,e,f) ICOM_CALL6(GetUIObjectOf,p,a,b,c,d,e,f) +#define IShellFolder_GetDisplayNameOf(p,a,b,c) ICOM_CALL3(GetDisplayNameOf,p,a,b,c) +#define IShellFolder_SetNameOf(p,a,b,c,d,e) ICOM_CALL5(SetNameOf,p,a,b,c,d,e) + +/***************************************************************************** + * IShellFolder2 interface + */ +/* IShellFolder2 */ + +/* GetDefaultColumnState */ +typedef enum +{ + SHCOLSTATE_TYPE_STR = 0x00000001, + SHCOLSTATE_TYPE_INT = 0x00000002, + SHCOLSTATE_TYPE_DATE = 0x00000003, + SHCOLSTATE_TYPEMASK = 0x0000000F, + SHCOLSTATE_ONBYDEFAULT = 0x00000010, + SHCOLSTATE_SLOW = 0x00000020, + SHCOLSTATE_EXTENDED = 0x00000040, + SHCOLSTATE_SECONDARYUI = 0x00000080, + SHCOLSTATE_HIDDEN = 0x00000100, +} SHCOLSTATE; + +typedef struct +{ + GUID fmtid; + DWORD pid; +} SHCOLUMNID, *LPSHCOLUMNID; +typedef const SHCOLUMNID* LPCSHCOLUMNID; + +/* GetDetailsEx */ +#define PID_FINDDATA 0 +#define PID_NETRESOURCE 1 +#define PID_DESCRIPTIONID 2 + +typedef struct +{ + int fmt; + int cxChar; + STRRET str; +} SHELLDETAILS, *LPSHELLDETAILS; + +#define ICOM_INTERFACE IShellFolder2 +#define IShellFolder2_METHODS \ + ICOM_METHOD1( HRESULT, GetDefaultSearchGUID, LPGUID, lpguid)\ + ICOM_METHOD1( HRESULT, EnumSearches, LPENUMEXTRASEARCH *, ppEnum) \ + ICOM_METHOD3( HRESULT, GetDefaultColumn, DWORD, dwReserved, ULONG *, pSort, ULONG *, pDisplay)\ + ICOM_METHOD2( HRESULT, GetDefaultColumnState, UINT, iColumn, DWORD *, pcsFlags)\ + ICOM_METHOD3( HRESULT, GetDetailsEx, LPCITEMIDLIST, pidl, const SHCOLUMNID *, pscid, VARIANT *, pv)\ + ICOM_METHOD3( HRESULT, GetDetailsOf, LPCITEMIDLIST, pidl, UINT, iColumn, LPSHELLDETAILS, pDetails)\ + ICOM_METHOD2( HRESULT, MapNameToSCID, LPCWSTR, pwszName, SHCOLUMNID *, pscid) +#define IShellFolder2_IMETHODS \ + IShellFolder_METHODS \ + IShellFolder2_METHODS +ICOM_DEFINE(IShellFolder2, IShellFolder) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellFolder2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellFolder2_AddRef(p) ICOM_CALL (AddRef,p) +#define IShellFolder2_Release(p) ICOM_CALL (Release,p) +/*** IShellFolder methods ***/ +#define IShellFolder2_ParseDisplayName(p,a,b,c,d,e,f) ICOM_CALL6(ParseDisplayName,p,a,b,c,d,e,f) +#define IShellFolder2_EnumObjects(p,a,b,c) ICOM_CALL3(EnumObjects,p,a,b,c) +#define IShellFolder2_BindToObject(p,a,b,c,d) ICOM_CALL4(BindToObject,p,a,b,c,d) +#define IShellFolder2_BindToStorage(p,a,b,c,d) ICOM_CALL4(BindToStorage,p,a,b,c,d) +#define IShellFolder2_CompareIDs(p,a,b,c) ICOM_CALL3(CompareIDs,p,a,b,c) +#define IShellFolder2_CreateViewObject(p,a,b,c) ICOM_CALL3(CreateViewObject,p,a,b,c) +#define IShellFolder2_GetAttributesOf(p,a,b,c) ICOM_CALL3(GetAttributesOf,p,a,b,c) +#define IShellFolder2_GetUIObjectOf(p,a,b,c,d,e,f) ICOM_CALL6(GetUIObjectOf,p,a,b,c,d,e,f) +#define IShellFolder2_GetDisplayNameOf(p,a,b,c) ICOM_CALL3(GetDisplayNameOf,p,a,b,c) +#define IShellFolder2_SetNameOf(p,a,b,c,d,e) ICOM_CALL5(SetNameOf,p,a,b,c,d,e) +/*** IShellFolder2 methods ***/ +#define IShellFolder2_GetDefaultSearchGUID(p,a) ICOM_CALL1(GetDefaultSearchGUID,p,a) +#define IShellFolder2_EnumSearches(p,a) ICOM_CALL1(EnumSearches,p,a) +#define IShellFolder2_GetDefaultColumn(p,a,b,c) ICOM_CALL3(GetDefaultColumn,p,a,b,c) +#define IShellFolder2_GetDefaultColumnState(p,a,b) ICOM_CALL2(GetDefaultColumnState,p,a,b) +#define IShellFolder2_GetDetailsEx(p,a,b,c) ICOM_CALL3(GetDetailsEx,p,a,b,c) +#define IShellFolder2_GetDetailsOf(p,a,b,c) ICOM_CALL3(GetDetailsOf,p,a,b,c) +#define IShellFolder2_MapNameToSCID(p,a,b) ICOM_CALL2(MapNameToSCID,p,a,b) + +/***************************************************************************** + * IPersistFolder interface + */ + +/* ClassID's */ +DEFINE_GUID (CLSID_SFMyComp,0x20D04FE0,0x3AEA,0x1069,0xA2,0xD8,0x08,0x00,0x2B,0x30,0x30,0x9D); +DEFINE_GUID (CLSID_SFINet, 0x871C5380,0x42A0,0x1069,0xA2,0xEA,0x08,0x00,0x2B,0x30,0x30,0x9D); +DEFINE_GUID (CLSID_SFFile, 0xF3364BA0,0x65B9,0x11CE,0xA9,0xBA,0x00,0xAA,0x00,0x4A,0xE8,0x37); + +#define ICOM_INTERFACE IPersistFolder +#define IPersistFolder_METHODS \ + ICOM_METHOD1( HRESULT, Initialize, LPCITEMIDLIST, pidl) +#define IPersistFolder_IMETHODS \ + IPersist_IMETHODS \ + IPersistFolder_METHODS +ICOM_DEFINE(IPersistFolder, IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistFolder_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistFolder_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistFolder_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistFolder_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistFolder methods ***/ +#define IPersistFolder_Initialize(p,a) ICOM_CALL1(Initialize,p,a) + +/***************************************************************************** + * IPersistFolder2 interface + */ + +#define ICOM_INTERFACE IPersistFolder2 +#define IPersistFolder2_METHODS \ + ICOM_METHOD1( HRESULT, GetCurFolder, LPITEMIDLIST*, pidl) +#define IPersistFolder2_IMETHODS \ + IPersist_IMETHODS \ + IPersistFolder_METHODS \ + IPersistFolder2_METHODS +ICOM_DEFINE(IPersistFolder2, IPersistFolder) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistFolder2_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistFolder2_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistFolder2_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistFolder2_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistFolder methods ***/ +#define IPersistFolder2_Initialize(p,a) ICOM_CALL1(Initialize,p,a) +/*** IPersistFolder2 methods ***/ +#define IPersistFolder2_GetCurFolder(p,a) ICOM_CALL1(GetCurFolder,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_SHELLFOLDER_H */ diff --git a/include/ole32/obj_shelllink.h b/include/ole32/obj_shelllink.h new file mode 100644 index 0000000..79bf29f --- /dev/null +++ b/include/ole32/obj_shelllink.h @@ -0,0 +1,146 @@ +/* + * Defines the COM interfaces and APIs related to IShellLink. + * + * Depends on 'obj_base.h'. + */ + +#ifndef __WINE_WINE_OBJ_SHELLLINK_H +#define __WINE_WINE_OBJ_SHELLLINK_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the interfaces + */ +typedef struct IShellLinkA IShellLinkA,*LPSHELLLINK; +typedef struct IShellLinkW IShellLinkW,*LPSHELLLINKW; + +/***************************************************************************** + * + */ +typedef enum +{ SLR_NO_UI = 0x0001, + SLR_ANY_MATCH = 0x0002, + SLR_UPDATE = 0x0004 +} SLR_FLAGS; + +/***************************************************************************** + * GetPath fFlags + */ +typedef enum +{ SLGP_SHORTPATH = 0x0001, + SLGP_UNCPRIORITY = 0x0002 +} SLGP_FLAGS; +/***************************************************************************** + * IShellLink interface + */ +#define ICOM_INTERFACE IShellLinkA +#define IShellLinkA_METHODS \ + ICOM_METHOD4( HRESULT, GetPath, LPSTR, pszFile, INT, cchMaxPath, WIN32_FIND_DATAA *, pfd, DWORD, fFlags) \ + ICOM_METHOD1( HRESULT, GetIDList, LPITEMIDLIST *, ppidl) \ + ICOM_METHOD1( HRESULT, SetIDList, LPCITEMIDLIST, pidl) \ + ICOM_METHOD2( HRESULT, GetDescription, LPSTR, pszName, INT, cchMaxName) \ + ICOM_METHOD1( HRESULT, SetDescription, LPCSTR, pszName) \ + ICOM_METHOD2( HRESULT, GetWorkingDirectory, LPSTR, pszDir,INT, cchMaxPath) \ + ICOM_METHOD1( HRESULT, SetWorkingDirectory, LPCSTR, pszDir) \ + ICOM_METHOD2( HRESULT, GetArguments, LPSTR, pszArgs, INT, cchMaxPath) \ + ICOM_METHOD1( HRESULT, SetArguments, LPCSTR, pszArgs) \ + ICOM_METHOD1( HRESULT, GetHotkey, WORD*, pwHotkey) \ + ICOM_METHOD1( HRESULT, SetHotkey, WORD, wHotkey) \ + ICOM_METHOD1( HRESULT, GetShowCmd, INT*, piShowCmd) \ + ICOM_METHOD1( HRESULT, SetShowCmd, INT, iShowCmd) \ + ICOM_METHOD3( HRESULT, GetIconLocation, LPSTR, pszIconPath, INT, cchIconPath,INT *, piIcon) \ + ICOM_METHOD2( HRESULT, SetIconLocation, LPCSTR, pszIconPath,INT, iIcon) \ + ICOM_METHOD2( HRESULT, SetRelativePath, LPCSTR, pszPathRel, DWORD, dwReserved) \ + ICOM_METHOD2( HRESULT, Resolve, HWND, hwnd, DWORD, fFlags) \ + ICOM_METHOD1( HRESULT, SetPath, LPCSTR, pszFile) +#define IShellLinkA_IMETHODS \ + IUnknown_IMETHODS \ + IShellLinkA_METHODS +ICOM_DEFINE(IShellLinkA,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellLinkA_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellLinkA_AddRef(p) ICOM_CALL (AddRef,p) +#define IShellLinkA_Release(p) ICOM_CALL (Release,p) +/*** IShellLink methods ***/ +#define IShellLinkA_GetPath(p,a,b,c,d) ICOM_CALL4(GetPath,p,a,b,c,d) +#define IShellLinkA_GetIDList(p,a) ICOM_CALL1(GetIDList,p,a) +#define IShellLinkA_SetIDList(p,a) ICOM_CALL1(SetIDList,p,a) +#define IShellLinkA_GetDescription(p,a,b) ICOM_CALL2(GetDescription,p,a,b) +#define IShellLinkA_SetDescription(p,a) ICOM_CALL1(SetDescription,p,a) +#define IShellLinkA_GetWorkingDirectory(p,a,b) ICOM_CALL2(GetWorkingDirectory,p,a,b) +#define IShellLinkA_SetWorkingDirectory(p,a) ICOM_CALL1(SetWorkingDirectory,p,a) +#define IShellLinkA_GetArguments(p,a,b) ICOM_CALL2(GetArguments,p,a,b) +#define IShellLinkA_SetArguments(p,a) ICOM_CALL1(SetArguments,p,a) +#define IShellLinkA_GetHotkey(p,a) ICOM_CALL1(GetHotkey,p,a) +#define IShellLinkA_SetHotkey(p,a) ICOM_CALL1(SetHotkey,p,a) +#define IShellLinkA_GetShowCmd(p,a) ICOM_CALL1(GetShowCmd,p,a) +#define IShellLinkA_SetShowCmd(p,a) ICOM_CALL1(SetShowCmd,p,a) +#define IShellLinkA_GetIconLocation(p,a,b,c) ICOM_CALL3(GetIconLocation,p,a,b,c) +#define IShellLinkA_SetIconLocation(p,a,b) ICOM_CALL2(SetIconLocation,p,a,b) +#define IShellLinkA_SetRelativePath(p,a,b) ICOM_CALL2(SetRelativePath,p,a,b) +#define IShellLinkA_Resolve(p,a,b) ICOM_CALL2(Resolve,p,a,b) +#define IShellLinkA_SetPath(p,a) ICOM_CALL1(SetPath,p,a) + +/***************************************************************************** + * IShellLinkW interface + */ +#define ICOM_INTERFACE IShellLinkW +#define IShellLinkW_METHODS \ + ICOM_METHOD4( HRESULT, GetPath, LPWSTR, pszFile, INT, cchMaxPath, WIN32_FIND_DATAA *, pfd, DWORD, fFlags) \ + ICOM_METHOD1( HRESULT, GetIDList, LPITEMIDLIST *, ppidl) \ + ICOM_METHOD1( HRESULT, SetIDList, LPCITEMIDLIST, pidl) \ + ICOM_METHOD2( HRESULT, GetDescription, LPWSTR, pszName, INT, cchMaxName) \ + ICOM_METHOD1( HRESULT, SetDescription, LPCWSTR, pszName) \ + ICOM_METHOD2( HRESULT, GetWorkingDirectory, LPWSTR, pszDir,INT, cchMaxPath) \ + ICOM_METHOD1( HRESULT, SetWorkingDirectory, LPCWSTR, pszDir) \ + ICOM_METHOD2( HRESULT, GetArguments, LPWSTR, pszArgs, INT, cchMaxPath) \ + ICOM_METHOD1( HRESULT, SetArguments, LPCWSTR, pszArgs) \ + ICOM_METHOD1( HRESULT, GetHotkey, WORD*, pwHotkey) \ + ICOM_METHOD1( HRESULT, SetHotkey, WORD, wHotkey) \ + ICOM_METHOD1( HRESULT, GetShowCmd, INT*, piShowCmd) \ + ICOM_METHOD1( HRESULT, SetShowCmd, INT, iShowCmd) \ + ICOM_METHOD3( HRESULT, GetIconLocation, LPWSTR, pszIconPath, INT, cchIconPath,INT *, piIcon) \ + ICOM_METHOD2( HRESULT, SetIconLocation, LPCWSTR, pszIconPath,INT, iIcon) \ + ICOM_METHOD2( HRESULT, SetRelativePath, LPCWSTR, pszPathRel, DWORD, dwReserved) \ + ICOM_METHOD2( HRESULT, Resolve, HWND, hwnd, DWORD, fFlags) \ + ICOM_METHOD1( HRESULT, SetPath, LPCWSTR, pszFile) +#define IShellLinkW_IMETHODS \ + IUnknown_IMETHODS \ + IShellLinkW_METHODS +ICOM_DEFINE(IShellLinkW,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellLinkW_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellLinkW_AddRef(p) ICOM_CALL (AddRef,p) +#define IShellLinkW_Release(p) ICOM_CALL (Release,p) +/*** IShellLinkW methods ***/ +#define IShellLinkW_GetPath(p,a,b,c,d) ICOM_CALL4(GetPath,p,a,b,c,d) +#define IShellLinkW_GetIDList(p,a) ICOM_CALL1(GetIDList,p,a) +#define IShellLinkW_SetIDList(p,a) ICOM_CALL1(SetIDList,p,a) +#define IShellLinkW_GetDescription(p,a,b) ICOM_CALL2(GetDescription,p,a,b) +#define IShellLinkW_SetDescription(p,a) ICOM_CALL1(SetDescription,p,a) +#define IShellLinkW_GetWorkingDirectory(p,a,b) ICOM_CALL2(GetWorkingDirectory,p,a,b) +#define IShellLinkW_SetWorkingDirectory(p,a) ICOM_CALL1(SetWorkingDirectory,p,a) +#define IShellLinkW_GetArguments(p,a,b) ICOM_CALL2(GetArguments,p,a,b) +#define IShellLinkW_SetArguments(p,a) ICOM_CALL1(SetArguments,p,a) +#define IShellLinkW_GetHotkey(p,a) ICOM_CALL1(GetHotkey,p,a) +#define IShellLinkW_SetHotkey(p,a) ICOM_CALL1(SetHotkey,p,a) +#define IShellLinkW_GetShowCmd(p,a) ICOM_CALL1(GetShowCmd,p,a) +#define IShellLinkW_SetShowCmd(p,a) ICOM_CALL1(SetShowCmd,p,a) +#define IShellLinkW_GetIconLocation(p,a,b,c) ICOM_CALL3(GetIconLocation,p,a,b,c) +#define IShellLinkW_SetIconLocation(p,a,b) ICOM_CALL2(SetIconLocation,p,a,b) +#define IShellLinkW_SetRelativePath(p,a,b) ICOM_CALL2(SetRelativePath,p,a,b) +#define IShellLinkW_Resolve(p,a,b) ICOM_CALL2(Resolve,p,a,b) +#define IShellLinkW_SetPath(p,a) ICOM_CALL1(SetPath,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_SHELLLINK_H */ diff --git a/include/ole32/obj_shellview.h b/include/ole32/obj_shellview.h new file mode 100644 index 0000000..5786bcc --- /dev/null +++ b/include/ole32/obj_shellview.h @@ -0,0 +1,159 @@ +/************************************************************ + * IShellView + */ + +#ifndef __WINE_WINE_OBJ_SHELLVIEW_H +#define __WINE_WINE_OBJ_SHELLVIEW_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/**************************************************************************** + * IShellBrowser is here defined because of a cyclic dependance between + * IShellBrowser and IShellView + */ +typedef struct IShellBrowser IShellBrowser, *LPSHELLBROWSER; + +typedef struct IShellView IShellView, *LPSHELLVIEW; + +/* shellview select item flags*/ +#define SVSI_DESELECT 0x0000 +#define SVSI_SELECT 0x0001 +#define SVSI_EDIT 0x0003 /* includes select */ +#define SVSI_DESELECTOTHERS 0x0004 +#define SVSI_ENSUREVISIBLE 0x0008 +#define SVSI_FOCUSED 0x0010 + +/* shellview get item object flags */ +#define SVGIO_BACKGROUND 0x00000000 +#define SVGIO_SELECTION 0x00000001 +#define SVGIO_ALLVIEW 0x00000002 + +/* The explorer dispatches WM_COMMAND messages based on the range of + command/menuitem IDs. All the IDs of menuitems that the view (right + pane) inserts must be in FCIDM_SHVIEWFIRST/LAST (otherwise, the explorer + won't dispatch them). The view should not deal with any menuitems + in FCIDM_BROWSERFIRST/LAST (otherwise, it won't work with the future + version of the shell). + + FCIDM_SHVIEWFIRST/LAST for the right pane (IShellView) + FCIDM_BROWSERFIRST/LAST for the explorer frame (IShellBrowser) + FCIDM_GLOBAL/LAST for the explorer's submenu IDs +*/ +#define FCIDM_SHVIEWFIRST 0x0000 +/* undocumented */ +#define FCIDM_SHVIEW_ARRANGE 0x7001 +#define FCIDM_SHVIEW_DELETE 0x7011 +#define FCIDM_SHVIEW_PROPERTIES 0x7013 +#define FCIDM_SHVIEW_CUT 0x7018 +#define FCIDM_SHVIEW_COPY 0x7019 +#define FCIDM_SHVIEW_INSERT 0x701A +#define FCIDM_SHVIEW_UNDO 0x701B +#define FCIDM_SHVIEW_INSERTLINK 0x701C +#define FCIDM_SHVIEW_SELECTALL 0x7021 +#define FCIDM_SHVIEW_INVERTSELECTION 0x7022 + +#define FCIDM_SHVIEW_BIGICON 0x7029 +#define FCIDM_SHVIEW_SMALLICON 0x702A +#define FCIDM_SHVIEW_LISTVIEW 0x702B +#define FCIDM_SHVIEW_REPORTVIEW 0x702C +/* 0x7030-0x703f are used by the shellbrowser */ +#define FCIDM_SHVIEW_AUTOARRANGE 0x7031 +#define FCIDM_SHVIEW_SNAPTOGRID 0x7032 + +#define FCIDM_SHVIEW_HELP 0x7041 +#define FCIDM_SHVIEW_RENAME 0x7050 +#define FCIDM_SHVIEW_CREATELINK 0x7051 +#define FCIDM_SHVIEW_NEWLINK 0x7052 +#define FCIDM_SHVIEW_NEWFOLDER 0x7053 + +#define FCIDM_SHVIEW_REFRESH 0x7100 /* fixme */ +#define FCIDM_SHVIEW_EXPLORE 0x7101 /* fixme */ +#define FCIDM_SHVIEW_OPEN 0x7102 /* fixme */ + +#define FCIDM_SHVIEWLAST 0x7fff +#define FCIDM_BROWSERFIRST 0xA000 +/* undocumented toolbar items from stddlg's*/ +#define FCIDM_TB_UPFOLDER 0xA001 +#define FCIDM_TB_NEWFOLDER 0xA002 +#define FCIDM_TB_SMALLICON 0xA003 +#define FCIDM_TB_REPORTVIEW 0xA004 +#define FCIDM_TB_DESKTOP 0xA005 /* fixme */ + +#define FCIDM_BROWSERLAST 0xbf00 +#define FCIDM_GLOBALFIRST 0x8000 +#define FCIDM_GLOBALLAST 0x9fff + +/* +* Global submenu IDs and separator IDs +*/ +#define FCIDM_MENU_FILE (FCIDM_GLOBALFIRST+0x0000) +#define FCIDM_MENU_EDIT (FCIDM_GLOBALFIRST+0x0040) +#define FCIDM_MENU_VIEW (FCIDM_GLOBALFIRST+0x0080) +#define FCIDM_MENU_VIEW_SEP_OPTIONS (FCIDM_GLOBALFIRST+0x0081) +#define FCIDM_MENU_TOOLS (FCIDM_GLOBALFIRST+0x00c0) +#define FCIDM_MENU_TOOLS_SEP_GOTO (FCIDM_GLOBALFIRST+0x00c1) +#define FCIDM_MENU_HELP (FCIDM_GLOBALFIRST+0x0100) +#define FCIDM_MENU_FIND (FCIDM_GLOBALFIRST+0x0140) +#define FCIDM_MENU_EXPLORE (FCIDM_GLOBALFIRST+0x0150) +#define FCIDM_MENU_FAVORITES (FCIDM_GLOBALFIRST+0x0170) + +/* control IDs known to the view */ +#define FCIDM_TOOLBAR (FCIDM_BROWSERFIRST + 0) +#define FCIDM_STATUS (FCIDM_BROWSERFIRST + 1) + +/* uState values for IShellView::UIActivate */ +typedef enum +{ SVUIA_DEACTIVATE = 0, + SVUIA_ACTIVATE_NOFOCUS = 1, + SVUIA_ACTIVATE_FOCUS = 2, + SVUIA_INPLACEACTIVATE = 3 /* new flag for IShellView2 */ +} SVUIA_STATUS; + +#define ICOM_INTERFACE IShellView +#define IShellView_METHODS \ + ICOM_METHOD1(HRESULT, TranslateAccelerator, LPMSG, lpmsg) \ + ICOM_METHOD1(HRESULT, EnableModeless, BOOL, fEnable) \ + ICOM_METHOD1(HRESULT, UIActivate, UINT, uState) \ + ICOM_METHOD(HRESULT, Refresh) \ + ICOM_METHOD5(HRESULT, CreateViewWindow, IShellView*, lpPrevView, LPCFOLDERSETTINGS, lpfs, IShellBrowser*, psb, RECT*, prcView, HWND*, phWnd) \ + ICOM_METHOD(HRESULT, DestroyViewWindow) \ + ICOM_METHOD1(HRESULT, GetCurrentInfo, LPFOLDERSETTINGS, lpfs) \ + ICOM_METHOD3(HRESULT, AddPropertySheetPages, DWORD, dwReserved, LPFNADDPROPSHEETPAGE, lpfn, LPARAM, lparam) \ + ICOM_METHOD (HRESULT, SaveViewState) \ + ICOM_METHOD2(HRESULT, SelectItem, LPCITEMIDLIST, pidlItem, UINT, uFlags) \ + ICOM_METHOD3(HRESULT, GetItemObject, UINT, uItem, REFIID, riid, LPVOID*, ppv) \ + ICOM_METHOD1(HRESULT, EditItem, LPCITEMIDLIST, pidlItem) +#define IShellView_IMETHODS \ + IOleWindow_IMETHODS \ + IShellView_METHODS +ICOM_DEFINE(IShellView,IOleWindow) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IShellView_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IShellView_AddRef(p) ICOM_CALL(AddRef,p) +#define IShellView_Release(p) ICOM_CALL(Release,p) +/*** IShellView methods ***/ +#define IShellView_GetWindow(p,a) ICOM_CALL1(GetWindow,p,a) +#define IShellView_ContextSensitiveHelp(p,a) ICOM_CALL1(ContextSensitiveHelp,p,a) +#define IShellView_TranslateAccelerator(p,a) ICOM_CALL1(TranslateAccelerator,p,a) +#define IShellView_EnableModeless(p,a) ICOM_CALL1(EnableModeless,p,a) +#define IShellView_UIActivate(p,a) ICOM_CALL1(UIActivate,p,a) +#define IShellView_Refresh(p) ICOM_CALL(Refresh,p) +#define IShellView_CreateViewWindow(p,a,b,c,d,e) ICOM_CALL5(CreateViewWindow,p,a,b,c,d,e) +#define IShellView_DestroyViewWindow(p) ICOM_CALL(DestroyViewWindow,p) +#define IShellView_GetCurrentInfo(p,a) ICOM_CALL1(GetCurrentInfo,p,a) +#define IShellView_AddPropertySheetPages(p,a,b,c) ICOM_CALL3(AddPropertySheetPages,p,a,b,c) +#define IShellView_SaveViewState(p) ICOM_CALL(SaveViewState,p) +#define IShellView_SelectItem(p,a,b) ICOM_CALL2(SelectItem,p,a,b) +#define IShellView_GetItemObject(p,a,b,c) ICOM_CALL3(GetItemObject,p,a,b,c) +/* WINE specific */ +#define IShellView_EditItem(p,a) ICOM_CALL1(EditItem,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_SHELLVIEW_H */ diff --git a/include/ole32/obj_storage.h b/include/ole32/obj_storage.h new file mode 100644 index 0000000..2449d79 --- /dev/null +++ b/include/ole32/obj_storage.h @@ -0,0 +1,650 @@ +/* + * Defines the COM interfaces and APIs related to structured data storage. + */ + +#ifndef __WINE_WINE_OBJ_STORAGE_H +#define __WINE_WINE_OBJ_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/***************************************************************************** + * Predeclare the structures + */ +typedef enum tagLOCKTYPE +{ + LOCK_WRITE = 1, + LOCK_EXCLUSIVE = 2, + LOCK_ONLYONCE = 4 +} LOCKTYPE; + +typedef struct tagStorageLayout +{ + DWORD LayoutType; + OLECHAR16* pwcsElementName; + LARGE_INTEGER cOffset; + LARGE_INTEGER cBytes; +} StorageLayout; + +typedef struct tagSTATSTG { + LPOLESTR pwcsName; + DWORD type; + ULARGE_INTEGER cbSize; + FILETIME mtime; + FILETIME ctime; + FILETIME atime; + DWORD grfMode; + DWORD grfLocksSupported; + CLSID clsid; + DWORD grfStateBits; + DWORD reserved; +} STATSTG; + +typedef struct tagSTATSTG16 { + LPOLESTR16 pwcsName; + DWORD type; + ULARGE_INTEGER cbSize; + FILETIME mtime; + FILETIME ctime; + FILETIME atime; + DWORD grfMode; + DWORD grfLocksSupported; + CLSID clsid; + DWORD grfStateBits; + DWORD reserved; +} STATSTG16; + +typedef LPOLESTR16 *SNB16; +typedef LPOLESTR *SNB; + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0); +typedef struct IEnumSTATSTG IEnumSTATSTG,*LPENUMSTATSTG; + +DEFINE_GUID (IID_IFillLockBytes, 0x99caf010L, 0x415e, 0x11cf, 0x88, 0x14, 0x00, 0xaa, 0x00, 0xb5, 0x69, 0xf5); +typedef struct IFillLockBytes IFillLockBytes,*LPFILLLOCKBYTES; + +DEFINE_GUID (IID_ILayoutStorage, 0x0e6d4d90L, 0x6738, 0x11cf, 0x96, 0x08, 0x00, 0xaa, 0x00, 0x68, 0x0d, 0xb4); +typedef struct ILayoutStorage ILayoutStorage,*LPLAYOUTSTORAGE; + +DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0); +typedef struct ILockBytes ILockBytes,*LPLOCKBYTES; + +DEFINE_OLEGUID(IID_IPersist, 0x0000010cL, 0, 0); +typedef struct IPersist IPersist,*LPPERSIST; + +DEFINE_OLEGUID(IID_IPersistFile, 0x0000010bL, 0, 0); +typedef struct IPersistFile IPersistFile,*LPPERSISTFILE; + +DEFINE_OLEGUID(IID_IPersistStorage, 0x0000010aL, 0, 0); +typedef struct IPersistStorage IPersistStorage,*LPPERSISTSTORAGE; + +DEFINE_OLEGUID(IID_IPersistStream, 0x00000109L, 0, 0); +typedef struct IPersistStream IPersistStream,*LPPERSISTSTREAM; + +DEFINE_GUID (IID_IProgressNotify, 0xa9d758a0L, 0x4617, 0x11cf, 0x95, 0xfc, 0x00, 0xaa, 0x00, 0x68, 0x0d, 0xb4); +typedef struct IProgressNotify IProgressNotify,*LPPROGRESSNOTIFY; + +DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0); +typedef struct IRootStorage IRootStorage,*LPROOTSTORAGE; + +DEFINE_GUID (IID_ISequentialStream, 0x0c733a30L, 0x2a1c, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d); +typedef struct ISequentialStream ISequentialStream,*LPSEQUENTIALSTREAM; + +DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0); +typedef struct IStorage16 IStorage16,*LPSTORAGE16; +typedef struct IStorage IStorage,*LPSTORAGE; + +DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0); +typedef struct IStream16 IStream16,*LPSTREAM16; +typedef struct IStream IStream,*LPSTREAM; + + +/***************************************************************************** + * STGM enumeration + * + * See IStorage and IStream + */ +#define STGM_DIRECT 0x00000000 +#define STGM_TRANSACTED 0x00010000 +#define STGM_SIMPLE 0x08000000 +#define STGM_READ 0x00000000 +#define STGM_WRITE 0x00000001 +#define STGM_READWRITE 0x00000002 +#define STGM_SHARE_DENY_NONE 0x00000040 +#define STGM_SHARE_DENY_READ 0x00000030 +#define STGM_SHARE_DENY_WRITE 0x00000020 +#define STGM_SHARE_EXCLUSIVE 0x00000010 +#define STGM_PRIORITY 0x00040000 +#define STGM_DELETEONRELEASE 0x04000000 +#define STGM_CREATE 0x00001000 +#define STGM_CONVERT 0x00020000 +#define STGM_FAILIFTHERE 0x00000000 +#define STGM_NOSCRATCH 0x00100000 +#define STGM_NOSNAPSHOT 0x00200000 + +/***************************************************************************** + * STGTY enumeration + * + * See IStorage + */ +#define STGTY_STORAGE 1 +#define STGTY_STREAM 2 +#define STGTY_LOCKBYTES 3 +#define STGTY_PROPERTY 4 + +/***************************************************************************** + * STATFLAG enumeration + * + * See IStorage and IStream + */ +#define STATFLAG_DEFAULT 0 +#define STATFLAG_NONAME 1 + +/***************************************************************************** + * STREAM_SEEK enumeration + * + * See IStream + */ +#define STREAM_SEEK_SET 0 +#define STREAM_SEEK_CUR 1 +#define STREAM_SEEK_END 2 + +/***************************************************************************** + * IEnumSTATSTG interface + */ +#define ICOM_INTERFACE IEnumSTATSTG +#define IEnumSTATSTG_METHODS \ + ICOM_METHOD3(HRESULT,Next, ULONG,celt, STATSTG*,rgelt, ULONG*,pceltFethed) \ + ICOM_METHOD1(HRESULT,Skip, ULONG,celt) \ + ICOM_METHOD (HRESULT,Reset) \ + ICOM_METHOD1(HRESULT,Clone, IEnumSTATSTG**,ppenum) +#define IEnumSTATSTG_IMETHODS \ + IUnknown_IMETHODS \ + IEnumSTATSTG_METHODS +ICOM_DEFINE(IEnumSTATSTG,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IEnumSTATSTG_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IEnumSTATSTG_AddRef(p) ICOM_CALL (AddRef,p) +#define IEnumSTATSTG_Release(p) ICOM_CALL (Release,p) +/*** IEnumSTATSTG methods ***/ +#define IEnumSTATSTG_Next(p,a,b,c) ICOM_CALL3(Next,p,a,b,c) +#define IEnumSTATSTG_Skip(p,a) ICOM_CALL1(Skip,p,a) +#define IEnumSTATSTG_Reset(p) ICOM_CALL(Reset,p) +#define IEnumSTATSTG_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * IFillLockBytes interface + */ +#define ICOM_INTERFACE IFillLockBytes +#define IFillLockBytes_METHODS \ + ICOM_METHOD3(HRESULT,FillAppend, const void*,pv, ULONG,cb, ULONG*,pcbWritten) \ + ICOM_METHOD4(HRESULT,FillAt, ULARGE_INTEGER,ulOffset, const void*,pv, ULONG,cb, ULONG*,pcbWritten) \ + ICOM_METHOD1(HRESULT,SetFillSize, ULARGE_INTEGER,ulSize) \ + ICOM_METHOD1(HRESULT,Terminate, BOOL,bCanceled) +#define IFillLockBytes_IMETHODS \ + IUnknown_IMETHODS \ + IFillLockBytes_METHODS +ICOM_DEFINE(IFillLockBytes,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IFillLockBytes_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IFillLockBytes_AddRef(p) ICOM_CALL (AddRef,p) +#define IFillLockBytes_Release(p) ICOM_CALL (Release,p) +/*** IFillLockBytes methods ***/ +#define IFillLockBytes_FillAppend(p,a,b,c) ICOM_CALL3(FillAppend,p,a,b,c) +#define IFillLockBytes_FillAt(p,a,b,c,d) ICOM_CALL4(FillAt,p,a,b,c,d) +#define IFillLockBytes_SetFillSize(p,a) ICOM_CALL1(SetFillSize,p,a) +#define IFillLockBytes_Terminate(p,a) ICOM_CALL1(Terminate,p,a) + + +/***************************************************************************** + * ILayoutStorage interface + */ +#define ICOM_INTERFACE ILayoutStorage +#define ILayoutStorage_METHODS \ + ICOM_METHOD2(HRESULT,LayoutScript, DWORD,nEntries, DWORD,glfInterleavedFlag) \ + ICOM_METHOD (HRESULT,BeginMonitor) \ + ICOM_METHOD (HRESULT,EndMonitor) \ + ICOM_METHOD1(HRESULT,ReLayoutDocfile, OLECHAR16*,pwcsNewDfName) \ + ICOM_METHOD1(HRESULT,ReLayoutDocfileOnILockBytes, ILockBytes*,pILockBytes) +#define ILayoutStorage_IMETHODS \ + IUnknown_IMETHODS \ + ILayoutStorage_METHODS +ICOM_DEFINE(ILayoutStorage,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ILayoutStorage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ILayoutStorage_AddRef(p) ICOM_CALL (AddRef,p) +#define ILayoutStorage_Release(p) ICOM_CALL (Release,p) +/*** ILayoutStorage methods ***/ +#define ILayoutStorage_LayoutScript(p,a,b) ICOM_CALL2(LayoutScript,p,a,b) +#define ILayoutStorage_BeginMonitor(p) ICOM_CALL (BeginMonitor,p) +#define ILayoutStorage_EndMonitor(p) ICOM_CALL (EndMonitor,p) +#define ILayoutStorage_ReLayoutDocfile(p,a) ICOM_CALL1(ReLayoutDocfile,p,a) +#define ILayoutStorage_ReLayoutDocfileOnILockBytes(p,a) ICOM_CALL1(ReLayoutDocfileOnILockBytes,p,a) + + +/***************************************************************************** + * ILockBytes interface + */ +#define ICOM_INTERFACE ILockBytes +#define ILockBytes_METHODS \ + ICOM_METHOD4(HRESULT,ReadAt, ULARGE_INTEGER,ulOffset, void*,pv, ULONG,cb, ULONG*,pcbRead) \ + ICOM_METHOD4(HRESULT,WriteAt, ULARGE_INTEGER,ulOffset, const void*,pv, ULONG,cb, ULONG*,pcbWritten) \ + ICOM_METHOD (HRESULT,Flush) \ + ICOM_METHOD1(HRESULT,SetSize, ULARGE_INTEGER,cb) \ + ICOM_METHOD3(HRESULT,LockRegion, ULARGE_INTEGER,libOffset, ULARGE_INTEGER,cb, DWORD,dwLockType) \ + ICOM_METHOD3(HRESULT,UnlockRegion, ULARGE_INTEGER,libOffset, ULARGE_INTEGER,cb, DWORD,dwLockType) \ + ICOM_METHOD2(HRESULT,Stat, STATSTG*,pstatstg, DWORD,grfStatFlag) +#define ILockBytes_IMETHODS \ + IUnknown_IMETHODS \ + ILockBytes_METHODS +ICOM_DEFINE(ILockBytes,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ILockBytes_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ILockBytes_AddRef(p) ICOM_CALL (AddRef,p) +#define ILockBytes_Release(p) ICOM_CALL (Release,p) +/*** ILockBytes methods ***/ +#define ILockBytes_ReadAt(p,a,b,c,d) ICOM_CALL4(ReadAt,p,a,b,c,d) +#define ILockBytes_WriteAt(p,a,b,c,d) ICOM_CALL4(WriteAt,p,a,b,c,d) +#define ILockBytes_Flush(p) ICOM_CALL (Flush,p) +#define ILockBytes_SetSize(p,a) ICOM_CALL1(SetSize,p,a) +#define ILockBytes_LockRegion(p,a,b,c) ICOM_CALL3(LockRegion,p,a,b,c) +#define ILockBytes_UnlockRegion(p,a,b,c) ICOM_CALL3(UnlockRegion,p,a,b,c) +#define ILockBytes_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b) + + +/***************************************************************************** + * IPersist interface + */ +#define ICOM_INTERFACE IPersist +#define IPersist_METHODS \ + ICOM_METHOD1(HRESULT,GetClassID, CLSID*,pClassID) +#define IPersist_IMETHODS \ + IUnknown_IMETHODS \ + IPersist_METHODS +ICOM_DEFINE(IPersist,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersist_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersist_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersist_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersist_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) + + +/***************************************************************************** + * IPersistFile interface + */ +#define ICOM_INTERFACE IPersistFile +#define IPersistFile_METHODS \ + ICOM_METHOD (HRESULT,IsDirty) \ + ICOM_METHOD2 (HRESULT,Load, LPCOLESTR,pszFileName, DWORD,dwMode) \ + ICOM_METHOD2 (HRESULT,Save, LPCOLESTR,pszFileName, BOOL,fRemember) \ + ICOM_METHOD1 (HRESULT,SaveCompleted, LPCOLESTR,pszFileName) \ + ICOM_METHOD1(HRESULT,GetCurFile, LPOLESTR*,ppszFileName) +#define IPersistFile_IMETHODS \ + IPersist_IMETHODS \ + IPersistFile_METHODS +ICOM_DEFINE(IPersistFile,IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistFile_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistFile_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistFile_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistFile_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistFile methods ***/ +#define IPersistFile_IsDirty(p) ICOM_CALL(IsDirty,p) +#define IPersistFile_Load(p,a,b) ICOM_CALL2(Load,p,a,b) +#define IPersistFile_Save(p,a,b) ICOM_CALL2(Save,p,a,b) +#define IPersistFile_SaveCompleted(p,a) ICOM_CALL1(SaveCompleted,p,a) +#define IPersistFile_GetCurFile(p,a) ICOM_CALL1(GetCurFile,p,a) + + +/***************************************************************************** + * IPersistStorage interface + */ +#define ICOM_INTERFACE IPersistStorage +#define IPersistStorage_METHODS \ + ICOM_METHOD (HRESULT,IsDirty) \ + ICOM_METHOD1(HRESULT,InitNew, IStorage*,pStg) \ + ICOM_METHOD1(HRESULT,Load, IStorage*,pStg) \ + ICOM_METHOD2(HRESULT,Save, IStorage*,pStg, BOOL,fSameAsLoad) \ + ICOM_METHOD1(HRESULT,SaveCompleted, IStorage*,pStgNew) \ + ICOM_METHOD (HRESULT,HandsOffStorage) +#define IPersistStorage_IMETHODS \ + IPersist_IMETHODS \ + IPersistStorage_METHODS +ICOM_DEFINE(IPersistStorage,IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistStorage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistStorage_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistStorage_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistStorage_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistStorage methods ***/ +#define IPersistStorage_IsDirty(p) ICOM_CALL (IsDirty,p) +#define IPersistStorage_InitNew(p,a) ICOM_CALL1(InitNew,p,a) +#define IPersistStorage_Load(p,a) ICOM_CALL1(Load,p,a) +#define IPersistStorage_Save(p,a,b) ICOM_CALL2(Save,p,a,b) +#define IPersistStorage_SaveCompleted(p,a) ICOM_CALL1(SaveCompleted,p,a) +#define IPersistStorage_HandsOffStorage(p) ICOM_CALL (HandsOffStorage,p) + + +/***************************************************************************** + * IPersistStream interface + */ +#define ICOM_INTERFACE IPersistStream +#define IPersistStream_METHODS \ + ICOM_METHOD (HRESULT,IsDirty) \ + ICOM_METHOD1(HRESULT,Load, IStream*,pStm) \ + ICOM_METHOD2(HRESULT,Save, IStream*,pStm, BOOL,fClearDirty) \ + ICOM_METHOD1(HRESULT,GetSizeMax, ULARGE_INTEGER*,pcbSize) +#define IPersistStream_IMETHODS \ + IPersist_IMETHODS \ + IPersistStream_METHODS +ICOM_DEFINE(IPersistStream,IPersist) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IPersistStream_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IPersistStream_AddRef(p) ICOM_CALL (AddRef,p) +#define IPersistStream_Release(p) ICOM_CALL (Release,p) +/*** IPersist methods ***/ +#define IPersistStream_GetClassID(p,a) ICOM_CALL1(GetClassID,p,a) +/*** IPersistStream methods ***/ +#define IPersistStream_IsDirty(p) ICOM_CALL (IsDirty,p) +#define IPersistStream_Load(p,a) ICOM_CALL1(Load,p,a) +#define IPersistStream_Save(p,a,b) ICOM_CALL2(Save,p,a,b) +#define IPersistStream_GetSizeMax(p,a) ICOM_CALL1(GetSizeMax,p,a) + + +/***************************************************************************** + * IProgressNotify interface + */ +#define ICOM_INTERFACE IProgressNotify +#define IProgressNotify_METHODS \ + ICOM_METHOD4(HRESULT,OnProgress, DWORD,dwProgressCurrent, DWORD,dwProgressMaximum, BOOL,fAccurate, BOOL,fOwner) +#define IProgressNotify_IMETHODS \ + IUnknown_IMETHODS \ + IProgressNotify_METHODS +ICOM_DEFINE(IProgressNotify,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IProgressNotify_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IProgressNotify_AddRef(p) ICOM_CALL (AddRef,p) +#define IProgressNotify_Release(p) ICOM_CALL (Release,p) +/*** IProgressNotify methods ***/ +#define IProgressNotify_OnProgress(p,a,b,c,d) ICOM_CALL4(OnProgress,p,a,b,c,d) + + +/***************************************************************************** + * IRootStorage interface + */ +#define ICOM_INTERFACE IRootStorage +#define IRootStorage_METHODS \ + ICOM_METHOD1(HRESULT,SwitchToFile, LPOLESTR,pszFile) +#define IRootStorage_IMETHODS \ + IUnknown_IMETHODS \ + IRootStorage_METHODS +ICOM_DEFINE(IRootStorage,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IRootStorage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IRootStorage_AddRef(p) ICOM_CALL (AddRef,p) +#define IRootStorage_Release(p) ICOM_CALL (Release,p) +/*** IRootStorage methods ***/ +#define IRootStorage_SwitchToFile(p,a) ICOM_CALLSwitchToFile(,p,a) + + +/***************************************************************************** + * ISequentialStream interface + */ +#define ICOM_INTERFACE ISequentialStream +#define ISequentialStream_METHODS \ + ICOM_METHOD3(HRESULT,Read, void*,pv, ULONG,cb, ULONG*,pcbRead) \ + ICOM_METHOD3(HRESULT,Write, const void*,pv, ULONG,cb, ULONG*,pcbWritten) +#define ISequentialStream_IMETHODS \ + IUnknown_IMETHODS \ + ISequentialStream_METHODS +ICOM_DEFINE(ISequentialStream,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ISequentialStream_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ISequentialStream_AddRef(p) ICOM_CALL (AddRef,p) +#define ISequentialStream_Release(p) ICOM_CALL (Release,p) +/*** ISequentialStream methods ***/ +#define ISequentialStream_Read(p,a,b,c) ICOM_CALL3(Read,p,a,b,c) +#define ISequentialStream_Write(p,a,b,c) ICOM_CALL3(Write,p,a,b,c) + + +/***************************************************************************** + * IStorage interface + */ +#define ICOM_INTERFACE IStorage16 +#define IStorage16_METHODS \ + ICOM_METHOD5(HRESULT,CreateStream, LPCOLESTR16,pwcsName, DWORD,grfMode, DWORD,reserved1, DWORD,reserved2, IStream16**,ppstm) \ + ICOM_METHOD5(HRESULT,OpenStream, LPCOLESTR16,pwcsName, void*,reserved1, DWORD,grfMode, DWORD,reserved2, IStream16**,ppstm) \ + ICOM_METHOD5(HRESULT,CreateStorage, LPCOLESTR16,pwcsName, DWORD,grfMode, DWORD,dwStgFmt, DWORD,reserved2, IStorage16**,ppstg) \ + ICOM_METHOD6(HRESULT,OpenStorage, LPCOLESTR16,pwcsName, IStorage16*,pstgPriority, DWORD,grfMode, SNB16,snb16Exclude, DWORD,reserved, IStorage16**,ppstg) \ + ICOM_METHOD4(HRESULT,CopyTo, DWORD,ciidExclude, const IID*,rgiidExclude, SNB16,snb16Exclude, IStorage16*,pstgDest) \ + ICOM_METHOD4(HRESULT,MoveElementTo, LPCOLESTR16,pwcsName, IStorage16*,pstgDest, LPCOLESTR16,pwcsNewName, DWORD,grfFlags) \ + ICOM_METHOD1(HRESULT,Commit, DWORD,grfCommitFlags) \ + ICOM_METHOD (HRESULT,Revert) \ + ICOM_METHOD4(HRESULT,EnumElements, DWORD,reserved1, void*,reserved2, DWORD,reserved3, IEnumSTATSTG**,ppenum) \ + ICOM_METHOD1(HRESULT,DestroyElement, LPCOLESTR16,pwcsName) \ + ICOM_METHOD2(HRESULT,RenameElement, LPCOLESTR16,pwcsOldName, LPOLESTR16,pwcsNewName) \ + ICOM_METHOD4(HRESULT,SetElementTimes,LPCOLESTR16,pwcsName, const FILETIME*,pctime, const FILETIME*,patime, const FILETIME*,pmtime) \ + ICOM_METHOD1(HRESULT,SetClass, REFCLSID,clsid) \ + ICOM_METHOD2(HRESULT,SetStateBits, DWORD,grfStateBits, DWORD,grfMask) \ + ICOM_METHOD2(HRESULT,Stat, STATSTG*,pstatstg, DWORD,grfStatFlag) +#define IStorage16_IMETHODS \ + IUnknown_IMETHODS \ + IStorage16_METHODS +ICOM_DEFINE(IStorage16,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IStorage16_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IStorage16_AddRef(p) ICOM_CALL (AddRef,p) +#define IStorage16_Release(p) ICOM_CALL (Release,p) +/*** IStorage16 methods ***/ +#define IStorage16_CreateStream(p,a,b,c,d,e) ICOM_CALL5(CreateStream,p,a,b,c,d,e) +#define IStorage16_OpenStream(p,a,b,c,d,e) ICOM_CALL5(OpenStream,p,a,b,c,d,e) +#define IStorage16_CreateStorage(p,a,b,c,d,e) ICOM_CALL5(CreateStorage,p,a,b,c,d,e) +#define IStorage16_OpenStorage(p,a,b,c,d,e,f) ICOM_CALL6(OpenStorage,p,a,b,c,d,e,f) +#define IStorage16_CopyTo(p,a,b,c,d) ICOM_CALL4(CopyTo,p,a,b,c,d) +#define IStorage16_MoveElementTo(p,a,b,c,d) ICOM_CALL4(MoveElementTo,p,a,b,c,d) +#define IStorage16_Commit(p,a) ICOM_CALL1(Commit,p,a) +#define IStorage16_Revert(p) ICOM_CALL (Revert,p) +#define IStorage16_EnumElements(p,a,b,c,d) ICOM_CALL4(EnumElements,p,a,b,c,d) +#define IStorage16_DestroyElement(p,a) ICOM_CALL1(DestroyElement,p,a) +#define IStorage16_RenameElement(p,a,b) ICOM_CALL2(RenameElement,p,a,b) +#define IStorage16_SetElementTimes(p,a,b,c,d) ICOM_CALL4(SetElementTimes,p,a,b,c,d) +#define IStorage16_SetClass(p,a) ICOM_CALL1(SetClass,p,a) +#define IStorage16_SetStateBits(p,a,b) ICOM_CALL2(SetStateBits,p,a,b) +#define IStorage16_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b) + + +#define ICOM_INTERFACE IStorage +#define IStorage_METHODS \ + ICOM_METHOD5(HRESULT,CreateStream, LPCOLESTR,pwcsName, DWORD,grfMode, DWORD,reserved1, DWORD,reserved2, IStream**,ppstm) \ + ICOM_METHOD5(HRESULT,OpenStream, LPCOLESTR,pwcsName, void*,reserved1, DWORD,grfMode, DWORD,reserved2, IStream**,ppstm) \ + ICOM_METHOD5(HRESULT,CreateStorage, LPCOLESTR,pwcsName, DWORD,grfMode, DWORD,dwStgFmt, DWORD,reserved2, IStorage**,ppstg) \ + ICOM_METHOD6(HRESULT,OpenStorage, LPCOLESTR,pwcsName, IStorage*,pstgPriority, DWORD,grfMode, SNB,snb16Exclude, DWORD,reserved, IStorage**,ppstg) \ + ICOM_METHOD4(HRESULT,CopyTo, DWORD,ciidExclude, const IID*,rgiidExclude, SNB,snb16Exclude, IStorage*,pstgDest) \ + ICOM_METHOD4(HRESULT,MoveElementTo, LPCOLESTR,pwcsName, IStorage*,pstgDest, LPCOLESTR,pwcsNewName, DWORD,grfFlags) \ + ICOM_METHOD1(HRESULT,Commit, DWORD,grfCommitFlags) \ + ICOM_METHOD (HRESULT,Revert) \ + ICOM_METHOD4(HRESULT,EnumElements, DWORD,reserved1, void*,reserved2, DWORD,reserved3, IEnumSTATSTG**,ppenum) \ + ICOM_METHOD1(HRESULT,DestroyElement, LPCOLESTR,pwcsName) \ + ICOM_METHOD2(HRESULT,RenameElement, LPCOLESTR,pwcsOldName, LPCOLESTR,pwcsNewName) \ + ICOM_METHOD4(HRESULT,SetElementTimes,LPCOLESTR,pwcsName, const FILETIME*,pctime, const FILETIME*,patime, const FILETIME*,pmtime) \ + ICOM_METHOD1(HRESULT,SetClass, REFCLSID,clsid) \ + ICOM_METHOD2(HRESULT,SetStateBits, DWORD,grfStateBits, DWORD,grfMask) \ + ICOM_METHOD2(HRESULT,Stat, STATSTG*,pstatstg, DWORD,grfStatFlag) +#define IStorage_IMETHODS \ + IUnknown_IMETHODS \ + IStorage_METHODS +ICOM_DEFINE(IStorage,IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IStorage_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IStorage_AddRef(p) ICOM_CALL (AddRef,p) +#define IStorage_Release(p) ICOM_CALL (Release,p) +/*** IStorage methods ***/ +#define IStorage_CreateStream(p,a,b,c,d,e) ICOM_CALL5(CreateStream,p,a,b,c,d,e) +#define IStorage_OpenStream(p,a,b,c,d,e) ICOM_CALL5(OpenStream,p,a,b,c,d,e) +#define IStorage_CreateStorage(p,a,b,c,d,e) ICOM_CALL5(CreateStorage,p,a,b,c,d,e) +#define IStorage_OpenStorage(p,a,b,c,d,e,f) ICOM_CALL6(OpenStorage,p,a,b,c,d,e,f) +#define IStorage_CopyTo(p,a,b,c,d) ICOM_CALL4(CopyTo,p,a,b,c,d) +#define IStorage_MoveElementTo(p,a,b,c,d) ICOM_CALL4(MoveElementTo,p,a,b,c,d) +#define IStorage_Commit(p,a) ICOM_CALL1(Commit,p,a) +#define IStorage_Revert(p) ICOM_CALL (Revert,p) +#define IStorage_EnumElements(p,a,b,c,d) ICOM_CALL4(EnumElements,p,a,b,c,d) +#define IStorage_DestroyElement(p,a) ICOM_CALL1(DestroyElement,p,a) +#define IStorage_RenameElement(p,a,b) ICOM_CALL2(RenameElement,p,a,b) +#define IStorage_SetElementTimes(p,a,b,c,d) ICOM_CALL4(SetElementTimes,p,a,b,c,d) +#define IStorage_SetClass(p,a) ICOM_CALL1(SetClass,p,a) +#define IStorage_SetStateBits(p,a,b) ICOM_CALL2(SetStateBits,p,a,b) +#define IStorage_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b) + + +/***************************************************************************** + * IStream interface + */ +#define ICOM_INTERFACE IStream16 +#define IStream16_METHODS \ + ICOM_METHOD3(HRESULT,Seek, LARGE_INTEGER,dlibMove, DWORD,dwOrigin, ULARGE_INTEGER*,plibNewPosition) \ + ICOM_METHOD1(HRESULT,SetSize, ULARGE_INTEGER,libNewSize) \ + ICOM_METHOD4(HRESULT,CopyTo, IStream16*,pstm, ULARGE_INTEGER,cb, ULARGE_INTEGER*,pcbRead, ULARGE_INTEGER*,pcbWritten) \ + ICOM_METHOD1(HRESULT,Commit, DWORD,grfCommitFlags) \ + ICOM_METHOD (HRESULT,Revert) \ + ICOM_METHOD3(HRESULT,LockRegion, ULARGE_INTEGER,libOffset, ULARGE_INTEGER,cb, DWORD,dwLockType) \ + ICOM_METHOD3(HRESULT,UnlockRegion,ULARGE_INTEGER,libOffset, ULARGE_INTEGER,cb, DWORD,dwLockType) \ + ICOM_METHOD2(HRESULT,Stat, STATSTG*,pstatstg, DWORD,grfStatFlag) \ + ICOM_METHOD1(HRESULT,Clone, IStream16**,ppstm) +#define IStream16_IMETHODS \ + ISequentialStream_IMETHODS \ + IStream16_METHODS +ICOM_DEFINE(IStream16,ISequentialStream) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IStream16_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IStream16_AddRef(p) ICOM_CALL (AddRef,p) +#define IStream16_Release(p) ICOM_CALL (Release,p) +/*** ISequentialStream methods ***/ +#define IStream16_Read(p,a,b,c) ICOM_CALL3(Read,p,a,b,c) +#define IStream16_Write(p,a,b,c) ICOM_CALL3(Write,p,a,b,c) +/*** IStream16 methods ***/ +#define IStream16_Seek(p) ICOM_CALL3(Seek,p) +#define IStream16_SetSize(p,a,b) ICOM_CALL1(SetSize,p,a,b) +#define IStream16_CopyTo(pa,b,c,d) ICOM_CALL4(CopyTo,pa,b,c,d) +#define IStream16_Commit(p,a) ICOM_CALL1(Commit,p,a) +#define IStream16_Revert(p) ICOM_CALL (Revert,p) +#define IStream16_LockRegion(pa,b,c) ICOM_CALL3(LockRegion,pa,b,c) +#define IStream16_UnlockRegion(p,a,b,c) ICOM_CALL3(UnlockRegion,p,a,b,c) +#define IStream16_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b) +#define IStream16_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +#define ICOM_INTERFACE IStream +#define IStream_METHODS \ + ICOM_METHOD3(HRESULT,Seek, LARGE_INTEGER,dlibMove, DWORD,dwOrigin, ULARGE_INTEGER*,plibNewPosition) \ + ICOM_METHOD1(HRESULT,SetSize, ULARGE_INTEGER,libNewSize) \ + ICOM_METHOD4(HRESULT,CopyTo, IStream*,pstm, ULARGE_INTEGER,cb, ULARGE_INTEGER*,pcbRead, ULARGE_INTEGER*,pcbWritten) \ + ICOM_METHOD1(HRESULT,Commit, DWORD,grfCommitFlags) \ + ICOM_METHOD (HRESULT,Revert) \ + ICOM_METHOD3(HRESULT,LockRegion, ULARGE_INTEGER,libOffset, ULARGE_INTEGER,cb, DWORD,dwLockType) \ + ICOM_METHOD3(HRESULT,UnlockRegion,ULARGE_INTEGER,libOffset, ULARGE_INTEGER,cb, DWORD,dwLockType) \ + ICOM_METHOD2(HRESULT,Stat, STATSTG*,pstatstg, DWORD,grfStatFlag) \ + ICOM_METHOD1(HRESULT,Clone, IStream**,ppstm) +#define IStream_IMETHODS \ + ISequentialStream_IMETHODS \ + IStream_METHODS +ICOM_DEFINE(IStream,ISequentialStream) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IStream_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IStream_AddRef(p) ICOM_CALL (AddRef,p) +#define IStream_Release(p) ICOM_CALL (Release,p) +/*** ISequentialStream methods ***/ +#define IStream_Read(p,a,b,c) ICOM_CALL3(Read,p,a,b,c) +#define IStream_Write(p,a,b,c) ICOM_CALL3(Write,p,a,b,c) +/*** IStream methods ***/ +#define IStream_Seek(p,a,b,c) ICOM_CALL3(Seek,p,a,b,c) +#define IStream_SetSize(p,a) ICOM_CALL1(SetSize,p,a) +#define IStream_CopyTo(p,a,b,c,d) ICOM_CALL4(CopyTo,p,a,b,c,d) +#define IStream_Commit(p,a) ICOM_CALL1(Commit,p,a) +#define IStream_Revert(p) ICOM_CALL (Revert,p) +#define IStream_LockRegion(p,a,b,c) ICOM_CALL3(LockRegion,p,a,b,c) +#define IStream_UnlockRegion(p,a,b,c) ICOM_CALL3(UnlockRegion,p,a,b,c) +#define IStream_Stat(p,a,b) ICOM_CALL2(Stat,p,a,b) +#define IStream_Clone(p,a) ICOM_CALL1(Clone,p,a) + + +/***************************************************************************** + * StgXXX API + */ +/* FIXME: many functions are missing */ +HRESULT WINAPI StgCreateDocFile16(LPCOLESTR16 pwcsName,DWORD grfMode,DWORD reserved,IStorage16 **ppstgOpen); +HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName,DWORD grfMode,DWORD reserved,IStorage **ppstgOpen); + +HRESULT WINAPI StgIsStorageFile16(LPCOLESTR16 fn); +HRESULT WINAPI StgIsStorageFile(LPCOLESTR fn); +HRESULT WINAPI StgIsStorageILockBytes(ILockBytes *plkbyt); + +HRESULT WINAPI StgOpenStorage16(const OLECHAR16* pwcsName,IStorage16* pstgPriority,DWORD grfMode,SNB16 snbExclude,DWORD reserved,IStorage16**ppstgOpen); +HRESULT WINAPI StgOpenStorage(const OLECHAR* pwcsName,IStorage* pstgPriority,DWORD grfMode,SNB snbExclude,DWORD reserved,IStorage**ppstgOpen); + +HRESULT WINAPI WriteClassStg(IStorage* pStg, REFCLSID rclsid); +HRESULT WINAPI ReadClassStg(IStorage *pstg,CLSID *pclsid); + +HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid); +HRESULT WINAPI ReadClassStm(IStream *pStm,REFCLSID rclsid); + +HRESULT WINAPI StgCreateDocfileOnILockBytes(ILockBytes *plkbyt,DWORD grfMode, DWORD reserved, IStorage** ppstgOpen); +HRESULT WINAPI StgOpenStorageOnILockBytes(ILockBytes *plkbyt, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstgOpen); + +/***************************************************************************** + * Other storage API + */ + +/* FIXME: not implemented */ +BOOL WINAPI CoDosDateTimeToFileTime(WORD nDosDate, WORD nDosTime, FILETIME* lpFileTime); + +/* FIXME: not implemented */ +BOOL WINAPI CoFileTimeToDosDateTime(FILETIME* lpFileTime, WORD* lpDosDate, WORD* lpDosTime); + +HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal); + +HRESULT WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_STORAGE_H */ diff --git a/include/ole32/obj_webbrowser.h b/include/ole32/obj_webbrowser.h new file mode 100644 index 0000000..fb9f3d6 --- /dev/null +++ b/include/ole32/obj_webbrowser.h @@ -0,0 +1,100 @@ +/* + * Defines the COM interfaces and APIs related to the IE Web browser control + * + * 2001 John R. Sheets (for CodeWeavers) + */ + +#ifndef __WINE_WINE_OBJ_WEBBROWSER_H +#define __WINE_WINE_OBJ_WEBBROWSER_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + + +/***************************************************************************** + * Predeclare the interfaces and class IDs + */ +DEFINE_GUID(IID_IWebBrowser, 0xeab22ac1, 0x30c1, 0x11cf, 0xa7, 0xeb, 0x00, 0x00, 0xc0, 0x5b, 0xae, 0x0b); +typedef struct IWebBrowser IWebBrowser, *LPWEBBROWSER; + +DEFINE_GUID(CLSID_WebBrowser, 0x8856f961, 0x340a, 0x11d0, 0xa9, 0x6b, 0x00, 0xc0, 0x4f, 0xd7, 0x05, 0xa2); + +/***************************************************************************** + * IWebBrowser interface + */ +#define ICOM_INTERFACE IWebBrowser +#define IWebBrowser_METHODS \ + ICOM_METHOD(HRESULT,GoBack) \ + ICOM_METHOD(HRESULT,GoForward) \ + ICOM_METHOD(HRESULT,GoHome) \ + ICOM_METHOD(HRESULT,GoSearch) \ + ICOM_METHOD5(HRESULT,Navigate, BSTR*,URL, VARIANT*,Flags, VARIANT*,TargetFrameName, \ + VARIANT*,PostData, VARIANT*,Headers) \ + ICOM_METHOD(HRESULT,Refresh) \ + ICOM_METHOD1(HRESULT,Refresh2, VARIANT*,Level) \ + ICOM_METHOD(HRESULT,Stop) \ + ICOM_METHOD1(HRESULT,get_Application, void**,ppDisp) \ + ICOM_METHOD1(HRESULT,get_Parent, void**,ppDisp) \ + ICOM_METHOD1(HRESULT,get_Container, void**,ppDisp) \ + ICOM_METHOD1(HRESULT,get_Document, void**,ppDisp) \ + ICOM_METHOD1(HRESULT,get_TopLevelContainer, VARIANT*,pBool) \ + ICOM_METHOD1(HRESULT,get_Type, BSTR*,Type) \ + ICOM_METHOD1(HRESULT,get_Left, long*,pl) \ + ICOM_METHOD1(HRESULT,put_Left, long,Left) \ + ICOM_METHOD1(HRESULT,get_Top, long*,pl) \ + ICOM_METHOD1(HRESULT,put_Top, long,Top) \ + ICOM_METHOD1(HRESULT,get_Width, long*,pl) \ + ICOM_METHOD1(HRESULT,put_Width, long,Width) \ + ICOM_METHOD1(HRESULT,get_Height, long*,pl) \ + ICOM_METHOD1(HRESULT,put_Height, long,Height) \ + ICOM_METHOD1(HRESULT,get_LocationName, BSTR*,LocationName) \ + ICOM_METHOD1(HRESULT,get_LocationURL, BSTR*,LocationURL) \ + ICOM_METHOD1(HRESULT,get_Busy, VARIANT*,pBool) +#define IWebBrowser_IMETHODS \ + IDispatch_METHODS \ + IWebBrowser_METHODS +ICOM_DEFINE(IWebBrowser,IDispatch) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define IWebBrowser_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define IWebBrowser_AddRef(p) ICOM_CALL (AddRef,p) +#define IWebBrowser_Release(p) ICOM_CALL (Release,p) +/*** IDispatch methods ***/ +#define IWebBrowser_GetTypeInfoCount(p,a) ICOM_CALL1 (GetTypeInfoCount,p,a) +#define IWebBrowser_GetTypeInfo(p,a,b,c) ICOM_CALL3 (GetTypeInfo,p,a,b,c) +#define IWebBrowser_GetIDsOfNames(p,a,b,c,d,e) ICOM_CALL5 (GetIDsOfNames,p,a,b,c,d,e) +#define IWebBrowser_Invoke(p,a,b,c,d,e,f,g,h) ICOM_CALL8 (Invoke,p,a,b,c,d,e,f,g,h) +/*** IWebBrowserContainer methods ***/ +#define IWebBrowser_GoBack(p,a) ICOM_CALL1(GoBack,p,a) +#define IWebBrowser_GoForward(p,a) ICOM_CALL1(GoForward,p,a) +#define IWebBrowser_GoHome(p,a) ICOM_CALL1(GoHome,p,a) +#define IWebBrowser_GoSearch(p,a) ICOM_CALL1(GoSearch,p,a) +#define IWebBrowser_Navigate(p,a) ICOM_CALL1(Navigate,p,a) +#define IWebBrowser_Refresh(p,a) ICOM_CALL1(Refresh,p,a) +#define IWebBrowser_Refresh2(p,a) ICOM_CALL1(Refresh2,p,a) +#define IWebBrowser_Stop(p,a) ICOM_CALL1(Stop,p,a) +#define IWebBrowser_get_Application(p,a) ICOM_CALL1(get_Application,p,a) +#define IWebBrowser_get_Parent(p,a) ICOM_CALL1(get_Parent,p,a) +#define IWebBrowser_get_Container(p,a) ICOM_CALL1(get_Container,p,a) +#define IWebBrowser_get_Document(p,a) ICOM_CALL1(get_Document,p,a) +#define IWebBrowser_get_TopLevelContainer(p,a) ICOM_CALL1(get_TopLevelContainer,p,a) +#define IWebBrowser_get_Type(p,a) ICOM_CALL1(get_Type,p,a) +#define IWebBrowser_get_Left(p,a) ICOM_CALL1(get_Left,p,a) +#define IWebBrowser_put_Left(p,a) ICOM_CALL1(put_Left,p,a) +#define IWebBrowser_get_Top(p,a) ICOM_CALL1(get_Top,p,a) +#define IWebBrowser_put_Top(p,a) ICOM_CALL1(put_Top,p,a) +#define IWebBrowser_get_Width(p,a) ICOM_CALL1(get_Width,p,a) +#define IWebBrowser_put_Width(p,a) ICOM_CALL1(put_Width,p,a) +#define IWebBrowser_get_Height(p,a) ICOM_CALL1(get_Height,p,a) +#define IWebBrowser_put_Height(p,a) ICOM_CALL1(put_Height,p,a) +#define IWebBrowser_get_LocationName(p,a) ICOM_CALL1(get_LocationName,p,a) +#define IWebBrowser_get_LocationURL(p,a) ICOM_CALL1(get_LocationURL,p,a) +#define IWebBrowser_get_Busy(p,a) ICOM_CALL1(get_Busy,p,a) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_WINE_OBJ_WEBBROWSER_H */ diff --git a/include/ole32/objbase.h b/include/ole32/objbase.h new file mode 100644 index 0000000..d2f7cf7 --- /dev/null +++ b/include/ole32/objbase.h @@ -0,0 +1,122 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include\ole32\objbase.h + * PURPOSE: Header file for the ole32.dll implementation + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#ifndef _OBJBASE +#define _OBJBASE + +#include "guiddef.h" + +#ifndef EXTERN_C + #ifdef __cplusplus + #define EXTERN_C extern "C" + #else + #define EXTERN_C extern + #endif +#endif + +#define STDMETHODCALLTYPE __stdcall +#define STDMETHODVCALLTYPE __cdecl + +#define STDAPICALLTYPE __stdcall +#define STDAPIVCALLTYPE __cdecl + + +#define STDAPI EXTERN_C HRESULT STDMETHODCALLTYPE +#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE + +#define STDMETHODIMP HRESULT STDMETHODCALLTYPE +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE + + +// variable argument lists versions +#define STDAPIV EXTERN_C HRESULT STDAPIVCALLTYPE +#define STDAPIV_(type) EXTERN_C type STDAPIVCALLTYPE + +#define STDMETHODIMPV HRESULT STDMETHODVCALLTYPE +#define STDMETHODIMPV_(type) type STDMETHODVCALLTYPE + +#ifndef WINOLEAPI + #define WINOLEAPI STDAPI + #define WINOLEAPI_(type) STDAPI_(type) +#endif + +// +// COM interface declaration macros [from the wine implementation +// +// These macros declare interfaces for both C and C++ depending for what +// language you are compiling +// +// DECLARE_INTERFACE(iface): declare not derived interface +// DECLARE_INTERFACE(iface, baseiface): declare derived interface +// +// Use CINTERFACE if you want to force a c style interface declaration, +// else, the compiler will look at the source file extension +// +#if defined(__cplusplus) && !defined(CINTERFACE) + // define the c++ macros + #define interface struct + #define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method + #define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method + #define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method + #define STDMETHODV_(type,method) virtual type STDMETHODVCALLTYPE method + #define PURE = 0 + #define THIS_ + #define THIS + #define DECLARE_INTERFACE(iface) interface iface + #define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface + +#else + // define the c macros + #define interface struct + #define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE* method) + #define STDMETHOD_(type,method) type (STDMETHODCALLTYPE* method) + #define STDMETHODV(method) HRESULT (STDMETHODVCALLTYPE* method) + #define STDMETHODV_(type,method)type (STDMETHODVCALLTYPE* method) + #define PURE + #define THIS_ INTERFACE FAR* This, + #define THIS INTERFACE FAR* This + + #ifdef CONST_VTABLE + #define DECLARE_INTERFACE(iface) typedef interface iface { \ + const struct iface##Vtbl FAR* lpVtbl; \ + } iface; \ + typedef const struct iface##Vtbl iface##Vtbl; \ + const struct iface##Vtbl + #else + #define DECLARE_INTERFACE(iface) typedef interface iface { \ + struct iface##Vtbl FAR* lpVtbl; \ + } iface; \ + typedef struct iface##Vtbl iface##Vtbl; \ + struct iface##Vtbl + #endif + + #define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface) +#endif + +#endif diff --git a/include/ole32/ole32.h b/include/ole32/ole32.h new file mode 100644 index 0000000..89cad83 --- /dev/null +++ b/include/ole32/ole32.h @@ -0,0 +1,45 @@ +#ifndef ___OLE32_H +#define ___OLE32_H + +#include +#include "wtypes.h" +#include "objbase.h" +#include "obj_base.h" +#include "obj_misc.h" + +#include "obj_storage.h" +#include "obj_moniker.h" +#include "obj_clientserver.h" +#include "obj_dataobject.h" +#include "obj_dragdrop.h" +#include "obj_inplace.h" +#include "obj_oleobj.h" +#include "obj_oleview.h" +#include "obj_cache.h" +#include "obj_marshal.h" + +#include "rpc.h" + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +/* + * OLE version conversion declarations + */ + +typedef struct _OLESTREAM* LPOLESTREAM; +typedef struct _OLESTREAMVTBL { + DWORD CALLBACK (*Get)(LPOLESTREAM,LPSTR,DWORD); + DWORD CALLBACK (*Put)(LPOLESTREAM,LPSTR,DWORD); +} OLESTREAMVTBL; +typedef OLESTREAMVTBL* LPOLESTREAMVTBL; +typedef struct _OLESTREAM { + LPOLESTREAMVTBL lpstbl; +} OLESTREAM; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __OLE32_H */ diff --git a/include/ole32/olectl.h b/include/ole32/olectl.h new file mode 100644 index 0000000..f031597 --- /dev/null +++ b/include/ole32/olectl.h @@ -0,0 +1,34 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS COm library + * FILE: include\ole32\olectl.c + * PURPOSE: OLE control interfaces + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 31/12/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#include + +// Dll register functions +STDAPI DllRegisterServer(void); +STDAPI DllUnregisterServer(void); \ No newline at end of file diff --git a/include/ole32/rpc.h b/include/ole32/rpc.h new file mode 100644 index 0000000..5cec503 --- /dev/null +++ b/include/ole32/rpc.h @@ -0,0 +1,45 @@ +/************************************** + * RPC interface + * + */ +#ifndef __WINE_RPC_H +#define __WINE_RPC_H + +#if !defined(RPC_NO_WINDOWS_H) && !defined(__WINE__) +#include "windows.h" +#endif + +#define __RPC_FAR +#define __RPC_API WINAPI +#define __RPC_USER WINAPI +#define __RPC_STUB WINAPI +#define RPC_ENTRY WINAPI +typedef long RPC_STATUS; + +typedef void* I_RPC_HANDLE; + +#ifndef _GUID_DEFINED +#define _GUID_DEFINED +typedef struct _GUID +{ + DWORD Data1; + WORD Data2; + WORD Data3; + BYTE Data4[8]; +} GUID; +#endif + +#ifndef UUID_DEFINED +#define UUID_DEFINED +typedef GUID UUID; +#endif + +RPC_STATUS RPC_ENTRY UuidCreate(UUID *Uuid); + +#include "rpcdce.h" +/* #include "rpcnsi.h" */ +/* #include "rpcnterr.h" */ +/* #include "excpt.h" */ +//#include "winerror.h" + +#endif /*__WINE_RPC_H */ diff --git a/include/ole32/rpcdce.h b/include/ole32/rpcdce.h new file mode 100644 index 0000000..6698f40 --- /dev/null +++ b/include/ole32/rpcdce.h @@ -0,0 +1,14 @@ +#ifndef __WINE_RPCDCE_H +#define __WINE_RPCDCE_H + +typedef void* RPC_AUTH_IDENTITY_HANDLE; +typedef void* RPC_AUTHZ_HANDLE; +typedef void* RPC_IF_HANDLE; +typedef I_RPC_HANDLE RPC_BINDING_HANDLE; +typedef RPC_BINDING_HANDLE handle_t; +#define rpc_binding_handle_t RPC_BINDING_HANDLE +#define RPC_MGR_EPV void + +#include "rpcdcep.h" + +#endif /*__WINE_RPCDCE_H */ diff --git a/include/ole32/rpcdcep.h b/include/ole32/rpcdcep.h new file mode 100644 index 0000000..ac00524 --- /dev/null +++ b/include/ole32/rpcdcep.h @@ -0,0 +1,30 @@ +#ifndef __WINE_RPCDCEP_H +#define __WINE_RPCDCEP_H + + +typedef struct _RPC_VERSION { + unsigned short MajorVersion; + unsigned short MinorVersion; +} RPC_VERSION; + +typedef struct _RPC_SYNTAX_IDENTIFIER { + GUID SyntaxGUID; + RPC_VERSION SyntaxVersion; +} RPC_SYNTAX_IDENTIFIER, *PRPC_SYNTAX_IDENTIFIER; + +typedef struct _RPC_MESSAGE +{ + RPC_BINDING_HANDLE Handle; + unsigned long DataRepresentation; + void* Buffer; + unsigned int BufferLength; + unsigned int ProcNum; + PRPC_SYNTAX_IDENTIFIER TransferSyntax; + void* RpcInterfaceInformation; + void* ReservedForRuntime; + RPC_MGR_EPV* ManagerEpv; + void* ImportContext; + unsigned long RpcFlags; +} RPC_MESSAGE, *PRPC_MESSAGE; + +#endif /*__WINE_RPCDCE_H */ diff --git a/include/ole32/unknwn.h b/include/ole32/unknwn.h new file mode 100644 index 0000000..287e6a4 --- /dev/null +++ b/include/ole32/unknwn.h @@ -0,0 +1,37 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include\ole32\unknwn.h + * PURPOSE: Defines IUnknown and IClassFactory interface + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#ifndef _UNKNWN_H +#define _UNKNWN_H + +#include + + + +#endif \ No newline at end of file diff --git a/include/ole32/winerror.h b/include/ole32/winerror.h new file mode 100644 index 0000000..ac9a181 --- /dev/null +++ b/include/ole32/winerror.h @@ -0,0 +1,59 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: include\ole32\winerror.h + * PURPOSE: Defines windows error codes + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#ifndef _WINERROR_H +#define _WINERROR_H +#if 0 +// +// Return Code macros +// +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) +#define FAILED(Status) ((HRESULT)(Status)<0) + +// +// Success Codes +// +#define S_OK 0x00000000L +#define S_FALSE 0x00000001L + +// +// Error Codes +// +#define E_NOINTERFACE 0x80000004L +#define E_POINTER 0x80004003L +#define E_FAIL 0x80004005L +#define E_UNEXPECTED 0x8000FFFFL +#define CLASS_E_NOAGGREGATION 0x80040110L +#define CLASS_E_CLASSNOTAVAILABLE 0x80040111L +#define E_OUTOFMEMORY 0x8007000EL +#define E_INVALIDARG 0x80070057L + +#endif + +#endif \ No newline at end of file diff --git a/include/ole32/wtypes.h b/include/ole32/wtypes.h new file mode 100644 index 0000000..98c31d7 --- /dev/null +++ b/include/ole32/wtypes.h @@ -0,0 +1,208 @@ +/* + * Defines the basic types used by COM interfaces. + */ + +#ifndef __WINE_WTYPES_H +#define __WINE_WTYPES_H + +#if 0 +#include "basetsd.h" +#include "guiddef.h" +#include "rpc.h" +#include "rpcndr.h" +#endif +#include +#include +#include + + +typedef void* HMETAFILEPICT; + +typedef WORD CLIPFORMAT, *LPCLIPFORMAT; + +/* FIXME: does not belong here */ +typedef CHAR OLECHAR16; +typedef LPSTR LPOLESTR16; +typedef LPCSTR LPCOLESTR16; +typedef OLECHAR16 *BSTR16; +typedef BSTR16 *LPBSTR16; +#define OLESTR16(x) x + +typedef WCHAR OLECHAR; +typedef LPWSTR LPOLESTR; +typedef LPCWSTR LPCOLESTR; +typedef OLECHAR *BSTR; +typedef BSTR *LPBSTR; +#ifndef __WINE__ +#define OLESTR(str) WINE_UNICODE_TEXT(str) +#endif + +typedef enum tagDVASPECT +{ + DVASPECT_CONTENT = 1, + DVASPECT_THUMBNAIL = 2, + DVASPECT_ICON = 4, + DVASPECT_DOCPRINT = 8 +} DVASPECT; + +typedef enum tagSTGC +{ + STGC_DEFAULT = 0, + STGC_OVERWRITE = 1, + STGC_ONLYIFCURRENT = 2, + STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4, + STGC_CONSOLIDATE = 8 +} STGC; + +typedef enum tagSTGMOVE +{ + STGMOVE_MOVE = 0, + STGMOVE_COPY = 1, + STGMOVE_SHALLOWCOPY = 2 +} STGMOVE; + + +typedef struct _COAUTHIDENTITY +{ + USHORT* User; + ULONG UserLength; + USHORT* Domain; + ULONG DomainLength; + USHORT* Password; + ULONG PasswordLength; + ULONG Flags; +} COAUTHIDENTITY; + +typedef struct _COAUTHINFO +{ + DWORD dwAuthnSvc; + DWORD dwAuthzSvc; + LPWSTR pwszServerPrincName; + DWORD dwAuthnLevel; + DWORD dwImpersonationLevel; + COAUTHIDENTITY* pAuthIdentityData; + DWORD dwCapabilities; +} COAUTHINFO; + +typedef struct _COSERVERINFO +{ + DWORD dwReserved1; + LPWSTR pwszName; + COAUTHINFO* pAuthInfo; + DWORD dwReserved2; +} COSERVERINFO; + +typedef enum tagCLSCTX +{ + CLSCTX_INPROC_SERVER = 0x1, + CLSCTX_INPROC_HANDLER = 0x2, + CLSCTX_LOCAL_SERVER = 0x4, + CLSCTX_INPROC_SERVER16 = 0x8, + CLSCTX_REMOTE_SERVER = 0x10, + CLSCTX_INPROC_HANDLER16 = 0x20, + CLSCTX_INPROC_SERVERX86 = 0x40, + CLSCTX_INPROC_HANDLERX86 = 0x80, + CLSCTX_ESERVER_HANDLER = 0x100 +} CLSCTX; + +#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER) +#define CLSCTX_ALL (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER) +#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER) + +typedef enum tagMSHLFLAGS +{ + MSHLFLAGS_NORMAL = 0, + MSHLFLAGS_TABLESTRONG = 1, + MSHLFLAGS_TABLEWEAK = 2, + MSHLFLAGS_NOPING = 4 +} MSHLFLAGS; + +typedef enum tagMSHCTX +{ + MSHCTX_LOCAL = 0, + MSHCTX_NOSHAREDMEM = 1, + MSHCTX_DIFFERENTMACHINE = 2, + MSHCTX_INPROC = 3 +} MSHCTX; + +typedef unsigned short VARTYPE; + +typedef ULONG PROPID; + +#ifndef _tagCY_DEFINED +#define _tagCY_DEFINED + +typedef union tagCY { + struct { +#ifdef BIG_ENDIAN + LONG Hi; + LONG Lo; +#else /* defined(BIG_ENDIAN) */ + ULONG Lo; + LONG Hi; +#endif /* defined(BIG_ENDIAN) */ + } DUMMYSTRUCTNAME; + LONGLONG int64; +} CY; + +#endif /* _tagCY_DEFINED */ + +typedef struct tagDEC { + USHORT wReserved; + union { + struct { + BYTE scale; + BYTE sign; + } DUMMYSTRUCTNAME1; + USHORT signscale; + } DUMMYUNIONNAME1; + ULONG Hi32; + union { + struct { +#ifdef BIG_ENDIAN + ULONG Mid32; + ULONG Lo32; +#else /* defined(BIG_ENDIAN) */ + ULONG Lo32; + ULONG Mid32; +#endif /* defined(BIG_ENDIAN) */ + } DUMMYSTRUCTNAME2; + ULONGLONG Lo64; + } DUMMYUNIONNAME2; +} DECIMAL; + +#define DECIMAL_NEG ((BYTE)0x80) +#ifndef NONAMELESSUNION +#define DECIMAL_SETZERO(d) \ + do {(d).Lo64 = 0; (d).Hi32 = 0; (d).signscale = 0;} while (0) +#else +#define DECIMAL_SETZERO(d) \ + do {(d).u2.Lo64 = 0; (d).Hi32 = 0; (d).u1.signscale = 0;} while (0) +#endif + +/* + * 0 == FALSE and -1 == TRUE + */ +#define VARIANT_TRUE ((VARIANT_BOOL)0xFFFF) +#define VARIANT_FALSE ((VARIANT_BOOL)0x0000) +typedef short VARIANT_BOOL,_VARIANT_BOOL; + +typedef struct tagCLIPDATA +{ + ULONG cbSize; + long ulClipFmt; + BYTE *pClipData; +} CLIPDATA; + +/* Macro to calculate the size of the above pClipData */ +#define CBPCLIPDATA(clipdata) ( (clipdata).cbSize - sizeof((clipdata).ulClipFmt) ) + +typedef LONG SCODE; + +#ifndef _ROTFLAGS_DEFINED +#define _ROTFLAGS_DEFINED +#define ROTFLAGS_REGISTRATIONKEEPSALIVE 0x1 +#define ROTFLAGS_ALLOWANYCLIENT 0x2 +#endif /* !defined(_ROTFLAGS_DEFINED) */ + +#endif /* __WINE_WTYPES_H */ diff --git a/include/pe.h b/include/pe.h new file mode 100644 index 0000000..0905542 --- /dev/null +++ b/include/pe.h @@ -0,0 +1,1065 @@ +#ifndef __INCLUDE_PE_H +#define __INCLUDE_PE_H + +#define _ANONYMOUS_UNION __extension__ +#define _ANONYMOUS_STRUCT __extension__ +#define NTAPI + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) + +#define IMAGE_SECTION_CHAR_CODE 0x00000020 +#define IMAGE_SECTION_CHAR_DATA 0x00000040 +#define IMAGE_SECTION_CHAR_BSS 0x00000080 +#define IMAGE_SECTION_CHAR_NON_CACHABLE 0x04000000 +#define IMAGE_SECTION_CHAR_NON_PAGEABLE 0x08000000 +#define IMAGE_SECTION_CHAR_SHARED 0x10000000 +#define IMAGE_SECTION_CHAR_EXECUTABLE 0x20000000 +#define IMAGE_SECTION_CHAR_READABLE 0x40000000 +#define IMAGE_SECTION_CHAR_WRITABLE 0x80000000 +#define IMAGE_SECTION_NOLOAD 0x00000002 + +#define IMAGE_DOS_MAGIC 0x5a4d +#define IMAGE_PE_MAGIC 0x00004550 + +#define IMAGE_DOS_SIGNATURE 0x5a4d +#define IMAGE_OS2_SIGNATURE 0x454e + +#define IMAGE_OS2_SIGNATURE_LE 0x454c +#define IMAGE_VXD_SIGNATURE 0x454c +#define IMAGE_NT_SIGNATURE 0x00004550 + + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0x160 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_R10000 0x168 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian + + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_OS2_GUI 4 +#define IMAGE_SUBSYSTEM_OS2_CUI 5 +#define IMAGE_SUBSYSTEM_POSIX_GUI 6 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 + + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address +// +// Section header format. +// +#define IMAGE_SIZEOF_FILE_HEADER 20 +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_NT_SIGNATURE 0x00004550 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 +#define IMAGE_SIZEOF_SHORT_NAME 8 +#define IMAGE_SIZEOF_SECTION_HEADER 40 +#define IMAGE_SIZEOF_SYMBOL 18 +#define IMAGE_SIZEOF_AUX_SYMBOL 18 +#define IMAGE_SIZEOF_RELOCATION 10 +#define IMAGE_SIZEOF_BASE_RELOCATION 8 +#define IMAGE_SIZEOF_LINENUMBER 6 +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 +#define SIZEOF_RFPO_DATA 16 +#define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader)) +#define IMAGE_SCN_TYPE_NO_PAD 8 +#define IMAGE_SCN_CNT_CODE 32 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 64 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 128 +#define IMAGE_SCN_LNK_OTHER 256 +#define IMAGE_SCN_LNK_INFO 512 +#define IMAGE_SCN_LNK_REMOVE 2048 +#define IMAGE_SCN_LNK_COMDAT 4096 +#define IMAGE_SCN_MEM_FARDATA 0x8000 +#define IMAGE_SCN_MEM_PURGEABLE 0x20000 +#define IMAGE_SCN_MEM_16BIT 0x20000 +#define IMAGE_SCN_MEM_LOCKED 0x40000 +#define IMAGE_SCN_MEM_PRELOAD 0x80000 +#define IMAGE_SCN_ALIGN_1BYTES 0x100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x700000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x1000000 +#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x4000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x8000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 +#define IMAGE_SYM_UNDEFINED 0 +#define IMAGE_SYM_ABSOLUTE (-1) +#define IMAGE_SYM_DEBUG (-2) +#define IMAGE_SYM_TYPE_NULL 0 +#define IMAGE_SYM_TYPE_VOID 1 +#define IMAGE_SYM_TYPE_CHAR 2 +#define IMAGE_SYM_TYPE_SHORT 3 +#define IMAGE_SYM_TYPE_INT 4 +#define IMAGE_SYM_TYPE_LONG 5 +#define IMAGE_SYM_TYPE_FLOAT 6 +#define IMAGE_SYM_TYPE_DOUBLE 7 +#define IMAGE_SYM_TYPE_STRUCT 8 +#define IMAGE_SYM_TYPE_UNION 9 +#define IMAGE_SYM_TYPE_ENUM 10 +#define IMAGE_SYM_TYPE_MOE 11 +#define IMAGE_SYM_TYPE_BYTE 12 +#define IMAGE_SYM_TYPE_WORD 13 +#define IMAGE_SYM_TYPE_UINT 14 +#define IMAGE_SYM_TYPE_DWORD 15 +#define IMAGE_SYM_TYPE_PCODE 32768 +#define IMAGE_SYM_DTYPE_NULL 0 +#define IMAGE_SYM_DTYPE_POINTER 1 +#define IMAGE_SYM_DTYPE_FUNCTION 2 +#define IMAGE_SYM_DTYPE_ARRAY 3 +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (-1) +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_FAR_EXTERNAL 68 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 +#define IMAGE_COMDAT_SELECT_LARGEST 6 +#define IMAGE_COMDAT_SELECT_NEWEST 7 +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 +#define IMAGE_REL_I386_ABSOLUTE 0 +#define IMAGE_REL_I386_DIR16 1 +#define IMAGE_REL_I386_REL16 2 +#define IMAGE_REL_I386_DIR32 6 +#define IMAGE_REL_I386_DIR32NB 7 +#define IMAGE_REL_I386_SEG12 9 +#define IMAGE_REL_I386_SECTION 10 +#define IMAGE_REL_I386_SECREL 11 +#define IMAGE_REL_I386_REL32 20 +#define IMAGE_REL_MIPS_ABSOLUTE 0 +#define IMAGE_REL_MIPS_REFHALF 1 +#define IMAGE_REL_MIPS_REFWORD 2 +#define IMAGE_REL_MIPS_JMPADDR 3 +#define IMAGE_REL_MIPS_REFHI 4 +#define IMAGE_REL_MIPS_REFLO 5 +#define IMAGE_REL_MIPS_GPREL 6 +#define IMAGE_REL_MIPS_LITERAL 7 +#define IMAGE_REL_MIPS_SECTION 10 +#define IMAGE_REL_MIPS_SECREL 11 +#define IMAGE_REL_MIPS_SECRELLO 12 +#define IMAGE_REL_MIPS_SECRELHI 13 +#define IMAGE_REL_MIPS_REFWORDNB 34 +#define IMAGE_REL_MIPS_PAIR 35 +#define IMAGE_REL_ALPHA_ABSOLUTE 0 +#define IMAGE_REL_ALPHA_REFLONG 1 +#define IMAGE_REL_ALPHA_REFQUAD 2 +#define IMAGE_REL_ALPHA_GPREL32 3 +#define IMAGE_REL_ALPHA_LITERAL 4 +#define IMAGE_REL_ALPHA_LITUSE 5 +#define IMAGE_REL_ALPHA_GPDISP 6 +#define IMAGE_REL_ALPHA_BRADDR 7 +#define IMAGE_REL_ALPHA_HINT 8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 9 +#define IMAGE_REL_ALPHA_REFHI 10 +#define IMAGE_REL_ALPHA_REFLO 11 +#define IMAGE_REL_ALPHA_PAIR 12 +#define IMAGE_REL_ALPHA_MATCH 13 +#define IMAGE_REL_ALPHA_SECTION 14 +#define IMAGE_REL_ALPHA_SECREL 15 +#define IMAGE_REL_ALPHA_REFLONGNB 16 +#define IMAGE_REL_ALPHA_SECRELLO 17 +#define IMAGE_REL_ALPHA_SECRELHI 18 +#define IMAGE_REL_PPC_ABSOLUTE 0 +#define IMAGE_REL_PPC_ADDR64 1 +#define IMAGE_REL_PPC_ADDR32 2 +#define IMAGE_REL_PPC_ADDR24 3 +#define IMAGE_REL_PPC_ADDR16 4 +#define IMAGE_REL_PPC_ADDR14 5 +#define IMAGE_REL_PPC_REL24 6 +#define IMAGE_REL_PPC_REL14 7 +#define IMAGE_REL_PPC_TOCREL16 8 +#define IMAGE_REL_PPC_TOCREL14 9 +#define IMAGE_REL_PPC_ADDR32NB 10 +#define IMAGE_REL_PPC_SECREL 11 +#define IMAGE_REL_PPC_SECTION 12 +#define IMAGE_REL_PPC_IFGLUE 13 +#define IMAGE_REL_PPC_IMGLUE 14 +#define IMAGE_REL_PPC_SECREL16 15 +#define IMAGE_REL_PPC_REFHI 16 +#define IMAGE_REL_PPC_REFLO 17 +#define IMAGE_REL_PPC_PAIR 18 +#define IMAGE_REL_PPC_TYPEMASK 255 +#define IMAGE_REL_PPC_NEG 256 +#define IMAGE_REL_PPC_BRTAKEN 512 +#define IMAGE_REL_PPC_BRNTAKEN 1024 +#define IMAGE_REL_PPC_TOCDEFN 2048 +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(o) ((o&IMAGE_ORDINAL_FLAG)!=0) +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_FPO 3 +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 + + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SECTION_CODE (0x20) +#define IMAGE_SECTION_INITIALIZED_DATA (0x40) +#define IMAGE_SECTION_UNINITIALIZED_DATA (0x80) + +#pragma pack(push,4) +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; +typedef struct _IMAGE_OPTIONAL_HEADER { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Reserved1; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + DWORD BaseOfBss; + DWORD GprMask; + DWORD CprMask[4]; + DWORD GpValue; +} IMAGE_ROM_OPTIONAL_HEADER,*PIMAGE_ROM_OPTIONAL_HEADER; +#pragma pack(pop) +#pragma pack(push,2) +typedef struct _IMAGE_DOS_HEADER { + WORD e_magic; + WORD e_cblp; + WORD e_cp; + WORD e_crlc; + WORD e_cparhdr; + WORD e_minalloc; + WORD e_maxalloc; + WORD e_ss; + WORD e_sp; + WORD e_csum; + WORD e_ip; + WORD e_cs; + WORD e_lfarlc; + WORD e_ovno; + WORD e_res[4]; + WORD e_oemid; + WORD e_oeminfo; + WORD e_res2[10]; + LONG e_lfanew; +} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; +typedef struct _IMAGE_OS2_HEADER { + WORD ne_magic; + CHAR ne_ver; + CHAR ne_rev; + WORD ne_enttab; + WORD ne_cbenttab; + LONG ne_crc; + WORD ne_flags; + WORD ne_autodata; + WORD ne_heap; + WORD ne_stack; + LONG ne_csip; + LONG ne_sssp; + WORD ne_cseg; + WORD ne_cmod; + WORD ne_cbnrestab; + WORD ne_segtab; + WORD ne_rsrctab; + WORD ne_restab; + WORD ne_modtab; + WORD ne_imptab; + LONG ne_nrestab; + WORD ne_cmovent; + WORD ne_align; + WORD ne_cres; + BYTE ne_exetyp; + BYTE ne_flagsothers; + WORD ne_pretthunks; + WORD ne_psegrefbytes; + WORD ne_swaparea; + WORD ne_expver; +} IMAGE_OS2_HEADER,*PIMAGE_OS2_HEADER; +#pragma pack(pop) +#pragma pack(push,4) +typedef struct _IMAGE_NT_HEADERS { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS; +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS,*PIMAGE_ROM_HEADERS; +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; +#pragma pack(pop) +#pragma pack(push,2) +typedef struct _IMAGE_SYMBOL { + union { + BYTE ShortName[8]; + struct { + DWORD Short; + DWORD Long; + } Name; + PBYTE LongName[2]; + } N; + DWORD Value; + SHORT SectionNumber; + WORD Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} IMAGE_SYMBOL,*PIMAGE_SYMBOL; +typedef union _IMAGE_AUX_SYMBOL { + struct { + DWORD TagIndex; + union { + struct { + WORD Linenumber; + WORD Size; + } LnSz; + DWORD TotalSize; + } Misc; + union { + struct { + DWORD PointerToLinenumber; + DWORD PointerToNextFunction; + } Function; + struct { + WORD Dimension[4]; + } Array; + } FcnAry; + WORD TvIndex; + } Sym; + struct { + BYTE Name[IMAGE_SIZEOF_SYMBOL]; + } File; + struct { + DWORD Length; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD CheckSum; + SHORT Number; + BYTE Selection; + } Section; +} IMAGE_AUX_SYMBOL,*PIMAGE_AUX_SYMBOL; +typedef struct _IMAGE_COFF_SYMBOLS_HEADER { + DWORD NumberOfSymbols; + DWORD LvaToFirstSymbol; + DWORD NumberOfLinenumbers; + DWORD LvaToFirstLinenumber; + DWORD RvaToFirstByteOfCode; + DWORD RvaToLastByteOfCode; + DWORD RvaToFirstByteOfData; + DWORD RvaToLastByteOfData; +} IMAGE_COFF_SYMBOLS_HEADER,*PIMAGE_COFF_SYMBOLS_HEADER; +typedef struct _IMAGE_RELOCATION { + _ANONYMOUS_UNION union { + DWORD VirtualAddress; + DWORD RelocCount; + } DUMMYUNIONNAME; + DWORD SymbolTableIndex; + WORD Type; +} IMAGE_RELOCATION,*PIMAGE_RELOCATION; +#pragma pack(pop) +#pragma pack(push,4) +typedef struct _IMAGE_BASE_RELOCATION { + DWORD VirtualAddress; + DWORD SizeOfBlock; +} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; +#pragma pack(pop) +#pragma pack(push,2) +typedef struct _IMAGE_LINENUMBER { + union { + DWORD SymbolTableIndex; + DWORD VirtualAddress; + } Type; + WORD Linenumber; +} IMAGE_LINENUMBER,*PIMAGE_LINENUMBER; +#pragma pack(pop) +#pragma pack(push,4) +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + BYTE Name[16]; + BYTE Date[12]; + BYTE UserID[6]; + BYTE GroupID[6]; + BYTE Mode[8]; + BYTE Size[10]; + BYTE EndHeader[2]; +} IMAGE_ARCHIVE_MEMBER_HEADER,*PIMAGE_ARCHIVE_MEMBER_HEADER; +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + PDWORD *AddressOfFunctions; + PDWORD *AddressOfNames; + PWORD *AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; +typedef struct _IMAGE_IMPORT_BY_NAME { + WORD Hint; + BYTE Name[1]; +} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; +typedef struct _IMAGE_THUNK_DATA { + union { + PBYTE ForwarderString; + PDWORD Function; + DWORD Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA,*PIMAGE_THUNK_DATA; +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + _ANONYMOUS_UNION union { + DWORD Characteristics; + PIMAGE_THUNK_DATA OriginalFirstThunk; + } DUMMYUNIONNAME; + DWORD TimeDateStamp; + DWORD ForwarderChain; + DWORD Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; +typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR { + DWORD TimeDateStamp; + WORD OffsetModuleName; + WORD NumberOfModuleForwarderRefs; +} IMAGE_BOUND_IMPORT_DESCRIPTOR,*PIMAGE_BOUND_IMPORT_DESCRIPTOR; +typedef struct _IMAGE_BOUND_FORWARDER_REF { + DWORD TimeDateStamp; + WORD OffsetModuleName; + WORD Reserved; +} IMAGE_BOUND_FORWARDER_REF,*PIMAGE_BOUND_FORWARDER_REF; +typedef void(NTAPI *PIMAGE_TLS_CALLBACK)(PVOID,DWORD,PVOID); +typedef struct _IMAGE_TLS_DIRECTORY { + DWORD StartAddressOfRawData; + DWORD EndAddressOfRawData; + PDWORD AddressOfIndex; + PIMAGE_TLS_CALLBACK *AddressOfCallBacks; + DWORD SizeOfZeroFill; + DWORD Characteristics; +} IMAGE_TLS_DIRECTORY,*PIMAGE_TLS_DIRECTORY; +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; +} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY; +/*_ANONYMOUS_STRUCT typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + _ANONYMOUS_UNION union { + _ANONYMOUS_STRUCT struct { + DWORD NameOffset:31; + DWORD NameIsString:1; + }DUMMYSTRUCTNAME; + DWORD Name; + WORD Id; + } DUMMYUNIONNAME; + _ANONYMOUS_UNION union { + DWORD OffsetToData; + _ANONYMOUS_STRUCT struct { + DWORD OffsetToDirectory:31; + DWORD DataIsDirectory:1; + } DUMMYSTRUCTNAME2; + } DUMMYUNIONNAME2; +} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY; +*/ +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + WORD Length; + CHAR NameString[1]; +} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING; +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + WORD Length; + WCHAR NameString[1]; +} IMAGE_RESOURCE_DIR_STRING_U,*PIMAGE_RESOURCE_DIR_STRING_U; +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; +} IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY; +typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD GlobalFlagsClear; + DWORD GlobalFlagsSet; + DWORD CriticalSectionDefaultTimeout; + DWORD DeCommitFreeBlockThreshold; + DWORD DeCommitTotalFreeThreshold; + PVOID LockPrefixTable; + DWORD MaximumAllocationSize; + DWORD VirtualMemoryThreshold; + DWORD ProcessHeapFlags; + DWORD Reserved[4]; +} IMAGE_LOAD_CONFIG_DIRECTORY,*PIMAGE_LOAD_CONFIG_DIRECTORY; +typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { + DWORD BeginAddress; + DWORD EndAddress; + PVOID ExceptionHandler; + PVOID HandlerData; + DWORD PrologEndAddress; +} IMAGE_RUNTIME_FUNCTION_ENTRY,*PIMAGE_RUNTIME_FUNCTION_ENTRY; +typedef struct _IMAGE_DEBUG_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Type; + DWORD SizeOfData; + DWORD AddressOfRawData; + DWORD PointerToRawData; +} IMAGE_DEBUG_DIRECTORY,*PIMAGE_DEBUG_DIRECTORY; +typedef struct _FPO_DATA { + DWORD ulOffStart; + DWORD cbProcSize; + DWORD cdwLocals; + WORD cdwParams; + WORD cbProlog:8; + WORD cbRegs:3; + WORD fHasSEH:1; + WORD fUseBP:1; + WORD reserved:1; + WORD cbFrame:2; +} FPO_DATA,*PFPO_DATA; +typedef struct _IMAGE_DEBUG_MISC { + DWORD DataType; + DWORD Length; + BOOLEAN Unicode; + BYTE Reserved[3]; + BYTE Data[1]; +} IMAGE_DEBUG_MISC,*PIMAGE_DEBUG_MISC; +typedef struct _IMAGE_FUNCTION_ENTRY { + DWORD StartingAddress; + DWORD EndingAddress; + DWORD EndOfPrologue; +} IMAGE_FUNCTION_ENTRY,*PIMAGE_FUNCTION_ENTRY; +typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { + WORD Signature; + WORD Flags; + WORD Machine; + WORD Characteristics; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD NumberOfSections; + DWORD ExportedNamesSize; + DWORD DebugDirectorySize; + DWORD Reserved[3]; +} IMAGE_SEPARATE_DEBUG_HEADER,*PIMAGE_SEPARATE_DEBUG_HEADER; +#pragma pack(pop) + +// +// Import Format +// + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + + +// Predefined resource types ... there may be some more, but I don't have +// the information yet. .....sang cho..... + +#define RT_NEWRESOURCE 0x2000 +#define RT_ERROR 0x7fff +#define NEWBITMAP (RT_BITMAP|RT_NEWRESOURCE) +#define NEWMENU (RT_MENU|RT_NEWRESOURCE) +#define NEWDIALOG (RT_DIALOG|RT_NEWRESOURCE) + + +// +// Resource Format. +// + +// +// Resource directory consists of two counts, following by a variable length +// array of directory entries. The first count is the number of entries at +// beginning of the array that have actual names associated with each entry. +// The entries are in ascending order, case insensitive strings. The second +// count is the number of entries that immediately follow the named entries. +// This second count identifies the number of entries that have 16-bit integer +// Ids as their name. These entries are also sorted in ascending order. +// +// This structure allows fast lookup by either name or number, but for any +// given resource entry only one form of lookup is supported, not both. +// This is consistant with the syntax of the .RC file and the .RES file. +// + + +// +// Each directory contains the 32-bit Name of the entry and an offset, +// relative to the beginning of the resource directory of the data associated +// with this directory entry. If the name of the entry is an actual text +// string instead of an integer Id, then the high order bit of the name field +// is set to one and the low order 31-bits are an offset, relative to the +// beginning of the resource directory of the string, which is of type +// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the +// low-order 16-bits are the integer Id that identify this resource directory +// entry. If the directory entry is yet another resource directory (i.e. a +// subdirectory), then the high order bit of the offset field will be +// set to indicate this. Otherwise the high bit is clear and the offset +// field points to a resource data entry. +// +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + DWORD Name; + DWORD OffsetToData; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; +/* +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; + IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[0]; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; +*/ +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 + + + +// +// For resource directory entries that have actual string names, the Name +// field of the directory entry points to an object of the following type. +// All of these string objects are stored together after the last resource +// directory entry and before the first resource data object. This minimizes +// the impact of these variable length objects on the alignment of the fixed +// size directory entry objects. +// +/* defined above from mingw. ei +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + WORD Length; + CHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; + + +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + WORD Length; + WCHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; +*/ + +// +// Each resource data entry describes a leaf node in the resource directory +// tree. It contains an offset, relative to the beginning of the resource +// directory of the data for the resource, a size field that gives the number +// of bytes of data at that offset, a CodePage that should be used when +// decoding code point values within the resource data. Typically for new +// applications the code page would be the unicode code page. +// +/* ei +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; +*/ + +// Menu Resources ... added by .....sang cho.... + +// Menu resources are composed of a menu header followed by a sequential list +// of menu items. There are two types of menu items: pop-ups and normal menu +// itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with +// an empty name, zero ID, and zero flags. + +typedef struct _IMAGE_MENU_HEADER{ + WORD wVersion; // Currently zero + WORD cbHeaderSize; // Also zero +} IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER; + +typedef struct _IMAGE_POPUP_MENU_ITEM{ + WORD fItemFlags; + WCHAR szItemText[1]; +} IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM; + +typedef struct _IMAGE_NORMAL_MENU_ITEM{ + WORD fItemFlags; + WORD wMenuID; + WCHAR szItemText[1]; +} IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM; + +#define MI_GRAYED 0x0001 // GRAYED keyword +#define MI_INACTIVE 0x0002 // INACTIVE keyword +#define MI_BITMAP 0x0004 // BITMAP keyword +#define MI_OWNERDRAW 0x0100 // OWNERDRAW keyword +#define MI_CHECKED 0x0008 // CHECKED keyword +#define MI_POPUP 0x0010 // used internally +#define MI_MENUBARBREAK 0x0020 // MENUBARBREAK keyword +#define MI_MENUBREAK 0x0040 // MENUBREAK keyword +#define MI_ENDMENU 0x0080 // used internally + +// Dialog Box Resources .................. added by sang cho. + +// A dialog box is contained in a single resource and has a header and +// a portion repeated for each control in the dialog box. +// The item DWORD IStyle is a standard window style composed of flags found +// in WINDOWS.H. +// The default style for a dialog box is: +// WS_POPUP | WS_BORDER | WS_SYSMENU +// +// The itme marked "Name or Ordinal" are : +// If the first word is an 0xffff, the next two bytes contain an ordinal ID. +// Otherwise, the first one or more WORDS contain a double-null-terminated string. +// An empty string is represented by a single WORD zero in the first location. +// +// The WORD wPointSize and WCHAR szFontName entries are present if the FONT +// statement was included for the dialog box. This can be detected by checking +// the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these +// entries will be present. + +typedef struct _IMAGE_DIALOG_BOX_HEADER1{ + DWORD IStyle; + DWORD IExtendedStyle; // New for Windows NT + WORD nControls; // Number of Controls + WORD x; + WORD y; + WORD cx; + WORD cy; +// N_OR_O MenuName; // Name or Ordinal ID +// N_OR_O ClassName; // Name or Ordinal ID +// WCHAR szCaption[]; +// WORD wPointSize; // Only here if FONT set for dialog +// WCHAR szFontName[]; // This too +} IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER; + +typedef union _NAME_OR_ORDINAL{ // Name or Ordinal ID + struct _ORD_ID{ + WORD flgId; + WORD Id; + } ORD_ID; + WCHAR szName[1]; +} NAME_OR_ORDINAL, *PNAME_OR_ORDINAL; + +// The data for each control starts on a DWORD boundary (which may require +// some padding from the previous control), and its format is as follows: + +typedef struct _IMAGE_CONTROL_DATA{ + DWORD IStyle; + DWORD IExtendedStyle; + WORD x; + WORD y; + WORD cx; + WORD cy; + WORD wId; +// N_OR_O ClassId; +// N_OR_O Text; +// WORD nExtraStuff; +} IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA; + +#define BUTTON 0x80 +#define EDIT 0x81 +//#define STATIC 0x82 +#define LISTBOX 0x83 +#define SCROLLBAR 0x84 +#define COMBOBOX 0x85 + +// The various statements used in a dialog script are all mapped to these +// classes along with certain modifying styles. The values for these styles +// can be found in WINDOWS.H. All dialog controls have the default styles +// of WS_CHILD and WS_VISIBLE. A list of the default styles used follows: +// +// Statement Default Class Default Styles +// CONTROL None WS_CHILD|WS_VISIBLE +// LTEXT STATIC ES_LEFT +// RTEXT STATIC ES_RIGHT +// CTEXT STATIC ES_CENTER +// LISTBOX LISTBOX WS_BORDER|LBS_NOTIFY +// CHECKBOX BUTTON BS_CHECKBOX|WS_TABSTOP +// PUSHBUTTON BUTTON BS_PUSHBUTTON|WS_TABSTOP +// GROUPBOX BUTTON BS_GROUPBOX +// DEFPUSHBUTTON BUTTON BS_DFPUSHBUTTON|WS_TABSTOP +// RADIOBUTTON BUTTON BS_RADIOBUTTON +// AUTOCHECKBOX BUTTON BS_AUTOCHECKBOX +// AUTO3STATE BUTTON BS_AUTO3STATE +// AUTORADIOBUTTON BUTTON BS_AUTORADIOBUTTON +// PUSHBOX BUTTON BS_PUSHBOX +// STATE3 BUTTON BS_3STATE +// EDITTEXT EDIT ES_LEFT|WS_BORDER|WS_TABSTOP +// COMBOBOX COMBOBOX None +// ICON STATIC SS_ICON +// SCROLLBAR SCROLLBAR None +/// + +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_FPO 3 +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 + + + +// +// Debugging information can be stripped from an image file and placed +// in a separate .DBG file, whose file name part is the same as the +// image file name part (e.g. symbols for CMD.EXE could be stripped +// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED +// flag in the Characteristics field of the file header. The beginning of +// the .DBG file contains the following structure which captures certain +// information from the image file. This allows a debug to proceed even if +// the original image file is not accessable. This header is followed by +// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more +// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in +// the image file contain file offsets relative to the beginning of the +// .DBG file. +// +// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure +// is left in the image file, but not mapped. This allows a debugger to +// compute the name of the .DBG file, from the name of the image in the +// IMAGE_DEBUG_MISC structure. +// +/* ei +typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { + WORD Signature; + WORD Flags; + WORD Machine; + WORD Characteristics; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD NumberOfSections; + DWORD ExportedNamesSize; + DWORD DebugDirectorySize; + DWORD SectionAlignment; + DWORD Reserved[2]; +} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER; +*/ +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 + +#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000 +#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the + // old checksum didn't match. + +// +// End Image Format +// + +#define SIZE_OF_NT_SIGNATURE sizeof (DWORD) +#define MAXRESOURCENAME 13 + +/* global macros to define header offsets into file */ +/* offset to PE file signature */ +#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew)) + +/* DOS header identifies the NT PEFile signature dword + the PEFILE header exists just after that dword */ +#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE)) + +/* PE optional header is immediately after PEFile header */ +#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE + \ + sizeof (IMAGE_FILE_HEADER))) + +/* section headers are immediately after PE optional header */ +#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE + \ + sizeof (IMAGE_FILE_HEADER) + \ + sizeof (IMAGE_OPTIONAL_HEADER))) + +//#define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field)) +/* defined above ei +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((ULONG_PTR)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) +*/ + +#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue)) + +typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY +{ + DWORD dwRVAFunctionNameList; + DWORD dwUseless1; + DWORD dwUseless2; + DWORD dwRVAModuleName; + DWORD dwRVAFunctionAddressList; +} IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY; + +typedef struct _RELOCATION_DIRECTORY +{ + DWORD VirtualAddress; /* adresse virtuelle du bloc ou se font les relocations */ + DWORD SizeOfBlock; // taille de cette structure + des structures + // relocation_entry qui suivent (ces dernieres sont + // donc au nombre de (SizeOfBlock-8)/2 +} RELOCATION_DIRECTORY, *PRELOCATION_DIRECTORY; + +typedef struct _RELOCATION_ENTRY +{ + WORD TypeOffset; + // (TypeOffset >> 12) est le type + // (TypeOffset&0xfff) est l'offset dans le bloc +} RELOCATION_ENTRY, *PRELOCATION_ENTRY; + +#define TYPE_RELOC_ABSOLUTE 0 +#define TYPE_RELOC_HIGH 1 +#define TYPE_RELOC_LOW 2 +#define TYPE_RELOC_HIGHLOW 3 +#define TYPE_RELOC_HIGHADJ 4 +#define TYPE_RELOC_MIPS_JMPADDR 5 + +#endif /* __INCLUDE_PE_H */ diff --git a/include/reactos/.cvsignore b/include/reactos/.cvsignore new file mode 100644 index 0000000..173ec6d --- /dev/null +++ b/include/reactos/.cvsignore @@ -0,0 +1,2 @@ +buildno.h +bugcodes.h \ No newline at end of file diff --git a/include/reactos/config.h b/include/reactos/config.h new file mode 100644 index 0000000..dca2e9f --- /dev/null +++ b/include/reactos/config.h @@ -0,0 +1,39 @@ +#ifndef _INC_REACTOS_CONFIG_H +#define _INC_REACTOS_CONFIG_H +/* $Id$ */ +/* ReactOS global configuration options */ + +#define CONFIG_PROCESSOR_FAMILY_I386 386L +#define CONFIG_PROCESSOR_FAMILY_I486 486L +#define CONFIG_PROCESSOR_FAMILY_I586 586L +#define CONFIG_PROCESSOR_FAMILY_IPII 686L + +#define CONFIG_PROCESSOR_FAMILY_ALPHA 0x10000000 + +#define CONFIG_ARCHITECTURE_IBMPC 0x00000000 +/* + * Processor and architecture. + */ +#define CONFIG_PROCESSOR_FAMILY CONFIG_PROCESSOR_FAMILY_I586 +#define CONFIG_ARCHITECTURE CONFIG_ARCHITECTURE_IBMPC +/* + * Hardware page size + */ +#define CONFIG_MEMORY_PAGE_SIZE 4096 +/* + * Use __fastcall calling conventions when needed + * in system components that require it. + */ +//#define CONFIG_USE_FASTCALL +/* + * Enable debugging output on a per module + * base. + */ +#define DBG_NTOSKRNL_KE_MAIN +#define DBG_NTOSKRNL_MM_MM +#define DBG_NTOSKRNL_MM_NPOOL + +#define DBG_NTDLL_LDR_STARTUP +#define DBG_NTDLL_LDR_UTILS + +#endif /* ndef _INC_REACTOS_CONFIG_H */ diff --git a/include/reactos/resource.h b/include/reactos/resource.h new file mode 100644 index 0000000..57f09de --- /dev/null +++ b/include/reactos/resource.h @@ -0,0 +1,36 @@ +#ifndef _INC_REACTOS_RESOURCE_H +#define _INC_REACTOS_RESOURCE_H +#include "version.h" +#include "buildno.h" + +/* Global File Version UINTs */ + +#define RES_UINT_FV_MAJOR KERNEL_VERSION_MAJOR +#define RES_UINT_FV_MINOR KERNEL_VERSION_MINOR +#define RES_UINT_FV_REVISION KERNEL_VERSION_PATCH_LEVEL +/* Build number as generated by buildno.c */ +#define RES_UINT_FV_BUILD KERNEL_VERSION_BUILD + +/* ReactOS Product Version UINTs */ + +#define RES_UINT_PV_MAJOR KERNEL_VERSION_MAJOR +#define RES_UINT_PV_MINOR KERNEL_VERSION_MINOR +#define RES_UINT_PV_REVISION KERNEL_VERSION_PATCH_LEVEL +/* Build number as YYYYMMDD */ +#define RES_UINT_PV_BUILD 0 + +/* Common version strings for rc scripts */ + +#define RES_STR_COMPANY_NAME "ReactOS Development Team\0" +#define RES_STR_LEGAL_COPYRIGHT "Copyright (c) 1998-2002 ReactOS Team\0" +#define RES_STR_PRODUCT_NAME "ReactOS Operating System\0" +#define RES_STR_PRODUCT_VERSION KERNEL_VERSION_RC + +/* FILE_VERSION defaults to PRODUCT_VERSION */ +#define RES_STR_FILE_VERSION KERNEL_RELEASE_RC + +/* ReactOS default Application Registry Root Path */ +#define RES_STR_ROSAPP_REGISTRY_ROOT "Software\\ReactWare" + +#endif /* ndef _INC_REACTOS_RESOURCE_H */ + diff --git a/include/reactos/version.h b/include/reactos/version.h new file mode 100644 index 0000000..6c923d0 --- /dev/null +++ b/include/reactos/version.h @@ -0,0 +1,29 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/version.h + * PURPOSE: Defines the current version + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISIONS: + * 1999-11-06 (ea) + * Moved from include/internal in include/reactos + * to be used by buildno. + * 2002-01-17 (ea) + * KERNEL_VERSION removed. Use + * reactos/buildno.h:KERNEL_VERSION_STR instead. + */ + +#ifndef __VERSION_H +#define __VERSION_H + +#define KERNEL_VERSION_MAJOR 0 +#define KERNEL_VERSION_MINOR 0 +#define KERNEL_VERSION_PATCH_LEVEL 20 +/* Edit each time a new release is out: format is YYYYMMDD (UTC) */ +#define KERNEL_RELEASE_DATE 20020805L + + +#endif + +/* EOF */ diff --git a/include/services/services.h b/include/services/services.h new file mode 100644 index 0000000..b8c59c5 --- /dev/null +++ b/include/services/services.h @@ -0,0 +1,5 @@ +#ifndef __INCLUDE_SERVICES_SERVICES_H +#define __INCLUDE_SERVICES_SERVICES_H + + +#endif /* __INCLUDE_SERVICES_SERVICES_H */ diff --git a/include/services/services.idl b/include/services/services.idl new file mode 100644 index 0000000..f2d1fc4 --- /dev/null +++ b/include/services/services.idl @@ -0,0 +1,16 @@ +[ +uuid(?), +version(1.0), +pointer_default(?) +] +interface SCM +{ + handle_t SvcOpenSCManagerW([in, string] wchar_t* lpMachineName, + [in, string] wchar_t* lpDatabaseName, + [in] unsigned int dwDesiredAccess); + handle_t SvcOpenSCManagerA([in, string] char* lpMachineName, + [in, string] char* lpDatabaseName, + [in] unsigned int dwDesiredAccess); + bool SvcClose([in] handle_t hSCObject); +} + diff --git a/include/snmp.h b/include/snmp.h new file mode 100644 index 0000000..71bfb61 --- /dev/null +++ b/include/snmp.h @@ -0,0 +1,290 @@ +/* + * ReactOS Simple Network Management Protocol - SNMP + * + * snmp.h + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SNMP_H__ +#define __SNMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// SNMP Error Codes +// + +#define SNMP_MEM_ALLOC_ERROR 1 +#define SNMP_BERAPI_INVALID_LENGTH 10 +#define SNMP_BERAPI_INVALID_TAG 11 +#define SNMP_BERAPI_OVERFLOW 12 +#define SNMP_BERAPI_SHORT_BUFFER 13 +#define SNMP_BERAPI_INVALID_OBJELEM 14 +#define SNMP_PDUAPI_UNRECOGNIZED_PDU 20 +#define SNMP_PDUAPI_INVALID_ES 21 +#define SNMP_PDUAPI_INVALID_GT 22 +#define SNMP_AUTHAPI_INVALID_VERSION 30 +#define SNMP_AUTHAPI_INVALID_MSG_TYPE 31 +#define SNMP_AUTHAPI_TRIV_AUTH_FAILED 32 + +//////////////////////////////////////////////////////////////////////////////// +// SNMP Type Definitions +// + +#include + +typedef struct { + BYTE* stream; + UINT length; + BOOL dynamic; +} AsnOctetString; + +typedef struct { + UINT idLength; + UINT* ids; +} AsnObjectIdentifier; + +typedef LONG AsnInteger32; +typedef ULONG AsnUnsigned32; +typedef ULARGE_INTEGER AsnCounter64; +typedef AsnUnsigned32 AsnCounter32; +typedef AsnUnsigned32 AsnGauge32; +typedef AsnUnsigned32 AsnTimeticks; +typedef AsnOctetString AsnBits; +typedef AsnOctetString AsnSequence; +typedef AsnOctetString AsnImplicitSequence; +typedef AsnOctetString AsnIPAddress; +typedef AsnOctetString AsnNetworkAddress; +typedef AsnOctetString AsnDisplayString; +typedef AsnOctetString AsnOpaque; + +typedef struct { + BYTE asnType; + union { + AsnInteger32 number; // ASN_INTEGER & ASN_INTEGER32 + AsnUnsigned32 unsigned32; // ASN_UNSIGNED32 + AsnCounter64 counter64; // ASN_COUNTER64 + AsnOctetString string; // ASN_OCTETSTRING + AsnBits bits; // ASN_BITS + AsnObjectIdentifier object; // ASN_OBJECTIDENTIFIER + AsnSequence sequence; // ASN_SEQUENCE + AsnIPAddress address; // ASN_IPADDRESS + AsnCounter32 counter; // ASN_COUNTER32 + AsnGauge32 gauge; // ASN_GAUGE32 + AsnTimeticks ticks; // ASN_TIMETICKS + AsnOpaque arbitrary; // ASN_OPAQUE + } asnValue; +} AsnAny; + +typedef AsnObjectIdentifier AsnObjectName; +typedef AsnAny AsnObjectSyntax; + +typedef struct { + AsnObjectName name; + AsnObjectSyntax value; +} SnmpVarBind; + +typedef struct { + SnmpVarBind* list; + UINT len; +} SnmpVarBindList; + +#include + +//////////////////////////////////////////////////////////////////////////////// +// SNMP Function Prototypes +// + +#define SNMPAPI INT +#ifndef SNMP_FUNC_TYPE +#define SNMP_FUNC_TYPE +#endif + +//LPVOID SNMP_FUNC_TYPE SnmpUtilMemAlloc(UINT nBytes); +//VOID SNMP_FUNC_TYPE SnmpUtilMemFree(LPVOID pMem); +//SNMPAPI SNMP_FUNC_TYPE SnmpUtilOidCpy(AsnObjectIdentifier* pOidDst, AsnObjectIdentifier* pOidSrc); +//VOID SNMP_FUNC_TYPE SnmpUtilOidFree(AsnObjectIdentifier* pOid); +//VOID SNMP_FUNC_TYPE SnmpUtilVarBindFree(SnmpVarBind* pVb); + +LPVOID SNMP_FUNC_TYPE SnmpUtilMemAlloc( + UINT nBytes // bytes to allocate for object +); + +VOID SNMP_FUNC_TYPE SnmpUtilMemFree( + LPVOID pMem // pointer to memory object to release +); + +LPVOID SNMP_FUNC_TYPE SnmpUtilMemReAlloc( + LPVOID pMem, // pointer to memory object + UINT nBytes // bytes to allocate +); + +VOID SNMP_FUNC_TYPE SnmpSvcInitUptime(); + +DWORD SNMP_FUNC_TYPE SnmpSvcGetUptime(); + +VOID SNMP_FUNC_TYPE SnmpSvcSetLogLevel( + INT nLogLevel // level of severity of the event +); + +VOID SNMP_FUNC_TYPE SnmpSvcSetLogType( + INT nLogType // destination for debug output +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilAsnAnyCpy( + AsnAny *pAnyDst, // destination structure + AsnAny *pAnySrc // source structure +); + +VOID SNMP_FUNC_TYPE SnmpUtilAsnAnyFree( + AsnAny *pAny // pointer to structure to free +); + +//VOID SNMP_FUNC_TYPE SnmpUtilDbgPrint( +// INT nLogLevel, // level of severity of event +// LPSTR szFormat // pointer to a format string +//); + +LPSTR SNMP_FUNC_TYPE SnmpUtilIdsToA( + UINT *Ids, // object identifier to convert + UINT IdLength // number of elements +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOctetsCmp( + AsnOctetString *pOctets1, // first octet string + AsnOctetString *pOctets2 // second octet string +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOctetsCpy( + AsnOctetString *pOctetsDst, // destination octet string + AsnOctetString *pOctetsSrc // source octet string +); + +VOID SNMP_FUNC_TYPE SnmpUtilOctetsFree( + AsnOctetString *pOctets // octet string to free +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOctetsNCmp( + AsnOctetString *pOctets1, // first octet string + AsnOctetString *pOctets2, // second octet string + UINT nChars // maximum length to compare +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOidAppend( + AsnObjectIdentifier *pOidDst, // destination object identifier + AsnObjectIdentifier *pOidSrc // source object identifier +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOidCmp( + AsnObjectIdentifier *pOid1, // first object identifier + AsnObjectIdentifier *pOid2 // second object identifier +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOidCpy( + AsnObjectIdentifier *pOidDst, // destination object identifier + AsnObjectIdentifier *pOidSrc // source object identifier +); + +VOID SNMP_FUNC_TYPE SnmpUtilOidFree( + AsnObjectIdentifier *pOid // object identifier to free +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilOidNCmp( + AsnObjectIdentifier *pOid1, // first object identifier + AsnObjectIdentifier *pOid2, // second object identifier + UINT nSubIds // maximum length to compare +); + +LPSTR SNMP_FUNC_TYPE SnmpUtilOidToA( + AsnObjectIdentifier *Oid // object identifier to convert +); + +VOID SNMP_FUNC_TYPE SnmpUtilPrintAsnAny( + AsnAny *pAny // pointer to value to print +); + +VOID SNMP_FUNC_TYPE SnmpUtilPrintOid( + AsnObjectIdentifier *Oid // object identifier to print +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilVarBindCpy( + SnmpVarBind *pVbDst, // destination variable bindings + SnmpVarBind *pVbSrc // source variable bindings +); + +VOID SNMP_FUNC_TYPE SnmpUtilVarBindFree( + SnmpVarBind *pVb // variable binding to free +); + +SNMPAPI SNMP_FUNC_TYPE SnmpUtilVarBindListCpy( + SnmpVarBindList *pVblDst, // destination variable bindings list + SnmpVarBindList *pVblSrc // source variable bindings list +); + +VOID SNMP_FUNC_TYPE SnmpUtilVarBindListFree( + SnmpVarBindList *pVbl // variable bindings list to free +); + + + +//////////////////////////////////////////////////////////////////////////////// +// SNMP Debugging Definitions +// + +#define SNMP_LOG_SILENT 0x0 +#define SNMP_LOG_FATAL 0x1 +#define SNMP_LOG_ERROR 0x2 +#define SNMP_LOG_WARNING 0x3 +#define SNMP_LOG_TRACE 0x4 +#define SNMP_LOG_VERBOSE 0x5 + +#define SNMP_OUTPUT_TO_CONSOLE 0x1 +#define SNMP_OUTPUT_TO_LOGFILE 0x2 +//#define SNMP_OUTPUT_TO_EVENTLOG 0x4 // no longer supported +#define SNMP_OUTPUT_TO_DEBUGGER 0x8 + +//////////////////////////////////////////////////////////////////////////////// +// SNMP Debugging Prototypes +// + +VOID +SNMP_FUNC_TYPE +SnmpUtilDbgPrint( + IN INT nLogLevel, // see log levels above... + IN LPSTR szFormat, + IN ... + ); + +#if DBG +#define SNMPDBG(_x_) SnmpUtilDbgPrint _x_ +#else +#define SNMPDBG(_x_) +#endif + + +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +}; +#endif + +#endif // __SNMP_H__ + diff --git a/include/sockets.h b/include/sockets.h new file mode 100644 index 0000000..11a8f51 --- /dev/null +++ b/include/sockets.h @@ -0,0 +1,965 @@ +/* + Sockets.h + + Windows Sockets specification version 1.1 + + Copyright (C) 1996 Free Software Foundation, Inc. + Thanks to Linux header files for supplying many needed definitions + + Author: Scott Christley + Date: 1996 + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/*- + * Portions Copyright (c) 1980, 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +#ifndef _GNU_H_WINDOWS32_SOCKETS +#define _GNU_H_WINDOWS32_SOCKETS + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* BSD */ +#ifndef _SYS_TYPES_H +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +#endif + +/* + Default maximium number of sockets. + Define this before including Sockets.h to increase; this does not + mean that the underlying Windows Sockets implementation has to + support that many! + */ +#ifndef FD_SETSIZE +#define FD_SETSIZE 64 +#endif /* !FD_SETSIZE */ + +/* + These macros are critical to the usage of Windows Sockets. + According to the documentation, a SOCKET is no longer represented + by a "small non-negative integer"; so all programs MUST use these + macros for setting, initializing, clearing and checking the + fd_set structures. + */ + +typedef u_int SOCKET; + +/* fd_set may have been defined by the newlib . */ +#ifdef fd_set +#undef fd_set +#endif +typedef struct fd_set { + u_int fd_count; + SOCKET fd_array[FD_SETSIZE]; +} fd_set; + +/* Internal function, not documented except in winsock.h */ +extern int PASCAL __WSAFDIsSet(SOCKET, fd_set*); + +#ifdef FD_CLR +#undef FD_CLR +#endif +#define FD_CLR(fd, set) do { \ + u_int __i; \ + for (__i = 0; __i < ((fd_set*)(set))->fd_count ; __i++) { \ + if (((fd_set*)(set))->fd_array[__i] == fd) { \ + while (__i < ((fd_set*)(set))->fd_count-1) { \ + ((fd_set*)(set))->fd_array[__i] = \ + ((fd_set*)(set))->fd_array[__i+1]; \ + __i++; \ + } \ + ((fd_set*)(set))->fd_count--; \ + break; \ + } \ + } \ +} while(0) + +#ifdef FD_SET +#undef FD_SET +#endif +#define FD_SET(fd, set) do { \ + if (((fd_set*)(set))->fd_count < FD_SETSIZE) \ + ((fd_set*)(set))->fd_array[((fd_set*)(set))->fd_count++]=(fd);\ +} while(0) + +#ifdef FD_ZERO +#undef FD_ZERO +#endif +#define FD_ZERO(set) (((fd_set*)(set))->fd_count=0) + +#ifdef FD_ISSET +#undef FD_ISSET +#endif +#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set*)(set)) + +/* + time structures + */ +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +/* + Operations on timevals. + + NB: timercmp does not work for >= or <=. + */ +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) \ + || (tvp)->tv_sec cmp (uvp)->tv_sec) +#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) + +/* + ioctl command encoding. + Some of this is different than what Linux has + */ +#define IOCPARM_MASK 0x7f +#define IOC_VOID 0x20000000 +#define IOC_OUT 0x40000000 +#define IOC_IN 0x80000000 +#define IOC_INOUT (IOC_IN | IOC_OUT) + +/* _IO(magic, subcode) */ +#define _IO(c,d) (IOC_VOID | ((c)<<8) | (d)) +/* _IOXX(magic, subcode, arg_t) */ +#define _IOW(c,d,t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK)<<16) | \ + ((c)<<8) | (d)) +#define _IOR(c,d,t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK)<<16) | \ + ((c)<<8) | (d)) + +/* + This stuff is hard-coded on Linux + But winsock.h uses the macros defined above + */ +#define FIONREAD _IOR('f', 127, u_long) +#define FIONBIO _IOW('f', 126, u_long) +#define FIOASYNC _IOW('f', 125, u_long) + +#define SIOCSHIWAT _IOW('s', 0, u_long) +#define SIOCGHIWAT _IOR('s', 1, u_long) +#define SIOCSLOWAT _IOW('s', 2, u_long) +#define SIOCGLOWAT _IOR('s', 3, u_long) +#define SIOCATMARK _IOR('s', 7, u_long) + +/* + Structures returned by network data base library, taken from the + BSD file netdb.h. All addresses are supplied in host order, and + returned in network order (suitable for use in system calls). + + Slight modifications for differences between Linux and winsock.h + */ + +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + short h_addrtype; /* host address type */ + short h_length; /* length of address */ + char **h_addr_list; /* list of addresses */ +#define h_addr h_addr_list[0] /* address, for backward compat */ +}; + +/* + * Assumption here is that a network number + * fits in an unsigned long -- someday that won't be true! + */ +struct netent { + char *n_name; /* official name of net */ + char **n_aliases; /* alias list */ + short n_addrtype; /* net address type */ + u_long n_net; /* network # */ +}; + +struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + short s_port; /* port # */ + char *s_proto; /* protocol to use */ +}; + +struct protoent { + char *p_name; /* official protocol name */ + char **p_aliases; /* alias list */ + short p_proto; /* protocol # */ +}; + +/* + Standard well-known IP protocols. + For some reason there are differences between Linx and winsock.h + */ +enum { + IPPROTO_IP = 0, + IPPROTO_ICMP = 1, + IPPROTO_GGP = 2, /* huh? */ + IPPROTO_IPIP = 4, + IPPROTO_TCP = 6, /* Transmission Control Protocol */ + IPPROTO_EGP = 8, + IPPROTO_PUP = 12, + IPPROTO_UDP = 17, /* User Datagram Protocol */ + IPPROTO_IDP = 22, + IPPROTO_ND = 77, /* This one was in winsock.h */ + + IPPROTO_RAW = 255, /* raw IP packets */ + IPPROTO_MAX +}; + +/* Standard well-known ports */ +enum { + IPPORT_ECHO = 7, + IPPORT_DISCARD = 9, + IPPORT_SYSTAT = 11, + IPPORT_DAYTIME = 13, + IPPORT_NETSTAT = 15, + IPPORT_FTP = 21, + IPPORT_TELNET = 23, + IPPORT_SMTP = 25, + IPPORT_TIMESERVER = 37, + IPPORT_NAMESERVER = 42, + IPPORT_WHOIS = 43, + IPPORT_MTP = 57, + + IPPORT_TFTP = 69, + IPPORT_RJE = 77, + IPPORT_FINGER = 79, + IPPORT_TTYLINK = 87, + IPPORT_SUPDUP = 95, + + IPPORT_EXECSERVER = 512, + IPPORT_LOGINSERVER = 513, + IPPORT_CMDSERVER = 514, + IPPORT_EFSSERVER = 520, + + /* UDP ports. */ + IPPORT_BIFFUDP = 512, + IPPORT_WHOSERVER = 513, + IPPORT_ROUTESERVER = 520, + + /* Ports less than this value are reservered for privileged processes. */ + IPPORT_RESERVED = 1024, + + /* Ports greater than this value are reserved for + (non-privileged) processes */ + IPPORT_USERRESERVED = 5000 +}; + +/* Link numbers. */ +#define IMPLINK_IP 155 +#define IMPLINK_LOWEXPER 156 +#define IMPLINK_HIGHEXPER 158 + +/* Linux uses a simple unsigned long int, but winsock.h ... */ +struct in_addr { + union { + struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; + struct { u_short s_w1,s_w2; } S_un_w; + u_long S_addr; + } S_un; +#define s_addr S_un.S_addr +#define s_host S_un.S_un_b.s_b2 +#define s_net S_un.S_un_b.s_b1 +#define s_imp S_un.S_un_w.s_w2 +#define s_impno S_un.S_un_b.s_b4 +#define s_lh S_un.S_un_b.s_b3 +}; + +/* + Definitions of bits in internet address integers. + On subnets, host and network parts are found according + to the subnet mask, not these masks. + */ +#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0x000000ff + +#define INADDR_ANY (u_long)0x00000000 +#define INADDR_LOOPBACK 0x7f000001 +#define INADDR_BROADCAST (u_long)0xffffffff +#define INADDR_NONE 0xffffffff + +/* + Structure describing an Internet (IP) socket address. + */ +struct sockaddr_in { + short sin_family; + u_short sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +/* + EVERYTHING FROM THIS POINT IS MAINLY SPECIFIC TO Win32 + + Structure which holds the detail for the underlying Window Sockets + implementation. Set when WSAStartup() is called. + */ +#define WSADESCRIPTION_LEN 256 +#define WSASYS_STATUS_LEN 128 + +typedef struct WSAData { + WORD wVersion; + WORD wHighVersion; + char szDescription[WSADESCRIPTION_LEN+1]; + char szSystemStatus[WSASYS_STATUS_LEN+1]; + unsigned short iMaxSockets; + unsigned short iMaxUdpDg; + char *lpVendorInfo; +} WSADATA, *LPWSADATA; + +#define IP_OPTIONS 1 +#define IP_MULTICAST_IF 2 +#define IP_MULTICAST_TTL 3 +#define IP_MULTICAST_LOOP 4 +#define IP_ADD_MEMBERSHIP 5 +#define IP_DROP_MEMBERSHIP 6 + +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 +#define IP_MAX_MEMBERSHIPS 20 + +struct ip_mreq { + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; + +/* + * Definitions related to sockets: types, address families, options, + * taken from the BSD file sys/socket.h. + */ + +/* + * This is used instead of -1, since the + * SOCKET type is unsigned. + */ +#define INVALID_SOCKET (SOCKET)(~0) +#define SOCKET_ERROR (-1) + +/* Socket types. */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +#define SOCK_RDM 4 +#define SOCK_SEQPACKET 5 + +/* For setsockoptions(2) */ +#define SO_DEBUG 0x0001 +#define SO_ACCEPTCONN 0x0002 +#define SO_REUSEADDR 0x0004 +#define SO_KEEPALIVE 0x0008 +#define SO_DONTROUTE 0x0010 +#define SO_BROADCAST 0x0020 +#define SO_USELOOPBACK 0x0040 +#define SO_LINGER 0x0080 +#define SO_OOBINLINE 0x0100 + +#define SO_DONTLINGER (u_int)(~SO_LINGER) + +/* + * Additional options. + */ +#define SO_SNDBUF 0x1001 /* send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ + +/* + * Options for connect and disconnect data and options. Used only by + * non-TCP/IP transports such as DECNet, OSI TP4, etc. + */ +#define SO_CONNDATA 0x7000 +#define SO_CONNOPT 0x7001 +#define SO_DISCDATA 0x7002 +#define SO_DISCOPT 0x7003 +#define SO_CONNDATALEN 0x7004 +#define SO_CONNOPTLEN 0x7005 +#define SO_DISCDATALEN 0x7006 +#define SO_DISCOPTLEN 0x7007 + +/* + * Option for opening sockets for synchronous access. + */ +#define SO_OPENTYPE 0x7008 + +#define SO_SYNCHRONOUS_ALERT 0x10 +#define SO_SYNCHRONOUS_NONALERT 0x20 + +/* + * Other NT-specific options. + */ +#define SO_MAXDG 0x7009 +#define SO_MAXPATHDG 0x700A + +/* + * TCP options. + */ +#define TCP_NODELAY 0x0001 +#define TCP_BSDURGENT 0x7000 + +/* + * Address families. + */ +#define AF_UNSPEC 0 /* unspecified */ +#define AF_UNIX 1 /* local to host (pipes, portals) */ +#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ +#define AF_IMPLINK 3 /* arpanet imp addresses */ +#define AF_PUP 4 /* pup protocols: e.g. BSP */ +#define AF_CHAOS 5 /* mit CHAOS protocols */ +#define AF_IPX 6 /* IPX and SPX */ +#define AF_NS 6 /* XEROX NS protocols */ +#define AF_ISO 7 /* ISO protocols */ +#define AF_OSI AF_ISO /* OSI is ISO */ +#define AF_ECMA 8 /* european computer manufacturers */ +#define AF_DATAKIT 9 /* datakit protocols */ +#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ +#define AF_SNA 11 /* IBM SNA */ +#define AF_DECnet 12 /* DECnet */ +#define AF_DLI 13 /* Direct data link interface */ +#define AF_LAT 14 /* LAT */ +#define AF_HYLINK 15 /* NSC Hyperchannel */ +#define AF_APPLETALK 16 /* AppleTalk */ +#define AF_NETBIOS 17 /* NetBios-style addresses */ + +#define AF_MAX 18 + +/* + * Structure used by kernel to store most + * addresses. + */ +struct sockaddr { + u_short sa_family; + char sa_data[14]; +}; + +/* + * Structure used by kernel to pass protocol + * information in raw sockets. + */ +struct sockproto { + u_short sp_family; + u_short sp_protocol; +}; + +/* + * Protocol families, same as address families for now. + */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_IPX AF_IPX +#define PF_ISO AF_ISO +#define PF_OSI AF_OSI +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK + +#define PF_MAX AF_MAX + +/* + * Structure used for manipulating linger option. + */ +struct linger { + u_short l_onoff; + u_short l_linger; +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xffff /* options for socket level */ + +/* + * Maximum queue length specifiable by listen. + */ +#define SOMAXCONN 5 + +#define MSG_OOB 0x1 /* process out-of-band data */ +#define MSG_PEEK 0x2 /* peek at incoming message */ +#define MSG_DONTROUTE 0x4 /* send without using routing tables */ + +#define MSG_MAXIOVLEN 16 + +#define MSG_PARTIAL 0x8000 /* partial send or recv for message xport */ + +/* + * Define constant based on rfc883, used by gethostbyxxxx() calls. + */ +#define MAXGETHOSTSTRUCT 1024 +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN MAXGETHOSTSTRUCT +#endif + +/* + * Define flags to be used with the WSAAsyncSelect() call. + */ +#define FD_READ 0x01 +#define FD_WRITE 0x02 +#define FD_OOB 0x04 +#define FD_ACCEPT 0x08 +#define FD_CONNECT 0x10 +#define FD_CLOSE 0x20 + +/* + * All Windows Sockets error constants are biased by WSABASEERR from + * the "normal" + */ +#define WSABASEERR 10000 +/* + * Windows Sockets definitions of regular Microsoft C error constants + */ +#define WSAEINTR (WSABASEERR+4) +#define WSAEBADF (WSABASEERR+9) +#define WSAEACCES (WSABASEERR+13) +#define WSAEFAULT (WSABASEERR+14) +#define WSAEINVAL (WSABASEERR+22) +#define WSAEMFILE (WSABASEERR+24) + +/* + * Windows Sockets definitions of regular Berkeley error constants + */ +#define WSAEWOULDBLOCK (WSABASEERR+35) +#define WSAEINPROGRESS (WSABASEERR+36) +#define WSAEALREADY (WSABASEERR+37) +#define WSAENOTSOCK (WSABASEERR+38) +#define WSAEDESTADDRREQ (WSABASEERR+39) +#define WSAEMSGSIZE (WSABASEERR+40) +#define WSAEPROTOTYPE (WSABASEERR+41) +#define WSAENOPROTOOPT (WSABASEERR+42) +#define WSAEPROTONOSUPPORT (WSABASEERR+43) +#define WSAESOCKTNOSUPPORT (WSABASEERR+44) +#define WSAEOPNOTSUPP (WSABASEERR+45) +#define WSAEPFNOSUPPORT (WSABASEERR+46) +#define WSAEAFNOSUPPORT (WSABASEERR+47) +#define WSAEADDRINUSE (WSABASEERR+48) +#define WSAEADDRNOTAVAIL (WSABASEERR+49) +#define WSAENETDOWN (WSABASEERR+50) +#define WSAENETUNREACH (WSABASEERR+51) +#define WSAENETRESET (WSABASEERR+52) +#define WSAECONNABORTED (WSABASEERR+53) +#define WSAECONNRESET (WSABASEERR+54) +#define WSAENOBUFS (WSABASEERR+55) +#define WSAEISCONN (WSABASEERR+56) +#define WSAENOTCONN (WSABASEERR+57) +#define WSAESHUTDOWN (WSABASEERR+58) +#define WSAETOOMANYREFS (WSABASEERR+59) +#define WSAETIMEDOUT (WSABASEERR+60) +#define WSAECONNREFUSED (WSABASEERR+61) +#define WSAELOOP (WSABASEERR+62) +#define WSAENAMETOOLONG (WSABASEERR+63) +#define WSAEHOSTDOWN (WSABASEERR+64) +#define WSAEHOSTUNREACH (WSABASEERR+65) +#define WSAENOTEMPTY (WSABASEERR+66) +#define WSAEPROCLIM (WSABASEERR+67) +#define WSAEUSERS (WSABASEERR+68) +#define WSAEDQUOT (WSABASEERR+69) +#define WSAESTALE (WSABASEERR+70) +#define WSAEREMOTE (WSABASEERR+71) + +#define WSAEDISCON (WSABASEERR+101) + +/* + * Extended Windows Sockets error constant definitions + */ +#define WSASYSNOTREADY (WSABASEERR+91) +#define WSAVERNOTSUPPORTED (WSABASEERR+92) +#define WSANOTINITIALISED (WSABASEERR+93) + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (when using the resolver). Note that these errors are + * retrieved via WSAGetLastError() and must therefore follow + * the rules for avoiding clashes with error numbers from + * specific implementations or language run-time systems. + * For this reason the codes are based at WSABASEERR+1001. + * Note also that [WSA]NO_ADDRESS is defined only for + * compatibility purposes. + */ + +#define h_errno WSAGetLastError() + +/* Authoritative Answer: Host not found */ +#define WSAHOST_NOT_FOUND (WSABASEERR+1001) +#define HOST_NOT_FOUND WSAHOST_NOT_FOUND + +/* Non-Authoritative: Host not found, or SERVERFAIL */ +#define WSATRY_AGAIN (WSABASEERR+1002) +#define TRY_AGAIN WSATRY_AGAIN + +/* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define WSANO_RECOVERY (WSABASEERR+1003) +#define NO_RECOVERY WSANO_RECOVERY + +/* Valid name, no data record of requested type */ +#define WSANO_DATA (WSABASEERR+1004) +#define NO_DATA WSANO_DATA + +/* no address, look for MX record */ +#define WSANO_ADDRESS WSANO_DATA +#define NO_ADDRESS WSANO_ADDRESS + +/* + * Windows Sockets errors redefined as regular Berkeley error constants. + * These are commented out in Windows NT to avoid conflicts with errno.h. + * Use the WSA constants instead. + */ +#if 0 +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EINPROGRESS WSAEINPROGRESS +#define EALREADY WSAEALREADY +#define ENOTSOCK WSAENOTSOCK +#define EDESTADDRREQ WSAEDESTADDRREQ +#define EMSGSIZE WSAEMSGSIZE +#define EPROTOTYPE WSAEPROTOTYPE +#define ENOPROTOOPT WSAENOPROTOOPT +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define EADDRINUSE WSAEADDRINUSE +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#define ENETDOWN WSAENETDOWN +#define ENETUNREACH WSAENETUNREACH +#define ENETRESET WSAENETRESET +#define ECONNABORTED WSAECONNABORTED +#define ECONNRESET WSAECONNRESET +#define ENOBUFS WSAENOBUFS +#define EISCONN WSAEISCONN +#define ENOTCONN WSAENOTCONN +#define ESHUTDOWN WSAESHUTDOWN +#define ETOOMANYREFS WSAETOOMANYREFS +#define ETIMEDOUT WSAETIMEDOUT +#define ECONNREFUSED WSAECONNREFUSED +#define ELOOP WSAELOOP +#define ENAMETOOLONG WSAENAMETOOLONG +#define EHOSTDOWN WSAEHOSTDOWN +#define EHOSTUNREACH WSAEHOSTUNREACH +#define ENOTEMPTY WSAENOTEMPTY +#define EPROCLIM WSAEPROCLIM +#define EUSERS WSAEUSERS +#define EDQUOT WSAEDQUOT +#define ESTALE WSAESTALE +#define EREMOTE WSAEREMOTE +#endif + +/* Socket function prototypes */ + +SOCKET PASCAL accept (SOCKET s, struct sockaddr *addr, + int *addrlen); + +int PASCAL bind (SOCKET s, const struct sockaddr *addr, int namelen); + +int PASCAL closesocket (SOCKET s); + +int PASCAL connect (SOCKET s, const struct sockaddr *name, int namelen); + +int PASCAL ioctlsocket (SOCKET s, long cmd, u_long *argp); + +int PASCAL getpeername (SOCKET s, struct sockaddr *name, + int * namelen); + +int PASCAL getsockname (SOCKET s, struct sockaddr *name, + int * namelen); + +int PASCAL getsockopt (SOCKET s, int level, int optname, + char * optval, int *optlen); + +u_long PASCAL htonl (u_long hostlong); + +/* For some reason WSOCK.LIB has htons defined as a 4 byte paramter?! */ +#ifdef _WIN32 +u_short PASCAL htons (u_long hostshort); +#else +u_short PASCAL htons (u_short hostshort); +#endif /* _WIN32 */ + +unsigned long PASCAL inet_addr (const char * cp); + +char * PASCAL inet_ntoa (struct in_addr in); + +int PASCAL listen (SOCKET s, int backlog); + +u_long PASCAL ntohl (u_long netlong); + +/* For some reason WSOCK.LIB has ntohs defined as a 4 byte paramter?! */ +#ifdef _WIN32 +u_short PASCAL ntohs (u_long netshort); +#else +u_short PASCAL ntohs (u_short netshort); +#endif /* _WIN32 */ + +int PASCAL recv (SOCKET s, char * buf, int len, int flags); + +int PASCAL recvfrom (SOCKET s, char * buf, int len, int flags, + struct sockaddr *from, int * fromlen); + +int PASCAL select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timeval *timeout); + +int PASCAL send (SOCKET s, const char * buf, int len, int flags); + +int PASCAL sendto (SOCKET s, const char * buf, int len, int flags, + const struct sockaddr *to, int tolen); + +int PASCAL setsockopt (SOCKET s, int level, int optname, + const char * optval, int optlen); + +int PASCAL shutdown (SOCKET s, int how); + +SOCKET PASCAL socket (int af, int type, int protocol); + +/* Database function prototypes */ + +struct hostent * PASCAL gethostbyaddr(const char * addr, + int len, int type); + +struct hostent * PASCAL gethostbyname(const char * name); + +int PASCAL gethostname (char * name, int namelen); + +struct servent * PASCAL getservbyport(int port, const char * proto); + +struct servent * PASCAL getservbyname(const char * name, + const char * proto); + +struct protoent * PASCAL getprotobynumber(int proto); + +struct protoent * PASCAL getprotobyname(const char * name); + +/* Microsoft Windows Extension function prototypes */ + +/* int PASCAL WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData); */ +int PASCAL WSAStartup(int wVersionRequired, LPWSADATA lpWSAData); + + +int PASCAL WSACleanup(void); + +void PASCAL WSASetLastError(int iError); + +int PASCAL WSAGetLastError(void); + +WINBOOL PASCAL WSAIsBlocking(void); + +int PASCAL WSAUnhookBlockingHook(void); + +FARPROC PASCAL WSASetBlockingHook(FARPROC lpBlockFunc); + +int PASCAL WSACancelBlockingCall(void); + +HANDLE PASCAL WSAAsyncGetServByName(HWND hWnd, u_int wMsg, + const char * name, + const char * proto, + char * buf, int buflen); + +HANDLE PASCAL WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, int port, + const char * proto, char * buf, + int buflen); + +HANDLE PASCAL WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, + const char * name, char * buf, + int buflen); + +HANDLE PASCAL WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, + int number, char * buf, + int buflen); + +HANDLE PASCAL WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, + const char * name, char * buf, + int buflen); + +HANDLE PASCAL WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, + const char * addr, int len, int type, + char * buf, int buflen); + +int PASCAL WSACancelAsyncRequest(HANDLE hAsyncTaskHandle); + +int PASCAL WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, + long lEvent); + +int PASCAL WSARecvEx (SOCKET s, char * buf, int len, int *flags); + +/* Microsoft Windows Extended data types */ +typedef struct sockaddr SOCKADDR; +typedef struct sockaddr *PSOCKADDR; +typedef struct sockaddr *LPSOCKADDR; + +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr_in *PSOCKADDR_IN; +typedef struct sockaddr_in *LPSOCKADDR_IN; + +typedef struct linger LINGER; +typedef struct linger *PLINGER; +typedef struct linger *LPLINGER; + +typedef struct in_addr IN_ADDR; +typedef struct in_addr *PIN_ADDR; +typedef struct in_addr *LPIN_ADDR; + +typedef struct fd_set FD_SET; +typedef struct fd_set *PFD_SET; +typedef struct fd_set *LPFD_SET; + +typedef struct hostent HOSTENT; +typedef struct hostent *PHOSTENT; +typedef struct hostent *LPHOSTENT; + +typedef struct servent SERVENT; +typedef struct servent *PSERVENT; +typedef struct servent *LPSERVENT; + +typedef struct protoent PROTOENT; +typedef struct protoent *PPROTOENT; +typedef struct protoent *LPPROTOENT; + +typedef struct timeval TIMEVAL; +typedef struct timeval *PTIMEVAL; +typedef struct timeval *LPTIMEVAL; + +/* + * Windows message parameter composition and decomposition + * macros. + * + * WSAMAKEASYNCREPLY is intended for use by the Windows Sockets implementation + * when constructing the response to a WSAAsyncGetXByY() routine. + */ +#define WSAMAKEASYNCREPLY(buflen,error) MAKELONG(buflen,error) +/* + * WSAMAKESELECTREPLY is intended for use by the Windows Sockets implementation + * when constructing the response to WSAAsyncSelect(). + */ +#define WSAMAKESELECTREPLY(event,error) MAKELONG(event,error) +/* + * WSAGETASYNCBUFLEN is intended for use by the Windows Sockets application + * to extract the buffer length from the lParam in the response + * to a WSAGetXByY(). + */ +#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam) +/* + * WSAGETASYNCERROR is intended for use by the Windows Sockets application + * to extract the error code from the lParam in the response + * to a WSAGetXByY(). + */ +#define WSAGETASYNCERROR(lParam) HIWORD(lParam) +/* + * WSAGETSELECTEVENT is intended for use by the Windows Sockets application + * to extract the event code from the lParam in the response + * to a WSAAsyncSelect(). + */ +#define WSAGETSELECTEVENT(lParam) LOWORD(lParam) +/* + * WSAGETSELECTERROR is intended for use by the Windows Sockets application + * to extract the error code from the lParam in the response + * to a WSAAsyncSelect(). + */ +#define WSAGETSELECTERROR(lParam) HIWORD(lParam) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GNU_H_WINDOWS32_SOCKETS */ diff --git a/include/structs.h b/include/structs.h new file mode 100644 index 0000000..7f7587c --- /dev/null +++ b/include/structs.h @@ -0,0 +1,4463 @@ +/* + Structures.h + + Declarations for all the Windows32 API Structures + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Scott Christley + Date: 1996 + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef _GNU_H_WINDOWS32_STRUCTURES +#define _GNU_H_WINDOWS32_STRUCTURES + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _VALENT +{ + LPTSTR ve_valuename; + DWORD ve_valuelen; + DWORD ve_valueptr; + DWORD ve_type; +} VALENT, *PVALENT; + +#ifndef WIN32_LEAN_AND_MEAN + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _ABC { + int abcA; + UINT abcB; + int abcC; +} ABC, *LPABC; + +typedef struct _ABCFLOAT { + FLOAT abcfA; + FLOAT abcfB; + FLOAT abcfC; +} ABCFLOAT, *LPABCFLOAT; + +typedef struct tagACCEL { + BYTE fVirt; + WORD key; + WORD cmd; +} ACCEL, *LPACCEL; + +typedef struct tagACCESSTIMEOUT { + UINT cbSize; + DWORD dwFlags; + DWORD iTimeOutMSec; +} ACCESSTIMEOUT; + +typedef struct _ACTION_HEADER { + ULONG transport_id; + USHORT action_code; + USHORT reserved; +} ACTION_HEADER; + +typedef struct _ADAPTER_STATUS { + UCHAR adapter_address[6]; + UCHAR rev_major; + UCHAR reserved0; + UCHAR adapter_type; + UCHAR rev_minor; + WORD duration; + WORD frmr_recv; + WORD frmr_xmit; + WORD iframe_recv_err; + WORD xmit_aborts; + DWORD xmit_success; + DWORD recv_success; + WORD iframe_xmit_err; + WORD recv_buff_unavail; + WORD t1_timeouts; + WORD ti_timeouts; + DWORD reserved1; + WORD free_ncbs; + WORD max_cfg_ncbs; + WORD max_ncbs; + WORD xmit_buf_unavail; + WORD max_dgram_size; + WORD pending_sess; + WORD max_cfg_sess; + WORD max_sess; + WORD max_sess_pkt_size; + WORD name_count; +} ADAPTER_STATUS; + +typedef struct _ADDJOB_INFO_1 { + LPTSTR Path; + DWORD JobId; +} ADDJOB_INFO_1; + +typedef struct tagANIMATIONINFO { + UINT cbSize; + int iMinAnimate; +} ANIMATIONINFO, *LPANIMATIONINFO; + +typedef struct _RECT { + LONG left; + LONG top; + LONG right; + LONG bottom; +} RECT, *LPRECT, *LPCRECT, *PRECT; + +typedef struct _RECTL { + LONG left; + LONG top; + LONG right; + LONG bottom; +} RECTL, *LPRECTL, *LPCRECTL, *PRECTL; + +typedef struct _AppBarData { + DWORD cbSize; + HWND hWnd; + UINT uCallbackMessage; + UINT uEdge; + RECT rc; + LPARAM lParam; +} APPBARDATA, *PAPPBARDATA; + +typedef struct tagBITMAP +{ + LONG bmType; + LONG bmWidth; + LONG bmHeight; + LONG bmWidthBytes; + WORD bmPlanes; + WORD bmBitsPixel; + LPVOID bmBits; +} BITMAP, *PBITMAP, *NPBITMAP, *LPBITMAP; + +typedef struct tagBITMAPCOREHEADER { + DWORD bcSize; + WORD bcWidth; + WORD bcHeight; + WORD bcPlanes; + WORD bcBitCount; +} BITMAPCOREHEADER; + +typedef struct tagRGBTRIPLE { + BYTE rgbtBlue; + BYTE rgbtGreen; + BYTE rgbtRed; +} RGBTRIPLE, *PRGBTRIPLE; + +typedef struct _BITMAPCOREINFO { + BITMAPCOREHEADER bmciHeader; + RGBTRIPLE bmciColors[1]; +} BITMAPCOREINFO, *PBITMAPCOREINFO, *LPBITMAPCOREINFO; + +typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; +} BITMAPFILEHEADER __attribute__((packed)); + +typedef struct tagBITMAPINFOHEADER { + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; + +typedef struct tagRGBQUAD { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD; + +typedef struct tagBITMAPINFO { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[1]; +} BITMAPINFO, *LPBITMAPINFO, *PBITMAPINFO; + +typedef long FXPT2DOT30, * LPFXPT2DOT30; + +typedef struct tagCIEXYZ +{ + FXPT2DOT30 ciexyzX; + FXPT2DOT30 ciexyzY; + FXPT2DOT30 ciexyzZ; +} CIEXYZ; +typedef CIEXYZ * LPCIEXYZ; + +typedef struct tagCIEXYZTRIPLE +{ + CIEXYZ ciexyzRed; + CIEXYZ ciexyzGreen; + CIEXYZ ciexyzBlue; +} CIEXYZTRIPLE; +typedef CIEXYZTRIPLE * LPCIEXYZTRIPLE; + +typedef struct { + DWORD bV4Size; + LONG bV4Width; + LONG bV4Height; + WORD bV4Planes; + WORD bV4BitCount; + DWORD bV4V4Compression; + DWORD bV4SizeImage; + LONG bV4XPelsPerMeter; + LONG bV4YPelsPerMeter; + DWORD bV4ClrUsed; + DWORD bV4ClrImportant; + DWORD bV4RedMask; + DWORD bV4GreenMask; + DWORD bV4BlueMask; + DWORD bV4AlphaMask; + DWORD bV4CSType; + CIEXYZTRIPLE bV4Endpoints; + DWORD bV4GammaRed; + DWORD bV4GammaGreen; + DWORD bV4GammaBlue; +} BITMAPV4HEADER, *LPBITMAPV4HEADER, *PBITMAPV4HEADER; + +#ifndef _BLOB_DEFINED +#define _BLOB_DEFINED +typedef struct _BLOB { + ULONG cbSize; + BYTE *pBlobData; +} BLOB; +#endif + +typedef struct _SHITEMID { + USHORT cb; + BYTE abID[1]; +} SHITEMID, * LPSHITEMID; +typedef const SHITEMID * LPCSHITEMID; + +typedef struct _ITEMIDLIST { + SHITEMID mkid; +} ITEMIDLIST, * LPITEMIDLIST; +typedef const ITEMIDLIST * LPCITEMIDLIST; + +typedef struct _browseinfo { + HWND hwndOwner; + LPCITEMIDLIST pidlRoot; + LPSTR pszDisplayName; + LPCSTR lpszTitle; + UINT ulFlags; + BFFCALLBACK lpfn; + LPARAM lParam; + int iImage; +} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO; + +typedef struct _BY_HANDLE_FILE_INFORMATION { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD dwVolumeSerialNumber; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD nNumberOfLinks; + DWORD nFileIndexHigh; + DWORD nFileIndexLow; +} BY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION; + +typedef struct _FIXED { + WORD fract; + short value; +} FIXED; + +typedef struct tagPOINT { + LONG x; + LONG y; +} POINT, *LPPOINT, *PPOINT; + +typedef struct tagPOINTFX { + FIXED x; + FIXED y; +} POINTFX; + +typedef struct _POINTL { + LONG x; + LONG y; +} POINTL, *PPOINTL; + +typedef struct tagPOINTS { + SHORT x; + SHORT y; +} POINTS; + +typedef struct _tagCANDIDATEFORM { + DWORD dwIndex; + DWORD dwStyle; + POINT ptCurrentPos; + RECT rcArea; +} CANDIDATEFORM, *LPCANDIDATEFORM; + +typedef struct _tagCANDIDATELIST { + DWORD dwSize; + DWORD dwStyle; + DWORD dwCount; + DWORD dwSelection; + DWORD dwPageStart; + DWORD dwPageSize; + DWORD dwOffset[1]; +} CANDIDATELIST, *LPCANDIDATELIST; + +typedef struct tagCREATESTRUCT { + LPVOID lpCreateParams; + HINSTANCE hInstance; + HMENU hMenu; + HWND hwndParent; + int cy; + int cx; + int y; + int x; + LONG style; + LPCTSTR lpszName; + LPCTSTR lpszClass; + DWORD dwExStyle; +} CREATESTRUCT, *LPCREATESTRUCT; + +typedef struct tagCREATESTRUCTA { + LPVOID lpCreateParams; + HINSTANCE hInstance; + HMENU hMenu; + HWND hwndParent; + int cy; + int cx; + int y; + int x; + LONG style; + LPCSTR lpszName; + LPCSTR lpszClass; + DWORD dwExStyle; +} CREATESTRUCTA, *LPCREATESTRUCTA; + +typedef struct tagCREATESTRUCTW { + LPVOID lpCreateParams; + HINSTANCE hInstance; + HMENU hMenu; + HWND hwndParent; + int cy; + int cx; + int y; + int x; + LONG style; + LPCWSTR lpszName; + LPCWSTR lpszClass; + DWORD dwExStyle; +} CREATESTRUCTW, *LPCREATESTRUCTW; + +typedef struct tagCBT_CREATEWND { + LPCREATESTRUCT lpcs; + HWND hwndInsertAfter; +} CBT_CREATEWND; + +typedef struct tagCBTACTIVATESTRUCT { + WINBOOL fMouse; + HWND hWndActive; +} CBTACTIVATESTRUCT; + +typedef struct _CHAR_INFO { + union { + WCHAR UnicodeChar; + CHAR AsciiChar; + } Char; + WORD Attributes; +} CHAR_INFO, *PCHAR_INFO; + +typedef struct _charformat { + UINT cbSize; + DWORD dwMask; + DWORD dwEffects; + LONG yHeight; + LONG yOffset; + COLORREF crTextColor; + BYTE bCharSet; + BYTE bPitchAndFamily; + TCHAR szFaceName[LF_FACESIZE]; +} CHARFORMAT; + +typedef struct _charrange { + LONG cpMin; + LONG cpMax; +} CHARRANGE; + +typedef struct tagCHARSET { + DWORD aflBlock[3]; + DWORD flLang; +} CHARSET; + +typedef struct tagFONTSIGNATURE { + DWORD fsUsb[4]; + DWORD fsCsb[2]; +} FONTSIGNATURE, *LPFONTSIGNATURE; + +typedef struct { + UINT ciCharset; + UINT ciACP; + FONTSIGNATURE fs; +} CHARSETINFO, *LPCHARSETINFO; + +typedef struct { + DWORD lStructSize; + HWND hwndOwner; + HWND hInstance; + COLORREF rgbResult; + COLORREF* lpCustColors; + DWORD Flags; + LPARAM lCustData; + LPCCHOOKPROC lpfnHook; + LPCTSTR lpTemplateName; +} CHOOSECOLOR, *LPCHOOSECOLOR; + +typedef struct tagLOGFONT { + LONG lfHeight; + LONG lfWidth; + LONG lfEscapement; + LONG lfOrientation; + LONG lfWeight; + BYTE lfItalic; + BYTE lfUnderline; + BYTE lfStrikeOut; + BYTE lfCharSet; + BYTE lfOutPrecision; + BYTE lfClipPrecision; + BYTE lfQuality; + BYTE lfPitchAndFamily; + TCHAR lfFaceName[LF_FACESIZE]; +} LOGFONT, *LPLOGFONT, *PLOGFONT; + +typedef struct tagLOGFONTW { + LONG lfHeight; + LONG lfWidth; + LONG lfEscapement; + LONG lfOrientation; + LONG lfWeight; + BYTE lfItalic; + BYTE lfUnderline; + BYTE lfStrikeOut; + BYTE lfCharSet; + BYTE lfOutPrecision; + BYTE lfClipPrecision; + BYTE lfQuality; + BYTE lfPitchAndFamily; + LPWSTR lfFaceName; +} LOGFONTW, *LPLOGFONTW, *PLOGFONTW; + +typedef struct { + DWORD lStructSize; + HWND hwndOwner; + HDC hDC; + LPLOGFONT lpLogFont; + INT iPointSize; + DWORD Flags; + DWORD rgbColors; + LPARAM lCustData; + LPCFHOOKPROC lpfnHook; + LPCTSTR lpTemplateName; + HINSTANCE hInstance; + LPTSTR lpszStyle; + WORD nFontType; + WORD ___MISSING_ALIGNMENT__; + INT nSizeMin; + INT nSizeMax; +} CHOOSEFONT, *LPCHOOSEFONT; + +typedef struct _IDA { + UINT cidl; + UINT aoffset[1]; +} CIDA, * LPIDA; + +typedef struct tagCLIENTCREATESTRUCT { + HANDLE hWindowMenu; + UINT idFirstChild; +} CLIENTCREATESTRUCT; + +typedef CLIENTCREATESTRUCT *LPCLIENTCREATESTRUCT; + +typedef struct _CMInvokeCommandInfo { + DWORD cbSize; + DWORD fMask; + HWND hwnd; + LPCSTR lpVerb; + LPCSTR lpParameters; + LPCSTR lpDirectory; + int nShow; + DWORD dwHotKey; + HANDLE hIcon; +} CMINVOKECOMMANDINFO, *LPCMINVOKECOMMANDINFO; + +typedef struct tagCOLORADJUSTMENT { + WORD caSize; + WORD caFlags; + WORD caIlluminantIndex; + WORD caRedGamma; + WORD caGreenGamma; + WORD caBlueGamma; + WORD caReferenceBlack; + WORD caReferenceWhite; + SHORT caContrast; + SHORT caBrightness; + SHORT caColorfulness; + SHORT caRedGreenTint; +} COLORADJUSTMENT, *LPCOLORADJUSTMENT; + +typedef struct _COLORMAP { + COLORREF from; + COLORREF to; +} COLORMAP, * LPCOLORMAP; + +typedef struct _DCB { + DWORD DCBlength; + DWORD BaudRate; + DWORD fBinary: 1; + DWORD fParity: 1; + DWORD fOutxCtsFlow:1; + DWORD fOutxDsrFlow:1; + DWORD fDtrControl:2; + DWORD fDsrSensitivity:1; + DWORD fTXContinueOnXoff:1; + DWORD fOutX: 1; + DWORD fInX: 1; + DWORD fErrorChar: 1; + DWORD fNull: 1; + DWORD fRtsControl:2; + DWORD fAbortOnError:1; + DWORD fDummy2:17; + WORD wReserved; + WORD XonLim; + WORD XoffLim; + BYTE ByteSize; + BYTE Parity; + BYTE StopBits; + char XonChar; + char XoffChar; + char ErrorChar; + char EofChar; + char EvtChar; + WORD wReserved1; +} DCB, *LPDCB; + +typedef struct _COMM_CONFIG { + DWORD dwSize; + WORD wVersion; + WORD wReserved; + DCB dcb; + DWORD dwProviderSubType; + DWORD dwProviderOffset; + DWORD dwProviderSize; + WCHAR wcProviderData[1]; +} COMMCONFIG, *LPCOMMCONFIG; + +typedef struct _COMMPROP { + WORD wPacketLength; + WORD wPacketVersion; + DWORD dwServiceMask; + DWORD dwReserved1; + DWORD dwMaxTxQueue; + DWORD dwMaxRxQueue; + DWORD dwMaxBaud; + DWORD dwProvSubType; + DWORD dwProvCapabilities; + DWORD dwSettableParams; + DWORD dwSettableBaud; + WORD wSettableData; + WORD wSettableStopParity; + DWORD dwCurrentTxQueue; + DWORD dwCurrentRxQueue; + DWORD dwProvSpec1; + DWORD dwProvSpec2; + WCHAR wcProvChar[1]; +} COMMPROP, *LPCOMMPROP; + +typedef struct _COMMTIMEOUTS { + DWORD ReadIntervalTimeout; + DWORD ReadTotalTimeoutMultiplier; + DWORD ReadTotalTimeoutConstant; + DWORD WriteTotalTimeoutMultiplier; + DWORD WriteTotalTimeoutConstant; +} COMMTIMEOUTS,*LPCOMMTIMEOUTS; + +typedef struct tagCOMPAREITEMSTRUCT { + UINT CtlType; + UINT CtlID; + HWND hwndItem; + UINT itemID1; + DWORD itemData1; + UINT itemID2; + DWORD itemData2; +} COMPAREITEMSTRUCT; + +typedef struct { + COLORREF crText; + COLORREF crBackground; + DWORD dwEffects; +} COMPCOLOR; + +typedef struct _tagCOMPOSITIONFORM { + DWORD dwStyle; + POINT ptCurrentPos; + RECT rcArea; +} COMPOSITIONFORM, *LPCOMPOSITIONFORM; + +typedef struct _COMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} COMSTAT, *LPCOMSTAT; + +typedef struct tagCONVCONTEXT { + UINT cb; + UINT wFlags; + UINT wCountryID; + int iCodePage; + DWORD dwLangID; + DWORD dwSecurity; + SECURITY_QUALITY_OF_SERVICE qos; +} CONVCONTEXT; + +typedef CONVCONTEXT *PCONVCONTEXT; + +typedef struct tagCONVINFO { + DWORD cb; + DWORD hUser; + HCONV hConvPartner; + HSZ hszSvcPartner; + HSZ hszServiceReq; + HSZ hszTopic; + HSZ hszItem; + UINT wFmt; + UINT wType; + UINT wStatus; + UINT wConvst; + UINT wLastError; + HCONVLIST hConvList; + CONVCONTEXT ConvCtxt; + HWND hwnd; + HWND hwndPartner; +} CONVINFO, *PCONVINFO; + +typedef struct tagCOPYDATASTRUCT { + DWORD dwData; + DWORD cbData; + PVOID lpData; +} COPYDATASTRUCT; + +typedef struct _cpinfo { + UINT MaxCharSize; + BYTE DefaultChar[MAX_DEFAULTCHAR]; + BYTE LeadByte[MAX_LEADBYTES]; +} CPINFO, *LPCPINFO; + +typedef struct tagCPLINFO { + int idIcon; + int idName; + int idInfo; + LONG lData; +} CPLINFO; + +typedef struct _CREATE_PROCESS_DEBUG_INFO { + HANDLE hFile; + HANDLE hProcess; + HANDLE hThread; + LPVOID lpBaseOfImage; + DWORD dwDebugInfoFileOffset; + DWORD nDebugInfoSize; + LPVOID lpThreadLocalBase; + LPTHREAD_START_ROUTINE lpStartAddress; + LPVOID lpImageName; + WORD fUnicode; +} CREATE_PROCESS_DEBUG_INFO; + +typedef struct _CREATE_THREAD_DEBUG_INFO { + HANDLE hThread; + LPVOID lpThreadLocalBase; + LPTHREAD_START_ROUTINE lpStartAddress; +} CREATE_THREAD_DEBUG_INFO; + +/* + TODO: sockets +typedef struct _SOCKET_ADDRESS { + LPSOCKADDR lpSockaddr ; + INT iSockaddrLength ; +} SOCKET_ADDRESS, *PSOCKET_ADDRESS, *LPSOCKET_ADDRESS; +*/ + +/* +typedef struct _CSADDR_INFO { + SOCKET_ADDRESS LocalAddr; + SOCKET_ADDRESS RemoteAddr; + INT iSocketType; + INT iProtocol; +} CSADDR_INFO; +*/ + +typedef struct _currencyfmt { + UINT NumDigits; + UINT LeadingZero; + UINT Grouping; + LPTSTR lpDecimalSep; + LPTSTR lpThousandSep; + UINT NegativeOrder; + UINT PositiveOrder; + LPTSTR lpCurrencySymbol; +} CURRENCYFMT; + +typedef struct tagCURSORSHAPE { + int xHotSpot; + int yHotSpot; + int cx; + int cy; + int cbWidth; + BYTE Planes; + BYTE BitsPixel; +} CURSORSHAPE, *LPCURSORSHAPE; + +typedef struct tagCWPRETSTRUCT { + LRESULT lResult; + LPARAM lParam; + WPARAM wParam; + DWORD message; + HWND hwnd; +} CWPRETSTRUCT; + +typedef struct tagCWPSTRUCT { + LPARAM lParam; + WPARAM wParam; + UINT message; + HWND hwnd; +} CWPSTRUCT; + +typedef struct _DATATYPES_INFO_1 { + LPTSTR pName; +} DATATYPES_INFO_1; + +typedef struct { + unsigned short bAppReturnCode:8, + reserved:6, + fBusy:1, + fAck:1; +} DDEACK; + +typedef struct { + unsigned short reserved:14, + fDeferUpd:1, + fAckReq:1; + short cfFormat; +} DDEADVISE; + +typedef struct { + unsigned short unused:12, + fResponse:1, + fRelease:1, + reserved:1, + fAckReq:1; + short cfFormat; + BYTE Value[1]; +} DDEDATA; + +typedef struct { + unsigned short unused:13, + fRelease:1, + fDeferUpd:1, + fAckReq:1; + short cfFormat; +} DDELN; + +typedef struct tagDDEML_MSG_HOOK_DATA { + UINT uiLo; + UINT uiHi; + DWORD cbData; + DWORD Data[8]; +} DDEML_MSG_HOOK_DATA; + +typedef struct { + unsigned short unused:13, + fRelease:1, + fReserved:2; + short cfFormat; + BYTE Value[1]; +} DDEPOKE; + +typedef struct { + unsigned short unused:12, + fAck:1, + fRelease:1, + fReserved:1, + fAckReq:1; + short cfFormat; + BYTE rgb[1]; +} DDEUP; + +typedef struct _EXCEPTION_DEBUG_INFO { + EXCEPTION_RECORD ExceptionRecord; + DWORD dwFirstChance; +} EXCEPTION_DEBUG_INFO; + +typedef struct _EXIT_PROCESS_DEBUG_INFO { + DWORD dwExitCode; +} EXIT_PROCESS_DEBUG_INFO; + +typedef struct _EXIT_THREAD_DEBUG_INFO { + DWORD dwExitCode; +} EXIT_THREAD_DEBUG_INFO; + +typedef struct _LOAD_DLL_DEBUG_INFO { + HANDLE hFile; + LPVOID lpBaseOfDll; + DWORD dwDebugInfoFileOffset; + DWORD nDebugInfoSize; + LPVOID lpImageName; + WORD fUnicode; +} LOAD_DLL_DEBUG_INFO; + +typedef struct _UNLOAD_DLL_DEBUG_INFO { + LPVOID lpBaseOfDll; +} UNLOAD_DLL_DEBUG_INFO; + +typedef struct _OUTPUT_DEBUG_STRING_INFO { + LPSTR lpDebugStringData; + WORD fUnicode; + WORD nDebugStringLength; +} OUTPUT_DEBUG_STRING_INFO; + +typedef struct _RIP_INFO { + DWORD dwError; + DWORD dwType; +} RIP_INFO; + +typedef struct _DEBUG_EVENT { + DWORD dwDebugEventCode; + DWORD dwProcessId; + DWORD dwThreadId; + union { + EXCEPTION_DEBUG_INFO Exception; + CREATE_THREAD_DEBUG_INFO CreateThread; + CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; + EXIT_THREAD_DEBUG_INFO ExitThread; + EXIT_PROCESS_DEBUG_INFO ExitProcess; + LOAD_DLL_DEBUG_INFO LoadDll; + UNLOAD_DLL_DEBUG_INFO UnloadDll; + OUTPUT_DEBUG_STRING_INFO DebugString; + RIP_INFO RipInfo; + } u; +} DEBUG_EVENT, *LPDEBUG_EVENT; + +typedef struct tagDEBUGHOOKINFO { + DWORD idThread; + DWORD idThreadInstaller; + LPARAM lParam; + WPARAM wParam; + int code; +} DEBUGHOOKINFO; + +typedef struct tagDELETEITEMSTRUCT { + UINT CtlType; + UINT CtlID; + UINT itemID; + HWND hwndItem; + UINT itemData; +} DELETEITEMSTRUCT; + +typedef struct _DEV_BROADCAST_HDR { + ULONG dbch_size; + ULONG dbch_devicetype; + ULONG dbch_reserved; +} DEV_BROADCAST_HDR; +typedef DEV_BROADCAST_HDR *PDEV_BROADCAST_HDR; + +typedef struct _DEV_BROADCAST_OEM { + ULONG dbco_size; + ULONG dbco_devicetype; + ULONG dbco_reserved; + ULONG dbco_identifier; + ULONG dbco_suppfunc; +} DEV_BROADCAST_OEM; +typedef DEV_BROADCAST_OEM *PDEV_BROADCAST_OEM; + +typedef struct _DEV_BROADCAST_PORT { + ULONG dbcp_size; + ULONG dbcp_devicetype; + ULONG dbcp_reserved; + char dbcp_name[1]; +} DEV_BROADCAST_PORT; +typedef DEV_BROADCAST_PORT *PDEV_BROADCAST_PORT; + +struct _DEV_BROADCAST_USERDEFINED { + struct _DEV_BROADCAST_HDR dbud_dbh; + char dbud_szName[1]; + BYTE dbud_rgbUserDefined[1]; +}; + +typedef struct _DEV_BROADCAST_VOLUME { + ULONG dbcv_size; + ULONG dbcv_devicetype; + ULONG dbcv_reserved; + ULONG dbcv_unitmask; + USHORT dbcv_flags; +} DEV_BROADCAST_VOLUME; +typedef DEV_BROADCAST_VOLUME *PDEV_BROADCAST_VOLUME; + +typedef struct tagDEVNAMES { + WORD wDriverOffset; + WORD wDeviceOffset; + WORD wOutputOffset; + WORD wDefault; +} DEVNAMES, *LPDEVNAMES; + +typedef struct tagDIBSECTION { + BITMAP dsBm; + BITMAPINFOHEADER dsBmih; + DWORD dsBitfields[3]; + HANDLE dshSection; + DWORD dsOffset; +} DIBSECTION; + +typedef struct _DISK_PERFORMANCE { + LARGE_INTEGER BytesRead; + LARGE_INTEGER BytesWritten; + LARGE_INTEGER ReadTime; + LARGE_INTEGER WriteTime; + DWORD ReadCount; + DWORD WriteCount; + DWORD QueueDepth; +} DISK_PERFORMANCE ; + +typedef struct { + DWORD style; + DWORD dwExtendedStyle; + short x; + short y; + short cx; + short cy; + WORD id; +} DLGITEMTEMPLATE PACKED; + +typedef DLGITEMTEMPLATE *LPDLGITEMTEMPLATE; +typedef DLGITEMTEMPLATE *PDLGITEMTEMPLATE; + +typedef struct { + DWORD style; + DWORD dwExtendedStyle; + WORD cdit; + short x; + short y; + short cx; + short cy; +} DLGTEMPLATE PACKED; + +typedef DLGTEMPLATE *LPDLGTEMPLATE; +typedef const DLGTEMPLATE *LPCDLGTEMPLATE; + +typedef struct _DOC_INFO_1 { + LPTSTR pDocName; + LPTSTR pOutputFile; + LPTSTR pDatatype; +} DOC_INFO_1; + +typedef struct _DOC_INFO_2 { + LPTSTR pDocName; + LPTSTR pOutputFile; + LPTSTR pDatatype; + DWORD dwMode; + DWORD JobId; +} DOC_INFO_2; + +typedef struct { + int cbSize; + LPCTSTR lpszDocName; + LPCTSTR lpszOutput; + LPCTSTR lpszDatatype; + DWORD fwType; +} DOCINFO, *PDOCINFO; + +typedef struct { + UINT uNotification; + HWND hWnd; + POINT ptCursor; +} DRAGLISTINFO, *LPDRAGLISTINFO; + +typedef struct tagDRAWITEMSTRUCT { + UINT CtlType; + UINT CtlID; + UINT itemID; + UINT itemAction; + UINT itemState; + HWND hwndItem; + HDC hDC; + RECT rcItem; + DWORD itemData; +} DRAWITEMSTRUCT, *LPDRAWITEMSTRUCT, *PDRAWITEMSTRUCT; + +typedef struct { + UINT cbSize; + int iTabLength; + int iLeftMargin; + int iRightMargin; + UINT uiLengthDrawn; +} DRAWTEXTPARAMS, *LPDRAWTEXTPARAMS; + + + +typedef struct _DRIVER_INFO_1 { + LPTSTR pName; +} DRIVER_INFO_1; + +typedef struct _DRIVER_INFO_2 { + DWORD cVersion; + LPTSTR pName; + LPTSTR pEnvironment; + LPTSTR pDriverPath; + LPTSTR pDataFile; + LPTSTR pConfigFile; +} DRIVER_INFO_2; + +typedef struct _DRIVER_INFO_3 { + DWORD cVersion; + LPTSTR pName; + LPTSTR pEnvironment; + LPTSTR pDriverPath; + LPTSTR pDataFile; + LPTSTR pConfigFile; + LPTSTR pHelpFile; + LPTSTR pDependentFiles; + LPTSTR pMonitorName; + LPTSTR pDefaultDataType; +} DRIVER_INFO_3; + +typedef struct _editstream { + DWORD dwCookie; + DWORD dwError; + EDITSTREAMCALLBACK pfnCallback; +} EDITSTREAM; + +typedef struct tagEMR +{ + DWORD iType; + DWORD nSize; +} EMR, *PEMR; + +typedef struct tagEMRANGLEARC +{ + EMR emr; + POINTL ptlCenter; + DWORD nRadius; + FLOAT eStartAngle; + FLOAT eSweepAngle; +} EMRANGLEARC, *PEMRANGLEARC; + +typedef struct tagEMRARC +{ + EMR emr; + RECTL rclBox; + POINTL ptlStart; + POINTL ptlEnd; +} EMRARC, *PEMRARC, + EMRARCTO, *PEMRARCTO, + EMRCHORD, *PEMRCHORD, + EMRPIE, *PEMRPIE; + +typedef struct _XFORM +{ + FLOAT eM11; + FLOAT eM12; + FLOAT eM21; + FLOAT eM22; + FLOAT eDx; + FLOAT eDy; +} XFORM, *PXFORM, *LPXFORM; + +typedef struct tagEMRBITBLT +{ + EMR emr; + RECTL rclBounds; + LONG xDest; + LONG yDest; + LONG cxDest; + LONG cyDest; + DWORD dwRop; + LONG xSrc; + LONG ySrc; + XFORM xformSrc; + COLORREF crBkColorSrc; + DWORD iUsageSrc; + DWORD offBmiSrc; + DWORD offBitsSrc; + DWORD cbBitsSrc; +} EMRBITBLT, *PEMRBITBLT; + +typedef struct tagLOGBRUSH { + UINT lbStyle; + COLORREF lbColor; + LONG lbHatch; +} LOGBRUSH, *PLOGBRUSH; + +typedef struct tagEMRCREATEBRUSHINDIRECT +{ + EMR emr; + DWORD ihBrush; + LOGBRUSH lb; +} EMRCREATEBRUSHINDIRECT, *PEMRCREATEBRUSHINDIRECT; + +typedef LONG LCSCSTYPE; +typedef LONG LCSGAMUTMATCH; + +typedef struct tagLOGCOLORSPACE { + DWORD lcsSignature; + DWORD lcsVersion; + DWORD lcsSize; + + LCSCSTYPE lcsCSType; + LCSGAMUTMATCH lcsIntent; + CIEXYZTRIPLE lcsEndpoints; + DWORD lcsGammaRed; + DWORD lcsGammaGreen; + DWORD lcsGammaBlue; + TCHAR lcsFilename[MAX_PATH]; +} LOGCOLORSPACE, *LPLOGCOLORSPACE; + +typedef struct tagEMRCREATECOLORSPACE +{ + EMR emr; + DWORD ihCS; + LOGCOLORSPACE lcs; +} EMRCREATECOLORSPACE, *PEMRCREATECOLORSPACE; + +typedef struct tagEMRCREATEDIBPATTERNBRUSHPT +{ + EMR emr; + DWORD ihBrush; + DWORD iUsage; + DWORD offBmi; + DWORD cbBmi; + DWORD offBits; + DWORD cbBits; +} EMRCREATEDIBPATTERNBRUSHPT, + PEMRCREATEDIBPATTERNBRUSHPT; + +typedef struct tagEMRCREATEMONOBRUSH +{ + EMR emr; + DWORD ihBrush; + DWORD iUsage; + DWORD offBmi; + DWORD cbBmi; + DWORD offBits; + DWORD cbBits; +} EMRCREATEMONOBRUSH, *PEMRCREATEMONOBRUSH; + +typedef struct tagPALETTEENTRY { + BYTE peRed; + BYTE peGreen; + BYTE peBlue; + BYTE peFlags; +} PALETTEENTRY, *LPPALETTEENTRY, *PPALETTEENTRY; + +typedef struct tagLOGPALETTE { + WORD palVersion; + WORD palNumEntries; + PALETTEENTRY palPalEntry[1]; +} LOGPALETTE, *LPLOGPALETTE, *PLOGPALETTE; + +typedef struct tagEMRCREATEPALETTE +{ + EMR emr; + DWORD ihPal; + LOGPALETTE lgpl; +} EMRCREATEPALETTE, *PEMRCREATEPALETTE; + +typedef struct tagLOGPEN { + UINT lopnStyle; + POINT lopnWidth; + COLORREF lopnColor; +} LOGPEN, *PLOGPEN; + +typedef struct tagEMRCREATEPEN +{ + EMR emr; + DWORD ihPen; + LOGPEN lopn; +} EMRCREATEPEN, *PEMRCREATEPEN; + +typedef struct tagEMRELLIPSE +{ + EMR emr; + RECTL rclBox; +} EMRELLIPSE, *PEMRELLIPSE, + EMRRECTANGLE, *PEMRRECTANGLE; + +typedef struct tagEMREOF +{ + EMR emr; + DWORD nPalEntries; + DWORD offPalEntries; + DWORD nSizeLast; +} EMREOF, *PEMREOF; + +typedef struct tagEMREXCLUDECLIPRECT +{ + EMR emr; + RECTL rclClip; +} EMREXCLUDECLIPRECT, *PEMREXCLUDECLIPRECT, + EMRINTERSECTCLIPRECT, *PEMRINTERSECTCLIPRECT; + +typedef struct tagPANOSE { + BYTE bFamilyType; + BYTE bSerifStyle; + BYTE bWeight; + BYTE bProportion; + BYTE bContrast; + BYTE bStrokeVariation; + BYTE bArmStyle; + BYTE bLetterform; + BYTE bMidline; + BYTE bXHeight; +} PANOSE; + +typedef struct tagEXTLOGFONT { + LOGFONT elfLogFont; + BCHAR elfFullName[LF_FULLFACESIZE]; + BCHAR elfStyle[LF_FACESIZE]; + DWORD elfVersion; + DWORD elfStyleSize; + DWORD elfMatch; + DWORD elfReserved; + BYTE elfVendorId[ELF_VENDOR_SIZE]; + DWORD elfCulture; + PANOSE elfPanose; +} EXTLOGFONT; + +typedef struct tagEMREXTCREATEFONTINDIRECTW +{ + EMR emr; + DWORD ihFont; + EXTLOGFONT elfw; +} EMREXTCREATEFONTINDIRECTW, + PEMREXTCREATEFONTINDIRECTW; + +typedef struct tagEXTLOGPEN { + UINT elpPenStyle; + UINT elpWidth; + UINT elpBrushStyle; + COLORREF elpColor; + LONG elpHatch; + DWORD elpNumEntries; + DWORD elpStyleEntry[1]; +} EXTLOGPEN; + +typedef struct tagEMREXTCREATEPEN +{ + EMR emr; + DWORD ihPen; + DWORD offBmi; + DWORD cbBmi; + DWORD offBits; + DWORD cbBits; + EXTLOGPEN elp; +} EMREXTCREATEPEN, *PEMREXTCREATEPEN; + +typedef struct tagEMREXTFLOODFILL +{ + EMR emr; + POINTL ptlStart; + COLORREF crColor; + DWORD iMode; +} EMREXTFLOODFILL, *PEMREXTFLOODFILL; + +typedef struct tagEMREXTSELECTCLIPRGN +{ + EMR emr; + DWORD cbRgnData; + DWORD iMode; + BYTE RgnData[1]; +} EMREXTSELECTCLIPRGN, *PEMREXTSELECTCLIPRGN; + +typedef struct tagEMRTEXT +{ + POINTL ptlReference; + DWORD nChars; + DWORD offString; + DWORD fOptions; + RECTL rcl; + DWORD offDx; +} EMRTEXT, *PEMRTEXT; + +typedef struct tagEMREXTTEXTOUTA +{ + EMR emr; + RECTL rclBounds; + DWORD iGraphicsMode; + FLOAT exScale; + FLOAT eyScale; + EMRTEXT emrtext; +} EMREXTTEXTOUTA, *PEMREXTTEXTOUTA, + EMREXTTEXTOUTW, *PEMREXTTEXTOUTW; + +typedef struct tagEMRFILLPATH +{ + EMR emr; + RECTL rclBounds; +} EMRFILLPATH, *PEMRFILLPATH, + EMRSTROKEANDFILLPATH, *PEMRSTROKEANDFILLPATH, + EMRSTROKEPATH, *PEMRSTROKEPATH; + +typedef struct tagEMRFILLRGN +{ + EMR emr; + RECTL rclBounds; + DWORD cbRgnData; + DWORD ihBrush; + BYTE RgnData[1]; +} EMRFILLRGN, *PEMRFILLRGN; + +typedef struct tagEMRFORMAT { + DWORD dSignature; + DWORD nVersion; + DWORD cbData; + DWORD offData; +} EMRFORMAT; + +typedef struct tagSIZE { + LONG cx; + LONG cy; +} SIZE, *PSIZE, *LPSIZE, SIZEL, *PSIZEL, *LPSIZEL; + +typedef struct tagEMRFRAMERGN +{ + EMR emr; + RECTL rclBounds; + DWORD cbRgnData; + DWORD ihBrush; + SIZEL szlStroke; + BYTE RgnData[1]; +} EMRFRAMERGN, *PEMRFRAMERGN; + +typedef struct tagEMRGDICOMMENT +{ + EMR emr; + DWORD cbData; + BYTE Data[1]; +} EMRGDICOMMENT, *PEMRGDICOMMENT; + +typedef struct tagEMRINVERTRGN +{ + EMR emr; + RECTL rclBounds; + DWORD cbRgnData; + BYTE RgnData[1]; +} EMRINVERTRGN, *PEMRINVERTRGN, + EMRPAINTRGN, *PEMRPAINTRGN; + +typedef struct tagEMRLINETO +{ + EMR emr; + POINTL ptl; +} EMRLINETO, *PEMRLINETO, + EMRMOVETOEX, *PEMRMOVETOEX; + +typedef struct tagEMRMASKBLT +{ + EMR emr; + RECTL rclBounds; + LONG xDest; + LONG yDest; + LONG cxDest; + LONG cyDest; + DWORD dwRop; + LONG xSrc; + LONG ySrc; + XFORM xformSrc; + COLORREF crBkColorSrc; + DWORD iUsageSrc; + DWORD offBmiSrc; + DWORD cbBmiSrc; + DWORD offBitsSrc; + DWORD cbBitsSrc; + LONG xMask; + LONG yMask; + DWORD iUsageMask; + DWORD offBmiMask; + DWORD cbBmiMask; + DWORD offBitsMask; + DWORD cbBitsMask; +} EMRMASKBLT, *PEMRMASKBLT; + +typedef struct tagEMRMODIFYWORLDTRANSFORM +{ + EMR emr; + XFORM xform; + DWORD iMode; +} EMRMODIFYWORLDTRANSFORM, + PEMRMODIFYWORLDTRANSFORM; + +typedef struct tagEMROFFSETCLIPRGN +{ + EMR emr; + POINTL ptlOffset; +} EMROFFSETCLIPRGN, *PEMROFFSETCLIPRGN; + +typedef struct tagEMRPLGBLT +{ + EMR emr; + RECTL rclBounds; + POINTL aptlDest[3]; + LONG xSrc; + LONG ySrc; + LONG cxSrc; + LONG cySrc; + XFORM xformSrc; + COLORREF crBkColorSrc; + DWORD iUsageSrc; + DWORD offBmiSrc; + DWORD cbBmiSrc; + DWORD offBitsSrc; + DWORD cbBitsSrc; + LONG xMask; + LONG yMask; + DWORD iUsageMask; + DWORD offBmiMask; + DWORD cbBmiMask; + DWORD offBitsMask; + DWORD cbBitsMask; +} EMRPLGBLT, *PEMRPLGBLT; + +typedef struct tagEMRPOLYDRAW +{ + EMR emr; + RECTL rclBounds; + DWORD cptl; + POINTL aptl[1]; + BYTE abTypes[1]; +} EMRPOLYDRAW, *PEMRPOLYDRAW; + +typedef struct tagEMRPOLYDRAW16 +{ + EMR emr; + RECTL rclBounds; + DWORD cpts; + POINTS apts[1]; + BYTE abTypes[1]; +} EMRPOLYDRAW16, *PEMRPOLYDRAW16; + +typedef struct tagEMRPOLYLINE +{ + EMR emr; + RECTL rclBounds; + DWORD cptl; + POINTL aptl[1]; +} EMRPOLYLINE, *PEMRPOLYLINE, + EMRPOLYBEZIER, *PEMRPOLYBEZIER, + EMRPOLYGON, *PEMRPOLYGON, + EMRPOLYBEZIERTO, *PEMRPOLYBEZIERTO, + EMRPOLYLINETO, *PEMRPOLYLINETO; + +typedef struct tagEMRPOLYLINE16 +{ + EMR emr; + RECTL rclBounds; + DWORD cpts; + POINTL apts[1]; +} EMRPOLYLINE16, *PEMRPOLYLINE16, + EMRPOLYBEZIER16, *PEMRPOLYBEZIER16, + EMRPOLYGON16, *PEMRPOLYGON16, + EMRPOLYBEZIERTO16, *PEMRPOLYBEZIERTO16, + EMRPOLYLINETO16, *PEMRPOLYLINETO16; + +typedef struct tagEMRPOLYPOLYLINE +{ + EMR emr; + RECTL rclBounds; + DWORD nPolys; + DWORD cptl; + DWORD aPolyCounts[1]; + POINTL aptl[1]; +} EMRPOLYPOLYLINE, *PEMRPOLYPOLYLINE, + EMRPOLYPOLYGON, *PEMRPOLYPOLYGON; + +typedef struct tagEMRPOLYPOLYLINE16 +{ + EMR emr; + RECTL rclBounds; + DWORD nPolys; + DWORD cpts; + DWORD aPolyCounts[1]; + POINTS apts[1]; +} EMRPOLYPOLYLINE16, *PEMRPOLYPOLYLINE16, + EMRPOLYPOLYGON16, *PEMRPOLYPOLYGON16; + +typedef struct tagEMRPOLYTEXTOUTA +{ + EMR emr; + RECTL rclBounds; + DWORD iGraphicsMode; + FLOAT exScale; + FLOAT eyScale; + LONG cStrings; + EMRTEXT aemrtext[1]; +} EMRPOLYTEXTOUTA, *PEMRPOLYTEXTOUTA, + EMRPOLYTEXTOUTW, *PEMRPOLYTEXTOUTW; + +typedef struct tagEMRRESIZEPALETTE +{ + EMR emr; + DWORD ihPal; + DWORD cEntries; +} EMRRESIZEPALETTE, *PEMRRESIZEPALETTE; + +typedef struct tagEMRRESTOREDC +{ + EMR emr; + LONG iRelative; +} EMRRESTOREDC, *PEMRRESTOREDC; + +typedef struct tagEMRROUNDRECT +{ + EMR emr; + RECTL rclBox; + SIZEL szlCorner; +} EMRROUNDRECT, *PEMRROUNDRECT; + +typedef struct tagEMRSCALEVIEWPORTEXTEX +{ + EMR emr; + LONG xNum; + LONG xDenom; + LONG yNum; + LONG yDenom; +} EMRSCALEVIEWPORTEXTEX, *PEMRSCALEVIEWPORTEXTEX, + EMRSCALEWINDOWEXTEX, *PEMRSCALEWINDOWEXTEX; + +typedef struct tagEMRSELECTCOLORSPACE +{ + EMR emr; + DWORD ihCS; +} EMRSELECTCOLORSPACE, *PEMRSELECTCOLORSPACE, + EMRDELETECOLORSPACE, *PEMRDELETECOLORSPACE; +typedef struct tagEMRSELECTOBJECT +{ + EMR emr; + DWORD ihObject; +} EMRSELECTOBJECT, *PEMRSELECTOBJECT, + EMRDELETEOBJECT, *PEMRDELETEOBJECT; + +typedef struct tagEMRSELECTPALETTE +{ + EMR emr; + DWORD ihPal; +} EMRSELECTPALETTE, *PEMRSELECTPALETTE; + +typedef struct tagEMRSETARCDIRECTION +{ + EMR emr; + DWORD iArcDirection; +} EMRSETARCDIRECTION, *PEMRSETARCDIRECTION; + +typedef struct tagEMRSETTEXTCOLOR +{ + EMR emr; + COLORREF crColor; +} EMRSETBKCOLOR, *PEMRSETBKCOLOR, + EMRSETTEXTCOLOR, *PEMRSETTEXTCOLOR; + +typedef struct tagEMRSETCOLORADJUSTMENT +{ + EMR emr; + COLORADJUSTMENT ColorAdjustment; +} EMRSETCOLORADJUSTMENT, *PEMRSETCOLORADJUSTMENT; + +typedef struct tagEMRSETDIBITSTODEVICE +{ + EMR emr; + RECTL rclBounds; + LONG xDest; + LONG yDest; + LONG xSrc; + LONG ySrc; + LONG cxSrc; + LONG cySrc; + DWORD offBmiSrc; + DWORD cbBmiSrc; + DWORD offBitsSrc; + DWORD cbBitsSrc; + DWORD iUsageSrc; + DWORD iStartScan; + DWORD cScans; +} EMRSETDIBITSTODEVICE, *PEMRSETDIBITSTODEVICE; + +typedef struct tagEMRSETMAPPERFLAGS +{ + EMR emr; + DWORD dwFlags; +} EMRSETMAPPERFLAGS, *PEMRSETMAPPERFLAGS; + +typedef struct tagEMRSETMITERLIMIT +{ + EMR emr; + FLOAT eMiterLimit; +} EMRSETMITERLIMIT, *PEMRSETMITERLIMIT; + +typedef struct tagEMRSETPALETTEENTRIES +{ + EMR emr; + DWORD ihPal; + DWORD iStart; + DWORD cEntries; + PALETTEENTRY aPalEntries[1]; +} EMRSETPALETTEENTRIES, *PEMRSETPALETTEENTRIES; + +typedef struct tagEMRSETPIXELV +{ + EMR emr; + POINTL ptlPixel; + COLORREF crColor; +} EMRSETPIXELV, *PEMRSETPIXELV; + +typedef struct tagEMRSETVIEWPORTEXTEX +{ + EMR emr; + SIZEL szlExtent; +} EMRSETVIEWPORTEXTEX, *PEMRSETVIEWPORTEXTEX, + EMRSETWINDOWEXTEX, *PEMRSETWINDOWEXTEX; + +typedef struct tagEMRSETVIEWPORTORGEX +{ + EMR emr; + POINTL ptlOrigin; +} EMRSETVIEWPORTORGEX, *PEMRSETVIEWPORTORGEX, + EMRSETWINDOWORGEX, *PEMRSETWINDOWORGEX, + EMRSETBRUSHORGEX, *PEMRSETBRUSHORGEX; + +typedef struct tagEMRSETWORLDTRANSFORM +{ + EMR emr; + XFORM xform; +} EMRSETWORLDTRANSFORM, *PEMRSETWORLDTRANSFORM; + +typedef struct tagEMRSTRETCHBLT +{ + EMR emr; + RECTL rclBounds; + LONG xDest; + LONG yDest; + LONG cxDest; + LONG cyDest; + DWORD dwRop; + LONG xSrc; + LONG ySrc; + XFORM xformSrc; + COLORREF crBkColorSrc; + DWORD iUsageSrc; + DWORD offBmiSrc; + DWORD cbBmiSrc; + DWORD offBitsSrc; + DWORD cbBitsSrc; + LONG cxSrc; + LONG cySrc; +} EMRSTRETCHBLT, *PEMRSTRETCHBLT; + +typedef struct tagEMRSTRETCHDIBITS +{ + EMR emr; + RECTL rclBounds; + LONG xDest; + LONG yDest; + LONG xSrc; + LONG ySrc; + LONG cxSrc; + LONG cySrc; + DWORD offBmiSrc; + DWORD cbBmiSrc; + DWORD offBitsSrc; + DWORD cbBitsSrc; + DWORD iUsageSrc; + DWORD dwRop; + LONG cxDest; + LONG cyDest; +} EMRSTRETCHDIBITS, *PEMRSTRETCHDIBITS; + +typedef struct tagABORTPATH +{ + EMR emr; +} EMRABORTPATH, *PEMRABORTPATH, + EMRBEGINPATH, *PEMRBEGINPATH, + EMRENDPATH, *PEMRENDPATH, + EMRCLOSEFIGURE, *PEMRCLOSEFIGURE, + EMRFLATTENPATH, *PEMRFLATTENPATH, + EMRWIDENPATH, *PEMRWIDENPATH, + EMRSETMETARGN, *PEMRSETMETARGN, + EMRSAVEDC, *PEMRSAVEDC, + EMRREALIZEPALETTE, *PEMRREALIZEPALETTE; + +typedef struct tagEMRSELECTCLIPPATH +{ + EMR emr; + DWORD iMode; +} EMRSELECTCLIPPATH, *PEMRSELECTCLIPPATH, + EMRSETBKMODE, *PEMRSETBKMODE, + EMRSETMAPMODE, *PEMRSETMAPMODE, + EMRSETPOLYFILLMODE, *PEMRSETPOLYFILLMODE, + EMRSETROP2, *PEMRSETROP2, + EMRSETSTRETCHBLTMODE, *PEMRSETSTRETCHBLTMODE, + EMRSETTEXTALIGN, *PEMRSETTEXTALIGN, + EMRENABLEICM, *PEMRENABLEICM; + +typedef struct tagNMHDR { + HWND hwndFrom; + UINT idFrom; + UINT code; +} NMHDR; + +typedef struct _encorrecttext { + NMHDR nmhdr; + CHARRANGE chrg; + WORD seltyp; +} ENCORRECTTEXT; + +typedef struct _endropfiles { + NMHDR nmhdr; + HANDLE hDrop; + LONG cp; + WINBOOL fProtected; +} ENDROPFILES; + +typedef struct { + NMHDR nmhdr; + LONG cObjectCount; + LONG cch; +} ENSAVECLIPBOARD; + +typedef struct { + NMHDR nmhdr; + LONG iob; + LONG lOper; + HRESULT hr; +} ENOLEOPFAILED; + +typedef struct tagENHMETAHEADER { + DWORD iType; + DWORD nSize; + RECTL rclBounds; + RECTL rclFrame; + DWORD dSignature; + DWORD nVersion; + DWORD nBytes; + DWORD nRecords; + WORD nHandles; + WORD sReserved; + DWORD nDescription; + DWORD offDescription; + DWORD nPalEntries; + SIZEL szlDevice; + SIZEL szlMillimeters; +} ENHMETAHEADER, *LPENHMETAHEADER; + +typedef struct tagENHMETARECORD { + DWORD iType; + DWORD nSize; + DWORD dParm[1]; +} ENHMETARECORD, *PENHMETARECORD, *LPENHMETARECORD; + +typedef struct _enprotected { + NMHDR nmhdr; + UINT msg; + WPARAM wParam; + LPARAM lParam; + CHARRANGE chrg; +} ENPROTECTED; + +typedef struct _SERVICE_STATUS { + DWORD dwServiceType; + DWORD dwCurrentState; + DWORD dwControlsAccepted; + DWORD dwWin32ExitCode; + DWORD dwServiceSpecificExitCode; + DWORD dwCheckPoint; + DWORD dwWaitHint; +} SERVICE_STATUS, *LPSERVICE_STATUS; + +typedef struct _ENUM_SERVICE_STATUSA { + LPSTR lpServiceName; + LPSTR lpDisplayName; + SERVICE_STATUS ServiceStatus; +} ENUM_SERVICE_STATUSA, *LPENUM_SERVICE_STATUSA; + +typedef struct _ENUM_SERVICE_STATUSW { + LPWSTR lpServiceName; + LPWSTR lpDisplayName; + SERVICE_STATUS ServiceStatus; +} ENUM_SERVICE_STATUSW, *LPENUM_SERVICE_STATUSW; + +#ifdef UNICODE +#define ENUM_SERVICE_STATUS ENUM_SERVICE_STATUSW +#define LPENUM_SERVICE_STATUS LPENUM_SERVICE_STATUSW +#else +#define ENUM_SERVICE_STATUS ENUM_SERVICE_STATUSA +#define LPENUM_SERVICE_STATUS LPENUM_SERVICE_STATUSA +#endif + +typedef struct tagENUMLOGFONT { + LOGFONT elfLogFont; + BCHAR elfFullName[LF_FULLFACESIZE]; + BCHAR elfStyle[LF_FACESIZE]; +} ENUMLOGFONT; + +typedef struct tagENUMLOGFONTEX { + LOGFONT elfLogFont; + BCHAR elfFullName[LF_FULLFACESIZE]; + BCHAR elfStyle[LF_FACESIZE]; + BCHAR elfScript[LF_FACESIZE]; +} ENUMLOGFONTEX; + +typedef struct _EVENTLOGRECORD { + DWORD Length; + DWORD Reserved; + DWORD RecordNumber; + DWORD TimeGenerated; + DWORD TimeWritten; + DWORD EventID; + WORD EventType; + WORD NumStrings; + WORD EventCategory; + WORD ReservedFlags; + DWORD ClosingRecordNumber; + DWORD StringOffset; + DWORD UserSidLength; + DWORD UserSidOffset; + DWORD DataLength; + DWORD DataOffset; + +/* + Then follow: + + TCHAR SourceName[] + TCHAR Computername[] + SID UserSid + TCHAR Strings[] + BYTE Data[] + CHAR Pad[] + DWORD Length; +*/ + +} EVENTLOGRECORD; + +typedef struct tagEVENTMSG { + UINT message; + UINT paramL; + UINT paramH; + DWORD time; + HWND hwnd; +} EVENTMSG; + +typedef struct _EXT_BUTTON { + WORD idCommand; + WORD idsHelp; + WORD fsStyle; +} EXT_BUTTON, *LPEXT_BUTTON; + +typedef struct tagFILTERKEYS { + UINT cbSize; + DWORD dwFlags; + DWORD iWaitMSec; + DWORD iDelayMSec; + DWORD iRepeatMSec; + DWORD iBounceMSec; +} FILTERKEYS; + +typedef struct _FIND_NAME_BUFFER { + UCHAR length; + UCHAR access_control; + UCHAR frame_control; + UCHAR destination_addr[6]; + UCHAR source_addr[6]; + UCHAR routing_info[18]; +} FIND_NAME_BUFFER; + +typedef struct _FIND_NAME_HEADER { + WORD node_count; + UCHAR reserved; + UCHAR unique_group; +} FIND_NAME_HEADER; + +typedef +enum _FINDEX_INFO_LEVELS +{ + FindExInfoStandard, + FindExInfoMaxInfoLevel +} FINDEX_INFO_LEVELS; + +typedef +enum _FINDEX_SEARCH_OPS +{ + FindExSearchNameMatch, + FindExSearchLimitToDirectories, + FindExSearchLimitToDevices, + FindExSearchMaxSearchOp + +} FINDEX_SEARCH_OPS; + +#define FIND_FIRST_EX_CASE_SENSITIVE 0x00000001 + +typedef struct { + DWORD lStructSize; + HWND hwndOwner; + HINSTANCE hInstance; + DWORD Flags; + LPTSTR lpstrFindWhat; + LPTSTR lpstrReplaceWith; + WORD wFindWhatLen; + WORD wReplaceWithLen; + LPARAM lCustData; + LPFRHOOKPROC lpfnHook; + LPCTSTR lpTemplateName; +} FINDREPLACE, *LPFINDREPLACE; + +typedef struct _findtext { + CHARRANGE chrg; + LPSTR lpstrText; +} FINDTEXT; + +typedef struct _findtextex { + CHARRANGE chrg; + LPSTR lpstrText; + CHARRANGE chrgText; +} FINDTEXTEX; + +typedef struct _FMS_GETDRIVEINFO { + DWORD dwTotalSpace; + DWORD dwFreeSpace; + TCHAR szPath[260]; + TCHAR szVolume[14]; + TCHAR szShare[128]; +} FMS_GETDRIVEINFO; + +typedef struct _FMS_GETFILESEL { + FILETIME ftTime; + DWORD dwSize; + BYTE bAttr; + TCHAR szName[260]; +} FMS_GETFILESEL; + +typedef struct _FMS_LOAD { + DWORD dwSize; + TCHAR szMenuName[MENU_TEXT_LEN]; + HMENU hMenu; + UINT wMenuDelta; +} FMS_LOAD; + +typedef struct _FMS_TOOLBARLOAD { + DWORD dwSize; + LPEXT_BUTTON lpButtons; + WORD cButtons; + WORD cBitmaps; + WORD idBitmap; + HBITMAP hBitmap; +} FMS_TOOLBARLOAD; + + +typedef struct _FORM_INFO_1 { + DWORD Flags; + LPTSTR pName; + SIZEL Size; + RECTL ImageableArea; +} FORM_INFO_1; + +typedef struct _FORMAT_PARAMETERS { + MEDIA_TYPE MediaType; + DWORD StartCylinderNumber; + DWORD EndCylinderNumber; + DWORD StartHeadNumber; + DWORD EndHeadNumber; +} FORMAT_PARAMETERS ; + +typedef struct _formatrange { + HDC hdc; + HDC hdcTarget; + RECT rc; + RECT rcPage; + CHARRANGE chrg; +} FORMATRANGE; + +typedef struct tagGCP_RESULTS { + DWORD lStructSize; + LPTSTR lpOutString; + UINT *lpOrder; + INT *lpDx; + INT *lpCaretPos; + LPTSTR lpClass; + UINT *lpGlyphs; + UINT nGlyphs; + UINT nMaxFit; +} GCP_RESULTS, *LPGCP_RESULTS; + + +typedef struct _GLYPHMETRICS { + UINT gmBlackBoxX; + UINT gmBlackBoxY; + POINT gmptGlyphOrigin; + short gmCellIncX; + short gmCellIncY; +} GLYPHMETRICS, *LPGLYPHMETRICS; + +typedef struct tagHANDLETABLE { + HGDIOBJ objectHandle[1]; +} HANDLETABLE, *LPHANDLETABLE; + +typedef struct _HD_HITTESTINFO { + POINT pt; + UINT flags; + int iItem; +} HD_HITTESTINFO; + +typedef struct _HD_ITEM { + UINT mask; + int cxy; + LPTSTR pszText; + HBITMAP hbm; + int cchTextMax; + int fmt; + LPARAM lParam; +} HD_ITEM; + +typedef struct _WINDOWPOS { + HWND hwnd; + HWND hwndInsertAfter; + int x; + int y; + int cx; + int cy; + UINT flags; +} WINDOWPOS, *PWINDOWPOS, *LPWINDOWPOS; + +typedef struct _HD_LAYOUT { + RECT * prc; + WINDOWPOS * pwpos; +} HD_LAYOUT; + +typedef struct _HD_NOTIFY { + NMHDR hdr; + int iItem; + int iButton; + HD_ITEM * pitem; +} HD_NOTIFY; + +typedef struct tagHELPINFO { + UINT cbSize; + int iContextType; + int iCtrlId; + HANDLE hItemHandle; + DWORD dwContextId; + POINT MousePos; +} HELPINFO, *LPHELPINFO; + +typedef struct { + DWORD mkSize; + CHAR mkKeyList; + CHAR szKeyphrase[1]; +} MULTIKEYHELPA, *PMULTIKEYHELPA, *LPMULTIKEYHELPA; + +typedef struct { + DWORD mkSize; + WCHAR mkKeyList; + WCHAR szKeyphrase[1]; +} MULTIKEYHELPW, *PMULTIKEYHELPW, *LPMULTIKEYHELPW; + +typedef struct { + int wStructSize; + int x; + int y; + int dx; + int dy; + int wMax; + TCHAR rgchMember[2]; +} HELPWININFO; + +typedef struct { + int wStructSize; + int x; + int y; + int dx; + int dy; + int wMax; + CHAR rgchMember[2]; +} HELPWININFOA, *PHELPWININFOA, *LPHELPWININFOA; + +typedef struct { + int wStructSize; + int x; + int y; + int dx; + int dy; + int wMax; + WCHAR rgchMember[2]; +} HELPWININFOW, *PHELPWININFOW, *LPHELPWININFOW; + + +typedef struct tagHIGHCONTRAST { + UINT cbSize; + DWORD dwFlags; + LPTSTR lpszDefaultScheme; +} HIGHCONTRAST, * LPHIGHCONTRAST; + +typedef struct tagHSZPAIR { + HSZ hszSvc; + HSZ hszTopic; +} HSZPAIR; + +typedef struct _ICONINFO { + WINBOOL fIcon; + DWORD xHotspot; + DWORD yHotspot; + HBITMAP hbmMask; + HBITMAP hbmColor; +} ICONINFO, *PICONINFO; + +typedef struct tagICONMETRICS { + UINT cbSize; + int iHorzSpacing; + int iVertSpacing; + int iTitleWrap; + LOGFONT lfFont; +} ICONMETRICS, *LPICONMETRICS; + +typedef struct _IMAGEINFO { + HBITMAP hbmImage; + HBITMAP hbmMask; + int Unused1; + int Unused2; + RECT rcImage; +} IMAGEINFO; + +typedef struct _JOB_INFO_1 { + DWORD JobId; + LPTSTR pPrinterName; + LPTSTR pMachineName; + LPTSTR pUserName; + LPTSTR pDocument; + LPTSTR pDatatype; + LPTSTR pStatus; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD TotalPages; + DWORD PagesPrinted; + SYSTEMTIME Submitted; +} JOB_INFO_1; + +#if 0 +typedef struct _JOB_INFO_2 { + DWORD JobId; + LPTSTR pPrinterName; + LPTSTR pMachineName; + LPTSTR pUserName; + LPTSTR pDocument; + LPTSTR pNotifyName; + LPTSTR pDatatype; + LPTSTR pPrintProcessor; + LPTSTR pParameters; + LPTSTR pDriverName; + LPDEVMODE pDevMode; + LPTSTR pStatus; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD StartTime; + DWORD UntilTime; + DWORD TotalPages; + DWORD Size; + SYSTEMTIME Submitted; + DWORD Time; + DWORD PagesPrinted ; +} JOB_INFO_2; +#endif + +typedef struct tagKERNINGPAIR { + WORD wFirst; + WORD wSecond; + int iKernAmount; +} KERNINGPAIR, *LPKERNINGPAIR; + +typedef struct _LANA_ENUM { + UCHAR length; + UCHAR lana[MAX_LANA]; +} LANA_ENUM; + +typedef struct _LDT_ENTRY { + WORD LimitLow; + WORD BaseLow; + union { + struct { + BYTE BaseMid; + BYTE Flags1; + BYTE Flags2; + BYTE BaseHi; + } Bytes; + struct { + DWORD BaseMid : 8; + DWORD Type : 5; + DWORD Dpl : 2; + DWORD Pres : 1; + DWORD LimitHi : 4; + DWORD Sys : 1; + DWORD Reserved_0 : 1; + DWORD Default_Big : 1; + DWORD Granularity : 1; + DWORD BaseHi : 8; + } Bits; + } HighWord; +} LDT_ENTRY, *PLDT_ENTRY, *LPLDT_ENTRY; + +typedef struct tagLOCALESIGNATURE { + DWORD lsUsb[4]; + DWORD lsCsbDefault[2]; + DWORD lsCsbSupported[2]; +} LOCALESIGNATURE; + + #if 0 +typedef struct _LOCALGROUP_MEMBERS_INFO_0 { + PSID lgrmi0_sid; +} LOCALGROUP_MEMBERS_INFO_0; + #endif + +typedef struct _LOCALGROUP_MEMBERS_INFO_3 { + LPWSTR lgrmi3_domainandname; +} LOCALGROUP_MEMBERS_INFO_3; + +typedef long FXPT16DOT16, * LPFXPT16DOT16; + + + +typedef LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES_ARRAY[ANYSIZE_ARRAY]; +typedef LUID_AND_ATTRIBUTES_ARRAY *PLUID_AND_ATTRIBUTES_ARRAY; + +typedef struct _LV_COLUMN { + UINT mask; + int fmt; + int cx; + LPTSTR pszText; + int cchTextMax; + int iSubItem; +} LV_COLUMN; + +typedef struct _LV_ITEM { + UINT mask; + int iItem; + int iSubItem; + UINT state; + UINT stateMask; + LPTSTR pszText; + int cchTextMax; + int iImage; + LPARAM lParam; +} LV_ITEM; + +typedef struct tagLV_DISPINFO { + NMHDR hdr; + LV_ITEM item; +} LV_DISPINFO; + +typedef struct _LV_FINDINFO { + UINT flags; + LPCTSTR psz; + LPARAM lParam; + POINT pt; + UINT vkDirection; +} LV_FINDINFO; + +typedef struct _LV_HITTESTINFO { + POINT pt; + UINT flags; + int iItem; +} LV_HITTESTINFO; + +typedef struct tagLV_KEYDOWN { + NMHDR hdr; + WORD wVKey; + UINT flags; +} LV_KEYDOWN; + +typedef struct _MAT2 { + FIXED eM11; + FIXED eM12; + FIXED eM21; + FIXED eM22; +} MAT2, *LPMAT2; + +typedef struct tagMDICREATESTRUCT { + LPCTSTR szClass; + LPCTSTR szTitle; + HANDLE hOwner; + int x; + int y; + int cx; + int cy; + DWORD style; + LPARAM lParam; +} MDICREATESTRUCT; + +typedef MDICREATESTRUCT *LPMDICREATESTRUCT; + +typedef struct tagMEASUREITEMSTRUCT { + UINT CtlType; + UINT CtlID; + UINT itemID; + UINT itemWidth; + UINT itemHeight; + DWORD itemData; +} MEASUREITEMSTRUCT, *LPMEASUREITEMSTRUCT; + +typedef struct _MEMORYSTATUS { + DWORD dwLength; + DWORD dwMemoryLoad; + DWORD dwTotalPhys; + DWORD dwAvailPhys; + DWORD dwTotalPageFile; + DWORD dwAvailPageFile; + DWORD dwTotalVirtual; + DWORD dwAvailVirtual; +} MEMORYSTATUS, *LPMEMORYSTATUS; + +typedef struct { + WORD wVersion; + WORD wOffset; + DWORD dwHelpId; +} MENUEX_TEMPLATE_HEADER; + +typedef struct { + DWORD dwType; + DWORD dwState; + UINT uId; + BYTE bResInfo; + WCHAR szText[1]; + DWORD dwHelpId; +} MENUEX_TEMPLATE_ITEM; + +typedef struct tagMENUITEMINFO { + UINT cbSize; + UINT fMask; + UINT fType; + UINT fState; + UINT wID; + HMENU hSubMenu; + HBITMAP hbmpChecked; + HBITMAP hbmpUnchecked; + DWORD dwItemData; + LPTSTR dwTypeData; + UINT cch; +} MENUITEMINFO, *LPMENUITEMINFO; +typedef MENUITEMINFO CONST *LPCMENUITEMINFO; + +typedef struct { + WORD mtOption; + WORD mtID; + WCHAR mtString[1]; +} MENUITEMTEMPLATE; + +typedef struct { + WORD versionNumber; + WORD offset; +} MENUITEMTEMPLATEHEADER; +typedef VOID MENUTEMPLATE, *LPMENUTEMPLATE; + +typedef struct tagMETAFILEPICT { +#if 0 + LONG mm; + LONG xExt; + LONG yExt; + HMETAFILE hMF; +#endif +} METAFILEPICT, *PMETAFILEPICT, *LPMETAFILEPICT; + +typedef struct tagMETAHEADER { + WORD mtType; + WORD mtHeaderSize; + WORD mtVersion; + DWORD mtSize; + WORD mtNoObjects; + DWORD mtMaxRecord; + WORD mtNoParameters; +} METAHEADER PACKED; + +typedef struct tagMETARECORD { + DWORD rdSize; + WORD rdFunction; + WORD rdParm[1]; +} METARECORD, *LPMETARECORD; + +typedef struct tagMINIMIZEDMETRICS { + UINT cbSize; + int iWidth; + int iHorzGap; + int iVertGap; + int iArrange; +} MINIMIZEDMETRICS, *LPMINIMIZEDMETRICS; + +typedef struct tagMINMAXINFO { + POINT ptReserved; + POINT ptMaxSize; + POINT ptMaxPosition; + POINT ptMinTrackSize; + POINT ptMaxTrackSize; +} MINMAXINFO; + +typedef struct modemdevcaps_tag { + DWORD dwActualSize; + DWORD dwRequiredSize; + DWORD dwDevSpecificOffset; + DWORD dwDevSpecificSize; + + DWORD dwModemProviderVersion; + DWORD dwModemManufacturerOffset; + DWORD dwModemManufacturerSize; + DWORD dwModemModelOffset; + DWORD dwModemModelSize; + DWORD dwModemVersionOffset; + DWORD dwModemVersionSize; + + DWORD dwDialOptions; + DWORD dwCallSetupFailTimer; + DWORD dwInactivityTimeout; + DWORD dwSpeakerVolume; + DWORD dwSpeakerMode; + DWORD dwModemOptions; + DWORD dwMaxDTERate; + DWORD dwMaxDCERate; + + BYTE abVariablePortion [1]; +} MODEMDEVCAPS, *PMODEMDEVCAPS, *LPMODEMDEVCAPS; + +typedef struct modemsettings_tag { + DWORD dwActualSize; + DWORD dwRequiredSize; + DWORD dwDevSpecificOffset; + DWORD dwDevSpecificSize; + + DWORD dwCallSetupFailTimer; + DWORD dwInactivityTimeout; + DWORD dwSpeakerVolume; + DWORD dwSpeakerMode; + DWORD dwPreferredModemOptions; + + DWORD dwNegotiatedModemOptions; + DWORD dwNegotiatedDCERate; + + BYTE abVariablePortion[1]; +} MODEMSETTINGS, *PMODEMSETTINGS, *LPMODEMSETTINGS; + +typedef struct tagMONCBSTRUCT { + UINT cb; + DWORD dwTime; + HANDLE hTask; + DWORD dwRet; + UINT wType; + UINT wFmt; + HCONV hConv; + HSZ hsz1; + HSZ hsz2; + HDDEDATA hData; + DWORD dwData1; + DWORD dwData2; + CONVCONTEXT cc; + DWORD cbData; + DWORD Data[8]; +} MONCBSTRUCT; + +typedef struct tagMONCONVSTRUCT { + UINT cb; + WINBOOL fConnect; + DWORD dwTime; + HANDLE hTask; + HSZ hszSvc; + HSZ hszTopic; + HCONV hConvClient; + HCONV hConvServer; +} MONCONVSTRUCT; + +typedef struct tagMONERRSTRUCT { + UINT cb; + UINT wLastError; + DWORD dwTime; + HANDLE hTask; +} MONERRSTRUCT; + +typedef struct tagMONHSZSTRUCT { + UINT cb; + WINBOOL fsAction; + DWORD dwTime; + HSZ hsz; + HANDLE hTask; + TCHAR str[1]; +} MONHSZSTRUCT; + +typedef struct _MONITOR_INFO_1 { + LPTSTR pName; +} MONITOR_INFO_1; + +typedef struct _MONITOR_INFO_2 { + LPTSTR pName; + LPTSTR pEnvironment ; + LPTSTR pDLLName ; +} MONITOR_INFO_2; + +typedef struct tagMONLINKSTRUCT { + UINT cb; + DWORD dwTime; + HANDLE hTask; + WINBOOL fEstablished; + WINBOOL fNoData; + HSZ hszSvc; + HSZ hszTopic; + HSZ hszItem; + UINT wFmt; + WINBOOL fServer; + HCONV hConvServer; + HCONV hConvClient; +} MONLINKSTRUCT; + +typedef struct tagMONMSGSTRUCT { + UINT cb; + HWND hwndTo; + DWORD dwTime; + HANDLE hTask; + UINT wMsg; + WPARAM wParam; + LPARAM lParam; + DDEML_MSG_HOOK_DATA dmhd; +} MONMSGSTRUCT; + +typedef struct tagMOUSEHOOKSTRUCT { + POINT pt; + HWND hwnd; + UINT wHitTestCode; + DWORD dwExtraInfo; +} MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT, *LPMOUSEHOOKSTRUCT; + +typedef struct _MOUSEKEYS { + DWORD cbSize; + DWORD dwFlags; + DWORD iMaxSpeed; + DWORD iTimeToMaxSpeed; + DWORD iCtrlSpeed; + DWORD dwReserved1; + DWORD dwReserved2; +} MOUSEKEYS; + +typedef struct tagMSG { + HWND hwnd; + UINT message; + WPARAM wParam; + LPARAM lParam; + DWORD time; + POINT pt; +} MSG, *LPMSG; + +typedef void CALLBACK (*MSGBOXCALLBACK) (LPHELPINFO lpHelpInfo); + +typedef struct { + UINT cbSize; + HWND hwndOwner; + HINSTANCE hInstance; + LPCSTR lpszText; + LPCSTR lpszCaption; + DWORD dwStyle; + LPCSTR lpszIcon; + DWORD dwContextHelpId; + MSGBOXCALLBACK lpfnMsgBoxCallback; + DWORD dwLanguageId; +} MSGBOXPARAMS, *PMSGBOXPARAMS, *LPMSGBOXPARAMS; + +typedef struct _msgfilter { + NMHDR nmhdr; + UINT msg; + WPARAM wParam; + LPARAM lParam; +} MSGFILTER; + +typedef struct tagMULTIKEYHELP { + DWORD mkSize; + TCHAR mkKeylist; + TCHAR szKeyphrase[1]; +} MULTIKEYHELP; + +typedef struct _NAME_BUFFER { + UCHAR name[NCBNAMSZ]; + UCHAR name_num; + UCHAR name_flags; +} NAME_BUFFER; + +typedef struct _NCB { + UCHAR ncb_command; + UCHAR ncb_retcode; + UCHAR ncb_lsn; + UCHAR ncb_num; + PUCHAR ncb_buffer; + WORD ncb_length; + UCHAR ncb_callname[NCBNAMSZ]; + UCHAR ncb_name[NCBNAMSZ]; + UCHAR ncb_rto; + UCHAR ncb_sto; + void (*ncb_post) (struct _NCB *); + UCHAR ncb_lana_num; + UCHAR ncb_cmd_cplt; + UCHAR ncb_reserve[10]; + HANDLE ncb_event; +} NCB; + +typedef struct _NCCALCSIZE_PARAMS { + RECT rgrc[3]; + PWINDOWPOS lppos; +} NCCALCSIZE_PARAMS; + +typedef struct _NDDESHAREINFO { + LONG lRevision; + LPTSTR lpszShareName; + LONG lShareType; + LPTSTR lpszAppTopicList; + LONG fSharedFlag; + LONG fService; + LONG fStartAppFlag; + LONG nCmdShow; + LONG qModifyId[2]; + LONG cNumItems; + LPTSTR lpszItemList; +}NDDESHAREINFO; + +typedef struct _NETRESOURCE { + DWORD dwScope; + DWORD dwType; + DWORD dwDisplayType; + DWORD dwUsage; + LPTSTR lpLocalName; + LPTSTR lpRemoteName; + LPTSTR lpComment; + LPTSTR lpProvider; +} NETRESOURCE, *LPNETRESOURCE; + +typedef struct tagNEWCPLINFO { + DWORD dwSize; + DWORD dwFlags; + DWORD dwHelpContext; + LONG lData; + HICON hIcon; + TCHAR szName[32]; + TCHAR szInfo[64]; + TCHAR szHelpFile[128]; +} NEWCPLINFO; + +typedef struct tagNEWTEXTMETRIC { + LONG tmHeight; + LONG tmAscent; + LONG tmDescent; + LONG tmInternalLeading; + LONG tmExternalLeading; + LONG tmAveCharWidth; + LONG tmMaxCharWidth; + LONG tmWeight; + LONG tmOverhang; + LONG tmDigitizedAspectX; + LONG tmDigitizedAspectY; + BCHAR tmFirstChar; + BCHAR tmLastChar; + BCHAR tmDefaultChar; + BCHAR tmBreakChar; + BYTE tmItalic; + BYTE tmUnderlined; + BYTE tmStruckOut; + BYTE tmPitchAndFamily; + BYTE tmCharSet; + DWORD ntmFlags; + UINT ntmSizeEM; + UINT ntmCellHeight; + UINT ntmAvgWidth; +} NEWTEXTMETRIC; + + +typedef struct tagNEWTEXTMETRICEX { + NEWTEXTMETRIC ntmentm; + FONTSIGNATURE ntmeFontSignature; +} NEWTEXTMETRICEX; + +typedef struct tagNM_LISTVIEW { + NMHDR hdr; + int iItem; + int iSubItem; + UINT uNewState; + UINT uOldState; + UINT uChanged; + POINT ptAction; + LPARAM lParam; +} NM_LISTVIEW; + +typedef struct _TREEITEM *HTREEITEM; + +typedef struct _TV_ITEM { + UINT mask; + HTREEITEM hItem; + UINT state; + UINT stateMask; + LPTSTR pszText; + int cchTextMax; + int iImage; + int iSelectedImage; + int cChildren; + LPARAM lParam; +} TV_ITEM, *LPTV_ITEM; + +typedef struct _NM_TREEVIEW { + NMHDR hdr; + UINT action; + TV_ITEM itemOld; + TV_ITEM itemNew; + POINT ptDrag; +} NM_TREEVIEW; +typedef NM_TREEVIEW *LPNM_TREEVIEW; + +typedef struct _NM_UPDOWN { + NMHDR hdr; + int iPos; + int iDelta; +} NM_UPDOWNW; + +typedef struct tagNONCLIENTMETRICS { + UINT cbSize; + int iBorderWidth; + int iScrollWidth; + int iScrollHeight; + int iCaptionWidth; + int iCaptionHeight; + LOGFONT lfCaptionFont; + int iSmCaptionWidth; + int iSmCaptionHeight; + LOGFONT lfSmCaptionFont; + int iMenuWidth; + int iMenuHeight; + LOGFONT lfMenuFont; + LOGFONT lfStatusFont; + LOGFONT lfMessageFont; +} NONCLIENTMETRICS, * LPNONCLIENTMETRICS; + +typedef struct _SERVICE_ADDRESS { + DWORD dwAddressType; + DWORD dwAddressFlags; + DWORD dwAddressLength; + DWORD dwPrincipalLength; + BYTE *lpAddress; + BYTE *lpPrincipal; +} SERVICE_ADDRESS; + +typedef struct _SERVICE_ADDRESSES { + DWORD dwAddressCount; + SERVICE_ADDRESS Addresses[1]; +} SERVICE_ADDRESSES, *LPSERVICE_ADDRESSES; + +#ifndef _GUID_DEFINED +#define _GUID_DEFINED +typedef struct _GUID +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID, *LPGUID; +typedef GUID CLSID, *LPCLSID; +#endif + +typedef struct _SERVICE_INFO { + LPGUID lpServiceType; + LPTSTR lpServiceName; + LPTSTR lpComment; + LPTSTR lpLocale; + DWORD dwDisplayHint; + DWORD dwVersion; + DWORD dwTime; + LPTSTR lpMachineName; + LPSERVICE_ADDRESSES lpServiceAddress; + BLOB ServiceSpecificInfo; +} SERVICE_INFO; + +typedef struct _NS_SERVICE_INFO { + DWORD dwNameSpace; + SERVICE_INFO ServiceInfo; +} NS_SERVICE_INFO; + +typedef struct _numberfmt { + UINT NumDigits; + UINT LeadingZero; + UINT Grouping; + LPTSTR lpDecimalSep; + LPTSTR lpThousandSep; + UINT NegativeOrder; +} NUMBERFMT; + +typedef struct _OFSTRUCT { + BYTE cBytes; + BYTE fFixedDisk; + WORD nErrCode; + WORD Reserved1; + WORD Reserved2; + CHAR szPathName[OFS_MAXPATHNAME]; +} OFSTRUCT, *LPOFSTRUCT; + +typedef struct tagOFN { + DWORD lStructSize; + HWND hwndOwner; + HINSTANCE hInstance; + LPCTSTR lpstrFilter; + LPTSTR lpstrCustomFilter; + DWORD nMaxCustFilter; + DWORD nFilterIndex; + LPTSTR lpstrFile; + DWORD nMaxFile; + LPTSTR lpstrFileTitle; + DWORD nMaxFileTitle; + LPCTSTR lpstrInitialDir; + LPCTSTR lpstrTitle; + DWORD Flags; + WORD nFileOffset; + WORD nFileExtension; + LPCTSTR lpstrDefExt; + DWORD lCustData; + LPOFNHOOKPROC lpfnHook; + LPCTSTR lpTemplateName; +} OPENFILENAME, *LPOPENFILENAME; + +typedef struct _OFNOTIFY { + NMHDR hdr; + LPOPENFILENAME lpOFN; + LPTSTR pszFile; +} OFNOTIFY, *LPOFNOTIFY; + +typedef struct _OSVERSIONINFO { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + TCHAR szCSDVersion[ 128 ]; +} OSVERSIONINFO, *POSVERSIONINFO, *LPOSVERSIONINFO; + +typedef struct tagTEXTMETRIC { + LONG tmHeight; + LONG tmAscent; + LONG tmDescent; + LONG tmInternalLeading; + LONG tmExternalLeading; + LONG tmAveCharWidth; + LONG tmMaxCharWidth; + LONG tmWeight; + LONG tmOverhang; + LONG tmDigitizedAspectX; + LONG tmDigitizedAspectY; + BCHAR tmFirstChar; + BCHAR tmLastChar; + BCHAR tmDefaultChar; + BCHAR tmBreakChar; + BYTE tmItalic; + BYTE tmUnderlined; + BYTE tmStruckOut; + BYTE tmPitchAndFamily; + BYTE tmCharSet; +} TEXTMETRIC, *LPTEXTMETRIC; + +typedef struct _OUTLINETEXTMETRIC { + UINT otmSize; + TEXTMETRIC otmTextMetrics; + BYTE otmFiller; + PANOSE otmPanoseNumber; + UINT otmfsSelection; + UINT otmfsType; + int otmsCharSlopeRise; + int otmsCharSlopeRun; + int otmItalicAngle; + UINT otmEMSquare; + int otmAscent; + int otmDescent; + UINT otmLineGap; + UINT otmsCapEmHeight; + UINT otmsXHeight; + RECT otmrcFontBox; + int otmMacAscent; + int otmMacDescent; + UINT otmMacLineGap; + UINT otmusMinimumPPEM; + POINT otmptSubscriptSize; + POINT otmptSubscriptOffset; + POINT otmptSuperscriptSize; + POINT otmptSuperscriptOffset; + UINT otmsStrikeoutSize; + int otmsStrikeoutPosition; + int otmsUnderscoreSize; + int otmsUnderscorePosition; + PSTR otmpFamilyName; + PSTR otmpFaceName; + PSTR otmpStyleName; + PSTR otmpFullName; +} OUTLINETEXTMETRIC, *LPOUTLINETEXTMETRIC; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct tagPSD { + DWORD lStructSize; + HWND hwndOwner; + HGLOBAL hDevMode; + HGLOBAL hDevNames; + DWORD Flags; + POINT ptPaperSize; + RECT rtMinMargin; + RECT rtMargin; + HINSTANCE hInstance; + LPARAM lCustData; + LPPAGESETUPHOOK lpfnPageSetupHook; + LPPAGEPAINTHOOK lpfnPagePaintHook; + LPCTSTR lpPageSetupTemplateName; + HGLOBAL hPageSetupTemplate; +} PAGESETUPDLG, *LPPAGESETUPDLG; + +typedef struct tagPAINTSTRUCT { + HDC hdc; + WINBOOL fErase; + RECT rcPaint; + WINBOOL fRestore; + WINBOOL fIncUpdate; + BYTE rgbReserved[32]; +} PAINTSTRUCT, *LPPAINTSTRUCT; + +typedef struct _paraformat { + UINT cbSize; + DWORD dwMask; + WORD wNumbering; + WORD wReserved; + LONG dxStartIndent; + LONG dxRightIndent; + LONG dxOffset; + WORD wAlignment; + SHORT cTabCount; + LONG rgxTabs[MAX_TAB_STOPS]; +} PARAFORMAT; + +typedef struct _PERF_COUNTER_BLOCK { + DWORD ByteLength; +} PERF_COUNTER_BLOCK; + +typedef struct _PERF_COUNTER_DEFINITION { + DWORD ByteLength; + DWORD CounterNameTitleIndex; + LPWSTR CounterNameTitle; + DWORD CounterHelpTitleIndex; + LPWSTR CounterHelpTitle; + DWORD DefaultScale; + DWORD DetailLevel; + DWORD CounterType; + DWORD CounterSize; + DWORD CounterOffset; +} PERF_COUNTER_DEFINITION; + +typedef struct _PERF_DATA_BLOCK { + WCHAR Signature[4]; + DWORD LittleEndian; + DWORD Version; + DWORD Revision; + DWORD TotalByteLength; + DWORD HeaderLength; + DWORD NumObjectTypes; + DWORD DefaultObject; + SYSTEMTIME SystemTime; + LARGE_INTEGER PerfTime; + LARGE_INTEGER PerfFreq; + LARGE_INTEGER PerfTime100nSec; + DWORD SystemNameLength; + DWORD SystemNameOffset; +} PERF_DATA_BLOCK; + +typedef struct _PERF_INSTANCE_DEFINITION { + DWORD ByteLength; + DWORD ParentObjectTitleIndex; + DWORD ParentObjectInstance; + DWORD UniqueID; + DWORD NameOffset; + DWORD NameLength; +} PERF_INSTANCE_DEFINITION; + +typedef struct _PERF_OBJECT_TYPE { + DWORD TotalByteLength; + DWORD DefinitionLength; + DWORD HeaderLength; + DWORD ObjectNameTitleIndex; + LPWSTR ObjectNameTitle; + DWORD ObjectHelpTitleIndex; + LPWSTR ObjectHelpTitle; + DWORD DetailLevel; + DWORD NumCounters; + DWORD DefaultCounter; + DWORD NumInstances; + DWORD CodePage; + LARGE_INTEGER PerfTime; + LARGE_INTEGER PerfFreq; +} PERF_OBJECT_TYPE; + +typedef struct _POLYTEXT { + int x; + int y; + UINT n; + LPCTSTR lpstr; + UINT uiFlags; + RECT rcl; + int *pdx; +} POLYTEXT, *LPPOLYTEXT; + +typedef struct _PORT_INFO_1 { + LPTSTR pName; +} PORT_INFO_1; + +typedef struct _PORT_INFO_2 { + LPSTR pPortName; + LPSTR pMonitorName; + LPSTR pDescription; + DWORD fPortType; + DWORD Reserved; +} PORT_INFO_2; + +typedef struct _PREVENT_MEDIA_REMOVAL { + BOOLEAN PreventMediaRemoval; +} PREVENT_MEDIA_REMOVAL ; + +typedef struct tagPD { + DWORD lStructSize; + HWND hwndOwner; + HANDLE hDevMode; + HANDLE hDevNames; + HDC hDC; + DWORD Flags; + WORD nFromPage; + WORD nToPage; + WORD nMinPage; + WORD nMaxPage; + WORD nCopies; + HINSTANCE hInstance; + DWORD lCustData; + LPPRINTHOOKPROC lpfnPrintHook; + LPSETUPHOOKPROC lpfnSetupHook; + LPCTSTR lpPrintTemplateName; + LPCTSTR lpSetupTemplateName; + HANDLE hPrintTemplate; + HANDLE hSetupTemplate; +} PRINTDLG PACKED, *LPPRINTDLG PACKED; + +typedef struct _PRINTER_DEFAULTSA +{ + LPTSTR pDatatype; + LPDEVMODEA pDevMode; + ACCESS_MASK DesiredAccess; +} PRINTER_DEFAULTSA, *PPRINTER_DEFAULTSA, *LPPRINTER_DEFAULTSA; + +typedef struct _PRINTER_DEFAULTSW +{ + LPTSTR pDatatype; + LPDEVMODEA pDevMode; + ACCESS_MASK DesiredAccess; +} PRINTER_DEFAULTSW, *PPRINTER_DEFAULTSW, *LPPRINTER_DEFAULTSW; + +typedef struct _PRINTER_INFO_1 { + DWORD Flags; + LPTSTR pDescription; + LPTSTR pName; + LPTSTR pComment; +} PRINTER_INFO_1, *PPRINTER_INFO_1, *LPPRINTER_INFO_1; + + #if 0 +typedef struct _PRINTER_INFO_2 { + LPTSTR pServerName; + LPTSTR pPrinterName; + LPTSTR pShareName; + LPTSTR pPortName; + LPTSTR pDriverName; + LPTSTR pComment; + LPTSTR pLocation; + LPDEVMODE pDevMode; + LPTSTR pSepFile; + LPTSTR pPrintProcessor; + LPTSTR pDatatype; + LPTSTR pParameters; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + DWORD Attributes; + DWORD Priority; + DWORD DefaultPriority; + DWORD StartTime; + DWORD UntilTime; + DWORD Status; + DWORD cJobs; + DWORD AveragePPM; +} PRINTER_INFO_2; + + +typedef struct _PRINTER_INFO_3 { + PSECURITY_DESCRIPTOR pSecurityDescriptor; +} PRINTER_INFO_3; + #endif + +typedef struct _PRINTER_INFO_4 { + LPTSTR pPrinterName; + LPTSTR pServerName; + DWORD Attributes; +} PRINTER_INFO_4; + +typedef struct _PRINTER_INFO_5 { + LPTSTR pPrinterName; + LPTSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeout; + DWORD TransmissionRetryTimeout; +} PRINTER_INFO_5; + +typedef struct _PRINTER_NOTIFY_INFO_DATA { + WORD Type; + WORD Field; + DWORD Reserved; + DWORD Id; + union { + DWORD adwData[2]; + struct { + DWORD cbBuf; + LPVOID pBuf; + } Data; + } NotifyData; +} PRINTER_NOTIFY_INFO_DATA; + +typedef struct _PRINTER_NOTIFY_INFO { + DWORD Version; + DWORD Flags; + DWORD Count; + PRINTER_NOTIFY_INFO_DATA aData[1]; +} PRINTER_NOTIFY_INFO; + +typedef struct _PRINTER_NOTIFY_OPTIONS_TYPE { + WORD Type; + WORD Reserved0; + DWORD Reserved1; + DWORD Reserved2; + DWORD Count; + PWORD pFields; +} PRINTER_NOTIFY_OPTIONS_TYPE, *PPRINTER_NOTIFY_OPTIONS_TYPE; + +typedef struct _PRINTER_NOTIFY_OPTIONS { + DWORD Version; + DWORD Flags; + DWORD Count; + PPRINTER_NOTIFY_OPTIONS_TYPE pTypes; +} PRINTER_NOTIFY_OPTIONS; + +typedef struct _PRINTPROCESSOR_INFO_1 { + LPTSTR pName; +} PRINTPROCESSOR_INFO_1; + + +typedef struct _PROCESS_HEAP_ENTRY { + PVOID lpData; + DWORD cbData; + BYTE cbOverhead; + BYTE iRegionIndex; + WORD wFlags; + DWORD dwCommittedSize; + DWORD dwUnCommittedSize; + LPVOID lpFirstBlock; + LPVOID lpLastBlock; + HANDLE hMem; +} PROCESS_HEAPENTRY, *LPPROCESS_HEAP_ENTRY; + +typedef struct _PROCESS_INFORMATION { + HANDLE hProcess; + HANDLE hThread; + DWORD dwProcessId; + DWORD dwThreadId; +} PROCESS_INFORMATION, *LPPROCESS_INFORMATION; + +typedef UINT CALLBACK (*LPFNPSPCALLBACK) (HWND, UINT, LPVOID); + +typedef struct _PROPSHEETPAGE { + DWORD dwSize; + DWORD dwFlags; + HINSTANCE hInstance; + union { + LPCTSTR pszTemplate; + LPCDLGTEMPLATE pResource; + } u1; + union { + HICON hIcon; + LPCTSTR pszIcon; + } u2; + LPCTSTR pszTitle; + DLGPROC pfnDlgProc; + LPARAM lParam; + LPFNPSPCALLBACK pfnCallback; + UINT * pcRefParent; +} PROPSHEETPAGE, *LPPROPSHEETPAGE; +typedef const PROPSHEETPAGE *LPCPROPSHEETPAGE; + +typedef struct _PSP *HPROPSHEETPAGE; +typedef struct _PROPSHEETHEADER { + DWORD dwSize; + DWORD dwFlags; + HWND hwndParent; + HINSTANCE hInstance; + union { + HICON hIcon; + LPCTSTR pszIcon; + } u1; + LPCTSTR pszCaption; + UINT nPages; + union { + UINT nStartPage; + LPCTSTR pStartPage; + } u2; + union { + LPCPROPSHEETPAGE ppsp; + HPROPSHEETPAGE *phpage; + } u3; + PFNPROPSHEETCALLBACK pfnCallback; +} PROPSHEETHEADER, *LPPROPSHEETHEADER; +typedef const PROPSHEETHEADER *LPCPROPSHEETHEADER; + +/* PropertySheet callbacks */ +typedef WINBOOL CALLBACK (*LPFNADDPROPSHEETPAGE) (HPROPSHEETPAGE, LPARAM); +typedef WINBOOL CALLBACK (*LPFNADDPROPSHEETPAGES) (LPVOID, + LPFNADDPROPSHEETPAGE, + LPARAM); + +typedef struct _PROTOCOL_INFO { + DWORD dwServiceFlags; + INT iAddressFamily; + INT iMaxSockAddr; + INT iMinSockAddr; + INT iSocketType; + INT iProtocol; + DWORD dwMessageSize; + LPTSTR lpProtocol; +} PROTOCOL_INFO; + +typedef struct _PROVIDOR_INFO_1 { + LPTSTR pName; + LPTSTR pEnvironment ; + LPTSTR pDLLName ; +} PROVIDOR_INFO_1; + +typedef struct _PSHNOTIFY { + NMHDR hdr; + LPARAM lParam; +} PSHNOTIFY, *LPPSHNOTIFY; + +typedef struct _punctuation { + UINT iSize; + LPSTR szPunctuation; +} PUNCTUATION; + +typedef struct _QUERY_SERVICE_CONFIGA { + DWORD dwServiceType; + DWORD dwStartType; + DWORD dwErrorControl; + LPSTR lpBinaryPathName; + LPSTR lpLoadOrderGroup; + DWORD dwTagId; + LPSTR lpDependencies; + LPSTR lpServiceStartName; + LPSTR lpDisplayName; +} QUERY_SERVICE_CONFIGA, *LPQUERY_SERVICE_CONFIGA; + +typedef struct _QUERY_SERVICE_CONFIGW { + DWORD dwServiceType; + DWORD dwStartType; + DWORD dwErrorControl; + LPWSTR lpBinaryPathName; + LPWSTR lpLoadOrderGroup; + DWORD dwTagId; + LPWSTR lpDependencies; + LPWSTR lpServiceStartName; + LPWSTR lpDisplayName; +} QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW; + +#ifdef UNICODE +#define QUERY_SERVICE_CONFIG QUERY_SERVICE_CONFIGW +#define LPQUERY_SERVICE_CONFIG LPQUERY_SERVICE_CONFIGW +#else +#define QUERY_SERVICE_CONFIG QUERY_SERVICE_CONFIGA +#define LPQUERY_SERVICE_CONFIG LPQUERY_SERVICE_CONFIGA +#endif + +typedef struct _QUERY_SERVICE_LOCK_STATUSA { + DWORD fIsLocked; + LPSTR lpLockOwner; + DWORD dwLockDuration; +} QUERY_SERVICE_LOCK_STATUSA, *LPQUERY_SERVICE_LOCK_STATUSA; + +typedef struct _QUERY_SERVICE_LOCK_STATUSW { + DWORD fIsLocked; + LPWSTR lpLockOwner; + DWORD dwLockDuration; +} QUERY_SERVICE_LOCK_STATUSW, *LPQUERY_SERVICE_LOCK_STATUSW; + +#ifdef UNICODE +#define QUERY_SERVICE_LOCK_STATUS QUERY_SERVICE_LOCK_STATUSW +#define LPQUERY_SERVICE_LOCK_STATUS LPQUERY_SERVICE_LOCK_STATUSW +#else +#define QUERY_SERVICE_LOCK_STATUS QUERY_SERVICE_LOCK_STATUSA +#define LPQUERY_SERVICE_LOCK_STATUS LPQUERY_SERVICE_LOCK_STATUSA +#endif + +typedef struct _RASAMB { + DWORD dwSize; + DWORD dwError; + TCHAR szNetBiosError[ NETBIOS_NAME_LEN + 1 ]; + BYTE bLana; +} RASAMB; + +typedef struct _RASCONN { + DWORD dwSize; + HRASCONN hrasconn; + TCHAR szEntryName[RAS_MaxEntryName + 1]; + + CHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; + CHAR szDeviceName[ RAS_MaxDeviceName + 1 ]; +} RASCONN ; + +typedef struct _RASCONNSTATUS { + DWORD dwSize; + RASCONNSTATE rasconnstate; + DWORD dwError; + TCHAR szDeviceType[RAS_MaxDeviceType + 1]; + TCHAR szDeviceName[RAS_MaxDeviceName + 1]; +} RASCONNSTATUS; + +typedef struct _RASDIALEXTENSIONS { + DWORD dwSize; + DWORD dwfOptions; + HWND hwndParent; + DWORD reserved; +} RASDIALEXTENSIONS; + +typedef struct _RASDIALPARAMS { + DWORD dwSize; + TCHAR szEntryName[RAS_MaxEntryName + 1]; + TCHAR szPhoneNumber[RAS_MaxPhoneNumber + 1]; + TCHAR szCallbackNumber[RAS_MaxCallbackNumber + 1]; + TCHAR szUserName[UNLEN + 1]; + TCHAR szPassword[PWLEN + 1]; + TCHAR szDomain[DNLEN + 1] ; +} RASDIALPARAMS; + +typedef struct _RASENTRYNAME { + DWORD dwSize; + TCHAR szEntryName[RAS_MaxEntryName + 1]; +}RASENTRYNAME; + +typedef struct _RASPPPIP { + DWORD dwSize; + DWORD dwError; + TCHAR szIpAddress[ RAS_MaxIpAddress + 1 ]; +} RASPPPIP; + +typedef struct _RASPPPIPX { + DWORD dwSize; + DWORD dwError; + TCHAR szIpxAddress[ RAS_MaxIpxAddress + 1 ]; +} RASPPPIPX; + +typedef struct _RASPPPNBF { + DWORD dwSize; + DWORD dwError; + DWORD dwNetBiosError; + TCHAR szNetBiosError[ NETBIOS_NAME_LEN + 1 ]; + TCHAR szWorkstationName[ NETBIOS_NAME_LEN + 1 ]; + BYTE bLana; +} RASPPPNBF; + +typedef struct _RASTERIZER_STATUS { + short nSize; + short wFlags; + short nLanguageID; +} RASTERIZER_STATUS, *LPRASTERIZER_STATUS; + +typedef struct _REASSIGN_BLOCKS { + WORD Reserved; + WORD Count; + DWORD BlockNumber[1]; +} REASSIGN_BLOCKS ; + +typedef struct _REMOTE_NAME_INFO { + LPTSTR lpUniversalName; + LPTSTR lpConnectionName; + LPTSTR lpRemainingPath; +} REMOTE_NAME_INFO; + +/* + TODO: OLE +typedef struct _reobject { + DWORD cbStruct; + LONG cp; + CLSID clsid; + LPOLEOBJECT poleobj; + LPSTORAGE pstg; + LPOLECLIENTSITE polesite; + SIZEL sizel; + DWORD dvaspect; + DWORD dwFlags; + DWORD dwUser; +} REOBJECT; +*/ + +typedef struct _repastespecial { + DWORD dwAspect; + DWORD dwParam; +} REPASTESPECIAL; + +typedef struct _reqresize { + NMHDR nmhdr; + RECT rc; +} REQRESIZE; + +typedef struct _RGNDATAHEADER { + DWORD dwSize; + DWORD iType; + DWORD nCount; + DWORD nRgnSize; + RECT rcBound; +} RGNDATAHEADER; + +typedef struct _RGNDATA { + RGNDATAHEADER rdh; + char Buffer[1]; +} RGNDATA, *PRGNDATA, *LPRGNDATA; + +typedef struct tagSCROLLINFO { + UINT cbSize; + UINT fMask; + int nMin; + int nMax; + UINT nPage; + int nPos; + int nTrackPos; +} SCROLLINFO, *LPSCROLLINFO; +typedef SCROLLINFO const *LPCSCROLLINFO; + + +typedef struct _selchange { + NMHDR nmhdr; + CHARRANGE chrg; + WORD seltyp; +} SELCHANGE; + +typedef struct tagSERIALKEYS { + DWORD cbSize; + DWORD dwFlags; + LPSTR lpszActivePort; + LPSTR lpszPort; + DWORD iBaudRate; + DWORD iPortState; +} SERIALKEYS, * LPSERIALKEYS; + +typedef struct _SERVICE_TABLE_ENTRYA { + LPSTR lpServiceName; + LPSERVICE_MAIN_FUNCTION lpServiceProc; +} SERVICE_TABLE_ENTRYA, *LPSERVICE_TABLE_ENTRYA; + +typedef struct _SERVICE_TABLE_ENTRYW { + LPWSTR lpServiceName; + LPSERVICE_MAIN_FUNCTION lpServiceProc; +} SERVICE_TABLE_ENTRYW, *LPSERVICE_TABLE_ENTRYW; + +#ifdef UNICODE +#define SERVICE_TABLE_ENTRY SERVICE_TABLE_ENTRYW +#define LPSERVICE_TABLE_ENTRY LPSERVICE_TABLE_ENTRYW +#else +#define SERVICE_TABLE_ENTRY SERVICE_TABLE_ENTRYA +#define LPSERVICE_TABLE_ENTRY LPSERVICE_TABLE_ENTRYA +#endif + + +typedef struct _SERVICE_TYPE_VALUE_ABS { + DWORD dwNameSpace; + DWORD dwValueType; + DWORD dwValueSize; + LPTSTR lpValueName; + PVOID lpValue; +} SERVICE_TYPE_VALUE_ABS; + +typedef struct _SERVICE_TYPE_INFO_ABS { + LPTSTR lpTypeName; + DWORD dwValueCount; + SERVICE_TYPE_VALUE_ABS Values[1]; +} SERVICE_TYPE_INFO_ABS; + +typedef struct _SESSION_BUFFER { + UCHAR lsn; + UCHAR state; + UCHAR local_name[NCBNAMSZ]; + UCHAR remote_name[NCBNAMSZ]; + UCHAR rcvs_outstanding; + UCHAR sends_outstanding; +} SESSION_BUFFER; + +typedef struct _SESSION_HEADER { + UCHAR sess_name; + UCHAR num_sess; + UCHAR rcv_dg_outstanding; + UCHAR rcv_any_outstanding; +} SESSION_HEADER; + +typedef enum tagSHCONTF { + SHCONTF_FOLDERS = 32, + SHCONTF_NONFOLDERS = 64, + SHCONTF_INCLUDEHIDDEN = 128, +} SHCONTF; + +typedef struct _SHFILEINFO { + HICON hIcon; + int iIcon; + DWORD dwAttributes; + char szDisplayName[MAX_PATH]; + char szTypeName[80]; +} SHFILEINFO; + +typedef WORD FILEOP_FLAGS; +typedef struct _SHFILEOPSTRUCT { + HWND hwnd; + UINT wFunc; + LPCSTR pFrom; + LPCSTR pTo; + FILEOP_FLAGS fFlags; + WINBOOL fAnyOperationsAborted; + LPVOID hNameMappings; + LPCSTR lpszProgressTitle; +} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT; + +typedef enum tagSHGDN { + SHGDN_NORMAL = 0, + SHGDN_INFOLDER = 1, + SHGDN_FORPARSING = 0x8000, +} SHGNO; + +typedef struct _SHNAMEMAPPING { + LPSTR pszOldPath; + LPSTR pszNewPath; + int cchOldPath; + int cchNewPath; +} SHNAMEMAPPING, *LPSHNAMEMAPPING; + +typedef struct tagSOUNDSENTRY { + UINT cbSize; + DWORD dwFlags; + DWORD iFSTextEffect; + DWORD iFSTextEffectMSec; + DWORD iFSTextEffectColorBits; + DWORD iFSGrafEffect; + DWORD iFSGrafEffectMSec; + DWORD iFSGrafEffectColor; + DWORD iWindowsEffect; + DWORD iWindowsEffectMSec; + LPTSTR lpszWindowsEffectDLL; + DWORD iWindowsEffectOrdinal; +} SOUNDSENTRY, *LPSOUNDSENTRY; + +typedef struct _STARTUPINFOA { + DWORD cb; + LPSTR lpReserved; + LPSTR lpDesktop; + LPSTR lpTitle; + DWORD dwX; + DWORD dwY; + DWORD dwXSize; + DWORD dwYSize; + DWORD dwXCountChars; + DWORD dwYCountChars; + DWORD dwFillAttribute; + DWORD dwFlags; + WORD wShowWindow; + WORD cbReserved2; + LPBYTE lpReserved2; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; +} STARTUPINFOA, *LPSTARTUPINFOA; + +typedef struct _STARTUPINFOW { + DWORD cb; + LPWSTR lpReserved; + LPWSTR lpDesktop; + LPWSTR lpTitle; + DWORD dwX; + DWORD dwY; + DWORD dwXSize; + DWORD dwYSize; + DWORD dwXCountChars; + DWORD dwYCountChars; + DWORD dwFillAttribute; + DWORD dwFlags; + WORD wShowWindow; + WORD cbReserved2; + LPBYTE lpReserved2; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; +} STARTUPINFOW, *LPSTARTUPINFOW; + +#ifdef UNICODE +typedef STARTUPINFOW STARTUPINFO; +typedef LPSTARTUPINFOW LPSTARTUPINFO; +#else +typedef STARTUPINFOA STARTUPINFO; +typedef LPSTARTUPINFOA LPSTARTUPINFO; +#endif /* UNICODE */ + +typedef struct tagSTICKYKEYS { + DWORD cbSize; + DWORD dwFlags; +} STICKYKEYS, *LPSTICKYKEYS; + +typedef struct _STRRET { + UINT uType; + union + { + LPWSTR pOleStr; + UINT uOffset; + char cStr[MAX_PATH]; + } DUMMYUNIONNAME; +} STRRET, *LPSTRRET; + +typedef struct _tagSTYLEBUF { + DWORD dwStyle; + CHAR szDescription[32]; +} STYLEBUF, *LPSTYLEBUF; + +typedef struct tagSTYLESTRUCT { + DWORD styleOld; + DWORD styleNew; +} STYLESTRUCT, * LPSTYLESTRUCT; + +typedef struct _SYSTEM_AUDIT_ACE { + ACE_HEADER Header; + ACCESS_MASK Mask; + DWORD SidStart; +} SYSTEM_AUDIT_ACE; + +typedef struct _SYSTEM_INFO +{ + union + { + DWORD dwOemId; + struct + { + WORD wProcessorArchitecture; + WORD wReserved; + } + s; + } + u; + DWORD dwPageSize; + LPVOID lpMinimumApplicationAddress; + LPVOID lpMaximumApplicationAddress; + DWORD dwActiveProcessorMask; + DWORD dwNumberOfProcessors; + DWORD dwProcessorType; + DWORD dwAllocationGranularity; + WORD wProcessorLevel; + WORD wProcessorRevision; +} SYSTEM_INFO, *LPSYSTEM_INFO; + +typedef struct _SYSTEM_POWER_STATUS { + BYTE ACLineStatus; + BYTE BatteryFlag; + BYTE BatteryLifePercent; + BYTE Reserved1; + DWORD BatteryLifeTime; + DWORD BatteryFullLifeTime; +} SYSTEM_POWER_STATUS; +typedef SYSTEM_POWER_STATUS *LPSYSTEM_POWER_STATUS; + +typedef struct _TAPE_ERASE { + ULONG Type; +} TAPE_ERASE; + +typedef struct _TAPE_GET_DRIVE_PARAMETERS { + BOOLEAN ECC; + BOOLEAN Compression; + BOOLEAN DataPadding; + BOOLEAN ReportSetmarks; + ULONG DefaultBlockSize; + ULONG MaximumBlockSize; + ULONG MinimumBlockSize; + ULONG MaximumPartitionCount; + ULONG FeaturesLow; + ULONG FeaturesHigh; + ULONG EOTWarningZoneSize; +} TAPE_GET_DRIVE_PARAMETERS; + +typedef struct _TAPE_GET_MEDIA_PARAMETERS { + LARGE_INTEGER Capacity; + LARGE_INTEGER Remaining; + DWORD BlockSize; + DWORD PartitionCount; + BOOLEAN WriteProtected; +} TAPE_GET_MEDIA_PARAMETERS; + +typedef struct _TAPE_GET_POSITION { + ULONG Type; + ULONG Partition; + ULONG OffsetLow; + ULONG OffsetHigh; +} TAPE_GET_POSITION; + +typedef struct _TAPE_PREPARE { + ULONG Operation; +} TAPE_PREPARE; + +typedef struct _TAPE_SET_DRIVE_PARAMETERS { + BOOLEAN ECC; + BOOLEAN Compression; + BOOLEAN DataPadding; + BOOLEAN ReportSetmarks; + ULONG EOTWarningZoneSize; +} TAPE_SET_DRIVE_PARAMETERS; + +typedef struct _TAPE_SET_MEDIA_PARAMETERS { + ULONG BlockSize; +} TAPE_SET_MEDIA_PARAMETERS; + +typedef struct _TAPE_SET_POSITION { + ULONG Method; + ULONG Partition; + ULONG OffsetLow; + ULONG OffsetHigh; +} TAPE_SET_POSITION; + +typedef struct _TAPE_WRITE_MARKS { + ULONG Type; + ULONG Count; +} TAPE_WRITE_MARKS; + +typedef struct { + HINSTANCE hInst; + UINT nID; +} TBADDBITMAP, *LPTBADDBITMAP; + +typedef struct _TBBUTTON { + int iBitmap; + int idCommand; + BYTE fsState; + BYTE fsStyle; + DWORD dwData; + int iString; +} TBBUTTON, * PTBBUTTON, * LPTBBUTTON; +typedef const TBBUTTON * LPCTBBUTTON; + +typedef struct { + NMHDR hdr; + int iItem; + TBBUTTON tbButton; + int cchText; + LPTSTR pszText; +} TBNOTIFY, *LPTBNOTIFY; + +typedef struct { + HKEY hkr; + LPCTSTR pszSubKey; + LPCTSTR pszValueName; +} TBSAVEPARAMS; + +typedef struct _TC_HITTESTINFO { + POINT pt; + UINT flags; +} TC_HITTESTINFO; + +typedef struct _TC_ITEM { + UINT mask; + UINT lpReserved1; + UINT lpReserved2; + LPTSTR pszText; + int cchTextMax; + int iImage; + LPARAM lParam; +} TC_ITEM; + +typedef struct _TC_ITEMHEADER { + UINT mask; + UINT lpReserved1; + UINT lpReserved2; + LPTSTR pszText; + int cchTextMax; + int iImage; +} TC_ITEMHEADER; + +typedef struct _TC_KEYDOWN { + NMHDR hdr; + WORD wVKey; + UINT flags; +} TC_KEYDOWN; + +typedef struct _textrange { + CHARRANGE chrg; + LPSTR lpstrText; +} TEXTRANGE; + +typedef struct tagTOGGLEKEYS { + DWORD cbSize; + DWORD dwFlags; +} TOGGLEKEYS; + +typedef struct { + UINT cbSize; + UINT uFlags; + HWND hwnd; + UINT uId; + RECT rect; + HINSTANCE hinst; + LPTSTR lpszText; +} TOOLINFO, *PTOOLINFO, *LPTOOLINFO; + +typedef struct { + NMHDR hdr; + LPTSTR lpszText; + char szText[80]; + HINSTANCE hinst; + UINT uFlags; +} TOOLTIPTEXT, *LPTOOLTIPTEXT; + +typedef struct tagTPMPARAMS { + UINT cbSize; + RECT rcExclude; +} TPMPARAMS, *LPTPMPARAMS; + +#if 0 // RobD - typedef removed due to conflict with mingw headers +typedef struct _TRANSMIT_FILE_BUFFERS { + PVOID Head; + DWORD HeadLength; + PVOID Tail; + DWORD TailLength; +} TRANSMIT_FILE_BUFFERS; +#endif + +typedef struct _TT_HITTESTINFO { + HWND hwnd; + POINT pt; + TOOLINFO ti; +} TTHITTESTINFO, * LPHITTESTINFO; + +typedef struct tagTTPOLYCURVE { + WORD wType; + WORD cpfx; + POINTFX apfx[1]; +} TTPOLYCURVE, * LPTTPOLYCURVE; + +typedef struct _TTPOLYGONHEADER { + DWORD cb; + DWORD dwType; + POINTFX pfxStart; +} TTPOLYGONHEADER, * LPTTPOLYGONHEADER; + +typedef struct _TV_DISPINFO { + NMHDR hdr; + TV_ITEM item; +} TV_DISPINFO; + +typedef struct _TVHITTESTINFO { + POINT pt; + UINT flags; + HTREEITEM hItem; +} TV_HITTESTINFO, *LPTV_HITTESTINFO; + +typedef struct _TV_INSERTSTRUCT { + HTREEITEM hParent; + HTREEITEM hInsertAfter; + TV_ITEM item; +} TV_INSERTSTRUCT, *LPTV_INSERTSTRUCT; + +typedef struct _TV_KEYDOWN { + NMHDR hdr; + WORD wVKey; + UINT flags; +} TV_KEYDOWN; + +typedef struct _TV_SORTCB { + HTREEITEM hParent; + PFNTVCOMPARE lpfnCompare; + LPARAM lParam; +} TV_SORTCB, *LPTV_SORTCB; + +typedef struct { + UINT nSec; + UINT nInc; +} UDACCEL; + +typedef struct _UNIVERSAL_NAME_INFO { + LPTSTR lpUniversalName; +} UNIVERSAL_NAME_INFO; + +typedef struct tagUSEROBJECTFLAGS { + WINBOOL fInherit; + WINBOOL fReserved; + DWORD dwFlags; +} USEROBJECTFLAGS; + +typedef struct _VERIFY_INFORMATION { + LARGE_INTEGER StartingOffset; + DWORD Length; +} VERIFY_INFORMATION ; + +typedef struct _VS_FIXEDFILEINFO { + DWORD dwSignature; + DWORD dwStrucVersion; + DWORD dwFileVersionMS; + DWORD dwFileVersionLS; + DWORD dwProductVersionMS; + DWORD dwProductVersionLS; + DWORD dwFileFlagsMask; + DWORD dwFileFlags; + DWORD dwFileOS; + DWORD dwFileType; + DWORD dwFileSubtype; + DWORD dwFileDateMS; + DWORD dwFileDateLS; +} VS_FIXEDFILEINFO; + +typedef struct _WIN32_FIND_DATAA { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + CHAR cFileName[ MAX_PATH ]; + CHAR cAlternateFileName[ 14 ]; +} WIN32_FIND_DATAA, *LPWIN32_FIND_DATAA, *PWIN32_FIND_DATAA; + +typedef struct _WIN32_FIND_DATAW { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + WCHAR cFileName[ MAX_PATH ]; + WCHAR cAlternateFileName[ 14 ]; +} WIN32_FIND_DATAW, *LPWIN32_FIND_DATAW, *PWIN32_FIND_DATAW; + +#ifdef UNICODE +#define WIN32_FIND_DATA WIN32_FIND_DATAW +#define PWIN32_FIND_DATA PWIN32_FIND_DATAW +#define LPWIN32_FIND_DATA LPWIN32_FIND_DATAW +#else +#define WIN32_FIND_DATA WIN32_FIND_DATAA +#define PWIN32_FIND_DATA PWIN32_FIND_DATAA +#define LPWIN32_FIND_DATA LPWIN32_FIND_DATAA +#endif + +typedef struct _WIN32_STREAM_ID { + DWORD dwStreamId; + DWORD dwStreamAttributes; + LARGE_INTEGER Size; + DWORD dwStreamNameSize; + WCHAR *cStreamName; +} WIN32_STREAM_ID; + +typedef struct _WINDOWPLACEMENT { + UINT length; + UINT flags; + UINT showCmd; + POINT ptMinPosition; + POINT ptMaxPosition; + RECT rcNormalPosition; +} WINDOWPLACEMENT; + +typedef struct _WNDCLASS { + UINT style; + WNDPROC lpfnWndProc; + int cbClsExtra; + int cbWndExtra; + HANDLE hInstance; + HICON hIcon; + HCURSOR hCursor; + HBRUSH hbrBackground; + LPCTSTR lpszMenuName; + LPCTSTR lpszClassName; +} WNDCLASS, *LPWNDCLASS; + +typedef struct _WNDCLASSEX { + UINT cbSize; + UINT style; + WNDPROC lpfnWndProc; + int cbClsExtra; + int cbWndExtra; + HANDLE hInstance; + HICON hIcon; + HCURSOR hCursor; + HBRUSH hbrBackground; + LPCTSTR lpszMenuName; + LPCTSTR lpszClassName; + HICON hIconSm; +} WNDCLASSEX, *LPWNDCLASSEX; + +typedef struct _CONNECTDLGSTRUCT { + DWORD cbStructure; + HWND hwndOwner; + LPNETRESOURCE lpConnRes; + DWORD dwFlags; + DWORD dwDevNum; +} CONNECTDLGSTRUCT, *LPCONNECTDLGSTRUCT; + +typedef struct _DISCDLGSTRUCT { + DWORD cbStructure; + HWND hwndOwner; + LPTSTR lpLocalName; + LPTSTR lpRemoteName; + DWORD dwFlags; +} DISCDLGSTRUCT, *LPDISCDLGSTRUCT; + +typedef struct _NETINFOSTRUCT{ + DWORD cbStructure; + DWORD dwProviderVersion; + DWORD dwStatus; + DWORD dwCharacteristics; + DWORD dwHandle; + WORD wNetType; + DWORD dwPrinters; + DWORD dwDrives; +} NETINFOSTRUCT, *LPNETINFOSTRUCT; + +typedef struct _NETCONNECTINFOSTRUCT{ + DWORD cbStructure; + DWORD dwFlags; + DWORD dwSpeed; + DWORD dwDelay; + DWORD dwOptDataSize; +} NETCONNECTINFOSTRUCT, *LPNETCONNECTINFOSTRUCT; + +typedef int CALLBACK (*ENUMMETAFILEPROC) (HDC, HANDLETABLE, + METARECORD, int, LPARAM); +typedef int CALLBACK (*ENHMETAFILEPROC) (HDC, HANDLETABLE, + ENHMETARECORD, int, LPARAM); + +typedef int CALLBACK (*ENUMFONTSPROC) (LPLOGFONT, LPTEXTMETRIC, DWORD, LPARAM); +typedef int CALLBACK (*FONTENUMPROC) (ENUMLOGFONT *, NEWTEXTMETRIC *, + int, LPARAM); +typedef int CALLBACK (*FONTENUMEXPROC) (ENUMLOGFONTEX *, NEWTEXTMETRICEX *, + int, LPARAM); + +typedef VOID CALLBACK (*LPOVERLAPPED_COMPLETION_ROUTINE) (DWORD, DWORD, + LPOVERLAPPED); + +/* + Structures for the extensions to OpenGL + */ +typedef struct _POINTFLOAT +{ + FLOAT x; + FLOAT y; +} POINTFLOAT, *PPOINTFLOAT; + +typedef struct _GLYPHMETRICSFLOAT +{ + FLOAT gmfBlackBoxX; + FLOAT gmfBlackBoxY; + POINTFLOAT gmfptGlyphOrigin; + FLOAT gmfCellIncX; + FLOAT gmfCellIncY; +} GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT; + +typedef struct tagLAYERPLANEDESCRIPTOR +{ + WORD nSize; + WORD nVersion; + DWORD dwFlags; + BYTE iPixelType; + BYTE cColorBits; + BYTE cRedBits; + BYTE cRedShift; + BYTE cGreenBits; + BYTE cGreenShift; + BYTE cBlueBits; + BYTE cBlueShift; + BYTE cAlphaBits; + BYTE cAlphaShift; + BYTE cAccumBits; + BYTE cAccumRedBits; + BYTE cAccumGreenBits; + BYTE cAccumBlueBits; + BYTE cAccumAlphaBits; + BYTE cDepthBits; + BYTE cStencilBits; + BYTE cAuxBuffers; + BYTE iLayerPlane; + BYTE bReserved; + COLORREF crTransparent; +} LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR; + +typedef struct tagPIXELFORMATDESCRIPTOR +{ + WORD nSize; + WORD nVersion; + DWORD dwFlags; + BYTE iPixelType; + BYTE cColorBits; + BYTE cRedBits; + BYTE cRedShift; + BYTE cGreenBits; + BYTE cGreenShift; + BYTE cBlueBits; + BYTE cBlueShift; + BYTE cAlphaBits; + BYTE cAlphaShift; + BYTE cAccumBits; + BYTE cAccumRedBits; + BYTE cAccumGreenBits; + BYTE cAccumBlueBits; + BYTE cAccumAlphaBits; + BYTE cDepthBits; + BYTE cStencilBits; + BYTE cAuxBuffers; + BYTE iLayerType; + BYTE bReserved; + DWORD dwLayerMask; + DWORD dwVisibleMask; + DWORD dwDamageMask; +} PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR; + +typedef struct +{ + LPWSTR usri2_name; + LPWSTR usri2_password; + DWORD usri2_password_age; + DWORD usri2_priv; + LPWSTR usri2_home_dir; + LPWSTR usri2_comment; + DWORD usri2_flags; + LPWSTR usri2_script_path; + DWORD usri2_auth_flags; + LPWSTR usri2_full_name; + LPWSTR usri2_usr_comment; + LPWSTR usri2_parms; + LPWSTR usri2_workstations; + DWORD usri2_last_logon; + DWORD usri2_last_logoff; + DWORD usri2_acct_expires; + DWORD usri2_max_storage; + DWORD usri2_units_per_week; + PBYTE usri2_logon_hours; + DWORD usri2_bad_pw_count; + DWORD usri2_num_logons; + LPWSTR usri2_logon_server; + DWORD usri2_country_code; + DWORD usri2_code_page; +} USER_INFO_2, *PUSER_INFO_2, *LPUSER_INFO_2; + +typedef struct +{ + LPWSTR usri0_name; +} USER_INFO_0, *PUSER_INFO_0, *LPUSER_INFO_0; + +typedef struct +{ + LPWSTR usri3_name; + LPWSTR usri3_password; + DWORD usri3_password_age; + DWORD usri3_priv; + LPWSTR usri3_home_dir; + LPWSTR usri3_comment; + DWORD usri3_flags; + LPWSTR usri3_script_path; + DWORD usri3_auth_flags; + LPWSTR usri3_full_name; + LPWSTR usri3_usr_comment; + LPWSTR usri3_parms; + LPWSTR usri3_workstations; + DWORD usri3_last_logon; + DWORD usri3_last_logoff; + DWORD usri3_acct_expires; + DWORD usri3_max_storage; + DWORD usri3_units_per_week; + PBYTE usri3_logon_hours; + DWORD usri3_bad_pw_count; + DWORD usri3_num_logons; + LPWSTR usri3_logon_server; + DWORD usri3_country_code; + DWORD usri3_code_page; + DWORD usri3_user_id; + DWORD usri3_primary_group_id; + LPWSTR usri3_profile; + LPWSTR usri3_home_dir_drive; + DWORD usri3_password_expired; +} USER_INFO_3, *PUSER_INFO_3, *LPUSER_INFO_3; + +typedef struct +{ + LPWSTR grpi2_name; + LPWSTR grpi2_comment; + DWORD grpi2_group_id; + DWORD grpi2_attributes; +} GROUP_INFO_2, *PGROUP_INFO_2; + +typedef struct +{ + LPWSTR lgrpi0_name; +} LOCALGROUP_INFO_0, *PLOCALGROUP_INFO_0, *LPLOCALGROUP_INFO_0; + +/* PE executable header. */ +/* Windows.h now includes pe.h to avoid conflicts! */ + +typedef struct _DISPLAY_DEVICE { + DWORD cb; + WCHAR DeviceName[32]; + WCHAR DeviceString[128]; + DWORD StateFlags; + WCHAR DeviceID[128]; + WCHAR DeviceKey[128]; +} DISPLAY_DEVICE, *PDISPLAY_DEVICE; + +typedef HANDLE HMONITOR; +typedef HANDLE HDEVNOTIFY; + +typedef BOOL CALLBACK (*MonitorEnumProc)( + HMONITOR hMonitor, + HDC hdcMonitor, + LPRECT lprcMonitor, + LPARAM dwData); + +typedef MonitorEnumProc MONITORENUMPROC; + +typedef struct { + UINT cbSize; + HWND hwnd; + DWORD dwFlags; + UINT uCount; + DWORD dwTimeout; +} FLASHWINFO, *PFLASHWINFO; + +typedef struct tagALTTABINFO { + DWORD cbSize; + int cItems; + int cColumns; + int cRows; + int iColFocus; + int iRowFocus; + int cxItem; + int cyItem; + POINT ptStart; +} ALTTABINFO, *PALTTABINFO, *LPALTTABINFO; + +typedef struct tagCOMBOBOXINFO { + DWORD cbSize; + RECT rcItem; + RECT rcButton; + DWORD stateButton; + HWND hwndCombo; + HWND hwndItem; + HWND hwndList; +} COMBOBOXINFO, *PCOMBOBOXINFO, *LPCOMBOBOXINFO; + +typedef struct tagCURSORINFO { + DWORD cbSize; + DWORD flags; + HCURSOR hCursor; + POINT ptScreenPos; +} CURSORINFO, *PCURSORINFO, *LPCURSORINFO; + +typedef struct tagGUITHREADINFO { + DWORD cbSize; + DWORD flags; + HWND hwndActive; + HWND hwndFocus; + HWND hwndCapture; + HWND hwndMenuOwner; + HWND hwndMoveSize; + HWND hwndCaret; + RECT rcCaret; +} GUITHREADINFO, *PGUITHREADINFO, *LPGUITHREADINFO; + +typedef struct tagLASTINPUTINFO { + UINT cbSize; + DWORD dwTime; +} LASTINPUTINFO, *PLASTINPUTINFO; + +typedef struct tagMENUBARINFO { + DWORD cbSize; + RECT rcBar; + HMENU hMenu; + HWND hwndMenu; + BOOL fBarFocused:1; + BOOL fFocused:1; +} MENUBARINFO, *PMENUBARINFO; + +typedef struct tagMENUINFO { + DWORD cbSize; + DWORD fMask; + DWORD dwStyle; + UINT cyMax; + HBRUSH hbrBack; + DWORD dwContextHelpID; + ULONG_PTR dwMenuData; +} MENUINFO, FAR *LPMENUINFO; +typedef MENUINFO CONST FAR *LPCMENUINFO; + +typedef struct tagMONITORINFO { + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; +} MONITORINFO, *LPMONITORINFO; + +typedef struct tagMOUSEMOVEPOINT { + int x; + int y; + DWORD time; + ULONG_PTR dwExtraInfo; +} MOUSEMOVEPOINT, *PMOUSEMOVEPOINT, *LPMOUSEMOVEPOINT; + +#define CCHILDREN_SCROLLBAR 5 + +typedef struct tagSCROLLBARINFO { + DWORD cbSize; + RECT rcScrollBar; + int dxyLineButton; + int xyThumbTop; + int xyThumbBottom; + int reserved; + DWORD rgstate[CCHILDREN_SCROLLBAR+1]; +} SCROLLBARINFO, *PSCROLLBARINFO, *LPSCROLLBARINFO; + +#define CCHILDREN_TITLEBAR 5 + +typedef struct tagTITLEBARINFO { + DWORD cbSize; + RECT rcTitleBar; + DWORD rgstate[CCHILDREN_TITLEBAR+1]; +} TITLEBARINFO, *PTITLEBARINFO, *LPTITLEBARINFO; + +typedef struct { + HWND hwnd; + LPCTSTR szWindowName; + UINT32 fToBeClosed; + UINT32 fToBeTerminated; +} WINDOWINFO, *PWINDOWINFO, *LPWINDOWINFO; + +typedef struct tagMOUSEINPUT { + LONG dx; + LONG dy; + DWORD mouseData; + DWORD dwFlags; + DWORD time; + ULONG_PTR dwExtraInfo; +} MOUSEINPUT, *PMOUSEINPUT; + +typedef struct tagKEYBDINPUT { + WORD wVk; + WORD wScan; + DWORD dwFlags; + DWORD time; + ULONG_PTR dwExtraInfo; +} KEYBDINPUT, *PKEYBDINPUT; + +typedef struct tagHARDWAREINPUT { + DWORD uMsg; + WORD wParamL; + WORD wParamH; +} HARDWAREINPUT, *PHARDWAREINPUT; + +typedef struct tagINPUT { + DWORD type; + union + { + MOUSEINPUT mi; + KEYBDINPUT ki; + HARDWAREINPUT hi; + } u; +} INPUT, *PINPUT, FAR* LPINPUT; + +typedef struct tagTRACKMOUSEEVENT { + DWORD cbSize; + DWORD dwFlags; + HWND hwndTrack; + DWORD dwHoverTime; +} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT; + +typedef struct _BLENDFUNCTION { + BYTE BlendOp; + BYTE BlendFlags; + BYTE SourceConstantAlpha; + BYTE AlphaFormat; +}BLENDFUNCTION, *PBLENDFUNCTION, *LPBLENDFUNCTION; + +typedef enum _GET_FILEEX_INFO_LEVELS { + GetFileExInfoStandard +} GET_FILEEX_INFO_LEVELS; + +typedef struct _WIN32_FILE_ATTRIBUTES_DATA { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; +} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* WIN32_LEAN_AND_MEAN */ + +#endif /* _GNU_H_WINDOWS32_STRUCTURES */ + + diff --git a/include/tchar.h b/include/tchar.h new file mode 100644 index 0000000..9dc3ab4 --- /dev/null +++ b/include/tchar.h @@ -0,0 +1,231 @@ +/* + * tchar.h + * + * Unicode mapping layer for the standard C library. By including this + * file and using the 't' names for string functions + * (eg. _tprintf) you can make code which can be easily adapted to both + * Unicode and non-unicode environments. In a unicode enabled compile define + * _UNICODE before including tchar.h, otherwise the standard non-unicode + * library functions will be used. + * + * Note that you still need to include string.h or stdlib.h etc. to define + * the appropriate functions. Also note that there are several defines + * included for non-ANSI functions which are commonly available (but using + * the convention of prepending an underscore to non-ANSI library function + * names). + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#ifndef _TCHAR_H_ +#define _TCHAR_H_ + +/* + * NOTE: This tests _UNICODE, which is different from the UNICODE define + * used to differentiate Win32 API calls. + */ +#ifdef _UNICODE + + +/* + * Use TCHAR instead of char or wchar_t. It will be appropriately translated + * if _UNICODE is correctly defined (or not). + */ +#ifndef _TCHAR_DEFINED +#ifndef RC_INVOKED +typedef wchar_t TCHAR; +#endif /* Not RC_INVOKED */ +#define _TCHAR_DEFINED +#endif + + +/* + * Enclose constant strings and literal characters in the _TEXT and _T macro to make + * them unicode constant strings when _UNICODE is defined. + */ +#define _TEXT(x) L ## x +#define _T(x) L ## x + +/* + * Unicode functions + */ + +#define _tprintf wprintf +#define _ftprintf fwprintf +#define _stprintf swprintf +#define _sntprintf _snwprintf +#define _vtprintf vwprintf +#define _vftprintf vfwprintf +#define _vstprintf vswprintf +#define _vsntprintf _vsnwprintf +#define _tscanf wscanf +#define _ftscanf fwscanf +#define _stscanf swscanf +#define _fgettc fgetwc +#define _fgettchar _fgetwchar +#define _fgetts fgetws +#define _fputtc fputwc +#define _fputtchar _fputwchar +#define _fputts fputws +#define _gettc getwc +#define _getts getws +#define _puttc putwc +#define _putts putws +#define _ungettc ungetwc +#define _tcstod wcstod +#define _tcstol wcstol +#define _tcstoul wcstoul +#define _tcscat wcscat +#define _tcschr wcschr +#define _tcscmp wcscmp +#define _tcscpy wcscpy +#define _tcscspn wcscspn +#define _tcslen wcslen +#define _tcsncat wcsncat +#define _tcsncmp wcsncmp +#define _tcsncpy wcsncpy +#define _tcspbrk wcspbrk +#define _tcsrchr wcsrchr +#define _tcsspn wcsspn +#define _tcsstr wcsstr +#define _tcstok wcstok +#define _tcsdup _wcsdup +#define _tcsicmp _wcsicmp +#define _tcsnicmp _wcsnicmp +#define _tcsnset _wcsnset +#define _tcsrev _wcsrev +#define _tcsset _wcsset +#define _tcslwr _wcslwr +#define _tcsupr _wcsupr +#define _tcsxfrm wcsxfrm +#define _tcscoll wcscoll +#define _tcsicoll _wcsicoll +#define _istalpha iswalpha +#define _istupper iswupper +#define _istlower iswlower +#define _istdigit iswdigit +#define _istxdigit iswxdigit +#define _istspace iswspace +#define _istpunct iswpunct +#define _istalnum iswalnum +#define _istprint iswprint +#define _istgraph iswgraph +#define _istcntrl iswcntrl +#define _istascii iswascii +#define _totupper towupper +#define _totlower towlower +#define _ttoi _wtoi +#define _tcsftime wcsftime + +#else /* Not _UNICODE */ + +/* + * TCHAR, the type you should use instead of char. + */ +#ifndef _TCHAR_DEFINED +#ifndef RC_INVOKED +typedef char TCHAR; +#endif +#define _TCHAR_DEFINED +#endif + +/* + * Enclose constant strings and characters in the _TEXT and _T macro. + */ +#define _TEXT(x) x +#define _T(x) x + + +/* + * Non-unicode (standard) functions + */ + +#define _tprintf printf +#define _ftprintf fprintf +#define _stprintf sprintf +#define _sntprintf _snprintf +#define _vtprintf vprintf +#define _vftprintf vfprintf +#define _vstprintf vsprintf +#define _vsntprintf _vsnprintf +#define _tscanf scanf +#define _ftscanf fscanf +#define _stscanf sscanf +#define _fgettc fgetc +#define _fgettchar _fgetchar +#define _fgetts fgets +#define _fputtc fputc +#define _fputtchar _fputchar +#define _fputts fputs +#define _gettc getc +#define _getts gets +#define _puttc putc +#define _putts puts +#define _ungettc ungetc +#define _tcstod strtod +#define _tcstol strtol +#define _tcstoul strtoul +#define _tcscat strcat +#define _tcschr strchr +#define _tcscmp strcmp +#define _tcscpy strcpy +#define _tcscspn strcspn +#define _tcslen strlen +#define _tcsncat strncat +#define _tcsncmp strncmp +#define _tcsncpy strncpy +#define _tcspbrk strpbrk +#define _tcsrchr strrchr +#define _tcsspn strspn +#define _tcsstr strstr +#define _tcstok strtok +#define _tcsdup _strdup +#define _tcsicmp _stricmp +#define _tcsnicmp _strnicmp +#define _tcsnset _strnset +#define _tcsrev _strrev +#define _tcsset _strset +#define _tcslwr _strlwr +#define _tcsupr _strupr +#define _tcsxfrm strxfrm +#define _tcscoll strcoll +#define _tcsicoll _stricoll +#define _istalpha isalpha +#define _istupper isupper +#define _istlower islower +#define _istdigit isdigit +#define _istxdigit isxdigit +#define _istspace isspace +#define _istpunct ispunct +#define _istalnum isalnum +#define _istprint isprint +#define _istgraph isgraph +#define _istcntrl iscntrl +#define _istascii isascii +#define _totupper toupper +#define _totlower tolower +#define _ttoi atoi +#define _tcsftime strftime + +#endif /* Not _UNICODE */ + +#endif /* Not _TCHAR_H_ */ + diff --git a/include/unicode.h b/include/unicode.h new file mode 100644 index 0000000..c3b1fb8 --- /dev/null +++ b/include/unicode.h @@ -0,0 +1,3030 @@ +/* + UnicodeFunctions.h + + Declarations for all the Windows32 API Unicode Functions + + Copyright (C) 1996 Free Software Foundation, Inc. + + Author: Scott Christley + Date: 1996 + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNU_H_WINDOWS32_UNICODEFUNCTIONS +#define _GNU_H_WINDOWS32_UNICODEFUNCTIONS + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +WINBOOL +STDCALL +GetBinaryTypeW( + LPCWSTR lpApplicationName, + LPDWORD lpBinaryType + ); + +DWORD +STDCALL +GetShortPathNameW( + LPCWSTR lpszLongPath, + LPWSTR lpszShortPath, + DWORD cchBuffer + ); + +LPWSTR +STDCALL +GetEnvironmentStringsW( + VOID + ); + +WINBOOL +STDCALL +FreeEnvironmentStringsW( + LPWSTR + ); + +DWORD +STDCALL +FormatMessageW( + DWORD dwFlags, + LPCVOID lpSource, + DWORD dwMessageId, + DWORD dwLanguageId, + LPWSTR lpBuffer, + DWORD nSize, + va_list *Arguments + ); + +HANDLE +STDCALL +CreateMailslotW( + LPCWSTR lpName, + DWORD nMaxMessageSize, + DWORD lReadTimeout, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +int +STDCALL +lstrcmpW( + LPCWSTR lpString1, + LPCWSTR lpString2 + ); + +int +STDCALL +lstrcmpiW( + LPCWSTR lpString1, + LPCWSTR lpString2 + ); + +LPWSTR +STDCALL +lstrcpynW( + LPWSTR lpString1, + LPCWSTR lpString2, + int iMaxLength + ); + +LPWSTR +STDCALL +lstrcpyW( + LPWSTR lpString1, + LPCWSTR lpString2 + ); + +LPWSTR +STDCALL +lstrcatW( + LPWSTR lpString1, + LPCWSTR lpString2 + ); + +int +STDCALL +lstrlenW( + LPCWSTR lpString + ); + +HANDLE +STDCALL +CreateMutexW( + LPSECURITY_ATTRIBUTES lpMutexAttributes, + WINBOOL bInitialOwner, + LPCWSTR lpName + ); + +HANDLE +STDCALL +OpenMutexW( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName + ); + +HANDLE +STDCALL +CreateEventW( + LPSECURITY_ATTRIBUTES lpEventAttributes, + WINBOOL bManualReset, + WINBOOL bInitialState, + LPCWSTR lpName + ); + +HANDLE +STDCALL +OpenEventW( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName + ); + +HANDLE +STDCALL +CreateSemaphoreW( + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCWSTR lpName + ); + +HANDLE +STDCALL +OpenSemaphoreW( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName + ); + +HANDLE +STDCALL +CreateFileMappingW( + HANDLE hFile, + LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + DWORD flProtect, + DWORD dwMaximumSizeHigh, + DWORD dwMaximumSizeLow, + LPCWSTR lpName + ); + +HANDLE +STDCALL +OpenFileMappingW( + DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName + ); + +DWORD +STDCALL +GetLogicalDriveStringsW( + DWORD nBufferLength, + LPWSTR lpBuffer + ); + +HINSTANCE +STDCALL +LoadLibraryW( + LPCWSTR lpLibFileName + ); + +HINSTANCE +STDCALL +LoadLibraryExW( + LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags + ); + +DWORD +STDCALL +GetModuleFileNameW( + HINSTANCE hModule, + LPWSTR lpFilename, + DWORD nSize + ); + +HMODULE +STDCALL +GetModuleHandleW( + LPCWSTR lpModuleName + ); + +VOID +STDCALL +FatalAppExitW( + UINT uAction, + LPCWSTR lpMessageText + ); + +LPWSTR +STDCALL +GetCommandLineW( + VOID + ); + +DWORD +STDCALL +GetEnvironmentVariableW( + LPCWSTR lpName, + LPWSTR lpBuffer, + DWORD nSize + ); + +WINBOOL +STDCALL +SetEnvironmentVariableW( + LPCWSTR lpName, + LPCWSTR lpValue + ); + +DWORD +STDCALL +ExpandEnvironmentStringsW( + LPCWSTR lpSrc, + LPWSTR lpDst, + DWORD nSize + ); + +VOID +STDCALL +OutputDebugStringW( + LPCWSTR lpOutputString + ); + +HRSRC +STDCALL +FindResourceW( + HINSTANCE hModule, + LPCWSTR lpName, + LPCWSTR lpType + ); + +HRSRC +STDCALL +FindResourceExW( + HINSTANCE hModule, + LPCWSTR lpType, + LPCWSTR lpName, + WORD wLanguage + ); + +WINBOOL +STDCALL +EnumResourceTypesW( + HINSTANCE hModule, + ENUMRESTYPEPROC lpEnumFunc, + LONG lParam + ); + +WINBOOL +STDCALL +EnumResourceNamesW( + HINSTANCE hModule, + LPCWSTR lpType, + ENUMRESNAMEPROC lpEnumFunc, + LONG lParam + ); + +WINBOOL +STDCALL +EnumResourceLanguagesW( + HINSTANCE hModule, + LPCWSTR lpType, + LPCWSTR lpName, + ENUMRESLANGPROC lpEnumFunc, + LONG lParam + ); + +HANDLE +STDCALL +BeginUpdateResourceW( + LPCWSTR pFileName, + WINBOOL bDeleteExistingResources + ); + +WINBOOL +STDCALL +UpdateResourceW( + HANDLE hUpdate, + LPCWSTR lpType, + LPCWSTR lpName, + WORD wLanguage, + LPVOID lpData, + DWORD cbData + ); + +WINBOOL +STDCALL +EndUpdateResourceW( + HANDLE hUpdate, + WINBOOL fDiscard + ); + +ATOM +STDCALL +GlobalAddAtomW( + LPCWSTR lpString + ); + +ATOM +STDCALL +GlobalFindAtomW( + LPCWSTR lpString + ); + +UINT +STDCALL +GlobalGetAtomNameW( + ATOM nAtom, + LPWSTR lpBuffer, + int nSize + ); + +ATOM +STDCALL +AddAtomW( + LPCWSTR lpString + ); + +ATOM +STDCALL +FindAtomW( + LPCWSTR lpString + ); + +UINT +STDCALL +GetAtomNameW( + ATOM nAtom, + LPWSTR lpBuffer, + int nSize + ); + +UINT +STDCALL +GetProfileIntW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + INT nDefault + ); + +DWORD +STDCALL +GetProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize + ); + +WINBOOL +STDCALL +WriteProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpString + ); + +DWORD +STDCALL +GetProfileSectionW( + LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize + ); + +WINBOOL +STDCALL +WriteProfileSectionW( + LPCWSTR lpAppName, + LPCWSTR lpString + ); + +UINT +STDCALL +GetPrivateProfileIntW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + INT nDefault, + LPCWSTR lpFileName + ); + +DWORD +STDCALL +GetPrivateProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName + ); + +WINBOOL +STDCALL +WritePrivateProfileStringW( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpString, + LPCWSTR lpFileName + ); + +DWORD +STDCALL +GetPrivateProfileSectionW( + LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName + ); + +WINBOOL +STDCALL +WritePrivateProfileSectionW( + LPCWSTR lpAppName, + LPCWSTR lpString, + LPCWSTR lpFileName + ); + +UINT +STDCALL +GetDriveTypeW( + LPCWSTR lpRootPathName + ); + +UINT +STDCALL +GetSystemDirectoryW( + LPWSTR lpBuffer, + UINT uSize + ); + +DWORD +STDCALL +GetTempPathW( + DWORD nBufferLength, + LPWSTR lpBuffer + ); + +UINT +STDCALL +GetTempFileNameW( + LPCWSTR lpPathName, + LPCWSTR lpPrefixString, + UINT uUnique, + LPWSTR lpTempFileName + ); + +UINT +STDCALL +GetWindowsDirectoryW( + LPWSTR lpBuffer, + UINT uSize + ); + +WINBOOL +STDCALL +SetCurrentDirectoryW( + LPCWSTR lpPathName + ); + +DWORD +STDCALL +GetCurrentDirectoryW( + DWORD nBufferLength, + LPWSTR lpBuffer + ); + +WINBOOL +STDCALL +GetDiskFreeSpaceW( + LPCWSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters + ); + +WINBOOL +STDCALL +GetDiskFreeSpaceExW( + LPCWSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes + ); + +WINBOOL +STDCALL +CreateDirectoryW( + LPCWSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +WINBOOL +STDCALL +CreateDirectoryExW( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +WINBOOL +STDCALL +RemoveDirectoryW( + LPCWSTR lpPathName + ); + +DWORD +STDCALL +GetFullPathNameW( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart + ); + +WINBOOL +STDCALL +DefineDosDeviceW( + DWORD dwFlags, + LPCWSTR lpDeviceName, + LPCWSTR lpTargetPath + ); + +DWORD +STDCALL +QueryDosDeviceW( + LPCWSTR lpDeviceName, + LPWSTR lpTargetPath, + DWORD ucchMax + ); + +HANDLE +STDCALL +CreateFileW( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile + ); + +WINBOOL +STDCALL +SetFileAttributesW( + LPCWSTR lpFileName, + DWORD dwFileAttributes + ); + +DWORD +STDCALL +GetFileAttributesW( + LPCWSTR lpFileName + ); + +DWORD +STDCALL +GetCompressedFileSizeW( + LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh + ); + +WINBOOL +STDCALL +DeleteFileW( + LPCWSTR lpFileName + ); + +DWORD +STDCALL +SearchPathW( + LPCWSTR lpPath, + LPCWSTR lpFileName, + LPCWSTR lpExtension, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart + ); + +WINBOOL +STDCALL +CopyFileW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + WINBOOL bFailIfExists + ); + +WINBOOL +STDCALL +MoveFileW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName + ); + +WINBOOL +STDCALL +MoveFileExW( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + DWORD dwFlags + ); + +HANDLE +STDCALL +CreateNamedPipeW( + LPCWSTR lpName, + DWORD dwOpenMode, + DWORD dwPipeMode, + DWORD nMaxInstances, + DWORD nOutBufferSize, + DWORD nInBufferSize, + DWORD nDefaultTimeOut, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +WINBOOL +STDCALL +GetNamedPipeHandleStateW( + HANDLE hNamedPipe, + LPDWORD lpState, + LPDWORD lpCurInstances, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout, + LPWSTR lpUserName, + DWORD nMaxUserNameSize + ); + +WINBOOL +STDCALL +CallNamedPipeW( + LPCWSTR lpNamedPipeName, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + DWORD nTimeOut + ); + +WINBOOL +STDCALL +WaitNamedPipeW( + LPCWSTR lpNamedPipeName, + DWORD nTimeOut + ); + +WINBOOL +STDCALL +SetVolumeLabelW( + LPCWSTR lpRootPathName, + LPCWSTR lpVolumeName + ); + +WINBOOL +STDCALL +GetVolumeInformationW( + LPCWSTR lpRootPathName, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize + ); + +WINBOOL +STDCALL +ClearEventLogW ( + HANDLE hEventLog, + LPCWSTR lpBackupFileName + ); + +WINBOOL +STDCALL +BackupEventLogW ( + HANDLE hEventLog, + LPCWSTR lpBackupFileName + ); + +HANDLE +STDCALL +OpenEventLogW ( + LPCWSTR lpUNCServerName, + LPCWSTR lpSourceName + ); + +HANDLE +STDCALL +RegisterEventSourceW ( + LPCWSTR lpUNCServerName, + LPCWSTR lpSourceName + ); + +HANDLE +STDCALL +OpenBackupEventLogW ( + LPCWSTR lpUNCServerName, + LPCWSTR lpFileName + ); + +WINBOOL +STDCALL +ReadEventLogW ( + HANDLE hEventLog, + DWORD dwReadFlags, + DWORD dwRecordOffset, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + DWORD *pnBytesRead, + DWORD *pnMinNumberOfBytesNeeded + ); + +WINBOOL +STDCALL +ReportEventW ( + HANDLE hEventLog, + WORD wType, + WORD wCategory, + DWORD dwEventID, + PSID lpUserSid, + WORD wNumStrings, + DWORD dwDataSize, + LPCWSTR *lpStrings, + LPVOID lpRawData + ); + +WINBOOL +STDCALL +AccessCheckAndAuditAlarmW ( + LPCWSTR SubsystemName, + LPVOID HandleId, + LPWSTR ObjectTypeName, + LPWSTR ObjectName, + PSECURITY_DESCRIPTOR SecurityDescriptor, + DWORD DesiredAccess, + PGENERIC_MAPPING GenericMapping, + WINBOOL ObjectCreation, + LPDWORD GrantedAccess, + LPBOOL AccessStatus, + LPBOOL pfGenerateOnClose + ); + +WINBOOL +STDCALL +ObjectOpenAuditAlarmW ( + LPCWSTR SubsystemName, + LPVOID HandleId, + LPWSTR ObjectTypeName, + LPWSTR ObjectName, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + HANDLE ClientToken, + DWORD DesiredAccess, + DWORD GrantedAccess, + PPRIVILEGE_SET Privileges, + WINBOOL ObjectCreation, + WINBOOL AccessGranted, + LPBOOL GenerateOnClose + ); + +WINBOOL +STDCALL +ObjectPrivilegeAuditAlarmW ( + LPCWSTR SubsystemName, + LPVOID HandleId, + HANDLE ClientToken, + DWORD DesiredAccess, + PPRIVILEGE_SET Privileges, + WINBOOL AccessGranted + ); + +WINBOOL +STDCALL +ObjectCloseAuditAlarmW ( + LPCWSTR SubsystemName, + LPVOID HandleId, + WINBOOL GenerateOnClose + ); + +WINBOOL +STDCALL +PrivilegedServiceAuditAlarmW ( + LPCWSTR SubsystemName, + LPCWSTR ServiceName, + HANDLE ClientToken, + PPRIVILEGE_SET Privileges, + WINBOOL AccessGranted + ); + +WINBOOL +STDCALL +SetFileSecurityW ( + LPCWSTR lpFileName, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor + ); + +WINBOOL +STDCALL +GetFileSecurityW ( + LPCWSTR lpFileName, + SECURITY_INFORMATION RequestedInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD nLength, + LPDWORD lpnLengthNeeded + ); + +HANDLE +STDCALL +FindFirstChangeNotificationW( + LPCWSTR lpPathName, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter + ); + +WINBOOL +STDCALL +IsBadStringPtrW( + LPCWSTR lpsz, + UINT ucchMax + ); + +WINBOOL +STDCALL +LookupAccountSidW( + LPCWSTR lpSystemName, + PSID Sid, + LPWSTR Name, + LPDWORD cbName, + LPWSTR ReferencedDomainName, + LPDWORD cbReferencedDomainName, + PSID_NAME_USE peUse + ); + +WINBOOL +STDCALL +LookupAccountNameW( + LPCWSTR lpSystemName, + LPCWSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPWSTR ReferencedDomainName, + LPDWORD cbReferencedDomainName, + PSID_NAME_USE peUse + ); + +WINBOOL +STDCALL +LookupPrivilegeValueW( + LPCWSTR lpSystemName, + LPCWSTR lpName, + PLUID lpLuid + ); + +WINBOOL +STDCALL +LookupPrivilegeNameW( + LPCWSTR lpSystemName, + PLUID lpLuid, + LPWSTR lpName, + LPDWORD cbName + ); + +WINBOOL +STDCALL +LookupPrivilegeDisplayNameW( + LPCWSTR lpSystemName, + LPCWSTR lpName, + LPWSTR lpDisplayName, + LPDWORD cbDisplayName, + LPDWORD lpLanguageId + ); + +WINBOOL +STDCALL +BuildCommDCBW( + LPCWSTR lpDef, + LPDCB lpDCB + ); + +WINBOOL +STDCALL +BuildCommDCBAndTimeoutsW( + LPCWSTR lpDef, + LPDCB lpDCB, + LPCOMMTIMEOUTS lpCommTimeouts + ); + +WINBOOL +STDCALL +CommConfigDialogW( + LPCWSTR lpszName, + HWND hWnd, + LPCOMMCONFIG lpCC + ); + +WINBOOL +STDCALL +GetDefaultCommConfigW( + LPCWSTR lpszName, + LPCOMMCONFIG lpCC, + LPDWORD lpdwSize + ); + +WINBOOL +STDCALL +SetDefaultCommConfigW( + LPCWSTR lpszName, + LPCOMMCONFIG lpCC, + DWORD dwSize + ); + +WINBOOL +STDCALL +GetComputerNameW ( + LPWSTR lpBuffer, + LPDWORD nSize + ); + +WINBOOL +STDCALL +SetComputerNameW ( + LPCWSTR lpComputerName + ); + +WINBOOL +STDCALL +GetUserNameW ( + LPWSTR lpBuffer, + LPDWORD nSize + ); + +int +STDCALL +wvsprintfW( + LPWSTR, + LPCWSTR, + va_list arglist); + +int +CDECL +wsprintfW(LPWSTR, LPCWSTR, ...); + +HKL +STDCALL +LoadKeyboardLayoutW( + LPCWSTR pwszKLID, + UINT Flags); + +WINBOOL +STDCALL +GetKeyboardLayoutNameW( + LPWSTR pwszKLID); + +HDESK +STDCALL +CreateDesktopW( + LPCWSTR lpszDesktop, + LPCWSTR lpszDevice, + LPDEVMODEW pDevmode, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa); + +HDESK +STDCALL +OpenDesktopW( + LPWSTR lpszDesktop, + DWORD dwFlags, + WINBOOL fInherit, + DWORD dwDesiredAccess); + +WINBOOL +STDCALL +EnumDesktopsW( + HWINSTA hwinsta, + DESKTOPENUMPROC lpEnumFunc, + LPARAM lParam); + +HWINSTA +STDCALL +CreateWindowStationW( + LPWSTR lpwinsta, + DWORD dwReserved, + DWORD dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa); + +HWINSTA +STDCALL +OpenWindowStationW( + LPWSTR lpszWinSta, + WINBOOL fInherit, + DWORD dwDesiredAccess); + +WINBOOL +STDCALL +EnumWindowStationsW( + ENUMWINDOWSTATIONPROC lpEnumFunc, + LPARAM lParam); + +WINBOOL +STDCALL +GetUserObjectInformationW( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength, + LPDWORD lpnLengthNeeded); + +WINBOOL +STDCALL +SetUserObjectInformationW( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength); + +UINT +STDCALL +RegisterWindowMessageW( + LPCWSTR lpString); + +WINBOOL +STDCALL +GetMessageW( + LPMSG lpMsg, + HWND hWnd , + UINT wMsgFilterMin, + UINT wMsgFilterMax); + +LRESULT +STDCALL +DispatchMessageW( + CONST MSG *lpMsg); + +WINBOOL +STDCALL +PeekMessageW( + LPMSG lpMsg, + HWND hWnd , + UINT wMsgFilterMin, + UINT wMsgFilterMax, + UINT wRemoveMsg); + +LRESULT +STDCALL +SendMessageW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +SendMessageTimeoutW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + UINT fuFlags, + UINT uTimeout, + PDWORD_PTR lpdwResult); + +WINBOOL +STDCALL +SendNotifyMessageW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +WINBOOL +STDCALL +SendMessageCallbackW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC lpResultCallBack, + ULONG_PTR dwData); + +WINBOOL +STDCALL +PostMessageW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +WINBOOL +STDCALL +PostThreadMessageW( + DWORD idThread, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +DefWindowProcW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +CallWindowProcW( + WNDPROC lpPrevWndFunc, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +ATOM +STDCALL +RegisterClassW( + CONST WNDCLASS *lpWndClass); + +WINBOOL +STDCALL +UnregisterClassW( + LPCWSTR lpClassName, + HINSTANCE hInstance); + +WINBOOL +STDCALL +GetClassInfoW( + HINSTANCE hInstance , + LPCWSTR lpClassName, + LPWNDCLASS lpWndClass); + +ATOM +STDCALL +RegisterClassExW(CONST WNDCLASSEX *); + +WINBOOL +STDCALL +GetClassInfoExW(HINSTANCE, LPCWSTR, LPWNDCLASSEX); + +HWND +STDCALL +CreateWindowExW( + DWORD dwExStyle, + LPCWSTR lpClassName, + LPCWSTR lpWindowName, + DWORD dwStyle, + int X, + int Y, + int nWidth, + int nHeight, + HWND hWndParent , + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam); + +HWND +STDCALL +CreateDialogParamW( + HINSTANCE hInstance, + LPCWSTR lpTemplateName, + HWND hWndParent , + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +HWND +STDCALL +CreateDialogIndirectParamW( + HINSTANCE hInstance, + LPCDLGTEMPLATE lpTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +int +STDCALL +DialogBoxParamW( + HINSTANCE hInstance, + LPCWSTR lpTemplateName, + HWND hWndParent , + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +int +STDCALL +DialogBoxIndirectParamW( + HINSTANCE hInstance, + LPCDLGTEMPLATE hDialogTemplate, + HWND hWndParent , + DLGPROC lpDialogFunc, + LPARAM dwInitParam); + +WINBOOL +STDCALL +SetDlgItemTextW( + HWND hDlg, + int nIDDlgItem, + LPCWSTR lpString); + +UINT +STDCALL +GetDlgItemTextW( + HWND hDlg, + int nIDDlgItem, + LPWSTR lpString, + int nMaxCount); + +LRESULT +STDCALL +SendDlgItemMessageW( + HWND hDlg, + int nIDDlgItem, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +DefDlgProcW( + HWND hDlg, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +WINBOOL +STDCALL +CallMsgFilterW( + LPMSG lpMsg, + int nCode); + +UINT +STDCALL +RegisterClipboardFormatW( + LPCWSTR lpszFormat); + +int +STDCALL +GetClipboardFormatNameW( + UINT format, + LPWSTR lpszFormatName, + int cchMaxCount); + +WINBOOL +STDCALL +CharToOemW( + LPCWSTR lpszSrc, + LPSTR lpszDst); + +WINBOOL +STDCALL +OemToCharW( + LPCSTR lpszSrc, + LPWSTR lpszDst); + +WINBOOL +STDCALL +CharToOemBuffW( + LPCWSTR lpszSrc, + LPSTR lpszDst, + DWORD cchDstLength); + +WINBOOL +STDCALL +OemToCharBuffW( + LPCSTR lpszSrc, + LPWSTR lpszDst, + DWORD cchDstLength); + +LPWSTR +STDCALL +CharUpperW( + LPWSTR lpsz); + +DWORD +STDCALL +CharUpperBuffW( + LPWSTR lpsz, + DWORD cchLength); + +LPWSTR +STDCALL +CharLowerW( + LPWSTR lpsz); + +DWORD +STDCALL +CharLowerBuffW( + LPWSTR lpsz, + DWORD cchLength); + +LPWSTR +STDCALL +CharNextW( + LPCWSTR lpsz); + +LPWSTR +STDCALL +CharPrevW( + LPCWSTR lpszStart, + LPCWSTR lpszCurrent); + +WINBOOL +STDCALL +IsCharAlphaW( + WCHAR ch); + +WINBOOL +STDCALL +IsCharAlphaNumericW( + WCHAR ch); + +WINBOOL +STDCALL +IsCharUpperW( + WCHAR ch); + +WINBOOL +STDCALL +IsCharLowerW( + WCHAR ch); + +int +STDCALL +GetKeyNameTextW( + LONG lParam, + LPWSTR lpString, + int nSize + ); + +SHORT +STDCALL +VkKeyScanW( + WCHAR ch); + +SHORT +STDCALL VkKeyScanExW( + WCHAR ch, + HKL dwhkl); + +UINT +STDCALL +MapVirtualKeyW( + UINT uCode, + UINT uMapType); + +UINT +STDCALL +MapVirtualKeyExW( + UINT uCode, + UINT uMapType, + HKL dwhkl); + +HACCEL +STDCALL +LoadAcceleratorsW( + HINSTANCE hInstance, + LPCWSTR lpTableName); + +HACCEL +STDCALL +CreateAcceleratorTableW( + LPACCEL, int); + +int +STDCALL +CopyAcceleratorTableW( + HACCEL hAccelSrc, + LPACCEL lpAccelDst, + int cAccelEntries); + +int +STDCALL +TranslateAcceleratorW( + HWND hWnd, + HACCEL hAccTable, + LPMSG lpMsg); + +HMENU +STDCALL +LoadMenuW( + HINSTANCE hInstance, + LPCWSTR lpMenuName); + +HMENU +STDCALL +LoadMenuIndirectW( + CONST MENUTEMPLATE *lpMenuTemplate); + +WINBOOL +STDCALL +ChangeMenuW( + HMENU hMenu, + UINT cmd, + LPCWSTR lpszNewItem, + UINT cmdInsert, + UINT flags); + +int +STDCALL +GetMenuStringW( + HMENU hMenu, + UINT uIDItem, + LPWSTR lpString, + int nMaxCount, + UINT uFlag); + +WINBOOL +STDCALL +InsertMenuW( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + UINT uIDNewItem, + LPCWSTR lpNewItem + ); + +WINBOOL +STDCALL +AppendMenuW( + HMENU hMenu, + UINT uFlags, + UINT uIDNewItem, + LPCWSTR lpNewItem + ); + +WINBOOL +STDCALL +ModifyMenuW( + HMENU hMnu, + UINT uPosition, + UINT uFlags, + UINT uIDNewItem, + LPCWSTR lpNewItem + ); + +WINBOOL +STDCALL +InsertMenuItemW( + HMENU, + UINT, + WINBOOL, + LPCMENUITEMINFO + ); + +WINBOOL +STDCALL +GetMenuItemInfoW( + HMENU, + UINT, + WINBOOL, + LPMENUITEMINFO + ); + +WINBOOL +STDCALL +SetMenuItemInfoW( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPMENUITEMINFO lpmii); + +int +STDCALL +DrawTextW( + HDC hDC, + LPCWSTR lpString, + int nCount, + LPRECT lpRect, + UINT uFormat); + +int +STDCALL +DrawTextExW(HDC, LPWSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); + +WINBOOL +STDCALL +GrayStringW( + HDC hDC, + HBRUSH hBrush, + GRAYSTRINGPROC lpOutputFunc, + LPARAM lpData, + int nCount, + int X, + int Y, + int nWidth, + int nHeight); + +WINBOOL STDCALL DrawStateW(HDC, HBRUSH, DRAWSTATEPROC, LPARAM, WPARAM, int, int, int, int, UINT); + +LONG +STDCALL +TabbedTextOutW( + HDC hDC, + int X, + int Y, + LPCWSTR lpString, + int nCount, + int nTabPositions, + LPINT lpnTabStopPositions, + int nTabOrigin); + +DWORD +STDCALL +GetTabbedTextExtentW( + HDC hDC, + LPCWSTR lpString, + int nCount, + int nTabPositions, + LPINT lpnTabStopPositions); + +WINBOOL +STDCALL +SetPropW( + HWND hWnd, + LPCWSTR lpString, + HANDLE hData); + +HANDLE +STDCALL +GetPropW( + HWND hWnd, + LPCWSTR lpString); + +HANDLE +STDCALL +RemovePropW( + HWND hWnd, + LPCWSTR lpString); + +int +STDCALL +EnumPropsExW( + HWND hWnd, + PROPENUMPROCEX lpEnumFunc, + LPARAM lParam); + +int +STDCALL +EnumPropsW( + HWND hWnd, + PROPENUMPROC lpEnumFunc); + +WINBOOL +STDCALL +SetWindowTextW( + HWND hWnd, + LPCWSTR lpString); + +int +STDCALL +GetWindowTextW( + HWND hWnd, + LPWSTR lpString, + int nMaxCount); + +int +STDCALL +GetWindowTextLengthW( + HWND hWnd); + +int +STDCALL +MessageBoxW( + HWND hWnd , + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType); + +int +STDCALL +MessageBoxExW( + HWND hWnd , + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType, + WORD wLanguageId); + +int +STDCALL +MessageBoxIndirectW(LPMSGBOXPARAMS); + +LONG +STDCALL +GetWindowLongW( + HWND hWnd, + int nIndex); + +LONG +STDCALL +SetWindowLongW( + HWND hWnd, + int nIndex, + LONG dwNewLong); + +DWORD +STDCALL +GetClassLongW( + HWND hWnd, + int nIndex); + +DWORD +STDCALL +SetClassLongW( + HWND hWnd, + int nIndex, + LONG dwNewLong); + +HWND +STDCALL +FindWindowW( + LPCWSTR lpClassName , + LPCWSTR lpWindowName); + +HWND +STDCALL +FindWindowExW(HWND, HWND, LPCWSTR, LPCWSTR); + +int +STDCALL +GetClassNameW( + HWND hWnd, + LPWSTR lpClassName, + int nMaxCount); + +HHOOK +STDCALL +SetWindowsHookExW( + int idHook, + HOOKPROC lpfn, + HINSTANCE hmod, + DWORD dwThreadId); + +HBITMAP +STDCALL +LoadBitmapW( + HINSTANCE hInstance, + LPCWSTR lpBitmapName); + +HCURSOR +STDCALL +LoadCursorW( + HINSTANCE hInstance, + LPCWSTR lpCursorName); + +HCURSOR +STDCALL +LoadCursorFromFileW( + LPCWSTR lpFileName); + +HICON +STDCALL +LoadIconW( + HINSTANCE hInstance, + LPCWSTR lpIconName); + +HANDLE +STDCALL +LoadImageW( + HINSTANCE, + LPCWSTR, + UINT, + int, + int, + UINT); + +int +STDCALL +LoadStringW( + HINSTANCE hInstance, + UINT uID, + LPWSTR lpBuffer, + int nBufferMax); + +WINBOOL +STDCALL +IsDialogMessageW( + HWND hDlg, + LPMSG lpMsg); + +int +STDCALL +DlgDirListW( + HWND hDlg, + LPWSTR lpPathSpec, + int nIDListBox, + int nIDStaticPath, + UINT uFileType); + +WINBOOL +STDCALL +DlgDirSelectExW( + HWND hDlg, + LPWSTR lpString, + int nCount, + int nIDListBox); + +int +STDCALL +DlgDirListComboBoxW( + HWND hDlg, + LPWSTR lpPathSpec, + int nIDComboBox, + int nIDStaticPath, + UINT uFiletype); + +WINBOOL +STDCALL +DlgDirSelectComboBoxExW( + HWND hDlg, + LPWSTR lpString, + int nCount, + int nIDComboBox); + +LRESULT +STDCALL +DefFrameProcW( + HWND hWnd, + HWND hWndMDIClient , + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +LRESULT +STDCALL +DefMDIChildProcW( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +HWND +STDCALL +CreateMDIWindowW( + LPCWSTR lpClassName, + LPCWSTR lpWindowName, + DWORD dwStyle, + int X, + int Y, + int nWidth, + int nHeight, + HWND hWndParent, + HINSTANCE hInstance, + LPARAM lParam + ); + +WINBOOL +STDCALL +WinHelpW( + HWND hWndMain, + LPCWSTR lpszHelp, + UINT uCommand, + DWORD dwData + ); + +LONG +STDCALL +ChangeDisplaySettingsW( + LPDEVMODEW lpDevMode, + DWORD dwFlags); + +WINBOOL +STDCALL +EnumDisplaySettingsW( + LPCWSTR lpszDeviceName, + DWORD iModeNum, + LPDEVMODEW lpDevMode); + +WINBOOL +STDCALL +SystemParametersInfoW( + UINT uiAction, + UINT uiParam, + PVOID pvParam, + UINT fWinIni); + +int +STDCALL +AddFontResourceW(LPCWSTR); + +HMETAFILE +STDCALL +CopyMetaFileW(HMETAFILE, LPCWSTR); + +HFONT +STDCALL +CreateFontIndirectW(CONST LOGFONT *); + +HFONT +STDCALL +CreateFontW(int, int, int, int, int, DWORD, + DWORD, DWORD, DWORD, DWORD, DWORD, + DWORD, DWORD, LPCWSTR); + +HDC +STDCALL +CreateICW(LPCWSTR, LPCWSTR , LPCWSTR , CONST DEVMODEW *); + +HDC +STDCALL +CreateMetaFileW(LPCWSTR); + +WINBOOL +STDCALL +CreateScalableFontResourceW(DWORD, LPCWSTR, LPCWSTR, LPCWSTR); + +int +STDCALL +DeviceCapabilitiesW(LPCWSTR, LPCWSTR, WORD, + LPWSTR, CONST DEVMODEW *); + +int +STDCALL +EnumFontFamiliesExW(HDC, LPLOGFONT, FONTENUMEXPROC, LPARAM, DWORD); + +int +STDCALL +EnumFontFamiliesW(HDC, LPCWSTR, FONTENUMPROC, LPARAM); + +int +STDCALL +EnumFontsW(HDC, LPCWSTR, ENUMFONTSPROC, LPARAM); + +WINBOOL +STDCALL +GetCharWidthW(HDC, UINT, UINT, LPINT); + +WINBOOL +STDCALL +GetCharWidth32W(HDC, UINT, UINT, LPINT); + +WINBOOL +STDCALL +GetCharWidthFloatW(HDC, UINT, UINT, PFLOAT); + +WINBOOL +STDCALL +GetCharABCWidthsW(HDC, UINT, UINT, LPABC); + +WINBOOL +STDCALL +GetCharABCWidthsFloatW(HDC, UINT, UINT, LPABCFLOAT); + +DWORD +STDCALL +GetGlyphOutlineW(HDC, UINT, UINT, LPGLYPHMETRICS, DWORD, LPVOID, CONST MAT2 *); + +HMETAFILE +STDCALL +GetMetaFileW(LPCWSTR); + +UINT +STDCALL +GetOutlineTextMetricsW(HDC, UINT, LPOUTLINETEXTMETRIC); + +WINBOOL +STDCALL GetTextExtentPointW( + HDC, + LPCWSTR, + int, + LPSIZE + ); + +WINBOOL +STDCALL +GetTextExtentPoint32W( + HDC, + LPCWSTR, + int, + LPSIZE + ); + +WINBOOL +STDCALL +GetTextExtentExPointW( + HDC, + LPCWSTR, + int, + int, + LPINT, + LPINT, + LPSIZE + ); + +DWORD +STDCALL +GetCharacterPlacementW(HDC, LPCWSTR, int, int, LPGCP_RESULTS, DWORD); + +HDC +STDCALL +ResetDCW(HDC, CONST DEVMODEW *); + +WINBOOL +STDCALL +RemoveFontResourceW(LPCWSTR); + +HENHMETAFILE +STDCALL +CopyEnhMetaFileW(HENHMETAFILE, LPCWSTR); + +HDC +STDCALL +CreateEnhMetaFileW(HDC, LPCWSTR, CONST RECT *, LPCWSTR); + +HENHMETAFILE +STDCALL +GetEnhMetaFileW(LPCWSTR); + +UINT +STDCALL +GetEnhMetaFileDescriptionW(HENHMETAFILE, UINT, LPWSTR ); + +WINBOOL +STDCALL +GetTextMetricsW(HDC, LPTEXTMETRIC); + +int +STDCALL +StartDocW(HDC, CONST DOCINFO *); + +int +STDCALL +GetObjectW(HGDIOBJ, int, LPVOID); + +WINBOOL +STDCALL +TextOutW(HDC, int, int, LPCWSTR, int); + +WINBOOL +STDCALL +ExtTextOutW(HDC, int, int, UINT, CONST RECT *,LPCWSTR, UINT, CONST INT *); + +WINBOOL +STDCALL +PolyTextOutW(HDC, CONST POLYTEXT *, int); + +int +STDCALL +GetTextFaceW(HDC, int, LPWSTR); + +DWORD +STDCALL +GetKerningPairsW(HDC, DWORD, LPKERNINGPAIR); + +WINBOOL +STDCALL +GetLogColorSpaceW(HCOLORSPACE,LPLOGCOLORSPACE,DWORD); + +HCOLORSPACE +STDCALL +CreateColorSpaceW(LPLOGCOLORSPACE); + +WINBOOL +STDCALL +GetICMProfileW(HDC,DWORD,LPWSTR); + +WINBOOL +STDCALL +SetICMProfileW(HDC,LPWSTR); + +WINBOOL +STDCALL +UpdateICMRegKeyW(DWORD, DWORD, LPWSTR, UINT); + +int +STDCALL +EnumICMProfilesW(HDC,ICMENUMPROC,LPARAM); + +HPROPSHEETPAGE +STDCALL +CreatePropertySheetPageW(LPCPROPSHEETPAGE lppsp); + +int +STDCALL +PropertySheetW(LPCPROPSHEETHEADER lppsph); + +HIMAGELIST +STDCALL +ImageList_LoadImageW(HINSTANCE hi, +LPCWSTR lpbmp, +int cx, +int cGrow, +COLORREF crMask, +UINT uType, +UINT uFlags); + +HWND +STDCALL +CreateStatusWindowW(LONG style, LPCWSTR lpszText, HWND hwndParent, UINT wID); + +void +STDCALL +DrawStatusTextW(HDC hDC, LPRECT lprc, LPCWSTR pszText, UINT uFlags); + +WINBOOL +STDCALL +GetOpenFileNameW(LPOPENFILENAME); + +WINBOOL +STDCALL +GetSaveFileNameW(LPOPENFILENAME); + +short +STDCALL +GetFileTitleW(LPCWSTR, LPWSTR, WORD); + +WINBOOL +STDCALL +ChooseColorW(LPCHOOSECOLOR); + +HWND +STDCALL +ReplaceTextW(LPFINDREPLACE); + +WINBOOL +STDCALL +ChooseFontW(LPCHOOSEFONT); + +HWND +STDCALL +FindTextW(LPFINDREPLACE); + +WINBOOL +STDCALL +PrintDlgW(LPPRINTDLG); + +WINBOOL +STDCALL +PageSetupDlgW(LPPAGESETUPDLG); + +WINBOOL +STDCALL +CreateProcessW( + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + WINBOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation + ); + +VOID +STDCALL +GetStartupInfoW( + LPSTARTUPINFOW lpStartupInfo + ); + +WINBASEAPI +HANDLE +WINAPI +FindFirstFileExW ( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ); + +HANDLE +STDCALL +FindFirstFileW( + LPCWSTR lpFileName, + LPWIN32_FIND_DATAW lpFindFileData + ); + +WINBOOL +STDCALL +FindNextFileW( + HANDLE hFindFile, + LPWIN32_FIND_DATAW lpFindFileData + ); + +WINBOOL +STDCALL +GetVersionExW( + LPOSVERSIONINFO lpVersionInformation + ); + +#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\ +nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\ +CreateWindowExW(0L, lpClassName, lpWindowName, dwStyle, x, y,\ +nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam) + +#define CreateDialogW(hInstance, lpName, hWndParent, lpDialogFunc) \ +CreateDialogParamW(hInstance, lpName, hWndParent, lpDialogFunc, 0L) + +#define CreateDialogIndirectW(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ +CreateDialogIndirectParamW(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L) + +#define DialogBoxW(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ +DialogBoxParamW(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L) + +#define DialogBoxIndirectW(hInstance, lpTemplate, hWndParent, lpDialogFunc) \ +DialogBoxIndirectParamW(hInstance, lpTemplate, hWndParent, lpDialogFunc, 0L) + +HDC +STDCALL +CreateDCW(LPCWSTR, LPCWSTR , LPCWSTR , CONST DEVMODEW *); + +HFONT +STDCALL +CreateFontA(int, int, int, int, int, DWORD, + DWORD, DWORD, DWORD, DWORD, DWORD, + DWORD, DWORD, LPCSTR); + +DWORD +STDCALL +VerInstallFileW( + DWORD uFlags, + LPWSTR szSrcFileName, + LPWSTR szDestFileName, + LPWSTR szSrcDir, + LPWSTR szDestDir, + LPWSTR szCurDir, + LPWSTR szTmpFile, + PUINT lpuTmpFileLen + ); + +DWORD +STDCALL +GetFileVersionInfoSizeW( + LPWSTR lptstrFilename, + LPDWORD lpdwHandle + ); + +WINBOOL +STDCALL +GetFileVersionInfoW( + LPWSTR lptstrFilename, + DWORD dwHandle, + DWORD dwLen, + LPVOID lpData + ); + +DWORD +STDCALL +VerLanguageNameW( + DWORD wLang, + LPWSTR szLang, + DWORD nSize + ); + +WINBOOL +STDCALL +VerQueryValueW( + const LPVOID pBlock, + LPWSTR lpSubBlock, + LPVOID * lplpBuffer, + PUINT puLen + ); + +DWORD +STDCALL +VerFindFileW( + DWORD uFlags, + LPWSTR szFileName, + LPWSTR szWinDir, + LPWSTR szAppDir, + LPWSTR szCurDir, + PUINT lpuCurDirLen, + LPWSTR szDestDir, + PUINT lpuDestDirLen + ); + +LONG +STDCALL +RegSetValueExW ( + HKEY hKey, + LPCWSTR lpValueName, + DWORD Reserved, + DWORD dwType, + CONST BYTE* lpData, + DWORD cbData + ); + +LONG +STDCALL +RegUnLoadKeyW ( + HKEY hKey, + LPCWSTR lpSubKey + ); + +WINBOOL +STDCALL +InitiateSystemShutdownW( + LPWSTR lpMachineName, + LPWSTR lpMessage, + DWORD dwTimeout, + WINBOOL bForceAppsClosed, + WINBOOL bRebootAfterShutdown + ); + +WINBOOL +STDCALL +AbortSystemShutdownW( + LPWSTR lpMachineName + ); + +LONG +STDCALL +RegRestoreKeyW ( + HKEY hKey, + LPCWSTR lpFile, + DWORD dwFlags + ); + +LONG +STDCALL +RegSaveKeyW ( + HKEY hKey, + LPCWSTR lpFile, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +LONG +STDCALL +RegSetValueW ( + HKEY hKey, + LPCWSTR lpSubKey, + DWORD dwType, + LPCWSTR lpData, + DWORD cbData + ); + +LONG +STDCALL +RegQueryValueW ( + HKEY hKey, + LPCWSTR lpSubKey, + LPWSTR lpValue, + PLONG lpcbValue + ); + +LONG +STDCALL +RegQueryMultipleValuesW ( + HKEY hKey, + PVALENT val_list, + DWORD num_vals, + LPWSTR lpValueBuf, + LPDWORD ldwTotsize + ); + +LONG +STDCALL +RegQueryValueExW ( + HKEY hKey, + LPWSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ); + +LONG +STDCALL +RegReplaceKeyW ( + HKEY hKey, + LPCWSTR lpSubKey, + LPCWSTR lpNewFile, + LPCWSTR lpOldFile + ); + +LONG +STDCALL +RegConnectRegistryW ( + LPWSTR lpMachineName, + HKEY hKey, + PHKEY phkResult + ); + +LONG +STDCALL +RegCreateKeyW ( + HKEY hKey, + LPCWSTR lpSubKey, + PHKEY phkResult + ); + +LONG +STDCALL +RegCreateKeyExW ( + HKEY hKey, + LPCWSTR lpSubKey, + DWORD Reserved, + LPWSTR lpClass, + DWORD dwOptions, + REGSAM samDesired, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + PHKEY phkResult, + LPDWORD lpdwDisposition + ); + +LONG +STDCALL +RegDeleteKeyW ( + HKEY hKey, + LPCWSTR lpSubKey + ); + +LONG +STDCALL +RegDeleteValueW ( + HKEY hKey, + LPCWSTR lpValueName + ); + +LONG +STDCALL +RegEnumKeyW ( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpName, + DWORD cbName + ); + +LONG +STDCALL +RegEnumKeyExW ( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpName, + LPDWORD lpcbName, + LPDWORD lpReserved, + LPWSTR lpClass, + LPDWORD lpcbClass, + PFILETIME lpftLastWriteTime + ); + +LONG +STDCALL +RegEnumValueW ( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpValueName, + LPDWORD lpcbValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ); + +LONG +STDCALL +RegLoadKeyW ( + HKEY hKey, + LPCWSTR lpSubKey, + LPCWSTR lpFile + ); + +LONG +STDCALL +RegOpenKeyW ( + HKEY hKey, + LPCWSTR lpSubKey, + PHKEY phkResult + ); + +LONG +STDCALL +RegOpenKeyExW ( + HKEY hKey, + LPCWSTR lpSubKey, + DWORD ulOptions, + REGSAM samDesired, + PHKEY phkResult + ); + +LONG +STDCALL +RegQueryInfoKeyW ( + HKEY hKey, + LPWSTR lpClass, + LPDWORD lpcbClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime + ); + +int +STDCALL +CompareStringW( + LCID Locale, + DWORD dwCmpFlags, + LPCWSTR lpString1, + int cchCount1, + LPCWSTR lpString2, + int cchCount2); + +int +STDCALL +LCMapStringW( + LCID Locale, + DWORD dwMapFlags, + LPCWSTR lpSrcStr, + int cchSrc, + LPWSTR lpDestStr, + int cchDest); + + +int +STDCALL +GetLocaleInfoW( + LCID Locale, + LCTYPE LCType, + LPWSTR lpLCData, + int cchData); + +WINBOOL +STDCALL +SetLocaleInfoW( + LCID Locale, + LCTYPE LCType, + LPCWSTR lpLCData); + +int +STDCALL +GetTimeFormatW( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME *lpTime, + LPCWSTR lpFormat, + LPWSTR lpTimeStr, + int cchTime); + +int +STDCALL +GetDateFormatW( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME *lpDate, + LPCWSTR lpFormat, + LPWSTR lpDateStr, + int cchDate); + +int +STDCALL +GetNumberFormatW( + LCID Locale, + DWORD dwFlags, + LPCWSTR lpValue, + CONST NUMBERFMT *lpFormat, + LPWSTR lpNumberStr, + int cchNumber); + +int +STDCALL +GetCurrencyFormatW( + LCID Locale, + DWORD dwFlags, + LPCWSTR lpValue, + CONST CURRENCYFMT *lpFormat, + LPWSTR lpCurrencyStr, + int cchCurrency); + +WINBOOL +STDCALL +EnumCalendarInfoW( + CALINFO_ENUMPROC lpCalInfoEnumProc, + LCID Locale, + CALID Calendar, + CALTYPE CalType); + +WINBOOL +STDCALL +EnumTimeFormatsW( + TIMEFMT_ENUMPROC lpTimeFmtEnumProc, + LCID Locale, + DWORD dwFlags); + +WINBOOL +STDCALL +EnumDateFormatsW( + DATEFMT_ENUMPROC lpDateFmtEnumProc, + LCID Locale, + DWORD dwFlags); + +WINBOOL +STDCALL +GetStringTypeExW( + LCID Locale, + DWORD dwInfoType, + LPCWSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType); + +WINBOOL +STDCALL +GetStringTypeW( + DWORD dwInfoType, + LPCWSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType); + +int +STDCALL +FoldStringW( + DWORD dwMapFlags, + LPCWSTR lpSrcStr, + int cchSrc, + LPWSTR lpDestStr, + int cchDest); + +WINBOOL +STDCALL +EnumSystemLocalesW( + LOCALE_ENUMPROC lpLocaleEnumProc, + DWORD dwFlags); + +WINBOOL +STDCALL +EnumSystemCodePagesW( + CODEPAGE_ENUMPROC lpCodePageEnumProc, + DWORD dwFlags); + +WINBOOL +STDCALL +PeekConsoleInputW( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ); + +WINBOOL +STDCALL +ReadConsoleInputW( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ); + +WINBOOL +STDCALL +WriteConsoleInputW( + HANDLE hConsoleInput, + CONST INPUT_RECORD *lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten + ); + +WINBOOL +STDCALL +ReadConsoleOutputW( + HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion + ); + +WINBOOL +STDCALL +WriteConsoleOutputW( + HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion + ); + +WINBOOL +STDCALL +ReadConsoleOutputCharacterW( + HANDLE hConsoleOutput, + LPWSTR lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead + ); + +WINBOOL +STDCALL +WriteConsoleOutputCharacterW( + HANDLE hConsoleOutput, + LPCWSTR lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ); + +WINBOOL +STDCALL +FillConsoleOutputCharacterW( + HANDLE hConsoleOutput, + WCHAR cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ); + +WINBOOL +STDCALL +ScrollConsoleScreenBufferW( + HANDLE hConsoleOutput, + CONST SMALL_RECT *lpScrollRectangle, + CONST SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + CONST CHAR_INFO *lpFill + ); + +DWORD +STDCALL +GetConsoleTitleW( + LPWSTR lpConsoleTitle, + DWORD nSize + ); + +WINBOOL +STDCALL +SetConsoleTitleW( + LPCWSTR lpConsoleTitle + ); + +WINBOOL +STDCALL +ReadConsoleW( + HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + LPVOID lpReserved + ); + +WINBOOL +STDCALL +WriteConsoleW( + HANDLE hConsoleOutput, + CONST VOID *lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved + ); + +DWORD STDCALL +WNetAddConnectionW( + LPCWSTR lpRemoteName, + LPCWSTR lpPassword, + LPCWSTR lpLocalName + ); + +DWORD STDCALL +WNetAddConnection2W( + LPNETRESOURCE lpNetResource, + LPCWSTR lpPassword, + LPCWSTR lpUserName, + DWORD dwFlags + ); + +DWORD STDCALL +WNetAddConnection3W( + HWND hwndOwner, + LPNETRESOURCE lpNetResource, + LPCWSTR lpPassword, + LPCWSTR lpUserName, + DWORD dwFlags + ); + +DWORD STDCALL +WNetCancelConnectionW( + LPCWSTR lpName, + WINBOOL fForce + ); + +DWORD STDCALL +WNetCancelConnection2W( + LPCWSTR lpName, + DWORD dwFlags, + WINBOOL fForce + ); + +DWORD STDCALL +WNetGetConnectionW( + LPCWSTR lpLocalName, + LPWSTR lpRemoteName, + LPDWORD lpnLength + ); + +DWORD STDCALL +WNetUseConnectionW( + HWND hwndOwner, + LPNETRESOURCE lpNetResource, + LPCWSTR lpUserID, + LPCWSTR lpPassword, + DWORD dwFlags, + LPWSTR lpAccessName, + LPDWORD lpBufferSize, + LPDWORD lpResult + ); + +DWORD STDCALL +WNetSetConnectionW( + LPCWSTR lpName, + DWORD dwProperties, + LPVOID pvValues + ); + +DWORD STDCALL +WNetConnectionDialog1W( + LPCONNECTDLGSTRUCT lpConnDlgStruct + ); + +DWORD STDCALL +WNetDisconnectDialog1W( + LPDISCDLGSTRUCT lpConnDlgStruct + ); + +DWORD STDCALL +WNetOpenEnumW( + DWORD dwScope, + DWORD dwType, + DWORD dwUsage, + LPNETRESOURCE lpNetResource, + LPHANDLE lphEnum + ); + +DWORD STDCALL +WNetEnumResourceW( + HANDLE hEnum, + LPDWORD lpcCount, + LPVOID lpBuffer, + LPDWORD lpBufferSize + ); + +DWORD STDCALL +WNetGetUniversalNameW( + LPCWSTR lpLocalPath, + DWORD dwInfoLevel, + LPVOID lpBuffer, + LPDWORD lpBufferSize + ); + +DWORD STDCALL +WNetGetUserW( + LPCWSTR lpName, + LPWSTR lpUserName, + LPDWORD lpnLength + ); + +DWORD STDCALL +WNetGetProviderNameW( + DWORD dwNetType, + LPWSTR lpProviderName, + LPDWORD lpBufferSize + ); + +DWORD STDCALL +WNetGetNetworkInformationW( + LPCWSTR lpProvider, + LPNETINFOSTRUCT lpNetInfoStruct + ); + +DWORD STDCALL +WNetGetLastErrorW( + LPDWORD lpError, + LPWSTR lpErrorBuf, + DWORD nErrorBufSize, + LPWSTR lpNameBuf, + DWORD nNameBufSize + ); + +DWORD STDCALL +MultinetGetConnectionPerformanceW( + LPNETRESOURCE lpNetResource, + LPNETCONNECTINFOSTRUCT lpNetConnectInfoStruct + ); + +WINBOOL +STDCALL +ChangeServiceConfigW( + SC_HANDLE hService, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCWSTR lpBinaryPathName, + LPCWSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCWSTR lpDependencies, + LPCWSTR lpServiceStartName, + LPCWSTR lpPassword, + LPCWSTR lpDisplayName + ); + +SC_HANDLE +STDCALL +CreateServiceW( + SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + LPCWSTR lpDisplayName, + DWORD dwDesiredAccess, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCWSTR lpBinaryPathName, + LPCWSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCWSTR lpDependencies, + LPCWSTR lpServiceStartName, + LPCWSTR lpPassword + ); + +WINBOOL +STDCALL +EnumDependentServicesW( + SC_HANDLE hService, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned + ); + +WINBOOL +STDCALL +EnumServicesStatusW( + SC_HANDLE hSCManager, + DWORD dwServiceType, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle + ); + +WINBOOL +STDCALL +GetServiceKeyNameW( + SC_HANDLE hSCManager, + LPCWSTR lpDisplayName, + LPWSTR lpServiceName, + LPDWORD lpcchBuffer + ); + +WINBOOL +STDCALL +GetServiceDisplayNameW( + SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + LPWSTR lpDisplayName, + LPDWORD lpcchBuffer + ); + +SC_HANDLE +STDCALL +OpenSCManagerW( + LPCWSTR lpMachineName, + LPCWSTR lpDatabaseName, + DWORD dwDesiredAccess + ); + +SC_HANDLE +STDCALL +OpenServiceW( + SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + DWORD dwDesiredAccess + ); + +WINBOOL +STDCALL +QueryServiceConfigW( + SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGW lpServiceConfig, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ); + +WINBOOL +STDCALL +QueryServiceLockStatusW( + SC_HANDLE hSCManager, + LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ); + +SERVICE_STATUS_HANDLE +STDCALL +RegisterServiceCtrlHandlerW( + LPCWSTR lpServiceName, + LPHANDLER_FUNCTION lpHandlerProc + ); + +WINBOOL +STDCALL +StartServiceCtrlDispatcherW( + LPSERVICE_TABLE_ENTRYW lpServiceStartTable + ); + +WINBOOL +STDCALL +StartServiceW( + SC_HANDLE hService, + DWORD dwNumServiceArgs, + LPCWSTR *lpServiceArgVectors + ); + +/* Extensions to OpenGL */ + +WINBOOL STDCALL +wglUseFontBitmapsW(HDC, DWORD, DWORD, DWORD); + +WINBOOL STDCALL +wglUseFontOutlinesW(HDC, DWORD, DWORD, DWORD, FLOAT, + FLOAT, int, LPGLYPHMETRICSFLOAT); + +/* ------------------------------------- */ +/* From shellapi.h in old Cygnus headers */ + +unsigned int WINAPI +DragQueryFileW(HDROP, unsigned int, LPCWSTR, unsigned int); + +HICON WINAPI +ExtractAssociatedIconW (HINSTANCE, LPCWSTR, WORD *); + +HICON WINAPI +ExtractIconW (HINSTANCE, const LPCWSTR, unsigned int); + +HINSTANCE WINAPI +FindExecutableW (const LPCWSTR, const LPCWSTR, LPCWSTR); + +int WINAPI +ShellAboutW (HWND, const LPCWSTR, const LPCWSTR, HICON); + +HINSTANCE WINAPI +ShellExecuteW (HWND, const LPCWSTR, const LPCWSTR, LPCWSTR, const LPCWSTR, int); + +/* end of stuff from shellapi.h in old Cygnus headers */ +/* -------------------------------------------------- */ +/* From ddeml.h in old Cygnus headers */ + +HSZ +WINAPI +DdeCreateStringHandleW( + DWORD idInst, + LPWSTR psz, + int iCodePage); + +UINT WINAPI +DdeInitializeW (DWORD *, CALLB, DWORD, DWORD); + +DWORD +WINAPI +DdeQueryStringW( + DWORD idInst, + HSZ hsz, + LPWSTR psz, + DWORD cchMax, + int iCodePage); + +/* end of stuff from ddeml.h in old Cygnus headers */ +/* ----------------------------------------------- */ + +WINBOOL STDCALL LogonUserW (LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD, HANDLE *); +WINBOOL STDCALL CreateProcessAsUserW (HANDLE, LPCWSTR, LPWSTR, + SECURITY_ATTRIBUTES*, SECURITY_ATTRIBUTES*, WINBOOL, + DWORD, LPVOID, LPCWSTR, STARTUPINFOW*, + PROCESS_INFORMATION*); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GNU_H_WINDOWS32_UNICODEFUNCTIONS */ diff --git a/include/user32/callback.h b/include/user32/callback.h new file mode 100644 index 0000000..e6f2fd5 --- /dev/null +++ b/include/user32/callback.h @@ -0,0 +1,85 @@ +#ifndef __INCLUDE_USER32_CALLBACK_H +#define __INCLUDE_USER32_CALLBACK_H + +#define USER32_CALLBACK_WINDOWPROC (0) +#define USER32_CALLBACK_SENDASYNCPROC (1) +#define USER32_CALLBACK_SENDNCCREATE (2) +#define USER32_CALLBACK_SENDNCCALCSIZE (3) +#define USER32_CALLBACK_SENDCREATE (4) +#define USER32_CALLBACK_SENDGETMINMAXINFO (5) +#define USER32_CALLBACK_MAXIMUM (6) + +typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS +{ + WNDPROC Proc; + HWND Wnd; + UINT Msg; + WPARAM wParam; + LPARAM lParam; +} WINDOWPROC_CALLBACK_ARGUMENTS, *PWINDOWPROC_CALLBACK_ARGUMENTS; + +typedef struct _SENDASYNCPROC_CALLBACK_ARGUMENTS +{ + SENDASYNCPROC Callback; + HWND Wnd; + UINT Msg; + ULONG_PTR Context; + LRESULT Result; +} SENDASYNCPROC_CALLBACK_ARGUMENTS, *PSENDASYNCPROC_CALLBACK_ARGUMENTS; + +typedef struct _SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS +{ + HWND Wnd; + CREATESTRUCTW CreateStruct; +} SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS, + *PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS; + +typedef struct _SENDCREATEMESSAGE_CALLBACK_ARGUMENTS +{ + HWND Wnd; + CREATESTRUCTW CreateStruct; +} SENDCREATEMESSAGE_CALLBACK_ARGUMENTS, *PSENDCREATEMESSAGE_CALLBACK_ARGUMENTS; + +typedef struct _SENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS +{ + HWND Wnd; + BOOL Validate; + RECT Rect; + NCCALCSIZE_PARAMS Params; +} SENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS, + *PSENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS; + +typedef struct _SENDNCCALCSIZEMESSAGE_CALLBACK_RESULT +{ + LRESULT Result; + RECT Rect; + NCCALCSIZE_PARAMS Params; +} SENDNCCALCSIZEMESSAGE_CALLBACK_RESULT, + *PSENDNCCALCSIZEMESSAGE_CALLBACK_RESULT; + +typedef struct _SENDGETMINMAXINFO_CALLBACK_ARGUMENTS +{ + HWND Wnd; + MINMAXINFO MinMaxInfo; +} SENDGETMINMAXINFO_CALLBACK_ARGUMENTS, *PSENDGETMINMAXINFO_CALLBACK_ARGUMENTS; + +typedef struct _SENDGETMINMAXINFO_CALLBACK_RESULT +{ + LRESULT Result; + MINMAXINFO MinMaxInfo; +} SENDGETMINMAXINFO_CALLBACK_RESULT, *PSENDGETMINMAXINFO_CALLBACK_RESULT; + +NTSTATUS STDCALL +User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32SendNCCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32SendCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32SendGETMINMAXINFOMessageForKernel(PVOID Arguments, ULONG ArgumentLength); +NTSTATUS STDCALL +User32SendNCCALCSIZEMessageForKernel(PVOID Arguments, ULONG ArgumentLength); + +#endif /* __INCLUDE_USER32_CALLBACK_H */ diff --git a/include/user32/wininternal.h b/include/user32/wininternal.h new file mode 100644 index 0000000..8f88319 --- /dev/null +++ b/include/user32/wininternal.h @@ -0,0 +1,22 @@ +#ifndef __INCLUDE_USER32_WININTERNAL_H +#define __INCLUDE_USER32_WININTERNAL_H + +typedef struct _INTERNALPOS +{ + RECT NormalRect; + POINT IconPos; + POINT MaxPos; + HWND IconTitle; +} INTERNALPOS, *PINTERNALPOS; + +#define WIN_NCACTIVATED (0x0080) + +/* internal DCX flags */ +#define DCX_DCEEMPTY 0x00000800 +#define DCX_DCEBUSY 0x00001000 +#define DCX_DCEDIRTY 0x00002000 +#define DCX_WINDOWPAINT 0x00020000 +#define DCX_KEEPCLIPRGN 0x00040000 +#define DCX_NOCLIPCHILDREN 0x00080000 + +#endif /* __INCLUDE_USER32_WININTERNAL_H */ diff --git a/include/win32k/bitmaps.h b/include/win32k/bitmaps.h new file mode 100644 index 0000000..e504a02 --- /dev/null +++ b/include/win32k/bitmaps.h @@ -0,0 +1,299 @@ + +#ifndef __WIN32K_BITMAPS_H +#define __WIN32K_BITMAPS_H + +#include +#include + +typedef struct _DDBITMAP +{ + const PDRIVER_FUNCTIONS pDriverFunctions; +// DHPDEV PDev; +// HSURF Surface; +} DDBITMAP; + +/* GDI logical bitmap object */ +typedef struct _BITMAPOBJ +{ + BITMAP bitmap; + SIZE size; /* For SetBitmapDimension() */ + + DDBITMAP *DDBitmap; + + /* For device-independent bitmaps: */ + DIBSECTION *dib; + RGBQUAD *ColorMap; +} BITMAPOBJ, *PBITMAPOBJ; + +/* Internal interface */ + +#define BITMAPOBJ_AllocBitmap() \ + ((HBITMAP) GDIOBJ_AllocObj (sizeof (BITMAPOBJ), GO_BITMAP_MAGIC)) +#define BITMAPOBJ_FreeBitmap(hBMObj) \ + GDIOBJ_FreeObj((HGDIOBJ) hBMObj, GO_BITMAP_MAGIC, GDIOBJFLAG_DEFAULT) +#define BITMAPOBJ_HandleToPtr(hBMObj) \ + ((PBITMAPOBJ) GDIOBJ_LockObj ((HGDIOBJ) hBMObj, GO_BITMAP_MAGIC)) +#define BITMAPOBJ_ReleasePtr(hBMObj) \ + GDIOBJ_UnlockObj ((HGDIOBJ) hBMObj, GO_BITMAP_MAGIC) + +/*#define BITMAPOBJ_PtrToHandle(hBMObj) \ + ((HBITMAP) GDIOBJ_PtrToHandle ((PGDIOBJ) hBMObj, GO_BITMAP_MAGIC))*/ +#define BITMAPOBJ_LockBitmap(hBMObj) GDIOBJ_LockObject ((HGDIOBJ) hBMObj) +#define BITMAPOBJ_UnlockBitmap(hBMObj) GDIOBJ_UnlockObject ((HGDIOBJ) hBMObj) + +INT BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp); +HBITMAP BITMAPOBJ_CopyBitmap (HBITMAP hBitmap); +int DIB_GetDIBWidthBytes (int width, int depth); +int DIB_GetDIBImageBytes (int width, int height, int depth); +int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse); +INT BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer); +BOOL Bitmap_InternalDelete( PBITMAPOBJ pBmp ); + +/* User Entry Points */ +BOOL +STDCALL +W32kBitBlt ( + HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + DWORD ROP + ); +HBITMAP +STDCALL +W32kCreateBitmap ( + INT Width, + INT Height, + UINT Planes, + UINT BitsPerPel, + CONST VOID * Bits + ); +HBITMAP +STDCALL +W32kCreateCompatibleBitmap ( + HDC hDC, + INT Width, + INT Height + ); +HBITMAP +STDCALL +W32kCreateBitmapIndirect ( + CONST BITMAP * BM + ); +HBITMAP +STDCALL +W32kCreateDIBitmap ( + HDC hDC, + CONST BITMAPINFOHEADER * bmih, + DWORD Init, + CONST VOID * bInit, + CONST BITMAPINFO * bmi, + UINT Usage + ); +HBITMAP +STDCALL +W32kCreateDIBSection ( + HDC hDC, + CONST BITMAPINFO * bmi, + UINT Usage, + VOID * Bits, + HANDLE hSection, + DWORD dwOffset + ); +HBITMAP +STDCALL +W32kCreateDiscardableBitmap ( + HDC hDC, + INT Width, + INT Height + ); +BOOL +STDCALL +W32kExtFloodFill ( + HDC hDC, + INT XStart, + INT YStart, + COLORREF Color, + UINT FillType + ); +BOOL +STDCALL +W32kFloodFill ( + HDC hDC, + INT XStart, + INT YStart, + COLORREF Fill + ); +LONG +STDCALL +W32kGetBitmapBits ( + HBITMAP hBitmap, + LONG Buffer, + LPVOID Bits + ); +BOOL +STDCALL +W32kGetBitmapDimensionEx ( + HBITMAP hBitmap, + LPSIZE Dimension + ); +UINT +STDCALL +W32kGetDIBColorTable ( + HDC hDC, + UINT StartIndex, + UINT Entries, + RGBQUAD * Colors + ); +INT +STDCALL +W32kGetDIBits ( + HDC hDC, + HBITMAP hBitmap, + UINT StartScan, + UINT ScanLines, + LPVOID Bits, + LPBITMAPINFO bi, + UINT Usage + ); +COLORREF +STDCALL +W32kGetPixel ( + HDC hDC, + INT XPos, + INT YPos + ); +BOOL +STDCALL +W32kMaskBlt ( + HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + HBITMAP hMaskBitmap, + INT xMask, + INT yMask, + DWORD ROP + ); +BOOL +STDCALL +W32kPlgBlt ( + HDC hDCDest, + CONST POINT * Point, + HDC hDCSrc, + INT XSrc, + INT YSrc, + INT Width, + INT Height, + HBITMAP hMaskBitmap, + INT xMask, + INT yMask + ); +LONG +STDCALL +W32kSetBitmapBits ( + HBITMAP hBitmap, + DWORD Bytes, + CONST VOID * Bits + ); +BOOL +STDCALL +W32kSetBitmapDimensionEx ( + HBITMAP hBitmap, + INT Width, + INT Height, + LPSIZE Size + ); +UINT +STDCALL +W32kSetDIBColorTable ( + HDC hDC, + UINT StartIndex, + UINT Entries, + CONST RGBQUAD * Colors + ); +INT +STDCALL +W32kSetDIBits ( + HDC hDC, + HBITMAP hBitmap, + UINT StartScan, + UINT ScanLines, + CONST VOID * Bits, + CONST BITMAPINFO * bmi, + UINT ColorUse + ); +INT +STDCALL +W32kSetDIBitsToDevice ( + HDC hDC, + INT XDest, + INT YDest, + DWORD Width, + DWORD Height, + INT XSrc, + INT YSrc, + UINT StartScan, + UINT ScanLines, + CONST VOID * Bits, + CONST BITMAPINFO * bmi, + UINT ColorUse + ); +COLORREF +STDCALL +W32kSetPixel ( + HDC hDC, + INT X, + INT Y, + COLORREF Color + ); +BOOL +STDCALL +W32kSetPixelV ( + HDC hDC, + INT X, + INT Y, + COLORREF Color + ); +BOOL +STDCALL +W32kStretchBlt ( + HDC hDCDest, + INT XOriginDest, + INT YOriginDest, + INT WidthDest, + INT HeightDest, + HDC hDCSrc, + INT XOriginSrc, + INT YOriginSrc, + INT WidthSrc, + INT HeightSrc, + DWORD ROP + ); +INT +STDCALL +W32kStretchDIBits ( + HDC hDC, + INT XDest, + INT YDest, + INT DestWidth, + INT DestHeight, + INT XSrc, + INT YSrc, + INT SrcWidth, + INT SrcHeight, + CONST VOID * Bits, + CONST BITMAPINFO * BitsInfo, + UINT Usage, + DWORD ROP + ); +#endif + diff --git a/include/win32k/brush.h b/include/win32k/brush.h new file mode 100644 index 0000000..ea52c93 --- /dev/null +++ b/include/win32k/brush.h @@ -0,0 +1,78 @@ +#ifndef __WIN32K_BRUSH_H +#define __WIN32K_BRUSH_H + +#include + +/* Internal interface */ + +#define NB_HATCH_STYLES 6 + +#define BRUSHOBJ_AllocBrush() \ + ((HBRUSH) GDIOBJ_AllocObj (sizeof (BRUSHOBJ), GO_BRUSH_MAGIC)) +#define BRUSHOBJ_FreeBrush(hBrush) GDIOBJ_FreeObj((HGDIOBJ)hBrush, GO_BRUSH_MAGIC, GDIOBJFLAG_DEFAULT) +/*#define BRUSHOBJ_HandleToPtr(hBrush) \ + ((PBRUSHOBJ) GDIOBJ_HandleToPtr ((HGDIOBJ) hBrush, GO_BRUSH_MAGIC)) +#define BRUSHOBJ_PtrToHandle(pBrushObj) \ + ((HBRUSH) GDIOBJ_PtrToHandle ((PGDIOBJ) pBrushObj, GO_BRUSH_MAGIC)) +*/ +#define BRUSHOBJ_LockBrush(hBrush) ((PBRUSHOBJ)GDIOBJ_LockObj((HGDIOBJ)hBrush, GO_BRUSH_MAGIC)) +#define BRUSHOBJ_UnlockBrush(hBrush) GDIOBJ_UnlockObj((HGDIOBJ)hBrush, GO_BRUSH_MAGIC) + +HBRUSH +STDCALL +W32kCreateBrushIndirect ( + CONST LOGBRUSH * lb + ); +HBRUSH +STDCALL +W32kCreateDIBPatternBrush ( + HGLOBAL hDIBPacked, + UINT ColorSpec + ); +HBRUSH +STDCALL +W32kCreateDIBPatternBrushPt ( + CONST VOID * PackedDIB, + UINT Usage + ); +HBRUSH +STDCALL +W32kCreateHatchBrush ( + INT Style, + COLORREF Color + ); +HBRUSH +STDCALL +W32kCreatePatternBrush ( + HBITMAP hBitmap + ); +HBRUSH +STDCALL +W32kCreateSolidBrush ( + COLORREF Color + ); +BOOL +STDCALL +W32kFixBrushOrgEx ( + VOID + ); +BOOL +STDCALL +W32kPatBlt ( + HDC hDC, + INT XLeft, + INT YLeft, + INT Width, + INT Height, + DWORD ROP + ); +BOOL +STDCALL +W32kSetBrushOrgEx ( + HDC hDC, + INT XOrg, + INT YOrg, + LPPOINT Point + ); +#endif + diff --git a/include/win32k/cliprgn.h b/include/win32k/cliprgn.h new file mode 100644 index 0000000..4b8f7cb --- /dev/null +++ b/include/win32k/cliprgn.h @@ -0,0 +1,81 @@ +#ifndef _WIN32K_CLIPRGN_H +#define _WIN32K_CLIPRGN_H + +HRGN WINAPI SaveVisRgn(HDC hdc); +INT WINAPI SelectVisRgn(HDC hdc, HRGN hrgn); + +int +STDCALL +W32kExcludeClipRect ( + HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect + ); +int +STDCALL +W32kExtSelectClipRgn ( + HDC hDC, + HRGN hrgn, + int fnMode + ); +int +STDCALL +W32kGetClipBox ( + HDC hDC, + LPRECT rc + ); +int +STDCALL +W32kGetMetaRgn ( + HDC hDC, + HRGN hrgn + ); +int +STDCALL +W32kIntersectClipRect ( + HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect + ); +int +STDCALL +W32kOffsetClipRgn ( + HDC hDC, + int XOffset, + int YOffset + ); +BOOL +STDCALL +W32kPtVisible ( + HDC hDC, + int X, + int Y + ); +BOOL +STDCALL +W32kRectVisible ( + HDC hDC, + CONST PRECT rc + ); +BOOL +STDCALL +W32kSelectClipPath ( + HDC hDC, + int Mode + ); +int +STDCALL +W32kSelectClipRgn ( + HDC hDC, + HRGN hrgn + ); +int +STDCALL +W32kSetMetaRgn ( + HDC hDC + ); +#endif diff --git a/include/win32k/color.h b/include/win32k/color.h new file mode 100644 index 0000000..2b68d19 --- /dev/null +++ b/include/win32k/color.h @@ -0,0 +1,114 @@ +#ifndef __WIN32K_COLOR_H +#define __WIN32K_COLOR_H + +#define CLR_INVALID 0xffffffff +#define PC_SYS_USED 0x80 // palentry is used (both system and logical) +#define PC_SYS_RESERVED 0x40 // system palentry is not to be mapped to +#define PC_SYS_MAPPED 0x10 // logical palentry is a direct alias for system palentry + +BOOL +STDCALL +W32kAnimatePalette ( + HPALETTE hpal, + UINT StartIndex, + UINT Entries, + CONST PPALETTEENTRY ppe + ); +HPALETTE +STDCALL +W32kCreateHalftonePalette ( + HDC hDC + ); +HPALETTE +STDCALL +W32kCreatePalette ( + CONST PLOGPALETTE lgpl + ); +BOOL +STDCALL +W32kGetColorAdjustment ( + HDC hDC, + LPCOLORADJUSTMENT ca + ); +COLORREF +STDCALL +W32kGetNearestColor ( + HDC hDC, + COLORREF Color + ); +UINT +STDCALL +W32kGetNearestPaletteIndex ( + HPALETTE hpal, + COLORREF Color + ); +UINT +STDCALL +W32kGetPaletteEntries ( + HPALETTE hpal, + UINT StartIndex, + UINT Entries, + LPPALETTEENTRY pe + ); +UINT +STDCALL +W32kGetSystemPaletteEntries ( + HDC hDC, + UINT StartIndex, + UINT Entries, + LPPALETTEENTRY pe + ); +UINT +STDCALL +W32kGetSystemPaletteUse ( + HDC hDC + ); +UINT +STDCALL +W32kRealizePalette ( + HDC hDC + ); +BOOL +STDCALL +W32kResizePalette ( + HPALETTE hpal, + UINT Entries + ); +HPALETTE +STDCALL +W32kSelectPalette ( + HDC hDC, + HPALETTE hpal, + BOOL ForceBackground + ); +BOOL +STDCALL +W32kSetColorAdjustment ( + HDC hDC, + CONST LPCOLORADJUSTMENT ca + ); +UINT +STDCALL +W32kSetPaletteEntries ( + HPALETTE hpal, + UINT Start, + UINT Entries, + CONST LPPALETTEENTRY pe + ); +UINT +STDCALL +W32kSetSystemPaletteUse ( + HDC hDC, + UINT Usage + ); +BOOL +STDCALL +W32kUnrealizeObject ( + HGDIOBJ hgdiobj + ); +BOOL +STDCALL +W32kUpdateColors ( + HDC hDC + ); +#endif diff --git a/include/win32k/coord.h b/include/win32k/coord.h new file mode 100644 index 0000000..5dfba5d --- /dev/null +++ b/include/win32k/coord.h @@ -0,0 +1,129 @@ +#ifndef __WIN32K_COORD_H +#define __WIN32K_COORD_H + +BOOL +STDCALL +W32kCombineTransform ( + LPXFORM XformResult, + CONST LPXFORM xform1, + CONST LPXFORM xform2 + ); +BOOL +STDCALL +W32kDPtoLP ( + HDC hDC, + LPPOINT Points, + int Count + ); +int +STDCALL +W32kGetGraphicsMode ( + HDC hDC + ); +BOOL +STDCALL +W32kGetWorldTransform ( + HDC hDC, + LPXFORM Xform + ); +BOOL +STDCALL +W32kLPtoDP ( + HDC hDC, + LPPOINT Points, + int Count + ); +BOOL +STDCALL +W32kModifyWorldTransform ( + HDC hDC, + CONST LPXFORM Xform, + DWORD Mode + ); +BOOL +STDCALL +W32kOffsetViewportOrgEx ( + HDC hDC, + int XOffset, + int YOffset, + LPPOINT Point + ); +BOOL +STDCALL +W32kOffsetWindowOrgEx ( + HDC hDC, + int XOffset, + int YOffset, + LPPOINT Point + ); +BOOL +STDCALL +W32kScaleViewportExtEx ( + HDC hDC, + int Xnum, + int Xdenom, + int Ynum, + int Ydenom, + LPSIZE Size + ); +BOOL +STDCALL +W32kScaleWindowExtEx ( + HDC hDC, + int Xnum, + int Xdenom, + int Ynum, + int Ydenom, + LPSIZE Size + ); +int +STDCALL +W32kSetGraphicsMode ( + HDC hDC, + int Mode + ); +int +STDCALL +W32kSetMapMode ( + HDC hDC, + int MapMode + ); +BOOL +STDCALL +W32kSetViewportExtEx ( + HDC hDC, + int XExtent, + int YExtent, + LPSIZE Size + ); +BOOL +STDCALL +W32kSetViewportOrgEx ( + HDC hDC, + int X, + int Y, + LPPOINT Point + ); +BOOL +STDCALL +W32kSetWindowExtEx ( + HDC hDC, + int XExtent, + int YExtent, + LPSIZE Size + ); +BOOL +STDCALL +W32kSetWindowOrgEx ( + HDC hDC, + int X, + int Y, + LPPOINT Point + ); +BOOL +STDCALL +W32kSetWorldTransform ( + HDC hDC, + CONST LPXFORM Xform + ); +#endif diff --git a/include/win32k/dc.h b/include/win32k/dc.h new file mode 100644 index 0000000..0a4e34c --- /dev/null +++ b/include/win32k/dc.h @@ -0,0 +1,241 @@ + +#ifndef __WIN32K_DC_H +#define __WIN32K_DC_H + +#include +#include +#include +#include + +typedef struct +{ + HANDLE Handle; + DHPDEV PDev; + DEVMODEW DMW; + HSURF FillPatterns[HS_DDI_MAX]; + GDIINFO GDIInfo; + DEVINFO DevInfo; + DRIVER_FUNCTIONS DriverFunctions; +} GDIDEVICE; + +/* (RJJ) Taken from WINE */ +typedef struct _DEVICECAPS +{ + WORD version; /* 0: driver version */ + WORD technology; /* 2: device technology */ + WORD horzSize; /* 4: width of display in mm */ + WORD vertSize; /* 6: height of display in mm */ + WORD horzRes; /* 8: width of display in pixels */ + WORD vertRes; /* 10: width of display in pixels */ + WORD bitsPixel; /* 12: bits per pixel */ + WORD planes; /* 14: color planes */ + WORD numBrushes; /* 16: device-specific brushes */ + WORD numPens; /* 18: device-specific pens */ + WORD numMarkers; /* 20: device-specific markers */ + WORD numFonts; /* 22: device-specific fonts */ + WORD numColors; /* 24: size of color table */ + WORD pdeviceSize; /* 26: size of PDEVICE structure */ + WORD curveCaps; /* 28: curve capabilities */ + WORD lineCaps; /* 30: line capabilities */ + WORD polygonalCaps; /* 32: polygon capabilities */ + WORD textCaps; /* 34: text capabilities */ + WORD clipCaps; /* 36: clipping capabilities */ + WORD rasterCaps; /* 38: raster capabilities */ + WORD aspectX; /* 40: relative width of device pixel */ + WORD aspectY; /* 42: relative height of device pixel */ + WORD aspectXY; /* 44: relative diagonal width of device pixel */ + WORD pad1[21]; /* 46-86: reserved */ + WORD logPixelsX; /* 88: pixels / logical X inch */ + WORD logPixelsY; /* 90: pixels / logical Y inch */ + WORD pad2[6]; /* 92-102: reserved */ + WORD sizePalette; /* 104: entries in system palette */ + WORD numReserved; /* 106: reserved entries */ + WORD colorRes; /* 108: color resolution */ +} DEVICECAPS, *PDEVICECAPS; + +typedef struct _WIN_DC_INFO +{ + int flags; + const PDEVICECAPS devCaps; + HRGN hClipRgn; /* Clip region (may be 0) */ + HRGN hVisRgn; /* Visible region (must never be 0) */ + HRGN hGCClipRgn; /* GC clip region (ClipRgn AND VisRgn) */ + HPEN hPen; + HBRUSH hBrush; + HFONT hFont; + HBITMAP hBitmap; + HBITMAP hFirstBitmap; /* Bitmap selected at creation of the DC */ + +// #if 0 + HANDLE hDevice; + HPALETTE hPalette; + + GdiPath path; +// #endif + + WORD ROPmode; + WORD polyFillMode; + WORD stretchBltMode; + WORD relAbsMode; + WORD backgroundMode; + COLORREF backgroundColor; + COLORREF textColor; + + short brushOrgX; + short brushOrgY; + + WORD textAlign; /* Text alignment from SetTextAlign() */ + short charExtra; /* Spacing from SetTextCharacterExtra() */ + short breakTotalExtra; /* Total extra space for justification */ + short breakCount; /* Break char. count */ + short breakExtra; /* breakTotalExtra / breakCount */ + short breakRem; /* breakTotalExtra % breakCount */ + + RECT totalExtent; + BYTE bitsPerPixel; + + INT MapMode; + INT GraphicsMode; /* Graphics mode */ + INT DCOrgX; /* DC origin */ + INT DCOrgY; + +#if 0 + FARPROC lpfnPrint; /* AbortProc for Printing */ +#endif + + INT CursPosX; /* Current position */ + INT CursPosY; + INT ArcDirection; + + XFORM xformWorld2Wnd; /* World-to-window transformation */ + XFORM xformWorld2Vport; /* World-to-viewport transformation */ + XFORM xformVport2World; /* Inverse of the above transformation */ + BOOL vport2WorldValid; /* Is xformVport2World valid? */ +} WIN_DC_INFO; + + /* DC flags */ +#define DC_MEMORY 0x0001 /* It is a memory DC */ +#define DC_SAVED 0x0002 /* It is a saved DC */ +#define DC_DIRTY 0x0004 /* hVisRgn has to be updated */ +#define DC_THUNKHOOK 0x0008 /* DC hook is in the 16-bit code */ + +#define GDI_DC_TYPE (1) + +typedef struct _DC +{ + HDC hSelf; + HDC hNext; + DHPDEV PDev; + DEVMODEW DMW; + HSURF FillPatternSurfaces[HS_DDI_MAX]; + GDIINFO GDIInfo; + DEVINFO DevInfo; + HSURF Surface; + + DRIVER_FUNCTIONS DriverFunctions; + PWSTR DriverName; + HANDLE DeviceDriver; + + INT wndOrgX; /* Window origin */ + INT wndOrgY; + INT wndExtX; /* Window extent */ + INT wndExtY; + INT vportOrgX; /* Viewport origin */ + INT vportOrgY; + INT vportExtX; /* Viewport extent */ + INT vportExtY; + + INT saveLevel; + + WIN_DC_INFO w; +} DC, *PDC; + +/* Internal functions */ + +/* +#define DC_PtrToHandle(pDC) \ + ((HDC) GDIOBJ_PtrToHandle ((PGDIOBJ) pDC, GO_DC_MAGIC)) +*/ + +#define DC_HandleToPtr(hDC) \ + ((PDC) GDIOBJ_LockObj ((HGDIOBJ) hDC, GO_DC_MAGIC)) +#define DC_ReleasePtr(hDC) \ + GDIOBJ_UnlockObj ((HGDIOBJ) hDC, GO_DC_MAGIC) + +HDC RetrieveDisplayHDC(VOID); +HDC DC_AllocDC(LPCWSTR Driver); +void DC_InitDC(HDC DCToInit); +HDC DC_FindOpenDC(LPCWSTR Driver); +void DC_FreeDC(HDC DCToFree); +HDC DC_GetNextDC (PDC pDC); +void DC_SetNextDC (PDC pDC, HDC hNextDC); +BOOL DC_InternalDeleteDC( PDC DCToDelete ); + +void DC_UpdateXforms(PDC dc); +BOOL DC_InvertXform(const XFORM *xformSrc, XFORM *xformDest); + +/* User entry points */ + +BOOL STDCALL W32kCancelDC(HDC hDC); +HDC STDCALL W32kCreateCompatableDC(HDC hDC); +HDC STDCALL W32kCreateDC(LPCWSTR Driver, + LPCWSTR Device, + LPCWSTR Output, + CONST PDEVMODEW InitData); +HDC STDCALL W32kCreateIC(LPCWSTR Driver, + LPCWSTR Device, + LPCWSTR Output, + CONST PDEVMODEW DevMode); +BOOL STDCALL W32kDeleteDC(HDC hDC); +BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject); +INT STDCALL W32kDrawEscape(HDC hDC, + INT nEscape, + INT cbInput, + LPCSTR lpszInData); + +/* FIXME: this typedef should go somewhere else... */ +typedef VOID (*GOBJENUMPROC)(PVOID, LPARAM); + +INT STDCALL W32kEnumObjects(HDC hDC, + INT ObjectType, + GOBJENUMPROC ObjectFunc, + LPARAM lParam); + +COLORREF STDCALL W32kGetBkColor(HDC hDC); +INT STDCALL W32kGetBkMode(HDC hDC); +BOOL STDCALL W32kGetBrushOrgEx(HDC hDC, LPPOINT brushOrg); +HRGN STDCALL W32kGetClipRgn(HDC hDC); +HGDIOBJ STDCALL W32kGetCurrentObject(HDC hDC, UINT ObjectType); +BOOL STDCALL W32kGetCurrentPositionEx(HDC hDC, LPPOINT currentPosition); +BOOL STDCALL W32kGetDCOrgEx(HDC hDC, LPPOINT Point); +HDC STDCALL W32kGetDCState16(HDC hDC); +INT STDCALL W32kGetDeviceCaps(HDC hDC, INT Index); +INT STDCALL W32kGetMapMode(HDC hDC); +INT STDCALL W32kGetObject(HGDIOBJ hGDIObj, + INT BufSize, + LPVOID Object); +DWORD STDCALL W32kGetObjectType(HGDIOBJ hGDIObj); +INT STDCALL W32kGetPolyFillMode(HDC hDC); +INT STDCALL W32kGetRelAbs(HDC hDC); +INT STDCALL W32kGetROP2(HDC hDC); +HGDIOBJ STDCALL W32kGetStockObject(INT Object); +INT STDCALL W32kGetStretchBltMode(HDC hDC); +COLORREF STDCALL W32kGetTextColor(HDC hDC); +UINT STDCALL W32kGetTextAlign(HDC hDC); +BOOL STDCALL W32kGetViewportExtEx(HDC hDC, LPSIZE viewportExt); +BOOL STDCALL W32kGetViewportOrgEx(HDC hDC, LPPOINT viewportOrg); +BOOL STDCALL W32kGetWindowExtEx(HDC hDC, LPSIZE windowExt); +BOOL STDCALL W32kGetWindowOrgEx(HDC hDC, LPPOINT windowOrg); +HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODEW *InitData); +BOOL STDCALL W32kRestoreDC(HDC hDC, INT SavedDC); +INT STDCALL W32kSaveDC(HDC hDC); +HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj); +INT STDCALL W32kSetBkMode(HDC hDC, INT backgroundMode); +INT STDCALL W32kSetPolyFillMode(HDC hDC, INT polyFillMode); +INT STDCALL W32kSetRelAbs(HDC hDC, INT relAbsMode); +INT STDCALL W32kSetROP2(HDC hDC, INT ROPmode); +INT STDCALL W32kSetStretchBltMode(HDC hDC, INT stretchBltMode); +COLORREF STDCALL W32kSetTextColor(HDC hDC, COLORREF color); + +#endif + diff --git a/include/win32k/debug.h b/include/win32k/debug.h new file mode 100644 index 0000000..a5b5669 --- /dev/null +++ b/include/win32k/debug.h @@ -0,0 +1,12 @@ + +#ifndef H_WIN32K_DEBUG +#define H_WIN32K_DEBUG + +#ifdef CHECKED_BUILD +#define FIXME(S) DbgPrint ("win32k: FIXME at: File:%s line:%d reason:%s", __FILE__, __LINE__, S) +#else +#define FIXME(S) +#endif + +#endif + diff --git a/include/win32k/debug1.h b/include/win32k/debug1.h new file mode 100644 index 0000000..7618cb8 --- /dev/null +++ b/include/win32k/debug1.h @@ -0,0 +1,100 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/debug.h + * PURPOSE: Useful debugging macros + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 28/05/98: Created + */ + +/* + * NOTE: Define NDEBUG before including this header to disable debugging + * macros + */ + +#ifndef __INTERNAL_DEBUG +#define __INTERNAL_DEBUG + +#define UNIMPLEMENTED do {DbgPrint("%s at %s:%d is unimplemented, have a nice day\n",__FUNCTION__,__FILE__,__LINE__); for(;;); } while(0); + +/* FIXME: should probably remove this later */ +#if !defined(CHECKED) && !defined(NDEBUG) +#define CHECKED +#endif + +#ifndef NASSERT +#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); } +#define ASSERT(x) assert(x) +#else +#define assert(x) +#define ASSERT(x) +#endif + +#define DPRINT1(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); ExAllocatePool(NonPagedPool,0); } while(0); +#define CHECKPOINT1 do { DbgPrint("%s:%d\n",__FILE__,__LINE__); ExAllocatePool(NonPagedPool,0); } while(0); + +extern unsigned int old_idt[256][2]; +//extern unsigned int idt; +extern unsigned int old_idt_valid; + +#ifdef __NTOSKRNL__ +//#define DPRINT_CHECKS ExAllocatePool(NonPagedPool,0); assert(old_idt_valid || (!memcmp(old_idt,KiIdt,256*2))); +//#define DPRINT_CHECKS ExAllocatePool(NonPagedPool,0); +#define DPRINT_CHECKS +#else +#define DPRINT_CHECKS +#endif + +#ifndef NDEBUG +#define OLD_DPRINT(fmt,args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(fmt,args); } while(0); +#define DPRINT(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); DPRINT_CHECKS } while(0); +#define CHECKPOINT do { DbgPrint("%s:%d\n",__FILE__,__LINE__); ExAllocatePool(NonPagedPool,0); } while(0); +#else +//#define DPRINT(args...) do { DPRINT_CHECKS } while (0); +#define DPRINT(args...) +#define OLD_DPRINT(args...) +#define CHECKPOINT +#endif /* NDEBUG */ + +/* + * FUNCTION: Assert a maximum value for the current irql + * ARGUMENTS: + * x = Maximum irql + */ +#define ASSERT_IRQL(x) assert(KeGetCurrentIrql()<=(x)) +#define assert_irql(x) assert(KeGetCurrentIrql()<=(x)) + +#define HBP_EXECUTE (0) +#define HBP_WRITE (1) +#define HBP_READWRITE (3) + +#define HBP_BYTE (0) +#define HBP_WORD (1) +#define HBP_DWORD (3) + +/* + * FUNCTION: Sets a hardware breakpoint + * ARGUMENTS: + * i = breakpoint to set (0 to 3) + * addr = linear address to break on + * type = Type of access to break on + * len = length of the variable to watch + * NOTES: + * The variable to watch must be aligned to its length (i.e. a dword + * breakpoint must be aligned to a dword boundary) + * + * A fatal exception will be generated on the access to the variable. + * It is (at the moment) only really useful for catching undefined + * pointers if you know the variable effected but not the buggy + * routine. + * + * FIXME: Extend to call out to kernel debugger on breakpoint + * Add support for I/O breakpoints + * REFERENCES: See the i386 programmer manual for more details + */ +void set_breakpoint(unsigned int i, unsigned int addr, unsigned int type, + unsigned int len); + + +#endif /* __INTERNAL_DEBUG */ diff --git a/include/win32k/driver.h b/include/win32k/driver.h new file mode 100644 index 0000000..ccd4e16 --- /dev/null +++ b/include/win32k/driver.h @@ -0,0 +1,168 @@ + +#ifndef __WIN32K_DRIVER_H +#define __WIN32K_DRIVER_H + +#include + +typedef BOOL STDCALL (*PGD_ENABLEDRIVER)(ULONG, ULONG, PDRVENABLEDATA); +typedef DHPDEV STDCALL (*PGD_ENABLEPDEV)(DEVMODEW *, + LPWSTR, + ULONG, + HSURF *, + ULONG, + ULONG *, + ULONG, + DEVINFO *, + LPWSTR, + LPWSTR, + HANDLE); +typedef VOID STDCALL (*PGD_COMPLETEPDEV)(DHPDEV, HDEV); +typedef VOID STDCALL (*PGD_DISABLEPDEV)(DHPDEV); +typedef HSURF STDCALL (*PGD_ENABLESURFACE)(DHPDEV); +typedef VOID STDCALL (*PGD_DISABLESURFACE)(DHPDEV); +typedef BOOL STDCALL (*PGD_ASSERTMODE)(DHPDEV, BOOL); +typedef BOOL STDCALL (*PGD_RESETPDEV)(DHPDEV, DHPDEV); +typedef HBITMAP STDCALL (*PGD_CREATEDEVICEBITMAP)(DHPDEV, SIZEL, ULONG); +typedef VOID STDCALL (*PGD_DELETEDEVICEBITMAP)(DHSURF); +typedef BOOL STDCALL (*PGD_REALIZEBRUSH)(PBRUSHOBJ, PSURFOBJ, PSURFOBJ, PSURFOBJ, + PXLATEOBJ, ULONG); +typedef ULONG STDCALL (*PGD_DITHERCOLOR)(DHPDEV, ULONG, ULONG, PULONG); +typedef BOOL STDCALL (*PGD_STROKEPATH)(PSURFOBJ, PPATHOBJ, PCLIPOBJ, PXFORMOBJ, + PBRUSHOBJ, PPOINTL, PLINEATTRS, MIX); +typedef BOOL STDCALL (*PGD_FILLPATH)(PSURFOBJ, PPATHOBJ, PCLIPOBJ, PBRUSHOBJ, + PPOINTL, MIX, ULONG); +typedef BOOL STDCALL (*PGD_STROKEANDFILLPATH)(PSURFOBJ, PPATHOBJ, PCLIPOBJ, + PXFORMOBJ, PBRUSHOBJ, PLINEATTRS, + PBRUSHOBJ, PPOINTL, MIX, ULONG); +typedef BOOL STDCALL (*PGD_PAINT)(PSURFOBJ, PCLIPOBJ, PBRUSHOBJ, PPOINTL, MIX); +typedef BOOL STDCALL (*PGD_BITBLT)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PCLIPOBJ, + PXLATEOBJ, PRECTL, PPOINTL, PPOINTL, PBRUSHOBJ, + PPOINTL, ROP4); +typedef BOOL STDCALL (*PGD_TRANSPARENTBLT)(PSURFOBJ, PSURFOBJ, PCLIPOBJ, PXLATEOBJ, PRECTL, PRECTL, ULONG, ULONG); +typedef BOOL STDCALL (*PGD_COPYBITS)(PSURFOBJ, PSURFOBJ, PCLIPOBJ, PXLATEOBJ, + PRECTL, PPOINTL); +typedef BOOL STDCALL (*PGD_STRETCHBLT)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PCLIPOBJ, + PXLATEOBJ, PCOLORADJUSTMENT, PPOINTL, + PRECTL, PRECTL, PPOINTL, ULONG); +typedef BOOL STDCALL (*PGD_SETPALETTE)(DHPDEV, PPALOBJ, ULONG, ULONG, ULONG); +typedef BOOL STDCALL (*PGD_TEXTOUT)(PSURFOBJ, PSTROBJ, PFONTOBJ, PCLIPOBJ, PRECTL, + PRECTL, PBRUSHOBJ, PBRUSHOBJ, PPOINTL, MIX); +typedef ULONG STDCALL (*PGD_ESCAPE)(PSURFOBJ, ULONG, ULONG, PVOID *, ULONG, PVOID *); +typedef ULONG STDCALL (*PGD_DRAWESCAPE)(PSURFOBJ, ULONG, PCLIPOBJ, PRECTL, ULONG, + PVOID *); +typedef PIFIMETRICS STDCALL (*PGD_QUERYFONT)(DHPDEV, ULONG, ULONG, PULONG); +typedef PVOID STDCALL (*PGD_QUERYFONTTREE)(DHPDEV, ULONG, ULONG, ULONG, PULONG); +typedef LONG STDCALL (*PGD_QUERYFONTDATA)(DHPDEV, PFONTOBJ, ULONG, HGLYPH, PGLYPHDATA, + PVOID, ULONG); +typedef ULONG STDCALL (*PGD_SETPOINTERSHAPE)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PXLATEOBJ, + LONG, LONG, LONG, LONG, PRECTL, ULONG); +typedef VOID STDCALL (*PGD_MOVEPOINTER)(PSURFOBJ, LONG, LONG, PRECTL); +typedef BOOL STDCALL (*PGD_LINETO)(PSURFOBJ, PCLIPOBJ, PBRUSHOBJ, LONG, LONG, LONG, + LONG, PRECTL, MIX); +typedef BOOL STDCALL (*PGD_SENDPAGE)(PSURFOBJ); +typedef BOOL STDCALL (*PGD_STARTPAGE)(PSURFOBJ); +typedef BOOL STDCALL (*PGD_ENDDOC)(PSURFOBJ, ULONG); +typedef BOOL STDCALL (*PGD_STARTDOC)(PSURFOBJ, PWSTR, DWORD); +typedef ULONG STDCALL (*PGD_GETGLYPHMODE)(DHPDEV, PFONTOBJ); +typedef VOID STDCALL (*PGD_SYNCHRONIZE)(DHPDEV, PRECTL); +typedef ULONG STDCALL (*PGD_SAVESCREENBITS)(PSURFOBJ, ULONG, ULONG, PRECTL); +typedef ULONG STDCALL (*PGD_GETMODES)(HANDLE, ULONG, PDEVMODEW); +typedef VOID STDCALL (*PGD_FREE)(PVOID, ULONG); +typedef VOID STDCALL (*PGD_DESTROYFONT)(PFONTOBJ); +typedef LONG STDCALL (*PGD_QUERYFONTCAPS)(ULONG, PULONG); +typedef ULONG STDCALL (*PGD_LOADFONTFILE)(ULONG, PVOID, ULONG, ULONG); +typedef BOOL STDCALL (*PGD_UNLOADFONTFILE)(ULONG); +typedef ULONG STDCALL (*PGD_FONTMANAGEMENT)(PSURFOBJ, PFONTOBJ, ULONG, ULONG, PVOID, + ULONG, PVOID); +typedef LONG STDCALL (*PGD_QUERYTRUETYPETABLE)(ULONG, ULONG, ULONG, PTRDIFF, ULONG, + PBYTE); +typedef LONG STDCALL (*PGD_QUERYTRUETYPEOUTLINE)(DHPDEV, PFONTOBJ, HGLYPH, BOOL, + PGLYPHDATA, ULONG, PTTPOLYGONHEADER); +typedef PVOID STDCALL (*PGD_GETTRUETYPEFILE)(ULONG, PULONG); +typedef LONG STDCALL (*PGD_QUERYFONTFILE)(ULONG, ULONG, ULONG, PULONG); +typedef BOOL STDCALL (*PGD_QUERYADVANCEWIDTHS)(DHPDEV, PFONTOBJ, ULONG, HGLYPH *, + PVOID *, ULONG); +typedef BOOL STDCALL (*PGD_SETPIXELFORMAT)(PSURFOBJ, LONG, ULONG); +typedef LONG STDCALL (*PGD_DESCRIBEPIXELFORMAT)(DHPDEV, LONG, ULONG, + PPIXELFORMATDESCRIPTOR); +typedef BOOL STDCALL (*PGD_SWAPBUFFERS)(PSURFOBJ, PWNDOBJ); +typedef BOOL STDCALL (*PGD_STARTBANDING)(PSURFOBJ, PPOINTL); +typedef BOOL STDCALL (*PGD_NEXTBAND)(PSURFOBJ, PPOINTL); +typedef LONG STDCALL (*PGD_QUERYSPOOLTYPE)(DHPDEV, LPWSTR); + + +typedef struct _DRIVER_FUNCTIONS +{ + PGD_ENABLEDRIVER EnableDriver; + PGD_ENABLEPDEV EnablePDev; + PGD_COMPLETEPDEV CompletePDev; + PGD_DISABLEPDEV DisablePDev; + PGD_ENABLESURFACE EnableSurface; + PGD_DISABLESURFACE DisableSurface; + PGD_ASSERTMODE AssertMode; + PGD_RESETPDEV ResetPDev; + PGD_CREATEDEVICEBITMAP CreateDeviceBitmap; + PGD_DELETEDEVICEBITMAP DeleteDeviceBitmap; + PGD_REALIZEBRUSH RealizeBrush; + PGD_DITHERCOLOR DitherColor; + PGD_STROKEPATH StrokePath; + PGD_FILLPATH FillPath; + PGD_STROKEANDFILLPATH StrokeAndFillPath; + PGD_PAINT Paint; + PGD_BITBLT BitBlt; + PGD_TRANSPARENTBLT TransparentBlt; + PGD_COPYBITS CopyBits; + PGD_STRETCHBLT StretchBlt; + PGD_SETPALETTE SetPalette; + PGD_TEXTOUT TextOut; + PGD_ESCAPE Escape; + PGD_DRAWESCAPE DrawEscape; + PGD_QUERYFONT QueryFont; + PGD_QUERYFONTTREE QueryFontTree; + PGD_QUERYFONTDATA QueryFontData; + PGD_SETPOINTERSHAPE SetPointerShape; + PGD_MOVEPOINTER MovePointer; + PGD_LINETO LineTo; + PGD_SENDPAGE SendPage; + PGD_STARTPAGE StartPage; + PGD_ENDDOC EndDoc; + PGD_STARTDOC StartDoc; + PGD_GETGLYPHMODE GetGlyphMode; + PGD_SYNCHRONIZE Synchronize; + PGD_SAVESCREENBITS SaveScreenBits; + PGD_GETMODES GetModes; + PGD_FREE Free; + PGD_DESTROYFONT DestroyFont; + PGD_QUERYFONTCAPS QueryFontCaps; + PGD_LOADFONTFILE LoadFontFile; + PGD_UNLOADFONTFILE UnloadFontFile; + PGD_FONTMANAGEMENT FontManagement; + PGD_QUERYTRUETYPETABLE QueryTrueTypeTable; + PGD_QUERYTRUETYPEOUTLINE QueryTrueTypeOutline; + PGD_GETTRUETYPEFILE GetTrueTypeFile; + PGD_QUERYFONTFILE QueryFontFile; + PGD_QUERYADVANCEWIDTHS QueryAdvanceWidths; + PGD_SETPIXELFORMAT SetPixelFormat; + PGD_DESCRIBEPIXELFORMAT DescribePixelFormat; + PGD_SWAPBUFFERS SwapBuffers; + PGD_STARTBANDING StartBanding; + PGD_NEXTBAND NextBand; +#if 0 + PGD_GETDIRECTDRAWINFO, + PGD_ENABLEDIRECTDRAW, + PGD_DISABLEDIRECTDRAW, +#endif + PGD_QUERYSPOOLTYPE QuerySpoolType; +} DRIVER_FUNCTIONS, *PDRIVER_FUNCTIONS; + +BOOL DRIVER_RegisterDriver(LPCWSTR Name, PGD_ENABLEDRIVER EnableDriver); +PGD_ENABLEDRIVER DRIVER_FindDDIDriver(LPCWSTR Name); +HANDLE DRIVER_FindMPDriver(LPCWSTR Name); +BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED, + PDRIVER_FUNCTIONS DF); +BOOL DRIVER_UnregisterDriver(LPCWSTR Name); +INT DRIVER_ReferenceDriver (LPCWSTR Name); +INT DRIVER_UnreferenceDriver (LPCWSTR Name); + +#endif + diff --git a/include/win32k/fillshap.h b/include/win32k/fillshap.h new file mode 100644 index 0000000..aa02437 --- /dev/null +++ b/include/win32k/fillshap.h @@ -0,0 +1,68 @@ +#ifndef __WIN32K_FILLSHAP_H +#define __WIN32K_FILLSHAP_H + +BOOL +STDCALL +W32kChord(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XRadial1, + int YRadial1, + int XRadial2, + int YRadial2); + +BOOL +STDCALL +W32kEllipse(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect); + +BOOL +STDCALL +W32kPie(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XRadial1, + int YRadial1, + int XRadial2, + int YRadial2); + +BOOL +STDCALL +W32kPolygon(HDC hDC, + CONST PPOINT Points, + int Count); + +BOOL +STDCALL +W32kPolyPolygon(HDC hDC, + CONST LPPOINT Points, + CONST LPINT PolyCounts, + int Count); + +BOOL +STDCALL +W32kRectangle(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect); + +BOOL +STDCALL +W32kRoundRect(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int Width, + int Height); + +#endif + diff --git a/include/win32k/float.h b/include/win32k/float.h new file mode 100644 index 0000000..16094d6 --- /dev/null +++ b/include/win32k/float.h @@ -0,0 +1,102 @@ +#ifndef __WIN32K_FLOAT_H +#define __WIN32K_FLOAT_H + +#include +#include +#include + +typedef struct tagFLOAT_POINT +{ + FLOAT x, y; +} FLOAT_POINT; + +/* Rounds a floating point number to integer. The world-to-viewport + * transformation process is done in floating point internally. This function + * is then used to round these coordinates to integer values. + */ +static inline INT GDI_ROUND(FLOAT val) +{ + return (int)floor(val + 0.5); +} + +/* Performs a world-to-viewport transformation on the specified point (which + * is in floating point format). + */ +static inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point) +{ + FLOAT x, y; + + /* Perform the transformation */ + x = point->x; + y = point->y; + point->x = x * dc->w.xformWorld2Vport.eM11 + + y * dc->w.xformWorld2Vport.eM21 + + dc->w.xformWorld2Vport.eDx; + point->y = x * dc->w.xformWorld2Vport.eM12 + + y * dc->w.xformWorld2Vport.eM22 + + dc->w.xformWorld2Vport.eDy; +} + +/* Performs a viewport-to-world transformation on the specified point (which + * is in integer format). Returns TRUE if successful, else FALSE. + */ +#if 0 +static inline BOOL INTERNAL_DPTOLP(DC *dc, LPPOINT point) +{ + FLOAT_POINT floatPoint; + + /* Perform operation with floating point */ + floatPoint.x=(FLOAT)point->x; + floatPoint.y=(FLOAT)point->y; + if (!INTERNAL_DPTOLP_FLOAT(dc, &floatPoint)) + return FALSE; + + /* Round to integers */ + point->x = GDI_ROUND(floatPoint.x); + point->y = GDI_ROUND(floatPoint.y); + + return TRUE; +} + +/* Performs a world-to-viewport transformation on the specified point (which + * is in integer format). + */ +static inline void INTERNAL_LPTODP(DC *dc, LPPOINT point) +{ + FLOAT_POINT floatPoint; + + /* Perform operation with floating point */ + floatPoint.x=(FLOAT)point->x; + floatPoint.y=(FLOAT)point->y; + INTERNAL_LPTODP_FLOAT(dc, &floatPoint); + + /* Round to integers */ + point->x = GDI_ROUND(floatPoint.x); + point->y = GDI_ROUND(floatPoint.y); +} + +#endif + +#define MulDiv( x, y, z ) EngMulDiv( x, y, z ) + +#define XDPTOLP(dc,x) \ + (MulDiv(((x)-(dc)->vportOrgX), (dc)->wndExtX, (dc)->vportExtX) + (dc)->wndOrgX) +#define YDPTOLP(dc,y) \ + (MulDiv(((y)-(dc)->vportOrgY), (dc)->wndExtY, (dc)->vportExtY) + (dc)->wndOrgY) +#define XLPTODP(dc,x) \ + (MulDiv(((x)-(dc)->wndOrgX), (dc)->vportExtX, (dc)->wndExtX) + (dc)->vportOrgX) +#define YLPTODP(dc,y) \ + (MulDiv(((y)-(dc)->wndOrgY), (dc)->vportExtY, (dc)->wndExtY) + (dc)->vportOrgY) + + /* Device <-> logical size conversion */ + +#define XDSTOLS(dc,x) \ + MulDiv((x), (dc)->wndExtX, (dc)->vportExtX) +#define YDSTOLS(dc,y) \ + MulDiv((y), (dc)->wndExtY, (dc)->vportExtY) +#define XLSTODS(dc,x) \ + MulDiv((x), (dc)->vportExtX, (dc)->wndExtX) +#define YLSTODS(dc,y) \ + MulDiv((y), (dc)->vportExtY, (dc)->wndExtY) + +#endif diff --git a/include/win32k/gdiobj.h b/include/win32k/gdiobj.h new file mode 100644 index 0000000..1b5fbbd --- /dev/null +++ b/include/win32k/gdiobj.h @@ -0,0 +1,91 @@ +/* + * GDI object common header definition + * + * (RJJ) taken from WINE + */ + +#ifndef __WIN32K_GDIOBJ_H +#define __WIN32K_GDIOBJ_H + +#include + + /* GDI objects magic numbers */ +#define GO_PEN_MAGIC 0x4f47 +#define GO_BRUSH_MAGIC 0x4f48 +#define GO_FONT_MAGIC 0x4f49 +#define GO_PALETTE_MAGIC 0x4f4a +#define GO_BITMAP_MAGIC 0x4f4b +#define GO_REGION_MAGIC 0x4f4c +#define GO_DC_MAGIC 0x4f4d +#define GO_DISABLED_DC_MAGIC 0x4f4e +#define GO_META_DC_MAGIC 0x4f4f +#define GO_METAFILE_MAGIC 0x4f50 +#define GO_METAFILE_DC_MAGIC 0x4f51 +#define GO_ENHMETAFILE_MAGIC 0x4f52 +#define GO_ENHMETAFILE_DC_MAGIC 0x4f53 +#define GO_DCE_MAGIC 0x4f54 +#define GO_MAGIC_DONTCARE 0xffff + +/* (RJJ) swiped stock handles from wine */ + /* First handle possible for stock objects (must be >= GDI_HEAP_SIZE) */ +#define FIRST_STOCK_HANDLE 0xffffff00 + + /* Stock objects handles */ +#define NB_STOCK_OBJECTS (DEFAULT_GUI_FONT + 1) +#define STOCK_WHITE_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+WHITE_BRUSH)) +#define STOCK_LTGRAY_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+LTGRAY_BRUSH)) +#define STOCK_GRAY_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+GRAY_BRUSH)) +#define STOCK_DKGRAY_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+DKGRAY_BRUSH)) +#define STOCK_BLACK_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+BLACK_BRUSH)) +#define STOCK_NULL_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+NULL_BRUSH)) +#define STOCK_HOLLOW_BRUSH ((HBRUSH)(FIRST_STOCK_HANDLE+HOLLOW_BRUSH)) +#define STOCK_WHITE_PEN ((HPEN)(FIRST_STOCK_HANDLE+WHITE_PEN)) +#define STOCK_BLACK_PEN ((HPEN)(FIRST_STOCK_HANDLE+BLACK_PEN)) +#define STOCK_NULL_PEN ((HPEN)(FIRST_STOCK_HANDLE+NULL_PEN)) +#define STOCK_OEM_FIXED_FONT ((HFONT)(FIRST_STOCK_HANDLE+OEM_FIXED_FONT)) +#define STOCK_ANSI_FIXED_FONT ((HFONT)(FIRST_STOCK_HANDLE+ANSI_FIXED_FONT)) +#define STOCK_ANSI_VAR_FONT ((HFONT)(FIRST_STOCK_HANDLE+ANSI_VAR_FONT)) +#define STOCK_SYSTEM_FONT ((HFONT)(FIRST_STOCK_HANDLE+SYSTEM_FONT)) +#define STOCK_DEVICE_DEFAULT_FONT ((HFONT)(FIRST_STOCK_HANDLE+DEVICE_DEFAULT_FONT)) +#define STOCK_DEFAULT_PALETTE ((HPALETTE)(FIRST_STOCK_HANDLE+DEFAULT_PALETTE)) +#define STOCK_SYSTEM_FIXED_FONT ((HFONT)(FIRST_STOCK_HANDLE+SYSTEM_FIXED_FONT)) +#define STOCK_DEFAULT_GUI_FONT ((HFONT)(FIRST_STOCK_HANDLE+DEFAULT_GUI_FONT)) +#define FIRST_STOCK_FONT STOCK_OEM_FIXED_FONT +#define LAST_STOCK_FONT STOCK_DEFAULT_GUI_FONT +#define LAST_STOCK_HANDLE ((DWORD)STOCK_DEFAULT_GUI_FONT) + +typedef struct _GDIOBJHDR +{ + WORD wTableIndex; + DWORD dwCount; //reference count. +} GDIOBJHDR, *PGDIOBJHDR; + +typedef PVOID PGDIOBJ; + +typedef struct _GDI_HANDLE_ENTRY +{ + WORD wMagic; + HANDLE hProcessId; + PGDIOBJ pObject; +} GDI_HANDLE_ENTRY, *PGDI_HANDLE_ENTRY; + +typedef struct _GDI_HANDLE_TABLE +{ + WORD wTableSize; + GDI_HANDLE_ENTRY Handles [1]; +} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE; + +HGDIOBJ GDIOBJ_AllocObj(WORD Size, WORD Magic); +BOOL GDIOBJ_FreeObj (HGDIOBJ Obj, WORD Magic, DWORD Flag); +PGDIOBJ GDIOBJ_LockObj (HGDIOBJ Obj, WORD Magic); +BOOL GDIOBJ_UnlockObj (HGDIOBJ Obj, WORD Magic); +WORD GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle); +VOID STDCALL W32kDumpGdiObjects( INT Process ); +BOOL STDCALL W32kCleanupForProcess( INT Process ); + +#define GDIOBJFLAG_DEFAULT (0x0) +#define GDIOBJFLAG_IGNOREPID (0x1) +#define GDIOBJFLAG_IGNORELOCK (0x2) + +#endif + diff --git a/include/win32k/icm.h b/include/win32k/icm.h new file mode 100644 index 0000000..a975b7e --- /dev/null +++ b/include/win32k/icm.h @@ -0,0 +1,81 @@ + +#ifndef __WIN32K_ICM_H +#define __WIN32K_ICM_H + +BOOL +STDCALL +W32kCheckColorsInGamut(HDC hDC, + LPVOID RGBTriples, + LPVOID Buffer, + UINT Count); + +BOOL +STDCALL +W32kColorMatchToTarget(HDC hDC, + HDC hDCTarget, + DWORD Action); + +HCOLORSPACE +STDCALL +W32kCreateColorSpace(LPLOGCOLORSPACE LogColorSpace); + +BOOL +STDCALL +W32kDeleteColorSpace(HCOLORSPACE hColorSpace); + +INT +STDCALL +W32kEnumICMProfiles(HDC hDC, + ICMENUMPROC EnumICMProfilesFunc, + LPARAM lParam); + +HCOLORSPACE +STDCALL +W32kGetColorSpace(HDC hDC); + +BOOL +STDCALL +W32kGetDeviceGammaRamp(HDC hDC, + LPVOID Ramp); + +BOOL +STDCALL +W32kGetICMProfile(HDC hDC, + LPDWORD NameSize, + LPWSTR Filename); + +BOOL +STDCALL +W32kGetLogColorSpace(HCOLORSPACE hColorSpace, + LPLOGCOLORSPACE Buffer, + DWORD Size); + +HCOLORSPACE +STDCALL +W32kSetColorSpace(HDC hDC, + HCOLORSPACE hColorSpace); + +BOOL +STDCALL +W32kSetDeviceGammaRamp(HDC hDC, + LPVOID Ramp); + +INT +STDCALL +W32kSetICMMode(HDC hDC, + INT EnableICM); + +BOOL +STDCALL +W32kSetICMProfile(HDC hDC, + LPWSTR Filename); + +BOOL +STDCALL +W32kUpdateICMRegKey(DWORD Reserved, + LPWSTR CMID, + LPWSTR Filename, + UINT Command); + +#endif + diff --git a/include/win32k/kapi.h b/include/win32k/kapi.h new file mode 100644 index 0000000..6f07515 --- /dev/null +++ b/include/win32k/kapi.h @@ -0,0 +1,23 @@ +#ifndef _WIN32K_KAPI_H +#define _WIN32K_KAPI_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* ndef _WIN32K_KAPI_H */ diff --git a/include/win32k/line.h b/include/win32k/line.h new file mode 100644 index 0000000..5e893d7 --- /dev/null +++ b/include/win32k/line.h @@ -0,0 +1,97 @@ +#ifndef __WIN32K_LINE_H +#define __WIN32K_LINE_H + +BOOL +STDCALL +W32kAngleArc(HDC hDC, + int X, + int Y, + DWORD Radius, + FLOAT StartAngle, + FLOAT SweepAngle); + +BOOL +STDCALL +W32kArc(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XStartArc, + int YStartArc, + int XEndArc, + int YEndArc); + +BOOL +STDCALL +W32kArcTo(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XRadial1, + int YRadial1, + int XRadial2, + int YRadial2); + +INT +STDCALL +W32kGetArcDirection(HDC hDC); + +BOOL +STDCALL +W32kLineTo(HDC hDC, + int XEnd, + int YEnd); + +BOOL +STDCALL +W32kMoveToEx(HDC hDC, + int X, + int Y, + LPPOINT Point); + +BOOL +STDCALL +W32kPolyBezier(HDC hDC, + CONST LPPOINT pt, + DWORD Count); + +BOOL +STDCALL +W32kPolyBezierTo(HDC hDC, + CONST LPPOINT pt, + DWORD Count); + +BOOL +STDCALL +W32kPolyDraw(HDC hDC, + CONST LPPOINT pt, + CONST LPBYTE Types, + int Count); + +BOOL +STDCALL +W32kPolyline(HDC hDC, + CONST LPPOINT pt, + int Count); + +BOOL +STDCALL +W32kPolylineTo(HDC hDC, + CONST LPPOINT pt, + DWORD Count); + +BOOL +STDCALL +W32kPolyPolyline(HDC hDC, + CONST LPPOINT pt, + CONST LPDWORD PolyPoints, + DWORD Count); + +int +STDCALL +W32kSetArcDirection(HDC hDC, + int ArcDirection); + +#endif diff --git a/include/win32k/math.h b/include/win32k/math.h new file mode 100644 index 0000000..fcb0e32 --- /dev/null +++ b/include/win32k/math.h @@ -0,0 +1,163 @@ +/* + * math.h + * + * Mathematical functions. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ +// added modfl + +#ifndef _MATH_H_ +#define _MATH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * HUGE_VAL is returned by strtod when the value would overflow the + * representation of 'double'. There are other uses as well. + * + * __imp__HUGE is a pointer to the actual variable _HUGE in + * MSVCRT.DLL. If we used _HUGE directly we would get a pointer + * to a thunk function. + * + * NOTE: The CRTDLL version uses _HUGE_dll instead. + */ +#if __MSVCRT__ +extern double* __imp__HUGE; +#define HUGE_VAL (*__imp__HUGE) +#else +/* CRTDLL */ +extern double* _HUGE_dll; +#define HUGE_VAL (*_HUGE_dll) +#endif + +#define M_PI 22 / 7 +#define M_PI_2 M_PI * 2 + +struct _exception +{ + int type; + char *name; + double arg1; + double arg2; + double retval; +}; + +/* + * Types for the above _exception structure. + */ + +#define _DOMAIN 1 /* domain error in argument */ +#define _SING 2 /* singularity */ +#define _OVERFLOW 3 /* range overflow */ +#define _UNDERFLOW 4 /* range underflow */ +#define _TLOSS 5 /* total loss of precision */ +#define _PLOSS 6 /* partial loss of precision */ + +/* + * Exception types with non-ANSI names for compatibility. + */ + +#ifndef __STRICT_ANSI__ +#ifndef _NO_OLDNAMES + +#define DOMAIN _DOMAIN +#define SING _SING +#define OVERFLOW _OVERFLOW +#define UNDERFLOW _UNDERFLOW +#define TLOSS _TLOSS +#define PLOSS _PLOSS + +#endif /* Not _NO_OLDNAMES */ +#endif /* Not __STRICT_ANSI__ */ + + +double sin (double x); +double cos (double x); +double tan (double x); +double sinh (double x); +double cosh (double x); +double tanh (double x); +double asin (double x); +double acos (double x); +double atan (double x); +double atan2 (double y, double x); +double exp (double x); +double log (double x); +double log10 (double x); +double pow (double x, double y); +long double powl (long double x,long double y); +double sqrt (double x); +double ceil (double x); +double floor (double x); +double fabs (double x); +double ldexp (double x, int n); +double frexp (double x, int* exp); +double modf (double x, double* ip); +long double modfl (long double x,long double* ip); +double fmod (double x, double y); + + +#ifndef __STRICT_ANSI__ + +/* Complex number (for cabs) */ +struct _complex +{ + double x; /* Real part */ + double y; /* Imaginary part */ +}; + +double _cabs (struct _complex x); +double _hypot (double x, double y); +double _j0 (double x); +double _j1 (double x); +double _jn (int n, double x); +double _y0 (double x); +double _y1 (double x); +double _yn (int n, double x); + +#ifndef _NO_OLDNAMES + +/* + * Non-underscored versions of non-ANSI functions. These reside in + * liboldnames.a. Provided for extra portability. + */ +double cabs (struct _complex x); +double hypot (double x, double y); +double j0 (double x); +double j1 (double x); +double jn (int n, double x); +double y0 (double x); +double y1 (double x); +double yn (int n, double x); + +#endif /* Not _NO_OLDNAMES */ + +#endif /* Not __STRICT_ANSI__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* Not _MATH_H_ */ + diff --git a/include/win32k/metafile.h b/include/win32k/metafile.h new file mode 100644 index 0000000..53cf60c --- /dev/null +++ b/include/win32k/metafile.h @@ -0,0 +1,180 @@ +#ifndef __WIN32K_METAFILE_H +#define __WIN32K_METAFILE_H + +HENHMETAFILE +STDCALL +W32kCloseEnhMetaFile ( + HDC hDC + ); +HMETAFILE +STDCALL +W32kCloseMetaFile ( + HDC hDC + ); +HENHMETAFILE +STDCALL +W32kCopyEnhMetaFile ( + HENHMETAFILE Src, + LPCWSTR File + ); +HMETAFILE +STDCALL +W32kCopyMetaFile ( + HMETAFILE Src, + LPCWSTR File + ); +HDC +STDCALL +W32kCreateEnhMetaFile ( + HDC hDCRef, + LPCWSTR File, + CONST LPRECT Rect, + LPCWSTR Description + ); +HDC +STDCALL +W32kCreateMetaFile ( + LPCWSTR File + ); +BOOL +STDCALL +W32kDeleteEnhMetaFile ( + HENHMETAFILE emf + ); +BOOL +STDCALL +W32kDeleteMetaFile ( + HMETAFILE mf + ); +BOOL +STDCALL +W32kEnumEnhMetaFile ( + HDC hDC, + HENHMETAFILE emf, + ENHMFENUMPROC EnhMetaFunc, + LPVOID Data, + CONST LPRECT Rect + ); +BOOL +STDCALL +W32kEnumMetaFile ( + HDC hDC, + HMETAFILE mf, + MFENUMPROC MetaFunc, + LPARAM lParam + ); +BOOL +STDCALL +W32kGdiComment ( + HDC hDC, + UINT Size, + CONST LPBYTE Data + ); +HENHMETAFILE +STDCALL +W32kGetEnhMetaFile ( + LPCWSTR MetaFile + ); +UINT +STDCALL +W32kGetEnhMetaFileBits ( + HENHMETAFILE hemf, + UINT BufSize, + LPBYTE Buffer + ); +UINT +STDCALL +W32kGetEnhMetaFileDescription ( + HENHMETAFILE hemf, + UINT BufSize, + LPWSTR Description + ); +UINT +STDCALL +W32kGetEnhMetaFileHeader ( + HENHMETAFILE hemf, + UINT BufSize, + LPENHMETAHEADER emh + ); +UINT +STDCALL +W32kGetEnhMetaFilePaletteEntries ( + HENHMETAFILE hemf, + UINT Entries, + LPPALETTEENTRY pe + ); +HMETAFILE +STDCALL +W32kGetMetaFile ( + LPCWSTR MetaFile + ); +UINT +STDCALL +W32kGetMetaFileBitsEx ( + HMETAFILE hmf, + UINT Size, + LPVOID Data + ); +UINT +STDCALL +W32kGetWinMetaFileBits ( + HENHMETAFILE hemf, + UINT BufSize, + LPBYTE Buffer, + INT MapMode, + HDC Ref + ); +BOOL +STDCALL +W32kPlayEnhMetaFile ( + HDC hDC, + HENHMETAFILE hemf, + CONST PRECT Rect + ); +BOOL +STDCALL +W32kPlayEnhMetaFileRecord ( + HDC hDC, + LPHANDLETABLE Handletable, + CONST ENHMETARECORD * EnhMetaRecord, + UINT Handles + ); +BOOL +STDCALL +W32kPlayMetaFile ( + HDC hDC, + HMETAFILE hmf + ); +BOOL +STDCALL +W32kPlayMetaFileRecord ( + HDC hDC, + LPHANDLETABLE Handletable, + LPMETARECORD MetaRecord, + UINT Handles + ); +HENHMETAFILE +STDCALL +W32kSetEnhMetaFileBits ( + UINT BufSize, + CONST PBYTE Data + ); +HMETAFILE +STDCALL +W32kSetMetaFileBitsEx ( + UINT Size, + CONST PBYTE Data + ); +#if 0 +HENHMETAFILE +STDCALL +W32kSetWinMetaFileBits ( + UINT BufSize, + CONST PBYTE Buffer, + HDC Ref, + CONST METAFILEPICT * mfp + ); +#endif + +#endif + diff --git a/include/win32k/misc.h b/include/win32k/misc.h new file mode 100644 index 0000000..93945f6 --- /dev/null +++ b/include/win32k/misc.h @@ -0,0 +1,8 @@ +#ifndef __WIN32K_MISC_H +#define __WIN32K_MISC_H + +BOOLEAN +STDCALL +W32kInitialize (VOID); + +#endif /* __WIN32K_MISC_H */ diff --git a/include/win32k/ntuser.h b/include/win32k/ntuser.h new file mode 100644 index 0000000..b38fdae --- /dev/null +++ b/include/win32k/ntuser.h @@ -0,0 +1,1732 @@ +#ifndef __WIN32K_NTUSER_H +#define __WIN32K_NTUSER_H + +ULONG STDCALL +NtUserGetSystemMetrics(ULONG Index); +DWORD STDCALL +NtUserGetClassLong(HWND hWnd, DWORD Offset); +DWORD STDCALL +NtUserGetWindowLong(HWND hWnd, DWORD Index); +INT STDCALL +NtUserReleaseDC(HWND hWnd, HDC hDc); +BOOL STDCALL +NtUserGetWindowRect(HWND hWnd, LPRECT Rect); +HANDLE STDCALL +NtUserGetProp(HWND hWnd, ATOM Atom); +BOOL STDCALL +NtUserGetClientOrigin(HWND hWnd, LPPOINT Point); + +NTSTATUS +STDCALL +NtUserAcquireOrReleaseInputOwnership( + BOOLEAN Release); + +DWORD +STDCALL +NtUserActivateKeyboardLayout( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserAlterWindowStyle( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserAttachThreadInput( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +HDC STDCALL +NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs); + +DWORD +STDCALL +NtUserBitBltSysBmp( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7); + +DWORD +STDCALL +NtUserBlockInput( + DWORD Unknown0); + +DWORD +STDCALL +NtUserBuildHwndList( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6); + +DWORD +STDCALL +NtUserBuildNameList( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserBuildPropList( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserCallHwnd( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCallHwndLock( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCallHwndOpt( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCallHwndParam( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserCallHwndParamLock( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserCallMsgFilter( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCallNextHookEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserCallNoParam( + DWORD Unknown0); + +DWORD +STDCALL +NtUserCallOneParam( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCallTwoParam( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserChangeClipboardChain( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserChangeDisplaySettings( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +DWORD +STDCALL +NtUserCheckMenuItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD STDCALL +NtUserChildWindowFromPointEx(HWND Parent, + LONG x, + LONG y, + UINT Flags); + +DWORD +STDCALL +NtUserClipCursor( + DWORD Unknown0); + +DWORD +STDCALL +NtUserCloseClipboard(VOID); + +BOOL +STDCALL +NtUserCloseDesktop( + HDESK hDesktop); + +BOOL +STDCALL +NtUserCloseWindowStation( + HWINSTA hWinSta); + +DWORD +STDCALL +NtUserConvertMemHandle( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCopyAcceleratorTable( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserCountClipboardFormats(VOID); + +DWORD +STDCALL +NtUserCreateAcceleratorTable( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserCreateCaret( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +HDESK +STDCALL +NtUserCreateDesktop( + PUNICODE_STRING lpszDesktopName, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpSecurity, + HWINSTA hWindowStation); + +DWORD +STDCALL +NtUserCreateLocalMemHandle( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +HWND +STDCALL +NtUserCreateWindowEx( + DWORD dwExStyle, + PUNICODE_STRING lpClassName, + PUNICODE_STRING lpWindowName, + DWORD dwStyle, + LONG x, + LONG y, + LONG nWidth, + LONG nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam, + DWORD Unknown12); + +HWINSTA +STDCALL +NtUserCreateWindowStation( + PUNICODE_STRING lpszWindowStationName, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpSecurity, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserDdeGetQualityOfService( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserDdeInitialize( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +DWORD +STDCALL +NtUserDdeSetQualityOfService( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD STDCALL +NtUserDeferWindowPos(HDWP WinPosInfo, + HWND Wnd, + HWND WndInsertAfter, + LONG x, + LONG y, + LONG cx, + LONG cy, + UINT Flags); +DWORD +STDCALL +NtUserDefSetText( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserDeleteMenu( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserDestroyAcceleratorTable( + DWORD Unknown0); + +DWORD +STDCALL +NtUserDestroyCursor( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserDestroyMenu( + DWORD Unknown0); + +BOOLEAN STDCALL +NtUserDestroyWindow(HWND Wnd); + +LRESULT +STDCALL +NtUserDispatchMessage(CONST MSG* lpmsg); + +DWORD +STDCALL +NtUserDragDetect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserDragObject( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +DWORD +STDCALL +NtUserDrawAnimatedRects( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserDrawCaption( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserDrawCaptionTemp( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6); + +DWORD +STDCALL +NtUserDrawIconEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10); + +DWORD +STDCALL +NtUserDrawMenuBarTemp( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +DWORD +STDCALL +NtUserEmptyClipboard(VOID); + +DWORD +STDCALL +NtUserEnableMenuItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserEnableScrollBar( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserEndDeferWindowPosEx( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserEndMenu(VOID); + +BOOL STDCALL +NtUserEndPaint(HWND hWnd, CONST PAINTSTRUCT* lPs); + +DWORD +STDCALL +NtUserEnumDisplayDevices( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserEnumDisplayMonitors( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserEnumDisplaySettings( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserEvent( + DWORD Unknown0); + +DWORD +STDCALL +NtUserExcludeUpdateRgn( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserFillWindow( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserFindExistingCursorIcon( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +HWND +STDCALL +NtUserFindWindowEx( + HWND hwndParent, + HWND hwndChildAfter, + PUNICODE_STRING ucClassName, + PUNICODE_STRING ucWindowName, + DWORD Unknown4); + +DWORD +STDCALL +NtUserFlashWindowEx( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetAltTabInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +HWND STDCALL +NtUserGetAncestor(HWND hWnd, UINT Flags); + + +DWORD +STDCALL +NtUserGetAsyncKeyState( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetCaretBlinkTime(VOID); + +DWORD +STDCALL +NtUserGetCaretPos( + DWORD Unknown0); + +DWORD STDCALL +NtUserGetClassInfo(IN LPWSTR ClassName, + IN ULONG InfoClass, + OUT PVOID Info, + IN ULONG InfoLength, + OUT PULONG ReturnedLength); + +DWORD +STDCALL +NtUserGetClassName( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetClipboardData( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetClipboardFormatName( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetClipboardOwner(VOID); + +DWORD +STDCALL +NtUserGetClipboardSequenceNumber(VOID); + +DWORD +STDCALL +NtUserGetClipboardViewer(VOID); + +DWORD +STDCALL +NtUserGetClipCursor( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetComboBoxInfo( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetControlBrush( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetControlColor( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserGetCPD( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetCursorFrameInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserGetCursorInfo( + DWORD Unknown0); + +HDC STDCALL +NtUserGetDC(HWND hWnd); + +HDC STDCALL NtUserGetDCEx(HWND hWnd, HANDLE hRegion, ULONG Flags); + +DWORD +STDCALL +NtUserGetDoubleClickTime(VOID); + +DWORD +STDCALL +NtUserGetForegroundWindow(VOID); + +DWORD +STDCALL +NtUserGetGuiResources( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetGUIThreadInfo( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetIconInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserGetIconSize( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserGetImeHotKey( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserGetInternalWindowPos( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetKeyboardLayoutList( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetKeyboardLayoutName( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetKeyboardState( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetKeyNameText( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetKeyState( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetListBoxInfo( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetMenuBarInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserGetMenuIndex( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetMenuItemRect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +BOOL +STDCALL +NtUserGetMessage( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax); + +DWORD +STDCALL +NtUserGetMouseMovePointsEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +BOOL +STDCALL +NtUserGetObjectInformation( + HANDLE hObject, + DWORD nIndex, + PVOID pvInformation, + DWORD nLength, + PDWORD nLengthNeeded); + +DWORD +STDCALL +NtUserGetOpenClipboardWindow(VOID); + +DWORD +STDCALL +NtUserGetPriorityClipboardFormat( + DWORD Unknown0, + DWORD Unknown1); + +HWINSTA +STDCALL +NtUserGetProcessWindowStation(VOID); + +DWORD +STDCALL +NtUserGetScrollBarInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetSystemMenu( + DWORD Unknown0, + DWORD Unknown1); + +HDESK +STDCALL +NtUserGetThreadDesktop( + DWORD dwThreadId, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetThreadState( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetTitleBarInfo( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetUpdateRect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetUpdateRgn( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserGetWindowDC( + DWORD Unknown0); + +DWORD +STDCALL +NtUserGetWindowPlacement( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserGetWOWClass( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserHideCaret( + DWORD Unknown0); + +DWORD +STDCALL +NtUserHiliteMenuItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserImpersonateDdeClientWindow( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserInitializeClientPfnArrays( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserInitTask( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10); + +DWORD +STDCALL +NtUserInternalGetWindowText( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserInvalidateRect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserInvalidateRgn( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserIsClipboardFormatAvailable( + DWORD Unknown0); + +DWORD +STDCALL +NtUserKillTimer( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserLoadKeyboardLayoutEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +BOOL +STDCALL +NtUserLockWindowStation( + HWINSTA hWindowStation); + +DWORD +STDCALL +NtUserLockWindowUpdate( + DWORD Unknown0); + +DWORD +STDCALL +NtUserLockWorkStation(VOID); + +DWORD +STDCALL +NtUserMapVirtualKeyEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserMenuItemFromPoint( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserMessageCall( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6); + +DWORD +STDCALL +NtUserMinMaximize( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserMNDragLeave(VOID); + +DWORD +STDCALL +NtUserMNDragOver( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserModifyUserStartupInfoFlags( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserMoveWindow( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserNotifyIMEStatus( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserNotifyWinEvent( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserOpenClipboard( + DWORD Unknown0, + DWORD Unknown1); + +HDESK +STDCALL +NtUserOpenDesktop( + PUNICODE_STRING lpszDesktopName, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess); + +HDESK +STDCALL +NtUserOpenInputDesktop( + DWORD dwFlags, + BOOL fInherit, + ACCESS_MASK dwDesiredAccess); + +HWINSTA +STDCALL +NtUserOpenWindowStation( + PUNICODE_STRING lpszWindowStationName, + ACCESS_MASK dwDesiredAccess); + +BOOL +STDCALL +NtUserPaintDesktop( + HDC hDC); + +BOOL +STDCALL +NtUserPeekMessage( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax, + UINT wRemoveMsg); + +BOOL +STDCALL +NtUserPostMessage( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +BOOL +STDCALL +NtUserPostThreadMessage( + DWORD idThread, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +DWORD +STDCALL +NtUserQuerySendMessage( + DWORD Unknown0); + +DWORD +STDCALL +NtUserQueryUserCounters( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +DWORD +STDCALL +NtUserQueryWindow( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserRealChildWindowFromPoint( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserRedrawWindow( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +RTL_ATOM +STDCALL +NtUserRegisterClassExWOW( + LPWNDCLASSEX lpwcx, + BOOL bUnicodeClass, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserRegisterHotKey( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserRegisterTasklist( + DWORD Unknown0); + +UINT STDCALL +NtUserRegisterWindowMessage(LPCWSTR MessageName); + +DWORD +STDCALL +NtUserRemoveMenu( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +HANDLE STDCALL +NtUserRemoveProp(HWND hWnd, ATOM Atom); + +DWORD +STDCALL +NtUserResolveDesktopForWOW( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSBGetParms( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserScrollDC( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6); + +DWORD +STDCALL +NtUserScrollWindowEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7); + +DWORD +STDCALL +NtUserSendInput( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +LRESULT STDCALL +NtUserSendMessage(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +BOOL +STDCALL +NtUserSendMessageCallback( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC lpCallBack, + ULONG_PTR dwData); + +BOOL +STDCALL +NtUserSendNotifyMessage( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam); + +DWORD +STDCALL +NtUserSetActiveWindow( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetCapture( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetClassLong( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetClassWord( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetClipboardData( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetClipboardViewer( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetConsoleReserveKeys( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetCursor( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetCursorContents( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetCursorIconData( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetDbgTag( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetFocus( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetImeHotKey( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4); + +DWORD +STDCALL +NtUserSetImeOwnerWindow( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetInternalWindowPos( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetKeyboardState( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetLayeredWindowAttributes( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetLogonNotifyWindow( + DWORD Unknown0); + +DWORD +STDCALL +NtUserSetMenu( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetMenuContextHelpId( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetMenuDefaultItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetMenuFlagRtoL( + DWORD Unknown0); + +BOOL +STDCALL +NtUserSetObjectInformation( + HANDLE hObject, + DWORD nIndex, + PVOID pvInformation, + DWORD nLength); + +DWORD +STDCALL +NtUserSetParent( + DWORD Unknown0, + DWORD Unknown1); + +BOOL +STDCALL +NtUserSetProcessWindowStation( + HWINSTA hWindowStation); + +BOOL STDCALL +NtUserSetProp(HWND hWnd, ATOM Atom, HANDLE Data); + +DWORD +STDCALL +NtUserSetRipFlags( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetScrollInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetShellWindowEx( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetSysColors( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetSystemCursor( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetSystemMenu( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetSystemTimer( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +BOOL +STDCALL +NtUserSetThreadDesktop( + HDESK hDesktop); + +DWORD +STDCALL +NtUserSetThreadState( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetTimer( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetWindowFNID( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetWindowLong( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetWindowPlacement( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserSetWindowPos( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6); + +DWORD +STDCALL +NtUserSetWindowRgn( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetWindowsHookAW( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetWindowsHookEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserSetWindowStationUser( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserSetWindowWord( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserSetWinEventHook( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7); + +DWORD +STDCALL +NtUserShowCaret( + DWORD Unknown0); + +DWORD +STDCALL +NtUserShowScrollBar( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +BOOL +STDCALL +NtUserShowWindow( + HWND hWnd, + LONG nCmdShow); + +DWORD +STDCALL +NtUserShowWindowAsync( + DWORD Unknown0, + DWORD Unknown1); + +BOOL +STDCALL +NtUserSwitchDesktop( + HDESK hDesktop); + +DWORD +STDCALL +NtUserSystemParametersInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3); + +DWORD +STDCALL +NtUserThunkedMenuInfo( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserThunkedMenuItemInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserToUnicodeEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6); + +DWORD +STDCALL +NtUserTrackMouseEvent( + DWORD Unknown0); + +DWORD +STDCALL +NtUserTrackPopupMenuEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserTranslateAccelerator( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +BOOL +STDCALL +NtUserTranslateMessage( + LPMSG lpMsg, + DWORD Unknown1); + +DWORD +STDCALL +NtUserUnhookWindowsHookEx( + DWORD Unknown0); + +DWORD +STDCALL +NtUserUnhookWinEvent( + DWORD Unknown0); + +DWORD +STDCALL +NtUserUnloadKeyboardLayout( + DWORD Unknown0); + +BOOL +STDCALL +NtUserUnlockWindowStation( + HWINSTA hWindowStation); + +DWORD +STDCALL +NtUserUnregisterClass( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserUnregisterHotKey( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserUpdateInputContext( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserUpdateInstance( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserUpdateLayeredWindow( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8); + +DWORD +STDCALL +NtUserUpdatePerUserSystemParameters( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserUserHandleGrantAccess( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserValidateHandleSecure( + DWORD Unknown0); + +DWORD +STDCALL +NtUserValidateRect( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserVkKeyScanEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserWaitForInputIdle( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2); + +DWORD +STDCALL +NtUserWaitForMsgAndEvent( + DWORD Unknown0); + +BOOL +STDCALL +NtUserWaitMessage(VOID); + +DWORD +STDCALL +NtUserWin32PoolAllocationStats( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5); + +DWORD +STDCALL +NtUserWindowFromPoint( + DWORD Unknown0, + DWORD Unknown1); + +DWORD +STDCALL +NtUserYieldTask(VOID); + +#endif /* __WIN32K_NTUSER_H */ + +/* EOF */ diff --git a/include/win32k/paint.h b/include/win32k/paint.h new file mode 100644 index 0000000..d8fae7a --- /dev/null +++ b/include/win32k/paint.h @@ -0,0 +1,12 @@ +#ifndef __WIN32K_PAINT_H +#define __WIN32K_PAINT_H + +BOOL STDCALL W32kGdiFlush (VOID); +DWORD STDCALL W32kGdiGetBatchLimit (VOID); +DWORD STDCALL W32kGdiSetBatchLimit (DWORD Limit); +UINT STDCALL W32kGetBoundsRect (HDC hDC, LPRECT Bounds, UINT Flags); +COLORREF STDCALL W32kSetBkColor (HDC hDC, COLORREF Color); +UINT STDCALL W32kSetBoundsRect (HDC hDC, CONST PRECT Bounds, UINT Flags); + +#endif + diff --git a/include/win32k/path.h b/include/win32k/path.h new file mode 100644 index 0000000..a461bb7 --- /dev/null +++ b/include/win32k/path.h @@ -0,0 +1,54 @@ +#ifndef __WIN32K_PATH_H +#define __WIN32K_PATH_H + +typedef enum tagGdiPathState +{ + PATH_Null, + PATH_Open, + PATH_Closed +} GdiPathState; + +typedef struct tagGdiPath +{ + GdiPathState state; + POINT *pPoints; + BYTE *pFlags; + int numEntriesUsed, numEntriesAllocated; + BOOL newStroke; +} GdiPath; + +#define PATH_IsPathOpen(path) ((path).state==PATH_Open) + +BOOL STDCALL W32kAbortPath(HDC hDC); + +BOOL STDCALL W32kBeginPath(HDC hDC); + +BOOL STDCALL W32kCloseFigure(HDC hDC); + +BOOL STDCALL W32kEndPath(HDC hDC); + +BOOL STDCALL W32kFillPath(HDC hDC); + +BOOL STDCALL W32kFlattenPath(HDC hDC); + +BOOL STDCALL W32kGetMiterLimit(HDC hDC, + PFLOAT Limit); + +INT STDCALL W32kGetPath(HDC hDC, + LPPOINT Points, + LPBYTE Types, + INT nSize); + +HRGN STDCALL W32kPathToRegion(HDC hDC); + +BOOL STDCALL W32kSetMiterLimit(HDC hDC, + FLOAT NewLimit, + PFLOAT OldLimit); + +BOOL STDCALL W32kStrokeAndFillPath(HDC hDC); + +BOOL STDCALL W32kStrokePath(HDC hDC); + +BOOL STDCALL W32kWidenPath(HDC hDC); + +#endif diff --git a/include/win32k/pen.h b/include/win32k/pen.h new file mode 100644 index 0000000..0c317e6 --- /dev/null +++ b/include/win32k/pen.h @@ -0,0 +1,40 @@ + +#ifndef __WIN32K_PEN_H +#define __WIN32K_PEN_H + +#include + +/* GDI logical pen object */ +typedef struct +{ + LOGPEN logpen; +} PENOBJ, *PPENOBJ; + +/* Internal interface */ + +#define PENOBJ_AllocPen() \ + ((HPEN) GDIOBJ_AllocObj (sizeof (PENOBJ), GO_PEN_MAGIC)) +#define PENOBJ_FreePen(hBMObj) GDIOBJ_FreeObj((HGDIOBJ) hBMObj, GO_PEN_MAGIC, GDIOBJFLAG_DEFAULT) +/* +#define PENOBJ_HandleToPtr(hBMObj) \ + ((PPENOBJ) GDIOBJ_HandleToPtr ((HGDIOBJ) hBMObj, GO_PEN_MAGIC)) +#define PENOBJ_PtrToHandle(hBMObj) \ + ((HPEN) GDIOBJ_PtrToHandle ((PGDIOBJ) hBMObj, GO_PEN_MAGIC)) +*/ +#define PENOBJ_LockPen(hBMObj) ((PPENOBJ)GDIOBJ_LockObj ((HGDIOBJ) hBMObj, GO_PEN_MAGIC)) +#define PENOBJ_UnlockPen(hBMObj) GDIOBJ_UnlockObj ((HGDIOBJ) hBMObj, GO_PEN_MAGIC) + +HPEN STDCALL W32kCreatePen(INT PenStyle, + INT Width, + COLORREF Color); + +HPEN STDCALL W32kCreatePenIndirect(CONST PLOGPEN lgpn); + +HPEN STDCALL W32kExtCreatePen(DWORD PenStyle, + DWORD Width, + CONST PLOGBRUSH lb, + DWORD StyleCount, + CONST PDWORD Style); + +#endif + diff --git a/include/win32k/print.h b/include/win32k/print.h new file mode 100644 index 0000000..52342d9 --- /dev/null +++ b/include/win32k/print.h @@ -0,0 +1,48 @@ + +#ifndef __WIN32K_PRINT_H +#define __WIN32K_PRINT_H + +INT +STDCALL +W32kAbortDoc(HDC hDC); + +INT +STDCALL +W32kEndDoc(HDC hDC); + +INT +STDCALL +W32kEndPage(HDC hDC); + +INT +STDCALL +W32kEscape(HDC hDC, + INT Escape, + INT InSize, + LPCSTR InData, + LPVOID OutData); + +INT +STDCALL +W32kExtEscape(HDC hDC, + INT Escape, + INT InSize, + LPCSTR InData, + INT OutSize, + LPSTR OutData); + +INT +STDCALL +W32kSetAbortProc(HDC hDC, + ABORTPROC AbortProc); + +INT +STDCALL +W32kStartDoc(HDC hDC, + CONST PDOCINFO di); + +INT +STDCALL +W32kStartPage(HDC hDC); + +#endif diff --git a/include/win32k/region.h b/include/win32k/region.h new file mode 100644 index 0000000..6650718 --- /dev/null +++ b/include/win32k/region.h @@ -0,0 +1,153 @@ + +#ifndef __WIN32K_REGION_H +#define __WIN32K_REGION_H + +#include + +//Internal region data. Can't use RGNDATA structure because buffer is allocated statically +typedef struct _ROSRGNDATA { + RGNDATAHEADER rdh; + char* Buffer; +} ROSRGNDATA, *PROSRGNDATA, *LPROSRGNDATA; + + +#define RGNDATA_FreeRgn(hRgn) GDIOBJ_FreeObj((HGDIOBJ)hRgn, GO_REGION_MAGIC, GDIOBJFLAG_DEFAULT) +#define RGNDATA_LockRgn(hRgn) ((PROSRGNDATA)GDIOBJ_LockObj((HGDIOBJ)hRgn, GO_REGION_MAGIC)) +#define RGNDATA_UnlockRgn(hRgn) GDIOBJ_UnlockObj((HGDIOBJ)hRgn, GO_REGION_MAGIC) +HRGN RGNDATA_AllocRgn(INT n); + +BOOL RGNDATA_InternalDelete( PROSRGNDATA Obj ); + +/* User entry points */ +HRGN STDCALL +W32kUnionRectWithRgn(HRGN hDest, const RECT* Rect); + +INT +STDCALL +W32kCombineRgn(HRGN hDest, + HRGN hSrc1, + HRGN hSrc2, + INT CombineMode); + +HRGN +STDCALL +W32kCreateEllipticRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect); + +HRGN +STDCALL +W32kCreateEllipticRgnIndirect(CONST PRECT rc); + +HRGN +STDCALL +W32kCreatePolygonRgn(CONST PPOINT pt, + INT Count, + INT PolyFillMode); + +HRGN +STDCALL +W32kCreatePolyPolygonRgn(CONST PPOINT pt, + CONST PINT PolyCounts, + INT Count, + INT PolyFillMode); + +HRGN +STDCALL +W32kCreateRectRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect); + +HRGN +STDCALL +W32kCreateRectRgnIndirect(CONST PRECT rc); + +HRGN +STDCALL +W32kCreateRoundRectRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect, + INT WidthEllipse, + INT HeightEllipse); + +BOOL +STDCALL +W32kEqualRgn(HRGN hSrcRgn1, + HRGN hSrcRgn2); + +HRGN +STDCALL +W32kExtCreateRegion(CONST PXFORM Xform, + DWORD Count, + CONST PROSRGNDATA RgnData); + +BOOL +STDCALL +W32kFillRgn(HDC hDC, + HRGN hRgn, + HBRUSH hBrush); + +BOOL +STDCALL +W32kFrameRgn(HDC hDC, + HRGN hRgn, + HBRUSH hBrush, + INT Width, + INT Height); + +INT +STDCALL +W32kGetRgnBox(HRGN hRgn, + LPRECT Rect); + +BOOL +STDCALL +W32kInvertRgn(HDC hDC, + HRGN hRgn); + +INT +STDCALL +W32kOffsetRgn(HRGN hRgn, + INT XOffset, + INT YOffset); + +BOOL +STDCALL +W32kPaintRgn(HDC hDC, + HRGN hRgn); + +BOOL +STDCALL +W32kPtInRegion(HRGN hRgn, + INT X, + INT Y); + +BOOL +STDCALL +W32kRectInRegion(HRGN hRgn, + CONST LPRECT rc); + +BOOL +STDCALL +W32kSetRectRgn(HRGN hRgn, + INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect); + +DWORD +STDCALL +W32kGetRegionData(HRGN hrgn, + DWORD count, + LPRGNDATA rgndata); +HRGN REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpPt); +HRGN STDCALL +UnsafeW32kCreateRectRgnIndirect(CONST PRECT rc); +INT STDCALL +UnsafeW32kGetRgnBox(HRGN hRgn, + LPRECT pRect); +#endif + diff --git a/include/win32k/text.h b/include/win32k/text.h new file mode 100644 index 0000000..fc1be70 --- /dev/null +++ b/include/win32k/text.h @@ -0,0 +1,261 @@ + +#ifndef __WIN32K_TEXT_H +#define __WIN32K_TEXT_H + +/* GDI logical font object */ +typedef struct +{ + LOGFONT logfont; +} TEXTOBJ, *PTEXTOBJ; + +/* Internal interface */ + +#define TEXTOBJ_AllocText() \ + ((HFONT) GDIOBJ_AllocObj (sizeof (TEXTOBJ), GO_FONT_MAGIC)) +#define TEXTOBJ_FreeText(hBMObj) GDIOBJ_FreeObj((HGDIOBJ) hBMObj, GO_FONT_MAGIC, GDIOBJFLAG_DEFAULT) +/* +#define TEXTOBJ_HandleToPtr(hBMObj) \ + ((PTEXTOBJ) GDIOBJ_HandleToPtr ((HGDIOBJ) hBMObj, GO_FONT_MAGIC)) +#define TEXTOBJ_PtrToHandle(hBMObj) \ + ((HFONT) GDIOBJ_PtrToHandle ((PGDIOBJ) hBMObj, GO_FONT_MAGIC)) +*/ +#define TEXTOBJ_LockText(hBMObj) ((PTEXTOBJ) GDIOBJ_LockObj ((HGDIOBJ) hBMObj, GO_FONT_MAGIC)) +#define TEXTOBJ_UnlockText(hBMObj) GDIOBJ_UnlockObj ((HGDIOBJ) hBMObj, GO_FONT_MAGIC) + +int +STDCALL +W32kAddFontResource(LPCWSTR Filename); + +HFONT +STDCALL +W32kCreateFont(int Height, + int Width, + int Escapement, + int Orientation, + int Weight, + DWORD Italic, + DWORD Underline, + DWORD StrikeOut, + DWORD CharSet, + DWORD OutputPrecision, + DWORD ClipPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCWSTR Face); + +HFONT +STDCALL +W32kCreateFontIndirect(CONST LPLOGFONT lf); + +BOOL +STDCALL +W32kCreateScalableFontResource(DWORD Hidden, + LPCWSTR FontRes, + LPCWSTR FontFile, + LPCWSTR CurrentPath); + +int +STDCALL +W32kEnumFontFamilies(HDC hDC, + LPCWSTR Family, + FONTENUMPROC EnumFontFamProc, + LPARAM lParam); + +int +STDCALL +W32kEnumFontFamiliesEx(HDC hDC, + LPLOGFONT Logfont, + FONTENUMPROC EnumFontFamExProc, + LPARAM lParam, + DWORD Flags); + +int +STDCALL +W32kEnumFonts(HDC hDC, + LPCWSTR FaceName, + FONTENUMPROC FontFunc, + LPARAM lParam); + +BOOL +STDCALL +W32kExtTextOut(HDC hDC, + int X, + int Y, + UINT Options, + CONST LPRECT rc, + LPCWSTR String, + UINT Count, + CONST LPINT Dx); + +BOOL +STDCALL +W32kGetAspectRatioFilterEx(HDC hDC, + LPSIZE AspectRatio); + +BOOL +STDCALL +W32kGetCharABCWidths(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPABC abc); + +BOOL +STDCALL +W32kGetCharABCWidthsFloat(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPABCFLOAT abcF); + +DWORD +STDCALL +W32kGetCharacterPlacement(HDC hDC, + LPCWSTR String, + int Count, + int MaxExtent, + LPGCP_RESULTS Results, + DWORD Flags); + +BOOL +STDCALL +W32kGetCharWidth(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPINT Buffer); + +BOOL +STDCALL +W32kGetCharWidth32(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPINT Buffer); + +BOOL +STDCALL +W32kGetCharWidthFloat(HDC hDC, + UINT FirstChar, + UINT LastChar, + PFLOAT Buffer); + +DWORD +STDCALL +W32kGetFontLanguageInfo(HDC hDC); + +DWORD +STDCALL +W32kGetGlyphOutline(HDC hDC, + UINT Char, + UINT Format, + LPGLYPHMETRICS gm, + DWORD Bufsize, + LPVOID Buffer, + CONST LPMAT2 mat2); + +DWORD +STDCALL +W32kGetKerningPairs(HDC hDC, + DWORD NumPairs, + LPKERNINGPAIR krnpair); + +UINT +STDCALL +W32kGetOutlineTextMetrics(HDC hDC, + UINT Data, + LPOUTLINETEXTMETRIC otm); + +BOOL +STDCALL +W32kGetRasterizerCaps(LPRASTERIZER_STATUS rs, + UINT Size); + +UINT +STDCALL +W32kGetTextCharset(HDC hDC); + +UINT +STDCALL +W32kGetTextCharsetInfo(HDC hDC, + LPFONTSIGNATURE Sig, + DWORD Flags); + +BOOL +STDCALL +W32kGetTextExtentExPoint(HDC hDC, + LPCWSTR String, + int Count, + int MaxExtent, + LPINT Fit, + LPINT Dx, + LPSIZE Size); + +BOOL +STDCALL +W32kGetTextExtentPoint(HDC hDC, + LPCWSTR String, + int Count, + LPSIZE Size); + +BOOL +STDCALL +W32kGetTextExtentPoint32(HDC hDC, + LPCWSTR String, + int Count, + LPSIZE Size); + +int +STDCALL +W32kGetTextFace(HDC hDC, + int Count, + LPWSTR FaceName); + +BOOL +STDCALL +W32kGetTextMetrics(HDC hDC, + LPTEXTMETRIC tm); + +BOOL +STDCALL +W32kPolyTextOut(HDC hDC, + CONST LPPOLYTEXT txt, + int Count); + +BOOL +STDCALL +W32kRemoveFontResource(LPCWSTR FileName); + +DWORD +STDCALL +W32kSetMapperFlags(HDC hDC, + DWORD Flag); + +UINT +STDCALL +W32kSetTextAlign(HDC hDC, + UINT Mode); + +COLORREF +STDCALL +W32kSetTextColor(HDC hDC, + COLORREF Color); + +BOOL +STDCALL +W32kSetTextJustification(HDC hDC, + int BreakExtra, + int BreakCount); + +BOOL +STDCALL +W32kTextOut(HDC hDC, + int XStart, + int YStart, + LPCWSTR String, + int Count); + +UINT +STDCALL +W32kTranslateCharsetInfo(PDWORD Src, + LPCHARSETINFO CSI, + DWORD Flags); + +#endif + diff --git a/include/win32k/userobj.h b/include/win32k/userobj.h new file mode 100644 index 0000000..6168d69 --- /dev/null +++ b/include/win32k/userobj.h @@ -0,0 +1,46 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: USER Object manager interface definition + * FILE: include/win32k/userobj.h + * PROGRAMER: Rex Jolliff (rex@lvcablemodem.com) + * + */ + +#ifndef __WIN32K_USEROBJ_H +#define __WIN32K_USEROBJ_H + +#include + +#define UO_CLASS_MAGIC 0x5141 +#define UO_WINDOW_MAGIC 0x5142 +#define UO_MAGIC_DONTCARE 0xffff + +#define USER_OBJECT_TAG (ULONG)(('W'<<0) + ('3'<<8) + ('2'<<16) + ('U'<<24)) + +typedef struct tag_USER_OBJECT_HEADER +{ + WORD magic; + DWORD referenceCount; + LIST_ENTRY listEntry; + FAST_MUTEX mutex; +} USER_OBJECT_HEADER, *PUSER_OBJECT_HEADER; + +typedef PVOID PUSER_OBJECT; +typedef HANDLE HUSEROBJ; + +#define UserObjectHeaderToBody(header) ((PUSER_OBJECT)(((PCHAR)header)+sizeof(USER_OBJECT_HEADER))) +#define UserObjectBodyToHeader(body) ((PUSER_OBJECT_HEADER)(((PCHAR)body)-sizeof(USER_OBJECT_HEADER))) +#define UserObjectHeaderToHandle(header) ((HUSEROBJ)header) +#define UserObjectHandleToHeader(handle) ((HUSEROBJ)handle) + +PUSER_OBJECT USEROBJ_AllocObject (WORD size, WORD magic); +BOOL USEROBJ_FreeObject (PUSER_OBJECT object, WORD magic); +HUSEROBJ USEROBJ_PtrToHandle (PUSER_OBJECT object, WORD magic); +PUSER_OBJECT USEROBJ_HandleToPtr (HUSEROBJ object, WORD magic); +BOOL USEROBJ_LockObject (HUSEROBJ Obj); +BOOL USEROBJ_UnlockObject (HUSEROBJ Obj); + +#endif + diff --git a/include/win32k/win32k.h b/include/win32k/win32k.h new file mode 100644 index 0000000..89a8210 --- /dev/null +++ b/include/win32k/win32k.h @@ -0,0 +1 @@ +#include diff --git a/include/win32k/wingl.h b/include/win32k/wingl.h new file mode 100644 index 0000000..b7a0e8b --- /dev/null +++ b/include/win32k/wingl.h @@ -0,0 +1,38 @@ + +#ifndef __WIN32K_WINGL_H +#define __WIN32K_WINGL_H + +INT +STDCALL +W32kChoosePixelFormat(HDC hDC, + CONST PPIXELFORMATDESCRIPTOR pfd); + +INT +STDCALL +W32kDescribePixelFormat(HDC hDC, + INT PixelFormat, + UINT BufSize, + PPIXELFORMATDESCRIPTOR pfd); + +UINT +STDCALL +W32kGetEnhMetaFilePixelFormat(HENHMETAFILE hEMF, + DWORD BufSize, + CONST PPIXELFORMATDESCRIPTOR pfd); + +INT +STDCALL +W32kGetPixelFormat(HDC hDC); + +BOOL +STDCALL +W32kSetPixelFormat(HDC hDC, + INT PixelFormat, + CONST PPIXELFORMATDESCRIPTOR pfd); + +BOOL +STDCALL +W32kSwapBuffers(HDC hDC); + +#endif + diff --git a/include/windows.h b/include/windows.h new file mode 100644 index 0000000..8e62678 --- /dev/null +++ b/include/windows.h @@ -0,0 +1,165 @@ +/* + windows.h + + Include this file if you wish to use the Windows32 API Library + + Copyright (C) 1996 Free Software Foundation + + Author: Scott Christley + Date: 1996 + + This file is part of the Windows32 API Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + If you are interested in a warranty or support for this source code, + contact Scott Christley for more information. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _GNU_H_WINDOWS_H +#define _GNU_H_WINDOWS_H + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX max +#endif +#ifndef MIN +#define MIN min +#endif + +#ifndef RC_INVOKED +#include +#include +#endif + +/* Base definitions */ +#include + +/* WIN32 messages */ +#ifndef WIN32_LEAN_AND_MEAN +#include +#endif + +/* WIN32 definitions */ +#include + +#ifndef RC_INVOKED + +/* WIN32 structures */ +#include + +/* WIN32 functions */ +#ifndef WIN32_LEAN_AND_MEAN +#include +#endif + +/* WIN32 PE file format */ +#include + +#endif /* ! defined (RC_INVOKED) */ + +/* WIN32 error codes */ +#ifndef WIN32_LEAN_AND_MEAN +#include +#endif + +#ifndef RC_INVOKED + +/* Windows sockets specification version 1.1 */ +#ifdef Win32_Winsock +#ifndef WIN32_LEAN_AND_MEAN +#include +#endif +#endif + +/* There is a conflict with BOOL between Objective-C and Win32, + so the Windows32 API Library defines and uses WINBOOL. + However, if we are not using Objective-C then define the normal + windows BOOL so Win32 programs compile normally. If you are + using Objective-C then you must use WINBOOL for Win32 operations. +*/ +#ifndef __OBJC__ +//typedef WINBOOL BOOL; +#endif /* !__OBJC__ */ + +/* How do we get the VM page size on NT? */ +#ifndef vm_page_size +#define vm_page_size 4096 +#endif + +#endif /* ! defined (RC_INVOKED) */ + +#ifdef __GNUC__ +#ifndef NONAMELESSUNION +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +#define _ANONYMOUS_UNION __extension__ +#define _ANONYMOUS_STRUCT __extension__ +#else +#if defined(__cplusplus) +#define _ANONYMOUS_UNION __extension__ +#endif +#endif /* __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) */ +#endif /* NONAMELESSUNION */ +#endif /* __GNUC__ */ + +#ifndef _ANONYMOUS_UNION +#define _ANONYMOUS_UNION +#define _UNION_NAME(x) x +#define DUMMYUNIONNAME u +#define DUMMYUNIONNAME2 u2 +#define DUMMYUNIONNAME3 u3 +#define DUMMYUNIONNAME4 u4 +#define DUMMYUNIONNAME5 u5 +#define DUMMYUNIONNAME6 u6 +#define DUMMYUNIONNAME7 u7 +#define DUMMYUNIONNAME8 u8 +#else +#define _UNION_NAME(x) +#define DUMMYUNIONNAME +#define DUMMYUNIONNAME2 +#define DUMMYUNIONNAME3 +#define DUMMYUNIONNAME4 +#define DUMMYUNIONNAME5 +#define DUMMYUNIONNAME6 +#define DUMMYUNIONNAME7 +#define DUMMYUNIONNAME8 +#endif +#ifndef _ANONYMOUS_STRUCT +#define _ANONYMOUS_STRUCT +#define _STRUCT_NAME(x) x +#define DUMMYSTRUCTNAME s +#define DUMMYSTRUCTNAME2 s2 +#define DUMMYSTRUCTNAME3 s3 +#else +#define _STRUCT_NAME(x) +#define DUMMYSTRUCTNAME +#define DUMMYSTRUCTNAME2 +#define DUMMYSTRUCTNAME3 +#endif + +#ifndef NO_STRICT +#ifndef STRICT +#define STRICT 1 +#endif +#endif + +#endif /* _GNU_H_WINDOWS_H */ diff --git a/include/wine/config.h b/include/wine/config.h new file mode 100644 index 0000000..564b3b0 --- /dev/null +++ b/include/wine/config.h @@ -0,0 +1,710 @@ +/* include/config.h. Generated by configure. */ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +#define __WINE_CONFIG_H + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to the name of the function returning errno for reentrant libc */ +/* #undef ERRNO_LOCATION */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +/* #undef HAVE_ALLOCA_H */ + +/* Define if you have ALSA including devel headers */ +/* #undef HAVE_ALSA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_NAMESER_H */ + +/* Define if you have ARTS sound server */ +/* #undef HAVE_ARTS */ + +/* Define to use .string instead of .ascii */ +#define HAVE_ASM_STRING 1 + +/* Define to 1 if you have the `chsize' function. */ +#define HAVE_CHSIZE 1 + +/* Define to 1 if you have the `clone' function. */ +/* #undef HAVE_CLONE */ + +/* Define to 1 if you have the `connect' function. */ +/* #undef HAVE_CONNECT */ + +/* Define if we have linux/input.h AND it contains the INPUT event API */ +/* #undef HAVE_CORRECT_LINUXINPUT_H */ + +/* Define if we have CUPS */ +/* #undef HAVE_CUPS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CURSES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DIRECT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define if you have dlopen */ +/* #undef HAVE_DLOPEN */ + +/* Define to 1 if you have the `ecvt' function. */ +#define HAVE_ECVT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ELF_H */ + +/* Define to 1 if you have the `finite' function. */ +/* #undef HAVE_FINITE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef HAVE_FPCLASS */ + +/* Define if FreeType 2 is installed */ +/* #undef HAVE_FREETYPE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_FREETYPE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_FTGLYPH_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_FTNAMES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_FTOUTLN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_FTSNAMES_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_FREETYPE_FTTRIGON_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_INTERNAL_SFNT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_TTNAMEID_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FREETYPE_TTTABLES_H */ + +/* Define to 1 if you have the `ftruncate' function. */ +/* #undef HAVE_FTRUNCATE */ + +/* Define to 1 if you have the `ftruncate64' function. */ +/* #undef HAVE_FTRUNCATE64 */ + +/* Define to 1 if you have the `getbkgd' function. */ +/* #undef HAVE_GETBKGD */ + +/* Define to 1 if you have the `gethostbyname' function. */ +/* #undef HAVE_GETHOSTBYNAME */ + +/* Define to 1 if you have the `getnetbyaddr' function. */ +/* #undef HAVE_GETNETBYADDR */ + +/* Define to 1 if you have the `getnetbyname' function. */ +/* #undef HAVE_GETNETBYNAME */ + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +/* #undef HAVE_GETPROTOBYNAME */ + +/* Define to 1 if you have the `getprotobynumber' function. */ +/* #undef HAVE_GETPROTOBYNUMBER */ + +/* Define to 1 if you have the `getpwuid' function. */ +/* #undef HAVE_GETPWUID */ + +/* Define to 1 if you have the `getservbyport' function. */ +/* #undef HAVE_GETSERVBYPORT */ + +/* Define to 1 if you have the `getsockopt' function. */ +/* #undef HAVE_GETSOCKOPT */ + +/* Define if the OpenGL headers define extension typedefs */ +/* #undef HAVE_GLEXT_PROTOTYPES */ + +/* Define if the OpenGL library supports the glXGetProcAddressARB call */ +/* #undef HAVE_GLX_GETPROCADDRESS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GL_GLEXT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GL_GLX_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GL_GL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define to 1 if you have the `inet_aton' function. */ +/* #undef HAVE_INET_ATON */ + +/* Define to 1 if you have the `inet_network' function. */ +/* #undef HAVE_INET_NETWORK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_INTTYPES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if IPX should use netipx/ipx.h from libc */ +/* #undef HAVE_IPX_GNU */ + +/* Define if IPX includes are taken from Linux kernel */ +/* #undef HAVE_IPX_LINUX */ + +/* Define to 1 if you have the `iswalnum' function. */ +#define HAVE_ISWALNUM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_JPEGLIB_H */ + +/* Define if you have the curses library (-lcurses) */ +/* #undef HAVE_LIBCURSES */ + +/* Define to 1 if you have the `i386' library (-li386). */ +/* #undef HAVE_LIBI386 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBIO_H */ + +/* Define if you have libjpeg including devel headers */ +/* #undef HAVE_LIBJPEG */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `mmap' library (-lmmap). */ +/* #undef HAVE_LIBMMAP */ + +/* Define if you have the ncurses library (-lncurses) */ +/* #undef HAVE_LIBNCURSES */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `ossaudio' library (-lossaudio). */ +/* #undef HAVE_LIBOSSAUDIO */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define to 1 if you have the `w' library (-lw). */ +/* #undef HAVE_LIBW */ + +/* Define to 1 if you have the `xpg4' library (-lxpg4). */ +/* #undef HAVE_LIBXPG4 */ + +/* Define if you have the X Shape extension */ +/* #undef HAVE_LIBXSHAPE */ + +/* Define if you have the Xxf86dga library version 1 */ +/* #undef HAVE_LIBXXF86DGA */ + +/* Define if you have the Xxf86dga library version 2 */ +/* #undef HAVE_LIBXXF86DGA2 */ + +/* Define if you have the Xxf86vm library */ +/* #undef HAVE_LIBXXF86VM */ + +/* Define if you have the X Shm extension */ +/* #undef HAVE_LIBXXSHM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINK_H */ + +/* Define if defines the Linux 2.2 joystick API */ +/* #undef HAVE_LINUX_22_JOYSTICK_API */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_CDROM_H */ + +/* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */ +/* #undef HAVE_LINUX_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_HDREG_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_INPUT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_JOYSTICK_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_MAJOR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_PARAM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_SERIAL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LINUX_UCDROM_H */ + +/* Define to 1 if you have the `lseek64' function. */ +/* #undef HAVE_LSEEK64 */ + +/* Define to 1 if you have the `lstat' function. */ +/* #undef HAVE_LSTAT */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +/* #undef HAVE_MMAP */ + +/* Define to 1 if the system has the type `mode_t'. */ +#define HAVE_MODE_T 1 + +/* Define if struct msghdr contains msg_accrights */ +/* #undef HAVE_MSGHDR_ACCRIGHTS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NCURSES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_SYSTM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NET_IF_H */ + +/* Define to 1 if the system has the type `off_t'. */ +#define HAVE_OFF_T 1 + +/* Define if OpenGL is present on the system */ +/* #undef HAVE_OPENGL */ + +/* Define if you have the Open Sound system */ +/* #undef HAVE_OSS */ + +/* Define if you have the Open Sound system (MIDI interface) */ +/* #undef HAVE_OSS_MIDI */ + +/* Define to 1 if you have the `pclose' function. */ +#define HAVE_PCLOSE 1 + +/* Define to 1 if the system has the type `pid_t'. */ +#define HAVE_PID_T 1 + +/* Define to 1 if you have the `popen' function. */ +#define HAVE_POPEN 1 + +/* Define if we can use ppdev.h for parallel port access */ +/* #undef HAVE_PPDEV */ + +/* Define to 1 if you have the `pread' function. */ +/* #undef HAVE_PREAD */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PTY_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `pwrite' function. */ +/* #undef HAVE_PWRITE */ + +/* Define to 1 if you have the `resizeterm' function. */ +/* #undef HAVE_RESIZETERM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RESOLV_H */ + +/* Define to 1 if you have the `rfork' function. */ +/* #undef HAVE_RFORK */ + +/* Define if we have SANE development environment */ +/* #undef HAVE_SANE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SCHED_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SCSI_SG_H */ + +/* Define to 1 if you have the `select' function. */ +/* #undef HAVE_SELECT */ + +/* Define to 1 if you have the `sendmsg' function. */ +/* #undef HAVE_SENDMSG */ + +/* Define to 1 if you have the `settimeofday' function. */ +/* #undef HAVE_SETTIMEOFDAY */ + +/* Define to 1 if you have the `sigaltstack' function. */ +/* #undef HAVE_SIGALTSTACK */ + +/* Define to 1 if the system has the type `size_t'. */ +#define HAVE_SIZE_T 1 + +/* Define to 1 if you have the `snprintf' function. */ +/* #undef HAVE_SNPRINTF */ + +/* Define if struct sockaddr contains sa_len */ +/* #undef HAVE_SOCKADDR_SA_LEN */ + +/* Define if struct sockaddr_un contains sun_len */ +/* #undef HAVE_SOCKADDR_SUN_LEN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SOUNDCARD_H */ + +/* Define to 1 if the system has the type `ssize_t'. */ +/* #undef HAVE_SSIZE_T */ + +/* Define to 1 if you have the `statfs' function. */ +/* #undef HAVE_STATFS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strncasecmp' function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYSCALL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ASOUNDLIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_CDIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_ERRNO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_INTTYPES_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_IPC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_LINK_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_LWP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MODEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MOUNT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MSG_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_PARAM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_PTRACE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_REG_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SHM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SIGNAL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOUNDCARD_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STATFS_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_STRTIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SYSCALL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SYSCTL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_USER_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_V86INTR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_V86_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_VFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_VM86_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* Define to 1 if you have the `tcgetattr' function. */ +/* #undef HAVE_TCGETATTR */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if you have the `timegm' function. */ +/* #undef HAVE_TIMEGM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UCONTEXT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `usleep' function. */ +/* #undef HAVE_USLEEP */ + +/* Define to 1 if you have the `vfscanf' function. */ +/* #undef HAVE_VFSCANF */ + +/* Define to 1 if you have the `wait4' function. */ +/* #undef HAVE_WAIT4 */ + +/* Define to 1 if you have the `waitpid' function. */ +/* #undef HAVE_WAITPID */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_EXTENSIONS_SHAPE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_EXTENSIONS_XF86DGA_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_EXTENSIONS_XF86VMODE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_EXTENSIONS_XRENDER_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_EXTENSIONS_XSHM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_EXTENSIONS_XVLIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_XKBLIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X11_XLIB_H */ + +/* Define if you have the XKB extension */ +/* #undef HAVE_XKB */ + +/* Define if the X libraries support XVideo */ +/* #undef HAVE_XVIDEO */ + +/* Define to 1 if you have the `_lwp_create' function. */ +/* #undef HAVE__LWP_CREATE */ + +/* Define to 1 if you have the `_pclose' function. */ +#define HAVE__PCLOSE 1 + +/* Define to 1 if you have the `_popen' function. */ +#define HAVE__POPEN 1 + +/* Define to 1 if you have the `_snprintf' function. */ +#define HAVE__SNPRINTF 1 + +/* Define to 1 if you have the `_stricmp' function. */ +#define HAVE__STRICMP 1 + +/* Define to 1 if you have the `_strnicmp' function. */ +#define HAVE__STRNICMP 1 + +/* Define to 1 if you have the `__libc_fork' function. */ +/* #undef HAVE___LIBC_FORK */ + +/* Define if stdcall symbols need to be decorated */ +#define NEED_STDCALL_DECORATION 1 + +/* Define if .type asm directive must be inside a .def directive */ +#define NEED_TYPE_IN_DEF 1 + +/* Define if symbols declared in assembly code need an underscore prefix */ +#define NEED_UNDERSCORE_PREFIX 1 + +/* Define to disable all debug messages. */ +/* #undef NO_DEBUG_MSGS */ + +/* Define to disable trace messages. */ +/* #undef NO_TRACE_MSGS */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Wine" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Wine 20020605" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "wine" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "20020605" + +/* The size of a `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* Define to the soname of the libfreetype library. */ +/* #undef SONAME_LIBFREETYPE */ + +/* Define to the soname of the libX11 library. */ +/* #undef SONAME_LIBX11 */ + +/* Define to the soname of the libXext library. */ +/* #undef SONAME_LIBXEXT */ + +/* Define to the soname of the libXrender library. */ +/* #undef SONAME_LIBXRENDER */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define if the struct statfs is defined by */ +/* #undef STATFS_DEFINED_BY_SYS_MOUNT */ + +/* Define if the struct statfs is defined by */ +/* #undef STATFS_DEFINED_BY_SYS_STATFS */ + +/* Define if the struct statfs is defined by */ +/* #undef STATFS_DEFINED_BY_SYS_VFS */ + +/* Define if the struct statfs has the member bavail */ +/* #undef STATFS_HAS_BAVAIL */ + +/* Define if the struct statfs has the member bfree */ +/* #undef STATFS_HAS_BFREE */ + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#define STAT_MACROS_BROKEN 1 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if the X Window System is missing or not being used. */ +#define X_DISPLAY_MISSING 1 + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Set this to 64 to enable 64-bit file support on Linux */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define as `__inline' if that's what the C compiler calls it, or to nothing + if it is not supported. */ +/* #undef inline */ diff --git a/include/wine/debugtools.h b/include/wine/debugtools.h new file mode 100644 index 0000000..a1146a8 --- /dev/null +++ b/include/wine/debugtools.h @@ -0,0 +1,115 @@ +#ifndef __WINE_DEBUGTOOLS_H +#define __WINE_DEBUGTOOLS_H + +#ifndef __NTDLL__ + +#include +#include "config.h" +#include "windef.h" + +#else + +#include + +#endif /* __NTDLL__ */ + +struct _GUID; + +/* Internal definitions (do not use these directly) */ + +enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL_COUNT }; + +#ifndef NO_TRACE_MSGS +# define __GET_DEBUGGING_TRACE(dbch) ((dbch)[0] & (1 << __DBCL_TRACE)) +#else +# define __GET_DEBUGGING_TRACE(dbch) 0 +#endif + +#ifndef NO_DEBUG_MSGS +# define __GET_DEBUGGING_WARN(dbch) ((dbch)[0] & (1 << __DBCL_WARN)) +# define __GET_DEBUGGING_FIXME(dbch) ((dbch)[0] & (1 << __DBCL_FIXME)) +#else +# define __GET_DEBUGGING_WARN(dbch) 0 +# define __GET_DEBUGGING_FIXME(dbch) 0 +#endif + +/* define error macro regardless of what is configured */ +#define __GET_DEBUGGING_ERR(dbch) ((dbch)[0] & (1 << __DBCL_ERR)) + +#define __GET_DEBUGGING(dbcl,dbch) __GET_DEBUGGING##dbcl(dbch) +#define __SET_DEBUGGING(dbcl,dbch,on) \ + ((on) ? ((dbch)[0] |= 1 << (dbcl)) : ((dbch)[0] &= ~(1 << (dbcl)))) + +#ifdef __GNUC__ + +#define __DPRINTF(dbcl,dbch) \ + do { if(__GET_DEBUGGING(dbcl,(dbch))) { \ + const char * const __dbch = (dbch); \ + const enum __DEBUG_CLASS __dbcl = __DBCL##dbcl; \ + __WINE_DBG_LOG + +#define __WINE_DBG_LOG(args...) \ + wine_dbg_log( __dbcl, __dbch, __FUNCTION__, args); } } while(0) + +#define __PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args))) + +#else /* __GNUC__ */ + +#define __DPRINTF(dbcl,dbch) \ + (!__GET_DEBUGGING(dbcl,(dbch)) || \ + (wine_dbg_log(__DBCL##dbcl,(dbch),__FILE__,"%d: ",__LINE__),0)) ? \ + (void)0 : (void)wine_dbg_printf + +#define __PRINTF_ATTR(fmt, args) + +#endif /* __GNUC__ */ + +/* Exported definitions and macros */ + +/* These function return a printable version of a string, including + quotes. The string will be valid for some time, but not indefinitely + as strings are re-used. */ +extern const char *wine_dbgstr_an( const char * s, int n ); +extern const char *wine_dbgstr_wn( const WCHAR *s, int n ); +extern const char *wine_dbgstr_guid( const struct _GUID *id ); + +extern int wine_dbg_vprintf( const char *format, va_list args ) __PRINTF_ATTR(1,0); +extern int wine_dbg_printf( const char *format, ... ) __PRINTF_ATTR(1,2); +extern int wine_dbg_log( enum __DEBUG_CLASS cls, const char *ch, + const char *func, const char *format, ... ) __PRINTF_ATTR(4,5); + +inline static const char *debugstr_an( const char * s, int n ) { return wine_dbgstr_an( s, n ); } +inline static const char *debugstr_wn( const WCHAR *s, int n ) { return wine_dbgstr_wn( s, n ); } +inline static const char *debugstr_guid( const struct _GUID *id ) { return wine_dbgstr_guid(id); } +inline static const char *debugstr_a( const char *s ) { return wine_dbgstr_an( s, 80 ); } +inline static const char *debugstr_w( const WCHAR *s ) { return wine_dbgstr_wn( s, 80 ); } +inline static const char *debugres_a( const char *s ) { return wine_dbgstr_an( s, 80 ); } +inline static const char *debugres_w( const WCHAR *s ) { return wine_dbgstr_wn( s, 80 ); } + +#define TRACE __DPRINTF(_TRACE,__wine_dbch___default) +#define TRACE_(ch) __DPRINTF(_TRACE,__wine_dbch_##ch) +#define TRACE_ON(ch) __GET_DEBUGGING(_TRACE,__wine_dbch_##ch) + +#define WARN __DPRINTF(_WARN,__wine_dbch___default) +#define WARN_(ch) __DPRINTF(_WARN,__wine_dbch_##ch) +#define WARN_ON(ch) __GET_DEBUGGING(_WARN,__wine_dbch_##ch) + +#define FIXME __DPRINTF(_FIXME,__wine_dbch___default) +#define FIXME_(ch) __DPRINTF(_FIXME,__wine_dbch_##ch) +#define FIXME_ON(ch) __GET_DEBUGGING(_FIXME,__wine_dbch_##ch) + +#undef ERR /* Solaris got an 'ERR' define in */ +#define ERR __DPRINTF(_ERR,__wine_dbch___default) +#define ERR_(ch) __DPRINTF(_ERR,__wine_dbch_##ch) +#define ERR_ON(ch) __GET_DEBUGGING(_ERR,__wine_dbch_##ch) + +#define DECLARE_DEBUG_CHANNEL(ch) \ + char __wine_dbch_##ch[1]; +#define DEFAULT_DEBUG_CHANNEL(ch) \ + char __wine_dbch_##ch[1]; static char * const __wine_dbch___default = __wine_dbch_##ch + +#define DPRINTF wine_dbg_printf +#define MESSAGE wine_dbg_printf + +#endif /* __WINE_DEBUGTOOLS_H */ + diff --git a/include/wine/wineros.h b/include/wine/wineros.h new file mode 100644 index 0000000..d0fe393 --- /dev/null +++ b/include/wine/wineros.h @@ -0,0 +1,10 @@ +/* Wine wrapper for ReactOS */ +#ifndef __REACTOS_WINE_WINEROS_H +#define __REACTOS_WINE_WINEROS_H + +typedef unsigned short u_short; +typedef unsigned long u_long; + +#define FD_SETSIZE 64 + +#endif /* __REACTOS_WINE_WINEROS_H */ \ No newline at end of file diff --git a/include/winsock2.h b/include/winsock2.h new file mode 100644 index 0000000..a93362b --- /dev/null +++ b/include/winsock2.h @@ -0,0 +1,1572 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 DLL + * FILE: include/winsock2.h + * PURPOSE: Header file for the WinSock 2 DLL + * and WinSock 2 applications + * DEFINES: UNICODE - Use unicode prototypes + * FD_SETSIZE - Maximum size of an FD_SET (default is 64) + */ +#ifndef __WINSOCK2_H +#define __WINSOCK2_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define WSAAPI STDCALL + + +#if 0 +typedef struct _GUID { + ULONG Data1; + USHORT Data2; + USHORT Data3; + UCHAR Data4[8]; +} GUID, *PGUID, *LPGUID; +#endif + +typedef UINT SOCKET; + +#define INVALID_SOCKET ((SOCKET)~0) +#define SOCKET_ERROR (-1) + +/* Socket types */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +#define SOCK_RDM 4 +#define SOCK_SEQPACKET 5 + +/* Per socket flags */ +#define SO_DEBUG 0x0001 +#define SO_ACCEPTCONN 0x0002 +#define SO_REUSEADDR 0x0004 +#define SO_KEEPALIVE 0x0008 +#define SO_DONTROUTE 0x0010 +#define SO_BROADCAST 0x0020 +#define SO_USELOOPBACK 0x0040 +#define SO_LINGER 0x0080 +#define SO_OOBINLINE 0x0100 + +#define SO_DONTLINGER (UINT)(~SO_LINGER) + +#define SO_SNDBUF 0x1001 +#define SO_RCVBUF 0x1002 +#define SO_SNDLOWAT 0x1003 +#define SO_RCVLOWAT 0x1004 +#define SO_SNDTIMEO 0x1005 +#define SO_RCVTIMEO 0x1006 +#define SO_ERROR 0x1007 +#define SO_TYPE 0x1008 + + +/* Address families */ +#define AF_UNSPEC 0 +#define AF_UNIX 1 +#define AF_INET 2 +#define AF_IMPLINK 3 +#define AF_PUP 4 +#define AF_CHAOS 5 +#define AF_NS 6 +#define AF_ISO 7 +#define AF_OSI AF_ISO +#define AF_ECMA 8 +#define AF_DATAKIT 9 +#define AF_CCITT 10 +#define AF_SNA 11 +#define AF_DECnet 12 +#define AF_DLI 13 +#define AF_LAT 14 +#define AF_HYLINK 15 +#define AF_APPLETALK 16 +#define AF_NETBIOS 17 + +#define AF_MAX 18 + + +/* Protocol families, same as address families */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_INET AF_INET +#define PF_IMPLINK AF_IMPLINK +#define PF_PUP AF_PUP +#define PF_CHAOS AF_CHAOS +#define PF_NS AF_NS +#define PF_ISO AF_ISO +#define PF_OSI AF_OSI +#define PF_ECMA AF_ECMA +#define PF_DATAKIT AF_DATAKIT +#define PF_CCITT AF_CCITT +#define PF_SNA AF_SNA +#define PF_DECnet AF_DECnet +#define PF_DLI AF_DLI +#define PF_LAT AF_LAT +#define PF_HYLINK AF_HYLINK +#define PF_APPLETALK AF_APPLETALK + +#define PF_MAX AF_MAX + + +#define SOL_SOCKET 0xffff + +#define SOMAXCONN 5 + +#define MSG_OOB 0x1 +#define MSG_PEEK 0x2 +#define MSG_DONTROUTE 0x4 + +#define MSG_MAXIOVLEN 16 + + +#define FD_READ 0x01 +#define FD_WRITE 0x02 +#define FD_OOB 0x04 +#define FD_ACCEPT 0x08 +#define FD_CONNECT 0x10 +#define FD_CLOSE 0x20 + +#define FD_MAX_EVENTS 6 +#define FD_ALL_EVENTS ((1 << FD_MAX_EVENTS) - 1) + + +/* Error codes */ + +#define WSABASEERR 10000 + +#define WSAEINTR (WSABASEERR+4) +#define WSAEBADF (WSABASEERR+9) +#define WSAEACCES (WSABASEERR+13) +#define WSAEFAULT (WSABASEERR+14) +#define WSAEINVAL (WSABASEERR+22) +#define WSAEMFILE (WSABASEERR+24) + +#define WSAEWOULDBLOCK (WSABASEERR+35) +#define WSAEINPROGRESS (WSABASEERR+36) +#define WSAEALREADY (WSABASEERR+37) +#define WSAENOTSOCK (WSABASEERR+38) +#define WSAEDESTADDRREQ (WSABASEERR+39) +#define WSAEMSGSIZE (WSABASEERR+40) +#define WSAEPROTOTYPE (WSABASEERR+41) +#define WSAENOPROTOOPT (WSABASEERR+42) +#define WSAEPROTONOSUPPORT (WSABASEERR+43) +#define WSAESOCKTNOSUPPORT (WSABASEERR+44) +#define WSAEOPNOTSUPP (WSABASEERR+45) +#define WSAEPFNOSUPPORT (WSABASEERR+46) +#define WSAEAFNOSUPPORT (WSABASEERR+47) +#define WSAEADDRINUSE (WSABASEERR+48) +#define WSAEADDRNOTAVAIL (WSABASEERR+49) +#define WSAENETDOWN (WSABASEERR+50) +#define WSAENETUNREACH (WSABASEERR+51) +#define WSAENETRESET (WSABASEERR+52) +#define WSAECONNABORTED (WSABASEERR+53) +#define WSAECONNRESET (WSABASEERR+54) +#define WSAENOBUFS (WSABASEERR+55) +#define WSAEISCONN (WSABASEERR+56) +#define WSAENOTCONN (WSABASEERR+57) +#define WSAESHUTDOWN (WSABASEERR+58) +#define WSAETOOMANYREFS (WSABASEERR+59) +#define WSAETIMEDOUT (WSABASEERR+60) +#define WSAECONNREFUSED (WSABASEERR+61) +#define WSAELOOP (WSABASEERR+62) +#define WSAENAMETOOLONG (WSABASEERR+63) +#define WSAEHOSTDOWN (WSABASEERR+64) +#define WSAEHOSTUNREACH (WSABASEERR+65) +#define WSAENOTEMPTY (WSABASEERR+66) +#define WSAEUSERS (WSABASEERR+68) +#define WSAEDQUOT (WSABASEERR+69) +#define WSAESTALE (WSABASEERR+70) +#define WSAEREMOTE (WSABASEERR+71) + +/* Extended Windows Sockets error codes */ +#define WSASYSNOTREADY (WSABASEERR+91) +#define WSAVERNOTSUPPORTED (WSABASEERR+92) +#define WSANOTINITIALISED (WSABASEERR+93) +#define WSAEDISCON (WSABASEERR+101) +#define WSAENOMORE (WSABASEERR+102) +#define WSAECANCELLED (WSABASEERR+103) +#define WSAEINVALIDPROCTABLE (WSABASEERR+104) +#define WSAEINVALIDPROVIDER (WSABASEERR+105) +#define WSAEPROVIDERFAILEDINIT (WSABASEERR+106) +#define WSASYSCALLFAILURE (WSABASEERR+107) +#define WSASERVICE_NOT_FOUND (WSABASEERR+108) +#define WSATYPE_NOT_FOUND (WSABASEERR+109) +#define WSA_E_NO_MORE (WSABASEERR+110) +#define WSA_E_CANCELLED (WSABASEERR+111) +#define WSAEREFUSED (WSABASEERR+112) + +#define WSAHOST_NOT_FOUND (WSABASEERR+1001) +#define WSATRY_AGAIN (WSABASEERR+1002) +#define WSANO_RECOVERY (WSABASEERR+1003) +#define WSANO_DATA (WSABASEERR+1004) +#define WSANO_ADDRESS WSANO_DATA + +#define WSAEVENT HANDLE +#define LPWSAEVENT LPHANDLE + +#define WSA_IO_PENDING (ERROR_IO_PENDING) +#define WSA_IO_INCOMPLETE (ERROR_IO_INCOMPLETE) +#define WSA_INVALID_HANDLE (ERROR_INVALID_HANDLE) +#define WSA_INVALID_PARAMETER (ERROR_INVALID_PARAMETER) +#define WSA_NOT_ENOUGH_MEMORY (ERROR_NOT_ENOUGH_MEMORY) +#define WSA_OPERATION_ABORTED (ERROR_OPERATION_ABORTED) + +#define WSA_INVALID_EVENT ((WSAEVENT)NULL) +#define WSA_MAXIMUM_WAIT_EVENTS (MAXIMUM_WAIT_OBJECTS) +#define WSA_WAIT_FAILED ((DWORD)-1L) +#define WSA_WAIT_EVENT_0 (WAIT_OBJECT_0) +#define WSA_WAIT_IO_COMPLETION (WAIT_IO_COMPLETION) +#define WSA_WAIT_TIMEOUT (WAIT_TIMEOUT) +#define WSA_INFINITE (INFINITE) + + + +#define IOCPARM_MASK 0x7f +#define IOC_VOID 0x20000000 +#define IOC_OUT 0x40000000 +#define IOC_IN 0x80000000 +#define IOC_INOUT (IOC_IN|IOC_OUT) + +#define _IO(x, y) (IOC_VOID|(x<<8)|y) + +#define _IOR(x, y, t) (IOC_OUT|(((LONG)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y) + +#define _IOW(x, y, t) (IOC_IN|(((LONG)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y) + +#define FIONREAD _IOR('f', 127, ULONG) +#define FIONBIO _IOW('f', 126, ULONG) +#define FIOASYNC _IOW('f', 125, ULONG) + +/* Socket I/O controls */ +#define SIOCSHIWAT _IOW('s', 0, ULONG) +#define SIOCGHIWAT _IOR('s', 1, ULONG) +#define SIOCSLOWAT _IOW('s', 2, ULONG) +#define SIOCGLOWAT _IOR('s', 3, ULONG) +#define SIOCATMARK _IOR('s', 7, ULONG) + + +struct in_addr { + union { + struct { UCHAR s_b1, s_b2,s_b3,s_b4; } S_un_b; + struct { USHORT s_w1,s_w2; } S_un_w; + ULONG S_addr; + } S_un; +#define s_addr S_un.S_addr +#define s_host S_un.S_un_b.s_b2 +#define s_net S_un.S_un_b.s_b1 +#define s_imp S_un.S_un_w.s_w2 +#define s_impno S_un.S_un_b.s_b4 +#define s_lh S_un.S_un_b.s_b3 +}; + +/* + Definitions of bits in internet address integers. + NOTE: On subnets the decomposition of addresses to host and + net parts is done according to subnet mask, not the masks here. + */ +#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST 0x000000ff + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IN_MULTICAST(i) IN_CLASSD(i) + +#define ADDR_ANY INADDR_ANY + + +struct timeval { + LONG tv_sec; + LONG tv_usec; +}; + + +struct sockaddr { + USHORT sa_family; + CHAR sa_data[14]; +}; + + +struct linger { + USHORT l_onoff; + USHORT l_linger; +}; + + +/* IP specific */ + +struct sockaddr_in { + SHORT sin_family; + USHORT sin_port; + struct in_addr sin_addr; + CHAR sin_zero[8]; +}; + +#define INADDR_ANY ((ULONG)0x00000000) +#define INADDR_LOOPBACK ((ULONG)0x7f000001) +#define INADDR_BROADCAST ((ULONG)0xffffffff) +#define INADDR_NONE ((ULONG)0xffffffff) + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_IGMP 2 +#define IPPROTO_GGP 3 +#define IPPROTO_TCP 6 +#define IPPROTO_PUP 12 +#define IPPROTO_UDP 17 +#define IPPROTO_IDP 22 +#define IPPROTO_ND 77 +#define IPPROTO_RAW 255 +#define IPPROTO_MAX 256 + + +#ifndef FD_SETSIZE +#define FD_SETSIZE 64 +#endif /* FD_SETSIZE */ + +typedef struct fd_set { + UINT fd_count; + SOCKET fd_array[FD_SETSIZE]; +} fd_set; + +extern INT PASCAL FAR __WSAFDIsSet(SOCKET, fd_set FAR*); + +#define FD_CLR(s, set) do { \ + UINT __i; \ + for (__i = 0; __i < ((fd_set FAR*)(set))->fd_count; __i++) { \ + if (((fd_set FAR*)(set))->fd_array[__i] == s) { \ + while (__i < ((fd_set FAR*)(set))->fd_count - 1) { \ + ((fd_set FAR *)(set))->fd_array[__i] = \ + ((fd_set FAR*)(set))->fd_array[__i+1]; \ + __i++; \ + } \ + ((fd_set FAR *)(set))->fd_count--; \ + break; \ + } \ + } \ +} while(0) + +#define FD_SET(s, set) do { \ + UINT __i; \ + for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \ + if (((fd_set FAR *)(set))->fd_array[__i] == (s)) { \ + break; \ + } \ + } \ + if (__i == ((fd_set FAR *)(set))->fd_count) { \ + if (((fd_set FAR*)(set))->fd_count < FD_SETSIZE) { \ + ((fd_set FAR*)(set))->fd_array[__i] = (s); \ + ((fd_set FAR*)(set))->fd_count++; \ + } \ + } \ +} while(0) + +#define FD_ISSET(s, set) __WSAFDIsSet((SOCKET)(s), (fd_set FAR*)(set)) + +#define FD_ZERO(set) (((fd_set FAR*)(set))->fd_count = 0) + + +typedef struct _WSAOVERLAPPED { + DWORD Internal; // reserved + DWORD InternalHigh; // reserved + DWORD Offset; // reserved + DWORD OffsetHigh; // reserved + WSAEVENT hEvent; +} WSAOVERLAPPED, FAR* LPWSAOVERLAPPED; + + +typedef struct __WSABUF { + ULONG len; // buffer length + CHAR FAR* buf; // pointer to buffer +} WSABUF, FAR* LPWSABUF; + + +typedef ULONG SERVICETYPE; + +#define SERVICETYPE_NOTRAFFIC 0x00000000 +#define SERVICETYPE_BESTEFFORT 0x00000001 +#define SERVICETYPE_CONTROLLEDLOAD 0x00000002 +#define SERVICETYPE_GUARANTEED 0x00000003 +#define SERVICETYPE_NETWORK_UNAVAILABLE 0x00000004 +#define SERVICETYPE_GENERAL_INFORMATION 0x00000005 +#define SERVICETYPE_NOCHANGE 0x00000006 +#define SERVICE_IMMEDIATE_TRAFFIC_CONTROL 0x00000007 + +typedef struct _flowspec { + ULONG TokenRate; /* In Bytes/sec */ + ULONG TokenBucketSize; /* In Bytes */ + ULONG PeakBandwidth; /* In Bytes/sec */ + ULONG Latency; /* In microseconds */ + ULONG DelayVariation; /* In microseconds */ + SERVICETYPE ServiceType; + ULONG MaxSduSize; /* In Bytes */ + ULONG MinimumPolicedSize; /* In Bytes */ +} FLOWSPEC, *PFLOWSPEC, FAR* LPFLOWSPEC; + + +typedef struct _QualityOfService { + FLOWSPEC SendingFlowspec; /* The flow spec for data sending */ + FLOWSPEC ReceivingFlowspec; /* The flow spec for data receiving */ + WSABUF ProviderSpecific; /* Additional provider specific stuff */ +} QOS, FAR* LPQOS; + + + +typedef struct _WSANETWORKEVENTS { + LONG lNetworkEvents; + INT iErrorCode[FD_MAX_EVENTS]; +} WSANETWORKEVENTS, FAR* LPWSANETWORKEVENTS; + + +#define MAX_PROTOCOL_CHAIN 7 + +#define BASE_PROTOCOL 1 +#define LAYERED_PROTOCOL 0 + +typedef struct _WSAPROTOCOLCHAIN { + INT ChainLen; + DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; +} WSAPROTOCOLCHAIN, FAR* LPWSAPROTOCOLCHAIN; + +#define WSAPROTOCOL_LEN 255 + +typedef struct _WSAPROTOCOL_INFOA { + DWORD dwServiceFlags1; + DWORD dwServiceFlags2; + DWORD dwServiceFlags3; + DWORD dwServiceFlags4; + DWORD dwProviderFlags; + GUID ProviderId; + DWORD dwCatalogEntryId; + WSAPROTOCOLCHAIN ProtocolChain; + INT iVersion; + INT iAddressFamily; + INT iMaxSockAddr; + INT iMinSockAddr; + INT iSocketType; + INT iProtocol; + INT iProtocolMaxOffset; + INT iNetworkByteOrder; + INT iSecurityScheme; + DWORD dwMessageSize; + DWORD dwProviderReserved; + CHAR szProtocol[WSAPROTOCOL_LEN + 1]; +} WSAPROTOCOL_INFOA, FAR* LPWSAPROTOCOL_INFOA; + +typedef struct _WSAPROTOCOL_INFOW { + DWORD dwServiceFlags1; + DWORD dwServiceFlags2; + DWORD dwServiceFlags3; + DWORD dwServiceFlags4; + DWORD dwProviderFlags; + GUID ProviderId; + DWORD dwCatalogEntryId; + WSAPROTOCOLCHAIN ProtocolChain; + INT iVersion; + INT iAddressFamily; + INT iMaxSockAddr; + INT iMinSockAddr; + INT iSocketType; + INT iProtocol; + INT iProtocolMaxOffset; + INT iNetworkByteOrder; + INT iSecurityScheme; + DWORD dwMessageSize; + DWORD dwProviderReserved; + WCHAR szProtocol[WSAPROTOCOL_LEN + 1]; +} WSAPROTOCOL_INFOW, FAR * LPWSAPROTOCOL_INFOW; + +#ifdef UNICODE +typedef WSAPROTOCOL_INFOW WSAPROTOCOL_INFO; +typedef LPWSAPROTOCOL_INFOW LPWSAPROTOCOL_INFO; +#else /* UNICODE */ +typedef WSAPROTOCOL_INFOA WSAPROTOCOL_INFO; +typedef LPWSAPROTOCOL_INFOA LPWSAPROTOCOL_INFO; +#endif /* UNICODE */ + + +/* WinSock 2 extended commands for WSAIoctl() */ + +#define IOC_UNIX 0x00000000 +#define IOC_WS2 0x08000000 +#define IOC_FAMILY 0x10000000 +#define IOC_VENDOR 0x18000000 + +#define _WSAIO (x,y) (IOC_VOID | (x) | (y)) +#define _WSAIOR (x,y) (IOC_OUT | (x) | (y)) +#define _WSAIOW (x,y) (IOC_IN | (x) | (y)) +#define _WSAIORW(x,y) (IOC_INOUT| (x) | (y)) + +#define SIO_ASSOCIATE_HANDLE _WSAIOW (IOC_WS2, 1) +#define SIO_ENABLE_CIRCULAR_QUEUEING _WSAIO (IOC_WS2, 2) +#define SIO_FIND_ROUTE _WSAIOR (IOC_WS2, 3) +#define SIO_FLUSH _WSAIO (IOC_WS2, 4) +#define SIO_GET_BROADCAST_ADDRESS -WSAIOR (IOC_WS2, 5) +#define SIO_GET_EXTENSION_FUNCTION_POINTER _WSAIORW(IOC_WS2, 6) +#define SIO_GET_QOS _WSAIORW(IOC_WS2, 7) +#define SIO_GET_GROUP_QOS _WSAIORW(IOC_WS2, 8) +#define SIO_MULTIPOINT_LOOPBACK _WSAIOW (IOC_WS2, 9) +#define SIO_MULTICAST_SCOPE _WSAIOW (IOC_WS2, 10) +#define SIO_SET_QOS _WSAIOW (IOC_WS2, 11) +#define SIO_SET_GROUP_QOS _WSAIOW (IOC_WS2, 12) +#define SIO_TRANSLATE_HANDLE _WSAIORW(IOC_WS2, 13) +#define SIO_ROUTING_INTERFACE_QUERY _WSAIORW(IOC_WS2, 20) +#define SIO_ROUTING_INTERFACE_CHANGE _WSAIOW (IOC_WS2, 21) +#define SIO_ADDRESS_LIST_QUERY _WSAIOR (IOC_WS2, 22) +#define SIO_ADDRESS_LIST_CHANGE _WSAIO (IOC_WS2, 23) +#define SIO_QUERY_TARGET_PNP_HANDLE _WSAIOR (IOC_W32, 24) + + +/* Structures for WinSock 1.1 compatible namespace resolution */ + +struct hostent { + CHAR FAR* h_name; + CHAR FAR* FAR* h_aliases; + SHORT h_addrtype; + SHORT h_length; + CHAR FAR* FAR* h_addr_list; +#define h_addr h_addr_list[0] /* Backward compatible field name */ +}; + +struct protoent { + CHAR FAR* p_name; + CHAR FAR* FAR* p_aliases; + SHORT p_proto; +}; + +struct servent { + CHAR FAR* s_name; + CHAR FAR* FAR* s_aliases; + SHORT s_port; + CHAR FAR* s_proto; +}; + +// It is assumed here that a network number fits in 32 bits. +struct netent { + CHAR FAR* n_name; // official net name + CHAR FAR* FAR* n_aliases; // list of alias's + SHORT n_addrtype; // network address type id + ULONG n_net; // network number +}; + + +typedef UINT GROUP; + +typedef +INT +(CALLBACK * LPCONDITIONPROC)( + LPWSABUF lpCallerId, + LPWSABUF lpCallerData, + LPQOS lpSQOS, + LPQOS lpGQOS, + LPWSABUF lpCalleeId, + LPWSABUF lpCalleeData, + GROUP FAR* g, + DWORD dwCallbackData); + +typedef +VOID +(CALLBACK* LPWSAOVERLAPPED_COMPLETION_ROUTINE)( + DWORD dwError, + DWORD cbTransferred, + LPWSAOVERLAPPED lpOverlapped, + DWORD dwFlags); + + +/* Microsoft Windows extended data types */ + +typedef struct sockaddr SOCKADDR; +typedef struct sockaddr *PSOCKADDR; +typedef struct sockaddr FAR *LPSOCKADDR; + +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr_in *PSOCKADDR_IN; +typedef struct sockaddr_in FAR *LPSOCKADDR_IN; + +typedef struct linger LINGER; +typedef struct linger *PLINGER; +typedef struct linger FAR *LPLINGER; + +typedef struct in_addr IN_ADDR; +typedef struct in_addr *PIN_ADDR; +typedef struct in_addr FAR *LPIN_ADDR; + +typedef struct fd_set FD_SET; +typedef struct fd_set *PFD_SET; +typedef struct fd_set FAR *LPFD_SET; + +typedef struct hostent HOSTENT; +typedef struct hostent *PHOSTENT; +typedef struct hostent FAR *LPHOSTENT; + +typedef struct servent SERVENT; +typedef struct servent *PSERVENT; +typedef struct servent FAR *LPSERVENT; + +typedef struct protoent PROTOENT; +typedef struct protoent *PPROTOENT; +typedef struct protoent FAR *LPPROTOENT; + +typedef struct timeval TIMEVAL; +typedef struct timeval *PTIMEVAL; +typedef struct timeval FAR *LPTIMEVAL; + +#define WSAMAKEASYNCREPLY(buflen,error) MAKELONG(buflen,error) +#define WSAMAKESELECTREPLY(event,error) MAKELONG(event,error) +#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam) +#define WSAGETASYNCERROR(lParam) HIWORD(lParam) +#define WSAGETSELECTEVENT(lParam) LOWORD(lParam) +#define WSAGETSELECTERROR(lParam) HIWORD(lParam) + + +#define WSADESCRIPTION_LEN 256 +#define WSASYS_STATUS_LEN 128 + +typedef struct WSAData { + WORD wVersion; + WORD wHighVersion; + CHAR szDescription[WSADESCRIPTION_LEN + 1]; + CHAR szSystemStatus[WSASYS_STATUS_LEN + 1]; + USHORT iMaxSockets; + USHORT iMaxUdpDg; + CHAR FAR* lpVendorInfo; +} WSADATA, FAR* LPWSADATA; + +#ifndef _BLOB_DEFINED +#define _BLOB_DEFINED +typedef struct _BLOB { + ULONG cbSize; + BYTE *pBlobData; +} BLOB, *LPBLOB; +#else +typedef BLOB *LPBLOB; +#endif + +typedef struct _SOCKET_ADDRESS { + LPSOCKADDR lpSockaddr; + INT iSockaddrLength; +} SOCKET_ADDRESS, *PSOCKET_ADDRESS, FAR* LPSOCKET_ADDRESS; + +typedef struct _SOCKET_ADDRESS_LIST { + INT iAddressCount; + SOCKET_ADDRESS Address[1]; +} SOCKET_ADDRESS_LIST, FAR* LPSOCKET_ADDRESS_LIST; + +typedef struct _CSADDR_INFO { + SOCKET_ADDRESS LocalAddr; + SOCKET_ADDRESS RemoteAddr; + INT iSocketType; + INT iProtocol; +} CSADDR_INFO, *PCSADDR_INFO, FAR* LPCSADDR_INFO; + + +/* Structures for namespace resolution */ + +typedef struct _WSANAMESPACE_INFOA { + GUID NSProviderId; + DWORD dwNameSpace; + BOOL fActive; + DWORD dwVersion; + LPSTR lpszIdentifier; +} WSANAMESPACE_INFOA, *PWSANAMESPACE_INFOA, *LPWSANAMESPACE_INFOA; + +typedef struct _WSANAMESPACE_INFOW { + GUID NSProviderId; + DWORD dwNameSpace; + BOOL fActive; + DWORD dwVersion; + LPWSTR lpszIdentifier; +} WSANAMESPACE_INFOW, *PWSANAMESPACE_INFOW, *LPWSANAMESPACE_INFOW; + +#ifdef UNICODE +typedef WSANAMESPACE_INFOW WSANAMESPACE_INFO; +typedef PWSANAMESPACE_INFOW PWSANAMESPACE_INFO; +typedef LPWSANAMESPACE_INFOW LPWSANAMESPACE_INFO; +#else /* UNICODE */ +typedef WSANAMESPACE_INFOA WSANAMESPACE_INFO; +typedef PWSANAMESPACE_INFOA PWSANAMESPACE_INFO; +typedef LPWSANAMESPACE_INFOA LPWSANAMESPACE_INFO; +#endif /* UNICODE */ + + +typedef enum _WSAEcomparator +{ + COMP_EQUAL = 0, + COMP_NOTLESS +} WSAECOMPARATOR, *PWSAECOMPARATOR, *LPWSAECOMPARATOR; + +typedef struct _WSAVersion +{ + DWORD dwVersion; + WSAECOMPARATOR ecHow; +}WSAVERSION, *PWSAVERSION, *LPWSAVERSION; + + +typedef struct _AFPROTOCOLS { + INT iAddressFamily; + INT iProtocol; +} AFPROTOCOLS, *PAFPROTOCOLS, *LPAFPROTOCOLS; + + +typedef struct _WSAQuerySetA { + DWORD dwSize; + LPSTR lpszServiceInstanceName; + LPGUID lpServiceClassId; + LPWSAVERSION lpVersion; + LPSTR lpszComment; + DWORD dwNameSpace; + LPGUID lpNSProviderId; + LPSTR lpszContext; + DWORD dwNumberOfProtocols; + LPAFPROTOCOLS lpafpProtocols; + LPSTR lpszQueryString; + DWORD dwNumberOfCsAddrs; + LPCSADDR_INFO lpcsaBuffer; + DWORD dwOutputFlags; + LPBLOB lpBlob; +} WSAQUERYSETA, *PWSAQUERYSETA, *LPWSAQUERYSETA; + +typedef struct _WSAQuerySetW { + DWORD dwSize; + LPWSTR lpszServiceInstanceName; + LPGUID lpServiceClassId; + LPWSAVERSION lpVersion; + LPWSTR lpszComment; + DWORD dwNameSpace; + LPGUID lpNSProviderId; + LPWSTR lpszContext; + DWORD dwNumberOfProtocols; + LPAFPROTOCOLS lpafpProtocols; + LPWSTR lpszQueryString; + DWORD dwNumberOfCsAddrs; + LPCSADDR_INFO lpcsaBuffer; + DWORD dwOutputFlags; + LPBLOB lpBlob; +} WSAQUERYSETW, *PWSAQUERYSETW, *LPWSAQUERYSETW; + +#ifdef UNICODE +typedef WSAQUERYSETW WSAQUERYSET; +typedef PWSAQUERYSETW PWSAQUERYSET; +typedef LPWSAQUERYSETW LPWSAQUERYSET; +#else /* UNICODE */ +typedef WSAQUERYSETA WSAQUERYSET; +typedef PWSAQUERYSETA PWSAQUERYSET; +typedef LPWSAQUERYSETA LPWSAQUERYSET; +#endif /* UNICODE */ + + +typedef enum _WSAESETSERVICEOP { + RNRSERVICE_REGISTER = 0, + RNRSERVICE_DEREGISTER, + RNRSERVICE_DELETE +} WSAESETSERVICEOP, *PWSAESETSERVICEOP, *LPWSAESETSERVICEOP; + + +typedef struct _WSANSClassInfoA { + LPSTR lpszName; + DWORD dwNameSpace; + DWORD dwValueType; + DWORD dwValueSize; + LPVOID lpValue; +} WSANSCLASSINFOA, *PWSANSCLASSINFOA, *LPWSANSCLASSINFOA; + +typedef struct _WSANSClassInfoW { + LPWSTR lpszName; + DWORD dwNameSpace; + DWORD dwValueType; + DWORD dwValueSize; + LPVOID lpValue; +} WSANSCLASSINFOW, *PWSANSCLASSINFOW, *LPWSANSCLASSINFOW; + +#ifdef UNICODE +typedef WSANSCLASSINFOW WSANSCLASSINFO; +typedef PWSANSCLASSINFOW PWSANSCLASSINFO; +typedef LPWSANSCLASSINFOW LPWSANSCLASSINFO; +#else /* UNICODE */ +typedef WSANSCLASSINFOA WSANSCLASSINFO; +typedef PWSANSCLASSINFOA PWSANSCLASSINFO; +typedef LPWSANSCLASSINFOA LPWSANSCLASSINFO; +#endif /* UNICODE */ + +typedef struct _WSAServiceClassInfoA { + LPGUID lpServiceClassId; + LPSTR lpszServiceClassName; + DWORD dwCount; + LPWSANSCLASSINFOA lpClassInfos; +} WSASERVICECLASSINFOA, *PWSASERVICECLASSINFOA, *LPWSASERVICECLASSINFOA; + +typedef struct _WSAServiceClassInfoW { + LPGUID lpServiceClassId; + LPWSTR lpszServiceClassName; + DWORD dwCount; + LPWSANSCLASSINFOW lpClassInfos; +} WSASERVICECLASSINFOW, *PWSASERVICECLASSINFOW, *LPWSASERVICECLASSINFOW; + +#ifdef UNICODE +typedef WSASERVICECLASSINFOW WSASERVICECLASSINFO; +typedef PWSASERVICECLASSINFOW PWSASERVICECLASSINFO; +typedef LPWSASERVICECLASSINFOW LPWSASERVICECLASSINFO; +#else /* UNICODE */ +typedef WSASERVICECLASSINFOA WSASERVICECLASSINFO; +typedef PWSASERVICECLASSINFOA PWSASERVICECLASSINFO; +typedef LPWSASERVICECLASSINFOA LPWSASERVICECLASSINFO; +#endif /* UNICODE */ + + +/* WinSock 2 DLL prototypes */ + +SOCKET +WSAAPI +accept( + IN SOCKET s, + OUT LPSOCKADDR addr, + OUT INT FAR* addrlen); + +INT +WSAAPI +bind( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen); + +INT +WSAAPI +closesocket( + IN SOCKET s); + +INT +WSAAPI +connect( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen); + +INT +WSAAPI +getpeername( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT INT FAR* namelen); + +INT +WSAAPI +getsockname( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT INT FAR* namelen); + +INT +WSAAPI +getsockopt( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT INT FAR* optlen); + +ULONG +WSAAPI +htonl( + IN ULONG hostlong); + +USHORT +WSAAPI +htons( + IN USHORT hostshort); + +INT +WSAAPI +ioctlsocket( + IN SOCKET s, + IN LONG cmd, + IN OUT ULONG FAR* argp); + +INT +WSAAPI +listen( + IN SOCKET s, + IN INT backlog); + +ULONG +WSAAPI +ntohl( + IN ULONG netlong); + +USHORT +WSAAPI +ntohs( + IN USHORT netshort); + +INT +WSAAPI +recv( + IN SOCKET s, + OUT CHAR FAR* buf, + IN INT len, + IN INT flags); + +INT +WSAAPI +recvfrom( + IN SOCKET s, + OUT CHAR FAR* buf, + IN INT len, + IN INT flags, + OUT LPSOCKADDR from, + IN OUT INT FAR* fromlen); + +INT +WSAAPI +select( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout); + +INT +WSAAPI +send( + IN SOCKET s, + IN CONST CHAR FAR* buf, + IN INT len, + IN INT flags); + +INT +WSAAPI +sendto( + IN SOCKET s, + IN CONST CHAR FAR* buf, + IN INT len, + IN INT flags, + IN CONST LPSOCKADDR to, + IN INT tolen); + +INT +WSAAPI +setsockopt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen); + +INT +WSAAPI +shutdown( + IN SOCKET s, + IN INT how); + +SOCKET +WSAAPI +socket( + IN INT af, + IN INT type, + IN INT protocol); + +SOCKET +WSAAPI +WSAAccept( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData); + +INT +WSAAPI +WSAAsyncSelect( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent); + +INT +WSAAPI +WSACancelBlockingCall(VOID); + +INT +WSAAPI +WSACleanup(VOID); + +BOOL +WSAAPI +WSACloseEvent( + IN WSAEVENT hEvent); + +INT +WSAAPI +WSAConnect( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS); + +WSAEVENT +WSAAPI +WSACreateEvent(VOID); + +INT +WSAAPI +WSADuplicateSocketA( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOA lpProtocolInfo); + +INT +WSAAPI +WSADuplicateSocketW( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo); + +#ifdef UNICODE +#define WSADuplicateSocket WSADuplicateSocketA +#else /* UNICODE */ +#define WSADuplicateSocket WSADuplicateSocketW +#endif /* UNICODE */ + +INT +WSAAPI +WSAEnumNetworkEvents( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents); + +INT +WSAAPI +WSAEnumProtocolsA( + IN LPINT lpiProtocols, + OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength); + +INT +WSAAPI +WSAEnumProtocolsW( + IN LPINT lpiProtocols, + OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength); + +#ifdef UNICODE +#define WSAEnumProtocols WSAEnumProtocolsA +#else /* UNICODE */ +#define WSAEnumProtocols WSAEnumProtocolsW +#endif /* UNICODE */ + +INT +WSAAPI +WSAEventSelect( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents); + +INT +WSAAPI +WSAGetLastError(VOID); + +BOOL +WSAAPI +WSAGetOverlappedResult( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags); + +BOOL +WSAAPI +WSAGetQOSByName( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS); + +INT +WSAAPI +WSAHtonl( + IN SOCKET s, + IN ULONG hostlong, + OUT ULONG FAR* lpnetlong); + +INT +WSAAPI +WSAHtons( + IN SOCKET s, + IN USHORT hostshort, + OUT USHORT FAR* lpnetshort); + +INT +WSAAPI +WSAIoctl( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +BOOL +WSAAPI +WSAIsBlocking(VOID); + +SOCKET +WSAAPI +WSAJoinLeaf( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags); + +INT +WSAAPI +WSANtohl( + IN SOCKET s, + IN ULONG netlong, + OUT ULONG FAR* lphostlong); + +INT +WSAAPI +WSANtohs( + IN SOCKET s, + IN USHORT netshort, + OUT USHORT FAR* lphostshort); + +INT +WSAAPI +WSARecv( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +INT +WSAAPI +WSARecvDisconnect( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData); + +INT +WSAAPI +WSARecvFrom( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromlen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +BOOL +WSAAPI +WSAResetEvent( + IN WSAEVENT hEvent); + +INT +WSAAPI +WSASend( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +INT +WSAAPI +WSASendDisconnect( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData); + +INT +WSAAPI +WSASendTo( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST LPSOCKADDR lpTo, + IN INT iToLen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +FARPROC +WSAAPI +WSASetBlockingHook( + IN FARPROC lpBlockFunc); + +BOOL +WSAAPI +WSASetEvent( + IN WSAEVENT hEvent); + +VOID +WSAAPI +WSASetLastError( + IN INT iError); + +SOCKET +WSAAPI +WSASocketA( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags); + +SOCKET +WSAAPI +WSASocketW( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags); + +#ifdef UNICODE +#define WSASocket WSASocketW +#else /* UNICODE */ +#define WSASocket WSASocketA +#endif /* UNICODE */ + +INT +WSAAPI +WSAStartup( + IN WORD wVersionRequested, + OUT LPWSADATA lpWSAData); + +INT +WSAAPI +WSAUnhookBlockingHook(VOID); + +DWORD +WSAAPI +WSAWaitForMultipleEvents( + IN DWORD cEvents, + IN CONST WSAEVENT FAR* lphEvents, + IN BOOL fWaitAll, + IN DWORD dwTimeout, + IN BOOL fAlertable); + +INT +WSAAPI +WSAProviderConfigChange( + IN OUT LPHANDLE lpNotificationHandle, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); + +/* Name resolution APIs */ + +INT +WSAAPI +WSAAddressToStringA( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + OUT LPSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength); + +INT +WSAAPI +WSAAddressToStringW( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength); + +#ifdef UNICODE +#define WSAAddressToString WSAAddressToStringW +#else /* UNICODE */ +#define WSAAddressToString WSAAddressToStringA +#endif /* UNICODE */ + +INT +WSAAPI +WSAEnumNameSpaceProvidersA( + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSANAMESPACE_INFOA lpnspBuffer); + +INT +WSAAPI +WSAEnumNameSpaceProvidersW( + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSANAMESPACE_INFOW lpnspBuffer); + +#ifdef UNICODE +#define WSAEnumNameSpaceProviders WSAEnumNameSpaceProvidersW +#else /* UNICODE */ +#define WSAEnumNameSpaceProviders WSAEnumNameSpaceProvidersA +#endif /* UNICODE */ + +INT +WSAAPI +WSAGetServiceClassInfoA( + IN LPGUID lpProviderId, + IN LPGUID lpServiceClassId, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSASERVICECLASSINFOA lpServiceClassInfo); + +INT +WSAAPI +WSAGetServiceClassInfoW( + IN LPGUID lpProviderId, + IN LPGUID lpServiceClassId, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSASERVICECLASSINFOW lpServiceClassInfo); + +#ifdef UNICODE +#define WSAGetServiceClassInfo WSAGetServiceClassInfoW +#else /* UNICODE */ +#define WSAGetServiceClassInfo WSAGetServiceClassInfoA +#endif /* UNICODE */ + +INT +WSAAPI +WSAGetServiceClassNameByClassIdA( + IN LPGUID lpServiceClassId, + OUT LPSTR lpszServiceClassName, + IN OUT LPDWORD lpdwBufferLength); + +INT +WSAAPI +WSAGetServiceClassNameByClassIdW( + IN LPGUID lpServiceClassId, + OUT LPWSTR lpszServiceClassName, + IN OUT LPDWORD lpdwBufferLength); + +#ifdef UNICODE +#define WSAGetServiceClassNameByClassId WSAGetServiceClassNameByClassIdW +#else /* UNICODE */ +#define WSAGetServiceClassNameByClassId WSAGetServiceClassNameByClassIdA +#endif /* UNICODE */ + +INT +WSAAPI +WSAInstallServiceClassA( + IN LPWSASERVICECLASSINFOA lpServiceClassInfo); + +INT +WSAAPI +WSAInstallServiceClassW( + IN LPWSASERVICECLASSINFOW lpServiceClassInfo); + +#ifdef UNICODE +#define WSAInstallServiceClass WSAInstallServiceClassW +#else /* UNICODE */ +#define WSAInstallServiceClass WSAInstallServiceClassA +#endif /* UNICODE */ + +INT +WSAAPI +WSALookupServiceBegin( + IN LPWSAQUERYSET lpqsRestrictions, + IN DWORD dwControlFlags, + OUT LPHANDLE lphLookup); + +INT +WSAAPI +WSALookupServiceEnd( + IN HANDLE hLookup); + +INT +WSAAPI +WSALookupServiceNext( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSET lpqsResults); + +INT +WSAAPI +WSARemoveServiceClass( + IN LPGUID lpServiceClassId); + +INT +WSAAPI +WSASetService( + IN LPWSAQUERYSET lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags); + +INT +WSAAPI +WSAStringToAddressA( + IN LPSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength); + +INT +WSAAPI +WSAStringToAddressW( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength); + +#ifdef UNICODE +#define WSAStringToAddress WSAStringToAddressW +#else /* UNICODE */ +#define WSAStringToAddress WSAStringToAddressA +#endif /* UNICODE */ + +/* WinSock 1.1 compatible name resolution APIs */ + +LPHOSTENT +WSAAPI +gethostbyaddr( + IN CONST CHAR FAR* addr, + IN INT len, + IN INT type); + +LPHOSTENT +WSAAPI +gethostbyname( + IN CONST CHAR FAR* name); + +INT +WSAAPI +gethostname( + OUT CHAR FAR* name, + IN INT namelen); + +LPPROTOENT +WSAAPI +getprotobyname( + IN CONST CHAR FAR* name); + +LPPROTOENT +WSAAPI +getprotobynumber( + IN INT number); + +LPSERVENT +WSAAPI +getservbyname( + IN CONST CHAR FAR* name, + IN CONST CHAR FAR* proto); + +LPSERVENT +WSAAPI +getservbyport( + IN INT port, + IN CONST CHAR FAR* proto); + +ULONG +WSAAPI +inet_addr( + IN CONST CHAR FAR* cp); + +CHAR FAR* +WSAAPI +inet_ntoa( + IN IN_ADDR in); + +HANDLE +WSAAPI +WSAAsyncGetHostByAddr( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* addr, + IN INT len, + IN INT type, + OUT CHAR FAR* buf, + IN INT buflen); + +HANDLE +WSAAPI +WSAAsyncGetHostByName( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* name, + OUT CHAR FAR* buf, + IN INT buflen); + +HANDLE +WSAAPI +WSAAsyncGetProtoByName( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* name, + OUT CHAR FAR* buf, + IN INT buflen); + +HANDLE +WSAAPI +WSAAsyncGetProtoByNumber( + IN HWND hWnd, + IN UINT wMsg, + IN INT number, + OUT CHAR FAR* buf, + IN INT buflen); + +HANDLE +WSAAPI +WSAAsyncGetServByName( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* name, + IN CONST CHAR FAR* proto, + OUT CHAR FAR* buf, + IN INT buflen); + +HANDLE +WSAAPI +WSAAsyncGetServByPort( + IN HWND hWnd, + IN UINT wMsg, + IN INT port, + IN CONST CHAR FAR* proto, + OUT CHAR FAR* buf, + IN INT buflen); + +INT +WSAAPI +WSACancelAsyncRequest( + IN HANDLE hAsyncTaskHandle); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* __WINSOCK2_H */ + +/* EOF */ diff --git a/include/ws2spi.h b/include/ws2spi.h new file mode 100644 index 0000000..1523de3 --- /dev/null +++ b/include/ws2spi.h @@ -0,0 +1,566 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 DLL + * FILE: include/ws2spi.h + * PURPOSE: Header file for the WinSock 2 DLL + * and WinSock 2 Service Providers + */ +#ifndef __WS2SPI_H +#define __WS2SPI_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define WSPAPI WSAAPI + + +#define WSPDESCRIPTION_LEN 255 + +typedef struct WSPData { + WORD wVersion; + WORD wHighVersion; + WCHAR szDescription[WSPDESCRIPTION_LEN + 1]; +} WSPDATA, FAR * LPWSPDATA; + + +typedef struct _WSATHREADID { + HANDLE ThreadHandle; + DWORD Reserved; +} WSATHREADID, FAR* LPWSATHREADID; + + +typedef BOOL (CALLBACK FAR* LPBLOCKINGCALLBACK)( + DWORD dwContext); + +typedef VOID (CALLBACK FAR* LPWSAUSERAPC)( + DWORD dwContext); + + +/* Prototypes for service provider procedure table */ + +typedef SOCKET (WSPAPI * LPWSPACCEPT)( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPADDRESSTOSTRING)( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPASYNCSELECT)( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPBIND)( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPCANCELBLOCKINGCALL)( + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPCLEANUP)( + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPCLOSESOCKET)( + IN SOCKET s, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPCONNECT)( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPDUPLICATESOCKET)( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPENUMNETWORKEVENTS)( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPEVENTSELECT)( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents, + OUT LPINT lpErrno); + +typedef BOOL (WSPAPI * LPWSPGETOVERLAPPEDRESULT)( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPGETPEERNAME)( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +typedef BOOL (WSPAPI * LPWSPGETQOSBYNAME)( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPGETSOCKNAME)( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPGETSOCKOPT)( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT LPINT optlen, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPIOCTL)( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef SOCKET (WSPAPI * LPWSPJOINLEAF)( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPLISTEN)( + IN SOCKET s, + IN INT backlog, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPRECV)( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPRECVDISCONNECT)( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPRECVFROM)( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromlen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSELECT)( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSEND)( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSENDDISCONNECT)( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSENDTO)( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST LPSOCKADDR lpTo, + IN INT iTolen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSETSOCKOPT)( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSHUTDOWN)( + IN SOCKET s, + IN INT how, + OUT LPINT lpErrno); + +typedef SOCKET (WSPAPI * LPWSPSOCKET)( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWSPSTRINGTOADDRESS)( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno); + + +/* Service provider procedure table */ +typedef struct _WSPPROC_TABLE { + LPWSPACCEPT lpWSPAccept; + LPWSPADDRESSTOSTRING lpWSPAddressToString; + LPWSPASYNCSELECT lpWSPAsyncSelect; + LPWSPBIND lpWSPBind; + LPWSPCANCELBLOCKINGCALL lpWSPCancelBlockingCall; + LPWSPCLEANUP lpWSPCleanup; + LPWSPCLOSESOCKET lpWSPCloseSocket; + LPWSPCONNECT lpWSPConnect; + LPWSPDUPLICATESOCKET lpWSPDuplicateSocket; + LPWSPENUMNETWORKEVENTS lpWSPEnumNetworkEvents; + LPWSPEVENTSELECT lpWSPEventSelect; + LPWSPGETOVERLAPPEDRESULT lpWSPGetOverlappedResult; + LPWSPGETPEERNAME lpWSPGetPeerName; + LPWSPGETSOCKNAME lpWSPGetSockName; + LPWSPGETSOCKOPT lpWSPGetSockOpt; + LPWSPGETQOSBYNAME lpWSPGetQOSByName; + LPWSPIOCTL lpWSPIoctl; + LPWSPJOINLEAF lpWSPJoinLeaf; + LPWSPLISTEN lpWSPListen; + LPWSPRECV lpWSPRecv; + LPWSPRECVDISCONNECT lpWSPRecvDisconnect; + LPWSPRECVFROM lpWSPRecvFrom; + LPWSPSELECT lpWSPSelect; + LPWSPSEND lpWSPSend; + LPWSPSENDDISCONNECT lpWSPSendDisconnect; + LPWSPSENDTO lpWSPSendTo; + LPWSPSETSOCKOPT lpWSPSetSockOpt; + LPWSPSHUTDOWN lpWSPShutdown; + LPWSPSOCKET lpWSPSocket; + LPWSPSTRINGTOADDRESS lpWSPStringToAddress; +} WSPPROC_TABLE, FAR* LPWSPPROC_TABLE; + + +/* Prototypes for service provider upcall procedure table */ + +typedef BOOL (WSPAPI * LPWPUCLOSEEVENT)( + IN WSAEVENT hEvent, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWPUCLOSESOCKETHANDLE)( + IN SOCKET s, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWPUCLOSETHREAD)( + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef WSAEVENT (WSPAPI * LPWPUCREATEEVENT)( + OUT LPINT lpErrno); + +typedef SOCKET (WSPAPI * LPWPUCREATESOCKETHANDLE)( + IN DWORD dwCatalogEntryId, + IN DWORD dwContext, + OUT LPINT lpErrno); + +typedef SOCKET (WSPAPI * LPWPUFDISSET)( + IN SOCKET s, + IN LPFD_SET set); + +typedef INT (WSPAPI * LPWPUGETPROVIDERPATH)( + IN LPGUID lpProviderId, + OUT LPWSTR lpszProviderDllPath, + IN OUT LPINT lpProviderDllPathLen, + OUT LPINT lpErrno); + +typedef SOCKET (WSPAPI * LPWPUMODIFYIFSHANDLE)( + IN DWORD dwCatalogEntryId, + IN SOCKET ProposedHandle, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWPUOPENCURRENTTHREAD)( + OUT LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +typedef BOOL (WSPAPI * LPWPUPOSTMESSAGE)( + IN HWND hWnd, + IN UINT Msg, + IN WPARAM wParam, + IN LPARAM lParam); + +typedef INT (WSPAPI * LPWPUQUERYBLOCKINGCALLBACK)( + IN DWORD dwCatalogEntryId, + OUT LPBLOCKINGCALLBACK FAR* lplpfnCallback, + OUT LPDWORD lpdwContext, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWPUQUERYSOCKETHANDLECONTEXT)( + IN SOCKET s, + OUT LPDWORD lpContext, + OUT LPINT lpErrno); + +typedef INT (WSPAPI * LPWPUQUEUEAPC)( + IN LPWSATHREADID lpThreadId, + IN LPWSAUSERAPC lpfnUserApc, + IN DWORD dwContext, + OUT LPINT lpErrno); + +typedef BOOL (WSPAPI * LPWPURESETEVENT)( + IN WSAEVENT hEvent, + OUT LPINT lpErrno); + +typedef BOOL (WSPAPI * LPWPUSETEVENT)( + IN WSAEVENT hEvent, + OUT LPINT lpErrno); + + +/* Available only directly from the DLL */ + +typedef INT (WSPAPI * LPWPUCOMPLETEOVERLAPPEDREQUEST)( + SOCKET s, + LPWSAOVERLAPPED lpOverlapped, + DWORD dwError, + DWORD cbTransferred, + LPINT lpErrno); + + +/* Service Provider upcall table */ + +typedef struct _WSPUPCALLTABLE { + LPWPUCLOSEEVENT lpWPUCloseEvent; + LPWPUCLOSESOCKETHANDLE lpWPUCloseSocketHandle; + LPWPUCREATEEVENT lpWPUCreateEvent; + LPWPUCREATESOCKETHANDLE lpWPUCreateSocketHandle; + LPWPUFDISSET lpWPUFDIsSet; + LPWPUGETPROVIDERPATH lpWPUGetProviderPath; + LPWPUMODIFYIFSHANDLE lpWPUModifyIFSHandle; + LPWPUPOSTMESSAGE lpWPUPostMessage; + LPWPUQUERYBLOCKINGCALLBACK lpWPUQueryBlockingCallback; + LPWPUQUERYSOCKETHANDLECONTEXT lpWPUQuerySocketHandleContext; + LPWPUQUEUEAPC lpWPUQueueApc; + LPWPURESETEVENT lpWPUResetEvent; + LPWPUSETEVENT lpWPUSetEvent; + LPWPUOPENCURRENTTHREAD lpWPUOpenCurrentThread; + LPWPUCLOSETHREAD lpWPUCloseThread; +} WSPUPCALLTABLE, FAR* LPWSPUPCALLTABLE; + + +typedef INT (WSPAPI * LPWSPSTARTUP)( + IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable); + + +/* Prototypes for service provider namespace procedure table */ + +typedef INT (WSPAPI * LPNSPCLEANUP)( + IN LPGUID lpProviderId); + +typedef INT (WSPAPI * LPNSPGETSERVICECLASSINFO)( + IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo); + +typedef INT (WSPAPI * LPNSPINSTALLSERVICECLASS)( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo); + +typedef INT (WSPAPI * LPNSPLOOKUPSERVICEBEGIN)( + IN LPGUID lpProviderId, + IN LPWSAQUERYSETW lpqsRestrictions, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN DWORD dwControlFlags, + OUT LPHANDLE lphLookup); + +typedef INT (WSPAPI * LPNSPLOOKUPSERVICEEND)( + IN HANDLE hLookup); + +typedef INT (WSPAPI * LPNSPLOOKUPSERVICENEXT)( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSET lpqsResults); + +typedef INT (WSPAPI * LPNSPREMOVESERVICECLASS)( + IN LPGUID lpProviderId, + IN LPGUID lpServiceClassId); + +typedef INT (WSPAPI * LPNSPSETSERVICE)( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags); + + +typedef struct _NSP_ROUTINE { + DWORD cbSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + LPNSPCLEANUP NSPCleanup; + LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin; + LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext; + LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd; + LPNSPSETSERVICE NSPSetService; + LPNSPINSTALLSERVICECLASS NSPInstallServiceClass; + LPNSPREMOVESERVICECLASS NSPRemoveServiceClass; + LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo; +} NSP_ROUTINE, *PNSP_ROUTINE, *LPNSP_ROUTINE; + + +INT +WSPAPI +NSPStartup( + IN LPGUID lpProviderId, + OUT LPNSP_ROUTINE lpNspRoutines); + + +/* WinSock 2 DLL function prototypes */ + +INT +WSPAPI +WPUCompleteOverlappedRequest( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + IN DWORD dwError, + IN DWORD cbTransferred, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPStartup( + IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable); + +INT +WSPAPI +WSCDeinstallProvider( + IN LPGUID lpProviderId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSCEnumProtocols( + IN LPINT lpiProtocols, + OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength, + OUT LPINT lpErrno); + +INT +WSPAPI +WSCGetProviderPath( + IN LPGUID lpProviderId, + OUT LPWSTR lpszProviderDllPath, + IN OUT LPINT lpProviderDllPathLen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSCInstallProvider( + IN CONST LPGUID lpProviderId, + IN CONST LPWSTR lpszProviderDllPath, + IN CONST LPWSAPROTOCOL_INFOW lpProtocolInfoList, + IN DWORD dwNumberOfEntries, + OUT LPINT lpErrno); + +INT +WSPAPI +WSCEnableNSProvider( + IN LPGUID lpProviderId, + IN BOOL fEnable); + +INT +WSPAPI +WSCInstallNameSpace( + IN LPWSTR lpszIdentifier, + IN LPWSTR lpszPathName, + IN DWORD dwNameSpace, + IN DWORD dwVersion, + IN LPGUID lpProviderId); + +INT +WSPAPI +WSCUnInstallNameSpace( + IN LPGUID lpProviderId); + +INT +WSPAPI +WSCWriteProviderOrder( + IN LPDWORD lpwdCatalogEntryId, + IN DWORD dwNumberOfEntries); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* __WS2SPI_H */ + +/* EOF */ diff --git a/include/wsahelp.h b/include/wsahelp.h new file mode 100644 index 0000000..e1e1b4d --- /dev/null +++ b/include/wsahelp.h @@ -0,0 +1,349 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 DLL + * FILE: include/wsahelp.h + * PURPOSE: Header file for the WinSock 2 DLL + * and WinSock 2 Helper DLLs + */ +#ifndef __WSAHELP_H +#define __WSAHELP_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define WSH_NOTIFY_BIND 0x00000001 +#define WSH_NOTIFY_LISTEN 0x00000002 +#define WSH_NOTIFY_CONNECT 0x00000004 +#define WSH_NOTIFY_ACCEPT 0x00000008 +#define WSH_NOTIFY_SHUTDOWN_RECEIVE 0x00000010 +#define WSH_NOTIFY_SHUTDOWN_SEND 0x00000020 +#define WSH_NOTIFY_SHUTDOWN_ALL 0x00000040 +#define WSH_NOTIFY_CLOSE 0x00000080 +#define WSH_NOTIFY_CONNECT_ERROR 0x00000100 + +#define SOL_INTERNAL 0xFFFE + +#define SO_CONTEXT 1 + +typedef enum _SOCKADDR_ADDRESS_INFO { + SockaddrAddressInfoNormal, + SockaddrAddressInfoWildcard, + SockaddrAddressInfoBroadcast, + SockaddrAddressInfoLoopback +} SOCKADDR_ADDRESS_INFO, *PSOCKADDR_ADDRESS_INFO; + +typedef enum _SOCKADDR_ENDPOINT_INFO { + SockaddrEndpointInfoNormal, + SockaddrEndpointInfoWildcard, + SockaddrEndpointInfoReserved, +} SOCKADDR_ENDPOINT_INFO, *PSOCKADDR_ENDPOINT_INFO; + + +typedef struct _WINSOCK_MAPPING { + DWORD Rows; + DWORD Columns; + struct { + DWORD AddressFamily; + DWORD SocketType; + DWORD Protocol; + } Mapping[1]; +} WINSOCK_MAPPING, *PWINSOCK_MAPPING; + + +typedef struct _SOCKADDR_INFO { + SOCKADDR_ADDRESS_INFO AddressInfo; + SOCKADDR_ENDPOINT_INFO EndpointInfo; +} SOCKADDR_INFO, *PSOCKADDR_INFO; + + +INT +WINAPI +WSHAddressToString( + IN LPSOCKADDR Address, + IN INT AddressLength, + IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, + OUT LPWSTR AddressString, + IN OUT LPDWORD AddressStringLength); + +INT +WINAPI +WSHEnumProtocols( + IN LPINT lpiProtocols OPTIONAL, + IN LPWSTR lpTransportKeyName, + IN OUT LPVOID lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength); + +INT +WINAPI +WSHGetBroadcastSockaddr( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength); + +INT +WINAPI +WSHGetProviderGuid( + IN LPWSTR ProviderName, + OUT LPGUID ProviderGuid); + +INT +WINAPI +WSHGetSockaddrType( + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + OUT PSOCKADDR_INFO SockaddrInfo); + +INT +WINAPI +WSHGetSocketInformation( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + OUT PCHAR OptionValue, + OUT INT OptionLength); + +INT +WINAPI +WSHGetWildcardSockaddr( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength); + +DWORD +WINAPI +WSHGetWinsockMapping( + OUT PWINSOCK_MAPPING Mapping, + IN DWORD MappingLength); + +INT +WINAPI +WSHGetWSAProtocolInfo( + IN LPWSTR ProviderName, + OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, + OUT LPDWORD ProtocolInfoEntries); + +INT +WINAPI +WSHIoctl( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD IoControlCode, + IN LPVOID InputBuffer, + IN DWORD InputBufferLength, + IN LPVOID OutputBuffer, + IN DWORD OutputBufferLength, + OUT LPDWORD NumberOfBytesReturned, + IN LPWSAOVERLAPPED Overlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, + OUT LPBOOL NeedsCompletion); + +INT +WINAPI +WSHJoinLeaf( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN PVOID LeafHelperDllSocketContext, + IN SOCKET LeafSocketHandle, + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + IN LPWSABUF CallerData, + IN LPWSABUF CalleeData, + IN LPQOS SocketQOS, + IN LPQOS GroupQOS, + IN DWORD Flags); + +INT +WINAPI +WSHNotify( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD NotifyEvent); + +INT +WINAPI +WSHOpenSocket( + IN OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID HelperDllSocketContext, + OUT PDWORD NotificationEvents); + +INT +WINAPI +WSHOpenSocket2( + OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + IN GROUP Group, + IN DWORD Flags, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID *HelperDllSocketContext, + OUT PDWORD NotificationEvents); + +INT +WINAPI +WSHSetSocketInformation( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + IN PCHAR OptionValue, + IN INT OptionLength); + +INT +WINAPI +WSHStringToAddress( + IN LPWSTR AddressString, + IN DWORD AddressFamily, + IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, + OUT LPSOCKADDR Address, + IN OUT LPDWORD AddressStringLength); + + + +typedef INT (WINAPI * PWSH_ADDRESS_TO_STRING)( + IN LPSOCKADDR Address, + IN INT AddressLength, + IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, + OUT LPWSTR AddressString, + IN OUT LPDWORD AddressStringLength); + +typedef INT (WINAPI * PWSH_ENUM_PROTOCOLS)( + IN LPINT lpiProtocols OPTIONAL, + IN LPWSTR lpTransportKeyName, + IN OUT LPVOID lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength); + +typedef INT (WINAPI * PWSH_GET_BROADCAST_SOCKADDR)( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength); + +typedef INT (WINAPI * PWSH_GET_PROVIDER_GUID)( + IN LPWSTR ProviderName, + OUT LPGUID ProviderGuid); + +typedef INT (WINAPI * PWSH_GET_SOCKADDR_TYPE)( + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + OUT PSOCKADDR_INFO SockaddrInfo); + +typedef INT (WINAPI * PWSH_GET_SOCKET_INFORMATION)( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + OUT PCHAR OptionValue, + OUT INT OptionLength); + +typedef INT (WINAPI * PWSH_GET_WILDCARD_SOCKEADDR)( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength); + +typedef DWORD (WINAPI * PWSH_GET_WINSOCK_MAPPING)( + OUT PWINSOCK_MAPPING Mapping, + IN DWORD MappingLength); + +typedef INT (WINAPI * PWSH_GET_WSAPROTOCOL_INFO)( + IN LPWSTR ProviderName, + OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, + OUT LPDWORD ProtocolInfoEntries); + +typedef INT (WINAPI * PWSH_IOCTL)( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD IoControlCode, + IN LPVOID InputBuffer, + IN DWORD InputBufferLength, + IN LPVOID OutputBuffer, + IN DWORD OutputBufferLength, + OUT LPDWORD NumberOfBytesReturned, + IN LPWSAOVERLAPPED Overlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, + OUT LPBOOL NeedsCompletion); + +typedef INT (WINAPI * PWSH_JOIN_LEAF)( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN PVOID LeafHelperDllSocketContext, + IN SOCKET LeafSocketHandle, + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + IN LPWSABUF CallerData, + IN LPWSABUF CalleeData, + IN LPQOS SocketQOS, + IN LPQOS GroupQOS, + IN DWORD Flags); + +typedef INT (WINAPI * PWSH_NOTIFY)( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD NotifyEvent); + +typedef INT (WINAPI * PWSH_OPEN_SOCKET)( + IN OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID HelperDllSocketContext, + OUT PDWORD NotificationEvents); + +typedef INT (WINAPI * PWSH_OPEN_SOCKET2)( + OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + IN GROUP Group, + IN DWORD Flags, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID *HelperDllSocketContext, + OUT PDWORD NotificationEvents); + +typedef INT (WINAPI * PWSH_SET_SOCKET_INFORMATION)( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + IN PCHAR OptionValue, + IN INT OptionLength); + +typedef INT (WINAPI * PWSH_STRING_TO_ADDRESS)( + IN LPWSTR AddressString, + IN DWORD AddressFamily, + IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL, + OUT LPSOCKADDR Address, + IN OUT LPDWORD AddressStringLength); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* __WSAHELP_H */ + +/* EOF */ diff --git a/install-system.sh b/install-system.sh new file mode 100644 index 0000000..1791cf4 --- /dev/null +++ b/install-system.sh @@ -0,0 +1 @@ +cp -rv reactos $1/ diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..0912556 --- /dev/null +++ b/install.bat @@ -0,0 +1,129 @@ +@echo off +if "%1" == "" goto NoParameter +set ROS_INSTALL=%1 +goto Install +:NoParameter +set ROS_INSTALL=c:\reactos +:Install +echo on +echo Installing to %ROS_INSTALL% +@echo off + +md %ROS_INSTALL% +md %ROS_INSTALL%\bin +md %ROS_INSTALL%\symbols +md %ROS_INSTALL%\system32 +md %ROS_INSTALL%\system32\config +md %ROS_INSTALL%\system32\drivers +md %ROS_INSTALL%\media +md %ROS_INSTALL%\media\fonts +copy boot.bat %ROS_INSTALL% +copy bootc.lst %ROS_INSTALL% +copy aboot.bat %ROS_INSTALL% +copy system.hiv %ROS_INSTALL%\system32\config +copy loaders\dos\loadros.com %ROS_INSTALL% +copy ntoskrnl\ntoskrnl.exe %ROS_INSTALL%\system32 +copy ntoskrnl\ntoskrnl.sym %ROS_INSTALL%\symbols +copy hal\halx86\hal.dll %ROS_INSTALL%\system32 +copy drivers\fs\vfat\vfatfs.sys %ROS_INSTALL%\system32\drivers +copy drivers\fs\cdfs\cdfs.sys %ROS_INSTALL%\system32\drivers +copy drivers\fs\fs_rec\fs_rec.sys %ROS_INSTALL%\system32\drivers +copy drivers\fs\ms\msfs.sys %ROS_INSTALL%\system32\drivers +copy drivers\fs\np\npfs.sys %ROS_INSTALL%\system32\drivers +copy drivers\fs\ntfs\ntfs.sys %ROS_INSTALL%\system32\drivers +copy drivers\fs\mup\mup.sys %ROS_INSTALL%\system32\drivers +copy drivers\bus\acpi\acpi.sys %ROS_INSTALL%\system32\drivers +copy drivers\bus\isapnp\isapnp.sys %ROS_INSTALL%\system32\drivers +copy drivers\bus\pci\pci.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\ide\ide.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\floppy\floppy.sys %ROS_INSTALL%\system32\drivers +copy drivers\input\keyboard\keyboard.sys %ROS_INSTALL%\system32\drivers +copy drivers\input\mouclass\mouclass.sys %ROS_INSTALL%\system32\drivers +copy drivers\input\psaux\psaux.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\blue\blue.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\beep\beep.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\null\null.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\serial\serial.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\serenum\serenum.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\vga\miniport\vgamp.sys %ROS_INSTALL%\system32\drivers +copy drivers\dd\vga\display\vgaddi.dll %ROS_INSTALL%\system32\drivers +copy drivers\dd\vidport\vidport.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\afd\afd.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\dd\ne2000\ne2000.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\dd\miniport\nscirda\nscirda.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\ndis\ndis.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\packet\packet.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\tcpip\tcpip.sys %ROS_INSTALL%\system32\drivers +copy drivers\net\wshtcpip\wshtcpip.dll %ROS_INSTALL%\system32 +copy drivers\storage\atapi\atapi.sys %ROS_INSTALL%\system32\drivers +copy drivers\storage\scsiport\scsiport.sys %ROS_INSTALL%\system32\drivers +copy drivers\storage\cdrom\cdrom.sys %ROS_INSTALL%\system32\drivers +copy drivers\storage\disk\disk.sys %ROS_INSTALL%\system32\drivers +copy drivers\storage\class2\class2.sys %ROS_INSTALL%\system32\drivers +copy subsys\system\autochk\autochk.exe %ROS_INSTALL%\system32 +copy subsys\system\gstart\gstart.exe %ROS_INSTALL%\system32 +copy subsys\system\shell\shell.exe %ROS_INSTALL%\system32 +copy subsys\system\winlogon\winlogon.exe %ROS_INSTALL%\system32 +copy subsys\system\services\services.exe %ROS_INSTALL%\system32 +copy services\eventlog\eventlog.exe %ROS_INSTALL%\system32 +copy services\rpcss\rpcss.exe %ROS_INSTALL%\system32 +copy lib\advapi32\advapi32.dll %ROS_INSTALL%\system32 +copy lib\crtdll\crtdll.dll %ROS_INSTALL%\system32 +copy lib\fmifs\fmifs.dll %ROS_INSTALL%\system32 +copy lib\gdi32\gdi32.dll %ROS_INSTALL%\system32 +copy lib\iphlpapi\iphlpapi.dll %ROS_INSTALL%\system32 +copy lib\kernel32\kernel32.dll %ROS_INSTALL%\system32 +copy lib\libpcap\libpcap.dll %ROS_INSTALL%\system32 +copy lib\msafd\msafd.dll %ROS_INSTALL%\system32 +copy lib\msvcrt\msvcrt.dll %ROS_INSTALL%\system32 +copy lib\ntdll\ntdll.dll %ROS_INSTALL%\system32 +copy lib\packet\packet.dll %ROS_INSTALL%\system32 +copy lib\secur32\secur32.dll %ROS_INSTALL%\system32 +copy lib\shell32\roshel32.dll %ROS_INSTALL%\system32 +copy lib\snmpapi\snmpapi.dll %ROS_INSTALL%\system32 +copy lib\user32\user32.dll %ROS_INSTALL%\system32 +copy lib\winmm\winmm.dll %ROS_INSTALL%\system32 +copy lib\ws2_32\ws2_32.dll %ROS_INSTALL%\system32 +copy lib\ws2help\ws2help.dll %ROS_INSTALL%\system32 +copy lib\wshirda\wshirda.dll %ROS_INSTALL%\system32 +copy lib\wsock32\wsock32.dll %ROS_INSTALL%\system32 +copy subsys\smss\smss.exe %ROS_INSTALL%\system32 +copy subsys\csrss\csrss.exe %ROS_INSTALL%\system32 +copy subsys\win32k\win32k.sys %ROS_INSTALL%\system32\drivers +copy apps\utils\cat\cat.exe %ROS_INSTALL%\bin +copy apps\utils\partinfo\partinfo.exe %ROS_INSTALL%\bin +copy apps\utils\objdir\objdir.exe %ROS_INSTALL%\bin +copy apps\utils\pice\module\pice.sys %ROS_INSTALL%\system32\drivers +copy apps\utils\pice\module\pice.sym %ROS_INSTALL%\symbols +copy apps\utils\pice\pice.cfg %ROS_INSTALL%\symbols +copy apps\tests\hello\hello.exe %ROS_INSTALL%\bin +copy apps\tests\args\args.exe %ROS_INSTALL%\bin +copy apps\tests\apc\apc.exe %ROS_INSTALL%\bin +copy apps\tests\shm\shmsrv.exe %ROS_INSTALL%\bin +copy apps\tests\shm\shmclt.exe %ROS_INSTALL%\bin +copy apps\tests\lpc\lpcsrv.exe %ROS_INSTALL%\bin +copy apps\tests\lpc\lpcclt.exe %ROS_INSTALL%\bin +copy apps\tests\thread\thread.exe %ROS_INSTALL%\bin +copy apps\tests\event\event.exe %ROS_INSTALL%\bin +copy apps\tests\file\file.exe %ROS_INSTALL%\bin +copy apps\tests\pteb\pteb.exe %ROS_INSTALL%\bin +copy apps\tests\consume\consume.exe %ROS_INSTALL%\bin +copy apps\tests\vmtest\vmtest.exe %ROS_INSTALL%\bin +copy apps\tests\gditest\gditest.exe %ROS_INSTALL%\bin +copy apps\tests\dibtest\dibtest.exe %ROS_INSTALL%\bin +copy apps\tests\mstest\msserver.exe %ROS_INSTALL%\bin +copy apps\tests\mstest\msclient.exe %ROS_INSTALL%\bin +copy apps\tests\nptest\npserver.exe %ROS_INSTALL%\bin +copy apps\tests\nptest\npclient.exe %ROS_INSTALL%\bin +copy apps\tests\atomtest\atomtest.exe %ROS_INSTALL%\bin +copy apps\tests\mutex\mutex.exe %ROS_INSTALL%\bin +copy apps\tests\winhello\winhello.exe %ROS_INSTALL%\bin +copy apps\tests\sectest\sectest.exe %ROS_INSTALL%\bin +copy apps\tests\isotest\isotest.exe %ROS_INSTALL%\bin +copy apps\tests\regtest\regtest.exe %ROS_INSTALL%\bin +copy apps\tests\restest\restest.exe %ROS_INSTALL%\bin +copy apps\tests\tokentest\tokentest.exe %ROS_INSTALL%\bin +copy media\fonts\helb____.ttf %ROS_INSTALL%\media\fonts +copy media\fonts\timr____.ttf %ROS_INSTALL%\media\fonts +copy media\nls\*.nls %ROS_INSTALL%\system32 +copy ntoskrnl\ntoskrnl.map %ROS_INSTALL%\symbols diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..345e63b --- /dev/null +++ b/install.sh @@ -0,0 +1 @@ +./install-system.sh $1 diff --git a/installwine.bat b/installwine.bat new file mode 100644 index 0000000..ea48521 --- /dev/null +++ b/installwine.bat @@ -0,0 +1,61 @@ +@echo off +REM +REM created by sedwards 11/11/01 +REM +if "%1" == "" goto NoParameter +set WINE_INSTALL=%1 +goto Install +:NoParameter +set WINE_INSTALL=c:\reactos\system32 +set ROS_INSTALL=c:\reactos +:Install +echo Installing dlls to %WINE_INSTALL% +@echo off +copy ..\wine\dlls\comctl32\comctl32.dll %WINE_INSTALL% +copy ..\wine\dlls\commdlg\comdlg32.dll %WINE_INSTALL% +copy ..\wine\dlls\ddraw\ddraw.dll %WINE_INSTALL% +copy ..\wine\dlls\dinput\dinput.dll %WINE_INSTALL% +copy ..\wine\dlls\dplay\dplay.dll %WINE_INSTALL% +copy ..\wine\dlls\dplayx\dplayx.dll %WINE_INSTALL% +copy ..\wine\dlls\mapi32\mapi32.dll %WINE_INSTALL% +copy ..\wine\dlls\ole32\ole32.dll %WINE_INSTALL% +copy ..\wine\dlls\oleaut32\oleaut32.dll %WINE_INSTALL% +copy ..\wine\dlls\olecli\olecli32.dll %WINE_INSTALL% +copy ..\wine\dlls\oledlg\oledlg.dll %WINE_INSTALL% +copy ..\wine\dlls\olepro32\olepro32.dll %WINE_INSTALL% +copy ..\wine\dlls\olesvr\olesvr32.dll %WINE_INSTALL% +copy ..\wine\dlls\psapi\psapi.dll %WINE_INSTALL% +copy ..\wine\dlls\richedit\riched32.dll %WINE_INSTALL% +copy ..\wine\dlls\rpcrt4\rpcrt4.dll %WINE_INSTALL% +copy ..\wine\dlls\serialui\serialui.dll %WINE_INSTALL% +copy ..\wine\dlls\shdocvw\shdocvw.dll %WINE_INSTALL% +copy ..\wine\dlls\shell32\shell32.dll %WINE_INSTALL% +copy ..\wine\dlls\shfolder\shfolder.dll %WINE_INSTALL% +copy ..\wine\dlls\shlwapi\shlwapi.dll %WINE_INSTALL% +copy ..\wine\dlls\tapi32\tapi32.dll %WINE_INSTALL% +copy ..\wine\dlls\urlmon\urlmon.dll %WINE_INSTALL% +copy ..\wine\dlls\wintrust\wintrust.dll %WINE_INSTALL% +REM +echo Installing winelib programs to %ROS_INSTALL%\bin +REM +copy ..\wine\programs\clock\winclock.exe %ROS_INSTALL%\bin +copy ..\wine\programs\cmdlgtst\cmdlgtst.exe %ROS_INSTALL%\bin +copy ..\wine\programs\control\control.exe %ROS_INSTALL%\bin +copy ..\wine\programs\notepad\notepad.exe %ROS_INSTALL%\bin +copy ..\wine\programs\progman\progman.exe %ROS_INSTALL%\bin +copy ..\wine\programs\uninstaller\uninstaller.exe %ROS_INSTALL%\bin +copy ..\wine\programs\view\view.exe %ROS_INSTALL%\bin +copy ..\wine\programs\wcmd\wcmd.exe %ROS_INSTALL%\bin +copy ..\wine\programs\winefile\winefile.exe %ROS_INSTALL%\bin +copy ..\wine\programs\winemine\winmine.exe %ROS_INSTALL%\bin +copy ..\wine\programs\winver\winver.exe %ROS_INSTALL%\bin +REM +echo Installing Regression tests to %ROS_INSTALL%\bin +copy ..\wine\dlls\advapi32\tests\advapi32_test.exe %WINE_INSTALL% +copy ..\wine\dlls\kernel\tests\kernel32_test.exe %WINE_INSTALL% +copy ..\wine\dlls\ntdll\tests\ntdll_test.exe %WINE_INSTALL% +copy ..\wine\dlls\user32\tests\user32_test.exe %WINE_INSTALL% +REM + + + diff --git a/lib/advapi32/.cvsignore b/lib/advapi32/.cvsignore new file mode 100644 index 0000000..5550cf6 --- /dev/null +++ b/lib/advapi32/.cvsignore @@ -0,0 +1,9 @@ +advapi32.a +advapi32.dll +advapi32.nostrip.dll +advapi32.lib +advapi32.coff +base.tmp +junk.tmp +temp.exp + diff --git a/lib/advapi32/advapi32.def b/lib/advapi32/advapi32.def new file mode 100644 index 0000000..da13cbc --- /dev/null +++ b/lib/advapi32/advapi32.def @@ -0,0 +1,411 @@ +; $Id$ +; +; advapi32.def +; +; ReactOS Operating System +; +; Some stack sizes are taken from Ander Norlander's .DEFs. +; +LIBRARY advapi32.dll +EXPORTS +AbortSystemShutdownA@4 +AbortSystemShutdownW@4 +AccessCheck@32 +AccessCheckAndAuditAlarmA@44 +AccessCheckAndAuditAlarmW@44 +AddAccessAllowedAce@16 +AddAccessDeniedAce@16 +AddAce@20 +AddAuditAccessAce@24 +AdjustTokenGroups@24 +AdjustTokenPrivileges@24 +AllocateAndInitializeSid@44 +AllocateLocallyUniqueId@4 +AreAllAccessesGranted@8 +AreAnyAccessesGranted@8 +BackupEventLogA@8 +BackupEventLogW@8 +BuildAccessRequestA@12 +BuildAccessRequestW@12 +BuildExplicitAccessWithNameA@20 +BuildExplicitAccessWithNameW@20 +BuildImpersonateExplicitAccessWithNameA@24 +BuildImpersonateExplicitAccessWithNameW@24 +BuildImpersonateTrusteeA@8 +BuildImpersonateTrusteeW@8 +BuildSecurityDescriptorA@36 +BuildSecurityDescriptorW@36 +BuildTrusteeWithNameA@8 +BuildTrusteeWithNameW@8 +BuildTrusteeWithSidA@8 +BuildTrusteeWithSidW@8 +ChangeServiceConfigA@44 +ChangeServiceConfigW@44 +ClearEventLogA@8 +ClearEventLogW@8 +ClearEventLogA@8 +CloseServiceHandle@4 +ControlService@12 +CopySid@12 +CreatePrivateObjectSecurity@24 +CreateProcessAsUserA@44 +CreateProcessAsUserW@44 +CreateServiceA@52 +CreateServiceW@52 +CryptAcquireContextA@20 +CryptAcquireContextW@20 +CryptCreateHash@20 +CryptDecrypt@24 +CryptDeriveKey@20 +CryptDestroyHash@4 +CryptDestroyKey@4 +CryptEncrypt@28 +CryptExportKey@24 +CryptGenKey@16 +CryptGenRandom@12 +CryptGetHashParam@20 +CryptGetKeyParam@20 +CryptGetProvParam@20 +CryptGetUserKey@12 +CryptHashData@16 +CryptHashSessionKey@12 +CryptImportKey@24 +CryptReleaseContext@8 +CryptSetHashParam@16 +CryptSetKeyParam@16 +CryptSetProvParam@16 +CryptSetProviderA@8 +CryptSetProviderW@8 +CryptSignHashA@24 +CryptSignHashW@24 +CryptVerifySignatureA@24 +CryptVerifySignatureW@24 +DeleteAce@8 +DeleteService@4 +DenyAccessRightsA +DenyAccessRightsW +DeregisterEventSource@4 +DestroyPrivateObjectSecurity@4 +DuplicateToken@12 +DuplicateTokenEx@24 +ElfBackupEventLogFileA@8 +ElfBackupEventLogFileW@8 +ElfChangeNotify@8 +ElfClearEventLogFileA@8 +ElfClearEventLogFileW@8 +ElfCloseEventLog@4 +ElfDeregisterEventSource@4 +ElfNumberOfRecords@8 +ElfOldestRecord@8 +ElfOpenBackupEventLogA@12 +ElfOpenBackupEventLogW@12 +ElfOpenEventLogA@12 +ElfOpenEventLogW@12 +ElfReadEventLogA@28 +ElfReadEventLogW@28 +ElfRegisterEventSourceA@12 +ElfRegisterEventSourceW@12 +ElfReportEventA@48 +ElfReportEventW@48 +EnumDependentServicesA@24 +EnumDependentServicesW@24 +EnumServiceGroupW@36 +EnumServicesStatusA@32 +EnumServicesStatusW@32 +EqualPrefixSid@8 +EqualSid@8 +FindFirstFreeAce@8 +FreeSid@4 +GetAce@12 +GetAclInformation@16 +GetAuditedPermissionsFromAclA@16 +GetAuditedPermissionsFromAclW@16 +GetAuditedPermissionsFromSDA@16 +GetAuditedPermissionsFromSDW@16 +GetCurrentHwProfileA@4 +GetCurrentHwProfileW@4 +GetEffectiveAccessRightsA@16 +GetEffectiveAccessRightsW@16 +GetEffectiveRightsFromAclA@12 +GetEffectiveRightsFromAclW@12 +GetEffectiveRightsFromSDA@12 +GetEffectiveRightsFromSDW@12 +GetExplicitAccessRightsA@16 +GetExplicitAccessRightsW@16 +GetExplicitEntriesFromAclA@12 +GetExplicitEntriesFromAclW@12 +GetFileSecurityA@20 +GetFileSecurityW@20 +GetKernelObjectSecurity@20 +GetLengthSid@4 +GetMultipleTrusteeA@4 +GetMultipleTrusteeOperationA@4 +GetMultipleTrusteeOperationW@4 +GetMultipleTrusteeW@4 +GetNamedSecurityInfoA@32 +GetNamedSecurityInfoW@32 +GetNumberOfEventLogRecords@8 +GetOldestEventLogRecord@8 +GetPrivateObjectSecurity@20 +GetSecurityDescriptorControl@12 +GetSecurityDescriptorDacl@16 +GetSecurityDescriptorGroup@12 +GetSecurityDescriptorLength@4 +GetSecurityDescriptorOwner@12 +GetSecurityDescriptorSacl@16 +GetSecurityInfo@32 +GetServiceDisplayNameA@16 +GetServiceDisplayNameW@16 +GetServiceKeyNameA@16 +GetServiceKeyNameW@16 +GetSidIdentifierAuthority@4 +GetSidLengthRequired@4 +GetSidSubAuthority@8 +GetSidSubAuthorityCount@4 +GetTokenInformation@20 +GetTrusteeForm@4 +GetTrusteeNameA@4 +GetTrusteeNameW@4 +GetTrusteeTypeA@4 +GetTrusteeTypeW@4 +GetUserNameA@8 +GetUserNameW@8 +GrantAccessRightsA@16 +GrantAccessRightsW@16 +I_ScGetCurrentGroupStateW@12 +I_ScSetServiceBitsA@20 +I_ScSetServiceBitsW@20 +ImpersonateLoggedOnUser@4 +ImpersonateNamedPipeClient@4 +ImpersonateSelf@4 +InitializeAcl@12 +InitializeSecurityDescriptor@8 +InitializeSid@12 +InitiateSystemShutdownA@20 +InitiateSystemShutdownW@20 +IsAccessPermittedA@20 +IsAccessPermittedW@20 +IsTextUnicode@12 +IsValidAcl@4 +IsValidSecurityDescriptor@4 +IsValidSid@4 +LockServiceDatabase@4 +LogonUserA@24 +LogonUserW@24 +LookupAccountNameA@28 +LookupAccountNameW@28 +LookupAccountSidA@28 +LookupAccountSidW@28 +LookupPrivilegeDisplayNameA@20 +LookupPrivilegeDisplayNameW@20 +LookupPrivilegeNameA@16 +LookupPrivilegeNameW@16 +LookupPrivilegeValueA@12 +LookupPrivilegeValueW@12 +LookupSecurityDescriptorPartsA@28 +LookupSecurityDescriptorPartsW@28 +LsaAddAccountRights@16 +LsaAddPrivilegesToAccount@8 +LsaClearAuditLog@4 +LsaClose@4 +LsaCreateAccount@16 +LsaCreateSecret@16 +LsaCreateTrustedDomain@16 +LsaDelete@4 +LsaDeleteTrustedDomain@8 +LsaEnumerateAccountRights@16 +LsaEnumerateAccounts@20 +LsaEnumerateAccountsWithUserRight@16 +LsaEnumeratePrivileges@20 +LsaEnumeratePrivilegesOfAccount@8 +LsaEnumerateTrustedDomains@20 +LsaFreeMemory@4 +LsaGetQuotasForAccount@8 +LsaGetSystemAccessAccount@8 +LsaGetUserName@8 +LsaICLookupNames@28 +LsaICLookupSids@28 +LsaLookupNames@20 +LsaLookupPrivilegeDisplayName@16 +LsaLookupPrivilegeName@12 +LsaLookupPrivilegeValue@12 +LsaLookupSids@20 +LsaNtStatusToWinError@4 +LsaOpenAccount@16 +LsaOpenPolicy@16 +LsaOpenSecret@16 +LsaOpenTrustedDomain@16 +LsaQueryInfoTrustedDomain@12 +LsaQueryInformationPolicy@12 +LsaQuerySecret@20 +LsaQuerySecurityObject@12 +LsaQueryTrustedDomainInfo@16 +LsaRemoveAccountRights@20 +LsaRemovePrivilegesFromAccount@12 +LsaRetrievePrivateData@12 +LsaSetInformationPolicy@12 +LsaSetInformationTrustedDomain@12 +LsaSetQuotasForAccount@8 +LsaSetSecret@12 +LsaSetSecurityObject@12 +LsaSetSystemAccessAccount@8 +LsaSetTrustedDomainInformation@16 +LsaStorePrivateData@12 +MakeAbsoluteSD@44 +MakeSelfRelativeSD@12 +MapGenericMask@8 +NTAccessMaskToProvAccessRights@12 +NotifyBootConfigStatus@4 +NotifyChangeEventLog@8 +ObjectCloseAuditAlarmA@12 +ObjectCloseAuditAlarmW@12 +ObjectDeleteAuditAlarmA@12 +ObjectDeleteAuditAlarmW@12 +ObjectOpenAuditAlarmA@48 +ObjectOpenAuditAlarmW@48 +ObjectPrivilegeAuditAlarmA@24 +ObjectPrivilegeAuditAlarmW@24 +OpenBackupEventLogA@8 +OpenBackupEventLogW@8 +OpenEventLogA@8 +OpenEventLogW@8 +OpenProcessToken@12 +OpenSCManagerA@12 +OpenSCManagerW@12 +OpenServiceA@12 +OpenServiceW@12 +OpenThreadToken@16 +PrivilegeCheck@12 +PrivilegedServiceAuditAlarmA@20 +PrivilegedServiceAuditAlarmW@20 +ProvAccessRightsToNTAccessMask@8 +QueryServiceConfigA@16 +QueryServiceConfigW@16 +QueryServiceLockStatusA@16 +QueryServiceLockStatusW@16 +QueryServiceObjectSecurity@20 +QueryServiceStatus@8 +QueryWindows31FilesMigration@4 +ReadEventLogA@28 +ReadEventLogW@28 +RegCloseKey@4 +RegConnectRegistryA@12 +RegConnectRegistryW@12 +RegCreateKeyA@12 +RegCreateKeyExA@36 +RegCreateKeyExW@36 +RegCreateKeyW@12 +RegDeleteKeyA@8 +RegDeleteKeyW@8 +RegDeleteValueA@8 +RegDeleteValueW@8 +RegEnumKeyA@16 +RegEnumKeyExA@32 +RegEnumKeyExW@32 +RegEnumKeyW@16 +RegEnumValueA@32 +RegEnumValueW@32 +RegFlushKey@4 +RegGetKeySecurity@16 +RegLoadKeyA@12 +RegLoadKeyW@12 +RegNotifyChangeKeyValue@20 +RegOpenKeyA@12 +RegOpenKeyExA@20 +RegOpenKeyExW@20 +RegOpenKeyW@12 +RegQueryInfoKeyA@48 +RegQueryInfoKeyW@48 +RegQueryMultipleValuesA@20 +RegQueryMultipleValuesW@20 +RegQueryValueA@16 +RegQueryValueExA@24 +RegQueryValueExW@24 +RegQueryValueW@16 +RegReplaceKeyA@16 +RegReplaceKeyW@16 +RegRestoreKeyA@12 +RegRestoreKeyW@12 +RegSaveKeyA@12 +RegSaveKeyW@12 +RegSetKeySecurity@12 +RegSetValueA@20 +RegSetValueExA@24 +RegSetValueExW@24 +RegSetValueW@20 +RegUnLoadKeyA@8 +RegUnLoadKeyW@8 +RegisterEventSourceA@8 +RegisterEventSourceW@8 +RegisterServiceCtrlHandlerA@8 +RegisterServiceCtrlHandlerW@8 +ReplaceAllAccessRightsA +ReplaceAllAccessRightsW +ReportEventA@36 +ReportEventW@36 +RevertToSelf@0 +RevokeExplicitAccessRightsA@16 +RevokeExplicitAccessRightsW@16 +SetAccessRightsA@16 +SetAccessRightsW@16 +SetAclInformation@16 +SetEntriesInAclA@16 +SetEntriesInAclA@16 +SetFileSecurityA@12 +SetFileSecurityW@12 +SetKernelObjectSecurity@12 +SetNamedSecurityInfoA@28 +SetNamedSecurityInfoW@28 +SetPrivateObjectSecurity@20 +SetSecurityDescriptorDacl@16 +SetSecurityDescriptorGroup@12 +SetSecurityDescriptorOwner@12 +SetSecurityDescriptorSacl@16 +SetSecurityInfo@28 +SetServiceBits@16 +SetServiceObjectSecurity@12 +SetServiceStatus@8 +SetThreadToken@8 +SetTokenInformation@16 +StartServiceA@12 +StartServiceCtrlDispatcherA@4 +StartServiceCtrlDispatcherW@4 +StartServiceW@12 +SynchronizeWindows31FilesAndWindowsNTRegistry@16 +SystemFunction001@12 +SystemFunction002@12 +SystemFunction003@8 +SystemFunction004@12 +SystemFunction005@12 +SystemFunction006@8 +SystemFunction007@8 +SystemFunction008@12 +SystemFunction009@12 +SystemFunction010@12 +SystemFunction011@12 +SystemFunction012@12 +SystemFunction013@12 +SystemFunction014@12 +SystemFunction015@12 +SystemFunction016@12 +SystemFunction017@12 +SystemFunction018@12 +SystemFunction019@12 +SystemFunction020@12 +SystemFunction021@12 +SystemFunction022@12 +SystemFunction023@12 +SystemFunction024@12 +SystemFunction025@12 +SystemFunction026@12 +SystemFunction027@12 +SystemFunction028@8 +SystemFunction029@8 +SystemFunction030@8 +SystemFunction031@8 +SystemFunction032@8 +SystemFunction033@8 +UnlockServiceDatabase@4 +WinLoadTrustProvider@4 +WinSubmitCertificate@4 +WinVerifyTrust@12 diff --git a/lib/advapi32/advapi32.edf b/lib/advapi32/advapi32.edf new file mode 100644 index 0000000..8893940 --- /dev/null +++ b/lib/advapi32/advapi32.edf @@ -0,0 +1,411 @@ +; $Id$ +; +; advapi32.edf +; +; ReactOS Operating System +; +; Some stack sizes are taken from Ander Norlander's .DEFs. +; +LIBRARY advapi32.dll +EXPORTS +AbortSystemShutdownA=AbortSystemShutdownA@4 +AbortSystemShutdownW=AbortSystemShutdownW@4 +AccessCheck=AccessCheck@32 +;AccessCheckAndAuditAlarmA=AccessCheckAndAuditAlarmA@44 +;AccessCheckAndAuditAlarmW=AccessCheckAndAuditAlarmW@44 +AddAccessAllowedAce=AddAccessAllowedAce@16 +AddAccessDeniedAce=AddAccessDeniedAce@16 +AddAce=AddAce@20 +AddAuditAccessAce=AddAuditAccessAce@24 +AdjustTokenGroups=AdjustTokenGroups@24 +AdjustTokenPrivileges=AdjustTokenPrivileges@24 +AllocateAndInitializeSid=AllocateAndInitializeSid@44 +AllocateLocallyUniqueId=AllocateLocallyUniqueId@4 +AreAllAccessesGranted=AreAllAccessesGranted@8 +AreAnyAccessesGranted=AreAnyAccessesGranted@8 +;BackupEventLogA=BackupEventLogA@8 +;BackupEventLogW=BackupEventLogW@8 +;BuildAccessRequestA=BuildAccessRequestA@12 +;BuildAccessRequestW=BuildAccessRequestW@12 +;BuildExplicitAccessWithNameA=BuildExplicitAccessWithNameA@20 +;BuildExplicitAccessWithNameW=BuildExplicitAccessWithNameW@20 +;BuildImpersonateExplicitAccessWithNameA +;BuildImpersonateExplicitAccessWithNameW +;BuildImpersonateTrusteeA +;BuildImpersonateTrusteeW +;BuildSecurityDescriptorA=BuildSecurityDescriptorA@36 +;BuildSecurityDescriptorW=BuildSecurityDescriptorW@36 +;BuildTrusteeWithNameA=BuildTrusteeWithNameA@8 +;BuildTrusteeWithNameW=BuildTrusteeWithNameW@8 +;BuildTrusteeWithSidA=BuildTrusteeWithSidA@8 +;BuildTrusteeWithSidW=BuildTrusteeWithSidW@8 +ChangeServiceConfigA=ChangeServiceConfigA@44 +ChangeServiceConfigW=ChangeServiceConfigW@44 +;ClearEventLogA=ClearEventLogA@8 +;ClearEventLogW=ClearEventLogW@8 +CloseServiceHandle=CloseServiceHandle@4 +ControlService=ControlService@12 +CopySid=CopySid@12 +;CreatePrivateObjectSecurity=CreatePrivateObjectSecurity@24 +;CreateProcessAsUserA=CreateProcessAsUserA@44 +;CreateProcessAsUserW=CreateProcessAsUserW@44 +CreateServiceA=CreateServiceA@52 +CreateServiceW=CreateServiceW@52 +;CryptAcquireContextA=CryptAcquireContextA@20 +;CryptAcquireContextW=CryptAcquireContextW@20 +;CryptCreateHash=CryptCreateHash@20 +;CryptDecrypt=CryptDecrypt@24 +;CryptDeriveKey=CryptDeriveKey@20 +;CryptDestroyHash=CryptDestroyHash@4 +;CryptDestroyKey=CryptDestroyKey@4 +;CryptEncrypt=CryptEncrypt@28 +;CryptExportKey=CryptExportKey@24 +;CryptGenKey=CryptGenKey@16 +;CryptGenRandom=CryptGenRandom@12 +;CryptGetHashParam=CryptGetHashParam@20 +;CryptGetKeyParam=CryptGetKeyParam@20 +;CryptGetProvParam=CryptGetProvParam@20 +;CryptGetUserKey=CryptGetUserKey@12 +;CryptHashData=CryptHashData@16 +;CryptHashSessionKey=CryptHashSessionKey@12 +;CryptImportKey=CryptImportKey@24 +;CryptReleaseContext=CryptReleaseContext@8 +;CryptSetHashParam=CryptSetHashParam@16 +;CryptSetKeyParam=CryptSetKeyParam@16 +;CryptSetProvParam=CryptSetProvParam@16 +;CryptSetProviderA=CryptSetProviderA@8 +;CryptSetProviderW=CryptSetProviderW@8 +;CryptSignHashA=CryptSignHashA@24 +;CryptSignHashW=CryptSignHashW@24 +;CryptVerifySignatureA=CryptVerifySignatureA@24 +;CryptVerifySignatureW=CryptVerifySignatureW@24 +DeleteAce=DeleteAce@8 +DeleteService=DeleteService@4 +;DenyAccessRightsA +;DenyAccessRightsW +;DeregisterEventSource=DeregisterEventSource@4 +;DestroyPrivateObjectSecurity=DestroyPrivateObjectSecurity@4 +DuplicateToken=DuplicateToken@12 +DuplicateTokenEx=DuplicateTokenEx@24 +;ElfBackupEventLogFileA=ElfBackupEventLogFileA@8 +;ElfBackupEventLogFileW=ElfBackupEventLogFileW@8 +;ElfChangeNotify=ElfChangeNotify@8 +;ElfClearEventLogFileA=ElfClearEventLogFileA@8 +;ElfClearEventLogFileW=ElfClearEventLogFileW@8 +;ElfCloseEventLog=ElfCloseEventLog@4 +;ElfDeregisterEventSource=ElfDeregisterEventSource@4 +;ElfNumberOfRecords=ElfNumberOfRecords@8 +;ElfOldestRecord=ElfOldestRecord@8 +;ElfOpenBackupEventLogA=ElfOpenBackupEventLogA@12 +;ElfOpenBackupEventLogW=ElfOpenBackupEventLogW@12 +;ElfOpenEventLogA=ElfOpenEventLogA@12 +;ElfOpenEventLogW=ElfOpenEventLogW@12 +;ElfReadEventLogA=ElfReadEventLogA@28 +;ElfReadEventLogW=ElfReadEventLogW@28 +;ElfRegisterEventSourceA=ElfRegisterEventSourceA@12 +;ElfRegisterEventSourceW=ElfRegisterEventSourceW@12 +;ElfReportEventA=ElfReportEventA@48 +;ElfReportEventW=ElfReportEventW@48 +EnumDependentServicesA=EnumDependentServicesA@24 +EnumDependentServicesW=EnumDependentServicesW@24 +EnumServiceGroupW=EnumServiceGroupW@36 +EnumServicesStatusA=EnumServicesStatusA@32 +EnumServicesStatusW=EnumServicesStatusW@32 +EqualPrefixSid=EqualPrefixSid@8 +EqualSid=EqualSid@8 +FindFirstFreeAce=FindFirstFreeAce@8 +FreeSid=FreeSid@4 +GetAce=GetAce@12 +GetAclInformation=GetAclInformation@16 +;GetAuditedPermissionsFromAclA=GetAuditedPermissionsFromAclA@16 +;GetAuditedPermissionsFromAclW=GetAuditedPermissionsFromAclW@16 +;GetAuditedPermissionsFromSDA=GetAuditedPermissionsFromSDA@16 +;GetAuditedPermissionsFromSDW=GetAuditedPermissionsFromSDW@16 +;GetCurrentHwProfileA=GetCurrentHwProfileA@4 +;GetCurrentHwProfileW=GetCurrentHwProfileW@4 +;GetEffectiveAccessRightsA=GetEffectiveAccessRightsA@16 +;GetEffectiveAccessRightsW=GetEffectiveAccessRightsW@16 +;GetEffectiveRightsFromAclA=GetEffectiveRightsFromAclA@12 +;GetEffectiveRightsFromAclW=GetEffectiveRightsFromAclW@12 +;GetEffectiveRightsFromSDA=GetEffectiveRightsFromSDA@12 +;GetEffectiveRightsFromSDW=GetEffectiveRightsFromSDW@12 +;GetExplicitAccessRightsA=GetExplicitAccessRightsA@16 +;GetExplicitAccessRightsW=GetExplicitAccessRightsW@16 +;GetExplicitEntriesFromAclA=GetExplicitEntriesFromAclA@12 +;GetExplicitEntriesFromAclW=GetExplicitEntriesFromAclW@12 +;GetFileSecurityA=GetFileSecurityA@20 +;GetFileSecurityW=GetFileSecurityW@20 +GetKernelObjectSecurity=GetKernelObjectSecurity@20 +GetLengthSid=GetLengthSid@4 +;GetMultipleTrusteeA=GetMultipleTrusteeA@4 +;GetMultipleTrusteeOperationA=GetMultipleTrusteeOperationA@4 +;GetMultipleTrusteeOperationW=GetMultipleTrusteeOperationW@4 +;GetMultipleTrusteeW=GetMultipleTrusteeW@4 +;GetNamedSecurityInfoA=GetNamedSecurityInfoA@32 +;GetNamedSecurityInfoW=GetNamedSecurityInfoW@32 +;GetNumberOfEventLogRecords=GetNumberOfEventLogRecords@8 +;GetOldestEventLogRecord=GetOldestEventLogRecord@8 +;GetPrivateObjectSecurity=GetPrivateObjectSecurity@20 +GetSecurityDescriptorControl=GetSecurityDescriptorControl@12 +GetSecurityDescriptorDacl=GetSecurityDescriptorDacl@16 +GetSecurityDescriptorGroup=GetSecurityDescriptorGroup@12 +GetSecurityDescriptorLength=GetSecurityDescriptorLength@4 +GetSecurityDescriptorOwner=GetSecurityDescriptorOwner@12 +GetSecurityDescriptorSacl=GetSecurityDescriptorSacl@16 +;GetSecurityInfo=GetSecurityInfo@32 +GetServiceDisplayNameA=GetServiceDisplayNameA@16 +GetServiceDisplayNameW=GetServiceDisplayNameW@16 +GetServiceKeyNameA=GetServiceKeyNameA@16 +GetServiceKeyNameW=GetServiceKeyNameW@16 +GetSidIdentifierAuthority=GetSidIdentifierAuthority@4 +GetSidLengthRequired=GetSidLengthRequired@4 +GetSidSubAuthority=GetSidSubAuthority@8 +GetSidSubAuthorityCount=GetSidSubAuthorityCount@4 +GetTokenInformation=GetTokenInformation@20 +;GetTrusteeForm=GetTrusteeForm@4 +;GetTrusteeNameA=GetTrusteeNameA@4 +;GetTrusteeNameW=GetTrusteeNameW@4 +;GetTrusteeTypeA=GetTrusteeTypeA@4 +;GetTrusteeTypeW=GetTrusteeTypeW@4 +GetUserNameA=GetUserNameA@8 +GetUserNameW=GetUserNameW@8 +;GrantAccessRightsA=GrantAccessRightsA@16 +;GrantAccessRightsW=GrantAccessRightsW@16 +;I_ScGetCurrentGroupStateW=I_ScGetCurrentGroupStateW@12 +;I_ScSetServiceBitsA=I_ScSetServiceBitsA@20 +;I_ScSetServiceBitsW=I_ScSetServiceBitsW@20 +;ImpersonateLoggedOnUser=ImpersonateLoggedOnUser@4 +;ImpersonateNamedPipeClient=ImpersonateNamedPipeClient@4 +ImpersonateSelf=ImpersonateSelf@4 +InitializeAcl=InitializeAcl@12 +InitializeSecurityDescriptor=InitializeSecurityDescriptor@8 +InitializeSid=InitializeSid@12 +InitiateSystemShutdownA=InitiateSystemShutdownA@20 +InitiateSystemShutdownW=InitiateSystemShutdownW@20 +;IsAccessPermittedA=IsAccessPermittedA@20 +;IsAccessPermittedW=IsAccessPermittedW@20 +;IsTextUnicode=IsTextUnicode@12 +IsValidAcl=IsValidAcl@4 +IsValidSecurityDescriptor=IsValidSecurityDescriptor@4 +IsValidSid=IsValidSid@4 +LockServiceDatabase=LockServiceDatabase@4 +;LogonUserA=LogonUserA@24 +;LogonUserW=LogonUserW@24 +LookupAccountNameA=LookupAccountNameA@28 +LookupAccountNameW=LookupAccountNameW@28 +LookupAccountSidA=LookupAccountSidA@28 +LookupAccountSidW=LookupAccountSidW@28 +LookupPrivilegeDisplayNameA=LookupPrivilegeDisplayNameA@20 +LookupPrivilegeDisplayNameW=LookupPrivilegeDisplayNameW@20 +LookupPrivilegeNameA=LookupPrivilegeNameA@16 +LookupPrivilegeNameW=LookupPrivilegeNameW@16 +LookupPrivilegeValueA=LookupPrivilegeValueA@12 +LookupPrivilegeValueW=LookupPrivilegeValueW@12 +;LookupSecurityDescriptorPartsA=LookupSecurityDescriptorPartsA@28 +;LookupSecurityDescriptorPartsW=LookupSecurityDescriptorPartsW@28 +;LsaAddAccountRights=LsaAddAccountRights@16 +;LsaAddPrivilegesToAccount=LsaAddPrivilegesToAccount@8 +;LsaClearAuditLog=LsaClearAuditLog@4 +;LsaClose=LsaClose@4 +;LsaCreateAccount=LsaCreateAccount@16 +;LsaCreateSecret=LsaCreateSecret@16 +;LsaCreateTrustedDomain=LsaCreateTrustedDomain@16 +;LsaDelete=LsaDelete@4 +;LsaDeleteTrustedDomain=LsaDeleteTrustedDomain@8 +;LsaEnumerateAccountRights=LsaEnumerateAccountRights@16 +;LsaEnumerateAccounts=LsaEnumerateAccounts@20 +;LsaEnumerateAccountsWithUserRight=LsaEnumerateAccountsWithUserRight@16 +;LsaEnumeratePrivileges=LsaEnumeratePrivileges@20 +;LsaEnumeratePrivilegesOfAccount=LsaEnumeratePrivilegesOfAccount@8 +;LsaEnumerateTrustedDomains=LsaEnumerateTrustedDomains@20 +;LsaFreeMemory=LsaFreeMemory@4 +;LsaGetQuotasForAccount=LsaGetQuotasForAccount@8 +;LsaGetSystemAccessAccount=LsaGetSystemAccessAccount@8 +;LsaGetUserName=LsaGetUserName@8 +;LsaICLookupNames=LsaICLookupNames@28 +;LsaICLookupSids=LsaICLookupSids@28 +;LsaLookupNames=LsaLookupNames@20 +;LsaLookupPrivilegeDisplayName=LsaLookupPrivilegeDisplayName@16 +;LsaLookupPrivilegeName=LsaLookupPrivilegeName@12 +;LsaLookupPrivilegeValue=LsaLookupPrivilegeValue@12 +;LsaLookupSids=LsaLookupSids@20 +;LsaNtStatusToWinError=LsaNtStatusToWinError@4 +;LsaOpenAccount=LsaOpenAccount@16 +;LsaOpenPolicy=LsaOpenPolicy@16 +;LsaOpenSecret=LsaOpenSecret@16 +;LsaOpenTrustedDomain=LsaOpenTrustedDomain@16 +;LsaQueryInfoTrustedDomain=LsaQueryInfoTrustedDomain@12 +;LsaQueryInformationPolicy=LsaQueryInformationPolicy@12 +;LsaQuerySecret=LsaQuerySecret@20 +;LsaQuerySecurityObject=LsaQuerySecurityObject@12 +;LsaQueryTrustedDomainInfo=LsaQueryTrustedDomainInfo@16 +;LsaRemoveAccountRights=LsaRemoveAccountRights@20 +;LsaRemovePrivilegesFromAccount=LsaRemovePrivilegesFromAccount@12 +;LsaRetrievePrivateData=LsaRetrievePrivateData@12 +;LsaSetInformationPolicy=LsaSetInformationPolicy@12 +;LsaSetInformationTrustedDomain=LsaSetInformationTrustedDomain@12 +;LsaSetQuotasForAccount=LsaSetQuotasForAccount@8 +;LsaSetSecret=LsaSetSecret@12 +;LsaSetSecurityObject=LsaSetSecurityObject@12 +;LsaSetSystemAccessAccount=LsaSetSystemAccessAccount@8 +;LsaSetTrustedDomainInformation=LsaSetTrustedDomainInformation@16 +;LsaStorePrivateData=LsaStorePrivateData@12 +MakeAbsoluteSD=MakeAbsoluteSD@44 +MakeSelfRelativeSD=MakeSelfRelativeSD@12 +MapGenericMask=MapGenericMask@8 +;NTAccessMaskToProvAccessRights=NTAccessMaskToProvAccessRights@12 +;NotifyBootConfigStatus=NotifyBootConfigStatus@4 +;NotifyChangeEventLog=NotifyChangeEventLog@8 +;ObjectCloseAuditAlarmA=ObjectCloseAuditAlarmA@12 +;ObjectCloseAuditAlarmW=ObjectCloseAuditAlarmW@12 +;ObjectDeleteAuditAlarmA=ObjectDeleteAuditAlarmA@12 +;ObjectDeleteAuditAlarmW=ObjectDeleteAuditAlarmW@12 +;ObjectOpenAuditAlarmA=ObjectOpenAuditAlarmA@48 +;ObjectOpenAuditAlarmW=ObjectOpenAuditAlarmW@48 +;ObjectPrivilegeAuditAlarmA=ObjectPrivilegeAuditAlarmA@24 +;ObjectPrivilegeAuditAlarmW=ObjectPrivilegeAuditAlarmW@24 +;OpenBackupEventLogA=OpenBackupEventLogA@8 +;OpenBackupEventLogW=OpenBackupEventLogW@8 +;OpenEventLogA=OpenEventLogA@8 +;OpenEventLogW=OpenEventLogW@8 +OpenProcessToken=OpenProcessToken@12 +OpenSCManagerA=OpenSCManagerA@12 +OpenSCManagerW=OpenSCManagerW@12 +OpenServiceA=OpenServiceA@12 +OpenServiceW=OpenServiceW@12 +OpenThreadToken=OpenThreadToken@16 +;PrivilegeCheck=PrivilegeCheck@12 +;PrivilegedServiceAuditAlarmA=PrivilegedServiceAuditAlarmA@20 +;PrivilegedServiceAuditAlarmW=PrivilegedServiceAuditAlarmW@20 +;ProvAccessRightsToNTAccessMask=ProvAccessRightsToNTAccessMask@8 +QueryServiceConfigA=QueryServiceConfigA@16 +QueryServiceConfigW=QueryServiceConfigW@16 +QueryServiceLockStatusA=QueryServiceLockStatusA@16 +QueryServiceLockStatusW=QueryServiceLockStatusW@16 +QueryServiceObjectSecurity=QueryServiceObjectSecurity@20 +QueryServiceStatus=QueryServiceStatus@8 +;QueryWindows31FilesMigration=QueryWindows31FilesMigration@4 +;ReadEventLogA=ReadEventLogA@28 +;ReadEventLogW=ReadEventLogW@28 +RegCloseKey=RegCloseKey@4 +RegConnectRegistryA=RegConnectRegistryA@12 +RegConnectRegistryW=RegConnectRegistryW@12 +RegCreateKeyA=RegCreateKeyA@12 +RegCreateKeyExA=RegCreateKeyExA@36 +RegCreateKeyExW=RegCreateKeyExW@36 +RegCreateKeyW=RegCreateKeyW@12 +RegDeleteKeyA=RegDeleteKeyA@8 +RegDeleteKeyW=RegDeleteKeyW@8 +RegDeleteValueA=RegDeleteValueA@8 +RegDeleteValueW=RegDeleteValueW@8 +RegEnumKeyA=RegEnumKeyA@16 +RegEnumKeyExA=RegEnumKeyExA@32 +RegEnumKeyExW=RegEnumKeyExW@32 +RegEnumKeyW=RegEnumKeyW@16 +RegEnumValueA=RegEnumValueA@32 +RegEnumValueW=RegEnumValueW@32 +RegFlushKey=RegFlushKey@4 +RegGetKeySecurity=RegGetKeySecurity@16 +RegLoadKeyA=RegLoadKeyA@12 +RegLoadKeyW=RegLoadKeyW@12 +RegNotifyChangeKeyValue=RegNotifyChangeKeyValue@20 +RegOpenKeyA=RegOpenKeyA@12 +RegOpenKeyExA=RegOpenKeyExA@20 +RegOpenKeyExW=RegOpenKeyExW@20 +RegOpenKeyW=RegOpenKeyW@12 +RegQueryInfoKeyA=RegQueryInfoKeyA@48 +RegQueryInfoKeyW=RegQueryInfoKeyW@48 +RegQueryMultipleValuesA=RegQueryMultipleValuesA@20 +RegQueryMultipleValuesW=RegQueryMultipleValuesW@20 +RegQueryValueA=RegQueryValueA@16 +RegQueryValueExA=RegQueryValueExA@24 +RegQueryValueExW=RegQueryValueExW@24 +RegQueryValueW=RegQueryValueW@16 +RegReplaceKeyA=RegReplaceKeyA@16 +RegReplaceKeyW=RegReplaceKeyW@16 +RegRestoreKeyA=RegRestoreKeyA@12 +RegRestoreKeyW=RegRestoreKeyW@12 +RegSaveKeyA=RegSaveKeyA@12 +RegSaveKeyW=RegSaveKeyW@12 +RegSetKeySecurity=RegSetKeySecurity@12 +RegSetValueA=RegSetValueA@20 +RegSetValueExA=RegSetValueExA@24 +RegSetValueExW=RegSetValueExW@24 +RegSetValueW=RegSetValueW@20 +RegUnLoadKeyA=RegUnLoadKeyA@8 +RegUnLoadKeyW=RegUnLoadKeyW@8 +;RegisterEventSourceA=RegisterEventSourceA@8 +;RegisterEventSourceW=RegisterEventSourceW@8 +RegisterServiceCtrlHandlerA=RegisterServiceCtrlHandlerA@8 +RegisterServiceCtrlHandlerW=RegisterServiceCtrlHandlerW@8 +;ReplaceAllAccessRightsA +;ReplaceAllAccessRightsW +;ReportEventA=ReportEventA@36 +;ReportEventW=ReportEventW@36 +RevertToSelf=RevertToSelf@0 +;RevokeExplicitAccessRightsA=RevokeExplicitAccessRightsA@16 +;RevokeExplicitAccessRightsW=RevokeExplicitAccessRightsW@16 +;SetAccessRightsA=SetAccessRightsA@16 +;SetAccessRightsW=SetAccessRightsW@16 +SetAclInformation=SetAclInformation@16 +;SetEntriesInAclA=SetEntriesInAclA@16 +;SetEntriesInAclW=SetEntriesInAclW@16 +;SetFileSecurityA=SetFileSecurityA@12 +;SetFileSecurityW=SetFileSecurityW@12 +SetKernelObjectSecurity=SetKernelObjectSecurity@12 +;SetNamedSecurityInfoA=SetNamedSecurityInfoA@28 +;SetNamedSecurityInfoW=SetNamedSecurityInfoW@28 +;SetPrivateObjectSecurity=SetPrivateObjectSecurity@20 +SetSecurityDescriptorDacl=SetSecurityDescriptorDacl@16 +SetSecurityDescriptorGroup=SetSecurityDescriptorGroup@12 +SetSecurityDescriptorOwner=SetSecurityDescriptorOwner@12 +SetSecurityDescriptorSacl=SetSecurityDescriptorSacl@16 +;SetSecurityInfo=SetSecurityInfo@28 +;SetServiceBits=SetServiceBits@16 +SetServiceObjectSecurity=SetServiceObjectSecurity@12 +SetServiceStatus=SetServiceStatus@8 +SetThreadToken=SetThreadToken@8 +SetTokenInformation=SetTokenInformation@16 +StartServiceA=StartServiceA@12 +StartServiceCtrlDispatcherA=StartServiceCtrlDispatcherA@4 +StartServiceCtrlDispatcherW=StartServiceCtrlDispatcherW@4 +StartServiceW=StartServiceW@12 +;SynchronizeWindows31FilesAndWindowsNTRegistry=SynchronizeWindows31FilesAndWindowsNTRegistry@16 +SystemFunction001=SystemFunction001@12 +SystemFunction002=SystemFunction002@12 +SystemFunction003=SystemFunction003@8 +SystemFunction004=SystemFunction004@12 +SystemFunction005=SystemFunction005@12 +SystemFunction006=SystemFunction006@8 +SystemFunction007=SystemFunction007@8 +SystemFunction008=SystemFunction008@12 +SystemFunction009=SystemFunction009@12 +SystemFunction010=SystemFunction010@12 +SystemFunction011=SystemFunction011@12 +SystemFunction012=SystemFunction012@12 +SystemFunction013=SystemFunction013@12 +SystemFunction014=SystemFunction014@12 +SystemFunction015=SystemFunction015@12 +SystemFunction016=SystemFunction016@12 +SystemFunction017=SystemFunction017@12 +SystemFunction018=SystemFunction018@12 +SystemFunction019=SystemFunction019@12 +SystemFunction020=SystemFunction020@12 +SystemFunction021=SystemFunction021@12 +SystemFunction022=SystemFunction022@12 +SystemFunction023=SystemFunction023@12 +SystemFunction024=SystemFunction024@12 +SystemFunction025=SystemFunction025@12 +SystemFunction026=SystemFunction026@12 +SystemFunction027=SystemFunction027@12 +SystemFunction028=SystemFunction028@8 +SystemFunction029=SystemFunction029@8 +SystemFunction030=SystemFunction030@8 +SystemFunction031=SystemFunction031@8 +SystemFunction032=SystemFunction032@8 +SystemFunction033=SystemFunction033@8 +UnlockServiceDatabase=UnlockServiceDatabase@4 +;WinLoadTrustProvider=WinLoadTrustProvider@4 +;WinSubmitCertificate=WinSubmitCertificate@4 +;WinVerifyTrust=WinVerifyTrust@12 + diff --git a/lib/advapi32/advapi32.rc b/lib/advapi32/advapi32.rc new file mode 100644 index 0000000..03b75b6 --- /dev/null +++ b/lib/advapi32/advapi32.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Advanced W32 Base API\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "advapi32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "advapi32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/advapi32/makefile b/lib/advapi32/makefile new file mode 100644 index 0000000..abe49da --- /dev/null +++ b/lib/advapi32/makefile @@ -0,0 +1,55 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = advapi32 + +TARGET_SDKLIBS = ntdll.a kernel32.a + +# TARGET_CFLAGS = -DUNICODE + +TARGET_BASE = 0x77dc0000 + +MISC_OBJECTS=\ + misc/dllmain.o \ + misc/shutdown.o \ + misc/sysfunc.o + +REGISTRY_OBJECTS=\ + reg/reg.o + +SECURITY_OBJECTS=\ + sec/ac.o \ + sec/lsa.o \ + sec/misc.o \ + sec/sec.o \ + sec/sid.o + +SERVICE_OBJECTS=\ + service/scm.o \ + service/sctrl.o \ + service/undoc.o + +TOKEN_OBJECTS=\ + token/privilege.o \ + token/token.o + +TARGET_OBJECTS = \ + $(MISC_OBJECTS) \ + $(REGISTRY_OBJECTS) \ + $(SECURITY_OBJECTS) \ + $(SERVICE_OBJECTS) \ + $(TOKEN_OBJECTS) + +TARGET_CLEAN = \ + misc/*.o \ + reg/*.o \ + sec/*.o \ + service/*.o \ + token/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/advapi32/misc/dllmain.c b/lib/advapi32/misc/dllmain.c new file mode 100644 index 0000000..c20c5e7 --- /dev/null +++ b/lib/advapi32/misc/dllmain.c @@ -0,0 +1,39 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/misc/dllmain.c + * PURPOSE: Library main function + * PROGRAMMER: ??? + * UPDATE HISTORY: + * Created ??? + */ + +#include +#include + +#define NDEBUG +#include + + +INT STDCALL +DllMain(PVOID hinstDll, + ULONG dwReason, + PVOID reserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDll); + RegInitialize(); + break; + + case DLL_PROCESS_DETACH: + RegCleanup(); + break; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/advapi32/misc/shutdown.c b/lib/advapi32/misc/shutdown.c new file mode 100644 index 0000000..0c2a4b2 --- /dev/null +++ b/lib/advapi32/misc/shutdown.c @@ -0,0 +1,193 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/misc/shutdown.c + * PURPOSE: System shutdown functions + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 19990413 EA created + * 19990515 EA + */ + +#include +#include + +#define USZ {0,0,0} + +/********************************************************************** + * AbortSystemShutdownW + */ +BOOL +STDCALL +AbortSystemShutdownW( + LPWSTR lpMachineName + ) +{ + NTSTATUS Status; + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * AbortSystemShutdownA + */ +BOOL +STDCALL +AbortSystemShutdownA( + LPSTR lpMachineName + ) +{ + ANSI_STRING MachineNameA; + UNICODE_STRING MachineNameW; + NTSTATUS Status; + BOOL rv; + + RtlInitAnsiString( + & MachineNameA, + lpMachineName + ); + Status = RtlAnsiStringToUnicodeString( + & MachineNameW, + & MachineNameA, + TRUE + ); + if (STATUS_SUCCESS != Status) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + rv = AbortSystemShutdownW( + MachineNameW.Buffer + ); + RtlFreeAnsiString( + & MachineNameA + ); + RtlFreeUnicodeString( + & MachineNameW + ); + SetLastError(ERROR_SUCCESS); + return rv; +} + + +/********************************************************************** + * InitiateSystemShutdownW + */ +BOOL +STDCALL +InitiateSystemShutdownW( + LPWSTR lpMachineName, + LPWSTR lpMessage, + DWORD dwTimeout, + BOOL bForceAppsClosed, + BOOL bRebootAfterShutdown + ) +{ + SHUTDOWN_ACTION Action = ShutdownNoReboot; + NTSTATUS Status; + + if (lpMachineName) + { + /* FIXME: remote machine shutdown not supported yet */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + if (dwTimeout) + { + } + Status = NtShutdownSystem(Action); + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; +} + + +/********************************************************************** + * InitiateSystemShutdownA + */ +BOOL +STDCALL +InitiateSystemShutdownA( + LPSTR lpMachineName, + LPSTR lpMessage, + DWORD dwTimeout, + BOOL bForceAppsClosed, + BOOL bRebootAfterShutdown + ) +{ + ANSI_STRING MachineNameA; + ANSI_STRING MessageA; + UNICODE_STRING MachineNameW; + UNICODE_STRING MessageW; + NTSTATUS Status; + INT LastError; + BOOL rv; + + if (lpMachineName) + { + RtlInitAnsiString( + & MachineNameA, + lpMachineName + ); + Status = RtlAnsiStringToUnicodeString( + & MachineNameW, + & MachineNameA, + TRUE + ); + if (STATUS_SUCCESS != Status) + { + RtlFreeAnsiString(&MachineNameA); + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + } + if (lpMessage) + { + RtlInitAnsiString( + & MessageA, + lpMessage + ); + Status = RtlAnsiStringToUnicodeString( + & MessageW, + & MessageA, + TRUE + ); + if (STATUS_SUCCESS != Status) + { + if (MachineNameW.Length) + { + RtlFreeAnsiString(&MachineNameA); + RtlFreeUnicodeString(&MachineNameW); + } + RtlFreeAnsiString(&MessageA); + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; + } + } + rv = InitiateSystemShutdownW( + MachineNameW.Buffer, + MessageW.Buffer, + dwTimeout, + bForceAppsClosed, + bRebootAfterShutdown + ); + LastError = GetLastError(); + if (lpMachineName) + { + RtlFreeAnsiString(&MachineNameA); + RtlFreeUnicodeString(&MachineNameW); + } + if (lpMessage) + { + RtlFreeAnsiString(&MessageA); + RtlFreeUnicodeString(&MessageW); + } + SetLastError(LastError); + return rv; +} + + +/* EOF */ + diff --git a/lib/advapi32/misc/sysfunc.c b/lib/advapi32/misc/sysfunc.c new file mode 100644 index 0000000..c6d41bb --- /dev/null +++ b/lib/advapi32/misc/sysfunc.c @@ -0,0 +1,410 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/misc/sysfun.c + * PURPOSE: advapi32.dll system functions (undocumented) + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 19990413 EA created + * 19990415 EA + */ +#include + +/********************************************************************** + * SystemFunction001 + */ +INT +STDCALL +SystemFunction001(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 1; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction002(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 2; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction003(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 3; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction004(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 4; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction005(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 5; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction006(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 6; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction007(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 7; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction008(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 8; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction009(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 9; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction010(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 10; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction011(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 11; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction012(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 12; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction013(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 13; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction014(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 14; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction015(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 15; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction016(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 16; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction017(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 17; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction018(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 18; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction019(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 19; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction020(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 20; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction021(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 21; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction022(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 22; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction023(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 23; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction024(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 24; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction025(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 25; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction026(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 26; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction027(INT a, INT b, INT c) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 27; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction028(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 28; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction029(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 29; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction030(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 30; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction031(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 31; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction032(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 32; +} + + +/********************************************************************** + * + */ +INT +STDCALL +SystemFunction033(INT a, INT b) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 33; +} + + +/* EOF */ diff --git a/lib/advapi32/reg/reg.c b/lib/advapi32/reg/reg.c new file mode 100644 index 0000000..8296a41 --- /dev/null +++ b/lib/advapi32/reg/reg.c @@ -0,0 +1,2504 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/reg/reg.c + * PURPOSE: Registry functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + * 19990309 EA Stubs + */ +#include +#include +#include +#include + +#define NDEBUG +#include + +#define CHECK_STATUS \ +{ \ + if (!NT_SUCCESS(Status)) \ + { \ + LONG _ErrorCode = RtlNtStatusToDosError(Status); \ + SetLastError(_ErrorCode); \ + return _ErrorCode; \ + } \ +} + +/* GLOBALS *******************************************************************/ + +#define MAX_DEFAULT_HANDLES 6 + +static CRITICAL_SECTION HandleTableCS; +static HANDLE DefaultHandleTable[MAX_DEFAULT_HANDLES]; + + +/* PROTOTYPES ****************************************************************/ + +static NTSTATUS MapDefaultKey (PHKEY ParentKey, HKEY Key); +static VOID CloseDefaultKeys(VOID); + +static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle); +static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle); +static NTSTATUS OpenUsersKey (PHANDLE KeyHandle); +static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle); + + +/* FUNCTIONS *****************************************************************/ + +inline RegiTerminateWideString(LPWSTR String, DWORD Length) +{ + LPWSTR AfterString = String + Length; + *AfterString = 0; +} + +/************************************************************************ + * RegInitDefaultHandles + */ + +BOOL +RegInitialize (VOID) +{ + DPRINT("RegInitialize()\n"); + + RtlZeroMemory (DefaultHandleTable, + MAX_DEFAULT_HANDLES * sizeof(HANDLE)); + + RtlInitializeCriticalSection(&HandleTableCS); + return TRUE; +} + + +/************************************************************************ + * RegInit + */ +BOOL +RegCleanup(VOID) +{ + DPRINT("RegCleanup()\n"); + + CloseDefaultKeys(); + RtlDeleteCriticalSection(&HandleTableCS); + return TRUE; +} + + +static NTSTATUS +MapDefaultKey(PHKEY RealKey, + HKEY Key) +{ + PHANDLE Handle; + ULONG Index; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("MapDefaultKey (Key %x)\n", Key); + + if (((ULONG)Key & 0xF0000000) != 0x80000000) + { + *RealKey = Key; + return STATUS_SUCCESS; + } + + /* Handle special cases here */ + Index = (ULONG)Key & 0x0FFFFFFF; + + if (Index >= MAX_DEFAULT_HANDLES) + return STATUS_INVALID_PARAMETER; + + RtlEnterCriticalSection(&HandleTableCS); + + Handle = &DefaultHandleTable[Index]; + if (*Handle == NULL) + { + /* create/open the default handle */ + switch (Index) + { + case 0: /* HKEY_CLASSES_ROOT */ + Status = OpenClassesRootKey(Handle); + break; + + case 1: /* HKEY_CURRENT_USER */ + Status = RtlOpenCurrentUser(KEY_ALL_ACCESS, + Handle); + break; + + case 2: /* HKEY_LOCAL_MACHINE */ + Status = OpenLocalMachineKey(Handle); + break; + + case 3: /* HKEY_USERS */ + Status = OpenUsersKey(Handle); + break; +#if 0 + case 4: /* HKEY_PERFORMANCE_DATA */ + Status = OpenPerformanceDataKey(Handle); + break; +#endif + case 5: /* HKEY_CURRENT_CONFIG */ + Status = OpenCurrentConfigKey(Handle); + break; + + default: + DPRINT("MapDefaultHandle() no handle creator\n"); + Status = STATUS_INVALID_PARAMETER; + } + } + + RtlLeaveCriticalSection(&HandleTableCS); + + if (NT_SUCCESS(Status)) + { + *RealKey = (HKEY)*Handle; + } + + return Status; +} + + +static VOID +CloseDefaultKeys(VOID) +{ + ULONG i; + + RtlEnterCriticalSection(&HandleTableCS); + + for (i = 0; i < MAX_DEFAULT_HANDLES; i++) + { + if (DefaultHandleTable[i] != NULL) + { + NtClose (DefaultHandleTable[i]); + DefaultHandleTable[i] = NULL; + } + } + + RtlLeaveCriticalSection(&HandleTableCS); +} + + +static NTSTATUS +OpenClassesRootKey(PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES Attributes; + UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software\\CLASSES"); + + DPRINT("OpenClassesRootKey()\n"); + + InitializeObjectAttributes(&Attributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + return(NtOpenKey(KeyHandle, + KEY_ALL_ACCESS, + &Attributes)); +} + + +static NTSTATUS +OpenLocalMachineKey(PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES Attributes; + UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine"); + + DPRINT("OpenLocalMachineKey()\n"); + + InitializeObjectAttributes(&Attributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + return(NtOpenKey(KeyHandle, + KEY_ALL_ACCESS, + &Attributes)); +} + + +static NTSTATUS +OpenUsersKey(PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES Attributes; + UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\User"); + + DPRINT("OpenUsersKey()\n"); + + InitializeObjectAttributes(&Attributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + return(NtOpenKey(KeyHandle, + KEY_ALL_ACCESS, + &Attributes)); +} + + +static NTSTATUS +OpenCurrentConfigKey(PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES Attributes; + UNICODE_STRING KeyName = + UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current"); + + DPRINT("OpenCurrentConfigKey()\n"); + + InitializeObjectAttributes(&Attributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + return(NtOpenKey(KeyHandle, + KEY_ALL_ACCESS, + &Attributes)); +} + +/************************************************************************ + * RegCloseKey + */ +LONG STDCALL +RegCloseKey(HKEY hKey) +{ + NTSTATUS Status; + + /* don't close null handle or a pseudo handle */ + if ((!hKey) || (((ULONG)hKey & 0xF0000000) == 0x80000000)) + return ERROR_INVALID_HANDLE; + + Status = NtClose (hKey); + if (!NT_SUCCESS(Status)) + { + LONG ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegConnectRegistryA + */ +LONG STDCALL +RegConnectRegistryA(LPSTR lpMachineName, + HKEY hKey, + PHKEY phkResult) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegConnectRegistryW + */ +LONG STDCALL +RegConnectRegistryW(LPWSTR lpMachineName, + HKEY hKey, + PHKEY phkResult) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegCreateKeyA + */ +LONG STDCALL +RegCreateKeyA(HKEY hKey, + LPCSTR lpSubKey, + PHKEY phkResult) +{ + return(RegCreateKeyExA(hKey, + lpSubKey, + 0, + NULL, + 0, + KEY_ALL_ACCESS, + NULL, + phkResult, + NULL)); +} + + +/************************************************************************ + * RegCreateKeyW + */ +LONG STDCALL +RegCreateKeyW(HKEY hKey, + LPCWSTR lpSubKey, + PHKEY phkResult) +{ + return(RegCreateKeyExW(hKey, + lpSubKey, + 0, + NULL, + 0, + KEY_ALL_ACCESS, + NULL, + phkResult, + NULL)); +} + + +/************************************************************************ + * RegCreateKeyExA + */ +LONG STDCALL +RegCreateKeyExA(HKEY hKey, + LPCSTR lpSubKey, + DWORD Reserved, + LPSTR lpClass, + DWORD dwOptions, + REGSAM samDesired, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + PHKEY phkResult, + LPDWORD lpdwDisposition) +{ + UNICODE_STRING SubKeyString; + UNICODE_STRING ClassString; + OBJECT_ATTRIBUTES Attributes; + NTSTATUS Status; + HKEY ParentKey; + + DPRINT("RegCreateKeyExW() called\n"); + + /* get the real parent key */ + Status = MapDefaultKey(&ParentKey, + hKey); + if (!NT_SUCCESS(Status)) + { + LONG ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + + DPRINT("ParentKey %x\n", (ULONG)ParentKey); + + if (lpClass != NULL) + RtlCreateUnicodeStringFromAsciiz(&ClassString, + lpClass); + RtlCreateUnicodeStringFromAsciiz(&SubKeyString, + (LPSTR)lpSubKey); + + InitializeObjectAttributes(&Attributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + (HANDLE)ParentKey, + (PSECURITY_DESCRIPTOR)lpSecurityAttributes); + + Status = NtCreateKey(phkResult, + samDesired, + &Attributes, + 0, + (lpClass == NULL)? NULL : &ClassString, + dwOptions, + (PULONG)lpdwDisposition); + + RtlFreeUnicodeString(&SubKeyString); + if (lpClass != NULL) + RtlFreeUnicodeString(&ClassString); + + DPRINT("Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + LONG ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + return(ERROR_SUCCESS); +} + + +/************************************************************************ + * RegCreateKeyExW + */ +LONG STDCALL +RegCreateKeyExW(HKEY hKey, + LPCWSTR lpSubKey, + DWORD Reserved, + LPWSTR lpClass, + DWORD dwOptions, + REGSAM samDesired, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + PHKEY phkResult, + LPDWORD lpdwDisposition) +{ + UNICODE_STRING SubKeyString; + UNICODE_STRING ClassString; + OBJECT_ATTRIBUTES Attributes; + NTSTATUS Status; + HKEY ParentKey; + + DPRINT("RegCreateKeyExW() called\n"); + + /* get the real parent key */ + Status = MapDefaultKey (&ParentKey, hKey); + if (!NT_SUCCESS(Status)) + { + LONG ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + DPRINT("ParentKey %x\n", (ULONG)ParentKey); + RtlInitUnicodeString (&ClassString, lpClass); + RtlInitUnicodeString (&SubKeyString, lpSubKey); + + InitializeObjectAttributes (&Attributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + (HANDLE)ParentKey, + (PSECURITY_DESCRIPTOR)lpSecurityAttributes); + + Status = NtCreateKey (phkResult, + samDesired, + &Attributes, + 0, + (lpClass == NULL)? NULL : &ClassString, + dwOptions, + (PULONG)lpdwDisposition); + DPRINT("Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + LONG ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegDeleteKeyA + */ +LONG +STDCALL +RegDeleteKeyA( + HKEY hKey, + LPCSTR lpSubKey + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING SubKeyStringW; + ANSI_STRING SubKeyStringA; + HANDLE ParentKey; + HANDLE TargetKey; + NTSTATUS Status; + LONG ErrorCode; + + Status = MapDefaultKey(&ParentKey, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitAnsiString(&SubKeyStringA, + (LPSTR)lpSubKey); + RtlAnsiStringToUnicodeString(&SubKeyStringW, + &SubKeyStringA, + TRUE); + + InitializeObjectAttributes (&ObjectAttributes, + &SubKeyStringW, + OBJ_CASE_INSENSITIVE, + (HANDLE)ParentKey, + NULL); + + Status = NtOpenKey (&TargetKey, + DELETE, + &ObjectAttributes); + + RtlFreeUnicodeString (&SubKeyStringW); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + Status = NtDeleteKey(TargetKey); + + NtClose(TargetKey); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegDeleteKeyW + */ +LONG +STDCALL +RegDeleteKeyW( + HKEY hKey, + LPCWSTR lpSubKey + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING SubKeyString; + HANDLE ParentKey; + HANDLE TargetKey; + NTSTATUS Status; + LONG ErrorCode; + + Status = MapDefaultKey(&ParentKey, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes (&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + (HANDLE)ParentKey, + NULL); + + Status = NtOpenKey (&TargetKey, + DELETE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + Status = NtDeleteKey(TargetKey); + + NtClose(TargetKey); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegDeleteValueA + */ +LONG +STDCALL +RegDeleteValueA( + HKEY hKey, + LPCSTR lpValueName + ) +{ + UNICODE_STRING ValueNameW; + ANSI_STRING ValueNameA; + NTSTATUS Status; + LONG ErrorCode; + HANDLE KeyHandle; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitAnsiString(&ValueNameA, + (LPSTR)lpValueName); + RtlAnsiStringToUnicodeString(&ValueNameW, + &ValueNameA, + TRUE); + + Status = NtDeleteValueKey(KeyHandle, + &ValueNameW); + + RtlFreeUnicodeString (&ValueNameW); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegDeleteValueW + */ +LONG +STDCALL +RegDeleteValueW( + HKEY hKey, + LPCWSTR lpValueName + ) +{ + UNICODE_STRING ValueName; + NTSTATUS Status; + LONG ErrorCode; + HANDLE KeyHandle; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitUnicodeString(&ValueName, + (LPWSTR)lpValueName); + + Status = NtDeleteValueKey(KeyHandle, + &ValueName); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegEnumKeyA + */ +LONG +STDCALL +RegEnumKeyA( + HKEY hKey, + DWORD dwIndex, + LPSTR lpName, + DWORD cbName + ) +{ + DWORD dwLength = cbName; + + return RegEnumKeyExA(hKey, + dwIndex, + lpName, + &dwLength, + NULL, + NULL, + NULL, + NULL); +} + + +/************************************************************************ + * RegEnumKeyExA + */ +LONG +STDCALL +RegEnumKeyExA( + HKEY hKey, + DWORD dwIndex, + LPSTR lpName, + LPDWORD lpcbName, + LPDWORD lpReserved, + LPSTR lpClass, + LPDWORD lpcbClass, + PFILETIME lpftLastWriteTime + ) +{ + WCHAR Name[MAX_PATH+1]; + UNICODE_STRING UnicodeStringName; + WCHAR Class[MAX_PATH+1]; + UNICODE_STRING UnicodeStringClass; + ANSI_STRING AnsiString; + LONG ErrorCode; + DWORD NameLength; + DWORD ClassLength; + + DPRINT("hKey 0x%x dwIndex %d lpName 0x%x *lpcbName %d lpClass 0x%x lpcbClass %d\n", + hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass); + + if ((lpClass) && (!lpcbClass)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + RtlInitUnicodeString(&UnicodeStringName, NULL); + UnicodeStringName.Buffer = &Name[0]; + UnicodeStringName.MaximumLength = sizeof(Name); + + RtlInitUnicodeString(&UnicodeStringClass, NULL); + + if (lpClass) + { + UnicodeStringClass.Buffer = &Class[0]; + UnicodeStringClass.MaximumLength = sizeof(Class); + ClassLength = *lpcbClass; + } + else + { + ClassLength = 0; + } + + NameLength = *lpcbName; + + ErrorCode = RegEnumKeyExW( + hKey, + dwIndex, + UnicodeStringName.Buffer, + &NameLength, + lpReserved, + UnicodeStringClass.Buffer, + &ClassLength, + lpftLastWriteTime); + + if (ErrorCode != ERROR_SUCCESS) + return ErrorCode; + + UnicodeStringName.Length = NameLength * sizeof(WCHAR); + UnicodeStringClass.Length = ClassLength * sizeof(WCHAR); + + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpName; + AnsiString.MaximumLength = *lpcbName; + RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE); + *lpcbName = AnsiString.Length; + + DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length); + DPRINT("Key Namea1 Length %d\n", NameLength); + DPRINT("Key Namea Length %d\n", *lpcbName); + DPRINT("Key Namea %s\n", lpName); + + if (lpClass) + { + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpClass; + AnsiString.MaximumLength = *lpcbClass; + RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE); + *lpcbClass = AnsiString.Length; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegEnumKeyExW + */ +LONG +STDCALL +RegEnumKeyExW( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpName, + LPDWORD lpcbName, + LPDWORD lpReserved, + LPWSTR lpClass, + LPDWORD lpcbClass, + PFILETIME lpftLastWriteTime + ) +{ + PKEY_NODE_INFORMATION KeyInfo; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + ULONG BufferSize; + ULONG ResultSize; + HANDLE KeyHandle; + + Status = MapDefaultKey(&KeyHandle, hKey); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + SetLastError (dwError); + return dwError; + } + + BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR); + if (lpClass) + BufferSize += *lpcbClass; + KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize); + + /* We don't know the exact size of the data returned, so call + NtEnumerateKey() with a buffer size determined from parameters + to this function. If that call fails with a status code of + STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */ + while (TRUE) { + KeyInfo = RtlAllocateHeap( + RtlGetProcessHeap(), + 0, + BufferSize); + if (KeyInfo == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + + Status = NtEnumerateKey( + KeyHandle, + (ULONG)dwIndex, + KeyNodeInformation, + KeyInfo, + BufferSize, + &ResultSize); + + DPRINT("NtEnumerateKey() returned status 0x%X\n", Status); + + if (Status == STATUS_BUFFER_OVERFLOW) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo); + BufferSize = ResultSize; + continue; + } + + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + SetLastError(dwError); + break; + } + else + { + if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass)) + { + dwError = ERROR_MORE_DATA; + SetLastError(dwError); + break; + } + + RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength); + *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR)); + RegiTerminateWideString(lpName, *lpcbName); + + if (lpClass) + { + RtlMoveMemory(lpClass, + (PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset), + KeyInfo->ClassLength); + *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR)); + } + + if (lpftLastWriteTime) + { + /* FIXME: Fill lpftLastWriteTime */ + } + + break; + } + } + + RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo); + + return dwError; +} + + +/************************************************************************ + * RegEnumKeyW + */ +LONG +STDCALL +RegEnumKeyW( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpName, + DWORD cbName + ) +{ + DWORD dwLength = cbName; + + return RegEnumKeyExW(hKey, + dwIndex, + lpName, + &dwLength, + NULL, + NULL, + NULL, + NULL); +} + + +/************************************************************************ + * RegEnumValueA + */ +LONG +STDCALL +RegEnumValueA( + HKEY hKey, + DWORD dwIndex, + LPSTR lpValueName, + LPDWORD lpcbValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ) +{ + WCHAR ValueName[MAX_PATH+1]; + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + LONG ErrorCode; + DWORD ValueNameLength; + + RtlInitUnicodeString(&UnicodeString, NULL); + UnicodeString.Buffer = &ValueName[0]; + UnicodeString.MaximumLength = sizeof(ValueName); + + ValueNameLength = *lpcbValueName; + + ErrorCode = RegEnumValueW( + hKey, + dwIndex, + UnicodeString.Buffer, + &ValueNameLength, + lpReserved, + lpType, + lpData, + lpcbData); + + if (ErrorCode != ERROR_SUCCESS) + return ErrorCode; + + UnicodeString.Length = ValueNameLength * sizeof(WCHAR); + + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpValueName; + AnsiString.MaximumLength = *lpcbValueName; + RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); + *lpcbValueName = AnsiString.Length; + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegEnumValueW + */ +LONG +STDCALL +RegEnumValueW( + HKEY hKey, + DWORD dwIndex, + LPWSTR lpValueName, + LPDWORD lpcbValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ) +{ + PKEY_VALUE_FULL_INFORMATION ValueInfo; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + ULONG BufferSize; + ULONG ResultSize; + HANDLE KeyHandle; + + Status = MapDefaultKey(&KeyHandle, hKey); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + SetLastError(dwError); + return(dwError); + } + + BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) + + *lpcbValueName * sizeof(WCHAR); + if (lpcbData) + BufferSize += *lpcbData; + + /* We don't know the exact size of the data returned, so call + NtEnumerateValueKey() with a buffer size determined from parameters + to this function. If that call fails with a status code of + STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */ + while (TRUE) { + ValueInfo = RtlAllocateHeap( + RtlGetProcessHeap(), + 0, + BufferSize); + if (ValueInfo == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + + Status = NtEnumerateValueKey( + KeyHandle, + (ULONG)dwIndex, + KeyValueFullInformation, + ValueInfo, + BufferSize, + &ResultSize); + + DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status); + + if (Status == STATUS_BUFFER_OVERFLOW) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo); + BufferSize = ResultSize; + continue; + } + + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + SetLastError(dwError); + break; + } + else + { + if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData)) + { + dwError = ERROR_MORE_DATA; + SetLastError(dwError); + break; + } + + memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength); + *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR)); + RegiTerminateWideString(lpValueName, *lpcbValueName); + + if (lpType) + *lpType = ValueInfo->Type; + + if (lpData) + { + memcpy(lpData, + (PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset), + ValueInfo->DataLength); + *lpcbData = (DWORD)ValueInfo->DataLength; + } + + break; + } + } + + RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo); + + return dwError; +} + + +/************************************************************************ + * RegFlushKey + */ +LONG STDCALL +RegFlushKey(HKEY hKey) +{ + HANDLE KeyHandle; + NTSTATUS Status; + LONG ErrorCode; + + if (hKey == HKEY_PERFORMANCE_DATA) + return(ERROR_SUCCESS); + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + + Status = NtFlushKey(KeyHandle); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + + return(ERROR_SUCCESS); +} + + +/************************************************************************ + * RegGetKeySecurity + */ +LONG +STDCALL +RegGetKeySecurity ( + HKEY hKey, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + LPDWORD lpcbSecurityDescriptor + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegLoadKeyA + */ +LONG +STDCALL +RegLoadKey( + HKEY hKey, + LPCSTR lpSubKey, + LPCSTR lpFile + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegLoadKeyW + */ +LONG +STDCALL +RegLoadKeyW( + HKEY hKey, + LPCWSTR lpSubKey, + LPCWSTR lpFile + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegNotifyChangeKeyValue + */ +LONG +STDCALL +RegNotifyChangeKeyValue( + HKEY hKey, + BOOL bWatchSubtree, + DWORD dwNotifyFilter, + HANDLE hEvent, + BOOL fAsynchronous + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + + +/************************************************************************ + * RegOpenKeyA + */ +LONG STDCALL +RegOpenKeyA(HKEY hKey, + LPCSTR lpSubKey, + PHKEY phkResult) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING SubKeyString; + HANDLE KeyHandle; + LONG ErrorCode; + NTSTATUS Status; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + + RtlCreateUnicodeStringFromAsciiz(&SubKeyString, + (LPSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + Status = NtOpenKey(phkResult, + KEY_ALL_ACCESS, + &ObjectAttributes); + + RtlFreeUnicodeString(&SubKeyString); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + return(ERROR_SUCCESS); +} + + +/************************************************************************ + * RegOpenKeyW + * + * 19981101 Ariadne + * 19990525 EA + */ +LONG +STDCALL +RegOpenKeyW ( + HKEY hKey, + LPCWSTR lpSubKey, + PHKEY phkResult + ) +{ + NTSTATUS errCode; + UNICODE_STRING SubKeyString; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + LONG ErrorCode; + + errCode = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(errCode)) + { + ErrorCode = RtlNtStatusToDosError(errCode); + + SetLastError (ErrorCode); + return ErrorCode; + } + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + errCode = NtOpenKey( + phkResult, + KEY_ALL_ACCESS, + & ObjectAttributes + ); + if ( !NT_SUCCESS(errCode) ) + { + ErrorCode = RtlNtStatusToDosError(errCode); + + SetLastError(ErrorCode); + return ErrorCode; + } + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegOpenKeyExA + */ +LONG STDCALL +RegOpenKeyExA(HKEY hKey, + LPCSTR lpSubKey, + DWORD ulOptions, + REGSAM samDesired, + PHKEY phkResult) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING SubKeyString; + HANDLE KeyHandle; + LONG ErrorCode; + NTSTATUS Status; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + + RtlCreateUnicodeStringFromAsciiz(&SubKeyString, + (LPSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + Status = NtOpenKey(phkResult, + samDesired, + &ObjectAttributes); + + RtlFreeUnicodeString(&SubKeyString); + + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + + return(ERROR_SUCCESS); +} + + +/************************************************************************ + * RegOpenKeyExW + */ +LONG STDCALL +RegOpenKeyExW(HKEY hKey, + LPCWSTR lpSubKey, + DWORD ulOptions, + REGSAM samDesired, + PHKEY phkResult) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING SubKeyString; + HANDLE KeyHandle; + LONG ErrorCode; + NTSTATUS Status; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError (ErrorCode); + return(ErrorCode); + } + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + Status = NtOpenKey(phkResult, + samDesired, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + + SetLastError(ErrorCode); + return(ErrorCode); + } + return(ERROR_SUCCESS); +} + + +/************************************************************************ + * RegQueryInfoKeyA + */ +LONG +STDCALL +RegQueryInfoKeyA( + HKEY hKey, + LPSTR lpClass, + LPDWORD lpcbClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime + ) +{ + WCHAR ClassName[MAX_PATH]; + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + LONG ErrorCode; + + RtlInitUnicodeString(&UnicodeString, NULL); + + if (lpClass) + { + UnicodeString.Buffer = &ClassName[0]; + UnicodeString.MaximumLength = sizeof(ClassName); + } + + ErrorCode = RegQueryInfoKeyW( + hKey, + UnicodeString.Buffer, + lpcbClass, + lpReserved, + lpcSubKeys, + lpcbMaxSubKeyLen, + lpcbMaxClassLen, + lpcValues, + lpcbMaxValueNameLen, + lpcbMaxValueLen, + lpcbSecurityDescriptor, + lpftLastWriteTime); + + if ((ErrorCode == ERROR_SUCCESS) && (lpClass)) + { + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpClass; + AnsiString.MaximumLength = *lpcbClass; + RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); + *lpcbClass = AnsiString.Length; + } + + return ErrorCode; +} + + +/************************************************************************ + * RegQueryInfoKeyW + */ +LONG +STDCALL +RegQueryInfoKeyW( + HKEY hKey, + LPWSTR lpClass, + LPDWORD lpcbClass, + LPDWORD lpReserved, + LPDWORD lpcSubKeys, + LPDWORD lpcbMaxSubKeyLen, + LPDWORD lpcbMaxClassLen, + LPDWORD lpcValues, + LPDWORD lpcbMaxValueNameLen, + LPDWORD lpcbMaxValueLen, + LPDWORD lpcbSecurityDescriptor, + PFILETIME lpftLastWriteTime + ) +{ + KEY_FULL_INFORMATION FullInfoBuffer; + PKEY_FULL_INFORMATION FullInfo; + ULONG FullInfoSize; + HANDLE KeyHandle; + NTSTATUS Status; + LONG ErrorCode; + ULONG Length; + + if ((lpClass) && (!lpcbClass)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + Status = MapDefaultKey(&KeyHandle, hKey); + CHECK_STATUS; + + if (lpClass) + { + FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass; + FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize); + if (!FullInfo) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + + FullInfo->ClassLength = *lpcbClass; + } + else + { + FullInfoSize = sizeof(KEY_FULL_INFORMATION); + FullInfo = &FullInfoBuffer; + FullInfo->ClassLength = 1; + } + + FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class); + + Status = NtQueryKey( + KeyHandle, + KeyFullInformation, + FullInfo, + FullInfoSize, + &Length); + + if (!NT_SUCCESS(Status)) + { + if (lpClass) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo); + } + + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError(ErrorCode); + return ErrorCode; + } + + if (lpcSubKeys) + { + *lpcSubKeys = FullInfo->SubKeys; + } + + if (lpcbMaxSubKeyLen) + { + *lpcbMaxSubKeyLen = FullInfo->MaxNameLen; + } + + if (lpcbMaxClassLen) + { + *lpcbMaxClassLen = FullInfo->MaxClassLen; + } + + if (lpcValues) + { + *lpcValues = FullInfo->Values; + } + + if (lpcbMaxValueNameLen) + { + *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen; + } + + if (lpcbMaxValueLen) + { + *lpcbMaxValueLen = FullInfo->MaxValueDataLen; + } + + if (lpcbSecurityDescriptor) + { + *lpcbSecurityDescriptor = 0; + /* FIXME */ + } + + if (lpftLastWriteTime != NULL) + { + lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart; + lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart; + } + + if (lpClass) + { + wcsncpy(lpClass, FullInfo->Class, *lpcbClass); + RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo); + } + + SetLastError(ERROR_SUCCESS); + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegQueryMultipleValuesA + */ +LONG +STDCALL +RegQueryMultipleValuesA( + HKEY hKey, + PVALENT val_list, + DWORD num_vals, + LPSTR lpValueBuf, + LPDWORD ldwTotsize + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegQueryMultipleValuesW + */ +LONG +STDCALL +RegQueryMultipleValuesW( + HKEY hKey, + PVALENT val_list, + DWORD num_vals, + LPWSTR lpValueBuf, + LPDWORD ldwTotsize + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegQueryValueA + */ +LONG +STDCALL +RegQueryValueA( + HKEY hKey, + LPCSTR lpSubKey, + LPSTR lpValue, + PLONG lpcbValue + ) +{ + WCHAR SubKeyNameBuffer[MAX_PATH+1]; + UNICODE_STRING SubKeyName; + UNICODE_STRING Value; + ANSI_STRING AnsiString; + LONG ValueSize; + LONG ErrorCode; + + if ((lpValue) && (!lpcbValue)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + RtlInitUnicodeString(&SubKeyName, NULL); + RtlInitUnicodeString(&Value, NULL); + + if ((lpSubKey) && (strlen(lpSubKey) != 0)) + { + RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey); + SubKeyName.Buffer = &SubKeyNameBuffer[0]; + SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer); + RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE); + } + + if (lpValue) + { + ValueSize = *lpcbValue * sizeof(WCHAR); + Value.MaximumLength = ValueSize; + Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize); + if (!Value.Buffer) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + } + else + { + ValueSize = 0; + } + + ErrorCode = RegQueryValueW( + hKey, + (LPCWSTR)SubKeyName.Buffer, + Value.Buffer, + &ValueSize); + + if (ErrorCode == ERROR_SUCCESS) + { + Value.Length = ValueSize; + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpValue; + AnsiString.MaximumLength = *lpcbValue; + RtlUnicodeStringToAnsiString(&AnsiString, &Value, FALSE); + } + + *lpcbValue = ValueSize; + + if (Value.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer); + } + + return ErrorCode; +} + + +/************************************************************************ + * RegQueryValueExA + */ +LONG +STDCALL +RegQueryValueExA( + HKEY hKey, + LPSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ) +{ + WCHAR ValueNameBuffer[MAX_PATH+1]; + UNICODE_STRING ValueName; + UNICODE_STRING ValueData; + ANSI_STRING AnsiString; + LONG ErrorCode; + DWORD ResultSize; + DWORD Type; + + /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */ + + if ((lpData) && (!lpcbData)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + RtlInitUnicodeString(&ValueData, NULL); + + if (lpData) + { + ValueData.MaximumLength = *lpcbData * sizeof(WCHAR); + ValueData.Buffer = RtlAllocateHeap( + RtlGetProcessHeap(), + 0, + ValueData.MaximumLength); + if (!ValueData.Buffer) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + } + + RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName); + RtlInitUnicodeString(&ValueName, NULL); + ValueName.Buffer = &ValueNameBuffer[0]; + ValueName.MaximumLength = sizeof(ValueNameBuffer); + RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE); + + if (lpcbData) + { + ResultSize = *lpcbData; + } + else + { + ResultSize = 0; + } + + ErrorCode = RegQueryValueExW( + hKey, + ValueName.Buffer, + lpReserved, + &Type, + (LPBYTE)ValueData.Buffer, + &ResultSize); + + if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL)) + { + if (lpType) + { + *lpType = Type; + } + + if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) + { + ValueData.Length = ResultSize; + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = lpData; + AnsiString.MaximumLength = *lpcbData; + RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE); + } + else + { + RtlMoveMemory(lpData, ValueData.Buffer, ResultSize); + } + } + + if (lpcbData) + { + *lpcbData = ResultSize; + } + + if (ValueData.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer); + } + + return ErrorCode; +} + + +/************************************************************************ + * RegQueryValueExW + */ +LONG +STDCALL +RegQueryValueExW( + HKEY hKey, + LPWSTR lpValueName, + LPDWORD lpReserved, + LPDWORD lpType, + LPBYTE lpData, + LPDWORD lpcbData + ) +{ + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + UNICODE_STRING ValueName; + NTSTATUS Status; + DWORD dwError = ERROR_SUCCESS; + ULONG BufferSize; + ULONG ResultSize; + HANDLE KeyHandle; + + DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n", + hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0); + + Status = MapDefaultKey(&KeyHandle, hKey); + if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + SetLastError(dwError); + return(dwError); + } + + if ((lpData) && (!lpcbData)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + RtlInitUnicodeString (&ValueName, + lpValueName); + + BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData; + ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(), + 0, + BufferSize); + if (ValueInfo == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + + Status = NtQueryValueKey (hKey, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + + DPRINT("Status 0x%X\n", Status); + + if (Status == STATUS_BUFFER_TOO_SMALL) + { + /* Return ERROR_SUCCESS and the buffer space needed for a successful call */ + dwError = ERROR_SUCCESS; + } + else if (!NT_SUCCESS(Status)) + { + dwError = RtlNtStatusToDosError(Status); + SetLastError(dwError); + } + else + { + if (lpType) + { + *lpType = ValueInfo->Type; + } + + RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength); + if ((ValueInfo->Type == REG_SZ) || + (ValueInfo->Type == REG_MULTI_SZ) || + (ValueInfo->Type == REG_EXPAND_SZ)) + { + ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0; + } + } + + DPRINT("Type %d ResultSize %d\n", ValueInfo->Type, ResultSize); + + *lpcbData = (DWORD)ResultSize; + + RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo); + + return dwError; +} + + +/************************************************************************ + * RegQueryValueW + */ +LONG +STDCALL +RegQueryValueW( + HKEY hKey, + LPCWSTR lpSubKey, + LPWSTR lpValue, + PLONG lpcbValue + ) +{ + NTSTATUS errCode; + UNICODE_STRING SubKeyString; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + HANDLE RealKey; + LONG ErrorCode; + BOOL CloseRealKey; + + errCode = MapDefaultKey(&KeyHandle, hKey); + if (!NT_SUCCESS(errCode)) + { + ErrorCode = RtlNtStatusToDosError(errCode); + SetLastError (ErrorCode); + return ErrorCode; + } + + if ((lpSubKey) && (wcslen(lpSubKey) != 0)) + { + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + errCode = NtOpenKey( + &RealKey, + KEY_ALL_ACCESS, + & ObjectAttributes + ); + if ( !NT_SUCCESS(errCode) ) + { + ErrorCode = RtlNtStatusToDosError(errCode); + SetLastError(ErrorCode); + return ErrorCode; + } + CloseRealKey = TRUE; + } + else + { + RealKey = hKey; + CloseRealKey = FALSE; + } + + ErrorCode = RegQueryValueExW( + RealKey, + NULL, + NULL, + NULL, + (LPBYTE)lpValue, + (LPDWORD)lpcbValue); + + if (CloseRealKey) + { + NtClose(RealKey); + } + + return ErrorCode; +} + + +/************************************************************************ + * RegReplaceKeyA + */ +LONG +STDCALL +RegReplaceKeyA( + HKEY hKey, + LPCSTR lpSubKey, + LPCSTR lpNewFile, + LPCSTR lpOldFile + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegReplaceKeyW + */ +LONG +STDCALL +RegReplaceKeyW( + HKEY hKey, + LPCWSTR lpSubKey, + LPCWSTR lpNewFile, + LPCWSTR lpOldFile + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegRestoreKeyA + */ +LONG +STDCALL +RegRestoreKeyA( + HKEY hKey, + LPCSTR lpFile, + DWORD dwFlags + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegRestoreKeyW + */ +LONG +STDCALL +RegRestoreKeyW( + HKEY hKey, + LPCWSTR lpFile, + DWORD dwFlags + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegSaveKeyA + */ +LONG STDCALL +RegSaveKeyA(HKEY hKey, + LPCSTR lpFile, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + UNICODE_STRING FileName; + LONG ErrorCode; + + RtlCreateUnicodeStringFromAsciiz(&FileName, + (LPSTR)lpFile); + ErrorCode = RegSaveKeyW(hKey, + FileName.Buffer, + lpSecurityAttributes); + RtlFreeUnicodeString(&FileName); + + return(ErrorCode); +} + + +/************************************************************************ + * RegSaveKeyW + */ +LONG STDCALL +RegSaveKeyW(HKEY hKey, + LPCWSTR lpFile, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING NtName; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE FileHandle; + HANDLE KeyHandle; + NTSTATUS Status; + LONG ErrorCode; + + Status = MapDefaultKey(&KeyHandle, + hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError(ErrorCode); + return(ErrorCode); + } + + if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFile, + &NtName, + NULL, + NULL)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return(ERROR_INVALID_PARAMETER); + } + + if (lpSecurityAttributes != NULL) + SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; + + InitializeObjectAttributes(&ObjectAttributes, + &NtName, + OBJ_CASE_INSENSITIVE, + NULL, + SecurityDescriptor); + + Status = NtCreateFile(&FileHandle, + GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_CREATE, + FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + RtlFreeUnicodeString(&NtName); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError(ErrorCode); + return(ErrorCode); + } + + Status = NtSaveKey(KeyHandle, + FileHandle); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError(ErrorCode); + return(ErrorCode); + } + + return(ERROR_SUCCESS); +} + + +/************************************************************************ + * RegSetKeySecurity + */ +LONG +STDCALL +RegSetKeySecurity( + HKEY hKey, + SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG? */ + PSECURITY_DESCRIPTOR pSecurityDescriptor + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegSetValueA + */ +LONG +STDCALL +RegSetValueA( + HKEY hKey, + LPCSTR lpSubKey, + DWORD dwType, + LPCSTR lpData, + DWORD cbData + ) +{ + WCHAR SubKeyNameBuffer[MAX_PATH+1]; + UNICODE_STRING SubKeyName; + UNICODE_STRING Data; + ANSI_STRING AnsiString; + LONG DataSize; + LONG ErrorCode; + + if (!lpData) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + RtlInitUnicodeString(&SubKeyName, NULL); + RtlInitUnicodeString(&Data, NULL); + + if ((lpSubKey) && (strlen(lpSubKey) != 0)) + { + RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey); + SubKeyName.Buffer = &SubKeyNameBuffer[0]; + SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer); + RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE); + } + + DataSize = cbData * sizeof(WCHAR); + Data.MaximumLength = DataSize; + Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize); + if (!Data.Buffer) + { + SetLastError(ERROR_OUTOFMEMORY); + return ERROR_OUTOFMEMORY; + } + + ErrorCode = RegSetValueW( + hKey, + (LPCWSTR)SubKeyName.Buffer, + dwType, + Data.Buffer, + DataSize); + + RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer); + + return ErrorCode; +} + + +/************************************************************************ + * RegSetValueExA + */ +LONG +STDCALL +RegSetValueExA( + HKEY hKey, + LPCSTR lpValueName, + DWORD Reserved, + DWORD dwType, + CONST BYTE *lpData, + DWORD cbData + ) +{ + UNICODE_STRING ValueName; + LPWSTR pValueName; + ANSI_STRING AnsiString; + UNICODE_STRING Data; + LONG ErrorCode; + LPBYTE pData; + DWORD DataSize; + + if (!lpData) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + if ((lpValueName) && (strlen(lpValueName) != 0)) + { + RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName); + pValueName = (LPWSTR)ValueName.Buffer; + } + else + { + pValueName = NULL; + } + + if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)) + { + RtlInitAnsiString(&AnsiString, NULL); + AnsiString.Buffer = (LPSTR)lpData; + AnsiString.Length = cbData; + AnsiString.MaximumLength = cbData; + RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE); + pData = (LPBYTE)Data.Buffer; + DataSize = cbData * sizeof(WCHAR); + } + else + { + RtlInitUnicodeString(&Data, NULL); + pData = (LPBYTE)lpData; + DataSize = cbData; + } + + ErrorCode = RegSetValueExW( + hKey, + pValueName, + Reserved, + dwType, + pData, + DataSize); + + if (pValueName) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer); + } + + if (Data.Buffer) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer); + } + + return ErrorCode; +} + + +/************************************************************************ + * RegSetValueExW + */ +LONG +STDCALL +RegSetValueExW( + HKEY hKey, + LPCWSTR lpValueName, + DWORD Reserved, + DWORD dwType, + CONST BYTE *lpData, + DWORD cbData + ) +{ + UNICODE_STRING ValueName; + PUNICODE_STRING pValueName; + HANDLE KeyHandle; + NTSTATUS Status; + LONG ErrorCode; + + Status = MapDefaultKey(&KeyHandle, hKey); + if (!NT_SUCCESS(Status)) + { + ErrorCode = RtlNtStatusToDosError(Status); + SetLastError(ErrorCode); + return ErrorCode; + } + + if (lpValueName) + { + RtlInitUnicodeString(&ValueName, lpValueName); + pValueName = &ValueName; + } + else + { + pValueName = NULL; + } + + Status = NtSetValueKey( + KeyHandle, + pValueName, + 0, + dwType, + (PVOID)lpData, + (ULONG)cbData); + if (!NT_SUCCESS(Status)) + { + LONG ErrorCode = RtlNtStatusToDosError(Status); + SetLastError (ErrorCode); + return ErrorCode; + } + + return ERROR_SUCCESS; +} + + +/************************************************************************ + * RegSetValueW + */ +LONG +STDCALL +RegSetValueW( + HKEY hKey, + LPCWSTR lpSubKey, + DWORD dwType, + LPCWSTR lpData, + DWORD cbData + ) +{ + NTSTATUS errCode; + UNICODE_STRING SubKeyString; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + HANDLE RealKey; + LONG ErrorCode; + BOOL CloseRealKey; + + errCode = MapDefaultKey(&KeyHandle, hKey); + if (!NT_SUCCESS(errCode)) + { + ErrorCode = RtlNtStatusToDosError(errCode); + SetLastError (ErrorCode); + return ErrorCode; + } + + if ((lpSubKey) && (wcslen(lpSubKey) != 0)) + { + + RtlInitUnicodeString(&SubKeyString, + (LPWSTR)lpSubKey); + + InitializeObjectAttributes(&ObjectAttributes, + &SubKeyString, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + errCode = NtOpenKey( + &RealKey, + KEY_ALL_ACCESS, + & ObjectAttributes + ); + if ( !NT_SUCCESS(errCode) ) + { + ErrorCode = RtlNtStatusToDosError(errCode); + SetLastError(ErrorCode); + return ErrorCode; + } + CloseRealKey = TRUE; + } + else + { + RealKey = hKey; + CloseRealKey = FALSE; + } + + ErrorCode = RegSetValueExW( + RealKey, + NULL, + 0, + dwType, + (LPBYTE)lpData, + cbData); + + if (CloseRealKey) + { + NtClose(RealKey); + } + + return ErrorCode; +} + + +/************************************************************************ + * RegUnLoadKeyA + */ +LONG +STDCALL +RegUnLoadKeyA( + HKEY hKey, + LPCSTR lpSubKey + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + + +/************************************************************************ + * RegUnLoadKeyW + */ +LONG +STDCALL +RegUnLoadKeyW( + HKEY hKey, + LPCWSTR lpSubKey + ) +{ + UNIMPLEMENTED; + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/lib/advapi32/sec/ac.c b/lib/advapi32/sec/ac.c new file mode 100644 index 0000000..9c82d4f --- /dev/null +++ b/lib/advapi32/sec/ac.c @@ -0,0 +1,375 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/sec/ac.c + * PURPOSE: ACL/ACE functions + */ + +#include +#include +#include + + +/* --- ACL --- */ + +WINBOOL +STDCALL +GetAclInformation ( + PACL pAcl, + LPVOID pAclInformation, + DWORD nAclInformationLength, + ACL_INFORMATION_CLASS dwAclInformationClass + ) +{ + NTSTATUS Status; + + Status = RtlQueryInformationAcl (pAcl, + pAclInformation, + nAclInformationLength, + dwAclInformationClass); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +#if 0 +DWORD +WINAPI +GetAuditedPermissionsFromAclA ( + IN PACL pacl, + IN PTRUSTEE_A pTrustee, + OUT PACCESS_MASK pSuccessfulAuditedRights, + OUT PACCESS_MASK pFailedAuditRights + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +WINAPI +GetAuditedPermissionsFromAclW ( + IN PACL pacl, + IN PTRUSTEE_W pTrustee, + OUT PACCESS_MASK pSuccessfulAuditedRights, + OUT PACCESS_MASK pFailedAuditRights + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +WINAPI +GetEffectiveRightsFromAclA ( + IN PACL pacl, + IN PTRUSTEE_A pTrustee, + OUT PACCESS_MASK pAccessRights + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +WINAPI +GetEffectiveRightsFromAclW ( + IN PACL pacl, + IN PTRUSTEE_W pTrustee, + OUT PACCESS_MASK pAccessRights + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +WINAPI +GetExplicitEntriesFromAclA ( + IN PACL pacl, + OUT PULONG pcCountOfExplicitEntries, + OUT PEXPLICIT_ACCESS_A * pListOfExplicitEntries + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +WINAPI +GetExplicitEntriesFromAclW ( + IN PACL pacl, + OUT PULONG pcCountOfExplicitEntries, + OUT PEXPLICIT_ACCESS_W * pListOfExplicitEntries + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} +#endif + + +WINBOOL +STDCALL +InitializeAcl ( + PACL pAcl, + DWORD nAclLength, + DWORD dwAclRevision + ) +{ + NTSTATUS Status; + + Status = RtlCreateAcl (pAcl, + nAclLength, + dwAclRevision); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +IsValidAcl ( + PACL pAcl + ) +{ + return RtlValidAcl (pAcl); +} + + +WINBOOL +STDCALL +SetAclInformation ( + PACL pAcl, + LPVOID pAclInformation, + DWORD nAclInformationLength, + ACL_INFORMATION_CLASS dwAclInformationClass + ) +{ + NTSTATUS Status; + + Status = RtlSetInformationAcl (pAcl, + pAclInformation, + nAclInformationLength, + dwAclInformationClass); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +#if 0 +DWORD +WINAPI +SetEntriesInAclA ( + IN ULONG cCountOfExplicitEntries, + IN PEXPLICIT_ACCESS_A pListOfExplicitEntries, + IN PACL OldAcl, + OUT PACL * NewAcl + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +WINAPI +SetEntriesInAclW ( + IN ULONG cCountOfExplicitEntries, + IN PEXPLICIT_ACCESS_W pListOfExplicitEntries, + IN PACL OldAcl, + OUT PACL * NewAcl + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} +#endif + + + +/* --- ACE --- */ + +WINBOOL +STDCALL +AddAccessAllowedAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD AccessMask, + PSID pSid + ) +{ + NTSTATUS Status; + + Status = RtlAddAccessAllowedAce (pAcl, + dwAceRevision, + AccessMask, + pSid); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +AddAccessDeniedAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD AccessMask, + PSID pSid + ) +{ + NTSTATUS Status; + + Status = RtlAddAccessDeniedAce (pAcl, + dwAceRevision, + AccessMask, + pSid); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +AddAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD dwStartingAceIndex, + LPVOID pAceList, + DWORD nAceListLength + ) +{ + NTSTATUS Status; + + Status = RtlAddAce (pAcl, + dwAceRevision, + dwStartingAceIndex, + pAceList, + nAceListLength); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +AddAuditAccessAce ( + PACL pAcl, + DWORD dwAceRevision, + DWORD dwAccessMask, + PSID pSid, + WINBOOL bAuditSuccess, + WINBOOL bAuditFailure + ) +{ + NTSTATUS Status; + + Status = RtlAddAuditAccessAce (pAcl, + dwAceRevision, + dwAccessMask, + pSid, + bAuditSuccess, + bAuditFailure); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +DeleteAce ( + PACL pAcl, + DWORD dwAceIndex + ) +{ + NTSTATUS Status; + + Status = RtlDeleteAce (pAcl, + dwAceIndex); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +FindFirstFreeAce ( + PACL pAcl, + LPVOID * pAce + ) +{ + return RtlFirstFreeAce (pAcl, + (PACE*)pAce); +} + + +WINBOOL +STDCALL +GetAce ( + PACL pAcl, + DWORD dwAceIndex, + LPVOID * pAce + ) +{ + NTSTATUS Status; + + Status = RtlGetAce (pAcl, + dwAceIndex, + (PACE*)pAce); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/advapi32/sec/lsa.c b/lib/advapi32/sec/lsa.c new file mode 100644 index 0000000..c6041da --- /dev/null +++ b/lib/advapi32/sec/lsa.c @@ -0,0 +1,586 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/sec/lsa.c + * PURPOSE: Local security authority functions + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 19990322 EA created + * 19990515 EA stubs + */ +#include +#include + + +/********************************************************************** + * LsaAddAccountRights + */ +INT +STDCALL +LsaAddAccountRights (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaAddPrivilegesToAccount + */ +INT +STDCALL +LsaAddPrivilegesToAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaClearAuditLog + */ +INT +STDCALL +LsaClearAuditLog (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaClose + */ +INT +STDCALL +LsaClose (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaCreateAccount + */ +INT +STDCALL +LsaCreateAccount ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaCreateSecret + */ +INT +STDCALL +LsaCreateSecret (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaCreateTrustedDomain + */ +INT +STDCALL +LsaCreateTrustedDomain (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaDelete + */ +INT +STDCALL +LsaDelete (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaDeleteTrustedDomain + */ +INT +STDCALL +LsaDeleteTrustedDomain (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaEnumerateAccountRights + */ +INT +STDCALL +LsaEnumerateAccountRights (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaEnumerateAccounts + */ +INT +STDCALL +LsaEnumerateAccounts (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaEnumerateAccountsWithUserRight + */ +INT +STDCALL +LsaEnumerateAccountsWithUserRight (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaEnumeratePrivileges + */ +INT +STDCALL +LsaEnumeratePrivileges (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaEnumeratePrivilegesOfAccount + */ +INT +STDCALL +LsaEnumeratePrivilegesOfAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaEnumerateTrustedDomains + */ +INT +STDCALL +LsaEnumerateTrustedDomains (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaFreeMemory + */ +INT +STDCALL +LsaFreeMemory (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaGetQuotasForAccount + */ +INT +STDCALL +LsaGetQuotasForAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaGetSystemAccessAccount + */ +INT +STDCALL +LsaGetSystemAccessAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaGetUserName + */ +INT +STDCALL +LsaGetUserName (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaICLookupNames + */ +INT +STDCALL +LsaICLookupNames (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaICLookupSids + */ +INT +STDCALL +LsaICLookupSids (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaLookupNames + */ +INT +STDCALL +LsaLookupNames (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaLookupPrivilegeDisplayName + */ +INT +STDCALL +LsaLookupPrivilegeDisplayName (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaLookupPrivilegeName + */ +INT +STDCALL +LsaLookupPrivilegeName (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaLookupPrivilegeValue + */ +INT +STDCALL +LsaLookupPrivilegeValue (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaLookupSids + */ +INT +STDCALL +LsaLookupSids (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaNtStatusToWinError + */ +INT +STDCALL +LsaNtStatusToWinError (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaOpenAccount + */ +INT +STDCALL +LsaOpenAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaOpenPolicy + */ +INT +STDCALL +LsaOpenPolicy (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaOpenSecret + */ +INT +STDCALL +LsaOpenSecret (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaOpenTrustedDomain + */ +INT +STDCALL +LsaOpenTrustedDomain (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaQueryInfoTrustedDomain + */ +INT +STDCALL +LsaQueryInfoTrustedDomain (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaQueryInformationPolicy + */ +INT +STDCALL +LsaQueryInformationPolicy (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaQuerySecret + */ +INT +STDCALL +LsaQuerySecret (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaQuerySecurityObject + */ +INT +STDCALL +LsaQuerySecurityObject (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaQueryTrustedDomainInfo + */ +INT +STDCALL +LsaQueryTrustedDomainInfo (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaRemoveAccountRights + */ +INT +STDCALL +LsaRemoveAccountRights (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaRemovePrivilegesFromAccount + */ +INT +STDCALL +LsaRemovePrivilegesFromAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaRetrievePrivateData + */ +INT +STDCALL +LsaRetrievePrivateData (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetInformationPolicy + */ +INT +STDCALL +LsaSetInformationPolicy (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetInformationTrustedDomain + */ +INT +STDCALL +LsaSetInformationTrustedDomain (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetQuotasForAccount + */ +INT +STDCALL +LsaSetQuotasForAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetSecret + */ +INT +STDCALL +LsaSetSecret (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetSecurityObject + */ +INT +STDCALL +LsaSetSecurityObject (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetSystemAccessAccount + */ +INT +STDCALL +LsaSetSystemAccessAccount (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaSetTrustedDomainInformation + */ +INT +STDCALL +LsaSetTrustedDomainInformation (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * LsaStorePrivateData + */ +INT +STDCALL +LsaStorePrivateData (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* EOF */ + diff --git a/lib/advapi32/sec/misc.c b/lib/advapi32/sec/misc.c new file mode 100644 index 0000000..9c6e602 --- /dev/null +++ b/lib/advapi32/sec/misc.c @@ -0,0 +1,112 @@ +/* + */ + +#include +#include +#include + + +WINBOOL STDCALL +AreAllAccessesGranted(DWORD GrantedAccess, + DWORD DesiredAccess) +{ + return((BOOL)RtlAreAllAccessesGranted(GrantedAccess, + DesiredAccess)); +} + + +WINBOOL STDCALL +AreAnyAccessesGranted(DWORD GrantedAccess, + DWORD DesiredAccess) +{ + return((BOOL)RtlAreAnyAccessesGranted(GrantedAccess, + DesiredAccess)); +} + + +WINBOOL STDCALL +GetKernelObjectSecurity(HANDLE Handle, + SECURITY_INFORMATION RequestedInformation, + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD nLength, + LPDWORD lpnLengthNeeded) +{ + NTSTATUS Status; + + Status = NtQuerySecurityObject(Handle, + RequestedInformation, + pSecurityDescriptor, + nLength, + lpnLengthNeeded); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + return(TRUE); +} + + +BOOL STDCALL +SetKernelObjectSecurity(HANDLE Handle, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + NTSTATUS Status; + + Status = NtSetSecurityObject(Handle, + SecurityInformation, + SecurityDescriptor); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + return(TRUE); +} + + +VOID STDCALL +MapGenericMask(PDWORD AccessMask, + PGENERIC_MAPPING GenericMapping) +{ + RtlMapGenericMask(AccessMask, + GenericMapping); +} + + +BOOL STDCALL +ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel) +{ + NTSTATUS Status; + + Status = RtlImpersonateSelf(ImpersonationLevel); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + return(TRUE); +} + + +BOOL STDCALL +RevertToSelf(VOID) +{ + NTSTATUS Status; + HANDLE Token = NULL; + + Status = NtSetInformationThread(NtCurrentThread(), + ThreadImpersonationToken, + &Token, + sizeof(HANDLE)); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + return(TRUE); +} + +/* EOF */ + diff --git a/lib/advapi32/sec/sec.c b/lib/advapi32/sec/sec.c new file mode 100644 index 0000000..03fa134 --- /dev/null +++ b/lib/advapi32/sec/sec.c @@ -0,0 +1,366 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/sec/sec.c + * PURPOSE: Registry functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include +#include + + +BOOL +STDCALL +GetSecurityDescriptorControl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL pControl, + LPDWORD lpdwRevision + ) +{ + NTSTATUS Status; + + Status = RtlGetControlSecurityDescriptor (pSecurityDescriptor, + pControl, + (PULONG)lpdwRevision); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +GetSecurityDescriptorDacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + LPBOOL lpbDaclPresent, + PACL *pDacl, + LPBOOL lpbDaclDefaulted + ) +{ + BOOLEAN DaclPresent; + BOOLEAN DaclDefaulted; + NTSTATUS Status; + + Status = RtlGetDaclSecurityDescriptor (pSecurityDescriptor, + &DaclPresent, + pDacl, + &DaclDefaulted); + *lpbDaclPresent = (BOOL)DaclPresent; + *lpbDaclDefaulted = (BOOL)DaclDefaulted; + + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +GetSecurityDescriptorGroup ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID *pGroup, + LPBOOL lpbGroupDefaulted + ) +{ + BOOLEAN GroupDefaulted; + NTSTATUS Status; + + Status = RtlGetGroupSecurityDescriptor (pSecurityDescriptor, + pGroup, + &GroupDefaulted); + *lpbGroupDefaulted = (BOOL)GroupDefaulted; + + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +DWORD +STDCALL +GetSecurityDescriptorLength ( + PSECURITY_DESCRIPTOR pSecurityDescriptor + ) +{ + return RtlLengthSecurityDescriptor(pSecurityDescriptor); +} + + +BOOL +STDCALL +GetSecurityDescriptorOwner ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID *pOwner, + LPBOOL lpbOwnerDefaulted +) +{ + BOOLEAN OwnerDefaulted; + NTSTATUS Status; + + Status = RtlGetOwnerSecurityDescriptor (pSecurityDescriptor, + pOwner, + &OwnerDefaulted); + *lpbOwnerDefaulted = (BOOL)OwnerDefaulted; + + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +GetSecurityDescriptorSacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + LPBOOL lpbSaclPresent, + PACL *pSacl, + LPBOOL lpbSaclDefaulted + ) +{ + BOOLEAN SaclPresent; + BOOLEAN SaclDefaulted; + NTSTATUS Status; + + Status = RtlGetSaclSecurityDescriptor (pSecurityDescriptor, + &SaclPresent, + pSacl, + &SaclDefaulted); + *lpbSaclPresent = (BOOL)SaclPresent; + *lpbSaclDefaulted = (BOOL)SaclDefaulted; + + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +InitializeSecurityDescriptor ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + DWORD dwRevision + ) +{ + NTSTATUS Status; + + Status = RtlCreateSecurityDescriptor (pSecurityDescriptor, + dwRevision); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + +BOOL +STDCALL +IsValidSecurityDescriptor ( + PSECURITY_DESCRIPTOR pSecurityDescriptor + ) +{ + BOOLEAN Result; + + Result = RtlValidSecurityDescriptor (pSecurityDescriptor); + if (Result == FALSE) + SetLastError (RtlNtStatusToDosError (STATUS_INVALID_SECURITY_DESCR)); + + return (BOOL)Result; +} + + +WINBOOL +STDCALL +MakeAbsoluteSD ( + PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, + PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, + LPDWORD lpdwAbsoluteSecurityDescriptorSize, + PACL pDacl, + LPDWORD lpdwDaclSize, + PACL pSacl, + LPDWORD lpdwSaclSize, + PSID pOwner, + LPDWORD lpdwOwnerSize, + PSID pPrimaryGroup, + LPDWORD lpdwPrimaryGroupSize + ) +{ + NTSTATUS Status; + + Status = RtlSelfRelativeToAbsoluteSD (pSelfRelativeSecurityDescriptor, + pAbsoluteSecurityDescriptor, + lpdwAbsoluteSecurityDescriptorSize, + pDacl, + lpdwDaclSize, + pSacl, + lpdwSaclSize, + pOwner, + lpdwOwnerSize, + pPrimaryGroup, + lpdwPrimaryGroupSize); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +MakeSelfRelativeSD ( + PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, + PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, + LPDWORD lpdwBufferLength + ) +{ + NTSTATUS Status; + + Status = RtlAbsoluteToSelfRelativeSD (pAbsoluteSecurityDescriptor, + pSelfRelativeSecurityDescriptor, + (PULONG)lpdwBufferLength); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +SetSecurityDescriptorDacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + BOOL bDaclPresent, + PACL pDacl, + BOOL bDaclDefaulted + ) +{ + NTSTATUS Status; + + Status = RtlSetDaclSecurityDescriptor (pSecurityDescriptor, + bDaclPresent, + pDacl, + bDaclDefaulted); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +SetSecurityDescriptorGroup ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID pGroup, + BOOL bGroupDefaulted + ) +{ + NTSTATUS Status; + + Status = RtlSetGroupSecurityDescriptor (pSecurityDescriptor, + pGroup, + bGroupDefaulted); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +SetSecurityDescriptorOwner ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + PSID pOwner, + BOOL bOwnerDefaulted + ) +{ + NTSTATUS Status; + + Status = RtlSetGroupSecurityDescriptor (pSecurityDescriptor, + pOwner, + bOwnerDefaulted); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +BOOL +STDCALL +SetSecurityDescriptorSacl ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + BOOL bSaclPresent, + PACL pSacl, + BOOL bSaclDefaulted + ) +{ + NTSTATUS Status; + + Status = RtlSetSaclSecurityDescriptor (pSecurityDescriptor, + bSaclPresent, + pSacl, + bSaclDefaulted); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + +BOOL STDCALL +GetUserNameA(LPSTR lpBuffer, LPDWORD nSize) +{ + return(FALSE); +} + +BOOL STDCALL +GetUserNameW(LPWSTR lpBuffer, LPDWORD nSize) +{ + return(FALSE); +} + +/* EOF */ diff --git a/lib/advapi32/sec/sid.c b/lib/advapi32/sec/sid.c new file mode 100644 index 0000000..5cd6de2 --- /dev/null +++ b/lib/advapi32/sec/sid.c @@ -0,0 +1,243 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/sec/sid.c + * PURPOSE: Security ID functions + */ + +#include +#include +#include + + +BOOL STDCALL +AllocateLocallyUniqueId(PLUID Luid) +{ + NTSTATUS Status; + + Status = NtAllocateLocallyUniqueId(Luid); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + return(TRUE); +} + +BOOL STDCALL +AllocateAndInitializeSid ( + PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, + BYTE nSubAuthorityCount, + DWORD dwSubAuthority0, + DWORD dwSubAuthority1, + DWORD dwSubAuthority2, + DWORD dwSubAuthority3, + DWORD dwSubAuthority4, + DWORD dwSubAuthority5, + DWORD dwSubAuthority6, + DWORD dwSubAuthority7, + PSID *pSid +) +{ + NTSTATUS Status; + + Status = RtlAllocateAndInitializeSid (pIdentifierAuthority, + nSubAuthorityCount, + dwSubAuthority0, + dwSubAuthority1, + dwSubAuthority2, + dwSubAuthority3, + dwSubAuthority4, + dwSubAuthority5, + dwSubAuthority6, + dwSubAuthority7, + pSid); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + +BOOL +STDCALL +CopySid ( + DWORD nDestinationSidLength, + PSID pDestinationSid, + PSID pSourceSid +) +{ + NTSTATUS Status; + + Status = RtlCopySid (nDestinationSidLength, + pDestinationSid, + pSourceSid); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + +WINBOOL +STDCALL +EqualPrefixSid ( + PSID pSid1, + PSID pSid2 + ) +{ + return RtlEqualPrefixSid (pSid1, pSid2); +} + +WINBOOL +STDCALL +EqualSid ( + PSID pSid1, + PSID pSid2 + ) +{ + return RtlEqualSid (pSid1, pSid2); +} + +PVOID +STDCALL +FreeSid ( + PSID pSid + ) +{ + return RtlFreeSid (pSid); +} + +DWORD +STDCALL +GetLengthSid ( + PSID pSid + ) +{ + return (DWORD)RtlLengthSid (pSid); +} + +PSID_IDENTIFIER_AUTHORITY +STDCALL +GetSidIdentifierAuthority ( + PSID pSid + ) +{ + return RtlIdentifierAuthoritySid (pSid); +} + +DWORD +STDCALL +GetSidLengthRequired ( + UCHAR nSubAuthorityCount + ) +{ + return (DWORD)RtlLengthRequiredSid (nSubAuthorityCount); +} + +PDWORD +STDCALL +GetSidSubAuthority ( + PSID pSid, + DWORD nSubAuthority + ) +{ + return (PDWORD)RtlSubAuthoritySid (pSid, nSubAuthority); +} + +PUCHAR +STDCALL +GetSidSubAuthorityCount ( + PSID pSid + ) +{ + return RtlSubAuthorityCountSid (pSid); +} + +WINBOOL +STDCALL +InitializeSid ( + PSID Sid, + PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, + BYTE nSubAuthorityCount + ) +{ + NTSTATUS Status; + + Status = RtlInitializeSid (Sid, + pIdentifierAuthority, + nSubAuthorityCount); + if (!NT_SUCCESS(Status)) + { + SetLastError (RtlNtStatusToDosError (Status)); + return FALSE; + } + + return TRUE; +} + + +WINBOOL STDCALL +IsValidSid(PSID pSid) +{ + return((WINBOOL)RtlValidSid(pSid)); +} + + +WINBOOL STDCALL +LookupAccountNameA(LPCSTR lpSystemName, + LPCSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPSTR DomainName, + LPDWORD cbDomainName, + PSID_NAME_USE peUse) +{ + return(FALSE); +} + + +WINBOOL STDCALL +LookupAccountNameW(LPCWSTR lpSystemName, + LPCWSTR lpAccountName, + PSID Sid, + LPDWORD cbSid, + LPWSTR DomainName, + LPDWORD cbDomainName, + PSID_NAME_USE peUse) +{ + return(FALSE); +} + + +WINBOOL STDCALL +LookupAccountSidA(LPCSTR lpSystemName, + PSID Sid, + LPSTR Name, + LPDWORD cbName, + LPSTR ReferencedDomainName, + LPDWORD cbReferencedDomainName, + PSID_NAME_USE peUse) +{ + return(FALSE); +} + + +WINBOOL STDCALL +LookupAccountSidW(LPCWSTR lpSystemName, + PSID Sid, + LPWSTR Name, + LPDWORD cbName, + LPWSTR ReferencedDomainName, + LPDWORD cbReferencedDomainName, + PSID_NAME_USE peUse) +{ + return(FALSE); +} + +/* EOF */ diff --git a/lib/advapi32/service/scm.c b/lib/advapi32/service/scm.c new file mode 100644 index 0000000..57ae15e --- /dev/null +++ b/lib/advapi32/service/scm.c @@ -0,0 +1,749 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/service/scm.c + * PURPOSE: Service control manager functions + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 19990413 EA created + * 19990515 EA + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * ChangeServiceConfigA + */ +BOOL +STDCALL +ChangeServiceConfigA( + SC_HANDLE hService, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCSTR lpDependencies, + LPCSTR lpServiceStartName, + LPCSTR lpPassword, + LPCSTR lpDisplayName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * ChangeServiceConfigW + */ +BOOL +STDCALL +ChangeServiceConfigW( + SC_HANDLE hService, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCWSTR lpBinaryPathName, + LPCWSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCWSTR lpDependencies, + LPCWSTR lpServiceStartName, + LPCWSTR lpPassword, + LPCWSTR lpDisplayName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * CloseServiceHandle + */ +BOOL +STDCALL +CloseServiceHandle( SC_HANDLE hSCObject ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * ControlService + */ +BOOL +STDCALL +ControlService( + SC_HANDLE hService, + DWORD dwControl, + LPSERVICE_STATUS lpServiceStatus + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * CreateServiceA + */ +SC_HANDLE +STDCALL +CreateServiceA( + SC_HANDLE hSCManager, + LPCSTR lpServiceName, + LPCSTR lpDisplayName, + DWORD dwDesiredAccess, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCSTR lpBinaryPathName, + LPCSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCSTR lpDependencies, + LPCSTR lpServiceStartName, + LPCSTR lpPassword + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * CreateServiceW + */ +SC_HANDLE +STDCALL +CreateServiceW( + SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + LPCWSTR lpDisplayName, + DWORD dwDesiredAccess, + DWORD dwServiceType, + DWORD dwStartType, + DWORD dwErrorControl, + LPCWSTR lpBinaryPathName, + LPCWSTR lpLoadOrderGroup, + LPDWORD lpdwTagId, + LPCWSTR lpDependencies, + LPCWSTR lpServiceStartName, + LPCWSTR lpPassword + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * DeleteService + */ +BOOL +STDCALL +DeleteService( SC_HANDLE hService ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumDependentServicesA + */ +BOOL +STDCALL +EnumDependentServicesA( + SC_HANDLE hService, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSA lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumDependentServicesW + */ +BOOL +STDCALL +EnumDependentServicesW( + SC_HANDLE hService, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumServiceGroupW + * + * (unknown) + */ +BOOL +STDCALL +EnumServiceGroupW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumServicesStatusA + */ +BOOL +STDCALL +EnumServicesStatusA ( + SC_HANDLE hSCManager, + DWORD dwServiceType, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSA lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumServicesStatusExA + */ +BOOL +STDCALL +EnumServicesStatusExA(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumServicesStatusExW + */ +BOOL +STDCALL +EnumServicesStatusExW(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * EnumServicesStatusW + */ +BOOL +STDCALL +EnumServicesStatusW( + SC_HANDLE hSCManager, + DWORD dwServiceType, + DWORD dwServiceState, + LPENUM_SERVICE_STATUSW lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * GetServiceDisplayNameA + */ +BOOL +STDCALL +GetServiceDisplayNameA( + SC_HANDLE hSCManager, + LPCSTR lpServiceName, + LPSTR lpDisplayName, + LPDWORD lpcchBuffer + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * GetServiceDisplayNameW + */ +BOOL +STDCALL +GetServiceDisplayNameW( + SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + LPWSTR lpDisplayName, + LPDWORD lpcchBuffer + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * GetServiceKeyNameA + */ +BOOL +STDCALL +GetServiceKeyNameA( + SC_HANDLE hSCManager, + LPCSTR lpDisplayName, + LPSTR lpServiceName, + LPDWORD lpcchBuffer + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * GetServiceKeyNameW + */ +BOOL +STDCALL +GetServiceKeyNameW( + SC_HANDLE hSCManager, + LPCWSTR lpDisplayName, + LPWSTR lpServiceName, + LPDWORD lpcchBuffer + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/********************************************************************** + * LockServiceDatabase + */ +SC_LOCK +STDCALL +LockServiceDatabase( + SC_HANDLE hSCManager + ) +{ + SetLastError (ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * OpenSCManagerA + */ +SC_HANDLE STDCALL +OpenSCManagerA(LPCSTR lpMachineName, + LPCSTR lpDatabaseName, + DWORD dwDesiredAccess) +{ + SC_HANDLE Handle; + UNICODE_STRING MachineNameW; + UNICODE_STRING DatabaseNameW; + ANSI_STRING MachineNameA; + ANSI_STRING DatabaseNameA; + + RtlInitAnsiString(&MachineNameA, (LPSTR)lpMachineName); + RtlAnsiStringToUnicodeString(&MachineNameW, + &MachineNameA, + TRUE); + RtlInitAnsiString(&DatabaseNameA, (LPSTR)lpDatabaseName); + RtlAnsiStringToUnicodeString(&DatabaseNameW, + &DatabaseNameA, + TRUE); + + Handle = OpenSCManagerW(MachineNameW.Buffer, + DatabaseNameW.Buffer, + dwDesiredAccess); + + RtlFreeHeap(GetProcessHeap(), + 0, + MachineNameW.Buffer); + RtlFreeHeap(GetProcessHeap(), + 0, + DatabaseNameW.Buffer); + + return(Handle); +} + + +/********************************************************************** + * OpenSCManagerW + */ +SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName, + LPCWSTR lpDatabaseName, + DWORD dwDesiredAccess) +{ + HANDLE hPipe; + DWORD dwMode; + DWORD dwWait; + BOOL fSuccess; + HANDLE hStartEvent; + LPWSTR lpszPipeName = L"\\\\.\\pipe\\Ntsvcs"; + + if(lpMachineName == NULL || wcslen(lpMachineName) == 0) + { + if(lpDatabaseName != NULL && wcscmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0) + { return(NULL); } + + // Only connect to scm when event "SvcctrlStartEvent_A3725DX" is signaled + hStartEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("SvcctrlStartEvent_A3725DX")); + if(hStartEvent == NULL) + { + SetLastError(ERROR_DATABASE_DOES_NOT_EXIST); + return (NULL); + } + dwWait = WaitForSingleObject(hStartEvent, INFINITE); + if(dwWait == WAIT_FAILED) + { + SetLastError(ERROR_ACCESS_DENIED); + return (NULL); + } + CloseHandle(hStartEvent); + + // Try to open a named pipe; wait for it, if necessary + while(1) + { + hPipe = CreateFileW(lpszPipeName, // pipe name + dwDesiredAccess, + 0, // no sharing + NULL, // no security attributes + OPEN_EXISTING, // opens existing pipe + 0, // default attributes + NULL); // no template file + + // Break if the pipe handle is valid + if(hPipe != INVALID_HANDLE_VALUE) + break; + + // Exit if an error other than ERROR_PIPE_BUSY occurs + if(GetLastError()!= ERROR_PIPE_BUSY) + { return(NULL); } + + // All pipe instances are busy, so wait for 20 seconds + if(!WaitNamedPipeW(lpszPipeName, 20000)) + { return(NULL); } + } + + // The pipe connected; change to message-read mode + dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time + if(!fSuccess) + { + CloseHandle(hPipe); + return(NULL); + } +#if 0 + // Send a message to the pipe server + lpvMessage = (argc > 1) ? argv[1] : "default message"; + + fSuccess = WriteFile( + hPipe, // pipe handle + lpvMessage, // message + strlen(lpvMessage) + 1, // message length + &cbWritten, // bytes written + NULL); // not overlapped + if(!fSuccess) + { + CloseHandle(hPipe); + return(NULL); + } + + do + { + // Read from the pipe + fSuccess = ReadFile( + hPipe, // pipe handle + chBuf, // buffer to receive reply + 512, // size of buffer + &cbRead, // number of bytes read + NULL); // not overlapped + + if(! fSuccess && GetLastError() != ERROR_MORE_DATA) + break; + + // Reply from the pipe is written to STDOUT. + if(!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf, cbRead, &cbWritten, NULL)) + break; + } while(!fSuccess); // repeat loop if ERROR_MORE_DATA + + //CloseHandle(hPipe); +#endif + return(hPipe); + } + else + { + /* FIXME: Connect to remote SCM */ + return(NULL); + } +} + + +/********************************************************************** + * OpenServiceA + */ +SC_HANDLE STDCALL +OpenServiceA(SC_HANDLE hSCManager, + LPCSTR lpServiceName, + DWORD dwDesiredAccess) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return(NULL); +} + + +/********************************************************************** + * OpenServiceW + */ +SC_HANDLE +STDCALL +OpenServiceW( + SC_HANDLE hSCManager, + LPCWSTR lpServiceName, + DWORD dwDesiredAccess + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * PrivilegedServiceAuditAlarmA + */ +BOOL +STDCALL +PrivilegedServiceAuditAlarmA( + LPCSTR SubsystemName, + LPCSTR ServiceName, + HANDLE ClientToken, + PPRIVILEGE_SET Privileges, + BOOL AccessGranted + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * PrivilegedServiceAuditAlarmW + */ +BOOL +STDCALL +PrivilegedServiceAuditAlarmW( + LPCWSTR SubsystemName, + LPCWSTR ServiceName, + HANDLE ClientToken, + PPRIVILEGE_SET Privileges, + BOOL AccessGranted + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 1; +} + + +/********************************************************************** + * QueryServiceConfigA + */ +BOOL +STDCALL +QueryServiceConfigA( + SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGA lpServiceConfig, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * QueryServiceConfigW + */ +BOOL +STDCALL +QueryServiceConfigW( + SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGW lpServiceConfig, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * QueryServiceLockStatusA + */ +BOOL +STDCALL +QueryServiceLockStatusA( + SC_HANDLE hSCManager, + LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * QueryServiceLockStatusW + */ +BOOL +STDCALL +QueryServiceLockStatusW( + SC_HANDLE hSCManager, + LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * QueryServiceObjectSecurity + */ +BOOL +STDCALL +QueryServiceObjectSecurity( + SC_HANDLE hService, + SECURITY_INFORMATION dwSecurityInformation, + PSECURITY_DESCRIPTOR lpSecurityDescriptor, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * QueryServiceStatus + */ +BOOL +STDCALL +QueryServiceStatus( + SC_HANDLE hService, + LPSERVICE_STATUS lpServiceStatus + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * QueryServiceStatusEx + */ +BOOL +STDCALL +QueryServiceStatusEx(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * StartServiceA + */ +BOOL +STDCALL +StartServiceA( + SC_HANDLE hService, + DWORD dwNumServiceArgs, + LPCSTR *lpServiceArgVectors + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + +/********************************************************************** + * StartServiceW + */ +BOOL +STDCALL +StartServiceW( + SC_HANDLE hService, + DWORD dwNumServiceArgs, + LPCWSTR *lpServiceArgVectors + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * UnlockServiceDatabase + */ +BOOL +STDCALL +UnlockServiceDatabase( + SC_LOCK ScLock + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* EOF */ diff --git a/lib/advapi32/service/sctrl.c b/lib/advapi32/service/sctrl.c new file mode 100644 index 0000000..b407f1a --- /dev/null +++ b/lib/advapi32/service/sctrl.c @@ -0,0 +1,426 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/service/sctrl.c + * PURPOSE: Service control manager functions + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 19990413 EA created + * 19990515 EA + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* TYPES *********************************************************************/ + +typedef struct +{ + DWORD ThreadId; + UNICODE_STRING ServiceName; + LPSERVICE_MAIN_FUNCTION MainFunction; + LPHANDLER_FUNCTION HandlerFunction; + SERVICE_STATUS ServiceStatus; +} ACTIVE_SERVICE, *PACTIVE_SERVICE; + +/* GLOBALS *******************************************************************/ + +static ULONG ActiveServiceCount; +static PACTIVE_SERVICE ActiveServices; +static PHANDLE ActiveServicesThreadHandles; + +/* FUNCTIONS *****************************************************************/ + + +static PACTIVE_SERVICE +ScLookupServiceByServiceName(LPWSTR lpServiceName) +{ + DWORD i; + + for (i = 0; i < ActiveServiceCount; i++) + { + if (_wcsicmp(ActiveServices[i].ServiceName.Buffer, lpServiceName) == 0) + { + return(&ActiveServices[i]); + } + } + + SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); + + return(NULL); +} + + +static PACTIVE_SERVICE +ScLookupServiceByThreadId(DWORD ThreadId) +{ + DWORD i; + + for (i = 0; i < ActiveServiceCount; i++) + { + if (ActiveServices[i].ThreadId == ThreadId) + { + return(&ActiveServices[i]); + } + } + + SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); + + return(NULL); +} + + +static DWORD +ScConnectControlPipe(HANDLE *hPipe) +{ + DWORD dwBytesWritten; + DWORD dwProcessId; + DWORD dwState; + + WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", + 15000); + + *hPipe = CreateFileW(L"\\\\.\\pipe\\net\\NtControlPipe", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (*hPipe == INVALID_HANDLE_VALUE) + return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT); + + dwState = PIPE_READMODE_MESSAGE; + if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL)) + { + CloseHandle(hPipe); + *hPipe = INVALID_HANDLE_VALUE; + return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT); + } + + dwProcessId = GetCurrentProcessId(); + WriteFile(*hPipe, + &dwProcessId, + sizeof(DWORD), + &dwBytesWritten, + NULL); + + return(ERROR_SUCCESS); +} + + +static VOID +ScServiceDispatcher(HANDLE hPipe, PVOID p1, PVOID p2) +{ + DPRINT1("ScDispatcherLoop() called\n"); + +#if 0 + while (TRUE) + { + /* Read command from the control pipe */ + + /* Execute command */ + + } +#endif +} + + +DWORD WINAPI +ScServiceMainStub(LPVOID Context) +{ + LPSERVICE_MAIN_FUNCTION lpServiceProc = (LPSERVICE_MAIN_FUNCTION)Context; + + /* FIXME: Send argc and argv (from command line) as arguments */ + + (lpServiceProc)(0, NULL); + + return ERROR_SUCCESS; +} + + +/********************************************************************** + * RegisterServiceCtrlHandlerA + */ +SERVICE_STATUS_HANDLE STDCALL +RegisterServiceCtrlHandlerA(LPCSTR lpServiceName, + LPHANDLER_FUNCTION lpHandlerProc) +{ + ANSI_STRING ServiceNameA; + UNICODE_STRING ServiceNameU; + SERVICE_STATUS_HANDLE SHandle; + + RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName); + if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE))) + { + SetLastError(ERROR_OUTOFMEMORY); + return((SERVICE_STATUS_HANDLE)0); + } + + SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer, + lpHandlerProc); + + RtlFreeUnicodeString(&ServiceNameU); + + return(SHandle); +} + + +/********************************************************************** + * RegisterServiceCtrlHandlerW + */ +SERVICE_STATUS_HANDLE STDCALL +RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, + LPHANDLER_FUNCTION lpHandlerProc) +{ + PACTIVE_SERVICE Service; + + Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName); + if (Service == NULL) + { + return((SERVICE_STATUS_HANDLE)NULL); + } + + Service->HandlerFunction = lpHandlerProc; + + return((SERVICE_STATUS_HANDLE)Service->ThreadId); +} + + +/********************************************************************** + * SetServiceBits + */ +BOOL STDCALL +SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus, + DWORD dwServiceBits, + BOOL bSetBitsOn, + BOOL bUpdateImmediately) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return(FALSE); +} + + +/********************************************************************** + * SetServiceObjectSecurity + */ +WINBOOL STDCALL +SetServiceObjectSecurity(SC_HANDLE hService, + SECURITY_INFORMATION dwSecurityInformation, + PSECURITY_DESCRIPTOR lpSecurityDescriptor) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * SetServiceStatus + */ +BOOL STDCALL +SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, + LPSERVICE_STATUS lpServiceStatus) +{ + PACTIVE_SERVICE Service; + + Service = ScLookupServiceByThreadId((DWORD)hServiceStatus); + if (!Service) + { + SetLastError(ERROR_INVALID_HANDLE); + return(FALSE); + } + + RtlCopyMemory(&Service->ServiceStatus, + lpServiceStatus, + sizeof(SERVICE_STATUS)); + + return(TRUE); +} + + +/********************************************************************** + * StartServiceCtrlDispatcherA + */ +BOOL STDCALL +StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable) +{ + LPSERVICE_TABLE_ENTRYW ServiceStartTableW; + ANSI_STRING ServiceNameA; + UNICODE_STRING ServiceNameW; + ULONG i, j; + ULONG Count; + BOOL b; + + i = 0; + while (lpServiceStartTable[i].lpServiceProc != NULL) + { + i++; + } + Count = i; + + ServiceStartTableW = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(SERVICE_TABLE_ENTRYW) * Count); + for (i = 0; i < Count; i++) + { + RtlInitAnsiString( + &ServiceNameA, + lpServiceStartTable[i].lpServiceName); + if (!NT_SUCCESS(RtlAnsiStringToUnicodeString( + &ServiceNameW, + &ServiceNameA, + TRUE))) + { + for (j = 0; j < i; j++) + { + RtlInitUnicodeString( + &ServiceNameW, + ServiceStartTableW[j].lpServiceName); + RtlFreeUnicodeString(&ServiceNameW); + } + RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW); + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + ServiceStartTableW[i].lpServiceName = ServiceNameW.Buffer; + ServiceStartTableW[i].lpServiceProc = + lpServiceStartTable[i].lpServiceProc; + } + + b = StartServiceCtrlDispatcherW(ServiceStartTableW); + + for (i = 0; i < Count; i++) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW[i].lpServiceName); + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW); + + return b; +} + + +/********************************************************************** + * StartServiceCtrlDispatcherW + */ +BOOL STDCALL +StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable) +{ + ULONG i; + HANDLE h; + DWORD Tid; + DWORD r; + HANDLE hPipe; + DWORD dwError; + + DPRINT1("StartServiceCtrlDispatcherW() called\n"); + + i = 0; + while (lpServiceStartTable[i].lpServiceProc != NULL) + { + i++; + } + + ActiveServiceCount = i; + ActiveServices = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + ActiveServiceCount * sizeof(ACTIVE_SERVICE)); + if (ActiveServices == NULL) + { + return(FALSE); + } + + /* Copy service names and start procedure */ + for (i = 0; i < ActiveServiceCount; i++) + { + RtlCreateUnicodeString(&ActiveServices[i].ServiceName, + lpServiceStartTable[i].lpServiceName); + ActiveServices[i].MainFunction = lpServiceStartTable[i].lpServiceProc; + } + + dwError = ScConnectControlPipe(&hPipe); + if (dwError = ERROR_SUCCESS) + { + /* FIXME: free the service table */ + return(FALSE); + } + + ScServiceDispatcher(hPipe, NULL, NULL); + CloseHandle(hPipe); + + /* FIXME: free the service table */ + + return(TRUE); + +#if 0 + ActiveServicesThreadHandles = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + (ActiveServiceCount + 1) * sizeof(HANDLE)); + if (!ActiveServicesThreadHandles) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices); + ActiveServices = NULL; + return(FALSE); + } + + for (i = 0; i 0) + { + r = WaitForMultipleObjects( + ActiveServiceCount + 1, + ActiveServicesThreadHandles, + FALSE, + INFINITE); + if (r == WAIT_OBJECT_0) + { + /* Received message from the scm */ + } + else if (r > WAIT_OBJECT_0 && r < (WAIT_OBJECT_0 + ActiveServiceCount)) + { + /* A service died */ + + ActiveServiceCount--; + ActiveServicesThreadHandles[r - WAIT_OBJECT_0 - 1] = + ActiveServicesThreadHandles[ActiveServiceCount + 1]; + RtlCopyMemory( + &ActiveServices[r - WAIT_OBJECT_0 - 2], + &ActiveServices[ActiveServiceCount], + sizeof(ACTIVE_SERVICE)); + } + else + { + /* Bail */ + } + } + return TRUE; +#endif +} + +/* EOF */ diff --git a/lib/advapi32/service/undoc.c b/lib/advapi32/service/undoc.c new file mode 100644 index 0000000..7894dd4 --- /dev/null +++ b/lib/advapi32/service/undoc.c @@ -0,0 +1,50 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/service/undoc.c + * PURPOSE: Undocumented service functions + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 19990413 EA created + * 19990515 EA + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * I_ScSetServiceBitsA + * + * Undocumented + * + * Return value unknown. + */ +DWORD +STDCALL +I_ScSetServiceBitsA(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 1; +} + + +/********************************************************************** + * I_ScSetServiceBitsW + * + * Undocumented + * + * Return value unknown. + */ +DWORD +STDCALL +I_ScSetServiceBitsW(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 1; +} + + diff --git a/lib/advapi32/token/privilege.c b/lib/advapi32/token/privilege.c new file mode 100644 index 0000000..5fad2a4 --- /dev/null +++ b/lib/advapi32/token/privilege.c @@ -0,0 +1,177 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/token/privilege.c + * PURPOSE: advapi32.dll token's privilege handling + * PROGRAMMER: E.Aliberti + * UPDATE HISTORY: + * 20010317 ea stubs + */ +#include +#include + + +/********************************************************************** + * LookupPrivilegeValueA EXPORTED + * LookupPrivilegeValueW EXPORTED + */ +BOOL STDCALL LookupPrivilegeValueA ( + LPCSTR lpSystemName, + LPCSTR lpName, + PLUID lpLuid + ) +{ + BOOL rv = FALSE; + DWORD le = ERROR_SUCCESS; + + ANSI_STRING SystemNameA; + UNICODE_STRING SystemNameW; + ANSI_STRING NameA; + UNICODE_STRING NameW; + + HANDLE ProcessHeap = GetProcessHeap (); + + + /* Remote system? */ + if (NULL != lpSystemName) + { + RtlInitAnsiString ( + & SystemNameA, + (LPSTR) lpSystemName + ); + RtlAnsiStringToUnicodeString ( + & SystemNameW, + & SystemNameA, + TRUE + ); + } + /* Check the privilege name is not NULL */ + if (NULL != lpName) + { + RtlInitAnsiString ( + & NameA, + (LPSTR) lpName + ); + RtlAnsiStringToUnicodeString ( + & NameW, + & NameA, + TRUE + ); + } + else + { + SetLastError (ERROR_INVALID_PARAMETER); + return (FALSE); + } + /* + * Forward the call to the UNICODE version + * of this API. + */ + if (FALSE == (rv = LookupPrivilegeValueW ( + (lpSystemName ? SystemNameW.Buffer : NULL), + NameW.Buffer, + lpLuid + ) + ) + ) + { + le = GetLastError (); + } + /* Remote system? */ + if (NULL != lpSystemName) + { + RtlFreeHeap ( + ProcessHeap, + 0, + SystemNameW.Buffer + ); + } + /* Name */ + RtlFreeHeap ( + ProcessHeap, + 0, + NameW.Buffer + ); + /* + * Set the last error, if any reported by + * the UNICODE call. + */ + if (ERROR_SUCCESS != le) + { + SetLastError (le); + } + return (rv); +} + + +BOOL STDCALL LookupPrivilegeValueW ( + LPCWSTR lpSystemName, + LPCWSTR lpName, + PLUID lpLuid + ) +{ + SetLastError (ERROR_CALL_NOT_IMPLEMENTED); + return (FALSE); +} + + +/********************************************************************** + * LookupPrivilegeDisplayNameA EXPORTED + * LookupPrivilegeDisplayNameW EXPORTED + */ +BOOL STDCALL LookupPrivilegeDisplayNameA ( + LPCSTR lpSystemName, + LPCSTR lpName, + LPSTR lpDisplayName, + LPDWORD cbDisplayName, + LPDWORD lpLanguageId + ) +{ + SetLastError (ERROR_CALL_NOT_IMPLEMENTED); + return (FALSE); +} + + +BOOL STDCALL LookupPrivilegeDisplayNameW ( + LPCWSTR lpSystemName, + LPCWSTR lpName, + LPWSTR lpDisplayName, + LPDWORD cbDisplayName, + LPDWORD lpLanguageId + ) +{ + SetLastError (ERROR_CALL_NOT_IMPLEMENTED); + return (FALSE); +} + + +/********************************************************************** + * LookupPrivilegeNameA EXPORTED + * LookupPrivilegeNameW EXPORTED + */ +BOOL STDCALL LookupPrivilegeNameA ( + LPCSTR lpSystemName, + PLUID lpLuid, + LPSTR lpName, + LPDWORD cbName + ) +{ + SetLastError (ERROR_CALL_NOT_IMPLEMENTED); + return (FALSE); +} + + +BOOL STDCALL LookupPrivilegeNameW ( + LPCWSTR lpSystemName, + PLUID lpLuid, + LPWSTR lpName, + LPDWORD cbName + ) +{ + SetLastError (ERROR_CALL_NOT_IMPLEMENTED); + return (FALSE); +} + + +/* EOF */ diff --git a/lib/advapi32/token/token.c b/lib/advapi32/token/token.c new file mode 100644 index 0000000..e276036 --- /dev/null +++ b/lib/advapi32/token/token.c @@ -0,0 +1,245 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/advapi32/token/token.c + * PURPOSE: Token functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include + +WINBOOL +STDCALL +AdjustTokenGroups ( + HANDLE TokenHandle, + WINBOOL ResetToDefault, + PTOKEN_GROUPS NewState, + DWORD BufferLength, + PTOKEN_GROUPS PreviousState, + PDWORD ReturnLength + ) +{ + NTSTATUS errCode; + errCode = NtAdjustGroupsToken(TokenHandle,ResetToDefault,NewState, + BufferLength, PreviousState, (PULONG)ReturnLength ); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + +WINBOOL +STDCALL +AdjustTokenPrivileges ( + HANDLE TokenHandle, + WINBOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, + DWORD BufferLength, + PTOKEN_PRIVILEGES PreviousState, + PDWORD ReturnLength + ) +{ NTSTATUS errCode; + errCode = NtAdjustPrivilegesToken(TokenHandle,DisableAllPrivileges,NewState, + BufferLength, PreviousState, (PULONG)ReturnLength ); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + +WINBOOL +STDCALL +GetTokenInformation ( + HANDLE TokenHandle, + TOKEN_INFORMATION_CLASS TokenInformationClass, + LPVOID TokenInformation, + DWORD TokenInformationLength, + PDWORD ReturnLength + ) +{ + NTSTATUS errCode; + errCode = NtQueryInformationToken(TokenHandle,TokenInformationClass,TokenInformation, + TokenInformationLength, (PULONG)ReturnLength); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + +WINBOOL +STDCALL +SetTokenInformation ( + HANDLE TokenHandle, + TOKEN_INFORMATION_CLASS TokenInformationClass, + LPVOID TokenInformation, + DWORD TokenInformationLength + ) +{ + NTSTATUS errCode; + errCode = NtSetInformationToken(TokenHandle,TokenInformationClass,TokenInformation, + TokenInformationLength); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + +WINBOOL +STDCALL +AccessCheck ( + PSECURITY_DESCRIPTOR pSecurityDescriptor, + HANDLE ClientToken, + DWORD DesiredAccess, + PGENERIC_MAPPING GenericMapping, + PPRIVILEGE_SET PrivilegeSet, + LPDWORD PrivilegeSetLength, + LPDWORD GrantedAccess, + LPBOOL AccessStatus + ) +{ + NTSTATUS errCode; + errCode = NtAccessCheck( pSecurityDescriptor, + ClientToken, + DesiredAccess, + GenericMapping, + PrivilegeSet, + (PULONG)PrivilegeSetLength, + (PULONG)GrantedAccess, + (PBOOLEAN)AccessStatus); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + + +WINBOOL +STDCALL +OpenProcessToken ( + HANDLE ProcessHandle, + DWORD DesiredAccess, + PHANDLE TokenHandle + ) +{ + NTSTATUS errCode; + errCode = NtOpenProcessToken(ProcessHandle,DesiredAccess,TokenHandle); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + + +WINBOOL +STDCALL +OpenThreadToken ( + HANDLE ThreadHandle, + DWORD DesiredAccess, + WINBOOL OpenAsSelf, + PHANDLE TokenHandle + ) +{ + NTSTATUS errCode; + errCode = NtOpenThreadToken(ThreadHandle,DesiredAccess,OpenAsSelf,TokenHandle); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + +WINBOOL +STDCALL +SetThreadToken ( + PHANDLE ThreadHandle, + HANDLE TokenHandle + ) +{ + NTSTATUS errCode; + HANDLE hThread = NtCurrentThread(); + if ( ThreadHandle != NULL ) + hThread = ThreadHandle; + errCode = NtSetInformationThread(hThread,ThreadImpersonationToken,TokenHandle,sizeof(HANDLE)); + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + +WINBOOL +STDCALL +DuplicateTokenEx ( + HANDLE ExistingTokenHandle, + DWORD dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpTokenAttributes, + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + TOKEN_TYPE TokenType, + PHANDLE DuplicateTokenHandle + ) +{ + NTSTATUS errCode; + HANDLE NewToken; + + OBJECT_ATTRIBUTES ObjectAttributes; + + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + if ( lpTokenAttributes->bInheritHandle ) + ObjectAttributes.Attributes |= OBJ_INHERIT; + + ObjectAttributes.SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor; + ObjectAttributes.SecurityQualityOfService = NULL; + + errCode = NtDuplicateToken( ExistingTokenHandle, dwDesiredAccess, + &ObjectAttributes, ImpersonationLevel, + TokenType, &NewToken ); + + if ( !NT_SUCCESS(errCode) ) { + SetLastError(RtlNtStatusToDosError(errCode)); + return FALSE; + } + return TRUE; +} + + +WINBOOL +STDCALL +DuplicateToken ( + HANDLE ExistingTokenHandle, + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + PHANDLE DuplicateTokenHandle + ) +{ + return DuplicateTokenEx ( + ExistingTokenHandle, + TOKEN_DUPLICATE|TOKEN_IMPERSONATE|TOKEN_QUERY, + NULL, + ImpersonationLevel, + TokenImpersonation, + DuplicateTokenHandle + ); +} + + + + + +/* EOF */ diff --git a/lib/crtdll/.cvsignore b/lib/crtdll/.cvsignore new file mode 100644 index 0000000..a26303a --- /dev/null +++ b/lib/crtdll/.cvsignore @@ -0,0 +1,6 @@ +crtdll.coff +crtdll.dll +crtdll.nostrip.dll +*.d +*.o +*.sym diff --git a/lib/crtdll/assert/.cvsignore b/lib/crtdll/assert/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/assert/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/assert/assert.c b/lib/crtdll/assert/assert.c new file mode 100644 index 0000000..2191a42 --- /dev/null +++ b/lib/crtdll/assert/assert.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +void _assert(const char *msg, const char *file, int line) +{ + /* Assertion failed at foo.c line 45: x +#include + +char * +_cgets(char *string) +{ + unsigned len = 0; + unsigned int maxlen_wanted; + char *sp; + int c; + /* + * Be smart and check for NULL pointer. + * Don't know wether TURBOC does this. + */ + if (!string) + return(NULL); + maxlen_wanted = (unsigned int)((unsigned char)string[0]); + sp = &(string[2]); + /* + * Should the string be shorter maxlen_wanted including or excluding + * the trailing '\0' ? We don't take any risk. + */ + while(len < maxlen_wanted-1) + { + c=_getch(); + /* + * shold we check for backspace here? + * TURBOC does (just checked) but doesn't in cscanf (thats harder + * or even impossible). We do the same. + */ + if (c == '\b') + { + if (len > 0) + { + _cputs("\b \b"); /* go back, clear char on screen with space + and go back again */ + len--; + sp[len] = '\0'; /* clear the character in the string */ + } + } + else if (c == '\r') + { + sp[len] = '\0'; + break; + } + else if (c == 0) + { + /* special character ends input */ + sp[len] = '\0'; + _ungetch(c); /* keep the char for later processing */ + break; + } + else + { + sp[len] = _putch(c); + len++; + } + } + sp[maxlen_wanted-1] = '\0'; + string[1] = (char)((unsigned char)len); + return(sp); +} + + diff --git a/lib/crtdll/conio/cprintf.c b/lib/crtdll/conio/cprintf.c new file mode 100644 index 0000000..21c33a9 --- /dev/null +++ b/lib/crtdll/conio/cprintf.c @@ -0,0 +1,17 @@ +#include +#include + +int +_cprintf(const char *fmt, ...) +{ + int cnt; + char buf[ 2048 ]; /* this is buggy, because buffer might be too small. */ + va_list ap; + + va_start(ap, fmt); + cnt = vsprintf(buf, fmt, ap); + va_end(ap); + + _cputs(buf); + return cnt; +} diff --git a/lib/crtdll/conio/cputs.c b/lib/crtdll/conio/cputs.c new file mode 100644 index 0000000..37cd12a --- /dev/null +++ b/lib/crtdll/conio/cputs.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/cputs.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include +#include + +int _cputs(const char *_str) +{ + int len = strlen(_str); + DWORD written = 0; + if (!WriteFile(filehnd(stdout->_file),_str,len,&written,NULL)) + return -1; + return 0; +} diff --git a/lib/crtdll/conio/cscanf.c b/lib/crtdll/conio/cscanf.c new file mode 100644 index 0000000..42a8779 --- /dev/null +++ b/lib/crtdll/conio/cscanf.c @@ -0,0 +1,19 @@ +#include +#include +#include + +int +_cscanf(char *fmt, ...) +{ + int cnt; + + va_list ap; + + //fixme cscanf should scan the console's keyboard + va_start(ap, fmt); + cnt = __vscanf(fmt, ap); + va_end(ap); + return cnt; +} + + diff --git a/lib/crtdll/conio/getch.c b/lib/crtdll/conio/getch.c new file mode 100644 index 0000000..6830ac5 --- /dev/null +++ b/lib/crtdll/conio/getch.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include + +extern int char_avail; +extern int ungot_char; + + +int +_getch(void) +{ + + DWORD NumberOfCharsRead = 0; + char c; + if (char_avail) + { + c = ungot_char; + char_avail = 0; + } + else + { + ReadConsoleA(_get_osfhandle(stdin->_file), &c,1,&NumberOfCharsRead ,NULL); + + } + if ( c == 10 ) + c = 13; + putchar(c); + return c; +} diff --git a/lib/crtdll/conio/getche.c b/lib/crtdll/conio/getche.c new file mode 100644 index 0000000..247634b --- /dev/null +++ b/lib/crtdll/conio/getche.c @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getche.c + * PURPOSE: Reads a character from stdin + * PROGRAMER: DJ Delorie + Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include + + +extern int char_avail; +int +getche(void) +{ + if (char_avail) + /* + * We don't know, wether the ungot char was already echoed + * we assume yes (for example in cscanf, probably the only + * place where ungetch is ever called. + * There is no way to check for this really, because + * ungetch could have been called with a character that + * hasn't been got by a conio function. + * We don't echo again. + */ + return(getch()); + return (_putch(getch())); +} diff --git a/lib/crtdll/conio/kbhit.c b/lib/crtdll/conio/kbhit.c new file mode 100644 index 0000000..1232d72 --- /dev/null +++ b/lib/crtdll/conio/kbhit.c @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + + +// FIXME PeekCosoleInput returns more than keyboard hits +extern int char_avail; + +int +_kbhit(void) +{ + INPUT_RECORD InputRecord; + DWORD NumberRead=0; + if (char_avail) + return(1); + else { + //FIXME PeekConsoleInput might do DeviceIo + //PeekConsoleInput((HANDLE)stdin->_file,&InputRecord,1,&NumberRead); + return NumberRead; + } + return 0; +} diff --git a/lib/crtdll/conio/putch.c b/lib/crtdll/conio/putch.c new file mode 100644 index 0000000..b207680 --- /dev/null +++ b/lib/crtdll/conio/putch.c @@ -0,0 +1,21 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/putch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +int _putch( int c ) +{ + DWORD NumberOfCharsWritten; + if ( WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),&c,1,&NumberOfCharsWritten,NULL) ) { + return -1; + } + + return NumberOfCharsWritten; +} diff --git a/lib/crtdll/conio/ungetch.c b/lib/crtdll/conio/ungetch.c new file mode 100644 index 0000000..730ac39 --- /dev/null +++ b/lib/crtdll/conio/ungetch.c @@ -0,0 +1,28 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/ungetch.c + * PURPOSE: Ungets a character from stdin + * PROGRAMER: DJ Delorie + Boudewijn Dekker [ Adapted from djgpp libc ] + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#define EOF -1 + +int char_avail = 0; +char ungot_char = 0; + + +int +_ungetch(int c) +{ + if (char_avail) + return(EOF); + ungot_char = c; + char_avail = 1; + return(c); +} diff --git a/lib/crtdll/crtdll.def b/lib/crtdll/crtdll.def new file mode 100644 index 0000000..76b2fd3 --- /dev/null +++ b/lib/crtdll/crtdll.def @@ -0,0 +1,567 @@ +; +; crtdll.def +; +; Exports from crtdll.dll from Windows 95 SYSTEM directory. Hopefully this +; should also work with the crtdll provided with Windows NT. +; Exports from crtdll.dll from Windows NT Server 4.0. +; +; Contributors: +; Created by Colin Peters +; Modified by Adhi P. Yoedo +; +; THIS SOFTWARE IS NOT COPYRIGHTED +; +; This source code is offered for use in the public domain. You may +; use, modify or distribute it freely. +; +; This code is distributed in the hope that it will be useful but +; WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY +; DISCLAMED. This includes but is not limited to warrenties of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +; +; $Revision$ +; $Author$ +; $Date$ +; +; These three functions appear to be name mangled in some way, so GCC is +; probably not going to be able to use them in any case. +; +; ??2@YAPAXI@Z +; ??3@YAXPAX@Z +; ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z +; +; Added functional equivalent placeholders: +; +; __builtin_new +; __builtin_delete +; _set_new_handler__FPFUi_i +; +; +LIBRARY CRTDLL.DLL +EXPORTS +__builtin_new +__builtin_delete +_set_new_handler__FPFUi_i +_CIacos +_CIasin +_CIatan +_CIatan2 +_CIcos +_CIcosh +_CIexp +_CIfmod +_CIlog +_CIlog10 +_CIpow +_CIsin +_CIsinh +_CIsqrt +_CItan +_CItanh +_HUGE_dll +_XcptFilter +__GetMainArgs +__argc_dll +__argv_dll +__dllonexit +__doserrno +__fpecode +__isascii +__iscsym +__iscsymf +__mb_cur_max_dll +__pxcptinfoptrs +__threadhandle +__threadid +__toascii +_abnormal_termination +_access +_acmdln_dll +_aexit_rtn_dll +_amsg_exit +_assert +_basemajor_dll +_baseminor_dll +_baseversion_dll +_beep +_beginthread +_c_exit +_cabs +_cexit +_cgets +_chdir +_chdrive +_chgsign +_chmod +_chsize +_clearfp +_close +_commit +_commode_dll +_control87 +_controlfp +_copysign +_cprintf +_cpumode_dll +_cputs +_creat +_cscanf +_ctype +_cwait +_daylight_dll +_dup +_dup2 +_ecvt +_endthread +_environ_dll +_eof +_errno +_except_handler2 +_execl +_execle +_execlp +_execlpe +_execv +_execve +_execvp +_execvpe +_exit +_expand +_fcloseall +_fcvt +_fdopen +_fgetchar +_fgetwchar +_filbuf +_fileinfo_dll +_filelength +_fileno +_findclose +_findfirst +_findnext +_finite +_flsbuf +_flushall +_fmode_dll +_fpclass +_fpieee_flt +_fpreset +_fputchar +_fputwchar +_fsopen +_fstat +_ftime +_ftol +_fullpath +_futime +_gcvt +_get_osfhandle +_getch +_getche +_getcwd +_getdcwd +_getdiskfree +_getdllprocaddr +_getdrive +_getdrives +_getpid +_getsystime +_getw +_global_unwind2 +_heapchk +_heapmin +_heapset +_heapwalk +_hypot +_initterm +_iob +_isatty +_isctype +_ismbbalnum +_ismbbalpha +_ismbbgraph +_ismbbkalnum +_ismbbkana +_ismbbkpunct +_ismbblead +_ismbbprint +_ismbbpunct +_ismbbtrail +_ismbcalpha +_ismbcdigit +_ismbchira +_ismbckata +_ismbcl0 +_ismbcl1 +_ismbcl2 +_ismbclegal +_ismbclower +_ismbcprint +_ismbcspace +_ismbcsymbol +_ismbcupper +_ismbslead +_ismbstrail +_isnan +_itoa +_itow +_j0 +_j1 +_jn +_kbhit +_lfind +_loaddll +_local_unwind2 +_locking +_logb +_lrotl +_lrotr +_lsearch +_lseek +_ltoa +_ltow +_makepath +_matherr +_mbbtombc +_mbbtype +_mbccpy +_mbcjistojms +_mbcjmstojis +_mbclen +_mbctohira +_mbctokata +_mbctolower +_mbctombb +_mbctoupper +_mbctype +_mbsbtype +_mbscat +_mbschr +_mbscmp +_mbscpy +_mbscspn +_mbsdec +_mbsdup +_mbsicmp +_mbsinc +_mbslen +_mbslwr +_mbsnbcat +_mbsnbcmp +_mbsnbcnt +_mbsnbcpy +_mbsnbicmp +_mbsnbset +_mbsncat +_mbsnccnt +_mbsncmp +_mbsncpy +_mbsnextc +_mbsnicmp +_mbsninc +_mbsnset +_mbspbrk +_mbsrchr +_mbsrev +_mbsset +_mbsspn +_mbsspnp +_mbsstr +_mbstok +_mbstrlen +_mbsupr +_memccpy +_memicmp +_mkdir +_mktemp +_msize +_nextafter +_onexit +_open +_open_osfhandle +_osmajor_dll +_osminor_dll +_osmode_dll +_osver_dll +_osversion_dll +_pclose +_pctype_dll +_pgmptr_dll +_pipe +_popen +_purecall +_putch +_putenv +_putw +_pwctype_dll +_read +_rmdir +_rmtmp +_rotl +_rotr +_scalb +_searchenv +_seterrormode +_setjmp +_setmode +_setsystime +_sleep +_snprintf +_snwprintf +_sopen +_spawnl +_spawnle +_spawnlp +_spawnlpe +_spawnv +_spawnve +_spawnvp +_spawnvpe +_splitpath +_stat +_statusfp +_strcmpi +_strdate +_strdec +_strdup +_strerror +_stricmp +_stricoll +_strinc +_strlwr +_strncnt +_strnextc +_strnicmp +_strninc +_strnset +_strrev +_strset +_strspnp +_strtime +_strupr +_swab +_sys_errlist +_sys_nerr_dll +_tell +_tempnam +_timezone_dll +_tolower +_toupper +_tzname +_tzset +_ultoa +_ultow +_umask +_ungetch +_unlink +_unloaddll +_utime +_vsnprintf +_vsnwprintf +_wcsdup +_wcsicmp +_wcsicoll +_wcslwr +_wcsnicmp +_wcsnset +_wcsrev +_wcsset +_wcsupr +_winmajor_dll +_winminor_dll +_winver_dll +_write +_wtoi +_wtol +_y0 +_y1 +_yn +abort +abs +acos +asctime +asin +atan +atan2 +atexit +atof +atoi +atol +bsearch +calloc +ceil +clearerr +clock +cos +cosh +ctime +difftime +div +exit +exp +fabs +fclose +feof +ferror +fflush +fgetc +fgetpos +fgets +fgetwc +floor +fmod +fopen +fprintf +fputc +fputs +fputwc +fread +free +freopen +frexp +fscanf +fseek +fsetpos +ftell +fwprintf +fwrite +fwscanf +getc +getchar +getenv +gets +gmtime +is_wctype +isalnum +isalpha +iscntrl +isdigit +isgraph +isleadbyte +islower +isprint +ispunct +isspace +isupper +iswalnum +iswalpha +iswascii +iswcntrl +iswctype +iswdigit +iswgraph +iswlower +iswprint +iswpunct +iswspace +iswupper +iswxdigit +isxdigit +labs +ldexp +ldiv +localeconv +localtime +log +log10 +longjmp +malloc +mblen +mbstowcs +mbtowc +memchr +memcmp +memcpy +memmove +memset +mktime +modf +perror +pow +printf +putc +putchar +puts +qsort +raise +rand +realloc +remove +rename +rewind +scanf +setbuf +setlocale +setvbuf +signal +sin +sinh +sprintf +sqrt +srand +sscanf +strcat +strchr +strcmp +strcoll +strcpy +strcspn +strerror +strftime +strlen +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtod +strtok +strtol +strtoul +strxfrm +swprintf +swscanf +system +tan +tanh +time +tmpfile +tmpnam +tolower +toupper +towlower +towupper +ungetc +ungetwc +vfprintf +vfwprintf +vprintf +vsprintf +vswprintf +vwprintf +wcscat +wcschr +wcscmp +wcscoll +wcscpy +wcscspn +wcsftime +wcslen +wcsncat +wcsncmp +wcsncpy +wcspbrk +wcsrchr +wcsspn +wcsstr +wcstod +wcstok +wcstol +wcstombs +wcstoul +wcsxfrm +wctomb +wprintf +wscanf diff --git a/lib/crtdll/crtdll.rc b/lib/crtdll/crtdll.rc new file mode 100644 index 0000000..c37f0a4 --- /dev/null +++ b/lib/crtdll/crtdll.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "C Runtime Library\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "crtdll\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "crtdll.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/lib/crtdll/ctype/.cvsignore b/lib/crtdll/ctype/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/ctype/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/ctype/isalnum.c b/lib/crtdll/ctype/isalnum.c new file mode 100644 index 0000000..66a591b --- /dev/null +++ b/lib/crtdll/ctype/isalnum.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/ctype/isalnum.c + * PURPOSE: Test for a alpha numeric character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + + +#undef isalnum +int isalnum(int c) +{ + return _isctype(c,_ALPHA | _DIGIT); +} + +#undef iswalnum +int iswalnum(wint_t c) +{ + return iswctype(c,_ALPHA | _DIGIT); +} diff --git a/lib/crtdll/ctype/isalpha.c b/lib/crtdll/ctype/isalpha.c new file mode 100644 index 0000000..3e0c496 --- /dev/null +++ b/lib/crtdll/ctype/isalpha.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/putch.c + * PURPOSE: Checks if a character is alphanumeric + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + +#undef isalpha +int isalpha(int c) +{ + return _isctype(c,_ALPHA); +} + +#undef iswalpha +int iswalpha(wint_t c) +{ + return iswctype(c,_ALPHA); +} diff --git a/lib/crtdll/ctype/isascii.c b/lib/crtdll/ctype/isascii.c new file mode 100644 index 0000000..4ef4daf --- /dev/null +++ b/lib/crtdll/ctype/isascii.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + +int __isascii(int c) +{ + return (!((c)&(~0x7f))) ; +} + +int iswascii(wint_t c) +{ + return __isascii(c); +} + + + + + + + + diff --git a/lib/crtdll/ctype/iscntrl.c b/lib/crtdll/ctype/iscntrl.c new file mode 100644 index 0000000..4eef7f8 --- /dev/null +++ b/lib/crtdll/ctype/iscntrl.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef iscntrl +int iscntrl(int c) +{ + return _isctype(c,_CONTROL); +} + +#undef iswcntrl +int iswcntrl(wint_t c) +{ + return iswctype(c,_CONTROL); +} diff --git a/lib/crtdll/ctype/iscsym.c b/lib/crtdll/ctype/iscsym.c new file mode 100644 index 0000000..4f1c1d6 --- /dev/null +++ b/lib/crtdll/ctype/iscsym.c @@ -0,0 +1,21 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/ctype/iscsym.c + * PURPOSE: Check for a valid characters in a c symbol + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + +int __iscsymf(int c) +{ + return (isalpha(c) || ( c == '_' )) ; +} + +int __iscsym(int c) +{ + return (isalnum(c) || ( c == '_' )) ; +} diff --git a/lib/crtdll/ctype/isctype.c b/lib/crtdll/ctype/isctype.c new file mode 100644 index 0000000..19db72a --- /dev/null +++ b/lib/crtdll/ctype/isctype.c @@ -0,0 +1,283 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +unsigned short _ctype[] = { + 0, /* , 0xFFFF */ + _CONTROL, /* CTRL+@, 0x00 */ + _CONTROL, /* CTRL+A, 0x01 */ + _CONTROL, /* CTRL+B, 0x02 */ + _CONTROL, /* CTRL+C, 0x03 */ + _CONTROL, /* CTRL+D, 0x04 */ + _CONTROL, /* CTRL+E, 0x05 */ + _CONTROL, /* CTRL+F, 0x06 */ + _CONTROL, /* CTRL+G, 0x07 */ + _CONTROL, /* CTRL+H, 0x08 */ + _CONTROL | _SPACE, /* CTRL+I, 0x09 */ + _CONTROL | _SPACE, /* CTRL+J, 0x0a */ + _CONTROL | _SPACE, /* CTRL+K, 0x0b */ + _CONTROL | _SPACE, /* CTRL+L, 0x0c */ + _CONTROL | _SPACE, /* CTRL+M, 0x0d */ + _CONTROL, /* CTRL+N, 0x0e */ + _CONTROL, /* CTRL+O, 0x0f */ + _CONTROL, /* CTRL+P, 0x10 */ + _CONTROL, /* CTRL+Q, 0x11 */ + _CONTROL, /* CTRL+R, 0x12 */ + _CONTROL, /* CTRL+S, 0x13 */ + _CONTROL, /* CTRL+T, 0x14 */ + _CONTROL, /* CTRL+U, 0x15 */ + _CONTROL, /* CTRL+V, 0x16 */ + _CONTROL, /* CTRL+W, 0x17 */ + _CONTROL, /* CTRL+X, 0x18 */ + _CONTROL, /* CTRL+Y, 0x19 */ + _CONTROL, /* CTRL+Z, 0x1a */ + _CONTROL, /* CTRL+[, 0x1b */ + _CONTROL, /* CTRL+\, 0x1c */ + _CONTROL, /* CTRL+], 0x1d */ + _CONTROL, /* CTRL+^, 0x1e */ + _CONTROL, /* CTRL+_, 0x1f */ + _SPACE | _BLANK, /* ` ', 0x20 */ + _PUNCT, /* `!', 0x21 */ + _PUNCT, /* 0x22 */ + _PUNCT, /* `#', 0x23 */ + _PUNCT, /* `$', 0x24 */ + _PUNCT, /* `%', 0x25 */ + _PUNCT, /* `&', 0x26 */ + _PUNCT, /* 0x27 */ + _PUNCT, /* `(', 0x28 */ + _PUNCT, /* `)', 0x29 */ + _PUNCT, /* `*', 0x2a */ + _PUNCT, /* `+', 0x2b */ + _PUNCT, /* `,', 0x2c */ + _PUNCT, /* `-', 0x2d */ + _PUNCT, /* `.', 0x2e */ + _PUNCT, /* `/', 0x2f */ + _DIGIT | _HEX, /* `0', 0x30 */ + _DIGIT | _HEX, /* `1', 0x31 */ + _DIGIT | _HEX, /* `2', 0x32 */ + _DIGIT | _HEX, /* `3', 0x33 */ + _DIGIT | _HEX, /* `4', 0x34 */ + _DIGIT | _HEX, /* `5', 0x35 */ + _DIGIT | _HEX, /* `6', 0x36 */ + _DIGIT | _HEX, /* `7', 0x37 */ + _DIGIT | _HEX, /* `8', 0x38 */ + _DIGIT | _HEX, /* `9', 0x39 */ + _PUNCT, /* `:', 0x3a */ + _PUNCT, /* `;', 0x3b */ + _PUNCT, /* `<', 0x3c */ + _PUNCT, /* `=', 0x3d */ + _PUNCT, /* `>', 0x3e */ + _PUNCT, /* `?', 0x3f */ + _PUNCT, /* `@', 0x40 */ + _UPPER | _HEX, /* `A', 0x41 */ + _UPPER | _HEX, /* `B', 0x42 */ + _UPPER | _HEX, /* `C', 0x43 */ + _UPPER | _HEX, /* `D', 0x44 */ + _UPPER | _HEX, /* `E', 0x45 */ + _UPPER | _HEX, /* `F', 0x46 */ + _UPPER, /* `G', 0x47 */ + _UPPER, /* `H', 0x48 */ + _UPPER, /* `I', 0x49 */ + _UPPER, /* `J', 0x4a */ + _UPPER, /* `K', 0x4b */ + _UPPER, /* `L', 0x4c */ + _UPPER, /* `M', 0x4d */ + _UPPER, /* `N', 0x4e */ + _UPPER, /* `O', 0x4f */ + _UPPER, /* `P', 0x50 */ + _UPPER, /* `Q', 0x51 */ + _UPPER, /* `R', 0x52 */ + _UPPER, /* `S', 0x53 */ + _UPPER, /* `T', 0x54 */ + _UPPER, /* `U', 0x55 */ + _UPPER, /* `V', 0x56 */ + _UPPER, /* `W', 0x57 */ + _UPPER, /* `X', 0x58 */ + _UPPER, /* `Y', 0x59 */ + _UPPER, /* `Z', 0x5a */ + _PUNCT, /* `[', 0x5b */ + _PUNCT, /* 0x5c */ + _PUNCT, /* `]', 0x5d */ + _PUNCT, /* `^', 0x5e */ + _PUNCT, /* `_', 0x5f */ + _PUNCT, /* 0x60 */ + _LOWER | _HEX, /* `a', 0x61 */ + _LOWER | _HEX, /* `b', 0x62 */ + _LOWER | _HEX, /* `c', 0x63 */ + _LOWER | _HEX, /* `d', 0x64 */ + _LOWER | _HEX, /* `e', 0x65 */ + _LOWER | _HEX, /* `f', 0x66 */ + _LOWER, /* `g', 0x67 */ + _LOWER, /* `h', 0x68 */ + _LOWER, /* `i', 0x69 */ + _LOWER, /* `j', 0x6a */ + _LOWER, /* `k', 0x6b */ + _LOWER, /* `l', 0x6c */ + _LOWER, /* `m', 0x6d */ + _LOWER, /* `n', 0x6e */ + _LOWER, /* `o', 0x6f */ + _LOWER, /* `p', 0x70 */ + _LOWER, /* `q', 0x71 */ + _LOWER, /* `r', 0x72 */ + _LOWER, /* `s', 0x73 */ + _LOWER, /* `t', 0x74 */ + _LOWER, /* `u', 0x75 */ + _LOWER, /* `v', 0x76 */ + _LOWER, /* `w', 0x77 */ + _LOWER, /* `x', 0x78 */ + _LOWER, /* `y', 0x79 */ + _LOWER, /* `z', 0x7a */ + _PUNCT, /* `{', 0x7b */ + _PUNCT, /* `|', 0x7c */ + _PUNCT, /* `}', 0x7d */ + _PUNCT, /* `~', 0x7e */ + _CONTROL, /* 0x7f */ + 0, /* 0x80 */ + 0, /* 0x81 */ + 0, /* 0x82 */ + 0, /* 0x83 */ + 0, /* 0x84 */ + 0, /* 0x85 */ + 0, /* 0x86 */ + 0, /* 0x87 */ + 0, /* 0x88 */ + 0, /* 0x89 */ + 0, /* 0x8a */ + 0, /* 0x8b */ + 0, /* 0x8c */ + 0, /* 0x8d */ + 0, /* 0x8e */ + 0, /* 0x8f */ + 0, /* 0x90 */ + 0, /* 0x91 */ + 0, /* 0x92 */ + 0, /* 0x93 */ + 0, /* 0x94 */ + 0, /* 0x95 */ + 0, /* 0x96 */ + 0, /* 0x97 */ + 0, /* 0x98 */ + 0, /* 0x99 */ + 0, /* 0x9a */ + 0, /* 0x9b */ + 0, /* 0x9c */ + 0, /* 0x9d */ + 0, /* 0x9e */ + 0, /* 0x9f */ + 0, /* 0xa0 */ + 0, /* 0xa1 */ + 0, /* 0xa2 */ + 0, /* 0xa3 */ + 0, /* 0xa4 */ + 0, /* 0xa5 */ + 0, /* 0xa6 */ + 0, /* 0xa7 */ + 0, /* 0xa8 */ + 0, /* 0xa9 */ + 0, /* 0xaa */ + 0, /* 0xab */ + 0, /* 0xac */ + 0, /* 0xad */ + 0, /* 0xae */ + 0, /* 0xaf */ + 0, /* 0xb0 */ + 0, /* 0xb1 */ + 0, /* 0xb2 */ + 0, /* 0xb3 */ + 0, /* 0xb4 */ + 0, /* 0xb5 */ + 0, /* 0xb6 */ + 0, /* 0xb7 */ + 0, /* 0xb8 */ + 0, /* 0xb9 */ + 0, /* 0xba */ + 0, /* 0xbb */ + 0, /* 0xbc */ + 0, /* 0xbd */ + 0, /* 0xbe */ + 0, /* 0xbf */ + 0, /* 0xc0 */ + 0, /* 0xc1 */ + 0, /* 0xc2 */ + 0, /* 0xc3 */ + 0, /* 0xc4 */ + 0, /* 0xc5 */ + 0, /* 0xc6 */ + 0, /* 0xc7 */ + 0, /* 0xc8 */ + 0, /* 0xc9 */ + 0, /* 0xca */ + 0, /* 0xcb */ + 0, /* 0xcc */ + 0, /* 0xcd */ + 0, /* 0xce */ + 0, /* 0xcf */ + 0, /* 0xd0 */ + 0, /* 0xd1 */ + 0, /* 0xd2 */ + 0, /* 0xd3 */ + 0, /* 0xd4 */ + 0, /* 0xd5 */ + 0, /* 0xd6 */ + 0, /* 0xd7 */ + 0, /* 0xd8 */ + 0, /* 0xd9 */ + 0, /* 0xda */ + 0, /* 0xdb */ + 0, /* 0xdc */ + 0, /* 0xdd */ + 0, /* 0xde */ + 0, /* 0xdf */ + 0, /* 0xe0 */ + 0, /* 0xe1 */ + 0, /* 0xe2 */ + 0, /* 0xe3 */ + 0, /* 0xe4 */ + 0, /* 0xe5 */ + 0, /* 0xe6 */ + 0, /* 0xe7 */ + 0, /* 0xe8 */ + 0, /* 0xe9 */ + 0, /* 0xea */ + 0, /* 0xeb */ + 0, /* 0xec */ + 0, /* 0xed */ + 0, /* 0xee */ + 0, /* 0xef */ + 0, /* 0xf0 */ + 0, /* 0xf1 */ + 0, /* 0xf2 */ + 0, /* 0xf3 */ + 0, /* 0xf4 */ + 0, /* 0xf5 */ + 0, /* 0xf6 */ + 0, /* 0xf7 */ + 0, /* 0xf8 */ + 0, /* 0xf9 */ + 0, /* 0xfa */ + 0, /* 0xfb */ + 0, /* 0xfc */ + 0, /* 0xfd */ + 0, /* 0xfe */ + 0 /* 0xff */ +}; + +unsigned short *_pctype_dll = _ctype + 1; +unsigned short *_pwctype_dll = _ctype + 1; + +int _isctype (unsigned int c, int ctypeFlags) +{ + return (_pctype_dll[(unsigned char)(c & 0xFF)] & ctypeFlags); +} + +int iswctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype_dll[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +// obsolete +int is_wctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype_dll[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +/* EOF */ diff --git a/lib/crtdll/ctype/isdigit.c b/lib/crtdll/ctype/isdigit.c new file mode 100644 index 0000000..93afd37 --- /dev/null +++ b/lib/crtdll/ctype/isdigit.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isdigit +int isdigit(int c) +{ + return _isctype(c,_DIGIT); +} + +#undef iswdigit +int iswdigit(wint_t c) +{ + return iswctype(c,_DIGIT); +} diff --git a/lib/crtdll/ctype/isgraph.c b/lib/crtdll/ctype/isgraph.c new file mode 100644 index 0000000..ead804c --- /dev/null +++ b/lib/crtdll/ctype/isgraph.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isgraph +int isgraph(int c) +{ + return _isctype(c,_PUNCT | _ALPHA | _DIGIT); +} + +#undef iswgraph +int iswgraph(wint_t c) +{ + return iswctype(c,_PUNCT | _ALPHA | _DIGIT); +} diff --git a/lib/crtdll/ctype/islower.c b/lib/crtdll/ctype/islower.c new file mode 100644 index 0000000..4ce38e1 --- /dev/null +++ b/lib/crtdll/ctype/islower.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef islower +int islower(int c) +{ + return _isctype(c,_LOWER); +} + +int iswlower(wint_t c) +{ + return iswctype(c,_LOWER); +} diff --git a/lib/crtdll/ctype/isprint.c b/lib/crtdll/ctype/isprint.c new file mode 100644 index 0000000..a75435d --- /dev/null +++ b/lib/crtdll/ctype/isprint.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isprint +int isprint(int c) +{ + return _isctype(c,_BLANK | _PUNCT | _ALPHA | _DIGIT); +} + +int iswprint(wint_t c) +{ + return iswctype((unsigned short)c,_BLANK | _PUNCT | _ALPHA | _DIGIT); +} diff --git a/lib/crtdll/ctype/ispunct.c b/lib/crtdll/ctype/ispunct.c new file mode 100644 index 0000000..57f0ab1 --- /dev/null +++ b/lib/crtdll/ctype/ispunct.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef ispunct +int ispunct(int c) +{ + return _isctype(c,_PUNCT); +} + +#undef iswpunct +int iswpunct(wint_t c) +{ + return iswctype(c,_PUNCT); +} diff --git a/lib/crtdll/ctype/isspace.c b/lib/crtdll/ctype/isspace.c new file mode 100644 index 0000000..0e90ae7 --- /dev/null +++ b/lib/crtdll/ctype/isspace.c @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/ctype/isspace.c + * PURPOSE: Test for a space character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + +#undef isspace +int isspace(int c) +{ + return _isctype(c,_SPACE); +} + +#undef iswspace +int iswspace(wint_t c) +{ + return iswctype(c,_SPACE); +} diff --git a/lib/crtdll/ctype/isupper.c b/lib/crtdll/ctype/isupper.c new file mode 100644 index 0000000..d0d95e0 --- /dev/null +++ b/lib/crtdll/ctype/isupper.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isupper +int isupper(int c) +{ + return _isctype(c,_UPPER); +} + +int iswupper(wint_t c) +{ + return iswctype(c,_UPPER); +} diff --git a/lib/crtdll/ctype/isxdigit.c b/lib/crtdll/ctype/isxdigit.c new file mode 100644 index 0000000..02c8c63 --- /dev/null +++ b/lib/crtdll/ctype/isxdigit.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isxdigit +int isxdigit(int c) +{ + return _isctype(c,_HEX); +} + +#undef iswxdigit +int iswxdigit(wint_t c) +{ + return iswctype(c,_HEX); +} + diff --git a/lib/crtdll/ctype/toascii.c b/lib/crtdll/ctype/toascii.c new file mode 100644 index 0000000..86d8ff3 --- /dev/null +++ b/lib/crtdll/ctype/toascii.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include + + +int __toascii(int c) +{ + return ((unsigned)(c) & 0x7F ); +} diff --git a/lib/crtdll/ctype/tolower.c b/lib/crtdll/ctype/tolower.c new file mode 100644 index 0000000..e3152d1 --- /dev/null +++ b/lib/crtdll/ctype/tolower.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef tolower +int tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - ('A' - 'a')); + return(c); +} + +#undef towlower +wchar_t towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - (L'A' - L'a')); + return(c); +} + +int _tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - ('A' - 'a')); + return(c); +} + +wchar_t _towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - (L'A' - L'a')); + return(c); +} + + + diff --git a/lib/crtdll/ctype/toupper.c b/lib/crtdll/ctype/toupper.c new file mode 100644 index 0000000..e0c8aa0 --- /dev/null +++ b/lib/crtdll/ctype/toupper.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#undef toupper +int toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + ('A' - 'a')); + return(c); +} + +#undef towupper +wchar_t towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + (L'A' - L'a')); + return(c); +} + +int _toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + ('A' - 'a')); + return(c); +} + +wchar_t _towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + (L'A' - L'a')); + return(c); +} diff --git a/lib/crtdll/direct/.cvsignore b/lib/crtdll/direct/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/direct/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/direct/chdir.c b/lib/crtdll/direct/chdir.c new file mode 100644 index 0000000..19a4a9f --- /dev/null +++ b/lib/crtdll/direct/chdir.c @@ -0,0 +1,18 @@ +#include +#include +#include + + + +int _chdir( const char *_path ) +{ + if ( _path[1] == ':') + _chdrive(tolower(_path[0] - 'a')+1); + if ( !SetCurrentDirectoryA((char *)_path) ) + return -1; + + return 0; +} + + + diff --git a/lib/crtdll/direct/chdrive.c b/lib/crtdll/direct/chdrive.c new file mode 100644 index 0000000..84d04c6 --- /dev/null +++ b/lib/crtdll/direct/chdrive.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +int cur_drive = 0; + + + +int _chdrive( int drive ) +{ + char d[3]; + if (!( drive >= 1 && drive <= 26 )) + return -1; + + if ( cur_drive != drive ) { + cur_drive = drive; + d[0] = toupper(cur_drive + '@'); + d[1] = ':'; + d[2] = 0; + SetCurrentDirectoryA(d); + } + + + return 0; +} diff --git a/lib/crtdll/direct/getcwd.c b/lib/crtdll/direct/getcwd.c new file mode 100644 index 0000000..65f8985 --- /dev/null +++ b/lib/crtdll/direct/getcwd.c @@ -0,0 +1,25 @@ +#include +#include +#include + + + +char *_getcwd( char *buffer, int maxlen ) +{ + char *cwd; + int len; + if ( buffer == NULL ) { + cwd = malloc(MAX_PATH); + len = MAX_PATH; + } + else { + cwd = buffer; + len = maxlen; + } + + if ( GetCurrentDirectoryA(len,cwd) == 0 ) + return NULL; + + return cwd; +} + diff --git a/lib/crtdll/direct/getdcwd.c b/lib/crtdll/direct/getdcwd.c new file mode 100644 index 0000000..0b2a8b5 --- /dev/null +++ b/lib/crtdll/direct/getdcwd.c @@ -0,0 +1,23 @@ +#include +#include + +char* _getdcwd (int nDrive, char* caBuffer, int nBufLen) +{ + int i =0; + int dr = _getdrive(); + + if ( nDrive < 1 || nDrive > 26 ) + return NULL; + + if ( dr != nDrive ) + _chdrive(nDrive); + + i = GetCurrentDirectoryA(nBufLen,caBuffer); + if ( i == nBufLen ) + return NULL; + + if ( dr != nDrive ) + _chdrive(dr); + + return caBuffer; +} diff --git a/lib/crtdll/direct/getdfree.c b/lib/crtdll/direct/getdfree.c new file mode 100644 index 0000000..766362b --- /dev/null +++ b/lib/crtdll/direct/getdfree.c @@ -0,0 +1,20 @@ +#include +#include +#include + + +unsigned int _getdiskfree(unsigned int _drive, struct _diskfree_t *_diskspace) +{ + char RootPathName[10]; + RootPathName[0] = toupper(_drive +'@'); + RootPathName[1] = ':'; + RootPathName[2] = '\\'; + RootPathName[3] = 0; + if ( _diskspace == NULL ) + return 0; + + if ( !GetDiskFreeSpaceA(RootPathName,(LPDWORD)&_diskspace->sectors_per_cluster,(LPDWORD)&_diskspace->bytes_per_sector, + (LPDWORD )&_diskspace->avail_clusters,(LPDWORD )&_diskspace->total_clusters ) ) + return 0; + return _diskspace->avail_clusters; +} diff --git a/lib/crtdll/direct/getdrive.c b/lib/crtdll/direct/getdrive.c new file mode 100644 index 0000000..a57e9ba --- /dev/null +++ b/lib/crtdll/direct/getdrive.c @@ -0,0 +1,26 @@ +#include +#include +#include + +extern int cur_drive; + + + +int _getdrive( void ) +{ + char Buffer[MAX_PATH]; + + if ( cur_drive == 0 ) { + GetCurrentDirectoryA(MAX_PATH,Buffer); + cur_drive = toupper(Buffer[0] - '@'); + } + + return cur_drive; +} + +unsigned long _getdrives(void) +{ + //fixme get logical drives + //return GetLogicalDrives(); + return 5; // drive A and C +} diff --git a/lib/crtdll/direct/mkdir.c b/lib/crtdll/direct/mkdir.c new file mode 100644 index 0000000..19191f8 --- /dev/null +++ b/lib/crtdll/direct/mkdir.c @@ -0,0 +1,10 @@ +#include +#include + + +int _mkdir( const char *_path ) +{ + if (!CreateDirectoryA(_path,NULL)) + return -1; + return 0; +} diff --git a/lib/crtdll/direct/rmdir.c b/lib/crtdll/direct/rmdir.c new file mode 100644 index 0000000..c6736de --- /dev/null +++ b/lib/crtdll/direct/rmdir.c @@ -0,0 +1,11 @@ +#include +#include + + + +int _rmdir( const char *_path ) +{ + if (!RemoveDirectoryA(_path)) + return -1; + return 0; +} diff --git a/lib/crtdll/dirent/.cvsignore b/lib/crtdll/dirent/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/dirent/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/dirent/dirent.c b/lib/crtdll/dirent/dirent.c new file mode 100644 index 0000000..018eb1d --- /dev/null +++ b/lib/crtdll/dirent/dirent.c @@ -0,0 +1,316 @@ +/* + * dirent.c + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Updated by Jeremy Bettis + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Peters + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +/* #include */ +#include +#include +#include +#include +#include + +#include + +#define SUFFIX "*" +#define SLASH "\\" +#define streq(a,b) (strcmp(a,b)==0) + +/* + * opendir + * + * Returns a pointer to a DIR structure appropriately filled in to begin + * searching a directory. + */ +DIR* +opendir(const char* szPath) +{ + DIR* nd; + struct stat statDir; + + errno = 0; + + if (!szPath) + { + errno = EFAULT; + return (DIR*) 0; + } + + if (szPath[0] == '\0') + { + errno = ENOTDIR; + return (DIR*) 0; + } + + /* Attempt to determine if the given path really is a directory. */ + if (_stat (szPath, &statDir)) + { + /* Error, stat should have set an error value. */ + return (DIR*) 0; + } + + if (!S_ISDIR(statDir.st_mode)) + { + /* Error, stat reports not a directory. */ + errno = ENOTDIR; + return (DIR*) 0; + } + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + nd = (DIR*) malloc (sizeof(DIR) + strlen(szPath) + strlen(SLASH) + + strlen(SUFFIX)); + + if (!nd) + { + /* Error, out of memory. */ + errno = ENOMEM; + return (DIR*) 0; + } + + /* Create the search expression. */ + strcpy(nd->dd_name, szPath); + + /* Add on a slash if the path does not end with one. */ + if (nd->dd_name[0] != '\0' && + nd->dd_name[strlen(nd->dd_name)-1] != '/' && + nd->dd_name[strlen(nd->dd_name)-1] != '\\') + { + strcat(nd->dd_name, SLASH); + } + + /* Add on the search pattern */ + strcat(nd->dd_name, SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst_t structure. */ + nd->dd_dir.d_ino = 0; + nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + nd->dd_dir.d_name = nd->dd_dta.name; + + return nd; +} + + +/* + * readdir + * + * Return a pointer to a dirent structure filled with the information on the + * next entry in the directory. + */ +struct dirent * +readdir( DIR *dirp ) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return (struct dirent*) 0; + } + + if (dirp->dd_dir.d_name != dirp->dd_dta.name) + { + /* The structure does not seem to be set up correctly. */ + errno = EINVAL; + return (struct dirent*) 0; + } + + if (dirp->dd_stat < 0) + { + /* We have already returned all files in the directory + * (or the structure has an invalid dd_stat). */ + return (struct dirent *) 0; + } + else if (dirp->dd_stat == 0) + { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = _findfirst(dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) + { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } + else + { + dirp->dd_stat = 1; + } + } + else + { + /* Get the next search entry. */ + if (_findnext(dirp->dd_handle, &(dirp->dd_dta))) + { + /* We are off the end or otherwise error. */ + _findclose (dirp->dd_handle); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + if (dirp->dd_stat > 0) + { + /* Successfully got an entry. Everything about the file is + * already appropriately filled in except the length of the + * file name. */ + dirp->dd_dir.d_namlen = strlen(dirp->dd_dir.d_name); + return &dirp->dd_dir; + } + + return (struct dirent*) 0; +} + + +/* + * closedir + * + * Frees up resources allocated by opendir. + */ +int +closedir (DIR* dirp) +{ + int rc; + + errno = 0; + rc = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + + if (dirp->dd_handle != -1) + { + rc = _findclose(dirp->dd_handle); + } + + /* Delete the dir structure. */ + free (dirp); + + return rc; +} + +/* + * rewinddir + * + * Return to the beginning of the directory "stream". We simply call findclose + * and then reset things like an opendir. + */ +void +rewinddir (DIR* dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (dirp->dd_handle != -1) + { + _findclose(dirp->dd_handle); + } + + dirp->dd_handle = -1; + dirp->dd_stat = 0; +} + +/* + * telldir + * + * Returns the "position" in the "directory stream" which can be used with + * seekdir to go back to an old entry. We simply return the value in stat. + */ +long +telldir (DIR* dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + return dirp->dd_stat; +} + +/* + * seekdir + * + * Seek to an entry previously returned by telldir. We rewind the directory + * and call readdir repeatedly until either dd_stat is the position number + * or -1 (off the end). This is not perfect, in that the directory may + * have changed while we weren't looking. But that is probably the case with + * any such system. + */ +void +seekdir (DIR* dirp, long lPos) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (lPos < -1) + { + /* Seeking to an invalid position. */ + errno = EINVAL; + return; + } + else if (lPos == -1) + { + /* Seek past end. */ + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Rewind and read forward to the appropriate index. */ + rewinddir (dirp); + + while ((dirp->dd_stat < lPos) && readdir(dirp)) + ; + } +} + diff --git a/lib/crtdll/except/.cvsignore b/lib/crtdll/except/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/except/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/except/abnorter.c b/lib/crtdll/except/abnorter.c new file mode 100644 index 0000000..2efd11a --- /dev/null +++ b/lib/crtdll/except/abnorter.c @@ -0,0 +1,7 @@ +#include + +int _abnormal_termination(void) +{ + printf("Abnormal Termination\n"); +// return AbnormalTermination(); +} diff --git a/lib/crtdll/except/exhand2.c b/lib/crtdll/except/exhand2.c new file mode 100644 index 0000000..be66fb4 --- /dev/null +++ b/lib/crtdll/except/exhand2.c @@ -0,0 +1,11 @@ +#include + +EXCEPTION_DISPOSITION +_except_handler2( +struct _EXCEPTION_RECORD *ExceptionRecord, +void *Frame, +struct _CONTEXT *ContextRecord, +void *DispatcherContext) +{ + printf("exception handler\n"); +} diff --git a/lib/crtdll/except/matherr.c b/lib/crtdll/except/matherr.c new file mode 100644 index 0000000..e921e84 --- /dev/null +++ b/lib/crtdll/except/matherr.c @@ -0,0 +1,22 @@ +struct _exception { + int type; + char *name; + double arg1; + double arg2; + double retval; + } ; + +int _matherr(struct _exception *e) +{ + return 0; +} +#define _FPIEEE_RECORD void + +int _fpieee_flt( + unsigned long exception_code, + struct _EXCEPTION_POINTERS *ExceptionPointer, + int (* handler)(_FPIEEE_RECORD *) + ) +{ + return 0; +} diff --git a/lib/crtdll/except/unwind.c b/lib/crtdll/except/unwind.c new file mode 100644 index 0000000..8bf460f --- /dev/null +++ b/lib/crtdll/except/unwind.c @@ -0,0 +1,14 @@ +#include +#define PEXCEPTION_FRAME void* + +void _global_unwind2( PEXCEPTION_FRAME frame ) +{ + //RtlUnwind( frame, 0, NULL, 0 ); +} + + +void _local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr ) +{ + //TRACE(crtdll,"(%p,%ld)\n",endframe,nr); + return; +} diff --git a/lib/crtdll/float/.cvsignore b/lib/crtdll/float/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/float/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/float/chgsign.c b/lib/crtdll/float/chgsign.c new file mode 100644 index 0000000..589cc40 --- /dev/null +++ b/lib/crtdll/float/chgsign.c @@ -0,0 +1,13 @@ +#include +#include + +double _chgsign( double __x ) +{ + double_t *x = (double_t *)&x; + if ( x->sign == 1 ) + x->sign = 0; + else + x->sign = 1; + + return __x; +} diff --git a/lib/crtdll/float/clearfp.c b/lib/crtdll/float/clearfp.c new file mode 100644 index 0000000..e824752 --- /dev/null +++ b/lib/crtdll/float/clearfp.c @@ -0,0 +1,13 @@ +#include + +unsigned int _clearfp (void) +{ + +unsigned short __res = _statusfp(); + +__asm__ __volatile__ ( + "fclex \n\t" + ); + return __res; +} + diff --git a/lib/crtdll/float/cntrlfp.c b/lib/crtdll/float/cntrlfp.c new file mode 100644 index 0000000..2ebdb0a --- /dev/null +++ b/lib/crtdll/float/cntrlfp.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include + +unsigned int _controlfp (unsigned int unNew, unsigned int unMask) +{ + return _control87(unNew,unMask); +} + +unsigned int _control87 (unsigned int unNew, unsigned int unMask) +{ + +register unsigned int __res; +__asm__ __volatile__ ( + "pushl %%eax \n\t" /* make room on stack */ + "fstcw (%%esp) \n\t" + "fwait \n\t" + "popl %%eax \n\t" + "andl $0xffff, %%eax \n\t" /* OK; we have the old value ready */ + + "movl %1, %%ecx \n\t" + "notl %%ecx \n\t" + "andl %%eax, %%ecx \n\t" /* the bits we want to keep */ + + "movl %2, %%edx \n\t" + "andl %1, %%edx \n\t" /* the bits we want to change */ + + "orl %%ecx, %%edx\n\t" /* the new value */ + "pushl %%edx \n\t" + "fldcw (%%esp) \n\t" + "popl %%edx \n\t" + + + :"=r" (__res):"r" (unNew),"r" (unMask): "ax", "dx", "cx"); +/* :"=a" (__res):"c" (unNew),"d" (unMask):"ax", "dx", "cx"); */ + + return __res; +} diff --git a/lib/crtdll/float/copysign.c b/lib/crtdll/float/copysign.c new file mode 100644 index 0000000..a59c08a --- /dev/null +++ b/lib/crtdll/float/copysign.c @@ -0,0 +1,13 @@ +#include +#include + +double _copysign (double __d, double __s) +{ + double_t *d = (double_t *)&__d; + double_t *s = (double_t *)&__s; + + d->sign = s->sign; + + return __d; +} + diff --git a/lib/crtdll/float/fpclass.c b/lib/crtdll/float/fpclass.c new file mode 100644 index 0000000..06c404f --- /dev/null +++ b/lib/crtdll/float/fpclass.c @@ -0,0 +1,65 @@ +#include +#include +#include + +#define _FPCLASS_SNAN 0x0001 /* signaling NaN */ +#define _FPCLASS_QNAN 0x0002 /* quiet NaN */ +#define _FPCLASS_NINF 0x0004 /* negative infinity */ +#define _FPCLASS_NN 0x0008 /* negative normal */ +#define _FPCLASS_ND 0x0010 /* negative denormal */ +#define _FPCLASS_NZ 0x0020 /* -0 */ +#define _FPCLASS_PZ 0x0040 /* +0 */ +#define _FPCLASS_PD 0x0080 /* positive denormal */ +#define _FPCLASS_PN 0x0100 /* positive normal */ +#define _FPCLASS_PINF 0x0200 /* positive infinity */ + +#define FP_SNAN 0x0001 // signaling NaN +#define FP_QNAN 0x0002 // quiet NaN +#define FP_NINF 0x0004 // negative infinity +#define FP_PINF 0x0200 // positive infinity +#define FP_NDENORM 0x0008 // negative denormalized non-zero +#define FP_PDENORM 0x0010 // positive denormalized non-zero +#define FP_NZERO 0x0020 // negative zero +#define FP_PZERO 0x0040 // positive zero +#define FP_NNORM 0x0080 // negative normalized non-zero +#define FP_PNORM 0x0100 // positive normalized non-zero + +typedef int fpclass_t; + +fpclass_t _fpclass(double __d) +{ + double_t *d = (double_t *)&__d; + + if ( d->exponent == 0 ) { + if ( d->mantissah == 0 && d->mantissal == 0 ) { + if ( d->sign ==0 ) + return FP_NZERO; + else + return FP_PZERO; + } else { + if ( d->sign ==0 ) + return FP_NDENORM; + else + return FP_PDENORM; + } + } + if (d->exponent == 0x7ff ) { + if ( d->mantissah == 0 && d->mantissal == 0 ) { + if ( d->sign ==0 ) + return FP_NINF; + else + return FP_PINF; + } + else if ( d->mantissah == 0 && d->mantissal != 0 ) { + return FP_QNAN; + } + else if ( d->mantissah == 0 && d->mantissal != 0 ) { + return FP_SNAN; + } + + } + + return 0; +} + + diff --git a/lib/crtdll/float/fpreset.c b/lib/crtdll/float/fpreset.c new file mode 100644 index 0000000..6e8dd3d --- /dev/null +++ b/lib/crtdll/float/fpreset.c @@ -0,0 +1,8 @@ +#include + +void _fpreset (void) +{ + /* FIXME: This causes an exception */ +// __asm__ __volatile__("fninit\n\t"); + return; +} diff --git a/lib/crtdll/float/isnan.c b/lib/crtdll/float/isnan.c new file mode 100644 index 0000000..d6f4ac0 --- /dev/null +++ b/lib/crtdll/float/isnan.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +int _isnan(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah != 0 || x->mantissal != 0 )); +} + +int _isnanl(long double __x) +{ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* IEEE 854 NaN's have the maximum possible + exponent and a nonzero mantissa. */ + + return (( x->exponent == 0x7fff) + && ( (x->mantissah & 0x80000000) != 0) + && ( (x->mantissah & (unsigned int)0x7fffffff) != 0 || x->mantissal != 0 )); +} + + +int _isinf(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah == 0 && x->mantissal == 0 )); +} + + + +int _finite( double x ) +{ + return !_isinf(x); +} + +int _isinfl(long double __x) +{ + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* An IEEE 854 infinity has an exponent with the + maximum possible value and a zero mantissa. */ + + + if ( x->exponent == 0x7fff && ( (x->mantissah == 0x80000000 ) && x->mantissal == 0 )) + return x->sign ? -1 : 1; + return 0; +} + + diff --git a/lib/crtdll/float/logb.c b/lib/crtdll/float/logb.c new file mode 100644 index 0000000..8b89627 --- /dev/null +++ b/lib/crtdll/float/logb.c @@ -0,0 +1,31 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +double _logb (double __x); + +double _logb (double __x) +{ + register double __value, __junk; + __asm __volatile__ + ("fxtract\n\t" + : "=t" (__junk), "=u" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/float/nafter.c b/lib/crtdll/float/nafter.c new file mode 100644 index 0000000..5e2a2ad --- /dev/null +++ b/lib/crtdll/float/nafter.c @@ -0,0 +1,12 @@ +#include + +double _nextafter( double x, double y ) +{ + if ( x == y) + return x; + + if ( isnan(x) || isnan(y) ) + return x; + + return x; +} diff --git a/lib/crtdll/float/nextaf.c b/lib/crtdll/float/nextaf.c new file mode 100644 index 0000000..d97d2dd --- /dev/null +++ b/lib/crtdll/float/nextaf.c @@ -0,0 +1,48 @@ +#define MAX_DOUBLE 1.7976931348623158e+308 +#define MIN_DOUBLE 2.2250738585072014e-308 + +double _xnextafter( double __x, double __y ) +{ + double_t *x = ( double_t *)&__x; + + double __e; + double_t *e = (double_t *)&__e; + + + if ( _isnan(__x) || _isinf(__x) ) + return __x; + + if ( _isnan(__y) ) + return __y; + + + // don't go to infinity just by adding + + if ( _isinf(__y) && fabs(__x) >= MAX_DOUBLE ) + return __x; + + if ( !_isinf(__y) && fabs(__x - __y) <= MIN_DOUBLE ) + return __y; + + + + + e->mantissal = 1; + e->mantissah = 0; + if ( x->exponent >= 53 ) + e->exponent = x->exponent - 52; + else + e->exponent = 1; + + if ( fabs(__x) < fabs(__y) ) + e->sign = 0; + else + e->sign = 1; + + + + return __x+__e; + + + +} diff --git a/lib/crtdll/float/scalb.c b/lib/crtdll/float/scalb.c new file mode 100644 index 0000000..e035584 --- /dev/null +++ b/lib/crtdll/float/scalb.c @@ -0,0 +1,12 @@ +#include +#include + +double _scalb( double __x, long e ) +{ + double_t *x = (double_t *)&__x; + + x->exponent += e; + + return __x; + +} diff --git a/lib/crtdll/float/statfp.c b/lib/crtdll/float/statfp.c new file mode 100644 index 0000000..5cfeabf --- /dev/null +++ b/lib/crtdll/float/statfp.c @@ -0,0 +1,14 @@ +#include + +unsigned int _statusfp (void) +{ + +register unsigned short __res; + +__asm__ __volatile__ ( + "fstsw %0 \n\t" +// "movzwl %ax, %eax" + :"=a" (__res) + ); + return __res; +} diff --git a/lib/crtdll/io/.cvsignore b/lib/crtdll/io/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/io/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/io/access.c b/lib/crtdll/io/access.c new file mode 100644 index 0000000..47f66cd --- /dev/null +++ b/lib/crtdll/io/access.c @@ -0,0 +1,38 @@ +#include +#include + +#ifndef F_OK + #define F_OK 0x01 +#endif +#ifndef R_OK + #define R_OK 0x02 +#endif +#ifndef W_OK + #define W_OK 0x04 +#endif +#ifndef X_OK + #define X_OK 0x08 +#endif +#ifndef D_OK + #define D_OK 0x10 +#endif + +int _access( const char *_path, int _amode ) +{ + DWORD Attributes = GetFileAttributesA(_path); + + if ( Attributes == -1 ) + return -1; + + if ( (_amode & W_OK) == W_OK ) { + if ( (Attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY ) + return -1; + } + if ( (_amode & D_OK) == D_OK ) { + if ( (Attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) + return -1; + } + + return 0; + +} diff --git a/lib/crtdll/io/chmod.c b/lib/crtdll/io/chmod.c new file mode 100644 index 0000000..be48dbf --- /dev/null +++ b/lib/crtdll/io/chmod.c @@ -0,0 +1,31 @@ +#include +#include +#define mode_t int + +int +_chmod(const char *filename, mode_t mode) +{ + DWORD FileAttributes = 0; + + FileAttributes = GetFileAttributes(filename); + if ( FileAttributes == -1 ) + return -1; + + if ( mode == 0 ) + return -1; + + + if ( (mode & _S_IREAD) == _S_IREAD && (mode & _S_IWRITE) != _S_IWRITE) + FileAttributes &= FILE_ATTRIBUTE_READONLY; + else if ( ((mode & _S_IREAD) != _S_IREAD) && ((mode & _S_IWRITE) == _S_IWRITE) ) + FileAttributes &= FILE_ATTRIBUTE_NORMAL; + else + FileAttributes &= FILE_ATTRIBUTE_NORMAL; + + + + if ( SetFileAttributes(filename,FileAttributes) == FALSE ) + return -1; + + return 1; +} diff --git a/lib/crtdll/io/chsize.c b/lib/crtdll/io/chsize.c new file mode 100644 index 0000000..9fd2ce2 --- /dev/null +++ b/lib/crtdll/io/chsize.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +#include + +int _chsize(int _fd, long size) +{ + if (lseek(_fd, size, 0) == -1) + return -1; + if (_write(_fd, 0, 0) < 0) + return -1; + return 0; +} diff --git a/lib/crtdll/io/close.c b/lib/crtdll/io/close.c new file mode 100644 index 0000000..2ca7aa8 --- /dev/null +++ b/lib/crtdll/io/close.c @@ -0,0 +1,14 @@ +#include +#include +#include + + +int _close(int _fd) +{ + if ( _fd == -1 ) + return -1; + if ( CloseHandle(_get_osfhandle(_fd)) == FALSE ) + return -1; + return __fileno_close(_fd); + +} diff --git a/lib/crtdll/io/commit.c b/lib/crtdll/io/commit.c new file mode 100644 index 0000000..8c9d787 --- /dev/null +++ b/lib/crtdll/io/commit.c @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +int _commode_dll = _IOCOMMIT; + +int _commit(int _fd) +{ + if (! FlushFileBuffers(_get_osfhandle(_fd)) ) { + __set_errno(EBADF); + return -1; + } + + return 0; +} diff --git a/lib/crtdll/io/create.c b/lib/crtdll/io/create.c new file mode 100644 index 0000000..4456a82 --- /dev/null +++ b/lib/crtdll/io/create.c @@ -0,0 +1,7 @@ +#include +#include + +int _creat(const char *filename, int mode) +{ + return open(filename,_O_CREAT|_O_TRUNC,mode); +} diff --git a/lib/crtdll/io/dup.c b/lib/crtdll/io/dup.c new file mode 100644 index 0000000..f2a22ce --- /dev/null +++ b/lib/crtdll/io/dup.c @@ -0,0 +1,12 @@ +#include +#include + +// fixme change type of mode argument to mode_t + +int __fileno_alloc(HANDLE hFile, int mode); +int __fileno_getmode(int _fd); + +int _dup( int handle ) +{ + return __fileno_alloc(_get_osfhandle(handle), __fileno_getmode(handle)); +} diff --git a/lib/crtdll/io/dup2.c b/lib/crtdll/io/dup2.c new file mode 100644 index 0000000..98ea368 --- /dev/null +++ b/lib/crtdll/io/dup2.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int _dup2( int handle1, int handle2 ) +{ + return __fileno_dup2( handle1, handle2 ); +} diff --git a/lib/crtdll/io/eof.c b/lib/crtdll/io/eof.c new file mode 100644 index 0000000..baf3952 --- /dev/null +++ b/lib/crtdll/io/eof.c @@ -0,0 +1,19 @@ +#include +#include + +int _eof( int _fd ) +{ + int cur_pos = _lseek(_fd, 0, SEEK_CUR); + int end_pos = _filelength( _fd ); + if ( cur_pos == -1 || end_pos == -1) + return -1; + + if ( cur_pos == end_pos ) + return 1; + + return 0; + + + + +} diff --git a/lib/crtdll/io/filelen.c b/lib/crtdll/io/filelen.c new file mode 100644 index 0000000..b234bf4 --- /dev/null +++ b/lib/crtdll/io/filelen.c @@ -0,0 +1,8 @@ +#include +#include + +long +_filelength(int _fd) +{ + return GetFileSize(_get_osfhandle(_fd),NULL); +} diff --git a/lib/crtdll/io/find.c b/lib/crtdll/io/find.c new file mode 100644 index 0000000..25ff5f7 --- /dev/null +++ b/lib/crtdll/io/find.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include + + + +int _findfirst(const char *_name, struct _finddata_t *result) +{ + + WIN32_FIND_DATA FindFileData; + char dir[MAX_PATH]; + long hFindFile; + int len = 0; + + if ( _name == NULL || _name[0] == 0 ) { + len = GetCurrentDirectory(MAX_PATH-4,dir); + if (dir[len-1] != '\\') { + dir[len] = '\\'; + dir[len+1] = 0; + } + strcat(dir,"*.*"); + } + else + strcpy(dir,_name); + hFindFile = (long)FindFirstFileA( dir, &FindFileData ); + if ( hFindFile == -1 ) { + memset(result,0,sizeof(struct _finddata_t)); + return -1; + } + result->attrib = FindFileData.dwFileAttributes; + + + result->time_create = FileTimeToUnixTime( &FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime( &FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime( &FindFileData.ftLastWriteTime,NULL); + result->size = FindFileData.nFileSizeLow; + strncpy(result->name,FindFileData.cFileName,260); + + // if no wildcard the find file handle can be closed right away + // a return value of 0 can flag this. + + if(!strchr(dir,'*') && !strchr(dir,'?')) { + _findclose(hFindFile); + return 0; + } + + + return hFindFile; + +} + +int _findnext(int handle, struct _finddata_t *result) +{ + WIN32_FIND_DATA FindFileData; + + // check no wildcards or invalid handle + if ( handle == 0 || handle == -1) + return 0; + + + + if ( !FindNextFile((void *)handle, &FindFileData ) ) + return -1; + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime( &FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime( &FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime( &FindFileData.ftLastWriteTime,NULL); + result->size = FindFileData.nFileSizeLow; + strncpy(result->name,FindFileData.cFileName,260); + return 0; +} + +int _findclose(int handle) +{ + // check no wildcards or invalid handle + if ( handle == 0 || handle == -1) + return 0; + return FindClose((void *)handle); +} diff --git a/lib/crtdll/io/fmode.c b/lib/crtdll/io/fmode.c new file mode 100644 index 0000000..79347bd --- /dev/null +++ b/lib/crtdll/io/fmode.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#undef _fmode +unsigned int _fmode = O_TEXT; + +unsigned int *_fmode_dll = &_fmode; + diff --git a/lib/crtdll/io/isatty.c b/lib/crtdll/io/isatty.c new file mode 100644 index 0000000..a452414 --- /dev/null +++ b/lib/crtdll/io/isatty.c @@ -0,0 +1,14 @@ +#include +#include + + +int _isatty( int fd ) +{ + struct stat buf; + + if (_fstat (fd, &buf) < 0) + return 0; + if (S_ISCHR (buf.st_mode)) + return 1; + return 0; +} diff --git a/lib/crtdll/io/locking.c b/lib/crtdll/io/locking.c new file mode 100644 index 0000000..b846ef5 --- /dev/null +++ b/lib/crtdll/io/locking.c @@ -0,0 +1,11 @@ +#include +#include + +int _locking( int _fd, int mode, long nbytes ) +{ + long offset = _lseek(_fd, 0L, 1); + if ( !LockFile(_get_osfhandle(_fd),offset,0,nbytes,0) ) + return -1; + + return 0; +} diff --git a/lib/crtdll/io/lseek.c b/lib/crtdll/io/lseek.c new file mode 100644 index 0000000..c585445 --- /dev/null +++ b/lib/crtdll/io/lseek.c @@ -0,0 +1,9 @@ +#include +#include +#include + +long _lseek(int _fildes, long _offset, int _whence) +{ + return _llseek((HFILE)filehnd(_fildes),_offset,_whence); +} + diff --git a/lib/crtdll/io/mktemp.c b/lib/crtdll/io/mktemp.c new file mode 100644 index 0000000..a5499ec --- /dev/null +++ b/lib/crtdll/io/mktemp.c @@ -0,0 +1,73 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/mktemp.c + * PURPOSE: Makes a temp file based on a template + * PROGRAMER: DJ Delorie + Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Appropriated for the Reactos Kernel + */ + +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + + +char* _mktemp (char *_template) +{ + static int count = 0; + char *cp, *dp; + int i, len, xcount, loopcnt; + + + + len = strlen (_template); + cp = _template + len; + + xcount = 0; + while (xcount < 6 && cp > _template && cp[-1] == 'X') + xcount++, cp--; + + if (xcount) { + dp = cp; + while (dp > _template && dp[-1] != '/' && dp[-1] != '\\' && dp[-1] != ':') + dp--; + + /* Keep the first characters of the template, but turn the rest into + Xs. */ + while (cp > dp + 8 - xcount) { + *--cp = 'X'; + xcount = (xcount >= 6) ? 6 : 1 + xcount; + } + + /* If dots occur too early -- squash them. */ + while (dp < cp) { + if (*dp == '.') *dp = 'a'; + dp++; + } + + /* Try to add ".tmp" to the filename. Truncate unused Xs. */ + if (cp + xcount + 3 < _template + len) + strcpy (cp + xcount, ".tmp"); + else + cp[xcount] = 0; + + /* This loop can run up to 2<<(5*6) times, or about 10^9 times. */ + for (loopcnt = 0; loopcnt < (1 << (5 * xcount)); loopcnt++) { + int c = count++; + for (i = 0; i < xcount; i++, c >>= 5) + cp[i] = "abcdefghijklmnopqrstuvwxyz012345"[c & 0x1f]; + if (_access(_template,0) == -1) + return _template; + } + } + + /* Failure: truncate the template and return NULL. */ + *_template = 0; + return 0; +} diff --git a/lib/crtdll/io/open.c b/lib/crtdll/io/open.c new file mode 100644 index 0000000..4cc7e33 --- /dev/null +++ b/lib/crtdll/io/open.c @@ -0,0 +1,268 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/open.c + * PURPOSE: Opens a file and translates handles to fileno + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +// rember to interlock the allocation of fileno when making this thread safe + +// possibly store extra information at the handle + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _fileno_modes_type +{ + HANDLE hFile; + int mode; + int fd; +} fileno_modes_type; + +fileno_modes_type *fileno_modes = NULL; + +int maxfno = 5; +int minfno = 5; + +char __is_text_file(FILE *p) +{ + if ( p == NULL || fileno_modes == NULL ) + return FALSE; + return (!((p)->_flag&_IOSTRG) && (fileno_modes[(p)->_file].mode&O_TEXT)); +} + + + + +int __fileno_alloc(HANDLE hFile, int mode); + + +int _open(const char *_path, int _oflag,...) +{ + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD dwCreationDistribution = 0; + DWORD dwFlagsAndAttributes = 0; + int mode; + va_list arg; + + va_start (arg, _oflag); + mode = va_arg(arg,int); + va_end (arg); + if ( (mode == S_IWRITE) || (mode == 0) ) + dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY; + + /* + * + * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.) + * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.) + * + */ + if (( _oflag & _O_RDWR ) == _O_RDWR ) + dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ ; + else if (( _oflag & _O_WRONLY ) == _O_WRONLY ) + dwDesiredAccess |= GENERIC_WRITE ; + else + dwDesiredAccess |= GENERIC_READ ; + + if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) ) + dwCreationDistribution |= CREATE_NEW; + + else if (( _oflag & O_TRUNC ) == O_TRUNC ) { + if (( _oflag & O_CREAT ) == O_CREAT ) + dwCreationDistribution |= CREATE_ALWAYS; + else if (( _oflag & O_RDONLY ) != O_RDONLY ) + dwCreationDistribution |= TRUNCATE_EXISTING; + } + else if (( _oflag & _O_APPEND ) == _O_APPEND ) + dwCreationDistribution |= OPEN_EXISTING; + else if (( _oflag & _O_CREAT ) == _O_CREAT ) + dwCreationDistribution |= OPEN_ALWAYS; + else + dwCreationDistribution |= OPEN_EXISTING; + + if (( _oflag & _O_RANDOM ) == _O_RANDOM ) + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL ) + dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + + if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY ) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED ) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + hFile = CreateFileA(_path, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDistribution, + dwFlagsAndAttributes, + NULL); + if (hFile == (HANDLE)-1) + return -1; + return __fileno_alloc(hFile,_oflag); + +// _O_APPEND Moves file pointer to end of file before every write operation. + +} + + + + +int +__fileno_alloc(HANDLE hFile, int mode) +{ + + int i; + /* Check for bogus values */ + if (hFile < 0) + return -1; + + for(i=minfno;i= maxfno ) + return (void *)-1; + + if ( fileno_modes[fileno].fd == -1 ) + return (void *)-1; + return fileno_modes[fileno].hFile; +} + +int __fileno_dup2( int handle1, int handle2 ) +{ + if ( handle1 >= maxfno ) + return -1; + + if ( handle1 < 0 ) + return -1; + if ( handle2 >= maxfno ) + return -1; + + if ( handle2 < 0 ) + return -1; + + memcpy(&fileno_modes[handle1],&fileno_modes[handle2],sizeof(fileno_modes)); + + + return handle1; +} + +int __fileno_setmode(int _fd, int _newmode) +{ + int m; + if ( _fd < minfno ) + return -1; + + if ( _fd >= maxfno ) + return -1; + + m = fileno_modes[_fd].mode; + fileno_modes[_fd].mode = _newmode; + return m; +} + +int __fileno_getmode(int _fd) +{ + if ( _fd < minfno ) + return -1; + + if ( _fd >= maxfno ) + return -1; + + return fileno_modes[_fd].mode; + +} + + +int __fileno_close(int _fd) +{ + if ( _fd < 0 ) + return -1; + + if ( _fd >= maxfno ) + return -1; + + fileno_modes[_fd].fd = -1; + fileno_modes[_fd].hFile = (HANDLE)-1; + return 0; +} + +int _open_osfhandle (void *osfhandle, int flags ) +{ + return __fileno_alloc((HANDLE)osfhandle, flags); +} + +void *_get_osfhandle( int fileno ) +{ + return filehnd(fileno); +} diff --git a/lib/crtdll/io/pipe.c b/lib/crtdll/io/pipe.c new file mode 100644 index 0000000..8c67f7a --- /dev/null +++ b/lib/crtdll/io/pipe.c @@ -0,0 +1,26 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/pipe.c + * PURPOSE: Creates a pipe + * PROGRAMER: DJ Delorie + * UPDATE HISTORY: + * 28/12/98: Appropriated for Reactos + */ +#include +#include +#include + + +int _pipe(int _fildes[2], unsigned int size, int mode ) +{ + HANDLE hReadPipe, hWritePipe; + + if ( !CreatePipe(&hReadPipe,&hWritePipe,NULL,size)) + return -1; + + _fildes[0] = __fileno_alloc(hReadPipe, mode); + _fildes[1] = __fileno_alloc(hWritePipe, mode); + + return 0; +} diff --git a/lib/crtdll/io/read.c b/lib/crtdll/io/read.c new file mode 100644 index 0000000..e5dc4ad --- /dev/null +++ b/lib/crtdll/io/read.c @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/read.c + * PURPOSE: Reads a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +size_t _read(int _fd, void *_buf, size_t _nbyte) +{ + DWORD _rbyte; + + if (!ReadFile(_get_osfhandle(_fd),_buf,_nbyte,&_rbyte,NULL)) + { + return -1; + } + return (size_t)_rbyte; +} diff --git a/lib/crtdll/io/setmode.c b/lib/crtdll/io/setmode.c new file mode 100644 index 0000000..ea6f7e8 --- /dev/null +++ b/lib/crtdll/io/setmode.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/setmode.c + * PURPOSE: Sets the file translation mode + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + + +int _setmode(int _fd, int _newmode) +{ + return __fileno_setmode(_fd, _newmode); +} diff --git a/lib/crtdll/io/sopen.c b/lib/crtdll/io/sopen.c new file mode 100644 index 0000000..5d42157 --- /dev/null +++ b/lib/crtdll/io/sopen.c @@ -0,0 +1,7 @@ +#include + + +int _sopen(char *path,int access,int shflag,int mode) +{ + return _open((path), (access)|(shflag), (mode)); +} diff --git a/lib/crtdll/io/tell.c b/lib/crtdll/io/tell.c new file mode 100644 index 0000000..ce53df0 --- /dev/null +++ b/lib/crtdll/io/tell.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + + +off_t +_tell(int _file) +{ + return _lseek(_file, 0, SEEK_CUR); +} diff --git a/lib/crtdll/io/umask.c b/lib/crtdll/io/umask.c new file mode 100644 index 0000000..7a8323b --- /dev/null +++ b/lib/crtdll/io/umask.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +unsigned _unMode_dll = 022; + +unsigned _umask (unsigned unMode) +{ + unsigned old_mask = _unMode_dll; + _unMode_dll = unMode; + return old_mask; +} diff --git a/lib/crtdll/io/unlink.c b/lib/crtdll/io/unlink.c new file mode 100644 index 0000000..65ef9d4 --- /dev/null +++ b/lib/crtdll/io/unlink.c @@ -0,0 +1,20 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/unlink.c + * PURPOSE: Deletes a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + + + +int _unlink( const char *filename ) +{ + if ( !DeleteFileA(filename) ) + return -1; + return 0; +} diff --git a/lib/crtdll/io/utime.c b/lib/crtdll/io/utime.c new file mode 100644 index 0000000..90b9921 --- /dev/null +++ b/lib/crtdll/io/utime.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +int _utime(const char* filename, struct _utimbuf* buf) +{ + int fn; + int ret; + + fn = _open(filename, _O_RDWR); + if ( fn == -1 ) { + __set_errno(EBADF); + return -1; + } + ret = _futime(fn,buf); + if ( _close(fn) < 0 ) + return -1; + return ret; + +} diff --git a/lib/crtdll/io/write.c b/lib/crtdll/io/write.c new file mode 100644 index 0000000..30f0f26 --- /dev/null +++ b/lib/crtdll/io/write.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/write.c + * PURPOSE: Writes to a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + + + +size_t _write(int _fd, const void *_buf, size_t _nbyte) +{ + DWORD _wbyte; + + if ( !WriteFile(_get_osfhandle(_fd),_buf,_nbyte,&_wbyte,NULL) ) + { + return -1; + } + return (size_t)_wbyte; +} diff --git a/lib/crtdll/libc/.cvsignore b/lib/crtdll/libc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/libc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/libc/atexit.h b/lib/crtdll/libc/atexit.h new file mode 100644 index 0000000..b3a9f01 --- /dev/null +++ b/lib/crtdll/libc/atexit.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_atexit_h__ +#define __dj_include_libc_dosexec_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +struct __atexit { + struct __atexit *__next; + void (*__function)(void); +}; + +extern struct __atexit *__atexit_ptr; + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_dosexec_h__ */ diff --git a/lib/crtdll/libc/file.h b/lib/crtdll/libc/file.h new file mode 100644 index 0000000..c80ffb5 --- /dev/null +++ b/lib/crtdll/libc/file.h @@ -0,0 +1,64 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_libc_file_h__ +#define __dj_include_libc_file_h__ + +#include +#include + + +//#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +#ifndef _IORMONCL +#define _IORMONCL 004000 /* remove on close, for temp files */ +#endif +/* if _flag & _IORMONCL, ._name_to_remove needs freeing */ + +#ifndef _IOUNGETC +#define _IOUNGETC 010000 /* there is an ungetc'ed character in the buffer */ +#endif + +int _flsbuf(int, FILE*); +int _filbuf(FILE *); +void _fwalk(void (*)(FILE *)); + + + +char __is_text_file(FILE *p); + +int _doprnt(const char *fmt, va_list args, FILE *f); +int _doscan(FILE *iop, const char *fmt, void **argp); + +void *filehnd(int fileno); +int __fileno_dup2( int handle1, int handle2 ); +int __fileno_setmode(int _fd, int _newmode); +int __fileno_close(int _fd); + +#undef fileno +#define fileno(f) (f->_file) +#undef feof +#define feof(f) (((f)->_flag&_IOEOF)!=0) +#undef ferror +#define ferror(f) (((f)->_flag&_IOERR)!=0) + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_libc_file_h__ */ diff --git a/lib/crtdll/locale/.cvsignore b/lib/crtdll/locale/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/locale/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/locale/locale.c b/lib/crtdll/locale/locale.c new file mode 100644 index 0000000..d72fcb0 --- /dev/null +++ b/lib/crtdll/locale/locale.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include + + +int _current_category; /* used by setlocale */ +const char *_current_locale; +int __mb_cur_max_dll = 1; + +int parse_locale(char *locale, char *lang, char *country, char *code_page); + +char *setlocale(int category, const char *locale) +{ + char lang[100]; + char country[100]; + char code_page[100]; + parse_locale((char *)locale,lang,country,code_page); + + //printf("%s %s %s %s\n",locale,lang,country,code_page); + + + switch ( category ) + { + case LC_COLLATE: + break; + case LC_CTYPE: + break; + case LC_MONETARY: + break; + case LC_NUMERIC: + break; + case LC_TIME: + break; + case LC_ALL: + break; + default: + break; + } + + return "C"; + +} + +/* + +locale "lang[_country[.code_page]]" + | ".code_page" + | "" + | NULL + +*/ +int parse_locale(char *locale, char *lang, char *country, char *code_page) +{ + while ( *locale != 0 && *locale != '.' && *locale != '_' ) + { + *lang = *locale; + lang++; + locale++; + } + *lang = 0; + if ( *locale == '_' ) { + locale++; + while ( *locale != 0 && *locale != '.' ) + { + *country = *locale; + country++; + locale++; + } + } + *country = 0; + + + if ( *locale == '.' ) { + locale++; + while ( *locale != 0 && *locale != '.' ) + { + *code_page = *locale; + code_page++; + locale++; + } + } + + *code_page = 0; + return 0; +} + +const struct map_lcid2str { + short langid; + const char *langname; + const char *country; +} languages[]={ + {0x0409,"English", "United States"}, + {0x0809,"English", "United Kingdom"}, + {0x0000,"Unknown", "Unknown"} + +}; + +const struct map_cntr { + const char *abrev; + const char *country; +} abrev[] = { + {"britain", "united kingdom"}, + {"england", "united kingdom"}, + {"gbr", "united kingdom"}, + {"great britain", "united kingdom"}, + {"uk", "united kingdom"}, + {"united kingdom", "united kingdom"}, + {"united-kingdom", "united kingdom"}, + {"america", "united states" }, + {"united states", "united states"}, + {"united-states", "united states"}, + {"us", "united states"}, + {"usa" "united states"} +}; + + +struct lconv _lconv = { +".", // decimal_point +",", // thousands_sep +"", // grouping; +"DOL", // int_curr_symbol +"$", // currency_symbol +".", // mon_decimal_point +",", // mon_thousands_sep +"", // mon_grouping; +"+", // positive_sign +"-", // negative_sign +127, // int_frac_digits +127, // frac_digits +127, // p_cs_precedes +127, // p_sep_by_space +127, // n_cs_precedes +127, // n_sep_by_space +127, // p_sign_posn; +127 // n_sign_posn; +}; + +struct lconv *localeconv(void) +{ + return (struct lconv *) &_lconv; +} + diff --git a/lib/crtdll/makefile b/lib/crtdll/makefile new file mode 100644 index 0000000..e834864 --- /dev/null +++ b/lib/crtdll/makefile @@ -0,0 +1,160 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = crtdll + +TARGET_LFLAGS = -nostartfiles + +TARGET_SDKLIBS = kernel32.a + +TARGET_BASE = 0x77630000 + +TARGET_DEFONLY = yes + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CLEAN = assert/*.o conio/*.o ctype/*.o direct/*.o dirent/*.o \ + except/*.o float/*.o io/*.o libc/*.o locale/*.o malloc/*.o \ + math/*.o mbstring/*.o misc/*.o process/*.o quad/*.o search/*.o \ + setjmp/*.o stdio/*.o stdlib/*.o string/*.o sys_stat/*.o tchar/*.o \ + time/*.o wchar/*.o signal/*.o + + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + + +ASSERT_OBJECTS = assert/assert.o + +CTYPE_OBJECTS = ctype/isalnum.o \ + ctype/isalpha.o ctype/isascii.o ctype/iscntrl.o ctype/isdigit.o ctype/isgraph.o \ + ctype/islower.o ctype/isprint.o ctype/ispunct.o ctype/isspace.o ctype/isupper.o \ + ctype/isxdigit.o ctype/toascii.o ctype/tolower.o ctype/toupper.o\ + ctype/iscsym.o ctype/isctype.o + +CONIO_OBJECTS = conio/cputs.o conio/getch.o conio/getche.o conio/putch.o conio/ungetch.o\ + conio/kbhit.o conio/cgets.o conio/cprintf.o conio/cscanf.o + +DIRECT_OBJECTS = direct/chdir.o direct/chdrive.o direct/getcwd.o direct/getdrive.o \ + direct/rmdir.o direct/mkdir.o direct/getdfree.o direct/getdcwd.o + +EXCEPT_OBJECTS = except/unwind.o except/abnorter.o except/exhand2.o except/matherr.o + +LOCALE_OBJECTS = locale/locale.o + +MALLOC_OBJECTS = malloc/expand.o malloc/heap.o + + +MISC_OBJECTS = misc/GetArgs.o misc/dllmain.o misc/setnew.o misc/purecall.o misc/initterm.o\ + misc/amsg.o + +MBSTRING_OBJECTS = mbstring/mbsnicmp.o mbstring/mbsnset.o mbstring/mbsnextc.o mbstring/mbsnicoll.o mbstring/islead.o mbstring/mbsspnp.o \ + mbstring/mbspbrk.o mbstring/mbsspn.o mbstring/mbbtype.o mbstring/mbscat.o mbstring/mbschr.o \ + mbstring/mbccpy.o mbstring/mbslen.o mbstring/mbsrchr.o mbstring/mbsset.o mbstring/mbsncat.o mbstring/mbsncmp.o \ + mbstring/mbscmp.o mbstring/mbsncoll.o mbstring/mbscoll.o mbstring/mbsncpy.o mbstring/mbscpy.o mbstring/mbscspn.o \ + mbstring/mbsdup.o mbstring/mbsicmp.o mbstring/mbsicoll.o mbstring/mbsnccnt.o mbstring/mbsrev.o mbstring/mbsstr.o \ + mbstring/mbsinc.o mbstring/mbsdec.o mbstring/mbsninc.o mbstring/mbclen.o mbstring/iskana.o mbstring/jmstojis.o \ + mbstring/jistojms.o mbstring/iskpun.o mbstring/iskmoji.o mbstring/ismbgra.o mbstring/ismbpri.o mbstring/isuppr.o \ + mbstring/islwr.o mbstring/ismbkaln.o mbstring/mbstrlen.o mbstring/ismbc.o \ + mbstring/ismbtrl.o mbstring/ismblead.o mbstring/ischira.o mbstring/hanzen.o mbstring/ismbaln.o mbstring/ismbal.o \ + mbstring/ismbpun.o mbstring/mbslwr.o mbstring/mbsupr.o mbstring/mbstok.o + +STRING_OBJECTS = string/memchr.o string/memcmp.o string/strcat.o \ + string/strchr.o string/strcmp.o string/strcoll.o \ + string/strcpy.o string/strcspn.o string/memcpy.o \ + string/strlen.o string/strncat.o string/strncmp.o \ + string/strncpy.o string/strpbrk.o string/strrchr.o \ + string/strspn.o string/strstr.o string/strtok.o \ + string/strxfrm.o string/memmove.o string/memset.o \ + string/strdup.o string/strlwr.o string/strupr.o \ + string/str_old.o string/strerror.o string/stricmp.o\ + string/strnlen.o string/strnicmp.o string/strrev.o\ + string/memccpy.o string/memicmp.o string/strset.o + +WCHAR_OBJECTS = wchar/wcscat.o wchar/wcschr.o wchar/wcscmp.o \ + wchar/wcscoll.o wchar/wcscpy.o wchar/wcscspn.o \ + wchar/wcsdup.o wchar/wcsicmp.o wchar/wcslen.o \ + wchar/wcslwr.o wchar/wcsncat.o wchar/wcsncmp.o \ + wchar/wcsncpy.o wchar/wcsnlen.o wchar/wcspbrk.o wchar/wcsrchr.o\ + wchar/wcsrev.o wchar/wcsset.o wchar/wcsspn.o wchar/wcsstr.o\ + wchar/wcstod.o wchar/wcstok.o wchar/wcstol.o wchar/wcsupr.o\ + wchar/wcsxfrm.o wchar/wtoi.o wchar/wcstombs.o wchar/wcsnicmp.o + +SETJMP_OBJECTS = setjmp/setjmp.o + +STDIO_OBJECTS = stdio/getenv.o stdio/filbuf.o \ + stdio/fclose.o stdio/feof.o stdio/ferror.o stdio/fileno.o\ + stdio/fflush.o stdio/fgetc.o stdio/fgetpos.o stdio/fgets.o stdio/flsbuf.o \ + stdio/fopen.o stdio/fprintf.o stdio/fputc.o stdio/fputs.o stdio/setvbuf.o\ + stdio/fread.o stdio/freopen.o stdio/fscanf.o stdio/fseek.o \ + stdio/fsetpos.o stdio/ftell.o stdio/fwalk.o stdio/fwrite.o stdio/getc.o \ + stdio/getchar.o stdio/gets.o stdio/getw.o stdio/perror.o stdio/clearerr.o \ + stdio/putc.o stdio/putchar.o stdio/puts.o stdio/putw.o stdio/fputchar.o\ + stdio/remove.o stdio/rename.o stdio/rewind.o stdio/allocfil.o\ + stdio/setbuf.o stdio/setbuffe.o stdlib/obsol.o stdio/setlineb.o\ + stdio/scanf.o stdio/sscanf.o stdio/vscanf.o stdio/vsscanf.o stdio/vfscanf.o\ + stdio/stdiohk.o stdio/stdhnd.o stdio/tempnam.o stdio/tmpfile.o stdio/tmpnam.o \ + stdio/ungetc.o stdio/printf.o stdio/vfprintf.o stdio/vprintf.o stdio/sprintf.o\ + stdio/fdopen.o stdio/vsprintf.o stdio/frlist.o stdio/fgetchar.o stdio/rmtmp.o\ + stdio/fsopen.o stdio/popen.o stdio/vfwprint.o + +QUAD_OBJECTS = quad/qdivrem.o quad/divdi3.o quad/moddi3.o quad/udivdi3.o quad/umoddi3.o + +IO_OBJECTS = io/access.o io/close.o io/create.o io/dup.o io/dup2.o io/find.o io/isatty.o io/lseek.o \ + io/open.o io/read.o io/setmode.o io/unlink.o io/write.o io/fmode.o io/mktemp.o\ + io/chmod.o io/chsize.o io/commit.o io/locking.o io/pipe.o io/sopen.o io/filelen.o\ + io/umask.o io/tell.o io/eof.o io/utime.o + +SEARCH_OBJECTS = search/lsearch.o search/lfind.o + +STDLIB_OBJECTS = stdlib/abort.o stdlib/abs.o stdlib/atexit.o stdlib/atof.o stdlib/atoi.o \ + stdlib/bsearch.o stdlib/div.o stdlib/errno.o stdlib/_exit.o \ + stdlib/fullpath.o stdlib/labs.o stdlib/ldiv.o stdlib/itoa.o\ + stdlib/makepath.o stdlib/malloc.o stdlib/putenv.o stdlib/qsort.o \ + stdlib/rand.o stdlib/senv.o stdlib/splitp.o stdlib/strtod.o stdlib/strtol.o \ + stdlib/strtoul.o stdlib/swab.o stdlib/atol.o stdlib/rot.o stdlib/wcstomb.o\ + stdlib/ecvt.o stdlib/ecvtbuf.o stdlib/gcvt.o stdlib/fcvt.o stdlib/fcvtbuf.o\ + stdlib/mbstowcs.o stdlib/itow.o + +SIGNAL_OBJECTS = signal/signal.o signal/xcptfil.o signal/xcptinfo.o + +PROCESS_OBJECTS = process/_cwait.o process/dll.o process/spawnl.o process/spawnlp.o process/spawnlpe.o process/spawnvp.o \ + process/spawnv.o process/spawnve.o process/spawnle.o process/execl.o process/execlp.o process/execlpe.o \ + process/execvpe.o process/execvp.o process/execv.o process/execle.o process/_system.o\ + process/execve.o process/threadid.o process/thread.o process/procid.o + +TCHAR_OBJECTS = tchar/strdec.o tchar/strinc.o tchar/strninc.o tchar/strncnt.o tchar/strnextc.o tchar/strspnp.o + +TIME_OBJECTS = time/ctime.o time/difftime.o time/strftime.o time/time.o time/clock.o time/strdate.o\ + time/strtime.o + +FLOAT_OBJECTS = float/fpreset.o float/clearfp.o float/cntrlfp.o float/statfp.o float/logb.o\ + float/chgsign.o float/fpclass.o float/isnan.o float/nafter.o float/scalb.o\ + float/copysign.o + +SYS_STAT_OBJECTS = sys_stat/fstat.o sys_stat/stat.o sys_stat/futime.o sys_stat/ftime.o\ + sys_stat/systime.o + +MATH_OBJECTS = math/acos.o math/acosh.o math/asin.o math/asinh.o math/atan.o math/atan2.o\ + math/atanh.o math/ceil.o math/cos.o math/cosh.o math/exp.o math/fabs.o\ + math/floor.o math/fmod.o math/frexp.o math/huge_val.o math/hypot.o\ + math/ldexp.o math/log.o math/log10.o math/modf.o math/pow.o\ + math/sin.o math/sinh.o math/sqrt.o math/tan.o\ + math/tanh.o math/stubs.o math/j0_y0.o math/j1_y1.o math/jn_yn.o\ + math/cabs.o math/ftol.o + +OBJECTS = $(MISC_OBJECTS) $(STDLIB_OBJECTS) $(IO_OBJECTS) \ + $(FLOAT_OBJECTS) $(ASSERT_OBJECTS) $(PROCESS_OBJECTS) \ + $(STDIO_OBJECTS) $(CTYPE_OBJECTS) $(MATH_OBJECTS) \ + $(STRING_OBJECTS) $(TIME_OBJECTS) $(WCHAR_OBJECTS) \ + $(SYS_STAT_OBJECTS) $(MALLOC_OBJECTS) $(MBSTRING_OBJECTS)\ + $(SEARCH_OBJECTS) $(CONIO_OBJECTS) $(DIRECT_OBJECTS) \ + $(SIGNAL_OBJECTS) $(SETJMP_OBJECTS) $(LOCALE_OBJECTS) \ + $(EXCEPT_OBJECTS) $(TCHAR_OBJECTS) + +$(TARGET_NAME).o: $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o diff --git a/lib/crtdll/malloc/.cvsignore b/lib/crtdll/malloc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/malloc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/malloc/expand.c b/lib/crtdll/malloc/expand.c new file mode 100644 index 0000000..321330b --- /dev/null +++ b/lib/crtdll/malloc/expand.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +void *_expand( void *pold, size_t size ) +{ + PHEAP_BUCKET pbucket; + PHEAP_SUBALLOC psub; + PHEAP_FRAGMENT pfrag=(PHEAP_FRAGMENT)((LPVOID)pold-HEAP_FRAG_ADMIN_SIZE); + + /* sanity checks */ + if(pfrag->Magic!=HEAP_FRAG_MAGIC) + return NULL; + + /* get bucket size */ + psub=pfrag->Sub; + pbucket=psub->Bucket; + if(size<=pbucket->Size) + { + pfrag->Size=size; + return pold; + } + else + return NULL; + + return NULL; +} + +size_t _msize (void* pBlock) +{ + PHEAP_BUCKET pbucket; + PHEAP_SUBALLOC psub; + PHEAP_FRAGMENT pfrag=(PHEAP_FRAGMENT)((LPVOID)pBlock-HEAP_FRAG_ADMIN_SIZE); + + /* sanity checks */ + if(pfrag->Magic!=HEAP_FRAG_MAGIC) + return 0; + + /* get bucket size */ + psub=pfrag->Sub; + pbucket=psub->Bucket; + return pbucket->Size; +} diff --git a/lib/crtdll/malloc/heap.c b/lib/crtdll/malloc/heap.c new file mode 100644 index 0000000..11d9907 --- /dev/null +++ b/lib/crtdll/malloc/heap.c @@ -0,0 +1,29 @@ + +#include +#include + +int _heapchk (void) +{ + if (!HeapValidate(GetProcessHeap(), 0, NULL)) + return -1; + return 0; +} +int _heapmin (void) +{ + if ( !HeapCompact( GetProcessHeap(), 0 )) + return -1; + return 0; +} +int _heapset (unsigned int unFill) +{ + if ( _heapchk() == -1 ) + return -1; + return 0; + +} + + +int _heapwalk ( struct _heapinfo *entry) +{ + return 0; +} diff --git a/lib/crtdll/math/.cvsignore b/lib/crtdll/math/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/math/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/math/acos.c b/lib/crtdll/math/acos.c new file mode 100644 index 0000000..776ddd2 --- /dev/null +++ b/lib/crtdll/math/acos.c @@ -0,0 +1,26 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double acos (double __x) +{ + return atan2 (sqrt (1.0 - __x * __x), __x); +} diff --git a/lib/crtdll/math/acosh.c b/lib/crtdll/math/acosh.c new file mode 100644 index 0000000..15f556c --- /dev/null +++ b/lib/crtdll/math/acosh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +acosh(double x) +{ + return log(x + sqrt(x*x - 1)); +} diff --git a/lib/crtdll/math/asin.c b/lib/crtdll/math/asin.c new file mode 100644 index 0000000..4109811 --- /dev/null +++ b/lib/crtdll/math/asin.c @@ -0,0 +1,26 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double asin (double __x) +{ + return atan2 (__x, sqrt (1.0 - __x * __x)); +} diff --git a/lib/crtdll/math/asinh.c b/lib/crtdll/math/asinh.c new file mode 100644 index 0000000..7089ebc --- /dev/null +++ b/lib/crtdll/math/asinh.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +asinh(double x) +{ + return x>0 ? log(x + sqrt(x*x + 1)) : -log(sqrt(x*x+1)-x); +} + diff --git a/lib/crtdll/math/atan.c b/lib/crtdll/math/atan.c new file mode 100644 index 0000000..853385b --- /dev/null +++ b/lib/crtdll/math/atan.c @@ -0,0 +1,32 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +double atan (double __x); + +double atan (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fpatan" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/atan2.c b/lib/crtdll/math/atan2.c new file mode 100644 index 0000000..f23be33 --- /dev/null +++ b/lib/crtdll/math/atan2.c @@ -0,0 +1,12 @@ +double atan2 (double __y, double __x); + +double atan2 (double __y, double __x) +{ + register double __value; + __asm __volatile__ + ("fpatan\n\t" + "fld %%st(0)" + : "=t" (__value) : "0" (__x), "u" (__y)); + + return __value; +} diff --git a/lib/crtdll/math/atanh.c b/lib/crtdll/math/atanh.c new file mode 100644 index 0000000..fdfb319 --- /dev/null +++ b/lib/crtdll/math/atanh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +atanh(double x) +{ + return log((1+x)/(1-x)) / 2.0; +} diff --git a/lib/crtdll/math/cabs.c b/lib/crtdll/math/cabs.c new file mode 100644 index 0000000..2c3ada9 --- /dev/null +++ b/lib/crtdll/math/cabs.c @@ -0,0 +1,11 @@ +#include + +double _cabs( struct _complex z ) +{ + return sqrt( z.x*z.x + z.y*z.y ); +// return hypot(z.x,z.y); +} + + + + diff --git a/lib/crtdll/math/ceil.c b/lib/crtdll/math/ceil.c new file mode 100644 index 0000000..eedff4f --- /dev/null +++ b/lib/crtdll/math/ceil.c @@ -0,0 +1,23 @@ +#include + +double ceil (double __x); + +double ceil (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + + +long double ceill (long double __x) +{ + return floor(__x)+1; +} diff --git a/lib/crtdll/math/cos.c b/lib/crtdll/math/cos.c new file mode 100644 index 0000000..07edd8b --- /dev/null +++ b/lib/crtdll/math/cos.c @@ -0,0 +1,11 @@ +double cos (double __x); + +double cos (double __x) +{ + register double __value; + __asm __volatile__ + ("fcos" + : "=t" (__value): "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/cosh.c b/lib/crtdll/math/cosh.c new file mode 100644 index 0000000..85e95f0 --- /dev/null +++ b/lib/crtdll/math/cosh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double cosh(double x) +{ + const double ebig = exp(fabs(x)); + return (ebig + 1.0/ebig) / 2.0; +} diff --git a/lib/crtdll/math/exp.c b/lib/crtdll/math/exp.c new file mode 100644 index 0000000..71df0e0 --- /dev/null +++ b/lib/crtdll/math/exp.c @@ -0,0 +1,42 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double exp (double __x); + +double exp (double __x) +{ + register double __value, __exponent; + __asm __volatile__ + ("fldl2e # e^x = 2^(x * log2(e))\n\t" + "fmul %%st(1) # x * log2(e)\n\t" + "fst %%st(1)\n\t" + "frndint # int(x * log2(e))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x * log2(e))\n\t" + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__x)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} diff --git a/lib/crtdll/math/fabs.c b/lib/crtdll/math/fabs.c new file mode 100644 index 0000000..a2a8bdc --- /dev/null +++ b/lib/crtdll/math/fabs.c @@ -0,0 +1,32 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double fabs (double __x); + +double fabs (double __x) +{ + register double __value; + __asm __volatile__ + ("fabs" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/floor.c b/lib/crtdll/math/floor.c new file mode 100644 index 0000000..7403a52 --- /dev/null +++ b/lib/crtdll/math/floor.c @@ -0,0 +1,50 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double floor (double __x); + +double floor (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + +typedef struct IEEExp { + unsigned manl:32; + unsigned manh:32; + unsigned exp:15; + unsigned sign:1; + } long_double_t; + +long double floorl(long double x ) +{ + + return (long double)(long long int)x; +} + diff --git a/lib/crtdll/math/fmod.c b/lib/crtdll/math/fmod.c new file mode 100644 index 0000000..5618cf3 --- /dev/null +++ b/lib/crtdll/math/fmod.c @@ -0,0 +1,35 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double fmod (double __x, double __y); + +double fmod (double __x, double __y) +{ + register double __value; + __asm __volatile__ + ("1: fprem\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b" + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); + + return __value; +} diff --git a/lib/crtdll/math/frexp.c b/lib/crtdll/math/frexp.c new file mode 100644 index 0000000..8b3390d --- /dev/null +++ b/lib/crtdll/math/frexp.c @@ -0,0 +1,20 @@ +#include +#include +#include + +double +frexp(double __x, int *exptr) +{ + double_t *x = (double_t *)&__x; + + if ( exptr != NULL ) + *exptr = x->exponent - 0x3FE; + + + x->exponent = 0x3FE; + + return __x; +} + + + diff --git a/lib/crtdll/math/ftol.c b/lib/crtdll/math/ftol.c new file mode 100644 index 0000000..b20aef4 --- /dev/null +++ b/lib/crtdll/math/ftol.c @@ -0,0 +1,5 @@ +#include + +long _ftol(double fl) { + return (long)fl; +} diff --git a/lib/crtdll/math/huge_val.c b/lib/crtdll/math/huge_val.c new file mode 100644 index 0000000..91eefa0 --- /dev/null +++ b/lib/crtdll/math/huge_val.c @@ -0,0 +1,7 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +#undef _HUGE +double_t _HUGE = { 0x00000, 0x00000, 0x7ff, 0x0 }; +double *_HUGE_dll = (double *)&_HUGE; diff --git a/lib/crtdll/math/hypot.c b/lib/crtdll/math/hypot.c new file mode 100644 index 0000000..08e3492 --- /dev/null +++ b/lib/crtdll/math/hypot.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * hypot() function for DJGPP. + * + * hypot() computes sqrt(x^2 + y^2). The problem with the obvious + * naive implementation is that it might fail for very large or + * very small arguments. For instance, for large x or y the result + * might overflow even if the value of the function should not, + * because squaring a large number might trigger an overflow. For + * very small numbers, their square might underflow and will be + * silently replaced by zero; this won't cause an exception, but might + * have an adverse effect on the accuracy of the result. + * + * This implementation tries to avoid the above pitfals, without + * inflicting too much of a performance hit. + * + */ + +#include +#include +#include + +/* Approximate square roots of DBL_MAX and DBL_MIN. Numbers + between these two shouldn't neither overflow nor underflow + when squared. */ +#define __SQRT_DBL_MAX 1.3e+154 +#define __SQRT_DBL_MIN 2.3e-162 + +double +_hypot(double x, double y) +{ + double abig = fabs(x), asmall = fabs(y); + double ratio; + + /* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */ + if (abig < asmall) + { + double temp = abig; + + abig = asmall; + asmall = temp; + } + + /* Trivial case. */ + if (asmall == 0.) + return abig; + + /* Scale the numbers as much as possible by using its ratio. + For example, if both ABIG and ASMALL are VERY small, then + X^2 + Y^2 might be VERY inaccurate due to loss of + significant digits. Dividing ASMALL by ABIG scales them + to a certain degree, so that accuracy is better. */ + + if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX) + return abig * sqrt(1.0 + ratio*ratio); + else + { + /* Slower but safer algorithm due to Moler and Morrison. Never + produces any intermediate result greater than roughly the + larger of X and Y. Should converge to machine-precision + accuracy in 3 iterations. */ + + double r = ratio*ratio, t, s, p = abig, q = asmall; + + do { + t = 4. + r; + if (t == 4.) + break; + s = r / t; + p += 2. * s * p; + q *= s; + r = (q / p) * (q / p); + } while (1); + + return p; + } +} + +#ifdef TEST + +#include + +int +main(void) +{ + printf("hypot(3, 4) =\t\t\t %25.17e\n", _hypot(3., 4.)); + printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", _hypot(3.e+150, 4.e+150)); + printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", _hypot(3.e+306, 4.e+306)); + printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n",_hypot(3.e-320, 4.e-320)); + printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n",_hypot(0.7*DBL_MAX, 0.7*DBL_MAX)); + printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", _hypot(DBL_MAX, 1.0)); + printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", _hypot(1.0, DBL_MAX)); + printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", _hypot(0.0, DBL_MAX)); + + return 0; +} + +#endif diff --git a/lib/crtdll/math/j0_y0.c b/lib/crtdll/math/j0_y0.c new file mode 100644 index 0000000..7512077 --- /dev/null +++ b/lib/crtdll/math/j0_y0.c @@ -0,0 +1,11 @@ +#include + +double _j0(double x) +{ + return x; +} + +double _y0(double x) +{ + return x; +} diff --git a/lib/crtdll/math/j1_y1.c b/lib/crtdll/math/j1_y1.c new file mode 100644 index 0000000..90e2fb1 --- /dev/null +++ b/lib/crtdll/math/j1_y1.c @@ -0,0 +1,11 @@ +#include + +double _j1(double x) +{ + return x; +} + +double _y1(double x) +{ + return x; +} diff --git a/lib/crtdll/math/jn_yn.c b/lib/crtdll/math/jn_yn.c new file mode 100644 index 0000000..b641a81 --- /dev/null +++ b/lib/crtdll/math/jn_yn.c @@ -0,0 +1,11 @@ +#include + +double _jn(int n, double x) +{ + return x; +} + +double _yn(int n, double x) +{ + return x; +} diff --git a/lib/crtdll/math/ldexp.c b/lib/crtdll/math/ldexp.c new file mode 100644 index 0000000..4599fd5 --- /dev/null +++ b/lib/crtdll/math/ldexp.c @@ -0,0 +1,31 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +double ldexp (double __x, int __y); + +double ldexp (double __x, int __y) +{ + register double __value; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__x), "u" ((double) __y)); + + return __value; +} diff --git a/lib/crtdll/math/log.c b/lib/crtdll/math/log.c new file mode 100644 index 0000000..c19c30f --- /dev/null +++ b/lib/crtdll/math/log.c @@ -0,0 +1,33 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +double log (double __x); + +double log (double __x) +{ + register double __value; + __asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/log10.c b/lib/crtdll/math/log10.c new file mode 100644 index 0000000..b57b1a5 --- /dev/null +++ b/lib/crtdll/math/log10.c @@ -0,0 +1,34 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double log10 (double __x); + +double log10 (double __x) +{ + register double __value; + __asm __volatile__ + ("fldlg2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/modf.c b/lib/crtdll/math/modf.c new file mode 100644 index 0000000..6864e52 --- /dev/null +++ b/lib/crtdll/math/modf.c @@ -0,0 +1,141 @@ +/* @(#)s_modf.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +#include +#include + + + +//static const double one = 1.0; + +double modf(double __x, double *__i) +{ + + double_t * x = (double_t *)&__x; + double_t * iptr = ( double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3ff; /* exponent of x */ + if(j0<20) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0; + iptr->sign = x->sign; + return __x; + } else { + + if ( x->mantissah == 0 && x->mantissal == 0 ) { + *__i = __x; + return 0.0; + } + + i = (0x000fffff)>>j0; + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&(~i); + iptr->mantissal = 0; + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } + } else if (j0>51) { /* no fraction part */ + *__i = __x; + if ( _isnan(__x) || _isinf(__x) ) + return __x; + + + __x = 0.0; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + + i = ((unsigned)(0xffffffff))>>(j0-20); + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } +} + + +long double modfl(long double __x, long double *__i) +{ + + + long_double_t * x = (long_double_t *)&__x; + long_double_t * iptr = (long_double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3fff; /* exponent of x */ + + + if(j0<32) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0L; + iptr->sign = x->sign; + return __x; + } else { + + i = ((unsigned int)(0xffffffff))>>(j0+1); + if ( x->mantissal == 0 && (x->mantissal & i) == 0 ) { + *__i = __x; + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&((~i)); + iptr->mantissal = 0; + + + return __x - *__i; + } + } else if (j0>63) { /* no fraction part */ + *__i = __x; + if ( _isnanl(__x) || _isinfl(__x) ) + return __x; + + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + i = ((unsigned int)(0xffffffff))>>(j0-32); + if ( x->mantissal == 0 ) { + *__i = __x; + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + + return __x - *__i; + + + } +} diff --git a/lib/crtdll/math/pow.c b/lib/crtdll/math/pow.c new file mode 100644 index 0000000..37810ac --- /dev/null +++ b/lib/crtdll/math/pow.c @@ -0,0 +1,85 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +double pow (double __x, double __y); + +double __log2 (double __x); + +double __log2 (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double pow (double __x, double __y) +{ + register double __value, __exponent; + long __p = (long) __y; + + if (__x == 0.0 && __y > 0.0) + return 0.0; + if (__y == (double) __p) + { + double __r = 1.0; + if (__p == 0) + return 1.0; + if (__p < 0) + { + __p = -__p; + __x = 1.0 / __x; + } + while (1) + { + if (__p & 1) + __r *= __x; + __p >>= 1; + if (__p == 0) + return __r; + __x *= __x; + } + /* NOTREACHED */ + } + __asm __volatile__ + ("fmul %%st(1) # y * log2(x)\n\t" + "fst %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +long double powl (long double __x,long double __y) +{ + return pow(__x,__y/2)*pow(__x,__y/2); +} + diff --git a/lib/crtdll/math/sin.c b/lib/crtdll/math/sin.c new file mode 100644 index 0000000..80d7630 --- /dev/null +++ b/lib/crtdll/math/sin.c @@ -0,0 +1,32 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double sin (double __x); + +double sin (double __x) +{ + register double __value; + __asm __volatile__ + ("fsin" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/sinh.c b/lib/crtdll/math/sinh.c new file mode 100644 index 0000000..7acb21f --- /dev/null +++ b/lib/crtdll/math/sinh.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double sinh(double x) +{ + if(x >= 0.0) + { + const double epos = exp(x); + return (epos - 1.0/epos) / 2.0; + } + else + { + const double eneg = exp(-x); + return (1.0/eneg - eneg) / 2.0; + } +} diff --git a/lib/crtdll/math/sqrt.c b/lib/crtdll/math/sqrt.c new file mode 100644 index 0000000..a17cec1 --- /dev/null +++ b/lib/crtdll/math/sqrt.c @@ -0,0 +1,32 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double sqrt (double __x); + +double sqrt (double __x) +{ + register double __value; + __asm __volatile__ + ("fsqrt" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/stubs.c b/lib/crtdll/math/stubs.c new file mode 100644 index 0000000..65b6010 --- /dev/null +++ b/lib/crtdll/math/stubs.c @@ -0,0 +1,84 @@ +#include + +double _CIsin (double x); +double _CIcos (double x); +double _CItan (double x); +double _CIsinh (double x); +double _CIcosh (double x); +double _CItanh (double x); +double _CIasin (double x); +double _CIacos (double x); +double _CIatan (double x); +double _CIatan2 (double y, double x); +double _CIexp (double x); +double _CIlog (double x); +double _CIlog10 (double x); +double _CIpow (double x, double y); +double _CIsqrt (double x); +double _CIfmod (double x, double y); + + +double _CIsin (double x) +{ + return sin(x); +} +double _CIcos (double x) +{ + return cos(x); +} +double _CItan (double x) +{ + return tan(x); +} +double _CIsinh (double x) +{ + return sinh(x); +} +double _CIcosh (double x) +{ + return cosh(x); +} +double _CItanh (double x) +{ + return tanh(x); +} +double _CIasin (double x) +{ + return asin(x); +} +double _CIacos (double x) +{ + return acos(x); +} +double _CIatan (double x) +{ + return atan(x); +} +double _CIatan2 (double y, double x) +{ + return atan2(y,x); +} +double _CIexp (double x) +{ + return exp(x); +} +double _CIlog (double x) +{ + return log(x); +} +double _CIlog10 (double x) +{ + return log10(x); +} +double _CIpow (double x, double y) +{ + return pow(x,y); +} +double _CIsqrt (double x) +{ + return sqrt(x); +} +double _CIfmod (double x, double y) +{ + return fmod(x,y); +} diff --git a/lib/crtdll/math/tan.c b/lib/crtdll/math/tan.c new file mode 100644 index 0000000..2a460a9 --- /dev/null +++ b/lib/crtdll/math/tan.c @@ -0,0 +1,33 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double tan (double __x); + +double tan (double __x) +{ + register double __value; + register double __value2 __attribute__ ((unused)); + __asm __volatile__ + ("fptan" + : "=t" (__value2), "=u" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/crtdll/math/tanh.c b/lib/crtdll/math/tanh.c new file mode 100644 index 0000000..12b0012 --- /dev/null +++ b/lib/crtdll/math/tanh.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double tanh(double x) +{ + if (x > 50) + return 1; + else if (x < -50) + return -1; + else + { + const double ebig = exp(x); + const double esmall = 1.0/ebig; + return (ebig - esmall) / (ebig + esmall); + } +} + diff --git a/lib/crtdll/mbstring/.cvsignore b/lib/crtdll/mbstring/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/mbstring/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/mbstring/hanzen.c b/lib/crtdll/mbstring/hanzen.c new file mode 100644 index 0000000..23df35a --- /dev/null +++ b/lib/crtdll/mbstring/hanzen.c @@ -0,0 +1,101 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Multibyte conversion routines formerly called hantozen and zentohan + * PROGRAMER: Boudewijn Dekker, Taiji Yamada + * UPDATE HISTORY: + Modified from Taiji Yamada japanese code system utilities + * 12/04/99: Created + */ + +#include + +static unsigned short han_to_zen_ascii_table[0x5f] = { + 0x8140, 0x8149, 0x8168, 0x8194, 0x8190, 0x8193, 0x8195, 0x8166, + 0x8169, 0x816a, 0x8196, 0x817b, 0x8143, 0x817c, 0x8144, 0x815e, + 0x824f, 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256, + 0x8257, 0x8258, 0x8146, 0x8147, 0x8183, 0x8181, 0x8184, 0x8148, + 0x8197, 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, 0x8265, 0x8266, + 0x8267, 0x8268, 0x8269, 0x826a, 0x826b, 0x826c, 0x826d, 0x826e, + 0x826f, 0x8270, 0x8271, 0x8272, 0x8273, 0x8274, 0x8275, 0x8276, + 0x8277, 0x8278, 0x8279, 0x816d, 0x818f, 0x816e, 0x814f, 0x8151, + 0x8165, 0x8281, 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287, + 0x8288, 0x8289, 0x828a, 0x828b, 0x828c, 0x828d, 0x828e, 0x828f, + 0x8290, 0x8291, 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297, + 0x8298, 0x8299, 0x829a, 0x816f, 0x8162, 0x8170, 0x8150 +}; +static unsigned short han_to_zen_kana_table[0x40] = { + 0x8140, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x8392, 0x8340, + 0x8342, 0x8344, 0x8346, 0x8348, 0x8383, 0x8385, 0x8387, 0x8362, + 0x815b, 0x8341, 0x8343, 0x8345, 0x8347, 0x8349, 0x834a, 0x834c, + 0x834e, 0x8350, 0x8352, 0x8354, 0x8356, 0x8358, 0x835a, 0x835c, + 0x835e, 0x8360, 0x8363, 0x8365, 0x8367, 0x8369, 0x836a, 0x836b, + 0x836c, 0x836d, 0x836e, 0x8371, 0x8374, 0x8377, 0x837a, 0x837d, + 0x837e, 0x8380, 0x8381, 0x8382, 0x8384, 0x8386, 0x8388, 0x8389, + 0x838a, 0x838b, 0x838c, 0x838d, 0x838f, 0x8393, 0x814a, 0x814b +}; +static unsigned char zen_to_han_kana_table[0x8396-0x8340+1] = { + 0xa7, 0xb1, 0xa8, 0xb2, 0xa9, 0xb3, 0xaa, 0xb4, + 0xab, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, + 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, + 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0xc0, 0xc0, + 0xc1, 0xc1, 0xaf, 0xc2, 0xc2, 0xc3, 0xc3, 0xc4, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xca, + 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, + 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xcf, 0xd0, 0, + 0xd1, 0xd2, 0xd3, 0xac, 0xd4, 0xad, 0xd5, 0xae, + 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdc, + 0xb2, 0xb4, 0xa6, 0xdd, 0xb3, 0xb6, 0xb9 +}; +#define ZTOH_SYMBOLS 9 +static unsigned short zen_to_han_symbol_table_1[ZTOH_SYMBOLS] = { + 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x815b, 0x814a, 0x814b +}; +static unsigned char zen_to_han_symbol_table_2[ZTOH_SYMBOLS] = { + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xb0, 0xde, 0xdf +}; +#define ISKANA(c) ((c) >= 0xa1 && (c) <= 0xdf) +#define JISHIRA(c) ((c) >= 0x829f && (c) <= 0x82f1) +#define JISKANA(c) ((c) >= 0x8340 && (c) <= 0x8396 && (c) != 0x837f) +#define JTOKANA(c) ((c) <= 0x82dd ? (c) + 0xa1 : (c) + 0xa2) + + +unsigned short _mbbtombc(unsigned short c) +{ + if (c >= 0x20 && c <= 0x7e) { + return han_to_zen_ascii_table[c - 0x20]; + } else if (ISKANA(c)) { + return han_to_zen_kana_table[c - 0xa0]; + } + return c; +} + + +unsigned short _mbctombb(unsigned short c) +{ + int i; + unsigned short *p; + + if (JISKANA(c)) { + return zen_to_han_kana_table[c - 0x8340]; + } else if (JISHIRA(c)) { + c = JTOKANA(c); + return zen_to_han_kana_table[c - 0x8340]; + } else if (c <= 0x8396) { + for (i = 0x20, p = han_to_zen_ascii_table; i <= 0x7e; i++, p++) { + if (*p == c) { + return i; + } + } + for (i = 0; i < ZTOH_SYMBOLS; i++) { + if (zen_to_han_symbol_table_1[i] == c) { + return zen_to_han_symbol_table_2[i]; + } + } + } + return c; +} + + + diff --git a/lib/crtdll/mbstring/ischira.c b/lib/crtdll/mbstring/ischira.c new file mode 100644 index 0000000..87a2236 --- /dev/null +++ b/lib/crtdll/mbstring/ischira.c @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/ischira.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +int _ismbchira( unsigned int c ) +{ + return ((c>=0x829F) && (c<=0x82F1)); +} + +int _ismbckata( unsigned int c ) +{ + return ((c>=0x8340) && (c<=0x8396)); +} + +unsigned int _mbctohira( unsigned int c ) +{ + return c; +} + +unsigned int _mbctokata( unsigned int c ) +{ + return c; +} + diff --git a/lib/crtdll/mbstring/iskana.c b/lib/crtdll/mbstring/iskana.c new file mode 100644 index 0000000..b61ff8b --- /dev/null +++ b/lib/crtdll/mbstring/iskana.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Checks for kana character + * PROGRAMER: Boudewijn Dekker, Taiji Yamada + * UPDATE HISTORY: + Modified from Taiji Yamada japanese code system utilities + * 12/04/99: Created + */ +#include +#include + +int _ismbbkana(unsigned char c) +{ + return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_M|_KNJ_P)); +} diff --git a/lib/crtdll/mbstring/iskmoji.c b/lib/crtdll/mbstring/iskmoji.c new file mode 100644 index 0000000..3884552 --- /dev/null +++ b/lib/crtdll/mbstring/iskmoji.c @@ -0,0 +1,6 @@ +#include + +int _ismbbkalpha(unsigned char c) +{ + return (0xA7 <= c <= 0xDF); +} diff --git a/lib/crtdll/mbstring/iskpun.c b/lib/crtdll/mbstring/iskpun.c new file mode 100644 index 0000000..e515354 --- /dev/null +++ b/lib/crtdll/mbstring/iskpun.c @@ -0,0 +1,15 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/iskpun.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include + +int _ismbbkpunct( unsigned int c ) +{ + return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_P)); +} diff --git a/lib/crtdll/mbstring/islead.c b/lib/crtdll/mbstring/islead.c new file mode 100644 index 0000000..6026c34 --- /dev/null +++ b/lib/crtdll/mbstring/islead.c @@ -0,0 +1,8 @@ +#include +#include + +int isleadbyte(char *mbstr) +{ + return 0; + //return IsDBCSLeadByteEx(0,*c); +} diff --git a/lib/crtdll/mbstring/islwr.c b/lib/crtdll/mbstring/islwr.c new file mode 100644 index 0000000..f64eade --- /dev/null +++ b/lib/crtdll/mbstring/islwr.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +// code page 952 only +int _ismbclower( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + if ( c >= 0x829A && c<= 0x829A ) + return 1; + } + + return islower(c); +} diff --git a/lib/crtdll/mbstring/ismbal.c b/lib/crtdll/mbstring/ismbal.c new file mode 100644 index 0000000..d62d5d1 --- /dev/null +++ b/lib/crtdll/mbstring/ismbal.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Checks for alphabetic multibyte character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include + +int _ismbbkalnum( unsigned int c ); + +int _ismbbalpha(unsigned char c) +{ + return (isalpha(c) ||_ismbbkalnum(c)); +} + diff --git a/lib/crtdll/mbstring/ismbaln.c b/lib/crtdll/mbstring/ismbaln.c new file mode 100644 index 0000000..2c85873 --- /dev/null +++ b/lib/crtdll/mbstring/ismbaln.c @@ -0,0 +1,10 @@ +#include +#include + +int _ismbbkalnum( unsigned int c ); + +int _ismbbalnum(unsigned char c) +{ + return (isalnum(c) || _ismbbkalnum(c)); +} + diff --git a/lib/crtdll/mbstring/ismbc.c b/lib/crtdll/mbstring/ismbc.c new file mode 100644 index 0000000..ad8c8c6 --- /dev/null +++ b/lib/crtdll/mbstring/ismbc.c @@ -0,0 +1,106 @@ +#include + +int _ismbbalpha(unsigned char c); +int _ismbbalnum(unsigned char c); + +int _ismbcalnum( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return _ismbbalnum(c); + + return 0; +} + +int _ismbcalpha( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return _ismbbalpha(c); + + return 0; +} + +int _ismbcdigit( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} + +int _ismbcprint( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} + +int _ismbcsymbol( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} + +int _ismbcspace( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} +int _ismbclegal(unsigned int c) +{ + if ((c & 0xFF00) != 0) { + return _ismbblead(c>>8) && _ismbbtrail(c&0xFF); + } + else + return _ismbbtrail(c&0xFF); + + return 0; + +} + +int _ismbcl0(unsigned int c) +{ + return 0; +} + +int _ismbcl1(unsigned int c) +{ + return 0; +} + +int _ismbcl2(unsigned int c) +{ + return 0; +} diff --git a/lib/crtdll/mbstring/ismbgra.c b/lib/crtdll/mbstring/ismbgra.c new file mode 100644 index 0000000..6b3469f --- /dev/null +++ b/lib/crtdll/mbstring/ismbgra.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int _ismbbgraph(unsigned char c) +{ + return (isgraph(c) || _ismbbkana(c)); +} diff --git a/lib/crtdll/mbstring/ismbkaln.c b/lib/crtdll/mbstring/ismbkaln.c new file mode 100644 index 0000000..64340ab --- /dev/null +++ b/lib/crtdll/mbstring/ismbkaln.c @@ -0,0 +1,16 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/iskpun.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include + +int _ismbbkalnum( unsigned int c ) +{ + return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_P)); +} diff --git a/lib/crtdll/mbstring/ismblead.c b/lib/crtdll/mbstring/ismblead.c new file mode 100644 index 0000000..9282210 --- /dev/null +++ b/lib/crtdll/mbstring/ismblead.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/ismblead.c + * PURPOSE: Checks for a lead byte + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * Modified from Taiji Yamada japanese code system utilities + * 12/04/99: Created + */ + +#include +#include +#include + +size_t _mbclen2(const unsigned int s); + +char _jctype[257] = { +/*-1*/ ___, +/*0x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*1x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*2x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*3x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*4x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, +/*5x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, +/*6x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, +/*7x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,___, +/*8x*/ __2,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, +/*9x*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, +/*Ax*/ __2,_P2,_P2,_P2,_P2,_P2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Bx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Cx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Dx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Ex*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, +/*Fx*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,___,___,___ +}; + +char *_mbctype = _jctype; +int _ismbblead(unsigned int c) +{ + return ((_jctype+1)[(unsigned char)(c)] & _KNJ_1); +} +//int _ismbblead(unsigned int byte) +//{ +// +// return (int)IsDBCSLeadByte(byte) +//} + +int _ismbslead( const unsigned char *str, const unsigned char *t) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && s != t) + { + + s+= _mbclen2(*s); + } + return _ismbblead( *s); +} + diff --git a/lib/crtdll/mbstring/ismbpri.c b/lib/crtdll/mbstring/ismbpri.c new file mode 100644 index 0000000..76d4075 --- /dev/null +++ b/lib/crtdll/mbstring/ismbpri.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int _ismbbprint(unsigned char c) +{ + return (isprint(c) || _ismbbkana(c)); +} diff --git a/lib/crtdll/mbstring/ismbpun.c b/lib/crtdll/mbstring/ismbpun.c new file mode 100644 index 0000000..eb418e4 --- /dev/null +++ b/lib/crtdll/mbstring/ismbpun.c @@ -0,0 +1,14 @@ + + //iskana() :(0xA1 <= c <= 0xDF) + //iskpun() :(0xA1 <= c <= 0xA6) + //iskmoji() :(0xA7 <= c <= 0xDF) +#include +#include +#include + +int _ismbbpunct(unsigned char c) +{ +// (0xA1 <= c <= 0xA6) + return (ispunct(c) || _ismbbkana(c)); +} + diff --git a/lib/crtdll/mbstring/ismbtrl.c b/lib/crtdll/mbstring/ismbtrl.c new file mode 100644 index 0000000..f6d7b40 --- /dev/null +++ b/lib/crtdll/mbstring/ismbtrl.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/ismbtrail.c + * PURPOSE: Checks for a trailing byte + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +size_t _mbclen2(const unsigned int s); + +// iskanji2() : (0x40 <= c <= 0x7E 0x80 <= c <= 0xFC) + +int _ismbbtrail(unsigned int c) +{ + return ((_jctype+1)[(unsigned char)(c)] & _KNJ_2); +} + +//int _ismbbtrail( unsigned int b) +//{ +// return ((b >= 0x40 && b <= 0x7e ) || (b >= 0x80 && b <= 0xfc ) ); +//} + + +int _ismbstrail( const unsigned char *str, const unsigned char *t) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && s != t) + { + + s+= _mbclen2(*s); + } + + return _ismbbtrail(*s); +} diff --git a/lib/crtdll/mbstring/isuppr.c b/lib/crtdll/mbstring/isuppr.c new file mode 100644 index 0000000..05afc64 --- /dev/null +++ b/lib/crtdll/mbstring/isuppr.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +// code page 952 only +int _ismbcupper( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + if ( c >= 0x8260 && c<= 0x8279 ) + return 1; + } + + return isupper(c); +} diff --git a/lib/crtdll/mbstring/jistojms.c b/lib/crtdll/mbstring/jistojms.c new file mode 100644 index 0000000..a34e311 --- /dev/null +++ b/lib/crtdll/mbstring/jistojms.c @@ -0,0 +1,24 @@ +#include + +unsigned short _mbcjistojms(unsigned short c) +{ + int c1, c2; + + c2 = (unsigned char)c; + c1 = c >> 8; + if (c1 >= 0x21 && c1 <= 0x7e && c2 >= 0x21 && c2 <= 0x7e) { + if (c1 & 0x01) { + c2 += 0x1f; + if (c2 >= 0x7f) + c2 ++; + } else { + c2 += 0x7e; + } + c1 += 0xe1; + c1 >>= 1; + if (c1 >= 0xa0) + c1 += 0x40; + return ((c1 << 8) | c2); + } + return 0; +} diff --git a/lib/crtdll/mbstring/jmstojis.c b/lib/crtdll/mbstring/jmstojis.c new file mode 100644 index 0000000..f3496aa --- /dev/null +++ b/lib/crtdll/mbstring/jmstojis.c @@ -0,0 +1,25 @@ +#include + +unsigned short _mbcjmstojis(unsigned short c) +{ + int c1, c2; + + c2 = (unsigned char)c; + c1 = c >> 8; + if (c1 < 0xf0 && _ismbblead(c1) && _ismbbtrail(c2)) { + if (c1 >= 0xe0) + c1 -= 0x40; + c1 -= 0x70; + c1 <<= 1; + if (c2 < 0x9f) { + c1 --; + c2 -= 0x1f; + if (c2 >= (0x80-0x1f)) + c2 --; + } else { + c2 -= 0x7e; + } + return ((c1 << 8) | c2); + } + return 0; +} diff --git a/lib/crtdll/mbstring/mbbtype.c b/lib/crtdll/mbstring/mbbtype.c new file mode 100644 index 0000000..06d6de8 --- /dev/null +++ b/lib/crtdll/mbstring/mbbtype.c @@ -0,0 +1,51 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbbtype.c + * PURPOSE: Determines the type of a multibyte character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +int _mbbtype(unsigned char c , int type) +{ + if ( type == 1 ) { + if ((c >= 0x40 && c <= 0x7e ) || (c >= 0x80 && c <= 0xfc ) ) + { + return _MBC_TRAIL; + } + else if (( c >= 0x20 && c >= 0x7E ) || ( c >= 0xA1 && c <= 0xDF ) || + ( c >= 0x81 && c <= 0x9F ) || ( c >= 0xE0 && c <= 0xFC ) ) + return _MBC_ILLEGAL; + else + return 0; + + } + else { + if (( c >= 0x20 && c <= 0x7E ) || ( c >= 0xA1 && c <= 0xDF )) { + return _MBC_SINGLE; + } + else if ( (c >= 0x81 && c <= 0x9F ) || ( c >= 0xE0 && c <= 0xFC) ) + return _MBC_LEAD; + else if (( c >= 0x20 && c >= 0x7E ) || ( c >= 0xA1 && c <= 0xDF ) || + ( c >= 0x81 && c <= 0x9F ) || ( c >= 0xE0 && c <= 0xFC ) ) + return _MBC_ILLEGAL; + else + return 0; + + } + + + return 0; +} + +int _mbsbtype( const unsigned char *str, size_t n ) +{ + if ( str == NULL ) + return -1; + return _mbbtype(*(str+n),1); +} diff --git a/lib/crtdll/mbstring/mbccpy.c b/lib/crtdll/mbstring/mbccpy.c new file mode 100644 index 0000000..d78af8d --- /dev/null +++ b/lib/crtdll/mbstring/mbccpy.c @@ -0,0 +1,12 @@ +#include +#include + +size_t _mbclen2(const unsigned int s); + +void _mbccpy(unsigned char *dst, const unsigned char *src) +{ + if (!_ismbblead(*src) ) + return; + + memcpy(dst,src,_mbclen2(*src)); +} diff --git a/lib/crtdll/mbstring/mbclen.c b/lib/crtdll/mbstring/mbclen.c new file mode 100644 index 0000000..c579932 --- /dev/null +++ b/lib/crtdll/mbstring/mbclen.c @@ -0,0 +1,27 @@ +#include + +#include + + +size_t _mbclen(const unsigned char *s) +{ + return (_ismbblead(*s>>8) && _ismbbtrail(*s&0x00FF)) ? 2 : 1; +} + +size_t _mbclen2(const unsigned int s) +{ + return (_ismbblead(s>>8) && _ismbbtrail(s&0x00FF)) ? 2 : 1; +} + +// assume MB_CUR_MAX == 2 +int mblen( const char *s, size_t count ) +{ + size_t l; + if ( s == NULL ) + return 0; + + l = _mbclen(s); + if ( l < count ) + return -1; + return l; +} diff --git a/lib/crtdll/mbstring/mbscat.c b/lib/crtdll/mbstring/mbscat.c new file mode 100644 index 0000000..62b3d05 --- /dev/null +++ b/lib/crtdll/mbstring/mbscat.c @@ -0,0 +1,6 @@ +#include + +unsigned char * _mbscat(unsigned char *dst, const unsigned char *src) +{ + return strcat(dst,src); +} diff --git a/lib/crtdll/mbstring/mbschr.c b/lib/crtdll/mbstring/mbschr.c new file mode 100644 index 0000000..f9be9c8 --- /dev/null +++ b/lib/crtdll/mbstring/mbschr.c @@ -0,0 +1,6 @@ +#include + +unsigned char * _mbschr(const unsigned char *str, unsigned int c) +{ + return strchr(str,c); +} diff --git a/lib/crtdll/mbstring/mbscmp.c b/lib/crtdll/mbstring/mbscmp.c new file mode 100644 index 0000000..ad48d16 --- /dev/null +++ b/lib/crtdll/mbstring/mbscmp.c @@ -0,0 +1,7 @@ +#include +#include + +int _mbscmp(const unsigned char *str1, const unsigned char *str2) +{ + return strcmp(str1,str2); +} diff --git a/lib/crtdll/mbstring/mbscoll.c b/lib/crtdll/mbstring/mbscoll.c new file mode 100644 index 0000000..d3236cd --- /dev/null +++ b/lib/crtdll/mbstring/mbscoll.c @@ -0,0 +1,95 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbscoll.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +int colldif(unsigned short c1, unsigned short c2); + +int _mbscoll(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + while ( *s1 != 0 ) { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + + } + } + else + return colldif(*s1, *s2); + } ; + return 0; +} + +int _mbsbcoll(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + + while ( *s1 != 0 ) { + + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + } + } + else + return colldif(*s1, *s2); + } ; + return 0; +} diff --git a/lib/crtdll/mbstring/mbscpy.c b/lib/crtdll/mbstring/mbscpy.c new file mode 100644 index 0000000..1c66e61 --- /dev/null +++ b/lib/crtdll/mbstring/mbscpy.c @@ -0,0 +1,7 @@ +#include +#include + +unsigned char * _mbscpy(unsigned char *dst, const unsigned char *str) +{ + return strcpy(dst,str); +} diff --git a/lib/crtdll/mbstring/mbscspn.c b/lib/crtdll/mbstring/mbscspn.c new file mode 100644 index 0000000..055adce --- /dev/null +++ b/lib/crtdll/mbstring/mbscspn.c @@ -0,0 +1,18 @@ +#include +// not correct +size_t _mbscspn(const unsigned char *s1, const unsigned char *s2) +{ + const char *p, *spanp; + char c, sc; + + for (p = s1;;) + { + c = *p++; + spanp = s2; + do { + if ((sc = *spanp++) == c) + return (size_t)(p - 1) - (size_t)s1; + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/crtdll/mbstring/mbsdec.c b/lib/crtdll/mbstring/mbsdec.c new file mode 100644 index 0000000..00b58f3 --- /dev/null +++ b/lib/crtdll/mbstring/mbsdec.c @@ -0,0 +1,14 @@ +#include + +unsigned char * _mbsdec(const unsigned char *str, const unsigned char *cur) +{ + unsigned char *s = (unsigned char *)cur; + if ( str >= cur ) + return NULL; + + s--; + if (_ismbblead(*(s-1)) ) + s--; + + return s; +} diff --git a/lib/crtdll/mbstring/mbsdup.c b/lib/crtdll/mbstring/mbsdup.c new file mode 100644 index 0000000..ac50252 --- /dev/null +++ b/lib/crtdll/mbstring/mbsdup.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Duplicates a multi byte string + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + Modified from DJGPP strdup + * 12/04/99: Created + */ + +#include +#include + +unsigned char * _mbsdup(const unsigned char *_s) +{ + char *rv; + if (_s == 0) + return 0; + rv = (char *)malloc(_mbslen(_s) + 1); + if (rv == 0) + return 0; + _mbscpy(rv, _s); + return rv; +} diff --git a/lib/crtdll/mbstring/mbsicmp.c b/lib/crtdll/mbstring/mbsicmp.c new file mode 100644 index 0000000..f8103c5 --- /dev/null +++ b/lib/crtdll/mbstring/mbsicmp.c @@ -0,0 +1,62 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsicmp.c + * PURPOSE: Duplicates a multi byte string + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include +#include + +int _mbsicmp(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (toupper(*s1) != toupper(*s2)) + return toupper(*s1) - toupper(*s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( _mbctoupper(*short_s1) != _mbctoupper(*short_s2 )) + return _mbctoupper(*short_s1) - _mbctoupper(*short_s2); + else { + s1 += 2; + s2 += 2; + } + } + else + return *s1 - *s2; + } while (*s1 != 0); + return 0; + + while (toupper(*s1) == toupper(*s2)) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); +} diff --git a/lib/crtdll/mbstring/mbsicoll.c b/lib/crtdll/mbstring/mbsicoll.c new file mode 100644 index 0000000..6b2da15 --- /dev/null +++ b/lib/crtdll/mbstring/mbsicoll.c @@ -0,0 +1,54 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/iskpun.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include +#include +int colldif(unsigned short c1, unsigned short c2); +int _mbsicoll(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + while ( *s1 != 0 ) { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (toupper(*s1) != toupper(*s2)) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( _mbctoupper(*short_s1) != _mbctoupper(*short_s2 )) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + + } + } + else + return colldif(*s1, *s2); + } ; + return 0; +} diff --git a/lib/crtdll/mbstring/mbsinc.c b/lib/crtdll/mbstring/mbsinc.c new file mode 100644 index 0000000..d062006 --- /dev/null +++ b/lib/crtdll/mbstring/mbsinc.c @@ -0,0 +1,10 @@ +#include + +unsigned char * _mbsinc(const unsigned char *s) +{ + unsigned char *c = (unsigned char *)s; + if (_ismbblead(*s) ) + c++; + c++; + return c; +} diff --git a/lib/crtdll/mbstring/mbslen.c b/lib/crtdll/mbstring/mbslen.c new file mode 100644 index 0000000..3eca134 --- /dev/null +++ b/lib/crtdll/mbstring/mbslen.c @@ -0,0 +1,15 @@ +#include + +size_t _mbclen2(const unsigned int s); + +size_t _mbslen(const unsigned char *str) +{ + int i = 0; + unsigned char *s; + + if (str == 0) + return 0; + + for (s = (unsigned char *)str; *s; s+=_mbclen2(*s),i++); + return i; +} diff --git a/lib/crtdll/mbstring/mbslwr.c b/lib/crtdll/mbstring/mbslwr.c new file mode 100644 index 0000000..cdbdf5f --- /dev/null +++ b/lib/crtdll/mbstring/mbslwr.c @@ -0,0 +1,40 @@ +#include +#include + +unsigned int _mbbtolower(unsigned int c) +{ + if (!_ismbblead(c) ) + return tolower(c); + return c; +} +// code page 952 +#define CASE_DIFF (0x8281 - 0x8260) + +unsigned int _mbctolower(unsigned int c) +{ + + if ((c & 0xFF00) != 0) { +// true multibyte case conversion needed + if ( _ismbclower(c) ) + return c + CASE_DIFF; + + } else + return _mbbtolower(c); + + return 0; +} + +unsigned char * _mbslwr(unsigned char *x) +{ + unsigned char *y=x; + + while (*y) { + if (!_ismbblead(*y) ) + *y = tolower(*y); + else { + *y=_mbctolower(*(unsigned short *)y); + y++; + } + } + return x; +} diff --git a/lib/crtdll/mbstring/mbsncat.c b/lib/crtdll/mbstring/mbsncat.c new file mode 100644 index 0000000..9cc580f --- /dev/null +++ b/lib/crtdll/mbstring/mbsncat.c @@ -0,0 +1,58 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsset.c + * PURPOSE: Concatenate two multi byte string to maximum of n characters or bytes + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsncat(unsigned char *dst, const unsigned char *src, size_t n) +{ + char *d = (char *)dst; + char *s = (char *)src; + if (n != 0) { + d = dst + strlen(dst); // get the end of string + d += _mbclen2(*d); // move 1 or 2 up + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + if (!_ismbblead(*s) ) + n--; + } while (n > 0); + } + return dst; +} + +unsigned char * _mbsnbcat(unsigned char *dst, const unsigned char *src, size_t n) +{ + char *d; + char *s = (char *)src; + if (n != 0) { + d = dst + strlen(dst); // get the end of string + d += _mbclen2(*d); // move 1 or 2 up + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + if ( !(n==1 && _ismbblead(*s)) ) + n--; + } while (n > 0); + } + return dst; +} diff --git a/lib/crtdll/mbstring/mbsnccnt.c b/lib/crtdll/mbstring/mbsnccnt.c new file mode 100644 index 0000000..1e30c9b --- /dev/null +++ b/lib/crtdll/mbstring/mbsnccnt.c @@ -0,0 +1,29 @@ +#include + +size_t _mbsnccnt(const unsigned char *str, size_t n) +{ + unsigned char *s = (unsigned char *)str; + size_t cnt = 0; + while(*s != 0 && n > 0) { + if (_ismbblead(*s) ) + s++; + else + n--; + s++; + cnt++; + } + + return cnt; +} + +size_t _mbsnbcnt(const unsigned char *str, size_t n) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && n > 0) { + if (!_ismbblead(*s) ) + n--; + s++; + } + + return (size_t)(s - str); +} diff --git a/lib/crtdll/mbstring/mbsncmp.c b/lib/crtdll/mbstring/mbsncmp.c new file mode 100644 index 0000000..00bd789 --- /dev/null +++ b/lib/crtdll/mbstring/mbsncmp.c @@ -0,0 +1,103 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: Compares two strings to a maximum of n bytes or characters + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +int _mbsncmp(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return *s1 - *s2; + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return *short_s1 - *short_s2; + else { + s1 += 2; + s2 += 2; + n--; + + } + } + else + return *s1 - *s2; + } while (n > 0); + return 0; +} + +int _mbsnbcmp(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return *s1 - *s2; + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return *short_s1 - *short_s2; + else { + s1 += 2; + s2 += 2; + n-=2; + + } + } + else + return *s1 - *s2; + } while (n > 0); + return 0; +} diff --git a/lib/crtdll/mbstring/mbsncoll.c b/lib/crtdll/mbstring/mbsncoll.c new file mode 100644 index 0000000..157f4ef --- /dev/null +++ b/lib/crtdll/mbstring/mbsncoll.c @@ -0,0 +1,109 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncoll.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include + +int colldif(unsigned short c1, unsigned short c2); + +int _mbsncoll(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + n--; + + } + } + else + return colldif(*s1, *s2); + } while (n > 0); + return 0; +} + +int _mbsnbcoll(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + n-=2; + + } + } + else + return colldif(*s1, *s2); + } while (n > 0); + return 0; +} + +int colldif(unsigned short c1, unsigned short c2) +{ + return c1 - c2; +} diff --git a/lib/crtdll/mbstring/mbsncpy.c b/lib/crtdll/mbstring/mbsncpy.c new file mode 100644 index 0000000..41fe445 --- /dev/null +++ b/lib/crtdll/mbstring/mbsncpy.c @@ -0,0 +1,77 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncpy.c + * PURPOSE: Copies a string to a maximum of n bytes or characters + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +unsigned char *_mbsncpy(unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + if (n == 0) + return 0; + do { + + if (*s2 == 0) + break; + + if ( !_ismbblead(*s2) ) { + + *s1 = *s2; + s1 += 1; + s2 += 1; + n--; + } + else { + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + *short_s1 = *short_s2; + s1 += 2; + s2 += 2; + n--; + } + } while (n > 0); + return str1; +} + +unsigned char * _mbsnbcpy(unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + if (n == 0) + return 0; + do { + + if (*s2 == 0) + break; + + if ( !_ismbblead(*s2) ) { + + *s1 = *s2; + s1 += 1; + s2 += 1; + n--; + } + else { + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + *short_s1 = *short_s2; + s1 += 2; + s2 += 2; + n-=2; + } + } while (n > 0); + return str1; +} diff --git a/lib/crtdll/mbstring/mbsnextc.c b/lib/crtdll/mbstring/mbsnextc.c new file mode 100644 index 0000000..5d3bb0a --- /dev/null +++ b/lib/crtdll/mbstring/mbsnextc.c @@ -0,0 +1,18 @@ +#include + +unsigned int _mbsnextc (const unsigned char *src) +{ + + unsigned char *char_src = (unsigned char *)src; + unsigned short *short_src = (unsigned short *)src; + + if ( src == NULL ) + return 0; + + if ( !_ismbblead(*src) ) + return *char_src; + else + return *short_src; + return 0; + +} diff --git a/lib/crtdll/mbstring/mbsnicmp.c b/lib/crtdll/mbstring/mbsnicmp.c new file mode 100644 index 0000000..49c7c3f --- /dev/null +++ b/lib/crtdll/mbstring/mbsnicmp.c @@ -0,0 +1,39 @@ +#include + +size_t _mbclen2(const unsigned int s); +unsigned int _mbbtoupper(unsigned int c); + +int _mbsnicmp(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + if (n == 0) + return 0; + do { + if (_mbbtoupper(*s1) != _mbbtoupper(*s2)) + return _mbbtoupper(*(unsigned const char *)s1) - _mbbtoupper(*(unsigned const char *)s2); + s1 += _mbclen2(*s1); + s2 += _mbclen2(*s2); + + if (*s1 == 0) + break; + if (!_ismbblead(*s1) ) + n--; + } while (n > 0); + return 0; +} + +int _mbsnbicmp(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + if (n == 0) + return 0; + do { + if (_mbbtoupper(*s1) != _mbbtoupper(*s2)) + return _mbbtoupper(*(unsigned const char *)s1) - _mbbtoupper(*(unsigned const char *)s2); + s1 += _mbclen2(*s1); + s2 += _mbclen2(*s2); + + if (*s1 == 0) + break; + n--; + } while (n > 0); + return 0; +} diff --git a/lib/crtdll/mbstring/mbsnicoll.c b/lib/crtdll/mbstring/mbsnicoll.c new file mode 100644 index 0000000..4b066e8 --- /dev/null +++ b/lib/crtdll/mbstring/mbsnicoll.c @@ -0,0 +1,10 @@ +#include + +int _mbsnicoll(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + return 0; +} +int _mbsnbicoll(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + return 0; +} diff --git a/lib/crtdll/mbstring/mbsninc.c b/lib/crtdll/mbstring/mbsninc.c new file mode 100644 index 0000000..3fb1235 --- /dev/null +++ b/lib/crtdll/mbstring/mbsninc.c @@ -0,0 +1,13 @@ +#include + +unsigned char * _mbsninc(const unsigned char *str, size_t n) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && n > 0) { + if (!_ismbblead(*s) ) + n--; + s++; + } + + return s; +} diff --git a/lib/crtdll/mbstring/mbsnset.c b/lib/crtdll/mbstring/mbsnset.c new file mode 100644 index 0000000..6c78d31 --- /dev/null +++ b/lib/crtdll/mbstring/mbsnset.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsset.c + * PURPOSE: Fills a string with a multibyte character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsnset(unsigned char *src, unsigned int val, size_t count) +{ + unsigned char *char_src = (unsigned char *)src; + unsigned short *short_src = (unsigned short *)src; + + if ( _mbclen2(val) == 1 ) { + + while(count > 0) { + *char_src = val; + char_src++; + count--; + } + *char_src = 0; + } + else { + while(count > 0) { + *short_src = val; + short_src++; + count-=2; + } + *short_src = 0; + } + + return src; +} + +unsigned char * _mbsnbset(unsigned char *src, unsigned int val, size_t count) +{ + unsigned char *char_src = (unsigned char *)src; + unsigned short *short_src = (unsigned short *)src; + + if ( _mbclen2(val) == 1 ) { + + while(count > 0) { + *char_src = val; + char_src++; + count--; + } + *char_src = 0; + } + else { + while(count > 0) { + *short_src = val; + short_src++; + count-=2; + } + *short_src = 0; + } + + return src; +} diff --git a/lib/crtdll/mbstring/mbspbrk.c b/lib/crtdll/mbstring/mbspbrk.c new file mode 100644 index 0000000..7b6e327 --- /dev/null +++ b/lib/crtdll/mbstring/mbspbrk.c @@ -0,0 +1,15 @@ +#include +// not correct +unsigned char * _mbspbrk(const unsigned char *s1, const unsigned char *s2) +{ + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return (unsigned char *)((char *)s1 - (char *)1); + } + return 0; +} diff --git a/lib/crtdll/mbstring/mbsrchr.c b/lib/crtdll/mbstring/mbsrchr.c new file mode 100644 index 0000000..824e639 --- /dev/null +++ b/lib/crtdll/mbstring/mbsrchr.c @@ -0,0 +1,30 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsrchr.c + * PURPOSE: Searches for a character in reverse + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsrchr(const unsigned char *src, unsigned int val) +{ + char *s = (char *)src; + short cc = val; + const char *sp=(char *)0; + + while (*s) + { + if (*(short *)s == cc) + sp = s; + s+= _mbclen2(*s); + } + if (cc == 0) + sp = s; + return (char *)sp; +} diff --git a/lib/crtdll/mbstring/mbsrev.c b/lib/crtdll/mbstring/mbsrev.c new file mode 100644 index 0000000..57cc335 --- /dev/null +++ b/lib/crtdll/mbstring/mbsrev.c @@ -0,0 +1,28 @@ +#include + +unsigned char * _mbsrev(unsigned char *s) +{ + unsigned char *e; + unsigned char a; + e=s; + while (*e) { + if ( _ismbblead(*e) ) { + a = *e; + *e = *++e; + if ( *e == 0 ) + break; + *e = a; + } + e++; + } + while (s + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsset(unsigned char *src, unsigned int c) +{ + unsigned char *char_src = src; + unsigned short *short_src = (unsigned short *)src; + + if ( _mbclen2(c) == 1 ) { + + while(*char_src != 0) { + *char_src = c; + char_src++; + } + *char_src = 0; + } + else { + while(*short_src != 0) { + *short_src = c; + short_src++; + } + *short_src = 0; + } + + return src; +} diff --git a/lib/crtdll/mbstring/mbsspn.c b/lib/crtdll/mbstring/mbsspn.c new file mode 100644 index 0000000..6ad7fef --- /dev/null +++ b/lib/crtdll/mbstring/mbsspn.c @@ -0,0 +1,15 @@ +#include +// not correct +size_t _mbsspn(const unsigned char *s1, const unsigned char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (size_t)(p - 1) - (size_t)s1; +// - (char *)s1); +} diff --git a/lib/crtdll/mbstring/mbsspnp.c b/lib/crtdll/mbstring/mbsspnp.c new file mode 100644 index 0000000..d8ec9e1 --- /dev/null +++ b/lib/crtdll/mbstring/mbsspnp.c @@ -0,0 +1,14 @@ +#include +// not correct +unsigned char * _mbsspnp(const unsigned char *s1, const unsigned char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (unsigned char *)p; +} diff --git a/lib/crtdll/mbstring/mbsstr.c b/lib/crtdll/mbstring/mbsstr.c new file mode 100644 index 0000000..321b36b --- /dev/null +++ b/lib/crtdll/mbstring/mbsstr.c @@ -0,0 +1,20 @@ +#include +#include + +unsigned char *_mbsstr(const unsigned char *src1,const unsigned char *src2) +{ + int len; + + if(src2 ==NULL || *src2 == 0) + return (unsigned char *)src1; + + len = _mbstrlen(src2); + + while(*src1) + { + if((*src1 == *src2) && (_mbsncmp(src1,src2,len) == 0)) + return (unsigned char *)src1; + src1 = (unsigned char *)_mbsinc(src1); + } + return NULL; +} diff --git a/lib/crtdll/mbstring/mbstok.c b/lib/crtdll/mbstring/mbstok.c new file mode 100644 index 0000000..538b856 --- /dev/null +++ b/lib/crtdll/mbstring/mbstok.c @@ -0,0 +1,53 @@ +#include + +unsigned char * _mbstok(unsigned char *s, unsigned char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s; + s = _mbsinc(s); + + for (spanp = delim; (sc = *spanp) != 0; spanp = _mbsinc(spanp)) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s; + s = _mbsinc(s); + spanp = delim; + do { + if ((sc = *spanp) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + spanp = _mbsinc(spanp); + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/crtdll/mbstring/mbstrlen.c b/lib/crtdll/mbstring/mbstrlen.c new file mode 100644 index 0000000..7cfd19f --- /dev/null +++ b/lib/crtdll/mbstring/mbstrlen.c @@ -0,0 +1,16 @@ +#include +#include + +size_t _mbstrlen( const char *string ) +{ + char *s = (char *)string; + size_t i = 0; + + while ( *s != 0 ) { + if ( _ismbblead(*s) ) + s++; + s++; + i++; + } + return i; +} diff --git a/lib/crtdll/mbstring/mbsupr.c b/lib/crtdll/mbstring/mbsupr.c new file mode 100644 index 0000000..90e5b0f --- /dev/null +++ b/lib/crtdll/mbstring/mbsupr.c @@ -0,0 +1,50 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include + +unsigned int _mbbtoupper(unsigned int c) +{ + if (!_ismbblead(c) ) + return toupper(c); + + return c; +} + +// codepage 952 +#define CASE_DIFF (0x8281 - 0x8260) + +unsigned int _mbctoupper(unsigned int c) +{ + + if ((c & 0xFF00) != 0) { +// true multibyte case conversion needed + if ( _ismbcupper(c) ) + return c + CASE_DIFF; + + } else + return _mbbtoupper(c); + + return 0; +} + +unsigned char * _mbsupr(unsigned char *x) +{ + unsigned char *y=x; + while (*y) { + if (!_ismbblead(*y) ) + *y = toupper(*y); + else { + *y=_mbctoupper(*(unsigned short *)y); + y++; + } + } + return x; +} diff --git a/lib/crtdll/misc/.cvsignore b/lib/crtdll/misc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/misc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/misc/CRT_noglob.c b/lib/crtdll/misc/CRT_noglob.c new file mode 100644 index 0000000..34e9a86 --- /dev/null +++ b/lib/crtdll/misc/CRT_noglob.c @@ -0,0 +1,18 @@ +/* + * noglob.c + * + * This file defines _CRT_glob to have a value of 0, which will + * turn off command line globbing. It is compiled into a separate object + * file which you can add to your link line to turn off globbing like + * this: + * + * gcc -o foo.exe foo.o noglob.o + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +int _CRT_glob = 0; + diff --git a/lib/crtdll/misc/CRTfmode.c b/lib/crtdll/misc/CRTfmode.c new file mode 100644 index 0000000..4edd811 --- /dev/null +++ b/lib/crtdll/misc/CRTfmode.c @@ -0,0 +1,21 @@ +/* + * CRTfmode.c + * + * Sets _CRT_fmode to be zero, which will cause _mingw32_init_fmode to leave + * all file modes in their default state (basically text mode). + * + * This file is part of the Mingw32 package. + * + * THIS FILE IS IN THE PUBLIC DOMAIN. + * + * Contributers: + * Created by Colin Peters + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +unsigned int _CRT_fmode = 0; + diff --git a/lib/crtdll/misc/CRTglob.c b/lib/crtdll/misc/CRTglob.c new file mode 100644 index 0000000..6b58fc9 --- /dev/null +++ b/lib/crtdll/misc/CRTglob.c @@ -0,0 +1,19 @@ +/* + * CRTglob.c + * + * This object file defines _CRT_glob to have a value of -1, which will + * turn on command line globbing by default. If you want to turn off + * command line globbing include a line + * + * int _CRT_glob = 0; + * + * in one of your source modules. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +int _CRT_glob = -1; + diff --git a/lib/crtdll/misc/CRTinit.c b/lib/crtdll/misc/CRTinit.c new file mode 100644 index 0000000..231658d --- /dev/null +++ b/lib/crtdll/misc/CRTinit.c @@ -0,0 +1,33 @@ +/* + * CRTinit.c + * + * A dummy version of _CRT_INIT for MS compatibility. Programs, or more often + * dlls, which use the static version of the MSVC run time are supposed to + * call _CRT_INIT to initialize the run time library in DllMain. This does + * not appear to be necessary when using crtdll or the dll versions of the + * MSVC runtime, so the dummy call simply does nothing. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +void +_CRT_INIT () +{ +} + diff --git a/lib/crtdll/misc/GetArgs.c b/lib/crtdll/misc/GetArgs.c new file mode 100644 index 0000000..1b9a9d9 --- /dev/null +++ b/lib/crtdll/misc/GetArgs.c @@ -0,0 +1,133 @@ +#include +#include +#include + + +char *_pgmptr_dll; +char *_acmdln_dll; +unsigned int _commode_dll; +unsigned int _winmajor_dll; +unsigned int _winminor_dll; +unsigned int _winver_dll; + + +unsigned int _osmajor_dll; +unsigned int _osminor_dll; +unsigned int _osmode_dll; +unsigned int _osver_dll; +unsigned int _osversion_dll; + +unsigned int _basemajor_dll; +unsigned int _baseminor_dll; +unsigned int _baseversion_dll; + +#undef __argv +#undef __argc + +char *xargv[1024]; + +char **__argv = xargv; +int __argc = 0; +int *__argc_dll = &__argc; +char ***__argv_dll = &__argv; + + +#undef _environ +char **_environ; +#undef _environ_dll +char *** _environ_dll = &_environ; +static int envAlloced = 0; + + +int BlockEnvToEnviron() +{ +char * ptr; +int i; + if (!envAlloced) + { + envAlloced = 50; + _environ = malloc (envAlloced * sizeof (char **)); + if (!_environ) return -1; + _environ[0] =NULL; + } + ptr = (char *)GetEnvironmentStringsA(); + if (!ptr) return -1; + for (i = 0 ; *ptr ; i++) + { + if(i>envAlloced-2) + { + envAlloced = i+3; + _environ = realloc (_environ,envAlloced * sizeof (char **)); + } + _environ[i] = ptr; + while(*ptr) ptr++; + ptr++; + } + _environ[i] =0; + return 0; +} + +int __GetMainArgs(int *argc,char ***argv,char ***env,int flag) +{ + int i,afterlastspace; + DWORD version; + + _acmdln_dll = GetCommandLineA(); + + version = GetVersion(); + _osver_dll = version >> 16; + _winminor_dll = version & 0xFF; + _winmajor_dll = (version>>8) & 0xFF; + _winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8); + + + /* missing threading init */ + + i=0; + afterlastspace=0; + __argc=0; + + while (_acmdln_dll[i]) + { + if (_acmdln_dll[i]==' ') + { + __argc++; + _acmdln_dll[i]='\0'; + __argv[__argc-1] = strdup(_acmdln_dll + afterlastspace); + _acmdln_dll[i]=' '; + i++; + while (_acmdln_dll[i]==' ') + i++; + afterlastspace=i; + } + else + { + i++; + } + } + + if (_acmdln_dll[afterlastspace] != 0) + { + __argc++; + _acmdln_dll[i]='\0'; + __argv[__argc-1] = strdup(_acmdln_dll+afterlastspace); + } + HeapValidate(GetProcessHeap(),0,NULL); + + if( BlockEnvToEnviron() ) + return FALSE; + _environ_dll = &_environ; + + *argc = __argc; + *argv = __argv; + *env = _environ; + + _pgmptr_dll = strdup((char *)argv[0]); + + return 0; +} + +int _chkstk(void) +{ + return 0; +} diff --git a/lib/crtdll/misc/amsg.c b/lib/crtdll/misc/amsg.c new file mode 100644 index 0000000..3ea80ee --- /dev/null +++ b/lib/crtdll/misc/amsg.c @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include + +int _aexit_rtn_dll(int exitcode) +{ + _exit(exitcode); +} + +void _amsg_exit (int errnum) +{ + fprintf(stderr,strerror(errnum)); + _aexit_rtn_dll(-1); +} + diff --git a/lib/crtdll/misc/crt1.c b/lib/crtdll/misc/crt1.c new file mode 100644 index 0000000..b7d6172 --- /dev/null +++ b/lib/crtdll/misc/crt1.c @@ -0,0 +1,157 @@ +/* + * crt1.c + * + * Source code for the startup proceedures used by all programs. This code + * is compiled to make crt0.o, which should be located in the library path. + * + * This code is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* NOTE: The code for initializing the _argv, _argc, and environ variables + * has been moved to a separate .c file which is included in both + * crt1.c and dllcrt1.c. This means changes in the code don't have to + * be manually synchronized, but it does lead to this not-generally- + * a-good-idea use of include. */ +#include "init.c" + +extern int main(int, char**, char**); + +/* + * Setup the default file handles to have the _CRT_fmode mode, as well as + * any new files created by the user. + */ +extern unsigned int _CRT_fmode; + +void +_mingw32_init_fmode (void) +{ + /* Don't set the file mode if the user hasn't set any value for it. */ + if (_CRT_fmode) + { + _fmode = _CRT_fmode; + + /* + * This overrides the default file mode settings for stdin, + * stdout and stderr. At first I thought you would have to + * test with isatty, but it seems that the DOS console at + * least is smart enough to handle _O_BINARY stdout and + * still display correctly. + */ + if (stdin) + { + _setmode (_fileno(stdin), _CRT_fmode); + } + if (stdout) + { + _setmode (_fileno(stdout), _CRT_fmode); + } + if (stderr) + { + _setmode (_fileno(stderr), _CRT_fmode); + } + } +} + + +/* + * The function mainCRTStartup is the entry point for all console programs. + */ +int +mainCRTStartup (void) +{ + int nRet; + + /* + * I have been told that this is the correct thing to do. You + * have to uncomment the prototype of SetUnhandledExceptionFilter + * in the GNU Win32 API headers for this to work. The type it + * expects is a pointer to a function of the same type as + * UnhandledExceptionFilter, which is prototyped just above + * (see Functions.h). + */ + //SetUnhandledExceptionFilter (NULL); + + /* + * Initialize floating point unit. + */ + _fpreset (); /* Supplied by the runtime library. */ + + /* + * Set up __argc, __argv and _environ. + */ + _mingw32_init_mainargs(); + + /* + * Sets the default file mode for stdin, stdout and stderr, as well + * as files later opened by the user, to _CRT_fmode. + * NOTE: DLLs don't do this because that would be rude! + */ + _mingw32_init_fmode(); + + /* + * Call the main function. If the user does not supply one + * the one in the 'libmingw32.a' library will be linked in, and + * that one calls WinMain. See main.c in the 'lib' dir + * for more details. + */ + nRet = main(_argc, _argv, _environ); + + /* + * Perform exit processing for the C library. This means + * flushing output and calling 'atexit' registered functions. + */ + _cexit(); + + ExitProcess (nRet); + + return 0; +} + +/* + * For now the GUI startup function is the same as the console one. + * This simply gets rid of the annoying warning about not being able + * to find WinMainCRTStartup when linking GUI applications. + */ +int +WinMainCRTStartup (void) +{ + return mainCRTStartup(); +} + +/* With the EGCS build from Mumit Khan (or apparently b19 from Cygnus) this + * is no longer necessary. */ +#ifdef __GNUC__ +/* + * This section terminates the list of imports under GCC. If you do not + * include this then you will have problems when linking with DLLs. + * + */ +asm (".section .idata$3\n" ".long 0,0,0,0,0,0,0,0"); +#endif + diff --git a/lib/crtdll/misc/dllcrt1.c b/lib/crtdll/misc/dllcrt1.c new file mode 100644 index 0000000..a609c0f --- /dev/null +++ b/lib/crtdll/misc/dllcrt1.c @@ -0,0 +1,105 @@ +/* + * dllcrt1.c + * + * Initialization code for DLLs. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * DLL support adapted from Gunther Ebert + * + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include +#include +#include + +/* See note in crt0.c */ +#include "init.c" + +/* Unlike normal crt0, I don't initialize the FPU, because the process + * should have done that already. I also don't set the file handle modes, + * because that would be rude. */ + +#ifdef __GNUC__ +extern void __main(); +extern void __do_global_dtors(); +#endif + +extern BOOL WINAPI DllMain(HANDLE, DWORD, LPVOID); + +BOOL WINAPI +DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + BOOL bRet; + + if (dwReason == DLL_PROCESS_ATTACH) + { + _mingw32_init_mainargs(); + +#ifdef __GNUC__ + /* From libgcc.a, calls global class constructors. */ + __main(); +#endif + } + + /* + * Call the user-supplied DllMain subroutine + * NOTE: DllMain is optional, so libmingw32.a includes a stub + * which will be used if the user does not supply one. + */ + bRet = DllMain(hDll, dwReason, lpReserved); + +#ifdef __GNUC__ + if (dwReason == DLL_PROCESS_DETACH) + { + /* From libgcc.a, calls global class destructors. */ + __do_global_dtors(); + } +#endif + + return bRet; +} + +/* + * For the moment a dummy atexit. Atexit causes problems in DLLs, especially + * if they are dynamically loaded. For now atexit inside a DLL does nothing. + * NOTE: We need this even if the DLL author never calls atexit because + * the global constructor function __do_global_ctors called from __main + * will attempt to register __do_global_dtors using atexit. + * Thanks to Andrey A. Smirnov for pointing this one out. + */ +int +atexit (void (*pfn)()) +{ + return 0; +} + +/* With the EGCS snapshot from Mumit Khan (or b19 from Cygnus I hear) this + * is no longer necessary. */ +#if 0 +#ifdef __GNUC__ +/* + * This section terminates the list of imports under GCC. If you do not + * include this then you will have problems when linking with DLLs. + */ +asm (".section .idata$3\n" ".long 0,0,0,0,0,0,0,0"); +#endif +#endif diff --git a/lib/crtdll/misc/dllmain.c b/lib/crtdll/misc/dllmain.c new file mode 100644 index 0000000..acf81f7 --- /dev/null +++ b/lib/crtdll/misc/dllmain.c @@ -0,0 +1,49 @@ +/* + * dllmain.c + * + * A stub DllMain function which will be called by DLLs which do not + * have a user supplied DllMain. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include +#include +#include + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[255]; + HANDLE OutputHandle; + + AllocConsole(); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + va_start(args,fmt); + vsprintf(buffer,fmt,args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL); + va_end(args); +} + +BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + return TRUE; +} + diff --git a/lib/crtdll/misc/gccmain.c b/lib/crtdll/misc/gccmain.c new file mode 100644 index 0000000..1c7f5d0 --- /dev/null +++ b/lib/crtdll/misc/gccmain.c @@ -0,0 +1,85 @@ +/* + * gccmain.c + * + * A separate version of __main, __do_global_ctors and __do_global_dtors for + * Mingw32 for use with Cygwin32 b19. Hopefully this object file will only + * be linked if the libgcc.a doesn't include __main, __do_global_dtors and + * __do_global_ctors. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Code supplied by Stan Cox + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +/* Needed for the atexit prototype. */ +#include + +typedef void (*func_ptr) (void); +extern func_ptr __CTOR_LIST__[]; +extern func_ptr __DTOR_LIST__[]; + +void +__do_global_dtors (void) +{ + static func_ptr *p = __DTOR_LIST__ + 1; + + /* + * Call each destructor in the destructor list until a null pointer + * is encountered. + */ + while (*p) + { + (*(p)) (); + p++; + } +} + +void +__do_global_ctors (void) +{ + unsigned long nptrs = (unsigned long) __CTOR_LIST__[0]; + unsigned i; + + /* + * If the first entry in the constructor list is -1 then the list + * is terminated with a null entry. Otherwise the first entry was + * the number of pointers in the list. + */ + if (nptrs == -1) + { + for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++) + ; + } + + /* + * Go through the list backwards calling constructors. + */ + for (i = nptrs; i >= 1; i--) + { + __CTOR_LIST__[i] (); + } + + /* + * Register the destructors for processing on exit. + */ + atexit (__do_global_dtors); +} + +static int initialized = 0; + +void +__main (void) +{ + if (! initialized) + { + initialized = 1; + __do_global_ctors (); + } +} + diff --git a/lib/crtdll/misc/init.c b/lib/crtdll/misc/init.c new file mode 100644 index 0000000..2ee3da1 --- /dev/null +++ b/lib/crtdll/misc/init.c @@ -0,0 +1,75 @@ +/* + * init.c + * + * Code to initialize standard file handles and command line arguments. + * This file is #included in both crt1.c and dllcrt1.c. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +/* + * Access to a standard 'main'-like argument count and list. Also included + * is a table of environment variables. + */ +int _argc = 0; +char** _argv = 0; + +/* NOTE: Thanks to Pedro A. Aranda Gutiirrez for pointing + * this out to me. GetMainArgs (used below) takes a fourth argument + * which is an int that controls the globbing of the command line. If + * _CRT_glob is non-zero the command line will be globbed (e.g. *.* + * expanded to be all files in the startup directory). In the mingw32 + * library a _CRT_glob variable is defined as being -1, enabling + * this command line globbing by default. To turn it off and do all + * command line processing yourself (and possibly escape bogons in + * MS's globbing code) include a line in one of your source modules + * defining _CRT_glob and setting it to zero, like this: + * int _CRT_glob = 0; + */ +extern int _CRT_glob; + +#ifdef __MSVCRT__ +extern void __getmainargs(int *, char***, char***, int); +#else +extern void __GetMainArgs(int *, char***, char***, int); +#endif + +/* + * Initialize the _argc, _argv and environ variables. + */ +static void +_mingw32_init_mainargs (void) +{ + /* The environ variable is provided directly in stdlib.h through + * a dll function call. */ + char** dummy_environ; + + /* + * Microsoft's runtime provides a function for doing just that. + */ +#ifdef __MSVCRT__ + (void) __getmainargs(&_argc, &_argv, &dummy_environ, _CRT_glob); +#else + /* CRTDLL version */ + (void) __GetMainArgs(&_argc, &_argv, &dummy_environ, _CRT_glob); +#endif +} + diff --git a/lib/crtdll/misc/initter.c b/lib/crtdll/misc/initter.c new file mode 100644 index 0000000..a185e70 --- /dev/null +++ b/lib/crtdll/misc/initter.c @@ -0,0 +1,7 @@ + +typedef void(*atexit_t)(void); + +void _initterm(atexit_t *, atexit_t *) +{ + return; +} \ No newline at end of file diff --git a/lib/crtdll/misc/initterm.c b/lib/crtdll/misc/initterm.c new file mode 100644 index 0000000..c834b61 --- /dev/null +++ b/lib/crtdll/misc/initterm.c @@ -0,0 +1,35 @@ +#include + + +void _initterm ( + void (* fStart[])(void), + void (* fEnd[])(void) + ) +{ + int i = 0; + + + if ( fStart == NULL || fEnd == NULL ) + return; + + while ( &fStart[i] < fEnd ) + { + if ( fStart[i] != NULL ) + (*fStart[i])(); + i++; + } +} +typedef int (* _onexit_t)(void); + +_onexit_t __dllonexit ( + _onexit_t func, + void (** fStart[])(void), + void (** fEnd[])(void) + ) +{ +} + +_onexit_t _onexit(_onexit_t x) +{ + return x; +} diff --git a/lib/crtdll/misc/main.c b/lib/crtdll/misc/main.c new file mode 100644 index 0000000..4d1446b --- /dev/null +++ b/lib/crtdll/misc/main.c @@ -0,0 +1,95 @@ +/* + * main.c + * + * Extra startup code for applications which do not have a main function + * of their own (but do have a WinMain). Generally these are GUI + * applications, but they don't *have* to be. + * + * This file is part of the Mingw32 package. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include +#include + +#define ISSPACE(a) (a == ' ' || a == '\t') + +extern int PASCAL WinMain (HANDLE hInst, HANDLE hPrevInst, LPSTR szCmdLine, + int nShow); + +int +main (int argc, char* argv[], char* environ[]) +{ + char* szCmd; + STARTUPINFO startinfo; + int nRet; + + /* Get the command line passed to the process. */ + szCmd = GetCommandLineA(); + GetStartupInfoA(&startinfo); + + /* Strip off the name of the application and any leading + * whitespace. */ + if (szCmd) + { + while(ISSPACE(*szCmd)) + { + szCmd++; + } + + /* On my system I always get the app name enclosed + * in quotes... */ + if (*szCmd == '\"') + { + do + { + szCmd++; + } + while (*szCmd != '\"' && *szCmd != '\0'); + + if (*szCmd == '\"') + { + szCmd++; + } + } + else + { + /* If no quotes then assume first token is program + * name. */ + while (!ISSPACE(*szCmd) && *szCmd != '\0') + { + szCmd++; + } + } + + while (ISSPACE(*szCmd)) + { + szCmd++; + } + } + + nRet = WinMain (GetModuleHandle(NULL), NULL, szCmd, + (startinfo.dwFlags & STARTF_USESHOWWINDOW) ? + startinfo.wShowWindow : SW_SHOWDEFAULT); + + return nRet; +} + diff --git a/lib/crtdll/misc/purecall.c b/lib/crtdll/misc/purecall.c new file mode 100644 index 0000000..4294742 --- /dev/null +++ b/lib/crtdll/misc/purecall.c @@ -0,0 +1,5 @@ + +int _purecall(void) +{ + return 0; +} diff --git a/lib/crtdll/misc/setnew.c b/lib/crtdll/misc/setnew.c new file mode 100644 index 0000000..885bd3b --- /dev/null +++ b/lib/crtdll/misc/setnew.c @@ -0,0 +1,29 @@ +#include + + +typedef int (* new_handler_t)( size_t ); + +new_handler_t new_handler; + +#undef _set_new_handler +new_handler_t _set_new_handler__FPFUi_i(new_handler_t hnd) +{ + new_handler_t old = new_handler; + + new_handler = hnd; + + return old; +} + +#undef delete +void __builtin_delete (void* m) +{ + if ( m != NULL ) + free( m ); +} + +#undef new +void * __builtin_new (unsigned int s ) +{ + return malloc( s ); +} diff --git a/lib/crtdll/misc/sleep.c b/lib/crtdll/misc/sleep.c new file mode 100644 index 0000000..8735808 --- /dev/null +++ b/lib/crtdll/misc/sleep.c @@ -0,0 +1,7 @@ +#include + + +void sleep(unsigned long timeout) +{ + Sleep((timeout)?timeout:1); +} diff --git a/lib/crtdll/misc/unwind.c b/lib/crtdll/misc/unwind.c new file mode 100644 index 0000000..a69fba1 --- /dev/null +++ b/lib/crtdll/misc/unwind.c @@ -0,0 +1,10 @@ +void _global_unwind2( PEXCEPTION_FRAME frame ) +{ + RtlUnwind( frame, 0, NULL, 0 ); +} + + +void _local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr ) +{ + TRACE(crtdll,"(%p,%ld)\n",endframe,nr); +} diff --git a/lib/crtdll/process/.cvsignore b/lib/crtdll/process/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/process/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/process/_cwait.c b/lib/crtdll/process/_cwait.c new file mode 100644 index 0000000..628a72d --- /dev/null +++ b/lib/crtdll/process/_cwait.c @@ -0,0 +1,30 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/process/cwait.c + * PURPOSE: Waits for a process to exit + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 04/03/99: Created + */ +#include +#include +#include +#include + +int _cwait (int* pnStatus, int hProc, int nAction) +{ + DWORD ExitCode; + + nAction = 0; + if ( WaitForSingleObject((void *)hProc,INFINITE) != WAIT_OBJECT_0 ) { + __set_errno(ECHILD); + return -1; + } + + if ( !GetExitCodeProcess((void *)hProc,&ExitCode) ) + return -1; + if (pnStatus != NULL) + *pnStatus = (int)ExitCode; + return hProc; +} diff --git a/lib/crtdll/process/_system.c b/lib/crtdll/process/_system.c new file mode 100644 index 0000000..f6d5b67 --- /dev/null +++ b/lib/crtdll/process/_system.c @@ -0,0 +1,83 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/process/system.c + * PURPOSE: Excutes a shell command + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 04/03/99: Created + */ +#include +#include +#include +#include + +int system(const char *command) +{ + char szCmdLine[MAX_PATH]; + char *szComSpec=NULL; + + + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + + int nStatus; + + szComSpec = getenv("COMSPEC"); + +// system should return 0 if command is null and the shell is found + + if ( command == NULL ) { + if ( szComSpec == NULL ) + return 0; + else + return -1; + } + + + +// should return 127 or 0 ( MS ) if the shell is not found +// __set_errno(ENOENT); + + if ( szComSpec == NULL ) + szComSpec = "cmd.exe"; + + + + strcpy(szCmdLine," /C "); + + strncat(szCmdLine,command,MAX_PATH-5); + +//check for a too long argument E2BIG + +//command file has invalid format ENOEXEC + + + StartupInfo.cb = sizeof(STARTUPINFO); + StartupInfo.lpReserved= NULL; + StartupInfo.dwFlags = 0; + StartupInfo.wShowWindow = SW_SHOWDEFAULT; + StartupInfo.lpReserved2 = NULL; + StartupInfo.cbReserved2 = 0; + +// According to ansi standards the new process should ignore SIGINT and SIGQUIT +// In order to disable ctr-c the process is created with CREATE_NEW_PROCESS_GROUP, +// thus SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process. + + +//SIGCHILD should be blocked aswell + + if ( CreateProcessA(szComSpec,szCmdLine,NULL,NULL,TRUE,CREATE_NEW_PROCESS_GROUP,NULL,NULL,&StartupInfo,&ProcessInformation) == FALSE) { + return -1; + } + + +// system should wait untill the calling process is finished + + _cwait(&nStatus,(int)ProcessInformation.hProcess,0); + +// free the comspec [ if the COMSPEC == NULL provision is removed + // free(szComSpec); + + return nStatus; +} diff --git a/lib/crtdll/process/dll.c b/lib/crtdll/process/dll.c new file mode 100644 index 0000000..71a33b1 --- /dev/null +++ b/lib/crtdll/process/dll.c @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/process/dll.c + * PURPOSE: Dll support routines + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 04/03/99: Created + */ + +#include +#include + +void *_loaddll (char *name) +{ + return LoadLibraryA(name); +} + +int _unloaddll(void *handle) +{ + return FreeLibrary(handle); +} + +FARPROC _getdllprocaddr(void *hModule,char * lpProcName, int iOrdinal) +{ + + + if ( lpProcName != NULL ) + return GetProcAddress(hModule, lpProcName); + else + return GetProcAddress(hModule, (LPSTR)iOrdinal); + return (NULL); +} diff --git a/lib/crtdll/process/execl.c b/lib/crtdll/process/execl.c new file mode 100644 index 0000000..1d05476 --- /dev/null +++ b/lib/crtdll/process/execl.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +int _execl(const char* szPath, const char* szArgv0, ...) +{ + char *szArg[100]; + const char *a; + int i = 0; + va_list l = 0; + va_start(l,szArgv0); + do { + a = va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + + return _spawnve(P_OVERLAY, szPath, szArg, _environ); +} diff --git a/lib/crtdll/process/execle.c b/lib/crtdll/process/execle.c new file mode 100644 index 0000000..f907798 --- /dev/null +++ b/lib/crtdll/process/execle.c @@ -0,0 +1,33 @@ +#include +#include +#include + + +// fixme rewrite to pass the array variants to va_list variant + +int _execle(const char *path, const char *szArgv0, ... /*, const char **envp */) +{ + char *szArg[100]; + const char *a; + char *ptr; + int i = 0; + va_list l = 0; + va_start(l,szArgv0); + do { + a = (const char *)va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + + +// szArg0 is passed and not environment if there is only one parameter; + + if ( i >=2 ) { + ptr = szArg[i-2]; + szArg[i-2] = NULL; + } + else + ptr = NULL; + + + return _spawnve(P_OVERLAY, path, (char * const *)szArg, (char * const *)ptr); +} diff --git a/lib/crtdll/process/execlp.c b/lib/crtdll/process/execlp.c new file mode 100644 index 0000000..1b97589 --- /dev/null +++ b/lib/crtdll/process/execlp.c @@ -0,0 +1,17 @@ +#include +#include +#include + +int _execlp(const char *szPath, const char *szArgv0, ...) +{ + char *szArg[100]; + const char *a; + int i = 0; + va_list l = 0; + va_start(l,szArgv0); + do { + a = (const char *)va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + return _spawnvpe(P_OVERLAY, szPath,szArg, _environ); +} diff --git a/lib/crtdll/process/execlpe.c b/lib/crtdll/process/execlpe.c new file mode 100644 index 0000000..785dff0 --- /dev/null +++ b/lib/crtdll/process/execlpe.c @@ -0,0 +1,29 @@ +#include +#include +#include + + +int execlpe(const char *path, const char *szArgv0, ... /*, const char **envp */) +{ + char *szArg[100]; + const char *a; + char *ptr; + int i = 0; + va_list l = 0; + va_start(l,szArgv0); + do { + a = (const char *)va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + + +// szArg0 is passed and not environment if there is only one parameter; + + if ( i >=2 ) { + ptr = szArg[i-2]; + szArg[i-2] = NULL; + } + else + ptr = NULL; + return spawnvpe(P_OVERLAY, path, (char * const *)szArg, (char * const *)ptr); +} diff --git a/lib/crtdll/process/execv.c b/lib/crtdll/process/execv.c new file mode 100644 index 0000000..d1d2bb8 --- /dev/null +++ b/lib/crtdll/process/execv.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include + +int _execv(const char* szPath, char* const* szaArgv) +{ + return _spawnve(P_OVERLAY, szPath, szaArgv, _environ); +} diff --git a/lib/crtdll/process/execve.c b/lib/crtdll/process/execve.c new file mode 100644 index 0000000..3ea6ae9 --- /dev/null +++ b/lib/crtdll/process/execve.c @@ -0,0 +1,7 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int _execve(const char* szPath, char* const* szaArgv, char* const* szaEnv) +{ + return spawnve(P_OVERLAY, szPath, szaArgv, szaEnv); +} diff --git a/lib/crtdll/process/execvp.c b/lib/crtdll/process/execvp.c new file mode 100644 index 0000000..7dd5a22 --- /dev/null +++ b/lib/crtdll/process/execvp.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details *///#include +//#include +#include +#include + +int _execvp(const char* szPath, char* const* szaArgv) +{ + return _spawnvpe(P_OVERLAY, szPath, szaArgv, _environ); +} diff --git a/lib/crtdll/process/execvpe.c b/lib/crtdll/process/execvpe.c new file mode 100644 index 0000000..b7393eb --- /dev/null +++ b/lib/crtdll/process/execvpe.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + + +#include + +int _execvpe(const char* szPath, char* const* szaArgv, char* const* szaEnv) +{ + return _spawnvpe(P_OVERLAY, szPath, szaArgv, szaEnv); +} + + diff --git a/lib/crtdll/process/procid.c b/lib/crtdll/process/procid.c new file mode 100644 index 0000000..26e92cb --- /dev/null +++ b/lib/crtdll/process/procid.c @@ -0,0 +1,10 @@ +#include +#include + +int _getpid (void) +{ + //fixme GetCurrentProcessId + //return (int)GetCurrentProcessId(); + return 1; +} + diff --git a/lib/crtdll/process/spawnl.c b/lib/crtdll/process/spawnl.c new file mode 100644 index 0000000..c2518d4 --- /dev/null +++ b/lib/crtdll/process/spawnl.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +int _spawnl(int nMode, const char* szPath, const char* szArgv0,...) +{ + char *szArg[100]; + const char *a; + int i = 1; + va_list l = 0; + szArg[0]=(char*)szArgv0; + va_start(l,szArgv0); + do { + a = va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + + return _spawnve(nMode, szPath, szArg, _environ); +} diff --git a/lib/crtdll/process/spawnle.c b/lib/crtdll/process/spawnle.c new file mode 100644 index 0000000..9a8e2dd --- /dev/null +++ b/lib/crtdll/process/spawnle.c @@ -0,0 +1,29 @@ +#include +#include +#include + + +int _spawnle(int mode, const char *path, const char *szArgv0, ... /*, const char **envp */) +{ + char *szArg[100]; + char *a; + char *ptr; + int i = 1; + va_list l = 0; + szArg[0]=(char*)szArgv0; + va_start(l,szArgv0); + do { + a = (char *)va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + + if(a != NULL) + { +// __set_errno(E2BIG); + return -1; + } + + ptr = (char *)va_arg(l,const char *); + + return _spawnve(mode, path, (char * const *)szArg, (char * const *)ptr); +} diff --git a/lib/crtdll/process/spawnlp.c b/lib/crtdll/process/spawnlp.c new file mode 100644 index 0000000..58ed2ed --- /dev/null +++ b/lib/crtdll/process/spawnlp.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +int _spawnlp(int nMode, const char* szPath, const char* szArgv0, ...) +{ + char *szArg[100]; + const char *a; + int i = 0; + va_list l = 0; + va_start(l,szArgv0); + do { + a = (const char *)va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + return _spawnvpe(nMode, szPath,szArg, _environ); +} diff --git a/lib/crtdll/process/spawnlpe.c b/lib/crtdll/process/spawnlpe.c new file mode 100644 index 0000000..cfd73f9 --- /dev/null +++ b/lib/crtdll/process/spawnlpe.c @@ -0,0 +1,30 @@ +#include +#include +#include + + +int _spawnlpe(int mode, const char *path, const char *szArgv0, ... /*, const char **envp */) +{ + char *szArg[100]; + const char *a; + char *ptr; + int i = 0; + va_list l = 0; + va_start(l,szArgv0); + do { + a = (const char *)va_arg(l,const char *); + szArg[i++] = (char *)a; + } while ( a != NULL && i < 100 ); + + +// szArg0 is passed and not environment if there is only one parameter; + + if ( i >=2 ) { + ptr = szArg[i-2]; + szArg[i-2] = NULL; + } + else + ptr = NULL; + + return _spawnvpe(mode, path, (char * const *)szArg, (char * const *)ptr); +} diff --git a/lib/crtdll/process/spawnv.c b/lib/crtdll/process/spawnv.c new file mode 100644 index 0000000..cf25274 --- /dev/null +++ b/lib/crtdll/process/spawnv.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include + +int _spawnv(int nMode, const char* szPath, char* const* szaArgv) +{ + return _spawnve(nMode, szPath, (char * const *)szaArgv, _environ); +} diff --git a/lib/crtdll/process/spawnve.c b/lib/crtdll/process/spawnve.c new file mode 100644 index 0000000..1b698b9 --- /dev/null +++ b/lib/crtdll/process/spawnve.c @@ -0,0 +1,338 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include + +#include +#include +#include +#include +//#include +#include +#include +#include + + +#ifndef F_OK + #define F_OK 0x01 +#endif +#ifndef R_OK + #define R_OK 0x02 +#endif +#ifndef W_OK + #define W_OK 0x04 +#endif +#ifndef X_OK + #define X_OK 0x08 +#endif +#ifndef D_OK + #define D_OK 0x10 +#endif + +// information about crtdll file handles is not passed to child +int _fileinfo_dll = 0; + +static int +direct_exec_tail(const char *program, const char *args, + char * const envp[], + PROCESS_INFORMATION *ProcessInformation) +{ + + static STARTUPINFO StartupInfo; + + StartupInfo.cb = sizeof(STARTUPINFO); + StartupInfo.lpReserved= NULL; + StartupInfo.dwFlags = 0; + StartupInfo.wShowWindow = SW_SHOWDEFAULT; + StartupInfo.lpReserved2 = NULL; + StartupInfo.cbReserved2 = 0; + + + if (! CreateProcessA((char *)program,(char *)args,NULL,NULL,FALSE,0,(char **)envp,NULL,&StartupInfo,ProcessInformation) ) + { + __set_errno( GetLastError() ); + return -1; + } + + return (int)ProcessInformation->hProcess; +} + +static int vdm_exec(const char *program, char **argv, char **envp, + PROCESS_INFORMATION *ProcessInformation) +{ + static char args[1024]; + int i = 0; + args[0] = 0; + + strcpy(args,"vdm.exe "); + while(argv[i] != NULL ) { + strcat(args,argv[i]); + strcat(args," "); + i++; + } + + return direct_exec_tail(program,args,envp,ProcessInformation); +} + +static int go32_exec(const char *program, char **argv, char **envp, + PROCESS_INFORMATION *ProcessInformation) +{ + + + static char args[1024]; + static char envblock[2048]; + char * penvblock; + int i = 0; + + + envblock[0] = 0; + penvblock=envblock; + + while(envp[i] != NULL ) { + strcat(penvblock,envp[i]); + penvblock+=strlen(envp[i])+1; + i++; + } + penvblock[0]=0; + + args[0] = 0; + i = 0; + while(argv[i] != NULL ) { + strcat(args,argv[i]); + strcat(args," "); + i++; + } + + return direct_exec_tail(program,args,envp,ProcessInformation); +} + +int +command_exec(const char *program, char **argv, char **envp, + PROCESS_INFORMATION *ProcessInformation) +{ + static char args[1024]; + int i = 0; + + + + args[0] = 0; + + strcpy(args,"cmd.exe /c "); + while(argv[i] != NULL ) { + strcat(args,argv[i]); + strcat(args," "); + i++; + } + + return direct_exec_tail(program,args,envp,ProcessInformation); + +} + +static int script_exec(const char *program, char **argv, char **envp, + PROCESS_INFORMATION *ProcessInformation) +{ + return 0; +} + + +/* Note: the following list is not supposed to mention *every* + possible extension of an executable file. It only mentions + those extensions that can be *omitted* when you invoke the + executable from one of the shells used on MSDOS. */ +static struct { + const char *extension; + int (*interp)(const char *, char **, char **, + PROCESS_INFORMATION *); +} interpreters[] = { + { ".com", vdm_exec }, + { ".exe", go32_exec }, + { ".dll", go32_exec }, + { ".cmd", command_exec }, + { ".bat", command_exec }, + { ".btm", command_exec }, + { ".sh", script_exec }, /* for compatibility with ms_sh */ + { ".ksh", script_exec }, + { ".pl", script_exec }, /* Perl */ + { ".sed", script_exec }, + { "", go32_exec }, + { 0, script_exec }, /* every extension not mentioned above calls it */ + { 0, 0 }, +}; + +/* This is the index into the above array of the interpreter + which is called when the program filename has no extension. */ +#define INTERP_NO_EXT (sizeof(interpreters)/sizeof(interpreters[0]) - 3) + +/*-------------------------------------------------*/ + + + + +int _spawnve(int mode, const char *path, char *const argv[], char *const envp[]) +{ + /* This is the one that does the work! */ + PROCESS_INFORMATION ProcessInformation; + union { char *const *x; char **p; } u; + int i = -1; + char **argvp; + char **envpp; + char rpath[FILENAME_MAX], *rp, *rd=0; + int e = errno; + int is_dir = 0; + int found = 0; + DWORD ExitCode; + + if (path == 0 || argv[0] == 0) + { + errno = EINVAL; + return -1; + } + if (strlen(path) > FILENAME_MAX - 1) + { + errno = ENAMETOOLONG; + return -1; + } + + u.x = argv; argvp = u.p; + u.x = envp; envpp = u.p; + + fflush(stdout); /* just in case */ + for (rp=rpath; *path; *rp++ = *path++) + { + if (*path == '.') + rd = rp; + if (*path == '\\' || *path == '/') + rd = 0; + } + *rp = 0; + + /* If LFN is supported on the volume where rpath resides, we + might have something like foo.bar.exe or even foo.exe.com. + If so, look for RPATH.ext before even trying RPATH itself. */ + if (!rd) + { + for (i=0; interpreters[i].extension; i++) + { + strcpy(rp, interpreters[i].extension); + if (_access(rpath, F_OK) == 0 && !(is_dir = (_access(rpath, D_OK) == 0))) + { + found = 1; + break; + } + } + } + + if (!found) + { + const char *rpath_ext; + + if (rd) + { + i = 0; + rpath_ext = rd; + } + else + { + i = INTERP_NO_EXT; + rpath_ext = ""; + } + for ( ; interpreters[i].extension; i++) + if (_stricmp(rpath_ext, interpreters[i].extension) == 0 + && _access(rpath, F_OK) == 0 + && !(is_dir = (_access(rpath, D_OK) == 0))) + { + found = 1; + break; + } + } + if (!found) + { + errno = is_dir ? EISDIR : ENOENT; + return -1; + } + errno = e; + i = interpreters[i].interp(rpath, argvp, envpp, &ProcessInformation); + if (mode == P_OVERLAY) + exit(i); + if (mode == P_WAIT) + { + WaitForSingleObject(ProcessInformation.hProcess,INFINITE); + GetExitCodeProcess(ProcessInformation.hProcess,&ExitCode); + i = (int)ExitCode; + } + return i; +} + + + + +const char * find_exec(char * path,char *rpath) +{ + char *rp, *rd=0; + int i; + int is_dir = 0; + int found = 0; + if (path == 0 ) + return 0; + if (strlen(path) > FILENAME_MAX - 1) + return path; + + /* copy path in rpath */ + for (rd=path,rp=rpath; *rd; *rp++ = *rd++) + ; + *rp = 0; + /* try first with the name as is */ + for (i=0; interpreters[i].extension; i++) + { + strcpy(rp, interpreters[i].extension); + if (_access(rpath, F_OK) == 0 && !(is_dir = (_access(rpath, D_OK) == 0))) + { + found = 1; + break; + } + } + + if (!found) + { + /* search in the PATH */ + char winpath[MAX_PATH]; + if( GetEnvironmentVariableA("PATH",winpath,MAX_PATH)) + { + char *ep=winpath; + while( *ep) + { + if(*ep == ';') ep++; + rp=rpath; + for ( ; *ep && (*ep != ';') ; *rp++ = *ep++) + ; + *rp++='/'; + for (rd=path ; *rd ; *rp++ = *rd++) + ; + + for (i=0; interpreters[i].extension; i++) + { + strcpy(rp, interpreters[i].extension); + if (_access(rpath, F_OK) == 0 && !(is_dir = (_access(rpath, D_OK) == 0))) + { + found = 1; + break; + } + } + if (found) break; + } + } + } + if (!found) + return path; + + return rpath; +} + +int _spawnvpe(int nMode, const char* szPath, char* const* szaArgv, char* const* szaEnv) +{ + char rpath[FILENAME_MAX]; + + return _spawnve(nMode, find_exec((char*)szPath,rpath), szaArgv, szaEnv); + +} diff --git a/lib/crtdll/process/spawnvp.c b/lib/crtdll/process/spawnvp.c new file mode 100644 index 0000000..aecd80e --- /dev/null +++ b/lib/crtdll/process/spawnvp.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include + +int _spawnvp(int nMode, const char* szPath, char* const* szaArgv) +{ + return spawnvpe(nMode, szPath, (char * const *)szaArgv, _environ); +} diff --git a/lib/crtdll/process/spawnvpe.c b/lib/crtdll/process/spawnvpe.c new file mode 100644 index 0000000..bdad981 --- /dev/null +++ b/lib/crtdll/process/spawnvpe.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include + + +int _spawnvpe(int nMode, const char* szPath, char* const* szaArgv, char* const* szaEnv) +{ + + return spawnve(nMode, szPath, szaArgv, szaEnv); + +} diff --git a/lib/crtdll/process/thread.c b/lib/crtdll/process/thread.c new file mode 100644 index 0000000..c2a12d3 --- /dev/null +++ b/lib/crtdll/process/thread.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include + + +unsigned long + _beginthread (void (*pfuncStart)(void *), + unsigned unStackSize, void* pArgList) +{ + DWORD ThreadId; + HANDLE hThread; + if ( pfuncStart == NULL ) + __set_errno(EINVAL); + + hThread = CreateThread( NULL,unStackSize,(LPTHREAD_START_ROUTINE)pfuncStart,pArgList,0, &ThreadId); + if (hThread == NULL ) { + __set_errno(EAGAIN); + return -1; + } + return (unsigned long)hThread; +} +void _endthread(void) +{ + //fixme ExitThread + //ExitThread(0); + for(;;); +} diff --git a/lib/crtdll/process/threadid.c b/lib/crtdll/process/threadid.c new file mode 100644 index 0000000..3b5c9aa --- /dev/null +++ b/lib/crtdll/process/threadid.c @@ -0,0 +1,12 @@ +#include +#include + +unsigned long __threadid (void) +{ + return GetCurrentThreadId(); +} + +void *__threadhandle(void) +{ + return GetCurrentThread(); +} diff --git a/lib/crtdll/quad/.cvsignore b/lib/crtdll/quad/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/quad/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/quad/divdi3.c b/lib/crtdll/quad/divdi3.c new file mode 100644 index 0000000..e0f375e --- /dev/null +++ b/lib/crtdll/quad/divdi3.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include + +/* + * Divide two signed quads. + * ??? if -1/2 should produce -1 on this machine, this code is wrong + */ +quad_t +__divdi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, uq; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + uq = __qdivrem(ua, ub, (u_quad_t *)0); + return (neg ? -uq : uq); +} + + + diff --git a/lib/crtdll/quad/moddi3.c b/lib/crtdll/quad/moddi3.c new file mode 100644 index 0000000..272461e --- /dev/null +++ b/lib/crtdll/quad/moddi3.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include + +/* + * Return remainder after dividing two signed quads. + * + * XXX + * If -1/2 should produce -1 on this machine, this code is wrong. + */ +quad_t +__moddi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, ur; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + (void)__qdivrem(ua, ub, &ur); + return (neg ? -ur : ur); +} \ No newline at end of file diff --git a/lib/crtdll/quad/qdivrem.c b/lib/crtdll/quad/qdivrem.c new file mode 100644 index 0000000..06f827a --- /dev/null +++ b/lib/crtdll/quad/qdivrem.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), + * section 4.3.1, pp. 257--259. + */ + +#include + +#define B (1 << HALF_BITS) /* digit base */ + +/* Combine two `digits' to make a single two-digit number. */ +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: use unsigned short if they fit */ +//#if (ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff) +//typedef unsigned short digit; +//#else +typedef u_long digit; +//#endif + +/* + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that + * `fall out' the left (there never will be any such anyway). + * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. + */ +static void +shl(register digit *p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + p[i] = LHALF(p[i] << sh); +} + +/* + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. + * + * We do this in base 2-sup-HALF_BITS, so that all intermediate products + * fit within u_long. As a consequence, the maximum length dividend and + * divisor are 4 `digits' in this base (they are shorter if they have + * leading zeros). + */ +u_quad_t +__qdivrem(uq, vq, arq) + u_quad_t uq, vq, *arq; +{ + union uu tmp; + digit *u, *v, *q; + register digit v1, v2; + u_long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + *arq = uq; + return (tmp.q); + } + if (uq < vq) { + if (arq) + *arq = uq; + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) { + if (--n == 1) { + u_long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + *arq = rbj % t; + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + m--; + for (i = 4 - m; --i >= 0;) + q[i] = 0; + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + d++; + if (d > 0) { + shl(&u[0], m + n, d); /* u <<= d */ + shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } else { + u_long n = COMBINE(uj0, uj1); + qhat = n / v1; + rhat = n % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + break; + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) { + qhat--; + for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) { + if (d) { + for (i = m + n; i > m; --i) + u[i] = (u[i] >> d) | + LHALF(u[i - 1] << (HALF_BITS - d)); + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); +} + + + + diff --git a/lib/crtdll/quad/udivdi3.c b/lib/crtdll/quad/udivdi3.c new file mode 100644 index 0000000..224e8a2 --- /dev/null +++ b/lib/crtdll/quad/udivdi3.c @@ -0,0 +1,52 @@ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include + +/* + * Divide two unsigned quads. + */ +u_quad_t +__udivdi3(a, b) + u_quad_t a, b; +{ + + return (__qdivrem(a, b, (u_quad_t *)0)); +} diff --git a/lib/crtdll/quad/umoddi3.c b/lib/crtdll/quad/umoddi3.c new file mode 100644 index 0000000..7843805 --- /dev/null +++ b/lib/crtdll/quad/umoddi3.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include + +/* + * Return remainder after dividing two unsigned quads. + */ +u_quad_t +__umoddi3(a, b) + u_quad_t a, b; +{ + u_quad_t r; + + (void)__qdivrem(a, b, &r); + return (r); +} + diff --git a/lib/crtdll/search/.cvsignore b/lib/crtdll/search/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/search/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/search/lfind.c b/lib/crtdll/search/lfind.c new file mode 100644 index 0000000..1569735 --- /dev/null +++ b/lib/crtdll/search/lfind.c @@ -0,0 +1,17 @@ +#include +#include + + +void *_lfind(const void *key, const void *base, size_t *nelp, + size_t width, int (*compar)(const void *, const void *)) +{ + char *char_base = (char *)base; + int i; + for(i=0;i<*nelp;i++) { + if ( compar(key,char_base) == 0) + return char_base; + char_base += width; + } + return NULL; +} + diff --git a/lib/crtdll/search/lsearch.c b/lib/crtdll/search/lsearch.c new file mode 100644 index 0000000..f388d07 --- /dev/null +++ b/lib/crtdll/search/lsearch.c @@ -0,0 +1,16 @@ +#include +#include +#include + +void *_lsearch(const void *key, void *base, size_t *nelp, size_t width, + int (*compar)(const void *, const void *)) +{ + void *ret_find = _lfind(key,base,nelp,width,compar); + if ( ret_find != NULL ) + return ret_find; + + memcpy( base + (*nelp*width), key, width ); + (*nelp)++; + return base ; +} + diff --git a/lib/crtdll/setjmp/.cvsignore b/lib/crtdll/setjmp/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/setjmp/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/setjmp/setjmp.c b/lib/crtdll/setjmp/setjmp.c new file mode 100644 index 0000000..dc0d5fa --- /dev/null +++ b/lib/crtdll/setjmp/setjmp.c @@ -0,0 +1,143 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* modified by Boudewijn Dekker */ +/* ms uses a smaller jmp_buf structure */ +/* might do a realloc in setjmp */ + +typedef struct { + unsigned int __eax, __ebx, __ecx, __edx, __esi; + unsigned int __edi, __ebp, __esp, __eip, __eflags; + unsigned short __cs, __ds, __es, __fs, __gs, __ss; + unsigned long __sigmask; /* for POSIX signals only */ + unsigned long __signum; /* for expansion */ + unsigned long __exception_ptr; /* pointer to previous exception */ + unsigned char __fpu_state[108]; /* for future use */ +} jmp_buf[1]; + + +/* jumps back to position specified in jmp_buf */ + +int longjmp( jmp_buf env, int value ) +{ + //push ebp generated by the compiler + //mov ebp, esp + + __asm__ __volatile__ ( + "movl 8(%ebp),%edi\n\t" /* get jmp_buf */ + "movl 12(%ebp),%eax\n\t" /* store retval in j->eax */ + "movl %eax,0(%edi)\n\t" + + "movw 46(%edi),%fs\n\t" + "movw 48(%edi),%gs\n\t" + "movl 4(%edi),%ebx\n\t" + "movl 8(%edi),%ecx\n\t" + "movl 12(%edi),%edx\n\t" + "movl 24(%edi),%ebp\n\t" + + /* Now for some uglyness. The jmp_buf structure may be ABOVE the + point on the new SS:ESP we are moving to. We don't allow overlap, + but do force that it always be valid. We will use ES:ESI for + our new stack before swapping to it. */ + + "movw 50(%edi),%es\n\t" + "movl 28(%edi),%esi\n\t" + "subl $28,%esi\n\t" /* We need 7 working longwords on stack */ + + "movl 60(%edi),%eax\n\t" + "es\n\t" + "movl %eax,(%esi)\n\t" /* Exception pointer */ + + "movzwl 42(%edi),%eax\n\t" + "es\n\t" + "movl %eax,4(%esi)\n\t" /* DS */ + + "movl 20(%edi),%eax\n\t" + "es\n\t" + "movl %eax,8(%esi)\n\t" /* EDI */ + + "movl 16(%edi),%eax\n\t" + "es\n\t" + "movl %eax,12(%esi)\n\t" /* ESI */ + + "movl 32(%edi),%eax\n\t" + "es\n\t" + "movl %eax,16(%esi)\n\t" /* EIP - start of IRET frame */ + + "movl 40(%edi),%eax\n\t" + "es\n\t" + "movl %eax,20(%esi)\n\t" /* CS */ + + "movl 36(%edi),%eax\n\t" + "es\n\t" + "movl %eax,24(%esi)\n\t" /* EFLAGS */ + + "movl 0(%edi),%eax\n\t" + "movw 44(%edi),%es\n\t" + + "movw 50(%edi),%ss\n\t" + "movl %esi,%esp\n\t" + + //"popl ___djgpp_exception_state_ptr\n\t" + "popl %edi\n\t" // dummy popl instead of djgpp_exception_state_ptr + "popl %ds\n\t" + "popl %edi\n\t" + "popl %esi\n\t" + + "iret\n\t" /* actually jump to new cs:eip loading flags */ + ); + + return value; // dummy return never reached +} + + + +int _setjmp( jmp_buf env ) +{ + //push ebp generated by the compiler + //mov ebp, esp + + __asm__ __volatile__ ( + + "pushl %edi\n\t" + "movl 8(%ebp),%edi\n\t" + + "movl %eax, (%edi)\n\t" + "movl %ebx,4(%edi)\n\t" + "movl %ecx,8(%edi)\n\t" + "movl %edx,12(%edi)\n\t" + "movl %esi,16(%edi)\n\t" + + "movl -4(%ebp),%eax\n\t" + "movl %eax,20(%edi)\n\t" + + "movl (%ebp),%eax\n\t" + "movl %eax,24(%edi)\n\t" + + "movl %esp,%eax\n\t" + "addl $12,%eax\n\t" + "movl %eax,28(%edi)\n\t" + + "movl 4(%ebp),%eax\n\t" + "movl %eax,32(%edi)\n\t" + + "pushfl\n\t" + "popl 36(%edi)\n\t" + + "movw %cs, 40(%edi)\n\t" + "movw %ds, 42(%edi)\n\t" + "movw %es, 44(%edi)\n\t" + "movw %fs, 46(%edi)\n\t" + "movw %gs, 48(%edi)\n\t" + "movw %ss, 50(%edi)\n\t" + + //movl ___djgpp_exception_state_ptr, %eax + //movl %eax, 60(%edi) + + "popl %edi\n\t" + ); + + + + + + return 0; +} diff --git a/lib/crtdll/signal/.cvsignore b/lib/crtdll/signal/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/signal/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/signal/signal.c b/lib/crtdll/signal/signal.c new file mode 100644 index 0000000..2e221f4 --- /dev/null +++ b/lib/crtdll/signal/signal.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +void _default_handler(int signal); + +typedef struct _sig_element +{ + int signal; + char *signame; + _p_sig_fn_t handler; +} sig_element; + +static sig_element signal_list[SIGMAX] = + { + { 0, "Signal 0", SIG_DFL }, + { SIGABRT, "Aborted",SIG_DFL }, + { SIGFPE, "Erroneous arithmetic operation",SIG_DFL }, + { SIGILL, "Illegal instruction",SIG_DFL }, + { SIGINT, "Interrupt",SIG_DFL }, + { SIGSEGV, "Invalid access to storage",SIG_DFL }, + { SIGTERM, "Terminated",SIG_DFL }, + { SIGHUP, "Hangup",SIG_DFL }, + { SIGQUIT, "Quit",SIG_DFL }, + { SIGPIPE, "Broken pipe",SIG_DFL }, + { SIGKILL, "Killed",SIG_DFL }, + { SIGALRM, "Alarm clock",SIG_DFL }, + { 0, "Stopped (signal)",SIG_DFL }, + { 0, "Stopped",SIG_DFL }, + { 0, "Continued",SIG_DFL }, + { 0, "Child exited",SIG_DFL }, + { 0, "Stopped (tty input)",SIG_DFL }, + { 0, "Stopped (tty output)",SIG_DFL }, + { 0, NULL, SIG_DFL } + }; + +int nsignal = 21; + +_p_sig_fn_t signal(int sig, _p_sig_fn_t func) +{ + _p_sig_fn_t temp; + int i; + if(sig <= 0 || sig > SIGMAX || sig == SIGKILL) + { + __set_errno(EINVAL); + return SIG_ERR; + } +// check with IsBadCodePtr + + if ( func < (_p_sig_fn_t)4096 ) { + __set_errno(EINVAL); + return SIG_ERR; + } + + for(i=0;i SIGMAX) + return -1; + for(i=0;i + + +int _XcptFilter ( + DWORD ExceptionCode, + struct _EXCEPTION_POINTERS * ExceptionInfo + ) +{ + //fixme XcptFilter +// return UnhandledExceptionFilter(ExceptionInfo); +} diff --git a/lib/crtdll/signal/xcptinfo.c b/lib/crtdll/signal/xcptinfo.c new file mode 100644 index 0000000..d32f760 --- /dev/null +++ b/lib/crtdll/signal/xcptinfo.c @@ -0,0 +1,6 @@ +#include + +void **__pxcptinfoptrs (void) +{ + return NULL; +} diff --git a/lib/crtdll/stdio/.cvsignore b/lib/crtdll/stdio/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/stdio/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/stdio/FILE.DOC b/lib/crtdll/stdio/FILE.DOC new file mode 100644 index 0000000..a436732 --- /dev/null +++ b/lib/crtdll/stdio/FILE.DOC @@ -0,0 +1,43 @@ +meaning of struct FILE* members + +int _cnt; + +W: number of empty slots left in the buffer. +R: number of characters left in the buffer. + +char *_ptr; + +pointer inside the buffer we're using. +R: points to next character to read out. +W: points to next cell to put character in. + +char *_base; + +pointer to the start of the buffer we're using. + +int _bufsiz; + +size of the buffer + +int _flag; + +_IORW file is used for both read and write +_IOWRT file is opened for write +_IOREAD file is opened for read +_IOMYBUF buffer needs to be freed +_IOEOF file is at EOF +_IOERR error occurred +_IOSTRG sprintf +_IOAPPEND append mode +_IORMONCL remove file on close +_IOUNGETC buffer contents does not correspond to file + +int _file; + +dos file descriptor + +char *_name_to_remove; + +If nonzero, the named file is removed when the file is fclosed. + + diff --git a/lib/crtdll/stdio/allocfil.c b/lib/crtdll/stdio/allocfil.c new file mode 100644 index 0000000..b0f9e64 --- /dev/null +++ b/lib/crtdll/stdio/allocfil.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + + +FILE * __alloc_file(void); + +char __validfp (FILE *f) +{ + if ( (unsigned int)f < 256) + return FALSE; + + if( f == NULL || (int)f== -1 ) + return FALSE; + + return TRUE; +} + +/* A FILE* is considered "free" if its flag is zero. */ + +FILE *__alloc_file(void) +{ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + FILE *rv=0; + int i; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) + { + if (fr->files[i]->_flag == 0) + { + return fr->files[i]; + } + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + if (!fr) + { + /* add another one to the end, make it empty */ + fr = *last_fr = (__file_rec *)malloc(sizeof(__file_rec)); + if (fr == 0) + return 0; + fr->next = 0; + fr->count = 0; + } + /* fr is a pointer to a rec with empty slots in it */ + rv = fr->files[fr->count] = (FILE *)malloc(sizeof(FILE)); + if (rv == 0) + return 0; + memset(rv, 0, sizeof(FILE)); + fr->count ++; + return rv; +} + + +int _fcloseall( void ) +{ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + + int total_closed = 0; + int i = 0; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) + if (fr->files[i]->_flag != 0) { + fclose(fr->files[i]); + total_closed++; + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + return total_closed; +} diff --git a/lib/crtdll/stdio/clearerr.c b/lib/crtdll/stdio/clearerr.c new file mode 100644 index 0000000..0543ed0 --- /dev/null +++ b/lib/crtdll/stdio/clearerr.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +#ifdef clearerr +#undef clearerr +void clearerr(FILE *stream); +#endif + +void +clearerr(FILE *f) +{ + if (!__validfp (f)) { + __set_errno (EINVAL); + return; + } + f->_flag &= ~(_IOERR|_IOEOF); +} diff --git a/lib/crtdll/stdio/doscan.c b/lib/crtdll/stdio/doscan.c new file mode 100644 index 0000000..a14f773 --- /dev/null +++ b/lib/crtdll/stdio/doscan.c @@ -0,0 +1,409 @@ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + + +#define atold atof + +// dubious variable +//static int _fltused = 0; + +int +_doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), + const char *fmt, va_list argp); + +//#include + +#define SPC 01 +#define STP 02 + +#define SHORT 0 +#define REGULAR 1 +#define LONG 2 +#define LONGDOUBLE 4 +#define INT 0 +#define FLOAT 1 + + + +static int _innum(int **ptr, int type, int len, int size, FILE *iop, + int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), + int *eofptr); +static int _instr(char *ptr, int type, int len, FILE *iop, + int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), + int *eofptr); +static const char *_getccl(const unsigned char *s); + +static char _sctab[256] = { + 0,0,0,0,0,0,0,0, + 0,SPC,SPC,SPC,SPC,SPC,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + SPC,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, +}; + +static int nchars = 0; + +int +_doscan(FILE *iop, const char *fmt, va_list argp) +{ + return(_doscan_low(iop, fgetc, ungetc, fmt, argp)); +} + +int +_dowscan(FILE *iop, const wchar_t *fmt, va_list argp) +{ + return(_doscan_low(iop, fgetwc, ((void *)ungetwc), ((void *)fmt), argp)); +} + +int +_doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), + const char *fmt, va_list argp) +{ + register int ch; + int nmatch, len, ch1; + int **ptr, fileended, size; + + nchars = 0; + nmatch = 0; + fileended = 0; + for (;;) switch (ch = *fmt++) { + case '\0': + return (nmatch); + case '%': + if ((ch = *fmt++) == '%') + goto def; + ptr = 0; + if (ch != '*') + ptr = va_arg(argp, int **); + else + ch = *fmt++; + len = 0; + size = REGULAR; + while (isdigit(ch)) { + len = len*10 + ch - '0'; + ch = *fmt++; + } + if (len == 0) + len = 30000; + + if (ch=='l') + { + size = LONG; + ch = *fmt++; + if (ch=='l') + { + size = LONGDOUBLE; /* for long long 'll' format */ + ch = *fmt++; + } + } + else if (ch=='h') { + size = SHORT; + ch = *fmt++; + } else if (ch=='L') { + size = LONGDOUBLE; + ch = *fmt++; + } else if (ch=='[') + fmt = _getccl((const unsigned char *)fmt); + if (isupper(ch)) { + /* ch = tolower(ch); + gcc gives warning: ANSI C forbids braced + groups within expressions */ + ch += 'a' - 'A'; + if (size==LONG) + size = LONGDOUBLE; + else if (size != LONGDOUBLE) + size = LONG; + } + if (ch == '\0') + return(-1); + + if (ch == 'n') + { + if (!ptr) + break; + if (size==LONG) + **(long**)ptr = nchars; + else if (size==SHORT) + **(short**)ptr = nchars; + else if (size==LONGDOUBLE) + **(long**)ptr = nchars; + else + **(int**)ptr = nchars; + break; + } + + if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc, + &fileended)) + { + if (ptr) + nmatch++; + } + else + { + if (fileended && nmatch==0) + return(-1); + return(nmatch); + } + break; + case ' ': + case '\n': + case '\t': + case '\r': + case '\f': + case '\v': + while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC)) + ; + if (ch1 != EOF) + { + scan_ungetc(ch1, iop); + } + nchars--; + break; + + default: + def: + ch1 = scan_getc(iop); + if (ch1 != EOF) nchars++; + if (ch1 != ch) { + if (ch1==EOF) + return(nmatch? nmatch: -1); + scan_ungetc(ch1, iop); + nchars--; + return(nmatch); + } + } +} + +static int +_innum(int **ptr, int type, int len, int size, FILE *iop, + int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr) +{ + register char *np; + char numbuf[64]; + register int c, base; + int expseen, scale, negflg, c1, ndigit; + long lcval; + int cpos; + + if (type=='c' || type=='s' || type=='[') + return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, + iop, scan_getc, scan_ungetc, eofptr)); + lcval = 0; + ndigit = 0; + scale = INT; + if (type=='e'||type=='f'||type=='g') + scale = FLOAT; + base = 10; + if (type=='o') + base = 8; + else if (type=='x') + base = 16; + np = numbuf; + expseen = 0; + negflg = 0; + while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC) ) + ; + if (c == EOF) nchars--; + if (c=='-') { + negflg++; + *np++ = c; + c = scan_getc(iop); + nchars++; + len--; + } else if (c=='+') { + len--; + c = scan_getc(iop); + nchars++; + } + cpos = 0; + for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) { + cpos++; + if (c == '0' && cpos == 1 && type == 'i') + base = 8; + if ((c == 'x' || c == 'X') && (type == 'i' || type == 'x') + && cpos == 2 && lcval == 0) + { + base = 16; + continue; + } + if (isdigit(c) + || (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) { + ndigit++; + if (base==8) + lcval <<=3; + else if (base==10) + lcval = ((lcval<<2) + lcval)<<1; + else + lcval <<= 4; + c1 = c; + if (isdigit(c)) + c -= '0'; + else if ('a'<=c && c<='f') + c -= 'a'-10; + else + c -= 'A'-10; + lcval += c; + c = c1; + continue; + } else if (c=='.') { + if (base!=10 || scale==INT) + break; + ndigit++; + continue; + } else if ((c=='e'||c=='E') && expseen==0) { + if (base!=10 || scale==INT || ndigit==0) + break; + expseen++; + *np++ = c; + c = scan_getc(iop); + nchars++; + if (c!='+'&&c!='-'&&('0'>c||c>'9')) + break; + } else + break; + } + if (negflg) + lcval = -lcval; + if (c != EOF) { + scan_ungetc(c, iop); + *eofptr = 0; + } else + *eofptr = 1; + nchars--; + if (np==numbuf || (negflg && np==numbuf+1) ) /* gene dykes*/ + return(0); + if (ptr==NULL) + return(1); + *np++ = 0; + switch((scale<<4) | size) { + + case (FLOAT<<4) | SHORT: + case (FLOAT<<4) | REGULAR: + **(float **)ptr = (float)atof(numbuf); + break; + + case (FLOAT<<4) | LONG: + **(double **)ptr = atof(numbuf); + break; + + case (FLOAT<<4) | LONGDOUBLE: + **(long double **)ptr = atold(numbuf); + break; + + case (INT<<4) | SHORT: + **(short **)ptr = (short)lcval; + break; + + case (INT<<4) | REGULAR: + **(int **)ptr = (int)lcval; + break; + + case (INT<<4) | LONG: + **(long **)ptr = lcval; + break; + + case (INT<<4) | LONGDOUBLE: + **(long **)ptr = lcval; + break; + } + return(1); +} + +static int +_instr(char *ptr, int type, int len, FILE *iop, + int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr) +{ + register int ch; + register char *optr; + int ignstp; + + *eofptr = 0; + optr = ptr; + if (type=='c' && len==30000) + len = 1; + ignstp = 0; + if (type=='s') + ignstp = SPC; + while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp) + ; + ignstp = SPC; + if (type=='c') + ignstp = 0; + else if (type=='[') + ignstp = STP; + while (ch!=EOF && (_sctab[ch]&ignstp)==0) { + if (ptr) + *ptr++ = ch; + if (--len <= 0) + break; + ch = scan_getc(iop); + nchars++; + } + if (ch != EOF) { + if (len > 0) + { + scan_ungetc(ch, iop); + nchars--; + } + *eofptr = 0; + } else + { + nchars--; + *eofptr = 1; + } + if (!ptr) + return(1); + if (ptr!=optr) { + if (type!='c') + *ptr++ = '\0'; + return(1); + } + return(0); +} + +static const char * +_getccl(const unsigned char *s) +{ + register int c, t; + + t = 0; + if (*s == '^') { + t++; + s++; + } + for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) + if (t) + _sctab[c] &= ~STP; + else + _sctab[c] |= STP; + if ((c = *s) == ']' || c == '-') { /* first char is special */ + if (t) + _sctab[c] |= STP; + else + _sctab[c] &= ~STP; + s++; + } + while ((c = *s++) != ']') { + if (c==0) + return((const char *)--s); + else if (c == '-' && *s != ']' && s[-2] < *s) { + for (c = s[-2] + 1; c < *s; c++) + if (t) + _sctab[c] |= STP; + else + _sctab[c] &= ~STP; + } else if (t) + _sctab[c] |= STP; + else + _sctab[c] &= ~STP; + } + return((const char *)s); +} diff --git a/lib/crtdll/stdio/fclose.c b/lib/crtdll/stdio/fclose.c new file mode 100644 index 0000000..1b141c5 --- /dev/null +++ b/lib/crtdll/stdio/fclose.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + +// changed check for writable stream + + +int +fclose(FILE *f) +{ + int r = 0; + + if (f == NULL) { + __set_errno (EINVAL); + return EOF; + } + + + +// flush only if stream was opened for writing + if ( !(f->_flag&_IOSTRG) ) { + if ( OPEN4WRITING(f) ) + r = fflush(f); + + if (_close(fileno(f)) < 0) + r = EOF; + if (f->_flag&_IOMYBUF) + free(f->_base); + +// Kernel might do this later + if (f->_flag & _IORMONCL && f->_name_to_remove) + { + remove(f->_name_to_remove); + free(f->_name_to_remove); + f->_name_to_remove = 0; + } + } + f->_cnt = 0; + f->_base = 0; + f->_ptr = 0; + f->_bufsiz = 0; + f->_flag = 0; + f->_file = -1; + return r; +} diff --git a/lib/crtdll/stdio/fdopen.c b/lib/crtdll/stdio/fdopen.c new file mode 100644 index 0000000..2427466 --- /dev/null +++ b/lib/crtdll/stdio/fdopen.c @@ -0,0 +1,62 @@ +#include +#include + +FILE * __alloc_file(void); + +FILE *_fdopen(int handle, char *mode) +{ + FILE *file; + int rw; + + if ( handle == 0 ) + return stdin; + + if ( handle == 1 ) + return stdout; + + if ( handle == 2 ) + return stderr; + + if ( handle == 3 ) + return stdaux; + + if ( handle == 4 ) + return stdprn; + + file = __alloc_file(); + if (file == NULL) + return NULL; + file->_file = handle; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + if (*mode == 'a') + _lseek(handle, 0, SEEK_END); + + file->_cnt = 0; + file->_file = handle; + file->_bufsiz = 0; + +// The mode of the stream must be compatible with the mode of the file descriptor. +// this should be checked. + + if (rw) + file->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + file->_flag = _IOREAD; + else + file->_flag = _IOWRT; + + file->_base = file->_ptr = NULL; + return file; +} + + + + + + + + + + diff --git a/lib/crtdll/stdio/feof.c b/lib/crtdll/stdio/feof.c new file mode 100644 index 0000000..8f6f01f --- /dev/null +++ b/lib/crtdll/stdio/feof.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +#ifdef feof +#undef feof +int feof(FILE *stream); +#endif + +int feof(FILE *stream) +{ + if (stream == NULL) { + __set_errno (EINVAL); + return EOF; + } + + return stream->_flag & _IOEOF; +} diff --git a/lib/crtdll/stdio/ferror.c b/lib/crtdll/stdio/ferror.c new file mode 100644 index 0000000..06d77c1 --- /dev/null +++ b/lib/crtdll/stdio/ferror.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#ifdef ferror +#undef ferror +int ferror(FILE *stream); +#endif + +int ferror(FILE *stream) +{ + return stream->_flag & _IOERR; +} diff --git a/lib/crtdll/stdio/fflush.c b/lib/crtdll/stdio/fflush.c new file mode 100644 index 0000000..0dc66f2 --- /dev/null +++ b/lib/crtdll/stdio/fflush.c @@ -0,0 +1,111 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + + +int fflush(FILE *f) +{ + char *base; + int n, rn; + + + + if (f == NULL) + { + int e = errno; + + __set_errno(0); + _fwalk((void (*)(FILE *))fflush); + if (_errno) + return EOF; + __set_errno(e); + return 0; + } + + +// nothing to do if stream can not be written to + + if ( !OPEN4WRITING(f) ) { + __set_errno (EINVAL); + return 0; + } + +// discard any unget characters + + f->_flag &= ~_IOUNGETC; + + +// check for buffered dirty block + + if ( (f->_flag&(_IODIRTY|_IONBF)) ==_IODIRTY && f->_base != NULL) + { + + base = f->_base; + + +// if the buffer is read ahead and dirty we will flush it entirely +// else the buffer is appended to the file to the extend it has valid bytes + + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + rn = n = f->_ptr - base + f->_cnt; + else + rn = n = f->_ptr - base; + + f->_ptr = base; + + if ((f->_flag & _IOFBF) == _IOFBF) { + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + _lseek(fileno(f),-rn, SEEK_CUR); + } + + f->_flag &= ~_IOAHEAD; + + + f->_cnt = (f->_flag&(_IOLBF|_IONBF)) ? 0 : f->_bufsiz; + +// how can write return less than rn without being on error ??? + +// possibly commit the flushed data +// better open the file in write through mode + + do { + n = _write(fileno(f), base, rn); + if (n <= 0) { + f->_flag |= _IOERR; + return EOF; + } + rn -= n; + base += n; + } while (rn > 0); + f->_flag &= ~_IODIRTY; + + } + if (OPEN4READING(f) && OPEN4WRITING(f) ) + { + f->_cnt = 0; + f->_ptr = f->_base; + } + return 0; +} + +int _flushall( void ) +{ + return fflush(NULL); +} diff --git a/lib/crtdll/stdio/fgetc.c b/lib/crtdll/stdio/fgetc.c new file mode 100644 index 0000000..33ed518 --- /dev/null +++ b/lib/crtdll/stdio/fgetc.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdio/fgetc.c + * PURPOSE: Get a character string from stdin + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Appropriated for Reactos + 25/02/99: Added fgetwc + */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +fgetc(FILE *f) +{ + return getc(f); +} + +wint_t +fgetwc(FILE *f) +{ + return getwc(f); +} diff --git a/lib/crtdll/stdio/fgetchar.c b/lib/crtdll/stdio/fgetchar.c new file mode 100644 index 0000000..392f7e2 --- /dev/null +++ b/lib/crtdll/stdio/fgetchar.c @@ -0,0 +1,13 @@ +#include +#include +#include + +int _fgetchar (void) +{ + return _getch(); +} + +int _fgetwchar (void) +{ + return _getch(); +} diff --git a/lib/crtdll/stdio/fgetpos.c b/lib/crtdll/stdio/fgetpos.c new file mode 100644 index 0000000..e063164 --- /dev/null +++ b/lib/crtdll/stdio/fgetpos.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +fgetpos(FILE *stream, fpos_t *pos) +{ + if (stream && pos) + { + *pos = (fpos_t)ftell(stream); + return 0; + } + //errno = EFAULT; + return 1; +} diff --git a/lib/crtdll/stdio/fgets.c b/lib/crtdll/stdio/fgets.c new file mode 100644 index 0000000..df78963 --- /dev/null +++ b/lib/crtdll/stdio/fgets.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +fgets(char *s, int n, FILE *f) +{ + int c=0; + char *cs; + + cs = s; + while (--n>0 && (c = getc(f)) != EOF) + { + *cs++ = c; + if (c == '\n') + break; + } + if (c == EOF && cs == s) + return NULL; + *cs++ = '\0'; + return s; +} diff --git a/lib/crtdll/stdio/filbuf.c b/lib/crtdll/stdio/filbuf.c new file mode 100644 index 0000000..b9b008a --- /dev/null +++ b/lib/crtdll/stdio/filbuf.c @@ -0,0 +1,131 @@ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int _readcnv(int fn, void *buf, size_t siz ); + +int +_filbuf(FILE *f) +{ + int size; + char c; + + + if ( !OPEN4READING(f)) { + __set_errno (EINVAL); + return EOF; + } + + + if (f->_flag&(_IOSTRG|_IOEOF)) + return EOF; + f->_flag &= ~_IOUNGETC; + + if (f->_base==NULL && (f->_flag&_IONBF)==0) { + size = 4096; + if ((f->_base = malloc(size+1)) == NULL) + { + // error ENOMEM + f->_flag |= _IONBF; + f->_flag &= ~(_IOFBF|_IOLBF); + } + else + { + f->_flag |= _IOMYBUF; + f->_bufsiz = size; + } + } + + + if (f->_flag&_IONBF) + f->_base = &c; + + +// fush stdout before reading from stdin + if (f == stdin) { + if (stdout->_flag&_IOLBF) + fflush(stdout); + if (stderr->_flag&_IOLBF) + fflush(stderr); + } + +// if we have a dirty stream we flush it + if ( (f->_flag &_IODIRTY) == _IODIRTY ) + fflush(f); + + + + f->_cnt = _read(fileno(f), f->_base, f->_flag & _IONBF ? 1 : f->_bufsiz ); + f->_flag |= _IOAHEAD; + + if(__is_text_file(f) && f->_cnt>0) + { + /* truncate text file at Ctrl-Z */ + char *cz=memchr(f->_base, 0x1A, f->_cnt); + if(cz) + { + int newcnt = cz - f->_base; + lseek(fileno(f), -(f->_cnt - newcnt), SEEK_CUR); + f->_cnt = newcnt; + } + } + + f->_ptr = f->_base; + + if (f->_flag & _IONBF) + f->_base = NULL; // statically allocated buffer for sprintf + + +//check for error + if (--f->_cnt < 0) { + if (f->_cnt == -1) { + f->_flag |= _IOEOF; + } else + f->_flag |= _IOERR; + f->_cnt = 0; + +// should set errno + + return EOF; + } + + f->_cnt--; + return *f->_ptr++ & 0377; +} + +wint_t _filwbuf(FILE *fp) +{ + return (wint_t )_filbuf(fp); +} + +// convert the carriage return line feed pairs + +int _readcnv(int fn, void *buf, size_t siz ) +{ + char *bufp = (char *)buf; + int _bufsiz = siz; + int cr = 0; + int n; + + n = _read(fn, buf, siz ); + + while (_bufsiz > 0) { + if (*bufp == '\r') + cr++; + else if ( cr != 0 ) + *bufp = *(bufp + cr); + bufp++; + _bufsiz--; + } + return n + cr; +} + diff --git a/lib/crtdll/stdio/fileno.c b/lib/crtdll/stdio/fileno.c new file mode 100644 index 0000000..f895187 --- /dev/null +++ b/lib/crtdll/stdio/fileno.c @@ -0,0 +1,13 @@ +#include + +#undef fileno +int fileno(FILE *f) +{ + return f->_file; +} + + +int _fileno(FILE *f) +{ + return f->_file; +} diff --git a/lib/crtdll/stdio/flsbuf.c b/lib/crtdll/stdio/flsbuf.c new file mode 100644 index 0000000..2a0feb6 --- /dev/null +++ b/lib/crtdll/stdio/flsbuf.c @@ -0,0 +1,179 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + +int cntcr(char *bufp, int bufsiz); +int convert(char *endp, int bufsiz,int n); +int _writecnv(int fn, void *buf, size_t bufsiz); + +int +_flsbuf(int c, FILE *f) +{ + char *base; + int n, rn; + char c1; + int size; + + + + if (!OPEN4WRITING(f)) { + __set_errno (EINVAL); + return EOF; + } + +// no file associated with buffer +// this is a memory stream + + if ( fileno(f) == -1 ) + return c; + + /* if the buffer is not yet allocated, allocate it */ + if ((base = f->_base) == NULL && (f->_flag & _IONBF) == 0) + { + size = 4096; + if ((f->_base = base = malloc (size)) == NULL) + { + f->_flag |= _IONBF; + f->_flag &= ~(_IOFBF|_IOLBF); + } + else + { + f->_flag |= _IOMYBUF; + f->_cnt = f->_bufsiz = size; + f->_ptr = base; + rn = 0; + if (f == stdout && isatty (fileno (stdout))) + f->_flag |= _IOLBF; + } + } + + if (f->_flag & _IOLBF) + { + /* in line-buffering mode we get here on each character */ + *f->_ptr++ = c; + rn = f->_ptr - base; + if (c == '\n' || rn >= f->_bufsiz) + { + /* time for real flush */ + f->_ptr = base; + f->_cnt = 0; + } + else + { + /* we got here because _cnt is wrong, so fix it */ + /* Negative _cnt causes all output functions + to call _flsbuf for each character, thus realizing line-buffering */ + f->_cnt = -rn; + return c; + } + } + else if (f->_flag & _IONBF) + { + c1 = c; + rn = 1; + base = &c1; + f->_cnt = 0; + } + else /* _IOFBF */ + { + rn = f->_ptr - base; + f->_ptr = base; + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + _lseek(fileno(f),-(rn+f->_cnt), SEEK_CUR); + f->_cnt = f->_bufsiz; + f->_flag &= ~_IOAHEAD; + } + + + + f->_flag &= ~_IODIRTY; + while (rn > 0) + { + n = _write(fileno(f), base, rn); + if (n <= 0) + { + f->_flag |= _IOERR; + return EOF; + } + rn -= n; + base += n; + } + + + if ((f->_flag&(_IOLBF|_IONBF)) == 0) + { + f->_cnt--; + *f->_ptr++ = c; + } + return c; +} + +wint_t _flswbuf(wchar_t c,FILE *fp) +{ + return (wint_t )_flsbuf((int)c,fp); +} + + +int _writecnv(int fn, void *buf, size_t siz) +{ + char *bufp = (char *)buf; + int bufsiz = siz; + + char *tmp; + int cr1 = 0; + int cr2 = 0; + + int n; + + + cr1 = cntcr(bufp,bufsiz); + + tmp = malloc(cr1); + memcpy(tmp,bufp+bufsiz-cr1,cr1); + cr2 = cntcr(tmp,cr1); + + convert(bufp,bufsiz-cr2,cr1-cr2); + n = _write(fn, bufp, bufsiz + cr1); + + convert(tmp,cr1,cr2); + n += _write(fn, tmp, cr1 + cr2); + free(tmp); + return n; + + +} + +int convert(char *endp, int bufsiz,int n) +{ + endp = endp + bufsiz + n; + while (bufsiz > 0) { + *endp = *(endp - n); + if (*endp == '\n') { + *endp--; + n--; + *endp = '\r'; + } + endp--; + bufsiz--; + } + return n; +} +int cntcr(char *bufp, int bufsiz) +{ + int cr = 0; + while (bufsiz > 0) { + if (*bufp == '\n') + cr++; + bufp++; + bufsiz--; + } + + return cr; +} diff --git a/lib/crtdll/stdio/fopen.c b/lib/crtdll/stdio/fopen.c new file mode 100644 index 0000000..9335cf2 --- /dev/null +++ b/lib/crtdll/stdio/fopen.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include + +//might change fopen(file,mode) -> fsopen(file,mode,_SH_DENYNO); + +FILE * __alloc_file(void); + + +FILE* fopen(const char *file, const char *mode) +{ + FILE *f; + int fd, rw, oflags = 0; + char tbchar; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + switch (*mode) + { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _open(file, oflags, 0666); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/lib/crtdll/stdio/fprintf.c b/lib/crtdll/stdio/fprintf.c new file mode 100644 index 0000000..9ac7b6b --- /dev/null +++ b/lib/crtdll/stdio/fprintf.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fprintf(register FILE *iop, const char *fmt, ...) +{ + int len; + char localbuf[BUFSIZ]; + va_list a=0; + + + va_start( a, fmt ); + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = localbuf; + iop->_bufsiz = BUFSIZ; + len = vfprintf(iop,fmt,a); + fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = vfprintf(iop, fmt, a); + return ferror(iop) ? EOF : len; +} + +int +fwprintf(register FILE *iop, const wchar_t *fmt, ...) +{ + int len; + wchar_t localbuf[BUFSIZ]; + va_list a=0; + + + va_start( a, fmt ); + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = (char *)localbuf; + iop->_bufsiz = BUFSIZ; + len = vfwprintf(iop,fmt,a); + fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = vfwprintf(iop, fmt, a); + return ferror(iop) ? EOF : len; +} diff --git a/lib/crtdll/stdio/fputc.c b/lib/crtdll/stdio/fputc.c new file mode 100644 index 0000000..c63635a --- /dev/null +++ b/lib/crtdll/stdio/fputc.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fputc(int c, FILE *fp) +{ + return putc(c, fp); +} + +wint_t +fputwc(wchar_t c, FILE *fp) +{ + return fputwc(c,fp); +} + diff --git a/lib/crtdll/stdio/fputchar.c b/lib/crtdll/stdio/fputchar.c new file mode 100644 index 0000000..235a085 --- /dev/null +++ b/lib/crtdll/stdio/fputchar.c @@ -0,0 +1,15 @@ +#include +#include +#include + +int _fputchar (int c) +{ + return _putch(c); +} + +int _fputwchar (wchar_t c) +{ + //return _putch(c); + return 0; +} + diff --git a/lib/crtdll/stdio/fputs.c b/lib/crtdll/stdio/fputs.c new file mode 100644 index 0000000..d8fbfff --- /dev/null +++ b/lib/crtdll/stdio/fputs.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +fputs(const char *s, FILE *f) +{ + + int r = 0; + int c; + int unbuffered; + char localbuf[BUFSIZ]; + + unbuffered = f->_flag & _IONBF; + if (unbuffered) + { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = localbuf; + f->_bufsiz = BUFSIZ; + } + + while ((c = *s++)) + r = putc(c, f); + + if (unbuffered) + { + fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } + + return(r); + +} diff --git a/lib/crtdll/stdio/fread.c b/lib/crtdll/stdio/fread.c new file mode 100644 index 0000000..c9f7238 --- /dev/null +++ b/lib/crtdll/stdio/fread.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + + +// carriage return line feed conversion is done in filbuf and flsbuf +#if 0 +size_t +fread(void *p, size_t size, size_t count, FILE *iop) +{ + char *ptr = (char *)p; + int to_read; + + to_read = size * count; + + + + while ( to_read > 0 ) { + *ptr = getc(iop) ; + if ( *ptr == EOF ) + break; + to_read--; + ptr++; + } + + + + return count- (to_read/size); +} + + +#else +size_t fread(void *vptr, size_t size, size_t count, FILE *iop) +{ + char *ptr = (char *)vptr; + size_t to_read ,n_read; + + to_read = size * count; + + if (!OPEN4READING(iop)) + { + __set_errno (EINVAL); + return 0; + } + + if (!__validfp (iop) ) + { + __set_errno (EINVAL); + return 0; + } + if (feof (iop) || ferror (iop)) + return 0; + + if (vptr == NULL || to_read == 0) + return 0; + + + while(iop->_cnt > 0 && to_read > 0 ) { + to_read--; + *ptr++ = getc(iop); + } + + // if the buffer is dirty it will have to be written now + // otherwise the file pointer won't match anymore. + + fflush(iop); + + // check to see if this will work with in combination with ungetc + + n_read = _read(fileno(iop), ptr, to_read); + if ( n_read != -1 ) + to_read -= n_read; + + // the file buffer is empty and there is no read ahead information anymore. + + iop->_flag &= ~_IOAHEAD; + + return count- (to_read/size); +} +#endif + diff --git a/lib/crtdll/stdio/freopen.c b/lib/crtdll/stdio/freopen.c new file mode 100644 index 0000000..13a60f1 --- /dev/null +++ b/lib/crtdll/stdio/freopen.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include + + + +FILE * +freopen(const char *file, const char *mode, FILE *f) +{ + int fd, rw, oflags=0; + char tbchar; + + if (file == 0 || mode == 0 || f == 0) + return 0; + + rw = (mode[1] == '+'); + + fclose(f); + + switch (*mode) { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return NULL; + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _open(file, oflags, 0666); + if (fd < 0) + return NULL; + + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/lib/crtdll/stdio/frlist.c b/lib/crtdll/stdio/frlist.c new file mode 100644 index 0000000..511d931 --- /dev/null +++ b/lib/crtdll/stdio/frlist.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +//#include +#include + + +static __file_rec __initial_file_rec = { + 0, + 5, + { &_iob[0], &_iob[1], &_iob[2], &_iob[3], &_iob[4] } +}; + +__file_rec *__file_rec_list = &__initial_file_rec; diff --git a/lib/crtdll/stdio/fscanf.c b/lib/crtdll/stdio/fscanf.c new file mode 100644 index 0000000..f8f33e7 --- /dev/null +++ b/lib/crtdll/stdio/fscanf.c @@ -0,0 +1,60 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +#include +#include +#include +#include + + +int __vfscanf (FILE *s, const char *format, va_list argptr); +/* Read formatted input from STREAM according to the format string FORMAT. */ +/* VARARGS2 */ +int fscanf(FILE *stream,const char *format, ...) +{ + va_list arg; + int done; + + va_start(arg, format); + done = __vfscanf(stream, format, arg); + va_end(arg); + + return done; +} + +int +fwscanf(FILE *stream, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + char *cf; + int i,len = wcslen(fmt); + + cf = malloc(len+1); + for(i=0;i +#include +#include +#include +#include + + +int fseek(FILE *f, long offset, int ptrname) +{ + long p = -1; /* can't happen? */ + if ( f == NULL ) { + __set_errno (EINVAL); + return -1; + } + + f->_flag &= ~_IOEOF; + if (!OPEN4WRITING(f)) + { + if (f->_base && !(f->_flag & _IONBF)) + { + p = ftell(f); + if (ptrname == SEEK_CUR) + { + offset += p; + ptrname = SEEK_SET; + } + /* check if the target position is in the buffer and + optimize seek by moving inside the buffer */ + if (ptrname == SEEK_SET && (f->_flag & (_IOUNGETC|_IOREAD|_IOWRT )) == 0 + && p-offset <= f->_ptr-f->_base && offset-p <= f->_cnt) + { + f->_ptr+=offset-p; + f->_cnt+=p-offset; + return 0; + } + } + + + p = lseek(fileno(f), offset, ptrname); + f->_cnt = 0; + f->_ptr = f->_base; + f->_flag &= ~_IOUNGETC; + } + else + { + p = fflush(f); + return lseek(fileno(f), offset, ptrname) == -1 || p == EOF ? + -1 : 0; + } + return p==-1 ? -1 : 0; + +} diff --git a/lib/crtdll/stdio/fsetpos.c b/lib/crtdll/stdio/fsetpos.c new file mode 100644 index 0000000..718bb6e --- /dev/null +++ b/lib/crtdll/stdio/fsetpos.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fsetpos(FILE *stream,const fpos_t *pos) +{ + if (stream && pos) + { + fseek(stream, (long)(*pos), SEEK_SET); + return 0; + } + __set_errno(EFAULT); + return -1; +} diff --git a/lib/crtdll/stdio/fsopen.c b/lib/crtdll/stdio/fsopen.c new file mode 100644 index 0000000..9c14819 --- /dev/null +++ b/lib/crtdll/stdio/fsopen.c @@ -0,0 +1,101 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include + + +FILE * __alloc_file(void); + + +FILE* _fsopen(const char *file, const char *mode, int shflag) +{ + FILE *f; + int fd, rw, oflags = 0; + char tbchar; + + int shf; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + switch (*mode) + { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + + + if ( shflag == _SH_DENYNO ) + shf = _S_IREAD | _S_IWRITE; + else if( shflag == _SH_DENYRD ) + shf = _S_IWRITE; + else if( shflag == _SH_DENYRW ) + shf = 0; + else if( shflag == _SH_DENYWR ) + shf = _S_IREAD; + else + shf = _S_IREAD | _S_IWRITE; + + fd = _open(file, oflags, shf); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/lib/crtdll/stdio/ftell.c b/lib/crtdll/stdio/ftell.c new file mode 100644 index 0000000..deb4bbd --- /dev/null +++ b/lib/crtdll/stdio/ftell.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +//#include +#include +//#include +#include +#include +#include +#include + + +long +ftell(FILE *f) +{ + long tres; + int adjust=0; + + if (!f) + { + __set_errno(EBADF); + return -1; + } + + if (f->_cnt < 0) + f->_cnt = 0; + + else if (f->_flag&_IOREAD) + { + adjust = - f->_cnt; + } + else if (f->_flag&(_IOWRT)) + { + if (f->_base && (f->_flag&_IONBF)==0) + adjust = f->_ptr - f->_base; + } + + else + return -1; + tres = lseek(fileno(f), 0L, SEEK_CUR); + if (tres<0) + return tres; + tres += adjust; + + //f->_cnt = f->_bufsiz - tres; + //f->_ptr = f->_base + tres; + return tres; +} diff --git a/lib/crtdll/stdio/fwalk.c b/lib/crtdll/stdio/fwalk.c new file mode 100644 index 0000000..11be7eb --- /dev/null +++ b/lib/crtdll/stdio/fwalk.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +// not exported by crtdll +__file_rec *__file_rec_list; + +void +_fwalk(void (*func)(FILE *)) +{ + __file_rec *fr; + int i; + + for (fr=__file_rec_list; fr; fr=fr->next) + for (i=0; icount; i++) + if (fr->files[i]->_flag) + func(fr->files[i]); +} diff --git a/lib/crtdll/stdio/fwrite.c b/lib/crtdll/stdio/fwrite.c new file mode 100644 index 0000000..7796416 --- /dev/null +++ b/lib/crtdll/stdio/fwrite.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +#if 0 +size_t +fwrite(const void *p, size_t size, size_t count, FILE *iop) +{ + char *ptr = (char *)p; + size_t to_write; + + + to_write = size * count; + + + + while ( to_write > 0 ) { + if ( putc(*ptr,iop) == EOF ) + break; + to_write--; + ptr++; + } + + + + return count -to_write/size; + +} + + +#else +size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop) + { + size_t to_write, n_written; + char *ptr = (char *)vptr; + + to_write = size*count; + if (!OPEN4WRITING(iop) ) + { + __set_errno (EINVAL); + return 0; + } + + + if (iop == NULL ) + { + __set_errno (EINVAL); + return 0; + } + + if (ferror (iop)) + return 0; + if (vptr == NULL || to_write == 0) + return 0; + + + while(iop->_cnt > 0 && to_write > 0 ) { + to_write--; + putc(*ptr++,iop); + } + + // if the buffer is dirty it will have to be written now + // otherwise the file pointer won't match anymore. + + fflush(iop); + + n_written = _write(fileno(iop), ptr,to_write); + if ( n_written != -1 ) + to_write -= n_written; + + // check to see if this will work with in combination with ungetc + + + // the file buffer is empty and there is no read ahead information anymore. + + iop->_flag &= ~_IOAHEAD; + + return count - (to_write/size); + +} + +#endif diff --git a/lib/crtdll/stdio/getc.c b/lib/crtdll/stdio/getc.c new file mode 100644 index 0000000..fe87af3 --- /dev/null +++ b/lib/crtdll/stdio/getc.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +//getc can be a macro +#undef getc + +int getc(FILE *fp) +{ + int c = -1; +// check for invalid stream + + if ( !__validfp (fp) ) { + __set_errno(EINVAL); + return EOF; + } +// check for read access on stream + + if ( !OPEN4READING(fp) ) { + __set_errno(EINVAL); + return -1; + } + + if(fp->_cnt > 0) { + fp->_cnt--; + c = (int)*fp->_ptr++; + } + else { + c = _filbuf(fp); + } + return c; +} + +// not exported + +wint_t getwc(FILE *fp) +{ + + // might check on multi bytes if text mode + + if(fp->_cnt > 0) { + fp->_cnt -= sizeof(wchar_t); + return (wint_t )*((wchar_t *)(fp->_ptr))++; + } + else { + return _filwbuf(fp); + } + + // never reached + return -1; +} + + + + diff --git a/lib/crtdll/stdio/getchar.c b/lib/crtdll/stdio/getchar.c new file mode 100644 index 0000000..fe0f036 --- /dev/null +++ b/lib/crtdll/stdio/getchar.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#undef getchar +int +getchar(void) +{ + return getc(stdin); +} diff --git a/lib/crtdll/stdio/getenv.c b/lib/crtdll/stdio/getenv.c new file mode 100644 index 0000000..9188ddb --- /dev/null +++ b/lib/crtdll/stdio/getenv.c @@ -0,0 +1,16 @@ +#include +#include + +void *malloc(size_t size); + + + +char *getenv(const char *name) +{ + char *buffer; + buffer = (char *)malloc(MAX_PATH); + buffer[0] = 0; + if ( GetEnvironmentVariableA(name,buffer,MAX_PATH) == 0 ) + return NULL; + return buffer; +} diff --git a/lib/crtdll/stdio/gets.c b/lib/crtdll/stdio/gets.c new file mode 100644 index 0000000..4885714 --- /dev/null +++ b/lib/crtdll/stdio/gets.c @@ -0,0 +1,107 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdio/gets.c + * PURPOSE: Get a character string from stdin + * PROGRAMER: DJ Delorie + * UPDATE HISTORY: + * 28/12/98: Appropriated for Reactos + */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +gets(char *s) +{ + int c; + char *cs; + + cs = s; + while ((c = getchar()) != '\n' && c != EOF) + *cs++ = c; + if (c == EOF && cs==s) + return NULL; + *cs++ = '\0'; + return s; +} + +#if 0 +/* Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +link_warning (gets, "the `gets' function is dangerous and should not be used.") + + +/* Read a newline-terminated multibyte string from stdin into S, + removing the trailing newline. Return S or NULL. */ + +char * +gets (s) + char *s; +{ + register char *p = s; + register int c; + FILE *stream = stdin; + int l; + + if (!__validfp (stream) || p == NULL) + { + __set_errno (EINVAL); + return NULL; + } + + if (feof (stream) || ferror (stream)) + return NULL; + + while ((c = getc(stdin)) != EOF) { + if (c == '\n') + break; + if ( isascii(c) ) + *cs++ = c; +#ifdef _MULTIBYTE + else if ( isleadbyte(c) ) { + l = mblen(c); + while(l > 0 ) { + c = getchar(); + if ( isleadbyte(c) || c == EOF ) + return NULL; // encoding error + *cs++ = c; + l--; + } + } +#endif + else + return NULL; // suspicious input + } + + *p = '\0'; + + /* Return null if we had an error, or if we got EOF + before writing any characters. */ + + if (ferror (stream) || (feof (stream) && p == s)) + return NULL; + + return s; +} + +#endif diff --git a/lib/crtdll/stdio/getw.c b/lib/crtdll/stdio/getw.c new file mode 100644 index 0000000..54b93c5 --- /dev/null +++ b/lib/crtdll/stdio/getw.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + + +/* Read a word (int) from STREAM. */ +int +_getw(FILE *stream) +{ + int w; + + /* Is there a better way? */ + if (fread( &w, sizeof(w), 1, stream) != 1) + return(EOF); + return(w); +} + diff --git a/lib/crtdll/stdio/perror.c b/lib/crtdll/stdio/perror.c new file mode 100644 index 0000000..fdde0bb --- /dev/null +++ b/lib/crtdll/stdio/perror.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +#ifdef perror +#undef perror +void perror(const char *s); +#endif + +void +perror(const char *s) +{ + + fprintf(stderr, "%s: %s\n", s, _strerror(NULL)); +} diff --git a/lib/crtdll/stdio/popen.c b/lib/crtdll/stdio/popen.c new file mode 100644 index 0000000..6ac7f68 --- /dev/null +++ b/lib/crtdll/stdio/popen.c @@ -0,0 +1,62 @@ + +#include +#include +#include +#include +#include +#include +#include + +FILE * +_popen (const char *cm, const char *md) /* program name, pipe mode */ +{ + FILE *pf; + HANDLE hReadPipe, hWritePipe; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + + // fixme CreatePipe + +// if ( !CreatePipe(&hReadPipe,&hWritePipe,NULL,1024)) +// return NULL; + + StartupInfo.cb = sizeof(STARTUPINFO); + if ( md == "r" ) { + StartupInfo.hStdOutput = hWritePipe; + } + else if ( md == "w" ) { + StartupInfo.hStdInput = hReadPipe; + } + + if (CreateProcessA("cmd.exe",(char *)cm,NULL,NULL,TRUE, + CREATE_NEW_CONSOLE,NULL,NULL, + &StartupInfo, + &ProcessInformation) == FALSE) + return NULL; + + + if ( *md == 'r' ) { + pf = _fdopen( __fileno_alloc(hReadPipe, _fmode) , "r" ); + } + else { + pf = _fdopen( __fileno_alloc(hWritePipe, _fmode) , "w" ); + } + + pf->_name_to_remove = ProcessInformation.hProcess; + + return pf; + + +} + + +int +_pclose (FILE *pp) +{ + + fclose(pp); + printf("Terminate Process\n"); +// if (!TerminateProcess(pp->_name_to_remove,0)) +// return -1; + return 0; +} diff --git a/lib/crtdll/stdio/printf.c b/lib/crtdll/stdio/printf.c new file mode 100644 index 0000000..2e8a45b --- /dev/null +++ b/lib/crtdll/stdio/printf.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +/* Write formatted output to stdout from the format string FORMAT. */ +/* VARARGS1 */ +int +printf (const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vprintf (format, arg); + va_end (arg); + return done; +} + +int +wprintf (const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vwprintf (format, arg); + va_end (arg); + return done; +} + +#ifdef USE_IN_LIBIO +# undef _IO_printf +/* This is for libg++. */ +strong_alias (printf, _IO_printf); +#endif + diff --git a/lib/crtdll/stdio/putc.c b/lib/crtdll/stdio/putc.c new file mode 100644 index 0000000..0764d07 --- /dev/null +++ b/lib/crtdll/stdio/putc.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + +// putc can be a macro +#undef putc + +int putc(int c, FILE *fp) +{ + +// valid stream macro should check that fp +// is dword aligned + if (!__validfp (fp)) { + __set_errno(EINVAL); + return -1; + } +// check for write access on fp + + if ( !OPEN4WRITING(fp) ) { + __set_errno(EINVAL); + return -1; + } + + fp->_flag |= _IODIRTY; + if (fp->_cnt > 0 ) { + fp->_cnt--; + *(fp)->_ptr++ = (unsigned char)c; + return (int)(unsigned char)c; + } + else { + return _flsbuf((unsigned char)c,fp); + } + return EOF; +} + +wint_t putwc(wchar_t c, FILE *fp) +{ + // might check on multi bytes if text mode + + if (fp->_cnt > 0 ) { + fp->_cnt-= sizeof(wchar_t); + *((wchar_t *)(fp->_ptr))++ = c; + return (wint_t)c; + } + else + return _flswbuf(c,fp); + + return -1; + + +} diff --git a/lib/crtdll/stdio/putchar.c b/lib/crtdll/stdio/putchar.c new file mode 100644 index 0000000..ce2b083 --- /dev/null +++ b/lib/crtdll/stdio/putchar.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + +#undef putc +#undef putchar + +int putchar(int c) +{ + int r = putc(c, stdout); + if (stdout->_flag & _IOLBF) + fflush(stdout); + return r; +} diff --git a/lib/crtdll/stdio/puts.c b/lib/crtdll/stdio/puts.c new file mode 100644 index 0000000..11d6eb6 --- /dev/null +++ b/lib/crtdll/stdio/puts.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +#undef putchar +int +puts(const char *s) +{ + + int c; + while ((c = *s++)) + putchar(c); + return putchar('\n'); + +} diff --git a/lib/crtdll/stdio/putw.c b/lib/crtdll/stdio/putw.c new file mode 100644 index 0000000..5b8227a --- /dev/null +++ b/lib/crtdll/stdio/putw.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +#include + + +/* Write the word (int) W to STREAM. */ +int +_putw(int w,FILE *stream) +{ + /* Is there a better way? */ + if (fwrite( &w, sizeof(w), 1, stream) < 1) + return(EOF); + return(0); +} diff --git a/lib/crtdll/stdio/remove.c b/lib/crtdll/stdio/remove.c new file mode 100644 index 0000000..8fc77bd --- /dev/null +++ b/lib/crtdll/stdio/remove.c @@ -0,0 +1,9 @@ +#include + +int remove(const char *fn) +{ + if (!DeleteFileA(fn)) + return -1; + return 0; +} + diff --git a/lib/crtdll/stdio/rename.c b/lib/crtdll/stdio/rename.c new file mode 100644 index 0000000..14eb401 --- /dev/null +++ b/lib/crtdll/stdio/rename.c @@ -0,0 +1,16 @@ +#include +#include +#include + + +int rename(const char *old_, const char *new_) +{ + if ( old_ == NULL || new_ == NULL ) + return -1; + if ( !MoveFileA(old_,new_) ) + return -1; + + return 0; +} + + diff --git a/lib/crtdll/stdio/rewind.c b/lib/crtdll/stdio/rewind.c new file mode 100644 index 0000000..099b6b7 --- /dev/null +++ b/lib/crtdll/stdio/rewind.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + + +void rewind(FILE *f) +{ + fflush(f); + lseek(fileno(f), 0L, SEEK_SET); + f->_cnt = 0; + f->_ptr = f->_base; + f->_flag &= ~(_IOERR|_IOEOF|_IOAHEAD); + +} diff --git a/lib/crtdll/stdio/rmtmp.c b/lib/crtdll/stdio/rmtmp.c new file mode 100644 index 0000000..18d0fe4 --- /dev/null +++ b/lib/crtdll/stdio/rmtmp.c @@ -0,0 +1,72 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdio/rmtmp.c + * PURPOSE: remove temporary files in current directory + * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 19/01/99 + * NOTE Not tested. + */ + +#include +#include +#include + +#ifndef F_OK + #define F_OK 0x01 +#endif +#ifndef R_OK + #define R_OK 0x02 +#endif +#ifndef W_OK + #define W_OK 0x04 +#endif +#ifndef X_OK + #define X_OK 0x08 +#endif +#ifndef D_OK + #define D_OK 0x10 +#endif + +// should be replace by a closure of the tmp files +extern __file_rec *__file_rec_list; + +int _rmtmp( void ) +{ +/* +loop files and check for name_to_remove +*/ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + + int total_closed = 0; + int i = 0; + char temp_name[260]; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) { + if (fr->files[i]->_name_to_remove != NULL) { + if ( _access(fr->files[i]->_name_to_remove,W_OK) ) { + strcpy(temp_name,fr->files[i]->_name_to_remove); + fclose(fr->files[i]); + remove(temp_name); + total_closed++; + } + } + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + return total_closed; +} diff --git a/lib/crtdll/stdio/scanf.c b/lib/crtdll/stdio/scanf.c new file mode 100644 index 0000000..9d44102 --- /dev/null +++ b/lib/crtdll/stdio/scanf.c @@ -0,0 +1,72 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include + + +/* The function `vscanf' is not defined in ISO C. Therefore we must + use the protected form here. In stdio it is called `__vscanf' and + in libio `_IO_vscanf'. */ +#ifdef USE_IN_LIBIO +# include +# define VSCANF _IO_vscanf +#else +# define VSCANF __vscanf +#endif + +int __vscanf (const char *format, va_list arg); + +/* Read formatted input from stdin according to the format string FORMAT. */ +/* VARARGS1 */ +int scanf (const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = VSCANF (format, arg); + va_end (arg); + + return done; +} + + + +int +wscanf(const wchar_t *fmt, ...) +{ + va_list arg; + int done; + char *f; + int i, len = wcslen(fmt); + + f = malloc(len+1); + for(i=0;i +#include +#include + +void +setbuf(FILE *f, char *buf) +{ + if (buf) + setvbuf(f, buf, _IOFBF, BUFSIZ); + else + setvbuf(f, 0, _IONBF, BUFSIZ); +} diff --git a/lib/crtdll/stdio/setbuffe.c b/lib/crtdll/stdio/setbuffe.c new file mode 100644 index 0000000..5fb09f2 --- /dev/null +++ b/lib/crtdll/stdio/setbuffe.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +//#include +#include +#include + +void setbuffer(FILE *f, void *buf, int size) +{ + if (buf) + setvbuf(f, buf, _IOFBF, size); + else + setvbuf(f, 0, _IONBF, 0); +} diff --git a/lib/crtdll/stdio/setlineb.c b/lib/crtdll/stdio/setlineb.c new file mode 100644 index 0000000..e8dcb04 --- /dev/null +++ b/lib/crtdll/stdio/setlineb.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +// not exported + +void setlinebuf(FILE *f) +{ + setvbuf(f, 0, _IOLBF, BUFSIZ); +} diff --git a/lib/crtdll/stdio/setvbuf.c b/lib/crtdll/stdio/setvbuf.c new file mode 100644 index 0000000..2f095e3 --- /dev/null +++ b/lib/crtdll/stdio/setvbuf.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + + +int setvbuf(FILE *f, char *buf, int type, size_t len) +{ + int mine=0; + if (!__validfp (f) ) { + __set_errno (EINVAL); + return 0; + } + if ( f->_base != NULL ) + fflush(f); + switch (type) + { + case _IOFBF: + case _IOLBF: + if (len <= 0) { + __set_errno (EINVAL); + return EOF; + } + if (buf == 0) + { + buf = (char *)malloc(len+1); + if (buf == NULL) { + __set_errno (ENOMEM); + return -1; + } + mine = 1; + } + /* FALLTHROUGH */ + case _IONBF: + if (f->_base != NULL && f->_flag & _IOMYBUF) + free(f->_base); + f->_cnt = 0; + + f->_flag &= ~(_IONBF|_IOFBF|_IOLBF|_IOUNGETC); + f->_flag |= type; + if (type != _IONBF) + { + if (mine) + f->_flag |= _IOMYBUF; + f->_ptr = f->_base = buf; + f->_bufsiz = len; + } + else + { + f->_base = 0; + f->_bufsiz = 0; + } + return 0; + default: + __set_errno (EINVAL); + return EOF; + } +} diff --git a/lib/crtdll/stdio/sprintf.c b/lib/crtdll/stdio/sprintf.c new file mode 100644 index 0000000..855bc55 --- /dev/null +++ b/lib/crtdll/stdio/sprintf.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include + +#undef sprintf +#undef wsprintf +int +sprintf(char *str, const char *fmt, ...) +{ + va_list arg; + int done; + + va_start (arg, fmt); + done = vsprintf (str, fmt, arg); + va_end (arg); + return done; +} + +int +swprintf(wchar_t *str, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + + va_start (arg, fmt); + done = vswprintf (str, fmt, arg); + va_end (arg); + return done; +} + + + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS3 */ +int +_snprintf (char *s, size_t maxlen,const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _vsnprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} + +int +_snwprintf (wchar_t *s, size_t maxlen,const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _vsnwprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} + + diff --git a/lib/crtdll/stdio/sscanf.c b/lib/crtdll/stdio/sscanf.c new file mode 100644 index 0000000..a81dde4 --- /dev/null +++ b/lib/crtdll/stdio/sscanf.c @@ -0,0 +1,79 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + + +int __vsscanf (const char *s,const char *format,va_list arg); + +/* Read formatted input from S, according to the format string FORMAT. */ +/* VARARGS2 */ +int sscanf (const char *s,const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vsscanf (s, format, arg); + va_end (arg); + + return done; +} + +#ifdef USE_IN_LIBIO +# undef _IO_sscanf +/* This is for libg++. */ +strong_alias (sscanf, _IO_sscanf) +#endif + + + + +int +swscanf(const wchar_t *str, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + char *f , *s; + int i,len = wcslen(fmt); + + f = malloc(len+1); + for(i=0;i +#include +//#include + + + +FILE _iob[5] = +{ + // stdin +{ + NULL, 0, NULL, + _IOREAD | _IOLBF , + 0, 0,0, NULL +}, + // stdout +{ + NULL, 0, NULL, + _IOWRT | _IOLBF |_IOSTRG, + 1,0,0, NULL +}, + // stderr +{ + NULL, 0, NULL, + _IOWRT | _IONBF, + 2,0,0, NULL +}, + // stdaux +{ + NULL, 0, NULL, + _IOREAD | _IOWRT | _IONBF, + 3,0,0, NULL +}, + // stdprn +{ + NULL, 0, NULL, + _IOWRT | _IONBF, + 4, 0,0,NULL +} +}; + + + diff --git a/lib/crtdll/stdio/stdiohk.c b/lib/crtdll/stdio/stdiohk.c new file mode 100644 index 0000000..83092aa --- /dev/null +++ b/lib/crtdll/stdio/stdiohk.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + + +static void fcloseall_helper(FILE *f) +{ + fflush(f); + if (fileno(f) > 2) + fclose(f); +} + +void __stdio_cleanup_proc(void); +void __stdio_cleanup_proc(void) +{ + _fwalk(fcloseall_helper); +} + +void (*__stdio_cleanup_hook)(void) = __stdio_cleanup_proc; diff --git a/lib/crtdll/stdio/tempnam.c b/lib/crtdll/stdio/tempnam.c new file mode 100644 index 0000000..efa4ade --- /dev/null +++ b/lib/crtdll/stdio/tempnam.c @@ -0,0 +1,21 @@ +#include +#include +#include + + +char *_tempnam(const char *dir,const char *prefix ) +{ + char *TempFileName = malloc(MAX_PATH); + char *d; + if ( dir == NULL ) + d = getenv("TMP"); + else + d = (char *)dir; + + if ( GetTempFileNameA(d, prefix, 0, TempFileName ) == 0 ) { + free(TempFileName); + return NULL; + } + + return TempFileName; +} diff --git a/lib/crtdll/stdio/tmpfile.c b/lib/crtdll/stdio/tmpfile.c new file mode 100644 index 0000000..22e3696 --- /dev/null +++ b/lib/crtdll/stdio/tmpfile.c @@ -0,0 +1,72 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +//#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + +#if 0 +#ifndef __dj_include_stdio_h_ +#define _name_to_remove _tmpfname +#endif +#endif + +FILE * __alloc_file(void); + +FILE * +tmpfile(void) +{ + int temp_fd; + FILE *f; + char *temp_name = tmpnam(0); + char *n_t_r = (char *)malloc(L_tmpnam); + + if (!n_t_r) + return 0; + + /* We could have a race condition, whereby another program + (in another virtual machine, or if the temporary file is + in a directory which is shared via a network) opens the + file returned by `tmpnam' between the call above and the + moment when we actually open the file below. This loop + retries the call to `tmpnam' until we actually succeed + to create the file which didn't exist before. */ + do { + // errno = 0; + temp_fd = _open(temp_name, 0, SH_DENYRW); + // if ( errno == ENOENT ) +// break; + } while (temp_fd == -1 && (temp_name = tmpnam(0)) != 0); + + if (temp_name == 0) + return 0; + + /* This should have been fdopen(temp_fd, "wb+"), but `fdopen' + is non-ANSI. So we need to dump some of its guts here. Sigh... */ + f = __alloc_file(); + if (f) + { + f->_file = temp_fd; + f->_cnt = 0; + f->_bufsiz = 0; + f->_flag = _IORMONCL | _IOREAD | _IOWRT; + f->_name_to_remove = n_t_r; + strcpy(f->_name_to_remove, temp_name); + f->_base = f->_ptr = NULL; + } + else + { + close(temp_fd); + remove(temp_name); + free(n_t_r); + } + return f; +} diff --git a/lib/crtdll/stdio/tmpnam.c b/lib/crtdll/stdio/tmpnam.c new file mode 100644 index 0000000..a3ce21d --- /dev/null +++ b/lib/crtdll/stdio/tmpnam.c @@ -0,0 +1,15 @@ +#include +#include +#include + + + +char * tmpnam(char *s) +{ + char PathName[MAX_PATH]; + static char static_buf[MAX_PATH]; + GetTempPath(MAX_PATH,PathName); + GetTempFileNameA(PathName, "ARI",007,static_buf); + strcpy(s,static_buf); + return s; +} diff --git a/lib/crtdll/stdio/ungetc.c b/lib/crtdll/stdio/ungetc.c new file mode 100644 index 0000000..99ef471 --- /dev/null +++ b/lib/crtdll/stdio/ungetc.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +ungetc(int c, FILE *f) +{ + + if (!__validfp (f) || !OPEN4READING(f)) { + __set_errno (EINVAL); + return EOF; + } + + if (c == EOF ) + return EOF; + + + + if ( f->_ptr == NULL || f->_base == NULL) + return EOF; + + if (f->_ptr == f->_base) + { + if (f->_cnt == 0) + f->_ptr++; + else + return EOF; + } + + f->_cnt++; + f->_ptr--; + if(*f->_ptr != c) + { + f->_flag |= _IOUNGETC; + *f->_ptr = c; + } + return c; +} + + +wint_t +ungetwc(wchar_t c, FILE *f) +{ + if (!__validfp (f) || !OPEN4READING(f)) { + __set_errno (EINVAL); + return EOF; + } + + if (c == (wchar_t)EOF ) + return EOF; + + + + if ( f->_ptr == NULL || f->_base == NULL) + return EOF; + + if (f->_ptr == f->_base) + { + if (f->_cnt == 0) + f->_ptr+=sizeof(wchar_t); + else + return EOF; + } + + f->_cnt+=sizeof(wchar_t); + f->_ptr-=sizeof(wchar_t); + + f->_flag |= _IOUNGETC; + *((wchar_t *)(f->_ptr)) = c; + + return c; +} diff --git a/lib/crtdll/stdio/vfprintf.c b/lib/crtdll/stdio/vfprintf.c new file mode 100644 index 0000000..394cd74 --- /dev/null +++ b/lib/crtdll/stdio/vfprintf.c @@ -0,0 +1,861 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int _isnanl(double x); +int _isinfl(double x); +int _isnan(double x); +int _isinf(double x); + + + +int +__vfprintf (FILE *fp, const char *fmt0, va_list argp); + +int +vfprintf(FILE *f, const char *fmt, va_list ap) +{ + int len; + char localbuf[BUFSIZ]; + + if (f->_flag & _IONBF) + { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = localbuf; + f->_bufsiz = BUFSIZ; + len = __vfprintf(f,fmt, ap); + (void)fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } + else + len = __vfprintf(f,fmt, ap); + return (ferror(f) ? EOF : len); +} + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + + +static int do_div(long long *n,int base) +{ + int __res = ((unsigned long long) *n) % (unsigned) base; + *n = ((unsigned long long) *n) / (unsigned) base; + return __res; +} + + +static void number(FILE * f, long long num, int base, int size, int precision ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (sign) + putc(sign,f); + if (type & SPECIAL) { + if (base==8) { + putc('0',f); + } + else if (base==16) { + putc('0', f); + putc(digits[33],f); + } + } + if (!(type & LEFT)) + while (size-- > 0) + putc(c,f); + while (i < precision--) + putc('0', f); + while (i-- > 0) + putc(tmp[i],f); + while (size-- > 0) + putc(' ', f); + return; +} + + +static void numberf(FILE * f, double __n, char exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + char sign; + char c; + char ro = 0; + + double_t *n = (double_t *)&__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type); + putc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == 'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modf(intr, &intr); + + p *=10; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (sign) + putc( sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc('0', f); + while (i-- > 0) + putc(tmp[i],f); + while (size-- > 0) + putc(' ', f); + } +} + + +static void numberfl(FILE * f, long double __n, char exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + char sign; + char c; + char ro = 0; + + long_double_t *n = (long_double_t *)&__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); + putc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == 'f' ) { + + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modfl(intr, &intr); + + p *=10; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (sign) + putc(sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc( '0', f); + while (i-- > 0) + putc(tmp[i],f); + while (size-- > 0) + putc(' ', f); + } +} + + +int __vfprintf(FILE *f, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + long double _ldouble; + double _double; + const char *s; + const short int* sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + putc(*fmt,f); + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case 'o': + case 'b': + case 'X': + case 'x': + case 'd': + case 'i': + case 'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == 'l' ) { + ++fmt; + qualifier = 'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + putc(' ', f); + if (qualifier == 'l' || qualifier == 'w') + putc((unsigned char)(wchar_t) va_arg(args, int), f); + else + putc((unsigned char) va_arg(args, int), f); + while (--field_width > 0) + putc(' ', f); + continue; + + case 'C': + if (!(flags & LEFT)) + while (--field_width > 0) + putc(' ', f); + if (qualifier == 'h') + putc((unsigned char) va_arg(args, int), f); + else + putc((unsigned char)(wchar_t) va_arg(args, int), f); + while (--field_width > 0) + putc(' ', f); + continue; + + case 's': + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc((unsigned char)(*sw++), f); + while (len < field_width--) + putc(' ', f); + } else { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc(*s++, f); + while (len < field_width--) + putc(' ', f); + } + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc(*s++, f); + while (len < field_width--) + putc(' ', f); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putc(' ', f); + for (i = 0; i < len; ++i) + putc((unsigned char)(*sw++), f); + while (len < field_width--) + putc(' ', f); + } + continue; + + case 'Z': + if (qualifier == 'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + s = ""; + while ((*s) != 0) + putc(*s++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++) + putc((unsigned char)(pus->Buffer[i]), f); + } + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + s = ""; + while ((*s) != 0) + putc(*s++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putc(pus->Buffer[i], f); + } + } + continue; + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (qualifier == 'l' || qualifier == 'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } + else if ( _isinfl(_ldouble) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } + else if ( _isinfl(_ldouble) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberfl(f,_ldouble,*fmt,field_width,precision,flags); + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else if ( _isinf(_double) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else if ( _isinf(_double) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + putc(*s++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberf(f,_double,*fmt,field_width,precision,flags); + } + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + putc('%', f); + if (*fmt) + putc(*fmt, f); + else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + number(f, num, base, field_width, precision, flags); + } + //putc('\0',f); + return 0; +} + +/* EOF */ diff --git a/lib/crtdll/stdio/vfscanf.c b/lib/crtdll/stdio/vfscanf.c new file mode 100644 index 0000000..a420885 --- /dev/null +++ b/lib/crtdll/stdio/vfscanf.c @@ -0,0 +1,1198 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* The internal entry points for `strtoX' take an extra flag argument + saying whether or not to parse locale-dependent number grouping. */ + +double __strtod_internal (const char *__nptr,char **__endptr, int __group); +float __strtof_internal (const char *__nptr, char **__endptr,int __group); +long double __strtold_internal (const char *__nptr,char **__endptr, int __group); +long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group); +unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group); + + + +#ifdef __GNUC__ +#define HAVE_LONGLONG +#define LONGLONG long long +#else +#define LONGLONG long +#endif + +/* Those are flags in the conversion format. */ +# define LONG 0x001 /* l: long or double */ +# define LONGDBL 0x002 /* L: long long or long double */ +# define SHORT 0x004 /* h: short */ +# define SUPPRESS 0x008 /* *: suppress assignment */ +# define POINTER 0x010 /* weird %p pointer (`fake hex') */ +# define NOSKIP 0x020 /* do not skip blanks */ +# define WIDTH 0x040 /* width was given */ +# define GROUP 0x080 /* ': group numbers */ +# define MALLOC 0x100 /* a: malloc strings */ + +# define TYPEMOD (LONG|LONGDBL|SHORT) + + +# define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s)) +# define inchar() ((c = getc (s)), (void) (c != EOF && ++read_in), c) +# define encode_error() do { \ + funlockfile (s); \ + __set_errno (EILSEQ); \ + return done; \ + } while (0) +# define conv_error() do { \ + funlockfile (s); \ + return done; \ + } while (0) +# define input_error() do { \ + funlockfile (s); \ + return done ? 0 : EOF; \ + } while (0) +# define memory_error() do { \ + funlockfile (s); \ + __set_errno (ENOMEM); \ + return EOF; \ + } while (0) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (s) || !s->__mode.__read) \ + { \ + __set_errno (EBADF); \ + return EOF; \ + } \ + else if (format == NULL) \ + { \ + __set_errno (EINVAL); \ + return EOF; \ + } \ + } while (0) + +# define flockfile(S) /* nothing */ +# define funlockfile(S) /* nothing */ + + char *wp = NULL; /* Workspace. */ + size_t wpmax = 0; /* Maximal size of workspace. */ + size_t wpsize = 0; /* Currently used bytes in workspace. */ + + +void ADDW(int Ch) \ +{ + if (wpsize == wpmax) + { + char *old = wp; + wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; + wp = (char *) malloc (wpmax); + if (old != NULL) { + memcpy (wp, old, wpsize); + free(old); + } + } + wp[wpsize++] = (Ch); + +} + + +int __vfscanf (FILE *s, const char *format, va_list argptr) +{ + va_list arg; + register const char *f = format; + register unsigned char fc; /* Current character of the format. */ + register size_t done = 0; /* Assignments done. */ + register size_t read_in = 0; /* Chars read in. */ + register int c = 0; /* Last char read. */ + register int width; /* Maximum field width. */ + register int flags; /* Modifiers for current format element. */ + + /* Status for reading F-P nums. */ + char got_dot, got_e, negative; + /* If a [...] is a [^...]. */ + char not_in; + /* Base for integral numbers. */ + int base; + /* Signedness for integral numbers. */ + int number_signed; + /* Decimal point character. */ + wchar_t decimal = '.'; + /* The thousands character of the current locale. */ + wchar_t thousands = ','; + /* Integral holding variables. */ + union + { + long long int q; + unsigned long long int uq; + long int l; + unsigned long int ul; + } num; + /* Character-buffer pointer. */ + char *str = NULL; + wchar_t *wstr = NULL; + char **strptr = NULL; + size_t strsize = 0; + /* We must not react on white spaces immediately because they can + possibly be matched even if in the input stream no character is + available anymore. */ + int skip_space = 0; + /* Workspace. */ + char *tw; /* Temporary pointer. */ + +#ifdef __va_copy + __va_copy (arg, argptr); +#else + arg = (va_list) argptr; +#endif + + + + /* Run through the format string. */ + while (*f != '\0') + { + unsigned int argpos; + /* Extract the next argument, which is of type TYPE. + For a %N$... spec, this is the Nth argument from the beginning; + otherwise it is the next argument after the state now in ARG. */ +#define ARG(type) va_arg(argptr,type) + + if (!isascii (*f)) + { + /* Non-ASCII, may be a multibyte. */ + // int len = mblen (f, strlen (f)); + int len =1; + if (len > 0) + { + do + { + c = inchar (); + if (c == EOF) + input_error (); + else if (c != *f++) + { + ungetc (c, s); + conv_error (); + } + } + while (--len > 0); + continue; + } + } + + fc = *f++; + if (fc != '%') + { + /* Remember to skip spaces. */ + if (isspace (fc)) + { + skip_space = 1; + continue; + } + + /* Read a character. */ + c = inchar (); + + /* Characters other than format specs must just match. */ + if (c == EOF) + input_error (); + + /* We saw white space char as the last character in the format + string. Now it's time to skip all leading white space. */ + if (skip_space) + { + while (isspace (c)) + if (inchar () == EOF && errno == EINTR) + conv_error (); + skip_space = 0; + } + + if (c != fc) + { + ungetc (c, s); + conv_error (); + } + + continue; + } + + /* This is the start of the conversion string. */ + flags = 0; + + /* Initialize state of modifiers. */ + argpos = 0; + + /* Prepare temporary buffer. */ + wpsize = 0; + + /* Check for a positional parameter specification. */ + if (isdigit (*f)) + { + argpos = *f++ - '0'; + while (isdigit (*f)) + argpos = argpos * 10 + (*f++ - '0'); + if (*f == '$') + ++f; + else + { + /* Oops; that was actually the field width. */ + width = argpos; + flags |= WIDTH; + argpos = 0; + goto got_width; + } + } + + /* Check for the assignment-suppressing and the number grouping flag. */ + while (*f == '*' || *f == '\'') + switch (*f++) + { + case '*': + flags |= SUPPRESS; + break; + case '\'': + flags |= GROUP; + break; + } + + /* We have seen width. */ + if (isdigit (*f)) + flags |= WIDTH; + + /* Find the maximum field width. */ + width = 0; + while (isdigit (*f)) + { + width *= 10; + width += *f++ - '0'; + } + got_width: + if (width == 0) + width = -1; + + /* Check for type modifiers. */ + while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q') + switch (*f++) + { + case 'h': + /* int's are short int's. */ + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + flags |= SHORT; + break; + case 'l': + if (flags & (SHORT|LONGDBL)) + conv_error (); + else if (flags & LONG) + { + /* A double `l' is equivalent to an `L'. */ + flags &= ~LONG; + flags |= LONGDBL; + } + else + /* int's are long int's. */ + flags |= LONG; + break; + case 'q': + case 'L': + /* double's are long double's, and int's are long long int's. */ + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + flags |= LONGDBL; + break; + case 'a': + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + /* String conversions (%s, %[) take a `char **' + arg and fill it in with a malloc'd pointer. */ + flags |= MALLOC; + break; + } + + /* End of the format string? */ + if (*f == '\0') + conv_error (); + + /* We must take care for EINTR errors. */ + if (c == EOF && errno == EINTR) + input_error (); + + /* Find the conversion specifier. */ + fc = *f++; + if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) + { + /* Eat whitespace. */ + do + if (inchar () == EOF && errno == EINTR) + input_error (); + while (isspace (c)); + ungetc (c, s); + skip_space = 0; + } + + switch (fc) + { + case '%': /* Must match a literal '%'. */ + c = inchar (); + if (c != fc) + { + ungetc (c, s); + conv_error (); + } + break; + + case 'n': /* Answer number of assignments done. */ + /* Corrigendum 1 to ISO C 1990 describes the allowed flags + with the 'n' conversion specifier. */ + if (!(flags & SUPPRESS)) + { + /* Don't count the read-ahead. */ + if (flags & LONGDBL) + *ARG (long int *) = read_in; + else if (flags & LONG) + *ARG (long int *) = read_in; + else if (flags & SHORT) + *ARG (short int *) = read_in; + else + *ARG (int *) = read_in; + +#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1 + /* We have a severe problem here. The ISO C standard + contradicts itself in explaining the effect of the %n + format in `scanf'. While in ISO C:1990 and the ISO C + Amendement 1:1995 the result is described as + + Execution of a %n directive does not effect the + assignment count returned at the completion of + execution of the f(w)scanf function. + + in ISO C Corrigendum 1:1994 the following was added: + + Subclause 7.9.6.2 + Add the following fourth example: + In: + #include + int d1, d2, n1, n2, i; + i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2); + the value 123 is assigned to d1 and the value3 to n1. + Because %n can never get an input failure the value + of 3 is also assigned to n2. The value of d2 is not + affected. The value 3 is assigned to i. + + We go for now with the historically correct code fro ISO C, + i.e., we don't count the %n assignments. When it ever + should proof to be wrong just remove the #ifdef above. */ + ++done; +#endif + } + break; + + case 'c': /* Match characters. */ + if ((flags & LONG) == 0) + { + if (!(flags & SUPPRESS)) + { + str = ARG (char *); + if (str == NULL) + conv_error (); + } + + c = inchar (); + if (c == EOF) + input_error (); + + if (width == -1) + width = 1; + + if (!(flags & SUPPRESS)) + { + do + *str++ = c; + while (--width > 0 && inchar () != EOF); + } + else + while (--width > 0 && inchar () != EOF); + + if (width > 0) + /* I.e., EOF was read. */ + --read_in; + + if (!(flags & SUPPRESS)) + ++done; + + break; + } + /* FALLTHROUGH */ + case 'C': + /* Get UTF-8 encoded wide character. Here we assume (as in + other parts of the libc) that we only have to handle + UTF-8. */ + { + wint_t val; + size_t cnt = 0; + int first = 1; + + if (!(flags & SUPPRESS)) + { + wstr = ARG (wchar_t *); + if (str == NULL) + conv_error (); + } + + do + { +#define NEXT_WIDE_CHAR(First) \ + c = inchar (); \ + if (c == EOF) { \ + /* EOF is only an error for the first character. */ \ + if (First) { \ + input_error (); \ + } \ + else \ + { \ + --read_in; \ + break; \ + } \ + } \ + val = c; \ + if (val >= 0x80) \ + { \ + if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ + encode_error (); \ + if ((c & 0xe0) == 0xc0) \ + { \ + /* We expect two bytes. */ \ + cnt = 1; \ + val &= 0x1f; \ + } \ + else if ((c & 0xf0) == 0xe0) \ + { \ + /* We expect three bytes. */ \ + cnt = 2; \ + val &= 0x0f; \ + } \ + else if ((c & 0xf8) == 0xf0) \ + { \ + /* We expect four bytes. */ \ + cnt = 3; \ + val &= 0x07; \ + } \ + else if ((c & 0xfc) == 0xf8) \ + { \ + /* We expect five bytes. */ \ + cnt = 4; \ + val &= 0x03; \ + } \ + else \ + { \ + /* We expect six bytes. */ \ + cnt = 5; \ + val &= 0x01; \ + } \ + \ + do \ + { \ + c = inchar (); \ + if (c == EOF \ + || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ + encode_error (); \ + val <<= 6; \ + val |= c & 0x3f; \ + } \ + while (--cnt > 0); \ + } \ + \ + if (!(flags & SUPPRESS)) \ + *wstr++ = val; \ + first = 0 + + NEXT_WIDE_CHAR (first); + } + while (--width > 0); + + if (width > 0) + /* I.e., EOF was read. */ + --read_in; + + if (!(flags & SUPPRESS)) + ++done; + } + break; + + case 's': /* Read a string. */ + if (flags & LONG) + /* We have to process a wide character string. */ + goto wide_char_string; + +#define STRING_ARG(Str, Type) \ + if (!(flags & SUPPRESS)) \ + { \ + if (flags & MALLOC) \ + { \ + /* The string is to be stored in a malloc'd buffer. */ \ + strptr = ARG (char **); \ + if (strptr == NULL) \ + conv_error (); \ + /* Allocate an initial buffer. */ \ + strsize = 100; \ + *strptr = malloc (strsize * sizeof (Type)); \ + Str = (Type *) *strptr; \ + } \ + else \ + Str = ARG (Type *); \ + if (Str == NULL) \ + conv_error (); \ + } + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + + do + { + if (isspace (c)) + { + ungetc (c, s); + break; + } +#define STRING_ADD_CHAR(Str, c, Type) \ + if (!(flags & SUPPRESS)) \ + { \ + *Str++ = c; \ + if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \ + { \ + /* Enlarge the buffer. */ \ + Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \ + if (Str == NULL) \ + { \ + /* Can't allocate that much. Last-ditch effort. */\ + Str = realloc (*strptr, \ + (strsize + 1) * sizeof (Type)); \ + if (Str == NULL) \ + { \ + /* We lose. Oh well. \ + Terminate the string and stop converting, \ + so at least we don't skip any input. */ \ + ((Type *) (*strptr))[strsize] = '\0'; \ + ++done; \ + conv_error (); \ + } \ + else \ + { \ + *strptr = (char *) Str; \ + Str = ((Type *) *strptr) + strsize; \ + ++strsize; \ + } \ + } \ + else \ + { \ + *strptr = (char *) Str; \ + Str = ((Type *) *strptr) + strsize; \ + strsize *= 2; \ + } \ + } \ + } + STRING_ADD_CHAR (str, c, char); + } while ((width <= 0 || --width > 0) && inchar () != EOF); + + if (!(flags & SUPPRESS)) + { + *str = '\0'; + ++done; + } + break; + + case 'S': + /* Wide character string. */ + wide_char_string: + { + wint_t val; + int first = 1; + STRING_ARG (wstr, wchar_t); + + do + { + size_t cnt = 0; + NEXT_WIDE_CHAR (first); + + if (iswspace (val)) + { + /* XXX We would have to push back the whole wide char + with possibly many bytes. But since scanf does + not make a difference for white space characters + we can simply push back a simple which is + guaranteed to be in the [:space:] class. */ + ungetc (' ', s); + break; + } + + STRING_ADD_CHAR (wstr, val, wchar_t); + first = 0; + } + while (width <= 0 || --width > 0); + + if (!(flags & SUPPRESS)) + { + *wstr = L'\0'; + ++done; + } + } + break; + + case 'x': /* Hexadecimal integer. */ + case 'X': /* Ditto. */ + base = 16; + number_signed = 0; + goto number; + + case 'o': /* Octal integer. */ + base = 8; + number_signed = 0; + goto number; + + case 'u': /* Unsigned decimal integer. */ + base = 10; + number_signed = 0; + goto number; + + case 'd': /* Signed decimal integer. */ + base = 10; + number_signed = 1; + goto number; + + case 'i': /* Generic number. */ + base = 0; + number_signed = 1; + + number: + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + ADDW (c); + if (width > 0) + --width; + c = inchar (); + } + + /* Look for a leading indication of base. */ + if (width != 0 && c == '0') + { + if (width > 0) + --width; + + ADDW (c); + c = inchar (); + + if (width != 0 && tolower (c) == 'x') + { + if (base == 0) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + c = inchar (); + } + } + else if (base == 0) + base = 8; + } + + if (base == 0) + base = 10; + + /* Read the number into workspace. */ + while (c != EOF && width != 0) + { + if (base == 16 ? !isxdigit (c) : + ((!isdigit (c) || c - '0' >= base) && + !((flags & GROUP) && base == 10 && c == thousands))) + break; + ADDW (c); + if (width > 0) + --width; + + c = inchar (); + } + + /* The just read character is not part of the number anymore. */ + ungetc (c, s); + + if (wpsize == 0 || + (wpsize == 1 && (wp[0] == '+' || wp[0] == '-'))) + /* There was no number. */ + conv_error (); + + /* Convert the number. */ + ADDW ('\0'); + if (flags & LONGDBL) + { +// if (number_signed) +// num.q = __strtoq_internal (wp, &tw, base, flags & GROUP); +// else +// num.uq = __strtouq_internal (wp, &tw, base, flags & GROUP); + } + else + { + if (number_signed) + num.l = __strtol_internal (wp, &tw, base, flags & GROUP); + else + num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); + } + if (wp == tw) + conv_error (); + + if (!(flags & SUPPRESS)) + { + if (! number_signed) + { + if (flags & LONGDBL) { + *ARG (unsigned LONGLONG int *) = num.uq; + } + else if (flags & LONG) + *ARG (unsigned long int *) = num.ul; + else if (flags & SHORT) + *ARG (unsigned short int *) = (unsigned short int) num.ul; + else + *ARG (unsigned int *) = (unsigned int) num.ul; + } + else + { + if (flags & LONGDBL) { + *ARG (LONGLONG int *) = num.q; + } + else if (flags & LONG) + *ARG (long int *) = num.l; + else if (flags & SHORT) + *ARG (short int *) = (short int) num.l; + else + *ARG (int *) = (int) num.l; + } + ++done; + } + break; + + case 'e': /* Floating-point numbers. */ + case 'E': + case 'f': + case 'g': + case 'G': + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + negative = c == '-'; + if (inchar () == EOF) + /* EOF is only an input error before we read any chars. */ + conv_error (); + if (width > 0) + --width; + } + else + negative = 0; + + got_dot = got_e = 0; + do + { + if (isdigit (c)) + ADDW (c); + else if (got_e && wp[wpsize - 1] == 'e' + && (c == '-' || c == '+')) + ADDW (c); + else if (wpsize > 0 && !got_e && tolower (c) == 'e') + { + ADDW ('e'); + got_e = got_dot = 1; + } + else if (c == decimal && !got_dot) + { + ADDW (c); + got_dot = 1; + } + else if ((flags & GROUP) && c == thousands && !got_dot) + ADDW (c); + else + { + /* The last read character is not part of the number + anymore. */ + ungetc (c, s); + break; + } + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + if (wpsize == 0) + conv_error (); + + /* Convert the number. */ + ADDW ('\0'); + if (flags & LONGDBL) + { + long double d = __strtold_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (long double *) = negative ? -d : d; + } + else if (flags & LONG) + { + double d = __strtod_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (double *) = negative ? -d : d; + } + else + { + float d = __strtof_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (float *) = negative ? -d : d; + } + + if (tw == wp) + conv_error (); + + if (!(flags & SUPPRESS)) + ++done; + break; + + case '[': /* Character class. */ + if (flags & LONG) + { + STRING_ARG (wstr, wchar_t); + c = '\0'; /* This is to keep gcc quiet. */ + } + else + { + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + } + + if (*f == '^') + { + ++f; + not_in = 1; + } + else + not_in = 0; + + /* Fill WP with byte flags indexed by character. + We will use this flag map for matching input characters. */ + if (wpmax < UCHAR_MAX) + { + wpmax = UCHAR_MAX; + wp = (char *) alloca (wpmax); + } + memset (wp, 0, UCHAR_MAX); + + fc = *f; + if (fc == ']' || fc == '-') + { + /* If ] or - appears before any char in the set, it is not + the terminator or separator, but the first char in the + set. */ + wp[fc] = 1; + ++f; + } + + while ((fc = *f++) != '\0' && fc != ']') + { + if (fc == '-' && *f != '\0' && *f != ']' && + (unsigned char) f[-2] <= (unsigned char) *f) + { + /* Add all characters from the one before the '-' + up to (but not including) the next format char. */ + for (fc = f[-2]; fc < *f; ++fc) + wp[fc] = 1; + } + else + /* Add the character to the flag map. */ + wp[fc] = 1; + } + if (fc == '\0') + { + if (!(flags & LONG)) + ungetc (c, s); + conv_error(); + } + + if (flags & LONG) + { + wint_t val; + int first = 1; + + do + { + size_t cnt = 0; + NEXT_WIDE_CHAR (first); + if (val > 255 || wp[val] == not_in) + { + /* XXX We have a problem here. We read a wide + character and this possibly took several + bytes. But we can only push back one single + character. To be sure we don't create wrong + input we push it back only in case it is + representable within one byte. */ + if (val < 0x80) + ungetc (val, s); + break; + } + STRING_ADD_CHAR (wstr, val, wchar_t); + if (width > 0) + --width; + first = 0; + } + while (width != 0); + + if (first) + conv_error (); + + if (!(flags & SUPPRESS)) + { + *wstr = L'\0'; + ++done; + } + } + else + { + num.ul = read_in - 1; /* -1 because we already read one char. */ + do + { + if (wp[c] == not_in) + { + ungetc (c, s); + break; + } + STRING_ADD_CHAR (str, c, char); + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + if (read_in == num.ul) + conv_error (); + + if (!(flags & SUPPRESS)) + { + *str = '\0'; + ++done; + } + } + break; + + case 'p': /* Generic pointer. */ + base = 16; + /* A PTR must be the same size as a `long int'. */ + flags &= ~(SHORT|LONGDBL); + flags |= LONG; + number_signed = 0; + goto number; + } + } + + /* The last thing we saw int the format string was a white space. + Consume the last white spaces. */ + if (skip_space) + { + do + c = inchar (); + while (isspace (c)); + ungetc (c, s); + } + + + return done; +} + + + +int +xfscanf(FILE *f, const char *fmt, ...) +{ + int r; + va_list a=0; + va_start(a, fmt); + r = __vfscanf(f, fmt, a); + va_end(a); + return r; +} + + +double __strtod_internal (const char *__nptr,char **__endptr, int __group) +{ + return strtod(__nptr,__endptr); +} +float __strtof_internal (const char *__nptr, char **__endptr,int __group) +{ + return (float)strtod(__nptr,__endptr); +} +static double powten[] = +{ + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L, + 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L +}; + +long double __strtold_internal (const char *s,char **sret, int __group) +{ + + long double r; /* result */ + int e, ne; /* exponent */ + int sign; /* +- 1.0 */ + int esign; + int flags=0; + int l2powm1; + + r = 0.0L; + sign = 1; + e = ne = 0; + esign = 1; + + while(*s && isspace(*s)) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0L; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r *= 10.0L; + r += *s - '0'; + s++; + ne++; + } + } + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0.0L; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + if (esign < 0) + { + esign = -esign; + e = -e; + } + e = e - ne; + if (e < -4096) + { + /* possibly subnormal number, 10^e would overflow */ + r *= 1.0e-2048L; + e += 2048; + } + if (e < 0) + { + e = -e; + esign = -esign; + } + if (e >= 8192) + e = 8191; + if (e) + { + double d = 1.0L; + l2powm1 = 0; + while (e) + { + if (e & 1) + d *= powten[l2powm1]; + e >>= 1; + l2powm1++; + } + if (esign > 0) + r *= d; + else + r /= d; + } + if (sret) + *sret = (char *)s; + return r * sign; + + return 0; +} +long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group) +{ + return strtol(__nptr,__endptr, __base); +} +unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group) +{ + return strtoul(__nptr,__endptr, __base); +} + + + + + + + + + diff --git a/lib/crtdll/stdio/vfwprint.c b/lib/crtdll/stdio/vfwprint.c new file mode 100644 index 0000000..31c60b1 --- /dev/null +++ b/lib/crtdll/stdio/vfwprint.c @@ -0,0 +1,865 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int _isnanl(double x); +int _isinfl(double x); +int _isnan(double x); +int _isinf(double x); + +extern int putwc (wchar_t wc, FILE* fileWrite); + +int +__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list argp); + + +int +vfwprintf(FILE *f, const wchar_t *fmt, va_list ap) +{ + int len; + wchar_t localbuf[BUFSIZ]; + + if (f->_flag & _IONBF) { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = (char *)localbuf; + f->_bufsiz = BUFSIZ; + len = __vfwprintf(f,fmt,ap); + (void)fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } else + len = __vfwprintf(f,fmt,ap); + + return (ferror(f) ? EOF : len); + +// return 0; +} + + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_wtoi(const wchar_t **s) +{ + int i=0; + + while (iswdigit(**s)) + i = i*10 + *((*s)++) - L'0'; + return i; +} + + +static int do_div(long long *n,int base) +{ + int __res = ((unsigned long long) *n) % (unsigned) base; + *n = ((unsigned long long) *n) / (unsigned) base; + return __res; +} + + +static void number(FILE * f, long long num, int base, int size, int precision ,int type) +{ + wchar_t c,sign,tmp[66]; + const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]=L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc(sign,f); + if (type & SPECIAL) { + if (base==8) { + putwc(L'0',f); + } + else if (base==16) { + putwc(L'0', f); + putwc(digits[33],f); + } + } + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + while (i < precision--) + putwc(L'0', f); + while (i-- > 0) + putwc(tmp[i],f); + while (size-- > 0) + putwc(L' ', f); + return; +} + + +static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + wchar_t sign; + wchar_t c; + char ro = 0; + + double_t *n = (double_t *)&__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type); + putwc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == 'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modf(intr, &intr); + + p *=10; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1 ) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc( sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putwc(L'0', f); + while (i-- > 0) + putwc(tmp[i],f); + while (size-- > 0) + putwc(L' ', f); + } +} + + +static void numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + wchar_t *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + wchar_t sign; + wchar_t c; + char ro = 0; + + long_double_t *n = (long_double_t *)&__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); + putwc( exp_sign,f); + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + number(f,ie, 10,2, 2,type ); + return; + } + + if ( exp_sign == L'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modfl(intr, &intr); + + p *=10; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc(sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc( '0', f); + while (i-- > 0) + putwc(tmp[i],f); + while (size-- > 0) + putwc(L' ', f); + } +} + + +int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + long double _ldouble; + double _double; + const char *s; + const wchar_t* sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != L'%') { + putwc(*fmt,f); + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case L'-': flags |= LEFT; goto repeat; + case L'+': flags |= PLUS; goto repeat; + case L' ': flags |= SPACE; goto repeat; + case L'#': flags |= SPECIAL; goto repeat; + case L'0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isxdigit(*fmt)) + field_width = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == L'.') { + ++fmt; + if (iswdigit(*fmt)) + precision = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case L'o': + case L'b': + case L'X': + case L'x': + case L'd': + case L'i': + case L'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == L'l' ) { + ++fmt; + qualifier = L'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case L'c': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + putwc(L' ', f); + if (qualifier == L'h') + putwc((wchar_t) va_arg(args, int), f); + else + putwc((wchar_t) va_arg(args, int), f); + while (--field_width > 0) + putwc(L' ', f); + continue; + + case L'C': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + putwc(L' ', f); + if (qualifier == L'l' || qualifier == L'w') + putwc((unsigned char)(wchar_t) va_arg(args, int), f); + else + putwc((unsigned char) va_arg(args, int), f); + while (--field_width > 0) + putwc(L' ', f); + continue; + + case L's': /* finished */ + if (qualifier == L'h') { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc((wchar_t)(*s++), f); + while (len < field_width--) + putwc(L' ', f); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc(*sw++, f); + while (len < field_width--) + putwc(L' ', f); + } + continue; + + case L'S': + if (qualifier == L'l' || qualifier == L'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + if (sw == NULL) + sw = L""; + + len = wcslen (sw); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc(*sw++, f); + while (len < field_width--) + putwc(L' ', f); + } else { + /* print ascii string */ + s = va_arg(args, char *); + if (s == NULL) + s = ""; + + len = strlen (s); + if ((unsigned int)len > (unsigned int)precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + putwc(L' ', f); + for (i = 0; i < len; ++i) + putwc((wchar_t)(*s++), f); + while (len < field_width--) + putwc(L' ', f); + } + continue; + +#if 0 + case L'Z': /* finished */ + if (qualifier == L'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer)) { + sw = L""; + while ((*sw) != 0) + putwc(*sw++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putwc(pus->Buffer[i], f); + } + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer)) { + sw = L""; + while ((*sw) != 0) + putwc(*sw++, f); + } else { + for (i = 0; pus->Buffer[i] && i < pus->Length; i++) + putwc((wchar_t)pus->Buffer[i], f); + } + } + continue; +#endif + + case L'e': /* finished */ + case L'E': + case L'f': + case L'g': + case L'G': + if (qualifier == L'l' || qualifier == L'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } + else if ( _isinfl(_ldouble) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } + else if ( _isinfl(_ldouble) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberfl(f,_ldouble,*fmt,field_width,precision,flags); + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else if ( _isinf(_double) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else if ( _isinf(_double) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + putwc(*sw++,f); + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + numberf(f,_double,*fmt,field_width,precision,flags); + } + } + continue; + + case L'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case L'n': + if (qualifier == L'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case L'o': + base = 8; + break; + + case L'b': + base = 2; + break; + + case L'X': + flags |= LARGE; + case L'x': + base = 16; + break; + + case L'd': + case L'i': + flags |= SIGN; + case L'u': + break; + + default: + if (*fmt != L'%') + putwc(L'%', f); + if (*fmt) + putwc(*fmt, f); + else + --fmt; + continue; + } + + if (qualifier == L'I') + num = va_arg(args, unsigned long long); + else if (qualifier == L'l') + num = va_arg(args, unsigned long); + else if (qualifier == L'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + number(f, num, base, field_width, precision, flags); + } + //putwc(L'\0',f); + return 0; +} + +/* EOF */ diff --git a/lib/crtdll/stdio/vprintf.c b/lib/crtdll/stdio/vprintf.c new file mode 100644 index 0000000..780d960 --- /dev/null +++ b/lib/crtdll/stdio/vprintf.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ +#include +#include + +#undef vprintf +#undef vwprintf + +/* Write formatted output to stdout according to the + format string FORMAT, using the argument list in ARG. */ +int +vprintf (format, arg) + const char *format; + va_list arg; +{ + int ret = vfprintf (stdout, format, arg); + fflush(stdout); + return ret; +} + +int +vwprintf (format, arg) + const wchar_t *format; + va_list arg; +{ + int ret = vfwprintf (stdout, format, arg); + fflush(stdout); + return ret; +} diff --git a/lib/crtdll/stdio/vscanf.c b/lib/crtdll/stdio/vscanf.c new file mode 100644 index 0000000..f7abe38 --- /dev/null +++ b/lib/crtdll/stdio/vscanf.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +int __vfscanf (FILE *s, const char *format, va_list argptr); + +#undef vscanf + + +/* Read formatted input from stdin according to the format + string in FORMAT, using the argument list in ARG. */ +int +__vscanf (const char *format, va_list arg) +{ + return __vfscanf (stdin, format, arg); +} +//weak_alias (__vscanf, vscanf) + diff --git a/lib/crtdll/stdio/vsprintf.c b/lib/crtdll/stdio/vsprintf.c new file mode 100644 index 0000000..52e899e --- /dev/null +++ b/lib/crtdll/stdio/vsprintf.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +vsprintf(char *str, const char *fmt, va_list ap) +{ + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = INT_MAX; + f._file = -1; + len = vfprintf(&f,fmt, ap); + *f._ptr = 0; + return len; +} + +int +vswprintf(wchar_t *str, const wchar_t *fmt, va_list ap) +{ + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = (char*)str; + f._cnt = INT_MAX; + f._file = -1; + len = vfwprintf(&f,fmt, ap); + *f._ptr = 0; + return len; +} + + +int +_vsnprintf(char *str, size_t maxlen, const char *fmt, va_list ap) +{ + FILE f; + int len; + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = maxlen; + f._file = -1; + len = vfprintf(&f,fmt, ap); + // what if the buffer is full ?? + *f._ptr = 0; + return len; +} + +int +_vsnwprintf(wchar_t *str, size_t maxlen, const wchar_t *fmt, va_list ap) +{ + FILE f; + int len; + f._flag = _IOWRT|_IOSTRG; + f._ptr = (char*)str; + f._cnt = maxlen; + f._file = -1; + len = vfwprintf(&f,fmt, ap); + // what if the buffer is full ?? + *f._ptr = 0; + return len; +} + + diff --git a/lib/crtdll/stdio/vsscanf.c b/lib/crtdll/stdio/vsscanf.c new file mode 100644 index 0000000..e5f9719 --- /dev/null +++ b/lib/crtdll/stdio/vsscanf.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include + +#undef vsscanf + +int __vfscanf (FILE *s, const char *format, va_list argptr); + +/* Read formatted input from S according to the format + string FORMAT, using the argument list in ARG. */ +int +__vsscanf (const char *s,const char *format,va_list arg) +{ + FILE f; + + if (s == NULL) + { + __set_errno (EINVAL); + return -1; + } + + memset ((void *) &f, 0, sizeof (f)); + + + + f._flag = _IOREAD; + f._ptr = (char *)s; + f._base = (char *)s; + f._bufsiz = strlen(s); + f._cnt = f._bufsiz; + + + return __vfscanf (&f, format, arg); +} + + +//weak_alias (__vsscanf, vsscanf) + diff --git a/lib/crtdll/stdlib/.cvsignore b/lib/crtdll/stdlib/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/stdlib/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/stdlib/_exit.c b/lib/crtdll/stdlib/_exit.c new file mode 100644 index 0000000..2f6cef3 --- /dev/null +++ b/lib/crtdll/stdlib/_exit.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +struct __atexit *__atexit_ptr = 0; + +void exit(int status) +{ + //int i; + struct __atexit *a = __atexit_ptr; + __atexit_ptr = 0; /* to prevent infinite loops */ + while (a) + { + (a->__function)(); + a = a->__next; + } +/* + if (__stdio_cleanup_hook) + __stdio_cleanup_hook(); + for (i=0; i +#include +#include +#include + +char *msg ="Abort\n\r"; + +void abort() +{ + fflush(NULL); + fcloseall(); + raise(SIGABRT); + _write(stderr->_file, msg, sizeof(msg)-1); + exit(3); +} + diff --git a/lib/crtdll/stdlib/abs.c b/lib/crtdll/stdlib/abs.c new file mode 100644 index 0000000..2863888 --- /dev/null +++ b/lib/crtdll/stdlib/abs.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +abs(int j) +{ + return j<0 ? -j : j; +} diff --git a/lib/crtdll/stdlib/atexit.c b/lib/crtdll/stdlib/atexit.c new file mode 100644 index 0000000..462fa07 --- /dev/null +++ b/lib/crtdll/stdlib/atexit.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +atexit(void (*a)(void)) +{ + struct __atexit *ap; + if (a == 0) + return -1; + ap = (struct __atexit *)malloc(sizeof(struct __atexit)); + if (!ap) + return -1; + ap->__next = __atexit_ptr; + ap->__function = a; + __atexit_ptr = ap; + return 0; +} diff --git a/lib/crtdll/stdlib/atof.c b/lib/crtdll/stdlib/atof.c new file mode 100644 index 0000000..2b93d8c --- /dev/null +++ b/lib/crtdll/stdlib/atof.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +atof(const char *ascii) +{ + return strtod(ascii, 0); +} diff --git a/lib/crtdll/stdlib/atoi.c b/lib/crtdll/stdlib/atoi.c new file mode 100644 index 0000000..1d19cf0 --- /dev/null +++ b/lib/crtdll/stdlib/atoi.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +atoi(const char *str) +{ + return (int)strtol(str, 0, 10); +} diff --git a/lib/crtdll/stdlib/atol.c b/lib/crtdll/stdlib/atol.c new file mode 100644 index 0000000..0360505 --- /dev/null +++ b/lib/crtdll/stdlib/atol.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +atol(const char *str) +{ + return strtol(str, 0, 10); +} diff --git a/lib/crtdll/stdlib/atold.c b/lib/crtdll/stdlib/atold.c new file mode 100644 index 0000000..1bcaeeb --- /dev/null +++ b/lib/crtdll/stdlib/atold.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long double +_atold(const char *ascii) +{ + return _strtold(ascii, 0); +} diff --git a/lib/crtdll/stdlib/bsearch.c b/lib/crtdll/stdlib/bsearch.c new file mode 100644 index 0000000..a36e43f --- /dev/null +++ b/lib/crtdll/stdlib/bsearch.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +void * +bsearch(const void *key, const void *base0, size_t nelem, + size_t size, int (*cmp)(const void *ck, const void *ce)) +{ + char *base = (char *)base0; + int lim, cmpval; + void *p; + + for (lim = nelem; lim != 0; lim >>= 1) + { + p = base + (lim >> 1) * size; + cmpval = (*cmp)(key, p); + if (cmpval == 0) + return p; + if (cmpval > 0) + { /* key > p: move right */ + base = (char *)p + size; + lim--; + } /* else move left */ + } + return 0; +} diff --git a/lib/crtdll/stdlib/calloc.c b/lib/crtdll/stdlib/calloc.c new file mode 100644 index 0000000..7325ed6 --- /dev/null +++ b/lib/crtdll/stdlib/calloc.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +void * +calloc(size_t size, size_t nelem) +{ + void *rv = malloc(size*nelem); + if (rv) + memset(rv, 0, size*nelem); + return rv; +} diff --git a/lib/crtdll/stdlib/div.c b/lib/crtdll/stdlib/div.c new file mode 100644 index 0000000..be64654 --- /dev/null +++ b/lib/crtdll/stdlib/div.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +div_t +div(int num, int denom) +{ + div_t r; + + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} diff --git a/lib/crtdll/stdlib/ecvt.c b/lib/crtdll/stdlib/ecvt.c new file mode 100644 index 0000000..56c4489 --- /dev/null +++ b/lib/crtdll/stdlib/ecvt.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char *ecvtbuf (double, int, int *, int *, char *); + +char * +_ecvt (double value, int ndigits, int *decpt, int *sign) +{ + static char ecvt_buf[DBL_MAX_10_EXP + 10]; + return ecvtbuf (value, ndigits, decpt, sign, ecvt_buf); +} diff --git a/lib/crtdll/stdlib/ecvtbuf.c b/lib/crtdll/stdlib/ecvtbuf.c new file mode 100644 index 0000000..e391e20 --- /dev/null +++ b/lib/crtdll/stdlib/ecvtbuf.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +// #include + +void __ecvround (char *, char *, const char *, int *); + +void +__ecvround (char *numbuf, char *last_digit, const char *after_last, int *decpt) +{ + char *p; + int carry = 0; + + /* Do we have at all to round the last digit? */ + if (*after_last > '4') + { + p = last_digit; + carry = 1; + + /* Propagate the rounding through trailing '9' digits. */ + do { + int sum = *p + carry; + carry = sum > '9'; + *p-- = sum - carry * 10; + } while (carry && p >= numbuf); + + /* We have 9999999... which needs to be rounded to 100000.. */ + if (carry && p == numbuf) + { + *p = '1'; + *decpt += 1; + } + } +} + +char * +ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) +{ + static char INFINITY[] = "Infinity"; + char decimal = '.' /* localeconv()->decimal_point[0] */; + char *cvtbuf = (char *)alloca (ndigits + 20); /* +3 for sign, dot, null; */ + /* two extra for rounding */ + /* 15 extra for alignment */ + char *s = cvtbuf, *d = buf; + + /* Produce two extra digits, so we could round properly. */ + sprintf (cvtbuf, "%-+.*E", ndigits + 2, value); + *decpt = 0; + + /* The sign. */ + if (*s++ == '-') + *sign = 1; + else + *sign = 0; + + /* Special values get special treatment. */ + if (strncmp (s, "Inf", 3) == 0) + { + /* SunOS docs says we have return "Infinity" for NDIGITS >= 8. */ + memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); + if (ndigits < 8) + buf[3] = '\0'; + } + else if (strcmp (s, "NaN") == 0) + memcpy (buf, s, 4); + else + { + char *last_digit, *digit_after_last; + + /* Copy (the single) digit before the decimal. */ + while (*s && *s != decimal && d - buf < ndigits) + *d++ = *s++; + + /* If we don't see any exponent, here's our decimal point. */ + *decpt = d - buf; + if (*s) + s++; + + /* Copy the fraction digits. */ + while (*s && *s != 'E' && d - buf < ndigits) + *d++ = *s++; + + /* Remember the last digit copied and the one after it. */ + last_digit = d > buf ? d - 1 : d; + digit_after_last = s; + + /* Get past the E in exponent field. */ + while (*s && *s++ != 'E') + ; + + /* Adjust the decimal point by the exponent value. */ + *decpt += atoi (s); + + /* Pad with zeroes if needed. */ + while (d - buf < ndigits) + *d++ = '0'; + + /* Zero-terminate. */ + *d = '\0'; + + /* Round if necessary. */ + __ecvround (buf, last_digit, digit_after_last, decpt); + } + return buf; +} diff --git a/lib/crtdll/stdlib/errno.c b/lib/crtdll/stdlib/errno.c new file mode 100644 index 0000000..b2bfaa6 --- /dev/null +++ b/lib/crtdll/stdlib/errno.c @@ -0,0 +1,36 @@ +#include +#include + +#undef errno +int errno; + +#undef _doserrno +int _doserrno; + +#undef _fpecode +int fpecode; + +int *_errno(void) +{ + return &errno; +} + + +int __set_errno (int error) +{ + errno = error; + return error; +} + + + +int * __fpecode ( void ) +{ + return &fpecode; +} + +int* __doserrno(void) +{ + _doserrno = GetLastError(); + return &_doserrno; +} diff --git a/lib/crtdll/stdlib/fcvt.c b/lib/crtdll/stdlib/fcvt.c new file mode 100644 index 0000000..ebe5552 --- /dev/null +++ b/lib/crtdll/stdlib/fcvt.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char *fcvtbuf (double, int, int *, int *, char *); + +char * +_fcvt (double value, int ndigits, int *decpt, int *sign) +{ + static char fcvt_buf[2 * DBL_MAX_10_EXP + 10]; + return fcvtbuf (value, ndigits, decpt, sign, fcvt_buf); +} diff --git a/lib/crtdll/stdlib/fcvtbuf.c b/lib/crtdll/stdlib/fcvtbuf.c new file mode 100644 index 0000000..4f9d137 --- /dev/null +++ b/lib/crtdll/stdlib/fcvtbuf.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +// #include + +void __ecvround (char *, char *, const char *, int *); +char *ecvtbuf (double, int, int *, int *, char *); + +char * +fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) +{ + static char INFINITY[] = "Infinity"; + char decimal = '.' /* localeconv()->decimal_point[0] */; + int digits = ndigits >= 0 ? ndigits : 0; + char *cvtbuf = (char *)alloca (2*DBL_MAX_10_EXP + 16); + char *s = cvtbuf; + char *dot; + + sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value); + + /* The sign. */ + if (*s++ == '-') + *sign = 1; + else + *sign = 0; + + /* Where's the decimal point? */ + dot = strchr (s, decimal); + *decpt = dot ? dot - s : strlen (s); + + /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity" + instead of "Inf". */ + if (strncmp (s, "Inf", 3) == 0) + { + memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); + if (ndigits < 8) + buf[3] = '\0'; + return buf; + } + else if (ndigits < 0) + return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf); + else if (*s == '0' && value != 0.0) + return ecvtbuf (value, ndigits, decpt, sign, buf); + else + { + memcpy (buf, s, *decpt); + if (s[*decpt] == decimal) + { + memcpy (buf + *decpt, s + *decpt + 1, ndigits); + buf[*decpt + ndigits] = '\0'; + } + else + buf[*decpt] = '\0'; + __ecvround (buf, buf + *decpt + ndigits - 1, + s + *decpt + ndigits + 1, decpt); + return buf; + } +} diff --git a/lib/crtdll/stdlib/fullpath.c b/lib/crtdll/stdlib/fullpath.c new file mode 100644 index 0000000..cf43e3e --- /dev/null +++ b/lib/crtdll/stdlib/fullpath.c @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/fullpath.c + * PURPOSE: Gets the fullpathname + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +#undef fullpath +char *fullpath( char *absPath, const char *relPath, size_t maxLength ) +{ + return _fullpath(absPath,relPath,maxLength ); +} + +char *_fullpath( char *absPath, const char *relPath, size_t maxLength ) +{ + + + char *lpFilePart; + if ( GetFullPathName(relPath,maxLength,absPath,&lpFilePart) == 0 ) + return NULL; + + return absPath; +} + + + + diff --git a/lib/crtdll/stdlib/gcvt.c b/lib/crtdll/stdlib/gcvt.c new file mode 100644 index 0000000..f32157a --- /dev/null +++ b/lib/crtdll/stdlib/gcvt.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +char * +_gcvt (double value, int ndigits, char *buf) +{ + char *p = buf; + + sprintf (buf, "%-#.*g", ndigits, value); + + /* It seems they expect us to return .XXXX instead of 0.XXXX */ + if (*p == '-') + p++; + if (*p == '0' && p[1] == '.') + memmove (p, p + 1, strlen (p + 1) + 1); + + /* They want Xe-YY, not X.e-YY, and XXXX instead of XXXX. */ + p = strchr (buf, 'e'); + if (!p) + { + p = buf + strlen (buf); + /* They don't want trailing zeroes. */ + while (p[-1] == '0' && p > buf + 2) + *--p = '\0'; + } + if (p > buf && p[-1] == '.') + memmove (p - 1, p, strlen (p) + 1); + return buf; +} diff --git a/lib/crtdll/stdlib/itoa.c b/lib/crtdll/stdlib/itoa.c new file mode 100644 index 0000000..087c8b4 --- /dev/null +++ b/lib/crtdll/stdlib/itoa.c @@ -0,0 +1,138 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/itoa.c + * PURPOSE: converts a integer to ascii + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +char * +itoa(int value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +char * +ltoa(long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned long)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +char * +_ultoa(unsigned long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+1); + sp = string; + + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} diff --git a/lib/crtdll/stdlib/itow.c b/lib/crtdll/stdlib/itow.c new file mode 100644 index 0000000..4a159aa --- /dev/null +++ b/lib/crtdll/stdlib/itow.c @@ -0,0 +1,177 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/itow.c + * PURPOSE: converts a integer to wchar_t + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + * 2000: derived from ./itoa.c by ea + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +wchar_t * +_itow (int value, wchar_t *string, int radix) +{ + wchar_t tmp [33]; + wchar_t * tp = tmp; + int i; + unsigned int v; + int sign; + wchar_t * sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = ((radix == 10) && (value < 0)); + if (sign) + { + v = -value; + } + else + { + v = (unsigned) value; + } + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + { + *tp++ = i+ (wchar_t) '0'; + } + else + { + *tp++ = i + (wchar_t) 'a' - 10; + } + } + + if (string == 0) + { + string = (wchar_t *) malloc((tp-tmp) + (sign + 1) * sizeof(wchar_t)); + } + sp = string; + + if (sign) + { + *sp++ = (wchar_t) '-'; + } + while (tp > tmp) + { + *sp++ = *--tp; + } + *sp = (wchar_t) 0; + return string; +} + + +wchar_t * +_ltow (long value, wchar_t *string, int radix) +{ + wchar_t tmp [33]; + wchar_t * tp = tmp; + long int i; + unsigned long int v; + int sign; + wchar_t * sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = ((radix == 10) && (value < 0)); + if (sign) + { + v = -value; + } + else + { + v = (unsigned long) value; + } + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + { + *tp++ = i + (wchar_t) '0'; + } + else + { + *tp++ = i + (wchar_t) 'a' - 10; + } + } + + if (string == 0) + { + string = (wchar_t *) malloc((tp - tmp) + (sign + 1) * sizeof(wchar_t)); + } + sp = string; + + if (sign) + { + *sp++ = (wchar_t) '-'; + } + while (tp > tmp) + { + *sp++ = *--tp; + } + *sp = (wchar_t) 0; + return string; +} + +wchar_t * +_ultow (unsigned long value, wchar_t *string, int radix) +{ + wchar_t tmp [33]; + wchar_t * tp = tmp; + long int i; + unsigned long int v = value; + wchar_t * sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + { + *tp++ = i + (wchar_t) '0'; + } + else + { + *tp++ = i + (wchar_t) 'a' - 10; + } + } + + if (string == 0) + { + string = (wchar_t *) malloc((tp - tmp) + sizeof(wchar_t)); + } + sp = string; + + + while (tp > tmp) + { + *sp++ = *--tp; + } + *sp = (wchar_t) 0; + return string; +} + + +/* EOF */ diff --git a/lib/crtdll/stdlib/labs.c b/lib/crtdll/stdlib/labs.c new file mode 100644 index 0000000..b1c4fa2 --- /dev/null +++ b/lib/crtdll/stdlib/labs.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +labs(long j) +{ + return j<0 ? -j : j; +} diff --git a/lib/crtdll/stdlib/ldiv.c b/lib/crtdll/stdlib/ldiv.c new file mode 100644 index 0000000..26cbfbb --- /dev/null +++ b/lib/crtdll/stdlib/ldiv.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +ldiv_t +ldiv(long num, long denom) +{ + ldiv_t r; + + if (num > 0 && denom < 0) + { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} diff --git a/lib/crtdll/stdlib/llabs.c b/lib/crtdll/stdlib/llabs.c new file mode 100644 index 0000000..fc6580a --- /dev/null +++ b/lib/crtdll/stdlib/llabs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long long +llabs(long long j) +{ + return j<0 ? -j : j; +} diff --git a/lib/crtdll/stdlib/lldiv.c b/lib/crtdll/stdlib/lldiv.c new file mode 100644 index 0000000..2a0e3f5 --- /dev/null +++ b/lib/crtdll/stdlib/lldiv.c @@ -0,0 +1,26 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +lldiv_t +lldiv(long long num, long long denom) +{ + lldiv_t r; + + if (num > 0 && denom < 0) + { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} diff --git a/lib/crtdll/stdlib/makepath.c b/lib/crtdll/stdlib/makepath.c new file mode 100644 index 0000000..ebc59aa --- /dev/null +++ b/lib/crtdll/stdlib/makepath.c @@ -0,0 +1,36 @@ +/* $Id$ + */ +#include +#include + +void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext) +{ + int dir_len; + + if ((drive != NULL) && (*drive)) + { + strcpy(path, drive); + strcat(path, ":"); + } + else + (*path)=0; + + if (dir != NULL) + { + strcat(path, dir); + dir_len = strlen(dir); + if (dir_len && *(dir + dir_len - 1) != '\\') + strcat(path, "\\"); + } + + if (fname != NULL) + { + strcat(path, fname); + if (ext != NULL && *ext != 0) + { + if (*ext != '.') + strcat(path, "."); + strcat(path, ext); + } + } +} diff --git a/lib/crtdll/stdlib/malloc.c b/lib/crtdll/stdlib/malloc.c new file mode 100644 index 0000000..116e38c --- /dev/null +++ b/lib/crtdll/stdlib/malloc.c @@ -0,0 +1,87 @@ +#include +#include + + +void* malloc(size_t _size) +{ + return(HeapAlloc(GetProcessHeap(),0,_size)); +} + +void free(void* _ptr) +{ + HeapFree(GetProcessHeap(),0,_ptr); +} + +void* calloc(size_t _nmemb, size_t _size) +{ + return(HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, _nmemb*_size)); +} + +void* realloc(void* _ptr, size_t _size) +{ + return(HeapReAlloc(GetProcessHeap(),0,_ptr,_size)); +} +#undef alloca +void *alloca(size_t s) +{ + register unsigned int as = s; + +// alloca(0) should not return the stack pointer + if ( s == 0 ) + return NULL; + + + if ( (s & 0xfffffffc) != 0 ) + as += 4; + + as &= 0xfffffffc; + + __asm__ __volatile__( + "mov %0, %%edx \n" +// "popl %%ebp \n" + "leave \n" + "popl %%ecx \n" + "subl %%edx, %%esp \n" + "movl %%esp, %%eax \n" + "addl $20, %%eax \n"//4 bytes + 16 bytes = arguments + "push %%ecx \n" + "ret \n" + : + :"g" ( as) + ); + + + return NULL; +} + +void *_alloca(size_t s) +{ + register unsigned int as = s; + +// alloca(0) should not return the stack pointer + if ( s == 0 ) + return NULL; + + + if ( (s & 0xfffffffc) != 0 ) + as += 4; + + as &= 0xfffffffc; + + __asm__ __volatile__( + "mov %0, %%edx \n" +// "popl %%ebp \n" + "leave \n" + "popl %%ecx \n" + "subl %%edx, %%esp \n" + "movl %%esp, %%eax \n" + "addl $20, %%eax \n"//4 bytes + 16 bytes = arguments + "push %%ecx \n" + "ret \n" + : + :"g" ( as) + ); + + + return NULL; +} diff --git a/lib/crtdll/stdlib/mbstow.c b/lib/crtdll/stdlib/mbstow.c new file mode 100644 index 0000000..f97c19e --- /dev/null +++ b/lib/crtdll/stdlib/mbstow.c @@ -0,0 +1,17 @@ +#include + + +int mblen (const char* mbs, size_t sizeString) +{ + return 0; +} + +size_t mbstowcs (wchar_t* wcaDest, const char* mbsConvert, size_t size) +{ + return 0; +} + +int mbtowc (wchar_t* wcDest, const char* mbConvert, size_t size) +{ + return 0; +} diff --git a/lib/crtdll/stdlib/mbstowcs.c b/lib/crtdll/stdlib/mbstowcs.c new file mode 100644 index 0000000..bb459dc --- /dev/null +++ b/lib/crtdll/stdlib/mbstowcs.c @@ -0,0 +1,12 @@ +#include + +size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count ) +{ + return 0; +} + +int mbtowc( wchar_t *wchar, const char *mbchar, size_t count ) +{ + return 0; +} + diff --git a/lib/crtdll/stdlib/obsol.c b/lib/crtdll/stdlib/obsol.c new file mode 100644 index 0000000..c5aec4e --- /dev/null +++ b/lib/crtdll/stdlib/obsol.c @@ -0,0 +1,24 @@ +#include +#include + +#undef _cpumode +unsigned char _cpumode = 0; +unsigned char *_cpumode_dll = &_cpumode; + +void _seterrormode(int nMode) +{ + SetErrorMode(nMode); + return; +} + +void _beep(unsigned nFreq, unsigned nDur) +{ + Beep(nFreq,nDur); + return; +} + +void _sleep(unsigned long ulTime) +{ + Sleep(ulTime); + return; +} diff --git a/lib/crtdll/stdlib/putenv.c b/lib/crtdll/stdlib/putenv.c new file mode 100644 index 0000000..cc91ccc --- /dev/null +++ b/lib/crtdll/stdlib/putenv.c @@ -0,0 +1,30 @@ +#include +#include +#include + + + +int +putenv(const char *val) +{ + + char buffer[1024]; + char *epos; + + strcpy(buffer,val); + + + epos = strchr(buffer, '='); + if ( epos == NULL ) + return -1; + + *epos = 0; + + return SetEnvironmentVariableA(buffer,epos+1); +} + + + + + + diff --git a/lib/crtdll/stdlib/qsort.c b/lib/crtdll/stdlib/qsort.c new file mode 100644 index 0000000..f2be7c5 --- /dev/null +++ b/lib/crtdll/stdlib/qsort.c @@ -0,0 +1,237 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +/*- + * Copyright (c) 1980, 1983 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * qsort.c: + * Our own version of the system qsort routine which is faster by an average + * of 25%, with lows and highs of 10% and 50%. + * The THRESHold below is the insertion sort threshold, and has been adjusted + * for records of size 48 bytes. + * The MTHREShold is where we stop finding a better median. + */ + +#define THRESH 4 /* threshold for insertion */ +#define MTHRESH 6 /* threshold for median */ + +static int (*qcmp)(const void *, const void *); /* the comparison routine */ +static int qsz; /* size of each record */ +static int thresh; /* THRESHold in chars */ +static int mthresh; /* MTHRESHold in chars */ + +/* + * qst: + * Do a quicksort + * First, find the median element, and put that one in the first place as the + * discriminator. (This "median" is just the median of the first, last and + * middle elements). (Using this median instead of the first element is a big + * win). Then, the usual partitioning/swapping, followed by moving the + * discriminator into the right place. Then, figure out the sizes of the two + * partions, do the smaller one recursively and the larger one via a repeat of + * this code. Stopping when there are less than THRESH elements in a partition + * and cleaning up with an insertion sort (in our caller) is a huge win. + * All data swaps are done in-line, which is space-losing but time-saving. + * (And there are only three places where this is done). + */ + +static void +qst(char *base, char *max) +{ + char c, *i, *j, *jj; + int ii; + char *mid, *tmp; + int lo, hi; + + /* + * At the top here, lo is the number of characters of elements in the + * current partition. (Which should be max - base). + * Find the median of the first, last, and middle element and make + * that the middle element. Set j to largest of first and middle. + * If max is larger than that guy, then it's that guy, else compare + * max with loser of first and take larger. Things are set up to + * prefer the middle, then the first in case of ties. + */ + lo = max - base; /* number of elements as chars */ + do { + mid = i = base + qsz * ((lo / qsz) >> 1); + if (lo >= mthresh) + { + j = (qcmp((jj = base), i) > 0 ? jj : i); + if (qcmp(j, (tmp = max - qsz)) > 0) + { + /* switch to first loser */ + j = (j == jj ? i : jj); + if (qcmp(j, tmp) < 0) + j = tmp; + } + if (j != i) + { + ii = qsz; + do { + c = *i; + *i++ = *j; + *j++ = c; + } while (--ii); + } + } + /* + * Semi-standard quicksort partitioning/swapping + */ + for (i = base, j = max - qsz; ; ) + { + while (i < mid && qcmp(i, mid) <= 0) + i += qsz; + while (j > mid) + { + if (qcmp(mid, j) <= 0) + { + j -= qsz; + continue; + } + tmp = i + qsz; /* value of i after swap */ + if (i == mid) + { + /* j <-> mid, new mid is j */ + mid = jj = j; + } + else + { + /* i <-> j */ + jj = j; + j -= qsz; + } + goto swap; + } + if (i == mid) + { + break; + } + else + { + /* i <-> mid, new mid is i */ + jj = mid; + tmp = mid = i; /* value of i after swap */ + j -= qsz; + } + swap: + ii = qsz; + do { + c = *i; + *i++ = *jj; + *jj++ = c; + } while (--ii); + i = tmp; + } + /* + * Look at sizes of the two partitions, do the smaller + * one first by recursion, then do the larger one by + * making sure lo is its size, base and max are update + * correctly, and branching back. But only repeat + * (recursively or by branching) if the partition is + * of at least size THRESH. + */ + i = (j = mid) + qsz; + if ((lo = j - base) <= (hi = max - i)) + { + if (lo >= thresh) + qst(base, j); + base = i; + lo = hi; + } + else + { + if (hi >= thresh) + qst(i, max); + max = j; + } + } while (lo >= thresh); +} + +/* + * qsort: + * First, set up some global parameters for qst to share. Then, quicksort + * with qst(), and then a cleanup insertion sort ourselves. Sound simple? + * It's not... + */ +void +qsort(const void *base0, size_t n, size_t size, _pfunccmp_t compar) +{ + char *base = (char *)base0; + char c, *i, *j, *lo, *hi; + char *min, *max; + + if (n <= 1) + return; + qsz = size; + qcmp = compar; + thresh = qsz * THRESH; + mthresh = qsz * MTHRESH; + max = base + n * qsz; + if (n >= THRESH) + { + qst(base, max); + hi = base + thresh; + } + else + { + hi = max; + } + /* + * First put smallest element, which must be in the first THRESH, in + * the first position as a sentinel. This is done just by searching + * the first THRESH elements (or the first n if n < THRESH), finding + * the min, and swapping it into the first position. + */ + for (j = lo = base; (lo += qsz) < hi; ) + if (qcmp(j, lo) > 0) + j = lo; + if (j != base) + { + /* swap j into place */ + for (i = base, hi = base + qsz; i < hi; ) + { + c = *j; + *j++ = *i; + *i++ = c; + } + } + /* + * With our sentinel in place, we now run the following hyper-fast + * insertion sort. For each remaining element, min, from [1] to [n-1], + * set hi to the index of the element AFTER which this one goes. + * Then, do the standard insertion sort shift on a character at a time + * basis for each element in the frob. + */ + for (min = base; (hi = min += qsz) < max; ) + { + while (qcmp(hi -= qsz, min) > 0) + /* void */; + if ((hi += qsz) != min) { + for (lo = min + qsz; --lo >= min; ) + { + c = *lo; + for (i = j = lo; (j -= qsz) >= hi; i = j) + *i = *j; + *i = c; + } + } + } +} diff --git a/lib/crtdll/stdlib/rand.c b/lib/crtdll/stdlib/rand.c new file mode 100644 index 0000000..78912a2 --- /dev/null +++ b/lib/crtdll/stdlib/rand.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +static unsigned long long next = 0; + +int +rand(void) +{ + next = next * 0x5deece66dLL + 11; + return (int)((next >> 16) & RAND_MAX); +} + +void +srand(unsigned seed) +{ + next = seed; +} diff --git a/lib/crtdll/stdlib/rot.c b/lib/crtdll/stdlib/rot.c new file mode 100644 index 0000000..7a67cb6 --- /dev/null +++ b/lib/crtdll/stdlib/rot.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/rot.c + * PURPOSE: Performs a bit wise rotation + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 03/04/99: Created + */ + +#include + +unsigned int _rotl( unsigned int value, int shift ) +{ + int max_bits = sizeof(unsigned int)<<3; + if ( shift < 0 ) + return _rotr(value,-shift); + + if ( shift > max_bits ) + shift = shift % max_bits; + return (value << shift) | (value >> (max_bits-shift)); +} + +unsigned int _rotr( unsigned int value, int shift ) +{ + int max_bits = sizeof(unsigned int)<<3; + if ( shift < 0 ) + return _rotl(value,-shift); + + if ( shift > max_bits<<3 ) + shift = shift % max_bits; + return (value >> shift) | (value << (max_bits-shift)); +} + + +unsigned long _lrotl( unsigned long value, int shift ) +{ + int max_bits = sizeof(unsigned long)<<3; + if ( shift < 0 ) + return _lrotr(value,-shift); + + if ( shift > max_bits ) + shift = shift % max_bits; + return (value << shift) | (value >> (max_bits-shift)); +} + +unsigned long _lrotr( unsigned long value, int shift ) +{ + int max_bits = sizeof(unsigned long)<<3; + if ( shift < 0 ) + return _lrotl(value,-shift); + + if ( shift > max_bits ) + shift = shift % max_bits; + return (value >> shift) | (value << (max_bits-shift)); +} diff --git a/lib/crtdll/stdlib/senv.c b/lib/crtdll/stdlib/senv.c new file mode 100644 index 0000000..66bf91e --- /dev/null +++ b/lib/crtdll/stdlib/senv.c @@ -0,0 +1,28 @@ +#include +#include +#include + +void _searchenv(const char *file,const char *var,char *path ) +{ + char *env = getenv(var); + + char *x; + char *y; + char *FilePart; + x = strchr(env,'='); + if ( x != NULL ) { + *x = 0; + x++; + } + y = strchr(env,';'); + while ( y != NULL ) { + *y = 0; + if ( SearchPathA(x,file,NULL,MAX_PATH,path,&FilePart) > 0 ) { + return; + } + x = y+1; + y = strchr(env,';'); + } + return; + +} diff --git a/lib/crtdll/stdlib/splitp.c b/lib/crtdll/stdlib/splitp.c new file mode 100644 index 0000000..9388ea0 --- /dev/null +++ b/lib/crtdll/stdlib/splitp.c @@ -0,0 +1,47 @@ +#include +#include + +void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext ) +{ + char *tmp_drive; + char *tmp_dir; + char *tmp_ext; + + tmp_drive = (char *)strchr(path,':'); + if ( tmp_drive != (char *)NULL ) { + strncpy(drive,tmp_drive-1,1); + *(drive+1) = 0; + } + else { + *drive = 0; + tmp_drive = (char *)path; + } + + tmp_dir = (char *)strrchr(path,'\\'); + if( tmp_dir != NULL && tmp_dir != tmp_drive + 1 ) { + strncpy(dir,tmp_drive+1,tmp_dir - tmp_drive); + *(dir + (tmp_dir - tmp_drive)) = 0; + } + else + *dir =0; + + tmp_ext = ( char *)strrchr(path,'.'); + if ( tmp_ext != NULL ) { + strcpy(ext,tmp_ext); + } + else + { + *ext = 0; + tmp_ext = (char*)path+strlen(path); + } + if ( tmp_dir != NULL ) { + strncpy(fname,tmp_dir+1,tmp_ext - tmp_dir - 1); + *(fname + (tmp_ext - tmp_dir -1)) = 0; + } + else + { + strncpy(fname,path,tmp_ext - path); + *(fname+(tmp_ext-path))=0; + } +} + diff --git a/lib/crtdll/stdlib/strtod.c b/lib/crtdll/stdlib/strtod.c new file mode 100644 index 0000000..289752b --- /dev/null +++ b/lib/crtdll/stdlib/strtod.c @@ -0,0 +1,97 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + + +double +strtod(const char *s, char **sret) +{ + long double r; /* result */ + int e; /* exponent */ + long double d; /* scale */ + int sign; /* +- 1.0 */ + int esign; + int i; + int flags=0; + + r = 0.0; + sign = 1; + e = 0; + esign = 1; + + while ((*s == ' ') || (*s == '\t')) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + d = 0.1L; + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r += d * (*s - '0'); + s++; + d *= 0.1L; + } + } + + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + if ((*s < '0') || (*s > '9')) + { + if (sret) + *sret = (char *)s; + return r; + } + + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + + if (esign < 0) + for (i = 1; i <= e; i++) + r *= 0.1L; + else + for (i = 1; i <= e; i++) + r *= 10.0; + + if (sret) + *sret = (char *)s; + return r * sign; +} diff --git a/lib/crtdll/stdlib/strtol.c b/lib/crtdll/stdlib/strtol.c new file mode 100644 index 0000000..cbe7e18 --- /dev/null +++ b/lib/crtdll/stdlib/strtol.c @@ -0,0 +1,91 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + +long +strtol(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + __set_errno(ERANGE); + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/crtdll/stdlib/strtold.c b/lib/crtdll/stdlib/strtold.c new file mode 100644 index 0000000..d38d025 --- /dev/null +++ b/lib/crtdll/stdlib/strtold.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +//#include + +static double powten[] = +{ + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L + 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L +}; + +long double +_strtold(const char *s, char **sret) +{ + double r; /* result */ + int e, ne; /* exponent */ + int sign; /* +- 1.0 */ + int esign; + int flags=0; + int l2powm1; + + r = 0.0L; + sign = 1; + e = ne = 0; + esign = 1; + + while(*s && isspace(*s)) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0L; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r *= 10.0L; + r += *s - '0'; + s++; + ne++; + } + } + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0.0L; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + if (esign < 0) + { + esign = -esign; + e = -e; + } + e = e - ne; + if (e < -4096) + { + /* possibly subnormal number, 10^e would overflow */ + r *= 1.0e-2048L; + e += 2048; + } + if (e < 0) + { + e = -e; + esign = -esign; + } + if (e >= 8192) + e = 8191; + if (e) + { + double d = 1.0L; + l2powm1 = 0; + while (e) + { + if (e & 1) + d *= powten[l2powm1]; + e >>= 1; + l2powm1++; + } + if (esign > 0) + r *= d; + else + r /= d; + } + if (sret) + *sret = (char *)s; + return r * sign; + + return 0; +} diff --git a/lib/crtdll/stdlib/strtoll.c b/lib/crtdll/stdlib/strtoll.c new file mode 100644 index 0000000..237aeac --- /dev/null +++ b/lib/crtdll/stdlib/strtoll.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +//#include + +/* constants used in Solaris */ +#define LLONG_MIN -9223372036854775807L-1L +#define LLONG_MAX 9223372036854775807L +#define ULLONG_MAX 18446744073709551615UL + +long +strtoll(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + +/* to prevent overflow, we take max-1 and add 1 after division */ + cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1; + cutlim = cutoff % base; + cutoff /= base; + if (++cutlim == base) + { + cutlim = 0; + cutoff++; + } + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LLONG_MIN : LLONG_MAX; + errno = ERANGE; + } + else if (neg) + acc *= -1; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/crtdll/stdlib/strtoul.c b/lib/crtdll/stdlib/strtoul.c new file mode 100644 index 0000000..ce4b432 --- /dev/null +++ b/lib/crtdll/stdlib/strtoul.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + __set_errno(ERANGE); + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/crtdll/stdlib/strtoull.c b/lib/crtdll/stdlib/strtoull.c new file mode 100644 index 0000000..d94845e --- /dev/null +++ b/lib/crtdll/stdlib/strtoull.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +//#include + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoull(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / base; + cutlim = (unsigned long)ULONG_MAX % base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + errno = ERANGE; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/crtdll/stdlib/swab.c b/lib/crtdll/stdlib/swab.c new file mode 100644 index 0000000..0126c59 --- /dev/null +++ b/lib/crtdll/stdlib/swab.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +void _swab (const char* caFrom, char* caTo, size_t sizeToCopy) +{ + unsigned long temp; + + sizeToCopy >>= 1; sizeToCopy++; +#define STEP temp = *((const char *)caFrom)++,*((char *)caTo)++ = *((const char *)caFrom)++,*((char *)caTo)++ = temp + /* round to multiple of 8 */ + while ((--sizeToCopy) & 07) + STEP; + sizeToCopy >>= 3; + while (--sizeToCopy >= 0) { + STEP; STEP; STEP; STEP; + STEP; STEP; STEP; STEP; + } +} diff --git a/lib/crtdll/stdlib/wcstom.c b/lib/crtdll/stdlib/wcstom.c new file mode 100644 index 0000000..9533eb2 --- /dev/null +++ b/lib/crtdll/stdlib/wcstom.c @@ -0,0 +1,14 @@ +#include + +size_t wcstombs (char* mbsDest, const wchar_t* wsConvert, size_t size) +{ + return 0; +} + +int wctomb (char* mbDest, wchar_t wc) +{ + return 0; +} + + + diff --git a/lib/crtdll/stdlib/wcstomb.c b/lib/crtdll/stdlib/wcstomb.c new file mode 100644 index 0000000..832672a --- /dev/null +++ b/lib/crtdll/stdlib/wcstomb.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include +#include + +#ifndef EILSEQ +#define EILSEQ EINVAL +#endif + +static const wchar_t encoding_mask[] = +{ + (wchar_t)~0x7ff, (wchar_t)~0xffff, (wchar_t)~0x1fffff, (wchar_t)~0x3ffffff +}; + +static const unsigned char encoding_byte[] = +{ + 0xc0, 0xe0, 0xf0, 0xf8, 0xfc +}; + +/* The state is for this UTF8 encoding not used. */ +//static mbstate_t internal; + + +//extern mbstate_t __no_r_state; /* Defined in mbtowc.c. */ + +size_t +__wcrtomb (char *s, wchar_t wc); + +/* Convert WCHAR into its multibyte character representation, + putting this in S and returning its length. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `wcrtomb'. */ +int +wctomb (char *s, wchar_t wchar) +{ + /* If S is NULL the function has to return null or not null + depending on the encoding having a state depending encoding or + not. This is nonsense because any multibyte encoding has a + state. The ISO C amendment 1 corrects this while introducing the + restartable functions. We simply say here all encodings have a + state. */ + if (s == NULL) + return 1; + + return __wcrtomb (s, wchar); +} + + +size_t +__wcrtomb (char *s, wchar_t wc) +{ + char fake[1]; + size_t written = 0; + + + + if (s == NULL) + { + s = fake; + wc = L'\0'; + } + + /* Store the UTF8 representation of WC. */ + if (wc < 0 || wc > 0x7fffffff) + { + /* This is no correct ISO 10646 character. */ + __set_errno (EILSEQ); + return (size_t) -1; + } + + if (wc < 0x80) + { + /* It's a one byte sequence. */ + if (s != NULL) + *s = (char) wc; + return 1; + } + + for (written = 2; written < 6; ++written) + if ((wc & encoding_mask[written - 2]) == 0) + break; + + if (s != NULL) + { + size_t cnt = written; + s[0] = encoding_byte[cnt - 2]; + + --cnt; + do + { + s[cnt] = 0x80 | (wc & 0x3f); + wc >>= 6; + } + while (--cnt > 0); + s[0] |= wc; + } + + return written; +} diff --git a/lib/crtdll/stdlib/wcstombs.c b/lib/crtdll/stdlib/wcstombs.c new file mode 100644 index 0000000..32fb7a0 --- /dev/null +++ b/lib/crtdll/stdlib/wcstombs.c @@ -0,0 +1,152 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +#ifndef EILSEQ +#define EILSEQ EINVAL +#endif + + +static const wchar_t encoding_mask[] = +{ + ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff +}; + +static const unsigned char encoding_byte[] = +{ + 0xc0, 0xe0, 0xf0, 0xf8, 0xfc +}; + +/* We don't need the state really because we don't have shift states + to maintain between calls to this function. */ +static mbstate_t internal; + + +extern mbstate_t __no_r_state; /* Defined in mbtowc.c. */ + +size_t +__wcsrtombs (char *dst, const wchar_t **src, size_t len, mbstate_t *ps); + +/* Convert the `wchar_t' string in PWCS to a multibyte character string + in S, writing no more than N characters. Return the number of bytes + written, or (size_t) -1 if an invalid `wchar_t' was found. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `wcsrtombs'. */ +size_t +wcstombs (char *s, const wchar_t *pwcs, size_t n) +{ + mbstate_t save_shift = __no_r_state; + size_t written; + + written = __wcsrtombs (s, &pwcs, n, &__no_r_state); + + /* Restore the old shift state. */ + __no_r_state = save_shift; + + /* Return how many we wrote (or maybe an error). */ + return written; +} + +size_t +__wcsrtombs (char *dst, const wchar_t **src, size_t len, mbstate_t *ps) +{ + size_t written = 0; + const wchar_t *run = *src; + + if (ps == NULL) + ps = &internal; + + if (dst == NULL) + /* The LEN parameter has to be ignored if we don't actually write + anything. */ + len = ~0; + + while (written < len) + { + wchar_t wc = *run++; + + if (wc < 0 || wc > 0x7fffffff) + { + /* This is no correct ISO 10646 character. */ + __set_errno (EILSEQ); + return (size_t) -1; + } + + if (wc == L'\0') + { + /* Found the end. */ + if (dst != NULL) + *dst = '\0'; + *src = NULL; + return written; + } + else if (wc < 0x80) + { + /* It's an one byte sequence. */ + if (dst != NULL) + *dst++ = (char) wc; + ++written; + } + else + { + size_t step; + + for (step = 2; step < 6; ++step) + if ((wc & encoding_mask[step - 2]) == 0) + break; + + if (written + step >= len) + /* Too long. */ + break; + + if (dst != NULL) + { + size_t cnt = step; + + dst[0] = encoding_byte[cnt - 2]; + + --cnt; + do + { + dst[cnt] = 0x80 | (wc & 0x3f); + wc >>= 6; + } + while (--cnt > 0); + dst[0] |= wc; + + dst += step; + } + + written += step; + } + } + + /* Store position of first unprocessed word. */ + *src = run; + + return written; +} +//weak_alias (__wcsrtombs, wcsrtombs) \ No newline at end of file diff --git a/lib/crtdll/string/.cvsignore b/lib/crtdll/string/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/string/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/string/memccpy.c b/lib/crtdll/string/memccpy.c new file mode 100644 index 0000000..ba13fa4 --- /dev/null +++ b/lib/crtdll/string/memccpy.c @@ -0,0 +1,9 @@ +#include + + +void * +_memccpy (void *to, const void *from,int c,size_t count) +{ + memcpy(to,from,count); + return memchr(to,c,count); +} diff --git a/lib/crtdll/string/memchr.c b/lib/crtdll/string/memchr.c new file mode 100644 index 0000000..cb0589f --- /dev/null +++ b/lib/crtdll/string/memchr.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + + +#include + +void * +memchr(const void *s, int c, size_t n) +{ + if (n) + { + const char *p = s; + do { + if (*p++ == c) + return (void *)(p-1); + } while (--n != 0); + } + return 0; +} diff --git a/lib/crtdll/string/memcmp.c b/lib/crtdll/string/memcmp.c new file mode 100644 index 0000000..ed5b9ae --- /dev/null +++ b/lib/crtdll/string/memcmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +memcmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (*p1++ != *p2++) + return (*--p1 - *--p2); + } while (--n != 0); + } + return 0; +} diff --git a/lib/crtdll/string/memcpy.c b/lib/crtdll/string/memcpy.c new file mode 100644 index 0000000..7a1f7f4 --- /dev/null +++ b/lib/crtdll/string/memcpy.c @@ -0,0 +1,16 @@ +#include + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +void * +memcpy (void *to, const void *from, size_t count) +{ + register char *f = (char *)from; + register char *t = (char *)to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; + + return to; +} diff --git a/lib/crtdll/string/memcpy.s b/lib/crtdll/string/memcpy.s new file mode 100644 index 0000000..2144836 --- /dev/null +++ b/lib/crtdll/string/memcpy.s @@ -0,0 +1,20 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + .file "memcpy.s" + .text + .align 4 + .globl _memcpy +_memcpy: + pushl %ebp + movl %esp,%ebp + pushl %esi + pushl %edi + movl 8(%ebp),%edi + movl 12(%ebp),%esi + movl 16(%ebp),%ecx + call ___dj_movedata + popl %edi + popl %esi + movl 8(%ebp),%eax + leave + ret + diff --git a/lib/crtdll/string/memicmp.c b/lib/crtdll/string/memicmp.c new file mode 100644 index 0000000..e95d771 --- /dev/null +++ b/lib/crtdll/string/memicmp.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_memicmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (toupper(*p1) != toupper(*p2)) + return (*p1 - *p2); + p1++; + p2++; + } while (--n != 0); + } + return 0; +} diff --git a/lib/crtdll/string/memmove.c b/lib/crtdll/string/memmove.c new file mode 100644 index 0000000..3315e10 --- /dev/null +++ b/lib/crtdll/string/memmove.c @@ -0,0 +1,36 @@ +#include + + +void * memmove(void *dest,const void *src,size_t count) +{ + char *char_dest = (char *)dest; + char *char_src = (char *)src; + + if ((char_dest <= char_src) || (char_dest >= (char_src+count))) + { + /* non-overlapping buffers */ + while(count > 0) + { + *char_dest = *char_src; + char_dest++; + char_src++; + count--; + } + } + else + { + /* overlaping buffers */ + char_dest = (char *)dest + count - 1; + char_src = (char *)src + count - 1; + + while(count > 0) + { + *char_dest = *char_src; + char_dest--; + char_src--; + count--; + } + } + + return dest; +} diff --git a/lib/crtdll/string/memmove.s b/lib/crtdll/string/memmove.s new file mode 100644 index 0000000..a667bbc --- /dev/null +++ b/lib/crtdll/string/memmove.s @@ -0,0 +1,33 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + .file "memmove.s" + .globl _memmove +_memmove: + pushl %ebp + movl %esp,%ebp + pushl %esi + pushl %edi + movl 8(%ebp),%edi + movl 12(%ebp),%esi + movl 16(%ebp),%ecx + jecxz L2 + cld + cmpl %esi,%edi + jb L3 + + std + addl %ecx,%esi + addl %ecx,%edi + decl %esi + decl %edi +L3: + rep + movsb + +L2: + cld + popl %edi + popl %esi + movl 8(%ebp),%eax + leave + ret + diff --git a/lib/crtdll/string/memset.c b/lib/crtdll/string/memset.c new file mode 100644 index 0000000..286ff5d --- /dev/null +++ b/lib/crtdll/string/memset.c @@ -0,0 +1,13 @@ +#include + +void * memset(void *src,int val,size_t count) +{ + char *char_src = (char *)src; + + while(count>0) { + *char_src = val; + char_src++; + count--; + } + return src; +} diff --git a/lib/crtdll/string/memset.s b/lib/crtdll/string/memset.s new file mode 100644 index 0000000..97d8c99 --- /dev/null +++ b/lib/crtdll/string/memset.s @@ -0,0 +1,51 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + .file "memset.s" + .text + .align 4 + .globl _memset +_memset: + pushl %ebp + movl %esp,%ebp + pushl %edi + movl 8(%ebp),%edi + movl 12(%ebp),%eax + movl 16(%ebp),%ecx + cld + + # We will handle memsets of <= 15 bytes one byte at a time. + # This avoids some extra overhead for small memsets, and + # knowing we are setting > 15 bytes eliminates some annoying + # checks in the "long move" case. + cmpl $15,%ecx + jle L3 + + # Otherwise, tile the byte value out into %eax. + # 0x41 -> 0x41414141, etc. + movb %al,%ah + movl %eax,%edx + sall $16,%eax + movw %dx,%ax + jmp L2 + + # Handle any cruft necessary to get %edi long-aligned. +L1: stosb + decl %ecx +L2: testl $3,%edi + jnz L1 + + # Now slam out all of the longs. + movl %ecx,%edx + shrl $2,%ecx + rep + stosl + + # Finally, handle any trailing cruft. We know the high three bytes + # of %ecx must be zero, so just put the "slop count" in the low byte. + movb %dl,%cl + andb $3,%cl +L3: rep + stosb + popl %edi + movl 8(%ebp),%eax + leave + ret diff --git a/lib/crtdll/string/str_old.c b/lib/crtdll/string/str_old.c new file mode 100644 index 0000000..7f959b5 --- /dev/null +++ b/lib/crtdll/string/str_old.c @@ -0,0 +1,49 @@ +/* + * string_old.c + * + * Oldnames from ANSI header string.h + * + * Some wrapper functions for those old name functions whose appropriate + * equivalents are not simply underscore prefixed. + * + * Contributors: + * Created by Colin Peters + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warrenties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include + +int +strcasecmp (const char* sz1, const char* sz2) +{ + return _stricmp (sz1, sz2); +} + +int +strncasecmp (const char* sz1, const char* sz2, size_t sizeMaxCompare) +{ + return _strnicmp (sz1, sz2, sizeMaxCompare); +} + +int +wcscmpi (const wchar_t* ws1, const wchar_t* ws2) +{ + //return wcsicmp (ws1, ws2); + return 0; +} + diff --git a/lib/crtdll/string/strcat.c b/lib/crtdll/string/strcat.c new file mode 100644 index 0000000..fd09547 --- /dev/null +++ b/lib/crtdll/string/strcat.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strcat(char *s, const char *append) +{ + char *save = s; + + for (; *s; ++s); + while ((*s++ = *append++)); + return save; +} diff --git a/lib/crtdll/string/strchr.c b/lib/crtdll/string/strchr.c new file mode 100644 index 0000000..4489403 --- /dev/null +++ b/lib/crtdll/string/strchr.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + + + +char *strchr(const char *s, int c); + +char *strchr(const char *s, int c) +{ + char cc = c; + while (*s) + { + if (*s == cc) + return (char *)s; + s++; + } + if (cc == 0) + return (char *)s; + return 0; +} + diff --git a/lib/crtdll/string/strcmp.c b/lib/crtdll/string/strcmp.c new file mode 100644 index 0000000..3f8c76e --- /dev/null +++ b/lib/crtdll/string/strcmp.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return *(unsigned const char *)s1 - *(unsigned const char *)(s2); +} diff --git a/lib/crtdll/string/strcoll.c b/lib/crtdll/string/strcoll.c new file mode 100644 index 0000000..07f5e24 --- /dev/null +++ b/lib/crtdll/string/strcoll.c @@ -0,0 +1,28 @@ +#include +#include +/* Compare S1 and S2, returning less than, equal to or + greater than zero if the collated form of S1 is lexicographically + less than, equal to or greater than the collated form of S2. */ + +#if 1 +int strcoll (const char* s1, const char* s2) +{ + return strcmp(s1,s2); +} + +int _stricoll (const char* s1, const char* s2) +{ + return _stricmp(s1,s2); +} +#else +int strcoll (const char *s1,const char *s2) +{ + int ret; + ret = CompareStringA(LOCALE_USER_DEFAULT,0,s1,strlen(s1),s2,strlen(s2)); + if (ret == 0) + return 0; + else + return ret - 2; + return 0; +} +#endif diff --git a/lib/crtdll/string/strcpy.c b/lib/crtdll/string/strcpy.c new file mode 100644 index 0000000..cf77c54 --- /dev/null +++ b/lib/crtdll/string/strcpy.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +char* strcpy(char *to, const char *from); + +char* strcpy(char *to, const char *from) +{ + char *save = to; + + for (; (*to = *from); ++from, ++to); + return save; +} diff --git a/lib/crtdll/string/strcspn.c b/lib/crtdll/string/strcspn.c new file mode 100644 index 0000000..430182d --- /dev/null +++ b/lib/crtdll/string/strcspn.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strcspn(const char *s1, const char *s2) +{ + const char *p, *spanp; + char c, sc; + + for (p = s1;;) + { + c = *p++; + spanp = s2; + do { + if ((sc = *spanp++) == c) + return p - 1 - s1; + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/crtdll/string/strdup.c b/lib/crtdll/string/strdup.c new file mode 100644 index 0000000..3214e4e --- /dev/null +++ b/lib/crtdll/string/strdup.c @@ -0,0 +1,16 @@ + +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char *_strdup(const char *_s) +{ + char *rv; + if (_s == 0) + return 0; + rv = (char *)malloc(strlen(_s) + 1); + if (rv == 0) + return 0; + strcpy(rv, _s); + return rv; +} diff --git a/lib/crtdll/string/strerror.c b/lib/crtdll/string/strerror.c new file mode 100644 index 0000000..7fad6fb --- /dev/null +++ b/lib/crtdll/string/strerror.c @@ -0,0 +1,101 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + + +char __syserr00[] = "No Error"; +char __syserr01[] = "Input to function out of range (EDOM)"; +char __syserr02[] = "Output of function out of range (ERANGE)"; +char __syserr03[] = "Argument list too long (E2BIG)"; +char __syserr04[] = "Permission denied (EACCES)"; +char __syserr05[] = "Resource temporarily unavailable (EAGAIN)"; +char __syserr06[] = "Bad file descriptor (EBADF)"; +char __syserr07[] = "Resource busy (EBUSY)"; +char __syserr08[] = "No child processes (ECHILD)"; +char __syserr09[] = "Resource deadlock avoided (EDEADLK)"; +char __syserr10[] = "File exists (EEXIST)"; +char __syserr11[] = "Bad address (EFAULT)"; +char __syserr12[] = "File too large (EFBIG)"; +char __syserr13[] = "Interrupted system call (EINTR)"; +char __syserr14[] = "Invalid argument (EINVAL)"; +char __syserr15[] = "Input or output error (EIO)"; +char __syserr16[] = "Is a directory (EISDIR)"; +char __syserr17[] = "Too many open files (EMFILE)"; +char __syserr18[] = "Too many links (EMLINK)"; +char __syserr19[] = "File name too long (ENAMETOOLONG)"; +char __syserr20[] = "Too many open files in system (ENFILE)"; +char __syserr21[] = "No such device (ENODEV)"; +char __syserr22[] = "No such file or directory (ENOENT)"; +char __syserr23[] = "Unable to execute file (ENOEXEC)"; +char __syserr24[] = "No locks available (ENOLCK)"; +char __syserr25[] = "Not enough memory (ENOMEM)"; +char __syserr26[] = "No space left on drive (ENOSPC)"; +char __syserr27[] = "Function not implemented (ENOSYS)"; +char __syserr28[] = "Not a directory (ENOTDIR)"; +char __syserr29[] = "Directory not empty (ENOTEMPTY)"; +char __syserr30[] = "Inappropriate I/O control operation (ENOTTY)"; +char __syserr31[] = "No such device or address (ENXIO)"; +char __syserr32[] = "Operation not permitted (EPERM)"; +char __syserr33[] = "Broken pipe (EPIPE)"; +char __syserr34[] = "Read-only file system (EROFS)"; +char __syserr35[] = "Invalid seek (ESPIPE)"; +char __syserr36[] = "No such process (ESRCH)"; +char __syserr37[] = "Improper link (EXDEV)"; +char __syserr38[] = "No more files (ENMFILE)"; + +const char *_sys_errlist[] = { +__syserr00, __syserr01, __syserr02, __syserr03, __syserr04, +__syserr05, __syserr06, __syserr07, __syserr08, __syserr09, +__syserr10, __syserr11, __syserr12, __syserr13, __syserr14, +__syserr15, __syserr16, __syserr17, __syserr18, __syserr19, +__syserr20, __syserr21, __syserr22, __syserr23, __syserr24, +__syserr25, __syserr26, __syserr27, __syserr28, __syserr29, +__syserr30, __syserr31, __syserr32, __syserr33, __syserr34, +__syserr35, __syserr36, __syserr37, __syserr38 +}; + +int __sys_nerr = sizeof(_sys_errlist) / sizeof(_sys_errlist[0]); + +int* _sys_nerr_dll = &__sys_nerr; + +char *strerror(int errnum) +{ + static char ebuf[40]; /* 64-bit number + slop */ + char *cp; + int v=1000000, lz=0; + + if (errnum >= 0 && errnum < __sys_nerr) + return((char *)_sys_errlist[errnum]); + + strcpy(ebuf, "Unknown error: "); + cp = ebuf + 15; + if (errnum < 0) + { + *cp++ = '-'; + errnum = -errnum; + } + while (v) + { + int d = errnum / v; + if (d || lz || (v == 1)) + { + *cp++ = d+'0'; + lz = 1; + } + errnum %= v; + v /= 10; + } + + return ebuf; +} + + +char *_strerror(const char *s) +{ + if ( s == NULL ) + return strerror(errno); + + return strerror(atoi(s)); +} diff --git a/lib/crtdll/string/stricmp.c b/lib/crtdll/string/stricmp.c new file mode 100644 index 0000000..913ceef --- /dev/null +++ b/lib/crtdll/string/stricmp.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_stricmp(const char *s1, const char *s2) +{ + while (toupper(*s1) == toupper(*s2)) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); +} + +int +_strcmpi(const char *s1, const char *s2) +{ + return _stricmp(s1,s2); +} diff --git a/lib/crtdll/string/strlen.c b/lib/crtdll/string/strlen.c new file mode 100644 index 0000000..c68a3dd --- /dev/null +++ b/lib/crtdll/string/strlen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strlen(const char *str) +{ + const char *s; + + if (str == 0) + return 0; + for (s = str; *s; ++s); + return s-str; +} + diff --git a/lib/crtdll/string/strlwr.c b/lib/crtdll/string/strlwr.c new file mode 100644 index 0000000..9a11967 --- /dev/null +++ b/lib/crtdll/string/strlwr.c @@ -0,0 +1,23 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + +#include +#include + +char * _strlwr(char *x) +{ + char *y=x; + + while (*y) { + *y=tolower(*y); + y++; + } + return x; +} diff --git a/lib/crtdll/string/strncat.c b/lib/crtdll/string/strncat.c new file mode 100644 index 0000000..d3803fe --- /dev/null +++ b/lib/crtdll/string/strncat.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strncat(char *dst, const char *src, size_t n) +{ + if (n != 0) + { + char *d = dst; + const char *s = src; + + while (*d != 0) + d++; + do { + if ((*d = *s++) == 0) + break; + d++; + } while (--n != 0); + *d = 0; + } + return dst; +} diff --git a/lib/crtdll/string/strncmp.c b/lib/crtdll/string/strncmp.c new file mode 100644 index 0000000..0f2950e --- /dev/null +++ b/lib/crtdll/string/strncmp.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return 0; + do { + if (*s1 != *s2++) + return *(unsigned const char *)s1 - *(unsigned const char *)--s2; + if (*s1++ == 0) + break; + } while (--n != 0); + return 0; +} diff --git a/lib/crtdll/string/strncpy.c b/lib/crtdll/string/strncpy.c new file mode 100644 index 0000000..428a235 --- /dev/null +++ b/lib/crtdll/string/strncpy.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) { + char *d = dst; + const char *s = src; + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + } while (--n != 0); + } + return dst; +} diff --git a/lib/crtdll/string/strnicmp.c b/lib/crtdll/string/strnicmp.c new file mode 100644 index 0000000..30563e9 --- /dev/null +++ b/lib/crtdll/string/strnicmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int _strnicmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return 0; + do { + if (toupper(*s1) != toupper(*s2++)) + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)--s2); + if (*s1++ == 0) + break; + } while (--n != 0); + return 0; +} diff --git a/lib/crtdll/string/strnlen.c b/lib/crtdll/string/strnlen.c new file mode 100644 index 0000000..6b92fb3 --- /dev/null +++ b/lib/crtdll/string/strnlen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strnlen(const char *str, size_t count) +{ + const char *s; + + if (str == 0) + return 0; + for (s = str; *s && count; ++s, count--); + return s-str; +} + diff --git a/lib/crtdll/string/strpbrk.c b/lib/crtdll/string/strpbrk.c new file mode 100644 index 0000000..c2968ae --- /dev/null +++ b/lib/crtdll/string/strpbrk.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +char * +strpbrk(const char *s1, const char *s2) +{ + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return (char *)(s1 - 1); + } + return 0; +} diff --git a/lib/crtdll/string/strrchr.c b/lib/crtdll/string/strrchr.c new file mode 100644 index 0000000..688d6bf --- /dev/null +++ b/lib/crtdll/string/strrchr.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +//#include + +char * +strrchr(const char *s, int c) +{ + char cc = c; + const char *sp=(char *)0; + while (*s) + { + if (*s == cc) + sp = s; + s++; + } + if (cc == 0) + sp = s; + return (char *)sp; +} + diff --git a/lib/crtdll/string/strrev.c b/lib/crtdll/string/strrev.c new file mode 100644 index 0000000..757ab08 --- /dev/null +++ b/lib/crtdll/string/strrev.c @@ -0,0 +1,18 @@ +#include + +char * _strrev(char *s) +{ + char *e; + char a; + e=s; + while (*e) + e++; + while (s +#include + +char* _strnset (char* szToFill, int szFill, size_t sizeMaxFill) +{ + char *t = szToFill; + int i = 0; + while( *szToFill != 0 && i < sizeMaxFill) + { + *szToFill = szFill; + szToFill++; + i++; + + } + return t; +} + +char* _strset (char* szToFill, int szFill) +{ + char *t = szToFill; + while( *szToFill != 0 ) + { + *szToFill = szFill; + szToFill++; + + } + return t; +} diff --git a/lib/crtdll/string/strspn.c b/lib/crtdll/string/strspn.c new file mode 100644 index 0000000..d6e234d --- /dev/null +++ b/lib/crtdll/string/strspn.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strspn(const char *s1, const char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (p - 1 - s1); +} diff --git a/lib/crtdll/string/strspnp.c b/lib/crtdll/string/strspnp.c new file mode 100644 index 0000000..bbb1e3b --- /dev/null +++ b/lib/crtdll/string/strspnp.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strspnp(const char *s1, const char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return p; +} diff --git a/lib/crtdll/string/strstr.c b/lib/crtdll/string/strstr.c new file mode 100644 index 0000000..e62eeb0 --- /dev/null +++ b/lib/crtdll/string/strstr.c @@ -0,0 +1,23 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +//#include + +char * +strstr(const char *s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) + { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return 0; + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return (char *)s; +} diff --git a/lib/crtdll/string/strtok.c b/lib/crtdll/string/strtok.c new file mode 100644 index 0000000..62b0fdc --- /dev/null +++ b/lib/crtdll/string/strtok.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strtok(char *s, const char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s++; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/crtdll/string/strtoul.c b/lib/crtdll/string/strtoul.c new file mode 100644 index 0000000..5a007e4 --- /dev/null +++ b/lib/crtdll/string/strtoul.c @@ -0,0 +1,27 @@ +#include +#include + +unsigned long strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} diff --git a/lib/crtdll/string/strupr.c b/lib/crtdll/string/strupr.c new file mode 100644 index 0000000..4cb0af4 --- /dev/null +++ b/lib/crtdll/string/strupr.c @@ -0,0 +1,24 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + + +#include +#include + +char *_strupr(char *x) +{ + char *y=x; + + while (*y) { + *y=toupper(*y); + y++; + } + return x; +} diff --git a/lib/crtdll/string/strxfrm.c b/lib/crtdll/string/strxfrm.c new file mode 100644 index 0000000..b23687c --- /dev/null +++ b/lib/crtdll/string/strxfrm.c @@ -0,0 +1,22 @@ +#include +#include + +#if 1 +size_t strxfrm( char *dest, const char *src, size_t n ) +{ +} +#else +size_t strxfrm( char *dest, const char *src, size_t n ) +{ + + int ret = LCMapStringA(LOCALE_USER_DEFAULT,LCMAP_LOWERCASE, + src, strlen(src), + dest, strlen(dest) ); + + + if ( ret == 0 ) + return -1; + return ret; + +} +#endif diff --git a/lib/crtdll/sys_stat/.cvsignore b/lib/crtdll/sys_stat/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/sys_stat/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/sys_stat/fstat.c b/lib/crtdll/sys_stat/fstat.c new file mode 100644 index 0000000..96a1e6c --- /dev/null +++ b/lib/crtdll/sys_stat/fstat.c @@ -0,0 +1,54 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/sys/fstat.c + * PURPOSE: Gather file information + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include +#include +#include +#include + + +int +_fstat(int fd, struct stat *statbuf) +{ + + BY_HANDLE_FILE_INFORMATION FileInformation; + + if (!statbuf) + { + __set_errno(EINVAL); + return -1; + } + + if ( !GetFileInformationByHandle(_get_osfhandle(fd),&FileInformation) ) { + __set_errno (EBADF); + return -1; + } + statbuf->st_ctime = FileTimeToUnixTime( &FileInformation.ftCreationTime,NULL); + statbuf->st_atime = FileTimeToUnixTime( &FileInformation.ftLastAccessTime,NULL); + statbuf->st_mtime = FileTimeToUnixTime( &FileInformation.ftLastWriteTime,NULL); + if (statbuf->st_atime ==0) + statbuf->st_atime = statbuf->st_mtime; + if (statbuf->st_ctime ==0) + statbuf->st_ctime = statbuf->st_mtime; + + statbuf->st_dev = FileInformation.dwVolumeSerialNumber; + statbuf->st_size = FileInformation.nFileSizeLow; + statbuf->st_nlink = FileInformation.nNumberOfLinks; + statbuf->st_mode = S_IREAD; + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + statbuf->st_mode |= S_IFDIR | S_IEXEC; + else + statbuf->st_mode |= S_IFREG; + if ( !(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + statbuf->st_mode |= S_IWRITE; + return 0; +} diff --git a/lib/crtdll/sys_stat/ftime.c b/lib/crtdll/sys_stat/ftime.c new file mode 100644 index 0000000..c78ad44 --- /dev/null +++ b/lib/crtdll/sys_stat/ftime.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1994, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +// crtdll has void return type instead of int +void +_ftime (timebuf) + struct timeb *timebuf; +{ + int save = errno; + struct tm *tp; + + __set_errno (0); + if (time (&timebuf->time) == (time_t) -1 && errno != 0) + return; + timebuf->millitm = 0; + tp = localtime(&timebuf->time); + if (tp == NULL) + return; + + timebuf->_timezone = tp->tm_gmtoff / 60; + timebuf->dstflag = tp->tm_isdst; + + free(tp); + __set_errno (save); + return; +} + diff --git a/lib/crtdll/sys_stat/futime.c b/lib/crtdll/sys_stat/futime.c new file mode 100644 index 0000000..cde6bfb --- /dev/null +++ b/lib/crtdll/sys_stat/futime.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include + +int _futime (int nHandle, struct _utimbuf *pTimes) +{ + FILETIME LastAccessTime; + FILETIME LastWriteTime; + + // check for stdin / stdout handles ?? + if ( nHandle == -1 ) { + __set_errno(EBADF); + return -1; + } + + if ( pTimes == NULL ) { + pTimes = alloca(sizeof(struct _utimbuf)); + time(&pTimes->actime); + time(&pTimes->modtime); + } + + if ( pTimes->actime < pTimes->modtime ) { + __set_errno(EINVAL); + return -1; + } + + UnixTimeToFileTime(pTimes->actime,&LastAccessTime,0); + UnixTimeToFileTime(pTimes->modtime,&LastWriteTime,0); + if ( !SetFileTime(_get_osfhandle(nHandle),NULL, &LastAccessTime, &LastWriteTime) ) { + __set_errno(EBADF); + return -1; + } + + return 0; +} diff --git a/lib/crtdll/sys_stat/stat.c b/lib/crtdll/sys_stat/stat.c new file mode 100644 index 0000000..f12d4b1 --- /dev/null +++ b/lib/crtdll/sys_stat/stat.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include + + +int _stat( const char *path, struct stat *buffer ) +{ + WIN32_FIND_DATA wfd; + HANDLE fh; + fh = FindFirstFile (path,&wfd); + if ( fh == INVALID_HANDLE_VALUE ) + { + __set_errno(ENOFILE); + return -1; + } + if ( ! (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + int fd = _open(path,_O_RDONLY); + int ret; + + ret = fstat(fd,buffer); + _close(fd); + + return ret; + } + buffer->st_ctime = FileTimeToUnixTime( &wfd.ftCreationTime,NULL); + buffer->st_atime = FileTimeToUnixTime( &wfd.ftLastAccessTime,NULL); + buffer->st_mtime = FileTimeToUnixTime( &wfd.ftLastWriteTime,NULL); + + if (buffer->st_atime ==0) + buffer->st_atime = buffer->st_mtime; + if (buffer->st_ctime ==0) + buffer->st_ctime = buffer->st_mtime; + + buffer->st_mode = S_IREAD; + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buffer->st_mode |= S_IFDIR; + else + buffer->st_mode |= S_IFREG; + if ( ! (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buffer->st_mode |= S_IWRITE | S_IEXEC; + + buffer->st_size = wfd.nFileSizeLow; + buffer->st_nlink = 1; + if (FindNextFile(fh,&wfd)) + { + __set_errno(ENOFILE); + FindClose(fh); + return -1; + } + return 0; +} diff --git a/lib/crtdll/sys_stat/systime.c b/lib/crtdll/sys_stat/systime.c new file mode 100644 index 0000000..2289ad4 --- /dev/null +++ b/lib/crtdll/sys_stat/systime.c @@ -0,0 +1,67 @@ +#include +#include + + +int month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31}; +unsigned int _getsystime(struct tm *tp) +{ + SYSTEMTIME Time; + TIME_ZONE_INFORMATION TimeZoneInformation; + DWORD TimeZoneId; + int i; + + GetLocalTime(&Time); + + tp->tm_year = Time.wYear - 1900; + tp->tm_mon = Time.wMonth - 1; + tp->tm_wday = Time.wDayOfWeek; + tp->tm_mday = Time.wDay; + tp->tm_hour = Time.wHour; + tp->tm_min = Time.wMinute; + tp->tm_sec = Time.wSecond; + + tp->tm_isdst = -1; + + //FIXME GetTimeZoneInformation currently not in kernel32 + + //TimeZoneId = GetTimeZoneInformation(&TimeZoneInformation ); + //if ( TimeZoneId == TIME_ZONE_ID_DAYLIGHT ) { + // tp->tm_isdst = 1; + //} + //else + // tp->tm_isdst = 0; + + + + if ( tp->tm_year%4 == 0 ) { + if (tp->tm_year%100 != 0 ) + tp->tm_yday = 1; + else if ( (tp->tm_year-100)%1000 == 0 ) + tp->tm_yday = 1; + } + + for(i=0;i<=tp->tm_mon;i++) + tp->tm_yday += month[i]; + + return Time.wMilliseconds; +} + + +unsigned int _setsystime(struct tm *tp, unsigned int ms) +{ + SYSTEMTIME Time; + + Time.wYear = tp->tm_year + 1900; + Time.wMonth = tp->tm_mon + 1; + Time.wDayOfWeek = tp->tm_wday; + Time.wDay = tp->tm_mday; + Time.wHour = tp->tm_hour; + Time.wMinute = tp->tm_min; + Time.wSecond = tp->tm_sec; + Time.wMilliseconds = ms; + + if ( !SetLocalTime(&Time)) + return -1; + + return 0; +} diff --git a/lib/crtdll/tchar/.cvsignore b/lib/crtdll/tchar/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/tchar/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/tchar/strdec.c b/lib/crtdll/tchar/strdec.c new file mode 100644 index 0000000..05cbf98 --- /dev/null +++ b/lib/crtdll/tchar/strdec.c @@ -0,0 +1,7 @@ +#include + +char * _strdec(const char *str1, const char *str2) +{ + return (char *) (( str1 >= str2 ) ? ( str1 ) : --str2); +} + diff --git a/lib/crtdll/tchar/strinc.c b/lib/crtdll/tchar/strinc.c new file mode 100644 index 0000000..bb1b49f --- /dev/null +++ b/lib/crtdll/tchar/strinc.c @@ -0,0 +1,6 @@ +#include + +char * _strinc(const char *str) +{ + return (char *)(++str); +} diff --git a/lib/crtdll/tchar/strncnt.c b/lib/crtdll/tchar/strncnt.c new file mode 100644 index 0000000..b47cc20 --- /dev/null +++ b/lib/crtdll/tchar/strncnt.c @@ -0,0 +1,8 @@ +#include +#include +#include + +size_t _strncnt( const char *str, size_t max) +{ + return strnlen(str,max); +} diff --git a/lib/crtdll/tchar/strnextc.c b/lib/crtdll/tchar/strnextc.c new file mode 100644 index 0000000..b1c0585 --- /dev/null +++ b/lib/crtdll/tchar/strnextc.c @@ -0,0 +1,6 @@ +#include + +int _strnextc(const char *str) +{ + return *(++str); +} diff --git a/lib/crtdll/tchar/strninc.c b/lib/crtdll/tchar/strninc.c new file mode 100644 index 0000000..75f279b --- /dev/null +++ b/lib/crtdll/tchar/strninc.c @@ -0,0 +1,7 @@ +#include +#include + +char * _strninc(const char *str, size_t inc) +{ + return (char *)(str + inc); +} diff --git a/lib/crtdll/tchar/strspnp.c b/lib/crtdll/tchar/strspnp.c new file mode 100644 index 0000000..3656740 --- /dev/null +++ b/lib/crtdll/tchar/strspnp.c @@ -0,0 +1,9 @@ +#include +#include + + +char * _strspnp( const char * str1, const char * str2) +{ + return NULL; +} + diff --git a/lib/crtdll/time/.cvsignore b/lib/crtdll/time/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/time/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/time/clock.c b/lib/crtdll/time/clock.c new file mode 100644 index 0000000..4fcda91 --- /dev/null +++ b/lib/crtdll/time/clock.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/time/clock.c + * PURPOSE: Get elapsed time + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + +VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); + +clock_t clock ( void ) +{ + FILETIME CreationTime; + FILETIME ExitTime; + FILETIME KernelTime; + FILETIME UserTime; + + DWORD Remainder; + + if ( !GetProcessTimes(GetCurrentProcess(),&CreationTime,&ExitTime,&KernelTime,&UserTime ) ) + return -1; + + + return FileTimeToUnixTime( &KernelTime,&Remainder ) + FileTimeToUnixTime( &UserTime,&Remainder ); +} diff --git a/lib/crtdll/time/ctime.c b/lib/crtdll/time/ctime.c new file mode 100644 index 0000000..9f33c97 --- /dev/null +++ b/lib/crtdll/time/ctime.c @@ -0,0 +1,1413 @@ + +// fix djdir + +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* This file has been modified by DJ Delorie. These modifications are +** Copyright (C) 1995 DJ Delorie, 24 Kirsten Ave, Rochester NH, +** 03867-2954, USA. +*/ + +/* + * Copyright (c) 1987, 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ctime.c 5.23 (Berkeley) 6/22/90"; +#endif /* LIBC_SCCS and not lint */ + +/* +** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). +** POSIX-style TZ environment variable handling from Guy Harris +** (guy@auspex.com). +*/ + + + + +#include +#include +#include +#include +#include +#include + +#include +#include "tzfile.h" + +#include + +#include "posixrul.h" + +#define P(s) s +#define alloc_size_t size_t +#define qsort_size_t size_t +#define fread_size_t size_t +#define fwrite_size_t size_t + +#define ACCESS_MODE O_RDONLY|O_BINARY +#define OPEN_MODE O_RDONLY|O_BINARY + +/* +** Someone might make incorrect use of a time zone abbreviation: +** 1. They might reference tzname[0] before calling tzset (explicitly +** or implicitly). +** 2. They might reference tzname[1] before calling tzset (explicitly +** or implicitly). +** 3. They might reference tzname[1] after setting to a time zone +** in which Daylight Saving Time is never observed. +** 4. They might reference tzname[0] after setting to a time zone +** in which Standard Time is never observed. +** 5. They might reference tm.TM_ZONE after calling offtime. +** What's best to do in the above cases is open to debate; +** for now, we just set things up so that in any of the five cases +** WILDABBR is used. Another possibility: initialize tzname[0] to the +** string "tzname[0] used before set", and similarly for the other cases. +** And another: initialize tzname[0] to "ERA", with an explanation in the +** manual page of what this "time zone abbreviation" means (doing this so +** that tzname[0] has the "normal" length of three characters). +*/ +int _daylight_dll; +int _timezone_dll; + +static char WILDABBR[] = " "; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif /* !defined TRUE */ + +static const char GMT[] = "GMT"; + +struct ttinfo { /* time type information */ + long tt_gmtoff; /* GMT offset in seconds */ + int tt_isdst; /* used to set tm_isdst */ + int tt_abbrind; /* abbreviation list index */ + int tt_ttisstd; /* TRUE if transition is std time */ +}; + +struct lsinfo { /* leap second information */ + time_t ls_trans; /* transition time */ + long ls_corr; /* correction to apply */ +}; + +struct state { + int leapcnt; + int timecnt; + int typecnt; + int charcnt; + time_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; + struct ttinfo ttis[TZ_MAX_TYPES]; + char chars[(TZ_MAX_CHARS + 1 > sizeof GMT) ? TZ_MAX_CHARS + 1 : sizeof GMT]; + struct lsinfo lsis[TZ_MAX_LEAPS]; +}; + +struct rule { + int r_type; /* type of rule--see below */ + int r_day; /* day number of rule */ + int r_week; /* week number of rule */ + int r_mon; /* month number of rule */ + long r_time; /* transition time of rule */ +}; + +#define JULIAN_DAY 0 /* Jn - Julian day */ +#define DAY_OF_YEAR 1 /* n - day of year */ +#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ + +/* +** Prototypes for static functions. +*/ + +static long detzcode P((const char * codep)); +static const char * getzname P((const char * strp)); +static const char * getnum P((const char * strp, int * nump, int min, + int max)); +static const char * getsecs P((const char * strp, long * secsp)); +static const char * getoffset P((const char * strp, long * offsetp)); +static const char * getrule P((const char * strp, struct rule * rulep)); +static void gmtload P((struct state * sp)); +static void gmtsub P((const time_t * timep, long offset, + struct tm * tmp)); +static void localsub P((const time_t * timep, long offset, + struct tm * tmp)); +static void normalize P((int * tensptr, int * unitsptr, int base)); +static void settzname P((void)); +static time_t time1 P((struct tm * tmp, void (* funcp)(const time_t * const, const long, struct tm * const), + long offset)); +static time_t time2 P((struct tm *tmp, void (* funcp)(const time_t * const, const long, struct tm * const), + long offset, int * okayp)); +static void timesub P((const time_t * timep, long offset, + const struct state * sp, struct tm * tmp)); +static int tmcomp P((const struct tm * atmp, + const struct tm * btmp)); +static time_t transtime P((time_t janfirst, int year, + const struct rule * rulep, long offset)); +static int tzload P((const char * name, struct state * sp)); +static int tzparse P((const char * name, struct state * sp, + int lastditch)); +static void tzsetwall(void); + +#ifdef ALL_STATE +static struct state *lclptr; +static struct state *gmtptr; +#endif /* defined ALL_STATE */ + +#ifndef ALL_STATE +static struct state lclmem; +static struct state gmtmem; +#define lclptr (&lclmem) +#define gmtptr (&gmtmem) +#endif /* State Farm */ + +static int lcl_is_set; +static int gmt_is_set; + +char * _tzname[2] = { + WILDABBR, + WILDABBR +}; + +static long +detzcode(const char * const codep) +{ + long result; + int i; + + result = 0; + for (i = 0; i < 4; ++i) + result = (result << 8) | (codep[i] & 0xff); + return result; +} + +static void +settzname(void) +{ + const struct state * const sp = lclptr; + int i; + + _tzname[0] = WILDABBR; + _tzname[1] = WILDABBR; +#ifdef ALL_STATE + if (sp == NULL) + { + _tzname[0] = _tzname[1] = GMT; + return; + } +#endif /* defined ALL_STATE */ + for (i = 0; i < sp->typecnt; ++i) + { + register const struct ttinfo * const ttisp = &sp->ttis[i]; + + _tzname[ttisp->tt_isdst] = + (char *)&sp->chars[ttisp->tt_abbrind]; +#if 0 + if (ttisp->tt_isdst) + _daylight = 1; + if (i == 0 || !ttisp->tt_isdst) + _timezone_dll = -(ttisp->tt_gmtoff); + if (i == 0 || ttisp->tt_isdst) + _altzone = -(ttisp->tt_gmtoff); +#endif + } + /* + ** And to get the latest zone names into tzname. . . + */ + for (i = 0; i < sp->timecnt; ++i) + { + const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]]; + + _tzname[ttisp->tt_isdst] = (char *)&sp->chars[ttisp->tt_abbrind]; + } +} + +static char * +tzdir(void) +{ + static char dir[80]={0}, *cp; + if (dir[0] == 0) + { + if ((cp = getenv("TZDIR"))) + { + strcpy(dir, cp); + } + else if ((cp = getenv("DJDIR"))) + { + strcpy(dir, cp); + strcat(dir, "/zoneinfo"); + } + else + strcpy(dir, "./"); + } + return dir; +} + +static int +tzload(const char *name, struct state * const sp) +{ + const char * p; + int i; + int fid; + char fullname[FILENAME_MAX + 1]; + const struct tzhead * tzhp; + char buf[sizeof *sp + sizeof *tzhp]; + int ttisstdcnt; + + if (name == NULL && (name = TZDEFAULT) == NULL) + return -1; + + if (name[0] == ':') + ++name; + if (name[0] != '/') + { + if ((p = tzdir()) == NULL) + return -1; + if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) + return -1; + strcpy(fullname, p); + strcat(fullname, "/"); + strcat(fullname, name); + name = fullname; + } + + if ((fid = open(name, OPEN_MODE)) == -1) + { + const char *base = strrchr(name, '/'); + if (base) + base++; + else + base = name; + if (strcmp(base, "posixrules")) + return -1; + + /* We've got a built-in copy of posixrules just in case */ + memcpy(buf, _posixrules_data, sizeof(_posixrules_data)); + i = sizeof(_posixrules_data); + } + else + { + i = read(fid, buf, sizeof buf); + if (close(fid) != 0 || i < sizeof *tzhp) + return -1; + } + + tzhp = (struct tzhead *) buf; + ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt); + sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt); + sp->timecnt = (int) detzcode(tzhp->tzh_timecnt); + sp->typecnt = (int) detzcode(tzhp->tzh_typecnt); + sp->charcnt = (int) detzcode(tzhp->tzh_charcnt); + if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || + sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || + sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || + sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || + (ttisstdcnt != sp->typecnt && ttisstdcnt != 0)) + return -1; + if (i < sizeof *tzhp + + sp->timecnt * (4 + sizeof (char)) + + sp->typecnt * (4 + 2 * sizeof (char)) + + sp->charcnt * sizeof (char) + + sp->leapcnt * 2 * 4 + + ttisstdcnt * sizeof (char)) + return -1; + p = buf + sizeof *tzhp; + for (i = 0; i < sp->timecnt; ++i) + { + sp->ats[i] = detzcode(p); + p += 4; + } + for (i = 0; i < sp->timecnt; ++i) + { + sp->types[i] = (unsigned char) *p++; + if (sp->types[i] >= sp->typecnt) + return -1; + } + for (i = 0; i < sp->typecnt; ++i) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[i]; + ttisp->tt_gmtoff = detzcode(p); + p += 4; + ttisp->tt_isdst = (unsigned char) *p++; + if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) + return -1; + ttisp->tt_abbrind = (unsigned char) *p++; + if (ttisp->tt_abbrind < 0 || + ttisp->tt_abbrind > sp->charcnt) + return -1; + } + for (i = 0; i < sp->charcnt; ++i) + sp->chars[i] = *p++; + sp->chars[i] = '\0'; /* ensure '\0' at end */ + for (i = 0; i < sp->leapcnt; ++i) + { + struct lsinfo * lsisp; + + lsisp = &sp->lsis[i]; + lsisp->ls_trans = detzcode(p); + p += 4; + lsisp->ls_corr = detzcode(p); + p += 4; + } + for (i = 0; i < sp->typecnt; ++i) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[i]; + if (ttisstdcnt == 0) + ttisp->tt_ttisstd = FALSE; + else + { + ttisp->tt_ttisstd = *p++; + if (ttisp->tt_ttisstd != TRUE && + ttisp->tt_ttisstd != FALSE) + return -1; + } + } + return 0; +} + +static const int mon_lengths[2][MONSPERYEAR] = { +{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, +{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const int year_lengths[2] = { +DAYSPERNYEAR, DAYSPERLYEAR +}; + +/* +** Given a pointer into a time zone string, scan until a character that is not +** a valid character in a zone name is found. Return a pointer to that +** character. +*/ + +static const char * +getzname(const char *strp) +{ + char c; + + while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' && + c != '+') + ++strp; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a number from that string. +** Check that the number is within a specified range; if it is not, return +** NULL. +** Otherwise, return a pointer to the first character not part of the number. +*/ + +static const char * +getnum(const char *strp, int * const nump, const int min, const int max) +{ + char c; + int num; + + if (strp == NULL || !isdigit(*strp)) + return NULL; + num = 0; + while ((c = *strp) != '\0' && isdigit(c)) + { + num = num * 10 + (c - '0'); + if (num > max) + return NULL; + ++strp; + } + if (num < min) + return NULL; + *nump = num; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a number of seconds, +** in hh[:mm[:ss]] form, from the string. +** If any error occurs, return NULL. +** Otherwise, return a pointer to the first character not part of the number +** of seconds. +*/ + +static const char * +getsecs(const char *strp, long * const secsp) +{ + int num; + + strp = getnum(strp, &num, 0, HOURSPERDAY); + if (strp == NULL) + return NULL; + *secsp = num * SECSPERHOUR; + if (*strp == ':') + { + ++strp; + strp = getnum(strp, &num, 0, MINSPERHOUR - 1); + if (strp == NULL) + return NULL; + *secsp += num * SECSPERMIN; + if (*strp == ':') + { + ++strp; + strp = getnum(strp, &num, 0, SECSPERMIN - 1); + if (strp == NULL) + return NULL; + *secsp += num; + } + } + return strp; +} + +/* +** Given a pointer into a time zone string, extract an offset, in +** [+-]hh[:mm[:ss]] form, from the string. +** If any error occurs, return NULL. +** Otherwise, return a pointer to the first character not part of the time. +*/ + +static const char * +getoffset(const char *strp, long * const offsetp) +{ + int neg; + + if (*strp == '-') + { + neg = 1; + ++strp; + } + else if (isdigit(*strp) || *strp++ == '+') + neg = 0; + else + return NULL; /* illegal offset */ + strp = getsecs(strp, offsetp); + if (strp == NULL) + return NULL; /* illegal time */ + if (neg) + *offsetp = -*offsetp; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a rule in the form +** date[/time]. See POSIX section 8 for the format of "date" and "time". +** If a valid rule is not found, return NULL. +** Otherwise, return a pointer to the first character not part of the rule. +*/ + +static const char * +getrule(const char *strp, struct rule * const rulep) +{ + if (*strp == 'J') + { + /* + ** Julian day. + */ + rulep->r_type = JULIAN_DAY; + ++strp; + strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); + } + else if (*strp == 'M') + { + /* + ** Month, week, day. + */ + rulep->r_type = MONTH_NTH_DAY_OF_WEEK; + ++strp; + strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); + if (strp == NULL) + return NULL; + if (*strp++ != '.') + return NULL; + strp = getnum(strp, &rulep->r_week, 1, 5); + if (strp == NULL) + return NULL; + if (*strp++ != '.') + return NULL; + strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); + } + else if (isdigit(*strp)) + { + /* + ** Day of year. + */ + rulep->r_type = DAY_OF_YEAR; + strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); + } + else + return NULL; /* invalid format */ + if (strp == NULL) + return NULL; + if (*strp == '/') + { + /* + ** Time specified. + */ + ++strp; + strp = getsecs(strp, &rulep->r_time); + } + else + rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ + return strp; +} + +/* +** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the +** year, a rule, and the offset from GMT at the time that rule takes effect, +** calculate the Epoch-relative time that rule takes effect. +*/ + +static time_t +transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset) +{ + int leapyear; + time_t value=0; + int i; + int d, m1, yy0, yy1, yy2, dow; + + leapyear = isleap(year); + switch (rulep->r_type) + { + + case JULIAN_DAY: + /* + ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap + ** years. + ** In non-leap years, or if the day number is 59 or less, just + ** add SECSPERDAY times the day number-1 to the time of + ** January 1, midnight, to get the day. + */ + value = janfirst + (rulep->r_day - 1) * SECSPERDAY; + if (leapyear && rulep->r_day >= 60) + value += SECSPERDAY; + break; + + case DAY_OF_YEAR: + /* + ** n - day of year. + ** Just add SECSPERDAY times the day number to the time of + ** January 1, midnight, to get the day. + */ + value = janfirst + rulep->r_day * SECSPERDAY; + break; + + case MONTH_NTH_DAY_OF_WEEK: + /* + ** Mm.n.d - nth "dth day" of month m. + */ + value = janfirst; + for (i = 0; i < rulep->r_mon - 1; ++i) + value += mon_lengths[leapyear][i] * SECSPERDAY; + + /* + ** Use Zeller's Congruence to get day-of-week of first day of + ** month. + */ + m1 = (rulep->r_mon + 9) % 12 + 1; + yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; + yy1 = yy0 / 100; + yy2 = yy0 % 100; + dow = ((26 * m1 - 2) / 10 + + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; + if (dow < 0) + dow += DAYSPERWEEK; + + /* + ** "dow" is the day-of-week of the first day of the month. Get + ** the day-of-month (zero-origin) of the first "dow" day of the + ** month. + */ + d = rulep->r_day - dow; + if (d < 0) + d += DAYSPERWEEK; + for (i = 1; i < rulep->r_week; ++i) + { + if (d + DAYSPERWEEK >= + mon_lengths[leapyear][rulep->r_mon - 1]) + break; + d += DAYSPERWEEK; + } + + /* + ** "d" is the day-of-month (zero-origin) of the day we want. + */ + value += d * SECSPERDAY; + break; + } + + /* + ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in + ** question. To get the Epoch-relative time of the specified local + ** time on that day, add the transition time and the current offset + ** from GMT. + */ + return value + rulep->r_time + offset; +} + +/* +** Given a POSIX section 8-style TZ string, fill in the rule tables as +** appropriate. +*/ + +static int +tzparse(const char *name, struct state * const sp, const int lastditch) +{ + const char * stdname; + const char * dstname=0; + int stdlen; + int dstlen; + long stdoffset; + long dstoffset; + time_t * atp; + unsigned char * typep; + char * cp; + int load_result; + + stdname = name; + if (lastditch) + { + stdlen = strlen(name); /* length of standard zone name */ + name += stdlen; + if (stdlen >= sizeof sp->chars) + stdlen = (sizeof sp->chars) - 1; + } + else + { + name = getzname(name); + stdlen = name - stdname; + if (stdlen < 3) + return -1; + } + if (*name == '\0') + return -1; + else + { + name = getoffset(name, &stdoffset); + if (name == NULL) + return -1; + } + load_result = tzload(TZDEFRULES, sp); + if (load_result != 0) + sp->leapcnt = 0; /* so, we're off a little */ + if (*name != '\0') + { + dstname = name; + name = getzname(name); + dstlen = name - dstname; /* length of DST zone name */ + if (dstlen < 3) + return -1; + if (*name != '\0' && *name != ',' && *name != ';') + { + name = getoffset(name, &dstoffset); + if (name == NULL) + return -1; + } + else + dstoffset = stdoffset - SECSPERHOUR; + if (*name == ',' || *name == ';') + { + struct rule start; + struct rule end; + int year; + time_t janfirst; + time_t starttime; + time_t endtime; + + ++name; + if ((name = getrule(name, &start)) == NULL) + return -1; + if (*name++ != ',') + return -1; + if ((name = getrule(name, &end)) == NULL) + return -1; + if (*name != '\0') + return -1; + sp->typecnt = 2; /* standard time and DST */ + /* + ** Two transitions per year, from EPOCH_YEAR to 2037. + */ + sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); + if (sp->timecnt > TZ_MAX_TIMES) + return -1; + sp->ttis[0].tt_gmtoff = -dstoffset; + sp->ttis[0].tt_isdst = 1; + sp->ttis[0].tt_abbrind = stdlen + 1; + sp->ttis[1].tt_gmtoff = -stdoffset; + sp->ttis[1].tt_isdst = 0; + sp->ttis[1].tt_abbrind = 0; + atp = sp->ats; + typep = sp->types; + janfirst = 0; + for (year = EPOCH_YEAR; year <= 2037; ++year) + { + starttime = transtime(janfirst, year, &start, + stdoffset); + endtime = transtime(janfirst, year, &end, + dstoffset); + if (starttime > endtime) + { + *atp++ = endtime; + *typep++ = 1; /* DST ends */ + *atp++ = starttime; + *typep++ = 0; /* DST begins */ + } + else + { + *atp++ = starttime; + *typep++ = 0; /* DST begins */ + *atp++ = endtime; + *typep++ = 1; /* DST ends */ + } + janfirst += + year_lengths[isleap(year)] * SECSPERDAY; + } + } + else + { + int sawstd; + int sawdst; + long stdfix; + long dstfix; + long oldfix; + int isdst; + int i; + + if (*name != '\0') + return -1; + if (load_result != 0) + return -1; + /* + ** Compute the difference between the real and + ** prototype standard and summer time offsets + ** from GMT, and put the real standard and summer + ** time offsets into the rules in place of the + ** prototype offsets. + */ + sawstd = FALSE; + sawdst = FALSE; + stdfix = 0; + dstfix = 0; + for (i = 0; i < sp->typecnt; ++i) + { + if (sp->ttis[i].tt_isdst) + { + oldfix = dstfix; + dstfix = + sp->ttis[i].tt_gmtoff + dstoffset; + if (sawdst && (oldfix != dstfix)) + return -1; + sp->ttis[i].tt_gmtoff = -dstoffset; + sp->ttis[i].tt_abbrind = stdlen + 1; + sawdst = TRUE; + } + else + { + oldfix = stdfix; + stdfix = + sp->ttis[i].tt_gmtoff + stdoffset; + if (sawstd && (oldfix != stdfix)) + return -1; + sp->ttis[i].tt_gmtoff = -stdoffset; + sp->ttis[i].tt_abbrind = 0; + sawstd = TRUE; + } + } + /* + ** Make sure we have both standard and summer time. + */ + if (!sawdst || !sawstd) + return -1; + /* + ** Now correct the transition times by shifting + ** them by the difference between the real and + ** prototype offsets. Note that this difference + ** can be different in standard and summer time; + ** the prototype probably has a 1-hour difference + ** between standard and summer time, but a different + ** difference can be specified in TZ. + */ + isdst = FALSE; /* we start in standard time */ + for (i = 0; i < sp->timecnt; ++i) + { + const struct ttinfo * ttisp; + + /* + ** If summer time is in effect, and the + ** transition time was not specified as + ** standard time, add the summer time + ** offset to the transition time; + ** otherwise, add the standard time offset + ** to the transition time. + */ + ttisp = &sp->ttis[sp->types[i]]; + sp->ats[i] += + (isdst && !ttisp->tt_ttisstd) ? + dstfix : stdfix; + isdst = ttisp->tt_isdst; + } + } + } + else + { + dstlen = 0; + sp->typecnt = 1; /* only standard time */ + sp->timecnt = 0; + sp->ttis[0].tt_gmtoff = -stdoffset; + sp->ttis[0].tt_isdst = 0; + sp->ttis[0].tt_abbrind = 0; + } + sp->charcnt = stdlen + 1; + if (dstlen != 0) + sp->charcnt += dstlen + 1; + if (sp->charcnt > sizeof sp->chars) + return -1; + cp = sp->chars; + (void) strncpy(cp, stdname, stdlen); + cp += stdlen; + *cp++ = '\0'; + if (dstlen != 0) + { + (void) strncpy(cp, dstname, dstlen); + *(cp + dstlen) = '\0'; + } + return 0; +} + +static void +gmtload(struct state * const sp) +{ + if (tzload(GMT, sp) != 0) + (void) tzparse(GMT, sp, TRUE); +} + +void +_tzset(void) +{ + const char * name; + + name = getenv("TZ"); + if (name == NULL) + { + tzsetwall(); + return; + } + lcl_is_set = TRUE; +#ifdef ALL_STATE + if (lclptr == NULL) + { + lclptr = (struct state *) malloc(sizeof *lclptr); + if (lclptr == NULL) + { + settzname(); /* all we can do */ + return; + } + } +#endif /* defined ALL_STATE */ + if (*name == '\0') + { + /* + ** User wants it fast rather than right. + */ + lclptr->leapcnt = 0; /* so, we're off a little */ + lclptr->timecnt = 0; + lclptr->ttis[0].tt_gmtoff = 0; + lclptr->ttis[0].tt_abbrind = 0; + (void) strcpy(lclptr->chars, GMT); + } + else if (tzload(name, lclptr) != 0) + if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) + gmtload(lclptr); + settzname(); +} + +void +tzsetwall(void) +{ + lcl_is_set = TRUE; +#ifdef ALL_STATE + if (lclptr == NULL) + { + lclptr = (struct state *) malloc(sizeof *lclptr); + if (lclptr == NULL) + { + settzname(); /* all we can do */ + return; + } + } +#endif /* defined ALL_STATE */ + if (tzload((char *) NULL, lclptr) != 0) + gmtload(lclptr); + settzname(); +} + +/* +** The easy way to behave "as if no library function calls" localtime +** is to not call it--so we drop its guts into "localsub", which can be +** freely called. (And no, the PANS doesn't require the above behavior-- +** but it *is* desirable.) +** +** The unused offset argument is for the benefit of mktime variants. +*/ + +/*ARGSUSED*/ +static void +localsub(const time_t * const timep, const long offset, struct tm * const tmp) +{ + const struct state * sp; + const struct ttinfo * ttisp; + int i; + const time_t t = *timep; + + if (!lcl_is_set) + _tzset(); + sp = lclptr; +#ifdef ALL_STATE + if (sp == NULL) + { + gmtsub(timep, offset, tmp); + return; + } +#endif /* defined ALL_STATE */ + if (sp->timecnt == 0 || t < sp->ats[0]) + { + i = 0; + while (sp->ttis[i].tt_isdst) + if (++i >= sp->typecnt) + { + i = 0; + break; + } + } + else + { + for (i = 1; i < sp->timecnt; ++i) + if (t < sp->ats[i]) + break; + i = sp->types[i - 1]; + } + ttisp = &sp->ttis[i]; + /* + ** To get (wrong) behavior that's compatible with System V Release 2.0 + ** you'd replace the statement below with + ** t += ttisp->tt_gmtoff; + ** timesub(&t, 0L, sp, tmp); + */ + timesub(&t, ttisp->tt_gmtoff, sp, tmp); + tmp->tm_isdst = ttisp->tt_isdst; + _tzname[tmp->tm_isdst] = (char *)&sp->chars[ttisp->tt_abbrind]; + tmp->tm_zone = (char *)&sp->chars[ttisp->tt_abbrind]; +} + +struct tm * +localtime(const time_t * const timep) +{ + static struct tm tm; + + localsub(timep, 0L, &tm); + return &tm; +} + +/* +** gmtsub is to gmtime as localsub is to localtime. +*/ + +static void +gmtsub(const time_t * const timep, const long offset, struct tm * const tmp) +{ + if (!gmt_is_set) + { + gmt_is_set = TRUE; +#ifdef ALL_STATE + gmtptr = (struct state *) malloc(sizeof *gmtptr); + if (gmtptr != NULL) +#endif /* defined ALL_STATE */ + gmtload(gmtptr); + } + timesub(timep, offset, gmtptr, tmp); + /* + ** Could get fancy here and deliver something such as + ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero, + ** but this is no time for a treasure hunt. + */ + if (offset != 0) + tmp->tm_zone = WILDABBR; + else + { +#ifdef ALL_STATE + if (gmtptr == NULL) + tmp->TM_ZONE = GMT; + else + tmp->TM_ZONE = gmtptr->chars; +#endif /* defined ALL_STATE */ +#ifndef ALL_STATE + tmp->tm_zone = gmtptr->chars; +#endif /* State Farm */ + } +} + +struct tm * +gmtime(const time_t * const timep) +{ + static struct tm tm; + + gmtsub(timep, 0L, &tm); + return &tm; +} + +static void +timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp) +{ + const struct lsinfo * lp; + long days; + long rem; + int y; + int yleap; + const int * ip; + long corr; + int hit; + int i; + + corr = 0; + hit = FALSE; +#ifdef ALL_STATE + i = (sp == NULL) ? 0 : sp->leapcnt; +#endif /* defined ALL_STATE */ +#ifndef ALL_STATE + i = sp->leapcnt; +#endif /* State Farm */ + while (--i >= 0) + { + lp = &sp->lsis[i]; + if (*timep >= lp->ls_trans) + { + if (*timep == lp->ls_trans) + hit = ((i == 0 && lp->ls_corr > 0) || + lp->ls_corr > sp->lsis[i - 1].ls_corr); + corr = lp->ls_corr; + break; + } + } + days = *timep / SECSPERDAY; + rem = *timep % SECSPERDAY; +#ifdef mc68k + if (*timep == 0x80000000) + { + /* + ** A 3B1 muffs the division on the most negative number. + */ + days = -24855; + rem = -11648; + } +#endif /* mc68k */ + rem += (offset - corr); + while (rem < 0) + { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) + { + rem -= SECSPERDAY; + ++days; + } + tmp->tm_hour = (int) (rem / SECSPERHOUR); + rem = rem % SECSPERHOUR; + tmp->tm_min = (int) (rem / SECSPERMIN); + tmp->tm_sec = (int) (rem % SECSPERMIN); + if (hit) + /* + ** A positive leap second requires a special + ** representation. This uses "... ??:59:60". + */ + ++(tmp->tm_sec); + tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); + if (tmp->tm_wday < 0) + tmp->tm_wday += DAYSPERWEEK; + y = EPOCH_YEAR; + if (days >= 0) + for ( ; ; ) + { + yleap = isleap(y); + if (days < (long) year_lengths[yleap]) + break; + ++y; + days = days - (long) year_lengths[yleap]; + } + else + do { + --y; + yleap = isleap(y); + days = days + (long) year_lengths[yleap]; + } while (days < 0); + tmp->tm_year = y - TM_YEAR_BASE; + tmp->tm_yday = (int) days; + ip = mon_lengths[yleap]; + for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) + days = days - (long) ip[tmp->tm_mon]; + tmp->tm_mday = (int) (days + 1); + tmp->tm_isdst = 0; + tmp->tm_gmtoff = offset; +} + +/* +** A la X3J11 +*/ + +char * +asctime(const struct tm *timeptr) +{ + static const char wday_name[DAYSPERWEEK][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char mon_name[MONSPERYEAR][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + static char result[26]; + + (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + wday_name[timeptr->tm_wday], + mon_name[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, + TM_YEAR_BASE + timeptr->tm_year); + return result; +} + +char * +ctime(const time_t * const timep) +{ + return asctime(localtime(timep)); +} + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static void +normalize(int * const tensptr, int * const unitsptr, const int base) +{ + if (*unitsptr >= base) + { + *tensptr += *unitsptr / base; + *unitsptr %= base; + } + else if (*unitsptr < 0) + { + --*tensptr; + *unitsptr += base; + if (*unitsptr < 0) + { + *tensptr -= 1 + (-*unitsptr) / base; + *unitsptr = base - (-*unitsptr) % base; + } + } +} + +static int +tmcomp(const struct tm * const atmp, const struct tm * const btmp) +{ + int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t +time2(struct tm *tmp, void (*const funcp)(const time_t *const,const long,struct tm *), const long offset, int * const okayp) +{ + const struct state * sp; + int dir; + int bits; + int i, j ; + int saved_seconds; + time_t newt; + time_t t; + struct tm yourtm, mytm; + + *okayp = FALSE; + yourtm = *tmp; + if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0) + normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN); + normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR); + normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY); + normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR); + while (yourtm.tm_mday <= 0) + { + --yourtm.tm_year; + yourtm.tm_mday += + year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; + } + for ( ; ; ) + { + i = mon_lengths[isleap(yourtm.tm_year + + TM_YEAR_BASE)][yourtm.tm_mon]; + if (yourtm.tm_mday <= i) + break; + yourtm.tm_mday -= i; + if (++yourtm.tm_mon >= MONSPERYEAR) + { + yourtm.tm_mon = 0; + ++yourtm.tm_year; + } + } + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (time_t) 1 << bits; + for ( ; ; ) + { + (*funcp)(&t, offset, &mytm); + dir = tmcomp(&mytm, &yourtm); + if (dir != 0) + { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) + break; + /* + ** Right time, wrong type. + ** Hunt for right time, right type. + ** It's okay to guess wrong since the guess + ** gets checked. + */ + sp = (const struct state *) + ((funcp == localsub) ? lclptr : gmtptr); +#ifdef ALL_STATE + if (sp == NULL) + return WRONG; +#endif /* defined ALL_STATE */ + for (i = 0; i < sp->typecnt; ++i) + { + if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) + continue; + for (j = 0; j < sp->typecnt; ++j) + { + if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) + continue; + newt = t + sp->ttis[j].tt_gmtoff - + sp->ttis[i].tt_gmtoff; + (*funcp)(&newt, offset, &mytm); + if (tmcomp(&mytm, &yourtm) != 0) + continue; + if (mytm.tm_isdst != yourtm.tm_isdst) + continue; + /* + ** We have a match. + */ + t = newt; + goto label; + } + } + return WRONG; + } + label: + t += saved_seconds; + (*funcp)(&t, offset, tmp); + *okayp = TRUE; + return t; +} + +static time_t +time1(struct tm * const tmp, void (*const funcp)(const time_t * const, const long, struct tm *), const long offset) +{ + time_t t; + const struct state * sp; + int samei, otheri; + int okay; + + if (tmp->tm_isdst > 1) + tmp->tm_isdst = 1; + t = time2(tmp, funcp, offset, &okay); + if (okay || tmp->tm_isdst < 0) + return t; + /* + ** We're supposed to assume that somebody took a time of one type + ** and did some math on it that yielded a "struct tm" that's bad. + ** We try to divine the type they started from and adjust to the + ** type they need. + */ + sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); +#ifdef ALL_STATE + if (sp == NULL) + return WRONG; +#endif /* defined ALL_STATE */ + for (samei = 0; samei < sp->typecnt; ++samei) + { + if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) + continue; + for (otheri = 0; otheri < sp->typecnt; ++otheri) + { + if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) + continue; + tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - + sp->ttis[samei].tt_gmtoff; + tmp->tm_isdst = !tmp->tm_isdst; + t = time2(tmp, funcp, offset, &okay); + if (okay) + return t; + tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - + sp->ttis[samei].tt_gmtoff; + tmp->tm_isdst = !tmp->tm_isdst; + } + } + return WRONG; +} + +time_t +mktime(struct tm * tmp) +{ + return time1(tmp, localsub, 0L); +} + + + + diff --git a/lib/crtdll/time/difftime.c b/lib/crtdll/time/difftime.c new file mode 100644 index 0000000..97d6b59 --- /dev/null +++ b/lib/crtdll/time/difftime.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +difftime(time_t time1, time_t time0) +{ + return time1-time0; +} diff --git a/lib/crtdll/time/posixrul.h b/lib/crtdll/time/posixrul.h new file mode 100644 index 0000000..48c5cee --- /dev/null +++ b/lib/crtdll/time/posixrul.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* generated with bin2h from DJGPP/zoneinfo/posixrules */ + +unsigned char _posixrules_data[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,16,0,0,0,2,0,0,0,8,0,151,254,240,1,135,225,224,2,119,224,240,3,112,254,96,4,96,253,112,5,80, +224,96,6,64,223,112,7,48,194,96,7,141,25,112,9,16,164,96,9,173,148,240,10,240,134,96,11,224,133,112,12,217,162, +224,13,192,103,112,14,185,132,224,15,169,131,240,16,153,102,224,17,137,101,240,18,121,72,224,19,105,71,240,20,89,42,224, +21,73,41,240,22,57,12,224,23,41,11,240,24,34,41,96,25,8,237,240,26,2,11,96,26,242,10,112,27,225,237,96,28, +209,236,112,29,193,207,96,30,177,206,112,31,161,177,96,32,118,0,240,33,129,147,96,34,85,226,240,35,106,175,224,36,53, +196,240,37,74,145,224,38,21,166,240,39,42,115,224,39,254,195,112,41,10,85,224,41,222,165,112,42,234,55,224,43,190,135, +112,44,211,84,96,45,158,105,112,46,179,54,96,47,126,75,112,48,147,24,96,49,103,103,240,50,114,250,96,51,71,73,240, +52,82,220,96,53,39,43,240,54,50,190,96,55,7,13,240,56,27,218,224,56,230,239,240,57,251,188,224,58,198,209,240,59, +219,158,224,60,175,238,112,61,187,128,224,62,143,208,112,63,155,98,224,64,111,178,112,65,132,127,96,66,79,148,112,67,100, +97,96,68,47,118,112,69,68,67,96,70,15,88,112,71,36,37,96,71,248,116,240,73,4,7,96,73,216,86,240,74,227,233, +96,75,184,56,240,76,205,5,224,77,152,26,240,78,172,231,224,79,119,252,240,80,140,201,224,81,97,25,112,82,108,171,224, +83,64,251,112,84,76,141,224,85,32,221,112,86,44,111,224,87,0,191,112,88,21,140,96,88,224,161,112,89,245,110,96,90, +192,131,112,91,213,80,96,92,169,159,240,93,181,50,96,94,137,129,240,95,149,20,96,96,105,99,240,97,126,48,224,98,73, +69,240,99,94,18,224,100,41,39,240,101,61,244,224,102,18,68,112,103,29,214,224,103,242,38,112,104,253,184,224,105,210,8, +112,106,221,154,224,107,177,234,112,108,198,183,96,109,145,204,112,110,166,153,96,111,113,174,112,112,134,123,96,113,90,202,240, +114,102,93,96,115,58,172,240,116,70,63,96,117,26,142,240,118,47,91,224,118,250,112,240,120,15,61,224,120,218,82,240,121, +239,31,224,122,186,52,240,123,207,1,224,124,163,81,112,125,174,227,224,126,131,51,112,127,142,197,224,128,99,21,112,129,119, +226,96,130,66,247,112,131,87,196,96,132,34,217,112,133,55,166,96,134,11,245,240,135,23,136,96,135,235,215,240,136,247,106, +96,137,203,185,240,138,215,76,96,139,171,155,240,140,192,104,224,141,139,125,240,142,160,74,224,143,107,95,240,144,128,44,224, +145,84,124,112,146,96,14,224,147,52,94,112,148,63,240,224,149,20,64,112,150,41,13,96,150,244,34,112,152,8,239,96,152, +212,4,112,153,232,209,96,154,189,32,240,155,200,179,96,156,157,2,240,157,168,149,96,158,124,228,240,159,136,119,96,160,92, +198,240,161,113,147,224,162,60,168,240,163,81,117,224,164,28,138,240,165,49,87,224,166,5,167,112,167,17,57,224,167,229,137, +112,168,241,27,224,169,197,107,112,170,218,56,96,171,165,77,112,172,186,26,96,173,133,47,112,174,153,252,96,175,101,17,112, +176,121,222,96,177,78,45,240,178,89,192,96,179,46,15,240,180,57,162,96,181,13,241,240,182,34,190,224,182,237,211,240,184, +2,160,224,184,205,181,240,185,226,130,224,186,182,210,112,187,194,100,224,188,150,180,112,189,162,70,224,190,118,150,112,191,130, +40,224,192,86,120,112,193,107,69,96,194,54,90,112,195,75,39,96,196,22,60,112,197,43,9,96,197,255,88,240,199,10,235, +96,199,223,58,240,200,234,205,96,201,191,28,240,202,211,233,224,203,158,254,240,204,179,203,224,205,126,224,240,206,147,173,224, +207,103,253,112,208,115,143,224,209,71,223,112,210,83,113,224,211,39,193,112,212,51,83,224,213,7,163,112,214,28,112,96,214, +231,133,112,215,252,82,96,216,199,103,112,217,220,52,96,218,176,131,240,219,188,22,96,220,144,101,240,221,155,248,96,222,112, +71,240,223,133,20,224,224,80,41,240,225,100,246,224,226,48,11,240,227,68,216,224,228,15,237,240,229,36,186,224,229,249,10, +112,231,4,156,224,231,216,236,112,232,228,126,224,233,184,206,112,234,205,155,96,235,152,176,112,236,173,125,96,237,120,146,112, +238,141,95,96,239,97,174,240,240,109,65,96,241,65,144,240,242,77,35,96,243,33,114,240,244,45,5,96,245,1,84,240,246, +22,33,224,246,225,54,240,247,246,3,224,248,193,24,240,249,213,229,224,250,160,250,240,251,181,199,224,252,138,23,112,253,149, +169,224,254,105,249,112,255,117,139,224,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,255,255,199,192,1,0,255,255,185,176,0,4,69,68,84, +0,69,83,84,0,0,0 +}; diff --git a/lib/crtdll/time/strdate.c b/lib/crtdll/time/strdate.c new file mode 100644 index 0000000..ca9b013 --- /dev/null +++ b/lib/crtdll/time/strdate.c @@ -0,0 +1,30 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/time/strtime.c + * PURPOSE: Fills a buffer with a formatted date representation + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include + +char *_strdate( const char *datestr ) +{ + + time_t t; + struct tm *d; + char *dt = (char *)datestr; + + if ( datestr == NULL ){ + __set_errno(EINVAL); + return NULL; + } + t = time(NULL); + d = localtime(&t); + sprintf(dt,"%d/%d/%d",d->tm_mday,d->tm_mon+1,d->tm_year); + return dt; +} diff --git a/lib/crtdll/time/strftime.c b/lib/crtdll/time/strftime.c new file mode 100644 index 0000000..c5c65df --- /dev/null +++ b/lib/crtdll/time/strftime.c @@ -0,0 +1,264 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +#define TM_YEAR_BASE 1900 + +static const char *afmt[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", +}; +static const char *Afmt[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", + "Saturday", +}; +static const char *bfmt[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec", +}; +static const char *Bfmt[] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December", +}; + +static size_t gsize; +static char *pt; + +static int +_add(const char *str) +{ + for (;; ++pt, --gsize) + { + if (!gsize) + return 0; + if (!(*pt = *str++)) + return 1; + } +} + +static int +_conv(int n, int digits, char pad) +{ + static char buf[10]; + char *p; + + for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) + *p-- = n % 10 + '0'; + while (p > buf && digits-- > 0) + *p-- = pad; + return _add(++p); +} + +static size_t +_fmt(const char *format, const struct tm *t) +{ + for (; *format; ++format) + { + if (*format == '%') { + if (*(format+1) == '#' ) {format++;} + + switch(*++format) + { + case '\0': + --format; + break; + case 'A': + if (t->tm_wday < 0 || t->tm_wday > 6) + return 0; + if (!_add(Afmt[t->tm_wday])) + return 0; + continue; + case 'a': + if (t->tm_wday < 0 || t->tm_wday > 6) + return 0; + if (!_add(afmt[t->tm_wday])) + return 0; + continue; + case 'B': + if (t->tm_mon < 0 || t->tm_mon > 11) + return 0; + if (!_add(Bfmt[t->tm_mon])) + return 0; + continue; + case 'b': + case 'h': + if (t->tm_mon < 0 || t->tm_mon > 11) + return 0; + if (!_add(bfmt[t->tm_mon])) + return 0; + continue; + case 'C': + if (!_fmt("%a %b %e %H:%M:%S %Y", t)) + return 0; + continue; + case 'c': + if (!_fmt("%m/%d/%y %H:%M:%S", t)) + return 0; + continue; + case 'e': + if (!_conv(t->tm_mday, 2, ' ')) + return 0; + continue; + case 'D': + if (!_fmt("%m/%d/%y", t)) + return 0; + continue; + case 'd': + if (!_conv(t->tm_mday, 2, '0')) + return 0; + continue; + case 'H': + if (!_conv(t->tm_hour, 2, '0')) + return 0; + continue; + case 'I': + if (!_conv(t->tm_hour % 12 ? + t->tm_hour % 12 : 12, 2, '0')) + return 0; + continue; + case 'j': + if (!_conv(t->tm_yday + 1, 3, '0')) + return 0; + continue; + case 'k': + if (!_conv(t->tm_hour, 2, ' ')) + return 0; + continue; + case 'l': + if (!_conv(t->tm_hour % 12 ? + t->tm_hour % 12 : 12, 2, ' ')) + return 0; + continue; + case 'M': + if (!_conv(t->tm_min, 2, '0')) + return 0; + continue; + case 'm': + if (!_conv(t->tm_mon + 1, 2, '0')) + return 0; + continue; + case 'n': + if (!_add("\n")) + return 0; + continue; + case 'p': + if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) + return 0; + continue; + case 'R': + if (!_fmt("%H:%M", t)) + return 0; + continue; + case 'r': + if (!_fmt("%I:%M:%S %p", t)) + return 0; + continue; + case 'S': + if (!_conv(t->tm_sec, 2, '0')) + return 0; + continue; + case 'T': + case 'X': + if (!_fmt("%H:%M:%S", t)) + return 0; + continue; + case 't': + if (!_add("\t")) + return 0; + continue; + case 'U': + if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, + 2, '0')) + return 0; + continue; + case 'W': + if (!_conv((t->tm_yday + 7 - + (t->tm_wday ? (t->tm_wday - 1) : 6)) + / 7, 2, '0')) + return 0; + continue; + case 'w': + if (!_conv(t->tm_wday, 1, '0')) + return 0; + continue; + case 'x': + if (!_fmt("%m/%d/%y", t)) + return 0; + continue; + case 'y': + if (!_conv((t->tm_year + TM_YEAR_BASE) + % 100, 2, '0')) + return 0; + continue; + case 'Y': + if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) + return 0; + continue; + case 'Z': + if (!t->tm_zone || !_add(t->tm_zone)) + return 0; + continue; + case '%': + /* + * X311J/88-090 (4.12.3.5): if conversion char is + * undefined, behavior is undefined. Print out the + * character itself as printf(3) does. + */ + default: + break; + } + } + if (!gsize--) + return 0; + *pt++ = *format; + } + return gsize; +} + +size_t +strftime(char *s, size_t maxsize, const char *format, const struct tm *t) +{ + pt = s; + if ((gsize = maxsize) < 1) + return 0; + if (_fmt(format, t)) + { + *pt = '\0'; + return maxsize - gsize; + } + return 0; +} + +size_t +wcsftime(wchar_t *s, size_t maxsize, const wchar_t *format, const struct tm *t) +{ + char *x; + char *f; + int i,j; + x = malloc(maxsize); + j = wcslen(format); + f = malloc(j+1); + for(i=0;i +#include +#include +#include + +char *_strtime(char* buf) +{ + time_t t; + struct tm *d; + char *dt = (char *)buf; + + if ( buf == NULL ) { + __set_errno(EINVAL); + return NULL; + } + t = time(NULL); + d = localtime(&t); + sprintf(dt,"%d:%d:%d",d->tm_hour,d->tm_min,d->tm_sec); + return dt; +} diff --git a/lib/crtdll/time/time.c b/lib/crtdll/time/time.c new file mode 100644 index 0000000..3a49372 --- /dev/null +++ b/lib/crtdll/time/time.c @@ -0,0 +1,219 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/time.c + * PURPOSE: Get system time + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +/* + * DOS file system functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include + +VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); + +time_t +time(time_t *t) +{ + FILETIME SystemTime; + DWORD Remainder; + GetSystemTimeAsFileTime(&SystemTime); + return FileTimeToUnixTime( &SystemTime,&Remainder ); +} + +/*********************************************************************** + * DOSFS_UnixTimeToFileTime + * + * Convert a Unix time to FILETIME format. + * The FILETIME structure is a 64-bit value representing the number of + * 100-nanosecond intervals since January 1, 1601, 0:00. + * 'remainder' is the nonnegative number of 100-ns intervals + * corresponding to the time fraction smaller than 1 second that + * couldn't be stored in the time_t value. + */ +void UnixTimeToFileTime( time_t unix_time, FILETIME *filetime, + DWORD remainder ) +{ + /* NOTES: + + CONSTANTS: + The time difference between 1 January 1601, 00:00:00 and + 1 January 1970, 00:00:00 is 369 years, plus the leap years + from 1604 to 1968, excluding 1700, 1800, 1900. + This makes (1968 - 1600) / 4 - 3 = 89 leap days, and a total + of 134774 days. + + Any day in that period had 24 * 60 * 60 = 86400 seconds. + + The time difference is 134774 * 86400 * 10000000, which can be written + 116444736000000000 + 27111902 * 2^32 + 3577643008 + 413 * 2^48 + 45534 * 2^32 + 54590 * 2^16 + 32768 + + If you find that these constants are buggy, please change them in all + instances in both conversion functions. + + VERSIONS: + There are two versions, one of them uses long long variables and + is presumably faster but not ISO C. The other one uses standard C + data types and operations but relies on the assumption that negative + numbers are stored as 2's complement (-1 is 0xffff....). If this + assumption is violated, dates before 1970 will not convert correctly. + This should however work on any reasonable architecture where WINE + will run. + + DETAILS: + + Take care not to remove the casts. I have tested these functions + (in both versions) for a lot of numbers. I would be interested in + results on other compilers than GCC. + + The operations have been designed to account for the possibility + of 64-bit time_t in future UNICES. Even the versions without + internal long long numbers will work if time_t only is 64 bit. + A 32-bit shift, which was necessary for that operation, turned out + not to work correctly in GCC, besides giving the warning. So I + used a double 16-bit shift instead. Numbers are in the ISO version + represented by three limbs, the most significant with 32 bit, the + other two with 16 bit each. + + As the modulo-operator % is not well-defined for negative numbers, + negative divisors have been avoided in DOSFS_FileTimeToUnixTime. + + There might be quicker ways to do this in C. Certainly so in + assembler. + + Claus Fischer, fischer@iue.tuwien.ac.at + */ + + + + + unsigned long a0; /* 16 bit, low bits */ + unsigned long a1; /* 16 bit, medium bits */ + unsigned long a2; /* 32 bit, high bits */ + + /* Copy the unix time to a2/a1/a0 */ + a0 = unix_time & 0xffff; + a1 = (unix_time >> 16) & 0xffff; + /* This is obsolete if unix_time is only 32 bits, but it does not hurt. + Do not replace this by >> 32, it gives a compiler warning and it does + not work. */ + a2 = (unix_time >= 0 ? (unix_time >> 16) >> 16 : + ~((~unix_time >> 16) >> 16)); + + /* Multiply a by 10000000 (a = a2/a1/a0) + Split the factor into 10000 * 1000 which are both less than 0xffff. */ + a0 *= 10000; + a1 = a1 * 10000 + (a0 >> 16); + a2 = a2 * 10000 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + a0 *= 1000; + a1 = a1 * 1000 + (a0 >> 16); + a2 = a2 * 1000 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + /* Add the time difference and the remainder */ + a0 += 32768 + (remainder & 0xffff); + a1 += 54590 + (remainder >> 16 ) + (a0 >> 16); + a2 += 27111902 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + /* Set filetime */ + filetime->dwLowDateTime = (a1 << 16) + a0; + filetime->dwHighDateTime = a2; +} + + +/*********************************************************************** + * DOSFS_FileTimeToUnixTime + * + * Convert a FILETIME format to Unix time. + * If not NULL, 'remainder' contains the fractional part of the filetime, + * in the range of [0..9999999] (even if time_t is negative). + */ +time_t FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ) +{ + /* Read the comment in the function DOSFS_UnixTimeToFileTime. */ + + unsigned long a0; /* 16 bit, low bits */ + unsigned long a1; /* 16 bit, medium bits */ + unsigned long a2; /* 32 bit, high bits */ + unsigned long r; /* remainder of division */ + unsigned int carry; /* carry bit for subtraction */ + int negative; /* whether a represents a negative value */ + + /* Copy the time values to a2/a1/a0 */ + a2 = (unsigned long)filetime->dwHighDateTime; + a1 = ((unsigned long)filetime->dwLowDateTime ) >> 16; + a0 = ((unsigned long)filetime->dwLowDateTime ) & 0xffff; + + /* Subtract the time difference */ + if (a0 >= 32768 ) a0 -= 32768 , carry = 0; + else a0 += (1 << 16) - 32768 , carry = 1; + + if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0; + else a1 += (1 << 16) - 54590 - carry, carry = 1; + + a2 -= 27111902 + carry; + + /* If a is negative, replace a by (-1-a) */ + negative = (a2 >= ((unsigned long)1) << 31); + if (negative) + { + /* Set a to -a - 1 (a is a2/a1/a0) */ + a0 = 0xffff - a0; + a1 = 0xffff - a1; + a2 = ~a2; + } + + /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r. + Split the divisor into 10000 * 1000 which are both less than 0xffff. */ + a1 += (a2 % 10000) << 16; + a2 /= 10000; + a0 += (a1 % 10000) << 16; + a1 /= 10000; + r = a0 % 10000; + a0 /= 10000; + + a1 += (a2 % 1000) << 16; + a2 /= 1000; + a0 += (a1 % 1000) << 16; + a1 /= 1000; + r += (a0 % 1000) * 10000; + a0 /= 1000; + + /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */ + if (negative) + { + /* Set a to -a - 1 (a is a2/a1/a0) */ + a0 = 0xffff - a0; + a1 = 0xffff - a1; + a2 = ~a2; + + r = 9999999 - r; + } + + if (remainder) *remainder = r; + + /* Do not replace this by << 32, it gives a compiler warning and it does + not work. */ + return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0; + +} + + + diff --git a/lib/crtdll/time/tzfile.h b/lib/crtdll/time/tzfile.h new file mode 100644 index 0000000..3999029 --- /dev/null +++ b/lib/crtdll/time/tzfile.h @@ -0,0 +1,160 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_tzfile_h__ +#define __dj_include_tzfile_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)tzfile.h 5.9 (Berkeley) 6/11/90 + */ + +/* +** Information about time zone files. +*/ + + /* Time zone object file directory */ +#define TZDIR "/usr/share/zoneinfo" +#define TZDEFAULT "/etc/localtime" +#define TZDEFRULES "posixrules" + +/* +** Each file begins with. . . +*/ + +struct tzhead { + char tzh_reserved[24]; /* reserved for future use */ + char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ + char tzh_leapcnt[4]; /* coded number of leap seconds */ + char tzh_timecnt[4]; /* coded number of transition times */ + char tzh_typecnt[4]; /* coded number of local time types */ + char tzh_charcnt[4]; /* coded number of abbr. chars */ +}; + +/* +** . . .followed by. . . +** +** tzh_timecnt (char [4])s coded transition times a la time(2) +** tzh_timecnt (unsigned char)s types of local time starting at above +** tzh_typecnt repetitions of +** one (char [4]) coded GMT offset in seconds +** one (unsigned char) used to set tm_isdst +** one (unsigned char) that's an abbreviation list index +** tzh_charcnt (char)s '\0'-terminated zone abbreviations +** tzh_leapcnt repetitions of +** one (char [4]) coded leap second transition times +** one (char [4]) total correction after above +** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition +** time is standard time, if FALSE, +** transition time is wall clock time +** if absent, transition times are +** assumed to be wall clock time +*/ + +/* +** In the current implementation, "tzset()" refuses to deal with files that +** exceed any of the limits below. +*/ + +/* +** The TZ_MAX_TIMES value below is enough to handle a bit more than a +** year's worth of solar time (corrected daily to the nearest second) or +** 138 years of Pacific Presidential Election time +** (where there are three time zone transitions every fourth year). +*/ +#define TZ_MAX_TIMES 370 + +#define NOSOLAR /* 4BSD doesn't currently handle solar time */ + +#ifndef NOSOLAR +#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +#else +#define TZ_MAX_TYPES 10 /* Maximum number of local time types */ +#endif + +#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ + +#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_JANUARY 0 +#define TM_FEBRUARY 1 +#define TM_MARCH 2 +#define TM_APRIL 3 +#define TM_MAY 4 +#define TM_JUNE 5 +#define TM_JULY 6 +#define TM_AUGUST 7 +#define TM_SEPTEMBER 8 +#define TM_OCTOBER 9 +#define TM_NOVEMBER 10 +#define TM_DECEMBER 11 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +/* +** Accurate only for the past couple of centuries; +** that will probably do. +*/ + +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_tzfile_h__ */ diff --git a/lib/crtdll/wchar/.cvsignore b/lib/crtdll/wchar/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/crtdll/wchar/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/crtdll/wchar/wcscat.c b/lib/crtdll/wchar/wcscat.c new file mode 100644 index 0000000..dc2a39e --- /dev/null +++ b/lib/crtdll/wchar/wcscat.c @@ -0,0 +1,19 @@ + + +#include + +wchar_t * wcscat(wchar_t * dest,const wchar_t * src) +{ + + wchar_t *d = dest; + for (; *dest !=0; dest++); + while (*src != 0) + { + *dest = *src; + dest++; + src++; + } + *dest = 0; + return d; +} + diff --git a/lib/crtdll/wchar/wcschr.c b/lib/crtdll/wchar/wcschr.c new file mode 100644 index 0000000..5bbd959 --- /dev/null +++ b/lib/crtdll/wchar/wcschr.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +wchar_t* wcschr(const wchar_t* str, wchar_t ch) +{ + while ((*str)!=0) + { + if ((*str)==ch) + { + return((wchar_t *)str); + } + str++; + } + return(NULL); +} diff --git a/lib/crtdll/wchar/wcscmp.c b/lib/crtdll/wchar/wcscmp.c new file mode 100644 index 0000000..ab25af4 --- /dev/null +++ b/lib/crtdll/wchar/wcscmp.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +int wcscmp(const wchar_t* cs,const wchar_t * ct) +{ + while (*cs == *ct) + { + if (*cs == 0) + return 0; + cs++; + ct++; + } + return *cs - *ct; + +} diff --git a/lib/crtdll/wchar/wcscoll.c b/lib/crtdll/wchar/wcscoll.c new file mode 100644 index 0000000..98a65d7 --- /dev/null +++ b/lib/crtdll/wchar/wcscoll.c @@ -0,0 +1,17 @@ + + +#include + +int wcscoll(const wchar_t *a1,const wchar_t *a2) +{ + /* FIXME: handle collates */ + return wcscmp(a1,a2); +} + + +int _wcsicoll(const wchar_t *a1,const wchar_t *a2) +{ + /* FIXME: handle collates */ + return _wcsicmp(a1,a2); +} + diff --git a/lib/crtdll/wchar/wcscpy.c b/lib/crtdll/wchar/wcscpy.c new file mode 100644 index 0000000..44f71f0 --- /dev/null +++ b/lib/crtdll/wchar/wcscpy.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +wchar_t * wcscpy(wchar_t * str1,const wchar_t * str2) +{ + wchar_t *save = str1; + + for (; (*str1 = *str2); ++str2, ++str1); + return save; +} diff --git a/lib/crtdll/wchar/wcscspn.c b/lib/crtdll/wchar/wcscspn.c new file mode 100644 index 0000000..2c3f2d2 --- /dev/null +++ b/lib/crtdll/wchar/wcscspn.c @@ -0,0 +1,20 @@ +#include + +size_t wcscspn(const wchar_t *str,const wchar_t *reject) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do { + t=(wchar_t *)reject; + while (*t) { + if (*t==*s) + break; + t++; + } + if (*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} diff --git a/lib/crtdll/wchar/wcsdup.c b/lib/crtdll/wchar/wcsdup.c new file mode 100644 index 0000000..6d9f216 --- /dev/null +++ b/lib/crtdll/wchar/wcsdup.c @@ -0,0 +1,19 @@ +#include +#include +#include + + +wchar_t *_wcsdup(const wchar_t *ptr) +{ + wchar_t *dup; + dup = malloc((wcslen(ptr) + 1)*sizeof(wchar_t)); + if( dup == NULL ) { + __set_errno(ENOMEM); + return NULL; + } + wcscpy(dup,ptr); + return dup; +} + + + diff --git a/lib/crtdll/wchar/wcsftime.c b/lib/crtdll/wchar/wcsftime.c new file mode 100644 index 0000000..4e402b5 --- /dev/null +++ b/lib/crtdll/wchar/wcsftime.c @@ -0,0 +1,6 @@ +#include + +size_t wcsftime(wchar_t *str, size_t len, const wchar_t *fmt, const struct tm *tp ) +{ + return 0; +} \ No newline at end of file diff --git a/lib/crtdll/wchar/wcsicmp.c b/lib/crtdll/wchar/wcsicmp.c new file mode 100644 index 0000000..1cfaf8e --- /dev/null +++ b/lib/crtdll/wchar/wcsicmp.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +int _wcsicmp(const wchar_t* cs,const wchar_t * ct) +{ + while (towlower(*cs) == towlower(*ct)) + { + if (*cs == 0) + return 0; + cs++; + ct++; + } + return towlower(*cs) - towlower(*ct); + +} diff --git a/lib/crtdll/wchar/wcslen.c b/lib/crtdll/wchar/wcslen.c new file mode 100644 index 0000000..df294b8 --- /dev/null +++ b/lib/crtdll/wchar/wcslen.c @@ -0,0 +1,23 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + + +size_t wcslen(const wchar_t * s) +{ + const wchar_t *save; + + if (s == 0) + return 0; + for (save = s; *save; ++save); + return save-s; +} + +size_t wstrlen(const wchar_t *s) +{ + return wcslen(s); +} + + + + diff --git a/lib/crtdll/wchar/wcslwr.c b/lib/crtdll/wchar/wcslwr.c new file mode 100644 index 0000000..0dcf2da --- /dev/null +++ b/lib/crtdll/wchar/wcslwr.c @@ -0,0 +1,22 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + +#include + +wchar_t * _wcslwr(wchar_t *x) +{ + wchar_t *y=x; + + while (*y) { + *y=towlower(*y); + y++; + } + return x; +} diff --git a/lib/crtdll/wchar/wcsncat.c b/lib/crtdll/wchar/wcsncat.c new file mode 100644 index 0000000..85d0d81 --- /dev/null +++ b/lib/crtdll/wchar/wcsncat.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +wchar_t *wcsncat(wchar_t *dst, const wchar_t *src, size_t n) +{ + if (n != 0) + { + wchar_t *d = dst; + const wchar_t *s = src; + + while (*d != 0) + d++; + do { + if ((*d = *s++) == 0) + break; + d++; + } while (--n != 0); + *d = 0; + } + return dst; +} diff --git a/lib/crtdll/wchar/wcsncmp.c b/lib/crtdll/wchar/wcsncmp.c new file mode 100644 index 0000000..6341f46 --- /dev/null +++ b/lib/crtdll/wchar/wcsncmp.c @@ -0,0 +1,16 @@ +#include + +int wcsncmp(const wchar_t * cs,const wchar_t * ct,size_t count) +{ + while ((*cs) == (*ct) && count > 0) + { + if (*cs == 0) + return 0; + cs++; + ct++; + count--; + } + return (*cs) - (*ct); + +} + diff --git a/lib/crtdll/wchar/wcsncpy.c b/lib/crtdll/wchar/wcsncpy.c new file mode 100644 index 0000000..9cad913 --- /dev/null +++ b/lib/crtdll/wchar/wcsncpy.c @@ -0,0 +1,21 @@ +#include + +wchar_t * wcsncpy(wchar_t * dest,const wchar_t *src,size_t count) +{ + int i; + + for (i=0;i + +int _wcsnicmp (const wchar_t *cs, const wchar_t *ct, size_t count) +{ + if (count == 0) + return 0; + do { + if (towupper(*cs) != towupper(*ct++)) + return towupper(*cs) - towupper(*--ct); + if (*cs++ == 0) + break; + } while (--count != 0); + return 0; +} diff --git a/lib/crtdll/wchar/wcsnlen.c b/lib/crtdll/wchar/wcsnlen.c new file mode 100644 index 0000000..dc5796c --- /dev/null +++ b/lib/crtdll/wchar/wcsnlen.c @@ -0,0 +1,12 @@ +#include + +size_t _wcsnlen(const wchar_t * s, size_t count) +{ + + unsigned int len=0; + + while(s[len]!=0 && len < count) { + len++; + }; + return len; +} diff --git a/lib/crtdll/wchar/wcspbrk.c b/lib/crtdll/wchar/wcspbrk.c new file mode 100644 index 0000000..ccef388 --- /dev/null +++ b/lib/crtdll/wchar/wcspbrk.c @@ -0,0 +1,16 @@ +#include + +wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2) +{ + const wchar_t *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) { + return (wchar_t *)(--s1); + } + } + return 0; +} diff --git a/lib/crtdll/wchar/wcsrchr.c b/lib/crtdll/wchar/wcsrchr.c new file mode 100644 index 0000000..8568d96 --- /dev/null +++ b/lib/crtdll/wchar/wcsrchr.c @@ -0,0 +1,16 @@ +#include + +wchar_t* wcsrchr(const wchar_t* str, wchar_t ch) +{ + + wchar_t *sp=(wchar_t *)0; + while (*str != 0) + { + if (*str == ch) + sp = (wchar_t *)str; + str++; + } + if (ch == 0) + sp = (wchar_t *)str; + return sp; +} diff --git a/lib/crtdll/wchar/wcsrev.c b/lib/crtdll/wchar/wcsrev.c new file mode 100644 index 0000000..695f0de --- /dev/null +++ b/lib/crtdll/wchar/wcsrev.c @@ -0,0 +1,18 @@ +#include + +wchar_t * _wcsrev(wchar_t *s) +{ + wchar_t *e; + wchar_t a; + e=s; + while (*e) + e++; + while (s + +wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill) +{ + wchar_t *t = wsToFill; + int i = 0; + while( *wsToFill != 0 && i < sizeMaxFill) + { + *wsToFill = wcFill; + wsToFill++; + i++; + + } + return t; +} + +wchar_t* _wcsset (wchar_t* wsToFill, wchar_t wcFill) +{ + wchar_t *t = wsToFill; + while( *wsToFill != 0 ) + { + *wsToFill = wcFill; + wsToFill++; + + } + return t; +} diff --git a/lib/crtdll/wchar/wcsspn.c b/lib/crtdll/wchar/wcsspn.c new file mode 100644 index 0000000..5ae0df0 --- /dev/null +++ b/lib/crtdll/wchar/wcsspn.c @@ -0,0 +1,20 @@ +#include + +size_t wcsspn(const wchar_t *str,const wchar_t *accept) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do { + t=(wchar_t *)accept; + while (*t) { + if (*t==*s) + break; + t++; + } + if (!*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} diff --git a/lib/crtdll/wchar/wcsstr.c b/lib/crtdll/wchar/wcsstr.c new file mode 100644 index 0000000..ebe638f --- /dev/null +++ b/lib/crtdll/wchar/wcsstr.c @@ -0,0 +1,23 @@ +#include + +wchar_t *wcsstr(const wchar_t *s,const wchar_t *b) +{ + wchar_t *x; + wchar_t *y; + wchar_t *c; + x=(wchar_t *)s; + while (*x) { + if (*x==*b) { + y=x; + c=(wchar_t *)b; + while (*y && *c && *y==*c) { + c++; + y++; + } + if (!*c) + return x; + } + x++; + } + return NULL; +} diff --git a/lib/crtdll/wchar/wcstod.c b/lib/crtdll/wchar/wcstod.c new file mode 100644 index 0000000..ffef827 --- /dev/null +++ b/lib/crtdll/wchar/wcstod.c @@ -0,0 +1,95 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +double wcstod(const wchar_t *s, wchar_t **sret) +{ + long double r; /* result */ + int e; /* exponent */ + long double d; /* scale */ + int sign; /* +- 1.0 */ + int esign; + int i; + int flags=0; + + r = 0.0; + sign = 1; + e = 0; + esign = 1; + + while ((*s == L' ') || (*s == L'\t')) + s++; + + if (*s == L'+') + s++; + else if (*s == L'-') + { + sign = -1; + s++; + } + + while ((*s >= L'0') && (*s <= L'9')) + { + flags |= 1; + r *= 10.0; + r += *s - L'0'; + s++; + } + + if (*s == L'.') + { + d = 0.1L; + s++; + while ((*s >= L'0') && (*s <= L'9')) + { + flags |= 2; + r += d * (*s - L'0'); + s++; + d *= 0.1L; + } + } + + if (flags == 0) + { + if (sret) + *sret = (wchar_t *)s; + return 0; + } + + if ((*s == L'e') || (*s == L'E')) + { + s++; + if (*s == L'+') + s++; + else if (*s == L'-') + { + s++; + esign = -1; + } + if ((*s < L'0') || (*s > L'9')) + { + if (sret) + *sret = (wchar_t *)s; + return r; + } + + while ((*s >= L'0') && (*s <= L'9')) + { + e *= 10; + e += *s - L'0'; + s++; + } + } + + if (esign < 0) + for (i = 1; i <= e; i++) + r *= 0.1L; + else + for (i = 1; i <= e; i++) + r *= 10.0; + + if (sret) + *sret = (wchar_t *)s; + return r * sign; +} diff --git a/lib/crtdll/wchar/wcstok.c b/lib/crtdll/wchar/wcstok.c new file mode 100644 index 0000000..3afd717 --- /dev/null +++ b/lib/crtdll/wchar/wcstok.c @@ -0,0 +1,54 @@ +#include + +wchar_t *wcstok(wchar_t *s, const wchar_t *ct) +{ + const wchar_t *spanp; + int c, sc; + wchar_t *tok; + static wchar_t *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading ctiters (s += strspn(s, ct), sort of). + */ + cont: + c = *s; + s++; + for (spanp = ct; (sc = *spanp) != 0;spanp++) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-ctiter characters */ + last = NULL; + return (NULL); + } + tok = s - 2; + + /* + * Scan token (scan for ctiters: s += strcspn(s, ct), sort of). + * Note that ct must have one NUL; we stop if we see that, too. + */ + for (;;) { + + c = *s; + s+=2; + spanp = ct; + do { + if ((sc = *spanp) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + spanp+=2; + } while (sc != 0); + + } + /* NOTREACHED */ +} diff --git a/lib/crtdll/wchar/wcstol.c b/lib/crtdll/wchar/wcstol.c new file mode 100644 index 0000000..5a5ae97 --- /dev/null +++ b/lib/crtdll/wchar/wcstol.c @@ -0,0 +1,60 @@ +#include + + +long wcstol(const wchar_t *cp,wchar_t **endp,int base) +{ + long result = 0,value; + int sign = 1; + + if ( *cp == L'-' ) { + sign = -1; + cp++; + } + + if (!base) { + base = 10; + if (*cp == L'0') { + base = 8; + cp++; + if ((*cp == L'x') && iswxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (iswxdigit(*cp) && (value = iswdigit(*cp) ? *cp-L'0' : (iswlower(*cp) + ? towupper(*cp) : *cp)-L'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (wchar_t *)cp; + return result * sign; +} + + +unsigned long wcstoul(const wchar_t *cp,wchar_t **endp,int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == L'0') { + base = 8; + cp++; + if ((*cp == L'x') && iswxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (iswxdigit(*cp) && (value = iswdigit(*cp) ? *cp-L'0' : (iswlower(*cp) + ? towupper(*cp) : *cp)-L'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (wchar_t *)cp; + return result; +} + diff --git a/lib/crtdll/wchar/wcstombs.c b/lib/crtdll/wchar/wcstombs.c new file mode 100644 index 0000000..f660411 --- /dev/null +++ b/lib/crtdll/wchar/wcstombs.c @@ -0,0 +1,7 @@ +#include +#include + +size_t wcstombs( char *dst, const wchar_t *src, size_t len ) +{ + return 0; +} diff --git a/lib/crtdll/wchar/wcsupr.c b/lib/crtdll/wchar/wcsupr.c new file mode 100644 index 0000000..438b5a9 --- /dev/null +++ b/lib/crtdll/wchar/wcsupr.c @@ -0,0 +1,12 @@ +#include + +wchar_t *_wcsupr(wchar_t *x) +{ + wchar_t *y=x; + + while (*y) { + *y=towupper(*y); + y++; + } + return x; +} diff --git a/lib/crtdll/wchar/wcsxfrm.c b/lib/crtdll/wchar/wcsxfrm.c new file mode 100644 index 0000000..91ae8e6 --- /dev/null +++ b/lib/crtdll/wchar/wcsxfrm.c @@ -0,0 +1,23 @@ +#include + +size_t wcsxfrm(wchar_t *dst,const wchar_t *src, size_t n) +{ + size_t r = 0; + int c; + + if (n != 0) { + while ((c = *src++) != 0) + { + r++; + if (--n == 0) + { + while (*src++ != 0) + r++; + break; + } + *dst++ = c; + } + *dst = 0; + } + return r; +} diff --git a/lib/crtdll/wchar/wtoi.c b/lib/crtdll/wchar/wtoi.c new file mode 100644 index 0000000..6aeb3d1 --- /dev/null +++ b/lib/crtdll/wchar/wtoi.c @@ -0,0 +1,11 @@ +#include + +int _wtoi( const wchar_t *str ) +{ + return (int)wcstol(str, 0, 10); +} + +long _wtol( const wchar_t *str ) +{ + return (int)wcstol(str, 0, 10); +} diff --git a/lib/fmifs/.cvsignore b/lib/fmifs/.cvsignore new file mode 100644 index 0000000..3ad077f --- /dev/null +++ b/lib/fmifs/.cvsignore @@ -0,0 +1,3 @@ +fmifs.coff +fmifs.dll +fmifs.nostrip.dll \ No newline at end of file diff --git a/lib/fmifs/chkdsk.c b/lib/fmifs/chkdsk.c new file mode 100644 index 0000000..5bc03d9 --- /dev/null +++ b/lib/fmifs/chkdsk.c @@ -0,0 +1,52 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/chkdsk.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + + +/* FMIFS.1 */ +VOID +__stdcall +Chkdsk( + PWCHAR DriveRoot, + PWCHAR Format, + BOOL CorrectErrors, + BOOL Verbose, + BOOL CheckOnlyIfDirty, + BOOL ScanDrive, + PVOID Unused2, + PVOID Unused3, + PFMIFSCALLBACK Callback + ) +{ + BOOL Argument = FALSE; + + /* FAIL immediately */ + Callback( + DONE, /* Command */ + 0, /* DWORD Modifier */ + & Argument /* Argument */ + ); +} + + +/* FMIFS.2 (SP4 only?) */ +VOID +__stdcall +ChkdskEx(VOID) +{ +} + + +/* EOF */ diff --git a/lib/fmifs/compress.c b/lib/fmifs/compress.c new file mode 100644 index 0000000..570f60c --- /dev/null +++ b/lib/fmifs/compress.c @@ -0,0 +1,30 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/compress.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + + +/* FMIFS.4 */ +BOOL +__stdcall +EnableVolumeCompression( + PWCHAR DriveRoot, + BOOL Enable + ) +{ + return FALSE; +} + + +/* EOF */ diff --git a/lib/fmifs/diskcopy.c b/lib/fmifs/diskcopy.c new file mode 100644 index 0000000..fcd9f56 --- /dev/null +++ b/lib/fmifs/diskcopy.c @@ -0,0 +1,25 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/diskcopy.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + +/* FMIFS.3 */ +VOID +__stdcall +DiskCopy(VOID) +{ +} + + +/* EOF */ diff --git a/lib/fmifs/dllmain.c b/lib/fmifs/dllmain.c new file mode 100644 index 0000000..b4dc3f6 --- /dev/null +++ b/lib/fmifs/dllmain.c @@ -0,0 +1,27 @@ +/* $Id$ + * + * ReactOS FMIFS.DLL + */ +#include +BOOLEAN +__stdcall +DllMain( + PVOID hinstDll, + ULONG dwReason, + PVOID reserved + ) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return (TRUE); +} +/* EOF */ diff --git a/lib/fmifs/extend.c b/lib/fmifs/extend.c new file mode 100644 index 0000000..9f5d4d6 --- /dev/null +++ b/lib/fmifs/extend.c @@ -0,0 +1,25 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/extend.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + +/* FMIFS.5 */ +VOID +__stdcall +Extend(VOID) +{ +} + + +/* EOF */ diff --git a/lib/fmifs/fmifs.def b/lib/fmifs/fmifs.def new file mode 100644 index 0000000..a678f2d --- /dev/null +++ b/lib/fmifs/fmifs.def @@ -0,0 +1,23 @@ +; $Id$ +; +; fmifs.def +; +; Project : ReactOS +; Description : fmifs.dll exported symbols +; Contributors: +; Created by Emanuele Aliberti +; +; +; NOTE: Functions with trailing @0 are unknown. +; +LIBRARY fmifs.dll +EXPORTS +Chkdsk@36 +DiskCopy@0 +EnableVolumeCompression@8 +Extend@0 +Format@0 +FormatEx@28 +InitializeFmIfs@0 +QuerySupportedMedia@0 +SetLabel@0 diff --git a/lib/fmifs/fmifs.edf b/lib/fmifs/fmifs.edf new file mode 100644 index 0000000..0717052 --- /dev/null +++ b/lib/fmifs/fmifs.edf @@ -0,0 +1,23 @@ +; $Id$ +; +; fmifs.def +; +; Project : ReactOS +; Description : fmifs.dll exported symbols +; Contributors: +; Created by Emanuele Aliberti +; +; +; NOTE: NOTE: Functions with trailing @0 are unknown. +; +LIBRARY fmifs.dll +EXPORTS +Chkdsk=Chkdsk@36 +DiskCopy=DiskCopy@0 +EnableVolumeCompression=EnableVolumeCompression@8 +Extend=Extend@0 +Format=Format@0 +FormatEx=FormatEx@28 +InitializeFmIfs=InitializeFmIfs@0 +QuerySupportedMedia=QuerySupportedMedia@0 +SetLabel=SetLabel@0 diff --git a/lib/fmifs/fmifs.rc b/lib/fmifs/fmifs.rc new file mode 100644 index 0000000..8fd6dff --- /dev/null +++ b/lib/fmifs/fmifs.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "File Management IFS Utility DLL\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "fmifs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "fmifs.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/fmifs/format.c b/lib/fmifs/format.c new file mode 100644 index 0000000..1f6d817 --- /dev/null +++ b/lib/fmifs/format.c @@ -0,0 +1,49 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/format.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + +/* FMIFS.6 */ +VOID +__stdcall +Format(VOID) +{ +} + + +/* FMIFS.7 */ +VOID +__stdcall +FormatEx( + PWCHAR DriveRoot, + DWORD MediaFlag, + PWCHAR Format, + PWCHAR Label, + BOOL QuickFormat, + DWORD ClusterSize, + PFMIFSCALLBACK Callback + ) +{ + BOOL Argument = FALSE; + + /* FAIL immediately */ + Callback( + DONE, /* Command */ + 0, /* DWORD Modifier */ + & Argument /* Argument */ + ); +} + + +/* EOF */ diff --git a/lib/fmifs/init.c b/lib/fmifs/init.c new file mode 100644 index 0000000..96e1d71 --- /dev/null +++ b/lib/fmifs/init.c @@ -0,0 +1,42 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/init.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + +/* FMIFS.8 */ +static BOOL FmIfsInitialized = FALSE; + +static BOOL STDCALL +InitializeFmIfsOnce (VOID) +{ + /* TODO: Check how many IFS are installed in the system */ + /* TOSO: and register a descriptor for each one */ + return TRUE; +} + +BOOL STDCALL +InitializeFmIfs(VOID) +{ + if (FALSE == FmIfsInitialized) + { + if (FALSE == InitializeFmIfsOnce()) + { + return FALSE; + } + FmIfsInitialized = TRUE; + } + return TRUE; +} + +/* EOF */ diff --git a/lib/fmifs/label.c b/lib/fmifs/label.c new file mode 100644 index 0000000..c377952 --- /dev/null +++ b/lib/fmifs/label.c @@ -0,0 +1,26 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/label.c + * DESCRIPTION: File management IFS utility functions + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + + +/* FMIFS.10 */ +VOID +__stdcall +SetLabel(VOID) +{ +} + + +/* EOF */ diff --git a/lib/fmifs/makefile b/lib/fmifs/makefile new file mode 100644 index 0000000..95797d2 --- /dev/null +++ b/lib/fmifs/makefile @@ -0,0 +1,30 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = fmifs + +TARGET_BASE = 0x76df0000 + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = \ + chkdsk.o \ + compress.o \ + diskcopy.o \ + dllmain.o \ + extend.o \ + format.o \ + init.o \ + label.o \ + media.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +TARGET_FILES = misc/*.o + +# EOF diff --git a/lib/fmifs/media.c b/lib/fmifs/media.c new file mode 100644 index 0000000..aee6a87 --- /dev/null +++ b/lib/fmifs/media.c @@ -0,0 +1,26 @@ +/* $Id$ + * + * COPYING: See the top level directory + * PROJECT: ReactOS + * FILE: reactos/lib/fmifs/media.c + * DESCRIPTION: fmifs.dll + * PROGRAMMER: Emanuele Aliberti + * UPDATED + * 1999-02-16 (Emanuele Aliberti) + * Entry points added. + */ +#define UNICODE +#define _UNICODE +#include +#include + + +/* FMIFS.9 */ +VOID +__stdcall +QuerySupportedMedia(VOID) +{ +} + + +/* EOF */ diff --git a/lib/gdi32/.cvsignore b/lib/gdi32/.cvsignore new file mode 100644 index 0000000..22801be --- /dev/null +++ b/lib/gdi32/.cvsignore @@ -0,0 +1,3 @@ +gdi32.coff +gdi32.dll +gdi32.nostrip.dll \ No newline at end of file diff --git a/lib/gdi32/gdi32.def b/lib/gdi32/gdi32.def new file mode 100644 index 0000000..e0b5e89 --- /dev/null +++ b/lib/gdi32/gdi32.def @@ -0,0 +1,344 @@ +; $Id$ +; +; gdi32.def +; +; ReactOS Operating System +; +; From Anders Norlander's w32api-0.1.5 gdi32.def. +; +LIBRARY gdi32.dll +EXPORTS +AbortDoc@4 +AbortPath@4 +AddFontResourceA@4 +AddFontResourceW@4 +AngleArc@24 +AnimatePalette@16 +Arc@36 +ArcTo@36 +BeginPath@4 +BitBlt@36 +CancelDC@4 +CheckColorsInGamut@16 +ChoosePixelFormat@8 +Chord@36 +CloseEnhMetaFile@4 +CloseFigure@4 +CloseMetaFile@4 +ColorMatchToTarget@12 +CombineRgn@16 +CombineTransform@12 +CopyEnhMetaFileA@8 +CopyEnhMetaFileW@8 +CopyMetaFileA@8 +CopyMetaFileW@8 +CreateBitmap@20 +CreateBitmapIndirect@4 +CreateBrushIndirect@4 +CreateColorSpaceA@4 +CreateColorSpaceW@4 +CreateCompatibleBitmap@12 +CreateCompatibleDC@4 +CreateDCA@16 +CreateDCW@16 +CreateDIBPatternBrush@8 +CreateDIBPatternBrushPt@8 +CreateDIBSection@24 +CreateDIBitmap@24 +CreateDiscardableBitmap@12 +CreateEllipticRgn@16 +CreateEllipticRgnIndirect@4 +CreateEnhMetaFileA@16 +CreateEnhMetaFileW@16 +CreateFontA@56 +CreateFontIndirectA@4 +CreateFontIndirectW@4 +CreateFontW@56 +CreateHalftonePalette@4 +CreateHatchBrush@8 +CreateICA@16 +CreateICW@16 +CreateMetaFileA@4 +CreateMetaFileW@4 +CreatePalette@4 +CreatePatternBrush@4 +CreatePen@12 +CreatePenIndirect@4 +CreatePolyPolygonRgn@16 +CreatePolygonRgn@12 +CreateRectRgn@16 +CreateRectRgnIndirect@4 +CreateRoundRectRgn@24 +CreateScalableFontResourceA@16 +CreateScalableFontResourceW@16 +CreateSolidBrush@4 +DPtoLP@12 +DeleteColorSpace@4 +DeleteDC@4 +DeleteEnhMetaFile@4 +DeleteMetaFile@4 +DeleteObject@4 +DescribePixelFormat@16 +DeviceCapabilitiesExA@20 +DeviceCapabilitiesExW@20 +DrawEscape@16 +Ellipse@20 +EndDoc@4 +EndPage@4 +EndPath@4 +EnumEnhMetaFile@20 +EnumFontFamiliesA@16 +EnumFontFamiliesExA@20 +EnumFontFamiliesExW@20 +EnumFontFamiliesW@16 +EnumFontsA@16 +EnumFontsW@16 +EnumICMProfilesA@12 +EnumICMProfilesW@12 +EnumMetaFile@16 +EnumObjects@16 +EqualRgn@8 +Escape@20 +ExcludeClipRect@20 +ExtCreatePen@20 +ExtCreateRegion@12 +ExtEscape@24 +ExtFloodFill@20 +ExtSelectClipRgn@12 +ExtTextOutA@32 +ExtTextOutW@32 +FillPath@4 +FillRgn@12 +FixBrushOrgEx@16 +FlattenPath@4 +FloodFill@16 +FrameRgn@20 +GdiComment@12 +GdiDllInitialize@12 +GdiFlush@0 +GdiGetBatchLimit@0 +GdiPlayDCScript@24 +GdiPlayJournal@20 +GdiPlayScript@28 +GdiProcessSetup@0 +GdiSetBatchLimit@4 +GetArcDirection@4 +GetAspectRatioFilterEx@8 +GetBitmapBits@12 +GetBitmapDimensionEx@8 +GetBkColor@4 +GetBkMode@4 +GetBoundsRect@12 +GetBrushOrgEx@8 +GetCharABCWidthsA@16 +GetCharABCWidthsFloatA@16 +GetCharABCWidthsFloatW@16 +GetCharABCWidthsW@16 +GetCharWidth32A@16 +GetCharWidth32W@16 +GetCharWidthA@16 +GetCharWidthFloatA@16 +GetCharWidthFloatW@16 +GetCharWidthW@16 +GetCharacterPlacementA@24 +GetCharacterPlacementW@24 +GetClipBox@8 +GetClipRgn@8 +GetColorAdjustment@8 +GetColorSpace@4 +GetCurrentObject@8 +GetCurrentPositionEx@8 +GetDCOrgEx@8 +GetDIBColorTable@16 +GetDIBits@28 +GetDeviceCaps@8 +GetDeviceGammaRamp@8 +GetEnhMetaFileA@4 +GetEnhMetaFileBits@12 +GetEnhMetaFileDescriptionA@12 +GetEnhMetaFileDescriptionW@12 +GetEnhMetaFileHeader@12 +GetEnhMetaFilePaletteEntries@12 +GetEnhMetaFilePixelFormat@12 +GetEnhMetaFileW@4 +GetFontData@20 +GetFontLanguageInfo@4 +GetFontResourceInfo@16 +GetFontResourceInfoW@16 +GetGlyphOutlineA@28 +GetGlyphOutlineA@28 +GetGlyphOutlineW@28 +GetGlyphOutlineWow@28 +GetGraphicsMode@4 +GetICMProfileA@12 +GetICMProfileW@12 +GetKerningPairsA@12 +GetKerningPairsA@12 +GetKerningPairsW@12 +GetLogColorSpaceA@12 +GetLogColorSpaceW@12 +GetMapMode@4 +GetMetaFileA@4 +GetMetaFileBitsEx@12 +GetMetaFileW@4 +GetMetaRgn@8 +GetMiterLimit@8 +GetNearestColor@8 +GetNearestPaletteIndex@8 +GetObjectA@12 +GetObjectType@4 +GetObjectW@12 +GetOutlineTextMetricsA@12 +GetOutlineTextMetricsW@12 +GetPaletteEntries@16 +GetPath@16 +GetPixel@12 +GetPixelFormat@4 +GetPolyFillMode@4 +GetROP2@4 +GetRandomRgn@12 +GetRasterizerCaps@8 +GetRegionData@12 +GetRelAbs@8 +GetRgnBox@8 +GetStockObject@4 +GetStretchBltMode@4 +GetSystemPaletteEntries@16 +GetSystemPaletteUse@4 +GetTextAlign@4 +GetTextCharacterExtra@4 +GetTextCharset@4 +GetTextCharsetInfo@12 +GetTextColor@4 +GetTextExtentExPointA@28 +GetTextExtentExPointW@28 +GetTextExtentPoint32A@16 +GetTextExtentPoint32W@16 +GetTextExtentPointA@16 +GetTextExtentPointW@16 +GetTextFaceA@12 +GetTextFaceW@12 +GetTextMetricsA@8 +GetTextMetricsW@8 +GetViewportExtEx@8 +GetViewportOrgEx@8 +GetWinMetaFileBits@20 +GetWindowExtEx@8 +GetWindowOrgEx@8 +GetWorldTransform@8 +IntersectClipRect@20 +InvertRgn@8 +LPtoDP@12 +LineDDA@24 +LineTo@12 +MaskBlt@48 +ModifyWorldTransform@12 +MoveToEx@16 +OffsetClipRgn@12 +OffsetRgn@12 +OffsetViewportOrgEx@16 +OffsetWindowOrgEx@16 +PaintRgn@8 +PatBlt@24 +PathToRegion@4 +Pie@36 +PlayEnhMetaFile@12 +PlayEnhMetaFileRecord@16 +PlayMetaFile@8 +PlayMetaFileRecord@16 +PlgBlt@40 +PolyBezier@12 +PolyBezierTo@12 +PolyDraw@16 +PolyPolygon@16 +PolyPolyline@16 +PolyTextOutA@12 +PolyTextOutW@12 +Polygon@12 +Polyline@12 +PolylineTo@12 +PtInRegion@12 +PtVisible@12 +RealizePalette@4 +RectInRegion@8 +RectVisible@8 +Rectangle@20 +RemoveFontResourceA@4 +RemoveFontResourceW@4 +ResetDCA@8 +ResetDCW@8 +ResizePalette@8 +RestoreDC@8 +RoundRect@28 +SaveDC@4 +ScaleViewportExtEx@24 +ScaleWindowExtEx@24 +SelectBrushLocal@8 +SelectClipPath@8 +SelectClipRgn@8 +SelectFontLocal@8 +SelectObject@8 +SelectPalette@12 +SetAbortProc@8 +SetArcDirection@8 +SetBitmapBits@12 +SetBitmapDimensionEx@16 +SetBkColor@8 +SetBkMode@8 +SetBoundsRect@12 +SetBrushOrgEx@16 +SetColorAdjustment@8 +SetColorSpace@8 +SetDIBColorTable@16 +SetDIBits@28 +SetDIBitsToDevice@48 +SetDeviceGammaRamp@8 +SetEnhMetaFileBits@8 +SetFontEnumeration@4 +SetGraphicsMode@8 +SetICMMode@8 +SetICMProfileA@8 +SetICMProfileW@8 +SetMapMode@8 +SetMapperFlags@8 +SetMetaFileBitsEx@8 +SetMetaRgn@4 +SetMiterLimit@12 +SetPaletteEntries@16 +SetPixel@16 +SetPixelFormat@12 +SetPixelV@16 +SetPolyFillMode@8 +SetROP2@8 +SetRectRgn@20 +SetRelAbs@8 +SetStretchBltMode@8 +SetSystemPaletteUse@8 +SetTextAlign@8 +SetTextCharacterExtra@8 +SetTextColor@8 +SetTextJustification@12 +SetViewportExtEx@16 +SetViewportOrgEx@16 +SetWinMetaFileBits@16 +SetWindowExtEx@16 +SetWindowOrgEx@16 +SetWorldTransform@8 +StartDocA@8 +StartDocW@8 +StartPage@4 +StretchBlt@44 +StretchDIBits@52 +StrokeAndFillPath@4 +StrokePath@4 +SwapBuffers@4 +TextOutA@20 +TextOutW@20 +TranslateCharsetInfo@12 +UnrealizeObject@4 +UpdateColors@4 +UpdateICMRegKeyA@16 +UpdateICMRegKeyA@16 +UpdateICMRegKeyW@16 +WidenPath@4 +gdiPlaySpoolStream@24 diff --git a/lib/gdi32/gdi32.edf b/lib/gdi32/gdi32.edf new file mode 100644 index 0000000..de0c99f --- /dev/null +++ b/lib/gdi32/gdi32.edf @@ -0,0 +1,344 @@ +; $Id$ +; +; gdi32.def +; +; ReactOS Operating System +; +; From Anders Norlander's w32api-0.1.5 gdi32.def. +; +LIBRARY gdi32.dll +EXPORTS +AbortDoc=AbortDoc@4 +AbortPath=AbortPath@4 +AddFontResourceA=AddFontResourceA@4 +AddFontResourceW=AddFontResourceW@4 +AngleArc=AngleArc@24 +AnimatePalette=AnimatePalette@16 +Arc=Arc@36 +ArcTo=ArcTo@36 +BeginPath=BeginPath@4 +BitBlt=BitBlt@36 +CancelDC=CancelDC@4 +CheckColorsInGamut=CheckColorsInGamut@16 +ChoosePixelFormat=ChoosePixelFormat@8 +Chord=Chord@36 +CloseEnhMetaFile=CloseEnhMetaFile@4 +CloseFigure=CloseFigure@4 +CloseMetaFile=CloseMetaFile@4 +ColorMatchToTarget=ColorMatchToTarget@12 +CombineRgn=CombineRgn@16 +CombineTransform=CombineTransform@12 +CopyEnhMetaFileA=CopyEnhMetaFileA@8 +CopyEnhMetaFileW=CopyEnhMetaFileW@8 +CopyMetaFileA=CopyMetaFileA@8 +CopyMetaFileW=CopyMetaFileW@8 +CreateBitmap=CreateBitmap@20 +CreateBitmapIndirect=CreateBitmapIndirect@4 +CreateBrushIndirect=CreateBrushIndirect@4 +CreateColorSpaceA=CreateColorSpaceA@4 +CreateColorSpaceW=CreateColorSpaceW@4 +CreateCompatibleBitmap=CreateCompatibleBitmap@12 +CreateCompatibleDC=CreateCompatibleDC@4 +CreateDCA=CreateDCA@16 +CreateDCW=CreateDCW@16 +CreateDIBPatternBrush=CreateDIBPatternBrush@8 +CreateDIBPatternBrushPt=CreateDIBPatternBrushPt@8 +CreateDIBSection=CreateDIBSection@24 +CreateDIBitmap=CreateDIBitmap@24 +CreateDiscardableBitmap=CreateDiscardableBitmap@12 +CreateEllipticRgn=CreateEllipticRgn@16 +CreateEllipticRgnIndirect=CreateEllipticRgnIndirect@4 +CreateEnhMetaFileA=CreateEnhMetaFileA@16 +CreateEnhMetaFileW=CreateEnhMetaFileW@16 +CreateFontA=CreateFontA@56 +CreateFontIndirectA=CreateFontIndirectA@4 +CreateFontIndirectW=CreateFontIndirectW@4 +CreateFontW=CreateFontW@56 +CreateHalftonePalette=CreateHalftonePalette@4 +CreateHatchBrush=CreateHatchBrush@8 +CreateICA=CreateICA@16 +CreateICW=CreateICW@16 +CreateMetaFileA=CreateMetaFileA@4 +CreateMetaFileW=CreateMetaFileW@4 +CreatePalette=CreatePalette@4 +CreatePatternBrush=CreatePatternBrush@4 +CreatePen=CreatePen@12 +CreatePenIndirect=CreatePenIndirect@4 +CreatePolyPolygonRgn=CreatePolyPolygonRgn@16 +CreatePolygonRgn=CreatePolygonRgn@12 +CreateRectRgn=CreateRectRgn@16 +CreateRectRgnIndirect=CreateRectRgnIndirect@4 +CreateRoundRectRgn=CreateRoundRectRgn@24 +CreateScalableFontResourceA=CreateScalableFontResourceA@16 +CreateScalableFontResourceW=CreateScalableFontResourceW@16 +CreateSolidBrush=CreateSolidBrush@4 +DPtoLP=DPtoLP@12 +DeleteColorSpace=DeleteColorSpace@4 +DeleteDC=DeleteDC@4 +DeleteEnhMetaFile=DeleteEnhMetaFile@4 +DeleteMetaFile=DeleteMetaFile@4 +DeleteObject=DeleteObject@4 +DescribePixelFormat=DescribePixelFormat@16 +DeviceCapabilitiesExA=DeviceCapabilitiesExA@20 +DeviceCapabilitiesExW=DeviceCapabilitiesExW@20 +DrawEscape=DrawEscape@16 +Ellipse=Ellipse@20 +EndDoc=EndDoc@4 +EndPage=EndPage@4 +EndPath=EndPath@4 +EnumEnhMetaFile=EnumEnhMetaFile@20 +EnumFontFamiliesA=EnumFontFamiliesA@16 +EnumFontFamiliesExA=EnumFontFamiliesExA@20 +EnumFontFamiliesExW=EnumFontFamiliesExW@20 +EnumFontFamiliesW=EnumFontFamiliesW@16 +EnumFontsA=EnumFontsA@16 +EnumFontsW=EnumFontsW@16 +EnumICMProfilesA=EnumICMProfilesA@12 +EnumICMProfilesW=EnumICMProfilesW@12 +EnumMetaFile=EnumMetaFile@16 +EnumObjects=EnumObjects@16 +EqualRgn=EqualRgn@8 +Escape=Escape@20 +ExcludeClipRect=ExcludeClipRect@20 +ExtCreatePen=ExtCreatePen@20 +ExtCreateRegion=ExtCreateRegion@12 +ExtEscape=ExtEscape@24 +ExtFloodFill=ExtFloodFill@20 +ExtSelectClipRgn=ExtSelectClipRgn@12 +ExtTextOutA=ExtTextOutA@32 +ExtTextOutW=ExtTextOutW@32 +FillPath=FillPath@4 +FillRgn=FillRgn@12 +FixBrushOrgEx=FixBrushOrgEx@16 +FlattenPath=FlattenPath@4 +FloodFill=FloodFill@16 +FrameRgn=FrameRgn@20 +GdiComment=GdiComment@12 +GdiDllInitialize=GdiDllInitialize@12 +GdiFlush=GdiFlush@0 +GdiGetBatchLimit=GdiGetBatchLimit@0 +GdiPlayDCScript=GdiPlayDCScript@24 +GdiPlayJournal=GdiPlayJournal@20 +GdiPlayScript=GdiPlayScript@28 +GdiProcessSetup=GdiProcessSetup@0 +GdiSetBatchLimit=GdiSetBatchLimit@4 +GetArcDirection=GetArcDirection@4 +GetAspectRatioFilterEx=GetAspectRatioFilterEx@8 +GetBitmapBits=GetBitmapBits@12 +GetBitmapDimensionEx=GetBitmapDimensionEx@8 +GetBkColor=GetBkColor@4 +GetBkMode=GetBkMode@4 +GetBoundsRect=GetBoundsRect@12 +GetBrushOrgEx=GetBrushOrgEx@8 +GetCharABCWidthsA=GetCharABCWidthsA@16 +GetCharABCWidthsFloatA=GetCharABCWidthsFloatA@16 +GetCharABCWidthsFloatW=GetCharABCWidthsFloatW@16 +GetCharABCWidthsW=GetCharABCWidthsW@16 +GetCharWidth32A=GetCharWidth32A@16 +GetCharWidth32W=GetCharWidth32W@16 +GetCharWidthA=GetCharWidthA@16 +GetCharWidthFloatA=GetCharWidthFloatA@16 +GetCharWidthFloatW=GetCharWidthFloatW@16 +GetCharWidthW=GetCharWidthW@16 +GetCharacterPlacementA=GetCharacterPlacementA@24 +GetCharacterPlacementW=GetCharacterPlacementW@24 +GetClipBox=GetClipBox@8 +GetClipRgn=GetClipRgn@8 +GetColorAdjustment=GetColorAdjustment@8 +GetColorSpace=GetColorSpace@4 +GetCurrentObject=GetCurrentObject@8 +GetCurrentPositionEx=GetCurrentPositionEx@8 +GetDCOrgEx=GetDCOrgEx@8 +GetDIBColorTable=GetDIBColorTable@16 +GetDIBits=GetDIBits@28 +GetDeviceCaps=GetDeviceCaps@8 +GetDeviceGammaRamp=GetDeviceGammaRamp@8 +GetEnhMetaFileA=GetEnhMetaFileA@4 +GetEnhMetaFileBits=GetEnhMetaFileBits@12 +GetEnhMetaFileDescriptionA=GetEnhMetaFileDescriptionA@12 +GetEnhMetaFileDescriptionW=GetEnhMetaFileDescriptionW@12 +GetEnhMetaFileHeader=GetEnhMetaFileHeader@12 +GetEnhMetaFilePaletteEntries=GetEnhMetaFilePaletteEntries@12 +GetEnhMetaFilePixelFormat=GetEnhMetaFilePixelFormat@12 +GetEnhMetaFileW=GetEnhMetaFileW@4 +GetFontData=GetFontData@20 +GetFontLanguageInfo=GetFontLanguageInfo@4 +GetFontResourceInfo=GetFontResourceInfo@16 +GetFontResourceInfoW=GetFontResourceInfoW@16 +GetGlyphOutlineA=GetGlyphOutlineA@28 +GetGlyphOutlineA=GetGlyphOutlineA@28 +GetGlyphOutlineW=GetGlyphOutlineW@28 +GetGlyphOutlineWow=GetGlyphOutlineWow@28 +GetGraphicsMode=GetGraphicsMode@4 +GetICMProfileA=GetICMProfileA@12 +GetICMProfileW=GetICMProfileW@12 +GetKerningPairsA=GetKerningPairsA@12 +GetKerningPairsA=GetKerningPairsA@12 +GetKerningPairsW=GetKerningPairsW@12 +GetLogColorSpaceA=GetLogColorSpaceA@12 +GetLogColorSpaceW=GetLogColorSpaceW@12 +GetMapMode=GetMapMode@4 +GetMetaFileA=GetMetaFileA@4 +GetMetaFileBitsEx=GetMetaFileBitsEx@12 +GetMetaFileW=GetMetaFileW@4 +GetMetaRgn=GetMetaRgn@8 +GetMiterLimit=GetMiterLimit@8 +GetNearestColor=GetNearestColor@8 +GetNearestPaletteIndex=GetNearestPaletteIndex@8 +GetObjectA=GetObjectA@12 +GetObjectType=GetObjectType@4 +GetObjectW=GetObjectW@12 +GetOutlineTextMetricsA=GetOutlineTextMetricsA@12 +GetOutlineTextMetricsW=GetOutlineTextMetricsW@12 +GetPaletteEntries=GetPaletteEntries@16 +GetPath=GetPath@16 +GetPixel=GetPixel@12 +GetPixelFormat=GetPixelFormat@4 +GetPolyFillMode=GetPolyFillMode@4 +GetROP2=GetROP2@4 +GetRandomRgn=GetRandomRgn@12 +GetRasterizerCaps=GetRasterizerCaps@8 +GetRegionData=GetRegionData@12 +GetRelAbs=GetRelAbs@8 +GetRgnBox=GetRgnBox@8 +GetStockObject=GetStockObject@4 +GetStretchBltMode=GetStretchBltMode@4 +GetSystemPaletteEntries=GetSystemPaletteEntries@16 +GetSystemPaletteUse=GetSystemPaletteUse@4 +GetTextAlign=GetTextAlign@4 +GetTextCharacterExtra=GetTextCharacterExtra@4 +GetTextCharset=GetTextCharset@4 +GetTextCharsetInfo=GetTextCharsetInfo@12 +GetTextColor=GetTextColor@4 +GetTextExtentExPointA=GetTextExtentExPointA@28 +GetTextExtentExPointW=GetTextExtentExPointW@28 +GetTextExtentPoint32A=GetTextExtentPoint32A@16 +GetTextExtentPoint32W=GetTextExtentPoint32W@16 +GetTextExtentPointA=GetTextExtentPointA@16 +GetTextExtentPointW=GetTextExtentPointW@16 +GetTextFaceA=GetTextFaceA@12 +GetTextFaceW=GetTextFaceW@12 +GetTextMetricsA=GetTextMetricsA@8 +GetTextMetricsW=GetTextMetricsW@8 +GetViewportExtEx=GetViewportExtEx@8 +GetViewportOrgEx=GetViewportOrgEx@8 +GetWinMetaFileBits=GetWinMetaFileBits@20 +GetWindowExtEx=GetWindowExtEx@8 +GetWindowOrgEx=GetWindowOrgEx@8 +GetWorldTransform=GetWorldTransform@8 +IntersectClipRect=IntersectClipRect@20 +InvertRgn=InvertRgn@8 +LPtoDP=LPtoDP@12 +LineDDA=LineDDA@24 +LineTo=LineTo@12 +MaskBlt=MaskBlt@48 +ModifyWorldTransform=ModifyWorldTransform@12 +MoveToEx=MoveToEx@16 +OffsetClipRgn=OffsetClipRgn@12 +OffsetRgn=OffsetRgn@12 +OffsetViewportOrgEx=OffsetViewportOrgEx@16 +OffsetWindowOrgEx=OffsetWindowOrgEx@16 +PaintRgn=PaintRgn@8 +PatBlt=PatBlt@24 +PathToRegion=PathToRegion@4 +Pie=Pie@36 +PlayEnhMetaFile=PlayEnhMetaFile@12 +PlayEnhMetaFileRecord=PlayEnhMetaFileRecord@16 +PlayMetaFile=PlayMetaFile@8 +PlayMetaFileRecord=PlayMetaFileRecord@16 +PlgBlt=PlgBlt@40 +PolyBezier=PolyBezier@12 +PolyBezierTo=PolyBezierTo@12 +PolyDraw=PolyDraw@16 +PolyPolygon=PolyPolygon@16 +PolyPolyline=PolyPolyline@16 +PolyTextOutA=PolyTextOutA@12 +PolyTextOutW=PolyTextOutW@12 +Polygon=Polygon@12 +Polyline=Polyline@12 +PolylineTo=PolylineTo@12 +PtInRegion=PtInRegion@12 +PtVisible=PtVisible@12 +RealizePalette=RealizePalette@4 +RectInRegion=RectInRegion@8 +RectVisible=RectVisible@8 +Rectangle=Rectangle@20 +RemoveFontResourceA=RemoveFontResourceA@4 +RemoveFontResourceW=RemoveFontResourceW@4 +ResetDCA=ResetDCA@8 +ResetDCW=ResetDCW@8 +ResizePalette=ResizePalette@8 +RestoreDC=RestoreDC@8 +RoundRect=RoundRect@28 +SaveDC=SaveDC@4 +ScaleViewportExtEx=ScaleViewportExtEx@24 +ScaleWindowExtEx=ScaleWindowExtEx@24 +SelectBrushLocal=SelectBrushLocal@8 +SelectClipPath=SelectClipPath@8 +SelectClipRgn=SelectClipRgn@8 +SelectFontLocal=SelectFontLocal@8 +SelectObject=SelectObject@8 +SelectPalette=SelectPalette@12 +SetAbortProc=SetAbortProc@8 +SetArcDirection=SetArcDirection@8 +SetBitmapBits=SetBitmapBits@12 +SetBitmapDimensionEx=SetBitmapDimensionEx@16 +SetBkColor=SetBkColor@8 +SetBkMode=SetBkMode@8 +SetBoundsRect=SetBoundsRect@12 +SetBrushOrgEx=SetBrushOrgEx@16 +SetColorAdjustment=SetColorAdjustment@8 +SetColorSpace=SetColorSpace@8 +SetDIBColorTable=SetDIBColorTable@16 +SetDIBits=SetDIBits@28 +SetDIBitsToDevice=SetDIBitsToDevice@48 +SetDeviceGammaRamp=SetDeviceGammaRamp@8 +SetEnhMetaFileBits=SetEnhMetaFileBits@8 +SetFontEnumeration=SetFontEnumeration@4 +SetGraphicsMode=SetGraphicsMode@8 +SetICMMode=SetICMMode@8 +SetICMProfileA=SetICMProfileA@8 +SetICMProfileW=SetICMProfileW@8 +SetMapMode=SetMapMode@8 +SetMapperFlags=SetMapperFlags@8 +SetMetaFileBitsEx=SetMetaFileBitsEx@8 +SetMetaRgn=SetMetaRgn@4 +SetMiterLimit=SetMiterLimit@12 +SetPaletteEntries=SetPaletteEntries@16 +SetPixel=SetPixel@16 +SetPixelFormat=SetPixelFormat@12 +SetPixelV=SetPixelV@16 +SetPolyFillMode=SetPolyFillMode@8 +SetROP2=SetROP2@8 +SetRectRgn=SetRectRgn@20 +SetRelAbs=SetRelAbs@8 +SetStretchBltMode=SetStretchBltMode@8 +SetSystemPaletteUse=SetSystemPaletteUse@8 +SetTextAlign=SetTextAlign@8 +SetTextCharacterExtra=SetTextCharacterExtra@8 +SetTextColor=SetTextColor@8 +SetTextJustification=SetTextJustification@12 +SetViewportExtEx=SetViewportExtEx@16 +SetViewportOrgEx=SetViewportOrgEx@16 +SetWinMetaFileBits=SetWinMetaFileBits@16 +SetWindowExtEx=SetWindowExtEx@16 +SetWindowOrgEx=SetWindowOrgEx@16 +SetWorldTransform=SetWorldTransform@8 +StartDocA=StartDocA@8 +StartDocW=StartDocW@8 +StartPage=StartPage@4 +StretchBlt=StretchBlt@44 +StretchDIBits=StretchDIBits@52 +StrokeAndFillPath=StrokeAndFillPath@4 +StrokePath=StrokePath@4 +SwapBuffers=SwapBuffers@4 +TextOutA=TextOutA@20 +TextOutW=TextOutW@20 +TranslateCharsetInfo=TranslateCharsetInfo@12 +UnrealizeObject=UnrealizeObject@4 +UpdateColors=UpdateColors@4 +UpdateICMRegKeyA=UpdateICMRegKeyA@16 +UpdateICMRegKeyA=UpdateICMRegKeyA@16 +UpdateICMRegKeyW=UpdateICMRegKeyW@16 +WidenPath=WidenPath@4 +gdiPlaySpoolStream=gdiPlaySpoolStream@24 diff --git a/lib/gdi32/gdi32.rc b/lib/gdi32/gdi32.rc new file mode 100644 index 0000000..159b5c3 --- /dev/null +++ b/lib/gdi32/gdi32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "GDI Client DLL\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "gdi32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "gdi32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/gdi32/gdi32_specs b/lib/gdi32/gdi32_specs new file mode 100644 index 0000000..f9cd789 --- /dev/null +++ b/lib/gdi32/gdi32_specs @@ -0,0 +1,78 @@ +*asm: + + +*asm_final: + + +*cpp: +-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} + +*cc1: +%(cc1_spec) + +*cc1plus: + + +*endfile: + + +*link: +%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12} + +*lib: + + +*libgcc: +-lgcc + +*startfile: + + +*switches_need_spaces: + + +*signed_char: +%{funsigned-char:-D__CHAR_UNSIGNED__} + +*predefines: +-Di386 -D_WIN32 -DWIN32 -D__WIN32__ -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D_stdcall=__attribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)=__attribute__((x)) -Asystem(winnt) -Acpu(i386) -Amachine(i386) + +*cross_compile: +1 + +*version: +egcs-2.91.57 + +*multilib: +. ; + +*multilib_defaults: + + +*multilib_extra: + + +*multilib_matches: + + +*linker: +collect2 + +*cpp_486: +%{!ansi:-Di486} -D__i486 -D__i486__ + +*cpp_586: +%{!ansi:-Di586 -Dpentium} -D__i586 -D__i586__ -D__pentium -D__pentium__ + +*cpp_686: +%{!ansi:-Di686 -Dpentiumpro} -D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__ + +*cpp_cpu_default: +%(cpp_586) + +*cpp_cpu: +-Acpu(i386) -Amachine(i386) %{!ansi:-Di386} -D__i386 -D__i386__ %{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} %{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} %{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} %{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}} + +*cc1_cpu: +%{!mcpu*: %{m386:-mcpu=i386 -march=i386} %{mno-486:-mcpu=i386 -march=i386} %{m486:-mcpu=i486 -march=i486} %{mno-386:-mcpu=i486 -march=i486} %{mno-pentium:-mcpu=i486 -march=i486} %{mpentium:-mcpu=pentium} %{mno-pentiumpro:-mcpu=pentium} %{mpentiumpro:-mcpu=pentiumpro}} + diff --git a/lib/gdi32/main/dllmain.c b/lib/gdi32/main/dllmain.c new file mode 100644 index 0000000..b3b334d --- /dev/null +++ b/lib/gdi32/main/dllmain.c @@ -0,0 +1,66 @@ +/* + * dllmain.c + * + * $Revision$ + * $Author$ + * $Date$ + * + */ + +#include +#include + +/* + * GDI32.DLL doesn't have an entry point. The initialization is done by a call + * to GdiDllInitialize(). This call is done from the entry point of USER32.DLL. + */ +BOOL +WINAPI +DllMain ( + HANDLE hDll, + DWORD dwReason, + LPVOID lpReserved + ) +{ + return TRUE; +} + + +BOOL +WINAPI +GdiDllInitialize ( + HANDLE hDll, + DWORD dwReason, + LPVOID lpReserved + ) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + GdiProcessSetup (); + break; + + case DLL_THREAD_ATTACH: + break; + + default: + return FALSE; + } + +#if 0 + /* FIXME: working teb handling needed */ + NtCurrentTeb()->GdiTebBatch.Offset = 0; + NtCurrentTeb()->GdiBatchCount = 0; +#endif + + return TRUE; +} + +VOID +WINAPI +GdiProcessSetup (VOID) +{ + +} + +/* EOF */ diff --git a/lib/gdi32/makefile b/lib/gdi32/makefile new file mode 100644 index 0000000..894abe5 --- /dev/null +++ b/lib/gdi32/makefile @@ -0,0 +1,32 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = gdi32 + +TARGET_BASE = 0x77ed0000 + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CLEAN = main/*.o misc/*.o objects/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +MAIN_OBJECTS = main/dllmain.o + +MISC_OBJECTS = misc/stubs.o misc/stubsa.o misc/stubsw.o misc/win32k.o + +OBJECTS_OBJECTS = objects/dc.o objects/line.o objects/pen.o objects/bitblt.o objects/text.o objects/region.o objects/brush.o + +OBJECTS = $(MAIN_OBJECTS) $(MISC_OBJECTS) $(OBJECTS_OBJECTS) + +$(TARGET_NAME).o: $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o + +# EOF diff --git a/lib/gdi32/misc/.cvsignore b/lib/gdi32/misc/.cvsignore new file mode 100644 index 0000000..63c24b8 --- /dev/null +++ b/lib/gdi32/misc/.cvsignore @@ -0,0 +1 @@ +win32k.c \ No newline at end of file diff --git a/lib/gdi32/misc/stubs.c b/lib/gdi32/misc/stubs.c new file mode 100644 index 0000000..5454fa5 --- /dev/null +++ b/lib/gdi32/misc/stubs.c @@ -0,0 +1,2861 @@ +/* $Id$ + * + * reactos/lib/gdi32/misc/stubs.c + * + * GDI32.DLL Stubs + * + * When you implement one of these functions, + * remove its stub from this file. + * + */ +#ifdef UNICODE +#undef UNICODE +#endif +#include + + +BOOL +STDCALL +AnimatePalette( + HPALETTE a0, + UINT a1, + UINT a2, + CONST PALETTEENTRY *a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +Arc( + HDC a0, + int a1, + int a2, + int a3, + int a4, + int a5, + int a6, + int a7, + int a8 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +CancelDC( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +Chord( + HDC a0, + int a1, + int a2, + int a3, + int a4, + int a5, + int a6, + int a7, + int a8 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +ChoosePixelFormat( + HDC a0, + CONST PIXELFORMATDESCRIPTOR *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HMETAFILE +STDCALL +CloseMetaFile( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HBRUSH +STDCALL +CreateBrushIndirect( + CONST LOGBRUSH *a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HBRUSH +STDCALL +CreateDIBPatternBrush( + HGLOBAL a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HBRUSH +STDCALL +CreateDIBPatternBrushPt( + CONST VOID *a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HRGN +STDCALL +CreateEllipticRgn( + int a0, + int a1, + int a2, + int a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HRGN +STDCALL +CreateEllipticRgnIndirect( + CONST RECT *a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HBRUSH +STDCALL +CreateHatchBrush( + int a0, + COLORREF a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HPALETTE +STDCALL +CreatePalette( + CONST LOGPALETTE *a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +BOOL +STDCALL +DeleteMetaFile( + HMETAFILE a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +DescribePixelFormat( + HDC a0, + int a1, + UINT a2, + LPPIXELFORMATDESCRIPTOR a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +DrawEscape( + HDC a0, + int a1, + int a2, + LPCSTR a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +Ellipse( + HDC a0, + int a1, + int a2, + int a3, + int a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +EnumObjects( + HDC a0, + int a1, + ENUMOBJECTSPROC a2, + LPARAM a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +Escape( + HDC a0, + int a1, + int a2, + LPCSTR a3, + LPVOID a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + +int +STDCALL +ExtEscape( + HDC a0, + int a1, + int a2, + LPCSTR a3, + int a4, + LPSTR a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +ExcludeClipRect( + HDC a0, + int a1, + int a2, + int a3, + int a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HRGN +STDCALL +ExtCreateRegion( + CONST XFORM * a0, + DWORD a1, + CONST RGNDATA * a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +ExtFloodFill( + HDC a0, + int a1, + int a2, + COLORREF a3, + UINT a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +FillRgn( + HDC a0, + HRGN a1, + HBRUSH a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +FloodFill( + HDC a0, + int a1, + int a2, + COLORREF a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +FrameRgn( + HDC a0, + HRGN a1, + HBRUSH a2, + int a3, + int a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +GetROP2( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +GetAspectRatioFilterEx( + HDC a0, + LPSIZE a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +COLORREF +STDCALL +GetBkColor( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetBkMode( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetBoundsRect( + HDC a0, + LPRECT a1, + UINT a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +GetBrushOrgEx( + HDC a0, + LPPOINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +GetClipRgn( + HDC a0, + HRGN a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetMetaRgn( + HDC a0, + HRGN a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HGDIOBJ +STDCALL +GetCurrentObject( + HDC a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +GetCurrentPositionEx( + HDC a0, + LPPOINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +GetDeviceCaps( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + +DWORD +STDCALL +GetFontData( + HDC a0, + DWORD a1, + DWORD a2, + LPVOID a3, + DWORD a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetGraphicsMode( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + +int +STDCALL +GetMapMode( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetMetaFileBitsEx( + HMETAFILE a0, + UINT a1, + LPVOID a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +COLORREF +STDCALL +GetNearestColor( + HDC a0, + COLORREF a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetNearestPaletteIndex( + HPALETTE a0, + COLORREF a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD +STDCALL +GetObjectType( + HGDIOBJ a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT +STDCALL +GetPaletteEntries( + HPALETTE a0, + UINT a1, + UINT a2, + LPPALETTEENTRY a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +COLORREF +STDCALL +GetPixel( + HDC a0, + int a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetPixelFormat( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetPolyFillMode( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +GetRasterizerCaps( + LPRASTERIZER_STATUS a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + + + +int +STDCALL +GetStretchBltMode( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetSystemPaletteEntries( + HDC a0, + UINT a1, + UINT a2, + LPPALETTEENTRY a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetSystemPaletteUse( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetTextCharacterExtra( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetTextAlign( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +COLORREF +STDCALL +GetTextColor( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetTextCharset( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +GetTextCharsetInfo( + HDC hdc, + LPFONTSIGNATURE lpSig, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +TranslateCharsetInfo( + DWORD FAR *lpSrc, + LPCHARSETINFO lpCs, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +DWORD +STDCALL +GetFontLanguageInfo( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +GetViewportExtEx( + HDC hDc, + LPSIZE lpSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GetViewportOrgEx( + HDC hDc, + LPPOINT lpPoint + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GetWindowExtEx( + HDC hDc, + LPSIZE lpSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GetWindowOrgEx( + HDC hDc, + LPPOINT lpPoint + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +IntersectClipRect( + HDC hDc, + int a1, + int a2, + int a3, + int a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +InvertRgn( + HDC hDc, + HRGN hRgn + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +LineDDA( + int a0, + int a1, + int a2, + int a3, + LINEDDAPROC a4, + LPARAM a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + +int +STDCALL +OffsetClipRgn( + HDC a0, + int a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + + +BOOL +STDCALL +Pie( + HDC a0, + int a1, + int a2, + int a3, + int a4, + int a5, + int a6, + int a7, + int a8 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PlayMetaFile( + HDC a0, + HMETAFILE a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + + + +BOOL +STDCALL +PolyPolygon( + HDC a0, + CONST POINT *a1, + CONST INT *a2, + int a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PtInRegion( + HRGN a0, + int a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PtVisible( + HDC a0, + int a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +RectInRegion( + HRGN a0, + CONST RECT *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +RectVisible( + HDC a0, + CONST RECT *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +RestoreDC( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +UINT +STDCALL +RealizePalette( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +RoundRect( + HDC a0, + int a1, + int a2, + int a3, + int a4, + int a5, + int a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +ResizePalette( + HPALETTE a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +SaveDC( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SelectClipRgn( + HDC a0, + HRGN a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +ExtSelectClipRgn( + HDC a0, + HRGN a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SetMetaRgn( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HPALETTE +STDCALL +SelectPalette( + HDC a0, + HPALETTE a1, + BOOL a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +COLORREF +STDCALL +SetBkColor( + HDC a0, + COLORREF a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SetBkMode( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +SetBoundsRect( + HDC a0, + CONST RECT *a1, + UINT a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD +STDCALL +SetMapperFlags( + HDC a0, + DWORD a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SetGraphicsMode( + HDC hdc, + int iMode + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HMETAFILE +STDCALL +SetMetaFileBitsEx( + UINT a0, + CONST BYTE *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +SetPaletteEntries( + HPALETTE a0, + UINT a1, + UINT a2, + CONST PALETTEENTRY *a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +SetPixelV( + HDC a0, + int a1, + int a2, + COLORREF a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SetPixelFormat( + HDC a0, + int a1, + CONST PIXELFORMATDESCRIPTOR *a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +SetPolyFillMode( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +StretchBlt( + HDC a0, + int a1, + int a2, + int a3, + int a4, + HDC a5, + int a6, + int a7, + int a8, + int a9, + DWORD a10 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +SetROP2( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SetStretchBltMode( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +SetSystemPaletteUse( + HDC a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SetTextCharacterExtra( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +SetTextAlign( + HDC a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +SetTextJustification( + HDC a0, + int a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +UpdateColors( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PlayMetaFileRecord( + HDC a0, + LPHANDLETABLE a1, + LPMETARECORD a2, + UINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +EnumMetaFile( + HDC a0, + HMETAFILE a1, + ENUMMETAFILEPROC a2, + LPARAM a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +HENHMETAFILE +STDCALL +CloseEnhMetaFile( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +DeleteEnhMetaFile( + HENHMETAFILE a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +EnumEnhMetaFile( + HDC a0, + HENHMETAFILE a1, + ENHMETAFILEPROC a2, + LPVOID a3, + CONST RECT *a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +UINT +STDCALL +GetEnhMetaFileBits( + HENHMETAFILE a0, + UINT a1, + LPBYTE a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetEnhMetaFileHeader( + HENHMETAFILE a0, + UINT a1, + LPENHMETAHEADER a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetEnhMetaFilePaletteEntries( + HENHMETAFILE a0, + UINT a1, + LPPALETTEENTRY a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetEnhMetaFilePixelFormat( + HENHMETAFILE a0, + DWORD a1, + CONST PIXELFORMATDESCRIPTOR *a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +GetWinMetaFileBits( + HENHMETAFILE a0, + UINT a1, + LPBYTE a2, + INT a3, + HDC a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +PlayEnhMetaFile( + HDC a0, + HENHMETAFILE a1, + CONST RECT *a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PlayEnhMetaFileRecord( + HDC a0, + LPHANDLETABLE a1, + CONST ENHMETARECORD *a2, + UINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +HENHMETAFILE +STDCALL +SetEnhMetaFileBits( + UINT a0, + CONST BYTE *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HENHMETAFILE +STDCALL +SetWinMetaFileBits( + UINT a0, + CONST BYTE *a1, + HDC a2, +// CONST METAFILEPICT *a3 + PVOID a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +GdiComment( + HDC a0, + UINT a1, + CONST BYTE *a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +AngleArc( + HDC hdc, + int a1, + int a2, + DWORD a3, + FLOAT a4, + FLOAT a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PolyPolyline( + HDC hdc, + CONST POINT *a1, + CONST DWORD *a2, + DWORD a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GetWorldTransform( + HDC hdc, + LPXFORM a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SetWorldTransform( + HDC a0, + CONST XFORM *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +ModifyWorldTransform( + HDC a0, + CONST XFORM *a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +CombineTransform( + LPXFORM a0, + CONST XFORM *a1, + CONST XFORM *a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +UINT +STDCALL +GetDIBColorTable( + HDC hdc, + UINT a1, + UINT a2, + RGBQUAD *a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +UINT +STDCALL +SetDIBColorTable( + HDC hdc, + UINT a1, + UINT a2, + CONST RGBQUAD *a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +SetColorAdjustment( + HDC hdc, + CONST COLORADJUSTMENT *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GetColorAdjustment( + HDC hdc, + LPCOLORADJUSTMENT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +HPALETTE +STDCALL +CreateHalftonePalette( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +EndDoc( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +StartPage( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +EndPage( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +AbortDoc( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +int +STDCALL +SetAbortProc( + HDC hdc, + ABORTPROC a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +AbortPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +ArcTo( + HDC hdc, + int a1, + int a2, + int a3, + int a4, + int a5, + int a6, + int a7, + int a8 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +BeginPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +CloseFigure( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +EndPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +FillPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +FlattenPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +GetPath( + HDC hdc, + LPPOINT a1, + LPBYTE a2, + int a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HRGN +STDCALL +PathToRegion( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +PolyDraw( + HDC hdc, + CONST POINT *a1, + CONST BYTE *a2, + int a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SelectClipPath( + HDC hdc, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +SetArcDirection( + HDC hdc, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +SetMiterLimit( + HDC hdc, + FLOAT a1, + PFLOAT a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +StrokeAndFillPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +StrokePath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +WidenPath( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +HPEN +STDCALL +ExtCreatePen( + DWORD a0, + DWORD a1, + CONST LOGBRUSH *a2, + DWORD a3, + CONST DWORD *a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +GetMiterLimit( + HDC hdc, + PFLOAT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +int +STDCALL +GetArcDirection( + HDC hdc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HRGN +STDCALL +CreatePolygonRgn( + CONST POINT *a0, + int a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +DPtoLP( + HDC a0, + LPPOINT a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +LPtoDP( + HDC a0, + LPPOINT a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +Polygon( + HDC a0, + CONST POINT *a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +Polyline( + HDC a0, + CONST POINT *a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PolyBezier( + HDC a0, + CONST POINT *a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PolyBezierTo( + HDC a0, + CONST POINT *a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +PolylineTo( + HDC a0, + CONST POINT *a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SetViewportExtEx( + HDC a0, + int a1, + int a2, + LPSIZE a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SetWindowExtEx( + HDC a0, + int a1, + int a2, + LPSIZE a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + +BOOL +STDCALL +OffsetViewportOrgEx( + HDC a0, + int a1, + int a2, + LPPOINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +OffsetWindowOrgEx( + HDC a0, + int a1, + int a2, + LPPOINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +ScaleViewportExtEx( + HDC a0, + int a1, + int a2, + int a3, + int a4, + LPSIZE a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +ScaleWindowExtEx( + HDC a0, + int a1, + int a2, + int a3, + int a4, + LPSIZE a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SetBitmapDimensionEx( + HBITMAP a0, + int a1, + int a2, + LPSIZE a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +SetBrushOrgEx( + HDC a0, + int a1, + int a2, + LPPOINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GetDCOrgEx( + HDC a0, + LPPOINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +FixBrushOrgEx( + HDC a0, + int a1, + int a2, + LPPOINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +UnrealizeObject( + HGDIOBJ a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +GdiFlush() +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +DWORD +STDCALL +GdiSetBatchLimit( + DWORD a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD +STDCALL +GdiGetBatchLimit() +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +SetICMMode( + HDC a0, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +CheckColorsInGamut( + HDC a0, + LPVOID a1, + LPVOID a2, + DWORD a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +HANDLE +STDCALL +GetColorSpace( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +SetColorSpace( + HDC a0, + HCOLORSPACE a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +DeleteColorSpace( + HCOLORSPACE a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +GetDeviceGammaRamp( + HDC a0, + LPVOID a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +SetDeviceGammaRamp( + HDC a0, + LPVOID a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +ColorMatchToTarget( + HDC a0, + HDC a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +wglCopyContext( + HGLRC a0, + HGLRC a1, + UINT a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +HGLRC +STDCALL +wglCreateContext( + HDC hDc + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HGLRC +STDCALL +wglCreateLayerContext( + HDC hDc, + int a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +wglDeleteContext( + HGLRC a + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +HGLRC +STDCALL +wglGetCurrentContext(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HDC +STDCALL +wglGetCurrentDC(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +PROC +STDCALL +wglGetProcAddress( + LPCSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +BOOL +STDCALL +wglMakeCurrent( + HDC a0, + HGLRC a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +wglShareLists( + HGLRC a0, + HGLRC a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +SwapBuffers( + HDC a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +BOOL +STDCALL +wglDescribeLayerPlane( + HDC a0, + int a1, + int a2, + UINT a3, + LPLAYERPLANEDESCRIPTOR a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +wglSetLayerPaletteEntries( + HDC a0, + int a1, + int a2, + int a3, + CONST COLORREF *a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +wglGetLayerPaletteEntries( + HDC a0, + int a1, + int a2, + int a3, + CONST COLORREF *a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +wglRealizeLayerPalette( + HDC a0, + int a1, + BOOL a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +wglSwapLayerBuffers( + HDC a0, + UINT a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* === AFTER THIS POINT I GUESS... ========= + * (based on stack size in Norlander's .def) + * === WHERE ARE THEY DEFINED? ============= + */ + + +DWORD +STDCALL +GdiPlayDCScript( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3, + DWORD a4, + DWORD a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GdiPlayJournal( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3, + DWORD a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GdiPlayScript( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3, + DWORD a4, + DWORD a5, + DWORD a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetGlyphOutlineWow( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3, + DWORD a4, + DWORD a5, + DWORD a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetRandomRgn( + DWORD a0, + DWORD a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetRelAbs( + DWORD a0, + DWORD a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD +STDCALL +SelectBrushLocal( + DWORD a0, + DWORD a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD +STDCALL +SelectFontLocal( + DWORD a0, + DWORD a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +SetFontEnumeration( + DWORD a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +SetRelAbs( + DWORD a0, + DWORD a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +gdiPlaySpoolStream( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3, + DWORD a4, + DWORD a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetFontResourceInfo( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* EOF */ diff --git a/lib/gdi32/misc/stubsa.c b/lib/gdi32/misc/stubsa.c new file mode 100644 index 0000000..ab5ce9f --- /dev/null +++ b/lib/gdi32/misc/stubsa.c @@ -0,0 +1,541 @@ +/* $Id$ + * + * reactos/lib/gdi32/misc/stubs.c + * + * GDI32.DLL Stubs for ANSI functions + * + * When you implement one of these functions, + * remove its stub from this file. + * + */ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include + +int +STDCALL +AddFontResourceA( + LPCSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HMETAFILE +STDCALL +CopyMetaFileA( + HMETAFILE a0, + LPCSTR a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +HDC +STDCALL +CreateICA( + LPCSTR a0, + LPCSTR a1, + LPCSTR a2, + CONST DEVMODEA * a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +CreateMetaFileA( + LPCSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +CreateScalableFontResourceA( + DWORD a0, + LPCSTR a1, + LPCSTR a2, + LPCSTR a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +DeviceCapabilitiesExA( + LPCSTR a0, + LPCSTR a1, + WORD a2, + LPSTR a3, + CONST DEVMODEA *a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +EnumFontFamiliesExA( + HDC a0, + LPLOGFONT a1, + FONTENUMEXPROC a2, + LPARAM a3, + DWORD a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +EnumFontFamiliesA( + HDC a0, + LPCSTR a1, + FONTENUMPROC a2, + LPARAM a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +EnumFontsA( + HDC a0, + LPCSTR a1, + ENUMFONTSPROC a2, + LPARAM a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +GetCharWidthA( + HDC a0, + UINT a1, + UINT a2, + LPINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +GetCharWidth32A( + HDC a0, + UINT a1, + UINT a2, + LPINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetCharWidthFloatA( + HDC a0, + UINT a1, + UINT a2, + PFLOAT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetCharABCWidthsA( + HDC a0, + UINT a1, + UINT a2, + LPABC a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetCharABCWidthsFloatA( + HDC a0, + UINT a1, + UINT a2, + LPABCFLOAT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +GetGlyphOutlineA( + HDC a0, + UINT a1, + UINT a2, + LPGLYPHMETRICS a3, + DWORD a4, + LPVOID a5, + CONST MAT2 *a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HMETAFILE +STDCALL +GetMetaFileA( + LPCSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT +APIENTRY +GetOutlineTextMetricsA( + HDC a0, + UINT a1, + LPOUTLINETEXTMETRIC a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +APIENTRY +GetTextExtentPoint32A( + HDC hDc, + LPCSTR a1, + int a2, + LPSIZE a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetTextExtentExPointA( + HDC hDc, + LPCSTR a1, + int a2, + int a3, + LPINT a4, + LPINT a5, + LPSIZE a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +GetCharacterPlacementA( + HDC hDc, + LPCSTR a1, + int a2, + int a3, + LPGCP_RESULTS a4, + DWORD a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +ResetDCA( + HDC a0, + CONST DEVMODEA *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +RemoveFontResourceA( + LPCSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +HENHMETAFILE +STDCALL +CopyEnhMetaFileA( + HENHMETAFILE a0, + LPCSTR a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +CreateEnhMetaFileA( + HDC a0, + LPCSTR a1, + CONST RECT *a2, + LPCSTR a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HENHMETAFILE +STDCALL +GetEnhMetaFileA( + LPCSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT +STDCALL +GetEnhMetaFileDescriptionA( + HENHMETAFILE a0, + UINT a1, + LPSTR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +StartDocA( + HDC hdc, + CONST DOCINFO *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetObjectA( + HGDIOBJ a0, + int a1, + LPVOID a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +PolyTextOutA( + HDC hdc, + CONST POLYTEXT *a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +GetTextFaceA( + HDC a0, + int a1, + LPSTR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +GetKerningPairsA( + HDC a0, + DWORD a1, + LPKERNINGPAIR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +GetLogColorSpaceA( + HCOLORSPACE a0, + LPLOGCOLORSPACE a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +HCOLORSPACE +STDCALL +CreateColorSpaceA( + LPLOGCOLORSPACE a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL +STDCALL +GetICMProfileA( + HDC a0, + DWORD a1, /* MS says LPDWORD! */ + LPSTR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +SetICMProfileA( + HDC a0, + LPSTR a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +EnumICMProfilesA( + HDC a0, + ICMENUMPROC a1, + LPARAM a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +wglUseFontBitmapsA( + HDC a0, + DWORD a1, + DWORD a2, + DWORD a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +wglUseFontOutlinesA( + HDC a0, + DWORD a1, + DWORD a2, + DWORD a3, + FLOAT a4, + FLOAT a5, + int a6, + LPGLYPHMETRICSFLOAT a7 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +UpdateICMRegKeyA( + DWORD a0, + DWORD a1, + LPSTR a2, + UINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* EOF */ diff --git a/lib/gdi32/misc/stubsw.c b/lib/gdi32/misc/stubsw.c new file mode 100644 index 0000000..77d382b --- /dev/null +++ b/lib/gdi32/misc/stubsw.c @@ -0,0 +1,558 @@ +/* $Id$ + * + * reactos/lib/gdi32/misc/stubs.c + * + * GDI32.DLL Stubs for Unicode functions + * + * When you implement one of these functions, + * remove its stub from this file. + * + */ +#define UNICODE +#include +#include + +int +STDCALL +AddFontResourceW( + LPCWSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HMETAFILE +STDCALL +CopyMetaFileW( + HMETAFILE a0, + LPCWSTR a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +CreateICW( + LPCWSTR a0, + LPCWSTR a1, + LPCWSTR a2, + CONST DEVMODEW * a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +CreateMetaFileW( + LPCWSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +CreateScalableFontResourceW( + DWORD a0, + LPCWSTR a1, + LPCWSTR a2, + LPCWSTR a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +DeviceCapabilitiesExW( + LPCWSTR a0, + LPCWSTR a1, + WORD a2, + LPWSTR a3, + CONST DEVMODEW *a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +EnumFontFamiliesExW( + HDC a0, + LPLOGFONT a1, + FONTENUMEXPROC a2, + LPARAM a3, + DWORD a4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +EnumFontFamiliesW( + HDC a0, + LPCWSTR a1, + FONTENUMPROC a2, + LPARAM a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +EnumFontsW( + HDC a0, + LPCWSTR a1, + ENUMFONTSPROC a2, + LPARAM a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +GetCharWidthW( + HDC a0, + UINT a1, + UINT a2, + LPINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +GetCharWidth32W( + HDC a0, + UINT a1, + UINT a2, + LPINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetCharWidthFloatW( + HDC a0, + UINT a1, + UINT a2, + PFLOAT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetCharABCWidthsW( + HDC a0, + UINT a1, + UINT a2, + LPABC a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetCharABCWidthsFloatW( + HDC a0, + UINT a1, + UINT a2, + LPABCFLOAT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +GetGlyphOutlineW( + HDC a0, + UINT a1, + UINT a2, + LPGLYPHMETRICS a3, + DWORD a4, + LPVOID a5, + CONST MAT2 *a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HMETAFILE +STDCALL +GetMetaFileW( + LPCWSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT +APIENTRY +GetOutlineTextMetricsW( + HDC a0, + UINT a1, + LPOUTLINETEXTMETRIC a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +APIENTRY +GetTextExtentPoint32W( + HDC hDc, + LPCWSTR a1, + int a2, + LPSIZE a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +APIENTRY +GetTextExtentExPointW( + HDC hDc, + LPCWSTR a1, + int a2, + int a3, + LPINT a4, + LPINT a5, + LPSIZE a6 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +GetCharacterPlacementW( + HDC hDc, + LPCWSTR a1, + int a2, + int a3, + LPGCP_RESULTS a4, + DWORD a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +ResetDCW( + HDC a0, + CONST DEVMODEW *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +RemoveFontResourceW( + LPCWSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +HENHMETAFILE +STDCALL +CopyEnhMetaFileW( + HENHMETAFILE a0, + LPCWSTR a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HDC +STDCALL +CreateEnhMetaFileW( + HDC a0, + LPCWSTR a1, + CONST RECT *a2, + LPCWSTR a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +HENHMETAFILE +STDCALL +GetEnhMetaFileW( + LPCWSTR a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT +STDCALL +GetEnhMetaFileDescriptionW( + HENHMETAFILE a0, + UINT a1, + LPWSTR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +StartDocW( + HDC hdc, + CONST DOCINFO *a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetObjectW( + HGDIOBJ a0, + int a1, + LPVOID a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +PolyTextOutW( + HDC hdc, + CONST POLYTEXT *a1, + int a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +GetTextFaceW( + HDC a0, + int a1, + LPWSTR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetKerningPairsW( + HDC a0, + DWORD a1, + LPKERNINGPAIR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +GetLogColorSpaceW( + HCOLORSPACE a0, + LPLOGCOLORSPACE a1, + DWORD a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +HCOLORSPACE +STDCALL +CreateColorSpaceW( + LPLOGCOLORSPACE a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL +STDCALL +GetICMProfileW( + HDC a0, + DWORD a1, /* MS says LPDWORD! */ + LPWSTR a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +SetICMProfileW( + HDC a0, + LPWSTR a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +EnumICMProfilesW( + HDC a0, + ICMENUMPROC a1, + LPARAM a2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +wglUseFontBitmapsW( + HDC a0, + DWORD a1, + DWORD a2, + DWORD a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +wglUseFontOutlinesW( + HDC a0, + DWORD a1, + DWORD a2, + DWORD a3, + FLOAT a4, + FLOAT a5, + int a6, + LPGLYPHMETRICSFLOAT a7 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +UpdateICMRegKeyW( + DWORD a0, + DWORD a1, + LPWSTR a2, + UINT a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* === AFTER THIS POINT I GUESS... ========= + * (based on stack size in Norlander's .def) + * === WHERE ARE THEY DEFINED? ============= + */ + + +DWORD +STDCALL +GetFontResourceInfoW( + DWORD a0, + DWORD a1, + DWORD a2, + DWORD a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* EOF */ diff --git a/lib/gdi32/objects/bitblt.c b/lib/gdi32/objects/bitblt.c new file mode 100644 index 0000000..ec8f3a4 --- /dev/null +++ b/lib/gdi32/objects/bitblt.c @@ -0,0 +1,267 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +BOOL +STDCALL +BitBlt(HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + DWORD ROP) +{ + return W32kBitBlt(hDCDest, XDest, YDest, Width, Height, hDCSrc, XSrc, YSrc, ROP); +} + +HBITMAP +STDCALL +CreateBitmap(INT Width, + INT Height, + UINT Planes, + UINT BitsPerPel, + CONST VOID *Bits) +{ + return W32kCreateBitmap(Width, Height, Planes, BitsPerPel, Bits); +} + +HBITMAP +STDCALL +CreateBitmapIndirect(CONST BITMAP *BM) +{ + return W32kCreateBitmapIndirect(BM); +} + +HBITMAP +STDCALL +CreateCompatibleBitmap(HDC hDC, + INT Width, + INT Height) +{ + return W32kCreateCompatibleBitmap(hDC, Width, Height); +} + +HBITMAP +STDCALL +CreateDiscardableBitmap(HDC hDC, + INT Width, + INT Height) +{ + return W32kCreateDiscardableBitmap(hDC, Width, Height); +} + +HBITMAP +STDCALL +CreateDIBitmap(HDC hDC, + CONST BITMAPINFOHEADER *bmih, + DWORD Init, + CONST VOID *bInit, + CONST BITMAPINFO *bmi, + UINT Usage) +{ + return W32kCreateDIBitmap(hDC, bmih, Init, bInit, bmi, Usage); +} + +LONG +STDCALL +GetBitmapBits(HBITMAP hBitmap, + LONG Count, + LPVOID Bits) +{ + return W32kGetBitmapBits(hBitmap, Count, Bits); +} + +BOOL +STDCALL +GetBitmapDimensionEx(HBITMAP hBitmap, + LPSIZE Dimension) +{ + return W32kGetBitmapDimensionEx(hBitmap, Dimension); +} + +int +STDCALL +GetDIBits(HDC hDC, + HBITMAP hBitmap, + UINT StartScan, + UINT ScanLines, + LPVOID Bits, + LPBITMAPINFO bi, + UINT Usage) +{ + return W32kGetDIBits(hDC, hBitmap, StartScan, ScanLines, Bits, bi, Usage); +} + +BOOL +STDCALL +MaskBlt(HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + HBITMAP hMaskBitmap, + INT xMask, + INT yMask, + DWORD ROP) +{ + return W32kMaskBlt(hDCDest, XDest, YDest, Width, Height, hDCSrc, XSrc, YSrc, hMaskBitmap, xMask, yMask, ROP); +} + +BOOL +STDCALL +PlgBlt(HDC hDCDest, + CONST POINT *Point, + HDC hDCSrc, + INT XSrc, + INT YSrc, + INT Width, + INT Height, + HBITMAP hMaskBitmap, + INT xMask, + INT yMask) +{ + return W32kPlgBlt(hDCDest, Point, hDCSrc, XSrc, YSrc, Width, Height, hMaskBitmap, xMask, yMask); +} + +LONG +STDCALL +SetBitmapBits(HBITMAP hBitmap, + DWORD Bytes, + CONST VOID *Bits) +{ + return W32kSetBitmapBits(hBitmap, Bytes, Bits); +} + +int +STDCALL +SetDIBits(HDC hDC, + HBITMAP hBitmap, + UINT StartScan, + UINT ScanLines, + CONST VOID *Bits, + CONST BITMAPINFO *bmi, + UINT ColorUse) +{ + return W32kSetDIBits(hDC, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse); +} + +int +STDCALL +SetDIBitsToDevice(HDC hDC, + INT XDest, + INT YDest, + DWORD Width, + DWORD Height, + INT XSrc, + INT YSrc, + UINT StartScan, + UINT ScanLines, + CONST VOID *Bits, + CONST BITMAPINFO *bmi, + UINT ColorUse) +{ + return W32kSetDIBitsToDevice(hDC, XDest, YDest, Width, Height, XSrc, YSrc, StartScan, ScanLines, + Bits, bmi, ColorUse); +} + +int +STDCALL +StretchDIBits(HDC hDC, + INT XDest, + INT YDest, + INT DestWidth, + INT DestHeight, + INT XSrc, + INT YSrc, + INT SrcWidth, + INT SrcHeight, + CONST VOID *Bits, + CONST BITMAPINFO *BitsInfo, + UINT Usage, + DWORD ROP) +{ + return W32kStretchDIBits(hDC, XDest, YDest, DestWidth, DestHeight, XSrc, YSrc, + SrcWidth, SrcHeight, Bits, BitsInfo, Usage, ROP); +} + +HBITMAP +STDCALL +CreateDIBSection(HDC hDC, + CONST BITMAPINFO *bmi, + UINT Usage, + VOID *Bits, + HANDLE hSection, + DWORD dwOffset) +{ + return W32kCreateDIBSection(hDC, bmi, Usage, Bits, hSection, dwOffset); +} + +COLORREF +STDCALL +SetPixel(HDC hDC, + INT X, + INT Y, + COLORREF Color) +{ + return W32kSetPixel(hDC, X, Y, Color); +} + +BOOL STDCALL +PatBlt(HDC hDC, INT Top, INT Left, INT Width, INT Height, ULONG Rop) +{ + return(W32kPatBlt(hDC, Top, Left, Width, Height, Rop)); +} + + + + +/* + +BOOL STDCALL W32kExtFloodFill(HDC hDC, INT XStart, INT YStart, COLORREF Color, UINT FillType) +BOOL STDCALL W32kFloodFill(HDC hDC, INT XStart, INT YStart, COLORREF Fill) +UINT STDCALL W32kGetDIBColorTable(HDC hDC, UINT StartIndex, UINT Entries, RGBQUAD *Colors) +COLORREF STDCALL W32kGetPixel(HDC hDC, + INT XPos, + INT YPos) +BOOL STDCALL W32kSetBitmapDimensionEx(HBITMAP hBitmap, + INT Width, + INT Height, + LPSIZE Size) +UINT STDCALL W32kSetDIBColorTable(HDC hDC, + UINT StartIndex, + UINT Entries, + CONST RGBQUAD *Colors) +BOOL STDCALL W32kSetPixelV(HDC hDC, + INT X, + INT Y, + COLORREF Color) +BOOL STDCALL W32kStretchBlt(HDC hDCDest, + INT XOriginDest, + INT YOriginDest, + INT WidthDest, + INT HeightDest, + HDC hDCSrc, + INT XOriginSrc, + INT YOriginSrc, + INT WidthSrc, + INT HeightSrc, + DWORD ROP) + +INT BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp) +HBITMAP BITMAPOBJ_CopyBitmap(HBITMAP hBitmap) +int DIB_GetDIBWidthBytes(int width, int depth) +int DIB_GetDIBImageBytes (int width, int height, int depth) +int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse) + +*/ diff --git a/lib/gdi32/objects/brush.c b/lib/gdi32/objects/brush.c new file mode 100644 index 0000000..29f663d --- /dev/null +++ b/lib/gdi32/objects/brush.c @@ -0,0 +1,18 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + + +HBRUSH +STDCALL +CreateSolidBrush( + COLORREF a0 + ) +{ + return W32kCreateSolidBrush(a0); +} diff --git a/lib/gdi32/objects/dc.c b/lib/gdi32/objects/dc.c new file mode 100644 index 0000000..13195c5 --- /dev/null +++ b/lib/gdi32/objects/dc.c @@ -0,0 +1,177 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +HGDIOBJ STDCALL +GetStockObject(int Index) +{ + return(W32kGetStockObject(Index)); +} + + +int STDCALL +GetClipBox(HDC hDc, LPRECT Rect) +{ + return(W32kGetClipBox(hDc, Rect)); +} + + +HDC +STDCALL +CreateDCA ( + LPCSTR lpszDriver, + LPCSTR lpszDevice, + LPCSTR lpszOutput, + CONST DEVMODEA * lpInitData + ) +{ + ANSI_STRING DriverA, DeviceA, OutputA; + UNICODE_STRING DriverU, DeviceU, OutputU; + HDC hDC; + DEVMODEW *lpInitDataW; + + /* + * If needed, convert to Unicode + * any string parameter. + */ + + if (NULL != lpszDriver) + { + RtlInitAnsiString(&DriverA, (LPSTR)lpszDriver); + RtlAnsiStringToUnicodeString(&DriverU, &DriverA, TRUE); + } else + DriverU.Buffer = NULL; + if (NULL != lpszDevice) + { + RtlInitAnsiString(&DeviceA, (LPSTR)lpszDevice); + RtlAnsiStringToUnicodeString(&DeviceU, &DeviceA, TRUE); + } else + DeviceU.Buffer = NULL; + if (NULL != lpszOutput) + { + RtlInitAnsiString(&OutputA, (LPSTR)lpszOutput); + RtlAnsiStringToUnicodeString(&OutputU, &OutputA, TRUE); + } else + OutputU.Buffer = NULL; + + if (NULL != lpInitData) + { +// lpInitDataW = HeapAllocMem( + } else + lpInitDataW = NULL; + + /* + * Call the Unicode version + * of CreateDC. + */ + + hDC = CreateDCW ( + DriverU.Buffer, + DeviceU.Buffer, + OutputU.Buffer, + NULL); +// lpInitDataW); + /* + * Free Unicode parameters. + */ + RtlFreeUnicodeString(&DriverU); + RtlFreeUnicodeString(&DeviceU); + RtlFreeUnicodeString(&OutputU); + + /* + * Return the possible DC handle. + */ + + return hDC; +} + +HDC +STDCALL +CreateDCW ( + LPCWSTR lpwszDriver, + LPCWSTR lpwszDevice, + LPCWSTR lpwszOutput, + CONST DEVMODEW * lpInitData + ) +{ + return W32kCreateDC ( + lpwszDriver, + lpwszDevice, + lpwszOutput, + (PDEVMODEW)lpInitData + ); +} + +BOOL STDCALL DeleteDC( HDC hDC ) +{ + return W32kDeleteDC( hDC ); +} + + +HDC +STDCALL +CreateCompatibleDC( + HDC hDC + ) +{ + return W32kCreateCompatableDC(hDC); +} + +HGDIOBJ +STDCALL +SelectObject( + HDC hDC, + HGDIOBJ hGDIObj + ) +{ + return W32kSelectObject(hDC, hGDIObj); +} + +int +STDCALL +SetMapMode( + HDC a0, + int a1 + ) +{ + return W32kSetMapMode( a0, a1 ); +} + +BOOL +STDCALL +SetViewportOrgEx( + HDC a0, + int a1, + int a2, + LPPOINT a3 + ) +{ + return W32kSetViewportOrgEx( a0, a1, a2, a3 ); +} + +BOOL +STDCALL +SetWindowOrgEx( + HDC a0, + int a1, + int a2, + LPPOINT a3 + ) +{ + return W32kSetWindowOrgEx( a0, a1, a2, a3 ); +} + + +BOOL +STDCALL +DeleteObject( + HGDIOBJ a0 + ) +{ + return W32kDeleteObject(a0); +} diff --git a/lib/gdi32/objects/line.c b/lib/gdi32/objects/line.c new file mode 100644 index 0000000..abb9ec6 --- /dev/null +++ b/lib/gdi32/objects/line.c @@ -0,0 +1,34 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +BOOL +STDCALL +LineTo(HDC hDC, int XEnd, int YEnd) +{ + return W32kLineTo(hDC, XEnd, YEnd); +} + +BOOL +STDCALL +MoveToEx(HDC hDC, int X, int Y, LPPOINT Point) +{ + return W32kMoveToEx(hDC, X, Y, Point); +} + +BOOL +STDCALL +Rectangle(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect) +{ + // MOVE to fillshap.c + return W32kRectangle(hDC, LeftRect, TopRect, RightRect, BottomRect); +} diff --git a/lib/gdi32/objects/pen.c b/lib/gdi32/objects/pen.c new file mode 100644 index 0000000..51286df --- /dev/null +++ b/lib/gdi32/objects/pen.c @@ -0,0 +1,29 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +HPEN +STDCALL +CreatePen(INT PenStyle, INT Width, COLORREF Color) +{ + return W32kCreatePen(PenStyle, Width, Color); +} + +HPEN +STDCALL +CreatePenIndirect(CONST LOGPEN *lgpn) +{ + return W32kCreatePenIndirect((CONST PLOGPEN)lgpn); +} +/* +VOID STDCALL +DumpGdiObjects( INT process ) +{ + W32kDumpGdiObjects( process ); +} +*/ diff --git a/lib/gdi32/objects/region.c b/lib/gdi32/objects/region.c new file mode 100644 index 0000000..69e288c --- /dev/null +++ b/lib/gdi32/objects/region.c @@ -0,0 +1,156 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + + + +HRGN +STDCALL +CreatePolyPolygonRgn( + CONST POINT *a0, + CONST INT *a1, + int a2, + int a3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HBRUSH +STDCALL +CreatePatternBrush( + HBITMAP a0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +HRGN +STDCALL +CreateRectRgn( + int a0, + int a1, + int a2, + int a3 + ) +{ + return W32kCreateRectRgn(a0,a1,a2,a3); +} + + + +HRGN +STDCALL +CreateRectRgnIndirect( + CONST RECT *a0 + ) +{ + return W32kCreateRectRgnIndirect(a0); +} + + + +HRGN +STDCALL +CreateRoundRectRgn( + int a0, + int a1, + int a2, + int a3, + int a4, + int a5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +BOOL +STDCALL +EqualRgn( + HRGN a0, + HRGN a1 + ) +{ + return W32kEqualRgn(a0,a1); +} + +int +STDCALL +OffsetRgn( + HRGN a0, + int a1, + int a2 + ) +{ + return W32kOffsetRgn(a0,a1,a2); +} + +int +STDCALL +GetRgnBox( + HRGN a0, + LPRECT a1 + ) +{ + return W32kGetRgnBox(a0,a1); +} + +BOOL +STDCALL +SetRectRgn( + HRGN a0, + int a1, + int a2, + int a3, + int a4 + ) +{ + return W32kSetRectRgn(a0,a1,a2,a3,a4); +} + +int +STDCALL +CombineRgn( + HRGN a0, + HRGN a1, + HRGN a2, + int a3 + ) +{ + return W32kCombineRgn(a0,a1,a2,a3); +} + +DWORD +STDCALL +GetRegionData( + HRGN a0, + DWORD a1, + LPRGNDATA a2 + ) +{ + return W32kGetRegionData(a0,a1,a2); +} + +BOOL +STDCALL +PaintRgn( + HDC a0, + HRGN a1 + ) +{ + return W32kPaintRgn( a0, a1 ); +} + + diff --git a/lib/gdi32/objects/text.c b/lib/gdi32/objects/text.c new file mode 100644 index 0000000..4ab5acd --- /dev/null +++ b/lib/gdi32/objects/text.c @@ -0,0 +1,240 @@ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +BOOL +STDCALL +TextOutA( + HDC hDC, + int XStart, + int YStart, + LPCSTR String, + int Count) +{ + ANSI_STRING StringA; + UNICODE_STRING StringU; + BOOL ret; + + if (NULL != String) + { + RtlInitAnsiString(&StringA, (LPSTR)String); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + } else + StringU.Buffer = NULL; + + ret = TextOutW(hDC, XStart, YStart, StringU.Buffer, Count); + RtlFreeUnicodeString(&StringU); + return ret; +} + +BOOL +STDCALL +TextOutW( + HDC hDC, + int XStart, + int YStart, + LPCWSTR String, + int Count) +{ + return W32kTextOut(hDC, XStart, YStart, String, Count); +} + +COLORREF STDCALL +SetTextColor(HDC hDC, COLORREF color) +{ + return(W32kSetTextColor(hDC, color)); +} + +BOOL +STDCALL +GetTextMetricsA( + HDC hdc, + LPTEXTMETRIC tm + ) +{ + return W32kGetTextMetrics(hdc, tm); +} + +BOOL +STDCALL +GetTextMetricsW( + HDC hdc, + LPTEXTMETRIC tm + ) +{ + return W32kGetTextMetrics(hdc, tm); +} + +BOOL +APIENTRY +GetTextExtentPointA( + HDC hDC, + LPCSTR String, + int Count, + LPSIZE Size + ) +{ + ANSI_STRING StringA; + UNICODE_STRING StringU; + BOOL ret; + + RtlInitAnsiString(&StringA, (LPSTR)String); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + + ret = GetTextExtentPointW(hDC, StringU.Buffer, Count, Size); + + RtlFreeUnicodeString(&StringU); + + return ret; +} + +BOOL +APIENTRY +GetTextExtentPointW( + HDC hDC, + LPCWSTR String, + int Count, + LPSIZE Size + ) +{ + return W32kGetTextExtentPoint(hDC, String, Count, Size); +} + +BOOL +STDCALL +ExtTextOutA( + HDC hDC, + int X, + int Y, + UINT Options, + CONST RECT *Rect, + LPCSTR String, + UINT Count, + CONST INT *Spacings + ) +{ + ANSI_STRING StringA; + UNICODE_STRING StringU; + BOOL ret; + + RtlInitAnsiString(&StringA, (LPSTR)String); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + + ret = ExtTextOutW(hDC, X, Y, Options, Rect, StringU.Buffer, Count, Spacings); + + RtlFreeUnicodeString(&StringU); + + return ret; +} + +BOOL +STDCALL +ExtTextOutW( + HDC hDC, + int X, + int Y, + UINT Options, + CONST RECT *Rect, + LPCWSTR String, + UINT Count, + CONST INT *Spacings + ) +{ + return W32kTextOut(hDC, X, Y, String, Count); +} + +HFONT +STDCALL +CreateFontIndirectA( + CONST LOGFONT *lf + ) +{ + ANSI_STRING StringA; + UNICODE_STRING StringU; + HFONT ret; + LOGFONT tlf; + + RtlInitAnsiString(&StringA, (LPSTR)lf->lfFaceName); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + memcpy(&tlf, lf, sizeof(LOGFONT)); + memcpy(&tlf.lfFaceName, &StringU.Buffer, StringU.Length); + + ret = CreateFontIndirectW((CONST LOGFONT *)&lf); + + RtlFreeUnicodeString(&StringU); + + return ret; +} + +HFONT +STDCALL +CreateFontIndirectW( + CONST LOGFONT *lf + ) +{ + return W32kCreateFontIndirect((CONST LPLOGFONT)lf); +} + +HFONT +STDCALL +CreateFontA( + int Height, + int Width, + int Escapement, + int Orientation, + int Weight, + DWORD Italic, + DWORD Underline, + DWORD StrikeOut, + DWORD CharSet, + DWORD OutputPrecision, + DWORD ClipPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCSTR Face + ) +{ + ANSI_STRING StringA; + UNICODE_STRING StringU; + HFONT ret; + LOGFONT tlf; + + RtlInitAnsiString(&StringA, (LPSTR)Face); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + + ret = CreateFontW(Height, Width, Escapement, Orientation, Weight, Italic, Underline, StrikeOut, + CharSet, OutputPrecision, ClipPrecision, Quality, PitchAndFamily, StringU.Buffer); + + RtlFreeUnicodeString(&StringU); + + return ret; +} + +HFONT +STDCALL +CreateFontW( + int Height, + int Width, + int Escapement, + int Orientation, + int Weight, + DWORD Italic, + DWORD Underline, + DWORD StrikeOut, + DWORD CharSet, + DWORD OutputPrecision, + DWORD ClipPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCWSTR Face + ) +{ + return W32kCreateFont(Height, Width, Escapement, Orientation, Weight, Italic, Underline, StrikeOut, + CharSet, OutputPrecision, ClipPrecision, Quality, PitchAndFamily, Face); +} + diff --git a/lib/iphlpapi/.cvsignore b/lib/iphlpapi/.cvsignore new file mode 100644 index 0000000..0e6f4b1 --- /dev/null +++ b/lib/iphlpapi/.cvsignore @@ -0,0 +1,23 @@ +iphlpapi.a +iphlpapi.dll +iphlpapi.nostrip.dll +iphlpapi.coff +base.tmp +junk.tmp +temp.exp +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/iphlpapi/debug.h b/lib/iphlpapi/debug.h new file mode 100644 index 0000000..13a623f --- /dev/null +++ b/lib/iphlpapi/debug.h @@ -0,0 +1,65 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 Helper DLL for TCP/IP + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define WSH_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { WSH_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define WSH_DbgPrint(_t_, _x_) + +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + WSH_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \ + please try again later.\n", __FILE__, __LINE__, __FUNCTION__)); + +#define CHECKPOINT \ + WSH_DbgPrint(MIN_TRACE, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/iphlpapi/iphlpapi.c b/lib/iphlpapi/iphlpapi.c new file mode 100644 index 0000000..7ddb040 --- /dev/null +++ b/lib/iphlpapi/iphlpapi.c @@ -0,0 +1,314 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 IP Helper API DLL + * FILE: iphlpapi.c + * PURPOSE: DLL entry + * PROGRAMMERS: Robert Dickenson (robd@reactos.org) + * REVISIONS: + * RDD August 18, 2002 Created + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "debug.h" +//#include "trace.h" + +#ifdef __GNUC__ +#define EXPORT STDCALL +#else +#define EXPORT CALLBACK +#endif + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + +/* To make the linker happy */ +//VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +BOOL +EXPORT +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + //WSH_DbgPrint(MIN_TRACE, ("DllMain of iphlpapi.dll\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications + so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + +DWORD +WINAPI +AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance) +{ + UNIMPLEMENTED + return 0L; +} + + +DWORD +WINAPI +SetIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + UNIMPLEMENTED + return 0L; +} + +DWORD +WINAPI +CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + UNIMPLEMENTED + return 0L; +} + + +#ifdef __GNUC__ + +DWORD +WINAPI +GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex) +{ + return 0; +} + +DWORD +WINAPI +GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) +{ + return 0; +} + +#endif + + +//////////////////////////////////////////////////////////////////////////////// + +DWORD +WINAPI +GetNumberOfInterfaces(OUT PDWORD pdwNumIf) +{ + DWORD result = NO_ERROR; + HKEY hKey; + LONG errCode; + int i = 0; + + if (pdwNumIf == NULL) return ERROR_INVALID_PARAMETER; + *pdwNumIf = 0; + errCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", 0, KEY_READ, &hKey); + if (errCode == ERROR_SUCCESS) { + DWORD dwSize; + errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, NULL, &dwSize); + if (errCode == ERROR_SUCCESS) { + wchar_t* pData = (wchar_t*)malloc(dwSize * sizeof(wchar_t)); + errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, (LPBYTE)pData, &dwSize); + if (errCode == ERROR_SUCCESS) { + wchar_t* pStr = pData; + for (i = 0; *pStr != L'\0'; i++) { + pStr = pStr + wcslen(pStr) + 1; // next string + } + } + free(pData); + } + RegCloseKey(hKey); + *pdwNumIf = i; + } else { + result = errCode; + } + return result; +} + + +DWORD +WINAPI +GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG pOutBufLen) +{ + DWORD result = ERROR_SUCCESS; + DWORD dwSize; + DWORD dwOutBufLen; + DWORD dwNumIf; + HKEY hKey; + LONG errCode; + int i = 0; + + if ((errCode = GetNumberOfInterfaces(&dwNumIf)) != NO_ERROR) { + _tprintf(_T("GetInterfaceInfo() failed with code 0x%08X - Use FormatMessage to obtain the message string for the returned error\n"), errCode); + return errCode; + } + if (dwNumIf == 0) return ERROR_NO_DATA; // No adapter information exists for the local computer + if (pOutBufLen == NULL) return ERROR_INVALID_PARAMETER; + dwOutBufLen = sizeof(IP_INTERFACE_INFO) + dwNumIf * sizeof(IP_ADAPTER_INDEX_MAP); + if (*pOutBufLen < dwOutBufLen || pIfTable == NULL) { + *pOutBufLen = dwOutBufLen; + return ERROR_INSUFFICIENT_BUFFER; + } + memset(pIfTable, 0, dwOutBufLen); + pIfTable->NumAdapters = dwNumIf - 1; + errCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", 0, KEY_READ, &hKey); + if (errCode == ERROR_SUCCESS) { + errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, NULL, &dwSize); + if (errCode == ERROR_SUCCESS) { + wchar_t* pData = (wchar_t*)malloc(dwSize * sizeof(wchar_t)); + errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, (LPBYTE)pData, &dwSize); + if (errCode == ERROR_SUCCESS) { + wchar_t* pStr = pData; + for (i = 0; i < pIfTable->NumAdapters, *pStr != L'\0'; pStr += wcslen(pStr) + 1) { + if (wcsstr(pStr, L"\\Device\\NdisWanIp") == 0) { + wcsncpy(pIfTable->Adapter[i].Name, pStr, MAX_ADAPTER_NAME); + pIfTable->Adapter[i].Index = i++; + } + } + + } + free(pData); + } + RegCloseKey(hKey); + } else { + result = errCode; + } + return result; +} + +DWORD +WINAPI +GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) +{ + DWORD result = ERROR_SUCCESS; + DWORD dwSize; + HKEY hKey; + LONG errCode; + + if (pFixedInfo == NULL || pOutBufLen == NULL) return ERROR_INVALID_PARAMETER; + + if (*pOutBufLen < sizeof(FIXED_INFO)) { + *pOutBufLen = sizeof(FIXED_INFO); + return ERROR_BUFFER_OVERFLOW; + } + memset(pFixedInfo, 0, sizeof(FIXED_INFO)); + + errCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"), 0, KEY_READ, &hKey); + if (errCode == ERROR_SUCCESS) { + dwSize = sizeof(pFixedInfo->HostName); + errCode = RegQueryValueExA(hKey, "Hostname", NULL, NULL, (LPBYTE)&pFixedInfo->HostName, &dwSize); + dwSize = sizeof(pFixedInfo->DomainName); + errCode = RegQueryValueExA(hKey, "Domain", NULL, NULL, (LPBYTE)&pFixedInfo->DomainName, &dwSize); + if (errCode != ERROR_SUCCESS) { + dwSize = sizeof(pFixedInfo->DomainName); + errCode = RegQueryValueExA(hKey, "DhcpDomain", NULL, NULL, (LPBYTE)&pFixedInfo->DomainName, &dwSize); + } + dwSize = sizeof(pFixedInfo->EnableRouting); + errCode = RegQueryValueEx(hKey, _T("IPEnableRouter"), NULL, NULL, (LPBYTE)&pFixedInfo->EnableRouting, &dwSize); + RegCloseKey(hKey); + } else { + result = ERROR_NO_DATA; // No adapter information exists for the local computer + } + + errCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters"), 0, KEY_READ, &hKey); + if (errCode == ERROR_SUCCESS) { + dwSize = sizeof(pFixedInfo->ScopeId); + errCode = RegQueryValueExA(hKey, "ScopeId", NULL, NULL, (LPBYTE)&pFixedInfo->ScopeId, &dwSize); + if (errCode != ERROR_SUCCESS) { + dwSize = sizeof(pFixedInfo->ScopeId); + errCode = RegQueryValueExA(hKey, "DhcpScopeId", NULL, NULL, (LPBYTE)&pFixedInfo->ScopeId, &dwSize); + } + dwSize = sizeof(pFixedInfo->NodeType); + errCode = RegQueryValueEx(hKey, _T("NodeType"), NULL, NULL, (LPBYTE)&pFixedInfo->NodeType, &dwSize); + if (errCode != ERROR_SUCCESS) { + dwSize = sizeof(pFixedInfo->NodeType); + errCode = RegQueryValueExA(hKey, "DhcpNodeType", NULL, NULL, (LPBYTE)&pFixedInfo->NodeType, &dwSize); + } + dwSize = sizeof(pFixedInfo->EnableProxy); + errCode = RegQueryValueEx(hKey, _T("EnableProxy"), NULL, NULL, (LPBYTE)&pFixedInfo->EnableProxy, &dwSize); + dwSize = sizeof(pFixedInfo->EnableDns); + errCode = RegQueryValueEx(hKey, _T("EnableDNS"), NULL, NULL, (LPBYTE)&pFixedInfo->EnableDns, &dwSize); + RegCloseKey(hKey); + } else { + result = ERROR_NO_DATA; // No adapter information exists for the local computer + } + + return result; +} + +DWORD +WINAPI +GetTcpStatistics(PMIB_TCPSTATS pStats) +{ + DWORD result = NO_ERROR; + + result = ERROR_NO_DATA; + + return result; +} + +DWORD +WINAPI +GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder) +{ + DWORD result = NO_ERROR; + + result = ERROR_NO_DATA; + + return result; +} + +DWORD +WINAPI +GetUdpStatistics(PMIB_UDPSTATS pStats) +{ + DWORD result = NO_ERROR; + + result = ERROR_NO_DATA; + + return result; +} + +DWORD +WINAPI +GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder) +{ + DWORD result = NO_ERROR; + + result = ERROR_NO_DATA; + + return result; +} + +DWORD +WINAPI +FlushIpNetTable(DWORD dwIfIndex) +{ + DWORD result = NO_ERROR; + + return result; +} + +/* EOF */ + diff --git a/lib/iphlpapi/iphlpapi.def b/lib/iphlpapi/iphlpapi.def new file mode 100644 index 0000000..e2b93e6 --- /dev/null +++ b/lib/iphlpapi/iphlpapi.def @@ -0,0 +1,17 @@ +; IPHLPAPI.DLL - ReactOS Sockets 2 IP Helper API DLL + +LIBRARY iphlpapi.dll + +EXPORTS +AddIPAddress @1 +SetIpNetEntry @107 +CreateIpForwardEntry @9 +GetNetworkParams @43 +GetNumberOfInterfaces @44 +GetInterfaceInfo @34 +GetTcpStatistics @47 +GetTcpTable @49 +GetUdpStatistics @51 +GetUdpTable @53 +FlushIpNetTable @17 +; EOF diff --git a/lib/iphlpapi/iphlpapi.edf b/lib/iphlpapi/iphlpapi.edf new file mode 100644 index 0000000..96723de --- /dev/null +++ b/lib/iphlpapi/iphlpapi.edf @@ -0,0 +1,17 @@ +; IPHLPAPI.DLL - ReactOS Sockets 2 IP Helper API DLL + +LIBRARY iphlpapi.dll + +EXPORTS +AddIPAddress=AddIPAddress@20 @1 +SetIpNetEntry=SetIpNetEntry@4 @107 +CreateIpForwardEntry=CreateIpForwardEntry@4 @9 +GetNetworkParams=GetNetworkParams@8 @43 +GetNumberOfInterfaces=GetNumberOfInterfaces@4 @44 +GetInterfaceInfo=GetInterfaceInfo@8 @34 +GetTcpStatistics=GetTcpStatistics@4 @47 +GetTcpTable=GetTcpTable@12 @49 +GetUdpStatistics=GetUdpStatistics@4 @51 +GetUdpTable=GetUdpTable@12 @53 +FlushIpNetTable=FlushIpNetTable@4 @17 +; EOF diff --git a/lib/iphlpapi/iphlpapi.rc b/lib/iphlpapi/iphlpapi.rc new file mode 100644 index 0000000..37c1c0b --- /dev/null +++ b/lib/iphlpapi/iphlpapi.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Sockets 2 IP Helper API\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "iphlpapi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "iphlpapi.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/iphlpapi/makefile b/lib/iphlpapi/makefile new file mode 100644 index 0000000..4bf95de --- /dev/null +++ b/lib/iphlpapi/makefile @@ -0,0 +1,19 @@ +# $Id: makefile + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = iphlpapi + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = -DUNICODE + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/iprtprio/.cvsignore b/lib/iprtprio/.cvsignore new file mode 100644 index 0000000..90b3bd7 --- /dev/null +++ b/lib/iprtprio/.cvsignore @@ -0,0 +1,17 @@ +iprtprio.a +iprtprio.dll +iprtprio.nostrip.dll +iprtprio.coff +base.tmp +junk.tmp +temp.exp +*.o +*.d +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/iprtprio/iprtprio.c b/lib/iprtprio/iprtprio.c new file mode 100644 index 0000000..69168b2 --- /dev/null +++ b/lib/iprtprio/iprtprio.c @@ -0,0 +1,119 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS IP Route Priority API DLL + * FILE: iprtprio.c + * PURPOSE: DLL entry + * PROGRAMMERS: Robert Dickenson (robd@reactos.org) + * REVISIONS: + * RDD August 27, 2002 Created + */ + +#include +#include +#include +#include + +#include +#include +//#include +//#include +//#include "iprtprio.h" +#include "debug.h" + +#ifdef __GNUC__ +#define EXPORT STDCALL +#else +#define EXPORT CALLBACK +#endif + +#ifdef DBG +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MAX_TRACE; +#endif /* DBG */ + +typedef struct tag_somestruct { + int size; + TCHAR szData[2345]; +} somestruct; + +BOOL Initialised = FALSE; +CRITICAL_SECTION CriticalSection; + +/* To make the linker happy */ +//VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + +BOOL +EXPORT +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + //WSH_DbgPrint(MIN_TRACE, ("DllMain of iprtprio.dll\n")); + if (!Initialised) { + InitializeCriticalSection(&CriticalSection); + } + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +DWORD +WINAPI +ComputeRouteMetric(IPAddr unknown1, IPMask unknown2, DWORD unknown3, DWORD unknown4) +{ + BYTE* buf = NULL; + + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(somestruct)); + if (buf != NULL) { + HeapFree(GetProcessHeap(), 0, buf); + } + + EnterCriticalSection(&CriticalSection); + LeaveCriticalSection(&CriticalSection); + + UNIMPLEMENTED + return 0L; +} + + +DWORD +WINAPI +GetPriorityInfo(DWORD unknown) +{ + DWORD result = NO_ERROR; + + EnterCriticalSection(&CriticalSection); + LeaveCriticalSection(&CriticalSection); + + UNIMPLEMENTED + return result; +} + +DWORD +WINAPI +SetPriorityInfo(DWORD unknown) +{ + DWORD result = NO_ERROR; + + EnterCriticalSection(&CriticalSection); + LeaveCriticalSection(&CriticalSection); + + UNIMPLEMENTED + return result; +} + +/* EOF */ diff --git a/lib/iprtprio/iprtprio.def b/lib/iprtprio/iprtprio.def new file mode 100644 index 0000000..bd19912 --- /dev/null +++ b/lib/iprtprio/iprtprio.def @@ -0,0 +1,9 @@ +; IPRTPRIO.DLL - ReactOS IP Route Priority API DLL + +LIBRARY iprtprio.dll + +EXPORTS +ComputeRouteMetric @1 +GetPriorityInfo @2 +SetPriorityInfo @3 +; EOF diff --git a/lib/iprtprio/iprtprio.edf b/lib/iprtprio/iprtprio.edf new file mode 100644 index 0000000..faf3974 --- /dev/null +++ b/lib/iprtprio/iprtprio.edf @@ -0,0 +1,9 @@ +; IPRTPRIO.DLL - ReactOS IP Route Priority API DLL + +LIBRARY iprtprio.dll + +EXPORTS +ComputeRouteMetric=ComputeRouteMetric@16 @1 +GetPriorityInfo=GetPriorityInfo@4 @2 +SetPriorityInfo=SetPriorityInfo@4 @3 +; EOF diff --git a/lib/iprtprio/iprtprio.rc b/lib/iprtprio/iprtprio.rc new file mode 100644 index 0000000..fc511df --- /dev/null +++ b/lib/iprtprio/iprtprio.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS IP Route Priority API DLL\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "iprtprio\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "iprtprio.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/iprtprio/makefile b/lib/iprtprio/makefile new file mode 100644 index 0000000..14403d3 --- /dev/null +++ b/lib/iprtprio/makefile @@ -0,0 +1,19 @@ +# $Id: makefile + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = iprtprio + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = -DUNICODE + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/kernel32/.cvsignore b/lib/kernel32/.cvsignore new file mode 100644 index 0000000..031332b --- /dev/null +++ b/lib/kernel32/.cvsignore @@ -0,0 +1,9 @@ +kernel32.a +kernel32.dll +kernel32.nostrip.dll +kernel32.lib +kernel32.coff +base.tmp +junk.tmp +temp.exp + diff --git a/lib/kernel32/except/.cvsignore b/lib/kernel32/except/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/except/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/except/except.c b/lib/kernel32/except/except.c new file mode 100644 index 0000000..2b05b57 --- /dev/null +++ b/lib/kernel32/except/except.c @@ -0,0 +1,153 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/except.c + * PURPOSE: Exception functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ] + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include + +#include + +typedef LONG (STDCALL *LPTOP_LEVEL_EXCEPTION_FILTER)( + struct _EXCEPTION_POINTERS *ExceptionInfo + ); + +UINT GlobalErrMode; +LPTOP_LEVEL_EXCEPTION_FILTER GlobalTopLevelExceptionFilter; + +UINT GetErrorMode(void); + + + +UINT GetErrorMode(void) +{ + return GlobalErrMode; +} + +UINT +STDCALL +SetErrorMode( UINT uMode ) +{ + UINT OldErrMode = GetErrorMode(); + GlobalErrMode = uMode; + return OldErrMode; +} + +LPTOP_LEVEL_EXCEPTION_FILTER +STDCALL +SetUnhandledExceptionFilter( + LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter + ) +{ + LPTOP_LEVEL_EXCEPTION_FILTER OldTopLevelExceptionFilter = + GlobalTopLevelExceptionFilter; + lpTopLevelExceptionFilter = GlobalTopLevelExceptionFilter; + return OldTopLevelExceptionFilter; +} + + +LONG +STDCALL +UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo) +{ + DWORD dbgRet; + HANDLE DebugPort; + NTSTATUS errCode; + + if(ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) { + // might check read only resource + // Is there a debugger running ? + errCode = NtQueryInformationProcess(NtCurrentProcess(),ProcessDebugPort,&DebugPort,sizeof(HANDLE),NULL); + if ( !NT_SUCCESS(errCode) ) { + SetLastErrorByStatus(errCode); + return EXCEPTION_EXECUTE_HANDLER; + } + if ( DebugPort ) { + //return EXCEPTION_CONTINUE_SEARCH; + } + if(GlobalTopLevelExceptionFilter != NULL) { + dbgRet = GlobalTopLevelExceptionFilter(ExceptionInfo); + if(dbgRet == EXCEPTION_EXECUTE_HANDLER) + return EXCEPTION_EXECUTE_HANDLER; + else if(dbgRet == EXCEPTION_CONTINUE_EXECUTION) + return EXCEPTION_CONTINUE_EXECUTION; + } + + } + + //if ( GetErrorMode() & SEM_NOGPFAULTERRORBOX == SEM_NOGPFAULTERRORBOX ) { + // produce a stack trace or pop a message + //sprintf( message, "Unhandled exception 0x%08lx at address 0x%08lx.", + // ExceptionInfo->ExceptionRecord->ExceptionCode, + // (DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress ); + //MessageBoxA( 0, message, "Error", MB_OK | MB_ICONHAND ); + + //} + // Returning EXCEPTION_EXECUTE_HANDLER means that the code in + // the __execept block will be executed. Normally this will end up in a + // Terminate process. + + return EXCEPTION_EXECUTE_HANDLER; + +} + +VOID +STDCALL +RaiseException ( + DWORD dwExceptionCode, + DWORD dwExceptionFlags, + DWORD nNumberOfArguments, + CONST DWORD * lpArguments OPTIONAL + ) +{ + EXCEPTION_RECORD ExceptionRecord; + + /* Do NOT normalize dwExceptionCode: it will be done in + * NTDLL.RtlRaiseException(). + */ + ExceptionRecord.ExceptionCode = dwExceptionCode; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.ExceptionAddress = (PVOID) RaiseException; + /* + * Normalize dwExceptionFlags. + */ + ExceptionRecord.ExceptionFlags = (dwExceptionFlags & EXCEPTION_NONCONTINUABLE); + /* + * Normalize nNumberOfArguments. + */ + if (EXCEPTION_MAXIMUM_PARAMETERS < nNumberOfArguments) + { + nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS; + } + /* + * If the exception has no argument, + * or it is a non-continuable exception, + * ignore nNumberOfArguments and lpArguments. + */ + if ((NULL == lpArguments) || ExceptionRecord.ExceptionFlags) + { + ExceptionRecord.NumberParameters = 0; + } + else + { + ExceptionRecord.NumberParameters = nNumberOfArguments; + for ( nNumberOfArguments = 0; + (nNumberOfArguments < ExceptionRecord.NumberParameters); + nNumberOfArguments ++ + ) + { + ExceptionRecord.ExceptionInformation [nNumberOfArguments] + = *lpArguments ++; + } + } + RtlRaiseException (& ExceptionRecord); +} + +/* EOF */ diff --git a/lib/kernel32/file/.cvsignore b/lib/kernel32/file/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/file/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/file/backup.c b/lib/kernel32/file/backup.c new file mode 100644 index 0000000..aa050fc --- /dev/null +++ b/lib/kernel32/file/backup.c @@ -0,0 +1,74 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/backup.c + * PURPOSE: Backup functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +BackupRead ( + HANDLE hFile, + LPBYTE lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + WINBOOL bAbort, + WINBOOL bProcessSecurity, + LPVOID * lpContext + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +BackupSeek ( + HANDLE hFile, + DWORD dwLowBytesToSeek, + DWORD dwHighBytesToSeek, + LPDWORD lpdwLowByteSeeked, + LPDWORD lpdwHighByteSeeked, + LPVOID * lpContext + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +BackupWrite ( + HANDLE hFile, + LPBYTE lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + WINBOOL bAbort, + WINBOOL bProcessSecurity, + LPVOID * lpContext + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* EOF */ diff --git a/lib/kernel32/file/cnotify.c b/lib/kernel32/file/cnotify.c new file mode 100644 index 0000000..15338ca --- /dev/null +++ b/lib/kernel32/file/cnotify.c @@ -0,0 +1,82 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include + + +WINBOOL STDCALL +FindCloseChangeNotification (HANDLE hChangeHandle) +{ + return FALSE; +} + + +HANDLE +STDCALL +FindFirstChangeNotificationA ( + LPCSTR lpPathName, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter + ) +{ +#if 0 + UNICODE_STRING PathNameU; + ANSI_STRING PathName; + HANDLE Result; + + RtlInitAnsiString (&PathName, + (LPSTR)lpPathName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&PathNameU, + &PathName, + TRUE); + else + RtlOemStringToUnicodeString (&PathNameU, + &PathName, + TRUE); + + Result = FindFirstChangeNotificationW (PathNameU.Buffer, + bWatchSubtree, + dwNotifyFilter); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + RootPathNameU.Buffer); + + return Result; +#endif +} + + +HANDLE +STDCALL +FindFirstChangeNotificationW ( + LPCWSTR lpPathName, + WINBOOL bWatchSubtree, + DWORD dwNotifyFilter + ) +{ + return NULL; +} + + +WINBOOL +STDCALL +FindNextChangeNotification ( + HANDLE hChangeHandle + ) +{ + return FALSE; +} + +/* EOF */ diff --git a/lib/kernel32/file/copy.c b/lib/kernel32/file/copy.c new file mode 100644 index 0000000..9f3c139 --- /dev/null +++ b/lib/kernel32/file/copy.c @@ -0,0 +1,284 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/copy.c + * PURPOSE: Copying files + * PROGRAMMER: Ariadne (ariadne@xs4all.nl) + * UPDATE HISTORY: + * 01/11/98 Created + * 07/02/99 Moved to seperate file + */ + +/* INCLUDES ****************************************************************/ + +#include +#include + +#define NDEBUG +#include +#include + + +#define LPPROGRESS_ROUTINE void* + + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +CopyFileExW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + WINBOOL *pbCancel, + DWORD dwCopyFlags + ) +{ + NTSTATUS errCode = 0; + HANDLE FileHandleSource, FileHandleDest; + IO_STATUS_BLOCK IoStatusBlock; + FILE_STANDARD_INFORMATION FileStandard; + FILE_BASIC_INFORMATION FileBasic; + FILE_POSITION_INFORMATION FilePosition; + UCHAR *lpBuffer = NULL; + ULONG RegionSize = 0x1000000; + BOOL bCancel = FALSE; + + FileHandleSource = CreateFileW(lpExistingFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING, + NULL); + if (FileHandleSource == NULL) + { + return(FALSE); + } + + errCode = NtQueryInformationFile(FileHandleSource, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + NtClose(FileHandleSource); + SetLastErrorByStatus(errCode); + return FALSE; + } + + errCode = NtQueryInformationFile(FileHandleSource, + &IoStatusBlock,&FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + NtClose(FileHandleSource); + SetLastErrorByStatus(errCode); + return FALSE; + } + + FileHandleDest = CreateFileW(lpNewFileName, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS, + FileBasic.FileAttributes|FILE_FLAG_NO_BUFFERING, + NULL); + if (FileHandleDest == NULL) + { + return(FALSE); + } + + FilePosition.CurrentByteOffset.QuadPart = 0; + + errCode = NtSetInformationFile(FileHandleSource, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (!NT_SUCCESS(errCode)) + { + NtClose(FileHandleSource); + NtClose(FileHandleDest); + SetLastErrorByStatus(errCode); + return FALSE; + } + + errCode = NtSetInformationFile(FileHandleDest, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (!NT_SUCCESS(errCode)) + { + NtClose(FileHandleSource); + NtClose(FileHandleDest); + SetLastErrorByStatus(errCode); + return FALSE; + } + + errCode = NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID *)&lpBuffer, + 2, + &RegionSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + + if (!NT_SUCCESS(errCode)) + { + NtClose(FileHandleSource); + NtClose(FileHandleDest); + SetLastErrorByStatus(errCode); + return FALSE; + } + + do { + errCode = NtReadFile(FileHandleSource, + NULL, + NULL, + NULL, + (PIO_STATUS_BLOCK)&IoStatusBlock, + lpBuffer, + RegionSize, + NULL, + NULL); + if (pbCancel != NULL) + bCancel = *pbCancel; + + if (!NT_SUCCESS(errCode) || bCancel) + { + NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID *)&lpBuffer, &RegionSize,MEM_RELEASE); + NtClose(FileHandleSource); + NtClose(FileHandleDest); + if ( errCode == STATUS_END_OF_FILE ) + break; + else + return FALSE; + } + + errCode = NtWriteFile(FileHandleDest, + NULL, + lpProgressRoutine, + lpData, + (PIO_STATUS_BLOCK)&IoStatusBlock, + lpBuffer, + IoStatusBlock.Information, + NULL, + NULL); + + if (!NT_SUCCESS(errCode)) + { + NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID *)&lpBuffer, + &RegionSize, + MEM_RELEASE); + NtClose(FileHandleSource); + NtClose(FileHandleDest); + return FALSE; + } + + } while ( TRUE ); + return TRUE; +} + + +WINBOOL +STDCALL +CopyFileExA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + LPPROGRESS_ROUTINE lpProgressRoutine, + LPVOID lpData, + WINBOOL *pbCancel, + DWORD dwCopyFlags + ) +{ + UNICODE_STRING ExistingFileNameU; + UNICODE_STRING NewFileNameU; + ANSI_STRING ExistingFileName; + ANSI_STRING NewFileName; + WINBOOL Result; + + RtlInitAnsiString (&ExistingFileName, + (LPSTR)lpExistingFileName); + + RtlInitAnsiString (&NewFileName, + (LPSTR)lpNewFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + { + RtlAnsiStringToUnicodeString (&ExistingFileNameU, + &ExistingFileName, + TRUE); + RtlAnsiStringToUnicodeString (&NewFileNameU, + &NewFileName, + TRUE); + } + else + { + RtlOemStringToUnicodeString (&ExistingFileNameU, + &ExistingFileName, + TRUE); + RtlOemStringToUnicodeString (&NewFileNameU, + &NewFileName, + TRUE); + } + + Result = CopyFileExW (ExistingFileNameU.Buffer, + NewFileNameU.Buffer, + lpProgressRoutine, + lpData, + pbCancel, + dwCopyFlags); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + ExistingFileNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NewFileNameU.Buffer); + + return Result; +} + + +WINBOOL +STDCALL +CopyFileA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + WINBOOL bFailIfExists + ) +{ + return CopyFileExA (lpExistingFileName, + lpNewFileName, + NULL, + NULL, + NULL, + bFailIfExists); +} + + +WINBOOL +STDCALL +CopyFileW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + WINBOOL bFailIfExists + ) +{ + return CopyFileExW (lpExistingFileName, + lpNewFileName, + NULL, + NULL, + NULL, + bFailIfExists); +} + +/* EOF */ diff --git a/lib/kernel32/file/create.c b/lib/kernel32/file/create.c new file mode 100644 index 0000000..1466ae8 --- /dev/null +++ b/lib/kernel32/file/create.c @@ -0,0 +1,263 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/create.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * GetTempFileName is modified from WINE [ Alexandre Juiliard ] + * UPDATE HISTORY: + * Created 01/11/98 + * Removed use of SearchPath (not used by Windows) + * 18/08/2002: CreateFileW mess cleaned up (KJK::Hyperion) + * 24/08/2002: removed superfluous DPRINTs (KJK::Hyperion) + */ + +/* INCLUDES *****************************************************************/ + +#include +/* please FIXME: ddk/ntddk.h should be enough */ +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* FUNCTIONS ****************************************************************/ + +HANDLE STDCALL CreateFileA (LPCSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + HANDLE FileHandle; + + DPRINT("CreateFileA(lpFileName %s)\n",lpFileName); + + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + + FileHandle = CreateFileW (FileNameU.Buffer, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileNameU.Buffer); + + return FileHandle; +} + + +HANDLE STDCALL CreateFileW (LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE FileHandle; + NTSTATUS Status; + ULONG Flags = 0; + + DPRINT("CreateFileW(lpFileName %S)\n",lpFileName); + + if(hTemplateFile != NULL) + { + /* FIXME */ + DPRINT("Template file feature not supported yet\n"); + SetLastError(ERROR_NOT_SUPPORTED); + return INVALID_HANDLE_VALUE; + } + + /* validate & translate the creation disposition */ + switch (dwCreationDisposition) + { + case CREATE_NEW: + dwCreationDisposition = FILE_CREATE; + break; + + case CREATE_ALWAYS: + dwCreationDisposition = FILE_OVERWRITE_IF; + break; + + case OPEN_EXISTING: + dwCreationDisposition = FILE_OPEN; + break; + + case OPEN_ALWAYS: + dwCreationDisposition = FILE_OPEN_IF; + break; + + case TRUNCATE_EXISTING: + dwCreationDisposition = FILE_OVERWRITE; + break; + + default: + SetLastError(ERROR_INVALID_PARAMETER); + return (INVALID_HANDLE_VALUE); + } + + /* validate & translate the flags */ + if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED) + { + DPRINT("Overlapped I/O not supported\n"); + SetLastError(ERROR_NOT_SUPPORTED); + return INVALID_HANDLE_VALUE; + } + else + Flags |= FILE_SYNCHRONOUS_IO_ALERT; + + /* validate & translate the filename */ + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName, + &NtPathU, + NULL, + NULL)) + { + DPRINT("Invalid path\n"); + SetLastError(ERROR_BAD_PATHNAME); + return INVALID_HANDLE_VALUE; + } + + DPRINT("NtPathU \'%S\'\n", NtPathU.Buffer); + + /* translate the flags that need no validation */ + if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) + Flags |= FILE_WRITE_THROUGH; + + if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING) + Flags |= FILE_NO_INTERMEDIATE_BUFFERING; + + if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) + Flags |= FILE_RANDOM_ACCESS; + + if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) + Flags |= FILE_SEQUENTIAL_ONLY; + + if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) + Flags |= FILE_DELETE_ON_CLOSE; + + if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) + { + if(dwDesiredAccess & GENERIC_ALL) + Flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY; + else + { + if(dwDesiredAccess & GENERIC_READ) + Flags |= FILE_OPEN_FOR_BACKUP_INTENT; + + if(dwDesiredAccess & GENERIC_WRITE) + Flags |= FILE_OPEN_FOR_RECOVERY; + } + } + else + Flags |= FILE_NON_DIRECTORY_FILE; + + /* FILE_FLAG_POSIX_SEMANTICS is handled later */ + +#if 0 + /* FIXME: Win32 constants to be defined */ + if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) + Flags |= FILE_OPEN_REPARSE_POINT; + + if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) + Flags |= FILE_OPEN_NO_RECALL; +#endif + + /* translate the desired access */ + if (dwDesiredAccess & GENERIC_ALL) + dwDesiredAccess |= FILE_ALL_ACCESS; + else + { + if (dwDesiredAccess & GENERIC_READ) + dwDesiredAccess |= FILE_GENERIC_READ; + + if (dwDesiredAccess & GENERIC_WRITE) + dwDesiredAccess |= FILE_GENERIC_WRITE; + + if (dwDesiredAccess & GENERIC_EXECUTE) + dwDesiredAccess |= FILE_GENERIC_EXECUTE; + } + + /* build the object attributes */ + InitializeObjectAttributes( + &ObjectAttributes, + &NtPathU, + 0, + NULL, + NULL + ); + + if (lpSecurityAttributes) + { + if(lpSecurityAttributes->bInheritHandle) + ObjectAttributes.Attributes |= OBJ_INHERIT; + + ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; + } + + if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS)) + ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; + + /* perform the call */ + Status = NtCreateFile (&FileHandle, + dwDesiredAccess, + &ObjectAttributes, + &IoStatusBlock, + NULL, + dwFlagsAndAttributes, + dwShareMode, + dwCreationDisposition, + Flags, + NULL, + 0); + + RtlFreeUnicodeString(&NtPathU); + + /* error */ + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return INVALID_HANDLE_VALUE; + } + + switch(IoStatusBlock.Information) + { + case FILE_OPENED: + case FILE_CREATED: + SetLastError(ERROR_ALREADY_EXISTS); + break; + + default: + } + + return FileHandle; +} + +/* EOF */ diff --git a/lib/kernel32/file/curdir.c b/lib/kernel32/file/curdir.c new file mode 100644 index 0000000..85caf3f --- /dev/null +++ b/lib/kernel32/file/curdir.c @@ -0,0 +1,386 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/curdir.c + * PURPOSE: Current directory functions + * UPDATE HISTORY: + * Created 30/09/98 + */ + + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* GLOBAL VARIABLES **********************************************************/ + +UNICODE_STRING SystemDirectory; +UNICODE_STRING WindowsDirectory; + + +/* FUNCTIONS *****************************************************************/ + +DWORD +STDCALL +GetCurrentDirectoryA ( + DWORD nBufferLength, + LPSTR lpBuffer + ) +{ + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + + /* initialize ansi string */ + AnsiString.Length = 0; + AnsiString.MaximumLength = nBufferLength; + AnsiString.Buffer = lpBuffer; + + /* allocate buffer for unicode string */ + UnicodeString.Length = 0; + UnicodeString.MaximumLength = nBufferLength * sizeof(WCHAR); + UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + UnicodeString.MaximumLength); + + /* get current directory */ + UnicodeString.Length = RtlGetCurrentDirectory_U (UnicodeString.MaximumLength, + UnicodeString.Buffer); + DPRINT("UnicodeString.Buffer %S\n", UnicodeString.Buffer); + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&AnsiString, + &UnicodeString, + FALSE); + else + RtlUnicodeStringToOemString (&AnsiString, + &UnicodeString, + FALSE); + DPRINT("AnsiString.Buffer %s\n", AnsiString.Buffer); + + /* free unicode string */ + RtlFreeHeap (RtlGetProcessHeap (), + 0, + UnicodeString.Buffer); + + return AnsiString.Length; +} + + +DWORD +STDCALL +GetCurrentDirectoryW ( + DWORD nBufferLength, + LPWSTR lpBuffer + ) +{ + ULONG Length; + + Length = RtlGetCurrentDirectory_U (nBufferLength, + lpBuffer); + + return (Length / sizeof (WCHAR)); +} + + +WINBOOL +STDCALL +SetCurrentDirectoryA ( + LPCSTR lpPathName + ) +{ + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + NTSTATUS Status; + + RtlInitAnsiString (&AnsiString, + (LPSTR)lpPathName); + + /* convert ansi (or oem) to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&UnicodeString, + &AnsiString, + TRUE); + else + RtlOemStringToUnicodeString (&UnicodeString, + &AnsiString, + TRUE); + + Status = RtlSetCurrentDirectory_U (&UnicodeString); + + RtlFreeUnicodeString (&UnicodeString); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +SetCurrentDirectoryW ( + LPCWSTR lpPathName + ) +{ + UNICODE_STRING UnicodeString; + NTSTATUS Status; + + RtlInitUnicodeString (&UnicodeString, + lpPathName); + + Status = RtlSetCurrentDirectory_U (&UnicodeString); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + + +DWORD +STDCALL +GetTempPathA ( + DWORD nBufferLength, + LPSTR lpBuffer + ) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + + AnsiString.Length = 0; + AnsiString.MaximumLength = nBufferLength; + AnsiString.Buffer = lpBuffer; + + /* initialize allocate unicode string */ + UnicodeString.Length = 0; + UnicodeString.MaximumLength = nBufferLength * sizeof(WCHAR); + UnicodeString.Buffer = RtlAllocateHeap (RtlGetProcessHeap(), + 0, + UnicodeString.MaximumLength); + + UnicodeString.Length = GetTempPathW (nBufferLength, + UnicodeString.Buffer) * sizeof(WCHAR); + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&AnsiString, + &UnicodeString, + FALSE); + else + RtlUnicodeStringToOemString (&AnsiString, + &UnicodeString, + FALSE); + + /* free unicode string buffer */ + RtlFreeHeap (RtlGetProcessHeap (), + 0, + UnicodeString.Buffer); + + return AnsiString.Length; +} + + +DWORD +STDCALL +GetTempPathW ( + DWORD nBufferLength, + LPWSTR lpBuffer + ) +{ + UNICODE_STRING Name; + UNICODE_STRING Value; + NTSTATUS Status; + + Value.Length = 0; + Value.MaximumLength = (nBufferLength - 1) * sizeof(WCHAR); + Value.Buffer = lpBuffer; + + RtlInitUnicodeStringFromLiteral (&Name, + L"TMP"); + + Status = RtlQueryEnvironmentVariable_U (NULL, + &Name, + &Value); + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + RtlInitUnicodeStringFromLiteral (&Name, + L"TEMP"); + + Status = RtlQueryEnvironmentVariable_U (NULL, + &Name, + &Value); + + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + Value.Length = RtlGetCurrentDirectory_U (Value.MaximumLength, + Value.Buffer); + } + } + + if (NT_SUCCESS(Status)) + { + lpBuffer[Value.Length / sizeof(WCHAR)] = L'\\'; + lpBuffer[Value.Length / sizeof(WCHAR) + 1] = 0; + } + + return Value.Length / sizeof(WCHAR) + 1; +} + + +UINT +STDCALL +GetSystemDirectoryA ( + LPSTR lpBuffer, + UINT uSize + ) +{ + ANSI_STRING String; + ULONG Length; + NTSTATUS Status; + + if (lpBuffer == NULL) + return 0; + + Length = RtlUnicodeStringToAnsiSize (&SystemDirectory); //len of ansi str incl. nullchar + + if (uSize >= Length){ + String.Length = 0; + String.MaximumLength = uSize; + String.Buffer = lpBuffer; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + Status = RtlUnicodeStringToAnsiString (&String, + &SystemDirectory, + FALSE); + else + Status = RtlUnicodeStringToOemString (&String, + &SystemDirectory, + FALSE); + if (!NT_SUCCESS(Status) ) + return 0; + + return Length-1; //good: ret chars excl. nullchar + + } + + return Length; //bad: ret space needed incl. nullchar +} + + +UINT +STDCALL +GetSystemDirectoryW ( + LPWSTR lpBuffer, + UINT uSize + ) +{ + ULONG Length; + + if (lpBuffer == NULL) + return 0; + + Length = SystemDirectory.Length / sizeof (WCHAR); + if (uSize > Length) { + memmove (lpBuffer, + SystemDirectory.Buffer, + SystemDirectory.Length); + lpBuffer[Length] = 0; + + return Length; //good: ret chars excl. nullchar + } + + return Length+1; //bad: ret space needed incl. nullchar +} + + +UINT +STDCALL +GetWindowsDirectoryA ( + LPSTR lpBuffer, + UINT uSize + ) +{ + ANSI_STRING String; + ULONG Length; + NTSTATUS Status; + + if (lpBuffer == NULL) + return 0; + + Length = RtlUnicodeStringToAnsiSize (&WindowsDirectory); //len of ansi str incl. nullchar + + printf("windirlen incl term %i\n", Length); + + if (uSize >= Length){ + + printf("ok: enoug space\n"); + + String.Length = 0; + String.MaximumLength = uSize; + String.Buffer = lpBuffer; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + Status = RtlUnicodeStringToAnsiString (&String, + &WindowsDirectory, + FALSE); + else + Status = RtlUnicodeStringToOemString (&String, + &WindowsDirectory, + FALSE); + + if (!NT_SUCCESS(Status)) + return 0; + + printf("good: ret chars %i\n",Length-1); + printf("dir: %s\n",lpBuffer); + return Length-1; //good: ret chars excl. nullchar + } + + printf("bad: ret chars needed %i\n",Length); + return Length; //bad: ret space needed incl. nullchar +} + + +UINT +STDCALL +GetWindowsDirectoryW ( + LPWSTR lpBuffer, + UINT uSize + ) +{ + ULONG Length; + + if (lpBuffer == NULL) + return 0; + + Length = WindowsDirectory.Length / sizeof (WCHAR); + if (uSize > Length) + { + memmove (lpBuffer, + WindowsDirectory.Buffer, + WindowsDirectory.Length); + lpBuffer[Length] = 0; + + return Length; //good: ret chars excl. nullchar + } + + return Length+1; //bad: ret space needed incl. nullchar +} + +/* EOF */ diff --git a/lib/kernel32/file/delete.c b/lib/kernel32/file/delete.c new file mode 100644 index 0000000..d427186 --- /dev/null +++ b/lib/kernel32/file/delete.c @@ -0,0 +1,135 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/delete.c + * PURPOSE: Deleting files + * PROGRAMMER: Ariadne (ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +DeleteFileA ( + LPCSTR lpFileName + ) +{ + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + WINBOOL Result; + + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + + Result = DeleteFileW (FileNameU.Buffer); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileNameU.Buffer); + + return Result; +} + + +WINBOOL +STDCALL +DeleteFileW ( + LPCWSTR lpFileName + ) +{ + FILE_DISPOSITION_INFORMATION FileDispInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE FileHandle; + NTSTATUS Status; + + DPRINT("DeleteFileW (lpFileName %S)\n",lpFileName); + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName, + &NtPathU, + NULL, + NULL)) + return FALSE; + + DPRINT("NtPathU \'%wZ\'\n", &NtPathU); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &NtPathU; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + Status = NtCreateFile (&FileHandle, + FILE_WRITE_ATTRIBUTES, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE, + NULL, + 0); + + RtlFreeUnicodeString(&NtPathU); + + if (!NT_SUCCESS(Status)) + { + CHECKPOINT; + SetLastErrorByStatus (Status); + return FALSE; + } + + FileDispInfo.DoDeleteFile = TRUE; + + Status = NtSetInformationFile (FileHandle, + &IoStatusBlock, + &FileDispInfo, + sizeof(FILE_DISPOSITION_INFORMATION), + FileDispositionInformation); + if (!NT_SUCCESS(Status)) + { + CHECKPOINT; + NtClose (FileHandle); + SetLastErrorByStatus (Status); + return FALSE; + } + + Status = NtClose (FileHandle); + if (!NT_SUCCESS (Status)) + { + CHECKPOINT; + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/file/deviceio.c b/lib/kernel32/file/deviceio.c new file mode 100644 index 0000000..79f5c34 --- /dev/null +++ b/lib/kernel32/file/deviceio.c @@ -0,0 +1,192 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/deviceio.c + * PURPOSE: Device I/O and Overlapped Result functions + * PROGRAMMER: Ariadne (ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include + +#define NDEBUG +//#define DBG +#include +#include + + +WINBOOL +STDCALL +DeviceIoControl( + HANDLE hDevice, + DWORD dwIoControlCode, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ) +{ + NTSTATUS errCode = 0; + HANDLE hEvent = NULL; + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK IIosb; + + WINBOOL bFsIoControlCode = FALSE; + + DPRINT("DeviceIoControl(hDevice %x dwIoControlCode %d lpInBuffer %x " + "nInBufferSize %d lpOutBuffer %x nOutBufferSize %d " + "lpBytesReturned %x lpOverlapped %x)\n", + hDevice,dwIoControlCode,lpInBuffer,nInBufferSize,lpOutBuffer, + nOutBufferSize,lpBytesReturned,lpOverlapped); + + if (lpBytesReturned == NULL) + { + DPRINT("DeviceIoControl() - returning STATUS_INVALID_PARAMETER\n"); + SetLastErrorByStatus (STATUS_INVALID_PARAMETER); + return FALSE; + } + // + // TODO: Review and approve this change by RobD. IoCtrls for Serial.sys were + // going to NtFsControlFile instead of NtDeviceIoControlFile. + // Don't know at this point if anything else is affected by this change. + // + // if (((dwIoControlCode >> 16) & FILE_DEVICE_FILE_SYSTEM) == FILE_DEVICE_FILE_SYSTEM) { + // + + if ((dwIoControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM) { + + bFsIoControlCode = TRUE; + DPRINT("DeviceIoControl() - FILE_DEVICE_FILE_SYSTEM == TRUE %x %x\n", dwIoControlCode, dwIoControlCode >> 16); + } else { + bFsIoControlCode = FALSE; + DPRINT("DeviceIoControl() - FILE_DEVICE_FILE_SYSTEM == FALSE %x %x\n", dwIoControlCode, dwIoControlCode >> 16); + } + + if(lpOverlapped != NULL) + { + hEvent = lpOverlapped->hEvent; + lpOverlapped->Internal = STATUS_PENDING; + IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped; + } + else + { + IoStatusBlock = &IIosb; + } + + if (bFsIoControlCode == TRUE) + { + errCode = NtFsControlFile (hDevice, + hEvent, + NULL, + NULL, + IoStatusBlock, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + else + { + errCode = NtDeviceIoControlFile (hDevice, + hEvent, + NULL, + NULL, + IoStatusBlock, + dwIoControlCode, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + + if (errCode == STATUS_PENDING) + { + DPRINT("DeviceIoControl() - STATUS_PENDING\n"); + if (NtWaitForSingleObject(hDevice,FALSE,NULL) < 0) + { + *lpBytesReturned = IoStatusBlock->Information; + SetLastErrorByStatus (errCode); + DPRINT("DeviceIoControl() - STATUS_PENDING wait failed.\n"); + return FALSE; + } + } + else if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + DPRINT("DeviceIoControl() - ERROR: %x\n", errCode); + return FALSE; + } + + if (lpOverlapped) + *lpBytesReturned = lpOverlapped->InternalHigh; + else + *lpBytesReturned = IoStatusBlock->Information; + + return TRUE; +} + + +WINBOOL +STDCALL +GetOverlappedResult ( + HANDLE hFile, + LPOVERLAPPED lpOverlapped, + LPDWORD lpNumberOfBytesTransferred, + WINBOOL bWait + ) +{ + DWORD WaitStatus; + + if (lpOverlapped == NULL) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return FALSE; + } + + if (lpOverlapped ->Internal == STATUS_PENDING) + { + if (lpNumberOfBytesTransferred == 0) + { + SetLastErrorByStatus (STATUS_PENDING); + return FALSE; + } + else if (bWait == TRUE) + { + if (lpOverlapped->hEvent != NULL) + { + WaitStatus = WaitForSingleObject (lpOverlapped->hEvent, + -1); + if (WaitStatus == STATUS_TIMEOUT) + { + SetLastError (ERROR_IO_INCOMPLETE); + return FALSE; + } + else + return GetOverlappedResult (hFile, + lpOverlapped, + lpNumberOfBytesTransferred, + FALSE); + } + } + } + + *lpNumberOfBytesTransferred = lpOverlapped->InternalHigh; + + if (lpOverlapped->Internal < 0) + { + SetLastErrorByStatus (lpOverlapped->Internal); + return FALSE; + } + + return TRUE; +} + +/* EOF */ + + diff --git a/lib/kernel32/file/dir.c b/lib/kernel32/file/dir.c new file mode 100644 index 0000000..269efe7 --- /dev/null +++ b/lib/kernel32/file/dir.c @@ -0,0 +1,624 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/dir.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* + * NOTES: Changed to using ZwCreateFile + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +CreateDirectoryA ( + LPCSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + return CreateDirectoryExA (NULL, + lpPathName, + lpSecurityAttributes); +} + +WINBOOL +STDCALL +CreateDirectoryExA ( + LPCSTR lpTemplateDirectory, + LPCSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + UNICODE_STRING TmplDirU; + UNICODE_STRING NewDirU; + ANSI_STRING TmplDir; + ANSI_STRING NewDir; + WINBOOL Result; + + RtlInitUnicodeString (&TmplDirU, + NULL); + + RtlInitUnicodeString (&NewDirU, + NULL); + + if (lpTemplateDirectory != NULL) + { + RtlInitAnsiString (&TmplDir, + (LPSTR)lpTemplateDirectory); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&TmplDirU, + &TmplDir, + TRUE); + else + RtlOemStringToUnicodeString (&TmplDirU, + &TmplDir, + TRUE); + } + + if (lpNewDirectory != NULL) + { + RtlInitAnsiString (&NewDir, + (LPSTR)lpNewDirectory); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&NewDirU, + &NewDir, + TRUE); + else + RtlOemStringToUnicodeString (&NewDirU, + &NewDir, + TRUE); + } + + Result = CreateDirectoryExW (TmplDirU.Buffer, + NewDirU.Buffer, + lpSecurityAttributes); + + if (lpTemplateDirectory != NULL) + RtlFreeHeap (RtlGetProcessHeap (), + 0, + TmplDirU.Buffer); + + if (lpNewDirectory != NULL) + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NewDirU.Buffer); + + return Result; +} + + +WINBOOL +STDCALL +CreateDirectoryW ( + LPCWSTR lpPathName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + return CreateDirectoryExW (NULL, + lpPathName, + lpSecurityAttributes); +} + + +WINBOOL +STDCALL +CreateDirectoryExW ( + LPCWSTR lpTemplateDirectory, + LPCWSTR lpNewDirectory, + LPSECURITY_ATTRIBUTES lpSecurityAttributes + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE DirectoryHandle; + NTSTATUS Status; + + DPRINT ("lpTemplateDirectory %S lpNewDirectory %S lpSecurityAttributes %p\n", + lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes); + + if (lpTemplateDirectory != NULL && *lpTemplateDirectory != 0) + { + // get object attributes from template directory + DPRINT("KERNEL32:FIXME:%s:%d\n",__FILE__,__LINE__); + return FALSE; + } + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewDirectory, + &NtPathU, + NULL, + NULL)) + return FALSE; + + DPRINT1 ("NtPathU \'%wZ\'\n", &NtPathU); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &NtPathU; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + Status = NtCreateFile (&DirectoryHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_DIRECTORY, + 0, + FILE_CREATE, + FILE_DIRECTORY_FILE, + NULL, + 0); + DPRINT("Status: %lx\n", Status); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + NtClose (DirectoryHandle); + + return TRUE; +} + + +WINBOOL +STDCALL +RemoveDirectoryA ( + LPCSTR lpPathName + ) +{ + UNICODE_STRING PathNameU; + ANSI_STRING PathName; + WINBOOL Result; + + RtlInitAnsiString (&PathName, + (LPSTR)lpPathName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&PathNameU, + &PathName, + TRUE); + else + RtlOemStringToUnicodeString (&PathNameU, + &PathName, + TRUE); + + Result = RemoveDirectoryW (PathNameU.Buffer); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + PathNameU.Buffer); + + return Result; +} + + +WINBOOL +STDCALL +RemoveDirectoryW ( + LPCWSTR lpPathName + ) +{ + FILE_DISPOSITION_INFORMATION FileDispInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + HANDLE DirectoryHandle; + NTSTATUS Status; + + DPRINT("lpPathName %S\n", lpPathName); + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpPathName, + &NtPathU, + NULL, + NULL)) + return FALSE; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &NtPathU; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + DPRINT("NtPathU '%S'\n", NtPathU.Buffer); + + Status = NtCreateFile (&DirectoryHandle, + FILE_WRITE_ATTRIBUTES, /* 0x110080 */ + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_DIRECTORY, /* 0x7 */ + 0, + FILE_OPEN, + FILE_DIRECTORY_FILE, /* 0x204021 */ + NULL, + 0); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + CHECKPOINT; + SetLastErrorByStatus (Status); + return FALSE; + } + + FileDispInfo.DoDeleteFile = TRUE; + + Status = NtSetInformationFile (DirectoryHandle, + &IoStatusBlock, + &FileDispInfo, + sizeof(FILE_DISPOSITION_INFORMATION), + FileDispositionInformation); + if (!NT_SUCCESS(Status)) + { + CHECKPOINT; + NtClose(DirectoryHandle); + SetLastErrorByStatus (Status); + return FALSE; + } + + Status = NtClose (DirectoryHandle); + if (!NT_SUCCESS(Status)) + { + CHECKPOINT; + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + + +DWORD +STDCALL +GetFullPathNameA ( + LPCSTR lpFileName, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart + ) +{ + UNICODE_STRING FileNameU; + UNICODE_STRING FullNameU; + ANSI_STRING FileName; + ANSI_STRING FullName; + PWSTR FilePartU; + ULONG BufferLength; + ULONG Offset; + + DPRINT("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, " + "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart); + + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + + BufferLength = nBufferLength * sizeof(WCHAR); + + FullNameU.MaximumLength = BufferLength; + FullNameU.Length = 0; + FullNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + BufferLength); + + FullNameU.Length = RtlGetFullPathName_U (FileNameU.Buffer, + BufferLength, + FullNameU.Buffer, + &FilePartU); + + RtlFreeUnicodeString (&FileNameU); + + FullName.MaximumLength = nBufferLength; + FullName.Length = 0; + FullName.Buffer = lpBuffer; + + RtlUnicodeStringToAnsiString (&FullName, + &FullNameU, + FALSE); + + if (lpFilePart != NULL) + { + Offset = (ULONG)(FilePartU - FullNameU.Buffer); + *lpFilePart = FullName.Buffer + Offset; + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FullNameU.Buffer); + + DPRINT("lpBuffer %s lpFilePart %s Length %ld\n", + lpBuffer, lpFilePart, FullName.Length); + + return FullName.Length; +} + + +DWORD +STDCALL +GetFullPathNameW ( + LPCWSTR lpFileName, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart + ) +{ + ULONG Length; + + DPRINT("GetFullPathNameW(lpFileName %S, nBufferLength %d, lpBuffer %p, " + "lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart); + + Length = RtlGetFullPathName_U ((LPWSTR)lpFileName, + nBufferLength * sizeof(WCHAR), + lpBuffer, + lpFilePart); + + DPRINT("lpBuffer %S lpFilePart %S Length %ld\n", + lpBuffer, lpFilePart, Length / sizeof(WCHAR)); + + return (Length / sizeof(WCHAR)); +} + + +DWORD +STDCALL +GetShortPathNameA ( + LPCSTR lpszLongPath, + LPSTR lpszShortPath, + DWORD cchBuffer + ) +{ + //1 remove unicode chars and spaces + //2 remove preceding and trailing periods. + //3 remove embedded periods except the last one + + //4 Split the string in two parts before and after the period + // truncate the part before the period to 6 chars and add ~1 + // truncate the part after the period to 3 chars + //3 Put the new name in uppercase + + //4 Increment the ~1 string if the resulting name allready exists + + return 0; +} + + +DWORD +STDCALL +GetShortPathNameW ( + LPCWSTR lpszLongPath, + LPWSTR lpszShortPath, + DWORD cchBuffer + ) +{ + return 0; +} + + +DWORD +STDCALL +SearchPathA ( + LPCSTR lpPath, + LPCSTR lpFileName, + LPCSTR lpExtension, + DWORD nBufferLength, + LPSTR lpBuffer, + LPSTR *lpFilePart + ) +{ + UNICODE_STRING PathU; + UNICODE_STRING FileNameU; + UNICODE_STRING ExtensionU; + UNICODE_STRING BufferU; + ANSI_STRING Path; + ANSI_STRING FileName; + ANSI_STRING Extension; + ANSI_STRING Buffer; + PWCHAR FilePartW; + DWORD RetValue; + + RtlInitAnsiString (&Path, + (LPSTR)lpPath); + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + RtlInitAnsiString (&Extension, + (LPSTR)lpExtension); + + /* convert ansi (or oem) strings to unicode */ + if (bIsFileApiAnsi) + { + RtlAnsiStringToUnicodeString (&PathU, + &Path, + TRUE); + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + RtlAnsiStringToUnicodeString (&ExtensionU, + &Extension, + TRUE); + } + else + { + RtlOemStringToUnicodeString (&PathU, + &Path, + TRUE); + RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + RtlOemStringToUnicodeString (&ExtensionU, + &Extension, + TRUE); + } + + BufferU.Length = 0; + BufferU.MaximumLength = nBufferLength * sizeof(WCHAR); + BufferU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + BufferU.MaximumLength); + + Buffer.Length = 0; + Buffer.MaximumLength = nBufferLength; + Buffer.Buffer = lpBuffer; + + RetValue = SearchPathW (PathU.Buffer, + FileNameU.Buffer, + ExtensionU.Buffer, + nBufferLength, + BufferU.Buffer, + &FilePartW); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + PathU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + ExtensionU.Buffer); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&Buffer, + &BufferU, + FALSE); + else + RtlUnicodeStringToOemString (&Buffer, + &BufferU, + FALSE); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + BufferU.Buffer); + + *lpFilePart = strrchr (lpBuffer, '\\') + 1; + + return RetValue; +} + + +DWORD +STDCALL +SearchPathW ( + LPCWSTR lpPath, + LPCWSTR lpFileName, + LPCWSTR lpExtension, + DWORD nBufferLength, + LPWSTR lpBuffer, + LPWSTR *lpFilePart + ) +/* + * FUNCTION: Searches for the specified file + * ARGUMENTS: + * lpPath = Points to a null-terminated string that specified the + * path to be searched. If this parameters is NULL then + * the following directories are searched + * The directory from which the application loaded + * The current directory + * The system directory + * The 16-bit system directory + * The windows directory + * The directories listed in the PATH environment + * variable + * lpFileName = Specifies the filename to search for + * lpExtension = Points to the null-terminated string that specifies + * an extension to be added to the filename when + * searching for the file. The first character of the + * filename extension must be a period (.). The + * extension is only added if the specified filename + * doesn't end with an extension + * + * If the filename extension is not required or if the + * filename contains an extension, this parameters can be + * NULL + * nBufferLength = The length in characters of the buffer for output + * lpBuffer = Points to the buffer for the valid path and filename of + * file found + * lpFilePart = Points to the last component of the valid path and + * filename + * RETURNS: On success, the length, in characters, of the string copied to the + * buffer + * On failure, zero. + */ +{ + DWORD retCode = 0; + ULONG pos, len; + PWCHAR EnvironmentBufferW = NULL; + WCHAR Buffer; + + DPRINT("SearchPath\n"); + + if (lpPath == NULL) + { + len = GetEnvironmentVariableW(L"PATH", &Buffer, 0); + len += 1 + GetCurrentDirectoryW(0, &Buffer); + len += 1 + GetSystemDirectoryW(&Buffer, 0); + len += 1 + GetWindowsDirectoryW(&Buffer, 0); + + EnvironmentBufferW = (PWCHAR) RtlAllocateHeap(GetProcessHeap(), + HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, + len * sizeof(WCHAR)); + if (EnvironmentBufferW == NULL) + { + return 0; + } + + pos = GetCurrentDirectoryW(len, EnvironmentBufferW); + EnvironmentBufferW[pos++] = L';'; + EnvironmentBufferW[pos] = 0; + pos += GetSystemDirectoryW(&EnvironmentBufferW[pos], len - pos); + EnvironmentBufferW[pos++] = L';'; + EnvironmentBufferW[pos] = 0; + pos += GetWindowsDirectoryW(&EnvironmentBufferW[pos], len - pos); + EnvironmentBufferW[pos++] = L';'; + EnvironmentBufferW[pos] = 0; + pos += GetEnvironmentVariableW(L"PATH", &EnvironmentBufferW[pos], len - pos); + lpPath = EnvironmentBufferW; + } + + retCode = RtlDosSearchPath_U ((PWCHAR)lpPath, (PWCHAR)lpFileName, (PWCHAR)lpExtension, nBufferLength, lpBuffer, lpFilePart); + + if (EnvironmentBufferW != NULL) + { + RtlFreeHeap(GetProcessHeap(), 0, EnvironmentBufferW); + } + return retCode; +} + +/* EOF */ diff --git a/lib/kernel32/file/dosdev.c b/lib/kernel32/file/dosdev.c new file mode 100644 index 0000000..414a736 --- /dev/null +++ b/lib/kernel32/file/dosdev.c @@ -0,0 +1,109 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/dosdev.c + * PURPOSE: Dos device functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include + + +WINBOOL +STDCALL +DefineDosDeviceA( + DWORD dwFlags, + LPCSTR lpDeviceName, + LPCSTR lpTargetPath + ) +{ + ULONG i; + + WCHAR DeviceNameW[MAX_PATH]; + WCHAR TargetPathW[MAX_PATH]; + + i = 0; + while ((*lpDeviceName)!=0 && i < MAX_PATH) + { + DeviceNameW[i] = *lpDeviceName; + lpDeviceName++; + i++; + } + DeviceNameW[i] = 0; + + i = 0; + while ((*lpTargetPath)!=0 && i < MAX_PATH) + { + TargetPathW[i] = *lpTargetPath; + lpTargetPath++; + i++; + } + TargetPathW[i] = 0; + return DefineDosDeviceW(dwFlags,DeviceNameW,TargetPathW); +} + + + +DWORD +STDCALL +QueryDosDeviceA( + LPCSTR lpDeviceName, + LPSTR lpTargetPath, + DWORD ucchMax + ) +{ + ULONG i; + + WCHAR DeviceNameW[MAX_PATH]; + WCHAR TargetPathW[MAX_PATH]; + + + + i = 0; + while ((*lpDeviceName)!=0 && i < MAX_PATH) + { + DeviceNameW[i] = *lpDeviceName; + lpDeviceName++; + i++; + } + DeviceNameW[i] = 0; + + i = 0; + while ((*lpTargetPath)!=0 && i < MAX_PATH) + { + TargetPathW[i] = *lpTargetPath; + lpTargetPath++; + i++; + } + TargetPathW[i] = 0; + return QueryDosDeviceW(DeviceNameW,TargetPathW,ucchMax); +} + + +WINBOOL +STDCALL +DefineDosDeviceW( + DWORD dwFlags, + LPCWSTR lpDeviceName, + LPCWSTR lpTargetPath + ) +{ + return FALSE; +} + +DWORD +STDCALL +QueryDosDeviceW( + LPCWSTR lpDeviceName, + LPWSTR lpTargetPath, + DWORD ucchMax + ) +{ + return FALSE; +} + +/* EOF */ diff --git a/lib/kernel32/file/file.c b/lib/kernel32/file/file.c new file mode 100644 index 0000000..e4c7163 --- /dev/null +++ b/lib/kernel32/file/file.c @@ -0,0 +1,811 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/file.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * GetTempFileName is modified from WINE [ Alexandre Juiliard ] + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include +#include + +#define LPPROGRESS_ROUTINE void* + + +/* GLOBALS ******************************************************************/ + +WINBOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem + + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +SetFileApisToOEM(VOID) +{ + bIsFileApiAnsi = FALSE; +} + + +VOID STDCALL +SetFileApisToANSI(VOID) +{ + bIsFileApiAnsi = TRUE; +} + + +WINBOOL STDCALL +AreFileApisANSI(VOID) +{ + return bIsFileApiAnsi; +} + + +HFILE STDCALL +OpenFile(LPCSTR lpFileName, + LPOFSTRUCT lpReOpenBuff, + UINT uStyle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING FileNameString; + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + WCHAR PathNameW[MAX_PATH]; + HANDLE FileHandle = NULL; + NTSTATUS errCode; + PWCHAR FilePart; + ULONG Len; + + DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle); + + if (lpReOpenBuff == NULL) + { + return FALSE; + } + + RtlInitAnsiString (&FileName, (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE); + + Len = SearchPathW (NULL, + FileNameU.Buffer, + NULL, + OFS_MAXPATHNAME, + PathNameW, + &FilePart); + + RtlFreeUnicodeString(&FileNameU); + + if (Len == 0 || Len > OFS_MAXPATHNAME) + { + return (HFILE)INVALID_HANDLE_VALUE; + } + + FileName.Buffer = lpReOpenBuff->szPathName; + FileName.Length = 0; + FileName.MaximumLength = OFS_MAXPATHNAME; + + RtlInitUnicodeString(&FileNameU, PathNameW); + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE); + else + RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE); + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)PathNameW, + &FileNameString, + NULL, + NULL)) + { + return (HFILE)INVALID_HANDLE_VALUE; + } + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &FileNameString; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + // FILE_SHARE_READ + // FILE_NO_INTERMEDIATE_BUFFERING + + if ((uStyle & OF_PARSE) == OF_PARSE) + { + RtlFreeUnicodeString(&FileNameString); + return (HFILE)NULL; + } + + errCode = NtOpenFile (&FileHandle, + GENERIC_READ|SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ, + FILE_NON_DIRECTORY_FILE); + + RtlFreeUnicodeString(&FileNameString); + + lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode); + + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return (HFILE)INVALID_HANDLE_VALUE; + } + + return (HFILE)FileHandle; +} + + +WINBOOL STDCALL +FlushFileBuffers(HANDLE hFile) +{ + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + + if (IsConsoleHandle(hFile)) + { + return FALSE; + } + + errCode = NtFlushBuffersFile(hFile, + &IoStatusBlock); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return(FALSE); + } + return(TRUE); +} + + +DWORD STDCALL +SetFilePointer(HANDLE hFile, + LONG lDistanceToMove, + PLONG lpDistanceToMoveHigh, + DWORD dwMoveMethod) +{ + FILE_POSITION_INFORMATION FilePosition; + FILE_STANDARD_INFORMATION FileStandart; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + LARGE_INTEGER Distance; + + DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n", + hFile,lDistanceToMove,dwMoveMethod); + + Distance.u.LowPart = lDistanceToMove; + if (lpDistanceToMoveHigh) + { + Distance.u.HighPart = *lpDistanceToMoveHigh; + } + else if (lDistanceToMove >= 0) + { + Distance.u.HighPart = 0; + } + else + { + Distance.u.HighPart = -1; + } + + if (dwMoveMethod == FILE_CURRENT) + { + NtQueryInformationFile(hFile, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart; + } + else if (dwMoveMethod == FILE_END) + { + NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandart, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + FilePosition.CurrentByteOffset.QuadPart = + FileStandart.EndOfFile.QuadPart + Distance.QuadPart; + } + else if ( dwMoveMethod == FILE_BEGIN ) + { + FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart; + } + + errCode = NtSetInformationFile(hFile, + &IoStatusBlock, + &FilePosition, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return -1; + } + + if (lpDistanceToMoveHigh != NULL) + { + *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart; + } + return FilePosition.CurrentByteOffset.u.LowPart; +} + + +DWORD STDCALL +GetFileType(HANDLE hFile) +{ + FILE_FS_DEVICE_INFORMATION DeviceInfo; + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + /* get real handle */ + switch ((ULONG)hFile) + { + case STD_INPUT_HANDLE: + hFile = NtCurrentPeb()->ProcessParameters->hStdInput; + break; + + case STD_OUTPUT_HANDLE: + hFile = NtCurrentPeb()->ProcessParameters->hStdOutput; + break; + + case STD_ERROR_HANDLE: + hFile = NtCurrentPeb()->ProcessParameters->hStdError; + break; + } + + /* check console handles */ + if (IsConsoleHandle(hFile)) + { +// if (VerifyConsoleHandle(hFile)) + return FILE_TYPE_CHAR; + } + + Status = NtQueryVolumeInformationFile(hFile, + &StatusBlock, + &DeviceInfo, + sizeof(FILE_FS_DEVICE_INFORMATION), + FileFsDeviceInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FILE_TYPE_UNKNOWN; + } + + switch (DeviceInfo.DeviceType) + { + case FILE_DEVICE_CD_ROM: + case FILE_DEVICE_CD_ROM_FILE_SYSTEM: + case FILE_DEVICE_CONTROLLER: + case FILE_DEVICE_DATALINK: + case FILE_DEVICE_DFS: + case FILE_DEVICE_DISK: + case FILE_DEVICE_DISK_FILE_SYSTEM: + case FILE_DEVICE_VIRTUAL_DISK: + return FILE_TYPE_DISK; + + case FILE_DEVICE_KEYBOARD: + case FILE_DEVICE_MOUSE: + case FILE_DEVICE_NULL: + case FILE_DEVICE_PARALLEL_PORT: + case FILE_DEVICE_PRINTER: + case FILE_DEVICE_SERIAL_PORT: + case FILE_DEVICE_SCREEN: + case FILE_DEVICE_SOUND: + case FILE_DEVICE_MODEM: + return FILE_TYPE_CHAR; + + case FILE_DEVICE_NAMED_PIPE: + return FILE_TYPE_PIPE; + } + + return FILE_TYPE_UNKNOWN; +} + + +DWORD STDCALL +GetFileSize(HANDLE hFile, + LPDWORD lpFileSizeHigh) +{ + NTSTATUS errCode; + FILE_STANDARD_INFORMATION FileStandard; + IO_STATUS_BLOCK IoStatusBlock; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + if ( lpFileSizeHigh == NULL ) + { + return -1; + } + else + { + return 0; + } + } + if ( lpFileSizeHigh != NULL ) + *lpFileSizeHigh = FileStandard.EndOfFile.u.HighPart; + + return FileStandard.EndOfFile.u.LowPart; +} + + +DWORD STDCALL +GetCompressedFileSizeA(LPCSTR lpFileName, + LPDWORD lpFileSizeHigh) +{ + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + DWORD Size; + + RtlInitAnsiString(&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString(&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString(&FileNameU, + &FileName, + TRUE); + + Size = GetCompressedFileSizeW(FileNameU.Buffer, + lpFileSizeHigh); + + RtlFreeUnicodeString (&FileNameU); + + return Size; +} + + +DWORD STDCALL +GetCompressedFileSizeW(LPCWSTR lpFileName, + LPDWORD lpFileSizeHigh) +{ + FILE_COMPRESSION_INFORMATION FileCompression; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE hFile; + + hFile = CreateFileW(lpFileName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileCompression, + sizeof(FILE_COMPRESSION_INFORMATION), + FileCompressionInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus(errCode); + return 0; + } + CloseHandle(hFile); + return 0; +} + + +WINBOOL STDCALL +GetFileInformationByHandle(HANDLE hFile, + LPBY_HANDLE_FILE_INFORMATION lpFileInformation) +{ + struct + { + FILE_FS_VOLUME_INFORMATION FileFsVolume; + WCHAR Name[255]; + } + FileFsVolume; + + FILE_BASIC_INFORMATION FileBasic; + FILE_INTERNAL_INFORMATION FileInternal; + FILE_STANDARD_INFORMATION FileStandard; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + + lpFileInformation->dwFileAttributes = (DWORD)FileBasic.FileAttributes; + memcpy(&lpFileInformation->ftCreationTime,&FileBasic.CreationTime,sizeof(LARGE_INTEGER)); + memcpy(&lpFileInformation->ftLastAccessTime,&FileBasic.LastAccessTime,sizeof(LARGE_INTEGER)); + memcpy(&lpFileInformation->ftLastWriteTime, &FileBasic.LastWriteTime,sizeof(LARGE_INTEGER)); + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileInternal, + sizeof(FILE_INTERNAL_INFORMATION), + FileInternalInformation); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + + lpFileInformation->nFileIndexHigh = FileInternal.IndexNumber.u.HighPart; + lpFileInformation->nFileIndexLow = FileInternal.IndexNumber.u.LowPart; + + errCode = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + &FileFsVolume, + sizeof(FileFsVolume), + FileFsVolumeInformation); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + + lpFileInformation->dwVolumeSerialNumber = FileFsVolume.FileFsVolume.VolumeSerialNumber; + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileStandard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + + lpFileInformation->nNumberOfLinks = FileStandard.NumberOfLinks; + lpFileInformation->nFileSizeHigh = FileStandard.EndOfFile.u.HighPart; + lpFileInformation->nFileSizeLow = FileStandard.EndOfFile.u.LowPart; + + return TRUE; +} + + +DWORD STDCALL +GetFileAttributesA(LPCSTR lpFileName) +{ + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + WINBOOL Result; + + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + + Result = GetFileAttributesW (FileNameU.Buffer); + + RtlFreeUnicodeString (&FileNameU); + + return Result; +} + + +DWORD STDCALL +GetFileAttributesW(LPCWSTR lpFileName) +{ + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; + HANDLE hFile; + NTSTATUS errCode; + + hFile = CreateFileW(lpFileName, + FILE_READ_ATTRIBUTES, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + return 0xFFFFFFFF; + } + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus(errCode); + return 0xFFFFFFFF; + } + CloseHandle(hFile); + return (DWORD)FileBasic.FileAttributes; +} + + +WINBOOL STDCALL +SetFileAttributesA(LPCSTR lpFileName, + DWORD dwFileAttributes) +{ + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + WINBOOL Result; + + RtlInitAnsiString(&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString(&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString(&FileNameU, + &FileName, + TRUE); + + Result = SetFileAttributesW(FileNameU.Buffer, + dwFileAttributes); + + RtlFreeUnicodeString(&FileNameU); + + return Result; +} + + +WINBOOL STDCALL +SetFileAttributesW(LPCWSTR lpFileName, + DWORD dwFileAttributes) +{ + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; + HANDLE hFile; + NTSTATUS errCode; + + hFile = CreateFileW(lpFileName, + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + errCode = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus(errCode); + return FALSE; + } + FileBasic.FileAttributes = dwFileAttributes; + errCode = NtSetInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus(errCode); + return FALSE; + } + CloseHandle(hFile); + return TRUE; +} + + +UINT STDCALL +GetTempFileNameA(LPCSTR lpPathName, + LPCSTR lpPrefixString, + UINT uUnique, + LPSTR lpTempFileName) +{ + HANDLE hFile; + UINT unique = uUnique; + UINT len; + const char *format = "%.*s\\~%.3s%4.4x.TMP"; + + DPRINT("GetTempFileNameA(lpPathName %s, lpPrefixString %.*s, " + "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, + lpPrefixString, uUnique, lpTempFileName); + + if (lpPathName == NULL) + return 0; + + len = strlen(lpPathName); + if (len > 0 && (lpPathName[len-1] == '\\' || lpPathName[len-1] == '/')) + len--; + + if (uUnique == 0) + uUnique = GetCurrentTime(); + + sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique); + + if (unique) + return uUnique; + + while ((hFile = CreateFileA(lpTempFileName, GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, + 0)) == INVALID_HANDLE_VALUE) + { + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + return 0; + } + sprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique); + } + CloseHandle(hFile); + return uUnique; +} + + +UINT STDCALL +GetTempFileNameW(LPCWSTR lpPathName, + LPCWSTR lpPrefixString, + UINT uUnique, + LPWSTR lpTempFileName) +{ + HANDLE hFile; + UINT unique = uUnique; + UINT len; + const WCHAR *format = L"%.*S\\~%.3S%4.4x.TMP"; + + DPRINT("GetTempFileNameW(lpPathName %S, lpPrefixString %.*S, " + "uUnique %x, lpTempFileName %x)\n", lpPathName, 4, + lpPrefixString, uUnique, lpTempFileName); + + if (lpPathName == NULL) + return 0; + + len = wcslen(lpPathName); + if (len > 0 && (lpPathName[len-1] == L'\\' || lpPathName[len-1] == L'/')) + len--; + + if (uUnique == 0) + uUnique = GetCurrentTime(); + + swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,uUnique); + + if (unique) + return uUnique; + + while ((hFile = CreateFileW(lpTempFileName, GENERIC_WRITE, 0, NULL, + CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, + 0)) == INVALID_HANDLE_VALUE) + { + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + return 0; + } + swprintf(lpTempFileName,format,len,lpPathName,lpPrefixString,++uUnique); + } + CloseHandle(hFile); + return uUnique; +} + + +WINBOOL STDCALL +GetFileTime(HANDLE hFile, + LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, + LPFILETIME lpLastWriteTime) +{ + IO_STATUS_BLOCK IoStatusBlock; + FILE_BASIC_INFORMATION FileBasic; + NTSTATUS Status; + + Status = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + if (lpCreationTime) + memcpy(lpCreationTime, &FileBasic.CreationTime, sizeof(FILETIME)); + if (lpLastAccessTime) + memcpy(lpLastAccessTime, &FileBasic.LastAccessTime, sizeof(FILETIME)); + if (lpLastWriteTime) + memcpy(lpLastWriteTime, &FileBasic.LastWriteTime, sizeof(FILETIME)); + + return TRUE; +} + + +WINBOOL STDCALL +SetFileTime(HANDLE hFile, + CONST FILETIME *lpCreationTime, + CONST FILETIME *lpLastAccessTime, + CONST FILETIME *lpLastWriteTime) +{ + FILE_BASIC_INFORMATION FileBasic; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + Status = NtQueryInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + if (lpCreationTime) + memcpy(&FileBasic.CreationTime, lpCreationTime, sizeof(FILETIME)); + if (lpLastAccessTime) + memcpy(&FileBasic.LastAccessTime, lpLastAccessTime, sizeof(FILETIME)); + if (lpLastWriteTime) + memcpy(&FileBasic.LastWriteTime, lpLastWriteTime, sizeof(FILETIME)); + + // should i initialize changetime ??? + + Status = NtSetInformationFile(hFile, + &IoStatusBlock, + &FileBasic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + + +WINBOOL STDCALL +SetEndOfFile(HANDLE hFile) +{ + int x = -1; + DWORD Num; + return WriteFile(hFile,&x,1,&Num,NULL); +} + +/* EOF */ diff --git a/lib/kernel32/file/find.c b/lib/kernel32/file/find.c new file mode 100644 index 0000000..8b47b75 --- /dev/null +++ b/lib/kernel32/file/find.c @@ -0,0 +1,494 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/find.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* TYPES ********************************************************************/ + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &( ((TYPE *) 0)->MEMBER )) +#endif + +#define FIND_DATA_SIZE (16*1024) + +typedef struct _KERNEL32_FIND_FILE_DATA +{ + HANDLE DirectoryHandle; + PFILE_BOTH_DIRECTORY_INFORMATION pFileInfo; +} KERNEL32_FIND_FILE_DATA, *PKERNEL32_FIND_FILE_DATA; + + +/* FUNCTIONS ****************************************************************/ + + +WINBOOL +STDCALL +InternalFindNextFile ( + HANDLE hFindFile + ) +{ + PKERNEL32_FIND_FILE_DATA IData; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + IData = (PKERNEL32_FIND_FILE_DATA)hFindFile; + + if (IData->pFileInfo->NextEntryOffset != 0) + { + IData->pFileInfo = (PVOID)IData->pFileInfo + IData->pFileInfo->NextEntryOffset; + DPRINT("Found %.*S\n",IData->pFileInfo->FileNameLength, IData->pFileInfo->FileName); + return TRUE; + } + IData->pFileInfo = (PVOID)IData + sizeof(KERNEL32_FIND_FILE_DATA); + IData->pFileInfo->FileIndex = 0; + Status = NtQueryDirectoryFile (IData->DirectoryHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + (PVOID)IData->pFileInfo, + FIND_DATA_SIZE, + FileBothDirectoryInformation, + FALSE, + NULL, + FALSE); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + DPRINT("Found %.*S\n",IData->pFileInfo->FileNameLength, IData->pFileInfo->FileName); + return TRUE; +} + + +HANDLE +STDCALL +InternalFindFirstFile ( + LPCWSTR lpFileName + ) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PKERNEL32_FIND_FILE_DATA IData; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING NtPathU; + UNICODE_STRING PatternStr; + NTSTATUS Status; + PWSTR End; + + DPRINT("FindFirstFileW(lpFileName %S)\n", + lpFileName); + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFileName, + &NtPathU, + &End, + NULL)) + return FALSE; + + DPRINT("NtPathU \'%S\' End \'%S\'\n", NtPathU.Buffer, End); + + IData = RtlAllocateHeap (hProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(KERNEL32_FIND_FILE_DATA) + FIND_DATA_SIZE); + + /* move seach pattern to separate string */ + RtlCreateUnicodeString (&PatternStr, + End); + *End = 0; + NtPathU.Length = wcslen(NtPathU.Buffer)*sizeof(WCHAR); + + /* change pattern: "*.*" --> "*" */ + if (!wcscmp (PatternStr.Buffer, L"*.*")) + { + PatternStr.Buffer[1] = 0; + PatternStr.Length = sizeof(WCHAR); + } + + DPRINT("NtPathU \'%S\' Pattern \'%S\'\n", + NtPathU.Buffer, PatternStr.Buffer); + + InitializeObjectAttributes (&ObjectAttributes, + &NtPathU, + 0, + NULL, + NULL); + + Status = NtOpenFile (&IData->DirectoryHandle, + FILE_LIST_DIRECTORY, + &ObjectAttributes, + &IoStatusBlock, + FILE_OPEN_IF, + OPEN_EXISTING); + + RtlFreeHeap (hProcessHeap, + 0, + NtPathU.Buffer); + + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap (hProcessHeap, 0, PatternStr.Buffer); + RtlFreeHeap (hProcessHeap, 0, IData); + SetLastErrorByStatus (Status); + return(NULL); + } + IData->pFileInfo = (PVOID)IData + sizeof(KERNEL32_FIND_FILE_DATA); + IData->pFileInfo->FileIndex = 0; + + Status = NtQueryDirectoryFile (IData->DirectoryHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + (PVOID)IData->pFileInfo, + FIND_DATA_SIZE, + FileBothDirectoryInformation, + TRUE, + &PatternStr, + TRUE); + RtlFreeHeap (hProcessHeap, 0, PatternStr.Buffer); + if (!NT_SUCCESS(Status)) + { + DPRINT("Status %lx\n", Status); + RtlFreeHeap (hProcessHeap, 0, IData); + SetLastErrorByStatus (Status); + return NULL; + } + DPRINT("Found %.*S\n",IData->pFileInfo->FileNameLength, IData->pFileInfo->FileName); + + return IData; +} + + +HANDLE +STDCALL +FindFirstFileA ( + LPCTSTR lpFileName, + LPWIN32_FIND_DATAA lpFindFileData + ) +{ + PKERNEL32_FIND_FILE_DATA IData; + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + + RtlInitAnsiString (&FileName, + (LPSTR)lpFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + else + RtlOemStringToUnicodeString (&FileNameU, + &FileName, + TRUE); + + IData = InternalFindFirstFile (FileNameU.Buffer); + + RtlFreeUnicodeString (&FileNameU); + + if (IData == NULL) + { + DPRINT("Failing request\n"); + return INVALID_HANDLE_VALUE; + } + + DPRINT("IData->pFileInfo->FileNameLength %d\n", + IData->pFileInfo->FileNameLength); + + /* copy data into WIN32_FIND_DATA structure */ + lpFindFileData->dwFileAttributes = IData->pFileInfo->FileAttributes; + memcpy (&lpFindFileData->ftCreationTime, + &IData->pFileInfo->CreationTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastAccessTime, + &IData->pFileInfo->LastAccessTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastWriteTime, + &IData->pFileInfo->LastWriteTime, + sizeof(FILETIME)); + lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart; + lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart; + + FileNameU.Length = IData->pFileInfo->FileNameLength; + FileNameU.MaximumLength = FileNameU.Length + sizeof(WCHAR); + FileNameU.Buffer = IData->pFileInfo->FileName; + + FileName.Length = 0; + FileName.MaximumLength = MAX_PATH; + FileName.Buffer = lpFindFileData->cFileName; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, + &FileNameU, + FALSE); + else + RtlUnicodeStringToOemString (&FileName, + &FileNameU, + FALSE); + + DPRINT("IData->pFileInfo->ShortNameLength %d\n", + IData->pFileInfo->ShortNameLength); + + FileNameU.Length = IData->pFileInfo->ShortNameLength; + FileNameU.MaximumLength = FileNameU.Length + sizeof(WCHAR); + FileNameU.Buffer = IData->pFileInfo->ShortName; + + FileName.Length = 0; + FileName.MaximumLength = 14; + FileName.Buffer = lpFindFileData->cAlternateFileName; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, + &FileNameU, + FALSE); + else + RtlUnicodeStringToOemString (&FileName, + &FileNameU, + FALSE); + + return (HANDLE)IData; +} + + +WINBOOL +STDCALL +FindNextFileA ( + HANDLE hFindFile, + LPWIN32_FIND_DATAA lpFindFileData) +{ + PKERNEL32_FIND_FILE_DATA IData; + UNICODE_STRING FileNameU; + ANSI_STRING FileName; + + IData = (PKERNEL32_FIND_FILE_DATA)hFindFile; + if (IData == NULL) + { + return FALSE; + } + + if (!InternalFindNextFile (hFindFile)) + { + DPRINT("InternalFindNextFile() failed\n"); + return FALSE; + } + + DPRINT("IData->pFileInfo->FileNameLength %d\n", + IData->pFileInfo->FileNameLength); + + /* copy data into WIN32_FIND_DATA structure */ + lpFindFileData->dwFileAttributes = IData->pFileInfo->FileAttributes; + memcpy (&lpFindFileData->ftCreationTime, + &IData->pFileInfo->CreationTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastAccessTime, + &IData->pFileInfo->LastAccessTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastWriteTime, + &IData->pFileInfo->LastWriteTime, + sizeof(FILETIME)); + lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart; + lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart; + + FileNameU.Length = IData->pFileInfo->FileNameLength; + FileNameU.MaximumLength = FileNameU.Length + sizeof(WCHAR); + FileNameU.Buffer = IData->pFileInfo->FileName; + + FileName.Length = 0; + FileName.MaximumLength = MAX_PATH; + FileName.Buffer = lpFindFileData->cFileName; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, + &FileNameU, + FALSE); + else + RtlUnicodeStringToOemString (&FileName, + &FileNameU, + FALSE); + + DPRINT("IData->pFileInfo->ShortNameLength %d\n", + IData->pFileInfo->ShortNameLength); + + FileNameU.Length = IData->pFileInfo->ShortNameLength; + FileNameU.MaximumLength = FileNameU.Length + sizeof(WCHAR); + FileNameU.Buffer = IData->pFileInfo->ShortName; + + FileName.Length = 0; + FileName.MaximumLength = 14; + FileName.Buffer = lpFindFileData->cAlternateFileName; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, + &FileNameU, + FALSE); + else + RtlUnicodeStringToOemString (&FileName, + &FileNameU, + FALSE); + + return TRUE; +} + + +BOOL +STDCALL +FindClose ( + HANDLE hFindFile + ) +{ + PKERNEL32_FIND_FILE_DATA IData; + + DPRINT("FindClose(hFindFile %x)\n",hFindFile); + + if (!hFindFile || hFindFile == INVALID_HANDLE_VALUE) + { + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + IData = (PKERNEL32_FIND_FILE_DATA)hFindFile; + + CloseHandle (IData->DirectoryHandle); + RtlFreeHeap (hProcessHeap, 0, IData); + + return TRUE; +} + + +HANDLE +STDCALL +FindFirstFileW ( + LPCWSTR lpFileName, + LPWIN32_FIND_DATAW lpFindFileData + ) +{ + PKERNEL32_FIND_FILE_DATA IData; + + IData = InternalFindFirstFile (lpFileName); + if (IData == NULL) + { + DPRINT("Failing request\n"); + return INVALID_HANDLE_VALUE; + } + + /* copy data into WIN32_FIND_DATA structure */ + lpFindFileData->dwFileAttributes = IData->pFileInfo->FileAttributes; + memcpy (&lpFindFileData->ftCreationTime, + &IData->pFileInfo->CreationTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastAccessTime, + &IData->pFileInfo->LastAccessTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastWriteTime, + &IData->pFileInfo->LastWriteTime, + sizeof(FILETIME)); + lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart; + lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart; + memcpy (lpFindFileData->cFileName, + IData->pFileInfo->FileName, + IData->pFileInfo->FileNameLength); + lpFindFileData->cFileName[IData->pFileInfo->FileNameLength] = 0; + memcpy (lpFindFileData->cAlternateFileName, + IData->pFileInfo->ShortName, + IData->pFileInfo->ShortNameLength); + lpFindFileData->cAlternateFileName[IData->pFileInfo->ShortNameLength] = 0; + return IData; +} + + +WINBOOL +STDCALL +FindNextFileW ( + HANDLE hFindFile, + LPWIN32_FIND_DATAW lpFindFileData + ) +{ + PKERNEL32_FIND_FILE_DATA IData; + + IData = (PKERNEL32_FIND_FILE_DATA)hFindFile; + if (!InternalFindNextFile(hFindFile)) + { + DPRINT("Failing request\n"); + return FALSE; + } + + /* copy data into WIN32_FIND_DATA structure */ + lpFindFileData->dwFileAttributes = IData->pFileInfo->FileAttributes; + memcpy (&lpFindFileData->ftCreationTime, + &IData->pFileInfo->CreationTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastAccessTime, + &IData->pFileInfo->LastAccessTime, + sizeof(FILETIME)); + memcpy (&lpFindFileData->ftLastWriteTime, + &IData->pFileInfo->LastWriteTime, + sizeof(FILETIME)); + lpFindFileData->nFileSizeHigh = IData->pFileInfo->EndOfFile.u.HighPart; + lpFindFileData->nFileSizeLow = IData->pFileInfo->EndOfFile.u.LowPart; + memcpy (lpFindFileData->cFileName, + IData->pFileInfo->FileName, + IData->pFileInfo->FileNameLength); + lpFindFileData->cFileName[IData->pFileInfo->FileNameLength] = 0; + memcpy (lpFindFileData->cAlternateFileName, + IData->pFileInfo->ShortName, + IData->pFileInfo->ShortNameLength); + lpFindFileData->cAlternateFileName[IData->pFileInfo->ShortNameLength] = 0; + return TRUE; +} + + +HANDLE +STDCALL +FindFirstFileExW ( + LPCWSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ) +{ + /* FIXME */ + return (HANDLE) 0; +} + + +HANDLE +STDCALL +FindFirstFileExA ( + LPCSTR lpFileName, + FINDEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFindFileData, + FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + DWORD dwAdditionalFlags + ) +{ + /* FIXME */ + return (HANDLE) 0; +} + + +/* EOF */ diff --git a/lib/kernel32/file/iocompl.c b/lib/kernel32/file/iocompl.c new file mode 100644 index 0000000..3d06b40 --- /dev/null +++ b/lib/kernel32/file/iocompl.c @@ -0,0 +1,141 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/iocompl.c + * PURPOSE: Io Completion functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include +#include + + +#include + + +typedef struct _FILE_COMPLETION_INFORMATION { + HANDLE CompletionPort; + ULONG CompletionKey; +} FILE_COMPLETION_INFORMATION; +typedef FILE_COMPLETION_INFORMATION *PFILE_COMPLETION_INFORMATION; + + +VOID +STDCALL +FileIOCompletionRoutine( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPOVERLAPPED lpOverlapped + ); + + +HANDLE +STDCALL +CreateIoCompletionPort( + HANDLE FileHandle, + HANDLE ExistingCompletionPort, + DWORD CompletionKey, + DWORD NumberOfConcurrentThreads + ) +{ + HANDLE CompletionPort = NULL; + NTSTATUS errCode; + FILE_COMPLETION_INFORMATION CompletionInformation; + IO_STATUS_BLOCK IoStatusBlock; + + if ( ExistingCompletionPort == NULL && FileHandle == INVALID_HANDLE_VALUE ) { + SetLastErrorByStatus (STATUS_INVALID_PARAMETER); + return FALSE; + } + + if ( ExistingCompletionPort != NULL ) { + CompletionPort = ExistingCompletionPort; + } + else { + errCode = NtCreateIoCompletion(&CompletionPort,GENERIC_ALL,&IoStatusBlock,NumberOfConcurrentThreads); + if (!NT_SUCCESS(errCode) ) { + SetLastErrorByStatus (errCode); + return FALSE; + } + + } + if ( FileHandle != INVALID_HANDLE_VALUE ) { + + CompletionInformation.CompletionPort = CompletionPort; + CompletionInformation.CompletionKey = CompletionKey; + + errCode = NtSetInformationFile(FileHandle, &IoStatusBlock,&CompletionInformation,sizeof(FILE_COMPLETION_INFORMATION),FileCompletionInformation); + if ( !NT_SUCCESS(errCode) ) { + if ( ExistingCompletionPort == NULL ) + NtClose(CompletionPort); + SetLastErrorByStatus (errCode); + return FALSE; + } + } + + return CompletionPort; +} + + +WINBOOL +STDCALL +GetQueuedCompletionStatus( + HANDLE CompletionPort, + LPDWORD lpNumberOfBytesTransferred, + LPDWORD lpCompletionKey, + LPOVERLAPPED *lpOverlapped, + DWORD dwMilliseconds + ) +{ + NTSTATUS errCode; + ULONG CompletionStatus; + LARGE_INTEGER TimeToWait; + + errCode = NtRemoveIoCompletion(CompletionPort,(PULONG)lpCompletionKey,(PIO_STATUS_BLOCK)lpOverlapped,&CompletionStatus,&TimeToWait); + if (!NT_SUCCESS(errCode) ) { + SetLastErrorByStatus (errCode); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +PostQueuedCompletionStatus( + HANDLE CompletionPort, + DWORD dwNumberOfBytesTransferred, + DWORD dwCompletionKey, + LPOVERLAPPED lpOverlapped +) +{ + NTSTATUS errCode; + errCode = NtSetIoCompletion(CompletionPort, dwCompletionKey, (PIO_STATUS_BLOCK)lpOverlapped , 0, (PULONG)&dwNumberOfBytesTransferred ); + + if ( !NT_SUCCESS(errCode) ) { + SetLastErrorByStatus (errCode); + return FALSE; + } + return TRUE; +} + + +// this should be a place holder ?????????????????? +VOID +STDCALL +FileIOCompletionRoutine( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPOVERLAPPED lpOverlapped + ) +{ + return; +} + + +/* EOF */ diff --git a/lib/kernel32/file/lfile.c b/lib/kernel32/file/lfile.c new file mode 100644 index 0000000..6bbec15 --- /dev/null +++ b/lib/kernel32/file/lfile.c @@ -0,0 +1,208 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/lfile.c + * PURPOSE: Find functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + + +long +STDCALL +_hread( + HFILE hFile, + LPVOID lpBuffer, + long lBytes + ) +{ + DWORD NumberOfBytesRead; + + if (ReadFile( + (HANDLE) hFile, + (LPVOID) lpBuffer, + (DWORD) lBytes, + & NumberOfBytesRead, + NULL + ) == FALSE) + { + return -1; + } + return NumberOfBytesRead; +} + + +/* +//19990828.EA: aliased in DEF +UINT +STDCALL +_lread ( + HFILE fd, + LPVOID buffer, + UINT count + ) +{ + return _hread( + fd, + buffer, + count + ); +} +*/ + + +long +STDCALL +_hwrite ( + HFILE hFile, + LPCSTR lpBuffer, + long lBytes + ) +{ + DWORD NumberOfBytesWritten; + + if (lBytes == 0) + { + if ( SetEndOfFile((HANDLE) hFile ) == FALSE ) + { + return -1; + } + return 0; + } + if ( WriteFile( + (HANDLE) hFile, + (LPVOID) lpBuffer, + (DWORD) lBytes, + & NumberOfBytesWritten, + NULL + ) == FALSE ) + { + return -1; + } + return NumberOfBytesWritten; +} + + +/* +//19990828.EA: aliased in DEF + +UINT +STDCALL +_lwrite( + HFILE hFile, + LPCSTR lpBuffer, + UINT uBytes + ) +{ + return _hwrite(hFile,lpBuffer,uBytes); +} +*/ + + +HFILE +STDCALL +_lopen ( + LPCSTR lpPathName, + int iReadWrite + ) +{ + DWORD dwAccessMask = 0; + DWORD dwShareMode = 0; + + if ( (iReadWrite & OF_READWRITE ) == OF_READWRITE ) + dwAccessMask = GENERIC_READ | GENERIC_WRITE; + else if ( (iReadWrite & OF_READ ) == OF_READ ) + dwAccessMask = GENERIC_READ; + else if ( (iReadWrite & OF_WRITE ) == OF_WRITE ) + dwAccessMask = GENERIC_WRITE; + + if ((iReadWrite & OF_SHARE_COMPAT) == OF_SHARE_COMPAT ) + dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_DENY_NONE) == OF_SHARE_DENY_NONE) + dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_DENY_READ) == OF_SHARE_DENY_READ) + dwShareMode = FILE_SHARE_WRITE | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_DENY_WRITE) == OF_SHARE_DENY_WRITE ) + dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE; + else if ((iReadWrite & OF_SHARE_EXCLUSIVE) == OF_SHARE_EXCLUSIVE) + dwShareMode = 0; + + SetLastError (ERROR_SUCCESS); + return (HFILE) CreateFileA( + lpPathName, + dwAccessMask, + dwShareMode, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); +} + + +HFILE +STDCALL +_lcreat ( + LPCSTR lpPathName, + int iAttribute + ) +{ + + DWORD FileAttributes = 0; + + if ( iAttribute == 1 ) + FileAttributes |= FILE_ATTRIBUTE_NORMAL; + else if ( iAttribute == 2 ) + FileAttributes |= FILE_ATTRIBUTE_READONLY; + else if ( iAttribute == 3 ) + FileAttributes |= FILE_ATTRIBUTE_HIDDEN; + else if ( iAttribute == 4 ) + FileAttributes |= FILE_ATTRIBUTE_SYSTEM; + + return (HFILE) CreateFileA( + lpPathName, + GENERIC_ALL, + (FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, + CREATE_ALWAYS, + iAttribute, + NULL); +} + + +int +STDCALL +_lclose ( + HFILE hFile + ) +{ + if (CloseHandle ((HANDLE)hFile)) + { + return 0; + } + return -1; +} + + +LONG +STDCALL +_llseek( + HFILE hFile, + LONG lOffset, + int iOrigin + ) +{ + return SetFilePointer ( + (HANDLE) hFile, + lOffset, + NULL, + (DWORD) iOrigin); +} + +/* EOF */ diff --git a/lib/kernel32/file/lock.c b/lib/kernel32/file/lock.c new file mode 100644 index 0000000..4ec38d1 --- /dev/null +++ b/lib/kernel32/file/lock.c @@ -0,0 +1,175 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/file.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * GetTempFileName is modified from WINE [ Alexandre Juiliard ] + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* FIXME: the large integer manipulations in this file dont handle overflow */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +//#define NDEBUG +#include +#include + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +LockFile( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh + ) +{ + DWORD dwReserved; + OVERLAPPED Overlapped; + + Overlapped.Offset = dwFileOffsetLow; + Overlapped.OffsetHigh = dwFileOffsetHigh; + dwReserved = 0; + + return LockFileEx(hFile, LOCKFILE_FAIL_IMMEDIATELY|LOCKFILE_EXCLUSIVE_LOCK,dwReserved,nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, &Overlapped ) ; + +} + +WINBOOL +STDCALL +LockFileEx( + HANDLE hFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped + ) +{ + LARGE_INTEGER BytesToLock; + BOOL LockImmediate; + BOOL LockExclusive; + NTSTATUS errCode; + LARGE_INTEGER Offset; + + if(dwReserved != 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + lpOverlapped->Internal = STATUS_PENDING; + + Offset.u.LowPart = lpOverlapped->Offset; + Offset.u.HighPart = lpOverlapped->OffsetHigh; + + if ( (dwFlags & LOCKFILE_FAIL_IMMEDIATELY) == LOCKFILE_FAIL_IMMEDIATELY ) + LockImmediate = TRUE; + else + LockImmediate = FALSE; + + if ( (dwFlags & LOCKFILE_EXCLUSIVE_LOCK) == LOCKFILE_EXCLUSIVE_LOCK ) + LockExclusive = TRUE; + else + LockExclusive = FALSE; + + BytesToLock.u.LowPart = nNumberOfBytesToLockLow; + BytesToLock.u.HighPart = nNumberOfBytesToLockHigh; + + errCode = NtLockFile(hFile, + NULL, + NULL, + NULL, + (PIO_STATUS_BLOCK)lpOverlapped, + &Offset, + &BytesToLock, + NULL, + LockImmediate, + LockExclusive); + if ( !NT_SUCCESS(errCode) ) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + + return TRUE; + +} + +WINBOOL +STDCALL +UnlockFile( + HANDLE hFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh + ) +{ + DWORD dwReserved; + OVERLAPPED Overlapped; + Overlapped.Offset = dwFileOffsetLow; + Overlapped.OffsetHigh = dwFileOffsetHigh; + dwReserved = 0; + return UnlockFileEx(hFile, dwReserved, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh, &Overlapped); + +} + + + +WINBOOL +STDCALL +UnlockFileEx( + HANDLE hFile, + DWORD dwReserved, + DWORD nNumberOfBytesToUnLockLow, + DWORD nNumberOfBytesToUnLockHigh, + LPOVERLAPPED lpOverlapped + ) +{ + LARGE_INTEGER BytesToUnLock; + LARGE_INTEGER StartAddress; + NTSTATUS errCode; + + if(dwReserved != 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if ( lpOverlapped == NULL ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + BytesToUnLock.u.LowPart = nNumberOfBytesToUnLockLow; + BytesToUnLock.u.HighPart = nNumberOfBytesToUnLockHigh; + + StartAddress.u.LowPart = lpOverlapped->Offset; + StartAddress.u.HighPart = lpOverlapped->OffsetHigh; + + errCode = NtUnlockFile(hFile, + (PIO_STATUS_BLOCK)lpOverlapped, + &StartAddress, + &BytesToUnLock, + NULL); + if ( !NT_SUCCESS(errCode) ) { + SetLastErrorByStatus (errCode); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/file/mailslot.c b/lib/kernel32/file/mailslot.c new file mode 100644 index 0000000..e429cc6 --- /dev/null +++ b/lib/kernel32/file/mailslot.c @@ -0,0 +1,171 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/mailslot.c + * PURPOSE: Mailslot functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include +#include + +/* FUNCTIONS ****************************************************************/ + +HANDLE STDCALL +CreateMailslotA(LPCSTR lpName, + DWORD nMaxMessageSize, + DWORD lReadTimeout, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + HANDLE MailslotHandle; + UNICODE_STRING NameU; + ANSI_STRING NameA; + + RtlInitAnsiString(&NameA, (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE); + + MailslotHandle = CreateMailslotW(NameU.Buffer, + nMaxMessageSize, + lReadTimeout, + lpSecurityAttributes); + + RtlFreeUnicodeString(&NameU); + + return(MailslotHandle); +} + + +HANDLE STDCALL +CreateMailslotW(LPCWSTR lpName, + DWORD nMaxMessageSize, + DWORD lReadTimeout, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING MailslotName; + HANDLE MailslotHandle; + NTSTATUS Status; + BOOLEAN Result; + LARGE_INTEGER DefaultTimeOut; + IO_STATUS_BLOCK Iosb; + + Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName, + &MailslotName, + NULL, + NULL); + if (!Result) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return(INVALID_HANDLE_VALUE); + } + + DPRINT("Mailslot name: %wZ\n", &MailslotName); + + InitializeObjectAttributes(&ObjectAttributes, + &MailslotName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + DefaultTimeOut.QuadPart = lReadTimeout * 10000; + + Status = NtCreateMailslotFile(&MailslotHandle, + GENERIC_READ | SYNCHRONIZE | WRITE_DAC, + &ObjectAttributes, + &Iosb, + FILE_WRITE_THROUGH, + 0, + nMaxMessageSize, + &DefaultTimeOut); + + RtlFreeUnicodeString(&MailslotName); + + if (!NT_SUCCESS(Status)) + { + DPRINT("NtCreateMailslot failed (Status %x)!\n", Status); + SetLastErrorByStatus (Status); + return(INVALID_HANDLE_VALUE); + } + + return(MailslotHandle); +} + + +WINBOOL STDCALL +GetMailslotInfo(HANDLE hMailslot, + LPDWORD lpMaxMessageSize, + LPDWORD lpNextSize, + LPDWORD lpMessageCount, + LPDWORD lpReadTimeout) +{ + FILE_MAILSLOT_QUERY_INFORMATION Buffer; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Status = NtQueryInformationFile(hMailslot, + &Iosb, + &Buffer, + sizeof(FILE_MAILSLOT_QUERY_INFORMATION), + FileMailslotQueryInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtQueryInformationFile failed (Status %x)!\n", Status); + SetLastErrorByStatus (Status); + return(FALSE); + } + + if (lpMaxMessageSize != NULL) + { + *lpMaxMessageSize = Buffer.MaxMessageSize; + } + if (lpNextSize != NULL) + { + *lpNextSize = Buffer.NextSize; + } + if (lpMessageCount != NULL) + { + *lpMessageCount = Buffer.MessageCount; + } + if (lpReadTimeout != NULL) + { + *lpReadTimeout = (DWORD)(Buffer.Timeout.QuadPart / -10000); + } + + return(TRUE); +} + + +WINBOOL STDCALL +SetMailslotInfo(HANDLE hMailslot, + DWORD lReadTimeout) +{ + FILE_MAILSLOT_SET_INFORMATION Buffer; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Buffer.Timeout.QuadPart = lReadTimeout * -10000; + + Status = NtSetInformationFile(hMailslot, + &Iosb, + &Buffer, + sizeof(FILE_MAILSLOT_SET_INFORMATION), + FileMailslotSetInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtSetInformationFile failed (Status %x)!\n", Status); + SetLastErrorByStatus (Status); + return(FALSE); + } + + return(TRUE); +} + +/* EOF */ diff --git a/lib/kernel32/file/move.c b/lib/kernel32/file/move.c new file mode 100644 index 0000000..635ddae --- /dev/null +++ b/lib/kernel32/file/move.c @@ -0,0 +1,157 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/file.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +#define FILE_RENAME_SIZE MAX_PATH +sizeof(FILE_RENAME_INFORMATION) + + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +MoveFileA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName + ) +{ + return MoveFileExA (lpExistingFileName, + lpNewFileName, + MOVEFILE_COPY_ALLOWED); +} + + +WINBOOL +STDCALL +MoveFileExA ( + LPCSTR lpExistingFileName, + LPCSTR lpNewFileName, + DWORD dwFlags + ) +{ + UNICODE_STRING ExistingFileNameU; + UNICODE_STRING NewFileNameU; + ANSI_STRING ExistingFileName; + ANSI_STRING NewFileName; + WINBOOL Result; + + RtlInitAnsiString (&ExistingFileName, + (LPSTR)lpExistingFileName); + + RtlInitAnsiString (&NewFileName, + (LPSTR)lpNewFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + { + RtlAnsiStringToUnicodeString (&ExistingFileNameU, + &ExistingFileName, + TRUE); + RtlAnsiStringToUnicodeString (&NewFileNameU, + &NewFileName, + TRUE); + } + else + { + RtlOemStringToUnicodeString (&ExistingFileNameU, + &ExistingFileName, + TRUE); + RtlOemStringToUnicodeString (&NewFileNameU, + &NewFileName, + TRUE); + } + + Result = MoveFileExW (ExistingFileNameU.Buffer, + NewFileNameU.Buffer, + dwFlags); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + ExistingFileNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + NewFileNameU.Buffer); + + return Result; +} + + +WINBOOL +STDCALL +MoveFileW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName + ) +{ + return MoveFileExW (lpExistingFileName, + lpNewFileName, + MOVEFILE_COPY_ALLOWED); +} + + +WINBOOL +STDCALL +MoveFileExW ( + LPCWSTR lpExistingFileName, + LPCWSTR lpNewFileName, + DWORD dwFlags + ) +{ + HANDLE hFile = NULL; + IO_STATUS_BLOCK IoStatusBlock; + FILE_RENAME_INFORMATION *FileRename; + USHORT Buffer[FILE_RENAME_SIZE]; + NTSTATUS errCode; + + hFile = CreateFileW (lpExistingFileName, + GENERIC_ALL, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + FileRename = (FILE_RENAME_INFORMATION *)Buffer; + if ((dwFlags & MOVEFILE_REPLACE_EXISTING) == MOVEFILE_REPLACE_EXISTING) + FileRename->Replace = TRUE; + else + FileRename->Replace = FALSE; + + FileRename->FileNameLength = wcslen (lpNewFileName); + memcpy (FileRename->FileName, + lpNewFileName, + min(FileRename->FileNameLength, MAX_PATH)); + + errCode = NtSetInformationFile (hFile, + &IoStatusBlock, + FileRename, + FILE_RENAME_SIZE, + FileRenameInformation); + CloseHandle(hFile); + if (!NT_SUCCESS(errCode)) + { + if (CopyFileW (lpExistingFileName, + lpNewFileName, + FileRename->Replace)) + DeleteFileW (lpExistingFileName); + } + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/file/npipe.c b/lib/kernel32/file/npipe.c new file mode 100644 index 0000000..b3cf709 --- /dev/null +++ b/lib/kernel32/file/npipe.c @@ -0,0 +1,824 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/npipe.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +//#include +//#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +HANDLE STDCALL +CreateNamedPipeA(LPCSTR lpName, + DWORD dwOpenMode, + DWORD dwPipeMode, + DWORD nMaxInstances, + DWORD nOutBufferSize, + DWORD nInBufferSize, + DWORD nDefaultTimeOut, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + HANDLE NamedPipeHandle; + UNICODE_STRING NameU; + ANSI_STRING NameA; + + RtlInitAnsiString(&NameA, (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE); + + NamedPipeHandle = CreateNamedPipeW(NameU.Buffer, + dwOpenMode, + dwPipeMode, + nMaxInstances, + nOutBufferSize, + nInBufferSize, + nDefaultTimeOut, + lpSecurityAttributes); + + RtlFreeUnicodeString(&NameU); + + return(NamedPipeHandle); +} + + +HANDLE STDCALL +CreateNamedPipeW(LPCWSTR lpName, + DWORD dwOpenMode, + DWORD dwPipeMode, + DWORD nMaxInstances, + DWORD nOutBufferSize, + DWORD nInBufferSize, + DWORD nDefaultTimeOut, + LPSECURITY_ATTRIBUTES lpSecurityAttributes) +{ + UNICODE_STRING NamedPipeName; + BOOL Result; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE PipeHandle; + ACCESS_MASK DesiredAccess; + ULONG CreateOptions; + ULONG CreateDisposition; + BOOLEAN WriteModeMessage; + BOOLEAN ReadModeMessage; + BOOLEAN NonBlocking; + IO_STATUS_BLOCK Iosb; + ULONG ShareAccess; + LARGE_INTEGER DefaultTimeOut; + + Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName, + &NamedPipeName, + NULL, + NULL); + if (!Result) + { + SetLastError(ERROR_PATH_NOT_FOUND); + return(INVALID_HANDLE_VALUE); + } + + DPRINT("Pipe name: %wZ\n", &NamedPipeName); + DPRINT("Pipe name: %S\n", NamedPipeName.Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + &NamedPipeName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + DesiredAccess = 0; + + ShareAccess = 0; + + CreateDisposition = FILE_OPEN_IF; + + CreateOptions = 0; + if (dwOpenMode & FILE_FLAG_WRITE_THROUGH) + { + CreateOptions = CreateOptions | FILE_WRITE_THROUGH; + } + if (dwOpenMode & FILE_FLAG_OVERLAPPED) + { + CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_ALERT; + } + if (dwOpenMode & PIPE_ACCESS_DUPLEX) + { + CreateOptions = CreateOptions | FILE_PIPE_FULL_DUPLEX; + } + else if (dwOpenMode & PIPE_ACCESS_INBOUND) + { + CreateOptions = CreateOptions | FILE_PIPE_INBOUND; + } + else if (dwOpenMode & PIPE_ACCESS_OUTBOUND) + { + CreateOptions = CreateOptions | FILE_PIPE_OUTBOUND; + } + + if (dwPipeMode & PIPE_TYPE_BYTE) + { + WriteModeMessage = FALSE; + } + else if (dwPipeMode & PIPE_TYPE_MESSAGE) + { + WriteModeMessage = TRUE; + } + else + { + WriteModeMessage = FALSE; + } + + if (dwPipeMode & PIPE_READMODE_BYTE) + { + ReadModeMessage = FALSE; + } + else if (dwPipeMode & PIPE_READMODE_MESSAGE) + { + ReadModeMessage = TRUE; + } + else + { + ReadModeMessage = FALSE; + } + + if (dwPipeMode & PIPE_WAIT) + { + NonBlocking = FALSE; + } + else if (dwPipeMode & PIPE_NOWAIT) + { + NonBlocking = TRUE; + } + else + { + NonBlocking = FALSE; + } + + if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES) + { + nMaxInstances = ULONG_MAX; + } + + DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000; + + Status = NtCreateNamedPipeFile(&PipeHandle, + DesiredAccess, + &ObjectAttributes, + &Iosb, + ShareAccess, + CreateDisposition, + CreateOptions, + WriteModeMessage, + ReadModeMessage, + NonBlocking, + nMaxInstances, + nInBufferSize, + nOutBufferSize, + &DefaultTimeOut); + + RtlFreeUnicodeString(&NamedPipeName); + + if (!NT_SUCCESS(Status)) + { + DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status); + SetLastErrorByStatus (Status); + return(INVALID_HANDLE_VALUE); + } + + return(PipeHandle); +} + + +BOOL STDCALL +WaitNamedPipeA(LPCSTR lpNamedPipeName, + DWORD nTimeOut) +{ + BOOL r; + UNICODE_STRING NameU; + ANSI_STRING NameA; + + RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName); + RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE); + + r = WaitNamedPipeW(NameU.Buffer, nTimeOut); + + RtlFreeUnicodeString(&NameU); + + return(r); +} + + +BOOL STDCALL +WaitNamedPipeW(LPCWSTR lpNamedPipeName, + DWORD nTimeOut) +{ + UNICODE_STRING NamedPipeName; + BOOL r; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + NPFS_WAIT_PIPE WaitPipe; + HANDLE FileHandle; + IO_STATUS_BLOCK Iosb; + + r = RtlDosPathNameToNtPathName_U((LPWSTR)lpNamedPipeName, + &NamedPipeName, + NULL, + NULL); + + if (!r) + { + return(FALSE); + } + + InitializeObjectAttributes(&ObjectAttributes, + &NamedPipeName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenFile(&FileHandle, + FILE_GENERIC_READ, + &ObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return(FALSE); + } + + WaitPipe.Timeout.QuadPart = nTimeOut * -10000; + + Status = NtFsControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_WAIT, + &WaitPipe, + sizeof(WaitPipe), + NULL, + 0); + NtClose(FileHandle); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return(FALSE); + } + + return(TRUE); +} + + +BOOL STDCALL +ConnectNamedPipe(HANDLE hNamedPipe, + LPOVERLAPPED lpOverlapped) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK Iosb; + HANDLE hEvent; + NTSTATUS Status; + + if (lpOverlapped != NULL) + { + lpOverlapped->Internal = STATUS_PENDING; + hEvent = lpOverlapped->hEvent; + IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped; + } + else + { + IoStatusBlock = &Iosb; + hEvent = NULL; + } + + Status = NtFsControlFile(hNamedPipe, + hEvent, + NULL, + NULL, + IoStatusBlock, + FSCTL_PIPE_LISTEN, + NULL, + 0, + NULL, + 0); + if ((lpOverlapped == NULL) && (Status == STATUS_PENDING)) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + Status = Iosb.Status; + } + if ((!NT_SUCCESS(Status) && Status != STATUS_PIPE_CONNECTED) || + (Status == STATUS_PENDING)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); +} + + +BOOL STDCALL +SetNamedPipeHandleState(HANDLE hNamedPipe, + LPDWORD lpMode, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout) +{ + NPFS_GET_STATE GetState; + NPFS_SET_STATE SetState; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_GET_STATE, + NULL, + 0, + &GetState, + sizeof(NPFS_GET_STATE)); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + } + + if (lpMode != NULL) + { + if ((*lpMode) & PIPE_READMODE_MESSAGE) + { + SetState.ReadModeMessage = TRUE; + } + else + { + SetState.ReadModeMessage = FALSE; + } + if ((*lpMode) & PIPE_NOWAIT) + { + SetState.NonBlocking = TRUE; + } + else + { + SetState.NonBlocking = FALSE; + } + SetState.WriteModeMessage = GetState.WriteModeMessage; + } + else + { + SetState.ReadModeMessage = GetState.ReadModeMessage; + SetState.WriteModeMessage = GetState.WriteModeMessage; + SetState.NonBlocking = SetState.NonBlocking; + } + + if (lpMaxCollectionCount != NULL) + { + SetState.InBufferSize = *lpMaxCollectionCount; + } + else + { + SetState.InBufferSize = GetState.InBufferSize; + } + + SetState.OutBufferSize = GetState.OutBufferSize; + + if (lpCollectDataTimeout != NULL) + { + SetState.Timeout.QuadPart = (*lpCollectDataTimeout) * -10000; + } + else + { + SetState.Timeout = GetState.Timeout; + } + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_SET_STATE, + &SetState, + sizeof(NPFS_SET_STATE), + NULL, + 0); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + } + + return(TRUE); +} + + +BOOL STDCALL +CallNamedPipeA(LPCSTR lpNamedPipeName, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + DWORD nTimeOut) +{ + UNICODE_STRING PipeName; + BOOL Result; + + RtlCreateUnicodeStringFromAsciiz(&PipeName, + (LPSTR)lpNamedPipeName); + + Result = CallNamedPipeW(PipeName.Buffer, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesRead, + nTimeOut); + + RtlFreeUnicodeString(&PipeName); + + return(Result); +} + + +BOOL STDCALL +CallNamedPipeW(LPCWSTR lpNamedPipeName, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + DWORD nTimeOut) +{ + HANDLE hPipe = INVALID_HANDLE_VALUE; + BOOL bRetry = TRUE; + BOOL bError = FALSE; + DWORD dwPipeMode; + + while (TRUE) + { + hPipe = CreateFileW(lpNamedPipeName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hPipe != INVALID_HANDLE_VALUE) + break; + + if (bRetry == FALSE) + return(FALSE); + + WaitNamedPipeW(lpNamedPipeName, + nTimeOut); + + bRetry = FALSE; + } + + dwPipeMode = PIPE_READMODE_MESSAGE; + bError = SetNamedPipeHandleState(hPipe, + &dwPipeMode, + NULL, + NULL); + if (!bError) + { + CloseHandle(hPipe); + return(FALSE); + } + + bError = TransactNamedPipe(hPipe, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, + lpBytesRead, + NULL); + CloseHandle(hPipe); + + return(bError); +} + + +BOOL STDCALL +DisconnectNamedPipe(HANDLE hNamedPipe) +{ + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_DISCONNECT, + NULL, + 0, + NULL, + 0); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + } + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); +} + + +WINBOOL STDCALL +GetNamedPipeHandleStateW(HANDLE hNamedPipe, + LPDWORD lpState, + LPDWORD lpCurInstances, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout, + LPWSTR lpUserName, + DWORD nMaxUserNameSize) +{ + FILE_PIPE_LOCAL_INFORMATION LocalInfo; + FILE_PIPE_INFORMATION PipeInfo; + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + if (lpState != NULL) + { + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &PipeInfo, + sizeof(FILE_PIPE_INFORMATION), + FilePipeInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + *lpState = 0; /* FIXME */ + } + + if (lpCurInstances != NULL) + { + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &LocalInfo, + sizeof(FILE_PIPE_LOCAL_INFORMATION), + FilePipeLocalInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + *lpCurInstances = min(LocalInfo.CurrentInstances, 255); + } + + + /* FIXME: retrieve remaining information */ + + + return(TRUE); +} + + +WINBOOL STDCALL +GetNamedPipeHandleStateA(HANDLE hNamedPipe, + LPDWORD lpState, + LPDWORD lpCurInstances, + LPDWORD lpMaxCollectionCount, + LPDWORD lpCollectDataTimeout, + LPSTR lpUserName, + DWORD nMaxUserNameSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +GetNamedPipeInfo(HANDLE hNamedPipe, + LPDWORD lpFlags, + LPDWORD lpOutBufferSize, + LPDWORD lpInBufferSize, + LPDWORD lpMaxInstances) +{ + FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation; + IO_STATUS_BLOCK StatusBlock; + NTSTATUS Status; + + Status = NtQueryInformationFile(hNamedPipe, + &StatusBlock, + &PipeLocalInformation, + sizeof(FILE_PIPE_LOCAL_INFORMATION), + FilePipeLocalInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + if (lpFlags != NULL) + { + *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END; + *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE; + } + + if (lpOutBufferSize != NULL) + *lpOutBufferSize = PipeLocalInformation.OutboundQuota; + + if (lpInBufferSize != NULL) + *lpInBufferSize = PipeLocalInformation.InboundQuota; + + if (lpMaxInstances != NULL) + { + if (PipeLocalInformation.MaximumInstances >= 255) + *lpMaxInstances = PIPE_UNLIMITED_INSTANCES; + else + *lpMaxInstances = PipeLocalInformation.MaximumInstances; + } + + return(TRUE); +} + + +BOOL STDCALL +PeekNamedPipe(HANDLE hNamedPipe, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesRead, + LPDWORD lpTotalBytesAvail, + LPDWORD lpBytesLeftThisMessage) +{ + PFILE_PIPE_PEEK_BUFFER Buffer; + IO_STATUS_BLOCK Iosb; + ULONG BufferSize; + NTSTATUS Status; + + BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferSize); + + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &Iosb, + FSCTL_PIPE_PEEK, + NULL, + 0, + Buffer, + BufferSize); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hNamedPipe, + FALSE, + NULL); + if (NT_SUCCESS(Status)) + Status = Iosb.Status; + } + + if (Status == STATUS_BUFFER_OVERFLOW) + { + Status = STATUS_SUCCESS; + } + + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + SetLastErrorByStatus(Status); + return(FALSE); + } + + if (lpTotalBytesAvail != NULL) + { + *lpTotalBytesAvail = Buffer->ReadDataAvailable; + } + + if (lpBytesRead != NULL) + { + *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER); + } + + if (lpBytesLeftThisMessage != NULL) + { + *lpBytesLeftThisMessage = Buffer->MessageLength - + (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)); + } + + if (lpBuffer != NULL) + { + memcpy(lpBuffer, Buffer->Data, + min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER))); + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + + return(TRUE); +} + + +BOOL STDCALL +TransactNamedPipe(HANDLE hNamedPipe, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + LPDWORD lpBytesRead, + LPOVERLAPPED lpOverlapped) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + if (lpOverlapped == NULL) + { + Status = NtFsControlFile(hNamedPipe, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_PIPE_TRANSCEIVE, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(hNamedPipe, + 0, + FALSE); + Status = IoStatusBlock.Status; + } + if (NT_SUCCESS(Status)) + { + *lpBytesRead = IoStatusBlock.Information; + } + } + else + { + lpOverlapped->Internal = STATUS_PENDING; + + Status = NtFsControlFile(hNamedPipe, + lpOverlapped->hEvent, + NULL, + NULL, + (PIO_STATUS_BLOCK)lpOverlapped, + FSCTL_PIPE_TRANSCEIVE, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize); + } + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + return(TRUE); +} + +/* EOF */ diff --git a/lib/kernel32/file/pipe.c b/lib/kernel32/file/pipe.c new file mode 100644 index 0000000..4ff0c88 --- /dev/null +++ b/lib/kernel32/file/pipe.c @@ -0,0 +1,106 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/create.c + * PURPOSE: Directory functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* GLOBALS ******************************************************************/ + +ULONG ProcessPipeId = 0; + +/* FUNCTIONS ****************************************************************/ + +BOOL STDCALL CreatePipe(PHANDLE hReadPipe, + PHANDLE hWritePipe, + LPSECURITY_ATTRIBUTES lpPipeAttributes, + DWORD nSize) +{ + WCHAR Buffer[64]; + UNICODE_STRING PipeName; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK StatusBlock; + LARGE_INTEGER DefaultTimeout; + NTSTATUS Status; + HANDLE ReadPipeHandle; + HANDLE WritePipeHandle; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + + DefaultTimeout.QuadPart = 300000000; /* 30 seconds */ + + ProcessPipeId++; + swprintf(Buffer, + L"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x", + NtCurrentTeb()->Cid.UniqueProcess, + ProcessPipeId); + RtlInitUnicodeString (&PipeName, + Buffer); + + if (lpPipeAttributes) + { + SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor; + } + + InitializeObjectAttributes(&ObjectAttributes, + &PipeName, + OBJ_CASE_INSENSITIVE, + NULL, + SecurityDescriptor); + if (lpPipeAttributes) + { + if(lpPipeAttributes->bInheritHandle) + ObjectAttributes.Attributes |= OBJ_INHERIT; + if (lpPipeAttributes->lpSecurityDescriptor) + ObjectAttributes.SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor; + } + + Status = NtCreateNamedPipeFile(&ReadPipeHandle, + FILE_GENERIC_READ, + &ObjectAttributes, + &StatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + FILE_SYNCHRONOUS_IO_NONALERT, + FALSE, + FALSE, + FALSE, + 1, + nSize, + nSize, + &DefaultTimeout); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + Status = NtOpenFile(&WritePipeHandle, + FILE_GENERIC_WRITE, + &ObjectAttributes, + &StatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + { + NtClose(ReadPipeHandle); + SetLastErrorByStatus(Status); + return FALSE; + } + + *hReadPipe = ReadPipeHandle; + *hWritePipe = WritePipeHandle; + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/file/rw.c b/lib/kernel32/file/rw.c new file mode 100644 index 0000000..7e43803 --- /dev/null +++ b/lib/kernel32/file/rw.c @@ -0,0 +1,248 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/rw.c + * PURPOSE: Read/write functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* FUNCTIONS ****************************************************************/ + +WINBOOL STDCALL WriteFile(HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, + LPOVERLAPPED lpOverLapped) +{ + HANDLE hEvent = NULL; + LARGE_INTEGER Offset; + NTSTATUS errCode; + IO_STATUS_BLOCK IIosb; + PIO_STATUS_BLOCK IoStatusBlock; + PLARGE_INTEGER ptrOffset; + + DPRINT("WriteFile(hFile %x)\n",hFile); + + if (IsConsoleHandle(hFile)) + { + return(WriteConsoleA(hFile, + lpBuffer, + nNumberOfBytesToWrite, + lpNumberOfBytesWritten, + NULL)); + } + + if (lpOverLapped != NULL) + { + Offset.u.LowPart = lpOverLapped->Offset; + Offset.u.HighPart = lpOverLapped->OffsetHigh; + lpOverLapped->Internal = STATUS_PENDING; + hEvent = lpOverLapped->hEvent; + IoStatusBlock = (PIO_STATUS_BLOCK)lpOverLapped; + ptrOffset = &Offset; + } + else + { + ptrOffset = NULL; + IoStatusBlock = &IIosb; + Offset.QuadPart = 0; + } + + errCode = NtWriteFile(hFile, + hEvent, + NULL, + NULL, + IoStatusBlock, + (PVOID)lpBuffer, + nNumberOfBytesToWrite, + ptrOffset, + NULL); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + DPRINT("WriteFile() failed\n"); + return FALSE; + } + if (lpNumberOfBytesWritten != NULL ) + { + *lpNumberOfBytesWritten = IoStatusBlock->Information; + } + DPRINT("WriteFile() succeeded\n"); + return(TRUE); +} + + + +WINBOOL STDCALL ReadFile(HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverLapped) +{ + HANDLE hEvent = NULL; + LARGE_INTEGER Offset; + NTSTATUS errCode; + IO_STATUS_BLOCK IIosb; + PIO_STATUS_BLOCK IoStatusBlock; + PLARGE_INTEGER ptrOffset; + + if (IsConsoleHandle(hFile)) + { + return(ReadConsoleA(hFile, + lpBuffer, + nNumberOfBytesToRead, + lpNumberOfBytesRead, + NULL)); + } + + if (lpOverLapped != NULL) + { + Offset.u.LowPart = lpOverLapped->Offset; + Offset.u.HighPart = lpOverLapped->OffsetHigh; + lpOverLapped->Internal = STATUS_PENDING; + hEvent = lpOverLapped->hEvent; + IoStatusBlock = (PIO_STATUS_BLOCK)lpOverLapped; + ptrOffset = &Offset; + } + else + { + ptrOffset = NULL; + IoStatusBlock = &IIosb; + } + + errCode = NtReadFile(hFile, + hEvent, + NULL, + NULL, + IoStatusBlock, + lpBuffer, + nNumberOfBytesToRead, + ptrOffset, + NULL); + + if (errCode != STATUS_PENDING && lpNumberOfBytesRead != NULL) + { + *lpNumberOfBytesRead = IoStatusBlock->Information; + } + + if (!NT_SUCCESS(errCode) && errCode != STATUS_END_OF_FILE) + { + SetLastErrorByStatus (errCode); + return(FALSE); + } + return(TRUE); +} + +VOID STDCALL ApcRoutine(PVOID ApcContext, + struct _IO_STATUS_BLOCK* IoStatusBlock, + ULONG NumberOfBytesTransfered) +{ + DWORD dwErrorCode; + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine = + (LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext; + + dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); + lpCompletionRoutine(dwErrorCode, + NumberOfBytesTransfered, + (LPOVERLAPPED)IoStatusBlock); +} + + +WINBOOL STDCALL +WriteFileEx (HANDLE hFile, + LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPOVERLAPPED lpOverLapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + + LARGE_INTEGER Offset; + NTSTATUS errCode; + PIO_STATUS_BLOCK IoStatusBlock; + PLARGE_INTEGER ptrOffset; + + DPRINT("WriteFileEx(hFile %x)\n",hFile); + + if (lpOverLapped == NULL) + return FALSE; + + Offset.u.LowPart = lpOverLapped->Offset; + Offset.u.HighPart = lpOverLapped->OffsetHigh; + lpOverLapped->Internal = STATUS_PENDING; + IoStatusBlock = (PIO_STATUS_BLOCK)lpOverLapped; + ptrOffset = &Offset; + + errCode = NtWriteFile(hFile, + NULL, + ApcRoutine, + lpCompletionRoutine, + IoStatusBlock, + (PVOID)lpBuffer, + nNumberOfBytesToWrite, + ptrOffset, + NULL); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + DPRINT("WriteFileEx() failed\n"); + return FALSE; + } + + DPRINT("WriteFileEx() succeeded\n"); + return(TRUE); +} + +WINBOOL STDCALL ReadFileEx(HANDLE hFile, + LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPOVERLAPPED lpOverLapped, + LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + LARGE_INTEGER Offset; + NTSTATUS errCode; + PIO_STATUS_BLOCK IoStatusBlock; + PLARGE_INTEGER ptrOffset; + + if (lpOverLapped == NULL) + return FALSE; + + Offset.u.LowPart = lpOverLapped->Offset; + Offset.u.HighPart = lpOverLapped->OffsetHigh; + lpOverLapped->Internal = STATUS_PENDING; + IoStatusBlock = (PIO_STATUS_BLOCK)lpOverLapped; + ptrOffset = &Offset; + + errCode = NtReadFile(hFile, + NULL, + ApcRoutine, + lpCompletionRoutine, + IoStatusBlock, + lpBuffer, + nNumberOfBytesToRead, + ptrOffset, + NULL); + + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return(FALSE); + } + return(TRUE); +} + +/* EOF */ diff --git a/lib/kernel32/file/tape.c b/lib/kernel32/file/tape.c new file mode 100644 index 0000000..372d07e --- /dev/null +++ b/lib/kernel32/file/tape.c @@ -0,0 +1,143 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/tape.c + * PURPOSE: Tape functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * GetTempFileName is modified from WINE [ Alexandre Juiliard ] + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include +#include + +/* FUNCTIONS ****************************************************************/ + +DWORD +STDCALL +CreateTapePartition ( + HANDLE hDevice, + DWORD dwPartitionMethod, + DWORD dwCount, + DWORD dwSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD +STDCALL +EraseTape ( + HANDLE hDevice, + DWORD dwEraseType, + WINBOOL bImmediate + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD +STDCALL +GetTapeParameters ( + HANDLE hDevice, + DWORD dwOperation, + LPDWORD lpdwSize, + LPVOID lpTapeInformation + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetTapeStatus ( + HANDLE hDevice + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD +STDCALL +PrepareTape ( + HANDLE hDevice, + DWORD dwOperation, + WINBOOL bImmediate + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD +STDCALL +SetTapeParameters ( + HANDLE hDevice, + DWORD dwOperation, + LPVOID lpTapeInformation + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +SetTapePosition ( + HANDLE hDevice, + DWORD dwPositionMethod, + DWORD dwPartition, + DWORD dwOffsetLow, + DWORD dwOffsetHigh, + WINBOOL bImmediate + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +DWORD +STDCALL +WriteTapemark ( + HANDLE hDevice, + DWORD dwTapemarkType, + DWORD dwTapemarkCount, + WINBOOL bImmediate + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD +STDCALL +GetTapePosition ( + HANDLE hDevice, + DWORD dwPositionType, + LPDWORD lpdwPartition, + LPDWORD lpdwOffsetLow, + LPDWORD lpdwOffsetHigh + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* EOF */ diff --git a/lib/kernel32/file/volume.c b/lib/kernel32/file/volume.c new file mode 100644 index 0000000..1852032 --- /dev/null +++ b/lib/kernel32/file/volume.c @@ -0,0 +1,709 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/volume.c + * PURPOSE: File volume functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Erik Bos, Alexandre Julliard : + * GetLogicalDriveStringsA, + * GetLogicalDriveStringsW, GetLogicalDrives + * UPDATE HISTORY: + * Created 01/11/98 + */ +//WINE copyright notice: +/* + * DOS drives handling functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include + +#define NDEBUG +#include +#include + + +#define MAX_DOS_DRIVES 26 + +HANDLE InternalOpenDirW(PWCHAR DirName, BOOLEAN Write) +{ + UNICODE_STRING NtPathU; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS errCode; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE hFile; + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)DirName, + &NtPathU, + NULL, + NULL)) + { + DPRINT("Invalid path\n"); + SetLastError(ERROR_BAD_PATHNAME); + return INVALID_HANDLE_VALUE; + } + + InitializeObjectAttributes(&ObjectAttributes, + &NtPathU, + Write ? FILE_WRITE_ATTRIBUTES : FILE_READ_ATTRIBUTES, + NULL, + NULL); + + errCode = NtCreateFile (&hFile, + Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + + RtlFreeUnicodeString(&NtPathU); + + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return INVALID_HANDLE_VALUE; + } + return hFile; +} + +DWORD STDCALL +GetLogicalDriveStringsA(DWORD nBufferLength, + LPSTR lpBuffer) +{ + DWORD drive, count; + DWORD dwDriveMap; + + dwDriveMap = SharedUserData->DosDeviceMap; + + for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) + { + if (dwDriveMap & (1<DosDeviceMap; + + for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) + { + if (dwDriveMap & (1<DosDeviceMap); +} + + +WINBOOL STDCALL +GetDiskFreeSpaceA ( + LPCSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters + ) +{ + UNICODE_STRING RootPathNameU; + ANSI_STRING RootPathName; + WINBOOL Result; + + RtlInitAnsiString (&RootPathName, + (LPSTR)lpRootPathName); + + RtlInitUnicodeString (&RootPathNameU, + NULL); + + if (lpRootPathName) + { + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + else + RtlOemStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + } + + Result = GetDiskFreeSpaceW (RootPathNameU.Buffer, + lpSectorsPerCluster, + lpBytesPerSector, + lpNumberOfFreeClusters, + lpTotalNumberOfClusters); + + if (lpRootPathName) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + RootPathNameU.Buffer); + } + + return Result; +} + + +WINBOOL STDCALL +GetDiskFreeSpaceW( + LPCWSTR lpRootPathName, + LPDWORD lpSectorsPerCluster, + LPDWORD lpBytesPerSector, + LPDWORD lpNumberOfFreeClusters, + LPDWORD lpTotalNumberOfClusters + ) +{ + FILE_FS_SIZE_INFORMATION FileFsSize; + IO_STATUS_BLOCK IoStatusBlock; + WCHAR RootPathName[MAX_PATH]; + HANDLE hFile; + NTSTATUS errCode; + + if (lpRootPathName) + { + wcsncpy (RootPathName, lpRootPathName, 3); + } + else + { + GetCurrentDirectoryW (MAX_PATH, RootPathName); + RootPathName[3] = 0; + } + + if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW((PWCHAR)lpRootPathName, FALSE))) + { + return FALSE; + } + + + errCode = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + &FileFsSize, + sizeof(FILE_FS_SIZE_INFORMATION), + FileFsSizeInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus (errCode); + return FALSE; + } + + *lpBytesPerSector = FileFsSize.BytesPerSector; + *lpSectorsPerCluster = FileFsSize.SectorsPerAllocationUnit; + *lpNumberOfFreeClusters = FileFsSize.AvailableAllocationUnits.u.LowPart; + *lpTotalNumberOfClusters = FileFsSize.TotalAllocationUnits.u.LowPart; + CloseHandle(hFile); + return TRUE; +} + + +WINBOOL STDCALL +GetDiskFreeSpaceExA ( + LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes + ) +{ + UNICODE_STRING DirectoryNameU; + ANSI_STRING DirectoryName; + WINBOOL Result; + + RtlInitAnsiString (&DirectoryName, + (LPSTR)lpDirectoryName); + + RtlInitUnicodeString (&DirectoryNameU, + NULL); + + if (lpDirectoryName) + { + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&DirectoryNameU, + &DirectoryName, + TRUE); + else + RtlOemStringToUnicodeString (&DirectoryNameU, + &DirectoryName, + TRUE); + } + + Result = GetDiskFreeSpaceExW (DirectoryNameU.Buffer, + lpFreeBytesAvailableToCaller, + lpTotalNumberOfBytes, + lpTotalNumberOfFreeBytes); + + if (lpDirectoryName) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DirectoryNameU.Buffer); + } + + return Result; +} + + +WINBOOL STDCALL +GetDiskFreeSpaceExW( + LPCWSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes + ) +{ + FILE_FS_SIZE_INFORMATION FileFsSize; + IO_STATUS_BLOCK IoStatusBlock; + ULARGE_INTEGER BytesPerCluster; + WCHAR RootPathName[MAX_PATH]; + HANDLE hFile; + NTSTATUS errCode; + + if (lpDirectoryName) + { + wcsncpy (RootPathName, lpDirectoryName, 3); + } + else + { + GetCurrentDirectoryW (MAX_PATH, RootPathName); + RootPathName[3] = 0; + } + + if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW(lpDirectoryName, FALSE))) + { + return FALSE; + } + + errCode = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + &FileFsSize, + sizeof(FILE_FS_SIZE_INFORMATION), + FileFsSizeInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus (errCode); + return FALSE; + } + + BytesPerCluster.QuadPart = + FileFsSize.BytesPerSector * FileFsSize.SectorsPerAllocationUnit; + + // FIXME: Use quota information + if (lpFreeBytesAvailableToCaller) + lpFreeBytesAvailableToCaller->QuadPart = + BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart; + + if (lpTotalNumberOfBytes) + lpTotalNumberOfBytes->QuadPart = + BytesPerCluster.QuadPart * FileFsSize.TotalAllocationUnits.QuadPart; + if (lpTotalNumberOfFreeBytes) + lpTotalNumberOfFreeBytes->QuadPart = + BytesPerCluster.QuadPart * FileFsSize.AvailableAllocationUnits.QuadPart; + + CloseHandle(hFile); + return TRUE; +} + + +UINT STDCALL +GetDriveTypeA(LPCSTR lpRootPathName) +{ + UNICODE_STRING RootPathNameU; + ANSI_STRING RootPathName; + UINT Result; + + RtlInitAnsiString (&RootPathName, + (LPSTR)lpRootPathName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + else + RtlOemStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + + Result = GetDriveTypeW (RootPathNameU.Buffer); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + RootPathNameU.Buffer); + + return Result; +} + +UINT STDCALL +GetDriveTypeW(LPCWSTR lpRootPathName) +{ + FILE_FS_DEVICE_INFORMATION FileFsDevice; + IO_STATUS_BLOCK IoStatusBlock; + + HANDLE hFile; + NTSTATUS errCode; + + hFile = InternalOpenDirW(lpRootPathName, FALSE); + if (hFile == INVALID_HANDLE_VALUE) + { + return 0; + } + + errCode = NtQueryVolumeInformationFile (hFile, + &IoStatusBlock, + &FileFsDevice, + sizeof(FILE_FS_DEVICE_INFORMATION), + FileFsDeviceInformation); + if (!NT_SUCCESS(errCode)) + { + CloseHandle(hFile); + SetLastErrorByStatus (errCode); + return 0; + } + CloseHandle(hFile); + return (UINT)FileFsDevice.DeviceType; +} + + +WINBOOL STDCALL +GetVolumeInformationA( + LPCSTR lpRootPathName, + LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize + ) +{ + UNICODE_STRING RootPathNameU; + UNICODE_STRING FileSystemNameU; + UNICODE_STRING VolumeNameU; + ANSI_STRING RootPathName; + ANSI_STRING VolumeName; + ANSI_STRING FileSystemName; + WINBOOL Result; + + RtlInitAnsiString (&RootPathName, + (LPSTR)lpRootPathName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + else + RtlOemStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + + VolumeNameU.Length = 0; + VolumeNameU.MaximumLength = nVolumeNameSize * sizeof(WCHAR); + VolumeNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + VolumeNameU.MaximumLength); + + FileSystemNameU.Length = 0; + FileSystemNameU.MaximumLength = nFileSystemNameSize * sizeof(WCHAR); + FileSystemNameU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + FileSystemNameU.MaximumLength); + + Result = GetVolumeInformationW (RootPathNameU.Buffer, + VolumeNameU.Buffer, + nVolumeNameSize, + lpVolumeSerialNumber, + lpMaximumComponentLength, + lpFileSystemFlags, + FileSystemNameU.Buffer, + nFileSystemNameSize); + + if (Result) + { + VolumeNameU.Length = wcslen(VolumeNameU.Buffer) * sizeof(WCHAR); + VolumeName.Length = 0; + VolumeName.MaximumLength = nVolumeNameSize; + VolumeName.Buffer = lpVolumeNameBuffer; + + FileSystemNameU.Length = wcslen(FileSystemNameU.Buffer) * sizeof(WCHAR); + FileSystemName.Length = 0; + FileSystemName.MaximumLength = nFileSystemNameSize; + FileSystemName.Buffer = lpFileSystemNameBuffer; + + /* convert unicode strings to ansi (or oem) */ + if (bIsFileApiAnsi) + { + RtlUnicodeStringToAnsiString (&VolumeName, + &VolumeNameU, + FALSE); + RtlUnicodeStringToAnsiString (&FileSystemName, + &FileSystemNameU, + FALSE); + } + else + { + RtlUnicodeStringToOemString (&VolumeName, + &VolumeNameU, + FALSE); + RtlUnicodeStringToOemString (&FileSystemName, + &FileSystemNameU, + FALSE); + } + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + RootPathNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VolumeNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + FileSystemNameU.Buffer); + + return Result; +} + + + + +#define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION)) + +#define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) + + +WINBOOL STDCALL +GetVolumeInformationW( + LPCWSTR lpRootPathName, + LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, + LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, + LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, + DWORD nFileSystemNameSize + ) +{ + PFILE_FS_VOLUME_INFORMATION FileFsVolume; + PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + USHORT Buffer[FS_VOLUME_BUFFER_SIZE]; + USHORT Buffer2[FS_ATTRIBUTE_BUFFER_SIZE]; + + HANDLE hFile; + NTSTATUS errCode; + + FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer; + FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer2; + + DPRINT("FileFsVolume %p\n", FileFsVolume); + DPRINT("FileFsAttribute %p\n", FileFsAttribute); + + hFile = InternalOpenDirW(lpRootPathName, FALSE); + if (hFile == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + DPRINT("hFile: %x\n", hFile); + errCode = NtQueryVolumeInformationFile(hFile, + &IoStatusBlock, + FileFsVolume, + FS_VOLUME_BUFFER_SIZE, + FileFsVolumeInformation); + if ( !NT_SUCCESS(errCode) ) { + DPRINT("Status: %x\n", errCode); + CloseHandle(hFile); + SetLastErrorByStatus (errCode); + return FALSE; + } + + if (lpVolumeSerialNumber) + *lpVolumeSerialNumber = FileFsVolume->VolumeSerialNumber; + + if (lpVolumeNameBuffer) + wcsncpy (lpVolumeNameBuffer, + FileFsVolume->VolumeLabel, + min(nVolumeNameSize,MAX_PATH)); + + errCode = NtQueryVolumeInformationFile (hFile, + &IoStatusBlock, + FileFsAttribute, + FS_ATTRIBUTE_BUFFER_SIZE, + FileFsAttributeInformation); + if (!NT_SUCCESS(errCode)) + { + DPRINT("Status: %x\n", errCode); + CloseHandle(hFile); + SetLastErrorByStatus (errCode); + return FALSE; + } + + if (lpFileSystemFlags) + *lpFileSystemFlags = FileFsAttribute->FileSystemAttributes; + if (lpMaximumComponentLength) + *lpMaximumComponentLength = FileFsAttribute->MaximumComponentNameLength; + if (lpFileSystemNameBuffer) + wcsncpy(lpFileSystemNameBuffer, FileFsAttribute->FileSystemName,min(nFileSystemNameSize,MAX_PATH)); + + CloseHandle(hFile); + return TRUE; +} + + +WINBOOL +STDCALL +SetVolumeLabelA ( + LPCSTR lpRootPathName, + LPCSTR lpVolumeName + ) +{ + UNICODE_STRING RootPathNameU; + ANSI_STRING RootPathName; + UNICODE_STRING VolumeNameU; + ANSI_STRING VolumeName; + WINBOOL Result; + + RtlInitAnsiString (&RootPathName, + (LPSTR)lpRootPathName); + RtlInitAnsiString (&VolumeName, + (LPSTR)lpVolumeName); + + /* convert ansi (or oem) strings to unicode */ + if (bIsFileApiAnsi) + { + RtlAnsiStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + RtlAnsiStringToUnicodeString (&VolumeNameU, + &VolumeName, + TRUE); + } + else + { + RtlOemStringToUnicodeString (&RootPathNameU, + &RootPathName, + TRUE); + RtlOemStringToUnicodeString (&VolumeNameU, + &VolumeName, + TRUE); + } + + Result = SetVolumeLabelW (RootPathNameU.Buffer, + VolumeNameU.Buffer); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + RootPathNameU.Buffer); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VolumeNameU.Buffer); + + return Result; +} + + +WINBOOL STDCALL +SetVolumeLabelW(LPCWSTR lpRootPathName, + LPCWSTR lpVolumeName) +{ + PFILE_FS_LABEL_INFORMATION LabelInfo; + IO_STATUS_BLOCK IoStatusBlock; + ULONG LabelLength; + HANDLE hFile; + NTSTATUS Status; + + LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR); + LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(FILE_FS_LABEL_INFORMATION) + + LabelLength); + LabelInfo->VolumeLabelLength = LabelLength; + wcscpy(LabelInfo->VolumeLabel, + lpVolumeName); + + if (INVALID_HANDLE_VALUE == (hFile = InternalOpenDirW(lpRootPathName, TRUE))) + { + return FALSE; + } + + Status = NtSetVolumeInformationFile(hFile, + &IoStatusBlock, + LabelInfo, + sizeof(FILE_FS_LABEL_INFORMATION) + + LabelLength, + FileFsLabelInformation); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + LabelInfo); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Status: %x\n", Status); + CloseHandle(hFile); + SetLastErrorByStatus(Status); + return FALSE; + } + + CloseHandle(hFile); + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/kernel32.def b/lib/kernel32/kernel32.def new file mode 100644 index 0000000..1401368 --- /dev/null +++ b/lib/kernel32/kernel32.def @@ -0,0 +1,691 @@ +; +; kernel32.def +; +; Exports for KERNEL32 DLL +; +; Copyright (C) 1996 Free Software Foundation, Inc. +; +; Author: Scott Christley +; Date: 1996 +; +; This file is part of the Windows32 API Library. +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Library General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Library General Public License for more details. +; +; If you are interested in a warranty or support for this source code, +; contact Scott Christley for more information. +; +; You should have received a copy of the GNU Library General Public +; License along with this library; see the file COPYING.LIB. +; If not, write to the Free Software Foundation, +; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +; +LIBRARY KERNEL32.DLL +EXPORTS +AddAtomA@4 +AddAtomW@4 +AddConsoleAliasA@12 +AddConsoleAliasW@12 +AllocConsole@0 +AreFileApisANSI@0 +BackupRead@28 +BackupSeek@24 +BackupWrite@28 +BaseAttachCompleteThunk@0 +Beep@8 +BeginUpdateResourceA@8 +BeginUpdateResourceW@8 +BuildCommDCBA@8 +BuildCommDCBAndTimeoutsA@12 +BuildCommDCBAndTimeoutsW@12 +BuildCommDCBW@8 +CallNamedPipeA@28 +CallNamedPipeW@28 +CancelIo +CancelWaitableTimer@4 +ClearCommBreak@4 +ClearCommError@12 +CloseConsoleHandle@4 +CloseHandle@4 +CloseProfileUserMapping@0 +CmdBatNotification@4 +CommConfigDialogA@12 +CommConfigDialogW@12 +CompareFileTime@8 +CompareStringA@24 +CompareStringW@24 +ConnectNamedPipe@8 +ConsoleMenuControl@12 +ContinueDebugEvent@12 +ConvertDefaultLocale@4 +ConvertThreadToFiber@4 +CopyFileA@12 +CopyFileExA@24 +CopyFileExW@24 +CopyFileW@12 +CreateConsoleScreenBuffer@20 +CreateDirectoryA@8 +CreateDirectoryExA@12 +CreateDirectoryExW@12 +CreateDirectoryW@8 +CreateEventA@16 +CreateEventW@16 +CreateFiber@12 +CreateFileA@28 +CreateFileMappingA@24 +CreateFileMappingW@24 +CreateFileW@28 +CreateIoCompletionPort@16 +CreateMailslotA@16 +CreateMailslotW@16 +CreateMutexA@12 +CreateMutexW@12 +CreateNamedPipeA@32 +CreateNamedPipeW@32 +CreatePipe@16 +CreateProcessA@40 +CreateProcessW@40 +CreateRemoteThread@28 +CreateSemaphoreA@16 +CreateSemaphoreW@16 +CreateTapePartition@16 +CreateThread@24 +CreateVirtualBuffer@12 +CreateWaitableTimerA@12 +CreateWaitableTimerW@12 +DebugActiveProcess@4 +DebugBreak@0 +DefineDosDeviceA@12 +DefineDosDeviceW@12 +DeleteAtom@4 +DeleteCriticalSection@4 +DeleteFiber@4 +DeleteFileA@4 +DeleteFileW@4 +DeviceIoControl@32 +DisableThreadLibraryCalls@4 +DisconnectNamedPipe@4 +DosDateTimeToFileTime@12 +DuplicateConsoleHandle@16 +DuplicateHandle@28 +EndUpdateResourceA@8 +EndUpdateResourceW@8 +EnterCriticalSection@4 +EnumCalendarInfoA@16 +EnumCalendarInfoW@16 +EnumDateFormatsA@12 +EnumDateFormatsW@12 +EnumResourceLanguagesA@20 +EnumResourceLanguagesW@20 +EnumResourceNamesA@16 +EnumResourceNamesW@16 +EnumResourceTypesA@12 +EnumResourceTypesW@12 +EnumSystemCodePagesA@8 +EnumSystemCodePagesW@8 +EnumSystemLocalesA@8 +EnumSystemLocalesW@8 +EnumTimeFormatsA@12 +EnumTimeFormatsW@12 +EraseTape@12 +EscapeCommFunction@8 +ExitProcess@4 +ExitThread@4 +ExitVDM@8 +ExpandEnvironmentStringsA@12 +ExpandEnvironmentStringsW@12 +ExpungeConsoleCommandHistoryA@4 +ExpungeConsoleCommandHistoryW@4 +ExtendVirtualBuffer@8 +FatalAppExitA@8 +FatalAppExitW@8 +FatalExit@4 +FileTimeToDosDateTime@12 +FileTimeToLocalFileTime@8 +FileTimeToSystemTime@8 +FillConsoleOutputAttribute@20 +FillConsoleOutputCharacterA@20 +FillConsoleOutputCharacterW@20 +FindAtomA@4 +FindAtomW@4 +FindClose@4 +FindCloseChangeNotification@4 +FindFirstChangeNotificationA@12 +FindFirstChangeNotificationW@12 +FindFirstFileA@8 +FindFirstFileW@8 +FindNextChangeNotification@4 +FindNextFileA@8 +FindNextFileW@8 +FindResourceA@12 +FindResourceExA@16 +FindResourceExW@16 +FindResourceW@12 +FlushConsoleInputBuffer@4 +FlushFileBuffers@4 +FlushInstructionCache@12 +FlushViewOfFile@8 +FoldStringA@20 +FoldStringW@20 +FormatMessageA@28 +FormatMessageW@28 +FreeConsole@0 +FreeEnvironmentStringsA@4 +FreeEnvironmentStringsW@4 +FreeLibrary@4 +FreeLibraryAndExitThread@8 +FreeResource@4 +FreeVirtualBuffer@4 +GenerateConsoleCtrlEvent@8 +GetACP@0 +GetAtomNameA@12 +GetAtomNameW@12 +GetBinaryType@8 +GetBinaryTypeA@8 +GetBinaryTypeW@8 +GetCPInfo@8 +GetCommConfig@12 +GetCommMask@8 +GetCommModemStatus@8 +GetCommProperties@8 +GetCommState@8 +GetCommTimeouts@8 +GetCommandLineA@0 +GetCommandLineW@0 +GetCompressedFileSizeA@8 +GetCompressedFileSizeW@8 +GetComputerNameA@8 +GetComputerNameW@8 +GetConsoleAliasA@16 +GetConsoleAliasExesA@8 +GetConsoleAliasExesLengthA@0 +GetConsoleAliasExesLengthW@0 +GetConsoleAliasExesW@8 +GetConsoleAliasW@16 +GetConsoleAliasesA@12 +GetConsoleAliasesLengthA@4 +GetConsoleAliasesLengthW@4 +GetConsoleAliasesW@12 +GetConsoleCP@0 +GetConsoleCommandHistoryA@12 +GetConsoleCommandHistoryLengthA@4 +GetConsoleCommandHistoryLengthW@4 +GetConsoleCommandHistoryW@12 +GetConsoleCursorInfo@8 +GetConsoleDisplayMode@4 +GetConsoleFontInfo@16 +GetConsoleFontSize@8 +GetConsoleHardwareState@12 +GetConsoleInputWaitHandle@0 +GetConsoleMode@8 +GetConsoleOutputCP@0 +GetConsoleScreenBufferInfo@8 +GetConsoleTitleA@8 +GetConsoleTitleW@8 +GetCurrencyFormatA@24 +GetCurrencyFormatW@24 +GetCurrentConsoleFont@12 +GetCurrentDirectoryA@8 +GetCurrentDirectoryW@8 +GetCurrentFiber@0 +GetCurrentProcess@0 +GetCurrentProcessId@0 +GetCurrentThread@0 +GetCurrentThreadId@0 +GetDateFormatA@24 +GetDateFormatW@24 +GetDefaultCommConfigA@12 +GetDefaultCommConfigW@12 +GetDiskFreeSpaceA@20 +GetDiskFreeSpaceW@20 +GetDiskFreeSpaceExA@16 +GetDiskFreeSpaceExW@16 +GetDriveTypeA@4 +GetDriveTypeW@4 +GetEnvironmentStringsA@0 +GetEnvironmentStringsW@0 +GetEnvironmentVariableA@12 +GetEnvironmentVariableW@12 +GetExitCodeProcess@8 +GetExitCodeThread@8 +GetFiberData@0 +GetFileAttributesA@4 +GetFileAttributesW@4 +GetFileInformationByHandle@8 +GetFileSize@8 +GetFileTime@16 +GetFileType@4 +GetFullPathNameA@16 +GetFullPathNameW@16 +GetHandleInformation@8 +GetLargestConsoleWindowSize@4 +GetLastError@0 +GetLocalTime@4 +GetLocaleInfoA@16 +GetLocaleInfoW@16 +GetLogicalDriveStringsA@8 +GetLogicalDriveStringsW@8 +GetLogicalDrives@0 +GetMailslotInfo@20 +GetModuleFileNameA@12 +GetModuleFileNameW@12 +GetModuleHandleA@4 +GetModuleHandleW@4 +GetNamedPipeHandleStateA@28 +GetNamedPipeHandleStateW@28 +GetNamedPipeInfo@20 +GetNextVDMCommand@4 +GetNumberFormatA@24 +GetNumberFormatW@24 +GetNumberOfConsoleFonts@0 +GetNumberOfConsoleInputEvents@8 +GetNumberOfConsoleMouseButtons@4 +GetOEMCP@0 +GetOverlappedResult@16 +GetPriorityClass@4 +GetPrivateProfileIntA@16 +GetPrivateProfileIntW@16 +GetPrivateProfileSectionA@16 +GetPrivateProfileSectionNamesA@12 +GetPrivateProfileSectionNamesW@12 +GetPrivateProfileSectionW@16 +GetPrivateProfileStringA@24 +GetPrivateProfileStringW@24 +GetPrivateProfileStructA@20 +GetPrivateProfileStructW@20 +GetProcAddress@8 +GetProcessAffinityMask@12 +GetProcessHeap@0 +GetProcessHeaps@8 +GetProcessShutdownParameters@8 +GetProcessTimes@20 +GetProcessVersion@4 +GetProcessWorkingSetSize@12 +GetProfileIntA@12 +GetProfileIntW@12 +GetProfileSectionA@12 +GetProfileSectionW@12 +GetProfileStringA@20 +GetProfileStringW@20 +GetQueuedCompletionStatus@20 +GetShortPathNameA@12 +GetShortPathNameW@12 +GetStartupInfoA@4 +GetStartupInfoW@4 +GetStdHandle@4 +GetStringTypeA@20 +GetStringTypeExA@20 +GetStringTypeExW@20 +GetStringTypeW@16 +GetSystemDefaultLCID@0 +GetSystemDefaultLangID@0 +GetSystemDirectoryA@8 +GetSystemDirectoryW@8 +GetSystemInfo@4 +GetSystemPowerStatus@4 +GetSystemTime@4 +GetSystemTimeAdjustment@12 +GetSystemTimeAsFileTime@4 +GetTapeParameters@16 +GetTapePosition@20 +GetTapeStatus@4 +GetTempFileNameA@16 +GetTempFileNameW@16 +GetTempPathA@8 +GetTempPathW@8 +GetThreadContext@8 +GetThreadLocale@0 +GetThreadPriority@4 +GetThreadPriorityBoost@8 +GetThreadSelectorEntry@12 +GetThreadTimes@20 +GetTickCount@0 +GetTimeFormatA@24 +GetTimeFormatW@24 +GetTimeZoneInformation@4 +GetUserDefaultLCID@0 +GetUserDefaultLangID@0 +GetVDMCurrentDirectories@8 +GetVersion@0 +GetVersionExA@4 +GetVersionExW@4 +GetVolumeInformationA@32 +GetVolumeInformationW@32 +GetWindowsDirectoryA@8 +GetWindowsDirectoryW@8 +GlobalAddAtomA@4 +GlobalAddAtomW@4 +GlobalAlloc@8 +GlobalCompact@4 +GlobalDeleteAtom@4 +GlobalFindAtomA@4 +GlobalFindAtomW@4 +GlobalFix@4 +GlobalFlags@4 +GlobalFree@4 +GlobalGetAtomNameA@12 +GlobalGetAtomNameW@12 +GlobalHandle@4 +GlobalLock@4 +GlobalMemoryStatus@4 +GlobalReAlloc@12 +GlobalSize@4 +GlobalUnWire@4 +GlobalUnfix@4 +GlobalUnlock@4 +GlobalWire@4 +HeapAlloc@12 +HeapCompact@8 +HeapCreate@12 +HeapCreateTagsW@16 +HeapDestroy@4 +HeapExtend@16 +HeapFree@12 +HeapLock@4 +HeapQueryTagW@20 +HeapReAlloc@16 +HeapSize@12 +HeapSummary@12 +HeapUnlock@4 +HeapUsage@20 +HeapValidate@12 +HeapWalk@8 +InitAtomTable@4 +InitializeCriticalSection@4 +InterlockedCompareExchange@12 +InterlockedDecrement@4 +InterlockedExchange@8 +InterlockedExchangeAdd@8 +InterlockedIncrement@4 +InvalidateConsoleDIBits@8 +IsBadCodePtr@4 +IsBadHugeReadPtr@8 +IsBadHugeWritePtr@8 +IsBadReadPtr@8 +IsBadStringPtrA@8 +IsBadStringPtrW@8 +IsBadWritePtr@8 +IsDBCSLeadByte@4 +IsDBCSLeadByteEx@8 +IsDebuggerPresent@0 +IsProcessorFeaturePresent@4 +IsValidCodePage@4 +IsValidLocale@8 +LCMapStringA@24 +LCMapStringW@24 +LeaveCriticalSection@4 +LoadLibraryA@4 +LoadLibraryExA@12 +LoadLibraryExW@12 +LoadLibraryW@4 +LoadModule@8 +LoadResource@8 +LocalAlloc@8 +LocalCompact@4 +LocalFileTimeToFileTime@8 +LocalFlags@4 +LocalFree@4 +LocalHandle@4 +LocalLock@4 +LocalReAlloc@12 +LocalShrink@8 +LocalSize@4 +LocalUnlock@4 +LockFile@20 +LockFileEx@24 +LockResource@4 +MapViewOfFile@20 +MapViewOfFileEx@24 +MoveFileA@8 +MoveFileExA@12 +MoveFileExW@12 +MoveFileW@8 +MulDiv@12 +MultiByteToWideChar@24 +OpenConsoleW@16 +OpenEventA@12 +OpenEventW@12 +OpenFile@12 +OpenFileMappingA@12 +OpenFileMappingW@12 +OpenMutexA@12 +OpenMutexW@12 +OpenProcess@12 +OpenProfileUserMapping@0 +OpenSemaphoreA@12 +OpenSemaphoreW@12 +OpenWaitableTimerA@12 +OpenWaitableTimerW@12 +OutputDebugStringA@4 +OutputDebugStringW@4 +PeekConsoleInputA@16 +PeekConsoleInputW@16 +PeekNamedPipe@24 +PostQueuedCompletionStatus@16 +PrepareTape@12 +ProcessIdToSessionId@8 +PulseEvent@4 +PurgeComm@8 +QueryDosDeviceA@12 +QueryDosDeviceW@12 +QueryPerformanceCounter@4 +QueryPerformanceFrequency@4 +QueryWin31IniFilesMappedToRegistry@16 +RaiseException@16 +ReadConsoleA@20 +ReadConsoleInputA@16 +ReadConsoleInputW@16 +ReadConsoleOutputA@20 +ReadConsoleOutputAttribute@20 +ReadConsoleOutputCharacterA@20 +ReadConsoleOutputCharacterW@20 +ReadConsoleOutputW@20 +ReadConsoleW@20 +ReadFile@20 +ReadFileEx@20 +ReadProcessMemory@20 +RegisterConsoleVDM@44 +RegisterWaitForInputIdle@4 +RegisterWowBaseHandlers@4 +RegisterWowExec@4 +ReleaseMutex@4 +ReleaseSemaphore@12 +RemoveDirectoryA@4 +RemoveDirectoryW@4 +ResetEvent@4 +ResumeThread@4 +RtlFillMemory@12 +RtlMoveMemory@12 +RtlUnwind@16 +RtlZeroMemory@8 +ScrollConsoleScreenBufferA@20 +ScrollConsoleScreenBufferW@20 +SearchPathA@24 +SearchPathW@24 +SetCommBreak@4 +SetCommConfig@12 +SetCommMask@8 +SetCommState@8 +SetCommTimeouts@8 +SetComputerNameA@4 +SetComputerNameW@4 +SetConsoleActiveScreenBuffer@4 +SetConsoleCP@4 +SetConsoleCommandHistoryMode@4 +SetConsoleCtrlHandler@8 +SetConsoleCursor@8 +SetConsoleCursorInfo@8 +SetConsoleCursorPosition@8 +SetConsoleDisplayMode@12 +SetConsoleFont@8 +SetConsoleHardwareState@12 +SetConsoleKeyShortcuts@16 +SetConsoleMaximumWindowSize@8 +SetConsoleMenuClose@4 +SetConsoleMode@8 +SetConsoleNumberOfCommandsA@8 +SetConsoleNumberOfCommandsW@8 +SetConsoleOutputCP@4 +SetConsolePalette@12 +SetConsoleScreenBufferSize@8 +SetConsoleTextAttribute@8 +SetConsoleTitleA@4 +SetConsoleTitleW@4 +SetConsoleWindowInfo@12 +SetCurrentDirectoryA@4 +SetCurrentDirectoryW@4 +SetDefaultCommConfigA@12 +SetDefaultCommConfigW@12 +SetEndOfFile@4 +SetEnvironmentVariableA@8 +SetEnvironmentVariableW@8 +SetErrorMode@4 +SetEvent@4 +SetFileApisToANSI@0 +SetFileApisToOEM@0 +SetFileAttributesA@8 +SetFileAttributesW@8 +SetFilePointer@16 +SetFileTime@16 +SetHandleCount@4 +SetHandleInformation@12 +SetLastConsoleEventActive@0 +SetLastError@4 +SetLastErrorByStatus@4 +SetLocalTime@4 +SetLocaleInfoA@12 +SetLocaleInfoW@12 +SetMailslotInfo@8 +SetNamedPipeHandleState@16 +SetPriorityClass@8 +SetProcessShutdownParameters@8 +SetProcessWorkingSetSize@12 +SetStdHandle@8 +SetSystemPowerState@8 +SetSystemTime@4 +SetSystemTimeAdjustment@8 +SetTapeParameters@12 +SetTapePosition@24 +SetThreadAffinityMask@8 +SetThreadContext@8 +SetThreadIdealProcessor@8 +SetThreadLocale@4 +SetThreadPriority@8 +SetThreadPriorityBoost@8 +SetTimeZoneInformation@4 +SetUnhandledExceptionFilter@4 +SetVDMCurrentDirectories@8 +SetVolumeLabelA@8 +SetVolumeLabelW@8 +SetWaitableTimer@24 +SetupComm@12 +ShowConsoleCursor@8 +SizeofResource@8 +Sleep@4 +SleepEx@8 +SuspendThread@4 +SwitchToFiber@4 +SwitchToThread@0 +SystemTimeToFileTime@8 +SystemTimeToTzSpecificLocalTime@12 +TerminateProcess@8 +TerminateThread@8 +TlsAlloc@0 +TlsFree@4 +TlsGetValue@4 +TlsSetValue@8 +TransactNamedPipe@28 +TransmitCommChar@8 +TrimVirtualBuffer@4 +TryEnterCriticalSection@4 +UnhandledExceptionFilter@4 +UnlockFile@20 +UnlockFileEx@20 +UnmapViewOfFile@4 +UpdateResourceA@24 +UpdateResourceW@24 +VDMConsoleOperation@8 +VDMOperationStarted@4 +VerLanguageNameA@12 +VerLanguageNameW@12 +VerifyConsoleIoHandle@4 +VirtualAlloc@16 +VirtualAllocEx@20 +VirtualBufferExceptionHandler@12 +VirtualFree@12 +VirtualFreeEx@16 +VirtualLock@8 +VirtualProtect@16 +VirtualProtectEx@20 +VirtualQuery@12 +VirtualQueryEx@16 +VirtualUnlock@8 +WaitCommEvent@12 +WaitForDebugEvent@8 +WaitForMultipleObjects@16 +WaitForMultipleObjectsEx@20 +WaitForSingleObject@8 +WaitForSingleObjectEx@12 +WaitNamedPipeA@8 +WaitNamedPipeW@8 +WideCharToMultiByte@32 +WinExec@8 +WriteConsoleA@20 +WriteConsoleInputA@16 +WriteConsoleInputVDMA@16 +WriteConsoleInputVDMW@16 +WriteConsoleInputW@16 +WriteConsoleOutputA@20 +WriteConsoleOutputAttribute@20 +WriteConsoleOutputCharacterA@20 +WriteConsoleOutputCharacterW@20 +WriteConsoleOutputW@20 +WriteConsoleW@20 +WriteFile@20 +WriteFileEx@20 +WritePrivateProfileSectionA@12 +WritePrivateProfileSectionW@12 +WritePrivateProfileStringA@16 +WritePrivateProfileStringW@16 +WritePrivateProfileStructA@20 +WritePrivateProfileStructW@20 +WriteProcessMemory@20 +WriteProfileSectionA@8 +WriteProfileSectionW@8 +WriteProfileStringA@12 +WriteProfileStringW@12 +WriteTapemark@16 +_hread@12 +_hwrite@12 +_lclose@4 +_lcreat@8 +_llseek@12 +_lopen@8 +_lread@12 +_lwrite@12 +;lstrcat@8 +lstrcatA@8 +lstrcatW@8 +;lstrcmp@8 +lstrcmpA@8 +lstrcmpW@8 +;lstrcmpi@8 +lstrcmpiA@8 +lstrcmpiW@8 +;lstrcpy@8 +lstrcpyA@8 +lstrcpyW@8 +;lstrcpyn@12 +lstrcpynA@12 +lstrcpynW@12 +;lstrlen@4 +lstrlenA@4 +lstrlenW@4 diff --git a/lib/kernel32/kernel32.edf b/lib/kernel32/kernel32.edf new file mode 100644 index 0000000..b0b69ba --- /dev/null +++ b/lib/kernel32/kernel32.edf @@ -0,0 +1,695 @@ +; $Id$ +; +; kernel32.edf +; +; ReactOS Operating System +; +; Aliased exports for KERNEL32.DLL generated by defedf reading +; kernel32.def by Scott Christley. +; +; Copyright (C) 1996 Free Software Foundation, Inc. +; +; Author: Scott Christley +; Date: 1996 +; +; This file is part of the Windows32 API Library. +; +; This library is free software; you can redistribute it and/or +; modify it under the terms of the GNU Library General Public +; License as published by the Free Software Foundation; either +; version 2 of the License, or (at your option) any later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +; Library General Public License for more details. +; +; If you are interested in a warranty or support for this source code, +; contact Scott Christley for more information. +; +; You should have received a copy of the GNU Library General Public +; License along with this library; see the file COPYING.LIB. +; If not, write to the Free Software Foundation, +; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +; +LIBRARY KERNEL32.DLL +EXPORTS +AddAtomA=AddAtomA@4 +AddAtomW=AddAtomW@4 +AddConsoleAliasA=AddConsoleAliasA@12 +AddConsoleAliasW=AddConsoleAliasW@12 +AllocConsole=AllocConsole@0 +AreFileApisANSI=AreFileApisANSI@0 +BackupRead=BackupRead@28 +BackupSeek=BackupSeek@24 +BackupWrite=BackupWrite@28 +BaseAttachCompleteThunk=BaseAttachCompleteThunk@0 +Beep=Beep@8 +BeginUpdateResourceA=BeginUpdateResourceA@8 +BeginUpdateResourceW=BeginUpdateResourceW@8 +BuildCommDCBA=BuildCommDCBA@8 +BuildCommDCBAndTimeoutsA=BuildCommDCBAndTimeoutsA@12 +BuildCommDCBAndTimeoutsW=BuildCommDCBAndTimeoutsW@12 +BuildCommDCBW=BuildCommDCBW@8 +CallNamedPipeA=CallNamedPipeA@28 +CallNamedPipeW=CallNamedPipeW@28 +CancelWaitableTimer=CancelWaitableTimer@4 +ClearCommBreak=ClearCommBreak@4 +ClearCommError=ClearCommError@12 +CloseConsoleHandle=CloseConsoleHandle@4 +CloseHandle=CloseHandle@4 +CloseProfileUserMapping=CloseProfileUserMapping@0 +CmdBatNotification=CmdBatNotification@4 +CommConfigDialogA=CommConfigDialogA@12 +CommConfigDialogW=CommConfigDialogW@12 +CompareFileTime=CompareFileTime@8 +CompareStringA=CompareStringA@24 +CompareStringW=CompareStringW@24 +ConnectNamedPipe=ConnectNamedPipe@8 +ConsoleMenuControl=ConsoleMenuControl@12 +ContinueDebugEvent=ContinueDebugEvent@12 +ConvertDefaultLocale=ConvertDefaultLocale@4 +ConvertThreadToFiber=ConvertThreadToFiber@4 +CopyFileA=CopyFileA@12 +CopyFileExA=CopyFileExA@24 +CopyFileExW=CopyFileExW@24 +CopyFileW=CopyFileW@12 +CreateConsoleScreenBuffer=CreateConsoleScreenBuffer@20 +CreateDirectoryA=CreateDirectoryA@8 +CreateDirectoryExA=CreateDirectoryExA@12 +CreateDirectoryExW=CreateDirectoryExW@12 +CreateDirectoryW=CreateDirectoryW@8 +CreateEventA=CreateEventA@16 +CreateEventW=CreateEventW@16 +CreateFiber=CreateFiber@12 +CreateFileA=CreateFileA@28 +CreateFileMappingA=CreateFileMappingA@24 +CreateFileMappingW=CreateFileMappingW@24 +CreateFileW=CreateFileW@28 +CreateIoCompletionPort=CreateIoCompletionPort@16 +CreateMailslotA=CreateMailslotA@16 +CreateMailslotW=CreateMailslotW@16 +CreateMutexA=CreateMutexA@12 +CreateMutexW=CreateMutexW@12 +CreateNamedPipeA=CreateNamedPipeA@32 +CreateNamedPipeW=CreateNamedPipeW@32 +CreatePipe=CreatePipe@16 +CreateProcessA=CreateProcessA@40 +CreateProcessW=CreateProcessW@40 +CreateRemoteThread=CreateRemoteThread@28 +CreateSemaphoreA=CreateSemaphoreA@16 +CreateSemaphoreW=CreateSemaphoreW@16 +CreateTapePartition=CreateTapePartition@16 +CreateThread=CreateThread@24 +CreateVirtualBuffer=CreateVirtualBuffer@12 +CreateWaitableTimerA=CreateWaitableTimerA@12 +CreateWaitableTimerW=CreateWaitableTimerW@12 +DebugActiveProcess=DebugActiveProcess@4 +DebugBreak=DebugBreak@0 +DefineDosDeviceA=DefineDosDeviceA@12 +DefineDosDeviceW=DefineDosDeviceW@12 +DeleteAtom=DeleteAtom@4 +DeleteCriticalSection=NTDLL.RtlDeleteCriticalSection +DeleteFiber=DeleteFiber@4 +DeleteFileA=DeleteFileA@4 +DeleteFileW=DeleteFileW@4 +DeviceIoControl=DeviceIoControl@32 +DisableThreadLibraryCalls=DisableThreadLibraryCalls@4 +DisconnectNamedPipe=DisconnectNamedPipe@4 +DosDateTimeToFileTime=DosDateTimeToFileTime@12 +DuplicateConsoleHandle=DuplicateConsoleHandle@16 +DuplicateHandle=DuplicateHandle@28 +EndUpdateResourceA=EndUpdateResourceA@8 +EndUpdateResourceW=EndUpdateResourceW@8 +EnterCriticalSection=NTDLL.RtlEnterCriticalSection +EnumCalendarInfoA=EnumCalendarInfoA@16 +EnumCalendarInfoW=EnumCalendarInfoW@16 +EnumDateFormatsA=EnumDateFormatsA@12 +EnumDateFormatsW=EnumDateFormatsW@12 +EnumResourceLanguagesA=EnumResourceLanguagesA@20 +EnumResourceLanguagesW=EnumResourceLanguagesW@20 +EnumResourceNamesA=EnumResourceNamesA@16 +EnumResourceNamesW=EnumResourceNamesW@16 +EnumResourceTypesA=EnumResourceTypesA@12 +EnumResourceTypesW=EnumResourceTypesW@12 +EnumSystemCodePagesA=EnumSystemCodePagesA@8 +EnumSystemCodePagesW=EnumSystemCodePagesW@8 +EnumSystemLocalesA=EnumSystemLocalesA@8 +EnumSystemLocalesW=EnumSystemLocalesW@8 +EnumTimeFormatsA=EnumTimeFormatsA@12 +EnumTimeFormatsW=EnumTimeFormatsW@12 +EraseTape=EraseTape@12 +EscapeCommFunction=EscapeCommFunction@8 +ExitProcess=ExitProcess@4 +ExitThread=ExitThread@4 +ExitVDM=ExitVDM@8 +ExpandEnvironmentStringsA=ExpandEnvironmentStringsA@12 +ExpandEnvironmentStringsW=ExpandEnvironmentStringsW@12 +ExpungeConsoleCommandHistoryA=ExpungeConsoleCommandHistoryA@4 +ExpungeConsoleCommandHistoryW=ExpungeConsoleCommandHistoryW@4 +ExtendVirtualBuffer=ExtendVirtualBuffer@8 +FatalAppExitA=FatalAppExitA@8 +FatalAppExitW=FatalAppExitW@8 +FatalExit=FatalExit@4 +FileTimeToDosDateTime=FileTimeToDosDateTime@12 +FileTimeToLocalFileTime=FileTimeToLocalFileTime@8 +FileTimeToSystemTime=FileTimeToSystemTime@8 +FillConsoleOutputAttribute=FillConsoleOutputAttribute@20 +FillConsoleOutputCharacterA=FillConsoleOutputCharacterA@20 +FillConsoleOutputCharacterW=FillConsoleOutputCharacterW@20 +FindAtomA=FindAtomA@4 +FindAtomW=FindAtomW@4 +FindClose=FindClose@4 +FindCloseChangeNotification=FindCloseChangeNotification@4 +FindFirstChangeNotificationA=FindFirstChangeNotificationA@12 +FindFirstChangeNotificationW=FindFirstChangeNotificationW@12 +FindFirstFileA=FindFirstFileA@8 +FindFirstFileW=FindFirstFileW@8 +FindNextChangeNotification=FindNextChangeNotification@4 +FindNextFileA=FindNextFileA@8 +FindNextFileW=FindNextFileW@8 +FindResourceA=FindResourceA@12 +FindResourceExA=FindResourceExA@16 +FindResourceExW=FindResourceExW@16 +FindResourceW=FindResourceW@12 +FlushConsoleInputBuffer=FlushConsoleInputBuffer@4 +FlushFileBuffers=FlushFileBuffers@4 +FlushInstructionCache=FlushInstructionCache@12 +FlushViewOfFile=FlushViewOfFile@8 +FoldStringA=FoldStringA@20 +FoldStringW=FoldStringW@20 +FormatMessageA=FormatMessageA@28 +FormatMessageW=FormatMessageW@28 +FreeConsole=FreeConsole@0 +FreeEnvironmentStringsA=FreeEnvironmentStringsA@4 +FreeEnvironmentStringsW=FreeEnvironmentStringsW@4 +FreeLibrary=FreeLibrary@4 +FreeLibraryAndExitThread=FreeLibraryAndExitThread@8 +FreeResource=FreeResource@4 +FreeVirtualBuffer=FreeVirtualBuffer@4 +GenerateConsoleCtrlEvent=GenerateConsoleCtrlEvent@8 +GetACP=GetACP@0 +GetAtomNameA=GetAtomNameA@12 +GetAtomNameW=GetAtomNameW@12 +GetBinaryType=GetBinaryTypeA@8 +GetBinaryTypeA=GetBinaryTypeA@8 +GetBinaryTypeW=GetBinaryTypeW@8 +GetCPInfo=GetCPInfo@8 +GetCommConfig=GetCommConfig@12 +GetCommMask=GetCommMask@8 +GetCommModemStatus=GetCommModemStatus@8 +GetCommProperties=GetCommProperties@8 +GetCommState=GetCommState@8 +GetCommTimeouts=GetCommTimeouts@8 +GetCommandLineA=GetCommandLineA@0 +GetCommandLineW=GetCommandLineW@0 +GetCompressedFileSizeA=GetCompressedFileSizeA@8 +GetCompressedFileSizeW=GetCompressedFileSizeW@8 +GetComputerNameA=GetComputerNameA@8 +GetComputerNameW=GetComputerNameW@8 +GetConsoleAliasA=GetConsoleAliasA@16 +GetConsoleAliasExesA=GetConsoleAliasExesA@8 +GetConsoleAliasExesLengthA=GetConsoleAliasExesLengthA@0 +GetConsoleAliasExesLengthW=GetConsoleAliasExesLengthW@0 +GetConsoleAliasExesW=GetConsoleAliasExesW@8 +GetConsoleAliasW=GetConsoleAliasW@16 +GetConsoleAliasesA=GetConsoleAliasesA@12 +GetConsoleAliasesLengthA=GetConsoleAliasesLengthA@4 +GetConsoleAliasesLengthW=GetConsoleAliasesLengthW@4 +GetConsoleAliasesW=GetConsoleAliasesW@12 +GetConsoleCP=GetConsoleCP@0 +GetConsoleCommandHistoryA=GetConsoleCommandHistoryA@12 +GetConsoleCommandHistoryLengthA=GetConsoleCommandHistoryLengthA@4 +GetConsoleCommandHistoryLengthW=GetConsoleCommandHistoryLengthW@4 +GetConsoleCommandHistoryW=GetConsoleCommandHistoryW@12 +GetConsoleCursorInfo=GetConsoleCursorInfo@8 +GetConsoleDisplayMode=GetConsoleDisplayMode@4 +GetConsoleFontInfo=GetConsoleFontInfo@16 +GetConsoleFontSize=GetConsoleFontSize@8 +GetConsoleHardwareState=GetConsoleHardwareState@12 +GetConsoleInputWaitHandle=GetConsoleInputWaitHandle@0 +GetConsoleMode=GetConsoleMode@8 +GetConsoleOutputCP=GetConsoleOutputCP@0 +GetConsoleScreenBufferInfo=GetConsoleScreenBufferInfo@8 +GetConsoleTitleA=GetConsoleTitleA@8 +GetConsoleTitleW=GetConsoleTitleW@8 +GetCurrencyFormatA=GetCurrencyFormatA@24 +GetCurrencyFormatW=GetCurrencyFormatW@24 +GetCurrentConsoleFont=GetCurrentConsoleFont@12 +GetCurrentDirectoryA=GetCurrentDirectoryA@8 +GetCurrentDirectoryW=GetCurrentDirectoryW@8 +GetCurrentFiber=GetCurrentFiber@0 +GetCurrentProcess=GetCurrentProcess@0 +GetCurrentProcessId=GetCurrentProcessId@0 +GetCurrentThread=GetCurrentThread@0 +GetCurrentThreadId=GetCurrentThreadId@0 +GetDateFormatA=GetDateFormatA@24 +GetDateFormatW=GetDateFormatW@24 +GetDefaultCommConfigA=GetDefaultCommConfigA@12 +GetDefaultCommConfigW=GetDefaultCommConfigW@12 +GetDiskFreeSpaceA=GetDiskFreeSpaceA@20 +GetDiskFreeSpaceW=GetDiskFreeSpaceW@20 +GetDiskFreeSpaceExA=GetDiskFreeSpaceExA@16 +GetDiskFreeSpaceExW=GetDiskFreeSpaceExW@16 +GetDriveTypeA=GetDriveTypeA@4 +GetDriveTypeW=GetDriveTypeW@4 +GetEnvironmentStrings=GetEnvironmentStringsA@0 +GetEnvironmentStringsA=GetEnvironmentStringsA@0 +GetEnvironmentStringsW=GetEnvironmentStringsW@0 +GetEnvironmentVariableA=GetEnvironmentVariableA@12 +GetEnvironmentVariableW=GetEnvironmentVariableW@12 +GetExitCodeProcess=GetExitCodeProcess@8 +GetExitCodeThread=GetExitCodeThread@8 +GetFiberData=GetFiberData@0 +GetFileAttributesA=GetFileAttributesA@4 +GetFileAttributesW=GetFileAttributesW@4 +GetFileInformationByHandle=GetFileInformationByHandle@8 +GetFileSize=GetFileSize@8 +GetFileTime=GetFileTime@16 +GetFileType=GetFileType@4 +GetFullPathNameA=GetFullPathNameA@16 +GetFullPathNameW=GetFullPathNameW@16 +GetHandleInformation=GetHandleInformation@8 +GetLargestConsoleWindowSize=GetLargestConsoleWindowSize@4 +GetLastError=GetLastError@0 +GetLocalTime=GetLocalTime@4 +GetLocaleInfoA=GetLocaleInfoA@16 +GetLocaleInfoW=GetLocaleInfoW@16 +GetLogicalDriveStringsA=GetLogicalDriveStringsA@8 +GetLogicalDriveStringsW=GetLogicalDriveStringsW@8 +GetLogicalDrives=GetLogicalDrives@0 +GetMailslotInfo=GetMailslotInfo@20 +GetModuleFileNameA=GetModuleFileNameA@12 +GetModuleFileNameW=GetModuleFileNameW@12 +GetModuleHandleA=GetModuleHandleA@4 +GetModuleHandleW=GetModuleHandleW@4 +GetNamedPipeHandleStateA=GetNamedPipeHandleStateA@28 +GetNamedPipeHandleStateW=GetNamedPipeHandleStateW@28 +GetNamedPipeInfo=GetNamedPipeInfo@20 +GetNextVDMCommand=GetNextVDMCommand@4 +GetNumberFormatA=GetNumberFormatA@24 +GetNumberFormatW=GetNumberFormatW@24 +GetNumberOfConsoleFonts=GetNumberOfConsoleFonts@0 +GetNumberOfConsoleInputEvents=GetNumberOfConsoleInputEvents@8 +GetNumberOfConsoleMouseButtons=GetNumberOfConsoleMouseButtons@4 +GetOEMCP=GetOEMCP@0 +GetOverlappedResult=GetOverlappedResult@16 +GetPriorityClass=GetPriorityClass@4 +GetPrivateProfileIntA=GetPrivateProfileIntA@16 +GetPrivateProfileIntW=GetPrivateProfileIntW@16 +GetPrivateProfileSectionA=GetPrivateProfileSectionA@16 +GetPrivateProfileSectionNamesA=GetPrivateProfileSectionNamesA@12 +GetPrivateProfileSectionNamesW=GetPrivateProfileSectionNamesW@12 +GetPrivateProfileSectionW=GetPrivateProfileSectionW@16 +GetPrivateProfileStringA=GetPrivateProfileStringA@24 +GetPrivateProfileStringW=GetPrivateProfileStringW@24 +GetPrivateProfileStructA=GetPrivateProfileStructA@20 +GetPrivateProfileStructW=GetPrivateProfileStructW@20 +GetProcAddress=GetProcAddress@8 +GetProcessAffinityMask=GetProcessAffinityMask@12 +GetProcessHeap=GetProcessHeap@0 +GetProcessHeaps=GetProcessHeaps@8 +GetProcessShutdownParameters=GetProcessShutdownParameters@8 +GetProcessTimes=GetProcessTimes@20 +GetProcessVersion=GetProcessVersion@4 +GetProcessWorkingSetSize=GetProcessWorkingSetSize@12 +GetProfileIntA=GetProfileIntA@12 +GetProfileIntW=GetProfileIntW@12 +GetProfileSectionA=GetProfileSectionA@12 +GetProfileSectionW=GetProfileSectionW@12 +GetProfileStringA=GetProfileStringA@20 +GetProfileStringW=GetProfileStringW@20 +GetQueuedCompletionStatus=GetQueuedCompletionStatus@20 +GetShortPathNameA=GetShortPathNameA@12 +GetShortPathNameW=GetShortPathNameW@12 +GetStartupInfoA=GetStartupInfoA@4 +GetStartupInfoW=GetStartupInfoW@4 +GetStdHandle=GetStdHandle@4 +GetStringTypeA=GetStringTypeA@20 +GetStringTypeExA=GetStringTypeExA@20 +GetStringTypeExW=GetStringTypeExW@20 +GetStringTypeW=GetStringTypeW@16 +GetSystemDefaultLCID=GetSystemDefaultLCID@0 +GetSystemDefaultLangID=GetSystemDefaultLangID@0 +GetSystemDirectoryA=GetSystemDirectoryA@8 +GetSystemDirectoryW=GetSystemDirectoryW@8 +GetSystemInfo=GetSystemInfo@4 +GetSystemPowerStatus=GetSystemPowerStatus@4 +GetSystemTime=GetSystemTime@4 +GetSystemTimeAdjustment=GetSystemTimeAdjustment@12 +GetSystemTimeAsFileTime=GetSystemTimeAsFileTime@4 +GetTapeParameters=GetTapeParameters@16 +GetTapePosition=GetTapePosition@20 +GetTapeStatus=GetTapeStatus@4 +GetTempFileNameA=GetTempFileNameA@16 +GetTempFileNameW=GetTempFileNameW@16 +GetTempPathA=GetTempPathA@8 +GetTempPathW=GetTempPathW@8 +GetThreadContext=GetThreadContext@8 +GetThreadLocale=GetThreadLocale@0 +GetThreadPriority=GetThreadPriority@4 +GetThreadPriorityBoost=GetThreadPriorityBoost@8 +GetThreadSelectorEntry=GetThreadSelectorEntry@12 +GetThreadTimes=GetThreadTimes@20 +GetTickCount=GetTickCount@0 +GetTimeFormatA=GetTimeFormatA@24 +GetTimeFormatW=GetTimeFormatW@24 +GetTimeZoneInformation=GetTimeZoneInformation@4 +GetUserDefaultLCID=GetUserDefaultLCID@0 +GetUserDefaultLangID=GetUserDefaultLangID@0 +GetVDMCurrentDirectories=GetVDMCurrentDirectories@8 +GetVersion=GetVersion@0 +GetVersionExA=GetVersionExA@4 +GetVersionExW=GetVersionExW@4 +GetVolumeInformationA=GetVolumeInformationA@32 +GetVolumeInformationW=GetVolumeInformationW@32 +GetWindowsDirectoryA=GetWindowsDirectoryA@8 +GetWindowsDirectoryW=GetWindowsDirectoryW@8 +GlobalAddAtomA=GlobalAddAtomA@4 +GlobalAddAtomW=GlobalAddAtomW@4 +GlobalAlloc=GlobalAlloc@8 +GlobalCompact=GlobalCompact@4 +GlobalDeleteAtom=GlobalDeleteAtom@4 +GlobalFindAtomA=GlobalFindAtomA@4 +GlobalFindAtomW=GlobalFindAtomW@4 +GlobalFix=GlobalFix@4 +GlobalFlags=GlobalFlags@4 +GlobalFree=GlobalFree@4 +GlobalGetAtomNameA=GlobalGetAtomNameA@12 +GlobalGetAtomNameW=GlobalGetAtomNameW@12 +GlobalHandle=GlobalHandle@4 +GlobalLock=GlobalLock@4 +GlobalMemoryStatus=GlobalMemoryStatus@4 +GlobalReAlloc=GlobalReAlloc@12 +GlobalSize=GlobalSize@4 +GlobalUnWire=GlobalUnWire@4 +GlobalUnfix=GlobalUnfix@4 +GlobalUnlock=GlobalUnlock@4 +GlobalWire=GlobalWire@4 +HeapAlloc=NTDLL.RtlAllocateHeap +HeapCompact=HeapCompact@8 +HeapCreate=HeapCreate@12 +HeapCreateTagsW=HeapCreateTagsW@16 +HeapDestroy=HeapDestroy@4 +HeapExtend=HeapExtend@16 +HeapFree=NTDLL.RtlFreeHeap +HeapLock=HeapLock@4 +HeapQueryTagW=HeapQueryTagW@20 +HeapReAlloc=NTDLL.RtlReAllocateHeap +HeapSize=NTDLL.RtlSizeHeap +HeapSummary=HeapSummary@12 +HeapUnlock=HeapUnlock@4 +HeapUsage=HeapUsage@20 +HeapValidate=HeapValidate@12 +HeapWalk=HeapWalk@8 +InitAtomTable=InitAtomTable@4 +InitializeCriticalSection=InitializeCriticalSection@4 +InterlockedCompareExchange=InterlockedCompareExchange@12 +InterlockedDecrement=InterlockedDecrement@4 +InterlockedExchange=InterlockedExchange@8 +InterlockedExchangeAdd=InterlockedExchangeAdd@8 +InterlockedIncrement=InterlockedIncrement@4 +InvalidateConsoleDIBits=InvalidateConsoleDIBits@8 +IsBadCodePtr=IsBadCodePtr@4 +IsBadHugeReadPtr=IsBadHugeReadPtr@8 +IsBadHugeWritePtr=IsBadHugeWritePtr@8 +IsBadReadPtr=IsBadReadPtr@8 +IsBadStringPtrA=IsBadStringPtrA@8 +IsBadStringPtrW=IsBadStringPtrW@8 +IsBadWritePtr=IsBadWritePtr@8 +IsDBCSLeadByte=IsDBCSLeadByte@4 +IsDBCSLeadByteEx=IsDBCSLeadByteEx@8 +IsDebuggerPresent=IsDebuggerPresent@0 +IsProcessorFeaturePresent=IsProcessorFeaturePresent@4 +IsValidCodePage=IsValidCodePage@4 +IsValidLocale=IsValidLocale@8 +LCMapStringA=LCMapStringA@24 +LCMapStringW=LCMapStringW@24 +LeaveCriticalSection=NTDLL.RtlLeaveCriticalSection +LoadLibraryA=LoadLibraryA@4 +LoadLibraryExA=LoadLibraryExA@12 +LoadLibraryExW=LoadLibraryExW@12 +LoadLibraryW=LoadLibraryW@4 +LoadModule=LoadModule@8 +LoadResource=LoadResource@8 +LocalAlloc=LocalAlloc@8 +LocalCompact=LocalCompact@4 +LocalFileTimeToFileTime=LocalFileTimeToFileTime@8 +LocalFlags=LocalFlags@4 +LocalFree=LocalFree@4 +LocalHandle=LocalHandle@4 +LocalLock=LocalLock@4 +LocalReAlloc=LocalReAlloc@12 +LocalShrink=LocalShrink@8 +LocalSize=LocalSize@4 +LocalUnlock=LocalUnlock@4 +LockFile=LockFile@20 +LockFileEx=LockFileEx@24 +LockResource=LockResource@4 +MapViewOfFile=MapViewOfFile@20 +MapViewOfFileEx=MapViewOfFileEx@24 +MoveFileA=MoveFileA@8 +MoveFileExA=MoveFileExA@12 +MoveFileExW=MoveFileExW@12 +MoveFileW=MoveFileW@8 +MulDiv=MulDiv@12 +MultiByteToWideChar=MultiByteToWideChar@24 +OpenConsoleW=OpenConsoleW@16 +OpenEventA=OpenEventA@12 +OpenEventW=OpenEventW@12 +OpenFile=OpenFile@12 +OpenFileMappingA=OpenFileMappingA@12 +OpenFileMappingW=OpenFileMappingW@12 +OpenMutexA=OpenMutexA@12 +OpenMutexW=OpenMutexW@12 +OpenProcess=OpenProcess@12 +OpenProfileUserMapping=OpenProfileUserMapping@0 +OpenSemaphoreA=OpenSemaphoreA@12 +OpenSemaphoreW=OpenSemaphoreW@12 +OpenWaitableTimerA=OpenWaitableTimerA@12 +OpenWaitableTimerW=OpenWaitableTimerW@12 +OutputDebugStringA=OutputDebugStringA@4 +OutputDebugStringW=OutputDebugStringW@4 +PeekConsoleInputA=PeekConsoleInputA@16 +PeekConsoleInputW=PeekConsoleInputW@16 +PeekNamedPipe=PeekNamedPipe@24 +PostQueuedCompletionStatus=PostQueuedCompletionStatus@16 +PrepareTape=PrepareTape@12 +ProcessIdToSessionId=ProcessIdToSessionId@8 +PulseEvent=PulseEvent@4 +PurgeComm=PurgeComm@8 +QueryDosDeviceA=QueryDosDeviceA@12 +QueryDosDeviceW=QueryDosDeviceW@12 +QueryPerformanceCounter=QueryPerformanceCounter@4 +QueryPerformanceFrequency=QueryPerformanceFrequency@4 +QueryWin31IniFilesMappedToRegistry=QueryWin31IniFilesMappedToRegistry@16 +RaiseException=RaiseException@16 +ReadConsoleA=ReadConsoleA@20 +ReadConsoleInputA=ReadConsoleInputA@16 +ReadConsoleInputW=ReadConsoleInputW@16 +ReadConsoleOutputA=ReadConsoleOutputA@20 +ReadConsoleOutputAttribute=ReadConsoleOutputAttribute@20 +ReadConsoleOutputCharacterA=ReadConsoleOutputCharacterA@20 +ReadConsoleOutputCharacterW=ReadConsoleOutputCharacterW@20 +ReadConsoleOutputW=ReadConsoleOutputW@20 +ReadConsoleW=ReadConsoleW@20 +ReadFile=ReadFile@20 +ReadFileEx=ReadFileEx@20 +ReadProcessMemory=ReadProcessMemory@20 +RegisterConsoleVDM=RegisterConsoleVDM@44 +RegisterWaitForInputIdle=RegisterWaitForInputIdle@4 +RegisterWowBaseHandlers=RegisterWowBaseHandlers@4 +RegisterWowExec=RegisterWowExec@4 +ReleaseMutex=ReleaseMutex@4 +ReleaseSemaphore=ReleaseSemaphore@12 +RemoveDirectoryA=RemoveDirectoryA@4 +RemoveDirectoryW=RemoveDirectoryW@4 +ResetEvent=ResetEvent@4 +ResumeThread=ResumeThread@4 +RtlFillMemory=NTDLL.RtlFillMemory +RtlMoveMemory=NTDLL.RtlMoveMemory +RtlUnwind=NTDLL.RtlUnwind +RtlZeroMemory=NTDLL.RtlZeroMemory +ScrollConsoleScreenBufferA=ScrollConsoleScreenBufferA@20 +ScrollConsoleScreenBufferW=ScrollConsoleScreenBufferW@20 +SearchPathA=SearchPathA@24 +SearchPathW=SearchPathW@24 +SetCommBreak=SetCommBreak@4 +SetCommConfig=SetCommConfig@12 +SetCommMask=SetCommMask@8 +SetCommState=SetCommState@8 +SetCommTimeouts=SetCommTimeouts@8 +SetComputerNameA=SetComputerNameA@4 +SetComputerNameW=SetComputerNameW@4 +SetConsoleActiveScreenBuffer=SetConsoleActiveScreenBuffer@4 +SetConsoleCP=SetConsoleCP@4 +SetConsoleCommandHistoryMode=SetConsoleCommandHistoryMode@4 +SetConsoleCtrlHandler=SetConsoleCtrlHandler@8 +SetConsoleCursor=SetConsoleCursor@8 +SetConsoleCursorInfo=SetConsoleCursorInfo@8 +SetConsoleCursorPosition=SetConsoleCursorPosition@8 +SetConsoleDisplayMode=SetConsoleDisplayMode@12 +SetConsoleFont=SetConsoleFont@8 +SetConsoleHardwareState=SetConsoleHardwareState@12 +SetConsoleKeyShortcuts=SetConsoleKeyShortcuts@16 +SetConsoleMaximumWindowSize=SetConsoleMaximumWindowSize@8 +SetConsoleMenuClose=SetConsoleMenuClose@4 +SetConsoleMode=SetConsoleMode@8 +SetConsoleNumberOfCommandsA=SetConsoleNumberOfCommandsA@8 +SetConsoleNumberOfCommandsW=SetConsoleNumberOfCommandsW@8 +SetConsoleOutputCP=SetConsoleOutputCP@4 +SetConsolePalette=SetConsolePalette@12 +SetConsoleScreenBufferSize=SetConsoleScreenBufferSize@8 +SetConsoleTextAttribute=SetConsoleTextAttribute@8 +SetConsoleTitleA=SetConsoleTitleA@4 +SetConsoleTitleW=SetConsoleTitleW@4 +SetConsoleWindowInfo=SetConsoleWindowInfo@12 +SetCurrentDirectoryA=SetCurrentDirectoryA@4 +SetCurrentDirectoryW=SetCurrentDirectoryW@4 +SetDefaultCommConfigA=SetDefaultCommConfigA@12 +SetDefaultCommConfigW=SetDefaultCommConfigW@12 +SetEndOfFile=SetEndOfFile@4 +SetEnvironmentVariableA=SetEnvironmentVariableA@8 +SetEnvironmentVariableW=SetEnvironmentVariableW@8 +SetErrorMode=SetErrorMode@4 +SetEvent=SetEvent@4 +SetFileApisToANSI=SetFileApisToANSI@0 +SetFileApisToOEM=SetFileApisToOEM@0 +SetFileAttributesA=SetFileAttributesA@8 +SetFileAttributesW=SetFileAttributesW@8 +SetFilePointer=SetFilePointer@16 +SetFileTime=SetFileTime@16 +SetHandleCount=SetHandleCount@4 +SetHandleInformation=SetHandleInformation@12 +SetLastConsoleEventActive=SetLastConsoleEventActive@0 +SetLastError=SetLastError@4 +SetLastErrorByStatus=SetLastErrorByStatus@4 +SetLocalTime=SetLocalTime@4 +SetLocaleInfoA=SetLocaleInfoA@12 +SetLocaleInfoW=SetLocaleInfoW@12 +SetMailslotInfo=SetMailslotInfo@8 +SetNamedPipeHandleState=SetNamedPipeHandleState@16 +SetPriorityClass=SetPriorityClass@8 +SetProcessShutdownParameters=SetProcessShutdownParameters@8 +SetProcessWorkingSetSize=SetProcessWorkingSetSize@12 +SetStdHandle=SetStdHandle@8 +SetSystemPowerState=SetSystemPowerState@8 +SetSystemTime=SetSystemTime@4 +SetSystemTimeAdjustment=SetSystemTimeAdjustment@8 +SetTapeParameters=SetTapeParameters@12 +SetTapePosition=SetTapePosition@24 +SetThreadAffinityMask=SetThreadAffinityMask@8 +SetThreadContext=SetThreadContext@8 +SetThreadIdealProcessor=SetThreadIdealProcessor@8 +SetThreadLocale=SetThreadLocale@4 +SetThreadPriority=SetThreadPriority@8 +SetThreadPriorityBoost=SetThreadPriorityBoost@8 +SetTimeZoneInformation=SetTimeZoneInformation@4 +SetUnhandledExceptionFilter=SetUnhandledExceptionFilter@4 +SetVDMCurrentDirectories=SetVDMCurrentDirectories@8 +SetVolumeLabelA=SetVolumeLabelA@8 +SetVolumeLabelW=SetVolumeLabelW@8 +SetWaitableTimer=SetWaitableTimer@24 +SetupComm=SetupComm@12 +ShowConsoleCursor=ShowConsoleCursor@8 +SizeofResource=SizeofResource@8 +Sleep=Sleep@4 +SleepEx=SleepEx@8 +SuspendThread=SuspendThread@4 +SwitchToFiber=SwitchToFiber@4 +SwitchToThread=SwitchToThread@0 +SystemTimeToFileTime=SystemTimeToFileTime@8 +SystemTimeToTzSpecificLocalTime=SystemTimeToTzSpecificLocalTime@12 +TerminateProcess=TerminateProcess@8 +TerminateThread=TerminateThread@8 +TlsAlloc=TlsAlloc@0 +TlsFree=TlsFree@4 +TlsGetValue=TlsGetValue@4 +TlsSetValue=TlsSetValue@8 +TransactNamedPipe=TransactNamedPipe@28 +TransmitCommChar=TransmitCommChar@8 +TrimVirtualBuffer=TrimVirtualBuffer@4 +TryEnterCriticalSection=NTDLL.RtlTryEnterCriticalSection +UnhandledExceptionFilter=UnhandledExceptionFilter@4 +UnlockFile=UnlockFile@20 +UnlockFileEx=UnlockFileEx@20 +UnmapViewOfFile=UnmapViewOfFile@4 +UpdateResourceA=UpdateResourceA@24 +UpdateResourceW=UpdateResourceW@24 +VDMConsoleOperation=VDMConsoleOperation@8 +VDMOperationStarted=VDMOperationStarted@4 +VerLanguageNameA=VerLanguageNameA@12 +VerLanguageNameW=VerLanguageNameW@12 +VerifyConsoleIoHandle=VerifyConsoleIoHandle@4 +VirtualAlloc=VirtualAlloc@16 +VirtualAllocEx=VirtualAllocEx@20 +VirtualBufferExceptionHandler=VirtualBufferExceptionHandler@12 +VirtualFree=VirtualFree@12 +VirtualFreeEx=VirtualFreeEx@16 +VirtualLock=VirtualLock@8 +VirtualProtect=VirtualProtect@16 +VirtualProtectEx=VirtualProtectEx@20 +VirtualQuery=VirtualQuery@12 +VirtualQueryEx=VirtualQueryEx@16 +VirtualUnlock=VirtualUnlock@8 +WaitCommEvent=WaitCommEvent@12 +WaitForDebugEvent=WaitForDebugEvent@8 +WaitForMultipleObjects=WaitForMultipleObjects@16 +WaitForMultipleObjectsEx=WaitForMultipleObjectsEx@20 +WaitForSingleObject=WaitForSingleObject@8 +WaitForSingleObjectEx=WaitForSingleObjectEx@12 +WaitNamedPipeA=WaitNamedPipeA@8 +WaitNamedPipeW=WaitNamedPipeW@8 +WideCharToMultiByte=WideCharToMultiByte@32 +WinExec=WinExec@8 +WriteConsoleA=WriteConsoleA@20 +WriteConsoleInputA=WriteConsoleInputA@16 +WriteConsoleInputVDMA=WriteConsoleInputVDMA@16 +WriteConsoleInputVDMW=WriteConsoleInputVDMW@16 +WriteConsoleInputW=WriteConsoleInputW@16 +WriteConsoleOutputA=WriteConsoleOutputA@20 +WriteConsoleOutputAttribute=WriteConsoleOutputAttribute@20 +WriteConsoleOutputCharacterA=WriteConsoleOutputCharacterA@20 +WriteConsoleOutputCharacterW=WriteConsoleOutputCharacterW@20 +WriteConsoleOutputW=WriteConsoleOutputW@20 +WriteConsoleW=WriteConsoleW@20 +WriteFile=WriteFile@20 +WriteFileEx=WriteFileEx@20 +WritePrivateProfileSectionA=WritePrivateProfileSectionA@12 +WritePrivateProfileSectionW=WritePrivateProfileSectionW@12 +WritePrivateProfileStringA=WritePrivateProfileStringA@16 +WritePrivateProfileStringW=WritePrivateProfileStringW@16 +WritePrivateProfileStructA=WritePrivateProfileStructA@20 +WritePrivateProfileStructW=WritePrivateProfileStructW@20 +WriteProcessMemory=WriteProcessMemory@20 +WriteProfileSectionA=WriteProfileSectionA@8 +WriteProfileSectionW=WriteProfileSectionW@8 +WriteProfileStringA=WriteProfileStringA@12 +WriteProfileStringW=WriteProfileStringW@12 +WriteTapemark=WriteTapemark@16 +_hread=_hread@12 +_hwrite=_hwrite@12 +_lclose=_lclose@4 +_lcreat=_lcreat@8 +_llseek=_llseek@12 +_lopen=_lopen@8 +_lread=_hread@12 +_lwrite=_hwrite@12 +lstrcat=lstrcatA@8 +lstrcatA=lstrcatA@8 +lstrcatW=lstrcatW@8 +lstrcmp=lstrcmpA@8 +lstrcmpA=lstrcmpA@8 +lstrcmpW=lstrcmpW@8 +lstrcmpi=lstrcmpiA@8 +lstrcmpiA=lstrcmpiA@8 +lstrcmpiW=lstrcmpiW@8 +lstrcpy=lstrcpyA@8 +lstrcpyA=lstrcpyA@8 +lstrcpyW=lstrcpyW@8 +lstrcpyn=lstrcpynA@12 +lstrcpynA=lstrcpynA@12 +lstrcpynW=lstrcpynW@12 +lstrlen=lstrlenA@4 +lstrlenA=lstrlenA@4 +lstrlenW=lstrlenW@4 diff --git a/lib/kernel32/kernel32.rc b/lib/kernel32/kernel32.rc new file mode 100644 index 0000000..78588bb --- /dev/null +++ b/lib/kernel32/kernel32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "W32 subsystem kernel\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "kernel32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "kernel32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/kernel32/makefile b/lib/kernel32/makefile new file mode 100644 index 0000000..0753d54 --- /dev/null +++ b/lib/kernel32/makefile @@ -0,0 +1,95 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = kernel32 + +TARGET_BASE = 0x77f00000 + +TARGET_CFLAGS = -DKERNEL32_BASE=$(TARGET_DLLBASE) + +TARGET_LFLAGS = -nostartfiles + +TARGET_SDKLIBS = ntdll.a + +TARGET_GCCLIBS = gcc + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CLEAN = except/*.o file/*.o mem/*.o misc/*.o nls/*.o \ + process/*.o string/*.o synch/*.o thread/*.o + + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + + +SYNCH_OBJECTS = synch/critical.o synch/event.o synch/intrlck.o synch/mutex.o \ + synch/sem.o synch/timer.o synch/wait.o + +MISC_OBJECTS = misc/error.o misc/atom.o misc/handle.o misc/env.o \ + misc/dllmain.o misc/comm.o \ + misc/console.o misc/time.o misc/stubs.o misc/ldr.o misc/res.o \ + misc/debug.o misc/sysinfo.o misc/profile.o + +FILE_OBJECTS = file/file.o file/curdir.o file/lfile.o file/dir.o \ + file/iocompl.o file/volume.o file/deviceio.o file/dosdev.o \ + file/create.o file/find.o file/copy.o file/pipe.o \ + file/move.o file/lock.o file/rw.o file/delete.o \ + file/npipe.o file/tape.o file/mailslot.o file/backup.o \ + file/cnotify.o + +MEM_OBJECTS = mem/global.o mem/heap.o mem/isbad.o mem/local.o \ + mem/procmem.o mem/section.o mem/virtual.o + +NLS_OBJECTS = nls/codepage.o nls/cpmisc.o nls/cptable.o\ + nls/cp37.o nls/cp437.o nls/cp500.o nls/cp737.o nls/cp775.o nls/cp850.o nls/cp852.o nls/cp855.o nls/cp857.o\ + nls/cp860.o nls/cp861.o nls/cp863.o nls/cp865.o nls/cp866.o nls/cp869.o nls/cp875.o nls/cp1026.o\ + nls/cp1250.o nls/cp1251.o nls/cp1252.o nls/cp1253.o nls/cp1254.o nls/cp1255.o nls/cp1256.o nls/cp1257.o\ + nls/cp10000.o nls/cp10006.o nls/cp10007.o nls/cp10029.o nls/cp10079.o nls/cp10081.o\ + nls/lctable.o\ + nls/lcAFK.o nls/lcBEL.o nls/lcBGR.o nls/lcCAT.o nls/lcCSY.o nls/lcDAN.o\ + nls/lcDEA.o nls/lcDEC.o nls/lcDEL.o nls/lcDES.o nls/lcDEU.o\ + nls/lcELL.o\ + nls/lcENA.o nls/lcENB.o nls/lcENC.o nls/lcENG.o nls/lcENI.o nls/lcENJ.o nls/lcENL.o nls/lcENS.o nls/lcENT.o\ + nls/lcENU.o nls/lcENZ.o\ + nls/lcESA.o nls/lcESB.o nls/lcESC.o nls/lcESD.o nls/lcESE.o nls/lcESF.o nls/lcESG.o nls/lcESH.o nls/lcESI.o\ + nls/lcESL.o nls/lcESM.o nls/lcESN.o nls/lcESO.o nls/lcESP.o nls/lcESR.o nls/lcESS.o nls/lcESU.o nls/lcESV.o\ + nls/lcESY.o nls/lcESZ.o\ + nls/lcETI.o nls/lcEUQ.o nls/lcFIN.o nls/lcFOS.o\ + nls/lcFRA.o nls/lcFRB.o nls/lcFRC.o nls/lcFRL.o nls/lcFRS.o\ + nls/lcHRV.o nls/lcHUN.o nls/lcIND.o nls/lcISL.o nls/lcITA.o nls/lcITS.o nls/lcLTH.o nls/lcLVI.o nls/lcNLB.o\ + nls/lcNLD.o nls/lcNON.o nls/lcNOR.o nls/lcPLK.o nls/lcPTB.o nls/lcPTG.o nls/lcROM.o nls/lcRUS.o nls/lcSKY.o\ + nls/lcSLV.o nls/lcSQI.o nls/lcSRB.o nls/lcSRL.o nls/lcSVE.o nls/lcSVF.o nls/lcTRK.o nls/lcUKR.o\ + nls/locale.o nls/mbtowc.o nls/wctomb.o nls/ole2nls.o + +THREAD_OBJECTS = \ + thread/fiber.o \ + thread/thread.o \ + thread/tls.o + +PROCESS_OBJECTS = \ + process/proc.o \ + process/cmdline.o \ + process/create.o \ + process/session.o + +STRING_OBJECTS = string/lstring.o + +EXCEPT_OBJECTS = except/except.o + +OBJECTS = $(MISC_OBJECTS) $(FILE_OBJECTS) $(THREAD_OBJECTS) \ + $(PROCESS_OBJECTS) $(STRING_OBJECTS) $(MEM_OBJECTS) \ + $(SYNCH_OBJECTS) $(EXCEPT_OBJECTS) + +$(TARGET_NAME).o: $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o + +%/TAGS: + etags -o $(@D)/TAGS $(@D)/\*.c + +etags: except/TAGS file/TAGS mem/TAGS misc/TAGS nls/TAGS process/TAGS string/TAGS synch/TAGS thread/TAGS + etags -i except/TAGS -i file/TAGS -i mem/TAGS -i misc/TAGS -i nls/TAGS -i process/TAGS -i string/TAGS -i synch/TAGS -i thread/TAGS diff --git a/lib/kernel32/mem/.cvsignore b/lib/kernel32/mem/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/mem/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/mem/global.c b/lib/kernel32/mem/global.c new file mode 100644 index 0000000..9fddbff --- /dev/null +++ b/lib/kernel32/mem/global.c @@ -0,0 +1,444 @@ +/* $Id$ + * + * Win32 Global/Local heap functions (GlobalXXX, LocalXXX). + * These functions included in Win32 for compatibility with 16 bit Windows + * Especially the moveable blocks and handles are oldish. + * But the ability to directly allocate memory with GPTR and LPTR is widely + * used. + */ + +/* + * NOTE: Only fixed memory is implemented!! + */ + +#include +#include +#include + +#define NDEBUG +#include + +#if 0 +#define MAGIC_GLOBAL_USED 0x5342BEEF +#define GLOBAL_LOCK_MAX 0xFF + +typedef struct __GLOBAL_LOCAL_HANDLE +{ + ULONG Magic; + LPVOID Pointer; + BYTE Flags; + BYTE LockCount; +} GLOBAL_HANDLE, LOCAL_HANDLE, *PGLOBAL_HANDLE, *PLOCAL_HANDLE; +#endif + +/* FUNCTIONS ***************************************************************/ + +HGLOBAL STDCALL +GlobalAlloc(UINT uFlags, + DWORD dwBytes) +{ +#if 0 + PGLOBAL_HANDLE phandle; + PVOID palloc; +#endif + + DPRINT("GlobalAlloc( 0x%X, 0x%lX )\n", uFlags, dwBytes); + + if ((uFlags & GMEM_MOVEABLE)==0) /* POINTER */ + { + if ((uFlags & GMEM_ZEROINIT)==0) + return ((HGLOBAL)RtlAllocateHeap(hProcessHeap, 0, dwBytes)); + else + return ((HGLOBAL)RtlAllocateHeap(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes)); + } + else /* HANDLE */ + { +#if 0 + HeapLock(__ProcessHeap); + + + phandle=__HeapAllocFragment(__ProcessHeap, 0, sizeof(GLOBAL_HANDLE)); + if(dwBytes) + { + palloc=HeapAlloc(__ProcessHeap, 0, size+sizeof(HANDLE)); + *(PHANDLE)palloc=(HANDLE) &(phandle->Pointer); + phandle->Pointer=palloc+sizeof(HANDLE); + } + else + phandle->Pointer=NULL; + phandle->Magic=MAGIC_GLOBAL_USED; + phandle->Flags=uFlags>>8; + phandle->LockCount=0; + HeapUnlock(__ProcessHeap); + + return (HGLOBAL) &(phandle->Pointer); +#endif + return (HGLOBAL)NULL; + } +} + + +UINT STDCALL +GlobalCompact(DWORD dwMinFree) +{ + return RtlCompactHeap(hProcessHeap, 0); +} + + +VOID STDCALL +GlobalFix(HGLOBAL hMem) +{ + if (hMem != INVALID_HANDLE_VALUE) + GlobalLock(hMem); +} + + +UINT STDCALL +GlobalFlags(HGLOBAL hMem) +{ +#if 0 + DWORD retval; + PGLOBAL_HANDLE phandle; +#endif + + DPRINT("GlobalFlags( 0x%lX )\n", (ULONG)hMem); + +#if 0 + if(((ULONG)hmem%8)==0) + { + retval=0; + } + else + { + HeapLock(__ProcessHeap); + phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4); + if(phandle->Magic==MAGIC_GLOBAL_USED) + { + retval=phandle->LockCount + (phandle->Flags<<8); + if(phandle->Pointer==0) + retval|= LMEM_DISCARDED; + } + else + { + DPRINT("GlobalSize: invalid handle\n"); + retval=0; + } + HeapUnlock(__ProcessHeap); + } + return retval; +#endif + + return 0; +} + + +HGLOBAL STDCALL +GlobalFree(HGLOBAL hMem) +{ +#if 0 + PGLOBAL_HANDLE phandle; +#endif + + DPRINT("GlobalFree( 0x%lX )\n", (ULONG)hMem); + + if (((ULONG)hMem % 4) == 0) /* POINTER */ + { + RtlFreeHeap(hProcessHeap, 0, (PVOID)hMem); + } + else /* HANDLE */ + { +#if 0 + HeapLock(__ProcessHeap); + phandle=(PGLOBAL_HANDLE)(((LPVOID) hMem)-4); + if(phandle->Magic==MAGIC_GLOBAL_USED) + { + HeapLock(__ProcessHeap); + if(phandle->LockCount!=0) + SetLastError(ERROR_INVALID_HANDLE); + if(phandle->Pointer) + HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, phandle->Pointer-sizeof(HANDLE)); + __HeapFreeFragment(__ProcessHeap, 0, phandle); + } + HeapUnlock(__ProcessHeap); +#endif + hMem = NULL; + } + return hMem; +} + + +HGLOBAL STDCALL +GlobalHandle(LPCVOID pMem) +{ + DPRINT("GlobalHandle( 0x%lX )\n", (ULONG)pMem); + +#if 0 + if(((ULONG)pmem%8)==0) /* FIXED */ + return (HGLOBAL) pmem; + else /* MOVEABLE */ + return (HGLOBAL) *(LPVOID *)(pmem-sizeof(HANDLE)); +#endif + + return (HGLOBAL)pMem; +} + + +LPVOID STDCALL +GlobalLock(HGLOBAL hMem) +{ +#if 0 + PGLOBAL_HANDLE phandle; + LPVOID palloc; +#endif + + DPRINT("GlobalLock( 0x%lX )\n", (ULONG)hMem); + +#if 0 + if(((ULONG)hmem%8)==0) + return (LPVOID) hmem; + + HeapLock(__ProcessHeap); + phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4); + if(phandle->Magic==MAGIC_GLOBAL_USED) + { + if(phandle->LockCountLockCount++; + palloc=phandle->Pointer; + } + else + { + DPRINT("GlobalLock: invalid handle\n"); + palloc=(LPVOID) hmem; + } + HeapUnlock(__ProcessHeap); + return palloc; +#else + return (LPVOID)hMem; +#endif +} + + +VOID STDCALL +GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) +{ + NTSTATUS Status; + SYSTEM_PERFORMANCE_INFO Spi; + QUOTA_LIMITS Ql; + VM_COUNTERS Vmc; + PIMAGE_NT_HEADERS ImageNtHeader; + + RtlZeroMemory (lpBuffer, sizeof (MEMORYSTATUS)); + lpBuffer->dwLength = sizeof (MEMORYSTATUS); + Status = NtQuerySystemInformation ( + SystemPerformanceInformation, + & Spi, + sizeof Spi, + NULL + ); + /* FIXME: perform computations and fill lpBuffer fields */ + Status = NtQueryInformationProcess ( + GetCurrentProcess(), + ProcessQuotaLimits, + & Ql, + sizeof Ql, + NULL + ); + /* FIXME: perform computations and fill lpBuffer fields */ + Status = NtQueryInformationProcess ( + GetCurrentProcess(), + ProcessVmCounters, + & Vmc, + sizeof Vmc, + NULL + ); + /* FIXME: perform computations and fill lpBuffer fields */ + ImageNtHeader = RtlImageNtHeader ((PVOID)NtCurrentPeb()->ImageBaseAddress); + /* FIXME: perform computations and fill lpBuffer fields */ +} + + +HGLOBAL STDCALL +GlobalReAlloc(HGLOBAL hMem, + DWORD dwBytes, + UINT uFlags) +{ +#if 0 + LPVOID palloc; + HGLOBAL hnew; + PGLOBAL_HANDLE phandle; +#endif + + DPRINT("GlobalReAlloc( 0x%lX, 0x%lX, 0x%X )\n", (ULONG)hMem, dwBytes, uFlags); + +#if 0 + hnew=NULL; + HeapLock(__ProcessHeap); + if(flags & GMEM_MODIFY) /* modify flags */ + { + if( (((ULONG)hmem%8)==0) && (flags & GMEM_MOVEABLE)) + { + /* make a fixed block moveable + * actually only NT is able to do this. And it's soo simple + */ + size=HeapSize(__ProcessHeap, 0, (LPVOID) hmem); + hnew=GlobalAlloc( flags, size); + palloc=GlobalLock(hnew); + memcpy(palloc, (LPVOID) hmem, size); + GlobalUnlock(hnew); + GlobalHeapFree(GetProcessHeap(),0,hmem); + } + else if((((ULONG)hmem%8) != 0)&&(flags & GMEM_DISCARDABLE)) + { + /* change the flags to make our block "discardable" */ + phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4); + phandle->Flags = phandle->Flags | (GMEM_DISCARDABLE >> 8); + hnew=hmem; + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + hnew=NULL; + } + } + else + { + if(((ULONG)hmem%8)!=0) + { + /* reallocate fixed memory */ + hnew=(HANDLE)HeapReAlloc(__ProcessHeap, 0, (LPVOID) hmem, size); + } + else + { + /* reallocate a moveable block */ + phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4); + if(phandle->LockCount!=0) + SetLastError(ERROR_INVALID_HANDLE); + else if(size!=0) + { + hnew=hmem; + if(phandle->Pointer) + { + palloc=HeapReAlloc(__ProcessHeap, 0, + phandle->Pointer-sizeof(HANDLE), + size+sizeof(HANDLE) ); + phandle->Pointer=palloc+sizeof(HANDLE); + } + else + { + palloc=HeapAlloc(__ProcessHeap, 0, size+sizeof(HANDLE)); + *(PHANDLE)palloc=hmem; + phandle->Pointer=palloc+sizeof(HANDLE); + } + } + else + { + if(phandle->Pointer) + { + HeapHeapFree(GetProcessHeap(),0,__ProcessHeap, 0, phandle->Pointer-sizeof(HANDLE)); + phandle->Pointer=NULL; + } + } + } + } + HeapUnlock(__ProcessHeap); + return hnew; +#else + return ((HGLOBAL)RtlReAllocateHeap(hProcessHeap, uFlags, (LPVOID)hMem, dwBytes)); +#endif +} + + +DWORD STDCALL +GlobalSize(HGLOBAL hMem) +{ + DWORD retval; +#if 0 + PGLOBAL_HANDLE phandle; +#endif + + DPRINT("GlobalSize( 0x%lX )\n", (ULONG)hMem); + + if(((ULONG)hMem % 4) == 0) + { + retval = RtlSizeHeap(hProcessHeap, 0, hMem); + } + else + { +#if 0 + HeapLock(__ProcessHeap); + phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4); + if(phandle->Magic==MAGIC_GLOBAL_USED) + { + retval=HeapSize(__ProcessHeap, 0, (phandle->Pointer)-sizeof(HANDLE))-4; + } + else + { + DPRINT("GlobalSize: invalid handle\n"); + retval=0; + } + HeapUnlock(__ProcessHeap); +#endif + retval = 0; + } + return retval; +} + + +VOID STDCALL +GlobalUnfix(HGLOBAL hMem) +{ + if (hMem != INVALID_HANDLE_VALUE) + GlobalUnlock(hMem); +} + + +BOOL STDCALL +GlobalUnlock(HGLOBAL hMem) +{ +#if 0 + PGLOBAL_HANDLE phandle; + BOOL locked; +#endif + + DPRINT("GlobalUnlock( 0x%lX )\n", (ULONG)hMem); + +#if 0 + if(((ULONG)hmem%8)==0) + return FALSE; + + HeapLock(__ProcessHeap); + phandle=(PGLOBAL_HANDLE)(((LPVOID) hmem)-4); + if(phandle->Magic==MAGIC_GLOBAL_USED) + { + if((phandle->LockCountLockCount>0)) + phandle->LockCount--; + + locked=(phandle->LockCount==0) ? TRUE : FALSE; + } + else + { + DPRINT("GlobalUnlock: invalid handle\n"); + locked=FALSE; + } + HeapUnlock(__ProcessHeap); + return locked; +#endif + + return TRUE; +} + + +BOOL STDCALL +GlobalUnWire(HGLOBAL hMem) +{ + return GlobalUnlock(hMem); +} + + +LPVOID STDCALL +GlobalWire(HGLOBAL hMem) +{ + return GlobalLock(hMem); +} + +/* EOF */ diff --git a/lib/kernel32/mem/heap.c b/lib/kernel32/mem/heap.c new file mode 100644 index 0000000..05c906c --- /dev/null +++ b/lib/kernel32/mem/heap.c @@ -0,0 +1,202 @@ +/* $Id$ + * + * kernel/heap.c + * Copyright (C) 1996, Onno Hovers, All rights reserved + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; see the file COPYING.LIB. If + * not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + * + * Win32 heap functions (HeapXXX). + * + */ + +/* + * Adapted for the ReactOS system libraries by David Welch (welch@mcmail.com) + * Put the type definitions of the heap in a seperate header. Boudewijn Dekker + */ + +#include +#include + +#define NDEBUG +#include + +/********************************************************************* +* HeapCreate -- KERNEL32 * +*********************************************************************/ +HANDLE STDCALL HeapCreate(DWORD flags, DWORD minsize, DWORD maxsize) +{ + + DPRINT("HeapCreate( 0x%lX, 0x%lX, 0x%lX )\n", flags, minsize, maxsize); + return(RtlCreateHeap(flags, NULL, maxsize, minsize, NULL, NULL)); +} + +/********************************************************************* +* HeapDestroy -- KERNEL32 * +*********************************************************************/ +BOOL WINAPI HeapDestroy(HANDLE hheap) +{ + return(RtlDestroyHeap(hheap)); +} + +/********************************************************************* +* GetProcessHeap -- KERNEL32 * +*********************************************************************/ +HANDLE WINAPI GetProcessHeap(VOID) +{ + DPRINT("GetProcessHeap()\n"); + return(RtlGetProcessHeap()); +} + +/******************************************************************** +* GetProcessHeaps -- KERNEL32 * +********************************************************************/ +DWORD WINAPI GetProcessHeaps(DWORD maxheaps, PHANDLE phandles ) +{ + return(RtlGetProcessHeaps(maxheaps, phandles)); +} + +/********************************************************************* +* HeapLock -- KERNEL32 * +*********************************************************************/ +BOOL WINAPI HeapLock(HANDLE hheap) +{ + return(RtlLockHeap(hheap)); +} + +/********************************************************************* +* HeapUnlock -- KERNEL32 * +*********************************************************************/ +BOOL WINAPI HeapUnlock(HANDLE hheap) +{ + return(RtlUnlockHeap(hheap)); +} + +/********************************************************************* +* HeapCompact -- KERNEL32 * +* * +* NT uses this function to compact moveable blocks and other things * +* Here it does not compact, but it finds the largest free region * +*********************************************************************/ +UINT WINAPI HeapCompact(HANDLE hheap, DWORD flags) +{ + return RtlCompactHeap(hheap, flags); +} + +/********************************************************************* +* HeapValidate -- KERNEL32 * +*********************************************************************/ +BOOL WINAPI HeapValidate(HANDLE hheap, DWORD flags, LPCVOID pmem) +{ + return(RtlValidateHeap(hheap, flags, (PVOID)pmem)); +} + + +DWORD +STDCALL +HeapCreateTagsW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +HeapExtend ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ +#if 0 + NTSTATUS Status; + + Status = RtlExtendHeap(Unknown1, Unknown2, Unknown3, Unknown4); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + return TRUE; +#endif + + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +HeapQueryTagW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +HeapSummary ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +HeapUsage ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL +STDCALL +HeapWalk ( + HANDLE hHeap, + LPPROCESS_HEAP_ENTRY lpEntry + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* EOF */ diff --git a/lib/kernel32/mem/isbad.c b/lib/kernel32/mem/isbad.c new file mode 100644 index 0000000..3be0666 --- /dev/null +++ b/lib/kernel32/mem/isbad.c @@ -0,0 +1,219 @@ +/* $Id$ + * + * lib/kernel32/mem/isbad.c + * + * ReactOS Operating System + * + */ +#include + +/* FIXME: Stubs. What is it for? */ +UINT +wcsnlen ( + LPCWSTR lpsz, + UINT ucchMax + ) +{ + return 0; +} + + +/* FIXME: Stubs. What is it for? */ +UINT +strnlen ( + LPCSTR lpsz, + UINT uiMax + ) +{ + return 0; +} + +/* --- --- --- */ + +WINBOOL +STDCALL +IsBadReadPtr ( + CONST VOID * lp, + UINT ucb + ) +{ + MEMORY_BASIC_INFORMATION MemoryInformation; + + if ( ucb == 0 ) + { + return FALSE; + } + + VirtualQuery ( + lp, + & MemoryInformation, + sizeof (MEMORY_BASIC_INFORMATION) + ); + + if ( MemoryInformation.State != MEM_COMMIT ) + { + return FALSE; + } + + if ( MemoryInformation.RegionSize < ucb ) + { + return FALSE; + } + + if ( MemoryInformation.Protect == PAGE_EXECUTE ) + { + return FALSE; + } + + if ( MemoryInformation.Protect == PAGE_NOACCESS ) + { + return FALSE; + } + + return TRUE; + +} + + +WINBOOL +STDCALL +IsBadHugeReadPtr ( + CONST VOID * lp, + UINT ucb + ) +{ + return IsBadReadPtr (lp, ucb); +} + + +WINBOOL +STDCALL +IsBadCodePtr ( + FARPROC lpfn + ) +{ + MEMORY_BASIC_INFORMATION MemoryInformation; + + + VirtualQuery ( + lpfn, + & MemoryInformation, + sizeof (MEMORY_BASIC_INFORMATION) + ); + + if ( MemoryInformation.State != MEM_COMMIT ) + { + return FALSE; + } + + if ( (MemoryInformation.Protect == PAGE_EXECUTE) + || (MemoryInformation.Protect == PAGE_EXECUTE_READ) + ) + { + return TRUE; + } + + return FALSE; +} + + +WINBOOL +STDCALL +IsBadWritePtr ( + LPVOID lp, + UINT ucb + ) +{ + MEMORY_BASIC_INFORMATION MemoryInformation; + + if ( ucb == 0 ) + { + return FALSE; + } + + VirtualQuery ( + lp, + & MemoryInformation, + sizeof (MEMORY_BASIC_INFORMATION) + ); + + if ( MemoryInformation.State != MEM_COMMIT ) + { + return FALSE; + } + + if ( MemoryInformation.RegionSize < ucb ) + { + return FALSE; + } + + + if ( MemoryInformation.Protect == PAGE_READONLY) + { + return FALSE; + } + + if ( (MemoryInformation.Protect == PAGE_EXECUTE) + || (MemoryInformation.Protect == PAGE_EXECUTE_READ) + ) + { + return FALSE; + } + + if ( MemoryInformation.Protect == PAGE_NOACCESS ) + { + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +IsBadHugeWritePtr ( + LPVOID lp, + UINT ucb + ) +{ + return IsBadWritePtr (lp, ucb); +} + + +WINBOOL +STDCALL +IsBadStringPtrW ( + LPCWSTR lpsz, + UINT ucchMax + ) +{ + UINT Len = wcsnlen ( + lpsz + 1, + ucchMax >> 1 + ); + return IsBadReadPtr ( + lpsz, + Len << 1 + ); +} + + +WINBOOL +STDCALL +IsBadStringPtrA ( + LPCSTR lpsz, + UINT ucchMax + ) +{ + UINT Len = strnlen ( + lpsz + 1, + ucchMax + ); + return IsBadReadPtr ( + lpsz, + Len + ); +} + + +/* EOF */ diff --git a/lib/kernel32/mem/local.c b/lib/kernel32/mem/local.c new file mode 100644 index 0000000..c0a0391 --- /dev/null +++ b/lib/kernel32/mem/local.c @@ -0,0 +1,106 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1996, Onno Hovers, All rights reserved + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/mem/local.c + * PURPOSE: Manages the local heap + * PROGRAMER: Onno Hovers (original wfc version) + * David Welch (adapted for ReactOS) + * UPDATE HISTORY: + * 9/4/98: Adapted from the wfc project + */ + + +/* NOTES + * + * The local heap is the same as the global heap for win32 and both are only + * required for legacy apps + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + + +HLOCAL STDCALL +LocalAlloc(UINT uFlags, + UINT uBytes) +{ + return (HLOCAL)GlobalAlloc(uFlags, uBytes); +} + + +UINT STDCALL +LocalCompact(UINT uMinFree) +{ + return RtlCompactHeap(hProcessHeap, 0); +} + + +UINT STDCALL +LocalFlags(HLOCAL hMem) +{ + return GlobalFlags((HGLOBAL)hMem); +} + + +HLOCAL STDCALL +LocalFree(HLOCAL hMem) +{ + return (HLOCAL)GlobalFree((HGLOBAL)hMem); +} + + +HLOCAL STDCALL +LocalHandle(LPCVOID pMem) +{ + return (HLOCAL)GlobalHandle(pMem); +} + + +LPVOID STDCALL +LocalLock(HLOCAL hMem) +{ + return GlobalLock((HGLOBAL)hMem); +} + + +HLOCAL STDCALL +LocalReAlloc(HLOCAL hMem, + UINT uBytes, + UINT uFlags) +{ + return (HLOCAL)GlobalReAlloc((HGLOBAL)hMem, uBytes, uFlags); +} + + +UINT STDCALL +LocalShrink(HLOCAL hMem, UINT cbNewSize) +{ + return RtlCompactHeap(hProcessHeap, 0); +} + + +UINT STDCALL +LocalSize(HLOCAL hMem) +{ + return GlobalSize((HGLOBAL)hMem); +} + + +BOOL STDCALL +LocalUnlock(HLOCAL hMem) +{ + return GlobalUnlock((HGLOBAL)hMem); +} + +/* EOF */ diff --git a/lib/kernel32/mem/procmem.c b/lib/kernel32/mem/procmem.c new file mode 100644 index 0000000..3a2b0f8 --- /dev/null +++ b/lib/kernel32/mem/procmem.c @@ -0,0 +1,69 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/kernel32/mem/procmem.c + * PURPOSE: + * PROGRAMMER: Boudewijn Dekker + */ + +/* INCLUDES ******************************************************************/ + + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ +WINBOOL +STDCALL +ReadProcessMemory ( + HANDLE hProcess, + LPCVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesRead + ) +{ + + NTSTATUS Status; + + Status = NtReadVirtualMemory( hProcess, (PVOID)lpBaseAddress,lpBuffer, nSize, + (PULONG)lpNumberOfBytesRead + ); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + return TRUE; +} + + +WINBOOL +STDCALL +WriteProcessMemory ( + HANDLE hProcess, + LPVOID lpBaseAddress, + LPVOID lpBuffer, + DWORD nSize, + LPDWORD lpNumberOfBytesWritten + ) +{ + NTSTATUS Status; + + Status = NtWriteVirtualMemory( hProcess, lpBaseAddress,lpBuffer, nSize, + (PULONG)lpNumberOfBytesWritten + ); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + return TRUE; +} + + +/* EOF */ diff --git a/lib/kernel32/mem/section.c b/lib/kernel32/mem/section.c new file mode 100644 index 0000000..42c8204 --- /dev/null +++ b/lib/kernel32/mem/section.c @@ -0,0 +1,309 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/kernel32/mem/section.c + * PURPOSE: Implementing file mapping + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +HANDLE STDCALL +CreateFileMappingA(HANDLE hFile, + LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + DWORD flProtect, + DWORD dwMaximumSizeHigh, + DWORD dwMaximumSizeLow, + LPCSTR lpName) +{ + NTSTATUS Status; + HANDLE SectionHandle; + LARGE_INTEGER MaximumSize; + OBJECT_ATTRIBUTES ObjectAttributes; + ANSI_STRING AnsiName; + UNICODE_STRING UnicodeName; + PSECURITY_DESCRIPTOR SecurityDescriptor; + + if (lpFileMappingAttributes) + { + SecurityDescriptor = lpFileMappingAttributes->lpSecurityDescriptor; + } + else + { + SecurityDescriptor = NULL; + } + + MaximumSize.u.LowPart = dwMaximumSizeLow; + MaximumSize.u.HighPart = dwMaximumSizeHigh; + RtlInitAnsiString(&AnsiName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&UnicodeName, + &AnsiName, + TRUE); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeName, + 0, + hBaseDir, + SecurityDescriptor); + Status = NtCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + &ObjectAttributes, + &MaximumSize, + flProtect, + 0, + hFile); + RtlFreeUnicodeString(&UnicodeName); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + return SectionHandle; +} + + +HANDLE STDCALL +CreateFileMappingW(HANDLE hFile, + LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + DWORD flProtect, + DWORD dwMaximumSizeHigh, + DWORD dwMaximumSizeLow, + LPCWSTR lpName) +{ + NTSTATUS Status; + HANDLE SectionHandle; + LARGE_INTEGER MaximumSize; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeName; + PSECURITY_DESCRIPTOR SecurityDescriptor; + + if (lpFileMappingAttributes) + { + SecurityDescriptor = lpFileMappingAttributes->lpSecurityDescriptor; + } + else + { + SecurityDescriptor = NULL; + } + + MaximumSize.u.LowPart = dwMaximumSizeLow; + MaximumSize.u.HighPart = dwMaximumSizeHigh; + RtlInitUnicodeString(&UnicodeName, + lpName); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeName, + 0, + hBaseDir, + SecurityDescriptor); + Status = NtCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + &ObjectAttributes, + &MaximumSize, + flProtect, + 0, + hFile); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + return SectionHandle; +} + + +LPVOID STDCALL +MapViewOfFileEx(HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + DWORD dwNumberOfBytesToMap, + LPVOID lpBaseAddress) +{ + NTSTATUS Status; + LARGE_INTEGER SectionOffset; + ULONG ViewSize; + ULONG Protect; + LPVOID BaseAddress; + + SectionOffset.u.LowPart = dwFileOffsetLow; + SectionOffset.u.HighPart = dwFileOffsetHigh; + + if ( ( dwDesiredAccess & FILE_MAP_WRITE) == FILE_MAP_WRITE) + Protect = PAGE_READWRITE; + else if ((dwDesiredAccess & FILE_MAP_READ) == FILE_MAP_READ) + Protect = PAGE_READONLY; + else if ((dwDesiredAccess & FILE_MAP_ALL_ACCESS) == FILE_MAP_ALL_ACCESS) + Protect = PAGE_READWRITE; + else if ((dwDesiredAccess & FILE_MAP_COPY) == FILE_MAP_COPY) + Protect = PAGE_WRITECOPY; + else + Protect = PAGE_READWRITE; + + if (lpBaseAddress == NULL) + { + BaseAddress = NULL; + } + else + { + BaseAddress = lpBaseAddress; + } + + ViewSize = (ULONG) dwNumberOfBytesToMap; + + Status = ZwMapViewOfSection(hFileMappingObject, + NtCurrentProcess(), + &BaseAddress, + 0, + dwNumberOfBytesToMap, + &SectionOffset, + &ViewSize, + ViewShare, + 0, + Protect); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + return BaseAddress; +} + + +LPVOID STDCALL +MapViewOfFile(HANDLE hFileMappingObject, + DWORD dwDesiredAccess, + DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, + DWORD dwNumberOfBytesToMap) +{ + return MapViewOfFileEx(hFileMappingObject, + dwDesiredAccess, + dwFileOffsetHigh, + dwFileOffsetLow, + dwNumberOfBytesToMap, + NULL); +} + + +WINBOOL STDCALL +UnmapViewOfFile(LPVOID lpBaseAddress) +{ + NTSTATUS Status; + + Status = NtUnmapViewOfSection(NtCurrentProcess(), + lpBaseAddress); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + return TRUE; +} + + +HANDLE STDCALL +OpenFileMappingA(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName) +{ + NTSTATUS Status; + HANDLE SectionHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + ANSI_STRING AnsiName; + UNICODE_STRING UnicodeName; + + ULONG Attributes = 0; + + if (bInheritHandle) + { + Attributes = OBJ_INHERIT; + } + + RtlInitAnsiString(&AnsiName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&UnicodeName, + &AnsiName, + TRUE); + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeName, + Attributes, + hBaseDir, + NULL); + Status = NtOpenSection(&SectionHandle, + SECTION_ALL_ACCESS, + &ObjectAttributes); + RtlFreeUnicodeString (&UnicodeName); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return NULL; + } + return SectionHandle; +} + + +HANDLE STDCALL +OpenFileMappingW(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName) +{ + NTSTATUS Status; + HANDLE SectionHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeName; + ULONG Attributes = 0; + + if (bInheritHandle) + { + Attributes = OBJ_INHERIT; + } + + RtlInitUnicodeString(&UnicodeName, + lpName); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeName, + Attributes, + hBaseDir, + NULL); + Status = ZwOpenSection(&SectionHandle, + SECTION_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + return SectionHandle; +} + + +WINBOOL STDCALL +FlushViewOfFile(LPCVOID lpBaseAddress, + DWORD dwNumberOfBytesToFlush) +{ + NTSTATUS Status; + ULONG NumberOfBytesFlushed; + + Status = NtFlushVirtualMemory(NtCurrentProcess(), + (LPVOID)lpBaseAddress, + dwNumberOfBytesToFlush, + &NumberOfBytesFlushed); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/mem/virtual.c b/lib/kernel32/mem/virtual.c new file mode 100644 index 0000000..1b5a52a --- /dev/null +++ b/lib/kernel32/mem/virtual.c @@ -0,0 +1,201 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/kernel32/mem/virtual.c + * PURPOSE: Passing the Virtualxxx functions onto the kernel + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +LPVOID STDCALL +VirtualAllocEx(HANDLE hProcess, + LPVOID lpAddress, + DWORD dwSize, + DWORD flAllocationType, + DWORD flProtect) +{ + NTSTATUS Status; + + Status = NtAllocateVirtualMemory(hProcess, + (PVOID *)&lpAddress, + 0, + (PULONG)&dwSize, + flAllocationType, + flProtect); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(NULL); + } + return(lpAddress); +} + + +LPVOID STDCALL +VirtualAlloc(LPVOID lpAddress, + DWORD dwSize, + DWORD flAllocationType, + DWORD flProtect) +{ + return(VirtualAllocEx(GetCurrentProcess(), + lpAddress, + dwSize, + flAllocationType, + flProtect)); +} + + +WINBOOL STDCALL +VirtualFreeEx(HANDLE hProcess, + LPVOID lpAddress, + DWORD dwSize, + DWORD dwFreeType) +{ + NTSTATUS Status; + + Status = NtFreeVirtualMemory(hProcess, + (PVOID *)&lpAddress, + (PULONG)&dwSize, + dwFreeType); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); +} + + +WINBOOL STDCALL +VirtualFree(LPVOID lpAddress, + DWORD dwSize, + DWORD dwFreeType) +{ + return(VirtualFreeEx(GetCurrentProcess(), + lpAddress, + dwSize, + dwFreeType)); +} + + +WINBOOL STDCALL +VirtualProtect(LPVOID lpAddress, + DWORD dwSize, + DWORD flNewProtect, + PDWORD lpflOldProtect) +{ + return(VirtualProtectEx(GetCurrentProcess(), + lpAddress, + dwSize, + flNewProtect, + lpflOldProtect)); +} + + +WINBOOL STDCALL +VirtualProtectEx(HANDLE hProcess, + LPVOID lpAddress, + DWORD dwSize, + DWORD flNewProtect, + PDWORD lpflOldProtect) +{ + NTSTATUS Status; + + Status = NtProtectVirtualMemory(hProcess, + (PVOID)lpAddress, + dwSize, + flNewProtect, + (PULONG)lpflOldProtect); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); +} + + +WINBOOL STDCALL +VirtualLock(LPVOID lpAddress, + DWORD dwSize) +{ + ULONG BytesLocked; + NTSTATUS Status; + + Status = NtLockVirtualMemory(NtCurrentProcess(), + lpAddress, + dwSize, + &BytesLocked); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); +} + + +DWORD STDCALL +VirtualQuery(LPCVOID lpAddress, + PMEMORY_BASIC_INFORMATION lpBuffer, + DWORD dwLength) +{ + return(VirtualQueryEx(NtCurrentProcess(), + lpAddress, + lpBuffer, + dwLength)); +} + + +DWORD STDCALL +VirtualQueryEx(HANDLE hProcess, + LPCVOID lpAddress, + PMEMORY_BASIC_INFORMATION lpBuffer, + DWORD dwLength) +{ + NTSTATUS Status; + ULONG ResultLength; + + Status = NtQueryVirtualMemory(hProcess, + (LPVOID)lpAddress, + MemoryBasicInformation, + lpBuffer, + sizeof(MEMORY_BASIC_INFORMATION), + &ResultLength ); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(ResultLength); + } + return(ResultLength); +} + + +WINBOOL STDCALL +VirtualUnlock(LPVOID lpAddress, + DWORD dwSize) +{ + ULONG BytesLocked; + NTSTATUS Status; + + Status = NtUnlockVirtualMemory(NtCurrentProcess(), + lpAddress, + dwSize, + &BytesLocked); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + return(TRUE); +} + +/* EOF */ diff --git a/lib/kernel32/misc/.cvsignore b/lib/kernel32/misc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/misc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/misc/atom.c b/lib/kernel32/misc/atom.c new file mode 100644 index 0000000..64e59d4 --- /dev/null +++ b/lib/kernel32/misc/atom.c @@ -0,0 +1,536 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/atom.c + * PURPOSE: Atom functions + * PROGRAMMER: Eric Kohl ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + * Full rewrite 27/05/2001 + */ + +#include +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +static PRTL_ATOM_TABLE LocalAtomTable = NULL; + +static PRTL_ATOM_TABLE GetLocalAtomTable(VOID); + + +/* FUNCTIONS *****************************************************************/ + +ATOM STDCALL +GlobalAddAtomA(LPCSTR lpString) +{ + UNICODE_STRING AtomName; + NTSTATUS Status; + ATOM Atom; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + RtlCreateUnicodeStringFromAsciiz(&AtomName, + (LPSTR)lpString); + + Status = NtAddAtom(AtomName.Buffer, + &Atom); + RtlFreeUnicodeString(&AtomName); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +ATOM STDCALL +GlobalAddAtomW(LPCWSTR lpString) +{ + ATOM Atom; + NTSTATUS Status; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + Status = NtAddAtom((LPWSTR)lpString, + &Atom); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +ATOM STDCALL +GlobalDeleteAtom(ATOM nAtom) +{ + NTSTATUS Status; + + if (nAtom < 0xC000) + { + return 0; + } + + Status = NtDeleteAtom(nAtom); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return nAtom; + } + + return 0; +} + + +ATOM STDCALL +GlobalFindAtomA(LPCSTR lpString) +{ + UNICODE_STRING AtomName; + NTSTATUS Status; + ATOM Atom; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + RtlCreateUnicodeStringFromAsciiz(&AtomName, + (LPSTR)lpString); + Status = NtFindAtom(AtomName.Buffer, + &Atom); + RtlFreeUnicodeString(&AtomName); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +ATOM STDCALL +GlobalFindAtomW(LPCWSTR lpString) +{ + ATOM Atom; + NTSTATUS Status; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + Status = NtFindAtom((LPWSTR)lpString, + &Atom); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +UINT STDCALL +GlobalGetAtomNameA(ATOM nAtom, + LPSTR lpBuffer, + int nSize) +{ + PATOM_BASIC_INFORMATION Buffer; + UNICODE_STRING AtomNameU; + ANSI_STRING AtomName; + ULONG BufferSize; + ULONG ReturnLength; + NTSTATUS Status; + + BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + BufferSize); + + Status = NtQueryInformationAtom(nAtom, + AtomBasicInformation, + (PVOID)&Buffer, + BufferSize, + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + return 0; + } + + RtlInitUnicodeString(&AtomNameU, + Buffer->Name); + AtomName.Buffer = lpBuffer; + AtomName.Length = 0; + AtomName.MaximumLength = nSize; + RtlUnicodeStringToAnsiString(&AtomName, + &AtomNameU, + FALSE); + + ReturnLength = AtomName.Length; + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + + return ReturnLength; +} + + +UINT STDCALL +GlobalGetAtomNameW(ATOM nAtom, + LPWSTR lpBuffer, + int nSize) +{ + PATOM_BASIC_INFORMATION Buffer; + ULONG BufferSize; + ULONG ReturnLength; + NTSTATUS Status; + + BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + BufferSize); + + Status = NtQueryInformationAtom(nAtom, + AtomBasicInformation, + (PVOID)&Buffer, + BufferSize, + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + return 0; + } + + wcscpy(lpBuffer, Buffer->Name); + ReturnLength = Buffer->NameLength / sizeof(WCHAR); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + + return ReturnLength; +} + + +static PRTL_ATOM_TABLE +GetLocalAtomTable(VOID) +{ + if (LocalAtomTable != NULL) + { + return LocalAtomTable; + } + RtlCreateAtomTable(37, + &LocalAtomTable); + return LocalAtomTable; +} + + +BOOL STDCALL +InitAtomTable(DWORD nSize) +{ + NTSTATUS Status; + + /* nSize should be a prime number */ + + if ( nSize < 4 || nSize >= 512 ) + { + nSize = 37; + } + + if (LocalAtomTable == NULL) + { + Status = RtlCreateAtomTable(nSize, + &LocalAtomTable); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + } + + return TRUE; +} + + +ATOM STDCALL +AddAtomA(LPCSTR lpString) +{ + PRTL_ATOM_TABLE AtomTable; + UNICODE_STRING AtomName; + NTSTATUS Status; + ATOM Atom; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + AtomTable = GetLocalAtomTable(); + + RtlCreateUnicodeStringFromAsciiz(&AtomName, + (LPSTR)lpString); + + Status = RtlAddAtomToAtomTable(AtomTable, + AtomName.Buffer, + &Atom); + RtlFreeUnicodeString(&AtomName); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +ATOM STDCALL +AddAtomW(LPCWSTR lpString) +{ + PRTL_ATOM_TABLE AtomTable; + ATOM Atom; + NTSTATUS Status; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + AtomTable = GetLocalAtomTable(); + + Status = RtlAddAtomToAtomTable(AtomTable, + (LPWSTR)lpString, + &Atom); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +ATOM STDCALL +DeleteAtom(ATOM nAtom) +{ + PRTL_ATOM_TABLE AtomTable; + NTSTATUS Status; + + if (nAtom < 0xC000) + { + return 0; + } + + AtomTable = GetLocalAtomTable(); + + Status = RtlDeleteAtomFromAtomTable(AtomTable, + nAtom); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return nAtom; + } + + return 0; +} + + +ATOM STDCALL +FindAtomA(LPCSTR lpString) +{ + PRTL_ATOM_TABLE AtomTable; + UNICODE_STRING AtomName; + NTSTATUS Status; + ATOM Atom; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + AtomTable = GetLocalAtomTable(); + RtlCreateUnicodeStringFromAsciiz(&AtomName, + (LPSTR)lpString); + Status = RtlLookupAtomInAtomTable(AtomTable, + AtomName.Buffer, + &Atom); + RtlFreeUnicodeString(&AtomName); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +ATOM STDCALL +FindAtomW(LPCWSTR lpString) +{ + PRTL_ATOM_TABLE AtomTable; + ATOM Atom; + NTSTATUS Status; + + if (HIWORD((ULONG)lpString) == 0) + { + if ((ULONG)lpString >= 0xC000) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return (ATOM)0; + } + return (ATOM)LOWORD((ULONG)lpString); + } + + AtomTable = GetLocalAtomTable(); + + Status = RtlLookupAtomInAtomTable(AtomTable, + (LPWSTR)lpString, + &Atom); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return (ATOM)0; + } + + return Atom; +} + + +UINT STDCALL +GetAtomNameA(ATOM nAtom, + LPSTR lpBuffer, + int nSize) +{ + PRTL_ATOM_TABLE AtomTable; + PWCHAR Buffer; + UNICODE_STRING AtomNameU; + ANSI_STRING AtomName; + ULONG NameLength; + NTSTATUS Status; + + AtomTable = GetLocalAtomTable(); + + NameLength = nSize * sizeof(WCHAR); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + NameLength); + + Status = RtlQueryAtomInAtomTable(AtomTable, + nAtom, + NULL, + NULL, + Buffer, + &NameLength); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + return 0; + } + + RtlInitUnicodeString(&AtomNameU, + Buffer); + AtomName.Buffer = lpBuffer; + AtomName.Length = 0; + AtomName.MaximumLength = nSize; + RtlUnicodeStringToAnsiString(&AtomName, + &AtomNameU, + FALSE); + + NameLength = AtomName.Length; + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Buffer); + + return NameLength; +} + + +UINT STDCALL +GetAtomNameW(ATOM nAtom, + LPWSTR lpBuffer, + int nSize) +{ + PRTL_ATOM_TABLE AtomTable; + ULONG NameLength; + NTSTATUS Status; + + AtomTable = GetLocalAtomTable(); + + NameLength = nSize * sizeof(WCHAR); + Status = RtlQueryAtomInAtomTable(AtomTable, + nAtom, + NULL, + NULL, + lpBuffer, + &NameLength); + if (!NT_SUCCESS(Status)) + { + return 0; + } + + return(NameLength / sizeof(WCHAR)); +} + +/* EOF */ diff --git a/lib/kernel32/misc/comm.c b/lib/kernel32/misc/comm.c new file mode 100644 index 0000000..4ffd707 --- /dev/null +++ b/lib/kernel32/misc/comm.c @@ -0,0 +1,659 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/comm.c + * PURPOSE: Comm functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ] + * Robert Dickenson (robd@mok.lvcom.com) + * UPDATE HISTORY: + * Created 01/11/98 + * RDD (30/09/2002) implemented many function bodies to call serial driver. + */ + +#include +#include +#include +#include +#include +#include + +//#define NDEBUG +#define DBG +#include +#include + + +WINBOOL +STDCALL +BuildCommDCBA(LPCSTR lpDef, LPDCB lpDCB) +{ + if (lpDCB == NULL) { + DPRINT("ERROR: BuildCommDCBA() - NULL DCB pointer\n"); + return FALSE; + } + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +BuildCommDCBW(LPCWSTR lpDef, LPDCB lpDCB) +{ + if (lpDCB == NULL) { + DPRINT("ERROR: BuildCommDCBW() - NULL DCB pointer\n"); + return FALSE; + } + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +BuildCommDCBAndTimeoutsA(LPCSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +{ + if (lpDCB == NULL) { + DPRINT("ERROR: BuildCommDCBAndTimeoutsA() - NULL DCB pointer\n"); + return FALSE; + } + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +BuildCommDCBAndTimeoutsW(LPCWSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts) +{ + if (lpDCB == NULL) { + DPRINT("ERROR: BuildCommDCBAndTimeoutsW() - NULL DCB pointer\n"); + return FALSE; + } + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +ClearCommBreak(HANDLE hFile) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + //SetLastError(CE_MODE); + return FALSE; + } + if (lpErrors == NULL) { + DPRINT("ERROR: GetCommState() - NULL Errors pointer\n"); + return FALSE; + } +// *lpErrors = CE_BREAK; +// *lpErrors = CE_FRAME; +// *lpErrors = CE_IOE; +// *lpErrors = CE_MODE; +// *lpErrors = CE_OVERRUN; +// *lpErrors = CE_RXOVER; +// *lpErrors = CE_RXPARITY; +// *lpErrors = CE_TXFULL; +/* +CE_BREAK The hardware detected a break condition. +CE_FRAME The hardware detected a framing error. +CE_IOE An I/O error occurred during communications with the device. +CE_MODE The requested mode is not supported, or the hFile parameter is invalid. If this value is specified, it is the only valid error. +CE_OVERRUN A character-buffer overrun has occurred. The next character is lost. +CE_RXOVER An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character. +CE_RXPARITY The hardware detected a parity error. +CE_TXFULL The application tried to transmit a character, but the output buffer was full. + */ + result = DeviceIoControl(hFile, IOCTL_SERIAL_RESET_DEVICE, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + + if (lpStat != NULL) { + lpStat->fCtsHold = 0; + lpStat->fDsrHold = 0; + lpStat->fRlsdHold = 0; + lpStat->fXoffHold = 0; + lpStat->fXoffSent = 0; + lpStat->fEof = 0; + lpStat->fTxim = 0; + lpStat->cbInQue = 0; + lpStat->cbOutQue = 0; + } + return TRUE; +} + +WINBOOL +STDCALL +CommConfigDialogA(LPCSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +CommConfigDialogW(LPCWSTR lpszName, HWND hWnd, LPCOMMCONFIG lpCC) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +EscapeCommFunction(HANDLE hFile, DWORD dwFunc) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + switch (dwFunc) { + case CLRDTR: // Clears the DTR (data-terminal-ready) signal. + result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case CLRRTS: // Clears the RTS (request-to-send) signal. + result = DeviceIoControl(hFile, IOCTL_SERIAL_CLR_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case SETDTR: // Sends the DTR (data-terminal-ready) signal. + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_DTR, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case SETRTS: // Sends the RTS (request-to-send) signal. + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_RTS, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case SETXOFF: // Causes transmission to act as if an XOFF character has been received. + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XOFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case SETXON: // Causes transmission to act as if an XON character has been received. + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_XON, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case SETBREAK: // Suspends character transmission and places the transmission line in a break state until the ClearCommBreak function is called (or EscapeCommFunction is called with the CLRBREAK extended function code). The SETBREAK extended function code is identical to the SetCommBreak function. Note that this extended function does not flush data that has not been transmitted. + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + case CLRBREAK: // Restores character transmission and places the transmission line in a nonbreak state. The CLRBREAK extended function code is identical to the ClearCommBreak function. + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + break; + default: + DPRINT("EscapeCommFunction() WARNING: unknown function code\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + break; + } + return TRUE; +} + +WINBOOL +STDCALL +GetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, LPDWORD lpdwSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +GetCommMask(HANDLE hFile, LPDWORD lpEvtMask) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_WAIT_MASK, + NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS, + NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +GetCommProperties(HANDLE hFile, LPCOMMPROP lpCommProp) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +GetCommState(HANDLE hFile, LPDCB lpDCB) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + SERIAL_BAUD_RATE BaudRate; + SERIAL_HANDFLOW HandFlow; + SERIAL_CHARS SpecialChars; + SERIAL_LINE_CONTROL LineControl; + + DPRINT("GetCommState(%d, %p)\n", hFile, lpDCB); + + if (hFile == INVALID_HANDLE_VALUE) { + DPRINT("ERROR: GetCommState() - INVALID_HANDLE_VALUE\n"); + return FALSE; + } + if (lpDCB == NULL) { + DPRINT("ERROR: GetCommState() - NULL DCB pointer\n"); + return FALSE; + } + if (lpDCB->DCBlength != sizeof(DCB)) { + DPRINT("ERROR: GetCommState() - Invalid DCB size\n"); + return FALSE; + } + +// DPRINT(" GetCommState() CALLING DeviceIoControl\n"); +// result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0, NULL, 0, &dwBytesReturned, NULL); +// DPRINT(" GetCommState() DeviceIoControl returned %d\n", result); + + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_BAUD_RATE, + NULL, 0, &BaudRate, sizeof(BaudRate),&dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_BAUD_RATE) Failed.\n"); + return FALSE; + } + lpDCB->BaudRate = BaudRate.BaudRate; + + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_HANDFLOW, + NULL, 0, &HandFlow, sizeof(HandFlow), &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_HANDFLOW) Failed.\n"); + return FALSE; + } + if (HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) { + lpDCB->fOutxCtsFlow = 1; + } + if (HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) { + lpDCB->fOutxDsrFlow = 1; + } + if (HandFlow.ControlHandShake & SERIAL_DTR_CONTROL) { + lpDCB->fDtrControl = 1; + } + if (HandFlow.ControlHandShake & SERIAL_DTR_HANDSHAKE) { + lpDCB->fDtrControl = 2; + } + if (HandFlow.ControlHandShake & SERIAL_RTS_CONTROL) { + lpDCB->fRtsControl = 1; + } + if (HandFlow.ControlHandShake & SERIAL_RTS_HANDSHAKE) { + lpDCB->fRtsControl = 2; + } + if (HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) { + lpDCB->fDsrSensitivity = 1; + } + if (HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) { + lpDCB->fAbortOnError = 1; + } + + if (HandFlow.FlowReplace & SERIAL_ERROR_CHAR) { + lpDCB->fErrorChar = 1; + } + if (HandFlow.FlowReplace & SERIAL_NULL_STRIPPING) { + lpDCB->fNull = 1; + } + if (HandFlow.FlowReplace & SERIAL_XOFF_CONTINUE) { + lpDCB->fTXContinueOnXoff = 1; + } + lpDCB->XonLim = HandFlow.XonLimit; + lpDCB->XoffLim = HandFlow.XoffLimit; + + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_CHARS, + NULL, 0, &SpecialChars, sizeof(SpecialChars), &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_CHARS) Failed.\n"); + return FALSE; + } + + lpDCB->EofChar = SpecialChars.EofChar; + lpDCB->ErrorChar = SpecialChars.ErrorChar; + // = SpecialChars.BreakChar; + lpDCB->EvtChar = SpecialChars.EventChar; + lpDCB->XonChar = SpecialChars.XonChar; + lpDCB->XoffChar = SpecialChars.XoffChar; + + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_LINE_CONTROL, + NULL, 0, &LineControl, sizeof(LineControl), &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: GetCommState() - DeviceIoControl(IOCTL_SERIAL_GET_LINE_CONTROL) Failed.\n"); + return FALSE; + } + lpDCB->StopBits = LineControl.StopBits; + lpDCB->Parity = LineControl.Parity; + lpDCB->ByteSize = LineControl.WordLength; + DPRINT("GetCommState() - COMPLETED SUCCESSFULLY\n"); + return TRUE; +} + +WINBOOL +STDCALL +GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + if (lpCommTimeouts == NULL) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_GET_TIMEOUTS, + NULL, 0, + lpCommTimeouts, sizeof(COMMTIMEOUTS), + &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +GetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +PurgeComm(HANDLE hFile, DWORD dwFlags) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_PURGE, + &dwFlags, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +SetCommBreak(HANDLE hFile) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +SetCommConfig(HANDLE hCommDev, LPCOMMCONFIG lpCC, DWORD dwSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +SetCommMask(HANDLE hFile, DWORD dwEvtMask) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_WAIT_MASK, + &dwEvtMask, sizeof(DWORD), NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +SetCommState(HANDLE hFile, LPDCB lpDCB) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + SERIAL_BAUD_RATE BaudRate; + SERIAL_HANDFLOW HandFlow; + SERIAL_CHARS SpecialChars; + SERIAL_LINE_CONTROL LineControl; + + DPRINT("SetCommState(%d, %p) - ENTERED\n", hFile, lpDCB); + + if (hFile == INVALID_HANDLE_VALUE) { + DPRINT("SetCommState() - ERROR: INVALID_HANDLE_VALUE\n"); + return FALSE; + } + if (lpDCB == NULL) { + DPRINT("SetCommState() - ERROR: NULL DCB pointer passed\n"); + return FALSE; + } + + BaudRate.BaudRate = lpDCB->BaudRate; + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_BAUD_RATE, + &BaudRate, sizeof(BaudRate), NULL, 0, &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_BAUD_RATE) Failed.\n"); + return FALSE; + } +/* +#define SERIAL_DTR_MASK ((ULONG)0x03) +#define SERIAL_DTR_CONTROL ((ULONG)0x01) +#define SERIAL_DTR_HANDSHAKE ((ULONG)0x02) +#define SERIAL_CTS_HANDSHAKE ((ULONG)0x08) +#define SERIAL_DSR_HANDSHAKE ((ULONG)0x10) +#define SERIAL_DCD_HANDSHAKE ((ULONG)0x20) +#define SERIAL_OUT_HANDSHAKEMASK ((ULONG)0x38) +#define SERIAL_DSR_SENSITIVITY ((ULONG)0x40) +#define SERIAL_ERROR_ABORT ((ULONG)0x80000000) +#define SERIAL_CONTROL_INVALID ((ULONG)0x7fffff84) + */ + HandFlow.ControlHandShake = 0; + + if (lpDCB->fOutxCtsFlow) { + HandFlow.ControlHandShake |= SERIAL_CTS_HANDSHAKE; + } + if (lpDCB->fOutxDsrFlow) { + HandFlow.ControlHandShake |= SERIAL_DSR_HANDSHAKE; + } + if (lpDCB->fDtrControl) { + HandFlow.ControlHandShake |= SERIAL_DTR_CONTROL; + } + if (lpDCB->fDtrControl) { + HandFlow.ControlHandShake |= SERIAL_DTR_HANDSHAKE; + } + if (lpDCB->fRtsControl) { + HandFlow.ControlHandShake |= SERIAL_RTS_CONTROL; + } + if (lpDCB->fRtsControl) { + HandFlow.ControlHandShake |= SERIAL_RTS_HANDSHAKE; + } + if (lpDCB->fDsrSensitivity) { + HandFlow.ControlHandShake |= SERIAL_DSR_SENSITIVITY; + } + if (lpDCB->fAbortOnError) { + HandFlow.ControlHandShake |= SERIAL_ERROR_ABORT; + } +/* +#define SERIAL_AUTO_TRANSMIT ((ULONG)0x01) +#define SERIAL_AUTO_RECEIVE ((ULONG)0x02) +#define SERIAL_ERROR_CHAR ((ULONG)0x04) +#define SERIAL_NULL_STRIPPING ((ULONG)0x08) +#define SERIAL_BREAK_CHAR ((ULONG)0x10) +#define SERIAL_RTS_MASK ((ULONG)0xc0) +#define SERIAL_RTS_CONTROL ((ULONG)0x40) +#define SERIAL_RTS_HANDSHAKE ((ULONG)0x80) +#define SERIAL_TRANSMIT_TOGGLE ((ULONG)0xc0) +#define SERIAL_XOFF_CONTINUE ((ULONG)0x80000000) +#define SERIAL_FLOW_INVALID ((ULONG)0x7fffff20) + */ + HandFlow.FlowReplace = 0; + if (lpDCB->fErrorChar) { + HandFlow.FlowReplace |= SERIAL_ERROR_CHAR; + } + if (lpDCB->fNull) { + HandFlow.FlowReplace |= SERIAL_NULL_STRIPPING; + } + if (lpDCB->fTXContinueOnXoff) { + HandFlow.FlowReplace |= SERIAL_XOFF_CONTINUE; + } + HandFlow.XonLimit = lpDCB->XonLim; + HandFlow.XoffLimit = lpDCB->XoffLim; + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_HANDFLOW, + &HandFlow, sizeof(HandFlow), NULL, 0, &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_HANDFLOW) Failed.\n"); + return FALSE; + } + + SpecialChars.EofChar = lpDCB->EofChar; + SpecialChars.ErrorChar = lpDCB->ErrorChar; + SpecialChars.BreakChar = 0; + SpecialChars.EventChar = lpDCB->EvtChar; + SpecialChars.XonChar = lpDCB->XonChar; + SpecialChars.XoffChar = lpDCB->XoffChar; + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_CHARS, + &SpecialChars, sizeof(SpecialChars), NULL, 0, &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_CHARS) Failed.\n"); + return FALSE; + } + + LineControl.StopBits = lpDCB->StopBits; + LineControl.Parity = lpDCB->Parity; + LineControl.WordLength = lpDCB->ByteSize; + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_LINE_CONTROL, + &LineControl, sizeof(LineControl), NULL, 0, &dwBytesReturned, NULL); + if (!NT_SUCCESS(result)) { + DPRINT("ERROR: SetCommState() - DeviceIoControl(IOCTL_SERIAL_SET_LINE_CONTROL) Failed.\n"); + return FALSE; + } + + DPRINT("SetCommState() - COMPLETED SUCCESSFULLY\n"); + return TRUE; +} + +WINBOOL +STDCALL +SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + SERIAL_TIMEOUTS Timeouts; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + if (lpCommTimeouts == NULL) { + return FALSE; + } + Timeouts.ReadIntervalTimeout = lpCommTimeouts->ReadIntervalTimeout; + Timeouts.ReadTotalTimeoutMultiplier = lpCommTimeouts->ReadTotalTimeoutMultiplier; + Timeouts.ReadTotalTimeoutConstant = lpCommTimeouts->ReadTotalTimeoutConstant; + Timeouts.WriteTotalTimeoutMultiplier = lpCommTimeouts->WriteTotalTimeoutMultiplier; + Timeouts.WriteTotalTimeoutConstant = lpCommTimeouts->WriteTotalTimeoutConstant; + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_TIMEOUTS, + &Timeouts, sizeof(Timeouts), NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +SetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +SetDefaultCommConfigW(LPCWSTR lpszName, LPCOMMCONFIG lpCC, DWORD dwSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +SetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + SERIAL_QUEUE_SIZE QueueSize; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + QueueSize.InSize = dwInQueue; + QueueSize.OutSize = dwOutQueue; + result = DeviceIoControl(hFile, IOCTL_SERIAL_SET_QUEUE_SIZE, + &QueueSize, sizeof(QueueSize), NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +TransmitCommChar(HANDLE hFile, char cChar) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_IMMEDIATE_CHAR, + &cChar, sizeof(cChar), NULL, 0, &dwBytesReturned, NULL); + return TRUE; +} + +WINBOOL +STDCALL +WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) +{ + WINBOOL result = FALSE; + DWORD dwBytesReturned; + + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + if (lpEvtMask == NULL) { + return FALSE; + } + result = DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, + NULL, 0, lpEvtMask, sizeof(DWORD), &dwBytesReturned, lpOverlapped); + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/misc/console.c b/lib/kernel32/misc/console.c new file mode 100644 index 0000000..b9a5025 --- /dev/null +++ b/lib/kernel32/misc/console.c @@ -0,0 +1,2444 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/console.c + * PURPOSE: Win32 server console functions + * PROGRAMMER: ??? + * UPDATE HISTORY: + * 199901?? ?? Created + * 19990204 EA SetConsoleTitleA + * 19990306 EA Stubs + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include + +#define NDEBUG +#include +#include + +/* GLOBALS *******************************************************************/ + +static BOOL IgnoreCtrlEvents = FALSE; +static ULONG NrCtrlHandlers = 0; +static PHANDLER_ROUTINE* CtrlHandlers = NULL; + +/* FUNCTIONS *****************************************************************/ + +BOOL STDCALL +AddConsoleAliasA (LPSTR Source, + LPSTR Target, + LPSTR ExeName) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL STDCALL +AddConsoleAliasW (LPWSTR Source, + LPWSTR Target, + LPWSTR ExeName) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL STDCALL +ConsoleMenuControl (HANDLE hConsole, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +BOOL STDCALL +DuplicateConsoleHandle (HANDLE hConsole, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +DWORD STDCALL +ExpungeConsoleCommandHistoryW (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +ExpungeConsoleCommandHistoryA (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasW (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetConsoleAliasA (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasExesW (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD STDCALL +GetConsoleAliasExesA (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD STDCALL +GetConsoleAliasExesLengthA (VOID) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasExesLengthW (VOID) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasesW (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasesA (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasesLengthW (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleAliasesLengthA (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleCommandHistoryW (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleCommandHistoryA (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleCommandHistoryLengthW (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleCommandHistoryLengthA (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleDisplayMode (LPDWORD lpdwMode) + /* + * FUNCTION: Get the console display mode + * ARGUMENTS: + * lpdwMode - Address of variable that receives the current value + * of display mode + * STATUS: Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleFontInfo (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleFontSize(HANDLE hConsoleOutput, + DWORD nFont) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleHardwareState (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +GetConsoleInputWaitHandle (VOID) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +DWORD STDCALL +GetCurrentConsoleFont(HANDLE hConsoleOutput, + BOOL bMaximumWindow, + PCONSOLE_FONT_INFO lpConsoleCurrentFont) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +ULONG STDCALL +GetNumberOfConsoleFonts (VOID) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 1; /* FIXME: call csrss.exe */ +} + +DWORD STDCALL +InvalidateConsoleDIBits (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +OpenConsoleW (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +WINBOOL STDCALL +SetConsoleCommandHistoryMode (DWORD dwMode) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleCursor (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleDisplayMode (HANDLE hOut, + DWORD dwNewMode, + LPDWORD lpdwOldMode) + /* + * FUNCTION: Set the console display mode. + * ARGUMENTS: + * hOut - Standard output handle. + * dwNewMode - New mode. + * lpdwOldMode - Address of a variable that receives the old mode. + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleFont (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleHardwareState (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleKeyShortcuts (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleMaximumWindowSize (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleMenuClose (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleNumberOfCommandsA (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsoleNumberOfCommandsW (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetConsolePalette (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +SetLastConsoleEventActive (VOID) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +DWORD STDCALL +ShowConsoleCursor (DWORD Unknown0, + DWORD Unknown1) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +VerifyConsoleIoHandle (DWORD Unknown0) + /* + * Undocumented + */ +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +WriteConsoleInputVDMA (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +DWORD STDCALL +WriteConsoleInputVDMW (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +WINBOOL STDCALL +CloseConsoleHandle(HANDLE Handle) + /* + * Undocumented + */ +{ + if (IsConsoleHandle (Handle) == FALSE) + { + SetLastError (ERROR_INVALID_PARAMETER); + return FALSE; + } + /* FIXME: call CSRSS */ + return TRUE/*FALSE*/; +} + +BOOLEAN STDCALL +IsConsoleHandle(HANDLE Handle) +{ + if ((((ULONG)Handle) & 0x10000003) == 0x3) + { + return(TRUE); + } + return(FALSE); +} + +HANDLE STDCALL +GetStdHandle(DWORD nStdHandle) + /* + * FUNCTION: Get a handle for the standard input, standard output + * and a standard error device. + * ARGUMENTS: + * nStdHandle - Specifies the device for which to return the handle. + * RETURNS: If the function succeeds, the return value is the handle + * of the specified device. Otherwise the value is INVALID_HANDLE_VALUE. + */ +{ + PRTL_USER_PROCESS_PARAMETERS Ppb; + + Ppb = NtCurrentPeb()->ProcessParameters; + switch (nStdHandle) + { + case STD_INPUT_HANDLE: return Ppb->hStdInput; + case STD_OUTPUT_HANDLE: return Ppb->hStdOutput; + case STD_ERROR_HANDLE: return Ppb->hStdError; + } + SetLastError (ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; +} + +WINBASEAPI BOOL WINAPI +SetStdHandle(DWORD nStdHandle, + HANDLE hHandle) + /* + * FUNCTION: Set the handle for the standard input, standard output or + * the standard error device. + * ARGUMENTS: + * nStdHandle - Specifies the handle to be set. + * hHandle - The handle to set. + * RETURNS: TRUE if the function succeeds, FALSE otherwise. + */ +{ + PRTL_USER_PROCESS_PARAMETERS Ppb; + + Ppb = NtCurrentPeb()->ProcessParameters; + + /* More checking needed? */ + if (hHandle == INVALID_HANDLE_VALUE) + { + SetLastError (ERROR_INVALID_HANDLE); + return FALSE; + } + + SetLastError(ERROR_SUCCESS); /* OK */ + switch (nStdHandle) + { + case STD_INPUT_HANDLE: + Ppb->hStdInput = hHandle; + return TRUE; + case STD_OUTPUT_HANDLE: + Ppb->hStdOutput = hHandle; + return TRUE; + case STD_ERROR_HANDLE: + Ppb->hStdError = hHandle; + return TRUE; + } + SetLastError (ERROR_INVALID_PARAMETER); + return FALSE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleA + */ +WINBOOL STDCALL +WriteConsoleA(HANDLE hConsoleOutput, + CONST VOID *lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + USHORT Size; + ULONG MessageSize; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + + CSRSS_MAX_WRITE_CONSOLE_REQUEST); + if (Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + Request->Type = CSRSS_WRITE_CONSOLE; + Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput; + if (lpNumberOfCharsWritten != NULL) + *lpNumberOfCharsWritten = nNumberOfCharsToWrite; + while (nNumberOfCharsToWrite) + { + if (nNumberOfCharsToWrite > CSRSS_MAX_WRITE_CONSOLE_REQUEST) + { + Size = CSRSS_MAX_WRITE_CONSOLE_REQUEST; + } + else + { + Size = nNumberOfCharsToWrite; + } + Request->Data.WriteConsoleRequest.NrCharactersToWrite = Size; + + memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, Size); + + MessageSize = CSRSS_REQUEST_HEADER_SIZE + + sizeof(CSRSS_WRITE_CONSOLE_REQUEST) + Size; + Status = CsrClientCallServer(Request, + &Reply, + MessageSize, + sizeof(CSRSS_API_REPLY)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Request); + SetLastErrorByStatus(Status); + return(FALSE); + } + nNumberOfCharsToWrite -= Size; + lpBuffer += Size; + } + RtlFreeHeap(GetProcessHeap(), 0, Request); + return TRUE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleA + */ +WINBOOL STDCALL ReadConsoleA(HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + LPVOID lpReserved) +{ + CSRSS_API_REQUEST Request; + PCSRSS_API_REPLY Reply; + NTSTATUS Status; + ULONG CharsRead = 0; + + Reply = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REPLY) + nNumberOfCharsToRead); + if (Reply == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + Request.Type = CSRSS_READ_CONSOLE; + Request.Data.ReadConsoleRequest.ConsoleHandle = hConsoleInput; + Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead; + Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = 0; + Status = CsrClientCallServer(&Request, + Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY) + + Request.Data.ReadConsoleRequest.NrCharactersToRead); + if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply->Status )) + { + DbgPrint( "CSR returned error in ReadConsole\n" ); + SetLastErrorByStatus ( Status ); + RtlFreeHeap( GetProcessHeap(), 0, Reply ); + return(FALSE); + } + if( Reply->Status == STATUS_NOTIFY_CLEANUP ) + Reply->Status = STATUS_PENDING; // ignore backspace because we have no chars to backspace + /* There may not be any chars or lines to read yet, so wait */ + while( Reply->Status == STATUS_PENDING ) + { + /* some chars may have been returned, but not a whole line yet, so recompute buffer and try again */ + nNumberOfCharsToRead -= Reply->Data.ReadConsoleReply.NrCharactersRead; + /* don't overflow caller's buffer, even if you still don't have a complete line */ + if( !nNumberOfCharsToRead ) + break; + Request.Data.ReadConsoleRequest.NrCharactersToRead = nNumberOfCharsToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : nNumberOfCharsToRead; + /* copy any chars already read to buffer */ + memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead ); + CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead; + /* wait for csrss to signal there is more data to read, but not if we got STATUS_NOTIFY_CLEANUP for backspace */ + Status = NtWaitForSingleObject( Reply->Data.ReadConsoleReply.EventHandle, FALSE, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "Wait for console input failed!\n" ); + RtlFreeHeap( GetProcessHeap(), 0, Reply ); + return FALSE; + } + Request.Data.ReadConsoleRequest.nCharsCanBeDeleted = CharsRead; + Status = CsrClientCallServer( &Request, Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) + Request.Data.ReadConsoleRequest.NrCharactersToRead ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply->Status ) ) + { + SetLastErrorByStatus ( Status ); + RtlFreeHeap( GetProcessHeap(), 0, Reply ); + return FALSE; + } + if( Reply->Status == STATUS_NOTIFY_CLEANUP ) + { + // delete last char + if( CharsRead ) + { + CharsRead--; + nNumberOfCharsToRead++; + } + Reply->Status = STATUS_PENDING; // retry + } + } + /* copy data to buffer, count total returned, and return */ + memcpy( lpBuffer + CharsRead, Reply->Data.ReadConsoleReply.Buffer, Reply->Data.ReadConsoleReply.NrCharactersRead ); + CharsRead += Reply->Data.ReadConsoleReply.NrCharactersRead; + if (lpNumberOfCharsRead != NULL) + *lpNumberOfCharsRead = CharsRead; + RtlFreeHeap(GetProcessHeap(), + 0, + Reply); + + return(TRUE); +} + + +/*-------------------------------------------------------------- + * AllocConsole + */ +WINBOOL STDCALL AllocConsole(VOID) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_ALLOC_CONSOLE; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle ); + SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle ); + SetStdHandle( STD_ERROR_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle ); + return TRUE; +} + + +/*-------------------------------------------------------------- + * FreeConsole + */ +WINBOOL STDCALL FreeConsole(VOID) +{ + DbgPrint("FreeConsole() is unimplemented\n"); + return FALSE; +} + + +/*-------------------------------------------------------------- + * GetConsoleScreenBufferInfo + */ +WINBOOL +STDCALL +GetConsoleScreenBufferInfo( + HANDLE hConsoleOutput, + PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SCREEN_BUFFER_INFO; + Request.Data.ScreenBufferInfoRequest.ConsoleHandle = hConsoleOutput; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + *lpConsoleScreenBufferInfo = Reply.Data.ScreenBufferInfoReply.Info; + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleCursorPosition + */ +WINBOOL +STDCALL +SetConsoleCursorPosition( + HANDLE hConsoleOutput, + COORD dwCursorPosition + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SET_CURSOR; + Request.Data.SetCursorRequest.ConsoleHandle = hConsoleOutput; + Request.Data.SetCursorRequest.Position = dwCursorPosition; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * FillConsoleOutputCharacterA + */ +WINBOOL STDCALL +FillConsoleOutputCharacterA( + HANDLE hConsoleOutput, + CHAR cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_FILL_OUTPUT; + Request.Data.FillOutputRequest.ConsoleHandle = hConsoleOutput; + Request.Data.FillOutputRequest.Char = cCharacter; + Request.Data.FillOutputRequest.Position = dwWriteCoord; + Request.Data.FillOutputRequest.Length = nLength; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if ( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + if (lpNumberOfCharsWritten != NULL) + *lpNumberOfCharsWritten = nLength; + return(TRUE); +} + + +/*-------------------------------------------------------------- + * FillConsoleOutputCharacterW + */ +WINBOOL +STDCALL +FillConsoleOutputCharacterW( + HANDLE hConsoleOutput, + WCHAR cCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * PeekConsoleInputA + */ +WINBASEAPI +BOOL +WINAPI +PeekConsoleInputA( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + PVOID BufferBase; + PVOID BufferTargetBase; + DWORD Size; + + if(lpBuffer == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Size = nLength * sizeof(INPUT_RECORD); + + Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, Size, &BufferBase, &BufferTargetBase); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REQUEST)); + if(Request == NULL) + { + CsrReleaseParameterBuffer(BufferBase); + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + + Request->Type = CSRSS_PEEK_CONSOLE_INPUT; + Request->Data.PeekConsoleInputRequest.ConsoleHandle = hConsoleInput; + Request->Data.PeekConsoleInputRequest.Length = nLength; + Request->Data.PeekConsoleInputRequest.InputRecord = (INPUT_RECORD*)BufferTargetBase; + + Status = CsrClientCallServer(Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY)); + + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + return FALSE; + } + + memcpy(lpBuffer, BufferBase, sizeof(INPUT_RECORD) * Reply.Data.PeekConsoleInputReply.Length); + + if(lpNumberOfEventsRead != NULL) + *lpNumberOfEventsRead = Reply.Data.PeekConsoleInputReply.Length; + + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + + return TRUE; +} + + +/*-------------------------------------------------------------- + * PeekConsoleInputW + */ +WINBASEAPI +BOOL +WINAPI +PeekConsoleInputW( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleInputA + */ +WINBASEAPI BOOL WINAPI +ReadConsoleInputA(HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + DWORD NumEventsRead; + NTSTATUS Status; + + Request.Type = CSRSS_READ_INPUT; + Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput; + Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + while (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(Reply.Data.ReadInputReply.Event, FALSE, + 0); + if(!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + Request.Type = CSRSS_READ_INPUT; + Request.Data.ReadInputRequest.ConsoleHandle = hConsoleInput; + Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + } + + NumEventsRead = 0; + *lpBuffer = Reply.Data.ReadInputReply.Input; + lpBuffer++; + NumEventsRead++; + + while ((NumEventsRead < nLength) && (Reply.Data.ReadInputReply.MoreEvents)) + { + Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + if (Status == STATUS_PENDING) + { + break; + } + + *lpBuffer = Reply.Data.ReadInputReply.Input; + lpBuffer++; + NumEventsRead++; + + } + *lpNumberOfEventsRead = NumEventsRead; + + return TRUE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleInputW + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleInputW( + HANDLE hConsoleInput, + PINPUT_RECORD lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsRead + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleInputA + */ +WINBASEAPI +BOOL +WINAPI +WriteConsoleInputA( + HANDLE hConsoleInput, + CONST INPUT_RECORD *lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleInputW + */ +WINBASEAPI +BOOL +WINAPI +WriteConsoleInputW( + HANDLE hConsoleInput, + CONST INPUT_RECORD *lpBuffer, + DWORD nLength, + LPDWORD lpNumberOfEventsWritten + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputA + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleOutputA( + HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputW + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleOutputW( + HANDLE hConsoleOutput, + PCHAR_INFO lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpReadRegion + ) +{ +/* TO DO */ + return FALSE; +} + +/*-------------------------------------------------------------- + * WriteConsoleOutputA + */ +WINBASEAPI BOOL WINAPI +WriteConsoleOutputA(HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + ULONG Size; + BOOLEAN Result; + ULONG i, j; + PVOID BufferBase; + PVOID BufferTargetBase; + + Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO); + + Status = CsrCaptureParameterBuffer((PVOID)lpBuffer, + Size, + &BufferBase, + &BufferTargetBase); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + Request = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST)); + if (Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT; + Request->Data.WriteConsoleOutputRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleOutputRequest.BufferSize = dwBufferSize; + Request->Data.WriteConsoleOutputRequest.BufferCoord = dwBufferCoord; + Request->Data.WriteConsoleOutputRequest.WriteRegion = *lpWriteRegion; + Request->Data.WriteConsoleOutputRequest.CharInfo = + (CHAR_INFO*)BufferTargetBase; + + Status = CsrClientCallServer(Request, &Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Request); + SetLastErrorByStatus(Status); + return FALSE; + } + + *lpWriteRegion = Reply.Data.WriteConsoleOutputReply.WriteRegion; + RtlFreeHeap(GetProcessHeap(), 0, Request); + CsrReleaseParameterBuffer(BufferBase); + return(TRUE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputW + */ +WINBASEAPI +BOOL +WINAPI +WriteConsoleOutputW( + HANDLE hConsoleOutput, + CONST CHAR_INFO *lpBuffer, + COORD dwBufferSize, + COORD dwBufferCoord, + PSMALL_RECT lpWriteRegion + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputCharacterA + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleOutputCharacterA( + HANDLE hConsoleOutput, + LPSTR lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead + ) +{ + CSRSS_API_REQUEST Request; + PCSRSS_API_REPLY Reply; + NTSTATUS Status; + DWORD Size; + + Reply = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REPLY) + CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR); + if (Reply == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + if (lpNumberOfCharsRead != NULL) + *lpNumberOfCharsRead = nLength; + + Request.Type = CSRSS_READ_CONSOLE_OUTPUT_CHAR; + Request.Data.ReadConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput; + Request.Data.ReadConsoleOutputCharRequest.ReadCoord = dwReadCoord; + + while (nLength != 0) + { + if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR) + Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_CHAR; + else + Size = nLength; + + Request.Data.ReadConsoleOutputCharRequest.NumCharsToRead = Size; + + Status = CsrClientCallServer(&Request, + Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY) + Size); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Reply); + SetLastErrorByStatus(Status); + return(FALSE); + } + + memcpy(lpCharacter, &Reply->Data.ReadConsoleOutputCharReply.String[0], Size); + lpCharacter += Size; + nLength -= Size; + Request.Data.ReadConsoleOutputCharRequest.ReadCoord = Reply->Data.ReadConsoleOutputCharReply.EndCoord; + } + + RtlFreeHeap(GetProcessHeap(), 0, Reply); + + return(TRUE); +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputCharacterW + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleOutputCharacterW( + HANDLE hConsoleOutput, + LPWSTR lpCharacter, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfCharsRead + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleOutputAttribute + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleOutputAttribute( + HANDLE hConsoleOutput, + LPWORD lpAttribute, + DWORD nLength, + COORD dwReadCoord, + LPDWORD lpNumberOfAttrsRead + ) +{ + CSRSS_API_REQUEST Request; + PCSRSS_API_REPLY Reply; + NTSTATUS Status; + DWORD Size, i; + + Reply = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REPLY) + CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB); + if (Reply == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + if (lpNumberOfAttrsRead != NULL) + *lpNumberOfAttrsRead = nLength; + + Request.Type = CSRSS_READ_CONSOLE_OUTPUT_ATTRIB; + Request.Data.ReadConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput; + Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = dwReadCoord; + + while (nLength != 0) + { + if (nLength > CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB) + Size = CSRSS_MAX_READ_CONSOLE_OUTPUT_ATTRIB; + else + Size = nLength; + + Request.Data.ReadConsoleOutputAttribRequest.NumAttrsToRead = Size; + + Status = CsrClientCallServer(&Request, + Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY) + Size); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Reply->Status)) + { + RtlFreeHeap(GetProcessHeap(), 0, Reply); + SetLastErrorByStatus(Status); + return(FALSE); + } + + // Convert CHARs to WORDs + for(i = 0; i < Size; ++i) + *lpAttribute++ = Reply->Data.ReadConsoleOutputAttribReply.String[i]; + + nLength -= Size; + Request.Data.ReadConsoleOutputAttribRequest.ReadCoord = Reply->Data.ReadConsoleOutputAttribReply.EndCoord; + } + + RtlFreeHeap(GetProcessHeap(), 0, Reply); + + return(TRUE); +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputCharacterA + */ +WINBASEAPI BOOL WINAPI +WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, + LPCSTR lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + WORD Size; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR); + if( !Request ) + { + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_CHAR; + Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleOutputCharRequest.Coord = dwWriteCoord; + if( lpNumberOfCharsWritten ) + *lpNumberOfCharsWritten = nLength; + while( nLength ) + { + Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR : nLength; + Request->Data.WriteConsoleOutputCharRequest.Length = Size; + memcpy( &Request->Data.WriteConsoleOutputCharRequest.String[0], + lpCharacter, + Size ); + Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + Size, sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + RtlFreeHeap( GetProcessHeap(), 0, Request ); + SetLastErrorByStatus ( Status ); + return FALSE; + } + nLength -= Size; + lpCharacter += Size; + Request->Data.WriteConsoleOutputCharRequest.Coord = Reply.Data.WriteConsoleOutputCharReply.EndCoord; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleOutputCharacterW + */ +WINBASEAPI +BOOL +WINAPI +WriteConsoleOutputCharacterW( + HANDLE hConsoleOutput, + LPCWSTR lpCharacter, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfCharsWritten + ) +{ +/* TO DO */ + return FALSE; +} + + + +/*-------------------------------------------------------------- + * WriteConsoleOutputAttribute + */ +WINBASEAPI +BOOL +WINAPI +WriteConsoleOutputAttribute( + HANDLE hConsoleOutput, + CONST WORD *lpAttribute, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfAttrsWritten + ) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + WORD Size; + int c; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB); + if( !Request ) + { + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + Request->Type = CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB; + Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleOutputAttribRequest.Coord = dwWriteCoord; + if( lpNumberOfAttrsWritten ) + *lpNumberOfAttrsWritten = nLength; + while( nLength ) + { + Size = nLength > CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB ? CSRSS_MAX_WRITE_CONSOLE_OUTPUT_ATTRIB : nLength; + Request->Data.WriteConsoleOutputAttribRequest.Length = Size; + for( c = 0; c < ( Size * 2 ); c++ ) + Request->Data.WriteConsoleOutputAttribRequest.String[c] = (char)lpAttribute[c]; + Status = CsrClientCallServer( Request, &Reply, sizeof( CSRSS_API_REQUEST ) + (Size * 2), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + RtlFreeHeap( GetProcessHeap(), 0, Request ); + SetLastErrorByStatus ( Status ); + return FALSE; + } + nLength -= Size; + lpAttribute += Size; + Request->Data.WriteConsoleOutputAttribRequest.Coord = Reply.Data.WriteConsoleOutputAttribReply.EndCoord; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * FillConsoleOutputAttribute + */ +WINBASEAPI +BOOL +WINAPI +FillConsoleOutputAttribute( + HANDLE hConsoleOutput, + WORD wAttribute, + DWORD nLength, + COORD dwWriteCoord, + LPDWORD lpNumberOfAttrsWritten + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_FILL_OUTPUT_ATTRIB; + Request.Data.FillOutputAttribRequest.ConsoleHandle = hConsoleOutput; + Request.Data.FillOutputAttribRequest.Attribute = wAttribute; + Request.Data.FillOutputAttribRequest.Coord = dwWriteCoord; + Request.Data.FillOutputAttribRequest.Length = nLength; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + if( lpNumberOfAttrsWritten ) + *lpNumberOfAttrsWritten = nLength; + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetConsoleMode + */ +WINBASEAPI +BOOL +WINAPI +GetConsoleMode( + HANDLE hConsoleHandle, + LPDWORD lpMode + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_GET_MODE; + Request.Data.GetConsoleModeRequest.ConsoleHandle = hConsoleHandle; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + *lpMode = Reply.Data.GetConsoleModeReply.ConsoleMode; + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetNumberOfConsoleInputEvents + */ +WINBASEAPI +BOOL +WINAPI +GetNumberOfConsoleInputEvents( + HANDLE hConsoleInput, + LPDWORD lpNumberOfEvents + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + if(lpNumberOfEvents == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Request.Type = CSRSS_GET_NUM_INPUT_EVENTS; + Request.Data.GetNumInputEventsRequest.ConsoleHandle = hConsoleInput; + Status = CsrClientCallServer(&Request, &Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY)); + if(!NT_SUCCESS(Status) || !NT_SUCCESS(Reply.Status)) + { + SetLastErrorByStatus(Reply.Status); + return FALSE; + } + + *lpNumberOfEvents = Reply.Data.GetNumInputEventsReply.NumInputEvents; + + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetLargestConsoleWindowSize + */ +WINBASEAPI +COORD +WINAPI +GetLargestConsoleWindowSize( + HANDLE hConsoleOutput + ) +{ +#if 1 /* FIXME: */ + COORD Coord = {80,25}; + +/* TO DO */ + return Coord; +#endif +} + + +/*-------------------------------------------------------------- + * GetConsoleCursorInfo + */ +WINBASEAPI +BOOL +WINAPI +GetConsoleCursorInfo( + HANDLE hConsoleOutput, + PCONSOLE_CURSOR_INFO lpConsoleCursorInfo + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_GET_CURSOR_INFO; + Request.Data.GetCursorInfoRequest.ConsoleHandle = hConsoleOutput; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + *lpConsoleCursorInfo = Reply.Data.GetCursorInfoReply.Info; + return TRUE; +} + + +/*-------------------------------------------------------------- + * GetNumberOfConsoleMouseButtons + */ +WINBASEAPI +BOOL +WINAPI +GetNumberOfConsoleMouseButtons( + LPDWORD lpNumberOfMouseButtons + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * SetConsoleMode + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleMode( + HANDLE hConsoleHandle, + DWORD dwMode + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SET_MODE; + Request.Data.SetConsoleModeRequest.ConsoleHandle = hConsoleHandle; + Request.Data.SetConsoleModeRequest.Mode = dwMode; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleActiveScreenBuffer + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleActiveScreenBuffer( + HANDLE hConsoleOutput + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SET_SCREEN_BUFFER; + Request.Data.SetActiveScreenBufferRequest.OutputHandle = hConsoleOutput; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * FlushConsoleInputBuffer + */ +WINBASEAPI +BOOL +WINAPI +FlushConsoleInputBuffer( + HANDLE hConsoleInput + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_FLUSH_INPUT_BUFFER; + Request.Data.FlushInputBufferRequest.ConsoleInput = hConsoleInput; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleScreenBufferSize + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleScreenBufferSize( + HANDLE hConsoleOutput, + COORD dwSize + ) +{ +/* TO DO */ + return FALSE; +} + +/*-------------------------------------------------------------- + * SetConsoleCursorInfo + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleCursorInfo( + HANDLE hConsoleOutput, + CONST CONSOLE_CURSOR_INFO *lpConsoleCursorInfo + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SET_CURSOR_INFO; + Request.Data.SetCursorInfoRequest.ConsoleHandle = hConsoleOutput; + Request.Data.SetCursorInfoRequest.Info = *lpConsoleCursorInfo; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * ScrollConsoleScreenBufferA + */ +WINBASEAPI +BOOL +WINAPI +ScrollConsoleScreenBufferA( + HANDLE hConsoleOutput, + CONST SMALL_RECT *lpScrollRectangle, + CONST SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + CONST CHAR_INFO *lpFill + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SCROLL_CONSOLE_SCREEN_BUFFER; + Request.Data.ScrollConsoleScreenBufferRequest.ConsoleHandle = hConsoleOutput; + Request.Data.ScrollConsoleScreenBufferRequest.ScrollRectangle = *lpScrollRectangle; + + if (lpClipRectangle != NULL) + { + Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = TRUE; + Request.Data.ScrollConsoleScreenBufferRequest.ClipRectangle = *lpClipRectangle; + } + else + { + Request.Data.ScrollConsoleScreenBufferRequest.UseClipRectangle = FALSE; + } + + Request.Data.ScrollConsoleScreenBufferRequest.DestinationOrigin = dwDestinationOrigin; + Request.Data.ScrollConsoleScreenBufferRequest.Fill = *lpFill; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + + +/*-------------------------------------------------------------- + * ScrollConsoleScreenBufferW + */ +WINBASEAPI +BOOL +WINAPI +ScrollConsoleScreenBufferW( + HANDLE hConsoleOutput, + CONST SMALL_RECT *lpScrollRectangle, + CONST SMALL_RECT *lpClipRectangle, + COORD dwDestinationOrigin, + CONST CHAR_INFO *lpFill + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * SetConsoleWindowInfo + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleWindowInfo( + HANDLE hConsoleOutput, + BOOL bAbsolute, + CONST SMALL_RECT *lpConsoleWindow + ) +{ +/* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * SetConsoleTextAttribute + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleTextAttribute( + HANDLE hConsoleOutput, + WORD wAttributes + ) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_SET_ATTRIB; + Request.Data.SetAttribRequest.ConsoleHandle = hConsoleOutput; + Request.Data.SetAttribRequest.Attrib = wAttributes; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return TRUE; +} + +BOOL STATIC +AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) +{ + if (HandlerRoutine == NULL) + { + IgnoreCtrlEvents = TRUE; + return(TRUE); + } + else + { + NrCtrlHandlers++; + CtrlHandlers = + RtlReAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + (PVOID)CtrlHandlers, + NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); + if (CtrlHandlers == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return(FALSE); + } + CtrlHandlers[NrCtrlHandlers - 1] = HandlerRoutine; + return(TRUE); + } +} + +BOOL STATIC +RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine) +{ + ULONG i; + + if (HandlerRoutine == NULL) + { + IgnoreCtrlEvents = FALSE; + return(TRUE); + } + else + { + for (i = 0; i < NrCtrlHandlers; i++) + { + if (CtrlHandlers[i] == HandlerRoutine) + { + CtrlHandlers[i] = CtrlHandlers[NrCtrlHandlers - 1]; + NrCtrlHandlers--; + CtrlHandlers = + RtlReAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + (PVOID)CtrlHandlers, + NrCtrlHandlers * sizeof(PHANDLER_ROUTINE)); + return(TRUE); + } + } + } + return(FALSE); +} + +WINBASEAPI BOOL WINAPI +SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, + BOOL Add) +{ + BOOLEAN Ret; + + RtlEnterCriticalSection(&DllLock); + if (Add) + { + Ret = AddConsoleCtrlHandler(HandlerRoutine); + } + else + { + Ret = RemoveConsoleCtrlHandler(HandlerRoutine); + } + RtlLeaveCriticalSection(&DllLock); + return(Ret); +} + + +/*-------------------------------------------------------------- + * GenerateConsoleCtrlEvent + */ +WINBASEAPI BOOL WINAPI +GenerateConsoleCtrlEvent( + DWORD dwCtrlEvent, + DWORD dwProcessGroupId + ) +{ + /* TO DO */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * GetConsoleTitleW + */ +#define MAX_CONSOLE_TITLE_LENGTH 80 + +WINBASEAPI +DWORD +WINAPI +GetConsoleTitleW( + LPWSTR lpConsoleTitle, + DWORD nSize + ) +{ + union { + CSRSS_API_REQUEST quest; + CSRSS_API_REPLY ply; + } Re; + NTSTATUS Status; + + /* Marshall data */ + Re.quest.Type = CSRSS_GET_TITLE; + Re.quest.Data.GetTitleRequest.ConsoleHandle = + GetStdHandle (STD_INPUT_HANDLE); + + /* Call CSRSS */ + Status = CsrClientCallServer ( + & Re.quest, + & Re.ply, + (sizeof (CSRSS_GET_TITLE_REQUEST) + + sizeof (LPC_MESSAGE_HEADER) + + sizeof (ULONG)), + sizeof (CSRSS_API_REPLY) + ); + if ( !NT_SUCCESS(Status) + || !NT_SUCCESS (Status = Re.ply.Status) + ) + { + SetLastErrorByStatus (Status); + return (0); + } + + /* Convert size in characters to size in bytes */ + nSize = sizeof (WCHAR) * nSize; + + /* Unmarshall data */ + if (nSize < Re.ply.Data.GetTitleReply.Length) + { + DbgPrint ("%s: ret=%d\n", __FUNCTION__, Re.ply.Data.GetTitleReply.Length); + nSize /= sizeof (WCHAR); + if (nSize > 1) + { + wcsncpy ( + lpConsoleTitle, + Re.ply.Data.GetTitleReply.Title, + (nSize - 1) + ); + /* Add null */ + lpConsoleTitle [nSize --] = L'\0'; + } + } + else + { + nSize = Re.ply.Data.GetTitleReply.Length / sizeof (WCHAR); + wcscpy (lpConsoleTitle, Re.ply.Data.GetTitleReply.Title); + } + + return nSize; +} + + +/*-------------------------------------------------------------- + * GetConsoleTitleA + * + * 19990306 EA + */ +WINBASEAPI +DWORD +WINAPI +GetConsoleTitleA( + LPSTR lpConsoleTitle, + DWORD nSize + ) +{ + wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH]; + DWORD nWideTitle = sizeof WideTitle; +// DWORD nWritten; + + if (!lpConsoleTitle || !nSize) return 0; + nWideTitle = GetConsoleTitleW( (LPWSTR) WideTitle, nWideTitle ); + if (!nWideTitle) return 0; +#if 0 + if ( (nWritten = WideCharToMultiByte( + CP_ACP, // ANSI code page + 0, // performance and mapping flags + (LPWSTR) WideTitle, // address of wide-character string + nWideTitle, // number of characters in string + lpConsoleTitle, // address of buffer for new string + nSize, // size of buffer + NULL, // FAST + NULL // FAST + ))) + { + lpConsoleTitle[nWritten] = '\0'; + return nWritten; + } +#endif + return 0; +} + + +/*-------------------------------------------------------------- + * SetConsoleTitleW + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleTitleW( + LPCWSTR lpConsoleTitle + ) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + unsigned int c; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST); + if (Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + Request->Type = CSRSS_SET_TITLE; + Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE ); + + for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ ) + Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c]; + // add null + Request->Data.SetTitleRequest.Title[c] = 0; + Request->Data.SetTitleRequest.Length = c; + Status = CsrClientCallServer(Request, + &Reply, + sizeof(CSRSS_SET_TITLE_REQUEST) + + c + + sizeof( LPC_MESSAGE_HEADER ) + + sizeof( ULONG ), + sizeof(CSRSS_API_REPLY)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) ) + { + RtlFreeHeap( GetProcessHeap(), 0, Request ); + SetLastErrorByStatus (Status); + return(FALSE); + } + RtlFreeHeap( GetProcessHeap(), 0, Request ); + return TRUE; +} + + +/*-------------------------------------------------------------- + * SetConsoleTitleA + * + * 19990204 EA Added + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleTitleA( + LPCSTR lpConsoleTitle + ) +{ + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + unsigned int c; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST); + if (Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + Request->Type = CSRSS_SET_TITLE; + Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE ); + + for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ ) + Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c]; + // add null + Request->Data.SetTitleRequest.Title[c] = 0; + Request->Data.SetTitleRequest.Length = c; + Status = CsrClientCallServer(Request, + &Reply, + sizeof(CSRSS_SET_TITLE_REQUEST) + + c + + sizeof( LPC_MESSAGE_HEADER ) + + sizeof( ULONG ), + sizeof(CSRSS_API_REPLY)); + + if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) ) + { + RtlFreeHeap( GetProcessHeap(), 0, Request ); + SetLastErrorByStatus (Status); + return(FALSE); + } + RtlFreeHeap( GetProcessHeap(), 0, Request ); + return TRUE; +} + + +/*-------------------------------------------------------------- + * ReadConsoleW + */ +WINBASEAPI +BOOL +WINAPI +ReadConsoleW( + HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + LPVOID lpReserved + ) +{ +/* --- TO DO --- */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * WriteConsoleW + */ +WINBASEAPI +BOOL +WINAPI +WriteConsoleW( + HANDLE hConsoleOutput, + CONST VOID *lpBuffer, + DWORD nNumberOfCharsToWrite, + LPDWORD lpNumberOfCharsWritten, + LPVOID lpReserved + ) +{ +#if 0 + PCSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request = RtlAllocateHeap(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite * sizeof(WCHAR)); + if (Request == NULL) + { + SetLastError(ERROR_OUTOFMEMORY); + return(FALSE); + } + + Request->Type = CSRSS_WRITE_CONSOLE; + Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput; + Request->Data.WriteConsoleRequest.NrCharactersToWrite = + nNumberOfCharsToWrite; +// DbgPrint("nNumberOfCharsToWrite %d\n", nNumberOfCharsToWrite); +// DbgPrint("Buffer %s\n", Request->Data.WriteConsoleRequest.Buffer); + memcpy(Request->Data.WriteConsoleRequest.Buffer, + lpBuffer, + nNumberOfCharsToWrite * sizeof(WCHAR)); + + Status = CsrClientCallServer(Request, + &Reply, + sizeof(CSRSS_API_REQUEST) + nNumberOfCharsToWrite, + sizeof(CSRSS_API_REPLY)); + + RtlFreeHeap(GetProcessHeap(), + 0, + Request); + + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + if (lpNumberOfCharsWritten != NULL) + { + *lpNumberOfCharsWritten = + Reply.Data.WriteConsoleReply.NrCharactersWritten; + } + + return(TRUE); +#endif + return(FALSE); +} + + +/*-------------------------------------------------------------- + * CreateConsoleScreenBuffer + */ +WINBASEAPI +HANDLE +WINAPI +CreateConsoleScreenBuffer( + DWORD dwDesiredAccess, + DWORD dwShareMode, + CONST SECURITY_ATTRIBUTES *lpSecurityAttributes, + DWORD dwFlags, + LPVOID lpScreenBufferData + ) +{ + // FIXME: don't ignore access, share mode, and security + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_CREATE_SCREEN_BUFFER; + Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) ); + if( !NT_SUCCESS( Status ) || !NT_SUCCESS( Status = Reply.Status ) ) + { + SetLastErrorByStatus ( Status ); + return FALSE; + } + return Reply.Data.CreateScreenBufferReply.OutputHandle; +} + + +/*-------------------------------------------------------------- + * GetConsoleCP + */ +WINBASEAPI +UINT +WINAPI +GetConsoleCP( VOID ) +{ +/* --- TO DO --- */ + return CP_OEMCP; /* FIXME */ +} + + +/*-------------------------------------------------------------- + * SetConsoleCP + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleCP( + UINT wCodePageID + ) +{ +/* --- TO DO --- */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * GetConsoleOutputCP + */ +WINBASEAPI +UINT +WINAPI +GetConsoleOutputCP( VOID ) +{ +/* --- TO DO --- */ + return 0; /* FIXME */ +} + + +/*-------------------------------------------------------------- + * SetConsoleOutputCP + */ +WINBASEAPI +BOOL +WINAPI +SetConsoleOutputCP( + UINT wCodePageID + ) +{ +/* --- TO DO --- */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * GetConsoleProcessList + */ +DWORD STDCALL +GetConsoleProcessList(LPDWORD lpdwProcessList, + DWORD dwProcessCount) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +/*-------------------------------------------------------------- + * GetConsoleSelectionInfo + */ +BOOL STDCALL +GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +/*-------------------------------------------------------------- + * AttachConsole + */ +BOOL STDCALL +AttachConsole(DWORD dwProcessId) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/* EOF */ diff --git a/lib/kernel32/misc/debug.c b/lib/kernel32/misc/debug.c new file mode 100644 index 0000000..10a1faf --- /dev/null +++ b/lib/kernel32/misc/debug.c @@ -0,0 +1,118 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/debug.c + * PURPOSE: Application debugger support functions + * PROGRAMMER: ??? + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +ContinueDebugEvent ( + DWORD dwProcessId, + DWORD dwThreadId, + DWORD dwContinueStatus + ) +{ + CLIENT_ID ClientId; + NTSTATUS Status; + + ClientId.UniqueProcess = (HANDLE)dwProcessId; + ClientId.UniqueThread = (HANDLE)dwThreadId; + + Status = DbgUiContinue (&ClientId, + dwContinueStatus); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + return TRUE; +} + + +WINBOOL +STDCALL +DebugActiveProcess ( + DWORD dwProcessId + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +VOID +STDCALL +DebugBreak ( + VOID + ) +{ + DbgBreakPoint (); +} + + +WINBOOL +STDCALL +IsDebuggerPresent ( + VOID + ) +{ + return (WINBOOL)NtCurrentPeb ()->BeingDebugged; +} + + +/* + * NOTE: Don't call DbgService()! + * It's a ntdll internal function and is NOT exported! + */ + +VOID STDCALL OutputDebugStringA(LPCSTR lpOutputString) +{ + DbgPrint( (PSTR)lpOutputString ); +} + +VOID STDCALL OutputDebugStringW(LPCWSTR lpOutputString) +{ + UNICODE_STRING UnicodeOutput; + ANSI_STRING AnsiString; + char buff[512]; + + UnicodeOutput.Buffer = (WCHAR *)lpOutputString; + UnicodeOutput.Length = lstrlenW(lpOutputString)*sizeof(WCHAR); + UnicodeOutput.MaximumLength = UnicodeOutput.Length; + AnsiString.Buffer = buff; + AnsiString.MaximumLength = 512; + AnsiString.Length = 0; + if( UnicodeOutput.Length > 512 ) + UnicodeOutput.Length = 512; + if( NT_SUCCESS( RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeOutput, FALSE ) ) ) + DbgPrint( AnsiString.Buffer ); +} + + +WINBOOL +STDCALL +WaitForDebugEvent ( + LPDEBUG_EVENT lpDebugEvent, + DWORD dwMilliseconds + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/* EOF */ diff --git a/lib/kernel32/misc/dllmain.c b/lib/kernel32/misc/dllmain.c new file mode 100644 index 0000000..0005813 --- /dev/null +++ b/lib/kernel32/misc/dllmain.c @@ -0,0 +1,167 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/dllmain.c + * PURPOSE: Initialization + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +extern UNICODE_STRING SystemDirectory; +extern UNICODE_STRING WindowsDirectory; + +HANDLE hProcessHeap = NULL; +HANDLE hBaseDir = NULL; + +static WINBOOL DllInitialized = FALSE; + +WINBOOL STDCALL DllMain (HANDLE hInst, + ULONG ul_reason_for_call, + LPVOID lpReserved); + +/* Critical section for various kernel32 data structures */ +CRITICAL_SECTION DllLock; + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS +OpenBaseDirectory(PHANDLE DirHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name = UNICODE_STRING_INITIALIZER(L"\\BaseNamedObjects"); + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_PERMANENT, + NULL, + NULL); + + Status = NtOpenDirectoryObject(DirHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + Status = NtCreateDirectoryObject(DirHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NtCreateDirectoryObject() failed\n"); + } + + return Status; + } + + return STATUS_SUCCESS; +} + + +BOOL WINAPI +DllMainCRTStartup(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + return(DllMain(hDll,dwReason,lpReserved)); +} + +WINBOOL STDCALL +DllMain(HANDLE hInst, + ULONG ul_reason_for_call, + LPVOID lpReserved) +{ + DPRINT("DllMain(hInst %x, ul_reason_for_call %d)\n", + hInst, ul_reason_for_call); + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + NTSTATUS Status; + + DPRINT("DLL_PROCESS_ATTACH\n"); + + LdrDisableThreadCalloutsForDll ((PVOID)hInst); + + /* + * Connect to the csrss server + */ + Status = CsrClientConnectToServer(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to connect to csrss.exe: expect trouble " + "Status was %X\n", Status); + ZwTerminateProcess(NtCurrentProcess(), Status); + } + + hProcessHeap = RtlGetProcessHeap(); + + /* + * Initialize WindowsDirectory and SystemDirectory + */ + DPRINT("NtSystemRoot: %S\n", + SharedUserData->NtSystemRoot); + RtlCreateUnicodeString (&WindowsDirectory, + SharedUserData->NtSystemRoot); + SystemDirectory.MaximumLength = WindowsDirectory.MaximumLength + 18; + SystemDirectory.Length = WindowsDirectory.Length + 18; + SystemDirectory.Buffer = RtlAllocateHeap (hProcessHeap, + 0, + SystemDirectory.MaximumLength); + wcscpy (SystemDirectory.Buffer, WindowsDirectory.Buffer); + wcscat (SystemDirectory.Buffer, L"\\System32"); + + /* Open object base directory */ + Status = OpenBaseDirectory(&hBaseDir); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to open object base directory: expect trouble\n"); + } + + /* Initialize the DLL critical section */ + RtlInitializeCriticalSection(&DllLock); + + /* Insert more dll attach stuff here! */ + + DllInitialized = TRUE; + + break; + } + case DLL_PROCESS_DETACH: + { + DPRINT("DLL_PROCESS_DETACH\n"); + if (DllInitialized == TRUE) + { + /* Insert more dll detach stuff here! */ + + /* Delete DLL critical section */ + RtlDeleteCriticalSection (&DllLock); + + /* Close object base directory */ + NtClose(hBaseDir); + + RtlFreeUnicodeString (&SystemDirectory); + RtlFreeUnicodeString (&WindowsDirectory); + } + break; + } + default: + break; + } + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/misc/env.c b/lib/kernel32/misc/env.c new file mode 100644 index 0000000..7375940 --- /dev/null +++ b/lib/kernel32/misc/env.c @@ -0,0 +1,464 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/env.c + * PURPOSE: Environment functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* FUNCTIONS ******************************************************************/ + +DWORD +STDCALL +GetEnvironmentVariableA ( + LPCSTR lpName, + LPSTR lpBuffer, + DWORD nSize + ) +{ + ANSI_STRING VarName; + ANSI_STRING VarValue; + UNICODE_STRING VarNameU; + UNICODE_STRING VarValueU; + NTSTATUS Status; + + /* initialize unicode variable name string */ + RtlInitAnsiString (&VarName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString (&VarNameU, + &VarName, + TRUE); + + /* initialize ansi variable value string */ + VarValue.Length = 0; + VarValue.MaximumLength = nSize; + VarValue.Buffer = lpBuffer; + + /* initialize unicode variable value string and allocate buffer */ + VarValueU.Length = 0; + VarValueU.MaximumLength = nSize * sizeof(WCHAR); + VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + VarValueU.MaximumLength); + + /* get unicode environment variable */ + Status = RtlQueryEnvironmentVariable_U (NULL, + &VarNameU, + &VarValueU); + if (!NT_SUCCESS(Status)) + { + /* free unicode buffer */ + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VarValueU.Buffer); + + /* free unicode variable name string */ + RtlFreeUnicodeString (&VarNameU); + + SetLastErrorByStatus (Status); + if (Status == STATUS_BUFFER_TOO_SMALL) + { + return VarValueU.Length / sizeof(WCHAR) + 1; + } + else + { + return 0; + } + } + + /* convert unicode value string to ansi */ + RtlUnicodeStringToAnsiString (&VarValue, + &VarValueU, + FALSE); + + /* free unicode buffer */ + RtlFreeHeap (RtlGetProcessHeap (), + 0, + VarValueU.Buffer); + + /* free unicode variable name string */ + RtlFreeUnicodeString (&VarNameU); + + return (VarValueU.Length / sizeof(WCHAR)); +} + + +DWORD +STDCALL +GetEnvironmentVariableW ( + LPCWSTR lpName, + LPWSTR lpBuffer, + DWORD nSize + ) +{ + UNICODE_STRING VarName; + UNICODE_STRING VarValue; + NTSTATUS Status; + + RtlInitUnicodeString (&VarName, + lpName); + + VarValue.Length = 0; + VarValue.MaximumLength = nSize * sizeof(WCHAR); + VarValue.Buffer = lpBuffer; + + Status = RtlQueryEnvironmentVariable_U (NULL, + &VarName, + &VarValue); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + if (Status == STATUS_BUFFER_TOO_SMALL) + { + return (VarValue.Length / sizeof(WCHAR)) + 1; + } + else + { + return 0; + } + } + + return (VarValue.Length / sizeof(WCHAR)); +} + + +WINBOOL +STDCALL +SetEnvironmentVariableA ( + LPCSTR lpName, + LPCSTR lpValue + ) +{ + ANSI_STRING VarName; + ANSI_STRING VarValue; + UNICODE_STRING VarNameU; + UNICODE_STRING VarValueU; + NTSTATUS Status; + + DPRINT("SetEnvironmentVariableA(Name '%s', Value '%s')\n", lpName, lpValue); + + RtlInitAnsiString (&VarName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString (&VarNameU, + &VarName, + TRUE); + + RtlInitAnsiString (&VarValue, + (LPSTR)lpValue); + RtlAnsiStringToUnicodeString (&VarValueU, + &VarValue, + TRUE); + + Status = RtlSetEnvironmentVariable (NULL, + &VarNameU, + &VarValueU); + + RtlFreeUnicodeString (&VarNameU); + RtlFreeUnicodeString (&VarValueU); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + + +WINBOOL +STDCALL +SetEnvironmentVariableW ( + LPCWSTR lpName, + LPCWSTR lpValue + ) +{ + UNICODE_STRING VarName; + UNICODE_STRING VarValue; + NTSTATUS Status; + + DPRINT("SetEnvironmentVariableW(Name '%S', Value '%S')\n", lpName, lpValue); + + RtlInitUnicodeString (&VarName, + lpName); + + RtlInitUnicodeString (&VarValue, + lpValue); + + Status = RtlSetEnvironmentVariable (NULL, + &VarName, + &VarValue); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + + +DWORD +STDCALL +GetVersion(VOID) +{ + DWORD Version = 0; + OSVERSIONINFO VersionInformation; + GetVersionExW(&VersionInformation); + + Version |= ( VersionInformation.dwMajorVersion << 8 ); + Version |= VersionInformation.dwMinorVersion; + + Version |= ( VersionInformation.dwPlatformId << 16 ); + + return Version; +} + + +WINBOOL +STDCALL +GetVersionExW( + LPOSVERSIONINFO lpVersionInformation + ) +{ + lpVersionInformation->dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + lpVersionInformation->dwMajorVersion = 4; + lpVersionInformation->dwMinorVersion = 0; + lpVersionInformation->dwBuildNumber = 12; + lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT; + lstrcpyW((WCHAR *)lpVersionInformation->szCSDVersion,L"Ariadne was here..."); + return TRUE; +} + + +WINBOOL +STDCALL +GetVersionExA( + LPOSVERSIONINFO lpVersionInformation + ) +{ + lpVersionInformation->dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + lpVersionInformation->dwMajorVersion = 4; + lpVersionInformation->dwMinorVersion = 0; + lpVersionInformation->dwBuildNumber = 12; + lpVersionInformation->dwPlatformId = VER_PLATFORM_WIN32_NT; + lstrcpyA((char *)lpVersionInformation->szCSDVersion,"ReactOs Pre-Alpha"); + return TRUE; +} + + +LPSTR +STDCALL +GetEnvironmentStringsA ( + VOID + ) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + PWCHAR EnvU; + PWCHAR PtrU; + ULONG Length; + PCHAR EnvPtr = NULL; + + EnvU = (PWCHAR)(NtCurrentPeb ()->ProcessParameters->Environment); + + if (EnvU == NULL) + return NULL; + + if (*EnvU == 0) + return NULL; + + /* get environment size */ + PtrU = EnvU; + while (*PtrU) + { + while (*PtrU) + PtrU++; + PtrU++; + } + Length = (ULONG)(PtrU - EnvU); + DPRINT("Length %lu\n", Length); + + /* allocate environment buffer */ + EnvPtr = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length + 1); + DPRINT("EnvPtr %p\n", EnvPtr); + + /* convert unicode environment to ansi */ + UnicodeString.MaximumLength = Length * sizeof(WCHAR) + sizeof(WCHAR); + UnicodeString.Buffer = EnvU; + + AnsiString.MaximumLength = Length + 1; + AnsiString.Length = 0; + AnsiString.Buffer = EnvPtr; + + DPRINT ("UnicodeString.Buffer \'%S\'\n", UnicodeString.Buffer); + + while (*(UnicodeString.Buffer)) + { + UnicodeString.Length = wcslen (UnicodeString.Buffer) * sizeof(WCHAR); + UnicodeString.MaximumLength = UnicodeString.Length + sizeof(WCHAR); + if (UnicodeString.Length > 0) + { + AnsiString.Length = 0; + AnsiString.MaximumLength = Length + 1 - (AnsiString.Buffer - EnvPtr); + + RtlUnicodeStringToAnsiString (&AnsiString, + &UnicodeString, + FALSE); + + AnsiString.Buffer += (AnsiString.Length + 1); + UnicodeString.Buffer += ((UnicodeString.Length / sizeof(WCHAR)) + 1); + } + } + *(AnsiString.Buffer) = 0; + + return EnvPtr; +} + + +LPWSTR +STDCALL +GetEnvironmentStringsW ( + VOID + ) +{ + return (LPWSTR)(NtCurrentPeb ()->ProcessParameters->Environment); +} + + +WINBOOL +STDCALL +FreeEnvironmentStringsA ( + LPSTR EnvironmentStrings + ) +{ + if (EnvironmentStrings == NULL) + return FALSE; + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + EnvironmentStrings); + + return TRUE; +} + + +WINBOOL +STDCALL +FreeEnvironmentStringsW ( + LPWSTR EnvironmentStrings + ) +{ + return TRUE; +} + + +DWORD +STDCALL +ExpandEnvironmentStringsA ( + LPCSTR lpSrc, + LPSTR lpDst, + DWORD nSize + ) +{ + ANSI_STRING Source; + ANSI_STRING Destination; + UNICODE_STRING SourceU; + UNICODE_STRING DestinationU; + NTSTATUS Status; + ULONG Length = 0; + + RtlInitAnsiString (&Source, + (LPSTR)lpSrc); + RtlAnsiStringToUnicodeString (&SourceU, + &Source, + TRUE); + + Destination.Length = 0; + Destination.MaximumLength = nSize; + Destination.Buffer = lpDst, + + DestinationU.Length = 0; + DestinationU.MaximumLength = nSize * sizeof(WCHAR); + DestinationU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + DestinationU.MaximumLength); + + Status = RtlExpandEnvironmentStrings_U (NULL, + &SourceU, + &DestinationU, + &Length); + + RtlFreeUnicodeString (&SourceU); + + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationU.Buffer); + SetLastErrorByStatus (Status); + return 0; + } + + RtlUnicodeStringToAnsiString (&Destination, + &DestinationU, + FALSE); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationU.Buffer); + + return (Length / sizeof(WCHAR)); +} + + +DWORD +STDCALL +ExpandEnvironmentStringsW ( + LPCWSTR lpSrc, + LPWSTR lpDst, + DWORD nSize + ) +{ + UNICODE_STRING Source; + UNICODE_STRING Destination; + NTSTATUS Status; + ULONG Length = 0; + + RtlInitUnicodeString (&Source, + (LPWSTR)lpSrc); + + Destination.Length = 0; + Destination.MaximumLength = nSize * sizeof(WCHAR); + Destination.Buffer = lpDst; + + Status = RtlExpandEnvironmentStrings_U (NULL, + &Source, + &Destination, + &Length); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return 0; + } + + return (Length / sizeof(WCHAR)); +} + +/* EOF */ diff --git a/lib/kernel32/misc/error.c b/lib/kernel32/misc/error.c new file mode 100644 index 0000000..ca49750 --- /dev/null +++ b/lib/kernel32/misc/error.c @@ -0,0 +1,81 @@ +/* $Id$ + * + * reactos/lib/kernel32/misc/error.c + * + */ +#include +#include + +// #define NDEBUG +#include +#include + + +/* INTERNAL */ +DWORD +STDCALL +SetLastErrorByStatus ( + NTSTATUS Status + ) +{ + DWORD Error = RtlNtStatusToDosError (Status); + SetLastError (Error); + return (Error); +} + + +VOID +STDCALL +SetLastError ( + DWORD dwErrorCode + ) +{ + NtCurrentTeb ()->LastErrorValue = (ULONG) dwErrorCode; +} + +DWORD +STDCALL +GetLastError (VOID) +{ + return (DWORD) (NtCurrentTeb ()->LastErrorValue); +} + + +WINBOOL +STDCALL +Beep (DWORD dwFreq, DWORD dwDuration) +{ + HANDLE hBeep; + BEEP_SET_PARAMETERS BeepSetParameters; + DWORD dwReturned; + + hBeep = CreateFile("\\\\.\\Beep", + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (hBeep == INVALID_HANDLE_VALUE) + return FALSE; + + /* Set beep data */ + BeepSetParameters.Frequency = dwFreq; + BeepSetParameters.Duration = dwDuration; + + DeviceIoControl(hBeep, + IOCTL_BEEP_SET, + &BeepSetParameters, + sizeof(BEEP_SET_PARAMETERS), + NULL, + 0, + &dwReturned, + NULL); + + CloseHandle (hBeep); + + return TRUE; +} + + +/* EOF */ diff --git a/lib/kernel32/misc/handle.c b/lib/kernel32/misc/handle.c new file mode 100644 index 0000000..2011d89 --- /dev/null +++ b/lib/kernel32/misc/handle.c @@ -0,0 +1,160 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/handle.c + * PURPOSE: Object functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL WINAPI GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags) +{ + OBJECT_DATA_INFORMATION HandleInfo; + ULONG BytesWritten; + NTSTATUS errCode; + + errCode = NtQueryObject(hObject, + ObjectDataInformation, + &HandleInfo, + sizeof(OBJECT_DATA_INFORMATION), + &BytesWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + if ( HandleInfo.bInheritHandle ) + *lpdwFlags &= HANDLE_FLAG_INHERIT; + if ( HandleInfo.bProtectFromClose ) + *lpdwFlags &= HANDLE_FLAG_PROTECT_FROM_CLOSE; + return TRUE; +} + + +WINBOOL STDCALL SetHandleInformation(HANDLE hObject, + DWORD dwMask, + DWORD dwFlags) +{ + OBJECT_DATA_INFORMATION HandleInfo; + NTSTATUS errCode; + ULONG BytesWritten; + + errCode = NtQueryObject(hObject, + ObjectDataInformation, + &HandleInfo, + sizeof(OBJECT_DATA_INFORMATION), + &BytesWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + if (dwMask & HANDLE_FLAG_INHERIT) + { + HandleInfo.bInheritHandle = TRUE; + } + if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) + { + HandleInfo.bProtectFromClose = TRUE; + } + + errCode = NtSetInformationObject(hObject, + ObjectDataInformation, + &HandleInfo, + sizeof(OBJECT_DATA_INFORMATION)); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + + return TRUE; +} + + +WINBOOL STDCALL CloseHandle(HANDLE hObject) +/* + * FUNCTION: Closes an open object handle + * PARAMETERS: + * hObject = Identifies an open object handle + * RETURNS: If the function succeeds, the return value is nonzero + * If the function fails, the return value is zero + */ +{ + NTSTATUS errCode; + + if (IsConsoleHandle(hObject)) + { + return(CloseConsoleHandle(hObject)); + } + + errCode = NtClose(hObject); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + + return TRUE; +} + + +WINBOOL STDCALL DuplicateHandle(HANDLE hSourceProcessHandle, + HANDLE hSourceHandle, + HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions) +{ + NTSTATUS errCode; + if (IsConsoleHandle(hSourceHandle)) + { + /* FIXME: call CSRSS for console handle duplication */ + if (hSourceProcessHandle == hTargetProcessHandle) + { + *lpTargetHandle = hSourceHandle; + return TRUE; + } + else + { + return FALSE; + } + } + + errCode = NtDuplicateObject(hSourceProcessHandle, + hSourceHandle, + hTargetProcessHandle, + lpTargetHandle, + dwDesiredAccess, + (BOOLEAN)bInheritHandle, + dwOptions); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + + return TRUE; +} + +UINT STDCALL SetHandleCount(UINT nCount) +{ + return(nCount); +} + + +/* EOF */ diff --git a/lib/kernel32/misc/ldr.c b/lib/kernel32/misc/ldr.c new file mode 100644 index 0000000..90f1ec4 --- /dev/null +++ b/lib/kernel32/misc/ldr.c @@ -0,0 +1,370 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT : ReactOS user mode libraries + * MODULE : kernel32.dll + * FILE : reactos/lib/kernel32/misc/ldr.c + * AUTHOR : Boudewijn Dekker + */ + +#include +#include +#include + +#define NDEBUG +#include +#include + + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +DisableThreadLibraryCalls ( + HMODULE hLibModule + ) +{ + NTSTATUS Status; + + Status = LdrDisableThreadCalloutsForDll ((PVOID)hLibModule); + if (!NT_SUCCESS (Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + return TRUE; +} + + +HINSTANCE +STDCALL +LoadLibraryA ( + LPCSTR lpLibFileName + ) +{ + return LoadLibraryExA (lpLibFileName, 0, 0); +} + + +HINSTANCE +STDCALL +LoadLibraryExA ( + LPCSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags + ) +{ + UNICODE_STRING LibFileNameU; + ANSI_STRING LibFileName; + HINSTANCE hInst; + NTSTATUS Status; + + RtlInitAnsiString (&LibFileName, + (LPSTR)lpLibFileName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&LibFileNameU, + &LibFileName, + TRUE); + else + RtlOemStringToUnicodeString (&LibFileNameU, + &LibFileName, + TRUE); + + Status = LdrLoadDll(NULL, + dwFlags, + &LibFileNameU, + (PVOID*)&hInst); + + RtlFreeUnicodeString (&LibFileNameU); + + if ( !NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return NULL; + } + + return hInst; +} + + +HINSTANCE +STDCALL +LoadLibraryW ( + LPCWSTR lpLibFileName + ) +{ + return LoadLibraryExW (lpLibFileName, 0, 0); +} + + +HINSTANCE +STDCALL +LoadLibraryExW ( + LPCWSTR lpLibFileName, + HANDLE hFile, + DWORD dwFlags + ) +{ + UNICODE_STRING DllName; + HINSTANCE hInst; + NTSTATUS Status; + + if ( lpLibFileName == NULL ) + return NULL; + + RtlInitUnicodeString (&DllName, (LPWSTR)lpLibFileName); + Status = LdrLoadDll(NULL, dwFlags, &DllName, (PVOID*)&hInst); + if ( !NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return NULL; + } + + return hInst; +} + + +FARPROC +STDCALL +GetProcAddress( HMODULE hModule, LPCSTR lpProcName ) +{ + ANSI_STRING ProcedureName; + FARPROC fnExp = NULL; + + if (HIWORD(lpProcName) != 0) + { + RtlInitAnsiString (&ProcedureName, + (LPSTR)lpProcName); + LdrGetProcedureAddress ((PVOID)hModule, + &ProcedureName, + 0, + (PVOID*)&fnExp); + } + else + { + LdrGetProcedureAddress ((PVOID)hModule, + NULL, + (ULONG)lpProcName, + (PVOID*)&fnExp); + } + + return fnExp; +} + + +WINBOOL +STDCALL +FreeLibrary( HMODULE hLibModule ) +{ + LdrUnloadDll(hLibModule); + return TRUE; +} + + +VOID +STDCALL +FreeLibraryAndExitThread ( + HMODULE hLibModule, + DWORD dwExitCode + ) +{ + if ( FreeLibrary(hLibModule) ) + ExitThread(dwExitCode); + return; +} + + +DWORD +STDCALL +GetModuleFileNameA ( + HINSTANCE hModule, + LPSTR lpFilename, + DWORD nSize + ) +{ + ANSI_STRING FileName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + PPEB Peb; + ULONG Length = 0; + + Peb = NtCurrentPeb (); + RtlEnterCriticalSection (Peb->LoaderLock); + + if (hModule == NULL) + hModule = Peb->ImageBaseAddress; + + ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + if (Module->BaseAddress == (PVOID)hModule) + { + if (nSize * sizeof(WCHAR) < Module->FullDllName.Length) + { + SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL); + } + else + { + FileName.Length = 0; + FileName.MaximumLength = nSize * sizeof(WCHAR); + FileName.Buffer = lpFilename; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&FileName, + &Module->FullDllName, + FALSE); + else + RtlUnicodeStringToOemString (&FileName, + &Module->FullDllName, + FALSE); + Length = Module->FullDllName.Length / sizeof(WCHAR); + } + + RtlLeaveCriticalSection (Peb->LoaderLock); + return Length; + } + + Entry = Entry->Flink; + } + + SetLastErrorByStatus (STATUS_DLL_NOT_FOUND); + RtlLeaveCriticalSection (Peb->LoaderLock); + + return 0; +} + + +DWORD +STDCALL +GetModuleFileNameW ( + HINSTANCE hModule, + LPWSTR lpFilename, + DWORD nSize + ) +{ + UNICODE_STRING FileName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + PPEB Peb; + ULONG Length = 0; + + Peb = NtCurrentPeb (); + RtlEnterCriticalSection (Peb->LoaderLock); + + if (hModule == NULL) + hModule = Peb->ImageBaseAddress; + + ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + if (Module->BaseAddress == (PVOID)hModule) + { + if (nSize * sizeof(WCHAR) < Module->FullDllName.Length) + { + SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL); + } + else + { + FileName.Length = 0; + FileName.MaximumLength = nSize * sizeof(WCHAR); + FileName.Buffer = lpFilename; + + RtlCopyUnicodeString (&FileName, + &Module->FullDllName); + Length = Module->FullDllName.Length / sizeof(WCHAR); + } + + RtlLeaveCriticalSection (Peb->LoaderLock); + return Length; + } + + Entry = Entry->Flink; + } + + SetLastErrorByStatus (STATUS_DLL_NOT_FOUND); + RtlLeaveCriticalSection (Peb->LoaderLock); + + return 0; +} + + +HMODULE +STDCALL +GetModuleHandleA ( LPCSTR lpModuleName ) +{ + UNICODE_STRING UnicodeName; + ANSI_STRING ModuleName; + PVOID BaseAddress; + NTSTATUS Status; + + if (lpModuleName == NULL) + return ((HMODULE)NtCurrentPeb()->ImageBaseAddress); + RtlInitAnsiString (&ModuleName, + (LPSTR)lpModuleName); + + /* convert ansi (or oem) string to unicode */ + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString (&UnicodeName, + &ModuleName, + TRUE); + else + RtlOemStringToUnicodeString (&UnicodeName, + &ModuleName, + TRUE); + + Status = LdrGetDllHandle (0, + 0, + &UnicodeName, + &BaseAddress); + + RtlFreeUnicodeString (&UnicodeName); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return NULL; + } + + return ((HMODULE)BaseAddress); +} + + +HMODULE +STDCALL +GetModuleHandleW (LPCWSTR lpModuleName) +{ + UNICODE_STRING ModuleName; + PVOID BaseAddress; + NTSTATUS Status; + + if (lpModuleName == NULL) + return ((HMODULE)NtCurrentPeb()->ImageBaseAddress); + + RtlInitUnicodeString (&ModuleName, + (LPWSTR)lpModuleName); + + Status = LdrGetDllHandle (0, + 0, + &ModuleName, + &BaseAddress); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return NULL; + } + + return ((HMODULE)BaseAddress); +} + +/* EOF */ diff --git a/lib/kernel32/misc/profile.c b/lib/kernel32/misc/profile.c new file mode 100644 index 0000000..99c8e1d --- /dev/null +++ b/lib/kernel32/misc/profile.c @@ -0,0 +1,381 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/profile.c + * PURPOSE: Profiles functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ] + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include +#include +#include +//#include + + +/* FUNCTIONS *****************************************************************/ + +BOOL STDCALL +CloseProfileUserMapping(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +UINT STDCALL +GetPrivateProfileIntW ( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + INT nDefault, + LPCWSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT STDCALL +GetPrivateProfileIntA ( + LPCSTR lpAppName, + LPCSTR lpKeyName, + INT nDefault, + LPCSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileSectionW ( + LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileSectionA ( + LPCSTR lpAppName, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileSectionNamesW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileSectionNamesA ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileStringW ( + LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize, + LPCWSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileStringA ( + LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize, + LPCSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileStructW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD STDCALL +GetPrivateProfileStructA ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +UINT STDCALL +GetProfileIntW(LPCWSTR lpAppName, + LPCWSTR lpKeyName, + INT nDefault) +{ + return GetPrivateProfileIntW(lpAppName, + lpKeyName, + nDefault, + NULL); +} + + +UINT STDCALL +GetProfileIntA(LPCSTR lpAppName, + LPCSTR lpKeyName, + INT nDefault) +{ + return GetPrivateProfileIntA(lpAppName, + lpKeyName, + nDefault, + NULL); +} + + +DWORD STDCALL +GetProfileSectionW(LPCWSTR lpAppName, + LPWSTR lpReturnedString, + DWORD nSize) +{ + return GetPrivateProfileSectionW(lpAppName, + lpReturnedString, + nSize, + NULL); +} + + +DWORD STDCALL +GetProfileSectionA(LPCSTR lpAppName, + LPSTR lpReturnedString, + DWORD nSize) +{ + return GetPrivateProfileSectionA(lpAppName, + lpReturnedString, + nSize, + NULL); +} + + +DWORD STDCALL +GetProfileStringW(LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpDefault, + LPWSTR lpReturnedString, + DWORD nSize) +{ + return GetPrivateProfileStringW(lpAppName, + lpKeyName, + lpDefault, + lpReturnedString, + nSize, + NULL); +} + + +DWORD STDCALL +GetProfileStringA(LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpDefault, + LPSTR lpReturnedString, + DWORD nSize) +{ + return GetPrivateProfileStringA(lpAppName, + lpKeyName, + lpDefault, + lpReturnedString, + nSize, + NULL); +} + + +BOOL STDCALL +OpenProfileUserMapping (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL STDCALL +QueryWin31IniFilesMappedToRegistry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WritePrivateProfileSectionA ( + LPCSTR lpAppName, + LPCSTR lpString, + LPCSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WritePrivateProfileSectionW ( + LPCWSTR lpAppName, + LPCWSTR lpString, + LPCWSTR lpFileName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WritePrivateProfileStringA(LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpString, + LPCSTR lpFileName) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WritePrivateProfileStringW(LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpString, + LPCWSTR lpFileName) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WritePrivateProfileStructA ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WritePrivateProfileStructW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL STDCALL +WriteProfileSectionA(LPCSTR lpAppName, + LPCSTR lpString) +{ + return WritePrivateProfileSectionA(lpAppName, + lpString, + NULL); +} + + +WINBOOL STDCALL +WriteProfileSectionW(LPCWSTR lpAppName, + LPCWSTR lpString) +{ + return WritePrivateProfileSectionW(lpAppName, + lpString, + NULL); +} + + +WINBOOL STDCALL +WriteProfileStringA(LPCSTR lpAppName, + LPCSTR lpKeyName, + LPCSTR lpString) +{ + return WritePrivateProfileStringA(lpAppName, + lpKeyName, + lpString, + NULL); +} + + +WINBOOL STDCALL +WriteProfileStringW(LPCWSTR lpAppName, + LPCWSTR lpKeyName, + LPCWSTR lpString) +{ + return WritePrivateProfileStringW(lpAppName, + lpKeyName, + lpString, + NULL); +} + +/* EOF */ diff --git a/lib/kernel32/misc/res.c b/lib/kernel32/misc/res.c new file mode 100644 index 0000000..80bbda1 --- /dev/null +++ b/lib/kernel32/misc/res.c @@ -0,0 +1,380 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT : ReactOS user mode libraries + * MODULE : kernel32.dll + * FILE : reactos/lib/kernel32/misc/res.c + * AUTHOR : ??? + */ + +#include +#include +#include +#include +#include + + +HRSRC +STDCALL +FindResourceA ( + HINSTANCE hModule, + LPCSTR lpName, + LPCSTR lpType + ) +{ + return FindResourceExA (hModule, lpType, lpName, 0); +} + +HRSRC +STDCALL +FindResourceExA( + HINSTANCE hModule, + LPCSTR lpType, + LPCSTR lpName, + WORD wLanguage + ) +{ + UNICODE_STRING TypeU; + UNICODE_STRING NameU; + ANSI_STRING Type; + ANSI_STRING Name; + HRSRC Res; + + RtlInitUnicodeString (&NameU, + NULL); + RtlInitUnicodeString (&TypeU, + NULL); + + if (HIWORD(lpName) != 0) + { + RtlInitAnsiString (&Name, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString (&NameU, + &Name, + TRUE); + } + else + NameU.Buffer = (PWSTR)lpName; + + if (HIWORD(lpType) != 0) + { + RtlInitAnsiString (&Type, + (LPSTR)lpType); + RtlAnsiStringToUnicodeString (&TypeU, + &Type, + TRUE); + } + else + TypeU.Buffer = (PWSTR)lpType; + + Res = FindResourceExW (hModule, + TypeU.Buffer, + NameU.Buffer, + wLanguage); + + if (HIWORD(lpName) != 0) + RtlFreeUnicodeString (&NameU); + + if (HIWORD(lpType) != 0) + RtlFreeUnicodeString (&TypeU); + + return Res; +} + +HRSRC +STDCALL +FindResourceW ( + HINSTANCE hModule, + LPCWSTR lpName, + LPCWSTR lpType + ) +{ + return FindResourceExW (hModule, lpType, lpName, 0); +} + +HRSRC +STDCALL +FindResourceExW ( + HINSTANCE hModule, + LPCWSTR lpType, + LPCWSTR lpName, + WORD wLanguage + ) +{ + PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry = NULL; + LDR_RESOURCE_INFO ResourceInfo; + NTSTATUS Status; + int i,l; + ULONG nType = 0, nName = 0; + + if ( hModule == NULL ) + hModule = GetModuleHandle(NULL); + + if ( HIWORD(lpName) != 0 ) { + if ( lpName[0] == L'#' ) { + l = lstrlenW(lpName) -1; + + for(i=0;iSize; +} + +WINBOOL +STDCALL +FreeResource ( + HGLOBAL hResData + ) +{ + return TRUE; +} + +LPVOID +STDCALL +LockResource ( + HGLOBAL hResData + ) +{ + return hResData; +} + +HANDLE +STDCALL +BeginUpdateResourceW ( + LPCWSTR pFileName, + WINBOOL bDeleteExistingResources + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +HANDLE +STDCALL +BeginUpdateResourceA ( + LPCSTR pFileName, + WINBOOL bDeleteExistingResources + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +EndUpdateResourceW ( + HANDLE hUpdate, + WINBOOL fDiscard + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EndUpdateResourceA ( + HANDLE hUpdate, + WINBOOL fDiscard + ) +{ + return EndUpdateResourceW( + hUpdate, + fDiscard + ); +} + +WINBOOL +STDCALL +EnumResourceLanguagesW ( + HINSTANCE hModule, + LPCWSTR lpType, + LPCWSTR lpName, + ENUMRESLANGPROC lpEnumFunc, + LONG lParam + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumResourceLanguagesA ( + HINSTANCE hModule, + LPCSTR lpType, + LPCSTR lpName, + ENUMRESLANGPROC lpEnumFunc, + LONG lParam + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumResourceNamesW ( + HINSTANCE hModule, + LPCWSTR lpType, + ENUMRESNAMEPROC lpEnumFunc, + LONG lParam + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumResourceNamesA ( + HINSTANCE hModule, + LPCSTR lpType, + ENUMRESNAMEPROC lpEnumFunc, + LONG lParam + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumResourceTypesW ( + HINSTANCE hModule, + ENUMRESTYPEPROC lpEnumFunc, + LONG lParam + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +WINBOOL +STDCALL +EnumResourceTypesA ( + HINSTANCE hModule, + ENUMRESTYPEPROC lpEnumFunc, + LONG lParam + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +UpdateResourceA ( + HANDLE hUpdate, + LPCSTR lpType, + LPCSTR lpName, + WORD wLanguage, + LPVOID lpData, + DWORD cbData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +UpdateResourceW ( + HANDLE hUpdate, + LPCWSTR lpType, + LPCWSTR lpName, + WORD wLanguage, + LPVOID lpData, + DWORD cbData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* EOF */ diff --git a/lib/kernel32/misc/stubs.c b/lib/kernel32/misc/stubs.c new file mode 100644 index 0000000..3f4b5f3 --- /dev/null +++ b/lib/kernel32/misc/stubs.c @@ -0,0 +1,1475 @@ +/* $Id$ + * + * KERNEL32.DLL stubs (unimplemented functions) + * Remove from this file, if you implement them. + */ +#include + + +BOOL +STDCALL +IsProcessorFeaturePresent( DWORD ProcessorFeature ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +BaseAttachCompleteThunk (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +BOOL +STDCALL +CmdBatNotification ( + DWORD Unknown + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +CompareStringA ( + LCID Locale, + DWORD dwCmpFlags, + LPCSTR lpString1, + int cchCount1, + LPCSTR lpString2, + int cchCount2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +CompareStringW ( + LCID Locale, + DWORD dwCmpFlags, + LPCWSTR lpString1, + int cchCount1, + LPCWSTR lpString2, + int cchCount2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +LCID +STDCALL +ConvertDefaultLocale ( + LCID Locale + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +CreateVirtualBuffer ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL +STDCALL +EnumCalendarInfoW ( + CALINFO_ENUMPROC lpCalInfoEnumProc, + LCID Locale, + CALID Calendar, + CALTYPE CalType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + +WINBOOL +STDCALL +EnumCalendarInfoA ( + CALINFO_ENUMPROC lpCalInfoEnumProc, + LCID Locale, + CALID Calendar, + CALTYPE CalType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumDateFormatsW ( + DATEFMT_ENUMPROC lpDateFmtEnumProc, + LCID Locale, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumDateFormatsA ( + DATEFMT_ENUMPROC lpDateFmtEnumProc, + LCID Locale, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + +WINBOOL +STDCALL +EnumSystemCodePagesW ( + CODEPAGE_ENUMPROC lpCodePageEnumProc, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumSystemCodePagesA ( + CODEPAGE_ENUMPROC lpCodePageEnumProc, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumSystemLocalesW ( + LOCALE_ENUMPROC lpLocaleEnumProc, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumSystemLocalesA ( + LOCALE_ENUMPROC lpLocaleEnumProc, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumTimeFormatsW ( + TIMEFMT_ENUMPROC lpTimeFmtEnumProc, + LCID Locale, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +EnumTimeFormatsA ( + TIMEFMT_ENUMPROC lpTimeFmtEnumProc, + LCID Locale, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + + + + + + +DWORD +STDCALL +ExitVDM ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + +BOOL +STDCALL +ExtendVirtualBuffer ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +FoldStringW ( + DWORD dwMapFlags, + LPCWSTR lpSrcStr, + int cchSrc, + LPWSTR lpDestStr, + int cchDest + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +FoldStringA ( + DWORD dwMapFlags, + LPCSTR lpSrcStr, + int cchSrc, + LPSTR lpDestStr, + int cchDest + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +FormatMessageW ( + DWORD dwFlags, + LPCVOID lpSource, + DWORD dwMessageId, + DWORD dwLanguageId, + LPWSTR lpBuffer, + DWORD nSize, + va_list * Arguments + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +FormatMessageA ( + DWORD dwFlags, + LPCVOID lpSource, + DWORD dwMessageId, + DWORD dwLanguageId, + LPSTR lpBuffer, + DWORD nSize, + va_list * Arguments + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +BOOL +STDCALL +FreeVirtualBuffer ( + HANDLE hVirtualBuffer + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +UINT +STDCALL +GetACP (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +WINBOOL +STDCALL +GetBinaryTypeW ( + LPCWSTR lpApplicationName, + LPDWORD lpBinaryType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +GetBinaryTypeA ( + LPCSTR lpApplicationName, + LPDWORD lpBinaryType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +GetCPInfo ( + UINT a0, + LPCPINFO a1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + +WINBOOL +STDCALL +GetComputerNameW ( + LPWSTR lpBuffer, + LPDWORD nSize + ) +{ + WCHAR Name [MAX_COMPUTERNAME_LENGTH + 1]; + DWORD Size = 0; + + /* + * FIXME: get the computer's name from + * the registry. + */ + lstrcpyW( Name, L"ROSHost" ); /* <-- FIXME -- */ + Size = lstrlenW(Name) + 1; + if (Size > *nSize) + { + *nSize = Size; + SetLastError(ERROR_BUFFER_OVERFLOW); + return FALSE; + } + lstrcpyW( lpBuffer, Name ); + return TRUE; +} + + +WINBOOL +STDCALL +GetComputerNameA ( + LPSTR lpBuffer, + LPDWORD nSize + ) +{ + WCHAR Name [MAX_COMPUTERNAME_LENGTH + 1]; + int i; + + if (FALSE == GetComputerNameW( + Name, + nSize + )) + { + return FALSE; + } +/* FIXME --> */ +/* Use UNICODE to ANSI */ + for ( i=0; Name[i]; ++i ) + { + lpBuffer[i] = (CHAR) Name[i]; + } + lpBuffer[i] = '\0'; +/* FIXME <-- */ + return TRUE; +} + + + + +int +STDCALL +GetCurrencyFormatW ( + LCID Locale, + DWORD dwFlags, + LPCWSTR lpValue, + CONST CURRENCYFMT * lpFormat, + LPWSTR lpCurrencyStr, + int cchCurrency + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetCurrencyFormatA ( + LCID Locale, + DWORD dwFlags, + LPCSTR lpValue, + CONST CURRENCYFMT * lpFormat, + LPSTR lpCurrencyStr, + int cchCurrency + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + + + +int +STDCALL +GetDateFormatW ( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME * lpDate, + LPCWSTR lpFormat, + LPWSTR lpDateStr, + int cchDate + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetDateFormatA ( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME * lpDate, + LPCSTR lpFormat, + LPSTR lpDateStr, + int cchDate + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetLocaleInfoW ( + LCID Locale, + LCTYPE LCType, + LPWSTR lpLCData, + int cchData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetLocaleInfoA ( + LCID Locale, + LCTYPE LCType, + LPSTR lpLCData, + int cchData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +GetNextVDMCommand ( + DWORD Unknown0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetNumberFormatW ( + LCID Locale, + DWORD dwFlags, + LPCWSTR lpValue, + CONST NUMBERFMT * lpFormat, + LPWSTR lpNumberStr, + int cchNumber + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetNumberFormatA ( + LCID Locale, + DWORD dwFlags, + LPCSTR lpValue, + CONST NUMBERFMT * lpFormat, + LPSTR lpNumberStr, + int cchNumber + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +UINT +STDCALL +GetOEMCP (VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 437; /* FIXME: call csrss.exe */ +} + + +WINBOOL +STDCALL +GetStringTypeExW ( + LCID Locale, + DWORD dwInfoType, + LPCWSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +GetStringTypeExA ( + LCID Locale, + DWORD dwInfoType, + LPCSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +GetStringTypeW ( + DWORD dwInfoType, + LPCWSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +GetStringTypeA ( + LCID Locale, + DWORD dwInfoType, + LPCSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +LCID +STDCALL +GetSystemDefaultLCID (VOID) +{ + /* FIXME: ??? */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MAKELCID( + LANG_ENGLISH, + SORT_DEFAULT + ); +} + + +LANGID +STDCALL +GetSystemDefaultLangID (VOID) +{ + /* FIXME: ??? */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MAKELANGID( + LANG_ENGLISH, + SUBLANG_ENGLISH_US + ); +} + + +DWORD +STDCALL +GetSystemPowerStatus ( + DWORD Unknown0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +LCID +STDCALL +GetThreadLocale (VOID) +{ + /* FIXME: ??? */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MAKELCID( + LANG_ENGLISH, + SORT_DEFAULT + ); +} + +WINBOOL +STDCALL +GetThreadPriorityBoost ( + HANDLE hThread, + DWORD dwSelector, + LPLDT_ENTRY lpSelectorEntry + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +GetThreadSelectorEntry ( + HANDLE hThread, + DWORD dwSelector, + LPLDT_ENTRY lpSelectorEntry + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +GetTimeFormatW ( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME * lpTime, + LPCWSTR lpFormat, + LPWSTR lpTimeStr, + int cchTime + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +GetTimeFormatA ( + LCID Locale, + DWORD dwFlags, + CONST SYSTEMTIME * lpTime, + LPCSTR lpFormat, + LPSTR lpTimeStr, + int cchTime + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +LCID +STDCALL +GetUserDefaultLCID (VOID) +{ + /* FIXME: ??? */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MAKELCID( + LANG_ENGLISH, + SORT_DEFAULT + ); +} + + +LANGID +STDCALL +GetUserDefaultLangID (VOID) +{ + /* FIXME: ??? */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return MAKELANGID( + LANG_ENGLISH, + SUBLANG_ENGLISH_US + ); +} + + +DWORD +STDCALL +GetVDMCurrentDirectories ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL +STDCALL +IsDBCSLeadByte ( + BYTE TestChar + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +IsDBCSLeadByteEx ( + UINT CodePage, + BYTE TestChar + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/********************************************************************** + * NAME PRIVATE + * IsInstalledCP@4 + * + * RETURN VALUE + * TRUE if CodePage is installed in the system. + */ +static +BOOL +STDCALL +IsInstalledCP ( + UINT CodePage + ) +{ + /* FIXME */ + return TRUE; +} + + +WINBOOL +STDCALL +IsValidCodePage ( + UINT CodePage + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +IsValidLocale ( + LCID Locale, + DWORD dwFlags + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +int +STDCALL +LCMapStringA ( + LCID Locale, + DWORD dwMapFlags, + LPCSTR lpSrcStr, + int cchSrc, + LPSTR lpDestStr, + int cchDest + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +int +STDCALL +LCMapStringW ( + LCID Locale, + DWORD dwMapFlags, + LPCWSTR lpSrcStr, + int cchSrc, + LPWSTR lpDestStr, + int cchDest + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +LoadModule ( + LPCSTR lpModuleName, + LPVOID lpParameterBlock + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/*********************************************************************** + * MulDiv (KERNEL32.@) + * RETURNS + * Result of multiplication and division + * -1: Overflow occurred or Divisor was 0 + */ + +//FIXME! move to correct file +INT STDCALL MulDiv( + INT nMultiplicand, + INT nMultiplier, + INT nDivisor) +{ +#if SIZEOF_LONG_LONG >= 8 + long long ret; + + if (!nDivisor) return -1; + + /* We want to deal with a positive divisor to simplify the logic. */ + if (nDivisor < 0) + { + nMultiplicand = - nMultiplicand; + nDivisor = -nDivisor; + } + + /* If the result is positive, we "add" to round. else, we subtract to round. */ + if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || + ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) + ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + else + ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + + if ((ret > 2147483647) || (ret < -2147483647)) return -1; + return ret; +#else + if (!nDivisor) return -1; + + /* We want to deal with a positive divisor to simplify the logic. */ + if (nDivisor < 0) + { + nMultiplicand = - nMultiplicand; + nDivisor = -nDivisor; + } + + /* If the result is positive, we "add" to round. else, we subtract to round. */ + if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || + ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) + return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + + return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + +#endif +} + + +/********************************************************************** + * NAME EXPORTED + * MultiByteToWideChar@24 + * + * ARGUMENTS + * CodePage + * CP_ACP ANSI code page + * CP_MACCP Macintosh code page + * CP_OEMCP OEM code page + * (UINT) Any installed code page + * + * dwFlags + * MB_PRECOMPOSED + * MB_COMPOSITE + * MB_ERR_INVALID_CHARS + * MB_USEGLYPHCHARS + * + * lpMultiByteStr + * Input buffer; + * + * cchMultiByte + * Size of MultiByteStr, or -1 if MultiByteStr is + * NULL terminated; + * + * lpWideCharStr + * Output buffer; + * + * cchWideChar + * Size (in WCHAR unit) of WideCharStr, or 0 + * if the caller just wants to know how large + * WideCharStr should be for a successful + * conversion. + * + * RETURN VALUE + * 0 on error; otherwise the number of WCHAR written + * in the WideCharStr buffer. + * + * NOTE + * A raw converter for now. It assumes lpMultiByteStr is + * NEVER multi-byte (that is each input character is + * 8-bit ASCII) and is ALWAYS NULL terminated. + * FIXME-FIXME-FIXME-FIXME + */ +INT +STDCALL +MultiByteToWideChar ( + UINT CodePage, + DWORD dwFlags, + LPCSTR lpMultiByteStr, + int cchMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar + ) +{ + int InStringLength = 0; + PCHAR r; + PWCHAR w; + int cchConverted; + + /* + * Check the parameters. + */ + if ( /* --- CODE PAGE --- */ + ( (CP_ACP != CodePage) + && (CP_MACCP != CodePage) + && (CP_OEMCP != CodePage) + && (FALSE == IsInstalledCP (CodePage)) + ) + /* --- FLAGS --- */ + || (dwFlags & ~(MB_PRECOMPOSED + | MB_COMPOSITE + | MB_ERR_INVALID_CHARS + | MB_USEGLYPHCHARS + ) + ) + /* --- INPUT BUFFER --- */ + || (NULL == lpMultiByteStr) + ) + { + SetLastError (ERROR_INVALID_PARAMETER); + return 0; + } + /* + * Compute the input buffer length. + */ + if (-1 == cchMultiByte) + { + InStringLength = lstrlen (lpMultiByteStr) + 1; + } + else + { + InStringLength = cchMultiByte; + } + /* + * Does caller query for output + * buffer size? + */ + if (0 == cchWideChar) + { + SetLastError (ERROR_SUCCESS); + return InStringLength; + } + /* + * Is space provided for the translated + * string enough? + */ + if (cchWideChar < InStringLength) + { + SetLastError (ERROR_INSUFFICIENT_BUFFER); + return 0; + } + /* + * Raw 8- to 16-bit conversion. + */ + for ( cchConverted = 0, + r = (PCHAR) lpMultiByteStr, + w = (PWCHAR) lpWideCharStr; + + cchConverted < InStringLength; + + r++, + w++, + cchConverted++ + ) + { + *w = (WCHAR) *r; + } + /* + * Return how many characters we + * wrote in the output buffer. + */ + SetLastError (ERROR_SUCCESS); + return cchConverted; +} + + +WINBOOL +STDCALL +QueryPerformanceCounter ( + LARGE_INTEGER * lpPerformanceCount + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +QueryPerformanceFrequency ( + LARGE_INTEGER * lpFrequency + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +RegisterConsoleVDM ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +RegisterWowBaseHandlers ( + DWORD Unknown0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +RegisterWowExec ( + DWORD Unknown0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +SetComputerNameA ( + LPCSTR lpComputerName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +SetComputerNameW ( + LPCWSTR lpComputerName + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +SetLocaleInfoA ( + LCID Locale, + LCTYPE LCType, + LPCSTR lpLCData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +SetLocaleInfoW ( + LCID Locale, + LCTYPE LCType, + LPCWSTR lpLCData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +SetSystemPowerState ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +SetThreadIdealProcessor(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +WINBOOL +STDCALL +SetThreadLocale ( + LCID Locale + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL +STDCALL +SetThreadPriorityBoost(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +WINBOOL +STDCALL +SetVDMCurrentDirectories ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +TrimVirtualBuffer ( + DWORD Unknown0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VDMConsoleOperation ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VDMOperationStarted ( + DWORD Unknown0 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerLanguageNameA ( + DWORD wLang, + LPSTR szLang, + DWORD nSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerLanguageNameW ( + DWORD wLang, + LPWSTR szLang, + DWORD nSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VirtualBufferExceptionHandler ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/********************************************************************** + * NAME EXPORTED + * MultiByteToWideChar@32 + * + * Not yet implemented complete (without NLS so far) + * + * ARGUMENTS + * CodePage + * CP_ACP ANSI code page + * CP_MACCP Macintosh code page + * CP_OEMCP OEM code page + * CP_SYMBOL Symbol code page (42) + * CP_THREAD_ACP Current thread's ANSI code page + * CP_UTF7 Translate using UTF-7 + * CP_UTF8 Translate using UTF-8 + * (UINT) Any installed code page + * + * dwFlags + * WC_NO_BEST_FIT_CHARS + * WC_COMPOSITECHECK Convert composite characters to precomposed characters. + * WC_DISCARDNS Discard nonspacing characters during conversion. + * WC_SEPCHARS Generate separate characters during conversion. This is the default conversion behavior. + * WC_DEFAULTCHAR Replace exceptions with the default character during conversion. + * + * lpWideCharStr + * Points to the wide-character string to be converted. + * + * cchWideChar + * Size (in WCHAR unit) of WideCharStr, or 0 + * if the caller just wants to know how large + * WideCharStr should be for a successful + * conversion. + * lpMultiByteStr + * Points to the buffer to receive the translated string. + * cchMultiByte + * Specifies the size in bytes of the buffer pointed to by the + * lpMultiByteStr parameter. If this value is zero, the function + * returns the number of bytes required for the buffer. + * lpDefaultChar + * Points to the character used if a wide character cannot be + * represented in the specified code page. If this parameter is + * NULL, a system default value is used. + FIXME: ignored + * lpUsedDefaultChar + * Points to a flag that indicates whether a default character was used. + * This parameter may be NULL. + FIXME: allways set to FALSE. + * + * + * + * RETURN VALUE + * 0 on error; otherwise the number of bytes written + * in the lpMultiByteStr buffer. Or the number of + * bytes needed for the lpMultiByteStr buffer if cchMultiByte is zero. + * + * NOTE + * A raw converter for now. It just cuts off the upper 9 Bit. + * So the MBCS-string does not contain any LeadCharacters + * FIXME - FIXME - FIXME - FIXME + */ + +int +STDCALL +WideCharToMultiByte ( + UINT CodePage, + DWORD dwFlags, + LPCWSTR lpWideCharStr, + int cchWideChar, + LPSTR lpMultiByteStr, + int cchMultiByte, + LPCSTR lpDefaultChar, + LPBOOL lpUsedDefaultChar + ) +{ + int wi, di; // wide counter, dbcs byte count + + /* + * Check the parameters. + */ + if ( /* --- CODE PAGE --- */ + ( (CP_ACP != CodePage) + && (CP_MACCP != CodePage) + && (CP_OEMCP != CodePage) + && (CP_SYMBOL != CodePage) + && (CP_THREAD_ACP != CodePage) + && (CP_UTF7 != CodePage) + && (CP_UTF8 != CodePage) + && (FALSE == IsInstalledCP (CodePage)) + ) + /* --- FLAGS --- */ + || (dwFlags & ~(/*WC_NO_BEST_FIT_CHARS + |*/ WC_COMPOSITECHECK + | WC_DISCARDNS + | WC_SEPCHARS + | WC_DEFAULTCHAR + ) + ) + /* --- INPUT BUFFER --- */ + || (NULL == lpWideCharStr) + ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + // for now, make no difference but only convert cut the characters to 7Bit + if( cchWideChar == -1 ) // assume its a 0-terminated str + { // and determine its length + for( cchWideChar=0; lpWideCharStr[cchWideChar]!=0; cchWideChar++) + cchWideChar++; + } + + // user wants to determine needed space + if( cchMultiByte == 0 ) + { + SetLastError(ERROR_SUCCESS); + return cchWideChar; // FIXME: determine correct. + } + // the lpWideCharStr is cchWideChar characters long. + for( wi=0, di=0; wi127) ) + { + lpMultiByteStr[di]= + *lpUsedDefaultChar = TRUE; + + }*/ + // FIXME + // just cut off the upper 9 Bit, since vals>=128 mean LeadByte. + lpMultiByteStr[di] = lpWideCharStr[wi] & 0x007F; + } + // has MultiByte exceeded but Wide is still in the string? + if( wi < cchWideChar && di >= cchMultiByte) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + // else return # of bytes wirtten to MBCSbuffer (di) + SetLastError(ERROR_SUCCESS); + // FIXME: move that elsewhere + if( lpUsedDefaultChar!=NULL ) *lpUsedDefaultChar=FALSE; + return di; +} + + + + + + + + + + + +/* EOF */ diff --git a/lib/kernel32/misc/sysinfo.c b/lib/kernel32/misc/sysinfo.c new file mode 100644 index 0000000..8efbb06 --- /dev/null +++ b/lib/kernel32/misc/sysinfo.c @@ -0,0 +1,126 @@ +/* $Id$ + * + * reactos/lib/kernel32/misc/sysinfo.c + * + */ +#include + +#include +#include + +#define WIN32_LEAN_AND_MEAN +#include + + +#define PV_NT351 0x00030033 + +VOID +STDCALL +GetSystemInfo ( + LPSYSTEM_INFO Si + ) +{ + SYSTEM_BASIC_INFORMATION Sbi; + SYSTEM_PROCESSOR_INFORMATION Spi; + DWORD ProcessVersion; + NTSTATUS Status; + + RtlZeroMemory (Si, sizeof (SYSTEM_INFO)); + Status = NtQuerySystemInformation ( + SystemBasicInformation, /* 0 */ + & Sbi, + sizeof Sbi, /* 44 */ + 0 + ); + if (STATUS_SUCCESS != Status) + { + SetLastErrorByStatus (Status); + return; + } + Status = NtQuerySystemInformation ( + SystemProcessorInformation, /* 1 */ + & Spi, + sizeof Spi, /* 12 */ + 0 + ); + if (STATUS_SUCCESS != Status) + { + SetLastErrorByStatus (Status); + return; + } + /* + * PROCESSOR_ARCHITECTURE_INTEL 0 + * PROCESSOR_ARCHITECTURE_MIPS 1 + * PROCESSOR_ARCHITECTURE_ALPHA 2 + * PROCESSOR_ARCHITECTURE_PPC 3 + * PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF + */ + Si->u.s.wProcessorArchitecture = Spi.ProcessorArchitecture; + /* For future use: always zero */ + Si->u.s.wReserved = 0; + Si->dwPageSize = Sbi.PageSize; + Si->lpMinimumApplicationAddress = (PVOID)Sbi.MinimumUserModeAddress; + Si->lpMaximumApplicationAddress = (PVOID)Sbi.MaximumUserModeAddress; + Si->dwActiveProcessorMask = Sbi.ActiveProcessorsAffinityMask; + Si->dwNumberOfProcessors = Sbi.NumberOfProcessors; + /* + * Compatibility (no longer relevant): + * PROCESSOR_INTEL_386 386 + * PROCESSOR_INTEL_486 486 + * PROCESSOR_INTEL_PENTIUM 586 + * PROCESSOR_MIPS_R4000 4000 + * PROCESSOR_ALPHA_21064 21064 + */ + switch (Spi.ProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + switch (Spi.ProcessorLevel) + { + case 3: + Si->dwProcessorType = PROCESSOR_INTEL_386; + break; + case 4: + Si->dwProcessorType = PROCESSOR_INTEL_486; + break; + case 5: + Si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; + break; + default: + /* FIXME: P2, P3, P4...? */ + Si->dwProcessorType = PROCESSOR_INTEL_PENTIUM; + } + break; + + case PROCESSOR_ARCHITECTURE_MIPS: + Si->dwProcessorType = PROCESSOR_MIPS_R4000; + break; + + case PROCESSOR_ARCHITECTURE_ALPHA: + Si->dwProcessorType = PROCESSOR_ALPHA_21064; + break; + + case PROCESSOR_ARCHITECTURE_PPC: + Si->dwProcessorType = -1; /* FIXME: what value? */ + break; + + } + /* Once hardcoded to 64kb */ + Si->dwAllocationGranularity = Sbi.AllocationGranularity; + /* */ + Si->wProcessorLevel = Spi.ProcessorLevel; + Si->wProcessorRevision = Spi.ProcessorRevision; + /* + * Get the version of Windows on which + * the process expects to run. + */ + ProcessVersion = GetProcessVersion (0); /* current process */ + /* In NT 3.1 and 3.5 these fields were always zero. */ + if (PV_NT351 > ProcessVersion) + { + Si->wProcessorLevel = 0; + Si->wProcessorRevision = 0; + } +} + + +/* EOF */ diff --git a/lib/kernel32/misc/time.c b/lib/kernel32/misc/time.c new file mode 100644 index 0000000..0d2dc57 --- /dev/null +++ b/lib/kernel32/misc/time.c @@ -0,0 +1,429 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/misc/time.c + * PURPOSE: Time conversion functions + * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) + * DOSDATE and DOSTIME structures from Onno Hovers + * UPDATE HISTORY: + * Created 19/01/99 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +//#include + +#define NDEBUG +#include + +/* TYPES *********************************************************************/ + +typedef struct __DOSTIME +{ + WORD Second:5; + WORD Minute:6; + WORD Hour:5; +} DOSTIME, *PDOSTIME; + +typedef struct __DOSDATE +{ + WORD Day:5; + WORD Month:4; + WORD Year:5; +} DOSDATE, *PDOSDATE; + +#define TICKSPERMIN 600000000 + +/* FUNCTIONS ****************************************************************/ + +WINBOOL +STDCALL +FileTimeToDosDateTime( + CONST FILETIME *lpFileTime, + LPWORD lpFatDate, + LPWORD lpFatTime + ) +{ + PDOSTIME pdtime=(PDOSTIME) lpFatTime; + PDOSDATE pddate=(PDOSDATE) lpFatDate; + SYSTEMTIME SystemTime; + + if ( lpFileTime == NULL ) + return FALSE; + + if ( lpFatDate == NULL ) + return FALSE; + + if ( lpFatTime == NULL ) + return FALSE; + + FileTimeToSystemTime( + lpFileTime, + &SystemTime + ); + + pdtime->Second = SystemTime.wSecond; + pdtime->Minute = SystemTime.wMinute; + pdtime->Hour = SystemTime.wHour; + + pddate->Day = SystemTime.wDay; + pddate->Month = SystemTime.wMonth; + pddate->Year = SystemTime.wYear - 1980; + + return TRUE; +} + +WINBOOL +STDCALL +DosDateTimeToFileTime( + WORD wFatDate, + WORD wFatTime, + LPFILETIME lpFileTime + ) +{ + PDOSTIME pdtime = (PDOSTIME) &wFatTime; + PDOSDATE pddate = (PDOSDATE) &wFatDate; + SYSTEMTIME SystemTime; + + if ( lpFileTime == NULL ) + return FALSE; + + SystemTime.wMilliseconds = 0; + SystemTime.wSecond = pdtime->Second; + SystemTime.wMinute = pdtime->Minute; + SystemTime.wHour = pdtime->Hour; + + SystemTime.wDay = pddate->Day; + SystemTime.wMonth = pddate->Month; + SystemTime.wYear = 1980 + pddate->Year; + + SystemTimeToFileTime(&SystemTime,lpFileTime); + + return TRUE; +} + +LONG +STDCALL +CompareFileTime( + CONST FILETIME *lpFileTime1, + CONST FILETIME *lpFileTime2 + ) +{ + if ( lpFileTime1 == NULL ) + return 0; + if ( lpFileTime2 == NULL ) + return 0; + + if (*((PLONGLONG)lpFileTime1) > *((PLONGLONG)lpFileTime2)) + return 1; + else if (*((PLONGLONG)lpFileTime1) < *((PLONGLONG)lpFileTime2)) + return -1; + + return 0; +} + +VOID +STDCALL +GetSystemTimeAsFileTime(PFILETIME lpFileTime) +{ + NtQuerySystemTime ((TIME *)lpFileTime); +} + +WINBOOL +STDCALL +SystemTimeToFileTime( + CONST SYSTEMTIME * lpSystemTime, + LPFILETIME lpFileTime + ) + +{ + TIME_FIELDS TimeFields; + LARGE_INTEGER liTime; + + TimeFields.Year = lpSystemTime->wYear; + TimeFields.Month = lpSystemTime->wMonth; + TimeFields.Day = lpSystemTime->wDay; + TimeFields.Hour = lpSystemTime->wHour; + TimeFields.Minute = lpSystemTime->wMinute; + TimeFields.Second = lpSystemTime->wSecond; + TimeFields.Milliseconds = lpSystemTime->wMilliseconds; + + if (RtlTimeFieldsToTime (&TimeFields, &liTime)) + { + lpFileTime->dwLowDateTime = liTime.u.LowPart; + lpFileTime->dwHighDateTime = liTime.u.HighPart; + return TRUE; + } + return FALSE; +} + +// dwDayOfWeek = RtlLargeIntegerDivide(FileTime,LIDAY,&dwRemDay); +// lpSystemTime->wDayOfWeek = 1 + GET_LARGE_INTEGER_LOW_PART(dwDayOfWeek) % 7; + + + +WINBOOL +STDCALL +FileTimeToSystemTime( + CONST FILETIME *lpFileTime, + LPSYSTEMTIME lpSystemTime + ) +{ + TIME_FIELDS TimeFields; + LARGE_INTEGER liTime; + + liTime.u.LowPart = lpFileTime->dwLowDateTime; + liTime.u.HighPart = lpFileTime->dwHighDateTime; + + if (liTime.u.HighPart >= 0x80000000) + { + return FALSE; + } + + RtlTimeToTimeFields(&liTime, &TimeFields); + + lpSystemTime->wYear = TimeFields.Year; + lpSystemTime->wMonth = TimeFields.Month; + lpSystemTime->wDay = TimeFields.Day; + lpSystemTime->wHour = TimeFields.Hour; + lpSystemTime->wMinute = TimeFields.Minute; + lpSystemTime->wSecond = TimeFields.Second; + lpSystemTime->wMilliseconds = TimeFields.Milliseconds; + lpSystemTime->wDayOfWeek = TimeFields.Weekday; + + return TRUE; +} + + +WINBOOL +STDCALL +FileTimeToLocalFileTime( + CONST FILETIME *lpFileTime, + LPFILETIME lpLocalFileTime + ) +{ + // FIXME: include time bias + *((PLONGLONG)lpLocalFileTime) = *((PLONGLONG)lpFileTime); + + return TRUE; +} + +WINBOOL +STDCALL +LocalFileTimeToFileTime( + CONST FILETIME *lpLocalFileTime, + LPFILETIME lpFileTime + ) +{ + // FIXME: include time bias + *((PLONGLONG)lpFileTime) = *((PLONGLONG)lpLocalFileTime); + + return TRUE; +} + + +VOID STDCALL +GetLocalTime(LPSYSTEMTIME lpSystemTime) +{ + FILETIME FileTime; + FILETIME LocalFileTime; + + NtQuerySystemTime ((TIME*)&FileTime); + FileTimeToLocalFileTime (&FileTime, &LocalFileTime); + FileTimeToSystemTime (&LocalFileTime, lpSystemTime); +} + + +VOID STDCALL +GetSystemTime(LPSYSTEMTIME lpSystemTime) +{ + FILETIME FileTime; + + NtQuerySystemTime ((TIME*)&FileTime); + FileTimeToSystemTime (&FileTime, lpSystemTime); +} + + +WINBOOL STDCALL +SetLocalTime(CONST SYSTEMTIME *lpSystemTime) +{ + FILETIME LocalFileTime; + LARGE_INTEGER FileTime; + NTSTATUS errCode; + + SystemTimeToFileTime (lpSystemTime, &LocalFileTime); + LocalFileTimeToFileTime (&LocalFileTime, (FILETIME *)&FileTime); + errCode = NtSetSystemTime (&FileTime, &FileTime); + if (!NT_SUCCESS(errCode)) + return FALSE; + return TRUE; +} + + +WINBOOL STDCALL +SetSystemTime(CONST SYSTEMTIME *lpSystemTime) +{ + LARGE_INTEGER NewSystemTime; + NTSTATUS errCode; + + SystemTimeToFileTime (lpSystemTime, (PFILETIME)&NewSystemTime); + errCode = NtSetSystemTime (&NewSystemTime, &NewSystemTime); + if (!NT_SUCCESS(errCode)) + return FALSE; + return TRUE; +} + + +DWORD STDCALL +GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) +{ + TIME_ZONE_INFORMATION TimeZoneInformation; + NTSTATUS Status; + + DPRINT("GetTimeZoneInformation()\n"); + + Status = NtQuerySystemInformation(SystemCurrentTimeZoneInformation, + &TimeZoneInformation, + sizeof(TIME_ZONE_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return TIME_ZONE_ID_INVALID; + } + + memcpy(lpTimeZoneInformation, + &TimeZoneInformation, + sizeof(TIME_ZONE_INFORMATION)); + + return(SharedUserData->TimeZoneId); +} + + +BOOL STDCALL +SetTimeZoneInformation(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation) +{ + TIME_ZONE_INFORMATION TimeZoneInformation; + NTSTATUS Status; + + DPRINT("SetTimeZoneInformation()\n"); + + memcpy(&TimeZoneInformation, + lpTimeZoneInformation, + sizeof(TIME_ZONE_INFORMATION)); + + Status = RtlSetTimeZoneInformation(&TimeZoneInformation); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + NtSetSystemTime(0,0); + + return TRUE; +} + + +DWORD STDCALL +GetCurrentTime(VOID) +{ + return GetTickCount(); +} + + +DWORD STDCALL +GetTickCount(VOID) +{ + ULONG UpTime; + NtGetTickCount(&UpTime); + return UpTime; +} + + +WINBOOL STDCALL +SystemTimeToTzSpecificLocalTime( + LPTIME_ZONE_INFORMATION lpTimeZoneInformation, + LPSYSTEMTIME lpUniversalTime, + LPSYSTEMTIME lpLocalTime + ) +{ + TIME_ZONE_INFORMATION TimeZoneInformation; + LPTIME_ZONE_INFORMATION lpTzInfo; + LARGE_INTEGER FileTime; + + if (!lpTimeZoneInformation) + { + GetTimeZoneInformation (&TimeZoneInformation); + lpTzInfo = &TimeZoneInformation; + } + else + lpTzInfo = lpTimeZoneInformation; + + if (!lpUniversalTime) + return FALSE; + + if (!lpLocalTime) + return FALSE; + + SystemTimeToFileTime (lpUniversalTime, (PFILETIME)&FileTime); + FileTime.QuadPart -= (lpTzInfo->Bias * TICKSPERMIN); + FileTimeToSystemTime ((PFILETIME)&FileTime, lpLocalTime); + + return TRUE; +} + + +WINBOOL STDCALL +GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, + PDWORD lpTimeIncrement, + PWINBOOL lpTimeAdjustmentDisabled) +{ + SYSTEM_QUERY_TIME_ADJUSTMENT Buffer; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemTimeAdjustmentInformation, + &Buffer, + sizeof(SYSTEM_QUERY_TIME_ADJUSTMENT), + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + *lpTimeAdjustment = (DWORD)Buffer.TimeAdjustment; + *lpTimeIncrement = (DWORD)Buffer.MaximumIncrement; + *lpTimeAdjustmentDisabled = (WINBOOL)Buffer.TimeSynchronization; + + return TRUE; +} + + +WINBOOL STDCALL +SetSystemTimeAdjustment(DWORD dwTimeAdjustment, + WINBOOL bTimeAdjustmentDisabled) +{ + NTSTATUS Status; + SYSTEM_TIME_ADJUSTMENT_INFO Buffer; + + Buffer.TimeAdjustment = (ULONG)dwTimeAdjustment; + Buffer.TimeSynchronization = (BOOLEAN)bTimeAdjustmentDisabled; + + Status = NtSetSystemInformation(SystemTimeAdjustmentInformation, + &Buffer, + sizeof(SYSTEM_TIME_ADJUSTMENT_INFO)); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/nls/.cvsignore b/lib/kernel32/nls/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/nls/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/nls/LGPL.c b/lib/kernel32/nls/LGPL.c new file mode 100644 index 0000000..46bb73a --- /dev/null +++ b/lib/kernel32/nls/LGPL.c @@ -0,0 +1,17 @@ +/* + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; see the file COPYING.LIB. If + * not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. + */ + \ No newline at end of file diff --git a/lib/kernel32/nls/afk.nls b/lib/kernel32/nls/afk.nls new file mode 100644 index 0000000..4af720f --- /dev/null +++ b/lib/kernel32/nls/afk.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Afrikaans (South Africa) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0436") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Afrikaans") +LOCVAL(LOCALE_SABBREVLANGNAME,"afk") +LOCVAL(LOCALE_SNATIVELANGNAME,"Afrikaans") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"South Africa") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ZAF") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Suid Afrika") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0436") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"ZAR") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE,"1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Maandag") +LOCVAL(LOCALE_SDAYNAME2,"Dinsdag") +LOCVAL(LOCALE_SDAYNAME3,"Woensdag") +LOCVAL(LOCALE_SDAYNAME4,"Donderdag") +LOCVAL(LOCALE_SDAYNAME5,"Vrydag") +LOCVAL(LOCALE_SDAYNAME6,"Saterdag") +LOCVAL(LOCALE_SDAYNAME7,"Sondag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Maan") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Dins") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Woen") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Dond") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Vry") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Son") + +LOCVAL(LOCALE_SMONTHNAME1,"Januarie") +LOCVAL(LOCALE_SMONTHNAME2,"Februarie") +LOCVAL(LOCALE_SMONTHNAME3,"Maart") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mei") +LOCVAL(LOCALE_SMONTHNAME6,"Junie") +LOCVAL(LOCALE_SMONTHNAME7,"Julie") +LOCVAL(LOCALE_SMONTHNAME8,"Augustus") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Desember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"af") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ZA") + diff --git a/lib/kernel32/nls/ara.nls b/lib/kernel32/nls/ara.nls new file mode 100644 index 0000000..54eea0f --- /dev/null +++ b/lib/kernel32/nls/ara.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Saudi Arabia) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0401") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Saudi Arabia)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ara") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Saudi Arabia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SAU") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SA") diff --git a/lib/kernel32/nls/arb.nls b/lib/kernel32/nls/arb.nls new file mode 100644 index 0000000..9bb29bf --- /dev/null +++ b/lib/kernel32/nls/arb.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Lebanon) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"3001") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Lebanon)") +LOCVAL(LOCALE_SABBREVLANGNAME,"arl") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Lebanon") +LOCVAL(LOCALE_SABBREVCTRYNAME, "LBN") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"LB") diff --git a/lib/kernel32/nls/are.nls b/lib/kernel32/nls/are.nls new file mode 100644 index 0000000..82712bd --- /dev/null +++ b/lib/kernel32/nls/are.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Egypt) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c01") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Egypt)") +LOCVAL(LOCALE_SABBREVLANGNAME,"are") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Egypt") +LOCVAL(LOCALE_SABBREVCTRYNAME,"EGY") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"Ì") +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING,"3") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"EG") diff --git a/lib/kernel32/nls/arg.nls b/lib/kernel32/nls/arg.nls new file mode 100644 index 0000000..3b6d1c4 --- /dev/null +++ b/lib/kernel32/nls/arg.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Algeria) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"1401") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Algeria)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ars") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Algeria") +LOCVAL(LOCALE_SABBREVCTRYNAME,"DZA") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"DZ") diff --git a/lib/kernel32/nls/ari.nls b/lib/kernel32/nls/ari.nls new file mode 100644 index 0000000..317f3bb --- /dev/null +++ b/lib/kernel32/nls/ari.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Iraq) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0801") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Iraq)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ari") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Iraq") +LOCVAL(LOCALE_SABBREVCTRYNAME,"IRQ") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL, "IQD") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"IQ") diff --git a/lib/kernel32/nls/ark.nls b/lib/kernel32/nls/ark.nls new file mode 100644 index 0000000..a188784 --- /dev/null +++ b/lib/kernel32/nls/ark.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Kuwait) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"3401") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Kuwait)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ark") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Kuwait") +LOCVAL(LOCALE_SABBREVCTRYNAME,"KWT") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"KWD") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"KW") diff --git a/lib/kernel32/nls/arm.nls b/lib/kernel32/nls/arm.nls new file mode 100644 index 0000000..a79268f --- /dev/null +++ b/lib/kernel32/nls/arm.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Marocco) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"1801") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Marocco)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ars") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Marocco") +LOCVAL(LOCALE_SABBREVCTRYNAME,"MAR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"MA") diff --git a/lib/kernel32/nls/aro.nls b/lib/kernel32/nls/aro.nls new file mode 100644 index 0000000..6115283 --- /dev/null +++ b/lib/kernel32/nls/aro.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Oman) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"2001") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Oman)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ars") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Oman") +LOCVAL(LOCALE_SABBREVCTRYNAME,"OMN") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"OM") diff --git a/lib/kernel32/nls/arq.nls b/lib/kernel32/nls/arq.nls new file mode 100644 index 0000000..8205feb --- /dev/null +++ b/lib/kernel32/nls/arq.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Quatar) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"4001") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Quatar)") +LOCVAL(LOCALE_SABBREVLANGNAME,"arq") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Quatar") +LOCVAL(LOCALE_SABBREVCTRYNAME,"QAT") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"QAR") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"QT") diff --git a/lib/kernel32/nls/ars.nls b/lib/kernel32/nls/ars.nls new file mode 100644 index 0000000..d3e33f5 --- /dev/null +++ b/lib/kernel32/nls/ars.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Syria) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"2801") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Syria)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ars") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Syria") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SYR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SY") diff --git a/lib/kernel32/nls/art.nls b/lib/kernel32/nls/art.nls new file mode 100644 index 0000000..b1f8c16 --- /dev/null +++ b/lib/kernel32/nls/art.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (Tunisia) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"1c01") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (Tunisia)") +LOCVAL(LOCALE_SABBREVLANGNAME,"art") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Tunisia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"TUN") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"TN") diff --git a/lib/kernel32/nls/aru.nls b/lib/kernel32/nls/aru.nls new file mode 100644 index 0000000..2a9373b --- /dev/null +++ b/lib/kernel32/nls/aru.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Arabic (UAE) + * + * (arabic strings in iso-8859-6) + */ + +LOCVAL(LOCALE_ILANGUAGE,"3801") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Arabic (United Arab Emirates)") +LOCVAL(LOCALE_SABBREVLANGNAME,"aru") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"United Arab Emirates") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ARE") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0401") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1256") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"AED") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE, "yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE, "å yyyy MMMM¬ dd dddd") +LOCVAL(LOCALE_STIMEFORMAT, "tt h:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "Õ") +LOCVAL(LOCALE_S2359, "å") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÇäÃËæêæ") +LOCVAL(LOCALE_SDAYNAME2,"ÇäËäÇËÇÁ") +LOCVAL(LOCALE_SDAYNAME3,"ÇäÃÑÈÙÇÁ") +LOCVAL(LOCALE_SDAYNAME4,"ÇäÎåêÓ") +LOCVAL(LOCALE_SDAYNAME5,"ÇäÌåÙç") +LOCVAL(LOCALE_SDAYNAME6,"ÇäÓÈÊ") +LOCVAL(LOCALE_SDAYNAME7,"ÇäÃÍÏ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"æ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ë") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ñ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Î") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ì") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ó") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Í") + +LOCVAL(LOCALE_SMONTHNAME1,"êæÇêÑ") +LOCVAL(LOCALE_SMONTHNAME2,"áÈÑÇêÑ") +LOCVAL(LOCALE_SMONTHNAME3,"åÇÑÓ") +LOCVAL(LOCALE_SMONTHNAME4,"ÅÈÑêä") +LOCVAL(LOCALE_SMONTHNAME5,"åÇêè") +LOCVAL(LOCALE_SMONTHNAME6,"êèæêç") +LOCVAL(LOCALE_SMONTHNAME7,"êèäêç") +LOCVAL(LOCALE_SMONTHNAME8,"ÃÚÓ×Ó") +LOCVAL(LOCALE_SMONTHNAME9,"ÓÈÊåÈÑ") +LOCVAL(LOCALE_SMONTHNAME10,"ÃãÊèÈÑ") +LOCVAL(LOCALE_SMONTHNAME11,"æèáåÈÑ") +LOCVAL(LOCALE_SMONTHNAME12,"ÏêÓåÈÑ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"êæÇ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"áÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"åÇÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"ÅÈÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"åÇê") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"êèæ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"êèä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ÃÚÓ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ÓÈå") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ÃãÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"æèá") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ÏêÓ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ar") +LOCVAL(LOCALE_SISO3166CTRYNAME,"AE") diff --git a/lib/kernel32/nls/bel.nls b/lib/kernel32/nls/bel.nls new file mode 100644 index 0000000..208444c --- /dev/null +++ b/lib/kernel32/nls/bel.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Belarusian + */ + +LOCVAL(LOCALE_ILANGUAGE,"0423") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Belarussian") +LOCVAL(LOCALE_SABBREVLANGNAME,"bel") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Belaruss") +LOCVAL(LOCALE_SABBREVCTRYNAME,"BLR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0423") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1251") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +/* LOCVAL(LOCALE_SINTLSYMBOL) */ +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"be") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BY") + diff --git a/lib/kernel32/nls/bgr.nls b/lib/kernel32/nls/bgr.nls new file mode 100644 index 0000000..ceec18d --- /dev/null +++ b/lib/kernel32/nls/bgr.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Bulgaria + */ + +LOCVAL(LOCALE_ILANGUAGE,"0402") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Bulgarian") +LOCVAL(LOCALE_SABBREVLANGNAME,"bgr") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Bulgaria") +LOCVAL(LOCALE_SABBREVCTRYNAME,"BGR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0402") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL, "BGL") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"bg") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BG") diff --git a/lib/kernel32/nls/cat.nls b/lib/kernel32/nls/cat.nls new file mode 100644 index 0000000..ab59b24 --- /dev/null +++ b/lib/kernel32/nls/cat.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Catalan + */ + +LOCVAL(LOCALE_ILANGUAGE,"0403") +LOCVAL(LOCALE_SLANGUAGE,"Català") +LOCVAL(LOCALE_SENGLANGUAGE,"Catalan") +LOCVAL(LOCALE_SABBREVLANGNAME,"cat") +LOCVAL(LOCALE_SNATIVELANGNAME,"català") +LOCVAL(LOCALE_ICOUNTRY,"34") +LOCVAL(LOCALE_SCOUNTRY,"Espanya") +LOCVAL(LOCALE_SENGCOUNTRY,"Spain") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ESP") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Espanya") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0403") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,"") +LOCVAL(LOCALE_SGROUPING,"0;0") +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Pts") +LOCVAL(LOCALE_SINTLSYMBOL, "ESP") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd d MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Dilluns") +LOCVAL(LOCALE_SDAYNAME2,"Dimarts") +LOCVAL(LOCALE_SDAYNAME3,"Dimecres") +LOCVAL(LOCALE_SDAYNAME4,"Dijous") +LOCVAL(LOCALE_SDAYNAME5,"Divendres") +LOCVAL(LOCALE_SDAYNAME6,"Dissabte") +LOCVAL(LOCALE_SDAYNAME7,"Diumenge") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Dl") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Dt") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Dc") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Dj") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Dv") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Ds") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Dg") + +LOCVAL(LOCALE_SMONTHNAME1,"Gener") +LOCVAL(LOCALE_SMONTHNAME2,"Febrer") +LOCVAL(LOCALE_SMONTHNAME3,"Març") +LOCVAL(LOCALE_SMONTHNAME4,"Abril") +LOCVAL(LOCALE_SMONTHNAME5,"Maig") +LOCVAL(LOCALE_SMONTHNAME6,"Juny") +LOCVAL(LOCALE_SMONTHNAME7,"Juliol") +LOCVAL(LOCALE_SMONTHNAME8,"Agost") +LOCVAL(LOCALE_SMONTHNAME9,"Setembre") +LOCVAL(LOCALE_SMONTHNAME10,"Octubre") +LOCVAL(LOCALE_SMONTHNAME11,"Novembre") +LOCVAL(LOCALE_SMONTHNAME12,"Desembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Gn") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Fb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mç") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Ab") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mg") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jn") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jl") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Ag") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"St") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Oc") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nv") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Ds") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ca") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ES") + diff --git a/lib/kernel32/nls/cht.nls b/lib/kernel32/nls/cht.nls new file mode 100644 index 0000000..0e79933 --- /dev/null +++ b/lib/kernel32/nls/cht.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Chinese (Taiwan) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0404") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Chinese (Taiwan)") +LOCVAL(LOCALE_SABBREVLANGNAME,"cht") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"China (Taiwan)") +LOCVAL(LOCALE_SABBREVCTRYNAME,"TWN") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0404") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL, "TWD") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"zh") +LOCVAL(LOCALE_SISO3166CTRYNAME,"TW") + diff --git a/lib/kernel32/nls/codepage.c b/lib/kernel32/nls/codepage.c new file mode 100644 index 0000000..2889426 --- /dev/null +++ b/lib/kernel32/nls/codepage.c @@ -0,0 +1,122 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + Addition copyrights might be specified in LGPL.c + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/nls/codepage.c + * PURPOSE: National language support functions + * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) + * UPDATE HISTORY: Modified from Onno Hovers wfc. ( 08/02/99 ) + Modified from wine. ( 08/02/99 ) + * + */ + +/* + * nls/codepage.c ( Onno Hovers ) + * + * + */ + +/* + * Win32 kernel functions + * + * Copyright 1995 Martin von Loewis and Cameron Heide + */ +#include +#include +#include +#include + +#define NDEBUG +#include + + +extern PLOCALE __TebLocale; + +#define GetTebLocale() __TebLocale + + +UINT STDCALL GetACP(void) +{ + DPRINT("GetACP()\n"); + + /* XXX: read from registry, take this as default */ + return GetTebLocale()->AnsiCodePage->Id; +} + +UINT STDCALL GetOEMCP(void) +{ + DPRINT("GetOEMCP()\n"); + /* XXX: read from registry, take this as default */ + return GetTebLocale()->OemCodePage->Id; +} + +WINBOOL STDCALL IsValidCodePage(UINT codepage) +{ + PCODEPAGE pcp; + + DPRINT("IsValidCodePage( %u )\n", codepage); + + switch(codepage) + { + case CP_ACP: return TRUE; + case CP_OEMCP: return TRUE; + case CP_MACCP: return TRUE; + default: + pcp=__CPFirst; + while((pcp)&&(pcp->Id!=codepage)) + pcp=pcp->Next; + return pcp ? TRUE : FALSE; + } +} + +WINBOOL GetCPInfo(UINT codepage, LPCPINFO pcpinfo) +{ + PCODEPAGE pcp; + + DPRINT("GetCPInfo( %u, 0x%lX )\n", codepage, (ULONG) pcpinfo); + + pcp=__CPFirst; + while((pcp)&&(pcp->Id!=codepage)) + pcp=pcp->Next; + if(!pcp) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if(!pcp->Info) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + *pcpinfo = *pcp->Info; + return TRUE; +} + + + +WINBOOL +STDCALL +IsDBCSLeadByteEx( UINT codepage, BYTE testchar ) +{ + CPINFO cpinfo; + int i; + + GetCPInfo(codepage, &cpinfo); + for (i = 0 ; i < sizeof(cpinfo.LeadByte)/sizeof(cpinfo.LeadByte[0]); i+=2) + { + if (cpinfo.LeadByte[i] == 0) + return FALSE; + if (cpinfo.LeadByte[i] <= testchar && testchar <= cpinfo.LeadByte[i+1]) + return TRUE; + } + return FALSE; +} + + + + +WINBOOL +STDCALL +IsDBCSLeadByte( BYTE testchar ) +{ + return IsDBCSLeadByteEx(GetACP(), testchar); +} \ No newline at end of file diff --git a/lib/kernel32/nls/cpmisc.c b/lib/kernel32/nls/cpmisc.c new file mode 100644 index 0000000..826c30d --- /dev/null +++ b/lib/kernel32/nls/cpmisc.c @@ -0,0 +1,101 @@ +/* + * nls/cpmisc.c + * ASCII to Unicode and Back + * + */ +#include +#include +#include + +WCHAR __ASCII_00[32]= +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F +}; + +WCHAR __ASCII_20[32]= +{ + ' ' , '!' , '\"', '#' , '$' , '%' , '&' , '\'', + '(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' , + '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , + '8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' +}; + +WCHAR __ASCII_40[32]= +{ + '@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , + 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , + 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , + 'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' +}; + +WCHAR __ASCII_60[32]= +{ + '`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , + 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , + 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , + 'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 0x7F +}; + +CHAR __ASCII_0000[32]= +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F +}; + +CHAR __ASCII_0020[32]= +{ + ' ' , '!' , '\"', '#' , '$' , '%' , '&' , '\'', + '(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' , + '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , + '8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' +}; + +CHAR __ASCII_0040[32]= +{ + '@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , + 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , + 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , + 'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' +}; + +CHAR __ASCII_0060[32]= +{ + '`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , + 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , + 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , + 'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 0x7F +}; + +WCHAR __NULL_00[32]= +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +CHAR __NULL_0000[32]= +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +CHAR *__NULL_00XX[32]= +{ + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000, + __NULL_0000, __NULL_0000, __NULL_0000, __NULL_0000 +}; + \ No newline at end of file diff --git a/lib/kernel32/nls/cptable.c b/lib/kernel32/nls/cptable.c new file mode 100644 index 0000000..4805ee6 --- /dev/null +++ b/lib/kernel32/nls/cptable.c @@ -0,0 +1,402 @@ +/* + * nls/cptable.c + * Copyright (C) 1996, Onno Hovers + * + */ + +#include +#include +#include + +extern CODEPAGE __CP37; +extern WCHAR *__CP37_ToUnicode; +extern CHAR **__CP37_FromUnicode; + +extern CODEPAGE __CP437; +extern WCHAR *__CP437_ToUnicode; +extern WCHAR *__CP437_ToUnicodeGlyph; +extern CHAR **__CP437_FromUnicode; + +extern CODEPAGE __CP500; +extern WCHAR *__CP500_ToUnicode; +extern CHAR **__CP500_FromUnicode; + +extern CODEPAGE __CP737; +extern WCHAR *__CP737_ToUnicode; +extern WCHAR *__CP737_ToUnicodeGlyph; +extern CHAR **__CP737_FromUnicode; + +extern CODEPAGE __CP775; +extern WCHAR *__CP775_ToUnicode; +extern WCHAR *__CP775_ToUnicodeGlyph; +extern CHAR **__CP775_FromUnicode; + +extern CODEPAGE __CP850; +extern WCHAR *__CP850_ToUnicode; +extern WCHAR *__CP850_ToUnicodeGlyph; +extern CHAR **__CP850_FromUnicode; + +extern CODEPAGE __CP852; +extern WCHAR *__CP852_ToUnicode; +extern WCHAR *__CP852_ToUnicodeGlyph; +extern CHAR **__CP852_FromUnicode; + +extern CODEPAGE __CP855; +extern WCHAR *__CP855_ToUnicode; +extern WCHAR *__CP855_ToUnicodeGlyph; +extern CHAR **__CP855_FromUnicode; + +extern CODEPAGE __CP857; +extern WCHAR *__CP857_ToUnicode; +extern WCHAR *__CP857_ToUnicodeGlyph; +extern CHAR **__CP857_FromUnicode; + +extern CODEPAGE __CP860; +extern WCHAR *__CP860_ToUnicode; +extern WCHAR *__CP860_ToUnicodeGlyph; +extern CHAR **__CP860_FromUnicode; + +extern CODEPAGE __CP861; +extern WCHAR *__CP861_ToUnicode; +extern WCHAR *__CP861_ToUnicodeGlyph; +extern CHAR **__CP861_FromUnicode; + +extern CODEPAGE __CP863; +extern WCHAR *__CP863_ToUnicode; +extern WCHAR *__CP863_ToUnicodeGlyph; +extern CHAR **__CP863_FromUnicode; + +extern CODEPAGE __CP865; +extern WCHAR *__CP865_ToUnicode; +extern WCHAR *__CP865_ToUnicodeGlyph; +extern CHAR **__CP865_FromUnicode; + +extern CODEPAGE __CP866; +extern WCHAR *__CP866_ToUnicode; +extern WCHAR *__CP866_ToUnicodeGlyph; +extern CHAR **__CP866_FromUnicode; + +extern CODEPAGE __CP869; +extern WCHAR *__CP869_ToUnicode; +extern WCHAR *__CP869_ToUnicodeGlyph; +extern CHAR **__CP869_FromUnicode; + +extern CODEPAGE __CP875; +extern WCHAR *__CP875_ToUnicode; +extern CHAR **__CP875_FromUnicode; + +extern CODEPAGE __CP1026; +extern WCHAR *__CP1026_ToUnicode; +extern CHAR **__CP1026_FromUnicode; + +extern CODEPAGE __CP1250; +extern WCHAR *__CP1250_ToUnicode; +extern CHAR **__CP1250_FromUnicode; + +extern CODEPAGE __CP1251; +extern WCHAR *__CP1251_ToUnicode; +extern CHAR **__CP1251_FromUnicode; + +extern CODEPAGE __CP1252; +extern WCHAR *__CP1252_ToUnicode; +extern CHAR **__CP1252_FromUnicode; + +extern CODEPAGE __CP1253; +extern WCHAR *__CP1253_ToUnicode; +extern CHAR **__CP1253_FromUnicode; + +extern CODEPAGE __CP1254; +extern WCHAR *__CP1254_ToUnicode; +extern CHAR **__CP1254_FromUnicode; + +extern CODEPAGE __CP1255; +extern WCHAR *__CP1255_ToUnicode; +extern CHAR **__CP1255_FromUnicode; + +extern CODEPAGE __CP1256; +extern WCHAR *__CP1256_ToUnicode; +extern CHAR **__CP1256_FromUnicode; + +extern CODEPAGE __CP1257; +extern WCHAR *__CP1257_ToUnicode; +extern CHAR **__CP1257_FromUnicode; + +extern CODEPAGE __CP1258; +extern WCHAR *__CP1258_ToUnicode; +extern CHAR **__CP1258_FromUnicode; + +extern CODEPAGE __CP10000; +extern WCHAR *__CP10000_ToUnicode; +extern CHAR **__CP10000_FromUnicode; + +extern CODEPAGE __CP10006; +extern WCHAR *__CP10006_ToUnicode; +extern CHAR **__CP10006_FromUnicode; + +extern CODEPAGE __CP10007; +extern WCHAR *__CP10007_ToUnicode; +extern CHAR **__CP10007_FromUnicode; + +extern CODEPAGE __CP10029; +extern WCHAR *__CP10029_ToUnicode; +extern CHAR **__CP10029_FromUnicode; + +extern CODEPAGE __CP10079; +extern WCHAR *__CP10079_ToUnicode; +extern CHAR **__CP10079_FromUnicode; + +extern CODEPAGE __CP10081; +extern WCHAR *__CP10081_ToUnicode; +extern CHAR **__CP10081_FromUnicode; + +CPINFO __CPGenInfo={1, {'?',0}, { 0,0,0,0, 0,0,0,0, 0,0,0,0 }}; + +PCODEPAGE __CPFirst = &__CP37; + +/* EBCDIC */ +CODEPAGE __CP37 = +{ + &__CP437, 37, CODEPAGE_EBCDIC, &__CP37_ToUnicode, + &__CP37_ToUnicode, &__CP37_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS U.S. */ +CODEPAGE __CP437 = +{ + &__CP500, 437, CODEPAGE_OEM, &__CP437_ToUnicode, + &__CP437_ToUnicodeGlyph, &__CP437_FromUnicode, + &__CPGenInfo +}; + +/* EBCDIC */ +CODEPAGE __CP500 = +{ + &__CP737, 500, CODEPAGE_EBCDIC, &__CP500_ToUnicode, + &__CP500_ToUnicode, &__CP500_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Greek */ +CODEPAGE __CP737 = +{ + &__CP775, 737, CODEPAGE_OEM, &__CP737_ToUnicode, + &__CP737_ToUnicodeGlyph, &__CP737_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Baltic Rim */ +CODEPAGE __CP775 = +{ + &__CP850, 775, CODEPAGE_OEM, &__CP775_ToUnicode, + &__CP775_ToUnicodeGlyph, &__CP775_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Latin 1 */ +CODEPAGE __CP850 = +{ + &__CP852, 850, CODEPAGE_OEM, &__CP850_ToUnicode, + &__CP850_ToUnicodeGlyph, &__CP850_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Latin 2 */ +CODEPAGE __CP852 = +{ + &__CP855, 852, CODEPAGE_OEM, &__CP852_ToUnicode, + &__CP852_ToUnicodeGlyph, &__CP852_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Cyrillic */ +CODEPAGE __CP855 = +{ + &__CP857, 855, CODEPAGE_OEM, &__CP855_ToUnicode, + &__CP855_ToUnicodeGlyph, &__CP855_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Turkish */ +CODEPAGE __CP857 = +{ + &__CP860, 857, CODEPAGE_OEM, &__CP857_ToUnicode, + &__CP857_ToUnicodeGlyph, &__CP857_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Portugese */ +CODEPAGE __CP860 = +{ + &__CP861, 860, CODEPAGE_OEM, &__CP860_ToUnicode, + &__CP860_ToUnicodeGlyph, &__CP860_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Icelandic */ +CODEPAGE __CP861 = +{ + &__CP863, 861, CODEPAGE_OEM, &__CP861_ToUnicode, + &__CP861_ToUnicodeGlyph, &__CP861_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS French Canada */ +CODEPAGE __CP863 = +{ + &__CP865, 863, CODEPAGE_OEM, &__CP863_ToUnicode, + &__CP863_ToUnicodeGlyph, &__CP863_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Nordic */ +CODEPAGE __CP865 = +{ + &__CP866, 865, CODEPAGE_OEM, &__CP865_ToUnicode, + &__CP865_ToUnicodeGlyph, &__CP865_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Cyrillic CIS-1 */ +CODEPAGE __CP866 = +{ + &__CP869, 866, CODEPAGE_OEM, &__CP866_ToUnicode, + &__CP866_ToUnicodeGlyph, &__CP866_FromUnicode, + &__CPGenInfo +}; + +/* MS-DOS Greek 2 */ +CODEPAGE __CP869 = +{ + &__CP875, 869, CODEPAGE_OEM, &__CP869_ToUnicode, + &__CP869_ToUnicodeGlyph, &__CP869_FromUnicode, + &__CPGenInfo +}; + +/* EBCDIC codepage */ +CODEPAGE __CP875 = +{ + &__CP1026, 875, CODEPAGE_EBCDIC, &__CP875_ToUnicode, + &__CP875_ToUnicode, &__CP875_FromUnicode, + &__CPGenInfo +}; + +/* EBCDIC codepage */ +CODEPAGE __CP1026 = +{ + &__CP1250, 1026, CODEPAGE_EBCDIC, &__CP1026_ToUnicode, + &__CP1026_ToUnicode, &__CP1026_FromUnicode, + &__CPGenInfo +}; + +/* Windows Latin 2 (Central Europe) */ +CODEPAGE __CP1250 = +{ + &__CP1251, 1250, CODEPAGE_ANSI, &__CP1250_ToUnicode, + &__CP1250_ToUnicode, &__CP1250_FromUnicode, + &__CPGenInfo +}; + +/* Windows Cyrillic */ +CODEPAGE __CP1251 = +{ + &__CP1252, 1251, CODEPAGE_ANSI, &__CP1251_ToUnicode, + &__CP1251_ToUnicode, &__CP1251_FromUnicode, + &__CPGenInfo +}; + +/* Windows Latin 1 */ +CODEPAGE __CP1252 = +{ + &__CP1253, 1252, CODEPAGE_ANSI, &__CP1252_ToUnicode, + &__CP1252_ToUnicode, &__CP1252_FromUnicode, + &__CPGenInfo +}; + +/* Windows Greek */ +CODEPAGE __CP1253 = +{ + &__CP1254, 1253, CODEPAGE_ANSI, &__CP1253_ToUnicode, + &__CP1253_ToUnicode, &__CP1253_FromUnicode, + &__CPGenInfo +}; + +/* Windows Latin 5 (Turkish) */ +CODEPAGE __CP1254 = +{ + &__CP1255, 1254, CODEPAGE_ANSI, &__CP1254_ToUnicode, + &__CP1254_ToUnicode, &__CP1254_FromUnicode, + &__CPGenInfo +}; + +/* Windows Hebrew */ +CODEPAGE __CP1255 = +{ + &__CP1256, 1255, CODEPAGE_ANSI, &__CP1255_ToUnicode, + &__CP1255_ToUnicode, &__CP1255_FromUnicode, + &__CPGenInfo +}; + +/* Windows Arabic */ +CODEPAGE __CP1256 = +{ + &__CP1257, 1256, CODEPAGE_ANSI, &__CP1256_ToUnicode, + &__CP1256_ToUnicode, &__CP1256_FromUnicode, + &__CPGenInfo +}; + +/* Windows Baltic Rim */ +CODEPAGE __CP1257 = +{ + &__CP10000, 1257, CODEPAGE_ANSI, &__CP1257_ToUnicode, + &__CP1257_ToUnicode, &__CP1257_FromUnicode, + &__CPGenInfo +}; + +/* Macintosh Roman */ +CODEPAGE __CP10000 = +{ + &__CP10006, 10000, CODEPAGE_MAC, &__CP10000_ToUnicode, + &__CP10000_ToUnicode, &__CP10000_FromUnicode, + &__CPGenInfo +}; + +/* Macintosh Greek 1 */ +CODEPAGE __CP10006 = +{ + &__CP10007, 10006, CODEPAGE_MAC, &__CP10006_ToUnicode, + &__CP10006_ToUnicode, &__CP10006_FromUnicode, + &__CPGenInfo +}; + +/* Macintosh Cyrillic */ +CODEPAGE __CP10007 = +{ + &__CP10029, 10007, CODEPAGE_MAC, &__CP10007_ToUnicode, + &__CP10007_ToUnicode, &__CP10007_FromUnicode, + &__CPGenInfo +}; + +/* Macintosh Latin 2 */ +CODEPAGE __CP10029 = +{ + &__CP10079, 10029, CODEPAGE_MAC, &__CP10029_ToUnicode, + &__CP10029_ToUnicode, &__CP10029_FromUnicode, + &__CPGenInfo +}; + +/* Macintosh Icelandic */ +CODEPAGE __CP10079 = +{ + &__CP10081, 10079, CODEPAGE_MAC, &__CP10079_ToUnicode, + &__CP10079_ToUnicode, &__CP10079_FromUnicode, + &__CPGenInfo +}; + +/* Macintosh Turkish */ +CODEPAGE __CP10081 = +{ + NULL, 10081, CODEPAGE_MAC, &__CP10081_ToUnicode, + &__CP10081_ToUnicode, &__CP10081_FromUnicode, + &__CPGenInfo +}; \ No newline at end of file diff --git a/lib/kernel32/nls/cze.nls b/lib/kernel32/nls/cze.nls new file mode 100644 index 0000000..240dc5f --- /dev/null +++ b/lib/kernel32/nls/cze.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Czech Republic + * (Czech strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0405") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Czech") +LOCVAL(LOCALE_SABBREVLANGNAME,"cze") +LOCVAL(LOCALE_SNATIVELANGNAME,"Èeský jazyk") +LOCVAL(LOCALE_ICOUNTRY,"42") +LOCVAL(LOCALE_SCOUNTRY,"Èeská Republika") +LOCVAL(LOCALE_SENGCOUNTRY,"Czech Republic") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CZE") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Èeská Republika") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0405") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"42") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"895") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Kè") +LOCVAL(LOCALE_SINTLSYMBOL,"CZK") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP," ") +LOCVAL(LOCALE_SMONGROUPING,"3;3") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Ponïelí") +LOCVAL(LOCALE_SDAYNAME2,"Úterý") +LOCVAL(LOCALE_SDAYNAME3,"Støeda") +LOCVAL(LOCALE_SDAYNAME4,"Ètvrtek") +LOCVAL(LOCALE_SDAYNAME5,"Pátek") +LOCVAL(LOCALE_SDAYNAME6,"Sobota") +LOCVAL(LOCALE_SDAYNAME7,"Nedìle") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Po") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Út") +LOCVAL(LOCALE_SABBREVDAYNAME3,"St") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Èt") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Pá") +LOCVAL(LOCALE_SABBREVDAYNAME6,"So") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Ne") + +LOCVAL(LOCALE_SMONTHNAME1,"Leden") +LOCVAL(LOCALE_SMONTHNAME2,"Únor") +LOCVAL(LOCALE_SMONTHNAME3,"Bøezen") +LOCVAL(LOCALE_SMONTHNAME4,"Duben") +LOCVAL(LOCALE_SMONTHNAME5,"Kvìten") +LOCVAL(LOCALE_SMONTHNAME6,"Èerven") +LOCVAL(LOCALE_SMONTHNAME7,"Èervenec") +LOCVAL(LOCALE_SMONTHNAME8,"Srpen") +LOCVAL(LOCALE_SMONTHNAME9,"Záøí") +LOCVAL(LOCALE_SMONTHNAME10,"Øíjen") +LOCVAL(LOCALE_SMONTHNAME11,"Listopad") +LOCVAL(LOCALE_SMONTHNAME12,"Prosinec") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Led") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Úno") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Bøe") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Dub") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Kvì") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Èer") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Ènc") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Srp") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Záø") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Øíj") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Lis") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Pro") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"cs") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CZ") + diff --git a/lib/kernel32/nls/dan.nls b/lib/kernel32/nls/dan.nls new file mode 100644 index 0000000..6284eb1 --- /dev/null +++ b/lib/kernel32/nls/dan.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Denmark + */ + +LOCVAL(LOCALE_ILANGUAGE,"0406") +LOCVAL(LOCALE_SLANGUAGE,"Dansk") +LOCVAL(LOCALE_SENGLANGUAGE,"Danish") +LOCVAL(LOCALE_SABBREVLANGNAME,"dan") +LOCVAL(LOCALE_SNATIVELANGNAME,"Dansk") +LOCVAL(LOCALE_ICOUNTRY,"45") +LOCVAL(LOCALE_SCOUNTRY,"Danmark") +LOCVAL(LOCALE_SENGCOUNTRY,"Denmark") +LOCVAL(LOCALE_SABBREVCTRYNAME,"DNK") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Danmark") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0406") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"45") +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"kr") +LOCVAL(LOCALE_SINTLSYMBOL,"DKK") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"mandag") +LOCVAL(LOCALE_SDAYNAME2,"tirsdag") +LOCVAL(LOCALE_SDAYNAME3,"onsdag") +LOCVAL(LOCALE_SDAYNAME4,"torsdag") +LOCVAL(LOCALE_SDAYNAME5,"fredag") +LOCVAL(LOCALE_SDAYNAME6,"lørdag") +LOCVAL(LOCALE_SDAYNAME7,"søndag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"ma") +LOCVAL(LOCALE_SABBREVDAYNAME2,"ti") +LOCVAL(LOCALE_SABBREVDAYNAME3,"on") +LOCVAL(LOCALE_SABBREVDAYNAME4,"to") +LOCVAL(LOCALE_SABBREVDAYNAME5,"fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"lø") +LOCVAL(LOCALE_SABBREVDAYNAME7,"sø") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februar") +LOCVAL(LOCALE_SMONTHNAME3,"marts") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"maj") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"december") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"da") +LOCVAL(LOCALE_SISO3166CTRYNAME,"DK") + diff --git a/lib/kernel32/nls/dea.nls b/lib/kernel32/nls/dea.nls new file mode 100644 index 0000000..be4b51f --- /dev/null +++ b/lib/kernel32/nls/dea.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Austria + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c07") +LOCVAL(LOCALE_SLANGUAGE,"Deutsch") +LOCVAL(LOCALE_SENGLANGUAGE,"German (Austria)") +LOCVAL(LOCALE_SABBREVLANGNAME,"dea") +LOCVAL(LOCALE_SNATIVELANGNAME,"Österreich") +LOCVAL(LOCALE_ICOUNTRY,"41") +LOCVAL(LOCALE_SCOUNTRY,"Österreich (Deutsch)") +LOCVAL(LOCALE_SENGCOUNTRY,"Austria") +LOCVAL(LOCALE_SABBREVCTRYNAME,"AUT") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Österreich") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0407") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"41") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"851") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,".") +LOCVAL(LOCALE_STHOUSAND,"'") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"S") +LOCVAL(LOCALE_SINTLSYMBOL,"ATS") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") + +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159,"") +LOCVAL(LOCALE_S2359,"") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Montag") +LOCVAL(LOCALE_SDAYNAME2,"Dienstag") +LOCVAL(LOCALE_SDAYNAME3,"Mittwoch") +LOCVAL(LOCALE_SDAYNAME4,"Donnerstag") +LOCVAL(LOCALE_SDAYNAME5,"Freitag") +LOCVAL(LOCALE_SDAYNAME6,"Samstag") +LOCVAL(LOCALE_SDAYNAME7,"Sonntag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Mo") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Mi") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"So") + +LOCVAL(LOCALE_SMONTHNAME1,"Jänner") +LOCVAL(LOCALE_SMONTHNAME2,"Februar") +LOCVAL(LOCALE_SMONTHNAME3,"März") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mai") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"August") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Dezember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jän") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mär") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"de") +LOCVAL(LOCALE_SISO3166CTRYNAME,"AT") diff --git a/lib/kernel32/nls/dec.nls b/lib/kernel32/nls/dec.nls new file mode 100644 index 0000000..7a8153a --- /dev/null +++ b/lib/kernel32/nls/dec.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Fuerstentum Liechtenstein + */ + +LOCVAL(LOCALE_ILANGUAGE,"1407") +LOCVAL(LOCALE_SLANGUAGE,"Deutsch") +LOCVAL(LOCALE_SENGLANGUAGE,"German") +LOCVAL(LOCALE_SABBREVLANGNAME,"dec") +LOCVAL(LOCALE_SNATIVELANGNAME,"Deutsch") +LOCVAL(LOCALE_ICOUNTRY,"41") +LOCVAL(LOCALE_SCOUNTRY,"Liechtenstein (Deutsch)") +LOCVAL(LOCALE_SENGCOUNTRY,"Liechtenstein") +LOCVAL(LOCALE_SABBREVCTRYNAME,"LIE") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Liechtenstein") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0407") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"41") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"851") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,".") +LOCVAL(LOCALE_STHOUSAND,"'") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"SFr") +LOCVAL(LOCALE_SINTLSYMBOL,"CHF") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") + +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159,"") +LOCVAL(LOCALE_S2359,"") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Montag") +LOCVAL(LOCALE_SDAYNAME2,"Dienstag") +LOCVAL(LOCALE_SDAYNAME3,"Mittwoch") +LOCVAL(LOCALE_SDAYNAME4,"Donnerstag") +LOCVAL(LOCALE_SDAYNAME5,"Freitag") +LOCVAL(LOCALE_SDAYNAME6,"Samstag") +LOCVAL(LOCALE_SDAYNAME7,"Sonntag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Mo") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Mi") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"So") + +LOCVAL(LOCALE_SMONTHNAME1,"Januar") +LOCVAL(LOCALE_SMONTHNAME2,"Februar") +LOCVAL(LOCALE_SMONTHNAME3,"März") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mai") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"August") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Dezember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mär") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"de") +LOCVAL(LOCALE_SISO3166CTRYNAME,"LI") diff --git a/lib/kernel32/nls/del.nls b/lib/kernel32/nls/del.nls new file mode 100644 index 0000000..0b5caae --- /dev/null +++ b/lib/kernel32/nls/del.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Luxembourg (German) + */ + +LOCVAL(LOCALE_ILANGUAGE,"1007") +LOCVAL(LOCALE_SLANGUAGE,"Deutsch") +LOCVAL(LOCALE_SENGLANGUAGE,"German") +LOCVAL(LOCALE_SABBREVLANGNAME,"deu") +LOCVAL(LOCALE_SNATIVELANGNAME,"Deutsch") +LOCVAL(LOCALE_ICOUNTRY,"49") +LOCVAL(LOCALE_SCOUNTRY,"Luxemburg") +LOCVAL(LOCALE_SENGCOUNTRY,"Luxemburg") +LOCVAL(LOCALE_SABBREVCTRYNAME,"LUX") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Luxembourg") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0407") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"49") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"851") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"F") +LOCVAL(LOCALE_SINTLSYMBOL, "LUF") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159,"") +LOCVAL(LOCALE_S2359,"") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Montag") +LOCVAL(LOCALE_SDAYNAME2,"Dienstag") +LOCVAL(LOCALE_SDAYNAME3,"Mittwoch") +LOCVAL(LOCALE_SDAYNAME4,"Donnerstag") +LOCVAL(LOCALE_SDAYNAME5,"Freitag") +LOCVAL(LOCALE_SDAYNAME6,"Sonnabend") +LOCVAL(LOCALE_SDAYNAME7,"Sonntag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Mo") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Mi") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"So") + +LOCVAL(LOCALE_SMONTHNAME1,"Januar") +LOCVAL(LOCALE_SMONTHNAME2,"Februar") +LOCVAL(LOCALE_SMONTHNAME3,"März") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mai") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"August") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Dezember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mär") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"de") +LOCVAL(LOCALE_SISO3166CTRYNAME,"LU") diff --git a/lib/kernel32/nls/des.nls b/lib/kernel32/nls/des.nls new file mode 100644 index 0000000..8e05ee1 --- /dev/null +++ b/lib/kernel32/nls/des.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Switzerland (German) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0807") +LOCVAL(LOCALE_SLANGUAGE,"Deutsch") +LOCVAL(LOCALE_SENGLANGUAGE,"German") +LOCVAL(LOCALE_SABBREVLANGNAME,"des") +LOCVAL(LOCALE_SNATIVELANGNAME,"Schweiz") +LOCVAL(LOCALE_ICOUNTRY,"41") +LOCVAL(LOCALE_SCOUNTRY,"Schweiz (Deutsch)") +LOCVAL(LOCALE_SENGCOUNTRY,"Switzerland") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CHE") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Schweiz") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0807") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"41") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"851") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,".") +LOCVAL(LOCALE_STHOUSAND,"'") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"SFr") +LOCVAL(LOCALE_SINTLSYMBOL,"CHF") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") + +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159,"") +LOCVAL(LOCALE_S2359,"") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Montag") +LOCVAL(LOCALE_SDAYNAME2,"Dienstag") +LOCVAL(LOCALE_SDAYNAME3,"Mittwoch") +LOCVAL(LOCALE_SDAYNAME4,"Donnerstag") +LOCVAL(LOCALE_SDAYNAME5,"Freitag") +LOCVAL(LOCALE_SDAYNAME6,"Samstag") +LOCVAL(LOCALE_SDAYNAME7,"Sonntag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Mo") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Mi") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"So") + +LOCVAL(LOCALE_SMONTHNAME1,"Januar") +LOCVAL(LOCALE_SMONTHNAME2,"Februar") +LOCVAL(LOCALE_SMONTHNAME3,"März") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mai") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"August") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Dezember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mär") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"de") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CH") diff --git a/lib/kernel32/nls/deu.nls b/lib/kernel32/nls/deu.nls new file mode 100644 index 0000000..0b042f9 --- /dev/null +++ b/lib/kernel32/nls/deu.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Germany + */ + +LOCVAL(LOCALE_ILANGUAGE,"0407") +LOCVAL(LOCALE_SLANGUAGE,"Deutsch (Deutschland)") +LOCVAL(LOCALE_SENGLANGUAGE,"German") +LOCVAL(LOCALE_SABBREVLANGNAME,"DEU") +LOCVAL(LOCALE_SNATIVELANGNAME,"Deutsch") +LOCVAL(LOCALE_ICOUNTRY,"49") +LOCVAL(LOCALE_SCOUNTRY,"Deutschland") +LOCVAL(LOCALE_SENGCOUNTRY,"Germany") +LOCVAL(LOCALE_SABBREVCTRYNAME,"DEU") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Deutschland") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0407") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"49") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +LOCVAL(LOCALE_SGROUPING,"3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_IDEFAULTMACCODEPAGE,"10000") +LOCVAL(LOCALE_ILZERO,"1") +LOCVAL(LOCALE_INEGNUMBER,"1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"DM") +LOCVAL(LOCALE_SINTLSYMBOL, "DEM") +LOCVAL(LOCALE_SMONDECIMALSEP, ",") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS,"2") +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yy") +LOCVAL(LOCALE_SLONGDATE,"dddd, d. MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT,"HH:mm:ss") +LOCVAL(LOCALE_IDATE,"1") +LOCVAL(LOCALE_ILDATE,"1") +LOCVAL(LOCALE_ITIME,"1") +LOCVAL(LOCALE_ITIMEMARKPOSN,"0") +LOCVAL(LOCALE_ICENTURY,"0") +LOCVAL(LOCALE_ITLZERO,"1") +LOCVAL(LOCALE_IDAYLZERO,"1") +LOCVAL(LOCALE_IMONLZERO,"1") +LOCVAL(LOCALE_S1159,"") +LOCVAL(LOCALE_S2359,"") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR,"0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK,"0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR,"2") + +LOCVAL(LOCALE_SDAYNAME1,"Montag") +LOCVAL(LOCALE_SDAYNAME2,"Dienstag") +LOCVAL(LOCALE_SDAYNAME3,"Mittwoch") +LOCVAL(LOCALE_SDAYNAME4,"Donnerstag") +LOCVAL(LOCALE_SDAYNAME5,"Freitag") +LOCVAL(LOCALE_SDAYNAME6,"Samstag") +LOCVAL(LOCALE_SDAYNAME7,"Sonntag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Mo") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Mi") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"So") + +LOCVAL(LOCALE_SMONTHNAME1,"Januar") +LOCVAL(LOCALE_SMONTHNAME2,"Februar") +LOCVAL(LOCALE_SMONTHNAME3,"März") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mai") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"August") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Dezember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mrz") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN,"1") +LOCVAL(LOCALE_INEGSIGNPOSN,"1") +LOCVAL(LOCALE_IPOSSYMPRECEDES,"0") +LOCVAL(LOCALE_IPOSSEPBYSPACE,"1") +LOCVAL(LOCALE_INEGSYMPRECEDES,"0") +LOCVAL(LOCALE_INEGSEPBYSPACE,"1") +LOCVAL(LOCALE_FONTSIGNATURE,"/") +LOCVAL(LOCALE_SISO639LANGNAME,"de") +LOCVAL(LOCALE_SISO3166CTRYNAME,"DE") diff --git a/lib/kernel32/nls/dnk.nls b/lib/kernel32/nls/dnk.nls new file mode 100644 index 0000000..e69de29 diff --git a/lib/kernel32/nls/empty.nls b/lib/kernel32/nls/empty.nls new file mode 100644 index 0000000..b8623c5 --- /dev/null +++ b/lib/kernel32/nls/empty.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Language (Information) + */ + +/* LOCVAL(LOCALE_ILANGUAGE,"") */ +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +/* LOCVAL(LOCALE_SENGLANGUAGE,"") */ +/* LOCVAL(LOCALE_SABBREVLANGNAME,"") */ +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +/* LOCVAL(LOCALE_SENGCOUNTRY,"") */ +/* LOCVAL(LOCALE_SABBREVCTRYNAME,"") */ +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +/* LOCVAL(LOCALE_IDEFAULTLANGUAGE,"") */ +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +/* LOCVAL(LOCALE_SINTLSYMBOL) */ +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +/* LOCVAL(LOCALE_ITIME,"1") */ +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +/* LOCVAL(LOCALE_ITLZERO,"1") */ +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +/* LOCVAL(LOCALE_ICALENDARTYPE) */ +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +/* LOCVAL(LOCALE_SISO639LANGNAME, "") */ +/* LOCVAL(LOCALE_SISO3166CTRYNAME, "") */ + +/* */ diff --git a/lib/kernel32/nls/ena.nls b/lib/kernel32/nls/ena.nls new file mode 100644 index 0000000..017e402 --- /dev/null +++ b/lib/kernel32/nls/ena.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Australia + */ + +LOCVAL(LOCALE_ILANGUAGE, "0c09") +LOCVAL(LOCALE_SLANGUAGE, "English (Australia)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "ena") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "44") +LOCVAL(LOCALE_SCOUNTRY, "Australia") +LOCVAL(LOCALE_SENGCOUNTRY, "Australia") +LOCVAL(LOCALE_SABBREVCTRYNAME, "AUS") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Australia") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "44") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "AUD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dd MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "1") +LOCVAL(LOCALE_IDAYLZERO, "1") +LOCVAL(LOCALE_IMONLZERO, "1") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"AU") diff --git a/lib/kernel32/nls/enb.nls b/lib/kernel32/nls/enb.nls new file mode 100644 index 0000000..04c6e8f --- /dev/null +++ b/lib/kernel32/nls/enb.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Caribbean + */ + +LOCVAL(LOCALE_ILANGUAGE, "2409") +LOCVAL(LOCALE_SLANGUAGE, "English (Caribbean)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "enb") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "44") +LOCVAL(LOCALE_SCOUNTRY, "Caribbean") +LOCVAL(LOCALE_SENGCOUNTRY, "Caribbean") +LOCVAL(LOCALE_SABBREVCTRYNAME, "CAR") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Carribean") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "2409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "44") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dd MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "1") +LOCVAL(LOCALE_IDAYLZERO, "1") +LOCVAL(LOCALE_IMONLZERO, "1") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +/* LOCVAL(LOCALE_SISO3166CTRYNAME,"") */ diff --git a/lib/kernel32/nls/enc.nls b/lib/kernel32/nls/enc.nls new file mode 100644 index 0000000..5285d6d --- /dev/null +++ b/lib/kernel32/nls/enc.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Canada (English) + */ + +LOCVAL(LOCALE_ILANGUAGE, "1009") +LOCVAL(LOCALE_SLANGUAGE, "English (Canada)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "enc") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "2") +LOCVAL(LOCALE_SCOUNTRY, "Canada") +LOCVAL(LOCALE_SENGCOUNTRY, "Canada") +LOCVAL(LOCALE_SABBREVCTRYNAME, "CAN") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Canada") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "1") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "CAD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "M/d/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CA") diff --git a/lib/kernel32/nls/eng.nls b/lib/kernel32/nls/eng.nls new file mode 100644 index 0000000..0d77020 --- /dev/null +++ b/lib/kernel32/nls/eng.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * United Kingdom + */ + +LOCVAL(LOCALE_ILANGUAGE, "0809") +LOCVAL(LOCALE_SLANGUAGE, "English (United Kingdom)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "eng") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "44") +LOCVAL(LOCALE_SCOUNTRY, "United Kingdom") +LOCVAL(LOCALE_SENGCOUNTRY, "United Kingdom") +LOCVAL(LOCALE_SABBREVCTRYNAME, "GBR") +LOCVAL(LOCALE_SNATIVECTRYNAME, "United Kingdom") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "44") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "£") +LOCVAL(LOCALE_SINTLSYMBOL, "GBP") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dd MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "1") +LOCVAL(LOCALE_IDAYLZERO, "1") +LOCVAL(LOCALE_IMONLZERO, "1") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"GB") diff --git a/lib/kernel32/nls/enj.nls b/lib/kernel32/nls/enj.nls new file mode 100644 index 0000000..7ce059c --- /dev/null +++ b/lib/kernel32/nls/enj.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Jamaica + */ + +LOCVAL(LOCALE_ILANGUAGE, "2009") +LOCVAL(LOCALE_SLANGUAGE, "English (Jamaica)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "enj") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "44") +LOCVAL(LOCALE_SCOUNTRY, "Jamaica") +LOCVAL(LOCALE_SENGCOUNTRY, "Jamaica") +LOCVAL(LOCALE_SABBREVCTRYNAME, "JAM") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Jamaica") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "44") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dd MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "1") +LOCVAL(LOCALE_IDAYLZERO, "1") +LOCVAL(LOCALE_IMONLZERO, "1") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"JM") diff --git a/lib/kernel32/nls/enl.nls b/lib/kernel32/nls/enl.nls new file mode 100644 index 0000000..89d6c83 --- /dev/null +++ b/lib/kernel32/nls/enl.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * English Belize + */ + +LOCVAL(LOCALE_ILANGUAGE, "2809") +LOCVAL(LOCALE_SLANGUAGE, "English (Belize)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "enl") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "1") +LOCVAL(LOCALE_SCOUNTRY, "Belize") +LOCVAL(LOCALE_SENGCOUNTRY, "Belize") +LOCVAL(LOCALE_SABBREVCTRYNAME, "BLZ") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Belize") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "1") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "437") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "M/d/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BZ") + diff --git a/lib/kernel32/nls/ens.nls b/lib/kernel32/nls/ens.nls new file mode 100644 index 0000000..4b5953d --- /dev/null +++ b/lib/kernel32/nls/ens.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * South Africa (English) + */ + +LOCVAL(LOCALE_ILANGUAGE, "1c09") +LOCVAL(LOCALE_SLANGUAGE, "English (South Africa)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "ens") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +/* LOCVAL(LOCALE_ICOUNTRY, "") */ +LOCVAL(LOCALE_SCOUNTRY, "South Africa") +LOCVAL(LOCALE_SENGCOUNTRY, "South Africa") +LOCVAL(LOCALE_SABBREVCTRYNAME, "ZAF") +LOCVAL(LOCALE_SNATIVECTRYNAME, "South Africa") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "44") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "R") +LOCVAL(LOCALE_SINTLSYMBOL, "ZAR") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dd MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "1") +LOCVAL(LOCALE_IDAYLZERO, "1") +LOCVAL(LOCALE_IMONLZERO, "1") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ZA") diff --git a/lib/kernel32/nls/ent.nls b/lib/kernel32/nls/ent.nls new file mode 100644 index 0000000..16eea3f --- /dev/null +++ b/lib/kernel32/nls/ent.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Trinidad & Tobago + */ + +LOCVAL(LOCALE_ILANGUAGE, "2c09") +LOCVAL(LOCALE_SLANGUAGE, "English (Trinidad & Tobago)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "ent") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +/* LOCVAL(LOCALE_ICOUNTRY, "") */ +LOCVAL(LOCALE_SCOUNTRY, "Trinidad & Tobago") +LOCVAL(LOCALE_SENGCOUNTRY, "Trinidad & Tobago") +LOCVAL(LOCALE_SABBREVCTRYNAME, "TTO") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Trinidad & Tobago") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "2c09") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "1") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "437") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "M/d/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"TT") + diff --git a/lib/kernel32/nls/enu.nls b/lib/kernel32/nls/enu.nls new file mode 100644 index 0000000..8bd3a91 --- /dev/null +++ b/lib/kernel32/nls/enu.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * United States + */ + +LOCVAL(LOCALE_ILANGUAGE, "0409") +LOCVAL(LOCALE_SLANGUAGE, "English (United States)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "enu") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "1") +LOCVAL(LOCALE_SCOUNTRY, "United States") +LOCVAL(LOCALE_SENGCOUNTRY, "United States") +LOCVAL(LOCALE_SABBREVCTRYNAME, "USA") +LOCVAL(LOCALE_SNATIVECTRYNAME, "United States") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "1") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "437") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "M/d/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +LOCVAL(LOCALE_FONTSIGNATURE,"\xaf\x00\x00\x80\xcb\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x80") +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"US") diff --git a/lib/kernel32/nls/enz.nls b/lib/kernel32/nls/enz.nls new file mode 100644 index 0000000..7b75df9 --- /dev/null +++ b/lib/kernel32/nls/enz.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * New Zealand + */ + +LOCVAL(LOCALE_ILANGUAGE, "1409") +LOCVAL(LOCALE_SLANGUAGE, "English (New Zealand)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "enz") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +/* LOCVAL(LOCALE_ICOUNTRY, "") */ +LOCVAL(LOCALE_SCOUNTRY, "New Zealand") +LOCVAL(LOCALE_SENGCOUNTRY, "New Zealand") +LOCVAL(LOCALE_SABBREVCTRYNAME, "NZL") +LOCVAL(LOCALE_SNATIVECTRYNAME, "New Zealand") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "44") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "NZD") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dd MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "1") +LOCVAL(LOCALE_IDAYLZERO, "1") +LOCVAL(LOCALE_IMONLZERO, "1") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"NZ") diff --git a/lib/kernel32/nls/esa.nls b/lib/kernel32/nls/esa.nls new file mode 100644 index 0000000..a6adf92 --- /dev/null +++ b/lib/kernel32/nls/esa.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Panama) + */ + +LOCVAL(LOCALE_ILANGUAGE,"180a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esa") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Panamá") +LOCVAL(LOCALE_SENGCOUNTRY,"Panama") +LOCVAL(LOCALE_SABBREVCTRYNAME,"PAN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Panamá") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"B") +LOCVAL(LOCALE_SINTLSYMBOL, "PAB") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"PA") diff --git a/lib/kernel32/nls/esb.nls b/lib/kernel32/nls/esb.nls new file mode 100644 index 0000000..6bf2eaf --- /dev/null +++ b/lib/kernel32/nls/esb.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Bolivia) + */ + +LOCVAL(LOCALE_ILANGUAGE,"400a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esb") +LOCVAL(LOCALE_SNATIVELANGNAME,"Bolivia") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Bolivia") +LOCVAL(LOCALE_SENGCOUNTRY,"Bolivia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"BOL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Bolivia") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Bs") +LOCVAL(LOCALE_SINTLSYMBOL, "BOB") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BO") diff --git a/lib/kernel32/nls/esc.nls b/lib/kernel32/nls/esc.nls new file mode 100644 index 0000000..7906a4d --- /dev/null +++ b/lib/kernel32/nls/esc.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Costa Rica) + */ + +LOCVAL(LOCALE_ILANGUAGE,"140a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esa") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Costa Rica") +LOCVAL(LOCALE_SENGCOUNTRY,"Costa Rica") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CRI") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Costa Rica") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"140a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"C") +LOCVAL(LOCALE_SINTLSYMBOL, "CRC") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CR") diff --git a/lib/kernel32/nls/esd.nls b/lib/kernel32/nls/esd.nls new file mode 100644 index 0000000..174b550 --- /dev/null +++ b/lib/kernel32/nls/esd.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Dominican Republic) + */ + +LOCVAL(LOCALE_ILANGUAGE,"1c0a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esd") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"República Dominicana") +LOCVAL(LOCALE_SENGCOUNTRY,"Dominican Republic") +LOCVAL(LOCALE_SABBREVCTRYNAME,"DOM") +LOCVAL(LOCALE_SNATIVECTRYNAME,"República Dominicana") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"RD$") +LOCVAL(LOCALE_SINTLSYMBOL, "DOP") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"DO") diff --git a/lib/kernel32/nls/ese.nls b/lib/kernel32/nls/ese.nls new file mode 100644 index 0000000..5cab2a9 --- /dev/null +++ b/lib/kernel32/nls/ese.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Spanish (El Salvador) + * + * (spanish strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"440a") +LOCVAL(LOCALE_SLANGUAGE,"Español (El Salvador)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"ese") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"El Salvador") +LOCVAL(LOCALE_SENGCOUNTRY,"El Salvador") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SLV") +LOCVAL(LOCALE_SNATIVECTRYNAME,"El Salvador") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"C") +LOCVAL(LOCALE_SINTLSYMBOL, "SVC") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SV") diff --git a/lib/kernel32/nls/esf.nls b/lib/kernel32/nls/esf.nls new file mode 100644 index 0000000..1687b80 --- /dev/null +++ b/lib/kernel32/nls/esf.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Ecuador) + */ + +LOCVAL(LOCALE_ILANGUAGE,"300a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esf") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Ecuador") +LOCVAL(LOCALE_SENGCOUNTRY,"Ecuador") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ECU") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Ecuador") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"S") +LOCVAL(LOCALE_SINTLSYMBOL, "ECS") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"EC") diff --git a/lib/kernel32/nls/esg.nls b/lib/kernel32/nls/esg.nls new file mode 100644 index 0000000..e9ac7c2 --- /dev/null +++ b/lib/kernel32/nls/esg.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Spanish (Guatemala) + * (spanish strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"100a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esg") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Guatemala") +LOCVAL(LOCALE_SENGCOUNTRY,"Guatemala") +LOCVAL(LOCALE_SABBREVCTRYNAME,"GTM") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Guatemala") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Q") +LOCVAL(LOCALE_SINTLSYMBOL, "GTQ") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"GT") diff --git a/lib/kernel32/nls/esh.nls b/lib/kernel32/nls/esh.nls new file mode 100644 index 0000000..2754ce0 --- /dev/null +++ b/lib/kernel32/nls/esh.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Honduras) + */ + +LOCVAL(LOCALE_ILANGUAGE,"480a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esh") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Honduras") +LOCVAL(LOCALE_SENGCOUNTRY,"Honduras") +LOCVAL(LOCALE_SABBREVCTRYNAME,"HND") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Honduras") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"L") +LOCVAL(LOCALE_SINTLSYMBOL, "HNL") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"HN") diff --git a/lib/kernel32/nls/esi.nls b/lib/kernel32/nls/esi.nls new file mode 100644 index 0000000..b4b3d44 --- /dev/null +++ b/lib/kernel32/nls/esi.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Spanish (Nicaragua) + */ + +LOCVAL(LOCALE_ILANGUAGE,"4c0a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish") +LOCVAL(LOCALE_SABBREVLANGNAME,"esi") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Nicaragua") +LOCVAL(LOCALE_SENGCOUNTRY,"Nicaragua") +LOCVAL(LOCALE_SABBREVCTRYNAME,"NIC") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Nicaragua") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL, "NIO") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"NI") + diff --git a/lib/kernel32/nls/esl.nls b/lib/kernel32/nls/esl.nls new file mode 100644 index 0000000..9c4a7f3 --- /dev/null +++ b/lib/kernel32/nls/esl.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Chile) + */ + +LOCVAL(LOCALE_ILANGUAGE,"340a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Chile)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Chile)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esl") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Chile") +LOCVAL(LOCALE_SENGCOUNTRY,"Chile") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CHL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Chile") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Ch$") +LOCVAL(LOCALE_SINTLSYMBOL, "CLP") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CL") diff --git a/lib/kernel32/nls/esm.nls b/lib/kernel32/nls/esm.nls new file mode 100644 index 0000000..5c00e47 --- /dev/null +++ b/lib/kernel32/nls/esm.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Mexico + */ + +LOCVAL(LOCALE_ILANGUAGE,"080a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Mexico)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Mexico)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esm") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español (Mexico)") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Mexico") +LOCVAL(LOCALE_SENGCOUNTRY,"Mexico") +LOCVAL(LOCALE_SABBREVCTRYNAME,"MEX") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Mexico") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"$") +LOCVAL(LOCALE_SINTLSYMBOL, "MXN") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"Enero") +LOCVAL(LOCALE_SMONTHNAME2,"Febrero") +LOCVAL(LOCALE_SMONTHNAME3,"Marzo") +LOCVAL(LOCALE_SMONTHNAME4,"Abril") +LOCVAL(LOCALE_SMONTHNAME5,"Mayo") +LOCVAL(LOCALE_SMONTHNAME6,"Junio") +LOCVAL(LOCALE_SMONTHNAME7,"Julio") +LOCVAL(LOCALE_SMONTHNAME8,"Agosto") +LOCVAL(LOCALE_SMONTHNAME9,"Septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"Octubre") +LOCVAL(LOCALE_SMONTHNAME11,"Noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"Diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"May") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"MX") diff --git a/lib/kernel32/nls/esn.nls b/lib/kernel32/nls/esn.nls new file mode 100644 index 0000000..f62cd59 --- /dev/null +++ b/lib/kernel32/nls/esn.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Modern Sort) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c0a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish - Modern Sort") +LOCVAL(LOCALE_SABBREVLANGNAME,"esn") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español (Moderno)") +LOCVAL(LOCALE_ICOUNTRY,"34") +LOCVAL(LOCALE_SCOUNTRY,"España") +LOCVAL(LOCALE_SENGCOUNTRY,"Spain") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ESP") +LOCVAL(LOCALE_SNATIVECTRYNAME,"España") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Pts") +LOCVAL(LOCALE_SINTLSYMBOL, "ESP") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ES") diff --git a/lib/kernel32/nls/eso.nls b/lib/kernel32/nls/eso.nls new file mode 100644 index 0000000..7e8280f --- /dev/null +++ b/lib/kernel32/nls/eso.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Spanish (Colombia) + */ + +LOCVAL(LOCALE_ILANGUAGE,"240a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Colombia)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Colombia)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esg") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Colombia") +LOCVAL(LOCALE_SENGCOUNTRY,"Colombia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"COL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Colombia") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"C$") +LOCVAL(LOCALE_SINTLSYMBOL, "COP") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CO") + diff --git a/lib/kernel32/nls/esp.nls b/lib/kernel32/nls/esp.nls new file mode 100644 index 0000000..df238c7 --- /dev/null +++ b/lib/kernel32/nls/esp.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Traditional Sort) + */ + +LOCVAL(LOCALE_ILANGUAGE,"040a") +LOCVAL(LOCALE_SLANGUAGE,"Español") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish - Traditional Sort") +LOCVAL(LOCALE_SABBREVLANGNAME,"esp") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +LOCVAL(LOCALE_ICOUNTRY,"34") +LOCVAL(LOCALE_SCOUNTRY,"España") +LOCVAL(LOCALE_SENGCOUNTRY,"Spain") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ESP") +LOCVAL(LOCALE_SNATIVECTRYNAME,"España") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Pts") +LOCVAL(LOCALE_SINTLSYMBOL, "ESP") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ES") diff --git a/lib/kernel32/nls/esperanto.nls b/lib/kernel32/nls/esperanto.nls new file mode 100644 index 0000000..b4a572e --- /dev/null +++ b/lib/kernel32/nls/esperanto.nls @@ -0,0 +1,129 @@ +/* + * OLE2NLS library + * Esperanto + * + * Esperanto seems not to be supported by Windows + * + * TODO: MS numerical ID for language ? + * + * I choose 0x8f for esperanto language as it is high enough + * not to be attributed to another language in the immediate + * future (as of 19980901 the last official languageID is 0x51) + * + * No Windows 125[0-8] codepage has the c^ g^ h^ j^ s^ used by esperanto. + * And for DOS codepage ? + * + * ISO 2 letter code for esperanto is "eo" but as Windows use + * three letter codes I added an "x" to the end. + * + * (esperanto strings in iso-8859-3) + */ + +LOCVAL(LOCALE_ILANGUAGE,"048f") +LOCVAL(LOCALE_SLANGUAGE,"Esperanto") +LOCVAL(LOCALE_SENGLANGUAGE,"Esperanto") +LOCVAL(LOCALE_SABBREVLANGNAME,"eox") +LOCVAL(LOCALE_SNATIVELANGNAME,"Esperanto") +/* LOCVAL(LOCALE_ICOUNTRY,"") not official in any one country */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +/* LOCVAL(LOCALE_SENGCOUNTRY,"") */ +/* LOCVAL(LOCALE_SABBREVCTRYNAME,"") */ +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"048f") /* MS LANGID TODO */ +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE,"") */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"") */ +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* euro symbol; it is 0xa4 in iso-8859-15 and 0x80 in cp1252 */ +LOCVAL(LOCALE_SCURRENCY,"¤") +LOCVAL(LOCALE_SINTLSYMBOL,"EMU") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"yyyy.mm.dd") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lundo") +LOCVAL(LOCALE_SDAYNAME2,"mardo") +LOCVAL(LOCALE_SDAYNAME3,"merkredo") +LOCVAL(LOCALE_SDAYNAME4,"¼aýdo") +LOCVAL(LOCALE_SDAYNAME5,"vendredo") +LOCVAL(LOCALE_SDAYNAME6,"sabato") +LOCVAL(LOCALE_SDAYNAME7,"dimanæo") +LOCVAL(LOCALE_SABBREVDAYNAME1,"lu") +LOCVAL(LOCALE_SABBREVDAYNAME2,"ma") +LOCVAL(LOCALE_SABBREVDAYNAME3,"me") +LOCVAL(LOCALE_SABBREVDAYNAME4,"¼a") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ve") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"di") + +LOCVAL(LOCALE_SMONTHNAME1,"januaro") +LOCVAL(LOCALE_SMONTHNAME2,"februaro") +LOCVAL(LOCALE_SMONTHNAME3,"marto") +LOCVAL(LOCALE_SMONTHNAME4,"aprilo") +LOCVAL(LOCALE_SMONTHNAME5,"majo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"aýgusto") +LOCVAL(LOCALE_SMONTHNAME9,"septembro") +LOCVAL(LOCALE_SMONTHNAME10,"oktobro") +LOCVAL(LOCALE_SMONTHNAME11,"novembro") +LOCVAL(LOCALE_SMONTHNAME12,"decembro") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aýg") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"eo") +/* LOCVAL(LOCALE_SISO3166CTRYNAME, "") */ + diff --git a/lib/kernel32/nls/esr.nls b/lib/kernel32/nls/esr.nls new file mode 100644 index 0000000..6aaddc6 --- /dev/null +++ b/lib/kernel32/nls/esr.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Peru) + */ + +LOCVAL(LOCALE_ILANGUAGE,"280a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Perú)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Peru)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esf") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Perú") +LOCVAL(LOCALE_SENGCOUNTRY,"Peru") +LOCVAL(LOCALE_SABBREVCTRYNAME,"PER") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Perú") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"S") +LOCVAL(LOCALE_SINTLSYMBOL, "PES") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"PE") diff --git a/lib/kernel32/nls/ess.nls b/lib/kernel32/nls/ess.nls new file mode 100644 index 0000000..5685cfb --- /dev/null +++ b/lib/kernel32/nls/ess.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Argentina) + */ + +LOCVAL(LOCALE_ILANGUAGE,"2c0a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Argentina)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Argentina)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esg") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Argentina") +LOCVAL(LOCALE_SENGCOUNTRY,"Argentina") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ARG") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Argentina") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"$") +LOCVAL(LOCALE_SINTLSYMBOL, "ARS") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"AR") diff --git a/lib/kernel32/nls/est.nls b/lib/kernel32/nls/est.nls new file mode 100644 index 0000000..0fcb419 --- /dev/null +++ b/lib/kernel32/nls/est.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Estonia + * + * (estonian strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0425") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Estonian") +LOCVAL(LOCALE_SABBREVLANGNAME,"est") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Estonia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"EST") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0425") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"EEK") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"esmaspäev") +LOCVAL(LOCALE_SDAYNAME2,"teisipäev") +LOCVAL(LOCALE_SDAYNAME3,"kolmapäev") +LOCVAL(LOCALE_SDAYNAME4,"meljapäev") +LOCVAL(LOCALE_SDAYNAME5,"reede") +LOCVAL(LOCALE_SDAYNAME6,"laupäev") +LOCVAL(LOCALE_SDAYNAME7,"pühapäev") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"E") +LOCVAL(LOCALE_SABBREVDAYNAME2,"T") +LOCVAL(LOCALE_SABBREVDAYNAME3,"K") +LOCVAL(LOCALE_SABBREVDAYNAME4,"N") +LOCVAL(LOCALE_SABBREVDAYNAME5,"R") +LOCVAL(LOCALE_SABBREVDAYNAME6,"L") +LOCVAL(LOCALE_SABBREVDAYNAME7,"P") + +LOCVAL(LOCALE_SMONTHNAME1,"jaanuar") +LOCVAL(LOCALE_SMONTHNAME2,"veebruar") +LOCVAL(LOCALE_SMONTHNAME3,"märts") +LOCVAL(LOCALE_SMONTHNAME4,"aprill") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juuni") +LOCVAL(LOCALE_SMONTHNAME7,"juuli") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktoober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"detsember") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jaan ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"veebr") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"märts") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai ") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"juuni") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"juuli") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sept ") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov ") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dets ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"et") +LOCVAL(LOCALE_SISO3166CTRYNAME,"EE") + diff --git a/lib/kernel32/nls/esu.nls b/lib/kernel32/nls/esu.nls new file mode 100644 index 0000000..f4f36b4 --- /dev/null +++ b/lib/kernel32/nls/esu.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Spanish (Puerto Rico) + */ + +LOCVAL(LOCALE_ILANGUAGE,"500a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Puerto Rico)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Puerto Rico)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esu") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español (Puerto Rico)") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Puerto Rico") +LOCVAL(LOCALE_SENGCOUNTRY,"Puerto Rico") +LOCVAL(LOCALE_SABBREVCTRYNAME,"PRI") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Puerto Rico") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"PR") diff --git a/lib/kernel32/nls/esv.nls b/lib/kernel32/nls/esv.nls new file mode 100644 index 0000000..41cd497 --- /dev/null +++ b/lib/kernel32/nls/esv.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Spanish (Venezuela) + */ + +LOCVAL(LOCALE_ILANGUAGE,"200a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Venezuela)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Venezuela)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esv") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español (Venezuela)") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Venezuela") +LOCVAL(LOCALE_SENGCOUNTRY,"Venezuela") +LOCVAL(LOCALE_SABBREVCTRYNAME,"VEN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Venezuela") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Bs") +LOCVAL(LOCALE_SINTLSYMBOL, "VEB") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"VE") + diff --git a/lib/kernel32/nls/esy.nls b/lib/kernel32/nls/esy.nls new file mode 100644 index 0000000..63a721a --- /dev/null +++ b/lib/kernel32/nls/esy.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Spanish (Uruguay) + */ + +LOCVAL(LOCALE_ILANGUAGE,"380a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Uruguay)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Uruguay)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esy") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español (Uruguay)") +LOCVAL(LOCALE_ICOUNTRY,"598") +LOCVAL(LOCALE_SCOUNTRY,"Uruguay") +LOCVAL(LOCALE_SENGCOUNTRY,"Uruguay") +LOCVAL(LOCALE_SABBREVCTRYNAME,"URY") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Uruguay") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"380a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"U$S") +LOCVAL(LOCALE_SINTLSYMBOL, "UYU") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d de MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"UY") + diff --git a/lib/kernel32/nls/esz.nls b/lib/kernel32/nls/esz.nls new file mode 100644 index 0000000..954b44f --- /dev/null +++ b/lib/kernel32/nls/esz.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Spanish (Paraguay) + */ + +LOCVAL(LOCALE_ILANGUAGE,"3c0a") +LOCVAL(LOCALE_SLANGUAGE,"Español (Paraguay)") +LOCVAL(LOCALE_SENGLANGUAGE,"Spanish (Paraguay)") +LOCVAL(LOCALE_SABBREVLANGNAME,"esz") +LOCVAL(LOCALE_SNATIVELANGNAME,"Español (Paraguay)") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Paraguay") +LOCVAL(LOCALE_SENGCOUNTRY,"Paraguay") +LOCVAL(LOCALE_SABBREVCTRYNAME,"PRY") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Paraguay") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040a") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"G") +LOCVAL(LOCALE_SINTLSYMBOL, "PYG") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunes") +LOCVAL(LOCALE_SDAYNAME2,"martes") +LOCVAL(LOCALE_SDAYNAME3,"miércoles") +LOCVAL(LOCALE_SDAYNAME4,"jueves") +LOCVAL(LOCALE_SDAYNAME5,"viernes") +LOCVAL(LOCALE_SDAYNAME6,"sábado") +LOCVAL(LOCALE_SDAYNAME7,"domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mié") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jue") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vie") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sáb") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"enero") +LOCVAL(LOCALE_SMONTHNAME2,"febrero") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"abril") +LOCVAL(LOCALE_SMONTHNAME5,"mayo") +LOCVAL(LOCALE_SMONTHNAME6,"junio") +LOCVAL(LOCALE_SMONTHNAME7,"julio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"septiembre") +LOCVAL(LOCALE_SMONTHNAME10,"octubre") +LOCVAL(LOCALE_SMONTHNAME11,"noviembre") +LOCVAL(LOCALE_SMONTHNAME12,"diciembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ene") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"may") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"es") +LOCVAL(LOCALE_SISO3166CTRYNAME,"PY") + diff --git a/lib/kernel32/nls/euq.nls b/lib/kernel32/nls/euq.nls new file mode 100644 index 0000000..94279a4 --- /dev/null +++ b/lib/kernel32/nls/euq.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Basque + * + * email: srtxg@chanae.alphanet.ch + */ + +LOCVAL(LOCALE_ILANGUAGE,"042d") +LOCVAL(LOCALE_SLANGUAGE,"Euskara") +LOCVAL(LOCALE_SENGLANGUAGE,"Basque") +LOCVAL(LOCALE_SABBREVLANGNAME,"euq") +LOCVAL(LOCALE_SNATIVELANGNAME,"Euskara") +LOCVAL(LOCALE_ICOUNTRY,"34") +LOCVAL(LOCALE_SCOUNTRY,"Espainia") +LOCVAL(LOCALE_SENGCOUNTRY,"Spain (Basque)") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ESP") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Espainia") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"04d2") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"34") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Pts") +LOCVAL(LOCALE_SINTLSYMBOL, "ESP") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"-") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"yyyy-MM-dd") +LOCVAL(LOCALE_SLONGDATE,"ddd, yyyyko MMMMren d.a") +LOCVAL(LOCALE_STIMEFORMAT, "HH:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"astelehena") +LOCVAL(LOCALE_SDAYNAME2,"asteartea") +LOCVAL(LOCALE_SDAYNAME3,"asteazkena") +LOCVAL(LOCALE_SDAYNAME4,"osteguna") +LOCVAL(LOCALE_SDAYNAME5,"ostirala") +LOCVAL(LOCALE_SDAYNAME6,"larunbata") +LOCVAL(LOCALE_SDAYNAME7,"igandea") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"leh") +LOCVAL(LOCALE_SABBREVDAYNAME2,"art") +LOCVAL(LOCALE_SABBREVDAYNAME3,"azk") +LOCVAL(LOCALE_SABBREVDAYNAME4,"teg") +LOCVAL(LOCALE_SABBREVDAYNAME5,"tir") +LOCVAL(LOCALE_SABBREVDAYNAME6,"lar") +LOCVAL(LOCALE_SABBREVDAYNAME7,"iga") + +LOCVAL(LOCALE_SMONTHNAME1,"urtarrila") +LOCVAL(LOCALE_SMONTHNAME2,"otsaila") +LOCVAL(LOCALE_SMONTHNAME3,"martxoa") +LOCVAL(LOCALE_SMONTHNAME4,"apirila") +LOCVAL(LOCALE_SMONTHNAME5,"maiatza") +LOCVAL(LOCALE_SMONTHNAME6,"ekaina") +LOCVAL(LOCALE_SMONTHNAME7,"uztaila") +LOCVAL(LOCALE_SMONTHNAME8,"abuztua") +LOCVAL(LOCALE_SMONTHNAME9,"iraila") +LOCVAL(LOCALE_SMONTHNAME10,"urria") +LOCVAL(LOCALE_SMONTHNAME11,"azaroa") +LOCVAL(LOCALE_SMONTHNAME12,"abendua") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"urt") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"ots") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"api") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"eka") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"uzt") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"abu") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"ira") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"urr") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"aza") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"abe") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"eu") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ES") + diff --git a/lib/kernel32/nls/fin.nls b/lib/kernel32/nls/fin.nls new file mode 100644 index 0000000..a94cfee --- /dev/null +++ b/lib/kernel32/nls/fin.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Finland + */ + +LOCVAL(LOCALE_ILANGUAGE,"040b") +LOCVAL(LOCALE_SLANGUAGE,"Suomi") +LOCVAL(LOCALE_SENGLANGUAGE,"Finnish") +LOCVAL(LOCALE_SABBREVLANGNAME,"fin") +LOCVAL(LOCALE_SNATIVELANGNAME,"suomi") +LOCVAL(LOCALE_ICOUNTRY,"358") +LOCVAL(LOCALE_SCOUNTRY,"Suomi") +LOCVAL(LOCALE_SENGCOUNTRY,"Finland") +LOCVAL(LOCALE_SABBREVCTRYNAME,"FIN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Suomi") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040b") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"358") +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"mk") +LOCVAL(LOCALE_SINTLSYMBOL,"FIM") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"maanantai") +LOCVAL(LOCALE_SDAYNAME2,"tiistai") +LOCVAL(LOCALE_SDAYNAME3,"keskiviikko") +LOCVAL(LOCALE_SDAYNAME4,"torstai") +LOCVAL(LOCALE_SDAYNAME5,"perjantai") +LOCVAL(LOCALE_SDAYNAME6,"lauantai") +LOCVAL(LOCALE_SDAYNAME7,"sunnuntai") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Ma") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ti") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ke") +LOCVAL(LOCALE_SABBREVDAYNAME4,"To") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Pe") +LOCVAL(LOCALE_SABBREVDAYNAME6,"La") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Su") + +LOCVAL(LOCALE_SMONTHNAME1,"tammikuu") +LOCVAL(LOCALE_SMONTHNAME2,"helmikuu") +LOCVAL(LOCALE_SMONTHNAME3,"maaliskuu") +LOCVAL(LOCALE_SMONTHNAME4,"huhtikuu") +LOCVAL(LOCALE_SMONTHNAME5,"toukokuu") +LOCVAL(LOCALE_SMONTHNAME6,"kesäkuu") +LOCVAL(LOCALE_SMONTHNAME7,"heinäkuu") +LOCVAL(LOCALE_SMONTHNAME8,"elokuu") +LOCVAL(LOCALE_SMONTHNAME9,"syyskuu") +LOCVAL(LOCALE_SMONTHNAME10,"lokakuu") +LOCVAL(LOCALE_SMONTHNAME11,"marraskuu") +LOCVAL(LOCALE_SMONTHNAME12,"joulukuu") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"tammi") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"helmi") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"maalis") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"huhti") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"touko") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"kesä") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"heinä") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"elo") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"syys") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"loka") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"marras") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"joulu") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fi") +LOCVAL(LOCALE_SISO3166CTRYNAME,"FI") diff --git a/lib/kernel32/nls/fos.nls b/lib/kernel32/nls/fos.nls new file mode 100644 index 0000000..641509d --- /dev/null +++ b/lib/kernel32/nls/fos.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Faroe Islands + * + * (faroese strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0438") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Faroese") +LOCVAL(LOCALE_SABBREVLANGNAME,"fos") +LOCVAL(LOCALE_SNATIVELANGNAME,"færoyskt") +LOCVAL(LOCALE_ICOUNTRY,"298") +LOCVAL(LOCALE_SCOUNTRY,"") +LOCVAL(LOCALE_SENGCOUNTRY,"Faroe Islands") +LOCVAL(LOCALE_SABBREVCTRYNAME,"FRO") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Froyar") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0438") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"40") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE,"851") */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"kr") +LOCVAL(LOCALE_SINTLSYMBOL, "DKK") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"mánadagur") +LOCVAL(LOCALE_SDAYNAME2,"týsdagur") +LOCVAL(LOCALE_SDAYNAME3,"mikudagur") +LOCVAL(LOCALE_SDAYNAME4,"hósdagur") +LOCVAL(LOCALE_SDAYNAME5,"fríggjadagur") +LOCVAL(LOCALE_SDAYNAME6,"leygardagur") +LOCVAL(LOCALE_SDAYNAME7,"sunnudagur") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"mán") +LOCVAL(LOCALE_SABBREVDAYNAME2,"týs") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mik") +LOCVAL(LOCALE_SABBREVDAYNAME4,"hós") +LOCVAL(LOCALE_SABBREVDAYNAME5,"frí") +LOCVAL(LOCALE_SABBREVDAYNAME6,"ley") +LOCVAL(LOCALE_SABBREVDAYNAME7,"sun") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februar") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"desember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"des") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fo") +LOCVAL(LOCALE_SISO3166CTRYNAME,"FO") diff --git a/lib/kernel32/nls/fra.nls b/lib/kernel32/nls/fra.nls new file mode 100644 index 0000000..48902dd --- /dev/null +++ b/lib/kernel32/nls/fra.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * France + */ + +LOCVAL(LOCALE_ILANGUAGE,"040c") +LOCVAL(LOCALE_SLANGUAGE,"Français") +LOCVAL(LOCALE_SENGLANGUAGE,"French") +LOCVAL(LOCALE_SABBREVLANGNAME,"fra") +LOCVAL(LOCALE_SNATIVELANGNAME,"Français") +LOCVAL(LOCALE_ICOUNTRY,"33") +LOCVAL(LOCALE_SCOUNTRY,"France") +LOCVAL(LOCALE_SENGCOUNTRY,"France") +LOCVAL(LOCALE_SABBREVCTRYNAME,"FRA") +LOCVAL(LOCALE_SNATIVECTRYNAME,"France") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040c") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"33") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND," ") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"F") +LOCVAL(LOCALE_SINTLSYMBOL, "FRF") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd d MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "hh:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1,"lundi") +LOCVAL(LOCALE_SDAYNAME2,"mardi") +LOCVAL(LOCALE_SDAYNAME3,"mercredi") +LOCVAL(LOCALE_SDAYNAME4,"jeudi") +LOCVAL(LOCALE_SDAYNAME5,"vendredi") +LOCVAL(LOCALE_SDAYNAME6,"samedi") +LOCVAL(LOCALE_SDAYNAME7,"dimanche") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mer") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jeu") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ven") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sam") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dim") + +LOCVAL(LOCALE_SMONTHNAME1,"janvier") +LOCVAL(LOCALE_SMONTHNAME2,"février") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"avril") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juin") +LOCVAL(LOCALE_SMONTHNAME7,"juillet") +LOCVAL(LOCALE_SMONTHNAME8,"août") +LOCVAL(LOCALE_SMONTHNAME9,"septembre") +LOCVAL(LOCALE_SMONTHNAME10,"octobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"décembre") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"fév") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"avr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aoû") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"déc") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"FR") diff --git a/lib/kernel32/nls/frb.nls b/lib/kernel32/nls/frb.nls new file mode 100644 index 0000000..9502d20 --- /dev/null +++ b/lib/kernel32/nls/frb.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Belgium + */ + +LOCVAL(LOCALE_ILANGUAGE,"080c") +LOCVAL(LOCALE_SLANGUAGE,"Français (Belgique)") +LOCVAL(LOCALE_SENGLANGUAGE,"French (Belgium)") +LOCVAL(LOCALE_SABBREVLANGNAME,"frb") +LOCVAL(LOCALE_SNATIVELANGNAME,"Français (Belgique)") +LOCVAL(LOCALE_ICOUNTRY,"32") +LOCVAL(LOCALE_SCOUNTRY,"Belgique") +LOCVAL(LOCALE_SENGCOUNTRY,"Belgium") +LOCVAL(LOCALE_SABBREVCTRYNAME,"BEL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Belgique") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040c") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"33") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND," ") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"FB") +LOCVAL(LOCALE_SINTLSYMBOL, "BEF") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd d MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "hh:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1,"lundi") +LOCVAL(LOCALE_SDAYNAME2,"mardi") +LOCVAL(LOCALE_SDAYNAME3,"mercredi") +LOCVAL(LOCALE_SDAYNAME4,"jeudi") +LOCVAL(LOCALE_SDAYNAME5,"vendredi") +LOCVAL(LOCALE_SDAYNAME6,"samedi") +LOCVAL(LOCALE_SDAYNAME7,"dimanche") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mer") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jeu") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ven") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sam") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dim") + +LOCVAL(LOCALE_SMONTHNAME1,"janvier") +LOCVAL(LOCALE_SMONTHNAME2,"février") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"avril") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juin") +LOCVAL(LOCALE_SMONTHNAME7,"juillet") +LOCVAL(LOCALE_SMONTHNAME8,"août") +LOCVAL(LOCALE_SMONTHNAME9,"septembre") +LOCVAL(LOCALE_SMONTHNAME10,"octobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"décembre") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"fév") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"avr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aoû") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"déc") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BE") diff --git a/lib/kernel32/nls/frc.nls b/lib/kernel32/nls/frc.nls new file mode 100644 index 0000000..b03995b --- /dev/null +++ b/lib/kernel32/nls/frc.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Canada (French) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c0c") +LOCVAL(LOCALE_SLANGUAGE,"Français (Canada)") +LOCVAL(LOCALE_SENGLANGUAGE,"French (Canada)") +LOCVAL(LOCALE_SABBREVLANGNAME,"frc") +LOCVAL(LOCALE_SNATIVELANGNAME,"français") +LOCVAL(LOCALE_ICOUNTRY,"2") +LOCVAL(LOCALE_SCOUNTRY,"Canada") +LOCVAL(LOCALE_SENGCOUNTRY,"Canada") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CAN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Canada") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040c") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"2") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"863") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND," ") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"$") +LOCVAL(LOCALE_SINTLSYMBOL, "CAD") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP," ") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"d MMMM, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "hh:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +/* LOCVAL(LOCALE_ITIME,"1") */ +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO,"1") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1,"lundi") +LOCVAL(LOCALE_SDAYNAME2,"mardi") +LOCVAL(LOCALE_SDAYNAME3,"mercredi") +LOCVAL(LOCALE_SDAYNAME4,"jeudi") +LOCVAL(LOCALE_SDAYNAME5,"vendredi") +LOCVAL(LOCALE_SDAYNAME6,"samedi") +LOCVAL(LOCALE_SDAYNAME7,"dimanche") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mer") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jeu") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ven") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sam") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dim") + +LOCVAL(LOCALE_SMONTHNAME1,"janvier") +LOCVAL(LOCALE_SMONTHNAME2,"février") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"avril") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juin") +LOCVAL(LOCALE_SMONTHNAME7,"juillet") +LOCVAL(LOCALE_SMONTHNAME8,"août") +LOCVAL(LOCALE_SMONTHNAME9,"septembre") +LOCVAL(LOCALE_SMONTHNAME10,"octobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"décembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"janv") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"févr") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mars") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"avr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"juin") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"juil") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"août") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sept") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"déc") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CA") diff --git a/lib/kernel32/nls/frl.nls b/lib/kernel32/nls/frl.nls new file mode 100644 index 0000000..4c6414b --- /dev/null +++ b/lib/kernel32/nls/frl.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Luxemburg (French) + */ + +LOCVAL(LOCALE_ILANGUAGE,"140c") +LOCVAL(LOCALE_SLANGUAGE,"Français (Luxembourg)") +LOCVAL(LOCALE_SENGLANGUAGE,"French (Luxembourg)") +LOCVAL(LOCALE_SABBREVLANGNAME,"frl") +LOCVAL(LOCALE_SNATIVELANGNAME,"français") +LOCVAL(LOCALE_ICOUNTRY,"352") +LOCVAL(LOCALE_SCOUNTRY,"Luxembourg") +LOCVAL(LOCALE_SENGCOUNTRY,"Luxemburg") +LOCVAL(LOCALE_SABBREVCTRYNAME,"LUX") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Luxembourg") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040c") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"33") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND," ") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"F") +LOCVAL(LOCALE_SINTLSYMBOL, "LUF") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd d MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "hh:mm:ss") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1,"lundi") +LOCVAL(LOCALE_SDAYNAME2,"mardi") +LOCVAL(LOCALE_SDAYNAME3,"mercredi") +LOCVAL(LOCALE_SDAYNAME4,"jeudi") +LOCVAL(LOCALE_SDAYNAME5,"vendredi") +LOCVAL(LOCALE_SDAYNAME6,"samedi") +LOCVAL(LOCALE_SDAYNAME7,"dimanche") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mer") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jeu") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ven") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sam") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dim") + +LOCVAL(LOCALE_SMONTHNAME1,"janvier") +LOCVAL(LOCALE_SMONTHNAME2,"février") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"avril") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juin") +LOCVAL(LOCALE_SMONTHNAME7,"juillet") +LOCVAL(LOCALE_SMONTHNAME8,"août") +LOCVAL(LOCALE_SMONTHNAME9,"septembre") +LOCVAL(LOCALE_SMONTHNAME10,"octobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"décembre") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"janv") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"févr") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mars") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"avr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"juin") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"juil") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"août") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sept") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"déc") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"LU") + +/* calendrier grégorien */ diff --git a/lib/kernel32/nls/frs.nls b/lib/kernel32/nls/frs.nls new file mode 100644 index 0000000..f2417d6 --- /dev/null +++ b/lib/kernel32/nls/frs.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Switzerland (French) + */ + +LOCVAL(LOCALE_ILANGUAGE,"100c") +LOCVAL(LOCALE_SLANGUAGE,"Français (Suisse)") +LOCVAL(LOCALE_SENGLANGUAGE,"French (Switzerland)") +LOCVAL(LOCALE_SABBREVLANGNAME,"frs") +LOCVAL(LOCALE_SNATIVELANGNAME,"Français (Suisse)") +LOCVAL(LOCALE_ICOUNTRY,"41") +LOCVAL(LOCALE_SCOUNTRY,"Suisse") +LOCVAL(LOCALE_SENGCOUNTRY,"Switzerland") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CHE") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Suisse") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040c") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"33") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"SFr") +LOCVAL(LOCALE_SINTLSYMBOL, "CHF") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lundi") +LOCVAL(LOCALE_SDAYNAME2,"mardi") +LOCVAL(LOCALE_SDAYNAME3,"mercredi") +LOCVAL(LOCALE_SDAYNAME4,"jeudi") +LOCVAL(LOCALE_SDAYNAME5,"vendredi") +LOCVAL(LOCALE_SDAYNAME6,"samedi") +LOCVAL(LOCALE_SDAYNAME7,"dimanche") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mer") +LOCVAL(LOCALE_SABBREVDAYNAME4,"jeu") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ven") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sam") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dim") + +LOCVAL(LOCALE_SMONTHNAME1,"janvier") +LOCVAL(LOCALE_SMONTHNAME2,"février") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"avril") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juin") +LOCVAL(LOCALE_SMONTHNAME7,"juillet") +LOCVAL(LOCALE_SMONTHNAME8,"août") +LOCVAL(LOCALE_SMONTHNAME9,"septembre") +LOCVAL(LOCALE_SMONTHNAME10,"octobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"décembre") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"fév") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"avr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aoû") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"déc") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"fr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CH") + +/* calendrier grégorien */ diff --git a/lib/kernel32/nls/grc.nls b/lib/kernel32/nls/grc.nls new file mode 100644 index 0000000..31977e9 --- /dev/null +++ b/lib/kernel32/nls/grc.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Greek + * (Greek strings in cp1253) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0408") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Greek") +LOCVAL(LOCALE_SABBREVLANGNAME,"grc") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +LOCVAL(LOCALE_ICOUNTRY,"30") +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Greece") +LOCVAL(LOCALE_SABBREVCTRYNAME,"GRC") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0408") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"30") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"737") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1253") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"äñ÷") +LOCVAL(LOCALE_SINTLSYMBOL, "GRD") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÄåõôÝñá") +LOCVAL(LOCALE_SDAYNAME2,"Ôñßôç") +LOCVAL(LOCALE_SDAYNAME3,"ÔåôÜñôç") +LOCVAL(LOCALE_SDAYNAME4,"ÐÝìðôç") +LOCVAL(LOCALE_SDAYNAME5,"ÐáñáóêåõÞ") +LOCVAL(LOCALE_SDAYNAME6,"ÓáââÜôï") +LOCVAL(LOCALE_SDAYNAME7,"Êõñéáêç") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Äåõ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ôñé") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Ôåô") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Ðåì") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ðáñ") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Óáâ") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Êõñ") + +LOCVAL(LOCALE_SMONTHNAME1,"ÉáíïÜñéïò") +LOCVAL(LOCALE_SMONTHNAME2,"ÖåâñïÜñéïò") +LOCVAL(LOCALE_SMONTHNAME3,"ÌÜñôéïò") +LOCVAL(LOCALE_SMONTHNAME4,"Áðñßëéïò") +LOCVAL(LOCALE_SMONTHNAME5,"ÌÜéïò") +LOCVAL(LOCALE_SMONTHNAME6,"Éïýíéïò") +LOCVAL(LOCALE_SMONTHNAME7,"Éïýëéïò") +LOCVAL(LOCALE_SMONTHNAME8,"Áýãïõóôïò") +LOCVAL(LOCALE_SMONTHNAME9,"ÓåðôÝìâñéïò") +LOCVAL(LOCALE_SMONTHNAME10,"Ïêôþâñéïò") +LOCVAL(LOCALE_SMONTHNAME11,"ÍïÝìâñéïò") +LOCVAL(LOCALE_SMONTHNAME12,"ÄåêÝìâñéïò") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Éáí") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Öåâ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"ÌÜñ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Áðñ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"ÌÜé") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Éïýí") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Éïýë") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Áýã") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Óåð") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Ïêô") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"ÍïÝ") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Äåê") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"el") +LOCVAL(LOCALE_SISO3166CTRYNAME,"GR") + diff --git a/lib/kernel32/nls/hkg.nls b/lib/kernel32/nls/hkg.nls new file mode 100644 index 0000000..47fbfd7 --- /dev/null +++ b/lib/kernel32/nls/hkg.nls @@ -0,0 +1,110 @@ +/* + * OLE2NLS library + * Chinese (Hong Kong) + */ + +/* LOCVAL(LOCALE_ILANGUAGE,"") */ +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +/* LOCVAL(LOCALE_SENGLANGUAGE,"Chinese (Hong Kong)") */ +LOCVAL(LOCALE_SABBREVLANGNAME,"hkg") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +/* LOCVAL(LOCALE_SENGCOUNTRY,"") */ +/* LOCVAL(LOCALE_SABBREVCTRYNAME,"") */ +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +/* LOCVAL(LOCALE_IDEFAULTLANGUAGE,"") */ +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +/* LOCVAL(LOCALE_SINTLSYMBOL) */ +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +/* LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +/* LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +/* LOCVAL(LOCALE_ICALENDARTYPE) */ +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"Ma") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"Ti") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"On") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"To") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"Lø") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"Sø") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ + diff --git a/lib/kernel32/nls/hrv.nls b/lib/kernel32/nls/hrv.nls new file mode 100644 index 0000000..2203889 --- /dev/null +++ b/lib/kernel32/nls/hrv.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Croatia + * (Croatian strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"041a") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Croatian") +LOCVAL(LOCALE_SABBREVLANGNAME,"hrv") +LOCVAL(LOCALE_SNATIVELANGNAME,"hrvatski") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Croatia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"HRV") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Hrvatska") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"041a") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"Din") +LOCVAL(LOCALE_SINTLSYMBOL,"HRD") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ponedeljak") +LOCVAL(LOCALE_SDAYNAME2,"utorak") +LOCVAL(LOCALE_SDAYNAME3,"sreda") +LOCVAL(LOCALE_SDAYNAME4,"èetvrtak") +LOCVAL(LOCALE_SDAYNAME5,"petak") +LOCVAL(LOCALE_SDAYNAME6,"subota") +LOCVAL(LOCALE_SDAYNAME7,"nedelja") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"pon") +LOCVAL(LOCALE_SABBREVDAYNAME2,"tor") +LOCVAL(LOCALE_SABBREVDAYNAME3,"sre") +LOCVAL(LOCALE_SABBREVDAYNAME4,"èet") +LOCVAL(LOCALE_SABBREVDAYNAME5,"pet") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sub") +LOCVAL(LOCALE_SABBREVDAYNAME7,"ned") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februar") +LOCVAL(LOCALE_SMONTHNAME3,"mart") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"maj") +LOCVAL(LOCALE_SMONTHNAME6,"jun") +LOCVAL(LOCALE_SMONTHNAME7,"jul") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"septembar") +LOCVAL(LOCALE_SMONTHNAME10,"oktobar") +LOCVAL(LOCALE_SMONTHNAME11,"novembar") +LOCVAL(LOCALE_SMONTHNAME12,"decembar") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"hr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"HR") + +/* Gregorijanski kalendar */ diff --git a/lib/kernel32/nls/hun.nls b/lib/kernel32/nls/hun.nls new file mode 100644 index 0000000..8df129a --- /dev/null +++ b/lib/kernel32/nls/hun.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Hungarian + * (Hungarian strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"040e") +LOCVAL(LOCALE_SLANGUAGE,"Magyar") +LOCVAL(LOCALE_SENGLANGUAGE,"Hungarian") +LOCVAL(LOCALE_SABBREVLANGNAME,"hun") +LOCVAL(LOCALE_SNATIVELANGNAME,"Magyar") +LOCVAL(LOCALE_ICOUNTRY,"36") +LOCVAL(LOCALE_SCOUNTRY,"Magyarország") +LOCVAL(LOCALE_SENGCOUNTRY,"Hungary") +LOCVAL(LOCALE_SABBREVCTRYNAME,"HUN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Magyarország") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040e") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"36") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"852") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,".") +LOCVAL(LOCALE_STHOUSAND,",") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Ft") +LOCVAL(LOCALE_SINTLSYMBOL,"HUF") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"0") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"yyyy.MM.dd") +LOCVAL(LOCALE_SLONGDATE,"ddd, yyyy. MMMM d") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Hétfõ") +LOCVAL(LOCALE_SDAYNAME2,"Kedd") +LOCVAL(LOCALE_SDAYNAME3,"Szerda") +LOCVAL(LOCALE_SDAYNAME4,"Csütörtök") +LOCVAL(LOCALE_SDAYNAME5,"Péntek") +LOCVAL(LOCALE_SDAYNAME6,"Szombat") +LOCVAL(LOCALE_SDAYNAME7,"Vasárnap") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Hé") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ke") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Se") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Cs") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Pé") +LOCVAL(LOCALE_SABBREVDAYNAME6,"So") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Va") + +LOCVAL(LOCALE_SMONTHNAME1,"Január") +LOCVAL(LOCALE_SMONTHNAME2,"Február") +LOCVAL(LOCALE_SMONTHNAME3,"Március") +LOCVAL(LOCALE_SMONTHNAME4,"Április") +LOCVAL(LOCALE_SMONTHNAME5,"Május") +LOCVAL(LOCALE_SMONTHNAME6,"Június") +LOCVAL(LOCALE_SMONTHNAME7,"Július") +LOCVAL(LOCALE_SMONTHNAME8,"Augusztus") +LOCVAL(LOCALE_SMONTHNAME9,"Szeptember") +LOCVAL(LOCALE_SMONTHNAME10,"Október") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"December") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Már") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Ápr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Máj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jún") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Júl") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sze") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"hu") +LOCVAL(LOCALE_SISO3166CTRYNAME,"HU") + diff --git a/lib/kernel32/nls/ind.nls b/lib/kernel32/nls/ind.nls new file mode 100644 index 0000000..603b147 --- /dev/null +++ b/lib/kernel32/nls/ind.nls @@ -0,0 +1,112 @@ +/* + * OLE2NLS library + * Indonesia (Bahasa) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0421") +LOCVAL(LOCALE_SLANGUAGE,"Bahasa Indonesia") +LOCVAL(LOCALE_SENGLANGUAGE,"Bahasa (Indonesia)") +LOCVAL(LOCALE_SABBREVLANGNAME,"ind") +LOCVAL(LOCALE_SNATIVELANGNAME,"Bahasa Indonesia") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Indonesia") +LOCVAL(LOCALE_SENGCOUNTRY,"Indonesia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"IDN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Indonesia") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0421") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"IDR") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"hari senin") +LOCVAL(LOCALE_SDAYNAME2,"hari selasa") +LOCVAL(LOCALE_SDAYNAME3,"hari rabu") +LOCVAL(LOCALE_SDAYNAME4,"hari kamis") +LOCVAL(LOCALE_SDAYNAME5,"hari jubat") +LOCVAL(LOCALE_SDAYNAME6,"hari sabtu") +LOCVAL(LOCALE_SDAYNAME7,"hari minggu") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"sen") +LOCVAL(LOCALE_SABBREVDAYNAME2,"sel") +LOCVAL(LOCALE_SABBREVDAYNAME3,"rab") +LOCVAL(LOCALE_SABBREVDAYNAME4,"kam") +LOCVAL(LOCALE_SABBREVDAYNAME5,"jub") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sab") +LOCVAL(LOCALE_SABBREVDAYNAME7,"min") + +LOCVAL(LOCALE_SMONTHNAME1,"Januari") +LOCVAL(LOCALE_SMONTHNAME2,"Februari") +LOCVAL(LOCALE_SMONTHNAME3,"Maret") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Mei") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"Agustus") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"Desember") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mei") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Agu") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Des") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"in") +LOCVAL(LOCALE_SISO3166CTRYNAME,"ID") diff --git a/lib/kernel32/nls/irl.nls b/lib/kernel32/nls/irl.nls new file mode 100644 index 0000000..08f46ad --- /dev/null +++ b/lib/kernel32/nls/irl.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Ireland + */ + +LOCVAL(LOCALE_ILANGUAGE, "1809") +LOCVAL(LOCALE_SLANGUAGE, "English (Ireland)") +LOCVAL(LOCALE_SENGLANGUAGE, "English") +LOCVAL(LOCALE_SABBREVLANGNAME, "irl") +LOCVAL(LOCALE_SNATIVELANGNAME, "English") +LOCVAL(LOCALE_ICOUNTRY, "353") +LOCVAL(LOCALE_SCOUNTRY, "Ireland") +LOCVAL(LOCALE_SENGCOUNTRY, "Ireland") +LOCVAL(LOCALE_SABBREVCTRYNAME, "IRL") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Eire") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0409") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "353") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "437") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "IR") +LOCVAL(LOCALE_SINTLSYMBOL, "IEP") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "M/d/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Monday") +LOCVAL(LOCALE_SDAYNAME2, "Tuesday") +LOCVAL(LOCALE_SDAYNAME3, "Wednesday") +LOCVAL(LOCALE_SDAYNAME4, "Thursday") +LOCVAL(LOCALE_SDAYNAME5, "Friday") +LOCVAL(LOCALE_SDAYNAME6, "Saturday") +LOCVAL(LOCALE_SDAYNAME7, "Sunday") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Mon") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Tue") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Wed") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Thu") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Fri") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Sat") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Sun") + +LOCVAL(LOCALE_SMONTHNAME1, "January") +LOCVAL(LOCALE_SMONTHNAME2, "February") +LOCVAL(LOCALE_SMONTHNAME3, "March") +LOCVAL(LOCALE_SMONTHNAME4, "April") +LOCVAL(LOCALE_SMONTHNAME5, "May") +LOCVAL(LOCALE_SMONTHNAME6, "June") +LOCVAL(LOCALE_SMONTHNAME7, "July") +LOCVAL(LOCALE_SMONTHNAME8, "August") +LOCVAL(LOCALE_SMONTHNAME9, "September") +LOCVAL(LOCALE_SMONTHNAME10, "October") +LOCVAL(LOCALE_SMONTHNAME11, "November") +LOCVAL(LOCALE_SMONTHNAME12, "December") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "May") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"en") +LOCVAL(LOCALE_SISO3166CTRYNAME,"IE") + +/* Gregorian Calendar */ diff --git a/lib/kernel32/nls/isl.nls b/lib/kernel32/nls/isl.nls new file mode 100644 index 0000000..a087c92 --- /dev/null +++ b/lib/kernel32/nls/isl.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Iceland + * (Icelandic strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"040f") +LOCVAL(LOCALE_SLANGUAGE,"Íslensk") +LOCVAL(LOCALE_SENGLANGUAGE,"Icelandic") +LOCVAL(LOCALE_SABBREVLANGNAME,"isl") +LOCVAL(LOCALE_SNATIVELANGNAME,"Íslenska") +LOCVAL(LOCALE_ICOUNTRY,"354") +LOCVAL(LOCALE_SCOUNTRY,"Ísland") +LOCVAL(LOCALE_SENGCOUNTRY,"Iceland") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ISL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Ísland") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"040f") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"354") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"kr") +LOCVAL(LOCALE_SINTLSYMBOL, "ISK") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"mánudagur") +LOCVAL(LOCALE_SDAYNAME2,"þriðjudagur") +LOCVAL(LOCALE_SDAYNAME3,"miðvikudagur") +LOCVAL(LOCALE_SDAYNAME4,"fimmtudagur") +LOCVAL(LOCALE_SDAYNAME5,"föstudagur") +LOCVAL(LOCALE_SDAYNAME6,"laugardagur") +LOCVAL(LOCALE_SDAYNAME7,"sunnudagur") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"mán") +LOCVAL(LOCALE_SABBREVDAYNAME2,"þri") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mið") +LOCVAL(LOCALE_SABBREVDAYNAME4,"fim") +LOCVAL(LOCALE_SABBREVDAYNAME5,"fös") +LOCVAL(LOCALE_SABBREVDAYNAME6,"lau") +LOCVAL(LOCALE_SABBREVDAYNAME7,"sun") + +LOCVAL(LOCALE_SMONTHNAME1,"janúar") +LOCVAL(LOCALE_SMONTHNAME2,"febrúar") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"maí") +LOCVAL(LOCALE_SMONTHNAME6,"júní") +LOCVAL(LOCALE_SMONTHNAME7,"júlí") +LOCVAL(LOCALE_SMONTHNAME8,"ágúst") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"október") +LOCVAL(LOCALE_SMONTHNAME11,"nóvember") +LOCVAL(LOCALE_SMONTHNAME12,"desember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"maí") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jún") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"júl") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ágú") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nóv") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"des") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"is") +LOCVAL(LOCALE_SISO3166CTRYNAME,"IS") + diff --git a/lib/kernel32/nls/ita.nls b/lib/kernel32/nls/ita.nls new file mode 100644 index 0000000..1ecdf99 --- /dev/null +++ b/lib/kernel32/nls/ita.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Italy + */ + +LOCVAL(LOCALE_ILANGUAGE,"0410") +LOCVAL(LOCALE_SLANGUAGE,"Italiano") +LOCVAL(LOCALE_SENGLANGUAGE,"Italian") +LOCVAL(LOCALE_SABBREVLANGNAME,"ita") +LOCVAL(LOCALE_SNATIVELANGNAME,"Italiano") +LOCVAL(LOCALE_ICOUNTRY,"39") +LOCVAL(LOCALE_SCOUNTRY,"Italia") +LOCVAL(LOCALE_SENGCOUNTRY,"Italy") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ITA") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Italia") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0410") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"39") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Lit.") +LOCVAL(LOCALE_SINTLSYMBOL, "ITL") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Lunedì") +LOCVAL(LOCALE_SDAYNAME2,"Martedì") +LOCVAL(LOCALE_SDAYNAME3,"Mercoledì") +LOCVAL(LOCALE_SDAYNAME4,"Giovedì") +LOCVAL(LOCALE_SDAYNAME5,"Venerdì") +LOCVAL(LOCALE_SDAYNAME6,"Sabato") +LOCVAL(LOCALE_SDAYNAME7,"Domenica") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Lu") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ma") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Me") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Gi") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Ve") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Sa") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Do") + +LOCVAL(LOCALE_SMONTHNAME1,"gennaio") +LOCVAL(LOCALE_SMONTHNAME2,"febbraio") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"aprile") +LOCVAL(LOCALE_SMONTHNAME5,"maggio") +LOCVAL(LOCALE_SMONTHNAME6,"giugno") +LOCVAL(LOCALE_SMONTHNAME7,"luglio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"settembre") +LOCVAL(LOCALE_SMONTHNAME10,"ottobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"dicembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"gen") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mag") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"giu") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"lug") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"set") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ott") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"it") +LOCVAL(LOCALE_SISO3166CTRYNAME,"IT") + +/* calendario gregoriano */ diff --git a/lib/kernel32/nls/its.nls b/lib/kernel32/nls/its.nls new file mode 100644 index 0000000..a40e7ec --- /dev/null +++ b/lib/kernel32/nls/its.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Switzerland (Italiano) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0810") +LOCVAL(LOCALE_SLANGUAGE,"Italiano") +LOCVAL(LOCALE_SENGLANGUAGE,"Italian") +LOCVAL(LOCALE_SABBREVLANGNAME,"its") +LOCVAL(LOCALE_SNATIVELANGNAME,"Italiano") +LOCVAL(LOCALE_ICOUNTRY,"41") +LOCVAL(LOCALE_SCOUNTRY,"Svizzera") +LOCVAL(LOCALE_SENGCOUNTRY,"Switzerand") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CHE") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Svizzera") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0410") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"41") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"SFr") +LOCVAL(LOCALE_SINTLSYMBOL, "CHF") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"lunedì") +LOCVAL(LOCALE_SDAYNAME2,"martedì") +LOCVAL(LOCALE_SDAYNAME3,"mercoledì") +LOCVAL(LOCALE_SDAYNAME4,"giovedì") +LOCVAL(LOCALE_SDAYNAME5,"venerdì") +LOCVAL(LOCALE_SDAYNAME6,"sabato") +LOCVAL(LOCALE_SDAYNAME7,"domenica") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"lun") +LOCVAL(LOCALE_SABBREVDAYNAME2,"mar") +LOCVAL(LOCALE_SABBREVDAYNAME3,"mer") +LOCVAL(LOCALE_SABBREVDAYNAME4,"gio") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ven") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sab") +LOCVAL(LOCALE_SABBREVDAYNAME7,"dom") + +LOCVAL(LOCALE_SMONTHNAME1,"gennaio") +LOCVAL(LOCALE_SMONTHNAME2,"febbraio") +LOCVAL(LOCALE_SMONTHNAME3,"marzo") +LOCVAL(LOCALE_SMONTHNAME4,"aprile") +LOCVAL(LOCALE_SMONTHNAME5,"maggio") +LOCVAL(LOCALE_SMONTHNAME6,"giugno") +LOCVAL(LOCALE_SMONTHNAME7,"luglio") +LOCVAL(LOCALE_SMONTHNAME8,"agosto") +LOCVAL(LOCALE_SMONTHNAME9,"settembre") +LOCVAL(LOCALE_SMONTHNAME10,"ottobre") +LOCVAL(LOCALE_SMONTHNAME11,"novembre") +LOCVAL(LOCALE_SMONTHNAME12,"dicembre") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"gen") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mag") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"giu") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"lug") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"set") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ott") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dic") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"it") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CH") + +/* calendario gregoriano */ diff --git a/lib/kernel32/nls/jpn.nls b/lib/kernel32/nls/jpn.nls new file mode 100644 index 0000000..62ea891 --- /dev/null +++ b/lib/kernel32/nls/jpn.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Japanese + * (Japanese strings in EUC-JP) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0411") +LOCVAL(LOCALE_SLANGUAGE,"ÆüËܸì") +LOCVAL(LOCALE_SENGLANGUAGE,"Japanese") +LOCVAL(LOCALE_SABBREVLANGNAME,"jpn") +LOCVAL(LOCALE_SNATIVELANGNAME,"ÆüËܸì") +LOCVAL(LOCALE_ICOUNTRY,"81") +LOCVAL(LOCALE_SCOUNTRY,"ÆüËÜ") +LOCVAL(LOCALE_SENGCOUNTRY,"Japan") +LOCVAL(LOCALE_SABBREVCTRYNAME,"JPN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"ÆüËÜ") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0411") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"81") +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +LOCVAL(LOCALE_SGROUPING,"3;0") +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"±ß") +LOCVAL(LOCALE_SINTLSYMBOL, "JPY") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +LOCVAL(LOCALE_SSHORTDATE,"yyyy.MM.dd") +LOCVAL(LOCALE_SLONGDATE,"yyyyǯMMMMd.Æü¤Îddd") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"·îÍËÆü") +LOCVAL(LOCALE_SDAYNAME2,"²ÐÍËÆü") +LOCVAL(LOCALE_SDAYNAME3,"¿åÍËÆü") +LOCVAL(LOCALE_SDAYNAME4,"ÌÚÍËÆü") +LOCVAL(LOCALE_SDAYNAME5,"¶âÍËÆü") +LOCVAL(LOCALE_SDAYNAME6,"ÅÚÍËÆü") +LOCVAL(LOCALE_SDAYNAME7,"ÆüÍËÆü") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"·î") +LOCVAL(LOCALE_SABBREVDAYNAME2,"²Ð") +LOCVAL(LOCALE_SABBREVDAYNAME3,"¿å") +LOCVAL(LOCALE_SABBREVDAYNAME4,"ÌÚ") +LOCVAL(LOCALE_SABBREVDAYNAME5,"¶â") +LOCVAL(LOCALE_SABBREVDAYNAME6,"ÅÚ") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Æü") + +LOCVAL(LOCALE_SMONTHNAME1,"°ì·î") +LOCVAL(LOCALE_SMONTHNAME2,"Æó·î") +LOCVAL(LOCALE_SMONTHNAME3,"»°·î") +LOCVAL(LOCALE_SMONTHNAME4,"»Í·î") +LOCVAL(LOCALE_SMONTHNAME5,"¸Þ·î") +LOCVAL(LOCALE_SMONTHNAME6,"Ï»·î") +LOCVAL(LOCALE_SMONTHNAME7,"¼··î") +LOCVAL(LOCALE_SMONTHNAME8,"Ȭ·î") +LOCVAL(LOCALE_SMONTHNAME9,"¶å·î") +LOCVAL(LOCALE_SMONTHNAME10,"½½·î") +LOCVAL(LOCALE_SMONTHNAME11,"½½°ì·î") +LOCVAL(LOCALE_SMONTHNAME12,"½½Æó·î") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"1·î") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"2·î") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"3·î") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"4·î") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"5·î") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"6·î") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"7·î") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"8·î") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"9·î") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"10·î") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"11·î") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"12·î") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ja") +LOCVAL(LOCALE_SISO3166CTRYNAME,"JP") + diff --git a/lib/kernel32/nls/koj.nls b/lib/kernel32/nls/koj.nls new file mode 100644 index 0000000..5529be0 --- /dev/null +++ b/lib/kernel32/nls/koj.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Korean (Johab) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0812") +LOCVAL(LOCALE_SLANGUAGE,"Korean (Johab)") +LOCVAL(LOCALE_SENGLANGUAGE,"Korean") +LOCVAL(LOCALE_SABBREVLANGNAME,"koj") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +LOCVAL(LOCALE_ICOUNTRY,"82") +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Korea") +LOCVAL(LOCALE_SABBREVCTRYNAME,"KOR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +/* LOCVAL(LOCALE_IDEFAULTLANGUAGE,"") */ +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"82") +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +LOCVAL(LOCALE_SLIST,",") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,".") +LOCVAL(LOCALE_STHOUSAND,",") +LOCVAL(LOCALE_SGROUPING,"3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"0") +LOCVAL(LOCALE_INEGNUMBER,"1") +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"KRW") +LOCVAL(LOCALE_SMONDECIMALSEP,".") +LOCVAL(LOCALE_SMONTHOUSANDSEP,",") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS,"2") +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"yyyy/MM/dd") +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +LOCVAL(LOCALE_STIMEFORMAT,"h:mm:ss tt") +LOCVAL(LOCALE_IDATE,"1") +LOCVAL(LOCALE_ILDATE,"1") +LOCVAL(LOCALE_ITIME,"1") +LOCVAL(LOCALE_ITIMEMARKPOSN,"0") +LOCVAL(LOCALE_ICENTURY,"0") +LOCVAL(LOCALE_ITLZERO,"0") +LOCVAL(LOCALE_IDAYLZERO,"0") +LOCVAL(LOCALE_IMONLZERO,"0") +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* Korean Tangun Era calendar */ +LOCVAL(LOCALE_IOPTIONALCALENDAR,"5") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK,"6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR,"0") + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN,"") +LOCVAL(LOCALE_SNEGATIVESIGN,"-") +LOCVAL(LOCALE_IPOSSIGNPOSN,"3") +LOCVAL(LOCALE_INEGSIGNPOSN,"0") +LOCVAL(LOCALE_IPOSSYMPRECEDES,"3") +LOCVAL(LOCALE_IPOSSEPBYSPACE,"0") +LOCVAL(LOCALE_INEGSYMPRECEDES,"3") +LOCVAL(LOCALE_INEGSEPBYSPACE,"0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ko") +LOCVAL(LOCALE_SISO3166CTRYNAME,"KR") + diff --git a/lib/kernel32/nls/kor.nls b/lib/kernel32/nls/kor.nls new file mode 100644 index 0000000..af19210 --- /dev/null +++ b/lib/kernel32/nls/kor.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Korean + * string using codepage 949 + */ + +LOCVAL(LOCALE_ILANGUAGE,"0412") +LOCVAL(LOCALE_SLANGUAGE,"\307\321\261\271\276\356") +LOCVAL(LOCALE_SENGLANGUAGE,"Korean") +LOCVAL(LOCALE_SABBREVLANGNAME,"kor") +LOCVAL(LOCALE_SNATIVELANGNAME,"\307\321\261\271\276\356") +LOCVAL(LOCALE_ICOUNTRY,"82") +LOCVAL(LOCALE_SCOUNTRY,"\264\353\307\321\271\316\261\271") +LOCVAL(LOCALE_SENGCOUNTRY,"Korea (South)") +LOCVAL(LOCALE_SABBREVCTRYNAME,"KOR") +LOCVAL(LOCALE_SNATIVECTRYNAME,"\264\353\307\321\271\316\261\271") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0412") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"82") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"949") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"949") +LOCVAL(LOCALE_SLIST,",") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,".") +LOCVAL(LOCALE_STHOUSAND,",") +LOCVAL(LOCALE_SGROUPING,"3;0") +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"0") +LOCVAL(LOCALE_INEGNUMBER,"1") +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"\\") +LOCVAL(LOCALE_SINTLSYMBOL,"KRW") +LOCVAL(LOCALE_SMONDECIMALSEP,".") +LOCVAL(LOCALE_SMONTHOUSANDSEP,",") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +LOCVAL(LOCALE_IINTLCURRDIGITS,"2") +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"yyyy/MM/dd") +LOCVAL(LOCALE_SLONGDATE,"yyyy/MM/dd") +LOCVAL(LOCALE_STIMEFORMAT,"h:mm:ss tt") +LOCVAL(LOCALE_IDATE,"1") +LOCVAL(LOCALE_ILDATE,"1") +LOCVAL(LOCALE_ITIME,"1") +LOCVAL(LOCALE_ITIMEMARKPOSN,"0") +LOCVAL(LOCALE_ICENTURY,"0") +LOCVAL(LOCALE_ITLZERO,"0") +LOCVAL(LOCALE_IDAYLZERO,"0") +LOCVAL(LOCALE_IMONLZERO,"0") +LOCVAL(LOCALE_S1159,"\277\300\300\374") +LOCVAL(LOCALE_S2359,"\277\300\310\304") +LOCVAL(LOCALE_ICALENDARTYPE,"1") +/* Korean Tangun Era calendar */ +LOCVAL(LOCALE_IOPTIONALCALENDAR,"5") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK,"6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR,"0") + +LOCVAL(LOCALE_SDAYNAME1,"\277\371\277\344\300\317") +LOCVAL(LOCALE_SDAYNAME2,"\310\255\277\344\300\317") +LOCVAL(LOCALE_SDAYNAME3,"\274\366\277\344\300\317") +LOCVAL(LOCALE_SDAYNAME4,"\270\361\277\344\300\317") +LOCVAL(LOCALE_SDAYNAME5,"\261\335\277\344\300\317") +LOCVAL(LOCALE_SDAYNAME6,"\305\344\277\344\300\317") +LOCVAL(LOCALE_SDAYNAME7,"\300\317\277\344\300\317") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"\277\371") +LOCVAL(LOCALE_SABBREVDAYNAME2,"\310\255") +LOCVAL(LOCALE_SABBREVDAYNAME3,"\274\366") +LOCVAL(LOCALE_SABBREVDAYNAME4,"\270\361") +LOCVAL(LOCALE_SABBREVDAYNAME5,"\261\335") +LOCVAL(LOCALE_SABBREVDAYNAME6,"\305\344") +LOCVAL(LOCALE_SABBREVDAYNAME7,"\300\317") + +LOCVAL(LOCALE_SMONTHNAME1,"1\277\371") +LOCVAL(LOCALE_SMONTHNAME2,"2\277\371") +LOCVAL(LOCALE_SMONTHNAME3,"3\277\371") +LOCVAL(LOCALE_SMONTHNAME4,"4\277\371") +LOCVAL(LOCALE_SMONTHNAME5,"5\277\371") +LOCVAL(LOCALE_SMONTHNAME6,"6\277\371") +LOCVAL(LOCALE_SMONTHNAME7,"7\277\371") +LOCVAL(LOCALE_SMONTHNAME8,"8\277\371") +LOCVAL(LOCALE_SMONTHNAME9,"9\277\371") +LOCVAL(LOCALE_SMONTHNAME10,"10\277\371") +LOCVAL(LOCALE_SMONTHNAME11,"11\277\371") +LOCVAL(LOCALE_SMONTHNAME12,"12\277\371") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"1\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"2\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"3\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"4\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"5\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"6\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"7\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"8\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"9\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"10\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"11\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"12\277\371") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN,"") +LOCVAL(LOCALE_SNEGATIVESIGN,"-") +LOCVAL(LOCALE_IPOSSIGNPOSN,"3") +LOCVAL(LOCALE_INEGSIGNPOSN,"0") +LOCVAL(LOCALE_IPOSSYMPRECEDES,"3") +LOCVAL(LOCALE_IPOSSEPBYSPACE,"0") +LOCVAL(LOCALE_INEGSYMPRECEDES,"3") +LOCVAL(LOCALE_INEGSEPBYSPACE,"0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ko") +LOCVAL(LOCALE_SISO3166CTRYNAME,"KR") + diff --git a/lib/kernel32/nls/lcAFK.c b/lib/kernel32/nls/lcAFK.c new file mode 100644 index 0000000..9f2fd68 --- /dev/null +++ b/lib/kernel32/nls/lcAFK.c @@ -0,0 +1,145 @@ +/* + * nls/lcAFK.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_AFK0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '3', '6', 0 }, + (CONST WCHAR[]) { 'A', 'f', 'r', 'i', 'k', 'a', 'a', 'n', 's', 0 }, + (CONST WCHAR[]) { 'A', 'F', 'K', 0 }, + (CONST WCHAR[]) { 'A', 'f', 'r', 'i', 'k', 'a', 'a', 'n', 's', 0 }, + (CONST WCHAR[]) { '2', '7', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'u', 't', 'h', ' ', 'A', 'f', 'r', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'Z', 'A', 'F', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'i', 'd', ' ', 'A', 'f', 'r', 'i', 'k', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '3', '6', 0 }, + (CONST WCHAR[]) { '2', '7', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'R', 0 }, + (CONST WCHAR[]) { 'Z', 'A', 'R', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'n', 'm', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'a', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'W', 'o', 'e', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'd', 'e', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'V', 'r', 'y', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'e', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'n', 's', 0 }, + (CONST WCHAR[]) { 'W', 'o', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'V', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'a', 'r', 't', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 'u', 's', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 's', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_AFK1[]= +{ + NULL, + (CONST WCHAR[]) { 'A', 'f', 'r', 'i', 'k', 'a', 'a', 'n', 's', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'u', 't', 'h', ' ', 'A', 'f', 'r', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_AFKds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_AFKdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_AFKt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcBEL.c b/lib/kernel32/nls/lcBEL.c new file mode 100644 index 0000000..52071cd --- /dev/null +++ b/lib/kernel32/nls/lcBEL.c @@ -0,0 +1,144 @@ +/* + * nls/lcBEL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_BEL0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '3', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'a', 'r', 'u', 's', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'B', 'E', 'L', 0 }, + (CONST WCHAR[]) { 0x431, 0x435, 0x43B, 0x430, 0x440, 0x443, 0x441, 0x43A, 0x438, 0 }, + (CONST WCHAR[]) { '3', '7', '5', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'a', 'r', 'u', 's', 0 }, + (CONST WCHAR[]) { 'B', 'L', 'R', 0 }, + (CONST WCHAR[]) { 0x411, 0x435, 0x43B, 0x430, 0x440, 0x443, 0x441, 0x44C, 0 }, + (CONST WCHAR[]) { '0', '4', '2', '3', 0 }, + (CONST WCHAR[]) { '7', 0 }, + (CONST WCHAR[]) { '8', '6', '6', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0x440, '.', 0 }, + (CONST WCHAR[]) { 'B', 'Y', 'B', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', '\'', ' ', 0x433, '.', '\'', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0x435, 0x434, 0x435, 0x43B, 0x44C, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x432, 0x442, 0x43E, 0x440, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x435, 0x434, 0x430, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0 }, + (CONST WCHAR[]) { 0x43F, 0x44F, 0x442, 0x43D, 0x438, 0x446, 0x430, 0 }, + (CONST WCHAR[]) { 0x441, 0x443, 0x431, 0x431, 0x43E, 0x442, 0x430, 0 }, + (CONST WCHAR[]) { 0x432, 0x43E, 0x441, 0x43A, 0x440, 0x435, 0x441, 0x435, 0x43D, 0x44C, 0x435, 0 }, + (CONST WCHAR[]) { 0x41F, 0x43D, 0 }, + (CONST WCHAR[]) { 0x412, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x440, 0 }, + (CONST WCHAR[]) { 0x427, 0x442, 0 }, + (CONST WCHAR[]) { 0x41F, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x431, 0 }, + (CONST WCHAR[]) { 0x412, 0x441, 0 }, + (CONST WCHAR[]) { 0x42F, 0x43D, 0x432, 0x430, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x424, 0x435, 0x432, 0x440, 0x430, 0x43B, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x440, 0x442, 0 }, + (CONST WCHAR[]) { 0x410, 0x43F, 0x440, 0x435, 0x43B, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x439, 0 }, + (CONST WCHAR[]) { 0x418, 0x44E, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x418, 0x44E, 0x43B, 0x44C, 0 }, + (CONST WCHAR[]) { 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x43D, 0x442, 0x44F, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41E, 0x43A, 0x442, 0x44F, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41D, 0x43E, 0x44F, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x414, 0x435, 0x43A, 0x430, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x42F, 0x43D, 0x432, 0 }, + (CONST WCHAR[]) { 0x424, 0x435, 0x432, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x410, 0x43F, 0x440, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x439, 0 }, + (CONST WCHAR[]) { 0x418, 0x44E, 0x43D, 0 }, + (CONST WCHAR[]) { 0x418, 0x44E, 0x43B, 0 }, + (CONST WCHAR[]) { 0x410, 0x432, 0x433, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x43D, 0 }, + (CONST WCHAR[]) { 0x41E, 0x43A, 0x442, 0 }, + (CONST WCHAR[]) { 0x41D, 0x43E, 0x44F, 0 }, + (CONST WCHAR[]) { 0x414, 0x435, 0x43A, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x203, 0x8000, 0x3848, 0, 0, 0, 0, 0, 0x4, 0, 0, 0x2, 0x4, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_BEL1[]= +{ + NULL, + (CONST WCHAR[]) { 'B', 'e', 'l', 'a', 'r', 'u', 's', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'a', 'r', 'u', 's', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_BELds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_BELdl[]= +{ + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', '\'', ' ', 0x433, '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_BELt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcBGR.c b/lib/kernel32/nls/lcBGR.c new file mode 100644 index 0000000..1652d43 --- /dev/null +++ b/lib/kernel32/nls/lcBGR.c @@ -0,0 +1,147 @@ +/* + * nls/lcBGR.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_BGR0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '2', 0 }, + (CONST WCHAR[]) { 'B', 'u', 'l', 'g', 'a', 'r', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'B', 'G', 'R', 0 }, + (CONST WCHAR[]) { 0x431, 0x44A, 0x43B, 0x433, 0x430, 0x440, 0x441, 0x43A, 0x438, 0 }, + (CONST WCHAR[]) { '3', '5', '9', 0 }, + (CONST WCHAR[]) { 'B', 'u', 'l', 'g', 'a', 'r', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'B', 'G', 'R', 0 }, + (CONST WCHAR[]) { 0x411, 0x44A, 0x43B, 0x433, 0x430, 0x440, 0x438, 0x44F, 0 }, + (CONST WCHAR[]) { '0', '4', '0', '2', 0 }, + (CONST WCHAR[]) { '3', '5', '9', 0 }, + (CONST WCHAR[]) { '8', '6', '6', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0x43B, 0x432, 0 }, + (CONST WCHAR[]) { 'B', 'G', 'L', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0x435, 0x434, 0x435, 0x43B, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x432, 0x442, 0x43E, 0x440, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x44F, 0x434, 0x430, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0x432, 0x44A, 0x432, 0x442, 0x44A, 0x43A, 0 }, + (CONST WCHAR[]) { 0x43F, 0x435, 0x442, 0x44A, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x44A, 0x431, 0x43E, 0x442, 0x430, 0 }, + (CONST WCHAR[]) { 0x43D, 0x435, 0x434, 0x435, 0x43B, 0x44F, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0x435, 0x434, 0x435, 0x43B, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x432, 0x442, 0x43E, 0x440, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x44F, 0x434, 0x430, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0x432, 0x44A, 0x432, 0x442, 0x44A, 0x43A, 0 }, + (CONST WCHAR[]) { 0x43F, 0x435, 0x442, 0x44A, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x44A, 0x431, 0x43E, 0x442, 0x430, 0 }, + (CONST WCHAR[]) { 0x43D, 0x435, 0x434, 0x435, 0x43B, 0x44F, 0 }, + (CONST WCHAR[]) { 0x42F, 0x43D, 0x443, 0x430, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x424, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x440, 0x442, 0 }, + (CONST WCHAR[]) { 0x410, 0x43F, 0x440, 0x438, 0x43B, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x439, 0 }, + (CONST WCHAR[]) { 0x42E, 0x43D, 0x438, 0 }, + (CONST WCHAR[]) { 0x42E, 0x43B, 0x438, 0 }, + (CONST WCHAR[]) { 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x43F, 0x442, 0x435, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x41E, 0x43A, 0x442, 0x43E, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x41D, 0x43E, 0x435, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x414, 0x435, 0x43A, 0x435, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x42F, 0x43D, 0x443, 0x430, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x424, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x440, 0x442, 0 }, + (CONST WCHAR[]) { 0x410, 0x43F, 0x440, 0x438, 0x43B, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x439, 0 }, + (CONST WCHAR[]) { 0x42E, 0x43D, 0x438, 0 }, + (CONST WCHAR[]) { 0x42E, 0x43B, 0x438, 0 }, + (CONST WCHAR[]) { 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x43F, 0x442, 0x435, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x41E, 0x43A, 0x442, 0x43E, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x41D, 0x43E, 0x435, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0x414, 0x435, 0x43A, 0x435, 0x43C, 0x432, 0x440, 0x438, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x203, 0x8000, 0x3848, 0, 0, 0, 0, 0, 0x4, 0, 0, 0x2, 0x4, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_BGR1[]= +{ + NULL, + (CONST WCHAR[]) { 'B', 'u', 'l', 'g', 'a', 'r', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'B', 'u', 'l', 'g', 'a', 'r', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_BGRds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_BGRdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_BGRt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcCAT.c b/lib/kernel32/nls/lcCAT.c new file mode 100644 index 0000000..17ad662 --- /dev/null +++ b/lib/kernel32/nls/lcCAT.c @@ -0,0 +1,144 @@ +/* + * nls/lcCAT.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_CAT0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '3', 0 }, + (CONST WCHAR[]) { 'C', 'a', 't', 'a', 'l', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'C', 'A', 'T', 0 }, + (CONST WCHAR[]) { 'c', 'a', 't', 'a', 'l', 0xE0, 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 'n', 'y', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'P', 'T', 'A', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '\'', ' ', '/', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', '/', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'd', 'i', 'l', 'l', 'u', 'n', 's', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'a', 'r', 't', 's', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'e', 'c', 'r', 'e', 's', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'j', 'o', 'u', 's', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'v', 'e', 'n', 'd', 'r', 'e', 's', 0 }, + (CONST WCHAR[]) { 'd', 'i', 's', 's', 'a', 'b', 't', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'u', 'm', 'e', 'n', 'g', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'l', '.', 0 }, + (CONST WCHAR[]) { 'd', 't', '.', 0 }, + (CONST WCHAR[]) { 'd', 'c', '.', 0 }, + (CONST WCHAR[]) { 'd', 'j', '.', 0 }, + (CONST WCHAR[]) { 'd', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 's', '.', 0 }, + (CONST WCHAR[]) { 'd', 'g', '.', 0 }, + (CONST WCHAR[]) { 'g', 'e', 'n', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0xE7, 0 }, + (CONST WCHAR[]) { 'a', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 'g', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'y', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 'o', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'g', 'e', 'n', '.', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0xE7, 0 }, + (CONST WCHAR[]) { 'a', 'b', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 'g', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'y', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'g', '.', 0 }, + (CONST WCHAR[]) { 's', 'e', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x3, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_CAT1[]= +{ + NULL, + (CONST WCHAR[]) { 'C', 'a', 't', 'a', 'l', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_CATds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_CATdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '\'', ' ', '/', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', '/', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_CATt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcCSY.c b/lib/kernel32/nls/lcCSY.c new file mode 100644 index 0000000..cc09173 --- /dev/null +++ b/lib/kernel32/nls/lcCSY.c @@ -0,0 +1,149 @@ +/* + * nls/lcCSY.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_CSY0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '5', 0 }, + (CONST WCHAR[]) { 'C', 'z', 'e', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'S', 'Y', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 0x161, 't', 'i', 'n', 'a', 0 }, + (CONST WCHAR[]) { '4', '2', 0 }, + (CONST WCHAR[]) { 'C', 'z', 'e', 'c', 'h', ' ', 'R', 'e', 'p', 'u', 'b', 'l', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'C', 'Z', 'E', 0 }, + (CONST WCHAR[]) { 0x10C, 'e', 's', 'k', 0xE1, ' ', 'r', 'e', 'p', 'u', 'b', 'l', 'i', 'k', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '0', '5', 0 }, + (CONST WCHAR[]) { '4', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'K', 0x10D, 0 }, + (CONST WCHAR[]) { 'C', 'Z', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'p', '.', 0 }, + (CONST WCHAR[]) { 'o', 'd', 'p', '.', 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 'd', 0x11B, 'l', 0xED, 0 }, + (CONST WCHAR[]) { 0xFA, 't', 'e', 'r', 0xFD, 0 }, + (CONST WCHAR[]) { 's', 't', 0x159, 'e', 'd', 'a', 0 }, + (CONST WCHAR[]) { 0x10D, 't', 'v', 'r', 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 'p', 0xE1, 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 's', 'o', 'b', 'o', 't', 'a', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 0x11B, 'l', 'e', 0 }, + (CONST WCHAR[]) { 'p', 'o', 0 }, + (CONST WCHAR[]) { 0xFA, 't', 0 }, + (CONST WCHAR[]) { 's', 't', 0 }, + (CONST WCHAR[]) { 0x10D, 't', 0 }, + (CONST WCHAR[]) { 'p', 0xE1, 0 }, + (CONST WCHAR[]) { 's', 'o', 0 }, + (CONST WCHAR[]) { 'n', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'e', 'd', 'e', 'n', 0 }, + (CONST WCHAR[]) { 0xFA, 'n', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'b', 0x159, 'e', 'z', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'd', 'u', 'b', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'k', 'v', 0x11B, 't', 'e', 'n', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 'r', 'v', 'e', 'n', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 'r', 'v', 'e', 'n', 'e', 'c', 0 }, + (CONST WCHAR[]) { 's', 'r', 'p', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'z', 0xE1, 0x159, 0xED, 0 }, + (CONST WCHAR[]) { 0x159, 0xED, 'j', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'l', 'i', 's', 't', 'o', 'p', 'a', 'd', 0 }, + (CONST WCHAR[]) { 'p', 'r', 'o', 's', 'i', 'n', 'e', 'c', 0 }, + (CONST WCHAR[]) { 'I', 0 }, + (CONST WCHAR[]) { 'I', 'I', 0 }, + (CONST WCHAR[]) { 'I', 'I', 'I', 0 }, + (CONST WCHAR[]) { 'I', 'V', 0 }, + (CONST WCHAR[]) { 'V', 0 }, + (CONST WCHAR[]) { 'V', 'I', 0 }, + (CONST WCHAR[]) { 'V', 'I', 'I', 0 }, + (CONST WCHAR[]) { 'V', 'I', 'I', 'I', 0 }, + (CONST WCHAR[]) { 'I', 'X', 0 }, + (CONST WCHAR[]) { 'X', 0 }, + (CONST WCHAR[]) { 'X', 'I', 0 }, + (CONST WCHAR[]) { 'X', 'I', 'I', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_CSY1[]= +{ + NULL, + (CONST WCHAR[]) { 'C', 'z', 'e', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'z', 'e', 'c', 'h', ' ', 'R', 'e', 'p', 'u', 'b', 'l', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_CSYds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', '-', 'd', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', '-', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_CSYdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_CSYt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'h', '.', 'm', 'm', '.', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcDAN.c b/lib/kernel32/nls/lcDAN.c new file mode 100644 index 0000000..9f34715 --- /dev/null +++ b/lib/kernel32/nls/lcDAN.c @@ -0,0 +1,149 @@ +/* + * nls/lcDAN.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_DAN0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '6', 0 }, + (CONST WCHAR[]) { 'D', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'A', 'N', 0 }, + (CONST WCHAR[]) { 'd', 'a', 'n', 's', 'k', 0 }, + (CONST WCHAR[]) { '4', '5', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'n', 'm', 'a', 'r', 'k', 0 }, + (CONST WCHAR[]) { 'D', 'N', 'K', 0 }, + (CONST WCHAR[]) { 'D', 'a', 'n', 'm', 'a', 'r', 'k', 0 }, + (CONST WCHAR[]) { '0', '4', '0', '6', 0 }, + (CONST WCHAR[]) { '4', '5', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'K', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', '2', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'i', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'o', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'e', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'l', 0xF8, 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 's', 0xF8, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0 }, + (CONST WCHAR[]) { 't', 'i', 0 }, + (CONST WCHAR[]) { 'o', 'n', 0 }, + (CONST WCHAR[]) { 't', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0 }, + (CONST WCHAR[]) { 'l', 0xF8, 0 }, + (CONST WCHAR[]) { 's', 0xF8, 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DAN1[]= +{ + NULL, + (CONST WCHAR[]) { 'D', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'n', 'm', 'a', 'r', 'k', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_DANds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', ' ', 'M', 'M', ' ', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DANdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DANt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcDEA.c b/lib/kernel32/nls/lcDEA.c new file mode 100644 index 0000000..043f21d --- /dev/null +++ b/lib/kernel32/nls/lcDEA.c @@ -0,0 +1,151 @@ +/* + * nls/lcDEA.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_DEA0[]= +{ + NULL, + (CONST WCHAR[]) { '0', 'c', '0', '7', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', ' ', '(', 'A', 'u', 's', 't', 'r', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'A', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'u', 't', 's', 'c', 'h', 0 }, + (CONST WCHAR[]) { '4', '3', 0 }, + (CONST WCHAR[]) { 'A', 'u', 's', 't', 'r', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'A', 'U', 'T', 0 }, + (CONST WCHAR[]) { 0xD6, 's', 't', 'e', 'r', 'r', 'e', 'i', 'c', 'h', 0 }, + (CONST WCHAR[]) { '0', 'c', '0', '7', 0 }, + (CONST WCHAR[]) { '4', '3', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0xF6, 'S', 0 }, + (CONST WCHAR[]) { 'A', 'T', 'S', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '9', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'e', 'n', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'i', 't', 't', 'w', 'o', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'n', 'e', 'r', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'i', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'm', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0 }, + (CONST WCHAR[]) { 'D', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'o', 0 }, + (CONST WCHAR[]) { 'J', 0xE4, 'n', 'n', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 0xE4, 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x93, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEA1[]= +{ + NULL, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'A', 'u', 's', 't', 'r', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_DEAds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEAdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', 'M', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEAt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', '\'', ' ', 'U', 'h', 'r', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcDEC.c b/lib/kernel32/nls/lcDEC.c new file mode 100644 index 0000000..bf3b93b --- /dev/null +++ b/lib/kernel32/nls/lcDEC.c @@ -0,0 +1,153 @@ +/* + * nls/lcDEC.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_DEC0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '4', '0', '7', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', ' ', '(', 'L', 'i', 'e', 'c', 'h', 't', 'e', 'n', 's', 't', 'e', 'i', 'n', ')', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'C', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'u', 't', 's', 'c', 'h', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { 'L', 'i', 'e', 'c', 'h', 't', 'e', 'n', 's', 't', 'e', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'I', 'E', 0 }, + (CONST WCHAR[]) { 'L', 'i', 'e', 'c', 'h', 't', 'e', 'n', 's', 't', 'e', 'i', 'n', 0 }, + (CONST WCHAR[]) { '1', '4', '0', '7', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'F', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'F', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'e', 'n', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'i', 't', 't', 'w', 'o', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'n', 'e', 'r', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'i', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'm', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0 }, + (CONST WCHAR[]) { 'D', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x93, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEC1[]= +{ + NULL, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'i', 'e', 'c', 'h', 't', 'e', 'n', 's', 't', 'e', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_DECds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', '.', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DECdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DECt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'h', '\'', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '\'', ' ', 'h', '\'', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'U', 'h', 'r', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcDEL.c b/lib/kernel32/nls/lcDEL.c new file mode 100644 index 0000000..e69ab1f --- /dev/null +++ b/lib/kernel32/nls/lcDEL.c @@ -0,0 +1,152 @@ +/* + * nls/lcDEL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_DEL0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '0', '0', '7', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', ' ', '(', 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', ')', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'L', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'u', 't', 's', 'c', 'h', 0 }, + (CONST WCHAR[]) { '3', '5', '2', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', 0 }, + (CONST WCHAR[]) { 'L', 'U', 'X', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'x', 'e', 'm', 'b', 'u', 'r', 'g', 0 }, + (CONST WCHAR[]) { '1', '0', '0', '7', 0 }, + (CONST WCHAR[]) { '3', '5', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'F', 0 }, + (CONST WCHAR[]) { 'L', 'U', 'F', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'e', 'n', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'i', 't', 't', 'w', 'o', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'n', 'e', 'r', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'i', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'm', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0 }, + (CONST WCHAR[]) { 'D', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x93, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEL1[]= +{ + NULL, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_DELds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DELdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DELt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'U', 'h', 'r', ' ', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcDES.c b/lib/kernel32/nls/lcDES.c new file mode 100644 index 0000000..2173c88 --- /dev/null +++ b/lib/kernel32/nls/lcDES.c @@ -0,0 +1,153 @@ +/* + * nls/lcDES.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_DES0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '0', '7', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', ' ', '(', 'S', 'w', 'i', 's', 's', ')', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'S', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'u', 't', 's', 'c', 'h', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'i', 't', 'z', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'E', 0 }, + (CONST WCHAR[]) { 'S', 'c', 'h', 'w', 'e', 'i', 'z', 0 }, + (CONST WCHAR[]) { '0', '8', '0', '7', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', 'F', 'r', '.', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'F', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'e', 'n', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'i', 't', 't', 'w', 'o', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'n', 'e', 'r', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'i', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'm', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0 }, + (CONST WCHAR[]) { 'D', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x93, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DES1[]= +{ + NULL, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'i', 't', 'z', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_DESds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', '.', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DESdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DESt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'h', '\'', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '\'', ' ', 'h', '\'', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'U', 'h', 'r', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcDEU.c b/lib/kernel32/nls/lcDEU.c new file mode 100644 index 0000000..4ba571d --- /dev/null +++ b/lib/kernel32/nls/lcDEU.c @@ -0,0 +1,152 @@ +/* + * nls/lcDEU.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_DEU0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '7', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', ' ', '(', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ')', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'U', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'u', 't', 's', 'c', 'h', 0 }, + (CONST WCHAR[]) { '4', '9', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 'y', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'U', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'u', 't', 's', 'c', 'h', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { '0', '4', '0', '7', 0 }, + (CONST WCHAR[]) { '4', '9', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'D', 'M', 0 }, + (CONST WCHAR[]) { 'D', 'E', 'M', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'e', 'n', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'i', 't', 't', 'w', 'o', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'n', 'n', 'e', 'r', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'i', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'm', 's', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'n', 'n', 't', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'M', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0 }, + (CONST WCHAR[]) { 'D', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'r', 'z', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x93, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEU1[]= +{ + NULL, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'r', 'm', 'a', 'n', 'y', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_DEUds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEUdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_DEUt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'U', 'h', 'r', ' ', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcELL.c b/lib/kernel32/nls/lcELL.c new file mode 100644 index 0000000..4e8ff5f --- /dev/null +++ b/lib/kernel32/nls/lcELL.c @@ -0,0 +1,151 @@ +/* + * nls/lcELL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ELL0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '8', 0 }, + (CONST WCHAR[]) { 'G', 'r', 'e', 'e', 'k', 0 }, + (CONST WCHAR[]) { 'E', 'L', 'L', 0 }, + (CONST WCHAR[]) { 0x3B5, 0x3BB, 0x3BB, 0x3B7, 0x3BD, 0x3B9, 0x3BA, 0x3AC, 0 }, + (CONST WCHAR[]) { '3', '0', 0 }, + (CONST WCHAR[]) { 'G', 'r', 'e', 'e', 'c', 'e', 0 }, + (CONST WCHAR[]) { 'G', 'R', 'C', 0 }, + (CONST WCHAR[]) { 0x395, 0x3BB, 0x3BB, 0x3AC, 0x3B4, 0x3B1, 0 }, + (CONST WCHAR[]) { '0', '4', '0', '8', 0 }, + (CONST WCHAR[]) { '3', '0', 0 }, + (CONST WCHAR[]) { '7', '3', '7', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0x394, 0x3C1, 0x3C7, 0 }, + (CONST WCHAR[]) { 'G', 'R', 'D', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0x3C0, 0x3BC, 0 }, + (CONST WCHAR[]) { 0x3BC, 0x3BC, 0 }, + (CONST WCHAR[]) { 0x394, 0x3B5, 0x3C5, 0x3C4, 0x3AD, 0x3C1, 0x3B1, 0 }, + (CONST WCHAR[]) { 0x3A4, 0x3C1, 0x3AF, 0x3C4, 0x3B7, 0 }, + (CONST WCHAR[]) { 0x3A4, 0x3B5, 0x3C4, 0x3AC, 0x3C1, 0x3C4, 0x3B7, 0 }, + (CONST WCHAR[]) { 0x3A0, 0x3AD, 0x3BC, 0x3C0, 0x3C4, 0x3B7, 0 }, + (CONST WCHAR[]) { 0x3A0, 0x3B1, 0x3C1, 0x3B1, 0x3C3, 0x3BA, 0x3B5, 0x3C5, 0x3AE, 0 }, + (CONST WCHAR[]) { 0x3A3, 0x3AC, 0x3B2, 0x3B2, 0x3B1, 0x3C4, 0x3BF, 0 }, + (CONST WCHAR[]) { 0x39A, 0x3C5, 0x3C1, 0x3B9, 0x3B1, 0x3BA, 0x3AE, 0 }, + (CONST WCHAR[]) { 0x394, 0x3B5, 0x3C5, 0 }, + (CONST WCHAR[]) { 0x3A4, 0x3C1, 0x3B9, 0 }, + (CONST WCHAR[]) { 0x3A4, 0x3B5, 0x3C4, 0 }, + (CONST WCHAR[]) { 0x3A0, 0x3B5, 0x3BC, 0 }, + (CONST WCHAR[]) { 0x3A0, 0x3B1, 0x3C1, 0 }, + (CONST WCHAR[]) { 0x3A3, 0x3B1, 0x3B2, 0 }, + (CONST WCHAR[]) { 0x39A, 0x3C5, 0x3C1, 0 }, + (CONST WCHAR[]) { 0x399, 0x3B1, 0x3BD, 0x3BF, 0x3C5, 0x3AC, 0x3C1, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x3A6, 0x3B5, 0x3B2, 0x3C1, 0x3BF, 0x3C5, 0x3AC, 0x3C1, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x39C, 0x3AC, 0x3C1, 0x3C4, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x391, 0x3C0, 0x3C1, 0x3AF, 0x3BB, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x39C, 0x3AC, 0x3CA, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x399, 0x3BF, 0x3CD, 0x3BD, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x399, 0x3BF, 0x3CD, 0x3BB, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x391, 0x3CD, 0x3B3, 0x3BF, 0x3C5, 0x3C3, 0x3C4, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x3A3, 0x3B5, 0x3C0, 0x3C4, 0x3AD, 0x3BC, 0x3B2, 0x3C1, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x39F, 0x3BA, 0x3C4, 0x3CE, 0x3B2, 0x3C1, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x39D, 0x3BF, 0x3AD, 0x3BC, 0x3B2, 0x3C1, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x394, 0x3B5, 0x3BA, 0x3AD, 0x3BC, 0x3B2, 0x3C1, 0x3B9, 0x3BF, 0x3C2, 0 }, + (CONST WCHAR[]) { 0x399, 0x3B1, 0x3BD, 0 }, + (CONST WCHAR[]) { 0x3A6, 0x3B5, 0x3B2, 0 }, + (CONST WCHAR[]) { 0x39C, 0x3B1, 0x3C1, 0 }, + (CONST WCHAR[]) { 0x391, 0x3C0, 0x3C1, 0 }, + (CONST WCHAR[]) { 0x39C, 0x3B1, 0x3CA, 0 }, + (CONST WCHAR[]) { 0x399, 0x3BF, 0x3C5, 0x3BD, 0 }, + (CONST WCHAR[]) { 0x399, 0x3BF, 0x3C5, 0x3BB, 0 }, + (CONST WCHAR[]) { 0x391, 0x3C5, 0x3B3, 0 }, + (CONST WCHAR[]) { 0x3A3, 0x3B5, 0x3C0, 0 }, + (CONST WCHAR[]) { 0x39F, 0x3BA, 0x3C4, 0 }, + (CONST WCHAR[]) { 0x39D, 0x3BF, 0x3B5, 0 }, + (CONST WCHAR[]) { 0x394, 0x3B5, 0x3BA, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x8B, 0x8000, 0x3849, 0x1000, 0, 0, 0, 0, 0x8, 0, 0, 0x1000, 0x8, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ELL1[]= +{ + NULL, + (CONST WCHAR[]) { 'G', 'r', 'e', 'e', 'k', 0 }, + (CONST WCHAR[]) { 'G', 'r', 'e', 'e', 'c', 'e', 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ELLds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ELLdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ELLt[]= +{ + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENA.c b/lib/kernel32/nls/lcENA.c new file mode 100644 index 0000000..fcf9644 --- /dev/null +++ b/lib/kernel32/nls/lcENA.c @@ -0,0 +1,148 @@ +/* + * nls/lcENA.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENA0[]= +{ + NULL, + (CONST WCHAR[]) { '0', 'c', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'A', 'u', 's', 't', 'r', 'a', 'l', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'A', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '6', '1', 0 }, + (CONST WCHAR[]) { 'A', 'u', 's', 't', 'r', 'a', 'l', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'A', 'U', 'S', 0 }, + (CONST WCHAR[]) { 'A', 'u', 's', 't', 'r', 'a', 'l', 'i', 'a', 0 }, + (CONST WCHAR[]) { '0', 'c', '0', '9', 0 }, + (CONST WCHAR[]) { '6', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'A', 'U', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENA1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'u', 's', 't', 'r', 'a', 'l', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENAds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENAdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENAt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENB.c b/lib/kernel32/nls/lcENB.c new file mode 100644 index 0000000..0d9c133 --- /dev/null +++ b/lib/kernel32/nls/lcENB.c @@ -0,0 +1,150 @@ +/* + * nls/lcENB.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENB0[]= +{ + NULL, + (CONST WCHAR[]) { '2', '4', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'C', 'a', 'r', 'i', 'b', 'b', 'e', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'B', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'r', 'i', 'b', 'b', 'e', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'C', 'A', 'R', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'r', 'i', 'b', 'b', 'e', 'a', 'n', 0 }, + (CONST WCHAR[]) { '2', 'c', '0', '9', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'U', 'S', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENB1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'r', 'i', 'b', 'b', 'e', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENBds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENBdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENBt[]= +{ + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENC.c b/lib/kernel32/nls/lcENC.c new file mode 100644 index 0000000..11e124a --- /dev/null +++ b/lib/kernel32/nls/lcENC.c @@ -0,0 +1,151 @@ +/* + * nls/lcENC.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENC0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '0', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'C', 'a', 'n', 'a', 'd', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'C', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'n', 'a', 'd', 'a', 0 }, + (CONST WCHAR[]) { 'C', 'A', 'N', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'n', 'a', 'd', 'a', 0 }, + (CONST WCHAR[]) { '1', '0', '0', '9', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'C', 'A', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'M', 'M', 'M', ' ', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENC1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'n', 'a', 'd', 'a', 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENCds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'M', '/', 'd', 'd', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENCdl[]= +{ + (CONST WCHAR[]) { 'M', 'M', 'M', 'M', ' ', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENCt[]= +{ + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENG.c b/lib/kernel32/nls/lcENG.c new file mode 100644 index 0000000..7c61821 --- /dev/null +++ b/lib/kernel32/nls/lcENG.c @@ -0,0 +1,148 @@ +/* + * nls/lcENG.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENG0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'U', 'n', 'i', 't', 'e', 'd', ' ', 'K', 'i', 'n', 'g', 'd', 'o', 'm', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'G', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '4', '4', 0 }, + (CONST WCHAR[]) { 'U', 'n', 'i', 't', 'e', 'd', ' ', 'K', 'i', 'n', 'g', 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'G', 'B', 'R', 0 }, + (CONST WCHAR[]) { 'U', 'n', 'i', 't', 'e', 'd', ' ', 'K', 'i', 'n', 'g', 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { '0', '8', '0', '9', 0 }, + (CONST WCHAR[]) { '4', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0xA3, 0 }, + (CONST WCHAR[]) { 'G', 'B', 'P', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENG1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'U', 'n', 'i', 't', 'e', 'd', ' ', 'K', 'i', 'n', 'g', 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENGds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENGdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENGt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENI.c b/lib/kernel32/nls/lcENI.c new file mode 100644 index 0000000..c786cb6 --- /dev/null +++ b/lib/kernel32/nls/lcENI.c @@ -0,0 +1,148 @@ +/* + * nls/lcENI.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENI0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '8', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'I', 'r', 'e', 'l', 'a', 'n', 'd', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'I', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '3', '5', '3', 0 }, + (CONST WCHAR[]) { 'I', 'r', 'e', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'I', 'R', 'L', 0 }, + (CONST WCHAR[]) { 'E', 'i', 'r', 'e', 0 }, + (CONST WCHAR[]) { '1', '8', '0', '9', 0 }, + (CONST WCHAR[]) { '3', '5', '3', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'I', 'R', 0xA3, 0 }, + (CONST WCHAR[]) { 'I', 'E', 'P', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENI1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'I', 'r', 'e', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENIds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENIdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENIt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENJ.c b/lib/kernel32/nls/lcENJ.c new file mode 100644 index 0000000..2071bfe --- /dev/null +++ b/lib/kernel32/nls/lcENJ.c @@ -0,0 +1,150 @@ +/* + * nls/lcENJ.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENJ0[]= +{ + NULL, + (CONST WCHAR[]) { '2', '0', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'J', 'a', 'm', 'a', 'i', 'c', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'J', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'm', 'a', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'J', 'A', 'M', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'm', 'a', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { '2', '0', '0', '9', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'J', '$', 0 }, + (CONST WCHAR[]) { 'U', 'S', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENJ1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'm', 'a', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENJds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENJdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENJt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENL.c b/lib/kernel32/nls/lcENL.c new file mode 100644 index 0000000..5511990 --- /dev/null +++ b/lib/kernel32/nls/lcENL.c @@ -0,0 +1,144 @@ +/* + * nls/lcENL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENL0[]= +{ + NULL, + (CONST WCHAR[]) { '2', '8', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'B', 'e', 'l', 'i', 'z', 'e', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'L', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '5', '0', '1', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'i', 'z', 'e', 0 }, + (CONST WCHAR[]) { 'B', 'L', 'Z', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'i', 'z', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'G', 0 }, + (CONST WCHAR[]) { '5', '0', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'B', 'Z', '$', 0 }, + (CONST WCHAR[]) { 'B', 'Z', 'E', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENL1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'i', 'z', 'e', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENLds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENLdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENLt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENS.c b/lib/kernel32/nls/lcENS.c new file mode 100644 index 0000000..20b6785 --- /dev/null +++ b/lib/kernel32/nls/lcENS.c @@ -0,0 +1,144 @@ +/* + * nls/lcENS.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENS0[]= +{ + NULL, + (CONST WCHAR[]) { '1', 'c', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'S', 'o', 'u', 't', 'h', ' ', 'A', 'f', 'r', 'i', 'c', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'S', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '2', '7', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'u', 't', 'h', ' ', 'A', 'f', 'r', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'Z', 'A', 'F', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'u', 't', 'h', ' ', 'A', 'f', 'r', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { '1', 'c', '0', '9', 0 }, + (CONST WCHAR[]) { '2', '7', 0 }, + (CONST WCHAR[]) { '4', '3', '7', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'R', 0 }, + (CONST WCHAR[]) { 'Z', 'A', 'R', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0xAF, 0x8000, 0x38CB, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x8000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENS1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'S', 'o', 'u', 't', 'h', ' ', 'A', 'f', 'r', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENSds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENSdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENSt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENT.c b/lib/kernel32/nls/lcENT.c new file mode 100644 index 0000000..cbb83d4 --- /dev/null +++ b/lib/kernel32/nls/lcENT.c @@ -0,0 +1,144 @@ +/* + * nls/lcENT.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENT0[]= +{ + NULL, + (CONST WCHAR[]) { '2', 'c', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'T', 'r', 'i', 'n', 'i', 'd', 'a', 'd', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'T', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'T', 'r', 'i', 'n', 'i', 'd', 'a', 'd', ' ', 'y', ' ', 'T', 'o', 'b', 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'T', 'T', 'O', 0 }, + (CONST WCHAR[]) { 'T', 'r', 'i', 'n', 'i', 'd', 'a', 'd', ' ', 'y', ' ', 'T', 'o', 'b', 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'G', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'T', 'T', '$', 0 }, + (CONST WCHAR[]) { 'T', 'T', 'O', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENT1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'T', 'r', 'i', 'n', 'i', 'd', 'a', 'd', ' ', 'y', ' ', 'T', 'o', 'b', 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENTds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENTdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENTt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENU.c b/lib/kernel32/nls/lcENU.c new file mode 100644 index 0000000..c471496 --- /dev/null +++ b/lib/kernel32/nls/lcENU.c @@ -0,0 +1,155 @@ +/* + * nls/lcENU.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENU0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'U', 'n', 'i', 't', 'e', 'd', ' ', 'S', 't', 'a', 't', 'e', 's', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'U', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'U', 'n', 'i', 't', 'e', 'd', ' ', 'S', 't', 'a', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'U', 'S', 'A', 0 }, + (CONST WCHAR[]) { 'U', 'n', 'i', 't', 'e', 'd', ' ', 'S', 't', 'a', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { '0', '4', '0', '9', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '4', '3', '7', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'U', 'S', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', '/', 'd', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0xAF, 0x8000, 0x38CB, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x8000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENU1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'U', 'n', 'i', 't', 'e', 'd', ' ', 'S', 't', 'a', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENUds[]= +{ + (CONST WCHAR[]) { 'M', '/', 'd', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'M', '/', 'd', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENUdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'M', 'M', 'M', 'M', ' ', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENUt[]= +{ + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcENZ.c b/lib/kernel32/nls/lcENZ.c new file mode 100644 index 0000000..426d875 --- /dev/null +++ b/lib/kernel32/nls/lcENZ.c @@ -0,0 +1,148 @@ +/* + * nls/lcENZ.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ENZ0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '4', '0', '9', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', ' ', '(', 'N', 'e', 'w', ' ', 'Z', 'e', 'a', 'l', 'a', 'n', 'd', ')', 0 }, + (CONST WCHAR[]) { 'E', 'N', 'Z', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { '6', '4', 0 }, + (CONST WCHAR[]) { 'N', 'e', 'w', ' ', 'Z', 'e', 'a', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'N', 'Z', 'L', 0 }, + (CONST WCHAR[]) { 'N', 'e', 'w', ' ', 'Z', 'e', 'a', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { '1', '4', '0', '9', 0 }, + (CONST WCHAR[]) { '6', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'N', 'Z', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 'd', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'W', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'T', 'h', 'u', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0xFF, '?', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENZ1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'N', 'e', 'w', ' ', 'Z', 'e', 'a', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ENZds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENZdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ENZt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESA.c b/lib/kernel32/nls/lcESA.c new file mode 100644 index 0000000..54143d5 --- /dev/null +++ b/lib/kernel32/nls/lcESA.c @@ -0,0 +1,151 @@ +/* + * nls/lcESA.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESA0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'P', 'a', 'n', 'a', 'm', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'A', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '0', '7', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'n', 'a', 'm', 'a', 0 }, + (CONST WCHAR[]) { 'P', 'A', 'N', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'n', 'a', 'm', 0xE1, 0 }, + (CONST WCHAR[]) { '1', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '0', '7', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'B', 0 }, + (CONST WCHAR[]) { 'P', 'A', 'B', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESA1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'n', 'a', 'm', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESAds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESAdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESAt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESB.c b/lib/kernel32/nls/lcESB.c new file mode 100644 index 0000000..4fe25be --- /dev/null +++ b/lib/kernel32/nls/lcESB.c @@ -0,0 +1,151 @@ +/* + * nls/lcESB.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESB0[]= +{ + NULL, + (CONST WCHAR[]) { '4', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'B', 'o', 'l', 'i', 'v', 'i', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'B', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '9', '1', 0 }, + (CONST WCHAR[]) { 'B', 'o', 'l', 'i', 'v', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'B', 'O', 'L', 0 }, + (CONST WCHAR[]) { 'B', 'o', 'l', 'i', 'v', 'i', 'a', 0 }, + (CONST WCHAR[]) { '4', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '9', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'B', 's', 0 }, + (CONST WCHAR[]) { 'B', 'O', 'B', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESB1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'B', 'o', 'l', 'i', 'v', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESBds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESBdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESBt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESC.c b/lib/kernel32/nls/lcESC.c new file mode 100644 index 0000000..0fd736b --- /dev/null +++ b/lib/kernel32/nls/lcESC.c @@ -0,0 +1,151 @@ +/* + * nls/lcESC.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESC0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'C', 'o', 's', 't', 'a', ' ', 'R', 'i', 'c', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'C', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '0', '6', 0 }, + (CONST WCHAR[]) { 'C', 'o', 's', 't', 'a', ' ', 'R', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'C', 'R', 'I', 0 }, + (CONST WCHAR[]) { 'C', 'o', 's', 't', 'a', ' ', 'R', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { '1', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '0', '6', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'C', 0 }, + (CONST WCHAR[]) { 'C', 'R', 'C', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESC1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'o', 's', 't', 'a', ' ', 'R', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESCds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESCdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESCt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESD.c b/lib/kernel32/nls/lcESD.c new file mode 100644 index 0000000..e9c9372 --- /dev/null +++ b/lib/kernel32/nls/lcESD.c @@ -0,0 +1,151 @@ +/* + * nls/lcESD.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESD0[]= +{ + NULL, + (CONST WCHAR[]) { '1', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'D', 'o', 'm', 'i', 'n', 'i', 'c', 'a', 'n', ' ', 'R', 'e', 'p', 'u', 'b', 'l', 'i', 'c', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'D', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'i', 'c', 'a', 'n', ' ', 'R', 'e', 'p', 'u', 'b', 'l', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'D', 'O', 'M', 0 }, + (CONST WCHAR[]) { 'R', 'e', 'p', 0xFA, 'b', 'l', 'i', 'c', 'a', ' ', 'D', 'o', 'm', 'i', 'n', 'i', 'c', 'a', 'n', 'a', 0 }, + (CONST WCHAR[]) { '1', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'R', 'D', '$', 0 }, + (CONST WCHAR[]) { 'D', 'O', 'P', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESD1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'i', 'c', 'a', 'n', ' ', 'R', 'e', 'p', 'u', 'b', 'l', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESDds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '/', 'd', 'd', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESDdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESDt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESE.c b/lib/kernel32/nls/lcESE.c new file mode 100644 index 0000000..fbf0468 --- /dev/null +++ b/lib/kernel32/nls/lcESE.c @@ -0,0 +1,144 @@ +/* + * nls/lcESE.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESE0[]= +{ + NULL, + (CONST WCHAR[]) { '4', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'E', 'l', ' ', 'S', 'a', 'l', 'v', 'a', 'd', 'o', 'r', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'E', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '0', '3', 0 }, + (CONST WCHAR[]) { 'E', 'l', ' ', 'S', 'a', 'l', 'v', 'a', 'd', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'L', 'V', 0 }, + (CONST WCHAR[]) { 'E', 'l', ' ', 'S', 'a', 'l', 'v', 'a', 'd', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'P', 'A', 0 }, + (CONST WCHAR[]) { '5', '0', '3', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'C', 0 }, + (CONST WCHAR[]) { 'S', 'V', 'C', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESE1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'E', 'l', ' ', 'S', 'a', 'l', 'v', 'a', 'd', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESEds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESEdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESEt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESF.c b/lib/kernel32/nls/lcESF.c new file mode 100644 index 0000000..f2df8c5 --- /dev/null +++ b/lib/kernel32/nls/lcESF.c @@ -0,0 +1,151 @@ +/* + * nls/lcESF.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESF0[]= +{ + NULL, + (CONST WCHAR[]) { '3', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'E', 'c', 'u', 'a', 'd', 'o', 'r', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'F', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '9', '3', 0 }, + (CONST WCHAR[]) { 'E', 'c', 'u', 'a', 'd', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'E', 'C', 'U', 0 }, + (CONST WCHAR[]) { 'E', 'c', 'u', 'a', 'd', 'o', 'r', 0 }, + (CONST WCHAR[]) { '3', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '9', '3', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', '/', 0 }, + (CONST WCHAR[]) { 'E', 'C', 'S', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESF1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'E', 'c', 'u', 'a', 'd', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESFds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESFdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESFt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESG.c b/lib/kernel32/nls/lcESG.c new file mode 100644 index 0000000..49e11c2 --- /dev/null +++ b/lib/kernel32/nls/lcESG.c @@ -0,0 +1,151 @@ +/* + * nls/lcESG.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESG0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'G', 'u', 'a', 't', 'e', 'm', 'a', 'l', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'G', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '0', '2', 0 }, + (CONST WCHAR[]) { 'G', 'u', 'a', 't', 'e', 'm', 'a', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'G', 'T', 'M', 0 }, + (CONST WCHAR[]) { 'G', 'u', 'a', 't', 'e', 'm', 'a', 'l', 'a', 0 }, + (CONST WCHAR[]) { '1', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '0', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'Q', 0 }, + (CONST WCHAR[]) { 'G', 'T', 'Q', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESG1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'G', 'u', 'a', 't', 'e', 'm', 'a', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESGds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESGdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESGt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESH.c b/lib/kernel32/nls/lcESH.c new file mode 100644 index 0000000..deae6d2 --- /dev/null +++ b/lib/kernel32/nls/lcESH.c @@ -0,0 +1,144 @@ +/* + * nls/lcESH.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESH0[]= +{ + NULL, + (CONST WCHAR[]) { '4', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'H', 'o', 'n', 'd', 'u', 'r', 'a', 's', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'H', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '0', '4', 0 }, + (CONST WCHAR[]) { 'H', 'o', 'n', 'd', 'u', 'r', 'a', 's', 0 }, + (CONST WCHAR[]) { 'H', 'N', 'D', 0 }, + (CONST WCHAR[]) { 'H', 'o', 'n', 'd', 'u', 'r', 'a', 's', 0 }, + (CONST WCHAR[]) { 'S', 'P', 'A', 0 }, + (CONST WCHAR[]) { '5', '0', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'L', 0 }, + (CONST WCHAR[]) { 'H', 'N', 'L', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESH1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'H', 'o', 'n', 'd', 'u', 'r', 'a', 's', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESHds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESHdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESHt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESI.c b/lib/kernel32/nls/lcESI.c new file mode 100644 index 0000000..d2b10f6 --- /dev/null +++ b/lib/kernel32/nls/lcESI.c @@ -0,0 +1,144 @@ +/* + * nls/lcESI.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESI0[]= +{ + NULL, + (CONST WCHAR[]) { '4', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'N', 'i', 'c', 'a', 'r', 'a', 'g', 'u', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'I', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '0', '5', 0 }, + (CONST WCHAR[]) { 'N', 'i', 'c', 'a', 'r', 'a', 'g', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'N', 'I', 'C', 0 }, + (CONST WCHAR[]) { 'N', 'i', 'c', 'a', 'r', 0xE1, 'g', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'P', 'A', 0 }, + (CONST WCHAR[]) { '5', '0', '5', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 'C', 0 }, + (CONST WCHAR[]) { 'N', 'I', 'O', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESI1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'N', 'i', 'c', 'a', 'r', 'a', 'g', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESIds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESIdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESIt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESL.c b/lib/kernel32/nls/lcESL.c new file mode 100644 index 0000000..f9aa864 --- /dev/null +++ b/lib/kernel32/nls/lcESL.c @@ -0,0 +1,151 @@ +/* + * nls/lcESL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESL0[]= +{ + NULL, + (CONST WCHAR[]) { '3', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'C', 'h', 'i', 'l', 'e', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'L', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '6', 0 }, + (CONST WCHAR[]) { 'C', 'h', 'i', 'l', 'e', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'L', 0 }, + (CONST WCHAR[]) { 'C', 'h', 'i', 'l', 'e', 0 }, + (CONST WCHAR[]) { '3', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '6', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'C', 'h', '$', 0 }, + (CONST WCHAR[]) { 'C', 'L', 'P', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', '2', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESL1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'h', 'i', 'l', 'e', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESLds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESLdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESLt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESM.c b/lib/kernel32/nls/lcESM.c new file mode 100644 index 0000000..59d5cb3 --- /dev/null +++ b/lib/kernel32/nls/lcESM.c @@ -0,0 +1,151 @@ +/* + * nls/lcESM.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESM0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'M', 'e', 'x', 'i', 'c', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'M', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '2', 0 }, + (CONST WCHAR[]) { 'M', 'e', 'x', 'i', 'c', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'E', 'X', 0 }, + (CONST WCHAR[]) { 'M', 0xE9, 'x', 'i', 'c', 'o', 0 }, + (CONST WCHAR[]) { '0', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'M', 'X', 'N', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESM1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'M', 'e', 'x', 'i', 'c', 'o', 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESMds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESMdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESMt[]= +{ + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESN.c b/lib/kernel32/nls/lcESN.c new file mode 100644 index 0000000..697e694 --- /dev/null +++ b/lib/kernel32/nls/lcESN.c @@ -0,0 +1,151 @@ +/* + * nls/lcESN.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESN0[]= +{ + NULL, + (CONST WCHAR[]) { '0', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'M', 'o', 'd', 'e', 'r', 'n', ' ', 'S', 'o', 'r', 't', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'N', 0 }, + (CONST WCHAR[]) { 'e', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'a', 0 }, + (CONST WCHAR[]) { '0', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'P', 't', 's', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'm', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'v', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 's', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'j', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'v', 'i', 'e', 0 }, + (CONST WCHAR[]) { 's', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'e', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'e', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESN1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '-', ' ', 'M', 'o', 'd', 'e', 'r', 'n', ' ', 'S', 'o', 'r', 't', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESNds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESNdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESNt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '\'', 'H', '\'', 'm', 'm', '\'', '\'', '\'', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESO.c b/lib/kernel32/nls/lcESO.c new file mode 100644 index 0000000..e93f1ef --- /dev/null +++ b/lib/kernel32/nls/lcESO.c @@ -0,0 +1,151 @@ +/* + * nls/lcESO.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESO0[]= +{ + NULL, + (CONST WCHAR[]) { '2', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'C', 'o', 'l', 'o', 'm', 'b', 'i', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'O', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '7', 0 }, + (CONST WCHAR[]) { 'C', 'o', 'l', 'o', 'm', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'C', 'O', 'L', 0 }, + (CONST WCHAR[]) { 'C', 'o', 'l', 'o', 'm', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { '2', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '7', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'C', '$', 0 }, + (CONST WCHAR[]) { 'C', 'O', 'P', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESO1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'o', 'l', 'o', 'm', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESOds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESOdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESOt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESP.c b/lib/kernel32/nls/lcESP.c new file mode 100644 index 0000000..73eb744 --- /dev/null +++ b/lib/kernel32/nls/lcESP.c @@ -0,0 +1,151 @@ +/* + * nls/lcESP.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESP0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'T', 'r', 'a', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', ' ', 'S', 'o', 'r', 't', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { 'e', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'P', 't', 's', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'm', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'v', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 's', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'j', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'v', 'i', 'e', 0 }, + (CONST WCHAR[]) { 's', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'e', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'e', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESP1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '-', ' ', 'T', 'r', 'a', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', ' ', 'S', 'o', 'r', 't', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESPds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESPdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESPt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '\'', 'H', '\'', 'm', 'm', '\'', '\'', '\'', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESR.c b/lib/kernel32/nls/lcESR.c new file mode 100644 index 0000000..515cd1c --- /dev/null +++ b/lib/kernel32/nls/lcESR.c @@ -0,0 +1,151 @@ +/* + * nls/lcESR.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESR0[]= +{ + NULL, + (CONST WCHAR[]) { '2', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'P', 'e', 'r', 'u', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'R', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '1', 0 }, + (CONST WCHAR[]) { 'P', 'e', 'r', 'u', 0 }, + (CONST WCHAR[]) { 'P', 'E', 'R', 0 }, + (CONST WCHAR[]) { 'P', 'e', 'r', 0xFA, 0 }, + (CONST WCHAR[]) { '2', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', '/', 0 }, + (CONST WCHAR[]) { 'P', 'E', 'S', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESR1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'P', 'e', 'r', 'u', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESRds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESRdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESRt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESS.c b/lib/kernel32/nls/lcESS.c new file mode 100644 index 0000000..14db6ab --- /dev/null +++ b/lib/kernel32/nls/lcESS.c @@ -0,0 +1,151 @@ +/* + * nls/lcESS.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESS0[]= +{ + NULL, + (CONST WCHAR[]) { '2', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'A', 'r', 'g', 'e', 'n', 't', 'i', 'n', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'S', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '4', 0 }, + (CONST WCHAR[]) { 'A', 'r', 'g', 'e', 'n', 't', 'i', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'A', 'R', 'G', 0 }, + (CONST WCHAR[]) { 'A', 'r', 'g', 'e', 'n', 't', 'i', 'n', 'a', 0 }, + (CONST WCHAR[]) { '2', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'A', 'R', 'S', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESS1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'A', 'r', 'g', 'e', 'n', 't', 'i', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESSds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESSdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESSt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESU.c b/lib/kernel32/nls/lcESU.c new file mode 100644 index 0000000..5f809df --- /dev/null +++ b/lib/kernel32/nls/lcESU.c @@ -0,0 +1,144 @@ +/* + * nls/lcESU.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESU0[]= +{ + NULL, + (CONST WCHAR[]) { '5', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'P', 'u', 'e', 'r', 't', 'o', ' ', 'R', 'i', 'c', 'o', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'U', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'P', 'u', 'e', 'r', 't', 'o', ' ', 'R', 'i', 'c', 'o', 0 }, + (CONST WCHAR[]) { 'P', 'R', 'I', 0 }, + (CONST WCHAR[]) { 'P', 'u', 'e', 'r', 't', 'o', ' ', 'R', 'i', 'c', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'P', 'A', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'U', 'S', 'D', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESU1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'P', 'u', 'e', 'r', 't', 'o', ' ', 'R', 'i', 'c', 'o', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESUds[]= +{ + (CONST WCHAR[]) { 'M', 'M', '-', 'd', 'd', '-', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESUdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESUt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESV.c b/lib/kernel32/nls/lcESV.c new file mode 100644 index 0000000..ffc8b59 --- /dev/null +++ b/lib/kernel32/nls/lcESV.c @@ -0,0 +1,151 @@ +/* + * nls/lcESV.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESV0[]= +{ + NULL, + (CONST WCHAR[]) { '2', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'V', 'e', 'n', 'e', 'z', 'u', 'e', 'l', 'a', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'V', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '8', 0 }, + (CONST WCHAR[]) { 'V', 'e', 'n', 'e', 'z', 'u', 'e', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'V', 'E', 'N', 0 }, + (CONST WCHAR[]) { 'V', 'e', 'n', 'e', 'z', 'u', 'e', 'l', 'a', 0 }, + (CONST WCHAR[]) { '2', '0', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '8', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'B', 's', 0 }, + (CONST WCHAR[]) { 'V', 'E', 'B', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', '2', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESV1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'V', 'e', 'n', 'e', 'z', 'u', 'e', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESVds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESVdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESVt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESY.c b/lib/kernel32/nls/lcESY.c new file mode 100644 index 0000000..66dd645 --- /dev/null +++ b/lib/kernel32/nls/lcESY.c @@ -0,0 +1,151 @@ +/* + * nls/lcESY.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESY0[]= +{ + NULL, + (CONST WCHAR[]) { '3', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'U', 'r', 'u', 'g', 'u', 'a', 'y', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'Y', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '9', '8', 0 }, + (CONST WCHAR[]) { 'U', 'r', 'u', 'g', 'u', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'U', 'R', 'Y', 0 }, + (CONST WCHAR[]) { 'U', 'r', 'u', 'g', 'u', 'a', 'y', 0 }, + (CONST WCHAR[]) { '3', '8', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '9', '8', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'N', 'U', '$', 0 }, + (CONST WCHAR[]) { 'U', 'Y', 'U', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESY1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'U', 'r', 'u', 'g', 'u', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESYds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESYdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESYt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcESZ.c b/lib/kernel32/nls/lcESZ.c new file mode 100644 index 0000000..f673d8b --- /dev/null +++ b/lib/kernel32/nls/lcESZ.c @@ -0,0 +1,151 @@ +/* + * nls/lcESZ.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ESZ0[]= +{ + NULL, + (CONST WCHAR[]) { '3', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', ' ', '(', 'P', 'a', 'r', 'a', 'g', 'u', 'a', 'y', ')', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'Z', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 0xF1, 'o', 'l', 0 }, + (CONST WCHAR[]) { '5', '9', '5', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'r', 'a', 'g', 'u', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'P', 'R', 'Y', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'r', 'a', 'g', 'u', 'a', 'y', 0 }, + (CONST WCHAR[]) { '3', 'c', '0', 'a', 0 }, + (CONST WCHAR[]) { '5', '9', '5', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'G', 0 }, + (CONST WCHAR[]) { 'P', 'Y', 'G', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'A', 'M', 0 }, + (CONST WCHAR[]) { 'P', 'M', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 'e', 's', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 'r', 'c', 'o', 'l', 'e', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 'v', 'e', 's', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 'r', 'n', 'e', 's', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0xE9, 0 }, + (CONST WCHAR[]) { 'J', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'V', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'e', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 'u', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 'i', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESZ1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'p', 'a', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'r', 'a', 'g', 'u', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ESZds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESZdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ESZt[]= +{ + (CONST WCHAR[]) { 'h', 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', ' ', 't', 't', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcETI.c b/lib/kernel32/nls/lcETI.c new file mode 100644 index 0000000..0f6e6cd --- /dev/null +++ b/lib/kernel32/nls/lcETI.c @@ -0,0 +1,144 @@ +/* + * nls/lcETI.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ETI0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '5', 0 }, + (CONST WCHAR[]) { 'E', 's', 't', 'o', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'E', 'T', 'I', 0 }, + (CONST WCHAR[]) { 'e', 'e', 's', 't', 'i', 0 }, + (CONST WCHAR[]) { '3', '7', '2', 0 }, + (CONST WCHAR[]) { 'E', 's', 't', 'o', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'T', 0 }, + (CONST WCHAR[]) { 'E', 'e', 's', 't', 'i', 0 }, + (CONST WCHAR[]) { '0', '4', '2', '5', 0 }, + (CONST WCHAR[]) { '3', '7', '2', 0 }, + (CONST WCHAR[]) { '7', '7', '5', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', 0 }, + (CONST WCHAR[]) { 'E', 'E', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', '\'', '.', ' ', 'A', '.', '\'', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'e', 's', 'm', 'a', 's', 'p', 0xE4, 'e', 'v', 0 }, + (CONST WCHAR[]) { 't', 'e', 'i', 's', 'i', 'p', 0xE4, 'e', 'v', 0 }, + (CONST WCHAR[]) { 'k', 'o', 'l', 'm', 'a', 'p', 0xE4, 'e', 'v', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'l', 'j', 'a', 'p', 0xE4, 'e', 'v', 0 }, + (CONST WCHAR[]) { 'r', 'e', 'e', 'd', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'a', 'u', 'p', 0xE4, 'e', 'v', 0 }, + (CONST WCHAR[]) { 'p', 0xFC, 'h', 'a', 'p', 0xE4, 'e', 'v', 0 }, + (CONST WCHAR[]) { 'E', 0 }, + (CONST WCHAR[]) { 'T', 0 }, + (CONST WCHAR[]) { 'K', 0 }, + (CONST WCHAR[]) { 'N', 0 }, + (CONST WCHAR[]) { 'R', 0 }, + (CONST WCHAR[]) { 'L', 0 }, + (CONST WCHAR[]) { 'P', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 0xE4, 'r', 't', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 't', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'V', 'e', 'e', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xE4, 'r', 't', 's', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 't', 's', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x7, 0x8000, 0x3848, 0x1000, 0, 0, 0, 0, 0x80, 0, 0, 0x800, 0x92, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ETI1[]= +{ + NULL, + (CONST WCHAR[]) { 'E', 's', 't', 'o', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'E', 's', 't', 'o', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '7', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ETIds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ETIdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', '\'', '.', ' ', 'A', '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ETIt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcEUQ.c b/lib/kernel32/nls/lcEUQ.c new file mode 100644 index 0000000..836eba9 --- /dev/null +++ b/lib/kernel32/nls/lcEUQ.c @@ -0,0 +1,144 @@ +/* + * nls/lcEUQ.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_EUQ0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', 'd', 0 }, + (CONST WCHAR[]) { 'B', 'a', 's', 'q', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'E', 'U', 'Q', 0 }, + (CONST WCHAR[]) { 'E', 'u', 's', 'k', 'a', 'r', 'a', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { 'E', 's', 'p', 'a', 'i', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'a', 0 }, + (CONST WCHAR[]) { '3', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'p', 't', 'a', '.', 0 }, + (CONST WCHAR[]) { 'E', 'S', 'P', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', '.', '\'', 'e', 'k', 'o', '\'', ' ', 'M', 'M', 'M', 'M', '\'', 'k', ' ', '\'', 'd', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'A', 's', 't', 'e', 'l', 'e', 'h', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'A', 's', 't', 'e', 'a', 'r', 't', 'e', 'a', 0 }, + (CONST WCHAR[]) { 'A', 's', 't', 'e', 'a', 'z', 'k', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'O', 's', 't', 'e', 'g', 'u', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'O', 's', 't', 'i', 'r', 'a', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'L', 'a', 'r', 'u', 'n', 'b', 'a', 't', 'a', 0 }, + (CONST WCHAR[]) { 'I', 'g', 'a', 'n', 'd', 'e', 'a', 0 }, + (CONST WCHAR[]) { 'A', 'l', '.', 0 }, + (CONST WCHAR[]) { 'A', 's', '.', 0 }, + (CONST WCHAR[]) { 'A', 'z', '.', 0 }, + (CONST WCHAR[]) { 'O', 'g', '.', 0 }, + (CONST WCHAR[]) { 'O', 'r', '.', 0 }, + (CONST WCHAR[]) { 'L', 'r', '.', 0 }, + (CONST WCHAR[]) { 'I', 'g', '.', 0 }, + (CONST WCHAR[]) { 'u', 'r', 't', 'a', 'r', 'r', 'i', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'o', 't', 's', 'a', 'i', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 'x', 'o', 'a', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'i', 'r', 'i', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 'a', 't', 'z', 'a', 0 }, + (CONST WCHAR[]) { 'e', 'k', 'a', 'i', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'u', 'z', 't', 'a', 'i', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'u', 'z', 't', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'i', 'r', 'a', 'i', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'u', 'r', 'r', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'a', 'z', 'a', 'r', 'o', 'a', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'e', 'n', 'd', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'u', 'r', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 't', 's', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', '.', 0 }, + (CONST WCHAR[]) { 'e', 'k', 'a', '.', 0 }, + (CONST WCHAR[]) { 'u', 'z', 't', '.', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'u', '.', 0 }, + (CONST WCHAR[]) { 'i', 'r', 'a', '.', 0 }, + (CONST WCHAR[]) { 'u', 'r', 'r', '.', 0 }, + (CONST WCHAR[]) { 'a', 'z', 'a', '.', 0 }, + (CONST WCHAR[]) { 'a', 'b', 'e', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_EUQ1[]= +{ + NULL, + (CONST WCHAR[]) { 'B', 'a', 's', 'q', 'u', 'e', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_EUQds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_EUQdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', '.', '\'', 'e', 'k', 'o', '\'', ' ', 'M', 'M', 'M', 'M', '\'', 'k', ' ', '\'', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_EUQt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFIN.c b/lib/kernel32/nls/lcFIN.c new file mode 100644 index 0000000..726b404 --- /dev/null +++ b/lib/kernel32/nls/lcFIN.c @@ -0,0 +1,150 @@ +/* + * nls/lcFIN.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FIN0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', 'b', 0 }, + (CONST WCHAR[]) { 'F', 'i', 'n', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'F', 'I', 'N', 0 }, + (CONST WCHAR[]) { 's', 'u', 'o', 'm', 'i', 0 }, + (CONST WCHAR[]) { '3', '5', '8', 0 }, + (CONST WCHAR[]) { 'F', 'i', 'n', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'F', 'I', 'N', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'o', 'm', 'i', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'b', 0 }, + (CONST WCHAR[]) { '3', '5', '8', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'm', 'k', 0 }, + (CONST WCHAR[]) { 'F', 'I', 'M', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', '\'', 't', 'a', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'n', 'a', 'n', 't', 'a', 'i', 0 }, + (CONST WCHAR[]) { 't', 'i', 'i', 's', 't', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'k', 'e', 's', 'k', 'i', 'v', 'i', 'i', 'k', 'k', 'o', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 's', 't', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'p', 'e', 'r', 'j', 'a', 'n', 't', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'l', 'a', 'u', 'a', 'n', 't', 'a', 'i', 0 }, + (CONST WCHAR[]) { 's', 'u', 'n', 'n', 'u', 'n', 't', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0 }, + (CONST WCHAR[]) { 't', 'i', 0 }, + (CONST WCHAR[]) { 'k', 'e', 0 }, + (CONST WCHAR[]) { 't', 'o', 0 }, + (CONST WCHAR[]) { 'p', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'a', 0 }, + (CONST WCHAR[]) { 's', 'u', 0 }, + (CONST WCHAR[]) { 't', 'a', 'm', 'm', 'i', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'h', 'e', 'l', 'm', 'i', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'l', 'i', 's', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'h', 'u', 'h', 't', 'i', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 't', 'o', 'u', 'k', 'o', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'k', 'e', 's', 0xE4, 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'h', 'e', 'i', 'n', 0xE4, 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'e', 'l', 'o', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 's', 'y', 'y', 's', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'l', 'o', 'k', 'a', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'r', 'a', 's', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 'j', 'o', 'u', 'l', 'u', 'k', 'u', 'u', 0 }, + (CONST WCHAR[]) { 't', 'a', 'm', 'm', 'i', 0 }, + (CONST WCHAR[]) { 'h', 'e', 'l', 'm', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 'h', 'u', 'h', 't', 'i', 0 }, + (CONST WCHAR[]) { 't', 'o', 'u', 'k', 'o', 0 }, + (CONST WCHAR[]) { 'k', 'e', 's', 0xE4, 0 }, + (CONST WCHAR[]) { 'h', 'e', 'i', 'n', 0xE4, 0 }, + (CONST WCHAR[]) { 'e', 'l', 'o', 0 }, + (CONST WCHAR[]) { 's', 'y', 'y', 's', 0 }, + (CONST WCHAR[]) { 'l', 'o', 'k', 'a', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'r', 'a', 's', 0 }, + (CONST WCHAR[]) { 'j', 'o', 'u', 'l', 'u', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FIN1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'i', 'n', 'n', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'F', 'i', 'n', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FINds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FINdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', '\'', 't', 'a', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', '\'', 't', 'a', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FINt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFOS.c b/lib/kernel32/nls/lcFOS.c new file mode 100644 index 0000000..a4fa562 --- /dev/null +++ b/lib/kernel32/nls/lcFOS.c @@ -0,0 +1,144 @@ +/* + * nls/lcFOS.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FOS0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '3', '8', 0 }, + (CONST WCHAR[]) { 'F', 'a', 'e', 'r', 'o', 'e', 's', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'O', 'S', 0 }, + (CONST WCHAR[]) { 'f', 0xF8, 'r', 'o', 'y', 's', 'k', 't', 0 }, + (CONST WCHAR[]) { '2', '9', '8', 0 }, + (CONST WCHAR[]) { 'F', 'a', 'e', 'r', 'o', 'e', ' ', 'I', 's', 'l', 'a', 'n', 'd', 's', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'O', 0 }, + (CONST WCHAR[]) { 'F', 0xF8, 'r', 'o', 'y', 'a', 'r', 0 }, + (CONST WCHAR[]) { '0', '4', '3', '8', 0 }, + (CONST WCHAR[]) { '2', '9', '8', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'K', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', '2', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'n', 'a', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 't', 0xFD, 's', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'i', 'k', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'h', 0xF3, 's', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0xED, 'g', 'g', 'j', 'a', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'l', 'e', 'y', 'g', 'a', 'r', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 's', 'u', 'n', 'n', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'n', 0 }, + (CONST WCHAR[]) { 't', 0xFD, 's', 0 }, + (CONST WCHAR[]) { 'm', 'i', 'k', 0 }, + (CONST WCHAR[]) { 'h', 0xF3, 's', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0xED, 0 }, + (CONST WCHAR[]) { 'l', 'e', 'y', 'g', 0 }, + (CONST WCHAR[]) { 's', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0xED, 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FOS1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'a', 'e', 'r', 'o', 'e', 's', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'a', 'e', 'r', 'o', 'e', ' ', 'I', 's', 'l', 'a', 'n', 'd', 's', 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '.', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FOSds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FOSdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FOSt[]= +{ + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFRA.c b/lib/kernel32/nls/lcFRA.c new file mode 100644 index 0000000..241ba91 --- /dev/null +++ b/lib/kernel32/nls/lcFRA.c @@ -0,0 +1,152 @@ +/* + * nls/lcFRA.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FRA0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', 'c', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', ' ', '(', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ')', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'A', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'a', 'n', 0xE7, 'a', 'i', 's', 0 }, + (CONST WCHAR[]) { '3', '3', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'a', 'n', 'c', 'e', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'A', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'a', 'n', 'c', 'e', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'c', 0 }, + (CONST WCHAR[]) { '3', '3', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'F', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'F', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'd', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'a', 'n', 'c', 'h', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', '.', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', '.', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', '.', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', '.', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', '.', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', 'l', 'e', 't', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', '.', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRA1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'a', 'n', 'c', 'e', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FRAds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRAdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRAt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '\'', ' ', 'h', ' ', '\'', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFRB.c b/lib/kernel32/nls/lcFRB.c new file mode 100644 index 0000000..ca3122a --- /dev/null +++ b/lib/kernel32/nls/lcFRB.c @@ -0,0 +1,153 @@ +/* + * nls/lcFRB.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FRB0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '0', 'c', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', ' ', '(', 'B', 'e', 'l', 'g', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'B', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'a', 'n', 0xE7, 'a', 'i', 's', 0 }, + (CONST WCHAR[]) { '3', '2', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'g', 'i', 'u', 'm', 0 }, + (CONST WCHAR[]) { 'B', 'E', 'L', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'g', 'i', 'q', 'u', 'e', 0 }, + (CONST WCHAR[]) { '0', '8', '0', 'c', 0 }, + (CONST WCHAR[]) { '3', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'F', 'B', 0 }, + (CONST WCHAR[]) { 'B', 'E', 'F', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'd', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'a', 'n', 'c', 'h', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', '.', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', '.', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', '.', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', '.', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', '.', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', 'l', 'e', 't', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', '.', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRB1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'g', 'i', 'u', 'm', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FRBds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '/', 'M', 'M', '/', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRBdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRBt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', '\'', ' ', 'h', ' ', '\'', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', '\'', ' ', 'h', ' ', '\'', 'm', '\'', ' ', 'm', 'i', 'n', ' ', '\'', 's', '\'', ' ', 's', ' ', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFRC.c b/lib/kernel32/nls/lcFRC.c new file mode 100644 index 0000000..c95cf01 --- /dev/null +++ b/lib/kernel32/nls/lcFRC.c @@ -0,0 +1,151 @@ +/* + * nls/lcFRC.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FRC0[]= +{ + NULL, + (CONST WCHAR[]) { '0', 'c', '0', 'c', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', ' ', '(', 'C', 'a', 'n', 'a', 'd', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'C', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'a', 'n', 0xE7, 'a', 'i', 's', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'n', 'a', 'd', 'a', 0 }, + (CONST WCHAR[]) { 'C', 'A', 'N', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'n', 'a', 'd', 'a', 0 }, + (CONST WCHAR[]) { '0', 'c', '0', 'c', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { 'C', 'A', 'D', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'd', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'a', 'n', 'c', 'h', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', '.', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', '.', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', '.', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', '.', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', '.', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', 'l', 'e', 't', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', '.', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRC1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'C', 'a', 'n', 'a', 'd', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FRCds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', ' ', 'M', 'M', ' ', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRCdl[]= +{ + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ',', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRCt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '\'', ' ', 'h', ' ', '\'', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFRL.c b/lib/kernel32/nls/lcFRL.c new file mode 100644 index 0000000..7edfd40 --- /dev/null +++ b/lib/kernel32/nls/lcFRL.c @@ -0,0 +1,152 @@ +/* + * nls/lcFRL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FRL0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '4', '0', 'c', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', ' ', '(', 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', ')', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'L', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'a', 'n', 0xE7, 'a', 'i', 's', 0 }, + (CONST WCHAR[]) { '3', '5', '2', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', 0 }, + (CONST WCHAR[]) { 'L', 'U', 'X', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', 0 }, + (CONST WCHAR[]) { '1', '4', '0', 'c', 0 }, + (CONST WCHAR[]) { '3', '5', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'F', 0 }, + (CONST WCHAR[]) { 'L', 'U', 'F', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'd', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'a', 'n', 'c', 'h', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', '.', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', '.', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', '.', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', '.', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', '.', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', 'l', 'e', 't', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', '.', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRL1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'L', 'u', 'x', 'e', 'm', 'b', 'o', 'u', 'r', 'g', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FRLds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRLdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRLt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '\'', ' ', 'h', ' ', '\'', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcFRS.c b/lib/kernel32/nls/lcFRS.c new file mode 100644 index 0000000..424ccb0 --- /dev/null +++ b/lib/kernel32/nls/lcFRS.c @@ -0,0 +1,150 @@ +/* + * nls/lcFRS.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_FRS0[]= +{ + NULL, + (CONST WCHAR[]) { '1', '0', '0', 'c', 0 }, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', ' ', '(', 'S', 'w', 'i', 's', 's', ')', 0 }, + (CONST WCHAR[]) { 'F', 'R', 'S', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'a', 'n', 0xE7, 'a', 'i', 's', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'i', 't', 'z', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'E', 0 }, + (CONST WCHAR[]) { 'S', 'u', 'i', 's', 's', 'e', 0 }, + (CONST WCHAR[]) { '1', '0', '0', 'c', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', 'F', 'r', '.', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'F', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'd', 'r', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', 'e', 'd', 'i', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', 'a', 'n', 'c', 'h', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', '.', 0 }, + (CONST WCHAR[]) { 'j', 'e', 'u', '.', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', '.', 0 }, + (CONST WCHAR[]) { 's', 'a', 'm', '.', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'm', '.', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', 'i', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', 'l', 'e', 't', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', '.', 0 }, + (CONST WCHAR[]) { 'f', 0xE9, 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'i', 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'o', 0xFB, 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 0xE9, 'c', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRS1[]= +{ + NULL, + (CONST WCHAR[]) { 'F', 'r', 'e', 'n', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'i', 't', 'z', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_FRSds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', '.', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRSdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_FRSt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '\'', ' ', 'h', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcHRV.c b/lib/kernel32/nls/lcHRV.c new file mode 100644 index 0000000..4c5b3fd --- /dev/null +++ b/lib/kernel32/nls/lcHRV.c @@ -0,0 +1,146 @@ +/* + * nls/lcHRV.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_HRV0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', 'a', 0 }, + (CONST WCHAR[]) { 'C', 'r', 'o', 'a', 't', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'R', 'V', 0 }, + (CONST WCHAR[]) { 'h', 'r', 'v', 'a', 't', 's', 'k', 'i', 0 }, + (CONST WCHAR[]) { '3', '8', '5', 0 }, + (CONST WCHAR[]) { 'C', 'r', 'o', 'a', 't', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'R', 'V', 0 }, + (CONST WCHAR[]) { 'H', 'r', 'v', 'a', 't', 's', 'k', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '1', 'a', 0 }, + (CONST WCHAR[]) { '3', '8', '5', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'K', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'R', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '9', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 'e', 'd', 'j', 'e', 'l', 'j', 'a', 'k', 0 }, + (CONST WCHAR[]) { 'u', 't', 'o', 'r', 'a', 'k', 0 }, + (CONST WCHAR[]) { 's', 'r', 'i', 'j', 'e', 'd', 'a', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 't', 'v', 'r', 't', 'a', 'k', 0 }, + (CONST WCHAR[]) { 'p', 'e', 't', 'a', 'k', 0 }, + (CONST WCHAR[]) { 's', 'u', 'b', 'o', 't', 'a', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 'j', 'e', 'l', 'j', 'a', 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'u', 't', 'o', 0 }, + (CONST WCHAR[]) { 's', 'r', 'i', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 't', 0 }, + (CONST WCHAR[]) { 'p', 'e', 't', 0 }, + (CONST WCHAR[]) { 's', 'u', 'b', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 0 }, + (CONST WCHAR[]) { 's', 'i', 'j', 'e', 0x10D, 'a', 'n', 'j', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'l', 'j', 'a', 0x10D, 'a', 0 }, + (CONST WCHAR[]) { 'o', 0x17E, 'u', 'j', 'a', 'k', 0 }, + (CONST WCHAR[]) { 't', 'r', 'a', 'v', 'a', 'n', 'j', 0 }, + (CONST WCHAR[]) { 's', 'v', 'i', 'b', 'a', 'n', 'j', 0 }, + (CONST WCHAR[]) { 'l', 'i', 'p', 'a', 'n', 'j', 0 }, + (CONST WCHAR[]) { 's', 'r', 'p', 'a', 'n', 'j', 0 }, + (CONST WCHAR[]) { 'k', 'o', 'l', 'o', 'v', 'o', 'z', 0 }, + (CONST WCHAR[]) { 'r', 'u', 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'l', 'i', 's', 't', 'o', 'p', 'a', 'd', 0 }, + (CONST WCHAR[]) { 's', 't', 'u', 'd', 'e', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'p', 'r', 'o', 's', 'i', 'n', 'a', 'c', 0 }, + (CONST WCHAR[]) { 's', 'i', 'j', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'l', 0 }, + (CONST WCHAR[]) { 'o', 0x17E, 'u', 0 }, + (CONST WCHAR[]) { 't', 'r', 'a', 0 }, + (CONST WCHAR[]) { 's', 'v', 'i', 0 }, + (CONST WCHAR[]) { 'l', 'i', 'p', 0 }, + (CONST WCHAR[]) { 's', 'r', 'p', 0 }, + (CONST WCHAR[]) { 'k', 'o', 'l', 0 }, + (CONST WCHAR[]) { 'r', 'u', 'j', 0 }, + (CONST WCHAR[]) { 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 's', 't', 'u', 0 }, + (CONST WCHAR[]) { 'p', 'r', 'o', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_HRV1[]= +{ + NULL, + (CONST WCHAR[]) { 'C', 'r', 'o', 'a', 't', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'C', 'r', 'o', 'a', 't', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '2', 0 }, + NULL +}; + +CONST WCHAR *__LC_HRVds[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', '.', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_HRVdl[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_HRVt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcHUN.c b/lib/kernel32/nls/lcHUN.c new file mode 100644 index 0000000..406dee4 --- /dev/null +++ b/lib/kernel32/nls/lcHUN.c @@ -0,0 +1,149 @@ +/* + * nls/lcHUN.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_HUN0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', 'e', 0 }, + (CONST WCHAR[]) { 'H', 'u', 'n', 'g', 'a', 'r', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'U', 'N', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'g', 'y', 'a', 'r', 0 }, + (CONST WCHAR[]) { '3', '6', 0 }, + (CONST WCHAR[]) { 'H', 'u', 'n', 'g', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'H', 'U', 'N', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'g', 'y', 'a', 'r', 'o', 'r', 's', 'z', 0xE1, 'g', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'e', 0 }, + (CONST WCHAR[]) { '3', '6', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'F', 't', 0 }, + (CONST WCHAR[]) { 'H', 'U', 'F', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', '.', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'd', '.', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'D', 'E', 0 }, + (CONST WCHAR[]) { 'D', 'U', 0 }, + (CONST WCHAR[]) { 'h', 0xE9, 't', 'f', 0x151, 0 }, + (CONST WCHAR[]) { 'k', 'e', 'd', 'd', 0 }, + (CONST WCHAR[]) { 's', 'z', 'e', 'r', 'd', 'a', 0 }, + (CONST WCHAR[]) { 'c', 's', 0xFC, 't', 0xF6, 'r', 't', 0xF6, 'k', 0 }, + (CONST WCHAR[]) { 'p', 0xE9, 'n', 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 's', 'z', 'o', 'm', 'b', 'a', 't', 0 }, + (CONST WCHAR[]) { 'v', 'a', 's', 0xE1, 'r', 'n', 'a', 'p', 0 }, + (CONST WCHAR[]) { 'H', 0 }, + (CONST WCHAR[]) { 'K', 0 }, + (CONST WCHAR[]) { 'S', 'z', 'e', 0 }, + (CONST WCHAR[]) { 'C', 's', 0 }, + (CONST WCHAR[]) { 'P', 0 }, + (CONST WCHAR[]) { 'S', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'V', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 0xE1, 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 0xE1, 'r', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'r', 'c', 'i', 'u', 's', 0 }, + (CONST WCHAR[]) { 0xE1, 'p', 'r', 'i', 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'j', 'u', 's', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'n', 'i', 'u', 's', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'l', 'i', 'u', 's', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 'z', 't', 'u', 's', 0 }, + (CONST WCHAR[]) { 's', 'z', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0xF3, 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', '.', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'r', 'c', '.', 0 }, + (CONST WCHAR[]) { 0xE1, 'p', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'j', '.', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'n', '.', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'l', '.', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', '.', 0 }, + (CONST WCHAR[]) { 's', 'z', 'e', 'p', 't', '.', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_HUN1[]= +{ + NULL, + (CONST WCHAR[]) { 'H', 'u', 'n', 'g', 'a', 'r', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'u', 'n', 'g', 'a', 'r', 'y', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_HUNds[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', '.', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', ' ', 'M', 'M', '.', ' ', 'd', 'd', '.', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_HUNdl[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'd', '.', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'd', 'd', '.', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_HUNt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcIND.c b/lib/kernel32/nls/lcIND.c new file mode 100644 index 0000000..f3f24ac --- /dev/null +++ b/lib/kernel32/nls/lcIND.c @@ -0,0 +1,144 @@ +/* + * nls/lcIND.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_IND0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '1', 0 }, + (CONST WCHAR[]) { 'I', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'I', 'N', 'D', 0 }, + (CONST WCHAR[]) { 'B', 'a', 'h', 'a', 's', 'a', ' ', 'I', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a', 0 }, + (CONST WCHAR[]) { '6', '2', 0 }, + (CONST WCHAR[]) { 'I', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'I', 'D', 'N', 0 }, + (CONST WCHAR[]) { 'I', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '2', '1', 0 }, + (CONST WCHAR[]) { '6', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'R', 'p', 0 }, + (CONST WCHAR[]) { 'I', 'D', 'R', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'S', 'e', 'n', 'i', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'l', 'a', 's', 'a', 0 }, + (CONST WCHAR[]) { 'R', 'a', 'b', 'u', 0 }, + (CONST WCHAR[]) { 'K', 'a', 'm', 'i', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'm', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'b', 't', 'u', 0 }, + (CONST WCHAR[]) { 'M', 'i', 'n', 'g', 'g', 'u', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'l', 0 }, + (CONST WCHAR[]) { 'R', 'a', 'b', 'u', 0 }, + (CONST WCHAR[]) { 'K', 'a', 'm', 'i', 's', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'm', 'a', 't', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'b', 't', 'u', 0 }, + (CONST WCHAR[]) { 'M', 'i', 'n', 'g', 'g', 'u', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 'e', 't', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'u', 's', 't', 'u', 's', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'p', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'D', 'e', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'p', 0 }, + (CONST WCHAR[]) { 'D', 'e', 's', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_IND1[]= +{ + NULL, + (CONST WCHAR[]) { 'I', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'I', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_INDds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_INDdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_INDt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcISL.c b/lib/kernel32/nls/lcISL.c new file mode 100644 index 0000000..32f72d3 --- /dev/null +++ b/lib/kernel32/nls/lcISL.c @@ -0,0 +1,151 @@ +/* + * nls/lcISL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ISL0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '0', 'f', 0 }, + (CONST WCHAR[]) { 'I', 'c', 'e', 'l', 'a', 'n', 'd', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'I', 'S', 'L', 0 }, + (CONST WCHAR[]) { 0xED, 's', 'l', 'e', 'n', 's', 'k', 'a', 0 }, + (CONST WCHAR[]) { '3', '5', '4', 0 }, + (CONST WCHAR[]) { 'I', 'c', 'e', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'I', 'S', 'L', 0 }, + (CONST WCHAR[]) { 0xCD, 's', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { '0', '4', '0', 'f', 0 }, + (CONST WCHAR[]) { '3', '5', '4', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', '.', 0 }, + (CONST WCHAR[]) { 'I', 'S', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'n', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 0xFE, 'r', 'i', 0xF0, 'j', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'i', 0xF0, 'v', 'i', 'k', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'i', 'm', 'm', 't', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'f', 0xF6, 's', 't', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'l', 'a', 'u', 'g', 'a', 'r', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 's', 'u', 'n', 'n', 'u', 'd', 'a', 'g', 'u', 'r', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'n', '.', 0 }, + (CONST WCHAR[]) { 0xFE, 'r', 'i', '.', 0 }, + (CONST WCHAR[]) { 'm', 'i', 0xF0, '.', 0 }, + (CONST WCHAR[]) { 'f', 'i', 'm', '.', 0 }, + (CONST WCHAR[]) { 'f', 0xF6, 's', '.', 0 }, + (CONST WCHAR[]) { 'l', 'a', 'u', '.', 0 }, + (CONST WCHAR[]) { 's', 'u', 'n', '.', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0xFA, 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 0xFA, 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0xED, 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0xED, 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'n', 0xED, 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'l', 0xED, 0 }, + (CONST WCHAR[]) { 0xE1, 'g', 0xFA, 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0xF3, 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 0xF3, 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', '.', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', '.', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', '.', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0xED, 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'n', '.', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'l', '.', 0 }, + (CONST WCHAR[]) { 0xE1, 'g', 0xFA, '.', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', '.', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', '.', 0 }, + (CONST WCHAR[]) { 'n', 0xF3, 'v', '.', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', '.', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x3, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ISL1[]= +{ + NULL, + (CONST WCHAR[]) { 'I', 'c', 'e', 'l', 'a', 'n', 'd', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'I', 'c', 'e', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ISLds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', '.', ' ', 'y', 'y', 'y', 'y', '.', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', '.', ' ', '\'', '\'', '\'', '\'', 'y', 'y', '.', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', ' ', 'M', 'M', ' ', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ISLdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ISLt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcITA.c b/lib/kernel32/nls/lcITA.c new file mode 100644 index 0000000..e11d2bb --- /dev/null +++ b/lib/kernel32/nls/lcITA.c @@ -0,0 +1,152 @@ +/* + * nls/lcITA.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ITA0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '0', 0 }, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'i', 'a', 'n', ' ', '(', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ')', 0 }, + (CONST WCHAR[]) { 'I', 'T', 'A', 0 }, + (CONST WCHAR[]) { 'i', 't', 'a', 'l', 'i', 'a', 'n', 'o', 0 }, + (CONST WCHAR[]) { '3', '9', 0 }, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'I', 'T', 'A', 0 }, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'i', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '1', '0', 0 }, + (CONST WCHAR[]) { '3', '9', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'L', '.', 0 }, + (CONST WCHAR[]) { 'I', 'T', 'L', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '9', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'o', 'l', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'g', 'i', 'o', 'v', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'e', 'r', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 's', 'a', 'b', 'a', 't', 'o', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 'e', 'n', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'g', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 0 }, + (CONST WCHAR[]) { 's', 'a', 'b', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'g', 'e', 'n', 'n', 'a', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'b', 'r', 'a', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 'e', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'g', 'g', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'g', 'i', 'u', 'g', 'n', 'o', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'g', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 't', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 't', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'g', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'g', 'i', 'u', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 't', 0 }, + (CONST WCHAR[]) { 'o', 't', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ITA1[]= +{ + NULL, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'y', 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '.', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ITAds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ITAdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ITAt[]= +{ + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcITS.c b/lib/kernel32/nls/lcITS.c new file mode 100644 index 0000000..04afd2a --- /dev/null +++ b/lib/kernel32/nls/lcITS.c @@ -0,0 +1,151 @@ +/* + * nls/lcITS.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ITS0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '1', '0', 0 }, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'i', 'a', 'n', ' ', '(', 'S', 'w', 'i', 's', 's', ')', 0 }, + (CONST WCHAR[]) { 'I', 'T', 'S', 0 }, + (CONST WCHAR[]) { 'i', 't', 'a', 'l', 'i', 'a', 'n', 'o', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'i', 't', 'z', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'E', 0 }, + (CONST WCHAR[]) { 'S', 'v', 'i', 'z', 'z', 'e', 'r', 'a', 0 }, + (CONST WCHAR[]) { '0', '8', '1', '0', 0 }, + (CONST WCHAR[]) { '4', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', 'F', 'r', '.', 0 }, + (CONST WCHAR[]) { 'C', 'H', 'F', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '\'', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 'c', 'o', 'l', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'g', 'i', 'o', 'v', 'e', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 'e', 'r', 'd', 0xEC, 0 }, + (CONST WCHAR[]) { 's', 'a', 'b', 'a', 't', 'o', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 'e', 'n', 'i', 'c', 'a', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'g', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'v', 'e', 'n', 0 }, + (CONST WCHAR[]) { 's', 'a', 'b', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'g', 'e', 'n', 'n', 'a', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'b', 'r', 'a', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'z', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 'e', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'g', 'g', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'g', 'i', 'u', 'g', 'n', 'o', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'g', 'l', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 't', 't', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'o', 't', 't', 'o', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 'e', 'm', 'b', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'g', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'g', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'l', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'a', 'g', 'o', 0 }, + (CONST WCHAR[]) { 's', 'e', 't', 0 }, + (CONST WCHAR[]) { 'o', 't', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ITS1[]= +{ + NULL, + (CONST WCHAR[]) { 'I', 't', 'a', 'l', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'i', 't', 'z', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ITSds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', '.', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ITSdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ITSt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'h', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcLTH.c b/lib/kernel32/nls/lcLTH.c new file mode 100644 index 0000000..9e89b6b --- /dev/null +++ b/lib/kernel32/nls/lcLTH.c @@ -0,0 +1,145 @@ +/* + * nls/lcLTH.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_LTH0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '7', 0 }, + (CONST WCHAR[]) { 'L', 'i', 't', 'h', 'u', 'a', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'T', 'H', 0 }, + (CONST WCHAR[]) { 'l', 'i', 'e', 't', 'u', 'v', 'i', 0x173, 0 }, + (CONST WCHAR[]) { '3', '7', '0', 0 }, + (CONST WCHAR[]) { 'L', 'i', 't', 'h', 'u', 'a', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'L', 'T', 'U', 0 }, + (CONST WCHAR[]) { 'L', 'i', 'e', 't', 'u', 'v', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '2', '7', 0 }, + (CONST WCHAR[]) { '3', '7', '0', 0 }, + (CONST WCHAR[]) { '7', '7', '5', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'L', 't', 0 }, + (CONST WCHAR[]) { 'L', 'T', 'L', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', ' ', '\'', 'm', '.', '\'', ' ', 'M', 'M', 'M', 'M', ' ', 'd', ' ', '\'', 'd', '.', '\'', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'i', 'r', 'm', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 'a', 'n', 't', 'r', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 't', 'r', 'e', 0x10D, 'i', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 'k', 'e', 't', 'v', 'i', 'r', 't', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 'p', 'e', 'n', 'k', 't', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 0x161, 'e', 0x161, 't', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 's', 'e', 'k', 'm', 'a', 'd', 'i', 'e', 'n', 'i', 's', 0 }, + (CONST WCHAR[]) { 'P', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'r', 0 }, + (CONST WCHAR[]) { 'K', 't', 0 }, + (CONST WCHAR[]) { 'P', 'n', 0 }, + (CONST WCHAR[]) { 0x160, 't', 0 }, + (CONST WCHAR[]) { 'S', 'k', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'u', 's', 'i', 's', 0 }, + (CONST WCHAR[]) { 'V', 'a', 's', 'a', 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'K', 'o', 'v', 'a', 's', 0 }, + (CONST WCHAR[]) { 'B', 'a', 'l', 'a', 'n', 'd', 'i', 's', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'g', 'u', 0x17E, 0x117, 0 }, + (CONST WCHAR[]) { 'B', 'i', 'r', 0x17E, 'e', 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 'L', 'i', 'e', 'p', 'a', 0 }, + (CONST WCHAR[]) { 'R', 'u', 'g', 'p', 'j', 0x16B, 't', 'i', 's', 0 }, + (CONST WCHAR[]) { 'R', 'u', 'g', 's', 0x117, 'j', 'i', 's', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'a', 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 'L', 'a', 'p', 'k', 'r', 'i', 't', 'i', 's', 0 }, + (CONST WCHAR[]) { 'G', 'r', 'u', 'o', 'd', 'i', 's', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'u', 0 }, + (CONST WCHAR[]) { 'V', 'a', 's', 0 }, + (CONST WCHAR[]) { 'K', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'B', 'a', 'l', 0 }, + (CONST WCHAR[]) { 'G', 'e', 'g', 0 }, + (CONST WCHAR[]) { 'B', 'i', 'r', 0 }, + (CONST WCHAR[]) { 'L', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'R', 'g', 'p', 0 }, + (CONST WCHAR[]) { 'R', 'g', 's', 0 }, + (CONST WCHAR[]) { 'S', 'p', 'l', 0 }, + (CONST WCHAR[]) { 'L', 'a', 'p', 0 }, + (CONST WCHAR[]) { 'G', 'r', 'd', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x7, 0x8000, 0x3848, 0x1000, 0, 0, 0, 0, 0x80, 0, 0, 0x800, 0x92, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_LTH1[]= +{ + NULL, + (CONST WCHAR[]) { 'L', 'i', 't', 'h', 'u', 'a', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'i', 't', 'h', 'u', 'a', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '7', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_LTHds[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_LTHdl[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', ' ', '\'', 'm', '.', '\'', ' ', 'M', 'M', 'M', 'M', ' ', 'd', ' ', '\'', 'd', '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_LTHt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcLVI.c b/lib/kernel32/nls/lcLVI.c new file mode 100644 index 0000000..6eafcba --- /dev/null +++ b/lib/kernel32/nls/lcLVI.c @@ -0,0 +1,144 @@ +/* + * nls/lcLVI.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_LVI0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '6', 0 }, + (CONST WCHAR[]) { 'L', 'a', 't', 'v', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'V', 'I', 0 }, + (CONST WCHAR[]) { 'l', 'a', 't', 'v', 'i', 'e', 0x161, 'u', 0 }, + (CONST WCHAR[]) { '3', '7', '1', 0 }, + (CONST WCHAR[]) { 'L', 'a', 't', 'v', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'L', 'V', 'A', 0 }, + (CONST WCHAR[]) { 'L', 'a', 't', 'v', 'i', 'j', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '2', '6', 0 }, + (CONST WCHAR[]) { '3', '7', '1', 0 }, + (CONST WCHAR[]) { '7', '7', '5', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'L', 's', 0 }, + (CONST WCHAR[]) { 'L', 'V', 'L', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', '.', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', '\'', '.', ' ', 'g', 'a', 'd', 'a', ' ', '\'', 'd', '.', ' ', 'M', 'M', 'M', 'M', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'i', 'r', 'm', 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'o', 't', 'r', 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 't', 'r', 'e', 0x161, 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'c', 'e', 't', 'u', 'r', 't', 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'p', 'i', 'e', 'k', 't', 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 's', 'e', 's', 't', 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 's', 'v', 0x113, 't', 'd', 'i', 'e', 'n', 'a', 0 }, + (CONST WCHAR[]) { 'P', 'r', 0 }, + (CONST WCHAR[]) { 'O', 't', 0 }, + (CONST WCHAR[]) { 'T', 'r', 0 }, + (CONST WCHAR[]) { 'C', 'e', 0 }, + (CONST WCHAR[]) { 'P', 'k', 0 }, + (CONST WCHAR[]) { 'S', 'e', 0 }, + (CONST WCHAR[]) { 'S', 'v', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'v', 0x101, 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 0x101, 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0x12B, 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 'j', 's', 0 }, + (CONST WCHAR[]) { 'j', 0x16B, 'n', 'i', 'j', 's', 0 }, + (CONST WCHAR[]) { 'j', 0x16B, 'l', 'i', 'j', 's', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 's', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'r', 'i', 's', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 0x16B, 'n', 0 }, + (CONST WCHAR[]) { 'J', 0x16B, 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'k', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x7, 0x8000, 0x3848, 0x1000, 0, 0, 0, 0, 0x80, 0, 0, 0x800, 0x92, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_LVI1[]= +{ + NULL, + (CONST WCHAR[]) { 'L', 'a', 't', 'v', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'L', 'a', 't', 'v', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '7', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_LVIds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', '.', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_LVIdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'y', 'y', 'y', 'y', '\'', '.', ' ', 'g', 'a', 'd', 'a', ' ', '\'', 'd', '.', ' ', 'M', 'M', 'M', 'M', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_LVIt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcNLB.c b/lib/kernel32/nls/lcNLB.c new file mode 100644 index 0000000..c04823c --- /dev/null +++ b/lib/kernel32/nls/lcNLB.c @@ -0,0 +1,152 @@ +/* + * nls/lcNLB.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_NLB0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '1', '3', 0 }, + (CONST WCHAR[]) { 'D', 'u', 't', 'c', 'h', ' ', '(', 'B', 'e', 'l', 'g', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'N', 'L', 'B', 0 }, + (CONST WCHAR[]) { 'N', 'e', 'd', 'e', 'r', 'l', 'a', 'n', 'd', 's', 0 }, + (CONST WCHAR[]) { '3', '2', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'g', 'i', 'u', 'm', 0 }, + (CONST WCHAR[]) { 'B', 'E', 'L', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'g', 'i', 0xEB, 0 }, + (CONST WCHAR[]) { '0', '8', '1', '3', 0 }, + (CONST WCHAR[]) { '3', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'B', 'F', 0 }, + (CONST WCHAR[]) { 'B', 'E', 'F', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'w', 'o', 'e', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'n', 'd', 'e', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'v', 'r', 'i', 'j', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'z', 'a', 't', 'e', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'z', 'o', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0 }, + (CONST WCHAR[]) { 'd', 'i', 0 }, + (CONST WCHAR[]) { 'w', 'o', 0 }, + (CONST WCHAR[]) { 'd', 'o', 0 }, + (CONST WCHAR[]) { 'v', 'r', 0 }, + (CONST WCHAR[]) { 'z', 'a', 0 }, + (CONST WCHAR[]) { 'z', 'o', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'r', 't', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 'u', 's', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'r', 't', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NLB1[]= +{ + NULL, + (CONST WCHAR[]) { 'D', 'u', 't', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'B', 'e', 'l', 'g', 'i', 'u', 'm', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_NLBds[]= +{ + (CONST WCHAR[]) { 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NLBdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NLBt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '\'', ' ', 'u', '.', '\'', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcNLD.c b/lib/kernel32/nls/lcNLD.c new file mode 100644 index 0000000..2a7468d --- /dev/null +++ b/lib/kernel32/nls/lcNLD.c @@ -0,0 +1,155 @@ +/* + * nls/lcNLD.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_NLD0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '3', 0 }, + (CONST WCHAR[]) { 'D', 'u', 't', 'c', 'h', ' ', '(', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ')', 0 }, + (CONST WCHAR[]) { 'N', 'L', 'D', 0 }, + (CONST WCHAR[]) { 'N', 'e', 'd', 'e', 'r', 'l', 'a', 'n', 'd', 's', 0 }, + (CONST WCHAR[]) { '3', '1', 0 }, + (CONST WCHAR[]) { 'N', 'e', 't', 'h', 'e', 'r', 'l', 'a', 'n', 'd', 's', 0 }, + (CONST WCHAR[]) { 'N', 'L', 'D', 0 }, + (CONST WCHAR[]) { 'N', 'e', 'd', 'e', 'r', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { '0', '4', '1', '3', 0 }, + (CONST WCHAR[]) { '3', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'f', 'l', 0 }, + (CONST WCHAR[]) { 'N', 'L', 'G', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', '1', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', '-', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'd', 'i', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'w', 'o', 'e', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'd', 'o', 'n', 'd', 'e', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'v', 'r', 'i', 'j', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'z', 'a', 't', 'e', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'z', 'o', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0 }, + (CONST WCHAR[]) { 'd', 'i', 0 }, + (CONST WCHAR[]) { 'w', 'o', 0 }, + (CONST WCHAR[]) { 'd', 'o', 0 }, + (CONST WCHAR[]) { 'v', 'r', 0 }, + (CONST WCHAR[]) { 'z', 'a', 0 }, + (CONST WCHAR[]) { 'z', 'o', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'a', 'r', 't', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 'u', 's', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'r', 't', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'e', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NLD1[]= +{ + NULL, + (CONST WCHAR[]) { 'D', 'u', 't', 'c', 'h', 0 }, + (CONST WCHAR[]) { 'N', 'e', 't', 'h', 'e', 'r', 'l', 'a', 'n', 'd', 's', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_NLDds[]= +{ + (CONST WCHAR[]) { 'd', '-', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NLDdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', 'M', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', ' ', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NLDt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '.', 's', 's', '\'', ' ', 'u', 'u', 'r', '\'', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', '\'', ' ', 'u', 'u', 'r', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcNON.c b/lib/kernel32/nls/lcNON.c new file mode 100644 index 0000000..0c2a76c --- /dev/null +++ b/lib/kernel32/nls/lcNON.c @@ -0,0 +1,150 @@ +/* + * nls/lcNON.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_NON0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '1', '4', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'e', 'g', 'i', 'a', 'n', ' ', '(', 'N', 'y', 'n', 'o', 'r', 's', 'k', ')', 0 }, + (CONST WCHAR[]) { 'N', 'O', 'N', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'r', 's', 'k', ' ', '(', 'n', 'y', 'n', 'o', 'r', 's', 'k', ')', 0 }, + (CONST WCHAR[]) { '4', '7', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'N', 'O', 'R', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'e', 'g', 0 }, + (CONST WCHAR[]) { '0', '8', '1', '4', 0 }, + (CONST WCHAR[]) { '4', '7', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'O', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 0xE5, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'y', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'o', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'e', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'l', 'a', 'u', 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 's', 'u', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 0xE5, 0 }, + (CONST WCHAR[]) { 't', 'y', 0 }, + (CONST WCHAR[]) { 'o', 'n', 0 }, + (CONST WCHAR[]) { 't', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0 }, + (CONST WCHAR[]) { 'l', 'a', 'u', 0 }, + (CONST WCHAR[]) { 's', 'u', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NON1[]= +{ + NULL, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'e', 'g', 'i', 'a', 'n', ' ', '(', 'N', 'y', 'n', 'o', 'r', 's', 'k', ')', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_NONds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NONdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NONt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { '\'', 'k', 'l', ' ', '\'', 'H', 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcNOR.c b/lib/kernel32/nls/lcNOR.c new file mode 100644 index 0000000..bac947a --- /dev/null +++ b/lib/kernel32/nls/lcNOR.c @@ -0,0 +1,150 @@ +/* + * nls/lcNOR.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_NOR0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '4', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'e', 'g', 'i', 'a', 'n', ' ', '(', 'B', 'o', 'k', 'm', 'a', 'l', ')', 0 }, + (CONST WCHAR[]) { 'N', 'O', 'R', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'r', 's', 'k', ' ', '(', 'b', 'o', 'k', 'm', 0xE5, 'l', ')', 0 }, + (CONST WCHAR[]) { '4', '7', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'N', 'O', 'R', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'g', 'e', 0 }, + (CONST WCHAR[]) { '0', '4', '1', '4', 0 }, + (CONST WCHAR[]) { '4', '7', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'O', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'i', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'o', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'e', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'l', 0xF8, 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 's', 0xF8, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 'a', 0 }, + (CONST WCHAR[]) { 't', 'i', 0 }, + (CONST WCHAR[]) { 'o', 'n', 0 }, + (CONST WCHAR[]) { 't', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0 }, + (CONST WCHAR[]) { 'l', 0xF8, 0 }, + (CONST WCHAR[]) { 's', 0xF8, 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 's', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '4', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NOR1[]= +{ + NULL, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'e', 'g', 'i', 'a', 'n', ' ', '(', 'B', 'o', 'k', 'm', 0xE5, 'l', ')', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'r', 'w', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_NORds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NORdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_NORt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { '\'', 'k', 'l', ' ', '\'', 'H', 'H', '.', 'm', 'm', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcPLK.c b/lib/kernel32/nls/lcPLK.c new file mode 100644 index 0000000..13b3eb4 --- /dev/null +++ b/lib/kernel32/nls/lcPLK.c @@ -0,0 +1,146 @@ +/* + * nls/lcPLK.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_PLK0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '5', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'P', 'L', 'K', 0 }, + (CONST WCHAR[]) { 'p', 'o', 'l', 's', 'k', 'i', 0 }, + (CONST WCHAR[]) { '4', '8', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'P', 'O', 'L', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'l', 's', 'k', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '1', '5', 0 }, + (CONST WCHAR[]) { '4', '8', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'z', 0x142, 0 }, + (CONST WCHAR[]) { 'P', 'L', 'N', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 'i', 'e', 'd', 'z', 'i', 'a', 0x142, 'e', 'k', 0 }, + (CONST WCHAR[]) { 'w', 't', 'o', 'r', 'e', 'k', 0 }, + (CONST WCHAR[]) { 0x15B, 'r', 'o', 'd', 'a', 0 }, + (CONST WCHAR[]) { 'c', 'z', 'w', 'a', 'r', 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 'p', 'i', 0x105, 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 's', 'o', 'b', 'o', 't', 'a', 0 }, + (CONST WCHAR[]) { 'n', 'i', 'e', 'd', 'z', 'i', 'e', 'l', 'a', 0 }, + (CONST WCHAR[]) { 'P', 'n', 0 }, + (CONST WCHAR[]) { 'W', 't', 0 }, + (CONST WCHAR[]) { 0x15A, 'r', 0 }, + (CONST WCHAR[]) { 'C', 'z', 0 }, + (CONST WCHAR[]) { 'P', 't', 0 }, + (CONST WCHAR[]) { 'S', 'o', 0 }, + (CONST WCHAR[]) { 'N', 0 }, + (CONST WCHAR[]) { 's', 't', 'y', 'c', 'z', 'e', 0x144, 0 }, + (CONST WCHAR[]) { 'l', 'u', 't', 'y', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'z', 'e', 'c', 0 }, + (CONST WCHAR[]) { 'k', 'w', 'i', 'e', 'c', 'i', 'e', 0x144, 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'c', 'z', 'e', 'r', 'w', 'i', 'e', 'c', 0 }, + (CONST WCHAR[]) { 'l', 'i', 'p', 'i', 'e', 'c', 0 }, + (CONST WCHAR[]) { 's', 'i', 'e', 'r', 'p', 'i', 'e', 0x144, 0 }, + (CONST WCHAR[]) { 'w', 'r', 'z', 'e', 's', 'i', 'e', 0x144, 0 }, + (CONST WCHAR[]) { 'p', 'a', 0x17A, 'd', 'z', 'i', 'e', 'r', 'n', 'i', 'k', 0 }, + (CONST WCHAR[]) { 'l', 'i', 's', 't', 'o', 'p', 'a', 'd', 0 }, + (CONST WCHAR[]) { 'g', 'r', 'u', 'd', 'z', 'i', 'e', 0x144, 0 }, + (CONST WCHAR[]) { 's', 't', 'y', 0 }, + (CONST WCHAR[]) { 'l', 'u', 't', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'k', 'w', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'c', 'z', 'e', 0 }, + (CONST WCHAR[]) { 'l', 'i', 'p', 0 }, + (CONST WCHAR[]) { 's', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'w', 'r', 'z', 0 }, + (CONST WCHAR[]) { 'p', 'a', 0x17A, 0 }, + (CONST WCHAR[]) { 'l', 'i', 's', 0 }, + (CONST WCHAR[]) { 'g', 'r', 'u', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PLK1[]= +{ + NULL, + (CONST WCHAR[]) { 'P', 'o', 'l', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_PLKds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PLKdl[]= +{ + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PLKt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcPTB.c b/lib/kernel32/nls/lcPTB.c new file mode 100644 index 0000000..0a93f79 --- /dev/null +++ b/lib/kernel32/nls/lcPTB.c @@ -0,0 +1,148 @@ +/* + * nls/lcPTB.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_PTB0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '6', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'u', 'e', 's', 'e', ' ', '(', 'B', 'r', 'a', 'z', 'i', 'l', 'i', 'a', 'n', ')', 0 }, + (CONST WCHAR[]) { 'P', 'T', 'B', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'u', 0xEA, 's', 0 }, + (CONST WCHAR[]) { '5', '5', 0 }, + (CONST WCHAR[]) { 'B', 'r', 'a', 'z', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'B', 'R', 'A', 0 }, + (CONST WCHAR[]) { 'B', 'r', 'a', 's', 'i', 'l', 0 }, + (CONST WCHAR[]) { '0', '4', '1', '6', 0 }, + (CONST WCHAR[]) { '5', '5', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'R', '$', 0 }, + (CONST WCHAR[]) { 'B', 'R', 'C', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'S', 'e', 'g', 'u', 'n', 'd', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'T', 'e', 'r', 0xE7, 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'a', 'r', 't', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'i', 'n', 't', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'x', 't', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'g', 0 }, + (CONST WCHAR[]) { 'T', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'x', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'e', 'i', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'v', 'e', 'r', 'e', 'i', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0xE7, 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'h', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'h', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 't', 'e', 'm', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'O', 'u', 't', 'u', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'v', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 't', 0 }, + (CONST WCHAR[]) { 'O', 'u', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PTB1[]= +{ + NULL, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'u', 'e', 's', 'e', 0 }, + (CONST WCHAR[]) { 'B', 'r', 'a', 'z', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '6', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_PTBds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PTBdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PTBt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcPTG.c b/lib/kernel32/nls/lcPTG.c new file mode 100644 index 0000000..728cbf8 --- /dev/null +++ b/lib/kernel32/nls/lcPTG.c @@ -0,0 +1,153 @@ +/* + * nls/lcPTG.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_PTG0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '1', '6', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'u', 'e', 's', 'e', ' ', '(', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ')', 0 }, + (CONST WCHAR[]) { 'P', 'T', 'G', 0 }, + (CONST WCHAR[]) { 'p', 'o', 'r', 't', 'u', 'g', 'u', 0xEA, 's', 0 }, + (CONST WCHAR[]) { '3', '5', '1', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'a', 'l', 0 }, + (CONST WCHAR[]) { 'P', 'R', 'T', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'a', 'l', 0 }, + (CONST WCHAR[]) { '0', '8', '1', '6', 0 }, + (CONST WCHAR[]) { '3', '5', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'E', 's', 'c', '.', 0 }, + (CONST WCHAR[]) { 'P', 'T', 'E', 0 }, + (CONST WCHAR[]) { '$', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'S', 'e', 'g', 'u', 'n', 'd', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'T', 'e', 'r', 0xE7, 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'a', 'r', 't', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'i', 'n', 't', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'x', 't', 'a', '-', 'f', 'e', 'i', 'r', 'a', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 'a', 'd', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 'i', 'n', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'g', 0 }, + (CONST WCHAR[]) { 'T', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'a', 0 }, + (CONST WCHAR[]) { 'Q', 'u', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'x', 0 }, + (CONST WCHAR[]) { 'S', 0xE1, 'b', 0 }, + (CONST WCHAR[]) { 'D', 'o', 'm', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 'e', 'i', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'v', 'e', 'r', 'e', 'i', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0xE7, 'o', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 'h', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 'h', 'o', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 's', 't', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 't', 'e', 'm', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'O', 'u', 't', 'u', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 'e', 'm', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 'e', 'm', 'b', 'r', 'o', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'v', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'b', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'J', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'g', 'o', 0 }, + (CONST WCHAR[]) { 'S', 'e', 't', 0 }, + (CONST WCHAR[]) { 'O', 'u', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'z', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PTG1[]= +{ + NULL, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'u', 'e', 's', 'e', 0 }, + (CONST WCHAR[]) { 'P', 'o', 'r', 't', 'u', 'g', 'a', 'l', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_PTGds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '-', 'M', 'M', '-', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PTGdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '\'', ' ', 'd', 'e', ' ', '\'', 'M', 'M', 'M', 'M', '\'', ' ', 'd', 'e', ' ', '\'', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '/', 'M', 'M', 'M', '/', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_PTGt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', '\'', 'H', '\'', 'm', 'm', '\'', 'm', '\'', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcROM.c b/lib/kernel32/nls/lcROM.c new file mode 100644 index 0000000..15ae27a --- /dev/null +++ b/lib/kernel32/nls/lcROM.c @@ -0,0 +1,148 @@ +/* + * nls/lcROM.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_ROM0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '8', 0 }, + (CONST WCHAR[]) { 'R', 'o', 'm', 'a', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'R', 'O', 'M', 0 }, + (CONST WCHAR[]) { 'r', 'o', 'm', 0xE2, 'n', 0x103, 0 }, + (CONST WCHAR[]) { '4', '0', 0 }, + (CONST WCHAR[]) { 'R', 'o', 'm', 'a', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'R', 'O', 'M', 0 }, + (CONST WCHAR[]) { 'R', 'o', 'm', 0xE2, 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '1', '8', 0 }, + (CONST WCHAR[]) { '4', '0', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'L', 'E', 'I', 0 }, + (CONST WCHAR[]) { 'R', 'O', 'L', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'l', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0x163, 'i', 0 }, + (CONST WCHAR[]) { 'm', 'i', 'e', 'r', 'c', 'u', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'o', 'i', 0 }, + (CONST WCHAR[]) { 'v', 'i', 'n', 'e', 'r', 'i', 0 }, + (CONST WCHAR[]) { 's', 0xEE, 'm', 'b', 0x103, 't', 0x103, 0 }, + (CONST WCHAR[]) { 'd', 'u', 'm', 'i', 'n', 'i', 'c', 0x103, 0 }, + (CONST WCHAR[]) { 'L', 0 }, + (CONST WCHAR[]) { 'M', 'a', 0 }, + (CONST WCHAR[]) { 'M', 'i', 0 }, + (CONST WCHAR[]) { 'J', 0 }, + (CONST WCHAR[]) { 'V', 0 }, + (CONST WCHAR[]) { 'S', 0 }, + (CONST WCHAR[]) { 'D', 0 }, + (CONST WCHAR[]) { 'i', 'a', 'n', 'u', 'a', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'i', 'u', 'n', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'i', 'u', 'l', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'o', 'c', 't', 'o', 'm', 'b', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'i', 'e', 'm', 'b', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'r', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'I', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'F', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'A', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'i', 0 }, + (CONST WCHAR[]) { 'I', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'I', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'A', 'u', 'g', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'O', 'c', 't', 0 }, + (CONST WCHAR[]) { 'N', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'D', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ROM1[]= +{ + NULL, + (CONST WCHAR[]) { 'R', 'o', 'm', 'a', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'R', 'o', 'm', 'a', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_ROMds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ROMdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_ROMt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcRUS.c b/lib/kernel32/nls/lcRUS.c new file mode 100644 index 0000000..04e16da --- /dev/null +++ b/lib/kernel32/nls/lcRUS.c @@ -0,0 +1,148 @@ +/* + * nls/lcRUS.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_RUS0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', '9', 0 }, + (CONST WCHAR[]) { 'R', 'u', 's', 's', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'R', 'U', 'S', 0 }, + (CONST WCHAR[]) { 0x440, 0x443, 0x441, 0x441, 0x43A, 0x438, 0x439, 0 }, + (CONST WCHAR[]) { '7', 0 }, + (CONST WCHAR[]) { 'R', 'u', 's', 's', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'R', 'U', 'S', 0 }, + (CONST WCHAR[]) { 0x420, 0x43E, 0x441, 0x441, 0x438, 0x44F, 0 }, + (CONST WCHAR[]) { '0', '4', '1', '9', 0 }, + (CONST WCHAR[]) { '7', 0 }, + (CONST WCHAR[]) { '8', '6', '6', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0x440, '.', 0 }, + (CONST WCHAR[]) { 'R', 'U', 'R', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '5', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0x435, 0x434, 0x435, 0x43B, 0x44C, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x432, 0x442, 0x43E, 0x440, 0x43D, 0x438, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x435, 0x434, 0x430, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0 }, + (CONST WCHAR[]) { 0x43F, 0x44F, 0x442, 0x43D, 0x438, 0x446, 0x430, 0 }, + (CONST WCHAR[]) { 0x441, 0x443, 0x431, 0x431, 0x43E, 0x442, 0x430, 0 }, + (CONST WCHAR[]) { 0x432, 0x43E, 0x441, 0x43A, 0x440, 0x435, 0x441, 0x435, 0x43D, 0x44C, 0x435, 0 }, + (CONST WCHAR[]) { 0x41F, 0x43D, 0 }, + (CONST WCHAR[]) { 0x412, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x440, 0 }, + (CONST WCHAR[]) { 0x427, 0x442, 0 }, + (CONST WCHAR[]) { 0x41F, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x431, 0 }, + (CONST WCHAR[]) { 0x412, 0x441, 0 }, + (CONST WCHAR[]) { 0x42F, 0x43D, 0x432, 0x430, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x424, 0x435, 0x432, 0x440, 0x430, 0x43B, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x440, 0x442, 0 }, + (CONST WCHAR[]) { 0x410, 0x43F, 0x440, 0x435, 0x43B, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41C, 0x430, 0x439, 0 }, + (CONST WCHAR[]) { 0x418, 0x44E, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x418, 0x44E, 0x43B, 0x44C, 0 }, + (CONST WCHAR[]) { 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x43D, 0x442, 0x44F, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41E, 0x43A, 0x442, 0x44F, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41D, 0x43E, 0x44F, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x414, 0x435, 0x43A, 0x430, 0x431, 0x440, 0x44C, 0 }, + (CONST WCHAR[]) { 0x44F, 0x43D, 0x432, 0 }, + (CONST WCHAR[]) { 0x444, 0x435, 0x432, 0 }, + (CONST WCHAR[]) { 0x43C, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x430, 0x43F, 0x440, 0 }, + (CONST WCHAR[]) { 0x43C, 0x430, 0x439, 0 }, + (CONST WCHAR[]) { 0x438, 0x44E, 0x43D, 0 }, + (CONST WCHAR[]) { 0x438, 0x44E, 0x43B, 0 }, + (CONST WCHAR[]) { 0x430, 0x432, 0x433, 0 }, + (CONST WCHAR[]) { 0x441, 0x435, 0x43D, 0 }, + (CONST WCHAR[]) { 0x43E, 0x43A, 0x442, 0 }, + (CONST WCHAR[]) { 0x43D, 0x43E, 0x44F, 0 }, + (CONST WCHAR[]) { 0x434, 0x435, 0x43A, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0x203, 0x8000, 0x3848, 0, 0, 0, 0, 0, 0x4, 0, 0, 0x2, 0x4, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_RUS1[]= +{ + NULL, + (CONST WCHAR[]) { 'R', 'u', 's', 's', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'R', 'u', 's', 's', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_RUSds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '/', 'M', 'M', '/', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_RUSdl[]= +{ + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', '\'', 0x433, '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_RUSt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSKY.c b/lib/kernel32/nls/lcSKY.c new file mode 100644 index 0000000..a43925a --- /dev/null +++ b/lib/kernel32/nls/lcSKY.c @@ -0,0 +1,150 @@ +/* + * nls/lcSKY.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SKY0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', 'b', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'a', 'k', 0 }, + (CONST WCHAR[]) { 'S', 'K', 'Y', 0 }, + (CONST WCHAR[]) { 's', 'l', 'o', 'v', 'e', 'n', 0x10D, 'i', 'n', 'a', 0 }, + (CONST WCHAR[]) { '4', '2', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'a', 'k', ' ', 'R', 'e', 'p', 'u', 'b', 'l', 'i', 'c', 0 }, + (CONST WCHAR[]) { 'S', 'V', 'K', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'e', 'n', 's', 'k', 0xE1, ' ', 'r', 'e', 'p', 'u', 'b', 'l', 'i', 'k', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '1', 'b', 0 }, + (CONST WCHAR[]) { '4', '2', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', 'k', 0 }, + (CONST WCHAR[]) { 'S', 'K', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 'd', 'e', 'l', 'o', 'k', 0 }, + (CONST WCHAR[]) { 'u', 't', 'o', 'r', 'o', 'k', 0 }, + (CONST WCHAR[]) { 's', 't', 'r', 'e', 'd', 'a', 0 }, + (CONST WCHAR[]) { 0x161, 't', 'v', 'r', 't', 'o', 'k', 0 }, + (CONST WCHAR[]) { 'p', 'i', 'a', 't', 'o', 'k', 0 }, + (CONST WCHAR[]) { 's', 'o', 'b', 'o', 't', 'a', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 'e', 0x13E, 'a', 0 }, + (CONST WCHAR[]) { 'p', 'o', 0 }, + (CONST WCHAR[]) { 'u', 't', 0 }, + (CONST WCHAR[]) { 's', 't', 0 }, + (CONST WCHAR[]) { 0x161, 't', 0 }, + (CONST WCHAR[]) { 'p', 'i', 0 }, + (CONST WCHAR[]) { 's', 'o', 0 }, + (CONST WCHAR[]) { 'n', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 0xE1, 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 0xE1, 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'e', 'c', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0xED, 'l', 0 }, + (CONST WCHAR[]) { 'm', 0xE1, 'j', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'n', 0 }, + (CONST WCHAR[]) { 'j', 0xFA, 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0xF3, 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'I', 0 }, + (CONST WCHAR[]) { 'I', 'I', 0 }, + (CONST WCHAR[]) { 'I', 'I', 'I', 0 }, + (CONST WCHAR[]) { 'I', 'V', 0 }, + (CONST WCHAR[]) { 'V', 0 }, + (CONST WCHAR[]) { 'V', 'I', 0 }, + (CONST WCHAR[]) { 'V', 'I', 'I', 0 }, + (CONST WCHAR[]) { 'V', 'I', 'I', 'I', 0 }, + (CONST WCHAR[]) { 'I', 'X', 0 }, + (CONST WCHAR[]) { 'X', 0 }, + (CONST WCHAR[]) { 'X', 'I', 0 }, + (CONST WCHAR[]) { 'X', 'I', 'I', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SKY1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'a', 'k', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'a', 'k', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SKYds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '-', 'M', '-', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SKYdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SKYt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', '.', 'm', 'm', '.', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSLV.c b/lib/kernel32/nls/lcSLV.c new file mode 100644 index 0000000..7a1c4bc --- /dev/null +++ b/lib/kernel32/nls/lcSLV.c @@ -0,0 +1,152 @@ +/* + * nls/lcSLV.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SLV0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '4', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'e', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'L', 'V', 0 }, + (CONST WCHAR[]) { 's', 'l', 'o', 'v', 'e', 'n', 's', 'k', 'i', 0 }, + (CONST WCHAR[]) { '3', '8', '6', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'e', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'V', 'N', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'e', 'n', 'i', 'j', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '2', '4', 0 }, + (CONST WCHAR[]) { '3', '8', '6', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '0', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'S', 'I', 'T', 0 }, + (CONST WCHAR[]) { 'S', 'I', 'T', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 'e', 'd', 'e', 'l', 'j', 'e', 'k', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 'e', 'k', 0 }, + (CONST WCHAR[]) { 's', 'r', 'e', 'd', 'a', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 't', 'r', 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 'p', 'e', 't', 'e', 'k', 0 }, + (CONST WCHAR[]) { 's', 'o', 'b', 'o', 't', 'a', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 'e', 'l', 'j', 'a', 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 0 }, + (CONST WCHAR[]) { 's', 'r', 'e', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 't', 0 }, + (CONST WCHAR[]) { 'p', 'e', 't', 0 }, + (CONST WCHAR[]) { 's', 'o', 'b', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 'e', 'c', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 'j', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SLV1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'e', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'S', 'l', 'o', 'v', 'e', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SLVds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', '.', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', ' ', 'M', '.', ' ', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SLVdl[]= +{ + (CONST WCHAR[]) { 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ',', ' ', 'd', '.', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SLVt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSQI.c b/lib/kernel32/nls/lcSQI.c new file mode 100644 index 0000000..66a5839 --- /dev/null +++ b/lib/kernel32/nls/lcSQI.c @@ -0,0 +1,144 @@ +/* + * nls/lcSQI.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SQI0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', 'c', 0 }, + (CONST WCHAR[]) { 'A', 'l', 'b', 'a', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'Q', 'I', 0 }, + (CONST WCHAR[]) { 's', 'h', 'q', 'i', 'p', 'e', 0 }, + (CONST WCHAR[]) { '3', '5', '5', 0 }, + (CONST WCHAR[]) { 'A', 'l', 'b', 'a', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'A', 'L', 'B', 0 }, + (CONST WCHAR[]) { 'S', 'h', 'q', 'i', 'p', 0xEB, 'r', 'i', 'a', 0 }, + (CONST WCHAR[]) { '0', '4', '1', 'c', 0 }, + (CONST WCHAR[]) { '3', '5', '5', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'L', 'e', 'k', 0 }, + (CONST WCHAR[]) { 'A', 'L', 'L', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '5', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 'P', 'D', 0 }, + (CONST WCHAR[]) { 'M', 'D', 0 }, + (CONST WCHAR[]) { 'e', ' ', 'h', 0xEB, 'n', 0xEB, 0 }, + (CONST WCHAR[]) { 'e', ' ', 'm', 'a', 'r', 't', 0xEB, 0 }, + (CONST WCHAR[]) { 'e', ' ', 'm', 0xEB, 'r', 'k', 'u', 'r', 0xEB, 0 }, + (CONST WCHAR[]) { 'e', ' ', 'e', 'n', 'j', 't', 'e', 0 }, + (CONST WCHAR[]) { 'e', ' ', 'p', 'r', 'e', 'm', 't', 'e', 0 }, + (CONST WCHAR[]) { 'e', ' ', 's', 'h', 't', 'u', 'n', 0xEB, 0 }, + (CONST WCHAR[]) { 'e', ' ', 'd', 'i', 'e', 'l', 0 }, + (CONST WCHAR[]) { 'H', 0xEB, 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'M', 0xEB, 'r', 0 }, + (CONST WCHAR[]) { 'E', 'n', 'j', 0 }, + (CONST WCHAR[]) { 'P', 'r', 'e', 0 }, + (CONST WCHAR[]) { 'S', 'h', 't', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'e', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'a', 'r', 0 }, + (CONST WCHAR[]) { 's', 'h', 'k', 'u', 'r', 't', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'p', 'r', 'i', 'l', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'q', 'e', 'r', 's', 'h', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'k', 'o', 'r', 'r', 'i', 'k', 0 }, + (CONST WCHAR[]) { 'g', 'u', 's', 'h', 't', 0 }, + (CONST WCHAR[]) { 's', 'h', 't', 'a', 't', 'o', 'r', 0 }, + (CONST WCHAR[]) { 't', 'e', 't', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'n', 0xEB, 'n', 't', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'h', 'j', 'e', 't', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'J', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'h', 'k', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'P', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'Q', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'K', 'o', 'r', 0 }, + (CONST WCHAR[]) { 'G', 's', 'h', 0 }, + (CONST WCHAR[]) { 'S', 'h', 't', 0 }, + (CONST WCHAR[]) { 'T', 'e', 't', 0 }, + (CONST WCHAR[]) { 'N', 0xEB, 'n', 0 }, + (CONST WCHAR[]) { 'D', 'h', 'j', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SQI1[]= +{ + NULL, + (CONST WCHAR[]) { 'A', 'l', 'b', 'a', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'A', 'l', 'b', 'a', 'n', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', '.', 't', 't', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SQIds[]= +{ + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SQIdl[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SQIt[]= +{ + (CONST WCHAR[]) { 'h', ':', 'm', 'm', ':', 's', 's', '.', 't', 't', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSRB.c b/lib/kernel32/nls/lcSRB.c new file mode 100644 index 0000000..f8464e4 --- /dev/null +++ b/lib/kernel32/nls/lcSRB.c @@ -0,0 +1,144 @@ +/* + * nls/lcSRB.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SRB0[]= +{ + NULL, + (CONST WCHAR[]) { '0', 'c', '1', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 'n', ' ', '(', 'C', 'y', 'r', 'i', 'l', 'l', 'i', 'c', ')', 0 }, + (CONST WCHAR[]) { 'S', 'R', 'B', 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x43F, 0x441, 0x43A, 0x438, 0 }, + (CONST WCHAR[]) { '3', '8', '1', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'P', 'B', 0 }, + (CONST WCHAR[]) { 0x408, 0x443, 0x433, 0x43E, 0x441, 0x43B, 0x430, 0x432, 0x438, 0x458, 0x430, 0 }, + (CONST WCHAR[]) { '0', 'c', '1', 'a', 0 }, + (CONST WCHAR[]) { '3', '8', '1', 0 }, + (CONST WCHAR[]) { '8', '6', '6', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'n', '.', 0 }, + (CONST WCHAR[]) { 'Y', 'U', 'D', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43A, 0 }, + (CONST WCHAR[]) { 0x443, 0x442, 0x43E, 0x440, 0x430, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x435, 0x434, 0x430, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43A, 0 }, + (CONST WCHAR[]) { 0x43F, 0x435, 0x442, 0x430, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x443, 0x431, 0x43E, 0x442, 0x430, 0 }, + (CONST WCHAR[]) { 0x43D, 0x435, 0x434, 0x435, 0x459, 0x430, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0 }, + (CONST WCHAR[]) { 0x443, 0x442, 0x43E, 0 }, + (CONST WCHAR[]) { 0x441, 0x440, 0x435, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0 }, + (CONST WCHAR[]) { 0x43F, 0x435, 0x442, 0 }, + (CONST WCHAR[]) { 0x441, 0x443, 0x431, 0 }, + (CONST WCHAR[]) { 0x43D, 0x435, 0x434, 0 }, + (CONST WCHAR[]) { 0x458, 0x430, 0x43D, 0x443, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x43C, 0x430, 0x440, 0x442, 0 }, + (CONST WCHAR[]) { 0x430, 0x43F, 0x440, 0x438, 0x43B, 0 }, + (CONST WCHAR[]) { 0x43C, 0x430, 0x458, 0 }, + (CONST WCHAR[]) { 0x458, 0x443, 0x43D, 0 }, + (CONST WCHAR[]) { 0x458, 0x443, 0x43B, 0 }, + (CONST WCHAR[]) { 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0 }, + (CONST WCHAR[]) { 0x441, 0x435, 0x43F, 0x442, 0x435, 0x43C, 0x431, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x43E, 0x43A, 0x442, 0x43E, 0x431, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x43D, 0x43E, 0x432, 0x435, 0x43C, 0x431, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x434, 0x435, 0x446, 0x435, 0x43C, 0x431, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x458, 0x430, 0x43D, 0 }, + (CONST WCHAR[]) { 0x444, 0x435, 0x431, 0 }, + (CONST WCHAR[]) { 0x43C, 0x430, 0x440, 0 }, + (CONST WCHAR[]) { 0x430, 0x43F, 0x440, 0 }, + (CONST WCHAR[]) { 0x43C, 0x430, 0x458, 0 }, + (CONST WCHAR[]) { 0x458, 0x443, 0x43D, 0 }, + (CONST WCHAR[]) { 0x458, 0x443, 0x43B, 0 }, + (CONST WCHAR[]) { 0x430, 0x432, 0x433, 0 }, + (CONST WCHAR[]) { 0x441, 0x435, 0x43F, 0 }, + (CONST WCHAR[]) { 0x43E, 0x43A, 0x442, 0 }, + (CONST WCHAR[]) { 0x43D, 0x43E, 0x432, 0 }, + (CONST WCHAR[]) { 0x434, 0x435, 0x446, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0x203, 0x8000, 0x3848, 0, 0, 0, 0, 0, 0x4, 0, 0, 0x2, 0x4, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SRB1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 'n', ' ', '(', 'C', 'y', 'r', 'i', 'l', 'l', 'i', 'c', ')', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SRBds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SRBdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SRBt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSRL.c b/lib/kernel32/nls/lcSRL.c new file mode 100644 index 0000000..cdfa03c --- /dev/null +++ b/lib/kernel32/nls/lcSRL.c @@ -0,0 +1,144 @@ +/* + * nls/lcSRL.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SRL0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '1', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 'n', ' ', '(', 'L', 'a', 't', 'i', 'n', ')', 0 }, + (CONST WCHAR[]) { 'S', 'R', 'L', 0 }, + (CONST WCHAR[]) { 's', 'r', 'p', 's', 'k', 'i', 0 }, + (CONST WCHAR[]) { '3', '8', '1', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'S', 'P', 'B', 0 }, + (CONST WCHAR[]) { 'S', 'r', 'b', 'i', 'j', 'a', 0 }, + (CONST WCHAR[]) { '0', '8', '1', 'a', 0 }, + (CONST WCHAR[]) { '3', '8', '1', 0 }, + (CONST WCHAR[]) { '8', '5', '2', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'D', 'i', 'n', '.', 0 }, + (CONST WCHAR[]) { 'Y', 'U', 'D', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 'e', 'd', 'e', 'l', 'j', 'a', 'k', 0 }, + (CONST WCHAR[]) { 'u', 't', 'o', 'r', 'a', 'k', 0 }, + (CONST WCHAR[]) { 's', 'r', 'e', 'd', 'a', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 't', 'v', 'r', 't', 'a', 'k', 0 }, + (CONST WCHAR[]) { 'p', 'e', 't', 'a', 'k', 0 }, + (CONST WCHAR[]) { 's', 'u', 'b', 'o', 't', 'a', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 'e', 'l', 'j', 'a', 0 }, + (CONST WCHAR[]) { 'p', 'o', 'n', 0 }, + (CONST WCHAR[]) { 'u', 't', 'o', 0 }, + (CONST WCHAR[]) { 's', 'r', 'e', 0 }, + (CONST WCHAR[]) { 0x10D, 'e', 't', 0 }, + (CONST WCHAR[]) { 'p', 'e', 't', 0 }, + (CONST WCHAR[]) { 's', 'u', 'b', 0 }, + (CONST WCHAR[]) { 'n', 'e', 'd', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 't', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'g', 'u', 's', 't', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'v', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '\'', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x2, 0, 0, 0x400, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SRL1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 'n', ' ', '(', 'L', 'a', 't', 'i', 'n', ')', 0 }, + (CONST WCHAR[]) { 'S', 'e', 'r', 'b', 'i', 'a', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SRLds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SRLdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', 'd', 'd', ' ', 'd', 'd', ',', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SRLt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSVE.c b/lib/kernel32/nls/lcSVE.c new file mode 100644 index 0000000..b3072e8 --- /dev/null +++ b/lib/kernel32/nls/lcSVE.c @@ -0,0 +1,148 @@ +/* + * nls/lcSVE.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SVE0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', 'd', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'e', 'd', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'S', 'V', 'E', 0 }, + (CONST WCHAR[]) { 's', 'v', 'e', 'n', 's', 'k', 'a', 0 }, + (CONST WCHAR[]) { '4', '6', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'e', 'd', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'S', 'W', 'E', 0 }, + (CONST WCHAR[]) { 'S', 'v', 'e', 'r', 'i', 'g', 'e', 0 }, + (CONST WCHAR[]) { '0', '4', '1', 'd', 0 }, + (CONST WCHAR[]) { '4', '6', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'k', 'r', 0 }, + (CONST WCHAR[]) { 'S', 'E', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0 }, + (CONST WCHAR[]) { '\'', 'd', 'e', 'n', ' ', '\'', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 0xE5, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'i', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'o', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'e', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'l', 0xF6, 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 's', 0xF6, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 0xE5, 0 }, + (CONST WCHAR[]) { 't', 'i', 0 }, + (CONST WCHAR[]) { 'o', 'n', 0 }, + (CONST WCHAR[]) { 't', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0 }, + (CONST WCHAR[]) { 'l', 0xF6, 0 }, + (CONST WCHAR[]) { 's', 0xF6, 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 'i', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SVE1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'w', 'e', 'd', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'e', 'd', 'e', 'n', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SVEds[]= +{ + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SVEdl[]= +{ + (CONST WCHAR[]) { '\'', 'd', 'e', 'n', ' ', '\'', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { '\'', 'd', 'e', 'n', ' ', '\'', 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SVEt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { '\'', 'k', 'l', ' ', '\'', 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcSVF.c b/lib/kernel32/nls/lcSVF.c new file mode 100644 index 0000000..a901222 --- /dev/null +++ b/lib/kernel32/nls/lcSVF.c @@ -0,0 +1,149 @@ +/* + * nls/lcSVF.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_SVF0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '8', '1', 'd', 0 }, + (CONST WCHAR[]) { 'S', 'w', 'e', 'd', 'i', 's', 'h', ' ', '(', 'F', 'i', 'n', 'l', 'a', 'n', 'd', ')', 0 }, + (CONST WCHAR[]) { 'S', 'V', 'F', 0 }, + (CONST WCHAR[]) { 's', 'v', 'e', 'n', 's', 'k', 'a', 0 }, + (CONST WCHAR[]) { '3', '5', '8', 0 }, + (CONST WCHAR[]) { 'F', 'i', 'n', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'F', 'I', 'N', 0 }, + (CONST WCHAR[]) { 'F', 'i', 'n', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { '0', '8', '1', 'd', 0 }, + (CONST WCHAR[]) { '3', '5', '8', 0 }, + (CONST WCHAR[]) { '8', '5', '0', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'm', 'k', 0 }, + (CONST WCHAR[]) { 'F', 'I', 'M', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '\'', 'd', 'e', 'n', ' ', '\'', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'm', 0xE5, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'i', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'o', 'n', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 't', 'o', 'r', 's', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'f', 'r', 'e', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'l', 0xF6, 'r', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 's', 0xF6, 'n', 'd', 'a', 'g', 0 }, + (CONST WCHAR[]) { 'm', 0xE5, 0 }, + (CONST WCHAR[]) { 't', 'i', 0 }, + (CONST WCHAR[]) { 'o', 'n', 0 }, + (CONST WCHAR[]) { 't', 'o', 0 }, + (CONST WCHAR[]) { 'f', 'r', 0 }, + (CONST WCHAR[]) { 'l', 0xF6, 0 }, + (CONST WCHAR[]) { 's', 0xF6, 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 'r', 'u', 'a', 'r', 'i', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 's', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 'i', 'l', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 'i', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 'i', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 'u', 's', 't', 'i', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 'o', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'j', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'f', 'e', 'b', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'a', 'p', 'r', 0 }, + (CONST WCHAR[]) { 'm', 'a', 'j', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'n', 0 }, + (CONST WCHAR[]) { 'j', 'u', 'l', 0 }, + (CONST WCHAR[]) { 'a', 'u', 'g', 0 }, + (CONST WCHAR[]) { 's', 'e', 'p', 0 }, + (CONST WCHAR[]) { 'o', 'k', 't', 0 }, + (CONST WCHAR[]) { 'n', 'o', 'v', 0 }, + (CONST WCHAR[]) { 'd', 'e', 'c', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0, 0, 0, 0, 0, 0x1, 0, 0, 0x4000, 0x13, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SVF1[]= +{ + NULL, + (CONST WCHAR[]) { 'S', 'w', 'e', 'd', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'F', 'i', 'n', 'l', 'a', 'n', 'd', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '2', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_SVFds[]= +{ + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', '.', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', 'y', 'y', '-', 'M', 'M', '-', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SVFdl[]= +{ + (CONST WCHAR[]) { '\'', 'd', 'e', 'n', ' ', '\'', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_SVFt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { '\'', 'k', 'l', ' ', '\'', 'H', ':', 'm', 'm', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcTRK.c b/lib/kernel32/nls/lcTRK.c new file mode 100644 index 0000000..1d118e9 --- /dev/null +++ b/lib/kernel32/nls/lcTRK.c @@ -0,0 +1,148 @@ +/* + * nls/lcTRK.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_TRK0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '1', 'f', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'r', 'k', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'T', 'R', 'K', 0 }, + (CONST WCHAR[]) { 'T', 0xFC, 'r', 'k', 0xE7, 'e', 0 }, + (CONST WCHAR[]) { '9', '0', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'r', 'k', 'e', 'y', 0 }, + (CONST WCHAR[]) { 'T', 'U', 'R', 0 }, + (CONST WCHAR[]) { 'T', 0xFC, 'r', 'k', 'i', 'y', 'e', 0 }, + (CONST WCHAR[]) { '0', '4', '1', 'f', 0 }, + (CONST WCHAR[]) { '9', '0', 0 }, + (CONST WCHAR[]) { '8', '5', '7', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 'T', 'L', 0 }, + (CONST WCHAR[]) { 'T', 'R', 'L', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', 'd', 'd', 'd', 'd', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 'P', 'a', 'z', 'a', 'r', 't', 'e', 's', 'i', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'l', 0x131, 0 }, + (CONST WCHAR[]) { 0xC7, 'a', 'r', 0x15F, 'a', 'm', 'b', 'a', 0 }, + (CONST WCHAR[]) { 'P', 'e', 'r', 0x15F, 'e', 'm', 'b', 'e', 0 }, + (CONST WCHAR[]) { 'C', 'u', 'm', 'a', 0 }, + (CONST WCHAR[]) { 'C', 'u', 'm', 'a', 'r', 't', 'e', 's', 'i', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'z', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'P', 'z', 't', 0 }, + (CONST WCHAR[]) { 'S', 'a', 'l', 0 }, + (CONST WCHAR[]) { 0xC7, 'a', 'r', 0 }, + (CONST WCHAR[]) { 'P', 'e', 'r', 0 }, + (CONST WCHAR[]) { 'C', 'u', 'm', 0 }, + (CONST WCHAR[]) { 'C', 'm', 't', 0 }, + (CONST WCHAR[]) { 'P', 'a', 'z', 0 }, + (CONST WCHAR[]) { 'O', 'c', 'a', 'k', 0 }, + (CONST WCHAR[]) { 0x15E, 'u', 'b', 'a', 't', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 't', 0 }, + (CONST WCHAR[]) { 'N', 'i', 's', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0x131, 's', 0 }, + (CONST WCHAR[]) { 'H', 'a', 'z', 'i', 'r', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'T', 'e', 'm', 'm', 'u', 'z', 0 }, + (CONST WCHAR[]) { 'A', 0x11F, 'u', 's', 't', 'o', 's', 0 }, + (CONST WCHAR[]) { 'E', 'y', 'l', 0xFC, 'l', 0 }, + (CONST WCHAR[]) { 'E', 'k', 'i', 'm', 0 }, + (CONST WCHAR[]) { 'K', 'a', 's', 0x131, 'm', 0 }, + (CONST WCHAR[]) { 'A', 'r', 'a', 'l', 0x131, 'k', 0 }, + (CONST WCHAR[]) { 'O', 'c', 'a', 0 }, + (CONST WCHAR[]) { 0x15E, 'u', 'b', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'r', 0 }, + (CONST WCHAR[]) { 'N', 'i', 's', 0 }, + (CONST WCHAR[]) { 'M', 'a', 'y', 0 }, + (CONST WCHAR[]) { 'H', 'a', 'z', 0 }, + (CONST WCHAR[]) { 'T', 'e', 'm', 0 }, + (CONST WCHAR[]) { 'A', 0x11F, 'u', 0 }, + (CONST WCHAR[]) { 'E', 'y', 'l', 0 }, + (CONST WCHAR[]) { 'E', 'k', 'i', 0 }, + (CONST WCHAR[]) { 'K', 'a', 's', 0 }, + (CONST WCHAR[]) { 'A', 'r', 'a', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '/', 0x8000, 0x3808, 0x1000, 0, 0, 0, 0, 0x10, 0, 0, 0x100, 0x12, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_TRK1[]= +{ + NULL, + (CONST WCHAR[]) { 'T', 'u', 'r', 'k', 'i', 's', 'h', 0 }, + (CONST WCHAR[]) { 'T', 'u', 'r', 'k', 'e', 'y', 0 }, + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '4', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_TRKds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + (CONST WCHAR[]) { 'y', 'y', '.', 'M', 'M', '.', 'd', 'd', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_TRKdl[]= +{ + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', ' ', 'd', 'd', 'd', 'd', 0, 0 }, + (CONST WCHAR[]) { 'd', 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_TRKt[]= +{ + (CONST WCHAR[]) { 'H', 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lcUKR.c b/lib/kernel32/nls/lcUKR.c new file mode 100644 index 0000000..bb352ab --- /dev/null +++ b/lib/kernel32/nls/lcUKR.c @@ -0,0 +1,144 @@ +/* + * nls/lcUKR.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlc.exe + */ + +#include +#include + +CONST WCHAR *__LC_UKR0[]= +{ + NULL, + (CONST WCHAR[]) { '0', '4', '2', '2', 0 }, + (CONST WCHAR[]) { 'U', 'k', 'r', 'a', 'i', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'U', 'K', 'R', 0 }, + (CONST WCHAR[]) { 0x443, 0x43A, 0x440, 0x430, 0x457, 0x43D, 0x44C, 0x441, 0x43A, 0x430, 0 }, + (CONST WCHAR[]) { '3', '8', '0', 0 }, + (CONST WCHAR[]) { 'U', 'k', 'r', 'a', 'i', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'U', 'K', 'R', 0 }, + (CONST WCHAR[]) { 0x423, 0x43A, 0x440, 0x430, 0x457, 0x43D, 0x430, 0 }, + (CONST WCHAR[]) { '0', '4', '2', '2', 0 }, + (CONST WCHAR[]) { '7', 0 }, + (CONST WCHAR[]) { '8', '6', '6', 0 }, + (CONST WCHAR[]) { ';', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0 }, + (CONST WCHAR[]) { 0x43A, '.', 0 }, + (CONST WCHAR[]) { 'U', 'A', 'K', 0 }, + (CONST WCHAR[]) { ',', 0 }, + (CONST WCHAR[]) { 0xA0, 0 }, + (CONST WCHAR[]) { '3', ';', '0', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '2', 0 }, + (CONST WCHAR[]) { '3', 0 }, + (CONST WCHAR[]) { '8', 0 }, + (CONST WCHAR[]) { '.', 0 }, + (CONST WCHAR[]) { ':', 0 }, + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0 }, + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', '\'', ' ', 0x440, '.', '\'', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0x43F, 0x43E, 0x43D, 0x435, 0x434, 0x456, 0x43B, 0x43E, 0x43A, 0 }, + (CONST WCHAR[]) { 0x432, 0x456, 0x432, 0x442, 0x43E, 0x440, 0x43E, 0x43A, 0 }, + (CONST WCHAR[]) { 0x441, 0x435, 0x440, 0x435, 0x434, 0x430, 0 }, + (CONST WCHAR[]) { 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0 }, + (CONST WCHAR[]) { 0x43F, '\'', 0x44F, 0x442, 0x43D, 0x438, 0x446, 0x44F, 0 }, + (CONST WCHAR[]) { 0x441, 0x443, 0x431, 0x43E, 0x442, 0x430, 0 }, + (CONST WCHAR[]) { 0x43D, 0x435, 0x434, 0x456, 0x43B, 0x44F, 0 }, + (CONST WCHAR[]) { 0x41F, 0x43D, 0 }, + (CONST WCHAR[]) { 0x412, 0x432, 0 }, + (CONST WCHAR[]) { 0x421, 0x440, 0 }, + (CONST WCHAR[]) { 0x427, 0x442, 0 }, + (CONST WCHAR[]) { 0x41F, 0x442, 0 }, + (CONST WCHAR[]) { 0x421, 0x431, 0 }, + (CONST WCHAR[]) { 0x41D, 0x434, 0 }, + (CONST WCHAR[]) { 0x421, 0x456, 0x447, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41B, 0x44E, 0x442, 0x438, 0x439, 0 }, + (CONST WCHAR[]) { 0x411, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41A, 0x432, 0x456, 0x442, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x422, 0x440, 0x430, 0x432, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x427, 0x435, 0x440, 0x432, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41B, 0x438, 0x43F, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x440, 0x43F, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x412, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x416, 0x43E, 0x432, 0x442, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x41B, 0x438, 0x441, 0x442, 0x43E, 0x43F, 0x430, 0x434, 0 }, + (CONST WCHAR[]) { 0x413, 0x440, 0x443, 0x434, 0x435, 0x43D, 0x44C, 0 }, + (CONST WCHAR[]) { 0x421, 0x456, 0x447, 0 }, + (CONST WCHAR[]) { 0x41B, 0x44E, 0x442, 0 }, + (CONST WCHAR[]) { 0x411, 0x435, 0x440, 0 }, + (CONST WCHAR[]) { 0x41A, 0x432, 0x456, 0 }, + (CONST WCHAR[]) { 0x422, 0x440, 0x430, 0 }, + (CONST WCHAR[]) { 0x427, 0x435, 0x440, 0 }, + (CONST WCHAR[]) { 0x416, 0x438, 0x43F, 0 }, + (CONST WCHAR[]) { 0x421, 0x435, 0x440, 0 }, + (CONST WCHAR[]) { 0x412, 0x435, 0x440, 0 }, + (CONST WCHAR[]) { 0x416, 0x43E, 0x432, 0 }, + (CONST WCHAR[]) { 0x41B, 0x438, 0x441, 0 }, + (CONST WCHAR[]) { 0x413, 0x440, 0x433, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '-', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '1', 0 }, + (CONST WCHAR[]) { 0x203, 0x8000, 0x3848, 0, 0, 0, 0, 0, 0x4, 0, 0, 0x2, 0x4, 0, 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_UKR1[]= +{ + NULL, + (CONST WCHAR[]) { 'U', 'k', 'r', 'a', 'i', 'n', 'i', 'a', 'n', 0 }, + (CONST WCHAR[]) { 'U', 'k', 'r', 'a', 'i', 'n', 'e', 0 }, + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0 }, + (CONST WCHAR[]) { '1', '2', '5', '1', 0 }, + (CONST WCHAR[]) { '0', 0 }, + NULL, + NULL, + NULL, + (CONST WCHAR[]) { '1', 0 }, + NULL, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { '0', 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { 0, 0 }, + (CONST WCHAR[]) { '1', 0 }, + NULL +}; + +CONST WCHAR *__LC_UKRds[]= +{ + (CONST WCHAR[]) { 'd', 'd', '.', 'M', 'M', '.', 'y', 'y', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_UKRdl[]= +{ + (CONST WCHAR[]) { 'd', ' ', 'M', 'M', 'M', 'M', ' ', 'y', 'y', 'y', 'y', '\'', ' ', 0x440, '.', '\'', 0, 0 }, + NULL +}; + +CONST WCHAR *__LC_UKRt[]= +{ + (CONST WCHAR[]) { 'H', ':', 'm', 'm', ':', 's', 's', 0, 0 }, + NULL +}; + diff --git a/lib/kernel32/nls/lctable.c b/lib/kernel32/nls/lctable.c new file mode 100644 index 0000000..41eb2f7 --- /dev/null +++ b/lib/kernel32/nls/lctable.c @@ -0,0 +1,639 @@ +/* + * nls/lctable.c + * Copyright (C) 1996, Onno Hovers + * + * This file has been generated by genlctab.exe + */ + +#include +#include +#include + +extern LPWSTR __LC_ENU0; +extern LPWSTR __LC_ENU1; +extern LPWSTR __LC_ENUds; +extern LPWSTR __LC_ENUdl; +extern LPWSTR __LC_ENUt; + +extern LPWSTR __LC_ENG0; +extern LPWSTR __LC_ENG1; +extern LPWSTR __LC_ENGds; +extern LPWSTR __LC_ENGdl; +extern LPWSTR __LC_ENGt; + +extern LPWSTR __LC_ENA0; +extern LPWSTR __LC_ENA1; +extern LPWSTR __LC_ENAds; +extern LPWSTR __LC_ENAdl; +extern LPWSTR __LC_ENAt; + +extern LPWSTR __LC_ENC0; +extern LPWSTR __LC_ENC1; +extern LPWSTR __LC_ENCds; +extern LPWSTR __LC_ENCdl; +extern LPWSTR __LC_ENCt; + +extern LPWSTR __LC_ENZ0; +extern LPWSTR __LC_ENZ1; +extern LPWSTR __LC_ENZds; +extern LPWSTR __LC_ENZdl; +extern LPWSTR __LC_ENZt; + +extern LPWSTR __LC_ENI0; +extern LPWSTR __LC_ENI1; +extern LPWSTR __LC_ENIds; +extern LPWSTR __LC_ENIdl; +extern LPWSTR __LC_ENIt; + +extern LPWSTR __LC_ENS0; +extern LPWSTR __LC_ENS1; +extern LPWSTR __LC_ENSds; +extern LPWSTR __LC_ENSdl; +extern LPWSTR __LC_ENSt; + +extern LPWSTR __LC_ENJ0; +extern LPWSTR __LC_ENJ1; +extern LPWSTR __LC_ENJds; +extern LPWSTR __LC_ENJdl; +extern LPWSTR __LC_ENJt; + +extern LPWSTR __LC_ENB0; +extern LPWSTR __LC_ENB1; +extern LPWSTR __LC_ENBds; +extern LPWSTR __LC_ENBdl; +extern LPWSTR __LC_ENBt; + +extern LPWSTR __LC_ENL0; +extern LPWSTR __LC_ENL1; +extern LPWSTR __LC_ENLds; +extern LPWSTR __LC_ENLdl; +extern LPWSTR __LC_ENLt; + +extern LPWSTR __LC_ENT0; +extern LPWSTR __LC_ENT1; +extern LPWSTR __LC_ENTds; +extern LPWSTR __LC_ENTdl; +extern LPWSTR __LC_ENTt; + +extern LPWSTR __LC_BGR0; +extern LPWSTR __LC_BGR1; +extern LPWSTR __LC_BGRds; +extern LPWSTR __LC_BGRdl; +extern LPWSTR __LC_BGRt; + +extern LPWSTR __LC_CSY0; +extern LPWSTR __LC_CSY1; +extern LPWSTR __LC_CSYds; +extern LPWSTR __LC_CSYdl; +extern LPWSTR __LC_CSYt; + +extern LPWSTR __LC_DAN0; +extern LPWSTR __LC_DAN1; +extern LPWSTR __LC_DANds; +extern LPWSTR __LC_DANdl; +extern LPWSTR __LC_DANt; + +extern LPWSTR __LC_DEU0; +extern LPWSTR __LC_DEU1; +extern LPWSTR __LC_DEUds; +extern LPWSTR __LC_DEUdl; +extern LPWSTR __LC_DEUt; + +extern LPWSTR __LC_DES0; +extern LPWSTR __LC_DES1; +extern LPWSTR __LC_DESds; +extern LPWSTR __LC_DESdl; +extern LPWSTR __LC_DESt; + +extern LPWSTR __LC_DEA0; +extern LPWSTR __LC_DEA1; +extern LPWSTR __LC_DEAds; +extern LPWSTR __LC_DEAdl; +extern LPWSTR __LC_DEAt; + +extern LPWSTR __LC_DEL0; +extern LPWSTR __LC_DEL1; +extern LPWSTR __LC_DELds; +extern LPWSTR __LC_DELdl; +extern LPWSTR __LC_DELt; + +extern LPWSTR __LC_DEC0; +extern LPWSTR __LC_DEC1; +extern LPWSTR __LC_DECds; +extern LPWSTR __LC_DECdl; +extern LPWSTR __LC_DECt; + +extern LPWSTR __LC_ELL0; +extern LPWSTR __LC_ELL1; +extern LPWSTR __LC_ELLds; +extern LPWSTR __LC_ELLdl; +extern LPWSTR __LC_ELLt; + +extern LPWSTR __LC_ESP0; +extern LPWSTR __LC_ESP1; +extern LPWSTR __LC_ESPds; +extern LPWSTR __LC_ESPdl; +extern LPWSTR __LC_ESPt; + +extern LPWSTR __LC_ESM0; +extern LPWSTR __LC_ESM1; +extern LPWSTR __LC_ESMds; +extern LPWSTR __LC_ESMdl; +extern LPWSTR __LC_ESMt; + +extern LPWSTR __LC_ESN0; +extern LPWSTR __LC_ESN1; +extern LPWSTR __LC_ESNds; +extern LPWSTR __LC_ESNdl; +extern LPWSTR __LC_ESNt; + +extern LPWSTR __LC_ESG0; +extern LPWSTR __LC_ESG1; +extern LPWSTR __LC_ESGds; +extern LPWSTR __LC_ESGdl; +extern LPWSTR __LC_ESGt; + +extern LPWSTR __LC_ESC0; +extern LPWSTR __LC_ESC1; +extern LPWSTR __LC_ESCds; +extern LPWSTR __LC_ESCdl; +extern LPWSTR __LC_ESCt; + +extern LPWSTR __LC_ESA0; +extern LPWSTR __LC_ESA1; +extern LPWSTR __LC_ESAds; +extern LPWSTR __LC_ESAdl; +extern LPWSTR __LC_ESAt; + +extern LPWSTR __LC_ESD0; +extern LPWSTR __LC_ESD1; +extern LPWSTR __LC_ESDds; +extern LPWSTR __LC_ESDdl; +extern LPWSTR __LC_ESDt; + +extern LPWSTR __LC_ESV0; +extern LPWSTR __LC_ESV1; +extern LPWSTR __LC_ESVds; +extern LPWSTR __LC_ESVdl; +extern LPWSTR __LC_ESVt; + +extern LPWSTR __LC_ESO0; +extern LPWSTR __LC_ESO1; +extern LPWSTR __LC_ESOds; +extern LPWSTR __LC_ESOdl; +extern LPWSTR __LC_ESOt; + +extern LPWSTR __LC_ESR0; +extern LPWSTR __LC_ESR1; +extern LPWSTR __LC_ESRds; +extern LPWSTR __LC_ESRdl; +extern LPWSTR __LC_ESRt; + +extern LPWSTR __LC_ESS0; +extern LPWSTR __LC_ESS1; +extern LPWSTR __LC_ESSds; +extern LPWSTR __LC_ESSdl; +extern LPWSTR __LC_ESSt; + +extern LPWSTR __LC_ESF0; +extern LPWSTR __LC_ESF1; +extern LPWSTR __LC_ESFds; +extern LPWSTR __LC_ESFdl; +extern LPWSTR __LC_ESFt; + +extern LPWSTR __LC_ESL0; +extern LPWSTR __LC_ESL1; +extern LPWSTR __LC_ESLds; +extern LPWSTR __LC_ESLdl; +extern LPWSTR __LC_ESLt; + +extern LPWSTR __LC_ESY0; +extern LPWSTR __LC_ESY1; +extern LPWSTR __LC_ESYds; +extern LPWSTR __LC_ESYdl; +extern LPWSTR __LC_ESYt; + +extern LPWSTR __LC_ESZ0; +extern LPWSTR __LC_ESZ1; +extern LPWSTR __LC_ESZds; +extern LPWSTR __LC_ESZdl; +extern LPWSTR __LC_ESZt; + +extern LPWSTR __LC_ESB0; +extern LPWSTR __LC_ESB1; +extern LPWSTR __LC_ESBds; +extern LPWSTR __LC_ESBdl; +extern LPWSTR __LC_ESBt; + +extern LPWSTR __LC_ESE0; +extern LPWSTR __LC_ESE1; +extern LPWSTR __LC_ESEds; +extern LPWSTR __LC_ESEdl; +extern LPWSTR __LC_ESEt; + +extern LPWSTR __LC_ESH0; +extern LPWSTR __LC_ESH1; +extern LPWSTR __LC_ESHds; +extern LPWSTR __LC_ESHdl; +extern LPWSTR __LC_ESHt; + +extern LPWSTR __LC_ESI0; +extern LPWSTR __LC_ESI1; +extern LPWSTR __LC_ESIds; +extern LPWSTR __LC_ESIdl; +extern LPWSTR __LC_ESIt; + +extern LPWSTR __LC_ESU0; +extern LPWSTR __LC_ESU1; +extern LPWSTR __LC_ESUds; +extern LPWSTR __LC_ESUdl; +extern LPWSTR __LC_ESUt; + +extern LPWSTR __LC_FIN0; +extern LPWSTR __LC_FIN1; +extern LPWSTR __LC_FINds; +extern LPWSTR __LC_FINdl; +extern LPWSTR __LC_FINt; + +extern LPWSTR __LC_FRA0; +extern LPWSTR __LC_FRA1; +extern LPWSTR __LC_FRAds; +extern LPWSTR __LC_FRAdl; +extern LPWSTR __LC_FRAt; + +extern LPWSTR __LC_FRB0; +extern LPWSTR __LC_FRB1; +extern LPWSTR __LC_FRBds; +extern LPWSTR __LC_FRBdl; +extern LPWSTR __LC_FRBt; + +extern LPWSTR __LC_FRC0; +extern LPWSTR __LC_FRC1; +extern LPWSTR __LC_FRCds; +extern LPWSTR __LC_FRCdl; +extern LPWSTR __LC_FRCt; + +extern LPWSTR __LC_FRS0; +extern LPWSTR __LC_FRS1; +extern LPWSTR __LC_FRSds; +extern LPWSTR __LC_FRSdl; +extern LPWSTR __LC_FRSt; + +extern LPWSTR __LC_FRL0; +extern LPWSTR __LC_FRL1; +extern LPWSTR __LC_FRLds; +extern LPWSTR __LC_FRLdl; +extern LPWSTR __LC_FRLt; + +extern LPWSTR __LC_HUN0; +extern LPWSTR __LC_HUN1; +extern LPWSTR __LC_HUNds; +extern LPWSTR __LC_HUNdl; +extern LPWSTR __LC_HUNt; + +extern LPWSTR __LC_ISL0; +extern LPWSTR __LC_ISL1; +extern LPWSTR __LC_ISLds; +extern LPWSTR __LC_ISLdl; +extern LPWSTR __LC_ISLt; + +extern LPWSTR __LC_ITA0; +extern LPWSTR __LC_ITA1; +extern LPWSTR __LC_ITAds; +extern LPWSTR __LC_ITAdl; +extern LPWSTR __LC_ITAt; + +extern LPWSTR __LC_ITS0; +extern LPWSTR __LC_ITS1; +extern LPWSTR __LC_ITSds; +extern LPWSTR __LC_ITSdl; +extern LPWSTR __LC_ITSt; + +extern LPWSTR __LC_NLD0; +extern LPWSTR __LC_NLD1; +extern LPWSTR __LC_NLDds; +extern LPWSTR __LC_NLDdl; +extern LPWSTR __LC_NLDt; + +extern LPWSTR __LC_NLB0; +extern LPWSTR __LC_NLB1; +extern LPWSTR __LC_NLBds; +extern LPWSTR __LC_NLBdl; +extern LPWSTR __LC_NLBt; + +extern LPWSTR __LC_NOR0; +extern LPWSTR __LC_NOR1; +extern LPWSTR __LC_NORds; +extern LPWSTR __LC_NORdl; +extern LPWSTR __LC_NORt; + +extern LPWSTR __LC_NON0; +extern LPWSTR __LC_NON1; +extern LPWSTR __LC_NONds; +extern LPWSTR __LC_NONdl; +extern LPWSTR __LC_NONt; + +extern LPWSTR __LC_PLK0; +extern LPWSTR __LC_PLK1; +extern LPWSTR __LC_PLKds; +extern LPWSTR __LC_PLKdl; +extern LPWSTR __LC_PLKt; + +extern LPWSTR __LC_PTB0; +extern LPWSTR __LC_PTB1; +extern LPWSTR __LC_PTBds; +extern LPWSTR __LC_PTBdl; +extern LPWSTR __LC_PTBt; + +extern LPWSTR __LC_PTG0; +extern LPWSTR __LC_PTG1; +extern LPWSTR __LC_PTGds; +extern LPWSTR __LC_PTGdl; +extern LPWSTR __LC_PTGt; + +extern LPWSTR __LC_ROM0; +extern LPWSTR __LC_ROM1; +extern LPWSTR __LC_ROMds; +extern LPWSTR __LC_ROMdl; +extern LPWSTR __LC_ROMt; + +extern LPWSTR __LC_RUS0; +extern LPWSTR __LC_RUS1; +extern LPWSTR __LC_RUSds; +extern LPWSTR __LC_RUSdl; +extern LPWSTR __LC_RUSt; + +extern LPWSTR __LC_HRV0; +extern LPWSTR __LC_HRV1; +extern LPWSTR __LC_HRVds; +extern LPWSTR __LC_HRVdl; +extern LPWSTR __LC_HRVt; + +extern LPWSTR __LC_SRL0; +extern LPWSTR __LC_SRL1; +extern LPWSTR __LC_SRLds; +extern LPWSTR __LC_SRLdl; +extern LPWSTR __LC_SRLt; + +extern LPWSTR __LC_SRB0; +extern LPWSTR __LC_SRB1; +extern LPWSTR __LC_SRBds; +extern LPWSTR __LC_SRBdl; +extern LPWSTR __LC_SRBt; + +extern LPWSTR __LC_SKY0; +extern LPWSTR __LC_SKY1; +extern LPWSTR __LC_SKYds; +extern LPWSTR __LC_SKYdl; +extern LPWSTR __LC_SKYt; + +extern LPWSTR __LC_SVE0; +extern LPWSTR __LC_SVE1; +extern LPWSTR __LC_SVEds; +extern LPWSTR __LC_SVEdl; +extern LPWSTR __LC_SVEt; + +extern LPWSTR __LC_SVF0; +extern LPWSTR __LC_SVF1; +extern LPWSTR __LC_SVFds; +extern LPWSTR __LC_SVFdl; +extern LPWSTR __LC_SVFt; + +extern LPWSTR __LC_TRK0; +extern LPWSTR __LC_TRK1; +extern LPWSTR __LC_TRKds; +extern LPWSTR __LC_TRKdl; +extern LPWSTR __LC_TRKt; + +extern LPWSTR __LC_SLV0; +extern LPWSTR __LC_SLV1; +extern LPWSTR __LC_SLVds; +extern LPWSTR __LC_SLVdl; +extern LPWSTR __LC_SLVt; + +extern LPWSTR __LC_AFK0; +extern LPWSTR __LC_AFK1; +extern LPWSTR __LC_AFKds; +extern LPWSTR __LC_AFKdl; +extern LPWSTR __LC_AFKt; + +extern LPWSTR __LC_SQI0; +extern LPWSTR __LC_SQI1; +extern LPWSTR __LC_SQIds; +extern LPWSTR __LC_SQIdl; +extern LPWSTR __LC_SQIt; + +extern LPWSTR __LC_EUQ0; +extern LPWSTR __LC_EUQ1; +extern LPWSTR __LC_EUQds; +extern LPWSTR __LC_EUQdl; +extern LPWSTR __LC_EUQt; + +extern LPWSTR __LC_BEL0; +extern LPWSTR __LC_BEL1; +extern LPWSTR __LC_BELds; +extern LPWSTR __LC_BELdl; +extern LPWSTR __LC_BELt; + +extern LPWSTR __LC_CAT0; +extern LPWSTR __LC_CAT1; +extern LPWSTR __LC_CATds; +extern LPWSTR __LC_CATdl; +extern LPWSTR __LC_CATt; + +extern LPWSTR __LC_ETI0; +extern LPWSTR __LC_ETI1; +extern LPWSTR __LC_ETIds; +extern LPWSTR __LC_ETIdl; +extern LPWSTR __LC_ETIt; + +extern LPWSTR __LC_FOS0; +extern LPWSTR __LC_FOS1; +extern LPWSTR __LC_FOSds; +extern LPWSTR __LC_FOSdl; +extern LPWSTR __LC_FOSt; + +extern LPWSTR __LC_IND0; +extern LPWSTR __LC_IND1; +extern LPWSTR __LC_INDds; +extern LPWSTR __LC_INDdl; +extern LPWSTR __LC_INDt; + +extern LPWSTR __LC_LVI0; +extern LPWSTR __LC_LVI1; +extern LPWSTR __LC_LVIds; +extern LPWSTR __LC_LVIdl; +extern LPWSTR __LC_LVIt; + +extern LPWSTR __LC_LTH0; +extern LPWSTR __LC_LTH1; +extern LPWSTR __LC_LTHds; +extern LPWSTR __LC_LTHdl; +extern LPWSTR __LC_LTHt; + +extern LPWSTR __LC_UKR0; +extern LPWSTR __LC_UKR1; +extern LPWSTR __LC_UKRds; +extern LPWSTR __LC_UKRdl; +extern LPWSTR __LC_UKRt; + +LOCALE __Locale[LOCALE_ARRAY]= +{ + { 0x0409, "ENU", &__LC_ENU0, &__LC_ENU1, &__LC_ENUds, &__LC_ENUdl, + &__LC_ENUt, &__CP1252, &__CP437 }, + { 0x0809, "ENG", &__LC_ENG0, &__LC_ENG1, &__LC_ENGds, &__LC_ENGdl, + &__LC_ENGt, &__CP1252, &__CP850 }, + { 0x0C09, "ENA", &__LC_ENA0, &__LC_ENA1, &__LC_ENAds, &__LC_ENAdl, + &__LC_ENAt, &__CP1252, &__CP850 }, + { 0x1009, "ENC", &__LC_ENC0, &__LC_ENC1, &__LC_ENCds, &__LC_ENCdl, + &__LC_ENCt, &__CP1252, &__CP850 }, + { 0x1409, "ENZ", &__LC_ENZ0, &__LC_ENZ1, &__LC_ENZds, &__LC_ENZdl, + &__LC_ENZt, &__CP1252, &__CP850 }, + { 0x1809, "ENI", &__LC_ENI0, &__LC_ENI1, &__LC_ENIds, &__LC_ENIdl, + &__LC_ENIt, &__CP1252, &__CP850 }, + { 0x1C09, "ENS", &__LC_ENS0, &__LC_ENS1, &__LC_ENSds, &__LC_ENSdl, + &__LC_ENSt, &__CP1252, &__CP437 }, + { 0x2009, "ENJ", &__LC_ENJ0, &__LC_ENJ1, &__LC_ENJds, &__LC_ENJdl, + &__LC_ENJt, &__CP1252, &__CP850 }, + { 0x2409, "ENB", &__LC_ENB0, &__LC_ENB1, &__LC_ENBds, &__LC_ENBdl, + &__LC_ENBt, &__CP1252, &__CP850 }, + { 0x2809, "ENL", &__LC_ENL0, &__LC_ENL1, &__LC_ENLds, &__LC_ENLdl, + &__LC_ENLt, &__CP1252, &__CP850 }, + { 0x2C09, "ENT", &__LC_ENT0, &__LC_ENT1, &__LC_ENTds, &__LC_ENTdl, + &__LC_ENTt, &__CP1252, &__CP850 }, + { 0x0402, "BGR", &__LC_BGR0, &__LC_BGR1, &__LC_BGRds, &__LC_BGRdl, + &__LC_BGRt, &__CP1251, &__CP866 }, + { 0x0405, "CSY", &__LC_CSY0, &__LC_CSY1, &__LC_CSYds, &__LC_CSYdl, + &__LC_CSYt, &__CP1250, &__CP852 }, + { 0x0406, "DAN", &__LC_DAN0, &__LC_DAN1, &__LC_DANds, &__LC_DANdl, + &__LC_DANt, &__CP1252, &__CP850 }, + { 0x0407, "DEU", &__LC_DEU0, &__LC_DEU1, &__LC_DEUds, &__LC_DEUdl, + &__LC_DEUt, &__CP1252, &__CP850 }, + { 0x0807, "DES", &__LC_DES0, &__LC_DES1, &__LC_DESds, &__LC_DESdl, + &__LC_DESt, &__CP1252, &__CP850 }, + { 0x0C07, "DEA", &__LC_DEA0, &__LC_DEA1, &__LC_DEAds, &__LC_DEAdl, + &__LC_DEAt, &__CP1252, &__CP850 }, + { 0x1007, "DEL", &__LC_DEL0, &__LC_DEL1, &__LC_DELds, &__LC_DELdl, + &__LC_DELt, &__CP1252, &__CP850 }, + { 0x1407, "DEC", &__LC_DEC0, &__LC_DEC1, &__LC_DECds, &__LC_DECdl, + &__LC_DECt, &__CP1252, &__CP850 }, + { 0x0408, "ELL", &__LC_ELL0, &__LC_ELL1, &__LC_ELLds, &__LC_ELLdl, + &__LC_ELLt, &__CP1253, &__CP737 }, + { 0x040A, "ESP", &__LC_ESP0, &__LC_ESP1, &__LC_ESPds, &__LC_ESPdl, + &__LC_ESPt, &__CP1252, &__CP850 }, + { 0x080A, "ESM", &__LC_ESM0, &__LC_ESM1, &__LC_ESMds, &__LC_ESMdl, + &__LC_ESMt, &__CP1252, &__CP850 }, + { 0x0C0A, "ESN", &__LC_ESN0, &__LC_ESN1, &__LC_ESNds, &__LC_ESNdl, + &__LC_ESNt, &__CP1252, &__CP850 }, + { 0x100A, "ESG", &__LC_ESG0, &__LC_ESG1, &__LC_ESGds, &__LC_ESGdl, + &__LC_ESGt, &__CP1252, &__CP850 }, + { 0x140A, "ESC", &__LC_ESC0, &__LC_ESC1, &__LC_ESCds, &__LC_ESCdl, + &__LC_ESCt, &__CP1252, &__CP850 }, + { 0x180A, "ESA", &__LC_ESA0, &__LC_ESA1, &__LC_ESAds, &__LC_ESAdl, + &__LC_ESAt, &__CP1252, &__CP850 }, + { 0x1C0A, "ESD", &__LC_ESD0, &__LC_ESD1, &__LC_ESDds, &__LC_ESDdl, + &__LC_ESDt, &__CP1252, &__CP850 }, + { 0x200A, "ESV", &__LC_ESV0, &__LC_ESV1, &__LC_ESVds, &__LC_ESVdl, + &__LC_ESVt, &__CP1252, &__CP850 }, + { 0x240A, "ESO", &__LC_ESO0, &__LC_ESO1, &__LC_ESOds, &__LC_ESOdl, + &__LC_ESOt, &__CP1252, &__CP850 }, + { 0x280A, "ESR", &__LC_ESR0, &__LC_ESR1, &__LC_ESRds, &__LC_ESRdl, + &__LC_ESRt, &__CP1252, &__CP850 }, + { 0x2C0A, "ESS", &__LC_ESS0, &__LC_ESS1, &__LC_ESSds, &__LC_ESSdl, + &__LC_ESSt, &__CP1252, &__CP850 }, + { 0x300A, "ESF", &__LC_ESF0, &__LC_ESF1, &__LC_ESFds, &__LC_ESFdl, + &__LC_ESFt, &__CP1252, &__CP850 }, + { 0x340A, "ESL", &__LC_ESL0, &__LC_ESL1, &__LC_ESLds, &__LC_ESLdl, + &__LC_ESLt, &__CP1252, &__CP850 }, + { 0x380A, "ESY", &__LC_ESY0, &__LC_ESY1, &__LC_ESYds, &__LC_ESYdl, + &__LC_ESYt, &__CP1252, &__CP850 }, + { 0x3C0A, "ESZ", &__LC_ESZ0, &__LC_ESZ1, &__LC_ESZds, &__LC_ESZdl, + &__LC_ESZt, &__CP1252, &__CP850 }, + { 0x400A, "ESB", &__LC_ESB0, &__LC_ESB1, &__LC_ESBds, &__LC_ESBdl, + &__LC_ESBt, &__CP1252, &__CP850 }, + { 0x440A, "ESE", &__LC_ESE0, &__LC_ESE1, &__LC_ESEds, &__LC_ESEdl, + &__LC_ESEt, &__CP1252, &__CP850 }, + { 0x480A, "ESH", &__LC_ESH0, &__LC_ESH1, &__LC_ESHds, &__LC_ESHdl, + &__LC_ESHt, &__CP1252, &__CP850 }, + { 0x4C0A, "ESI", &__LC_ESI0, &__LC_ESI1, &__LC_ESIds, &__LC_ESIdl, + &__LC_ESIt, &__CP1252, &__CP850 }, + { 0x500A, "ESU", &__LC_ESU0, &__LC_ESU1, &__LC_ESUds, &__LC_ESUdl, + &__LC_ESUt, &__CP1252, &__CP850 }, + { 0x040B, "FIN", &__LC_FIN0, &__LC_FIN1, &__LC_FINds, &__LC_FINdl, + &__LC_FINt, &__CP1252, &__CP850 }, + { 0x040C, "FRA", &__LC_FRA0, &__LC_FRA1, &__LC_FRAds, &__LC_FRAdl, + &__LC_FRAt, &__CP1252, &__CP850 }, + { 0x080C, "FRB", &__LC_FRB0, &__LC_FRB1, &__LC_FRBds, &__LC_FRBdl, + &__LC_FRBt, &__CP1252, &__CP850 }, + { 0x0C0C, "FRC", &__LC_FRC0, &__LC_FRC1, &__LC_FRCds, &__LC_FRCdl, + &__LC_FRCt, &__CP1252, &__CP850 }, + { 0x100C, "FRS", &__LC_FRS0, &__LC_FRS1, &__LC_FRSds, &__LC_FRSdl, + &__LC_FRSt, &__CP1252, &__CP850 }, + { 0x140C, "FRL", &__LC_FRL0, &__LC_FRL1, &__LC_FRLds, &__LC_FRLdl, + &__LC_FRLt, &__CP1252, &__CP850 }, + { 0x040E, "HUN", &__LC_HUN0, &__LC_HUN1, &__LC_HUNds, &__LC_HUNdl, + &__LC_HUNt, &__CP1250, &__CP852 }, + { 0x040F, "ISL", &__LC_ISL0, &__LC_ISL1, &__LC_ISLds, &__LC_ISLdl, + &__LC_ISLt, &__CP1252, &__CP850 }, + { 0x0410, "ITA", &__LC_ITA0, &__LC_ITA1, &__LC_ITAds, &__LC_ITAdl, + &__LC_ITAt, &__CP1252, &__CP850 }, + { 0x0810, "ITS", &__LC_ITS0, &__LC_ITS1, &__LC_ITSds, &__LC_ITSdl, + &__LC_ITSt, &__CP1252, &__CP850 }, + { 0x0413, "NLD", &__LC_NLD0, &__LC_NLD1, &__LC_NLDds, &__LC_NLDdl, + &__LC_NLDt, &__CP1252, &__CP850 }, + { 0x0813, "NLB", &__LC_NLB0, &__LC_NLB1, &__LC_NLBds, &__LC_NLBdl, + &__LC_NLBt, &__CP1252, &__CP850 }, + { 0x0414, "NOR", &__LC_NOR0, &__LC_NOR1, &__LC_NORds, &__LC_NORdl, + &__LC_NORt, &__CP1252, &__CP850 }, + { 0x0814, "NON", &__LC_NON0, &__LC_NON1, &__LC_NONds, &__LC_NONdl, + &__LC_NONt, &__CP1252, &__CP850 }, + { 0x0415, "PLK", &__LC_PLK0, &__LC_PLK1, &__LC_PLKds, &__LC_PLKdl, + &__LC_PLKt, &__CP1250, &__CP852 }, + { 0x0416, "PTB", &__LC_PTB0, &__LC_PTB1, &__LC_PTBds, &__LC_PTBdl, + &__LC_PTBt, &__CP1252, &__CP850 }, + { 0x0816, "PTG", &__LC_PTG0, &__LC_PTG1, &__LC_PTGds, &__LC_PTGdl, + &__LC_PTGt, &__CP1252, &__CP850 }, + { 0x0418, "ROM", &__LC_ROM0, &__LC_ROM1, &__LC_ROMds, &__LC_ROMdl, + &__LC_ROMt, &__CP1250, &__CP852 }, + { 0x0419, "RUS", &__LC_RUS0, &__LC_RUS1, &__LC_RUSds, &__LC_RUSdl, + &__LC_RUSt, &__CP1251, &__CP866 }, + { 0x041A, "HRV", &__LC_HRV0, &__LC_HRV1, &__LC_HRVds, &__LC_HRVdl, + &__LC_HRVt, &__CP1250, &__CP852 }, + { 0x081A, "SRL", &__LC_SRL0, &__LC_SRL1, &__LC_SRLds, &__LC_SRLdl, + &__LC_SRLt, &__CP1250, &__CP852 }, + { 0x0C1A, "SRB", &__LC_SRB0, &__LC_SRB1, &__LC_SRBds, &__LC_SRBdl, + &__LC_SRBt, &__CP1251, &__CP866 }, + { 0x041B, "SKY", &__LC_SKY0, &__LC_SKY1, &__LC_SKYds, &__LC_SKYdl, + &__LC_SKYt, &__CP1250, &__CP852 }, + { 0x041D, "SVE", &__LC_SVE0, &__LC_SVE1, &__LC_SVEds, &__LC_SVEdl, + &__LC_SVEt, &__CP1252, &__CP850 }, + { 0x081D, "SVF", &__LC_SVF0, &__LC_SVF1, &__LC_SVFds, &__LC_SVFdl, + &__LC_SVFt, &__CP1252, &__CP850 }, + { 0x041F, "TRK", &__LC_TRK0, &__LC_TRK1, &__LC_TRKds, &__LC_TRKdl, + &__LC_TRKt, &__CP1254, &__CP857 }, + { 0x0424, "SLV", &__LC_SLV0, &__LC_SLV1, &__LC_SLVds, &__LC_SLVdl, + &__LC_SLVt, &__CP1250, &__CP852 }, + { 0x0436, "AFK", &__LC_AFK0, &__LC_AFK1, &__LC_AFKds, &__LC_AFKdl, + &__LC_AFKt, &__CP1252, &__CP850 }, + { 0x041C, "SQI", &__LC_SQI0, &__LC_SQI1, &__LC_SQIds, &__LC_SQIdl, + &__LC_SQIt, &__CP1250, &__CP852 }, + { 0x042D, "EUQ", &__LC_EUQ0, &__LC_EUQ1, &__LC_EUQds, &__LC_EUQdl, + &__LC_EUQt, &__CP1252, &__CP850 }, + { 0x0423, "BEL", &__LC_BEL0, &__LC_BEL1, &__LC_BELds, &__LC_BELdl, + &__LC_BELt, &__CP1251, &__CP866 }, + { 0x0403, "CAT", &__LC_CAT0, &__LC_CAT1, &__LC_CATds, &__LC_CATdl, + &__LC_CATt, &__CP1252, &__CP850 }, + { 0x0425, "ETI", &__LC_ETI0, &__LC_ETI1, &__LC_ETIds, &__LC_ETIdl, + &__LC_ETIt, &__CP1257, &__CP775 }, + { 0x0438, "FOS", &__LC_FOS0, &__LC_FOS1, &__LC_FOSds, &__LC_FOSdl, + &__LC_FOSt, &__CP1252, &__CP850 }, + { 0x0421, "IND", &__LC_IND0, &__LC_IND1, &__LC_INDds, &__LC_INDdl, + &__LC_INDt, &__CP1252, &__CP850 }, + { 0x0426, "LVI", &__LC_LVI0, &__LC_LVI1, &__LC_LVIds, &__LC_LVIdl, + &__LC_LVIt, &__CP1257, &__CP775 }, + { 0x0427, "LTH", &__LC_LTH0, &__LC_LTH1, &__LC_LTHds, &__LC_LTHdl, + &__LC_LTHt, &__CP1257, &__CP775 }, + { 0x0422, "UKR", &__LC_UKR0, &__LC_UKR1, &__LC_UKRds, &__LC_UKRdl, + &__LC_UKRt, &__CP1251, &__CP866 }, + { 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; diff --git a/lib/kernel32/nls/locale.c b/lib/kernel32/nls/locale.c new file mode 100644 index 0000000..9209e2d --- /dev/null +++ b/lib/kernel32/nls/locale.c @@ -0,0 +1,1280 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + Addition copyrights might be specified in LGPL.c + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/nls/locale.c + * PURPOSE: National language support functions + * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) + * UPDATE HISTORY: Modified from Onno Hovers wfc. ( 08/02/99 ) + Modified from wine. ( 08/02/99 ) + * + */ + +/* + * nls/locale.c + * + */ +/* + * OLE2NLS library + * + * Copyright 1995 Martin von Loewis + * Copyright 1998 David Lee Lambert + */ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include + +#include +#include + +#undef tolower +#undef toupper +#undef isupper +#undef islower +#undef isalnum +#undef isalpha +#undef isblank +#undef isdigit + +#undef towlower +#undef towupper +#undef iswupper +#undef iswlower +#undef iswalnum +#undef iswalpha + +#define tolower(c) ((c >= 'A' && c <= 'Z') ? c - ( 'A' - 'a' ) : c) +#define toupper(c) ((c >= 'a' && c <= 'z') ? c + 'A' - 'a' : c); +#define isupper(c) (c >= 'A' && c <= 'Z' ) +#define islower(c) (c >= 'a' && c <= 'z') +#define isalnum(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) +#define isalpha(c) (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') +#define isblank(c) ( c == ' ' || c == '\t' ) +#define isdigit(c) ((c >= '0' && c <= '9')) +#define isspace(c) ((c == ' ')) +#define ispunct(c) ((c == '.')) +#define isxdigit(c) ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9')) +#define iscntrl(c) ((c >=0x00 && c <= 0x1f) || c == 0x7f) + + +#define towlower(c) ((c >= L'A' && c <= L'Z') ? c - ( L'A' - L'a' ) : c) +#define towupper(c) ((c >= L'a' && c <= L'z') ? c + L'A' - L'a' : c); +#define iswupper(c) (c >= L'A' && c <= L'Z' ) +#define iswlower(c) (c >= L'a' && c <= L'z') +#define iswalnum(c) ((c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z') || (c >= L'0' && c <= L'9')) +#define iswalpha(c) (c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z') + +/* + +int OLE_GetFormatA(LCID locale, + DWORD flags, + DWORD tflags, + LPSYSTEMTIME xtime, + LPCSTR _format, + LPSTR date, + int datelen); +*/ + +#undef LCID + +#define SYSTEM_DEFAULT_LANGUAGE LANG_ENGLISH +#define SYSTEM_DEFAULT_SUBLANGUAGE SUBLANG_ENGLISH_US +#define SYSTEM_DEFAULT_SORTORDER SORT_DEFAULT + + +PLOCALE __UserLocale; +PLOCALE __TebLocale; +LOCALE __Locale[LOCALE_ARRAY]; + +WINBOOL __LocaleInit(void) +{ + PSTR locstr; + LCID lcid; + PLOCALE plocale=NULL; + + locstr=getenv("WF_LOCALE"); + if(locstr) + { + plocale=__Locale; + while((plocale->Id)&&(strcasecmp(locstr,plocale->AbbrName))) + plocale++; + } + /* if we do not have a locale, default */ + if(!plocale) + { + lcid=MAKELCID(MAKELANGID(SYSTEM_DEFAULT_LANGUAGE, + SYSTEM_DEFAULT_SUBLANGUAGE), + SYSTEM_DEFAULT_SORTORDER); + plocale=__Locale; + while((plocale->Id)&&(lcid!=plocale->Id)) + plocale++; + } + /* if this does not work, use our disaster plan */ + if(!plocale) + plocale=__Locale; + + __UserLocale=plocale; + __TebLocale=plocale; + return TRUE; +} + +LANGID STDCALL GetUserDefaultLangID(void) +{ + return LANGIDFROMLCID(__UserLocale->Id); +} + +LCID +STDCALL +GetUserDefaultLCID(void) +{ + return __UserLocale->Id; +} + +LANGID STDCALL GetSystemDefaultLangID(void) +{ + return MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US); +} + +LCID STDCALL GetSystemDefaultLCID(void) +{ + return MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), + SORT_DEFAULT); +} + +LCID STDCALL GetThreadLocale(void) +{ + return __TebLocale; +} + +WINBOOL STDCALL SetThreadLocale(LCID Locale) +{ + PLOCALE plocale; + + plocale=__Locale; + /* find locale */ + while((plocale->Id)&&(Locale!=plocale->Id)) + plocale++; + if(!plocale) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + __TebLocale=plocale; + return TRUE; +} + +WINBOOL +STDCALL +IsValidLocale( + LCID Locale, + DWORD dwFlags) +{ + PLOCALE plocale; + + plocale=__Locale; + + /* find locale */ + while((plocale->Id)&&(Locale!=plocale->Id)) + plocale++; + /* is it valid ?? */ + if(!plocale) + return FALSE; + else + return TRUE; +} + +LPSTR static __xtoa(LPSTR str, DWORD val) +{ + LPSTR retstr=str; + DWORD hex; + + do + { + hex=val%16; + if(hex<10) + *str=val + '0'; + else + *str=val + 'A'; + val=val/16; + str++; + } + while(val); + return retstr; +} + +LPWSTR static __xtow(LPWSTR str, DWORD val) +{ + LPWSTR retstr=str; + DWORD hex; + + do + { + hex=val%16; + if(hex<10) + *str=val + '0'; + else + *str=val + 'A'; + val=val/16; + str++; + } + while(val); + return retstr; +} + + +WINBOOL +STDCALL +EnumSystemLocalesA( + LOCALE_ENUMPROC lpLocaleEnumProc, + DWORD dwFlags) +{ + CHAR locstr[10]; + BOOL retval; + PLOCALE plocale; + + if(!lpLocaleEnumProc) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + plocale=__Locale; + retval=TRUE; + while((plocale->Id)&&(retval)) + { + __xtoa(locstr,plocale->Id); + retval=lpLocaleEnumProc((void *)locstr); + } + return TRUE; +} +WINBOOL +STDCALL +EnumSystemLocalesW( + LOCALE_ENUMPROC lpLocaleEnumProc, + DWORD dwFlags) +{ + WCHAR locstr[10]; + WINBOOL retval=TRUE; + PLOCALE plocale=__Locale; + + + if(!lpLocaleEnumProc) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + while((plocale->Id)&&(retval)) + { + __xtow(locstr,plocale->Id); + retval=lpLocaleEnumProc((void *)locstr); + } + return TRUE; +} + +int +STDCALL +GetLocaleInfoW( + LCID Locale, + LCTYPE LCType, + LPWSTR lpLCData, + int cchData) +{ + INT retcnt=0; + PLOCALE plocale=__Locale; + LPWSTR infostr; + + while(plocale->Id!=Locale) + plocale++; + + if(LCType<89) + infostr=plocale->Info0[LCType]; + else if((LCType>0x1000)&&(LCType<0x1011)) + infostr=plocale->Info1[LCType-0x1000]; + else + { SetLastError(ERROR_INVALID_PARAMETER); return 0; } + + if(cchData) + { + /* I really need a wide string copy, here */ + do + { + *lpLCData=*infostr; + infostr++; + lpLCData++; + cchData--; + retcnt++; + } + while((*infostr)&&(cchData)); + } + else + { + /* I really need a wide string length, here */ + do + { + infostr++; + retcnt++; + } + while(*infostr); + } + return retcnt; +} +int +STDCALL +GetLocaleInfoA( + LCID Locale, + LCTYPE LCType, + LPSTR lpLCData, + int cchData) +{ + INT retcnt=0; + PLOCALE plocale=__Locale; + LPWSTR infostr; + + while(plocale->Id!=Locale) + plocale++; + + if(LCType<89) + infostr=plocale->Info0[LCType]; + else if((LCType>0x1000)&&(LCType<0x1011)) + infostr=plocale->Info1[LCType-0x1000]; + else + { SetLastError(ERROR_INVALID_PARAMETER); return 0; } + + if(cchData) + { + /* I really need a wide string copy, here */ + do + { + *lpLCData=*infostr; + infostr++; + lpLCData++; + cchData--; + retcnt++; + } + while((*infostr)&&(cchData)); + } + else + { + /* I really need a wide string length, here */ + do + { + infostr++; + retcnt++; + } + while(*infostr); + } + return retcnt; +} + +const struct map_lcid2str { + LCID langid; + const char *langname; +} languages[]={ + {0x0401,"Arabic (Saudi Arabia)"}, + {0x0801,"Arabic (Iraq)"}, + {0x0c01,"Arabic (Egypt)"}, + {0x1001,"Arabic (Libya)"}, + {0x1401,"Arabic (Algeria)"}, + {0x1801,"Arabic (Morocco)"}, + {0x1c01,"Arabic (Tunisia)"}, + {0x2001,"Arabic (Oman)"}, + {0x2401,"Arabic (Yemen)"}, + {0x2801,"Arabic (Syria)"}, + {0x2c01,"Arabic (Jordan)"}, + {0x3001,"Arabic (Lebanon)"}, + {0x3401,"Arabic (Kuwait)"}, + {0x3801,"Arabic (United Arab Emirates)"}, + {0x3c01,"Arabic (Bahrain)"}, + {0x4001,"Arabic (Qatar)"}, + {0x0402,"Bulgarian"}, + {0x0403,"Catalan"}, + {0x0404,"Chinese (Taiwan)"}, + {0x0804,"Chinese (People's Republic of China)"}, + {0x0c04,"Chinese (Hong Kong)"}, + {0x1004,"Chinese (Singapore)"}, + {0x1404,"Chinese (Macau)"}, + {0x0405,"Czech"}, + {0x0406,"Danish"}, + {0x0407,"German (Germany)"}, + {0x0807,"German (Switzerland)"}, + {0x0c07,"German (Austria)"}, + {0x1007,"German (Luxembourg)"}, + {0x1407,"German (Liechtenstein)"}, + {0x0408,"Greek"}, + {0x0409,"English (United States)"}, + {0x0809,"English (United Kingdom)"}, + {0x0c09,"English (Australia)"}, + {0x1009,"English (Canada)"}, + {0x1409,"English (New Zealand)"}, + {0x1809,"English (Ireland)"}, + {0x1c09,"English (South Africa)"}, + {0x2009,"English (Jamaica)"}, + {0x2409,"English (Caribbean)"}, + {0x2809,"English (Belize)"}, + {0x2c09,"English (Trinidad)"}, + {0x3009,"English (Zimbabwe)"}, + {0x3409,"English (Philippines)"}, + {0x040a,"Spanish (Spain, traditional sorting)"}, + {0x080a,"Spanish (Mexico)"}, + {0x0c0a,"Spanish (Spain, international sorting)"}, + {0x100a,"Spanish (Guatemala)"}, + {0x140a,"Spanish (Costa Rica)"}, + {0x180a,"Spanish (Panama)"}, + {0x1c0a,"Spanish (Dominican Republic)"}, + {0x200a,"Spanish (Venezuela)"}, + {0x240a,"Spanish (Colombia)"}, + {0x280a,"Spanish (Peru)"}, + {0x2c0a,"Spanish (Argentina)"}, + {0x300a,"Spanish (Ecuador)"}, + {0x340a,"Spanish (Chile)"}, + {0x380a,"Spanish (Uruguay)"}, + {0x3c0a,"Spanish (Paraguay)"}, + {0x400a,"Spanish (Bolivia)"}, + {0x440a,"Spanish (El Salvador)"}, + {0x480a,"Spanish (Honduras)"}, + {0x4c0a,"Spanish (Nicaragua)"}, + {0x500a,"Spanish (Puerto Rico)"}, + {0x040b,"Finnish"}, + {0x040c,"French (France)"}, + {0x080c,"French (Belgium)"}, + {0x0c0c,"French (Canada)"}, + {0x100c,"French (Switzerland)"}, + {0x140c,"French (Luxembourg)"}, + {0x180c,"French (Monaco)"}, + {0x040d,"Hebrew"}, + {0x040e,"Hungarian"}, + {0x040f,"Icelandic"}, + {0x0410,"Italian (Italy)"}, + {0x0810,"Italian (Switzerland)"}, + {0x0411,"Japanese"}, + {0x0412,"Korean (Wansung)"}, + {0x0812,"Korean (Johab)"}, + {0x0413,"Dutch (Netherlands)"}, + {0x0813,"Dutch (Belgium)"}, + {0x0414,"Norwegian (Bokmal)"}, + {0x0814,"Norwegian (Nynorsk)"}, + {0x0415,"Polish"}, + {0x0416,"Portuguese (Brazil)"}, + {0x0816,"Portuguese (Portugal)"}, + {0x0417,"Rhaeto Romanic"}, + {0x0418,"Romanian"}, + {0x0818,"Moldavian"}, + {0x0419,"Russian (Russia)"}, + {0x0819,"Russian (Moldavia)"}, + {0x041a,"Croatian"}, + {0x081a,"Serbian (latin)"}, + {0x0c1a,"Serbian (cyrillic)"}, + {0x041b,"Slovak"}, + {0x041c,"Albanian"}, + {0x041d,"Swedish (Sweden)"}, + {0x081d,"Swedish (Finland)"}, + {0x041e,"Thai"}, + {0x041f,"Turkish"}, + {0x0420,"Urdu"}, + {0x0421,"Indonesian"}, + {0x0422,"Ukrainian"}, + {0x0423,"Belarusian"}, + {0x0424,"Slovene"}, + {0x0425,"Estonian"}, + {0x0426,"Latvian"}, + {0x0427,"Lithuanian (modern)"}, + {0x0827,"Lithuanian (classic)"}, + {0x0428,"Maori"}, + {0x0429,"Farsi"}, + {0x042a,"Vietnamese"}, + {0x042b,"Armenian"}, + {0x042c,"Azeri (latin)"}, + {0x082c,"Azeri (cyrillic)"}, + {0x042d,"Basque"}, + {0x042e,"Sorbian"}, + {0x042f,"Macedonian"}, + {0x0430,"Sutu"}, + {0x0431,"Tsonga"}, + {0x0432,"Tswana"}, + {0x0433,"Venda"}, + {0x0434,"Xhosa"}, + {0x0435,"Zulu"}, + {0x0436,"Afrikaans"}, + {0x0437,"Georgian"}, + {0x0438,"Faeroese"}, + {0x0439,"Hindi"}, + {0x043a,"Maltese"}, + {0x043b,"Saami"}, + {0x043c,"Irish gaelic"}, + {0x083c,"Scottish gaelic"}, + {0x043e,"Malay (Malaysia)"}, + {0x083e,"Malay (Brunei Darussalam)"}, + {0x043f,"Kazak"}, + {0x0441,"Swahili"}, + {0x0443,"Uzbek (latin)"}, + {0x0843,"Uzbek (cyrillic)"}, + {0x0444,"Tatar"}, + {0x0445,"Bengali"}, + {0x0446,"Punjabi"}, + {0x0447,"Gujarati"}, + {0x0448,"Oriya"}, + {0x0449,"Tamil"}, + {0x044a,"Telugu"}, + {0x044b,"Kannada"}, + {0x044c,"Malayalam"}, + {0x044d,"Assamese"}, + {0x044e,"Marathi"}, + {0x044f,"Sanskrit"}, + {0x0457,"Konkani"}, + {0x048f,"Esperanto"}, /* Non official */ + {0x0000,"Unknown"} + +}; + + +static const unsigned char CT_CType2_LUT[] = { + C2_NOTAPPLICABLE, /* - 0 */ + C2_NOTAPPLICABLE, /* - 1 */ + C2_NOTAPPLICABLE, /* - 2 */ + C2_NOTAPPLICABLE, /* - 3 */ + C2_NOTAPPLICABLE, /* - 4 */ + C2_NOTAPPLICABLE, /* - 5 */ + C2_NOTAPPLICABLE, /* - 6 */ + C2_NOTAPPLICABLE, /* - 7 */ + C2_NOTAPPLICABLE, /* - 8 */ + C2_SEGMENTSEPARATOR, /* - 9 */ + C2_NOTAPPLICABLE, /* - 10 */ + C2_NOTAPPLICABLE, /* - 11 */ + C2_NOTAPPLICABLE, /* - 12 */ + C2_NOTAPPLICABLE, /* - 13 */ + C2_NOTAPPLICABLE, /* - 14 */ + C2_NOTAPPLICABLE, /* - 15 */ + C2_NOTAPPLICABLE, /* - 16 */ + C2_NOTAPPLICABLE, /* - 17 */ + C2_NOTAPPLICABLE, /* - 18 */ + C2_NOTAPPLICABLE, /* - 19 */ + C2_NOTAPPLICABLE, /* - 20 */ + C2_NOTAPPLICABLE, /* - 21 */ + C2_NOTAPPLICABLE, /* - 22 */ + C2_NOTAPPLICABLE, /* - 23 */ + C2_NOTAPPLICABLE, /* - 24 */ + C2_NOTAPPLICABLE, /* - 25 */ + C2_NOTAPPLICABLE, /* - 26 */ + C2_NOTAPPLICABLE, /* - 27 */ + C2_NOTAPPLICABLE, /* - 28 */ + C2_NOTAPPLICABLE, /* - 29 */ + C2_NOTAPPLICABLE, /* - 30 */ + C2_NOTAPPLICABLE, /* - 31 */ + C2_WHITESPACE, /* - 32 */ + C2_OTHERNEUTRAL, /* ! - 33 */ + C2_OTHERNEUTRAL, /* " - 34 */ /* " */ + C2_EUROPETERMINATOR, /* # - 35 */ + C2_EUROPETERMINATOR, /* $ - 36 */ + C2_EUROPETERMINATOR, /* % - 37 */ + C2_LEFTTORIGHT, /* & - 38 */ + C2_OTHERNEUTRAL, /* ' - 39 */ + C2_OTHERNEUTRAL, /* ( - 40 */ + C2_OTHERNEUTRAL, /* ) - 41 */ + C2_OTHERNEUTRAL, /* * - 42 */ + C2_EUROPETERMINATOR, /* + - 43 */ + C2_COMMONSEPARATOR, /* , - 44 */ + C2_EUROPETERMINATOR, /* - - 45 */ + C2_EUROPESEPARATOR, /* . - 46 */ + C2_EUROPESEPARATOR, /* / - 47 */ + C2_EUROPENUMBER, /* 0 - 48 */ + C2_EUROPENUMBER, /* 1 - 49 */ + C2_EUROPENUMBER, /* 2 - 50 */ + C2_EUROPENUMBER, /* 3 - 51 */ + C2_EUROPENUMBER, /* 4 - 52 */ + C2_EUROPENUMBER, /* 5 - 53 */ + C2_EUROPENUMBER, /* 6 - 54 */ + C2_EUROPENUMBER, /* 7 - 55 */ + C2_EUROPENUMBER, /* 8 - 56 */ + C2_EUROPENUMBER, /* 9 - 57 */ + C2_COMMONSEPARATOR, /* : - 58 */ + C2_OTHERNEUTRAL, /* ; - 59 */ + C2_OTHERNEUTRAL, /* < - 60 */ + C2_OTHERNEUTRAL, /* = - 61 */ + C2_OTHERNEUTRAL, /* > - 62 */ + C2_OTHERNEUTRAL, /* ? - 63 */ + C2_LEFTTORIGHT, /* @ - 64 */ + C2_LEFTTORIGHT, /* A - 65 */ + C2_LEFTTORIGHT, /* B - 66 */ + C2_LEFTTORIGHT, /* C - 67 */ + C2_LEFTTORIGHT, /* D - 68 */ + C2_LEFTTORIGHT, /* E - 69 */ + C2_LEFTTORIGHT, /* F - 70 */ + C2_LEFTTORIGHT, /* G - 71 */ + C2_LEFTTORIGHT, /* H - 72 */ + C2_LEFTTORIGHT, /* I - 73 */ + C2_LEFTTORIGHT, /* J - 74 */ + C2_LEFTTORIGHT, /* K - 75 */ + C2_LEFTTORIGHT, /* L - 76 */ + C2_LEFTTORIGHT, /* M - 77 */ + C2_LEFTTORIGHT, /* N - 78 */ + C2_LEFTTORIGHT, /* O - 79 */ + C2_LEFTTORIGHT, /* P - 80 */ + C2_LEFTTORIGHT, /* Q - 81 */ + C2_LEFTTORIGHT, /* R - 82 */ + C2_LEFTTORIGHT, /* S - 83 */ + C2_LEFTTORIGHT, /* T - 84 */ + C2_LEFTTORIGHT, /* U - 85 */ + C2_LEFTTORIGHT, /* V - 86 */ + C2_LEFTTORIGHT, /* W - 87 */ + C2_LEFTTORIGHT, /* X - 88 */ + C2_LEFTTORIGHT, /* Y - 89 */ + C2_LEFTTORIGHT, /* Z - 90 */ + C2_OTHERNEUTRAL, /* [ - 91 */ + C2_OTHERNEUTRAL, /* \ - 92 */ + C2_OTHERNEUTRAL, /* ] - 93 */ + C2_OTHERNEUTRAL, /* ^ - 94 */ + C2_OTHERNEUTRAL, /* _ - 95 */ + C2_OTHERNEUTRAL, /* ` - 96 */ + C2_LEFTTORIGHT, /* a - 97 */ + C2_LEFTTORIGHT, /* b - 98 */ + C2_LEFTTORIGHT, /* c - 99 */ + C2_LEFTTORIGHT, /* d - 100 */ + C2_LEFTTORIGHT, /* e - 101 */ + C2_LEFTTORIGHT, /* f - 102 */ + C2_LEFTTORIGHT, /* g - 103 */ + C2_LEFTTORIGHT, /* h - 104 */ + C2_LEFTTORIGHT, /* i - 105 */ + C2_LEFTTORIGHT, /* j - 106 */ + C2_LEFTTORIGHT, /* k - 107 */ + C2_LEFTTORIGHT, /* l - 108 */ + C2_LEFTTORIGHT, /* m - 109 */ + C2_LEFTTORIGHT, /* n - 110 */ + C2_LEFTTORIGHT, /* o - 111 */ + C2_LEFTTORIGHT, /* p - 112 */ + C2_LEFTTORIGHT, /* q - 113 */ + C2_LEFTTORIGHT, /* r - 114 */ + C2_LEFTTORIGHT, /* s - 115 */ + C2_LEFTTORIGHT, /* t - 116 */ + C2_LEFTTORIGHT, /* u - 117 */ + C2_LEFTTORIGHT, /* v - 118 */ + C2_LEFTTORIGHT, /* w - 119 */ + C2_LEFTTORIGHT, /* x - 120 */ + C2_LEFTTORIGHT, /* y - 121 */ + C2_LEFTTORIGHT, /* z - 122 */ + C2_OTHERNEUTRAL, /* { - 123 */ + C2_OTHERNEUTRAL, /* | - 124 */ + C2_OTHERNEUTRAL, /* } - 125 */ + C2_OTHERNEUTRAL, /* ~ - 126 */ + C2_NOTAPPLICABLE, /*  - 127 */ + C2_NOTAPPLICABLE, /* € - 128 */ + C2_NOTAPPLICABLE, /*  - 129 */ + C2_OTHERNEUTRAL, /* ‚ - 130 */ + C2_LEFTTORIGHT, /* ƒ - 131 */ + C2_OTHERNEUTRAL, /* „ - 132 */ + C2_OTHERNEUTRAL, /* … - 133 */ + C2_OTHERNEUTRAL, /* † - 134 */ + C2_OTHERNEUTRAL, /* ‡ - 135 */ + C2_LEFTTORIGHT, /* ˆ - 136 */ + C2_EUROPETERMINATOR, /* ‰ - 137 */ + C2_LEFTTORIGHT, /* Š - 138 */ + C2_OTHERNEUTRAL, /* ‹ - 139 */ + C2_LEFTTORIGHT, /* Œ - 140 */ + C2_NOTAPPLICABLE, /*  - 141 */ + C2_NOTAPPLICABLE, /* Ž - 142 */ + C2_NOTAPPLICABLE, /*  - 143 */ + C2_NOTAPPLICABLE, /*  - 144 */ + C2_OTHERNEUTRAL, /* ‘ - 145 */ + C2_OTHERNEUTRAL, /* ’ - 146 */ + C2_OTHERNEUTRAL, /* “ - 147 */ + C2_OTHERNEUTRAL, /* ” - 148 */ + C2_OTHERNEUTRAL, /* • - 149 */ + C2_OTHERNEUTRAL, /* – - 150 */ + C2_OTHERNEUTRAL, /* — - 151 */ + C2_LEFTTORIGHT, /* ˜ - 152 */ + C2_OTHERNEUTRAL, /* ™ - 153 */ + C2_LEFTTORIGHT, /* š - 154 */ + C2_OTHERNEUTRAL, /* › - 155 */ + C2_LEFTTORIGHT, /* œ - 156 */ + C2_NOTAPPLICABLE, /*  - 157 */ + C2_NOTAPPLICABLE, /* ž - 158 */ + C2_LEFTTORIGHT, /* Ÿ - 159 */ + C2_WHITESPACE, /*   - 160 */ + C2_OTHERNEUTRAL, /* ¡ - 161 */ + C2_EUROPETERMINATOR, /* ¢ - 162 */ + C2_EUROPETERMINATOR, /* £ - 163 */ + C2_EUROPETERMINATOR, /* ¤ - 164 */ + C2_EUROPETERMINATOR, /* ¥ - 165 */ + C2_OTHERNEUTRAL, /* ¦ - 166 */ + C2_OTHERNEUTRAL, /* § - 167 */ + C2_OTHERNEUTRAL, /* ¨ - 168 */ + C2_OTHERNEUTRAL, /* © - 169 */ + C2_OTHERNEUTRAL, /* ª - 170 */ + C2_OTHERNEUTRAL, /* « - 171 */ + C2_OTHERNEUTRAL, /* ¬ - 172 */ + C2_OTHERNEUTRAL, /* ­ - 173 */ + C2_OTHERNEUTRAL, /* ® - 174 */ + C2_OTHERNEUTRAL, /* ¯ - 175 */ + C2_EUROPETERMINATOR, /* ° - 176 */ + C2_EUROPETERMINATOR, /* ± - 177 */ + C2_EUROPENUMBER, /* ² - 178 */ + C2_EUROPENUMBER, /* ³ - 179 */ + C2_OTHERNEUTRAL, /* ´ - 180 */ + C2_OTHERNEUTRAL, /* µ - 181 */ + C2_OTHERNEUTRAL, /* ¶ - 182 */ + C2_OTHERNEUTRAL, /* · - 183 */ + C2_OTHERNEUTRAL, /* ¸ - 184 */ + C2_EUROPENUMBER, /* ¹ - 185 */ + C2_OTHERNEUTRAL, /* º - 186 */ + C2_OTHERNEUTRAL, /* » - 187 */ + C2_OTHERNEUTRAL, /* ¼ - 188 */ + C2_OTHERNEUTRAL, /* ½ - 189 */ + C2_OTHERNEUTRAL, /* ¾ - 190 */ + C2_OTHERNEUTRAL, /* ¿ - 191 */ + C2_LEFTTORIGHT, /* À - 192 */ + C2_LEFTTORIGHT, /* Á - 193 */ + C2_LEFTTORIGHT, /*  - 194 */ + C2_LEFTTORIGHT, /* à - 195 */ + C2_LEFTTORIGHT, /* Ä - 196 */ + C2_LEFTTORIGHT, /* Å - 197 */ + C2_LEFTTORIGHT, /* Æ - 198 */ + C2_LEFTTORIGHT, /* Ç - 199 */ + C2_LEFTTORIGHT, /* È - 200 */ + C2_LEFTTORIGHT, /* É - 201 */ + C2_LEFTTORIGHT, /* Ê - 202 */ + C2_LEFTTORIGHT, /* Ë - 203 */ + C2_LEFTTORIGHT, /* Ì - 204 */ + C2_LEFTTORIGHT, /* Í - 205 */ + C2_LEFTTORIGHT, /* Î - 206 */ + C2_LEFTTORIGHT, /* Ï - 207 */ + C2_LEFTTORIGHT, /* Ð - 208 */ + C2_LEFTTORIGHT, /* Ñ - 209 */ + C2_LEFTTORIGHT, /* Ò - 210 */ + C2_LEFTTORIGHT, /* Ó - 211 */ + C2_LEFTTORIGHT, /* Ô - 212 */ + C2_LEFTTORIGHT, /* Õ - 213 */ + C2_LEFTTORIGHT, /* Ö - 214 */ + C2_OTHERNEUTRAL, /* × - 215 */ + C2_LEFTTORIGHT, /* Ø - 216 */ + C2_LEFTTORIGHT, /* Ù - 217 */ + C2_LEFTTORIGHT, /* Ú - 218 */ + C2_LEFTTORIGHT, /* Û - 219 */ + C2_LEFTTORIGHT, /* Ü - 220 */ + C2_LEFTTORIGHT, /* Ý - 221 */ + C2_LEFTTORIGHT, /* Þ - 222 */ + C2_LEFTTORIGHT, /* ß - 223 */ + C2_LEFTTORIGHT, /* à - 224 */ + C2_LEFTTORIGHT, /* á - 225 */ + C2_LEFTTORIGHT, /* â - 226 */ + C2_LEFTTORIGHT, /* ã - 227 */ + C2_LEFTTORIGHT, /* ä - 228 */ + C2_LEFTTORIGHT, /* å - 229 */ + C2_LEFTTORIGHT, /* æ - 230 */ + C2_LEFTTORIGHT, /* ç - 231 */ + C2_LEFTTORIGHT, /* è - 232 */ + C2_LEFTTORIGHT, /* é - 233 */ + C2_LEFTTORIGHT, /* ê - 234 */ + C2_LEFTTORIGHT, /* ë - 235 */ + C2_LEFTTORIGHT, /* ì - 236 */ + C2_LEFTTORIGHT, /* í - 237 */ + C2_LEFTTORIGHT, /* î - 238 */ + C2_LEFTTORIGHT, /* ï - 239 */ + C2_LEFTTORIGHT, /* ð - 240 */ + C2_LEFTTORIGHT, /* ñ - 241 */ + C2_LEFTTORIGHT, /* ò - 242 */ + C2_LEFTTORIGHT, /* ó - 243 */ + C2_LEFTTORIGHT, /* ô - 244 */ + C2_LEFTTORIGHT, /* õ - 245 */ + C2_LEFTTORIGHT, /* ö - 246 */ + C2_OTHERNEUTRAL, /* ÷ - 247 */ + C2_LEFTTORIGHT, /* ø - 248 */ + C2_LEFTTORIGHT, /* ù - 249 */ + C2_LEFTTORIGHT, /* ú - 250 */ + C2_LEFTTORIGHT, /* û - 251 */ + C2_LEFTTORIGHT, /* ü - 252 */ + C2_LEFTTORIGHT, /* ý - 253 */ + C2_LEFTTORIGHT, /* þ - 254 */ + C2_LEFTTORIGHT /* ÿ - 255 */ +}; + +static const WORD CT_CType3_LUT[] = { + 0x0000, /* - 0 */ + 0x0000, /* - 1 */ + 0x0000, /* - 2 */ + 0x0000, /* - 3 */ + 0x0000, /* - 4 */ + 0x0000, /* - 5 */ + 0x0000, /* - 6 */ + 0x0000, /* - 7 */ + 0x0000, /* - 8 */ + 0x0008, /* - 9 */ + 0x0008, /* - 10 */ + 0x0008, /* - 11 */ + 0x0008, /* - 12 */ + 0x0008, /* - 13 */ + 0x0000, /* - 14 */ + 0x0000, /* - 15 */ + 0x0000, /* - 16 */ + 0x0000, /* - 17 */ + 0x0000, /* - 18 */ + 0x0000, /* - 19 */ + 0x0000, /* - 20 */ + 0x0000, /* - 21 */ + 0x0000, /* - 22 */ + 0x0000, /* - 23 */ + 0x0000, /* - 24 */ + 0x0000, /* - 25 */ + 0x0000, /* - 26 */ + 0x0000, /* - 27 */ + 0x0000, /* - 28 */ + 0x0000, /* - 29 */ + 0x0000, /* - 30 */ + 0x0000, /* - 31 */ + 0x0048, /* - 32 */ + 0x0048, /* ! - 33 */ + 0x0448, /* " - 34 */ /* " */ + 0x0048, /* # - 35 */ + 0x0448, /* $ - 36 */ + 0x0048, /* % - 37 */ + 0x0048, /* & - 38 */ + 0x0440, /* ' - 39 */ + 0x0048, /* ( - 40 */ + 0x0048, /* ) - 41 */ + 0x0048, /* * - 42 */ + 0x0048, /* + - 43 */ + 0x0048, /* , - 44 */ + 0x0440, /* - - 45 */ + 0x0048, /* . - 46 */ + 0x0448, /* / - 47 */ + 0x0040, /* 0 - 48 */ + 0x0040, /* 1 - 49 */ + 0x0040, /* 2 - 50 */ + 0x0040, /* 3 - 51 */ + 0x0040, /* 4 - 52 */ + 0x0040, /* 5 - 53 */ + 0x0040, /* 6 - 54 */ + 0x0040, /* 7 - 55 */ + 0x0040, /* 8 - 56 */ + 0x0040, /* 9 - 57 */ + 0x0048, /* : - 58 */ + 0x0048, /* ; - 59 */ + 0x0048, /* < - 60 */ + 0x0448, /* = - 61 */ + 0x0048, /* > - 62 */ + 0x0048, /* ? - 63 */ + 0x0448, /* @ - 64 */ + 0x8040, /* A - 65 */ + 0x8040, /* B - 66 */ + 0x8040, /* C - 67 */ + 0x8040, /* D - 68 */ + 0x8040, /* E - 69 */ + 0x8040, /* F - 70 */ + 0x8040, /* G - 71 */ + 0x8040, /* H - 72 */ + 0x8040, /* I - 73 */ + 0x8040, /* J - 74 */ + 0x8040, /* K - 75 */ + 0x8040, /* L - 76 */ + 0x8040, /* M - 77 */ + 0x8040, /* N - 78 */ + 0x8040, /* O - 79 */ + 0x8040, /* P - 80 */ + 0x8040, /* Q - 81 */ + 0x8040, /* R - 82 */ + 0x8040, /* S - 83 */ + 0x8040, /* T - 84 */ + 0x8040, /* U - 85 */ + 0x8040, /* V - 86 */ + 0x8040, /* W - 87 */ + 0x8040, /* X - 88 */ + 0x8040, /* Y - 89 */ + 0x8040, /* Z - 90 */ + 0x0048, /* [ - 91 */ + 0x0448, /* \ - 92 */ + 0x0048, /* ] - 93 */ + 0x0448, /* ^ - 94 */ + 0x0448, /* _ - 95 */ + 0x0448, /* ` - 96 */ + 0x8040, /* a - 97 */ + 0x8040, /* b - 98 */ + 0x8040, /* c - 99 */ + 0x8040, /* d - 100 */ + 0x8040, /* e - 101 */ + 0x8040, /* f - 102 */ + 0x8040, /* g - 103 */ + 0x8040, /* h - 104 */ + 0x8040, /* i - 105 */ + 0x8040, /* j - 106 */ + 0x8040, /* k - 107 */ + 0x8040, /* l - 108 */ + 0x8040, /* m - 109 */ + 0x8040, /* n - 110 */ + 0x8040, /* o - 111 */ + 0x8040, /* p - 112 */ + 0x8040, /* q - 113 */ + 0x8040, /* r - 114 */ + 0x8040, /* s - 115 */ + 0x8040, /* t - 116 */ + 0x8040, /* u - 117 */ + 0x8040, /* v - 118 */ + 0x8040, /* w - 119 */ + 0x8040, /* x - 120 */ + 0x8040, /* y - 121 */ + 0x8040, /* z - 122 */ + 0x0048, /* { - 123 */ + 0x0048, /* | - 124 */ + 0x0048, /* } - 125 */ + 0x0448, /* ~ - 126 */ + 0x0000, /*  - 127 */ + 0x0000, /* € - 128 */ + 0x0000, /*  - 129 */ + 0x0008, /* ‚ - 130 */ + 0x8000, /* ƒ - 131 */ + 0x0008, /* „ - 132 */ + 0x0008, /* … - 133 */ + 0x0008, /* † - 134 */ + 0x0008, /* ‡ - 135 */ + 0x0001, /* ˆ - 136 */ + 0x0008, /* ‰ - 137 */ + 0x8003, /* Š - 138 */ + 0x0008, /* ‹ - 139 */ + 0x8000, /* Œ - 140 */ + 0x0000, /*  - 141 */ + 0x0000, /* Ž - 142 */ + 0x0000, /*  - 143 */ + 0x0000, /*  - 144 */ + 0x0088, /* ‘ - 145 */ + 0x0088, /* ’ - 146 */ + 0x0088, /* “ - 147 */ + 0x0088, /* ” - 148 */ + 0x0008, /* • - 149 */ + 0x0400, /* – - 150 */ + 0x0400, /* — - 151 */ + 0x0408, /* ˜ - 152 */ + 0x0000, /* ™ - 153 */ + 0x8003, /* š - 154 */ + 0x0008, /* › - 155 */ + 0x8000, /* œ - 156 */ + 0x0000, /*  - 157 */ + 0x0000, /* ž - 158 */ + 0x8003, /* Ÿ - 159 */ + 0x0008, /*   - 160 */ + 0x0008, /* ¡ - 161 */ + 0x0048, /* ¢ - 162 */ + 0x0048, /* £ - 163 */ + 0x0008, /* ¤ - 164 */ + 0x0048, /* ¥ - 165 */ + 0x0048, /* ¦ - 166 */ + 0x0008, /* § - 167 */ + 0x0408, /* ¨ - 168 */ + 0x0008, /* © - 169 */ + 0x0400, /* ª - 170 */ + 0x0008, /* « - 171 */ + 0x0048, /* ¬ - 172 */ + 0x0408, /* ­ - 173 */ + 0x0008, /* ® - 174 */ + 0x0448, /* ¯ - 175 */ + 0x0008, /* ° - 176 */ + 0x0008, /* ± - 177 */ + 0x0000, /* ² - 178 */ + 0x0000, /* ³ - 179 */ + 0x0408, /* ´ - 180 */ + 0x0008, /* µ - 181 */ + 0x0008, /* ¶ - 182 */ + 0x0008, /* · - 183 */ + 0x0408, /* ¸ - 184 */ + 0x0000, /* ¹ - 185 */ + 0x0400, /* º - 186 */ + 0x0008, /* » - 187 */ + 0x0000, /* ¼ - 188 */ + 0x0000, /* ½ - 189 */ + 0x0000, /* ¾ - 190 */ + 0x0008, /* ¿ - 191 */ + 0x8003, /* À - 192 */ + 0x8003, /* Á - 193 */ + 0x8003, /*  - 194 */ + 0x8003, /* à - 195 */ + 0x8003, /* Ä - 196 */ + 0x8003, /* Å - 197 */ + 0x8000, /* Æ - 198 */ + 0x8003, /* Ç - 199 */ + 0x8003, /* È - 200 */ + 0x8003, /* É - 201 */ + 0x8003, /* Ê - 202 */ + 0x8003, /* Ë - 203 */ + 0x8003, /* Ì - 204 */ + 0x8003, /* Í - 205 */ + 0x8003, /* Î - 206 */ + 0x8003, /* Ï - 207 */ + 0x8000, /* Ð - 208 */ + 0x8003, /* Ñ - 209 */ + 0x8003, /* Ò - 210 */ + 0x8003, /* Ó - 211 */ + 0x8003, /* Ô - 212 */ + 0x8003, /* Õ - 213 */ + 0x8003, /* Ö - 214 */ + 0x0008, /* × - 215 */ + 0x8003, /* Ø - 216 */ + 0x8003, /* Ù - 217 */ + 0x8003, /* Ú - 218 */ + 0x8003, /* Û - 219 */ + 0x8003, /* Ü - 220 */ + 0x8003, /* Ý - 221 */ + 0x8000, /* Þ - 222 */ + 0x8000, /* ß - 223 */ + 0x8003, /* à - 224 */ + 0x8003, /* á - 225 */ + 0x8003, /* â - 226 */ + 0x8003, /* ã - 227 */ + 0x8003, /* ä - 228 */ + 0x8003, /* å - 229 */ + 0x8000, /* æ - 230 */ + 0x8003, /* ç - 231 */ + 0x8003, /* è - 232 */ + 0x8003, /* é - 233 */ + 0x8003, /* ê - 234 */ + 0x8003, /* ë - 235 */ + 0x8003, /* ì - 236 */ + 0x8003, /* í - 237 */ + 0x8003, /* î - 238 */ + 0x8003, /* ï - 239 */ + 0x8000, /* ð - 240 */ + 0x8003, /* ñ - 241 */ + 0x8003, /* ò - 242 */ + 0x8003, /* ó - 243 */ + 0x8003, /* ô - 244 */ + 0x8003, /* õ - 245 */ + 0x8003, /* ö - 246 */ + 0x0008, /* ÷ - 247 */ + 0x8003, /* ø - 248 */ + 0x8003, /* ù - 249 */ + 0x8003, /* ú - 250 */ + 0x8003, /* û - 251 */ + 0x8003, /* ü - 252 */ + 0x8003, /* ý - 253 */ + 0x8000, /* þ - 254 */ + 0x8003 /* ÿ - 255 */ +}; + + + +WINBOOL +STDCALL +GetStringTypeExA( + LCID Locale, + DWORD dwInfoType, + LPCSTR lpSrcStr, + int cchSrc, + LPWORD lpCharType) +{ + int i; + + if ((lpSrcStr==NULL) || (lpCharType==NULL) || (lpSrcStr==(LPCSTR)lpCharType)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (cchSrc==-1) + cchSrc=lstrlenA(lpSrcStr)+1; + + switch (dwInfoType) { + case CT_CTYPE1: + for (i=0;i +#include +#include +#include +#include + +#define NDEBUG +#include + +extern PLOCALE __TebLocale; + +#define GetTebLocale() __TebLocale + +INT MultiByteToWideChar(UINT cpid, DWORD flags, LPCSTR src, int srclen, + LPWSTR dest, int destlen) +{ + PCODEPAGE pcodepage =__CPFirst; + INT copylen; + INT retlen; + WCHAR **atou; + CHAR c; + + DPRINT("MultiByteToWideChar( %u, 0x%lX, %s, %d, 0x%lX, %d )\n", + cpid, flags, src, srclen, (ULONG) dest, destlen); + + /* get codepage */ + switch(cpid) + { + case CP_ACP: pcodepage= GetTebLocale()->OemCodePage; break; + case CP_OEMCP: pcodepage= GetTebLocale()->AnsiCodePage; break; + case CP_MACCP: pcodepage=&__CP10000; break; + default: + pcodepage=__CPFirst; + while((pcodepage)&&(pcodepage->Id!=cpid)) + pcodepage=pcodepage->Next; + } + if(pcodepage==NULL) + { SetLastError(ERROR_INVALID_PARAMETER); return 0; } + + /* get conversion table */ + atou=pcodepage->ToUnicode; + + if(destlen!=0) + { + /* how long are we ?? */ + if(srclen==0) + srclen=strlen(src); + + copylen=min(srclen,destlen); + retlen=copylen; + + /* XXX: maybe some inline assembly to speed things up, here ??? */ + while(copylen>0) + { + c=*src; + *dest=atou [c>>5] [(c)&0x1F]; + src++; + dest++; + copylen--; + } + } + else + { + /* XXXX: composites etc. */ + retlen = strlen(src); + } + return retlen; +} \ No newline at end of file diff --git a/lib/kernel32/nls/nlb.nls b/lib/kernel32/nls/nlb.nls new file mode 100644 index 0000000..e60c642 --- /dev/null +++ b/lib/kernel32/nls/nlb.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Dutch (Belgium) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0813") +LOCVAL(LOCALE_SLANGUAGE,"Nederlands (België)") +LOCVAL(LOCALE_SENGLANGUAGE,"Dutch (Belgium)") +LOCVAL(LOCALE_SABBREVLANGNAME,"nlb") +LOCVAL(LOCALE_SNATIVELANGNAME,"Nederlands") +LOCVAL(LOCALE_ICOUNTRY,"32") +LOCVAL(LOCALE_SCOUNTRY,"België") +LOCVAL(LOCALE_SENGCOUNTRY,"Belgium") +LOCVAL(LOCALE_SABBREVCTRYNAME,"BEL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"België") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0413") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"32") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"BF") +LOCVAL(LOCALE_SINTLSYMBOL,"BEF") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"maandag") +LOCVAL(LOCALE_SDAYNAME2,"dinsdag") +LOCVAL(LOCALE_SDAYNAME3,"woensdag") +LOCVAL(LOCALE_SDAYNAME4,"donderdag") +LOCVAL(LOCALE_SDAYNAME5,"vrijdag") +LOCVAL(LOCALE_SDAYNAME6,"zaterdag") +LOCVAL(LOCALE_SDAYNAME7,"zondag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"ma") +LOCVAL(LOCALE_SABBREVDAYNAME2,"di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"wo") +LOCVAL(LOCALE_SABBREVDAYNAME4,"do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"za") +LOCVAL(LOCALE_SABBREVDAYNAME7,"zo") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februari") +LOCVAL(LOCALE_SMONTHNAME3,"maart") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"mei") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"augustus") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"december") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mrt") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mei") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"nl") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BE") + +/* Gregorianse kalender */ diff --git a/lib/kernel32/nls/nld.nls b/lib/kernel32/nls/nld.nls new file mode 100644 index 0000000..1fe18ac --- /dev/null +++ b/lib/kernel32/nls/nld.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Dutch (Netherlands) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0413") +LOCVAL(LOCALE_SLANGUAGE,"Nederlands") +LOCVAL(LOCALE_SENGLANGUAGE,"Dutch") +LOCVAL(LOCALE_SABBREVLANGNAME,"nld") +LOCVAL(LOCALE_SNATIVELANGNAME,"Nederlands") +LOCVAL(LOCALE_ICOUNTRY,"31") +LOCVAL(LOCALE_SCOUNTRY,"Nederland") +LOCVAL(LOCALE_SENGCOUNTRY,"Netherlands") +LOCVAL(LOCALE_SABBREVCTRYNAME,"NLD") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Nederland") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0413") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"31") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"F") +LOCVAL(LOCALE_SINTLSYMBOL,"NLG") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"maandag") +LOCVAL(LOCALE_SDAYNAME2,"dinsdag") +LOCVAL(LOCALE_SDAYNAME3,"woensdag") +LOCVAL(LOCALE_SDAYNAME4,"donderdag") +LOCVAL(LOCALE_SDAYNAME5,"vrijdag") +LOCVAL(LOCALE_SDAYNAME6,"zaterdag") +LOCVAL(LOCALE_SDAYNAME7,"zondag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"ma") +LOCVAL(LOCALE_SABBREVDAYNAME2,"di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"wo") +LOCVAL(LOCALE_SABBREVDAYNAME4,"do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"za") +LOCVAL(LOCALE_SABBREVDAYNAME7,"zo") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februari") +LOCVAL(LOCALE_SMONTHNAME3,"maart") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"mei") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"augustus") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"december") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mrt") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mei") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"nl") +LOCVAL(LOCALE_SISO3166CTRYNAME,"NL") + +/* Gregorianse kalender */ diff --git a/lib/kernel32/nls/nls.nls b/lib/kernel32/nls/nls.nls new file mode 100644 index 0000000..648a25a --- /dev/null +++ b/lib/kernel32/nls/nls.nls @@ -0,0 +1,119 @@ +/* + * OLE2NLS library + * Dutch (Surinam ?) + * + * The code for Dutch/Surinam doesn't appear on my docs; + * It should be something + 0x13 as 0x13 is the Dutch language; + * Following the same logic as other multi-coutries languages + * I picked 0x0c13 for Surinam/Dutch. + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c13") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Dutch (Suriname)") +LOCVAL(LOCALE_SABBREVLANGNAME,"nls") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Suriname") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SUR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0413") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"SRG") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"maandag") +LOCVAL(LOCALE_SDAYNAME2,"dinsdag") +LOCVAL(LOCALE_SDAYNAME3,"woensdag") +LOCVAL(LOCALE_SDAYNAME4,"donderdag") +LOCVAL(LOCALE_SDAYNAME5,"vrijdag") +LOCVAL(LOCALE_SDAYNAME6,"zaterdag") +LOCVAL(LOCALE_SDAYNAME7,"zondag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"ma") +LOCVAL(LOCALE_SABBREVDAYNAME2,"di") +LOCVAL(LOCALE_SABBREVDAYNAME3,"wo") +LOCVAL(LOCALE_SABBREVDAYNAME4,"do") +LOCVAL(LOCALE_SABBREVDAYNAME5,"vr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"za") +LOCVAL(LOCALE_SABBREVDAYNAME7,"zo") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februari") +LOCVAL(LOCALE_SMONTHNAME3,"maart") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"mei") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"augustus") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"december") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mrt") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mei") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"nl") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SR") + +/* Gregorianse kalender */ diff --git a/lib/kernel32/nls/non.nls b/lib/kernel32/nls/non.nls new file mode 100644 index 0000000..9b95335 --- /dev/null +++ b/lib/kernel32/nls/non.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Norway (Nynorsk) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0814") +LOCVAL(LOCALE_SLANGUAGE,"Norwegian (Nynorsk)") +LOCVAL(LOCALE_SENGLANGUAGE,"Norwegian") +LOCVAL(LOCALE_SABBREVLANGNAME,"non") +LOCVAL(LOCALE_SNATIVELANGNAME,"nynorsk") +LOCVAL(LOCALE_ICOUNTRY,"47") +LOCVAL(LOCALE_SCOUNTRY,"Noreg") +LOCVAL(LOCALE_SENGCOUNTRY,"Norway") +LOCVAL(LOCALE_SABBREVCTRYNAME,"NOR") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Noreg") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0814") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"47") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"kr") +LOCVAL(LOCALE_SINTLSYMBOL,"NOK") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"m?ndag") +LOCVAL(LOCALE_SDAYNAME2,"tysdag") +LOCVAL(LOCALE_SDAYNAME3,"fredag") +LOCVAL(LOCALE_SDAYNAME4,"onsdag") +LOCVAL(LOCALE_SDAYNAME5,"torsdag") +LOCVAL(LOCALE_SDAYNAME6,"laurdag") +LOCVAL(LOCALE_SDAYNAME7,"sundag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"m?") +LOCVAL(LOCALE_SABBREVDAYNAME2,"ty") +LOCVAL(LOCALE_SABBREVDAYNAME3,"fr") +LOCVAL(LOCALE_SABBREVDAYNAME4,"on") +LOCVAL(LOCALE_SABBREVDAYNAME5,"to") +LOCVAL(LOCALE_SABBREVDAYNAME6,"lau") +LOCVAL(LOCALE_SABBREVDAYNAME7,"su") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februar") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"desember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"des") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"no") +LOCVAL(LOCALE_SISO3166CTRYNAME,"NO") + +/* gregoriansk kalender */ diff --git a/lib/kernel32/nls/nor.nls b/lib/kernel32/nls/nor.nls new file mode 100644 index 0000000..0a66334 --- /dev/null +++ b/lib/kernel32/nls/nor.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Norway (Bokmaal) + * (Norwegian strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0414") +LOCVAL(LOCALE_SLANGUAGE,"Norsk (Bokmål)") +LOCVAL(LOCALE_SENGLANGUAGE,"Norwegian (Bokmaal)") +LOCVAL(LOCALE_SABBREVLANGNAME,"nor") +LOCVAL(LOCALE_SNATIVELANGNAME,"bokmål") +LOCVAL(LOCALE_ICOUNTRY,"47") +LOCVAL(LOCALE_SCOUNTRY,"Norge") +LOCVAL(LOCALE_SENGCOUNTRY,"Norway") +LOCVAL(LOCALE_SABBREVCTRYNAME,"NOR") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Norge") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0414") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"47") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"kr") +LOCVAL(LOCALE_SINTLSYMBOL,"NOK") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"mandag") +LOCVAL(LOCALE_SDAYNAME2,"tirsdag") +LOCVAL(LOCALE_SDAYNAME3,"onsdag") +LOCVAL(LOCALE_SDAYNAME4,"torsdag") +LOCVAL(LOCALE_SDAYNAME5,"fredag") +LOCVAL(LOCALE_SDAYNAME6,"lørdag") +LOCVAL(LOCALE_SDAYNAME7,"søndag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"ma") +LOCVAL(LOCALE_SABBREVDAYNAME2,"ti") +LOCVAL(LOCALE_SABBREVDAYNAME3,"on") +LOCVAL(LOCALE_SABBREVDAYNAME4,"to") +LOCVAL(LOCALE_SABBREVDAYNAME5,"fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"lø") +LOCVAL(LOCALE_SABBREVDAYNAME7,"sø") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februar") +LOCVAL(LOCALE_SMONTHNAME3,"mars") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"desember") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"des") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"no") +LOCVAL(LOCALE_SISO3166CTRYNAME,"NO") + +/* gregoriansk kalender */ diff --git a/lib/kernel32/nls/ole2nls.c b/lib/kernel32/nls/ole2nls.c new file mode 100644 index 0000000..d3703a9 --- /dev/null +++ b/lib/kernel32/nls/ole2nls.c @@ -0,0 +1,3113 @@ +/* + * OLE2NLS library + * + * Copyright 1995 Martin von Loewis + * Copyright 1998 David Lee Lambert + */ + +#include +#include +#include +#include +#include +//#include "heap.h" +//#include "ole.h" +//#include "options.h" +//#include "winnls.h" +//#include "winreg.h" +//#include "winerror.h" +//#include "debug.h" +//#include "main.h" + +struct NLS_langlocale { + const int lang; + struct NLS_localevar { + const int type; + const char *val; + } locvars[150]; +}; + +#define LANG_BEGIN(l,s) { MAKELANGID(l,s), { + +#define LOCVAL(type,value) {type,value}, + +#define LANG_END }}, + +static const struct NLS_langlocale langlocales[] = { +/* add languages in numerical order of main language (last two digits) + * it is much easier to find the missing holes that way */ + +LANG_BEGIN (LANG_CATALAN, SUBLANG_DEFAULT) /*0x0403*/ +#include "nls/cat.nls" +LANG_END + +LANG_BEGIN (LANG_CZECH, SUBLANG_DEFAULT) /*0x0405*/ +#include "nls/cze.nls" +LANG_END + +LANG_BEGIN (LANG_DANISH, SUBLANG_DEFAULT) /*0x0406*/ +#include "nls/dan.nls" +LANG_END + +LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN) /*0x0407*/ +#include "nls/deu.nls" +LANG_END +LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_SWISS) /*0x0807*/ +#include "nls/des.nls" +LANG_END +LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN) /*0x0C07*/ +#include "nls/dea.nls" +LANG_END +LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG) /*0x1007*/ +#include "nls/del.nls" +LANG_END +LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN) /*0x1407*/ +#include "nls/dec.nls" +LANG_END + +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_US) /*0x0409*/ +#include "nls/enu.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_UK) /*0x0809*/ +#include "nls/eng.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_AUS) /*0x0C09*/ +#include "nls/ena.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CAN) /*0x1009*/ +#include "nls/enc.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_NZ) /*0x1409*/ +#include "nls/enz.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_EIRE) /*0x1809*/ +#include "nls/irl.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_SAFRICA) /*0x1C09*/ +#include "nls/ens.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA) /*0x2009*/ +#include "nls/enj.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CARRIBEAN) /*0x2409*/ +#include "nls/enb.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE) /*0x2809*/ +#include "nls/enl.nls" +LANG_END +LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD) /*0x2C09*/ +#include "nls/ent.nls" +LANG_END + +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH) /*0x040a*/ +#include "nls/esp.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MEXICAN) /*0x080a*/ +#include "nls/esm.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MODERN) /*0x0C0a*/ +#include "nls/esn.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA) /*0x100a*/ +#include "nls/esg.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COSTARICA) /*0x140a*/ +#include "nls/esc.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PANAMA) /*0x180a*/ +#include "nls/esa.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN) /*0x1C0A*/ +#include "nls/esd.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA) /*0x200a*/ +#include "nls/esv.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA) /*0x240a*/ +#include "nls/eso.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PERU) /*0x280a*/ +#include "nls/esr.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA) /*0x2c0a*/ +#include "nls/ess.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ECUADOR) /*0x300a*/ +#include "nls/esf.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_CHILE) /*0x340a*/ +#include "nls/esl.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_URUGUAY) /*0x380a*/ +#include "nls/esy.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY) /*0x3c0a*/ +#include "nls/esz.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA) /*0x400a*/ +#include "nls/esb.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR) /*0x440a*/ +#include "nls/ese.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_HONDURAS) /*0x480a*/ +#include "nls/esh.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA) /*0x4c0a*/ +#include "nls/esi.nls" +LANG_END +LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO) /*0x500a*/ +#include "nls/esu.nls" +LANG_END + +LANG_BEGIN (LANG_FINNISH, SUBLANG_DEFAULT) /*0x040B*/ +#include "nls/fin.nls" +LANG_END + +LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH) /*0x040C*/ +#include "nls/fra.nls" +LANG_END +LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_BELGIAN) /*0x080C*/ +#include "nls/frb.nls" +LANG_END +LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_CANADIAN) /*0x0C0C*/ +#include "nls/frc.nls" +LANG_END +LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_SWISS) /*0x100C*/ +#include "nls/frs.nls" +LANG_END +LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG) /*0x140C*/ +#include "nls/frl.nls" +LANG_END + +LANG_BEGIN (LANG_HUNGARIAN, SUBLANG_DEFAULT) /*0x040e*/ +#include "nls/hun.nls" +LANG_END + +LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN) /*0x0410*/ +#include "nls/ita.nls" +LANG_END +LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN_SWISS) /*0x0810*/ +#include "nls/its.nls" +LANG_END + +LANG_BEGIN (LANG_KOREAN, SUBLANG_KOREAN) /*0x0412*/ +#include "nls/kor.nls" +LANG_END + +LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL) /*0x0414*/ +#include "nls/nor.nls" +LANG_END +LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK) /*0x0814*/ +#include "nls/non.nls" +LANG_END + +LANG_BEGIN (LANG_POLISH, SUBLANG_DEFAULT) /*0x0415*/ +#include "nls/plk.nls" +LANG_END + +LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE_BRAZILIAN) /*0x0416*/ +#include "nls/ptb.nls" +LANG_END +LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE) /*0x0816*/ +#include "nls/ptg.nls" +LANG_END + +LANG_BEGIN (LANG_SLOVAK, SUBLANG_DEFAULT) /*0x041b*/ +#include "nls/sky.nls" +LANG_END + +LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH) /*0x041d*/ +#include "nls/sve.nls" +LANG_END +LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND) /*0x081d*/ +#include "nls/svf.nls" +LANG_END + +LANG_BEGIN (LANG_THAI, SUBLANG_DEFAULT) /*0x41e*/ +#include "nls/tha.nls" +LANG_END + +LANG_BEGIN (LANG_ESPERANTO, SUBLANG_DEFAULT) /*0x048f*/ +#include "nls/esperanto.nls" +LANG_END + }; + + +/* Locale name to id map. used by EnumSystemLocales, GetLocalInfoA + * MUST contain all #defines from winnls.h + * last entry has NULL name, 0 id. + */ +#define LOCALE_ENTRY(x) {#x,LOCALE_##x} +static struct tagLOCALE_NAME2ID { + char *name; + DWORD id; +} locale_name2id[]= { + LOCALE_ENTRY(ILANGUAGE), + LOCALE_ENTRY(SLANGUAGE), + LOCALE_ENTRY(SENGLANGUAGE), + LOCALE_ENTRY(SABBREVLANGNAME), + LOCALE_ENTRY(SNATIVELANGNAME), + LOCALE_ENTRY(ICOUNTRY), + LOCALE_ENTRY(SCOUNTRY), + LOCALE_ENTRY(SENGCOUNTRY), + LOCALE_ENTRY(SABBREVCTRYNAME), + LOCALE_ENTRY(SNATIVECTRYNAME), + LOCALE_ENTRY(IDEFAULTLANGUAGE), + LOCALE_ENTRY(IDEFAULTCOUNTRY), + LOCALE_ENTRY(IDEFAULTCODEPAGE), + LOCALE_ENTRY(IDEFAULTANSICODEPAGE), + LOCALE_ENTRY(IDEFAULTMACCODEPAGE), + LOCALE_ENTRY(SLIST), + LOCALE_ENTRY(IMEASURE), + LOCALE_ENTRY(SDECIMAL), + LOCALE_ENTRY(STHOUSAND), + LOCALE_ENTRY(SGROUPING), + LOCALE_ENTRY(IDIGITS), + LOCALE_ENTRY(ILZERO), + LOCALE_ENTRY(INEGNUMBER), + LOCALE_ENTRY(SNATIVEDIGITS), + LOCALE_ENTRY(SCURRENCY), + LOCALE_ENTRY(SINTLSYMBOL), + LOCALE_ENTRY(SMONDECIMALSEP), + LOCALE_ENTRY(SMONTHOUSANDSEP), + LOCALE_ENTRY(SMONGROUPING), + LOCALE_ENTRY(ICURRDIGITS), + LOCALE_ENTRY(IINTLCURRDIGITS), + LOCALE_ENTRY(ICURRENCY), + LOCALE_ENTRY(INEGCURR), + LOCALE_ENTRY(SDATE), + LOCALE_ENTRY(STIME), + LOCALE_ENTRY(SSHORTDATE), + LOCALE_ENTRY(SLONGDATE), + LOCALE_ENTRY(STIMEFORMAT), + LOCALE_ENTRY(IDATE), + LOCALE_ENTRY(ILDATE), + LOCALE_ENTRY(ITIME), + LOCALE_ENTRY(ITIMEMARKPOSN), + LOCALE_ENTRY(ICENTURY), + LOCALE_ENTRY(ITLZERO), + LOCALE_ENTRY(IDAYLZERO), + LOCALE_ENTRY(IMONLZERO), + LOCALE_ENTRY(S1159), + LOCALE_ENTRY(S2359), + LOCALE_ENTRY(ICALENDARTYPE), + LOCALE_ENTRY(IOPTIONALCALENDAR), + LOCALE_ENTRY(IFIRSTDAYOFWEEK), + LOCALE_ENTRY(IFIRSTWEEKOFYEAR), + LOCALE_ENTRY(SDAYNAME1), + LOCALE_ENTRY(SDAYNAME2), + LOCALE_ENTRY(SDAYNAME3), + LOCALE_ENTRY(SDAYNAME4), + LOCALE_ENTRY(SDAYNAME5), + LOCALE_ENTRY(SDAYNAME6), + LOCALE_ENTRY(SDAYNAME7), + LOCALE_ENTRY(SABBREVDAYNAME1), + LOCALE_ENTRY(SABBREVDAYNAME2), + LOCALE_ENTRY(SABBREVDAYNAME3), + LOCALE_ENTRY(SABBREVDAYNAME4), + LOCALE_ENTRY(SABBREVDAYNAME5), + LOCALE_ENTRY(SABBREVDAYNAME6), + LOCALE_ENTRY(SABBREVDAYNAME7), + LOCALE_ENTRY(SMONTHNAME1), + LOCALE_ENTRY(SMONTHNAME2), + LOCALE_ENTRY(SMONTHNAME3), + LOCALE_ENTRY(SMONTHNAME4), + LOCALE_ENTRY(SMONTHNAME5), + LOCALE_ENTRY(SMONTHNAME6), + LOCALE_ENTRY(SMONTHNAME7), + LOCALE_ENTRY(SMONTHNAME8), + LOCALE_ENTRY(SMONTHNAME9), + LOCALE_ENTRY(SMONTHNAME10), + LOCALE_ENTRY(SMONTHNAME11), + LOCALE_ENTRY(SMONTHNAME12), + LOCALE_ENTRY(SMONTHNAME13), + LOCALE_ENTRY(SABBREVMONTHNAME1), + LOCALE_ENTRY(SABBREVMONTHNAME2), + LOCALE_ENTRY(SABBREVMONTHNAME3), + LOCALE_ENTRY(SABBREVMONTHNAME4), + LOCALE_ENTRY(SABBREVMONTHNAME5), + LOCALE_ENTRY(SABBREVMONTHNAME6), + LOCALE_ENTRY(SABBREVMONTHNAME7), + LOCALE_ENTRY(SABBREVMONTHNAME8), + LOCALE_ENTRY(SABBREVMONTHNAME9), + LOCALE_ENTRY(SABBREVMONTHNAME10), + LOCALE_ENTRY(SABBREVMONTHNAME11), + LOCALE_ENTRY(SABBREVMONTHNAME12), + LOCALE_ENTRY(SABBREVMONTHNAME13), + LOCALE_ENTRY(SPOSITIVESIGN), + LOCALE_ENTRY(SNEGATIVESIGN), + LOCALE_ENTRY(IPOSSIGNPOSN), + LOCALE_ENTRY(INEGSIGNPOSN), + LOCALE_ENTRY(IPOSSYMPRECEDES), + LOCALE_ENTRY(IPOSSEPBYSPACE), + LOCALE_ENTRY(INEGSYMPRECEDES), + LOCALE_ENTRY(INEGSEPBYSPACE), + LOCALE_ENTRY(FONTSIGNATURE), + LOCALE_ENTRY(SISO639LANGNAME), + LOCALE_ENTRY(SISO3166CTRYNAME), + {NULL,0}, +}; + +const struct map_lcid2str { + LCID langid; + const char *langname; +} languages[]={ + {0x0401,"Arabic (Saudi Arabia)"}, + {0x0801,"Arabic (Iraq)"}, + {0x0c01,"Arabic (Egypt)"}, + {0x1001,"Arabic (Libya)"}, + {0x1401,"Arabic (Algeria)"}, + {0x1801,"Arabic (Morocco)"}, + {0x1c01,"Arabic (Tunisia)"}, + {0x2001,"Arabic (Oman)"}, + {0x2401,"Arabic (Yemen)"}, + {0x2801,"Arabic (Syria)"}, + {0x2c01,"Arabic (Jordan)"}, + {0x3001,"Arabic (Lebanon)"}, + {0x3401,"Arabic (Kuwait)"}, + {0x3801,"Arabic (United Arab Emirates)"}, + {0x3c01,"Arabic (Bahrain)"}, + {0x4001,"Arabic (Qatar)"}, + {0x0402,"Bulgarian"}, + {0x0403,"Catalan"}, + {0x0404,"Chinese (Taiwan)"}, + {0x0804,"Chinese (People's Republic of China)"}, + {0x0c04,"Chinese (Hong Kong)"}, + {0x1004,"Chinese (Singapore)"}, + {0x1404,"Chinese (Macau)"}, + {0x0405,"Czech"}, + {0x0406,"Danish"}, + {0x0407,"German (Germany)"}, + {0x0807,"German (Switzerland)"}, + {0x0c07,"German (Austria)"}, + {0x1007,"German (Luxembourg)"}, + {0x1407,"German (Liechtenstein)"}, + {0x0408,"Greek"}, + {0x0409,"English (United States)"}, + {0x0809,"English (United Kingdom)"}, + {0x0c09,"English (Australia)"}, + {0x1009,"English (Canada)"}, + {0x1409,"English (New Zealand)"}, + {0x1809,"English (Ireland)"}, + {0x1c09,"English (South Africa)"}, + {0x2009,"English (Jamaica)"}, + {0x2409,"English (Caribbean)"}, + {0x2809,"English (Belize)"}, + {0x2c09,"English (Trinidad)"}, + {0x3009,"English (Zimbabwe)"}, + {0x3409,"English (Philippines)"}, + {0x040a,"Spanish (Spain, traditional sorting)"}, + {0x080a,"Spanish (Mexico)"}, + {0x0c0a,"Spanish (Spain, international sorting)"}, + {0x100a,"Spanish (Guatemala)"}, + {0x140a,"Spanish (Costa Rica)"}, + {0x180a,"Spanish (Panama)"}, + {0x1c0a,"Spanish (Dominican Republic)"}, + {0x200a,"Spanish (Venezuela)"}, + {0x240a,"Spanish (Colombia)"}, + {0x280a,"Spanish (Peru)"}, + {0x2c0a,"Spanish (Argentina)"}, + {0x300a,"Spanish (Ecuador)"}, + {0x340a,"Spanish (Chile)"}, + {0x380a,"Spanish (Uruguay)"}, + {0x3c0a,"Spanish (Paraguay)"}, + {0x400a,"Spanish (Bolivia)"}, + {0x440a,"Spanish (El Salvador)"}, + {0x480a,"Spanish (Honduras)"}, + {0x4c0a,"Spanish (Nicaragua)"}, + {0x500a,"Spanish (Puerto Rico)"}, + {0x040b,"Finnish"}, + {0x040c,"French (France)"}, + {0x080c,"French (Belgium)"}, + {0x0c0c,"French (Canada)"}, + {0x100c,"French (Switzerland)"}, + {0x140c,"French (Luxembourg)"}, + {0x180c,"French (Monaco)"}, + {0x040d,"Hebrew"}, + {0x040e,"Hungarian"}, + {0x040f,"Icelandic"}, + {0x0410,"Italian (Italy)"}, + {0x0810,"Italian (Switzerland)"}, + {0x0411,"Japanese"}, + {0x0412,"Korean (Wansung)"}, + {0x0812,"Korean (Johab)"}, + {0x0413,"Dutch (Netherlands)"}, + {0x0813,"Dutch (Belgium)"}, + {0x0414,"Norwegian (Bokmal)"}, + {0x0814,"Norwegian (Nynorsk)"}, + {0x0415,"Polish"}, + {0x0416,"Portuguese (Brazil)"}, + {0x0816,"Portuguese (Portugal)"}, + {0x0417,"Rhaeto Romanic"}, + {0x0418,"Romanian"}, + {0x0818,"Moldavian"}, + {0x0419,"Russian (Russia)"}, + {0x0819,"Russian (Moldavia)"}, + {0x041a,"Croatian"}, + {0x081a,"Serbian (latin)"}, + {0x0c1a,"Serbian (cyrillic)"}, + {0x041b,"Slovak"}, + {0x041c,"Albanian"}, + {0x041d,"Swedish (Sweden)"}, + {0x081d,"Swedish (Finland)"}, + {0x041e,"Thai"}, + {0x041f,"Turkish"}, + {0x0420,"Urdu"}, + {0x0421,"Indonesian"}, + {0x0422,"Ukrainian"}, + {0x0423,"Belarusian"}, + {0x0424,"Slovene"}, + {0x0425,"Estonian"}, + {0x0426,"Latvian"}, + {0x0427,"Lithuanian (modern)"}, + {0x0827,"Lithuanian (classic)"}, + {0x0428,"Maori"}, + {0x0429,"Farsi"}, + {0x042a,"Vietnamese"}, + {0x042b,"Armenian"}, + {0x042c,"Azeri (latin)"}, + {0x082c,"Azeri (cyrillic)"}, + {0x042d,"Basque"}, + {0x042e,"Sorbian"}, + {0x042f,"Macedonian"}, + {0x0430,"Sutu"}, + {0x0431,"Tsonga"}, + {0x0432,"Tswana"}, + {0x0433,"Venda"}, + {0x0434,"Xhosa"}, + {0x0435,"Zulu"}, + {0x0436,"Afrikaans"}, + {0x0437,"Georgian"}, + {0x0438,"Faeroese"}, + {0x0439,"Hindi"}, + {0x043a,"Maltese"}, + {0x043b,"Saami"}, + {0x043c,"Irish gaelic"}, + {0x083c,"Scottish gaelic"}, + {0x043e,"Malay (Malaysia)"}, + {0x083e,"Malay (Brunei Darussalam)"}, + {0x043f,"Kazak"}, + {0x0441,"Swahili"}, + {0x0443,"Uzbek (latin)"}, + {0x0843,"Uzbek (cyrillic)"}, + {0x0444,"Tatar"}, + {0x0445,"Bengali"}, + {0x0446,"Punjabi"}, + {0x0447,"Gujarati"}, + {0x0448,"Oriya"}, + {0x0449,"Tamil"}, + {0x044a,"Telugu"}, + {0x044b,"Kannada"}, + {0x044c,"Malayalam"}, + {0x044d,"Assamese"}, + {0x044e,"Marathi"}, + {0x044f,"Sanskrit"}, + {0x0457,"Konkani"}, + {0x048f,"Esperanto"}, /* Non official */ + {0x0000,"Unknown"} + }, languages_de[]={ + {0x0401,"Arabic"}, + {0x0402,"Bulgarisch"}, + {0x0403,"Katalanisch"}, + {0x0404,"Traditionales Chinesisch"}, + {0x0405,"Tschecisch"}, + {0x0406,"Dänisch"}, + {0x0407,"Deutsch"}, + {0x0408,"Griechisch"}, + {0x0409,"Amerikanisches Englisch"}, + {0x040A,"Kastilisches Spanisch"}, + {0x040B,"Finnisch"}, + {0x040C,"Franzvsisch"}, + {0x040D,"Hebrdisch"}, + {0x040E,"Ungarisch"}, + {0x040F,"Isldndisch"}, + {0x0410,"Italienisch"}, + {0x0411,"Japanisch"}, + {0x0412,"Koreanisch"}, + {0x0413,"Niederldndisch"}, + {0x0414,"Norwegisch-Bokmal"}, + {0x0415,"Polnisch"}, + {0x0416,"Brasilianisches Portugiesisch"}, + {0x0417,"Rdtoromanisch"}, + {0x0418,"Rumdnisch"}, + {0x0419,"Russisch"}, + {0x041A,"Kroatoserbisch (lateinisch)"}, + {0x041B,"Slowenisch"}, + {0x041C,"Albanisch"}, + {0x041D,"Schwedisch"}, + {0x041E,"Thai"}, + {0x041F,"Türkisch"}, + {0x0420,"Urdu"}, + {0x0421,"Bahasa"}, + {0x0804,"Vereinfachtes Chinesisch"}, + {0x0807,"Schweizerdeutsch"}, + {0x0809,"Britisches Englisch"}, + {0x080A,"Mexikanisches Spanisch"}, + {0x080C,"Belgisches Franzvsisch"}, + {0x0810,"Schweizerisches Italienisch"}, + {0x0813,"Belgisches Niederldndisch"}, + {0x0814,"Norgwegisch-Nynorsk"}, + {0x0816,"Portugiesisch"}, + {0x081A,"Serbokratisch (kyrillisch)"}, + {0x0C1C,"Kanadisches Franzvsisch"}, + {0x100C,"Schweizerisches Franzvsisch"}, + {0x0000,"Unbekannt"}, +}; + +/*********************************************************************** + * GetUserDefaultLCID (OLE2NLS.1) + */ +LCID WINAPI GetUserDefaultLCID() +{ + return MAKELCID( GetUserDefaultLangID() , SORT_DEFAULT ); +} + +/*********************************************************************** + * GetSystemDefaultLCID (OLE2NLS.2) + */ +LCID WINAPI GetSystemDefaultLCID() +{ + return GetUserDefaultLCID(); +} + +/*********************************************************************** + * GetUserDefaultLangID (OLE2NLS.3) + */ +#if 0 +LANGID WINAPI GetUserDefaultLangID() +{ + /* caching result, if defined from environment, which should (?) not change during a WINE session */ + static LANGID userLCID = 0; + if (Options.language) { + return Languages[Options.language].langid; + } + + if (userLCID == 0) { + char *buf=NULL; + char *lang,*country,*charset,*dialect,*next; + int ret=0; + + buf=getenv("LANGUAGE"); + if (!buf) buf=getenv("LANG"); + if (!buf) buf=getenv("LC_ALL"); + if (!buf) buf=getenv("LC_MESSAGES"); + if (!buf) buf=getenv("LC_CTYPE"); + if (!buf) return userLCID = MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ); + + if (!strcmp(buf,"POSIX") || !strcmp(buf,"C")) { + return MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ); + } + + lang=buf; + + do { + next=strchr(lang,':'); if (next) *next++='\0'; + dialect=strchr(lang,'@'); if (dialect) *dialect++='\0'; + charset=strchr(lang,'.'); if (charset) *charset++='\0'; + country=strchr(lang,'_'); if (country) *country++='\0'; + + ret=MAIN_GetLanguageID(lang, country, charset, dialect); + + lang=next; + + } while (lang && !ret); + + /* FIXME : are strings returned by getenv() to be free()'ed ? */ + userLCID = (LANGID)ret; + } + return userLCID; +} +#endif + +/*********************************************************************** + * GetSystemDefaultLangID (OLE2NLS.4) + */ +LANGID WINAPI GetSystemDefaultLangID() +{ + return GetUserDefaultLangID(); +} + +/****************************************************************************** + * GetLocaleInfo32A [KERNEL32.342] + * + * NOTES + * LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT + */ +ULONG WINAPI GetLocaleInfo32A(LCID lcid,LCTYPE LCType,LPSTR buf,ULONG len) +{ + LPCSTR retString; + int found,i; + int lang=0; + + DPRINT("(lcid=0x%lx,lctype=0x%lx,%p,%x)\n",lcid,LCType,buf,len); + + if (len && (! buf) ) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + + if (lcid ==0 || lcid == LANG_SYSTEM_DEFAULT || (LCType & LOCALE_NOUSEROVERRIDE) ) /* 0x00, 0x400 */ + { + lcid = GetSystemDefaultLCID(); + } + else if (lcid == LANG_USER_DEFAULT) /*0x800*/ + { + lcid = GetUserDefaultLCID(); + } + LCType &= ~(LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP); + + /* As an option, we could obtain the value from win.ini. + This would not match the Wine compile-time option. + Also, not all identifiers are available from win.ini */ + retString=0; + /* If we are through all of this, retLen should not be zero anymore. + If it is, the value is not supported */ + i=0; + while (locale_name2id[i].name!=NULL) { + if (LCType == locale_name2id[i].id) { + retString = locale_name2id[i].name; + break; + } + i++; + } + if (!retString) { + FIXME(ole,"Unkown LC type %lX\n",LCType); + return 0; + } + + found=0;lang=lcid; + for (i=0;(i<3 && !found);i++) { + int j; + + for (j=0;j - 62 */ + C2_OTHERNEUTRAL, /* ? - 63 */ + C2_LEFTTORIGHT, /* @ - 64 */ + C2_LEFTTORIGHT, /* A - 65 */ + C2_LEFTTORIGHT, /* B - 66 */ + C2_LEFTTORIGHT, /* C - 67 */ + C2_LEFTTORIGHT, /* D - 68 */ + C2_LEFTTORIGHT, /* E - 69 */ + C2_LEFTTORIGHT, /* F - 70 */ + C2_LEFTTORIGHT, /* G - 71 */ + C2_LEFTTORIGHT, /* H - 72 */ + C2_LEFTTORIGHT, /* I - 73 */ + C2_LEFTTORIGHT, /* J - 74 */ + C2_LEFTTORIGHT, /* K - 75 */ + C2_LEFTTORIGHT, /* L - 76 */ + C2_LEFTTORIGHT, /* M - 77 */ + C2_LEFTTORIGHT, /* N - 78 */ + C2_LEFTTORIGHT, /* O - 79 */ + C2_LEFTTORIGHT, /* P - 80 */ + C2_LEFTTORIGHT, /* Q - 81 */ + C2_LEFTTORIGHT, /* R - 82 */ + C2_LEFTTORIGHT, /* S - 83 */ + C2_LEFTTORIGHT, /* T - 84 */ + C2_LEFTTORIGHT, /* U - 85 */ + C2_LEFTTORIGHT, /* V - 86 */ + C2_LEFTTORIGHT, /* W - 87 */ + C2_LEFTTORIGHT, /* X - 88 */ + C2_LEFTTORIGHT, /* Y - 89 */ + C2_LEFTTORIGHT, /* Z - 90 */ + C2_OTHERNEUTRAL, /* [ - 91 */ + C2_OTHERNEUTRAL, /* \ - 92 */ + C2_OTHERNEUTRAL, /* ] - 93 */ + C2_OTHERNEUTRAL, /* ^ - 94 */ + C2_OTHERNEUTRAL, /* _ - 95 */ + C2_OTHERNEUTRAL, /* ` - 96 */ + C2_LEFTTORIGHT, /* a - 97 */ + C2_LEFTTORIGHT, /* b - 98 */ + C2_LEFTTORIGHT, /* c - 99 */ + C2_LEFTTORIGHT, /* d - 100 */ + C2_LEFTTORIGHT, /* e - 101 */ + C2_LEFTTORIGHT, /* f - 102 */ + C2_LEFTTORIGHT, /* g - 103 */ + C2_LEFTTORIGHT, /* h - 104 */ + C2_LEFTTORIGHT, /* i - 105 */ + C2_LEFTTORIGHT, /* j - 106 */ + C2_LEFTTORIGHT, /* k - 107 */ + C2_LEFTTORIGHT, /* l - 108 */ + C2_LEFTTORIGHT, /* m - 109 */ + C2_LEFTTORIGHT, /* n - 110 */ + C2_LEFTTORIGHT, /* o - 111 */ + C2_LEFTTORIGHT, /* p - 112 */ + C2_LEFTTORIGHT, /* q - 113 */ + C2_LEFTTORIGHT, /* r - 114 */ + C2_LEFTTORIGHT, /* s - 115 */ + C2_LEFTTORIGHT, /* t - 116 */ + C2_LEFTTORIGHT, /* u - 117 */ + C2_LEFTTORIGHT, /* v - 118 */ + C2_LEFTTORIGHT, /* w - 119 */ + C2_LEFTTORIGHT, /* x - 120 */ + C2_LEFTTORIGHT, /* y - 121 */ + C2_LEFTTORIGHT, /* z - 122 */ + C2_OTHERNEUTRAL, /* { - 123 */ + C2_OTHERNEUTRAL, /* | - 124 */ + C2_OTHERNEUTRAL, /* } - 125 */ + C2_OTHERNEUTRAL, /* ~ - 126 */ + C2_NOTAPPLICABLE, /*  - 127 */ + C2_NOTAPPLICABLE, /* € - 128 */ + C2_NOTAPPLICABLE, /*  - 129 */ + C2_OTHERNEUTRAL, /* ‚ - 130 */ + C2_LEFTTORIGHT, /* ƒ - 131 */ + C2_OTHERNEUTRAL, /* „ - 132 */ + C2_OTHERNEUTRAL, /* … - 133 */ + C2_OTHERNEUTRAL, /* † - 134 */ + C2_OTHERNEUTRAL, /* ‡ - 135 */ + C2_LEFTTORIGHT, /* ˆ - 136 */ + C2_EUROPETERMINATOR, /* ‰ - 137 */ + C2_LEFTTORIGHT, /* Š - 138 */ + C2_OTHERNEUTRAL, /* ‹ - 139 */ + C2_LEFTTORIGHT, /* Œ - 140 */ + C2_NOTAPPLICABLE, /*  - 141 */ + C2_NOTAPPLICABLE, /* Ž - 142 */ + C2_NOTAPPLICABLE, /*  - 143 */ + C2_NOTAPPLICABLE, /*  - 144 */ + C2_OTHERNEUTRAL, /* ‘ - 145 */ + C2_OTHERNEUTRAL, /* ’ - 146 */ + C2_OTHERNEUTRAL, /* “ - 147 */ + C2_OTHERNEUTRAL, /* ” - 148 */ + C2_OTHERNEUTRAL, /* • - 149 */ + C2_OTHERNEUTRAL, /* – - 150 */ + C2_OTHERNEUTRAL, /* — - 151 */ + C2_LEFTTORIGHT, /* ˜ - 152 */ + C2_OTHERNEUTRAL, /* ™ - 153 */ + C2_LEFTTORIGHT, /* š - 154 */ + C2_OTHERNEUTRAL, /* › - 155 */ + C2_LEFTTORIGHT, /* œ - 156 */ + C2_NOTAPPLICABLE, /*  - 157 */ + C2_NOTAPPLICABLE, /* ž - 158 */ + C2_LEFTTORIGHT, /* Ÿ - 159 */ + C2_WHITESPACE, /*   - 160 */ + C2_OTHERNEUTRAL, /* ¡ - 161 */ + C2_EUROPETERMINATOR, /* ¢ - 162 */ + C2_EUROPETERMINATOR, /* £ - 163 */ + C2_EUROPETERMINATOR, /* ¤ - 164 */ + C2_EUROPETERMINATOR, /* ¥ - 165 */ + C2_OTHERNEUTRAL, /* ¦ - 166 */ + C2_OTHERNEUTRAL, /* § - 167 */ + C2_OTHERNEUTRAL, /* ¨ - 168 */ + C2_OTHERNEUTRAL, /* © - 169 */ + C2_OTHERNEUTRAL, /* ª - 170 */ + C2_OTHERNEUTRAL, /* « - 171 */ + C2_OTHERNEUTRAL, /* ¬ - 172 */ + C2_OTHERNEUTRAL, /* ­ - 173 */ + C2_OTHERNEUTRAL, /* ® - 174 */ + C2_OTHERNEUTRAL, /* ¯ - 175 */ + C2_EUROPETERMINATOR, /* ° - 176 */ + C2_EUROPETERMINATOR, /* ± - 177 */ + C2_EUROPENUMBER, /* ² - 178 */ + C2_EUROPENUMBER, /* ³ - 179 */ + C2_OTHERNEUTRAL, /* ´ - 180 */ + C2_OTHERNEUTRAL, /* µ - 181 */ + C2_OTHERNEUTRAL, /* ¶ - 182 */ + C2_OTHERNEUTRAL, /* · - 183 */ + C2_OTHERNEUTRAL, /* ¸ - 184 */ + C2_EUROPENUMBER, /* ¹ - 185 */ + C2_OTHERNEUTRAL, /* º - 186 */ + C2_OTHERNEUTRAL, /* » - 187 */ + C2_OTHERNEUTRAL, /* ¼ - 188 */ + C2_OTHERNEUTRAL, /* ½ - 189 */ + C2_OTHERNEUTRAL, /* ¾ - 190 */ + C2_OTHERNEUTRAL, /* ¿ - 191 */ + C2_LEFTTORIGHT, /* À - 192 */ + C2_LEFTTORIGHT, /* Á - 193 */ + C2_LEFTTORIGHT, /*  - 194 */ + C2_LEFTTORIGHT, /* à - 195 */ + C2_LEFTTORIGHT, /* Ä - 196 */ + C2_LEFTTORIGHT, /* Å - 197 */ + C2_LEFTTORIGHT, /* Æ - 198 */ + C2_LEFTTORIGHT, /* Ç - 199 */ + C2_LEFTTORIGHT, /* È - 200 */ + C2_LEFTTORIGHT, /* É - 201 */ + C2_LEFTTORIGHT, /* Ê - 202 */ + C2_LEFTTORIGHT, /* Ë - 203 */ + C2_LEFTTORIGHT, /* Ì - 204 */ + C2_LEFTTORIGHT, /* Í - 205 */ + C2_LEFTTORIGHT, /* Î - 206 */ + C2_LEFTTORIGHT, /* Ï - 207 */ + C2_LEFTTORIGHT, /* Ð - 208 */ + C2_LEFTTORIGHT, /* Ñ - 209 */ + C2_LEFTTORIGHT, /* Ò - 210 */ + C2_LEFTTORIGHT, /* Ó - 211 */ + C2_LEFTTORIGHT, /* Ô - 212 */ + C2_LEFTTORIGHT, /* Õ - 213 */ + C2_LEFTTORIGHT, /* Ö - 214 */ + C2_OTHERNEUTRAL, /* × - 215 */ + C2_LEFTTORIGHT, /* Ø - 216 */ + C2_LEFTTORIGHT, /* Ù - 217 */ + C2_LEFTTORIGHT, /* Ú - 218 */ + C2_LEFTTORIGHT, /* Û - 219 */ + C2_LEFTTORIGHT, /* Ü - 220 */ + C2_LEFTTORIGHT, /* Ý - 221 */ + C2_LEFTTORIGHT, /* Þ - 222 */ + C2_LEFTTORIGHT, /* ß - 223 */ + C2_LEFTTORIGHT, /* à - 224 */ + C2_LEFTTORIGHT, /* á - 225 */ + C2_LEFTTORIGHT, /* â - 226 */ + C2_LEFTTORIGHT, /* ã - 227 */ + C2_LEFTTORIGHT, /* ä - 228 */ + C2_LEFTTORIGHT, /* å - 229 */ + C2_LEFTTORIGHT, /* æ - 230 */ + C2_LEFTTORIGHT, /* ç - 231 */ + C2_LEFTTORIGHT, /* è - 232 */ + C2_LEFTTORIGHT, /* é - 233 */ + C2_LEFTTORIGHT, /* ê - 234 */ + C2_LEFTTORIGHT, /* ë - 235 */ + C2_LEFTTORIGHT, /* ì - 236 */ + C2_LEFTTORIGHT, /* í - 237 */ + C2_LEFTTORIGHT, /* î - 238 */ + C2_LEFTTORIGHT, /* ï - 239 */ + C2_LEFTTORIGHT, /* ð - 240 */ + C2_LEFTTORIGHT, /* ñ - 241 */ + C2_LEFTTORIGHT, /* ò - 242 */ + C2_LEFTTORIGHT, /* ó - 243 */ + C2_LEFTTORIGHT, /* ô - 244 */ + C2_LEFTTORIGHT, /* õ - 245 */ + C2_LEFTTORIGHT, /* ö - 246 */ + C2_OTHERNEUTRAL, /* ÷ - 247 */ + C2_LEFTTORIGHT, /* ø - 248 */ + C2_LEFTTORIGHT, /* ù - 249 */ + C2_LEFTTORIGHT, /* ú - 250 */ + C2_LEFTTORIGHT, /* û - 251 */ + C2_LEFTTORIGHT, /* ü - 252 */ + C2_LEFTTORIGHT, /* ý - 253 */ + C2_LEFTTORIGHT, /* þ - 254 */ + C2_LEFTTORIGHT /* ÿ - 255 */ +}; + +static const WORD CT_CType3_LUT[] = { + 0x0000, /* - 0 */ + 0x0000, /* - 1 */ + 0x0000, /* - 2 */ + 0x0000, /* - 3 */ + 0x0000, /* - 4 */ + 0x0000, /* - 5 */ + 0x0000, /* - 6 */ + 0x0000, /* - 7 */ + 0x0000, /* - 8 */ + 0x0008, /* - 9 */ + 0x0008, /* - 10 */ + 0x0008, /* - 11 */ + 0x0008, /* - 12 */ + 0x0008, /* - 13 */ + 0x0000, /* - 14 */ + 0x0000, /* - 15 */ + 0x0000, /* - 16 */ + 0x0000, /* - 17 */ + 0x0000, /* - 18 */ + 0x0000, /* - 19 */ + 0x0000, /* - 20 */ + 0x0000, /* - 21 */ + 0x0000, /* - 22 */ + 0x0000, /* - 23 */ + 0x0000, /* - 24 */ + 0x0000, /* - 25 */ + 0x0000, /* - 26 */ + 0x0000, /* - 27 */ + 0x0000, /* - 28 */ + 0x0000, /* - 29 */ + 0x0000, /* - 30 */ + 0x0000, /* - 31 */ + 0x0048, /* - 32 */ + 0x0048, /* ! - 33 */ + 0x0448, /* " - 34 */ /* " */ + 0x0048, /* # - 35 */ + 0x0448, /* $ - 36 */ + 0x0048, /* % - 37 */ + 0x0048, /* & - 38 */ + 0x0440, /* ' - 39 */ + 0x0048, /* ( - 40 */ + 0x0048, /* ) - 41 */ + 0x0048, /* * - 42 */ + 0x0048, /* + - 43 */ + 0x0048, /* , - 44 */ + 0x0440, /* - - 45 */ + 0x0048, /* . - 46 */ + 0x0448, /* / - 47 */ + 0x0040, /* 0 - 48 */ + 0x0040, /* 1 - 49 */ + 0x0040, /* 2 - 50 */ + 0x0040, /* 3 - 51 */ + 0x0040, /* 4 - 52 */ + 0x0040, /* 5 - 53 */ + 0x0040, /* 6 - 54 */ + 0x0040, /* 7 - 55 */ + 0x0040, /* 8 - 56 */ + 0x0040, /* 9 - 57 */ + 0x0048, /* : - 58 */ + 0x0048, /* ; - 59 */ + 0x0048, /* < - 60 */ + 0x0448, /* = - 61 */ + 0x0048, /* > - 62 */ + 0x0048, /* ? - 63 */ + 0x0448, /* @ - 64 */ + 0x8040, /* A - 65 */ + 0x8040, /* B - 66 */ + 0x8040, /* C - 67 */ + 0x8040, /* D - 68 */ + 0x8040, /* E - 69 */ + 0x8040, /* F - 70 */ + 0x8040, /* G - 71 */ + 0x8040, /* H - 72 */ + 0x8040, /* I - 73 */ + 0x8040, /* J - 74 */ + 0x8040, /* K - 75 */ + 0x8040, /* L - 76 */ + 0x8040, /* M - 77 */ + 0x8040, /* N - 78 */ + 0x8040, /* O - 79 */ + 0x8040, /* P - 80 */ + 0x8040, /* Q - 81 */ + 0x8040, /* R - 82 */ + 0x8040, /* S - 83 */ + 0x8040, /* T - 84 */ + 0x8040, /* U - 85 */ + 0x8040, /* V - 86 */ + 0x8040, /* W - 87 */ + 0x8040, /* X - 88 */ + 0x8040, /* Y - 89 */ + 0x8040, /* Z - 90 */ + 0x0048, /* [ - 91 */ + 0x0448, /* \ - 92 */ + 0x0048, /* ] - 93 */ + 0x0448, /* ^ - 94 */ + 0x0448, /* _ - 95 */ + 0x0448, /* ` - 96 */ + 0x8040, /* a - 97 */ + 0x8040, /* b - 98 */ + 0x8040, /* c - 99 */ + 0x8040, /* d - 100 */ + 0x8040, /* e - 101 */ + 0x8040, /* f - 102 */ + 0x8040, /* g - 103 */ + 0x8040, /* h - 104 */ + 0x8040, /* i - 105 */ + 0x8040, /* j - 106 */ + 0x8040, /* k - 107 */ + 0x8040, /* l - 108 */ + 0x8040, /* m - 109 */ + 0x8040, /* n - 110 */ + 0x8040, /* o - 111 */ + 0x8040, /* p - 112 */ + 0x8040, /* q - 113 */ + 0x8040, /* r - 114 */ + 0x8040, /* s - 115 */ + 0x8040, /* t - 116 */ + 0x8040, /* u - 117 */ + 0x8040, /* v - 118 */ + 0x8040, /* w - 119 */ + 0x8040, /* x - 120 */ + 0x8040, /* y - 121 */ + 0x8040, /* z - 122 */ + 0x0048, /* { - 123 */ + 0x0048, /* | - 124 */ + 0x0048, /* } - 125 */ + 0x0448, /* ~ - 126 */ + 0x0000, /*  - 127 */ + 0x0000, /* € - 128 */ + 0x0000, /*  - 129 */ + 0x0008, /* ‚ - 130 */ + 0x8000, /* ƒ - 131 */ + 0x0008, /* „ - 132 */ + 0x0008, /* … - 133 */ + 0x0008, /* † - 134 */ + 0x0008, /* ‡ - 135 */ + 0x0001, /* ˆ - 136 */ + 0x0008, /* ‰ - 137 */ + 0x8003, /* Š - 138 */ + 0x0008, /* ‹ - 139 */ + 0x8000, /* Œ - 140 */ + 0x0000, /*  - 141 */ + 0x0000, /* Ž - 142 */ + 0x0000, /*  - 143 */ + 0x0000, /*  - 144 */ + 0x0088, /* ‘ - 145 */ + 0x0088, /* ’ - 146 */ + 0x0088, /* “ - 147 */ + 0x0088, /* ” - 148 */ + 0x0008, /* • - 149 */ + 0x0400, /* – - 150 */ + 0x0400, /* — - 151 */ + 0x0408, /* ˜ - 152 */ + 0x0000, /* ™ - 153 */ + 0x8003, /* š - 154 */ + 0x0008, /* › - 155 */ + 0x8000, /* œ - 156 */ + 0x0000, /*  - 157 */ + 0x0000, /* ž - 158 */ + 0x8003, /* Ÿ - 159 */ + 0x0008, /*   - 160 */ + 0x0008, /* ¡ - 161 */ + 0x0048, /* ¢ - 162 */ + 0x0048, /* £ - 163 */ + 0x0008, /* ¤ - 164 */ + 0x0048, /* ¥ - 165 */ + 0x0048, /* ¦ - 166 */ + 0x0008, /* § - 167 */ + 0x0408, /* ¨ - 168 */ + 0x0008, /* © - 169 */ + 0x0400, /* ª - 170 */ + 0x0008, /* « - 171 */ + 0x0048, /* ¬ - 172 */ + 0x0408, /* ­ - 173 */ + 0x0008, /* ® - 174 */ + 0x0448, /* ¯ - 175 */ + 0x0008, /* ° - 176 */ + 0x0008, /* ± - 177 */ + 0x0000, /* ² - 178 */ + 0x0000, /* ³ - 179 */ + 0x0408, /* ´ - 180 */ + 0x0008, /* µ - 181 */ + 0x0008, /* ¶ - 182 */ + 0x0008, /* · - 183 */ + 0x0408, /* ¸ - 184 */ + 0x0000, /* ¹ - 185 */ + 0x0400, /* º - 186 */ + 0x0008, /* » - 187 */ + 0x0000, /* ¼ - 188 */ + 0x0000, /* ½ - 189 */ + 0x0000, /* ¾ - 190 */ + 0x0008, /* ¿ - 191 */ + 0x8003, /* À - 192 */ + 0x8003, /* Á - 193 */ + 0x8003, /*  - 194 */ + 0x8003, /* à - 195 */ + 0x8003, /* Ä - 196 */ + 0x8003, /* Å - 197 */ + 0x8000, /* Æ - 198 */ + 0x8003, /* Ç - 199 */ + 0x8003, /* È - 200 */ + 0x8003, /* É - 201 */ + 0x8003, /* Ê - 202 */ + 0x8003, /* Ë - 203 */ + 0x8003, /* Ì - 204 */ + 0x8003, /* Í - 205 */ + 0x8003, /* Î - 206 */ + 0x8003, /* Ï - 207 */ + 0x8000, /* Ð - 208 */ + 0x8003, /* Ñ - 209 */ + 0x8003, /* Ò - 210 */ + 0x8003, /* Ó - 211 */ + 0x8003, /* Ô - 212 */ + 0x8003, /* Õ - 213 */ + 0x8003, /* Ö - 214 */ + 0x0008, /* × - 215 */ + 0x8003, /* Ø - 216 */ + 0x8003, /* Ù - 217 */ + 0x8003, /* Ú - 218 */ + 0x8003, /* Û - 219 */ + 0x8003, /* Ü - 220 */ + 0x8003, /* Ý - 221 */ + 0x8000, /* Þ - 222 */ + 0x8000, /* ß - 223 */ + 0x8003, /* à - 224 */ + 0x8003, /* á - 225 */ + 0x8003, /* â - 226 */ + 0x8003, /* ã - 227 */ + 0x8003, /* ä - 228 */ + 0x8003, /* å - 229 */ + 0x8000, /* æ - 230 */ + 0x8003, /* ç - 231 */ + 0x8003, /* è - 232 */ + 0x8003, /* é - 233 */ + 0x8003, /* ê - 234 */ + 0x8003, /* ë - 235 */ + 0x8003, /* ì - 236 */ + 0x8003, /* í - 237 */ + 0x8003, /* î - 238 */ + 0x8003, /* ï - 239 */ + 0x8000, /* ð - 240 */ + 0x8003, /* ñ - 241 */ + 0x8003, /* ò - 242 */ + 0x8003, /* ó - 243 */ + 0x8003, /* ô - 244 */ + 0x8003, /* õ - 245 */ + 0x8003, /* ö - 246 */ + 0x0008, /* ÷ - 247 */ + 0x8003, /* ø - 248 */ + 0x8003, /* ù - 249 */ + 0x8003, /* ú - 250 */ + 0x8003, /* û - 251 */ + 0x8003, /* ü - 252 */ + 0x8003, /* ý - 253 */ + 0x8000, /* þ - 254 */ + 0x8003 /* ÿ - 255 */ +}; + +/****************************************************************************** + * GetStringType32A [KERNEL32.396] + */ +BOOL32 WINAPI GetStringType32A(LCID locale,DWORD dwInfoType,LPCSTR src, + ULONG cchSrc,LPWORD chartype) +{ + return GetStringTypeEx32A(locale,dwInfoType,src,cchSrc,chartype); +} + +/****************************************************************************** + * GetStringTypeEx32A [KERNEL32.397] + * + * FIXME: Ignores the locale. + */ +BOOL32 WINAPI GetStringTypeEx32A(LCID locale,DWORD dwInfoType,LPCSTR src, + ULONG cchSrc,LPWORD chartype) +{ + int i; + + if ((src==NULL) || (chartype==NULL) || (src==(LPSTR)chartype)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (cchSrc==-1) + cchSrc=lstrlen32A(src)+1; + + switch (dwInfoType) { + case CT_CTYPE1: + for (i=0;i + * from the registry. + */ + sprintf(buffer, + "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x", + langid); + keyname = HEAP_strdupAtoW( GetProcessHeap(), 0, buffer ); + result = RegQueryValue32W(HKEY_LOCAL_MACHINE, keyname, langname, + (LPDWORD)&langnamelen); + HeapFree( GetProcessHeap(), 0, keyname ); + if (result != ERROR_SUCCESS) { + /* if that fails, use the internal table */ + for (i=0;languages[i].langid!=0;i++) + if (langid==languages[i].langid) + break; + lstrcpyAtoW( langname, languages[i].langname ); + langnamelen = strlen(languages[i].langname); + /* same as strlenW(langname); */ + } + return langnamelen; +} + +static const unsigned char LCM_Unicode_LUT[] = { + 6 , 3, /* - 1 */ + 6 , 4, /* - 2 */ + 6 , 5, /* - 3 */ + 6 , 6, /* - 4 */ + 6 , 7, /* - 5 */ + 6 , 8, /* - 6 */ + 6 , 9, /* - 7 */ + 6 , 10, /* - 8 */ + 7 , 5, /* - 9 */ + 7 , 6, /* - 10 */ + 7 , 7, /* - 11 */ + 7 , 8, /* - 12 */ + 7 , 9, /* - 13 */ + 6 , 11, /* - 14 */ + 6 , 12, /* - 15 */ + 6 , 13, /* - 16 */ + 6 , 14, /* - 17 */ + 6 , 15, /* - 18 */ + 6 , 16, /* - 19 */ + 6 , 17, /* - 20 */ + 6 , 18, /* - 21 */ + 6 , 19, /* - 22 */ + 6 , 20, /* - 23 */ + 6 , 21, /* - 24 */ + 6 , 22, /* - 25 */ + 6 , 23, /* - 26 */ + 6 , 24, /* - 27 */ + 6 , 25, /* - 28 */ + 6 , 26, /* - 29 */ + 6 , 27, /* - 30 */ + 6 , 28, /* - 31 */ + 7 , 2, /* - 32 */ + 7 , 28, /* ! - 33 */ + 7 , 29, /* " - 34 */ /* " */ + 7 , 31, /* # - 35 */ + 7 , 33, /* $ - 36 */ + 7 , 35, /* % - 37 */ + 7 , 37, /* & - 38 */ + 6 , 128, /* ' - 39 */ + 7 , 39, /* ( - 40 */ + 7 , 42, /* ) - 41 */ + 7 , 45, /* * - 42 */ + 8 , 3, /* + - 43 */ + 7 , 47, /* , - 44 */ + 6 , 130, /* - - 45 */ + 7 , 51, /* . - 46 */ + 7 , 53, /* / - 47 */ + 12 , 3, /* 0 - 48 */ + 12 , 33, /* 1 - 49 */ + 12 , 51, /* 2 - 50 */ + 12 , 70, /* 3 - 51 */ + 12 , 88, /* 4 - 52 */ + 12 , 106, /* 5 - 53 */ + 12 , 125, /* 6 - 54 */ + 12 , 144, /* 7 - 55 */ + 12 , 162, /* 8 - 56 */ + 12 , 180, /* 9 - 57 */ + 7 , 55, /* : - 58 */ + 7 , 58, /* ; - 59 */ + 8 , 14, /* < - 60 */ + 8 , 18, /* = - 61 */ + 8 , 20, /* > - 62 */ + 7 , 60, /* ? - 63 */ + 7 , 62, /* @ - 64 */ + 14 , 2, /* A - 65 */ + 14 , 9, /* B - 66 */ + 14 , 10, /* C - 67 */ + 14 , 26, /* D - 68 */ + 14 , 33, /* E - 69 */ + 14 , 35, /* F - 70 */ + 14 , 37, /* G - 71 */ + 14 , 44, /* H - 72 */ + 14 , 50, /* I - 73 */ + 14 , 53, /* J - 74 */ + 14 , 54, /* K - 75 */ + 14 , 72, /* L - 76 */ + 14 , 81, /* M - 77 */ + 14 , 112, /* N - 78 */ + 14 , 124, /* O - 79 */ + 14 , 126, /* P - 80 */ + 14 , 137, /* Q - 81 */ + 14 , 138, /* R - 82 */ + 14 , 145, /* S - 83 */ + 14 , 153, /* T - 84 */ + 14 , 159, /* U - 85 */ + 14 , 162, /* V - 86 */ + 14 , 164, /* W - 87 */ + 14 , 166, /* X - 88 */ + 14 , 167, /* Y - 89 */ + 14 , 169, /* Z - 90 */ + 7 , 63, /* [ - 91 */ + 7 , 65, /* \ - 92 */ + 7 , 66, /* ] - 93 */ + 7 , 67, /* ^ - 94 */ + 7 , 68, /* _ - 95 */ + 7 , 72, /* ` - 96 */ + 14 , 2, /* a - 97 */ + 14 , 9, /* b - 98 */ + 14 , 10, /* c - 99 */ + 14 , 26, /* d - 100 */ + 14 , 33, /* e - 101 */ + 14 , 35, /* f - 102 */ + 14 , 37, /* g - 103 */ + 14 , 44, /* h - 104 */ + 14 , 50, /* i - 105 */ + 14 , 53, /* j - 106 */ + 14 , 54, /* k - 107 */ + 14 , 72, /* l - 108 */ + 14 , 81, /* m - 109 */ + 14 , 112, /* n - 110 */ + 14 , 124, /* o - 111 */ + 14 , 126, /* p - 112 */ + 14 , 137, /* q - 113 */ + 14 , 138, /* r - 114 */ + 14 , 145, /* s - 115 */ + 14 , 153, /* t - 116 */ + 14 , 159, /* u - 117 */ + 14 , 162, /* v - 118 */ + 14 , 164, /* w - 119 */ + 14 , 166, /* x - 120 */ + 14 , 167, /* y - 121 */ + 14 , 169, /* z - 122 */ + 7 , 74, /* { - 123 */ + 7 , 76, /* | - 124 */ + 7 , 78, /* } - 125 */ + 7 , 80, /* ~ - 126 */ + 6 , 29, /*  - 127 */ + 6 , 30, /* € - 128 */ + 6 , 31, /*  - 129 */ + 7 , 123, /* ‚ - 130 */ + 14 , 35, /* ƒ - 131 */ + 7 , 127, /* „ - 132 */ + 10 , 21, /* … - 133 */ + 10 , 15, /* † - 134 */ + 10 , 16, /* ‡ - 135 */ + 7 , 67, /* ˆ - 136 */ + 10 , 22, /* ‰ - 137 */ + 14 , 145, /* Š - 138 */ + 7 , 136, /* ‹ - 139 */ + 14 + 16 , 124, /* Œ - 140 */ + 6 , 43, /*  - 141 */ + 6 , 44, /* Ž - 142 */ + 6 , 45, /*  - 143 */ + 6 , 46, /*  - 144 */ + 7 , 121, /* ‘ - 145 */ + 7 , 122, /* ’ - 146 */ + 7 , 125, /* “ - 147 */ + 7 , 126, /* ” - 148 */ + 10 , 17, /* • - 149 */ + 6 , 137, /* – - 150 */ + 6 , 139, /* — - 151 */ + 7 , 93, /* ˜ - 152 */ + 14 , 156, /* ™ - 153 */ + 14 , 145, /* š - 154 */ + 7 , 137, /* › - 155 */ + 14 + 16 , 124, /* œ - 156 */ + 6 , 59, /*  - 157 */ + 6 , 60, /* ž - 158 */ + 14 , 167, /* Ÿ - 159 */ + 7 , 4, /*   - 160 */ + 7 , 81, /* ¡ - 161 */ + 10 , 2, /* ¢ - 162 */ + 10 , 3, /* £ - 163 */ + 10 , 4, /* ¤ - 164 */ + 10 , 5, /* ¥ - 165 */ + 7 , 82, /* ¦ - 166 */ + 10 , 6, /* § - 167 */ + 7 , 83, /* ¨ - 168 */ + 10 , 7, /* © - 169 */ + 14 , 2, /* ª - 170 */ + 8 , 24, /* « - 171 */ + 10 , 8, /* ¬ - 172 */ + 6 , 131, /* ­ - 173 */ + 10 , 9, /* ® - 174 */ + 7 , 84, /* ¯ - 175 */ + 10 , 10, /* ° - 176 */ + 8 , 23, /* ± - 177 */ + 12 , 51, /* ² - 178 */ + 12 , 70, /* ³ - 179 */ + 7 , 85, /* ´ - 180 */ + 10 , 11, /* µ - 181 */ + 10 , 12, /* ¶ - 182 */ + 10 , 13, /* · - 183 */ + 7 , 86, /* ¸ - 184 */ + 12 , 33, /* ¹ - 185 */ + 14 , 124, /* º - 186 */ + 8 , 26, /* » - 187 */ + 12 , 21, /* ¼ - 188 */ + 12 , 25, /* ½ - 189 */ + 12 , 29, /* ¾ - 190 */ + 7 , 87, /* ¿ - 191 */ + 14 , 2, /* À - 192 */ + 14 , 2, /* Á - 193 */ + 14 , 2, /*  - 194 */ + 14 , 2, /* à - 195 */ + 14 , 2, /* Ä - 196 */ + 14 , 2, /* Å - 197 */ + 14 + 16 , 2, /* Æ - 198 */ + 14 , 10, /* Ç - 199 */ + 14 , 33, /* È - 200 */ + 14 , 33, /* É - 201 */ + 14 , 33, /* Ê - 202 */ + 14 , 33, /* Ë - 203 */ + 14 , 50, /* Ì - 204 */ + 14 , 50, /* Í - 205 */ + 14 , 50, /* Î - 206 */ + 14 , 50, /* Ï - 207 */ + 14 , 26, /* Ð - 208 */ + 14 , 112, /* Ñ - 209 */ + 14 , 124, /* Ò - 210 */ + 14 , 124, /* Ó - 211 */ + 14 , 124, /* Ô - 212 */ + 14 , 124, /* Õ - 213 */ + 14 , 124, /* Ö - 214 */ + 8 , 28, /* × - 215 */ + 14 , 124, /* Ø - 216 */ + 14 , 159, /* Ù - 217 */ + 14 , 159, /* Ú - 218 */ + 14 , 159, /* Û - 219 */ + 14 , 159, /* Ü - 220 */ + 14 , 167, /* Ý - 221 */ + 14 + 32 , 153, /* Þ - 222 */ + 14 + 48 , 145, /* ß - 223 */ + 14 , 2, /* à - 224 */ + 14 , 2, /* á - 225 */ + 14 , 2, /* â - 226 */ + 14 , 2, /* ã - 227 */ + 14 , 2, /* ä - 228 */ + 14 , 2, /* å - 229 */ + 14 + 16 , 2, /* æ - 230 */ + 14 , 10, /* ç - 231 */ + 14 , 33, /* è - 232 */ + 14 , 33, /* é - 233 */ + 14 , 33, /* ê - 234 */ + 14 , 33, /* ë - 235 */ + 14 , 50, /* ì - 236 */ + 14 , 50, /* í - 237 */ + 14 , 50, /* î - 238 */ + 14 , 50, /* ï - 239 */ + 14 , 26, /* ð - 240 */ + 14 , 112, /* ñ - 241 */ + 14 , 124, /* ò - 242 */ + 14 , 124, /* ó - 243 */ + 14 , 124, /* ô - 244 */ + 14 , 124, /* õ - 245 */ + 14 , 124, /* ö - 246 */ + 8 , 29, /* ÷ - 247 */ + 14 , 124, /* ø - 248 */ + 14 , 159, /* ù - 249 */ + 14 , 159, /* ú - 250 */ + 14 , 159, /* û - 251 */ + 14 , 159, /* ü - 252 */ + 14 , 167, /* ý - 253 */ + 14 + 32 , 153, /* þ - 254 */ + 14 , 167 /* ÿ - 255 */ }; + +static const unsigned char LCM_Unicode_LUT_2[] = { 33, 44, 145 }; + +#define LCM_Diacritic_Start 131 + +static const unsigned char LCM_Diacritic_LUT[] = { +123, /* ƒ - 131 */ + 2, /* „ - 132 */ + 2, /* … - 133 */ + 2, /* † - 134 */ + 2, /* ‡ - 135 */ + 3, /* ˆ - 136 */ + 2, /* ‰ - 137 */ + 20, /* Š - 138 */ + 2, /* ‹ - 139 */ + 2, /* Œ - 140 */ + 2, /*  - 141 */ + 2, /* Ž - 142 */ + 2, /*  - 143 */ + 2, /*  - 144 */ + 2, /* ‘ - 145 */ + 2, /* ’ - 146 */ + 2, /* “ - 147 */ + 2, /* ” - 148 */ + 2, /* • - 149 */ + 2, /* – - 150 */ + 2, /* — - 151 */ + 2, /* ˜ - 152 */ + 2, /* ™ - 153 */ + 20, /* š - 154 */ + 2, /* › - 155 */ + 2, /* œ - 156 */ + 2, /*  - 157 */ + 2, /* ž - 158 */ + 19, /* Ÿ - 159 */ + 2, /*   - 160 */ + 2, /* ¡ - 161 */ + 2, /* ¢ - 162 */ + 2, /* £ - 163 */ + 2, /* ¤ - 164 */ + 2, /* ¥ - 165 */ + 2, /* ¦ - 166 */ + 2, /* § - 167 */ + 2, /* ¨ - 168 */ + 2, /* © - 169 */ + 3, /* ª - 170 */ + 2, /* « - 171 */ + 2, /* ¬ - 172 */ + 2, /* ­ - 173 */ + 2, /* ® - 174 */ + 2, /* ¯ - 175 */ + 2, /* ° - 176 */ + 2, /* ± - 177 */ + 2, /* ² - 178 */ + 2, /* ³ - 179 */ + 2, /* ´ - 180 */ + 2, /* µ - 181 */ + 2, /* ¶ - 182 */ + 2, /* · - 183 */ + 2, /* ¸ - 184 */ + 2, /* ¹ - 185 */ + 3, /* º - 186 */ + 2, /* » - 187 */ + 2, /* ¼ - 188 */ + 2, /* ½ - 189 */ + 2, /* ¾ - 190 */ + 2, /* ¿ - 191 */ + 15, /* À - 192 */ + 14, /* Á - 193 */ + 18, /*  - 194 */ + 25, /* à - 195 */ + 19, /* Ä - 196 */ + 26, /* Å - 197 */ + 2, /* Æ - 198 */ + 28, /* Ç - 199 */ + 15, /* È - 200 */ + 14, /* É - 201 */ + 18, /* Ê - 202 */ + 19, /* Ë - 203 */ + 15, /* Ì - 204 */ + 14, /* Í - 205 */ + 18, /* Î - 206 */ + 19, /* Ï - 207 */ +104, /* Ð - 208 */ + 25, /* Ñ - 209 */ + 15, /* Ò - 210 */ + 14, /* Ó - 211 */ + 18, /* Ô - 212 */ + 25, /* Õ - 213 */ + 19, /* Ö - 214 */ + 2, /* × - 215 */ + 33, /* Ø - 216 */ + 15, /* Ù - 217 */ + 14, /* Ú - 218 */ + 18, /* Û - 219 */ + 19, /* Ü - 220 */ + 14, /* Ý - 221 */ + 2, /* Þ - 222 */ + 2, /* ß - 223 */ + 15, /* à - 224 */ + 14, /* á - 225 */ + 18, /* â - 226 */ + 25, /* ã - 227 */ + 19, /* ä - 228 */ + 26, /* å - 229 */ + 2, /* æ - 230 */ + 28, /* ç - 231 */ + 15, /* è - 232 */ + 14, /* é - 233 */ + 18, /* ê - 234 */ + 19, /* ë - 235 */ + 15, /* ì - 236 */ + 14, /* í - 237 */ + 18, /* î - 238 */ + 19, /* ï - 239 */ +104, /* ð - 240 */ + 25, /* ñ - 241 */ + 15, /* ò - 242 */ + 14, /* ó - 243 */ + 18, /* ô - 244 */ + 25, /* õ - 245 */ + 19, /* ö - 246 */ + 2, /* ÷ - 247 */ + 33, /* ø - 248 */ + 15, /* ù - 249 */ + 14, /* ú - 250 */ + 18, /* û - 251 */ + 19, /* ü - 252 */ + 14, /* ý - 253 */ + 2, /* þ - 254 */ + 19, /* ÿ - 255 */ +} ; + +/****************************************************************************** + * OLE2NLS_isPunctuation [INTERNAL] + */ +static int OLE2NLS_isPunctuation(unsigned char c) +{ + /* "punctuation character" in this context is a character which is + considered "less important" during word sort comparison. + See LCMapString implementation for the precise definition + of "less important". */ + + return (LCM_Unicode_LUT[-2+2*c]==6); +} + +/****************************************************************************** + * identity [Internal] + */ +static int identity(int c) +{ + return c; +} + +/************************************************************************* + * LCMapString32A [KERNEL32.492] + * + * Convert a string, or generate a sort key from it. + * + * If (mapflags & LCMAP_SORTKEY), the function will generate + * a sort key for the source string. Else, it will convert it + * accordingly to the flags LCMAP_UPPERCASE, LCMAP_LOWERCASE,... + * + * RETURNS + * Error : 0. + * Success : length of the result string. + * + * NOTES + * If called with scrlen = -1, the function will compute the length + * of the 0-terminated string strsrc by itself. + * + * If called with dstlen = 0, returns the buffer length that + * would be required. + * + * NORM_IGNOREWIDTH means to compare ASCII and Unicode characters + * as if they are equal. Since Wine separates ASCII and Unicode into + * separate functions, we shouldn't have to do anything for this flag. + * I added it to the list of flags that don't need a fixme message + * to make MS Word 95 not print several thousand fixme messages for + * this function. + */ +ULONG WINAPI LCMapString32A( + LCID lcid /* locale identifier created with MAKELCID; + LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT are + predefined values. */, + DWORD mapflags /* flags */, + LPCSTR srcstr /* source buffer */, + ULONG srclen /* source length */, + LPSTR dststr /* destination buffer */, + ULONG dstlen /* destination buffer length */) +{ + int i; + + TRACE(string,"(0x%04lx,0x%08lx,%s,%d,%p,%d)\n", + lcid,mapflags,srcstr,srclen,dststr,dstlen); + + if ( ((dstlen!=0) && (dststr==NULL)) || (srcstr==NULL) ) + { + ERR(ole, "(src=%s,dest=%s): Invalid NULL string\n", srcstr, dststr); + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (srclen == -1) + srclen = lstrlen32A(srcstr) + 1 ; /* (include final '\0') */ + + if (mapflags & ~ ( LCMAP_UPPERCASE | LCMAP_LOWERCASE | LCMAP_SORTKEY | + NORM_IGNORECASE | NORM_IGNORENONSPACE | SORT_STRINGSORT | + NORM_IGNOREWIDTH) ) + { + FIXME(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d): " + "unimplemented flags: 0x%08lx\n", + lcid, + mapflags&~(LCMAP_UPPERCASE | LCMAP_LOWERCASE | LCMAP_SORTKEY | + NORM_IGNORECASE | NORM_IGNORENONSPACE | SORT_STRINGSORT | + NORM_IGNOREWIDTH), + srcstr, + srclen, + dststr, + dstlen, + mapflags + ); + } + + if ( !(mapflags & LCMAP_SORTKEY) ) + { + int (*f)(int)=identity; + + if (dstlen==0) + return srclen; /* dstlen=0 means "do nothing but return required length" */ + if (dstlen=0) && (LCM_Diacritic_LUT[ofs]!=2)) + diacritic_len=unicode_len; + } + + if (mapflags & NORM_IGNORECASE) + case_len=0; + if (mapflags & NORM_IGNORENONSPACE) + diacritic_len=0; + + room = 2 * unicode_len /* "unicode" component */ + + diacritic_len /* "diacritic" component */ + + case_len /* "case" component */ + + 4 * delayed_punctuation_len /* punctuation in word sort mode */ + + 4 /* four '\1' separators */ + + 1 ; /* terminal '\0' */ + if (dstlen==0) + return room; + else if (dstlen> 4; + type &= 15; + if (!flag_stringsort && OLE2NLS_isPunctuation(source_char)) + { + UINT16 encrypted_location = (1<<15) + 7 + 4*count; + *delayed_punctuation_component++ = (unsigned char) (encrypted_location>>8); + *delayed_punctuation_component++ = (unsigned char) (encrypted_location&255); + /* big-endian is used here because it lets string comparison be + compatible with numerical comparison */ + + *delayed_punctuation_component++ = type; + *delayed_punctuation_component++ = LCM_Unicode_LUT[-1+2*source_char]; + /* assumption : a punctuation character is never a + double or accented letter */ + } + else + { + dststr[2*count] = type; + dststr[2*count+1] = LCM_Unicode_LUT[-1+2*source_char]; + if (longcode) + { + if (count longcode = 1 + 32 in the first column of LCM_Unicode_LUT --> longcode = 2 + 48 in the first column of LCM_Unicode_LUT --> longcode = 3 */ + } + + if (count=0 ? LCM_Diacritic_LUT[ofs] : 2); + } + count++; + } + } + } + dststr[room-1] = '\0'; + return room; + } +} + +/************************************************************************* + * LCMapString32W [KERNEL32.493] + * + * Convert a string, or generate a sort key from it. + * + * NOTE + * + * See LCMapString32A for documentation + */ +ULONG WINAPI LCMapString32W( + LCID lcid,DWORD mapflags,LPCWSTR srcstr,ULONG srclen,LPWSTR dststr, + ULONG dstlen) +{ + int i; + + TRACE(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d)\n", + lcid,mapflags,srcstr,srclen,dststr,dstlen); + + if ( ((dstlen!=0) && (dststr==NULL)) || (srcstr==NULL) ) + { + ERR(ole, "(src=%p,dst=%p): Invalid NULL string\n", srcstr, dststr); + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (srclen==-1) + srclen = lstrlen32W(srcstr)+1; + if (mapflags & LCMAP_SORTKEY) + { + FIXME(string,"(0x%04lx,0x%08lx,%p,%d,%p,%d): " + "unimplemented flags: 0x%08lx\n", + lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags); + return 0; + } + else + { + int (*f)(int)=identity; + + if (dstlen==0) + return srclen; + if (dstlenwDay, xtime->wHour, xtime->wMinute, xtime->wSecond, + _format, _format, date, datelen); + + if(datelen == 0) { + FIXME(ole, "datelen = 0, returning 255\n"); + return 255; + } + + /* initalize state variables and output buffer */ + inpos = outpos = 0; + count = 0; inquote = 0; Overflow = 0; + type = '\0'; + date[0] = buf[0] = '\0'; + + strcpy(format,_format); + + /* alter the formatstring, while it works for all languages now in wine + its possible that it fails when the time looks like ss:mm:hh as example*/ + if (tflags & (TIME_NOMINUTESORSECONDS)) + { if ((pos = strstr ( format, ":mm"))) + { memcpy ( pos, pos+3, strlen(format)-(pos-format)-2 ); + } + } + if (tflags & (TIME_NOSECONDS)) + { if ((pos = strstr ( format, ":ss"))) + { memcpy ( pos, pos+3, strlen(format)-(pos-format)-2 ); + } + } + + for (inpos = 0;; inpos++) { + /* TRACE(ole, "STATE inpos=%2d outpos=%2d count=%d inquote=%d type=%c buf,date = %c,%c\n", inpos, outpos, count, inquote, type, buf[inpos], date[outpos]); */ + if (inquote) { + if (format[inpos] == '\'') { + if (format[inpos+1] == '\'') { + inpos += 1; + date[outpos++] = '\''; + } else { + inquote = 0; + continue; /* we did nothing to the output */ + } + } else if (format[inpos] == '\0') { + date[outpos++] = '\0'; + if (outpos > datelen) Overflow = 1; + break; + } else { + date[outpos++] = format[inpos]; + if (outpos > datelen) { + Overflow = 1; + date[outpos-1] = '\0'; /* this is the last place where + it's safe to write */ + break; + } + } + } else if ( (count && (format[inpos] != type)) + || count == 4 + || (count == 2 && strchr("ghHmst", type)) ) + { + if (type == 'd') { + if (count == 4) { + GetLocaleInfo32A(locale, + LOCALE_SDAYNAME1 + + xtime->wDayOfWeek - 1, + buf, sizeof(buf)); + } else if (count == 3) { + GetLocaleInfo32A(locale, + LOCALE_SABBREVDAYNAME1 + + xtime->wDayOfWeek - 1, + buf, sizeof(buf)); + } else { + sprintf(buf, dgfmt[count], xtime->wDay); + } + } else if (type == 'M') { + if (count == 3) { + GetLocaleInfo32A(locale, + LOCALE_SABBREVMONTHNAME1 + + xtime->wMonth - 1, + buf, sizeof(buf)); + } else if (count == 4) { + GetLocaleInfo32A(locale, + LOCALE_SMONTHNAME1 + + xtime->wMonth - 1, + buf, sizeof(buf)); + } else { + sprintf(buf, dgfmt[count], xtime->wMonth); + } + } else if (type == 'y') { + if (count == 4) { + sprintf(buf, "%d", xtime->wYear); + } else if (count == 3) { + strcpy(buf, "yyy"); + WARN(ole, "unknown format, c=%c, n=%d\n", type, count); + } else { + sprintf(buf, dgfmt[count], xtime->wYear % 100); + } + } else if (type == 'g') { + if (count == 2) { + FIXME(ole, "LOCALE_ICALENDARTYPE unimp.\n"); + strcpy(buf, "AD"); + } else { + strcpy(buf, "g"); + WARN(ole, "unknown format, c=%c, n=%d\n", type, count); + } + } else if (type == 'h') { + /* gives us hours 1:00 -- 12:00 */ + sprintf(buf, dgfmt[count], (xtime->wHour-1)%12 +1); + } else if (type == 'H') { + /* 24-hour time */ + sprintf(buf, dgfmt[count], xtime->wHour); + } else if ( type == 'm') { + sprintf(buf, dgfmt[count], xtime->wMinute); + } else if ( type == 's') { + sprintf(buf, dgfmt[count], xtime->wSecond); + } else if (type == 't') { + if (count == 1) { + sprintf(buf, "%c", (xtime->wHour < 12) ? 'A' : 'P'); + } else if (count == 2) { + /* sprintf(buf, "%s", (xtime->wHour < 12) ? "AM" : "PM"); */ + GetLocaleInfo32A(locale, + (xtime->wHour<12) + ? LOCALE_S1159 : LOCALE_S2359, + buf, sizeof(buf)); + } + }; + + /* we need to check the next char in the format string + again, no matter what happened */ + inpos--; + + /* add the contents of buf to the output */ + buflen = strlen(buf); + if (outpos + buflen < datelen) { + date[outpos] = '\0'; /* for strcat to hook onto */ + strcat(date, buf); + outpos += buflen; + } else { + date[outpos] = '\0'; + strncat(date, buf, datelen - outpos); + date[datelen - 1] = '\0'; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + WARN(ole, "insufficient buffer\n"); + return 0; + } + + /* reset the variables we used to keep track of this item */ + count = 0; + type = '\0'; + } else if (format[inpos] == '\0') { + /* we can't check for this at the loop-head, because + that breaks the printing of the last format-item */ + date[outpos] = '\0'; + break; + } else if (count) { + /* continuing a code for an item */ + count +=1; + continue; + } else if (strchr("hHmstyMdg", format[inpos])) { + type = format[inpos]; + count = 1; + continue; + } else if (format[inpos] == '\'') { + inquote = 1; + continue; + } else { + date[outpos++] = format[inpos]; + } + /* now deal with a possible buffer overflow */ + if (outpos >= datelen) { + date[datelen - 1] = '\0'; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + } + + if (Overflow) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + }; + + /* finish it off with a string terminator */ + outpos++; + /* sanity check */ + if (outpos > datelen-1) outpos = datelen-1; + date[outpos] = '\0'; + + TRACE(ole, "OLE_GetFormatA returns string '%s', len %d\n", + date, outpos); + return outpos; +} + +/****************************************************************************** + * OLE_GetFormatW [INTERNAL] + */ +static ULONG OLE_GetFormatW(LCID locale, DWORD flags, DWORD tflags, + LPSYSTEMTIME xtime, + LPCWSTR format, + LPWSTR output, ULONG outlen) +{ + ULONG inpos, outpos; + int count, type=0, inquote; + int Overflow; /* loop check */ + WCHAR buf[40]; + int buflen=0; + WCHAR arg0[] = {0}, arg1[] = {'%','d',0}; + WCHAR arg2[] = {'%','0','2','d',0}; + WCHAR *argarr[] = {arg0, arg1, arg2}; + int datevars=0, timevars=0; + + /* make a debug report */ + TRACE(ole, "args: 0x%lx, 0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt:%s (at %p), + %p with max len %d\n", + locale, flags, tflags, + xtime->wDay, xtime->wHour, xtime->wMinute, xtime->wSecond, + debugstr_w(format), format, output, outlen); + + if(outlen == 0) { + FIXME(ole, "outlen = 0, returning 255\n"); + return 255; + } + + /* initialize state variables */ + inpos = outpos = 0; + count = 0; + inquote = Overflow = 0; + /* this is really just a sanity check */ + output[0] = buf[0] = 0; + + /* this loop is the core of the function */ + for (inpos = 0; /* we have several break points */ ; inpos++) { + if (inquote) { + if (format[inpos] == (WCHAR) '\'') { + if (format[inpos+1] == '\'') { + inpos++; + output[outpos++] = '\''; + } else { + inquote = 0; + continue; + } + } else if (format[inpos] == 0) { + output[outpos++] = 0; + if (outpos > outlen) Overflow = 1; + break; /* normal exit (within a quote) */ + } else { + output[outpos++] = format[inpos]; /* copy input */ + if (outpos > outlen) { + Overflow = 1; + output[outpos-1] = 0; + break; + } + } + } else if ( (count && (format[inpos] != type)) + || ( (count==4 && type =='y') || + (count==4 && type =='M') || + (count==4 && type =='d') || + (count==2 && type =='g') || + (count==2 && type =='h') || + (count==2 && type =='H') || + (count==2 && type =='m') || + (count==2 && type =='s') || + (count==2 && type =='t') ) ) { + if (type == 'd') { + if (count == 3) { + GetLocaleInfo32W(locale, + LOCALE_SDAYNAME1 + xtime->wDayOfWeek -1, + buf, sizeof(buf)/sizeof(WCHAR) ); + } else if (count == 3) { + GetLocaleInfo32W(locale, + LOCALE_SABBREVDAYNAME1 + + xtime->wDayOfWeek -1, + buf, sizeof(buf)/sizeof(WCHAR) ); + } else { + wsnprintf32W(buf, 5, argarr[count], xtime->wDay ); + }; + } else if (type == 'M') { + if (count == 4) { + GetLocaleInfo32W(locale, LOCALE_SMONTHNAME1 + + xtime->wMonth -1, buf, + sizeof(buf)/sizeof(WCHAR) ); + } else if (count == 3) { + GetLocaleInfo32W(locale, LOCALE_SABBREVMONTHNAME1 + + xtime->wMonth -1, buf, + sizeof(buf)/sizeof(WCHAR) ); + } else { + wsnprintf32W(buf, 5, argarr[count], xtime->wMonth); + } + } else if (type == 'y') { + if (count == 4) { + wsnprintf32W(buf, 6, argarr[1] /* "%d" */, + xtime->wYear); + } else if (count == 3) { + lstrcpynAtoW(buf, "yyy", 5); + } else { + wsnprintf32W(buf, 6, argarr[count], + xtime->wYear % 100); + } + } else if (type == 'g') { + if (count == 2) { + FIXME(ole, "LOCALE_ICALENDARTYPE unimplemented\n"); + lstrcpynAtoW(buf, "AD", 5); + } else { + /* Win API sez we copy it verbatim */ + lstrcpynAtoW(buf, "g", 5); + } + } else if (type == 'h') { + /* hours 1:00-12:00 --- is this right? */ + wsnprintf32W(buf, 5, argarr[count], + (xtime->wHour-1)%12 +1); + } else if (type == 'H') { + wsnprintf32W(buf, 5, argarr[count], + xtime->wHour); + } else if (type == 'm' ) { + wsnprintf32W(buf, 5, argarr[count], + xtime->wMinute); + } else if (type == 's' ) { + wsnprintf32W(buf, 5, argarr[count], + xtime->wSecond); + } else if (type == 't') { + GetLocaleInfo32W(locale, (xtime->wHour < 12) ? + LOCALE_S1159 : LOCALE_S2359, + buf, sizeof(buf) ); + if (count == 1) { + buf[1] = 0; + } +} + + /* no matter what happened, we need to check this next + character the next time we loop through */ + inpos--; + + /* cat buf onto the output */ + outlen = lstrlen32W(buf); + if (outpos + buflen < outlen) { + output[outpos] = 0; /* a "hook" for strcat */ + lstrcat32W(output, buf); + outpos += buflen; + } else { + output[outpos] = 0; + lstrcatn32W(output, buf, outlen - outpos); + output[outlen - 1] = 0; + Overflow = 1; + break; /* Abnormal exit */ + } + + /* reset the variables we used this time */ + count = 0; + type = '\0'; + } else if (format[inpos] == 0) { + /* we can't check for this at the beginning, because that + would keep us from printing a format spec that ended the + string */ + output[outpos] = 0; + break; /* NORMAL EXIT */ + } else if (count) { + /* how we keep track of the middle of a format spec */ + count++; + continue; + } else if ( (datevars && (format[inpos]=='d' || + format[inpos]=='M' || + format[inpos]=='y' || + format[inpos]=='g') ) || + (timevars && (format[inpos]=='H' || + format[inpos]=='h' || + format[inpos]=='m' || + format[inpos]=='s' || + format[inpos]=='t') ) ) { + type = format[inpos]; + count = 1; + continue; + } else if (format[inpos] == '\'') { + inquote = 1; + continue; + } else { + /* unquoted literals */ + output[outpos++] = format[inpos]; + } + } + + if (Overflow) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + WARN(ole, " buffer overflow\n"); + }; + + /* final string terminator and sanity check */ + outpos++; + if (outpos > outlen-1) outpos = outlen-1; + output[outpos] = '0'; + + TRACE(ole, " returning %s\n", debugstr_w(output)); + + return (!Overflow) ? outlen : 0; + +} + + +/****************************************************************************** + * GetDateFormat32A [KERNEL32.310] + * Makes an ASCII string of the date + * + * This function uses format to format the date, or, if format + * is NULL, uses the default for the locale. format is a string + * of literal fields and characters as follows: + * + * - d single-digit (no leading zero) day (of month) + * - dd two-digit day (of month) + * - ddd short day-of-week name + * - dddd long day-of-week name + * - M single-digit month + * - MM two-digit month + * - MMM short month name + * - MMMM full month name + * - y two-digit year, no leading 0 + * - yy two-digit year + * - yyyy four-digit year + * - gg era string + * + */ +ULONG WINAPI GetDateFormat32A(LCID locale,DWORD flags, + LPSYSTEMTIME xtime, + LPCSTR format, LPSTR date,ULONG datelen) +{ + + char format_buf[40]; + LPCSTR thisformat; + SYSTEMTIME t; + LPSYSTEMTIME thistime; + LCID thislocale; + ULONG ret; + + TRACE(ole,"(0x%04lx,0x%08lx,%p,%s,%p,%d)\n", + locale,flags,xtime,format,date,datelen); + + if (!locale) { + locale = LOCALE_SYSTEM_DEFAULT; + }; + + if (locale == LOCALE_SYSTEM_DEFAULT) { + thislocale = GetSystemDefaultLCID(); + } else if (locale == LOCALE_USER_DEFAULT) { + thislocale = GetUserDefaultLCID(); + } else { + thislocale = locale; + }; + + if (xtime == NULL) { + GetSystemTime(&t); + thistime = &t; + } else { + thistime = xtime; + }; + + if (format == NULL) { + GetLocaleInfo32A(thislocale, ((flags&DATE_LONGDATE) + ? LOCALE_SLONGDATE + : LOCALE_SSHORTDATE), + format_buf, sizeof(format_buf)); + thisformat = format_buf; + } else { + thisformat = format; + }; + + + ret = OLE_GetFormatA(thislocale, flags, 0, thistime, thisformat, + date, datelen); + + + TRACE(ole, + "GetDateFormat32A() returning %d, with data=%s\n", + ret, date); + return ret; +} + +/****************************************************************************** + * GetDateFormat32W [KERNEL32.311] + * Makes a Unicode string of the date + * + * Acts the same as GetDateFormat32A(), except that it's Unicode. + * Accepts & returns sizes as counts of Unicode characters. + * + */ +ULONG WINAPI GetDateFormat32W(LCID locale,DWORD flags, + LPSYSTEMTIME xtime, + LPCWSTR format, + LPWSTR date, INT32 datelen) +{ + unsigned short datearr[] = {'1','9','9','4','-','1','-','1',0}; + + FIXME(ole, "STUB (should call OLE_GetFormatW)\n"); + lstrcpyn32W(date, datearr, datelen); + return ( datelen < 9) ? datelen : 9; + + +} + +/************************************************************************** + * EnumDateFormats32A (KERNEL32.198) + */ +BOOL32 WINAPI EnumDateFormats32A( + DATEFMT_ENUMPROC32A lpDateFmtEnumProc, LCID Locale, DWORD dwFlags) +{ + FIXME(ole, "Only US English supported\n"); + + if(!lpDateFmtEnumProc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + switch(dwFlags) + { + case DATE_SHORTDATE: + if(!(*lpDateFmtEnumProc)("M/d/yy")) return TRUE; + if(!(*lpDateFmtEnumProc)("M/d/yyyy")) return TRUE; + if(!(*lpDateFmtEnumProc)("MM/dd/yy")) return TRUE; + if(!(*lpDateFmtEnumProc)("MM/dd/yyyy")) return TRUE; + if(!(*lpDateFmtEnumProc)("yy/MM/dd")) return TRUE; + if(!(*lpDateFmtEnumProc)("dd-MMM-yy")) return TRUE; + return TRUE; + case DATE_LONGDATE: + if(!(*lpDateFmtEnumProc)("dddd, MMMM dd, yyyy")) return TRUE; + if(!(*lpDateFmtEnumProc)("MMMM dd, yyyy")) return TRUE; + if(!(*lpDateFmtEnumProc)("dddd, dd MMMM, yyyy")) return TRUE; + if(!(*lpDateFmtEnumProc)("dd MMMM, yyyy")) return TRUE; + return TRUE; + default: + FIXME(ole, "Unknown date format (%ld)\n", dwFlags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +} + +/************************************************************************** + * EnumDateFormats32W (KERNEL32.199) + */ +BOOL32 WINAPI EnumDateFormats32W( + DATEFMT_ENUMPROC32W lpDateFmtEnumProc, LCID Locale, DWORD dwFlags) +{ + FIXME(ole, "(%p, %ld, %ld): stub\n", lpDateFmtEnumProc, Locale, dwFlags); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/************************************************************************** + * EnumTimeFormats32A (KERNEL32.210) + */ +BOOL32 WINAPI EnumTimeFormats32A( + TIMEFMT_ENUMPROC32A lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags) +{ + FIXME(ole, "Only US English supported\n"); + + if(!lpTimeFmtEnumProc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(dwFlags) + { + FIXME(ole, "Unknown time format (%ld)\n", dwFlags); + } + + if(!(*lpTimeFmtEnumProc)("h:mm:ss tt")) return TRUE; + if(!(*lpTimeFmtEnumProc)("hh:mm:ss tt")) return TRUE; + if(!(*lpTimeFmtEnumProc)("H:mm:ss")) return TRUE; + if(!(*lpTimeFmtEnumProc)("HH:mm:ss")) return TRUE; + + return TRUE; +} + +/************************************************************************** + * EnumTimeFormats32W (KERNEL32.211) + */ +BOOL32 WINAPI EnumTimeFormats32W( + TIMEFMT_ENUMPROC32W lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags) +{ + FIXME(ole, "(%p,%ld,%ld): stub", lpTimeFmtEnumProc, Locale, dwFlags); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/************************************************************************** + * GetNumberFormat32A (KERNEL32.355) + */ +INT32 WINAPI GetNumberFormat32A(LCID locale, DWORD dwflags, + LPCSTR lpvalue, const NUMBERFMT32A * lpFormat, + LPSTR lpNumberStr, int cchNumber) +{ + FIXME(file,"%s: stub, no reformating done\n",lpvalue); + + lstrcpyn32A( lpNumberStr, lpvalue, cchNumber ); + return cchNumber? lstrlen32A( lpNumberStr ) : 0; +} +/************************************************************************** + * GetNumberFormat32W (KERNEL32.xxx) + */ +INT32 WINAPI GetNumberFormat32W(LCID locale, DWORD dwflags, + LPCWSTR lpvalue, const NUMBERFMT32W * lpFormat, + LPWSTR lpNumberStr, int cchNumber) +{ + FIXME(file,"%s: stub, no reformating done\n",debugstr_w(lpvalue)); + + lstrcpyn32W( lpNumberStr, lpvalue, cchNumber ); + return cchNumber? lstrlen32W( lpNumberStr ) : 0; +} +/****************************************************************************** + * OLE2NLS_CheckLocale [intern] + */ +static LCID OLE2NLS_CheckLocale (LCID locale) +{ + if (!locale) + { locale = LOCALE_SYSTEM_DEFAULT; + } + + if (locale == LOCALE_SYSTEM_DEFAULT) + { return GetSystemDefaultLCID(); + } + else if (locale == LOCALE_USER_DEFAULT) + { return GetUserDefaultLCID(); + } + else + { return locale; + } +} +/****************************************************************************** + * GetTimeFormat32A [KERNEL32.422] + * Makes an ASCII string of the time + * + * Formats date according to format, or locale default if format is + * NULL. The format consists of literal characters and fields as follows: + * + * h hours with no leading zero (12-hour) + * hh hours with full two digits + * H hours with no leading zero (24-hour) + * HH hours with full two digits + * m minutes with no leading zero + * mm minutes with full two digits + * s seconds with no leading zero + * ss seconds with full two digits + * t time marker (A or P) + * tt time marker (AM, PM) + * + */ +INT32 WINAPI +GetTimeFormat32A(LCID locale, /* in */ + DWORD flags, /* in */ + LPSYSTEMTIME xtime, /* in */ + LPCSTR format, /* in */ + LPSTR timestr, /* out */ + INT32 timelen /* in */) +{ char format_buf[40]; + LPCSTR thisformat; + SYSTEMTIME t; + LPSYSTEMTIME thistime; + LCID thislocale=0; + DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */ + INT32 ret; + + TRACE(ole,"GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale,flags,xtime,format,timestr,timelen); + + thislocale = OLE2NLS_CheckLocale ( locale ); + + if ( flags & (TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT )) + { FIXME(ole,"TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n"); + } + + flags &= (TIME_NOSECONDS | TIME_NOMINUTESORSECONDS); /* mask for OLE_GetFormatA*/ + + if (format == NULL) + { if (flags & LOCALE_NOUSEROVERRIDE) /*use system default*/ + { thislocale = GetSystemDefaultLCID(); + } + GetLocaleInfo32A(thislocale, thisflags, format_buf, sizeof(format_buf)); + thisformat = format_buf; + } + else + { thisformat = format; + } + + if (xtime == NULL) /* NULL means use the current local time*/ + { GetSystemTime(&t); + thistime = &t; + } + else + { thistime = xtime; + } + ret = OLE_GetFormatA(thislocale, thisflags, flags, thistime, thisformat, + timestr, timelen); + return ret; +} + + +/****************************************************************************** + * GetTimeFormat32W [KERNEL32.423] + * Makes a Unicode string of the time + */ +INT32 WINAPI +GetTimeFormat32W(LCID locale, /* in */ + DWORD flags, /* in */ + LPSYSTEMTIME xtime, /* in */ + LPCWSTR format, /* in */ + LPWSTR timestr, /* out */ + INT32 timelen /* in */) +{ WCHAR format_buf[40]; + LPCWSTR thisformat; + SYSTEMTIME t; + LPSYSTEMTIME thistime; + LCID thislocale=0; + DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */ + INT32 ret; + + TRACE(ole,"GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale,flags, + xtime,debugstr_w(format),timestr,timelen); + + thislocale = OLE2NLS_CheckLocale ( locale ); + + if ( flags & (TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT )) + { FIXME(ole,"TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n"); + } + + flags &= (TIME_NOSECONDS | TIME_NOMINUTESORSECONDS); /* mask for OLE_GetFormatA*/ + + if (format == NULL) + { if (flags & LOCALE_NOUSEROVERRIDE) /*use system default*/ + { thislocale = GetSystemDefaultLCID(); + } + GetLocaleInfo32W(thislocale, thisflags, format_buf, 40); + thisformat = format_buf; + } + else + { thisformat = format; + } + + if (xtime == NULL) /* NULL means use the current local time*/ + { GetSystemTime(&t); + thistime = &t; + } + else + { thistime = xtime; + } + + ret = OLE_GetFormatW(thislocale, thisflags, flags, thistime, thisformat, + timestr, timelen); + return ret; +} diff --git a/lib/kernel32/nls/plk.nls b/lib/kernel32/nls/plk.nls new file mode 100644 index 0000000..b81bfee --- /dev/null +++ b/lib/kernel32/nls/plk.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Poland + * (Polish strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0415") +LOCVAL(LOCALE_SLANGUAGE,"Polski") +LOCVAL(LOCALE_SENGLANGUAGE,"Polish") +LOCVAL(LOCALE_SABBREVLANGNAME, "plk") +LOCVAL(LOCALE_SNATIVELANGNAME,"Polski") +LOCVAL(LOCALE_ICOUNTRY,"49") +LOCVAL(LOCALE_SCOUNTRY,"Polska") +LOCVAL(LOCALE_SENGCOUNTRY,"Poland") +LOCVAL(LOCALE_SABBREVCTRYNAME,"POL") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Polska") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0415") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"49") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"852") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND," ") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"z\xB3") +LOCVAL(LOCALE_SINTLSYMBOL,"PLZ") +/* LOCVAL(LOCALE_SMONDECIMALSEP) */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP) */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159) */ +/* LOCVAL(LOCALE_S2359) */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Poniedzia\263ek") +LOCVAL(LOCALE_SDAYNAME2,"Wtorek") +LOCVAL(LOCALE_SDAYNAME3,"\214roda") +LOCVAL(LOCALE_SDAYNAME4,"Czwartek") +LOCVAL(LOCALE_SDAYNAME5,"Pi\271tek") +LOCVAL(LOCALE_SDAYNAME6,"Sobota") +LOCVAL(LOCALE_SDAYNAME7,"Niedziela") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Po") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Wt") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Sr") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Cz") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Pt") +LOCVAL(LOCALE_SABBREVDAYNAME6,"So") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Ni") + +LOCVAL(LOCALE_SMONTHNAME1,"Stycze\xF1") +LOCVAL(LOCALE_SMONTHNAME2,"Luty") +LOCVAL(LOCALE_SMONTHNAME3,"Marzec") +LOCVAL(LOCALE_SMONTHNAME4,"Kwiecie\xF1") +LOCVAL(LOCALE_SMONTHNAME5,"Maj") +LOCVAL(LOCALE_SMONTHNAME6,"Czerwiec") +LOCVAL(LOCALE_SMONTHNAME7,"Lipiec") +LOCVAL(LOCALE_SMONTHNAME8,"Sierpie\xF1") +LOCVAL(LOCALE_SMONTHNAME9,"Wrzesie\xF1") +LOCVAL(LOCALE_SMONTHNAME10,"Pa\237dziernik") +LOCVAL(LOCALE_SMONTHNAME11,"Listapad") +LOCVAL(LOCALE_SMONTHNAME12,"Grudzie\xF1") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Sty") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Lut") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Kwi") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Cze") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Lip") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Sie") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Wrz") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Pa\237") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Lis") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Gru") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +/* LOCVAL(LOCALE_SPOSITIVESIGN) */ +/* LOCVAL(LOCALE_SNEGATIVESIGN) */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN) */ +/* LOCVAL(LOCALE_INEGSIGNPOSN) */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES) */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES) */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE) */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"pl") +LOCVAL(LOCALE_SISO3166CTRYNAME,"PL") + +/* kalendarz gregoria?dski */ diff --git a/lib/kernel32/nls/prc.nls b/lib/kernel32/nls/prc.nls new file mode 100644 index 0000000..b46252c --- /dev/null +++ b/lib/kernel32/nls/prc.nls @@ -0,0 +1,110 @@ +/* + * OLE2NLS library + * People's republic of China + */ + +/* LOCVAL(LOCALE_ILANGUAGE,"") */ +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +/* LOCVAL(LOCALE_SENGLANGUAGE,"People's republic of China") */ +LOCVAL(LOCALE_SABBREVLANGNAME,"prc") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +/* LOCVAL(LOCALE_SENGCOUNTRY,"") */ +/* LOCVAL(LOCALE_SABBREVCTRYNAME,"") */ +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +/* LOCVAL(LOCALE_IDEFAULTLANGUAGE,"") */ +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +/* LOCVAL(LOCALE_SINTLSYMBOL) */ +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +/* LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +/* LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +/* LOCVAL(LOCALE_ICALENDARTYPE) */ +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"Ma") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"Ti") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"On") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"To") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"Lø") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"Sø") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ + diff --git a/lib/kernel32/nls/ptb.nls b/lib/kernel32/nls/ptb.nls new file mode 100644 index 0000000..e2a08e0 --- /dev/null +++ b/lib/kernel32/nls/ptb.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Brazil + */ + +LOCVAL(LOCALE_ILANGUAGE, "0416") +LOCVAL(LOCALE_SLANGUAGE, "Portugu\352s (Brasil)") +LOCVAL(LOCALE_SENGLANGUAGE, "Protuguese") +LOCVAL(LOCALE_SABBREVLANGNAME, "ptb") +LOCVAL(LOCALE_SNATIVELANGNAME, "Portugu\352s") +LOCVAL(LOCALE_ICOUNTRY, "55") +LOCVAL(LOCALE_SCOUNTRY, "Brasil") +LOCVAL(LOCALE_SENGCOUNTRY, "Brazil") +LOCVAL(LOCALE_SABBREVCTRYNAME, "BRA") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Brasil") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0416") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "55") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ";") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ",") +LOCVAL(LOCALE_STHOUSAND, ".") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "BRC") +LOCVAL(LOCALE_SMONDECIMALSEP, ",") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Segunda-feira") +LOCVAL(LOCALE_SDAYNAME2, "Ter\347a-feira") +LOCVAL(LOCALE_SDAYNAME3, "Quarta-feira") +LOCVAL(LOCALE_SDAYNAME4, "Quinta-feira") +LOCVAL(LOCALE_SDAYNAME5, "Sexta-feira") +LOCVAL(LOCALE_SDAYNAME6, "S\341bado") +LOCVAL(LOCALE_SDAYNAME7, "Domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Seg") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Ter") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Qua") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Qui") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Sex") +LOCVAL(LOCALE_SABBREVDAYNAME6, "S\341b") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Dom") + +LOCVAL(LOCALE_SMONTHNAME1, "Janeiro") +LOCVAL(LOCALE_SMONTHNAME2, "Fevereiro") +LOCVAL(LOCALE_SMONTHNAME3, "Mar\347o") +LOCVAL(LOCALE_SMONTHNAME4, "Abril") +LOCVAL(LOCALE_SMONTHNAME5, "Maio") +LOCVAL(LOCALE_SMONTHNAME6, "Junho") +LOCVAL(LOCALE_SMONTHNAME7, "Julho") +LOCVAL(LOCALE_SMONTHNAME8, "Agosto") +LOCVAL(LOCALE_SMONTHNAME9, "Setembro") +LOCVAL(LOCALE_SMONTHNAME10, "Outubro") +LOCVAL(LOCALE_SMONTHNAME11, "Novembro") +LOCVAL(LOCALE_SMONTHNAME12, "Dezembro") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Fev") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Set") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Out") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"pt") +LOCVAL(LOCALE_SISO3166CTRYNAME,"BR") + +/* Calend?rio gregoriano */ diff --git a/lib/kernel32/nls/ptg.nls b/lib/kernel32/nls/ptg.nls new file mode 100644 index 0000000..9815ace --- /dev/null +++ b/lib/kernel32/nls/ptg.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Portugal + * + * (portuguese strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE, "0816") +LOCVAL(LOCALE_SLANGUAGE, "Portugu\352s") +LOCVAL(LOCALE_SENGLANGUAGE, "Protuguese") +LOCVAL(LOCALE_SABBREVLANGNAME, "ptg") +LOCVAL(LOCALE_SNATIVELANGNAME, "Portugu\352s") +LOCVAL(LOCALE_ICOUNTRY, "351") +LOCVAL(LOCALE_SCOUNTRY, "Portugal") +LOCVAL(LOCALE_SENGCOUNTRY, "Portugal") +LOCVAL(LOCALE_SABBREVCTRYNAME, "PRT") +LOCVAL(LOCALE_SNATIVECTRYNAME, "Portugal") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "0416") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "351") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "1252") +LOCVAL(LOCALE_SLIST, ";") +LOCVAL(LOCALE_IMEASURE, "1") +LOCVAL(LOCALE_SDECIMAL, ",") +LOCVAL(LOCALE_STHOUSAND, ".") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "$") +LOCVAL(LOCALE_SINTLSYMBOL, "USD") +LOCVAL(LOCALE_SMONDECIMALSEP, ",") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "0") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "dd/MM/yy") +LOCVAL(LOCALE_SLONGDATE, "dddd, MMMM dd, yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "h:mm:ss tt") +LOCVAL(LOCALE_IDATE, "0") +LOCVAL(LOCALE_ILDATE, "0") +LOCVAL(LOCALE_ITIME, "0") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "6") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "Segunda") +LOCVAL(LOCALE_SDAYNAME2, "Ter\347a") +LOCVAL(LOCALE_SDAYNAME3, "Quarta") +LOCVAL(LOCALE_SDAYNAME4, "Quinta") +LOCVAL(LOCALE_SDAYNAME5, "Sexta") +LOCVAL(LOCALE_SDAYNAME6, "S\341bado") +LOCVAL(LOCALE_SDAYNAME7, "Domingo") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "Seg") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Ter") +LOCVAL(LOCALE_SABBREVDAYNAME3, "Qua") +LOCVAL(LOCALE_SABBREVDAYNAME4, "Qui") +LOCVAL(LOCALE_SABBREVDAYNAME5, "Sex") +LOCVAL(LOCALE_SABBREVDAYNAME6, "S\341b") +LOCVAL(LOCALE_SABBREVDAYNAME7, "Dom") + +LOCVAL(LOCALE_SMONTHNAME1, "Janeiro") +LOCVAL(LOCALE_SMONTHNAME2, "Fevereiro") +LOCVAL(LOCALE_SMONTHNAME3, "Mar\347o") +LOCVAL(LOCALE_SMONTHNAME4, "Abril") +LOCVAL(LOCALE_SMONTHNAME5, "Maio") +LOCVAL(LOCALE_SMONTHNAME6, "Junho") +LOCVAL(LOCALE_SMONTHNAME7, "Julho") +LOCVAL(LOCALE_SMONTHNAME8, "Agosto") +LOCVAL(LOCALE_SMONTHNAME9, "Setembro") +LOCVAL(LOCALE_SMONTHNAME10, "Outubro") +LOCVAL(LOCALE_SMONTHNAME11, "Novembro") +LOCVAL(LOCALE_SMONTHNAME12, "Dezembro") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "Fev") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "Abr") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Ago") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "Set") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "Out") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "Dez") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "0") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"pt") +LOCVAL(LOCALE_SISO3166CTRYNAME,"PT") + diff --git a/lib/kernel32/nls/rom.nls b/lib/kernel32/nls/rom.nls new file mode 100644 index 0000000..10de1db --- /dev/null +++ b/lib/kernel32/nls/rom.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Romania + * (Romanian strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0418") +LOCVAL(LOCALE_SLANGUAGE,"Româna") +LOCVAL(LOCALE_SENGLANGUAGE,"Romanian") +LOCVAL(LOCALE_SABBREVLANGNAME,"rom") +LOCVAL(LOCALE_SNATIVELANGNAME,"Româna") +LOCVAL(LOCALE_ICOUNTRY,"40") +LOCVAL(LOCALE_SCOUNTRY,"România") +LOCVAL(LOCALE_SENGCOUNTRY,"Romania") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ROM") +LOCVAL(LOCALE_SNATIVECTRYNAME,"România") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0418") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"40") +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +LOCVAL(LOCALE_SLIST,";") +/* LOCVAL(LOCALE_IMEASURE,"") */ +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS,"2") +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"LEI") +LOCVAL(LOCALE_SINTLSYMBOL,"ROL") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING,"3;0") +LOCVAL(LOCALE_ICURRDIGITS,"0") +LOCVAL(LOCALE_IINTLCURRDIGITS,"2") +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd.MM.yy") +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +LOCVAL(LOCALE_STIMEFORMAT,"HH:mm:ss") +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE,"1") */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"luni") +LOCVAL(LOCALE_SDAYNAME2,"marþi") +LOCVAL(LOCALE_SDAYNAME3,"miercuri") +LOCVAL(LOCALE_SDAYNAME4,"joi") +LOCVAL(LOCALE_SDAYNAME5,"vineri") +LOCVAL(LOCALE_SDAYNAME6,"sîmbãtã") +LOCVAL(LOCALE_SDAYNAME7,"duminicã") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"L ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ma") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Mi") +LOCVAL(LOCALE_SABBREVDAYNAME4,"J ") +LOCVAL(LOCALE_SABBREVDAYNAME5,"V ") +LOCVAL(LOCALE_SABBREVDAYNAME6,"S ") +LOCVAL(LOCALE_SABBREVDAYNAME7,"D ") + +LOCVAL(LOCALE_SMONTHNAME1,"ianuarie") +LOCVAL(LOCALE_SMONTHNAME2,"februarie") +LOCVAL(LOCALE_SMONTHNAME3,"martie") +LOCVAL(LOCALE_SMONTHNAME4,"aprilie") +LOCVAL(LOCALE_SMONTHNAME5,"mai") +LOCVAL(LOCALE_SMONTHNAME6,"iunie") +LOCVAL(LOCALE_SMONTHNAME7,"iulie") +LOCVAL(LOCALE_SMONTHNAME8,"august") +LOCVAL(LOCALE_SMONTHNAME9,"septembrie") +LOCVAL(LOCALE_SMONTHNAME10,"octombrie") +LOCVAL(LOCALE_SMONTHNAME11,"noiembrie") +LOCVAL(LOCALE_SMONTHNAME12,"decembrie") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Ian") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Mai") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Iun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Iul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Oct") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "1") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "1") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "0") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ro") +LOCVAL(LOCALE_SISO3166CTRYNAME,"RO") + +/* Gregorian calendar */ diff --git a/lib/kernel32/nls/rus.nls b/lib/kernel32/nls/rus.nls new file mode 100644 index 0000000..bf81cfc --- /dev/null +++ b/lib/kernel32/nls/rus.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Russia + * (russian strings in koi8-r) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0419") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Russian") +LOCVAL(LOCALE_SABBREVLANGNAME,"rus") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"òÏÓÓÉÑ") +LOCVAL(LOCALE_SENGCOUNTRY,"Russia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"RUS") +LOCVAL(LOCALE_SNATIVECTRYNAME,"òÏÓÓÉÑ") +/* LOCVAL(LOCALE_IDEFAULTLANGUAGE,"") */ +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"866") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1251") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +LOCVAL(LOCALE_SCURRENCY,"ÒÕÂ") +LOCVAL(LOCALE_SINTLSYMBOL,"RUR") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ðÏÎÅÄÅÌØÎÉË") +LOCVAL(LOCALE_SDAYNAME2,"÷ÔÏÒÎÉË") +LOCVAL(LOCALE_SDAYNAME3,"óÒÅÄÁ") +LOCVAL(LOCALE_SDAYNAME4,"þÅÔ×ÅÒÇ") +LOCVAL(LOCALE_SDAYNAME5,"ðÑÔÎÉÃÁ") +LOCVAL(LOCALE_SDAYNAME6,"óÕÂÂÏÔÁ") +LOCVAL(LOCALE_SDAYNAME7,"÷ÏÓËÒÅÓÅÎØÅ") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"ðÎÄ") +LOCVAL(LOCALE_SABBREVDAYNAME2,"÷ÔÒ") +LOCVAL(LOCALE_SABBREVDAYNAME3,"óÒÄ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"þÔ×") +LOCVAL(LOCALE_SABBREVDAYNAME5,"ðÔÎ") +LOCVAL(LOCALE_SABBREVDAYNAME6,"óÕÂ") +LOCVAL(LOCALE_SABBREVDAYNAME7,"÷ÓË") + +LOCVAL(LOCALE_SMONTHNAME1,"ñÎ×ÁÒØ") +LOCVAL(LOCALE_SMONTHNAME2,"æÅ×ÒÁÌØ") +LOCVAL(LOCALE_SMONTHNAME3,"íÁÒÔ") +LOCVAL(LOCALE_SMONTHNAME4,"áÐÒÅÌØ") +LOCVAL(LOCALE_SMONTHNAME5,"íÁÊ") +LOCVAL(LOCALE_SMONTHNAME6,"éÀÎØ") +LOCVAL(LOCALE_SMONTHNAME7,"éÀÌØ") +LOCVAL(LOCALE_SMONTHNAME8,"á×ÇÕÓÔ") +LOCVAL(LOCALE_SMONTHNAME9,"óÅÎÔÑÂÒØ") +LOCVAL(LOCALE_SMONTHNAME10,"ïËÔÑÂÒØ") +LOCVAL(LOCALE_SMONTHNAME11,"îÏÑÂÒØ") +LOCVAL(LOCALE_SMONTHNAME12,"äÅËÁÂÒØ") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"ñÎ×") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"æÅ×") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"íÁÒ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"áÐÒ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"íÁÊ") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"éÀÎ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"éÀÌ") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"á×Ç") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"óÅÎ") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"ïËÔ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"îÏÑ") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"äÅË") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"ru") +LOCVAL(LOCALE_SISO3166CTRYNAME,"RU") + +/* calendario gregoriano */ diff --git a/lib/kernel32/nls/sgp.nls b/lib/kernel32/nls/sgp.nls new file mode 100644 index 0000000..7ca7e4c --- /dev/null +++ b/lib/kernel32/nls/sgp.nls @@ -0,0 +1,110 @@ +/* + * OLE2NLS library + * Chinese (Singapore) + */ + +/* LOCVAL(LOCALE_ILANGUAGE,"") */ +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +/* LOCVAL(LOCALE_SENGLANGUAGE,"Chinese (Singapore)") */ +LOCVAL(LOCALE_SABBREVLANGNAME,"sgp") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +/* LOCVAL(LOCALE_SENGCOUNTRY,"") */ +/* LOCVAL(LOCALE_SABBREVCTRYNAME,"") */ +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +/* LOCVAL(LOCALE_IDEFAULTLANGUAGE,"") */ +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +/* LOCVAL(LOCALE_SINTLSYMBOL) */ +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +/* LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +/* LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +/* LOCVAL(LOCALE_ICALENDARTYPE) */ +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"Ma") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"Ti") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"On") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"To") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"Lø") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"Sø") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ + diff --git a/lib/kernel32/nls/sky.nls b/lib/kernel32/nls/sky.nls new file mode 100644 index 0000000..b027952 --- /dev/null +++ b/lib/kernel32/nls/sky.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Slovakia + * (Slovakian strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"041b") +LOCVAL(LOCALE_SLANGUAGE,"Slovenèina") +LOCVAL(LOCALE_SENGLANGUAGE,"Slovak") +LOCVAL(LOCALE_SABBREVLANGNAME,"sky") +LOCVAL(LOCALE_SNATIVELANGNAME,"slovenèina") +LOCVAL(LOCALE_ICOUNTRY, "42") +LOCVAL(LOCALE_SCOUNTRY,"Slovensko") +LOCVAL(LOCALE_SENGCOUNTRY,"Slovakia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SVK") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Slovenská Republika") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"041b") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "42") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"895") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +LOCVAL(LOCALE_IDEFAULTMACCODEPAGE,"") +LOCVAL(LOCALE_SLIST, ";") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ",") +LOCVAL(LOCALE_STHOUSAND, " ") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "1") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY, "Sk") +LOCVAL(LOCALE_SINTLSYMBOL,"SKK") +LOCVAL(LOCALE_SMONDECIMALSEP, ",") +LOCVAL(LOCALE_SMONTHOUSANDSEP, " ") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "3") +LOCVAL(LOCALE_INEGCURR, "8") +LOCVAL(LOCALE_SDATE, ".") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "d.M.yyyy") +LOCVAL(LOCALE_SLONGDATE, "d. MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "H:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME,"1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "1") +LOCVAL(LOCALE_ITLZERO,"1") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "0") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") + +LOCVAL(LOCALE_SDAYNAME1, "pondelok") +LOCVAL(LOCALE_SDAYNAME2, "utorok") +LOCVAL(LOCALE_SDAYNAME3, "streda") +LOCVAL(LOCALE_SDAYNAME4, "štvrtok") +LOCVAL(LOCALE_SDAYNAME5, "piatok") +LOCVAL(LOCALE_SDAYNAME6, "sobota") +LOCVAL(LOCALE_SDAYNAME7, "nede¾a") + +LOCVAL(LOCALE_SABBREVDAYNAME1, "po") +LOCVAL(LOCALE_SABBREVDAYNAME2, "ut") +LOCVAL(LOCALE_SABBREVDAYNAME3, "st") +LOCVAL(LOCALE_SABBREVDAYNAME4, "št") +LOCVAL(LOCALE_SABBREVDAYNAME5, "pi") +LOCVAL(LOCALE_SABBREVDAYNAME6, "so") +LOCVAL(LOCALE_SABBREVDAYNAME7, "ne") + +LOCVAL(LOCALE_SMONTHNAME1, "január") +LOCVAL(LOCALE_SMONTHNAME2, "február") +LOCVAL(LOCALE_SMONTHNAME3, "marec") +LOCVAL(LOCALE_SMONTHNAME4, "apríl") +LOCVAL(LOCALE_SMONTHNAME5, "máj") +LOCVAL(LOCALE_SMONTHNAME6, "jún") +LOCVAL(LOCALE_SMONTHNAME7, "júl") +LOCVAL(LOCALE_SMONTHNAME8, "august") +LOCVAL(LOCALE_SMONTHNAME9, "september") +LOCVAL(LOCALE_SMONTHNAME10, "október") +LOCVAL(LOCALE_SMONTHNAME11, "november") +LOCVAL(LOCALE_SMONTHNAME12, "december") +LOCVAL(LOCALE_SMONTHNAME13, "") + +LOCVAL(LOCALE_SABBREVMONTHNAME1, "I") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "II") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "III") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "IV") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "V") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "VI") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "VII") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "VIII") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "IX") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "X") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "XI") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "XII") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "1") +LOCVAL(LOCALE_INEGSIGNPOSN, "1") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "0") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "1") +LOCVAL(LOCALE_INEGSYMPRECEDES, "0") +LOCVAL(LOCALE_INEGSEPBYSPACE, "1") +LOCVAL(LOCALE_FONTSIGNATURE, "'") +LOCVAL(LOCALE_SISO639LANGNAME, "sk") +LOCVAL(LOCALE_SISO3166CTRYNAME, "SK") diff --git a/lib/kernel32/nls/slv.nls b/lib/kernel32/nls/slv.nls new file mode 100644 index 0000000..127fd5b --- /dev/null +++ b/lib/kernel32/nls/slv.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Slovenia + * (Slovenian strings in cp1250) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0424") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Slovenian") +LOCVAL(LOCALE_SABBREVLANGNAME,"slv") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Slovenia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SVN") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0424") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"SIT") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ponedeljek") +LOCVAL(LOCALE_SDAYNAME2,"torek") +LOCVAL(LOCALE_SDAYNAME3,"sreda") +LOCVAL(LOCALE_SDAYNAME4,"èetrtek") +LOCVAL(LOCALE_SDAYNAME5,"petek") +LOCVAL(LOCALE_SDAYNAME6,"sobota") +LOCVAL(LOCALE_SDAYNAME7,"nedelja") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"pon") +LOCVAL(LOCALE_SABBREVDAYNAME2,"tor") +LOCVAL(LOCALE_SABBREVDAYNAME3,"sre") +LOCVAL(LOCALE_SABBREVDAYNAME4,"èet") +LOCVAL(LOCALE_SABBREVDAYNAME5,"pet") +LOCVAL(LOCALE_SABBREVDAYNAME6,"sob") +LOCVAL(LOCALE_SABBREVDAYNAME7,"ned") + +LOCVAL(LOCALE_SMONTHNAME1,"januar") +LOCVAL(LOCALE_SMONTHNAME2,"februar") +LOCVAL(LOCALE_SMONTHNAME3,"marec") +LOCVAL(LOCALE_SMONTHNAME4,"april") +LOCVAL(LOCALE_SMONTHNAME5,"maj") +LOCVAL(LOCALE_SMONTHNAME6,"juni") +LOCVAL(LOCALE_SMONTHNAME7,"juli") +LOCVAL(LOCALE_SMONTHNAME8,"avgust") +LOCVAL(LOCALE_SMONTHNAME9,"september") +LOCVAL(LOCALE_SMONTHNAME10,"oktober") +LOCVAL(LOCALE_SMONTHNAME11,"november") +LOCVAL(LOCALE_SMONTHNAME12,"december") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"avg") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"sl") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SI") + +/* calendario gregoriano */ diff --git a/lib/kernel32/nls/sqi.nls b/lib/kernel32/nls/sqi.nls new file mode 100644 index 0000000..415d67f --- /dev/null +++ b/lib/kernel32/nls/sqi.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Albania + */ + +LOCVAL(LOCALE_ILANGUAGE,"041c") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Albanian") +LOCVAL(LOCALE_SABBREVLANGNAME,"sqi") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"Shqip?ria") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Albania") +LOCVAL(LOCALE_SABBREVCTRYNAME,"ALB") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"041c") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789") +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"ALL") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +LOCVAL(LOCALE_SMONGROUPING,"3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"sq") +LOCVAL(LOCALE_SISO3166CTRYNAME,"AL") + +/* Gregorian Calendar */ diff --git a/lib/kernel32/nls/srb.nls b/lib/kernel32/nls/srb.nls new file mode 100644 index 0000000..115cdc9 --- /dev/null +++ b/lib/kernel32/nls/srb.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Serbia + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c1a") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Serbian (cyrillic)") +LOCVAL(LOCALE_SABBREVLANGNAME,"srb") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Yugoslavia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"YUG") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0c1a") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"YUN") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"sr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"YU") + diff --git a/lib/kernel32/nls/srl.nls b/lib/kernel32/nls/srl.nls new file mode 100644 index 0000000..d0ecdd7 --- /dev/null +++ b/lib/kernel32/nls/srl.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Serbian (Latin) + */ + +LOCVAL(LOCALE_ILANGUAGE,"081a") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Serbian (latin)") +LOCVAL(LOCALE_SABBREVLANGNAME,"srl") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Yugoslavia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"YUG") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Yugoslavija") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"081a") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1250") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"YUN") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"sh") +LOCVAL(LOCALE_SISO3166CTRYNAME,"YU") + diff --git a/lib/kernel32/nls/sve.nls b/lib/kernel32/nls/sve.nls new file mode 100644 index 0000000..39e7db1 --- /dev/null +++ b/lib/kernel32/nls/sve.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Sweden + * + * (swedish strings in cp1252) + */ + +LOCVAL(LOCALE_ILANGUAGE,"041d") +LOCVAL(LOCALE_SLANGUAGE,"Svenska") +LOCVAL(LOCALE_SENGLANGUAGE,"Swedish") +LOCVAL(LOCALE_SABBREVLANGNAME,"sve") +LOCVAL(LOCALE_SNATIVELANGNAME,"Svenska") +LOCVAL(LOCALE_ICOUNTRY,"45") +LOCVAL(LOCALE_SCOUNTRY,"SWE") +LOCVAL(LOCALE_SENGCOUNTRY,"Sweden") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SWE") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Sverige") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"041d") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"45") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"kr") +LOCVAL(LOCALE_SINTLSYMBOL,"SEK") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Måndag") +LOCVAL(LOCALE_SDAYNAME2,"Tisdag") +LOCVAL(LOCALE_SDAYNAME3,"Onsdag") +LOCVAL(LOCALE_SDAYNAME4,"Torsdag") +LOCVAL(LOCALE_SDAYNAME5,"Fredag") +LOCVAL(LOCALE_SDAYNAME6,"Lördag") +LOCVAL(LOCALE_SDAYNAME7,"Söndag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Må") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ti") +LOCVAL(LOCALE_SABBREVDAYNAME3,"On") +LOCVAL(LOCALE_SABBREVDAYNAME4,"To") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Lö") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Sö") + +LOCVAL(LOCALE_SMONTHNAME1,"Januari") +LOCVAL(LOCALE_SMONTHNAME2,"Februari") +LOCVAL(LOCALE_SMONTHNAME3,"Mars") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Maj") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"Augusti") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"December") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"sv") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SE") + diff --git a/lib/kernel32/nls/svf.nls b/lib/kernel32/nls/svf.nls new file mode 100644 index 0000000..e0b4a5e --- /dev/null +++ b/lib/kernel32/nls/svf.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Finland (Swedish) + */ + +LOCVAL(LOCALE_ILANGUAGE,"081d") +LOCVAL(LOCALE_SLANGUAGE,"Svenska") +LOCVAL(LOCALE_SENGLANGUAGE,"Swedish (Finland)") +LOCVAL(LOCALE_SABBREVLANGNAME,"sve") +LOCVAL(LOCALE_SNATIVELANGNAME,"Svenska") +LOCVAL(LOCALE_ICOUNTRY,"45") +LOCVAL(LOCALE_SCOUNTRY,"SWE") +LOCVAL(LOCALE_SENGCOUNTRY,"Finland") +LOCVAL(LOCALE_SABBREVCTRYNAME,"FIN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Finland") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"081d") +LOCVAL(LOCALE_IDEFAULTCOUNTRY,"45") +LOCVAL(LOCALE_IDEFAULTCODEPAGE,"850") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1252") +LOCVAL(LOCALE_SLIST,";") +LOCVAL(LOCALE_IMEASURE,"0") +LOCVAL(LOCALE_SDECIMAL,",") +LOCVAL(LOCALE_STHOUSAND,".") +/* LOCVAL(LOCALE_SGROUPING) */ +LOCVAL(LOCALE_IDIGITS,"2") +LOCVAL(LOCALE_ILZERO,"1") +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"mk") +LOCVAL(LOCALE_SINTLSYMBOL,"FIM") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +/* LOCVAL(LOCALE_SMONGROUPING) */ +LOCVAL(LOCALE_ICURRDIGITS,"2") +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +LOCVAL(LOCALE_ICURRENCY,"3") +LOCVAL(LOCALE_INEGCURR,"8") +LOCVAL(LOCALE_SDATE,".") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") +/* LOCVAL(LOCALE_STIMEFORMAT) */ +LOCVAL(LOCALE_IDATE,"1") +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "") +LOCVAL(LOCALE_S2359, "") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Måndag") +LOCVAL(LOCALE_SDAYNAME2,"Tisdag") +LOCVAL(LOCALE_SDAYNAME3,"Onsdag") +LOCVAL(LOCALE_SDAYNAME4,"Torsdag") +LOCVAL(LOCALE_SDAYNAME5,"Fredag") +LOCVAL(LOCALE_SDAYNAME6,"Lördag") +LOCVAL(LOCALE_SDAYNAME7,"Söndag") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Må") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ti") +LOCVAL(LOCALE_SABBREVDAYNAME3,"On") +LOCVAL(LOCALE_SABBREVDAYNAME4,"To") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Fr") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Lö") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Sö") + +LOCVAL(LOCALE_SMONTHNAME1,"Januari") +LOCVAL(LOCALE_SMONTHNAME2,"Februari") +LOCVAL(LOCALE_SMONTHNAME3,"Mars") +LOCVAL(LOCALE_SMONTHNAME4,"April") +LOCVAL(LOCALE_SMONTHNAME5,"Maj") +LOCVAL(LOCALE_SMONTHNAME6,"Juni") +LOCVAL(LOCALE_SMONTHNAME7,"Juli") +LOCVAL(LOCALE_SMONTHNAME8,"Augusti") +LOCVAL(LOCALE_SMONTHNAME9,"September") +LOCVAL(LOCALE_SMONTHNAME10,"Oktober") +LOCVAL(LOCALE_SMONTHNAME11,"November") +LOCVAL(LOCALE_SMONTHNAME12,"December") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Jan") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Feb") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Apr") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Maj") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Jun") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Jul") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aug") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Sep") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Okt") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Nov") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Dec") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"sv") +LOCVAL(LOCALE_SISO3166CTRYNAME,"FI") + +/* gregoriansk kalender */ diff --git a/lib/kernel32/nls/tha.nls b/lib/kernel32/nls/tha.nls new file mode 100644 index 0000000..f49cb98 --- /dev/null +++ b/lib/kernel32/nls/tha.nls @@ -0,0 +1,114 @@ +/* + * OLE2NLS library + * Thai + */ +LOCVAL(LOCALE_ILANGUAGE, "041e") +LOCVAL(LOCALE_SLANGUAGE, "Thai") +LOCVAL(LOCALE_SENGLANGUAGE, "Thai") +LOCVAL(LOCALE_SABBREVLANGNAME, "THA") +LOCVAL(LOCALE_SNATIVELANGNAME, "ä·Â") +LOCVAL(LOCALE_ICOUNTRY, "66") +LOCVAL(LOCALE_SCOUNTRY, "Thailand") +LOCVAL(LOCALE_SENGCOUNTRY, "Thailand") +LOCVAL(LOCALE_SABBREVCTRYNAME, "THA") +LOCVAL(LOCALE_SNATIVECTRYNAME, "ä·Â") +LOCVAL(LOCALE_IDEFAULTLANGUAGE, "041e") +LOCVAL(LOCALE_IDEFAULTCOUNTRY, "66") +LOCVAL(LOCALE_IDEFAULTCODEPAGE, "874") +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE, "874") +LOCVAL(LOCALE_IDEFAULTMACCODEPAGE, """") +LOCVAL(LOCALE_SLIST, ",") +LOCVAL(LOCALE_IMEASURE, "0") +LOCVAL(LOCALE_SDECIMAL, ".") +LOCVAL(LOCALE_STHOUSAND, ",") +LOCVAL(LOCALE_SGROUPING, "3;0") +LOCVAL(LOCALE_IDIGITS, "2") +LOCVAL(LOCALE_ILZERO, "0") +LOCVAL(LOCALE_INEGNUMBER, "1") +LOCVAL(LOCALE_SNATIVEDIGITS, "ðñòóôõö÷øù") +LOCVAL(LOCALE_SCURRENCY, "ß") +LOCVAL(LOCALE_SINTLSYMBOL, "THB") +LOCVAL(LOCALE_SMONDECIMALSEP, ".") +LOCVAL(LOCALE_SMONTHOUSANDSEP, ",") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +LOCVAL(LOCALE_ICURRDIGITS, "2") +LOCVAL(LOCALE_IINTLCURRDIGITS, "2") +LOCVAL(LOCALE_ICURRENCY, "0") +LOCVAL(LOCALE_INEGCURR, "1") +LOCVAL(LOCALE_SDATE, "/") +LOCVAL(LOCALE_STIME, ":") +LOCVAL(LOCALE_SSHORTDATE, "d/M/yy") +LOCVAL(LOCALE_SLONGDATE, "d MMMM yyyy") +LOCVAL(LOCALE_STIMEFORMAT, "H:mm:ss") +LOCVAL(LOCALE_IDATE, "1") +LOCVAL(LOCALE_ILDATE, "1") +LOCVAL(LOCALE_ITIME, "1") +LOCVAL(LOCALE_ITIMEMARKPOSN, "0") +LOCVAL(LOCALE_ICENTURY, "0") +LOCVAL(LOCALE_ITLZERO, "0") +LOCVAL(LOCALE_IDAYLZERO, "0") +LOCVAL(LOCALE_IMONLZERO, "0") +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "7") +LOCVAL(LOCALE_IOPTIONALCALENDAR, "7") +LOCVAL(LOCALE_IFIRSTDAYOFWEEK, "0") +LOCVAL(LOCALE_IFIRSTWEEKOFYEAR, "0") +LOCVAL(LOCALE_SDAYNAME1, "¨Ñ¹·Ãì") +LOCVAL(LOCALE_SDAYNAME2, "Íѧ¤ÒÃ") +LOCVAL(LOCALE_SDAYNAME3, "¾Ø¸") +LOCVAL(LOCALE_SDAYNAME4, "¾ÄËÑʺ´Õ") +LOCVAL(LOCALE_SDAYNAME5, "ÈØ¡Ãì") +LOCVAL(LOCALE_SDAYNAME6, "àÊÒÃì") +LOCVAL(LOCALE_SDAYNAME7, "ÍÒ·ÔµÂì") +LOCVAL(LOCALE_SABBREVDAYNAME1, "¨.") +LOCVAL(LOCALE_SABBREVDAYNAME2, "Í.") +LOCVAL(LOCALE_SABBREVDAYNAME3, "¾.") +LOCVAL(LOCALE_SABBREVDAYNAME4, "¾Ä.") +LOCVAL(LOCALE_SABBREVDAYNAME5, "È.") +LOCVAL(LOCALE_SABBREVDAYNAME6, "Ê.") +LOCVAL(LOCALE_SABBREVDAYNAME7, "ÍÒ.") +LOCVAL(LOCALE_SMONTHNAME1, "Á¡ÃÒ¤Á") +LOCVAL(LOCALE_SMONTHNAME2, "¡ØÁÀҾѹ¸ì") +LOCVAL(LOCALE_SMONTHNAME3, "ÁÕ¹Ò¤Á") +LOCVAL(LOCALE_SMONTHNAME4, "àÁÉÒ¹") +LOCVAL(LOCALE_SMONTHNAME5, "¾ÄÉÀÒ¤Á") +LOCVAL(LOCALE_SMONTHNAME6, "ÁԶعÒ¹") +LOCVAL(LOCALE_SMONTHNAME7, "¡Ã¡®Ò¤Á") +LOCVAL(LOCALE_SMONTHNAME8, "ÊÔ§ËÒ¤Á") +LOCVAL(LOCALE_SMONTHNAME9, "¡Ñ¹ÂÒ¹") +LOCVAL(LOCALE_SMONTHNAME10, "µØÅÒ¤Á") +LOCVAL(LOCALE_SMONTHNAME11, "¾ÄȨԡÒ¹") +LOCVAL(LOCALE_SMONTHNAME12, "¸Ñ¹ÇÒ¤Á") +LOCVAL(LOCALE_SMONTHNAME13, "") +LOCVAL(LOCALE_SABBREVMONTHNAME1, "Á.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME2, "¡.¾.") +LOCVAL(LOCALE_SABBREVMONTHNAME3, "ÁÕ.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME4, "àÁ.Â.") +LOCVAL(LOCALE_SABBREVMONTHNAME5, "¾.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME6, "ÁÔ.Â.") +LOCVAL(LOCALE_SABBREVMONTHNAME7, "¡.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME8, "Ê.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME9, "¡.Â.") +LOCVAL(LOCALE_SABBREVMONTHNAME10, "µ.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME11, "¾.Â.") +LOCVAL(LOCALE_SABBREVMONTHNAME12, "¸.¤.") +LOCVAL(LOCALE_SABBREVMONTHNAME13, "") +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +LOCVAL(LOCALE_IPOSSIGNPOSN, "3") +LOCVAL(LOCALE_INEGSIGNPOSN, "3") +LOCVAL(LOCALE_IPOSSYMPRECEDES, "1") +LOCVAL(LOCALE_IPOSSEPBYSPACE, "0") +LOCVAL(LOCALE_INEGSYMPRECEDES, "1") +LOCVAL(LOCALE_INEGSEPBYSPACE, "0") +LOCVAL(LOCALE_FONTSIGNATURE, "") +LOCVAL(LOCALE_SISO639LANGNAME, "th") +LOCVAL(LOCALE_SISO3166CTRYNAME, "TH") +/*LOCVAL(LOCALE_IDEFAULTEBCDICCODEPAGE, """")*/ +/*LOCVAL(LOCALE_IPAPERSIZE, """")*/ +/*LOCVAL(LOCALE_SENGCURRNAME, """")*/ +/*LOCVAL(LOCALE_SNATIVECURRNAME, """")*/ +/*LOCVAL(LOCALE_SYEARMONTH, """")*/ +/*LOCVAL(LOCALE_SSORTNAME, """")*/ +/*LOCVAL(LOCALE_IDIGITSUBSTITUTION, """")*/ diff --git a/lib/kernel32/nls/trk.nls b/lib/kernel32/nls/trk.nls new file mode 100644 index 0000000..a30b064 --- /dev/null +++ b/lib/kernel32/nls/trk.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Turkey + * (Turkish strings in cp1254) + */ + +LOCVAL(LOCALE_ILANGUAGE,"041f") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Turkish") +LOCVAL(LOCALE_SABBREVLANGNAME,"trk") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Türkiye") +LOCVAL(LOCALE_SENGCOUNTRY,"Turkey") +LOCVAL(LOCALE_SABBREVCTRYNAME,"TUR") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Türkiye") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"041f") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1254") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +LOCVAL(LOCALE_SCURRENCY,"TL") +LOCVAL(LOCALE_SINTLSYMBOL,"TRL") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"Pazartesi") +LOCVAL(LOCALE_SDAYNAME2,"Salý") +LOCVAL(LOCALE_SDAYNAME3,"Çarþamba") +LOCVAL(LOCALE_SDAYNAME4,"Perþembe") +LOCVAL(LOCALE_SDAYNAME5,"Cuma") +LOCVAL(LOCALE_SDAYNAME6,"Cumartesi") +LOCVAL(LOCALE_SDAYNAME7,"Pazar") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Pzt") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Sal") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Çrþ") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Prþ") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Cum") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Cts") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Paz") + +LOCVAL(LOCALE_SMONTHNAME1,"Ocak") +LOCVAL(LOCALE_SMONTHNAME2,"Þubat") +LOCVAL(LOCALE_SMONTHNAME3,"Mart") +LOCVAL(LOCALE_SMONTHNAME4,"Nisan") +LOCVAL(LOCALE_SMONTHNAME5,"Mayýs") +LOCVAL(LOCALE_SMONTHNAME6,"Haziran") +LOCVAL(LOCALE_SMONTHNAME7,"Temmus") +LOCVAL(LOCALE_SMONTHNAME8,"Aðustos") +LOCVAL(LOCALE_SMONTHNAME9,"Eylül") +LOCVAL(LOCALE_SMONTHNAME10,"Ekim") +LOCVAL(LOCALE_SMONTHNAME11,"Kasým") +LOCVAL(LOCALE_SMONTHNAME12,"Aralýk") +LOCVAL(LOCALE_SMONTHNAME13,"") + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Oca") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Þub") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Mar") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Nis") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"May") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Haz") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Tem") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Aðu") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Eyl") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"Eki") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Kas") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"Ara") +LOCVAL(LOCALE_SABBREVMONTHNAME13,"") + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"tr") +LOCVAL(LOCALE_SISO3166CTRYNAME,"TR") + +/* calendario gregoriano */ diff --git a/lib/kernel32/nls/ukr.nls b/lib/kernel32/nls/ukr.nls new file mode 100644 index 0000000..c339d16 --- /dev/null +++ b/lib/kernel32/nls/ukr.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Ukrainian + */ + +LOCVAL(LOCALE_ILANGUAGE,"0422") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Ukrainian") +LOCVAL(LOCALE_SABBREVLANGNAME,"ukr") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Ukrainia") +LOCVAL(LOCALE_SABBREVCTRYNAME,"UKR") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0422") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"1251") +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"UAK") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"uk") +LOCVAL(LOCALE_SISO3166CTRYNAME,"UA") + diff --git a/lib/kernel32/nls/vie.nls b/lib/kernel32/nls/vie.nls new file mode 100644 index 0000000..17ab906 --- /dev/null +++ b/lib/kernel32/nls/vie.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * Vietnam + * + * (vietnamese strings in VISCII) + */ + +LOCVAL(LOCALE_ILANGUAGE,"042a") +LOCVAL(LOCALE_SLANGUAGE,"Tiªng Vi®t") +LOCVAL(LOCALE_SENGLANGUAGE,"Vietnamese") +LOCVAL(LOCALE_SABBREVLANGNAME,"vie") +LOCVAL(LOCALE_SNATIVELANGNAME,"Tiªng Vi®t") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Vi®t Nam") +LOCVAL(LOCALE_SENGCOUNTRY,"Vietnam") +LOCVAL(LOCALE_SABBREVCTRYNAME,"VNM") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Vi®t Nam") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"042a") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"аng") +LOCVAL(LOCALE_SINTLSYMBOL, "VND") +LOCVAL(LOCALE_SMONDECIMALSEP,",") +LOCVAL(LOCALE_SMONTHOUSANDSEP,".") +LOCVAL(LOCALE_SMONGROUPING, "3;0") +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"/") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"dd/MM/yyyy") +LOCVAL(LOCALE_SLONGDATE,"ddd, d MMMM nåm yyyy") +LOCVAL(LOCALE_STIMEFORMAT,"h:mm:ss tt") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "sáng") +LOCVAL(LOCALE_S2359, "chi«u") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"thÑ hai") +LOCVAL(LOCALE_SDAYNAME2,"thÑ ba") +LOCVAL(LOCALE_SDAYNAME3,"thÑ tß") +LOCVAL(LOCALE_SDAYNAME4,"thÑ nåm") +LOCVAL(LOCALE_SDAYNAME5,"thÑ sáu") +LOCVAL(LOCALE_SDAYNAME6,"thÑ bäy") +LOCVAL(LOCALE_SDAYNAME7,"chü nh§t") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Hai") +LOCVAL(LOCALE_SABBREVDAYNAME2,"Ba") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Tß") +LOCVAL(LOCALE_SABBREVDAYNAME4,"Nåm") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Sáu") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Bäy") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Nh§t") + +LOCVAL(LOCALE_SMONTHNAME1,"tháng giêng") +LOCVAL(LOCALE_SMONTHNAME2,"tháng hai") +LOCVAL(LOCALE_SMONTHNAME3,"tháng ba") +LOCVAL(LOCALE_SMONTHNAME4,"tháng tß") +LOCVAL(LOCALE_SMONTHNAME5,"tháng nåm") +LOCVAL(LOCALE_SMONTHNAME6,"tháng sáu") +LOCVAL(LOCALE_SMONTHNAME7,"tháng bäy") +LOCVAL(LOCALE_SMONTHNAME8,"tháng tám") +LOCVAL(LOCALE_SMONTHNAME9,"tháng chín") +LOCVAL(LOCALE_SMONTHNAME10,"tháng m߶i") +LOCVAL(LOCALE_SMONTHNAME11,"tháng mµt") +LOCVAL(LOCALE_SMONTHNAME12,"tháng chÕp") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"Giêng") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"Hai") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"Ba") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"Tß") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"Nåm") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"Sáu") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"Bäy") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"Tám") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"Chín") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"M߶i") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"Mµt") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"ChÕp") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +LOCVAL(LOCALE_SPOSITIVESIGN, "") +LOCVAL(LOCALE_SNEGATIVESIGN, "-") +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"vi") +LOCVAL(LOCALE_SISO3166CTRYNAME,"VN") + diff --git a/lib/kernel32/nls/wctomb.c b/lib/kernel32/nls/wctomb.c new file mode 100644 index 0000000..c93826d --- /dev/null +++ b/lib/kernel32/nls/wctomb.c @@ -0,0 +1,101 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + Addition copyrights might be specified in LGPL.c + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/nls/wctomb.c + * PURPOSE: National language support functions + * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) + * UPDATE HISTORY: Modified from Onno Hovers wfc. ( 08/02/99 ) + * + */ + +/* + * nls/wctomb.c + * Copyright (c) 1996, Onno Hovers, All rights reserved + */ + +#include + +#include +#include +#include + +#define NDEBUG +#include + +extern PLOCALE __TebLocale; + +#define GetTebLocale() __TebLocale + +INT WideCharToMultiByte(UINT cpid, DWORD flags, LPCWSTR src, int srclen, + LPSTR dest, int destlen, LPCSTR pdefchar, + LPBOOL pdefused ) +{ + PCODEPAGE pcodepage = __CPFirst; + BOOL defused=FALSE; + INT copylen; + INT retlen; + CHAR ***utoa; + CHAR defchar='?'; + CHAR d; + WCHAR c; + + DPRINT("WideCharToMultiByte()\n"); + + /* get codepage */ + switch(cpid) + { + case CP_ACP: pcodepage=GetTebLocale()->OemCodePage; break; + case CP_OEMCP: pcodepage=GetTebLocale()->AnsiCodePage; break; + case CP_MACCP: pcodepage=&__CP10000; break; + default: + pcodepage=__CPFirst; + while((pcodepage)&&(pcodepage->Id!=cpid)) + pcodepage=pcodepage->Next; + } + if(pcodepage==NULL) + { SetLastError(ERROR_INVALID_PARAMETER); return 0; } + + /* get conversion table */ + utoa=pcodepage->FromUnicode; + + /* get default char */ + if(pdefchar) + defchar=*pdefchar; + else + defchar=pcodepage->Info->DefaultChar[0]; + + + if(destlen!=0) + { + /* how long are we ?? */ + if(srclen==0) + srclen=wcslen(src); + + copylen=min(srclen,destlen); + retlen=copylen; + + /* XXX: maybe some inline assembly to speed things up, here ??? */ + while(copylen>0) + { + c=*src; + + d=utoa[c>>10][(c>>5)&0x1F][(c)&0x1F]; + if((!d)&&(c)) + { + d=defchar; + defused=TRUE; + } + *dest=d; + src++; + dest++; + copylen--; + } + } + else + { + /* XXXX: composites etc. */ + retlen = wcslen(src); + } + return retlen; +} \ No newline at end of file diff --git a/lib/kernel32/nls/zhh.nls b/lib/kernel32/nls/zhh.nls new file mode 100644 index 0000000..23f522e --- /dev/null +++ b/lib/kernel32/nls/zhh.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Chinese (Hong Kong) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0c04") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Chinese (Hong Kong)") +LOCVAL(LOCALE_SABBREVLANGNAME,"zhh") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Hong Kong") +LOCVAL(LOCALE_SABBREVCTRYNAME,"HKG") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0404") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +/* LOCVAL(LOCALE_SNATIVEDIGITS) */ +/* LOCVAL(LOCALE_SCURRENCY,"") */ +LOCVAL(LOCALE_SINTLSYMBOL,"HKD") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"zh") +LOCVAL(LOCALE_SISO3166CTRYNAME,"HK") + diff --git a/lib/kernel32/nls/zhi.nls b/lib/kernel32/nls/zhi.nls new file mode 100644 index 0000000..8c6ebb3 --- /dev/null +++ b/lib/kernel32/nls/zhi.nls @@ -0,0 +1,115 @@ +/* + * OLE2NLS library + * People's republic of China + * + * (chinese strings in 8bit GuoBiao) + */ + +LOCVAL(LOCALE_ILANGUAGE,"0804") +LOCVAL(LOCALE_SLANGUAGE,"ººÓï") +LOCVAL(LOCALE_SENGLANGUAGE,"Chinese (People's republic of China") +LOCVAL(LOCALE_SABBREVLANGNAME,"zhi") +LOCVAL(LOCALE_SNATIVELANGNAME,"ººÓï") +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +LOCVAL(LOCALE_SCOUNTRY,"Öйú") +LOCVAL(LOCALE_SENGCOUNTRY,"People's republic of China") +LOCVAL(LOCALE_SABBREVCTRYNAME,"CHN") +LOCVAL(LOCALE_SNATIVECTRYNAME,"Öйú") +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0804") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"Ôª") +LOCVAL(LOCALE_SINTLSYMBOL,"CNY") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +LOCVAL(LOCALE_SDATE,"-") +LOCVAL(LOCALE_STIME,":") +LOCVAL(LOCALE_SSHORTDATE,"yyy-MM-dd") +LOCVAL(LOCALE_SLONGDATE,"yyyyÄêMMMMd.ºÅddd") +LOCVAL(LOCALE_STIMEFORMAT, "HHʱmm·ÖssÃë") +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +/* LOCVAL(LOCALE_S1159, "") */ +/* LOCVAL(LOCALE_S2359, "") */ +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +LOCVAL(LOCALE_SDAYNAME1,"ÐÇÆÚÒ»") +LOCVAL(LOCALE_SDAYNAME2,"ÐÇÆÚ¶þ") +LOCVAL(LOCALE_SDAYNAME3,"ÐÇÆÚÈý") +LOCVAL(LOCALE_SDAYNAME4,"ÐÇÆÚËÄ") +LOCVAL(LOCALE_SDAYNAME5,"ÐÇÆÚÎå") +LOCVAL(LOCALE_SDAYNAME6,"ÐÇÆÚÁù") +LOCVAL(LOCALE_SDAYNAME7,"ÐÇÆÚÌì") + +LOCVAL(LOCALE_SABBREVDAYNAME1,"Ò»") +LOCVAL(LOCALE_SABBREVDAYNAME2,"¶þ") +LOCVAL(LOCALE_SABBREVDAYNAME3,"Èý") +LOCVAL(LOCALE_SABBREVDAYNAME4,"ËÄ") +LOCVAL(LOCALE_SABBREVDAYNAME5,"Îå") +LOCVAL(LOCALE_SABBREVDAYNAME6,"Áù") +LOCVAL(LOCALE_SABBREVDAYNAME7,"Ìì") + +LOCVAL(LOCALE_SMONTHNAME1,"Ò»ÔÂ") +LOCVAL(LOCALE_SMONTHNAME2,"¶þÔÂ") +LOCVAL(LOCALE_SMONTHNAME3,"ÈýÔÂ") +LOCVAL(LOCALE_SMONTHNAME4,"ËÄÔÂ") +LOCVAL(LOCALE_SMONTHNAME5,"ÎåÔÂ") +LOCVAL(LOCALE_SMONTHNAME6,"ÁùÔÂ") +LOCVAL(LOCALE_SMONTHNAME7,"ÆßÔÂ") +LOCVAL(LOCALE_SMONTHNAME8,"°ËÔÂ") +LOCVAL(LOCALE_SMONTHNAME9,"¾ÅÔÂ") +LOCVAL(LOCALE_SMONTHNAME10,"Ê®ÔÂ") +LOCVAL(LOCALE_SMONTHNAME11,"ʮһÔÂ") +LOCVAL(LOCALE_SMONTHNAME12,"Ê®¶þÔÂ") +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +LOCVAL(LOCALE_SABBREVMONTHNAME1,"1ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME2,"2ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME3,"3ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME4,"4ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME5,"5ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME6,"6ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME7,"7ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME8,"8ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME9,"9ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME10,"10ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME11,"11ÔÂ") +LOCVAL(LOCALE_SABBREVMONTHNAME12,"12ÔÂ") +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"zh") +LOCVAL(LOCALE_SISO3166CTRYNAME,"CN") + diff --git a/lib/kernel32/nls/zhs.nls b/lib/kernel32/nls/zhs.nls new file mode 100644 index 0000000..b2f8e8b --- /dev/null +++ b/lib/kernel32/nls/zhs.nls @@ -0,0 +1,113 @@ +/* + * OLE2NLS library + * Chinese (Singapore) + */ + +LOCVAL(LOCALE_ILANGUAGE,"1004") +/* LOCVAL(LOCALE_SLANGUAGE,"") */ +LOCVAL(LOCALE_SENGLANGUAGE,"Chinese (Singapore)") +LOCVAL(LOCALE_SABBREVLANGNAME,"zhs") +/* LOCVAL(LOCALE_SNATIVELANGNAME,"") */ +/* LOCVAL(LOCALE_ICOUNTRY,"") */ +/* LOCVAL(LOCALE_SCOUNTRY,"") */ +LOCVAL(LOCALE_SENGCOUNTRY,"Singapore") +LOCVAL(LOCALE_SABBREVCTRYNAME,"SGP") +/* LOCVAL(LOCALE_SNATIVECTRYNAME,"") */ +LOCVAL(LOCALE_IDEFAULTLANGUAGE,"0404") +/* LOCVAL(LOCALE_IDEFAULTCOUNTRY,"") */ +/* LOCVAL(LOCALE_IDEFAULTCODEPAGE) */ +/* LOCVAL(LOCALE_IDEFAULTANSICODEPAGE) */ +/* LOCVAL(LOCALE_SLIST,"") */ +/* LOCVAL(LOCALE_IMEASURE,"") */ +/* LOCVAL(LOCALE_SDECIMAL,"") */ +/* LOCVAL(LOCALE_STHOUSAND,"") */ +/* LOCVAL(LOCALE_SGROUPING) */ +/* LOCVAL(LOCALE_IDIGITS,"2") */ +/* LOCVAL(LOCALE_ILZERO,"1") */ +/* LOCVAL(LOCALE_INEGNUMBER) */ +LOCVAL(LOCALE_SNATIVEDIGITS, "0123456789") +LOCVAL(LOCALE_SCURRENCY,"$") +LOCVAL(LOCALE_SINTLSYMBOL,"SGD") +/* LOCVAL(LOCALE_SMONDECIMALSEP,",") */ +/* LOCVAL(LOCALE_SMONTHOUSANDSEP,".") */ +/* LOCVAL(LOCALE_SMONGROUPING) */ +/* LOCVAL(LOCALE_ICURRDIGITS,"2") */ +/* LOCVAL(LOCALE_IINTLCURRDIGITS) */ +/* LOCVAL(LOCALE_ICURRENCY,"3") */ +/* LOCVAL(LOCALE_INEGCURR,"8") */ +/* LOCVAL(LOCALE_SDATE,".") */ +/* LOCVAL(LOCALE_STIME,":") */ +/* LOCVAL(LOCALE_SSHORTDATE,"dd/MM-yyyy") */ +/* LOCVAL(LOCALE_SLONGDATE,"ddd, d. MMMM yyyy") */ +/* LOCVAL(LOCALE_STIMEFORMAT) */ +/* LOCVAL(LOCALE_IDATE,"1") */ +/* LOCVAL(LOCALE_ILDATE) */ +LOCVAL(LOCALE_ITIME,"1") +/* LOCVAL(LOCALE_ITIMEMARKPOSN) */ +/* LOCVAL(LOCALE_ICENTURY) */ +LOCVAL(LOCALE_ITLZERO,"1") +/* LOCVAL(LOCALE_IDAYLZERO) */ +/* LOCVAL(LOCALE_IMONLZERO) */ +LOCVAL(LOCALE_S1159, "AM") +LOCVAL(LOCALE_S2359, "PM") +LOCVAL(LOCALE_ICALENDARTYPE, "1") +/* LOCVAL(LOCALE_IOPTIONALCALENDAR) */ +/* LOCVAL(LOCALE_IFIRSTDAYOFWEEK) */ +/* LOCVAL(LOCALE_IFIRSTWEEKOFYEAR) */ + +/* LOCVAL(LOCALE_SDAYNAME1,"") */ +/* LOCVAL(LOCALE_SDAYNAME2,"") */ +/* LOCVAL(LOCALE_SDAYNAME3,"") */ +/* LOCVAL(LOCALE_SDAYNAME4,"") */ +/* LOCVAL(LOCALE_SDAYNAME5,"") */ +/* LOCVAL(LOCALE_SDAYNAME6,"") */ +/* LOCVAL(LOCALE_SDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SABBREVDAYNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVDAYNAME7,"") */ + +/* LOCVAL(LOCALE_SMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SABBREVMONTHNAME1,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME2,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME3,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME4,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME5,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME6,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME7,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME8,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME9,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME10,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME11,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME12,"") */ +/* LOCVAL(LOCALE_SABBREVMONTHNAME13,"") */ + +/* LOCVAL(LOCALE_SPOSITIVESIGN, "") */ +/* LOCVAL(LOCALE_SNEGATIVESIGN, "") */ +/* LOCVAL(LOCALE_IPOSSIGNPOSN, "") */ +/* LOCVAL(LOCALE_INEGSIGNPOSN, "") */ +/* LOCVAL(LOCALE_IPOSSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_IPOSSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_INEGSYMPRECEDES, "") */ +/* LOCVAL(LOCALE_INEGSEPBYSPACE, "") */ +/* LOCVAL(LOCALE_FONTSIGNATURE, "") */ +LOCVAL(LOCALE_SISO639LANGNAME,"zh") +LOCVAL(LOCALE_SISO3166CTRYNAME,"SG") + diff --git a/lib/kernel32/process/.cvsignore b/lib/kernel32/process/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/process/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/process/cmdline.c b/lib/kernel32/process/cmdline.c new file mode 100644 index 0000000..d5fa397 --- /dev/null +++ b/lib/kernel32/process/cmdline.c @@ -0,0 +1,100 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/proc/proc.c + * PURPOSE: Process functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS ******************************************************************/ + +static UNICODE_STRING CommandLineStringW; +static ANSI_STRING CommandLineStringA; + +static WINBOOL bCommandLineInitialized = FALSE; + + +/* FUNCTIONS ****************************************************************/ + +static VOID +InitCommandLines (VOID) +{ + PRTL_USER_PROCESS_PARAMETERS Params; + + // get command line + Params = NtCurrentPeb()->ProcessParameters; + RtlNormalizeProcessParams (Params); + + // initialize command line buffers + CommandLineStringW.Length = Params->CommandLine.Length; + CommandLineStringW.MaximumLength = CommandLineStringW.Length + sizeof(WCHAR); + CommandLineStringW.Buffer = RtlAllocateHeap(GetProcessHeap(), + HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, + CommandLineStringW.MaximumLength); + + RtlInitAnsiString(&CommandLineStringA, NULL); + + // copy command line + RtlCopyUnicodeString (&CommandLineStringW, + &(Params->CommandLine)); + CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0; + + /* convert unicode string to ansi (or oem) */ + if (bIsFileApiAnsi) + RtlUnicodeStringToAnsiString (&CommandLineStringA, + &CommandLineStringW, + TRUE); + else + RtlUnicodeStringToOemString (&CommandLineStringA, + &CommandLineStringW, + TRUE); + + CommandLineStringA.Buffer[CommandLineStringA.Length] = 0; + + bCommandLineInitialized = TRUE; +} + + +LPSTR STDCALL GetCommandLineA(VOID) +{ + if (bCommandLineInitialized == FALSE) + { + InitCommandLines (); + } + + DPRINT ("CommandLine \'%s\'\n", CommandLineStringA.Buffer); + + return(CommandLineStringA.Buffer); +} + +LPWSTR STDCALL GetCommandLineW (VOID) +{ + if (bCommandLineInitialized == FALSE) + { + InitCommandLines (); + } + + DPRINT ("CommandLine \'%S\'\n", CommandLineStringW.Buffer); + + return(CommandLineStringW.Buffer); +} + +/* EOF */ diff --git a/lib/kernel32/process/create.c b/lib/kernel32/process/create.c new file mode 100644 index 0000000..9abb98f --- /dev/null +++ b/lib/kernel32/process/create.c @@ -0,0 +1,998 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/process/create.c + * PURPOSE: Process functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include +#include + +/* FUNCTIONS ****************************************************************/ + +WINBOOL STDCALL +CreateProcessA (LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + WINBOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +/* + * FUNCTION: The CreateProcess function creates a new process and its + * primary thread. The new process executes the specified executable file + * ARGUMENTS: + * + * lpApplicationName = Pointer to name of executable module + * lpCommandLine = Pointer to command line string + * lpProcessAttributes = Process security attributes + * lpThreadAttributes = Thread security attributes + * bInheritHandles = Handle inheritance flag + * dwCreationFlags = Creation flags + * lpEnvironment = Pointer to new environment block + * lpCurrentDirectory = Pointer to current directory name + * lpStartupInfo = Pointer to startup info + * lpProcessInformation = Pointer to process information + */ +{ + PWCHAR lpEnvironmentW = NULL; + UNICODE_STRING ApplicationNameU; + UNICODE_STRING CurrentDirectoryU; + UNICODE_STRING CommandLineU; + ANSI_STRING ApplicationName; + ANSI_STRING CurrentDirectory; + ANSI_STRING CommandLine; + WINBOOL Result; + CHAR TempCurrentDirectoryA[256]; + + DPRINT("CreateProcessA(%s)\n", lpApplicationName); + DPRINT("dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, " + "lpStartupInfo %x, lpProcessInformation %x\n", dwCreationFlags, + lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); + + if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) + { + PCHAR ptr = lpEnvironment; + ULONG len = 0; + UNICODE_STRING EnvironmentU; + ANSI_STRING EnvironmentA; + while (*ptr) + { + RtlInitAnsiString(&EnvironmentA, ptr); + if (bIsFileApiAnsi) + len += RtlAnsiStringToUnicodeSize(&EnvironmentA) + sizeof(WCHAR); + else + len += RtlOemStringToUnicodeSize(&EnvironmentA) + sizeof(WCHAR); + ptr += EnvironmentA.MaximumLength; + } + len += sizeof(WCHAR); + lpEnvironmentW = (PWCHAR)RtlAllocateHeap(GetProcessHeap(), + HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY, + len); + if (lpEnvironmentW == NULL) + { + return FALSE; + } + ptr = lpEnvironment; + EnvironmentU.Buffer = lpEnvironmentW; + EnvironmentU.Length = 0; + EnvironmentU.MaximumLength = len; + while (*ptr) + { + RtlInitAnsiString(&EnvironmentA, ptr); + if (bIsFileApiAnsi) + RtlAnsiStringToUnicodeString(&EnvironmentU, &EnvironmentA, FALSE); + else + RtlOemStringToUnicodeString(&EnvironmentU, &EnvironmentA, FALSE); + ptr += EnvironmentA.MaximumLength; + EnvironmentU.Buffer += (EnvironmentU.Length / sizeof(WCHAR) + 1); + EnvironmentU.MaximumLength -= (EnvironmentU.Length + sizeof(WCHAR)); + EnvironmentU.Length = 0; + } + + EnvironmentU.Buffer[0] = 0; + } + + RtlInitAnsiString (&CommandLine, + lpCommandLine); + RtlInitAnsiString (&ApplicationName, + (LPSTR)lpApplicationName); + if (lpCurrentDirectory != NULL) + { + RtlInitAnsiString (&CurrentDirectory, + (LPSTR)lpCurrentDirectory); + } + + /* convert ansi (or oem) strings to unicode */ + if (bIsFileApiAnsi) + { + RtlAnsiStringToUnicodeString (&CommandLineU, &CommandLine, TRUE); + RtlAnsiStringToUnicodeString (&ApplicationNameU, &ApplicationName, TRUE); + if (lpCurrentDirectory != NULL) + RtlAnsiStringToUnicodeString (&CurrentDirectoryU, &CurrentDirectory, TRUE); + } + else + { + RtlOemStringToUnicodeString (&CommandLineU, &CommandLine, TRUE); + RtlOemStringToUnicodeString (&ApplicationNameU, &ApplicationName, TRUE); + if (lpCurrentDirectory != NULL) + RtlOemStringToUnicodeString (&CurrentDirectoryU, &CurrentDirectory, TRUE); + } + + Result = CreateProcessW (ApplicationNameU.Buffer, + CommandLineU.Buffer, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + dwCreationFlags & CREATE_UNICODE_ENVIRONMENT ? lpEnvironment : lpEnvironmentW, + (lpCurrentDirectory == NULL) ? NULL : CurrentDirectoryU.Buffer, + (LPSTARTUPINFOW)lpStartupInfo, + lpProcessInformation); + + RtlFreeUnicodeString (&ApplicationNameU); + RtlFreeUnicodeString (&CommandLineU); + if (lpCurrentDirectory != NULL) + RtlFreeUnicodeString (&CurrentDirectoryU); + + if (lpEnvironmentW) + { + RtlFreeHeap(GetProcessHeap(), 0, lpEnvironmentW); + } + + return Result; +} + + +static +EXCEPTION_DISPOSITION +__cdecl +_except_handler( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext ) +{ + DPRINT("Process terminated abnormally...\n"); + + if (/* FIXME: */ TRUE) /* Not a service */ + { + ExitProcess(0); + } + else + { + ExitThread(0); + } + + /* We should not get to here */ + return ExceptionContinueSearch; +} + +VOID STDCALL +BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress, + DWORD lpParameter) +{ + UINT uExitCode = 0; + + __try1(_except_handler) + { + uExitCode = (lpStartAddress)(lpParameter); + } __except1 + { + } + + ExitThread(uExitCode); +} + + +HANDLE STDCALL +KlCreateFirstThread(HANDLE ProcessHandle, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + ULONG StackReserve, + ULONG StackCommit, + LPTHREAD_START_ROUTINE lpStartAddress, + DWORD dwCreationFlags, + LPDWORD lpThreadId) +{ + NTSTATUS Status; + HANDLE ThreadHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; + CONTEXT ThreadContext; + INITIAL_TEB InitialTeb; + BOOLEAN CreateSuspended = FALSE; + ULONG OldPageProtection; + ULONG ResultLength; + ULONG InitialStack[6]; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + if (lpThreadAttributes != NULL) + { + if (lpThreadAttributes->bInheritHandle) + ObjectAttributes.Attributes = OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = + lpThreadAttributes->lpSecurityDescriptor; + } + ObjectAttributes.SecurityQualityOfService = NULL; + + if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED) + CreateSuspended = TRUE; + else + CreateSuspended = FALSE; + + InitialTeb.StackReserve = (StackReserve < 0x100000) ? 0x100000 : StackReserve; + /* FIXME: use correct commit size */ +#if 0 + InitialTeb.StackCommit = (StackCommit < PAGE_SIZE) ? PAGE_SIZE : StackCommit; +#endif + InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE; + + /* size of guard page */ + InitialTeb.StackCommit += PAGE_SIZE; + + /* Reserve stack */ + InitialTeb.StackAllocate = NULL; + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackAllocate, + 0, + &InitialTeb.StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Error reserving stack space!\n"); + SetLastErrorByStatus(Status); + return(NULL); + } + + DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n", + InitialTeb.StackAllocate, InitialTeb.StackReserve); + + InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve); + InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit); + + DPRINT("StackBase: %p StackCommit: %p\n", + InitialTeb.StackBase, InitialTeb.StackCommit); + + /* Commit stack page(s) */ + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackLimit, + 0, + &InitialTeb.StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting stack page(s)!\n"); + SetLastErrorByStatus(Status); + return(INVALID_HANDLE_VALUE); + } + + DPRINT("StackLimit: %p\n", + InitialTeb.StackLimit); + + /* Protect guard page */ + Status = NtProtectVirtualMemory(ProcessHandle, + InitialTeb.StackLimit, + PAGE_SIZE, + PAGE_GUARD | PAGE_READWRITE, + &OldPageProtection); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting guard page!\n"); + SetLastErrorByStatus(Status); + return(INVALID_HANDLE_VALUE); + } + + memset(&ThreadContext,0,sizeof(CONTEXT)); + ThreadContext.Eip = (ULONG)BaseProcessStart; + ThreadContext.SegGs = USER_DS; + ThreadContext.SegFs = USER_DS; + ThreadContext.SegEs = USER_DS; + ThreadContext.SegDs = USER_DS; + ThreadContext.SegCs = USER_CS; + ThreadContext.SegSs = USER_DS; + ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 6*4; + ThreadContext.EFlags = (1<<1) + (1<<9); + + DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip); + + /* + * Write in the initial stack. + */ + InitialStack[0] = 0; + InitialStack[1] = (DWORD)lpStartAddress; + InitialStack[2] = PEB_BASE; + + Status = ZwWriteVirtualMemory(ProcessHandle, + (PVOID)ThreadContext.Esp, + InitialStack, + sizeof(InitialStack), + &ResultLength); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to write initial stack.\n"); + return(INVALID_HANDLE_VALUE); + } + + Status = NtCreateThread(&ThreadHandle, + THREAD_ALL_ACCESS, + &ObjectAttributes, + ProcessHandle, + &ClientId, + &ThreadContext, + &InitialTeb, + CreateSuspended); + if (!NT_SUCCESS(Status)) + { + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + SetLastErrorByStatus(Status); + return(INVALID_HANDLE_VALUE); + } + + if (lpThreadId != NULL) + { + memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG)); + } + + return(ThreadHandle); +} + +HANDLE +KlMapFile(LPCWSTR lpApplicationName) +{ + HANDLE hFile; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING ApplicationNameString; + OBJECT_ATTRIBUTES ObjectAttributes; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + NTSTATUS Status; + HANDLE hSection; + + hFile = NULL; + + /* + * Find the application name + */ + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpApplicationName, + &ApplicationNameString, + NULL, + NULL)) + return NULL; + + DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + &ApplicationNameString, + OBJ_CASE_INSENSITIVE, + NULL, + SecurityDescriptor); + + /* + * Try to open the executable + */ + + Status = NtOpenFile(&hFile, + SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE|FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE); + + RtlFreeUnicodeString (&ApplicationNameString); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to open file\n"); + SetLastErrorByStatus (Status); + return(NULL); + } + + Status = NtCreateSection(&hSection, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_EXECUTE, + SEC_IMAGE, + hFile); + NtClose(hFile); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create section\n"); + SetLastErrorByStatus (Status); + return(NULL); + } + + return(hSection); +} + +static NTSTATUS +KlInitPeb (HANDLE ProcessHandle, + PRTL_USER_PROCESS_PARAMETERS Ppb, + PVOID* ImageBaseAddress) +{ + NTSTATUS Status; + PVOID PpbBase; + ULONG PpbSize; + ULONG BytesWritten; + ULONG Offset; + PVOID ParentEnv = NULL; + PVOID EnvPtr = NULL; + PWCHAR ptr; + ULONG EnvSize = 0, EnvSize1 = 0; + + /* create the Environment */ + if (Ppb->Environment != NULL) + { + ParentEnv = Ppb->Environment; + ptr = ParentEnv; + while (*ptr) + { + while(*ptr++); + } + ptr++; + EnvSize = (PVOID)ptr - ParentEnv; + } + else if (NtCurrentPeb()->ProcessParameters->Environment != NULL) + { + MEMORY_BASIC_INFORMATION MemInfo; + ParentEnv = NtCurrentPeb()->ProcessParameters->Environment; + + Status = NtQueryVirtualMemory (NtCurrentProcess (), + ParentEnv, + MemoryBasicInformation, + &MemInfo, + sizeof(MEMORY_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + EnvSize = MemInfo.RegionSize; + } + DPRINT("EnvironmentSize %ld\n", EnvSize); + + /* allocate and initialize new environment block */ + if (EnvSize != 0) + { + EnvSize1 = EnvSize; + Status = NtAllocateVirtualMemory(ProcessHandle, + &EnvPtr, + 0, + &EnvSize1, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + NtWriteVirtualMemory(ProcessHandle, + EnvPtr, + ParentEnv, + EnvSize, + &BytesWritten); + } + + /* create the PPB */ + PpbBase = NULL; + PpbSize = Ppb->AllocationSize; + Status = NtAllocateVirtualMemory(ProcessHandle, + &PpbBase, + 0, + &PpbSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength); + NtWriteVirtualMemory(ProcessHandle, + PpbBase, + Ppb, + Ppb->AllocationSize, + &BytesWritten); + + /* write pointer to environment */ + Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment); + NtWriteVirtualMemory(ProcessHandle, + (PVOID)(PpbBase + Offset), + &EnvPtr, + sizeof(EnvPtr), + &BytesWritten); + + /* write pointer to process parameter block */ + Offset = FIELD_OFFSET(PEB, ProcessParameters); + NtWriteVirtualMemory(ProcessHandle, + (PVOID)(PEB_BASE + Offset), + &PpbBase, + sizeof(PpbBase), + &BytesWritten); + + /* Read image base address. */ + Offset = FIELD_OFFSET(PEB, ImageBaseAddress); + NtReadVirtualMemory(ProcessHandle, + (PVOID)(PEB_BASE + Offset), + ImageBaseAddress, + sizeof(PVOID), + &BytesWritten); + + return(STATUS_SUCCESS); +} + + +WINBOOL STDCALL +CreateProcessW(LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + WINBOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + HANDLE hSection, hProcess, hThread; + NTSTATUS Status; + LPTHREAD_START_ROUTINE lpStartAddress = NULL; + WCHAR ImagePathName[256]; + UNICODE_STRING ImagePathName_U; + PROCESS_BASIC_INFORMATION ProcessBasicInfo; + ULONG retlen; + PRTL_USER_PROCESS_PARAMETERS Ppb; + UNICODE_STRING CommandLine_U; + CSRSS_API_REQUEST CsrRequest; + CSRSS_API_REPLY CsrReply; + CHAR ImageFileName[8]; + PWCHAR s, e; + ULONG i, len; + ANSI_STRING ProcedureName; + UNICODE_STRING CurrentDirectory_U; + SECTION_IMAGE_INFORMATION Sii; + WCHAR TempCurrentDirectoryW[256]; + WCHAR TempApplicationNameW[256]; + WCHAR TempCommandLineNameW[256]; + UNICODE_STRING RuntimeInfo_U; + PVOID ImageBaseAddress; + + DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n", + lpApplicationName, lpCommandLine); + + if (lpApplicationName != NULL && lpApplicationName[0] != 0) + { + wcscpy (TempApplicationNameW, lpApplicationName); + i = wcslen(TempApplicationNameW); + if (TempApplicationNameW[i - 1] == L'.') + { + TempApplicationNameW[i - 1] = 0; + } + else + { + s = max(wcsrchr(TempApplicationNameW, L'\\'), wcsrchr(TempApplicationNameW, L'/')); + if (s == NULL) + { + s = TempApplicationNameW; + } + else + { + s++; + } + e = wcsrchr(s, L'.'); + if (e == NULL) + { + wcscat(s, L".exe"); + e = wcsrchr(s, L'.'); + } + } + } + else if (lpCommandLine != NULL && lpCommandLine[0] != 0) + { + if (lpCommandLine[0] == L'"') + { + wcscpy(TempApplicationNameW, &lpCommandLine[0]); + s = wcschr(TempApplicationNameW, L'"'); + if (s == NULL) + { + return FALSE; + } + *s = 0; + } + else + { + wcscpy(TempApplicationNameW, lpCommandLine); + s = wcschr(TempApplicationNameW, L' '); + if (s != NULL) + { + *s = 0; + } + } + s = max(wcsrchr(TempApplicationNameW, L'\\'), wcsrchr(TempApplicationNameW, L'/')); + if (s == NULL) + { + s = TempApplicationNameW; + } + s = wcsrchr(TempApplicationNameW, L'.'); + if (s == NULL) + wcscat(TempApplicationNameW, L".exe"); + } + else + { + return FALSE; + } + + if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s)) + { + return FALSE; + } + + e = wcsrchr(s, L'.'); + if (e != NULL && (!_wcsicmp(e, L".bat") || !_wcsicmp(e, L".cmd"))) + { + // the command is a batch file + if (lpApplicationName != NULL && lpApplicationName[0]) + { + // FIXME: use COMSPEC for the command interpreter + wcscpy(TempCommandLineNameW, L"cmd /c "); + wcscat(TempCommandLineNameW, lpApplicationName); + lpCommandLine = TempCommandLineNameW; + wcscpy(TempApplicationNameW, L"cmd.exe"); + if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s)) + { + return FALSE; + } + } + else + { + return FALSE; + } + } + + /* + * Store the image file name for the process + */ + e = wcschr(s, L'.'); + if (e != NULL) + { + *e = 0; + } + for (i = 0; i < 8; i++) + { + ImageFileName[i] = (CHAR)(s[i]); + } + if (e != NULL) + { + *e = '.'; + } + + /* + * Process the application name and command line + */ + RtlInitUnicodeString(&ImagePathName_U, ImagePathName); + RtlInitUnicodeString(&CommandLine_U, lpCommandLine); + + DPRINT("ImagePathName_U %S\n", ImagePathName_U.Buffer); + DPRINT("CommandLine_U %S\n", CommandLine_U.Buffer); + + /* Initialize the current directory string */ + if (lpCurrentDirectory != NULL) + { + RtlInitUnicodeString(&CurrentDirectory_U, + lpCurrentDirectory); + } + else + { + GetCurrentDirectoryW(256, TempCurrentDirectoryW); + RtlInitUnicodeString(&CurrentDirectory_U, + TempCurrentDirectoryW); + } + + + /* + * Create a section for the executable + */ + + hSection = KlMapFile (ImagePathName); + if (hSection == NULL) + { + return FALSE; + } + + /* + * Create a new process + */ + Status = NtCreateProcess(&hProcess, + PROCESS_ALL_ACCESS, + NULL, + NtCurrentProcess(), + bInheritHandles, + hSection, + NULL, + NULL); + if (lpStartupInfo) + { + if (lpStartupInfo->lpReserved2) + { + ULONG i, Count = *(ULONG*)lpStartupInfo->lpReserved2; + HANDLE * hFile; + HANDLE hTemp; + PRTL_USER_PROCESS_PARAMETERS CurrPpb = NtCurrentPeb()->ProcessParameters; + + + /* FIXME: + * ROUND_UP(xxx,2) + 2 is a dirty hack. RtlCreateProcessParameters assumes that + * the runtimeinfo is a unicode string and use RtlCopyUnicodeString for duplication. + * If is possible that this function overwrite the last information in runtimeinfo + * with the null terminator for the unicode string. + */ + RuntimeInfo_U.Length = RuntimeInfo_U.MaximumLength = ROUND_UP(lpStartupInfo->cbReserved2, 2) + 2; + RuntimeInfo_U.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, RuntimeInfo_U.Length); + memcpy(RuntimeInfo_U.Buffer, lpStartupInfo->lpReserved2, lpStartupInfo->cbReserved2); + } + } + + /* + * Create the PPB + */ + RtlCreateProcessParameters(&Ppb, + &ImagePathName_U, + NULL, + lpCurrentDirectory ? &CurrentDirectory_U : NULL, + &CommandLine_U, + lpEnvironment, + NULL, + NULL, + NULL, + lpStartupInfo && lpStartupInfo->lpReserved2 ? &RuntimeInfo_U : NULL); + + if (lpStartupInfo && lpStartupInfo->lpReserved2) + RtlFreeHeap(GetProcessHeap(), 0, RuntimeInfo_U.Buffer); + + + /* + * Translate some handles for the new process + */ + if (Ppb->CurrentDirectoryHandle) + { + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->CurrentDirectoryHandle, + hProcess, + &Ppb->CurrentDirectoryHandle, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + } + + if (Ppb->hConsole) + { + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hConsole, + hProcess, + &Ppb->hConsole, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + } + + /* + * Get some information about the executable + */ + Status = ZwQuerySection(hSection, + SectionImageInformation, + &Sii, + sizeof(Sii), + &i); + /* + * Close the section + */ + NtClose(hSection); + + /* + * Get some information about the process + */ + ZwQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasicInfo, + sizeof(ProcessBasicInfo), + &retlen); + DPRINT("ProcessBasicInfo.UniqueProcessId %d\n", + ProcessBasicInfo.UniqueProcessId); + lpProcessInformation->dwProcessId = ProcessBasicInfo.UniqueProcessId; + + /* + * Tell the csrss server we are creating a new process + */ + CsrRequest.Type = CSRSS_CREATE_PROCESS; + CsrRequest.Data.CreateProcessRequest.NewProcessId = + ProcessBasicInfo.UniqueProcessId; + CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags; + Status = CsrClientCallServer(&CsrRequest, + &CsrReply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) + { + DbgPrint("Failed to tell csrss about new process. Expect trouble.\n"); + } + + // Set the child console handles + Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput; + Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput; + Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError; + + if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES)) + { + if (lpStartupInfo->hStdInput) + Ppb->hStdInput = lpStartupInfo->hStdInput; + if (lpStartupInfo->hStdOutput) + Ppb->hStdOutput = lpStartupInfo->hStdOutput; + if (lpStartupInfo->hStdError) + Ppb->hStdError = lpStartupInfo->hStdError; + } + + if (IsConsoleHandle(Ppb->hStdInput)) + { + Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle; + } + else + { + DPRINT("Duplicate input handle\n"); + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hStdInput, + hProcess, + &Ppb->hStdInput, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if(!NT_SUCCESS(Status)) + { + DPRINT("NtDuplicateObject failed, status %x\n", Status); + } + } + + if (IsConsoleHandle(Ppb->hStdOutput)) + { + Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle; + } + else + { + DPRINT("Duplicate output handle\n"); + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hStdOutput, + hProcess, + &Ppb->hStdOutput, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if(!NT_SUCCESS(Status)) + { + DPRINT("NtDuplicateObject failed, status %x\n", Status); + } + } + if (IsConsoleHandle(Ppb->hStdError)) + { + Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle; + } + else + { + DPRINT("Duplicate error handle\n"); + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hStdError, + hProcess, + &Ppb->hStdError, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if(!NT_SUCCESS(Status)) + { + DPRINT("NtDuplicateObject failed, status %x\n", Status); + } + } + + /* + * Initialize some other fields in the PPB + */ + if (lpStartupInfo) + { + Ppb->dwFlags = lpStartupInfo->dwFlags; + if (Ppb->dwFlags & STARTF_USESHOWWINDOW) + { + Ppb->wShowWindow = lpStartupInfo->wShowWindow; + } + else + { + Ppb->wShowWindow = SW_SHOWDEFAULT; + } + Ppb->dwX = lpStartupInfo->dwX; + Ppb->dwY = lpStartupInfo->dwY; + Ppb->dwXSize = lpStartupInfo->dwXSize; + Ppb->dwYSize = lpStartupInfo->dwYSize; + Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute; + } + else + { + Ppb->Flags = 0; + } + + /* + * Create Process Environment Block + */ + DPRINT("Creating peb\n"); + + KlInitPeb(hProcess, Ppb, &ImageBaseAddress); + + RtlDestroyProcessParameters (Ppb); + + Status = NtSetInformationProcess(hProcess, + ProcessImageFileName, + ImageFileName, + 8); + /* + * Create the thread for the kernel + */ + DPRINT("Creating thread for process\n"); + hThread = KlCreateFirstThread(hProcess, + lpThreadAttributes, + Sii.StackReserve, + Sii.StackCommit, + ImageBaseAddress + (ULONG)Sii.EntryPoint, + dwCreationFlags, + &lpProcessInformation->dwThreadId); + if (hThread == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + lpProcessInformation->hProcess = hProcess; + lpProcessInformation->hThread = hThread; + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/process/proc.c b/lib/kernel32/process/proc.c new file mode 100644 index 0000000..a243ce4 --- /dev/null +++ b/lib/kernel32/process/proc.c @@ -0,0 +1,706 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/proc/proc.c + * PURPOSE: Process functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle; + +LPSTARTUPINFO lpLocalStartupInfo = NULL; + +VOID STDCALL +RegisterWaitForInputIdle (WaitForInputIdleType lpfnRegisterWaitForInputIdle); + + +/* FUNCTIONS ****************************************************************/ + +WINBOOL STDCALL +GetProcessId (HANDLE hProcess, LPDWORD lpProcessId); + +WINBOOL STDCALL +GetProcessAffinityMask(HANDLE hProcess, + LPDWORD lpProcessAffinityMask, + LPDWORD lpSystemAffinityMask) +{ + if ((NULL == lpProcessAffinityMask) + || (NULL == lpSystemAffinityMask)) + { + SetLastError(ERROR_BAD_ARGUMENTS); + return(FALSE); + } + + /* FIXME: check hProcess is actually a process */ + /* FIXME: query the kernel process object */ + *lpProcessAffinityMask = 0x00000001; + *lpSystemAffinityMask = 0x00000001; + + return(TRUE); +} + + +WINBOOL STDCALL +GetProcessShutdownParameters(LPDWORD lpdwLevel, + LPDWORD lpdwFlags) +{ + CSRSS_API_REQUEST CsrRequest; + CSRSS_API_REPLY CsrReply; + NTSTATUS Status; + + CsrRequest.Type = CSRSS_GET_SHUTDOWN_PARAMETERS; + Status = CsrClientCallServer(&CsrRequest, + &CsrReply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) + { + SetLastError(Status); + return(FALSE); + } + + *lpdwLevel = CsrReply.Data.GetShutdownParametersReply.Level; + *lpdwFlags = CsrReply.Data.GetShutdownParametersReply.Flags; + + return(TRUE); +} + + +WINBOOL STDCALL +SetProcessShutdownParameters(DWORD dwLevel, + DWORD dwFlags) +{ + CSRSS_API_REQUEST CsrRequest; + CSRSS_API_REPLY CsrReply; + NTSTATUS Status; + + CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel; + CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags; + + CsrRequest.Type = CSRSS_SET_SHUTDOWN_PARAMETERS; + Status = CsrClientCallServer(&CsrRequest, + &CsrReply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) + { + SetLastError(Status); + return(FALSE); + } + + return(TRUE); +} + + +WINBOOL STDCALL +GetProcessWorkingSetSize(HANDLE hProcess, + LPDWORD lpMinimumWorkingSetSize, + LPDWORD lpMaximumWorkingSetSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return(FALSE); +} + + +WINBOOL STDCALL +SetProcessWorkingSetSize(HANDLE hProcess, + DWORD dwMinimumWorkingSetSize, + DWORD dwMaximumWorkingSetSize) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return(FALSE); +} + + +WINBOOL STDCALL +GetProcessTimes(HANDLE hProcess, + LPFILETIME lpCreationTime, + LPFILETIME lpExitTime, + LPFILETIME lpKernelTime, + LPFILETIME lpUserTime) +{ + KERNEL_USER_TIMES Kut; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessTimes, + &Kut, + sizeof(Kut), + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart; + lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart; + + lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart; + lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart; + + lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart; + lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart; + + lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart; + lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart; + + return(TRUE); +} + + +HANDLE STDCALL +GetCurrentProcess(VOID) +{ + return((HANDLE)NtCurrentProcess()); +} + + +HANDLE STDCALL +GetCurrentThread(VOID) +{ + return((HANDLE)NtCurrentThread()); +} + + +DWORD STDCALL +GetCurrentProcessId(VOID) +{ + return((DWORD)GetTeb()->Cid.UniqueProcess); +} + + +WINBOOL STDCALL +GetExitCodeProcess(HANDLE hProcess, + LPDWORD lpExitCode) +{ + PROCESS_BASIC_INFORMATION ProcessBasic; + ULONG BytesWritten; + NTSTATUS Status; + + Status = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasic, + sizeof(PROCESS_BASIC_INFORMATION), + &BytesWritten); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return(FALSE); + } + + memcpy(lpExitCode, &ProcessBasic.ExitStatus, sizeof(DWORD)); + + return(TRUE); +} + + +WINBOOL STDCALL +GetProcessId(HANDLE hProcess, + LPDWORD lpProcessId) +{ + NTSTATUS errCode; + PROCESS_BASIC_INFORMATION ProcessBasic; + ULONG BytesWritten; + + errCode = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasic, + sizeof(PROCESS_BASIC_INFORMATION), + &BytesWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return FALSE; + } + memcpy( lpProcessId ,&ProcessBasic.UniqueProcessId,sizeof(DWORD)); + return TRUE; +} + + +HANDLE STDCALL +OpenProcess(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + DWORD dwProcessId) +{ + NTSTATUS errCode; + HANDLE ProcessHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId ; + + ClientId.UniqueProcess = (HANDLE)dwProcessId; + ClientId.UniqueThread = INVALID_HANDLE_VALUE; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = (HANDLE)NULL; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + ObjectAttributes.ObjectName = NULL; + + if (bInheritHandle == TRUE) + ObjectAttributes.Attributes = OBJ_INHERIT; + else + ObjectAttributes.Attributes = 0; + + errCode = NtOpenProcess(&ProcessHandle, + dwDesiredAccess, + &ObjectAttributes, + &ClientId); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return NULL; + } + return ProcessHandle; +} + + +UINT STDCALL +WinExec(LPCSTR lpCmdLine, + UINT uCmdShow) +{ + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInformation; + HINSTANCE hInst; + DWORD dosErr; + + StartupInfo.cb = sizeof(STARTUPINFOA); + StartupInfo.wShowWindow = uCmdShow; + StartupInfo.dwFlags = 0; + + hInst = (HINSTANCE)CreateProcessA(NULL, + (PVOID)lpCmdLine, + NULL, + NULL, + FALSE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + if ( hInst == NULL ) + { + dosErr = GetLastError(); + return dosErr; + } + if (NULL != lpfnGlobalRegisterWaitForInputIdle) + { + lpfnGlobalRegisterWaitForInputIdle ( + ProcessInformation.hProcess, + 10000 + ); + } + NtClose (ProcessInformation.hProcess); + NtClose (ProcessInformation.hThread); + return 0; +} + + +VOID STDCALL +RegisterWaitForInputIdle ( + WaitForInputIdleType lpfnRegisterWaitForInputIdle + ) +{ + lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle; + return; +} + + +DWORD STDCALL +WaitForInputIdle ( + HANDLE hProcess, + DWORD dwMilliseconds + ) +{ + return 0; +} + + +VOID STDCALL +Sleep(DWORD dwMilliseconds) +{ + SleepEx(dwMilliseconds, FALSE); + return; +} + + +DWORD STDCALL +SleepEx(DWORD dwMilliseconds, + BOOL bAlertable) +{ + TIME Interval; + NTSTATUS errCode; + + if (dwMilliseconds != INFINITE) + { + /* + * System time units are 100 nanoseconds (a nanosecond is a billionth of + * a second). + */ + Interval.QuadPart = dwMilliseconds; + Interval.QuadPart = -(Interval.QuadPart * 10000); + } + else + { + /* Approximately 292000 years hence */ + Interval.QuadPart = -0x7FFFFFFFFFFFFFFF; + } + + errCode = NtDelayExecution (bAlertable, &Interval); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return -1; + } + return 0; +} + + +VOID STDCALL +GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo) +{ + PRTL_USER_PROCESS_PARAMETERS Params; + + if (lpStartupInfo == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return; + } + + Params = NtCurrentPeb()->ProcessParameters; + + lpStartupInfo->cb = sizeof(STARTUPINFOW); + lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer; + lpStartupInfo->lpTitle = Params->WindowTitle.Buffer; + lpStartupInfo->dwX = Params->dwX; + lpStartupInfo->dwY = Params->dwY; + lpStartupInfo->dwXSize = Params->dwXSize; + lpStartupInfo->dwYSize = Params->dwYSize; + lpStartupInfo->dwXCountChars = Params->dwXCountChars; + lpStartupInfo->dwYCountChars = Params->dwYCountChars; + lpStartupInfo->dwFillAttribute = Params->dwFillAttribute; + lpStartupInfo->dwFlags = Params->dwFlags; + lpStartupInfo->wShowWindow = Params->wShowWindow; + lpStartupInfo->lpReserved = Params->ShellInfo.Buffer; + lpStartupInfo->cbReserved2 = Params->RuntimeInfo.Length; + lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer; + + lpStartupInfo->hStdInput = Params->hStdInput; + lpStartupInfo->hStdOutput = Params->hStdOutput; + lpStartupInfo->hStdError = Params->hStdError; +} + + +VOID STDCALL +GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo) +{ + PRTL_USER_PROCESS_PARAMETERS Params; + ANSI_STRING AnsiString; + + if (lpStartupInfo == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return; + } + + Params = NtCurrentPeb ()->ProcessParameters; + + RtlAcquirePebLock (); + + if (lpLocalStartupInfo == NULL) + { + /* create new local startup info (ansi) */ + lpLocalStartupInfo = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + sizeof(STARTUPINFOA)); + + lpLocalStartupInfo->cb = sizeof(STARTUPINFOA); + + /* copy window title string */ + RtlUnicodeStringToAnsiString (&AnsiString, + &Params->WindowTitle, + TRUE); + lpLocalStartupInfo->lpTitle = AnsiString.Buffer; + + /* copy desktop info string */ + RtlUnicodeStringToAnsiString (&AnsiString, + &Params->DesktopInfo, + TRUE); + lpLocalStartupInfo->lpDesktop = AnsiString.Buffer; + + /* copy shell info string */ + RtlUnicodeStringToAnsiString (&AnsiString, + &Params->ShellInfo, + TRUE); + lpLocalStartupInfo->lpReserved = AnsiString.Buffer; + + lpLocalStartupInfo->dwX = Params->dwX; + lpLocalStartupInfo->dwY = Params->dwY; + lpLocalStartupInfo->dwXSize = Params->dwXSize; + lpLocalStartupInfo->dwYSize = Params->dwYSize; + lpLocalStartupInfo->dwXCountChars = Params->dwXCountChars; + lpLocalStartupInfo->dwYCountChars = Params->dwYCountChars; + lpLocalStartupInfo->dwFillAttribute = Params->dwFillAttribute; + lpLocalStartupInfo->dwFlags = Params->dwFlags; + lpLocalStartupInfo->wShowWindow = Params->wShowWindow; + lpLocalStartupInfo->cbReserved2 = Params->RuntimeInfo.Length; + lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer; + + lpLocalStartupInfo->hStdInput = Params->hStdInput; + lpLocalStartupInfo->hStdOutput = Params->hStdOutput; + lpLocalStartupInfo->hStdError = Params->hStdError; + } + + RtlReleasePebLock (); + + /* copy local startup info data to external startup info */ + memcpy (lpStartupInfo, + lpLocalStartupInfo, + sizeof(STARTUPINFOA)); +} + + +BOOL STDCALL +FlushInstructionCache (HANDLE hProcess, + LPCVOID lpBaseAddress, + DWORD dwSize) +{ + NTSTATUS Status; + + Status = NtFlushInstructionCache(hProcess, + (PVOID)lpBaseAddress, + dwSize); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + return TRUE; +} + + +VOID STDCALL +ExitProcess(UINT uExitCode) +{ + CSRSS_API_REQUEST CsrRequest; + CSRSS_API_REPLY CsrReply; + NTSTATUS Status; + + /* unload all dll's */ + LdrShutdownProcess (); + + /* notify csrss of process termination */ + CsrRequest.Type = CSRSS_TERMINATE_PROCESS; + Status = CsrClientCallServer(&CsrRequest, + &CsrReply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) + { + DbgPrint("Failed to tell csrss about terminating process. " + "Expect trouble.\n"); + } + + + NtTerminateProcess (NtCurrentProcess (), + uExitCode); +} + + +WINBOOL STDCALL +TerminateProcess (HANDLE hProcess, + UINT uExitCode) +{ + NTSTATUS Status; + + Status = NtTerminateProcess (hProcess, uExitCode); + if (NT_SUCCESS(Status)) + { + return TRUE; + } + SetLastErrorByStatus (Status); + return FALSE; +} + + +VOID STDCALL +FatalAppExitA (UINT uAction, + LPCSTR lpMessageText) +{ + UNICODE_STRING MessageTextU; + ANSI_STRING MessageText; + + RtlInitAnsiString (&MessageText, (LPSTR) lpMessageText); + + RtlAnsiStringToUnicodeString (&MessageTextU, + &MessageText, + TRUE); + + FatalAppExitW (uAction, MessageTextU.Buffer); + + RtlFreeUnicodeString (&MessageTextU); +} + + +VOID STDCALL +FatalAppExitW(UINT uAction, + LPCWSTR lpMessageText) +{ + return; +} + + +VOID STDCALL +FatalExit (int ExitCode) +{ + ExitProcess(ExitCode); +} + + +DWORD STDCALL +GetPriorityClass (HANDLE hProcess) +{ + HANDLE hProcessTmp; + DWORD CsrPriorityClass = 0; // This tells CSRSS we want to GET it! + NTSTATUS Status; + + Status = + NtDuplicateObject (GetCurrentProcess(), + hProcess, + GetCurrentProcess(), + &hProcessTmp, + (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION), + FALSE, + 0); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return (0); /* ERROR */ + } + /* Ask CSRSS to set it */ + CsrSetPriorityClass (hProcessTmp, &CsrPriorityClass); + NtClose (hProcessTmp); + /* Translate CSR->W32 priorities */ + switch (CsrPriorityClass) + { + case CSR_PRIORITY_CLASS_NORMAL: + return (NORMAL_PRIORITY_CLASS); /* 32 */ + case CSR_PRIORITY_CLASS_IDLE: + return (IDLE_PRIORITY_CLASS); /* 64 */ + case CSR_PRIORITY_CLASS_HIGH: + return (HIGH_PRIORITY_CLASS); /* 128 */ + case CSR_PRIORITY_CLASS_REALTIME: + return (REALTIME_PRIORITY_CLASS); /* 256 */ + } + SetLastError (ERROR_ACCESS_DENIED); + return (0); /* ERROR */ +} + + + +WINBOOL STDCALL +SetPriorityClass (HANDLE hProcess, + DWORD dwPriorityClass) +{ + HANDLE hProcessTmp; + DWORD CsrPriorityClass; + NTSTATUS Status; + + switch (dwPriorityClass) + { + case NORMAL_PRIORITY_CLASS: /* 32 */ + CsrPriorityClass = CSR_PRIORITY_CLASS_NORMAL; + break; + case IDLE_PRIORITY_CLASS: /* 64 */ + CsrPriorityClass = CSR_PRIORITY_CLASS_IDLE; + break; + case HIGH_PRIORITY_CLASS: /* 128 */ + CsrPriorityClass = CSR_PRIORITY_CLASS_HIGH; + break; + case REALTIME_PRIORITY_CLASS: /* 256 */ + CsrPriorityClass = CSR_PRIORITY_CLASS_REALTIME; + break; + default: + SetLastError (ERROR_INVALID_PARAMETER); + return (FALSE); + } + Status = + NtDuplicateObject (GetCurrentProcess(), + hProcess, + GetCurrentProcess(), + &hProcessTmp, + (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION), + FALSE, + 0); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return (FALSE); /* ERROR */ + } + /* Ask CSRSS to set it */ + Status = CsrSetPriorityClass (hProcessTmp, &CsrPriorityClass); + NtClose (hProcessTmp); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return (FALSE); + } + return (TRUE); +} + + +DWORD STDCALL +GetProcessVersion (DWORD ProcessId) +{ + DWORD Version = 0; + PIMAGE_NT_HEADERS NtHeader = NULL; + PVOID BaseAddress = NULL; + + /* Caller's */ + if (0 == ProcessId) + { + BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress; + NtHeader = RtlImageNtHeader (BaseAddress); + if (NULL != NtHeader) + { + Version = + (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) | + (NtHeader->OptionalHeader.MinorOperatingSystemVersion); + } + } + else /* other process */ + { + /* FIXME: open the other process */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + } + return (Version); +} + + + +/* EOF */ diff --git a/lib/kernel32/process/session.c b/lib/kernel32/process/session.c new file mode 100644 index 0000000..dca7cc4 --- /dev/null +++ b/lib/kernel32/process/session.c @@ -0,0 +1,28 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/proc/session.c + * PURPOSE: Win32 session (TS) functions + * PROGRAMMER: Emanuele Aliberti + * UPDATE HISTORY: + * 2001-12-07 created + */ +#include + +BOOL STDCALL ProcessIdToSessionId ( + DWORD dwProcessId, + DWORD* pSessionId + ) +{ + if (NULL != pSessionId) + { + /* TODO: implement TS */ + *pSessionId = 0; /* no TS */ + return TRUE; + } + return FALSE; +} + + +/* EOF */ diff --git a/lib/kernel32/string/.cvsignore b/lib/kernel32/string/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/string/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/string/lstring.c b/lib/kernel32/string/lstring.c new file mode 100644 index 0000000..855da67 --- /dev/null +++ b/lib/kernel32/string/lstring.c @@ -0,0 +1,136 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/file/lstring.c + * PURPOSE: Local string functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +#include +#include +#include + + +int +STDCALL +lstrcmpA( + LPCSTR lpString1, + LPCSTR lpString2 + ) +{ + return strcmp(lpString1,lpString2); +} + +int +STDCALL +lstrcmpiA( + LPCSTR lpString1, + LPCSTR lpString2 + ) +{ + return _stricmp(lpString1,lpString2); +} + +LPSTR +STDCALL +lstrcpynA( + LPSTR lpString1, + LPCSTR lpString2, + int iMaxLength + ) +{ + return strncpy(lpString1,lpString2,iMaxLength); +} + +LPSTR +STDCALL +lstrcpyA( + LPSTR lpString1, + LPCSTR lpString2 + ) +{ + return strcpy(lpString1,lpString2); +} + +LPSTR +STDCALL +lstrcatA( + LPSTR lpString1, + LPCSTR lpString2 + ) +{ + return strcat(lpString1,lpString2); +} + +int +STDCALL +lstrlenA( + LPCSTR lpString + ) +{ + return strlen(lpString); +} + +int +STDCALL +lstrcmpW( + LPCWSTR lpString1, + LPCWSTR lpString2 + ) +{ + return wcscmp(lpString1,lpString2); +} + +int +STDCALL +lstrcmpiW( + LPCWSTR lpString1, + LPCWSTR lpString2 + ) +{ + return _wcsicmp(lpString1,lpString2); +} + +LPWSTR +STDCALL +lstrcpynW( + LPWSTR lpString1, + LPCWSTR lpString2, + int iMaxLength + ) +{ + return wcsncpy(lpString1,lpString2,iMaxLength); +} + +LPWSTR +STDCALL +lstrcpyW( + LPWSTR lpString1, + LPCWSTR lpString2 + ) +{ + return wcscpy(lpString1,lpString2); +} + +LPWSTR +STDCALL +lstrcatW( + LPWSTR lpString1, + LPCWSTR lpString2 + ) +{ + return wcscat(lpString1,lpString2); +} + +int +STDCALL +lstrlenW( + LPCWSTR lpString + ) +{ + return wcslen(lpString); +} + + diff --git a/lib/kernel32/synch/.cvsignore b/lib/kernel32/synch/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/synch/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/synch/critical.c b/lib/kernel32/synch/critical.c new file mode 100644 index 0000000..188b470 --- /dev/null +++ b/lib/kernel32/synch/critical.c @@ -0,0 +1,32 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/sync/critical.c + * PURPOSE: Critical sections + * UPDATE HISTORY: + * Created 30/09/98 + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include + + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) +{ + NTSTATUS Status; + + Status = RtlInitializeCriticalSection(lpCriticalSection); + if (!NT_SUCCESS(Status)) + { + RtlRaiseStatus(Status); + } +} + +/* EOF */ diff --git a/lib/kernel32/synch/event.c b/lib/kernel32/synch/event.c new file mode 100644 index 0000000..1f7b48c --- /dev/null +++ b/lib/kernel32/synch/event.c @@ -0,0 +1,228 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/synch/event.c + * PURPOSE: Local string functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include +#include + +/* FUNCTIONS ****************************************************************/ + +HANDLE STDCALL +CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, + WINBOOL bManualReset, + WINBOOL bInitialState, + LPCSTR lpName) +{ + UNICODE_STRING EventNameU; + ANSI_STRING EventName; + HANDLE EventHandle; + + RtlInitUnicodeString (&EventNameU, NULL); + + if (lpName) + { + RtlInitAnsiString(&EventName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&EventNameU, + &EventName, + TRUE); + } + + EventHandle = CreateEventW(lpEventAttributes, + bManualReset, + bInitialState, + EventNameU.Buffer); + + if (lpName) + { + RtlFreeUnicodeString(&EventNameU); + } + + return EventHandle; +} + + +HANDLE STDCALL +CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, + WINBOOL bManualReset, + WINBOOL bInitialState, + LPCWSTR lpName) +{ + NTSTATUS Status; + HANDLE hEvent; + UNICODE_STRING EventNameString; + POBJECT_ATTRIBUTES PtrObjectAttributes; + OBJECT_ATTRIBUTES ObjectAttributes; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + if (lpName != NULL) + { + RtlInitUnicodeString(&EventNameString, (LPWSTR)lpName); + ObjectAttributes.ObjectName = &EventNameString; + } + + Status = NtCreateEvent(&hEvent, + STANDARD_RIGHTS_ALL|EVENT_READ_ACCESS|EVENT_WRITE_ACCESS, + &ObjectAttributes, + bManualReset, + bInitialState); + DPRINT( "Called\n" ); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return hEvent; +} + + +HANDLE STDCALL +OpenEventA(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName) +{ + UNICODE_STRING EventNameU; + ANSI_STRING EventName; + HANDLE EventHandle; + + RtlInitUnicodeString(&EventNameU, + NULL); + + if (lpName) + { + RtlInitAnsiString(&EventName, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&EventNameU, + &EventName, + TRUE); + } + + EventHandle = OpenEventW(dwDesiredAccess, + bInheritHandle, + EventNameU.Buffer); + + if (lpName) + { + RtlFreeUnicodeString(&EventNameU); + } + + return EventHandle; +} + + +HANDLE STDCALL +OpenEventW(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING EventNameString; + NTSTATUS Status; + HANDLE hEvent = NULL; + + if (lpName == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + RtlInitUnicodeString(&EventNameString, (LPWSTR)lpName); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &EventNameString; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + if (bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + + Status = NtOpenEvent(&hEvent, + dwDesiredAccess, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return hEvent; +} + + +WINBOOL STDCALL +PulseEvent(HANDLE hEvent) +{ + ULONG Count; + NTSTATUS Status; + + Status = NtPulseEvent(hEvent, + &Count); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus (Status); + return FALSE; + } + + return TRUE; +} + + +WINBOOL STDCALL +ResetEvent(HANDLE hEvent) +{ + NTSTATUS Status; + ULONG Count; + + Status = NtResetEvent(hEvent, + &Count); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + + +WINBOOL STDCALL +SetEvent(HANDLE hEvent) +{ + NTSTATUS Status; + ULONG Count; + + Status = NtSetEvent(hEvent, + &Count); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/synch/intrlck.c b/lib/kernel32/synch/intrlck.c new file mode 100644 index 0000000..e09d757 --- /dev/null +++ b/lib/kernel32/synch/intrlck.c @@ -0,0 +1,162 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/sync/intrlck.c + * PURPOSE: Inter lock increments + * UPDATE HISTORY: + * Created 30/09/99 + */ + +/* + * Win32 kernel functions + * + * Copyright 1995 Martin von Loewis + * Copyright 1997 Onno Hovers + */ + + +/************************************************************************ +* InterlockedIncrement * +* * +* InterlockedIncrement adds 1 to a long variable and returns * +* - a negative number if the result < 0 * +* - zero if the result == 0 * +* - a positive number if the result > 0 * +* * +* The returned number need not be equal to the result!!!! * +* note: * +* * +************************************************************************/ + +#include + +LONG +STDCALL +InterlockedIncrement(PLONG Addend) +{ + long ret = 0; + __asm__ + ( + "\tlock\n" /* for SMP systems */ + "\tincl (%1)\n" + "\tje 2f\n" + "\tjl 1f\n" + "\tincl %0\n" + "\tjmp 2f\n" + "1:\tdec %0\n" + "2:\n" + :"=r" (ret):"r" (Addend), "0" (0): "memory" + ); + return ret; +} + +/************************************************************************ +* InterlockedDecrement * +* * +* InterlockedIncrement adds 1 to a long variable and returns * +* - a negative number if the result < 0 * +* - zero if the result == 0 * +* - a positive number if the result > 0 * +* * +* The returned number need not be equal to the result!!!! * +************************************************************************/ + +LONG +STDCALL +InterlockedDecrement(LPLONG lpAddend) +{ + long ret; + __asm__ + ( + "\tlock\n" /* for SMP systems */ + "\tdecl (%1)\n" + "\tje 2f\n" + "\tjl 1f\n" + "\tincl %0\n" + "\tjmp 2f\n" + "1:\tdec %0\n" + "2:\n" + :"=r" (ret):"r" (lpAddend), "0" (0): "memory" + ); + return ret; + + +} + +/************************************************************************ + * InterlockedExchange + * + * Atomically exchanges a pair of values. + * + * RETURNS + * Prior value of value pointed to by Target + */ + +LONG +STDCALL +InterlockedExchange(LPLONG target, LONG value ) +{ + + long ret; + __asm__ ( /* lock for SMP systems */ + "lock\n\txchgl %0,(%1)" + :"=r" (ret):"r" (target), "0" (value):"memory" ); + return ret; + + +} + +/************************************************************************ + * InterlockedCompareExchange + * + * Atomically compares Destination and Comperand, and if found equal exchanges + * the value of Destination with Exchange + * + * RETURNS + * Prior value of value pointed to by Destination + */ +PVOID +STDCALL +InterlockedCompareExchange( + PVOID *Destination, + PVOID Exchange, + PVOID Comperand ) +{ + PVOID ret; + __asm__ ( /* lock for SMP systems */ + "lock\n\t" + "cmpxchgl %2,(%1)" + :"=r" (ret) + :"r" (Destination),"r" (Exchange), "0" (Comperand) + :"memory" ); + return ret; + +} + +/************************************************************************ + * InterlockedExchangeAdd + * + * Atomically adds Increment to Addend and returns the previous value of + * Addend + * + * RETURNS + * Prior value of value pointed to by Addend + */ +LONG +STDCALL +InterlockedExchangeAdd( + PLONG Addend, + LONG Increment +) +{ + + LONG ret; + __asm__ ( /* lock for SMP systems */ + "lock\n\t" + "xaddl %0,(%1)" + :"=r" (ret) + :"r" (Addend), "0" (Increment) + :"memory" ); + return ret; + +} diff --git a/lib/kernel32/synch/mutex.c b/lib/kernel32/synch/mutex.c new file mode 100644 index 0000000..2d94b51 --- /dev/null +++ b/lib/kernel32/synch/mutex.c @@ -0,0 +1,201 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/synch/mutex.c + * PURPOSE: Mutex functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 01/20/2001 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +HANDLE STDCALL +CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, + WINBOOL bInitialOwner, + LPCSTR lpName) +{ + UNICODE_STRING NameU; + ANSI_STRING Name; + HANDLE Handle; + + RtlInitAnsiString(&Name, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, + &Name, + TRUE); + + Handle = CreateMutexW(lpMutexAttributes, + bInitialOwner, + NameU.Buffer); + + RtlFreeUnicodeString(&NameU); + + return Handle; +} + + +HANDLE STDCALL +CreateMutexW(LPSECURITY_ATTRIBUTES lpMutexAttributes, + WINBOOL bInitialOwner, + LPCWSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + UNICODE_STRING NameString; + HANDLE MutantHandle; + + RtlInitUnicodeString(&NameString, + (LPWSTR)lpName); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &NameString; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + if (lpMutexAttributes != NULL) + { + ObjectAttributes.SecurityDescriptor = lpMutexAttributes->lpSecurityDescriptor; + if (lpMutexAttributes->bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + } + + Status = NtCreateMutant(&MutantHandle, + MUTEX_ALL_ACCESS, + &ObjectAttributes, + (BOOLEAN)bInitialOwner); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return MutantHandle; +} + + +HANDLE STDCALL +OpenMutexA(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING NameU; + ANSI_STRING Name; + HANDLE Handle; + NTSTATUS Status; + + if (lpName == NULL) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return NULL; + } + + RtlInitAnsiString(&Name, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, + &Name, + TRUE); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &NameU; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + if (bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + + Status = NtOpenMutant(&Handle, + (ACCESS_MASK)dwDesiredAccess, + &ObjectAttributes); + + RtlFreeUnicodeString(&NameU); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return Handle; +} + + +HANDLE STDCALL +OpenMutexW(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name; + HANDLE Handle; + NTSTATUS Status; + + if (lpName == NULL) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return NULL; + } + + RtlInitUnicodeString(&Name, + (LPWSTR)lpName); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &Name; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + if (bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + + Status = NtOpenMutant(&Handle, + (ACCESS_MASK)dwDesiredAccess, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return Handle; +} + + +WINBOOL STDCALL +ReleaseMutex(HANDLE hMutex) +{ + NTSTATUS Status; + + Status = NtReleaseMutant(hMutex, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + + +/* EOF */ diff --git a/lib/kernel32/synch/sem.c b/lib/kernel32/synch/sem.c new file mode 100644 index 0000000..d5c2e05 --- /dev/null +++ b/lib/kernel32/synch/sem.c @@ -0,0 +1,214 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/synch/sem.c + * PURPOSE: Semaphore functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 01/20/2001 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include +#include + +/* FUNCTIONS ****************************************************************/ + +HANDLE STDCALL +CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCSTR lpName) +{ + UNICODE_STRING NameU; + ANSI_STRING Name; + HANDLE Handle; + + RtlInitAnsiString(&Name, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, + &Name, + TRUE); + + Handle = CreateSemaphoreW(lpSemaphoreAttributes, + lInitialCount, + lMaximumCount, + NameU.Buffer); + + RtlFreeUnicodeString (&NameU); + + return Handle; +} + + +HANDLE STDCALL +CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCWSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + UNICODE_STRING NameString; + HANDLE SemaphoreHandle; + + if (lpName) + { + NameString.Length = lstrlenW(lpName)*sizeof(WCHAR); + } + else + { + NameString.Length = 0; + } + + NameString.Buffer = (WCHAR *)lpName; + NameString.MaximumLength = NameString.Length; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &NameString; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + if (lpSemaphoreAttributes != NULL) + { + ObjectAttributes.SecurityDescriptor = lpSemaphoreAttributes->lpSecurityDescriptor; + if (lpSemaphoreAttributes->bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + } + + Status = NtCreateSemaphore(&SemaphoreHandle, + SEMAPHORE_ALL_ACCESS, + &ObjectAttributes, + lInitialCount, + lMaximumCount); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + return SemaphoreHandle; +} + + +HANDLE STDCALL +OpenSemaphoreA(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING NameU; + ANSI_STRING Name; + HANDLE Handle; + NTSTATUS Status; + + if (lpName == NULL) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return NULL; + } + + RtlInitAnsiString(&Name, + (LPSTR)lpName); + RtlAnsiStringToUnicodeString(&NameU, + &Name, + TRUE); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &NameU; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + if (bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + + Status = NtOpenSemaphore(&Handle, + (ACCESS_MASK)dwDesiredAccess, + &ObjectAttributes); + + RtlFreeUnicodeString(&NameU); + + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return Handle; +} + + +HANDLE STDCALL +OpenSemaphoreW(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name; + HANDLE Handle; + NTSTATUS Status; + + if (lpName == NULL) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return NULL; + } + + RtlInitUnicodeString(&Name, + (LPWSTR)lpName); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = hBaseDir; + ObjectAttributes.ObjectName = &Name; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + if (bInheritHandle == TRUE) + { + ObjectAttributes.Attributes |= OBJ_INHERIT; + } + + Status = NtOpenSemaphore(&Handle, + (ACCESS_MASK)dwDesiredAccess, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return Handle; +} + + +WINBOOL STDCALL +ReleaseSemaphore(HANDLE hSemaphore, + LONG lReleaseCount, + LPLONG lpPreviousCount) +{ + NTSTATUS Status; + + Status = NtReleaseSemaphore(hSemaphore, + lReleaseCount, + lpPreviousCount); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/synch/timer.c b/lib/kernel32/synch/timer.c new file mode 100644 index 0000000..6199e45 --- /dev/null +++ b/lib/kernel32/synch/timer.c @@ -0,0 +1,188 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/kernel32/synch/timer.c + * PURPOSE: Implementing timer + * PROGRAMMER: + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +HANDLE STDCALL +CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes, + WINBOOL bManualReset, + LPWSTR lpTimerName) +{ + NTSTATUS Status; + HANDLE TimerHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeName; + ULONG TimerType; + + if (bManualReset) + TimerType = NotificationTimer; + else + TimerType = SynchronizationTimer; + + RtlInitUnicodeString(&UnicodeName, lpTimerName); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeName, + 0, + hBaseDir, + NULL); + + Status = NtCreateTimer(&TimerHandle, + TIMER_ALL_ACCESS, + &ObjectAttributes, + TimerType); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return TimerHandle; +} + + +HANDLE STDCALL +CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes, + WINBOOL bManualReset, + LPCSTR lpTimerName) +{ + UNICODE_STRING TimerNameU; + ANSI_STRING TimerName; + HANDLE TimerHandle; + + RtlInitAnsiString (&TimerName, + (LPSTR)lpTimerName); + RtlAnsiStringToUnicodeString (&TimerNameU, + &TimerName, + TRUE); + + TimerHandle = CreateWaitableTimerW (lpTimerAttributes, + bManualReset, + TimerNameU.Buffer); + + RtlFreeUnicodeString (&TimerNameU); + + return TimerHandle; +} + + +HANDLE STDCALL +OpenWaitableTimerW(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCWSTR lpTimerName) +{ + NTSTATUS Status; + HANDLE TimerHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeName; + ULONG Attributes = 0; + + if (bInheritHandle) + { + Attributes = OBJ_INHERIT; + } + + RtlInitUnicodeString(&UnicodeName, + lpTimerName); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeName, + Attributes, + hBaseDir, + NULL); + + Status = NtOpenTimer(&TimerHandle, + dwDesiredAccess, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return NULL; + } + + return TimerHandle; +} + + +HANDLE STDCALL +OpenWaitableTimerA(DWORD dwDesiredAccess, + WINBOOL bInheritHandle, + LPCSTR lpTimerName) +{ + UNICODE_STRING TimerNameU; + ANSI_STRING TimerName; + HANDLE TimerHandle; + + RtlInitAnsiString (&TimerName, + (LPSTR)lpTimerName); + RtlAnsiStringToUnicodeString (&TimerNameU, + &TimerName, + TRUE); + + TimerHandle = OpenWaitableTimerW (dwDesiredAccess, + bInheritHandle, + TimerNameU.Buffer); + + RtlFreeUnicodeString (&TimerNameU); + + return TimerHandle; +} + + +WINBOOL STDCALL +SetWaitableTimer(HANDLE hTimer, + const LARGE_INTEGER *pDueTime, + LONG lPeriod, + PTIMERAPCROUTINE pfnCompletionRoutine, + LPVOID lpArgToCompletionRoutine, + WINBOOL fResume) +{ + NTSTATUS Status; + BOOLEAN pState; + + Status = NtSetTimer(hTimer, + (LARGE_INTEGER *)pDueTime, + pfnCompletionRoutine, + lpArgToCompletionRoutine, + fResume, + lPeriod, + &pState); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + return TRUE; +} + + +WINBOOL STDCALL +CancelWaitableTimer(HANDLE hTimer) +{ + NTSTATUS Status; + BOOLEAN CurrentState; + + Status = NtCancelTimer(hTimer, + &CurrentState); + if (!NT_SUCCESS(Status)) + { + SetLastErrorByStatus(Status); + return FALSE; + } + return TRUE; +} + +/* EOF */ diff --git a/lib/kernel32/synch/wait.c b/lib/kernel32/synch/wait.c new file mode 100644 index 0000000..af4ecc5 --- /dev/null +++ b/lib/kernel32/synch/wait.c @@ -0,0 +1,143 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/synch/wait.c + * PURPOSE: Wait functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +DWORD STDCALL +WaitForSingleObject(HANDLE hHandle, + DWORD dwMilliseconds) +{ + return WaitForSingleObjectEx(hHandle, + dwMilliseconds, + FALSE); +} + + +DWORD STDCALL +WaitForSingleObjectEx(HANDLE hHandle, + DWORD dwMilliseconds, + BOOL bAlertable) +{ + NTSTATUS errCode; + PLARGE_INTEGER TimePtr; + LARGE_INTEGER Time; + + if (dwMilliseconds == INFINITE) + { + TimePtr = NULL; + } + else + { + Time.QuadPart = -10000 * dwMilliseconds; + TimePtr = &Time; + } + + errCode = NtWaitForSingleObject(hHandle, + (BOOLEAN) bAlertable, + TimePtr); + if (errCode == STATUS_TIMEOUT) + { + return WAIT_TIMEOUT; + } + else if ((errCode == WAIT_OBJECT_0) || + (errCode == WAIT_ABANDONED_0)) + { + return(errCode); + } + + SetLastErrorByStatus (errCode); + + return(WAIT_FAILED); +} + + +DWORD STDCALL +WaitForMultipleObjects(DWORD nCount, + CONST HANDLE *lpHandles, + BOOL bWaitAll, + DWORD dwMilliseconds) +{ + return WaitForMultipleObjectsEx(nCount, + lpHandles, + bWaitAll ? WaitAll : WaitAny, + dwMilliseconds, + FALSE); +} + + +DWORD STDCALL +WaitForMultipleObjectsEx(DWORD nCount, + CONST HANDLE *lpHandles, + BOOL bWaitAll, + DWORD dwMilliseconds, + BOOL bAlertable) +{ + NTSTATUS errCode; + LARGE_INTEGER Time; + PLARGE_INTEGER TimePtr; + + DPRINT("nCount %lu\n", nCount); + + if (dwMilliseconds == INFINITE) + { + TimePtr = NULL; + } + else + { + Time.QuadPart = -10000 * dwMilliseconds; + TimePtr = &Time; + } + + errCode = NtWaitForMultipleObjects (nCount, + (PHANDLE)lpHandles, + (CINT)bWaitAll, + (BOOLEAN)bAlertable, + TimePtr); + + if (errCode == STATUS_TIMEOUT) + { + return WAIT_TIMEOUT; + } + else if (((errCode >= WAIT_OBJECT_0) && + (errCode <= WAIT_OBJECT_0 + nCount - 1)) || + ((errCode >= WAIT_ABANDONED_0) && + (errCode <= WAIT_ABANDONED_0 + nCount - 1))) + { + return(errCode); + } + + DPRINT("errCode %lx\n", errCode); + SetLastErrorByStatus (errCode); + + return(WAIT_FAILED); +} + + +BOOL STDCALL +SignalObjectAndWait(HANDLE hObjectToSignal, + HANDLE hObjectToWaitOn, + DWORD dwMilliseconds, + BOOL bAlertable) +{ + UNIMPLEMENTED +} + +/* EOF */ diff --git a/lib/kernel32/thread/.cvsignore b/lib/kernel32/thread/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/kernel32/thread/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/kernel32/thread/fiber.c b/lib/kernel32/thread/fiber.c new file mode 100644 index 0000000..a96a0a2 --- /dev/null +++ b/lib/kernel32/thread/fiber.c @@ -0,0 +1,93 @@ +/* $Id$ + * + * FILE: lib/kernel32/thread/fiber.c + * + * ReactOS Kernel32.dll + * + */ +#include + + +/********************************************************************** + * ConvertThreadToFiber + */ +LPVOID +STDCALL +ConvertThreadToFiber( + LPVOID lpArgument + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * CreateFiber + */ +LPVOID +STDCALL +CreateFiber( + DWORD dwStackSize, + LPFIBER_START_ROUTINE lpStartAddress, + LPVOID lpArgument + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * DeleteFiber + */ +VOID +STDCALL +DeleteFiber( + LPVOID lpFiber + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return; +} + + +/********************************************************************** + * GetCurrentFiber + */ +PVOID +STDCALL +GetCurrentFiber(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * GetFiberData + */ +PVOID +STDCALL +GetFiberData(VOID) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + + +/********************************************************************** + * SwitchToFiber + */ +VOID +STDCALL +SwitchToFiber( + LPVOID lpFiber + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return; +} + + +/* EOF */ diff --git a/lib/kernel32/thread/thread.c b/lib/kernel32/thread/thread.c new file mode 100644 index 0000000..f64a980 --- /dev/null +++ b/lib/kernel32/thread/thread.c @@ -0,0 +1,476 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/thread/thread.c + * PURPOSE: Thread functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Tls functions are modified from WINE + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include +#include + + +static VOID ThreadAttachDlls (VOID); + +/* FUNCTIONS *****************************************************************/ + +static +EXCEPTION_DISPOSITION +__cdecl +_except_handler( + struct _EXCEPTION_RECORD *ExceptionRecord, + void * EstablisherFrame, + struct _CONTEXT *ContextRecord, + void * DispatcherContext ) +{ + ExitThread(0); + + /* We should not get to here */ + return ExceptionContinueSearch; +} + +static VOID STDCALL +ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter) +{ + UINT uExitCode; + + __try1(_except_handler) + { + /* FIXME: notify csrss of thread creation ?? */ + uExitCode = (lpStartAddress)(lpParameter); + } __except1 + { + } + + ExitThread(uExitCode); +} + +HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId) +{ + return(CreateRemoteThread(NtCurrentProcess(), + lpThreadAttributes, + dwStackSize, + lpStartAddress, + lpParameter, + dwCreationFlags, + lpThreadId)); +} + +HANDLE STDCALL CreateRemoteThread(HANDLE hProcess, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId) +{ + HANDLE ThreadHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + CLIENT_ID ClientId; + CONTEXT ThreadContext; + INITIAL_TEB InitialTeb; + BOOLEAN CreateSuspended = FALSE; + PVOID BaseAddress; + ULONG OldPageProtection; + NTSTATUS Status; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + if (lpThreadAttributes != NULL) + { + if (lpThreadAttributes->bInheritHandle) + ObjectAttributes.Attributes = OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = + lpThreadAttributes->lpSecurityDescriptor; + } + ObjectAttributes.SecurityQualityOfService = NULL; + + if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED) + CreateSuspended = TRUE; + else + CreateSuspended = FALSE; + + InitialTeb.StackReserve = 0x100000; /* 1MByte */ + /* FIXME: use correct commit size */ +#if 0 + InitialTeb.StackCommit = (dwStackSize == 0) ? PAGE_SIZE : dwStackSize; +#endif + InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE; + + /* size of guard page */ + InitialTeb.StackCommit += PAGE_SIZE; + + /* Reserve stack */ + InitialTeb.StackAllocate = NULL; + Status = NtAllocateVirtualMemory(hProcess, + &InitialTeb.StackAllocate, + 0, + &InitialTeb.StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Error reserving stack space!\n"); + SetLastErrorByStatus(Status); + return(NULL); + } + + DPRINT("StackDeallocation: %p ReserveSize: 0x%lX\n", + InitialTeb.StackDeallocation, InitialTeb.StackReserve); + + InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve); + InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit); + + DPRINT("StackBase: %p\nStackCommit: 0x%lX\n", + InitialTeb.StackBase, + InitialTeb.StackCommit); + + /* Commit stack pages */ + Status = NtAllocateVirtualMemory(hProcess, + &InitialTeb.StackLimit, + 0, + &InitialTeb.StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(hProcess, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting stack page(s)!\n"); + SetLastErrorByStatus(Status); + return(NULL); + } + + DPRINT("StackLimit: %p\n", + InitialTeb.StackLimit); + + /* Protect guard page */ + Status = NtProtectVirtualMemory(hProcess, + InitialTeb.StackLimit, + PAGE_SIZE, + PAGE_GUARD | PAGE_READWRITE, + &OldPageProtection); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(hProcess, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting guard page!\n"); + SetLastErrorByStatus(Status); + return(NULL); + } + + memset(&ThreadContext,0,sizeof(CONTEXT)); + ThreadContext.Eip = (LONG)ThreadStartup; + ThreadContext.SegGs = USER_DS; + ThreadContext.SegFs = TEB_SELECTOR; + ThreadContext.SegEs = USER_DS; + ThreadContext.SegDs = USER_DS; + ThreadContext.SegCs = USER_CS; + ThreadContext.SegSs = USER_DS; + ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 12; + ThreadContext.EFlags = (1<<1) + (1<<9); + + /* initialize call stack */ + *((PULONG)((ULONG)InitialTeb.StackBase - 4)) = (ULONG)lpParameter; + *((PULONG)((ULONG)InitialTeb.StackBase - 8)) = (ULONG)lpStartAddress; + *((PULONG)((ULONG)InitialTeb.StackBase - 12)) = 0xdeadbeef; + + DPRINT("Esp: %p\n", ThreadContext.Esp); + DPRINT("Eip: %p\n", ThreadContext.Eip); + + Status = NtCreateThread(&ThreadHandle, + THREAD_ALL_ACCESS, + &ObjectAttributes, + hProcess, + &ClientId, + &ThreadContext, + &InitialTeb, + CreateSuspended); + if (!NT_SUCCESS(Status)) + { + NtFreeVirtualMemory(hProcess, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("NtCreateThread() failed!\n"); + SetLastErrorByStatus(Status); + return(NULL); + } + + if (lpThreadId != NULL) + memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG)); + + return(ThreadHandle); +} + +PTEB +GetTeb(VOID) +{ + return(NtCurrentTeb()); +} + +WINBOOL STDCALL +SwitchToThread(VOID) +{ + NTSTATUS errCode; + errCode = NtYieldExecution(); + return TRUE; +} + +DWORD STDCALL +GetCurrentThreadId() +{ + return((DWORD)(NtCurrentTeb()->Cid).UniqueThread); +} + +VOID STDCALL +ExitThread(DWORD uExitCode) +{ + NTSTATUS errCode; + BOOLEAN LastThread; + NTSTATUS Status; + + /* + * Terminate process if this is the last thread + * of the current process + */ + Status = NtQueryInformationThread(NtCurrentThread(), + ThreadAmILastThread, + &LastThread, + sizeof(BOOLEAN), + NULL); + if (NT_SUCCESS(Status) && LastThread == TRUE) + { + ExitProcess (uExitCode); + } + + /* FIXME: notify csrss of thread termination */ + + LdrShutdownThread(); + + errCode = NtTerminateThread(NtCurrentThread(), + uExitCode); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + } +} + +WINBOOL STDCALL GetThreadTimes(HANDLE hThread, + LPFILETIME lpCreationTime, + LPFILETIME lpExitTime, + LPFILETIME lpKernelTime, + LPFILETIME lpUserTime) +{ + NTSTATUS errCode; + KERNEL_USER_TIMES KernelUserTimes; + ULONG ReturnLength; + + errCode = NtQueryInformationThread(hThread, + ThreadTimes, + &KernelUserTimes, + sizeof(KERNEL_USER_TIMES), + &ReturnLength); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + memcpy(lpCreationTime, &KernelUserTimes.CreateTime, sizeof(FILETIME)); + memcpy(lpExitTime, &KernelUserTimes.ExitTime, sizeof(FILETIME)); + memcpy(lpKernelTime, &KernelUserTimes.KernelTime, sizeof(FILETIME)); + memcpy(lpUserTime, &KernelUserTimes.UserTime, sizeof(FILETIME)); + return TRUE; +} + + +WINBOOL STDCALL GetThreadContext(HANDLE hThread, + LPCONTEXT lpContext) +{ + NTSTATUS errCode; + + errCode = NtGetContextThread(hThread, + lpContext); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + return TRUE; +} + +WINBOOL STDCALL SetThreadContext(HANDLE hThread, + CONST CONTEXT *lpContext) +{ + NTSTATUS errCode; + + errCode = NtSetContextThread(hThread, + (void *)lpContext); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + return TRUE; +} + +WINBOOL STDCALL GetExitCodeThread(HANDLE hThread, + LPDWORD lpExitCode) +{ + NTSTATUS errCode; + THREAD_BASIC_INFORMATION ThreadBasic; + ULONG DataWritten; + + errCode = NtQueryInformationThread(hThread, + ThreadBasicInformation, + &ThreadBasic, + sizeof(THREAD_BASIC_INFORMATION), + &DataWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD)); + return TRUE; +} + +DWORD STDCALL ResumeThread(HANDLE hThread) +{ + NTSTATUS errCode; + ULONG PreviousResumeCount; + + errCode = NtResumeThread(hThread, + &PreviousResumeCount); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return -1; + } + return PreviousResumeCount; +} + + +WINBOOL STDCALL +TerminateThread (HANDLE hThread, + DWORD dwExitCode) +{ + if (0 == hThread) + { + SetLastError (ERROR_INVALID_HANDLE); + } + else + { + NTSTATUS Status = NtTerminateThread (hThread, dwExitCode); + + if (NT_SUCCESS(Status)) + { + return TRUE; + } + SetLastErrorByStatus (Status); + } + return FALSE; +} + + +DWORD STDCALL SuspendThread(HANDLE hThread) +{ + NTSTATUS errCode; + ULONG PreviousSuspendCount; + + errCode = NtSuspendThread(hThread, + &PreviousSuspendCount); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return -1; + } + return PreviousSuspendCount; +} + +DWORD STDCALL SetThreadAffinityMask(HANDLE hThread, + DWORD dwThreadAffinityMask) +{ + return 0; +} + +WINBOOL STDCALL SetThreadPriority(HANDLE hThread, + int nPriority) +{ + NTSTATUS errCode; + THREAD_BASIC_INFORMATION ThreadBasic; + ULONG DataWritten; + + errCode = NtQueryInformationThread(hThread, + ThreadBasicInformation, + &ThreadBasic, + sizeof(THREAD_BASIC_INFORMATION), + &DataWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + ThreadBasic.BasePriority = nPriority; + errCode = NtSetInformationThread(hThread, + ThreadBasicInformation, + &ThreadBasic, + sizeof(THREAD_BASIC_INFORMATION)); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return FALSE; + } + return TRUE; +} + +int STDCALL GetThreadPriority(HANDLE hThread) +{ + NTSTATUS errCode; + THREAD_BASIC_INFORMATION ThreadBasic; + ULONG DataWritten; + + errCode = NtQueryInformationThread(hThread, + ThreadBasicInformation, + &ThreadBasic, + sizeof(THREAD_BASIC_INFORMATION), + &DataWritten); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus(errCode); + return THREAD_PRIORITY_ERROR_RETURN; + } + return ThreadBasic.BasePriority; +} + +/* EOF */ diff --git a/lib/kernel32/thread/tls.c b/lib/kernel32/thread/tls.c new file mode 100644 index 0000000..e3cc27b --- /dev/null +++ b/lib/kernel32/thread/tls.c @@ -0,0 +1,99 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/kernel32/thread/tls.c + * PURPOSE: Thread functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * Tls functions are modified from WINE + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +DWORD STDCALL +TlsAlloc(VOID) +{ + ULONG Index; + + RtlAcquirePebLock(); + Index = RtlFindClearBitsAndSet (NtCurrentPeb()->TlsBitmap, 1, 0); + if (Index == (ULONG)-1) + { + SetLastErrorByStatus(STATUS_NO_MEMORY); + } + else + { + NtCurrentTeb()->TlsSlots[Index] = 0; + } + RtlReleasePebLock(); + + return(Index); +} + +WINBOOL STDCALL +TlsFree(DWORD dwTlsIndex) +{ + if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return(FALSE); + } + + RtlAcquirePebLock(); + if (RtlAreBitsSet(NtCurrentPeb()->TlsBitmap, dwTlsIndex, 1)) + { + /* + * clear the tls cells (slots) in all threads + * of the current process + */ + NtSetInformationThread(NtCurrentThread(), + ThreadZeroTlsCell, + &dwTlsIndex, + sizeof(DWORD)); + RtlClearBits(NtCurrentPeb()->TlsBitmap, + dwTlsIndex, + 1); + } + RtlReleasePebLock(); + + return(TRUE); +} + +LPVOID STDCALL +TlsGetValue(DWORD dwTlsIndex) +{ + if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return(NULL); + } + return(NtCurrentTeb()->TlsSlots[dwTlsIndex]); +} + +WINBOOL STDCALL +TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) +{ + if (dwTlsIndex >= TLS_MINIMUM_AVAILABLE) + { + SetLastErrorByStatus(STATUS_INVALID_PARAMETER); + return(FALSE); + } + NtCurrentTeb()->TlsSlots[dwTlsIndex] = lpTlsValue; + return(TRUE); +} + +/* EOF */ diff --git a/lib/makefile b/lib/makefile new file mode 100644 index 0000000..6a32b6c --- /dev/null +++ b/lib/makefile @@ -0,0 +1,14 @@ +LIBRARIES = ntdll kernel32 + +BASE_CFLAGS = -I../include + +all: $(LIBRARIES) + +ntdll: dummy + make -C ntdll + +kernel32: dummy + make -C kernel32 + +dummy: + diff --git a/lib/msafd/.cvsignore b/lib/msafd/.cvsignore new file mode 100644 index 0000000..095ef4e --- /dev/null +++ b/lib/msafd/.cvsignore @@ -0,0 +1,7 @@ +msafd.a +msafd.dll +msafd.nostrip.dll +msafd.coff +base.tmp +junk.tmp +temp.exp diff --git a/lib/msafd/include/debug.h b/lib/msafd/include/debug.h new file mode 100644 index 0000000..0430c32 --- /dev/null +++ b/lib/msafd/include/debug.h @@ -0,0 +1,65 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_CHECK 0x00000100 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define AFD_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { AFD_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define AFD_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) + + +#define UNIMPLEMENTED \ + AFD_DbgPrint(MIN_TRACE, ("is unimplemented, please try again later.\n")); + +#define CHECKPOINT \ + AFD_DbgPrint(DEBUG_CHECK, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/msafd/include/helpers.h b/lib/msafd/include/helpers.h new file mode 100644 index 0000000..a4647ec --- /dev/null +++ b/lib/msafd/include/helpers.h @@ -0,0 +1,62 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/helpers.h + * PURPOSE: Definitions for helper DLL management + */ +#ifndef __HELPERS_H +#define __HELPERS_H + +#include + +typedef struct _WSHELPER_DLL_ENTRIES { + PWSH_ADDRESS_TO_STRING lpWSHAddressToString; + PWSH_ENUM_PROTOCOLS lpWSHEnumProtocols; + PWSH_GET_BROADCAST_SOCKADDR lpWSHGetBroadcastSockaddr; + PWSH_GET_PROVIDER_GUID lpWSHGetProviderGuid; + PWSH_GET_SOCKADDR_TYPE lpWSHGetSockaddrType; + PWSH_GET_SOCKET_INFORMATION lpWSHGetSocketInformation; + PWSH_GET_WILDCARD_SOCKEADDR lpWSHGetWildcardSockaddr; + PWSH_GET_WINSOCK_MAPPING lpWSHGetWinsockMapping; + PWSH_GET_WSAPROTOCOL_INFO lpWSHGetWSAProtocolInfo; + PWSH_IOCTL lpWSHIoctl; + PWSH_JOIN_LEAF lpWSHJoinLeaf; + PWSH_NOTIFY lpWSHNotify; + PWSH_OPEN_SOCKET lpWSHOpenSocket; + PWSH_OPEN_SOCKET2 lpWSHOpenSocket2; + PWSH_SET_SOCKET_INFORMATION lpWSHSetSocketInformation; + PWSH_STRING_TO_ADDRESS lpWSHStringToAddress; +} WSHELPER_DLL_ENTRIES, *PWSHELPER_DLL_ENTRIES; + +typedef struct _WSHELPER_DLL { + LIST_ENTRY ListEntry; + CRITICAL_SECTION Lock; + WCHAR LibraryName[MAX_PATH]; + HMODULE hModule; + WSHELPER_DLL_ENTRIES EntryTable; + PWINSOCK_MAPPING Mapping; +} WSHELPER_DLL, *PWSHELPER_DLL; + + +PWSHELPER_DLL CreateHelperDLL( + LPWSTR LibraryName); + +INT DestroyHelperDLL( + PWSHELPER_DLL HelperDLL); + +PWSHELPER_DLL LocateHelperDLL( + LPWSAPROTOCOL_INFOW lpProtocolInfo); + +INT LoadHelperDLL( + PWSHELPER_DLL HelperDLL); + +INT UnloadHelperDLL( + PWSHELPER_DLL HelperDLL); + +VOID CreateHelperDLLDatabase(VOID); + +VOID DestroyHelperDLLDatabase(VOID); + +#endif /* __HELPERS_H */ + +/* EOF */ diff --git a/lib/msafd/include/msafd.h b/lib/msafd/include/msafd.h new file mode 100644 index 0000000..46b560d --- /dev/null +++ b/lib/msafd/include/msafd.h @@ -0,0 +1,310 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/msafd.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __MSAFD_H +#define __MSAFD_H + +#include +#include +#include +#include +#include +#include +#include +#include + +extern HANDLE GlobalHeap; +extern WSPUPCALLTABLE Upcalls; +extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; + +SOCKET +WSPAPI +WSPAccept( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPAddressToString( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPAsyncSelect( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno); + +INT +WSPAPI WSPBind( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCancelBlockingCall( + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCleanup( + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCloseSocket( + IN SOCKET s, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPConnect( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPDuplicateSocket( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPEnumNetworkEvents( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPEventSelect( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WSPGetOverlappedResult( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetPeerName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WSPGetQOSByName( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetSockName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT LPINT optlen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPIoctl( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WSPJoinLeaf( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPListen( + IN SOCKET s, + IN INT backlog, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecv( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecvDisconnect( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecvFrom( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromlen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSelect( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSend( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSendDisconnect( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSendTo( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST LPSOCKADDR lpTo, + IN INT iTolen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPShutdown( + IN SOCKET s, + IN INT how, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WSPSocket( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPStringToAddress( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno); + +#endif /* __MSAFD_H */ + +/* EOF */ diff --git a/lib/msafd/makefile b/lib/msafd/makefile new file mode 100644 index 0000000..631dae2 --- /dev/null +++ b/lib/msafd/makefile @@ -0,0 +1,34 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = msafd + +TARGET_BASE = 0x777a0000 + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_CFLAGS = -I./include -DUNICODE -DDBG + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CLEAN = misc/*.o + + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + + +MISC_OBJECTS = \ + misc/dllmain.o misc/event.o misc/helpers.o \ + misc/sndrcv.o misc/stubs.o + +OBJECTS = $(MISC_OBJECTS) + +$(TARGET_NAME).o: $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o + +# EOF diff --git a/lib/msafd/misc/dllmain.c b/lib/msafd/misc/dllmain.c new file mode 100644 index 0000000..47f25c9 --- /dev/null +++ b/lib/msafd/misc/dllmain.c @@ -0,0 +1,884 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: misc/dllmain.c + * PURPOSE: DLL entry point + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MIN_TRACE; +//DWORD DebugTraceLevel = DEBUG_ULTRA; + +#endif /* DBG */ + +/* To make the linker happy */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +HANDLE GlobalHeap; +WSPUPCALLTABLE Upcalls; +LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; +CRITICAL_SECTION InitCriticalSection; +DWORD StartupCount = 0; +HANDLE CommandChannel; + + +NTSTATUS OpenSocket( + SOCKET *Socket, + INT AddressFamily, + INT SocketType, + INT Protocol, + PVOID HelperContext, + DWORD NotificationEvents, + PUNICODE_STRING TdiDeviceName) +/* + * FUNCTION: Opens a socket + * ARGUMENTS: + * Socket = Address of buffer to place socket descriptor + * AddressFamily = Address family + * SocketType = Type of socket + * Protocol = Protocol type + * HelperContext = Pointer to context information for helper DLL + * NotificationEvents = Events for which helper DLL is to be notified + * TdiDeviceName = Pointer to name of TDI device to use + * RETURNS: + * Status of operation + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PAFD_SOCKET_INFORMATION SocketInfo; + PFILE_FULL_EA_INFORMATION EaInfo; + UNICODE_STRING DeviceName; + IO_STATUS_BLOCK Iosb; + HANDLE FileHandle; + NTSTATUS Status; + ULONG EaLength; + ULONG EaShort; + + AFD_DbgPrint(MAX_TRACE, ("Socket (0x%X) TdiDeviceName (%wZ)\n", + Socket, TdiDeviceName)); + + AFD_DbgPrint(MAX_TRACE, ("Socket2 (0x%X) TdiDeviceName (%S)\n", + Socket, TdiDeviceName->Buffer)); + + EaShort = sizeof(FILE_FULL_EA_INFORMATION) + + AFD_SOCKET_LENGTH + + sizeof(AFD_SOCKET_INFORMATION); + + EaLength = EaShort + TdiDeviceName->Length + sizeof(WCHAR); + + EaInfo = (PFILE_FULL_EA_INFORMATION)HeapAlloc(GlobalHeap, 0, EaLength); + if (!EaInfo) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(EaInfo, EaLength); + EaInfo->EaNameLength = AFD_SOCKET_LENGTH; + RtlCopyMemory(EaInfo->EaName, + AfdSocket, + AFD_SOCKET_LENGTH); + EaInfo->EaValueLength = sizeof(AFD_SOCKET_INFORMATION); + + SocketInfo = (PAFD_SOCKET_INFORMATION)((ULONG_PTR)EaInfo->EaName + AFD_SOCKET_LENGTH); + SocketInfo->CommandChannel = FALSE; + SocketInfo->AddressFamily = AddressFamily; + SocketInfo->SocketType = SocketType; + SocketInfo->Protocol = Protocol; + SocketInfo->HelperContext = HelperContext; + SocketInfo->NotificationEvents = NotificationEvents; + /* Zeroed above so initialized to a wildcard address if a raw socket */ + SocketInfo->Name.sa_family = AddressFamily; + + /* Store TDI device name last in buffer */ + SocketInfo->TdiDeviceName.Buffer = (PWCHAR)(EaInfo + EaShort); + SocketInfo->TdiDeviceName.MaximumLength = TdiDeviceName->Length + sizeof(WCHAR); + RtlCopyUnicodeString(&SocketInfo->TdiDeviceName, TdiDeviceName); + + AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X) EaLength is (%d).\n", (UINT)EaInfo, (INT)EaLength)); + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\Afd"); + InitializeObjectAttributes( + &ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + + Status = NtCreateFile( + &FileHandle, + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + &ObjectAttributes, + &Iosb, + NULL, + 0, + 0, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_ALERT, + EaInfo, + EaLength); + + HeapFree(GlobalHeap, 0, EaInfo); + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE, ("Error opening device (Status 0x%X).\n", + (UINT)Status)); + return STATUS_INSUFFICIENT_RESOURCES; + } + + *Socket = (SOCKET)FileHandle; + + return STATUS_SUCCESS; +} + + +SOCKET +WSPAPI +WSPSocket( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags, + OUT LPINT lpErrno) +/* + * FUNCTION: Creates a new socket + * ARGUMENTS: + * af = Address family + * type = Socket type + * protocol = Protocol type + * lpProtocolInfo = Pointer to protocol information + * g = Reserved + * dwFlags = Socket flags + * lpErrno = Address of buffer for error information + * RETURNS: + * Created socket, or INVALID_SOCKET if it could not be created + */ +{ + WSAPROTOCOL_INFOW ProtocolInfo; + UNICODE_STRING TdiDeviceName; + DWORD NotificationEvents; + PWSHELPER_DLL HelperDLL; + PVOID HelperContext; + INT AddressFamily; + NTSTATUS NtStatus; + INT SocketType; + SOCKET Socket2; + SOCKET Socket; + INT Protocol; + INT Status; + + AFD_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", + af, type, protocol)); + + if (!lpProtocolInfo) { + lpProtocolInfo = &ProtocolInfo; + ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW)); + + ProtocolInfo.iAddressFamily = af; + ProtocolInfo.iSocketType = type; + ProtocolInfo.iProtocol = protocol; + } + + HelperDLL = LocateHelperDLL(lpProtocolInfo); + if (!HelperDLL) { + *lpErrno = WSAEAFNOSUPPORT; + return INVALID_SOCKET; + } + + AddressFamily = lpProtocolInfo->iAddressFamily; + SocketType = lpProtocolInfo->iSocketType; + Protocol = lpProtocolInfo->iProtocol; + + Status = HelperDLL->EntryTable.lpWSHOpenSocket2( + &AddressFamily, + &SocketType, + &Protocol, + 0, + 0, + &TdiDeviceName, + &HelperContext, + &NotificationEvents); + if (Status != NO_ERROR) { + AFD_DbgPrint(MAX_TRACE, ("WinSock Helper DLL failed (0x%X).\n", Status)); + *lpErrno = Status; + return INVALID_SOCKET; + } + + NtStatus = OpenSocket(&Socket, + AddressFamily, + SocketType, + Protocol, + HelperContext, + NotificationEvents, + &TdiDeviceName); + + RtlFreeUnicodeString(&TdiDeviceName); + if (!NT_SUCCESS(NtStatus)) { + *lpErrno = RtlNtStatusToDosError(Status); + return INVALID_SOCKET; + } + + /* FIXME: Assumes catalog entry id to be 1 */ + Socket2 = Upcalls.lpWPUModifyIFSHandle(1, Socket, lpErrno); + + if (Socket2 == INVALID_SOCKET) { + /* FIXME: Cleanup */ + AFD_DbgPrint(MIN_TRACE, ("FIXME: Cleanup.\n")); + return INVALID_SOCKET; + } + + *lpErrno = NO_ERROR; + + AFD_DbgPrint(MID_TRACE, ("Returning socket descriptor (0x%X).\n", Socket2)); + + return Socket2; +} + + +INT +WSPAPI +WSPCloseSocket( + IN SOCKET s, + OUT LPINT lpErrno) +/* + * FUNCTION: Closes an open socket + * ARGUMENTS: + * s = Socket descriptor + * lpErrno = Address of buffer for error information + * RETURNS: + * NO_ERROR, or SOCKET_ERROR if the socket could not be closed + */ +{ + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s)); + + Status = NtClose((HANDLE)s); + + if (NT_SUCCESS(Status)) { + *lpErrno = NO_ERROR; + return NO_ERROR; + } + + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; +} + + +INT +WSPAPI +WSPBind( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + OUT LPINT lpErrno) +/* + * FUNCTION: Associates a local address with a socket + * ARGUMENTS: + * s = Socket descriptor + * name = Pointer to local address + * namelen = Length of name + * lpErrno = Address of buffer for error information + * RETURNS: + * 0, or SOCKET_ERROR if the socket could not be bound + */ +{ + FILE_REQUEST_BIND Request; + FILE_REPLY_BIND Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("s (0x%X) name (0x%X) namelen (%d).\n", s, name, namelen)); + + RtlCopyMemory(&Request.Name, name, sizeof(SOCKADDR)); + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_BIND, + &Request, + sizeof(FILE_REQUEST_BIND), + &Reply, + sizeof(FILE_REPLY_BIND)); + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + *lpErrno = Reply.Status; + return SOCKET_ERROR; + } + + return 0; +} + +INT +WSPAPI +WSPListen( + IN SOCKET s, + IN INT backlog, + OUT LPINT lpErrno) +/* + * FUNCTION: Listens for incoming connections + * ARGUMENTS: + * s = Socket descriptor + * backlog = Maximum number of pending connection requests + * lpErrno = Address of buffer for error information + * RETURNS: + * 0, or SOCKET_ERROR if the socket could not be bound + */ +{ + FILE_REQUEST_LISTEN Request; + FILE_REPLY_LISTEN Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("s (0x%X) backlog (%d).\n", s, backlog)); + + Request.Backlog = backlog; + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_LISTEN, + &Request, + sizeof(FILE_REQUEST_LISTEN), + &Reply, + sizeof(FILE_REPLY_LISTEN)); + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + *lpErrno = Reply.Status; + return SOCKET_ERROR; + } + + return 0; +} + + +INT +WSPAPI +WSPSelect( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout, + OUT LPINT lpErrno) +/* + * FUNCTION: Returns status of one or more sockets + * ARGUMENTS: + * nfds = Always ignored + * readfds = Pointer to socket set to be checked for readability (optional) + * writefds = Pointer to socket set to be checked for writability (optional) + * exceptfds = Pointer to socket set to be checked for errors (optional) + * timeout = Pointer to a TIMEVAL structure indicating maximum wait time + * (NULL means wait forever) + * lpErrno = Address of buffer for error information + * RETURNS: + * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred + */ +{ + PFILE_REQUEST_SELECT Request; + FILE_REPLY_SELECT Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + DWORD Size; + DWORD ReadSize; + DWORD WriteSize; + DWORD ExceptSize; + PVOID Current; + + AFD_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n", + readfds, writefds, exceptfds)); +#if 0 + /* FIXME: For now, all reads are timed out immediately */ + if (readfds != NULL) { + AFD_DbgPrint(MID_TRACE, ("Timing out read query.\n")); + *lpErrno = WSAETIMEDOUT; + return SOCKET_ERROR; + } + + /* FIXME: For now, always allow write */ + if (writefds != NULL) { + AFD_DbgPrint(MID_TRACE, ("Setting one socket writeable.\n")); + *lpErrno = NO_ERROR; + return 1; + } +#endif + + ReadSize = 0; + if ((readfds != NULL) && (readfds->fd_count > 0)) { + ReadSize = (readfds->fd_count * sizeof(SOCKET)) + sizeof(UINT); + } + + WriteSize = 0; + if ((writefds != NULL) && (writefds->fd_count > 0)) { + WriteSize = (writefds->fd_count * sizeof(SOCKET)) + sizeof(UINT); + } + + ExceptSize = 0; + if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) { + ExceptSize = (exceptfds->fd_count * sizeof(SOCKET)) + sizeof(UINT); + } + + Size = ReadSize + WriteSize + ExceptSize; + + Request = (PFILE_REQUEST_SELECT)HeapAlloc( + GlobalHeap, 0, sizeof(FILE_REQUEST_SELECT) + Size); + if (!Request) { + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + /* Put FD SETs after request structure */ + Current = (Request + 1); + + if (ReadSize > 0) { + Request->ReadFDSet = (LPFD_SET)Current; + Current += ReadSize; + RtlCopyMemory(Request->ReadFDSet, readfds, ReadSize); + } else { + Request->ReadFDSet = NULL; + } + + if (WriteSize > 0) { + Request->WriteFDSet = (LPFD_SET)Current; + Current += WriteSize; + RtlCopyMemory(Request->WriteFDSet, writefds, WriteSize); + } else { + Request->WriteFDSet = NULL; + } + + if (ExceptSize > 0) { + Request->ExceptFDSet = (LPFD_SET)Current; + RtlCopyMemory(Request->ExceptFDSet, exceptfds, ExceptSize); + } else { + Request->ExceptFDSet = NULL; + } + + AFD_DbgPrint(MAX_TRACE, ("R1 (0x%X) W1 (0x%X).\n", Request->ReadFDSet, Request->WriteFDSet)); + + Status = NtDeviceIoControlFile( + CommandChannel, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_SELECT, + Request, + sizeof(FILE_REQUEST_SELECT) + Size, + &Reply, + sizeof(FILE_REPLY_SELECT)); + + HeapFree(GlobalHeap, 0, Request); + + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject(CommandChannel, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("Select successful. Status (0x%X) Count (0x%X).\n", + Reply.Status, Reply.SocketCount)); + + *lpErrno = Reply.Status; + + return Reply.SocketCount; +} + +SOCKET +WSPAPI +WSPAccept( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData, + OUT LPINT lpErrno) +{ + FILE_REQUEST_ACCEPT Request; + FILE_REPLY_ACCEPT Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s)); + + Request.addr = addr; + Request.addrlen = *addrlen; + Request.lpfnCondition = lpfnCondition; + Request.dwCallbackData = dwCallbackData; + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_ACCEPT, + &Request, + sizeof(FILE_REQUEST_ACCEPT), + &Reply, + sizeof(FILE_REPLY_ACCEPT)); + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + *lpErrno = Reply.Status; + return INVALID_SOCKET; + } + + *addrlen = Reply.addrlen; + + return Reply.Socket; +} + + +INT +WSPAPI +WSPConnect( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + OUT LPINT lpErrno) +{ + FILE_REQUEST_CONNECT Request; + FILE_REPLY_CONNECT Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + AFD_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s)); + + Request.name = name; + Request.namelen = namelen; + Request.lpCallerData = lpCallerData; + Request.lpCalleeData = lpCalleeData; + Request.lpSQOS = lpSQOS; + Request.lpGQOS = lpGQOS; + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_CONNECT, + &Request, + sizeof(FILE_REQUEST_CONNECT), + &Reply, + sizeof(FILE_REPLY_CONNECT)); + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + *lpErrno = Reply.Status; + return INVALID_SOCKET; + } + + return 0; +} + + +NTSTATUS OpenCommandChannel( + VOID) +/* + * FUNCTION: Opens a command channel to afd.sys + * ARGUMENTS: + * None + * RETURNS: + * Status of operation + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PAFD_SOCKET_INFORMATION SocketInfo; + PFILE_FULL_EA_INFORMATION EaInfo; + UNICODE_STRING DeviceName; + IO_STATUS_BLOCK Iosb; + HANDLE FileHandle; + NTSTATUS Status; + ULONG EaLength; + ULONG EaShort; + + AFD_DbgPrint(MAX_TRACE, ("Called\n")); + + EaShort = sizeof(FILE_FULL_EA_INFORMATION) + + AFD_SOCKET_LENGTH + + sizeof(AFD_SOCKET_INFORMATION); + + EaLength = EaShort; + + EaInfo = (PFILE_FULL_EA_INFORMATION)HeapAlloc(GlobalHeap, 0, EaLength); + if (!EaInfo) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(EaInfo, EaLength); + EaInfo->EaNameLength = AFD_SOCKET_LENGTH; + RtlCopyMemory(EaInfo->EaName, + AfdSocket, + AFD_SOCKET_LENGTH); + EaInfo->EaValueLength = sizeof(AFD_SOCKET_INFORMATION); + + SocketInfo = (PAFD_SOCKET_INFORMATION)((ULONG_PTR)EaInfo->EaName + AFD_SOCKET_LENGTH); + SocketInfo->CommandChannel = TRUE; + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\Device\\Afd"); + InitializeObjectAttributes( + &ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + + Status = NtCreateFile( + &FileHandle, + FILE_GENERIC_READ | FILE_GENERIC_WRITE, + &ObjectAttributes, + &Iosb, + NULL, + 0, + 0, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_ALERT, + EaInfo, + EaLength); + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MIN_TRACE, ("Error opening device (Status 0x%X).\n", + (UINT)Status)); + return Status; + } + + CommandChannel = FileHandle; + + return STATUS_SUCCESS; +} + + +NTSTATUS CloseCommandChannel( + VOID) +/* + * FUNCTION: Closes command channel to afd.sys + * ARGUMENTS: + * None + * RETURNS: + * Status of operation + */ +{ + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + return NtClose(CommandChannel); +} + + +INT +WSPAPI +WSPStartup( + IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable) +/* + * FUNCTION: Initialize service provider for a client + * ARGUMENTS: + * wVersionRequested = Highest WinSock SPI version that the caller can use + * lpWSPData = Address of WSPDATA structure to initialize + * lpProtocolInfo = Pointer to structure that defines the desired protocol + * UpcallTable = Pointer to upcall table of the WinSock DLL + * lpProcTable = Address of procedure table to initialize + * RETURNS: + * Status of operation + */ +{ + HMODULE hWS2_32; + INT Status; + + AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested)); + + EnterCriticalSection(&InitCriticalSection); + + Upcalls = UpcallTable; + + if (StartupCount == 0) { + /* First time called */ + + Status = OpenCommandChannel(); + if (NT_SUCCESS(Status)) { + hWS2_32 = GetModuleHandle(L"ws2_32.dll"); + if (hWS2_32 != NULL) { + lpWPUCompleteOverlappedRequest = (LPWPUCOMPLETEOVERLAPPEDREQUEST) + GetProcAddress(hWS2_32, "WPUCompleteOverlappedRequest"); + if (lpWPUCompleteOverlappedRequest != NULL) { + Status = NO_ERROR; + StartupCount++; + } + } else { + AFD_DbgPrint(MIN_TRACE, ("GetModuleHandle() failed for ws2_32.dll\n")); + } + } else { + AFD_DbgPrint(MIN_TRACE, ("Cannot open afd.sys\n")); + } + } else { + Status = NO_ERROR; + StartupCount++; + } + + LeaveCriticalSection(&InitCriticalSection); + + if (Status == NO_ERROR) { + lpProcTable->lpWSPAccept = WSPAccept; + lpProcTable->lpWSPAddressToString = WSPAddressToString; + lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect; + lpProcTable->lpWSPBind = WSPBind; + lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall; + lpProcTable->lpWSPCleanup = WSPCleanup; + lpProcTable->lpWSPCloseSocket = WSPCloseSocket; + lpProcTable->lpWSPConnect = WSPConnect; + lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket; + lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents; + lpProcTable->lpWSPEventSelect = WSPEventSelect; + lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult; + lpProcTable->lpWSPGetPeerName = WSPGetPeerName; + lpProcTable->lpWSPGetSockName = WSPGetSockName; + lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt; + lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName; + lpProcTable->lpWSPIoctl = WSPIoctl; + lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf; + lpProcTable->lpWSPListen = WSPListen; + lpProcTable->lpWSPRecv = WSPRecv; + lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect; + lpProcTable->lpWSPRecvFrom = WSPRecvFrom; + lpProcTable->lpWSPSelect = WSPSelect; + lpProcTable->lpWSPSend = WSPSend; + lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect; + lpProcTable->lpWSPSendTo = WSPSendTo; + lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt; + lpProcTable->lpWSPShutdown = WSPShutdown; + lpProcTable->lpWSPSocket = WSPSocket; + lpProcTable->lpWSPStringToAddress = WSPStringToAddress; + + lpWSPData->wVersion = MAKEWORD(2, 2); + lpWSPData->wHighVersion = MAKEWORD(2, 2); + } + + AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); + + return Status; +} + + +INT +WSPAPI +WSPCleanup( + OUT LPINT lpErrno) +/* + * FUNCTION: Cleans up service provider for a client + * ARGUMENTS: + * lpErrno = Address of buffer for error information + * RETURNS: + * 0 if successful, or SOCKET_ERROR if not + */ +{ + AFD_DbgPrint(MAX_TRACE, ("\n")); + + EnterCriticalSection(&InitCriticalSection); + + if (StartupCount > 0) { + StartupCount--; + + if (StartupCount == 0) { + AFD_DbgPrint(MAX_TRACE, ("Cleaning up msafd.dll.\n")); + + CloseCommandChannel(); + } + } + + LeaveCriticalSection(&InitCriticalSection); + + AFD_DbgPrint(MAX_TRACE, ("Leaving.\n")); + + *lpErrno = NO_ERROR; + + return 0; +} + + +BOOL +STDCALL +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications + so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + + InitializeCriticalSection(&InitCriticalSection); + + GlobalHeap = GetProcessHeap(); + + CreateHelperDLLDatabase(); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + + DestroyHelperDLLDatabase(); + + DeleteCriticalSection(&InitCriticalSection); + + break; + } + + AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n")); + + return TRUE; +} + +/* EOF */ diff --git a/lib/msafd/misc/event.c b/lib/msafd/misc/event.c new file mode 100644 index 0000000..910c6cf --- /dev/null +++ b/lib/msafd/misc/event.c @@ -0,0 +1,105 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: misc/event.c + * PURPOSE: Event handling + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 15/06-2001 Created + */ +#include + +INT +WSPAPI +WSPEventSelect( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents, + OUT LPINT lpErrno) +{ + FILE_REQUEST_EVENTSELECT Request; + FILE_REPLY_EVENTSELECT Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Request.hEventObject = hEventObject; + Request.lNetworkEvents = lNetworkEvents; + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_EVENTSELECT, + &Request, + sizeof(FILE_REQUEST_EVENTSELECT), + &Reply, + sizeof(FILE_REPLY_EVENTSELECT)); + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("Event select successful. Status (0x%X).\n", + Reply.Status)); + + *lpErrno = Reply.Status; + + return 0; +} + +INT +WSPAPI +WSPEnumNetworkEvents( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno) +{ + FILE_REQUEST_ENUMNETWORKEVENTS Request; + FILE_REPLY_ENUMNETWORKEVENTS Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + Request.hEventObject = hEventObject; + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_ENUMNETWORKEVENTS, + &Request, + sizeof(FILE_REQUEST_ENUMNETWORKEVENTS), + &Reply, + sizeof(FILE_REPLY_ENUMNETWORKEVENTS)); + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("EnumNetworkEvents successful. Status (0x%X).\n", + Reply.Status)); + + *lpErrno = Reply.Status; + + return 0; +} + +/* EOF */ diff --git a/lib/msafd/misc/helpers.c b/lib/msafd/misc/helpers.c new file mode 100644 index 0000000..648bad0 --- /dev/null +++ b/lib/msafd/misc/helpers.c @@ -0,0 +1,242 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: misc/helpers.c + * PURPOSE: Helper DLL management + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include + +CRITICAL_SECTION HelperDLLDatabaseLock; +LIST_ENTRY HelperDLLDatabaseListHead; + +PWSHELPER_DLL CreateHelperDLL( + LPWSTR LibraryName) +{ + PWSHELPER_DLL HelperDLL; + + HelperDLL = HeapAlloc(GlobalHeap, 0, sizeof(WSHELPER_DLL)); + if (!HelperDLL) + return NULL; + + InitializeCriticalSection(&HelperDLL->Lock); + HelperDLL->hModule = NULL; + lstrcpyW(HelperDLL->LibraryName, LibraryName); + HelperDLL->Mapping = NULL; + + EnterCriticalSection(&HelperDLLDatabaseLock); + InsertTailList(&HelperDLLDatabaseListHead, &HelperDLL->ListEntry); + LeaveCriticalSection(&HelperDLLDatabaseLock); + + AFD_DbgPrint(MAX_TRACE, ("Returning helper at (0x%X).\n", HelperDLL)); + + return HelperDLL; +} + + +INT DestroyHelperDLL( + PWSHELPER_DLL HelperDLL) +{ + INT Status; + + AFD_DbgPrint(MAX_TRACE, ("HelperDLL (0x%X).\n", HelperDLL)); + + EnterCriticalSection(&HelperDLLDatabaseLock); + RemoveEntryList(&HelperDLL->ListEntry); + LeaveCriticalSection(&HelperDLLDatabaseLock); + + if (HelperDLL->hModule) { + Status = UnloadHelperDLL(HelperDLL); + } else { + Status = NO_ERROR; + } + + if (HelperDLL->Mapping) + HeapFree(GlobalHeap, 0, HelperDLL->Mapping); + + DeleteCriticalSection(&HelperDLL->Lock); + + HeapFree(GlobalHeap, 0, HelperDLL); + + return Status; +} + + +PWSHELPER_DLL LocateHelperDLL( + LPWSAPROTOCOL_INFOW lpProtocolInfo) +{ + PLIST_ENTRY CurrentEntry; + PWSHELPER_DLL HelperDLL; + UINT i; + + EnterCriticalSection(&HelperDLLDatabaseLock); + CurrentEntry = HelperDLLDatabaseListHead.Flink; + while (CurrentEntry != &HelperDLLDatabaseListHead) { + HelperDLL = CONTAINING_RECORD(CurrentEntry, + WSHELPER_DLL, + ListEntry); + + for (i = 0; i < HelperDLL->Mapping->Rows; i++) { + if ((lpProtocolInfo->iAddressFamily == HelperDLL->Mapping->Mapping[i].AddressFamily) && + (lpProtocolInfo->iSocketType == HelperDLL->Mapping->Mapping[i].SocketType) && + ((lpProtocolInfo->iProtocol == HelperDLL->Mapping->Mapping[i].Protocol) || + (lpProtocolInfo->iSocketType == SOCK_RAW))) { + LeaveCriticalSection(&HelperDLLDatabaseLock); + AFD_DbgPrint(MAX_TRACE, ("Returning helper DLL at (0x%X).\n", HelperDLL)); + return HelperDLL; + } + } + + CurrentEntry = CurrentEntry->Flink; + } + LeaveCriticalSection(&HelperDLLDatabaseLock); + + AFD_DbgPrint(MAX_TRACE, ("Could not locate helper DLL.\n")); + + return NULL; +} + + +#define GET_ENTRY_POINT(helper, exportname, identifier) { \ + PVOID entry; \ + \ + entry = GetProcAddress(helper->hModule, exportname); \ + if (!entry) \ + return ERROR_BAD_PROVIDER; \ + ((PVOID)helper->EntryTable.##identifier) = entry; \ +} + + +INT GetHelperDLLEntries( + PWSHELPER_DLL HelperDLL) +{ + GET_ENTRY_POINT(HelperDLL, "WSHAddressToString", lpWSHAddressToString); + GET_ENTRY_POINT(HelperDLL, "WSHEnumProtocols", lpWSHEnumProtocols); + GET_ENTRY_POINT(HelperDLL, "WSHGetBroadcastSockaddr", lpWSHGetBroadcastSockaddr); + GET_ENTRY_POINT(HelperDLL, "WSHGetProviderGuid", lpWSHGetProviderGuid); + GET_ENTRY_POINT(HelperDLL, "WSHGetSockaddrType", lpWSHGetSockaddrType); + GET_ENTRY_POINT(HelperDLL, "WSHGetSocketInformation", lpWSHGetSocketInformation); + GET_ENTRY_POINT(HelperDLL, "WSHGetWildcardSockaddr", lpWSHGetWildcardSockaddr); + GET_ENTRY_POINT(HelperDLL, "WSHGetWinsockMapping", lpWSHGetWinsockMapping); + GET_ENTRY_POINT(HelperDLL, "WSHGetWSAProtocolInfo", lpWSHGetWSAProtocolInfo); + GET_ENTRY_POINT(HelperDLL, "WSHIoctl", lpWSHIoctl); + GET_ENTRY_POINT(HelperDLL, "WSHJoinLeaf", lpWSHJoinLeaf); + GET_ENTRY_POINT(HelperDLL, "WSHNotify", lpWSHNotify); + GET_ENTRY_POINT(HelperDLL, "WSHOpenSocket", lpWSHOpenSocket); + GET_ENTRY_POINT(HelperDLL, "WSHOpenSocket2", lpWSHOpenSocket2); + GET_ENTRY_POINT(HelperDLL, "WSHSetSocketInformation", lpWSHSetSocketInformation); + GET_ENTRY_POINT(HelperDLL, "WSHStringToAddress", lpWSHStringToAddress); + + return NO_ERROR; +} + + +INT LoadHelperDLL( + PWSHELPER_DLL HelperDLL) +{ + INT Status = NO_ERROR; + + AFD_DbgPrint(MAX_TRACE, ("Loading helper dll at (0x%X).\n", HelperDLL)); + + if (!HelperDLL->hModule) { + /* DLL is not loaded so load it now */ + HelperDLL->hModule = LoadLibrary(HelperDLL->LibraryName); + + AFD_DbgPrint(MAX_TRACE, ("hModule is (0x%X).\n", HelperDLL->hModule)); + + if (HelperDLL->hModule) { + Status = GetHelperDLLEntries(HelperDLL); + } else + Status = ERROR_DLL_NOT_FOUND; + } else + Status = NO_ERROR; + + AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); + + return Status; +} + + +INT UnloadHelperDLL( + PWSHELPER_DLL HelperDLL) +{ + INT Status = NO_ERROR; + + AFD_DbgPrint(MAX_TRACE, ("HelperDLL (0x%X) hModule (0x%X).\n", HelperDLL, HelperDLL->hModule)); + + if (HelperDLL->hModule) { + if (!FreeLibrary(HelperDLL->hModule)) { + Status = GetLastError(); + } + HelperDLL->hModule = NULL; + } + + return Status; +} + + +VOID CreateHelperDLLDatabase(VOID) +{ + PWSHELPER_DLL HelperDLL; + + InitializeCriticalSection(&HelperDLLDatabaseLock); + + InitializeListHead(&HelperDLLDatabaseListHead); + + /* FIXME: Read helper DLL configuration from registry */ + HelperDLL = CreateHelperDLL(L"wshtcpip.dll"); + if (!HelperDLL) + return; + + HelperDLL->Mapping = HeapAlloc( + GlobalHeap, + 0, + 3 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD)); + if (!HelperDLL->Mapping) + return; + + HelperDLL->Mapping->Rows = 3; + HelperDLL->Mapping->Columns = 3; + + HelperDLL->Mapping->Mapping[0].AddressFamily = AF_INET; + HelperDLL->Mapping->Mapping[0].SocketType = SOCK_STREAM; + HelperDLL->Mapping->Mapping[0].Protocol = IPPROTO_TCP; + + HelperDLL->Mapping->Mapping[1].AddressFamily = AF_INET; + HelperDLL->Mapping->Mapping[1].SocketType = SOCK_DGRAM; + HelperDLL->Mapping->Mapping[1].Protocol = IPPROTO_UDP; + + HelperDLL->Mapping->Mapping[2].AddressFamily = AF_INET; + HelperDLL->Mapping->Mapping[2].SocketType = SOCK_RAW; + HelperDLL->Mapping->Mapping[2].Protocol = 0; + + LoadHelperDLL(HelperDLL); +} + + +VOID DestroyHelperDLLDatabase(VOID) +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PWSHELPER_DLL HelperDLL; + + CurrentEntry = HelperDLLDatabaseListHead.Flink; + while (CurrentEntry != &HelperDLLDatabaseListHead) { + NextEntry = CurrentEntry->Flink; + + HelperDLL = CONTAINING_RECORD(CurrentEntry, + WSHELPER_DLL, + ListEntry); + + DestroyHelperDLL(HelperDLL); + + CurrentEntry = NextEntry; + } + + DeleteCriticalSection(&HelperDLLDatabaseLock); +} + +/* EOF */ diff --git a/lib/msafd/misc/sndrcv.c b/lib/msafd/misc/sndrcv.c new file mode 100644 index 0000000..742c0b2 --- /dev/null +++ b/lib/msafd/misc/sndrcv.c @@ -0,0 +1,350 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: misc/sndrcv.c + * PURPOSE: Send/receive routines + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +INT +WSPAPI +WSPAsyncSelect( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPRecv( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PFILE_REQUEST_RECV Request; + FILE_REPLY_RECV Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + DWORD Size; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + Size = dwBufferCount * sizeof(WSABUF); + + Request = (PFILE_REQUEST_RECV)HeapAlloc( + GlobalHeap, 0, sizeof(FILE_REQUEST_RECV) + Size); + if (!Request) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + /* Put buffer pointers after request structure */ + Request->Buffers = (LPWSABUF)(Request + 1); + Request->BufferCount = dwBufferCount; + Request->Flags = lpFlags; + + RtlCopyMemory(Request->Buffers, lpBuffers, Size); + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_RECV, + Request, + sizeof(FILE_REQUEST_RECV) + Size, + &Reply, + sizeof(FILE_REPLY_RECV)); + + HeapFree(GlobalHeap, 0, Request); + + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("Receive successful (0x%X).\n", + Reply.NumberOfBytesRecvd)); + + *lpNumberOfBytesRecvd = Reply.NumberOfBytesRecvd; + //*lpFlags = 0; + + return 0; +} + + +INT +WSPAPI +WSPRecvDisconnect( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WSPAPI +WSPRecvFrom( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromLen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PFILE_REQUEST_RECVFROM Request; + FILE_REPLY_RECVFROM Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + DWORD Size; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + Size = dwBufferCount * sizeof(WSABUF); + + Request = (PFILE_REQUEST_RECVFROM)HeapAlloc( + GlobalHeap, 0, sizeof(FILE_REQUEST_RECVFROM) + Size); + if (!Request) { + AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + /* Put buffer pointers after request structure */ + Request->Buffers = (LPWSABUF)(Request + 1); + Request->BufferCount = dwBufferCount; + Request->Flags = lpFlags; + Request->From = lpFrom; + Request->FromLen = lpFromLen; + + RtlCopyMemory(Request->Buffers, lpBuffers, Size); + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_RECVFROM, + Request, + sizeof(FILE_REQUEST_RECVFROM) + Size, + &Reply, + sizeof(FILE_REPLY_RECVFROM)); + + HeapFree(GlobalHeap, 0, Request); + + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("Receive successful (0x%X).\n", + Reply.NumberOfBytesRecvd)); + + *lpNumberOfBytesRecvd = Reply.NumberOfBytesRecvd; + //*lpFlags = 0; + ((PSOCKADDR_IN)lpFrom)->sin_family = AF_INET; + ((PSOCKADDR_IN)lpFrom)->sin_port = 0; + ((PSOCKADDR_IN)lpFrom)->sin_addr.S_un.S_addr = 0x0100007F; + *lpFromLen = sizeof(SOCKADDR_IN); + + return 0; +} + + +INT +WSPAPI +WSPSend( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PFILE_REQUEST_SENDTO Request; + FILE_REPLY_SENDTO Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + DWORD Size; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + Size = dwBufferCount * sizeof(WSABUF); + + Request = (PFILE_REQUEST_SENDTO)HeapAlloc( + GlobalHeap, 0, sizeof(FILE_REQUEST_SEND) + Size); + if (!Request) { + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + /* Put buffer pointers after request structure */ + Request->Buffers = (LPWSABUF)(Request + 1); + Request->BufferCount = dwBufferCount; + Request->Flags = dwFlags; + + RtlCopyMemory(Request->Buffers, lpBuffers, Size); + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_SEND, + Request, + sizeof(FILE_REQUEST_SEND) + Size, + &Reply, + sizeof(FILE_REPLY_SEND)); + + HeapFree(GlobalHeap, 0, Request); + + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("Send successful.\n")); + + return 0; +} + + +INT +WSPAPI +WSPSendDisconnect( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPSendTo( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST LPSOCKADDR lpTo, + IN INT iToLen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PFILE_REQUEST_SENDTO Request; + FILE_REPLY_SENDTO Reply; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + DWORD Size; + + AFD_DbgPrint(MAX_TRACE, ("Called.\n")); + + Size = dwBufferCount * sizeof(WSABUF); + + Request = (PFILE_REQUEST_SENDTO)HeapAlloc( + GlobalHeap, 0, sizeof(FILE_REQUEST_SENDTO) + Size); + if (!Request) { + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + /* Put buffer pointers after request structure */ + Request->Buffers = (LPWSABUF)(Request + 1); + Request->BufferCount = dwBufferCount; + Request->Flags = dwFlags; + Request->ToLen = iToLen; + + RtlCopyMemory(&Request->To, lpTo, sizeof(SOCKADDR)); + + RtlCopyMemory(Request->Buffers, lpBuffers, Size); + + Status = NtDeviceIoControlFile( + (HANDLE)s, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_AFD_SENDTO, + Request, + sizeof(FILE_REQUEST_SENDTO) + Size, + &Reply, + sizeof(FILE_REPLY_SENDTO)); + + HeapFree(GlobalHeap, 0, Request); + + if (Status == STATUS_PENDING) { + AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n")); + /* FIXME: Wait only for blocking sockets */ + Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL); + } + + if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status)); + *lpErrno = WSAENOBUFS; + return SOCKET_ERROR; + } + + AFD_DbgPrint(MAX_TRACE, ("Send successful.\n")); + + return 0; +} + +/* EOF */ diff --git a/lib/msafd/misc/stubs.c b/lib/msafd/misc/stubs.c new file mode 100644 index 0000000..003ff4d --- /dev/null +++ b/lib/msafd/misc/stubs.c @@ -0,0 +1,212 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: misc/stubs.c + * PURPOSE: Stubs + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + + +INT +WSPAPI +WSPAddressToString( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPCancelBlockingCall( + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPDuplicateSocket( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +BOOL +WSPAPI +WSPGetOverlappedResult( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return FALSE; +} + + +INT +WSPAPI +WSPGetPeerName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +BOOL +WSPAPI +WSPGetQOSByName( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return FALSE; +} + + +INT +WSPAPI +WSPGetSockName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPGetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT LPINT optlen, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPIoctl( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +SOCKET +WSPAPI +WSPJoinLeaf( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return (SOCKET)0; +} + + +INT +WSPAPI +WSPSetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPShutdown( + IN SOCKET s, + IN INT how, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WSPStringToAddress( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/lib/msafd/msafd.def b/lib/msafd/msafd.def new file mode 100644 index 0000000..54062c4 --- /dev/null +++ b/lib/msafd/msafd.def @@ -0,0 +1,10 @@ +; MSAFD.DLL - Ancillary Function Driver DLL + +LIBRARY msafd.dll + +EXPORTS +WSPGetSockOpt@24 +WSPSetSockOpt@24 +WSPStartup@76 + +; EOF diff --git a/lib/msafd/msafd.edf b/lib/msafd/msafd.edf new file mode 100644 index 0000000..731b6f6 --- /dev/null +++ b/lib/msafd/msafd.edf @@ -0,0 +1,10 @@ +; MSAFD.DLL - Ancillary Function Driver DLL + +LIBRARY msafd.dll + +EXPORTS +WSPGetSockOpt=WSPGetSockOpt@24 +WSPSetSockOpt=WSPSetSockOpt@24 +WSPStartup=WSPStartup@76 + +; EOF diff --git a/lib/msafd/msafd.rc b/lib/msafd/msafd.rc new file mode 100644 index 0000000..dc3f890 --- /dev/null +++ b/lib/msafd/msafd.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Ancillary Function Driver DLL\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "msafd\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "msafd.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/msvcrt/.cvsignore b/lib/msvcrt/.cvsignore new file mode 100644 index 0000000..0147911 --- /dev/null +++ b/lib/msvcrt/.cvsignore @@ -0,0 +1,6 @@ +msvcrt.coff +msvcrt.dll +msvcrt.nostrip.dll +*.d +*.o +*.sym diff --git a/lib/msvcrt/Makefile b/lib/msvcrt/Makefile new file mode 100644 index 0000000..a25f79e --- /dev/null +++ b/lib/msvcrt/Makefile @@ -0,0 +1,448 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_DEFONLY = yes + +TARGET_TYPE = dynlink + +TARGET_NAME = msvcrt + +TARGET_LFLAGS = -nostartfiles + +TARGET_SDKLIBS = kernel32.a ntdll.a + +TARGET_GCCLIBS = gcc + +TARGET_BASE = 0x78000000 + +TARGET_CFLAGS = -D__MSVCRT__ + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CLEAN = \ + conio/*.o ctype/*.o direct/*.o except/*.o float/*.o io/*.o \ + locale/*.o math/*.o mbstring/*.o misc/*.o process/*.o search/*.o \ + setjmp/*.o signal/*.o stdio/*.o stdlib/*.o string/*.o sys_stat/*.o \ + time/*.o wstring/*.o + + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + + +OBJECTS_CONIO = \ + conio/cgets.o \ + conio/cprintf.o \ + conio/cputs.o \ + conio/cscanf.o \ + conio/getch.o \ + conio/getche.o \ + conio/kbhit.o \ + conio/putch.o \ + conio/ungetch.o + +OBJECTS_CTYPE = \ + ctype/isalnum.o \ + ctype/isalpha.o \ + ctype/isascii.o \ + ctype/iscntrl.o \ + ctype/isdigit.o \ + ctype/isgraph.o \ + ctype/islower.o \ + ctype/isprint.o \ + ctype/ispunct.o \ + ctype/isspace.o \ + ctype/isupper.o \ + ctype/isxdigit.o \ + ctype/toascii.o \ + ctype/tolower.o \ + ctype/toupper.o \ + ctype/iscsym.o \ + ctype/isctype.o + +OBJECTS_DIRECT = \ + direct/chdir.o \ + direct/chdrive.o \ + direct/getcwd.o \ + direct/getdcwd.o \ + direct/getdfree.o \ + direct/getdrive.o \ + direct/mkdir.o \ + direct/rmdir.o + +OBJECTS_EXCEPT = \ + except/seh.o \ + except/abnorter.o \ + except/exhand2.o \ + except/matherr.o \ + except/unwind.o \ + except/xcptfil.o + +OBJECTS_FLOAT = \ + float/chgsign.o \ + float/clearfp.o \ + float/cntrlfp.o \ + float/copysign.o \ + float/fpclass.o \ + float/fpecode.o \ + float/fpreset.o \ + float/isnan.o \ + float/logb.o \ + float/nafter.o \ + float/scalb.o \ + float/statfp.o + +OBJECTS_IO = \ + io/access.o \ + io/chmod.o \ + io/chsize.o \ + io/close.o \ + io/commit.o \ + io/create.o \ + io/dup.o \ + io/dup2.o \ + io/eof.o \ + io/filelen.o \ + io/find.o \ + io/fmode.o \ + io/isatty.o \ + io/locking.o \ + io/lseek.o \ + io/mktemp.o \ + io/open.o \ + io/pipe.o \ + io/read.o \ + io/setmode.o \ + io/sopen.o \ + io/tell.o \ + io/umask.o \ + io/unlink.o \ + io/utime.o \ + io/write.o + +OBJECTS_LOCALE = \ + locale/locale.o + +OBJECTS_MATH = \ + math/acos.o \ + math/adjust.o \ + math/asin.o \ + math/atan.o \ + math/atan2.o \ + math/cabs.o \ + math/ceil.o \ + math/cos.o \ + math/cosh.o \ + math/exp.o \ + math/fabs.o \ + math/floor.o \ + math/fmod.o \ + math/frexp.o \ + math/ftol.o \ + math/huge_val.o \ + math/hypot.o \ + math/j0_y0.o \ + math/j1_y1.o \ + math/jn_yn.o \ + math/ldexp.o \ + math/log.o \ + math/log10.o \ + math/modf.o \ + math/pow.o \ + math/sin.o \ + math/sinh.o \ + math/sqrt.o \ + math/stubs.o \ + math/tan.o \ + math/tanh.o + +OBJECTS_MBSTRING = \ + mbstring/hanzen.o \ + mbstring/ischira.o \ + mbstring/iskana.o \ + mbstring/iskpun.o \ + mbstring/islead.o \ + mbstring/islwr.o \ + mbstring/ismbal.o \ + mbstring/ismbaln.o \ + mbstring/ismbc.o \ + mbstring/ismbgra.o \ + mbstring/ismbkaln.o \ + mbstring/ismblead.o \ + mbstring/ismbpri.o \ + mbstring/ismbpun.o \ + mbstring/ismbtrl.o \ + mbstring/isuppr.o \ + mbstring/jistojms.o \ + mbstring/jmstojis.o \ + mbstring/mbbtype.o \ + mbstring/mbccpy.o \ + mbstring/mbclen.o \ + mbstring/mbscat.o \ + mbstring/mbschr.o \ + mbstring/mbscmp.o \ + mbstring/mbscoll.o \ + mbstring/mbscpy.o \ + mbstring/mbscspn.o \ + mbstring/mbsdec.o \ + mbstring/mbsdup.o \ + mbstring/mbsicmp.o \ + mbstring/mbsicoll.o \ + mbstring/mbsinc.o \ + mbstring/mbslen.o \ + mbstring/mbslwr.o \ + mbstring/mbsncat.o \ + mbstring/mbsnccnt.o \ + mbstring/mbsncmp.o \ + mbstring/mbsncoll.o \ + mbstring/mbsncpy.o \ + mbstring/mbsnextc.o \ + mbstring/mbsnicmp.o \ + mbstring/mbsnicoll.o \ + mbstring/mbsninc.o \ + mbstring/mbsnset.o \ + mbstring/mbspbrk.o \ + mbstring/mbsrchr.o \ + mbstring/mbsrev.o \ + mbstring/mbsset.o \ + mbstring/mbsspn.o \ + mbstring/mbsspnp.o \ + mbstring/mbsstr.o \ + mbstring/mbstok.o \ + mbstring/mbstrlen.o \ + mbstring/mbsupr.o + +OBJECTS_MISC = \ + misc/amsg.o \ + misc/assert.o \ + misc/dllmain.o \ + misc/getargs.o \ + misc/initterm.o \ + misc/purecall.o \ + misc/tls.o + +OBJECTS_PROCESS = \ + process/_cwait.o \ + process/_system.o \ + process/dll.o \ + process/process.o \ + process/procid.o \ + process/thread.o \ + process/threadid.o + +OBJECTS_SEARCH = \ + search/lfind.o \ + search/lsearch.o + +OBJECTS_SETJMP = \ + setjmp/setjmp.o + +OBJECTS_SIGNAL = \ + signal/signal.o + +OBJECTS_STDIO = \ + stdio/allocfil.o \ + stdio/clearerr.o \ + stdio/fclose.o \ + stdio/fdopen.o \ + stdio/feof.o \ + stdio/ferror.o \ + stdio/fflush.o \ + stdio/fgetc.o \ + stdio/fgetchar.o \ + stdio/fgetpos.o \ + stdio/fgets.o \ + stdio/filbuf.o \ + stdio/fileno.o \ + stdio/flsbuf.o \ + stdio/fopen.o \ + stdio/fprintf.o \ + stdio/fputc.o \ + stdio/fputchar.o \ + stdio/fputs.o \ + stdio/fread.o \ + stdio/freopen.o \ + stdio/fscanf.o \ + stdio/fseek.o \ + stdio/fsetpos.o \ + stdio/fsopen.o \ + stdio/ftell.o \ + stdio/fwalk.o \ + stdio/fwrite.o \ + stdio/getc.o \ + stdio/getchar.o \ + stdio/gets.o \ + stdio/getw.o \ + stdio/perror.o \ + stdio/popen.o \ + stdio/printf.o \ + stdio/putc.o \ + stdio/putchar.o \ + stdio/puts.o \ + stdio/putw.o \ + stdio/remove.o \ + stdio/rename.o \ + stdio/rewind.o \ + stdio/rmtmp.o \ + stdio/scanf.o \ + stdio/setbuf.o \ + stdio/setvbuf.o \ + stdio/sprintf.o \ + stdio/sscanf.o \ + stdio/stdhnd.o \ + stdio/tempnam.o \ + stdio/tmpfile.o \ + stdio/tmpnam.o \ + stdio/ungetc.o \ + stdio/vfprintf.o \ + stdio/vfscanf.o \ + stdio/vfwprint.o \ + stdio/vprintf.o \ + stdio/vscanf.o \ + stdio/vsprintf.o \ + stdio/vsscanf.o + +OBJECTS_STDLIB = \ + stdlib/_exit.o \ + stdlib/abort.o \ + stdlib/abs.o \ + stdlib/atexit.o \ + stdlib/atof.o \ + stdlib/atoi.o \ + stdlib/atoi64.o \ + stdlib/atol.o \ + stdlib/bsearch.o \ + stdlib/div.o \ + stdlib/ecvt.o \ + stdlib/ecvtbuf.o \ + stdlib/errno.o \ + stdlib/fcvt.o \ + stdlib/fcvtbuf.o \ + stdlib/fullpath.o \ + stdlib/gcvt.o \ + stdlib/getenv.o \ + stdlib/itoa.o \ + stdlib/itow.o \ + stdlib/labs.o \ + stdlib/ldiv.o \ + stdlib/makepath.o \ + stdlib/malloc.o \ + stdlib/obsol.o \ + stdlib/putenv.o \ + stdlib/qsort.o \ + stdlib/rand.o \ + stdlib/rot.o \ + stdlib/senv.o \ + stdlib/splitp.o \ + stdlib/strtod.o \ + stdlib/strtol.o \ + stdlib/strtoul.o \ + stdlib/swab.o \ + stdlib/wcstod.o \ + stdlib/wcstol.o \ + stdlib/wcstoul.o \ + stdlib/wtoi.o \ + stdlib/wtoi64.o + +OBJECTS_STRING = \ + string/memccpy.o \ + string/memchr.o \ + string/memcmp.o \ + string/memcpy.o \ + string/memicmp.o \ + string/memmove.o \ + string/memset.o \ + string/strcat.o \ + string/strchr.o \ + string/strcmp.o \ + string/strcoll.o \ + string/strcpy.o \ + string/strcspn.o \ + string/strdup.o \ + string/strerror.o \ + string/stricmp.o \ + string/strlen.o \ + string/strlwr.o \ + string/strncat.o \ + string/strncmp.o \ + string/strncpy.o \ + string/strnicmp.o \ + string/strnlen.o \ + string/strpbrk.o \ + string/strrchr.o \ + string/strrev.o\ + string/strset.o \ + string/strspn.o \ + string/strstr.o \ + string/strtok.o \ + string/strupr.o \ + string/strxfrm.o + +OBJECTS_SYS_STAT = \ + sys_stat/fstat.o \ + sys_stat/futime.o \ + sys_stat/stat.o + +OBJECTS_TIME = \ + time/clock.o \ + time/ctime.o \ + time/difftime.o \ + time/strdate.o \ + time/strftime.o \ + time/strtime.o \ + time/time.o + +OBJECTS_WSTRING = \ + wstring/wcscat.o \ + wstring/wcschr.o \ + wstring/wcscmp.o \ + wstring/wcscoll.o \ + wstring/wcscpy.o \ + wstring/wcscspn.o \ + wstring/wcsdup.o \ + wstring/wcsicmp.o \ + wstring/wcslen.o \ + wstring/wcslwr.o \ + wstring/wcsncat.o \ + wstring/wcsncmp.o \ + wstring/wcsncpy.o \ + wstring/wcsnicmp.o \ + wstring/wcsnlen.o \ + wstring/wcspbrk.o \ + wstring/wcsrchr.o \ + wstring/wcsrev.o \ + wstring/wcsset.o \ + wstring/wcsspn.o \ + wstring/wcsstr.o \ + wstring/wcstok.o \ + wstring/wcsupr.o \ + wstring/wcsxfrm.o + +OBJECTS = \ + $(OBJECTS_CONIO) \ + $(OBJECTS_CTYPE) \ + $(OBJECTS_DIRECT) \ + $(OBJECTS_EXCEPT) \ + $(OBJECTS_FLOAT) \ + $(OBJECTS_IO) \ + $(OBJECTS_LOCALE) \ + $(OBJECTS_MATH) \ + $(OBJECTS_MBSTRING) \ + $(OBJECTS_MISC) \ + $(OBJECTS_PROCESS) \ + $(OBJECTS_SEARCH) \ + $(OBJECTS_SETJMP) \ + $(OBJECTS_SIGNAL) \ + $(OBJECTS_STDIO) \ + $(OBJECTS_STDLIB) \ + $(OBJECTS_STRING) \ + $(OBJECTS_SYS_STAT) \ + $(OBJECTS_TIME) \ + $(OBJECTS_WSTRING) + +$(TARGET_NAME).o: $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o + +# EOF diff --git a/lib/msvcrt/conio/.cvsignore b/lib/msvcrt/conio/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/conio/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/conio/cgets.c b/lib/msvcrt/conio/cgets.c new file mode 100644 index 0000000..71645d0 --- /dev/null +++ b/lib/msvcrt/conio/cgets.c @@ -0,0 +1,64 @@ +#include +#include + + +char *_cgets(char *string) +{ + unsigned len = 0; + unsigned int maxlen_wanted; + char *sp; + int c; + /* + * Be smart and check for NULL pointer. + * Don't know wether TURBOC does this. + */ + if (!string) + return(NULL); + maxlen_wanted = (unsigned int)((unsigned char)string[0]); + sp = &(string[2]); + /* + * Should the string be shorter maxlen_wanted including or excluding + * the trailing '\0' ? We don't take any risk. + */ + while(len < maxlen_wanted-1) + { + c=_getch(); + /* + * shold we check for backspace here? + * TURBOC does (just checked) but doesn't in cscanf (thats harder + * or even impossible). We do the same. + */ + if (c == '\b') + { + if (len > 0) + { + _cputs("\b \b"); /* go back, clear char on screen with space + and go back again */ + len--; + sp[len] = '\0'; /* clear the character in the string */ + } + } + else if (c == '\r') + { + sp[len] = '\0'; + break; + } + else if (c == 0) + { + /* special character ends input */ + sp[len] = '\0'; + _ungetch(c); /* keep the char for later processing */ + break; + } + else + { + sp[len] = _putch(c); + len++; + } + } + sp[maxlen_wanted-1] = '\0'; + string[1] = (char)((unsigned char)len); + return(sp); +} + + diff --git a/lib/msvcrt/conio/cprintf.c b/lib/msvcrt/conio/cprintf.c new file mode 100644 index 0000000..da3ca0c --- /dev/null +++ b/lib/msvcrt/conio/cprintf.c @@ -0,0 +1,17 @@ +#include +#include + +int +_cprintf(const char *fmt, ...) +{ + int cnt; + char buf[ 2048 ]; /* this is buggy, because buffer might be too small. */ + va_list ap; + + va_start(ap, fmt); + cnt = vsprintf(buf, fmt, ap); + va_end(ap); + + _cputs(buf); + return cnt; +} diff --git a/lib/msvcrt/conio/cputs.c b/lib/msvcrt/conio/cputs.c new file mode 100644 index 0000000..396c71e --- /dev/null +++ b/lib/msvcrt/conio/cputs.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/cputs.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include +#include + +int _cputs(const char *_str) +{ + int len = strlen(_str); + DWORD written = 0; + if (!WriteFile(filehnd(stdout->_file),_str,len,&written,NULL)) + return -1; + return 0; +} diff --git a/lib/msvcrt/conio/cscanf.c b/lib/msvcrt/conio/cscanf.c new file mode 100644 index 0000000..58e01d9 --- /dev/null +++ b/lib/msvcrt/conio/cscanf.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int _cscanf(char *fmt, ...) +{ + int cnt; + va_list ap; + + //fixme cscanf should scan the console's keyboard + va_start(ap, fmt); + cnt = __vscanf(fmt, ap); + va_end(ap); + + return cnt; +} + + diff --git a/lib/msvcrt/conio/getch.c b/lib/msvcrt/conio/getch.c new file mode 100644 index 0000000..15d2eb6 --- /dev/null +++ b/lib/msvcrt/conio/getch.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include +#include + + +int _getch(void) +{ + DWORD NumberOfCharsRead = 0; + char c; + + if (char_avail) + { + c = ungot_char; + char_avail = 0; + } + else + { + ReadConsoleA(_get_osfhandle(stdin->_file), + &c, + 1, + &NumberOfCharsRead, + NULL); + } + if (c == 10) + c = 13; + putchar(c); + + return c; +} diff --git a/lib/msvcrt/conio/getche.c b/lib/msvcrt/conio/getche.c new file mode 100644 index 0000000..f994649 --- /dev/null +++ b/lib/msvcrt/conio/getche.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getche.c + * PURPOSE: Reads a character from stdin + * PROGRAMER: DJ Delorie + Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include + + +int getche(void) +{ + if (char_avail) + /* + * We don't know, wether the ungot char was already echoed + * we assume yes (for example in cscanf, probably the only + * place where ungetch is ever called. + * There is no way to check for this really, because + * ungetch could have been called with a character that + * hasn't been got by a conio function. + * We don't echo again. + */ + return(getch()); + return (_putch(getch())); +} diff --git a/lib/msvcrt/conio/kbhit.c b/lib/msvcrt/conio/kbhit.c new file mode 100644 index 0000000..876099f --- /dev/null +++ b/lib/msvcrt/conio/kbhit.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + + +// FIXME PeekCosoleInput returns more than keyboard hits + +int _kbhit(void) +{ + INPUT_RECORD InputRecord; + DWORD NumberRead=0; + if (char_avail) + return(1); + else + { + //FIXME PeekConsoleInput might do DeviceIo + //PeekConsoleInput((HANDLE)stdin->_file,&InputRecord,1,&NumberRead); + return NumberRead; + } + return 0; +} diff --git a/lib/msvcrt/conio/putch.c b/lib/msvcrt/conio/putch.c new file mode 100644 index 0000000..5f37013 --- /dev/null +++ b/lib/msvcrt/conio/putch.c @@ -0,0 +1,21 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/putch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +int _putch(int c) +{ + DWORD NumberOfCharsWritten; + + if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),&c,1,&NumberOfCharsWritten,NULL)) + return -1; + + return NumberOfCharsWritten; +} diff --git a/lib/msvcrt/conio/ungetch.c b/lib/msvcrt/conio/ungetch.c new file mode 100644 index 0000000..8b974bb --- /dev/null +++ b/lib/msvcrt/conio/ungetch.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/ungetch.c + * PURPOSE: Ungets a character from stdin + * PROGRAMER: DJ Delorie + Boudewijn Dekker [ Adapted from djgpp libc ] + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include + +#define EOF -1 + +int char_avail = 0; +int ungot_char = 0; + + +int _ungetch(int c) +{ + if (char_avail) + return(EOF); + ungot_char = c; + char_avail = 1; + return(c); +} diff --git a/lib/msvcrt/ctype/.cvsignore b/lib/msvcrt/ctype/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/ctype/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/ctype/isalnum.c b/lib/msvcrt/ctype/isalnum.c new file mode 100644 index 0000000..0dc3922 --- /dev/null +++ b/lib/msvcrt/ctype/isalnum.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/ctype/isalnum.c + * PURPOSE: Test for a alpha numeric character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + + +#undef isalnum +int isalnum(int c) +{ + return _isctype(c,_ALPHA | _DIGIT); +} + +#undef iswalnum +int iswalnum(wint_t c) +{ + return iswctype(c,_ALPHA | _DIGIT); +} diff --git a/lib/msvcrt/ctype/isalpha.c b/lib/msvcrt/ctype/isalpha.c new file mode 100644 index 0000000..a506197 --- /dev/null +++ b/lib/msvcrt/ctype/isalpha.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/mscvrt/ctype/isalpha.c + * PURPOSE: Checks if a character is alphanumeric + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + +#undef isalpha +int isalpha(int c) +{ + return _isctype(c,_ALPHA); +} + +#undef iswalpha +int iswalpha(wint_t c) +{ + return iswctype(c,_ALPHA); +} diff --git a/lib/msvcrt/ctype/isascii.c b/lib/msvcrt/ctype/isascii.c new file mode 100644 index 0000000..612a9a9 --- /dev/null +++ b/lib/msvcrt/ctype/isascii.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/ctype/isascii.c + * PURPOSE: Checks if a character is ascii + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + +int __isascii(int c) +{ + return (!((c)&(~0x7f))); +} + +int iswascii(wint_t c) +{ + return __isascii(c); +} + + + + + + + + diff --git a/lib/msvcrt/ctype/iscntrl.c b/lib/msvcrt/ctype/iscntrl.c new file mode 100644 index 0000000..f6a685e --- /dev/null +++ b/lib/msvcrt/ctype/iscntrl.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef iscntrl +int iscntrl(int c) +{ + return _isctype(c,_CONTROL); +} + +#undef iswcntrl +int iswcntrl(wint_t c) +{ + return iswctype(c,_CONTROL); +} diff --git a/lib/msvcrt/ctype/iscsym.c b/lib/msvcrt/ctype/iscsym.c new file mode 100644 index 0000000..41a6da6 --- /dev/null +++ b/lib/msvcrt/ctype/iscsym.c @@ -0,0 +1,21 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/ctype/iscsym.c + * PURPOSE: Check for a valid characters in a c symbol + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + +int __iscsymf(int c) +{ + return (isalpha(c) || ( c == '_' )); +} + +int __iscsym(int c) +{ + return (isalnum(c) || ( c == '_' )); +} diff --git a/lib/msvcrt/ctype/isctype.c b/lib/msvcrt/ctype/isctype.c new file mode 100644 index 0000000..22a94e1 --- /dev/null +++ b/lib/msvcrt/ctype/isctype.c @@ -0,0 +1,293 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +unsigned short _ctype[] = { + 0, /* , 0xFFFF */ + _CONTROL, /* CTRL+@, 0x00 */ + _CONTROL, /* CTRL+A, 0x01 */ + _CONTROL, /* CTRL+B, 0x02 */ + _CONTROL, /* CTRL+C, 0x03 */ + _CONTROL, /* CTRL+D, 0x04 */ + _CONTROL, /* CTRL+E, 0x05 */ + _CONTROL, /* CTRL+F, 0x06 */ + _CONTROL, /* CTRL+G, 0x07 */ + _CONTROL, /* CTRL+H, 0x08 */ + _CONTROL | _SPACE, /* CTRL+I, 0x09 */ + _CONTROL | _SPACE, /* CTRL+J, 0x0a */ + _CONTROL | _SPACE, /* CTRL+K, 0x0b */ + _CONTROL | _SPACE, /* CTRL+L, 0x0c */ + _CONTROL | _SPACE, /* CTRL+M, 0x0d */ + _CONTROL, /* CTRL+N, 0x0e */ + _CONTROL, /* CTRL+O, 0x0f */ + _CONTROL, /* CTRL+P, 0x10 */ + _CONTROL, /* CTRL+Q, 0x11 */ + _CONTROL, /* CTRL+R, 0x12 */ + _CONTROL, /* CTRL+S, 0x13 */ + _CONTROL, /* CTRL+T, 0x14 */ + _CONTROL, /* CTRL+U, 0x15 */ + _CONTROL, /* CTRL+V, 0x16 */ + _CONTROL, /* CTRL+W, 0x17 */ + _CONTROL, /* CTRL+X, 0x18 */ + _CONTROL, /* CTRL+Y, 0x19 */ + _CONTROL, /* CTRL+Z, 0x1a */ + _CONTROL, /* CTRL+[, 0x1b */ + _CONTROL, /* CTRL+\, 0x1c */ + _CONTROL, /* CTRL+], 0x1d */ + _CONTROL, /* CTRL+^, 0x1e */ + _CONTROL, /* CTRL+_, 0x1f */ + _SPACE | _BLANK, /* ` ', 0x20 */ + _PUNCT, /* `!', 0x21 */ + _PUNCT, /* 0x22 */ + _PUNCT, /* `#', 0x23 */ + _PUNCT, /* `$', 0x24 */ + _PUNCT, /* `%', 0x25 */ + _PUNCT, /* `&', 0x26 */ + _PUNCT, /* 0x27 */ + _PUNCT, /* `(', 0x28 */ + _PUNCT, /* `)', 0x29 */ + _PUNCT, /* `*', 0x2a */ + _PUNCT, /* `+', 0x2b */ + _PUNCT, /* `,', 0x2c */ + _PUNCT, /* `-', 0x2d */ + _PUNCT, /* `.', 0x2e */ + _PUNCT, /* `/', 0x2f */ + _DIGIT | _HEX, /* `0', 0x30 */ + _DIGIT | _HEX, /* `1', 0x31 */ + _DIGIT | _HEX, /* `2', 0x32 */ + _DIGIT | _HEX, /* `3', 0x33 */ + _DIGIT | _HEX, /* `4', 0x34 */ + _DIGIT | _HEX, /* `5', 0x35 */ + _DIGIT | _HEX, /* `6', 0x36 */ + _DIGIT | _HEX, /* `7', 0x37 */ + _DIGIT | _HEX, /* `8', 0x38 */ + _DIGIT | _HEX, /* `9', 0x39 */ + _PUNCT, /* `:', 0x3a */ + _PUNCT, /* `;', 0x3b */ + _PUNCT, /* `<', 0x3c */ + _PUNCT, /* `=', 0x3d */ + _PUNCT, /* `>', 0x3e */ + _PUNCT, /* `?', 0x3f */ + _PUNCT, /* `@', 0x40 */ + _UPPER | _HEX, /* `A', 0x41 */ + _UPPER | _HEX, /* `B', 0x42 */ + _UPPER | _HEX, /* `C', 0x43 */ + _UPPER | _HEX, /* `D', 0x44 */ + _UPPER | _HEX, /* `E', 0x45 */ + _UPPER | _HEX, /* `F', 0x46 */ + _UPPER, /* `G', 0x47 */ + _UPPER, /* `H', 0x48 */ + _UPPER, /* `I', 0x49 */ + _UPPER, /* `J', 0x4a */ + _UPPER, /* `K', 0x4b */ + _UPPER, /* `L', 0x4c */ + _UPPER, /* `M', 0x4d */ + _UPPER, /* `N', 0x4e */ + _UPPER, /* `O', 0x4f */ + _UPPER, /* `P', 0x50 */ + _UPPER, /* `Q', 0x51 */ + _UPPER, /* `R', 0x52 */ + _UPPER, /* `S', 0x53 */ + _UPPER, /* `T', 0x54 */ + _UPPER, /* `U', 0x55 */ + _UPPER, /* `V', 0x56 */ + _UPPER, /* `W', 0x57 */ + _UPPER, /* `X', 0x58 */ + _UPPER, /* `Y', 0x59 */ + _UPPER, /* `Z', 0x5a */ + _PUNCT, /* `[', 0x5b */ + _PUNCT, /* 0x5c */ + _PUNCT, /* `]', 0x5d */ + _PUNCT, /* `^', 0x5e */ + _PUNCT, /* `_', 0x5f */ + _PUNCT, /* 0x60 */ + _LOWER | _HEX, /* `a', 0x61 */ + _LOWER | _HEX, /* `b', 0x62 */ + _LOWER | _HEX, /* `c', 0x63 */ + _LOWER | _HEX, /* `d', 0x64 */ + _LOWER | _HEX, /* `e', 0x65 */ + _LOWER | _HEX, /* `f', 0x66 */ + _LOWER, /* `g', 0x67 */ + _LOWER, /* `h', 0x68 */ + _LOWER, /* `i', 0x69 */ + _LOWER, /* `j', 0x6a */ + _LOWER, /* `k', 0x6b */ + _LOWER, /* `l', 0x6c */ + _LOWER, /* `m', 0x6d */ + _LOWER, /* `n', 0x6e */ + _LOWER, /* `o', 0x6f */ + _LOWER, /* `p', 0x70 */ + _LOWER, /* `q', 0x71 */ + _LOWER, /* `r', 0x72 */ + _LOWER, /* `s', 0x73 */ + _LOWER, /* `t', 0x74 */ + _LOWER, /* `u', 0x75 */ + _LOWER, /* `v', 0x76 */ + _LOWER, /* `w', 0x77 */ + _LOWER, /* `x', 0x78 */ + _LOWER, /* `y', 0x79 */ + _LOWER, /* `z', 0x7a */ + _PUNCT, /* `{', 0x7b */ + _PUNCT, /* `|', 0x7c */ + _PUNCT, /* `}', 0x7d */ + _PUNCT, /* `~', 0x7e */ + _CONTROL, /* 0x7f */ + 0, /* 0x80 */ + 0, /* 0x81 */ + 0, /* 0x82 */ + 0, /* 0x83 */ + 0, /* 0x84 */ + 0, /* 0x85 */ + 0, /* 0x86 */ + 0, /* 0x87 */ + 0, /* 0x88 */ + 0, /* 0x89 */ + 0, /* 0x8a */ + 0, /* 0x8b */ + 0, /* 0x8c */ + 0, /* 0x8d */ + 0, /* 0x8e */ + 0, /* 0x8f */ + 0, /* 0x90 */ + 0, /* 0x91 */ + 0, /* 0x92 */ + 0, /* 0x93 */ + 0, /* 0x94 */ + 0, /* 0x95 */ + 0, /* 0x96 */ + 0, /* 0x97 */ + 0, /* 0x98 */ + 0, /* 0x99 */ + 0, /* 0x9a */ + 0, /* 0x9b */ + 0, /* 0x9c */ + 0, /* 0x9d */ + 0, /* 0x9e */ + 0, /* 0x9f */ + 0, /* 0xa0 */ + 0, /* 0xa1 */ + 0, /* 0xa2 */ + 0, /* 0xa3 */ + 0, /* 0xa4 */ + 0, /* 0xa5 */ + 0, /* 0xa6 */ + 0, /* 0xa7 */ + 0, /* 0xa8 */ + 0, /* 0xa9 */ + 0, /* 0xaa */ + 0, /* 0xab */ + 0, /* 0xac */ + 0, /* 0xad */ + 0, /* 0xae */ + 0, /* 0xaf */ + 0, /* 0xb0 */ + 0, /* 0xb1 */ + 0, /* 0xb2 */ + 0, /* 0xb3 */ + 0, /* 0xb4 */ + 0, /* 0xb5 */ + 0, /* 0xb6 */ + 0, /* 0xb7 */ + 0, /* 0xb8 */ + 0, /* 0xb9 */ + 0, /* 0xba */ + 0, /* 0xbb */ + 0, /* 0xbc */ + 0, /* 0xbd */ + 0, /* 0xbe */ + 0, /* 0xbf */ + 0, /* 0xc0 */ + 0, /* 0xc1 */ + 0, /* 0xc2 */ + 0, /* 0xc3 */ + 0, /* 0xc4 */ + 0, /* 0xc5 */ + 0, /* 0xc6 */ + 0, /* 0xc7 */ + 0, /* 0xc8 */ + 0, /* 0xc9 */ + 0, /* 0xca */ + 0, /* 0xcb */ + 0, /* 0xcc */ + 0, /* 0xcd */ + 0, /* 0xce */ + 0, /* 0xcf */ + 0, /* 0xd0 */ + 0, /* 0xd1 */ + 0, /* 0xd2 */ + 0, /* 0xd3 */ + 0, /* 0xd4 */ + 0, /* 0xd5 */ + 0, /* 0xd6 */ + 0, /* 0xd7 */ + 0, /* 0xd8 */ + 0, /* 0xd9 */ + 0, /* 0xda */ + 0, /* 0xdb */ + 0, /* 0xdc */ + 0, /* 0xdd */ + 0, /* 0xde */ + 0, /* 0xdf */ + 0, /* 0xe0 */ + 0, /* 0xe1 */ + 0, /* 0xe2 */ + 0, /* 0xe3 */ + 0, /* 0xe4 */ + 0, /* 0xe5 */ + 0, /* 0xe6 */ + 0, /* 0xe7 */ + 0, /* 0xe8 */ + 0, /* 0xe9 */ + 0, /* 0xea */ + 0, /* 0xeb */ + 0, /* 0xec */ + 0, /* 0xed */ + 0, /* 0xee */ + 0, /* 0xef */ + 0, /* 0xf0 */ + 0, /* 0xf1 */ + 0, /* 0xf2 */ + 0, /* 0xf3 */ + 0, /* 0xf4 */ + 0, /* 0xf5 */ + 0, /* 0xf6 */ + 0, /* 0xf7 */ + 0, /* 0xf8 */ + 0, /* 0xf9 */ + 0, /* 0xfa */ + 0, /* 0xfb */ + 0, /* 0xfc */ + 0, /* 0xfd */ + 0, /* 0xfe */ + 0 /* 0xff */ +}; + +unsigned short *_pctype = _ctype + 1; +unsigned short *_pwctype = _ctype + 1; + +unsigned short **__p__pctype(void) +{ + return &_pctype; +} + +unsigned short **__p__pwctype(void) +{ + return &_pwctype; +} + +int _isctype(unsigned int c, int ctypeFlags) +{ + return (_pctype[(unsigned char)(c & 0xFF)] & ctypeFlags); +} + +int iswctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +// obsolete +int is_wctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +/* EOF */ diff --git a/lib/msvcrt/ctype/isdigit.c b/lib/msvcrt/ctype/isdigit.c new file mode 100644 index 0000000..ae588e4 --- /dev/null +++ b/lib/msvcrt/ctype/isdigit.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isdigit +int isdigit(int c) +{ + return _isctype(c,_DIGIT); +} + +#undef iswdigit +int iswdigit(wint_t c) +{ + return iswctype(c,_DIGIT); +} diff --git a/lib/msvcrt/ctype/isgraph.c b/lib/msvcrt/ctype/isgraph.c new file mode 100644 index 0000000..39c500c --- /dev/null +++ b/lib/msvcrt/ctype/isgraph.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isgraph +int isgraph(int c) +{ + return _isctype(c,_PUNCT | _ALPHA | _DIGIT); +} + +#undef iswgraph +int iswgraph(wint_t c) +{ + return iswctype(c,_PUNCT | _ALPHA | _DIGIT); +} diff --git a/lib/msvcrt/ctype/islower.c b/lib/msvcrt/ctype/islower.c new file mode 100644 index 0000000..c3a9178 --- /dev/null +++ b/lib/msvcrt/ctype/islower.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef islower +int islower(int c) +{ + return _isctype(c,_LOWER); +} + +int iswlower(wint_t c) +{ + return iswctype(c,_LOWER); +} diff --git a/lib/msvcrt/ctype/isprint.c b/lib/msvcrt/ctype/isprint.c new file mode 100644 index 0000000..8c6dbf5 --- /dev/null +++ b/lib/msvcrt/ctype/isprint.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isprint +int isprint(int c) +{ + return _isctype(c,_BLANK | _PUNCT | _ALPHA | _DIGIT); +} + +int iswprint(wint_t c) +{ + return iswctype((unsigned short)c,_BLANK | _PUNCT | _ALPHA | _DIGIT); +} diff --git a/lib/msvcrt/ctype/ispunct.c b/lib/msvcrt/ctype/ispunct.c new file mode 100644 index 0000000..e26e3e8 --- /dev/null +++ b/lib/msvcrt/ctype/ispunct.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef ispunct +int ispunct(int c) +{ + return _isctype(c,_PUNCT); +} + +#undef iswpunct +int iswpunct(wint_t c) +{ + return iswctype(c,_PUNCT); +} diff --git a/lib/msvcrt/ctype/isspace.c b/lib/msvcrt/ctype/isspace.c new file mode 100644 index 0000000..e0ebcb3 --- /dev/null +++ b/lib/msvcrt/ctype/isspace.c @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/ctype/isspace.c + * PURPOSE: Checks for a whitespace characters + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + +#undef isspace +int isspace(int c) +{ + return _isctype(c,_SPACE); +} + +#undef iswspace +int iswspace(wint_t c) +{ + return iswctype(c,_SPACE); +} diff --git a/lib/msvcrt/ctype/isupper.c b/lib/msvcrt/ctype/isupper.c new file mode 100644 index 0000000..9898cb3 --- /dev/null +++ b/lib/msvcrt/ctype/isupper.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isupper +int isupper(int c) +{ + return _isctype(c,_UPPER); +} + +int iswupper(wint_t c) +{ + return iswctype(c,_UPPER); +} diff --git a/lib/msvcrt/ctype/isxdigit.c b/lib/msvcrt/ctype/isxdigit.c new file mode 100644 index 0000000..9c24dda --- /dev/null +++ b/lib/msvcrt/ctype/isxdigit.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef isxdigit +int isxdigit(int c) +{ + return _isctype(c,_HEX); +} + +#undef iswxdigit +int iswxdigit(wint_t c) +{ + return iswctype(c,_HEX); +} + diff --git a/lib/msvcrt/ctype/toascii.c b/lib/msvcrt/ctype/toascii.c new file mode 100644 index 0000000..16d959b --- /dev/null +++ b/lib/msvcrt/ctype/toascii.c @@ -0,0 +1,9 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include + + +int __toascii(int c) +{ + return ((unsigned)(c) & 0x7F ); +} diff --git a/lib/msvcrt/ctype/tolower.c b/lib/msvcrt/ctype/tolower.c new file mode 100644 index 0000000..e2c188c --- /dev/null +++ b/lib/msvcrt/ctype/tolower.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +#undef tolower +int tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - ('A' - 'a')); + return(c); +} + +#undef towlower +wchar_t towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - (L'A' - L'a')); + return(c); +} + +int _tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - ('A' - 'a')); + return(c); +} + +/* +wchar_t _towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - (L'A' - L'a')); + return(c); +} +*/ + + diff --git a/lib/msvcrt/ctype/toupper.c b/lib/msvcrt/ctype/toupper.c new file mode 100644 index 0000000..666cee2 --- /dev/null +++ b/lib/msvcrt/ctype/toupper.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + + +#undef toupper +int toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + ('A' - 'a')); + return(c); +} + +#undef towupper +wchar_t towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + (L'A' - L'a')); + return(c); +} + +int _toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + ('A' - 'a')); + return(c); +} + +/* +wchar_t _towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + (L'A' - L'a')); + return(c); +} +*/ + diff --git a/lib/msvcrt/direct/.cvsignore b/lib/msvcrt/direct/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/direct/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/direct/chdir.c b/lib/msvcrt/direct/chdir.c new file mode 100644 index 0000000..521cf52 --- /dev/null +++ b/lib/msvcrt/direct/chdir.c @@ -0,0 +1,24 @@ +#include +#include +#include + + +int _chdir( const char *_path ) +{ + if ( _path[1] == ':') + _chdrive(tolower(_path[0] - 'a')+1); + if ( !SetCurrentDirectoryA((char *)_path) ) + return -1; + + return 0; +} + +int _wchdir( const wchar_t *_path ) +{ + if ( _path[1] == L':') + _chdrive(towlower(_path[0] - L'a')+1); + if ( !SetCurrentDirectoryW((wchar_t *)_path) ) + return -1; + + return 0; +} diff --git a/lib/msvcrt/direct/chdrive.c b/lib/msvcrt/direct/chdrive.c new file mode 100644 index 0000000..6b67c8f --- /dev/null +++ b/lib/msvcrt/direct/chdrive.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +int cur_drive = 0; + +int _chdrive( int drive ) +{ + char d[3]; + if (!( drive >= 1 && drive <= 26 )) + return -1; + + if ( cur_drive != drive ) { + cur_drive = drive; + d[0] = toupper(cur_drive + '@'); + d[1] = ':'; + d[2] = 0; + SetCurrentDirectoryA(d); + } + + return 0; +} diff --git a/lib/msvcrt/direct/getcwd.c b/lib/msvcrt/direct/getcwd.c new file mode 100644 index 0000000..461e085 --- /dev/null +++ b/lib/msvcrt/direct/getcwd.c @@ -0,0 +1,42 @@ +#include +#include +#include + + +char *_getcwd( char *buffer, int maxlen ) +{ + char *cwd; + int len; + if ( buffer == NULL ) { + cwd = malloc(MAX_PATH); + len = MAX_PATH; + } + else { + cwd = buffer; + len = maxlen; + } + + if ( GetCurrentDirectoryA(len,cwd) == 0 ) + return NULL; + + return cwd; +} + +wchar_t *_wgetcwd( wchar_t *buffer, int maxlen ) +{ + wchar_t *cwd; + int len; + if ( buffer == NULL ) { + cwd = malloc(MAX_PATH * sizeof(wchar_t)); + len = MAX_PATH; + } + else { + cwd = buffer; + len = maxlen; + } + + if ( GetCurrentDirectoryW(len,cwd) == 0 ) + return NULL; + + return cwd; +} diff --git a/lib/msvcrt/direct/getdcwd.c b/lib/msvcrt/direct/getdcwd.c new file mode 100644 index 0000000..e6e719e --- /dev/null +++ b/lib/msvcrt/direct/getdcwd.c @@ -0,0 +1,44 @@ +#include +#include + +char* _getdcwd (int nDrive, char* caBuffer, int nBufLen) +{ + int i =0; + int dr = _getdrive(); + + if ( nDrive < 1 || nDrive > 26 ) + return NULL; + + if ( dr != nDrive ) + _chdrive(nDrive); + + i = GetCurrentDirectoryA(nBufLen,caBuffer); + if ( i == nBufLen ) + return NULL; + + if ( dr != nDrive ) + _chdrive(dr); + + return caBuffer; +} + +wchar_t* _wgetdcwd (int nDrive, wchar_t* caBuffer, int nBufLen) +{ + int i =0; + int dr = _getdrive(); + + if ( nDrive < 1 || nDrive > 26 ) + return NULL; + + if ( dr != nDrive ) + _chdrive(nDrive); + + i = GetCurrentDirectoryW(nBufLen,caBuffer); + if ( i == nBufLen ) + return NULL; + + if ( dr != nDrive ) + _chdrive(dr); + + return caBuffer; +} diff --git a/lib/msvcrt/direct/getdfree.c b/lib/msvcrt/direct/getdfree.c new file mode 100644 index 0000000..a240503 --- /dev/null +++ b/lib/msvcrt/direct/getdfree.c @@ -0,0 +1,20 @@ +#include +#include +#include + + +unsigned int _getdiskfree(unsigned int _drive, struct _diskfree_t *_diskspace) +{ + char RootPathName[10]; + RootPathName[0] = toupper(_drive +'@'); + RootPathName[1] = ':'; + RootPathName[2] = '\\'; + RootPathName[3] = 0; + if ( _diskspace == NULL ) + return 0; + + if ( !GetDiskFreeSpaceA(RootPathName,(LPDWORD)&_diskspace->sectors_per_cluster,(LPDWORD)&_diskspace->bytes_per_sector, + (LPDWORD )&_diskspace->avail_clusters,(LPDWORD )&_diskspace->total_clusters ) ) + return 0; + return _diskspace->avail_clusters; +} diff --git a/lib/msvcrt/direct/getdrive.c b/lib/msvcrt/direct/getdrive.c new file mode 100644 index 0000000..e2b6e66 --- /dev/null +++ b/lib/msvcrt/direct/getdrive.c @@ -0,0 +1,25 @@ +#include +#include +#include + + +extern int cur_drive; + +int _getdrive( void ) +{ + char Buffer[MAX_PATH]; + + if ( cur_drive == 0 ) { + GetCurrentDirectoryA(MAX_PATH,Buffer); + cur_drive = toupper(Buffer[0] - '@'); + } + + return cur_drive; +} + +unsigned long _getdrives(void) +{ + //fixme get logical drives + //return GetLogicalDrives(); + return 5; // drive A and C +} diff --git a/lib/msvcrt/direct/mkdir.c b/lib/msvcrt/direct/mkdir.c new file mode 100644 index 0000000..3abb112 --- /dev/null +++ b/lib/msvcrt/direct/mkdir.c @@ -0,0 +1,17 @@ +#include +#include + + +int _mkdir( const char *_path ) +{ + if (!CreateDirectoryA(_path,NULL)) + return -1; + return 0; +} + +int _wmkdir( const wchar_t *_path ) +{ + if (!CreateDirectoryW(_path,NULL)) + return -1; + return 0; +} diff --git a/lib/msvcrt/direct/rmdir.c b/lib/msvcrt/direct/rmdir.c new file mode 100644 index 0000000..90804f0 --- /dev/null +++ b/lib/msvcrt/direct/rmdir.c @@ -0,0 +1,16 @@ +#include +#include + +int _rmdir( const char *_path ) +{ + if (!RemoveDirectoryA(_path)) + return -1; + return 0; +} + +int _wrmdir( const wchar_t *_path ) +{ + if (!RemoveDirectoryW(_path)) + return -1; + return 0; +} diff --git a/lib/msvcrt/except/.cvsignore b/lib/msvcrt/except/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/except/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/except/abnorter.c b/lib/msvcrt/except/abnorter.c new file mode 100644 index 0000000..2efd11a --- /dev/null +++ b/lib/msvcrt/except/abnorter.c @@ -0,0 +1,7 @@ +#include + +int _abnormal_termination(void) +{ + printf("Abnormal Termination\n"); +// return AbnormalTermination(); +} diff --git a/lib/msvcrt/except/exhand2.c b/lib/msvcrt/except/exhand2.c new file mode 100644 index 0000000..7bd2a72 --- /dev/null +++ b/lib/msvcrt/except/exhand2.c @@ -0,0 +1,17 @@ +#include + +VOID STDCALL +MsvcrtDebug(ULONG Value) +{ + DbgPrint("MsvcrtDebug 0x%.08x\n", Value); +} + +EXCEPTION_DISPOSITION +_except_handler2( +struct _EXCEPTION_RECORD *ExceptionRecord, +void *Frame, +struct _CONTEXT *ContextRecord, +void *DispatcherContext) +{ + printf("_except_handler2()\n"); +} diff --git a/lib/msvcrt/except/matherr.c b/lib/msvcrt/except/matherr.c new file mode 100644 index 0000000..5d03db2 --- /dev/null +++ b/lib/msvcrt/except/matherr.c @@ -0,0 +1,28 @@ +struct _exception { + int type; + char *name; + double arg1; + double arg2; + double retval; + } ; + +int _matherr(struct _exception *e) +{ + return 0; +} + +void __setusermatherr(int (* handler)(struct _exception *)) +{ + +} + +#define _FPIEEE_RECORD void + +int _fpieee_flt( + unsigned long exception_code, + struct _EXCEPTION_POINTERS *ExceptionPointer, + int (* handler)(_FPIEEE_RECORD *) + ) +{ + return 0; +} diff --git a/lib/msvcrt/except/seh.s b/lib/msvcrt/except/seh.s new file mode 100755 index 0000000..da4008c --- /dev/null +++ b/lib/msvcrt/except/seh.s @@ -0,0 +1,366 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS MSVCRT Runtime Library + * PURPOSE: Runtime library exception support for IA-32 + * FILE: lib/msvcrt/except/seh.s + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: This file is shared with ntoskrnl/rtl/i386/seh.s. + * Please keep them in sync. + */ + +#define ExceptionContinueExecution 0 +#define ExceptionContinueSearch 1 +#define ExceptionNestedException 2 +#define ExceptionCollidedUnwind 3 + +#define EXCEPTION_NONCONTINUABLE 0x01 +#define EXCEPTION_UNWINDING 0x02 +#define EXCEPTION_EXIT_UNWIND 0x04 +#define EXCEPTION_STACK_INVALID 0x08 +#define EXCEPTION_NESTED_CALL 0x10 +#define EXCEPTION_TARGET_UNWIND 0x20 +#define EXCEPTION_COLLIDED_UNWIND 0x40 + +#define EXCEPTION_UNWIND_MODE \ +( EXCEPTION_UNWINDING \ + | EXCEPTION_EXIT_UNWIND \ + | EXCEPTION_TARGET_UNWIND \ + | EXCEPTION_COLLIDED_UNWIND) + +#define EREC_CODE 0x00 +#define EREC_FLAGS 0x04 +#define EREC_RECORD 0x08 +#define EREC_ADDRESS 0x0C +#define EREC_NUMPARAMS 0x10 +#define EREC_INFO 0x14 + +#define TRYLEVEL_NONE -1 +#define TRYLEVEL_INVALID -2 + +#define ER_STANDARDESP -0x08 +#define ER_EPOINTERS -0x04 +#define ER_PREVFRAME 0x00 +#define ER_HANDLER 0x04 +#define ER_SCOPETABLE 0x08 +#define ER_TRYLEVEL 0x0C +#define ER_EBP 0x10 + +#define ST_TRYLEVEL 0x00 +#define ST_FILTER 0x04 +#define ST_HANDLER 0x08 + +#define CONTEXT_EDI 0x9C +#define CONTEXT_EBX 0xA4 +#define CONTEXT_EIP 0xB8 + +.globl __local_unwind2 +.globl __except_handler3 + +// EAX = value to print +_do_debug: + pushal + pushl %eax + call _MsvcrtDebug@4 + popal + ret + +#define LU2_TRYLEVEL 0x08 +#define LU2_REGFRAME 0x04 + +// +// void +// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame, +// LONG TryLevel) +// +// Parameters: +// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [EDX+04h] - LONG TryLevel +// Registers: +// EBP - EBP of call frame we are unwinding +// Returns: +// Nothing +// Notes: +// Run all termination handlers for a call frame from the current +// try-level up to (but not including) the given stop try-level. +__local_unwind2: + // Setup our call frame so we can access parameters using EDX + //pushl %ebp + movl %esp, %edx + + // FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the + // unwinding in case something goes wrong + +.lu2_next_scope: + + // Keep a pointer to the exception registration in EBX + movl LU2_REGFRAME(%edx), %ebx + + // If we have reached the end of the chain or we're asked to stop here + // by the caller then exit + movl ER_TRYLEVEL(%ebx), %eax + + cmpl $-1, %eax + je .lu2_done + + cmpl LU2_TRYLEVEL(%edx), %eax + je .lu2_done + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + + // Compute the offset of the entry in the scopetable that describes + // the scope that is to be unwound. Put the offset in EDI. + movl ST_TRYLEVEL(%esi), %edi + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + + // If this is not a termination handler then skip it + cmpl $0, ST_FILTER(%edi) + jne .lu2_next_scope + + // Save the previous try-level in the exception registration structure + movl ST_TRYLEVEL(%edi), %eax + movl %eax, ER_TRYLEVEL(%ebx) + + // Fetch the address of the termination handler + movl ST_HANDLER(%edi), %eax + + // Termination handlers may trash all registers so save the + // important ones and then call the handler + pushl %edx + call *%eax + + // Get our base pointer back + popl %edx + + jmp .lu2_next_scope + +.lu2_done: + + // FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect + // the unwinding + + //movl %esi, %esp + //popl %ebp + ret + +#define EH3_DISPCONTEXT 0x14 +#define EH3_CONTEXT 0x10 +#define EH3_REGFRAME 0x0C +#define EH3_ERECORD 0x08 + +// Parameters: +// [ESP+14h] - PVOID DispatcherContext +// [ESP+10h] - PCONTEXT Context +// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord +// Registers: +// Unknown +// Returns: +// EXCEPTION_DISPOSITION - How this handler handled the exception +// Notes: +// Try to find an exception handler that will handle the exception. +// Traverse the entries in the scopetable that is associated with the +// exception registration passed as a parameter to this function. +// If an exception handler that will handle the exception is found, it +// is called and this function never returns +__except_handler3: + // Setup our call frame so we can access parameters using EBP + pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION) + movl %esp, %ebp + + // Don't trust the direction flag to be cleared + cld + + // Either we're called to handle an exception or we're called to unwind + movl EH3_ERECORD(%ebp), %eax + testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax) + jnz .eh3_unwind + + // Keep a pointer to the exception registration in EBX + movl EH3_REGFRAME(%ebp), %ebx + + // Build an EXCEPTION_POINTERS structure on the stack and store it's + // address in the EXCEPTION_REGISTRATION structure + movl EH3_CONTEXT(%esp), %eax + pushl %ebx // Registration frame + pushl %eax // Context + movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack + + // Keep current try-level in EDI + movl ER_TRYLEVEL(%ebx), %edi + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + +.eh3_next_scope: + + // If we have reached the end of the chain then exit + cmpl $-1, %edi + je .eh3_search + + // Compute the offset of the entry in the scopetable and store + // the absolute address in EAX + lea (%edi, %edi, 2), %eax + shll $2, %eax + addl %esi, %eax + + // Fetch the address of the filter routine + movl ST_FILTER(%eax), %eax + + // If this is a termination handler then skip it + cmpl $0, %eax + je .eh3_continue + + // Filter routines may trash all registers so save the important + // ones before restoring the call frame ebp and calling the handler + pushl %ebp + pushl %edi // Stop try-level + lea ER_EBP(%ebx), %ebp + call *%eax + popl %edi // Stop try-level + popl %ebp + + // Reload EBX with registration frame address + movl EH3_REGFRAME(%ebp), %ebx + + // Be more flexible here by checking if the return value is less than + // zero, equal to zero, or larger than zero instead of the defined + // values: + // -1 (EXCEPTION_CONTINUE_EXECUTION) + // 0 (EXCEPTION_CONTINUE_SEARCH) + // +1 (EXCEPTION_EXECUTE_HANDLER) + orl %eax, %eax + jz .eh3_continue + js .eh3_dismiss + + // Filter returned: EXCEPTION_EXECUTE_HANDLER + + // Ask the OS to perform global unwinding. + pushl %edi // Save stop try-level + pushl %ebx // Save registration frame address + pushl %ebx // Registration frame address + call __global_unwind2 + popl %eax // Remove parameter to __global_unwind2 + popl %ebx // Restore registration frame address + popl %edi // Restore stop try-level + + // Change the context structure so _except_finish is called in the + // correct context since we return ExceptionContinueExecution. + movl EH3_CONTEXT(%ebp), %eax + + movl %edi, CONTEXT_EDI(%eax) // Stop try-level + movl %ebx, CONTEXT_EBX(%eax) // Registration frame address + movl $_except_finish, CONTEXT_EIP(%eax) + + movl $ExceptionContinueExecution, %eax + jmp .eh3_return + + // Filter returned: EXCEPTION_CONTINUE_SEARCH +.eh3_continue: + + // Reload ESI because the filter routine may have trashed it + movl ER_SCOPETABLE(%ebx), %esi + + // Go one try-level closer to the top + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + movl ST_TRYLEVEL(%edi), %edi + + jmp .eh3_next_scope + + // Filter returned: EXCEPTION_CONTINUE_EXECUTION + // Continue execution like nothing happened +.eh3_dismiss: + movl $ExceptionContinueExecution, %eax + jmp .eh3_return + + // Tell the OS to search for another handler that will handle the exception +.eh3_search: + + movl $ExceptionContinueSearch, %eax + jmp .eh3_return + + // Perform local unwinding +.eh3_unwind: + + movl $ExceptionContinueSearch, %eax + testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax) + jnz .eh3_return + + // Save some important registers + pushl %ebp + + lea ER_EBP(%ebx), %ebp + pushl $-1 + pushl %ebx + call __local_unwind2 + addl $8, %esp + + // Restore some important registers + popl %ebp + + movl $ExceptionContinueSearch, %eax + + // Get me out of here +.eh3_return: + + movl %ebp, %esp + popl %ebp + ret + +// Parameters: +// None +// Registers: +// EBX - Pointer to exception registration structure +// EDI - Stop try-level +// Returns: +// - +// Notes: +// - +_except_finish: + + // Setup EBP for the exception handler. By doing this the exception + // handler can access local variables as normal + lea ER_EBP(%ebx), %ebp + + // Save some important registers + pushl %ebp + pushl %ebx + pushl %edi + + // Stop try-level + pushl %edi + + // Pointer to exception registration structure + pushl %ebx + call __local_unwind2 + addl $8, %esp + + // Restore some important registers + popl %edi + popl %ebx + popl %ebp + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + + // Compute the offset of the entry in the scopetable and store + // the absolute address in EDI + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + + // Set the current try-level to the previous try-level and call + // the exception handler + movl ST_TRYLEVEL(%edi), %eax + movl %eax, ER_TRYLEVEL(%ebx) + movl ST_HANDLER(%edi), %eax + + call *%eax + + // We should never get here + ret diff --git a/lib/msvcrt/except/unwind.c b/lib/msvcrt/except/unwind.c new file mode 100644 index 0000000..b4dc555 --- /dev/null +++ b/lib/msvcrt/except/unwind.c @@ -0,0 +1,10 @@ +#include + +void __cdecl +_global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame) +{ + RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0); +__ret_label: + // return is important + return; +} diff --git a/lib/msvcrt/except/xcptfil.c b/lib/msvcrt/except/xcptfil.c new file mode 100644 index 0000000..0a4271a --- /dev/null +++ b/lib/msvcrt/except/xcptfil.c @@ -0,0 +1,11 @@ +#include + + +int +_XcptFilter(DWORD ExceptionCode, + struct _EXCEPTION_POINTERS * ExceptionInfo) +{ + //fixme XcptFilter +// return UnhandledExceptionFilter(ExceptionInfo); +} + diff --git a/lib/msvcrt/float/.cvsignore b/lib/msvcrt/float/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/float/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/float/chgsign.c b/lib/msvcrt/float/chgsign.c new file mode 100644 index 0000000..0fb4072 --- /dev/null +++ b/lib/msvcrt/float/chgsign.c @@ -0,0 +1,13 @@ +#include +#include + +double _chgsign( double __x ) +{ + double_t *x = (double_t *)&x; + if ( x->sign == 1 ) + x->sign = 0; + else + x->sign = 1; + + return __x; +} diff --git a/lib/msvcrt/float/clearfp.c b/lib/msvcrt/float/clearfp.c new file mode 100644 index 0000000..11e03e5 --- /dev/null +++ b/lib/msvcrt/float/clearfp.c @@ -0,0 +1,13 @@ +#include + +unsigned int _clearfp (void) +{ + unsigned short __res = _statusfp(); + +__asm__ __volatile__ ( + "fclex \n\t" + ); + + return __res; +} + diff --git a/lib/msvcrt/float/cntrlfp.c b/lib/msvcrt/float/cntrlfp.c new file mode 100644 index 0000000..c15444d --- /dev/null +++ b/lib/msvcrt/float/cntrlfp.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include + +unsigned int _controlfp(unsigned int unNew, unsigned int unMask) +{ + return _control87(unNew,unMask); +} + +unsigned int _control87(unsigned int unNew, unsigned int unMask) +{ +register unsigned int __res; + +__asm__ __volatile__ ( + "pushl %%eax \n\t" /* make room on stack */ + "fstcw (%%esp) \n\t" + "fwait \n\t" + "popl %%eax \n\t" + "andl $0xffff, %%eax \n\t" /* OK; we have the old value ready */ + + "movl %1, %%ecx \n\t" + "notl %%ecx \n\t" + "andl %%eax, %%ecx \n\t" /* the bits we want to keep */ + + "movl %2, %%edx \n\t" + "andl %1, %%edx \n\t" /* the bits we want to change */ + + "orl %%ecx, %%edx\n\t" /* the new value */ + "pushl %%edx \n\t" + "fldcw (%%esp) \n\t" + "popl %%edx \n\t" + + :"=r" (__res):"r" (unNew),"r" (unMask): "ax", "dx", "cx"); + + return __res; +} diff --git a/lib/msvcrt/float/copysign.c b/lib/msvcrt/float/copysign.c new file mode 100644 index 0000000..1c488b4 --- /dev/null +++ b/lib/msvcrt/float/copysign.c @@ -0,0 +1,13 @@ +#include +#include + +double _copysign (double __d, double __s) +{ + double_t *d = (double_t *)&__d; + double_t *s = (double_t *)&__s; + + d->sign = s->sign; + + return __d; +} + diff --git a/lib/msvcrt/float/fpclass.c b/lib/msvcrt/float/fpclass.c new file mode 100644 index 0000000..d4c280a --- /dev/null +++ b/lib/msvcrt/float/fpclass.c @@ -0,0 +1,65 @@ +#include +#include +#include + +#define _FPCLASS_SNAN 0x0001 /* signaling NaN */ +#define _FPCLASS_QNAN 0x0002 /* quiet NaN */ +#define _FPCLASS_NINF 0x0004 /* negative infinity */ +#define _FPCLASS_NN 0x0008 /* negative normal */ +#define _FPCLASS_ND 0x0010 /* negative denormal */ +#define _FPCLASS_NZ 0x0020 /* -0 */ +#define _FPCLASS_PZ 0x0040 /* +0 */ +#define _FPCLASS_PD 0x0080 /* positive denormal */ +#define _FPCLASS_PN 0x0100 /* positive normal */ +#define _FPCLASS_PINF 0x0200 /* positive infinity */ + +#define FP_SNAN 0x0001 // signaling NaN +#define FP_QNAN 0x0002 // quiet NaN +#define FP_NINF 0x0004 // negative infinity +#define FP_PINF 0x0200 // positive infinity +#define FP_NDENORM 0x0008 // negative denormalized non-zero +#define FP_PDENORM 0x0010 // positive denormalized non-zero +#define FP_NZERO 0x0020 // negative zero +#define FP_PZERO 0x0040 // positive zero +#define FP_NNORM 0x0080 // negative normalized non-zero +#define FP_PNORM 0x0100 // positive normalized non-zero + +typedef int fpclass_t; + +fpclass_t _fpclass(double __d) +{ + double_t *d = (double_t *)&__d; + + if ( d->exponent == 0 ) { + if ( d->mantissah == 0 && d->mantissal == 0 ) { + if ( d->sign ==0 ) + return FP_NZERO; + else + return FP_PZERO; + } else { + if ( d->sign ==0 ) + return FP_NDENORM; + else + return FP_PDENORM; + } + } + if (d->exponent == 0x7ff ) { + if ( d->mantissah == 0 && d->mantissal == 0 ) { + if ( d->sign ==0 ) + return FP_NINF; + else + return FP_PINF; + } + else if ( d->mantissah == 0 && d->mantissal != 0 ) { + return FP_QNAN; + } + else if ( d->mantissah == 0 && d->mantissal != 0 ) { + return FP_SNAN; + } + + } + + return 0; +} + + diff --git a/lib/msvcrt/float/fpecode.c b/lib/msvcrt/float/fpecode.c new file mode 100644 index 0000000..3bc2082 --- /dev/null +++ b/lib/msvcrt/float/fpecode.c @@ -0,0 +1,7 @@ +#include +#include + +int * __fpecode(void) +{ + return(&(GetThreadData()->fpecode)); +} diff --git a/lib/msvcrt/float/fpreset.c b/lib/msvcrt/float/fpreset.c new file mode 100644 index 0000000..4127159 --- /dev/null +++ b/lib/msvcrt/float/fpreset.c @@ -0,0 +1,8 @@ +#include + +void _fpreset(void) +{ + /* FIXME: This causes an exception */ +// __asm__ __volatile__("fninit\n\t"); + return; +} diff --git a/lib/msvcrt/float/isnan.c b/lib/msvcrt/float/isnan.c new file mode 100644 index 0000000..6cff15b --- /dev/null +++ b/lib/msvcrt/float/isnan.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +int _isnan(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah != 0 || x->mantissal != 0 )); +} + +int _isnanl(long double __x) +{ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* IEEE 854 NaN's have the maximum possible + exponent and a nonzero mantissa. */ + + return (( x->exponent == 0x7fff) + && ( (x->mantissah & 0x80000000) != 0) + && ( (x->mantissah & (unsigned int)0x7fffffff) != 0 || x->mantissal != 0 )); +} + + +int _isinf(double __x) +{ + double_t * x = (double_t *)&__x; + return ( x->exponent == 0x7ff && ( x->mantissah == 0 && x->mantissal == 0 )); +} + + + +int _finite( double x ) +{ + return !_isinf(x); +} + +int _isinfl(long double __x) +{ + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + + long_double_t * x = (long_double_t *)&__x; + + + /* An IEEE 854 infinity has an exponent with the + maximum possible value and a zero mantissa. */ + + + if ( x->exponent == 0x7fff && ( (x->mantissah == 0x80000000 ) && x->mantissal == 0 )) + return x->sign ? -1 : 1; + return 0; +} + + diff --git a/lib/msvcrt/float/logb.c b/lib/msvcrt/float/logb.c new file mode 100644 index 0000000..140a104 --- /dev/null +++ b/lib/msvcrt/float/logb.c @@ -0,0 +1,31 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double _logb (double __x) +{ + register double __value, __junk; + __asm __volatile__ + ("fxtract\n\t" + : "=t" (__junk), "=u" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/float/nafter.c b/lib/msvcrt/float/nafter.c new file mode 100644 index 0000000..9773d92 --- /dev/null +++ b/lib/msvcrt/float/nafter.c @@ -0,0 +1,12 @@ +#include + +double _nextafter( double x, double y ) +{ + if ( x == y) + return x; + + if ( isnan(x) || isnan(y) ) + return x; + + return x; +} diff --git a/lib/msvcrt/float/scalb.c b/lib/msvcrt/float/scalb.c new file mode 100644 index 0000000..a2d1eac --- /dev/null +++ b/lib/msvcrt/float/scalb.c @@ -0,0 +1,11 @@ +#include +#include + +double _scalb( double __x, long e ) +{ + double_t *x = (double_t *)&__x; + + x->exponent += e; + + return __x; +} diff --git a/lib/msvcrt/float/statfp.c b/lib/msvcrt/float/statfp.c new file mode 100644 index 0000000..cef37a3 --- /dev/null +++ b/lib/msvcrt/float/statfp.c @@ -0,0 +1,14 @@ +#include + +unsigned int _statusfp (void) +{ + +register unsigned short __res; + +__asm__ __volatile__ ( + "fstsw %0 \n\t" +// "movzwl %ax, %eax" + :"=a" (__res) + ); + return __res; +} diff --git a/lib/msvcrt/io/.cvsignore b/lib/msvcrt/io/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/io/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/io/access.c b/lib/msvcrt/io/access.c new file mode 100644 index 0000000..493c4a7 --- /dev/null +++ b/lib/msvcrt/io/access.c @@ -0,0 +1,72 @@ +#include +#include +#include +#define NDEBUG +#include + +#ifndef F_OK + #define F_OK 0x01 +#endif +#ifndef R_OK + #define R_OK 0x02 +#endif +#ifndef W_OK + #define W_OK 0x04 +#endif +#ifndef X_OK + #define X_OK 0x08 +#endif +#ifndef D_OK + #define D_OK 0x10 +#endif + +int _access( const char *_path, int _amode ) +{ + DWORD Attributes = GetFileAttributesA(_path); + DPRINT("_access('%s', %x)\n", _path, _amode); + + if ( Attributes == -1 ) { + __set_errno(ENOENT); + return -1; + } + + if ( (_amode & W_OK) == W_OK ) { + if ( (Attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY ) { + __set_errno(EACCES); + return -1; + } + } + if ( (_amode & D_OK) == D_OK ) { + if ( (Attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) { + __set_errno(EACCES); + return -1; + } + } + + return 0; +} + +int _waccess( const wchar_t *_path, int _amode ) +{ + DWORD Attributes = GetFileAttributesW(_path); + + if ( Attributes == -1 ) { + __set_errno(ENOENT); + return -1; + } + + if ( (_amode & W_OK) == W_OK ) { + if ( (Attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY ) { + __set_errno(EACCES); + return -1; + } + } + if ( (_amode & D_OK) == D_OK ) { + if ( (Attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ) { + __set_errno(EACCES); + return -1; + } + } + + return 0; +} diff --git a/lib/msvcrt/io/chmod.c b/lib/msvcrt/io/chmod.c new file mode 100644 index 0000000..f5d61aa --- /dev/null +++ b/lib/msvcrt/io/chmod.c @@ -0,0 +1,57 @@ +#include +#include + +#define NDEBUG +#include + +#define mode_t int + +int _chmod(const char *filename, mode_t mode) +{ + DWORD FileAttributes = 0; + DPRINT("_chmod('%s', %x)\n", filename, mode); + + FileAttributes = GetFileAttributesA(filename); + if ( FileAttributes == -1 ) + return -1; + + if ( mode == 0 ) + return -1; + + if ((mode & _S_IREAD) == _S_IREAD && (mode & _S_IWRITE) != _S_IWRITE) + FileAttributes &= FILE_ATTRIBUTE_READONLY; + else if (((mode & _S_IREAD) != _S_IREAD) && ((mode & _S_IWRITE) == _S_IWRITE)) + FileAttributes &= FILE_ATTRIBUTE_NORMAL; + else + FileAttributes &= FILE_ATTRIBUTE_NORMAL; + + if (SetFileAttributesA(filename, FileAttributes) == FALSE) + return -1; + + return 1; +} + +int _wchmod(const wchar_t *filename, mode_t mode) +{ + DWORD FileAttributes = 0; + DPRINT("_wchmod('%S', %x)\n", filename, mode); + + FileAttributes = GetFileAttributesW(filename); + if ( FileAttributes == -1 ) + return -1; + + if ( mode == 0 ) + return -1; + + if ((mode & _S_IREAD) == _S_IREAD && (mode & _S_IWRITE) != _S_IWRITE) + FileAttributes &= FILE_ATTRIBUTE_READONLY; + else if (((mode & _S_IREAD) != _S_IREAD) && ((mode & _S_IWRITE) == _S_IWRITE)) + FileAttributes &= FILE_ATTRIBUTE_NORMAL; + else + FileAttributes &= FILE_ATTRIBUTE_NORMAL; + + if (SetFileAttributesW(filename, FileAttributes) == FALSE) + return -1; + + return 1; +} diff --git a/lib/msvcrt/io/chsize.c b/lib/msvcrt/io/chsize.c new file mode 100644 index 0000000..865bec2 --- /dev/null +++ b/lib/msvcrt/io/chsize.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +#include + +#define NDEBUG +#include + +int _chsize(int _fd, long size) +{ + DPRINT("_chsize(fd %d, size %d)\n", _fd, size); + if (lseek(_fd, size, 0) == -1) + return -1; + if (_write(_fd, 0, 0) < 0) + return -1; + return 0; +} diff --git a/lib/msvcrt/io/close.c b/lib/msvcrt/io/close.c new file mode 100644 index 0000000..65d6230 --- /dev/null +++ b/lib/msvcrt/io/close.c @@ -0,0 +1,16 @@ +#include +#include +#include + +#define NDEBUG +#include + +int _close(int _fd) +{ + DPRINT("_close(fd %d)\n", _fd); + if (_fd == -1) + return -1; + if (CloseHandle(_get_osfhandle(_fd)) == FALSE) + return -1; + return __fileno_close(_fd); +} diff --git a/lib/msvcrt/io/commit.c b/lib/msvcrt/io/commit.c new file mode 100644 index 0000000..406b03f --- /dev/null +++ b/lib/msvcrt/io/commit.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +int _commode = _IOCOMMIT; + + +int *__p__commode(void) +{ + return &_commode; +} + +int _commit(int _fd) +{ + if (! FlushFileBuffers(_get_osfhandle(_fd)) ) + { + __set_errno(EBADF); + return -1; + } + + return 0; +} diff --git a/lib/msvcrt/io/create.c b/lib/msvcrt/io/create.c new file mode 100644 index 0000000..3f11706 --- /dev/null +++ b/lib/msvcrt/io/create.c @@ -0,0 +1,17 @@ +#include +#include + +#define NDEBUG +#include + +int _creat(const char *filename, int mode) +{ + DPRINT("_creat('%s', mode %x)\n", filename, mode); + return _open(filename,_O_CREAT|_O_TRUNC,mode); +} + +int _wcreat(const wchar_t *filename, int mode) +{ + DPRINT("_wcreat('%S', mode %x)\n", filename, mode); + return _wopen(filename,_O_CREAT|_O_TRUNC,mode); +} diff --git a/lib/msvcrt/io/dup.c b/lib/msvcrt/io/dup.c new file mode 100644 index 0000000..048c423 --- /dev/null +++ b/lib/msvcrt/io/dup.c @@ -0,0 +1,33 @@ +/* $Id$ */ +#include +#include +#include + + +int _dup(int handle) +{ + HANDLE hFile; + HANDLE hProcess = GetCurrentProcess(); + BOOL result; + int fd; + + hFile = _get_osfhandle(handle); + if (hFile == INVALID_HANDLE_VALUE) + return -1; + result = DuplicateHandle(hProcess, + hFile, + hProcess, + &hFile, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if (result == FALSE) + return -1; + + fd = __fileno_alloc(hFile, __fileno_getmode(handle)); + if (fd < 0) + { + CloseHandle(hFile); + } + return fd; +} diff --git a/lib/msvcrt/io/dup2.c b/lib/msvcrt/io/dup2.c new file mode 100644 index 0000000..fc82505 --- /dev/null +++ b/lib/msvcrt/io/dup2.c @@ -0,0 +1,7 @@ +#include +#include + +int _dup2(int handle1, int handle2) +{ + return __fileno_dup2(handle1, handle2); +} diff --git a/lib/msvcrt/io/eof.c b/lib/msvcrt/io/eof.c new file mode 100644 index 0000000..5fa959d --- /dev/null +++ b/lib/msvcrt/io/eof.c @@ -0,0 +1,15 @@ +//#include +#include + +int _eof(int _fd) +{ + __int64 cur_pos = _lseeki64(_fd, 0, SEEK_CUR); + __int64 end_pos = _lseeki64(_fd, 0, SEEK_END); + if ( cur_pos == -1 || end_pos == -1) + return -1; + + if (cur_pos == end_pos) + return 1; + + return 0; +} diff --git a/lib/msvcrt/io/filelen.c b/lib/msvcrt/io/filelen.c new file mode 100644 index 0000000..84e9f10 --- /dev/null +++ b/lib/msvcrt/io/filelen.c @@ -0,0 +1,16 @@ +#include +#include + +long _filelength(int _fd) +{ + return GetFileSize(_get_osfhandle(_fd),NULL); +} + +__int64 _filelengthi64(int _fd) +{ + long lo_length, hi_length; + + lo_length = GetFileSize(_get_osfhandle(_fd), &hi_length); + + return((((__int64)hi_length) << 32) + lo_length); +} diff --git a/lib/msvcrt/io/find.c b/lib/msvcrt/io/find.c new file mode 100644 index 0000000..f7921b8 --- /dev/null +++ b/lib/msvcrt/io/find.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include + + +int _findclose(int handle) +{ + // check no wildcards or invalid handle + if (handle == 0 || handle == -1) + return 0; + return FindClose((void *)handle); +} + +int _findfirst(const char *_name, struct _finddata_t *result) +{ + WIN32_FIND_DATAA FindFileData; + char dir[MAX_PATH]; + long hFindFile; + int len = 0; + + if ( _name == NULL || _name[0] == 0 ) + { + len = GetCurrentDirectoryA(MAX_PATH-4,dir); + if (dir[len-1] != '\\') + { + dir[len] = '\\'; + dir[len+1] = 0; + } + strcat(dir,"*.*"); + } + else + strcpy(dir,_name); + + hFindFile = (long)FindFirstFileA( dir, &FindFileData ); + if (hFindFile == -1) + { + memset(result,0,sizeof(struct _finddata_t)); + return -1; + } + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = FindFileData.nFileSizeLow; + strncpy(result->name,FindFileData.cFileName,MAX_PATH); + + // if no wildcard the find file handle can be closed right away + // a return value of 0 can flag this. + + if (!strchr(dir,'*') && !strchr(dir,'?')) + { + _findclose(hFindFile); + return 0; + } + + return hFindFile; +} + +int _findfirsti64(const char *_name, struct _finddatai64_t *result) +{ + WIN32_FIND_DATAA FindFileData; + char dir[MAX_PATH]; + long hFindFile; + int len = 0; + + if ( _name == NULL || _name[0] == 0 ) + { + len = GetCurrentDirectoryA(MAX_PATH-4,dir); + if (dir[len-1] != '\\') + { + dir[len] = '\\'; + dir[len+1] = 0; + } + strcat(dir, "*.*"); + } + else + strcpy(dir, _name); + + hFindFile = (long)FindFirstFileA(dir, &FindFileData); + if (hFindFile == -1) + { + memset(result,0,sizeof(struct _finddatai64_t)); + return -1; + } + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = + (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow; + strncpy(result->name,FindFileData.cFileName,MAX_PATH); + + // if no wildcard the find file handle can be closed right away + // a return value of 0 can flag this. + + if (!strchr(dir,'*') && !strchr(dir,'?')) + { + _findclose(hFindFile); + return 0; + } + + return hFindFile; +} + +int _findnext(int handle, struct _finddata_t *result) +{ + WIN32_FIND_DATAA FindFileData; + + // check no wildcards or invalid handle + if (handle == 0 || handle == -1) + return 0; + + if (!FindNextFileA((void *)handle, &FindFileData)) + return -1; + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = FindFileData.nFileSizeLow; + strncpy(result->name,FindFileData.cFileName, MAX_PATH); + + return 0; +} + +int _findnexti64(int handle, struct _finddatai64_t *result) +{ + WIN32_FIND_DATAA FindFileData; + + // check no wildcards or invalid handle + if (handle == 0 || handle == -1) + return 0; + + if (!FindNextFileA((void *)handle, &FindFileData)) + return -1; + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = + (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow; + strncpy(result->name,FindFileData.cFileName,MAX_PATH); + + return 0; +} + +int _wfindfirst(const wchar_t *_name, struct _wfinddata_t *result) +{ + WIN32_FIND_DATAW FindFileData; + wchar_t dir[MAX_PATH]; + long hFindFile; + int len = 0; + + if ( _name == NULL || _name[0] == 0 ) + { + len = GetCurrentDirectoryW(MAX_PATH-4, dir); + if (dir[len-1] != L'\\') + { + dir[len] = L'\\'; + dir[len+1] = 0; + } + wcscat(dir, L"*.*"); + } + else + wcscpy(dir, _name); + + hFindFile = (long)FindFirstFileW(dir, &FindFileData); + if (hFindFile == -1) + { + memset(result,0,sizeof(struct _wfinddata_t)); + return -1; + } + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = FindFileData.nFileSizeLow; + wcsncpy(result->name,FindFileData.cFileName,MAX_PATH); + + // if no wildcard the find file handle can be closed right away + // a return value of 0 can flag this. + + if (!wcschr(dir, L'*') && !wcschr(dir, L'?')) + { + _findclose(hFindFile); + return 0; + } + + return hFindFile; +} + +int _wfindfirsti64(const wchar_t *_name, struct _wfinddatai64_t *result) +{ + WIN32_FIND_DATAW FindFileData; + wchar_t dir[MAX_PATH]; + long hFindFile; + int len = 0; + + if (_name == NULL || _name[0] == 0) + { + len = GetCurrentDirectoryW(MAX_PATH-4,dir); + if (dir[len-1] != L'\\') + { + dir[len] = L'\\'; + dir[len+1] = 0; + } + wcscat(dir, L"*.*"); + } + else + wcscpy(dir, _name); + + hFindFile = (long)FindFirstFileW(dir, &FindFileData); + if (hFindFile == -1) + { + memset(result,0,sizeof(struct _wfinddatai64_t)); + return -1; + } + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = + (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow; + wcsncpy(result->name,FindFileData.cFileName,MAX_PATH); + + // if no wildcard the find file handle can be closed right away + // a return value of 0 can flag this. + + if (!wcschr(dir,L'*') && !wcschr(dir,L'?')) + { + _findclose(hFindFile); + return 0; + } + + return hFindFile; +} + +int _wfindnext(int handle, struct _wfinddata_t *result) +{ + WIN32_FIND_DATAW FindFileData; + + // check no wildcards or invalid handle + if (handle == 0 || handle == -1) + return 0; + + if (!FindNextFileW((void *)handle, &FindFileData)) + return -1; + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = FindFileData.nFileSizeLow; + wcsncpy(result->name,FindFileData.cFileName, MAX_PATH); + + return 0; +} + +int _wfindnexti64(int handle, struct _wfinddatai64_t *result) +{ + WIN32_FIND_DATAW FindFileData; + + // check no wildcards or invalid handle + if (handle == 0 || handle == -1) + return 0; + + if (!FindNextFileW((void *)handle, &FindFileData)) + return -1; + + result->attrib = FindFileData.dwFileAttributes; + result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL); + result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL); + result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL); + result->size = + (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow; + wcsncpy(result->name,FindFileData.cFileName,MAX_PATH); + + return 0; +} diff --git a/lib/msvcrt/io/fmode.c b/lib/msvcrt/io/fmode.c new file mode 100644 index 0000000..7d1909d --- /dev/null +++ b/lib/msvcrt/io/fmode.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#undef _fmode +unsigned int _fmode = O_TEXT; + +unsigned int *__p__fmode(void) +{ + return &_fmode; +} diff --git a/lib/msvcrt/io/isatty.c b/lib/msvcrt/io/isatty.c new file mode 100644 index 0000000..3ed7a80 --- /dev/null +++ b/lib/msvcrt/io/isatty.c @@ -0,0 +1,16 @@ +#include +#include + +#define NDEBUG +#include + +int _isatty( int fd ) +{ + struct stat buf; + DPRINT("_isatty(fd %d)\n", fd); + if (_fstat (fd, &buf) < 0) + return 0; + if (S_ISCHR (buf.st_mode)) + return 1; + return 0; +} diff --git a/lib/msvcrt/io/locking.c b/lib/msvcrt/io/locking.c new file mode 100644 index 0000000..ba32830 --- /dev/null +++ b/lib/msvcrt/io/locking.c @@ -0,0 +1,10 @@ +#include +#include + +int _locking(int _fd, int mode, long nbytes) +{ + long offset = _lseek(_fd, 0L, 1); + if (!LockFile(_get_osfhandle(_fd),offset,0,nbytes,0)) + return -1; + return 0; +} diff --git a/lib/msvcrt/io/lseek.c b/lib/msvcrt/io/lseek.c new file mode 100644 index 0000000..4f03d43 --- /dev/null +++ b/lib/msvcrt/io/lseek.c @@ -0,0 +1,17 @@ +#include +#include +#include + + +long _lseek(int _fildes, long _offset, int _whence) +{ + return (SetFilePointer((HANDLE)filehnd(_fildes), _offset, NULL, _whence)); +} + +__int64 _lseeki64(int _fildes, __int64 _offset, int _whence) +{ + ULONG lo_pos, hi_pos; + + lo_pos = SetFilePointer((HANDLE)filehnd(_fildes), _offset, &hi_pos, _whence); + return((((__int64)hi_pos) << 32) + lo_pos); +} diff --git a/lib/msvcrt/io/mktemp.c b/lib/msvcrt/io/mktemp.c new file mode 100644 index 0000000..6f31b4a --- /dev/null +++ b/lib/msvcrt/io/mktemp.c @@ -0,0 +1,128 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/mktemp.c + * PURPOSE: Makes a temp file based on a template + * PROGRAMER: DJ Delorie + Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Appropriated for the Reactos Kernel + */ + +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +#define NDEBUG +#include + + +char* _mktemp (char *_template) +{ + static int count = 0; + char *cp, *dp; + int i, len, xcount, loopcnt; + + DPRINT("_mktemp('%s')\n", _template); + len = strlen (_template); + cp = _template + len; + + xcount = 0; + while (xcount < 6 && cp > _template && cp[-1] == 'X') + xcount++, cp--; + + if (xcount) { + dp = cp; + while (dp > _template && dp[-1] != '/' && dp[-1] != '\\' && dp[-1] != ':') + dp--; + + /* Keep the first characters of the template, but turn the rest into + Xs. */ + while (cp > dp + 8 - xcount) { + *--cp = 'X'; + xcount = (xcount >= 6) ? 6 : 1 + xcount; + } + + /* If dots occur too early -- squash them. */ + while (dp < cp) { + if (*dp == '.') *dp = 'a'; + dp++; + } + + /* Try to add ".tmp" to the filename. Truncate unused Xs. */ + if (cp + xcount + 3 < _template + len) + strcpy (cp + xcount, ".tmp"); + else + cp[xcount] = 0; + + /* This loop can run up to 2<<(5*6) times, or about 10^9 times. */ + for (loopcnt = 0; loopcnt < (1 << (5 * xcount)); loopcnt++) { + int c = count++; + for (i = 0; i < xcount; i++, c >>= 5) + cp[i] = "abcdefghijklmnopqrstuvwxyz012345"[c & 0x1f]; + if (_access(_template,0) == -1) + return _template; + } + } + + /* Failure: truncate the template and return NULL. */ + *_template = 0; + return 0; +} + +wchar_t* _wmktemp (wchar_t *_template) +{ + static int count = 0; + wchar_t *cp, *dp; + int i, len, xcount, loopcnt; + + DPRINT("_wmktemp('%S')\n", _template); + len = wcslen (_template); + cp = _template + len; + + xcount = 0; + while (xcount < 6 && cp > _template && cp[-1] == L'X') + xcount++, cp--; + + if (xcount) { + dp = cp; + while (dp > _template && dp[-1] != L'/' && dp[-1] != L'\\' && dp[-1] != L':') + dp--; + + /* Keep the first characters of the template, but turn the rest into + Xs. */ + while (cp > dp + 8 - xcount) { + *--cp = L'X'; + xcount = (xcount >= 6) ? 6 : 1 + xcount; + } + + /* If dots occur too early -- squash them. */ + while (dp < cp) { + if (*dp == L'.') *dp = L'a'; + dp++; + } + + /* Try to add ".tmp" to the filename. Truncate unused Xs. */ + if (cp + xcount + 3 < _template + len) + wcscpy (cp + xcount, L".tmp"); + else + cp[xcount] = 0; + + /* This loop can run up to 2<<(5*6) times, or about 10^9 times. */ + for (loopcnt = 0; loopcnt < (1 << (5 * xcount)); loopcnt++) { + int c = count++; + for (i = 0; i < xcount; i++, c >>= 5) + cp[i] = L"abcdefghijklmnopqrstuvwxyz012345"[c & 0x1f]; + if (_waccess(_template,0) == -1) + return _template; + } + } + + /* Failure: truncate the template and return NULL. */ + *_template = 0; + return 0; +} diff --git a/lib/msvcrt/io/open.c b/lib/msvcrt/io/open.c new file mode 100644 index 0000000..354c2db --- /dev/null +++ b/lib/msvcrt/io/open.c @@ -0,0 +1,490 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/open.c + * PURPOSE: Opens a file and translates handles to fileno + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +// rember to interlock the allocation of fileno when making this thread safe + +// possibly store extra information at the handle + +#include +#if !defined(NDEBUG) && defined(DBG) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#define STD_AUX_HANDLE 3 +#define STD_PRINTER_HANDLE 4 + +typedef struct _fileno_modes_type +{ + HANDLE hFile; + int mode; + int fd; +} fileno_modes_type; + +fileno_modes_type *fileno_modes = NULL; + +int maxfno = 0; + +char __is_text_file(FILE *p) +{ + if ( p == NULL || fileno_modes == NULL ) + return FALSE; + return (!((p)->_flag&_IOSTRG) && (fileno_modes[(p)->_file].mode&O_TEXT)); +} + + +int _open(const char *_path, int _oflag,...) +{ +#if !defined(NDEBUG) && defined(DBG) + va_list arg; + int pmode; +#endif + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwShareMode = 0; + DWORD dwCreationDistribution = 0; + DWORD dwFlagsAndAttributes = 0; + DWORD dwLastError; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + +#if !defined(NDEBUG) && defined(DBG) + va_start(arg, _oflag); + pmode = va_arg(arg, int); +#endif + + DPRINT("_open('%s', %x, (%x))\n", _path, _oflag, pmode); + + if (( _oflag & S_IREAD ) == S_IREAD) + dwShareMode = FILE_SHARE_READ; + else if ( ( _oflag & S_IWRITE) == S_IWRITE ) { + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + + /* + * + * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.) + * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.) + * + * _O_APPEND Moves file pointer to end of file before every write operation. + */ + if (( _oflag & _O_RDWR ) == _O_RDWR ) + dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ ; + else if (( _oflag & O_RDONLY ) == O_RDONLY ) + dwDesiredAccess |= GENERIC_READ ; + else if (( _oflag & _O_WRONLY ) == _O_WRONLY ) + dwDesiredAccess |= GENERIC_WRITE ; + + if (( _oflag & S_IREAD ) == S_IREAD ) + dwShareMode |= FILE_SHARE_READ; + + if (( _oflag & S_IWRITE ) == S_IWRITE ) + dwShareMode |= FILE_SHARE_WRITE; + + if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) ) + dwCreationDistribution |= CREATE_NEW; + + else if (( _oflag & O_TRUNC ) == O_TRUNC ) { + if (( _oflag & O_CREAT ) == O_CREAT ) + dwCreationDistribution |= CREATE_ALWAYS; + else if (( _oflag & O_RDONLY ) != O_RDONLY ) + dwCreationDistribution |= TRUNCATE_EXISTING; + } + else if (( _oflag & _O_APPEND ) == _O_APPEND ) + dwCreationDistribution |= OPEN_EXISTING; + else if (( _oflag & _O_CREAT ) == _O_CREAT ) + dwCreationDistribution |= OPEN_ALWAYS; + else + dwCreationDistribution |= OPEN_EXISTING; + + if (( _oflag & _O_RANDOM ) == _O_RANDOM ) + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL ) + dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + + if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY ) + { + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n"); + } + + if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED ) + { + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n"); + } + + if (_oflag & _O_NOINHERIT) + sa.bInheritHandle = FALSE; + + hFile = CreateFileA(_path, + dwDesiredAccess, + dwShareMode, + &sa, + dwCreationDistribution, + dwFlagsAndAttributes, + NULL); + if (hFile == (HANDLE)-1) + { + dwLastError = GetLastError(); + if (dwLastError == ERROR_ALREADY_EXISTS) + { + DPRINT("ERROR_ALREADY_EXISTS\n"); + __set_errno(EEXIST); + } + else + { + DPRINT("%x\n", dwLastError); + __set_errno(ENOFILE); + } + return -1; + } + DPRINT("OK\n"); + if (!(_oflag & (_O_TEXT|_O_BINARY))) + { + _oflag |= _fmode; + } + return __fileno_alloc(hFile,_oflag); +} + + +int _wopen(const wchar_t *_path, int _oflag,...) +{ +#if !defined(NDEBUG) && defined(DBG) + va_list arg; + int pmode; +#endif + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwShareMode = 0; + DWORD dwCreationDistribution = 0; + DWORD dwFlagsAndAttributes = 0; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + +#if !defined(NDEBUG) && defined(DBG) + va_start(arg, _oflag); + pmode = va_arg(arg, int); +#endif + + DPRINT("_wopen('%S', %x, (%x))\n", _path, _oflag, pmode); + + if (( _oflag & S_IREAD ) == S_IREAD) + dwShareMode = FILE_SHARE_READ; + else if ( ( _oflag & S_IWRITE) == S_IWRITE ) { + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + + /* + * + * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.) + * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.) + * + * _O_APPEND Moves file pointer to end of file before every write operation. + */ + if (( _oflag & _O_RDWR ) == _O_RDWR ) + dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA | + FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | + FILE_WRITE_ATTRIBUTES; + else if (( _oflag & O_RDONLY ) == O_RDONLY ) + dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES + | FILE_WRITE_ATTRIBUTES; + else if (( _oflag & _O_WRONLY ) == _O_WRONLY ) + dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA | + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES; + + if (( _oflag & S_IREAD ) == S_IREAD ) + dwShareMode |= FILE_SHARE_READ; + + if (( _oflag & S_IWRITE ) == S_IWRITE ) + dwShareMode |= FILE_SHARE_WRITE; + + if (( _oflag & (_O_CREAT | _O_EXCL ) ) == (_O_CREAT | _O_EXCL) ) + dwCreationDistribution |= CREATE_NEW; + + else if (( _oflag & O_TRUNC ) == O_TRUNC ) { + if (( _oflag & O_CREAT ) == O_CREAT ) + dwCreationDistribution |= CREATE_ALWAYS; + else if (( _oflag & O_RDONLY ) != O_RDONLY ) + dwCreationDistribution |= TRUNCATE_EXISTING; + } + else if (( _oflag & _O_APPEND ) == _O_APPEND ) + dwCreationDistribution |= OPEN_EXISTING; + else if (( _oflag & _O_CREAT ) == _O_CREAT ) + dwCreationDistribution |= OPEN_ALWAYS; + else + dwCreationDistribution |= OPEN_EXISTING; + + if (( _oflag & _O_RANDOM ) == _O_RANDOM ) + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + if (( _oflag & _O_SEQUENTIAL ) == _O_SEQUENTIAL ) + dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + + if (( _oflag & _O_TEMPORARY ) == _O_TEMPORARY ) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + if (( _oflag & _O_SHORT_LIVED ) == _O_SHORT_LIVED ) + dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; + + if (_oflag & _O_NOINHERIT) + sa.bInheritHandle = FALSE; + + hFile = CreateFileW(_path, + dwDesiredAccess, + dwShareMode, + &sa, + dwCreationDistribution, + dwFlagsAndAttributes, + NULL); + if (hFile == (HANDLE)-1) + return -1; + return __fileno_alloc(hFile,_oflag); +} + + +int +__fileno_alloc(HANDLE hFile, int mode) +{ + int i; + /* Check for bogus values */ + if (hFile < 0) + return -1; + + for(i=5;i= maxfno || fileno_modes[fileno].fd == -1) + { + return (void *)-1; + } + return fileno_modes[fileno].hFile; +} + +int __fileno_dup2( int handle1, int handle2 ) +{ + HANDLE hProcess; + BOOL result; + if (handle1 >= maxfno || handle1 < 0 || handle2 >= maxfno || handle2 < 0 ) + { + __set_errno(EBADF); + return -1; + } + if (fileno_modes[handle1].fd == -1) + { + __set_errno(EBADF); + return -1; + } + if (handle1 == handle2) + return handle1; + if (fileno_modes[handle2].fd != -1) + { + _close(handle2); + } + hProcess = GetCurrentProcess(); + result = DuplicateHandle(hProcess, + fileno_modes[handle1].hFile, + hProcess, + &fileno_modes[handle2].hFile, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if (result) + { + fileno_modes[handle2].fd = handle2; + fileno_modes[handle2].mode = fileno_modes[handle1].mode; + switch (handle2) + { + case 0: + SetStdHandle(STD_INPUT_HANDLE, fileno_modes[handle2].hFile); + break; + case 1: + SetStdHandle(STD_OUTPUT_HANDLE, fileno_modes[handle2].hFile); + break; + case 2: + SetStdHandle(STD_ERROR_HANDLE, fileno_modes[handle2].hFile); + break; + case 3: + SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile); + break; + case 4: + SetStdHandle(STD_AUX_HANDLE, fileno_modes[handle2].hFile); + break; + } + return handle1; + } + else + { + __set_errno(EMFILE); // Is this the correct error no.? + return -1; + } +} + +int __fileno_setmode(int _fd, int _newmode) +{ + int m; + if ( _fd < 0 || _fd >= maxfno ) + { + __set_errno(EBADF); + return -1; + } + + m = fileno_modes[_fd].mode; + fileno_modes[_fd].mode = _newmode; + return m; +} + +int __fileno_getmode(int _fd) +{ + if ( _fd < 0 || _fd >= maxfno ) + { + __set_errno(EBADF); + return -1; + } + return fileno_modes[_fd].mode; + +} + +int __fileno_close(int _fd) +{ + if ( _fd < 0 || _fd >= maxfno ) + { + __set_errno(EBADF); + return -1; + } + + fileno_modes[_fd].fd = -1; + fileno_modes[_fd].hFile = (HANDLE)-1; + return 0; +} + +int _open_osfhandle (void *osfhandle, int flags ) +{ + return __fileno_alloc((HANDLE)osfhandle, flags); +} + +void *_get_osfhandle( int fileno ) +{ + return filehnd(fileno); +} + +void __fileno_init(void) +{ + ULONG count = 0, i; + HANDLE *pFile; + char* pmode; + STARTUPINFO StInfo; + + GetStartupInfoA(&StInfo); + + if (StInfo.lpReserved2 && StInfo.cbReserved2 >= sizeof(ULONG)) + { + count = *(ULONG*)StInfo.lpReserved2; +/* + if (sizeof(ULONG) + count * (sizeof(HANDLE) + sizeof(char)) != StInfo.cbReserved2) + { + count = 0; + } +*/ + } + maxfno = 255; + while(count >= maxfno) + maxfno += 255; + + fileno_modes = (fileno_modes_type*)malloc(sizeof(fileno_modes_type) * maxfno); + memset(fileno_modes, -1, sizeof(fileno_modes_type) * maxfno); + + if (count) + { + pFile = (HANDLE*)(StInfo.lpReserved2 + sizeof(ULONG) + count * sizeof(char)); + pmode = (char*)(StInfo.lpReserved2 + sizeof(ULONG)); + for (i = 0; i < count; i++) + { + if (*pFile != INVALID_HANDLE_VALUE) + { + fileno_modes[i].fd = i; + fileno_modes[i].mode = ((*pmode << 8) & (_O_TEXT|_O_BINARY)) | (*pmode & _O_ACCMODE); + fileno_modes[i].hFile = *pFile; + } + pFile++; + pmode++; + } + } + + if (fileno_modes[0].fd == -1) + { + fileno_modes[0].fd = 0; + fileno_modes[0].hFile = GetStdHandle(STD_INPUT_HANDLE); + fileno_modes[0].mode = _O_RDONLY|_O_TEXT; + } + if (fileno_modes[1].fd == -1) + { + fileno_modes[1].fd = 1; + fileno_modes[1].hFile = GetStdHandle(STD_OUTPUT_HANDLE); + fileno_modes[1].mode = _O_WRONLY|_O_TEXT; + } + if (fileno_modes[2].fd == -1) + { + fileno_modes[2].fd = 2; + fileno_modes[2].hFile = GetStdHandle(STD_ERROR_HANDLE); + fileno_modes[2].mode = _O_WRONLY|_O_TEXT; + } + if (fileno_modes[3].fd == -1) + { + fileno_modes[3].fd = 3; + fileno_modes[3].hFile = GetStdHandle(STD_AUX_HANDLE); + fileno_modes[3].mode = _O_WRONLY|_O_TEXT; + } + if (fileno_modes[4].fd == -1) + { + fileno_modes[4].fd = 4; + fileno_modes[4].hFile = GetStdHandle(STD_PRINTER_HANDLE); + fileno_modes[4].mode = _O_WRONLY|_O_TEXT; + } +} diff --git a/lib/msvcrt/io/pipe.c b/lib/msvcrt/io/pipe.c new file mode 100644 index 0000000..5d4d7fb --- /dev/null +++ b/lib/msvcrt/io/pipe.c @@ -0,0 +1,45 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/pipe.c + * PURPOSE: Creates a pipe + * PROGRAMER: DJ Delorie + * UPDATE HISTORY: + * 28/12/98: Appropriated for Reactos + */ +#include +#include +#include +#include + + +int _pipe(int _fildes[2], unsigned int size, int mode ) +{ + HANDLE hReadPipe, hWritePipe; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + + if (mode & O_NOINHERIT) + sa.bInheritHandle = FALSE; + + if (!CreatePipe(&hReadPipe,&hWritePipe,&sa,size)) + return -1; + + if ((_fildes[0] = __fileno_alloc(hReadPipe, mode)) < 0) + { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + __set_errno(EMFILE); + return -1; + } + + if ((_fildes[1] = __fileno_alloc(hWritePipe, mode)) < 0) + { + __fileno_close(_fildes[0]); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + __set_errno(EMFILE); + return -1; + } + return 0; +} diff --git a/lib/msvcrt/io/read.c b/lib/msvcrt/io/read.c new file mode 100644 index 0000000..f55875f --- /dev/null +++ b/lib/msvcrt/io/read.c @@ -0,0 +1,73 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/io/read.c + * PURPOSE: Reads a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/1998: Created + * 03/05/2002: made _read() non-greedy - it now returns as soon as + * any amount of data has been read. It's the expected + * behavior for line-buffered streams (KJK::Hyperion) + */ +#include +#include +#include + +#define NDEBUG +#include + +size_t _read(int _fd, void *_buf, size_t _nbyte) +{ + DWORD _rbyte = 0, nbyte = _nbyte; + char *bufp = (char*)_buf; + HANDLE hfile; + int istext, error; + + DPRINT("_read(fd %d, buf %x, nbyte %d)\n", _fd, _buf, _nbyte); + + /* null read */ + if(_nbyte == 0) + return 0; + + hfile = _get_osfhandle(_fd); + istext = __fileno_getmode(_fd) & O_TEXT; + + /* read data */ + if (!ReadFile(hfile, bufp, nbyte, &_rbyte, NULL)) + { + /* failure */ + error = GetLastError(); + if (error == ERROR_BROKEN_PIPE) + { + return 0; + } + return -1; + } + + /* text mode */ + if (_rbyte && istext) + { + int cr = 0; + DWORD count = _rbyte; + + /* repeat for all bytes in the buffer */ + for(; count; bufp++, count--) + { + /* carriage return */ + if (*bufp == '\r') + cr++; + /* shift characters back, to ignore carriage returns */ + else if (cr != 0) + *(bufp - cr) = *bufp; + + } + + /* ignore the carriage returns */ + _rbyte -= cr; + } + + DPRINT("%d\n", _rbyte); + return _rbyte; +} diff --git a/lib/msvcrt/io/setmode.c b/lib/msvcrt/io/setmode.c new file mode 100644 index 0000000..ca26cec --- /dev/null +++ b/lib/msvcrt/io/setmode.c @@ -0,0 +1,24 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/io/setmode.c + * PURPOSE: Sets the file translation mode + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + +#define NDEBUG +#include + + +int _setmode(int _fd, int _newmode) +{ + DPRINT("_setmod(fd %d, newmode %x)\n", _fd, _newmode); + return __fileno_setmode(_fd, _newmode); +} diff --git a/lib/msvcrt/io/sopen.c b/lib/msvcrt/io/sopen.c new file mode 100644 index 0000000..e98fa85 --- /dev/null +++ b/lib/msvcrt/io/sopen.c @@ -0,0 +1,12 @@ +#include + + +int _sopen(char *path, int access, int shflag, int mode) +{ + return _open((path), (access)|(shflag), (mode)); +} + +int _wsopen(wchar_t *path, int access, int shflag, int mode) +{ + return _wopen((path), (access)|(shflag), (mode)); +} diff --git a/lib/msvcrt/io/tell.c b/lib/msvcrt/io/tell.c new file mode 100644 index 0000000..3d7d95b --- /dev/null +++ b/lib/msvcrt/io/tell.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + + +off_t _tell(int _file) +{ + return _lseek(_file, 0, SEEK_CUR); +} + +__int64 _telli64(int _file) +{ + return _lseeki64(_file, 0, SEEK_CUR); +} diff --git a/lib/msvcrt/io/umask.c b/lib/msvcrt/io/umask.c new file mode 100644 index 0000000..4146b81 --- /dev/null +++ b/lib/msvcrt/io/umask.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +unsigned _unMode_dll = 022; + +unsigned _umask (unsigned unMode) +{ + unsigned old_mask = _unMode_dll; + _unMode_dll = unMode; + return old_mask; +} diff --git a/lib/msvcrt/io/unlink.c b/lib/msvcrt/io/unlink.c new file mode 100644 index 0000000..9165aac --- /dev/null +++ b/lib/msvcrt/io/unlink.c @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/io/unlink.c + * PURPOSE: Deletes a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +#define NDEBUG +#include + + +int _unlink(const char *filename) +{ + int result = 0; + DPRINT("_unlink('%s')\n", filename); + if (!DeleteFileA(filename)) + result = -1; + DPRINT("%d\n", result); + return result; +} + +int _wunlink(const wchar_t *filename) +{ + DPRINT("_wunlink('%S')\n", filename); + if (!DeleteFileW(filename)) + return -1; + return 0; +} diff --git a/lib/msvcrt/io/utime.c b/lib/msvcrt/io/utime.c new file mode 100644 index 0000000..7a5b037 --- /dev/null +++ b/lib/msvcrt/io/utime.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +int _utime(const char* filename, struct _utimbuf* buf) +{ + int fn; + int ret; + + fn = _open(filename, _O_RDWR); + if (fn == -1) + { + __set_errno(EBADF); + return -1; + } + ret = _futime(fn,buf); + if (_close(fn) < 0) + return -1; + return ret; +} + +int _wutime(const wchar_t* filename, struct _utimbuf* buf) +{ + int fn; + int ret; + + fn = _wopen(filename, _O_RDWR); + if (fn == -1) + { + __set_errno(EBADF); + return -1; + } + ret = _futime(fn,buf); + if (_close(fn) < 0) + return -1; + return ret; +} diff --git a/lib/msvcrt/io/write.c b/lib/msvcrt/io/write.c new file mode 100644 index 0000000..299d304 --- /dev/null +++ b/lib/msvcrt/io/write.c @@ -0,0 +1,88 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/io/write.c + * PURPOSE: Writes to a file + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include + +#define NDEBUG +#include + +#define BUFSIZE 4096 + +size_t _write(int _fd, const void *_buf, size_t _nbyte) +{ + char *tmp, *in, *out; + int count, result; + DWORD wbyte; + + DPRINT("_write(fd %d, buf %x, nbyte %d)\n", _fd, _buf, _nbyte); + if (__fileno_getmode(_fd) & O_TEXT) + { + result = _nbyte; + tmp = (char*) malloc(BUFSIZE); + if (tmp == NULL) + { + return -1; + } + count = BUFSIZE; + out = tmp; + in = (char*) _buf; + while (_nbyte--) + { + if (*in == 0x0a) + { + *out++ = 0x0d; + count--; + if (count == 0) + { + if (!WriteFile(_get_osfhandle(_fd), tmp, BUFSIZE, &wbyte, NULL)) + { + result = -1; + break; + } + if (wbyte < BUFSIZE) + { + result = in - (char*)_buf; + break; + } + count = BUFSIZE; + out = tmp; + } + } + *out++ = *in++; + count--; + if (count == 0 || _nbyte == 0) + { + if (!WriteFile(_get_osfhandle(_fd), tmp, BUFSIZE - count, &wbyte, NULL)) + { + result = -1; + break; + } + if (wbyte < BUFSIZE - count) + { + result = in - (char*)_buf; + break; + } + count = BUFSIZE; + out = tmp; + } + } + free(tmp); + return result; + } + else + { + if(!WriteFile(_get_osfhandle(_fd), _buf, _nbyte, &wbyte, NULL)) + { + return -1; + } + return wbyte; + } +} diff --git a/lib/msvcrt/locale/.cvsignore b/lib/msvcrt/locale/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/locale/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/locale/locale.c b/lib/msvcrt/locale/locale.c new file mode 100644 index 0000000..971c706 --- /dev/null +++ b/lib/msvcrt/locale/locale.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include + + +int _current_category; /* used by setlocale */ +const char *_current_locale; + +int parse_locale(char *locale, char *lang, char *country, char *code_page); + +char *setlocale(int category, const char *locale) +{ + char lang[100]; + char country[100]; + char code_page[100]; + parse_locale((char *)locale,lang,country,code_page); + + //printf("%s %s %s %s\n",locale,lang,country,code_page); + + + switch ( category ) + { + case LC_COLLATE: + break; + case LC_CTYPE: + break; + case LC_MONETARY: + break; + case LC_NUMERIC: + break; + case LC_TIME: + break; + case LC_ALL: + break; + default: + break; + } + + return "C"; + +} + +/* + +locale "lang[_country[.code_page]]" + | ".code_page" + | "" + | NULL + +*/ +int parse_locale(char *locale, char *lang, char *country, char *code_page) +{ + while ( *locale != 0 && *locale != '.' && *locale != '_' ) + { + *lang = *locale; + lang++; + locale++; + } + *lang = 0; + if ( *locale == '_' ) { + locale++; + while ( *locale != 0 && *locale != '.' ) + { + *country = *locale; + country++; + locale++; + } + } + *country = 0; + + + if ( *locale == '.' ) { + locale++; + while ( *locale != 0 && *locale != '.' ) + { + *code_page = *locale; + code_page++; + locale++; + } + } + + *code_page = 0; + return 0; +} + +const struct map_lcid2str { + short langid; + const char *langname; + const char *country; +} languages[]={ + {0x0409,"English", "United States"}, + {0x0809,"English", "United Kingdom"}, + {0x0000,"Unknown", "Unknown"} + +}; + +const struct map_cntr { + const char *abrev; + const char *country; +} abrev[] = { + {"britain", "united kingdom"}, + {"england", "united kingdom"}, + {"gbr", "united kingdom"}, + {"great britain", "united kingdom"}, + {"uk", "united kingdom"}, + {"united kingdom", "united kingdom"}, + {"united-kingdom", "united kingdom"}, + {"america", "united states" }, + {"united states", "united states"}, + {"united-states", "united states"}, + {"us", "united states"}, + {"usa" "united states"} +}; + + +struct lconv _lconv = { +".", // decimal_point +",", // thousands_sep +"", // grouping; +"DOL", // int_curr_symbol +"$", // currency_symbol +".", // mon_decimal_point +",", // mon_thousands_sep +"", // mon_grouping; +"+", // positive_sign +"-", // negative_sign +127, // int_frac_digits +127, // frac_digits +127, // p_cs_precedes +127, // p_sep_by_space +127, // n_cs_precedes +127, // n_sep_by_space +127, // p_sign_posn; +127 // n_sign_posn; +}; + +struct lconv *localeconv(void) +{ + return (struct lconv *) &_lconv; +} diff --git a/lib/msvcrt/math/.cvsignore b/lib/msvcrt/math/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/math/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/math/acos.c b/lib/msvcrt/math/acos.c new file mode 100644 index 0000000..9bde5e9 --- /dev/null +++ b/lib/msvcrt/math/acos.c @@ -0,0 +1,26 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double acos (double __x) +{ + return atan2 (sqrt (1.0 - __x * __x), __x); +} diff --git a/lib/msvcrt/math/adjust.c b/lib/msvcrt/math/adjust.c new file mode 100644 index 0000000..f27c825 --- /dev/null +++ b/lib/msvcrt/math/adjust.c @@ -0,0 +1,7 @@ +/* $Id$ + * + */ + +int _adjust_fdiv = 0; + +/* EOF */ diff --git a/lib/msvcrt/math/asin.c b/lib/msvcrt/math/asin.c new file mode 100644 index 0000000..5f912ba --- /dev/null +++ b/lib/msvcrt/math/asin.c @@ -0,0 +1,26 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double asin (double __x) +{ + return atan2 (__x, sqrt (1.0 - __x * __x)); +} diff --git a/lib/msvcrt/math/atan.c b/lib/msvcrt/math/atan.c new file mode 100644 index 0000000..d1df503 --- /dev/null +++ b/lib/msvcrt/math/atan.c @@ -0,0 +1,34 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double atan (double __x); + +double atan (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fpatan" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/atan2.c b/lib/msvcrt/math/atan2.c new file mode 100644 index 0000000..f430c27 --- /dev/null +++ b/lib/msvcrt/math/atan2.c @@ -0,0 +1,15 @@ + +#include + +double atan2 (double __y, double __x); + +double atan2 (double __y, double __x) +{ + register double __value; + __asm __volatile__ + ("fpatan\n\t" + "fld %%st(0)" + : "=t" (__value) : "0" (__x), "u" (__y)); + + return __value; +} diff --git a/lib/msvcrt/math/cabs.c b/lib/msvcrt/math/cabs.c new file mode 100644 index 0000000..73d4643 --- /dev/null +++ b/lib/msvcrt/math/cabs.c @@ -0,0 +1,11 @@ +#include + +double _cabs( struct _complex z ) +{ + return sqrt( z.x*z.x + z.y*z.y ); +// return hypot(z.x,z.y); +} + + + + diff --git a/lib/msvcrt/math/ceil.c b/lib/msvcrt/math/ceil.c new file mode 100644 index 0000000..34a1019 --- /dev/null +++ b/lib/msvcrt/math/ceil.c @@ -0,0 +1,15 @@ +#include + +double ceil (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} diff --git a/lib/msvcrt/math/cos.c b/lib/msvcrt/math/cos.c new file mode 100644 index 0000000..1753f59 --- /dev/null +++ b/lib/msvcrt/math/cos.c @@ -0,0 +1,13 @@ +#include + +double cos (double __x); + +double cos (double __x) +{ + register double __value; + __asm __volatile__ + ("fcos" + : "=t" (__value): "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/cosh.c b/lib/msvcrt/math/cosh.c new file mode 100644 index 0000000..1f89a0e --- /dev/null +++ b/lib/msvcrt/math/cosh.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double cosh(double x) +{ + const double ebig = exp(fabs(x)); + return (ebig + 1.0/ebig) / 2.0; +} diff --git a/lib/msvcrt/math/exp.c b/lib/msvcrt/math/exp.c new file mode 100644 index 0000000..fb074fb --- /dev/null +++ b/lib/msvcrt/math/exp.c @@ -0,0 +1,43 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double exp (double __x); + +double exp (double __x) +{ + register double __value, __exponent; + __asm __volatile__ + ("fldl2e # e^x = 2^(x * log2(e))\n\t" + "fmul %%st(1) # x * log2(e)\n\t" + "fst %%st(1)\n\t" + "frndint # int(x * log2(e))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(x * log2(e))\n\t" + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__x)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} diff --git a/lib/msvcrt/math/fabs.c b/lib/msvcrt/math/fabs.c new file mode 100644 index 0000000..2e1587a --- /dev/null +++ b/lib/msvcrt/math/fabs.c @@ -0,0 +1,33 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double fabs (double __x); + +double fabs (double __x) +{ + register double __value; + __asm __volatile__ + ("fabs" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/floor.c b/lib/msvcrt/math/floor.c new file mode 100644 index 0000000..3e56781 --- /dev/null +++ b/lib/msvcrt/math/floor.c @@ -0,0 +1,37 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double floor (double __x); + +double floor (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} diff --git a/lib/msvcrt/math/fmod.c b/lib/msvcrt/math/fmod.c new file mode 100644 index 0000000..823fc00 --- /dev/null +++ b/lib/msvcrt/math/fmod.c @@ -0,0 +1,36 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double fmod (double __x, double __y); + +double fmod (double __x, double __y) +{ + register double __value; + __asm __volatile__ + ("1: fprem\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b" + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); + + return __value; +} diff --git a/lib/msvcrt/math/frexp.c b/lib/msvcrt/math/frexp.c new file mode 100644 index 0000000..27de8a3 --- /dev/null +++ b/lib/msvcrt/math/frexp.c @@ -0,0 +1,19 @@ +#include +#include +#include + +double +frexp(double __x, int *exptr) +{ + double_t *x = (double_t *)&__x; + + if (exptr != NULL) + *exptr = x->exponent - 0x3FE; + + x->exponent = 0x3FE; + + return __x; +} + + + diff --git a/lib/msvcrt/math/ftol.c b/lib/msvcrt/math/ftol.c new file mode 100644 index 0000000..dfa3346 --- /dev/null +++ b/lib/msvcrt/math/ftol.c @@ -0,0 +1,6 @@ +#include + +long _ftol(double fl) +{ + return (long)fl; +} diff --git a/lib/msvcrt/math/huge_val.c b/lib/msvcrt/math/huge_val.c new file mode 100644 index 0000000..aaa50d0 --- /dev/null +++ b/lib/msvcrt/math/huge_val.c @@ -0,0 +1,6 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +#undef _HUGE +double_t _HUGE = { 0x00000, 0x00000, 0x7ff, 0x0 }; diff --git a/lib/msvcrt/math/hypot.c b/lib/msvcrt/math/hypot.c new file mode 100644 index 0000000..9ca52e3 --- /dev/null +++ b/lib/msvcrt/math/hypot.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* + * hypot() function for DJGPP. + * + * hypot() computes sqrt(x^2 + y^2). The problem with the obvious + * naive implementation is that it might fail for very large or + * very small arguments. For instance, for large x or y the result + * might overflow even if the value of the function should not, + * because squaring a large number might trigger an overflow. For + * very small numbers, their square might underflow and will be + * silently replaced by zero; this won't cause an exception, but might + * have an adverse effect on the accuracy of the result. + * + * This implementation tries to avoid the above pitfals, without + * inflicting too much of a performance hit. + * + */ + +#include +#include +#include + +/* Approximate square roots of DBL_MAX and DBL_MIN. Numbers + between these two shouldn't neither overflow nor underflow + when squared. */ +#define __SQRT_DBL_MAX 1.3e+154 +#define __SQRT_DBL_MIN 2.3e-162 + +double +_hypot(double x, double y) +{ + double abig = fabs(x), asmall = fabs(y); + double ratio; + + /* Make abig = max(|x|, |y|), asmall = min(|x|, |y|). */ + if (abig < asmall) + { + double temp = abig; + + abig = asmall; + asmall = temp; + } + + /* Trivial case. */ + if (asmall == 0.) + return abig; + + /* Scale the numbers as much as possible by using its ratio. + For example, if both ABIG and ASMALL are VERY small, then + X^2 + Y^2 might be VERY inaccurate due to loss of + significant digits. Dividing ASMALL by ABIG scales them + to a certain degree, so that accuracy is better. */ + + if ((ratio = asmall / abig) > __SQRT_DBL_MIN && abig < __SQRT_DBL_MAX) + return abig * sqrt(1.0 + ratio*ratio); + else + { + /* Slower but safer algorithm due to Moler and Morrison. Never + produces any intermediate result greater than roughly the + larger of X and Y. Should converge to machine-precision + accuracy in 3 iterations. */ + + double r = ratio*ratio, t, s, p = abig, q = asmall; + + do { + t = 4. + r; + if (t == 4.) + break; + s = r / t; + p += 2. * s * p; + q *= s; + r = (q / p) * (q / p); + } while (1); + + return p; + } +} + +#ifdef TEST + +#include + +int +main(void) +{ + printf("hypot(3, 4) =\t\t\t %25.17e\n", _hypot(3., 4.)); + printf("hypot(3*10^150, 4*10^150) =\t %25.17g\n", _hypot(3.e+150, 4.e+150)); + printf("hypot(3*10^306, 4*10^306) =\t %25.17g\n", _hypot(3.e+306, 4.e+306)); + printf("hypot(3*10^-320, 4*10^-320) =\t %25.17g\n",_hypot(3.e-320, 4.e-320)); + printf("hypot(0.7*DBL_MAX, 0.7*DBL_MAX) =%25.17g\n",_hypot(0.7*DBL_MAX, 0.7*DBL_MAX)); + printf("hypot(DBL_MAX, 1.0) =\t\t %25.17g\n", _hypot(DBL_MAX, 1.0)); + printf("hypot(1.0, DBL_MAX) =\t\t %25.17g\n", _hypot(1.0, DBL_MAX)); + printf("hypot(0.0, DBL_MAX) =\t\t %25.17g\n", _hypot(0.0, DBL_MAX)); + + return 0; +} + +#endif diff --git a/lib/msvcrt/math/j0_y0.c b/lib/msvcrt/math/j0_y0.c new file mode 100644 index 0000000..db89a92 --- /dev/null +++ b/lib/msvcrt/math/j0_y0.c @@ -0,0 +1,12 @@ +#include + +double _j0(double x) +{ + return x; +} + +double _y0(double x) +{ + return x; +} + diff --git a/lib/msvcrt/math/j1_y1.c b/lib/msvcrt/math/j1_y1.c new file mode 100644 index 0000000..fa0f618 --- /dev/null +++ b/lib/msvcrt/math/j1_y1.c @@ -0,0 +1,11 @@ +#include + +double _j1(double x) +{ + return x; +} + +double _y1(double x) +{ + return x; +} diff --git a/lib/msvcrt/math/jn_yn.c b/lib/msvcrt/math/jn_yn.c new file mode 100644 index 0000000..b641a81 --- /dev/null +++ b/lib/msvcrt/math/jn_yn.c @@ -0,0 +1,11 @@ +#include + +double _jn(int n, double x) +{ + return x; +} + +double _yn(int n, double x) +{ + return x; +} diff --git a/lib/msvcrt/math/ldexp.c b/lib/msvcrt/math/ldexp.c new file mode 100644 index 0000000..65e9e25 --- /dev/null +++ b/lib/msvcrt/math/ldexp.c @@ -0,0 +1,33 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double ldexp (double __x, int __y); + +double ldexp (double __x, int __y) +{ + register double __value; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__x), "u" ((double) __y)); + + return __value; +} diff --git a/lib/msvcrt/math/log.c b/lib/msvcrt/math/log.c new file mode 100644 index 0000000..e9b7cb6 --- /dev/null +++ b/lib/msvcrt/math/log.c @@ -0,0 +1,35 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double log (double __x); + +double log (double __x) +{ + register double __value; + __asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/log10.c b/lib/msvcrt/math/log10.c new file mode 100644 index 0000000..e198837 --- /dev/null +++ b/lib/msvcrt/math/log10.c @@ -0,0 +1,35 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double log10 (double __x); + +double log10 (double __x) +{ + register double __value; + __asm __volatile__ + ("fldlg2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/modf.c b/lib/msvcrt/math/modf.c new file mode 100644 index 0000000..336a7d7 --- /dev/null +++ b/lib/msvcrt/math/modf.c @@ -0,0 +1,132 @@ +/* @(#)s_modf.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +#include +#include + + + +//static const double one = 1.0; + +double modf(double __x, double *__i) +{ + double_t * x = (double_t *)&__x; + double_t * iptr = ( double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3ff; /* exponent of x */ + if(j0<20) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0; + iptr->sign = x->sign; + return __x; + } else { + + if ( x->mantissah == 0 && x->mantissal == 0 ) { + *__i = __x; + return 0.0; + } + + i = (0x000fffff)>>j0; + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&(~i); + iptr->mantissal = 0; + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } + } else if (j0>51) { /* no fraction part */ + *__i = __x; + if ( _isnan(__x) || _isinf(__x) ) + return __x; + + __x = 0.0; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + i = ((unsigned)(0xffffffff))>>(j0-20); + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + if ( __x == *__i ) { + __x = 0.0; + x->sign = iptr->sign; + return __x; + } + return __x - *__i; + } +} + + +long double modfl(long double __x, long double *__i) +{ + long_double_t * x = (long_double_t *)&__x; + long_double_t * iptr = (long_double_t *)__i; + + int j0; + unsigned int i; + j0 = x->exponent - 0x3fff; /* exponent of x */ + + if(j0<32) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + *__i = 0.0L; + iptr->sign = x->sign; + return __x; + } else { + + i = ((unsigned int)(0xffffffff))>>(j0+1); + if ( x->mantissal == 0 && (x->mantissal & i) == 0 ) { + *__i = __x; + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah&((~i)); + iptr->mantissal = 0; + + return __x - *__i; + } + } else if (j0>63) { /* no fraction part */ + *__i = __x; + if ( _isnanl(__x) || _isinfl(__x) ) + return __x; + + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } else { /* fraction part in low x */ + + i = ((unsigned int)(0xffffffff))>>(j0-32); + if ( x->mantissal == 0 ) { + *__i = __x; + __x = 0.0L; + x->sign = iptr->sign; + return __x; + } + iptr->sign = x->sign; + iptr->exponent = x->exponent; + iptr->mantissah = x->mantissah; + iptr->mantissal = x->mantissal&(~i); + + return __x - *__i; + } +} diff --git a/lib/msvcrt/math/pow.c b/lib/msvcrt/math/pow.c new file mode 100644 index 0000000..266fc03 --- /dev/null +++ b/lib/msvcrt/math/pow.c @@ -0,0 +1,86 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double pow (double __x, double __y); + +double __log2 (double __x); + +double __log2 (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double pow (double __x, double __y) +{ + register double __value, __exponent; + long __p = (long) __y; + + if (__x == 0.0 && __y > 0.0) + return 0.0; + if (__y == (double) __p) + { + double __r = 1.0; + if (__p == 0) + return 1.0; + if (__p < 0) + { + __p = -__p; + __x = 1.0 / __x; + } + while (1) + { + if (__p & 1) + __r *= __x; + __p >>= 1; + if (__p == 0) + return __r; + __x *= __x; + } + /* NOTREACHED */ + } + __asm __volatile__ + ("fmul %%st(1) # y * log2(x)\n\t" + "fst %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +long double powl (long double __x,long double __y) +{ + return pow(__x,__y/2)*pow(__x,__y/2); +} diff --git a/lib/msvcrt/math/sin.c b/lib/msvcrt/math/sin.c new file mode 100644 index 0000000..97e58a3 --- /dev/null +++ b/lib/msvcrt/math/sin.c @@ -0,0 +1,33 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double sin (double __x); + +double sin (double __x) +{ + register double __value; + __asm __volatile__ + ("fsin" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/sinh.c b/lib/msvcrt/math/sinh.c new file mode 100644 index 0000000..5a0b2be --- /dev/null +++ b/lib/msvcrt/math/sinh.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double sinh(double x) +{ + if(x >= 0.0) + { + const double epos = exp(x); + return (epos - 1.0/epos) / 2.0; + } + else + { + const double eneg = exp(-x); + return (1.0/eneg - eneg) / 2.0; + } +} diff --git a/lib/msvcrt/math/sqrt.c b/lib/msvcrt/math/sqrt.c new file mode 100644 index 0000000..47e5e5f --- /dev/null +++ b/lib/msvcrt/math/sqrt.c @@ -0,0 +1,32 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ +#include + +double sqrt (double __x); + +double sqrt (double __x) +{ + register double __value; + __asm __volatile__ + ("fsqrt" + : "=t" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/stubs.c b/lib/msvcrt/math/stubs.c new file mode 100644 index 0000000..a43b9fc --- /dev/null +++ b/lib/msvcrt/math/stubs.c @@ -0,0 +1,84 @@ +#include + +double _CIsin (double x); +double _CIcos (double x); +double _CItan (double x); +double _CIsinh (double x); +double _CIcosh (double x); +double _CItanh (double x); +double _CIasin (double x); +double _CIacos (double x); +double _CIatan (double x); +double _CIatan2 (double y, double x); +double _CIexp (double x); +double _CIlog (double x); +double _CIlog10 (double x); +double _CIpow (double x, double y); +double _CIsqrt (double x); +double _CIfmod (double x, double y); + + +double _CIsin (double x) +{ + return sin(x); +} +double _CIcos (double x) +{ + return cos(x); +} +double _CItan (double x) +{ + return tan(x); +} +double _CIsinh (double x) +{ + return sinh(x); +} +double _CIcosh (double x) +{ + return cosh(x); +} +double _CItanh (double x) +{ + return tanh(x); +} +double _CIasin (double x) +{ + return asin(x); +} +double _CIacos (double x) +{ + return acos(x); +} +double _CIatan (double x) +{ + return atan(x); +} +double _CIatan2 (double y, double x) +{ + return atan2(y,x); +} +double _CIexp (double x) +{ + return exp(x); +} +double _CIlog (double x) +{ + return log(x); +} +double _CIlog10 (double x) +{ + return log10(x); +} +double _CIpow (double x, double y) +{ + return pow(x,y); +} +double _CIsqrt (double x) +{ + return sqrt(x); +} +double _CIfmod (double x, double y) +{ + return fmod(x,y); +} diff --git a/lib/msvcrt/math/tan.c b/lib/msvcrt/math/tan.c new file mode 100644 index 0000000..baa92c4 --- /dev/null +++ b/lib/msvcrt/math/tan.c @@ -0,0 +1,34 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +double tan (double __x); + +double tan (double __x) +{ + register double __value; + register double __value2 __attribute__ ((unused)); + __asm __volatile__ + ("fptan" + : "=t" (__value2), "=u" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/msvcrt/math/tanh.c b/lib/msvcrt/math/tanh.c new file mode 100644 index 0000000..da1eabb --- /dev/null +++ b/lib/msvcrt/math/tanh.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +double tanh(double x) +{ + if (x > 50) + return 1; + else if (x < -50) + return -1; + else + { + const double ebig = exp(x); + const double esmall = 1.0/ebig; + return (ebig - esmall) / (ebig + esmall); + } +} diff --git a/lib/msvcrt/mbstring/.cvsignore b/lib/msvcrt/mbstring/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/mbstring/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/mbstring/hanzen.c b/lib/msvcrt/mbstring/hanzen.c new file mode 100644 index 0000000..f640d4e --- /dev/null +++ b/lib/msvcrt/mbstring/hanzen.c @@ -0,0 +1,101 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Multibyte conversion routines formerly called hantozen and zentohan + * PROGRAMER: Boudewijn Dekker, Taiji Yamada + * UPDATE HISTORY: + Modified from Taiji Yamada japanese code system utilities + * 12/04/99: Created + */ + +#include + +static unsigned short han_to_zen_ascii_table[0x5f] = { + 0x8140, 0x8149, 0x8168, 0x8194, 0x8190, 0x8193, 0x8195, 0x8166, + 0x8169, 0x816a, 0x8196, 0x817b, 0x8143, 0x817c, 0x8144, 0x815e, + 0x824f, 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256, + 0x8257, 0x8258, 0x8146, 0x8147, 0x8183, 0x8181, 0x8184, 0x8148, + 0x8197, 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, 0x8265, 0x8266, + 0x8267, 0x8268, 0x8269, 0x826a, 0x826b, 0x826c, 0x826d, 0x826e, + 0x826f, 0x8270, 0x8271, 0x8272, 0x8273, 0x8274, 0x8275, 0x8276, + 0x8277, 0x8278, 0x8279, 0x816d, 0x818f, 0x816e, 0x814f, 0x8151, + 0x8165, 0x8281, 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287, + 0x8288, 0x8289, 0x828a, 0x828b, 0x828c, 0x828d, 0x828e, 0x828f, + 0x8290, 0x8291, 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297, + 0x8298, 0x8299, 0x829a, 0x816f, 0x8162, 0x8170, 0x8150 +}; +static unsigned short han_to_zen_kana_table[0x40] = { + 0x8140, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x8392, 0x8340, + 0x8342, 0x8344, 0x8346, 0x8348, 0x8383, 0x8385, 0x8387, 0x8362, + 0x815b, 0x8341, 0x8343, 0x8345, 0x8347, 0x8349, 0x834a, 0x834c, + 0x834e, 0x8350, 0x8352, 0x8354, 0x8356, 0x8358, 0x835a, 0x835c, + 0x835e, 0x8360, 0x8363, 0x8365, 0x8367, 0x8369, 0x836a, 0x836b, + 0x836c, 0x836d, 0x836e, 0x8371, 0x8374, 0x8377, 0x837a, 0x837d, + 0x837e, 0x8380, 0x8381, 0x8382, 0x8384, 0x8386, 0x8388, 0x8389, + 0x838a, 0x838b, 0x838c, 0x838d, 0x838f, 0x8393, 0x814a, 0x814b +}; +static unsigned char zen_to_han_kana_table[0x8396-0x8340+1] = { + 0xa7, 0xb1, 0xa8, 0xb2, 0xa9, 0xb3, 0xaa, 0xb4, + 0xab, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, + 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, + 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xbf, 0xc0, 0xc0, + 0xc1, 0xc1, 0xaf, 0xc2, 0xc2, 0xc3, 0xc3, 0xc4, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xca, + 0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcd, + 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xcf, 0xd0, 0, + 0xd1, 0xd2, 0xd3, 0xac, 0xd4, 0xad, 0xd5, 0xae, + 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdc, + 0xb2, 0xb4, 0xa6, 0xdd, 0xb3, 0xb6, 0xb9 +}; +#define ZTOH_SYMBOLS 9 +static unsigned short zen_to_han_symbol_table_1[ZTOH_SYMBOLS] = { + 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x815b, 0x814a, 0x814b +}; +static unsigned char zen_to_han_symbol_table_2[ZTOH_SYMBOLS] = { + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xb0, 0xde, 0xdf +}; +#define ISKANA(c) ((c) >= 0xa1 && (c) <= 0xdf) +#define JISHIRA(c) ((c) >= 0x829f && (c) <= 0x82f1) +#define JISKANA(c) ((c) >= 0x8340 && (c) <= 0x8396 && (c) != 0x837f) +#define JTOKANA(c) ((c) <= 0x82dd ? (c) + 0xa1 : (c) + 0xa2) + + +unsigned short _mbbtombc(unsigned short c) +{ + if (c >= 0x20 && c <= 0x7e) { + return han_to_zen_ascii_table[c - 0x20]; + } else if (ISKANA(c)) { + return han_to_zen_kana_table[c - 0xa0]; + } + return c; +} + + +unsigned short _mbctombb(unsigned short c) +{ + int i; + unsigned short *p; + + if (JISKANA(c)) { + return zen_to_han_kana_table[c - 0x8340]; + } else if (JISHIRA(c)) { + c = JTOKANA(c); + return zen_to_han_kana_table[c - 0x8340]; + } else if (c <= 0x8396) { + for (i = 0x20, p = han_to_zen_ascii_table; i <= 0x7e; i++, p++) { + if (*p == c) { + return i; + } + } + for (i = 0; i < ZTOH_SYMBOLS; i++) { + if (zen_to_han_symbol_table_1[i] == c) { + return zen_to_han_symbol_table_2[i]; + } + } + } + return c; +} + + + diff --git a/lib/msvcrt/mbstring/ischira.c b/lib/msvcrt/mbstring/ischira.c new file mode 100644 index 0000000..b27bf6e --- /dev/null +++ b/lib/msvcrt/mbstring/ischira.c @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/ischira.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +int _ismbchira( unsigned int c ) +{ + return ((c>=0x829F) && (c<=0x82F1)); +} + +int _ismbckata( unsigned int c ) +{ + return ((c>=0x8340) && (c<=0x8396)); +} + +unsigned int _mbctohira( unsigned int c ) +{ + return c; +} + +unsigned int _mbctokata( unsigned int c ) +{ + return c; +} + diff --git a/lib/msvcrt/mbstring/iskana.c b/lib/msvcrt/mbstring/iskana.c new file mode 100644 index 0000000..f7d028b --- /dev/null +++ b/lib/msvcrt/mbstring/iskana.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Checks for kana character + * PROGRAMER: Boudewijn Dekker, Taiji Yamada + * UPDATE HISTORY: + Modified from Taiji Yamada japanese code system utilities + * 12/04/99: Created + */ +#include +#include + +int _ismbbkana(unsigned char c) +{ + return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_M|_KNJ_P)); +} diff --git a/lib/msvcrt/mbstring/iskmoji.c b/lib/msvcrt/mbstring/iskmoji.c new file mode 100644 index 0000000..a8cc174 --- /dev/null +++ b/lib/msvcrt/mbstring/iskmoji.c @@ -0,0 +1,6 @@ +#include + +int _ismbbkalpha(unsigned char c) +{ + return (0xA7 <= c <= 0xDF); +} \ No newline at end of file diff --git a/lib/msvcrt/mbstring/iskpun.c b/lib/msvcrt/mbstring/iskpun.c new file mode 100644 index 0000000..fc04c8d --- /dev/null +++ b/lib/msvcrt/mbstring/iskpun.c @@ -0,0 +1,15 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/iskpun.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include + +int _ismbbkpunct( unsigned int c ) +{ + return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_P)); +} diff --git a/lib/msvcrt/mbstring/islead.c b/lib/msvcrt/mbstring/islead.c new file mode 100644 index 0000000..08ff0a6 --- /dev/null +++ b/lib/msvcrt/mbstring/islead.c @@ -0,0 +1,8 @@ +#include +#include + +int isleadbyte(char *mbstr) +{ + return 0; + //return IsDBCSLeadByteEx(0,*c); +} diff --git a/lib/msvcrt/mbstring/islwr.c b/lib/msvcrt/mbstring/islwr.c new file mode 100644 index 0000000..01c9cf4 --- /dev/null +++ b/lib/msvcrt/mbstring/islwr.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +// code page 952 only +int _ismbclower( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + if ( c >= 0x829A && c<= 0x829A ) + return 1; + } + + return islower(c); +} diff --git a/lib/msvcrt/mbstring/ismbal.c b/lib/msvcrt/mbstring/ismbal.c new file mode 100644 index 0000000..ee59df2 --- /dev/null +++ b/lib/msvcrt/mbstring/ismbal.c @@ -0,0 +1,17 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Checks for alphabetic multibyte character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include + +int _ismbbalpha(unsigned char c) +{ + return (isalpha(c) || _ismbbkalnum(c)); +} + diff --git a/lib/msvcrt/mbstring/ismbaln.c b/lib/msvcrt/mbstring/ismbaln.c new file mode 100644 index 0000000..a72f4d8 --- /dev/null +++ b/lib/msvcrt/mbstring/ismbaln.c @@ -0,0 +1,9 @@ +#include +#include + + +int _ismbbalnum(unsigned char c) +{ + return (isalnum(c) || _ismbbkalnum(c)); +} + diff --git a/lib/msvcrt/mbstring/ismbc.c b/lib/msvcrt/mbstring/ismbc.c new file mode 100644 index 0000000..6c2ece2 --- /dev/null +++ b/lib/msvcrt/mbstring/ismbc.c @@ -0,0 +1,105 @@ +#include + +int _ismbbalpha(unsigned char c); +int _ismbbalnum(unsigned char c); + +int _ismbcalnum( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return _ismbbalnum(c); + + return 0; +} + +int _ismbcalpha( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return _ismbbalpha(c); + + return 0; +} + +int _ismbcdigit( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} + +int _ismbcprint( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} + +int _ismbcsymbol( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} + +int _ismbcspace( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + // true multibyte character + return 0; + } + else + return 0; +// return _ismbbdigit(c); + + return 0; +} +int _ismbclegal(unsigned int c) +{ + if ((c & 0xFF00) != 0) { + return _ismbblead(c>>8) && _ismbbtrail(c&0xFF); + } + else + return _ismbbtrail(c&0xFF); + + return 0; +} + +int _ismbcl0(unsigned int c) +{ + return 0; +} + +int _ismbcl1(unsigned int c) +{ + return 0; +} + +int _ismbcl2(unsigned int c) +{ + return 0; +} diff --git a/lib/msvcrt/mbstring/ismbgra.c b/lib/msvcrt/mbstring/ismbgra.c new file mode 100644 index 0000000..d86781f --- /dev/null +++ b/lib/msvcrt/mbstring/ismbgra.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int _ismbbgraph(unsigned char c) +{ + return (isgraph(c) || _ismbbkana(c)); +} diff --git a/lib/msvcrt/mbstring/ismbkaln.c b/lib/msvcrt/mbstring/ismbkaln.c new file mode 100644 index 0000000..446a598 --- /dev/null +++ b/lib/msvcrt/mbstring/ismbkaln.c @@ -0,0 +1,16 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/iskpun.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include + +int _ismbbkalnum( unsigned int c ) +{ + return ((_jctype+1)[(unsigned char)(c)] & (_KNJ_P)); +} diff --git a/lib/msvcrt/mbstring/ismblead.c b/lib/msvcrt/mbstring/ismblead.c new file mode 100644 index 0000000..f15f3ec --- /dev/null +++ b/lib/msvcrt/mbstring/ismblead.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/ismblead.c + * PURPOSE: Checks for a lead byte + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * Modified from Taiji Yamada japanese code system utilities + * 12/04/99: Created + */ + +#include +#include +#include + +size_t _mbclen2(const unsigned int s); + +char _jctype[257] = { +/*-1*/ ___, +/*0x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*1x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*2x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*3x*/ ___,___,___,___,___,___,___,___,___,___,___,___,___,___,___,___, +/*4x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, +/*5x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, +/*6x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2, +/*7x*/ __2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,__2,___, +/*8x*/ __2,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, +/*9x*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, +/*Ax*/ __2,_P2,_P2,_P2,_P2,_P2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Bx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Cx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Dx*/ _M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2,_M2, +/*Ex*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12, +/*Fx*/ _12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,_12,___,___,___ +}; + +char *_mbctype = _jctype; +int _ismbblead(unsigned int c) +{ + return ((_jctype+1)[(unsigned char)(c)] & _KNJ_1); +} +//int _ismbblead(unsigned int byte) +//{ +// +// return (int)IsDBCSLeadByte(byte) +//} + +int _ismbslead( const unsigned char *str, const unsigned char *t) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && s != t) + { + + s+= _mbclen2(*s); + } + return _ismbblead( *s); +} + diff --git a/lib/msvcrt/mbstring/ismbpri.c b/lib/msvcrt/mbstring/ismbpri.c new file mode 100644 index 0000000..c6d9bf6 --- /dev/null +++ b/lib/msvcrt/mbstring/ismbpri.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int _ismbbprint(unsigned char c) +{ + return (isprint(c) || _ismbbkana(c)); +} diff --git a/lib/msvcrt/mbstring/ismbpun.c b/lib/msvcrt/mbstring/ismbpun.c new file mode 100644 index 0000000..171b1a4 --- /dev/null +++ b/lib/msvcrt/mbstring/ismbpun.c @@ -0,0 +1,14 @@ + + //iskana() :(0xA1 <= c <= 0xDF) + //iskpun() :(0xA1 <= c <= 0xA6) + //iskmoji() :(0xA7 <= c <= 0xDF) +#include +#include +#include + +int _ismbbpunct(unsigned char c) +{ +// (0xA1 <= c <= 0xA6) + return (ispunct(c) || _ismbbkana(c)); +} + diff --git a/lib/msvcrt/mbstring/ismbtrl.c b/lib/msvcrt/mbstring/ismbtrl.c new file mode 100644 index 0000000..aeeff7e --- /dev/null +++ b/lib/msvcrt/mbstring/ismbtrl.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/ismbtrail.c + * PURPOSE: Checks for a trailing byte + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +size_t _mbclen2(const unsigned int s); + +// iskanji2() : (0x40 <= c <= 0x7E 0x80 <= c <= 0xFC) + +int _ismbbtrail(unsigned int c) +{ + return ((_jctype+1)[(unsigned char)(c)] & _KNJ_2); +} + +//int _ismbbtrail( unsigned int b) +//{ +// return ((b >= 0x40 && b <= 0x7e ) || (b >= 0x80 && b <= 0xfc ) ); +//} + + +int _ismbstrail( const unsigned char *str, const unsigned char *t) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && s != t) + { + + s+= _mbclen2(*s); + } + + return _ismbbtrail(*s); +} diff --git a/lib/msvcrt/mbstring/isuppr.c b/lib/msvcrt/mbstring/isuppr.c new file mode 100644 index 0000000..110b9a8 --- /dev/null +++ b/lib/msvcrt/mbstring/isuppr.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +// code page 952 only +int _ismbcupper( unsigned int c ) +{ + if ((c & 0xFF00) != 0) { + if ( c >= 0x8260 && c<= 0x8279 ) + return 1; + } + + return isupper(c); +} diff --git a/lib/msvcrt/mbstring/jistojms.c b/lib/msvcrt/mbstring/jistojms.c new file mode 100644 index 0000000..c05d80e --- /dev/null +++ b/lib/msvcrt/mbstring/jistojms.c @@ -0,0 +1,24 @@ +#include + +unsigned short _mbcjistojms(unsigned short c) +{ + int c1, c2; + + c2 = (unsigned char)c; + c1 = c >> 8; + if (c1 >= 0x21 && c1 <= 0x7e && c2 >= 0x21 && c2 <= 0x7e) { + if (c1 & 0x01) { + c2 += 0x1f; + if (c2 >= 0x7f) + c2 ++; + } else { + c2 += 0x7e; + } + c1 += 0xe1; + c1 >>= 1; + if (c1 >= 0xa0) + c1 += 0x40; + return ((c1 << 8) | c2); + } + return 0; +} diff --git a/lib/msvcrt/mbstring/jmstojis.c b/lib/msvcrt/mbstring/jmstojis.c new file mode 100644 index 0000000..62c948d --- /dev/null +++ b/lib/msvcrt/mbstring/jmstojis.c @@ -0,0 +1,25 @@ +#include + +unsigned short _mbcjmstojis(unsigned short c) +{ + int c1, c2; + + c2 = (unsigned char)c; + c1 = c >> 8; + if (c1 < 0xf0 && _ismbblead(c1) && _ismbbtrail(c2)) { + if (c1 >= 0xe0) + c1 -= 0x40; + c1 -= 0x70; + c1 <<= 1; + if (c2 < 0x9f) { + c1 --; + c2 -= 0x1f; + if (c2 >= (0x80-0x1f)) + c2 --; + } else { + c2 -= 0x7e; + } + return ((c1 << 8) | c2); + } + return 0; +} diff --git a/lib/msvcrt/mbstring/mbbtype.c b/lib/msvcrt/mbstring/mbbtype.c new file mode 100644 index 0000000..85e605a --- /dev/null +++ b/lib/msvcrt/mbstring/mbbtype.c @@ -0,0 +1,48 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbbtype.c + * PURPOSE: Determines the type of a multibyte character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +int _mbbtype(unsigned char c , int type) +{ + if (type == 1) + { + if ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc)) + { + return _MBC_TRAIL; + } + else if ((c >= 0x20 && c >= 0x7E) || (c >= 0xA1 && c <= 0xDF) || + (c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xFC)) + return _MBC_ILLEGAL; + else + return 0; + } + else + { + if ((c >= 0x20 && c <= 0x7E) || (c >= 0xA1 && c <= 0xDF )) + return _MBC_SINGLE; + else if ((c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xFC)) + return _MBC_LEAD; + else if ((c >= 0x20 && c >= 0x7E) || (c >= 0xA1 && c <= 0xDF) || + (c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xFC)) + return _MBC_ILLEGAL; + else + return 0; + } + return 0; +} + +int _mbsbtype( const unsigned char *str, size_t n ) +{ + if (str == NULL) + return -1; + return _mbbtype(*(str+n),1); +} diff --git a/lib/msvcrt/mbstring/mbccpy.c b/lib/msvcrt/mbstring/mbccpy.c new file mode 100644 index 0000000..6cf434e --- /dev/null +++ b/lib/msvcrt/mbstring/mbccpy.c @@ -0,0 +1,12 @@ +#include +#include + +size_t _mbclen2(const unsigned int s); + +void _mbccpy(unsigned char *dst, const unsigned char *src) +{ + if (!_ismbblead(*src) ) + return; + + memcpy(dst,src,_mbclen2(*src)); +} diff --git a/lib/msvcrt/mbstring/mbclen.c b/lib/msvcrt/mbstring/mbclen.c new file mode 100644 index 0000000..389aa07 --- /dev/null +++ b/lib/msvcrt/mbstring/mbclen.c @@ -0,0 +1,30 @@ + +#include +#include + + +size_t _mbclen(const unsigned char *s) +{ + return (_ismbblead(*s>>8) && _ismbbtrail(*s&0x00FF)) ? 2 : 1; +} + +size_t _mbclen2(const unsigned int s) +{ + return (_ismbblead(s>>8) && _ismbbtrail(s&0x00FF)) ? 2 : 1; +} + +// assume MB_CUR_MAX == 2 +int mblen( const char *s, size_t count ) +{ + size_t l; + if ( s == NULL ) + return 0; + + l = _mbclen(s); + if ( l < count ) + return -1; + return l; +} + + + diff --git a/lib/msvcrt/mbstring/mbscat.c b/lib/msvcrt/mbstring/mbscat.c new file mode 100644 index 0000000..dc6a982 --- /dev/null +++ b/lib/msvcrt/mbstring/mbscat.c @@ -0,0 +1,6 @@ +#include + +unsigned char * _mbscat(unsigned char *dst, const unsigned char *src) +{ + return strcat(dst,src); +} diff --git a/lib/msvcrt/mbstring/mbschr.c b/lib/msvcrt/mbstring/mbschr.c new file mode 100644 index 0000000..70c4c67 --- /dev/null +++ b/lib/msvcrt/mbstring/mbschr.c @@ -0,0 +1,6 @@ +#include + +unsigned char * _mbschr(const unsigned char *str, unsigned int c) +{ + return strchr(str,c); +} diff --git a/lib/msvcrt/mbstring/mbscmp.c b/lib/msvcrt/mbstring/mbscmp.c new file mode 100644 index 0000000..3bc0d98 --- /dev/null +++ b/lib/msvcrt/mbstring/mbscmp.c @@ -0,0 +1,7 @@ +#include +#include + +int _mbscmp(const unsigned char *str1, const unsigned char *str2) +{ + return strcmp(str1,str2); +} diff --git a/lib/msvcrt/mbstring/mbscoll.c b/lib/msvcrt/mbstring/mbscoll.c new file mode 100644 index 0000000..dad12be --- /dev/null +++ b/lib/msvcrt/mbstring/mbscoll.c @@ -0,0 +1,97 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbscoll.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +int colldif(unsigned short c1, unsigned short c2); + +int _mbscoll(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + while ( *s1 != 0 ) { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + + } + } + else + return colldif(*s1, *s2); + } ; + return 0; +} + +#if 0 +int _mbsbcoll(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + + while ( *s1 != 0 ) { + + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + } + } + else + return colldif(*s1, *s2); + } ; + return 0; +} +#endif diff --git a/lib/msvcrt/mbstring/mbscpy.c b/lib/msvcrt/mbstring/mbscpy.c new file mode 100644 index 0000000..247900a --- /dev/null +++ b/lib/msvcrt/mbstring/mbscpy.c @@ -0,0 +1,7 @@ +#include +#include + +unsigned char * _mbscpy(unsigned char *dst, const unsigned char *str) +{ + return strcpy(dst,str); +} diff --git a/lib/msvcrt/mbstring/mbscspn.c b/lib/msvcrt/mbstring/mbscspn.c new file mode 100644 index 0000000..46783ee --- /dev/null +++ b/lib/msvcrt/mbstring/mbscspn.c @@ -0,0 +1,19 @@ +#include + +// not correct +size_t _mbscspn(const unsigned char *s1, const unsigned char *s2) +{ + const char *p, *spanp; + char c, sc; + + for (p = s1;;) + { + c = *p++; + spanp = s2; + do { + if ((sc = *spanp++) == c) + return (size_t)(p - 1) - (size_t)s1; + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/msvcrt/mbstring/mbsdec.c b/lib/msvcrt/mbstring/mbsdec.c new file mode 100644 index 0000000..0836f15 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsdec.c @@ -0,0 +1,14 @@ +#include + +unsigned char * _mbsdec(const unsigned char *str, const unsigned char *cur) +{ + unsigned char *s = (unsigned char *)cur; + if ( str >= cur ) + return NULL; + + s--; + if (_ismbblead(*(s-1)) ) + s--; + + return s; +} diff --git a/lib/msvcrt/mbstring/mbsdup.c b/lib/msvcrt/mbstring/mbsdup.c new file mode 100644 index 0000000..00dc9d0 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsdup.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/hanzen.c + * PURPOSE: Duplicates a multi byte string + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + Modified from DJGPP strdup + * 12/04/99: Created + */ + +#include +#include + +unsigned char * _mbsdup(const unsigned char *_s) +{ + char *rv; + if (_s == 0) + return 0; + rv = (char *)malloc(_mbslen(_s) + 1); + if (rv == 0) + return 0; + _mbscpy(rv, _s); + return rv; +} diff --git a/lib/msvcrt/mbstring/mbsicmp.c b/lib/msvcrt/mbstring/mbsicmp.c new file mode 100644 index 0000000..db88fed --- /dev/null +++ b/lib/msvcrt/mbstring/mbsicmp.c @@ -0,0 +1,62 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsicmp.c + * PURPOSE: Duplicates a multi byte string + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include +#include + +int _mbsicmp(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (toupper(*s1) != toupper(*s2)) + return toupper(*s1) - toupper(*s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( _mbctoupper(*short_s1) != _mbctoupper(*short_s2 )) + return _mbctoupper(*short_s1) - _mbctoupper(*short_s2); + else { + s1 += 2; + s2 += 2; + } + } + else + return *s1 - *s2; + } while (*s1 != 0); + return 0; + + while (toupper(*s1) == toupper(*s2)) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); +} diff --git a/lib/msvcrt/mbstring/mbsicoll.c b/lib/msvcrt/mbstring/mbsicoll.c new file mode 100644 index 0000000..32020cc --- /dev/null +++ b/lib/msvcrt/mbstring/mbsicoll.c @@ -0,0 +1,55 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/iskpun.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include +#include + +int colldif(unsigned short c1, unsigned short c2); +int _mbsicoll(const unsigned char *str1, const unsigned char *str2) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + while ( *s1 != 0 ) { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (toupper(*s1) != toupper(*s2)) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( _mbctoupper(*short_s1) != _mbctoupper(*short_s2 )) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + + } + } + else + return colldif(*s1, *s2); + } ; + return 0; +} diff --git a/lib/msvcrt/mbstring/mbsinc.c b/lib/msvcrt/mbstring/mbsinc.c new file mode 100644 index 0000000..30e42e9 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsinc.c @@ -0,0 +1,10 @@ +#include + +unsigned char * _mbsinc(const unsigned char *s) +{ + unsigned char *c = (unsigned char *)s; + if (_ismbblead(*s) ) + c++; + c++; + return c; +} diff --git a/lib/msvcrt/mbstring/mbslen.c b/lib/msvcrt/mbstring/mbslen.c new file mode 100644 index 0000000..06386b2 --- /dev/null +++ b/lib/msvcrt/mbstring/mbslen.c @@ -0,0 +1,15 @@ +#include + +size_t _mbclen2(const unsigned int s); + +size_t _mbslen(const unsigned char *str) +{ + int i = 0; + unsigned char *s; + + if (str == 0) + return 0; + + for (s = (unsigned char *)str; *s; s+=_mbclen2(*s),i++); + return i; +} diff --git a/lib/msvcrt/mbstring/mbslwr.c b/lib/msvcrt/mbstring/mbslwr.c new file mode 100644 index 0000000..0b405fd --- /dev/null +++ b/lib/msvcrt/mbstring/mbslwr.c @@ -0,0 +1,45 @@ +#include +#include + +unsigned int _mbbtolower(unsigned int c) +{ + if (!_ismbblead(c) ) + return tolower(c); + return c; +} + +// code page 952 +#define CASE_DIFF (0x8281 - 0x8260) + +unsigned int _mbctolower(unsigned int c) +{ + if ((c & 0xFF00) != 0) + { + // true multibyte case conversion needed + if (_ismbclower(c)) + return c + CASE_DIFF; + } + else + return _mbbtolower(c); + + return 0; +} + +unsigned char * _mbslwr(unsigned char *x) +{ + unsigned char *y=x; + + while (*y) + { + if (!_ismbblead(*y)) + { + *y = tolower(*y); + } + else + { + *y=_mbctolower(*(unsigned short *)y); + y++; + } + } + return x; +} diff --git a/lib/msvcrt/mbstring/mbsncat.c b/lib/msvcrt/mbstring/mbsncat.c new file mode 100644 index 0000000..a875ab0 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsncat.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsset.c + * PURPOSE: Concatenate two multi byte string to maximum of n characters or bytes + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include +#include + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsncat(unsigned char *dst, const unsigned char *src, size_t n) +{ + char *d = (char *)dst; + char *s = (char *)src; + if (n != 0) { + d = dst + strlen(dst); // get the end of string + d += _mbclen2(*d); // move 1 or 2 up + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + if (!_ismbblead(*s) ) + n--; + } while (n > 0); + } + return dst; +} + +unsigned char * _mbsnbcat(unsigned char *dst, const unsigned char *src, size_t n) +{ + char *d; + char *s = (char *)src; + if (n != 0) { + d = dst + strlen(dst); // get the end of string + d += _mbclen2(*d); // move 1 or 2 up + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + if ( !(n==1 && _ismbblead(*s)) ) + n--; + } while (n > 0); + } + return dst; +} + diff --git a/lib/msvcrt/mbstring/mbsnccnt.c b/lib/msvcrt/mbstring/mbsnccnt.c new file mode 100644 index 0000000..daa4484 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsnccnt.c @@ -0,0 +1,29 @@ +#include + +size_t _mbsnccnt(const unsigned char *str, size_t n) +{ + unsigned char *s = (unsigned char *)str; + size_t cnt = 0; + while(*s != 0 && n > 0) { + if (_ismbblead(*s) ) + s++; + else + n--; + s++; + cnt++; + } + + return cnt; +} + +size_t _mbsnbcnt(const unsigned char *str, size_t n) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && n > 0) { + if (!_ismbblead(*s) ) + n--; + s++; + } + + return (size_t)(s - str); +} diff --git a/lib/msvcrt/mbstring/mbsncmp.c b/lib/msvcrt/mbstring/mbsncmp.c new file mode 100644 index 0000000..8e1011b --- /dev/null +++ b/lib/msvcrt/mbstring/mbsncmp.c @@ -0,0 +1,103 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncmp.c + * PURPOSE: Compares two strings to a maximum of n bytes or characters + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +int _mbsncmp(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return *s1 - *s2; + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return *short_s1 - *short_s2; + else { + s1 += 2; + s2 += 2; + n--; + + } + } + else + return *s1 - *s2; + } while (n > 0); + return 0; +} + +int _mbsnbcmp(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return *s1 - *s2; + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return *short_s1 - *short_s2; + else { + s1 += 2; + s2 += 2; + n-=2; + + } + } + else + return *s1 - *s2; + } while (n > 0); + return 0; +} diff --git a/lib/msvcrt/mbstring/mbsncoll.c b/lib/msvcrt/mbstring/mbsncoll.c new file mode 100644 index 0000000..e32cbd0 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsncoll.c @@ -0,0 +1,109 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncoll.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include + +int colldif(unsigned short c1, unsigned short c2); + +int _mbsncoll(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + n--; + + } + } + else + return colldif(*s1, *s2); + } while (n > 0); + return 0; +} + +int _mbsnbcoll(const unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + int l1, l2; + + if (n == 0) + return 0; + do { + + if (*s1 == 0) + break; + + l1 = _ismbblead(*s1); + l2 = _ismbblead(*s2); + if ( !l1 && !l2 ) { + + if (*s1 != *s2) + return colldif(*s1, *s2); + else { + s1 += 1; + s2 += 1; + n--; + } + } + else if ( l1 && l2 ){ + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + if ( *short_s1 != *short_s2 ) + return colldif(*short_s1, *short_s2); + else { + s1 += 2; + s2 += 2; + n-=2; + + } + } + else + return colldif(*s1, *s2); + } while (n > 0); + return 0; +} + +int colldif(unsigned short c1, unsigned short c2) +{ + return c1 - c2; +} diff --git a/lib/msvcrt/mbstring/mbsncpy.c b/lib/msvcrt/mbstring/mbsncpy.c new file mode 100644 index 0000000..a2e21c0 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsncpy.c @@ -0,0 +1,77 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsncpy.c + * PURPOSE: Copies a string to a maximum of n bytes or characters + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +unsigned char *_mbsncpy(unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + if (n == 0) + return 0; + do { + + if (*s2 == 0) + break; + + if ( !_ismbblead(*s2) ) { + + *s1 = *s2; + s1 += 1; + s2 += 1; + n--; + } + else { + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + *short_s1 = *short_s2; + s1 += 2; + s2 += 2; + n--; + } + } while (n > 0); + return str1; +} + +unsigned char * _mbsnbcpy(unsigned char *str1, const unsigned char *str2, size_t n) +{ + unsigned char *s1 = (unsigned char *)str1; + unsigned char *s2 = (unsigned char *)str2; + + unsigned short *short_s1, *short_s2; + + if (n == 0) + return 0; + do { + + if (*s2 == 0) + break; + + if ( !_ismbblead(*s2) ) { + + *s1 = *s2; + s1 += 1; + s2 += 1; + n--; + } + else { + short_s1 = (unsigned short *)s1; + short_s2 = (unsigned short *)s2; + *short_s1 = *short_s2; + s1 += 2; + s2 += 2; + n-=2; + } + } while (n > 0); + return str1; +} diff --git a/lib/msvcrt/mbstring/mbsnextc.c b/lib/msvcrt/mbstring/mbsnextc.c new file mode 100644 index 0000000..9b9c4f7 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsnextc.c @@ -0,0 +1,16 @@ +#include + +unsigned int _mbsnextc (const unsigned char *src) +{ + unsigned char *char_src = (unsigned char *)src; + unsigned short *short_src = (unsigned short *)src; + + if (src == NULL) + return 0; + + if (!_ismbblead(*src)) + return *char_src; + else + return *short_src; + return 0; +} diff --git a/lib/msvcrt/mbstring/mbsnicmp.c b/lib/msvcrt/mbstring/mbsnicmp.c new file mode 100644 index 0000000..ef34bd1 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsnicmp.c @@ -0,0 +1,40 @@ +#include + +size_t _mbclen2(const unsigned int s); +unsigned int _mbbtoupper(unsigned int c); + +int _mbsnicmp(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + if (n == 0) + return 0; + do { + if (_mbbtoupper(*s1) != _mbbtoupper(*s2)) + return _mbbtoupper(*(unsigned const char *)s1) - _mbbtoupper(*(unsigned const char *)s2); + s1 += _mbclen2(*s1); + s2 += _mbclen2(*s2); + + if (*s1 == 0) + break; + if (!_ismbblead(*s1)) + n--; + } while (n > 0); + return 0; +} + +int _mbsnbicmp(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + if (n == 0) + return 0; + do { + if (_mbbtoupper(*s1) != _mbbtoupper(*s2)) + return _mbbtoupper(*(unsigned const char *)s1) - _mbbtoupper(*(unsigned const char *)s2); + s1 += _mbclen2(*s1); + s2 += _mbclen2(*s2); + + if (*s1 == 0) + break; + n--; + } while (n > 0); + return 0; +} + diff --git a/lib/msvcrt/mbstring/mbsnicoll.c b/lib/msvcrt/mbstring/mbsnicoll.c new file mode 100644 index 0000000..c163636 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsnicoll.c @@ -0,0 +1,11 @@ +#include + +int _mbsnicoll(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + return 0; +} + +int _mbsnbicoll(const unsigned char *s1, const unsigned char *s2, size_t n) +{ + return 0; +} diff --git a/lib/msvcrt/mbstring/mbsninc.c b/lib/msvcrt/mbstring/mbsninc.c new file mode 100644 index 0000000..3cb3a49 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsninc.c @@ -0,0 +1,13 @@ +#include + +unsigned char * _mbsninc(const unsigned char *str, size_t n) +{ + unsigned char *s = (unsigned char *)str; + while(*s != 0 && n > 0) { + if (!_ismbblead(*s) ) + n--; + s++; + } + + return s; +} diff --git a/lib/msvcrt/mbstring/mbsnset.c b/lib/msvcrt/mbstring/mbsnset.c new file mode 100644 index 0000000..75befef --- /dev/null +++ b/lib/msvcrt/mbstring/mbsnset.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsset.c + * PURPOSE: Fills a string with a multibyte character + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsnset(unsigned char *src, unsigned int val, size_t count) +{ + unsigned char *char_src = (unsigned char *)src; + unsigned short *short_src = (unsigned short *)src; + + if ( _mbclen2(val) == 1 ) { + + while(count > 0) { + *char_src = val; + char_src++; + count--; + } + *char_src = 0; + } + else { + while(count > 0) { + *short_src = val; + short_src++; + count-=2; + } + *short_src = 0; + } + + return src; +} + +unsigned char * _mbsnbset(unsigned char *src, unsigned int val, size_t count) +{ + unsigned char *char_src = (unsigned char *)src; + unsigned short *short_src = (unsigned short *)src; + + if ( _mbclen2(val) == 1 ) { + + while(count > 0) { + *char_src = val; + char_src++; + count--; + } + *char_src = 0; + } + else { + while(count > 0) { + *short_src = val; + short_src++; + count-=2; + } + *short_src = 0; + } + + return src; +} diff --git a/lib/msvcrt/mbstring/mbspbrk.c b/lib/msvcrt/mbstring/mbspbrk.c new file mode 100644 index 0000000..f9566e7 --- /dev/null +++ b/lib/msvcrt/mbstring/mbspbrk.c @@ -0,0 +1,16 @@ +#include + +// not correct +unsigned char * _mbspbrk(const unsigned char *s1, const unsigned char *s2) +{ + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return (unsigned char *)((char *)s1 - (char *)1); + } + return 0; +} diff --git a/lib/msvcrt/mbstring/mbsrchr.c b/lib/msvcrt/mbstring/mbsrchr.c new file mode 100644 index 0000000..3a2a8d6 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsrchr.c @@ -0,0 +1,30 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/mbstring/mbsrchr.c + * PURPOSE: Searches for a character in reverse + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ + +#include + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsrchr(const unsigned char *src, unsigned int val) +{ + char *s = (char *)src; + short cc = val; + const char *sp=(char *)0; + + while (*s) + { + if (*(short *)s == cc) + sp = s; + s+= _mbclen2(*s); + } + if (cc == 0) + sp = s; + return (char *)sp; +} diff --git a/lib/msvcrt/mbstring/mbsrev.c b/lib/msvcrt/mbstring/mbsrev.c new file mode 100644 index 0000000..5509c9d --- /dev/null +++ b/lib/msvcrt/mbstring/mbsrev.c @@ -0,0 +1,28 @@ +#include + +unsigned char * _mbsrev(unsigned char *s) +{ + unsigned char *e; + unsigned char a; + e=s; + while (*e) { + if ( _ismbblead(*e) ) { + a = *e; + *e = *++e; + if ( *e == 0 ) + break; + *e = a; + } + e++; + } + while (s + +size_t _mbclen2(const unsigned int s); + +unsigned char * _mbsset(unsigned char *src, unsigned int c) +{ + unsigned char *char_src = src; + unsigned short *short_src = (unsigned short *)src; + + if ( _mbclen2(c) == 1 ) { + + while(*char_src != 0) { + *char_src = c; + char_src++; + } + *char_src = 0; + } + else { + while(*short_src != 0) { + *short_src = c; + short_src++; + } + *short_src = 0; + } + + return src; +} diff --git a/lib/msvcrt/mbstring/mbsspn.c b/lib/msvcrt/mbstring/mbsspn.c new file mode 100644 index 0000000..c9ca1ac --- /dev/null +++ b/lib/msvcrt/mbstring/mbsspn.c @@ -0,0 +1,16 @@ +#include + +// not correct +size_t _mbsspn(const unsigned char *s1, const unsigned char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (size_t)(p - 1) - (size_t)s1; +// - (char *)s1); +} diff --git a/lib/msvcrt/mbstring/mbsspnp.c b/lib/msvcrt/mbstring/mbsspnp.c new file mode 100644 index 0000000..37b8f36 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsspnp.c @@ -0,0 +1,15 @@ +#include + +// not correct +unsigned char * _mbsspnp(const unsigned char *s1, const unsigned char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (unsigned char *)p; +} diff --git a/lib/msvcrt/mbstring/mbsstr.c b/lib/msvcrt/mbstring/mbsstr.c new file mode 100644 index 0000000..ba0b862 --- /dev/null +++ b/lib/msvcrt/mbstring/mbsstr.c @@ -0,0 +1,20 @@ +#include +#include + +unsigned char *_mbsstr(const unsigned char *src1,const unsigned char *src2) +{ + int len; + + if (src2 ==NULL || *src2 == 0) + return (unsigned char *)src1; + + len = _mbstrlen(src2); + + while(*src1) + { + if ((*src1 == *src2) && (_mbsncmp(src1,src2,len) == 0)) + return (unsigned char *)src1; + src1 = (unsigned char *)_mbsinc(src1); + } + return NULL; +} diff --git a/lib/msvcrt/mbstring/mbstok.c b/lib/msvcrt/mbstring/mbstok.c new file mode 100644 index 0000000..3c68097 --- /dev/null +++ b/lib/msvcrt/mbstring/mbstok.c @@ -0,0 +1,53 @@ +#include + +unsigned char * _mbstok(unsigned char *s, unsigned char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s; + s = _mbsinc(s); + + for (spanp = delim; (sc = *spanp) != 0; spanp = _mbsinc(spanp)) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s; + s = _mbsinc(s); + spanp = delim; + do { + if ((sc = *spanp) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + spanp = _mbsinc(spanp); + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/msvcrt/mbstring/mbstrlen.c b/lib/msvcrt/mbstring/mbstrlen.c new file mode 100644 index 0000000..aa35677 --- /dev/null +++ b/lib/msvcrt/mbstring/mbstrlen.c @@ -0,0 +1,16 @@ +#include +#include + +size_t _mbstrlen( const char *string ) +{ + char *s = (char *)string; + size_t i = 0; + + while ( *s != 0 ) { + if ( _ismbblead(*s) ) + s++; + s++; + i++; + } + return i; +} diff --git a/lib/msvcrt/mbstring/mbsupr.c b/lib/msvcrt/mbstring/mbsupr.c new file mode 100644 index 0000000..8f8ac5b --- /dev/null +++ b/lib/msvcrt/mbstring/mbsupr.c @@ -0,0 +1,51 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/mbstring/mbsupr.c + * PURPOSE: + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 12/04/99: Created + */ +#include +#include + +unsigned int _mbbtoupper(unsigned int c) +{ + if (!_ismbblead(c) ) + return toupper(c); + + return c; +} + +// codepage 952 +#define CASE_DIFF (0x8281 - 0x8260) + +unsigned int _mbctoupper(unsigned int c) +{ + + if ((c & 0xFF00) != 0) { +// true multibyte case conversion needed + if ( _ismbcupper(c) ) + return c + CASE_DIFF; + + } else + return _mbbtoupper(c); + + return 0; +} + +unsigned char * _mbsupr(unsigned char *x) +{ + unsigned char *y=x; + while (*y) { + if (!_ismbblead(*y) ) + *y = toupper(*y); + else { + *y=_mbctoupper(*(unsigned short *)y); + y++; + } + } + return x; +} + diff --git a/lib/msvcrt/misc/.cvsignore b/lib/msvcrt/misc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/misc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/misc/amsg.c b/lib/msvcrt/misc/amsg.c new file mode 100644 index 0000000..dafdcd1 --- /dev/null +++ b/lib/msvcrt/misc/amsg.c @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/misc/amsg.c + * PURPOSE: Print runtime error messages + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include + + +static char *__rt_err_msg[] = +{ + "stack overflow", /* _RT_STACK */ + "null pointer assignment", /* _RT_NULLPTR */ + "floating point not loaded", /* _RT_FLOAT */ + "integer divide by 0", /* _RT_INTDIV */ + "not enough space for arguments", /* _RT_SPACEARG */ + "not enough space for environment", /* _RT_SPACEENV */ + "abnormal program termination", /* _RT_ABORT */ + "not enough space for thread data", /* _RT_THREAD */ + "unexpected multithread lock error", /* _RT_LOCK */ + "unexpected heap error", /* _RT_HEAP */ + "unable to open console device", /* _RT_OPENCON */ + "non-continuable exception", /* _RT_NONCONT */ + "invalid exception disposition", /* _RT_INVALDISP */ + "not enough space for _onexit/atexit table", /* _RT_ONEXIT */ + "pure virtual function call", /* _RT_PUREVIRT */ + "not enough space for stdio initialization", /* _RT_STDIOINIT */ + "not enough space for lowio initialization", /* _RT_LOWIOINIT */ +}; + + +int _aexit_rtn(int exitcode) +{ + _exit(exitcode); +} + +void _amsg_exit (int errnum) +{ + fprintf(stderr, "runtime error - %s\n", __rt_err_msg[errnum]); + _aexit_rtn(-1); +} + +/* EOF */ diff --git a/lib/msvcrt/misc/assert.c b/lib/msvcrt/misc/assert.c new file mode 100644 index 0000000..59b3bbd --- /dev/null +++ b/lib/msvcrt/misc/assert.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +void _assert(const char *msg, const char *file, int line) +{ + /* Assertion failed at foo.c line 45: x + +#include +#include + +#define NDEBUG +#include + +static int nAttachCount = 0; + +unsigned int _osver = 0; +unsigned int _winminor = 0; +unsigned int _winmajor = 0; +unsigned int _winver = 0; + +char *_acmdln = NULL; /* pointer to ascii command line */ +#undef _environ +char **_environ = NULL; /* pointer to environment block */ +char ***_environ_dll = &_environ;/* pointer to environment block */ + +char **__initenv = NULL; + +char *_pgmptr = NULL; /* pointer to program name */ + +int __app_type = 0; //_UNKNOWN_APP; /* application type */ + +int __mb_cur_max = 1; + +HANDLE hHeap = NULL; /* handle for heap */ + + +/* FUNCTIONS **************************************************************/ + +int BlockEnvToEnviron() +{ + char * ptr, * ptr2; + int i, len; + + DPRINT("BlockEnvToEnviron()\n"); + + if (_environ) + { + FreeEnvironmentStringsA(_environ[0]); + free(_environ); + _environ = NULL; + } + ptr2 = ptr = (char*)GetEnvironmentStringsA(); + if (ptr == NULL) + { + DPRINT("GetEnvironmentStringsA() returnd NULL\n"); + return -1; + } + len = 0; + while (*ptr2) + { + len++; + while (*ptr2++); + } + _environ = malloc((len + 1) * sizeof(char*)); + if (_environ == NULL) + { + FreeEnvironmentStringsA(ptr); + return -1; + } + for (i = 0; i < len && *ptr; i++) + { + _environ[i] = ptr; + while (*ptr++); + } + _environ[i] = NULL; + return 0; +} + +BOOL __stdcall +DllMain(PVOID hinstDll, + ULONG dwReason, + PVOID reserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH://1 + /* initialize version info */ + DPRINT("Attach %d\n", nAttachCount); + _osver = GetVersion(); + _winmajor = (_osver >> 8) & 0xFF; + _winminor = _osver & 0xFF; + _winver = (_winmajor << 8) + _winminor; + _osver = (_osver >> 16) & 0xFFFF; + + if (hHeap == NULL || hHeap == INVALID_HANDLE_VALUE) + { + hHeap = HeapCreate(0, 0, 0); + if (hHeap == NULL || hHeap == INVALID_HANDLE_VALUE) + { + return FALSE; + } + } + if (nAttachCount==0) + { + __fileno_init(); + } + + /* create tls stuff */ + if (!CreateThreadData()) + return FALSE; + + _acmdln = (char *)GetCommandLineA(); + + /* FIXME: This crashes all applications */ + if (BlockEnvToEnviron() < 0) + return FALSE; + + /* FIXME: more initializations... */ + + nAttachCount++; + DPRINT("Attach done\n"); + break; + + case DLL_THREAD_ATTACH://2 + break; + + case DLL_THREAD_DETACH://4 + FreeThreadData(NULL); + break; + + case DLL_PROCESS_DETACH://0 + DPRINT("Detach %d\n", nAttachCount); + if (nAttachCount > 0) + { + nAttachCount--; + + /* FIXME: more cleanup... */ + _fcloseall(); + + /* destroy tls stuff */ + DestroyThreadData(); + + /* destroy heap */ + if (nAttachCount == 0) + { + + if (_environ) + { + FreeEnvironmentStringsA(_environ[0]); + free(_environ); + _environ = NULL; + } +#if 1 + HeapDestroy(hHeap); + hHeap = NULL; +#endif + } + DPRINT("Detach done\n"); + } + break; + } + + return TRUE; +} + + + +void __set_app_type(int app_type) +{ + __app_type = app_type; +} + + +char **__p__acmdln(void) +{ + return &_acmdln; +} + +char ***__p__environ(void) +{ + return _environ_dll; +} + +char ***__p___initenv(void) +{ + return &__initenv; +} + +int *__p___mb_cur_max(void) +{ + return &__mb_cur_max; +} + +unsigned int *__p__osver(void) +{ + return &_osver; +} + +char **__p__pgmptr(void) +{ + return &_pgmptr; +} + +unsigned int *__p__winmajor(void) +{ + return &_winmajor; +} + +unsigned int *__p__winminor(void) +{ + return &_winminor; +} + +unsigned int *__p__winver(void) +{ + return &_winver; +} + + + +/* EOF */ diff --git a/lib/msvcrt/misc/getargs.c b/lib/msvcrt/misc/getargs.c new file mode 100644 index 0000000..b9452e7 --- /dev/null +++ b/lib/msvcrt/misc/getargs.c @@ -0,0 +1,155 @@ +#include +#include +#include + +extern char *_acmdln; +extern char *_pgmptr; +#undef _environ +extern char **_environ; + +#undef __argv +#undef __argc + +char **__argv = NULL; +int __argc = 0; + +extern HANDLE hHeap; + +char* strndup(char* name, int len) +{ + char *s = malloc(len + 1); + if (s != NULL) + { + strncpy(s, name, len); + } + return s; +} + +#define SIZE (4096 / sizeof(char*)) + +int add(char *name) +{ + char** _new; + if ((__argc % SIZE) == 0) + { + _new = malloc(sizeof(char*) * (__argc + SIZE)); + if (_new == NULL) + { + return -1; + } + if (__argv) + { + memcpy(_new, __argv, sizeof(char*) * __argc); + free(__argv); + } + __argv = _new; + } + __argv[__argc++] = name; +} + +int expand(char* name) +{ + char *s; + WIN32_FIND_DATA fd; + HANDLE hFile; + BOOLEAN first = TRUE; + char buffer[256]; + int pos; + + s = strpbrk(name, "*?"); + if (s) + { + hFile = FindFirstFile(name, &fd); + if (hFile != INVALID_HANDLE_VALUE) + { + while(s != name && *s != '/' && *s != '\\') + s--; + pos = s - name; + if (*s == '/' || *s == '\\') + pos++; + strncpy(buffer, name, pos); + do + { + if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + strcpy(&buffer[pos], fd.cFileName); + if (add(strdup(buffer)) < 0) + { + FindClose(hFile); + return -1; + } + first = FALSE; + } + } + while(FindNextFile(hFile, &fd)); + FindClose(hFile); + } + } + if (first) + { + if (add(name) < 0) + return -1; + } + else + free(name); + return 0; +} + +int __getmainargs(int *argc,char ***argv,char ***env,int flag) +{ + int i,afterlastspace; + + /* missing threading init */ + + i=0; + afterlastspace=0; + + while (_acmdln[i]) + { + if (_acmdln[i]==' ') + { + expand(strndup(_acmdln + afterlastspace, i - afterlastspace)); + i++; + while (_acmdln[i]==' ') + i++; + afterlastspace=i; + } + else + { + i++; + } + } + + if (_acmdln[afterlastspace] != 0) + { + expand(strndup(_acmdln+afterlastspace, i - afterlastspace)); + } + + HeapValidate(hHeap,0,NULL); + + *argc = __argc; + *argv = __argv; + *env = _environ; + + _pgmptr = strdup((char *)argv[0]); + + return 0; +} + + +int *__p___argc(void) +{ + return &__argc; +} + +char ***__p___argv(void) +{ + return &__argv; +} + +#if 0 +int _chkstk(void) +{ + return 0; +} +#endif diff --git a/lib/msvcrt/misc/initterm.c b/lib/msvcrt/misc/initterm.c new file mode 100644 index 0000000..69f9e65 --- /dev/null +++ b/lib/msvcrt/misc/initterm.c @@ -0,0 +1,35 @@ +#include + + +void +_initterm(void (* fStart[])(void), + void (* fEnd[])(void)) +{ + int i = 0; + + if ( fStart == NULL || fEnd == NULL ) + return; + + while ( &fStart[i] < fEnd ) + { + if ( fStart[i] != NULL ) + (*fStart[i])(); + i++; + } +} + + +typedef int (* _onexit_t)(void); + +_onexit_t +__dllonexit(_onexit_t func, + void (** fStart[])(void), + void (** fEnd[])(void)) +{ +} + +_onexit_t +_onexit(_onexit_t x) +{ + return x; +} diff --git a/lib/msvcrt/misc/purecall.c b/lib/msvcrt/misc/purecall.c new file mode 100644 index 0000000..fea7d5e --- /dev/null +++ b/lib/msvcrt/misc/purecall.c @@ -0,0 +1,7 @@ + +#include + +void _purecall(void) +{ + _amsg_exit(_RT_PUREVIRT); +} diff --git a/lib/msvcrt/misc/tls.c b/lib/msvcrt/misc/tls.c new file mode 100644 index 0000000..1e8a81b --- /dev/null +++ b/lib/msvcrt/misc/tls.c @@ -0,0 +1,101 @@ +/* tls.c */ + +#include +#include +#include + + +static unsigned long TlsIndex = (unsigned long)-1; + + +static void InitThreadData(PTHREADDATA ThreadData) +{ + ThreadData->terrno = 0; + ThreadData->tdoserrno = 0; + + ThreadData->fpecode = 0; + + /* FIXME: init more thread local data */ + +} + + +int CreateThreadData(void) +{ + PTHREADDATA ThreadData; + + TlsIndex = TlsAlloc(); + if (TlsIndex == (unsigned long)-1) + return FALSE; + + ThreadData = (PTHREADDATA)calloc(1, sizeof(THREADDATA)); + if (ThreadData == NULL) + return FALSE; + + if(!TlsSetValue(TlsIndex, (LPVOID)ThreadData)) + return FALSE; + + InitThreadData(ThreadData); + + return TRUE; +} + + +void DestroyThreadData(void) +{ + if (TlsIndex != (unsigned long)-1) + { + TlsFree(TlsIndex); + TlsIndex = (unsigned long)-1; + } +} + + +void FreeThreadData(PTHREADDATA ThreadData) +{ + if (TlsIndex != (unsigned long)-1) + { + if (ThreadData == NULL) + ThreadData = TlsGetValue(TlsIndex); + + if (ThreadData != NULL) + { + /* FIXME: free more thread local data */ + + free(ThreadData); + } + + TlsSetValue(TlsIndex, NULL); + } +} + + +PTHREADDATA GetThreadData(void) +{ + PTHREADDATA ThreadData; + DWORD LastError; + + LastError = GetLastError(); + ThreadData = TlsGetValue(TlsIndex); + if (ThreadData == NULL) + { + ThreadData = (PTHREADDATA)calloc(1, sizeof(THREADDATA)); + if (ThreadData != NULL) + { + TlsSetValue(TlsIndex, (LPVOID)ThreadData); + + InitThreadData(ThreadData); + } + else + { + _amsg_exit(_RT_THREAD); /* write message and die */ + } + } + + SetLastError(LastError); + + return ThreadData; +} + +/* EOF */ + diff --git a/lib/msvcrt/msvcrt.def b/lib/msvcrt/msvcrt.def new file mode 100644 index 0000000..49bf1f3 --- /dev/null +++ b/lib/msvcrt/msvcrt.def @@ -0,0 +1,773 @@ +; $Id$ +; +; ReactOS MSVCRT Compatibility Library +; +LIBRARY MSVCRT.DLL +EXPORTS +;---------------------------------------------------------------------- +; C++ Mangled Symbols +;---------------------------------------------------------------------- +; $I10_OUTPUT +; ??0__non_rtti_object@@QAE@ABV0@@Z +; ??0__non_rtti_object@@QAE@PBD@Z +; ??0bad_cast@@QAE@ABQBD@Z +; ??0bad_cast@@QAE@ABV0@@Z +; ??0bad_typeid@@QAE@ABV0@@Z +; ??0bad_typeid@@QAE@PBD@Z +; ??0exception@@QAE@ABQBD@Z +; ??0exception@@QAE@ABV0@@Z +; ??0exception@@QAE@XZ +; ??1__non_rtti_object@@UAE@XZ +; ??1bad_cast@@UAE@XZ +; ??1bad_typeid@@UAE@XZ +; ??1exception@@UAE@XZ +; ??1type_info@@UAE@XZ +; ??2@YAPAXI@Z +; ??3@YAXPAX@Z +; ??4__non_rtti_object@@QAEAAV0@ABV0@@Z +; ??4bad_cast@@QAEAAV0@ABV0@@Z +; ??4bad_typeid@@QAEAAV0@ABV0@@Z +; ??4exception@@QAEAAV0@ABV0@@Z +; ??8type_info@@QBEHABV0@@Z +; ??9type_info@@QBEHABV0@@Z +; ??_7__non_rtti_object@@6B@ +; ??_7bad_cast@@6B@ +; ??_7bad_typeid@@6B@ +; ??_7exception@@6B@ +; ??_E__non_rtti_object@@UAEPAXI@Z +; ??_Ebad_cast@@UAEPAXI@Z +; ??_Ebad_typeid@@UAEPAXI@Z +; ??_Eexception@@UAEPAXI@Z +; ??_G__non_rtti_object@@UAEPAXI@Z +; ??_Gbad_cast@@UAEPAXI@Z +; ??_Gbad_typeid@@UAEPAXI@Z +; ??_Gexception@@UAEPAXI@Z +; ?_query_new_handler@@YAP6AHI@ZXZ +; ?_query_new_mode@@YAHXZ +; ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z +; ?_set_new_mode@@YAHH@Z +; ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z +; ?before@type_info@@QBEHABV1@@Z +; ?name@type_info@@QBEPBDXZ +; ?raw_name@type_info@@QBEPBDXZ +; ?set_new_handler@@YAP6AXXZP6AXXZ@Z +; ?set_terminate@@YAP6AXXZP6AXXZ@Z +; ?set_unexpected@@YAP6AXXZP6AXXZ@Z +; ?terminate@@YAXXZ +; ?unexpected@@YAXXZ +; ?what@exception@@UBEPBDXZ +;---------------------------------------------------------------------- +; C Undecorated Symbols +;---------------------------------------------------------------------- +_CIacos +_CIasin +_CIatan +_CIatan2 +_CIcos +_CIcosh +_CIexp +_CIfmod +_CIlog +_CIlog10 +_CIpow +_CIsin +_CIsinh +_CIsqrt +_CItan +_CItanh +; _CxxThrowException +; _EH_prolog +; _Getdays +; _Getmonths +; _Gettnames +_HUGE DATA +; _Strftime +_XcptFilter +; __CxxFrameHandler +; __CxxLongjmpUnwind +; __RTCastToVoid +; __RTDynamicCast +; __RTtypeid +; __STRINGTOLD +__argc DATA +__argv DATA +; __badioinfo +; __crtCompareStringA +; __crtGetLocaleInfoW +; __crtLCMapStringA +__dllonexit +__doserrno +__fpecode +__getmainargs +__initenv DATA +__isascii +__iscsym +__iscsymf +; __lc_codepage +; __lc_collate_cp +; __lc_handle +; __lconv_init +__mb_cur_max DATA +__p___argc +__p___argv +__p___initenv +__p___mb_cur_max +; __p___wargv +; __p___winitenv +__p__acmdln +; __p__amblksiz +__p__commode +; __p__daylight +; __p__dstbias +__p__environ +; __p__fileinfo +__p__fmode +; __p__iob +; __p__mbcasemap +; __p__mbctype +__p__osver +__p__pctype +__p__pgmptr +__p__pwctype +; __p__timezone +; __p__tzname +; __p__wcmdln +; __p__wenviron +__p__winmajor +__p__winminor +__p__winver +; __p__wpgmptr +; __pioinfo +; __pxcptinfoptrs +__set_app_type +; __setlc_active +__setusermatherr +__threadhandle +__threadid +__toascii +; __unDName +; __unDNameEx +; __unguarded_readlc_active +; __wargv +; __wgetmainargs +; __winitenv +_abnormal_termination +_access +_acmdln DATA +; _adj_fdiv_m16i +; _adj_fdiv_m32 +; _adj_fdiv_m32i +; _adj_fdiv_m64 +; _adj_fdiv_r +; _adj_fdivr_m16i +; _adj_fdivr_m32 +; _adj_fdivr_m32i +; _adj_fdivr_m64 +; _adj_fpatan +; _adj_fprem +; _adj_fprem1 +; _adj_fptan +_adjust_fdiv DATA +_aexit_rtn +_amsg_exit +_assert +; _atodbl +_atoi64 +; _atoldbl +_beep +_beginthread +_beginthreadex +_c_exit +_cabs +; _callnewh +_cexit +_cgets +_chdir +_chdrive +_chgsign +; _chkesp +_chmod +_chsize +_clearfp +_close +_commit +_commode DATA +_control87 +_controlfp +_copysign +_cprintf +_cputs +_creat +_cscanf +_ctype DATA +_cwait +_daylight DATA +; _dstbias +_dup +_dup2 +_ecvt +_endthread +_endthreadex +_environ_dll DATA +_eof +_errno +_except_handler2 +_except_handler3 +_execl +_execle +_execlp +_execlpe +_execv +_execve +_execvp +_execvpe +_exit +; _expand +_fcloseall +_fcvt +_fdopen +_fgetchar +_fgetwchar +_filbuf +; _fileinfo DATA +_filelength +_filelengthi64 +_fileno +_findclose +_findfirst +_findfirsti64 +_findnext +_findnexti64 +_finite +_flsbuf +_flushall +_fmode DATA +_fpclass +_fpieee_flt +_fpreset +_fputchar +_fputwchar +_fsopen +_fstat +_fstati64 +; _ftime +_ftol +_fullpath +_futime +_gcvt +_get_osfhandle +; _get_sbh_threshold +_getch +_getche +_getcwd +_getdcwd +_getdiskfree +_getdllprocaddr +_getdrive +_getdrives +; _getmaxstdio +; _getmbcp +_getpid +; _getsystime +_getw +; _getws +_global_unwind2 +; _heapadd +; _heapchk +; _heapmin +; _heapset +; _heapused +; _heapwalk +_hypot +_i64toa +_i64tow +_initterm +; _inp +; _inpd +; _inpw +_iob +_isatty +_isctype +_ismbbalnum +_ismbbalpha +_ismbbgraph +_ismbbkalnum +_ismbbkana +; _ismbbkprint +_ismbbkpunct +_ismbblead +_ismbbprint +_ismbbpunct +_ismbbtrail +_ismbcalnum +_ismbcalpha +_ismbcdigit +; _ismbcgraph +_ismbchira +_ismbckata +_ismbcl0 +_ismbcl1 +_ismbcl2 +_ismbclegal +_ismbclower +_ismbcprint +; _ismbcpunct +_ismbcspace +_ismbcsymbol +_ismbcupper +_ismbslead +_ismbstrail +_isnan +_itoa +_itow +_j0 +_j1 +_jn +_kbhit +_lfind +_loaddll +_local_unwind2 +; _lock +_locking +_logb +; _longjmpex +_lrotl +_lrotr +_lsearch +_lseek +_lseeki64 +_ltoa +_ltow +_makepath +_mbbtombc +_mbbtype +; _mbcasemap +_mbccpy +_mbcjistojms +_mbcjmstojis +_mbclen +_mbctohira +_mbctokata +_mbctolower +_mbctombb +_mbctoupper +_mbctype DATA +_mbsbtype +_mbscat +_mbschr +_mbscmp +_mbscoll +_mbscpy +_mbscspn +_mbsdec +_mbsdup +_mbsicmp +_mbsicoll +_mbsinc +_mbslen +_mbslwr +_mbsnbcat +_mbsnbcmp +_mbsnbcnt +_mbsnbcoll +_mbsnbcpy +_mbsnbicmp +_mbsnbicoll +_mbsnbset +_mbsncat +_mbsnccnt +_mbsncmp +_mbsncoll +_mbsncpy +_mbsnextc +_mbsnicmp +_mbsnicoll +_mbsninc +_mbsnset +_mbspbrk +_mbsrchr +_mbsrev +_mbsset +_mbsspn +_mbsspnp +_mbsstr +_mbstok +_mbstrlen +_mbsupr +_memccpy +_memicmp +_mkdir +_mktemp +;_msize +_nextafter +_onexit +_open +_open_osfhandle +_osver DATA +; _outp +; _outpd +; _outpw +_pclose +_pctype DATA +_pgmptr DATA +_pipe +_popen +_purecall +_putch +_putenv +_putw +_putws +_pwctype DATA +_read +_rmdir +_rmtmp +_rotl +_rotr +; _safe_fdiv +; _safe_fdivr +; _safe_fprem +; _safe_fprem1 +_scalb +_searchenv +; _seh_longjmp_unwind +; _set_error_mode +; _set_sbh_threshold +_seterrormode +_setjmp +; _setjmp3 +; _setmaxstdio +; _setmbcp +_setmode +; _setsystime +_sleep +_snprintf +_snwprintf +_sopen +_spawnl +_spawnle +_spawnlp +_spawnlpe +_spawnv +_spawnve +_spawnvp +_spawnvpe +_splitpath +_stat +_stati64 +_statusfp +_strcmpi +_strdate +_strdup +_strerror +_stricmp +_stricoll +_strlwr +_strncoll +_strnicmp +_strnicoll +_strnset +_strrev +_strset +_strtime +_strupr +_swab +_sys_errlist DATA +_sys_nerr DATA +_tell +_telli64 +_tempnam +_timezone DATA +_tolower +_toupper +_tzname DATA +_tzset +_ui64toa +_ui64tow +_ultoa +_ultow +_umask +_ungetch +_unlink +_unloaddll +; _unlock +_utime +_vsnprintf +_vsnwprintf +_waccess +_wasctime +_wchdir +_wchmod +; _wcmdln +_wcreat +_wcsdup +_wcsicmp +_wcsicoll +_wcslwr +_wcsncoll +_wcsnicmp +_wcsnicoll +_wcsnset +_wcsrev +_wcsset +_wcsupr +_wctime +; _wenviron +; _wexecl +; _wexecle +; _wexeclp +; _wexeclpe +; _wexecv +; _wexecve +; _wexecvp +; _wexecvpe +_wfdopen +_wfindfirst +_wfindfirsti64 +_wfindnext +_wfindnexti64 +_wfopen +_wfreopen +_wfsopen +_wfullpath +_wgetcwd +_wgetdcwd +_wgetenv +_winmajor DATA +_winminor DATA +_winver DATA +_wmakepath +_wmkdir +_wmktemp +_wopen +_wperror +; _wpgmptr DATA +_wpopen +_wputenv +_wremove +_wrename +_write +_wrmdir +_wsearchenv +; _wsetlocale +_wsopen +; _wspawnl +; _wspawnle +; _wspawnlp +; _wspawnlpe +; _wspawnv +; _wspawnve +; _wspawnvp +; _wspawnvpe +_wsplitpath +_wstat +_wstati64 +_wstrdate +_wstrtime +; _wsystem +_wtempnam +_wtmpnam +_wtoi +_wtoi64 +_wtol +_wunlink +_wutime +_y0 +_y1 +_yn +abort +abs +acos +asctime +asin +atan +atan2 +atexit +atof +atoi +atol +bsearch +calloc +ceil +clearerr +clock +cos +cosh +ctime +difftime +div +exit +exp +fabs +fclose +feof +ferror +fflush +fgetc +fgetpos +fgets +fgetwc +; fgetws +floor +fmod +fopen +fprintf +fputc +fputs +fputwc +; fputws +fread +free +freopen +frexp +fscanf +fseek +fsetpos +ftell +fwprintf +fwrite +fwscanf +getc +getchar +getenv +gets +getwc +; getwchar +gmtime +is_wctype +isalnum +isalpha +iscntrl +isdigit +isgraph +isleadbyte +islower +isprint +ispunct +isspace +isupper +iswalnum +iswalpha +iswascii +iswcntrl +iswctype +iswdigit +iswgraph +iswlower +iswprint +iswpunct +iswspace +iswupper +iswxdigit +isxdigit +labs +ldexp +ldiv +localeconv +localtime +log +log10 +longjmp +malloc +mblen +; mbstowcs +; mbtowc +memchr +memcmp +memcpy +memmove +memset +mktime +modf +perror +pow +printf +putc +putchar +puts +putwc +putwchar +qsort +raise +rand +realloc +remove +rename +rewind +scanf +setbuf +setlocale +setvbuf +signal +sin +sinh +sprintf +sqrt +srand +sscanf +strcat +strchr +strcmp +strcoll +strcpy +strcspn +strerror +strftime +strlen +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtod +strtok +strtol +strtoul +strxfrm +swprintf +swscanf +system +tan +tanh +time +tmpfile +tmpnam +tolower +toupper +towlower +towupper +ungetc +ungetwc +vfprintf +vfwprintf +vprintf +vsprintf +vswprintf +vwprintf +wcscat +wcschr +wcscmp +wcscoll +wcscpy +wcscspn +wcsftime +wcslen +wcsncat +wcsncmp +wcsncpy +wcspbrk +wcsrchr +wcsspn +wcsstr +wcstod +wcstok +wcstol +; wcstombs +wcstoul +wcsxfrm +; wctomb +wprintf +wscanf + +; EOF diff --git a/lib/msvcrt/msvcrt.rc b/lib/msvcrt/msvcrt.rc new file mode 100644 index 0000000..efb5c31 --- /dev/null +++ b/lib/msvcrt/msvcrt.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "MSVCRT.DLL Compatibility Library\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "msvcrt\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "msvcrt.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/lib/msvcrt/process/.cvsignore b/lib/msvcrt/process/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/process/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/process/_cwait.c b/lib/msvcrt/process/_cwait.c new file mode 100644 index 0000000..d4df111 --- /dev/null +++ b/lib/msvcrt/process/_cwait.c @@ -0,0 +1,32 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/process/cwait.c + * PURPOSE: Waits for a process to exit + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 04/03/99: Created + */ +#include +#include +#include +#include + +int _cwait(int* pnStatus, int hProc, int nAction) +{ + DWORD ExitCode; + + nAction = 0; + if (WaitForSingleObject((void *)hProc,INFINITE) != WAIT_OBJECT_0) + { + __set_errno(ECHILD); + return -1; + } + + if (!GetExitCodeProcess((void *)hProc,&ExitCode)) + return -1; + if (pnStatus != NULL) + *pnStatus = (int)ExitCode; + CloseHandle((HANDLE)hProc); + return hProc; +} diff --git a/lib/msvcrt/process/_system.c b/lib/msvcrt/process/_system.c new file mode 100644 index 0000000..ef72256 --- /dev/null +++ b/lib/msvcrt/process/_system.c @@ -0,0 +1,121 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/process/system.c + * PURPOSE: Excutes a shell command + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 04/03/99: Created + */ +#include +#include +#include +#include +#include + +int system(const char *command) +{ + char *szCmdLine = NULL; + char *szComSpec = NULL; + + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + char *s; + BOOL result; + + int nStatus; + + szComSpec = getenv("COMSPEC"); + +// system should return 0 if command is null and the shell is found + + if (command == NULL) + { + if (szComSpec == NULL) + return 0; + else + { + free(szComSpec); + return -1; + } + } + +// should return 127 or 0 ( MS ) if the shell is not found +// __set_errno(ENOENT); + + if (szComSpec == NULL) + { + szComSpec = strdup("cmd.exe"); + if (szComSpec == NULL) + { + __set_errno(ENOMEM); + return -1; + } + } + + s = max(strchr(szComSpec, '\\'), strchr(szComSpec, '/')); + if (s == NULL) + s = szComSpec; + else + s++; + + szCmdLine = malloc(strlen(s) + 4 + strlen(command) + 1); + if (szCmdLine == NULL) + { + free (szComSpec); + __set_errno(ENOMEM); + return -1; + } + + strcpy(szCmdLine, s); + s = strrchr(szCmdLine, '.'); + if (s) + *s = 0; + strcat(szCmdLine, " /C "); + strcat(szCmdLine, command); + +//command file has invalid format ENOEXEC + + memset (&StartupInfo, 0, sizeof(STARTUPINFO)); + StartupInfo.cb = sizeof(STARTUPINFO); + StartupInfo.lpReserved= NULL; + StartupInfo.dwFlags = 0; + StartupInfo.wShowWindow = SW_SHOWDEFAULT; + StartupInfo.lpReserved2 = NULL; + StartupInfo.cbReserved2 = 0; + +// According to ansi standards the new process should ignore SIGINT and SIGQUIT +// In order to disable ctr-c the process is created with CREATE_NEW_PROCESS_GROUP, +// thus SetConsoleCtrlHandler(NULL,TRUE) is made on behalf of the new process. + + +//SIGCHILD should be blocked aswell + + result = CreateProcessA(szComSpec, + szCmdLine, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + free(szCmdLine); + free(szComSpec); + + if (result == FALSE) + { + __set_errno(ENOEXEC); + return -1; + } + + CloseHandle(ProcessInformation.hThread); + +// system should wait untill the calling process is finished + _cwait(&nStatus,(int)ProcessInformation.hProcess,0); + CloseHandle(ProcessInformation.hProcess); + + return nStatus; +} diff --git a/lib/msvcrt/process/dll.c b/lib/msvcrt/process/dll.c new file mode 100644 index 0000000..ccb3c2a --- /dev/null +++ b/lib/msvcrt/process/dll.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/process/dll.c + * PURPOSE: Dll support routines + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 04/03/99: Created + */ + +#include +#include + +void *_loaddll (char *name) +{ + return LoadLibraryA(name); +} + +int _unloaddll(void *handle) +{ + return FreeLibrary(handle); +} + +FARPROC _getdllprocaddr(void *hModule,char * lpProcName, int iOrdinal) +{ + if ( lpProcName != NULL ) + return GetProcAddress(hModule, lpProcName); + else + return GetProcAddress(hModule, (LPSTR)iOrdinal); + return (NULL); +} diff --git a/lib/msvcrt/process/process.c b/lib/msvcrt/process/process.c new file mode 100644 index 0000000..d9cdc52 --- /dev/null +++ b/lib/msvcrt/process/process.c @@ -0,0 +1,478 @@ +/* $Id$ */ +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +extern int maxfno; + +static char* +argvtos(char* const* argv, char delim) +{ + int i, len; + char *ptr, *str; + + if (argv == NULL) + return NULL; + + for (i = 0, len = 0; argv[i]; i++) + { + len += strlen(argv[i]) + 1; + } + + str = ptr = (char*) malloc(len + 1); + if (str == NULL) + return NULL; + + for(i = 0; argv[i]; i++) + { + len = strlen(argv[i]); + memcpy(ptr, argv[i], len); + ptr += len; + *ptr++ = delim; + } + *ptr = 0; + + return str; +} + +static char* +valisttos(const char* arg0, va_list alist, char delim) +{ + va_list alist2 = alist; + char *ptr, *str; + int len; + + if (arg0 == NULL) + return NULL; + + ptr = (char*)arg0; + len = 0; + do + { + len += strlen(ptr) + 1; + ptr = va_arg(alist, char*); + } + while(ptr != NULL); + + str = (char*) malloc(len + 1); + if (str == NULL) + return NULL; + + ptr = str; + do + { + len = strlen(arg0); + memcpy(ptr, arg0, len); + *ptr++ = delim; + arg0 = va_arg(alist2, char*); + } + while(arg0 != NULL); + *ptr = 0; + + return str; +} + +static int +do_spawn(int mode, const char* cmdname, const char* args, const char* envp) +{ + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + char* fmode; + HANDLE* hFile; + int i, last; + BOOL bResult; + DWORD dwExitCode; + DWORD dwError; + + DPRINT("do_spawn('%s')\n", cmdname); + + if (mode != _P_NOWAIT && mode != _P_NOWAITO && mode != _P_WAIT && mode != _P_DETACH && mode != _P_OVERLAY) + { + errno = EINVAL; + return -1; + } + + if (0 != _access(cmdname, F_OK)) + { + errno = ENOENT; + return -1; + } + if (0 == _access(cmdname, D_OK)) + { + errno = EISDIR; + return -1; + } + + memset (&StartupInfo, 0, sizeof(STARTUPINFO)); + StartupInfo.cb = sizeof(STARTUPINFO); + + for (last = i = 0; i < maxfno; i++) + { + if ((void*)-1 != _get_osfhandle(i)) + { + last = i + 1; + } + } + + if (last) + { + StartupInfo.cbReserved2 = sizeof(ULONG) + last * (sizeof(char) + sizeof(HANDLE)); + StartupInfo.lpReserved2 = malloc(StartupInfo.cbReserved2); + if (StartupInfo.lpReserved2 == NULL) + { + errno = ENOMEM; + return -1; + } + + *(DWORD*)StartupInfo.lpReserved2 = last; + fmode = (char*)(StartupInfo.lpReserved2 + sizeof(ULONG)); + hFile = (HANDLE*)(StartupInfo.lpReserved2 + sizeof(ULONG) + last * sizeof(char)); + for (i = 0; i < last; i++) + { + int _mode = __fileno_getmode(i); + HANDLE h = _get_osfhandle(i); + /* FIXME: The test of console handles (((ULONG)Handle) & 0x10000003) == 0x3) + * is possible wrong + */ + if ((((ULONG)h) & 0x10000003) == 0x3 || _mode & _O_NOINHERIT || (i < 3 && mode == _P_DETACH)) + { + *hFile = INVALID_HANDLE_VALUE; + *fmode = 0; + } + else + { + DWORD dwFlags; + BOOL bFlag; + bFlag = GetHandleInformation(h, &dwFlags); + if (bFlag && (dwFlags & HANDLE_FLAG_INHERIT)) + { + *hFile = h; + *fmode = (_O_ACCMODE & _mode) | (((_O_TEXT | _O_BINARY) & _mode) >> 8); + } + else + { + *hFile = INVALID_HANDLE_VALUE; + *fmode = 0; + } + fmode++; + hFile++; + } + } + } + + bResult = CreateProcessA((char *)cmdname, + (char *)args, + NULL, + NULL, + TRUE, + mode == _P_DETACH ? DETACHED_PROCESS : 0, + (LPVOID)envp, + NULL, + &StartupInfo, + &ProcessInformation); + if (StartupInfo.lpReserved2) + { + free(StartupInfo.lpReserved2); + } + + if (!bResult) + { + dwError = GetLastError(); + DPRINT("%x\n", dwError); + __set_errno(dwError); + return -1; + } + CloseHandle(ProcessInformation.hThread); + switch(mode) + { + case _P_OVERLAY: + _exit(0); + case _P_WAIT: + WaitForSingleObject(ProcessInformation.hProcess, INFINITE); + GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode); + CloseHandle(ProcessInformation.hProcess); + return (int)dwExitCode; + case _P_DETACH: + CloseHandle(ProcessInformation.hProcess); + return 0; + } + return (int)ProcessInformation.hProcess; +} + +int _spawnl(int mode, const char *cmdname, const char* arg0, ...) +{ + va_list argp; + char* args; + int ret = -1; + + DPRINT("_spawnl('%s')\n", cmdname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + + if (args) + { + ret = do_spawn(mode, cmdname, args, NULL); + free(args); + } + return ret; +} + +int _spawnv(int mode, const char *cmdname, char* const* argv) +{ + char* args; + int ret = -1; + + DPRINT("_spawnv('%s')\n", cmdname); + + args = argvtos(argv, ' '); + + if (args) + { + ret = do_spawn(mode, cmdname, args, NULL); + free(args); + } + return ret; +} + +int _spawnle(int mode, const char *cmdname, const char* arg0, ... /*, NULL, const char* const* envp*/) +{ + va_list argp; + char* args; + char* envs; + char* const* ptr; + int ret = -1; + + DPRINT("_spawnle('%s')\n", cmdname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + do + { + ptr = (char* const*)va_arg(argp, char*); + } + while (ptr != NULL); + envs = argvtos(ptr, 0); + if (args) + { + ret = do_spawn(mode, cmdname, args, envs); + free(args); + } + if (envs) + { + free(envs); + } + return ret; + +} + +int _spawnve(int mode, const char *cmdname, char* const* argv, char* const* envp) +{ + char *args; + char *envs; + int ret = -1; + + DPRINT("_spawnve('%s')\n", cmdname); + + args = argvtos(argv, ' '); + envs = argvtos(envp, 0); + + if (args) + { + ret = do_spawn(mode, cmdname, args, envs); + free(args); + } + if (envs) + { + free(envs); + } + return ret; +} + +int _spawnvp(int mode, const char* cmdname, char* const* argv) +{ + char pathname[FILENAME_MAX]; + + DPRINT("_spawnvp('%s')\n", cmdname); + + _searchenv(cmdname, "PATH", pathname); + + return _spawnv(mode, pathname[0] ? pathname : cmdname, argv); +} + +int _spawnlpe(int mode, const char* cmdname, const char* arg0, .../*, NULL, const char* const* envp*/) +{ + va_list argp; + char* args; + char* envs; + char* const * ptr; + int ret = -1; + char pathname[FILENAME_MAX]; + + DPRINT("_spawnlpe('%s')\n", cmdname); + + _searchenv(cmdname, "PATH", pathname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + do + { + ptr = (char* const*)va_arg(argp, char*); + } + while (ptr != NULL); + envs = argvtos(ptr, 0); + if (args) + { + ret = do_spawn(mode, pathname[0] ? pathname : cmdname, args, envs); + free(args); + } + if (envs) + { + free(envs); + } + return ret; +} + +int _spawnvpe(int mode, const char* cmdname, char* const* argv, char* const* envp) +{ + char pathname[FILENAME_MAX]; + + DPRINT("_spawnvpe('%s')\n", cmdname); + + _searchenv(cmdname, "PATH", pathname); + + return _spawnve(mode, pathname[0] ? pathname : cmdname, argv, envp); +} + +int _execl(const char* cmdname, const char* arg0, ...) +{ + char* args; + va_list argp; + int ret = -1; + + DPRINT("_execl('%s')\n", cmdname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + + if (args) + { + ret = do_spawn(P_OVERLAY, cmdname, args, NULL); + free(args); + } + return ret; +} + +int _execv(const char* cmdname, char* const* argv) +{ + DPRINT("_execv('%s')\n", cmdname); + return _spawnv(P_OVERLAY, cmdname, argv); +} + +int _execle(const char* cmdname, const char* arg0, ... /*, NULL, char* const* envp */) +{ + va_list argp; + char* args; + char* envs; + char* const* ptr; + int ret = -1; + + DPRINT("_execle('%s')\n", cmdname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + do + { + ptr = (char* const*)va_arg(argp, char*); + } + while (ptr != NULL); + envs = argvtos((char**)ptr, 0); + if (args) + { + ret = do_spawn(P_OVERLAY, cmdname, args, envs); + free(args); + } + if (envs) + { + free(envs); + } + return ret; +} + +int _execve(const char* cmdname, char* const* argv, char* const* envp) +{ + DPRINT("_execve('%s')\n", cmdname); + return _spawnve(P_OVERLAY, cmdname, argv, envp); +} + +int _execlp(const char* cmdname, const char* arg0, ...) +{ + char* args; + va_list argp; + int ret = -1; + char pathname[FILENAME_MAX]; + + DPRINT("_execlp('%s')\n", cmdname); + + _searchenv(cmdname, "PATH", pathname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + + if (args) + { + ret = do_spawn(P_OVERLAY, pathname[0] ? pathname : cmdname, args, NULL); + free(args); + } + return ret; +} + +int _execvp(const char* cmdname, char* const* argv) +{ + DPRINT("_execvp('%s')\n", cmdname); + return _spawnvp(P_OVERLAY, cmdname, argv); +} + +int _execlpe(const char* cmdname, const char* arg0, ... /*, NULL, char* const* envp */) +{ + va_list argp; + char* args; + char* envs; + char* const* ptr; + int ret = -1; + char pathname[FILENAME_MAX]; + + DPRINT("_execlpe('%s')\n", cmdname); + + _searchenv(cmdname, "PATH", pathname); + + va_start(argp, arg0); + args = valisttos(arg0, argp, ' '); + do + { + ptr = (char* const*)va_arg(argp, char*); + } + while (ptr != NULL); + envs = argvtos(ptr, 0); + if (args) + { + ret = do_spawn(P_OVERLAY, pathname[0] ? pathname : cmdname, args, envs); + free(args); + } + if (envs) + { + free(envs); + } + return ret; +} + +int _execvpe(const char* cmdname, char* const* argv, char* const* envp) +{ + DPRINT("_execvpe('%s')\n", cmdname); + return _spawnvpe(P_OVERLAY, cmdname, argv, envp); +} diff --git a/lib/msvcrt/process/procid.c b/lib/msvcrt/process/procid.c new file mode 100644 index 0000000..a8616fb --- /dev/null +++ b/lib/msvcrt/process/procid.c @@ -0,0 +1,8 @@ +#include +#include + +int _getpid (void) +{ + return (int)GetCurrentProcessId(); +} + diff --git a/lib/msvcrt/process/thread.c b/lib/msvcrt/process/thread.c new file mode 100644 index 0000000..4692b40 --- /dev/null +++ b/lib/msvcrt/process/thread.c @@ -0,0 +1,45 @@ +/* $Id$ + * + */ +#include +#include +#include + +unsigned long +_beginthread ( + void ( __cdecl * start_address ) (void *), + unsigned stack_size, + void * arglist + ) +{ + errno = ENOSYS; + return (unsigned long) -1; +} + + +unsigned long +_beginthreadex ( + void * security, + unsigned stack_size, + unsigned ( __stdcall * start_address ) (void *), + void * arglist, + unsigned initflag, + unsigned * thrdaddr + ) +{ + errno = ENOSYS; + return (unsigned long) -1; +} + + +void _endthread (void) +{ +} + + +void _endthreadex (unsigned retval) +{ +} + + +/* EOF */ diff --git a/lib/msvcrt/process/threadid.c b/lib/msvcrt/process/threadid.c new file mode 100644 index 0000000..bd97858 --- /dev/null +++ b/lib/msvcrt/process/threadid.c @@ -0,0 +1,12 @@ +#include +#include + +unsigned long __threadid (void) +{ + return GetCurrentThreadId(); +} + +void *__threadhandle(void) +{ + return GetCurrentThread(); +} diff --git a/lib/msvcrt/search/.cvsignore b/lib/msvcrt/search/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/search/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/search/lfind.c b/lib/msvcrt/search/lfind.c new file mode 100644 index 0000000..210a149 --- /dev/null +++ b/lib/msvcrt/search/lfind.c @@ -0,0 +1,19 @@ +#include +#include + + +void *_lfind(const void *key, const void *base, size_t *nelp, + size_t width, int (*compar)(const void *, const void *)) +{ + char *char_base = (char *)base; + int i; + + for (i=0;i<*nelp;i++) + { + if (compar(key,char_base) == 0) + return char_base; + char_base += width; + } + return NULL; +} + diff --git a/lib/msvcrt/search/lsearch.c b/lib/msvcrt/search/lsearch.c new file mode 100644 index 0000000..a1ada3f --- /dev/null +++ b/lib/msvcrt/search/lsearch.c @@ -0,0 +1,17 @@ +#include +#include +#include + +void *_lsearch(const void *key, void *base, size_t *nelp, size_t width, + int (*compar)(const void *, const void *)) +{ + void *ret_find = _lfind(key,base,nelp,width,compar); + + if (ret_find != NULL) + return ret_find; + + memcpy(base + (*nelp*width), key, width); + (*nelp)++; + return base; +} + diff --git a/lib/msvcrt/setjmp/.cvsignore b/lib/msvcrt/setjmp/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/setjmp/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/setjmp/setjmp.c b/lib/msvcrt/setjmp/setjmp.c new file mode 100644 index 0000000..65a7050 --- /dev/null +++ b/lib/msvcrt/setjmp/setjmp.c @@ -0,0 +1,137 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* modified by Boudewijn Dekker */ +/* ms uses a smaller jmp_buf structure */ +/* might do a realloc in setjmp */ + +typedef struct { + unsigned int __eax, __ebx, __ecx, __edx, __esi; + unsigned int __edi, __ebp, __esp, __eip, __eflags; + unsigned short __cs, __ds, __es, __fs, __gs, __ss; + unsigned long __sigmask; /* for POSIX signals only */ + unsigned long __signum; /* for expansion */ + unsigned long __exception_ptr; /* pointer to previous exception */ + unsigned char __fpu_state[108]; /* for future use */ +} jmp_buf[1]; + + +/* jumps back to position specified in jmp_buf */ + +int longjmp( jmp_buf env, int value ) +{ + //push ebp generated by the compiler + //mov ebp, esp + + __asm__ __volatile__ ( + "movl 8(%ebp),%edi\n\t" /* get jmp_buf */ + "movl 12(%ebp),%eax\n\t" /* store retval in j->eax */ + "movl %eax,0(%edi)\n\t" + + "movw 46(%edi),%fs\n\t" + "movw 48(%edi),%gs\n\t" + "movl 4(%edi),%ebx\n\t" + "movl 8(%edi),%ecx\n\t" + "movl 12(%edi),%edx\n\t" + "movl 24(%edi),%ebp\n\t" + + /* Now for some uglyness. The jmp_buf structure may be ABOVE the + point on the new SS:ESP we are moving to. We don't allow overlap, + but do force that it always be valid. We will use ES:ESI for + our new stack before swapping to it. */ + + "movw 50(%edi),%es\n\t" + "movl 28(%edi),%esi\n\t" + "subl $28,%esi\n\t" /* We need 7 working longwords on stack */ + + "movl 60(%edi),%eax\n\t" + "es\n\t" + "movl %eax,(%esi)\n\t" /* Exception pointer */ + + "movzwl 42(%edi),%eax\n\t" + "es\n\t" + "movl %eax,4(%esi)\n\t" /* DS */ + + "movl 20(%edi),%eax\n\t" + "es\n\t" + "movl %eax,8(%esi)\n\t" /* EDI */ + + "movl 16(%edi),%eax\n\t" + "es\n\t" + "movl %eax,12(%esi)\n\t" /* ESI */ + + "movl 32(%edi),%eax\n\t" + "es\n\t" + "movl %eax,16(%esi)\n\t" /* EIP - start of IRET frame */ + + "movl 40(%edi),%eax\n\t" + "es\n\t" + "movl %eax,20(%esi)\n\t" /* CS */ + + "movl 36(%edi),%eax\n\t" + "es\n\t" + "movl %eax,24(%esi)\n\t" /* EFLAGS */ + + "movl 0(%edi),%eax\n\t" + "movw 44(%edi),%es\n\t" + + "movw 50(%edi),%ss\n\t" + "movl %esi,%esp\n\t" + + //"popl ___djgpp_exception_state_ptr\n\t" + "popl %edi\n\t" // dummy popl instead of djgpp_exception_state_ptr + "popl %ds\n\t" + "popl %edi\n\t" + "popl %esi\n\t" + + "iret\n\t" /* actually jump to new cs:eip loading flags */ + ); + + return value; // dummy return never reached +} + + +int _setjmp( jmp_buf env ) +{ + //push ebp generated by the compiler + //mov ebp, esp + + __asm__ __volatile__ ( + "pushl %edi\n\t" + "movl 8(%ebp),%edi\n\t" + + "movl %eax, (%edi)\n\t" + "movl %ebx,4(%edi)\n\t" + "movl %ecx,8(%edi)\n\t" + "movl %edx,12(%edi)\n\t" + "movl %esi,16(%edi)\n\t" + + "movl -4(%ebp),%eax\n\t" + "movl %eax,20(%edi)\n\t" + + "movl (%ebp),%eax\n\t" + "movl %eax,24(%edi)\n\t" + + "movl %esp,%eax\n\t" + "addl $12,%eax\n\t" + "movl %eax,28(%edi)\n\t" + + "movl 4(%ebp),%eax\n\t" + "movl %eax,32(%edi)\n\t" + + "pushfl\n\t" + "popl 36(%edi)\n\t" + + "movw %cs, 40(%edi)\n\t" + "movw %ds, 42(%edi)\n\t" + "movw %es, 44(%edi)\n\t" + "movw %fs, 46(%edi)\n\t" + "movw %gs, 48(%edi)\n\t" + "movw %ss, 50(%edi)\n\t" + + //movl ___djgpp_exception_state_ptr, %eax + //movl %eax, 60(%edi) + + "popl %edi\n\t" + ); + + return 0; +} diff --git a/lib/msvcrt/signal/.cvsignore b/lib/msvcrt/signal/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/signal/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/signal/signal.c b/lib/msvcrt/signal/signal.c new file mode 100644 index 0000000..69d90a6 --- /dev/null +++ b/lib/msvcrt/signal/signal.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +void _default_handler(int signal); + +typedef struct _sig_element +{ + int signal; + char *signame; + _p_sig_fn_t handler; +} sig_element; + +static sig_element signal_list[SIGMAX] = + { + { 0, "Signal 0", SIG_DFL }, + { SIGABRT, "Aborted",SIG_DFL }, + { SIGFPE, "Erroneous arithmetic operation",SIG_DFL }, + { SIGILL, "Illegal instruction",SIG_DFL }, + { SIGINT, "Interrupt",SIG_DFL }, + { SIGSEGV, "Invalid access to storage",SIG_DFL }, + { SIGTERM, "Terminated",SIG_DFL }, + { SIGHUP, "Hangup",SIG_DFL }, + { SIGQUIT, "Quit",SIG_DFL }, + { SIGPIPE, "Broken pipe",SIG_DFL }, + { SIGKILL, "Killed",SIG_DFL }, + { SIGALRM, "Alarm clock",SIG_DFL }, + { 0, "Stopped (signal)",SIG_DFL }, + { 0, "Stopped",SIG_DFL }, + { 0, "Continued",SIG_DFL }, + { 0, "Child exited",SIG_DFL }, + { 0, "Stopped (tty input)",SIG_DFL }, + { 0, "Stopped (tty output)",SIG_DFL }, + { 0, NULL, SIG_DFL } + }; + +int nsignal = 21; + +_p_sig_fn_t signal(int sig, _p_sig_fn_t func) +{ + _p_sig_fn_t temp; + int i; + if(sig <= 0 || sig > SIGMAX || sig == SIGKILL) + { + __set_errno(EINVAL); + return SIG_ERR; + } +// check with IsBadCodePtr + + if ( func < (_p_sig_fn_t)4096 ) { + __set_errno(EINVAL); + return SIG_ERR; + } + + for(i=0;i SIGMAX) + return -1; + for(i=0;i +#include +#include +#include + + +FILE * __alloc_file(void); + +char __validfp (FILE *f) +{ + if ( (unsigned int)f < 256) + return FALSE; + + if( f == NULL || (int)f== -1 ) + return FALSE; + + return TRUE; +} + +/* A FILE* is considered "free" if its flag is zero. */ + +FILE *__alloc_file(void) +{ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + FILE *rv=0; + int i; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) + { + if (fr->files[i]->_flag == 0) + { + return fr->files[i]; + } + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + if (!fr) + { + /* add another one to the end, make it empty */ + fr = *last_fr = (__file_rec *)malloc(sizeof(__file_rec)); + if (fr == 0) + return 0; + fr->next = 0; + fr->count = 0; + } + /* fr is a pointer to a rec with empty slots in it */ + rv = fr->files[fr->count] = (FILE *)malloc(sizeof(FILE)); + if (rv == 0) + return 0; + memset(rv, 0, sizeof(FILE)); + fr->count ++; + return rv; +} + + +int _fcloseall( void ) +{ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + + int total_closed = 0; + int i = 0; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) + if (fr->files[i]->_flag != 0) { + fclose(fr->files[i]); + total_closed++; + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + return total_closed; +} diff --git a/lib/msvcrt/stdio/clearerr.c b/lib/msvcrt/stdio/clearerr.c new file mode 100644 index 0000000..5055fa7 --- /dev/null +++ b/lib/msvcrt/stdio/clearerr.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +#ifdef clearerr +#undef clearerr +void clearerr(FILE *stream); +#endif + +void +clearerr(FILE *f) +{ + if (!__validfp (f)) { + __set_errno (EINVAL); + return; + } + f->_flag &= ~(_IOERR|_IOEOF); +} diff --git a/lib/msvcrt/stdio/fclose.c b/lib/msvcrt/stdio/fclose.c new file mode 100644 index 0000000..74b3b0c --- /dev/null +++ b/lib/msvcrt/stdio/fclose.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + +// changed check for writable stream + + +int +fclose(FILE *f) +{ + int r = 0; + + if (f == NULL) { + __set_errno (EINVAL); + return EOF; + } + + + +// flush only if stream was opened for writing + if ( !(f->_flag&_IOSTRG) ) { + if ( OPEN4WRITING(f) ) + r = fflush(f); + + if (_close(fileno(f)) < 0) + r = EOF; + if (f->_flag&_IOMYBUF) + free(f->_base); + +// Kernel might do this later + if (f->_flag & _IORMONCL && f->_name_to_remove) + { + remove(f->_name_to_remove); + free(f->_name_to_remove); + f->_name_to_remove = 0; + } + } + f->_cnt = 0; + f->_base = 0; + f->_ptr = 0; + f->_bufsiz = 0; + f->_flag = 0; + f->_file = -1; + return r; +} diff --git a/lib/msvcrt/stdio/fdopen.c b/lib/msvcrt/stdio/fdopen.c new file mode 100644 index 0000000..a9f70cc --- /dev/null +++ b/lib/msvcrt/stdio/fdopen.c @@ -0,0 +1,102 @@ +#include +#include + +FILE * __alloc_file(void); + +FILE *_fdopen(int handle, char *mode) +{ + FILE *file; + int rw; + + if (handle == 0) + return stdin; + + if (handle == 1) + return stdout; + + if (handle == 2) + return stderr; + + if (handle == 3) + return stdaux; + + if (handle == 4) + return stdprn; + + file = __alloc_file(); + if (file == NULL) + return NULL; + file->_file = handle; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + if (*mode == 'a') + _lseek(handle, 0, SEEK_END); + + file->_cnt = 0; + file->_file = handle; + file->_bufsiz = 0; + +// The mode of the stream must be compatible with the mode of the file descriptor. +// this should be checked. + + if (rw) + file->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + file->_flag = _IOREAD; + else + file->_flag = _IOWRT; + + file->_base = file->_ptr = NULL; + + return file; +} + +FILE *_wfdopen(int handle, wchar_t *mode) +{ + FILE *file; + int rw; + + if (handle == 0) + return stdin; + + if (handle == 1) + return stdout; + + if (handle == 2) + return stderr; + + if (handle == 3) + return stdaux; + + if (handle == 4) + return stdprn; + + file = __alloc_file(); + if (file == NULL) + return NULL; + file->_file = handle; + + rw = (mode[1] == L'+') || (mode[1] && (mode[2] == L'+')); + + if (*mode == L'a') + _lseek(handle, 0, SEEK_END); + + file->_cnt = 0; + file->_file = handle; + file->_bufsiz = 0; + +// The mode of the stream must be compatible with the mode of the file descriptor. +// this should be checked. + + if (rw) + file->_flag = _IOREAD | _IOWRT; + else if (*mode == L'r') + file->_flag = _IOREAD; + else + file->_flag = _IOWRT; + + file->_base = file->_ptr = NULL; + + return file; +} diff --git a/lib/msvcrt/stdio/feof.c b/lib/msvcrt/stdio/feof.c new file mode 100644 index 0000000..a2487d8 --- /dev/null +++ b/lib/msvcrt/stdio/feof.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +#ifdef feof +#undef feof +int feof(FILE *stream); +#endif + +int feof(FILE *stream) +{ + if (stream == NULL) { + __set_errno (EINVAL); + return EOF; + } + + return stream->_flag & _IOEOF; +} diff --git a/lib/msvcrt/stdio/ferror.c b/lib/msvcrt/stdio/ferror.c new file mode 100644 index 0000000..05110cd --- /dev/null +++ b/lib/msvcrt/stdio/ferror.c @@ -0,0 +1,13 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#ifdef ferror +#undef ferror +int ferror(FILE *stream); +#endif + +int ferror(FILE *stream) +{ + return stream->_flag & _IOERR; +} diff --git a/lib/msvcrt/stdio/fflush.c b/lib/msvcrt/stdio/fflush.c new file mode 100644 index 0000000..7848bb3 --- /dev/null +++ b/lib/msvcrt/stdio/fflush.c @@ -0,0 +1,111 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + + +int fflush(FILE *f) +{ + char *base; + int n, rn; + + + + if (f == NULL) + { + int e = errno; + + __set_errno(0); + _fwalk((void (*)(FILE *))fflush); + if (_errno) + return EOF; + __set_errno(e); + return 0; + } + + +// nothing to do if stream can not be written to + + if ( !OPEN4WRITING(f) ) { + __set_errno (EINVAL); + return 0; + } + +// discard any unget characters + + f->_flag &= ~_IOUNGETC; + + +// check for buffered dirty block + + if ( (f->_flag&(_IODIRTY|_IONBF)) ==_IODIRTY && f->_base != NULL) + { + + base = f->_base; + + +// if the buffer is read ahead and dirty we will flush it entirely +// else the buffer is appended to the file to the extend it has valid bytes + + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + rn = n = f->_ptr - base + f->_cnt; + else + rn = n = f->_ptr - base; + + f->_ptr = base; + + if ((f->_flag & _IOFBF) == _IOFBF) { + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + _lseek(fileno(f),-rn, SEEK_CUR); + } + + f->_flag &= ~_IOAHEAD; + + + f->_cnt = (f->_flag&(_IOLBF|_IONBF)) ? 0 : f->_bufsiz; + +// how can write return less than rn without being on error ??? + +// possibly commit the flushed data +// better open the file in write through mode + + while (rn > 0) { + n = _write(fileno(f), base, rn); + if (n <= 0) { + f->_flag |= _IOERR; + return EOF; + } + rn -= n; + base += n; + }; + f->_flag &= ~_IODIRTY; + + } + if (OPEN4READING(f) && OPEN4WRITING(f) ) + { + f->_cnt = 0; + f->_ptr = f->_base; + } + return 0; +} + +int _flushall( void ) +{ + return fflush(NULL); +} diff --git a/lib/msvcrt/stdio/fgetc.c b/lib/msvcrt/stdio/fgetc.c new file mode 100644 index 0000000..7ce598c --- /dev/null +++ b/lib/msvcrt/stdio/fgetc.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdio/fgetc.c + * PURPOSE: Get a character string from stdin + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Appropriated for Reactos + 25/02/99: Added fgetwc + */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int fgetc(FILE *f) +{ + return getc(f); +} + +wint_t fgetwc(FILE *f) +{ + return getwc(f); +} diff --git a/lib/msvcrt/stdio/fgetchar.c b/lib/msvcrt/stdio/fgetchar.c new file mode 100644 index 0000000..a80ce3a --- /dev/null +++ b/lib/msvcrt/stdio/fgetchar.c @@ -0,0 +1,12 @@ +#include +#include + +int _fgetchar(void) +{ + return _getch(); +} + +int _fgetwchar(void) +{ + return _getch(); +} diff --git a/lib/msvcrt/stdio/fgetpos.c b/lib/msvcrt/stdio/fgetpos.c new file mode 100644 index 0000000..82c4bf5 --- /dev/null +++ b/lib/msvcrt/stdio/fgetpos.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int fgetpos(FILE *stream, fpos_t *pos) +{ + if (stream && pos) + { + *pos = (fpos_t)ftell(stream); + return 0; + } + //errno = EFAULT; + return 1; +} diff --git a/lib/msvcrt/stdio/fgets.c b/lib/msvcrt/stdio/fgets.c new file mode 100644 index 0000000..3230fc5 --- /dev/null +++ b/lib/msvcrt/stdio/fgets.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +fgets(char *s, int n, FILE *f) +{ + int c=0; + char *cs; + + cs = s; + while (--n>0 && (c = getc(f)) != EOF) + { + *cs++ = c; + if (c == '\n') + break; + } + if (c == EOF && cs == s) + return NULL; + *cs++ = '\0'; + return s; +} diff --git a/lib/msvcrt/stdio/filbuf.c b/lib/msvcrt/stdio/filbuf.c new file mode 100644 index 0000000..5033a60 --- /dev/null +++ b/lib/msvcrt/stdio/filbuf.c @@ -0,0 +1,131 @@ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int _readcnv(int fn, void *buf, size_t siz ); + +int +_filbuf(FILE *f) +{ + int size; + char c; + + + if ( !OPEN4READING(f)) { + __set_errno (EINVAL); + return EOF; + } + + + if (f->_flag&(_IOSTRG|_IOEOF)) + return EOF; + f->_flag &= ~_IOUNGETC; + + if (f->_base==NULL && (f->_flag&_IONBF)==0) { + size = 4096; + if ((f->_base = malloc(size+1)) == NULL) + { + // error ENOMEM + f->_flag |= _IONBF; + f->_flag &= ~(_IOFBF|_IOLBF); + } + else + { + f->_flag |= _IOMYBUF; + f->_bufsiz = size; + } + } + + + if (f->_flag&_IONBF) + f->_base = &c; + + +// fush stdout before reading from stdin + if (f == stdin) { + if (stdout->_flag&_IOLBF) + fflush(stdout); + if (stderr->_flag&_IOLBF) + fflush(stderr); + } + +// if we have a dirty stream we flush it + if ( (f->_flag &_IODIRTY) == _IODIRTY ) + fflush(f); + + + + f->_cnt = _read(fileno(f), f->_base, f->_flag & _IONBF ? 1 : f->_bufsiz ); + f->_flag |= _IOAHEAD; + + if(__is_text_file(f) && f->_cnt>0) + { + /* truncate text file at Ctrl-Z */ + char *cz=memchr(f->_base, 0x1A, f->_cnt); + if(cz) + { + int newcnt = cz - f->_base; + lseek(fileno(f), -(f->_cnt - newcnt), SEEK_CUR); + f->_cnt = newcnt; + } + } + + f->_ptr = f->_base; + + if (f->_flag & _IONBF) + f->_base = NULL; // statically allocated buffer for sprintf + + +//check for error + if (f->_cnt <= 0) { + if (f->_cnt == 0) { + f->_flag |= _IOEOF; + } else + f->_flag |= _IOERR; + f->_cnt = 0; + +// should set errno + + return EOF; + } + + f->_cnt--; + return *f->_ptr++ & 0377; +} + +wint_t _filwbuf(FILE *fp) +{ + return (wint_t )_filbuf(fp); +} + +// convert the carriage return line feed pairs + +int _readcnv(int fn, void *buf, size_t siz ) +{ + char *bufp = (char *)buf; + int _bufsiz = siz; + int cr = 0; + int n; + + n = _read(fn, buf, siz ); + + while (_bufsiz > 0) { + if (*bufp == '\r') + cr++; + else if ( cr != 0 ) + *bufp = *(bufp + cr); + bufp++; + _bufsiz--; + } + return n + cr; +} + diff --git a/lib/msvcrt/stdio/fileno.c b/lib/msvcrt/stdio/fileno.c new file mode 100644 index 0000000..50019c0 --- /dev/null +++ b/lib/msvcrt/stdio/fileno.c @@ -0,0 +1,14 @@ +#include + +#if 0 +#undef fileno +int fileno(FILE *f) +{ + return f->_file; +} +#endif + +int _fileno(FILE *f) +{ + return f->_file; +} diff --git a/lib/msvcrt/stdio/flsbuf.c b/lib/msvcrt/stdio/flsbuf.c new file mode 100644 index 0000000..4af1ee9 --- /dev/null +++ b/lib/msvcrt/stdio/flsbuf.c @@ -0,0 +1,179 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include +#include + +int cntcr(char *bufp, int bufsiz); +int convert(char *endp, int bufsiz,int n); +int _writecnv(int fn, void *buf, size_t bufsiz); + +int +_flsbuf(int c, FILE *f) +{ + char *base; + int n, rn; + char c1; + int size; + + + + if (!OPEN4WRITING(f)) { + __set_errno (EINVAL); + return EOF; + } + +// no file associated with buffer +// this is a memory stream + + if ( fileno(f) == -1 ) + return c; + + /* if the buffer is not yet allocated, allocate it */ + if ((base = f->_base) == NULL && (f->_flag & _IONBF) == 0) + { + size = 4096; + if ((f->_base = base = malloc (size)) == NULL) + { + f->_flag |= _IONBF; + f->_flag &= ~(_IOFBF|_IOLBF); + } + else + { + f->_flag |= _IOMYBUF; + f->_cnt = f->_bufsiz = size; + f->_ptr = base; + rn = 0; + if (f == stdout && isatty (fileno (stdout))) + f->_flag |= _IOLBF; + } + } + + if (f->_flag & _IOLBF) + { + /* in line-buffering mode we get here on each character */ + *f->_ptr++ = c; + rn = f->_ptr - base; + if (c == '\n' || rn >= f->_bufsiz) + { + /* time for real flush */ + f->_ptr = base; + f->_cnt = 0; + } + else + { + /* we got here because _cnt is wrong, so fix it */ + /* Negative _cnt causes all output functions + to call _flsbuf for each character, thus realizing line-buffering */ + f->_cnt = -rn; + return c; + } + } + else if (f->_flag & _IONBF) + { + c1 = c; + rn = 1; + base = &c1; + f->_cnt = 0; + } + else /* _IOFBF */ + { + rn = f->_ptr - base; + f->_ptr = base; + if ( (f->_flag & _IOAHEAD) == _IOAHEAD ) + _lseek(fileno(f),-(rn+f->_cnt), SEEK_CUR); + f->_cnt = f->_bufsiz; + f->_flag &= ~_IOAHEAD; + } + + + + f->_flag &= ~_IODIRTY; + while (rn > 0) + { + n = _write(fileno(f), base, rn); + if (n <= 0) + { + f->_flag |= _IOERR; + return EOF; + } + rn -= n; + base += n; + } + + + if ((f->_flag&(_IOLBF|_IONBF)) == 0) + { + f->_cnt--; + *f->_ptr++ = c; + } + return c; +} + +wint_t _flswbuf(wchar_t c,FILE *fp) +{ + return (wint_t )_flsbuf((int)c,fp); +} + + +int _writecnv(int fn, void *buf, size_t siz) +{ + char *bufp = (char *)buf; + int bufsiz = siz; + + char *tmp; + int cr1 = 0; + int cr2 = 0; + + int n; + + + cr1 = cntcr(bufp,bufsiz); + + tmp = malloc(cr1); + memcpy(tmp,bufp+bufsiz-cr1,cr1); + cr2 = cntcr(tmp,cr1); + + convert(bufp,bufsiz-cr2,cr1-cr2); + n = _write(fn, bufp, bufsiz + cr1); + + convert(tmp,cr1,cr2); + n += _write(fn, tmp, cr1 + cr2); + free(tmp); + return n; + + +} + +int convert(char *endp, int bufsiz,int n) +{ + endp = endp + bufsiz + n; + while (bufsiz > 0) { + *endp = *(endp - n); + if (*endp == '\n') { + *endp--; + n--; + *endp = '\r'; + } + endp--; + bufsiz--; + } + return n; +} +int cntcr(char *bufp, int bufsiz) +{ + int cr = 0; + while (bufsiz > 0) { + if (*bufp == '\n') + cr++; + bufp++; + bufsiz--; + } + + return cr; +} diff --git a/lib/msvcrt/stdio/fopen.c b/lib/msvcrt/stdio/fopen.c new file mode 100644 index 0000000..def102f --- /dev/null +++ b/lib/msvcrt/stdio/fopen.c @@ -0,0 +1,145 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +//#include + +//might change fopen(file,mode) -> fsopen(file,mode,_SH_DENYNO); + +#undef _fmode +extern unsigned int _fmode; + +FILE * __alloc_file(void); + + +FILE* fopen(const char *file, const char *mode) +{ + FILE *f; + int fd, rw, oflags = 0; + char tbchar; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + switch (*mode) + { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _open(file, oflags, 0); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} + +FILE* _wfopen(const wchar_t *file, const wchar_t *mode) +{ + FILE *f; + int fd, rw, oflags = 0; + wchar_t tbchar; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == L'+') || (mode[1] && (mode[2] == L'+')); + + switch (*mode) + { + case L'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case L'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case L'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == L'+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == L't') + oflags |= O_TEXT; + else if (tbchar == L'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _wopen(file, oflags, 0); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == L'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == L'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/lib/msvcrt/stdio/fprintf.c b/lib/msvcrt/stdio/fprintf.c new file mode 100644 index 0000000..6c503de --- /dev/null +++ b/lib/msvcrt/stdio/fprintf.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fprintf(register FILE *iop, const char *fmt, ...) +{ + int len; + char localbuf[BUFSIZ]; + va_list a=0; + + + va_start( a, fmt ); + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = localbuf; + iop->_bufsiz = BUFSIZ; + len = vfprintf(iop,fmt,a); + fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = vfprintf(iop, fmt, a); + return ferror(iop) ? EOF : len; +} + +int +fwprintf(register FILE *iop, const wchar_t *fmt, ...) +{ + int len; + wchar_t localbuf[BUFSIZ]; + va_list a=0; + + + va_start( a, fmt ); + if (iop->_flag & _IONBF) + { + iop->_flag &= ~_IONBF; + iop->_ptr = iop->_base = (char *)localbuf; + iop->_bufsiz = BUFSIZ; + len = vfwprintf(iop,fmt,a); + fflush(iop); + iop->_flag |= _IONBF; + iop->_base = NULL; + iop->_bufsiz = 0; + iop->_cnt = 0; + } + else + len = vfwprintf(iop, fmt, a); + return ferror(iop) ? EOF : len; +} diff --git a/lib/msvcrt/stdio/fputc.c b/lib/msvcrt/stdio/fputc.c new file mode 100644 index 0000000..a5c6761 --- /dev/null +++ b/lib/msvcrt/stdio/fputc.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int +fputc(int c, FILE *fp) +{ + return putc(c, fp); +} + +wint_t +fputwc(wchar_t c, FILE *fp) +{ + return putwc(c,fp); +} + diff --git a/lib/msvcrt/stdio/fputchar.c b/lib/msvcrt/stdio/fputchar.c new file mode 100644 index 0000000..46d4eb5 --- /dev/null +++ b/lib/msvcrt/stdio/fputchar.c @@ -0,0 +1,14 @@ +#include +#include + + +int _fputchar(int c) +{ + return _putch(c); +} + +int _fputwchar(wchar_t c) +{ + //return _putch(c); + return 0; +} diff --git a/lib/msvcrt/stdio/fputs.c b/lib/msvcrt/stdio/fputs.c new file mode 100644 index 0000000..d39672b --- /dev/null +++ b/lib/msvcrt/stdio/fputs.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +fputs(const char *s, FILE *f) +{ + int r = 0; + int c; + int unbuffered; + char localbuf[BUFSIZ]; + + unbuffered = f->_flag & _IONBF; + if (unbuffered) + { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = localbuf; + f->_bufsiz = BUFSIZ; + } + + while ((c = *s++)) + r = putc(c, f); + + if (unbuffered) + { + fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } + + return(r); +} diff --git a/lib/msvcrt/stdio/fread.c b/lib/msvcrt/stdio/fread.c new file mode 100644 index 0000000..d5f3369 --- /dev/null +++ b/lib/msvcrt/stdio/fread.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include + + +size_t fread(void *vptr, size_t size, size_t count, FILE *iop) +{ + unsigned char *ptr = (unsigned char *)vptr; + size_t to_read ,n_read; + int c, copy; + + to_read = size * count; + + if (!OPEN4READING(iop)) + { + __set_errno (EINVAL); + return 0; + } + + if (!__validfp (iop) ) + { + __set_errno (EINVAL); + return 0; + } + if (feof (iop) || ferror (iop)) + return 0; + + if (vptr == NULL || to_read == 0) + return 0; + + if (iop->_base == NULL) + { + int c = _filbuf(iop); + if (c == EOF) + return 0; + *ptr++ = c; + if (--to_read == 0) + return 1; + } + + if (iop->_cnt > 0 && to_read > 0) + { + copy = min(iop->_cnt, to_read); + memcpy(ptr, iop->_ptr, copy); + ptr += copy; + iop->_ptr += copy; + iop->_cnt -= copy; + to_read -= copy; + if (to_read == 0) + return count; + } + + if (to_read > 0) + { + + if (to_read >= iop->_bufsiz) + { + n_read = _read(fileno(iop), ptr, to_read); + if (n_read < 0) + iop->_flag |= _IOERR; + else if (n_read == 0) + iop->_flag |= _IOEOF; + else + to_read -= n_read; + + // the file buffer is empty and there is no read ahead information anymore. + iop->_flag &= ~_IOAHEAD; + } + else + { + c = _filbuf(iop); + if (c != EOF) + { + *ptr++ = c; + to_read--; + copy = min(iop->_cnt, to_read); + memcpy(ptr, iop->_ptr, copy); + iop->_ptr += copy; + iop->_cnt -= copy; + to_read -= copy; + } + } + } + return count - (to_read/size); +} diff --git a/lib/msvcrt/stdio/freopen.c b/lib/msvcrt/stdio/freopen.c new file mode 100644 index 0000000..f6f14fd --- /dev/null +++ b/lib/msvcrt/stdio/freopen.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include + + +FILE *freopen(const char *file, const char *mode, FILE *f) +{ + int fd, rw, oflags=0; + char tbchar; + + if (file == 0 || mode == 0 || f == 0) + return 0; + + rw = (mode[1] == '+'); + + fclose(f); + + switch (*mode) { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return NULL; + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _open(file, oflags, 0666); + if (fd < 0) + return NULL; + + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} + +FILE *_wfreopen(const wchar_t *file, const wchar_t *mode, FILE *f) +{ + int fd, rw, oflags=0; + wchar_t tbchar; + + if (file == 0 || mode == 0 || f == 0) + return 0; + + rw = (mode[1] == L'+'); + + fclose(f); + + switch (*mode) { + case L'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case L'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case L'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return NULL; + } + if (mode[1] == L'+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == L't') + oflags |= O_TEXT; + else if (tbchar == L'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + fd = _wopen(file, oflags, 0666); + if (fd < 0) + return NULL; + + if (*mode == L'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == L'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/lib/msvcrt/stdio/fscanf.c b/lib/msvcrt/stdio/fscanf.c new file mode 100644 index 0000000..0187334 --- /dev/null +++ b/lib/msvcrt/stdio/fscanf.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +#include +#include +#include +#include +#include + + +/* Read formatted input from STREAM according to the format string FORMAT. */ +/* VARARGS2 */ +int fscanf(FILE *stream,const char *format, ...) +{ + va_list arg; + int done; + + va_start(arg, format); + done = __vfscanf(stream, format, arg); + va_end(arg); + + return done; +} + +int +fwscanf(FILE *stream, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + char *cf; + int i,len = wcslen(fmt); + + cf = malloc(len+1); + for(i=0;i +#include +#include +#include +#include + + +int fseek(FILE *f, long offset, int ptrname) +{ + long p = -1; /* can't happen? */ + if ( f == NULL ) { + __set_errno (EINVAL); + return -1; + } + + f->_flag &= ~_IOEOF; + if (!OPEN4WRITING(f)) + { + if (f->_base && !(f->_flag & _IONBF)) + { + p = ftell(f); + if (ptrname == SEEK_CUR) + { + offset += p; + ptrname = SEEK_SET; + } + /* check if the target position is in the buffer and + optimize seek by moving inside the buffer */ + if (ptrname == SEEK_SET && (f->_flag & (_IOUNGETC|_IOREAD|_IOWRT )) == 0 + && p-offset <= f->_ptr-f->_base && offset-p <= f->_cnt) + { + f->_ptr+=offset-p; + f->_cnt+=p-offset; + return 0; + } + } + + p = lseek(fileno(f), offset, ptrname); + f->_cnt = 0; + f->_ptr = f->_base; + f->_flag &= ~_IOUNGETC; + } + else + { + p = fflush(f); + return lseek(fileno(f), offset, ptrname) == -1 || p == EOF ? + -1 : 0; + } + return p==-1 ? -1 : 0; +} diff --git a/lib/msvcrt/stdio/fsetpos.c b/lib/msvcrt/stdio/fsetpos.c new file mode 100644 index 0000000..eb48557 --- /dev/null +++ b/lib/msvcrt/stdio/fsetpos.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +int fsetpos(FILE *stream,const fpos_t *pos) +{ + if (stream && pos) + { + fseek(stream, (long)(*pos), SEEK_SET); + return 0; + } + __set_errno(EFAULT); + return -1; +} diff --git a/lib/msvcrt/stdio/fsopen.c b/lib/msvcrt/stdio/fsopen.c new file mode 100644 index 0000000..0b36507 --- /dev/null +++ b/lib/msvcrt/stdio/fsopen.c @@ -0,0 +1,177 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/kbhit.c + * PURPOSE: Checks for keyboard hits + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +#include + + +FILE * __alloc_file(void); + + +FILE* _fsopen(const char *file, const char *mode, int shflag) +{ + FILE *f; + int fd, rw, oflags = 0; + char tbchar; + + int shf; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == '+') || (mode[1] && (mode[2] == '+')); + + switch (*mode) + { + case 'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case 'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case 'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == '+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == 't') + oflags |= O_TEXT; + else if (tbchar == 'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + if ( shflag == _SH_DENYNO ) + shf = _S_IREAD | _S_IWRITE; + else if( shflag == _SH_DENYRD ) + shf = _S_IWRITE; + else if( shflag == _SH_DENYRW ) + shf = 0; + else if( shflag == _SH_DENYWR ) + shf = _S_IREAD; + else + shf = _S_IREAD | _S_IWRITE; + + fd = _open(file, oflags, shf); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == 'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == 'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} + +FILE* _wfsopen(const wchar_t *file, const wchar_t *mode, int shflag) +{ + FILE *f; + int fd, rw, oflags = 0; + wchar_t tbchar; + + int shf; + + if (file == 0) + return 0; + if (mode == 0) + return 0; + + f = __alloc_file(); + if (f == NULL) + return NULL; + + rw = (mode[1] == L'+') || (mode[1] && (mode[2] == L'+')); + + switch (*mode) + { + case L'a': + oflags = O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + case L'r': + oflags = rw ? O_RDWR : O_RDONLY; + break; + case L'w': + oflags = O_TRUNC | O_CREAT | (rw ? O_RDWR : O_WRONLY); + break; + default: + return (NULL); + } + if (mode[1] == L'+') + tbchar = mode[2]; + else + tbchar = mode[1]; + if (tbchar == L't') + oflags |= O_TEXT; + else if (tbchar == L'b') + oflags |= O_BINARY; + else + oflags |= (_fmode & (O_TEXT|O_BINARY)); + + if ( shflag == _SH_DENYNO ) + shf = _S_IREAD | _S_IWRITE; + else if( shflag == _SH_DENYRD ) + shf = _S_IWRITE; + else if( shflag == _SH_DENYRW ) + shf = 0; + else if( shflag == _SH_DENYWR ) + shf = _S_IREAD; + else + shf = _S_IREAD | _S_IWRITE; + + fd = _wopen(file, oflags, shf); + if (fd < 0) + return NULL; + +// ms crtdll ensures that writes will end up at the end of file in append mode +// we just move the file pointer to the end of file initially + if (*mode == L'a') + lseek(fd, 0, SEEK_END); + + f->_cnt = 0; + f->_file = fd; + f->_bufsiz = 0; + if (rw) + f->_flag = _IOREAD | _IOWRT; + else if (*mode == L'r') + f->_flag = _IOREAD; + else + f->_flag = _IOWRT; + + f->_base = f->_ptr = NULL; + return f; +} diff --git a/lib/msvcrt/stdio/ftell.c b/lib/msvcrt/stdio/ftell.c new file mode 100644 index 0000000..bb48673 --- /dev/null +++ b/lib/msvcrt/stdio/ftell.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +//#include +#include +#include +#include +#include + + +long ftell(FILE *f) +{ + long tres; + int adjust=0; + + if (!f) + { + __set_errno(EBADF); + return -1; + } + + if (f->_cnt < 0) + f->_cnt = 0; + else if (f->_flag&(_IOWRT)) + { + if (f->_base && (f->_flag&_IONBF)==0) + adjust = f->_ptr - f->_base; + } + else if (f->_flag&_IOREAD) + { + adjust = - f->_cnt; + } + else + return -1; + + tres = lseek(fileno(f), 0L, SEEK_CUR); + if (tres<0) + return tres; + tres += adjust; + + //f->_cnt = f->_bufsiz - tres; + //f->_ptr = f->_base + tres; + + return tres; +} diff --git a/lib/msvcrt/stdio/fwalk.c b/lib/msvcrt/stdio/fwalk.c new file mode 100644 index 0000000..f7d261b --- /dev/null +++ b/lib/msvcrt/stdio/fwalk.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +// not exported by crtdll +__file_rec *__file_rec_list; + +void +_fwalk(void (*func)(FILE *)) +{ + __file_rec *fr; + int i; + + for (fr=__file_rec_list; fr; fr=fr->next) + for (i=0; icount; i++) + if (fr->files[i]->_flag) + func(fr->files[i]); +} diff --git a/lib/msvcrt/stdio/fwrite.c b/lib/msvcrt/stdio/fwrite.c new file mode 100644 index 0000000..c5f573e --- /dev/null +++ b/lib/msvcrt/stdio/fwrite.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#define NDEBUG +#include + + +size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop) +{ + size_t to_write, n_written; + unsigned char *ptr = (unsigned char *)vptr; + int copy; + + DPRINT("fwrite(%x, %d, %d, %x)\n", vptr, size, count, iop); + + to_write = size*count; + if (!OPEN4WRITING(iop)) + { + __set_errno (EINVAL); + return 0; + } + + if (iop == NULL) + { + __set_errno (EINVAL); + return 0; + } + + if (ferror (iop)) + return 0; + if (vptr == NULL || to_write == 0) + return 0; + + if (iop->_base == NULL && !(iop->_flag&_IONBF)) + { + if (EOF == _flsbuf(*ptr++, iop)) + return 0; + if (--to_write == 0) + return 1; + } + + if (iop->_flag & _IOLBF) + { + while (to_write > 0) + { + if (EOF == putc(*ptr++, iop)) + { + iop->_flag |= _IOERR; + break; + } + to_write--; + } + } + else + { + if (iop->_cnt > 0 && to_write > 0) + { + copy = min(iop->_cnt, to_write); + memcpy(iop->_ptr, ptr, copy); + ptr += copy; + iop->_ptr += copy; + iop->_cnt -= copy; + to_write -= copy; + iop->_flag |= _IODIRTY; + } + + if (to_write > 0) + { + // if the buffer is dirty it will have to be written now + // otherwise the file pointer won't match anymore. + fflush(iop); + if (to_write >= iop->_bufsiz) + { + while (to_write > 0) + { + n_written = _write(fileno(iop), ptr, to_write); + if (n_written <= 0) + { + iop->_flag |= _IOERR; + break; + } + to_write -= n_written; + ptr += n_written; + } + + // check to see if this will work with in combination with ungetc + + // the file buffer is empty and there is no read ahead information anymore. + iop->_flag &= ~_IOAHEAD; + } + else + { + if (EOF != _flsbuf(*ptr++, iop)) + { + if (--to_write > 0) + { + memcpy(iop->_ptr, ptr, to_write); + iop->_ptr += to_write; + iop->_cnt -= to_write; + iop->_flag |= _IODIRTY; + return count; + } + } + } + } + } + + return count - (to_write/size); +} diff --git a/lib/msvcrt/stdio/getc.c b/lib/msvcrt/stdio/getc.c new file mode 100644 index 0000000..3bdb61c --- /dev/null +++ b/lib/msvcrt/stdio/getc.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include + +//getc can be a macro +#undef getc + +int getc(FILE *fp) +{ + int c = -1; +// check for invalid stream + + if ( !__validfp (fp) ) { + __set_errno(EINVAL); + return EOF; + } +// check for read access on stream + + if ( !OPEN4READING(fp) ) { + __set_errno(EINVAL); + return -1; + } + + if(fp->_cnt > 0) { + fp->_cnt--; + c = (int)*fp->_ptr++; + } + else { + c = _filbuf(fp); + } + return c; +} + +wint_t getwc(FILE *fp) +{ + int c = -1; + + // check for invalid stream + if (!__validfp(fp)) + { + __set_errno(EINVAL); + return EOF; + } + + // check for read access on stream + if (!OPEN4READING(fp)) + { + __set_errno(EINVAL); + return -1; + } + + // might check on multi bytes if text mode + + if (fp->_cnt > 0) + { + fp->_cnt -= sizeof(wchar_t); + c = (wint_t )*((wchar_t *)(fp->_ptr))++; + } + else + { + c = _filwbuf(fp); + } + return c; +} + + + + diff --git a/lib/msvcrt/stdio/getchar.c b/lib/msvcrt/stdio/getchar.c new file mode 100644 index 0000000..14392d2 --- /dev/null +++ b/lib/msvcrt/stdio/getchar.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#undef getchar +int +getchar(void) +{ + return getc(stdin); +} diff --git a/lib/msvcrt/stdio/gets.c b/lib/msvcrt/stdio/gets.c new file mode 100644 index 0000000..ac97420 --- /dev/null +++ b/lib/msvcrt/stdio/gets.c @@ -0,0 +1,106 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdio/gets.c + * PURPOSE: Get a character string from stdin + * PROGRAMER: DJ Delorie + * UPDATE HISTORY: + * 28/12/98: Appropriated for Reactos + */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char *gets(char *s) +{ + int c; + char *cs; + + cs = s; + while ((c = getchar()) != '\n' && c != EOF) + *cs++ = c; + if (c == EOF && cs==s) + return NULL; + *cs++ = '\0'; + return s; +} + +#if 0 +/* Copyright (C) 1991, 1994, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +link_warning (gets, "the `gets' function is dangerous and should not be used.") + + +/* Read a newline-terminated multibyte string from stdin into S, + removing the trailing newline. Return S or NULL. */ + +char * +gets (s) + char *s; +{ + register char *p = s; + register int c; + FILE *stream = stdin; + int l; + + if (!__validfp (stream) || p == NULL) + { + __set_errno (EINVAL); + return NULL; + } + + if (feof (stream) || ferror (stream)) + return NULL; + + while ((c = getc(stdin)) != EOF) { + if (c == '\n') + break; + if ( isascii(c) ) + *cs++ = c; +#ifdef _MULTIBYTE + else if ( isleadbyte(c) ) { + l = mblen(c); + while(l > 0 ) { + c = getchar(); + if ( isleadbyte(c) || c == EOF ) + return NULL; // encoding error + *cs++ = c; + l--; + } + } +#endif + else + return NULL; // suspicious input + } + + *p = '\0'; + + /* Return null if we had an error, or if we got EOF + before writing any characters. */ + + if (ferror (stream) || (feof (stream) && p == s)) + return NULL; + + return s; +} + +#endif diff --git a/lib/msvcrt/stdio/getw.c b/lib/msvcrt/stdio/getw.c new file mode 100644 index 0000000..119d4e1 --- /dev/null +++ b/lib/msvcrt/stdio/getw.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + +/* Read a word (int) from STREAM. */ +int _getw(FILE *stream) +{ + int w; + + /* Is there a better way? */ + if (fread( &w, sizeof(w), 1, stream) != 1) + return(EOF); + return(w); +} diff --git a/lib/msvcrt/stdio/perror.c b/lib/msvcrt/stdio/perror.c new file mode 100644 index 0000000..7606a1e --- /dev/null +++ b/lib/msvcrt/stdio/perror.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +#ifdef perror +#undef perror +void perror(const char *s); +#endif + +void perror(const char *s) +{ + fprintf(stderr, "%s: %s\n", s, _strerror(NULL)); +} + +void _wperror(const wchar_t *s) +{ + fwprintf(stderr, L"%s: %S\n", s, _strerror(NULL)); +} diff --git a/lib/msvcrt/stdio/popen.c b/lib/msvcrt/stdio/popen.c new file mode 100644 index 0000000..5e0e1e2 --- /dev/null +++ b/lib/msvcrt/stdio/popen.c @@ -0,0 +1,227 @@ +/* $Id$ */ +#include +#include +#include +#include +#include +#include +#include +#define NDEBUG +#include + + +FILE *_popen (const char *cm, const char *md) /* program name, pipe mode */ +{ + char *szCmdLine=NULL; + char *szComSpec=NULL; + char *s; + FILE *pf; + HANDLE hReadPipe, hWritePipe; + BOOL result; + STARTUPINFOA StartupInfo; + PROCESS_INFORMATION ProcessInformation; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + + DPRINT("_popen('%s', '%s')\n", cm, md); + + if (cm == NULL) + return NULL; + + szComSpec = getenv("COMSPEC"); + + if (szComSpec == NULL) + { + szComSpec = strdup("cmd.exe"); + if (szComSpec == NULL) + return NULL; + } + + s = max(strrchr(szComSpec, '\\'), strrchr(szComSpec, '/')); + if (s == NULL) + s = szComSpec; + else + s++; + + szCmdLine = malloc(strlen(s) + 4 + strlen(cm) + 1); + if (szCmdLine == NULL) + { + free (szComSpec); + return NULL; + } + + strcpy(szCmdLine, s); + s = strrchr(szCmdLine, '.'); + if (s) + *s = 0; + strcat(szCmdLine, " /C "); + strcat(szCmdLine, cm); + + if ( !CreatePipe(&hReadPipe,&hWritePipe,&sa,1024)) + { + free (szComSpec); + free (szCmdLine); + return NULL; + } + + memset(&StartupInfo, 0, sizeof(STARTUPINFOA)); + StartupInfo.cb = sizeof(STARTUPINFOA); + + if (*md == 'r' ) { + StartupInfo.hStdOutput = hWritePipe; + StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + } + else if ( *md == 'w' ) { + StartupInfo.hStdInput = hReadPipe; + StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + } + + result = CreateProcessA(szComSpec, + szCmdLine, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + free (szComSpec); + free (szCmdLine); + + if (result == FALSE) + { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + return NULL; + } + + CloseHandle(ProcessInformation.hThread); + + if ( *md == 'r' ) + { + pf = _fdopen(__fileno_alloc(hReadPipe, _fmode) , "r"); + CloseHandle(hWritePipe); + } + else + { + pf = _fdopen( __fileno_alloc(hWritePipe, _fmode) , "w"); + CloseHandle(hReadPipe); + } + + pf->_name_to_remove = ProcessInformation.hProcess; + + return pf; +} + + +int _pclose (FILE *pp) +{ + fclose(pp); + if (!TerminateProcess(pp->_name_to_remove,0)) + return -1; + return 0; +} + + +FILE *_wpopen (const wchar_t *cm, const wchar_t *md) /* program name, pipe mode */ +{ + wchar_t *szCmdLine=NULL; + wchar_t *szComSpec=NULL; + wchar_t *s; + FILE *pf; + HANDLE hReadPipe, hWritePipe; + BOOL result; + STARTUPINFOW StartupInfo; + PROCESS_INFORMATION ProcessInformation; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + + DPRINT("_wpopen('%S', '%S')\n", cm, md); + + if (cm == NULL) + return NULL; + + szComSpec = _wgetenv(L"COMSPEC"); + + if (szComSpec == NULL) + { + szComSpec = _wcsdup(L"cmd.exe"); + if (szComSpec == NULL) + return NULL; + } + + s = max(wcsrchr(szComSpec, L'\\'), wcsrchr(szComSpec, L'/')); + if (s == NULL) + s = szComSpec; + else + s++; + + szCmdLine = malloc((wcslen(s) + 4 + wcslen(cm) + 1) * sizeof(wchar_t)); + if (szCmdLine == NULL) + { + free (szComSpec); + return NULL; + } + + wcscpy(szCmdLine, s); + s = wcsrchr(szCmdLine, L'.'); + if (s) + *s = 0; + wcscat(szCmdLine, L" /C "); + wcscat(szCmdLine, cm); + + if ( !CreatePipe(&hReadPipe,&hWritePipe,&sa,1024)) + { + free (szComSpec); + free (szCmdLine); + return NULL; + } + + memset(&StartupInfo, 0, sizeof(STARTUPINFOW)); + StartupInfo.cb = sizeof(STARTUPINFOW); + + if (*md == L'r' ) { + StartupInfo.hStdOutput = hWritePipe; + StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + } + else if ( *md == L'w' ) { + StartupInfo.hStdInput = hReadPipe; + StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + } + + result = CreateProcessW(szComSpec, + szCmdLine, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + free (szComSpec); + free (szCmdLine); + + if (result == FALSE) + { + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); + return NULL; + } + + CloseHandle(ProcessInformation.hThread); + + if ( *md == L'r' ) + { + pf = _wfdopen(__fileno_alloc(hReadPipe, _fmode) , L"r"); + CloseHandle(hWritePipe); + } + else + { + pf = _wfdopen( __fileno_alloc(hWritePipe, _fmode) , L"w"); + CloseHandle(hReadPipe); + } + + pf->_name_to_remove = ProcessInformation.hProcess; + + return pf; +} diff --git a/lib/msvcrt/stdio/printf.c b/lib/msvcrt/stdio/printf.c new file mode 100644 index 0000000..36cd1ae --- /dev/null +++ b/lib/msvcrt/stdio/printf.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +/* Write formatted output to stdout from the format string FORMAT. */ +/* VARARGS1 */ +int +printf (const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vprintf (format, arg); + va_end (arg); + return done; +} + +int +wprintf (const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = vwprintf (format, arg); + va_end (arg); + return done; +} + +#ifdef USE_IN_LIBIO +# undef _IO_printf +/* This is for libg++. */ +strong_alias (printf, _IO_printf); +#endif + diff --git a/lib/msvcrt/stdio/putc.c b/lib/msvcrt/stdio/putc.c new file mode 100644 index 0000000..62f31ce --- /dev/null +++ b/lib/msvcrt/stdio/putc.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + +// putc can be a macro +#undef putc + +int putc(int c, FILE *fp) +{ + +// valid stream macro should check that fp +// is dword aligned + if (!__validfp (fp)) { + __set_errno(EINVAL); + return -1; + } +// check for write access on fp + + if ( !OPEN4WRITING(fp) ) { + __set_errno(EINVAL); + return -1; + } + + fp->_flag |= _IODIRTY; + if (fp->_cnt > 0 ) { + fp->_cnt--; + *(fp)->_ptr++ = (unsigned char)c; + return (int)(unsigned char)c; + } + else { + return _flsbuf((unsigned char)c,fp); + } + return EOF; +} + +wint_t putwc(wint_t c, FILE *fp) +{ +// valid stream macro should check that fp +// is dword aligned + if (!__validfp (fp)) { + __set_errno(EINVAL); + return -1; + } +// check for write access on fp + + if ( !OPEN4WRITING(fp) ) { + __set_errno(EINVAL); + return -1; + } + // might check on multi bytes if text mode + + fp->_flag |= _IODIRTY; + + if (fp->_cnt > 0 ) { + fp->_cnt-= sizeof(wchar_t); + *((wchar_t *)(fp->_ptr))++ = c; + return (wint_t)c; + } + else + return _flswbuf(c,fp); + + return -1; + + +} diff --git a/lib/msvcrt/stdio/putchar.c b/lib/msvcrt/stdio/putchar.c new file mode 100644 index 0000000..cc85051 --- /dev/null +++ b/lib/msvcrt/stdio/putchar.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/getch.c + * PURPOSE: Writes a character to stdout + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include + +#undef putc +#undef putchar + +int putchar(int c) +{ + int r = putc(c, stdout); + if (stdout->_flag & _IOLBF) + fflush(stdout); + return r; +} + +wint_t putwchar(wint_t c) +{ + wint_t r = putwc(c, stdout); + if (stdout->_flag & _IOLBF) + fflush(stdout); + return r; +} diff --git a/lib/msvcrt/stdio/puts.c b/lib/msvcrt/stdio/puts.c new file mode 100644 index 0000000..443a36b --- /dev/null +++ b/lib/msvcrt/stdio/puts.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +#undef putchar +int +puts(const char *s) +{ + + int c; + while ((c = *s++)) + putchar(c); + return putchar('\n'); + +} + +int +_putws(const wchar_t *s) +{ + + wint_t c; + while ((c = *s++)) + putwchar(c); + return putwchar(L'\n'); + +} diff --git a/lib/msvcrt/stdio/putw.c b/lib/msvcrt/stdio/putw.c new file mode 100644 index 0000000..9495126 --- /dev/null +++ b/lib/msvcrt/stdio/putw.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU C Library; see the file COPYING.LIB. If + * not, write to the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge, MA 02139, USA. */ + + +#include + + +/* Write the word (int) W to STREAM. */ +int _putw(int w,FILE *stream) +{ + /* Is there a better way? */ + if (fwrite( &w, sizeof(w), 1, stream) < 1) + return(EOF); + return(0); +} diff --git a/lib/msvcrt/stdio/remove.c b/lib/msvcrt/stdio/remove.c new file mode 100644 index 0000000..5f309af --- /dev/null +++ b/lib/msvcrt/stdio/remove.c @@ -0,0 +1,24 @@ +#include +#include +#include + +#define NDEBUG +#include + +int remove(const char *fn) +{ + int result = 0; + DPRINT("remove('%s')\n", fn); + if (!DeleteFileA(fn)) + result = -1; + DPRINT("%d\n", result); + return result; +} + +int _wremove(const wchar_t *fn) +{ + DPRINT("_wremove('%S')\n", fn); + if (!DeleteFileW(fn)) + return -1; + return 0; +} diff --git a/lib/msvcrt/stdio/rename.c b/lib/msvcrt/stdio/rename.c new file mode 100644 index 0000000..6139cf7 --- /dev/null +++ b/lib/msvcrt/stdio/rename.c @@ -0,0 +1,27 @@ +#include +#include +#include + + +int rename(const char *old_, const char *new_) +{ + if (old_ == NULL || new_ == NULL) + return -1; + + if (!MoveFileA(old_,new_)) + return -1; + + return 0; +} + +int _wrename(const wchar_t *old_, const wchar_t *new_) +{ + if (old_ == NULL || new_ == NULL) + return -1; + + if (!MoveFileW(old_,new_)) + return -1; + + return 0; +} + diff --git a/lib/msvcrt/stdio/rewind.c b/lib/msvcrt/stdio/rewind.c new file mode 100644 index 0000000..013e2fc --- /dev/null +++ b/lib/msvcrt/stdio/rewind.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + + +void rewind(FILE *f) +{ + fflush(f); + lseek(fileno(f), 0L, SEEK_SET); + f->_cnt = 0; + f->_ptr = f->_base; + f->_flag &= ~(_IOERR|_IOEOF|_IOAHEAD); +} diff --git a/lib/msvcrt/stdio/rmtmp.c b/lib/msvcrt/stdio/rmtmp.c new file mode 100644 index 0000000..6989447 --- /dev/null +++ b/lib/msvcrt/stdio/rmtmp.c @@ -0,0 +1,72 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdio/rmtmp.c + * PURPOSE: remove temporary files in current directory + * PROGRAMMER: Boudewijn ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 19/01/99 + * NOTE Not tested. + */ + +#include +#include +#include + +#ifndef F_OK + #define F_OK 0x01 +#endif +#ifndef R_OK + #define R_OK 0x02 +#endif +#ifndef W_OK + #define W_OK 0x04 +#endif +#ifndef X_OK + #define X_OK 0x08 +#endif +#ifndef D_OK + #define D_OK 0x10 +#endif + +// should be replace by a closure of the tmp files +extern __file_rec *__file_rec_list; + +int _rmtmp( void ) +{ +/* +loop files and check for name_to_remove +*/ + __file_rec *fr = __file_rec_list; + __file_rec **last_fr = &__file_rec_list; + + int total_closed = 0; + int i = 0; + char temp_name[260]; + + /* Try to find an empty slot */ + while (fr) + { + last_fr = &(fr->next); + + /* If one of the existing slots is available, return it */ + for (i=0; icount; i++) { + if (fr->files[i]->_name_to_remove != NULL) { + if ( _access(fr->files[i]->_name_to_remove,W_OK) ) { + strcpy(temp_name,fr->files[i]->_name_to_remove); + fclose(fr->files[i]); + remove(temp_name); + total_closed++; + } + } + } + + /* If this one is full, go to the next */ + if (fr->count == __FILE_REC_MAX) + fr = fr->next; + else + /* it isn't full, we can add to it */ + break; + } + return total_closed; +} diff --git a/lib/msvcrt/stdio/scanf.c b/lib/msvcrt/stdio/scanf.c new file mode 100644 index 0000000..41462b0 --- /dev/null +++ b/lib/msvcrt/stdio/scanf.c @@ -0,0 +1,58 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include + + +/* Read formatted input from stdin according to the format string FORMAT. */ +/* VARARGS1 */ +int scanf(const char *format, ...) +{ + va_list arg; + int done; + + va_start(arg, format); + done = __vscanf(format, arg); + va_end(arg); + + return done; +} + +int +wscanf(const wchar_t *fmt, ...) +{ + va_list arg; + int done; + char *f; + int i, len = wcslen(fmt); + + f = malloc(len+1); + for(i=0;i +#include +#include + +void setbuf(FILE *f, char *buf) +{ + if (buf) + setvbuf(f, buf, _IOFBF, BUFSIZ); + else + setvbuf(f, 0, _IONBF, BUFSIZ); +} diff --git a/lib/msvcrt/stdio/setvbuf.c b/lib/msvcrt/stdio/setvbuf.c new file mode 100644 index 0000000..2b1d074 --- /dev/null +++ b/lib/msvcrt/stdio/setvbuf.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include + + +int setvbuf(FILE *f, char *buf, int type, size_t len) +{ + int mine=0; + if (!__validfp (f) ) { + __set_errno (EINVAL); + return 0; + } + if ( f->_base != NULL ) + fflush(f); + switch (type) + { + case _IOFBF: + case _IOLBF: + if (len <= 0) { + __set_errno (EINVAL); + return EOF; + } + if (buf == 0) + { + buf = (char *)malloc(len+1); + if (buf == NULL) { + __set_errno (ENOMEM); + return -1; + } + mine = 1; + } + /* FALLTHROUGH */ + case _IONBF: + if (f->_base != NULL && f->_flag & _IOMYBUF) + free(f->_base); + f->_cnt = 0; + + f->_flag &= ~(_IONBF|_IOFBF|_IOLBF|_IOUNGETC); + f->_flag |= type; + if (type != _IONBF) + { + if (mine) + f->_flag |= _IOMYBUF; + f->_ptr = f->_base = buf; + f->_bufsiz = len; + } + else + { + f->_base = 0; + f->_bufsiz = 0; + } + return 0; + default: + __set_errno (EINVAL); + return EOF; + } +} diff --git a/lib/msvcrt/stdio/sprintf.c b/lib/msvcrt/stdio/sprintf.c new file mode 100644 index 0000000..8a27c85 --- /dev/null +++ b/lib/msvcrt/stdio/sprintf.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +/* Copyright (C) 1991, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include + +#undef sprintf +#undef wsprintf +int +sprintf(char *str, const char *fmt, ...) +{ + va_list arg; + int done; + + va_start (arg, fmt); + done = vsprintf (str, fmt, arg); + va_end (arg); + return done; +} + +int +swprintf(wchar_t *str, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + + va_start (arg, fmt); + done = vswprintf (str, fmt, arg); + va_end (arg); + return done; +} + + + +/* Write formatted output into S, according to the format + string FORMAT, writing no more than MAXLEN characters. */ +/* VARARGS3 */ +int +_snprintf (char *s, size_t maxlen,const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _vsnprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} + +int +_snwprintf (wchar_t *s, size_t maxlen,const wchar_t *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = _vsnwprintf (s, maxlen, format, arg); + va_end (arg); + + return done; +} + + diff --git a/lib/msvcrt/stdio/sscanf.c b/lib/msvcrt/stdio/sscanf.c new file mode 100644 index 0000000..2261657 --- /dev/null +++ b/lib/msvcrt/stdio/sscanf.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + + +/* Read formatted input from S, according to the format string FORMAT. */ +/* VARARGS2 */ +int sscanf (const char *s,const char *format, ...) +{ + va_list arg; + int done; + + va_start (arg, format); + done = __vsscanf (s, format, arg); + va_end (arg); + + return done; +} + +int swscanf(const wchar_t *str, const wchar_t *fmt, ...) +{ + va_list arg; + int done; + char *f , *s; + int i,len = wcslen(fmt); + + f = malloc(len+1); + for(i=0;i +#include + +FILE _iob[5] = +{ + // stdin +{ + NULL, 0, NULL, + _IOREAD | _IOLBF , + 0, 0,0, NULL +}, + // stdout +{ + NULL, 0, NULL, + _IOWRT | _IOLBF |_IOSTRG, + 1,0,0, NULL +}, + // stderr +{ + NULL, 0, NULL, + _IOWRT | _IONBF, + 2,0,0, NULL +}, + // stdaux +{ + NULL, 0, NULL, + _IOREAD | _IOWRT | _IONBF, + 3,0,0, NULL +}, + // stdprn +{ + NULL, 0, NULL, + _IOWRT | _IONBF, + 4, 0,0,NULL +} +}; + + + diff --git a/lib/msvcrt/stdio/tempnam.c b/lib/msvcrt/stdio/tempnam.c new file mode 100644 index 0000000..81215eb --- /dev/null +++ b/lib/msvcrt/stdio/tempnam.c @@ -0,0 +1,42 @@ +#include +#include +#include + + +char *_tempnam(const char *dir,const char *prefix ) +{ + char *TempFileName = malloc(MAX_PATH); + char *d; + + if (dir == NULL) + d = getenv("TMP"); + else + d = (char *)dir; + + if (GetTempFileNameA(d, prefix, 1, TempFileName) == 0) + { + free(TempFileName); + return NULL; + } + + return TempFileName; +} + +wchar_t *_wtempnam(const wchar_t *dir,const wchar_t *prefix) +{ + wchar_t *TempFileName = malloc(MAX_PATH); + wchar_t *d; + + if (dir == NULL) + d = _wgetenv(L"TMP"); + else + d = (wchar_t *)dir; + + if (GetTempFileNameW(d, prefix, 1, TempFileName) == 0) + { + free(TempFileName); + return NULL; + } + + return TempFileName; +} diff --git a/lib/msvcrt/stdio/tmpfile.c b/lib/msvcrt/stdio/tmpfile.c new file mode 100644 index 0000000..1e1c116 --- /dev/null +++ b/lib/msvcrt/stdio/tmpfile.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include +//#include +#include +#include +#include + + +FILE * __alloc_file(void); + +FILE * +tmpfile(void) +{ + int temp_fd; + FILE *f; + char *temp_name = tmpnam(0); + char *n_t_r = (char *)malloc(L_tmpnam); + + if (!n_t_r) + return 0; + + /* We could have a race condition, whereby another program + (in another virtual machine, or if the temporary file is + in a directory which is shared via a network) opens the + file returned by `tmpnam' between the call above and the + moment when we actually open the file below. This loop + retries the call to `tmpnam' until we actually succeed + to create the file which didn't exist before. */ + do { + // errno = 0; + temp_fd = _open(temp_name, 0, SH_DENYRW); + // if ( errno == ENOENT ) +// break; + } while (temp_fd == -1 && (temp_name = tmpnam(0)) != 0); + + if (temp_name == 0) + return 0; + + /* This should have been fdopen(temp_fd, "wb+"), but `fdopen' + is non-ANSI. So we need to dump some of its guts here. Sigh... */ + f = __alloc_file(); + if (f) + { + f->_file = temp_fd; + f->_cnt = 0; + f->_bufsiz = 0; + f->_flag = _IORMONCL | _IOREAD | _IOWRT; + f->_name_to_remove = n_t_r; + strcpy(f->_name_to_remove, temp_name); + f->_base = f->_ptr = NULL; + } + else + { + close(temp_fd); + remove(temp_name); + free(n_t_r); + } + return f; +} diff --git a/lib/msvcrt/stdio/tmpnam.c b/lib/msvcrt/stdio/tmpnam.c new file mode 100644 index 0000000..cd16118 --- /dev/null +++ b/lib/msvcrt/stdio/tmpnam.c @@ -0,0 +1,28 @@ +#include +#include +#include + + +char *tmpnam(char *s) +{ + char PathName[MAX_PATH]; + static char static_buf[MAX_PATH]; + + GetTempPathA(MAX_PATH, PathName); + GetTempFileNameA(PathName, "ARI", 007, static_buf); + strcpy(s, static_buf); + + return s; +} + +wchar_t *_wtmpnam(wchar_t *s) +{ + wchar_t PathName[MAX_PATH]; + static wchar_t static_buf[MAX_PATH]; + + GetTempPathW(MAX_PATH, PathName); + GetTempFileNameW(PathName, L"ARI", 007, static_buf); + wcscpy(s, static_buf); + + return s; +} diff --git a/lib/msvcrt/stdio/ungetc.c b/lib/msvcrt/stdio/ungetc.c new file mode 100644 index 0000000..1ef5b43 --- /dev/null +++ b/lib/msvcrt/stdio/ungetc.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int ungetc(int c, FILE *f) +{ + if (!__validfp (f) || !OPEN4READING(f)) + { + __set_errno (EINVAL); + return EOF; + } + + if (c == EOF) + return EOF; + + if (f->_ptr == NULL || f->_base == NULL) + return EOF; + + if (f->_ptr == f->_base) + { + if (f->_cnt == 0) + f->_ptr++; + else + return EOF; + } + + f->_cnt++; + f->_ptr--; + if (*f->_ptr != c) + { + f->_flag |= _IOUNGETC; + *f->_ptr = c; + } + return c; +} + + +wint_t +ungetwc(wchar_t c, FILE *f) +{ + if (!__validfp (f) || !OPEN4READING(f)) + { + __set_errno(EINVAL); + return EOF; + } + + if (c == (wchar_t)EOF) + return EOF; + + if (f->_ptr == NULL || f->_base == NULL) + return EOF; + + if (f->_ptr == f->_base) + { + if (f->_cnt == 0) + f->_ptr+=sizeof(wchar_t); + else + return EOF; + } + + f->_cnt+=sizeof(wchar_t); + f->_ptr-=sizeof(wchar_t); + + f->_flag |= _IOUNGETC; + *((wchar_t *)(f->_ptr)) = c; + + return c; +} diff --git a/lib/msvcrt/stdio/vfprintf.c b/lib/msvcrt/stdio/vfprintf.c new file mode 100644 index 0000000..c24cceb --- /dev/null +++ b/lib/msvcrt/stdio/vfprintf.c @@ -0,0 +1,1077 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int _isnanl(double x); +int _isinfl(double x); +int _isnan(double x); +int _isinf(double x); + + + +int +__vfprintf (FILE *fp, const char *fmt0, va_list args); + +int +vfprintf(FILE *f, const char *fmt, va_list ap) +{ + int len; + char localbuf[BUFSIZ]; + +#if 0 + __fileno_lock(fileno(f)); +#endif + if (f->_flag & _IONBF) + { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = localbuf; + f->_bufsiz = BUFSIZ; + len = __vfprintf(f,fmt, ap); + (void)fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } + else + len = __vfprintf(f,fmt, ap); +#if 0 + __fileno_unlock(fileno(f)); +#endif + return (ferror(f) ? EOF : len); +} + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + + +static int do_div(long long *n,int base) +{ + int __res = ((unsigned long long) *n) % (unsigned) base; + *n = ((unsigned long long) *n) / (unsigned) base; + return __res; +} + + +static int number(FILE * f, long long num, int base, int size, int precision ,int type) +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i, done = 0; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return done; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putc(' ',f) == EOF) + return -1; + done++; + } + if (sign) + { + if (putc(sign,f) == EOF) + return -1; + done++; + } + if (type & SPECIAL) { + if (base==8) { + if (putc('0',f) == EOF) + return -1; + done++; + } + else if (base==16) { + if (putc('0', f) == EOF) + return -1; + done++; + if (putc(digits[33],f) == EOF) + return -1; + done++; + } + } + if (!(type & LEFT)) + while (size-- > 0) + { + if (putc(c,f) == EOF) + return -1; + done++; + } + while (i < precision--) + { + if (putc('0', f) == EOF) + return -1; + done++; + } + while (i-- > 0) + { + if (putc(tmp[i],f) == EOF) + return -1; + done++; + } + while (size-- > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + return done; +} + + +static int numberf(FILE * f, double __n, char exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + char sign; + char c; + char ro = 0; + int result, done = 0; + + double_t *n = (double_t *)&__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type); + if (result < 0) + return -1; + done += result; + if (putc( exp_sign,f) == EOF) + return -1; + done++; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return -1; + done += result; + return done; + } + + if ( exp_sign == 'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modf(intr, &intr); + + p *=10; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putc(' ',f) == EOF) + return -1; + done++; + } + if (sign) + { + if (putc( sign,f) == EOF) + return -1; + done++; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putc(' ',f) == EOF) + return -1; + done++; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + if (putc(c,f) == EOF) + return -1; + done++; + } + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc('0', f); + while (i-- > 0) + { + if (putc(tmp[i],f) == EOF) + return -1; + done++; + } + while (size-- > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + } + return done; +} + + +static int numberfl(FILE * f, long double __n, char exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + char sign; + char c; + char ro = 0; + + int result, done = 0; + + long_double_t *n = (long_double_t *)&__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); + if (result < 0) + return -1; + done += result; + if (putc( exp_sign,f) == EOF) + return -1; + done++; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return -1; + done += result; + return done; + } + + if ( exp_sign == 'f' ) { + + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modfl(intr, &intr); + + p *=10; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putc(' ',f) == EOF) + return -1; + done++; + } + if (sign) + { + if (putc(sign,f) == EOF) + return -1; + done++; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putc(' ',f) == EOF) + return -1; + done++; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + if (putc(c,f) == EOF) + return -1; + done++; + } + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc( '0', f); + while (i-- > 0) + { + if ( putc(tmp[i],f) == EOF) + return -1; + done++; + } + while (size-- > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + } + return done; +} + +static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (s[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + for (i = 0; i < len; ++i) + { + if (putc(*s++, f) == EOF) + return -1; + done++; + } + while (len < field_width--) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + return done; +} + +static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (sw[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + for (i = 0; i < len; ++i) + { + if (putc((unsigned char)(*sw++), f) == EOF) + return -1; + done++; + } + while (len < field_width--) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + return done; +} + +int __vfprintf(FILE *f, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + long double _ldouble; + double _double; + const char *s; + const short int* sw; + int result, done = 0; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + if (putc(*fmt,f) == EOF) + return -1; + done++; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = 0; + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case 'o': + case 'b': + case 'X': + case 'x': + case 'd': + case 'i': + case 'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == 'l' ) { + ++fmt; + qualifier = 'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + if (qualifier == 'l' || qualifier == 'w') + { + if (putc((unsigned char)(wchar_t) va_arg(args, int), f) == EOF) + return -1; + done++; + } + else + { + if (putc((unsigned char) va_arg(args, int), f) == EOF) + return -1; + done++; + } + while (--field_width > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + continue; + + case 'C': + if (!(flags & LEFT)) + while (--field_width > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + if (qualifier == 'h') + { + if (putc((unsigned char) va_arg(args, int), f) == EOF) + return -1; + done++; + } + else + { + if (putc((unsigned char)(wchar_t) va_arg(args, int), f) == EOF) + return -1; + done++; + } + while (--field_width > 0) + { + if (putc(' ', f) == EOF) + return -1; + done++; + } + continue; + + case 's': + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + result = stringw(f, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + result = string(f, s, -1, field_width, precision, flags); + } + if (result < 0) + return -1; + done += result; + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + result = string(f, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + result = stringw(f, sw, -1, field_width, precision, flags); + } + if (result < 0) + return -1; + done += result; + continue; + + case 'Z': + if (qualifier == 'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + len = pus->Length / sizeof(WCHAR); + } + result = stringw(f, sw, len, field_width, precision, flags); + } else { + /* print counted ascii string */ + PANSI_STRING pas = va_arg(args, PANSI_STRING); + if ((pas == NULL) || (pas->Buffer == NULL)) { + s = NULL; + len = -1; + } else { + s = pas->Buffer; + len = pas->Length; + } + result = string(f, s, -1, field_width, precision, flags); + } + if (result < 0) + return -1; + done += result; + continue; + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (qualifier == 'l' || qualifier == 'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } + else if ( _isinfl(_ldouble) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } + else if ( _isinfl(_ldouble) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + result = numberfl(f,_ldouble,*fmt,field_width,precision,flags); + if (result < 0) + return -1; + done += result; + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + s = "Nan"; + len = 3; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) < 0 ) { + s = "-Inf"; + len = 4; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) > 0 ) { + s = "+Inf"; + len = 4; + while ( len > 0 ) { + if (putc(*s++,f) == EOF) + return -1; + done++; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + result = numberf(f,_double,*fmt,field_width,precision,flags); + if (result < 0) + return -1; + done += result; + } + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + result = number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + if (result < 0) + return -1; + done += result; + continue; + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + { + if (putc('%', f) == EOF) + return -1; + done++; + } + if (*fmt) + { + if (putc(*fmt, f) == EOF) + return -1; + done++; + } + else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + result = number(f, num, base, field_width, precision, flags); + if (result < 0) + return -1; + done += result; + } + //putc('\0',f); + return done; +} + +/* EOF */ diff --git a/lib/msvcrt/stdio/vfscanf.c b/lib/msvcrt/stdio/vfscanf.c new file mode 100644 index 0000000..909901b --- /dev/null +++ b/lib/msvcrt/stdio/vfscanf.c @@ -0,0 +1,1199 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The internal entry points for `strtoX' take an extra flag argument + saying whether or not to parse locale-dependent number grouping. */ + +double __strtod_internal (const char *__nptr,char **__endptr, int __group); +float __strtof_internal (const char *__nptr, char **__endptr,int __group); +long double __strtold_internal (const char *__nptr,char **__endptr, int __group); +long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group); +unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group); + + + +#ifdef __GNUC__ +#define HAVE_LONGLONG +#define LONGLONG long long +#else +#define LONGLONG long +#endif + +/* Those are flags in the conversion format. */ +# define LONG 0x001 /* l: long or double */ +# define LONGDBL 0x002 /* L: long long or long double */ +# define SHORT 0x004 /* h: short */ +# define SUPPRESS 0x008 /* *: suppress assignment */ +# define POINTER 0x010 /* weird %p pointer (`fake hex') */ +# define NOSKIP 0x020 /* do not skip blanks */ +# define WIDTH 0x040 /* width was given */ +# define GROUP 0x080 /* ': group numbers */ +# define MALLOC 0x100 /* a: malloc strings */ + +# define TYPEMOD (LONG|LONGDBL|SHORT) + + +# define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s)) +# define inchar() ((c = getc (s)), (void) (c != EOF && ++read_in), c) +# define encode_error() do { \ + funlockfile (s); \ + __set_errno (EILSEQ); \ + return done; \ + } while (0) +# define conv_error() do { \ + funlockfile (s); \ + return done; \ + } while (0) +# define input_error() do { \ + funlockfile (s); \ + return done ? 0 : EOF; \ + } while (0) +# define memory_error() do { \ + funlockfile (s); \ + __set_errno (ENOMEM); \ + return EOF; \ + } while (0) +# define ARGCHECK(s, format) \ + do \ + { \ + /* Check file argument for consistence. */ \ + if (!__validfp (s) || !s->__mode.__read) \ + { \ + __set_errno (EBADF); \ + return EOF; \ + } \ + else if (format == NULL) \ + { \ + __set_errno (EINVAL); \ + return EOF; \ + } \ + } while (0) + +# define flockfile(S) /* nothing */ +# define funlockfile(S) /* nothing */ + + char *wp = NULL; /* Workspace. */ + size_t wpmax = 0; /* Maximal size of workspace. */ + size_t wpsize = 0; /* Currently used bytes in workspace. */ + + +void ADDW(int Ch) \ +{ + if (wpsize == wpmax) + { + char *old = wp; + wpmax = UCHAR_MAX > 2 * wpmax ? UCHAR_MAX : 2 * wpmax; + wp = (char *) malloc (wpmax); + if (old != NULL) + { + memcpy (wp, old, wpsize); + free(old); + } + } + wp[wpsize++] = (Ch); +} + + +int __vfscanf (FILE *s, const char *format, va_list argptr) +{ + va_list arg; + register const char *f = format; + register unsigned char fc; /* Current character of the format. */ + register size_t done = 0; /* Assignments done. */ + register size_t read_in = 0; /* Chars read in. */ + register int c = 0; /* Last char read. */ + register int width; /* Maximum field width. */ + register int flags; /* Modifiers for current format element. */ + + /* Status for reading F-P nums. */ + char got_dot, got_e, negative; + /* If a [...] is a [^...]. */ + char not_in; + /* Base for integral numbers. */ + int base; + /* Signedness for integral numbers. */ + int number_signed; + /* Decimal point character. */ + wchar_t decimal = '.'; + /* The thousands character of the current locale. */ + wchar_t thousands = ','; + /* Integral holding variables. */ + union + { + long long int q; + unsigned long long int uq; + long int l; + unsigned long int ul; + } num; + /* Character-buffer pointer. */ + char *str = NULL; + wchar_t *wstr = NULL; + char **strptr = NULL; + size_t strsize = 0; + /* We must not react on white spaces immediately because they can + possibly be matched even if in the input stream no character is + available anymore. */ + int skip_space = 0; + /* Workspace. */ + char *tw; /* Temporary pointer. */ + +#ifdef __va_copy + __va_copy (arg, argptr); +#else + arg = (va_list) argptr; +#endif + + + + /* Run through the format string. */ + while (*f != '\0') + { + unsigned int argpos; + /* Extract the next argument, which is of type TYPE. + For a %N$... spec, this is the Nth argument from the beginning; + otherwise it is the next argument after the state now in ARG. */ +#define ARG(type) va_arg(argptr,type) + + if (!isascii (*f)) + { + /* Non-ASCII, may be a multibyte. */ + // int len = mblen (f, strlen (f)); + int len =1; + if (len > 0) + { + do + { + c = inchar (); + if (c == EOF) + input_error (); + else if (c != *f++) + { + ungetc (c, s); + conv_error (); + } + } + while (--len > 0); + continue; + } + } + + fc = *f++; + if (fc != '%') + { + /* Remember to skip spaces. */ + if (isspace (fc)) + { + skip_space = 1; + continue; + } + + /* Read a character. */ + c = inchar (); + + /* Characters other than format specs must just match. */ + if (c == EOF) + input_error (); + + /* We saw white space char as the last character in the format + string. Now it's time to skip all leading white space. */ + if (skip_space) + { + while (isspace (c)) + if (inchar () == EOF && errno == EINTR) + conv_error (); + skip_space = 0; + } + + if (c != fc) + { + ungetc (c, s); + conv_error (); + } + + continue; + } + + /* This is the start of the conversion string. */ + flags = 0; + + /* Initialize state of modifiers. */ + argpos = 0; + + /* Prepare temporary buffer. */ + wpsize = 0; + + /* Check for a positional parameter specification. */ + if (isdigit (*f)) + { + argpos = *f++ - '0'; + while (isdigit (*f)) + argpos = argpos * 10 + (*f++ - '0'); + if (*f == '$') + ++f; + else + { + /* Oops; that was actually the field width. */ + width = argpos; + flags |= WIDTH; + argpos = 0; + goto got_width; + } + } + + /* Check for the assignment-suppressing and the number grouping flag. */ + while (*f == '*' || *f == '\'') + switch (*f++) + { + case '*': + flags |= SUPPRESS; + break; + case '\'': + flags |= GROUP; + break; + } + + /* We have seen width. */ + if (isdigit (*f)) + flags |= WIDTH; + + /* Find the maximum field width. */ + width = 0; + while (isdigit (*f)) + { + width *= 10; + width += *f++ - '0'; + } + got_width: + if (width == 0) + width = -1; + + /* Check for type modifiers. */ + while (*f == 'h' || *f == 'l' || *f == 'L' || *f == 'a' || *f == 'q') + switch (*f++) + { + case 'h': + /* int's are short int's. */ + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + flags |= SHORT; + break; + case 'l': + if (flags & (SHORT|LONGDBL)) + conv_error (); + else if (flags & LONG) + { + /* A double `l' is equivalent to an `L'. */ + flags &= ~LONG; + flags |= LONGDBL; + } + else + /* int's are long int's. */ + flags |= LONG; + break; + case 'q': + case 'L': + /* double's are long double's, and int's are long long int's. */ + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + flags |= LONGDBL; + break; + case 'a': + if (flags & TYPEMOD) + /* Signal illegal format element. */ + conv_error (); + /* String conversions (%s, %[) take a `char **' + arg and fill it in with a malloc'd pointer. */ + flags |= MALLOC; + break; + } + + /* End of the format string? */ + if (*f == '\0') + conv_error (); + + /* We must take care for EINTR errors. */ + if (c == EOF && errno == EINTR) + input_error (); + + /* Find the conversion specifier. */ + fc = *f++; + if (skip_space || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) + { + /* Eat whitespace. */ + do + if (inchar () == EOF && errno == EINTR) + input_error (); + while (isspace (c)); + ungetc (c, s); + skip_space = 0; + } + + switch (fc) + { + case '%': /* Must match a literal '%'. */ + c = inchar (); + if (c != fc) + { + ungetc (c, s); + conv_error (); + } + break; + + case 'n': /* Answer number of assignments done. */ + /* Corrigendum 1 to ISO C 1990 describes the allowed flags + with the 'n' conversion specifier. */ + if (!(flags & SUPPRESS)) + { + /* Don't count the read-ahead. */ + if (flags & LONGDBL) + *ARG (long int *) = read_in; + else if (flags & LONG) + *ARG (long int *) = read_in; + else if (flags & SHORT) + *ARG (short int *) = read_in; + else + *ARG (int *) = read_in; + +#ifdef NO_BUG_IN_ISO_C_CORRIGENDUM_1 + /* We have a severe problem here. The ISO C standard + contradicts itself in explaining the effect of the %n + format in `scanf'. While in ISO C:1990 and the ISO C + Amendement 1:1995 the result is described as + + Execution of a %n directive does not effect the + assignment count returned at the completion of + execution of the f(w)scanf function. + + in ISO C Corrigendum 1:1994 the following was added: + + Subclause 7.9.6.2 + Add the following fourth example: + In: + #include + int d1, d2, n1, n2, i; + i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2); + the value 123 is assigned to d1 and the value3 to n1. + Because %n can never get an input failure the value + of 3 is also assigned to n2. The value of d2 is not + affected. The value 3 is assigned to i. + + We go for now with the historically correct code fro ISO C, + i.e., we don't count the %n assignments. When it ever + should proof to be wrong just remove the #ifdef above. */ + ++done; +#endif + } + break; + + case 'c': /* Match characters. */ + if ((flags & LONG) == 0) + { + if (!(flags & SUPPRESS)) + { + str = ARG (char *); + if (str == NULL) + conv_error (); + } + + c = inchar (); + if (c == EOF) + input_error (); + + if (width == -1) + width = 1; + + if (!(flags & SUPPRESS)) + { + do + *str++ = c; + while (--width > 0 && inchar () != EOF); + } + else + while (--width > 0 && inchar () != EOF); + + if (width > 0) + /* I.e., EOF was read. */ + --read_in; + + if (!(flags & SUPPRESS)) + ++done; + + break; + } + /* FALLTHROUGH */ + case 'C': + /* Get UTF-8 encoded wide character. Here we assume (as in + other parts of the libc) that we only have to handle + UTF-8. */ + { + wint_t val; + size_t cnt = 0; + int first = 1; + + if (!(flags & SUPPRESS)) + { + wstr = ARG (wchar_t *); + if (str == NULL) + conv_error (); + } + + do + { +#define NEXT_WIDE_CHAR(First) \ + c = inchar (); \ + if (c == EOF) { \ + /* EOF is only an error for the first character. */ \ + if (First) { \ + input_error (); \ + } \ + else \ + { \ + --read_in; \ + break; \ + } \ + } \ + val = c; \ + if (val >= 0x80) \ + { \ + if ((c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ + encode_error (); \ + if ((c & 0xe0) == 0xc0) \ + { \ + /* We expect two bytes. */ \ + cnt = 1; \ + val &= 0x1f; \ + } \ + else if ((c & 0xf0) == 0xe0) \ + { \ + /* We expect three bytes. */ \ + cnt = 2; \ + val &= 0x0f; \ + } \ + else if ((c & 0xf8) == 0xf0) \ + { \ + /* We expect four bytes. */ \ + cnt = 3; \ + val &= 0x07; \ + } \ + else if ((c & 0xfc) == 0xf8) \ + { \ + /* We expect five bytes. */ \ + cnt = 4; \ + val &= 0x03; \ + } \ + else \ + { \ + /* We expect six bytes. */ \ + cnt = 5; \ + val &= 0x01; \ + } \ + \ + do \ + { \ + c = inchar (); \ + if (c == EOF \ + || (c & 0xc0) == 0x80 || (c & 0xfe) == 0xfe) \ + encode_error (); \ + val <<= 6; \ + val |= c & 0x3f; \ + } \ + while (--cnt > 0); \ + } \ + \ + if (!(flags & SUPPRESS)) \ + *wstr++ = val; \ + first = 0 + + NEXT_WIDE_CHAR (first); + } + while (--width > 0); + + if (width > 0) + /* I.e., EOF was read. */ + --read_in; + + if (!(flags & SUPPRESS)) + ++done; + } + break; + + case 's': /* Read a string. */ + if (flags & LONG) + /* We have to process a wide character string. */ + goto wide_char_string; + +#define STRING_ARG(Str, Type) \ + if (!(flags & SUPPRESS)) \ + { \ + if (flags & MALLOC) \ + { \ + /* The string is to be stored in a malloc'd buffer. */ \ + strptr = ARG (char **); \ + if (strptr == NULL) \ + conv_error (); \ + /* Allocate an initial buffer. */ \ + strsize = 100; \ + *strptr = malloc (strsize * sizeof (Type)); \ + Str = (Type *) *strptr; \ + } \ + else \ + Str = ARG (Type *); \ + if (Str == NULL) \ + conv_error (); \ + } + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + + do + { + if (isspace (c)) + { + ungetc (c, s); + break; + } +#define STRING_ADD_CHAR(Str, c, Type) \ + if (!(flags & SUPPRESS)) \ + { \ + *Str++ = c; \ + if ((flags & MALLOC) && (char *) Str == *strptr + strsize) \ + { \ + /* Enlarge the buffer. */ \ + Str = realloc (*strptr, strsize * 2 * sizeof (Type)); \ + if (Str == NULL) \ + { \ + /* Can't allocate that much. Last-ditch effort. */\ + Str = realloc (*strptr, \ + (strsize + 1) * sizeof (Type)); \ + if (Str == NULL) \ + { \ + /* We lose. Oh well. \ + Terminate the string and stop converting, \ + so at least we don't skip any input. */ \ + ((Type *) (*strptr))[strsize] = '\0'; \ + ++done; \ + conv_error (); \ + } \ + else \ + { \ + *strptr = (char *) Str; \ + Str = ((Type *) *strptr) + strsize; \ + ++strsize; \ + } \ + } \ + else \ + { \ + *strptr = (char *) Str; \ + Str = ((Type *) *strptr) + strsize; \ + strsize *= 2; \ + } \ + } \ + } + STRING_ADD_CHAR (str, c, char); + } while ((width <= 0 || --width > 0) && inchar () != EOF); + + if (!(flags & SUPPRESS)) + { + *str = '\0'; + ++done; + } + break; + + case 'S': + /* Wide character string. */ + wide_char_string: + { + wint_t val; + int first = 1; + STRING_ARG (wstr, wchar_t); + + do + { + size_t cnt = 0; + NEXT_WIDE_CHAR (first); + + if (iswspace (val)) + { + /* XXX We would have to push back the whole wide char + with possibly many bytes. But since scanf does + not make a difference for white space characters + we can simply push back a simple which is + guaranteed to be in the [:space:] class. */ + ungetc (' ', s); + break; + } + + STRING_ADD_CHAR (wstr, val, wchar_t); + first = 0; + } + while (width <= 0 || --width > 0); + + if (!(flags & SUPPRESS)) + { + *wstr = L'\0'; + ++done; + } + } + break; + + case 'x': /* Hexadecimal integer. */ + case 'X': /* Ditto. */ + base = 16; + number_signed = 0; + goto number; + + case 'o': /* Octal integer. */ + base = 8; + number_signed = 0; + goto number; + + case 'u': /* Unsigned decimal integer. */ + base = 10; + number_signed = 0; + goto number; + + case 'd': /* Signed decimal integer. */ + base = 10; + number_signed = 1; + goto number; + + case 'i': /* Generic number. */ + base = 0; + number_signed = 1; + + number: + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + ADDW (c); + if (width > 0) + --width; + c = inchar (); + } + + /* Look for a leading indication of base. */ + if (width != 0 && c == '0') + { + if (width > 0) + --width; + + ADDW (c); + c = inchar (); + + if (width != 0 && tolower (c) == 'x') + { + if (base == 0) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + c = inchar (); + } + } + else if (base == 0) + base = 8; + } + + if (base == 0) + base = 10; + + /* Read the number into workspace. */ + while (c != EOF && width != 0) + { + if (base == 16 ? !isxdigit (c) : + ((!isdigit (c) || c - '0' >= base) && + !((flags & GROUP) && base == 10 && c == thousands))) + break; + ADDW (c); + if (width > 0) + --width; + + c = inchar (); + } + + /* The just read character is not part of the number anymore. */ + ungetc (c, s); + + if (wpsize == 0 || + (wpsize == 1 && (wp[0] == '+' || wp[0] == '-'))) + /* There was no number. */ + conv_error (); + + /* Convert the number. */ + ADDW ('\0'); + if (flags & LONGDBL) + { +// if (number_signed) +// num.q = __strtoq_internal (wp, &tw, base, flags & GROUP); +// else +// num.uq = __strtouq_internal (wp, &tw, base, flags & GROUP); + } + else + { + if (number_signed) + num.l = __strtol_internal (wp, &tw, base, flags & GROUP); + else + num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP); + } + if (wp == tw) + conv_error (); + + if (!(flags & SUPPRESS)) + { + if (! number_signed) + { + if (flags & LONGDBL) { + *ARG (unsigned LONGLONG int *) = num.uq; + } + else if (flags & LONG) + *ARG (unsigned long int *) = num.ul; + else if (flags & SHORT) + *ARG (unsigned short int *) = (unsigned short int) num.ul; + else + *ARG (unsigned int *) = (unsigned int) num.ul; + } + else + { + if (flags & LONGDBL) { + *ARG (LONGLONG int *) = num.q; + } + else if (flags & LONG) + *ARG (long int *) = num.l; + else if (flags & SHORT) + *ARG (short int *) = (short int) num.l; + else + *ARG (int *) = (int) num.l; + } + ++done; + } + break; + + case 'e': /* Floating-point numbers. */ + case 'E': + case 'f': + case 'g': + case 'G': + c = inchar (); + if (c == EOF) + input_error (); + + /* Check for a sign. */ + if (c == '-' || c == '+') + { + negative = c == '-'; + if (inchar () == EOF) + /* EOF is only an input error before we read any chars. */ + conv_error (); + if (width > 0) + --width; + } + else + negative = 0; + + got_dot = got_e = 0; + do + { + if (isdigit (c)) + ADDW (c); + else if (got_e && wp[wpsize - 1] == 'e' + && (c == '-' || c == '+')) + ADDW (c); + else if (wpsize > 0 && !got_e && tolower (c) == 'e') + { + ADDW ('e'); + got_e = got_dot = 1; + } + else if (c == decimal && !got_dot) + { + ADDW (c); + got_dot = 1; + } + else if ((flags & GROUP) && c == thousands && !got_dot) + ADDW (c); + else + { + /* The last read character is not part of the number + anymore. */ + ungetc (c, s); + break; + } + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + if (wpsize == 0) + conv_error (); + + /* Convert the number. */ + ADDW ('\0'); + if (flags & LONGDBL) + { + long double d = __strtold_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (long double *) = negative ? -d : d; + } + else if (flags & LONG) + { + double d = __strtod_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (double *) = negative ? -d : d; + } + else + { + float d = __strtof_internal (wp, &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != wp) + *ARG (float *) = negative ? -d : d; + } + + if (tw == wp) + conv_error (); + + if (!(flags & SUPPRESS)) + ++done; + break; + + case '[': /* Character class. */ + if (flags & LONG) + { + STRING_ARG (wstr, wchar_t); + c = '\0'; /* This is to keep gcc quiet. */ + } + else + { + STRING_ARG (str, char); + + c = inchar (); + if (c == EOF) + input_error (); + } + + if (*f == '^') + { + ++f; + not_in = 1; + } + else + not_in = 0; + + /* Fill WP with byte flags indexed by character. + We will use this flag map for matching input characters. */ + if (wpmax < UCHAR_MAX) + { + wpmax = UCHAR_MAX; + wp = (char *) alloca (wpmax); + } + memset (wp, 0, UCHAR_MAX); + + fc = *f; + if (fc == ']' || fc == '-') + { + /* If ] or - appears before any char in the set, it is not + the terminator or separator, but the first char in the + set. */ + wp[fc] = 1; + ++f; + } + + while ((fc = *f++) != '\0' && fc != ']') + { + if (fc == '-' && *f != '\0' && *f != ']' && + (unsigned char) f[-2] <= (unsigned char) *f) + { + /* Add all characters from the one before the '-' + up to (but not including) the next format char. */ + for (fc = f[-2]; fc < *f; ++fc) + wp[fc] = 1; + } + else + /* Add the character to the flag map. */ + wp[fc] = 1; + } + if (fc == '\0') + { + if (!(flags & LONG)) + ungetc (c, s); + conv_error(); + } + + if (flags & LONG) + { + wint_t val; + int first = 1; + + do + { + size_t cnt = 0; + NEXT_WIDE_CHAR (first); + if (val > 255 || wp[val] == not_in) + { + /* XXX We have a problem here. We read a wide + character and this possibly took several + bytes. But we can only push back one single + character. To be sure we don't create wrong + input we push it back only in case it is + representable within one byte. */ + if (val < 0x80) + ungetc (val, s); + break; + } + STRING_ADD_CHAR (wstr, val, wchar_t); + if (width > 0) + --width; + first = 0; + } + while (width != 0); + + if (first) + conv_error (); + + if (!(flags & SUPPRESS)) + { + *wstr = L'\0'; + ++done; + } + } + else + { + num.ul = read_in - 1; /* -1 because we already read one char. */ + do + { + if (wp[c] == not_in) + { + ungetc (c, s); + break; + } + STRING_ADD_CHAR (str, c, char); + if (width > 0) + --width; + } + while (width != 0 && inchar () != EOF); + + if (read_in == num.ul) + conv_error (); + + if (!(flags & SUPPRESS)) + { + *str = '\0'; + ++done; + } + } + break; + + case 'p': /* Generic pointer. */ + base = 16; + /* A PTR must be the same size as a `long int'. */ + flags &= ~(SHORT|LONGDBL); + flags |= LONG; + number_signed = 0; + goto number; + } + } + + /* The last thing we saw int the format string was a white space. + Consume the last white spaces. */ + if (skip_space) + { + do + c = inchar (); + while (isspace (c)); + ungetc (c, s); + } + + + return done; +} + + + +int +xfscanf(FILE *f, const char *fmt, ...) +{ + int r; + va_list a=0; + va_start(a, fmt); + r = __vfscanf(f, fmt, a); + va_end(a); + return r; +} + + +double __strtod_internal (const char *__nptr,char **__endptr, int __group) +{ + return strtod(__nptr,__endptr); +} +float __strtof_internal (const char *__nptr, char **__endptr,int __group) +{ + return (float)strtod(__nptr,__endptr); +} +static double powten[] = +{ + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L, + 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L +}; + +long double __strtold_internal (const char *s,char **sret, int __group) +{ + + long double r; /* result */ + int e, ne; /* exponent */ + int sign; /* +- 1.0 */ + int esign; + int flags=0; + int l2powm1; + + r = 0.0L; + sign = 1; + e = ne = 0; + esign = 1; + + while(*s && isspace(*s)) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0L; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r *= 10.0L; + r += *s - '0'; + s++; + ne++; + } + } + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0.0L; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + if (esign < 0) + { + esign = -esign; + e = -e; + } + e = e - ne; + if (e < -4096) + { + /* possibly subnormal number, 10^e would overflow */ + r *= 1.0e-2048L; + e += 2048; + } + if (e < 0) + { + e = -e; + esign = -esign; + } + if (e >= 8192) + e = 8191; + if (e) + { + double d = 1.0L; + l2powm1 = 0; + while (e) + { + if (e & 1) + d *= powten[l2powm1]; + e >>= 1; + l2powm1++; + } + if (esign > 0) + r *= d; + else + r /= d; + } + if (sret) + *sret = (char *)s; + return r * sign; + + return 0; +} +long int __strtol_internal (const char *__nptr, char **__endptr, int __base, int __group) +{ + return strtol(__nptr,__endptr, __base); +} +unsigned long int __strtoul_internal (const char *__nptr, char **__endptr, int __base, int __group) +{ + return strtoul(__nptr,__endptr, __base); +} + + + + + + + + + diff --git a/lib/msvcrt/stdio/vfwprint.c b/lib/msvcrt/stdio/vfwprint.c new file mode 100644 index 0000000..4266f5d --- /dev/null +++ b/lib/msvcrt/stdio/vfwprint.c @@ -0,0 +1,1057 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int _isnanl(double x); +int _isinfl(double x); +int _isnan(double x); +int _isinf(double x); + + +int +__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list argp); + + +int +vfwprintf(FILE *f, const wchar_t *fmt, va_list ap) +{ + int len; + wchar_t localbuf[BUFSIZ]; + +#if 0 + __fileno_lock(fileno(f)); +#endif + if (f->_flag & _IONBF) { + f->_flag &= ~_IONBF; + f->_ptr = f->_base = (char *)localbuf; + f->_bufsiz = BUFSIZ; + len = __vfwprintf(f,fmt,ap); + (void)fflush(f); + f->_flag |= _IONBF; + f->_base = NULL; + f->_bufsiz = 0; + f->_cnt = 0; + } else + len = __vfwprintf(f,fmt,ap); +#if 0 + __fileno_unlock(fileno(f)); +#endif + return (ferror(f) ? EOF : len); +} + + + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Appropiated for the reactos kernel, March 1998 -- David Welch + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ +#define ZEROTRUNC 128 /* truncate zero 's */ + + +static int skip_wtoi(const wchar_t **s) +{ + int i=0; + + while (iswdigit(**s)) + i = i*10 + *((*s)++) - L'0'; + return i; +} + + +static int do_div(long long *n,int base) +{ + int __res = ((unsigned long long) *n) % (unsigned) base; + *n = ((unsigned long long) *n) / (unsigned) base; + return __res; +} + + +static int number(FILE * f, long long num, int base, int size, int precision ,int type) +{ + wchar_t c,sign,tmp[66]; + const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz"; + int i, done = 0; + + if (type & LARGE) + digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return done; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]=L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putwc(L' ',f) == WEOF) + return -1; + done++; + } + + if (sign) + { + if (putwc(sign,f) == WEOF) + return -1; + done++; + } + if (type & SPECIAL) { + if (base==8) { + if (putwc(L'0',f) == WEOF) + return -1; + done++; + } + else if (base==16) { + if (putwc(L'0', f) == WEOF) + return -1; + done++; + if (putwc(digits[33],f) == WEOF) + return -1; + done++; + } + } + if (!(type & LEFT)) + while (size-- > 0) + { + if (putwc(c,f) == WEOF) + return -1; + done++; + } + while (i < precision--) + { + if (putwc(L'0', f) == WEOF) + return -1; + done++; + } + while (i-- > 0) + { + if (putwc(tmp[i],f) == WEOF) + return -1; + done++; + } + while (size-- > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + return done; +} + + +static int numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + wchar_t sign; + wchar_t c; + char ro = 0; + int result, done = 0; + + double_t *n = (double_t *)&__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type); + if (result < 0) + return -1; + done += result; + if (putwc( exp_sign,f) == WEOF) + return -1; + done++; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return -1; + done += result; + return done; + } + + if ( exp_sign == 'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modf(intr, &intr); + + p *=10; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1 ) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putwc(L' ',f) == WEOF) + return -1; + done++; + } + if (sign) + { + if (putwc( sign,f) == WEOF) + return -1; + done++; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + if (putwc(L' ',f) == WEOF) + return -1; + done++; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + if (putwc(c,f) == WEOF) + return -1; + done++; + } + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putwc(L'0', f); + while (i-- > 0) + { + if (putwc(tmp[i],f) == WEOF) + return -1; + done++; + } + while (size-- > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + } + return done; +} + + +static int numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + wchar_t *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + wchar_t sign; + wchar_t c; + char ro = 0; + + int result, done = 0; + + long_double_t *n = (long_double_t *)&__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); + if (result < 0) + return -1; + done += result; + if (putwc( exp_sign,f) == WEOF) + return -1; + done++; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return -1; + done += result; + return done; + } + + if ( exp_sign == L'f' ) { + buf = alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + intr/=10.0L; + p = modfl(intr, &intr); + + p *=10; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (sign) + putwc(sign,f); + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + putwc(L' ',f); + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + putwc(c,f); + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc( '0', f); + while (i-- > 0) + { + if (putwc(tmp[i],f) == WEOF) + return -1; + done++; + } + while (size-- > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + } + return done; +} + +static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (s[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + for (i = 0; i < len; ++i) + { + if (putwc(*s++, f) == WEOF) + return -1; + done++; + } + while (len < field_width--) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + return done; +} + +static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (sw[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + for (i = 0; i < len; ++i) + { + if (putwc(*sw++, f) == WEOF) + return -1; + done++; + } + while (len < field_width--) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + return done; +} + +int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + long double _ldouble; + double _double; + const char *s; + const wchar_t* sw; + int result, done = 0; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) { + if (*fmt != L'%') { + if (putwc(*fmt,f) == WEOF) + return -1; + done++; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case L'-': flags |= LEFT; goto repeat; + case L'+': flags |= PLUS; goto repeat; + case L' ': flags |= SPACE; goto repeat; + case L'#': flags |= SPECIAL; goto repeat; + case L'0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isxdigit(*fmt)) + field_width = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == L'.') { + ++fmt; + if (iswdigit(*fmt)) + precision = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier=0; + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case L'o': + case L'b': + case L'X': + case L'x': + case L'd': + case L'i': + case L'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == L'l' ) { + ++fmt; + qualifier = L'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case L'c': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + if (qualifier == L'h') + { + if (putwc((wchar_t) va_arg(args, int), f) == WEOF) + return -1; + } + else + { + if (putwc((wchar_t) va_arg(args, int), f) == WEOF) + return -1; + } + done++; + while (--field_width > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + continue; + + case L'C': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done; + } + if (qualifier == L'l' || qualifier == L'w') + { + if (putwc((unsigned char) va_arg(args, int), f) == WEOF) + return -1; + } + else + { + if (putwc((unsigned char) va_arg(args, int), f) == WEOF) + return -1; + } + done++; + while (--field_width > 0) + { + if (putwc(L' ', f) == WEOF) + return -1; + done++; + } + continue; + + case L's': /* finished */ + if (qualifier == L'h') { + /* print ascii string */ + s = va_arg(args, char *); + result = string(f, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + result = stringw(f, sw, -1, field_width, precision, flags); + } + if (result < 0) + return -1; + done += result; + continue; + + case L'S': + if (qualifier == L'l' || qualifier == L'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + result = stringw(f, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + } + if (result < 0) + return -1; + done += result; + continue; + + case L'Z': /* finished */ + if (qualifier == L'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + } + result = stringw(f, sw, len, field_width, precision, flags); + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer)) { + s = NULL; + len = -1; + } else { + s = pus->Buffer; + len = pus->Length; + } + result = string(f, s, len, field_width, precision, flags); + } + if (result < 0) + return -1; + done += result; + continue; + + case L'e': /* finished */ + case L'E': + case L'f': + case L'g': + case L'G': + if (qualifier == L'l' || qualifier == L'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } + else if ( _isinfl(_ldouble) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } + else if ( _isinfl(_ldouble) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + result = numberfl(f,_ldouble,*fmt,field_width,precision,flags); + if (result < 0) + return -1; + done += result; + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) { + sw = L"Nan"; + len = 3; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) < 0 ) { + sw = L"-Inf"; + len = 4; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else if ( _isinf(_double) > 0 ) { + sw = L"+Inf"; + len = 4; + while ( len > 0 ) { + if (putwc(*sw++,f) == WEOF) + return -1; + done++; + len --; + } + } else { + if ( precision == -1 ) + precision = 6; + result = numberf(f,_double,*fmt,field_width,precision,flags); + if (result < 0) + return -1; + done += result; + } + } + continue; + + case L'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + result = number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + if (result < 0) + return -1; + done += result; + continue; + + case L'n': + if (qualifier == L'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case L'o': + base = 8; + break; + + case L'b': + base = 2; + break; + + case L'X': + flags |= LARGE; + case L'x': + base = 16; + break; + + case L'd': + case L'i': + flags |= SIGN; + case L'u': + break; + + default: + if (*fmt != L'%') + { + if (putwc(L'%', f) == WEOF) + return -1; + done++; + } + if (*fmt) + { + if (putwc(*fmt, f) == WEOF) + return -1; + done++; + } + else + --fmt; + continue; + } + + if (qualifier == L'I') + num = va_arg(args, unsigned long long); + else if (qualifier == L'l') + num = va_arg(args, unsigned long); + else if (qualifier == L'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + result = number(f, num, base, field_width, precision, flags); + if (result < 0) + return -1; + done += result; + } + //putwc(L'\0',f); + return done; +} + +/* EOF */ diff --git a/lib/msvcrt/stdio/vprintf.c b/lib/msvcrt/stdio/vprintf.c new file mode 100644 index 0000000..f724749 --- /dev/null +++ b/lib/msvcrt/stdio/vprintf.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#undef __OPTIMIZE__ /* Avoid inline `vprintf' function. */ +#include +#include + +#undef vprintf +#undef vwprintf + +/* Write formatted output to stdout according to the + format string FORMAT, using the argument list in ARG. */ +int +vprintf (format, arg) + const char *format; + va_list arg; +{ + int ret = vfprintf (stdout, format, arg); + fflush(stdout); + return ret; +} + +int +vwprintf (format, arg) + const wchar_t *format; + va_list arg; +{ + int ret = vfwprintf (stdout, format, arg); + fflush(stdout); + return ret; +} diff --git a/lib/msvcrt/stdio/vscanf.c b/lib/msvcrt/stdio/vscanf.c new file mode 100644 index 0000000..4c6b796 --- /dev/null +++ b/lib/msvcrt/stdio/vscanf.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1992, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include + + +#undef vscanf + + +/* Read formatted input from stdin according to the format + string in FORMAT, using the argument list in ARG. */ +int __vscanf (const char *format, va_list arg) +{ + return __vfscanf(stdin, format, arg); +} + diff --git a/lib/msvcrt/stdio/vsprintf.c b/lib/msvcrt/stdio/vsprintf.c new file mode 100644 index 0000000..75bfb1d --- /dev/null +++ b/lib/msvcrt/stdio/vsprintf.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +vsprintf(char *str, const char *fmt, va_list ap) +{ + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = INT_MAX; + f._file = -1; + len = vfprintf(&f,fmt, ap); + *f._ptr = 0; + return len; +} + +int +vswprintf(wchar_t *str, const wchar_t *fmt, va_list ap) +{ + FILE f; + int len; + + f._flag = _IOWRT|_IOSTRG; + f._ptr = (char*)str; + f._cnt = INT_MAX; + f._file = -1; + len = vfwprintf(&f,fmt, ap); + *f._ptr = 0; + return len; +} + + +int +_vsnprintf(char *str, size_t maxlen, const char *fmt, va_list ap) +{ + FILE f; + int len; + f._flag = _IOWRT|_IOSTRG; + f._ptr = str; + f._cnt = maxlen; + f._file = -1; + len = vfprintf(&f,fmt, ap); + // what if the buffer is full ?? + *f._ptr = 0; + return len; +} + +int +_vsnwprintf(wchar_t *str, size_t maxlen, const wchar_t *fmt, va_list ap) +{ + FILE f; + int len; + f._flag = _IOWRT|_IOSTRG; + f._ptr = (char*)str; + f._cnt = maxlen; + f._file = -1; + len = vfwprintf(&f,fmt, ap); + // what if the buffer is full ?? + *f._ptr = 0; + return len; +} + + diff --git a/lib/msvcrt/stdio/vsscanf.c b/lib/msvcrt/stdio/vsscanf.c new file mode 100644 index 0000000..42348a1 --- /dev/null +++ b/lib/msvcrt/stdio/vsscanf.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include + +#undef vsscanf + +/* Read formatted input from S according to the format + string FORMAT, using the argument list in ARG. */ +int __vsscanf(const char *s,const char *format,va_list arg) +{ + FILE f; + + if (s == NULL) + { + __set_errno(EINVAL); + return -1; + } + + memset((void *) &f, 0, sizeof (f)); + + f._flag = _IOREAD; + f._ptr = (char *)s; + f._base = (char *)s; + f._bufsiz = strlen(s); + f._cnt = f._bufsiz; + + return __vfscanf(&f, format, arg); +} + diff --git a/lib/msvcrt/stdlib/.cvsignore b/lib/msvcrt/stdlib/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/stdlib/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/stdlib/_exit.c b/lib/msvcrt/stdlib/_exit.c new file mode 100644 index 0000000..c67e0cf --- /dev/null +++ b/lib/msvcrt/stdlib/_exit.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +struct __atexit *__atexit_ptr = 0; + +void exit(int status) +{ + //int i; + struct __atexit *a = __atexit_ptr; + __atexit_ptr = 0; /* to prevent infinite loops */ + while (a) + { + (a->__function)(); + a = a->__next; + } +/* + if (__stdio_cleanup_hook) + __stdio_cleanup_hook(); + for (i=0; i +#include +#include +#include + +char *msg ="Abort\n\r"; + +void abort() +{ + fflush(NULL); + fcloseall(); + raise(SIGABRT); + _write(stderr->_file, msg, sizeof(msg)-1); + exit(3); +} + diff --git a/lib/msvcrt/stdlib/abs.c b/lib/msvcrt/stdlib/abs.c new file mode 100644 index 0000000..95802c5 --- /dev/null +++ b/lib/msvcrt/stdlib/abs.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +abs(int j) +{ + return j<0 ? -j : j; +} diff --git a/lib/msvcrt/stdlib/atexit.c b/lib/msvcrt/stdlib/atexit.c new file mode 100644 index 0000000..fd80fde --- /dev/null +++ b/lib/msvcrt/stdlib/atexit.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +atexit(void (*a)(void)) +{ + struct __atexit *ap; + if (a == 0) + return -1; + ap = (struct __atexit *)malloc(sizeof(struct __atexit)); + if (!ap) + return -1; + ap->__next = __atexit_ptr; + ap->__function = a; + __atexit_ptr = ap; + return 0; +} diff --git a/lib/msvcrt/stdlib/atof.c b/lib/msvcrt/stdlib/atof.c new file mode 100644 index 0000000..8497148 --- /dev/null +++ b/lib/msvcrt/stdlib/atof.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +atof(const char *ascii) +{ + return strtod(ascii, 0); +} diff --git a/lib/msvcrt/stdlib/atoi.c b/lib/msvcrt/stdlib/atoi.c new file mode 100644 index 0000000..c6b95e3 --- /dev/null +++ b/lib/msvcrt/stdlib/atoi.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +atoi(const char *str) +{ + return (int)strtol(str, 0, 10); +} diff --git a/lib/msvcrt/stdlib/atoi64.c b/lib/msvcrt/stdlib/atoi64.c new file mode 100644 index 0000000..9b81b19 --- /dev/null +++ b/lib/msvcrt/stdlib/atoi64.c @@ -0,0 +1,31 @@ + +#include +#include + +__int64 +_atoi64(const char *nptr) +{ + char *s = (char *)nptr; + __int64 acc = 0; + int neg = 0; + + while(isspace((int)*s)) + s++; + if (*s == '-') + { + neg = 1; + s++; + } + else if (*s == '+') + s++; + + while (isdigit((int)*s)) + { + acc = 10 * acc + ((int)*s - '0'); + s++; + } + + if (neg) + acc *= -1; + return acc; +} diff --git a/lib/msvcrt/stdlib/atol.c b/lib/msvcrt/stdlib/atol.c new file mode 100644 index 0000000..3cac430 --- /dev/null +++ b/lib/msvcrt/stdlib/atol.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +atol(const char *str) +{ + return strtol(str, 0, 10); +} diff --git a/lib/msvcrt/stdlib/atold.c b/lib/msvcrt/stdlib/atold.c new file mode 100644 index 0000000..c9b5116 --- /dev/null +++ b/lib/msvcrt/stdlib/atold.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long double +_atold(const char *ascii) +{ + return _strtold(ascii, 0); +} diff --git a/lib/msvcrt/stdlib/bsearch.c b/lib/msvcrt/stdlib/bsearch.c new file mode 100644 index 0000000..7c3d9ed --- /dev/null +++ b/lib/msvcrt/stdlib/bsearch.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +void * +bsearch(const void *key, const void *base0, size_t nelem, + size_t size, int (*cmp)(const void *ck, const void *ce)) +{ + char *base = (char *)base0; + int lim, cmpval; + void *p; + + for (lim = nelem; lim != 0; lim >>= 1) + { + p = base + (lim >> 1) * size; + cmpval = (*cmp)(key, p); + if (cmpval == 0) + return p; + if (cmpval > 0) + { /* key > p: move right */ + base = (char *)p + size; + lim--; + } /* else move left */ + } + return 0; +} diff --git a/lib/msvcrt/stdlib/div.c b/lib/msvcrt/stdlib/div.c new file mode 100644 index 0000000..833e6a3 --- /dev/null +++ b/lib/msvcrt/stdlib/div.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +div_t +div(int num, int denom) +{ + div_t r; + + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} diff --git a/lib/msvcrt/stdlib/ecvt.c b/lib/msvcrt/stdlib/ecvt.c new file mode 100644 index 0000000..18d0090 --- /dev/null +++ b/lib/msvcrt/stdlib/ecvt.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char *ecvtbuf (double, int, int *, int *, char *); + +char * +_ecvt (double value, int ndigits, int *decpt, int *sign) +{ + static char ecvt_buf[DBL_MAX_10_EXP + 10]; + return ecvtbuf (value, ndigits, decpt, sign, ecvt_buf); +} diff --git a/lib/msvcrt/stdlib/ecvtbuf.c b/lib/msvcrt/stdlib/ecvtbuf.c new file mode 100644 index 0000000..1d0f65f --- /dev/null +++ b/lib/msvcrt/stdlib/ecvtbuf.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +// #include + +void __ecvround (char *, char *, const char *, int *); + +void +__ecvround (char *numbuf, char *last_digit, const char *after_last, int *decpt) +{ + char *p; + int carry = 0; + + /* Do we have at all to round the last digit? */ + if (*after_last > '4') + { + p = last_digit; + carry = 1; + + /* Propagate the rounding through trailing '9' digits. */ + do { + int sum = *p + carry; + carry = sum > '9'; + *p-- = sum - carry * 10; + } while (carry && p >= numbuf); + + /* We have 9999999... which needs to be rounded to 100000.. */ + if (carry && p == numbuf) + { + *p = '1'; + *decpt += 1; + } + } +} + +char * +ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) +{ + static char INFINITY[] = "Infinity"; + char decimal = '.' /* localeconv()->decimal_point[0] */; + char *cvtbuf = (char *)alloca (ndigits + 20); /* +3 for sign, dot, null; */ + /* two extra for rounding */ + /* 15 extra for alignment */ + char *s = cvtbuf, *d = buf; + + /* Produce two extra digits, so we could round properly. */ + sprintf (cvtbuf, "%-+.*E", ndigits + 2, value); + *decpt = 0; + + /* The sign. */ + if (*s++ == '-') + *sign = 1; + else + *sign = 0; + + /* Special values get special treatment. */ + if (strncmp (s, "Inf", 3) == 0) + { + /* SunOS docs says we have return "Infinity" for NDIGITS >= 8. */ + memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); + if (ndigits < 8) + buf[3] = '\0'; + } + else if (strcmp (s, "NaN") == 0) + memcpy (buf, s, 4); + else + { + char *last_digit, *digit_after_last; + + /* Copy (the single) digit before the decimal. */ + while (*s && *s != decimal && d - buf < ndigits) + *d++ = *s++; + + /* If we don't see any exponent, here's our decimal point. */ + *decpt = d - buf; + if (*s) + s++; + + /* Copy the fraction digits. */ + while (*s && *s != 'E' && d - buf < ndigits) + *d++ = *s++; + + /* Remember the last digit copied and the one after it. */ + last_digit = d > buf ? d - 1 : d; + digit_after_last = s; + + /* Get past the E in exponent field. */ + while (*s && *s++ != 'E') + ; + + /* Adjust the decimal point by the exponent value. */ + *decpt += atoi (s); + + /* Pad with zeroes if needed. */ + while (d - buf < ndigits) + *d++ = '0'; + + /* Zero-terminate. */ + *d = '\0'; + + /* Round if necessary. */ + __ecvround (buf, last_digit, digit_after_last, decpt); + } + return buf; +} diff --git a/lib/msvcrt/stdlib/errno.c b/lib/msvcrt/stdlib/errno.c new file mode 100644 index 0000000..3579cd5 --- /dev/null +++ b/lib/msvcrt/stdlib/errno.c @@ -0,0 +1,42 @@ +/* $Id$ + * + */ + +#include +#include +#include + +int* __doserrno(void) +{ + return(&GetThreadData()->tdoserrno); +} + +int *_errno(void) +{ + return(&GetThreadData()->terrno); +} + + +int __set_doserrno(int error) +{ + PTHREADDATA ThreadData; + + ThreadData = GetThreadData(); + if (ThreadData) + ThreadData->tdoserrno = error; + + return(error); +} + +int __set_errno(int error) +{ + PTHREADDATA ThreadData; + + ThreadData = GetThreadData(); + if (ThreadData) + ThreadData->terrno = error; + + return(error); +} + +/* EOF */ diff --git a/lib/msvcrt/stdlib/fcvt.c b/lib/msvcrt/stdlib/fcvt.c new file mode 100644 index 0000000..8e4a3ed --- /dev/null +++ b/lib/msvcrt/stdlib/fcvt.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char *fcvtbuf (double, int, int *, int *, char *); + +char * +_fcvt (double value, int ndigits, int *decpt, int *sign) +{ + static char fcvt_buf[2 * DBL_MAX_10_EXP + 10]; + return fcvtbuf (value, ndigits, decpt, sign, fcvt_buf); +} diff --git a/lib/msvcrt/stdlib/fcvtbuf.c b/lib/msvcrt/stdlib/fcvtbuf.c new file mode 100644 index 0000000..2bf85aa --- /dev/null +++ b/lib/msvcrt/stdlib/fcvtbuf.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +// #include + +void __ecvround (char *, char *, const char *, int *); +char *ecvtbuf (double, int, int *, int *, char *); + +char * +fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf) +{ + static char INFINITY[] = "Infinity"; + char decimal = '.' /* localeconv()->decimal_point[0] */; + int digits = ndigits >= 0 ? ndigits : 0; + char *cvtbuf = (char *)alloca (2*DBL_MAX_10_EXP + 16); + char *s = cvtbuf; + char *dot; + + sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value); + + /* The sign. */ + if (*s++ == '-') + *sign = 1; + else + *sign = 0; + + /* Where's the decimal point? */ + dot = strchr (s, decimal); + *decpt = dot ? dot - s : strlen (s); + + /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity" + instead of "Inf". */ + if (strncmp (s, "Inf", 3) == 0) + { + memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3); + if (ndigits < 8) + buf[3] = '\0'; + return buf; + } + else if (ndigits < 0) + return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf); + else if (*s == '0' && value != 0.0) + return ecvtbuf (value, ndigits, decpt, sign, buf); + else + { + memcpy (buf, s, *decpt); + if (s[*decpt] == decimal) + { + memcpy (buf + *decpt, s + *decpt + 1, ndigits); + buf[*decpt + ndigits] = '\0'; + } + else + buf[*decpt] = '\0'; + __ecvround (buf, buf + *decpt + ndigits - 1, + s + *decpt + ndigits + 1, decpt); + return buf; + } +} diff --git a/lib/msvcrt/stdlib/fullpath.c b/lib/msvcrt/stdlib/fullpath.c new file mode 100644 index 0000000..9b3c200 --- /dev/null +++ b/lib/msvcrt/stdlib/fullpath.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/stdlib/fullpath.c + * PURPOSE: Gets the fullpathname + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include + +char *_fullpath( char *absPath, const char *relPath, size_t maxLength ) +{ + char *lpFilePart; + if ( GetFullPathNameA(relPath,maxLength,absPath,&lpFilePart) == 0 ) + return NULL; + + return absPath; +} + +wchar_t *_wfullpath( wchar_t *absPath, const wchar_t *relPath, size_t maxLength ) +{ + wchar_t *lpFilePart; + if ( GetFullPathNameW(relPath,maxLength,absPath,&lpFilePart) == 0 ) + return NULL; + + return absPath; +} diff --git a/lib/msvcrt/stdlib/gcvt.c b/lib/msvcrt/stdlib/gcvt.c new file mode 100644 index 0000000..3a0b621 --- /dev/null +++ b/lib/msvcrt/stdlib/gcvt.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + +char * +_gcvt (double value, int ndigits, char *buf) +{ + char *p = buf; + + sprintf (buf, "%-#.*g", ndigits, value); + + /* It seems they expect us to return .XXXX instead of 0.XXXX */ + if (*p == '-') + p++; + if (*p == '0' && p[1] == '.') + memmove (p, p + 1, strlen (p + 1) + 1); + + /* They want Xe-YY, not X.e-YY, and XXXX instead of XXXX. */ + p = strchr (buf, 'e'); + if (!p) + { + p = buf + strlen (buf); + /* They don't want trailing zeroes. */ + while (p[-1] == '0' && p > buf + 2) + *--p = '\0'; + } + if (p > buf && p[-1] == '.') + memmove (p - 1, p, strlen (p) + 1); + return buf; +} diff --git a/lib/msvcrt/stdlib/getenv.c b/lib/msvcrt/stdlib/getenv.c new file mode 100644 index 0000000..359ac0d --- /dev/null +++ b/lib/msvcrt/stdlib/getenv.c @@ -0,0 +1,35 @@ +#include +#include + +#define NDEBUG +#include + + +char *getenv(const char *name) +{ + char *buffer = (char*)0xffffffff; + int len = GetEnvironmentVariableA(name,buffer,0) + 1; + DPRINT("getenv(%s)\n", name); + buffer = (char *)malloc(len); + DPRINT("getenv('%s') %d %x\n", name, len, buffer); + if (buffer == NULL || GetEnvironmentVariableA(name,buffer,len) == 0 ) + { + free(buffer); + return NULL; + } + return buffer; +} + +wchar_t *_wgetenv(const wchar_t *name) +{ + wchar_t *buffer = (wchar_t*)0xffffffff; + int len = GetEnvironmentVariableW(name, buffer,0) + 1; + DPRINT("_wgetenv(%S)\n", name); + buffer = (wchar_t *)malloc(len * sizeof(wchar_t)); + if (buffer == NULL || GetEnvironmentVariableW(name,buffer,len) == 0) + { + free(buffer); + return NULL; + } + return buffer; +} diff --git a/lib/msvcrt/stdlib/itoa.c b/lib/msvcrt/stdlib/itoa.c new file mode 100644 index 0000000..e8b62af --- /dev/null +++ b/lib/msvcrt/stdlib/itoa.c @@ -0,0 +1,212 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/stdlib/itoa.c + * PURPOSE: converts a integer to ascii + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +_itoa(int value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +char * +_ltoa(long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned long)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +char * +_ultoa(unsigned long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+1); + sp = string; + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +char * +_i64toa(__int64 value, char *string, int radix) +{ + char tmp[65]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+sign+1); + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +char * +_ui64toa(unsigned __int64 value, char *string, int radix) +{ + char tmp[65]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (string == 0) + string = (char *)malloc((tp-tmp)+1); + sp = string; + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} diff --git a/lib/msvcrt/stdlib/itow.c b/lib/msvcrt/stdlib/itow.c new file mode 100644 index 0000000..f65531e --- /dev/null +++ b/lib/msvcrt/stdlib/itow.c @@ -0,0 +1,212 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/stdlib/itoa.c + * PURPOSE: converts a integer to ascii + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +wchar_t * +_itow(int value, wchar_t *string, int radix) +{ + wchar_t tmp[33]; + wchar_t *tp = tmp; + int i; + unsigned v; + int sign; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + if (string == 0) + string = (wchar_t *)malloc(((tp-tmp)+sign+1)*sizeof(wchar_t)); + sp = string; + + if (sign) + *sp++ = L'-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +wchar_t * +_ltow(long value, wchar_t *string, int radix) +{ + wchar_t tmp[33]; + wchar_t *tp = tmp; + long i; + unsigned long v; + int sign; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned long)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + if (string == 0) + string = (wchar_t *)malloc(((tp-tmp)+sign+1)*sizeof(wchar_t)); + sp = string; + + if (sign) + *sp++ = L'-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +wchar_t * +_ultow(unsigned long value, wchar_t *string, int radix) +{ + wchar_t tmp[33]; + wchar_t *tp = tmp; + long i; + unsigned long v = value; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + if (string == 0) + string = (wchar_t *)malloc(((tp-tmp)+1)*sizeof(wchar_t)); + sp = string; + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +wchar_t * +_i64tow(__int64 value, wchar_t *string, int radix) +{ + wchar_t tmp[65]; + wchar_t *tp = tmp; + int i; + unsigned v; + int sign; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + if (string == 0) + string = (wchar_t *)malloc(((tp-tmp)+sign+1)*sizeof(wchar_t)); + sp = string; + + if (sign) + *sp++ = L'-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + +wchar_t * +_ui64tow(unsigned __int64 value, wchar_t *string, int radix) +{ + wchar_t tmp[65]; + wchar_t *tp = tmp; + long i; + unsigned long v = value; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + __set_errno(EDOM); + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + if (string == 0) + string = (wchar_t *)malloc(((tp-tmp)+1)*sizeof(wchar_t)); + sp = string; + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} diff --git a/lib/msvcrt/stdlib/labs.c b/lib/msvcrt/stdlib/labs.c new file mode 100644 index 0000000..eea5989 --- /dev/null +++ b/lib/msvcrt/stdlib/labs.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +labs(long j) +{ + return j<0 ? -j : j; +} diff --git a/lib/msvcrt/stdlib/ldiv.c b/lib/msvcrt/stdlib/ldiv.c new file mode 100644 index 0000000..a3b121b --- /dev/null +++ b/lib/msvcrt/stdlib/ldiv.c @@ -0,0 +1,25 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +ldiv_t +ldiv(long num, long denom) +{ + ldiv_t r; + + if (num > 0 && denom < 0) + { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} diff --git a/lib/msvcrt/stdlib/makepath.c b/lib/msvcrt/stdlib/makepath.c new file mode 100644 index 0000000..e61af37 --- /dev/null +++ b/lib/msvcrt/stdlib/makepath.c @@ -0,0 +1,69 @@ +/* $Id$ + */ +#include +#include + +void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext) +{ + int dir_len; + + if ((drive != NULL) && (*drive)) + { + strcpy(path, drive); + strcat(path, ":"); + } + else + (*path)=0; + + if (dir != NULL) + { + strcat(path, dir); + dir_len = strlen(dir); + if (dir_len && *(dir + dir_len - 1) != '\\') + strcat(path, "\\"); + } + + if (fname != NULL) + { + strcat(path, fname); + if (ext != NULL && *ext != 0) + { + if (*ext != '.') + strcat(path, "."); + strcat(path, ext); + } + } +} + + +void _wmakepath(wchar_t *path, const wchar_t *drive, const wchar_t *dir, const wchar_t *fname, const wchar_t *ext) +{ + int dir_len; + + if ((drive != NULL) && (*drive)) + { + wcscpy(path, drive); + wcscat(path, L":"); + } + else + (*path)=0; + + if (dir != NULL) + { + wcscat(path, dir); + dir_len = wcslen(dir); + if (dir_len && *(dir + dir_len - 1) != L'\\') + wcscat(path, L"\\"); + } + + if (fname != NULL) + { + wcscat(path, fname); + if (ext != NULL && *ext != 0) + { + if (*ext != L'.') + wcscat(path, L"."); + wcscat(path, ext); + } + } +} diff --git a/lib/msvcrt/stdlib/malloc.c b/lib/msvcrt/stdlib/malloc.c new file mode 100644 index 0000000..8353267 --- /dev/null +++ b/lib/msvcrt/stdlib/malloc.c @@ -0,0 +1,24 @@ +#include +#include + +extern HANDLE hHeap; + +void* malloc(size_t _size) +{ + return HeapAlloc(hHeap, HEAP_ZERO_MEMORY, _size); +} + +void free(void* _ptr) +{ + HeapFree(hHeap,0,_ptr); +} + +void* calloc(size_t _nmemb, size_t _size) +{ + return HeapAlloc(hHeap, HEAP_ZERO_MEMORY, _nmemb*_size); +} + +void* realloc(void* _ptr, size_t _size) +{ + return HeapReAlloc(hHeap, 0, _ptr, _size); +} diff --git a/lib/msvcrt/stdlib/mbstow.c b/lib/msvcrt/stdlib/mbstow.c new file mode 100644 index 0000000..9daae0b --- /dev/null +++ b/lib/msvcrt/stdlib/mbstow.c @@ -0,0 +1,17 @@ +#include + + +int mblen (const char* mbs, size_t sizeString) +{ + return 0; +} + +size_t mbstowcs (wchar_t* wcaDest, const char* mbsConvert, size_t size) +{ + return 0; +} + +int mbtowc (wchar_t* wcDest, const char* mbConvert, size_t size) +{ + return 0; +} diff --git a/lib/msvcrt/stdlib/mbstowcs.c b/lib/msvcrt/stdlib/mbstowcs.c new file mode 100644 index 0000000..0aac3f1 --- /dev/null +++ b/lib/msvcrt/stdlib/mbstowcs.c @@ -0,0 +1,11 @@ +#include + +size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count ) +{ + return 0; +} + +int mbtowc( wchar_t *wchar, const char *mbchar, size_t count ) +{ + return 0; +} \ No newline at end of file diff --git a/lib/msvcrt/stdlib/obsol.c b/lib/msvcrt/stdlib/obsol.c new file mode 100644 index 0000000..eac7119 --- /dev/null +++ b/lib/msvcrt/stdlib/obsol.c @@ -0,0 +1,24 @@ +#include +#include + +#undef _cpumode +unsigned char _cpumode = 0; +unsigned char *_cpumode_dll = &_cpumode; + +void _seterrormode(int nMode) +{ + SetErrorMode(nMode); + return; +} + +void _beep(unsigned nFreq, unsigned nDur) +{ + Beep(nFreq,nDur); + return; +} + +void _sleep(unsigned long ulTime) +{ + Sleep(ulTime); + return; +} diff --git a/lib/msvcrt/stdlib/putenv.c b/lib/msvcrt/stdlib/putenv.c new file mode 100644 index 0000000..ce68245 --- /dev/null +++ b/lib/msvcrt/stdlib/putenv.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#define NDEBUG +#include + + +extern int BlockEnvToEnviron(); // defined in misc/dllmain.c + +int _putenv(const char *val) +{ + char *buffer; + char *epos; + int res; + + DPRINT("_putenv('%s')\n", val); + epos = strchr(val, '='); + if ( epos == NULL ) + return -1; + buffer = (char*)malloc(epos - val + 1); + if (buffer == NULL) + return -1; + strncpy(buffer, val, epos - val); + buffer[epos - val] = 0; + res = SetEnvironmentVariableA(buffer,epos+1); + free(buffer); + if (BlockEnvToEnviron()) return 0; + return res; +} + +int _wputenv(const wchar_t *val) +{ + wchar_t *buffer; + wchar_t *epos; + int res; + + DPRINT("_wputenv('%S')\n", val); + epos = wcsrchr(val, L'='); + if ( epos == NULL ) + return -1; + buffer = (char*)malloc((epos - val + 1) * sizeof (wchar_t)); + if (buffer == NULL) + return -1; + wcsncpy(buffer, val, epos - val); + buffer[epos - val] = 0; + res = SetEnvironmentVariableW(buffer,epos+1); + free(buffer); + if (BlockEnvToEnviron() ) return 0; + return res; +} diff --git a/lib/msvcrt/stdlib/qsort.c b/lib/msvcrt/stdlib/qsort.c new file mode 100644 index 0000000..f0e2f55 --- /dev/null +++ b/lib/msvcrt/stdlib/qsort.c @@ -0,0 +1,237 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +/*- + * Copyright (c) 1980, 1983 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * qsort.c: + * Our own version of the system qsort routine which is faster by an average + * of 25%, with lows and highs of 10% and 50%. + * The THRESHold below is the insertion sort threshold, and has been adjusted + * for records of size 48 bytes. + * The MTHREShold is where we stop finding a better median. + */ + +#define THRESH 4 /* threshold for insertion */ +#define MTHRESH 6 /* threshold for median */ + +/* + * qst: + * Do a quicksort + * First, find the median element, and put that one in the first place as the + * discriminator. (This "median" is just the median of the first, last and + * middle elements). (Using this median instead of the first element is a big + * win). Then, the usual partitioning/swapping, followed by moving the + * discriminator into the right place. Then, figure out the sizes of the two + * partions, do the smaller one recursively and the larger one via a repeat of + * this code. Stopping when there are less than THRESH elements in a partition + * and cleaning up with an insertion sort (in our caller) is a huge win. + * All data swaps are done in-line, which is space-losing but time-saving. + * (And there are only three places where this is done). + */ + +static void +qst(PTHREADDATA pThreadData, char *base, char *max) +{ + char c, *i, *j, *jj; + int ii; + char *mid, *tmp; + int lo, hi; + + /* + * At the top here, lo is the number of characters of elements in the + * current partition. (Which should be max - base). + * Find the median of the first, last, and middle element and make + * that the middle element. Set j to largest of first and middle. + * If max is larger than that guy, then it's that guy, else compare + * max with loser of first and take larger. Things are set up to + * prefer the middle, then the first in case of ties. + */ + lo = max - base; /* number of elements as chars */ + do { + mid = i = base + pThreadData->qsz * ((lo / pThreadData->qsz) >> 1); + if (lo >= pThreadData->mthresh) + { + j = (pThreadData->qcmp((jj = base), i) > 0 ? jj : i); + if (pThreadData->qcmp(j, (tmp = max - pThreadData->qsz)) > 0) + { + /* switch to first loser */ + j = (j == jj ? i : jj); + if (pThreadData->qcmp(j, tmp) < 0) + j = tmp; + } + if (j != i) + { + ii = pThreadData->qsz; + do { + c = *i; + *i++ = *j; + *j++ = c; + } while (--ii); + } + } + /* + * Semi-standard quicksort partitioning/swapping + */ + for (i = base, j = max - pThreadData->qsz; ; ) + { + while (i < mid && pThreadData->qcmp(i, mid) <= 0) + i += pThreadData->qsz; + while (j > mid) + { + if (pThreadData->qcmp(mid, j) <= 0) + { + j -= pThreadData->qsz; + continue; + } + tmp = i + pThreadData->qsz; /* value of i after swap */ + if (i == mid) + { + /* j <-> mid, new mid is j */ + mid = jj = j; + } + else + { + /* i <-> j */ + jj = j; + j -= pThreadData->qsz; + } + goto swap; + } + if (i == mid) + { + break; + } + else + { + /* i <-> mid, new mid is i */ + jj = mid; + tmp = mid = i; /* value of i after swap */ + j -= pThreadData->qsz; + } + swap: + ii = pThreadData->qsz; + do { + c = *i; + *i++ = *jj; + *jj++ = c; + } while (--ii); + i = tmp; + } + /* + * Look at sizes of the two partitions, do the smaller + * one first by recursion, then do the larger one by + * making sure lo is its size, base and max are update + * correctly, and branching back. But only repeat + * (recursively or by branching) if the partition is + * of at least size THRESH. + */ + i = (j = mid) + pThreadData->qsz; + if ((lo = j - base) <= (hi = max - i)) + { + if (lo >= pThreadData->thresh) + qst(pThreadData, base, j); + base = i; + lo = hi; + } + else + { + if (hi >= pThreadData->thresh) + qst(pThreadData, i, max); + max = j; + } + } while (lo >= pThreadData->thresh); +} + +/* + * qsort: + * First, set up some global parameters for qst to share. Then, quicksort + * with qst(), and then a cleanup insertion sort ourselves. Sound simple? + * It's not... + */ +void +qsort(const void *base0, size_t n, size_t size, _pfunccmp_t compar) +{ + PTHREADDATA pThreadData; + char *base = (char *)base0; + char c, *i, *j, *lo, *hi; + char *min, *max; + + if (n <= 1) + return; + + pThreadData = GetThreadData(); + + pThreadData->qsz = size; + pThreadData->qcmp = compar; + pThreadData->thresh = pThreadData->qsz * THRESH; + pThreadData->mthresh = pThreadData->qsz * MTHRESH; + max = base + n * pThreadData->qsz; + if (n >= THRESH) + { + qst(pThreadData, base, max); + hi = base + pThreadData->thresh; + } + else + { + hi = max; + } + /* + * First put smallest element, which must be in the first THRESH, in + * the first position as a sentinel. This is done just by searching + * the first THRESH elements (or the first n if n < THRESH), finding + * the min, and swapping it into the first position. + */ + for (j = lo = base; (lo += pThreadData->qsz) < hi; ) + if (pThreadData->qcmp(j, lo) > 0) + j = lo; + if (j != base) + { + /* swap j into place */ + for (i = base, hi = base + pThreadData->qsz; i < hi; ) + { + c = *j; + *j++ = *i; + *i++ = c; + } + } + /* + * With our sentinel in place, we now run the following hyper-fast + * insertion sort. For each remaining element, min, from [1] to [n-1], + * set hi to the index of the element AFTER which this one goes. + * Then, do the standard insertion sort shift on a character at a time + * basis for each element in the frob. + */ + for (min = base; (hi = min += pThreadData->qsz) < max; ) + { + while (pThreadData->qcmp(hi -= pThreadData->qsz, min) > 0) + /* void */; + if ((hi += pThreadData->qsz) != min) { + for (lo = min + pThreadData->qsz; --lo >= min; ) + { + c = *lo; + for (i = j = lo; (j -= pThreadData->qsz) >= hi; i = j) + *i = *j; + *i = c; + } + } + } +} diff --git a/lib/msvcrt/stdlib/rand.c b/lib/msvcrt/stdlib/rand.c new file mode 100644 index 0000000..bae3e28 --- /dev/null +++ b/lib/msvcrt/stdlib/rand.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +rand(void) +{ + PTHREADDATA ThreadData = GetThreadData(); + + ThreadData->tnext = ThreadData->tnext * 0x5deece66dLL + 11; + return (int)((ThreadData->tnext >> 16) & RAND_MAX); +} + +void +srand(unsigned int seed) +{ + PTHREADDATA ThreadData = GetThreadData(); + + ThreadData->tnext = (unsigned long long)seed; +} diff --git a/lib/msvcrt/stdlib/rot.c b/lib/msvcrt/stdlib/rot.c new file mode 100644 index 0000000..ee6dfe4 --- /dev/null +++ b/lib/msvcrt/stdlib/rot.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/stdlib/rot.c + * PURPOSE: Performs a bitwise rotation + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 03/04/99: Created + */ + +#include + +unsigned int _rotl( unsigned int value, int shift ) +{ + int max_bits = sizeof(unsigned int)<<3; + if ( shift < 0 ) + return _rotr(value,-shift); + + if ( shift > max_bits ) + shift = shift % max_bits; + return (value << shift) | (value >> (max_bits-shift)); +} + +unsigned int _rotr( unsigned int value, int shift ) +{ + int max_bits = sizeof(unsigned int)<<3; + if ( shift < 0 ) + return _rotl(value,-shift); + + if ( shift > max_bits<<3 ) + shift = shift % max_bits; + return (value >> shift) | (value << (max_bits-shift)); +} + + +unsigned long _lrotl( unsigned long value, int shift ) +{ + int max_bits = sizeof(unsigned long)<<3; + if ( shift < 0 ) + return _lrotr(value,-shift); + + if ( shift > max_bits ) + shift = shift % max_bits; + return (value << shift) | (value >> (max_bits-shift)); +} + +unsigned long _lrotr( unsigned long value, int shift ) +{ + int max_bits = sizeof(unsigned long)<<3; + if ( shift < 0 ) + return _lrotl(value,-shift); + + if ( shift > max_bits ) + shift = shift % max_bits; + return (value >> shift) | (value << (max_bits-shift)); +} \ No newline at end of file diff --git a/lib/msvcrt/stdlib/senv.c b/lib/msvcrt/stdlib/senv.c new file mode 100644 index 0000000..32c1afe --- /dev/null +++ b/lib/msvcrt/stdlib/senv.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#define NDEBUG +#include + +void _searchenv(const char *file,const char *var,char *path ) +{ + char *env = getenv(var); + char *x; + char *y; + char *FilePart; + + DPRINT("_searchenv()\n"); + x = strchr(env,'='); + if ( x != NULL ) { + *x = 0; + x++; + } + y = strchr(env,';'); + while ( y != NULL ) { + *y = 0; + if ( SearchPathA(x,file,NULL,MAX_PATH,path,&FilePart) > 0 ) { + return; + } + x = y+1; + y = strchr(env,';'); + } + return; +} + +void _wsearchenv(const wchar_t *file,const wchar_t *var,wchar_t *path) +{ + wchar_t *env = _wgetenv(var); + wchar_t *x; + wchar_t *y; + wchar_t *FilePart; + + DPRINT("_searchenw()\n"); + x = wcschr(env,L'='); + if ( x != NULL ) { + *x = 0; + x++; + } + y = wcschr(env,L';'); + while ( y != NULL ) { + *y = 0; + if ( SearchPathW(x,file,NULL,MAX_PATH,path,&FilePart) > 0 ) { + return; + } + x = y+1; + y = wcschr(env,L';'); + } + return; +} diff --git a/lib/msvcrt/stdlib/splitp.c b/lib/msvcrt/stdlib/splitp.c new file mode 100644 index 0000000..20536c6 --- /dev/null +++ b/lib/msvcrt/stdlib/splitp.c @@ -0,0 +1,91 @@ +#include +#include + +void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext ) +{ + char *tmp_drive; + char *tmp_dir; + char *tmp_ext; + + tmp_drive = (char *)strchr(path,':'); + if ( tmp_drive != (char *)NULL ) { + strncpy(drive,tmp_drive-1,1); + *(drive+1) = 0; + } + else { + *drive = 0; + tmp_drive = (char *)path; + } + + tmp_dir = (char *)strrchr(path,'\\'); + if( tmp_dir != NULL && tmp_dir != tmp_drive + 1 ) { + strncpy(dir,tmp_drive+1,tmp_dir - tmp_drive); + *(dir + (tmp_dir - tmp_drive)) = 0; + } + else + *dir =0; + + tmp_ext = ( char *)strrchr(path,'.'); + if ( tmp_ext != NULL ) { + strcpy(ext,tmp_ext); + } + else + { + *ext = 0; + tmp_ext = (char *)path+strlen(path); + } + if ( tmp_dir != NULL ) { + strncpy(fname,tmp_dir+1,tmp_ext - tmp_dir - 1); + *(fname + (tmp_ext - tmp_dir -1)) = 0; + } + else + { + strncpy(fname,path,tmp_ext - path); + *(fname+(tmp_ext-path))=0; + } +} + +void _wsplitpath( const wchar_t *path, wchar_t *drive, wchar_t *dir, wchar_t *fname, wchar_t *ext ) +{ + wchar_t *tmp_drive; + wchar_t *tmp_dir; + wchar_t *tmp_ext; + + tmp_drive = (wchar_t *)wcschr(path,L':'); + if ( tmp_drive != (wchar_t *)NULL ) { + wcsncpy(drive,tmp_drive-1,1); + *(drive+1) = 0; + } + else { + *drive = 0; + tmp_drive = (wchar_t *)path; + } + + tmp_dir = (wchar_t *)wcsrchr(path,L'\\'); + if( tmp_dir != NULL && tmp_dir != tmp_drive + 1 ) { + wcsncpy(dir,tmp_drive+1,tmp_dir - tmp_drive); + *(dir + (tmp_dir - tmp_drive)) = 0; + } + else + *dir =0; + + tmp_ext = (wchar_t *)wcsrchr(path,L'.'); + if ( tmp_ext != NULL ) { + wcscpy(ext,tmp_ext); + } + else + { + *ext = 0; + tmp_ext = (wchar_t *)path+wcslen(path); + } + + if ( tmp_dir != NULL ) { + wcsncpy(fname,tmp_dir+1,tmp_ext - tmp_dir - 1); + *(fname + (tmp_ext - tmp_dir -1)) = 0; + } + else + { + wcsncpy(fname,path,tmp_ext - path); + *(fname+(tmp_ext-path))=0; + } +} diff --git a/lib/msvcrt/stdlib/strtod.c b/lib/msvcrt/stdlib/strtod.c new file mode 100644 index 0000000..433ea38 --- /dev/null +++ b/lib/msvcrt/stdlib/strtod.c @@ -0,0 +1,97 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + + +double +strtod(const char *s, char **sret) +{ + long double r; /* result */ + int e; /* exponent */ + long double d; /* scale */ + int sign; /* +- 1.0 */ + int esign; + int i; + int flags=0; + + r = 0.0; + sign = 1; + e = 0; + esign = 1; + + while ((*s == ' ') || (*s == '\t')) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + d = 0.1L; + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r += d * (*s - '0'); + s++; + d *= 0.1L; + } + } + + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + if ((*s < '0') || (*s > '9')) + { + if (sret) + *sret = (char *)s; + return r; + } + + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + + if (esign < 0) + for (i = 1; i <= e; i++) + r *= 0.1L; + else + for (i = 1; i <= e; i++) + r *= 10.0; + + if (sret) + *sret = (char *)s; + return r * sign; +} diff --git a/lib/msvcrt/stdlib/strtol.c b/lib/msvcrt/stdlib/strtol.c new file mode 100644 index 0000000..1d32150 --- /dev/null +++ b/lib/msvcrt/stdlib/strtol.c @@ -0,0 +1,91 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + + +long +strtol(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + __set_errno(ERANGE); + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/msvcrt/stdlib/strtold.c b/lib/msvcrt/stdlib/strtold.c new file mode 100644 index 0000000..90e847b --- /dev/null +++ b/lib/msvcrt/stdlib/strtold.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +//#include + +static double powten[] = +{ + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L + 1e512L, 1e512L*1e512L, 1e2048L, 1e4096L +}; + +long double +_strtold(const char *s, char **sret) +{ + double r; /* result */ + int e, ne; /* exponent */ + int sign; /* +- 1.0 */ + int esign; + int flags=0; + int l2powm1; + + r = 0.0L; + sign = 1; + e = ne = 0; + esign = 1; + + while(*s && isspace(*s)) + s++; + + if (*s == '+') + s++; + else if (*s == '-') + { + sign = -1; + s++; + } + + while ((*s >= '0') && (*s <= '9')) + { + flags |= 1; + r *= 10.0L; + r += *s - '0'; + s++; + } + + if (*s == '.') + { + s++; + while ((*s >= '0') && (*s <= '9')) + { + flags |= 2; + r *= 10.0L; + r += *s - '0'; + s++; + ne++; + } + } + if (flags == 0) + { + if (sret) + *sret = (char *)s; + return 0.0L; + } + + if ((*s == 'e') || (*s == 'E')) + { + s++; + if (*s == '+') + s++; + else if (*s == '-') + { + s++; + esign = -1; + } + while ((*s >= '0') && (*s <= '9')) + { + e *= 10; + e += *s - '0'; + s++; + } + } + if (esign < 0) + { + esign = -esign; + e = -e; + } + e = e - ne; + if (e < -4096) + { + /* possibly subnormal number, 10^e would overflow */ + r *= 1.0e-2048L; + e += 2048; + } + if (e < 0) + { + e = -e; + esign = -esign; + } + if (e >= 8192) + e = 8191; + if (e) + { + double d = 1.0L; + l2powm1 = 0; + while (e) + { + if (e & 1) + d *= powten[l2powm1]; + e >>= 1; + l2powm1++; + } + if (esign > 0) + r *= d; + else + r /= d; + } + if (sret) + *sret = (char *)s; + return r * sign; + + return 0; +} diff --git a/lib/msvcrt/stdlib/strtoll.c b/lib/msvcrt/stdlib/strtoll.c new file mode 100644 index 0000000..b609e79 --- /dev/null +++ b/lib/msvcrt/stdlib/strtoll.c @@ -0,0 +1,84 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +//#include + +/* constants used in Solaris */ +#define LLONG_MIN -9223372036854775807L-1L +#define LLONG_MAX 9223372036854775807L +#define ULLONG_MAX 18446744073709551615UL + +long +strtoll(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + +/* to prevent overflow, we take max-1 and add 1 after division */ + cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1; + cutlim = cutoff % base; + cutoff /= base; + if (++cutlim == base) + { + cutlim = 0; + cutoff++; + } + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LLONG_MIN : LLONG_MAX; + errno = ERANGE; + } + else if (neg) + acc *= -1; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/msvcrt/stdlib/strtoul.c b/lib/msvcrt/stdlib/strtoul.c new file mode 100644 index 0000000..7e275da --- /dev/null +++ b/lib/msvcrt/stdlib/strtoul.c @@ -0,0 +1,74 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + __set_errno(ERANGE); + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/msvcrt/stdlib/strtoull.c b/lib/msvcrt/stdlib/strtoull.c new file mode 100644 index 0000000..ec9f852 --- /dev/null +++ b/lib/msvcrt/stdlib/strtoull.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +//#include + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoull(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / base; + cutlim = (unsigned long)ULONG_MAX % base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + errno = ERANGE; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/msvcrt/stdlib/swab.c b/lib/msvcrt/stdlib/swab.c new file mode 100644 index 0000000..bdc39de --- /dev/null +++ b/lib/msvcrt/stdlib/swab.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +void _swab (const char* caFrom, char* caTo, size_t sizeToCopy) +{ + unsigned long temp; + + sizeToCopy >>= 1; sizeToCopy++; +#define STEP temp = *((const char *)caFrom)++,*((char *)caTo)++ = *((const char *)caFrom)++,*((char *)caTo)++ = temp + /* round to multiple of 8 */ + while ((--sizeToCopy) & 07) + STEP; + sizeToCopy >>= 3; + while (--sizeToCopy >= 0) { + STEP; STEP; STEP; STEP; + STEP; STEP; STEP; STEP; + } +} diff --git a/lib/msvcrt/stdlib/wcstod.c b/lib/msvcrt/stdlib/wcstod.c new file mode 100644 index 0000000..7772718 --- /dev/null +++ b/lib/msvcrt/stdlib/wcstod.c @@ -0,0 +1,95 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +double wcstod(const wchar_t *s, wchar_t **sret) +{ + long double r; /* result */ + int e; /* exponent */ + long double d; /* scale */ + int sign; /* +- 1.0 */ + int esign; + int i; + int flags=0; + + r = 0.0; + sign = 1; + e = 0; + esign = 1; + + while ((*s == L' ') || (*s == L'\t')) + s++; + + if (*s == L'+') + s++; + else if (*s == L'-') + { + sign = -1; + s++; + } + + while ((*s >= L'0') && (*s <= L'9')) + { + flags |= 1; + r *= 10.0; + r += *s - L'0'; + s++; + } + + if (*s == L'.') + { + d = 0.1L; + s++; + while ((*s >= L'0') && (*s <= L'9')) + { + flags |= 2; + r += d * (*s - L'0'); + s++; + d *= 0.1L; + } + } + + if (flags == 0) + { + if (sret) + *sret = (wchar_t *)s; + return 0; + } + + if ((*s == L'e') || (*s == L'E')) + { + s++; + if (*s == L'+') + s++; + else if (*s == L'-') + { + s++; + esign = -1; + } + if ((*s < L'0') || (*s > L'9')) + { + if (sret) + *sret = (wchar_t *)s; + return r; + } + + while ((*s >= L'0') && (*s <= L'9')) + { + e *= 10; + e += *s - L'0'; + s++; + } + } + + if (esign < 0) + for (i = 1; i <= e; i++) + r *= 0.1L; + else + for (i = 1; i <= e; i++) + r *= 10.0; + + if (sret) + *sret = (wchar_t *)s; + return r * sign; +} diff --git a/lib/msvcrt/stdlib/wcstol.c b/lib/msvcrt/stdlib/wcstol.c new file mode 100644 index 0000000..732eb3d --- /dev/null +++ b/lib/msvcrt/stdlib/wcstol.c @@ -0,0 +1,33 @@ +#include + + +long wcstol(const wchar_t *cp,wchar_t **endp,int base) +{ + long result = 0,value; + int sign = 1; + + if ( *cp == L'-' ) { + sign = -1; + cp++; + } + + if (!base) { + base = 10; + if (*cp == L'0') { + base = 8; + cp++; + if ((*cp == L'x') && iswxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (iswxdigit(*cp) && (value = iswdigit(*cp) ? *cp-L'0' : (iswlower(*cp) + ? towupper(*cp) : *cp)-L'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (wchar_t *)cp; + return result * sign; +} diff --git a/lib/msvcrt/stdlib/wcstom.c b/lib/msvcrt/stdlib/wcstom.c new file mode 100644 index 0000000..ce3921d --- /dev/null +++ b/lib/msvcrt/stdlib/wcstom.c @@ -0,0 +1,14 @@ +#include + +size_t wcstombs (char* mbsDest, const wchar_t* wsConvert, size_t size) +{ + return 0; +} + +int wctomb (char* mbDest, wchar_t wc) +{ + return 0; +} + + + diff --git a/lib/msvcrt/stdlib/wcstomb.c b/lib/msvcrt/stdlib/wcstomb.c new file mode 100644 index 0000000..978bd2a --- /dev/null +++ b/lib/msvcrt/stdlib/wcstomb.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include +#include + +#ifndef EILSEQ +#define EILSEQ EINVAL +#endif + +static const wchar_t encoding_mask[] = +{ + ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff +}; + +static const unsigned char encoding_byte[] = +{ + 0xc0, 0xe0, 0xf0, 0xf8, 0xfc +}; + +/* The state is for this UTF8 encoding not used. */ +//static mbstate_t internal; + + +//extern mbstate_t __no_r_state; /* Defined in mbtowc.c. */ + +size_t +__wcrtomb (char *s, wchar_t wc); + +/* Convert WCHAR into its multibyte character representation, + putting this in S and returning its length. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `wcrtomb'. */ +int +wctomb (char *s, wchar_t wchar) +{ + /* If S is NULL the function has to return null or not null + depending on the encoding having a state depending encoding or + not. This is nonsense because any multibyte encoding has a + state. The ISO C amendment 1 corrects this while introducing the + restartable functions. We simply say here all encodings have a + state. */ + if (s == NULL) + return 1; + + return __wcrtomb (s, wchar); +} + + +size_t +__wcrtomb (char *s, wchar_t wc) +{ + char fake[1]; + size_t written = 0; + + + + if (s == NULL) + { + s = fake; + wc = L'\0'; + } + + /* Store the UTF8 representation of WC. */ + if (wc < 0 || wc > 0x7fffffff) + { + /* This is no correct ISO 10646 character. */ + __set_errno (EILSEQ); + return (size_t) -1; + } + + if (wc < 0x80) + { + /* It's a one byte sequence. */ + if (s != NULL) + *s = (char) wc; + return 1; + } + + for (written = 2; written < 6; ++written) + if ((wc & encoding_mask[written - 2]) == 0) + break; + + if (s != NULL) + { + size_t cnt = written; + s[0] = encoding_byte[cnt - 2]; + + --cnt; + do + { + s[cnt] = 0x80 | (wc & 0x3f); + wc >>= 6; + } + while (--cnt > 0); + s[0] |= wc; + } + + return written; +} diff --git a/lib/msvcrt/stdlib/wcstombs.c b/lib/msvcrt/stdlib/wcstombs.c new file mode 100644 index 0000000..4fc85df --- /dev/null +++ b/lib/msvcrt/stdlib/wcstombs.c @@ -0,0 +1,152 @@ +/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#include +#include + +#ifndef EILSEQ +#define EILSEQ EINVAL +#endif + + +static const wchar_t encoding_mask[] = +{ + ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff +}; + +static const unsigned char encoding_byte[] = +{ + 0xc0, 0xe0, 0xf0, 0xf8, 0xfc +}; + +/* We don't need the state really because we don't have shift states + to maintain between calls to this function. */ +static mbstate_t internal; + + +extern mbstate_t __no_r_state; /* Defined in mbtowc.c. */ + +size_t +__wcsrtombs (char *dst, const wchar_t **src, size_t len, mbstate_t *ps); + +/* Convert the `wchar_t' string in PWCS to a multibyte character string + in S, writing no more than N characters. Return the number of bytes + written, or (size_t) -1 if an invalid `wchar_t' was found. + + Attention: this function should NEVER be intentionally used. + The interface is completely stupid. The state is shared between + all conversion functions. You should use instead the restartable + version `wcsrtombs'. */ +size_t +wcstombs (char *s, const wchar_t *pwcs, size_t n) +{ + mbstate_t save_shift = __no_r_state; + size_t written; + + written = __wcsrtombs (s, &pwcs, n, &__no_r_state); + + /* Restore the old shift state. */ + __no_r_state = save_shift; + + /* Return how many we wrote (or maybe an error). */ + return written; +} + +size_t +__wcsrtombs (char *dst, const wchar_t **src, size_t len, mbstate_t *ps) +{ + size_t written = 0; + const wchar_t *run = *src; + + if (ps == NULL) + ps = &internal; + + if (dst == NULL) + /* The LEN parameter has to be ignored if we don't actually write + anything. */ + len = ~0; + + while (written < len) + { + wchar_t wc = *run++; + + if (wc < 0 || wc > 0x7fffffff) + { + /* This is no correct ISO 10646 character. */ + __set_errno (EILSEQ); + return (size_t) -1; + } + + if (wc == L'\0') + { + /* Found the end. */ + if (dst != NULL) + *dst = '\0'; + *src = NULL; + return written; + } + else if (wc < 0x80) + { + /* It's an one byte sequence. */ + if (dst != NULL) + *dst++ = (char) wc; + ++written; + } + else + { + size_t step; + + for (step = 2; step < 6; ++step) + if ((wc & encoding_mask[step - 2]) == 0) + break; + + if (written + step >= len) + /* Too long. */ + break; + + if (dst != NULL) + { + size_t cnt = step; + + dst[0] = encoding_byte[cnt - 2]; + + --cnt; + do + { + dst[cnt] = 0x80 | (wc & 0x3f); + wc >>= 6; + } + while (--cnt > 0); + dst[0] |= wc; + + dst += step; + } + + written += step; + } + } + + /* Store position of first unprocessed word. */ + *src = run; + + return written; +} +//weak_alias (__wcsrtombs, wcsrtombs) \ No newline at end of file diff --git a/lib/msvcrt/stdlib/wcstoul.c b/lib/msvcrt/stdlib/wcstoul.c new file mode 100644 index 0000000..5ee82ee --- /dev/null +++ b/lib/msvcrt/stdlib/wcstoul.c @@ -0,0 +1,101 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +/* + * Convert a unicode string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +wcstoul(const wchar_t *nptr, wchar_t **endptr, int base) +{ + const wchar_t *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (iswspace(c)); + if (c == L'-') + { + neg = 1; + c = *s++; + } + else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (iswdigit(c)) + c -= L'0'; + else if (iswalpha(c)) + c -= iswupper(c) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + __set_errno(ERANGE); + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (wchar_t *)s - 1 : (wchar_t *)nptr; + return acc; +} + +#if 0 +unsigned long wcstoul(const wchar_t *cp,wchar_t **endp,int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == L'0') { + base = 8; + cp++; + if ((*cp == L'x') && iswxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (iswxdigit(*cp) && (value = iswdigit(*cp) ? *cp-L'0' : (iswlower(*cp) + ? towupper(*cp) : *cp)-L'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (wchar_t *)cp; + return result; +} +#endif diff --git a/lib/msvcrt/stdlib/wtoi.c b/lib/msvcrt/stdlib/wtoi.c new file mode 100644 index 0000000..38f03db --- /dev/null +++ b/lib/msvcrt/stdlib/wtoi.c @@ -0,0 +1,11 @@ +#include + +int _wtoi( const wchar_t *str ) +{ + return (int)wcstol(str, 0, 10); +} + +long _wtol( const wchar_t *str ) +{ + return (int)wcstol(str, 0, 10); +} diff --git a/lib/msvcrt/stdlib/wtoi64.c b/lib/msvcrt/stdlib/wtoi64.c new file mode 100644 index 0000000..c9d9441 --- /dev/null +++ b/lib/msvcrt/stdlib/wtoi64.c @@ -0,0 +1,31 @@ + +#include +#include + +__int64 +_wtoi64(const wchar_t *nptr) +{ + wchar_t *s = (wchar_t *)nptr; + __int64 acc = 0; + int neg = 0; + + while(iswspace((int)*s)) + s++; + if (*s == '-') + { + neg = 1; + s++; + } + else if (*s == '+') + s++; + + while (iswdigit((int)*s)) + { + acc = 10 * acc + ((int)*s - '0'); + s++; + } + + if (neg) + acc *= -1; + return acc; +} diff --git a/lib/msvcrt/string/.cvsignore b/lib/msvcrt/string/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/string/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/string/memccpy.c b/lib/msvcrt/string/memccpy.c new file mode 100644 index 0000000..42fd26b --- /dev/null +++ b/lib/msvcrt/string/memccpy.c @@ -0,0 +1,9 @@ +#include + + +void * +_memccpy (void *to, const void *from,int c,size_t count) +{ + memcpy(to,from,count); + return memchr(to,c,count); +} diff --git a/lib/msvcrt/string/memchr.c b/lib/msvcrt/string/memchr.c new file mode 100644 index 0000000..fd21697 --- /dev/null +++ b/lib/msvcrt/string/memchr.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +void * +memchr(const void *s, int c, size_t n) +{ + if (n) + { + const char *p = s; + do { + if (*p++ == c) + return (void *)(p-1); + } while (--n != 0); + } + return 0; +} diff --git a/lib/msvcrt/string/memcmp.c b/lib/msvcrt/string/memcmp.c new file mode 100644 index 0000000..81371e0 --- /dev/null +++ b/lib/msvcrt/string/memcmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +memcmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (*p1++ != *p2++) + return (*--p1 - *--p2); + } while (--n != 0); + } + return 0; +} diff --git a/lib/msvcrt/string/memcpy.c b/lib/msvcrt/string/memcpy.c new file mode 100644 index 0000000..83077e1 --- /dev/null +++ b/lib/msvcrt/string/memcpy.c @@ -0,0 +1,16 @@ +#include + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +void * +memcpy (void *to, const void *from, size_t count) +{ + register char *f = (char *)from; + register char *t = (char *)to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; + + return to; +} diff --git a/lib/msvcrt/string/memicmp.c b/lib/msvcrt/string/memicmp.c new file mode 100644 index 0000000..ed76603 --- /dev/null +++ b/lib/msvcrt/string/memicmp.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_memicmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (toupper(*p1) != toupper(*p2)) + return (*p1 - *p2); + p1++; + p2++; + } while (--n != 0); + } + return 0; +} diff --git a/lib/msvcrt/string/memmove.c b/lib/msvcrt/string/memmove.c new file mode 100644 index 0000000..a3d3726 --- /dev/null +++ b/lib/msvcrt/string/memmove.c @@ -0,0 +1,36 @@ +#include + + +void * memmove(void *dest,const void *src,size_t count) +{ + char *char_dest = (char *)dest; + char *char_src = (char *)src; + + if ((char_dest <= char_src) || (char_dest >= (char_src+count))) + { + /* non-overlapping buffers */ + while(count > 0) + { + *char_dest = *char_src; + char_dest++; + char_src++; + count--; + } + } + else + { + /* overlaping buffers */ + char_dest = (char *)dest + count - 1; + char_src = (char *)src + count - 1; + + while(count > 0) + { + *char_dest = *char_src; + char_dest--; + char_src--; + count--; + } + } + + return dest; +} diff --git a/lib/msvcrt/string/memset.c b/lib/msvcrt/string/memset.c new file mode 100644 index 0000000..129e6ac --- /dev/null +++ b/lib/msvcrt/string/memset.c @@ -0,0 +1,13 @@ +#include + +void * memset(void *src,int val,size_t count) +{ + char *char_src = (char *)src; + + while(count>0) { + *char_src = val; + char_src++; + count--; + } + return src; +} diff --git a/lib/msvcrt/string/strcat.c b/lib/msvcrt/string/strcat.c new file mode 100644 index 0000000..fa71718 --- /dev/null +++ b/lib/msvcrt/string/strcat.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strcat(char *s, const char *append) +{ + char *save = s; + + for (; *s; ++s); + while ((*s++ = *append++)); + return save; +} diff --git a/lib/msvcrt/string/strchr.c b/lib/msvcrt/string/strchr.c new file mode 100644 index 0000000..2e739a8 --- /dev/null +++ b/lib/msvcrt/string/strchr.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +char *strchr(const char *s, int c) +{ + char cc = c; + while (*s) + { + if (*s == cc) + return (char *)s; + s++; + } + if (cc == 0) + return (char *)s; + return 0; +} + diff --git a/lib/msvcrt/string/strcmp.c b/lib/msvcrt/string/strcmp.c new file mode 100644 index 0000000..edc4c94 --- /dev/null +++ b/lib/msvcrt/string/strcmp.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return *(unsigned const char *)s1 - *(unsigned const char *)(s2); +} diff --git a/lib/msvcrt/string/strcoll.c b/lib/msvcrt/string/strcoll.c new file mode 100644 index 0000000..30b4b4c --- /dev/null +++ b/lib/msvcrt/string/strcoll.c @@ -0,0 +1,39 @@ +#include +#include + +/* Compare S1 and S2, returning less than, equal to or + greater than zero if the collated form of S1 is lexicographically + less than, equal to or greater than the collated form of S2. */ + +#if 1 +int strcoll (const char* s1, const char* s2) +{ + return strcmp(s1,s2); +} + +int _stricoll (const char* s1, const char* s2) +{ + return _stricmp(s1,s2); +} + +int _strncoll (const char *s1, const char *s2, size_t c) +{ + return strncmp(s1,s2,c); +} + +int _strnicoll (const char *s1, const char *s2, size_t c) +{ + return _strnicmp(s1,s2,c); +} +#else +int strcoll (const char *s1,const char *s2) +{ + int ret; + ret = CompareStringA(LOCALE_USER_DEFAULT,0,s1,strlen(s1),s2,strlen(s2)); + if (ret == 0) + return 0; + else + return ret - 2; + return 0; +} +#endif diff --git a/lib/msvcrt/string/strcpy.c b/lib/msvcrt/string/strcpy.c new file mode 100644 index 0000000..c62cf0d --- /dev/null +++ b/lib/msvcrt/string/strcpy.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +char* strcpy(char *to, const char *from) +{ + char *save = to; + + for (; (*to = *from); ++from, ++to); + return save; +} diff --git a/lib/msvcrt/string/strcspn.c b/lib/msvcrt/string/strcspn.c new file mode 100644 index 0000000..db77bb7 --- /dev/null +++ b/lib/msvcrt/string/strcspn.c @@ -0,0 +1,19 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t strcspn(const char *s1, const char *s2) +{ + const char *p, *spanp; + char c, sc; + + for (p = s1;;) + { + c = *p++; + spanp = s2; + do { + if ((sc = *spanp++) == c) + return p - 1 - s1; + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/msvcrt/string/strdup.c b/lib/msvcrt/string/strdup.c new file mode 100644 index 0000000..a84de36 --- /dev/null +++ b/lib/msvcrt/string/strdup.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include + + +char *_strdup(const char *_s) +{ + char *rv; + if (_s == 0) + return 0; + rv = (char *)malloc(strlen(_s) + 1); + if (rv == 0) + return 0; + strcpy(rv, _s); + return rv; +} diff --git a/lib/msvcrt/string/strerror.c b/lib/msvcrt/string/strerror.c new file mode 100644 index 0000000..620a35d --- /dev/null +++ b/lib/msvcrt/string/strerror.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +char __syserr00[] = "No Error"; +char __syserr01[] = "Operation not permitted (EPERM)"; +char __syserr02[] = "No such file or directory (ENOENT)"; +char __syserr03[] = "No such process (ESRCH)"; +char __syserr04[] = "Interrupted system call (EINTR)"; +char __syserr05[] = "Input or output error (EIO)"; +char __syserr06[] = "No such device or address (ENXIO)"; +char __syserr07[] = "Argument list too long (E2BIG)"; +char __syserr08[] = "Unable to execute file (ENOEXEC)"; +char __syserr09[] = "Bad file descriptor (EBADF)"; +char __syserr10[] = "No child processes (ECHILD)"; +char __syserr11[] = "Resource temporarily unavailable (EAGAIN)"; +char __syserr12[] = "Not enough memory (ENOMEM)"; +char __syserr13[] = "Permission denied (EACCES)"; +char __syserr14[] = "Bad address (EFAULT)"; +char __syserr15[] = "Unknown Error: 15"; +char __syserr16[] = "Resource busy (EBUSY)"; +char __syserr17[] = "File exists (EEXIST)"; +char __syserr18[] = "Improper link (EXDEV)"; +char __syserr19[] = "No such device (ENODEV)"; +char __syserr20[] = "Not a directory (ENOTDIR)"; +char __syserr21[] = "Is a directory (EISDIR)"; +char __syserr22[] = "Invalid argument (EINVAL)"; +char __syserr23[] = "Too many open files in system (ENFILE)"; +char __syserr24[] = "Too many open files (EMFILE)"; +char __syserr25[] = "Inappropriate I/O control operation (ENOTTY)"; +char __syserr26[] = "Unknown error: 26"; +char __syserr27[] = "File too large (EFBIG)"; +char __syserr28[] = "No space left on drive (ENOSPC)"; +char __syserr29[] = "Invalid seek (ESPIPE)"; +char __syserr30[] = "Read-only file system (EROFS)"; +char __syserr31[] = "Too many links (EMLINK)"; +char __syserr32[] = "Broken pipe (EPIPE)"; +char __syserr33[] = "Input to function out of range (EDOM)"; +char __syserr34[] = "Output of function out of range (ERANGE)"; +char __syserr35[] = "Unknown error: 35"; +char __syserr36[] = "Resource deadlock avoided (EDEADLK)"; +char __syserr37[] = "Unknown error: 37"; +char __syserr38[] = "File name too long (ENAMETOOLONG)"; +char __syserr39[] = "No locks available (ENOLCK)"; +char __syserr40[] = "Function not implemented (ENOSYS)"; +char __syserr41[] = "Directory not empty (ENOTEMPTY)"; +char __syserr42[] = "Illegal byte sequence (EILSEQ)"; + + + + +const char *_sys_errlist[] = { +__syserr00, __syserr01, __syserr02, __syserr03, __syserr04, +__syserr05, __syserr06, __syserr07, __syserr08, __syserr09, +__syserr10, __syserr11, __syserr12, __syserr13, __syserr14, +__syserr15, __syserr16, __syserr17, __syserr18, __syserr19, +__syserr20, __syserr21, __syserr22, __syserr23, __syserr24, +__syserr25, __syserr26, __syserr27, __syserr28, __syserr29, +__syserr30, __syserr31, __syserr32, __syserr33, __syserr34, +__syserr35, __syserr36, __syserr37, __syserr38, __syserr39, +__syserr40, __syserr41, __syserr42 +}; + +int __sys_nerr = sizeof(_sys_errlist) / sizeof(_sys_errlist[0]); + +int* _sys_nerr = &__sys_nerr; + +char *strerror(int errnum) +{ + static char ebuf[40]; /* 64-bit number + slop */ + char *cp; + int v=1000000, lz=0; + + if (errnum >= 0 && errnum < __sys_nerr) + return((char *)_sys_errlist[errnum]); + + strcpy(ebuf, "Unknown error: "); + cp = ebuf + 15; + if (errnum < 0) + { + *cp++ = '-'; + errnum = -errnum; + } + while (v) + { + int d = errnum / v; + if (d || lz || (v == 1)) + { + *cp++ = d+'0'; + lz = 1; + } + errnum %= v; + v /= 10; + } + + return ebuf; +} + + +char *_strerror(const char *s) +{ + if ( s == NULL ) + return strerror(errno); + + return strerror(atoi(s)); +} diff --git a/lib/msvcrt/string/stricmp.c b/lib/msvcrt/string/stricmp.c new file mode 100644 index 0000000..de15d0f --- /dev/null +++ b/lib/msvcrt/string/stricmp.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_stricmp(const char *s1, const char *s2) +{ + while (toupper(*s1) == toupper(*s2)) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); +} + +int +_strcmpi(const char *s1, const char *s2) +{ + return _stricmp(s1,s2); +} diff --git a/lib/msvcrt/string/strlen.c b/lib/msvcrt/string/strlen.c new file mode 100644 index 0000000..808d96c --- /dev/null +++ b/lib/msvcrt/string/strlen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strlen(const char *str) +{ + const char *s; + + if (str == 0) + return 0; + for (s = str; *s; ++s); + return s-str; +} + diff --git a/lib/msvcrt/string/strlwr.c b/lib/msvcrt/string/strlwr.c new file mode 100644 index 0000000..131ec3f --- /dev/null +++ b/lib/msvcrt/string/strlwr.c @@ -0,0 +1,23 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + +#include +#include + +char * _strlwr(char *x) +{ + char *y=x; + + while (*y) { + *y=tolower(*y); + y++; + } + return x; +} diff --git a/lib/msvcrt/string/strncat.c b/lib/msvcrt/string/strncat.c new file mode 100644 index 0000000..be963b4 --- /dev/null +++ b/lib/msvcrt/string/strncat.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strncat(char *dst, const char *src, size_t n) +{ + if (n != 0) + { + char *d = dst; + const char *s = src; + + while (*d != 0) + d++; + do { + if ((*d = *s++) == 0) + break; + d++; + } while (--n != 0); + *d = 0; + } + return dst; +} diff --git a/lib/msvcrt/string/strncmp.c b/lib/msvcrt/string/strncmp.c new file mode 100644 index 0000000..6a2352d --- /dev/null +++ b/lib/msvcrt/string/strncmp.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return 0; + do { + if (*s1 != *s2++) + return *(unsigned const char *)s1 - *(unsigned const char *)--s2; + if (*s1++ == 0) + break; + } while (--n != 0); + return 0; +} diff --git a/lib/msvcrt/string/strncpy.c b/lib/msvcrt/string/strncpy.c new file mode 100644 index 0000000..6981589 --- /dev/null +++ b/lib/msvcrt/string/strncpy.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) { + char *d = dst; + const char *s = src; + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + } while (--n != 0); + } + return dst; +} diff --git a/lib/msvcrt/string/strnicmp.c b/lib/msvcrt/string/strnicmp.c new file mode 100644 index 0000000..b19a8a8 --- /dev/null +++ b/lib/msvcrt/string/strnicmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int _strnicmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return 0; + do { + if (toupper(*s1) != toupper(*s2++)) + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)--s2); + if (*s1++ == 0) + break; + } while (--n != 0); + return 0; +} diff --git a/lib/msvcrt/string/strnlen.c b/lib/msvcrt/string/strnlen.c new file mode 100644 index 0000000..ba113d0 --- /dev/null +++ b/lib/msvcrt/string/strnlen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strnlen(const char *str, size_t count) +{ + const char *s; + + if (str == 0) + return 0; + for (s = str; *s && count; ++s, count--); + return s-str; +} + diff --git a/lib/msvcrt/string/strpbrk.c b/lib/msvcrt/string/strpbrk.c new file mode 100644 index 0000000..c4837fc --- /dev/null +++ b/lib/msvcrt/string/strpbrk.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +char * +strpbrk(const char *s1, const char *s2) +{ + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return (char *)(s1 - 1); + } + return 0; +} diff --git a/lib/msvcrt/string/strrchr.c b/lib/msvcrt/string/strrchr.c new file mode 100644 index 0000000..64be5cd --- /dev/null +++ b/lib/msvcrt/string/strrchr.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strrchr(const char *s, int c) +{ + char cc = c; + const char *sp=(char *)0; + while (*s) + { + if (*s == cc) + sp = s; + s++; + } + if (cc == 0) + sp = s; + return (char *)sp; +} + diff --git a/lib/msvcrt/string/strrev.c b/lib/msvcrt/string/strrev.c new file mode 100644 index 0000000..d36b7a3 --- /dev/null +++ b/lib/msvcrt/string/strrev.c @@ -0,0 +1,18 @@ +#include + +char * _strrev(char *s) +{ + char *e; + char a; + e=s; + while (*e) + e++; + while (s +#include + +char* _strnset (char* szToFill, int szFill, size_t sizeMaxFill) +{ + char *t = szToFill; + int i = 0; + while( *szToFill != 0 && i < sizeMaxFill) + { + *szToFill = szFill; + szToFill++; + i++; + + } + return t; +} + +char* _strset (char* szToFill, int szFill) +{ + char *t = szToFill; + while( *szToFill != 0 ) + { + *szToFill = szFill; + szToFill++; + + } + return t; +} diff --git a/lib/msvcrt/string/strspn.c b/lib/msvcrt/string/strspn.c new file mode 100644 index 0000000..f01e1bf --- /dev/null +++ b/lib/msvcrt/string/strspn.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strspn(const char *s1, const char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (p - 1 - s1); +} diff --git a/lib/msvcrt/string/strstr.c b/lib/msvcrt/string/strstr.c new file mode 100644 index 0000000..4f23e4f --- /dev/null +++ b/lib/msvcrt/string/strstr.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +char *strstr(const char *s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) + { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return 0; + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return (char *)s; +} diff --git a/lib/msvcrt/string/strtok.c b/lib/msvcrt/string/strtok.c new file mode 100644 index 0000000..1388dbe --- /dev/null +++ b/lib/msvcrt/string/strtok.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char *strtok(char *s, const char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + PTHREADDATA ThreadData = GetThreadData(); + + if (s == NULL && (s = ThreadData->lasttoken) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s++; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + ThreadData->lasttoken = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + ThreadData->lasttoken = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/msvcrt/string/strupr.c b/lib/msvcrt/string/strupr.c new file mode 100644 index 0000000..21b17f4 --- /dev/null +++ b/lib/msvcrt/string/strupr.c @@ -0,0 +1,24 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + + +#include +#include + +char *_strupr(char *x) +{ + char *y=x; + + while (*y) { + *y=toupper(*y); + y++; + } + return x; +} diff --git a/lib/msvcrt/string/strxfrm.c b/lib/msvcrt/string/strxfrm.c new file mode 100644 index 0000000..eca0b2d --- /dev/null +++ b/lib/msvcrt/string/strxfrm.c @@ -0,0 +1,22 @@ +#include +#include + +#if 1 +size_t strxfrm( char *dest, const char *src, size_t n ) +{ + strncpy(dest, src, n); + return (strlen(dest)); +} +#else +size_t strxfrm( char *dest, const char *src, size_t n ) +{ + int ret = LCMapStringA(LOCALE_USER_DEFAULT,LCMAP_LOWERCASE, + src, strlen(src), + dest, strlen(dest) ); + + if ( ret == 0 ) + return -1; + return ret; + +} +#endif diff --git a/lib/msvcrt/sys_stat/.cvsignore b/lib/msvcrt/sys_stat/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/sys_stat/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/sys_stat/fstat.c b/lib/msvcrt/sys_stat/fstat.c new file mode 100644 index 0000000..d82d233 --- /dev/null +++ b/lib/msvcrt/sys_stat/fstat.c @@ -0,0 +1,146 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/sys/fstat.c + * PURPOSE: Gather file information + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include +#include +#include +#include + +int _fstat(int fd, struct stat *statbuf) +{ + BY_HANDLE_FILE_INFORMATION FileInformation; + DWORD dwFileType; + void* handle; + + if (!statbuf) + { + __set_errno(EINVAL); + return -1; + } + + if ((void*)-1 == (handle = _get_osfhandle(fd))) + { + __set_errno(EBADF); + return -1; + } + + fflush(NULL); + + memset (statbuf, 0, sizeof(struct stat)); + + dwFileType = GetFileType(handle); + + if (dwFileType == FILE_TYPE_DISK) + { + if (!GetFileInformationByHandle(handle,&FileInformation)) + { + __set_errno(EBADF); + return -1; + } + statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL); + statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL); + statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL); + + statbuf->st_dev = fd; + statbuf->st_size = FileInformation.nFileSizeLow; + statbuf->st_mode = S_IREAD; + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + statbuf->st_mode |= S_IFDIR; + else + statbuf->st_mode |= S_IFREG; + if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE; + } + else if (dwFileType == FILE_TYPE_CHAR) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFCHR; + } + else if (dwFileType == FILE_TYPE_PIPE) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFIFO; + } + else + { + // dwFileType is FILE_TYPE_UNKNOWN or has a bad value + __set_errno(EBADF); + return -1; + } + return 0; +} + +__int64 _fstati64 (int fd, struct _stati64* statbuf) +{ + BY_HANDLE_FILE_INFORMATION FileInformation; + DWORD dwFileType; + void *handle; + + if (!statbuf) + { + __set_errno(EINVAL); + return -1; + } + + if ((void*)-1 == (handle = _get_osfhandle(fd))) + { + __set_errno(EBADF); + return -1; + } + + fflush(NULL); + + memset(statbuf, 0, sizeof(struct _stati64)); + + dwFileType = GetFileType(handle); + + if (dwFileType == FILE_TYPE_DISK) + { + if (!GetFileInformationByHandle(handle,&FileInformation)) + { + __set_errno(EBADF); + return -1; + } + statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL); + statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL); + statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL); + + statbuf->st_dev = fd; + statbuf->st_size = (((__int64)FileInformation.nFileSizeHigh) << 32) + + FileInformation.nFileSizeLow; + statbuf->st_mode = S_IREAD; + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + statbuf->st_mode |= S_IFDIR; + else + statbuf->st_mode |= S_IFREG; + if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE; + } + else if (dwFileType == FILE_TYPE_CHAR) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFCHR; + } + else if (dwFileType == FILE_TYPE_PIPE) + { + statbuf->st_dev = fd; + statbuf->st_mode = S_IFIFO; + } + else + { + // dwFileType is FILE_TYPE_UNKNOWN or has a bad value + __set_errno(EBADF); + return -1; + } + return 0; +} + + diff --git a/lib/msvcrt/sys_stat/futime.c b/lib/msvcrt/sys_stat/futime.c new file mode 100644 index 0000000..b308d08 --- /dev/null +++ b/lib/msvcrt/sys_stat/futime.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include +#include + +int _futime (int nHandle, struct _utimbuf *pTimes) +{ + FILETIME LastAccessTime; + FILETIME LastWriteTime; + + // check for stdin / stdout handles ?? + if (nHandle == -1) + { + __set_errno(EBADF); + return -1; + } + + if (pTimes == NULL) + { + pTimes = alloca(sizeof(struct _utimbuf)); + time(&pTimes->actime); + time(&pTimes->modtime); + } + + if (pTimes->actime < pTimes->modtime) + { + __set_errno(EINVAL); + return -1; + } + + UnixTimeToFileTime(pTimes->actime,&LastAccessTime,0); + UnixTimeToFileTime(pTimes->modtime,&LastWriteTime,0); + if (!SetFileTime(_get_osfhandle(nHandle),NULL, &LastAccessTime, &LastWriteTime)) + { + __set_errno(EBADF); + return -1; + } + + return 0; +} diff --git a/lib/msvcrt/sys_stat/stat.c b/lib/msvcrt/sys_stat/stat.c new file mode 100644 index 0000000..9e7a164 --- /dev/null +++ b/lib/msvcrt/sys_stat/stat.c @@ -0,0 +1,190 @@ +#include +#include +#include +#include +#include + +#include + + +int _stat(const char *path, struct stat *buffer) +{ + HANDLE findHandle; + WIN32_FIND_DATAA findData; + + if (!buffer) + { + __set_errno(EINVAL); + return -1; + } + + if(strchr(path, '*') || strchr(path, '?')) + { + __set_errno(EINVAL); + return -1; + } + + findHandle = FindFirstFileA(path, &findData); + if (findHandle == INVALID_HANDLE_VALUE) + { + __set_errno(ENOENT); + return -1; + } + + FindClose(findHandle); + + memset (buffer, 0, sizeof(struct stat)); + + buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL); + buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL); + buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL); + +// statbuf->st_dev = fd; + buffer->st_size = findData.nFileSizeLow; + buffer->st_mode = S_IREAD; + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buffer->st_mode |= S_IFDIR; + else + buffer->st_mode |= S_IFREG; + if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buffer->st_mode |= S_IWRITE; + + return 0; +} + +__int64 _stati64 (const char *path, struct _stati64 *buffer) +{ + HANDLE findHandle; + WIN32_FIND_DATAA findData; + + if (!buffer) + { + __set_errno(EINVAL); + return -1; + } + + if(strchr(path, '*') || strchr(path, '?')) + { + __set_errno(EINVAL); + return -1; + } + + findHandle = FindFirstFileA(path, &findData); + if (findHandle == INVALID_HANDLE_VALUE) + { + __set_errno(ENOENT); + return -1; + } + + FindClose(findHandle); + + memset (buffer, 0, sizeof(struct stat)); + + buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL); + buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL); + buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL); + +// statbuf->st_dev = fd; + buffer->st_size = (((__int64)findData.nFileSizeHigh) << 32) + + findData.nFileSizeLow; + buffer->st_mode = S_IREAD; + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buffer->st_mode |= S_IFDIR; + else + buffer->st_mode |= S_IFREG; + if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buffer->st_mode |= S_IWRITE; + + return 0; +} + +int _wstat (const wchar_t *path, struct stat *buffer) +{ + HANDLE findHandle; + WIN32_FIND_DATAW findData; + + if (!buffer) + { + __set_errno(EINVAL); + return -1; + } + + if(wcschr(path, L'*') || wcschr(path, L'?')) + { + __set_errno(EINVAL); + return -1; + } + + findHandle = FindFirstFileW(path, &findData); + if (findHandle == INVALID_HANDLE_VALUE) + { + __set_errno(ENOENT); + return -1; + } + + FindClose(findHandle); + + memset (buffer, 0, sizeof(struct stat)); + + buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL); + buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL); + buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL); + +// statbuf->st_dev = fd; + buffer->st_size = findData.nFileSizeLow; + buffer->st_mode = S_IREAD; + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buffer->st_mode |= S_IFDIR; + else + buffer->st_mode |= S_IFREG; + if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buffer->st_mode |= S_IWRITE; + + return 0; +} + +__int64 _wstati64 (const wchar_t *path, struct _stati64 *buffer) +{ + HANDLE findHandle; + WIN32_FIND_DATAW findData; + + if (!buffer) + { + __set_errno(EINVAL); + return -1; + } + + if(wcschr(path, L'*') || wcschr(path, L'?')) + { + __set_errno(EINVAL); + return -1; + } + + findHandle = FindFirstFileW(path, &findData); + if (findHandle == INVALID_HANDLE_VALUE) + { + __set_errno(ENOENT); + return -1; + } + + FindClose(findHandle); + + memset (buffer, 0, sizeof(struct stat)); + + buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL); + buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL); + buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL); + +// statbuf->st_dev = fd; + buffer->st_size = (((__int64)findData.nFileSizeHigh) << 32) + + findData.nFileSizeLow; + buffer->st_mode = S_IREAD; + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buffer->st_mode |= S_IFDIR; + else + buffer->st_mode |= S_IFREG; + if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + buffer->st_mode |= S_IWRITE; + + return 0; +} diff --git a/lib/msvcrt/time/.cvsignore b/lib/msvcrt/time/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/time/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/time/clock.c b/lib/msvcrt/time/clock.c new file mode 100644 index 0000000..15c22c5 --- /dev/null +++ b/lib/msvcrt/time/clock.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/time/clock.c + * PURPOSE: Get elapsed time + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +#include +#include +#include + +VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); + +clock_t clock ( void ) +{ + FILETIME CreationTime; + FILETIME ExitTime; + FILETIME KernelTime; + FILETIME UserTime; + DWORD Remainder; + + if (!GetProcessTimes(GetCurrentProcess(),&CreationTime,&ExitTime,&KernelTime,&UserTime)) + return -1; + + return FileTimeToUnixTime(&KernelTime,&Remainder) + FileTimeToUnixTime(&UserTime,&Remainder); +} diff --git a/lib/msvcrt/time/ctime.c b/lib/msvcrt/time/ctime.c new file mode 100644 index 0000000..b34b515 --- /dev/null +++ b/lib/msvcrt/time/ctime.c @@ -0,0 +1,1441 @@ + +// fix djdir + +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* This file has been modified by DJ Delorie. These modifications are +** Copyright (C) 1995 DJ Delorie, 24 Kirsten Ave, Rochester NH, +** 03867-2954, USA. +*/ + +/* + * Copyright (c) 1987, 1989 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)ctime.c 5.23 (Berkeley) 6/22/90"; +#endif /* LIBC_SCCS and not lint */ + +/* +** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). +** POSIX-style TZ environment variable handling from Guy Harris +** (guy@auspex.com). +*/ + + + + +#include +#include +#include +#include +#include +#include + +#include +#include "tzfile.h" + +#include + +#include "posixrul.h" + +#define P(s) s +#define alloc_size_t size_t +#define qsort_size_t size_t +#define fread_size_t size_t +#define fwrite_size_t size_t + +#define ACCESS_MODE O_RDONLY|O_BINARY +#define OPEN_MODE O_RDONLY|O_BINARY + +/* +** Someone might make incorrect use of a time zone abbreviation: +** 1. They might reference tzname[0] before calling tzset (explicitly +** or implicitly). +** 2. They might reference tzname[1] before calling tzset (explicitly +** or implicitly). +** 3. They might reference tzname[1] after setting to a time zone +** in which Daylight Saving Time is never observed. +** 4. They might reference tzname[0] after setting to a time zone +** in which Standard Time is never observed. +** 5. They might reference tm.TM_ZONE after calling offtime. +** What's best to do in the above cases is open to debate; +** for now, we just set things up so that in any of the five cases +** WILDABBR is used. Another possibility: initialize tzname[0] to the +** string "tzname[0] used before set", and similarly for the other cases. +** And another: initialize tzname[0] to "ERA", with an explanation in the +** manual page of what this "time zone abbreviation" means (doing this so +** that tzname[0] has the "normal" length of three characters). +*/ +int _daylight; +int _timezone; + +static char WILDABBR[] = " "; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif /* !defined TRUE */ + +static const char GMT[] = "GMT"; + +struct ttinfo { /* time type information */ + long tt_gmtoff; /* GMT offset in seconds */ + int tt_isdst; /* used to set tm_isdst */ + int tt_abbrind; /* abbreviation list index */ + int tt_ttisstd; /* TRUE if transition is std time */ +}; + +struct lsinfo { /* leap second information */ + time_t ls_trans; /* transition time */ + long ls_corr; /* correction to apply */ +}; + +struct state { + int leapcnt; + int timecnt; + int typecnt; + int charcnt; + time_t ats[TZ_MAX_TIMES]; + unsigned char types[TZ_MAX_TIMES]; + struct ttinfo ttis[TZ_MAX_TYPES]; + char chars[(TZ_MAX_CHARS + 1 > sizeof GMT) ? TZ_MAX_CHARS + 1 : sizeof GMT]; + struct lsinfo lsis[TZ_MAX_LEAPS]; +}; + +struct rule { + int r_type; /* type of rule--see below */ + int r_day; /* day number of rule */ + int r_week; /* week number of rule */ + int r_mon; /* month number of rule */ + long r_time; /* transition time of rule */ +}; + +#define JULIAN_DAY 0 /* Jn - Julian day */ +#define DAY_OF_YEAR 1 /* n - day of year */ +#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ + +/* +** Prototypes for static functions. +*/ + +static long detzcode P((const char * codep)); +static const char * getzname P((const char * strp)); +static const char * getnum P((const char * strp, int * nump, int min, + int max)); +static const char * getsecs P((const char * strp, long * secsp)); +static const char * getoffset P((const char * strp, long * offsetp)); +static const char * getrule P((const char * strp, struct rule * rulep)); +static void gmtload P((struct state * sp)); +static void gmtsub P((const time_t * timep, long offset, + struct tm * tmp)); +static void localsub P((const time_t * timep, long offset, + struct tm * tmp)); +static void normalize P((int * tensptr, int * unitsptr, int base)); +static void settzname P((void)); +static time_t time1 P((struct tm * tmp, void (* funcp)(const time_t * const, const long, struct tm * const), + long offset)); +static time_t time2 P((struct tm *tmp, void (* funcp)(const time_t * const, const long, struct tm * const), + long offset, int * okayp)); +static void timesub P((const time_t * timep, long offset, + const struct state * sp, struct tm * tmp)); +static int tmcomp P((const struct tm * atmp, + const struct tm * btmp)); +static time_t transtime P((time_t janfirst, int year, + const struct rule * rulep, long offset)); +static int tzload P((const char * name, struct state * sp)); +static int tzparse P((const char * name, struct state * sp, + int lastditch)); +static void tzsetwall(void); + +#ifdef ALL_STATE +static struct state *lclptr; +static struct state *gmtptr; +#endif /* defined ALL_STATE */ + +#ifndef ALL_STATE +static struct state lclmem; +static struct state gmtmem; +#define lclptr (&lclmem) +#define gmtptr (&gmtmem) +#endif /* State Farm */ + +static int lcl_is_set; +static int gmt_is_set; + +char * _tzname[2] = { + WILDABBR, + WILDABBR +}; + +static long +detzcode(const char * const codep) +{ + long result; + int i; + + result = 0; + for (i = 0; i < 4; ++i) + result = (result << 8) | (codep[i] & 0xff); + return result; +} + +static void +settzname(void) +{ + const struct state * const sp = lclptr; + int i; + + _tzname[0] = WILDABBR; + _tzname[1] = WILDABBR; +#ifdef ALL_STATE + if (sp == NULL) + { + _tzname[0] = _tzname[1] = GMT; + return; + } +#endif /* defined ALL_STATE */ + for (i = 0; i < sp->typecnt; ++i) + { + register const struct ttinfo * const ttisp = &sp->ttis[i]; + + _tzname[ttisp->tt_isdst] = + (char *)&sp->chars[ttisp->tt_abbrind]; +#if 0 + if (ttisp->tt_isdst) + _daylight = 1; + if (i == 0 || !ttisp->tt_isdst) + _timezone_dll = -(ttisp->tt_gmtoff); + if (i == 0 || ttisp->tt_isdst) + _altzone = -(ttisp->tt_gmtoff); +#endif + } + /* + ** And to get the latest zone names into tzname. . . + */ + for (i = 0; i < sp->timecnt; ++i) + { + const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]]; + + _tzname[ttisp->tt_isdst] = (char *)&sp->chars[ttisp->tt_abbrind]; + } +} + +static char * +tzdir(void) +{ + static char dir[80]={0}, *cp; + if (dir[0] == 0) + { + if ((cp = getenv("TZDIR"))) + { + strcpy(dir, cp); + } + else if ((cp = getenv("DJDIR"))) + { + strcpy(dir, cp); + strcat(dir, "/zoneinfo"); + } + else + strcpy(dir, "./"); + } + return dir; +} + +static int +tzload(const char *name, struct state * const sp) +{ + const char * p; + int i; + int fid; + char fullname[FILENAME_MAX + 1]; + const struct tzhead * tzhp; + char buf[sizeof *sp + sizeof *tzhp]; + int ttisstdcnt; + + if (name == NULL && (name = TZDEFAULT) == NULL) + return -1; + + if (name[0] == ':') + ++name; + if (name[0] != '/') + { + if ((p = tzdir()) == NULL) + return -1; + if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) + return -1; + strcpy(fullname, p); + strcat(fullname, "/"); + strcat(fullname, name); + name = fullname; + } + + if ((fid = open(name, OPEN_MODE)) == -1) + { + const char *base = strrchr(name, '/'); + if (base) + base++; + else + base = name; + if (strcmp(base, "posixrules")) + return -1; + + /* We've got a built-in copy of posixrules just in case */ + memcpy(buf, _posixrules_data, sizeof(_posixrules_data)); + i = sizeof(_posixrules_data); + } + else + { + i = read(fid, buf, sizeof buf); + if (close(fid) != 0 || i < sizeof *tzhp) + return -1; + } + + tzhp = (struct tzhead *) buf; + ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt); + sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt); + sp->timecnt = (int) detzcode(tzhp->tzh_timecnt); + sp->typecnt = (int) detzcode(tzhp->tzh_typecnt); + sp->charcnt = (int) detzcode(tzhp->tzh_charcnt); + if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || + sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || + sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || + sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || + (ttisstdcnt != sp->typecnt && ttisstdcnt != 0)) + return -1; + if (i < sizeof *tzhp + + sp->timecnt * (4 + sizeof (char)) + + sp->typecnt * (4 + 2 * sizeof (char)) + + sp->charcnt * sizeof (char) + + sp->leapcnt * 2 * 4 + + ttisstdcnt * sizeof (char)) + return -1; + p = buf + sizeof *tzhp; + for (i = 0; i < sp->timecnt; ++i) + { + sp->ats[i] = detzcode(p); + p += 4; + } + for (i = 0; i < sp->timecnt; ++i) + { + sp->types[i] = (unsigned char) *p++; + if (sp->types[i] >= sp->typecnt) + return -1; + } + for (i = 0; i < sp->typecnt; ++i) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[i]; + ttisp->tt_gmtoff = detzcode(p); + p += 4; + ttisp->tt_isdst = (unsigned char) *p++; + if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) + return -1; + ttisp->tt_abbrind = (unsigned char) *p++; + if (ttisp->tt_abbrind < 0 || + ttisp->tt_abbrind > sp->charcnt) + return -1; + } + for (i = 0; i < sp->charcnt; ++i) + sp->chars[i] = *p++; + sp->chars[i] = '\0'; /* ensure '\0' at end */ + for (i = 0; i < sp->leapcnt; ++i) + { + struct lsinfo * lsisp; + + lsisp = &sp->lsis[i]; + lsisp->ls_trans = detzcode(p); + p += 4; + lsisp->ls_corr = detzcode(p); + p += 4; + } + for (i = 0; i < sp->typecnt; ++i) + { + struct ttinfo * ttisp; + + ttisp = &sp->ttis[i]; + if (ttisstdcnt == 0) + ttisp->tt_ttisstd = FALSE; + else + { + ttisp->tt_ttisstd = *p++; + if (ttisp->tt_ttisstd != TRUE && + ttisp->tt_ttisstd != FALSE) + return -1; + } + } + return 0; +} + +static const int mon_lengths[2][MONSPERYEAR] = { +{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, +{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const int year_lengths[2] = { +DAYSPERNYEAR, DAYSPERLYEAR +}; + +/* +** Given a pointer into a time zone string, scan until a character that is not +** a valid character in a zone name is found. Return a pointer to that +** character. +*/ + +static const char * +getzname(const char *strp) +{ + char c; + + while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' && + c != '+') + ++strp; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a number from that string. +** Check that the number is within a specified range; if it is not, return +** NULL. +** Otherwise, return a pointer to the first character not part of the number. +*/ + +static const char * +getnum(const char *strp, int * const nump, const int min, const int max) +{ + char c; + int num; + + if (strp == NULL || !isdigit(*strp)) + return NULL; + num = 0; + while ((c = *strp) != '\0' && isdigit(c)) + { + num = num * 10 + (c - '0'); + if (num > max) + return NULL; + ++strp; + } + if (num < min) + return NULL; + *nump = num; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a number of seconds, +** in hh[:mm[:ss]] form, from the string. +** If any error occurs, return NULL. +** Otherwise, return a pointer to the first character not part of the number +** of seconds. +*/ + +static const char * +getsecs(const char *strp, long * const secsp) +{ + int num; + + strp = getnum(strp, &num, 0, HOURSPERDAY); + if (strp == NULL) + return NULL; + *secsp = num * SECSPERHOUR; + if (*strp == ':') + { + ++strp; + strp = getnum(strp, &num, 0, MINSPERHOUR - 1); + if (strp == NULL) + return NULL; + *secsp += num * SECSPERMIN; + if (*strp == ':') + { + ++strp; + strp = getnum(strp, &num, 0, SECSPERMIN - 1); + if (strp == NULL) + return NULL; + *secsp += num; + } + } + return strp; +} + +/* +** Given a pointer into a time zone string, extract an offset, in +** [+-]hh[:mm[:ss]] form, from the string. +** If any error occurs, return NULL. +** Otherwise, return a pointer to the first character not part of the time. +*/ + +static const char * +getoffset(const char *strp, long * const offsetp) +{ + int neg; + + if (*strp == '-') + { + neg = 1; + ++strp; + } + else if (isdigit(*strp) || *strp++ == '+') + neg = 0; + else + return NULL; /* illegal offset */ + strp = getsecs(strp, offsetp); + if (strp == NULL) + return NULL; /* illegal time */ + if (neg) + *offsetp = -*offsetp; + return strp; +} + +/* +** Given a pointer into a time zone string, extract a rule in the form +** date[/time]. See POSIX section 8 for the format of "date" and "time". +** If a valid rule is not found, return NULL. +** Otherwise, return a pointer to the first character not part of the rule. +*/ + +static const char * +getrule(const char *strp, struct rule * const rulep) +{ + if (*strp == 'J') + { + /* + ** Julian day. + */ + rulep->r_type = JULIAN_DAY; + ++strp; + strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); + } + else if (*strp == 'M') + { + /* + ** Month, week, day. + */ + rulep->r_type = MONTH_NTH_DAY_OF_WEEK; + ++strp; + strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); + if (strp == NULL) + return NULL; + if (*strp++ != '.') + return NULL; + strp = getnum(strp, &rulep->r_week, 1, 5); + if (strp == NULL) + return NULL; + if (*strp++ != '.') + return NULL; + strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); + } + else if (isdigit(*strp)) + { + /* + ** Day of year. + */ + rulep->r_type = DAY_OF_YEAR; + strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); + } + else + return NULL; /* invalid format */ + if (strp == NULL) + return NULL; + if (*strp == '/') + { + /* + ** Time specified. + */ + ++strp; + strp = getsecs(strp, &rulep->r_time); + } + else + rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ + return strp; +} + +/* +** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the +** year, a rule, and the offset from GMT at the time that rule takes effect, +** calculate the Epoch-relative time that rule takes effect. +*/ + +static time_t +transtime(const time_t janfirst, const int year, const struct rule * const rulep, const long offset) +{ + int leapyear; + time_t value=0; + int i; + int d, m1, yy0, yy1, yy2, dow; + + leapyear = isleap(year); + switch (rulep->r_type) + { + + case JULIAN_DAY: + /* + ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap + ** years. + ** In non-leap years, or if the day number is 59 or less, just + ** add SECSPERDAY times the day number-1 to the time of + ** January 1, midnight, to get the day. + */ + value = janfirst + (rulep->r_day - 1) * SECSPERDAY; + if (leapyear && rulep->r_day >= 60) + value += SECSPERDAY; + break; + + case DAY_OF_YEAR: + /* + ** n - day of year. + ** Just add SECSPERDAY times the day number to the time of + ** January 1, midnight, to get the day. + */ + value = janfirst + rulep->r_day * SECSPERDAY; + break; + + case MONTH_NTH_DAY_OF_WEEK: + /* + ** Mm.n.d - nth "dth day" of month m. + */ + value = janfirst; + for (i = 0; i < rulep->r_mon - 1; ++i) + value += mon_lengths[leapyear][i] * SECSPERDAY; + + /* + ** Use Zeller's Congruence to get day-of-week of first day of + ** month. + */ + m1 = (rulep->r_mon + 9) % 12 + 1; + yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; + yy1 = yy0 / 100; + yy2 = yy0 % 100; + dow = ((26 * m1 - 2) / 10 + + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; + if (dow < 0) + dow += DAYSPERWEEK; + + /* + ** "dow" is the day-of-week of the first day of the month. Get + ** the day-of-month (zero-origin) of the first "dow" day of the + ** month. + */ + d = rulep->r_day - dow; + if (d < 0) + d += DAYSPERWEEK; + for (i = 1; i < rulep->r_week; ++i) + { + if (d + DAYSPERWEEK >= + mon_lengths[leapyear][rulep->r_mon - 1]) + break; + d += DAYSPERWEEK; + } + + /* + ** "d" is the day-of-month (zero-origin) of the day we want. + */ + value += d * SECSPERDAY; + break; + } + + /* + ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in + ** question. To get the Epoch-relative time of the specified local + ** time on that day, add the transition time and the current offset + ** from GMT. + */ + return value + rulep->r_time + offset; +} + +/* +** Given a POSIX section 8-style TZ string, fill in the rule tables as +** appropriate. +*/ + +static int +tzparse(const char *name, struct state * const sp, const int lastditch) +{ + const char * stdname; + const char * dstname=0; + int stdlen; + int dstlen; + long stdoffset; + long dstoffset; + time_t * atp; + unsigned char * typep; + char * cp; + int load_result; + + stdname = name; + if (lastditch) + { + stdlen = strlen(name); /* length of standard zone name */ + name += stdlen; + if (stdlen >= sizeof sp->chars) + stdlen = (sizeof sp->chars) - 1; + } + else + { + name = getzname(name); + stdlen = name - stdname; + if (stdlen < 3) + return -1; + } + if (*name == '\0') + return -1; + else + { + name = getoffset(name, &stdoffset); + if (name == NULL) + return -1; + } + load_result = tzload(TZDEFRULES, sp); + if (load_result != 0) + sp->leapcnt = 0; /* so, we're off a little */ + if (*name != '\0') + { + dstname = name; + name = getzname(name); + dstlen = name - dstname; /* length of DST zone name */ + if (dstlen < 3) + return -1; + if (*name != '\0' && *name != ',' && *name != ';') + { + name = getoffset(name, &dstoffset); + if (name == NULL) + return -1; + } + else + dstoffset = stdoffset - SECSPERHOUR; + if (*name == ',' || *name == ';') + { + struct rule start; + struct rule end; + int year; + time_t janfirst; + time_t starttime; + time_t endtime; + + ++name; + if ((name = getrule(name, &start)) == NULL) + return -1; + if (*name++ != ',') + return -1; + if ((name = getrule(name, &end)) == NULL) + return -1; + if (*name != '\0') + return -1; + sp->typecnt = 2; /* standard time and DST */ + /* + ** Two transitions per year, from EPOCH_YEAR to 2037. + */ + sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); + if (sp->timecnt > TZ_MAX_TIMES) + return -1; + sp->ttis[0].tt_gmtoff = -dstoffset; + sp->ttis[0].tt_isdst = 1; + sp->ttis[0].tt_abbrind = stdlen + 1; + sp->ttis[1].tt_gmtoff = -stdoffset; + sp->ttis[1].tt_isdst = 0; + sp->ttis[1].tt_abbrind = 0; + atp = sp->ats; + typep = sp->types; + janfirst = 0; + for (year = EPOCH_YEAR; year <= 2037; ++year) + { + starttime = transtime(janfirst, year, &start, + stdoffset); + endtime = transtime(janfirst, year, &end, + dstoffset); + if (starttime > endtime) + { + *atp++ = endtime; + *typep++ = 1; /* DST ends */ + *atp++ = starttime; + *typep++ = 0; /* DST begins */ + } + else + { + *atp++ = starttime; + *typep++ = 0; /* DST begins */ + *atp++ = endtime; + *typep++ = 1; /* DST ends */ + } + janfirst += + year_lengths[isleap(year)] * SECSPERDAY; + } + } + else + { + int sawstd; + int sawdst; + long stdfix; + long dstfix; + long oldfix; + int isdst; + int i; + + if (*name != '\0') + return -1; + if (load_result != 0) + return -1; + /* + ** Compute the difference between the real and + ** prototype standard and summer time offsets + ** from GMT, and put the real standard and summer + ** time offsets into the rules in place of the + ** prototype offsets. + */ + sawstd = FALSE; + sawdst = FALSE; + stdfix = 0; + dstfix = 0; + for (i = 0; i < sp->typecnt; ++i) + { + if (sp->ttis[i].tt_isdst) + { + oldfix = dstfix; + dstfix = + sp->ttis[i].tt_gmtoff + dstoffset; + if (sawdst && (oldfix != dstfix)) + return -1; + sp->ttis[i].tt_gmtoff = -dstoffset; + sp->ttis[i].tt_abbrind = stdlen + 1; + sawdst = TRUE; + } + else + { + oldfix = stdfix; + stdfix = + sp->ttis[i].tt_gmtoff + stdoffset; + if (sawstd && (oldfix != stdfix)) + return -1; + sp->ttis[i].tt_gmtoff = -stdoffset; + sp->ttis[i].tt_abbrind = 0; + sawstd = TRUE; + } + } + /* + ** Make sure we have both standard and summer time. + */ + if (!sawdst || !sawstd) + return -1; + /* + ** Now correct the transition times by shifting + ** them by the difference between the real and + ** prototype offsets. Note that this difference + ** can be different in standard and summer time; + ** the prototype probably has a 1-hour difference + ** between standard and summer time, but a different + ** difference can be specified in TZ. + */ + isdst = FALSE; /* we start in standard time */ + for (i = 0; i < sp->timecnt; ++i) + { + const struct ttinfo * ttisp; + + /* + ** If summer time is in effect, and the + ** transition time was not specified as + ** standard time, add the summer time + ** offset to the transition time; + ** otherwise, add the standard time offset + ** to the transition time. + */ + ttisp = &sp->ttis[sp->types[i]]; + sp->ats[i] += + (isdst && !ttisp->tt_ttisstd) ? + dstfix : stdfix; + isdst = ttisp->tt_isdst; + } + } + } + else + { + dstlen = 0; + sp->typecnt = 1; /* only standard time */ + sp->timecnt = 0; + sp->ttis[0].tt_gmtoff = -stdoffset; + sp->ttis[0].tt_isdst = 0; + sp->ttis[0].tt_abbrind = 0; + } + sp->charcnt = stdlen + 1; + if (dstlen != 0) + sp->charcnt += dstlen + 1; + if (sp->charcnt > sizeof sp->chars) + return -1; + cp = sp->chars; + (void) strncpy(cp, stdname, stdlen); + cp += stdlen; + *cp++ = '\0'; + if (dstlen != 0) + { + (void) strncpy(cp, dstname, dstlen); + *(cp + dstlen) = '\0'; + } + return 0; +} + +static void +gmtload(struct state * const sp) +{ + if (tzload(GMT, sp) != 0) + (void) tzparse(GMT, sp, TRUE); +} + +void +_tzset(void) +{ + const char * name; + + name = getenv("TZ"); + if (name == NULL) + { + tzsetwall(); + return; + } + lcl_is_set = TRUE; +#ifdef ALL_STATE + if (lclptr == NULL) + { + lclptr = (struct state *) malloc(sizeof *lclptr); + if (lclptr == NULL) + { + settzname(); /* all we can do */ + return; + } + } +#endif /* defined ALL_STATE */ + if (*name == '\0') + { + /* + ** User wants it fast rather than right. + */ + lclptr->leapcnt = 0; /* so, we're off a little */ + lclptr->timecnt = 0; + lclptr->ttis[0].tt_gmtoff = 0; + lclptr->ttis[0].tt_abbrind = 0; + (void) strcpy(lclptr->chars, GMT); + } + else if (tzload(name, lclptr) != 0) + if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) + gmtload(lclptr); + settzname(); +} + +void +tzsetwall(void) +{ + lcl_is_set = TRUE; +#ifdef ALL_STATE + if (lclptr == NULL) + { + lclptr = (struct state *) malloc(sizeof *lclptr); + if (lclptr == NULL) + { + settzname(); /* all we can do */ + return; + } + } +#endif /* defined ALL_STATE */ + if (tzload((char *) NULL, lclptr) != 0) + gmtload(lclptr); + settzname(); +} + +/* +** The easy way to behave "as if no library function calls" localtime +** is to not call it--so we drop its guts into "localsub", which can be +** freely called. (And no, the PANS doesn't require the above behavior-- +** but it *is* desirable.) +** +** The unused offset argument is for the benefit of mktime variants. +*/ + +/*ARGSUSED*/ +static void +localsub(const time_t * const timep, const long offset, struct tm * const tmp) +{ + const struct state * sp; + const struct ttinfo * ttisp; + int i; + const time_t t = *timep; + + if (!lcl_is_set) + _tzset(); + sp = lclptr; +#ifdef ALL_STATE + if (sp == NULL) + { + gmtsub(timep, offset, tmp); + return; + } +#endif /* defined ALL_STATE */ + if (sp->timecnt == 0 || t < sp->ats[0]) + { + i = 0; + while (sp->ttis[i].tt_isdst) + if (++i >= sp->typecnt) + { + i = 0; + break; + } + } + else + { + for (i = 1; i < sp->timecnt; ++i) + if (t < sp->ats[i]) + break; + i = sp->types[i - 1]; + } + ttisp = &sp->ttis[i]; + /* + ** To get (wrong) behavior that's compatible with System V Release 2.0 + ** you'd replace the statement below with + ** t += ttisp->tt_gmtoff; + ** timesub(&t, 0L, sp, tmp); + */ + timesub(&t, ttisp->tt_gmtoff, sp, tmp); + tmp->tm_isdst = ttisp->tt_isdst; + _tzname[tmp->tm_isdst] = (char *)&sp->chars[ttisp->tt_abbrind]; + tmp->tm_zone = (char *)&sp->chars[ttisp->tt_abbrind]; +} + +struct tm * +localtime(const time_t * const timep) +{ + static struct tm tm; + + localsub(timep, 0L, &tm); + return &tm; +} + +/* +** gmtsub is to gmtime as localsub is to localtime. +*/ + +static void +gmtsub(const time_t * const timep, const long offset, struct tm * const tmp) +{ + if (!gmt_is_set) + { + gmt_is_set = TRUE; +#ifdef ALL_STATE + gmtptr = (struct state *) malloc(sizeof *gmtptr); + if (gmtptr != NULL) +#endif /* defined ALL_STATE */ + gmtload(gmtptr); + } + timesub(timep, offset, gmtptr, tmp); + /* + ** Could get fancy here and deliver something such as + ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero, + ** but this is no time for a treasure hunt. + */ + if (offset != 0) + tmp->tm_zone = WILDABBR; + else + { +#ifdef ALL_STATE + if (gmtptr == NULL) + tmp->TM_ZONE = GMT; + else + tmp->TM_ZONE = gmtptr->chars; +#endif /* defined ALL_STATE */ +#ifndef ALL_STATE + tmp->tm_zone = gmtptr->chars; +#endif /* State Farm */ + } +} + +struct tm * +gmtime(const time_t * const timep) +{ + static struct tm tm; + + gmtsub(timep, 0L, &tm); + return &tm; +} + +static void +timesub(const time_t * const timep, const long offset, const struct state * const sp, struct tm * const tmp) +{ + const struct lsinfo * lp; + long days; + long rem; + int y; + int yleap; + const int * ip; + long corr; + int hit; + int i; + + corr = 0; + hit = FALSE; +#ifdef ALL_STATE + i = (sp == NULL) ? 0 : sp->leapcnt; +#endif /* defined ALL_STATE */ +#ifndef ALL_STATE + i = sp->leapcnt; +#endif /* State Farm */ + while (--i >= 0) + { + lp = &sp->lsis[i]; + if (*timep >= lp->ls_trans) + { + if (*timep == lp->ls_trans) + hit = ((i == 0 && lp->ls_corr > 0) || + lp->ls_corr > sp->lsis[i - 1].ls_corr); + corr = lp->ls_corr; + break; + } + } + days = *timep / SECSPERDAY; + rem = *timep % SECSPERDAY; +#ifdef mc68k + if (*timep == 0x80000000) + { + /* + ** A 3B1 muffs the division on the most negative number. + */ + days = -24855; + rem = -11648; + } +#endif /* mc68k */ + rem += (offset - corr); + while (rem < 0) + { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) + { + rem -= SECSPERDAY; + ++days; + } + tmp->tm_hour = (int) (rem / SECSPERHOUR); + rem = rem % SECSPERHOUR; + tmp->tm_min = (int) (rem / SECSPERMIN); + tmp->tm_sec = (int) (rem % SECSPERMIN); + if (hit) + /* + ** A positive leap second requires a special + ** representation. This uses "... ??:59:60". + */ + ++(tmp->tm_sec); + tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); + if (tmp->tm_wday < 0) + tmp->tm_wday += DAYSPERWEEK; + y = EPOCH_YEAR; + if (days >= 0) + for ( ; ; ) + { + yleap = isleap(y); + if (days < (long) year_lengths[yleap]) + break; + ++y; + days = days - (long) year_lengths[yleap]; + } + else + do { + --y; + yleap = isleap(y); + days = days + (long) year_lengths[yleap]; + } while (days < 0); + tmp->tm_year = y - TM_YEAR_BASE; + tmp->tm_yday = (int) days; + ip = mon_lengths[yleap]; + for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) + days = days - (long) ip[tmp->tm_mon]; + tmp->tm_mday = (int) (days + 1); + tmp->tm_isdst = 0; + tmp->tm_gmtoff = offset; +} + +/* +** A la X3J11 +*/ + +char * +asctime(const struct tm *timeptr) +{ + static const char wday_name[DAYSPERWEEK][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char mon_name[MONSPERYEAR][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + static char result[26]; + + (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + wday_name[timeptr->tm_wday], + mon_name[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, + TM_YEAR_BASE + timeptr->tm_year); + return result; +} + +wchar_t * +_wasctime(const struct tm *timeptr) +{ + static const wchar_t wday_name[DAYSPERWEEK][3] = { + L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat" + }; + static const wchar_t mon_name[MONSPERYEAR][3] = { + L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", + L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec" + }; + static wchar_t result[26]; + + (void)swprintf(result, L"%.3s %.3s%3d %02d:%02d:%02d %d\n", + wday_name[timeptr->tm_wday], + mon_name[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, + TM_YEAR_BASE + timeptr->tm_year); + return result; +} + + +char * +ctime(const time_t * const timep) +{ + return asctime(localtime(timep)); +} + +wchar_t * +_wctime(const time_t * const timep) +{ + return _wasctime(localtime(timep)); +} + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static void +normalize(int * const tensptr, int * const unitsptr, const int base) +{ + if (*unitsptr >= base) + { + *tensptr += *unitsptr / base; + *unitsptr %= base; + } + else if (*unitsptr < 0) + { + --*tensptr; + *unitsptr += base; + if (*unitsptr < 0) + { + *tensptr -= 1 + (-*unitsptr) / base; + *unitsptr = base - (-*unitsptr) % base; + } + } +} + +static int +tmcomp(const struct tm * const atmp, const struct tm * const btmp) +{ + int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t +time2(struct tm *tmp, void (*const funcp)(const time_t *const,const long,struct tm *), const long offset, int * const okayp) +{ + const struct state * sp; + int dir; + int bits; + int i, j ; + int saved_seconds; + time_t newt; + time_t t; + struct tm yourtm, mytm; + + *okayp = FALSE; + yourtm = *tmp; + if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0) + normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN); + normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR); + normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY); + normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR); + while (yourtm.tm_mday <= 0) + { + --yourtm.tm_year; + yourtm.tm_mday += + year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; + } + for ( ; ; ) + { + i = mon_lengths[isleap(yourtm.tm_year + + TM_YEAR_BASE)][yourtm.tm_mon]; + if (yourtm.tm_mday <= i) + break; + yourtm.tm_mday -= i; + if (++yourtm.tm_mon >= MONSPERYEAR) + { + yourtm.tm_mon = 0; + ++yourtm.tm_year; + } + } + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (time_t) ((1 << bits) - 1); + for ( ; ; ) + { + (*funcp)(&t, offset, &mytm); + dir = tmcomp(&mytm, &yourtm); + if (dir != 0) + { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) + break; + /* + ** Right time, wrong type. + ** Hunt for right time, right type. + ** It's okay to guess wrong since the guess + ** gets checked. + */ + sp = (const struct state *) + ((funcp == localsub) ? lclptr : gmtptr); +#ifdef ALL_STATE + if (sp == NULL) + return WRONG; +#endif /* defined ALL_STATE */ + for (i = 0; i < sp->typecnt; ++i) + { + if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) + continue; + for (j = 0; j < sp->typecnt; ++j) + { + if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) + continue; + newt = t + sp->ttis[j].tt_gmtoff - + sp->ttis[i].tt_gmtoff; + (*funcp)(&newt, offset, &mytm); + if (tmcomp(&mytm, &yourtm) != 0) + continue; + if (mytm.tm_isdst != yourtm.tm_isdst) + continue; + /* + ** We have a match. + */ + t = newt; + goto label; + } + } + return WRONG; + } + label: + t += saved_seconds; + (*funcp)(&t, offset, tmp); + *okayp = TRUE; + return t; +} + +static time_t +time1(struct tm * const tmp, void (*const funcp)(const time_t * const, const long, struct tm *), const long offset) +{ + time_t t; + const struct state * sp; + int samei, otheri; + int okay; + + if (tmp->tm_isdst > 1) + tmp->tm_isdst = 1; + t = time2(tmp, funcp, offset, &okay); + if (okay || tmp->tm_isdst < 0) + return t; + /* + ** We're supposed to assume that somebody took a time of one type + ** and did some math on it that yielded a "struct tm" that's bad. + ** We try to divine the type they started from and adjust to the + ** type they need. + */ + sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr); +#ifdef ALL_STATE + if (sp == NULL) + return WRONG; +#endif /* defined ALL_STATE */ + for (samei = 0; samei < sp->typecnt; ++samei) + { + if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) + continue; + for (otheri = 0; otheri < sp->typecnt; ++otheri) + { + if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) + continue; + tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - + sp->ttis[samei].tt_gmtoff; + tmp->tm_isdst = !tmp->tm_isdst; + t = time2(tmp, funcp, offset, &okay); + if (okay) + return t; + tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - + sp->ttis[samei].tt_gmtoff; + tmp->tm_isdst = !tmp->tm_isdst; + } + } + return WRONG; +} + +time_t +mktime(struct tm * tmp) +{ + return time1(tmp, localsub, 0L); +} + + + + diff --git a/lib/msvcrt/time/difftime.c b/lib/msvcrt/time/difftime.c new file mode 100644 index 0000000..87f4005 --- /dev/null +++ b/lib/msvcrt/time/difftime.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +double +difftime(time_t time1, time_t time0) +{ + return time1-time0; +} diff --git a/lib/msvcrt/time/posixrul.h b/lib/msvcrt/time/posixrul.h new file mode 100644 index 0000000..48c5cee --- /dev/null +++ b/lib/msvcrt/time/posixrul.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +/* generated with bin2h from DJGPP/zoneinfo/posixrules */ + +unsigned char _posixrules_data[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,16,0,0,0,2,0,0,0,8,0,151,254,240,1,135,225,224,2,119,224,240,3,112,254,96,4,96,253,112,5,80, +224,96,6,64,223,112,7,48,194,96,7,141,25,112,9,16,164,96,9,173,148,240,10,240,134,96,11,224,133,112,12,217,162, +224,13,192,103,112,14,185,132,224,15,169,131,240,16,153,102,224,17,137,101,240,18,121,72,224,19,105,71,240,20,89,42,224, +21,73,41,240,22,57,12,224,23,41,11,240,24,34,41,96,25,8,237,240,26,2,11,96,26,242,10,112,27,225,237,96,28, +209,236,112,29,193,207,96,30,177,206,112,31,161,177,96,32,118,0,240,33,129,147,96,34,85,226,240,35,106,175,224,36,53, +196,240,37,74,145,224,38,21,166,240,39,42,115,224,39,254,195,112,41,10,85,224,41,222,165,112,42,234,55,224,43,190,135, +112,44,211,84,96,45,158,105,112,46,179,54,96,47,126,75,112,48,147,24,96,49,103,103,240,50,114,250,96,51,71,73,240, +52,82,220,96,53,39,43,240,54,50,190,96,55,7,13,240,56,27,218,224,56,230,239,240,57,251,188,224,58,198,209,240,59, +219,158,224,60,175,238,112,61,187,128,224,62,143,208,112,63,155,98,224,64,111,178,112,65,132,127,96,66,79,148,112,67,100, +97,96,68,47,118,112,69,68,67,96,70,15,88,112,71,36,37,96,71,248,116,240,73,4,7,96,73,216,86,240,74,227,233, +96,75,184,56,240,76,205,5,224,77,152,26,240,78,172,231,224,79,119,252,240,80,140,201,224,81,97,25,112,82,108,171,224, +83,64,251,112,84,76,141,224,85,32,221,112,86,44,111,224,87,0,191,112,88,21,140,96,88,224,161,112,89,245,110,96,90, +192,131,112,91,213,80,96,92,169,159,240,93,181,50,96,94,137,129,240,95,149,20,96,96,105,99,240,97,126,48,224,98,73, +69,240,99,94,18,224,100,41,39,240,101,61,244,224,102,18,68,112,103,29,214,224,103,242,38,112,104,253,184,224,105,210,8, +112,106,221,154,224,107,177,234,112,108,198,183,96,109,145,204,112,110,166,153,96,111,113,174,112,112,134,123,96,113,90,202,240, +114,102,93,96,115,58,172,240,116,70,63,96,117,26,142,240,118,47,91,224,118,250,112,240,120,15,61,224,120,218,82,240,121, +239,31,224,122,186,52,240,123,207,1,224,124,163,81,112,125,174,227,224,126,131,51,112,127,142,197,224,128,99,21,112,129,119, +226,96,130,66,247,112,131,87,196,96,132,34,217,112,133,55,166,96,134,11,245,240,135,23,136,96,135,235,215,240,136,247,106, +96,137,203,185,240,138,215,76,96,139,171,155,240,140,192,104,224,141,139,125,240,142,160,74,224,143,107,95,240,144,128,44,224, +145,84,124,112,146,96,14,224,147,52,94,112,148,63,240,224,149,20,64,112,150,41,13,96,150,244,34,112,152,8,239,96,152, +212,4,112,153,232,209,96,154,189,32,240,155,200,179,96,156,157,2,240,157,168,149,96,158,124,228,240,159,136,119,96,160,92, +198,240,161,113,147,224,162,60,168,240,163,81,117,224,164,28,138,240,165,49,87,224,166,5,167,112,167,17,57,224,167,229,137, +112,168,241,27,224,169,197,107,112,170,218,56,96,171,165,77,112,172,186,26,96,173,133,47,112,174,153,252,96,175,101,17,112, +176,121,222,96,177,78,45,240,178,89,192,96,179,46,15,240,180,57,162,96,181,13,241,240,182,34,190,224,182,237,211,240,184, +2,160,224,184,205,181,240,185,226,130,224,186,182,210,112,187,194,100,224,188,150,180,112,189,162,70,224,190,118,150,112,191,130, +40,224,192,86,120,112,193,107,69,96,194,54,90,112,195,75,39,96,196,22,60,112,197,43,9,96,197,255,88,240,199,10,235, +96,199,223,58,240,200,234,205,96,201,191,28,240,202,211,233,224,203,158,254,240,204,179,203,224,205,126,224,240,206,147,173,224, +207,103,253,112,208,115,143,224,209,71,223,112,210,83,113,224,211,39,193,112,212,51,83,224,213,7,163,112,214,28,112,96,214, +231,133,112,215,252,82,96,216,199,103,112,217,220,52,96,218,176,131,240,219,188,22,96,220,144,101,240,221,155,248,96,222,112, +71,240,223,133,20,224,224,80,41,240,225,100,246,224,226,48,11,240,227,68,216,224,228,15,237,240,229,36,186,224,229,249,10, +112,231,4,156,224,231,216,236,112,232,228,126,224,233,184,206,112,234,205,155,96,235,152,176,112,236,173,125,96,237,120,146,112, +238,141,95,96,239,97,174,240,240,109,65,96,241,65,144,240,242,77,35,96,243,33,114,240,244,45,5,96,245,1,84,240,246, +22,33,224,246,225,54,240,247,246,3,224,248,193,24,240,249,213,229,224,250,160,250,240,251,181,199,224,252,138,23,112,253,149, +169,224,254,105,249,112,255,117,139,224,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0, +1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, +0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,255,255,199,192,1,0,255,255,185,176,0,4,69,68,84, +0,69,83,84,0,0,0 +}; diff --git a/lib/msvcrt/time/strdate.c b/lib/msvcrt/time/strdate.c new file mode 100644 index 0000000..91ff36c --- /dev/null +++ b/lib/msvcrt/time/strdate.c @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/msvcrt/time/strtime.c + * PURPOSE: Fills a buffer with a formatted date representation + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ +#include +#include +#include +#include + +char *_strdate( const char *datestr ) +{ + time_t t; + struct tm *d; + char *dt = (char *)datestr; + + if ( datestr == NULL ) + { + __set_errno(EINVAL); + return NULL; + } + t = time(NULL); + d = localtime(&t); + sprintf(dt,"%d/%d/%d",d->tm_mday,d->tm_mon+1,d->tm_year); + return dt; +} + +wchar_t *_wstrdate( const wchar_t *datestr ) +{ + time_t t; + struct tm *d; + wchar_t *dt = (wchar_t *)datestr; + + if ( datestr == NULL ) + { + __set_errno(EINVAL); + return NULL; + } + t = time(NULL); + d = localtime(&t); + swprintf(dt,L"%d/%d/%d",d->tm_mday,d->tm_mon+1,d->tm_year); + return dt; +} diff --git a/lib/msvcrt/time/strftime.c b/lib/msvcrt/time/strftime.c new file mode 100644 index 0000000..96831ed --- /dev/null +++ b/lib/msvcrt/time/strftime.c @@ -0,0 +1,264 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +#define TM_YEAR_BASE 1900 + +static const char *afmt[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", +}; +static const char *Afmt[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", + "Saturday", +}; +static const char *bfmt[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec", +}; +static const char *Bfmt[] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December", +}; + +static size_t gsize; +static char *pt; + +static int +_add(const char *str) +{ + for (;; ++pt, --gsize) + { + if (!gsize) + return 0; + if (!(*pt = *str++)) + return 1; + } +} + +static int +_conv(int n, int digits, char pad) +{ + static char buf[10]; + char *p; + + for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) + *p-- = n % 10 + '0'; + while (p > buf && digits-- > 0) + *p-- = pad; + return _add(++p); +} + +static size_t +_fmt(const char *format, const struct tm *t) +{ + for (; *format; ++format) + { + if (*format == '%') { + if (*(format+1) == '#' ) {format++;} + + switch(*++format) + { + case '\0': + --format; + break; + case 'A': + if (t->tm_wday < 0 || t->tm_wday > 6) + return 0; + if (!_add(Afmt[t->tm_wday])) + return 0; + continue; + case 'a': + if (t->tm_wday < 0 || t->tm_wday > 6) + return 0; + if (!_add(afmt[t->tm_wday])) + return 0; + continue; + case 'B': + if (t->tm_mon < 0 || t->tm_mon > 11) + return 0; + if (!_add(Bfmt[t->tm_mon])) + return 0; + continue; + case 'b': + case 'h': + if (t->tm_mon < 0 || t->tm_mon > 11) + return 0; + if (!_add(bfmt[t->tm_mon])) + return 0; + continue; + case 'C': + if (!_fmt("%a %b %e %H:%M:%S %Y", t)) + return 0; + continue; + case 'c': + if (!_fmt("%m/%d/%y %H:%M:%S", t)) + return 0; + continue; + case 'e': + if (!_conv(t->tm_mday, 2, ' ')) + return 0; + continue; + case 'D': + if (!_fmt("%m/%d/%y", t)) + return 0; + continue; + case 'd': + if (!_conv(t->tm_mday, 2, '0')) + return 0; + continue; + case 'H': + if (!_conv(t->tm_hour, 2, '0')) + return 0; + continue; + case 'I': + if (!_conv(t->tm_hour % 12 ? + t->tm_hour % 12 : 12, 2, '0')) + return 0; + continue; + case 'j': + if (!_conv(t->tm_yday + 1, 3, '0')) + return 0; + continue; + case 'k': + if (!_conv(t->tm_hour, 2, ' ')) + return 0; + continue; + case 'l': + if (!_conv(t->tm_hour % 12 ? + t->tm_hour % 12 : 12, 2, ' ')) + return 0; + continue; + case 'M': + if (!_conv(t->tm_min, 2, '0')) + return 0; + continue; + case 'm': + if (!_conv(t->tm_mon + 1, 2, '0')) + return 0; + continue; + case 'n': + if (!_add("\n")) + return 0; + continue; + case 'p': + if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) + return 0; + continue; + case 'R': + if (!_fmt("%H:%M", t)) + return 0; + continue; + case 'r': + if (!_fmt("%I:%M:%S %p", t)) + return 0; + continue; + case 'S': + if (!_conv(t->tm_sec, 2, '0')) + return 0; + continue; + case 'T': + case 'X': + if (!_fmt("%H:%M:%S", t)) + return 0; + continue; + case 't': + if (!_add("\t")) + return 0; + continue; + case 'U': + if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, + 2, '0')) + return 0; + continue; + case 'W': + if (!_conv((t->tm_yday + 7 - + (t->tm_wday ? (t->tm_wday - 1) : 6)) + / 7, 2, '0')) + return 0; + continue; + case 'w': + if (!_conv(t->tm_wday, 1, '0')) + return 0; + continue; + case 'x': + if (!_fmt("%m/%d/%y", t)) + return 0; + continue; + case 'y': + if (!_conv((t->tm_year + TM_YEAR_BASE) + % 100, 2, '0')) + return 0; + continue; + case 'Y': + if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) + return 0; + continue; + case 'Z': + if (!t->tm_zone || !_add(t->tm_zone)) + return 0; + continue; + case '%': + /* + * X311J/88-090 (4.12.3.5): if conversion char is + * undefined, behavior is undefined. Print out the + * character itself as printf(3) does. + */ + default: + break; + } + } + if (!gsize--) + return 0; + *pt++ = *format; + } + return gsize; +} + +size_t +strftime(char *s, size_t maxsize, const char *format, const struct tm *t) +{ + pt = s; + if ((gsize = maxsize) < 1) + return 0; + if (_fmt(format, t)) + { + *pt = '\0'; + return maxsize - gsize; + } + return 0; +} + +size_t +wcsftime(wchar_t *s, size_t maxsize, const wchar_t *format, const struct tm *t) +{ + char *x; + char *f; + int i,j; + x = malloc(maxsize); + j = wcslen(format); + f = malloc(j+1); + for(i=0;i +#include +#include +#include + +char *_strtime(char* buf) +{ + time_t t; + struct tm *d; + char *dt = (char *)buf; + + if ( buf == NULL ) + { + __set_errno(EINVAL); + return NULL; + } + t = time(NULL); + d = localtime(&t); + sprintf(dt,"%d:%d:%d",d->tm_hour,d->tm_min,d->tm_sec); + return dt; +} + +wchar_t *_wstrtime(wchar_t* buf) +{ + time_t t; + struct tm *d; + wchar_t *dt = (wchar_t *)buf; + + if ( buf == NULL ) + { + __set_errno(EINVAL); + return NULL; + } + t = time(NULL); + d = localtime(&t); + swprintf(dt,L"%d:%d:%d",d->tm_hour,d->tm_min,d->tm_sec); + return dt; +} diff --git a/lib/msvcrt/time/time.c b/lib/msvcrt/time/time.c new file mode 100644 index 0000000..6b0da0b --- /dev/null +++ b/lib/msvcrt/time/time.c @@ -0,0 +1,223 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/crtdll/conio/time.c + * PURPOSE: Get system time + * PROGRAMER: Boudewijn Dekker + * UPDATE HISTORY: + * 28/12/98: Created + */ + +/* + * DOS file system functions + * + * Copyright 1993 Erik Bos + * Copyright 1996 Alexandre Julliard + */ + +#include +#include +#include + +VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime ); + +time_t +time(time_t *t) +{ + FILETIME SystemTime; + DWORD Remainder; + time_t tt; + GetSystemTimeAsFileTime(&SystemTime); + tt = FileTimeToUnixTime( &SystemTime,&Remainder ); + if (t) + *t = tt; + return tt; +} + +/*********************************************************************** + * DOSFS_UnixTimeToFileTime + * + * Convert a Unix time to FILETIME format. + * The FILETIME structure is a 64-bit value representing the number of + * 100-nanosecond intervals since January 1, 1601, 0:00. + * 'remainder' is the nonnegative number of 100-ns intervals + * corresponding to the time fraction smaller than 1 second that + * couldn't be stored in the time_t value. + */ +void UnixTimeToFileTime( time_t unix_time, FILETIME *filetime, + DWORD remainder ) +{ + /* NOTES: + + CONSTANTS: + The time difference between 1 January 1601, 00:00:00 and + 1 January 1970, 00:00:00 is 369 years, plus the leap years + from 1604 to 1968, excluding 1700, 1800, 1900. + This makes (1968 - 1600) / 4 - 3 = 89 leap days, and a total + of 134774 days. + + Any day in that period had 24 * 60 * 60 = 86400 seconds. + + The time difference is 134774 * 86400 * 10000000, which can be written + 116444736000000000 + 27111902 * 2^32 + 3577643008 + 413 * 2^48 + 45534 * 2^32 + 54590 * 2^16 + 32768 + + If you find that these constants are buggy, please change them in all + instances in both conversion functions. + + VERSIONS: + There are two versions, one of them uses long long variables and + is presumably faster but not ISO C. The other one uses standard C + data types and operations but relies on the assumption that negative + numbers are stored as 2's complement (-1 is 0xffff....). If this + assumption is violated, dates before 1970 will not convert correctly. + This should however work on any reasonable architecture where WINE + will run. + + DETAILS: + + Take care not to remove the casts. I have tested these functions + (in both versions) for a lot of numbers. I would be interested in + results on other compilers than GCC. + + The operations have been designed to account for the possibility + of 64-bit time_t in future UNICES. Even the versions without + internal long long numbers will work if time_t only is 64 bit. + A 32-bit shift, which was necessary for that operation, turned out + not to work correctly in GCC, besides giving the warning. So I + used a double 16-bit shift instead. Numbers are in the ISO version + represented by three limbs, the most significant with 32 bit, the + other two with 16 bit each. + + As the modulo-operator % is not well-defined for negative numbers, + negative divisors have been avoided in DOSFS_FileTimeToUnixTime. + + There might be quicker ways to do this in C. Certainly so in + assembler. + + Claus Fischer, fischer@iue.tuwien.ac.at + */ + + + + + unsigned long a0; /* 16 bit, low bits */ + unsigned long a1; /* 16 bit, medium bits */ + unsigned long a2; /* 32 bit, high bits */ + + /* Copy the unix time to a2/a1/a0 */ + a0 = unix_time & 0xffff; + a1 = (unix_time >> 16) & 0xffff; + /* This is obsolete if unix_time is only 32 bits, but it does not hurt. + Do not replace this by >> 32, it gives a compiler warning and it does + not work. */ + a2 = (unix_time >= 0 ? (unix_time >> 16) >> 16 : + ~((~unix_time >> 16) >> 16)); + + /* Multiply a by 10000000 (a = a2/a1/a0) + Split the factor into 10000 * 1000 which are both less than 0xffff. */ + a0 *= 10000; + a1 = a1 * 10000 + (a0 >> 16); + a2 = a2 * 10000 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + a0 *= 1000; + a1 = a1 * 1000 + (a0 >> 16); + a2 = a2 * 1000 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + /* Add the time difference and the remainder */ + a0 += 32768 + (remainder & 0xffff); + a1 += 54590 + (remainder >> 16 ) + (a0 >> 16); + a2 += 27111902 + (a1 >> 16); + a0 &= 0xffff; + a1 &= 0xffff; + + /* Set filetime */ + filetime->dwLowDateTime = (a1 << 16) + a0; + filetime->dwHighDateTime = a2; +} + + +/*********************************************************************** + * DOSFS_FileTimeToUnixTime + * + * Convert a FILETIME format to Unix time. + * If not NULL, 'remainder' contains the fractional part of the filetime, + * in the range of [0..9999999] (even if time_t is negative). + */ +time_t FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ) +{ + /* Read the comment in the function DOSFS_UnixTimeToFileTime. */ + + unsigned long a0; /* 16 bit, low bits */ + unsigned long a1; /* 16 bit, medium bits */ + unsigned long a2; /* 32 bit, high bits */ + unsigned long r; /* remainder of division */ + unsigned int carry; /* carry bit for subtraction */ + int negative; /* whether a represents a negative value */ + + /* Copy the time values to a2/a1/a0 */ + a2 = (unsigned long)filetime->dwHighDateTime; + a1 = ((unsigned long)filetime->dwLowDateTime ) >> 16; + a0 = ((unsigned long)filetime->dwLowDateTime ) & 0xffff; + + /* Subtract the time difference */ + if (a0 >= 32768 ) a0 -= 32768 , carry = 0; + else a0 += (1 << 16) - 32768 , carry = 1; + + if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0; + else a1 += (1 << 16) - 54590 - carry, carry = 1; + + a2 -= 27111902 + carry; + + /* If a is negative, replace a by (-1-a) */ + negative = (a2 >= ((unsigned long)1) << 31); + if (negative) + { + /* Set a to -a - 1 (a is a2/a1/a0) */ + a0 = 0xffff - a0; + a1 = 0xffff - a1; + a2 = ~a2; + } + + /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r. + Split the divisor into 10000 * 1000 which are both less than 0xffff. */ + a1 += (a2 % 10000) << 16; + a2 /= 10000; + a0 += (a1 % 10000) << 16; + a1 /= 10000; + r = a0 % 10000; + a0 /= 10000; + + a1 += (a2 % 1000) << 16; + a2 /= 1000; + a0 += (a1 % 1000) << 16; + a1 /= 1000; + r += (a0 % 1000) * 10000; + a0 /= 1000; + + /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */ + if (negative) + { + /* Set a to -a - 1 (a is a2/a1/a0) */ + a0 = 0xffff - a0; + a1 = 0xffff - a1; + a2 = ~a2; + + r = 9999999 - r; + } + + if (remainder) *remainder = r; + + /* Do not replace this by << 32, it gives a compiler warning and it does + not work. */ + return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0; + +} + + + diff --git a/lib/msvcrt/time/tzfile.h b/lib/msvcrt/time/tzfile.h new file mode 100644 index 0000000..3999029 --- /dev/null +++ b/lib/msvcrt/time/tzfile.h @@ -0,0 +1,160 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#ifndef __dj_include_tzfile_h__ +#define __dj_include_tzfile_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __dj_ENFORCE_ANSI_FREESTANDING + +#ifndef __STRICT_ANSI__ + +#ifndef _POSIX_SOURCE + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)tzfile.h 5.9 (Berkeley) 6/11/90 + */ + +/* +** Information about time zone files. +*/ + + /* Time zone object file directory */ +#define TZDIR "/usr/share/zoneinfo" +#define TZDEFAULT "/etc/localtime" +#define TZDEFRULES "posixrules" + +/* +** Each file begins with. . . +*/ + +struct tzhead { + char tzh_reserved[24]; /* reserved for future use */ + char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ + char tzh_leapcnt[4]; /* coded number of leap seconds */ + char tzh_timecnt[4]; /* coded number of transition times */ + char tzh_typecnt[4]; /* coded number of local time types */ + char tzh_charcnt[4]; /* coded number of abbr. chars */ +}; + +/* +** . . .followed by. . . +** +** tzh_timecnt (char [4])s coded transition times a la time(2) +** tzh_timecnt (unsigned char)s types of local time starting at above +** tzh_typecnt repetitions of +** one (char [4]) coded GMT offset in seconds +** one (unsigned char) used to set tm_isdst +** one (unsigned char) that's an abbreviation list index +** tzh_charcnt (char)s '\0'-terminated zone abbreviations +** tzh_leapcnt repetitions of +** one (char [4]) coded leap second transition times +** one (char [4]) total correction after above +** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition +** time is standard time, if FALSE, +** transition time is wall clock time +** if absent, transition times are +** assumed to be wall clock time +*/ + +/* +** In the current implementation, "tzset()" refuses to deal with files that +** exceed any of the limits below. +*/ + +/* +** The TZ_MAX_TIMES value below is enough to handle a bit more than a +** year's worth of solar time (corrected daily to the nearest second) or +** 138 years of Pacific Presidential Election time +** (where there are three time zone transitions every fourth year). +*/ +#define TZ_MAX_TIMES 370 + +#define NOSOLAR /* 4BSD doesn't currently handle solar time */ + +#ifndef NOSOLAR +#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +#else +#define TZ_MAX_TYPES 10 /* Maximum number of local time types */ +#endif + +#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ + +#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_JANUARY 0 +#define TM_FEBRUARY 1 +#define TM_MARCH 2 +#define TM_APRIL 3 +#define TM_MAY 4 +#define TM_JUNE 5 +#define TM_JULY 6 +#define TM_AUGUST 7 +#define TM_SEPTEMBER 8 +#define TM_OCTOBER 9 +#define TM_NOVEMBER 10 +#define TM_DECEMBER 11 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +/* +** Accurate only for the past couple of centuries; +** that will probably do. +*/ + +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +#endif /* !_POSIX_SOURCE */ +#endif /* !__STRICT_ANSI__ */ +#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ + +#ifndef __dj_ENFORCE_FUNCTION_CALLS +#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dj_include_tzfile_h__ */ diff --git a/lib/msvcrt/wstring/.cvsignore b/lib/msvcrt/wstring/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/msvcrt/wstring/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/msvcrt/wstring/wcscat.c b/lib/msvcrt/wstring/wcscat.c new file mode 100644 index 0000000..e561617 --- /dev/null +++ b/lib/msvcrt/wstring/wcscat.c @@ -0,0 +1,18 @@ + + +#include + +wchar_t * wcscat(wchar_t * dest,const wchar_t * src) +{ + wchar_t *d = dest; + for (; *dest !=0; dest++); + while (*src != 0) + { + *dest = *src; + dest++; + src++; + } + *dest = 0; + return d; +} + diff --git a/lib/msvcrt/wstring/wcschr.c b/lib/msvcrt/wstring/wcschr.c new file mode 100644 index 0000000..31ccb1d --- /dev/null +++ b/lib/msvcrt/wstring/wcschr.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +wchar_t* wcschr(const wchar_t* str, wchar_t ch) +{ + while ((*str)!=0) + { + if ((*str)==ch) + { + return((wchar_t *)str); + } + str++; + } + return(NULL); +} diff --git a/lib/msvcrt/wstring/wcscmp.c b/lib/msvcrt/wstring/wcscmp.c new file mode 100644 index 0000000..4d5a48f --- /dev/null +++ b/lib/msvcrt/wstring/wcscmp.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +int wcscmp(const wchar_t* cs,const wchar_t * ct) +{ + while (*cs == *ct) + { + if (*cs == 0) + return 0; + cs++; + ct++; + } + return *cs - *ct; +} diff --git a/lib/msvcrt/wstring/wcscoll.c b/lib/msvcrt/wstring/wcscoll.c new file mode 100644 index 0000000..21c51c2 --- /dev/null +++ b/lib/msvcrt/wstring/wcscoll.c @@ -0,0 +1,26 @@ + +#include + +int wcscoll(const wchar_t *a1,const wchar_t *a2) +{ + /* FIXME: handle collates */ + return wcscmp(a1,a2); +} + +int _wcsicoll(const wchar_t *a1,const wchar_t *a2) +{ + /* FIXME: handle collates */ + return _wcsicmp(a1,a2); +} + +int _wcsncoll (const wchar_t *s1, const wchar_t *s2, size_t c) +{ + /* FIXME: handle collates */ + return wcsncmp(s1,s2,c); +} + +int _wcsnicoll (const wchar_t *s1, const wchar_t *s2, size_t c) +{ + /* FIXME: handle collates */ + return _wcsnicmp(s1,s2,c); +} diff --git a/lib/msvcrt/wstring/wcscpy.c b/lib/msvcrt/wstring/wcscpy.c new file mode 100644 index 0000000..e63e91f --- /dev/null +++ b/lib/msvcrt/wstring/wcscpy.c @@ -0,0 +1,11 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +wchar_t * wcscpy(wchar_t * str1,const wchar_t * str2) +{ + wchar_t *save = str1; + + for (; (*str1 = *str2); ++str2, ++str1); + return save; +} diff --git a/lib/msvcrt/wstring/wcscspn.c b/lib/msvcrt/wstring/wcscspn.c new file mode 100644 index 0000000..4cccc33 --- /dev/null +++ b/lib/msvcrt/wstring/wcscspn.c @@ -0,0 +1,20 @@ +#include + +size_t wcscspn(const wchar_t *str,const wchar_t *reject) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do { + t=(wchar_t *)reject; + while (*t) { + if (*t==*s) + break; + t++; + } + if (*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} diff --git a/lib/msvcrt/wstring/wcsdup.c b/lib/msvcrt/wstring/wcsdup.c new file mode 100644 index 0000000..c3e646a --- /dev/null +++ b/lib/msvcrt/wstring/wcsdup.c @@ -0,0 +1,16 @@ +#include +#include +#include + + +wchar_t *_wcsdup(const wchar_t *ptr) +{ + wchar_t *dup; + dup = malloc((wcslen(ptr) + 1)*sizeof(wchar_t)); + if( dup == NULL ) { + __set_errno(ENOMEM); + return NULL; + } + wcscpy(dup,ptr); + return dup; +} diff --git a/lib/msvcrt/wstring/wcsicmp.c b/lib/msvcrt/wstring/wcsicmp.c new file mode 100644 index 0000000..4e1f0db --- /dev/null +++ b/lib/msvcrt/wstring/wcsicmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include +#include + + +int _wcsicmp(const wchar_t* cs,const wchar_t * ct) +{ + while (towlower(*cs) == towlower(*ct)) + { + if (*cs == 0) + return 0; + cs++; + ct++; + } + return towlower(*cs) - towlower(*ct); +} diff --git a/lib/msvcrt/wstring/wcslen.c b/lib/msvcrt/wstring/wcslen.c new file mode 100644 index 0000000..7829d2f --- /dev/null +++ b/lib/msvcrt/wstring/wcslen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + + +size_t wcslen(const wchar_t * s) +{ + const wchar_t *save; + + if (s == 0) + return 0; + for (save = s; *save; ++save); + return save-s; +} diff --git a/lib/msvcrt/wstring/wcslwr.c b/lib/msvcrt/wstring/wcslwr.c new file mode 100644 index 0000000..8980b83 --- /dev/null +++ b/lib/msvcrt/wstring/wcslwr.c @@ -0,0 +1,22 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + +#include + +wchar_t * _wcslwr(wchar_t *x) +{ + wchar_t *y=x; + + while (*y) { + *y=towlower(*y); + y++; + } + return x; +} diff --git a/lib/msvcrt/wstring/wcsncat.c b/lib/msvcrt/wstring/wcsncat.c new file mode 100644 index 0000000..bca5052 --- /dev/null +++ b/lib/msvcrt/wstring/wcsncat.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +wchar_t *wcsncat(wchar_t *dst, const wchar_t *src, size_t n) +{ + if (n != 0) + { + wchar_t *d = dst; + const wchar_t *s = src; + + while (*d != 0) + d++; + do { + if ((*d = *s++) == 0) + break; + d++; + } while (--n != 0); + *d = 0; + } + return dst; +} diff --git a/lib/msvcrt/wstring/wcsncmp.c b/lib/msvcrt/wstring/wcsncmp.c new file mode 100644 index 0000000..e661043 --- /dev/null +++ b/lib/msvcrt/wstring/wcsncmp.c @@ -0,0 +1,16 @@ +#include + +int wcsncmp(const wchar_t * cs,const wchar_t * ct,size_t count) +{ + while ((*cs) == (*ct) && count > 0) + { + if (*cs == 0) + return 0; + cs++; + ct++; + count--; + } + return (*cs) - (*ct); + +} + diff --git a/lib/msvcrt/wstring/wcsncpy.c b/lib/msvcrt/wstring/wcsncpy.c new file mode 100644 index 0000000..07d0000 --- /dev/null +++ b/lib/msvcrt/wstring/wcsncpy.c @@ -0,0 +1,21 @@ +#include + +wchar_t * wcsncpy(wchar_t * dest,const wchar_t *src,size_t count) +{ + int i; + + for (i=0;i + +int _wcsnicmp (const wchar_t *cs, const wchar_t *ct, size_t count) +{ + if (count == 0) + return 0; + do { + if (towupper(*cs) != towupper(*ct++)) + return towupper(*cs) - towupper(*--ct); + if (*cs++ == 0) + break; + } while (--count != 0); + return 0; +} diff --git a/lib/msvcrt/wstring/wcsnlen.c b/lib/msvcrt/wstring/wcsnlen.c new file mode 100644 index 0000000..aa3e330 --- /dev/null +++ b/lib/msvcrt/wstring/wcsnlen.c @@ -0,0 +1,10 @@ +#include + +size_t _wcsnlen(const wchar_t * s, size_t count) +{ + unsigned int len=0; + + while(s[len]!=0 && len < count) + len++; + return len; +} diff --git a/lib/msvcrt/wstring/wcspbrk.c b/lib/msvcrt/wstring/wcspbrk.c new file mode 100644 index 0000000..7ab4b91 --- /dev/null +++ b/lib/msvcrt/wstring/wcspbrk.c @@ -0,0 +1,16 @@ +#include + +wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2) +{ + const wchar_t *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) { + return (wchar_t *)(--s1); + } + } + return 0; +} \ No newline at end of file diff --git a/lib/msvcrt/wstring/wcsrchr.c b/lib/msvcrt/wstring/wcsrchr.c new file mode 100644 index 0000000..19d9d9a --- /dev/null +++ b/lib/msvcrt/wstring/wcsrchr.c @@ -0,0 +1,15 @@ +#include + +wchar_t* wcsrchr(const wchar_t* str, wchar_t ch) +{ + wchar_t *sp=(wchar_t *)0; + while (*str != 0) + { + if (*str == ch) + sp = (wchar_t *)str; + str++; + } + if (ch == 0) + sp = (wchar_t *)str; + return sp; +} diff --git a/lib/msvcrt/wstring/wcsrev.c b/lib/msvcrt/wstring/wcsrev.c new file mode 100644 index 0000000..cafd759 --- /dev/null +++ b/lib/msvcrt/wstring/wcsrev.c @@ -0,0 +1,18 @@ +#include + +wchar_t * _wcsrev(wchar_t *s) +{ + wchar_t *e; + wchar_t a; + e=s; + while (*e) + e++; + while (s + +wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill) +{ + wchar_t *t = wsToFill; + int i = 0; + while( *wsToFill != 0 && i < sizeMaxFill) + { + *wsToFill = wcFill; + wsToFill++; + i++; + + } + return t; +} + +wchar_t* _wcsset (wchar_t* wsToFill, wchar_t wcFill) +{ + wchar_t *t = wsToFill; + while( *wsToFill != 0 ) + { + *wsToFill = wcFill; + wsToFill++; + + } + return t; +} diff --git a/lib/msvcrt/wstring/wcsspn.c b/lib/msvcrt/wstring/wcsspn.c new file mode 100644 index 0000000..d3d32c6 --- /dev/null +++ b/lib/msvcrt/wstring/wcsspn.c @@ -0,0 +1,20 @@ +#include + +size_t wcsspn(const wchar_t *str,const wchar_t *accept) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do { + t=(wchar_t *)accept; + while (*t) { + if (*t==*s) + break; + t++; + } + if (!*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} diff --git a/lib/msvcrt/wstring/wcsstr.c b/lib/msvcrt/wstring/wcsstr.c new file mode 100644 index 0000000..c061a17 --- /dev/null +++ b/lib/msvcrt/wstring/wcsstr.c @@ -0,0 +1,23 @@ +#include + +wchar_t *wcsstr(const wchar_t *s,const wchar_t *b) +{ + wchar_t *x; + wchar_t *y; + wchar_t *c; + x=(wchar_t *)s; + while (*x) { + if (*x==*b) { + y=x; + c=(wchar_t *)b; + while (*y && *c && *y==*c) { + c++; + y++; + } + if (!*c) + return x; + } + x++; + } + return NULL; +} diff --git a/lib/msvcrt/wstring/wcstok.c b/lib/msvcrt/wstring/wcstok.c new file mode 100644 index 0000000..ee8c40a --- /dev/null +++ b/lib/msvcrt/wstring/wcstok.c @@ -0,0 +1,52 @@ +#include +#include + +wchar_t *wcstok(wchar_t *s, const wchar_t *ct) +{ + const wchar_t *spanp; + int c, sc; + wchar_t *tok; + PTHREADDATA ThreadData = GetThreadData(); + + if (s == NULL && (s = ThreadData->wlasttoken) == NULL) + return (NULL); + + /* + * Skip (span) leading ctiters (s += strspn(s, ct), sort of). + */ + cont: + c = *s; + s++; + for (spanp = ct; (sc = *spanp) != 0;spanp++) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-ctiter characters */ + ThreadData->wlasttoken = NULL; + return (NULL); + } + tok = s - 2; + + /* + * Scan token (scan for ctiters: s += strcspn(s, ct), sort of). + * Note that ct must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s; + s+=2; + spanp = ct; + do { + if ((sc = *spanp) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + ThreadData->wlasttoken = s; + return (tok); + } + spanp+=2; + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/msvcrt/wstring/wcsupr.c b/lib/msvcrt/wstring/wcsupr.c new file mode 100644 index 0000000..27db416 --- /dev/null +++ b/lib/msvcrt/wstring/wcsupr.c @@ -0,0 +1,12 @@ +#include + +wchar_t *_wcsupr(wchar_t *x) +{ + wchar_t *y=x; + + while (*y) { + *y=towupper(*y); + y++; + } + return x; +} diff --git a/lib/msvcrt/wstring/wcsxfrm.c b/lib/msvcrt/wstring/wcsxfrm.c new file mode 100644 index 0000000..60a5bab --- /dev/null +++ b/lib/msvcrt/wstring/wcsxfrm.c @@ -0,0 +1,23 @@ +#include + +size_t wcsxfrm(wchar_t *dst,const wchar_t *src, size_t n) +{ + size_t r = 0; + int c; + + if (n != 0) { + while ((c = *src++) != 0) + { + r++; + if (--n == 0) + { + while (*src++ != 0) + r++; + break; + } + *dst++ = c; + } + *dst = 0; + } + return r; +} diff --git a/lib/ntdll/.cvsignore b/lib/ntdll/.cvsignore new file mode 100644 index 0000000..20b8edc --- /dev/null +++ b/lib/ntdll/.cvsignore @@ -0,0 +1,9 @@ +base.tmp +junk.tmp +napi.asm +napi.c +ntdll.lib +ntdll.coff +ntdll.dll +ntdll.nostrip.dll +temp.exp diff --git a/lib/ntdll/csr/.cvsignore b/lib/ntdll/csr/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/csr/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/csr/capture.c b/lib/ntdll/csr/capture.c new file mode 100644 index 0000000..dbfba29 --- /dev/null +++ b/lib/ntdll/csr/capture.c @@ -0,0 +1,86 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/csr/capture.c + * PURPOSE: CSRSS Capture API + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static HANDLE hCaptureHeap = INVALID_HANDLE_VALUE; /* FIXME: use the general NTDLL heap */ + +/* FUNCTIONS *****************************************************************/ + +PVOID +STDCALL CsrAllocateCaptureBuffer ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + /* FIXME: implement it! */ + return NULL; +} + +VOID STDCALL +CsrCaptureMessageString (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ +} + +VOID STDCALL +CsrAllocateCapturePointer(ULONG Unknown0, + ULONG Unknown1, + ULONG Unknown2) +{ + +} + +VOID STDCALL CsrAllocateMessagePointer (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ +} + +VOID STDCALL +CsrCaptureMessageBuffer(ULONG Unknown0, + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +{ + +} + +BOOLEAN STDCALL CsrFreeCaptureBuffer (PVOID CaptureBuffer) +{ + /* FIXME: use NTDLL own heap */ + return RtlFreeHeap (hCaptureHeap, 0, CaptureBuffer); +} + +PLARGE_INTEGER STDCALL +CsrCaptureTimeout(LONG Milliseconds, + PLARGE_INTEGER Timeout) +{ + if (Milliseconds == -1) + return NULL; + + Timeout->QuadPart = Milliseconds * -100000; + return Timeout; +} + +/* EOF */ diff --git a/lib/ntdll/csr/lpc.c b/lib/ntdll/csr/lpc.c new file mode 100644 index 0000000..fea9ea3 --- /dev/null +++ b/lib/ntdll/csr/lpc.c @@ -0,0 +1,185 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/csr/lpc.c + * PURPOSE: CSRSS Client/Server LPC API + * + * REVISIONS: + * 2001-06-16 (ea) + * File api.c renamed lpc.c. Process/thread code moved + * in thread.c. Check added on the LPC port. + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +HANDLE WindowsApiPort = INVALID_HANDLE_VALUE; +static PVOID CsrSectionMapBase = NULL; +static PVOID CsrSectionMapServerBase = NULL; +static HANDLE CsrCommHeap = NULL; + +#define CSR_CONTROL_HEAP_SIZE (65536) + +/* FUNCTIONS *****************************************************************/ + +/* Possible CsrClientCallServer (the NT one): + +#define CSR_CCS_NATIVE 0x0000 +#define CSR_CCS_CSR 0x0001 +#define CSR_CCS_GUI 0x0002 + +typedef union _CSR_CCS_API +{ + WORD Index; // CSRSS API number + WORD Subsystem; // 0=NTDLL;1=KERNEL32;2=KERNEL32 + +} CSR_CCS_API, * PCSR_CCS_API; + +NTSTATUS STDCALL +CsrClientCallServer(PVOID Request, + PVOID Unknown OPTIONAL, + CSR_CCS_API CsrApi, + ULONG SizeOfData); + +Request is the family of PCSRSS_XXX_REQUEST objects. +XXX_REQUEST depend on the CsrApiNumber.Index. + +*/ + +NTSTATUS STDCALL +CsrCaptureParameterBuffer(PVOID ParameterBuffer, + ULONG ParameterBufferSize, + PVOID* ClientAddress, + PVOID* ServerAddress) +{ + PVOID Block; + + Block = RtlAllocateHeap(CsrCommHeap, 0, ParameterBufferSize); + if (Block == NULL) + { + return(STATUS_NO_MEMORY); + } + memcpy(Block, ParameterBuffer, ParameterBufferSize); + *ClientAddress = Block; + *ServerAddress = Block - CsrSectionMapBase + CsrSectionMapServerBase; + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CsrReleaseParameterBuffer(PVOID ClientAddress) +{ + RtlFreeHeap(CsrCommHeap, 0, ClientAddress); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CsrClientCallServer(PCSRSS_API_REQUEST Request, + PCSRSS_API_REPLY Reply OPTIONAL, + ULONG Length, + ULONG ReplyLength) +{ + NTSTATUS Status; + + if (INVALID_HANDLE_VALUE == WindowsApiPort) + { + DbgPrint ("NTDLL.%s: client not connected to CSRSS!\n", __FUNCTION__); + return (STATUS_UNSUCCESSFUL); + } + + Request->Header.DataSize = Length - sizeof(LPC_MESSAGE_HEADER); + Request->Header.MessageSize = Length; + + Status = NtRequestWaitReplyPort(WindowsApiPort, + &Request->Header, + (Reply?&Reply->Header:&Request->Header)); + + return(Status); +} + +NTSTATUS STDCALL +CsrClientConnectToServer(VOID) +{ + NTSTATUS Status; + UNICODE_STRING PortName; + ULONG ConnectInfoLength; + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + LPC_SECTION_WRITE LpcWrite; + HANDLE CsrSectionHandle; + LARGE_INTEGER CsrSectionViewSize; + + CsrSectionViewSize.QuadPart = CSR_CSRSS_SECTION_SIZE; + Status = NtCreateSection(&CsrSectionHandle, + SECTION_ALL_ACCESS, + NULL, + &CsrSectionViewSize, + PAGE_READWRITE, + SEC_COMMIT, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + RtlInitUnicodeStringFromLiteral(&PortName, L"\\Windows\\ApiPort"); + ConnectInfoLength = 0; + LpcWrite.Length = sizeof(LPC_SECTION_WRITE); + LpcWrite.SectionHandle = CsrSectionHandle; + LpcWrite.SectionOffset = 0; + LpcWrite.ViewSize = CsrSectionViewSize.u.LowPart; + Status = NtConnectPort(&WindowsApiPort, + &PortName, + NULL, + &LpcWrite, + NULL, + NULL, + NULL, + &ConnectInfoLength); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + NtClose(CsrSectionHandle); + CsrSectionMapBase = LpcWrite.ViewBase; + CsrSectionMapServerBase = LpcWrite.TargetViewBase; + + /* Create the heap for communication for csrss. */ + CsrCommHeap = RtlCreateHeap(HEAP_NO_VALLOC, + CsrSectionMapBase, + CsrSectionViewSize.u.LowPart, + CsrSectionViewSize.u.LowPart, + 0, + NULL); + if (CsrCommHeap == NULL) + { + return(STATUS_NO_MEMORY); + } + + Request.Type = CSRSS_CONNECT_PROCESS; + Status = CsrClientCallServer(&Request, + &Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (!NT_SUCCESS(Reply.Status)) + { + return(Reply.Status); + } + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/lib/ntdll/csr/probe.c b/lib/ntdll/csr/probe.c new file mode 100644 index 0000000..691d9b4 --- /dev/null +++ b/lib/ntdll/csr/probe.c @@ -0,0 +1,61 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/csr/probe.c + * PURPOSE: CSRSS address range access probing API + * AUTHOR: Eric Kohl + * DATE: 2001-06-17 + */ +#define NTOS_MODE_USER +#include + +#define NDEBUG +#include + +VOID STDCALL +CsrProbeForRead(IN CONST PVOID Address, + IN ULONG Length, + IN ULONG Alignment) +{ + PUCHAR Pointer; + UCHAR Data; + + if (Length == 0) + return; + + if ((ULONG)Address & (Alignment - 1)) + RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT); + + Pointer = (PUCHAR)Address; + Data = *Pointer; + Pointer = (PUCHAR)((ULONG)Address + Length -1); + Data = *Pointer; +} + +VOID STDCALL +CsrProbeForWrite(IN CONST PVOID Address, + IN ULONG Length, + IN ULONG Alignment) +{ + PUCHAR Pointer; + UCHAR Data; + + if (Length == 0) + return; + + if ((ULONG)Address & (Alignment - 1)) + RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT); + +// if (Address >= MmUserProbeAddress) +// RtlRaiseStatus(STATUS_ACCESS_VIOLATION); + + Pointer = (PUCHAR)Address; + Data = *Pointer; + *Pointer = Data; + Pointer = (PUCHAR)((ULONG)Address + Length -1); + Data = *Pointer; + *Pointer = Data; +} + +/* EOF */ diff --git a/lib/ntdll/csr/thread.c b/lib/ntdll/csr/thread.c new file mode 100644 index 0000000..c2f0340 --- /dev/null +++ b/lib/ntdll/csr/thread.c @@ -0,0 +1,57 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/csr/propvar.c + * PURPOSE: CSRSS threads API + */ +#define NTOS_MODE_USER +#include + +#include +#include + +#include + +#define NDEBUG +#include + +NTSTATUS STDCALL +CsrNewThread(VOID) +{ + return (NtRegisterThreadTerminatePort(WindowsApiPort)); +} + +NTSTATUS STDCALL +CsrSetPriorityClass(HANDLE Process, + PULONG PriorityClass) +{ + /* FIXME: call csrss to get hProcess' priority */ + *PriorityClass = CSR_PRIORITY_CLASS_NORMAL; + + return (STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS +STDCALL +CsrIdentifyAlertableThread (VOID) +{ + /* FIXME: notify csrss that current thread is alertable */ +#if 0 + CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY Reply; + CSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST Request = (PCSRSS_IDENTIFY_ALERTABLE_THREAD_REQUEST) & Reply; + PNT_TEB Teb; + + Request->UniqueThread = NtCurrentTeb()->Cid.UniqueThread; + /* FIXME: this is written the NT way, NOT the ROS way! */ + return CsrClientCallServer ( + Request, + NULL, /* use Request storage for reply */ + CSRSS_IDENTIFY_ALERTABLE_THREAD, + sizeof (CSRSS_IDENTIFY_ALERTABLE_THREAD_REPLY) + ); +#endif + return (STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/lib/ntdll/dbg/.cvsignore b/lib/ntdll/dbg/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/dbg/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/dbg/brkpoint.c b/lib/ntdll/dbg/brkpoint.c new file mode 100644 index 0000000..f41af1a --- /dev/null +++ b/lib/ntdll/dbg/brkpoint.c @@ -0,0 +1,29 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/dbg/brkpoint.c + * PURPOSE: Handles breakpoints + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * Created 28/12/1999 + */ + +/* INCLUDES *****************************************************************/ + +#include + + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL DbgBreakPoint(VOID) +{ + __asm__("int $3\n\t"); +} + +VOID STDCALL DbgUserBreakPoint(VOID) +{ + __asm__("int $3\n\t"); +} + +/* EOF */ diff --git a/lib/ntdll/dbg/debug.c b/lib/ntdll/dbg/debug.c new file mode 100644 index 0000000..dc852f9 --- /dev/null +++ b/lib/ntdll/dbg/debug.c @@ -0,0 +1,172 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/dbg/debug.c + * PURPOSE: User mode debugger support functions + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 14/04/2000 Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +static HANDLE DbgSsApiPort = NULL; +static HANDLE DbgSsReplyPort = NULL; + + +typedef struct _LPC_DBGSS_MESSAGE +{ + LPC_MESSAGE_HEADER Header; + ULONG Unknown1; + ULONG Unknown2; + ULONG Unknown3; + ULONG Unknown4; +} LPC_DBGSS_MESSAGE, *PLPC_DBGSS_MESSAGE; + + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +DbgSsServerThread(PVOID Unused) +{ + LPC_DBGSS_MESSAGE Message; + NTSTATUS Status; + + for (;;) + { + Status = NtReplyWaitReceivePort (DbgSsApiPort, + NULL, + NULL, + (PLPC_MESSAGE)&Message); + if (!NT_SUCCESS(Status)) + { + DbgPrint ("DbgSs: NtReplyWaitReceivePort failed - Status == %lx\n", + Status); + + DbgBreakPoint (); + } + else + { + /* FIXME: missing code!! */ + + } + } +} + + +NTSTATUS STDCALL +DbgSsHandleKmApiMsg(ULONG Unknown1, + HANDLE EventHandle) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS STDCALL +DbgSsInitialize(HANDLE ReplyPort, + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +{ + SECURITY_QUALITY_OF_SERVICE Qos; + UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(L"\\DbgSsApiPort"); + NTSTATUS Status; + + Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + Qos.ImpersonationLevel = SecurityIdentification; + Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + Qos.EffectiveOnly = TRUE; + + Status = NtConnectPort (&DbgSsApiPort, + &PortName, + &Qos, + NULL, + NULL, + NULL, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + DbgSsReplyPort = ReplyPort; +// UnknownData1 = Unknown1; +// UnknownData2 = Unknown2; +// UnknownData3 = Unknown3; + + Status = RtlCreateUserThread (NtCurrentProcess (), + NULL, + FALSE, + 0, + NULL, + NULL, + (PTHREAD_START_ROUTINE)DbgSsServerThread, + NULL, + NULL, + NULL); + + return Status; +} + + +NTSTATUS STDCALL +DbgUiConnectToDbg(VOID) +{ + SECURITY_QUALITY_OF_SERVICE Qos; + UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(L"\\DbgUiApiPort"); + NTSTATUS Status; + PTEB Teb; + ULONG InfoSize; + + Teb = NtCurrentTeb (); + + Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + Qos.ImpersonationLevel = SecurityIdentification; + Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + Qos.EffectiveOnly = TRUE; + + InfoSize = sizeof(ULONG); + + Status = NtConnectPort (&Teb->DbgSsReserved[1], + &PortName, + &Qos, + NULL, + NULL, + NULL, + &Teb->DbgSsReserved[0], + &InfoSize); + if (!NT_SUCCESS(Status)) + { + Teb->DbgSsReserved[1] = NULL; + return Status; + } + + NtRegisterThreadTerminatePort(Teb->DbgSsReserved[1]); + + return Status; +} + + +NTSTATUS STDCALL +DbgUiContinue(PCLIENT_ID ClientId, + ULONG ContinueStatus) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS STDCALL +DbgUiWaitStateChange(ULONG Unknown1, + ULONG Unknown2) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/lib/ntdll/dbg/print.c b/lib/ntdll/dbg/print.c new file mode 100644 index 0000000..2abba4b --- /dev/null +++ b/lib/ntdll/dbg/print.c @@ -0,0 +1,74 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/dbg/print.c + * PURPOSE: Debug output + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * Created 28/12/1999 + */ + +#include +#include +#include +#include + + +/* FUNCTIONS ***************************************************************/ + +ULONG DbgService (ULONG Service, PVOID Context1, PVOID Context2); +__asm__ ("\n\t.global _DbgService\n\t" + "_DbgService:\n\t" + "mov 4(%esp), %eax\n\t" + "mov 8(%esp), %ecx\n\t" + "mov 12(%esp), %edx\n\t" + "int $0x2D\n\t" + "ret\n\t"); + +ULONG +DbgPrint(PCH Format, ...) +{ + ANSI_STRING DebugString; + CHAR Buffer[4096]; + va_list ap; + + /* init ansi string */ + DebugString.Buffer = Buffer; + DebugString.MaximumLength = sizeof(Buffer); + + va_start (ap, Format); + DebugString.Length = _vsnprintf (Buffer, sizeof(Buffer), Format, ap); + va_end (ap); + + DbgService (1, &DebugString, NULL); + + return (ULONG)DebugString.Length; +} + + +VOID +STDCALL +DbgPrompt ( + PCH OutputString, + PCH InputString, + USHORT InputSize + ) +{ + ANSI_STRING Output; + ANSI_STRING Input; + + Input.Length = 0; + Input.MaximumLength = InputSize; + Input.Buffer = InputString; + + Output.Length = strlen (OutputString); + Output.MaximumLength = Output.Length + 1; + Output.Buffer = OutputString; + + DbgService (2, + &Output, + &Input); +} + +/* EOF */ diff --git a/lib/ntdll/dbg/winedbg.c b/lib/ntdll/dbg/winedbg.c new file mode 100644 index 0000000..c18c6d6 --- /dev/null +++ b/lib/ntdll/dbg/winedbg.c @@ -0,0 +1,251 @@ +/* + * Debugging functions for WINE + */ +#include +#include + +DECLARE_DEBUG_CHANNEL(tid); + +/* ---------------------------------------------------------------------- */ + +struct debug_info +{ + char *str_pos; /* current position in strings buffer */ + char *out_pos; /* current position in output buffer */ + char strings[1024]; /* buffer for temporary strings */ + char output[1024]; /* current output line */ +}; + +static struct debug_info tmp; + +/* get the debug info pointer for the current thread */ +static inline struct debug_info *get_info(void) +{ + struct debug_info *info = NtCurrentTeb()->WineDebugInfo; + if (!info) + { + if (!tmp.str_pos) + { + tmp.str_pos = tmp.strings; + tmp.out_pos = tmp.output; + } + if (!RtlGetProcessHeap()) return &tmp; + /* setup the temp structure in case HeapAlloc wants to print something */ + NtCurrentTeb()->WineDebugInfo = &tmp; + info = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*info) ); + info->str_pos = info->strings; + info->out_pos = info->output; + NtCurrentTeb()->WineDebugInfo = info; + } + return info; +} + +/* allocate some tmp space for a string */ +static void *gimme1(int n) +{ + struct debug_info *info = get_info(); + char *res = info->str_pos; + + if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings; + info->str_pos = res + n; + return res; +} + +/* release extra space that we requested in gimme1() */ +static inline void release( void *ptr ) +{ + struct debug_info *info = NtCurrentTeb()->WineDebugInfo; + info->str_pos = ptr; +} + +/*********************************************************************** + * wine_dbgstr_an (NTDLL.@) + */ +const char *wine_dbgstr_an( const char *src, int n ) +{ + char *dst, *res; + + if (!((WORD)(DWORD)(src) >> 16)) + { + if (!src) return "(null)"; + res = gimme1(6); + sprintf(res, "#%04x", (WORD)(DWORD)(src) ); + return res; + } + if (n < 0) n = 0; + else if (n > 200) n = 200; + dst = res = gimme1 (n * 4 + 6); + *dst++ = '"'; + while (n-- > 0 && *src) + { + unsigned char c = *src++; + switch (c) + { + case '\n': *dst++ = '\\'; *dst++ = 'n'; break; + case '\r': *dst++ = '\\'; *dst++ = 'r'; break; + case '\t': *dst++ = '\\'; *dst++ = 't'; break; + case '"': *dst++ = '\\'; *dst++ = '"'; break; + case '\\': *dst++ = '\\'; *dst++ = '\\'; break; + default: + if (c >= ' ' && c <= 126) + *dst++ = c; + else + { + *dst++ = '\\'; + *dst++ = '0' + ((c >> 6) & 7); + *dst++ = '0' + ((c >> 3) & 7); + *dst++ = '0' + ((c >> 0) & 7); + } + } + } + *dst++ = '"'; + if (*src) + { + *dst++ = '.'; + *dst++ = '.'; + *dst++ = '.'; + } + *dst++ = '\0'; + release( dst ); + return res; +} + +/*********************************************************************** + * wine_dbgstr_wn (NTDLL.@) + */ +const char *wine_dbgstr_wn( const WCHAR *src, int n ) +{ + char *dst, *res; + + if (!((WORD)(DWORD)(src) >> 16)) + { + if (!src) return "(null)"; + res = gimme1(6); + sprintf(res, "#%04x", (WORD)(DWORD)(src) ); + return res; + } + if (n < 0) n = 0; + else if (n > 200) n = 200; + dst = res = gimme1 (n * 5 + 7); + *dst++ = 'L'; + *dst++ = '"'; + while (n-- > 0 && *src) + { + WCHAR c = *src++; + switch (c) + { + case '\n': *dst++ = '\\'; *dst++ = 'n'; break; + case '\r': *dst++ = '\\'; *dst++ = 'r'; break; + case '\t': *dst++ = '\\'; *dst++ = 't'; break; + case '"': *dst++ = '\\'; *dst++ = '"'; break; + case '\\': *dst++ = '\\'; *dst++ = '\\'; break; + default: + if (c >= ' ' && c <= 126) + *dst++ = c; + else + { + *dst++ = '\\'; + sprintf(dst,"%04x",c); + dst+=4; + } + } + } + *dst++ = '"'; + if (*src) + { + *dst++ = '.'; + *dst++ = '.'; + *dst++ = '.'; + } + *dst++ = '\0'; + release( dst ); + return res; +} + +/*********************************************************************** + * wine_dbgstr_guid (NTDLL.@) + */ +const char *wine_dbgstr_guid( const GUID *id ) +{ + char *str; + + if (!id) return "(null)"; + if (!((WORD)(DWORD)(id) >> 16)) + { + str = gimme1(12); + sprintf( str, "", (WORD)(DWORD)(id) ); + } + else + { + str = gimme1(40); + sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], + id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] ); + } + return str; +} + +/*********************************************************************** + * wine_dbg_vprintf (NTDLL.@) + */ +int wine_dbg_vprintf( const char *format, va_list args ) +{ + struct debug_info *info = get_info(); + char *p; + + int ret = _vsnprintf( info->out_pos, sizeof(info->output) - (info->out_pos - info->output), + format, args ); + + p = strrchr( info->out_pos, '\n' ); + if (!p) info->out_pos += ret; + else + { + char *pos = info->output; + char saved_ch; + p++; + saved_ch = *p; + *p = 0; + DbgPrint(pos); + *p = saved_ch; + /* move beginning of next line to start of buffer */ + while ((*pos = *p++)) pos++; + info->out_pos = pos; + } + return ret; +} + +/*********************************************************************** + * wine_dbg_printf (NTDLL.@) + */ +int wine_dbg_printf(const char *format, ...) +{ + int ret; + va_list valist; + + va_start(valist, format); + ret = wine_dbg_vprintf( format, valist ); + va_end(valist); + return ret; +} + +/*********************************************************************** + * wine_dbg_log (NTDLL.@) + */ +int wine_dbg_log(enum __DEBUG_CLASS cls, const char *channel, + const char *function, const char *format, ... ) +{ + static const char *classes[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" }; + va_list valist; + int ret = 0; + + va_start(valist, format); + if (TRACE_ON(tid)) + ret = wine_dbg_printf( "%08lx:", NtCurrentTeb()->Cid.UniqueThread); + if (cls < __DBCL_COUNT) + ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, function ); + if (format) + ret += wine_dbg_vprintf( format, valist ); + va_end(valist); + return ret; +} diff --git a/lib/ntdll/def/.cvsignore b/lib/ntdll/def/.cvsignore new file mode 100644 index 0000000..b514f25 --- /dev/null +++ b/lib/ntdll/def/.cvsignore @@ -0,0 +1 @@ +ntdll.coff \ No newline at end of file diff --git a/lib/ntdll/def/ntdll.def b/lib/ntdll/def/ntdll.def new file mode 100644 index 0000000..bb4eba9 --- /dev/null +++ b/lib/ntdll/def/ntdll.def @@ -0,0 +1,948 @@ +; $Id$ +; +; ReactOS Operating System +; +LIBRARY ntdll.dll + +EXPORTS +CsrCaptureParameterBuffer@16 +CsrReleaseParameterBuffer@4 +CsrAllocateCaptureBuffer@12 +CsrAllocateCapturePointer@12 +CsrAllocateMessagePointer@12 +CsrCaptureMessageBuffer@16 +CsrCaptureMessageString@20 +CsrCaptureTimeout@8 +CsrClientCallServer@16 +CsrClientConnectToServer@0 +CsrFreeCaptureBuffer@4 +CsrIdentifyAlertableThread@0 +CsrNewThread@0 +CsrProbeForRead@12 +CsrProbeForWrite@12 +CsrSetPriorityClass@8 +DbgBreakPoint@0 +DbgPrint +DbgPrompt@12 +DbgSsHandleKmApiMsg@8 +DbgSsInitialize@16 +DbgUiConnectToDbg@0 +DbgUiContinue@8 +DbgUiWaitStateChange@8 +DbgUserBreakPoint@0 +;KiRaiseUserExceptionDispatcher +KiUserApcDispatcher +KiUserCallbackDispatcher +KiUserExceptionDispatcher +LdrAccessResource@16 +LdrDisableThreadCalloutsForDll@4 +;LdrEnumResources@20 +LdrFindEntryForAddress@8 +LdrFindResourceDirectory_U@16 +LdrFindResource_U@16 +LdrGetDllHandle@16 +LdrGetProcedureAddress@16 +LdrInitializeThunk@16 +LdrLoadDll@16 +;LdrProcessRelocationBlock@16 +;LdrQueryImageFileExecutionOptions@24 +LdrQueryProcessModuleInformation@12 +LdrShutdownProcess@0 +LdrShutdownThread@0 +LdrUnloadDll@4 +;LdrVerifyImageMatchesChecksum@16 +NlsAnsiCodePage DATA +NlsMbCodePageTag DATA +NlsMbOemCodePageTag DATA +NtAcceptConnectPort@24 +NtAccessCheck@32 +NtAccessCheckAndAuditAlarm@44 +NtAddAtom@8 +NtAdjustGroupsToken@24 +NtAdjustPrivilegesToken@24 +NtAlertResumeThread@8 +NtAlertThread@4 +NtAllocateLocallyUniqueId@4 +NtAllocateUuids@12 +NtAllocateVirtualMemory@24 +NtCallbackReturn@12 +NtCancelIoFile@8 +NtCancelTimer@8 +NtClearEvent@4 +NtClose@4 +NtCloseObjectAuditAlarm@12 +NtCompleteConnectPort@4 +NtConnectPort@32 +NtContinue@8 +NtCreateChannel@8 +NtCreateDirectoryObject@12 +NtCreateEvent@20 +NtCreateEventPair@12 +NtCreateFile@44 +NtCreateIoCompletion@16 +NtCreateKey@28 +NtCreateMailslotFile@32 +NtCreateMutant@16 +NtCreateNamedPipeFile@56 +NtCreatePagingFile@16 +NtCreatePort@20 +NtCreateProcess@32 +NtCreateProfile@36 +NtCreateSection@28 +NtCreateSemaphore@20 +NtCreateSymbolicLinkObject@16 +NtCreateThread@32 +NtCreateTimer@16 +NtCreateToken@52 +NtCreateWaitablePort@20 +NtDelayExecution@8 +NtDeleteAtom@4 +NtDeleteFile@4 +NtDeleteKey@4 +NtDeleteObjectAuditAlarm@12 +NtDeleteValueKey@8 +NtDeviceIoControlFile@40 +NtDisplayString@4 +NtDuplicateObject@28 +NtDuplicateToken@24 +NtEnumerateKey@24 +NtEnumerateValueKey@24 +NtExtendSection@8 +NtFindAtom@8 +NtFlushBuffersFile@8 +NtFlushInstructionCache@12 +NtFlushKey@4 +NtFlushVirtualMemory@16 +NtFlushWriteBuffer@0 +NtFreeVirtualMemory@16 +NtFsControlFile@40 +NtGetContextThread@8 +NtGetPlugPlayEvent@16 +NtGetTickCount@4 +NtImpersonateClientOfPort@8 +NtImpersonateThread@12 +NtInitializeRegistry@4 +NtListenChannel@8 +NtListenPort@8 +NtLoadDriver@4 +NtLoadKey@8 +NtLoadKey2@12 +NtLockFile@40 +NtLockVirtualMemory@16 +NtMakeTemporaryObject@4 +NtMapViewOfSection@40 +NtNotifyChangeDirectoryFile@36 +NtNotifyChangeKey@40 +NtOpenChannel@8 +NtOpenDirectoryObject@12 +NtOpenEvent@12 +NtOpenEventPair@12 +NtOpenFile@24 +NtOpenIoCompletion@12 +NtOpenKey@12 +NtOpenMutant@12 +NtOpenObjectAuditAlarm@48 +NtOpenProcess@16 +NtOpenProcessToken@12 +NtOpenSection@12 +NtOpenSemaphore@12 +NtOpenSymbolicLinkObject@12 +NtOpenThread@16 +NtOpenThreadToken@16 +NtOpenTimer@12 +NtPlugPlayControl@16 +NtPrivilegeCheck@12 +NtPrivilegedServiceAuditAlarm@20 +NtPrivilegeObjectAuditAlarm@24 +NtProtectVirtualMemory@20 +NtPulseEvent@8 +NtQueueApcThread@20 +NtQueryAttributesFile@8 +NtQueryDefaultLocale@8 +NtQueryDirectoryFile@44 +NtQueryDirectoryObject@28 +NtQueryEaFile@36 +NtQueryEvent@20 +NtQueryFullAttributesFile@8 +NtQueryInformationAtom@20 +NtQueryInformationFile@20 +NtQueryInformationPort@20 +NtQueryInformationProcess@20 +NtQueryInformationThread@20 +NtQueryInformationToken@20 +NtQueryIoCompletion@20 +NtQueryIntervalProfile@8 +NtQueryKey@20 +NtQueryMultipleValueKey@24 +NtQueryMutant@20 +NtQueryObject@20 +NtQueryOleDirectoryFile@44 +NtQueryPerformanceCounter@8 +NtQuerySection@20 +NtQuerySecurityObject@20 +NtQuerySemaphore@20 +NtQuerySymbolicLinkObject@12 +NtQuerySystemEnvironmentValue@16 +NtQuerySystemInformation@16 +NtQuerySystemTime@4 +NtQueryTimer@20 +NtQueryTimerResolution@12 +NtQueryValueKey@24 +NtQueryVirtualMemory@24 +NtQueryVolumeInformationFile@20 +NtRaiseException@12 +NtRaiseHardError@24 +NtReadFile@36 +NtReadFileScatter@36 +NtReadRequestData@24 +NtReadVirtualMemory@20 +NtRegisterThreadTerminatePort@4 +NtReleaseMutant@8 +NtReleaseSemaphore@12 +NtRemoveIoCompletion@20 +NtReplaceKey@12 +NtReplyPort@8 +NtReplyWaitReceivePort@16 +NtReplyWaitReplyPort@8 +NtReplyWaitSendChannel@12 +NtRequestPort@8 +NtRequestWaitReplyPort@12 +NtResetEvent@8 +NtRestoreKey@12 +NtResumeThread@8 +NtSaveKey@8 +NtSendWaitReplyChannel@16 +NtSetContextChannel@4 +NtSetContextThread@8 +NtSetDefaultHardErrorPort@4 +NtSetDefaultLocale@8 +NtSetEaFile@16 +NtSetEvent@8 +NtSetHighEventPair@4 +NtSetHighWaitLowEventPair@4 +NtSetInformationFile@20 +NtSetInformationKey@16 +NtSetInformationObject@16 +NtSetInformationProcess@16 +NtSetInformationThread@16 +NtSetInformationToken@16 +NtSetIntervalProfile@8 +NtSetIoCompletion@20 +NtSetLdtEntries@24 +NtSetLowEventPair@4 +NtSetLowWaitHighEventPair@4 +NtSetSecurityObject@12 +NtSetSystemEnvironmentValue@8 +NtSetSystemInformation@12 +NtSetSystemPowerState@12 +NtSetSystemTime@8 +NtSetTimer@28 +NtSetTimerResolution@12 +NtSetValueKey@24 +NtSetVolumeInformationFile@20 +NtShutdownSystem@4 +NtSignalAndWaitForSingleObject@16 +NtStartProfile@4 +NtStopProfile@4 +NtSuspendThread@8 +NtSystemDebugControl@24 +NtTerminateProcess@8 +NtTerminateThread@8 +NtTestAlert@0 +NtUnloadDriver@4 +NtUnloadKey@4 +NtUnlockFile@20 +NtUnlockVirtualMemory@16 +NtUnmapViewOfSection@8 +NtVdmControl@8 +NtWaitForMultipleObjects@20 +NtWaitForSingleObject@12 +NtWaitHighEventPair@4 +NtWaitLowEventPair@4 +NtWriteFile@36 +NtWriteFileGather@36 +NtWriteRequestData@24 +NtWriteVirtualMemory@20 +NtW32Call@20 +NtYieldExecution@0 +;PfxFindPrefix +;PfxInitialize +;PfxInsertPrefix +;PfxRemovePrefix +;PropertyLengthAsVariant +;RestoreEm87Context +;RtlAbortRXact +RtlAbsoluteToSelfRelativeSD@12 +RtlAcquirePebLock@0 +RtlAcquireResourceExclusive@8 +RtlAcquireResourceShared@8 +RtlAddAccessAllowedAce@16 +RtlAddAccessDeniedAce@16 +RtlAddAce@20 +;RtlAddActionToRXact +RtlAddAtomToAtomTable@12 +;RtlAddAttributeActionToRXact +RtlAddAuditAccessAce@24 +;RtlAddCompoundAce +;RtlAdjustPrivilege +RtlAllocateAndInitializeSid@44 +RtlAllocateHandle@8 +RtlAllocateHeap@12 +RtlAnsiCharToUnicodeChar@4 +RtlAnsiStringToUnicodeSize@4 +RtlAnsiStringToUnicodeString@12 +RtlAppendAsciizToString@8 +RtlAppendStringToString@8 +RtlAppendUnicodeStringToString@8 +RtlAppendUnicodeToString@8 +;RtlApplyRXact +;RtlApplyRXactNoFlush +RtlAreAllAccessesGranted@8 +RtlAreAnyAccessesGranted@8 +RtlAreBitsClear@12 +RtlAreBitsSet@12 +RtlAssert@16 +;RtlCaptureStackBackTrace +RtlCharToInteger@12 +RtlCheckRegistryKey@8 +RtlClearAllBits@4 +RtlClearBits@12 +;RtlClosePropertySet +RtlCompactHeap@8 +RtlCompareMemory@12 +RtlCompareMemoryUlong@12 +RtlCompareString@12 +RtlCompareUnicodeString@12 +RtlCompressBuffer@32 +;RtlConsoleMultiByteToUnicodeN +RtlConvertExclusiveToShared@4 +RtlConvertLongToLargeInteger@4 +RtlConvertSharedToExclusive@4 +RtlConvertSidToUnicodeString@12 +;RtlConvertUiListToApiList +RtlConvertUlongToLargeInteger@4 +RtlCopyLuid@8 +RtlCopyLuidAndAttributesArray@12 +;RtlCopySecurityDescriptor +RtlCopySid@12 +RtlCopySidAndAttributesArray@28 +RtlCopyString@8 +RtlCopyUnicodeString@8 +RtlCreateAcl@12 +;RtlCreateAndSetSD +RtlCreateAtomTable@8 +RtlCreateEnvironment@8 +RtlCreateHeap@24 +RtlCreateProcessParameters@40 +;RtlCreatePropertySet +;RtlCreateQueryDebugBuffer +RtlCreateRegistryKey@8 +RtlCreateSecurityDescriptor@8 +;RtlCreateTagHeap +RtlCreateUnicodeString@8 +RtlCreateUnicodeStringFromAsciiz@8 +RtlCreateUserProcess@40 +;RtlCreateUserSecurityObject +RtlCreateUserThread@40 +RtlCustomCPToUnicodeN@24 +;RtlCutoverTimeToSystemTime +RtlDeNormalizeProcessParams@4 +RtlDecompressBuffer@24 +RtlDecompressFragment@32 +;RtlDelete +RtlDeleteAce@8 +RtlDeleteAtomFromAtomTable@8 +RtlDeleteCriticalSection@4 +;RtlDeleteElementGenericTable +;RtlDeleteNoSplay +RtlDeleteRegistryValue@12 +RtlDeleteResource@4 +;RtlDeleteSecurityObject +RtlDestroyAtomTable@4 +RtlDestroyEnvironment@4 +RtlDestroyHandleTable@4 +RtlDestroyHeap@4 +RtlDestroyProcessParameters@4 +;RtlDestroyQueryDebugBuffer +RtlDetermineDosPathNameType_U@4 +RtlDoesFileExists_U@4 +RtlDosPathNameToNtPathName_U@16 +RtlDosSearchPath_U@24 +RtlDowncaseUnicodeString@12 +RtlDumpResource@4 +RtlEmptyAtomTable@8 +RtlEnlargedIntegerMultiply@8 +RtlEnlargedUnsignedDivide@16 +RtlEnlargedUnsignedMultiply@8 +RtlEnterCriticalSection@4 +RtlEnumProcessHeaps@8 +;RtlEnumerateGenericTable +;RtlEnumerateGenericTableWithoutSplaying +;RtlEnumerateProperties +RtlEqualComputerName@8 +RtlEqualDomainName@8 +RtlEqualLuid@8 +RtlEqualPrefixSid@8 +RtlEqualSid@8 +RtlEqualString@12 +RtlEqualUnicodeString@12 +RtlEraseUnicodeString@4 +RtlExpandEnvironmentStrings_U@16 +;RtlExtendHeap +RtlExtendedIntegerMultiply@12 +RtlExtendedLargeIntegerDivide@16 +RtlExtendedMagicDivide@20 +RtlFillMemory@12 +RtlFillMemoryUlong@12 +RtlFindClearBits@12 +RtlFindClearBitsAndSet@12 +RtlFindLongestRunClear@8 +RtlFindLongestRunSet@8 +RtlFindMessage@20 +RtlFindSetBits@12 +RtlFindSetBitsAndClear@12 +RtlFirstFreeAce@8 +;RtlFlushPropertySet +RtlFormatCurrentUserKeyPath@4 +;RtlFormatMessage@36 +RtlFreeAnsiString@4 +RtlFreeHandle@8 +RtlFreeHeap@12 +RtlFreeOemString@4 +RtlFreeSid@4 +RtlFreeUnicodeString@4 +RtlFreeUserThreadStack@8 +RtlGenerate8dot3Name@16 +RtlGetAce@12 +;RtlGetCallersAddress +RtlGetCompressionWorkSpaceSize@12 +RtlGetControlSecurityDescriptor@12 +RtlGetCurrentDirectory_U@8 +RtlGetDaclSecurityDescriptor@16 +;RtlGetElementGenericTable +RtlGetFullPathName_U@16 +RtlGetGroupSecurityDescriptor@12 +RtlGetLongestNtPathLength@0 +RtlGetNtGlobalFlags@0 +RtlGetNtProductType@4 +RtlGetOwnerSecurityDescriptor@12 +RtlGetProcessHeaps@8 +RtlGetSaclSecurityDescriptor@16 +;RtlGetUserInfoHeap +;RtlGuidToPropertySetName +RtlIdentifierAuthoritySid@4 +RtlImageDirectoryEntryToData@16 +RtlImageNtHeader@4 +RtlImageRvaToSection@12 +RtlImageRvaToVa@16 +RtlImpersonateSelf@4 +RtlInitAnsiString@8 +;RtlInitCodePageTable +;RtlInitNlsTables +RtlInitString@8 +RtlInitUnicodeString@8 +;RtlInitializeAtomPackage +RtlInitializeBitMap@12 +RtlInitializeContext@20 +RtlInitializeCriticalSection@4 +;RtlInitializeGenericTable +RtlInitializeHandleTable@12 +;RtlInitializeRXact +RtlInitializeResource@4 +RtlInitializeSid@12 +;RtlInsertElementGenericTable +RtlIntegerToChar@16 +RtlIntegerToUnicodeString@12 +RtlIsDosDeviceName_U@4 +;RtlIsGenericTableEmpty +RtlIsNameLegalDOS8Dot3@12 +;RtlIsTextUnicode +RtlIsValidHandle@8 +RtlIsValidIndexHandle@12 +RtlLargeIntegerAdd@16 +RtlLargeIntegerArithmeticShift@12 +RtlLargeIntegerDivide@20 +RtlLargeIntegerNegate@8 +RtlLargeIntegerShiftLeft@12 +RtlLargeIntegerShiftRight@12 +RtlLargeIntegerSubtract@16 +RtlLargeIntegerToChar@16 +RtlLeaveCriticalSection@4 +RtlLengthRequiredSid@4 +RtlLengthSecurityDescriptor@4 +RtlLengthSid@4 +RtlLocalTimeToSystemTime@8 +RtlLockHeap@4 +RtlLookupAtomInAtomTable@12 +;RtlLookupElementGenericTable +RtlMakeSelfRelativeSD@12 +RtlMapGenericMask@8 +RtlMoveMemory@12 +RtlMultiByteToUnicodeN@20 +RtlMultiByteToUnicodeSize@12 +;RtlNewInstanceSecurityObject +;RtlNewSecurityGrantedAccess +;RtlNewSecurityObject +RtlNormalizeProcessParams@4 +RtlNtStatusToDosError@4 +RtlNtStatusToPsxErrno@4 +;RtlNumberGenericTableElements +RtlNumberOfClearBits@4 +RtlNumberOfSetBits@4 +RtlOemStringToUnicodeSize@4 +RtlOemStringToUnicodeString@12 +RtlOemToUnicodeN@20 +RtlOpenCurrentUser@8 +;RtlPcToFileHeader +RtlPinAtomInAtomTable@8 +RtlPrefixString@12 +RtlPrefixUnicodeString@12 +;RtlPropertySetNameToGuid +;RtlProtectHeap +RtlQueryAtomInAtomTable@24 +RtlQueryEnvironmentVariable_U@12 +RtlQueryInformationAcl@16 +;RtlQueryProcessBackTraceInformation +;RtlQueryProcessDebugInformation +;RtlQueryProcessHeapInformation +;RtlQueryProcessLockInformation +;RtlQueryProperties +;RtlQueryPropertyNames +;RtlQueryPropertySet +RtlQueryRegistryValues@20 +;RtlQuerySecutityObject +;RtlQueryTagHeap +RtlQueryTimeZoneInformation@4 +RtlRaiseException@4 +RtlRaiseStatus@4 +;RtlRandom +RtlReAllocateHeap@16 +;RtlRealPredecessor +;RtlRealSuccessor +RtlReleasePebLock@0 +RtlReleaseResource@4 +;RtlRemoteCall +;RtlResetRtlTranslations +;RtlRunDecodeUnicodeString +;RtlRunEncodeUnicodeString +RtlSecondsSince1970ToTime@8 +RtlSecondsSince1980ToTime@8 +RtlSelfRelativeToAbsoluteSD@44 +RtlSetAllBits@4 +;RtlSetAttributesSecurityDescriptor +RtlSetBits@12 +RtlSetCurrentDirectory_U@4 +RtlSetCurrentEnvironment@8 +RtlSetDaclSecurityDescriptor@16 +RtlSetEnvironmentVariable@12 +RtlSetGroupSecurityDescriptor@12 +RtlSetInformationAcl@16 +RtlSetOwnerSecurityDescriptor@12 +;RtlSetProperties +;RtlSetPropertyNames +;RtlSetPropertySetClassId +RtlSetSaclSecurityDescriptor@16 +;RtlSetSecurityObject +RtlSetTimeZoneInformation@4 +;RtlSetUnicodeCallouts +;RtlSetUserFlagsHeap +;RtlSetUserValueHeap +RtlSizeHeap@12 +;RtlSplay +;RtlStartRXact +RtlSubAuthorityCountSid@4 +RtlSubAuthoritySid@8 +;RtlSubtreePredecessor +;RtlSubtreeSuccessor +RtlSystemTimeToLocalTime@8 +RtlTimeFieldsToTime@8 +RtlTimeToElapsedTimeFields@8 +RtlTimeToSecondsSince1970@8 +RtlTimeToSecondsSince1980@8 +RtlTimeToTimeFields@8 +RtlTryEnterCriticalSection@4 +RtlUnicodeStringToAnsiSize@4 +RtlUnicodeStringToAnsiString@12 +RtlUnicodeStringToCountedOemString@12 +RtlUnicodeStringToInteger@12 +RtlUnicodeStringToOemSize@4 +RtlUnicodeStringToOemString@12 +RtlUnicodeToCustomCPN@24 +RtlUnicodeToMultiByteN@20 +RtlUnicodeToMultiByteSize@12 +RtlUnicodeToOemN@20 +;RtlUniform +RtlUnlockHeap@4 +RtlUnwind@16 +RtlUpcaseUnicodeChar@4 +RtlUpcaseUnicodeString@12 +RtlUpcaseUnicodeStringToAnsiString@12 +RtlUpcaseUnicodeStringToCountedOemString@12 +RtlUpcaseUnicodeStringToOemString@12 +RtlUpcaseUnicodeToCustomCPN@24 +RtlUpcaseUnicodeToMultiByteN@20 +RtlUpcaseUnicodeToOemN@20 +RtlUpperChar@4 +RtlUpperString@8 +;RtlUsageHeap +RtlValidAcl@4 +RtlValidSecurityDescriptor@4 +RtlValidSid@4 +RtlValidateHeap@12 +RtlValidateProcessHeaps@0 +;RtlWalkHeap +RtlWriteRegistryValue@24 +;RtlZeroHeap +RtlZeroMemory@8 +RtlpNtCreateKey@24 +RtlpNtEnumerateSubKey@16 +RtlpNtMakeTemporaryKey@4 +RtlpNtOpenKey@16 +RtlpNtQueryValueKey@20 +RtlpNtSetValueKey@16 +;RtlpUnWaitCriticalSection +;RtlpWaitForCriticalSection +RtlxAnsiStringToUnicodeSize@4 +RtlxOemStringToUnicodeSize@4 +RtlxUnicodeStringToAnsiSize@4 +RtlxUnicodeStringToOemSize@4 +;SaveEm87Context +ZwAcceptConnectPort@24 +ZwAccessCheck@32 +ZwAccessCheckAndAuditAlarm@44 +ZwAddAtom@8 +ZwAdjustGroupsToken@24 +ZwAdjustPrivilegesToken@24 +ZwAlertResumeThread@8 +ZwAlertThread@4 +ZwAllocateLocallyUniqueId@4 +ZwAllocateUuids@12 +ZwAllocateVirtualMemory@24 +ZwCallbackReturn@12 +ZwCancelIoFile@8 +ZwCancelTimer@8 +ZwClearEvent@4 +ZwClose@4 +ZwCloseObjectAuditAlarm@12 +ZwCompleteConnectPort@4 +ZwConnectPort@32 +ZwContinue@8 +ZwCreateChannel@8 +ZwCreateDirectoryObject@12 +ZwCreateEvent@20 +ZwCreateEventPair@12 +ZwCreateFile@44 +ZwCreateIoCompletion@16 +ZwCreateKey@28 +ZwCreateMailslotFile@32 +ZwCreateMutant@16 +ZwCreateNamedPipeFile@56 +ZwCreatePagingFile@16 +ZwCreatePort@20 +ZwCreateProcess@32 +ZwCreateProfile@36 +ZwCreateSection@28 +ZwCreateSemaphore@20 +ZwCreateSymbolicLinkObject@16 +ZwCreateThread@32 +ZwCreateTimer@16 +ZwCreateToken@52 +ZwDelayExecution@8 +ZwDeleteAtom@4 +ZwDeleteFile@4 +ZwDeleteKey@4 +ZwDeleteObjectAuditAlarm@12 +ZwDeleteValueKey@8 +ZwDeviceIoControlFile@40 +ZwDisplayString@4 +ZwDuplicateObject@28 +ZwDuplicateToken@24 +ZwEnumerateKey@24 +ZwEnumerateValueKey@24 +ZwExtendSection@8 +ZwFindAtom@8 +ZwFlushBuffersFile@8 +ZwFlushInstructionCache@12 +ZwFlushKey@4 +ZwFlushVirtualMemory@16 +ZwFlushWriteBuffer@0 +ZwFreeVirtualMemory@16 +ZwFsControlFile@40 +ZwGetContextThread@8 +ZwGetPlugPlayEvent@16 +ZwGetTickCount@4 +ZwImpersonateClientOfPort@8 +ZwImpersonateThread@12 +ZwInitializeRegistry@4 +ZwListenChannel@8 +ZwListenPort@8 +ZwLoadDriver@4 +ZwLoadKey@8 +ZwLoadKey2@12 +ZwLockFile@40 +ZwLockVirtualMemory@16 +ZwMakeTemporaryObject@4 +ZwMapViewOfSection@40 +ZwNotifyChangeDirectoryFile@36 +ZwNotifyChangeKey@40 +ZwOpenChannel@8 +ZwOpenDirectoryObject@12 +ZwOpenEvent@12 +ZwOpenEventPair@12 +ZwOpenFile@24 +ZwOpenIoCompletion@12 +ZwOpenKey@12 +ZwOpenMutant@12 +ZwOpenObjectAuditAlarm@48 +ZwOpenProcess@16 +ZwOpenProcessToken@12 +ZwOpenSection@12 +ZwOpenSemaphore@12 +ZwOpenSymbolicLinkObject@12 +ZwOpenThread@16 +ZwOpenThreadToken@16 +ZwOpenTimer@12 +ZwPlugPlayControl@16 +ZwPrivilegeCheck@12 +ZwPrivilegedServiceAuditAlarm@20 +ZwPrivilegeObjectAuditAlarm@24 +ZwProtectVirtualMemory@20 +ZwPulseEvent@8 +ZwQueueApcThread@20 +ZwQueryInformationAtom@20 +ZwQueryAttributesFile@8 +ZwQueryDefaultLocale@8 +ZwQueryDirectoryFile@44 +ZwQueryDirectoryObject@28 +ZwQueryEaFile@36 +ZwQueryEvent@20 +ZwQueryFullAttributesFile@8 +ZwQueryInformationFile@20 +ZwQueryInformationPort@20 +ZwQueryInformationProcess@20 +ZwQueryInformationThread@20 +ZwQueryInformationToken@20 +ZwQueryIntervalProfile@8 +ZwQueryIoCompletion@20 +ZwQueryKey@20 +ZwQueryMultipleValueKey@24 +ZwQueryMutant@20 +ZwQueryObject@20 +ZwQueryOleDirectoryFile@44 +ZwQueryPerformanceCounter@8 +ZwQuerySection@20 +ZwQuerySecurityObject@20 +ZwQuerySemaphore@20 +ZwQuerySymbolicLinkObject@12 +ZwQuerySystemEnvironmentValue@16 +ZwQuerySystemInformation@16 +ZwQuerySystemTime@4 +ZwQueryTimer@20 +ZwQueryTimerResolution@12 +ZwQueryValueKey@24 +ZwQueryVirtualMemory@24 +ZwQueryVolumeInformationFile@20 +ZwRaiseException@12 +ZwRaiseHardError@24 +ZwReadFile@36 +ZwReadFileScatter@36 +ZwReadRequestData@24 +ZwReadVirtualMemory@20 +ZwRegisterThreadTerminatePort@4 +ZwReleaseMutant@8 +ZwReleaseSemaphore@12 +ZwRemoveIoCompletion@20 +ZwReplaceKey@12 +ZwReplyPort@8 +ZwReplyWaitReceivePort@16 +ZwReplyWaitReplyPort@8 +ZwReplyWaitSendChannel@12 +ZwRequestPort@8 +ZwRequestWaitReplyPort@12 +ZwResetEvent@8 +ZwRestoreKey@12 +ZwResumeThread@8 +ZwSaveKey@8 +ZwSendWaitReplyChannel@16 +ZwSetContextChannel@4 +ZwSetContextThread@8 +ZwSetDefaultHardErrorPort@4 +ZwSetDefaultLocale@8 +ZwSetEaFile@16 +ZwSetEvent@8 +ZwSetHighEventPair@4 +ZwSetHighWaitLowEventPair@4 +ZwSetInformationFile@20 +ZwSetInformationKey@16 +ZwSetInformationObject@16 +ZwSetInformationProcess@16 +ZwSetInformationThread@16 +ZwSetInformationToken@16 +ZwSetIntervalProfile@8 +ZwSetIoCompletion@20 +ZwSetLdtEntries@24 +ZwSetLowEventPair@4 +ZwSetLowWaitHighEventPair@4 +ZwSetSecurityObject@12 +ZwSetSystemEnvironmentValue@8 +ZwSetSystemInformation@12 +ZwSetSystemPowerState@12 +ZwSetSystemTime@8 +ZwSetTimer@28 +ZwSetTimerResolution@12 +ZwSetValueKey@24 +ZwSetVolumeInformationFile@20 +ZwShutdownSystem@4 +ZwSignalAndWaitForSingleObject@16 +ZwStartProfile@4 +ZwStopProfile@4 +ZwSuspendThread@8 +ZwSystemDebugControl@24 +ZwTerminateProcess@8 +ZwTerminateThread@8 +ZwTestAlert@0 +ZwUnloadDriver@4 +ZwUnloadKey@4 +ZwUnlockFile@20 +ZwUnlockVirtualMemory@16 +ZwUnmapViewOfSection@8 +ZwVdmControl@8 +ZwWaitForMultipleObjects@20 +ZwWaitForSingleObject@12 +ZwWaitHighEventPair@4 +ZwWaitLowEventPair@4 +ZwWriteFile@36 +ZwWriteFileGather@36 +ZwWriteRequestData@24 +ZwWriteVirtualMemory@20 +ZwW32Call@20 +ZwYieldExecution@0 +__isascii +__iscsym +__iscsymf +__toascii +;_alldiv +;_allmul +;_alloca_probe +;_allrem +;_allshl +;_allshr +_atoi64 +;_aulldiv +;_aullrem +;_aullshr +;_chkstk +;_fltused +_ftol +_i64toa +_i64tow +_itoa +_itow +_ltoa +_ltow +_memccpy +_memicmp +_snprintf +_snwprintf +_splitpath +_strcmpi +_stricmp +_strlwr +_strnicmp +_strupr +_tolower +_toupper +_ultoa +_ultow +_vsnprintf +_wcsicmp +_wcslwr +_wcsnicmp +_wcsupr +_wtoi +_wtoi64 +_wtol +abs +atan +atoi +atol +ceil +cos +fabs +floor +isalnum +isalpha +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +iswalpha +iswctype +isxdigit +labs +log +mbstowcs +memchr +memcmp +memcpy +memmove +memset +pow +qsort +sin +sprintf +sqrt +;sscanf +strcat +strchr +strcmp +strcpy +strcspn +strlen +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtol +strtoul +swprintf +tan +tolower +toupper +towlower +towupper +vsprintf +wcscat +wcschr +wcscmp +wcscpy +wcscspn +wcslen +wcsncat +wcsncmp +wcsncpy +wcspbrk +wcsrchr +wcsspn +wcsstr +wcstol +wcstombs +wcstoul +wine_dbgstr_an +wine_dbgstr_wn +wine_dbgstr_guid +wine_dbg_vprintf +wine_dbg_printf +wine_dbg_log +InterlockedIncrement@4 +InterlockedDecrement@4 +InterlockedExchange@8 +InterlockedCompareExchange@12 +;EOF diff --git a/lib/ntdll/def/ntdll.edf b/lib/ntdll/def/ntdll.edf new file mode 100644 index 0000000..e43cd21 --- /dev/null +++ b/lib/ntdll/def/ntdll.edf @@ -0,0 +1,947 @@ +; $Id$ +; +; ReactOS Operating System +; +LIBRARY ntdll.dll + +EXPORTS +CsrCaptureParameterBuffer=CsrCaptureParameterBuffer@16 +CsrReleaseParameterBuffer=CsrReleaseParameterBuffer@4 +CsrAllocateCaptureBuffer=CsrAllocateCaptureBuffer@12 +CsrAllocateCapturePointer=CsrAllocateCapturePointer@12 +CsrAllocateMessagePointer=CsrAllocateMessagePointer@12 +CsrCaptureMessageBuffer=CsrCaptureMessageBuffer@16 +CsrCaptureMessageString=CsrCaptureMessageString@20 +CsrCaptureTimeout=CsrCaptureTimeout@8 +CsrClientCallServer=CsrClientCallServer@16 +CsrClientConnectToServer=CsrClientConnectToServer@0 +CsrFreeCaptureBuffer=CsrFreeCaptureBuffer@4 +CsrIdentifyAlertableThread=CsrIdentifyAlertableThread@0 +CsrNewThread=CsrNewThread@0 +CsrProbeForRead=CsrProbeForRead@12 +CsrProbeForWrite=CsrProbeForWrite@12 +CsrSetPriorityClass=CsrSetPriorityClass@8 +DbgBreakPoint=DbgBreakPoint@0 +DbgPrint +DbgPrompt=DbgPrompt@12 +DbgSsHandleKmApiMsg=DbgSsHandleKmApiMsg@8 +DbgSsInitialize=DbgSsInitialize@16 +DbgUiConnectToDbg=DbgUiConnectToDbg@0 +DbgUiContinue=DbgUiContinue@8 +DbgUiWaitStateChange=DbgUiWaitStateChange@8 +DbgUserBreakPoint=DbgUserBreakPoint@0 +;KiRaiseUserExceptionDispatcher +KiUserApcDispatcher=KiUserApcDispatcher@20 +KiUserCallbackDispatcher=KiUserCallbackDispatcher@12 +KiUserExceptionDispatcher=KiUserExceptionDispatcher@8 +LdrAccessResource=LdrAccessResource@16 +LdrDisableThreadCalloutsForDll=LdrDisableThreadCalloutsForDll@4 +;LdrEnumResources +LdrFindEntryForAddress=LdrFindEntryForAddress@8 +LdrFindResourceDirectory_U=LdrFindResourceDirectory_U@16 +LdrFindResource_U=LdrFindResource_U@16 +LdrGetDllHandle=LdrGetDllHandle@16 +LdrGetProcedureAddress=LdrGetProcedureAddress@16 +LdrInitializeThunk=LdrInitializeThunk@16 +LdrLoadDll=LdrLoadDll@16 +;LdrProcessRelocationBlock +;LdrQueryImageFileExecutionOptions +LdrQueryProcessModuleInformation=LdrQueryProcessModuleInformation@12 +LdrShutdownProcess=LdrShutdownProcess@0 +LdrShutdownThread=LdrShutdownThread@0 +LdrUnloadDll=LdrUnloadDll@4 +;LdrVerifyImageMatchesChecksum@16 +NlsAnsiCodePage DATA +NlsMbCodePageTag DATA +NlsMbOemCodePageTag DATA +NtAcceptConnectPort=NtAcceptConnectPort@24 +NtAccessCheck=NtAccessCheck@32 +NtAccessCheckAndAuditAlarm=NtAccessCheckAndAuditAlarm@44 +NtAddAtom=NtAddAtom@8 +NtAdjustGroupsToken=NtAdjustGroupsToken@24 +NtAdjustPrivilegesToken=NtAdjustPrivilegesToken@24 +NtAlertResumeThread=NtAlertResumeThread@8 +NtAlertThread=NtAlertThread@4 +NtAllocateLocallyUniqueId=NtAllocateLocallyUniqueId@4 +NtAllocateUuids=NtAllocateUuids@12 +NtAllocateVirtualMemory=NtAllocateVirtualMemory@24 +NtCallbackReturn=NtCallbackReturn@12 +NtCancelIoFile=NtCancelIoFile@8 +NtCancelTimer=NtCancelTimer@8 +NtClearEvent=NtClearEvent@4 +NtClose=NtClose@4 +NtCloseObjectAuditAlarm=NtCloseObjectAuditAlarm@12 +NtCompleteConnectPort=NtCompleteConnectPort@4 +NtConnectPort=NtConnectPort@32 +NtContinue=NtContinue@8 +NtCreateChannel=NtCreateChannel@8 +NtCreateDirectoryObject=NtCreateDirectoryObject@12 +NtCreateEvent=NtCreateEvent@20 +NtCreateEventPair=NtCreateEventPair@12 +NtCreateFile=NtCreateFile@44 +NtCreateIoCompletion=NtCreateIoCompletion@16 +NtCreateKey=NtCreateKey@28 +NtCreateMailslotFile=NtCreateMailslotFile@32 +NtCreateMutant=NtCreateMutant@16 +NtCreateNamedPipeFile=NtCreateNamedPipeFile@56 +NtCreatePagingFile=NtCreatePagingFile@16 +NtCreatePort=NtCreatePort@20 +NtCreateProcess=NtCreateProcess@32 +NtCreateProfile=NtCreateProfile@36 +NtCreateSection=NtCreateSection@28 +NtCreateSemaphore=NtCreateSemaphore@20 +NtCreateSymbolicLinkObject=NtCreateSymbolicLinkObject@16 +NtCreateThread=NtCreateThread@32 +NtCreateTimer=NtCreateTimer@16 +NtCreateToken=NtCreateToken@52 +NtCreateWaitablePort=NtCreateWaitablePort@20 +NtDelayExecution=NtDelayExecution@8 +NtDeleteAtom=NtDeleteAtom@4 +NtDeleteFile=NtDeleteFile@4 +NtDeleteKey=NtDeleteKey@4 +NtDeleteObjectAuditAlarm=NtDeleteObjectAuditAlarm@12 +NtDeleteValueKey=NtDeleteValueKey@8 +NtDeviceIoControlFile=NtDeviceIoControlFile@40 +NtDisplayString=NtDisplayString@4 +NtDuplicateObject=NtDuplicateObject@28 +NtDuplicateToken=NtDuplicateToken@24 +NtEnumerateKey=NtEnumerateKey@24 +NtEnumerateValueKey=NtEnumerateValueKey@24 +NtExtendSection=NtExtendSection@8 +NtFindAtom=NtFindAtom@8 +NtFlushBuffersFile=NtFlushBuffersFile@8 +NtFlushInstructionCache=NtFlushInstructionCache@12 +NtFlushKey=NtFlushKey@4 +NtFlushVirtualMemory=NtFlushVirtualMemory@16 +NtFlushWriteBuffer=NtFlushWriteBuffer@0 +NtFreeVirtualMemory=NtFreeVirtualMemory@16 +NtFsControlFile=NtFsControlFile@40 +NtGetContextThread=NtGetContextThread@8 +NtGetPlugPlayEvent=NtGetPlugPlayEvent@16 +NtGetTickCount=NtGetTickCount@4 +NtImpersonateClientOfPort=NtImpersonateClientOfPort@8 +NtImpersonateThread=NtImpersonateThread@12 +NtInitializeRegistry=NtInitializeRegistry@4 +NtListenChannel=NtListenChannel@8 +NtListenPort=NtListenPort@8 +NtLoadDriver=NtLoadDriver@4 +NtLoadKey=NtLoadKey@8 +NtLoadKey2=NtLoadKey2@12 +NtLockFile=NtLockFile@40 +NtLockVirtualMemory=NtLockVirtualMemory@16 +NtMakeTemporaryObject=NtMakeTemporaryObject@4 +NtMapViewOfSection=NtMapViewOfSection@40 +NtNotifyChangeDirectoryFile=NtNotifyChangeDirectoryFile@36 +NtNotifyChangeKey=NtNotifyChangeKey@40 +NtOpenChannel=NtOpenChannel@8 +NtOpenDirectoryObject=NtOpenDirectoryObject@12 +NtOpenEvent=NtOpenEvent@12 +NtOpenEventPair=NtOpenEventPair@12 +NtOpenFile=NtOpenFile@24 +NtOpenIoCompletion=NtOpenIoCompletion@12 +NtOpenKey=NtOpenKey@12 +NtOpenMutant=NtOpenMutant@12 +NtOpenObjectAuditAlarm=NtOpenObjectAuditAlarm@48 +NtOpenProcess=NtOpenProcess@16 +NtOpenProcessToken=NtOpenProcessToken@12 +NtOpenSection=NtOpenSection@12 +NtOpenSemaphore=NtOpenSemaphore@12 +NtOpenSymbolicLinkObject=NtOpenSymbolicLinkObject@12 +NtOpenThread=NtOpenThread@16 +NtOpenThreadToken=NtOpenThreadToken@16 +NtOpenTimer=NtOpenTimer@12 +NtPlugPlayControl=NtPlugPlayControl@16 +NtPrivilegeCheck=NtPrivilegeCheck@12 +NtPrivilegedServiceAuditAlarm=NtPrivilegedServiceAuditAlarm@20 +NtPrivilegeObjectAuditAlarm=NtPrivilegeObjectAuditAlarm@24 +NtProtectVirtualMemory=NtProtectVirtualMemory@20 +NtPulseEvent=NtPulseEvent@8 +NtQueueApcThread=NtQueueApcThread@20 +NtQueryAttributesFile=NtQueryAttributesFile@8 +NtQueryDefaultLocale=NtQueryDefaultLocale@8 +NtQueryDirectoryFile=NtQueryDirectoryFile@44 +NtQueryDirectoryObject=NtQueryDirectoryObject@28 +NtQueryEaFile=NtQueryEaFile@36 +NtQueryEvent=NtQueryEvent@20 +NtQueryFullAttributesFile=NtQueryFullAttributesFile@8 +NtQueryInformationAtom=NtQueryInformationAtom@20 +NtQueryInformationFile=NtQueryInformationFile@20 +NtQueryInformationPort=NtQueryInformationPort@20 +NtQueryInformationProcess=NtQueryInformationProcess@20 +NtQueryInformationThread=NtQueryInformationThread@20 +NtQueryInformationToken=NtQueryInformationToken@20 +NtQueryIoCompletion=NtQueryIoCompletion@20 +NtQueryIntervalProfile=NtQueryIntervalProfile@8 +NtQueryKey=NtQueryKey@20 +NtQueryMultipleValueKey=NtQueryMultipleValueKey@24 +NtQueryMutant=NtQueryMutant@20 +NtQueryObject=NtQueryObject@20 +NtQueryOleDirectoryFile=NtQueryOleDirectoryFile@44 +NtQueryPerformanceCounter=NtQueryPerformanceCounter@8 +NtQuerySection=NtQuerySection@20 +NtQuerySecurityObject=NtQuerySecurityObject@20 +NtQuerySemaphore=NtQuerySemaphore@20 +NtQuerySymbolicLinkObject=NtQuerySymbolicLinkObject@12 +NtQuerySystemEnvironmentValue=NtQuerySystemEnvironmentValue@16 +NtQuerySystemInformation=NtQuerySystemInformation@16 +NtQuerySystemTime=NtQuerySystemTime@4 +NtQueryTimer=NtQueryTimer@20 +NtQueryTimerResolution=NtQueryTimerResolution@12 +NtQueryValueKey=NtQueryValueKey@24 +NtQueryVirtualMemory=NtQueryVirtualMemory@24 +NtQueryVolumeInformationFile=NtQueryVolumeInformationFile@20 +NtRaiseException=NtRaiseException@12 +NtRaiseHardError=NtRaiseHardError@24 +NtReadFile=NtReadFile@36 +NtReadFileScatter=NtReadFileScatter@36 +NtReadRequestData=NtReadRequestData@24 +NtReadVirtualMemory=NtReadVirtualMemory@20 +NtRegisterThreadTerminatePort=NtRegisterThreadTerminatePort@4 +NtReleaseMutant=NtReleaseMutant@8 +NtReleaseSemaphore=NtReleaseSemaphore@12 +NtRemoveIoCompletion=NtRemoveIoCompletion@20 +NtReplaceKey=NtReplaceKey@12 +NtReplyPort=NtReplyPort@8 +NtReplyWaitReceivePort=NtReplyWaitReceivePort@16 +NtReplyWaitReplyPort=NtReplyWaitReplyPort@8 +NtReplyWaitSendChannel=NtReplyWaitSendChannel@12 +NtRequestPort=NtRequestPort@8 +NtRequestWaitReplyPort=NtRequestWaitReplyPort@12 +NtResetEvent=NtResetEvent@8 +NtRestoreKey=NtRestoreKey@12 +NtResumeThread=NtResumeThread@8 +NtSaveKey=NtSaveKey@8 +NtSendWaitReplyChannel=NtSendWaitReplyChannel@16 +NtSetContextChannel=NtSetContextChannel@4 +NtSetContextThread=NtSetContextThread@8 +NtSetDefaultHardErrorPort=NtSetDefaultHardErrorPort@4 +NtSetDefaultLocale=NtSetDefaultLocale@8 +NtSetEaFile=NtSetEaFile@16 +NtSetEvent=NtSetEvent@8 +NtSetHighEventPair=NtSetHighEventPair@4 +NtSetHighWaitLowEventPair=NtSetHighWaitLowEventPair@4 +NtSetInformationFile=NtSetInformationFile@20 +NtSetInformationKey=NtSetInformationKey@16 +NtSetInformationObject=NtSetInformationObject@16 +NtSetInformationProcess=NtSetInformationProcess@16 +NtSetInformationThread=NtSetInformationThread@16 +NtSetInformationToken=NtSetInformationToken@16 +NtSetIntervalProfile=NtSetIntervalProfile@8 +NtSetIoCompletion=NtSetIoCompletion@20 +NtSetLdtEntries=NtSetLdtEntries@24 +NtSetLowEventPair=NtSetLowEventPair@4 +NtSetLowWaitHighEventPair=NtSetLowWaitHighEventPair@4 +NtSetSecurityObject=NtSetSecurityObject@12 +NtSetSystemEnvironmentValue=NtSetSystemEnvironmentValue@8 +NtSetSystemInformation=NtSetSystemInformation@12 +NtSetSystemPowerState=NtSetSystemPowerState@12 +NtSetSystemTime=NtSetSystemTime@8 +NtSetTimer=NtSetTimer@28 +NtSetTimerResolution=NtSetTimerResolution@12 +NtSetValueKey=NtSetValueKey@24 +NtSetVolumeInformationFile=NtSetVolumeInformationFile@20 +NtShutdownSystem=NtShutdownSystem@4 +NtSignalAndWaitForSingleObject=NtSignalAndWaitForSingleObject@16 +NtStartProfile=NtStartProfile@4 +NtStopProfile=NtStopProfile@4 +NtSuspendThread=NtSuspendThread@8 +NtSystemDebugControl=NtSystemDebugControl@24 +NtTerminateProcess=NtTerminateProcess@8 +NtTerminateThread=NtTerminateThread@8 +NtTestAlert=NtTestAlert@0 +NtUnloadDriver=NtUnloadDriver@4 +NtUnloadKey=NtUnloadKey@4 +NtUnlockFile=NtUnlockFile@20 +NtUnlockVirtualMemory=NtUnlockVirtualMemory@16 +NtUnmapViewOfSection=NtUnmapViewOfSection@8 +NtVdmControl=NtVdmControl@8 +NtWaitForMultipleObjects=NtWaitForMultipleObjects@20 +NtWaitForSingleObject=NtWaitForSingleObject@12 +NtWaitHighEventPair=NtWaitHighEventPair@4 +NtWaitLowEventPair=NtWaitLowEventPair@4 +NtWriteFile=NtWriteFile@36 +NtWriteFileGather=NtWriteFileGather@36 +NtWriteRequestData=NtWriteRequestData@24 +NtWriteVirtualMemory=NtWriteVirtualMemory@20 +NtW32Call=NtW32Call@20 +NtYieldExecution=NtYieldExecution@0 +;PfxFindPrefix +;PfxInitialize +;PfxInsertPrefix +;PfxRemovePrefix +;PropertyLengthAsVariant +;RestoreEm87Context +;RtlAbortRXact +RtlAbsoluteToSelfRelativeSD=RtlAbsoluteToSelfRelativeSD@12 +RtlAcquirePebLock=RtlAcquirePebLock@0 +RtlAcquireResourceExclusive=RtlAcquireResourceExclusive@8 +RtlAcquireResourceShared=RtlAcquireResourceShared@8 +RtlAddAccessAllowedAce=RtlAddAccessAllowedAce@16 +RtlAddAccessDeniedAce=RtlAddAccessDeniedAce@16 +RtlAddAce=RtlAddAce@20 +;RtlAddActionToRXact +RtlAddAtomToAtomTable=RtlAddAtomToAtomTable@12 +;RtlAddAttributeActionToRXact +RtlAddAuditAccessAce=RtlAddAuditAccessAce@24 +;RtlAddCompoundAce +;RtlAdjustPrivilege +RtlAllocateAndInitializeSid=RtlAllocateAndInitializeSid@44 +RtlAllocateHandle=RtlAllocateHandle@8 +RtlAllocateHeap=RtlAllocateHeap@12 +RtlAnsiCharToUnicodeChar=RtlAnsiCharToUnicodeChar@4 +RtlAnsiStringToUnicodeSize=RtlAnsiStringToUnicodeSize@4 +RtlAnsiStringToUnicodeString=RtlAnsiStringToUnicodeString@12 +RtlAppendAsciizToString=RtlAppendAsciizToString@8 +RtlAppendStringToString=RtlAppendStringToString@8 +RtlAppendUnicodeStringToString=RtlAppendUnicodeStringToString@8 +RtlAppendUnicodeToString=RtlAppendUnicodeToString@8 +;RtlApplyRXact +;RtlApplyRXactNoFlush +RtlAreAllAccessesGranted=RtlAreAllAccessesGranted@8 +RtlAreAnyAccessesGranted=RtlAreAnyAccessesGranted@8 +RtlAreBitsClear=RtlAreBitsClear@12 +RtlAreBitsSet=RtlAreBitsSet@12 +RtlAssert=RtlAssert@16 +;RtlCaptureStackBackTrace +RtlCharToInteger=RtlCharToInteger@12 +RtlCheckRegistryKey=RtlCheckRegistryKey@8 +RtlClearAllBits=RtlClearAllBits@4 +RtlClearBits=RtlClearBits@12 +;RtlClosePropertySet +RtlCompactHeap=RtlCompactHeap@8 +RtlCompareMemory=RtlCompareMemory@12 +RtlCompareMemoryUlong=RtlCompareMemoryUlong@12 +RtlCompareString=RtlCompareString@12 +RtlCompareUnicodeString=RtlCompareUnicodeString@12 +RtlCompressBuffer=RtlCompressBuffer@32 +;RtlConsoleMultiByteToUnicodeN +RtlConvertExclusiveToShared=RtlConvertExclusiveToShared@4 +RtlConvertLongToLargeInteger=RtlConvertLongToLargeInteger@4 +RtlConvertSharedToExclusive=RtlConvertSharedToExclusive@4 +RtlConvertSidToUnicodeString=RtlConvertSidToUnicodeString@12 +;RtlConvertUiListToApiList +RtlConvertUlongToLargeInteger=RtlConvertUlongToLargeInteger@4 +RtlCopyLuid=RtlCopyLuid@8 +RtlCopyLuidAndAttributesArray=RtlCopyLuidAndAttributesArray@12 +;RtlCopySecurityDescriptor +RtlCopySid=RtlCopySid@12 +RtlCopySidAndAttributesArray=RtlCopySidAndAttributesArray@28 +RtlCopyString=RtlCopyString@8 +RtlCopyUnicodeString=RtlCopyUnicodeString@8 +RtlCreateAcl=RtlCreateAcl@12 +;RtlCreateAndSetSD +RtlCreateAtomTable=RtlCreateAtomTable@8 +RtlCreateEnvironment=RtlCreateEnvironment@8 +RtlCreateHeap=RtlCreateHeap@24 +RtlCreateProcessParameters=RtlCreateProcessParameters@40 +;RtlCreatePropertySet +;RtlCreateQueryDebugBuffer +RtlCreateRegistryKey=RtlCreateRegistryKey@8 +RtlCreateSecurityDescriptor=RtlCreateSecurityDescriptor@8 +;RtlCreateTagHeap +RtlCreateUnicodeString=RtlCreateUnicodeString@8 +RtlCreateUnicodeStringFromAsciiz=RtlCreateUnicodeStringFromAsciiz@8 +RtlCreateUserProcess=RtlCreateUserProcess@40 +;RtlCreateUserSecurityObject +RtlCreateUserThread=RtlCreateUserThread@40 +RtlCustomCPToUnicodeN=RtlCustomCPToUnicodeN@24 +;RtlCutoverTimeToSystemTime +RtlDeNormalizeProcessParams=RtlDeNormalizeProcessParams@4 +RtlDecompressBuffer=RtlDecompressBuffer@24 +RtlDecompressFragment=RtlDecompressFragment@32 +;RtlDelete +RtlDeleteAce=RtlDeleteAce@8 +RtlDeleteAtomFromAtomTable=RtlDeleteAtomFromAtomTable@8 +RtlDeleteCriticalSection=RtlDeleteCriticalSection@4 +;RtlDeleteElementGenericTable +;RtlDeleteNoSplay +RtlDeleteRegistryValue=RtlDeleteRegistryValue@12 +RtlDeleteResource=RtlDeleteResource@4 +;RtlDeleteSecurityObject +RtlDestroyAtomTable=RtlDestroyAtomTable@4 +RtlDestroyEnvironment=RtlDestroyEnvironment@4 +RtlDestroyHandleTable=RtlDestroyHandleTable@4 +RtlDestroyHeap=RtlDestroyHeap@4 +RtlDestroyProcessParameters=RtlDestroyProcessParameters@4 +;RtlDestroyQueryDebugBuffer +RtlDetermineDosPathNameType_U=RtlDetermineDosPathNameType_U@4 +RtlDoesFileExists_U=RtlDoesFileExists_U@4 +RtlDosPathNameToNtPathName_U=RtlDosPathNameToNtPathName_U@16 +RtlDosSearchPath_U=RtlDosSearchPath_U@24 +RtlDowncaseUnicodeString=RtlDowncaseUnicodeString@12 +RtlDumpResource=RtlDumpResource@4 +RtlEmptyAtomTable=RtlEmptyAtomTable@8 +RtlEnlargedIntegerMultiply=RtlEnlargedIntegerMultiply@8 +RtlEnlargedUnsignedDivide=RtlEnlargedUnsignedDivide@16 +RtlEnlargedUnsignedMultiply=RtlEnlargedUnsignedMultiply@8 +RtlEnterCriticalSection=RtlEnterCriticalSection@4 +RtlEnumProcessHeaps=RtlEnumProcessHeaps@8 +;RtlEnumerateGenericTable +;RtlEnumerateGenericTableWithoutSplaying +;RtlEnumerateProperties +RtlEqualComputerName=RtlEqualComputerName@8 +RtlEqualDomainName=RtlEqualDomainName@8 +RtlEqualLuid=RtlEqualLuid@8 +RtlEqualPrefixSid=RtlEqualPrefixSid@8 +RtlEqualSid=RtlEqualSid@8 +RtlEqualString=RtlEqualString@12 +RtlEqualUnicodeString=RtlEqualUnicodeString@12 +RtlEraseUnicodeString=RtlEraseUnicodeString@4 +RtlExpandEnvironmentStrings_U=RtlExpandEnvironmentStrings_U@16 +;RtlExtendHeap +RtlExtendedIntegerMultiply=RtlExtendedIntegerMultiply@12 +RtlExtendedLargeIntegerDivide=RtlExtendedLargeIntegerDivide@16 +RtlExtendedMagicDivide=RtlExtendedMagicDivide@20 +RtlFillMemory=RtlFillMemory@12 +RtlFillMemoryUlong=RtlFillMemoryUlong@12 +RtlFindClearBits=RtlFindClearBits@12 +RtlFindClearBitsAndSet=RtlFindClearBitsAndSet@12 +RtlFirstFreeAce=RtlFirstFreeAce@8 +RtlFindLongestRunClear=RtlFindLongestRunClear@8 +RtlFindLongestRunSet=RtlFindLongestRunSet@8 +RtlFindMessage=RtlFindMessage@20 +RtlFindSetBits=RtlFindSetBits@12 +RtlFindSetBitsAndClear=RtlFindSetBitsAndClear@12 +;RtlFlushPropertySet +RtlFormatCurrentUserKeyPath=RtlFormatCurrentUserKeyPath@4 +;RtlFormatMessage +RtlFreeAnsiString=RtlFreeAnsiString@4 +RtlFreeHandle=RtlFreeHandle@8 +RtlFreeHeap=RtlFreeHeap@12 +RtlFreeSid=RtlFreeSid@4 +RtlFreeUnicodeString=RtlFreeUnicodeString@4 +RtlFreeUserThreadStack=RtlFreeUserThreadStack@8 +RtlGenerate8dot3Name=RtlGenerate8dot3Name@16 +RtlGetAce=RtlGetAce@12 +;RtlGetCallersAddress +RtlGetCompressionWorkSpaceSize=RtlGetCompressionWorkSpaceSize@12 +RtlGetControlSecurityDescriptor=RtlGetControlSecurityDescriptor@12 +RtlGetCurrentDirectory_U=RtlGetCurrentDirectory_U@8 +RtlGetDaclSecurityDescriptor=RtlGetDaclSecurityDescriptor@16 +;RtlGetElementGenericTable +RtlGetFullPathName_U=RtlGetFullPathName_U@16 +RtlGetGroupSecurityDescriptor=RtlGetGroupSecurityDescriptor@12 +RtlGetLongestNtPathLength=RtlGetLongestNtPathLength@0 +RtlGetNtGlobalFlags=RtlGetNtGlobalFlags@0 +RtlGetNtProductType=RtlGetNtProductType@4 +RtlGetOwnerSecurityDescriptor=RtlGetOwnerSecurityDescriptor@12 +RtlGetProcessHeaps=RtlGetProcessHeaps@8 +RtlGetSaclSecurityDescriptor=RtlGetSaclSecurityDescriptor@16 +;RtlGetUserInfoHeap +;RtlGuidToPropertySetName +RtlIdentifierAuthoritySid=RtlIdentifierAuthoritySid@4 +RtlImageDirectoryEntryToData=RtlImageDirectoryEntryToData@16 +RtlImageNtHeader=RtlImageNtHeader@4 +RtlImageRvaToSection=RtlImageRvaToSection@12 +RtlImageRvaToVa=RtlImageRvaToVa@16 +RtlImpersonateSelf=RtlImpersonateSelf@4 +RtlInitAnsiString=RtlInitAnsiString@8 +;RtlInitCodePageTable +;RtlInitNlsTables +RtlInitString=RtlInitString@8 +RtlInitUnicodeString=RtlInitUnicodeString@8 +;RtlInitializeAtomPackage +RtlInitializeBitMap=RtlInitializeBitMap@12 +RtlInitializeContext=RtlInitializeContext@20 +RtlInitializeCriticalSection=RtlInitializeCriticalSection@4 +;RtlInitializeGenericTable +RtlInitializeHandleTable=RtlInitializeHandleTable@12 +;RtlInitializeRXact +RtlInitializeResource=RtlInitializeResource@4 +RtlInitializeSid=RtlInitializeSid@12 +;RtlInsertElementGenericTable +RtlIntegerToChar=RtlIntegerToChar@16 +RtlIntegerToUnicodeString=RtlIntegerToUnicodeString@12 +RtlIsDosDeviceName_U=RtlIsDosDeviceName_U@4 +;RtlIsGenericTableEmpty +RtlIsNameLegalDOS8Dot3=RtlIsNameLegalDOS8Dot3@12 +;RtlIsTextUnicode +RtlIsValidHandle=RtlIsValidHandle@8 +RtlIsValidIndexHandle=RtlIsValidIndexHandle@12 +RtlLargeIntegerAdd=RtlLargeIntegerAdd@16 +RtlLargeIntegerArithmeticShift=RtlLargeIntegerArithmeticShift@12 +RtlLargeIntegerDivide=RtlLargeIntegerDivide@20 +RtlLargeIntegerNegate=RtlLargeIntegerNegate@8 +RtlLargeIntegerShiftLeft=RtlLargeIntegerShiftLeft@12 +RtlLargeIntegerShiftRight=RtlLargeIntegerShiftRight@12 +RtlLargeIntegerSubtract=RtlLargeIntegerSubtract@16 +RtlLargeIntegerToChar=RtlLargeIntegerToChar@16 +RtlLeaveCriticalSection=RtlLeaveCriticalSection@4 +RtlLengthRequiredSid=RtlLengthRequiredSid@4 +RtlLengthSecurityDescriptor=RtlLengthSecurityDescriptor@4 +RtlLengthSid=RtlLengthSid@4 +RtlLocalTimeToSystemTime=RtlLocalTimeToSystemTime@8 +RtlLockHeap=RtlLockHeap@4 +RtlLookupAtomInAtomTable=RtlLookupAtomInAtomTable@12 +;RtlLookupElementGenericTable +RtlMakeSelfRelativeSD=RtlMakeSelfRelativeSD@12 +RtlMapGenericMask=RtlMapGenericMask@8 +RtlMoveMemory=RtlMoveMemory@12 +RtlMultiByteToUnicodeN=RtlMultiByteToUnicodeN@20 +RtlMultiByteToUnicodeSize=RtlMultiByteToUnicodeSize@12 +;RtlNewInstanceSecurityObject +;RtlNewSecurityGrantedAccess +;RtlNewSecurityObject +RtlNormalizeProcessParams=RtlNormalizeProcessParams@4 +RtlNtStatusToDosError=RtlNtStatusToDosError@4 +RtlNtStatusToPsxErrno=RtlNtStatusToPsxErrno@4 +;RtlNumberGenericTableElements +RtlNumberOfClearBits=RtlNumberOfClearBits@4 +RtlNumberOfSetBits=RtlNumberOfSetBits@4 +RtlOemStringToUnicodeSize=RtlOemStringToUnicodeSize@4 +RtlOemStringToUnicodeString=RtlOemStringToUnicodeString@12 +RtlOemToUnicodeN=RtlOemToUnicodeN@20 +RtlOpenCurrentUser=RtlOpenCurrentUser@8 +;RtlPcToFileHeader +RtlPinAtomInAtomTable=RtlPinAtomInAtomTable@8 +RtlPrefixString=RtlPrefixString@12 +RtlPrefixUnicodeString=RtlPrefixUnicodeString@12 +;RtlPropertySetNameToGuid +;RtlProtectHeap +RtlQueryAtomInAtomTable=RtlQueryAtomInAtomTable@24 +RtlQueryEnvironmentVariable_U=RtlQueryEnvironmentVariable_U@12 +RtlQueryInformationAcl=RtlQueryInformationAcl@16 +;RtlQueryProcessBackTraceInformation +;RtlQueryProcessDebugInformation +;RtlQueryProcessHeapInformation +;RtlQueryProcessLockInformation +;RtlQueryProperties +;RtlQueryPropertyNames +;RtlQueryPropertySet +RtlQueryRegistryValues=RtlQueryRegistryValues@20 +;RtlQuerySecutityObject +;RtlQueryTagHeap +RtlQueryTimeZoneInformation=RtlQueryTimeZoneInformation@4 +RtlRaiseException=RtlRaiseException@4 +RtlRaiseStatus=RtlRaiseStatus@4 +;RtlRandom +RtlReAllocateHeap=RtlReAllocateHeap@16 +;RtlRealPredecessor +;RtlRealSuccessor +RtlReleasePebLock=RtlReleasePebLock@0 +RtlReleaseResource=RtlReleaseResource@4 +;RtlRemoteCall +;RtlResetRtlTranslations +;RtlRunDecodeUnicodeString +;RtlRunEncodeUnicodeString +RtlSecondsSince1970ToTime=RtlSecondsSince1970ToTime@8 +RtlSecondsSince1980ToTime=RtlSecondsSince1980ToTime@8 +RtlSelfRelativeToAbsoluteSD=RtlSelfRelativeToAbsoluteSD@44 +RtlSetAllBits=RtlSetAllBits@4 +;RtlSetAttributesSecurityDescriptor +RtlSetBits=RtlSetBits@12 +RtlSetCurrentDirectory_U=RtlSetCurrentDirectory_U@4 +RtlSetCurrentEnvironment=RtlSetCurrentEnvironment@8 +RtlSetDaclSecurityDescriptor=RtlSetDaclSecurityDescriptor@16 +RtlSetEnvironmentVariable=RtlSetEnvironmentVariable@12 +RtlSetGroupSecurityDescriptor=RtlSetGroupSecurityDescriptor@12 +RtlSetInformationAcl=RtlSetInformationAcl@16 +RtlSetOwnerSecurityDescriptor=RtlSetOwnerSecurityDescriptor@12 +;RtlSetProperties +;RtlSetPropertyNames +;RtlSetPropertySetClassId +RtlSetSaclSecurityDescriptor=RtlSetSaclSecurityDescriptor@16 +;RtlSetSecurityObject +RtlSetTimeZoneInformation=RtlSetTimeZoneInformation@4 +;RtlSetUnicodeCallouts +;RtlSetUserFlagsHeap +;RtlSetUserValueHeap +RtlSizeHeap=RtlSizeHeap@12 +;RtlSplay +;RtlStartRXact +RtlSubAuthorityCountSid=RtlSubAuthorityCountSid@4 +RtlSubAuthoritySid=RtlSubAuthoritySid@8 +;RtlSubtreePredecessor +;RtlSubtreeSuccessor +RtlSystemTimeToLocalTime=RtlSystemTimeToLocalTime@8 +RtlTimeFieldsToTime=RtlTimeFieldsToTime@8 +RtlTimeToElapsedTimeFields=RtlTimeToElapsedTimeFields@8 +RtlTimeToSecondsSince1970=RtlTimeToSecondsSince1970@8 +RtlTimeToSecondsSince1980=RtlTimeToSecondsSince1980@8 +RtlTimeToTimeFields=RtlTimeToTimeFields@8 +RtlTryEnterCriticalSection=RtlTryEnterCriticalSection@4 +RtlUnicodeStringToAnsiSize=RtlUnicodeStringToAnsiSize@4 +RtlUnicodeStringToAnsiString=RtlUnicodeStringToAnsiString@12 +RtlUnicodeStringToCountedOemString=RtlUnicodeStringToCountedOemString@12 +RtlUnicodeStringToInteger=RtlUnicodeStringToInteger@12 +RtlUnicodeStringToOemSize=RtlUnicodeStringToOemSize@4 +RtlUnicodeStringToOemString=RtlUnicodeStringToOemString@12 +RtlUnicodeToCustomCPN=RtlUnicodeToCustomCPN@24 +RtlUnicodeToMultiByteN=RtlUnicodeToMultiByteN@20 +RtlUnicodeToMultiByteSize=RtlUnicodeToMultiByteSize@12 +RtlUnicodeToOemN=RtlUnicodeToOemN@20 +;RtlUniform +RtlUnlockHeap=RtlUnlockHeap@4 +RtlUnwind=RtlUnwind@16 +RtlUpcaseUnicodeChar=RtlUpcaseUnicodeChar@4 +RtlUpcaseUnicodeString=RtlUpcaseUnicodeString@12 +RtlUpcaseUnicodeStringToAnsiString=RtlUpcaseUnicodeStringToAnsiString@12 +RtlUpcaseUnicodeStringToCountedOemString=RtlUpcaseUnicodeStringToCountedOemString@12 +RtlUpcaseUnicodeStringToOemString=RtlUpcaseUnicodeStringToOemString@12 +RtlUpcaseUnicodeToCustomCPN=RtlUpcaseUnicodeToCustomCPN@24 +RtlUpcaseUnicodeToMultiByteN=RtlUpcaseUnicodeToMultiByteN@20 +RtlUpcaseUnicodeToOemN=RtlUpcaseUnicodeToOemN@20 +RtlUpperChar=RtlUpperChar@4 +RtlUpperString=RtlUpperString@8 +;RtlUsageHeap +RtlValidAcl=RtlValidAcl@4 +RtlValidSecurityDescriptor=RtlValidSecurityDescriptor@4 +RtlValidSid=RtlValidSid@4 +RtlValidateHeap=RtlValidateHeap@12 +RtlValidateProcessHeaps=RtlValidateProcessHeaps@0 +;RtlWalkHeap +RtlWriteRegistryValue=RtlWriteRegistryValue@24 +;RtlZeroHeap +RtlZeroMemory=RtlZeroMemory@8 +RtlpNtCreateKey=RtlpNtCreateKey@24 +RtlpNtEnumerateSubKey=RtlpNtEnumerateSubKey@16 +RtlpNtMakeTemporaryKey=RtlpNtMakeTemporaryKey@4 +RtlpNtOpenKey=RtlpNtOpenKey@16 +RtlpNtQueryValueKey=RtlpNtQueryValueKey@20 +RtlpNtSetValueKey=RtlpNtSetValueKey@16 +;RtlpUnWaitCriticalSection +;RtlpWaitForCriticalSection +RtlxAnsiStringToUnicodeSize=RtlxAnsiStringToUnicodeSize@4 +RtlxOemStringToUnicodeSize=RtlxOemStringToUnicodeSize@4 +RtlxUnicodeStringToAnsiSize=RtlxUnicodeStringToAnsiSize@4 +RtlxUnicodeStringToOemSize=RtlxUnicodeStringToOemSize@4 +;SaveEm87Context +ZwAcceptConnectPort=ZwAcceptConnectPort@24 +ZwAccessCheck=ZwAccessCheck@32 +ZwAccessCheckAndAuditAlarm=ZwAccessCheckAndAuditAlarm@44 +ZwAddAtom=ZwAddAtom@8 +ZwAdjustGroupsToken=ZwAdjustGroupsToken@24 +ZwAdjustPrivilegesToken=ZwAdjustPrivilegesToken@24 +ZwAlertResumeThread=ZwAlertResumeThread@8 +ZwAlertThread=ZwAlertThread@4 +ZwAllocateLocallyUniqueId=ZwAllocateLocallyUniqueId@4 +ZwAllocateUuids=ZwAllocateUuids@12 +ZwAllocateVirtualMemory=ZwAllocateVirtualMemory@24 +ZwCallbackReturn=ZwCallbackReturn@12 +ZwCancelIoFile=ZwCancelIoFile@8 +ZwCancelTimer=ZwCancelTimer@8 +ZwClearEvent=ZwClearEvent@4 +ZwClose=ZwClose@4 +ZwCloseObjectAuditAlarm=ZwCloseObjectAuditAlarm@12 +ZwCompleteConnectPort=ZwCompleteConnectPort@4 +ZwConnectPort=ZwConnectPort@32 +ZwContinue=ZwContinue@8 +ZwCreateChannel=ZwCreateChannel@8 +ZwCreateDirectoryObject=ZwCreateDirectoryObject@12 +ZwCreateEvent=ZwCreateEvent@20 +ZwCreateEventPair=ZwCreateEventPair@12 +ZwCreateFile=ZwCreateFile@44 +ZwCreateIoCompletion=ZwCreateIoCompletion@16 +ZwCreateKey=ZwCreateKey@28 +ZwCreateMailslotFile=ZwCreateMailslotFile@32 +ZwCreateMutant=ZwCreateMutant@16 +ZwCreateNamedPipeFile=ZwCreateNamedPipeFile@56 +ZwCreatePagingFile=ZwCreatePagingFile@16 +ZwCreatePort=ZwCreatePort@20 +ZwCreateProcess=ZwCreateProcess@32 +ZwCreateProfile=ZwCreateProfile@36 +ZwCreateSection=ZwCreateSection@28 +ZwCreateSemaphore=ZwCreateSemaphore@20 +ZwCreateSymbolicLinkObject=ZwCreateSymbolicLinkObject@16 +ZwCreateThread=ZwCreateThread@32 +ZwCreateTimer=ZwCreateTimer@16 +ZwCreateToken=ZwCreateToken@52 +ZwDelayExecution=ZwDelayExecution@8 +ZwDeleteAtom=ZwDeleteAtom@4 +ZwDeleteFile=ZwDeleteFile@4 +ZwDeleteKey=ZwDeleteKey@4 +ZwDeleteObjectAuditAlarm=ZwDeleteObjectAuditAlarm@12 +ZwDeleteValueKey=ZwDeleteValueKey@8 +ZwDeviceIoControlFile=ZwDeviceIoControlFile@40 +ZwDisplayString=ZwDisplayString@4 +ZwDuplicateObject=ZwDuplicateObject@28 +ZwDuplicateToken=ZwDuplicateToken@24 +ZwEnumerateKey=ZwEnumerateKey@24 +ZwEnumerateValueKey=ZwEnumerateValueKey@24 +ZwExtendSection=ZwExtendSection@8 +ZwFindAtom=ZwFindAtom@8 +ZwFlushBuffersFile=ZwFlushBuffersFile@8 +ZwFlushInstructionCache=ZwFlushInstructionCache@12 +ZwFlushKey=ZwFlushKey@4 +ZwFlushVirtualMemory=ZwFlushVirtualMemory@16 +ZwFlushWriteBuffer=ZwFlushWriteBuffer@0 +ZwFreeVirtualMemory=ZwFreeVirtualMemory@16 +ZwFsControlFile=ZwFsControlFile@40 +ZwGetContextThread=ZwGetContextThread@8 +ZwGetPlugPlayEvent=ZwGetPlugPlayEvent@16 +ZwGetTickCount=ZwGetTickCount@4 +ZwImpersonateClientOfPort=ZwImpersonateClientOfPort@8 +ZwImpersonateThread=ZwImpersonateThread@12 +ZwInitializeRegistry=ZwInitializeRegistry@4 +ZwListenChannel=ZwListenChannel@8 +ZwListenPort=ZwListenPort@8 +ZwLoadDriver=ZwLoadDriver@4 +ZwLoadKey=ZwLoadKey@8 +ZwLoadKey2=ZwLoadKey2@12 +ZwLockFile=ZwLockFile@40 +ZwLockVirtualMemory=ZwLockVirtualMemory@16 +ZwMakeTemporaryObject=ZwMakeTemporaryObject@4 +ZwMapViewOfSection=ZwMapViewOfSection@40 +ZwNotifyChangeDirectoryFile=ZwNotifyChangeDirectoryFile@36 +ZwNotifyChangeKey=ZwNotifyChangeKey@40 +ZwOpenChannel=ZwOpenChannel@8 +ZwOpenDirectoryObject=ZwOpenDirectoryObject@12 +ZwOpenEvent=ZwOpenEvent@12 +ZwOpenEventPair=ZwOpenEventPair@12 +ZwOpenFile=ZwOpenFile@24 +ZwOpenIoCompletion=ZwOpenIoCompletion@12 +ZwOpenKey=ZwOpenKey@12 +ZwOpenMutant=ZwOpenMutant@12 +ZwOpenObjectAuditAlarm=ZwOpenObjectAuditAlarm@48 +ZwOpenProcess=ZwOpenProcess@16 +ZwOpenProcessToken=ZwOpenProcessToken@12 +ZwOpenSection=ZwOpenSection@12 +ZwOpenSemaphore=ZwOpenSemaphore@12 +ZwOpenSymbolicLinkObject=ZwOpenSymbolicLinkObject@12 +ZwOpenThread=ZwOpenThread@16 +ZwOpenThreadToken=ZwOpenThreadToken@16 +ZwOpenTimer=ZwOpenTimer@12 +ZwPlugPlayControl=ZwPlugPlayControl@16 +ZwPrivilegeCheck=ZwPrivilegeCheck@12 +ZwPrivilegedServiceAuditAlarm=ZwPrivilegedServiceAuditAlarm@20 +ZwPrivilegeObjectAuditAlarm=ZwPrivilegeObjectAuditAlarm@24 +ZwProtectVirtualMemory=ZwProtectVirtualMemory@20 +ZwPulseEvent=ZwPulseEvent@8 +ZwQueueApcThread=ZwQueueApcThread@20 +ZwQueryInformationAtom=ZwQueryInformationAtom@20 +ZwQueryAttributesFile=ZwQueryAttributesFile@8 +ZwQueryDefaultLocale=ZwQueryDefaultLocale@8 +ZwQueryDirectoryFile=ZwQueryDirectoryFile@44 +ZwQueryDirectoryObject=ZwQueryDirectoryObject@28 +ZwQueryEaFile=ZwQueryEaFile@36 +ZwQueryEvent=ZwQueryEvent@20 +ZwQueryFullAttributesFile=ZwQueryFullAttributesFile@8 +ZwQueryInformationFile=ZwQueryInformationFile@20 +ZwQueryInformationPort=ZwQueryInformationPort@20 +ZwQueryInformationProcess=ZwQueryInformationProcess@20 +ZwQueryInformationThread=ZwQueryInformationThread@20 +ZwQueryInformationToken=ZwQueryInformationToken@20 +ZwQueryIntervalProfile=ZwQueryIntervalProfile@8 +ZwQueryIoCompletion=ZwQueryIoCompletion@20 +ZwQueryKey=ZwQueryKey@20 +ZwQueryMultipleValueKey=ZwQueryMultipleValueKey@24 +ZwQueryMutant=ZwQueryMutant@20 +ZwQueryObject=ZwQueryObject@20 +ZwQueryOleDirectoryFile=ZwQueryOleDirectoryFile@44 +ZwQueryPerformanceCounter=ZwQueryPerformanceCounter@8 +ZwQuerySection=ZwQuerySection@20 +ZwQuerySecurityObject=ZwQuerySecurityObject@20 +ZwQuerySemaphore=ZwQuerySemaphore@20 +ZwQuerySymbolicLinkObject=ZwQuerySymbolicLinkObject@12 +ZwQuerySystemEnvironmentValue=ZwQuerySystemEnvironmentValue@16 +ZwQuerySystemInformation=ZwQuerySystemInformation@16 +ZwQuerySystemTime=ZwQuerySystemTime@4 +ZwQueryTimer=ZwQueryTimer@20 +ZwQueryTimerResolution=ZwQueryTimerResolution@12 +ZwQueryValueKey=ZwQueryValueKey@24 +ZwQueryVirtualMemory=ZwQueryVirtualMemory@24 +ZwQueryVolumeInformationFile=ZwQueryVolumeInformationFile@20 +ZwRaiseException=ZwRaiseException@12 +ZwRaiseHardError=ZwRaiseHardError@24 +ZwReadFile=ZwReadFile@36 +ZwReadFileScatter=ZwReadFileScatter@36 +ZwReadRequestData=ZwReadRequestData@24 +ZwReadVirtualMemory=ZwReadVirtualMemory@20 +ZwRegisterThreadTerminatePort=ZwRegisterThreadTerminatePort@4 +ZwReleaseMutant=ZwReleaseMutant@8 +ZwReleaseSemaphore=ZwReleaseSemaphore@12 +ZwRemoveIoCompletion=ZwRemoveIoCompletion@20 +ZwReplaceKey=ZwReplaceKey@12 +ZwReplyPort=ZwReplyPort@8 +ZwReplyWaitReceivePort=ZwReplyWaitReceivePort@16 +ZwReplyWaitReplyPort=ZwReplyWaitReplyPort@8 +ZwReplyWaitSendChannel=ZwReplyWaitSendChannel@12 +ZwRequestPort=ZwRequestPort@8 +ZwRequestWaitReplyPort=ZwRequestWaitReplyPort@12 +ZwResetEvent=ZwResetEvent@8 +ZwRestoreKey=ZwRestoreKey@12 +ZwResumeThread=ZwResumeThread@8 +ZwSaveKey=ZwSaveKey@8 +ZwSendWaitReplyChannel=ZwSendWaitReplyChannel@16 +ZwSetContextChannel=ZwSetContextChannel@4 +ZwSetContextThread=ZwSetContextThread@8 +ZwSetDefaultHardErrorPort=ZwSetDefaultHardErrorPort@4 +ZwSetDefaultLocale=ZwSetDefaultLocale@8 +ZwSetEaFile=ZwSetEaFile@16 +ZwSetEvent=ZwSetEvent@8 +ZwSetHighEventPair=ZwSetHighEventPair@4 +ZwSetHighWaitLowEventPair=ZwSetHighWaitLowEventPair@4 +ZwSetInformationFile=ZwSetInformationFile@20 +ZwSetInformationKey=ZwSetInformationKey@16 +ZwSetInformationObject=ZwSetInformationObject@16 +ZwSetInformationProcess=ZwSetInformationProcess@16 +ZwSetInformationThread=ZwSetInformationThread@16 +ZwSetInformationToken=ZwSetInformationToken@16 +ZwSetIntervalProfile=ZwSetIntervalProfile@8 +ZwSetIoCompletion=ZwSetIoCompletion@20 +ZwSetLdtEntries=ZwSetLdtEntries@24 +ZwSetLowEventPair=ZwSetLowEventPair@4 +ZwSetLowWaitHighEventPair=ZwSetLowWaitHighEventPair@4 +ZwSetSecurityObject=ZwSetSecurityObject@12 +ZwSetSystemEnvironmentValue=ZwSetSystemEnvironmentValue@8 +ZwSetSystemInformation=ZwSetSystemInformation@12 +ZwSetSystemPowerState=ZwSetSystemPowerState@12 +ZwSetSystemTime=ZwSetSystemTime@8 +ZwSetTimer=ZwSetTimer@28 +ZwSetTimerResolution=ZwSetTimerResolution@12 +ZwSetValueKey=ZwSetValueKey@24 +ZwSetVolumeInformationFile=ZwSetVolumeInformationFile@20 +ZwShutdownSystem=ZwShutdownSystem@4 +ZwSignalAndWaitForSingleObject=ZwSignalAndWaitForSingleObject@16 +ZwStartProfile=ZwStartProfile@4 +ZwStopProfile=ZwStopProfile@4 +ZwSuspendThread=ZwSuspendThread@8 +ZwSystemDebugControl=ZwSystemDebugControl@24 +ZwTerminateProcess=ZwTerminateProcess@8 +ZwTerminateThread=ZwTerminateThread@8 +ZwTestAlert=ZwTestAlert@0 +ZwUnloadDriver=ZwUnloadDriver@4 +ZwUnloadKey=ZwUnloadKey@4 +ZwUnlockFile=ZwUnlockFile@20 +ZwUnlockVirtualMemory=ZwUnlockVirtualMemory@16 +ZwUnmapViewOfSection=ZwUnmapViewOfSection@8 +ZwVdmControl=ZwVdmControl@8 +ZwWaitForMultipleObjects=ZwWaitForMultipleObjects@20 +ZwWaitForSingleObject=ZwWaitForSingleObject@12 +ZwWaitHighEventPair=ZwWaitHighEventPair@4 +ZwWaitLowEventPair=ZwWaitLowEventPair@4 +ZwWriteFile=ZwWriteFile@36 +ZwWriteFileGather=ZwWriteFileGather@36 +ZwWriteRequestData=ZwWriteRequestData@24 +ZwWriteVirtualMemory=ZwWriteVirtualMemory@20 +ZwW32Call=ZwW32Call@20 +ZwYieldExecution=ZwYieldExecution@0 +InterlockedIncrement=InterlockedIncrement@4 +InterlockedDecrement=InterlockedDecrement@4 +InterlockedExchange=InterlockedExchange@8 +InterlockedCompareExchange=InterlockedCompareExchange@12 +__isascii +__iscsym +__iscsymf +__toascii +;_alldiv +;_allmul +;_alloca_probe +;_allrem +;_allshl +;_allshr +_atoi64 +;_aulldiv +;_aullrem +;_aullshr +;_chkstk +;_fltused +_ftol +_i64toa +_i64tow +_itoa +_itow +_ltoa +_ltow +_memccpy +_memicmp +_snprintf +_snwprintf +_splitpath +_strcmpi +_stricmp +_strlwr +_strnicmp +_strupr +_tolower +_toupper +_ultoa +_ultow +_vsnprintf +_wcsicmp +_wcslwr +_wcsnicmp +_wcsupr +_wtoi +_wtoi64 +_wtol +abs +atan +atoi +atol +ceil +cos +fabs +floor +isalpha +isalnum +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +iswalpha +iswctype +isxdigit +labs +log +mbstowcs +memchr +memcmp +memcpy +memmove +memset +pow +qsort +sin +sprintf +sqrt +;sscanf +strcat +strchr +strcmp +strcpy +strcspn +strlen +strncat +strncmp +strncpy +strpbrk +strrchr +strspn +strstr +strtol +strtoul +swprintf +tan +tolower +toupper +towlower +towupper +vsprintf +wcscat +wcschr +wcscmp +wcscpy +wcscspn +wcslen +wcsncat +wcsncmp +wcsncpy +wcspbrk +wcsrchr +wcsspn +wcsstr +wcstol +wcstombs +wcstoul +wine_dbgstr_an +wine_dbgstr_wn +wine_dbgstr_guid +wine_dbg_vprintf +wine_dbg_printf +wine_dbg_log +;EOF diff --git a/lib/ntdll/def/ntdll.rc b/lib/ntdll/def/ntdll.rc new file mode 100644 index 0000000..3d18969 --- /dev/null +++ b/lib/ntdll/def/ntdll.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Layer DLL\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ntdll\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ntdll.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/lib/ntdll/ldr/.cvsignore b/lib/ntdll/ldr/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/ldr/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/ldr/startup.c b/lib/ntdll/ldr/startup.c new file mode 100644 index 0000000..d897e55 --- /dev/null +++ b/lib/ntdll/ldr/startup.c @@ -0,0 +1,280 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/ldr/startup.c + * PURPOSE: Process startup for PE executables + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +VOID RtlInitializeHeapManager (VOID); + +/* GLOBALS *******************************************************************/ + + +extern unsigned int _image_base__; + +static CRITICAL_SECTION PebLock; +static CRITICAL_SECTION LoaderLock; +static RTL_BITMAP TlsBitMap; + +ULONG NtGlobalFlag = 0; + + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +LdrInitializeThunk (ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4) +{ + PIMAGE_NT_HEADERS NTHeaders; + PEPFUNC EntryPoint; + PIMAGE_DOS_HEADER PEDosHeader; + NTSTATUS Status; + PVOID ImageBase; + PPEB Peb; + PLDR_MODULE NtModule; // ntdll + PLDR_MODULE ExeModule; // executable + WCHAR FullNtDllPath[MAX_PATH]; + + DPRINT("LdrInitializeThunk()\n"); + if (NtCurrentPeb()->Ldr != NULL && NtCurrentPeb()->Ldr->Initialized == TRUE) + { + PLIST_ENTRY current_entry; + PDLLMAIN_FUNC Entrypoint; + PLDR_MODULE current; + + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + current_entry = + NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink; + while (current_entry != + &NtCurrentPeb()->Ldr->InInitializationOrderModuleList) + { + current = CONTAINING_RECORD(current_entry, LDR_MODULE, + InInitializationOrderModuleList); + Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint; + if (Entrypoint != NULL && + current->BaseAddress != NtCurrentPeb()->ImageBaseAddress) + { + (VOID)Entrypoint(current->BaseAddress, DLL_THREAD_ATTACH, NULL); + } + current_entry = current_entry->Flink; + } + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); + return; + } + + Peb = (PPEB)(PEB_BASE); + DPRINT("Peb %x\n", Peb); + ImageBase = Peb->ImageBaseAddress; + DPRINT("ImageBase %x\n", ImageBase); + if (ImageBase <= (PVOID)0x1000) + { + DPRINT("ImageBase is null\n"); + ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL); + } + + NtGlobalFlag = Peb->NtGlobalFlag; + + /* If MZ header exists */ + PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase; + DPRINT("PEDosHeader %x\n", PEDosHeader); + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC || + PEDosHeader->e_lfanew == 0L || + *(PULONG)((PUCHAR)ImageBase + PEDosHeader->e_lfanew) != IMAGE_PE_MAGIC) + { + DbgPrint("Image has bad header\n"); + ZwTerminateProcess(NtCurrentProcess(), STATUS_UNSUCCESSFUL); + } + + /* normalize process parameters */ + RtlNormalizeProcessParams (Peb->ProcessParameters); + +#if 0 + /* initialize NLS data */ + RtlInitNlsTables (Peb->AnsiCodePageData, + Peb->OemCodePageData, + Peb->UnicodeCaseTableData, + &TranslationTable); + RtlResetRtlTranslations (&TranslationTable); +#endif + + NTHeaders = (PIMAGE_NT_HEADERS)(ImageBase + PEDosHeader->e_lfanew); + + /* create process heap */ + RtlInitializeHeapManager(); + Peb->ProcessHeap = RtlCreateHeap(0, + (PVOID)HEAP_BASE, + NTHeaders->OptionalHeader.SizeOfHeapCommit, + NTHeaders->OptionalHeader.SizeOfHeapReserve, + NULL, + NULL); + if (Peb->ProcessHeap == 0) + { + DbgPrint("Failed to create process heap\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + + /* initalize peb lock support */ + RtlInitializeCriticalSection (&PebLock); + Peb->FastPebLock = &PebLock; + Peb->FastPebLockRoutine = (PPEBLOCKROUTINE)RtlEnterCriticalSection; + Peb->FastPebUnlockRoutine = (PPEBLOCKROUTINE)RtlLeaveCriticalSection; + + /* initialize tls bitmap */ + RtlInitializeBitMap (&TlsBitMap, + Peb->TlsBitmapBits, + TLS_MINIMUM_AVAILABLE); + Peb->TlsBitmap = &TlsBitMap; + Peb->TlsExpansionCounter = TLS_MINIMUM_AVAILABLE; + + /* Initialize table of callbacks for the kernel. */ + Peb->KernelCallbackTable = + RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(PVOID) * USER32_CALLBACK_MAXIMUM); + + /* initalize loader lock */ + RtlInitializeCriticalSection (&LoaderLock); + Peb->LoaderLock = &LoaderLock; + + /* create loader information */ + Peb->Ldr = (PPEB_LDR_DATA)RtlAllocateHeap (Peb->ProcessHeap, + 0, + sizeof(PEB_LDR_DATA)); + if (Peb->Ldr == NULL) + { + DbgPrint("Failed to create loader data\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + Peb->Ldr->Length = sizeof(PEB_LDR_DATA); + Peb->Ldr->Initialized = FALSE; + Peb->Ldr->SsHandle = NULL; + InitializeListHead(&Peb->Ldr->InLoadOrderModuleList); + InitializeListHead(&Peb->Ldr->InMemoryOrderModuleList); + InitializeListHead(&Peb->Ldr->InInitializationOrderModuleList); + + /* build full ntdll path */ + wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot); + wcscat (FullNtDllPath, L"\\system32\\ntdll.dll"); + + /* add entry for ntdll */ + NtModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap, + 0, + sizeof(LDR_MODULE)); + if (NtModule == NULL) + { + DbgPrint("Failed to create loader module entry (NTDLL)\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + memset(NtModule, 0, sizeof(LDR_MODULE)); + + NtModule->BaseAddress = (PVOID)&_image_base__; + NtModule->EntryPoint = 0; /* no entry point */ + RtlCreateUnicodeString (&NtModule->FullDllName, + FullNtDllPath); + RtlCreateUnicodeString (&NtModule->BaseDllName, + L"ntdll.dll"); + NtModule->Flags = 0; + NtModule->LoadCount = -1; /* don't unload */ + NtModule->TlsIndex = 0; + NtModule->SectionHandle = NULL; + NtModule->CheckSum = 0; + + NTHeaders = RtlImageNtHeader (NtModule->BaseAddress); + NtModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + NtModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; + + InsertTailList(&Peb->Ldr->InLoadOrderModuleList, + &NtModule->InLoadOrderModuleList); + InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, + &NtModule->InInitializationOrderModuleList); + +#ifdef DBG + + LdrpLoadUserModuleSymbols(NtModule); + +#endif /* DBG */ + + /* add entry for executable (becomes first list entry) */ + ExeModule = (PLDR_MODULE)RtlAllocateHeap (Peb->ProcessHeap, + 0, + sizeof(LDR_MODULE)); + if (ExeModule == NULL) + { + DbgPrint("Failed to create loader module infomation\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } + ExeModule->BaseAddress = Peb->ImageBaseAddress; + + if ((Peb->ProcessParameters != NULL) && + (Peb->ProcessParameters->ImagePathName.Length != 0)) + { + RtlCreateUnicodeString (&ExeModule->FullDllName, + Peb->ProcessParameters->ImagePathName.Buffer); + RtlCreateUnicodeString (&ExeModule->BaseDllName, + wcsrchr(ExeModule->FullDllName.Buffer, L'\\') + 1); + } + else + { + /* FIXME(???): smss.exe doesn't have a process parameter block */ + wcscpy (FullNtDllPath, SharedUserData->NtSystemRoot); + wcscat (FullNtDllPath, L"\\system32\\smss.exe"); + RtlCreateUnicodeString (&ExeModule->BaseDllName, + L"smss.exe"); + RtlCreateUnicodeString (&ExeModule->FullDllName, + FullNtDllPath); + } + + ExeModule->Flags = 0; + ExeModule->LoadCount = -1; /* don't unload */ + ExeModule->TlsIndex = 0; + ExeModule->SectionHandle = NULL; + ExeModule->CheckSum = 0; + + NTHeaders = RtlImageNtHeader (ExeModule->BaseAddress); + ExeModule->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + ExeModule->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; + + InsertHeadList(&Peb->Ldr->InLoadOrderModuleList, + &ExeModule->InLoadOrderModuleList); + +#ifdef DBG + + LdrpLoadUserModuleSymbols(ExeModule); + +#endif /* DBG */ + + EntryPoint = LdrPEStartup((PVOID)ImageBase, NULL, NULL, NULL); + ExeModule->EntryPoint = (ULONG)EntryPoint; + + /* all required dlls are loaded now */ + Peb->Ldr->Initialized = TRUE; + + /* Check before returning that we can run the image safely. */ + if (EntryPoint == NULL) + { + DbgPrint("Failed to initialize image\n"); + ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); + } +} + +/* EOF */ diff --git a/lib/ntdll/ldr/utils.c b/lib/ntdll/ldr/utils.c new file mode 100644 index 0000000..dc21967 --- /dev/null +++ b/lib/ntdll/ldr/utils.c @@ -0,0 +1,1912 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/ldr/startup.c + * PURPOSE: Process startup for PE executables + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + */ + +/* + * TODO: + * - Fix calling of entry points + * - Handle loading flags correctly + * - any more ?? + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef DBG_NTDLL_LDR_UTILS +#define NDEBUG +#endif +#include + +/* PROTOTYPES ****************************************************************/ + +static NTSTATUS LdrFindEntryForName(PUNICODE_STRING Name, PLDR_MODULE *Module); +static PVOID LdrFixupForward(PCHAR ForwardName); +static PVOID LdrGetExportByName(PVOID BaseAddress, PUCHAR SymbolName, USHORT Hint); + + +/* FUNCTIONS *****************************************************************/ + + +#ifdef DBG + +VOID +LdrpLoadUserModuleSymbols(PLDR_MODULE LdrModule) +{ + NtSystemDebugControl( + DebugDbgLoadSymbols, + (PVOID)LdrModule, + 0, + NULL, + 0, + NULL); +} + +#endif /* DBG */ + + +/*************************************************************************** + * NAME LOCAL + * LdrAdjustDllName + * + * DESCRIPTION + * Adjusts the name of a dll to a fully qualified name. + * + * ARGUMENTS + * FullDllName: Pointer to caller supplied storage for the fully + * qualified dll name. + * DllName: Pointer to the dll name. + * BaseName: TRUE: Only the file name is passed to FullDllName + * FALSE: The full path is preserved in FullDllName + * + * RETURN VALUE + * None + * + * REVISIONS + * + * NOTE + * A given path is not affected by the adjustment, but the file + * name only: + * ntdll --> ntdll.dll + * ntdll. --> ntdll + * ntdll.xyz --> ntdll.xyz + */ + +static VOID +LdrAdjustDllName (PUNICODE_STRING FullDllName, + PUNICODE_STRING DllName, + BOOLEAN BaseName) +{ + WCHAR Buffer[MAX_PATH]; + ULONG Length; + PWCHAR Extension; + PWCHAR Pointer; + + Length = DllName->Length / sizeof(WCHAR); + + if (BaseName == TRUE) + { + /* get the base dll name */ + Pointer = DllName->Buffer + Length; + Extension = Pointer; + + do + { + --Pointer; + } + while (Pointer >= DllName->Buffer && *Pointer != L'\\' && *Pointer != L'/'); + + Pointer++; + Length = Extension - Pointer; + memmove (Buffer, Pointer, Length * sizeof(WCHAR)); + Buffer[Length] = L'\0'; + } + else + { + /* get the full dll name */ + memmove (Buffer, DllName->Buffer, DllName->Length); + Buffer[DllName->Length / sizeof(WCHAR)] = L'\0'; + } + + /* Build the DLL's absolute name */ + Extension = wcsrchr (Buffer, L'.'); + if ((Extension != NULL) && (*Extension == L'.')) + { + /* with extension - remove dot if it's the last character */ + if (Buffer[Length - 1] == L'.') + Length--; + Buffer[Length] = 0; + } + else + { + /* name without extension - assume that it is .dll */ + memmove (Buffer + Length, L".dll", 10); + } + + RtlCreateUnicodeString (FullDllName, + Buffer); +} + +PLDR_MODULE +LdrAddModuleEntry(PVOID ImageBase, PIMAGE_NT_HEADERS NTHeaders, + PWSTR FullDosName) +{ + PLDR_MODULE Module; + Module = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof (LDR_MODULE)); + assert(Module); + Module->BaseAddress = (PVOID)ImageBase; + Module->EntryPoint = NTHeaders->OptionalHeader.AddressOfEntryPoint; + if (Module->EntryPoint != 0) + Module->EntryPoint += (ULONG)Module->BaseAddress; + Module->SizeOfImage = NTHeaders->OptionalHeader.SizeOfImage; + if (NtCurrentPeb()->Ldr->Initialized == TRUE) + { + /* loading while app is running */ + Module->LoadCount = 1; + } + else + { + /* + * loading while app is initializing + * dll must not be unloaded + */ + Module->LoadCount = -1; + } + + Module->TlsIndex = 0; + Module->CheckSum = NTHeaders->OptionalHeader.CheckSum; + Module->TimeDateStamp = NTHeaders->FileHeader.TimeDateStamp; + + RtlCreateUnicodeString (&Module->FullDllName, + FullDosName); + RtlCreateUnicodeString (&Module->BaseDllName, + wcsrchr(FullDosName, L'\\') + 1); + DPRINT ("BaseDllName %wZ\n", &Module->BaseDllName); + + /* FIXME: aquire loader lock */ + InsertTailList(&NtCurrentPeb()->Ldr->InLoadOrderModuleList, + &Module->InLoadOrderModuleList); + InsertTailList(&NtCurrentPeb()->Ldr->InInitializationOrderModuleList, + &Module->InInitializationOrderModuleList); + /* FIXME: release loader lock */ + + return(Module); +} + +/*************************************************************************** + * NAME EXPORTED + * LdrLoadDll + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ + +NTSTATUS STDCALL +LdrLoadDll (IN PWSTR SearchPath OPTIONAL, + IN ULONG LoadFlags, + IN PUNICODE_STRING Name, + OUT PVOID *BaseAddress OPTIONAL) +{ + WCHAR SearchPathBuffer[MAX_PATH]; + WCHAR FullDosName[MAX_PATH]; + UNICODE_STRING AdjustedName; + UNICODE_STRING FullNtFileName; + OBJECT_ATTRIBUTES FileObjectAttributes; + char BlockBuffer [1024]; + PIMAGE_DOS_HEADER DosHeader; + NTSTATUS Status; + PIMAGE_NT_HEADERS NTHeaders; + ULONG ImageSize; + ULONG InitialViewSize; + PVOID ImageBase; + HANDLE FileHandle; + HANDLE SectionHandle; + PDLLMAIN_FUNC Entrypoint = NULL; + PLDR_MODULE Module; + + if (Name == NULL) + { + *BaseAddress = NtCurrentPeb()->ImageBaseAddress; + return STATUS_SUCCESS; + } + + *BaseAddress = NULL; + + DPRINT("LdrLoadDll(Name \"%wZ\" BaseAddress %x)\n", + Name, BaseAddress); + + /* adjust the full dll name */ + LdrAdjustDllName (&AdjustedName, + Name, + FALSE); + DPRINT("AdjustedName: %wZ\n", &AdjustedName); + + /* + * Test if dll is already loaded. + */ + if (LdrFindEntryForName(&AdjustedName, &Module) == STATUS_SUCCESS) + { + DPRINT("DLL %wZ already loaded.\n", &AdjustedName); + if (Module->LoadCount != -1) + Module->LoadCount++; + *BaseAddress = Module->BaseAddress; + return STATUS_SUCCESS; + } + DPRINT("Loading \"%wZ\"\n", Name); + + if (SearchPath == NULL) + { + SearchPath = SearchPathBuffer; + wcscpy (SearchPathBuffer, SharedUserData->NtSystemRoot); + wcscat (SearchPathBuffer, L"\\system32;"); + wcscat (SearchPathBuffer, SharedUserData->NtSystemRoot); + wcscat (SearchPathBuffer, L";."); + } + + DPRINT("SearchPath %S\n", SearchPath); + + if (RtlDosSearchPath_U (SearchPath, + AdjustedName.Buffer, + NULL, + MAX_PATH, + FullDosName, + NULL) == 0) + return STATUS_DLL_NOT_FOUND; + + DPRINT("FullDosName %S\n", FullDosName); + + RtlFreeUnicodeString (&AdjustedName); + + if (!RtlDosPathNameToNtPathName_U (FullDosName, + &FullNtFileName, + NULL, + NULL)) + return STATUS_DLL_NOT_FOUND; + + DPRINT("FullNtFileName %wZ\n", &FullNtFileName); + + InitializeObjectAttributes(&FileObjectAttributes, + &FullNtFileName, + 0, + NULL, + NULL); + + DPRINT("Opening dll \"%wZ\"\n", &FullNtFileName); + + Status = ZwOpenFile(&FileHandle, + FILE_ALL_ACCESS, + &FileObjectAttributes, + NULL, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Dll open of %wZ failed: Status = 0x%08x\n", + &FullNtFileName, Status); + RtlFreeUnicodeString (&FullNtFileName); + return Status; + } + RtlFreeUnicodeString (&FullNtFileName); + + Status = ZwReadFile(FileHandle, + 0, + 0, + 0, + 0, + BlockBuffer, + sizeof(BlockBuffer), + 0, + 0); + if (!NT_SUCCESS(Status)) + { + DPRINT("Dll header read failed: Status = 0x%08x\n", Status); + ZwClose(FileHandle); + return Status; + } + /* + * Overlay DOS and NT headers structures to the + * buffer with DLL's header raw data. + */ + DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer; + NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew); + /* + * Check it is a PE image file. + */ + if ((DosHeader->e_magic != IMAGE_DOS_MAGIC) + || (DosHeader->e_lfanew == 0L) + || (*(PULONG)(NTHeaders) != IMAGE_PE_MAGIC)) + { + DPRINT("NTDLL format invalid\n"); + ZwClose(FileHandle); + + return STATUS_UNSUCCESSFUL; + } + + ImageBase = (PVOID) NTHeaders->OptionalHeader.ImageBase; + ImageSize = NTHeaders->OptionalHeader.SizeOfImage; + + DPRINT("ImageBase 0x%08x\n", ImageBase); + + /* + * Create a section for dll. + */ + Status = ZwCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_READWRITE, + SEC_COMMIT | SEC_IMAGE, + FileHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("NTDLL create section failed: Status = 0x%08x\n", Status); + ZwClose(FileHandle); + return Status; + } + + /* + * Map the dll into the process. + */ + InitialViewSize = 0; + ImageBase = 0; + Status = ZwMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &ImageBase, + 0, + InitialViewSize, + NULL, + &InitialViewSize, + 0, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NTDLL.LDR: map view of section failed (Status %x)\n", + Status); + ZwClose(FileHandle); + return(Status); + } + ZwClose(FileHandle); + + /* relocate dll and fixup import table */ + if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == + IMAGE_FILE_DLL) + { + Entrypoint = + (PDLLMAIN_FUNC) LdrPEStartup(ImageBase, SectionHandle, &Module, + FullDosName); + if (Entrypoint == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + } + +#ifdef DBG + + LdrpLoadUserModuleSymbols(Module); + +#endif /* DBG */ + + /* initialize dll */ + if ((NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == + IMAGE_FILE_DLL) + { + if (Module->EntryPoint != 0) + { + Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint; + + DPRINT("Calling entry point at 0x%08x\n", Entrypoint); + if (FALSE == Entrypoint(Module->BaseAddress, + DLL_PROCESS_ATTACH, + NULL)) + { + DPRINT("NTDLL.LDR: DLL \"%wZ\" failed to initialize\n", + &Module->BaseDllName); + /* FIXME: should clean up and fail */ + } + else + { + DPRINT("NTDLL.LDR: DLL \"%wZ\" initialized successfully\n", + &Module->BaseDllName); + } + } + else + { + DPRINT("NTDLL.LDR: Entrypoint is NULL for \"%wZ\"\n", + &Module->BaseDllName); + } + } + + *BaseAddress = Module->BaseAddress; + return STATUS_SUCCESS; +} + + +/*************************************************************************** + * NAME EXPORTED + * LdrFindEntryForAddress + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +NTSTATUS STDCALL +LdrFindEntryForAddress(PVOID Address, + PLDR_MODULE *Module) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE ModulePtr; + + DPRINT("NTDLL.LdrFindEntryForAddress(Address %p)\n", Address); + + if (NtCurrentPeb()->Ldr == NULL) + return(STATUS_NO_MORE_ENTRIES); + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + if (Entry == ModuleListHead) + return(STATUS_NO_MORE_ENTRIES); + + while (Entry != ModuleListHead) + { + ModulePtr = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + DPRINT("Scanning %wZ at %p\n", &ModulePtr->BaseDllName, ModulePtr->BaseAddress); + + if ((Address >= ModulePtr->BaseAddress) && + (Address <= (ModulePtr->BaseAddress + ModulePtr->SizeOfImage))) + { + *Module = ModulePtr; + return(STATUS_SUCCESS); + } + + Entry = Entry->Flink; + } + + DPRINT("Failed to find module entry.\n"); + + return(STATUS_NO_MORE_ENTRIES); +} + + +/*************************************************************************** + * NAME LOCAL + * LdrFindEntryForName + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static NTSTATUS +LdrFindEntryForName(PUNICODE_STRING Name, + PLDR_MODULE *Module) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE ModulePtr; + + DPRINT("NTDLL.LdrFindEntryForName(Name %wZ)\n", Name); + + if (NtCurrentPeb()->Ldr == NULL) + return(STATUS_NO_MORE_ENTRIES); + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + if (Entry == ModuleListHead) + return(STATUS_NO_MORE_ENTRIES); + + // NULL is the current process + if (Name == NULL) + { + *Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + return(STATUS_SUCCESS); + } + + while (Entry != ModuleListHead) + { + ModulePtr = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + DPRINT("Scanning %wZ %wZ\n", &ModulePtr->BaseDllName, Name); + + if (RtlCompareUnicodeString(&ModulePtr->BaseDllName, Name, TRUE) == 0) + { + *Module = ModulePtr; + return(STATUS_SUCCESS); + } + + Entry = Entry->Flink; + } + + DPRINT("Failed to find dll %wZ\n", Name); + + return(STATUS_NO_MORE_ENTRIES); +} + +/********************************************************************** + * NAME LOCAL + * LdrFixupForward + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static PVOID +LdrFixupForward(PCHAR ForwardName) +{ + CHAR NameBuffer[128]; + UNICODE_STRING DllName; + UNICODE_STRING FunctionName; + NTSTATUS Status; + PCHAR p; + PVOID BaseAddress; + + strcpy(NameBuffer, ForwardName); + p = strchr(NameBuffer, '.'); + if (p != NULL) + { + *p = 0; + + DPRINT("Dll: %s Function: %s\n", NameBuffer, p+1); + RtlCreateUnicodeStringFromAsciiz (&DllName, + NameBuffer); + + Status = LdrGetDllHandle (0, 0, &DllName, &BaseAddress); + if (!NT_SUCCESS(Status)) + { + Status = LdrLoadDll(NULL, + 0, + &DllName, + &BaseAddress); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LdrFixupForward: failed to load %wZ\n", &DllName); + RtlFreeUnicodeString (&DllName); + return NULL; + } + } + + RtlFreeUnicodeString (&DllName); + DPRINT("BaseAddress: %p\n", BaseAddress); + + return LdrGetExportByName(BaseAddress, p+1, -1); + } + + return NULL; +} + + +/********************************************************************** + * NAME LOCAL + * LdrGetExportByOrdinal + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static PVOID +LdrGetExportByOrdinal ( + PVOID BaseAddress, + ULONG Ordinal + ) +{ + PIMAGE_EXPORT_DIRECTORY ExportDir; + PDWORD * ExFunctions; + USHORT * ExOrdinals; + + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + NULL); + + + ExOrdinals = (USHORT *) + RVA( + BaseAddress, + ExportDir->AddressOfNameOrdinals + ); + ExFunctions = (PDWORD *) + RVA( + BaseAddress, + ExportDir->AddressOfFunctions + ); + DbgPrint( + "LdrGetExportByOrdinal(Ordinal %d) = %x\n", + Ordinal, + ExFunctions[ExOrdinals[Ordinal - ExportDir->Base]] + ); + return(ExFunctions[ExOrdinals[Ordinal - ExportDir->Base]]); +} + + +/********************************************************************** + * NAME LOCAL + * LdrGetExportByName + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static PVOID +LdrGetExportByName(PVOID BaseAddress, + PUCHAR SymbolName, + WORD Hint) +{ + PIMAGE_EXPORT_DIRECTORY ExportDir; + PDWORD * ExFunctions; + PDWORD * ExNames; + USHORT * ExOrdinals; + ULONG i; + PVOID ExName; + ULONG Ordinal; + PVOID Function; + ULONG minn, maxn; + ULONG ExportDirSize; + + DPRINT("LdrGetExportByName %x %s %hu\n", BaseAddress, SymbolName, Hint); + + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData(BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportDirSize); + if (ExportDir == NULL) + { + DbgPrint("LdrGetExportByName(): no export directory!\n"); + return NULL; + } + + /* + * Get header pointers + */ + ExNames = (PDWORD *)RVA(BaseAddress, + ExportDir->AddressOfNames); + ExOrdinals = (USHORT *)RVA(BaseAddress, + ExportDir->AddressOfNameOrdinals); + ExFunctions = (PDWORD *)RVA(BaseAddress, + ExportDir->AddressOfFunctions); + + /* + * Check the hint first + */ + if (Hint < ExportDir->NumberOfFunctions) + { + ExName = RVA(BaseAddress, ExNames[Hint]); + if (strcmp(ExName, SymbolName) == 0) + { + Ordinal = ExOrdinals[Hint]; + Function = RVA(BaseAddress, ExFunctions[Ordinal]); + if (((ULONG)Function >= (ULONG)ExportDir) && + ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize)) + { + DPRINT("Forward: %s\n", (PCHAR)Function); + Function = LdrFixupForward((PCHAR)Function); + } + if (Function != NULL) + return Function; + } + } + + /* + * Try a binary search first + */ + minn = 0; + maxn = ExportDir->NumberOfFunctions; + while (minn <= maxn) + { + ULONG mid; + LONG res; + + mid = (minn + maxn) / 2; + + ExName = RVA(BaseAddress, ExNames[mid]); + res = strcmp(ExName, SymbolName); + if (res == 0) + { + Ordinal = ExOrdinals[mid]; + Function = RVA(BaseAddress, ExFunctions[Ordinal]); + if (((ULONG)Function >= (ULONG)ExportDir) && + ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize)) + { + DPRINT("Forward: %s\n", (PCHAR)Function); + Function = LdrFixupForward((PCHAR)Function); + } + if (Function != NULL) + return Function; + } + else if (minn == maxn) + { + DPRINT("LdrGetExportByName(): binary search failed\n"); + break; + } + else if (res > 0) + { + maxn = mid - 1; + } + else + { + minn = mid + 1; + } + } + + /* + * Fall back on a linear search + */ + DPRINT("LdrGetExportByName(): Falling back on a linear search of export table\n"); + for (i = 0; i < ExportDir->NumberOfFunctions; i++) + { + ExName = RVA(BaseAddress, ExNames[i]); + if (strcmp(ExName,SymbolName) == 0) + { + Ordinal = ExOrdinals[i]; + Function = RVA(BaseAddress, ExFunctions[Ordinal]); + DPRINT("%x %x %x\n", Function, ExportDir, ExportDir + ExportDirSize); + if (((ULONG)Function >= (ULONG)ExportDir) && + ((ULONG)Function < (ULONG)ExportDir + (ULONG)ExportDirSize)) + { + DPRINT("Forward: %s\n", (PCHAR)Function); + Function = LdrFixupForward((PCHAR)Function); + } + return Function; + } + } + DbgPrint("LdrGetExportByName(): failed to find %s\n",SymbolName); + return NULL; +} + + +/********************************************************************** + * NAME LOCAL + * LdrPerformRelocations + * + * DESCRIPTION + * Relocate a DLL's memory image. + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static NTSTATUS LdrPerformRelocations (PIMAGE_NT_HEADERS NTHeaders, + PVOID ImageBase) +{ + USHORT NumberOfEntries; + PUSHORT pValue16; + ULONG RelocationRVA; + ULONG Delta32; + ULONG Offset; + PULONG pValue32; + PRELOCATION_DIRECTORY RelocationDir; + PRELOCATION_ENTRY RelocationBlock; + int i; + PIMAGE_DATA_DIRECTORY RelocationDDir; + ULONG OldProtect; + NTSTATUS Status; + PIMAGE_SECTION_HEADER Sections; + ULONG MaxExtend; + ULONG LastOffset; + + Sections = + (PIMAGE_SECTION_HEADER)((PVOID)NTHeaders + sizeof(IMAGE_NT_HEADERS)); + MaxExtend = 0; + for (i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++) + { + if (!(Sections[i].Characteristics & IMAGE_SECTION_NOLOAD)) + { + ULONG Extend; + Extend = + (ULONG)(Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize); + MaxExtend = max(MaxExtend, Extend); + } + } + + RelocationDDir = + &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + RelocationRVA = RelocationDDir->VirtualAddress; + + if (RelocationRVA) + { + RelocationDir = + (PRELOCATION_DIRECTORY)((PCHAR)ImageBase + RelocationRVA); + + while (RelocationDir->SizeOfBlock) + { + if (RelocationDir->VirtualAddress > MaxExtend) + { + RelocationRVA += RelocationDir->SizeOfBlock; + RelocationDir = + (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA); + continue; + } + + Delta32 = (ULONG)(ImageBase - NTHeaders->OptionalHeader.ImageBase); + RelocationBlock = + (PRELOCATION_ENTRY) (RelocationRVA + ImageBase + + sizeof (RELOCATION_DIRECTORY)); + NumberOfEntries = + RelocationDir->SizeOfBlock - sizeof (RELOCATION_DIRECTORY); + NumberOfEntries = NumberOfEntries / sizeof (RELOCATION_ENTRY); + + Status = NtProtectVirtualMemory(NtCurrentProcess(), + ImageBase + + RelocationDir->VirtualAddress, + PAGE_SIZE, + PAGE_READWRITE, + &OldProtect); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to unprotect relocation target.\n"); + return(Status); + } + + for (i = 0; i < NumberOfEntries; i++) + { + Offset = (RelocationBlock[i].TypeOffset & 0xfff); + Offset += (ULONG)(RelocationDir->VirtualAddress + ImageBase); + + /* + * What kind of relocations should we perform + * for the current entry? + */ + switch (RelocationBlock[i].TypeOffset >> 12) + { + case TYPE_RELOC_ABSOLUTE: + break; + + case TYPE_RELOC_HIGH: + pValue16 = (PUSHORT)Offset; + *pValue16 += Delta32 >> 16; + break; + + case TYPE_RELOC_LOW: + pValue16 = (PUSHORT)Offset; + *pValue16 += Delta32 & 0xffff; + break; + + case TYPE_RELOC_HIGHLOW: + pValue32 = (PULONG)Offset; + *pValue32 += Delta32; + break; + + case TYPE_RELOC_HIGHADJ: + /* FIXME: do the highadjust fixup */ + DPRINT("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n"); + return(STATUS_UNSUCCESSFUL); + + default: + DPRINT("unexpected fixup type\n"); + return STATUS_UNSUCCESSFUL; + } + } + + Status = NtProtectVirtualMemory(NtCurrentProcess(), + ImageBase + + RelocationDir->VirtualAddress, + PAGE_SIZE, + OldProtect, + &OldProtect); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to protect relocation target.\n"); + return(Status); + } + + RelocationRVA += RelocationDir->SizeOfBlock; + RelocationDir = + (PRELOCATION_DIRECTORY) (ImageBase + RelocationRVA); + } + } + return STATUS_SUCCESS; +} + + +/********************************************************************** + * NAME LOCAL + * LdrFixupImports + * + * DESCRIPTION + * Compute the entry point for every symbol the DLL imports + * from other modules. + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + * + */ +static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders, + PVOID ImageBase) +{ + PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory; + ULONG Ordinal; + PVOID BaseAddress; + NTSTATUS Status; + ULONG IATSize; + + DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders, + ImageBase); + + /* + * Process each import module. + */ + ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)( + ImageBase + NTHeaders->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); + DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory); + + while (ImportModuleDirectory->dwRVAModuleName) + { + PVOID * ImportAddressList; + PULONG FunctionNameList; + UNICODE_STRING DllName; + DWORD pName; + WORD pHint; + PVOID IATBase; + ULONG OldProtect; + + DPRINT("ImportModule->Directory->dwRVAModuleName %s\n", + (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName)); + + RtlCreateUnicodeStringFromAsciiz (&DllName, + (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName)); + + Status = LdrGetDllHandle (0, 0, &DllName, &BaseAddress); + if (!NT_SUCCESS(Status)) + { + Status = LdrLoadDll(NULL, + 0, + &DllName, + &BaseAddress); + RtlFreeUnicodeString (&DllName); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LdrFixupImports:failed to load %s\n" + ,(PCHAR)(ImageBase + + ImportModuleDirectory->dwRVAModuleName)); + + return Status; + } + } + + /* + * Get the import address list. + */ + ImportAddressList = (PVOID *)(NTHeaders->OptionalHeader.ImageBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + + /* + * Get the list of functions to import. + */ + if (ImportModuleDirectory->dwRVAFunctionNameList != 0) + { + FunctionNameList = (PULONG) ( + ImageBase + + ImportModuleDirectory->dwRVAFunctionNameList + ); + } + else + { + FunctionNameList = + (PULONG)(ImageBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + } + + /* + * Get the size of IAT. + */ + IATSize = 0; + while (FunctionNameList[IATSize] != 0L) + { + IATSize++; + } + + /* + * Unprotect the region we are about to write into. + */ + IATBase = (PVOID)ImportAddressList; + Status = NtProtectVirtualMemory(NtCurrentProcess(), + IATBase, + IATSize * sizeof(PVOID*), + PAGE_READWRITE, + &OldProtect); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LDR: Failed to unprotect IAT.\n"); + return(Status); + } + + /* + * Walk through function list and fixup addresses. + */ + while (*FunctionNameList != 0L) + { + if ((*FunctionNameList) & 0x80000000) + { + Ordinal = (*FunctionNameList) & 0x7fffffff; + *ImportAddressList = + LdrGetExportByOrdinal(BaseAddress, + Ordinal); + } + else + { + pName = (DWORD) (ImageBase + *FunctionNameList + 2); + pHint = *(PWORD)(ImageBase + *FunctionNameList); + + *ImportAddressList = + LdrGetExportByName(BaseAddress, (PUCHAR)pName, pHint); + if ((*ImportAddressList) == NULL) + { + DbgPrint("Failed to import %s\n", pName); + return STATUS_UNSUCCESSFUL; + } + } + ImportAddressList++; + FunctionNameList++; + } + + /* + * Protect the region we are about to write into. + */ + Status = NtProtectVirtualMemory(NtCurrentProcess(), + IATBase, + IATSize * sizeof(PVOID*), + OldProtect, + &OldProtect); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LDR: Failed to protect IAT.\n"); + return(Status); + } + + ImportModuleDirectory++; + } + return STATUS_SUCCESS; +} + + +/********************************************************************** + * NAME + * LdrPEStartup + * + * DESCRIPTION + * 1. Map the DLL's sections into memory. + * 2. Relocate, if needed the DLL. + * 3. Fixup any imported symbol. + * 4. Compute the DLL's entry point. + * + * ARGUMENTS + * ImageBase + * Address at which the DLL's image + * is loaded. + * + * SectionHandle + * Handle of the section that contains + * the DLL's image. + * + * RETURN VALUE + * NULL on error; otherwise the entry point + * to call for initializing the DLL. + * + * REVISIONS + * + * NOTE + * + */ +PEPFUNC LdrPEStartup (PVOID ImageBase, + HANDLE SectionHandle, + PLDR_MODULE* Module, + PWSTR FullDosName) +{ + NTSTATUS Status; + PEPFUNC EntryPoint = NULL; + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NTHeaders; + + DPRINT("LdrPEStartup(ImageBase %x SectionHandle %x)\n", + ImageBase, (ULONG)SectionHandle); + + /* + * Overlay DOS and WNT headers structures + * to the DLL's image. + */ + DosHeader = (PIMAGE_DOS_HEADER) ImageBase; + NTHeaders = (PIMAGE_NT_HEADERS) (ImageBase + DosHeader->e_lfanew); + + /* + * If the base address is different from the + * one the DLL is actually loaded, perform any + * relocation. + */ + if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase) + { + DbgPrint("LDR: Performing relocations\n"); + Status = LdrPerformRelocations(NTHeaders, ImageBase); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LdrPerformRelocations() failed\n"); + return NULL; + } + } + + if (Module != NULL) + { + *Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName); + } + + /* + * If the DLL's imports symbols from other + * modules, fixup the imported calls entry points. + */ + if (NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress != 0) + { + DPRINT("About to fixup imports\n"); + Status = LdrFixupImports(NTHeaders, ImageBase); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LdrFixupImports() failed\n"); + return NULL; + } + DPRINT("Fixup done\n"); + } + + /* + * Compute the DLL's entry point's address. + */ + DPRINT("ImageBase = %x\n",(ULONG)ImageBase); + DPRINT("AddressOfEntryPoint = %x\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint); + if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0) + { + EntryPoint = (PEPFUNC) (ImageBase + + NTHeaders->OptionalHeader.AddressOfEntryPoint); + } + DPRINT("LdrPEStartup() = %x\n",EntryPoint); + return EntryPoint; +} + + +NTSTATUS STDCALL +LdrUnloadDll (IN PVOID BaseAddress) +{ + PIMAGE_NT_HEADERS NtHeaders; + PDLLMAIN_FUNC Entrypoint; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + NTSTATUS Status; + + if (BaseAddress == NULL) + return STATUS_SUCCESS; + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + if (Module->BaseAddress == BaseAddress) + { + if (Module->LoadCount == -1) + { + /* never unload this dll */ + return STATUS_SUCCESS; + } + else if (Module->LoadCount > 1) + { + Module->LoadCount--; + return STATUS_SUCCESS; + } + + NtHeaders = RtlImageNtHeader (Module->BaseAddress); + if ((NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL) + { + if (Module->EntryPoint != 0) + { + Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint; + DPRINT("Calling entry point at 0x%08x\n", Entrypoint); + Entrypoint(Module->BaseAddress, + DLL_PROCESS_DETACH, + NULL); + } + else + { + DPRINT("NTDLL.LDR: Entrypoint is NULL for \n"); + } + } + Status = ZwUnmapViewOfSection (NtCurrentProcess (), + Module->BaseAddress); + ZwClose (Module->SectionHandle); + + /* remove the module entry from the list */ + RtlFreeUnicodeString (&Module->FullDllName); + RtlFreeUnicodeString (&Module->BaseDllName); + RemoveEntryList (Entry); + RtlFreeHeap (RtlGetProcessHeap (), 0, Module); + + return Status; + } + + Entry = Entry->Flink; + } + + DPRINT("NTDLL.LDR: Dll not found\n") + + return STATUS_UNSUCCESSFUL; +} + + +NTSTATUS STDCALL +LdrFindResource_U(PVOID BaseAddress, + PLDR_RESOURCE_INFO ResourceInfo, + ULONG Level, + PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry) +{ + PIMAGE_RESOURCE_DIRECTORY ResDir; + PIMAGE_RESOURCE_DIRECTORY ResBase; + PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry; + NTSTATUS Status = STATUS_SUCCESS; + ULONG EntryCount; + PWCHAR ws; + ULONG i; + ULONG Id; + + DPRINT ("LdrFindResource_U()\n"); + + /* Get the pointer to the resource directory */ + ResDir = (PIMAGE_RESOURCE_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_RESOURCE, + &i); + if (ResDir == NULL) + { + return STATUS_RESOURCE_DATA_NOT_FOUND; + } + + DPRINT("ResourceDirectory: %x\n", (ULONG)ResDir); + + ResBase = ResDir; + + /* Let's go into resource tree */ + for (i = 0; i < Level; i++) + { + DPRINT("ResDir: %x\n", (ULONG)ResDir); + Id = ((PULONG)ResourceInfo)[i]; + EntryCount = ResDir->NumberOfNamedEntries; + ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1); + DPRINT("ResEntry %x\n", (ULONG)ResEntry); + if (Id & 0xFFFF0000) + { + /* Resource name is a unicode string */ + for (; EntryCount--; ResEntry++) + { + /* Scan entries for equal name */ + if (ResEntry->Name & 0x80000000) + { + ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF)); + if (!wcsncmp((PWCHAR)Id, ws + 1, *ws ) && + wcslen((PWCHAR)Id) == (int)*ws ) + { + goto found; + } + } + } + } + else + { + /* We use ID number instead of string */ + ResEntry += EntryCount; + EntryCount = ResDir->NumberOfIdEntries; + for (; EntryCount--; ResEntry++) + { + /* Scan entries for equal name */ + if (ResEntry->Name == Id) + { + DPRINT("ID entry found %x\n", Id); + goto found; + } + } + } + DPRINT("Error %lu\n", i); + + switch (i) + { + case 0: + return STATUS_RESOURCE_TYPE_NOT_FOUND; + + case 1: + return STATUS_RESOURCE_NAME_NOT_FOUND; + + case 2: + if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) + { + /* Use the first available language */ + ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1); + break; + } + return STATUS_RESOURCE_LANG_NOT_FOUND; + + case 3: + return STATUS_RESOURCE_DATA_NOT_FOUND; + + default: + return STATUS_INVALID_PARAMETER; + } +found:; + ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase + + (ResEntry->OffsetToData & 0x7FFFFFFF)); + } + DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir); + + if (ResourceDataEntry) + { + *ResourceDataEntry = (PVOID)ResDir; + } + + return Status; +} + + +NTSTATUS STDCALL +LdrAccessResource(IN PVOID BaseAddress, + IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry, + OUT PVOID *Resource OPTIONAL, + OUT PULONG Size OPTIONAL) +{ + PIMAGE_SECTION_HEADER Section; + PIMAGE_NT_HEADERS NtHeader; + ULONG SectionRva; + ULONG SectionVa; + ULONG DataSize; + ULONG Offset = 0; + ULONG Data; + + Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_RESOURCE, + &DataSize); + if (Data == 0) + return STATUS_RESOURCE_DATA_NOT_FOUND; + + if ((ULONG)BaseAddress & 1) + { + /* loaded as ordinary file */ + NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL)); + Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + Section = RtlImageRvaToSection (NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); + if (Section == NULL) + { + return STATUS_RESOURCE_DATA_NOT_FOUND; + } + + if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) + { + SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress; + SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL); + Offset = SectionRva - SectionVa + Data - Section->VirtualAddress; + } + } + + if (Resource) + { + *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress); + } + + if (Size) + { + *Size = ResourceDataEntry->Size; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +LdrDisableThreadCalloutsForDll (IN PVOID BaseAddress) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + NTSTATUS Status; + + DPRINT("LdrDisableThreadCalloutsForDll (BaseAddress %x)\n", + BaseAddress); + + Status = STATUS_DLL_NOT_FOUND; + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + DPRINT("BaseDllName %wZ BaseAddress %x\n", + &Module->BaseDllName, + Module->BaseAddress); + + if (Module->BaseAddress == BaseAddress) + { + if (Module->TlsIndex == 0) + { + Module->Flags |= 0x00040000; + Status = STATUS_SUCCESS; + } + return Status; + } + + Entry = Entry->Flink; + } + + return Status; +} + + +NTSTATUS STDCALL +LdrFindResourceDirectory_U (IN PVOID BaseAddress, + WCHAR **name, + DWORD level, + OUT PVOID *addr) +{ + PIMAGE_RESOURCE_DIRECTORY ResDir; + PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry; + ULONG EntryCount; + ULONG i; + NTSTATUS Status = STATUS_SUCCESS; + WCHAR *ws; + + /* Get the pointer to the resource directory */ + ResDir = (PIMAGE_RESOURCE_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_RESOURCE, + &i); + if (ResDir == NULL) + { + return STATUS_RESOURCE_DATA_NOT_FOUND; + } + + /* Let's go into resource tree */ + for (i = 0; i < level; i++, name++) + { + EntryCount = ResDir->NumberOfNamedEntries; + ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1); + if ((ULONG)(*name) & 0xFFFF0000) + { + /* Resource name is a unicode string */ + for (; EntryCount--; ResEntry++) + { + /* Scan entries for equal name */ + if (ResEntry->Name & 0x80000000) + { + ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF)); + if (!wcsncmp( *name, ws + 1, *ws ) && wcslen( *name ) == (int)*ws ) + { + goto found; + } + } + } + } + else + { + /* We use ID number instead of string */ + ResEntry += EntryCount; + EntryCount = ResDir->NumberOfIdEntries; + for (; EntryCount--; ResEntry++) + { + /* Scan entries for equal name */ + if (ResEntry->Name == (ULONG)(*name)) + goto found; + } + } + + switch (i) + { + case 0: + return STATUS_RESOURCE_TYPE_NOT_FOUND; + + case 1: + return STATUS_RESOURCE_NAME_NOT_FOUND; + + case 2: + Status = STATUS_RESOURCE_LANG_NOT_FOUND; + /* Just use first language entry */ + if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) + { + ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1); + break; + } + return Status; + + case 3: + return STATUS_RESOURCE_DATA_NOT_FOUND; + + default: + return STATUS_INVALID_PARAMETER; + } +found:; + ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData); + } + + if (addr) + { + *addr = (PVOID)ResDir; + } + + return Status; +} + + +NTSTATUS STDCALL +LdrGetDllHandle (IN ULONG Unknown1, + IN ULONG Unknown2, + IN PUNICODE_STRING DllName, + OUT PVOID *BaseAddress) +{ + UNICODE_STRING FullDllName; + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + + DPRINT("LdrGetDllHandle (Unknown1 %x Unknown2 %x DllName %wZ BaseAddress %p)\n", + Unknown1, Unknown2, DllName, BaseAddress); + + /* NULL is the current executable */ + if ( DllName == NULL ) + { + *BaseAddress = NtCurrentPeb()->ImageBaseAddress; + DPRINT("BaseAddress %x\n", *BaseAddress); + return STATUS_SUCCESS; + } + + LdrAdjustDllName (&FullDllName, + DllName, + TRUE); + + DPRINT("FullDllName %wZ\n", + &FullDllName); + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + DPRINT("EntryPoint %x\n", Module->EntryPoint); + DPRINT("Comparing %wZ and %wZ\n", + &Module->BaseDllName, + &FullDllName); + + if (!RtlCompareUnicodeString(&Module->BaseDllName, &FullDllName, TRUE)) + { + RtlFreeUnicodeString (&FullDllName); + *BaseAddress = Module->BaseAddress; + DPRINT("BaseAddress %x\n", *BaseAddress); + return STATUS_SUCCESS; + } + + Entry = Entry->Flink; + } + + DPRINT("Failed to find dll %wZ\n", &FullDllName); + RtlFreeUnicodeString (&FullDllName); + *BaseAddress = NULL; + return STATUS_DLL_NOT_FOUND; +} + + +NTSTATUS STDCALL +LdrGetProcedureAddress (IN PVOID BaseAddress, + IN PANSI_STRING Name, + IN ULONG Ordinal, + OUT PVOID *ProcedureAddress) +{ + PIMAGE_EXPORT_DIRECTORY ExportDir; + PUSHORT OrdinalPtr; + PULONG NamePtr; + PULONG AddressPtr; + ULONG i = 0; + + DPRINT("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n", + BaseAddress, Name, Ordinal, ProcedureAddress); + + /* Get the pointer to the export directory */ + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &i); + + DPRINT("ExportDir %x i %lu\n", ExportDir, i); + + if (!ExportDir || !i || !ProcedureAddress) + { + return STATUS_INVALID_PARAMETER; + } + + AddressPtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfFunctions); + if (Name && Name->Length) + { + /* by name */ + OrdinalPtr = (PUSHORT)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNameOrdinals); + NamePtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNames); + for( i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++) + { + if (!_strnicmp(Name->Buffer, (char*)(BaseAddress + *NamePtr), Name->Length)) + { + *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[*OrdinalPtr]); + return STATUS_SUCCESS; + } + } + DbgPrint("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name); + } + else + { + /* by ordinal */ + Ordinal &= 0x0000FFFF; + if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) + { + *ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[Ordinal - ExportDir->Base]); + return STATUS_SUCCESS; + } + DbgPrint("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal); + } + + return STATUS_PROCEDURE_NOT_FOUND; +} + + +NTSTATUS STDCALL +LdrShutdownProcess (VOID) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + + DPRINT("LdrShutdownProcess() called\n"); + + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + + ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList; + Entry = ModuleListHead->Blink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList); + + DPRINT(" Unloading %S\n", + &Module->BaseDllName); + // PJS: only detach from static dlls, they should FreeLibrary() any dlls that + // they loaded dynamically, and when the last reference is gone, that lib will + // be detached. + if (Module->EntryPoint != 0 && Module->LoadCount == -1) + { + PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint; + + DPRINT("Calling entry point at 0x%08x\n", Entrypoint); + Entrypoint (Module->BaseAddress, + DLL_PROCESS_DETACH, + NULL); + } + + Entry = Entry->Blink; + } + + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); + + DPRINT("LdrShutdownProcess() done\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +LdrShutdownThread (VOID) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + + DPRINT("LdrShutdownThread() called\n"); + + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + + ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList; + Entry = ModuleListHead->Blink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList); + + DPRINT(" Unloading %wZ\n", + &Module->BaseDllName); + + if (Module->EntryPoint != 0) + { + PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint; + + DPRINT("Calling entry point at 0x%08x\n", Entrypoint); + Entrypoint (Module->BaseAddress, + DLL_THREAD_DETACH, + NULL); + } + + Entry = Entry->Blink; + } + + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); + + DPRINT("LdrShutdownThread() done\n"); + + return STATUS_SUCCESS; +} + + +/*************************************************************************** + * NAME EXPORTED + * LdrQueryProcessModuleInformation + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + * NOTE + */ +NTSTATUS STDCALL +LdrQueryProcessModuleInformation(IN PMODULE_INFORMATION ModuleInformation OPTIONAL, + IN ULONG Size OPTIONAL, + OUT PULONG ReturnedSize) + +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_MODULE Module; + PMODULE_ENTRY ModulePtr = NULL; + NTSTATUS Status = STATUS_SUCCESS; + ULONG UsedSize = sizeof(ULONG); + ANSI_STRING AnsiString; + PCHAR p; + + DPRINT("LdrQueryProcessModuleInformation() called\n"); + + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + + if (ModuleInformation == NULL || Size == 0) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else + { + ModuleInformation->ModuleCount = 0; + ModulePtr = &ModuleInformation->ModuleEntry[0]; + Status = STATUS_SUCCESS; + } + + ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; + Entry = ModuleListHead->Flink; + + while (Entry != ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, LDR_MODULE, InLoadOrderModuleList); + + DPRINT(" Module %wZ\n", + &Module->FullDllName); + + if (UsedSize > Size) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + } + else if (ModuleInformation != NULL) + { + ModulePtr->Unknown0 = 0; // FIXME: ?? + ModulePtr->Unknown1 = 0; // FIXME: ?? + ModulePtr->BaseAddress = Module->BaseAddress; + ModulePtr->SizeOfImage = Module->SizeOfImage; + ModulePtr->Flags = Module->Flags; + ModulePtr->Unknown2 = 0; // FIXME: load order index ?? + ModulePtr->Unknown3 = 0; // FIXME: ?? + ModulePtr->LoadCount = Module->LoadCount; + + AnsiString.Length = 0; + AnsiString.MaximumLength = 256; + AnsiString.Buffer = ModulePtr->ModuleName; + RtlUnicodeStringToAnsiString(&AnsiString, + &Module->FullDllName, + FALSE); + p = strrchr(ModulePtr->ModuleName, '\\'); + if (p != NULL) + ModulePtr->PathLength = p - ModulePtr->ModuleName + 1; + else + ModulePtr->PathLength = 0; + + ModulePtr++; + ModuleInformation->ModuleCount++; + } + UsedSize += sizeof(MODULE_ENTRY); + + Entry = Entry->Flink; + } + + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); + + if (ReturnedSize != 0) + *ReturnedSize = UsedSize; + + DPRINT("LdrQueryProcessModuleInformation() done\n"); + + return(Status); +} + +/* EOF */ diff --git a/lib/ntdll/main/.cvsignore b/lib/ntdll/main/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/main/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/main/dllmain.c b/lib/ntdll/main/dllmain.c new file mode 100644 index 0000000..143a019 --- /dev/null +++ b/lib/ntdll/main/dllmain.c @@ -0,0 +1,23 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/main/dllmain.c + * PURPOSE: + * PROGRAMMER: + */ + +#include +#include +#include +#include +#include + +BOOL WINAPI DllMainCRTStartup(HINSTANCE hinstDll, + DWORD fdwReason, + LPVOID fImpLoad) +{ + return TRUE; +} + +/* EOF */ diff --git a/lib/ntdll/makefile b/lib/ntdll/makefile new file mode 100644 index 0000000..84279cb --- /dev/null +++ b/lib/ntdll/makefile @@ -0,0 +1,82 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = ntdll + +TARGET_CFLAGS = -g -D__NTDLL__ + +TARGET_LFLAGS = -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -nostartfiles + +TARGET_GCCLIBS = gcc + +TARGET_BASE = 0x77f60000 + +TARGET_PATH = def + +TARGET_ENTRY = _LdrInitializeThunk@16 + +CSR_OBJECTS = csr/lpc.o csr/capture.o csr/probe.o csr/thread.o + +DBG_OBJECTS = dbg/brkpoint.o dbg/debug.o dbg/print.o dbg/winedbg.o + +RTL_I386_OBJECTS = \ + rtl/i386/exception.o \ + rtl/i386/except.o + +RTL_OBJECTS = rtl/critical.o rtl/error.o rtl/heap.o rtl/largeint.o \ + rtl/math.o rtl/mem.o rtl/nls.o rtl/process.o rtl/sd.o \ + rtl/thread.o rtl/unicode.o rtl/env.o rtl/path.o rtl/ppb.o \ + rtl/bitmap.o rtl/time.o rtl/acl.o rtl/sid.o rtl/image.o \ + rtl/access.o rtl/apc.o rtl/callback.o rtl/luid.o rtl/misc.o \ + rtl/registry.o rtl/exception.o rtl/intrlck.o rtl/resource.o \ + rtl/handle.o rtl/atom.o rtl/message.o rtl/timezone.o \ + rtl/propvar.o rtl/security.o rtl/dos8dot3.o rtl/compress.o + +STDIO_OBJECTS = stdio/sprintf.o stdio/swprintf.o + +STDLIB_OBJECTS = stdlib/abs.o stdlib/atoi.o stdlib/atoi64.o stdlib/atol.o \ + stdlib/itoa.o stdlib/itow.o stdlib/labs.o stdlib/splitp.o \ + stdlib/strtol.o stdlib/strtoul.o stdlib/wcstol.o \ + stdlib/wcstoul.o stdlib/wtoi.o stdlib/wtoi64.o stdlib/wtol.o \ + stdlib/mbstowcs.o stdlib/wcstombs.o stdlib/qsort.o + +STRING_OBJECTS = string/ctype.o string/memccpy.o string/memchr.o \ + string/memcmp.o string/memcpy.o string/memicmp.o\ + string/memmove.o string/memset.o string/strcat.o \ + string/strchr.o string/strcmp.o string/strcspn.o \ + string/strcpy.o string/stricmp.o string/strlen.o \ + string/strlwr.o string/strncat.o string/strncmp.o \ + string/strncpy.o string/strnicmp.o string/strnlen.o \ + string/strpbrk.o string/strrchr.o string/strspn.o \ + string/strstr.o string/strupr.o string/wstring.o + +ARCH_OBJECTS = \ + $(RTL_I386_OBJECTS) + +TARGET_OBJECTS = \ + napi.o \ + ldr/startup.o \ + $(ARCH_OBJECTS) \ + $(DBG_OBJECTS) \ + $(RTL_OBJECTS) \ + $(STDIO_OBJECTS) \ + $(STDLIB_OBJECTS) \ + $(STRING_OBJECTS) \ + stubs/stubs.o \ + ldr/utils.o \ + $(CSR_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +%/TAGS: + etags -o $(@D)/TAGS $(@D)/\*.c + +etags: csr/TAGS dbg/TAGS ldr/TAGS main/TAGS rtl/TAGS stdio/TAGS stdlib/TAGS string/TAGS stubs/TAGS + etags -i csr/TAGS -i dbg/TAGS -i ldr/TAGS -i main/TAGS -i rtl/TAGS -i stdio/TAGS -i stdlib/TAGS -i string/TAGS -i stubs/TAGS diff --git a/lib/ntdll/rtl/.cvsignore b/lib/ntdll/rtl/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/rtl/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/rtl/access.c b/lib/ntdll/rtl/access.c new file mode 100644 index 0000000..90ce919 --- /dev/null +++ b/lib/ntdll/rtl/access.c @@ -0,0 +1,64 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Access rights handling functions + * FILE: lib/ntdll/rtl/access.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 06/04/2000: Created + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN +STDCALL +RtlAreAllAccessesGranted ( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ) +{ + return ((GrantedAccess & DesiredAccess) == DesiredAccess); +} + + +BOOLEAN +STDCALL +RtlAreAnyAccessesGranted ( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ) +{ + return ((GrantedAccess & DesiredAccess) != 0); +} + + +VOID +STDCALL +RtlMapGenericMask ( + PACCESS_MASK AccessMask, + PGENERIC_MAPPING GenericMapping + ) +{ + if (*AccessMask & GENERIC_READ) + *AccessMask |= GenericMapping->GenericRead; + + if (*AccessMask & GENERIC_WRITE) + *AccessMask |= GenericMapping->GenericWrite; + + if (*AccessMask & GENERIC_EXECUTE) + *AccessMask |= GenericMapping->GenericExecute; + + if (*AccessMask & GENERIC_ALL) + *AccessMask |= GenericMapping->GenericAll; + + *AccessMask &= 0x0FFFFFFF; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/acl.c b/lib/ntdll/rtl/acl.c new file mode 100644 index 0000000..96223e3 --- /dev/null +++ b/lib/ntdll/rtl/acl.c @@ -0,0 +1,552 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: kernel/se/acl.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN STDCALL +RtlFirstFreeAce(PACL Acl, + PACE* Ace) +{ + PACE Current; + PVOID AclEnd; + ULONG i; + + Current = (PACE)(Acl + 1); + *Ace = NULL; + i = 0; + if (Acl->AceCount == 0) + { + *Ace = Current; + return(TRUE); + } + AclEnd = Acl->AclSize + (PVOID)Acl; + do + { + if ((PVOID)Current >= AclEnd) + { + return(FALSE); + } + if (Current->Header.AceType == 4) + { + if (Acl->AclRevision < 3) + { + return(FALSE); + } + } + Current = (PACE)((PVOID)Current + (ULONG)Current->Header.AceSize); + i++; + } + while (i < Acl->AceCount); + + if ((PVOID)Current < AclEnd) + { + *Ace = Current; + } + + return(TRUE); +} + + +NTSTATUS STDCALL +RtlGetAce(PACL Acl, + ULONG AceIndex, + PACE *Ace) +{ + ULONG i; + + *Ace = (PACE)(Acl + 1); + + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(STATUS_INVALID_PARAMETER); + } + + if (AceIndex >= Acl->AceCount) + { + return(STATUS_INVALID_PARAMETER); + } + + for (i = 0; i < AceIndex; i++) + { + if ((PVOID)*Ace >= (PVOID)Acl + Acl->AclSize) + { + return(STATUS_INVALID_PARAMETER); + } + *Ace = (PACE)((PVOID)(*Ace) + (ULONG)(*Ace)->Header.AceSize); + } + + if ((PVOID)*Ace >= (PVOID)Acl + Acl->AclSize) + { + return(STATUS_INVALID_PARAMETER); + } + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +RtlpAddKnownAce(PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid, + ULONG Type) +{ + PACE Ace; + + if (!RtlValidSid(Sid)) + { + return(STATUS_INVALID_SID); + } + if (Acl->AclRevision > 3 || + Revision > 3) + { + return(STATUS_UNKNOWN_REVISION); + } + if (Revision < Acl->AclRevision) + { + Revision = Acl->AclRevision; + } + if (!RtlFirstFreeAce(Acl, &Ace)) + { + return(STATUS_INVALID_ACL); + } + if (Ace == NULL) + { + return(STATUS_ALLOTTED_SPACE_EXCEEDED); + } + if (((PVOID)Ace + RtlLengthSid(Sid) + sizeof(ACE)) >= + ((PVOID)Acl + Acl->AclSize)) + { + return(STATUS_ALLOTTED_SPACE_EXCEEDED); + } + Ace->Header.AceFlags = 0; + Ace->Header.AceType = Type; + Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE); + Ace->AccessMask = AccessMask; + RtlCopySid(RtlLengthSid(Sid), (PSID)(Ace + 1), Sid); + Acl->AceCount++; + Acl->AclRevision = Revision; + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlAddAccessAllowedAce(PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid) +{ + return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 0)); +} + + +NTSTATUS STDCALL +RtlAddAccessDeniedAce(PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid) +{ + return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 1)); +} + + +static VOID +RtlpAddData(PVOID AceList, + ULONG AceListLength, + PVOID Ace, + ULONG Offset) +{ + if (Offset > 0) + { + memcpy((PUCHAR)Ace + AceListLength, + Ace, + Offset); + } + + if (AceListLength != 0) + { + memcpy(Ace, + AceList, + AceListLength); + } +} + + +NTSTATUS STDCALL +RtlAddAce(PACL Acl, + ULONG AclRevision, + ULONG StartingIndex, + PACE AceList, + ULONG AceListLength) +{ + PACE Ace; + ULONG i; + PACE Current; + ULONG j; + + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(STATUS_INVALID_PARAMETER); + } + + if (!RtlFirstFreeAce(Acl,&Ace)) + { + return(STATUS_INVALID_PARAMETER); + } + + if (Acl->AclRevision <= AclRevision) + { + AclRevision = Acl->AclRevision; + } + + if (((PVOID)AceList + AceListLength) <= (PVOID)AceList) + { + return(STATUS_INVALID_PARAMETER); + } + + i = 0; + Current = (PACE)(Acl + 1); + while ((PVOID)Current < ((PVOID)AceList + AceListLength)) + { + if (AceList->Header.AceType == 4 && + AclRevision < 3) + { + return(STATUS_INVALID_PARAMETER); + } + Current = (PACE)((PVOID)Current + Current->Header.AceSize); + } + + if (Ace == NULL) + { + return(STATUS_BUFFER_TOO_SMALL); + } + + if (((PVOID)Ace + AceListLength) >= ((PVOID)Acl + Acl->AclSize)) + { + return(STATUS_BUFFER_TOO_SMALL); + } + + if (StartingIndex != 0) + { + if (Acl->AceCount > 0) + { + Current = (PACE)(Acl + 1); + for (j = 0; j < StartingIndex; j++) + { + Current = (PACE)((PVOID)Current + Current->Header.AceSize); + } + } + } + + RtlpAddData(AceList, + AceListLength, + Current, + (ULONG)Ace - (ULONG)Current); + Acl->AceCount = Acl->AceCount + i; + Acl->AclRevision = AclRevision; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlAddAuditAccessAce(PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid, + BOOLEAN Success, + BOOLEAN Failure) +{ + PACE Ace; + ULONG Flags = 0; + + if (Success != FALSE) + { + Flags |= SUCCESSFUL_ACCESS_ACE_FLAG; + } + + if (Failure != FALSE) + { + Flags |= FAILED_ACCESS_ACE_FLAG; + } + + if (!RtlValidSid(Sid)) + { + return(STATUS_INVALID_SID); + } + + if (Acl->AclRevision > 3 || + Revision > 3) + { + return(STATUS_REVISION_MISMATCH); + } + + if (Revision < Acl->AclRevision) + { + Revision = Acl->AclRevision; + } + + if (!RtlFirstFreeAce(Acl, &Ace)) + { + return(STATUS_INVALID_ACL); + } + + if (Ace == NULL) + { + return(STATUS_ALLOTTED_SPACE_EXCEEDED); + } + + if (((PVOID)Ace + RtlLengthSid(Sid) + sizeof(ACE)) >= ((PVOID)Acl + Acl->AclSize)) + { + return(STATUS_ALLOTTED_SPACE_EXCEEDED); + } + + Ace->Header.AceFlags = Flags; + Ace->Header.AceType = 2; + Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE); + Ace->AccessMask = AccessMask; + RtlCopySid(RtlLengthSid(Sid), + (PSID)(Ace + 1), + Sid); + Acl->AceCount++; + Acl->AclRevision = Revision; + + return(STATUS_SUCCESS); +} + + +static VOID +RtlpDeleteData(PVOID Ace, + ULONG AceSize, + ULONG Offset) +{ + if (AceSize < Offset) + { + memcpy(Ace, + (PUCHAR)Ace + AceSize, + Offset - AceSize); + } + + if (Offset - AceSize < Offset) + { + memset((PUCHAR)Ace + Offset - AceSize, + 0, + AceSize); + } +} + + +NTSTATUS STDCALL +RtlDeleteAce(PACL Acl, + ULONG AceIndex) +{ + PACE Ace; + PACE Current; + + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(STATUS_INVALID_PARAMETER); + } + + if (Acl->AceCount <= AceIndex) + { + return(STATUS_INVALID_PARAMETER); + } + + if (!RtlFirstFreeAce(Acl, &Ace)) + { + return(STATUS_INVALID_PARAMETER); + } + + Current = (PACE)(Acl + 1); + + while(AceIndex--) + { + Current = (PACE)((PVOID)Current + Current->Header.AceSize); + } + + RtlpDeleteData(Current, + Current->Header.AceSize, + Ace - Current); + Acl->AceCount++; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCreateAcl(PACL Acl, + ULONG AclSize, + ULONG AclRevision) +{ + if (AclSize < 8) + { + return(STATUS_BUFFER_TOO_SMALL); + } + + if (AclRevision != 2 && + AclRevision != 3) + { + return(STATUS_INVALID_PARAMETER); + } + + if (AclSize > 0xffff) + { + return(STATUS_INVALID_PARAMETER); + } + + AclSize = AclSize & ~(0x3); + Acl->AclSize = AclSize; + Acl->AclRevision = AclRevision; + Acl->AceCount = 0; + Acl->Sbz1 = 0; + Acl->Sbz2 = 0; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlQueryInformationAcl(PACL Acl, + PVOID Information, + ULONG InformationLength, + ACL_INFORMATION_CLASS InformationClass) +{ + PACE Ace; + + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(STATUS_INVALID_PARAMETER); + } + + switch (InformationClass) + { + case AclRevisionInformation: + { + PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information; + + if (InformationLength < sizeof(ACL_REVISION_INFORMATION)) + { + return(STATUS_BUFFER_TOO_SMALL); + } + Info->AclRevision = Acl->AclRevision; + } + break; + + case AclSizeInformation: + { + PACL_SIZE_INFORMATION Info = (PACL_SIZE_INFORMATION)Information; + + if (InformationLength < sizeof(ACL_SIZE_INFORMATION)) + { + return(STATUS_BUFFER_TOO_SMALL); + } + + if (!RtlFirstFreeAce(Acl, &Ace)) + { + return(STATUS_INVALID_PARAMETER); + } + + Info->AceCount = Acl->AceCount; + if (Ace != NULL) + { + Info->AclBytesInUse = (PVOID)Ace - (PVOID)Acl; + Info->AclBytesFree = Acl->AclSize - Info->AclBytesInUse; + } + else + { + Info->AclBytesInUse = Acl->AclSize; + Info->AclBytesFree = 0; + } + } + break; + + default: + return(STATUS_INVALID_INFO_CLASS); + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlSetInformationAcl(PACL Acl, + PVOID Information, + ULONG InformationLength, + ACL_INFORMATION_CLASS InformationClass) +{ + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(STATUS_INVALID_PARAMETER); + } + + switch (InformationClass) + { + case AclRevisionInformation: + { + PACL_REVISION_INFORMATION Info = (PACL_REVISION_INFORMATION)Information; + + if (InformationLength < sizeof(ACL_REVISION_INFORMATION)) + { + return(STATUS_BUFFER_TOO_SMALL); + } + + if (Acl->AclRevision >= Info->AclRevision) + { + return(STATUS_INVALID_PARAMETER); + } + + Acl->AclRevision = Info->AclRevision; + } + break; + + default: + return(STATUS_INVALID_INFO_CLASS); + } + + return(STATUS_SUCCESS); +} + + +BOOLEAN STDCALL +RtlValidAcl(PACL Acl) +{ + PACE Ace; + USHORT Size; + + Size = (Acl->AclSize + 3) & ~3; + + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(FALSE); + } + + if (Size != Acl->AclSize) + { + return(FALSE); + } + + return(RtlFirstFreeAce(Acl, &Ace)); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/apc.c b/lib/ntdll/rtl/apc.c new file mode 100644 index 0000000..f548df1 --- /dev/null +++ b/lib/ntdll/rtl/apc.c @@ -0,0 +1,52 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * PURPOSE: User-mode APC support + * FILE: lib/ntdll/rtl/apc.c + * PROGRAMER: David Welch + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS ***************************************************************/ + +VOID STDCALL +KiUserApcDispatcher(PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK Iosb, + ULONG Reserved, + PCONTEXT Context) +{ + /* + * Call the APC + */ + ApcRoutine(ApcContext, + Iosb, + Reserved); + /* + * Switch back to the interrupted context + */ + NtContinue(Context, 1); +} + diff --git a/lib/ntdll/rtl/atom.c b/lib/ntdll/rtl/atom.c new file mode 100644 index 0000000..f4a7d6b --- /dev/null +++ b/lib/ntdll/rtl/atom.c @@ -0,0 +1,700 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/atom.c + * PURPOSE: Atom managment + * PROGRAMMER: Nobody + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +/* LOCAL TYPES ***************************************************************/ + +typedef struct _RTL_ATOM_ENTRY +{ + LIST_ENTRY List; + UNICODE_STRING Name; + ULONG RefCount; + BOOLEAN Locked; + ULONG Index; + PRTL_HANDLE Handle; +} RTL_ATOM_ENTRY, *PRTL_ATOM_ENTRY; + +typedef struct _RTL_ATOM_HANDLE +{ + RTL_HANDLE Handle; + PRTL_ATOM_ENTRY Entry; +} RTL_ATOM_HANDLE, *PRTL_ATOM_HANDLE; + + +/* PROTOTYPES ****************************************************************/ + +static ULONG RtlpHashAtomName(ULONG TableSize, PWSTR AtomName); +static BOOLEAN RtlpCheckIntegerAtom(PWSTR AtomName, PUSHORT AtomValue); + +static NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable); +static VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable); +static BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable); +static VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable); + +static BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable); +static VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable); + + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS STDCALL +RtlCreateAtomTable(ULONG TableSize, + PRTL_ATOM_TABLE *AtomTable) +{ + PRTL_ATOM_TABLE Table; + ULONG i; + NTSTATUS Status; + + DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n", + TableSize, AtomTable); + + if (*AtomTable != NULL) + { + return STATUS_SUCCESS; + } + + /* allocate atom table */ + Table = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + TableSize * sizeof(LIST_ENTRY) + + sizeof(RTL_ATOM_TABLE)); + if (Table == NULL) + { + return STATUS_NO_MEMORY; + } + + /* initialize atom table */ + Table->TableSize = TableSize; + + for (i = 0; i < TableSize; i++) + { + InitializeListHead(&Table->Slot[i]); + } + + Status = RtlpInitAtomTableLock(Table); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Table); + return Status; + } + + if (RtlpCreateAtomHandleTable(Table) == FALSE) + { + RtlpDestroyAtomTableLock(Table); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Table); + return STATUS_NO_MEMORY; + } + + *AtomTable = Table; + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable) +{ + PLIST_ENTRY Current; + PRTL_ATOM_ENTRY AtomEntry; + ULONG i; + + if (RtlpLockAtomTable(AtomTable) == FALSE) + { + return (STATUS_INVALID_PARAMETER); + } + + /* delete all atoms */ + for (i = 0; i < AtomTable->TableSize; i++) + { + + Current = AtomTable->Slot[i].Flink; + while (Current != &AtomTable->Slot[i]) + { + AtomEntry = (PRTL_ATOM_ENTRY)Current; + RtlFreeUnicodeString(&AtomEntry->Name); + RemoveEntryList(&AtomEntry->List); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomEntry); + Current = AtomTable->Slot[i].Flink; + } + + } + + RtlpDestroyAtomHandleTable(AtomTable); + + RtlpUnlockAtomTable(AtomTable); + + RtlpDestroyAtomTableLock(AtomTable); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlEmptyAtomTable(PRTL_ATOM_TABLE AtomTable, + BOOLEAN DeletePinned) +{ + PLIST_ENTRY Current, Next; + PRTL_ATOM_ENTRY AtomEntry; + ULONG i; + + DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n", + AtomTable, DeletePinned); + + if (RtlpLockAtomTable(AtomTable) == FALSE) + { + return (STATUS_INVALID_PARAMETER); + } + + /* delete all atoms */ + for (i = 0; i < AtomTable->TableSize; i++) + { + Current = AtomTable->Slot[i].Flink; + while (Current != &AtomTable->Slot[i]) + { + Next = Current->Flink; + AtomEntry = (PRTL_ATOM_ENTRY)Current; + + if ((AtomEntry->Locked == FALSE) || + ((AtomEntry->Locked == TRUE) && (DeletePinned == TRUE))) + { + RtlFreeUnicodeString(&AtomEntry->Name); + + RtlFreeHandle(AtomTable->HandleTable, + AtomEntry->Handle); + + RemoveEntryList(&AtomEntry->List); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomEntry); + } + Current = Next; + } + + } + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN PWSTR AtomName, + OUT PRTL_ATOM Atom) +{ + ULONG Hash; + PLIST_ENTRY Current; + PRTL_ATOM_ENTRY Entry; + USHORT AtomValue; + NTSTATUS Status; + PRTL_ATOM_HANDLE AtomHandle; + ULONG AtomIndex; + + DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n", + AtomTable, AtomName, Atom); + + if (RtlpCheckIntegerAtom (AtomName, &AtomValue)) + { + /* integer atom */ + if (AtomValue >= 0xC000) + { + AtomValue = 0; + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = STATUS_SUCCESS; + } + + if (Atom) + *Atom = (RTL_ATOM)AtomValue; + + return Status; + } + + RtlpLockAtomTable(AtomTable); + + /* string atom */ + Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName); + + /* search for existing atom */ + Current = AtomTable->Slot[Hash].Flink; + while (Current != &AtomTable->Slot[Hash]) + { + Entry = (PRTL_ATOM_ENTRY)Current; + + DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName); + if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0) + { + Entry->RefCount++; + if (Atom) + *Atom = (RTL_ATOM)(Entry->Index + 0xC000); + RtlpUnlockAtomTable(AtomTable); + return STATUS_SUCCESS; + } + Current = Current->Flink; + } + + /* insert new atom */ + Entry = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(RTL_ATOM_ENTRY)); + if (Entry == NULL) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_NO_MEMORY; + } + + InsertTailList(&AtomTable->Slot[Hash], &Entry->List) + RtlCreateUnicodeString (&Entry->Name, + AtomName); + Entry->RefCount = 1; + Entry->Locked = FALSE; + + /* FIXME: use general function instead !! */ + AtomHandle = (PRTL_ATOM_HANDLE)RtlAllocateHandle(AtomTable->HandleTable, + &AtomIndex); + + DPRINT("AtomHandle %p AtomIndex %x\n", AtomHandle, AtomIndex); + + AtomHandle->Entry = Entry; + Entry->Index = AtomIndex; + Entry->Handle = (PRTL_HANDLE)AtomHandle; + + if (Atom) + *Atom = (RTL_ATOM)(AtomIndex + 0xC000); + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom) +{ + PRTL_ATOM_HANDLE AtomHandle; + PRTL_ATOM_ENTRY AtomEntry; + + DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n", + AtomTable, Atom); + + if (Atom < 0xC000) + { + return STATUS_SUCCESS; + } + + RtlpLockAtomTable(AtomTable); + + /* FIXME: use general function instead !! */ + if (!RtlIsValidIndexHandle(AtomTable->HandleTable, + (PRTL_HANDLE *)&AtomHandle, + (ULONG)Atom - 0xC000)) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_INVALID_HANDLE; + } + + DPRINT("AtomHandle %x\n", AtomHandle); + DPRINT("AtomHandle->Entry %x\n", AtomHandle->Entry); + + AtomEntry = AtomHandle->Entry; + + DPRINT("Atom name: %wZ\n", &AtomEntry->Name); + + AtomEntry->RefCount--; + + if (AtomEntry->RefCount == 0) + { + if (AtomEntry->Locked == TRUE) + { + DPRINT("Atom %wZ is locked!\n", &AtomEntry->Name); + + RtlpUnlockAtomTable(AtomTable); + return STATUS_WAS_LOCKED; + } + + DPRINT("Removing atom: %wZ\n", &AtomEntry->Name); + + RtlFreeUnicodeString(&AtomEntry->Name); + RemoveEntryList(&AtomEntry->List); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomEntry); + RtlFreeHandle(AtomTable->HandleTable, + (PRTL_HANDLE)AtomHandle); + } + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN PWSTR AtomName, + OUT PRTL_ATOM Atom) +{ + ULONG Hash; + PLIST_ENTRY Current; + PRTL_ATOM_ENTRY Entry; + USHORT AtomValue; + NTSTATUS Status; + + DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n", + AtomTable, AtomName, Atom); + + if (RtlpCheckIntegerAtom (AtomName, &AtomValue)) + { + /* integer atom */ + if (AtomValue >= 0xC000) + { + AtomValue = 0; + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = STATUS_SUCCESS; + } + + if (Atom) + *Atom = (RTL_ATOM)AtomValue; + + return Status; + } + + RtlpLockAtomTable(AtomTable); + + /* string atom */ + Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName); + + /* search for existing atom */ + Current = AtomTable->Slot[Hash].Flink; + while (Current != &AtomTable->Slot[Hash]) + { + Entry = (PRTL_ATOM_ENTRY)Current; + + DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName); + if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0) + { + if (Atom) + *Atom = (RTL_ATOM)(Entry->Index + 0xC000); + RtlpUnlockAtomTable(AtomTable); + return STATUS_SUCCESS; + } + + Current = Current->Flink; + } + + return STATUS_OBJECT_NAME_NOT_FOUND; +} + + +NTSTATUS STDCALL +RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom) +{ + PRTL_ATOM_HANDLE AtomHandle; + PRTL_ATOM_ENTRY AtomEntry; + + DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n", + AtomTable, Atom); + + if (Atom < 0xC000) + { + return STATUS_SUCCESS; + } + + RtlpLockAtomTable(AtomTable); + + /* FIXME: use general function instead !! */ + if (!RtlIsValidIndexHandle(AtomTable->HandleTable, + (PRTL_HANDLE *)&AtomHandle, + (ULONG)Atom - 0xC000)) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_INVALID_HANDLE; + } + + DPRINT("AtomHandle %x\n", AtomHandle); + DPRINT("AtomHandle->Entry %x\n", AtomHandle->Entry); + + AtomEntry = AtomHandle->Entry; + + DPRINT("Atom name: %wZ\n", &AtomEntry->Name); + + AtomEntry->Locked = TRUE; + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlQueryAtomInAtomTable(PRTL_ATOM_TABLE AtomTable, + RTL_ATOM Atom, + PULONG RefCount, + PULONG PinCount, + PWSTR AtomName, + PULONG NameLength) +{ + ULONG Length; + PRTL_ATOM_HANDLE AtomHandle; + PRTL_ATOM_ENTRY AtomEntry; + + if (Atom < 0xC000) + { + if (RefCount != NULL) + { + *RefCount = 1; + } + + if (PinCount != NULL) + { + *PinCount = 1; + } + + if ((AtomName != NULL) && (NameLength != NULL) && (NameLength > 0)) + { + Length = swprintf(AtomName, L"#%lu", (ULONG)Atom); + *NameLength = Length * sizeof(WCHAR); + } + + return STATUS_SUCCESS; + } + + RtlpLockAtomTable(AtomTable); + + /* FIXME: use general function instead !! */ + if (!RtlIsValidIndexHandle(AtomTable->HandleTable, + (PRTL_HANDLE *)&AtomHandle, + (ULONG)Atom - 0xC000)) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_INVALID_HANDLE; + } + + DPRINT("AtomHandle %x\n", AtomHandle); + DPRINT("AtomHandle->Entry %x\n", AtomHandle->Entry); + + AtomEntry = AtomHandle->Entry; + + DPRINT("Atom name: %wZ\n", &AtomEntry->Name); + + if (RefCount != NULL) + { + *RefCount = AtomEntry->RefCount; + } + + if (PinCount != NULL) + { + *PinCount = (ULONG)AtomEntry->Locked; + } + + if ((AtomName != NULL) && (NameLength != NULL)) + { + if (*NameLength < AtomEntry->Name.Length) + { + *NameLength = AtomEntry->Name.Length; + RtlpUnlockAtomTable(AtomTable); + return STATUS_BUFFER_TOO_SMALL; + } + + Length = swprintf(AtomName, L"%s", AtomEntry->Name.Buffer); + *NameLength = Length * sizeof(WCHAR); + } + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +/* INTERNAL FUNCTIONS ********************************************************/ + +static ULONG +RtlpHashAtomName(ULONG TableSize, + PWSTR AtomName) +{ + ULONG q = 0; + PWCHAR p; + + DPRINT("RtlpHashAtomName(TableSize %ld AtomName '%S')\n", + TableSize, AtomName); + + /* convert the string to an internal representation */ + p = AtomName; + while (*p != 0) + { + q += (ULONG)towupper(*p); + p++; + } + + DPRINT("q %lu Hash %lu\n", q, q % TableSize); + + return (q % TableSize); +} + + +static BOOLEAN +RtlpCheckIntegerAtom(PWSTR AtomName, + PUSHORT AtomValue) +{ + UNICODE_STRING AtomString; + USHORT LoValue; + ULONG LongValue; + PWCHAR p; + + DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n", + AtomName, AtomValue); + + if (!((ULONG)AtomName & 0xFFFF0000)) + { + LoValue = (USHORT)((ULONG)AtomName & 0xFFFF); + + if (LoValue >= 0xC000) + return FALSE; + + if (LoValue == 0) + LoValue = 0xC000; + + if (AtomValue != NULL) + *AtomValue = LoValue; + + return TRUE; + } + + if (*AtomName != L'#') + return FALSE; + + p = AtomName; + p++; + while (*p) + { + if ((*p < L'0') || (*p > L'9')) + return FALSE; + p++; + } + + p = AtomName; + p++; + RtlInitUnicodeString(&AtomString, + p); + + RtlUnicodeStringToInteger(&AtomString,10, &LongValue); + + *AtomValue = (USHORT)(LongValue & 0x0000FFFF); + + return TRUE; +} + + +/* lock functions */ + +static NTSTATUS +RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable) +{ + AtomTable->Lock = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CRITICAL_SECTION)); + if (AtomTable->Lock == NULL) + return STATUS_NO_MEMORY; + + RtlInitializeCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); + + return STATUS_SUCCESS; +} + + +static VOID +RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable) +{ + if (AtomTable->Lock) + { + RtlDeleteCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomTable->Lock); + AtomTable->Lock = NULL; + } +} + + +static BOOLEAN +RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable) +{ + RtlEnterCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); + return TRUE; +} + + +static VOID +RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable) +{ + RtlLeaveCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); +} + + +/* handle functions */ + +static BOOLEAN +RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable) +{ + AtomTable->HandleTable = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(RTL_HANDLE_TABLE)); + if (AtomTable->HandleTable == NULL) + return FALSE; + + RtlInitializeHandleTable(0xCFFF, + sizeof(RTL_ATOM_HANDLE), + (PRTL_HANDLE_TABLE)AtomTable->HandleTable); + + return TRUE; +} + +static VOID +RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable) +{ + if (AtomTable->HandleTable) + { + RtlDestroyHandleTable((PRTL_HANDLE_TABLE)AtomTable->HandleTable); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomTable->HandleTable); + AtomTable->HandleTable = NULL; + } +} + +/* EOF */ diff --git a/lib/ntdll/rtl/bitmap.c b/lib/ntdll/rtl/bitmap.c new file mode 100644 index 0000000..c44e5a4 --- /dev/null +++ b/lib/ntdll/rtl/bitmap.c @@ -0,0 +1,664 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/bitmap.c + * PURPOSE: Bitmap functions + * UPDATE HISTORY: + * 20/08/99 Created by Eric Kohl + */ + +#include + + +#define NDEBUG +#include + +#define ALIGN(x,align) (((x)+(align)-1) / (align)) + + +/* FUNCTIONS *****************************************************************/ + +VOID +STDCALL +RtlInitializeBitMap ( + PRTL_BITMAP BitMapHeader, + PULONG BitMapBuffer, + ULONG SizeOfBitMap + ) +{ + BitMapHeader->SizeOfBitMap = SizeOfBitMap; + BitMapHeader->Buffer = BitMapBuffer; +} + + +BOOLEAN +STDCALL +RtlAreBitsClear ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Shift; + ULONG Count; + PUCHAR Ptr; + + if (StartingIndex >= Size || + !Length || + (StartingIndex + Length > Size)) + return FALSE; + + Ptr = (PUCHAR)BitMapHeader->Buffer + (StartingIndex / 8); + while (Length) + { + /* get bit shift in current byte */ + Shift = StartingIndex & 7; + + /* get number of bits to check in current byte */ + Count = (Length > 8 - Shift) ? 8 - Shift : Length; + + /* check byte */ + if (*Ptr & (~(0xFF << Count) << Shift)) + return FALSE; + + Ptr++; + Length -= Count; + StartingIndex += Count; + } + + return TRUE; +} + + +BOOLEAN +STDCALL +RtlAreBitsSet ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Shift; + ULONG Count; + PUCHAR Ptr; + UCHAR Check; + + if (StartingIndex >= Size || + !Length || + (StartingIndex + Length > Size)) + return FALSE; + + Ptr = (PUCHAR)BitMapHeader->Buffer + (StartingIndex / 8); + while (Length) + { + /* get bit shift in current byte */ + Shift = StartingIndex & 7; + + /* get number of bits to check in current byte */ + Count = (Length > 8 - Shift) ? 8 - Shift : Length; + + /* bulid check byte */ + Check = ~(0xFF << Count) << Shift; + + /* check byte */ + if ((*Ptr & Check) != Check) + return FALSE; + + Ptr++; + Length -= Count; + StartingIndex += Count; + } + + return TRUE; +} + + +VOID +STDCALL +RtlClearAllBits ( + IN OUT PRTL_BITMAP BitMapHeader + ) +{ + memset (BitMapHeader->Buffer, + 0x00, + ALIGN(BitMapHeader->SizeOfBitMap, 8)); +} + + +VOID +STDCALL +RtlClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToClear + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Count; + ULONG Shift; + PCHAR Ptr; + + if (StartingIndex >= Size || NumberToClear == 0) + return; + + if (StartingIndex + NumberToClear > Size) + NumberToClear = Size - StartingIndex; + + Ptr = (PCHAR)(BitMapHeader->Buffer + (StartingIndex / 8)); + while (NumberToClear) + { + /* bit shift in current byte */ + Shift = StartingIndex & 7; + + /* number of bits to change in current byte */ + Count = (NumberToClear > 8 - Shift ) ? 8 - Shift : NumberToClear; + + /* adjust byte */ + *Ptr &= ~(~(0xFF << Count) << Shift); + + Ptr++; + NumberToClear -= Count; + StartingIndex += Count; + } +} + + +ULONG +STDCALL +RtlFindClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (NumberToFind > Size || NumberToFind == 0) + return -1; + + if (HintIndex >= Size) + HintIndex = 0; + + Index = HintIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + while (HintIndex < Size) + { + /* count clear bits */ + for (Count = 0; Index < Size && ~*Ptr & Mask; Index++) + { + if (++Count >= NumberToFind) + return HintIndex; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip set bits */ + for (; Index < Size && *Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + HintIndex = Index; + } + + return -1; +} + + +ULONG +STDCALL +RtlFindClearBitsAndSet ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Index; + + Index = RtlFindClearBits (BitMapHeader, + NumberToFind, + HintIndex); + if (Index != (ULONG)-1) + RtlSetBits (BitMapHeader, + Index, + NumberToFind); + + return Index; +} + + +ULONG +STDCALL +RtlFindFirstRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (*StartingIndex > Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + + Index = *StartingIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + /* skip set bits */ + for (; Index < Size && *Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* return index of first clear bit */ + if (Index >= Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + else + *StartingIndex = Index; + + /* count clear bits */ + for (Count = 0; Index < Size && ~*Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +ULONG +STDCALL +RtlFindFirstRunSet ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (*StartingIndex > Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + + Index = *StartingIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + /* skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* return index of first set bit */ + if (Index >= Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + else + *StartingIndex = Index; + + /* count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +ULONG +STDCALL +RtlFindLongestRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Index = 0; + ULONG Count; + ULONG Max = 0; + ULONG Start; + ULONG Maxstart = 0; + CHAR Mask = 1; + + while (Index < Size) + { + Start = Index; + + /* count clear bits */ + for (Count = 0; Index < Size && ~*Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip set bits */ + for (; Index < Size && *Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + if (Count > Max) + { + Max = Count; + Maxstart = Start; + } + } + + if (StartingIndex) + *StartingIndex = Maxstart; + + return Max; +} + + +ULONG +STDCALL +RtlFindLongestRunSet ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Index = 0; + ULONG Count; + ULONG Max = 0; + ULONG Start; + ULONG Maxstart = 0; + CHAR Mask = 1; + + while (Index < Size) + { + Start = Index; + + /* count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + if (Count > Max) + { + Max = Count; + Maxstart = Start; + } + } + + if (StartingIndex) + *StartingIndex = Maxstart; + + return Max; +} + + +ULONG +STDCALL +RtlFindSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (NumberToFind > Size || NumberToFind == 0) + return (ULONG)-1; + + if (HintIndex >= Size) + HintIndex = 0; + + Index = HintIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + while (HintIndex < Size) + { + /* count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + if (++Count >= NumberToFind) + return HintIndex; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + HintIndex = Index; + } + + return (ULONG)-1; +} + + +ULONG +STDCALL +RtlFindSetBitsAndClear ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Index; + + Index = RtlFindSetBits (BitMapHeader, + NumberToFind, + HintIndex); + if (Index != (ULONG)-1) + RtlClearBits (BitMapHeader, + Index, + NumberToFind); + + return Index; +} + + +ULONG +STDCALL +RtlNumberOfClearBits ( + PRTL_BITMAP BitMapHeader + ) +{ + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + CHAR Mask; + + for (Mask = 1, Index = 0, Count = 0; Index < Size; Index++) + { + if (~*Ptr & Mask) + Count++; + + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +ULONG +STDCALL +RtlNumberOfSetBits ( + PRTL_BITMAP BitMapHeader + ) +{ + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + CHAR Mask; + + for (Mask = 1, Index = 0, Count = 0; Index < Size; Index++) + { + if (*Ptr & Mask) + Count++; + + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +VOID +STDCALL +RtlSetAllBits ( + IN OUT PRTL_BITMAP BitMapHeader + ) +{ + memset (BitMapHeader->Buffer, + 0xFF, + ALIGN(BitMapHeader->SizeOfBitMap, 8)); +} + + +VOID +STDCALL +RtlSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToSet + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Count; + ULONG Shift; + PCHAR Ptr; + + if (StartingIndex >= Size || NumberToSet == 0) + return; + + if (StartingIndex + NumberToSet > Size) + NumberToSet = Size - StartingIndex; + + Ptr = (PCHAR)BitMapHeader->Buffer + (StartingIndex / 8); + while (NumberToSet) + { + /* bit shift in current byte */ + Shift = StartingIndex & 7; + + /* number of bits to change in current byte */ + Count = (NumberToSet > 8 - Shift) ? 8 - Shift : NumberToSet; + + /* adjust byte */ + *Ptr |= ~(0xFF << Count) << Shift; + + Ptr++; + NumberToSet -= Count; + StartingIndex += Count; + } +} + +/* EOF */ diff --git a/lib/ntdll/rtl/callback.c b/lib/ntdll/rtl/callback.c new file mode 100644 index 0000000..73c7417 --- /dev/null +++ b/lib/ntdll/rtl/callback.c @@ -0,0 +1,37 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User-mode callback support + * FILE: lib/ntdll/rtl/callback.c + * PROGRAMER: David Welch + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + + +/* TYPES *********************************************************************/ + +typedef NTSTATUS STDCALL (*CALLBACK_FUNCTION)(PVOID Argument, + ULONG ArgumentLength); + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +KiUserCallbackDispatcher(ULONG RoutineIndex, + PVOID Argument, + ULONG ArgumentLength) +{ + PPEB Peb; + NTSTATUS Status; + CALLBACK_FUNCTION Callback; + + Peb = NtCurrentPeb(); + Callback = (CALLBACK_FUNCTION)Peb->KernelCallbackTable[RoutineIndex]; + Status = Callback(Argument, ArgumentLength); + ZwCallbackReturn(NULL, 0, Status); +} diff --git a/lib/ntdll/rtl/compress.c b/lib/ntdll/rtl/compress.c new file mode 100644 index 0000000..cd96ea6 --- /dev/null +++ b/lib/ntdll/rtl/compress.c @@ -0,0 +1,212 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Compression and decompression functions + * FILE: lib/ntdll/rtl/compress.c + * PROGRAMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include + + +/* MACROS *******************************************************************/ + +#define COMPRESSION_FORMAT_MASK 0x00FF +#define COMPRESSION_ENGINE_MASK 0xFF00 + + +/* FUNCTIONS ****************************************************************/ + + +static NTSTATUS +RtlpCompressBufferLZNT1(USHORT Engine, + PUCHAR UncompressedBuffer, + ULONG UncompressedBufferSize, + PUCHAR CompressedBuffer, + ULONG CompressedBufferSize, + ULONG UncompressedChunkSize, + PULONG FinalCompressedSize, + PVOID WorkSpace) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +static NTSTATUS +RtlpWorkSpaceSizeLZNT1(USHORT Engine, + PULONG BufferAndWorkSpaceSize, + PULONG FragmentWorkSpaceSize) +{ + if (Engine == COMPRESSION_ENGINE_STANDARD) + { + *BufferAndWorkSpaceSize = 0x8010; + *FragmentWorkSpaceSize = 0x1000; + return(STATUS_SUCCESS); + } + else if (Engine == COMPRESSION_ENGINE_MAXIMUM) + { + *BufferAndWorkSpaceSize = 0x10; + *FragmentWorkSpaceSize = 0x1000; + return(STATUS_SUCCESS); + } + + return(STATUS_NOT_SUPPORTED); +} + + + +NTSTATUS STDCALL +RtlCompressBuffer(IN USHORT CompressionFormatAndEngine, + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG UncompressedChunkSize, + OUT PULONG FinalCompressedSize, + IN PVOID WorkSpace) +{ + USHORT Format = CompressionFormatAndEngine & COMPRESSION_FORMAT_MASK; + USHORT Engine = CompressionFormatAndEngine & COMPRESSION_ENGINE_MASK; + + if ((Format == COMPRESSION_FORMAT_NONE) || + (Format == COMPRESSION_FORMAT_DEFAULT)) + return(STATUS_INVALID_PARAMETER); + + if (Format == COMPRESSION_FORMAT_LZNT1) + return(RtlpCompressBufferLZNT1(Engine, + UncompressedBuffer, + UncompressedBufferSize, + CompressedBuffer, + CompressedBufferSize, + UncompressedChunkSize, + FinalCompressedSize, + WorkSpace)); + + return(STATUS_UNSUPPORTED_COMPRESSION); +} + + +#if 0 +NTSTATUS STDCALL +RtlCompressChunks(IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PVOID WorkSpace) +{ + return(STATUS_NOT_IMPLEMENTED); +} +#endif + + +NTSTATUS STDCALL +RtlDecompressBuffer(IN USHORT CompressionFormat, + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + OUT PULONG FinalUncompressedSize) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +#if 0 +NTSTATUS STDCALL +RtlDecompressChunks(OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN PUCHAR CompressedTail, + IN ULONG CompressedTailSize, + IN PCOMPRESSED_DATA_INFO CompressedDataInfo) +{ + return(STATUS_NOT_IMPLEMENTED); +} +#endif + + +NTSTATUS STDCALL +RtlDecompressFragment(IN USHORT CompressionFormat, + OUT PUCHAR UncompressedFragment, + IN ULONG UncompressedFragmentSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG FragmentOffset, + OUT PULONG FinalUncompressedSize, + IN PVOID WorkSpace) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +#if 0 +NTSTATUS STDCALL +RtlDescribeChunk(IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + OUT PULONG ChunkSize) +{ + return(STATUS_NOT_IMPLEMENTED); +} +#endif + + +NTSTATUS STDCALL +RtlGetCompressionWorkSpaceSize(IN USHORT CompressionFormatAndEngine, + OUT PULONG CompressBufferAndWorkSpaceSize, + OUT PULONG CompressFragmentWorkSpaceSize) +{ + USHORT Format = CompressionFormatAndEngine & COMPRESSION_FORMAT_MASK; + USHORT Engine = CompressionFormatAndEngine & COMPRESSION_ENGINE_MASK; + + if ((Format == COMPRESSION_FORMAT_NONE) || + (Format == COMPRESSION_FORMAT_DEFAULT)) + return(STATUS_INVALID_PARAMETER); + + if (Format == COMPRESSION_FORMAT_LZNT1) + return(RtlpWorkSpaceSizeLZNT1(Engine, + CompressBufferAndWorkSpaceSize, + CompressFragmentWorkSpaceSize)); + + return(STATUS_UNSUPPORTED_COMPRESSION); +} + + +#if 0 +NTSTATUS STDCALL +RtlReserveChunk(IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + IN ULONG ChunkSize) +{ + return(STATUS_NOT_IMPLEMENTED); +} +#endif + +/* EOF */ diff --git a/lib/ntdll/rtl/critical.c b/lib/ntdll/rtl/critical.c new file mode 100644 index 0000000..b3dcba2 --- /dev/null +++ b/lib/ntdll/rtl/critical.c @@ -0,0 +1,171 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/critical.c + * PURPOSE: Critical sections + * UPDATE HISTORY: + * Created 30/09/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +RtlDeleteCriticalSection(PCRITICAL_SECTION CriticalSection) +{ + NtClose(CriticalSection->LockSemaphore); + CriticalSection->Reserved = -1; +} + +VOID STDCALL +RtlEnterCriticalSection(PCRITICAL_SECTION CriticalSection) +{ + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + ULONG ret; + + if (InterlockedIncrement(&CriticalSection->LockCount)) + { + NTSTATUS Status; + + if (CriticalSection->OwningThread == Thread) + { + CriticalSection->RecursionCount++; + return; + } + +// DbgPrint("Entering wait for critical section\n"); + Status = NtWaitForSingleObject(CriticalSection->LockSemaphore, + 0, FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("RtlEnterCriticalSection: Failed to wait (Status %x)\n", + Status); + } +// DbgPrint("Left wait for critical section\n"); + } + CriticalSection->OwningThread = Thread; + CriticalSection->RecursionCount = 1; + +#if 0 + if ((ret = InterlockedIncrement(&(CriticalSection->LockCount) )) != 1) + { + if (CriticalSection->OwningThread != Thread) + { + NtWaitForSingleObject(CriticalSection->LockSemaphore, + 0, + FALSE); + CriticalSection->OwningThread = Thread; + } + } + else + { + CriticalSection->OwningThread = Thread; + } + + CriticalSection->RecursionCount++; +#endif +} + +NTSTATUS STDCALL +RtlInitializeCriticalSection(PCRITICAL_SECTION CriticalSection) +{ + NTSTATUS Status; + + CriticalSection->LockCount = -1; + CriticalSection->RecursionCount = 0; + CriticalSection->OwningThread = (HANDLE)0; + CriticalSection->Reserved = 0; + + Status = NtCreateSemaphore(&CriticalSection->LockSemaphore, + SEMAPHORE_ALL_ACCESS, + NULL, + 0, + 1); + return Status; +} + +VOID STDCALL +RtlLeaveCriticalSection(PCRITICAL_SECTION CriticalSection) +{ + HANDLE Thread = (HANDLE)NtCurrentTeb()->Cid.UniqueThread; + + if (CriticalSection->OwningThread != Thread) + { + DbgPrint("Freeing critical section not owned\n"); + return; + } + + CriticalSection->RecursionCount--; + if (CriticalSection->RecursionCount > 0) + { + InterlockedDecrement(&CriticalSection->LockCount); + return; + } + CriticalSection->OwningThread = 0; + if (InterlockedIncrement(&CriticalSection->LockCount) >= 0) + { + NTSTATUS Status; + + Status = NtReleaseSemaphore(CriticalSection->LockSemaphore, 1, NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to release semaphore (Status %x)\n", + Status); + } + } + +#if 0 + CriticalSection->RecursionCount--; + if (CriticalSection->RecursionCount == 0) + { + CriticalSection->OwningThread = (HANDLE)-1; + // if LockCount > 0 and RecursionCount == 0 there + // is a waiting thread + // ReleaseSemaphore will fire up a waiting thread + if (InterlockedDecrement(&CriticalSection->LockCount) > 0) + { + NtReleaseSemaphore(CriticalSection->LockSemaphore,1,NULL); + } + } + else + { + InterlockedDecrement(&CriticalSection->LockCount); + } +#endif +} + +BOOLEAN STDCALL +RtlTryEnterCriticalSection(PCRITICAL_SECTION CriticalSection) +{ + if (InterlockedCompareExchange((PVOID*)&CriticalSection->LockCount, + (PVOID)1, (PVOID)0 ) == 0) + { + CriticalSection->OwningThread = + (HANDLE) NtCurrentTeb()->Cid.UniqueThread; + CriticalSection->RecursionCount++; + return TRUE; + } + if (CriticalSection->OwningThread == + (HANDLE)NtCurrentTeb()->Cid.UniqueThread) + { + CriticalSection->RecursionCount++; + return TRUE; + } + return FALSE; +} + + +/* EOF */ + + + + + diff --git a/lib/ntdll/rtl/dos8dot3.c b/lib/ntdll/rtl/dos8dot3.c new file mode 100644 index 0000000..7624a2b --- /dev/null +++ b/lib/ntdll/rtl/dos8dot3.c @@ -0,0 +1,252 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/dos8dot3.c + * PURPOSE: Short name (8.3 name) functions + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +//#define NDEBUG +#include + + +/* CONSTANTS *****************************************************************/ + +const PWCHAR RtlpShortIllegals = L" ;+=[]',\"*\\<>/?:|"; + + +/* FUNCTIONS *****************************************************************/ + +static BOOLEAN +RtlpIsShortIllegal(WCHAR Char) +{ + int i; + + for (i = 0; RtlpShortIllegals[i]; i++) + { + if (Char == RtlpShortIllegals[i]) + return(TRUE); + } + + return(FALSE); +} + + +VOID STDCALL +RtlGenerate8dot3Name(IN PUNICODE_STRING Name, + IN BOOLEAN AllowExtendedCharacters, + IN OUT PGENERATE_NAME_CONTEXT Context, + OUT PUNICODE_STRING Name8dot3) +{ + WCHAR NameBuffer[8]; + WCHAR ExtBuffer[4]; + USHORT StrLength; + USHORT NameLength; + USHORT ExtLength; + USHORT CopyLength; + USHORT DotPos; + USHORT i, j; + USHORT CurrentIndex; + + memset(NameBuffer, 0, sizeof(NameBuffer)); + memset(ExtBuffer, 0, sizeof(ExtBuffer)); + + StrLength = Name->Length / sizeof(WCHAR); + + DPRINT("StrLength: %hu\n", StrLength); + + /* Find last dot in Name */ + DotPos = 0; + for (i = 0; i < StrLength; i++) + { + if (Name->Buffer[i] == L'.') + { + DotPos = i; + } + } + + if (DotPos == 0) + { + DotPos = i; + } + + DPRINT("DotPos: %hu\n", DotPos); + + /* Copy name (6 valid characters max) */ + for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++) + { + if ((!RtlpIsShortIllegal(Name->Buffer[i])) && + (Name->Buffer[i] != L'.')) + { + NameBuffer[NameLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]); + } + } + DPRINT("NameBuffer: '%.08S'\n", NameBuffer); + DPRINT("NameLength: %hu\n", NameLength); + + /* Copy extension (4 valid characters max) */ + if (DotPos < StrLength) + { + for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++) + { + if (!RtlpIsShortIllegal(Name->Buffer[i])) + { + ExtBuffer[ExtLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]); + } + } + } + + DPRINT("ExtBuffer: '%.04S'\n", ExtBuffer); + DPRINT("ExtLength: %hu\n", ExtLength); + + /* Determine next index */ + CurrentIndex = Context->LastIndexValue; + CopyLength = min(NameLength, (CurrentIndex < 10) ? 6 : 5); + + if ((Context->NameLength == CopyLength) && + (wcsncmp(Context->NameBuffer, NameBuffer, CopyLength) == 0) && + (Context->ExtensionLength == ExtLength) && + (wcsncmp(Context->ExtensionBuffer, ExtBuffer, ExtLength) == 0)) + CurrentIndex++; + else + CurrentIndex = 1; + + DPRINT("CurrentIndex: %hu\n", CurrentIndex); + + /* Build the short name */ + for (i = 0; i < CopyLength; i++) + { + Name8dot3->Buffer[i] = NameBuffer[i]; + } + + Name8dot3->Buffer[i++] = L'~'; + if (CurrentIndex >= 10) + Name8dot3->Buffer[i++] = (CurrentIndex / 10) + L'0'; + Name8dot3->Buffer[i++] = (CurrentIndex % 10) + L'0'; + + for (j = 0; j < ExtLength; i++, j++) + { + Name8dot3->Buffer[i] = ExtBuffer[j]; + } + + Name8dot3->Length = i * sizeof(WCHAR); + + DPRINT("Name8dot3: '%wZ'\n", Name8dot3); + + /* Update context */ + Context->NameLength = CopyLength; + for (i = 0; i < CopyLength; i++) + { + Context->NameBuffer[i] = NameBuffer[i]; + } + + Context->ExtensionLength = ExtLength; + for (i = 0; i < ExtLength; i++) + { + Context->ExtensionBuffer[i] = ExtBuffer[i]; + } + + Context->LastIndexValue = CurrentIndex; +} + + +BOOLEAN STDCALL +RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName, + IN PANSI_STRING AnsiName, + OUT PBOOLEAN SpacesFound) +{ + PANSI_STRING name = AnsiName; + ANSI_STRING DummyString; + CHAR Buffer[12]; + char *str; + ULONG Length; + ULONG i; + NTSTATUS Status; + BOOLEAN HasSpace = FALSE; + BOOLEAN HasDot = FALSE; + + if (UnicodeName->Length > 24) + { + return(FALSE); /* name too long */ + } + + if (!name) + { + name = &DummyString; + name->Length = 0; + name->MaximumLength = 12; + name->Buffer = Buffer; + } + + Status = RtlUpcaseUnicodeStringToCountedOemString(name, + UnicodeName, + FALSE); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + Length = name->Length; + str = name->Buffer; + + if (!(Length == 1 && *str == '.') && + !(Length == 2 && *str == '.' && *(str + 1) == '.')) + { + for (i = 0; i < Length; i++, str++) + { + switch (*str) + { + case ' ': + HasSpace = TRUE; + break; + + case '.': + if ((HasDot) || /* two or more dots */ + (i == 0) || /* dot is first char */ + (i + 1 == Length) || /* dot is last char */ + (Length - i > 4) || /* more than 3 chars of extension */ + (HasDot == FALSE && i > 8)) /* name is longer than 8 chars */ + return(FALSE); + HasDot = TRUE; + break; + } + } + } + + /* Name is longer than 8 chars and does not have an extension */ + if (Length > 8 && HasDot == FALSE) + { + return(FALSE); + } + + if (SpacesFound) + *SpacesFound = HasSpace; + + return(TRUE); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/env.c b/lib/ntdll/rtl/env.c new file mode 100644 index 0000000..cbdf7be --- /dev/null +++ b/lib/ntdll/rtl/env.c @@ -0,0 +1,496 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/env.c + * PURPOSE: Environment functions + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * Created 30/09/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +RtlCreateEnvironment(BOOLEAN Inherit, + PWSTR *Environment) +{ + MEMORY_BASIC_INFORMATION MemInfo; + PVOID EnvPtr = NULL; + NTSTATUS Status = STATUS_SUCCESS; + ULONG RegionSize = PAGE_SIZE; + + if (Inherit == TRUE) + { + RtlAcquirePebLock(); +#if 0 + if (NtCurrentPeb()->ProcessParameters->Environment != NULL) + { + Status = NtQueryVirtualMemory(NtCurrentProcess(), + NtCurrentPeb()->ProcessParameters->Environment, + MemoryBasicInformation, + &MemInfo, + sizeof(MEMORY_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + RtlReleasePebLock(); + *Environment = NULL; + return(Status); + } + + RegionSize = MemInfo.RegionSize; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &EnvPtr, + 0, + &RegionSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + RtlReleasePebLock(); + *Environment = NULL; + return(Status); + } + + memmove(EnvPtr, + NtCurrentPeb ()->ProcessParameters->Environment, + MemInfo.RegionSize); + + *Environment = EnvPtr; + } +#endif + RtlReleasePebLock (); + } + else + { + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &EnvPtr, + 0, + &RegionSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (NT_SUCCESS(Status)) + { + memset(EnvPtr, + 0, + RegionSize); + *Environment = EnvPtr; + } + } + + return(Status); +} + + +VOID STDCALL +RtlDestroyEnvironment(PWSTR Environment) +{ + ULONG Size = 0; + + NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&Environment, + &Size, + MEM_RELEASE); +} + + +NTSTATUS STDCALL +RtlExpandEnvironmentStrings_U(PWSTR Environment, + PUNICODE_STRING Source, + PUNICODE_STRING Destination, + PULONG Length) +{ + UNICODE_STRING var; + UNICODE_STRING val; + NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN flag = FALSE; + PWSTR s; + PWSTR d; + PWSTR w; + int src_len; + int dst_max; + int tail; + + DPRINT("RtlExpandEnvironmentStrings_U %p %wZ %p %p\n", + Environment, Source, Destination, Length); + + src_len = Source->Length / sizeof(WCHAR); + s = Source->Buffer; + dst_max = Destination->MaximumLength / sizeof(WCHAR); + d = Destination->Buffer; + + while (src_len) + { + if (*s == L'%') + { + if (flag) + { + flag = FALSE; + goto copy; + } + w = s + 1; + tail = src_len - 1; + while (*w != L'%' && tail) + { + w++; + tail--; + } + if (!tail) + goto copy; + + var.Length = (w - ( s + 1)) * sizeof(WCHAR); + var.MaximumLength = var.Length; + var.Buffer = s + 1; + + val.Length = 0; + val.MaximumLength = dst_max * sizeof(WCHAR); + val.Buffer = d; + Status = RtlQueryEnvironmentVariable_U (Environment, &var, &val); + if (NT_SUCCESS(Status)) + { + d += val.Length / sizeof(WCHAR); + dst_max -= val.Length / sizeof(WCHAR); + s = w + 1; + src_len = tail - 1; + continue; + } + /* variable not found or buffer too small, just copy %var% */ + flag = TRUE; + } +copy: + if (!dst_max) + { + Status = STATUS_BUFFER_TOO_SMALL; + break; + } + + *d++ = *s++; + dst_max--; + src_len--; + } + + Destination->Length = (d - Destination->Buffer) * sizeof(WCHAR); + if (Length != NULL) + *Length = Destination->Length; + if (dst_max) + Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0; + + DPRINT("Destination %wZ\n", Destination); + return(Status); +} + + +VOID STDCALL +RtlSetCurrentEnvironment(PWSTR NewEnvironment, + PWSTR *OldEnvironment) +{ + PVOID EnvPtr; + + DPRINT("NewEnvironment %x OldEnvironment %x\n", + NewEnvironment, OldEnvironment); + + RtlAcquirePebLock(); + + EnvPtr = NtCurrentPeb()->ProcessParameters->Environment; + NtCurrentPeb()->ProcessParameters->Environment = NewEnvironment; + + if (OldEnvironment != NULL) + *OldEnvironment = EnvPtr; + + RtlReleasePebLock(); +} + + +NTSTATUS STDCALL +RtlSetEnvironmentVariable(PWSTR *Environment, + PUNICODE_STRING Name, + PUNICODE_STRING Value) +{ + MEMORY_BASIC_INFORMATION mbi; + UNICODE_STRING var; + int hole_len, new_len, env_len = 0; + WCHAR *new_env = 0, *env_end = 0, *wcs, *env, *val = 0, *tail = 0, *hole = 0; + PWSTR head = NULL; + ULONG size = 0, new_size; + LONG f = 1; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("RtlSetEnvironmentVariable(Environment %p Name %wZ Value %wZ)\n", + Environment, Name, Value); + + if (Environment) + { + env = *Environment; + } + else + { + RtlAcquirePebLock(); + env = NtCurrentPeb()->ProcessParameters->Environment; + } + + if (env) + { + /* get environment length */ + wcs = env_end = env; + while (*env_end) + while (*env_end++) + ; + env_end++; + env_len = env_end - env; + DPRINT("environment length %ld characters\n", env_len); + + /* find where to insert */ + while (*wcs) + { + for (var.Buffer = wcs++; *wcs && *wcs != L'='; wcs++) + ; + if (*wcs) + { + var.Length = (wcs - var.Buffer) * sizeof(WCHAR); + var.MaximumLength = var.Length; + for ( val = ++wcs; *wcs; wcs++) + ; + f = RtlCompareUnicodeString(&var, Name, TRUE); + if (f >= 0) + { + if (f) /* Insert before found */ + { + hole = tail = var.Buffer; + } + else /* Exact match */ + { + head = var.Buffer; + tail = ++wcs; + hole = val; + } + goto found; + } + } + wcs++; + } + hole = tail = wcs; /* Append to environment */ + } + +found: + if (Value->Length > 0) + { + hole_len = tail - hole; + /* calculate new environment size */ + new_size = Value->Length + sizeof(WCHAR); + /* adding new variable */ + if (f) + new_size += Name->Length + sizeof(WCHAR); + new_len = new_size / sizeof(WCHAR); + if (hole_len < new_len) + { + /* enlarge environment size */ + /* check the size of available memory */ + new_size += (env_len - hole_len) * sizeof(WCHAR); + new_size = ROUNDUP(new_size, PAGE_SIZE); + mbi.RegionSize = 0; + DPRINT("new_size %lu\n", new_size); + + if (env) + { + Status = NtQueryVirtualMemory(NtCurrentProcess(), + env, + 0, + &mbi, + sizeof(mbi), + NULL); + if (!NT_SUCCESS(Status)) + { + if (Environment == NULL) + { + RtlReleasePebLock(); + } + return(Status); + } + } + + if (new_size > mbi.RegionSize) + { + /* reallocate memory area */ + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + (VOID**)&new_env, + 0, + &new_size, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + if (Environment == NULL) + { + RtlReleasePebLock(); + } + return(Status); + } + + if (env) + { + memmove(new_env, + env, + (hole - env) * sizeof(WCHAR)); + hole = new_env + (hole - env); + } + else + { + /* absolutely new environment */ + tail = hole = new_env; + *hole = 0; + env_end = hole + 1; + } + } + } + + /* move tail */ + memmove (hole + new_len, tail, (env_end - tail) * sizeof(WCHAR)); + + if (new_env) + { + /* we reallocated environment, let's free the old one */ + if (Environment) + *Environment = new_env; + else + NtCurrentPeb()->ProcessParameters->Environment = new_env; + + if (env) + { + size = 0; + NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&env, + &size, + MEM_RELEASE); + } + } + + /* and now copy given stuff */ + if (f) + { + /* copy variable name and '=' character */ + memmove(hole, + Name->Buffer, + Name->Length); + hole += Name->Length / sizeof(WCHAR); + *hole++ = L'='; + } + + /* copy value */ + memmove(hole, + Value->Buffer, + Value->Length); + hole += Value->Length / sizeof(WCHAR); + *hole = 0; + } + else + { + /* remove the environment variable */ + if (f == 0) + { + memmove(head, + tail, + (env_end - tail) * sizeof(WCHAR)); + } + else + { + Status = STATUS_VARIABLE_NOT_FOUND; + } + } + + if (Environment == NULL) + { + RtlReleasePebLock(); + } + + return(Status); +} + + +NTSTATUS STDCALL +RtlQueryEnvironmentVariable_U(PWSTR Environment, + PUNICODE_STRING Name, + PUNICODE_STRING Value) +{ + NTSTATUS Status; + PWSTR wcs; + PWSTR var; + PWSTR val; + int varlen; + int len; + BOOLEAN SysEnvUsed = FALSE; + + DPRINT("RtlQueryEnvironmentVariable_U Environment %p Variable %wZ Value %p\n", + Environment, Name, Value); + + if (Environment == NULL) + { + Environment = NtCurrentPeb()->ProcessParameters->Environment; + SysEnvUsed = TRUE; + } + + if (Environment == NULL) + return(STATUS_VARIABLE_NOT_FOUND); + + Value->Length = 0; + if (SysEnvUsed == TRUE) + RtlAcquirePebLock(); + + wcs = Environment; + len = Name->Length / sizeof(WCHAR); + while (*wcs) + { + for (var = wcs++; *wcs && *wcs != L'='; wcs++) + ; + + if (*wcs) + { + varlen = wcs - var; + for (val = ++wcs; *wcs; wcs++) + ; + + if (varlen == len && + !_wcsnicmp(var, Name->Buffer, len)) + { + Value->Length = (wcs - val) * sizeof(WCHAR); + if (Value->Length < Value->MaximumLength) + { + wcscpy(Value->Buffer, val); + DPRINT("Value %S\n", val); + DPRINT("Return STATUS_SUCCESS\n"); + Status = STATUS_SUCCESS; + } + else + { + DPRINT("Return STATUS_BUFFER_TOO_SMALL\n"); + Status = STATUS_BUFFER_TOO_SMALL; + } + + if (SysEnvUsed == TRUE) + RtlReleasePebLock(); + + return(Status); + } + } + wcs++; + } + + if (SysEnvUsed == TRUE) + RtlReleasePebLock(); + + DPRINT("Return STATUS_VARIABLE_NOT_FOUND\n"); + return(STATUS_VARIABLE_NOT_FOUND); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/error.c b/lib/ntdll/rtl/error.c new file mode 100644 index 0000000..6eb801e --- /dev/null +++ b/lib/ntdll/rtl/error.c @@ -0,0 +1,965 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Rtl error functions + * FILE: lib/ntdll/rtl/error.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 22/07/99: Added RtlNtStatusToDosError. + * 1999-11-30: Added RtlNtStatusToPsxErrno. + * 1999-12-18: STDCALL RtlNtStatusToDosError + */ + +/* + * Partially taken from WINE, original copyright: + * + * Copyright 2000 Alexandre Julliard + */ + + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +typedef struct _ERROR_TABLE +{ + ULONG Start; + ULONG End; + const WORD *Table; +} ERROR_TABLE, *PERROR_TABLE; + + +/* FUNCTIONS ***************************************************************/ + +static const WORD table_00000103[11] = +{ + ERROR_IO_PENDING, /* 00000103 (STATUS_PENDING) */ + ERROR_MR_MID_NOT_FOUND, /* 00000104 (STATUS_REPARSE) */ + ERROR_MORE_DATA, /* 00000105 (STATUS_MORE_ENTRIES) */ + ERROR_NOT_ALL_ASSIGNED, /* 00000106 (STATUS_NOT_ALL_ASSIGNED) */ + ERROR_SOME_NOT_MAPPED, /* 00000107 (STATUS_SOME_NOT_MAPPED) */ + ERROR_MR_MID_NOT_FOUND, /* 00000108 (STATUS_OPLOCK_BREAK_IN_PROCESS) */ + ERROR_MR_MID_NOT_FOUND, /* 00000109 (STATUS_VOLUME_MOUNTED) */ + ERROR_MR_MID_NOT_FOUND, /* 0000010a (STATUS_RXACT_COMMITTED) */ + ERROR_MR_MID_NOT_FOUND, /* 0000010b (STATUS_NOTIFY_CLEANUP) */ + ERROR_NOTIFY_ENUM_DIR, /* 0000010c (STATUS_NOTIFY_ENUM_DIR) */ + ERROR_NO_QUOTAS_FOR_ACCOUNT /* 0000010d (STATUS_NO_QUOTAS_FOR_ACCOUNT) */ +// /* 0000010e (STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED) */ +}; + +static const WORD table_40000002[12] = +{ + ERROR_INVALID_PARAMETER, /* 40000002 */ + ERROR_MR_MID_NOT_FOUND, /* 40000003 */ + ERROR_MR_MID_NOT_FOUND, /* 40000004 */ + ERROR_MR_MID_NOT_FOUND, /* 40000005 */ + ERROR_LOCAL_USER_SESSION_KEY, /* 40000006 (STATUS_LOCAL_USER_SESSION_KEY) */ + ERROR_MR_MID_NOT_FOUND, /* 40000007 */ + ERROR_MORE_WRITES, /* 40000008 (STATUS_SERIAL_MORE_WRITES) */ + ERROR_REGISTRY_RECOVERED, /* 40000009 (STATUS_REGISTRY_RECOVERED) */ + ERROR_MR_MID_NOT_FOUND, /* 4000000a */ + ERROR_MR_MID_NOT_FOUND, /* 4000000b */ + ERROR_COUNTER_TIMEOUT, /* 4000000c (STATUS_SERIAL_COUNTER_TIMEOUT) */ + ERROR_NULL_LM_PASSWORD /* 4000000d (STATUS_NULL_LM_PASSWORD) */ +}; + +static const WORD table_40020056[1] = +{ + RPC_S_UUID_LOCAL_ONLY /* 40020056 */ +}; + +static const WORD table_400200af[1] = +{ + RPC_S_SEND_INCOMPLETE /* 400200af */ +}; + +static const WORD table_80000001[38] = +{ + 0, /* 80000001 (STATUS_GUARD_PAGE_VIOLATION) */ + ERROR_NOACCESS, /* 80000002 (STATUS_DATATYPE_MISALIGNMENT) */ + 0, /* 80000003 (STATUS_BREAKPOINT) */ + 0, /* 80000004 (STATUS_SINGLE_STEP) */ + ERROR_MORE_DATA, /* 80000005 (STATUS_BUFFER_OVERFLOW) */ + ERROR_NO_MORE_FILES, /* 80000006 (STATUS_NO_MORE_FILES) */ + ERROR_MR_MID_NOT_FOUND, /* 80000007 (STATUS_WAKE_SYSTEM_DEBUGGER) */ + ERROR_MR_MID_NOT_FOUND, /* 80000008 */ + ERROR_MR_MID_NOT_FOUND, /* 80000009 */ + ERROR_MR_MID_NOT_FOUND, /* 8000000a (STATUS_HANDLES_CLOSED) */ + ERROR_NO_INHERITANCE, /* 8000000b (STATUS_NO_INHERITANCE) */ + ERROR_MR_MID_NOT_FOUND, /* 8000000c (STATUS_GUID_SUBSTITUTION_MADE) */ + ERROR_PARTIAL_COPY, /* 8000000d (STATUS_PARTIAL_COPY) */ + ERROR_OUT_OF_PAPER, /* 8000000e (STATUS_DEVICE_PAPER_EMPTY) */ + ERROR_NOT_READY, /* 8000000f (STATUS_DEVICE_POWERED_OFF) */ + ERROR_NOT_READY, /* 80000010 (STATUS_DEVICE_OFF_LINE) */ + ERROR_BUSY, /* 80000011 (STATUS_DEVICE_BUSY) */ + ERROR_NO_MORE_ITEMS, /* 80000012 (STATUS_NO_MORE_EAS) */ + ERROR_INVALID_EA_NAME, /* 80000013 (STATUS_INVALID_EA_NAME) */ + ERROR_EA_LIST_INCONSISTENT, /* 80000014 (STATUS_EA_LIST_INCONSISTENT) */ + ERROR_EA_LIST_INCONSISTENT, /* 80000015 (STATUS_INVALID_EA_FLAG) */ + ERROR_MEDIA_CHANGED, /* 80000016 (STATUS_VERIFY_REQUIRED) */ + ERROR_MR_MID_NOT_FOUND, /* 80000017 (STATUS_EXTRANEOUS_INFORMATION) */ + ERROR_MR_MID_NOT_FOUND, /* 80000018 (STATUS_RXACT_COMMIT_NECESSARY) */ + ERROR_MR_MID_NOT_FOUND, /* 80000019 */ + ERROR_NO_MORE_ITEMS, /* 8000001a (STATUS_NO_MORE_ENTRIES) */ + ERROR_FILEMARK_DETECTED, /* 8000001b (STATUS_FILEMARK_DETECTED) */ + ERROR_MEDIA_CHANGED, /* 8000001c (STATUS_MEDIA_CHANGED) */ + ERROR_BUS_RESET, /* 8000001d (STATUS_BUS_RESET) */ + ERROR_END_OF_MEDIA, /* 8000001e (STATUS_END_OF_MEDIA) */ + ERROR_BEGINNING_OF_MEDIA, /* 8000001f (STATUS_BEGINNING_OF_MEDIA) */ + ERROR_MR_MID_NOT_FOUND, /* 80000020 (STATUS_MEDIA_CHECK) */ + ERROR_SETMARK_DETECTED, /* 80000021 (STATUS_SETMARK_DETECTED) */ + ERROR_NO_DATA_DETECTED, /* 80000022 (STATUS_NO_DATA_DETECTED) */ + ERROR_MR_MID_NOT_FOUND, /* 80000023 (STATUS_REDIRECTOR_HAS_OPEN_HANDLES) */ + ERROR_MR_MID_NOT_FOUND, /* 80000024 (STATUS_SERVER_HAS_OPEN_HANDLES) */ + ERROR_ACTIVE_CONNECTIONS, /* 80000025 (STATUS_ALREADY_DISCONNECTED) */ + ERROR_MR_MID_NOT_FOUND /* 80000026 (STATUS_LONGJUMP) */ +}; + +static const WORD table_80090300[23] = +{ + ERROR_NO_SYSTEM_RESOURCES, /* 80090300 */ + ERROR_INVALID_HANDLE, /* 80090301 */ + ERROR_INVALID_FUNCTION, /* 80090302 */ + ERROR_BAD_NETPATH, /* 80090303 */ + ERROR_INTERNAL_ERROR, /* 80090304 */ + ERROR_NO_SUCH_PACKAGE, /* 80090305 */ + ERROR_NOT_OWNER, /* 80090306 */ + ERROR_NO_SUCH_PACKAGE, /* 80090307 */ + ERROR_INVALID_PARAMETER, /* 80090308 */ + ERROR_INVALID_PARAMETER, /* 80090309 */ + ERROR_NOT_SUPPORTED, /* 8009030a */ + ERROR_CANNOT_IMPERSONATE, /* 8009030b */ + ERROR_LOGON_FAILURE, /* 8009030c */ + ERROR_INVALID_PARAMETER, /* 8009030d */ + ERROR_NO_SUCH_LOGON_SESSION, /* 8009030e */ + ERROR_ACCESS_DENIED, /* 8009030f */ + ERROR_ACCESS_DENIED, /* 80090310 */ + ERROR_NO_LOGON_SERVERS, /* 80090311 */ + ERROR_MR_MID_NOT_FOUND, /* 80090312 */ + ERROR_MR_MID_NOT_FOUND, /* 80090313 */ + ERROR_MR_MID_NOT_FOUND, /* 80090314 */ + ERROR_MR_MID_NOT_FOUND, /* 80090315 */ + ERROR_NO_SUCH_PACKAGE /* 80090316 */ +}; + +static const WORD table_c0000001[411] = +{ + ERROR_GEN_FAILURE, /* c0000001 (STATUS_UNSUCCESSFUL) */ + ERROR_INVALID_FUNCTION, /* c0000002 (STATUS_NOT_IMPLEMENTED) */ + ERROR_INVALID_PARAMETER, /* c0000003 (STATUS_INVALID_INFO_CLASS) */ + ERROR_BAD_LENGTH, /* c0000004 (STATUS_INFO_LENGTH_MISMATCH) */ + ERROR_NOACCESS, /* c0000005 (STATUS_ACCESS_VIOLATION) */ + ERROR_SWAPERROR, /* c0000006 (STATUS_IN_PAGE_ERROR) */ + ERROR_PAGEFILE_QUOTA, /* c0000007 (STATUS_PAGEFILE_QUOTA) */ + ERROR_INVALID_HANDLE, /* c0000008 (STATUS_INVALID_HANDLE) */ + ERROR_STACK_OVERFLOW, /* c0000009 (STATUS_BAD_INITIAL_STACK) */ + ERROR_BAD_EXE_FORMAT, /* c000000a (STATUS_BAD_INITIAL_PC) */ + ERROR_INVALID_PARAMETER, /* c000000b (STATUS_INVALID_CID) */ + ERROR_MR_MID_NOT_FOUND, /* c000000c (STATUS_TIMER_NOT_CANCELED) */ + ERROR_INVALID_PARAMETER, /* c000000d (STATUS_INVALID_PARAMETER) */ + ERROR_FILE_NOT_FOUND, /* c000000e (STATUS_NO_SUCH_DEVICE) */ + ERROR_FILE_NOT_FOUND, /* c000000f (STATUS_NO_SUCH_FILE) */ + ERROR_INVALID_FUNCTION, /* c0000010 (STATUS_INVALID_DEVICE_REQUEST) */ + ERROR_HANDLE_EOF, /* c0000011 (STATUS_END_OF_FILE) */ + ERROR_WRONG_DISK, /* c0000012 (STATUS_WRONG_VOLUME) */ + ERROR_NOT_READY, /* c0000013 (STATUS_NO_MEDIA_IN_DEVICE) */ + ERROR_UNRECOGNIZED_MEDIA, /* c0000014 (STATUS_UNRECOGNIZED_MEDIA) */ + ERROR_SECTOR_NOT_FOUND, /* c0000015 (STATUS_NONEXISTENT_SECTOR) */ + ERROR_MORE_DATA, /* c0000016 (STATUS_MORE_PROCESSING_REQUIRED) */ + ERROR_NOT_ENOUGH_MEMORY, /* c0000017 (STATUS_NO_MEMORY) */ + ERROR_INVALID_ADDRESS, /* c0000018 (STATUS_CONFLICTING_ADDRESSES) */ + ERROR_INVALID_ADDRESS, /* c0000019 (STATUS_NOT_MAPPED_VIEW) */ + ERROR_INVALID_PARAMETER, /* c000001a (STATUS_UNABLE_TO_FREE_VM) */ + ERROR_INVALID_PARAMETER, /* c000001b (STATUS_UNABLE_TO_DELETE_SECTION) */ + ERROR_INVALID_FUNCTION, /* c000001c (STATUS_INVALID_SYSTEM_SERVICE) */ + 0, /* c000001d (STATUS_ILLEGAL_INSTRUCTION) */ + ERROR_ACCESS_DENIED, /* c000001e (STATUS_INVALID_LOCK_SEQUENCE) */ + ERROR_ACCESS_DENIED, /* c000001f (STATUS_INVALID_VIEW_SIZE) */ + ERROR_BAD_EXE_FORMAT, /* c0000020 (STATUS_INVALID_FILE_FOR_SECTION) */ + ERROR_ACCESS_DENIED, /* c0000021 (STATUS_ALREADY_COMMITTED) */ + ERROR_ACCESS_DENIED, /* c0000022 (STATUS_ACCESS_DENIED) */ + ERROR_INSUFFICIENT_BUFFER, /* c0000023 (STATUS_BUFFER_TOO_SMALL) */ + ERROR_INVALID_HANDLE, /* c0000024 (STATUS_OBJECT_TYPE_MISMATCH) */ + 0, /* c0000025 (STATUS_NONCONTINUABLE_EXCEPTION) */ + 0, /* c0000026 (STATUS_INVALID_DISPOSITION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000027 (STATUS_UNWIND) */ + ERROR_MR_MID_NOT_FOUND, /* c0000028 (STATUS_BAD_STACK) */ + ERROR_MR_MID_NOT_FOUND, /* c0000029 (STATUS_INVALID_UNWIND_TARGET) */ + ERROR_NOT_LOCKED, /* c000002a (STATUS_NOT_LOCKED) */ + 0, /* c000002b (STATUS_PARITY_ERROR) */ + ERROR_INVALID_ADDRESS, /* c000002c (STATUS_UNABLE_TO_DECOMMIT_VM) */ + ERROR_INVALID_ADDRESS, /* c000002d (STATUS_NOT_COMMITTED) */ + ERROR_MR_MID_NOT_FOUND, /* c000002e (STATUS_INVALID_PORT_ATTRIBUTES) */ + ERROR_MR_MID_NOT_FOUND, /* c000002f (STATUS_PORT_MESSAGE_TOO_LONG) */ + ERROR_INVALID_PARAMETER, /* c0000030 (STATUS_INVALID_PARAMETER_MIX) */ + ERROR_MR_MID_NOT_FOUND, /* c0000031 (STATUS_INVALID_QUOTA_LOWER) */ + ERROR_DISK_CORRUPT, /* c0000032 (STATUS_DISK_CORRUPT_ERROR) */ + ERROR_INVALID_NAME, /* c0000033 (STATUS_OBJECT_NAME_INVALID) */ + ERROR_FILE_NOT_FOUND, /* c0000034 (STATUS_OBJECT_NAME_NOT_FOUND) */ + ERROR_ALREADY_EXISTS, /* c0000035 (STATUS_OBJECT_NAME_COLLISION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000036 */ + ERROR_INVALID_HANDLE, /* c0000037 (STATUS_PORT_DISCONNECTED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000038 (STATUS_DEVICE_ALREADY_ATTACHED) */ + ERROR_BAD_PATHNAME, /* c0000039 (STATUS_OBJECT_PATH_INVALID) */ + ERROR_PATH_NOT_FOUND, /* c000003a (STATUS_OBJECT_PATH_NOT_FOUND) */ + ERROR_BAD_PATHNAME, /* c000003b (STATUS_PATH_SYNTAX_BAD) */ + ERROR_IO_DEVICE, /* c000003c (STATUS_DATA_OVERRUN) */ + ERROR_IO_DEVICE, /* c000003d (STATUS_DATA_LATE_ERROR) */ + ERROR_CRC, /* c000003e (STATUS_DATA_ERROR) */ + ERROR_CRC, /* c000003f (STATUS_CRC_ERROR) */ + ERROR_NOT_ENOUGH_MEMORY, /* c0000040 (STATUS_SECTION_TOO_BIG) */ + ERROR_ACCESS_DENIED, /* c0000041 (STATUS_PORT_CONNECTION_REFUSED) */ + ERROR_INVALID_HANDLE, /* c0000042 (STATUS_INVALID_PORT_HANDLE) */ + ERROR_SHARING_VIOLATION, /* c0000043 (STATUS_SHARING_VIOLATION) */ + ERROR_NOT_ENOUGH_QUOTA, /* c0000044 (STATUS_QUOTA_EXCEEDED) */ + ERROR_INVALID_PARAMETER, /* c0000045 (STATUS_INVALID_PAGE_PROTECTION) */ + ERROR_NOT_OWNER, /* c0000046 (STATUS_MUTANT_NOT_OWNED) */ + ERROR_TOO_MANY_POSTS, /* c0000047 (STATUS_SEMAPHORE_LIMIT_EXCEEDED) */ + ERROR_INVALID_PARAMETER, /* c0000048 (STATUS_PORT_ALREADY_SET) */ + ERROR_INVALID_PARAMETER, /* c0000049 (STATUS_SECTION_NOT_IMAGE) */ + ERROR_SIGNAL_REFUSED, /* c000004a (STATUS_SUSPEND_COUNT_EXCEEDED) */ + ERROR_ACCESS_DENIED, /* c000004b (STATUS_THREAD_IS_TERMINATING) */ + ERROR_INVALID_PARAMETER, /* c000004c (STATUS_BAD_WORKING_SET_LIMIT) */ + ERROR_INVALID_PARAMETER, /* c000004d (STATUS_INCOMPATIBLE_FILE_MAP) */ + ERROR_INVALID_PARAMETER, /* c000004e (STATUS_SECTION_PROTECTION) */ + ERROR_MR_MID_NOT_FOUND, /* c000004f (STATUS_EAS_NOT_SUPPORTED) */ + ERROR_EA_LIST_INCONSISTENT, /* c0000050 (STATUS_EA_TOO_LARGE) */ + ERROR_FILE_CORRUPT, /* c0000051 (STATUS_NONEXISTENT_EA_ENTRY) */ + ERROR_FILE_CORRUPT, /* c0000052 (STATUS_NO_EAS_ON_FILE) */ + ERROR_FILE_CORRUPT, /* c0000053 (STATUS_EA_CORRUPT_ERROR) */ + ERROR_LOCK_VIOLATION, /* c0000054 (STATUS_LOCK_NOT_GRANTED) */ + ERROR_LOCK_VIOLATION, /* c0000055 (STATUS_FILE_LOCK_CONFLICT) */ + ERROR_ACCESS_DENIED, /* c0000056 (STATUS_DELETE_PENDING) */ + ERROR_NOT_SUPPORTED, /* c0000057 (STATUS_CTL_FILE_NOT_SUPPORTED) */ + ERROR_UNKNOWN_REVISION, /* c0000058 (STATUS_UNKNOWN_REVISION) */ + ERROR_REVISION_MISMATCH, /* c0000059 (STATUS_REVISION_MISMATCH) */ + ERROR_INVALID_OWNER, /* c000005a (STATUS_INVALID_OWNER) */ + ERROR_INVALID_PRIMARY_GROUP, /* c000005b (STATUS_INVALID_PRIMARY_GROUP) */ + ERROR_NO_IMPERSONATION_TOKEN, /* c000005c (STATUS_NO_IMPERSONATION_TOKEN) */ + ERROR_CANT_DISABLE_MANDATORY, /* c000005d (STATUS_CANT_DISABLE_MANDATORY) */ + ERROR_NO_LOGON_SERVERS, /* c000005e (STATUS_NO_LOGON_SERVERS) */ + ERROR_NO_SUCH_LOGON_SESSION, /* c000005f (STATUS_NO_SUCH_LOGON_SESSION) */ + ERROR_NO_SUCH_PRIVILEGE, /* c0000060 (STATUS_NO_SUCH_PRIVILEGE) */ + ERROR_PRIVILEGE_NOT_HELD, /* c0000061 (STATUS_PRIVILEGE_NOT_HELD) */ + ERROR_INVALID_ACCOUNT_NAME, /* c0000062 (STATUS_INVALID_ACCOUNT_NAME) */ + ERROR_USER_EXISTS, /* c0000063 (STATUS_USER_EXISTS) */ + ERROR_NO_SUCH_USER, /* c0000064 (STATUS_NO_SUCH_USER) */ + ERROR_GROUP_EXISTS, /* c0000065 (STATUS_GROUP_EXISTS) */ + ERROR_NO_SUCH_GROUP, /* c0000066 (STATUS_NO_SUCH_GROUP) */ + ERROR_MEMBER_IN_GROUP, /* c0000067 (STATUS_MEMBER_IN_GROUP) */ + ERROR_MEMBER_NOT_IN_GROUP, /* c0000068 (STATUS_MEMBER_NOT_IN_GROUP) */ + ERROR_LAST_ADMIN, /* c0000069 (STATUS_LAST_ADMIN) */ + ERROR_INVALID_PASSWORD, /* c000006a (STATUS_WRONG_PASSWORD) */ + ERROR_ILL_FORMED_PASSWORD, /* c000006b (STATUS_ILL_FORMED_PASSWORD) */ + ERROR_PASSWORD_RESTRICTION, /* c000006c (STATUS_PASSWORD_RESTRICTION) */ + ERROR_LOGON_FAILURE, /* c000006d (STATUS_LOGON_FAILURE) */ + ERROR_ACCOUNT_RESTRICTION, /* c000006e (STATUS_ACCOUNT_RESTRICTION) */ + ERROR_INVALID_LOGON_HOURS, /* c000006f (STATUS_INVALID_LOGON_HOURS) */ + ERROR_INVALID_WORKSTATION, /* c0000070 (STATUS_INVALID_WORKSTATION) */ + ERROR_PASSWORD_EXPIRED, /* c0000071 (STATUS_PASSWORD_EXPIRED) */ + ERROR_ACCOUNT_DISABLED, /* c0000072 (STATUS_ACCOUNT_DISABLED) */ + ERROR_NONE_MAPPED, /* c0000073 (STATUS_NONE_MAPPED) */ + ERROR_TOO_MANY_LUIDS_REQUESTED, /* c0000074 (STATUS_TOO_MANY_LUIDS_REQUESTED) */ + ERROR_LUIDS_EXHAUSTED, /* c0000075 (STATUS_LUIDS_EXHAUSTED) */ + ERROR_INVALID_SUB_AUTHORITY, /* c0000076 (STATUS_INVALID_SUB_AUTHORITY) */ + ERROR_INVALID_ACL, /* c0000077 (STATUS_INVALID_ACL) */ + ERROR_INVALID_SID, /* c0000078 (STATUS_INVALID_SID) */ + ERROR_INVALID_SECURITY_DESCR, /* c0000079 (STATUS_INVALID_SECURITY_DESCR) */ + ERROR_PROC_NOT_FOUND, /* c000007a (STATUS_PROCEDURE_NOT_FOUND) */ + ERROR_BAD_EXE_FORMAT, /* c000007b (STATUS_INVALID_IMAGE_FORMAT) */ + ERROR_NO_TOKEN, /* c000007c (STATUS_NO_TOKEN) */ + ERROR_BAD_INHERITANCE_ACL, /* c000007d (STATUS_BAD_INHERITANCE_ACL) */ + ERROR_NOT_LOCKED, /* c000007e (STATUS_RANGE_NOT_LOCKED) */ + ERROR_DISK_FULL, /* c000007f (STATUS_DISK_FULL) */ + ERROR_SERVER_DISABLED, /* c0000080 (STATUS_SERVER_DISABLED) */ + ERROR_SERVER_NOT_DISABLED, /* c0000081 (STATUS_SERVER_NOT_DISABLED) */ + ERROR_TOO_MANY_NAMES, /* c0000082 (STATUS_TOO_MANY_GUIDS_REQUESTED) */ + ERROR_NO_MORE_ITEMS, /* c0000083 (STATUS_GUIDS_EXHAUSTED) */ + ERROR_INVALID_ID_AUTHORITY, /* c0000084 (STATUS_INVALID_ID_AUTHORITY) */ + ERROR_NO_MORE_ITEMS, /* c0000085 (STATUS_AGENTS_EXHAUSTED) */ + ERROR_LABEL_TOO_LONG, /* c0000086 (STATUS_INVALID_VOLUME_LABEL) */ + ERROR_OUTOFMEMORY, /* c0000087 (STATUS_SECTION_NOT_EXTENDED) */ + ERROR_INVALID_ADDRESS, /* c0000088 (STATUS_NOT_MAPPED_DATA) */ + ERROR_RESOURCE_DATA_NOT_FOUND, /* c0000089 (STATUS_RESOURCE_DATA_NOT_FOUND) */ + ERROR_RESOURCE_TYPE_NOT_FOUND, /* c000008a (STATUS_RESOURCE_TYPE_NOT_FOUND) */ + ERROR_RESOURCE_NAME_NOT_FOUND, /* c000008b (STATUS_RESOURCE_NAME_NOT_FOUND) */ + 0, /* c000008c (STATUS_ARRAY_BOUNDS_EXCEEDED) */ + 0, /* c000008d (STATUS_FLOAT_DENORMAL_OPERAND) */ + 0, /* c000008e (STATUS_FLOAT_DIVIDE_BY_ZERO) */ + 0, /* c000008f (STATUS_FLOAT_INEXACT_RESULT) */ + 0, /* c0000090 (STATUS_FLOAT_INVALID_OPERATION) */ + 0, /* c0000091 (STATUS_FLOAT_OVERFLOW) */ + 0, /* c0000092 (STATUS_FLOAT_STACK_CHECK) */ + 0, /* c0000093 (STATUS_FLOAT_UNDERFLOW) */ + 0, /* c0000094 (STATUS_INTEGER_DIVIDE_BY_ZERO) */ + ERROR_ARITHMETIC_OVERFLOW, /* c0000095 (STATUS_INTEGER_OVERFLOW) */ + 0, /* c0000096 (STATUS_PRIVILEGED_INSTRUCTION) */ + ERROR_NOT_ENOUGH_MEMORY, /* c0000097 (STATUS_TOO_MANY_PAGING_FILES) */ + ERROR_FILE_INVALID, /* c0000098 (STATUS_FILE_INVALID) */ + ERROR_ALLOTTED_SPACE_EXCEEDED, /* c0000099 (STATUS_ALLOTTED_SPACE_EXCEEDED) */ + ERROR_NO_SYSTEM_RESOURCES, /* c000009a (STATUS_INSUFFICIENT_RESOURCES) */ + ERROR_PATH_NOT_FOUND, /* c000009b (STATUS_DFS_EXIT_PATH_FOUND) */ + ERROR_CRC, /* c000009c (STATUS_DEVICE_DATA_ERROR) */ + ERROR_NOT_READY, /* c000009d (STATUS_DEVICE_NOT_CONNECTED) */ + ERROR_NOT_READY, /* c000009e (STATUS_DEVICE_POWER_FAILURE) */ + ERROR_INVALID_ADDRESS, /* c000009f (STATUS_FREE_VM_NOT_AT_BASE) */ + ERROR_INVALID_ADDRESS, /* c00000a0 (STATUS_MEMORY_NOT_ALLOCATED) */ + ERROR_WORKING_SET_QUOTA, /* c00000a1 (STATUS_WORKING_SET_QUOTA) */ + ERROR_WRITE_PROTECT, /* c00000a2 (STATUS_MEDIA_WRITE_PROTECTED) */ + ERROR_NOT_READY, /* c00000a3 (STATUS_DEVICE_NOT_READY) */ + ERROR_INVALID_GROUP_ATTRIBUTES, /* c00000a4 (STATUS_INVALID_GROUP_ATTRIBUTES) */ + ERROR_BAD_IMPERSONATION_LEVEL, /* c00000a5 (STATUS_BAD_IMPERSONATION_LEVEL) */ + ERROR_CANT_OPEN_ANONYMOUS, /* c00000a6 (STATUS_CANT_OPEN_ANONYMOUS) */ + ERROR_BAD_VALIDATION_CLASS, /* c00000a7 (STATUS_BAD_VALIDATION_CLASS) */ + ERROR_BAD_TOKEN_TYPE, /* c00000a8 (STATUS_BAD_TOKEN_TYPE)*/ + ERROR_MR_MID_NOT_FOUND, /* c00000a9 (STATUS_BAD_MASTER_BOOT_RECORD) */ + ERROR_MR_MID_NOT_FOUND, /* c00000aa (STATUS_INSTRUCTION_MISALIGNMENT) */ + ERROR_PIPE_BUSY, /* c00000ab (STATUS_INSTANCE_NOT_AVAILABLE) */ + ERROR_PIPE_BUSY, /* c00000ac (STATUS_PIPE_NOT_AVAILABLE) */ + ERROR_BAD_PIPE, /* c00000ad (STATUS_INVALID_PIPE_STATE) */ + ERROR_PIPE_BUSY, /* c00000ae (STATUS_PIPE_BUSY) */ + ERROR_INVALID_FUNCTION, /* c00000af (STATUS_ILLEGAL_FUNCTION) */ + ERROR_PIPE_NOT_CONNECTED, /* c00000b0 (STATUS_PIPE_DISCONNECTED) */ + ERROR_NO_DATA, /* c00000b1 (STATUS_PIPE_CLOSING) */ + ERROR_PIPE_CONNECTED, /* c00000b2 (STATUS_PIPE_CONNECTED) */ + ERROR_PIPE_LISTENING, /* c00000b3 (STATUS_PIPE_LISTENING) */ + ERROR_BAD_PIPE, /* c00000b4 (STATUS_INVALID_READ_MODE) */ + ERROR_SEM_TIMEOUT, /* c00000b5 (STATUS_IO_TIMEOUT) */ + ERROR_HANDLE_EOF, /* c00000b6 (STATUS_FILE_FORCED_CLOSED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000b7 (STATUS_PROFILING_NOT_STARTED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000b8 (STATUS_PROFILING_NOT_STOPPED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000b9 (STATUS_COULD_NOT_INTERPRET) */ + ERROR_ACCESS_DENIED, /* c00000ba (STATUS_FILE_IS_A_DIRECTORY) */ + ERROR_NOT_SUPPORTED, /* c00000bb (STATUS_NOT_SUPPORTED) */ + ERROR_REM_NOT_LIST, /* c00000bc (STATUS_REMOTE_NOT_LISTENING) */ + ERROR_DUP_NAME, /* c00000bd (STATUS_DUPLICATE_NAME) */ + ERROR_BAD_NETPATH, /* c00000be (STATUS_BAD_NETWORK_PATH) */ + ERROR_NETWORK_BUSY, /* c00000bf (STATUS_NETWORK_BUSY) */ + ERROR_DEV_NOT_EXIST, /* c00000c0 (STATUS_DEVICE_DOES_NOT_EXIST) */ + ERROR_TOO_MANY_CMDS, /* c00000c1 (STATUS_TOO_MANY_COMMANDS) */ + ERROR_ADAP_HDW_ERR, /* c00000c2 (STATUS_ADAPTER_HARDWARE_ERROR) */ + ERROR_BAD_NET_RESP, /* c00000c3 (STATUS_INVALID_NETWORK_RESPONSE) */ + ERROR_UNEXP_NET_ERR, /* c00000c4 (STATUS_UNEXPECTED_NETWORK_ERROR) */ + ERROR_BAD_REM_ADAP, /* c00000c5 (STATUS_BAD_REMOTE_ADAPTER) */ + ERROR_PRINTQ_FULL, /* c00000c6 (STATUS_PRINT_QUEUE_FULL) */ + ERROR_NO_SPOOL_SPACE, /* c00000c7 (STATUS_NO_SPOOL_SPACE) */ + ERROR_PRINT_CANCELLED, /* c00000c8 (STATUS_PRINT_CANCELLED) */ + ERROR_NETNAME_DELETED, /* c00000c9 (STATUS_NETWORK_NAME_DELETED) */ + ERROR_NETWORK_ACCESS_DENIED, /* c00000ca (STATUS_NETWORK_ACCESS_DENIED) */ + ERROR_BAD_DEV_TYPE, /* c00000cb (STATUS_BAD_DEVICE_TYPE) */ + ERROR_BAD_NET_NAME, /* c00000cc (STATUS_BAD_NETWORK_NAME) */ + ERROR_TOO_MANY_NAMES, /* c00000cd (STATUS_TOO_MANY_NAMES) */ + ERROR_TOO_MANY_SESS, /* c00000ce (STATUS_TOO_MANY_SESSIONS) */ + ERROR_SHARING_PAUSED, /* c00000cf (STATUS_SHARING_PAUSED) */ + ERROR_REQ_NOT_ACCEP, /* c00000d0 (STATUS_REQUEST_NOT_ACCEPTED) */ + ERROR_REDIR_PAUSED, /* c00000d1 (STATUS_REDIRECTOR_PAUSED) */ + ERROR_NET_WRITE_FAULT, /* c00000d2 (STATUS_NET_WRITE_FAULT) */ + ERROR_MR_MID_NOT_FOUND, /* c00000d3 (STATUS_PROFILING_AT_LIMIT) */ + ERROR_NOT_SAME_DEVICE, /* c00000d4 (STATUS_NOT_SAME_DEVICE) */ + ERROR_MR_MID_NOT_FOUND, /* c00000d5 (STATUS_FILE_RENAMED) */ + ERROR_VC_DISCONNECTED, /* c00000d6 (STATUS_VIRTUAL_CIRCUIT_CLOSED) */ + ERROR_NO_SECURITY_ON_OBJECT, /* c00000d7 (STATUS_NO_SECURITY_ON_OBJECT) */ + ERROR_MR_MID_NOT_FOUND, /* c00000d8 (STATUS_CANT_WAIT) */ + ERROR_NO_DATA, /* c00000d9 (STATUS_PIPE_EMPTY) */ + ERROR_CANT_ACCESS_DOMAIN_INFO, /* c00000da (STATUS_CANT_ACCESS_DOMAIN_INFO) */ + ERROR_MR_MID_NOT_FOUND, /* c00000db (STATUS_CANT_TERMINATE_SELF) */ + ERROR_INVALID_SERVER_STATE, /* c00000dc (STATUS_INVALID_SERVER_STATE) */ + ERROR_INVALID_DOMAIN_STATE, /* c00000dd (STATUS_INVALID_DOMAIN_STATE) */ + ERROR_INVALID_DOMAIN_ROLE, /* c00000de (STATUS_INVALID_DOMAIN_ROLE) */ + ERROR_NO_SUCH_DOMAIN, /* c00000df (STATUS_NO_SUCH_DOMAIN) */ + ERROR_DOMAIN_EXISTS, /* c00000e0 (STATUS_DOMAIN_EXISTS) */ + ERROR_DOMAIN_LIMIT_EXCEEDED, /* c00000e1 (STATUS_DOMAIN_LIMIT_EXCEEDED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000e2 (STATUS_OPLOCK_NOT_GRANTED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000e3 (STATUS_INVALID_OPLOCK_PROTOCOL) */ + ERROR_INTERNAL_DB_CORRUPTION, /* c00000e4 (STATUS_INTERNAL_DB_CORRUPTION) */ + ERROR_INTERNAL_ERROR, /* c00000e5 (STATUS_INTERNAL_ERROR) */ + ERROR_GENERIC_NOT_MAPPED, /* c00000e6 (STATUS_GENERIC_NOT_MAPPED) */ + ERROR_BAD_DESCRIPTOR_FORMAT, /* c00000e7 (STATUS_BAD_DESCRIPTOR_FORMAT) */ + ERROR_INVALID_USER_BUFFER, /* c00000e8 (STATUS_INVALID_USER_BUFFER) */ + ERROR_MR_MID_NOT_FOUND, /* c00000e9 (STATUS_UNEXPECTED_IO_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c00000ea (STATUS_UNEXPECTED_MM_CREATE_ERR) */ + ERROR_MR_MID_NOT_FOUND, /* c00000eb (STATUS_UNEXPECTED_MM_MAP_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c00000ec (STATUS_UNEXPECTED_MM_EXTEND_ERR) */ + ERROR_NOT_LOGON_PROCESS, /* c00000ed (STATUS_NOT_LOGON_PROCESS) */ + ERROR_LOGON_SESSION_EXISTS, /* c00000ee (STATUS_LOGON_SESSION_EXISTS) */ + ERROR_INVALID_PARAMETER, /* c00000ef (STATUS_INVALID_PARAMETER_1) */ + ERROR_INVALID_PARAMETER, /* c00000f0 (STATUS_INVALID_PARAMETER_2) */ + ERROR_INVALID_PARAMETER, /* c00000f1 (STATUS_INVALID_PARAMETER_3) */ + ERROR_INVALID_PARAMETER, /* c00000f2 (STATUS_INVALID_PARAMETER_4) */ + ERROR_INVALID_PARAMETER, /* c00000f3 (STATUS_INVALID_PARAMETER_5) */ + ERROR_INVALID_PARAMETER, /* c00000f4 (STATUS_INVALID_PARAMETER_6) */ + ERROR_INVALID_PARAMETER, /* c00000f5 (STATUS_INVALID_PARAMETER_7) */ + ERROR_INVALID_PARAMETER, /* c00000f6 (STATUS_INVALID_PARAMETER_8) */ + ERROR_INVALID_PARAMETER, /* c00000f7 (STATUS_INVALID_PARAMETER_9) */ + ERROR_INVALID_PARAMETER, /* c00000f8 (STATUS_INVALID_PARAMETER_10) */ + ERROR_INVALID_PARAMETER, /* c00000f9 (STATUS_INVALID_PARAMETER_11) */ + ERROR_INVALID_PARAMETER, /* c00000fa (STATUS_INVALID_PARAMETER_12) */ + ERROR_PATH_NOT_FOUND, /* c00000fb (STATUS_REDIRECTOR_NOT_STARTED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000fc (STATUS_REDIRECTOR_STARTED) */ + ERROR_STACK_OVERFLOW, /* c00000fd (STATUS_STACK_OVERFLOW) */ + ERROR_NO_SUCH_PACKAGE, /* c00000fe (STATUS_NO_SUCH_PACKAGE) */ + ERROR_MR_MID_NOT_FOUND, /* c00000ff (STATUS_BAD_FUNCTION_TABLE) */ + ERROR_ENVVAR_NOT_FOUND, /* c0000100 (STATUS_VARIABLE_NOT_FOUND) */ + ERROR_DIR_NOT_EMPTY, /* c0000101 (STATUS_DIRECTORY_NOT_EMPTY) */ + ERROR_FILE_CORRUPT, /* c0000102 (STATUS_FILE_CORRUPT_ERROR) */ + ERROR_DIRECTORY, /* c0000103 (STATUS_NOT_A_DIRECTORY) */ + ERROR_BAD_LOGON_SESSION_STATE, /* c0000104 (STATUS_BAD_LOGON_SESSION_STATE) */ + ERROR_LOGON_SESSION_COLLISION, /* c0000105 (STATUS_LOGON_SESSION_COLLISION) */ + ERROR_FILENAME_EXCED_RANGE, /* c0000106 (STATUS_NAME_TOO_LONG) */ + ERROR_MR_MID_NOT_FOUND, /* c0000107 (STATUS_FILES_OPEN) */ + ERROR_DEVICE_IN_USE, /* c0000108 (STATUS_CONNECTION_IN_USE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000109 (STATUS_MESSAGE_NOT_FOUND) */ + ERROR_ACCESS_DENIED, /* c000010a (STATUS_PROCESS_IS_TERMINATING) */ + ERROR_INVALID_LOGON_TYPE, /* c000010b (STATUS_INVALID_LOGON_TYPE) */ + ERROR_MR_MID_NOT_FOUND, /* c000010c (STATUS_NO_GUID_TRANSLATION) */ + ERROR_CANNOT_IMPERSONATE, /* c000010d (STATUS_CANNOT_IMPERSONATE) */ + ERROR_SERVICE_ALREADY_RUNNING, /* c000010e (STATUS_IMAGE_ALREADY_LOADED) */ + ERROR_MR_MID_NOT_FOUND, /* c000010f (STATUS_ABIOS_NOT_PRESENT) */ + ERROR_MR_MID_NOT_FOUND, /* c0000110 (STATUS_ABIOS_LID_NOT_EXIST) */ + ERROR_MR_MID_NOT_FOUND, /* c0000111 (STATUS_ABIOS_LID_ALREADY_OWNED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000112 (STATUS_ABIOS_NOT_LID_OWNER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000113 (STATUS_ABIOS_INVALID_COMMAND) */ + ERROR_MR_MID_NOT_FOUND, /* c0000114 (STATUS_ABIOS_INVALID_LID) */ + ERROR_MR_MID_NOT_FOUND, /* c0000115 (STATUS_ABIOS_SELECTOR_NOT_AVAILABLE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000116 (STATUS_ABIOS_INVALID_SELECTOR) */ + ERROR_MR_MID_NOT_FOUND, /* c0000117 (STATUS_NO_LDT) */ + ERROR_MR_MID_NOT_FOUND, /* c0000118 (STATUS_INVALID_LDT_SIZE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000119 (STATUS_INVALID_LDT_OFFSET) */ + ERROR_MR_MID_NOT_FOUND, /* c000011a (STATUS_INVALID_LDT_DESCRIPTOR) */ + ERROR_BAD_EXE_FORMAT, /* c000011b (STATUS_INVALID_IMAGE_NE_FORMAT) */ + ERROR_RXACT_INVALID_STATE, /* c000011c (STATUS_RXACT_INVALID_STATE) */ + ERROR_RXACT_COMMIT_FAILURE, /* c000011d (STATUS_RXACT_COMMIT_FAILURE) */ + ERROR_FILE_INVALID, /* c000011e (STATUS_MAPPED_FILE_SIZE_ZERO) */ + ERROR_TOO_MANY_OPEN_FILES, /* c000011f (STATUS_TOO_MANY_OPENED_FILES) */ + ERROR_OPERATION_ABORTED, /* c0000120 (STATUS_CANCELLED) */ + ERROR_ACCESS_DENIED, /* c0000121 (STATUS_CANNOT_DELETE) */ + ERROR_INVALID_COMPUTERNAME, /* c0000122 (STATUS_INVALID_COMPUTER_NAME) */ + ERROR_ACCESS_DENIED, /* c0000123 (STATUS_FILE_DELETED) */ + ERROR_SPECIAL_ACCOUNT, /* c0000124 (STATUS_SPECIAL_ACCOUNT) */ + ERROR_SPECIAL_GROUP, /* c0000125 (STATUS_SPECIAL_GROUP) */ + ERROR_SPECIAL_USER, /* c0000126 (STATUS_SPECIAL_USER) */ + ERROR_MEMBERS_PRIMARY_GROUP, /* c0000127 (STATUS_MEMBERS_PRIMARY_GROUP) */ + ERROR_INVALID_HANDLE, /* c0000128 (STATUS_FILE_CLOSED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000129 (STATUS_TOO_MANY_THREADS) */ + ERROR_MR_MID_NOT_FOUND, /* c000012a (STATUS_THREAD_NOT_IN_PROCESS) */ + ERROR_TOKEN_ALREADY_IN_USE, /* c000012b (STATUS_TOKEN_ALREADY_IN_USE) */ + ERROR_MR_MID_NOT_FOUND, /* c000012c (STATUS_PAGEFILE_QUOTA_EXCEEDED) */ + ERROR_COMMITMENT_LIMIT, /* c000012d (STATUS_COMMITMENT_LIMIT) */ + ERROR_BAD_EXE_FORMAT, /* c000012e (STATUS_INVALID_IMAGE_LE_FORMAT) */ + ERROR_BAD_EXE_FORMAT, /* c000012f (STATUS_INVALID_IMAGE_NOT_MZ) */ + ERROR_BAD_EXE_FORMAT, /* c0000130 (STATUS_INVALID_IMAGE_PROTECT) */ + ERROR_BAD_EXE_FORMAT, /* c0000131 (STATUS_INVALID_IMAGE_WIN_16) */ + ERROR_MR_MID_NOT_FOUND, /* c0000132 (STATUS_LOGON_SERVER_CONFLICT) */ + ERROR_MR_MID_NOT_FOUND, /* c0000133 (STATUS_TIME_DIFFERENCE_AT_DC) */ + ERROR_MR_MID_NOT_FOUND, /* c0000134 (STATUS_SYNCHRONIZATION_REQUIRED) */ + ERROR_MOD_NOT_FOUND, /* c0000135 (STATUS_DLL_NOT_FOUND) */ + ERROR_MR_MID_NOT_FOUND, /* c0000136 (STATUS_OPEN_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000137 (STATUS_IO_PRIVILEGE_FAILED) */ + ERROR_INVALID_ORDINAL, /* c0000138 (STATUS_ORDINAL_NOT_FOUND) */ + ERROR_PROC_NOT_FOUND, /* c0000139 (STATUS_ENTRYPOINT_NOT_FOUND) */ + ERROR_MR_MID_NOT_FOUND, /* c000013a (STATUS_CONTROL_C_EXIT) */ + ERROR_NETNAME_DELETED, /* c000013b (STATUS_LOCAL_DISCONNECT) */ + ERROR_NETNAME_DELETED, /* c000013c (STATUS_REMOTE_DISCONNECT) */ + ERROR_REM_NOT_LIST, /* c000013d (STATUS_REMOTE_RESOURCES) */ + ERROR_UNEXP_NET_ERR, /* c000013e (STATUS_LINK_FAILED) */ + ERROR_UNEXP_NET_ERR, /* c000013f (STATUS_LINK_TIMEOUT) */ + ERROR_UNEXP_NET_ERR, /* c0000140 (STATUS_INVALID_CONNECTION) */ + ERROR_UNEXP_NET_ERR, /* c0000141 (STATUS_INVALID_ADDRESS) */ + ERROR_DLL_INIT_FAILED, /* c0000142 (STATUS_DLL_INIT_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000143 (STATUS_MISSING_SYSTEMFILE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000144 (STATUS_UNHANDLED_EXCEPTION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000145 (STATUS_APP_INIT_FAILURE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000146 (STATUS_PAGEFILE_CREATE_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000147 (STATUS_NO_PAGEFILE) */ + ERROR_INVALID_LEVEL, /* c0000148 (STATUS_INVALID_LEVEL) */ + ERROR_INVALID_PASSWORD, /* c0000149 (STATUS_WRONG_PASSWORD_CORE) */ + ERROR_MR_MID_NOT_FOUND, /* c000014a (STATUS_ILLEGAL_FLOAT_CONTEXT) */ + ERROR_BROKEN_PIPE, /* c000014b (STATUS_PIPE_BROKEN) */ + ERROR_BADDB, /* c000014c (STATUS_REGISTRY_CORRUPT) */ + ERROR_REGISTRY_IO_FAILED, /* c000014d (STATUS_REGISTRY_IO_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c000014e (STATUS_NO_EVENT_PAIR) */ + ERROR_UNRECOGNIZED_VOLUME, /* c000014f (STATUS_UNRECOGNIZED_VOLUME) */ + ERROR_SERIAL_NO_DEVICE, /* c0000150 (STATUS_SERIAL_NO_DEVICE_INITED) */ + ERROR_NO_SUCH_ALIAS, /* c0000151 (STATUS_NO_SUCH_ALIAS) */ + ERROR_MEMBER_NOT_IN_ALIAS, /* c0000152 (STATUS_MEMBER_NOT_IN_ALIAS) */ + ERROR_MEMBER_IN_ALIAS, /* c0000153 (STATUS_MEMBER_IN_ALIAS) */ + ERROR_ALIAS_EXISTS, /* c0000154 (STATUS_ALIAS_EXISTS) */ + ERROR_LOGON_NOT_GRANTED, /* c0000155 (STATUS_LOGON_NOT_GRANTED) */ + ERROR_TOO_MANY_SECRETS, /* c0000156 (STATUS_TOO_MANY_SECRETS) */ + ERROR_SECRET_TOO_LONG, /* c0000157 (STATUS_SECRET_TOO_LONG) */ + ERROR_INTERNAL_DB_ERROR, /* c0000158 (STATUS_INTERNAL_DB_ERROR) */ + ERROR_FULLSCREEN_MODE, /* c0000159 (STATUS_FULLSCREEN_MODE) */ + ERROR_TOO_MANY_CONTEXT_IDS, /* c000015a (STATUS_TOO_MANY_CONTEXT_IDS) */ + ERROR_LOGON_TYPE_NOT_GRANTED, /* c000015b (STATUS_LOGON_TYPE_NOT_GRANTED) */ + ERROR_NOT_REGISTRY_FILE, /* c000015c (STATUS_NOT_REGISTRY_FILE) */ + ERROR_NT_CROSS_ENCRYPTION_REQUIRED, /* c000015d (STATUS_NT_CROSS_ENCRYPTION_REQUIRED) */ + ERROR_MR_MID_NOT_FOUND, /* c000015e (STATUS_DOMAIN_CTRLR_CONFIG_ERROR) */ + ERROR_IO_DEVICE, /* c000015f (STATUS_FT_MISSING_MEMBER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000160 (STATUS_ILL_FORMED_SERVICE_ENTRY) */ + ERROR_MR_MID_NOT_FOUND, /* c0000161 (STATUS_ILLEGAL_CHARACTER) */ + ERROR_NO_UNICODE_TRANSLATION, /* c0000162 (STATUS_UNMAPPABLE_CHARACTER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000163 (STATUS_UNDEFINED_CHARACTER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000164 (STATUS_FLOPPY_VOLUME) */ + ERROR_FLOPPY_ID_MARK_NOT_FOUND, /* c0000165 (STATUS_FLOPPY_ID_MARK_NOT_FOUND) */ + ERROR_FLOPPY_WRONG_CYLINDER, /* c0000166 (STATUS_FLOPPY_WRONG_CYLINDER) */ + ERROR_FLOPPY_UNKNOWN_ERROR, /* c0000167 (STATUS_FLOPPY_UNKNOWN_ERROR) */ + ERROR_FLOPPY_BAD_REGISTERS, /* c0000168 (STATUS_FLOPPY_BAD_REGISTERS) */ + ERROR_DISK_RECALIBRATE_FAILED, /* c0000169 (STATUS_DISK_RECALIBRATE_FAILED) */ + ERROR_DISK_OPERATION_FAILED, /* c000016a (STATUS_DISK_OPERATION_FAILED) */ + ERROR_DISK_RESET_FAILED, /* c000016b (STATUS_DISK_RESET_FAILED) */ + ERROR_IRQ_BUSY, /* c000016c (STATUS_SHARED_IRQ_BUSY) */ + ERROR_IO_DEVICE, /* c000016d (STATUS_FT_ORPHANING) */ + ERROR_MR_MID_NOT_FOUND, /* c000016e (STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT) */ + ERROR_MR_MID_NOT_FOUND, /* c000016f */ + ERROR_MR_MID_NOT_FOUND, /* c0000170 */ + ERROR_MR_MID_NOT_FOUND, /* c0000171 */ + ERROR_PARTITION_FAILURE, /* c0000172 (STATUS_PARTITION_FAILURE) */ + ERROR_INVALID_BLOCK_LENGTH, /* c0000173 (STATUS_INVALID_BLOCK_LENGTH) */ + ERROR_DEVICE_NOT_PARTITIONED, /* c0000174 (STATUS_DEVICE_NOT_PARTITIONED) */ + ERROR_UNABLE_TO_LOCK_MEDIA, /* c0000175 (STATUS_UNABLE_TO_LOCK_MEDIA) */ + ERROR_UNABLE_TO_UNLOAD_MEDIA, /* c0000176 (STATUS_UNABLE_TO_UNLOAD_MEDIA) */ + ERROR_EOM_OVERFLOW, /* c0000177 (STATUS_EOM_OVERFLOW) */ + ERROR_NO_MEDIA_IN_DRIVE, /* c0000178 (STATUS_NO_MEDIA) */ + ERROR_MR_MID_NOT_FOUND, /* c0000179 */ + ERROR_NO_SUCH_MEMBER, /* c000017a (STATUS_NO_SUCH_MEMBER) */ + ERROR_INVALID_MEMBER, /* c000017b (STATUS_INVALID_MEMBER) */ + ERROR_KEY_DELETED, /* c000017c (STATUS_KEY_DELETED) */ + ERROR_NO_LOG_SPACE, /* c000017d (STATUS_NO_LOG_SPACE) */ + ERROR_TOO_MANY_SIDS, /* c000017e (STATUS_TOO_MANY_SIDS) */ + ERROR_LM_CROSS_ENCRYPTION_REQUIRED, /* c000017f (STATUS_LM_CROSS_ENCRYPTION_REQUIRED) */ + ERROR_KEY_HAS_CHILDREN, /* c0000180 (STATUS_KEY_HAS_CHILDREN) */ + ERROR_CHILD_MUST_BE_VOLATILE, /* c0000181 (STATUS_CHILD_MUST_BE_VOLATILE) */ + ERROR_INVALID_PARAMETER, /* c0000182 (STATUS_DEVICE_CONFIGURATION_ERROR) */ + ERROR_IO_DEVICE, /* c0000183 (STATUS_DRIVER_INTERNAL_ERROR) */ + ERROR_BAD_COMMAND, /* c0000184 (STATUS_INVALID_DEVICE_STATE) */ + ERROR_IO_DEVICE, /* c0000185 (STATUS_IO_DEVICE_ERROR) */ + ERROR_IO_DEVICE, /* c0000186 (STATUS_DEVICE_PROTOCOL_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c0000187 (STATUS_BACKUP_CONTROLLER) */ + ERROR_LOG_FILE_FULL, /* c0000188 (STATUS_LOG_FILE_FULL) */ + ERROR_WRITE_PROTECT, /* c0000189 (STATUS_TOO_LATE) */ + ERROR_NO_TRUST_LSA_SECRET, /* c000018a (STATUS_NO_TRUST_LSA_SECRET) */ + ERROR_NO_TRUST_SAM_ACCOUNT, /* c000018b (STATUS_NO_TRUST_SAM_ACCOUNT) */ + ERROR_TRUSTED_DOMAIN_FAILURE, /* c000018c (STATUS_TRUSTED_DOMAIN_FAILURE) */ + ERROR_TRUSTED_RELATIONSHIP_FAILURE, /* c000018d (STATUS_TRUSTED_RELATIONSHIP_FAILURE) */ + ERROR_EVENTLOG_FILE_CORRUPT, /* c000018e (STATUS_EVENTLOG_FILE_CORRUPT) */ + ERROR_EVENTLOG_CANT_START, /* c000018f (STATUS_EVENTLOG_CANT_START) */ + ERROR_TRUST_FAILURE, /* c0000190 (STATUS_TRUST_FAILURE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000191 (STATUS_MUTANT_LIMIT_EXCEEDED) */ + ERROR_NETLOGON_NOT_STARTED, /* c0000192 (STATUS_NETLOGON_NOT_STARTED) */ + ERROR_ACCOUNT_EXPIRED, /* c0000193 (STATUS_ACCOUNT_EXPIRED) */ + ERROR_POSSIBLE_DEADLOCK, /* c0000194 (STATUS_POSSIBLE_DEADLOCK) */ + ERROR_SESSION_CREDENTIAL_CONFLICT, /* c0000195 (STATUS_NETWORK_CREDENTIAL_CONFLICT) */ + ERROR_REMOTE_SESSION_LIMIT_EXCEEDED, /* c0000196 (STATUS_REMOTE_SESSION_LIMIT) */ + ERROR_EVENTLOG_FILE_CHANGED, /* c0000197 (STATUS_EVENTLOG_FILE_CHANGED) */ + ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,/* c0000198 (STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT) */ + ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT,/* c0000199 (STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT) */ + ERROR_NOLOGON_SERVER_TRUST_ACCOUNT, /* c000019a (STATUS_NOLOGON_SERVER_TRUST_ACCOUNT) */ + ERROR_DOMAIN_TRUST_INCONSISTENT /* c000019b (STATUS_DOMAIN_TRUST_INCONSISTENT) */ +}; + +static const WORD table_c0000202[109] = +{ + ERROR_NO_USER_SESSION_KEY, /* c0000202 (STATUS_NO_USER_SESSION_KEY) */ + ERROR_UNEXP_NET_ERR, /* c0000203 (STATUS_USER_SESSION_DELETED) */ + ERROR_RESOURCE_LANG_NOT_FOUND, /* c0000204 (STATUS_RESOURCE_LANG_NOT_FOUND) */ + ERROR_NOT_ENOUGH_SERVER_MEMORY, /* c0000205 (STATUS_INSUFF_SERVER_RESOURCES) */ + ERROR_INVALID_USER_BUFFER, /* c0000206 (STATUS_INVALID_BUFFER_SIZE) */ + ERROR_INVALID_NETNAME, /* c0000207 (STATUS_INVALID_ADDRESS_COMPONENT) */ + ERROR_INVALID_NETNAME, /* c0000208 (STATUS_INVALID_ADDRESS_WILDCARD) */ + ERROR_TOO_MANY_NAMES, /* c0000209 (STATUS_TOO_MANY_ADDRESSES) */ + ERROR_DUP_NAME, /* c000020a (STATUS_ADDRESS_ALREADY_EXISTS) */ + ERROR_NETNAME_DELETED, /* c000020b (STATUS_ADDRESS_CLOSED) */ + ERROR_NETNAME_DELETED, /* c000020c (STATUS_CONNECTION_DISCONNECTED) */ + ERROR_NETNAME_DELETED, /* c000020d (STATUS_CONNECTION_RESET) */ + ERROR_TOO_MANY_NAMES, /* c000020e (STATUS_TOO_MANY_NODES) */ + ERROR_UNEXP_NET_ERR, /* c000020f (STATUS_TRANSACTION_ABORTED) */ + ERROR_UNEXP_NET_ERR, /* c0000210 (STATUS_TRANSACTION_TIMED_OUT) */ + ERROR_UNEXP_NET_ERR, /* c0000211 (STATUS_TRANSACTION_NO_RELEASE) */ + ERROR_UNEXP_NET_ERR, /* c0000212 (STATUS_TRANSACTION_NO_MATCH) */ + ERROR_UNEXP_NET_ERR, /* c0000213 (STATUS_TRANSACTION_RESPONDED) */ + ERROR_UNEXP_NET_ERR, /* c0000214 (STATUS_TRANSACTION_INVALID_ID) */ + ERROR_UNEXP_NET_ERR, /* c0000215 (STATUS_TRANSACTION_INVALID_TYPE) */ + ERROR_NOT_SUPPORTED, /* c0000216 (STATUS_NOT_SERVER_SESSION) */ + ERROR_NOT_SUPPORTED, /* c0000217 (STATUS_NOT_CLIENT_SESSION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000218 (STATUS_CANNOT_LOAD_REGISTRY_FILE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000219 */ + ERROR_MR_MID_NOT_FOUND, /* c000021a */ + ERROR_MR_MID_NOT_FOUND, /* c000021b */ + ERROR_NO_BROWSER_SERVERS_FOUND, /* c000021c (STATUS_NO_BROWSER_SERVERS_FOUND) */ + ERROR_MR_MID_NOT_FOUND, /* c000021d */ + ERROR_MR_MID_NOT_FOUND, /* c000021e */ + ERROR_MR_MID_NOT_FOUND, /* c000021f */ + ERROR_MAPPED_ALIGNMENT, /* c0000220 (STATUS_MAPPED_ALIGNMENT) */ + ERROR_BAD_EXE_FORMAT, /* c0000221 (STATUS_IMAGE_CHECKSUM_MISMATCH) */ + ERROR_MR_MID_NOT_FOUND, /* c0000222 */ + ERROR_MR_MID_NOT_FOUND, /* c0000223 */ + ERROR_PASSWORD_MUST_CHANGE, /* c0000224 (STATUS_PASSWORD_MUST_CHANGE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000225 */ + ERROR_MR_MID_NOT_FOUND, /* c0000226 */ + ERROR_MR_MID_NOT_FOUND, /* c0000227 */ + ERROR_MR_MID_NOT_FOUND, /* c0000228 */ + ERROR_MR_MID_NOT_FOUND, /* c0000229 */ + 0, /* c000022a */ + 0, /* c000022b */ + ERROR_MR_MID_NOT_FOUND, /* c000022c */ + ERROR_MR_MID_NOT_FOUND, /* c000022d */ + ERROR_MR_MID_NOT_FOUND, /* c000022e */ + ERROR_MR_MID_NOT_FOUND, /* c000022f */ + ERROR_MR_MID_NOT_FOUND, /* c0000230 */ + ERROR_MR_MID_NOT_FOUND, /* c0000231 */ + ERROR_MR_MID_NOT_FOUND, /* c0000232 */ + ERROR_DOMAIN_CONTROLLER_NOT_FOUND, /* c0000233 */ + ERROR_ACCOUNT_LOCKED_OUT, /* c0000234 */ + ERROR_INVALID_HANDLE, /* c0000235 */ + ERROR_CONNECTION_REFUSED, /* c0000236 */ + ERROR_GRACEFUL_DISCONNECT, /* c0000237 */ + ERROR_ADDRESS_ALREADY_ASSOCIATED, /* c0000238 */ + ERROR_ADDRESS_NOT_ASSOCIATED, /* c0000239 */ + ERROR_CONNECTION_INVALID, /* c000023a */ + ERROR_CONNECTION_ACTIVE, /* c000023b */ + ERROR_NETWORK_UNREACHABLE, /* c000023c */ + ERROR_HOST_UNREACHABLE, /* c000023d */ + ERROR_PROTOCOL_UNREACHABLE, /* c000023e */ + ERROR_PORT_UNREACHABLE, /* c000023f */ + ERROR_REQUEST_ABORTED, /* c0000240 */ + ERROR_CONNECTION_ABORTED, /* c0000241 */ + ERROR_MR_MID_NOT_FOUND, /* c0000242 */ + ERROR_USER_MAPPED_FILE, /* c0000243 */ + ERROR_MR_MID_NOT_FOUND, /* c0000244 */ + ERROR_MR_MID_NOT_FOUND, /* c0000245 */ + ERROR_CONNECTION_COUNT_LIMIT, /* c0000246 */ + ERROR_LOGIN_TIME_RESTRICTION, /* c0000247 */ + ERROR_LOGIN_WKSTA_RESTRICTION, /* c0000248 */ + ERROR_BAD_EXE_FORMAT, /* c0000249 */ + ERROR_MR_MID_NOT_FOUND, /* c000024a */ + ERROR_MR_MID_NOT_FOUND, /* c000024b */ + ERROR_MR_MID_NOT_FOUND, /* c000024c */ + ERROR_MR_MID_NOT_FOUND, /* c000024d */ + ERROR_MR_MID_NOT_FOUND, /* c000024e */ + ERROR_MR_MID_NOT_FOUND, /* c000024f */ + ERROR_MR_MID_NOT_FOUND, /* c0000250 */ + ERROR_MR_MID_NOT_FOUND, /* c0000251 */ + ERROR_MR_MID_NOT_FOUND, /* c0000252 */ + ERROR_INTERNAL_ERROR, /* c0000253 */ + ERROR_MR_MID_NOT_FOUND, /* c0000254 */ + ERROR_MR_MID_NOT_FOUND, /* c0000255 */ + ERROR_MR_MID_NOT_FOUND, /* c0000256 */ + ERROR_HOST_UNREACHABLE, /* c0000257 */ + ERROR_MR_MID_NOT_FOUND, /* c0000258 */ + ERROR_LICENSE_QUOTA_EXCEEDED, /* c0000259 */ + ERROR_MR_MID_NOT_FOUND, /* c000025a */ + ERROR_MR_MID_NOT_FOUND, /* c000025b */ + ERROR_MR_MID_NOT_FOUND, /* c000025c */ + ERROR_MR_MID_NOT_FOUND, /* c000025d */ + ERROR_SERVICE_DISABLED, /* c000025e */ + ERROR_MR_MID_NOT_FOUND, /* c000025f */ + ERROR_MR_MID_NOT_FOUND, /* c0000260 */ + ERROR_MR_MID_NOT_FOUND, /* c0000261 */ + ERROR_INVALID_ORDINAL, /* c0000262 */ + ERROR_PROC_NOT_FOUND, /* c0000263 */ + ERROR_NOT_OWNER, /* c0000264 */ + ERROR_TOO_MANY_LINKS, /* c0000265 */ + ERROR_MR_MID_NOT_FOUND, /* c0000266 */ + ERROR_MR_MID_NOT_FOUND, /* c0000267 */ + ERROR_MR_MID_NOT_FOUND, /* c0000268 */ + ERROR_MR_MID_NOT_FOUND, /* c0000269 */ + ERROR_MR_MID_NOT_FOUND, /* c000026a */ + ERROR_MR_MID_NOT_FOUND, /* c000026b */ + ERROR_MR_MID_NOT_FOUND, /* c000026c */ + ERROR_MR_MID_NOT_FOUND, /* c000026d */ + ERROR_NOT_READY /* c000026e (STATUS_VOLUME_DISMOUNTED) */ +}; + +static const WORD table_c0020001[88] = +{ + RPC_S_INVALID_STRING_BINDING, /* c0020001 (RPC_NT_INVALID_STRING_BINDING) */ + RPC_S_WRONG_KIND_OF_BINDING, /* c0020002 (RPC_NT_WRONG_KIND_OF_BINDING) */ + ERROR_INVALID_HANDLE, /* c0020003 (RPC_NT_INVALID_BINDING) */ + RPC_S_PROTSEQ_NOT_SUPPORTED, /* c0020004 (RPC_NT_PROTSEQ_NOT_SUPPORTED) */ + RPC_S_INVALID_RPC_PROTSEQ, /* c0020005 (RPC_NT_INVALID_RPC_PROTSEQ) */ + RPC_S_INVALID_STRING_UUID, /* c0020006 (RPC_NT_INVALID_STRING_UUID) */ + RPC_S_INVALID_ENDPOINT_FORMAT, /* c0020007 (RPC_NT_INVALID_ENDPOINT_FORMAT) */ + RPC_S_INVALID_NET_ADDR, /* c0020008 (RPC_NT_INVALID_NET_ADDR) */ + RPC_S_NO_ENDPOINT_FOUND, /* c0020009 (RPC_NT_NO_ENDPOINT_FOUND) */ + RPC_S_INVALID_TIMEOUT, /* c002000a (RPC_NT_INVALID_TIMEOUT) */ + RPC_S_OBJECT_NOT_FOUND, /* c002000b (RPC_NT_OBJECT_NOT_FOUND) */ + RPC_S_ALREADY_REGISTERED, /* c002000c (RPC_NT_ALREADY_REGISTERED) */ + RPC_S_TYPE_ALREADY_REGISTERED, /* c002000d (RPC_NT_TYPE_ALREADY_REGISTERED) */ + RPC_S_ALREADY_LISTENING, /* c002000e (RPC_NT_ALREADY_LISTENING) */ + RPC_S_NO_PROTSEQS_REGISTERED, /* c002000f (RPC_NT_NO_PROTSEQS_REGISTERED) */ + RPC_S_NOT_LISTENING, /* c0020010 (RPC_NT_NOT_LISTENING) */ + RPC_S_UNKNOWN_MGR_TYPE, /* c0020011 (RPC_NT_UNKNOWN_MGR_TYPE) */ + RPC_S_UNKNOWN_IF, /* c0020012 (RPC_NT_UNKNOWN_IF) */ + RPC_S_NO_BINDINGS, /* c0020013 (RPC_NT_NO_BINDINGS) */ + RPC_S_NO_PROTSEQS, /* c0020014 (RPC_NT_NO_PROTSEQS) */ + RPC_S_CANT_CREATE_ENDPOINT, /* c0020015 (RPC_NT_CANT_CREATE_ENDPOINT) */ + RPC_S_OUT_OF_RESOURCES, /* c0020016 (RPC_NT_OUT_OF_RESOURCES) */ + RPC_S_SERVER_UNAVAILABLE, /* c0020017 (RPC_NT_SERVER_UNAVAILABLE) */ + RPC_S_SERVER_TOO_BUSY, /* c0020018 (RPC_NT_SERVER_TOO_BUSY) */ + RPC_S_INVALID_NETWORK_OPTIONS, /* c0020019 (RPC_NT_INVALID_NETWORK_OPTIONS) */ + RPC_S_NO_CALL_ACTIVE, /* c002001a (RPC_NT_NO_CALL_ACTIVE) */ + RPC_S_CALL_FAILED, /* c002001b (RPC_NT_CALL_FAILED) */ + RPC_S_CALL_FAILED_DNE, /* c002001c (RPC_NT_CALL_FAILED_DNE) */ + RPC_S_PROTOCOL_ERROR, /* c002001d (RPC_NT_PROTOCOL_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c002001e */ + RPC_S_UNSUPPORTED_TRANS_SYN, /* c002001f (RPC_NT_UNSUPPORTED_TRANS_SYN) */ + ERROR_MR_MID_NOT_FOUND, /* c0020020 */ + RPC_S_UNSUPPORTED_TYPE, /* c0020021 (RPC_NT_UNSUPPORTED_TYPE) */ + RPC_S_INVALID_TAG, /* c0020022 (RPC_NT_INVALID_TAG) */ + RPC_S_INVALID_BOUND, /* c0020023 (RPC_NT_INVALID_BOUND) */ + RPC_S_NO_ENTRY_NAME, /* c0020024 (RPC_NT_NO_ENTRY_NAME) */ + RPC_S_INVALID_NAME_SYNTAX, /* c0020025 (RPC_NT_INVALID_NAME_SYNTAX) */ + RPC_S_UNSUPPORTED_NAME_SYNTAX, /* c0020026 (RPC_NT_UNSUPPORTED_NAME_SYNTAX) */ + ERROR_MR_MID_NOT_FOUND, /* c0020027 */ + RPC_S_UUID_NO_ADDRESS, /* c0020028 (RPC_NT_UUID_NO_ADDRESS) */ + RPC_S_DUPLICATE_ENDPOINT, /* c0020029 (RPC_NT_DUPLICATE_ENDPOINT) */ + RPC_S_UNKNOWN_AUTHN_TYPE, /* c002002a (RPC_NT_UNKNOWN_AUTHN_TYPE) */ + RPC_S_MAX_CALLS_TOO_SMALL, /* c002002b (RPC_NT_MAX_CALLS_TOO_SMALL) */ + RPC_S_STRING_TOO_LONG, /* c002002c (RPC_NT_STRING_TOO_LONG) */ + RPC_S_PROTSEQ_NOT_FOUND, /* c002002d (RPC_NT_PROTSEQ_NOT_FOUND) */ + RPC_S_PROCNUM_OUT_OF_RANGE, /* c002002e (RPC_NT_PROCNUM_OUT_OF_RANGE) */ + RPC_S_BINDING_HAS_NO_AUTH, /* c002002f (RPC_NT_BINDING_HAS_NO_AUTH) */ + RPC_S_UNKNOWN_AUTHN_SERVICE, /* c0020030 (RPC_NT_UNKNOWN_AUTHN_SERVICE) */ + RPC_S_UNKNOWN_AUTHN_LEVEL, /* c0020031 (RPC_NT_UNKNOWN_AUTHN_LEVEL) */ + RPC_S_INVALID_AUTH_IDENTITY, /* c0020032 (RPC_NT_INVALID_AUTH_IDENTITY) */ + RPC_S_UNKNOWN_AUTHZ_SERVICE, /* c0020033 (RPC_NT_UNKNOWN_AUTHZ_SERVICE) */ + EPT_S_INVALID_ENTRY, /* c0020034 (EPT_NT_INVALID_ENTRY) */ + EPT_S_CANT_PERFORM_OP, /* c0020035 (EPT_NT_CANT_PERFORM_OP) */ + EPT_S_NOT_REGISTERED, /* c0020036 (EPT_NT_NOT_REGISTERED) */ + RPC_S_NOTHING_TO_EXPORT, /* c0020037 (RPC_NT_NOTHING_TO_EXPORT) */ + RPC_S_INCOMPLETE_NAME, /* c0020038 (RPC_NT_INCOMPLETE_NAME) */ + RPC_S_INVALID_VERS_OPTION, /* c0020039 (RPC_NT_INVALID_VERS_OPTION) */ + RPC_S_NO_MORE_MEMBERS, /* c002003a (RPC_NT_NO_MORE_MEMBERS) */ + RPC_S_NOT_ALL_OBJS_UNEXPORTED, /* c002003b (RPC_NT_NOT_ALL_OBJS_UNEXPORTED) */ + RPC_S_INTERFACE_NOT_FOUND, /* c002003c (RPC_NT_INTERFACE_NOT_FOUND) */ + RPC_S_ENTRY_ALREADY_EXISTS, /* c002003d (RPC_NT_ENTRY_ALREADY_EXISTS) */ + RPC_S_ENTRY_NOT_FOUND, /* c002003e (RPC_NT_ENTRY_NOT_FOUND) */ + RPC_S_NAME_SERVICE_UNAVAILABLE, /* c002003f (RPC_NT_NAME_SERVICE_UNAVAILABLE) */ + RPC_S_INVALID_NAF_ID, /* c0020040 (RPC_NT_INVALID_NAF_ID) */ + RPC_S_CANNOT_SUPPORT, /* c0020041 (RPC_NT_CANNOT_SUPPORT) */ + RPC_S_NO_CONTEXT_AVAILABLE, /* c0020042 (RPC_NT_NO_CONTEXT_AVAILABLE) */ + RPC_S_INTERNAL_ERROR, /* c0020043 (RPC_NT_INTERNAL_ERROR) */ + RPC_S_ZERO_DIVIDE, /* c0020044 (RPC_NT_ZERO_DIVIDE) */ + RPC_S_ADDRESS_ERROR, /* c0020045 (RPC_NT_ADDRESS_ERROR) */ + RPC_S_FP_DIV_ZERO, /* c0020046 (RPC_NT_FP_DIV_ZERO) */ + RPC_S_FP_UNDERFLOW, /* c0020047 (RPC_NT_FP_UNDERFLOW) */ + RPC_S_FP_OVERFLOW, /* c0020048 (RPC_NT_FP_OVERFLOW) */ + RPC_S_CALL_IN_PROGRESS, /* c0020049 (RPC_NT_CALL_IN_PROGRESS) */ + RPC_S_NO_MORE_BINDINGS, /* c002004a (RPC_NT_NO_MORE_BINDINGS) */ + RPC_S_GROUP_MEMBER_NOT_FOUND, /* c002004b (RPC_NT_GROUP_MEMBER_NOT_FOUND) */ + EPT_S_CANT_CREATE, /* c002004c (EPT_NT_CANT_CREATE) */ + RPC_S_INVALID_OBJECT, /* c002004d (RPC_NT_INVALID_OBJECT) */ + ERROR_MR_MID_NOT_FOUND, /* c002004e */ + RPC_S_NO_INTERFACES, /* c002004f */ + RPC_S_CALL_CANCELLED, /* c0020050 */ + RPC_S_BINDING_INCOMPLETE, /* c0020051 */ + RPC_S_COMM_FAILURE, /* c0020052 */ + RPC_S_UNSUPPORTED_AUTHN_LEVEL, /* c0020053 */ + RPC_S_NO_PRINC_NAME, /* c0020054 */ + RPC_S_NOT_RPC_ERROR, /* c0020055 */ + ERROR_MR_MID_NOT_FOUND, /* c0020056 */ + RPC_S_SEC_PKG_ERROR, /* c0020057 */ + RPC_S_NOT_CANCELLED /* c0020058 */ +}; + +static const WORD table_c0030001[12] = +{ + RPC_X_NO_MORE_ENTRIES, /* c0030001 (RPC_NT_NO_MORE_ENTRIES) */ + RPC_X_SS_CHAR_TRANS_OPEN_FAIL, /* c0030002 (RPC_NT_SS_CHAR_TRANS_OPEN_FAIL) */ + RPC_X_SS_CHAR_TRANS_SHORT_FILE, /* c0030003 (RPC_NT_SS_CHAR_TRANS_SHORT_FILE) */ + ERROR_INVALID_HANDLE, /* c0030004 (RPC_NT_SS_IN_NULL_CONTEXT) */ + ERROR_INVALID_HANDLE, /* c0030005 */ + RPC_X_SS_CONTEXT_DAMAGED, /* c0030006 (RPC_NT_SS_CONTEXT_DAMAGED) */ + RPC_X_SS_HANDLES_MISMATCH, /* c0030007 (RPC_NT_SS_HANDLES_MISMATCH) */ + RPC_X_SS_CANNOT_GET_CALL_HANDLE, /* c0030008 (RPC_NT_SS_CANNOT_GET_CALL_HANDLE) */ + RPC_X_NULL_REF_POINTER, /* c0030009 (RPC_NT_NULL_REF_POINTER) */ + RPC_X_ENUM_VALUE_OUT_OF_RANGE, /* c003000a (RPC_NT_ENUM_VALUE_OUT_OF_RANGE) */ + RPC_X_BYTE_COUNT_TOO_SMALL, /* c003000b (RPC_NT_BYTE_COUNT_TOO_SMALL) */ + RPC_X_BAD_STUB_DATA /* c003000c (RPC_NT_BAD_STUB_DATA) */ +}; + +static const WORD table_c0030059[6] = +{ + RPC_X_INVALID_ES_ACTION, /* c0030059 */ + RPC_X_WRONG_ES_VERSION, /* c003005a */ + RPC_X_WRONG_STUB_VERSION, /* c003005b */ + RPC_X_INVALID_PIPE_OBJECT, /* c003005c */ + RPC_X_WRONG_PIPE_ORDER, /* c003005d */ + RPC_X_WRONG_PIPE_VERSION /* c003005e */ +}; + +static const ERROR_TABLE ErrorTable[] = +{ + { 0x00000103, 0x0000010e, table_00000103 }, + { 0x40000002, 0x4000000e, table_40000002 }, + { 0x40020056, 0x40020057, table_40020056 }, + { 0x400200af, 0x400200b0, table_400200af }, + { 0x80000001, 0x80000027, table_80000001 }, + { 0x80090300, 0x80090317, table_80090300 }, + { 0xc0000001, 0xc000019c, table_c0000001 }, + { 0xc0000202, 0xc000026f, table_c0000202 }, + { 0xc0020001, 0xc0020059, table_c0020001 }, + { 0xc0030001, 0xc003000d, table_c0030001 }, + { 0xc0030059, 0xc003005f, table_c0030059 }, + { 0, 0, 0 } /* last entry */ +}; + + +#if 0 +/* currently not assigned values */ + ERROR_ARENA_TRASHED +STATUS_HANDLE_NOT_WAITABLE ERROR_INVALID_HANDLE; +STATUS_LOCK_NOT_GRANTED ERROR_LOCK_VIOLATION; + +RPC_NT_SS_CONTEXT_MISMATCH ERROR_INVALID_HANDLE +#endif + + +/* FUNCTIONS ***************************************************************/ + +VOID +STDCALL +RtlAssert ( + PVOID FailedAssertion, + PVOID FileName, + ULONG LineNumber, + PCHAR Message + ) +{ + DbgPrint ("Assertion \'%s\' failed at %s line %d: %s\n", + (PCHAR)FailedAssertion, + (PCHAR)FileName, + LineNumber, + Message); +} + + +/********************************************************************** + * NAME PRIVATE + * RtlNtStatusToDosErrorNoTeb + * + * DESCRIPTION + * Convert an Executive status ID into a DOS error number + * (winerror.h). + * + * ARGUMENTS + * Status The Executive status ID to convert. + * + * RETURN VALUE + * dos error as in winerror.h + * + * REMARK + * RtlNtStatusToDosErrorNoTeb() does the real work. + */ +DWORD STDCALL +RtlNtStatusToDosErrorNoTeb(NTSTATUS Status) +{ + PERROR_TABLE Table = (PERROR_TABLE)ErrorTable; + + if (!Status || (Status & 0x20000000)) + return Status; + + /* 0xd... is equivalent to 0xc... */ + if ((Status & 0xf0000000) == 0xd0000000) + Status &= ~0x10000000; + + while (Table->Start) + { + if (Status < Table->Start) + break; + + if (Status < Table->End) + { + DWORD ret = Table->Table[Status - Table->Start]; + if (!ret) + ret = Status; /* 0 means 1:1 mapping */ + else if (ret == ERROR_MR_MID_NOT_FOUND) + { + DbgPrint("RTL: RtlNtStatusToDosErrorNoTeb(0x%lx): no valid W32 error mapping\n", Status); + } + return ret; + } + Table++; + } + + /* now some special cases */ + if (HIWORD(Status) == 0xc001) + return LOWORD(Status); + if (HIWORD(Status) == 0x8007) + return LOWORD(Status); + + DbgPrint("RTL: RtlNtStatusToDosErrorNoTeb(0x%lx): no valid W32 error mapping\n", Status); + return ERROR_MR_MID_NOT_FOUND; +} + + +/********************************************************************** + * NAME EXPORTED + * RtlNtStatusToDosError + * + * DESCRIPTION + * Convert an Executive status ID into a DOS error number + * (winerror.h). + * + * ARGUMENTS + * Status The Executive status ID to convert. + * + * RETURN VALUE + * dos error as in winerror.h + * + * REMARK + * RtlNtStatusToDosErrorNoTeb() does the real work. + */ +DWORD STDCALL +RtlNtStatusToDosError(NTSTATUS Status) +{ + PTEB Teb = NtCurrentTeb(); + + if (NULL != Teb) + { + Teb->LastStatusValue = Status; + } + return RtlNtStatusToDosErrorNoTeb(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * RtlNtStatusToPsxErrno + * + * DESCRIPTION + * Convert an Executive status ID into a POSIX error number + * (errno.h). + * + * NOTE + * Not present in the legacy WNT (a ReactOS extension to support + * the POSIX+ subsystem). + * + * ARGUMENTS + * Status The Executive status ID to convert. + * + * RETURN VALUE + * errno as in errno.h + * + * REVISIONS + * 1999-11-30 ea + */ +INT STDCALL +RtlNtStatusToPsxErrno(IN NTSTATUS Status) +{ +#if 0 + switch (Status) + { + } +#endif + return -1; /* generic POSIX error */ +} + +/* EOF */ diff --git a/lib/ntdll/rtl/exception.c b/lib/ntdll/rtl/exception.c new file mode 100644 index 0000000..f56caac --- /dev/null +++ b/lib/ntdll/rtl/exception.c @@ -0,0 +1,57 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User-mode exception support + * FILE: lib/ntdll/rtl/exception.c + * PROGRAMER: David Welch + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context); + +VOID STDCALL +KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context) +{ + EXCEPTION_RECORD NestedExceptionRecord; + NTSTATUS Status; + + DPRINT("KiUserExceptionDispatcher()\n"); + + if (RtlpDispatchException(ExceptionRecord, Context) != ExceptionContinueExecution) + { + Status = NtContinue(Context, FALSE); + } + else + { + Status = NtRaiseException(ExceptionRecord, Context, FALSE); + } + + NestedExceptionRecord.ExceptionCode = Status; + NestedExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + NestedExceptionRecord.ExceptionRecord = ExceptionRecord; + NestedExceptionRecord.NumberParameters = Status; + + RtlRaiseException(&NestedExceptionRecord); +} + +VOID STDCALL +RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) +{ + DbgPrint("RtlRaiseException()"); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/handle.c b/lib/ntdll/rtl/handle.c new file mode 100644 index 0000000..cb07599 --- /dev/null +++ b/lib/ntdll/rtl/handle.c @@ -0,0 +1,168 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Handle table + * FILE: lib/ntdll/rtl/handle.c + * PROGRAMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +RtlInitializeHandleTable(ULONG TableSize, + ULONG HandleSize, + PRTL_HANDLE_TABLE HandleTable) +{ + /* initialize handle table */ + memset(HandleTable, + 0, + sizeof(RTL_HANDLE_TABLE)); + HandleTable->TableSize = TableSize; + HandleTable->HandleSize = HandleSize; +} + + +VOID STDCALL +RtlDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable) +{ + PVOID ArrayPointer; + ULONG ArraySize; + + /* free handle array */ + ArrayPointer = (PVOID)HandleTable->Handles; + ArraySize = (ULONG)HandleTable->Limit - (ULONG)HandleTable->Handles; + NtFreeVirtualMemory(NtCurrentProcess(), + &ArrayPointer, + &ArraySize, + MEM_RELEASE); +} + + +PRTL_HANDLE STDCALL +RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable, + PULONG Index) +{ + RTL_HANDLE **pp_new,**pph,*ph; + NTSTATUS Status; + PRTL_HANDLE retval; + PVOID ArrayPointer; + ULONG ArraySize; + + pp_new = &HandleTable->FirstFree; + + if (HandleTable->FirstFree == NULL) + { + /* no free handle available */ + if (HandleTable->LastUsed == NULL) + { + /* allocate handle array */ + ArraySize = HandleTable->HandleSize * HandleTable->TableSize; + ArrayPointer = NULL; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID*)&ArrayPointer, + 0, + &ArraySize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + return NULL; + + /* update handle array pointers */ + HandleTable->Handles = (PRTL_HANDLE)ArrayPointer; + HandleTable->Limit = (PRTL_HANDLE)(ArrayPointer + ArraySize); + HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer; + } + + /* build free list in handle array */ + ph = HandleTable->LastUsed; + pph = pp_new; + while (ph < HandleTable->Limit) + { + *pph = ph; + pph = &ph->Next; + ph = (PRTL_HANDLE)((ULONG)ph + HandleTable->HandleSize); + } + *pph = 0; + } + + /* remove handle from free list */ + retval = *pp_new; + *pp_new = retval->Next; + retval->Next = NULL; + + if (Index) + *Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / HandleTable->HandleSize; + + return retval; +} + + +BOOLEAN STDCALL +RtlFreeHandle(PRTL_HANDLE_TABLE HandleTable, + PRTL_HANDLE Handle) +{ + /* check if handle is valid */ + if (RtlIsValidHandle(HandleTable, Handle)) + return FALSE; + + /* clear handle */ + memset(Handle, 0, HandleTable->HandleSize); + + /* add handle to free list */ + Handle->Next = HandleTable->FirstFree; + HandleTable->FirstFree = Handle; + + return TRUE; +} + + +BOOLEAN STDCALL +RtlIsValidHandle(PRTL_HANDLE_TABLE HandleTable, + PRTL_HANDLE Handle) +{ + if ((HandleTable != NULL) + && (Handle != NULL) + && (Handle >= HandleTable->Handles) + && (Handle < HandleTable->Limit)) + return TRUE; + return FALSE; +} + + +BOOLEAN STDCALL +RtlIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable, + PRTL_HANDLE *Handle, + ULONG Index) +{ + PRTL_HANDLE InternalHandle; + + DPRINT("RtlIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index); + + if (HandleTable == NULL) + return FALSE; + + DPRINT("Handles %p HandleSize %x\n", + HandleTable->Handles, HandleTable->HandleSize); + + InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + (HandleTable->HandleSize * Index)); + if (RtlIsValidHandle(HandleTable, InternalHandle) == FALSE) + return FALSE; + + DPRINT("InternalHandle %p\n", InternalHandle); + + if (Handle != NULL) + *Handle = InternalHandle; + + return TRUE; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/heap.c b/lib/ntdll/rtl/heap.c new file mode 100644 index 0000000..a2f5d36 --- /dev/null +++ b/lib/ntdll/rtl/heap.c @@ -0,0 +1,1632 @@ +/* + * Win32 heap functions + * + * Copyright 1996 Alexandre Julliard + * Copyright 1998 Ulrich Weigand + */ + + +/* Note: the heap data structures are based on what Pietrek describes in his + * book 'Windows 95 System Programming Secrets'. The layout is not exactly + * the same, but could be easily adapted if it turns out some programs + * require it. + */ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#define DPRINTF DPRINT +#define ERR DPRINT +#define SetLastError(x) +#define WARN DPRINT +#define TRACE DPRINT +#define WARN_ON(x) (1) + +#undef assert +#ifdef NDEBUG +#define TRACE_ON(x) (0) +#define assert(x) +#else +#define TRACE_ON(x) (1) +#define assert(x) +#endif + + +static CRITICAL_SECTION RtlpProcessHeapsListLock; + + +typedef struct tagARENA_INUSE +{ + DWORD size; /* Block size; must be the first field */ + WORD threadId; /* Allocating thread id */ + WORD magic; /* Magic number */ + void *callerEIP; /* EIP of caller upon allocation */ +} ARENA_INUSE; + +typedef struct tagARENA_FREE +{ + DWORD size; /* Block size; must be the first field */ + WORD threadId; /* Freeing thread id */ + WORD magic; /* Magic number */ + struct tagARENA_FREE *next; /* Next free arena */ + struct tagARENA_FREE *prev; /* Prev free arena */ +} ARENA_FREE; + +#define ARENA_FLAG_FREE 0x00000001 /* flags OR'ed with arena size */ +#define ARENA_FLAG_PREV_FREE 0x00000002 +#define ARENA_SIZE_MASK 0xfffffffc +#define ARENA_INUSE_MAGIC 0x4842 /* Value for arena 'magic' field */ +#define ARENA_FREE_MAGIC 0x4846 /* Value for arena 'magic' field */ + +#define ARENA_INUSE_FILLER 0x55 +#define ARENA_FREE_FILLER 0xaa + +#define QUIET 1 /* Suppress messages */ +#define NOISY 0 /* Report all errors */ + +#define HEAP_NB_FREE_LISTS 4 /* Number of free lists */ + +/* Max size of the blocks on the free lists */ +static const DWORD HEAP_freeListSizes[HEAP_NB_FREE_LISTS] = +{ + 0x20, 0x80, 0x200, 0xffffffff +}; + +typedef struct +{ + DWORD size; + ARENA_FREE arena; +} FREE_LIST_ENTRY; + +struct tagHEAP; + +typedef struct tagSUBHEAP +{ + DWORD size; /* Size of the whole sub-heap */ + DWORD commitSize; /* Committed size of the sub-heap */ + DWORD headerSize; /* Size of the heap header */ + struct tagSUBHEAP *next; /* Next sub-heap */ + struct tagHEAP *heap; /* Main heap structure */ + DWORD magic; /* Magic number */ + WORD selector; /* Selector for HEAP_WINE_SEGPTR heaps */ +} SUBHEAP, *PSUBHEAP; + +#define SUBHEAP_MAGIC ((DWORD)('S' | ('U'<<8) | ('B'<<16) | ('H'<<24))) + +typedef struct tagHEAP +{ + SUBHEAP subheap; /* First sub-heap */ + struct tagHEAP *next; /* Next heap for this process */ + FREE_LIST_ENTRY freeList[HEAP_NB_FREE_LISTS]; /* Free lists */ + CRITICAL_SECTION critSection; /* Critical section for serialization */ + DWORD flags; /* Heap flags */ + DWORD magic; /* Magic number */ + void *private; /* Private pointer for the user of the heap */ +} HEAP, *PHEAP; + +#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24))) + +#define HEAP_DEF_SIZE 0x110000 /* Default heap size = 1Mb + 64Kb */ +#define HEAP_MIN_BLOCK_SIZE (8+sizeof(ARENA_FREE)) /* Min. heap block size */ +#define COMMIT_MASK 0xffff /* bitmask for commit/decommit granularity */ + + +static BOOL HEAP_IsRealArena( HANDLE heap, DWORD flags, LPCVOID block, BOOL quiet ); + +#ifdef __GNUC__ +#define GET_EIP() (__builtin_return_address(0)) +#define SET_EIP(ptr) ((ARENA_INUSE*)(ptr) - 1)->callerEIP = GET_EIP() +#else +#define GET_EIP() 0 +#define SET_EIP(ptr) /* nothing */ +#endif /* __GNUC__ */ + + +/*********************************************************************** + * HEAP_Dump + */ +void +HEAP_Dump(PHEAP heap) +{ + int i; + SUBHEAP *subheap; + char *ptr; + + DPRINTF( "Heap: %08lx\n", (DWORD)heap ); + DPRINTF( "Next: %08lx Sub-heaps: %08lx", + (DWORD)heap->next, (DWORD)&heap->subheap ); + subheap = &heap->subheap; + while (subheap->next) + { + DPRINTF( " -> %08lx", (DWORD)subheap->next ); + subheap = subheap->next; + } + + DPRINTF( "\nFree lists:\n Block Stat Size Id\n" ); + for (i = 0; i < HEAP_NB_FREE_LISTS; i++) + DPRINTF( "%08lx free %08lx %04x prev=%08lx next=%08lx\n", + (DWORD)&heap->freeList[i].arena, heap->freeList[i].arena.size, + heap->freeList[i].arena.threadId, + (DWORD)heap->freeList[i].arena.prev, + (DWORD)heap->freeList[i].arena.next ); + + subheap = &heap->subheap; + while (subheap) + { + DWORD freeSize = 0, usedSize = 0, arenaSize = subheap->headerSize; + DPRINTF( "\n\nSub-heap %08lx: size=%08lx committed=%08lx\n", + (DWORD)subheap, subheap->size, subheap->commitSize ); + + DPRINTF( "\n Block Stat Size Id\n" ); + ptr = (char*)subheap + subheap->headerSize; + while (ptr < (char *)subheap + subheap->size) + { + if (*(DWORD *)ptr & ARENA_FLAG_FREE) + { + ARENA_FREE *pArena = (ARENA_FREE *)ptr; + DPRINTF( "%08lx free %08lx %04x prev=%08lx next=%08lx\n", + (DWORD)pArena, pArena->size & ARENA_SIZE_MASK, + pArena->threadId, (DWORD)pArena->prev, + (DWORD)pArena->next); + ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); + arenaSize += sizeof(ARENA_FREE); + freeSize += pArena->size & ARENA_SIZE_MASK; + } + else if (*(DWORD *)ptr & ARENA_FLAG_PREV_FREE) + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr; + DPRINTF( "%08lx Used %08lx %04x back=%08lx EIP=%p\n", + (DWORD)pArena, pArena->size & ARENA_SIZE_MASK, + pArena->threadId, *((DWORD *)pArena - 1), + pArena->callerEIP ); + ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); + arenaSize += sizeof(ARENA_INUSE); + usedSize += pArena->size & ARENA_SIZE_MASK; + } + else + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr; + DPRINTF( "%08lx used %08lx %04x EIP=%p\n", + (DWORD)pArena, pArena->size & ARENA_SIZE_MASK, + pArena->threadId, pArena->callerEIP ); + ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK); + arenaSize += sizeof(ARENA_INUSE); + usedSize += pArena->size & ARENA_SIZE_MASK; + } + } + DPRINTF( "\nTotal: Size=%08lx Committed=%08lx Free=%08lx Used=%08lx Arenas=%08lx (%ld%%)\n\n", + subheap->size, subheap->commitSize, freeSize, usedSize, + arenaSize, (arenaSize * 100) / subheap->size ); + subheap = subheap->next; + } +} + + +/*********************************************************************** + * HEAP_GetPtr + * RETURNS + * Pointer to the heap + * NULL: Failure + */ +static PHEAP +HEAP_GetPtr(HANDLE heap) /* [in] Handle to the heap */ +{ + HEAP *heapPtr = (HEAP *)heap; + if (!heapPtr || (heapPtr->magic != HEAP_MAGIC)) + { + ERR("Invalid heap %08x!\n", heap ); + return NULL; + } + if (TRACE_ON(heap) && !HEAP_IsRealArena( heap, 0, NULL, NOISY )) + { + HEAP_Dump( heapPtr ); + assert( FALSE ); + return NULL; + } + return heapPtr; +} + + +/*********************************************************************** + * HEAP_InsertFreeBlock + * + * Insert a free block into the free list. + */ +static VOID +HEAP_InsertFreeBlock(PHEAP heap, + ARENA_FREE *pArena) +{ + FREE_LIST_ENTRY *pEntry = heap->freeList; + while (pEntry->size < pArena->size) pEntry++; + pArena->size |= ARENA_FLAG_FREE; + pArena->next = pEntry->arena.next; + pArena->next->prev = pArena; + pArena->prev = &pEntry->arena; + pEntry->arena.next = pArena; +} + + +/*********************************************************************** + * HEAP_FindSubHeap + * Find the sub-heap containing a given address. + * + * RETURNS + * Pointer: Success + * NULL: Failure + */ +static PSUBHEAP +HEAP_FindSubHeap(HEAP *heap, /* [in] Heap pointer */ + LPCVOID ptr) /* [in] Address */ +{ + SUBHEAP *sub = &heap->subheap; + while (sub) + { + if (((char *)ptr >= (char *)sub) && + ((char *)ptr < (char *)sub + sub->size)) return sub; + sub = sub->next; + } + return NULL; +} + + +/*********************************************************************** + * HEAP_Commit + * + * Make sure the heap storage is committed up to (not including) ptr. + */ +static inline BOOL +HEAP_Commit(SUBHEAP *subheap, + void *ptr, + DWORD flags) +{ + DWORD size = (DWORD)((char *)ptr - (char *)subheap); + NTSTATUS Status; + PVOID address; + ULONG commitsize; + + size = (size + COMMIT_MASK) & ~COMMIT_MASK; + if (size > subheap->size) size = subheap->size; + if (size <= subheap->commitSize) return TRUE; + + address = (PVOID)((char *)subheap + subheap->commitSize); + commitsize = size - subheap->commitSize; + + if (!(flags & HEAP_NO_VALLOC)) + { + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &address, + 0, + &commitsize, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + WARN("Could not commit %08lx bytes at %08lx for heap %08lx\n", + size - subheap->commitSize, + (DWORD)((char *)subheap + subheap->commitSize), + (DWORD)subheap->heap ); + return FALSE; + } + } + subheap->commitSize = size; + return TRUE; +} + + +/*********************************************************************** + * HEAP_Decommit + * + * If possible, decommit the heap storage from (including) 'ptr'. + */ +static inline BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr, DWORD flags ) +{ + DWORD size = (DWORD)((char *)ptr - (char *)subheap); + PVOID address; + ULONG decommitsize; + NTSTATUS Status; + /* round to next block and add one full block */ + size = ((size + COMMIT_MASK) & ~COMMIT_MASK) + COMMIT_MASK + 1; + if (size >= subheap->commitSize) return TRUE; + + address = (PVOID)((char *)subheap + size); + decommitsize = subheap->commitSize - size; + + if (!(flags & HEAP_NO_VALLOC)) + { + Status = ZwFreeVirtualMemory(NtCurrentProcess(), + &address, + &decommitsize, + MEM_DECOMMIT); + if (!NT_SUCCESS(Status)); + { + WARN("Could not decommit %08lx bytes at %08lx for heap %08lx\n", + subheap->commitSize - size, + (DWORD)((char *)subheap + size), + (DWORD)subheap->heap ); + return FALSE; + } + } + subheap->commitSize = size; + return TRUE; +} + + +/*********************************************************************** + * HEAP_CreateFreeBlock + * + * Create a free block at a specified address. 'size' is the size of the + * whole block, including the new arena. + */ +static void HEAP_CreateFreeBlock( SUBHEAP *subheap, void *ptr, DWORD size ) +{ + ARENA_FREE *pFree; + + /* Create a free arena */ + + pFree = (ARENA_FREE *)ptr; + pFree->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread; + pFree->magic = ARENA_FREE_MAGIC; + + /* If debugging, erase the freed block content */ + + if (TRACE_ON(heap)) + { + char *pEnd = (char *)ptr + size; + if (pEnd > (char *)subheap + subheap->commitSize) + pEnd = (char *)subheap + subheap->commitSize; + if (pEnd > (char *)(pFree + 1)) + memset( pFree + 1, ARENA_FREE_FILLER, pEnd - (char *)(pFree + 1) ); + } + + /* Check if next block is free also */ + + if (((char *)ptr + size < (char *)subheap + subheap->size) && + (*(DWORD *)((char *)ptr + size) & ARENA_FLAG_FREE)) + { + /* Remove the next arena from the free list */ + ARENA_FREE *pNext = (ARENA_FREE *)((char *)ptr + size); + pNext->next->prev = pNext->prev; + pNext->prev->next = pNext->next; + size += (pNext->size & ARENA_SIZE_MASK) + sizeof(*pNext); + if (TRACE_ON(heap)) + memset( pNext, ARENA_FREE_FILLER, sizeof(ARENA_FREE) ); + } + + /* Set the next block PREV_FREE flag and pointer */ + + if ((char *)ptr + size < (char *)subheap + subheap->size) + { + DWORD *pNext = (DWORD *)((char *)ptr + size); + *pNext |= ARENA_FLAG_PREV_FREE; + *(ARENA_FREE **)(pNext - 1) = pFree; + } + + /* Last, insert the new block into the free list */ + + pFree->size = size - sizeof(*pFree); + HEAP_InsertFreeBlock( subheap->heap, pFree ); +} + + +/*********************************************************************** + * HEAP_MakeInUseBlockFree + * + * Turn an in-use block into a free block. Can also decommit the end of + * the heap, and possibly even free the sub-heap altogether. + */ +static void HEAP_MakeInUseBlockFree( SUBHEAP *subheap, ARENA_INUSE *pArena, + DWORD flags) +{ + ARENA_FREE *pFree; + DWORD size = (pArena->size & ARENA_SIZE_MASK) + sizeof(*pArena); + + /* Check if we can merge with previous block */ + + if (pArena->size & ARENA_FLAG_PREV_FREE) + { + pFree = *((ARENA_FREE **)pArena - 1); + size += (pFree->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE); + /* Remove it from the free list */ + pFree->next->prev = pFree->prev; + pFree->prev->next = pFree->next; + } + else pFree = (ARENA_FREE *)pArena; + + /* Create a free block */ + + HEAP_CreateFreeBlock( subheap, pFree, size ); + size = (pFree->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE); + if ((char *)pFree + size < (char *)subheap + subheap->size) + return; /* Not the last block, so nothing more to do */ + + /* Free the whole sub-heap if it's empty and not the original one */ + + if (((char *)pFree == (char *)subheap + subheap->headerSize) && + (subheap != &subheap->heap->subheap)) + { + SUBHEAP *pPrev = &subheap->heap->subheap; + /* Remove the free block from the list */ + pFree->next->prev = pFree->prev; + pFree->prev->next = pFree->next; + /* Remove the subheap from the list */ + while (pPrev && (pPrev->next != subheap)) pPrev = pPrev->next; + if (pPrev) pPrev->next = subheap->next; + /* Free the memory */ + subheap->magic = 0; + if (!(flags & HEAP_NO_VALLOC)) + { + ULONG dummySize = 0; + ZwFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&subheap, + &dummySize, + MEM_RELEASE); + } + return; + } + + /* Decommit the end of the heap */ +} + + +/*********************************************************************** + * HEAP_ShrinkBlock + * + * Shrink an in-use block. + */ +static void HEAP_ShrinkBlock(SUBHEAP *subheap, ARENA_INUSE *pArena, DWORD size) +{ + if ((pArena->size & ARENA_SIZE_MASK) >= size + HEAP_MIN_BLOCK_SIZE) + { + HEAP_CreateFreeBlock( subheap, (char *)(pArena + 1) + size, + (pArena->size & ARENA_SIZE_MASK) - size ); + pArena->size = (pArena->size & ~ARENA_SIZE_MASK) | size; + } + else + { + /* Turn off PREV_FREE flag in next block */ + char *pNext = (char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK); + if (pNext < (char *)subheap + subheap->size) + *(DWORD *)pNext &= ~ARENA_FLAG_PREV_FREE; + } +} + +/*********************************************************************** + * HEAP_InitSubHeap + */ +static BOOL HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags, + DWORD commitSize, DWORD totalSize ) +{ + SUBHEAP *subheap = (SUBHEAP *)address; + WORD selector = 0; + FREE_LIST_ENTRY *pEntry; + int i; + NTSTATUS Status; + + /* Commit memory */ + if (!(flags & HEAP_NO_VALLOC)) + { + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &address, + 0, + (PULONG)&commitSize, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + WARN("Could not commit %08lx bytes for sub-heap %08lx\n", + commitSize, (DWORD)address ); + return FALSE; + } + } + + /* Fill the sub-heap structure */ + + subheap->heap = heap; + subheap->selector = selector; + subheap->size = totalSize; + subheap->commitSize = commitSize; + subheap->magic = SUBHEAP_MAGIC; + + if ( subheap != (SUBHEAP *)heap ) + { + /* If this is a secondary subheap, insert it into list */ + + subheap->headerSize = sizeof(SUBHEAP); + subheap->next = heap->subheap.next; + heap->subheap.next = subheap; + } + else + { + /* If this is a primary subheap, initialize main heap */ + + subheap->headerSize = sizeof(HEAP); + subheap->next = NULL; + heap->next = NULL; + heap->flags = flags; + heap->magic = HEAP_MAGIC; + + /* Build the free lists */ + + for (i = 0, pEntry = heap->freeList; i < HEAP_NB_FREE_LISTS; i++, pEntry++) + { + pEntry->size = HEAP_freeListSizes[i]; + pEntry->arena.size = 0 | ARENA_FLAG_FREE; + pEntry->arena.next = i < HEAP_NB_FREE_LISTS-1 ? + &heap->freeList[i+1].arena : &heap->freeList[0].arena; + pEntry->arena.prev = i ? &heap->freeList[i-1].arena : + &heap->freeList[HEAP_NB_FREE_LISTS-1].arena; + pEntry->arena.threadId = 0; + pEntry->arena.magic = ARENA_FREE_MAGIC; + } + + /* Initialize critical section */ + + RtlInitializeCriticalSection( &heap->critSection ); + } + + /* Create the first free block */ + + HEAP_CreateFreeBlock( subheap, (LPBYTE)subheap + subheap->headerSize, + subheap->size - subheap->headerSize ); + + return TRUE; +} + +/*********************************************************************** + * HEAP_CreateSubHeap + * + * Create a sub-heap of the given size. + * If heap == NULL, creates a main heap. + */ +static SUBHEAP *HEAP_CreateSubHeap(PVOID BaseAddress, + HEAP *heap, DWORD flags, + DWORD commitSize, DWORD totalSize ) +{ + LPVOID address; + NTSTATUS Status; + + /* Round-up sizes on a 64K boundary */ + + totalSize = (totalSize + 0xffff) & 0xffff0000; + commitSize = (commitSize + 0xffff) & 0xffff0000; + if (!commitSize) commitSize = 0x10000; + if (totalSize < commitSize) totalSize = commitSize; + + /* Allocate the memory block */ + address = BaseAddress; + if (!(flags & HEAP_NO_VALLOC)) + { + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &address, + 0, + (PULONG)&totalSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + WARN("Could not VirtualAlloc %08lx bytes\n", + totalSize ); + return NULL; + } + } + + /* Initialize subheap */ + + if (!HEAP_InitSubHeap( heap? heap : (HEAP *)address, + address, flags, commitSize, totalSize )) + { + if (!(flags & HEAP_NO_VALLOC)) + { + ULONG dummySize = 0; + ZwFreeVirtualMemory(NtCurrentProcess(), + address, + &dummySize, + MEM_RELEASE); + return NULL; + } + } + + return (SUBHEAP *)address; +} + + +/*********************************************************************** + * HEAP_FindFreeBlock + * + * Find a free block at least as large as the requested size, and make sure + * the requested size is committed. + */ +static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, DWORD size, + SUBHEAP **ppSubHeap ) +{ + SUBHEAP *subheap; + ARENA_FREE *pArena; + FREE_LIST_ENTRY *pEntry = heap->freeList; + + /* Find a suitable free list, and in it find a block large enough */ + + while (pEntry->size < size) pEntry++; + pArena = pEntry->arena.next; + while (pArena != &heap->freeList[0].arena) + { + if (pArena->size > size) + { + subheap = HEAP_FindSubHeap( heap, pArena ); + if (!HEAP_Commit( subheap, (char *)pArena + sizeof(ARENA_INUSE) + + size + HEAP_MIN_BLOCK_SIZE, + heap->flags)) + return NULL; + *ppSubHeap = subheap; + return pArena; + } + + pArena = pArena->next; + } + + /* If no block was found, attempt to grow the heap */ + + if (!(heap->flags & HEAP_GROWABLE)) + { + WARN("Not enough space in heap %08lx for %08lx bytes\n", + (DWORD)heap, size ); + return NULL; + } + size += sizeof(SUBHEAP) + sizeof(ARENA_FREE); + if (!(subheap = HEAP_CreateSubHeap( NULL, heap, heap->flags, size, + max( HEAP_DEF_SIZE, size ) ))) + return NULL; + + TRACE("created new sub-heap %08lx of %08lx bytes for heap %08lx\n", + (DWORD)subheap, size, (DWORD)heap ); + + *ppSubHeap = subheap; + return (ARENA_FREE *)(subheap + 1); +} + + +/*********************************************************************** + * HEAP_IsValidArenaPtr + * + * Check that the pointer is inside the range possible for arenas. + */ +static BOOL HEAP_IsValidArenaPtr( HEAP *heap, void *ptr ) +{ + int i; + SUBHEAP *subheap = HEAP_FindSubHeap( heap, ptr ); + if (!subheap) return FALSE; + if ((char *)ptr >= (char *)subheap + subheap->headerSize) return TRUE; + if (subheap != &heap->subheap) return FALSE; + for (i = 0; i < HEAP_NB_FREE_LISTS; i++) + if (ptr == (void *)&heap->freeList[i].arena) return TRUE; + return FALSE; +} + + +/*********************************************************************** + * HEAP_ValidateFreeArena + */ +static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena ) +{ + char *heapEnd = (char *)subheap + subheap->size; + + /* Check magic number */ + if (pArena->magic != ARENA_FREE_MAGIC) + { + ERR("Heap %08lx: invalid free arena magic for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check size flags */ + if (!(pArena->size & ARENA_FLAG_FREE) || + (pArena->size & ARENA_FLAG_PREV_FREE)) + { + ERR("Heap %08lx: bad flags %lx for free arena %08lx\n", + (DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena ); + } + /* Check arena size */ + if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd) + { + ERR("Heap %08lx: bad size %08lx for free arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena ); + return FALSE; + } + /* Check that next pointer is valid */ + if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->next )) + { + ERR("Heap %08lx: bad next ptr %08lx for arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena ); + return FALSE; + } + /* Check that next arena is free */ + if (!(pArena->next->size & ARENA_FLAG_FREE) || + (pArena->next->magic != ARENA_FREE_MAGIC)) + { + ERR("Heap %08lx: next arena %08lx invalid for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena ); + return FALSE; + } + /* Check that prev pointer is valid */ + if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->prev )) + { + ERR("Heap %08lx: bad prev ptr %08lx for arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena ); + return FALSE; + } + /* Check that prev arena is free */ + if (!(pArena->prev->size & ARENA_FLAG_FREE) || + (pArena->prev->magic != ARENA_FREE_MAGIC)) + { + ERR("Heap %08lx: prev arena %08lx invalid for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena ); + return FALSE; + } + /* Check that next block has PREV_FREE flag */ + if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd) + { + if (!(*(DWORD *)((char *)(pArena + 1) + + (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE)) + { + ERR("Heap %08lx: free arena %08lx next block has no PREV_FREE flag\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check next block back pointer */ + if (*((ARENA_FREE **)((char *)(pArena + 1) + + (pArena->size & ARENA_SIZE_MASK)) - 1) != pArena) + { + ERR("Heap %08lx: arena %08lx has wrong back ptr %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena, + *((DWORD *)((char *)(pArena+1)+ (pArena->size & ARENA_SIZE_MASK)) - 1)); + return FALSE; + } + } + return TRUE; +} + + +/*********************************************************************** + * HEAP_ValidateInUseArena + */ +static BOOL HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena, BOOL quiet ) +{ + char *heapEnd = (char *)subheap + subheap->size; + + /* Check magic number */ + if (pArena->magic != ARENA_INUSE_MAGIC) + { + if (quiet == NOISY) { + ERR("Heap %08lx: invalid in-use arena magic for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena ); + if (TRACE_ON(heap)) + HEAP_Dump( subheap->heap ); + } else if (WARN_ON(heap)) { + WARN("Heap %08lx: invalid in-use arena magic for %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena ); + if (TRACE_ON(heap)) + HEAP_Dump( subheap->heap ); + } + return FALSE; + } + /* Check size flags */ + if (pArena->size & ARENA_FLAG_FREE) + { + ERR("Heap %08lx: bad flags %lx for in-use arena %08lx\n", + (DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena ); + } + /* Check arena size */ + if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd) + { + ERR("Heap %08lx: bad size %08lx for in-use arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena ); + return FALSE; + } + /* Check next arena PREV_FREE flag */ + if (((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd) && + (*(DWORD *)((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE)) + { + ERR("Heap %08lx: in-use arena %08lx next block has PREV_FREE flag\n", + (DWORD)subheap->heap, (DWORD)pArena ); + return FALSE; + } + /* Check prev free arena */ + if (pArena->size & ARENA_FLAG_PREV_FREE) + { + ARENA_FREE *pPrev = *((ARENA_FREE **)pArena - 1); + /* Check prev pointer */ + if (!HEAP_IsValidArenaPtr( subheap->heap, pPrev )) + { + ERR("Heap %08lx: bad back ptr %08lx for arena %08lx\n", + (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena ); + return FALSE; + } + /* Check that prev arena is free */ + if (!(pPrev->size & ARENA_FLAG_FREE) || + (pPrev->magic != ARENA_FREE_MAGIC)) + { + ERR("Heap %08lx: prev arena %08lx invalid for in-use %08lx\n", + (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena ); + return FALSE; + } + /* Check that prev arena is really the previous block */ + if ((char *)(pPrev + 1) + (pPrev->size & ARENA_SIZE_MASK) != (char *)pArena) + { + ERR("Heap %08lx: prev arena %08lx is not prev for in-use %08lx\n", + (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena ); + return FALSE; + } + } + return TRUE; +} + + +/*********************************************************************** + * HEAP_IsInsideHeap + * Checks whether the pointer points to a block inside a given heap. + * + * NOTES + * Should this return BOOL32? + * + * RETURNS + * !0: Success + * 0: Failure + */ +int HEAP_IsInsideHeap( + HANDLE heap, /* [in] Heap */ + DWORD flags, /* [in] Flags */ + LPCVOID ptr /* [in] Pointer */ +) { + HEAP *heapPtr = HEAP_GetPtr( heap ); + SUBHEAP *subheap; + int ret; + + /* Validate the parameters */ + + if (!heapPtr) return 0; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + ret = (((subheap = HEAP_FindSubHeap( heapPtr, ptr )) != NULL) && + (((char *)ptr >= (char *)subheap + subheap->headerSize + + sizeof(ARENA_INUSE)))); + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + return ret; +} + + + + +/*********************************************************************** + * HEAP_IsRealArena [Internal] + * Validates a block is a valid arena. + * + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +static BOOL HEAP_IsRealArena( + HANDLE heap, /* [in] Handle to the heap */ + DWORD flags, /* [in] Bit flags that control access during operation */ + LPCVOID block, /* [in] Optional pointer to memory block to validate */ + BOOL quiet /* [in] Flag - if true, HEAP_ValidateInUseArena + * does not complain */ +) { + SUBHEAP *subheap; + HEAP *heapPtr = (HEAP *)(heap); + BOOL ret = TRUE; + + if (!heapPtr || (heapPtr->magic != HEAP_MAGIC)) + { + ERR("Invalid heap %08x!\n", heap ); + return FALSE; + } + + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; + /* calling HeapLock may result in infinite recursion, so do the critsect directly */ + if (!(flags & HEAP_NO_SERIALIZE)) + RtlEnterCriticalSection( &heapPtr->critSection ); + + if (block) + { + /* Only check this single memory block */ + + /* The following code is really HEAP_IsInsideHeap * + * with serialization already done. */ + if (!(subheap = HEAP_FindSubHeap( heapPtr, block )) || + ((char *)block < (char *)subheap + subheap->headerSize + + sizeof(ARENA_INUSE))) + { + if (quiet == NOISY) + { + ERR("Heap %08lx: block %08lx is not inside heap\n", + (DWORD)heap, (DWORD)block ); + } + else if (WARN_ON(heap)) + { + WARN("Heap %08lx: block %08lx is not inside heap\n", + (DWORD)heap, (DWORD)block ); + } + ret = FALSE; + } else + ret = HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1, quiet ); + + if (!(flags & HEAP_NO_SERIALIZE)) + RtlLeaveCriticalSection( &heapPtr->critSection ); + return ret; + } + + subheap = &heapPtr->subheap; + while (subheap && ret) + { + char *ptr = (char *)subheap + subheap->headerSize; + while (ptr < (char *)subheap + subheap->size) + { + if (*(DWORD *)ptr & ARENA_FLAG_FREE) + { + if (!HEAP_ValidateFreeArena( subheap, (ARENA_FREE *)ptr )) { + ret = FALSE; + break; + } + ptr += sizeof(ARENA_FREE) + (*(DWORD *)ptr & ARENA_SIZE_MASK); + } + else + { + if (!HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)ptr, NOISY )) { + ret = FALSE; + break; + } + ptr += sizeof(ARENA_INUSE) + (*(DWORD *)ptr & ARENA_SIZE_MASK); + } + } + subheap = subheap->next; + } + + if (!(flags & HEAP_NO_SERIALIZE)) + RtlLeaveCriticalSection( &heapPtr->critSection ); + return ret; +} + + +/*********************************************************************** + * HeapCreate (KERNEL32.336) + * RETURNS + * Handle of heap: Success + * NULL: Failure + */ +HANDLE STDCALL +RtlCreateHeap(ULONG flags, + PVOID BaseAddress, + ULONG initialSize, + ULONG maxSize, + PVOID Unknown, + PRTL_HEAP_DEFINITION Definition) +{ + SUBHEAP *subheap; + ULONG i; + + /* Allocate the heap block */ + + if (!maxSize) + { + maxSize = HEAP_DEF_SIZE; + flags |= HEAP_GROWABLE; + } + if (!(subheap = HEAP_CreateSubHeap( BaseAddress, NULL, flags, initialSize, maxSize ))) + { + return 0; + } + + RtlEnterCriticalSection (&RtlpProcessHeapsListLock); + for (i = 0; i < NtCurrentPeb ()->NumberOfHeaps; i++) + { + if (NtCurrentPeb ()->ProcessHeaps[i] == NULL) + { + NtCurrentPeb()->ProcessHeaps[i] = (PVOID)subheap; + break; + } + } + RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + + return (HANDLE)subheap; +} + +/*********************************************************************** + * HeapDestroy (KERNEL32.337) + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +BOOL STDCALL +RtlDestroyHeap(HANDLE heap) /* [in] Handle of heap */ +{ + HEAP *heapPtr = HEAP_GetPtr( heap ); + SUBHEAP *subheap; + ULONG i, flags; + + TRACE("%08x\n", heap ); + if (!heapPtr) return FALSE; + + RtlEnterCriticalSection (&RtlpProcessHeapsListLock); + for (i = 0; i < NtCurrentPeb ()->NumberOfHeaps; i++) + { + if (NtCurrentPeb ()->ProcessHeaps[i] == heap) + { + NtCurrentPeb()->ProcessHeaps[i] = NULL; + break; + } + } + RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + + RtlDeleteCriticalSection( &heapPtr->critSection ); + subheap = &heapPtr->subheap; + // We must save the flags. The first subheap is located after + // the heap structure. If we release the first subheap, + // we release also the heap structure. + flags = heapPtr->flags; + while (subheap) + { + SUBHEAP *next = subheap->next; + + if (!(flags & HEAP_NO_VALLOC)) + { + ULONG dummySize = 0; + ZwFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&subheap, + &dummySize, + MEM_RELEASE); + } + subheap = next; + } + return TRUE; +} + + +/*********************************************************************** + * HeapAlloc (KERNEL32.334) + * RETURNS + * Pointer to allocated memory block + * NULL: Failure + */ +PVOID STDCALL +RtlAllocateHeap(HANDLE heap, /* [in] Handle of private heap block */ + ULONG flags, /* [in] Heap allocation control flags */ + ULONG size) /* [in] Number of bytes to allocate */ +{ + ARENA_FREE *pArena; + ARENA_INUSE *pInUse; + SUBHEAP *subheap; + HEAP *heapPtr = HEAP_GetPtr( heap ); + + /* Validate the parameters */ + + if (!heapPtr) return NULL; + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + size = (size + 3) & ~3; + if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE; + + /* Locate a suitable free block */ + + if (!(pArena = HEAP_FindFreeBlock( heapPtr, size, &subheap ))) + { + TRACE("(%08x,%08lx,%08lx): returning NULL\n", + heap, flags, size ); + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + return NULL; + } + + /* Remove the arena from the free list */ + + pArena->next->prev = pArena->prev; + pArena->prev->next = pArena->next; + + /* Build the in-use arena */ + + pInUse = (ARENA_INUSE *)pArena; + pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE) + + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); + pInUse->callerEIP = GET_EIP(); + pInUse->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread; + pInUse->magic = ARENA_INUSE_MAGIC; + + /* Shrink the block */ + + HEAP_ShrinkBlock( subheap, pInUse, size ); + + if (flags & HEAP_ZERO_MEMORY) + memset( pInUse + 1, 0, pInUse->size & ARENA_SIZE_MASK ); + else if (TRACE_ON(heap)) + memset( pInUse + 1, ARENA_INUSE_FILLER, pInUse->size & ARENA_SIZE_MASK ); + + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + + TRACE("(%08x,%08lx,%08lx): returning %08lx\n", + heap, flags, size, (DWORD)(pInUse + 1) ); + return (LPVOID)(pInUse + 1); +} + + +/*********************************************************************** + * HeapFree (KERNEL32.338) + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +BOOLEAN STDCALL RtlFreeHeap( + HANDLE heap, /* [in] Handle of heap */ + ULONG flags, /* [in] Heap freeing flags */ + PVOID ptr /* [in] Address of memory to free */ +) { + ARENA_INUSE *pInUse; + SUBHEAP *subheap; + HEAP *heapPtr = HEAP_GetPtr( heap ); + + /* Validate the parameters */ + + if (!heapPtr) return FALSE; + if (!ptr) /* Freeing a NULL ptr is doesn't indicate an error in Win2k */ + { + WARN("(%08x,%08lx,%08lx): asked to free NULL\n", + heap, flags, (DWORD)ptr ); + return TRUE; + } + + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET )) + { + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + TRACE("(%08x,%08lx,%08lx): returning FALSE\n", + heap, flags, (DWORD)ptr ); + return FALSE; + } + + /* Turn the block into a free block */ + + pInUse = (ARENA_INUSE *)ptr - 1; + subheap = HEAP_FindSubHeap( heapPtr, pInUse ); + HEAP_MakeInUseBlockFree( subheap, pInUse, heapPtr->flags ); + + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + + TRACE("(%08x,%08lx,%08lx): returning TRUE\n", + heap, flags, (DWORD)ptr ); + return TRUE; +} + + +/*********************************************************************** + * HeapReAlloc (KERNEL32.340) + * RETURNS + * Pointer to reallocated memory block + * NULL: Failure + */ +LPVOID STDCALL RtlReAllocateHeap( + HANDLE heap, /* [in] Handle of heap block */ + DWORD flags, /* [in] Heap reallocation flags */ + LPVOID ptr, /* [in] Address of memory to reallocate */ + DWORD size /* [in] Number of bytes to reallocate */ +) { + ARENA_INUSE *pArena; + DWORD oldSize; + HEAP *heapPtr; + SUBHEAP *subheap; + + if (!ptr) return RtlAllocateHeap( heap, flags, size ); /* FIXME: correct? */ + if (!(heapPtr = HEAP_GetPtr( heap ))) return FALSE; + + /* Validate the parameters */ + + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | + HEAP_REALLOC_IN_PLACE_ONLY; + flags |= heapPtr->flags; + size = (size + 3) & ~3; + if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE; + + if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET )) + { + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + TRACE("(%08x,%08lx,%08lx,%08lx): returning NULL\n", + heap, flags, (DWORD)ptr, size ); + return NULL; + } + + /* Check if we need to grow the block */ + + pArena = (ARENA_INUSE *)ptr - 1; + pArena->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread; + + subheap = HEAP_FindSubHeap( heapPtr, pArena ); + oldSize = (pArena->size & ARENA_SIZE_MASK); + if (size > oldSize) + { + char *pNext = (char *)(pArena + 1) + oldSize; + if ((pNext < (char *)subheap + subheap->size) && + (*(DWORD *)pNext & ARENA_FLAG_FREE) && + (oldSize + (*(DWORD *)pNext & ARENA_SIZE_MASK) + sizeof(ARENA_FREE) >= size)) + { + /* The next block is free and large enough */ + ARENA_FREE *pFree = (ARENA_FREE *)pNext; + pFree->next->prev = pFree->prev; + pFree->prev->next = pFree->next; + pArena->size += (pFree->size & ARENA_SIZE_MASK) + sizeof(*pFree); + if (!HEAP_Commit( subheap, (char *)pArena + sizeof(ARENA_INUSE) + + size + HEAP_MIN_BLOCK_SIZE, + heapPtr->flags)) + { + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + return NULL; + } + HEAP_ShrinkBlock( subheap, pArena, size ); + } + else /* Do it the hard way */ + { + ARENA_FREE *pNew; + ARENA_INUSE *pInUse; + SUBHEAP *newsubheap; + + if ((flags & HEAP_REALLOC_IN_PLACE_ONLY) || + !(pNew = HEAP_FindFreeBlock( heapPtr, size, &newsubheap ))) + { + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + return NULL; + } + + /* Build the in-use arena */ + + pNew->next->prev = pNew->prev; + pNew->prev->next = pNew->next; + pInUse = (ARENA_INUSE *)pNew; + pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE) + + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); + pInUse->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread; + pInUse->magic = ARENA_INUSE_MAGIC; + HEAP_ShrinkBlock( newsubheap, pInUse, size ); + memcpy( pInUse + 1, pArena + 1, oldSize ); + + /* Free the previous block */ + + HEAP_MakeInUseBlockFree( subheap, pArena, flags ); + subheap = newsubheap; + pArena = pInUse; + } + } + else HEAP_ShrinkBlock( subheap, pArena, size ); /* Shrink the block */ + + /* Clear the extra bytes if needed */ + + if (size > oldSize) + { + if (flags & HEAP_ZERO_MEMORY) + memset( (char *)(pArena + 1) + oldSize, 0, + (pArena->size & ARENA_SIZE_MASK) - oldSize ); + else if (TRACE_ON(heap)) + memset( (char *)(pArena + 1) + oldSize, ARENA_INUSE_FILLER, + (pArena->size & ARENA_SIZE_MASK) - oldSize ); + } + + /* Return the new arena */ + + pArena->callerEIP = GET_EIP(); + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + + TRACE("(%08x,%08lx,%08lx,%08lx): returning %08lx\n", + heap, flags, (DWORD)ptr, size, (DWORD)(pArena + 1) ); + return (LPVOID)(pArena + 1); +} + + +/*********************************************************************** + * HeapCompact (KERNEL32.335) + */ +DWORD STDCALL RtlCompactHeap( HANDLE heap, DWORD flags ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/*********************************************************************** + * HeapLock (KERNEL32.339) + * Attempts to acquire the critical section object for a specified heap. + * + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +BOOL STDCALL RtlLockHeap( + HANDLE heap /* [in] Handle of heap to lock for exclusive access */ +) { + HEAP *heapPtr = HEAP_GetPtr( heap ); + if (!heapPtr) return FALSE; + RtlEnterCriticalSection( &heapPtr->critSection ); + return TRUE; +} + + +/*********************************************************************** + * HeapUnlock (KERNEL32.342) + * Releases ownership of the critical section object. + * + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +BOOL STDCALL RtlUnlockHeap( + HANDLE heap /* [in] Handle to the heap to unlock */ +) { + HEAP *heapPtr = HEAP_GetPtr( heap ); + if (!heapPtr) return FALSE; + RtlLeaveCriticalSection( &heapPtr->critSection ); + return TRUE; +} + + +/*********************************************************************** + * HeapSize (KERNEL32.341) + * RETURNS + * Size in bytes of allocated memory + * 0xffffffff: Failure + */ +DWORD STDCALL RtlSizeHeap( + HANDLE heap, /* [in] Handle of heap */ + DWORD flags, /* [in] Heap size control flags */ + LPVOID ptr /* [in] Address of memory to return size for */ +) { + DWORD ret; + HEAP *heapPtr = HEAP_GetPtr( heap ); + + if (!heapPtr) return FALSE; + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; + if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + ret = 0xffffffff; + } + else + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr - 1; + ret = pArena->size & ARENA_SIZE_MASK; + } + if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + + TRACE("(%08x,%08lx,%08lx): returning %08lx\n", + heap, flags, (DWORD)ptr, ret ); + return ret; +} + + +/*********************************************************************** + * HeapValidate (KERNEL32.343) + * Validates a specified heap. + * + * NOTES + * Flags is ignored. + * + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +BOOL STDCALL RtlValidateHeap( + HANDLE heap, /* [in] Handle to the heap */ + DWORD flags, /* [in] Bit flags that control access during operation */ + PVOID block /* [in] Optional pointer to memory block to validate */ +) { + + return HEAP_IsRealArena( heap, flags, block, QUIET ); +} + + +/*********************************************************************** + * HeapWalk (KERNEL32.344) + * Enumerates the memory blocks in a specified heap. + * See HEAP_Dump() for info on heap structure. + * + * TODO + * - handling of PROCESS_HEAP_ENTRY_MOVEABLE and + * PROCESS_HEAP_ENTRY_DDESHARE (needs heap.c support) + * + * RETURNS + * TRUE: Success + * FALSE: Failure + */ +#if 0 +BOOL STDCALL HeapWalk( + HANDLE heap, /* [in] Handle to heap to enumerate */ + LPPROCESS_HEAP_ENTRY entry /* [out] Pointer to structure of enumeration info */ +) { + HEAP *heapPtr = HEAP_GetPtr(heap); + SUBHEAP *sub, *currentheap = NULL; + BOOL ret = FALSE; + char *ptr; + int region_index = 0; + + if (!heapPtr || !entry) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); + + /* set ptr to the next arena to be examined */ + + if (!entry->lpData) /* first call (init) ? */ + { + TRACE("begin walking of heap 0x%08x.\n", heap); + /*HEAP_Dump(heapPtr);*/ + currentheap = &heapPtr->subheap; + ptr = (char*)currentheap + currentheap->headerSize; + } + else + { + ptr = entry->lpData; + sub = &heapPtr->subheap; + while (sub) + { + if (((char *)ptr >= (char *)sub) && + ((char *)ptr < (char *)sub + sub->size)) + { + currentheap = sub; + break; + } + sub = sub->next; + region_index++; + } + if (currentheap == NULL) + { + ERR("no matching subheap found, shouldn't happen !\n"); + SetLastError(ERROR_NO_MORE_ITEMS); + goto HW_end; + } + + ptr += entry->cbData; /* point to next arena */ + if (ptr > (char *)currentheap + currentheap->size - 1) + { /* proceed with next subheap */ + if (!(currentheap = currentheap->next)) + { /* successfully finished */ + TRACE("end reached.\n"); + SetLastError(ERROR_NO_MORE_ITEMS); + goto HW_end; + } + ptr = (char*)currentheap + currentheap->headerSize; + } + } + + entry->wFlags = 0; + if (*(DWORD *)ptr & ARENA_FLAG_FREE) + { + ARENA_FREE *pArena = (ARENA_FREE *)ptr; + + /*TRACE("free, magic: %04x\n", pArena->magic);*/ + + entry->lpData = pArena + 1; + entry->cbData = pArena->size & ARENA_SIZE_MASK; + entry->cbOverhead = sizeof(ARENA_FREE); + entry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE; + } + else + { + ARENA_INUSE *pArena = (ARENA_INUSE *)ptr; + + /*TRACE("busy, magic: %04x\n", pArena->magic);*/ + + entry->lpData = pArena + 1; + entry->cbData = pArena->size & ARENA_SIZE_MASK; + entry->cbOverhead = sizeof(ARENA_INUSE); + entry->wFlags = PROCESS_HEAP_ENTRY_BUSY; + /* FIXME: can't handle PROCESS_HEAP_ENTRY_MOVEABLE + and PROCESS_HEAP_ENTRY_DDESHARE yet */ + } + + entry->iRegionIndex = region_index; + + /* first element of heap ? */ + if (ptr == (char *)(currentheap + currentheap->headerSize)) + { + entry->wFlags |= PROCESS_HEAP_REGION; + entry->Foo.Region.dwCommittedSize = currentheap->commitSize; + entry->Foo.Region.dwUnCommittedSize = + currentheap->size - currentheap->commitSize; + entry->Foo.Region.lpFirstBlock = /* first valid block */ + currentheap + currentheap->headerSize; + entry->Foo.Region.lpLastBlock = /* first invalid block */ + currentheap + currentheap->size; + } + ret = TRUE; + +HW_end: + if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); + + return ret; +} +#endif + +VOID +RtlInitializeHeapManager(VOID) +{ + PPEB Peb; + + Peb = NtCurrentPeb(); + + Peb->NumberOfHeaps = 0; + Peb->MaximumNumberOfHeaps = (PAGE_SIZE - sizeof(PEB)) / sizeof(HANDLE); + Peb->ProcessHeaps = (PVOID)Peb + sizeof(PEB); + + RtlInitializeCriticalSection(&RtlpProcessHeapsListLock); +} + + +NTSTATUS STDCALL +RtlEnumProcessHeaps(DWORD STDCALL(*func)(void*,LONG), + LONG lParam) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG i; + + RtlEnterCriticalSection(&RtlpProcessHeapsListLock); + + for (i = 0; i < NtCurrentPeb()->NumberOfHeaps; i++) + { + Status = func(NtCurrentPeb()->ProcessHeaps[i],lParam); + if (!NT_SUCCESS(Status)) + break; + } + + RtlLeaveCriticalSection(&RtlpProcessHeapsListLock); + + return Status; +} + + +ULONG STDCALL +RtlGetProcessHeaps(ULONG HeapCount, + HANDLE *HeapArray) +{ + ULONG Result = 0; + + RtlEnterCriticalSection(&RtlpProcessHeapsListLock); + + if (NtCurrentPeb()->NumberOfHeaps <= HeapCount) + { + Result = NtCurrentPeb()->NumberOfHeaps; + memmove(HeapArray, + NtCurrentPeb()->ProcessHeaps, + Result * sizeof(HANDLE)); + } + + RtlLeaveCriticalSection (&RtlpProcessHeapsListLock); + + return Result; +} + + +BOOLEAN STDCALL +RtlValidateProcessHeaps(VOID) +{ + HANDLE Heaps[128]; + BOOLEAN Result = TRUE; + ULONG HeapCount; + ULONG i; + + HeapCount = RtlGetProcessHeaps(128, Heaps); + for (i = 0; i < HeapCount; i++) + { + if (!RtlValidateHeap(Heaps[i], 0, NULL)) + Result = FALSE; + } + + return Result; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/i386/except.s b/lib/ntdll/rtl/i386/except.s new file mode 100755 index 0000000..41c12ac --- /dev/null +++ b/lib/ntdll/rtl/i386/except.s @@ -0,0 +1,291 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User-mode exception support for IA-32 + * FILE: lib/ntdll/rtl/i386/except.s + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: This file is shared with ntoskrnl/rtl/i386/except.s. + * Please keep them in sync. + */ + +#define EXCEPTION_UNWINDING 0x02 + +#define EREC_FLAGS 0x04 + +#define ExceptionContinueExecution 0 +#define ExceptionContinueSearch 1 +#define ExceptionNestedException 2 +#define ExceptionCollidedUnwind 3 + +.globl _RtlpExecuteHandlerForException +.globl _RtlpExecuteHandlerForUnwind + +#define CONTEXT_FLAGS 0x00 +#define CONTEXT_SEGGS 0x8C +#define CONTEXT_SEGFS 0x90 +#define CONTEXT_SEGES 0x94 +#define CONTEXT_SEGDS 0x98 +#define CONTEXT_EDI 0x9C +#define CONTEXT_ESI 0xA0 +#define CONTEXT_EBX 0xA4 +#define CONTEXT_EDX 0xA8 +#define CONTEXT_ECX 0xAC +#define CONTEXT_EAX 0xB0 +#define CONTEXT_EBP 0xB4 +#define CONTEXT_EIP 0xB8 +#define CONTEXT_SEGCS 0xBC +#define CONTEXT_EFLAGS 0xC0 +#define CONTEXT_ESP 0xC4 +#define CONTEXT_SEGSS 0xC8 + + +#define RCC_CONTEXT 0x08 + +// EAX = value to print +_do_debug: + pushal + pushl %eax + call _AsmDebug@4 + popal + ret + +#ifndef __NTOSKRNL__ + +// +// VOID +// RtlpCaptureContext(PCONTEXT pContext); +// +// Parameters: +// [ESP+08h] - PCONTEXT_X86 pContext +// Registers: +// None +// Returns: +// Nothing +// Notes: +// Grabs the current CPU context. +.globl _RtlpCaptureContext +_RtlpCaptureContext: + pushl %ebp + movl %esp, %ebp + movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure + + cld + pushf + pop %eax + movl %eax, CONTEXT_EFLAGS(%edx) + xorl %eax, %eax + movl %eax, CONTEXT_EAX(%edx) + movl %eax, CONTEXT_EBX(%edx) + movl %eax, CONTEXT_ECX(%edx) + movl %eax, CONTEXT_EDX(%edx) + movl %eax, CONTEXT_ESI(%edx) + movl %eax, CONTEXT_EDI(%edx) + movl %cs, %eax + movl %eax, CONTEXT_SEGCS(%edx) + movl %ds, %eax + movl %eax, CONTEXT_SEGDS(%edx) + movl %es, %eax + movl %eax, CONTEXT_SEGES(%edx) + movl %fs, %eax + movl %eax, CONTEXT_SEGFS(%edx) + movl %gs, %eax + movl %eax, CONTEXT_SEGGS(%edx) + movl %ss, %eax + movl %eax, CONTEXT_SEGSS(%edx) + + // + // STACK LAYOUT: - (ESP to put in context structure) + // - RETURN ADDRESS OF CALLER OF CALLER + // - EBP OF CALLER OF CALLER + // ... + // - RETURN ADDRESS OF CALLER + // - EBP OF CALLER + // ... + // + + // Get return address of the caller of the caller of this function + movl %ebp, %ebx + //movl 4(%ebx), %eax // EAX = return address of caller + movl (%ebx), %ebx // EBX = EBP of caller + + movl 4(%ebx), %eax // EAX = return address of caller of caller + movl (%ebx), %ebx // EBX = EBP of caller of caller + + movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller + movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller + addl $8, %ebx + movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8 + + movl %ebp, %esp + popl %ebp + ret + +#endif /* !__NTOSKRNL__ */ + +#define REH_ERECORD 0x08 +#define REH_RFRAME 0x0C +#define REH_CONTEXT 0x10 +#define REH_DCONTEXT 0x14 +#define REH_EROUTINE 0x18 + +// Parameters: +// None +// Registers: +// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord +// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame +// [EBP+10h] - PVOID Context +// [EBP+14h] - PVOID DispatcherContext +// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine +// EDX - Address of protecting exception handler +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// Setup the protecting exception handler and call the exception +// handler in the right context. +_RtlpExecuteHandler: + pushl %ebp + movl %esp, %ebp + pushl REH_RFRAME(%ebp) + + pushl %edx + pushl %fs:0x0 + movl %esp, %fs:0x0 + + // Prepare to call the exception handler + pushl REH_DCONTEXT(%ebp) + pushl REH_CONTEXT(%ebp) + pushl REH_RFRAME(%ebp) + pushl REH_ERECORD(%ebp) + + // Now call the exception handler + movl REH_EROUTINE(%ebp), %eax + call *%eax + + cmpl $-1, %fs:0x0 + jne .reh_stack_looks_ok + + // This should not happen + pushl 0 + pushl 0 + pushl 0 + pushl 0 + call _RtlAssert@16 + +.reh_loop: + jmp .reh_loop + +.reh_stack_looks_ok: + movl %fs:0x0, %esp + + // Return to the 'front-end' for this function + popl %fs:0x0 + movl %ebp, %esp + popl %ebp + ret + + +#define REP_ERECORD 0x04 +#define REP_RFRAME 0x08 +#define REP_CONTEXT 0x0C +#define REP_DCONTEXT 0x10 + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// This exception handler protects the exception handling +// mechanism by detecting nested exceptions. +_RtlpExceptionProtector: + movl $ExceptionContinueSearch, %eax + movl REP_ERECORD(%esp), %ecx + testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) + jnz .rep_end + + // Unwinding is not taking place, so return ExceptionNestedException + + // Set DispatcherContext field to the exception registration for the + // exception handler that executed when a nested exception occurred + movl REP_DCONTEXT(%esp), %ecx + movl REP_RFRAME(%esp), %eax + movl %eax, (%ecx) + movl $ExceptionNestedException, %eax + +.rep_end: + ret + + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// Front-end +_RtlpExecuteHandlerForException: + movl $_RtlpExceptionProtector, %edx + jmp _RtlpExecuteHandler + + +#define RUP_ERECORD 0x04 +#define RUP_RFRAME 0x08 +#define RUP_CONTEXT 0x0C +#define RUP_DCONTEXT 0x10 + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// This exception handler protects the exception handling +// mechanism by detecting collided unwinds. +_RtlpUnwindProtector: + movl $ExceptionContinueSearch, %eax + movl %ecx, RUP_ERECORD(%esp) + testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) + jz .rup_end + + // Unwinding is taking place, so return ExceptionCollidedUnwind + + movl RUP_RFRAME(%esp), %ecx + movl RUP_DCONTEXT(%esp), %edx + + // Set DispatcherContext field to the exception registration for the + // exception handler that executed when a collision occurred + movl RUP_RFRAME(%ecx), %eax + movl %eax, (%edx) + movl $ExceptionCollidedUnwind, %eax + +.rup_end: + ret + + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +_RtlpExecuteHandlerForUnwind: + movl $_RtlpUnwindProtector, %edx + jmp _RtlpExecuteHandler diff --git a/lib/ntdll/rtl/i386/exception.c b/lib/ntdll/rtl/i386/exception.c new file mode 100755 index 0000000..f3803ed --- /dev/null +++ b/lib/ntdll/rtl/i386/exception.c @@ -0,0 +1,433 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User-mode exception support for IA-32 + * FILE: lib/ntdll/rtl/i386/exception.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +/* Implemented in except.s */ + +VOID +RtlpCaptureContext(PCONTEXT pContext); + +/* Macros that will help streamline the SEH implementations for + kernel mode and user mode */ + +#define SehpGetStackLimits(StackBase, StackLimit) \ +{ \ + (*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \ + (*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \ +} + +#define SehpGetExceptionList() \ + (PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList) + +#define SehpSetExceptionList(NewExceptionList) \ + NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList) + +#define SehpCaptureContext(Context) \ +{ \ + RtlpCaptureContext(Context); \ +} + +/*** Code below this line is shared with ntoskrnl/rtl/i386/exception.c - please keep in sync ***/ + +VOID STDCALL +AsmDebug(ULONG Value) +{ + DbgPrint("Value 0x%.08x\n", Value); +} + + +/* Declare a few prototypes for the functions in except.s */ + +EXCEPTION_DISPOSITION +RtlpExecuteHandlerForException( + PEXCEPTION_RECORD ExceptionRecord, + PEXCEPTION_REGISTRATION RegistrationFrame, + PCONTEXT Context, + PVOID DispatcherContext, + PEXCEPTION_HANDLER ExceptionHandler); + +EXCEPTION_DISPOSITION +RtlpExecuteHandlerForUnwind( + PEXCEPTION_RECORD ExceptionRecord, + PEXCEPTION_REGISTRATION RegistrationFrame, + PCONTEXT Context, + PVOID DispatcherContext, + PEXCEPTION_HANDLER ExceptionHandler); + + +#ifndef NDEBUG + +VOID RtlpDumpExceptionRegistrations(VOID) +{ + PEXCEPTION_REGISTRATION Current; + + DbgPrint("Dumping exception registrations:\n"); + + Current = SehpGetExceptionList(); + + if ((ULONG_PTR)Current != -1) + { + while ((ULONG_PTR)Current != -1) + { + DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler); + Current = Current->prev; + } + DbgPrint(" End-Of-List\n"); + } else { + DbgPrint(" No exception registrations exists.\n"); + } +} + +#endif /* NDEBUG */ + +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) +{ + PEXCEPTION_REGISTRATION RegistrationFrame; + DWORD DispatcherContext; + DWORD ReturnValue; + + DPRINT("RtlpDispatchException()\n"); + +#ifndef NDEBUG + RtlpDumpExceptionRegistrations(); +#endif /* NDEBUG */ + + RegistrationFrame = SehpGetExceptionList(); + + DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame); + + while ((ULONG_PTR)RegistrationFrame != -1) + { + EXCEPTION_RECORD ExceptionRecord2; + DWORD Temp = 0; + //PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8; + + // Make sure the registration frame is located within the stack + + DPRINT("Error checking\n"); +#if 0 + if (Teb->Tib.StackBase > RegistrationFrameEnd) + { + DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n", + Teb->Tib.StackBase, RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } + // FIXME: Stack top, correct? + if (Teb->Tib.StackLimit < RegistrationFrameEnd) + { + DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n", + Teb->Tib.StackLimit, RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } + + // Make sure stack is DWORD aligned + if ((ULONG_PTR)RegistrationFrame & 3) + { + DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n", + RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } +#endif + +#if 0 + /* FIXME: */ + if (someFlag) + RtlpLogLastExceptionDisposition( hLog, retValue ); +#endif + + DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler); + DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord); + DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame); + DPRINT("Context 0x%X\n", Context); + DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext); + + ReturnValue = RtlpExecuteHandlerForException( + ExceptionRecord, + RegistrationFrame, + Context, + &DispatcherContext, + RegistrationFrame->handler); + + DPRINT("Exception handler said 0x%X\n", ReturnValue); + DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame); + { + PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08); + DPRINT("StandardESP == 0x%.08x\n", sp[0]); + DPRINT("Exception Pointers == 0x%.08x\n", sp[1]); + DPRINT("PrevFrame == 0x%.08x\n", sp[2]); + DPRINT("Handler == 0x%.08x\n", sp[3]); + DPRINT("ScopeTable == 0x%.08x\n", sp[4]); + DPRINT("TryLevel == 0x%.08x\n", sp[5]); + DPRINT("EBP == 0x%.08x\n", sp[6]); + } + + if (RegistrationFrame == NULL) + { + ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag + } + + if (ReturnValue == ExceptionContinueExecution) + { + DPRINT("ReturnValue == ExceptionContinueExecution\n"); + if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) + { + DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n"); + + ExceptionRecord2.ExceptionRecord = ExceptionRecord; + ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; + ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ExceptionRecord2.NumberParameters = 0; + RtlRaiseException(&ExceptionRecord2); + } + else + { + /* Copy the (possibly changed) context back to the trap frame and return */ + NtContinue(Context, FALSE); + return ExceptionContinueExecution; + } + } + else if (ReturnValue == ExceptionContinueSearch) + { + DPRINT("ReturnValue == ExceptionContinueSearch\n"); + + /* Nothing to do here */ + } + else if (ReturnValue == ExceptionNestedException) + { + DPRINT("ReturnValue == ExceptionNestedException\n"); + + ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND; + if (DispatcherContext > Temp) + { + Temp = DispatcherContext; + } + } + else /* if (ReturnValue == ExceptionCollidedUnwind) */ + { + DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n"); + + ExceptionRecord2.ExceptionRecord = ExceptionRecord; + ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; + ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ExceptionRecord2.NumberParameters = 0; + RtlRaiseException(&ExceptionRecord2); + } + + RegistrationFrame = RegistrationFrame->prev; // Go to previous frame + } + + /* No exception handler will handle this exception */ + + DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n"); + + return ExceptionContinueExecution; +} + +VOID STDCALL +RtlRaiseStatus(NTSTATUS Status) +{ + EXCEPTION_RECORD ExceptionRecord; + + DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status); + + ExceptionRecord.ExceptionCode = Status; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.NumberParameters = 0; + ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + RtlRaiseException (& ExceptionRecord); +} + +VOID STDCALL +RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame, + PVOID ReturnAddress, + PEXCEPTION_RECORD ExceptionRecord, + DWORD EaxValue) +{ + PEXCEPTION_REGISTRATION ERHead; + PEXCEPTION_RECORD pExceptRec; + EXCEPTION_RECORD TempER; + CONTEXT Context; + + DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame); + +#ifndef NDEBUG + RtlpDumpExceptionRegistrations(); +#endif /* NDEBUG */ + + ERHead = SehpGetExceptionList(); + + DPRINT("ERHead is 0x%X\n", ERHead); + + if (ExceptionRecord == NULL) // The normal case + { + DPRINT("ExceptionRecord == NULL (normal)\n"); + + pExceptRec = &TempER; + pExceptRec->ExceptionFlags = 0; + pExceptRec->ExceptionCode = STATUS_UNWIND; + pExceptRec->ExceptionRecord = NULL; + pExceptRec->ExceptionAddress = ReturnAddress; + pExceptRec->ExceptionInformation[0] = 0; + } + + if (RegistrationFrame) + pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING; + else + pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND); + +#ifndef NDEBUG + DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags); + if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING) + { + DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING); + } + if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND) + { + DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND); + } +#endif /* NDEBUG */ + + Context.ContextFlags = + (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); + + SehpCaptureContext(&Context); + + DPRINT("Context.Eip = 0x%.08x\n", Context.Eip); + DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp); + DPRINT("Context.Esp = 0x%.08x\n", Context.Esp); + + Context.Esp += 0x10; + Context.Eax = EaxValue; + + // Begin traversing the list of EXCEPTION_REGISTRATION + while ((ULONG_PTR)ERHead != -1) + { + EXCEPTION_RECORD er2; + + DPRINT("ERHead 0x%X\n", ERHead); + + if (ERHead == RegistrationFrame) + { + DPRINT("Continueing execution\n"); + NtContinue(&Context, FALSE); + return; + } + else + { + // If there's an exception frame, but it's lower on the stack + // than the head of the exception list, something's wrong! + if (RegistrationFrame && (RegistrationFrame <= ERHead)) + { + DPRINT("The exception frame is bad\n"); + + // Generate an exception to bail out + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + } + +#if 0 + Stack = ERHead + sizeof(EXCEPTION_REGISTRATION); + if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead + && (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple + && (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane) + { +#else + if (1) { +#endif + PEXCEPTION_REGISTRATION NewERHead; + PEXCEPTION_REGISTRATION pCurrExceptReg; + EXCEPTION_DISPOSITION ReturnValue; + + DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler); + + ReturnValue = RtlpExecuteHandlerForUnwind( + pExceptRec, + ERHead, + &Context, + &NewERHead, + ERHead->handler); + + DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue); + + if (ReturnValue != ExceptionContinueSearch) + { + if (ReturnValue != ExceptionCollidedUnwind) + { + DPRINT("Bad return value\n"); + + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_INVALID_DISPOSITION; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + else + { + ERHead = NewERHead; + } + } + + pCurrExceptReg = ERHead; + ERHead = ERHead->prev; + + DPRINT("New ERHead is 0x%X\n", ERHead); + + DPRINT("Setting exception registration at 0x%X as current\n", + RegistrationFrame->prev); + + // Unlink the exception handler + SehpSetExceptionList(RegistrationFrame->prev); + } + else // The stack looks goofy! Raise an exception to bail out + { + DPRINT("Bad stack\n"); + + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_BAD_STACK; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + } + + // If we get here, we reached the end of the EXCEPTION_REGISTRATION list. + // This shouldn't happen normally. + + DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n", + RegistrationFrame); + + if ((ULONG_PTR)RegistrationFrame == -1) + NtContinue(&Context, FALSE); + else + NtRaiseException(pExceptRec, &Context, 0); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/image.c b/lib/ntdll/rtl/image.c new file mode 100644 index 0000000..66c3360 --- /dev/null +++ b/lib/ntdll/rtl/image.c @@ -0,0 +1,146 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/image.c + * PURPOSE: Image handling functions + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 17/03/2000 Created + */ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +PIMAGE_NT_HEADERS STDCALL +RtlImageNtHeader (IN PVOID BaseAddress) +{ + PIMAGE_NT_HEADERS NtHeader; + PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress; + + if (DosHeader && DosHeader->e_magic != IMAGE_DOS_SIGNATURE) + { + DPRINT1("DosHeader->e_magic %x\n", DosHeader->e_magic); + DPRINT1("NtHeader %x\n", (BaseAddress + DosHeader->e_lfanew)); + } + +// if (DosHeader && DosHeader->e_magic == IMAGE_DOS_SIGNATURE) +// { + NtHeader = (PIMAGE_NT_HEADERS)(BaseAddress + DosHeader->e_lfanew); + if (NtHeader->Signature == IMAGE_NT_SIGNATURE) + return NtHeader; +// } + return NULL; +} + + +PVOID +STDCALL +RtlImageDirectoryEntryToData ( + PVOID BaseAddress, + BOOLEAN bFlag, + ULONG Directory, + PULONG Size + ) +{ + PIMAGE_NT_HEADERS NtHeader; + PIMAGE_SECTION_HEADER SectionHeader; + ULONG Va; + ULONG Count; + + NtHeader = RtlImageNtHeader (BaseAddress); + if (NtHeader == NULL) + return NULL; + + if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) + return NULL; + + Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress; + if (Va == 0) + return NULL; + + if (Size) + *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size; + + if (bFlag) + return (PVOID)(BaseAddress + Va); + + /* image mapped as ordinary file, we must find raw pointer */ + SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1); + Count = NtHeader->FileHeader.NumberOfSections; + while (Count--) + { + if (SectionHeader->VirtualAddress == Va) + return (PVOID)(BaseAddress + SectionHeader->PointerToRawData); + SectionHeader++; + } + + return NULL; +} + + +PIMAGE_SECTION_HEADER +STDCALL +RtlImageRvaToSection ( + PIMAGE_NT_HEADERS NtHeader, + PVOID BaseAddress, + ULONG Rva + ) +{ + PIMAGE_SECTION_HEADER Section; + ULONG Va; + ULONG Count; + + Count = NtHeader->FileHeader.NumberOfSections; + Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader + + NtHeader->FileHeader.SizeOfOptionalHeader); + while (Count) + { + Va = Section->VirtualAddress; + if ((Va <= Rva) && + (Rva < Va + Section->SizeOfRawData)) + return Section; + Section++; + } + return NULL; +} + + +ULONG +STDCALL +RtlImageRvaToVa ( + PIMAGE_NT_HEADERS NtHeader, + PVOID BaseAddress, + ULONG Rva, + PIMAGE_SECTION_HEADER *SectionHeader + ) +{ + PIMAGE_SECTION_HEADER Section = NULL; + + if (SectionHeader) + Section = *SectionHeader; + + if (Section == NULL || + Rva < Section->VirtualAddress || + Rva >= Section->VirtualAddress + Section->SizeOfRawData) + { + Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva); + if (Section == NULL) + return 0; + + if (SectionHeader) + *SectionHeader = Section; + } + + return (ULONG)(BaseAddress + + Rva + + Section->PointerToRawData - + Section->VirtualAddress); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/intrlck.c b/lib/ntdll/rtl/intrlck.c new file mode 100644 index 0000000..5e91816 --- /dev/null +++ b/lib/ntdll/rtl/intrlck.c @@ -0,0 +1,163 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/intrlck.c + * PURPOSE: Inter lock increments + * UPDATE HISTORY: + * Created 30/09/99 + */ + +/* + * Win32 kernel functions + * + * Copyright 1995 Martin von Loewis + * Copyright 1997 Onno Hovers + * Copied from kernel32 + */ + + +/************************************************************************ +* InterlockedIncrement * +* * +* InterlockedIncrement adds 1 to a long variable and returns * +* - a negative number if the result < 0 * +* - zero if the result == 0 * +* - a positive number if the result > 0 * +* * +* The returned number need not be equal to the result!!!! * +* note: * +* * +************************************************************************/ + +#include + +LONG +STDCALL +InterlockedIncrement(PLONG Addend) +{ + long ret = 0; + __asm__ + ( + "\tlock\n" /* for SMP systems */ + "\tincl (%1)\n" + "\tje 2f\n" + "\tjl 1f\n" + "\tincl %0\n" + "\tjmp 2f\n" + "1:\tdec %0\n" + "2:\n" + :"=r" (ret):"r" (Addend), "0" (0): "memory" + ); + return ret; +} + +/************************************************************************ +* InterlockedDecrement * +* * +* InterlockedIncrement adds 1 to a long variable and returns * +* - a negative number if the result < 0 * +* - zero if the result == 0 * +* - a positive number if the result > 0 * +* * +* The returned number need not be equal to the result!!!! * +************************************************************************/ + +LONG +STDCALL +InterlockedDecrement(LPLONG lpAddend) +{ + long ret; + __asm__ + ( + "\tlock\n" /* for SMP systems */ + "\tdecl (%1)\n" + "\tje 2f\n" + "\tjl 1f\n" + "\tincl %0\n" + "\tjmp 2f\n" + "1:\tdec %0\n" + "2:\n" + :"=r" (ret):"r" (lpAddend), "0" (0): "memory" + ); + return ret; + + +} + +/************************************************************************ + * InterlockedExchange + * + * Atomically exchanges a pair of values. + * + * RETURNS + * Prior value of value pointed to by Target + */ + +LONG +STDCALL +InterlockedExchange(LPLONG target, LONG value ) +{ + + long ret; + __asm__ ( /* lock for SMP systems */ + "lock\n\txchgl %0,(%1)" + :"=r" (ret):"r" (target), "0" (value):"memory" ); + return ret; + + +} + +/************************************************************************ + * InterlockedCompareExchange + * + * Atomically compares Destination and Comperand, and if found equal exchanges + * the value of Destination with Exchange + * + * RETURNS + * Prior value of value pointed to by Destination + */ +PVOID +STDCALL +InterlockedCompareExchange( + PVOID *Destination, + PVOID Exchange, + PVOID Comperand ) +{ + PVOID ret; + __asm__ ( /* lock for SMP systems */ + "lock\n\t" + "cmpxchgl %2,(%1)" + :"=r" (ret) + :"r" (Destination),"r" (Exchange), "0" (Comperand) + :"memory" ); + return ret; + +} + +/************************************************************************ + * InterlockedExchangeAdd + * + * Atomically adds Increment to Addend and returns the previous value of + * Addend + * + * RETURNS + * Prior value of value pointed to by Addend + */ +LONG +STDCALL +InterlockedExchangeAdd( + PLONG Addend, + LONG Increment +) +{ + + LONG ret; + __asm__ ( /* lock for SMP systems */ + "lock\n\t" + "xaddl %0,(%1)" + :"=r" (ret) + :"r" (Addend), "0" (Increment) + :"memory" ); + return ret; + +} diff --git a/lib/ntdll/rtl/largeint.c b/lib/ntdll/rtl/largeint.c new file mode 100644 index 0000000..3cc9e5f --- /dev/null +++ b/lib/ntdll/rtl/largeint.c @@ -0,0 +1,250 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/largeint.c + * PURPOSE: Large integer operations + * UPDATE HISTORY: + * Created 22/05/98 + * 08/30/98 RJJ Implemented several functions + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +LARGE_INTEGER +STDCALL +RtlConvertLongToLargeInteger ( + LONG SignedInteger + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = SignedInteger; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlConvertUlongToLargeInteger ( + ULONG UnsignedInteger + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = UnsignedInteger; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlEnlargedIntegerMultiply ( + LONG Multiplicand, + LONG Multiplier + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = (LONGLONG) Multiplicand * Multiplier; + + return RC; +} + +ULONG +STDCALL +RtlEnlargedUnsignedDivide ( + ULARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ) +{ + if (Remainder) + *Remainder = Dividend.QuadPart % Divisor; + + return (ULONG)(Dividend.QuadPart / Divisor); +} + +LARGE_INTEGER +STDCALL +RtlEnlargedUnsignedMultiply ( + ULONG Multiplicand, + ULONG Multiplier + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlExtendedIntegerMultiply ( + LARGE_INTEGER Multiplicand, + LONG Multiplier + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = Multiplicand.QuadPart * Multiplier; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlExtendedLargeIntegerDivide ( + LARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ) +{ + LARGE_INTEGER RC; + + if (Remainder) + *Remainder = Dividend.QuadPart % Divisor; + + RC.QuadPart = Dividend.QuadPart / Divisor; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlExtendedMagicDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER MagicDivisor, + CCHAR ShiftCount + ) +{ + UNIMPLEMENTED; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerAdd ( + LARGE_INTEGER Addend1, + LARGE_INTEGER Addend2 + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerArithmeticShift ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ) +{ + LARGE_INTEGER RC; + CHAR Shift; + + Shift = ShiftCount % 64; + + if (Shift < 32) + { + RC.QuadPart = LargeInteger.QuadPart >> Shift; + } + else + { + /* copy the sign bit */ + RC.u.HighPart |= (LargeInteger.u.HighPart & 0x80000000); + RC.u.LowPart = LargeInteger.u.HighPart >> Shift; + } + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER Divisor, + PLARGE_INTEGER Remainder + ) +{ + LARGE_INTEGER RC; + + if (Remainder) + Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart; + + RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerNegate ( + LARGE_INTEGER Subtrahend + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = - Subtrahend.QuadPart; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerShiftLeft ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ) +{ + LARGE_INTEGER RC; + CCHAR Shift; + + Shift = ShiftCount % 64; + RC.QuadPart = LargeInteger.QuadPart << Shift; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerShiftRight ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ) +{ + LARGE_INTEGER RC; + CCHAR Shift; + + Shift = ShiftCount % 64; + RC.QuadPart = LargeInteger.QuadPart >> Shift; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerSubtract ( + LARGE_INTEGER Minuend, + LARGE_INTEGER Subtrahend + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart; + + return RC; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/luid.c b/lib/ntdll/rtl/luid.c new file mode 100644 index 0000000..20b0a7a --- /dev/null +++ b/lib/ntdll/rtl/luid.c @@ -0,0 +1,49 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Locally unique identifier (LUID) helper functions + * FILE: lib/ntdll/rtl/luid.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 15/04/2000: Created + */ + +/* INCLUDES *****************************************************************/ + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +RtlCopyLuid(PLUID LuidDest, + PLUID LuidSrc) +{ + LuidDest->QuadPart = LuidSrc->QuadPart; +} + + +VOID STDCALL +RtlCopyLuidAndAttributesArray(ULONG Count, + PLUID_AND_ATTRIBUTES Src, + PLUID_AND_ATTRIBUTES Dest) +{ + ULONG i; + + for (i = 0; i < Count; i++) + { + RtlCopyMemory(&Dest[i], + &Src[i], + sizeof(LUID_AND_ATTRIBUTES)); + } +} + + +BOOLEAN STDCALL +RtlEqualLuid(PLUID Luid1, + PLUID Luid2) +{ + return((Luid1->QuadPart == Luid2->QuadPart) ? TRUE : FALSE); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/math.c b/lib/ntdll/rtl/math.c new file mode 100644 index 0000000..028951b --- /dev/null +++ b/lib/ntdll/rtl/math.c @@ -0,0 +1,197 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +double atan (double __x); +double ceil (double __x); +double cos (double __x); +double fabs (double __x); +double floor (double __x); +long _ftol (double fl); +double log (double __x); +double __log2 (double __x); +double pow (double __x, double __y); +double sin (double __x); +double sqrt (double __x); +double tan (double __x); + + +double atan (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fpatan" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double ceil (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + +double cos (double __x) +{ + register double __value; + __asm __volatile__ + ("fcos" + : "=t" (__value): "0" (__x)); + + return __value; +} + +double fabs (double __x) +{ + register double __value; + __asm __volatile__ + ("fabs" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double floor (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + +long _ftol (double fl) +{ + return (long)fl; +} + +double log (double __x) +{ + register double __value; + __asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double __log2 (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double pow (double __x, double __y) +{ + register double __value, __exponent; + long __p = (long) __y; + + if (__x == 0.0 && __y > 0.0) + return 0.0; + if (__y == (double) __p) + { + double __r = 1.0; + if (__p == 0) + return 1.0; + if (__p < 0) + { + __p = -__p; + __x = 1.0 / __x; + } + while (1) + { + if (__p & 1) + __r *= __x; + __p >>= 1; + if (__p == 0) + return __r; + __x *= __x; + } + /* NOTREACHED */ + } + __asm __volatile__ + ("fmul %%st(1) # y * log2(x)\n\t" + "fst %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +double sin (double __x) +{ + register double __value; + __asm __volatile__ + ("fsin" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double sqrt (double __x) +{ + register double __value; + __asm __volatile__ + ("fsqrt" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double tan (double __x) +{ + register double __value; + register double __value2 __attribute__ ((unused)); + __asm __volatile__ + ("fptan" + : "=t" (__value2), "=u" (__value) : "0" (__x)); + + return __value; +} diff --git a/lib/ntdll/rtl/mem.c b/lib/ntdll/rtl/mem.c new file mode 100644 index 0000000..d117b28 --- /dev/null +++ b/lib/ntdll/rtl/mem.c @@ -0,0 +1,156 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: kernel/rtl/mem.c + * PURPOSE: Memory functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +ULONG +STDCALL +RtlCompareMemory(PVOID Source1, PVOID Source2, ULONG Length) +/* + * FUNCTION: Compares blocks of memory and returns the number of equal bytes + * ARGUMENTS: + * Source1 = Block to compare + * Source2 = Block to compare + * Length = Number of bytes to compare + * RETURNS: Number of equal bytes + */ +{ + int i,total; + + for (i=0,total=0;i 0) + { + *Dest = Fill; + Dest++; + Count--; + } +} + + +VOID +STDCALL +RtlZeroMemory ( + PVOID Destination, + ULONG Length + ) +{ + RtlFillMemory ( + Destination, + Length, + 0 + ); +} + + +VOID +STDCALL +RtlMoveMemory ( + PVOID Destination, + CONST VOID * Source, + ULONG Length + ) +{ + memmove ( + Destination, + Source, + Length + ); +} + + +/* EOF */ diff --git a/lib/ntdll/rtl/message.c b/lib/ntdll/rtl/message.c new file mode 100644 index 0000000..c21387a --- /dev/null +++ b/lib/ntdll/rtl/message.c @@ -0,0 +1,123 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Message table functions + * FILE: lib/ntdll/rtl/message.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 29/05/2001: Created + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +RtlFindMessage(PVOID BaseAddress, + ULONG Type, + ULONG Language, + ULONG MessageId, + PRTL_MESSAGE_RESOURCE_ENTRY *MessageResourceEntry) +{ + LDR_RESOURCE_INFO ResourceInfo; + PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry; + PRTL_MESSAGE_RESOURCE_DATA MessageTable; + NTSTATUS Status; + ULONG EntryOffset, IdOffset; + PRTL_MESSAGE_RESOURCE_ENTRY MessageEntry; + ULONG i; + + DPRINT("RtlFindMessage()\n"); + + ResourceInfo.Type = Type; + ResourceInfo.Name = 1; + ResourceInfo.Language = Language; + + Status = LdrFindResource_U(BaseAddress, + &ResourceInfo, + RESOURCE_DATA_LEVEL, + &ResourceDataEntry); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("ResourceDataEntry: %p\n", ResourceDataEntry); + + Status = LdrAccessResource(BaseAddress, + ResourceDataEntry, + (PVOID*)&MessageTable, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("MessageTable: %p\n", MessageTable); + + DPRINT("NumberOfBlocks %lu\n", MessageTable->NumberOfBlocks); + for (i = 0; i < MessageTable->NumberOfBlocks; i++) + { + DPRINT("LoId 0x%08lx HiId 0x%08lx Offset 0x%08lx\n", + MessageTable->Blocks[i].LowId, + MessageTable->Blocks[i].HighId, + MessageTable->Blocks[i].OffsetToEntries); + } + + for (i = 0; i < MessageTable->NumberOfBlocks; i++) + { + if ((MessageId >= MessageTable->Blocks[i].LowId) && + (MessageId <= MessageTable->Blocks[i].HighId)) + { + EntryOffset = MessageTable->Blocks[i].OffsetToEntries; + IdOffset = MessageId - MessageTable->Blocks[i].LowId; + break; + } + + if (MessageId < MessageTable->Blocks[i].LowId) + { + return STATUS_MESSAGE_NOT_FOUND; + } + } + + MessageEntry = (PRTL_MESSAGE_RESOURCE_ENTRY)((PUCHAR)MessageTable + MessageTable->Blocks[i].OffsetToEntries); + + DPRINT("EntryOffset 0x%08lx\n", EntryOffset); + DPRINT("IdOffset 0x%08lx\n", IdOffset); + + DPRINT("MessageEntry: %p\n", MessageEntry); + for (i = 0; i < IdOffset; i++) + { + MessageEntry = (PRTL_MESSAGE_RESOURCE_ENTRY)((PUCHAR)MessageEntry + (ULONG)MessageEntry->Length); + } + + if (MessageEntry->Flags == 0) + { + DPRINT("AnsiText: %s\n", MessageEntry->Text); + } + else + { + DPRINT("UnicodeText: %S\n", (PWSTR)MessageEntry->Text); + } + + if (MessageResourceEntry != NULL); + { + *MessageResourceEntry = MessageEntry; + } + + return(STATUS_SUCCESS); +} + + +/* +RtlFormatMessage + */ + +/* EOF */ diff --git a/lib/ntdll/rtl/misc.c b/lib/ntdll/rtl/misc.c new file mode 100644 index 0000000..4b9cf76 --- /dev/null +++ b/lib/ntdll/rtl/misc.c @@ -0,0 +1,77 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Various functions + * FILE: lib/ntdll/rtl/misc.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 10/08/2000: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* GLOBALS ******************************************************************/ + +extern ULONG NtGlobalFlag; + +/* FUNCTIONS ****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * RtlGetNtGlobalFlags + * + * DESCRIPTION + * Retrieves the global os flags. + * + * ARGUMENTS + * None + * + * RETURN VALUE + * global flags + * + * REVISIONS + * 2000-08-10 ekohl + */ + +ULONG STDCALL +RtlGetNtGlobalFlags(VOID) +{ + return(NtGlobalFlag); +} + + +/********************************************************************** + * NAME EXPORTED + * RtlGetNtProductType + * + * DESCRIPTION + * Retrieves the OS product type. + * + * ARGUMENTS + * ProductType Pointer to the product type variable. + * + * RETURN VALUE + * TRUE if successful, otherwise FALSE + * + * NOTE + * ProductType can be one of the following values: + * 1 Workstation (Winnt) + * 2 Server (Lanmannt) + * 3 Advanced Server (Servernt) + * + * REVISIONS + * 2000-08-10 ekohl + */ + +BOOLEAN STDCALL +RtlGetNtProductType(PNT_PRODUCT_TYPE ProductType) +{ + *ProductType = SharedUserData->NtProductType; + return(TRUE); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/nls.c b/lib/ntdll/rtl/nls.c new file mode 100644 index 0000000..428d39d --- /dev/null +++ b/lib/ntdll/rtl/nls.c @@ -0,0 +1,543 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/nls.c + * PURPOSE: National Language Support (NLS) functions + * UPDATE HISTORY: + * 20/08/99 Created by Emanuele Aliberti + * 10/11/99 Added translation functions. + * + * NOTE: + * Multi-byte code pages are not supported yet. Even single-byte code + * pages are not supported properly. Only stupid CHAR->WCHAR and + * WCHAR->CHAR (Attention: data loss!!!) translation is done. + * + * TODO: + * 1) Implement code to initialize the translation tables. + * 2) Use fixed translation table for translation. + * 3) Add loading of translation tables (NLS files). + * 4) Implement unicode upcase and downcase handling. + * 5) Add multi-byte translation code. + */ + +#include +//#include + + +BOOLEAN +NlsMbCodePageTag = FALSE; + +BOOLEAN +NlsMbOemCodePageTag = FALSE; + +BYTE +NlsLeadByteInfo = 0; /* ? */ + +USHORT +NlsOemLeadByteInfo = 0; + +USHORT +NlsAnsiCodePage = 0; + +USHORT +NlsOemCodePage = 0; /* not exported */ + +#if 0 +PWCHAR NlsAnsiToUnicodeTable = NULL; +PWCHAR NlsOemToUnicodeTable = NULL; + +PCHAR NlsUnicodeToAnsiTable = NULL; +PCHAR NlsUnicodeToOemTable = NULL; + +PWCHAR NlsUnicodeUpcaseTable = NULL; +PWCHAR NlsUnicodeLowercaseTable = NULL; +#endif + + +/* FUNCTIONS *****************************************************************/ + +/* + * Missing functions: + * RtlInitCodePageTable + * RtlInitNlsTables + * RtlResetRtlTranslations + */ + +/* + * RtlConsoleMultiByteToUnicodeN@24 + */ + +NTSTATUS +STDCALL +RtlCustomCPToUnicodeN ( + PRTL_NLS_DATA NlsData, + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR CustomString, + ULONG CustomSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsData->DbcsFlag == FALSE) + { + /* single-byte code page */ + if (CustomSize > (UnicodeSize / sizeof(WCHAR))) + Size = UnicodeSize / sizeof(WCHAR); + else + Size = CustomSize; + + if (ResultSize != NULL) + *ResultSize = Size * sizeof(WCHAR); + + for (i = 0; i < Size; i++) + { + *UnicodeString = NlsData->MultiByteToUnicode[(int)*CustomString]; + UnicodeString++; + CustomString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +VOID +STDCALL +RtlGetDefaultCodePage ( + PUSHORT AnsiCodePage, + PUSHORT OemCodePage + ) +{ + *AnsiCodePage = NlsAnsiCodePage; + *OemCodePage = NlsOemCodePage; +} + + +NTSTATUS +STDCALL +RtlMultiByteToUnicodeN ( + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR MbString, + ULONG MbSize + ) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + if (MbSize > (UnicodeSize / sizeof(WCHAR))) + Size = UnicodeSize / sizeof(WCHAR); + else + Size = MbSize; + + if (ResultSize != NULL) + *ResultSize = Size * sizeof(WCHAR); + + for (i = 0; i < Size; i++) + { + *UnicodeString = *MbString; +#if 0 + *UnicodeString = NlsAnsiToUnicodeTable[*MbString]; +#endif + + UnicodeString++; + MbString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlMultiByteToUnicodeSize ( + PULONG UnicodeSize, + PCHAR MbString, + ULONG MbSize + ) +{ + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + *UnicodeSize = MbSize * sizeof (WCHAR); + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlOemToUnicodeN ( + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR OemString, + ULONG OemSize + ) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbOemCodePageTag == FALSE) + { + /* single-byte code page */ + if (OemSize > (UnicodeSize / sizeof(WCHAR))) + Size = UnicodeSize / sizeof(WCHAR); + else + Size = OemSize; + + if (ResultSize != NULL) + *ResultSize = Size * sizeof(WCHAR); + + for (i = 0; i < Size; i++) + { + *UnicodeString = *OemString; +#if 0 + *UnicodeString = NlsOemToUnicodeTable[*OemString]; +#endif + + UnicodeString++; + OemString++; + }; + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUnicodeToCustomCPN ( + PRTL_NLS_DATA NlsData, + PCHAR CustomString, + ULONG CustomSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + ULONG Size = 0; + ULONG i; + + if (NlsData->DbcsFlag == 0) + { + /* single-byte code page */ + if (UnicodeSize > (CustomSize * sizeof(WCHAR))) + Size = CustomSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *CustomString = NlsData->UnicodeToMultiByte[*UnicodeString]; + CustomString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUnicodeToMultiByteN ( + PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (MbSize * sizeof(WCHAR))) + Size = MbSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *MbString = *UnicodeString; +#if 0 + *MbString = UnicodeToAnsiTable[*UnicodeString]; +#endif + + MbString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUnicodeToMultiByteSize ( + PULONG MbSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + *MbSize = UnicodeSize / sizeof (WCHAR); + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUnicodeToOemN ( + PCHAR OemString, + ULONG OemSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbOemCodePageTag == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (OemSize * sizeof(WCHAR))) + Size = OemSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *OemString = *UnicodeString; +#if 0 + *OemString = UnicodeToOemTable[*UnicodeString]; +#endif + + OemString++; + UnicodeString++; + }; + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeToCustomCPN ( + PRTL_NLS_DATA NlsData, + PCHAR CustomString, + ULONG CustomSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + WCHAR UpcaseChar; + ULONG Size = 0; + ULONG i; + + if (NlsData->DbcsFlag == 0) + { + /* single-byte code page */ + if (UnicodeSize > (CustomSize * sizeof(WCHAR))) + Size = CustomSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *CustomString = NlsData->UnicodeToMultiByte[*UnicodeString]; +#if 0 + UpcaseChar = NlsUnicodeUpcaseTable[*UnicodeString]; + *CustomString = NlsData->UnicodeToMultiByte[UpcaseChar]; +#endif + CustomString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeToMultiByteN ( + PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + WCHAR UpcaseChar; + ULONG Size = 0; + ULONG i; + + if (NLS_MB_CODE_PAGE_TAG == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (MbSize * sizeof(WCHAR))) + Size = MbSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *MbString = *UnicodeString; +#if 0 + UpcaseChar = NlsUnicodeUpcaseTable[*UnicodeString]; + *MbString = NlsUnicodeToAnsiTable[UpcaseChar]; +#endif + + MbString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeToOemN ( + PCHAR OemString, + ULONG OemSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize + ) +{ + WCHAR UpcaseChar; + ULONG Size = 0; + ULONG i; + + if (NLS_MB_OEM_CODE_PAGE_TAG == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (OemSize * sizeof(WCHAR))) + Size = OemSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *OemString = *UnicodeString; +#if 0 + UpcaseChar = NlsUnicodeUpcaseTable[*UnicodeString]; + *OemString = UnicodeToOemTable[UpcaseChar]; +#endif + + OemString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + + } + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/path.c b/lib/ntdll/rtl/path.c new file mode 100644 index 0000000..dcdb1c2 --- /dev/null +++ b/lib/ntdll/rtl/path.c @@ -0,0 +1,861 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/path.c + * PURPOSE: Path and current directory functions + * UPDATE HISTORY: + * Created 03/02/00 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* DEFINITONS and MACROS ******************************************************/ + +#define MAX_PFX_SIZE 16 + +#define IS_PATH_SEPARATOR(x) (((x)==L'\\')||((x)==L'/')) + + +/* FUNCTIONS *****************************************************************/ + +static ULONG RtlpGetDotSequence (PWSTR p) +{ + ULONG Count = 0; + + for (;;) + { + if (*p == '.') + Count++; + else if ((*p == '\\' || *p == '\0') && Count) + return Count; + else + return 0; + p++; + } + return 0; +} + + +static VOID RtlpEatPath (PWSTR Path) +{ + PWSTR p, prev; + + p = Path + 2; + prev = p; + + while ((*p) != 0 || ((*p) == L'\\' && (*(p+1)) == 0)) + { + ULONG DotLen; + + DotLen = RtlpGetDotSequence (p+1); + DPRINT("DotSequenceLength %u\n", DotLen); + DPRINT("prev %S p %S\n",prev,p); + + if (DotLen == 0) + { + prev = p; + do + { + p++; + } + while ((*p) != 0 && (*p) != L'\\'); + } + else if (DotLen == 1) + { + wcscpy (p, p+2); + } + else + { + if (DotLen > 2) + { + int n = DotLen - 2; + + while (n > 0 && prev > (Path + 2)) + { + prev--; + if ((*prev) == L'\\') + n--; + } + } + + if (*(p + DotLen + 1) == 0) + *(prev + 1) = 0; + else + wcscpy (prev, p + DotLen + 1); + p = prev; + if (prev > (Path + 2)) + { + prev--; + while ((*prev) != L'\\') + { + prev--; + } + } + } + } +} + + +ULONG STDCALL RtlGetLongestNtPathLength (VOID) +{ + return (MAX_PATH + 9); +} + + +ULONG STDCALL +RtlDetermineDosPathNameType_U(PWSTR Path) +{ + DPRINT("RtlDetermineDosPathNameType_U %S\n", Path); + + if (Path == NULL) + { + return 0; + } + + if (IS_PATH_SEPARATOR(Path[0])) + { + if (!IS_PATH_SEPARATOR(Path[1])) + { + return 4; /* \xxx */ + } + + if (Path[2] != L'.') + return 1; /* \\xxx */ + + if (IS_PATH_SEPARATOR(Path[3])) + return 6; /* \\.\xxx */ + + if (Path[3]) + return 1; /* \\.xxxx */ + + return 7; /* \\. */ + } + else + { + if (Path[1] != L':') + return 5; /* xxx */ + + if (IS_PATH_SEPARATOR(Path[2])) + return 2; /* x:\xxx */ + + return 3; /* x:xxx */ + } +} + + +/* returns 0 if name is not valid DOS device name, or DWORD with + * offset in bytes to DOS device name from beginning of buffer in high word + * and size in bytes of DOS device name in low word */ + +ULONG STDCALL +RtlIsDosDeviceName_U(PWSTR DeviceName) +{ + ULONG Type; + ULONG Length = 0; + ULONG Offset; + PWCHAR wc; + + if (DeviceName == NULL) + { + return 0; + } + + while (DeviceName[Length]) + { + Length++; + } + + Type = RtlDetermineDosPathNameType_U(DeviceName); + if (Type <= 1) + { + return 0; + } + + if (Type == 6) + { + if (Length == 7 && + !_wcsnicmp (DeviceName, L"\\\\.\\CON", 7)) + return 0x00080006; + return 0; + } + + /* name can end with ':' */ + if (Length && DeviceName[Length - 1 ] == L':') + { + Length--; + } + + /* there can be spaces or points at the end of name */ + wc = DeviceName + Length - 1; + while (Length && (*wc == L'.' || *wc == L' ')) + { + Length--; + wc--; + } + + /* let's find a beginning of name */ + wc = DeviceName + Length - 1; + while (wc > DeviceName && !IS_PATH_SEPARATOR(*(wc - 1))) + { + wc--; + } + Offset = wc - DeviceName; + Length -= Offset; + + /* check for LPTx or COMx */ + if (Length == 4 && wc[3] >= L'0' && wc[3] <= L'9') + { + if (wc[3] == L'0') + { + return 0; + } + + if (!_wcsnicmp (wc, L"LPT", 3) || + !_wcsnicmp (wc, L"COM", 3)) + { + return ((Offset * 2) << 16 ) | 8; + } + return 0; + } + + /* check for PRN,AUX,NUL or CON */ + if (Length == 3 && + (!_wcsnicmp (wc, L"PRN", 3) || + !_wcsnicmp (wc, L"AUX", 3) || + !_wcsnicmp (wc, L"NUL", 3) || + !_wcsnicmp (wc, L"CON", 3))) + { + return ((Offset * 2) << 16) | 6; + } + + return 0; +} + + +ULONG STDCALL +RtlGetCurrentDirectory_U(ULONG MaximumLength, + PWSTR Buffer) +{ + ULONG Length; + PCURDIR cd; + + DPRINT ("RtlGetCurrentDirectory %lu %p\n", MaximumLength, Buffer); + + cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName); + + RtlAcquirePebLock(); + Length = cd->DosPath.Length / sizeof(WCHAR); + if (cd->DosPath.Buffer[Length - 1] == L'\\' && + cd->DosPath.Buffer[Length - 2] != L':') + Length--; + + DPRINT ("cd->DosPath.Buffer %S Length %d\n", + cd->DosPath.Buffer, Length); + + if (MaximumLength / sizeof(WCHAR) > Length) + { + memcpy (Buffer, + cd->DosPath.Buffer, + Length * sizeof(WCHAR)); + Buffer[Length] = 0; + } + else + { + Length++; + } + + RtlReleasePebLock (); + + DPRINT ("CurrentDirectory %S\n", Buffer); + + return (Length * sizeof(WCHAR)); +} + + +NTSTATUS STDCALL +RtlSetCurrentDirectory_U(PUNICODE_STRING name) +{ + UNICODE_STRING full; + UNICODE_STRING envvar; + OBJECT_ATTRIBUTES Attr; + IO_STATUS_BLOCK iosb; + PCURDIR cd; + NTSTATUS Status; + ULONG size; + HANDLE handle = NULL; + PWSTR wcs; + PWSTR buf = 0; + PFILE_NAME_INFORMATION filenameinfo; + ULONG backslashcount = 0; + PWSTR cntr; + WCHAR var[4]; + + DPRINT ("RtlSetCurrentDirectory %wZ\n", name); + + RtlAcquirePebLock (); + cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName; + size = cd->DosPath.MaximumLength; + + buf = RtlAllocateHeap (RtlGetProcessHeap(), + 0, + size); + if (buf == NULL) + { + RtlReleasePebLock (); + return STATUS_NO_MEMORY; + } + + size = RtlGetFullPathName_U (name->Buffer, size, buf, 0); + if (!size) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + buf); + RtlReleasePebLock (); + return STATUS_OBJECT_NAME_INVALID; + } + + if (!RtlDosPathNameToNtPathName_U (buf, &full, 0, 0)) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + buf); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + full.Buffer); + RtlReleasePebLock (); + return STATUS_OBJECT_NAME_INVALID; + } + + InitializeObjectAttributes (&Attr, + &full, + OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + NULL, + NULL); + + Status = NtOpenFile (&handle, + SYNCHRONIZE | FILE_TRAVERSE, + &Attr, + &iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + buf); + RtlFreeHeap (RtlGetProcessHeap (), + 0, + full.Buffer); + RtlReleasePebLock (); + return Status; + } + + filenameinfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + MAX_PATH*sizeof(WCHAR)+sizeof(ULONG)); + + Status = NtQueryInformationFile(handle, + &iosb, + filenameinfo, + MAX_PATH*sizeof(WCHAR)+sizeof(ULONG), + FileNameInformation); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + filenameinfo); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + buf); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + full.Buffer); + RtlReleasePebLock(); + return(Status); + } + + if (filenameinfo->FileName[1]) // If it's just "\", we need special handling + { + wcs = buf + size / sizeof(WCHAR) - 1; + if (*wcs == L'\\') + { + *(wcs) = 0; + wcs--; + size -= sizeof(WCHAR); + } + + for (cntr=filenameinfo->FileName;*cntr!=0;cntr++) + { + if (*cntr=='\\') backslashcount++; + } + + DPRINT("%d \n",backslashcount); + for (;backslashcount;wcs--) + { + if (*wcs=='\\') backslashcount--; + } + wcs++; + + wcscpy(wcs,filenameinfo->FileName); + + size=((wcs-buf)+wcslen(filenameinfo->FileName))*sizeof(WCHAR); + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + filenameinfo); + + /* append backslash if missing */ + wcs = buf + size / sizeof(WCHAR) - 1; + if (*wcs != L'\\') + { + *(++wcs) = L'\\'; + *(++wcs) = 0; + size += sizeof(WCHAR); + } + + memmove(cd->DosPath.Buffer, + buf, + size + sizeof(WCHAR)); + cd->DosPath.Length = size; + + if (cd->Handle) + NtClose(cd->Handle); + cd->Handle = handle; + + if (cd->DosPath.Buffer[1]==':') + { + envvar.Length = 2 * swprintf (var, L"=%c:", cd->DosPath.Buffer[0]); + envvar.MaximumLength = 8; + envvar.Buffer = var; + + RtlSetEnvironmentVariable(NULL, + &envvar, + &cd->DosPath); + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + buf); + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + full.Buffer); + + RtlReleasePebLock(); + + return STATUS_SUCCESS; +} + + +ULONG STDCALL +RtlGetFullPathName_U(PWSTR DosName, + ULONG size, + PWSTR buf, + PWSTR *FilePart) +{ + WCHAR *wcs, var[4], drive; + int len; + int reallen; + DWORD offs, sz, type; + UNICODE_STRING usvar, pfx; + PCURDIR cd; + NTSTATUS Status; + + DPRINT("RtlGetFullPathName_U %S %ld %p %p\n", + DosName, size, buf, FilePart); + + if (!DosName || !*DosName) + return 0; + + len = wcslen (DosName); + + /* strip trailing spaces */ + while (len && DosName[len - 1] == L' ') + len--; + if (!len) + return 0; + + reallen=len; + /* strip trailing path separator (but don't change '\') */ + if ((len > 1) && + IS_PATH_SEPARATOR(DosName[len - 1])) + len--; + if (FilePart) + *FilePart = L'\0'; + memset (buf, 0, size); + +CHECKPOINT; + /* check for DOS device name */ + sz = RtlIsDosDeviceName_U (DosName); + if (sz) + { + offs = sz >> 17; + sz &= 0x0000FFFF; + if (sz + 8 >= size) + return sz + 10; + wcscpy (buf, L"\\\\.\\"); + wcsncat (buf, DosName + offs, sz / sizeof(WCHAR)); + return sz + 8; + } + +CHECKPOINT; + type = RtlDetermineDosPathNameType_U (DosName); + + RtlAcquirePebLock(); + + cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName); +DPRINT("type %ld\n", type); + switch (type) + { + case 1: /* \\xxx or \\.xxx */ + case 6: /* \\.\xxx */ + break; + + case 2: /* x:\xxx */ + *DosName = towupper (*DosName); + break; + + case 3: /* x:xxx */ + drive = towupper (*DosName); + DosName += 2; + len -= 2; +CHECKPOINT; + if (drive == towupper (cd->DosPath.Buffer[0])) + { +CHECKPOINT; + wcscpy (buf, cd->DosPath.Buffer); + } + else + { +CHECKPOINT; + usvar.Length = 2 * swprintf (var, L"=%c:", drive); + usvar.MaximumLength = 8; + usvar.Buffer = var; + pfx.Length = 0; + pfx.MaximumLength = size; + pfx.Buffer = buf; + Status = RtlQueryEnvironmentVariable_U (NULL, + &usvar, + &pfx); +CHECKPOINT; + if (!NT_SUCCESS(Status)) + { +CHECKPOINT; + if (Status == STATUS_BUFFER_TOO_SMALL) + return pfx.Length + len * 2 + 2; + swprintf (buf, L"%c:\\", drive); + } + } + break; + + case 4: /* \xxx */ + wcsncpy (buf, cd->DosPath.Buffer, 2); + break; + + case 5: /* xxx */ + wcscpy (buf, cd->DosPath.Buffer); + break; + + case 7: /* \\. */ + wcscpy (buf, L"\\\\.\\"); + len = 0; + break; + + default: + return 0; + } + + DPRINT("buf \'%S\' DosName \'%S\' len %ld\n", buf, DosName, len); + /* add dosname to prefix */ + wcsncat (buf, DosName, len); + + CHECKPOINT; + /* replace slashes */ + for (wcs = buf; *wcs; wcs++) + if (*wcs == L'/') + *wcs = L'\\'; + + len = wcslen (buf); + if (len < 3 && buf[len-1] == L':') + wcscat (buf, L"\\"); + + DPRINT("buf \'%S\'\n", buf); + RtlpEatPath (buf); + DPRINT("buf \'%S\'\n", buf); + + len = wcslen (buf); + + /* find file part */ + if (FilePart) + { + for (wcs = buf + len - 1; wcs >= buf; wcs--) + { + if (*wcs == L'\\') + { + *FilePart = wcs + 1; + break; + } + } + } + + RtlReleasePebLock(); + + return len * sizeof(WCHAR); +} + + +BOOLEAN STDCALL +RtlDosPathNameToNtPathName_U(PWSTR dosname, + PUNICODE_STRING ntname, + PWSTR *FilePart, + PCURDIR nah) +{ + UNICODE_STRING us; + PCURDIR cd; + ULONG Type; + ULONG Size; + ULONG Length; + ULONG Offset; + WCHAR fullname[2*MAX_PATH]; + PWSTR Buffer = NULL; + + RtlAcquirePebLock (); + + RtlInitUnicodeString (&us, dosname); + if (us.Length > 8) + { + Buffer = us.Buffer; + /* check for "\\?\" - allows to use very long filenames ( up to 32k ) */ + if (Buffer[0] == L'\\' && Buffer[1] == L'\\' && + Buffer[2] == L'?' && Buffer[3] == L'\\') + { +// if( f_77F68606( &us, ntname, shortname, nah ) ) +// { +// RtlReleasePebLock (); +// return TRUE; +// } + Buffer = NULL; + RtlReleasePebLock (); + return FALSE; + } + } + + Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + sizeof( fullname ) + MAX_PFX_SIZE); + if (Buffer == NULL) + { + RtlReleasePebLock (); + return FALSE; + } + + Size = RtlGetFullPathName_U (dosname, + sizeof(fullname), + fullname, + FilePart); + if (Size == 0 || Size > MAX_PATH * sizeof(WCHAR)) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + Buffer); + RtlReleasePebLock (); + return FALSE; + } + + /* Set NT prefix */ + Offset = 0; + wcscpy (Buffer, L"\\??\\"); + + Type = RtlDetermineDosPathNameType_U (fullname); + switch (Type) + { + case 1: + wcscat (Buffer, L"UNC\\"); + Offset = 2; + break; /* \\xxx */ + + case 6: + Offset = 4; + break; /* \\.\xxx */ + } + wcscat (Buffer, fullname + Offset); + Length = wcslen (Buffer); + + /* set NT filename */ + ntname->Length = Length * sizeof(WCHAR); + ntname->MaximumLength = sizeof(fullname) + MAX_PFX_SIZE; + ntname->Buffer = Buffer; + + /* set pointer to file part if possible */ + if (FilePart && *FilePart) + *FilePart = Buffer + Length - wcslen (*FilePart); + + /* Set name and handle structure if possible */ + if (nah) + { + memset (nah, 0, sizeof(CURDIR)); + cd = (PCURDIR)&(NtCurrentPeb ()->ProcessParameters->CurrentDirectoryName); + if (Type == 5 && cd->Handle && + !_wcsnicmp (cd->DosPath.Buffer, fullname, cd->DosPath.Length / 2)) + { + Length = ((cd->DosPath.Length / sizeof(WCHAR)) - Offset) + ((Type == 1) ? 8 : 4); + nah->DosPath.Buffer = Buffer + Length; + nah->DosPath.Length = ntname->Length - (Length * sizeof(WCHAR)); + nah->DosPath.MaximumLength = nah->DosPath.Length; + nah->Handle = cd->Handle; + } + } + + RtlReleasePebLock(); + + return TRUE; +} + + +ULONG +STDCALL +RtlDosSearchPath_U ( + WCHAR *sp, + WCHAR *name, + WCHAR *ext, + ULONG buf_sz, + WCHAR *buffer, + PWSTR *FilePart + ) +{ + ULONG Type; + ULONG Length = 0; + PWSTR full_name; + PWSTR wcs; + PWSTR path; + + Type = RtlDetermineDosPathNameType_U (name); + + if (Type == 5) + { + Length = wcslen (sp); + Length += wcslen (name); + if (wcschr (name, L'.')) + ext = NULL; + if (ext != NULL) + Length += wcslen (ext); + + full_name = (WCHAR*)RtlAllocateHeap (RtlGetProcessHeap (), + 0, + (Length + 1) * sizeof(WCHAR)); + Length = 0; + if (full_name != NULL) + { + path = sp; + while (*path) + { + wcs = full_name; + while (*path && *path != L';') + *wcs++ = *path++; + if (*path) + path++; + if (wcs != full_name && *(wcs - 1) != L'\\') + *wcs++ = L'\\'; + wcscpy (wcs, name); + if (ext) + wcscat (wcs, ext); + if (RtlDoesFileExists_U (full_name)) + { + Length = RtlGetFullPathName_U (full_name, + buf_sz, + buffer, + FilePart); + break; + } + } + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + full_name); + } + } + else if (RtlDoesFileExists_U (name)) + { + Length = RtlGetFullPathName_U (name, + buf_sz, + buffer, + FilePart); + } + + return Length; +} + + +BOOLEAN STDCALL +RtlDoesFileExists_U(IN PWSTR FileName) +{ + UNICODE_STRING NtFileName; + OBJECT_ATTRIBUTES Attr; + NTSTATUS Status; + CURDIR CurDir; + PWSTR Buffer; + + /* only used by replacement code */ + HANDLE FileHandle; + IO_STATUS_BLOCK StatusBlock; + + if (!RtlDosPathNameToNtPathName_U (FileName, + &NtFileName, + NULL, + &CurDir)) + return FALSE; + + /* don't forget to free it! */ + Buffer = NtFileName.Buffer; + + if (CurDir.DosPath.Length) + NtFileName = CurDir.DosPath; + else + CurDir.Handle = 0; + + InitializeObjectAttributes (&Attr, + &NtFileName, + OBJ_CASE_INSENSITIVE, + CurDir.Handle, + NULL); + + /* FIXME: not implemented yet */ +// Status = NtQueryAttributesFile (&Attr, NULL); + + /* REPLACEMENT start */ + Status = NtOpenFile (&FileHandle, + 0x10001, + &Attr, + &StatusBlock, + 1, + FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS(Status)) + NtClose (FileHandle); + /* REPLACEMENT end */ + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + Buffer); + + if (NT_SUCCESS(Status) || + Status == STATUS_SHARING_VIOLATION || + Status == STATUS_ACCESS_DENIED) + return TRUE; + + return FALSE; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/ppb.c b/lib/ntdll/rtl/ppb.c new file mode 100644 index 0000000..50feb7b --- /dev/null +++ b/lib/ntdll/rtl/ppb.c @@ -0,0 +1,295 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/ppb.c + * PURPOSE: Process parameters functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* MACROS ****************************************************************/ + +#define NORMALIZE(x,addr) {if(x) x=(VOID*)((ULONG)(x)+(ULONG)(addr));} +#define DENORMALIZE(x,addr) {if(x) x=(VOID*)((ULONG)(x)-(ULONG)(addr));} +#define ALIGN(x,align) (((ULONG)(x)+(align)-1UL)&(~((align)-1UL))) + + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +RtlAcquirePebLock(VOID) +{ + PPEB Peb = NtCurrentPeb (); + Peb->FastPebLockRoutine (Peb->FastPebLock); +} + + +VOID STDCALL +RtlReleasePebLock(VOID) +{ + PPEB Peb = NtCurrentPeb (); + Peb->FastPebUnlockRoutine (Peb->FastPebLock); +} + +static inline VOID +RtlpCopyParameterString(PWCHAR *Ptr, + PUNICODE_STRING Destination, + PUNICODE_STRING Source, + ULONG Size) +{ + Destination->Length = Source->Length; + Destination->MaximumLength = Size ? Size : Source->MaximumLength; + Destination->Buffer = (PWCHAR)(*Ptr); + if (Source->Length) + memmove (Destination->Buffer, Source->Buffer, Source->Length); + Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0; + *Ptr += Destination->MaximumLength/sizeof(WCHAR); +} + + +NTSTATUS STDCALL +RtlCreateProcessParameters(PRTL_USER_PROCESS_PARAMETERS *ProcessParameters, + PUNICODE_STRING ImagePathName, + PUNICODE_STRING DllPath, + PUNICODE_STRING CurrentDirectory, + PUNICODE_STRING CommandLine, + PWSTR Environment, + PUNICODE_STRING WindowTitle, + PUNICODE_STRING DesktopInfo, + PUNICODE_STRING ShellInfo, + PUNICODE_STRING RuntimeInfo) +{ + NTSTATUS Status = STATUS_SUCCESS; + PRTL_USER_PROCESS_PARAMETERS Param = NULL; + ULONG RegionSize = 0; + ULONG Length = 0; + PWCHAR Dest; + UNICODE_STRING EmptyString; + HANDLE CurrentDirectoryHandle; + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + + DPRINT ("RtlCreateProcessParameters\n"); + + RtlAcquirePebLock(); + + EmptyString.Length = 0; + EmptyString.MaximumLength = sizeof(WCHAR); + EmptyString.Buffer = L""; + + if (NtCurrentPeb()->ProcessParameters) + { + if (DllPath == NULL) + DllPath = &NtCurrentPeb()->ProcessParameters->DllPath; + if (Environment == NULL) + Environment = NtCurrentPeb()->ProcessParameters->Environment; + if (CurrentDirectory == NULL) + CurrentDirectory = &NtCurrentPeb()->ProcessParameters->CurrentDirectoryName; + CurrentDirectoryHandle = NtCurrentPeb()->ProcessParameters->CurrentDirectoryHandle; + ConsoleHandle = NtCurrentPeb()->ProcessParameters->hConsole; + ConsoleFlags = NtCurrentPeb()->ProcessParameters->ProcessGroup; + } + else + { + if (DllPath == NULL) + DllPath = &EmptyString; + if (CurrentDirectory == NULL) + CurrentDirectory = &EmptyString; + CurrentDirectoryHandle = NULL; + ConsoleHandle = NULL; + ConsoleFlags = 0; + } + + if (CommandLine == NULL) + CommandLine = &EmptyString; + if (WindowTitle == NULL) + WindowTitle = &EmptyString; + if (DesktopInfo == NULL) + DesktopInfo = &EmptyString; + if (ShellInfo == NULL) + ShellInfo = &EmptyString; + if (RuntimeInfo == NULL) + RuntimeInfo = &EmptyString; + + /* size of process parameter block */ + Length = sizeof(RTL_USER_PROCESS_PARAMETERS); + + /* size of current directory buffer */ + Length += (MAX_PATH * sizeof(WCHAR)); + + /* add string lengths */ + Length += ALIGN(DllPath->MaximumLength, sizeof(ULONG)); + Length += ALIGN(ImagePathName->Length + sizeof(WCHAR), sizeof(ULONG)); + Length += ALIGN(CommandLine->Length + sizeof(WCHAR), sizeof(ULONG)); + Length += ALIGN(WindowTitle->MaximumLength, sizeof(ULONG)); + Length += ALIGN(DesktopInfo->MaximumLength, sizeof(ULONG)); + Length += ALIGN(ShellInfo->MaximumLength, sizeof(ULONG)); + Length += ALIGN(RuntimeInfo->MaximumLength, sizeof(ULONG)); + + /* Calculate the required block size */ + RegionSize = ROUNDUP(Length, PAGE_SIZE); + + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID*)&Param, + 0, + &RegionSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + RtlReleasePebLock(); + return Status; + } + + DPRINT ("Process parameters allocated\n"); + + Param->AllocationSize = RegionSize; + Param->Size = Length; + Param->Flags = PPF_NORMALIZED; + Param->Environment = Environment; + Param->CurrentDirectoryHandle = CurrentDirectoryHandle; + Param->hConsole = ConsoleHandle; + Param->ProcessGroup = ConsoleFlags; + + Dest = (PWCHAR)(((PBYTE)Param) + sizeof(RTL_USER_PROCESS_PARAMETERS)); + + /* copy current directory */ + RtlpCopyParameterString(&Dest, + &Param->CurrentDirectoryName, + CurrentDirectory, + MAX_PATH * sizeof(WCHAR)); + + /* make sure the current directory has a trailing backslash */ + if (Param->CurrentDirectoryName.Length > 0) + { + ULONG Length; + + Length = Param->CurrentDirectoryName.Length / sizeof(WCHAR); + if (Param->CurrentDirectoryName.Buffer[Length-1] != L'\\') + { + Param->CurrentDirectoryName.Buffer[Length] = L'\\'; + Param->CurrentDirectoryName.Buffer[Length + 1] = 0; + Param->CurrentDirectoryName.Length += sizeof(WCHAR); + } + } + + /* copy dll path */ + RtlpCopyParameterString(&Dest, + &Param->DllPath, + DllPath, + 0); + + /* copy image path name */ + RtlpCopyParameterString(&Dest, + &Param->ImagePathName, + ImagePathName, + ImagePathName->Length + sizeof(WCHAR)); + + /* copy command line */ + RtlpCopyParameterString(&Dest, + &Param->CommandLine, + CommandLine, + CommandLine->Length + sizeof(WCHAR)); + + /* copy title */ + RtlpCopyParameterString(&Dest, + &Param->WindowTitle, + WindowTitle, + 0); + + /* copy desktop */ + RtlpCopyParameterString(&Dest, + &Param->DesktopInfo, + DesktopInfo, + 0); + + /* copy shell info */ + RtlpCopyParameterString(&Dest, + &Param->ShellInfo, + ShellInfo, + 0); + + /* copy runtime info */ + RtlpCopyParameterString(&Dest, + &Param->RuntimeInfo, + RuntimeInfo, + 0); + + RtlDeNormalizeProcessParams(Param); + *ProcessParameters = Param; + RtlReleasePebLock(); + + return STATUS_SUCCESS; +} + +VOID STDCALL +RtlDestroyProcessParameters(PRTL_USER_PROCESS_PARAMETERS ProcessParameters) +{ + ULONG RegionSize = 0; + + NtFreeVirtualMemory (NtCurrentProcess (), + (PVOID)ProcessParameters, + &RegionSize, + MEM_RELEASE); +} + +/* + * denormalize process parameters (Pointer-->Offset) + */ +PRTL_USER_PROCESS_PARAMETERS STDCALL +RtlDeNormalizeProcessParams(PRTL_USER_PROCESS_PARAMETERS Params) +{ + if (Params && (Params->Flags & PPF_NORMALIZED)) + { + DENORMALIZE(Params->CurrentDirectoryName.Buffer, Params); + DENORMALIZE(Params->DllPath.Buffer, Params); + DENORMALIZE(Params->ImagePathName.Buffer, Params); + DENORMALIZE(Params->CommandLine.Buffer, Params); + DENORMALIZE(Params->WindowTitle.Buffer, Params); + DENORMALIZE(Params->DesktopInfo.Buffer, Params); + DENORMALIZE(Params->ShellInfo.Buffer, Params); + DENORMALIZE(Params->RuntimeInfo.Buffer, Params); + + Params->Flags &= ~PPF_NORMALIZED; + } + + return Params; +} + +/* + * normalize process parameters (Offset-->Pointer) + */ +PRTL_USER_PROCESS_PARAMETERS STDCALL +RtlNormalizeProcessParams(PRTL_USER_PROCESS_PARAMETERS Params) +{ + if (Params && !(Params->Flags & PPF_NORMALIZED)) + { + NORMALIZE(Params->CurrentDirectoryName.Buffer, Params); + NORMALIZE(Params->DllPath.Buffer, Params); + NORMALIZE(Params->ImagePathName.Buffer, Params); + NORMALIZE(Params->CommandLine.Buffer, Params); + NORMALIZE(Params->WindowTitle.Buffer, Params); + NORMALIZE(Params->DesktopInfo.Buffer, Params); + NORMALIZE(Params->ShellInfo.Buffer, Params); + NORMALIZE(Params->RuntimeInfo.Buffer, Params); + + Params->Flags |= PPF_NORMALIZED; + } + + return Params; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/process.c b/lib/ntdll/rtl/process.c new file mode 100644 index 0000000..7dfb963 --- /dev/null +++ b/lib/ntdll/rtl/process.c @@ -0,0 +1,483 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/process.c + * PURPOSE: Process functions + * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) + * UPDATE HISTORY: + * Created 01/11/98 + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +RtlpCreateFirstThread(HANDLE ProcessHandle, + ULONG StackReserve, + ULONG StackCommit, + LPTHREAD_START_ROUTINE lpStartAddress, + PCLIENT_ID ClientId, + PHANDLE ThreadHandle) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + CONTEXT ThreadContext; + INITIAL_TEB InitialTeb; + ULONG OldPageProtection; + CLIENT_ID Cid; + ULONG InitialStack[5]; + ULONG ResultLength; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityQualityOfService = NULL; + + if (StackReserve > 0x100000) + InitialTeb.StackReserve = StackReserve; + else + InitialTeb.StackReserve = 0x100000; /* 1MByte */ + + /* FIXME */ +#if 0 + if (StackCommit > PAGE_SIZE) + InitialTeb.StackCommit = StackCommit; + else + InitialTeb.StackCommit = PAGE_SIZE; +#endif + InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE; + + /* add guard page size */ + InitialTeb.StackCommit += PAGE_SIZE; + + /* Reserve stack */ + InitialTeb.StackAllocate = NULL; + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackAllocate, + 0, + &InitialTeb.StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Error reserving stack space!\n"); + return(Status); + } + + DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n", + InitialTeb.StackAllocate, InitialTeb.StackReserve); + + InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve); + InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit); + + DPRINT("StackBase: %p StackCommit: 0x%lX\n", + InitialTeb.StackBase, InitialTeb.StackCommit); + + /* Commit stack */ + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackLimit, + 0, + &InitialTeb.StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting stack page(s)!\n"); + return(Status); + } + + DPRINT("StackLimit: %p\n", InitialTeb.StackLimit); + + /* Protect guard page */ + Status = NtProtectVirtualMemory(ProcessHandle, + InitialTeb.StackLimit, + PAGE_SIZE, + PAGE_GUARD | PAGE_READWRITE, + &OldPageProtection); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting guard page!\n"); + return(Status); + } + + memset(&ThreadContext,0,sizeof(CONTEXT)); + ThreadContext.Eip = (ULONG)lpStartAddress; + ThreadContext.SegGs = USER_DS; + ThreadContext.SegFs = TEB_SELECTOR; + ThreadContext.SegEs = USER_DS; + ThreadContext.SegDs = USER_DS; + ThreadContext.SegCs = USER_CS; + ThreadContext.SegSs = USER_DS; + ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 20; + ThreadContext.EFlags = (1<<1) + (1<<9); + + DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip); + + /* + * Write in the initial stack. + */ + InitialStack[0] = 0; + InitialStack[1] = PEB_BASE; + Status = ZwWriteVirtualMemory(ProcessHandle, + (PVOID)ThreadContext.Esp, + InitialStack, + sizeof(InitialStack), + &ResultLength); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to write initial stack.\n"); + return(Status); + } + + Status = NtCreateThread(ThreadHandle, + THREAD_ALL_ACCESS, + &ObjectAttributes, + ProcessHandle, + &Cid, + &ThreadContext, + &InitialTeb, + FALSE); + if (!NT_SUCCESS(Status)) + { + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + return(Status); + } + + if (ClientId != NULL) + { + memcpy(&ClientId->UniqueThread, &Cid.UniqueThread, sizeof(ULONG)); + } + + return(STATUS_SUCCESS); +} + +static NTSTATUS +RtlpMapFile(PRTL_USER_PROCESS_PARAMETERS Ppb, + ULONG Attributes, + PHANDLE Section, + PCHAR ImageFileName) +{ + HANDLE hFile; + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + NTSTATUS Status; + PWCHAR s; + PWCHAR e; + ULONG i; + + hFile = NULL; + + RtlDeNormalizeProcessParams (Ppb); + +// DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + &(Ppb->ImagePathName), + Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT), + NULL, + SecurityDescriptor); + + RtlNormalizeProcessParams (Ppb); + + /* + * + */ +// DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer); +// DbgPrint("ImagePathName %S\n", Ppb->ImagePathName.Buffer); + s = wcsrchr(Ppb->ImagePathName.Buffer, '\\'); + if (s == NULL) + { + s = Ppb->ImagePathName.Buffer; + } + else + { + s++; + } + e = wcschr(s, '.'); + if (e != NULL) + { + *e = 0; + } + for (i = 0; i < 8; i++) + { + ImageFileName[i] = (CHAR)(s[i]); + } + if (e != NULL) + { + *e = '.'; + } + + /* + * Try to open the executable + */ + + Status = NtOpenFile(&hFile, + SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_DELETE|FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = NtCreateSection(Section, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_EXECUTE, + SEC_IMAGE, + hFile); + NtClose(hFile); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + return(STATUS_SUCCESS); +} + +static NTSTATUS KlInitPeb (HANDLE ProcessHandle, + PRTL_USER_PROCESS_PARAMETERS Ppb, + PVOID* ImageBaseAddress) +{ + NTSTATUS Status; + PVOID PpbBase; + ULONG PpbSize; + ULONG BytesWritten; + ULONG Offset; + PVOID EnvPtr = NULL; + ULONG EnvSize = 0; + + /* create the Environment */ + if (Ppb->Environment != NULL) + { + MEMORY_BASIC_INFORMATION MemInfo; + + Status = NtQueryVirtualMemory (NtCurrentProcess (), + Ppb->Environment, + MemoryBasicInformation, + &MemInfo, + sizeof(MEMORY_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + EnvSize = MemInfo.RegionSize; + } + DPRINT("EnvironmentSize %ld\n", EnvSize); + + /* allocate and initialize new environment block */ + if (EnvSize != 0) + { + Status = NtAllocateVirtualMemory(ProcessHandle, + &EnvPtr, + 0, + &EnvSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + NtWriteVirtualMemory(ProcessHandle, + EnvPtr, + Ppb->Environment, + EnvSize, + &BytesWritten); + } + DPRINT("EnvironmentPointer %p\n", EnvPtr); + + /* create the PPB */ + PpbBase = NULL; + PpbSize = Ppb->AllocationSize; + Status = NtAllocateVirtualMemory(ProcessHandle, + &PpbBase, + 0, + &PpbSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength); + + /* write process parameters block*/ + RtlDeNormalizeProcessParams (Ppb); + NtWriteVirtualMemory(ProcessHandle, + PpbBase, + Ppb, + Ppb->AllocationSize, + &BytesWritten); + RtlNormalizeProcessParams (Ppb); + + /* write pointer to environment */ + Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment); + NtWriteVirtualMemory(ProcessHandle, + (PVOID)(PpbBase + Offset), + &EnvPtr, + sizeof(EnvPtr), + &BytesWritten); + + /* write pointer to process parameter block */ + Offset = FIELD_OFFSET(PEB, ProcessParameters); + NtWriteVirtualMemory(ProcessHandle, + (PVOID)(PEB_BASE + Offset), + &PpbBase, + sizeof(PpbBase), + &BytesWritten); + + /* Read image base address. */ + Offset = FIELD_OFFSET(PEB, ImageBaseAddress); + NtReadVirtualMemory(ProcessHandle, + (PVOID)(PEB_BASE + Offset), + ImageBaseAddress, + sizeof(PVOID), + &BytesWritten); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCreateUserProcess(PUNICODE_STRING ImageFileName, + ULONG Attributes, + PRTL_USER_PROCESS_PARAMETERS ProcessParameters, + PSECURITY_DESCRIPTOR ProcessSecurityDescriptor, + PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + HANDLE ParentProcess, + BOOLEAN CurrentDirectory, + HANDLE DebugPort, + HANDLE ExceptionPort, + PRTL_PROCESS_INFO ProcessInfo) +{ + HANDLE hSection; + NTSTATUS Status; + LPTHREAD_START_ROUTINE lpStartAddress = NULL; + PROCESS_BASIC_INFORMATION ProcessBasicInfo; + ULONG retlen; + CHAR FileName[8]; + ANSI_STRING ProcedureName; + SECTION_IMAGE_INFORMATION Sii; + ULONG ResultLength; + PVOID ImageBaseAddress; + + DPRINT("RtlCreateUserProcess\n"); + + Status = RtlpMapFile(ProcessParameters, + Attributes, + &hSection, + FileName); + if( !NT_SUCCESS( Status ) ) + return Status; + + /* + * Create a new process + */ + if (ParentProcess == NULL) + ParentProcess = NtCurrentProcess(); + + Status = NtCreateProcess(&(ProcessInfo->ProcessHandle), + PROCESS_ALL_ACCESS, + NULL, + ParentProcess, + CurrentDirectory, + hSection, + DebugPort, + ExceptionPort); + if (!NT_SUCCESS(Status)) + { + NtClose(hSection); + return(Status); + } + + /* + * Get some information about the process + */ + NtQueryInformationProcess(ProcessInfo->ProcessHandle, + ProcessBasicInformation, + &ProcessBasicInfo, + sizeof(ProcessBasicInfo), + &retlen); + DPRINT("ProcessBasicInfo.UniqueProcessId %d\n", + ProcessBasicInfo.UniqueProcessId); + ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId; + + Status = NtSetInformationProcess(ProcessInfo->ProcessHandle, + ProcessImageFileName, + FileName, + 8); + + /* + * Create Process Environment Block + */ + DPRINT("Creating peb\n"); + KlInitPeb(ProcessInfo->ProcessHandle, + ProcessParameters, + &ImageBaseAddress); + + Status = NtQuerySection(hSection, + SectionImageInformation, + &Sii, + sizeof(Sii), + &ResultLength); + if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii)) + { + DPRINT("Failed to get section image information.\n"); + NtClose(hSection); + return(Status); + } + + DPRINT("Creating thread for process\n"); + Status = RtlpCreateFirstThread(ProcessInfo->ProcessHandle, + Sii.StackReserve, + Sii.StackCommit, + ImageBaseAddress + (ULONG)Sii.EntryPoint, + &ProcessInfo->ClientId, + &ProcessInfo->ThreadHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create thread\n"); + NtClose(hSection); + return(Status); + } + NtClose(hSection); + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/propvar.c b/lib/ntdll/rtl/propvar.c new file mode 100644 index 0000000..c836e32 --- /dev/null +++ b/lib/ntdll/rtl/propvar.c @@ -0,0 +1,62 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/csr/propvar.c + * PURPOSE: CSRSS properties and variants API + */ +#define NTOS_MODE_USER +#include + +NTSTATUS +STDCALL +PropertyLengthAsVariant ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + return (STATUS_NOT_IMPLEMENTED); +} + +BOOLEAN +STDCALL +RtlCompareVariants ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + return (FALSE); +} + +BOOLEAN +STDCALL +RtlConvertPropertyToVariant ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + return (FALSE); +} + +NTSTATUS +STDCALL +RtlConvertVariantToProperty ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6 + ) +{ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* EOF */ diff --git a/lib/ntdll/rtl/registry.c b/lib/ntdll/rtl/registry.c new file mode 100644 index 0000000..3643771 --- /dev/null +++ b/lib/ntdll/rtl/registry.c @@ -0,0 +1,982 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Rtl registry functions + * FILE: lib/ntdll/rtl/registry.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 2000/08/11: Created + */ + +/* + * TODO: + * - finish RtlQueryRegistryValues() + * - support RTL_QUERY_REGISTRY_DELETE + * + * - finish RtlFormatCurrentUserKeyPath() + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +RtlCheckRegistryKey(IN ULONG RelativeTo, + IN PWSTR Path) +{ + HANDLE KeyHandle; + NTSTATUS Status; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + FALSE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + NtClose(KeyHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCreateRegistryKey(IN ULONG RelativeTo, + IN PWSTR Path) +{ + HANDLE KeyHandle; + NTSTATUS Status; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + NtClose(KeyHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlDeleteRegistryValue(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ValueName) +{ + HANDLE KeyHandle; + NTSTATUS Status; + UNICODE_STRING Name; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + FALSE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + RtlInitUnicodeString(&Name, + ValueName); + + Status = NtDeleteValueKey(KeyHandle, + &Name); + + NtClose(KeyHandle); + + return(Status); +} + + +NTSTATUS STDCALL +RtlFormatCurrentUserKeyPath(PUNICODE_STRING KeyPath) +{ + /* FIXME: !!! */ +#if 0 + RtlCreateUnicodeString(KeyPath, + L"\\Registry\\User\\.Default"); +#endif + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, + OUT PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + UNICODE_STRING KeyPath = UNICODE_STRING_INITIALIZER(L"\\Registry\\User\\.Default"); + + Status = RtlFormatCurrentUserKeyPath(&KeyPath); + if (NT_SUCCESS(Status)) + { + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(KeyHandle, + DesiredAccess, + &ObjectAttributes); + if (NT_SUCCESS(Status)) { + RtlFreeUnicodeString(&KeyPath); + return(STATUS_SUCCESS); + } + } + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(KeyHandle, + DesiredAccess, + &ObjectAttributes); + RtlFreeUnicodeString(&KeyPath); + return(Status); +} + + +NTSTATUS STDCALL +RtlQueryRegistryValues(IN ULONG RelativeTo, + IN PWSTR Path, + IN PRTL_QUERY_REGISTRY_TABLE QueryTable, + IN PVOID Context, + IN PVOID Environment) +{ + NTSTATUS Status; + HANDLE BaseKeyHandle; + HANDLE CurrentKeyHandle; + PRTL_QUERY_REGISTRY_TABLE QueryEntry; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + PKEY_VALUE_FULL_INFORMATION FullValueInfo; + ULONG BufferSize; + ULONG ResultSize; + ULONG Index; + ULONG StringLen; + PWSTR StringPtr; + PWSTR ExpandBuffer; + UNICODE_STRING EnvValue; + UNICODE_STRING EnvExpandedValue; + + DPRINT("RtlQueryRegistryValues() called\n"); + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + FALSE, + &BaseKeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed (Status %lx)\n", Status); + return(Status); + } + + CurrentKeyHandle = BaseKeyHandle; + QueryEntry = QueryTable; + while ((QueryEntry->QueryRoutine != NULL) || + (QueryEntry->Name != NULL)) + { + if ((QueryEntry->QueryRoutine == NULL) && + ((QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) != 0)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + DPRINT("Name: %S\n", QueryEntry->Name); + + if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) && + (BaseKeyHandle != CurrentKeyHandle)) + { + NtClose(CurrentKeyHandle); + CurrentKeyHandle = BaseKeyHandle; + } + + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) + { + DPRINT("Open new subkey: %S\n", QueryEntry->Name); + + RtlInitUnicodeString(&KeyName, + QueryEntry->Name); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + BaseKeyHandle, + NULL); + Status = NtOpenKey(&CurrentKeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + break; + } + else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT) + { + DPRINT("Query value directly: %S\n", QueryEntry->Name); + + RtlInitUnicodeString(&KeyName, + QueryEntry->Name); + + BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096; + ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferSize); + if (ValueInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + Status = NtQueryValueKey(CurrentKeyHandle, + &KeyName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo); + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + if (QueryEntry->DefaultType == REG_SZ) + { + PUNICODE_STRING ValueString; + PUNICODE_STRING SourceString; + + SourceString = (PUNICODE_STRING)QueryEntry->DefaultData; + ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; + if (ValueString->Buffer == 0) + { + ValueString->Length = SourceString->Length; + ValueString->MaximumLength = SourceString->MaximumLength; + ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + ValueString->MaximumLength); + if (!ValueString->Buffer) + break; + ValueString->Buffer[0] = 0; + memcpy(ValueString->Buffer, + SourceString->Buffer, + SourceString->MaximumLength); + } + else + { + ValueString->Length = min(SourceString->Length, + ValueString->MaximumLength - sizeof(WCHAR)); + memcpy(ValueString->Buffer, + SourceString->Buffer, + ValueString->Length); + ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; + } + } + else + { + memcpy(QueryEntry->EntryContext, + QueryEntry->DefaultData, + QueryEntry->DefaultLength); + } + Status = STATUS_SUCCESS; + } + else + { + if ((ValueInfo->Type == REG_SZ) || + (ValueInfo->Type == REG_MULTI_SZ) || + (ValueInfo->Type == REG_EXPAND_SZ && (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))) + { + PUNICODE_STRING ValueString; + + ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; + if (ValueString->Buffer == NULL) + { + ValueString->MaximumLength = ValueInfo->DataLength + sizeof(WCHAR); + ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + ValueString->MaximumLength); + if (ValueString->Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + ValueString->Buffer[0] = 0; + } + ValueString->Length = min(ValueInfo->DataLength, + ValueString->MaximumLength - sizeof(WCHAR)); + memcpy(ValueString->Buffer, + ValueInfo->Data, + ValueString->Length); + ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; + } + else if (ValueInfo->Type == REG_EXPAND_SZ) + { + PUNICODE_STRING ValueString; + + DPRINT("Expand REG_EXPAND_SZ type\n"); + + ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; + + ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + ValueInfo->DataLength * 2); + if (ExpandBuffer == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + RtlInitUnicodeString(&EnvValue, + (PWSTR)ValueInfo->Data); + EnvExpandedValue.Length = 0; + EnvExpandedValue.MaximumLength = ValueInfo->DataLength * 2 * sizeof(WCHAR); + EnvExpandedValue.Buffer = ExpandBuffer; + *ExpandBuffer = 0; + + RtlExpandEnvironmentStrings_U(Environment, + &EnvValue, + &EnvExpandedValue, + &StringLen); + + if (ValueString->Buffer == NULL) + { + ValueString->MaximumLength = EnvExpandedValue.Length + sizeof(WCHAR); + ValueString->Length = EnvExpandedValue.Length; + ValueString->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + ValueString->MaximumLength); + if (ValueString->Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + } + else + { + ValueString->Length = min(EnvExpandedValue.Length, + ValueString->MaximumLength - sizeof(WCHAR)); + } + + memcpy(ValueString->Buffer, + EnvExpandedValue.Buffer, + ValueString->Length); + ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ExpandBuffer); + } + else + { + memcpy(QueryEntry->EntryContext, + ValueInfo->Data, + ValueInfo->DataLength); + } + } + + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) + { + DPRINT1("FIXME: Delete value: %S\n", QueryEntry->Name); + + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ValueInfo); + } + else + { + DPRINT("Query value via query routine: %S\n", QueryEntry->Name); + if (QueryEntry->Name != NULL) + { + RtlInitUnicodeString(&KeyName, + QueryEntry->Name); + + BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + 4096; + ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferSize); + if (ValueInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + Status = NtQueryValueKey(CurrentKeyHandle, + &KeyName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + QueryEntry->DefaultType, + QueryEntry->DefaultData, + QueryEntry->DefaultLength, + Context, + QueryEntry->EntryContext); + } + else if ((ValueInfo->Type == REG_MULTI_SZ) && + !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + DPRINT("Expand REG_MULTI_SZ type\n"); + StringPtr = (PWSTR)ValueInfo->Data; + while (*StringPtr != 0) + { + StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR); + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + REG_SZ, + (PVOID)StringPtr, + StringLen, + Context, + QueryEntry->EntryContext); + if(!NT_SUCCESS(Status)) + break; + StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen); + } + } + else if ((ValueInfo->Type == REG_EXPAND_SZ) && + !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + DPRINT("Expand REG_EXPAND_SZ type\n"); + + ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + ValueInfo->DataLength * 2); + if (ExpandBuffer == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + RtlInitUnicodeString(&EnvValue, + (PWSTR)ValueInfo->Data); + EnvExpandedValue.Length = 0; + EnvExpandedValue.MaximumLength = ValueInfo->DataLength * 2 * sizeof(WCHAR); + EnvExpandedValue.Buffer = ExpandBuffer; + *ExpandBuffer = 0; + + RtlExpandEnvironmentStrings_U(Environment, + &EnvValue, + &EnvExpandedValue, + &StringLen); + + StringLen = (wcslen(ExpandBuffer) + 1) * sizeof(WCHAR); + Status = QueryEntry->QueryRoutine(FullValueInfo->Name, + REG_SZ, + (PVOID)ExpandBuffer, + StringLen, + Context, + QueryEntry->EntryContext); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ExpandBuffer); + } + else + { + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + ValueInfo->Type, + ValueInfo->Data, + ValueInfo->DataLength, + Context, + QueryEntry->EntryContext); + } + + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) + { + DPRINT1("FIXME: Delete value: %S\n", QueryEntry->Name); + + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ValueInfo); + if (!NT_SUCCESS(Status)) + break; + } + else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOVALUE) + { + DPRINT("Simple callback\n"); + Status = QueryEntry->QueryRoutine(NULL, + REG_NONE, + NULL, + 0, + Context, + QueryEntry->EntryContext); + if (!NT_SUCCESS(Status)) + break; + } + else + { + DPRINT("Enumerate values\n"); + + BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096; + FullValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferSize); + if (FullValueInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + Index = 0; + while (TRUE) + { + Status = NtEnumerateValueKey(CurrentKeyHandle, + Index, + KeyValueFullInformation, + FullValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + if ((Status == STATUS_NO_MORE_ENTRIES) && + (Index == 0) && + (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + else if (Status == STATUS_NO_MORE_ENTRIES) + { + Status = STATUS_SUCCESS; + } + break; + } + + DPRINT("FullValueInfo->Type: %lu\n", FullValueInfo->Type); + if ((FullValueInfo->Type == REG_MULTI_SZ) && + !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + DPRINT("Expand REG_MULTI_SZ type\n"); + StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset); + while (*StringPtr != 0) + { + StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR); + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + REG_SZ, + (PVOID)StringPtr, + StringLen, + Context, + QueryEntry->EntryContext); + if(!NT_SUCCESS(Status)) + break; + StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen); + } + } + else if ((FullValueInfo->Type == REG_EXPAND_SZ) && + !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + DPRINT("Expand REG_EXPAND_SZ type\n"); + + StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset); + ExpandBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + FullValueInfo->DataLength * 2); + if (ExpandBuffer == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + RtlInitUnicodeString(&EnvValue, + StringPtr); + EnvExpandedValue.Length = 0; + EnvExpandedValue.MaximumLength = FullValueInfo->DataLength * 2 * sizeof(WCHAR); + EnvExpandedValue.Buffer = ExpandBuffer; + *ExpandBuffer = 0; + + RtlExpandEnvironmentStrings_U(Environment, + &EnvValue, + &EnvExpandedValue, + &StringLen); + + StringLen = (wcslen(ExpandBuffer) + 1) * sizeof(WCHAR); + Status = QueryEntry->QueryRoutine(FullValueInfo->Name, + REG_SZ, + (PVOID)ExpandBuffer, + StringLen, + Context, + QueryEntry->EntryContext); + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ExpandBuffer); + } + else + { + Status = QueryEntry->QueryRoutine(FullValueInfo->Name, + FullValueInfo->Type, + (PVOID)FullValueInfo + FullValueInfo->DataOffset, + FullValueInfo->DataLength, + Context, + QueryEntry->EntryContext); + } + + if (!NT_SUCCESS(Status)) + break; + + /* FIXME: How will these be deleted? */ + + Index++; + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + FullValueInfo); + + if (!NT_SUCCESS(Status)) + break; + } + } + + QueryEntry++; + } + + if (CurrentKeyHandle != BaseKeyHandle) + NtClose(CurrentKeyHandle); + + NtClose(BaseKeyHandle); + + return(Status); +} + + +NTSTATUS STDCALL +RtlWriteRegistryValue(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength) +{ + HANDLE KeyHandle; + NTSTATUS Status; + UNICODE_STRING Name; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + RtlInitUnicodeString(&Name, + ValueName); + + Status = NtSetValueKey(KeyHandle, + &Name, + 0, + ValueType, + ValueData, + ValueLength); + if (NT_SUCCESS(Status)) + NtClose(KeyHandle); + + return(Status); +} + + +NTSTATUS STDCALL +RtlpNtCreateKey(OUT HANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Unused1, + OUT PULONG Disposition, + IN ULONG Unused2) +{ + if (ObjectAttributes != NULL) + ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); + + return(NtCreateKey(KeyHandle, + DesiredAccess, + ObjectAttributes, + 0, + NULL, + 0, + Disposition)); +} + + +NTSTATUS STDCALL +RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, + OUT PUNICODE_STRING SubKeyName, + IN ULONG Index, + IN ULONG Unused) +{ + PKEY_BASIC_INFORMATION KeyInfo = NULL; + ULONG BufferLength = 0; + ULONG ReturnedLength; + NTSTATUS Status; + + if (SubKeyName->MaximumLength != 0) + { + BufferLength = SubKeyName->MaximumLength + + sizeof(KEY_BASIC_INFORMATION); + KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferLength); + if (KeyInfo == NULL) + return(STATUS_NO_MEMORY); + } + + Status = NtEnumerateKey(KeyHandle, + Index, + KeyBasicInformation, + KeyInfo, + BufferLength, + &ReturnedLength); + if (NT_SUCCESS(Status)) + { + if (KeyInfo->NameLength + sizeof(WCHAR) <= SubKeyName->MaximumLength) + { + memmove(SubKeyName->Buffer, + KeyInfo->Name, + KeyInfo->NameLength); + SubKeyName->Buffer[KeyInfo->NameLength / sizeof(WCHAR)] = 0; + SubKeyName->Length = KeyInfo->NameLength; + } + else + { + Status = STATUS_BUFFER_OVERFLOW; + } + } + + if (KeyInfo != NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), + 0, + KeyInfo); + } + + return(Status); +} + + +NTSTATUS STDCALL +RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle) +{ + return(NtDeleteKey(KeyHandle)); +} + + +NTSTATUS STDCALL +RtlpNtOpenKey(OUT HANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Unused) +{ + if (ObjectAttributes != NULL) + ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); + + return(NtOpenKey(KeyHandle, + DesiredAccess, + ObjectAttributes)); +} + + +NTSTATUS STDCALL +RtlpNtQueryValueKey(IN HANDLE KeyHandle, + OUT PULONG Type OPTIONAL, + OUT PVOID Data OPTIONAL, + IN OUT PULONG DataLength OPTIONAL, + IN ULONG Unused) +{ + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + UNICODE_STRING ValueName; + ULONG BufferLength; + ULONG ReturnedLength; + NTSTATUS Status; + + RtlInitUnicodeString(&ValueName, + NULL); + + BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION); + if (DataLength != NULL) + BufferLength = *DataLength; + + ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + BufferLength); + if (ValueInfo == NULL) + return(STATUS_NO_MEMORY); + + Status = NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + BufferLength, + &ReturnedLength); + if (NT_SUCCESS(Status)) + { + if (DataLength != NULL) + *DataLength = ValueInfo->DataLength; + + if (Type != NULL) + *Type = ValueInfo->Type; + + if (Data != NULL) + { + memmove(Data, + ValueInfo->Data, + ValueInfo->DataLength); + } + } + + RtlFreeHeap(RtlGetProcessHeap(), + 0, + ValueInfo); + + return(Status); +} + + +NTSTATUS STDCALL +RtlpNtSetValueKey(IN HANDLE KeyHandle, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataLength) +{ + UNICODE_STRING ValueName; + + RtlInitUnicodeString(&ValueName, + NULL); + return(NtSetValueKey(KeyHandle, + &ValueName, + 0, + Type, + Data, + DataLength)); +} + + +/* INTERNAL FUNCTIONS ******************************************************/ + +NTSTATUS +RtlpGetRegistryHandle(ULONG RelativeTo, + PWSTR Path, + BOOLEAN Create, + PHANDLE KeyHandle) +{ + UNICODE_STRING KeyName; + WCHAR KeyBuffer[MAX_PATH]; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + DPRINT("RtlpGetRegistryHandle()\n"); + + if (RelativeTo & RTL_REGISTRY_HANDLE) + { + Status = NtDuplicateObject(NtCurrentProcess(), + (HANDLE)Path, + NtCurrentProcess(), + KeyHandle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS); + return(Status); + } + + if (RelativeTo & RTL_REGISTRY_OPTIONAL) + RelativeTo &= ~RTL_REGISTRY_OPTIONAL; + + if (RelativeTo >= RTL_REGISTRY_MAXIMUM) + return(STATUS_INVALID_PARAMETER); + + KeyName.Length = 0; + KeyName.MaximumLength = MAX_PATH; + KeyName.Buffer = KeyBuffer; + KeyBuffer[0] = 0; + + switch (RelativeTo) + { + case RTL_REGISTRY_ABSOLUTE: + RtlAppendUnicodeToString(&KeyName, + L"\\"); + break; + + case RTL_REGISTRY_SERVICES: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + break; + + case RTL_REGISTRY_CONTROL: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\"); + break; + + case RTL_REGISTRY_WINDOWS_NT: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\"); + break; + + case RTL_REGISTRY_DEVICEMAP: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\Hardware\\DeviceMap\\"); + break; + + case RTL_REGISTRY_USER: + Status = RtlFormatCurrentUserKeyPath(&KeyName); + if (!NT_SUCCESS(Status)) + return(Status); + break; + + /* ReactOS specific */ + case RTL_REGISTRY_ENUM: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + break; + } + + DPRINT("KeyName %wZ\n", &KeyName); + + if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) + { + Path++; + } + RtlAppendUnicodeToString(&KeyName, + Path); + + DPRINT("KeyName %wZ\n", &KeyName); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + NULL, + NULL); + + if (Create == TRUE) + { + Status = NtCreateKey(KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + 0, + NULL); + } + else + { + Status = NtOpenKey(KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + } + + return(Status); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/resource.c b/lib/ntdll/rtl/resource.c new file mode 100644 index 0000000..b311924 --- /dev/null +++ b/lib/ntdll/rtl/resource.c @@ -0,0 +1,302 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/rtl/resource.c + * PURPOSE: Resource (multiple-reader-single-writer lock) functions + * PROGRAMMER: + * UPDATE HISTORY: + * Created 24/05/2001 + * + * NOTES: Partially take from Wine: + * Copyright 1996-1998 Marcus Meissner + * 1999 Alex Korobka + */ + +/* + * xxxResource() functions implement multiple-reader-single-writer lock. + * The code is based on information published in WDJ January 1999 issue. + */ + +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +RtlInitializeResource(PRTL_RESOURCE Resource) +{ + NTSTATUS Status; + + Status = RtlInitializeCriticalSection(&Resource->Lock); + if (!NT_SUCCESS(Status)) + { + RtlRaiseStatus(Status); + } + + Status = NtCreateSemaphore(&Resource->SharedSemaphore, + SEMAPHORE_ALL_ACCESS, + NULL, + 0, + 65535); + if (!NT_SUCCESS(Status)) + { + RtlRaiseStatus(Status); + } + Resource->SharedWaiters = 0; + + Status = NtCreateSemaphore(&Resource->ExclusiveSemaphore, + SEMAPHORE_ALL_ACCESS, + NULL, + 0, + 65535); + if (!NT_SUCCESS(Status)) + { + RtlRaiseStatus(Status); + } + Resource->ExclusiveWaiters = 0; + + Resource->NumberActive = 0; + Resource->OwningThread = NULL; + Resource->TimeoutBoost = 0; /* no info on this one, default value is 0 */ +} + + +VOID STDCALL +RtlDeleteResource(PRTL_RESOURCE Resource) +{ + RtlDeleteCriticalSection(&Resource->Lock); + NtClose(Resource->ExclusiveSemaphore); + NtClose(Resource->SharedSemaphore); + Resource->OwningThread = NULL; + Resource->ExclusiveWaiters = 0; + Resource->SharedWaiters = 0; + Resource->NumberActive = 0; +} + + +BOOLEAN STDCALL +RtlAcquireResourceExclusive(PRTL_RESOURCE Resource, + BOOLEAN Wait) +{ + NTSTATUS Status; + BOOLEAN retVal = FALSE; + +start: + RtlEnterCriticalSection(&Resource->Lock); + if (Resource->NumberActive == 0) /* lock is free */ + { + Resource->NumberActive = -1; + retVal = TRUE; + } + else if (Resource->NumberActive < 0) /* exclusive lock in progress */ + { + if (Resource->OwningThread == NtCurrentTeb()->Cid.UniqueThread) + { + retVal = TRUE; + Resource->NumberActive--; + goto done; + } +wait: + if (Wait == TRUE) + { + Resource->ExclusiveWaiters++; + + RtlLeaveCriticalSection(&Resource->Lock); + Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + goto done; + goto start; /* restart the acquisition to avoid deadlocks */ + } + } + else /* one or more shared locks are in progress */ + { + if (Wait == TRUE) + goto wait; + } + if (retVal == TRUE) + Resource->OwningThread = NtCurrentTeb()->Cid.UniqueThread; +done: + RtlLeaveCriticalSection(&Resource->Lock); + return retVal; +} + + +BOOLEAN STDCALL +RtlAcquireResourceShared(PRTL_RESOURCE Resource, + BOOLEAN Wait) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN retVal = FALSE; + +start: + RtlEnterCriticalSection(&Resource->Lock); + if (Resource->NumberActive < 0) + { + if (Resource->OwningThread == NtCurrentTeb()->Cid.UniqueThread) + { + Resource->NumberActive--; + retVal = TRUE; + goto done; + } + + if (Wait == TRUE) + { + Resource->SharedWaiters++; + RtlLeaveCriticalSection(&Resource->Lock); + Status = NtWaitForSingleObject(Resource->SharedSemaphore, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + goto done; + goto start; + } + } + else + { + if (Status != STATUS_WAIT_0) /* otherwise RtlReleaseResource() has already done it */ + Resource->NumberActive++; + retVal = TRUE; + } +done: + RtlLeaveCriticalSection(&Resource->Lock); + return retVal; +} + + +VOID STDCALL +RtlConvertExclusiveToShared(PRTL_RESOURCE Resource) +{ + RtlEnterCriticalSection(&Resource->Lock); + + if (Resource->NumberActive == -1) + { + Resource->OwningThread = NULL; + + if (Resource->SharedWaiters > 0) + { + ULONG n; + /* prevent new writers from joining until + * all queued readers have done their thing */ + n = Resource->SharedWaiters; + Resource->NumberActive = Resource->SharedWaiters + 1; + Resource->SharedWaiters = 0; + NtReleaseSemaphore(Resource->SharedSemaphore, + n, + NULL); + } + else + { + Resource->NumberActive = 1; + } + } + + RtlLeaveCriticalSection(&Resource->Lock); +} + + +VOID STDCALL +RtlConvertSharedToExclusive(PRTL_RESOURCE Resource) +{ + NTSTATUS Status; + + RtlEnterCriticalSection(&Resource->Lock); + + if (Resource->NumberActive == 1) + { + Resource->OwningThread = NtCurrentTeb()->Cid.UniqueThread; + Resource->NumberActive = -1; + } + else + { + Resource->ExclusiveWaiters++; + + RtlLeaveCriticalSection(&Resource->Lock); + Status = NtWaitForSingleObject(Resource->ExclusiveSemaphore, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + return; + + RtlEnterCriticalSection(&Resource->Lock); + Resource->OwningThread = NtCurrentTeb()->Cid.UniqueThread; + Resource->NumberActive = -1; + } + RtlLeaveCriticalSection(&Resource->Lock); +} + + +VOID STDCALL +RtlReleaseResource(PRTL_RESOURCE Resource) +{ + RtlEnterCriticalSection(&Resource->Lock); + + if (Resource->NumberActive > 0) /* have one or more readers */ + { + Resource->NumberActive--; + if (Resource->NumberActive == 0) + { + if (Resource->ExclusiveWaiters > 0) + { +wake_exclusive: + Resource->ExclusiveWaiters--; + NtReleaseSemaphore(Resource->ExclusiveSemaphore, + 1, + NULL); + } + } + } + else if (Resource->NumberActive < 0) /* have a writer, possibly recursive */ + { + Resource->NumberActive++; + if (Resource->NumberActive == 0) + { + Resource->OwningThread = 0; + if (Resource->ExclusiveWaiters > 0) + { + goto wake_exclusive; + } + else + { + if (Resource->SharedWaiters > 0) + { + ULONG n; + /* prevent new writers from joining until + * all queued readers have done their thing */ + n = Resource->SharedWaiters; + Resource->NumberActive = Resource->SharedWaiters; + Resource->SharedWaiters = 0; + NtReleaseSemaphore(Resource->SharedSemaphore, + n, + NULL); + } + } + } + } + RtlLeaveCriticalSection(&Resource->Lock); +} + + +VOID STDCALL +RtlDumpResource(PRTL_RESOURCE Resource) +{ + DbgPrint("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n", + Resource, + Resource->NumberActive, + Resource->SharedWaiters, + Resource->ExclusiveWaiters); + if (Resource->NumberActive != 0) + { + DbgPrint("\towner thread = %08x\n", + Resource->OwningThread); + } +} + +/* EOF */ \ No newline at end of file diff --git a/lib/ntdll/rtl/sd.c b/lib/ntdll/rtl/sd.c new file mode 100644 index 0000000..05f3471 --- /dev/null +++ b/lib/ntdll/rtl/sd.c @@ -0,0 +1,660 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security descriptor functions + * FILE: lib/ntdll/rtl/sd.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + ULONG Revision) +{ + if (Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + + SecurityDescriptor->Revision = 1; + SecurityDescriptor->Sbz1 = 0; + SecurityDescriptor->Control = 0; + SecurityDescriptor->Owner = NULL; + SecurityDescriptor->Group = NULL; + SecurityDescriptor->Sacl = NULL; + SecurityDescriptor->Dacl = NULL; + + return(STATUS_SUCCESS); +} + +ULONG STDCALL +RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + PSID Owner; + PSID Group; + ULONG Length; + PACL Dacl; + PACL Sacl; + + Length = sizeof(SECURITY_DESCRIPTOR); + + if (SecurityDescriptor->Owner != NULL) + { + Owner = SecurityDescriptor->Owner; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Owner = (PSID)((ULONG)Owner + + (ULONG)SecurityDescriptor); + } + Length = Length + ((sizeof(SID) + (Owner->SubAuthorityCount - 1) * + sizeof(ULONG) + 3) & 0xfc); + } + + if (SecurityDescriptor->Group != NULL) + { + Group = SecurityDescriptor->Group; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor); + } + Length = Length + ((sizeof(SID) + (Group->SubAuthorityCount - 1) * + sizeof(ULONG) + 3) & 0xfc); + } + + if (SecurityDescriptor->Control & SE_DACL_PRESENT && + SecurityDescriptor->Dacl != NULL) + { + Dacl = SecurityDescriptor->Dacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Dacl = (PACL)((ULONG)Dacl + (PVOID)SecurityDescriptor); + } + Length = Length + ((Dacl->AclSize + 3) & 0xfc); + } + + if (SecurityDescriptor->Control & SE_SACL_PRESENT && + SecurityDescriptor->Sacl != NULL) + { + Sacl = SecurityDescriptor->Sacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Sacl = (PACL)((ULONG)Sacl + (PVOID)SecurityDescriptor); + } + Length = Length + ((Sacl->AclSize + 3) & 0xfc); + } + + return(Length); +} + + +NTSTATUS STDCALL +RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PBOOLEAN DaclPresent, + PACL* Dacl, + PBOOLEAN DaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (!(SecurityDescriptor->Control & SE_DACL_PRESENT)) + { + *DaclPresent = 0; + return(STATUS_SUCCESS); + } + *DaclPresent = 1; + if (SecurityDescriptor->Dacl == NULL) + { + *Dacl = NULL; + } + else + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Dacl = (PACL)((ULONG)SecurityDescriptor->Dacl + + (PVOID)SecurityDescriptor); + } + else + { + *Dacl = SecurityDescriptor->Dacl; + } + } + if (SecurityDescriptor->Control & SE_DACL_DEFAULTED) + { + *DaclDefaulted = 1; + } + else + { + *DaclDefaulted = 0; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN DaclPresent, + PACL Dacl, + BOOLEAN DaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + if (!DaclPresent) + { + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_PRESENT); + return(STATUS_SUCCESS); + } + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_PRESENT; + SecurityDescriptor->Dacl = Dacl; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_DEFAULTED); + if (DaclDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_DEFAULTED; + } + return(STATUS_SUCCESS); +} + + +BOOLEAN STDCALL +RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + PSID Owner; + PSID Group; + PACL Sacl; + PACL Dacl; + + if (SecurityDescriptor->Revision != 1) + { + return(FALSE); + } + + Owner = SecurityDescriptor->Owner; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Owner = (PSID)((ULONG)Owner + (ULONG)SecurityDescriptor); + } + + if (!RtlValidSid(Owner)) + { + return(FALSE); + } + + Group = SecurityDescriptor->Group; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor); + } + + if (!RtlValidSid(Group)) + { + return(FALSE); + } + + if (SecurityDescriptor->Control & SE_DACL_PRESENT && + SecurityDescriptor->Dacl != NULL) + { + Dacl = SecurityDescriptor->Dacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Dacl = (PACL)((ULONG)Dacl + (ULONG)SecurityDescriptor); + } + + if (!RtlValidAcl(Dacl)) + { + return(FALSE); + } + } + + if (SecurityDescriptor->Control & SE_SACL_PRESENT && + SecurityDescriptor->Sacl != NULL) + { + Sacl = SecurityDescriptor->Sacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Sacl = (PACL)((ULONG)Sacl + (ULONG)SecurityDescriptor); + } + + if (!RtlValidAcl(Sacl)) + { + return(FALSE); + } + } + + return(TRUE); +} + + +NTSTATUS STDCALL +RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID Owner, + BOOLEAN OwnerDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + SecurityDescriptor->Owner = Owner; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_OWNER_DEFAULTED); + if (OwnerDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_OWNER_DEFAULTED; + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID* Owner, + PBOOLEAN OwnerDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Owner != NULL) + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Owner = (PSID)((ULONG)SecurityDescriptor->Owner + + (PVOID)SecurityDescriptor); + } + else + { + *Owner = SecurityDescriptor->Owner; + } + } + else + { + *Owner = NULL; + } + if (SecurityDescriptor->Control & SE_OWNER_DEFAULTED) + { + *OwnerDefaulted = 1; + } + else + { + *OwnerDefaulted = 0; + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID Group, + BOOLEAN GroupDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + SecurityDescriptor->Group = Group; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_GROUP_DEFAULTED); + if (GroupDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_GROUP_DEFAULTED; + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID* Group, + PBOOLEAN GroupDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Group != NULL) + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Group = (PSID)((ULONG)SecurityDescriptor->Group + + (PVOID)SecurityDescriptor); + } + else + { + *Group = SecurityDescriptor->Group; + } + } + else + { + *Group = NULL; + } + if (SecurityDescriptor->Control & SE_GROUP_DEFAULTED) + { + *GroupDefaulted = 1; + } + else + { + *GroupDefaulted = 0; + } + return(STATUS_SUCCESS); +} + + +static VOID +RtlpQuerySecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID* Owner, + PULONG OwnerLength, + PSID* Group, + PULONG GroupLength, + PACL* Dacl, + PULONG DaclLength, + PACL* Sacl, + PULONG SaclLength) +{ + if (SecurityDescriptor->Owner == NULL) + { + *Owner = NULL; + } + else + { + *Owner = SecurityDescriptor->Owner; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Owner = (PSID)((ULONG)*Owner + (ULONG)SecurityDescriptor); + } + } + + if (*Owner != NULL) + { + *OwnerLength = (RtlLengthSid(*Owner) + 3) & ~3; + } + else + { + *OwnerLength = 0; + } + + if ((SecurityDescriptor->Control & SE_DACL_PRESENT) && + SecurityDescriptor->Dacl != NULL) + { + *Dacl = SecurityDescriptor->Dacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Dacl = (PACL)((ULONG)*Dacl + (ULONG)SecurityDescriptor); + } + } + else + { + *Dacl = NULL; + } + + if (*Dacl != NULL) + { + *DaclLength = ((*Dacl)->AclSize + 3) & ~3; + } + else + { + *DaclLength = 0; + } + + if (SecurityDescriptor->Group != NULL) + { + *Group = NULL; + } + else + { + *Group = SecurityDescriptor->Group; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Group = (PSID)((ULONG)*Group + (ULONG)SecurityDescriptor); + } + } + + if (*Group != NULL) + { + *GroupLength = (RtlLengthSid(*Group) + 3) & ~3; + } + else + { + *GroupLength = 0; + } + + if ((SecurityDescriptor->Control & SE_SACL_PRESENT) && + SecurityDescriptor->Sacl != NULL) + { + *Sacl = SecurityDescriptor->Sacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Sacl = (PACL)((ULONG)*Sacl + (ULONG)SecurityDescriptor); + } + } + else + { + *Sacl = NULL; + } + + if (*Sacl != NULL) + { + *SaclLength = ((*Sacl)->AclSize + 3) & ~3; + } +} + + +NTSTATUS STDCALL +RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, + PSECURITY_DESCRIPTOR RelSD, + PULONG BufferLength) +{ + PSID Owner; + PSID Group; + PACL Sacl; + PACL Dacl; + ULONG OwnerLength; + ULONG GroupLength; + ULONG SaclLength; + ULONG DaclLength; + ULONG TotalLength; + ULONG Current; + + RtlpQuerySecurityDescriptor(AbsSD, + &Owner, + &OwnerLength, + &Group, + &GroupLength, + &Dacl, + &DaclLength, + &Sacl, + &SaclLength); + + TotalLength = OwnerLength + GroupLength + SaclLength + DaclLength + sizeof(SECURITY_DESCRIPTOR); + if (*BufferLength < TotalLength) + { + return(STATUS_BUFFER_TOO_SMALL); + } + + RtlZeroMemory(RelSD, + TotalLength); + memmove(RelSD, + AbsSD, + sizeof(SECURITY_DESCRIPTOR)); + Current = (ULONG)RelSD + sizeof(SECURITY_DESCRIPTOR); + + if (SaclLength != 0) + { + memmove((PVOID)Current, + Sacl, + SaclLength); + RelSD->Sacl = (PACL)((ULONG)Current - (ULONG)RelSD); + Current += SaclLength; + } + + if (DaclLength != 0) + { + memmove((PVOID)Current, + Dacl, + DaclLength); + RelSD->Dacl = (PACL)((ULONG)Current - (ULONG)RelSD); + Current += DaclLength; + } + + if (OwnerLength != 0) + { + memmove((PVOID)Current, + Owner, + OwnerLength); + RelSD->Owner = (PSID)((ULONG)Current - (ULONG)RelSD); + Current += OwnerLength; + } + + if (GroupLength != 0) + { + memmove((PVOID)Current, + Group, + GroupLength); + RelSD->Group = (PSID)((ULONG)Current - (ULONG)RelSD); + } + + RelSD->Control |= SE_SELF_RELATIVE; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlAbsoluteToSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, + PSECURITY_DESCRIPTOR RelSD, + PULONG BufferLength + ) +{ + if (AbsSD->Control & SE_SELF_RELATIVE) + { + return(STATUS_BAD_DESCRIPTOR_FORMAT); + } + + return(RtlMakeSelfRelativeSD(AbsSD, RelSD, BufferLength)); +} + + +NTSTATUS STDCALL +RtlGetControlSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSECURITY_DESCRIPTOR_CONTROL Control, + PULONG Revision) +{ + *Revision = SecurityDescriptor->Revision; + + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNKNOWN_REVISION); + } + + *Control = SecurityDescriptor->Control; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PBOOLEAN SaclPresent, + PACL *Sacl, + PBOOLEAN SaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (!(SecurityDescriptor->Control & SE_SACL_PRESENT)) + { + *SaclPresent = 0; + return(STATUS_SUCCESS); + } + *SaclPresent = 1; + if (SecurityDescriptor->Sacl == NULL) + { + *Sacl = NULL; + } + else + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Sacl = (PACL)((ULONG)SecurityDescriptor->Sacl + + (PVOID)SecurityDescriptor); + } + else + { + *Sacl = SecurityDescriptor->Sacl; + } + } + if (SecurityDescriptor->Control & SE_SACL_DEFAULTED) + { + *SaclDefaulted = 1; + } + else + { + *SaclDefaulted = 0; + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN SaclPresent, + PACL Sacl, + BOOLEAN SaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + if (!SaclPresent) + { + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_PRESENT); + return(STATUS_SUCCESS); + } + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_PRESENT; + SecurityDescriptor->Sacl = Sacl; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_DEFAULTED); + if (SaclDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_DEFAULTED; + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +RtlSelfRelativeToAbsoluteSD(PSECURITY_DESCRIPTOR RelSD, + PSECURITY_DESCRIPTOR AbsSD, + PDWORD AbsSDSize, + PACL Dacl, + PDWORD DaclSize, + PACL Sacl, + PDWORD SaclSize, + PSID Owner, + PDWORD OwnerSize, + PSID Group, + PDWORD GroupSize) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/security.c b/lib/ntdll/rtl/security.c new file mode 100644 index 0000000..a41a793 --- /dev/null +++ b/lib/ntdll/rtl/security.c @@ -0,0 +1,65 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/security.c + * PURPOSE: Miscellaneous securitiy related functions + * PROGRAMMER: Eric Kohl + * UPDATE HISTORY: + * 21/11/2001 Created + */ + +#include +#include + + +NTSTATUS STDCALL +RtlImpersonateSelf(IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + SECURITY_QUALITY_OF_SERVICE SecQos; + HANDLE ProcessToken; + HANDLE ImpersonationToken; + NTSTATUS Status; + + Status = NtOpenProcessToken(NtCurrentProcess(), + TOKEN_DUPLICATE, + &ProcessToken); + if (!NT_SUCCESS(Status)) + return(Status); + + SecQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + SecQos.ImpersonationLevel = ImpersonationLevel; + SecQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; + SecQos.EffectiveOnly = FALSE; + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = 0; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = 0; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = &SecQos; + + Status = NtDuplicateToken(ProcessToken, + TOKEN_IMPERSONATE, + &ObjectAttributes, + 0, + TokenImpersonation, + &ImpersonationToken); + if (!NT_SUCCESS(Status)) + { + NtClose(ProcessToken); + return(Status); + } + + Status = NtSetInformationThread(NtCurrentThread(), + ThreadImpersonationToken, + &ImpersonationToken, + sizeof(HANDLE)); + NtClose(ImpersonationToken); + NtClose(ProcessToken); + + return(Status); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/sid.c b/lib/ntdll/rtl/sid.c new file mode 100644 index 0000000..c5f7d90 --- /dev/null +++ b/lib/ntdll/rtl/sid.c @@ -0,0 +1,311 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: lib/ntdll/rtl/sid.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +//#include + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN STDCALL +RtlValidSid(IN PSID Sid) +{ + if ((Sid->Revision & 0xf) != 1) + { + return(FALSE); + } + if (Sid->SubAuthorityCount > 15) + { + return(FALSE); + } + return(TRUE); +} + + +ULONG STDCALL +RtlLengthRequiredSid(IN UCHAR SubAuthorityCount) +{ + return(sizeof(SID) + (SubAuthorityCount - 1) * sizeof(ULONG)); +} + + +NTSTATUS STDCALL +RtlInitializeSid(IN PSID Sid, + IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + IN UCHAR SubAuthorityCount) +{ + Sid->Revision = 1; + Sid->SubAuthorityCount = SubAuthorityCount; + memcpy(&Sid->IdentifierAuthority, + IdentifierAuthority, + sizeof(SID_IDENTIFIER_AUTHORITY)); + return(STATUS_SUCCESS); +} + + +PULONG STDCALL +RtlSubAuthoritySid(IN PSID Sid, + IN ULONG SubAuthority) +{ + return(&Sid->SubAuthority[SubAuthority]); +} + + +PUCHAR STDCALL +RtlSubAuthorityCountSid(IN PSID Sid) +{ + return(&Sid->SubAuthorityCount); +} + + +BOOLEAN STDCALL +RtlEqualSid(IN PSID Sid1, + IN PSID Sid2) +{ + if (Sid1->Revision != Sid2->Revision) + { + return(FALSE); + } + if ((*RtlSubAuthorityCountSid(Sid1)) != (*RtlSubAuthorityCountSid(Sid2))) + { + return(FALSE); + } + if (memcmp(Sid1, Sid2, RtlLengthSid(Sid1)) != 0) + { + return(FALSE); + } + return(TRUE); +} + + +ULONG STDCALL +RtlLengthSid(IN PSID Sid) +{ + return(sizeof(SID) + (Sid->SubAuthorityCount-1)*4); +} + + +NTSTATUS STDCALL +RtlCopySid(ULONG BufferLength, + PSID Dest, + PSID Src) +{ + if (BufferLength < RtlLengthSid(Src)) + { + return(STATUS_UNSUCCESSFUL); + } + memmove(Dest, + Src, + RtlLengthSid(Src)); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCopySidAndAttributesArray(ULONG Count, + PSID_AND_ATTRIBUTES Src, + ULONG SidAreaSize, + PSID_AND_ATTRIBUTES Dest, + PVOID SidArea, + PVOID* RemainingSidArea, + PULONG RemainingSidAreaSize) +{ + ULONG SidLength; + ULONG Length; + ULONG i; + + Length = SidAreaSize; + + for (i=0; i Length) + { + return(STATUS_BUFFER_TOO_SMALL); + } + SidLength = RtlLengthSid(Src[i].Sid); + Length = Length - SidLength; + Dest[i].Sid = SidArea; + Dest[i].Attributes = Src[i].Attributes; + RtlCopySid(SidLength, + SidArea, + Src[i].Sid); + SidArea = SidArea + SidLength; + } + *RemainingSidArea = SidArea; + *RemainingSidAreaSize = Length; + return(STATUS_SUCCESS); +} + + +PSID_IDENTIFIER_AUTHORITY STDCALL +RtlIdentifierAuthoritySid(IN PSID Sid) +{ + return(&Sid->IdentifierAuthority); +} + + +NTSTATUS +STDCALL +RtlAllocateAndInitializeSid ( + PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + UCHAR SubAuthorityCount, + ULONG SubAuthority0, + ULONG SubAuthority1, + ULONG SubAuthority2, + ULONG SubAuthority3, + ULONG SubAuthority4, + ULONG SubAuthority5, + ULONG SubAuthority6, + ULONG SubAuthority7, + PSID *Sid + ) +{ + PSID pSid; + + if (SubAuthorityCount > 8) + return STATUS_INVALID_SID; + + if (Sid == NULL) + return STATUS_INVALID_PARAMETER; + + pSid = (PSID)RtlAllocateHeap (RtlGetProcessHeap (), + 0, + SubAuthorityCount * sizeof(DWORD) + 8); + if (pSid == NULL) + return STATUS_NO_MEMORY; + + pSid->Revision = 1; + pSid->SubAuthorityCount = SubAuthorityCount; + memcpy (&pSid->IdentifierAuthority, + IdentifierAuthority, + sizeof(SID_IDENTIFIER_AUTHORITY)); + + switch (SubAuthorityCount) + { + case 8: + pSid->SubAuthority[7] = SubAuthority7; + case 7: + pSid->SubAuthority[6] = SubAuthority6; + case 6: + pSid->SubAuthority[5] = SubAuthority5; + case 5: + pSid->SubAuthority[4] = SubAuthority4; + case 4: + pSid->SubAuthority[3] = SubAuthority3; + case 3: + pSid->SubAuthority[2] = SubAuthority2; + case 2: + pSid->SubAuthority[1] = SubAuthority1; + case 1: + pSid->SubAuthority[0] = SubAuthority0; + break; + } + + *Sid = pSid; + + return STATUS_SUCCESS; +} + + +PSID STDCALL +RtlFreeSid(IN PSID Sid) +{ + RtlFreeHeap(RtlGetProcessHeap(), + 0, + Sid); + return(Sid); +} + + +BOOLEAN STDCALL +RtlEqualPrefixSid(IN PSID Sid1, + IN PSID Sid2) +{ + return(Sid1->SubAuthorityCount == Sid2->SubAuthorityCount && + !memcmp(Sid1, Sid2, + (Sid1->SubAuthorityCount - 1) * sizeof(DWORD) + 8)); +} + + +NTSTATUS STDCALL +RtlConvertSidToUnicodeString(PUNICODE_STRING String, + PSID Sid, + BOOLEAN AllocateBuffer) +{ + WCHAR Buffer[256]; + PWSTR wcs; + ULONG Length; + BYTE i; + + if (RtlValidSid (Sid) == FALSE) + return STATUS_INVALID_SID; + + wcs = Buffer; + wcs += swprintf (wcs, L"S-%u-", Sid->Revision); + if (!Sid->IdentifierAuthority.Value[0] && + !Sid->IdentifierAuthority.Value[1]) + { + wcs += swprintf (wcs, + L"%u", + (DWORD)Sid->IdentifierAuthority.Value[2] << 24 | + (DWORD)Sid->IdentifierAuthority.Value[3] << 16 | + (DWORD)Sid->IdentifierAuthority.Value[4] << 8 | + (DWORD)Sid->IdentifierAuthority.Value[5]); + } + else + { + wcs += swprintf (wcs, + L"0x%02hx%02hx%02hx%02hx%02hx%02hx", + Sid->IdentifierAuthority.Value[0], + Sid->IdentifierAuthority.Value[1], + Sid->IdentifierAuthority.Value[2], + Sid->IdentifierAuthority.Value[3], + Sid->IdentifierAuthority.Value[4], + Sid->IdentifierAuthority.Value[5]); + } + + for (i = 0; i < Sid->SubAuthorityCount; i++) + { + wcs += swprintf (wcs, + L"-%u", + Sid->SubAuthority[0]); + } + + Length = (wcs - Buffer) * sizeof(WCHAR); + if(AllocateBuffer) + { + String->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length + sizeof(WCHAR)); + if (String->Buffer == NULL) + return STATUS_NO_MEMORY; + String->MaximumLength = Length + sizeof(WCHAR); + } + else + { + if (Length > String->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + + String->Length = Length; + memmove (String->Buffer, + Buffer, + Length); + if (Length < String->MaximumLength) + String->Buffer[Length] = 0; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/thread.c b/lib/ntdll/rtl/thread.c new file mode 100644 index 0000000..0bd496c --- /dev/null +++ b/lib/ntdll/rtl/thread.c @@ -0,0 +1,273 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Rtl user thread functions + * FILE: lib/ntdll/rtl/thread.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 09/07/99: Created + * 09/10/99: Cleanup and full stack support. + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS ***************************************************************/ + + +NTSTATUS STDCALL +RtlCreateUserThread(HANDLE ProcessHandle, + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN CreateSuspended, + LONG StackZeroBits, + PULONG StackReserve, + PULONG StackCommit, + PTHREAD_START_ROUTINE StartAddress, + PVOID Parameter, + PHANDLE ThreadHandle, + PCLIENT_ID ClientId) +{ + HANDLE LocalThreadHandle; + CLIENT_ID LocalClientId; + OBJECT_ATTRIBUTES ObjectAttributes; + INITIAL_TEB InitialTeb; + CONTEXT ThreadContext; + ULONG OldPageProtection; + NTSTATUS Status; + + /* initialize initial teb */ + if ((StackReserve != NULL) && (*StackReserve > 0x100000)) + InitialTeb.StackReserve = *StackReserve; + else + InitialTeb.StackReserve = 0x100000; /* 1MByte */ + + /* FIXME: use correct commit size */ +#if 0 + if ((StackCommit != NULL) && (*StackCommit > PAGE_SIZE)) + InitialTeb.StackCommit = *StackCommit; + else + InitialTeb.StackCommit = PAGE_SIZE; +#endif + InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE; + + /* add size of guard page */ + InitialTeb.StackCommit += PAGE_SIZE; + + /* Reserve stack */ + InitialTeb.StackAllocate = NULL; + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackAllocate, + 0, + &InitialTeb.StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Error reserving stack space!\n"); + return(Status); + } + + DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n", + InitialTeb.StackAllocate, InitialTeb.StackReserve); + + InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve); + InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit); + + DPRINT("StackBase: %p StackCommit: 0x%lX\n", + InitialTeb.StackBase, InitialTeb.StackCommit); + + /* Commit stack */ + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackLimit, + 0, + &InitialTeb.StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting stack page!\n"); + return(Status); + } + + DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n", + InitialTeb.StackLimit, + InitialTeb.StackCommit); + + /* Protect guard page */ + Status = NtProtectVirtualMemory(ProcessHandle, + InitialTeb.StackLimit, + PAGE_SIZE, + PAGE_GUARD | PAGE_READWRITE, + &OldPageProtection); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error protecting guard page!\n"); + return(Status); + } + + /* initialize thread context */ + RtlInitializeContext(ProcessHandle, + &ThreadContext, + Parameter, + StartAddress, + &InitialTeb); + + /* create the thread */ + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = NULL; + ObjectAttributes.Attributes = OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = SecurityDescriptor; + ObjectAttributes.SecurityQualityOfService = NULL; + + Status = NtCreateThread(&LocalThreadHandle, + THREAD_ALL_ACCESS, + &ObjectAttributes, + ProcessHandle, + &LocalClientId, + &ThreadContext, + &InitialTeb, + CreateSuspended); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error creating thread!\n"); + return(Status); + } + + /* return committed stack size */ + if (StackCommit) + *StackCommit = InitialTeb.StackCommit; + + /* return reserved stack size */ + if (StackReserve) + *StackReserve = InitialTeb.StackReserve; + + /* return thread handle */ + if (ThreadHandle) + *ThreadHandle = LocalThreadHandle; + + /* return client id */ + if (ClientId) + { + ClientId->UniqueProcess = LocalClientId.UniqueProcess; + ClientId->UniqueThread = LocalClientId.UniqueThread; + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlInitializeContext(HANDLE ProcessHandle, + PCONTEXT Context, + PVOID Parameter, + PTHREAD_START_ROUTINE StartAddress, + PINITIAL_TEB InitialTeb) +{ + ULONG Buffer[2]; + ULONG BytesWritten; + NTSTATUS Status; + + memset (Context, 0, sizeof(CONTEXT)); + Context->Eip = (LONG)StartAddress; + Context->SegGs = USER_DS; + Context->SegFs = TEB_SELECTOR; + Context->SegEs = USER_DS; + Context->SegDs = USER_DS; + Context->SegCs = USER_CS; + Context->SegSs = USER_DS; + Context->Esp = (ULONG)InitialTeb->StackBase - 8; + Context->EFlags = (1<<1) + (1<<9); + + /* prepare the thread stack for execution */ + if (ProcessHandle == NtCurrentProcess()) + { + *((PULONG)(InitialTeb->StackBase - 4)) = (ULONG)Parameter; + *((PULONG)(InitialTeb->StackBase - 8)) = 0xdeadbeef; + } + else + { + Buffer[0] = (ULONG)Parameter; + Buffer[1] = 0xdeadbeef; + + Status = NtWriteVirtualMemory(ProcessHandle, + (PVOID)((ULONG)InitialTeb->StackBase - 8), + Buffer, + 2 * sizeof(ULONG), + &BytesWritten); + return Status; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlFreeUserThreadStack(HANDLE ProcessHandle, + HANDLE ThreadHandle) +{ + THREAD_BASIC_INFORMATION ThreadInfo; + NTSTATUS Status; + ULONG BytesRead; + ULONG RegionSize; + PVOID StackBase; + PTEB Teb; + + Status = NtQueryInformationThread(ThreadHandle, + ThreadBasicInformation, + &ThreadInfo, + sizeof(THREAD_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + if (ThreadInfo.TebBaseAddress == NULL) + return(Status); + + Teb = (PTEB)ThreadInfo.TebBaseAddress; + Status = NtReadVirtualMemory(ProcessHandle, + &Teb->DeallocationStack, + &StackBase, + sizeof(PVOID), + &BytesRead); + if (!NT_SUCCESS(Status)) + return(Status); + + if (StackBase == NULL) + return(Status); + + RegionSize = 0; + Status = NtFreeVirtualMemory(ProcessHandle, + StackBase, + &RegionSize, + MEM_RELEASE); + return(Status); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/time.c b/lib/ntdll/rtl/time.c new file mode 100644 index 0000000..4c7cbb8 --- /dev/null +++ b/lib/ntdll/rtl/time.c @@ -0,0 +1,337 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/time.c + * PURPOSE: Conversion between Time and TimeFields + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + * UPDATE HISTORY: + * Created 22/05/98 + * 08/03/98 RJJ Implemented these functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + + +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 +#define SECSPERHOUR 3600 +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define EPOCHWEEKDAY 1 +#define DAYSPERWEEK 7 +#define EPOCHYEAR 1601 +#define DAYSPERNORMALYEAR 365 +#define DAYSPERLEAPYEAR 366 +#define MONSPERYEAR 12 + +#define TICKSTO1970 0x019db1ded53e8000 +#define TICKSTO1980 0x01a8e79fe1d58000 + +static const int YearLengths[2] = {DAYSPERNORMALYEAR, DAYSPERLEAPYEAR}; +static const int MonthLengths[2][MONSPERYEAR] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static __inline int IsLeapYear(int Year) +{ + return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; +} + +static __inline void NormalizeTimeFields(CSHORT *FieldToNormalize, + CSHORT *CarryField, + int Modulus) +{ + *FieldToNormalize = (CSHORT) (*FieldToNormalize - Modulus); + *CarryField = (CSHORT) (*CarryField + 1); +} + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +RtlTimeToElapsedTimeFields(IN PLARGE_INTEGER Time, + OUT PTIME_FIELDS TimeFields) +{ + ULONGLONG ElapsedSeconds; + ULONG SecondsInDay; + ULONG SecondsInMinute; + + /* Extract millisecond from time */ + TimeFields->Milliseconds = (CSHORT)((Time->QuadPart % TICKSPERSEC) / TICKSPERMSEC); + + /* Compute elapsed seconds */ + ElapsedSeconds = (ULONGLONG)Time->QuadPart / TICKSPERSEC; + + /* Compute seconds within the day */ + SecondsInDay = ElapsedSeconds % SECSPERDAY; + + /* Compute elapsed minutes within the day */ + SecondsInMinute = SecondsInDay % SECSPERHOUR; + + /* Compute elapsed time of day */ + TimeFields->Hour = (CSHORT)(SecondsInDay / SECSPERHOUR); + TimeFields->Minute = (CSHORT)(SecondsInMinute / SECSPERMIN); + TimeFields->Second = (CSHORT)(SecondsInMinute % SECSPERMIN); + + /* Compute elapsed days */ + TimeFields->Day = (CSHORT)(ElapsedSeconds / SECSPERDAY); + + /* The elapsed number of months and days cannot be calculated */ + TimeFields->Month = 0; + TimeFields->Year = 0; +} + + +VOID STDCALL +RtlTimeToTimeFields(PLARGE_INTEGER liTime, + PTIME_FIELDS TimeFields) +{ + const int *Months; + int LeapSecondCorrections, SecondsInDay, CurYear; + int LeapYear, CurMonth, GMTOffset; + long int Days; + long long int Time = (long long int)liTime->QuadPart; + + /* Extract millisecond from time and convert time into seconds */ + TimeFields->Milliseconds = (CSHORT) ((Time % TICKSPERSEC) / TICKSPERMSEC); + Time = Time / TICKSPERSEC; + + /* FIXME: Compute the number of leap second corrections here */ + LeapSecondCorrections = 0; + + /* FIXME: get the GMT offset here */ + GMTOffset = 0; + + /* Split the time into days and seconds within the day */ + Days = Time / SECSPERDAY; + SecondsInDay = Time % SECSPERDAY; + + /* Adjust the values for GMT and leap seconds */ + SecondsInDay += (GMTOffset - LeapSecondCorrections); + while (SecondsInDay < 0) + { + SecondsInDay += SECSPERDAY; + Days--; + } + while (SecondsInDay >= SECSPERDAY) + { + SecondsInDay -= SECSPERDAY; + Days++; + } + + /* compute time of day */ + TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR); + SecondsInDay = SecondsInDay % SECSPERHOUR; + TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN); + TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN); + + /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */ + + /* compute day of week */ + TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK); + + /* compute year */ + CurYear = EPOCHYEAR; + CurYear += Days / DAYSPERLEAPYEAR; + Days -= (CurYear - EPOCHYEAR) * DAYSPERLEAPYEAR; + CurYear--; /* The next calculation needs CurYear - 1 */ + Days += CurYear - CurYear / 4 + CurYear / 100 - CurYear / 400; + CurYear++; + Days -= EPOCHYEAR - 1 - (EPOCHYEAR -1) / 4 + (EPOCHYEAR -1) / 100 - (EPOCHYEAR - 1) / 400; + + /* FIXME: handle calendar modifications */ + while (1) + { + LeapYear = IsLeapYear(CurYear); + if (Days < (long) YearLengths[LeapYear]) + { + break; + } + CurYear++; + Days = Days - (long) YearLengths[LeapYear]; + } + TimeFields->Year = (CSHORT) CurYear; + + /* Compute month of year */ + LeapYear = IsLeapYear(CurYear); + Months = MonthLengths[LeapYear]; + for (CurMonth = 0; Days >= (long) Months[CurMonth]; CurMonth++) + Days = Days - (long) Months[CurMonth]; + TimeFields->Month = (CSHORT) (CurMonth + 1); + TimeFields->Day = (CSHORT) (Days + 1); +} + + +BOOLEAN STDCALL +RtlTimeFieldsToTime(PTIME_FIELDS tfTimeFields, + PLARGE_INTEGER Time) +{ + int CurYear, CurMonth; + long long int rcTime; + TIME_FIELDS TimeFields = *tfTimeFields; + + rcTime = 0; + + /* FIXME: normalize the TIME_FIELDS structure here */ + while (TimeFields.Second >= SECSPERMIN) + { + NormalizeTimeFields(&TimeFields.Second, + &TimeFields.Minute, + SECSPERMIN); + } + while (TimeFields.Minute >= MINSPERHOUR) + { + NormalizeTimeFields(&TimeFields.Minute, + &TimeFields.Hour, + MINSPERHOUR); + } + while (TimeFields.Hour >= HOURSPERDAY) + { + NormalizeTimeFields(&TimeFields.Hour, + &TimeFields.Day, + HOURSPERDAY); + } + while (TimeFields.Day > + MonthLengths[IsLeapYear(TimeFields.Year)][TimeFields.Month - 1]) + { + NormalizeTimeFields(&TimeFields.Day, + &TimeFields.Month, + SECSPERMIN); + } + while (TimeFields.Month > MONSPERYEAR) + { + NormalizeTimeFields(&TimeFields.Month, + &TimeFields.Year, + MONSPERYEAR); + } + + /* FIXME: handle calendar corrections here */ + for (CurYear = EPOCHYEAR; CurYear < TimeFields.Year; CurYear++) + { + rcTime += YearLengths[IsLeapYear(CurYear)]; + } + for (CurMonth = 1; CurMonth < TimeFields.Month; CurMonth++) + { + rcTime += MonthLengths[IsLeapYear(CurYear)][CurMonth - 1]; + } + rcTime += TimeFields.Day - 1; + rcTime *= SECSPERDAY; + rcTime += TimeFields.Hour * SECSPERHOUR + TimeFields.Minute * SECSPERMIN + + TimeFields.Second; + rcTime *= TICKSPERSEC; + rcTime += TimeFields.Milliseconds * TICKSPERMSEC; + *Time = *(LARGE_INTEGER *)&rcTime; + + return TRUE; +} + + +VOID STDCALL +RtlSecondsSince1970ToTime(ULONG SecondsSince1970, + PLARGE_INTEGER Time) +{ + LONGLONG llTime; + + llTime = (SecondsSince1970 * TICKSPERSEC) + TICKSTO1970; + + *Time = *(LARGE_INTEGER *)&llTime; +} + + +VOID STDCALL +RtlSecondsSince1980ToTime(ULONG SecondsSince1980, + PLARGE_INTEGER Time) +{ + LONGLONG llTime; + + llTime = (SecondsSince1980 * TICKSPERSEC) + TICKSTO1980; + + *Time = *(LARGE_INTEGER *)&llTime; +} + + +BOOLEAN STDCALL +RtlTimeToSecondsSince1970(PLARGE_INTEGER Time, + PULONG SecondsSince1970) +{ + LARGE_INTEGER liTime; + + liTime.QuadPart = Time->QuadPart - TICKSTO1970; + liTime.QuadPart = liTime.QuadPart / TICKSPERSEC; + + if (liTime.u.HighPart != 0) + return(FALSE); + + *SecondsSince1970 = liTime.u.LowPart; + + return(TRUE); +} + + +BOOLEAN STDCALL +RtlTimeToSecondsSince1980(PLARGE_INTEGER Time, + PULONG SecondsSince1980) +{ + LARGE_INTEGER liTime; + + liTime.QuadPart = Time->QuadPart - TICKSTO1980; + liTime.QuadPart = liTime.QuadPart / TICKSPERSEC; + + if (liTime.u.HighPart != 0) + return(FALSE); + + *SecondsSince1980 = liTime.u.LowPart; + + return(TRUE); +} + + +NTSTATUS STDCALL +RtlLocalTimeToSystemTime(PLARGE_INTEGER LocalTime, + PLARGE_INTEGER SystemTime) +{ + SYSTEM_TIMEOFDAY_INFORMATION TimeInformation; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemTimeOfDayInformation, + &TimeInformation, + sizeof(SYSTEM_TIMEOFDAY_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + SystemTime->QuadPart = LocalTime->QuadPart + + TimeInformation.TimeZoneBias.QuadPart; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlSystemTimeToLocalTime(PLARGE_INTEGER SystemTime, + PLARGE_INTEGER LocalTime) +{ + SYSTEM_TIMEOFDAY_INFORMATION TimeInformation; + NTSTATUS Status; + + Status = NtQuerySystemInformation(SystemTimeOfDayInformation, + &TimeInformation, + sizeof(SYSTEM_TIMEOFDAY_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + LocalTime->QuadPart = SystemTime->QuadPart - + TimeInformation.TimeZoneBias.QuadPart; + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/lib/ntdll/rtl/timezone.c b/lib/ntdll/rtl/timezone.c new file mode 100644 index 0000000..9396336 --- /dev/null +++ b/lib/ntdll/rtl/timezone.c @@ -0,0 +1,200 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Timezone functions + * FILE: lib/ntdll/rtl/timezone.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 29/05/2001: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +RtlQueryTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) +{ + HANDLE KeyHandle; + RTL_QUERY_REGISTRY_TABLE QueryTable[8]; + UNICODE_STRING StandardName; + UNICODE_STRING DaylightName; + NTSTATUS Status; + + DPRINT("RtlQueryTimeZoneInformation()\n"); + + Status = RtlpGetRegistryHandle(RTL_REGISTRY_CONTROL, + L"TimeZoneInformation", + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle failed (Status %x)\n", Status); + return Status; + } + + RtlZeroMemory(QueryTable, + sizeof(QueryTable)); + + StandardName.Length = 0; + StandardName.MaximumLength = 32 * sizeof(WCHAR); + StandardName.Buffer = TimeZoneInformation->StandardName; + + DaylightName.Length = 0; + DaylightName.MaximumLength = 32 * sizeof(WCHAR); + DaylightName.Buffer = TimeZoneInformation->DaylightName; + + QueryTable[0].Name = L"Bias"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &TimeZoneInformation->Bias; + + QueryTable[1].Name = L"Standard Name"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[1].EntryContext = &StandardName; + + QueryTable[2].Name = L"Standard Bias"; + QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[2].EntryContext = &TimeZoneInformation->StandardBias; + + QueryTable[3].Name = L"Standard Start"; + QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[3].EntryContext = &TimeZoneInformation->StandardDate; + + QueryTable[4].Name = L"Daylight Name"; + QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[4].EntryContext = &DaylightName; + + QueryTable[5].Name = L"Daylight Bias"; + QueryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[5].EntryContext = &TimeZoneInformation->DaylightBias; + + QueryTable[6].Name = L"Daylight Start"; + QueryTable[6].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[6].EntryContext = &TimeZoneInformation->DaylightDate; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + NtClose(KeyHandle); + + return Status; +} + + +NTSTATUS STDCALL +RtlSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) +{ + HANDLE KeyHandle; + ULONG Length; + NTSTATUS Status; + + DPRINT("RtlSetTimeZoneInformation()\n"); + + Status = RtlpGetRegistryHandle(RTL_REGISTRY_CONTROL, + L"TimeZoneInformation", + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle failed (Status %x)\n", Status); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Bias", + REG_DWORD, + &TimeZoneInformation->Bias, + sizeof(LONG)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Length = (wcslen(TimeZoneInformation->StandardName) + 1) * sizeof(WCHAR); + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Standard Name", + REG_SZ, + TimeZoneInformation->StandardName, + Length); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Standard Bias", + REG_DWORD, + &TimeZoneInformation->StandardBias, + sizeof(LONG)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Standard Start", + REG_BINARY, + &TimeZoneInformation->StandardDate, + sizeof(SYSTEMTIME)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Length = (wcslen(TimeZoneInformation->DaylightName) + 1) * sizeof(WCHAR); + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Daylight Name", + REG_SZ, + TimeZoneInformation->DaylightName, + Length); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Daylight Bias", + REG_DWORD, + &TimeZoneInformation->DaylightBias, + sizeof(LONG)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Daylight Start", + REG_BINARY, + &TimeZoneInformation->DaylightDate, + sizeof(SYSTEMTIME)); + + NtClose(KeyHandle); + + return Status; +} + +/* EOF */ diff --git a/lib/ntdll/rtl/trace.c b/lib/ntdll/rtl/trace.c new file mode 100644 index 0000000..687a090 --- /dev/null +++ b/lib/ntdll/rtl/trace.c @@ -0,0 +1,127 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * PURPOSE: Tracing library calls + * FILE: lib/ntdll/rtl/trace.c + * PROGRAMER: David Welch + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#include + +/* GLOBALS *******************************************************************/ + +static NTDLL_TRACE_TABLE TraceTable; +static BOOLEAN TraceTableValid = FALSE; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +RtlpInitTrace(VOID) +{ + HANDLE SectionHandle; + UNICODE_STRING SectionName; + OBJECT_ATTRIBUTES ObjectAttributes; + CHAR Buffer[4096]; + NTSTATUS Status; + PROCESS_BASIC_INFORMATION Pbi; + ULONG ReturnedSize; + PVOID BaseAddress; + LARGE_INTEGER Offset; + ULONG ViewSize; + + Status = NtQueryInformationProcess(NtCurrentProcess(), + ProcessBasicInformation, + (PVOID)&Pbi, + sizeof(Pbi), + &ReturnedSize); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + sprintf(Buffer, "\\??\\TraceSection%d", Pbi.UniqueProcessId); + + InitializeObjectAttributes(&ObjectAttributes, + &SectionName, + 0, + NULL, + NULL); + Status = NtOpenSection(&SectionHandle, + SECTION_MAP_READ, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + BaseAddress = 0; + Offset.QuadPart = 0; + ViewSize = 0; + Status = NtMapViewOfSection(SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + sizeof(NTDLL_TRACE_TABLE), + &Offset, + &ViewSize, + ViewUnmap, + 0, + PAGE_READONLY); + if (!NT_SUCCESS(Status)) + { + NtClose(SectionHandle); + return(Status); + } + NtClose(SectionHandle); + + memcpy(&TraceTable, BaseAddress, sizeof(TraceTable)); + TraceTableValid = TRUE; + + Status = NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress); + + return(STATUS_SUCCESS); +} + +VOID +RtlPrintTrace(ULONG Flag, PCH Format, ...) +{ + va_list ap; + CHAR FString[4096]; + + if (!TraceTableValid) + { + return; + } + if (TraceTable.Flags[Flag / BITS_IN_CHAR] & (1 << (Flag % BITS_IN_CHAR))) + { + va_start(ap, Format); + vsprintf(FString, Format, ap); + DbgPrint(FString); + va_end(ap); + } +} diff --git a/lib/ntdll/rtl/unicode.c b/lib/ntdll/rtl/unicode.c new file mode 100644 index 0000000..3bff31e --- /dev/null +++ b/lib/ntdll/rtl/unicode.c @@ -0,0 +1,1792 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/unicode.c + * PURPOSE: String functions + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * UPDATE HISTORY: + * Created 10/08/98 + */ + +#include +#include +//#include +#include +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +WCHAR +STDCALL +RtlAnsiCharToUnicodeChar ( + IN CHAR AnsiChar + ) +{ + ULONG Size; + WCHAR UnicodeChar; + + Size = 1; +#if 0 + Size = (NlsLeadByteInfo[AnsiChar] == 0) ? 1 : 2; +#endif + + RtlMultiByteToUnicodeN (&UnicodeChar, + sizeof(WCHAR), + NULL, + &AnsiChar, + Size); + + return UnicodeChar; +} + + +ULONG +STDCALL +RtlAnsiStringToUnicodeSize ( + IN PANSI_STRING AnsiString + ) +{ + ULONG Size; + + RtlMultiByteToUnicodeSize (&Size, + AnsiString->Buffer, + AnsiString->Length); + + return Size; +} + + +NTSTATUS +STDCALL +RtlAnsiStringToUnicodeString( + IN OUT PUNICODE_STRING DestinationString, + IN PANSI_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE) + Length = RtlAnsiStringToUnicodeSize (SourceString); + else + Length = SourceString->Length * sizeof(WCHAR); + + if (Length > 65535) + return STATUS_INVALID_PARAMETER_2; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(WCHAR); + DestinationString->Buffer = + RtlAllocateHeap (RtlGetProcessHeap (), + 0, + DestinationString->MaximumLength); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length + sizeof(WCHAR) > DestinationString->MaximumLength) + { + DPRINT("STATUS_BUFFER_TOO_SMALL\n"); + return STATUS_BUFFER_TOO_SMALL; + } + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlMultiByteToUnicodeN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Length / sizeof(WCHAR)] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlAppendAsciizToString ( + IN OUT PSTRING Destination, + IN PCSZ Source + ) +{ + ULONG Length; + PCHAR Ptr; + + if (Source == NULL) + return STATUS_SUCCESS; + + Length = strlen (Source); + if (Destination->Length + Length >= Destination->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + + Ptr = Destination->Buffer + Destination->Length; + memmove (Ptr, + Source, + Length); + Ptr += Length; + *Ptr = 0; + + Destination->Length += Length; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlAppendStringToString ( + IN OUT PSTRING Destination, + IN PSTRING Source + ) +{ + PCHAR Ptr; + + if (Source->Length == 0) + return STATUS_SUCCESS; + + if (Destination->Length + Source->Length >= Destination->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + + Ptr = Destination->Buffer + Destination->Length; + memmove (Ptr, + Source->Buffer, + Source->Length); + Ptr += Source->Length; + *Ptr = 0; + + Destination->Length += Source->Length; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlAppendUnicodeStringToString ( + IN OUT PUNICODE_STRING Destination, + IN PUNICODE_STRING Source + ) +{ + PWCHAR Src; + PWCHAR Dest; + ULONG i; + + if ((Source->Length + Destination->Length) >= Destination->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + + Src = Source->Buffer; + Dest = Destination->Buffer + (Destination->Length / sizeof (WCHAR)); + for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + Destination->Length += Source->Length; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination, + IN PWSTR Source) +{ + PWCHAR Src; + PWCHAR Dest; + ULONG i; + ULONG slen; + + slen = wcslen(Source) * sizeof(WCHAR); + + if (Destination->Length + slen >= Destination->MaximumLength) + return(STATUS_BUFFER_TOO_SMALL); + + Src = Source; + Dest = Destination->Buffer + (Destination->Length / sizeof(WCHAR)); + + for (i = 0; i < (slen / sizeof(WCHAR)); i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + Destination->Length += slen; + + return(STATUS_SUCCESS); +} + + +NTSTATUS +STDCALL +RtlCharToInteger ( + IN PCSZ String, + IN ULONG Base, + IN OUT PULONG Value) +{ + ULONG Val; + + *Value = 0; + + if (Base == 0) + { + Base = 10; + if (*String == '0') + { + Base = 8; + String++; + if ((*String == 'x') && isxdigit (String[1])) + { + String++; + Base = 16; + } + } + } + + if (!isxdigit (*String)) + return STATUS_INVALID_PARAMETER; + + while (isxdigit (*String) && + (Val = isdigit (*String) ? * String - '0' : (islower (*String) + ? toupper (*String) : *String) - 'A' + 10) < Base) + { + *Value = *Value * Base + Val; + String++; + } + + return STATUS_SUCCESS; +} + + +LONG +STDCALL +RtlCompareString ( + IN PSTRING String1, + IN PSTRING String2, + IN BOOLEAN CaseInsensitive + ) +{ + ULONG len1, len2; + PCHAR s1, s2; + CHAR c1, c2; + + if (String1 && String2) + { + len1 = String1->Length; + len2 = String2->Length; + s1 = String1->Buffer; + s2 = String2->Buffer; + + if (s1 && s2) + { + if (CaseInsensitive) + { + while (1) + { + c1 = len1-- ? RtlUpperChar (*s1++) : 0; + c2 = len2-- ? RtlUpperChar (*s2++) : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + else + { + while (1) + { + c1 = len1-- ? *s1++ : 0; + c2 = len2-- ? *s2++ : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + } + } + + return 0; +} + + +LONG +STDCALL +RtlCompareUnicodeString ( + IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2, + IN BOOLEAN CaseInsensitive + ) +{ + ULONG len1, len2; + PWCHAR s1, s2; + WCHAR c1, c2; + + if (String1 && String2) + { + len1 = String1->Length / sizeof(WCHAR); + len2 = String2->Length / sizeof(WCHAR); + s1 = String1->Buffer; + s2 = String2->Buffer; + + if (s1 && s2) + { + if (CaseInsensitive) + { + while (1) + { + c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0; + c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + else + { + while (1) + { + c1 = len1-- ? *s1++ : 0; + c2 = len2-- ? *s2++ : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + } + } + + return 0; +} + + +VOID +STDCALL +RtlCopyString ( + IN OUT PSTRING DestinationString, + IN PSTRING SourceString + ) +{ + ULONG copylen, i; + PCHAR Src, Dest; + + if (SourceString == NULL) + { + DestinationString->Length = 0; + return; + } + + copylen = min (DestinationString->MaximumLength - sizeof(CHAR), + SourceString->Length); + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + + for (i = 0; i < copylen; i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + DestinationString->Length = copylen; +} + + +VOID +STDCALL +RtlCopyUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString + ) +{ + ULONG copylen, i; + PWCHAR Src, Dest; + + if (SourceString == NULL) + { + DestinationString->Length = 0; + return; + } + + copylen = min (DestinationString->MaximumLength - sizeof(WCHAR), + SourceString->Length); + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + + for (i = 0; i < (copylen / sizeof (WCHAR)); i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + DestinationString->Length = copylen; +} + + +BOOLEAN +STDCALL +RtlCreateUnicodeString ( + IN OUT PUNICODE_STRING Destination, + IN PWSTR Source + ) +{ + ULONG Length; + + Length = (wcslen (Source) + 1) * sizeof(WCHAR); + + Destination->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length); + if (Destination->Buffer == NULL) + return FALSE; + + memmove (Destination->Buffer, + Source, + Length); + + Destination->MaximumLength = Length; + Destination->Length = Length - sizeof (WCHAR); + + return TRUE; +} + + +BOOLEAN STDCALL +RtlCreateUnicodeStringFromAsciiz (OUT PUNICODE_STRING Destination, + IN PCSZ Source) +{ + ANSI_STRING AnsiString; + NTSTATUS Status; + + RtlInitAnsiString (&AnsiString, + Source); + + Status = RtlAnsiStringToUnicodeString (Destination, + &AnsiString, + TRUE); + + return NT_SUCCESS(Status); +} + + +NTSTATUS +STDCALL +RtlDowncaseUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + ULONG i; + PWCHAR Src, Dest; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR); + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + SourceString->Length + sizeof(WCHAR)); + } + else + { + if (SourceString->Length >= DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = SourceString->Length; + + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + for (i=0; i < SourceString->Length / sizeof(WCHAR); i++) + { + if (*Src < L'A') + { + *Dest = *Src; + } + else if (*Src <= L'Z') + { + *Dest = (*Src + (L'a' - L'A')); + } + else + { + /* FIXME: characters above 'Z' */ + *Dest = *Src; + } + + Dest++; + Src++; + } + *Dest = 0; + + return STATUS_SUCCESS; +} + + +BOOLEAN +STDCALL +RtlEqualComputerName ( + IN PUNICODE_STRING ComputerName1, + IN PUNICODE_STRING ComputerName2 + ) +{ + return RtlEqualDomainName (ComputerName1, + ComputerName2); +} + + +BOOLEAN +STDCALL +RtlEqualDomainName ( + IN PUNICODE_STRING DomainName1, + IN PUNICODE_STRING DomainName2 + ) +{ + OEM_STRING OemString1; + OEM_STRING OemString2; + BOOLEAN Result; + + RtlUpcaseUnicodeStringToOemString (&OemString1, + DomainName1, + TRUE); + RtlUpcaseUnicodeStringToOemString (&OemString2, + DomainName2, + TRUE); + + Result = RtlEqualString (&OemString1, + &OemString2, + FALSE); + + RtlFreeOemString (&OemString1); + RtlFreeOemString (&OemString2); + + return Result; +} + + +BOOLEAN +STDCALL +RtlEqualString ( + IN PSTRING String1, + IN PSTRING String2, + IN BOOLEAN CaseInsensitive + ) +{ + ULONG i; + CHAR c1, c2; + PCHAR p1, p2; + + if (String1->Length != String2->Length) + return FALSE; + + p1 = String1->Buffer; + p2 = String2->Buffer; + for (i = 0; i < String1->Length; i++) + { + if (CaseInsensitive == TRUE) + { + c1 = RtlUpperChar (*p1); + c2 = RtlUpperChar (*p2); + } + else + { + c1 = *p1; + c2 = *p2; + } + + if (c1 != c2) + return FALSE; + + p1++; + p2++; + } + + return TRUE; +} + + +BOOLEAN +STDCALL +RtlEqualUnicodeString ( + IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2, + IN BOOLEAN CaseInsensitive + ) +{ + ULONG i; + WCHAR wc1, wc2; + PWCHAR pw1, pw2; + + if (String1->Length != String2->Length) + return FALSE; + + pw1 = String1->Buffer; + pw2 = String2->Buffer; + + for (i = 0; i < String1->Length / sizeof(WCHAR); i++) + { + if (CaseInsensitive == TRUE) + { + wc1 = RtlUpcaseUnicodeChar (*pw1); + wc2 = RtlUpcaseUnicodeChar (*pw2); + } + else + { + wc1 = *pw1; + wc2 = *pw2; + } + + if (wc1 != wc2) + return FALSE; + + pw1++; + pw2++; + } + + return TRUE; +} + + +VOID +STDCALL +RtlEraseUnicodeString ( + IN PUNICODE_STRING String + ) +{ + if (String->Buffer == NULL) + return; + + if (String->MaximumLength == 0) + return; + + memset (String->Buffer, + 0, + String->MaximumLength); + + String->Length = 0; +} + + +VOID +STDCALL +RtlFreeAnsiString ( + IN PANSI_STRING AnsiString + ) +{ + if (AnsiString->Buffer == NULL) + return; + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + AnsiString->Buffer); + + AnsiString->Buffer = NULL; + AnsiString->Length = 0; + AnsiString->MaximumLength = 0; +} + + +VOID +STDCALL +RtlFreeOemString ( + IN POEM_STRING OemString + ) +{ + if (OemString->Buffer == NULL) + return; + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + OemString->Buffer); + + OemString->Buffer = NULL; + OemString->Length = 0; + OemString->MaximumLength = 0; +} + + +VOID +STDCALL +RtlFreeUnicodeString ( + IN PUNICODE_STRING UnicodeString + ) +{ + if (UnicodeString->Buffer == NULL) + return; + + RtlFreeHeap (RtlGetProcessHeap (), + 0, + UnicodeString->Buffer); + + UnicodeString->Buffer = NULL; + UnicodeString->Length = 0; + UnicodeString->MaximumLength = 0; +} + + +VOID +STDCALL +RtlInitAnsiString ( + IN OUT PANSI_STRING DestinationString, + IN PCSZ SourceString + ) +{ + ULONG DestSize; + + if(SourceString==NULL) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + DestSize = strlen ((const char *)SourceString); + DestinationString->Length = DestSize; + DestinationString->MaximumLength = DestSize + 1; + } + DestinationString->Buffer = (PCHAR)SourceString; +} + + +VOID +STDCALL +RtlInitString ( + IN OUT PSTRING DestinationString, + IN PCSZ SourceString + ) +{ + ULONG DestSize; + + if (SourceString == NULL) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + DestSize = strlen((const char *)SourceString); + DestinationString->Length = DestSize; + DestinationString->MaximumLength = DestSize + sizeof(CHAR); + } + DestinationString->Buffer = (PCHAR)SourceString; +} + + +VOID +STDCALL +RtlInitUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN PCWSTR SourceString + ) +{ + ULONG DestSize; + + if (SourceString==NULL) + { + DestinationString->Length=0; + DestinationString->MaximumLength=0; + } + else + { + DestSize = wcslen((PWSTR)SourceString) * sizeof(WCHAR); + DestinationString->Length = DestSize; + DestinationString->MaximumLength = DestSize + sizeof(WCHAR); + } + DestinationString->Buffer = (PWSTR)SourceString; +} + + +NTSTATUS +STDCALL +RtlIntegerToChar ( + IN ULONG Value, + IN ULONG Base, + IN ULONG Length, + IN OUT PCHAR String + ) +{ + ULONG Radix; + CHAR temp[33]; + ULONG v = Value; + ULONG i; + PCHAR tp; + PCHAR sp; + + Radix = Base; + if (Radix == 0) + Radix = 10; + + if ((Radix != 2) && (Radix != 8) && + (Radix != 10) && (Radix != 16)) + return STATUS_INVALID_PARAMETER; + + tp = temp; + while (v || tp == temp) + { + i = v % Radix; + v = v / Radix; + if (i < 10) + *tp = i + '0'; + else + *tp = i + 'a' - 10; + tp++; + } + + if (tp - temp >= Length) + return STATUS_BUFFER_TOO_SMALL; + + sp = String; + while (tp > temp) + *sp++ = *--tp; + *sp = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlIntegerToUnicodeString ( + IN ULONG Value, + IN ULONG Base, /* optional */ + IN OUT PUNICODE_STRING String + ) +{ + ANSI_STRING AnsiString; + CHAR Buffer[33]; + NTSTATUS Status; + + Status = RtlIntegerToChar (Value, + Base, + 33, + Buffer); + if (!NT_SUCCESS(Status)) + return Status; + + AnsiString.Buffer = Buffer; + AnsiString.Length = strlen (Buffer); + AnsiString.MaximumLength = 33; + + Status = RtlAnsiStringToUnicodeString (String, + &AnsiString, + FALSE); + + return Status; +} + + +NTSTATUS +STDCALL +RtlLargeIntegerToChar ( + IN PLARGE_INTEGER Value, + IN ULONG Base, + IN ULONG Length, + IN OUT PCHAR String + ) +{ + ULONG Radix; + CHAR temp[65]; + ULONGLONG v = Value->QuadPart; + ULONG i; + PCHAR tp; + PCHAR sp; + + Radix = Base; + if (Radix == 0) + Radix = 10; + + if ((Radix != 2) && (Radix != 8) && + (Radix != 10) && (Radix != 16)) + return STATUS_INVALID_PARAMETER; + + tp = temp; + while (v || tp == temp) + { + i = v % Radix; + v = v / Radix; + if (i < 10) + *tp = i + '0'; + else + *tp = i + 'a' - 10; + tp++; + } + + if (tp - temp >= Length) + return STATUS_BUFFER_TOO_SMALL; + + sp = String; + while (tp > temp) + *sp++ = *--tp; + *sp = 0; + + return STATUS_SUCCESS; +} + + +ULONG +STDCALL +RtlOemStringToUnicodeSize ( + IN POEM_STRING OemString + ) +{ + ULONG Size; + + RtlMultiByteToUnicodeSize (&Size, + OemString->Buffer, + OemString->Length); + + return Size; +} + + +NTSTATUS +STDCALL +RtlOemStringToUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN POEM_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE) + Length = RtlAnsiStringToUnicodeSize (SourceString); + else + Length = SourceString->Length * sizeof(WCHAR); + + if (Length > 65535) + return STATUS_INVALID_PARAMETER_2; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(WCHAR); + DestinationString->Buffer = + RtlAllocateHeap (RtlGetProcessHeap (), + 0, + DestinationString->MaximumLength); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length + sizeof(WCHAR) > DestinationString->MaximumLength) + { + DPRINT("STATUS_BUFFER_TOO_SMALL\n"); + return STATUS_BUFFER_TOO_SMALL; + } + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlOemToUnicodeN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Length / sizeof(WCHAR)] = 0; + + return STATUS_SUCCESS; +} + + +BOOLEAN +STDCALL +RtlPrefixString ( + PANSI_STRING String1, + PANSI_STRING String2, + BOOLEAN CaseInsensitive + ) +{ + PCHAR pc1; + PCHAR pc2; + ULONG Length; + + if (String2->Length < String1->Length) + return FALSE; + + Length = String1->Length; + pc1 = String1->Buffer; + pc2 = String2->Buffer; + + if (pc1 && pc2) + { + if (CaseInsensitive) + { + while (Length--) + { + if (RtlUpperChar (*pc1++) != RtlUpperChar (*pc2++)) + return FALSE; + } + } + else + { + while (Length--) + { + if (*pc1++ != *pc2++) + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + + +BOOLEAN +STDCALL +RtlPrefixUnicodeString ( + PUNICODE_STRING String1, + PUNICODE_STRING String2, + BOOLEAN CaseInsensitive + ) +{ + PWCHAR pc1; + PWCHAR pc2; + ULONG Length; + + if (String2->Length < String1->Length) + return FALSE; + + Length = String1->Length / 2; + pc1 = String1->Buffer; + pc2 = String2->Buffer; + + if (pc1 && pc2) + { + if (CaseInsensitive) + { + while (Length--) + { + if (RtlUpcaseUnicodeChar (*pc1++) + != RtlUpcaseUnicodeChar (*pc2++)) + return FALSE; + } + } + else + { + while (Length--) + { + if( *pc1++ != *pc2++ ) + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + + +ULONG +STDCALL +RtlUnicodeStringToAnsiSize ( + IN PUNICODE_STRING UnicodeString + ) +{ + ULONG Size; + + RtlUnicodeToMultiByteSize (&Size, + UnicodeString->Buffer, + UnicodeString->Length); + + return Size+1; //NB: incl. nullterm +} + + +NTSTATUS +STDCALL +RtlUnicodeStringToAnsiString ( + IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString); + else + Length = SourceString->Length / sizeof(WCHAR); + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(CHAR); + DestinationString->Buffer = + RtlAllocateHeap (RtlGetProcessHeap (), + 0, + DestinationString->MaximumLength); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length >= DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlUnicodeToMultiByteN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString == TRUE) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Length] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUnicodeStringToInteger ( + IN PUNICODE_STRING String, + IN ULONG Base, + OUT PULONG Value + ) +{ + PWCHAR Str; + ULONG lenmin = 0; + ULONG i; + ULONG Val; + BOOLEAN addneg = FALSE; + + *Value = 0; + Str = String->Buffer; + + for (i = 0; i < String->Length / sizeof(WCHAR); i++) + { + if (*Str == L'b') + { + Base = 2; + lenmin++; + } + else if (*Str == L'o') + { + Base = 8; + lenmin++; + } + else if (*Str == L'd') + { + Base = 10; + lenmin++; + } + else if (*Str == L'x') + { + Base = 16; + lenmin++; + } + else if (*Str == L'+') + { + lenmin++; + } + else if (*Str == L'-') + { + addneg = TRUE; + lenmin++; + } + else if ((*Str > L'1') && (Base == 2)) + { + return STATUS_INVALID_PARAMETER; + } + else if (((*Str > L'7') || (*Str < L'0')) && (Base == 8)) + { + return STATUS_INVALID_PARAMETER; + } + else if (((*Str > L'9') || (*Str < L'0')) && (Base == 10)) + { + return STATUS_INVALID_PARAMETER; + } + else if ((((*Str > L'9') || (*Str < L'0')) || + ((towupper (*Str) > L'F') || + (towupper (*Str) < L'A'))) && (Base == 16)) + { + return STATUS_INVALID_PARAMETER; + } + else + Str++; + } + + Str = String->Buffer + lenmin; + + if (Base == 0) + Base = 10; + + while (iswxdigit (*Str) && + (Val = iswdigit (*Str) ? *Str - L'0' : (iswlower (*Str) + ? toupper (*Str) : *Str) - L'A' + 10) < Base) + { + *Value = *Value * Base + Val; + Str++; + } + + if (addneg == TRUE) + *Value *= -1; + + return STATUS_SUCCESS; +} + + +ULONG +STDCALL +RtlUnicodeStringToOemSize ( + IN PUNICODE_STRING UnicodeString + ) +{ + ULONG Size; + + RtlUnicodeToMultiByteSize (&Size, + UnicodeString->Buffer, + UnicodeString->Length); + + return Size+1; //NB: incl. nullterm +} + + +NTSTATUS +STDCALL +RtlUnicodeStringToCountedOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbOemCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return STATUS_INVALID_PARAMETER_2; + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString) + { + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + + RtlZeroMemory (DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (DestinationString->MaximumLength == 0) + return STATUS_BUFFER_OVERFLOW; + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUnicodeToOemN (DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Size] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUnicodeStringToOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbOemCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return STATUS_INVALID_PARAMETER_2; + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString) + { + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + + RtlZeroMemory (DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (DestinationString->MaximumLength == 0) + return STATUS_BUFFER_OVERFLOW; + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUnicodeToOemN (DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Size] = 0; + + return STATUS_SUCCESS; +} + + +WCHAR +STDCALL +RtlUpcaseUnicodeChar ( + IN WCHAR Source + ) +{ + if (Source < L'a') + return Source; + + if (Source <= L'z') + return (Source - (L'a' - L'A')); + + /* FIXME: characters above 'z' */ + + return Source; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeString ( + IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + ULONG i; + PWCHAR Src, Dest; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength=SourceString->Length+sizeof(WCHAR); + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + SourceString->Length + sizeof(WCHAR)); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (SourceString->Length >= DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = SourceString->Length; + + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + for (i = 0; i < SourceString->Length / sizeof(WCHAR); i++) + { + *Dest = RtlUpcaseUnicodeChar (*Src); + Dest++; + Src++; + } + *Dest = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeStringToAnsiString ( + IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return STATUS_INVALID_PARAMETER_2; + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString == TRUE) + { + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + DestinationString->MaximumLength); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + + RtlZeroMemory (DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (!DestinationString->MaximumLength) + return STATUS_BUFFER_OVERFLOW; + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUpcaseUnicodeToMultiByteN (DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Size] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeStringToCountedOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return STATUS_INVALID_PARAMETER_2; + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString == TRUE) + { + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + + RtlZeroMemory (DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (DestinationString->MaximumLength == 0) + return STATUS_BUFFER_OVERFLOW; + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUpcaseUnicodeToOemN (DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Size] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +RtlUpcaseUnicodeStringToOemString ( + IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString + ) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbOemCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return STATUS_INVALID_PARAMETER_2; + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString == TRUE) + { + DestinationString->Buffer = RtlAllocateHeap (RtlGetProcessHeap (), + 0, + Length); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + + RtlZeroMemory (DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (DestinationString->MaximumLength == 0) + return STATUS_BUFFER_OVERFLOW; + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUpcaseUnicodeToOemN (DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + { + RtlFreeHeap (RtlGetProcessHeap (), + 0, + DestinationString->Buffer); + } + return Status; + } + + DestinationString->Buffer[Size] = 0; + + return STATUS_SUCCESS; +} + + +CHAR +STDCALL +RtlUpperChar ( + IN CHAR Source + ) +{ + WCHAR Unicode; + CHAR Destination; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + /* ansi->unicode */ + Unicode = (WCHAR)Source; +#if 0 + Unicode = NlsAnsiToUnicodeData[Source]; +#endif + + /* upcase conversion */ + Unicode = RtlUpcaseUnicodeChar (Unicode); + + /* unicode -> ansi */ + Destination = (CHAR)Unicode; +#if 0 + Destination = NlsUnicodeToAnsiData[Unicode]; +#endif + } + else + { + /* single-byte code page */ + /* FIXME: implement the multi-byte stuff!! */ + Destination = Source; + } + + return Destination; +} + + +VOID +STDCALL +RtlUpperString ( + IN OUT PSTRING DestinationString, + IN PSTRING SourceString + ) +{ + ULONG Length; + ULONG i; + PCHAR Src; + PCHAR Dest; + + Length = min(SourceString->Length, DestinationString->MaximumLength - 1); + + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + for (i = 0; i < Length; i++) + { + *Dest = RtlUpperChar (*Src); + Src++; + Dest++; + } + *Dest = 0; + + DestinationString->Length = SourceString->Length; +} + + +ULONG +STDCALL +RtlxAnsiStringToUnicodeSize ( + IN PANSI_STRING AnsiString + ) +{ + return RtlAnsiStringToUnicodeSize (AnsiString); +} + + +ULONG +STDCALL +RtlxOemStringToUnicodeSize ( + IN POEM_STRING OemString + ) +{ + return RtlAnsiStringToUnicodeSize ((PANSI_STRING)OemString); +} + + +ULONG +STDCALL +RtlxUnicodeStringToAnsiSize ( + IN PUNICODE_STRING UnicodeString + ) +{ + return RtlUnicodeStringToAnsiSize (UnicodeString); +} + + +ULONG +STDCALL +RtlxUnicodeStringToOemSize ( + IN PUNICODE_STRING UnicodeString + ) +{ + return RtlUnicodeStringToAnsiSize (UnicodeString); +} + +/* EOF */ diff --git a/lib/ntdll/stdio/.cvsignore b/lib/ntdll/stdio/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/stdio/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/stdio/sprintf.c b/lib/ntdll/stdio/sprintf.c new file mode 100644 index 0000000..fc7ea45 --- /dev/null +++ b/lib/ntdll/stdio/sprintf.c @@ -0,0 +1,539 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/stdio/sprintf.c + * PURPOSE: Single byte sprintf functions + * PROGRAMMERS: David Welch + * Eric Kohl + * + */ + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ +__res; }) + + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + + +static char * +number(char * buf, char * end, long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits; + const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = '0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = '0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = '0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +static char* +string(char* buf, char* end, const char* s, int len, int field_width, int precision, int flags) +{ + int i; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (s[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = *s++; + ++buf; + } + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +static char* +stringw(char* buf, char* end, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (sw[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = (unsigned char)(*sw++); + ++buf; + } + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +int _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char *str, *end; + const char *s; + const wchar_t *sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */ + + str = buf; + end = buf + cnt - 1; + if (end < buf - 1) { + end = ((void *) -1); + cnt = end - buf + 1; + } + + for ( ; *fmt ; ++fmt) { + if (*fmt != '%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + if (qualifier == 'l' || qualifier == 'w') { + if (str <= end) + *str = (unsigned char)(wchar_t) va_arg(args, int); + ++str; + } else { + if (str <= end) + *str = (unsigned char) va_arg(args, int); + ++str; + } + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 'C': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + if (qualifier == 'h') { + if (str <= end) + *str = (unsigned char) va_arg(args, int); + ++str; + } else { + if (str <= end) + *str = (unsigned char)(wchar_t) va_arg(args, int); + ++str; + } + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 's': /* finished */ + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } + continue; + + case 'Z': + if (qualifier == 'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + len = pus->Length / sizeof(WCHAR); + } + str = stringw(str, end, sw, len, field_width, precision, flags); + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + s = NULL; + len = -1; + } else { + s = pus->Buffer; + len = pus->Length; + } + str = string(str, end, s, len, field_width, precision, flags); + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2 * sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case 'n': + /* FIXME: What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') { + if (str <= end) + *str = '%'; + ++str; + } + if (*fmt) { + if (str <= end) + *str = *fmt; + ++str; + } else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + str = number(str, end, num, base, field_width, precision, flags); + } + if (str <= end) + *str = '\0'; + else if (cnt > 0) + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + return str-buf; +} + + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnprintf(buf,INT_MAX,fmt,args); + va_end(args); + return i; +} + + +int _snprintf(char * buf, size_t cnt, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnprintf(buf,cnt,fmt,args); + va_end(args); + return i; +} + + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return _vsnprintf(buf,INT_MAX,fmt,args); +} + +/* EOF */ diff --git a/lib/ntdll/stdio/swprintf.c b/lib/ntdll/stdio/swprintf.c new file mode 100644 index 0000000..a05ac07 --- /dev/null +++ b/lib/ntdll/stdio/swprintf.c @@ -0,0 +1,542 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/stdio/swprintf.c + * PURPOSE: unicode sprintf functions + * PROGRAMMERS: David Welch + * Eric Kohl + * + * TODO: + * - Verify the implementation of '%Z'. + */ + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ +__res; }) + + +static int skip_atoi(const wchar_t **s) +{ + int i=0; + + while (iswdigit(**s)) + i = i*10 + *((*s)++) - L'0'; + return i; +} + + +static wchar_t * +number(wchar_t * buf, wchar_t * end, long long num, int base, int size, int precision, int type) +{ + wchar_t c, sign, tmp[66]; + const wchar_t *digits; + const wchar_t small_digits[] = L"0123456789abcdefghijklmnopqrstuvwxyz"; + const wchar_t large_digits[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++] = L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = L' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = L'0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = L'0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = L'0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = L' '; + ++buf; + } + return buf; +} + +static wchar_t* +string(wchar_t* buf, wchar_t* end, const char* s, int len, int field_width, int precision, int flags) +{ + int i; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (s[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + ++buf; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = *s++; + ++buf; + } + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + ++buf; + } + return buf; +} + +static wchar_t* +stringw(wchar_t* buf, wchar_t* end, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (sw[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + buf++; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = *sw++; + buf++; + } + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + buf++; + } + return buf; +} + + +int _vsnwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + wchar_t * str, * end; + const char *s; + const wchar_t *sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */ + + str = buf; + end = buf + cnt - 1; + if (end < buf - 1) { + end = ((void *) -1); + cnt = end - buf + 1; + } + + for ( ; *fmt ; ++fmt) { + if (*fmt != L'%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case L'-': flags |= LEFT; goto repeat; + case L'+': flags |= PLUS; goto repeat; + case L' ': flags |= SPACE; goto repeat; + case L'#': flags |= SPECIAL; goto repeat; + case L'0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (iswdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == L'.') { + ++fmt; + if (iswdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case L'c': + if (!(flags & LEFT)) + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + if (qualifier == 'h') { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } else { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + continue; + + case L'C': + if (!(flags & LEFT)) + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + if (qualifier == 'l' || qualifier == 'w') { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } else { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + continue; + + case L's': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } + continue; + + case L'S': + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } + continue; + + case L'Z': + if (qualifier == 'h') { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + s = NULL; + len = -1; + } else { + s = pus->Buffer; + len = pus->Length; + } + str = string(str, end, s, len, field_width, precision, flags); + } else { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + len = pus->Length / sizeof(WCHAR); + } + str = stringw(str, end, sw, len, field_width, precision, flags); + } + continue; + + case L'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case L'n': + /* FIXME: What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + /* integer number formats - set up the flags and "break" */ + case L'o': + base = 8; + break; + + case L'b': + base = 2; + break; + + case L'X': + flags |= LARGE; + case L'x': + base = 16; + break; + + case L'd': + case L'i': + flags |= SIGN; + case L'u': + break; + + default: + if (*fmt != L'%') { + if (str <= end) + *str = L'%'; + ++str; + } + if (*fmt) { + if (str <= end) + *str = *fmt; + ++str; + } else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + str = number(str, end, num, base, field_width, precision, flags); + } + if (str <= end) + *str = L'\0'; + else if (cnt > 0) + /* don't write out a null byte if the buf size is zero */ + *end = L'\0'; + return str-buf; +} + + +int swprintf(wchar_t *buf, const wchar_t *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnwprintf(buf,INT_MAX,fmt,args); + va_end(args); + return i; +} + + +int _snwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnwprintf(buf,cnt,fmt,args); + va_end(args); + return i; +} + + +int vswprintf(wchar_t *buf, const wchar_t *fmt, va_list args) +{ + return _vsnwprintf(buf,INT_MAX,fmt,args); +} + +/* EOF */ diff --git a/lib/ntdll/stdlib/.cvsignore b/lib/ntdll/stdlib/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/stdlib/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/stdlib/abs.c b/lib/ntdll/stdlib/abs.c new file mode 100644 index 0000000..2863888 --- /dev/null +++ b/lib/ntdll/stdlib/abs.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +abs(int j) +{ + return j<0 ? -j : j; +} diff --git a/lib/ntdll/stdlib/atoi.c b/lib/ntdll/stdlib/atoi.c new file mode 100644 index 0000000..ba4e2df --- /dev/null +++ b/lib/ntdll/stdlib/atoi.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +atoi(const char *str) +{ + return (int)strtol(str, 0, 10); +} diff --git a/lib/ntdll/stdlib/atoi64.c b/lib/ntdll/stdlib/atoi64.c new file mode 100644 index 0000000..2c6de7d --- /dev/null +++ b/lib/ntdll/stdlib/atoi64.c @@ -0,0 +1,41 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/stdlib/atoi64.c + * PURPOSE: converts an ascii string to 64 bit integer + */ + +#include +#include + +__int64 +_atoi64 (const char *nptr) +{ + int c; + __int64 value; + int sign; + + while (isspace((int)*nptr)) + ++nptr; + + c = (int)*nptr++; + sign = c; + if (c == '-' || c == '+') + c = (int)*nptr++; + + value = 0; + + while (isdigit(c)) + { + value = 10 * value + (c - '0'); + c = (int)*nptr++; + } + + if (sign == '-') + return -value; + else + return value; +} + +/* EOF */ diff --git a/lib/ntdll/stdlib/atol.c b/lib/ntdll/stdlib/atol.c new file mode 100644 index 0000000..2680abd --- /dev/null +++ b/lib/ntdll/stdlib/atol.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +atol(const char *str) +{ + return strtol(str, 0, 10); +} diff --git a/lib/ntdll/stdlib/itoa.c b/lib/ntdll/stdlib/itoa.c new file mode 100644 index 0000000..c4185e9 --- /dev/null +++ b/lib/ntdll/stdlib/itoa.c @@ -0,0 +1,163 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/stdlib/itoa.c + * PURPOSE: converts an integer to ascii + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +_i64toa(__int64 value, char *string, int radix) +{ + char tmp[65]; + char *tp = tmp; + __int64 i; + unsigned __int64 v; + __int64 sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned __int64)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +char * +_itoa(int value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +char * +_ltoa(long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned long)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +char * +_ultoa(unsigned long value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} diff --git a/lib/ntdll/stdlib/itow.c b/lib/ntdll/stdlib/itow.c new file mode 100644 index 0000000..47537b6 --- /dev/null +++ b/lib/ntdll/stdlib/itow.c @@ -0,0 +1,163 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/ntdll/stdlib/itow.c + * PURPOSE: converts an integer to Unicode + * PROGRAMER: + * UPDATE HISTORY: + * 1995: Created + * 1998: Added ltoa Boudewijn Dekker + */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +wchar_t * +_i64tow(__int64 value, wchar_t *string, int radix) +{ + wchar_t tmp[65]; + wchar_t *tp = tmp; + __int64 i; + unsigned __int64 v; + __int64 sign; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned __int64)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + sp = string; + if (sign) + *sp++ = L'-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +wchar_t * +_itow(int value, wchar_t *string, int radix) +{ + wchar_t tmp[33]; + wchar_t *tp = tmp; + int i; + unsigned v; + int sign; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + sp = string; + if (sign) + *sp++ = L'-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +wchar_t * +_ltow(long value, wchar_t *string, int radix) +{ + wchar_t tmp[33]; + wchar_t *tp = tmp; + long i; + unsigned long v; + int sign; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned long)value; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + sp = string; + if (sign) + *sp++ = L'-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} + + +wchar_t * +_ultow(unsigned long value, wchar_t *string, int radix) +{ + wchar_t tmp[33]; + wchar_t *tp = tmp; + long i; + unsigned long v = value; + wchar_t *sp; + + if (radix > 36 || radix <= 1) + { + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+L'0'; + else + *tp++ = i + L'a' - 10; + } + + sp = string; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + return string; +} diff --git a/lib/ntdll/stdlib/labs.c b/lib/ntdll/stdlib/labs.c new file mode 100644 index 0000000..eb2fb71 --- /dev/null +++ b/lib/ntdll/stdlib/labs.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +labs(long j) +{ + return j<0 ? -j : j; +} diff --git a/lib/ntdll/stdlib/mbstowcs.c b/lib/ntdll/stdlib/mbstowcs.c new file mode 100644 index 0000000..e4dbf1a --- /dev/null +++ b/lib/ntdll/stdlib/mbstowcs.c @@ -0,0 +1,41 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/stdlib/mbstowcs.c + * PURPOSE: converts a multi byte string to a unicode string + */ + +#include +#include +#include + +size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count) +{ + NTSTATUS Status; + ULONG Size; + ULONG Length; + + Length = strlen (mbstr); + + if (wcstr == NULL) + { + RtlMultiByteToUnicodeSize (&Size, + (char *)mbstr, + Length); + + return (size_t)Size; + } + + Status = RtlMultiByteToUnicodeN (wcstr, + count, + &Size, + (char *)mbstr, + Length); + if (!NT_SUCCESS(Status)) + return -1; + + return (size_t)Size; +} + +/* EOF */ diff --git a/lib/ntdll/stdlib/qsort.c b/lib/ntdll/stdlib/qsort.c new file mode 100644 index 0000000..84a59b6 --- /dev/null +++ b/lib/ntdll/stdlib/qsort.c @@ -0,0 +1,266 @@ +/* $Id$ + * + * FILE: lib/ntdll/stdlib/qsort.c + * NOTE: Adapted from CygWin newlib 2000-03-12. + */ +/* +FUNCTION +<>---sort an array + +INDEX + qsort + +ANSI_SYNOPSIS + #include + void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>, + int (*<[compar]>)(const void *, const void *) ); + +TRAD_SYNOPSIS + #include + qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> ) + char *<[base]>; + size_t <[nmemb]>; + size_t <[size]>; + int (*<[compar]>)(); + +DESCRIPTION +<> sorts an array (beginning at <[base]>) of <[nmemb]> objects. +<[size]> describes the size of each element of the array. + +You must supply a pointer to a comparison function, using the argument +shown as <[compar]>. (This permits sorting objects of unknown +properties.) Define the comparison function to accept two arguments, +each a pointer to an element of the array starting at <[base]>. The +result of <<(*<[compar]>)>> must be negative if the first argument is +less than the second, zero if the two arguments match, and positive if +the first argument is greater than the second (where ``less than'' and +``greater than'' refer to whatever arbitrary ordering is appropriate). + +The array is sorted in place; that is, when <> returns, the +array elements beginning at <[base]> have been reordered. + +RETURNS +<> does not return a result. + +PORTABILITY +<> is required by ANSI (without specifying the sorting algorithm). +*/ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __GNUC__ +#define inline +#endif + +/* FIXME: these types should be from the default includes */ + +typedef int (* _pfunccmp_t) (char *, char *); +typedef int size_t; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *) (parmi); \ + register TYPE *pj = (TYPE *) (parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc ( + char * a, + char * b, + int n, + int swaptype + ) +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +static inline char * +med3 ( + char * a, + char * b, + char * c, + _pfunccmp_t cmp + ) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} + + +/* EXPORTED */ +void +qsort ( + void * a, + size_t n, + size_t es, + _pfunccmp_t cmp + ) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + pm = (char *) a + (n / 2) * es; + if (n > 7) + { + pl = (char *) a; + pn = (char *) a + (n - 1) * es; + if (n > 40) + { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *) a + es; + + pc = pd = (char *) a + (n - 1) * es; + for (;;) + { + while (pb <= pc && (r = cmp(pb, a)) <= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + { + break; + } + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) /* Switch to insertion sort */ + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + + pn = (char *) a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) + { + qsort(a, r / es, es, cmp); + } + if ((r = pd - pc) > es) + { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} + + +/* EOF */ diff --git a/lib/ntdll/stdlib/splitp.c b/lib/ntdll/stdlib/splitp.c new file mode 100644 index 0000000..8dbe18b --- /dev/null +++ b/lib/ntdll/stdlib/splitp.c @@ -0,0 +1,42 @@ +#include +#include + +void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext ) +{ + char *tmp_drive; + char *tmp_dir; + char *tmp_ext; + + tmp_drive = (char *)strchr(path,':'); + if ( tmp_drive != (char *)NULL ) { + strncpy(drive,tmp_drive-1,1); + *(drive+1) = 0; + } + else { + *drive = 0; + tmp_drive = (char *)path; + } + + tmp_dir = (char *)strrchr(path,'\\'); + if( tmp_dir != NULL && tmp_dir != tmp_drive + 1 ) { + strncpy(dir,tmp_drive+1,tmp_dir - tmp_drive); + *(dir + (tmp_dir - tmp_drive)) = 0; + } + else + *dir =0; + + tmp_ext = ( char *)strrchr(path,'.'); + if ( tmp_ext != NULL ) { + strcpy(ext,tmp_ext); + } + else + *ext = 0; + if ( tmp_dir != NULL ) { + strncpy(fname,tmp_dir+1,tmp_ext - tmp_dir - 1); + *(fname + (tmp_ext - tmp_dir -1)) = 0; + } + else + strncpy(fname,path,tmp_ext - path); + +} + diff --git a/lib/ntdll/stdlib/strtol.c b/lib/ntdll/stdlib/strtol.c new file mode 100644 index 0000000..f9486ca --- /dev/null +++ b/lib/ntdll/stdlib/strtol.c @@ -0,0 +1,89 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +long +strtol(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/ntdll/stdlib/strtoul.c b/lib/ntdll/stdlib/strtoul.c new file mode 100644 index 0000000..f6d0f06 --- /dev/null +++ b/lib/ntdll/stdlib/strtoul.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} diff --git a/lib/ntdll/stdlib/wcstol.c b/lib/ntdll/stdlib/wcstol.c new file mode 100644 index 0000000..fbddb1a --- /dev/null +++ b/lib/ntdll/stdlib/wcstol.c @@ -0,0 +1,89 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +long +wcstol(const wchar_t *nptr, wchar_t **endptr, int base) +{ + const wchar_t *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (iswctype(c, _SPACE)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (iswctype(c, _DIGIT)) + c -= L'0'; + else if (iswctype(c, _ALPHA)) + c -= iswctype(c, _UPPER) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (wchar_t *)s - 1 : (wchar_t *)nptr; + return acc; +} diff --git a/lib/ntdll/stdlib/wcstombs.c b/lib/ntdll/stdlib/wcstombs.c new file mode 100644 index 0000000..4712d1d --- /dev/null +++ b/lib/ntdll/stdlib/wcstombs.c @@ -0,0 +1,41 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/stdlib/wcstombs.c + * PURPOSE: converts a unicode string to a multi byte string + */ + +#include +#include +#include + +size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count) +{ + NTSTATUS Status; + ULONG Size; + ULONG Length; + + Length = wcslen (wcstr); + + if (mbstr == NULL) + { + RtlUnicodeToMultiByteSize (&Size, + (wchar_t *)wcstr, + Length * sizeof(WCHAR)); + + return (size_t)Size; + } + + Status = RtlUnicodeToMultiByteN (mbstr, + count, + &Size, + (wchar_t *)wcstr, + Length * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + return -1; + + return (size_t)Size; +} + +/* EOF */ diff --git a/lib/ntdll/stdlib/wcstoul.c b/lib/ntdll/stdlib/wcstoul.c new file mode 100644 index 0000000..835e681 --- /dev/null +++ b/lib/ntdll/stdlib/wcstoul.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include + + +/* + * Convert a unicode string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +wcstoul(const wchar_t *nptr, wchar_t **endptr, int base) +{ + const wchar_t *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (iswctype(c, _SPACE)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == L'+') + c = *s++; + if ((base == 0 || base == 16) && + c == L'0' && (*s == L'x' || *s == L'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == L'0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (iswctype(c, _DIGIT)) + c -= L'0'; + else if (iswctype(c, _ALPHA)) + c -= iswctype(c, _UPPER) ? L'A' - 10 : L'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (wchar_t *)s - 1 : (wchar_t *)nptr; + return acc; +} diff --git a/lib/ntdll/stdlib/wtoi.c b/lib/ntdll/stdlib/wtoi.c new file mode 100644 index 0000000..fcf3d18 --- /dev/null +++ b/lib/ntdll/stdlib/wtoi.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +_wtoi(const wchar_t *str) +{ + return (int)wcstol(str, 0, 10); +} diff --git a/lib/ntdll/stdlib/wtoi64.c b/lib/ntdll/stdlib/wtoi64.c new file mode 100644 index 0000000..81f2068 --- /dev/null +++ b/lib/ntdll/stdlib/wtoi64.c @@ -0,0 +1,41 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/stdlib/wtoi64.c + * PURPOSE: converts a unicode string to 64 bit integer + */ + +#include +#include + +__int64 +_wtoi64 (const wchar_t *nptr) +{ + int c; + __int64 value; + int sign; + + while (iswctype((int)*nptr, _SPACE)) + ++nptr; + + c = (int)*nptr++; + sign = c; + if (c == L'-' || c == L'+') + c = (int)*nptr++; + + value = 0; + + while (iswctype(c, _DIGIT)) + { + value = 10 * value + (c - L'0'); + c = (int)*nptr++; + } + + if (sign == L'-') + return -value; + else + return value; +} + +/* EOF */ diff --git a/lib/ntdll/stdlib/wtol.c b/lib/ntdll/stdlib/wtol.c new file mode 100644 index 0000000..a74ce32 --- /dev/null +++ b/lib/ntdll/stdlib/wtol.c @@ -0,0 +1,8 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +long +_wtol(const wchar_t *str) +{ + return wcstol(str, 0, 10); +} diff --git a/lib/ntdll/string/.cvsignore b/lib/ntdll/string/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/string/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/string/ctype.c b/lib/ntdll/string/ctype.c new file mode 100644 index 0000000..21d58cd --- /dev/null +++ b/lib/ntdll/string/ctype.c @@ -0,0 +1,433 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/rtl/ctype.c + * PURPOSE: Character type and conversion functions + * PROGRAMMERS: ??? + * Eric Kohl + * HISTORY: ???: Created + * 29/12/1999: Added missing functions and changed + * all functions to use ctype table + */ +#undef __MSVCRT__ +#include + +#undef _pctype + +#define upalpha ('A' - 'a') + + +unsigned short _ctype[] = { + 0, /* , 0xFFFF */ + _CONTROL, /* CTRL+@, 0x00 */ + _CONTROL, /* CTRL+A, 0x01 */ + _CONTROL, /* CTRL+B, 0x02 */ + _CONTROL, /* CTRL+C, 0x03 */ + _CONTROL, /* CTRL+D, 0x04 */ + _CONTROL, /* CTRL+E, 0x05 */ + _CONTROL, /* CTRL+F, 0x06 */ + _CONTROL, /* CTRL+G, 0x07 */ + _CONTROL, /* CTRL+H, 0x08 */ + _CONTROL | _SPACE, /* CTRL+I, 0x09 */ + _CONTROL | _SPACE, /* CTRL+J, 0x0a */ + _CONTROL | _SPACE, /* CTRL+K, 0x0b */ + _CONTROL | _SPACE, /* CTRL+L, 0x0c */ + _CONTROL | _SPACE, /* CTRL+M, 0x0d */ + _CONTROL, /* CTRL+N, 0x0e */ + _CONTROL, /* CTRL+O, 0x0f */ + _CONTROL, /* CTRL+P, 0x10 */ + _CONTROL, /* CTRL+Q, 0x11 */ + _CONTROL, /* CTRL+R, 0x12 */ + _CONTROL, /* CTRL+S, 0x13 */ + _CONTROL, /* CTRL+T, 0x14 */ + _CONTROL, /* CTRL+U, 0x15 */ + _CONTROL, /* CTRL+V, 0x16 */ + _CONTROL, /* CTRL+W, 0x17 */ + _CONTROL, /* CTRL+X, 0x18 */ + _CONTROL, /* CTRL+Y, 0x19 */ + _CONTROL, /* CTRL+Z, 0x1a */ + _CONTROL, /* CTRL+[, 0x1b */ + _CONTROL, /* CTRL+\, 0x1c */ + _CONTROL, /* CTRL+], 0x1d */ + _CONTROL, /* CTRL+^, 0x1e */ + _CONTROL, /* CTRL+_, 0x1f */ + _SPACE | _BLANK, /* ` ', 0x20 */ + _PUNCT, /* `!', 0x21 */ + _PUNCT, /* 0x22 */ + _PUNCT, /* `#', 0x23 */ + _PUNCT, /* `$', 0x24 */ + _PUNCT, /* `%', 0x25 */ + _PUNCT, /* `&', 0x26 */ + _PUNCT, /* 0x27 */ + _PUNCT, /* `(', 0x28 */ + _PUNCT, /* `)', 0x29 */ + _PUNCT, /* `*', 0x2a */ + _PUNCT, /* `+', 0x2b */ + _PUNCT, /* `,', 0x2c */ + _PUNCT, /* `-', 0x2d */ + _PUNCT, /* `.', 0x2e */ + _PUNCT, /* `/', 0x2f */ + _DIGIT | _HEX, /* `0', 0x30 */ + _DIGIT | _HEX, /* `1', 0x31 */ + _DIGIT | _HEX, /* `2', 0x32 */ + _DIGIT | _HEX, /* `3', 0x33 */ + _DIGIT | _HEX, /* `4', 0x34 */ + _DIGIT | _HEX, /* `5', 0x35 */ + _DIGIT | _HEX, /* `6', 0x36 */ + _DIGIT | _HEX, /* `7', 0x37 */ + _DIGIT | _HEX, /* `8', 0x38 */ + _DIGIT | _HEX, /* `9', 0x39 */ + _PUNCT, /* `:', 0x3a */ + _PUNCT, /* `;', 0x3b */ + _PUNCT, /* `<', 0x3c */ + _PUNCT, /* `=', 0x3d */ + _PUNCT, /* `>', 0x3e */ + _PUNCT, /* `?', 0x3f */ + _PUNCT, /* `@', 0x40 */ + _UPPER | _HEX, /* `A', 0x41 */ + _UPPER | _HEX, /* `B', 0x42 */ + _UPPER | _HEX, /* `C', 0x43 */ + _UPPER | _HEX, /* `D', 0x44 */ + _UPPER | _HEX, /* `E', 0x45 */ + _UPPER | _HEX, /* `F', 0x46 */ + _UPPER, /* `G', 0x47 */ + _UPPER, /* `H', 0x48 */ + _UPPER, /* `I', 0x49 */ + _UPPER, /* `J', 0x4a */ + _UPPER, /* `K', 0x4b */ + _UPPER, /* `L', 0x4c */ + _UPPER, /* `M', 0x4d */ + _UPPER, /* `N', 0x4e */ + _UPPER, /* `O', 0x4f */ + _UPPER, /* `P', 0x50 */ + _UPPER, /* `Q', 0x51 */ + _UPPER, /* `R', 0x52 */ + _UPPER, /* `S', 0x53 */ + _UPPER, /* `T', 0x54 */ + _UPPER, /* `U', 0x55 */ + _UPPER, /* `V', 0x56 */ + _UPPER, /* `W', 0x57 */ + _UPPER, /* `X', 0x58 */ + _UPPER, /* `Y', 0x59 */ + _UPPER, /* `Z', 0x5a */ + _PUNCT, /* `[', 0x5b */ + _PUNCT, /* 0x5c */ + _PUNCT, /* `]', 0x5d */ + _PUNCT, /* `^', 0x5e */ + _PUNCT, /* `_', 0x5f */ + _PUNCT, /* 0x60 */ + _LOWER | _HEX, /* `a', 0x61 */ + _LOWER | _HEX, /* `b', 0x62 */ + _LOWER | _HEX, /* `c', 0x63 */ + _LOWER | _HEX, /* `d', 0x64 */ + _LOWER | _HEX, /* `e', 0x65 */ + _LOWER | _HEX, /* `f', 0x66 */ + _LOWER, /* `g', 0x67 */ + _LOWER, /* `h', 0x68 */ + _LOWER, /* `i', 0x69 */ + _LOWER, /* `j', 0x6a */ + _LOWER, /* `k', 0x6b */ + _LOWER, /* `l', 0x6c */ + _LOWER, /* `m', 0x6d */ + _LOWER, /* `n', 0x6e */ + _LOWER, /* `o', 0x6f */ + _LOWER, /* `p', 0x70 */ + _LOWER, /* `q', 0x71 */ + _LOWER, /* `r', 0x72 */ + _LOWER, /* `s', 0x73 */ + _LOWER, /* `t', 0x74 */ + _LOWER, /* `u', 0x75 */ + _LOWER, /* `v', 0x76 */ + _LOWER, /* `w', 0x77 */ + _LOWER, /* `x', 0x78 */ + _LOWER, /* `y', 0x79 */ + _LOWER, /* `z', 0x7a */ + _PUNCT, /* `{', 0x7b */ + _PUNCT, /* `|', 0x7c */ + _PUNCT, /* `}', 0x7d */ + _PUNCT, /* `~', 0x7e */ + _CONTROL, /* 0x7f */ + 0, /* 0x80 */ + 0, /* 0x81 */ + 0, /* 0x82 */ + 0, /* 0x83 */ + 0, /* 0x84 */ + 0, /* 0x85 */ + 0, /* 0x86 */ + 0, /* 0x87 */ + 0, /* 0x88 */ + 0, /* 0x89 */ + 0, /* 0x8a */ + 0, /* 0x8b */ + 0, /* 0x8c */ + 0, /* 0x8d */ + 0, /* 0x8e */ + 0, /* 0x8f */ + 0, /* 0x90 */ + 0, /* 0x91 */ + 0, /* 0x92 */ + 0, /* 0x93 */ + 0, /* 0x94 */ + 0, /* 0x95 */ + 0, /* 0x96 */ + 0, /* 0x97 */ + 0, /* 0x98 */ + 0, /* 0x99 */ + 0, /* 0x9a */ + 0, /* 0x9b */ + 0, /* 0x9c */ + 0, /* 0x9d */ + 0, /* 0x9e */ + 0, /* 0x9f */ + 0, /* 0xa0 */ + 0, /* 0xa1 */ + 0, /* 0xa2 */ + 0, /* 0xa3 */ + 0, /* 0xa4 */ + 0, /* 0xa5 */ + 0, /* 0xa6 */ + 0, /* 0xa7 */ + 0, /* 0xa8 */ + 0, /* 0xa9 */ + 0, /* 0xaa */ + 0, /* 0xab */ + 0, /* 0xac */ + 0, /* 0xad */ + 0, /* 0xae */ + 0, /* 0xaf */ + 0, /* 0xb0 */ + 0, /* 0xb1 */ + 0, /* 0xb2 */ + 0, /* 0xb3 */ + 0, /* 0xb4 */ + 0, /* 0xb5 */ + 0, /* 0xb6 */ + 0, /* 0xb7 */ + 0, /* 0xb8 */ + 0, /* 0xb9 */ + 0, /* 0xba */ + 0, /* 0xbb */ + 0, /* 0xbc */ + 0, /* 0xbd */ + 0, /* 0xbe */ + 0, /* 0xbf */ + 0, /* 0xc0 */ + 0, /* 0xc1 */ + 0, /* 0xc2 */ + 0, /* 0xc3 */ + 0, /* 0xc4 */ + 0, /* 0xc5 */ + 0, /* 0xc6 */ + 0, /* 0xc7 */ + 0, /* 0xc8 */ + 0, /* 0xc9 */ + 0, /* 0xca */ + 0, /* 0xcb */ + 0, /* 0xcc */ + 0, /* 0xcd */ + 0, /* 0xce */ + 0, /* 0xcf */ + 0, /* 0xd0 */ + 0, /* 0xd1 */ + 0, /* 0xd2 */ + 0, /* 0xd3 */ + 0, /* 0xd4 */ + 0, /* 0xd5 */ + 0, /* 0xd6 */ + 0, /* 0xd7 */ + 0, /* 0xd8 */ + 0, /* 0xd9 */ + 0, /* 0xda */ + 0, /* 0xdb */ + 0, /* 0xdc */ + 0, /* 0xdd */ + 0, /* 0xde */ + 0, /* 0xdf */ + 0, /* 0xe0 */ + 0, /* 0xe1 */ + 0, /* 0xe2 */ + 0, /* 0xe3 */ + 0, /* 0xe4 */ + 0, /* 0xe5 */ + 0, /* 0xe6 */ + 0, /* 0xe7 */ + 0, /* 0xe8 */ + 0, /* 0xe9 */ + 0, /* 0xea */ + 0, /* 0xeb */ + 0, /* 0xec */ + 0, /* 0xed */ + 0, /* 0xee */ + 0, /* 0xef */ + 0, /* 0xf0 */ + 0, /* 0xf1 */ + 0, /* 0xf2 */ + 0, /* 0xf3 */ + 0, /* 0xf4 */ + 0, /* 0xf5 */ + 0, /* 0xf6 */ + 0, /* 0xf7 */ + 0, /* 0xf8 */ + 0, /* 0xf9 */ + 0, /* 0xfa */ + 0, /* 0xfb */ + 0, /* 0xfc */ + 0, /* 0xfd */ + 0, /* 0xfe */ + 0 /* 0xff */ +}; + +unsigned short *_pctype = _ctype + 1; +unsigned short *_pwctype = _ctype + 1; + +int _isctype (int c, int ctypeFlags) +{ + return (_pctype[(unsigned char)(c & 0xFF)] & ctypeFlags); +} + +int iswctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +int isalpha(int c) +{ + return(_isctype(c, _ALPHA)); +} + +int isalnum(int c) +{ + return(_isctype(c, _ALPHA | _DIGIT)); +} + +int __isascii(int c) +{ + return ((unsigned char)c <= 0x7f); +} + +int iscntrl(int c) +{ + return(_isctype(c, _CONTROL)); +} + +int __iscsym(int c) +{ + return(isalnum(c)||(c == '_')); +} + +int __iscsymf(int c) +{ + return(isalpha(c)||(c == '_')); +} + +int isdigit(int c) +{ + return(_isctype(c, _DIGIT)); +} + +int isgraph(int c) +{ + return (_isctype (c, _PUNCT | _ALPHA | _DIGIT)); +} + +int islower(int c) +{ + return (_isctype (c, _LOWER)); +} + +int isprint(int c) +{ + return (_isctype (c, _BLANK | _PUNCT | _ALPHA | _DIGIT)); +} + +int ispunct(int c) +{ + return (_isctype (c, _PUNCT)); +} + +int isspace(int c) +{ + return (_isctype (c, _SPACE)); +} + +int isupper(int c) +{ + return (_isctype (c, _UPPER)); +} + +int isxdigit(int c) +{ + return (_isctype (c, _HEX)); +} + + +int iswalpha(wint_t c) +{ + return (iswctype (c, _ALPHA)); +} + +int iswdigit(wint_t c) +{ + return (iswctype (c, _DIGIT)); +} + +int iswlower(wint_t c) +{ + return (iswctype (c, _LOWER)); +} + +int iswxdigit(wint_t c) +{ + return (iswctype (c, _HEX)); +} + + +int __toascii(int c) +{ + return((unsigned)(c) & 0x7f); +} + +int _tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int _toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +int tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +wchar_t towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +wchar_t towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +/* EOF */ diff --git a/lib/ntdll/string/memccpy.c b/lib/ntdll/string/memccpy.c new file mode 100644 index 0000000..9fe3058 --- /dev/null +++ b/lib/ntdll/string/memccpy.c @@ -0,0 +1,9 @@ +#include + + +void * +_memccpy (void *to, const void *from,int c,size_t count) +{ + memcpy(to,from,count); + return memchr(to,c,count); +} diff --git a/lib/ntdll/string/memchr.c b/lib/ntdll/string/memchr.c new file mode 100644 index 0000000..a0d57dd --- /dev/null +++ b/lib/ntdll/string/memchr.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + +#include + +void * +memchr(const void *s, int c, size_t n) +{ + if (n) + { + const char *p = s; + do { + if (*p++ == c) + return (void *)(p-1); + } while (--n != 0); + } + return 0; +} diff --git a/lib/ntdll/string/memcmp.c b/lib/ntdll/string/memcmp.c new file mode 100644 index 0000000..1c361a3 --- /dev/null +++ b/lib/ntdll/string/memcmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +memcmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (*p1++ != *p2++) + return (*--p1 - *--p2); + } while (--n != 0); + } + return 0; +} diff --git a/lib/ntdll/string/memcpy.c b/lib/ntdll/string/memcpy.c new file mode 100644 index 0000000..7d18be3 --- /dev/null +++ b/lib/ntdll/string/memcpy.c @@ -0,0 +1,16 @@ +#include + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +void * +memcpy (void *to, const void *from, size_t count) +{ + register char *f = (char *)from; + register char *t = (char *)to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; + + return to; +} diff --git a/lib/ntdll/string/memicmp.c b/lib/ntdll/string/memicmp.c new file mode 100644 index 0000000..001c1cd --- /dev/null +++ b/lib/ntdll/string/memicmp.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_memicmp(const void *s1, const void *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (toupper(*p1) != toupper(*p2)) + return (*p1 - *p2); + p1++; + p2++; + } while (--n != 0); + } + return 0; +} diff --git a/lib/ntdll/string/memmove.c b/lib/ntdll/string/memmove.c new file mode 100644 index 0000000..0a0b81f --- /dev/null +++ b/lib/ntdll/string/memmove.c @@ -0,0 +1,36 @@ +#include + +void * memmove(void *dest,const void *src,size_t count) +{ + char *char_dest = (char *)dest; + char *char_src = (char *)src; + + if ((char_dest <= char_src) || (char_dest >= (char_src+count))) + { + /* non-overlapping buffers */ + while(count > 0) + { + *char_dest = *char_src; + char_dest++; + char_src++; + count--; + } + } + else + { + /* overlaping buffers */ + char_dest = (char *)dest + count - 1; + char_src = (char *)src + count - 1; + + while(count > 0) + { + *char_dest = *char_src; + char_dest--; + char_src--; + count--; + } + } + + return dest; +} + diff --git a/lib/ntdll/string/memset.c b/lib/ntdll/string/memset.c new file mode 100644 index 0000000..b26ba92 --- /dev/null +++ b/lib/ntdll/string/memset.c @@ -0,0 +1,13 @@ +#include + +void * memset(void *src,int val,size_t count) +{ + char *char_src = (char *)src; + + while(count>0) { + *char_src = val; + char_src++; + count--; + } + return src; +} diff --git a/lib/ntdll/string/strcat.c b/lib/ntdll/string/strcat.c new file mode 100644 index 0000000..3305047 --- /dev/null +++ b/lib/ntdll/string/strcat.c @@ -0,0 +1,12 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strcat(char *s, const char *append) +{ + char *save = s; + + for (; *s; ++s); + while ((*s++ = *append++)); + return save; +} diff --git a/lib/ntdll/string/strchr.c b/lib/ntdll/string/strchr.c new file mode 100644 index 0000000..4489403 --- /dev/null +++ b/lib/ntdll/string/strchr.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ + + + +char *strchr(const char *s, int c); + +char *strchr(const char *s, int c) +{ + char cc = c; + while (*s) + { + if (*s == cc) + return (char *)s; + s++; + } + if (cc == 0) + return (char *)s; + return 0; +} + diff --git a/lib/ntdll/string/strcmp.c b/lib/ntdll/string/strcmp.c new file mode 100644 index 0000000..7b82a6e --- /dev/null +++ b/lib/ntdll/string/strcmp.c @@ -0,0 +1,15 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return *(unsigned const char *)s1 - *(unsigned const char *)(s2); +} diff --git a/lib/ntdll/string/strcpy.c b/lib/ntdll/string/strcpy.c new file mode 100644 index 0000000..cf77c54 --- /dev/null +++ b/lib/ntdll/string/strcpy.c @@ -0,0 +1,10 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +char* strcpy(char *to, const char *from); + +char* strcpy(char *to, const char *from) +{ + char *save = to; + + for (; (*to = *from); ++from, ++to); + return save; +} diff --git a/lib/ntdll/string/strcspn.c b/lib/ntdll/string/strcspn.c new file mode 100644 index 0000000..7e17b21 --- /dev/null +++ b/lib/ntdll/string/strcspn.c @@ -0,0 +1,20 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strcspn(const char *s1, const char *s2) +{ + const char *p, *spanp; + char c, sc; + + for (p = s1;;) + { + c = *p++; + spanp = s2; + do { + if ((sc = *spanp++) == c) + return p - 1 - s1; + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/lib/ntdll/string/stricmp.c b/lib/ntdll/string/stricmp.c new file mode 100644 index 0000000..913ceef --- /dev/null +++ b/lib/ntdll/string/stricmp.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +_stricmp(const char *s1, const char *s2) +{ + while (toupper(*s1) == toupper(*s2)) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); +} + +int +_strcmpi(const char *s1, const char *s2) +{ + return _stricmp(s1,s2); +} diff --git a/lib/ntdll/string/strlen.c b/lib/ntdll/string/strlen.c new file mode 100644 index 0000000..d5b8d68 --- /dev/null +++ b/lib/ntdll/string/strlen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strlen(const char *str) +{ + const char *s; + + if (str == 0) + return 0; + for (s = str; *s; ++s); + return s-str; +} + diff --git a/lib/ntdll/string/strlwr.c b/lib/ntdll/string/strlwr.c new file mode 100644 index 0000000..461429f --- /dev/null +++ b/lib/ntdll/string/strlwr.c @@ -0,0 +1,23 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + +#include +#include + +char * _strlwr(char *x) +{ + char *y=x; + + while (*y) { + *y=tolower(*y); + y++; + } + return x; +} diff --git a/lib/ntdll/string/strncat.c b/lib/ntdll/string/strncat.c new file mode 100644 index 0000000..75fc9ee --- /dev/null +++ b/lib/ntdll/string/strncat.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strncat(char *dst, const char *src, size_t n) +{ + if (n != 0) + { + char *d = dst; + const char *s = src; + + while (*d != 0) + d++; + do { + if ((*d = *s++) == 0) + break; + d++; + } while (--n != 0); + *d = 0; + } + return dst; +} diff --git a/lib/ntdll/string/strncmp.c b/lib/ntdll/string/strncmp.c new file mode 100644 index 0000000..f90eb5b --- /dev/null +++ b/lib/ntdll/string/strncmp.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return 0; + do { + if (*s1 != *s2++) + return *(unsigned const char *)s1 - *(unsigned const char *)--s2; + if (*s1++ == 0) + break; + } while (--n != 0); + return 0; +} diff --git a/lib/ntdll/string/strncpy.c b/lib/ntdll/string/strncpy.c new file mode 100644 index 0000000..fdf7bd6 --- /dev/null +++ b/lib/ntdll/string/strncpy.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +char * +strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) { + char *d = dst; + const char *s = src; + + do { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + } while (--n != 0); + } + return dst; +} diff --git a/lib/ntdll/string/strnicmp.c b/lib/ntdll/string/strnicmp.c new file mode 100644 index 0000000..40c5e20 --- /dev/null +++ b/lib/ntdll/string/strnicmp.c @@ -0,0 +1,17 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int _strnicmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return 0; + do { + if (toupper(*s1) != toupper(*s2++)) + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)--s2); + if (*s1++ == 0) + break; + } while (--n != 0); + return 0; +} diff --git a/lib/ntdll/string/strnlen.c b/lib/ntdll/string/strnlen.c new file mode 100644 index 0000000..e71c158 --- /dev/null +++ b/lib/ntdll/string/strnlen.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strnlen(const char *str, size_t count) +{ + const char *s; + + if (str == 0) + return 0; + for (s = str; *s && count; ++s, count--); + return s-str; +} + diff --git a/lib/ntdll/string/strpbrk.c b/lib/ntdll/string/strpbrk.c new file mode 100644 index 0000000..5f642c4 --- /dev/null +++ b/lib/ntdll/string/strpbrk.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + + +char * +strpbrk(const char *s1, const char *s2) +{ + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return (char *)(s1 - 1); + } + return 0; +} diff --git a/lib/ntdll/string/strrchr.c b/lib/ntdll/string/strrchr.c new file mode 100644 index 0000000..e6f3399 --- /dev/null +++ b/lib/ntdll/string/strrchr.c @@ -0,0 +1,21 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +//#include + +char * +strrchr(const char *s, int c) +{ + char cc = c; + const char *sp=(char *)0; + while (*s) + { + if (*s == cc) + sp = s; + s++; + } + if (cc == 0) + sp = s; + return (char *)sp; +} + diff --git a/lib/ntdll/string/strspn.c b/lib/ntdll/string/strspn.c new file mode 100644 index 0000000..1532db0 --- /dev/null +++ b/lib/ntdll/string/strspn.c @@ -0,0 +1,16 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strspn(const char *s1, const char *s2) +{ + const char *p = s1, *spanp; + char c, sc; + + cont: + c = *p++; + for (spanp = s2; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (p - 1 - s1); +} diff --git a/lib/ntdll/string/strstr.c b/lib/ntdll/string/strstr.c new file mode 100644 index 0000000..10095a1 --- /dev/null +++ b/lib/ntdll/string/strstr.c @@ -0,0 +1,23 @@ +/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */ +#include +//#include + +char * +strstr(const char *s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) + { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return 0; + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return (char *)s; +} diff --git a/lib/ntdll/string/strupr.c b/lib/ntdll/string/strupr.c new file mode 100644 index 0000000..1183e4c --- /dev/null +++ b/lib/ntdll/string/strupr.c @@ -0,0 +1,24 @@ +/* + * The C RunTime DLL + * + * Implements C run-time functionality as known from UNIX. + * + * Copyright 1996,1998 Marcus Meissner + * Copyright 1996 Jukka Iivonen + * Copyright 1997 Uwe Bonnes + */ + + +#include +#include + +char *_strupr(char *x) +{ + char *y=x; + + while (*y) { + *y=toupper(*y); + y++; + } + return x; +} diff --git a/lib/ntdll/string/wstring.c b/lib/ntdll/string/wstring.c new file mode 100644 index 0000000..592a55a --- /dev/null +++ b/lib/ntdll/string/wstring.c @@ -0,0 +1,288 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: lib/ntdll/string/wstring.c + * PURPOSE: Wide string functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + * 1998/12/04 RJJ Cleaned up and added i386 def checks + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + + +/* FUNCTIONS *****************************************************************/ + +int _wcsicmp (const wchar_t* cs, const wchar_t * ct) +{ + while (towlower(*cs) == towlower(*ct)) + { + if (*cs == 0) + return 0; + cs++; + ct++; + } + return towlower(*cs) - towlower(*ct); +} + + +wchar_t *_wcslwr (wchar_t *x) +{ + wchar_t *y=x; + + while (*y) { + *y=towlower(*y); + y++; + } + return x; +} + + +int _wcsnicmp (const wchar_t * cs, const wchar_t * ct, size_t count) +{ + if (count == 0) + return 0; + do { + if (towupper(*cs) != towupper(*ct++)) + return towupper(*cs) - towupper(*--ct); + if (*cs++ == 0) + break; + } while (--count != 0); + return 0; +} + + +wchar_t *_wcsupr(wchar_t *x) +{ + wchar_t *y=x; + + while (*y) { + *y=towupper(*y); + y++; + } + return x; +} + + +wchar_t *wcscat (wchar_t *dest, const wchar_t *src) +{ + int i, j; + + for (j = 0; dest[j] != 0; j++) + ; + for (i = 0; src[i] != 0; i++) + { + dest[j + i] = src[i]; + } + dest[j + i] = 0; + + return dest; +} + +wchar_t *wcschr (const wchar_t *str, wchar_t ch) +{ + while ((*str) != ((wchar_t) 0)) + { + if ((*str) == ch) + { + return (wchar_t *)str; + } + str++; + } + + return NULL; +} + +int wcscmp(const wchar_t *cs, const wchar_t *ct) +{ + while (*cs != '\0' && *ct != '\0' && *cs == *ct) + { + cs++; + ct++; + } + return *cs - *ct; +} + +wchar_t* wcscpy(wchar_t* str1, const wchar_t* str2) +{ + wchar_t* s = str1; + while ((*str2)!=0) + { + *s = *str2; + s++; + str2++; + } + *s = 0; + return(str1); +} + + +size_t wcscspn(const wchar_t *str,const wchar_t *reject) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do { + t=(wchar_t *)reject; + while (*t) { + if (*t==*s) + break; + t++; + } + if (*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} + + +size_t wcslen(const wchar_t *s) +{ + unsigned int len = 0; + + while (s[len] != 0) + { + len++; + } + + return len; +} + +wchar_t *wcsncat(wchar_t *dest, const wchar_t *src, size_t count) +{ + int i, j; + + for (j = 0; dest[j] != 0; j++) + ; + for (i = 0; i < count; i++) + { + dest[j + i] = src[i]; + if (src[i] == 0) + { + return dest; + } + } + dest[j + i] = 0; + + return dest; +} + + +int wcsncmp(const wchar_t * cs,const wchar_t * ct,size_t count) +{ + while ((*cs) == (*ct) && count > 0) + { + if (*cs == 0) + return 0; + cs++; + ct++; + count--; + } + return (*cs) - (*ct); +} + + +wchar_t* wcsncpy(wchar_t *dest, const wchar_t *src, size_t count) +{ + int i; + + for (i = 0; i < count; i++) + { + dest[i] = src[i]; + if (src[i] == 0) + { + return dest; + } + } + dest[i] = 0; + + return dest; +} + + +wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2) +{ + const wchar_t *scanp; + int c, sc; + + while ((c = *s1++) != 0) + { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + { + return (wchar_t *)(--s1); + } + } + return 0; +} + + +wchar_t * wcsrchr(const wchar_t *str, wchar_t ch) +{ + unsigned int len = 0; + while (str[len] != ((wchar_t)0)) + { + len++; + } + + for (; len > 0; len--) + { + if (str[len-1]==ch) + { + return (wchar_t *) &str[len - 1]; + } + } + + return NULL; +} + + +size_t wcsspn(const wchar_t *str,const wchar_t *accept) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do { + t=(wchar_t *)accept; + while (*t) { + if (*t==*s) + break; + t++; + } + if (!*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} + + +wchar_t *wcsstr(const wchar_t *s,const wchar_t *b) +{ + wchar_t *x; + wchar_t *y; + wchar_t *c; + x=(wchar_t *)s; + while (*x) { + if (*x==*b) { + y=x; + c=(wchar_t *)b; + while (*y && *c && *y==*c) { + c++; + y++; + } + if (!*c) + return x; + } + x++; + } + return NULL; +} + +/* EOF */ diff --git a/lib/ntdll/stubs/.cvsignore b/lib/ntdll/stubs/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/lib/ntdll/stubs/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/lib/ntdll/stubs/stubs.c b/lib/ntdll/stubs/stubs.c new file mode 100644 index 0000000..ade64b3 --- /dev/null +++ b/lib/ntdll/stubs/stubs.c @@ -0,0 +1,153 @@ +#include + +#define STUB(x) void x(void) { \ + UNICODE_STRING UnicodeString = \ + UNICODE_STRING_INITIALIZER( \ + L"NTDLL: Stub for "#x"\n" \ + ); \ + NtDisplayString(&UnicodeString); } + + +// ?Allocate@CBufferAllocator@@UAEPAXK@Z + +STUB(KiRaiseUserExceptionDispatcher) +STUB(LdrEnumResources) +STUB(LdrProcessRelocationBlock) +STUB(LdrQueryImageFileExecutionOptions) +STUB(LdrVerifyImageMatchesChecksum) +STUB(NPXEMULATORTABLE) +STUB(PfxFindPrefix) +STUB(PfxInitialize) +STUB(PfxInsertPrefix) +STUB(PfxRemovePrefix) +STUB(RestoreEm87Context) +STUB(RtlWalkHeap) +STUB(RtlZeroHeap) +STUB(RtlpUnWaitCriticalSection) +STUB(RtlpWaitForCriticalSection) +STUB(SaveEm87Context) +STUB(_CIpow) +STUB(__eCommonExceptions) +STUB(__eEmulatorInit) +STUB(__eF2XM1) +STUB(__eFABS) +STUB(__eFADD32) +STUB(__eFADD64) +STUB(__eFADDPreg) +STUB(__eFADDreg) +STUB(__eFADDtop) +STUB(__eFCHS) +STUB(__eFCOM) +STUB(__eFCOM32) +STUB(__eFCOM64) +STUB(__eFCOMP) +STUB(__eFCOMP32) +STUB(__eFCOMP64) +STUB(__eFCOMPP) +STUB(__eFCOS) +STUB(__eFDECSTP) +STUB(__eFDIV32) +STUB(__eFDIV64) +STUB(__eFDIVPreg) +STUB(__eFDIVR32) +STUB(__eFDIVR64) +STUB(__eFDIVRPreg) +STUB(__eFDIVRreg) +STUB(__eFDIVRtop) +STUB(__eFDIVreg) +STUB(__eFDIVtop) +STUB(__eFFREE) +STUB(__eFIADD16) +STUB(__eFIADD32) +STUB(__eFICOM16) +STUB(__eFICOM32) +STUB(__eFICOMP16) +STUB(__eFICOMP32) +STUB(__eFIDIV16) +STUB(__eFIDIV32) +STUB(__eFIDIVR16) +STUB(__eFIDIVR32) +STUB(__eFILD16) +STUB(__eFILD32) +STUB(__eFILD64) +STUB(__eFIMUL16) +STUB(__eFIMUL32) +STUB(__eFINCSTP) +STUB(__eFINIT) +STUB(__eFIST16) +STUB(__eFIST32) +STUB(__eFISTP16) +STUB(__eFISTP32) +STUB(__eFISTP64) +STUB(__eFISUB16) +STUB(__eFISUB32) +STUB(__eFISUBR16) +STUB(__eFISUBR32) +STUB(__eFLD1) +STUB(__eFLD32) +STUB(__eFLD64) +STUB(__eFLD80) +STUB(__eFLDCW) +STUB(__eFLDENV) +STUB(__eFLDL2E) +STUB(__eFLDLN2) +STUB(__eFLDPI) +STUB(__eFLDZ) +STUB(__eFMUL32) +STUB(__eFMUL64) +STUB(__eFMULPreg) +STUB(__eFMULreg) +STUB(__eFMULtop) +STUB(__eFPATAN) +STUB(__eFPREM) +STUB(__eFPREM1) +STUB(__eFPTAN) +STUB(__eFRNDINT) +STUB(__eFRSTOR) +STUB(__eFSAVE) +STUB(__eFSCALE) +STUB(__eFSIN) +STUB(__eFSQRT) +STUB(__eFST) +STUB(__eFST32) +STUB(__eFST64) +STUB(__eFSTCW) +STUB(__eFSTENV) +STUB(__eFSTP) +STUB(__eFSTP32) +STUB(__eFSTP64) +STUB(__eFSTP80) +STUB(__eFSTSW) +STUB(__eFSUB32) +STUB(__eFSUB64) +STUB(__eFSUBPreg) +STUB(__eFSUBR32) +STUB(__eFSUBR64) +STUB(__eFSUBRPreg) +STUB(__eFSUBRreg) +STUB(__eFSUBRtop) +STUB(__eFSUBreg) +STUB(__eFSUBtop) +STUB(__eFTST) +STUB(__eFUCOM) +STUB(__eFUCOMP) +STUB(__eFUCOMPP) +STUB(__eFXAM) +STUB(__eFXCH) +STUB(__eFXTRACT) +STUB(__eFYL2X) +STUB(__eFYL2XP1) +STUB(__eGetStatusWord) +STUB(_alldiv) +STUB(_allmul) +STUB(_alloca_probe) +STUB(_allrem) +STUB(_allshl) +STUB(_allshr) +STUB(_aulldiv) +STUB(_aullrem) +STUB(_aullshr) +//STUB(_chkstk) +STUB(_fltused) +//STUB(sscanf) + diff --git a/lib/ole32/.cvsignore b/lib/ole32/.cvsignore new file mode 100644 index 0000000..5086e0e --- /dev/null +++ b/lib/ole32/.cvsignore @@ -0,0 +1,2 @@ +ole32.coff +ole32.dll diff --git a/lib/ole32/CoXxx.c b/lib/ole32/CoXxx.c new file mode 100644 index 0000000..5da41ef --- /dev/null +++ b/lib/ole32/CoXxx.c @@ -0,0 +1,470 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib\ole32\CoXxx.c + * PURPOSE: The Co... function implementation + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ + +//#define INITGUID +#include + +#include + +// +// lCOMLockCount is a reference count, when it reaches 0, all COM libraries are freed +// +static ULONG lCOMLockCount = 0; + +WINOLEAPI_(ULONG) CoAddRefServerProcess() +{ + UNIMPLEMENTED; + + return 0L; +} + +WINOLEAPI CoAllowSetForegroundWindow(IUnknown *pUnk, LPVOID lpvReserved) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + + +WINOLEAPI CoCancelCall(DWORD dwThreadId, ULONG ulTimeout) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +WINOLEAPI CoCopyProxy(IUnknown* pProxy, IUnknown** ppCopy) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoDisableCallCancellation(LPVOID pvReserved) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI_(BOOL) CoDosDateTimeToFileTime(WORD nDosDate, WORD nDosTime, FILETIME* lpFileTime) +{ + UNIMPLEMENTED; + + return TRUE; +} + +// +// +// +WINOLEAPI CoEnableCallCancellation(LPVOID pvReserver) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI_(BOOL) CoFileTimeToDosDateTime(FILETIME* lpFileTime, LPWORD lpDosDate, LPWORD lpDosTime) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetCallContext(REFIID riid, void** ppInterface) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetCancelObject(DWORD dwThreadId, REFIID iid, void** ppUnk) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI_(DWORD) CoGetCurrentProcess() +{ + UNIMPLEMENTED; + + return 0; +} + +// +// +// +WINOLEAPI CoGetInstanceFromFile(COSERVERINFO* pServerInfo, CLSID* pClsid, IUnknown* punkOuter, + DWORD dwClsCtx, DWORD grfMode, OLECHAR* pwszName, DWORD dwCount, MULTI_QI* pResults) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetInstanceFromIStorage(COSERVERINFO* pServerInfo, CLSID* pClsid, IUnknown* punkOuter, + DWORD dwClsCtx, IStorage *pstg, DWORD dwCount, MULTI_QI* pResults) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID iid, LPVOID* ppv) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetMarshalSizeMax(ULONG* pulSize, REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, + LPVOID pvdestContext, DWORD mshlflags) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetObject(LPCWSTR pszName, BIND_OPTS* pBindOptions, REFIID riid, void** ppv) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetObjectContext(REFIID riid, LPVOID FAR* ppv) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvdestContext, + DWORD mshlflags, LPMARSHAL* ppMarshal) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetStdMarshalEx(LPUNKNOWN pUnkOuter, DWORD smexflags, LPUNKNOWN* ppUnkInner) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew) +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +// +// +// +WINOLEAPI CoImpersonateClient() +{ + UNIMPLEMENTED; + + return E_FAIL; +} + +WINOLEAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoRevokeMallocSpy() +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoSuspendClassObjects() +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI_(ULONG) CoReleaseServerProcess() +{ + UNIMPLEMENTED; + + return 0; +} + +WINOLEAPI CoRegisterPSClsid(IN REFIID riid, IN REFCLSID rclsid) +{ + UNIMPLEMENTED; + + return S_OK; +} + +#if 0 +WINOLEAPI CoRegisterSurrogate(IN LPSURROGATE pSurrogate) +{ + UNIMPLEMENTED; + + return S_OK; +} +#endif + +WINOLEAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk, DWORD dwDestContext, LPVOID pvDestContext, + DWORD mshlflags) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoReleaseMarshalData(LPSTREAM pStm) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk) +{ + UNIMPLEMENTED; + + return S_OK; +} + + +WINOLEAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM *ppStm) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoInitializeSecurity( + PSECURITY_DESCRIPTOR pSecDesc, + LONG cAuthSvc, + SOLE_AUTHENTICATION_SERVICE *asAuthSvc, + void *pReserved1, + DWORD dwAuthnLevel, + DWORD dwImpLevel, + void *pAuthList, + DWORD dwCapabilities, + void *pReserved3 ) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoQueryProxyBlanket( + IUnknown *pProxy, + DWORD *pwAuthnSvc, + DWORD *pAuthzSvc, + OLECHAR **pServerPrincName, + DWORD *pAuthnLevel, + DWORD *pImpLevel, + RPC_AUTH_IDENTITY_HANDLE *pAuthInfo, + DWORD *pCapabilites ) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoSetProxyBlanket( + IUnknown *pProxy, + DWORD dwAuthnSvc, + DWORD dwAuthzSvc, + OLECHAR *pServerPrincName, + DWORD dwAuthnLevel, + DWORD dwImpLevel, + RPC_AUTH_IDENTITY_HANDLE pAuthInfo, + DWORD dwCapabilities ) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoQueryClientBlanket( + DWORD *pAuthnSvc, + DWORD *pAuthzSvc, + OLECHAR **pServerPrincName, + DWORD *pAuthnLevel, + DWORD *pImpLevel, + RPC_AUTHZ_HANDLE *pPrivs, + DWORD *pCapabilities ) +{ + UNIMPLEMENTED; + + return S_OK; + +} + +WINOLEAPI CoRevertToSelf() +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoQueryAuthenticationServices( + DWORD *pcAuthSvc, + SOLE_AUTHENTICATION_SERVICE **asAuthSvc ) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoSwitchCallContext(IUnknown *pNewObject, IUnknown **ppOldObject ) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoSetCancelObject(IUnknown *pUnk) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoTestCancel() +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoRegisterMessageFilter( IN LPMESSAGEFILTER lpMessageFilter, + OUT LPMESSAGEFILTER FAR* lplpMessageFilter) +{ + UNIMPLEMENTED; + + return S_OK; +} + +#if 0 +WINOLEAPI CoRegisterChannelHook(REFGUID ExtensionUuid, IChannelHook *pChannelHook ) +{ + UNIMPLEMENTED; + + return S_OK; +} +#endif + +WINOLEAPI CoWaitForMultipleHandles(IN DWORD dwFlags, + IN DWORD dwTimeout, + IN ULONG cHandles, + IN LPHANDLE pHandles, + OUT LPDWORD lpdwindex) +{ + UNIMPLEMENTED; + + return S_OK; +} + +WINOLEAPI CoTreatAsClass(IN REFCLSID clsidOld, IN REFCLSID clsidNew) +{ + UNIMPLEMENTED; + + return S_OK; +} diff --git a/lib/ole32/DllMain.c b/lib/ole32/DllMain.c new file mode 100644 index 0000000..d904ec1 --- /dev/null +++ b/lib/ole32/DllMain.c @@ -0,0 +1,43 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib\ole32\DllMain.c + * PURPOSE: The dll entry routine + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#include + +#include + +#ifdef DBG + +DWORD DebugTraceLevel = MIN_TRACE; + +#endif /* DBG */ + +BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved) +{ + return TRUE; +} diff --git a/lib/ole32/Misc.c b/lib/ole32/Misc.c new file mode 100644 index 0000000..4252a4e --- /dev/null +++ b/lib/ole32/Misc.c @@ -0,0 +1,115 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib\ole32\Misc.c + * PURPOSE: Ole32.dll helper functions + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 14/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#include + +#if 0 + +WINOLEAPI PropVariantClear(PROPVARIANT *pvar){return S_OK;} +WINOLEAPI FreePropVariantArray( + ULONG cVariants, //Count of elements in the structure + PROPVARIANT *rgvars //Pointer to the PROPVARIANT structure +){return S_OK;} + +WINOLEAPI PropVariantCopy(PROPVARIANT* pvarDest, const PROPVARIANT* pvarSrc){return S_OK;} + +WINOLEAPI CreateDataAdviseHolder(OUT LPDATAADVISEHOLDER FAR* ppDAHolder) +{ + return S_OK; +} + +WINOLEAPI CreateDataCache(IN LPUNKNOWN pUnkOuter, IN REFCLSID rclsid, + IN REFIID iid, OUT LPVOID FAR* ppv) +{ + return S_OK; +} + +WINOLEAPI StringFromCLSID(IN REFCLSID rclsid, OUT LPOLESTR FAR* lplpsz) +{ + return S_OK; +} + +WINOLEAPI CLSIDFromString(IN LPOLESTR lpsz, OUT LPCLSID pclsid) +{ + return E_FAIL; +} + +WINOLEAPI StringFromIID(IN REFIID rclsid, OUT LPOLESTR FAR* lplpsz) +{ + return S_OK; +} + +WINOLEAPI IIDFromString(IN LPOLESTR lpsz, OUT LPIID lpiid) +{ + return S_OK; +} + +WINOLEAPI_(BOOL) CoIsOle1Class(IN REFCLSID rclsid) +{ + return S_OK; +} + +WINOLEAPI ProgIDFromCLSID (IN REFCLSID clsid, OUT LPOLESTR FAR* lplpszProgID) +{ + return S_OK; +} + +WINOLEAPI CLSIDFromProgID (IN LPCOLESTR lpszProgID, OUT LPCLSID lpclsid) +{ + return S_OK; +} + +WINOLEAPI CLSIDFromProgIDEx (IN LPCOLESTR lpszProgID, OUT LPCLSID lpclsid) +{ + return S_OK; +} + +WINOLEAPI_(int) StringFromGUID2(IN REFGUID rguid, OUT LPOLESTR lpsz, IN int cchMax) +{ + return S_OK; +} + +#endif + +/****************************************************************************** + * IsValidInterface [OLE32.78] + * + * RETURNS + * True, if the passed pointer is a valid interface + */ +BOOL WINAPI IsValidInterface( + LPUNKNOWN punk /* [in] interface to be tested */ +) { + return !( + IsBadReadPtr(punk,4) || + IsBadReadPtr(ICOM_VTBL(punk),4) || + IsBadReadPtr(ICOM_VTBL(punk)->QueryInterface,9) || + IsBadCodePtr((FARPROC)ICOM_VTBL(punk)->QueryInterface) + ); +} diff --git a/lib/ole32/Moniker.c b/lib/ole32/Moniker.c new file mode 100644 index 0000000..0b77f10 --- /dev/null +++ b/lib/ole32/Moniker.c @@ -0,0 +1,508 @@ +/* + * Monikers + * + * Copyright 1998 Marcus Meissner + * Copyright 1999 Noomen Hamza + */ + +#include + +#include +#include +#include +#include +#include + +#include + + +#define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */ + +/* define the structure of the running object table elements */ +typedef struct RunObject{ + + IUnknown* pObj; /* points on a running object*/ + IMoniker* pmkObj; /* points on a moniker who identifies this object */ + FILETIME lastModifObj; + DWORD identRegObj; /* registration key relative to this object */ + DWORD regTypeObj; /* registration type : strong or weak */ +}RunObject; + +/* define the RunningObjectTableImpl structure */ +typedef struct RunningObjectTableImpl{ + + ICOM_VFIELD(IRunningObjectTable); + ULONG ref; + + RunObject* runObjTab; /* pointer to the first object in the table */ + DWORD runObjTabSize; /* current table size */ + DWORD runObjTabLastIndx; /* first free index element in the table. */ + DWORD runObjTabRegister; /* registration key of the next registered object */ + +} RunningObjectTableImpl; + +RunningObjectTableImpl* runningObjectTableInstance=0; + +/* IRunningObjectTable prototype functions : */ +/* IUnknown functions*/ +static HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface); +static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface); +/* IRunningObjectTable functions */ +static HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,IUnknown* punkObject,IMoniker* pmkObjectName,DWORD* pdwRegister); +static HRESULT WINAPI RunningObjectTableImpl_Revoke(IRunningObjectTable* iface, DWORD dwRegister); +static HRESULT WINAPI RunningObjectTableImpl_IsRunning(IRunningObjectTable* iface, IMoniker* pmkObjectName); +static HRESULT WINAPI RunningObjectTableImpl_GetObject(IRunningObjectTable* iface, IMoniker* pmkObjectName,IUnknown** ppunkObject); +static HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, DWORD dwRegister,FILETIME* pfiletime); +static HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, IMoniker* pmkObjectName,FILETIME* pfiletime); +static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker** ppenumMoniker); +/* Local functions*/ +HRESULT WINAPI RunningObjectTableImpl_Initialize(); +HRESULT WINAPI RunningObjectTableImpl_UnInitialize(); +HRESULT WINAPI RunningObjectTableImpl_Destroy(); +HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,DWORD identReg,IMoniker* pmk,DWORD *indx); + +/* Virtual function table for the IRunningObjectTable class. */ +static ICOM_VTABLE(IRunningObjectTable) VT_RunningObjectTableImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + RunningObjectTableImpl_QueryInterface, + RunningObjectTableImpl_AddRef, + RunningObjectTableImpl_Release, + RunningObjectTableImpl_Register, + RunningObjectTableImpl_Revoke, + RunningObjectTableImpl_IsRunning, + RunningObjectTableImpl_GetObject, + RunningObjectTableImpl_NoteChangeTime, + RunningObjectTableImpl_GetTimeOfLastChange, + RunningObjectTableImpl_EnumRunning +}; + +/*********************************************************************** + * RunningObjectTable_QueryInterface + */ +HRESULT WINAPI RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + /* validate arguments */ + if (This==0) + return CO_E_NOTINITIALIZED; + + if (ppvObject==0) + return E_INVALIDARG; + + *ppvObject = 0; + + if (IsEqualIID(&IID_IUnknown, riid)) + *ppvObject = (IRunningObjectTable*)This; + else + if (IsEqualIID(&IID_IRunningObjectTable, riid)) + *ppvObject = (IRunningObjectTable*)This; + + if ((*ppvObject)==0) + return E_NOINTERFACE; + + RunningObjectTableImpl_AddRef(iface); + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_AddRef + */ +ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable* iface) +{ + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return ++(This->ref); +} + +/*********************************************************************** + * RunningObjectTable_Initialize + */ +HRESULT WINAPI RunningObjectTableImpl_Destroy() +{ + Print(MAX_TRACE, ("()\n")); + + if (runningObjectTableInstance==NULL) + return E_INVALIDARG; + + /* free the ROT table memory */ + HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab); + + /* free the ROT structure memory */ + HeapFree(GetProcessHeap(),0,runningObjectTableInstance); + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_Release + */ +ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable* iface) +{ + DWORD i; + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + This->ref--; + + /* unitialize ROT structure if there's no more reference to it*/ + if (This->ref==0){ + + /* release all registered objects */ + for(i=0;irunObjTabLastIndx;i++) + { + if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0) + IUnknown_Release(This->runObjTab[i].pObj); + + IMoniker_Release(This->runObjTab[i].pmkObj); + } + /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only + * when RunningObjectTableImpl_UnInitialize function is called + */ + + /* there's no more elements in the table */ + This->runObjTabRegister=0; + This->runObjTabLastIndx=0; + + return 0; + } + + return This->ref; +} + +/*********************************************************************** + * RunningObjectTable_Initialize + */ +HRESULT WINAPI RunningObjectTableImpl_Initialize() +{ + Print(MAX_TRACE, ("()\n")); + + /* create the unique instance of the RunningObjectTableImpl structure */ + runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl)); + + if (runningObjectTableInstance == 0) + return E_OUTOFMEMORY; + + /* initialize the virtual table function */ + ICOM_VTBL(runningObjectTableInstance) = &VT_RunningObjectTableImpl; + + /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */ + /* the ROT refered many times not in the same time (all the objects in the ROT will */ + /* be removed every time the ROT is removed ) */ + runningObjectTableInstance->ref = 1; + + /* allocate space memory for the table which contains all the running objects */ + runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE])); + + if (runningObjectTableInstance->runObjTab == NULL) + return E_OUTOFMEMORY; + + runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE; + runningObjectTableInstance->runObjTabRegister=1; + runningObjectTableInstance->runObjTabLastIndx=0; + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_UnInitialize + */ +HRESULT WINAPI RunningObjectTableImpl_UnInitialize() +{ + Print(MAX_TRACE, ("()\n")); + + if (runningObjectTableInstance==NULL) + return E_POINTER; + + RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance); + + RunningObjectTableImpl_Destroy(); + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_Register + */ +HRESULT WINAPI RunningObjectTableImpl_Register(IRunningObjectTable* iface, + DWORD grfFlags, /* Registration options */ + IUnknown *punkObject, /* Pointer to the object being registered */ + IMoniker *pmkObjectName, /* Pointer to the moniker of the object being registered */ + DWORD *pdwRegister) /* Pointer to the value identifying the registration */ +{ + HRESULT res=S_OK; + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister)); + + /* there's only two types of register : strong and or weak registration (only one must be passed on parameter) */ + if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && + (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) && + (grfFlags) ) + return E_INVALIDARG; + + if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL) + return E_INVALIDARG; + + /* verify if the object to be registered was registered before */ + if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK) + res = MK_S_MONIKERALREADYREGISTERED; + + /* put the new registered object in the first free element in the table */ + This->runObjTab[This->runObjTabLastIndx].pObj = punkObject; + This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName; + This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags; + This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister; + CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj)); + + /* gives a registration identifier to the registered object*/ + (*pdwRegister)= This->runObjTabRegister; + + if (This->runObjTabRegister == 0xFFFFFFFF){ + + Print(MIN_TRACE, ("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister)); + return E_FAIL; +} + This->runObjTabRegister++; + This->runObjTabLastIndx++; + + if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */ + + This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */ + This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab, + This->runObjTabSize * sizeof(RunObject)); + if (!This->runObjTab) + return E_OUTOFMEMORY; + } + /* add a reference to the object in the strong registration case */ + if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) + IUnknown_AddRef(punkObject); + + IMoniker_AddRef(pmkObjectName); + + return res; +} + +/*********************************************************************** + * RunningObjectTable_Revoke + */ +HRESULT WINAPI RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, + DWORD dwRegister) /* Value identifying registration to be revoked*/ +{ + + DWORD index,j; + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%ld)\n",This,dwRegister)); + + /* verify if the object to be revoked was registered before or not */ + if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE) + + return E_INVALIDARG; + + /* release the object if it was registered with a strong registrantion option */ + if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) + IUnknown_Release(This->runObjTab[index].pObj); + + IMoniker_Release(This->runObjTab[index].pmkObj); + + /* remove the object from the table */ + for(j=index; jrunObjTabLastIndx-1; j++) + This->runObjTab[j]= This->runObjTab[j+1]; + + This->runObjTabLastIndx--; + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_IsRunning + */ +HRESULT WINAPI RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, + IMoniker *pmkObjectName) /* Pointer to the moniker of the object whose status is desired */ +{ + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",This,pmkObjectName)); + + return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL); +} + +/*********************************************************************** + * RunningObjectTable_GetObject + */ +HRESULT WINAPI RunningObjectTableImpl_GetObject( IRunningObjectTable* iface, + IMoniker *pmkObjectName,/* Pointer to the moniker on the object */ + IUnknown **ppunkObject) /* Address of output variable that receives the IUnknown interface pointer */ +{ + DWORD index; + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject)); + + if (ppunkObject==NULL) + return E_POINTER; + + *ppunkObject=0; + + /* verify if the object was registered before or not */ + if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) + return MK_E_UNAVAILABLE; + + /* add a reference to the object then set output object argument */ + IUnknown_AddRef(This->runObjTab[index].pObj); + *ppunkObject=This->runObjTab[index].pObj; + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_NoteChangeTime + */ +HRESULT WINAPI RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface, + DWORD dwRegister, /* Value identifying registration being updated */ + FILETIME *pfiletime) /* Pointer to structure containing object's last change time */ +{ + DWORD index=-1; + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%ld,%p)\n",This,dwRegister,pfiletime)); + + /* verify if the object to be changed was registered before or not */ + if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE) + return E_INVALIDARG; + + /* set the new value of the last time change */ + This->runObjTab[index].lastModifObj= (*pfiletime); + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_GetTimeOfLastChange + */ +HRESULT WINAPI RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface, + IMoniker *pmkObjectName, /* Pointer to moniker on the object whose status is desired */ + FILETIME *pfiletime) /* Pointer to structure that receives object's last change time */ +{ + DWORD index=-1; + ICOM_THIS(RunningObjectTableImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,pmkObjectName,pfiletime)); + + if (pmkObjectName==NULL || pfiletime==NULL) + return E_INVALIDARG; + + /* verify if the object was registered before or not */ + if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) + return MK_E_UNAVAILABLE;; + + (*pfiletime)= This->runObjTab[index].lastModifObj; + + return S_OK; +} + +/*********************************************************************** + * RunningObjectTable_EnumRunning + */ +HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, + IEnumMoniker **ppenumMoniker) /* Address of output variable that receives the IEnumMoniker interface pointer */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/*********************************************************************** + * GetObjectIndex + */ +HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This, + DWORD identReg, + IMoniker* pmk, + DWORD *indx) +{ + + DWORD i; + + Print(MAX_TRACE, ("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx)); + + if (pmk!=NULL) + /* search object identified by a moniker */ + for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++); + else + /* search object identified by a register identifier */ + for(i=0;((irunObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++); + + if (i==This->runObjTabLastIndx) return S_FALSE; + + if (indx != NULL) *indx=i; + + return S_OK; +} + +/****************************************************************************** + * GetRunningObjectTable16 [OLE2.30] + */ +HRESULT WINAPI GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/*********************************************************************** + * GetRunningObjectTable (OLE2.73) + */ +HRESULT WINAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot) +{ + IID riid=IID_IRunningObjectTable; + HRESULT res; + + Print(MAX_TRACE, ("()\n")); + + if (reserved!=0) + return E_UNEXPECTED; + + if(runningObjectTableInstance==NULL) + return CO_E_NOTINITIALIZED; + + res = RunningObjectTableImpl_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot); + + return res; +} + +/****************************************************************************** + * OleRun [OLE32.123] + */ +HRESULT WINAPI OleRun(LPUNKNOWN pUnknown) +{ + IRunnableObject *runable; + ICOM_THIS(IRunnableObject,pUnknown); + LRESULT ret; + + ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable); + if (ret) + return 0; /* Appears to return no error. */ + ret = IRunnableObject_Run(runable,NULL); + IRunnableObject_Release(runable); + return ret; +} + +/****************************************************************************** + * MkParseDisplayName [OLE32.81] + */ +HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName, + LPDWORD pchEaten, LPMONIKER *ppmk) +{ + Print(MIN_TRACE, ("(%p, %S, %p, %p): stub.\n", pbc, szUserName, pchEaten, *ppmk)); + if (!(IsValidInterface((LPUNKNOWN) pbc))) + return E_INVALIDARG; + + return MK_E_SYNTAX; +} diff --git a/lib/ole32/Ole2.c b/lib/ole32/Ole2.c new file mode 100644 index 0000000..29e941b --- /dev/null +++ b/lib/ole32/Ole2.c @@ -0,0 +1,2228 @@ +/* + * OLE2 library + * + * Copyright 1995 Martin von Loewis + * Copyright 1999 Francis Beaudet + * Copyright 1999 Noel Borthwick + */ + +#include +#include +#include + +#include +#include +#include +#include +#include "ole32_main.h" + +#include + +#if 0 + +/****************************************************************************** + * These are static/global variables and internal data structures that the + * OLE module uses to maintain it's state. + */ +typedef struct tagDropTargetNode +{ + HWND hwndTarget; + IDropTarget* dropTarget; + struct tagDropTargetNode* prevDropTarget; + struct tagDropTargetNode* nextDropTarget; +} DropTargetNode; + +typedef struct tagTrackerWindowInfo +{ + IDataObject* dataObject; + IDropSource* dropSource; + DWORD dwOKEffect; + DWORD* pdwEffect; + BOOL trackingDone; + HRESULT returnValue; + + BOOL escPressed; + HWND curDragTargetHWND; + IDropTarget* curDragTarget; +} TrackerWindowInfo; + +typedef struct tagOleMenuDescriptor /* OleMenuDescriptor */ +{ + HWND hwndFrame; /* The containers frame window */ + HWND hwndActiveObject; /* The active objects window */ + OLEMENUGROUPWIDTHS mgw; /* OLE menu group widths for the shared menu */ + HMENU hmenuCombined; /* The combined menu */ + BOOL bIsServerItem; /* True if the currently open popup belongs to the server */ +} OleMenuDescriptor; + +typedef struct tagOleMenuHookItem /* OleMenu hook item in per thread hook list */ +{ + DWORD tid; /* Thread Id */ + HANDLE hHeap; /* Heap this is allocated from */ + HHOOK GetMsg_hHook; /* message hook for WH_GETMESSAGE */ + HHOOK CallWndProc_hHook; /* message hook for WH_CALLWNDPROC */ + struct tagOleMenuHookItem *next; +} OleMenuHookItem; + +static OleMenuHookItem *hook_list; + +/* + * This is the lock count on the OLE library. It is controlled by the + * OLEInitialize/OLEUninitialize methods. + */ +static ULONG OLE_moduleLockCount = 0; + +/* + * Name of our registered window class. + */ +static const char OLEDD_DRAGTRACKERCLASS[] = "WineDragDropTracker32"; + +/* + * This is the head of the Drop target container. + */ +static DropTargetNode* targetListHead = NULL; + +/****************************************************************************** + * These are the prototypes of miscelaneous utility methods + */ +static void OLEUTL_ReadRegistryDWORDValue(HKEY regKey, DWORD* pdwValue); + +/****************************************************************************** + * These are the prototypes of the utility methods used to manage a shared menu + */ +static void OLEMenu_Initialize(); +static void OLEMenu_UnInitialize(); +BOOL OLEMenu_InstallHooks( DWORD tid ); +BOOL OLEMenu_UnInstallHooks( DWORD tid ); +OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid ); +static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos ); +BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor ); +LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam); + +/****************************************************************************** + * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c) + */ +void OLEClipbrd_UnInitialize(); +void OLEClipbrd_Initialize(); + +/****************************************************************************** + * These are the prototypes of the utility methods used for OLE Drag n Drop + */ +static void OLEDD_Initialize(); +static void OLEDD_UnInitialize(); +static void OLEDD_InsertDropTarget( + DropTargetNode* nodeToAdd); +static DropTargetNode* OLEDD_ExtractDropTarget( + HWND hwndOfTarget); +static DropTargetNode* OLEDD_FindDropTarget( + HWND hwndOfTarget); +static LRESULT WINAPI OLEDD_DragTrackerWindowProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); +static void OLEDD_TrackMouseMove( + TrackerWindowInfo* trackerInfo, + POINT mousePos, + DWORD keyState); +static void OLEDD_TrackStateChange( + TrackerWindowInfo* trackerInfo, + POINT mousePos, + DWORD keyState); +static DWORD OLEDD_GetButtonState(); + + +/****************************************************************************** + * OleBuildVersion [OLE2.1] + */ +DWORD WINAPI OleBuildVersion(void) +{ + Print(MAX_TRACE, ("Returning version %d, build %d.\n", 1, 0)); + return (1<<16)+0; +} + +/*********************************************************************** + * OleInitialize (OLE2.2) (OLE32.108) + */ +HRESULT WINAPI OleInitialize(LPVOID reserved) +{ + HRESULT hr; + + Print(MAX_TRACE, ("(%p)\n", reserved)); + + /* + * The first duty of the OleInitialize is to initialize the COM libraries. + */ + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + /* + * If the CoInitializeEx call failed, the OLE libraries can't be + * initialized. + */ + if (FAILED(hr)) + return hr; + + /* + * Then, it has to initialize the OLE specific modules. + * This includes: + * Clipboard + * Drag and Drop + * Object linking and Embedding + * In-place activation + */ + if (OLE_moduleLockCount==0) +{ + /* + * Initialize the libraries. + */ + Print(MAX_TRACE, ("() - Initializing the OLE libraries\n")); + + /* + * OLE Clipboard + */ + OLEClipbrd_Initialize(); + + /* + * Drag and Drop + */ + OLEDD_Initialize(); + + /* + * OLE shared menu + */ + OLEMenu_Initialize(); +} + + /* + * Then, we increase the lock count on the OLE module. + */ + OLE_moduleLockCount++; + + return hr; +} + +/****************************************************************************** + * CoGetCurrentProcess [COMPOBJ.34] [OLE2.2][OLE32.108] + * + * NOTES + * Is DWORD really the correct return type for this function? + */ +DWORD WINAPI CoGetCurrentProcess(void) +{ + return GetCurrentProcessId(); +} + +/****************************************************************************** + * OleUninitialize [OLE2.3] [OLE32.131] + */ +void WINAPI OleUninitialize(void) +{ + Print(MAX_TRACE, ("()\n")); + + /* + * Decrease the lock count on the OLE module. + */ + OLE_moduleLockCount--; + + /* + * If we hit the bottom of the lock stack, free the libraries. + */ + if (OLE_moduleLockCount==0) + { + /* + * Actually free the libraries. + */ + Print(MAX_TRACE, ("() - Freeing the last reference count\n")); + + /* + * OLE Clipboard + */ + OLEClipbrd_UnInitialize(); + + /* + * Drag and Drop + */ + OLEDD_UnInitialize(); + + /* + * OLE shared menu + */ + OLEMenu_UnInitialize(); + } + + /* + * Then, uninitialize the COM libraries. + */ + CoUninitialize(); +} + +/****************************************************************************** + * CoRegisterMessageFilter [OLE32.38] + */ +HRESULT WINAPI CoRegisterMessageFilter( + LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */ + LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */ +) { + Print(MIN_TRACE, ("stub\n")); + if (lplpMessageFilter) { + *lplpMessageFilter = NULL; + } + return S_OK; +} + +/****************************************************************************** + * OleInitializeWOW [OLE32.109] + */ +HRESULT WINAPI OleInitializeWOW(DWORD x) { + Print(MIN_TRACE, ("(0x%08lx),stub!\n",x)); + return 0; +} + +/*********************************************************************** + * RegisterDragDrop16 (OLE2.35) + */ +HRESULT WINAPI RegisterDragDrop16( + DWORD hwnd, + LPDROPTARGET pDropTarget +) { + UNIMPLEMENTED; + return S_OK; +} + +/*********************************************************************** + * RegisterDragDrop (OLE32.139) + */ +HRESULT WINAPI RegisterDragDrop( + HWND hwnd, + LPDROPTARGET pDropTarget) +{ + DropTargetNode* dropTargetInfo; + + Print(MAX_TRACE, ("(0x%x,%p)\n", hwnd, pDropTarget)); + + /* + * First, check if the window is already registered. + */ + dropTargetInfo = OLEDD_FindDropTarget(hwnd); + + if (dropTargetInfo!=NULL) + return DRAGDROP_E_ALREADYREGISTERED; + + /* + * If it's not there, we can add it. We first create a node for it. + */ + dropTargetInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(DropTargetNode)); + + if (dropTargetInfo==NULL) + return E_OUTOFMEMORY; + + dropTargetInfo->hwndTarget = hwnd; + dropTargetInfo->prevDropTarget = NULL; + dropTargetInfo->nextDropTarget = NULL; + + /* + * Don't forget that this is an interface pointer, need to nail it down since + * we keep a copy of it. + */ + dropTargetInfo->dropTarget = pDropTarget; + IDropTarget_AddRef(dropTargetInfo->dropTarget); + + OLEDD_InsertDropTarget(dropTargetInfo); + + return S_OK; +} + +/*********************************************************************** + * RevokeDragDrop16 (OLE2.36) + */ +HRESULT WINAPI RevokeDragDrop16( + DWORD hwnd +) { + UNIMPLEMENTED; + return S_OK; +} + +/*********************************************************************** + * RevokeDragDrop (OLE32.141) + */ +HRESULT WINAPI RevokeDragDrop( + HWND hwnd) +{ + DropTargetNode* dropTargetInfo; + + Print(MAX_TRACE, ("(0x%x)\n", hwnd)); + + /* + * First, check if the window is already registered. + */ + dropTargetInfo = OLEDD_ExtractDropTarget(hwnd); + + /* + * If it ain't in there, it's an error. + */ + if (dropTargetInfo==NULL) + return DRAGDROP_E_NOTREGISTERED; + + /* + * If it's in there, clean-up it's used memory and + * references + */ + IDropTarget_Release(dropTargetInfo->dropTarget); + HeapFree(GetProcessHeap(), 0, dropTargetInfo); + + return S_OK; +} + +/*********************************************************************** + * OleRegGetUserType (OLE32.122) + * + * This implementation of OleRegGetUserType ignores the dwFormOfType + * parameter and always returns the full name of the object. This is + * not too bad since this is the case for many objects because of the + * way they are registered. + */ +HRESULT WINAPI OleRegGetUserType( + REFCLSID clsid, + DWORD dwFormOfType, + LPOLESTR* pszUserType) +{ + char keyName[60]; + DWORD dwKeyType; + DWORD cbData; + HKEY clsidKey; + LONG hres; + LPBYTE buffer; + HRESULT retVal; + /* + * Initialize the out parameter. + */ + *pszUserType = NULL; + + /* + * Build the key name we're looking for + */ + sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\", + clsid->Data1, clsid->Data2, clsid->Data3, + clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], + clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] ); + + Print(MAX_TRACE, ("(%s, %ld, %p)\n", keyName, dwFormOfType, pszUserType)); + + /* + * Open the class id Key + */ + hres = RegOpenKeyA(HKEY_CLASSES_ROOT, + keyName, + &clsidKey); + + if (hres != ERROR_SUCCESS) + return REGDB_E_CLASSNOTREG; + + /* + * Retrieve the size of the name string. + */ + cbData = 0; + + hres = RegQueryValueExA(clsidKey, + "", + NULL, + &dwKeyType, + NULL, + &cbData); + + if (hres!=ERROR_SUCCESS) + { + RegCloseKey(clsidKey); + return REGDB_E_READREGDB; + } + + /* + * Allocate a buffer for the registry value. + */ + *pszUserType = CoTaskMemAlloc(cbData*2); + + if (*pszUserType==NULL) + { + RegCloseKey(clsidKey); + return E_OUTOFMEMORY; + } + + buffer = HeapAlloc(GetProcessHeap(), 0, cbData); + + if (buffer == NULL) + { + RegCloseKey(clsidKey); + CoTaskMemFree(*pszUserType); + *pszUserType=NULL; + return E_OUTOFMEMORY; + } + + hres = RegQueryValueExA(clsidKey, + "", + NULL, + &dwKeyType, + buffer, + &cbData); + + RegCloseKey(clsidKey); + + + if (hres!=ERROR_SUCCESS) + { + CoTaskMemFree(*pszUserType); + *pszUserType=NULL; + + retVal = REGDB_E_READREGDB; + } + else + { + MultiByteToWideChar( CP_ACP, 0, buffer, -1, *pszUserType, cbData /*FIXME*/ ); + retVal = S_OK; + } + HeapFree(GetProcessHeap(), 0, buffer); + + return retVal; +} + +/*********************************************************************** + * DoDragDrop [OLE32.65] + */ +HRESULT WINAPI DoDragDrop ( + IDataObject *pDataObject, /* [in] ptr to the data obj */ + IDropSource* pDropSource, /* [in] ptr to the source obj */ + DWORD dwOKEffect, /* [in] effects allowed by the source */ + DWORD *pdwEffect) /* [out] ptr to effects of the source */ +{ + TrackerWindowInfo trackerInfo; + HWND hwndTrackWindow; + MSG msg; + + Print(MAX_TRACE, ("(DataObject %p, DropSource %p)\n", pDataObject, pDropSource)); + + /* + * Setup the drag n drop tracking window. + */ + trackerInfo.dataObject = pDataObject; + trackerInfo.dropSource = pDropSource; + trackerInfo.dwOKEffect = dwOKEffect; + trackerInfo.pdwEffect = pdwEffect; + trackerInfo.trackingDone = FALSE; + trackerInfo.escPressed = FALSE; + trackerInfo.curDragTargetHWND = 0; + trackerInfo.curDragTarget = 0; + + hwndTrackWindow = CreateWindowA(OLEDD_DRAGTRACKERCLASS, + "TrackerWindow", + WS_POPUP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + 0, + 0, + 0, + (LPVOID)&trackerInfo); + + if (hwndTrackWindow!=0) + { + /* + * Capture the mouse input + */ + SetCapture(hwndTrackWindow); + + /* + * Pump messages. All mouse input should go the the capture window. + */ + while (!trackerInfo.trackingDone && GetMessageA(&msg, 0, 0, 0) ) + { + if ( (msg.message >= WM_KEYFIRST) && + (msg.message <= WM_KEYLAST) ) + { + /* + * When keyboard messages are sent to windows on this thread, we + * want to ignore notify the drop source that the state changed. + * in the case of the Escape key, we also notify the drop source + * we give it a special meaning. + */ + if ( (msg.message==WM_KEYDOWN) && + (msg.wParam==VK_ESCAPE) ) + { + trackerInfo.escPressed = TRUE; + } + + /* + * Notify the drop source. + */ + OLEDD_TrackStateChange(&trackerInfo, + msg.pt, + OLEDD_GetButtonState()); + } + else + { + /* + * Dispatch the messages only when it's not a keyboard message. + */ + DispatchMessageA(&msg); + } + } + + /* + * Destroy the temporary window. + */ + DestroyWindow(hwndTrackWindow); + + return trackerInfo.returnValue; + } + + return E_FAIL; +} + +/*********************************************************************** + * OleQueryLinkFromData [OLE32.118] + */ +HRESULT WINAPI OleQueryLinkFromData( + IDataObject* pSrcDataObject) +{ + Print(MIN_TRACE, ("(%p),stub!\n", pSrcDataObject)); + return S_OK; +} + +/*********************************************************************** + * OleRegGetMiscStatus [OLE32.121] + */ +HRESULT WINAPI OleRegGetMiscStatus( + REFCLSID clsid, + DWORD dwAspect, + DWORD* pdwStatus) +{ + char keyName[60]; + HKEY clsidKey; + HKEY miscStatusKey; + HKEY aspectKey; + LONG result; + + /* + * Initialize the out parameter. + */ + *pdwStatus = 0; + + /* + * Build the key name we're looking for + */ + sprintf( keyName, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\", + clsid->Data1, clsid->Data2, clsid->Data3, + clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], + clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] ); + + Print(MAX_TRACE, ("(%s, %ld, %p)\n", keyName, dwAspect, pdwStatus)); + + /* + * Open the class id Key + */ + result = RegOpenKeyA(HKEY_CLASSES_ROOT, + keyName, + &clsidKey); + + if (result != ERROR_SUCCESS) + return REGDB_E_CLASSNOTREG; + + /* + * Get the MiscStatus + */ + result = RegOpenKeyA(clsidKey, + "MiscStatus", + &miscStatusKey); + + + if (result != ERROR_SUCCESS) + { + RegCloseKey(clsidKey); + return REGDB_E_READREGDB; + } + + /* + * Read the default value + */ + OLEUTL_ReadRegistryDWORDValue(miscStatusKey, pdwStatus); + + /* + * Open the key specific to the requested aspect. + */ + sprintf(keyName, "%ld", dwAspect); + + result = RegOpenKeyA(miscStatusKey, + keyName, + &aspectKey); + + if (result == ERROR_SUCCESS) + { + OLEUTL_ReadRegistryDWORDValue(aspectKey, pdwStatus); + RegCloseKey(aspectKey); + } + + /* + * Cleanup + */ + RegCloseKey(miscStatusKey); + RegCloseKey(clsidKey); + + return S_OK; +} + +/****************************************************************************** + * OleSetContainedObject [OLE32.128] + */ +HRESULT WINAPI OleSetContainedObject( + LPUNKNOWN pUnknown, + BOOL fContained) +{ + IRunnableObject* runnable = NULL; + HRESULT hres; + + Print(MAX_TRACE, ("(%p,%x), stub!\n", pUnknown, fContained)); + + hres = IUnknown_QueryInterface(pUnknown, + &IID_IRunnableObject, + (void**)&runnable); + + if (SUCCEEDED(hres)) + { + hres = IRunnableObject_SetContainedObject(runnable, fContained); + + IRunnableObject_Release(runnable); + + return hres; + } + + return S_OK; +} + +/****************************************************************************** + * OleLoad [OLE32.112] + */ +HRESULT WINAPI OleLoad( + LPSTORAGE pStg, + REFIID riid, + LPOLECLIENTSITE pClientSite, + LPVOID* ppvObj) +{ + IPersistStorage* persistStorage = NULL; + IOleObject* oleObject = NULL; + STATSTG storageInfo; + HRESULT hres; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n", pStg, riid, pClientSite, ppvObj)); + + /* + * TODO, Conversion ... OleDoAutoConvert + */ + + /* + * Get the class ID for the object. + */ + hres = IStorage_Stat(pStg, &storageInfo, STATFLAG_NONAME); + + /* + * Now, try and create the handler for the object + */ + hres = CoCreateInstance(&storageInfo.clsid, + NULL, + CLSCTX_INPROC_HANDLER, + &IID_IOleObject, + (void**)&oleObject); + + /* + * If that fails, as it will most times, load the default + * OLE handler. + */ + if (FAILED(hres)) + { + hres = OleCreateDefaultHandler(&storageInfo.clsid, + NULL, + &IID_IOleObject, + (void**)&oleObject); + } + + /* + * If we couldn't find a handler... this is bad. Abort the whole thing. + */ + if (FAILED(hres)) + return hres; + + /* + * Inform the new object of it's client site. + */ + hres = IOleObject_SetClientSite(oleObject, pClientSite); + + /* + * Initialize the object with it's IPersistStorage interface. + */ + hres = IOleObject_QueryInterface(oleObject, + &IID_IPersistStorage, + (void**)&persistStorage); + + if (SUCCEEDED(hres)) + { + IPersistStorage_Load(persistStorage, pStg); + + IPersistStorage_Release(persistStorage); + persistStorage = NULL; + } + + /* + * Return the requested interface to the caller. + */ + hres = IOleObject_QueryInterface(oleObject, riid, ppvObj); + + /* + * Cleanup interfaces used internally + */ + IOleObject_Release(oleObject); + + return hres; +} + +/*********************************************************************** + * OleSave [OLE32.124] + */ +HRESULT WINAPI OleSave( + LPPERSISTSTORAGE pPS, + LPSTORAGE pStg, + BOOL fSameAsLoad) +{ + HRESULT hres; + CLSID objectClass; + + Print(MAX_TRACE, ("(%p,%p,%x)\n", pPS, pStg, fSameAsLoad)); + + /* + * First, we transfer the class ID (if available) + */ + hres = IPersistStorage_GetClassID(pPS, &objectClass); + + if (SUCCEEDED(hres)) + { + WriteClassStg(pStg, &objectClass); + } + + /* + * Then, we ask the object to save itself to the + * storage. If it is successful, we commit the storage. + */ + hres = IPersistStorage_Save(pPS, pStg, fSameAsLoad); + + if (SUCCEEDED(hres)) + { + IStorage_Commit(pStg, + STGC_DEFAULT); + } + + return hres; +} + + +/****************************************************************************** + * OleLockRunning [OLE32.114] + */ +HRESULT WINAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses) +{ + IRunnableObject* runnable = NULL; + HRESULT hres; + + Print(MAX_TRACE, ("(%p,%x,%x)\n", pUnknown, fLock, fLastUnlockCloses)); + + hres = IUnknown_QueryInterface(pUnknown, + &IID_IRunnableObject, + (void**)&runnable); + + if (SUCCEEDED(hres)) + { + hres = IRunnableObject_LockRunning(runnable, fLock, fLastUnlockCloses); + + IRunnableObject_Release(runnable); + + return hres; + } + else + return E_INVALIDARG; +} + + +/************************************************************************** + * Internal methods to manage the shared OLE menu in response to the + * OLE***MenuDescriptor API + */ + +/*** + * OLEMenu_Initialize() + * + * Initializes the OLEMENU data structures. + */ +static void OLEMenu_Initialize() +{ +} + +/*** + * OLEMenu_UnInitialize() + * + * Releases the OLEMENU data structures. + */ +static void OLEMenu_UnInitialize() +{ +} + +/************************************************************************* + * OLEMenu_InstallHooks + * Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC + * + * RETURNS: TRUE if message hooks were succesfully installed + * FALSE on failure + */ +BOOL OLEMenu_InstallHooks( DWORD tid ) +{ + OleMenuHookItem *pHookItem = NULL; + + /* Create an entry for the hook table */ + if ( !(pHookItem = HeapAlloc(GetProcessHeap(), 0, + sizeof(OleMenuHookItem)) ) ) + return FALSE; + + pHookItem->tid = tid; + pHookItem->hHeap = GetProcessHeap(); + + /* Install a thread scope message hook for WH_GETMESSAGE */ + pHookItem->GetMsg_hHook = SetWindowsHookExA( WH_GETMESSAGE, OLEMenu_GetMsgProc, + 0, GetCurrentThreadId() ); + if ( !pHookItem->GetMsg_hHook ) + goto CLEANUP; + + /* Install a thread scope message hook for WH_CALLWNDPROC */ + pHookItem->CallWndProc_hHook = SetWindowsHookExA( WH_CALLWNDPROC, OLEMenu_CallWndProc, + 0, GetCurrentThreadId() ); + if ( !pHookItem->CallWndProc_hHook ) + goto CLEANUP; + + /* Insert the hook table entry */ + pHookItem->next = hook_list; + hook_list = pHookItem; + + return TRUE; + +CLEANUP: + /* Unhook any hooks */ + if ( pHookItem->GetMsg_hHook ) + UnhookWindowsHookEx( pHookItem->GetMsg_hHook ); + if ( pHookItem->CallWndProc_hHook ) + UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ); + /* Release the hook table entry */ + HeapFree(pHookItem->hHeap, 0, pHookItem ); + + return FALSE; +} + +/************************************************************************* + * OLEMenu_UnInstallHooks + * UnInstall thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC + * + * RETURNS: TRUE if message hooks were succesfully installed + * FALSE on failure + */ +BOOL OLEMenu_UnInstallHooks( DWORD tid ) +{ + OleMenuHookItem *pHookItem = NULL; + OleMenuHookItem **ppHook = &hook_list; + + while (*ppHook) + { + if ((*ppHook)->tid == tid) + { + pHookItem = *ppHook; + *ppHook = pHookItem->next; + break; + } + ppHook = &(*ppHook)->next; + } + if (!pHookItem) return FALSE; + + /* Uninstall the hooks installed for this thread */ + if ( !UnhookWindowsHookEx( pHookItem->GetMsg_hHook ) ) + goto CLEANUP; + if ( !UnhookWindowsHookEx( pHookItem->CallWndProc_hHook ) ) + goto CLEANUP; + + /* Release the hook table entry */ + HeapFree(pHookItem->hHeap, 0, pHookItem ); + + return TRUE; + +CLEANUP: + /* Release the hook table entry */ + if (pHookItem) + HeapFree(pHookItem->hHeap, 0, pHookItem ); + + return FALSE; +} + +/************************************************************************* + * OLEMenu_IsHookInstalled + * Tests if OLEMenu hooks have been installed for a thread + * + * RETURNS: The pointer and index of the hook table entry for the tid + * NULL and -1 for the index if no hooks were installed for this thread + */ +OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid ) +{ + OleMenuHookItem *pHookItem = NULL; + + /* Do a simple linear search for an entry whose tid matches ours. + * We really need a map but efficiency is not a concern here. */ + for (pHookItem = hook_list; pHookItem; pHookItem = pHookItem->next) + { + if ( tid == pHookItem->tid ) + return pHookItem; + } + + return NULL; +} + +/*********************************************************************** + * OLEMenu_FindMainMenuIndex + * + * Used by OLEMenu API to find the top level group a menu item belongs to. + * On success pnPos contains the index of the item in the top level menu group + * + * RETURNS: TRUE if the ID was found, FALSE on failure + */ +static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos ) +{ + UINT i, nItems; + + nItems = GetMenuItemCount( hMainMenu ); + + for (i = 0; i < nItems; i++) + { + HMENU hsubmenu; + + /* Is the current item a submenu? */ + if ( (hsubmenu = GetSubMenu(hMainMenu, i)) ) + { + /* If the handle is the same we're done */ + if ( hsubmenu == hPopupMenu ) + { + if (pnPos) + *pnPos = i; + return TRUE; + } + /* Recursively search without updating pnPos */ + else if ( OLEMenu_FindMainMenuIndex( hsubmenu, hPopupMenu, NULL ) ) + { + if (pnPos) + *pnPos = i; + return TRUE; + } + } + } + + return FALSE; +} + +/*********************************************************************** + * OLEMenu_SetIsServerMenu + * + * Checks whether a popup menu belongs to a shared menu group which is + * owned by the server, and sets the menu descriptor state accordingly. + * All menu messages from these groups should be routed to the server. + * + * RETURNS: TRUE if the popup menu is part of a server owned group + * FASE if the popup menu is part of a container owned group + */ +BOOL OLEMenu_SetIsServerMenu( HMENU hmenu, OleMenuDescriptor *pOleMenuDescriptor ) +{ + UINT nPos = 0, nWidth, i; + + pOleMenuDescriptor->bIsServerItem = FALSE; + + /* Don't bother searching if the popup is the combined menu itself */ + if ( hmenu == pOleMenuDescriptor->hmenuCombined ) + return FALSE; + + /* Find the menu item index in the shared OLE menu that this item belongs to */ + if ( !OLEMenu_FindMainMenuIndex( pOleMenuDescriptor->hmenuCombined, hmenu, &nPos ) ) + return FALSE; + + /* The group widths array has counts for the number of elements + * in the groups File, Edit, Container, Object, Window, Help. + * The Edit, Object & Help groups belong to the server object + * and the other three belong to the container. + * Loop thru the group widths and locate the group we are a member of. + */ + for ( i = 0, nWidth = 0; i < 6; i++ ) + { + nWidth += pOleMenuDescriptor->mgw.width[i]; + if ( nPos < nWidth ) + { + /* Odd elements are server menu widths */ + pOleMenuDescriptor->bIsServerItem = (i%2) ? TRUE : FALSE; + break; + } + } + + return pOleMenuDescriptor->bIsServerItem; +} + +/************************************************************************* + * OLEMenu_CallWndProc + * Thread scope WH_CALLWNDPROC hook proc filter function (callback) + * This is invoked from a message hook installed in OleSetMenuDescriptor. + */ +LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lParam) +{ +#if 0 + LPCWPSTRUCT pMsg = NULL; + HOLEMENU hOleMenu = 0; + OleMenuDescriptor *pOleMenuDescriptor = NULL; + OleMenuHookItem *pHookItem = NULL; + WORD fuFlags; + + Print(MAX_TRACE, ("%i, %04x, %08x\n", code, wParam, (unsigned)lParam )); + + /* Check if we're being asked to process the message */ + if ( HC_ACTION != code ) + goto NEXTHOOK; + + /* Retrieve the current message being dispatched from lParam */ + pMsg = (LPCWPSTRUCT)lParam; + + /* Check if the message is destined for a window we are interested in: + * If the window has an OLEMenu property we may need to dispatch + * the menu message to its active objects window instead. */ + + hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" ); + if ( !hOleMenu ) + goto NEXTHOOK; + + /* Get the menu descriptor */ + pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); + if ( !pOleMenuDescriptor ) /* Bad descriptor! */ + goto NEXTHOOK; + + /* Process menu messages */ + switch( pMsg->message ) + { + case WM_INITMENU: + { + /* Reset the menu descriptor state */ + pOleMenuDescriptor->bIsServerItem = FALSE; + + /* Send this message to the server as well */ + SendMessageA( pOleMenuDescriptor->hwndActiveObject, + pMsg->message, pMsg->wParam, pMsg->lParam ); + goto NEXTHOOK; + } + + case WM_INITMENUPOPUP: + { + /* Save the state for whether this is a server owned menu */ + OLEMenu_SetIsServerMenu( (HMENU)pMsg->wParam, pOleMenuDescriptor ); + break; + } + + case WM_MENUSELECT: + { + fuFlags = HIWORD(pMsg->wParam); /* Get flags */ + if ( fuFlags & MF_SYSMENU ) + goto NEXTHOOK; + + /* Save the state for whether this is a server owned popup menu */ + else if ( fuFlags & MF_POPUP ) + OLEMenu_SetIsServerMenu( (HMENU)pMsg->lParam, pOleMenuDescriptor ); + + break; + } + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) pMsg->lParam; + if ( pMsg->wParam != 0 || lpdis->CtlType != ODT_MENU ) + goto NEXTHOOK; /* Not a menu message */ + + break; + } + + default: + goto NEXTHOOK; + } + + /* If the message was for the server dispatch it accordingly */ + if ( pOleMenuDescriptor->bIsServerItem ) + { + SendMessageA( pOleMenuDescriptor->hwndActiveObject, + pMsg->message, pMsg->wParam, pMsg->lParam ); + } + +NEXTHOOK: + if ( pOleMenuDescriptor ) + GlobalUnlock( hOleMenu ); + + /* Lookup the hook item for the current thread */ + if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) ) + { + /* This should never fail!! */ + Print(MID_TRACE, ("could not retrieve hHook for current thread!\n" )); + return 0; + } + + /* Pass on the message to the next hooker */ + return CallNextHookEx( pHookItem->CallWndProc_hHook, code, wParam, lParam ); + +#else + UNIMPLEMENTED; + return 0; +#endif +} + +/************************************************************************* + * OLEMenu_GetMsgProc + * Thread scope WH_GETMESSAGE hook proc filter function (callback) + * This is invoked from a message hook installed in OleSetMenuDescriptor. + */ +LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam) +{ + LPMSG pMsg = NULL; + HOLEMENU hOleMenu = 0; + OleMenuDescriptor *pOleMenuDescriptor = NULL; + OleMenuHookItem *pHookItem = NULL; + WORD wCode; + + Print(MAX_TRACE, ("%i, %04x, %08x\n", code, wParam, (unsigned)lParam )); + + /* Check if we're being asked to process a messages */ + if ( HC_ACTION != code ) + goto NEXTHOOK; + + /* Retrieve the current message being dispatched from lParam */ + pMsg = (LPMSG)lParam; + + /* Check if the message is destined for a window we are interested in: + * If the window has an OLEMenu property we may need to dispatch + * the menu message to its active objects window instead. */ + + hOleMenu = (HOLEMENU)GetPropA( pMsg->hwnd, "PROP_OLEMenuDescriptor" ); + if ( !hOleMenu ) + goto NEXTHOOK; + + /* Process menu messages */ + switch( pMsg->message ) + { + case WM_COMMAND: + { + wCode = HIWORD(pMsg->wParam); /* Get notification code */ + if ( wCode ) + goto NEXTHOOK; /* Not a menu message */ + break; + } + default: + goto NEXTHOOK; + } + + /* Get the menu descriptor */ + pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); + if ( !pOleMenuDescriptor ) /* Bad descriptor! */ + goto NEXTHOOK; + + /* If the message was for the server dispatch it accordingly */ + if ( pOleMenuDescriptor->bIsServerItem ) + { + /* Change the hWnd in the message to the active objects hWnd. + * The message loop which reads this message will automatically + * dispatch it to the embedded objects window. */ + pMsg->hwnd = pOleMenuDescriptor->hwndActiveObject; + } + +NEXTHOOK: + if ( pOleMenuDescriptor ) + GlobalUnlock( hOleMenu ); + + /* Lookup the hook item for the current thread */ + if ( !( pHookItem = OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) ) + { + /* This should never fail!! */ + Print(MID_TRACE, ("could not retrieve hHook for current thread!\n" )); + return FALSE; + } + + /* Pass on the message to the next hooker */ + return CallNextHookEx( pHookItem->GetMsg_hHook, code, wParam, lParam ); +} + +/*********************************************************************** + * OleCreateMenuDescriptor [OLE32.97] + * Creates an OLE menu descriptor for OLE to use when dispatching + * menu messages and commands. + * + * PARAMS: + * hmenuCombined - Handle to the objects combined menu + * lpMenuWidths - Pointer to array of 6 LONG's indicating menus per group + * + */ +HOLEMENU WINAPI OleCreateMenuDescriptor( + HMENU hmenuCombined, + LPOLEMENUGROUPWIDTHS lpMenuWidths) +{ + HOLEMENU hOleMenu; + OleMenuDescriptor *pOleMenuDescriptor; + int i; + + if ( !hmenuCombined || !lpMenuWidths ) + return 0; + + /* Create an OLE menu descriptor */ + if ( !(hOleMenu = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, + sizeof(OleMenuDescriptor) ) ) ) + return 0; + + pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); + if ( !pOleMenuDescriptor ) + return 0; + + /* Initialize menu group widths and hmenu */ + for ( i = 0; i < 6; i++ ) + pOleMenuDescriptor->mgw.width[i] = lpMenuWidths->width[i]; + + pOleMenuDescriptor->hmenuCombined = hmenuCombined; + pOleMenuDescriptor->bIsServerItem = FALSE; + GlobalUnlock( hOleMenu ); + + return hOleMenu; +} + +/*********************************************************************** + * OleDestroyMenuDescriptor [OLE32.99] + * Destroy the shared menu descriptor + */ +HRESULT WINAPI OleDestroyMenuDescriptor( + HOLEMENU hmenuDescriptor) +{ + if ( hmenuDescriptor ) + GlobalFree( hmenuDescriptor ); + return S_OK; +} + +/*********************************************************************** + * OleSetMenuDescriptor [OLE32.129] + * Installs or removes OLE dispatching code for the containers frame window + * FIXME: The lpFrame and lpActiveObject parameters are currently ignored + * OLE should install context sensitive help F1 filtering for the app when + * these are non null. + * + * PARAMS: + * hOleMenu Handle to composite menu descriptor + * hwndFrame Handle to containers frame window + * hwndActiveObject Handle to objects in-place activation window + * lpFrame Pointer to IOleInPlaceFrame on containers window + * lpActiveObject Pointer to IOleInPlaceActiveObject on active in-place object + * + * RETURNS: + * S_OK - menu installed correctly + * E_FAIL, E_INVALIDARG, E_UNEXPECTED - failure + */ +HRESULT WINAPI OleSetMenuDescriptor( + HOLEMENU hOleMenu, + HWND hwndFrame, + HWND hwndActiveObject, + LPOLEINPLACEFRAME lpFrame, + LPOLEINPLACEACTIVEOBJECT lpActiveObject) +{ + OleMenuDescriptor *pOleMenuDescriptor = NULL; + + /* Check args */ + if ( !hwndFrame || (hOleMenu && !hwndActiveObject) ) + return E_INVALIDARG; + + if ( lpFrame || lpActiveObject ) + { + Print(MIN_TRACE, ("(%x, %x, %x, %p, %p), Context sensitive help filtering not implemented!\n", + (unsigned int)hOleMenu, + hwndFrame, + hwndActiveObject, + lpFrame, + lpActiveObject)); + } + + /* Set up a message hook to intercept the containers frame window messages. + * The message filter is responsible for dispatching menu messages from the + * shared menu which are intended for the object. + */ + + if ( hOleMenu ) /* Want to install dispatching code */ + { + /* If OLEMenu hooks are already installed for this thread, fail + * Note: This effectively means that OleSetMenuDescriptor cannot + * be called twice in succession on the same frame window + * without first calling it with a null hOleMenu to uninstall */ + if ( OLEMenu_IsHookInstalled( GetCurrentThreadId() ) ) + return E_FAIL; + + /* Get the menu descriptor */ + pOleMenuDescriptor = (OleMenuDescriptor *) GlobalLock( hOleMenu ); + if ( !pOleMenuDescriptor ) + return E_UNEXPECTED; + + /* Update the menu descriptor */ + pOleMenuDescriptor->hwndFrame = hwndFrame; + pOleMenuDescriptor->hwndActiveObject = hwndActiveObject; + + GlobalUnlock( hOleMenu ); + pOleMenuDescriptor = NULL; + + /* Add a menu descriptor windows property to the frame window */ + SetPropA( hwndFrame, "PROP_OLEMenuDescriptor", hOleMenu ); + + /* Install thread scope message hooks for WH_GETMESSAGE and WH_CALLWNDPROC */ + if ( !OLEMenu_InstallHooks( GetCurrentThreadId() ) ) + return E_FAIL; + } + else /* Want to uninstall dispatching code */ + { + /* Uninstall the hooks */ + if ( !OLEMenu_UnInstallHooks( GetCurrentThreadId() ) ) + return E_FAIL; + + /* Remove the menu descriptor property from the frame window */ + RemovePropA( hwndFrame, "PROP_OLEMenuDescriptor" ); + } + + return S_OK; +} + +/****************************************************************************** + * IsAccelerator [OLE32.75] + * Mostly copied from controls/menu.c TranslateAccelerator implementation + */ +BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD* lpwCmd) +{ +#if 0 + /* YES, Accel16! */ + LPACCEL16 lpAccelTbl; + int i; + + if(!lpMsg) return FALSE; + if (!hAccel || !(lpAccelTbl = (LPACCEL16)LockResource16(hAccel))) + { + WARN_(accel)("invalid accel handle=%04x\n", hAccel); + return FALSE; + } + if((lpMsg->message != WM_KEYDOWN && + lpMsg->message != WM_KEYUP && + lpMsg->message != WM_SYSKEYDOWN && + lpMsg->message != WM_SYSKEYUP && + lpMsg->message != WM_CHAR)) return FALSE; + + Print(MAX_TRACE, ("hAccel=%04x, cAccelEntries=%d," + "msg->hwnd=%04x, msg->message=%04x, wParam=%08x, lParam=%08lx\n", + hAccel, cAccelEntries, + lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam)); + for(i = 0; i < cAccelEntries; i++) + { + if(lpAccelTbl[i].key != lpMsg->wParam) + continue; + + if(lpMsg->message == WM_CHAR) + { + if(!(lpAccelTbl[i].fVirt & FALT) && !(lpAccelTbl[i].fVirt & FVIRTKEY)) + { + Print(MAX_TRACE, ("found accel for WM_CHAR: ('%c')\n", lpMsg->wParam & 0xff)); + goto found; + } + } + else + { + if(lpAccelTbl[i].fVirt & FVIRTKEY) + { + INT mask = 0; + Print(MAX_TRACE, ("found accel for virt_key %04x (scan %04x)\n", + lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff)); + if(GetKeyState(VK_SHIFT) & 0x8000) mask |= FSHIFT; + if(GetKeyState(VK_CONTROL) & 0x8000) mask |= FCONTROL; + if(GetKeyState(VK_MENU) & 0x8000) mask |= FALT; + if(mask == (lpAccelTbl[i].fVirt & (FSHIFT | FCONTROL | FALT))) goto found; + Print(MAX_TRACE, ("incorrect SHIFT/CTRL/ALT-state\n")); + } + else + { + if(!(lpMsg->lParam & 0x01000000)) /* no special_key */ + { + if((lpAccelTbl[i].fVirt & FALT) && (lpMsg->lParam & 0x20000000)) + { /* ^^ ALT pressed */ + Print(MAX_TRACE, ("found accel for Alt-%c\n", lpMsg->wParam & 0xff)); + goto found; + } + } + } + } + } + + WARN_(accel)("couldn't translate accelerator key\n"); + return FALSE; + +found: + if(lpwCmd) *lpwCmd = lpAccelTbl[i].cmd; + return TRUE; +#else + return FALSE; +#endif +} + +/*********************************************************************** + * ReleaseStgMedium [OLE32.140] + */ +void WINAPI ReleaseStgMedium( + STGMEDIUM* pmedium) +{ + switch (pmedium->tymed) + { + case TYMED_HGLOBAL: + { + if ( (pmedium->pUnkForRelease==0) && + (pmedium->u.hGlobal!=0) ) + GlobalFree(pmedium->u.hGlobal); + + pmedium->u.hGlobal = 0; + break; + } + case TYMED_FILE: + { + if (pmedium->u.lpszFileName!=0) + { + if (pmedium->pUnkForRelease==0) + { + DeleteFileW(pmedium->u.lpszFileName); + } + + CoTaskMemFree(pmedium->u.lpszFileName); + } + + pmedium->u.lpszFileName = 0; + break; + } + case TYMED_ISTREAM: + { + if (pmedium->u.pstm!=0) + { + IStream_Release(pmedium->u.pstm); + } + + pmedium->u.pstm = 0; + break; + } + case TYMED_ISTORAGE: + { + if (pmedium->u.pstg!=0) + { + IStorage_Release(pmedium->u.pstg); + } + + pmedium->u.pstg = 0; + break; + } + case TYMED_GDI: + { + if ( (pmedium->pUnkForRelease==0) && + (pmedium->u.hGlobal!=0) ) + DeleteObject(pmedium->u.hGlobal); + + pmedium->u.hGlobal = 0; + break; + } + case TYMED_MFPICT: + { + if ( (pmedium->pUnkForRelease==0) && + (pmedium->u.hMetaFilePict!=0) ) + { +#if 0 + LPMETAFILEPICT pMP = GlobalLock(pmedium->u.hMetaFilePict); + DeleteMetaFile(pMP->hMF); +#else + Print(MIN_TRACE, ("Depending on MetaFile implementation\n")); +#endif + GlobalUnlock(pmedium->u.hMetaFilePict); + GlobalFree(pmedium->u.hMetaFilePict); + } + + pmedium->u.hMetaFilePict = 0; + break; + } + case TYMED_ENHMF: + { + if ( (pmedium->pUnkForRelease==0) && + (pmedium->u.hEnhMetaFile!=0) ) + { + DeleteEnhMetaFile(pmedium->u.hEnhMetaFile); + } + + pmedium->u.hEnhMetaFile = 0; + break; + } + case TYMED_NULL: + default: + break; + } + + /* + * After cleaning up, the unknown is released + */ + if (pmedium->pUnkForRelease!=0) + { + IUnknown_Release(pmedium->pUnkForRelease); + pmedium->pUnkForRelease = 0; + } +} + +/*** + * OLEDD_Initialize() + * + * Initializes the OLE drag and drop data structures. + */ +static void OLEDD_Initialize() +{ + WNDCLASS wndClass; + + ZeroMemory (&wndClass, sizeof(WNDCLASS)); + wndClass.style = CS_GLOBALCLASS; + wndClass.lpfnWndProc = (WNDPROC)OLEDD_DragTrackerWindowProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = sizeof(TrackerWindowInfo*); + wndClass.hCursor = 0; + wndClass.hbrBackground = 0; + wndClass.lpszClassName = OLEDD_DRAGTRACKERCLASS; + + RegisterClassA (&wndClass); +} + +/*** + * OLEDD_UnInitialize() + * + * Releases the OLE drag and drop data structures. + */ +static void OLEDD_UnInitialize() +{ + /* + * Simply empty the list. + */ + while (targetListHead!=NULL) + { + RevokeDragDrop(targetListHead->hwndTarget); + } +} + +/*** + * OLEDD_InsertDropTarget() + * + * Insert the target node in the tree. + */ +static void OLEDD_InsertDropTarget(DropTargetNode* nodeToAdd) +{ + DropTargetNode* curNode; + DropTargetNode** parentNodeLink; + + /* + * Iterate the tree to find the insertion point. + */ + curNode = targetListHead; + parentNodeLink = &targetListHead; + + while (curNode!=NULL) + { + if (nodeToAdd->hwndTargethwndTarget) + { + /* + * If the node we want to add has a smaller HWND, go left + */ + parentNodeLink = &curNode->prevDropTarget; + curNode = curNode->prevDropTarget; + } + else if (nodeToAdd->hwndTarget>curNode->hwndTarget) + { + /* + * If the node we want to add has a larger HWND, go right + */ + parentNodeLink = &curNode->nextDropTarget; + curNode = curNode->nextDropTarget; + } + else + { + /* + * The item was found in the list. It shouldn't have been there + */ + assert(FALSE); + return; + } + } + + /* + * If we get here, we have found a spot for our item. The parentNodeLink + * pointer points to the pointer that we have to modify. + * The curNode should be NULL. We just have to establish the link and Voila! + */ + assert(curNode==NULL); + assert(parentNodeLink!=NULL); + assert(*parentNodeLink==NULL); + + *parentNodeLink=nodeToAdd; +} + +/*** + * OLEDD_ExtractDropTarget() + * + * Removes the target node from the tree. + */ +static DropTargetNode* OLEDD_ExtractDropTarget(HWND hwndOfTarget) +{ + DropTargetNode* curNode; + DropTargetNode** parentNodeLink; + + /* + * Iterate the tree to find the insertion point. + */ + curNode = targetListHead; + parentNodeLink = &targetListHead; + + while (curNode!=NULL) + { + if (hwndOfTargethwndTarget) + { + /* + * If the node we want to add has a smaller HWND, go left + */ + parentNodeLink = &curNode->prevDropTarget; + curNode = curNode->prevDropTarget; + } + else if (hwndOfTarget>curNode->hwndTarget) + { + /* + * If the node we want to add has a larger HWND, go right + */ + parentNodeLink = &curNode->nextDropTarget; + curNode = curNode->nextDropTarget; + } + else + { + /* + * The item was found in the list. Detach it from it's parent and + * re-insert it's kids in the tree. + */ + assert(parentNodeLink!=NULL); + assert(*parentNodeLink==curNode); + + /* + * We arbitrately re-attach the left sub-tree to the parent. + */ + *parentNodeLink = curNode->prevDropTarget; + + /* + * And we re-insert the right subtree + */ + if (curNode->nextDropTarget!=NULL) + { + OLEDD_InsertDropTarget(curNode->nextDropTarget); + } + + /* + * The node we found is still a valid node once we complete + * the unlinking of the kids. + */ + curNode->nextDropTarget=NULL; + curNode->prevDropTarget=NULL; + + return curNode; + } + } + + /* + * If we get here, the node is not in the tree + */ + return NULL; +} + +/*** + * OLEDD_FindDropTarget() + * + * Finds information about the drop target. + */ +static DropTargetNode* OLEDD_FindDropTarget(HWND hwndOfTarget) +{ + DropTargetNode* curNode; + + /* + * Iterate the tree to find the HWND value. + */ + curNode = targetListHead; + + while (curNode!=NULL) + { + if (hwndOfTargethwndTarget) + { + /* + * If the node we want to add has a smaller HWND, go left + */ + curNode = curNode->prevDropTarget; + } + else if (hwndOfTarget>curNode->hwndTarget) + { + /* + * If the node we want to add has a larger HWND, go right + */ + curNode = curNode->nextDropTarget; + } + else + { + /* + * The item was found in the list. + */ + return curNode; + } + } + + /* + * If we get here, the item is not in the list + */ + return NULL; +} + +/*** + * OLEDD_DragTrackerWindowProc() + * + * This method is the WindowProcedure of the drag n drop tracking + * window. During a drag n Drop operation, an invisible window is created + * to receive the user input and act upon it. This procedure is in charge + * of this behavior. + */ +static LRESULT WINAPI OLEDD_DragTrackerWindowProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) + { + case WM_CREATE: + { + LPCREATESTRUCT createStruct = (LPCREATESTRUCT)lParam; + + SetWindowLongA(hwnd, 0, (LONG)createStruct->lpCreateParams); + + + break; + } + case WM_MOUSEMOVE: + { + TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0); + POINT mousePos; + + /* + * Get the current mouse position in screen coordinates. + */ + mousePos.x = LOWORD(lParam); + mousePos.y = HIWORD(lParam); + ClientToScreen(hwnd, &mousePos); + + /* + * Track the movement of the mouse. + */ + OLEDD_TrackMouseMove(trackerInfo, mousePos, wParam); + + break; + } + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + { + TrackerWindowInfo* trackerInfo = (TrackerWindowInfo*)GetWindowLongA(hwnd, 0); + POINT mousePos; + + /* + * Get the current mouse position in screen coordinates. + */ + mousePos.x = LOWORD(lParam); + mousePos.y = HIWORD(lParam); + ClientToScreen(hwnd, &mousePos); + + /* + * Notify everyone that the button state changed + * TODO: Check if the "escape" key was pressed. + */ + OLEDD_TrackStateChange(trackerInfo, mousePos, wParam); + + break; + } + } + + /* + * This is a window proc after all. Let's call the default. + */ + return DefWindowProcA (hwnd, uMsg, wParam, lParam); +} + +/*** + * OLEDD_TrackMouseMove() + * + * This method is invoked while a drag and drop operation is in effect. + * it will generate the appropriate callbacks in the drop source + * and drop target. It will also provide the expected feedback to + * the user. + * + * params: + * trackerInfo - Pointer to the structure identifying the + * drag & drop operation that is currently + * active. + * mousePos - Current position of the mouse in screen + * coordinates. + * keyState - Contains the state of the shift keys and the + * mouse buttons (MK_LBUTTON and the like) + */ +static void OLEDD_TrackMouseMove( + TrackerWindowInfo* trackerInfo, + POINT mousePos, + DWORD keyState) +{ + HWND hwndNewTarget = 0; + HRESULT hr = S_OK; + + /* + * Get the handle of the window under the mouse + */ + hwndNewTarget = WindowFromPoint(mousePos); + + /* + * Every time, we re-initialize the effects passed to the + * IDropTarget to the effects allowed by the source. + */ + *trackerInfo->pdwEffect = trackerInfo->dwOKEffect; + + /* + * If we are hovering over the same target as before, send the + * DragOver notification + */ + if ( (trackerInfo->curDragTarget != 0) && + (trackerInfo->curDragTargetHWND==hwndNewTarget) ) + { + POINTL mousePosParam; + + /* + * The documentation tells me that the coordinate should be in the target + * window's coordinate space. However, the tests I made tell me the + * coordinates should be in screen coordinates. + */ + mousePosParam.x = mousePos.x; + mousePosParam.y = mousePos.y; + + IDropTarget_DragOver(trackerInfo->curDragTarget, + keyState, + mousePosParam, + trackerInfo->pdwEffect); + } + else + { + DropTargetNode* newDropTargetNode = 0; + + /* + * If we changed window, we have to notify our old target and check for + * the new one. + */ + if (trackerInfo->curDragTarget!=0) + { + IDropTarget_DragLeave(trackerInfo->curDragTarget); + } + + /* + * Make sure we're hovering over a window. + */ + if (hwndNewTarget!=0) + { + /* + * Find-out if there is a drag target under the mouse + */ + HWND nexttar = hwndNewTarget; + do { + newDropTargetNode = OLEDD_FindDropTarget(nexttar); + } while (!newDropTargetNode && (nexttar = GetParent(nexttar)) != 0); + if(nexttar) hwndNewTarget = nexttar; + + trackerInfo->curDragTargetHWND = hwndNewTarget; + trackerInfo->curDragTarget = newDropTargetNode ? newDropTargetNode->dropTarget : 0; + + /* + * If there is, notify it that we just dragged-in + */ + if (trackerInfo->curDragTarget!=0) + { + POINTL mousePosParam; + + /* + * The documentation tells me that the coordinate should be in the target + * window's coordinate space. However, the tests I made tell me the + * coordinates should be in screen coordinates. + */ + mousePosParam.x = mousePos.x; + mousePosParam.y = mousePos.y; + + IDropTarget_DragEnter(trackerInfo->curDragTarget, + trackerInfo->dataObject, + keyState, + mousePosParam, + trackerInfo->pdwEffect); + } + } + else + { + /* + * The mouse is not over a window so we don't track anything. + */ + trackerInfo->curDragTargetHWND = 0; + trackerInfo->curDragTarget = 0; + } + } + + /* + * Now that we have done that, we have to tell the source to give + * us feedback on the work being done by the target. If we don't + * have a target, simulate no effect. + */ + if (trackerInfo->curDragTarget==0) + { + *trackerInfo->pdwEffect = DROPEFFECT_NONE; + } + + hr = IDropSource_GiveFeedback(trackerInfo->dropSource, + *trackerInfo->pdwEffect); + + /* + * When we ask for feedback from the drop source, sometimes it will + * do all the necessary work and sometimes it will not handle it + * when that's the case, we must display the standard drag and drop + * cursors. + */ + if (hr==DRAGDROP_S_USEDEFAULTCURSORS) + { + if (*trackerInfo->pdwEffect & DROPEFFECT_MOVE) + { + SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCE(1))); + } + else if (*trackerInfo->pdwEffect & DROPEFFECT_COPY) + { + SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCE(2))); + } + else if (*trackerInfo->pdwEffect & DROPEFFECT_LINK) + { + SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCE(3))); + } + else + { + SetCursor(LoadCursorA(OLE32_hInstance, MAKEINTRESOURCE(0))); + } + } +} + +/*** + * OLEDD_TrackStateChange() + * + * This method is invoked while a drag and drop operation is in effect. + * It is used to notify the drop target/drop source callbacks when + * the state of the keyboard or mouse button change. + * + * params: + * trackerInfo - Pointer to the structure identifying the + * drag & drop operation that is currently + * active. + * mousePos - Current position of the mouse in screen + * coordinates. + * keyState - Contains the state of the shift keys and the + * mouse buttons (MK_LBUTTON and the like) + */ +static void OLEDD_TrackStateChange( + TrackerWindowInfo* trackerInfo, + POINT mousePos, + DWORD keyState) +{ + /* + * Ask the drop source what to do with the operation. + */ + trackerInfo->returnValue = IDropSource_QueryContinueDrag( + trackerInfo->dropSource, + trackerInfo->escPressed, + keyState); + + /* + * All the return valued will stop the operation except the S_OK + * return value. + */ + if (trackerInfo->returnValue!=S_OK) + { + /* + * Make sure the message loop in DoDragDrop stops + */ + trackerInfo->trackingDone = TRUE; + + /* + * Release the mouse in case the drop target decides to show a popup + * or a menu or something. + */ + ReleaseCapture(); + + /* + * If we end-up over a target, drop the object in the target or + * inform the target that the operation was cancelled. + */ + if (trackerInfo->curDragTarget!=0) + { + switch (trackerInfo->returnValue) + { + /* + * If the source wants us to complete the operation, we tell + * the drop target that we just dropped the object in it. + */ + case DRAGDROP_S_DROP: + { + POINTL mousePosParam; + + /* + * The documentation tells me that the coordinate should be + * in the target window's coordinate space. However, the tests + * I made tell me the coordinates should be in screen coordinates. + */ + mousePosParam.x = mousePos.x; + mousePosParam.y = mousePos.y; + + IDropTarget_Drop(trackerInfo->curDragTarget, + trackerInfo->dataObject, + keyState, + mousePosParam, + trackerInfo->pdwEffect); + break; + } + /* + * If the source told us that we should cancel, fool the drop + * target by telling it that the mouse left it's window. + * Also set the drop effect to "NONE" in case the application + * ignores the result of DoDragDrop. + */ + case DRAGDROP_S_CANCEL: + IDropTarget_DragLeave(trackerInfo->curDragTarget); + *trackerInfo->pdwEffect = DROPEFFECT_NONE; + break; + } + } + } +} + +/*** + * OLEDD_GetButtonState() + * + * This method will use the current state of the keyboard to build + * a button state mask equivalent to the one passed in the + * WM_MOUSEMOVE wParam. + */ +static DWORD OLEDD_GetButtonState() +{ + BYTE keyboardState[256]; + DWORD keyMask = 0; + + GetKeyboardState(keyboardState); + + if ( (keyboardState[VK_SHIFT] & 0x80) !=0) + keyMask |= MK_SHIFT; + + if ( (keyboardState[VK_CONTROL] & 0x80) !=0) + keyMask |= MK_CONTROL; + + if ( (keyboardState[VK_LBUTTON] & 0x80) !=0) + keyMask |= MK_LBUTTON; + + if ( (keyboardState[VK_RBUTTON] & 0x80) !=0) + keyMask |= MK_RBUTTON; + + if ( (keyboardState[VK_MBUTTON] & 0x80) !=0) + keyMask |= MK_MBUTTON; + + return keyMask; +} + +/*** + * OLEDD_GetButtonState() + * + * This method will read the default value of the registry key in + * parameter and extract a DWORD value from it. The registry key value + * can be in a string key or a DWORD key. + * + * params: + * regKey - Key to read the default value from + * pdwValue - Pointer to the location where the DWORD + * value is returned. This value is not modified + * if the value is not found. + */ + +static void OLEUTL_ReadRegistryDWORDValue( + HKEY regKey, + DWORD* pdwValue) +{ + char buffer[20]; + DWORD dwKeyType; + DWORD cbData = 20; + LONG lres; + + lres = RegQueryValueExA(regKey, + "", + NULL, + &dwKeyType, + (LPBYTE)buffer, + &cbData); + + if (lres==ERROR_SUCCESS) + { + switch (dwKeyType) + { + case REG_DWORD: + *pdwValue = *(DWORD*)buffer; + break; + case REG_EXPAND_SZ: + case REG_MULTI_SZ: + case REG_SZ: + *pdwValue = (DWORD)strtoul(buffer, NULL, 10); + break; + } + } +} + +/****************************************************************************** + * OleMetaFilePictFromIconAndLabel + * + * Returns a global memory handle to a metafile which contains the icon and + * label given. + * I guess the result of that should look somehow like desktop icons. + * If no hIcon is given, we load the icon via lpszSourceFile and iIconIndex. + * This code might be wrong at some places. + */ +DWORD WINAPI OleMetaFilePictFromIconAndLabel16( + DWORD hIcon, + PVOID lpszLabel, + PVOID lpszSourceFile, + DWORD iIconIndex +) { + UNIMPLEMENTED; + return 0; +} + +/****************************************************************************** + * DllDebugObjectRPCHook + * turns on and off internal debugging, pointer is only used on macintosh + */ + +BOOL WINAPI DllDebugObjectRPCHook(BOOL b, void *dummy) +{ + Print(MIN_TRACE, ("stub\n")); + return TRUE; +} + +#endif diff --git a/lib/ole32/Ole32.h b/lib/ole32/Ole32.h new file mode 100644 index 0000000..75473ec --- /dev/null +++ b/lib/ole32/Ole32.h @@ -0,0 +1,43 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib\ole32\Ole32.h + * PURPOSE: The internal include file for the ole32.dll + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#ifndef _OLE32 +#define _OLE32 + + +// include windows stuff +#include +//#include +//#include +#include +//#include +#include + + +#endif diff --git a/lib/ole32/OleAuto.c b/lib/ole32/OleAuto.c new file mode 100644 index 0000000..a7cf73a --- /dev/null +++ b/lib/ole32/OleAuto.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib\ole32\oleauto.c + * PURPOSE: Ole automation helper functions + * PROGRAMMER: jurgen van gael [jurgen.vangael@student.kuleuven.ac.be] + * UPDATE HISTORY: + * Created 01/05/2001 + */ +/******************************************************************** + + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + +********************************************************************/ +#include "Ole32.h" + +/*WINOLEAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo){return S_OK;} +WINOLEAPI GetErrorInfo( + DWORD dwReserved, + IErrorInfo **pperrinfo +){return S_OK;}*/ diff --git a/lib/ole32/Storage.c b/lib/ole32/Storage.c new file mode 100644 index 0000000..e0a2f00 --- /dev/null +++ b/lib/ole32/Storage.c @@ -0,0 +1,778 @@ +/* Compound Storage + * + * Implemented using the documentation of the LAOLA project at + * + * (Thanks to Martin Schwartz ) + * + * Copyright 1998 Marcus Meissner + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct storage_header { + BYTE magic[8]; /* 00: magic */ + BYTE unknown1[36]; /* 08: unknown */ + DWORD num_of_bbd_blocks;/* 2C: length of big datablocks */ + DWORD root_startblock;/* 30: root storage first big block */ + DWORD unknown2[2]; /* 34: unknown */ + DWORD sbd_startblock; /* 3C: small block depot first big block */ + DWORD unknown3[3]; /* 40: unknown */ + DWORD bbd_list[109]; /* 4C: big data block list (up to end of sector)*/ +}; +struct storage_pps_entry { + WCHAR pps_rawname[32];/* 00: \0 terminated widechar name */ + WORD pps_sizeofname; /* 40: namelength in bytes */ + BYTE pps_type; /* 42: flags, 1 storage/dir, 2 stream, 5 root */ + BYTE pps_unknown0; /* 43: unknown */ + DWORD pps_prev; /* 44: previous pps */ + DWORD pps_next; /* 48: next pps */ + DWORD pps_dir; /* 4C: directory pps */ + GUID pps_guid; /* 50: class ID */ + DWORD pps_unknown1; /* 60: unknown */ + FILETIME pps_ft1; /* 64: filetime1 */ + FILETIME pps_ft2; /* 70: filetime2 */ + DWORD pps_sb; /* 74: data startblock */ + DWORD pps_size; /* 78: datalength. (<0x1000)?small:big blocks*/ + DWORD pps_unknown2; /* 7C: unknown */ +}; + +#define STORAGE_CHAINENTRY_FAT 0xfffffffd +#define STORAGE_CHAINENTRY_ENDOFCHAIN 0xfffffffe +#define STORAGE_CHAINENTRY_FREE 0xffffffff + + +//static const BYTE STORAGE_magic[8] ={0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1}; +//static const BYTE STORAGE_notmagic[8]={0x0e,0x11,0xfc,0x0d,0xd0,0xcf,0x11,0xe0}; +//static const BYTE STORAGE_oldmagic[8]={0xd0,0xcf,0x11,0xe0,0x0e,0x11,0xfc,0x0d}; + +#define BIGSIZE 512 +#define SMALLSIZE 64 + +#define SMALLBLOCKS_PER_BIGBLOCK (BIGSIZE/SMALLSIZE) + +#define READ_HEADER assert(STORAGE_get_big_block(hf,-1,(LPBYTE)&sth));assert(!memcmp(STORAGE_magic,sth.magic,sizeof(STORAGE_magic))); +static ICOM_VTABLE(IStorage16) stvt16; +static ICOM_VTABLE(IStorage16) *segstvt16 = NULL; +static ICOM_VTABLE(IStream16) strvt16; +static ICOM_VTABLE(IStream16) *segstrvt16 = NULL; + +/*ULONG WINAPI IStorage16_AddRef(LPSTORAGE16 this);*/ +static void _create_istorage16(LPSTORAGE16 *stg); +static void _create_istream16(LPSTREAM16 *str); + +#define IMPLEMENTED 1 + + +/****************************************************************************** + * STORAGE_get_big_block [Internal] + * + * Reading OLE compound storage + */ +static BOOL +STORAGE_get_big_block(HFILE hf,int n,BYTE *block) { + assert(n>=-1); + if (-1==_llseek(hf,(n+1)*BIGSIZE,SEEK_SET)) { + Print(MID_TRACE, (" seek failed (%ld)\n",GetLastError())); + return FALSE; + } + assert((n+1)*BIGSIZE==_llseek(hf,0,SEEK_CUR)); + if (BIGSIZE!=_lread(hf,block,BIGSIZE)) { + Print(MID_TRACE, ("(block size %d): read didn't read (%ld)\n",n,GetLastError())); + assert(0); + return FALSE; + } + return TRUE; +} + +/****************************************************************************** + * STORAGE_put_big_block [INTERNAL] + */ +static BOOL +STORAGE_put_big_block(HFILE hf,int n,BYTE *block) { + assert(n>=-1); + if (-1==_llseek(hf,(n+1)*BIGSIZE,SEEK_SET)) { + Print(MID_TRACE, (" seek failed (%ld)\n",GetLastError())); + return FALSE; + } + assert((n+1)*BIGSIZE==_llseek(hf,0,SEEK_CUR)); + if (BIGSIZE!=_lwrite(hf,block,BIGSIZE)) { + Print(MID_TRACE, (" write failed (%ld)\n",GetLastError())); + return FALSE; + } + return TRUE; +} + +/****************************************************************************** + * STORAGE_get_next_big_blocknr [INTERNAL] + */ +static int +STORAGE_get_next_big_blocknr(HFILE hf,int blocknr) { + INT bbs[BIGSIZE/sizeof(INT)]; + struct storage_header sth; + + READ_HEADER; + + assert(blocknr>>7>7]==0xffffffff) + return -5; + if (!STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs)) + return -5; + assert(bbs[blocknr&0x7f]!=STORAGE_CHAINENTRY_FREE); + return bbs[blocknr&0x7f]; +} + +/****************************************************************************** + * STORAGE_get_nth_next_big_blocknr [INTERNAL] + */ +static int +STORAGE_get_nth_next_big_blocknr(HFILE hf,int blocknr,int nr) { + INT bbs[BIGSIZE/sizeof(INT)]; + int lastblock = -1; + struct storage_header sth; + + READ_HEADER; + + assert(blocknr>=0); + while (nr--) { + assert((blocknr>>7)>7]!=0xffffffff); + + /* simple caching... */ + if (lastblock!=sth.bbd_list[blocknr>>7]) { + assert(STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs)); + lastblock = sth.bbd_list[blocknr>>7]; + } + blocknr = bbs[blocknr&0x7f]; + } + return blocknr; +} + +/****************************************************************************** + * STORAGE_get_root_pps_entry [Internal] + */ +static BOOL +STORAGE_get_root_pps_entry(HFILE hf,struct storage_pps_entry *pstde) { + int blocknr,i; + BYTE block[BIGSIZE]; + struct storage_pps_entry *stde=(struct storage_pps_entry*)block; + struct storage_header sth; + + READ_HEADER; + blocknr = sth.root_startblock; + while (blocknr>=0) { + assert(STORAGE_get_big_block(hf,blocknr,block)); + for (i=0;i<4;i++) { + if (!stde[i].pps_sizeofname) + continue; + if (stde[i].pps_type==5) { + *pstde=stde[i]; + return TRUE; + } + } + blocknr=STORAGE_get_next_big_blocknr(hf,blocknr); + } + return FALSE; +} + +/****************************************************************************** + * STORAGE_get_small_block [INTERNAL] + */ +static BOOL +STORAGE_get_small_block(HFILE hf,int blocknr,BYTE *sblock) { + BYTE block[BIGSIZE]; + int bigblocknr; + struct storage_pps_entry root; + + assert(blocknr>=0); + assert(STORAGE_get_root_pps_entry(hf,&root)); + bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK); + assert(bigblocknr>=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + + memcpy(sblock,((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),SMALLSIZE); + return TRUE; +} + +/****************************************************************************** + * STORAGE_put_small_block [INTERNAL] + */ +static BOOL +STORAGE_put_small_block(HFILE hf,int blocknr,BYTE *sblock) { + BYTE block[BIGSIZE]; + int bigblocknr; + struct storage_pps_entry root; + + assert(blocknr>=0); + + assert(STORAGE_get_root_pps_entry(hf,&root)); + bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK); + assert(bigblocknr>=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + + memcpy(((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),sblock,SMALLSIZE); + assert(STORAGE_put_big_block(hf,bigblocknr,block)); + return TRUE; +} + +/****************************************************************************** + * STORAGE_get_next_small_blocknr [INTERNAL] + */ +static int +STORAGE_get_next_small_blocknr(HFILE hf,int blocknr) { + BYTE block[BIGSIZE]; + LPINT sbd = (LPINT)block; + int bigblocknr; + struct storage_header sth; + + READ_HEADER; + assert(blocknr>=0); + bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128); + assert(bigblocknr>=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + assert(sbd[blocknr & 127]!=STORAGE_CHAINENTRY_FREE); + return sbd[blocknr & (128-1)]; +} + +/****************************************************************************** + * STORAGE_get_nth_next_small_blocknr [INTERNAL] + */ +static int +STORAGE_get_nth_next_small_blocknr(HFILE hf,int blocknr,int nr) { + int lastblocknr; + BYTE block[BIGSIZE]; + LPINT sbd = (LPINT)block; + struct storage_header sth; + + READ_HEADER; + lastblocknr=-1; + assert(blocknr>=0); + while ((nr--) && (blocknr>=0)) { + if (lastblocknr/128!=blocknr/128) { + int bigblocknr; + bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128); + assert(bigblocknr>=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + lastblocknr = blocknr; + } + assert(lastblocknr>=0); + lastblocknr=blocknr; + blocknr=sbd[blocknr & (128-1)]; + assert(blocknr!=STORAGE_CHAINENTRY_FREE); + } + return blocknr; +} + +/****************************************************************************** + * STORAGE_get_pps_entry [INTERNAL] + */ +static int +STORAGE_get_pps_entry(HFILE hf,int n,struct storage_pps_entry *pstde) { + int blocknr; + BYTE block[BIGSIZE]; + struct storage_pps_entry *stde = (struct storage_pps_entry*)(((LPBYTE)block)+128*(n&3)); + struct storage_header sth; + + READ_HEADER; + /* we have 4 pps entries per big block */ + blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4); + assert(blocknr>=0); + assert(STORAGE_get_big_block(hf,blocknr,block)); + + *pstde=*stde; + return 1; +} + +/****************************************************************************** + * STORAGE_put_pps_entry [Internal] + */ +static int +STORAGE_put_pps_entry(HFILE hf,int n,struct storage_pps_entry *pstde) { + int blocknr; + BYTE block[BIGSIZE]; + struct storage_pps_entry *stde = (struct storage_pps_entry*)(((LPBYTE)block)+128*(n&3)); + struct storage_header sth; + + READ_HEADER; + + /* we have 4 pps entries per big block */ + blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4); + assert(blocknr>=0); + assert(STORAGE_get_big_block(hf,blocknr,block)); + *stde=*pstde; + assert(STORAGE_put_big_block(hf,blocknr,block)); + return 1; +} + +/****************************************************************************** + * STORAGE_look_for_named_pps [Internal] + */ +static int +STORAGE_look_for_named_pps(HFILE hf,int n,LPOLESTR name) { + struct storage_pps_entry stde; + int ret; + + if (n==-1) + return -1; + if (1!=STORAGE_get_pps_entry(hf,n,&stde)) + return -1; + + if (!lstrcmpW(name,stde.pps_rawname)) + return n; + if (stde.pps_prev != -1) { + ret=STORAGE_look_for_named_pps(hf,stde.pps_prev,name); + if (ret!=-1) + return ret; + } + if (stde.pps_next != -1) { + ret=STORAGE_look_for_named_pps(hf,stde.pps_next,name); + if (ret!=-1) + return ret; + } + return -1; +} + +/****************************************************************************** + * STORAGE_dump_pps_entry [Internal] + * + * FIXME + * Function is unused + */ +void +STORAGE_dump_pps_entry(struct storage_pps_entry *stde) { +#if 0 + char name[33]; + + WideCharToMultiByte( CP_ACP, 0, stde->pps_rawname, -1, name, sizeof(name), NULL, NULL); + if (!stde->pps_sizeofname) + return; + Print(MAX_TRACE, ("name: %s\n",name)); + Print(MAX_TRACE, ("type: %d\n",stde->pps_type)); + Print(MAX_TRACE, ("prev pps: %ld\n",stde->pps_prev)); + Print(MAX_TRACE, ("next pps: %ld\n",stde->pps_next)); + Print(MAX_TRACE, ("dir pps: %ld\n",stde->pps_dir)); + Print(MAX_TRACE, ("guid: %s\n",PRINT_GUID(&(stde->pps_guid)))); + if (stde->pps_type !=2) { + time_t t; + DWORD dw; + RtlTimeToSecondsSince1970(&(stde->pps_ft1),&dw); + t = dw; + Print(MAX_TRACE, ("ts1: %s\n",ctime(&t))); + RtlTimeToSecondsSince1970(&(stde->pps_ft2),&dw); + t = dw; + Print(MAX_TRACE, ("ts2: %s\n",ctime(&t))); + } + Print(MAX_TRACE, ("startblock: %ld\n",stde->pps_sb)); + Print(MAX_TRACE, ("size: %ld\n",stde->pps_size)); +#endif +} + +/****************************************************************************** + * STORAGE_init_storage [INTERNAL] + */ +static BOOL +STORAGE_init_storage(HFILE hf) { + BYTE block[BIGSIZE]; + LPDWORD bbs; + struct storage_header *sth; + struct storage_pps_entry *stde; + + assert(-1!=_llseek(hf,0,SEEK_SET)); + /* block -1 is the storage header */ + sth = (struct storage_header*)block; + memcpy(sth->magic,STORAGE_magic,8); + memset(sth->unknown1,0,sizeof(sth->unknown1)); + memset(sth->unknown2,0,sizeof(sth->unknown2)); + memset(sth->unknown3,0,sizeof(sth->unknown3)); + sth->num_of_bbd_blocks = 1; + sth->root_startblock = 1; + sth->sbd_startblock = 0xffffffff; + memset(sth->bbd_list,0xff,sizeof(sth->bbd_list)); + sth->bbd_list[0] = 0; + assert(BIGSIZE==_lwrite(hf,block,BIGSIZE)); + /* block 0 is the big block directory */ + bbs=(LPDWORD)block; + memset(block,0xff,sizeof(block)); /* mark all blocks as free */ + bbs[0]=STORAGE_CHAINENTRY_ENDOFCHAIN; /* for this block */ + bbs[1]=STORAGE_CHAINENTRY_ENDOFCHAIN; /* for directory entry */ + assert(BIGSIZE==_lwrite(hf,block,BIGSIZE)); + /* block 1 is the root directory entry */ + memset(block,0x00,sizeof(block)); + stde = (struct storage_pps_entry*)block; + MultiByteToWideChar( CP_ACP, 0, "RootEntry", -1, stde->pps_rawname, + sizeof(stde->pps_rawname)/sizeof(WCHAR)); + stde->pps_sizeofname = (lstrlenW(stde->pps_rawname)+1) * sizeof(WCHAR); + stde->pps_type = 5; + stde->pps_dir = -1; + stde->pps_next = -1; + stde->pps_prev = -1; + stde->pps_sb = 0xffffffff; + stde->pps_size = 0; + assert(BIGSIZE==_lwrite(hf,block,BIGSIZE)); + return TRUE; +} + +/****************************************************************************** + * STORAGE_set_big_chain [Internal] + */ +static BOOL +STORAGE_set_big_chain(HFILE hf,int blocknr,INT type) { + BYTE block[BIGSIZE]; + LPINT bbd = (LPINT)block; + int nextblocknr,bigblocknr; + struct storage_header sth; + + READ_HEADER; + assert(blocknr!=type); + while (blocknr>=0) { + bigblocknr = sth.bbd_list[blocknr/128]; + assert(bigblocknr>=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + + nextblocknr = bbd[blocknr&(128-1)]; + bbd[blocknr&(128-1)] = type; + if (type>=0) + return TRUE; + assert(STORAGE_put_big_block(hf,bigblocknr,block)); + type = STORAGE_CHAINENTRY_FREE; + blocknr = nextblocknr; + } + return TRUE; +} + +/****************************************************************************** + * STORAGE_set_small_chain [Internal] + */ +static BOOL +STORAGE_set_small_chain(HFILE hf,int blocknr,INT type) { + BYTE block[BIGSIZE]; + LPINT sbd = (LPINT)block; + int lastblocknr,nextsmallblocknr,bigblocknr; + struct storage_header sth; + + READ_HEADER; + + assert(blocknr!=type); + lastblocknr=-129;bigblocknr=-2; + while (blocknr>=0) { + /* cache block ... */ + if (lastblocknr/128!=blocknr/128) { + bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128); + assert(bigblocknr>=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + } + lastblocknr = blocknr; + nextsmallblocknr = sbd[blocknr&(128-1)]; + sbd[blocknr&(128-1)] = type; + assert(STORAGE_put_big_block(hf,bigblocknr,block)); + if (type>=0) + return TRUE; + type = STORAGE_CHAINENTRY_FREE; + blocknr = nextsmallblocknr; + } + return TRUE; +} + +/****************************************************************************** + * STORAGE_get_free_big_blocknr [Internal] + */ +static int +STORAGE_get_free_big_blocknr(HFILE hf) { + BYTE block[BIGSIZE]; + LPINT sbd = (LPINT)block; + int lastbigblocknr,i,curblock,bigblocknr; + struct storage_header sth; + + READ_HEADER; + curblock = 0; + lastbigblocknr = -1; + bigblocknr = sth.bbd_list[curblock]; + while (curblock=0); + assert(STORAGE_get_big_block(hf,bigblocknr,block)); + for (i=0;i<128;i++) + if (sbd[i]==STORAGE_CHAINENTRY_FREE) { + sbd[i] = STORAGE_CHAINENTRY_ENDOFCHAIN; + assert(STORAGE_put_big_block(hf,bigblocknr,block)); + memset(block,0x42,sizeof(block)); + assert(STORAGE_put_big_block(hf,i+curblock*128,block)); + return i+curblock*128; + } + lastbigblocknr = bigblocknr; + bigblocknr = sth.bbd_list[++curblock]; + } + bigblocknr = curblock*128; + /* since we have marked all blocks from 0 up to curblock*128-1 + * the next free one is curblock*128, where we happily put our + * next large block depot. + */ + memset(block,0xff,sizeof(block)); + /* mark the block allocated and returned by this function */ + sbd[1] = STORAGE_CHAINENTRY_ENDOFCHAIN; + assert(STORAGE_put_big_block(hf,bigblocknr,block)); + + /* if we had a bbd block already (mostlikely) we need + * to link the new one into the chain + */ + if (lastbigblocknr!=-1) + assert(STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr)); + sth.bbd_list[curblock]=bigblocknr; + sth.num_of_bbd_blocks++; + assert(sth.num_of_bbd_blocks==curblock+1); + assert(STORAGE_put_big_block(hf,-1,(LPBYTE)&sth)); + + /* Set the end of the chain for the bigblockdepots */ + assert(STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN)); + /* add 1, for the first entry is used for the additional big block + * depot. (means we already used bigblocknr) */ + memset(block,0x42,sizeof(block)); + /* allocate this block (filled with 0x42) */ + assert(STORAGE_put_big_block(hf,bigblocknr+1,block)); + return bigblocknr+1; +} + + +/****************************************************************************** + * STORAGE_get_free_small_blocknr [Internal] + */ +static int +STORAGE_get_free_small_blocknr(HFILE hf) { + BYTE block[BIGSIZE]; + LPINT sbd = (LPINT)block; + int lastbigblocknr,newblocknr,i,curblock,bigblocknr; + struct storage_pps_entry root; + struct storage_header sth; + + READ_HEADER; + bigblocknr = sth.sbd_startblock; + curblock = 0; + lastbigblocknr = -1; + newblocknr = -1; + while (bigblocknr>=0) { + if (!STORAGE_get_big_block(hf,bigblocknr,block)) + return -1; + for (i=0;i<128;i++) + if (sbd[i]==STORAGE_CHAINENTRY_FREE) { + sbd[i]=STORAGE_CHAINENTRY_ENDOFCHAIN; + newblocknr = i+curblock*128; + break; + } + if (i!=128) + break; + lastbigblocknr = bigblocknr; + bigblocknr = STORAGE_get_next_big_blocknr(hf,bigblocknr); + curblock++; + } + if (newblocknr==-1) { + bigblocknr = STORAGE_get_free_big_blocknr(hf); + if (bigblocknr<0) + return -1; + READ_HEADER; + memset(block,0xff,sizeof(block)); + sbd[0]=STORAGE_CHAINENTRY_ENDOFCHAIN; + if (!STORAGE_put_big_block(hf,bigblocknr,block)) + return -1; + if (lastbigblocknr==-1) { + sth.sbd_startblock = bigblocknr; + if (!STORAGE_put_big_block(hf,-1,(LPBYTE)&sth)) /* need to write it */ + return -1; + } else { + if (!STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr)) + return -1; + } + if (!STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN)) + return -1; + newblocknr = curblock*128; + } + /* allocate enough big blocks for storing the allocated small block */ + if (!STORAGE_get_root_pps_entry(hf,&root)) + return -1; + if (root.pps_sb==-1) + lastbigblocknr = -1; + else + lastbigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,(root.pps_size-1)/BIGSIZE); + while (root.pps_size < (newblocknr*SMALLSIZE+SMALLSIZE-1)) { + /* we need to allocate more stuff */ + bigblocknr = STORAGE_get_free_big_blocknr(hf); + if (bigblocknr<0) + return -1; + READ_HEADER; + if (root.pps_sb==-1) { + root.pps_sb = bigblocknr; + root.pps_size += BIGSIZE; + } else { + if (!STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr)) + return -1; + root.pps_size += BIGSIZE; + } + lastbigblocknr = bigblocknr; + } + if (!STORAGE_set_big_chain(hf,lastbigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN)) + return -1; + if (!STORAGE_put_pps_entry(hf,0,&root)) + return -1; + return newblocknr; +} + +/****************************************************************************** + * STORAGE_get_free_pps_entry [Internal] + */ +static int +STORAGE_get_free_pps_entry(HFILE hf) { + int blocknr,i,curblock,lastblocknr; + BYTE block[BIGSIZE]; + struct storage_pps_entry *stde = (struct storage_pps_entry*)block; + struct storage_header sth; + + READ_HEADER; + blocknr = sth.root_startblock; + assert(blocknr>=0); + curblock=0; + while (blocknr>=0) { + if (!STORAGE_get_big_block(hf,blocknr,block)) + return -1; + for (i=0;i<4;i++) + if (stde[i].pps_sizeofname==0) /* free */ + return curblock*4+i; + lastblocknr = blocknr; + blocknr = STORAGE_get_next_big_blocknr(hf,blocknr); + curblock++; + } + assert(blocknr==STORAGE_CHAINENTRY_ENDOFCHAIN); + blocknr = STORAGE_get_free_big_blocknr(hf); + /* sth invalidated */ + if (blocknr<0) + return -1; + + if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr)) + return -1; + if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN)) + return -1; + memset(block,0,sizeof(block)); + STORAGE_put_big_block(hf,blocknr,block); + return curblock*4; +} + +/* --- IStream32 implementation */ + +typedef struct +{ + /* IUnknown fields */ + ICOM_VFIELD(IStream); + DWORD ref; + /* IStream32 fields */ + struct storage_pps_entry stde; + int ppsent; + HFILE hf; + ULARGE_INTEGER offset; +} IStream32Impl; + +/***************************************************************************** + * IStream32_QueryInterface [VTABLE] + */ +HRESULT WINAPI IStream_fnQueryInterface( + IStream* iface,REFIID refiid,LPVOID *obj +) { + ICOM_THIS(IStream32Impl,iface); + + Print(MAX_TRACE, ("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj)); + if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) { + *obj = This; + return 0; + } + return OLE_E_ENUM_NOMORE; + +} + +/****************************************************************************** + * IStream32_AddRef [VTABLE] + */ +ULONG WINAPI IStream_fnAddRef(IStream* iface) { + ICOM_THIS(IStream32Impl,iface); + return ++(This->ref); +} + +/****************************************************************************** + * IStream32_Release [VTABLE] + */ +ULONG WINAPI IStream_fnRelease(IStream* iface) { +#if 0 + ICOM_THIS(IStream32Impl,iface); + FlushFileBuffers(This->hf); + This->ref--; + if (!This->ref) { + CloseHandle(This->hf); + SEGPTR_FREE(This); + return 0; + } + return This->ref; +#else + UNIMPLEMENTED; + return 0; +#endif +} + + +/****************************************************************************** + * Storage API functions + */ + +/****************************************************************************** + * StgCreateDocFile16 [STORAGE.1] + */ +HRESULT WINAPI StgCreateDocFile16( + LPCOLESTR16 pwcsName,DWORD grfMode,DWORD reserved,IStorage16 **ppstgOpen +) { + UNIMPLEMENTED; + return S_OK; +} + +/****************************************************************************** + * StgIsStorageFile16 [STORAGE.5] + */ +HRESULT WINAPI StgIsStorageFile16(LPCOLESTR16 fn) { + UNIMPLEMENTED; + return S_OK; +} + +/****************************************************************************** + * StgIsStorageFile [OLE32.146] + */ +HRESULT WINAPI +StgIsStorageFile(LPCOLESTR fn) +{ +#if 0 + LPOLESTR16 xfn = HEAP_strdupWtoA(GetProcessHeap(),0,fn); + HRESULT ret = StgIsStorageFile16(xfn); + + HeapFree(GetProcessHeap(),0,xfn); + return ret; +#else + UNIMPLEMENTED; + return S_OK; +#endif +} + + +/****************************************************************************** + * StgOpenStorage16 [STORAGE.3] + */ +HRESULT WINAPI StgOpenStorage16( + LPCOLESTR16 pwcsName,IStorage16 *pstgPriority,DWORD grfMode, + SNB16 snbExclude,DWORD reserved, IStorage16 **ppstgOpen +) { + UNIMPLEMENTED; + return S_OK; +} + + diff --git a/lib/ole32/antimoniker.c b/lib/ole32/antimoniker.c new file mode 100644 index 0000000..67e3326 --- /dev/null +++ b/lib/ole32/antimoniker.c @@ -0,0 +1,645 @@ +/*************************************************************************************** + * AntiMonikers implementation + * + * Copyright 1999 Noomen Hamza + ***************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + + +/* AntiMoniker data structure */ +typedef struct AntiMonikerImpl{ + + ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/ + + /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether + * two monikers are equal. That's whay IROTData interface is implemented by monikers. + */ + ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/ + + ULONG ref; /* reference counter for this object */ + +} AntiMonikerImpl; + +/********************************************************************************/ +/* AntiMoniker prototype functions : */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker* iface); +static ULONG WINAPI AntiMonikerImpl_Release(IMoniker* iface); + +/* IPersist prototype functions */ +static HRESULT WINAPI AntiMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID); + +/* IPersistStream prototype functions */ +static HRESULT WINAPI AntiMonikerImpl_IsDirty(IMoniker* iface); +static HRESULT WINAPI AntiMonikerImpl_Load(IMoniker* iface, IStream* pStm); +static HRESULT WINAPI AntiMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty); +static HRESULT WINAPI AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize); + +/* IMoniker prototype functions */ +static HRESULT WINAPI AntiMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI AntiMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI AntiMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced); +static HRESULT WINAPI AntiMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite); +static HRESULT WINAPI AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker); +static HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker); +static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash); +static HRESULT WINAPI AntiMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning); +static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pAntiTime); +static HRESULT WINAPI AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk); +static HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix); +static HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath); +static HRESULT WINAPI AntiMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName); +static HRESULT WINAPI AntiMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut); +static HRESULT WINAPI AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys); + +/********************************************************************************/ +/* IROTData prototype functions */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI AntiMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject); +static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData* iface); +static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface); + +/* IROTData prototype function */ +static HRESULT WINAPI AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); + +/* Local function used by AntiMoniker implementation */ +HRESULT WINAPI AntiMonikerImpl_Construct(AntiMonikerImpl* iface); +HRESULT WINAPI AntiMonikerImpl_Destroy(AntiMonikerImpl* iface); + +/********************************************************************************/ +/* Virtual function table for the AntiMonikerImpl class which include IPersist,*/ +/* IPersistStream and IMoniker functions. */ +static ICOM_VTABLE(IMoniker) VT_AntiMonikerImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + AntiMonikerImpl_QueryInterface, + AntiMonikerImpl_AddRef, + AntiMonikerImpl_Release, + AntiMonikerImpl_GetClassID, + AntiMonikerImpl_IsDirty, + AntiMonikerImpl_Load, + AntiMonikerImpl_Save, + AntiMonikerImpl_GetSizeMax, + AntiMonikerImpl_BindToObject, + AntiMonikerImpl_BindToStorage, + AntiMonikerImpl_Reduce, + AntiMonikerImpl_ComposeWith, + AntiMonikerImpl_Enum, + AntiMonikerImpl_IsEqual, + AntiMonikerImpl_Hash, + AntiMonikerImpl_IsRunning, + AntiMonikerImpl_GetTimeOfLastChange, + AntiMonikerImpl_Inverse, + AntiMonikerImpl_CommonPrefixWith, + AntiMonikerImpl_RelativePathTo, + AntiMonikerImpl_GetDisplayName, + AntiMonikerImpl_ParseDisplayName, + AntiMonikerImpl_IsSystemMoniker +}; + +/********************************************************************************/ +/* Virtual function table for the IROTData class. */ +static ICOM_VTABLE(IROTData) VT_ROTDataImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + AntiMonikerROTDataImpl_QueryInterface, + AntiMonikerROTDataImpl_AddRef, + AntiMonikerROTDataImpl_Release, + AntiMonikerROTDataImpl_GetComparaisonData +}; + +/******************************************************************************* + * AntiMoniker_QueryInterface + *******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS(AntiMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream, riid) || + IsEqualIID(&IID_IMoniker, riid) + ) + *ppvObject = iface; + else if (IsEqualIID(&IID_IROTData, riid)) + *ppvObject = (IROTData*)&(This->lpvtbl2); + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + AntiMonikerImpl_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_AddRef + ******************************************************************************/ +ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker* iface) +{ + ICOM_THIS(AntiMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return ++(This->ref); +} + +/****************************************************************************** + * AntiMoniker_Release + ******************************************************************************/ +ULONG WINAPI AntiMonikerImpl_Release(IMoniker* iface) +{ + ICOM_THIS(AntiMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + This->ref--; + + /* destroy the object if there's no more reference on it */ + if (This->ref==0){ + + AntiMonikerImpl_Destroy(This); + + return 0; + } + return This->ref;; +} + +/****************************************************************************** + * AntiMoniker_GetClassID + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) +{ + Print(MAX_TRACE, ("(%p,%p),stub!\n",iface,pClassID)); + + if (pClassID==NULL) + return E_POINTER; + + *pClassID = CLSID_AntiMoniker; + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_IsDirty + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_IsDirty(IMoniker* iface) +{ + /* Note that the OLE-provided implementations of the IPersistStream::IsDirty + method in the OLE-provided moniker interfaces always return S_FALSE because + their internal state never changes. */ + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return S_FALSE; +} + +/****************************************************************************** + * AntiMoniker_Load + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm) +{ + DWORD constant=1,dwbuffer; + HRESULT res; + + /* data read by this function is only a DWORD constant (must be 1) ! */ + res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),NULL); + + if (SUCCEEDED(res)&& dwbuffer!=constant) + return E_FAIL; + + return res; +} + +/****************************************************************************** + * AntiMoniker_Save + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty) +{ + DWORD constant=1; + HRESULT res; + + /* data writen by this function is only a DWORD constant seted to 1 ! */ + res=IStream_Write(pStm,&constant,sizeof(constant),NULL); + + return res; +} + +/****************************************************************************** + * AntiMoniker_GetSizeMax + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_GetSizeMax(IMoniker* iface, + ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ +{ + Print(MAX_TRACE, ("(%p,%p)\n",iface,pcbSize)); + + if (pcbSize!=NULL) + return E_POINTER; + + /* for more details see AntiMonikerImpl_Save coments */ + + /* Normaly the sizemax must be the size of DWORD ! but I tested this function it ususlly return 16 bytes */ + /* more than the number of bytes used by AntiMoniker::Save function */ + pcbSize->u.LowPart = sizeof(DWORD)+16; + + pcbSize->u.HighPart=0; + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_Construct (local function) + *******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Construct(AntiMonikerImpl* This) +{ + + Print(MAX_TRACE, ("(%p)\n",This)); + + /* Initialize the virtual fgunction table. */ + This->lpvtbl1 = &VT_AntiMonikerImpl; + This->lpvtbl2 = &VT_ROTDataImpl; + This->ref = 0; + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_Destroy (local function) + *******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Destroy(AntiMonikerImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n",This)); + + return HeapFree(GetProcessHeap(),0,This); +} + +/****************************************************************************** + * AntiMoniker_BindToObject + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_BindToObject(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + return E_NOTIMPL; +} + +/****************************************************************************** + * AntiMoniker_BindToStorage + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_BindToStorage(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + return E_NOTIMPL; +} + +/****************************************************************************** + * AntiMoniker_Reduce + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Reduce(IMoniker* iface, + IBindCtx* pbc, + DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, + IMoniker** ppmkReduced) +{ + Print(MAX_TRACE, ("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced)); + + if (ppmkReduced==NULL) + return E_POINTER; + + AntiMonikerImpl_AddRef(iface); + + *ppmkReduced=iface; + + return MK_S_REDUCED_TO_SELF; +} +/****************************************************************************** + * AntiMoniker_ComposeWith + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_ComposeWith(IMoniker* iface, + IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, + IMoniker** ppmkComposite) +{ + + Print(MAX_TRACE, ("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite)); + + if ((ppmkComposite==NULL)||(pmkRight==NULL)) + return E_POINTER; + + *ppmkComposite=0; + + if (fOnlyIfNotGeneric) + return MK_E_NEEDGENERIC; + else + return CreateGenericComposite(iface,pmkRight,ppmkComposite); +} + +/****************************************************************************** + * AntiMoniker_Enum + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) +{ + Print(MAX_TRACE, ("(%p,%d,%p)\n",iface,fForward,ppenumMoniker)); + + if (ppenumMoniker == NULL) + return E_POINTER; + + *ppenumMoniker = NULL; + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_IsEqual + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +{ + DWORD mkSys; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pmkOtherMoniker)); + + if (pmkOtherMoniker==NULL) + return S_FALSE; + + IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys); + + if (mkSys==MKSYS_ANTIMONIKER) + return S_OK; + else + return S_FALSE; +} + +/****************************************************************************** + * AntiMoniker_Hash + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) +{ + if (pdwHash==NULL) + return E_POINTER; + + *pdwHash=0; + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_IsRunning + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_IsRunning(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + IRunningObjectTable* rot; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning)); + + if (pbc==NULL) + return E_INVALIDARG; + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (FAILED(res)) + return res; + + res = IRunningObjectTable_IsRunning(rot,iface); + + IRunningObjectTable_Release(rot); + + return res; +} + +/****************************************************************************** + * AntiMoniker_GetTimeOfLastChange + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pAntiTime) +{ + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime)); + return E_NOTIMPL; +} + +/****************************************************************************** + * AntiMoniker_Inverse + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +{ + Print(MAX_TRACE, ("(%p,%p)\n",iface,ppmk)); + + if (ppmk==NULL) + return E_POINTER; + + *ppmk=0; + + return MK_E_NOINVERSE; +} + +/****************************************************************************** + * AntiMoniker_CommonPrefixWith + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +{ + DWORD mkSys; + + IMoniker_IsSystemMoniker(pmkOther,&mkSys); + + if(mkSys==MKSYS_ITEMMONIKER){ + + IMoniker_AddRef(iface); + + *ppmkPrefix=iface; + + IMoniker_AddRef(iface); + + return MK_S_US; + } + else + return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix); +} + +/****************************************************************************** + * AntiMoniker_RelativePathTo + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) +{ + Print(MAX_TRACE, ("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath)); + + if (ppmkRelPath==NULL) + return E_POINTER; + + IMoniker_AddRef(pmOther); + + *ppmkRelPath=pmOther; + + return MK_S_HIM; +} + +/****************************************************************************** + * AntiMoniker_GetDisplayName + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_GetDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR *ppszDisplayName) +{ + WCHAR back[]={'\\','.','.',0}; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName)); + + if (ppszDisplayName==NULL) + return E_POINTER; + + if (pmkToLeft!=NULL){ + Print(MIN_TRACE, ("() pmkToLeft!=NULL not implemented \n")); + return E_NOTIMPL; + } + + *ppszDisplayName=CoTaskMemAlloc(sizeof(back)); + + if (*ppszDisplayName==NULL) + return E_OUTOFMEMORY; + + lstrcpyW(*ppszDisplayName,back); + + return S_OK; +} + +/****************************************************************************** + * AntiMoniker_ParseDisplayName + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_ParseDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR pszDisplayName, + ULONG* pchEaten, + IMoniker** ppmkOut) +{ + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut)); + return E_NOTIMPL; +} + +/****************************************************************************** + * AntiMoniker_IsSystemMoniker + ******************************************************************************/ +HRESULT WINAPI AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) +{ + Print(MAX_TRACE, ("(%p,%p)\n",iface,pwdMksys)); + + if (!pwdMksys) + return E_POINTER; + + (*pwdMksys)=MKSYS_ANTIMONIKER; + + return S_OK; +} + +/******************************************************************************* + * AntiMonikerIROTData_QueryInterface + *******************************************************************************/ +HRESULT WINAPI AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) +{ + + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",iface,riid,ppvObject)); + + return AntiMonikerImpl_QueryInterface(This, riid, ppvObject); +} + +/*********************************************************************** + * AntiMonikerIROTData_AddRef + */ +ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface) +{ + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return AntiMonikerImpl_AddRef(This); +} + +/*********************************************************************** + * AntiMonikerIROTData_Release + */ +ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface) +{ + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return AntiMonikerImpl_Release(This); +} + +/****************************************************************************** + * AntiMonikerIROTData_GetComparaisonData + ******************************************************************************/ +HRESULT WINAPI AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface, + BYTE* pbData, + ULONG cbMax, + ULONG* pcbData) +{ + Print(MIN_TRACE, ("(),stub!\n")); + return E_NOTIMPL; +} + +/****************************************************************************** + * CreateAntiMoniker [OLE.55] + ******************************************************************************/ +HRESULT WINAPI CreateAntiMoniker(LPMONIKER * ppmk) +{ + AntiMonikerImpl* newAntiMoniker = 0; + HRESULT hr = S_OK; + IID riid=IID_IMoniker; + + Print(MAX_TRACE, ("(%p)\n",ppmk)); + + newAntiMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(AntiMonikerImpl)); + + if (newAntiMoniker == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = AntiMonikerImpl_Construct(newAntiMoniker); + + if (FAILED(hr)){ + + HeapFree(GetProcessHeap(),0,newAntiMoniker); + return hr; + } + + hr = AntiMonikerImpl_QueryInterface((IMoniker*)newAntiMoniker,&riid,(void**)ppmk); + + return hr; +} diff --git a/lib/ole32/bindctx.c b/lib/ole32/bindctx.c new file mode 100644 index 0000000..1a6e24e --- /dev/null +++ b/lib/ole32/bindctx.c @@ -0,0 +1,544 @@ +/*************************************************************************************** + * BindCtx implementation + * + * Copyright 1999 Noomen Hamza + ***************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + + +/* represent the first size table and it's increment block size */ +#define BLOCK_TAB_SIZE 10 +#define MAX_TAB_SIZE 0xFFFFFFFF + +/* data structure of the BindCtx table elements */ +typedef struct BindCtxObject{ + + IUnknown* pObj; /* point on a bound object */ + + LPOLESTR pkeyObj; /* key associated to this bound object */ + + BYTE regType; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */ + +} BindCtxObject; + +/* BindCtx data strucrture */ +typedef struct BindCtxImpl{ + + ICOM_VFIELD(IBindCtx); /* VTable relative to the IBindCtx interface.*/ + + ULONG ref; /* reference counter for this object */ + + BindCtxObject* bindCtxTable; /* this is a table in which all bounded objects are stored*/ + DWORD bindCtxTableLastIndex; /* first free index in the table */ + DWORD bindCtxTableSize; /* size table */ + + BIND_OPTS2 bindOption2; /* a structure which contains the bind options*/ + +} BindCtxImpl; + +/* IBindCtx prototype functions : */ + +/* IUnknown functions*/ +static HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface); +static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface); +/* IBindCtx functions */ +static HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk); +static HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk); +static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface); +static HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts); +static HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts); +static HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot); +static HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk); +static HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk); +static HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** ppenum); +static HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR pszkey); +/* Local functions*/ +HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This); +HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This); +HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,IUnknown* punk,LPOLESTR pszkey,DWORD *index); + +/* Virtual function table for the BindCtx class. */ +static ICOM_VTABLE(IBindCtx) VT_BindCtxImpl = + { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + BindCtxImpl_QueryInterface, + BindCtxImpl_AddRef, + BindCtxImpl_Release, + BindCtxImpl_RegisterObjectBound, + BindCtxImpl_RevokeObjectBound, + BindCtxImpl_ReleaseBoundObjects, + BindCtxImpl_SetBindOptions, + BindCtxImpl_GetBindOptions, + BindCtxImpl_GetRunningObjectTable, + BindCtxImpl_RegisterObjectParam, + BindCtxImpl_GetObjectParam, + BindCtxImpl_EnumObjectParam, + BindCtxImpl_RevokeObjectParam +}; + +/******************************************************************************* + * BindCtx_QueryInterface + *******************************************************************************/ +HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter.*/ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid)) + *ppvObject = (IBindCtx*)This; + else + if (IsEqualIID(&IID_IBindCtx, riid)) + *ppvObject = (IBindCtx*)This; + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + BindCtxImpl_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * BindCtx_AddRef + ******************************************************************************/ +ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface) +{ + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return ++(This->ref); +} + +/****************************************************************************** + * BindCtx_Release + ******************************************************************************/ +ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface) +{ + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This);) + + This->ref--; + + if (This->ref==0){ + + /* release all registered objects */ + BindCtxImpl_ReleaseBoundObjects((IBindCtx*)This); + + BindCtxImpl_Destroy(This); + + return 0; + } + return This->ref;; +} + + +/****************************************************************************** + * BindCtx_Construct (local function) + *******************************************************************************/ +HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n",This)); + + /* Initialize the virtual function table.*/ + ICOM_VTBL(This) = &VT_BindCtxImpl; + This->ref = 0; + + /* Initialize the BIND_OPTS2 structure */ + This->bindOption2.cbStruct = sizeof(BIND_OPTS2); + This->bindOption2.grfFlags = 0; + This->bindOption2.grfMode = STGM_READWRITE; + This->bindOption2.dwTickCountDeadline = 0; + + This->bindOption2.dwTrackFlags = 0; + This->bindOption2.dwClassContext = CLSCTX_SERVER; + This->bindOption2.locale = 1033; + This->bindOption2.pServerInfo = 0; + + /* Initialize the bindctx table */ + This->bindCtxTableSize=BLOCK_TAB_SIZE; + This->bindCtxTableLastIndex=0; + This->bindCtxTable= HeapAlloc(GetProcessHeap(), 0,This->bindCtxTableSize*sizeof(BindCtxObject)); + + if (This->bindCtxTable==NULL) + return E_OUTOFMEMORY; + + return S_OK; +} + +/****************************************************************************** + * BindCtx_Destroy (local function) + *******************************************************************************/ +HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n",This)); + + /* free the table space memory */ + HeapFree(GetProcessHeap(),0,This->bindCtxTable); + + /* free the bindctx structure */ + HeapFree(GetProcessHeap(),0,This); + + return S_OK; +} + + +/****************************************************************************** + * BindCtx_RegisterObjectBound + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk) +{ + + ICOM_THIS(BindCtxImpl,iface); + DWORD lastIndex=This->bindCtxTableLastIndex; + BindCtxObject cell; + + Print(MAX_TRACE, ("(%p,%p)\n",This,punk)); + + if (punk==NULL) + return E_POINTER; + + IUnknown_AddRef(punk); + + /* put the object in the first free element in the table */ + This->bindCtxTable[lastIndex].pObj = punk; + This->bindCtxTable[lastIndex].pkeyObj = NULL; + This->bindCtxTable[lastIndex].regType = 0; + cell=This->bindCtxTable[lastIndex]; + lastIndex= ++This->bindCtxTableLastIndex; + + if (lastIndex == This->bindCtxTableSize){ /* the table is full so it must be resized */ + + if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){ + Print(MIN_TRACE, ("This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize)); + return E_FAIL; +} + + This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */ + + This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable, + This->bindCtxTableSize * sizeof(BindCtxObject)); + if (!This->bindCtxTable) + return E_OUTOFMEMORY; + } + return S_OK; +} + +/****************************************************************************** + * BindCtx_RevokeObjectBound + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk) +{ + DWORD index,j; + + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",This,punk)); + + /* check if the object was registred or not */ + if (BindCtxImpl_GetObjectIndex(This,punk,NULL,&index)==S_FALSE) + + return MK_E_NOTBOUND; + + IUnknown_Release(This->bindCtxTable[index].pObj); + + /* left-shift all elements in the right side of the current revoked object */ + for(j=index; jbindCtxTableLastIndex-1; j++) + This->bindCtxTable[j]= This->bindCtxTable[j+1]; + + This->bindCtxTableLastIndex--; + + return S_OK; +} + +/****************************************************************************** + * BindCtx_ReleaseBoundObjects + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface) +{ + DWORD i; + + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + for(i=0;ibindCtxTableLastIndex;i++) + IUnknown_Release(This->bindCtxTable[i].pObj); + + This->bindCtxTableLastIndex = 0; + + return S_OK; +} + +/****************************************************************************** + * BindCtx_SetBindOptions + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts) +{ + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",This,pbindopts)); + + if (pbindopts==NULL) + return E_POINTER; + + if (pbindopts->cbStruct > sizeof(BIND_OPTS2)) + { + Print(MID_TRACE, ("invalid size\n")); + return E_INVALIDARG; /* FIXME : not verified */ + } + memcpy(&This->bindOption2, pbindopts, pbindopts->cbStruct); + return S_OK; +} + +/****************************************************************************** + * BindCtx_GetBindOptions + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts) +{ + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",This,pbindopts)); + + if (pbindopts==NULL) + return E_POINTER; + + if (pbindopts->cbStruct > sizeof(BIND_OPTS2)) + { + Print(MID_TRACE, ("invalid size\n")); + return E_INVALIDARG; /* FIXME : not verified */ + } + memcpy(pbindopts, &This->bindOption2, pbindopts->cbStruct); + return S_OK; +} + +/****************************************************************************** + * BindCtx_GetRunningObjectTable + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot) +{ + HRESULT res; + + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",This,pprot)); + + if (pprot==NULL) + return E_POINTER; + + res=GetRunningObjectTable(0, pprot); + + return res; +} + +/****************************************************************************** + * BindCtx_RegisterObjectParam + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk) +{ + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,pszkey,punk)); + + if (punk==NULL) + return E_INVALIDARG; + + IUnknown_AddRef(punk); + + This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk; + This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1; + + if (pszkey==NULL) + + This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL; + + else{ + + This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj= + HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR)*(1+lstrlenW(pszkey)))); + + if (This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj==NULL) + return E_OUTOFMEMORY; + lstrcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey); +} + + This->bindCtxTableLastIndex++; + + if (This->bindCtxTableLastIndex == This->bindCtxTableSize){ /* table is full ! must be resized */ + + This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */ + + if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){ + Print(MIN_TRACE, ("This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize)); + return E_FAIL; + } + This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable, + This->bindCtxTableSize * sizeof(BindCtxObject)); + if (!This->bindCtxTable) + return E_OUTOFMEMORY; + } + return S_OK; +} +/****************************************************************************** + * BindCtx_GetObjectParam + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk) +{ + DWORD index; + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,pszkey,punk)); + + if (punk==NULL) + return E_POINTER; + + *punk=0; + + if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE) + return E_FAIL; + + IUnknown_AddRef(This->bindCtxTable[index].pObj); + + *punk = This->bindCtxTable[index].pObj; + + return S_OK; +} + +/****************************************************************************** + * BindCtx_RevokeObjectParam + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum) +{ + DWORD index,j; + + ICOM_THIS(BindCtxImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",This,ppenum)); + + if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE) + return E_FAIL; + + /* release the object if it's found */ + IUnknown_Release(This->bindCtxTable[index].pObj); + + /* remove the object from the table with a left-shifting of all objects in the right side */ + for(j=index; jbindCtxTableLastIndex-1; j++) + This->bindCtxTable[j]= This->bindCtxTable[j+1]; + + This->bindCtxTableLastIndex--; + + return S_OK; +} + +/****************************************************************************** + * BindCtx_EnumObjectParam + ******************************************************************************/ +HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/******************************************************************************** + * GetObjectIndex (local function) + ********************************************************************************/ +HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This, + IUnknown* punk, + LPOLESTR pszkey, + DWORD *index) +{ + + DWORD i; + BYTE found=0; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",This,punk,pszkey,index)); + + if (punk==NULL) + /* search object identified by a register key */ + for(i=0; ( (ibindCtxTableLastIndex) && (!found));i++){ + + if(This->bindCtxTable[i].regType==1){ + + if ( ( (This->bindCtxTable[i].pkeyObj==NULL) && (pszkey==NULL) ) || + ( (This->bindCtxTable[i].pkeyObj!=NULL) && + (pszkey!=NULL) && + (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0) + ) + ) + + found=1; + } + } + else + /* search object identified by a moniker*/ + for(i=0; ( (ibindCtxTableLastIndex) && (!found));i++) + if(This->bindCtxTable[i].pObj==punk) + found=1; + + if (index != NULL) + *index=i-1; + + if (found) + return S_OK; + else + return S_FALSE; +} + +/****************************************************************************** + * CreateBindCtx16 + ******************************************************************************/ +HRESULT WINAPI CreateBindCtx16(DWORD reserved, LPBC * ppbc) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/****************************************************************************** + * CreateBindCtx + ******************************************************************************/ +HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc) +{ + BindCtxImpl* newBindCtx = 0; + HRESULT hr; + IID riid=IID_IBindCtx; + + Print(MAX_TRACE, ("(%ld,%p)\n",reserved,ppbc)); + + newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl)); + + if (newBindCtx == 0) + return E_OUTOFMEMORY; + + hr = BindCtxImpl_Construct(newBindCtx); + + if (FAILED(hr)){ + + HeapFree(GetProcessHeap(),0,newBindCtx); + return hr; + } + + hr = BindCtxImpl_QueryInterface((IBindCtx*)newBindCtx,&riid,(void**)ppbc); + + return hr; +} diff --git a/lib/ole32/compobj.c b/lib/ole32/compobj.c new file mode 100644 index 0000000..534937b --- /dev/null +++ b/lib/ole32/compobj.c @@ -0,0 +1,2060 @@ +/* + * COMPOBJ library + * + * Copyright 1995 Martin von Loewis + * Copyright 1998 Justin Bradford + * Copyright 1999 Francis Beaudet + * Copyright 1999 Sylvain St-Germain + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * COM External Lock structures and methods declaration + * + * This api provides a linked list to managed external references to + * COM objects. + * + * The public interface consists of three calls: + * COM_ExternalLockAddRef + * COM_ExternalLockRelease + * COM_ExternalLockFreeList + */ + +#define EL_END_OF_LIST 0 +#define EL_NOT_FOUND 0 + +/* + * Declaration of the static structure that manage the + * external lock to COM objects. + */ +typedef struct COM_ExternalLock COM_ExternalLock; +typedef struct COM_ExternalLockList COM_ExternalLockList; + +struct COM_ExternalLock +{ + IUnknown *pUnk; /* IUnknown referenced */ + ULONG uRefCount; /* external lock counter to IUnknown object*/ + COM_ExternalLock *next; /* Pointer to next element in list */ +}; + +struct COM_ExternalLockList +{ + COM_ExternalLock *head; /* head of list */ +}; + +/* + * Declaration and initialization of the static structure that manages + * the external lock to COM objects. + */ +static COM_ExternalLockList elList = { EL_END_OF_LIST }; + +/* + * Public Interface to the external lock list + */ +static void COM_ExternalLockFreeList(); +static void COM_ExternalLockAddRef(IUnknown *pUnk); +static void COM_ExternalLockRelease(IUnknown *pUnk, BOOL bRelAll); +void COM_ExternalLockDump(); /* testing purposes, not static to avoid warning */ + +/* + * Private methods used to managed the linked list + */ +static BOOL COM_ExternalLockInsert( + IUnknown *pUnk); + +static void COM_ExternalLockDelete( + COM_ExternalLock *element); + +static COM_ExternalLock* COM_ExternalLockFind( + IUnknown *pUnk); + +static COM_ExternalLock* COM_ExternalLockLocate( + COM_ExternalLock *element, + IUnknown *pUnk); + +/**************************************************************************** + * This section defines variables internal to the COM module. + * + * TODO: Most of these things will have to be made thread-safe. + */ +HINSTANCE COMPOBJ_hInstance32 = 0; +static int COMPOBJ_Attach = 0; + +LPMALLOC currentMalloc32=NULL; + +WORD Table_ETask[62]; + +/* + * This lock count counts the number of times CoInitialize is called. It is + * decreased every time CoUninitialize is called. When it hits 0, the COM + * libraries are freed + */ +static ULONG s_COMLockCount = 0; + +/* + * This linked list contains the list of registered class objects. These + * are mostly used to register the factories for out-of-proc servers of OLE + * objects. + * + * TODO: Make this data structure aware of inter-process communication. This + * means that parts of this will be exported to the Wine Server. + */ +typedef struct tagRegisteredClass +{ + CLSID classIdentifier; + LPUNKNOWN classObject; + DWORD runContext; + DWORD connectFlags; + DWORD dwCookie; + struct tagRegisteredClass* nextClass; +} RegisteredClass; + +static RegisteredClass* firstRegisteredClass = NULL; + +/* this open DLL table belongs in a per process table, but my guess is that + * it shouldn't live in the kernel, so I'll put them out here in DLL + * space assuming that there is one OLE32 per process. + */ +typedef struct tagOpenDll { + HINSTANCE hLibrary; + struct tagOpenDll *next; +} OpenDll; + +static OpenDll *openDllList = NULL; /* linked list of open dlls */ + +/***************************************************************************** + * This section contains prototypes to internal methods for this + * module + */ +static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, + DWORD dwClsContext, + LPUNKNOWN* ppUnk); + +static void COM_RevokeAllClasses(); + + +/****************************************************************************** + * CoBuildVersion [COMPOBJ.1] + * + * RETURNS + * Current build version, hiword is majornumber, loword is minornumber + */ +DWORD WINAPI CoBuildVersion(void) +{ + Print(MAX_TRACE, ("Returning version %d, build %d.\n", 1, 0)); + return (1<<16)+0; +} + +/****************************************************************************** + * CoInitialize16 [COMPOBJ.2] + * Set the win16 IMalloc used for memory management + */ +HRESULT WINAPI CoInitialize16( + LPVOID lpReserved /* [in] pointer to win16 malloc interface */ +) { + UNIMPLEMENTED; + return S_OK; +} + +/****************************************************************************** + * CoInitialize [OLE32.26] + * + * Initializes the COM libraries. + * + * See CoInitializeEx + */ +HRESULT WINAPI CoInitialize( + LPVOID lpReserved /* [in] pointer to win32 malloc interface + (obsolete, should be NULL) */ +) +{ +#if 0 + /* + * Just delegate to the newer method. + */ + return CoInitializeEx(lpReserved, )COINIT_APARTMENTTHREADED); +#else + return E_FAIL; +#endif +} + +/****************************************************************************** + * CoInitializeEx [OLE32.163] + * + * Initializes the COM libraries. The behavior used to set the win32 IMalloc + * used for memory management is obsolete. + * + * RETURNS + * S_OK if successful, + * S_FALSE if this function was called already. + * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another + * threading model. + * + * BUGS + * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE + * is never returned. + * + * See the windows documentation for more details. + */ +HRESULT WINAPI CoInitializeEx( + LPVOID lpReserved, /* [in] pointer to win32 malloc interface + (obsolete, should be NULL) */ + DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */ +) +{ + HRESULT hr; + + Print(MAX_TRACE, ("(%p, %x)\n", lpReserved, (int)dwCoInit)); + + if (lpReserved!=NULL) + { + Print(MIN_TRACE, ("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved)); + } + + /* + * Check for unsupported features. + */ + if (dwCoInit!=COINIT_APARTMENTTHREADED) + { + Print(MAX_TRACE, (":(%p,%x): unsupported flag %x\n", lpReserved, (int)dwCoInit, (int)dwCoInit)); + /* Hope for the best and continue anyway */ + } + + /* + * Check the lock count. If this is the first time going through the initialize + * process, we have to initialize the libraries. + */ + if (s_COMLockCount==0) + { + /* + * Initialize the various COM libraries and data structures. + */ + Print(MAX_TRACE, ("() - Initializing the COM libraries\n")); + + RunningObjectTableImpl_Initialize(); + + hr = S_OK; + } + else + hr = S_FALSE; + + /* + * Crank-up that lock count. + */ + s_COMLockCount++; + + return hr; +} + +/*********************************************************************** + * CoUninitialize16 [COMPOBJ.3] + * Don't know what it does. + * 3-Nov-98 -- this was originally misspelled, I changed it to what I + * believe is the correct spelling + */ +void WINAPI CoUninitialize16(void) +{ + Print(MAX_TRACE, ("Called\n")); + CoFreeAllLibraries(); +} + +/*********************************************************************** + * CoUninitialize [OLE32.47] + * + * This method will release the COM libraries. + * + * See the windows documentation for more details. + */ +void WINAPI CoUninitialize(void) +{ + Print(MAX_TRACE, ("Called\n")); + + /* + * Decrease the reference count. + */ + s_COMLockCount--; + + /* + * If we are back to 0 locks on the COM library, make sure we free + * all the associated data structures. + */ + if (s_COMLockCount==0) + { + /* + * Release the various COM libraries and data structures. + */ + Print(MAX_TRACE, ("() - Releasing the COM libraries\n")); + + RunningObjectTableImpl_UnInitialize(); + /* + * Release the references to the registered class objects. + */ + COM_RevokeAllClasses(); + + /* + * This will free the loaded COM Dlls. + */ + CoFreeAllLibraries(); + + /* + * This will free list of external references to COM objects. + */ + COM_ExternalLockFreeList(); +} +} + +/*********************************************************************** + * CoGetMalloc16 [COMPOBJ.4] + * RETURNS + * The current win16 IMalloc + */ +HRESULT WINAPI CoGetMalloc16( + DWORD dwMemContext, /* [in] unknown */ + PVOID lpMalloc /* [out] current win16 malloc interface */ +) { + UNIMPLEMENTED; + return S_OK; +} + +/****************************************************************************** + * CoGetMalloc [OLE32.20] + * + * RETURNS + * The current win32 IMalloc + */ +HRESULT WINAPI CoGetMalloc( + DWORD dwMemContext, /* [in] unknown */ + LPMALLOC *lpMalloc /* [out] current win32 malloc interface */ +) { +#if 0 + if(!currentMalloc32) + currentMalloc32 = IMalloc_Constructor(); + *lpMalloc = currentMalloc32; + return S_OK; +#else + UNIMPLEMENTED; + return S_OK; +#endif +} + +/*********************************************************************** + * CoCreateStandardMalloc16 [COMPOBJ.71] + */ +HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext, + PVOID lpMalloc) +{ + UNIMPLEMENTED; + return S_OK; +} + +/****************************************************************************** + * CoDisconnectObject [COMPOBJ.15] + */ +HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved ) +{ + Print(MAX_TRACE, ("(%p, %lx)\n",lpUnk,reserved)); + return S_OK; +} + +/*********************************************************************** + * IsEqualGUID16 [COMPOBJ.18] + * + * Compares two Unique Identifiers. + * + * RETURNS + * TRUE if equal + */ +BOOL WINAPI IsEqualGUID16( + GUID* g1, /* [in] unique id 1 */ + GUID* g2 /* [in] unique id 2 */ +) { + return !memcmp( g1, g2, sizeof(GUID) ); +} + +/****************************************************************************** + * CLSIDFromString16 [COMPOBJ.20] + * Converts a unique identifier from its string representation into + * the GUID struct. + * + * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6] + * + * RETURNS + * the converted GUID + */ +HRESULT WINAPI CLSIDFromString16( + LPCOLESTR16 idstr, /* [in] string representation of guid */ + CLSID *id /* [out] GUID converted from string */ +) { + BYTE *s = (BYTE *) idstr; + BYTE *p; + int i; + BYTE table[256]; + + if (!s) + s = "{00000000-0000-0000-0000-000000000000}"; + else { /* validate the CLSID string */ + + if (strlen(s) != 38) + return CO_E_CLASSSTRING; + + if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}')) + return CO_E_CLASSSTRING; + + for (i=1; i<37; i++) + { + if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue; + if (!(((s[i] >= '0') && (s[i] <= '9')) || + ((s[i] >= 'a') && (s[i] <= 'f')) || + ((s[i] >= 'A') && (s[i] <= 'F'))) + ) + return CO_E_CLASSSTRING; + } + } + + Print(MAX_TRACE, ("%s -> %p\n", s, id)); + + /* quick lookup table */ + memset(table, 0, 256); + + for (i = 0; i < 10; i++) { + table['0' + i] = i; + } + for (i = 0; i < 6; i++) { + table['A' + i] = i+10; + table['a' + i] = i+10; + } + + /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ + + p = (BYTE *) id; + + s++; /* skip leading brace */ + for (i = 0; i < 4; i++) { + p[3 - i] = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + p += 4; + s++; /* skip - */ + + for (i = 0; i < 2; i++) { + p[1-i] = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + p += 2; + s++; /* skip - */ + + for (i = 0; i < 2; i++) { + p[1-i] = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + p += 2; + s++; /* skip - */ + + /* these are just sequential bytes */ + for (i = 0; i < 2; i++) { + *p++ = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + s++; /* skip - */ + + for (i = 0; i < 6; i++) { + *p++ = table[*s]<<4 | table[*(s+1)]; + s += 2; + } + + return S_OK; +} + +/****************************************************************************** + * CoCreateGuid[OLE32.6] + * + */ +HRESULT WINAPI CoCreateGuid( + GUID *pguid /* [out] points to the GUID to initialize */ +) { + return UuidCreate(pguid); +} + +/****************************************************************************** + * CLSIDFromString [OLE32.3] + * Converts a unique identifier from its string representation into + * the GUID struct. + * + * UNDOCUMENTED + * If idstr is not a valid CLSID string then it gets treated as a ProgID + * + * RETURNS + * the converted GUID + */ +HRESULT WINAPI CLSIDFromString( + LPCOLESTR idstr, /* [in] string representation of GUID */ + CLSID *id /* [out] GUID represented by above string */ +) { +#if 0 + LPOLESTR16 xid = HEAP_strdupWtoA(GetProcessHeap(),0,idstr); + HRESULT ret = CLSIDFromString16(xid,id); + + HeapFree(GetProcessHeap(),0,xid); + if(ret != S_OK) { /* It appears a ProgID is also valid */ + ret = CLSIDFromProgID(idstr, id); + } + return ret; +#else + UNIMPLEMENTED; + return (HRESULT)0; +#endif +} + +/****************************************************************************** + * WINE_StringFromCLSID [Internal] + * Converts a GUID into the respective string representation. + * + * NOTES + * + * RETURNS + * the string representation and HRESULT + */ +static HRESULT WINE_StringFromCLSID( + const CLSID *id, /* [in] GUID to be converted */ + LPSTR idstr /* [out] pointer to buffer to contain converted guid */ +) { + static const char *hex = "0123456789ABCDEF"; + char *s; + int i; + + if (!id) + { Print(MIN_TRACE, ("called with id=Null\n")); + *idstr = 0x00; + return E_FAIL; + } + + sprintf(idstr, "{%08lX-%04X-%04X-%02X%02X-", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1]); + s = &idstr[25]; + + /* 6 hex bytes */ + for (i = 2; i < 8; i++) { + *s++ = hex[id->Data4[i]>>4]; + *s++ = hex[id->Data4[i] & 0xf]; + } + + *s++ = '}'; + *s++ = '\0'; + + Print(MAX_TRACE, ("%p->%s\n", id, idstr)); + + return S_OK; +} + +/****************************************************************************** + * StringFromCLSID16 [COMPOBJ.19] + * Converts a GUID into the respective string representation. + * The target string is allocated using the OLE IMalloc. + * RETURNS + * the string representation and HRESULT + */ +HRESULT WINAPI StringFromCLSID16( + REFCLSID id, /* [in] the GUID to be converted */ + LPOLESTR16 *idstr /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */ + +) { +#if 0 + extern BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags, + DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode ); + LPMALLOC16 mllc; + HRESULT ret; + DWORD args[2]; + + ret = CoGetMalloc16(0,&mllc); + if (ret) return ret; + + args[0] = (DWORD)mllc; + args[1] = 40; + + /* No need for a Callback entry, we have WOWCallback16Ex which does + * everything we need. + */ + if (!K32WOWCallback16Ex( + (DWORD)((ICOM_VTABLE(IMalloc16)*)MapSL( + (SEGPTR)ICOM_VTBL(((LPMALLOC16)MapSL((SEGPTR)mllc)))) + )->Alloc, + WCB16_CDECL, + 2*sizeof(DWORD), + (LPVOID)args, + (LPDWORD)idstr + )) { + WARN("CallTo16 IMalloc16 failed\n"); + return E_FAIL; + } + return WINE_StringFromCLSID(id,MapSL((SEGPTR)*idstr)); +#else + UNIMPLEMENTED; + return (HRESULT)0; +#endif +} + +/****************************************************************************** + * StringFromCLSID [OLE32.151] + * Converts a GUID into the respective string representation. + * The target string is allocated using the OLE IMalloc. + * RETURNS + * the string representation and HRESULT + */ +HRESULT WINAPI StringFromCLSID( + REFCLSID id, /* [in] the GUID to be converted */ + LPOLESTR *idstr /* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */ +) { + char buf[80]; + HRESULT ret; + LPMALLOC mllc; + + if ((ret=CoGetMalloc(0,&mllc))) + return ret; + + ret=WINE_StringFromCLSID(id,buf); + if (!ret) { + DWORD len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ); + *idstr = IMalloc_Alloc( mllc, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, buf, -1, *idstr, len ); + } + return ret; +} + +/****************************************************************************** + * StringFromGUID2 [COMPOBJ.76] [OLE32.152] + * + * Converts a global unique identifier into a string of an API- + * specified fixed format. (The usual {.....} stuff.) + * + * RETURNS + * The (UNICODE) string representation of the GUID in 'str' + * The length of the resulting string, 0 if there was any problem. + */ +INT WINAPI +StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax) +{ + char xguid[80]; + + if (WINE_StringFromCLSID(id,xguid)) + return 0; + return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax ); +} + +/****************************************************************************** + * ProgIDFromCLSID [OLE32.133] + * Converts a class id into the respective Program ID. (By using a registry lookup) + * RETURNS S_OK on success + * riid associated with the progid + */ + +HRESULT WINAPI ProgIDFromCLSID( + REFCLSID clsid, /* [in] class id as found in registry */ + LPOLESTR *lplpszProgID/* [out] associated Prog ID */ +) +{ + char strCLSID[50], *buf, *buf2; + DWORD buf2len; + HKEY xhkey; + LPMALLOC mllc; + HRESULT ret = S_OK; + + WINE_StringFromCLSID(clsid, strCLSID); + + buf = HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID)+14); + sprintf(buf,"CLSID\\%s\\ProgID", strCLSID); + if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey)) + ret = REGDB_E_CLASSNOTREG; + + HeapFree(GetProcessHeap(), 0, buf); + + if (ret == S_OK) + { + buf2 = HeapAlloc(GetProcessHeap(), 0, 255); + buf2len = 255; + if (RegQueryValueA(xhkey, NULL, buf2, &buf2len)) + ret = REGDB_E_CLASSNOTREG; + + if (ret == S_OK) + { + if (CoGetMalloc(0,&mllc)) + ret = E_OUTOFMEMORY; + else + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, buf2, -1, NULL, 0 ); + *lplpszProgID = IMalloc_Alloc(mllc, len * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, buf2, -1, *lplpszProgID, len ); + } + } + HeapFree(GetProcessHeap(), 0, buf2); + } + + RegCloseKey(xhkey); + return ret; +} + +/****************************************************************************** + * CLSIDFromProgID16 [COMPOBJ.61] + * Converts a program id into the respective GUID. (By using a registry lookup) + * RETURNS + * riid associated with the progid + */ +HRESULT WINAPI CLSIDFromProgID16( + LPCOLESTR16 progid, /* [in] program id as found in registry */ + LPCLSID riid /* [out] associated CLSID */ +) { + char *buf,buf2[80]; + DWORD buf2len; + HRESULT err; + HKEY xhkey; + + buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8); + sprintf(buf,"%s\\CLSID",progid); + if ((err=RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey))) { + HeapFree(GetProcessHeap(),0,buf); + return CO_E_CLASSSTRING; + } + HeapFree(GetProcessHeap(),0,buf); + buf2len = sizeof(buf2); + if ((err=RegQueryValueA(xhkey,NULL,buf2,&buf2len))) { + RegCloseKey(xhkey); + return CO_E_CLASSSTRING; + } + RegCloseKey(xhkey); + return CLSIDFromString16(buf2,riid); +} + +/****************************************************************************** + * CLSIDFromProgID [OLE32.2] + * Converts a program id into the respective GUID. (By using a registry lookup) + * RETURNS + * riid associated with the progid + */ +HRESULT WINAPI CLSIDFromProgID( + LPCOLESTR progid, /* [in] program id as found in registry */ + LPCLSID riid /* [out] associated CLSID */ +) { +#if 0 + LPOLESTR16 pid = HEAP_strdupWtoA(GetProcessHeap(),0,progid); + HRESULT ret = CLSIDFromProgID16(pid,riid); + + HeapFree(GetProcessHeap(),0,pid); + return ret; +#else + UNIMPLEMENTED; + return (HRESULT)0; +#endif +} + + + +/***************************************************************************** + * CoGetPSClsid [OLE32.22] + * + * This function returns the CLSID of the DLL that implements the proxy and stub + * for the specified interface. + * + * It determines this by searching the + * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry + * and any interface id registered by CoRegisterPSClsid within the current process. + * + * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid. + */ +HRESULT WINAPI CoGetPSClsid( + REFIID riid, /* [in] Interface whose proxy/stub CLSID is to be returned */ + CLSID *pclsid ) /* [out] Where to store returned proxy/stub CLSID */ +{ + char *buf, buf2[40]; + DWORD buf2len; + HKEY xhkey; + + Print(MAX_TRACE, ("() riid=%s, pclsid=%p\n", PRINT_GUID(riid), pclsid)); + + /* Get the input iid as a string */ + WINE_StringFromCLSID(riid, buf2); + /* Allocate memory for the registry key we will construct. + (length of iid string plus constant length of static text */ + buf = HeapAlloc(GetProcessHeap(), 0, strlen(buf2)+27); + if (buf == NULL) + { + return (E_OUTOFMEMORY); + } + + /* Construct the registry key we want */ + sprintf(buf,"Interface\\%s\\ProxyStubClsid32", buf2); + + /* Open the key.. */ + if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey)) + { + HeapFree(GetProcessHeap(),0,buf); + return (E_INVALIDARG); + } + HeapFree(GetProcessHeap(),0,buf); + + /* ... Once we have the key, query the registry to get the + value of CLSID as a string, and convert it into a + proper CLSID structure to be passed back to the app */ + buf2len = sizeof(buf2); + if ( (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) ) + { + RegCloseKey(xhkey); + return E_INVALIDARG; + } + RegCloseKey(xhkey); + + /* We have the CLSid we want back from the registry as a string, so + lets convert it into a CLSID structure */ + if ( (CLSIDFromString16(buf2,pclsid)) != NOERROR) + { + return E_INVALIDARG; + } + + Print(MAX_TRACE, ("() Returning CLSID=%s\n", PRINT_GUID(pclsid))); + return (S_OK); +} + + + +/*********************************************************************** + * WriteClassStm + * + * This function write a CLSID on stream + */ +HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid) +{ + Print(MAX_TRACE, ("(%p,%p)\n",pStm,rclsid)); + + if (rclsid==NULL) + return E_INVALIDARG; + + return IStream_Write(pStm,rclsid,sizeof(CLSID),NULL); +} + +/*********************************************************************** + * ReadClassStm + * + * This function read a CLSID from a stream + */ +HRESULT WINAPI ReadClassStm(IStream *pStm,REFCLSID rclsid) +{ + ULONG nbByte; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p)\n",pStm,rclsid)); + + if (rclsid==NULL) + return E_INVALIDARG; + + res = IStream_Read(pStm,(void*)rclsid,sizeof(CLSID),&nbByte); + + if (FAILED(res)) + return res; + + if (nbByte != sizeof(CLSID)) + return S_FALSE; + else + return S_OK; +} + +/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */ +/*********************************************************************** + * LookupETask (COMPOBJ.94) + */ +HRESULT WINAPI LookupETask16(PVOID hTask,LPVOID p) { + UNIMPLEMENTED; + return S_OK; +} + +/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */ +/*********************************************************************** + * SetETask (COMPOBJ.95) + */ +HRESULT WINAPI SetETask16(DWORD hTask, LPVOID p) { + UNIMPLEMENTED; + return S_OK; +} + +/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */ +/*********************************************************************** + * CallObjectInWOW (COMPOBJ.201) + */ +HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) { + UNIMPLEMENTED; + return 0; +} + +/****************************************************************************** + * CoRegisterClassObject16 [COMPOBJ.5] + * + * Don't know where it registers it ... + */ +HRESULT WINAPI CoRegisterClassObject16( + REFCLSID rclsid, + LPUNKNOWN pUnk, + DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */ + DWORD flags, /* [in] REGCLS flags indicating how connections are made */ + LPDWORD lpdwRegister +) { + UNIMPLEMENTED; + return S_OK; +} + + +/****************************************************************************** + * CoRevokeClassObject16 [COMPOBJ.6] + * + */ +HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */ +{ + UNIMPLEMENTED; + return S_OK; +} + + +/*** + * COM_GetRegisteredClassObject + * + * This internal method is used to scan the registered class list to + * find a class object. + * + * Params: + * rclsid Class ID of the class to find. + * dwClsContext Class context to match. + * ppv [out] returns a pointer to the class object. Complying + * to normal COM usage, this method will increase the + * reference count on this object. + */ +static HRESULT COM_GetRegisteredClassObject( + REFCLSID rclsid, + DWORD dwClsContext, + LPUNKNOWN* ppUnk) +{ + RegisteredClass* curClass; + + /* + * Sanity check + */ + assert(ppUnk!=0); + + /* + * Iterate through the whole list and try to match the class ID. + */ + curClass = firstRegisteredClass; + + while (curClass != 0) + { + /* + * Check if we have a match on the class ID. + */ + if (IsEqualGUID(&(curClass->classIdentifier), rclsid)) + { + /* + * Since we don't do out-of process or DCOM just right away, let's ignore the + * class context. + */ + + /* + * We have a match, return the pointer to the class object. + */ + *ppUnk = curClass->classObject; + + IUnknown_AddRef(curClass->classObject); + + return S_OK; + } + + /* + * Step to the next class in the list. + */ + curClass = curClass->nextClass; + } + + /* + * If we get to here, we haven't found our class. + */ + return S_FALSE; +} + +/****************************************************************************** + * CoRegisterClassObject [OLE32.36] + * + * This method will register the class object for a given class ID. + * + * See the Windows documentation for more details. + */ +HRESULT WINAPI CoRegisterClassObject( + REFCLSID rclsid, + LPUNKNOWN pUnk, + DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */ + DWORD flags, /* [in] REGCLS flags indicating how connections are made */ + LPDWORD lpdwRegister +) +{ + RegisteredClass* newClass; + LPUNKNOWN foundObject; + HRESULT hr; + char buf[80]; + + WINE_StringFromCLSID(rclsid,buf); + + Print(MAX_TRACE, ("(%s,%p,0x%08lx,0x%08lx,%p)\n", + buf,pUnk,dwClsContext,flags,lpdwRegister)); + + /* + * Perform a sanity check on the parameters + */ + if ( (lpdwRegister==0) || (pUnk==0) ) + { + return E_INVALIDARG; +} + + /* + * Initialize the cookie (out parameter) + */ + *lpdwRegister = 0; + + /* + * First, check if the class is already registered. + * If it is, this should cause an error. + */ + hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject); + + if (hr == S_OK) + { + /* + * The COM_GetRegisteredClassObject increased the reference count on the + * object so it has to be released. + */ + IUnknown_Release(foundObject); + + return CO_E_OBJISREG; + } + + /* + * If it is not registered, we must create a new entry for this class and + * append it to the registered class list. + * We use the address of the chain node as the cookie since we are sure it's + * unique. + */ + newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass)); + + /* + * Initialize the node. + */ + newClass->classIdentifier = *rclsid; + newClass->runContext = dwClsContext; + newClass->connectFlags = flags; + newClass->dwCookie = (DWORD)newClass; + newClass->nextClass = firstRegisteredClass; + + /* + * Since we're making a copy of the object pointer, we have to increase its + * reference count. + */ + newClass->classObject = pUnk; + IUnknown_AddRef(newClass->classObject); + + firstRegisteredClass = newClass; + + /* + * Assign the out parameter (cookie) + */ + *lpdwRegister = newClass->dwCookie; + + /* + * We're successful Yippee! + */ + return S_OK; +} + +/*********************************************************************** + * CoRevokeClassObject [OLE32.40] + * + * This method will remove a class object from the class registry + * + * See the Windows documentation for more details. + */ +HRESULT WINAPI CoRevokeClassObject( + DWORD dwRegister) +{ + RegisteredClass** prevClassLink; + RegisteredClass* curClass; + + Print(MAX_TRACE, ("(%08lx)\n",dwRegister)); + + /* + * Iterate through the whole list and try to match the cookie. + */ + curClass = firstRegisteredClass; + prevClassLink = &firstRegisteredClass; + + while (curClass != 0) + { + /* + * Check if we have a match on the cookie. + */ + if (curClass->dwCookie == dwRegister) + { + /* + * Remove the class from the chain. + */ + *prevClassLink = curClass->nextClass; + + /* + * Release the reference to the class object. + */ + IUnknown_Release(curClass->classObject); + + /* + * Free the memory used by the chain node. + */ + HeapFree(GetProcessHeap(), 0, curClass); + + return S_OK; +} + + /* + * Step to the next class in the list. + */ + prevClassLink = &(curClass->nextClass); + curClass = curClass->nextClass; + } + + /* + * If we get to here, we haven't found our class. + */ + return E_INVALIDARG; +} + +/*********************************************************************** + * CoGetClassObject [COMPOBJ.7] + */ +HRESULT WINAPI CoGetClassObject( + REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, + REFIID iid, LPVOID *ppv +) { + LPUNKNOWN regClassObject; + HRESULT hres = E_UNEXPECTED; + char xclsid[80]; + WCHAR dllName[MAX_PATH+1]; + DWORD dllNameLen = sizeof(dllName); + HINSTANCE hLibrary; + typedef HRESULT CALLBACK (*DllGetClassObjectFunc)(REFCLSID clsid, + REFIID iid, LPVOID *ppv); + DllGetClassObjectFunc DllGetClassObject; + + WINE_StringFromCLSID((LPCLSID)rclsid,xclsid); + + Print(MIN_TRACE, ("\n\tCLSID:\t%s,\n\tIID:\t%s\n", + PRINT_GUID(rclsid), + PRINT_GUID(iid) + )); + + if (pServerInfo) { + Print(MIN_TRACE, ("\tpServerInfo: name=%S\n",pServerInfo->pwszName)); + Print(MIN_TRACE, ("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo)); + } + + /* + * First, try and see if we can't match the class ID with one of the + * registered classes. + */ + if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, ®ClassObject)) + { + /* + * Get the required interface from the retrieved pointer. + */ + hres = IUnknown_QueryInterface(regClassObject, iid, ppv); + + /* + * Since QI got another reference on the pointer, we want to release the + * one we already have. If QI was unsuccessful, this will release the object. This + * is good since we are not returning it in the "out" parameter. + */ + IUnknown_Release(regClassObject); + + return hres; + } + + /* out of process and remote servers not supported yet */ + if ( ((CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER) & dwClsContext) + && !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) + ){ + Print(MIN_TRACE, ("%s %s not supported!\n", + (dwClsContext&CLSCTX_LOCAL_SERVER)?"CLSCTX_LOCAL_SERVER":"", + (dwClsContext&CLSCTX_REMOTE_SERVER)?"CLSCTX_REMOTE_SERVER":"" + )); + return E_ACCESSDENIED; + } + + if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) { + HKEY key; + char buf[200]; + + sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid); + hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key); + + if (hres != ERROR_SUCCESS) { + return REGDB_E_CLASSNOTREG; + } + + memset(dllName,0,sizeof(dllName)); + hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen); + if (hres) + return REGDB_E_CLASSNOTREG; /* FIXME: check retval */ + RegCloseKey(key); + Print(MAX_TRACE, ("found InprocServer32 dll %S\n", dllName)); + + /* open dll, call DllGetClassObject */ + hLibrary = CoLoadLibrary(dllName, TRUE); + if (hLibrary == 0) { + Print(MIN_TRACE, ("couldn't load InprocServer32 dll %S\n", dllName)); + return E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */ + } + DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject"); + if (!DllGetClassObject) { + /* not sure if this should be called here CoFreeLibrary(hLibrary);*/ + Print(MIN_TRACE, ("couldn't find function DllGetClassObject in %S\n", dllName)); + return E_ACCESSDENIED; + } + + /* + * Ask the DLL for its class object. (there was a note here about class + * factories but this is good. + */ + return DllGetClassObject(rclsid, iid, ppv); + } + return hres; +} + +/*********************************************************************** + * CoResumeClassObjects + * + * Resumes classobjects registered with REGCLS suspended + */ +HRESULT WINAPI CoResumeClassObjects(void) +{ + UNIMPLEMENTED; + return S_OK; +} + +/*********************************************************************** + * GetClassFile + * + * This function supplies the CLSID associated with the given filename. + */ +HRESULT WINAPI GetClassFile(LPOLESTR filePathName,CLSID *pclsid) +{ + IStorage *pstg=0; + HRESULT res; + int nbElm=0,length=0,i=0; + LONG sizeProgId=20; + LPOLESTR *pathDec=0,absFile=0,progId=0; + WCHAR extention[100]={0}; + + Print(MAX_TRACE, ("()\n")); + + /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/ + if((StgIsStorageFile(filePathName))==S_OK){ + + res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg); + + if (SUCCEEDED(res)) + res=ReadClassStg(pstg,pclsid); + + IStorage_Release(pstg); + + return res; + } + /* if the file is not a storage object then attemps to match various bits in the file against a + pattern in the registry. this case is not frequently used ! so I present only the psodocode for + this case + + for(i=0;i=0) && (extention[i]=absFile[i]) );i--); + + /* get the progId associated to the extension */ + progId=CoTaskMemAlloc(sizeProgId); + + res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId); + + if (res==ERROR_MORE_DATA){ + + progId = CoTaskMemRealloc(progId,sizeProgId); + res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId); + } + if (res==ERROR_SUCCESS) + /* return the clsid associated to the progId */ + res= CLSIDFromProgID(progId,pclsid); + + for(i=0; pathDec[i]!=NULL;i++) + CoTaskMemFree(pathDec[i]); + CoTaskMemFree(pathDec); + + CoTaskMemFree(progId); + + if (res==ERROR_SUCCESS) + return res; + + return MK_E_INVALIDEXTENSION; +} +/****************************************************************************** + * CoRegisterMessageFilter16 [COMPOBJ.27] + */ +HRESULT WINAPI CoRegisterMessageFilter16( + DWORD lpMessageFilter, + DWORD *lplpMessageFilter +) { + UNIMPLEMENTED; + return 0; +} + +/*********************************************************************** + * CoCreateInstance [COMPOBJ.13, OLE32.7] + */ +HRESULT WINAPI CoCreateInstance( + REFCLSID rclsid, + LPUNKNOWN pUnkOuter, + DWORD dwClsContext, + REFIID iid, + LPVOID *ppv) +{ + HRESULT hres; + LPCLASSFACTORY lpclf = 0; + + /* + * Sanity check + */ + if (ppv==0) + return E_POINTER; + + /* + * Initialize the "out" parameter + */ + *ppv = 0; + + /* + * Get a class factory to construct the object we want. + */ + hres = CoGetClassObject(rclsid, + dwClsContext, + NULL, + &IID_IClassFactory, + (LPVOID)&lpclf); + + if (FAILED(hres)) { + Print(MIN_TRACE, ("no instance created for %s, hres is 0x%08lx\n",PRINT_GUID(iid),hres)); + return hres; + } + + /* + * Create the object and don't forget to release the factory + */ + hres = IClassFactory_CreateInstance(lpclf, pUnkOuter, iid, ppv); + IClassFactory_Release(lpclf); + + return hres; +} + +/*********************************************************************** + * CoCreateInstanceEx [OLE32.165] + */ +HRESULT WINAPI CoCreateInstanceEx( + REFCLSID rclsid, + LPUNKNOWN pUnkOuter, + DWORD dwClsContext, + COSERVERINFO* pServerInfo, + ULONG cmq, + MULTI_QI* pResults) +{ + IUnknown* pUnk = NULL; + HRESULT hr; + ULONG index; + int successCount = 0; + + /* + * Sanity check + */ + if ( (cmq==0) || (pResults==NULL)) + return E_INVALIDARG; + + if (pServerInfo!=NULL) + Print(MIN_TRACE, ("() non-NULL pServerInfo not supported!\n")); + + /* + * Initialize all the "out" parameters. + */ + for (index = 0; index < cmq; index++) + { + pResults[index].pItf = NULL; + pResults[index].hr = E_NOINTERFACE; + } + + /* + * Get the object and get its IUnknown pointer. + */ + hr = CoCreateInstance(rclsid, + pUnkOuter, + dwClsContext, + &IID_IUnknown, + (VOID**)&pUnk); + + if (hr) + return hr; + + /* + * Then, query for all the interfaces requested. + */ + for (index = 0; index < cmq; index++) + { + pResults[index].hr = IUnknown_QueryInterface(pUnk, + pResults[index].pIID, + (VOID**)&(pResults[index].pItf)); + + if (pResults[index].hr == S_OK) + successCount++; + } + + /* + * Release our temporary unknown pointer. + */ + IUnknown_Release(pUnk); + + if (successCount == 0) + return E_NOINTERFACE; + + if (successCount!=cmq) + return CO_S_NOTALLINTERFACES; + + return S_OK; +} + +/*********************************************************************** + * CoFreeLibrary [COMPOBJ.13] + */ +void WINAPI CoFreeLibrary(HINSTANCE hLibrary) +{ + OpenDll *ptr, *prev; + OpenDll *tmp; + + /* lookup library in linked list */ + prev = NULL; + for (ptr = openDllList; ptr != NULL; ptr=ptr->next) { + if (ptr->hLibrary == hLibrary) { + break; + } + prev = ptr; + } + + if (ptr == NULL) { + /* shouldn't happen if user passed in a valid hLibrary */ + return; + } + /* assert: ptr points to the library entry to free */ + + /* free library and remove node from list */ + FreeLibrary(hLibrary); + if (ptr == openDllList) { + tmp = openDllList->next; + HeapFree(GetProcessHeap(), 0, openDllList); + openDllList = tmp; + } else { + tmp = ptr->next; + HeapFree(GetProcessHeap(), 0, ptr); + prev->next = tmp; + } + +} + + +/*********************************************************************** + * CoFreeAllLibraries [COMPOBJ.12] + */ +void WINAPI CoFreeAllLibraries(void) +{ + OpenDll *ptr, *tmp; + + for (ptr = openDllList; ptr != NULL; ) { + tmp=ptr->next; + CoFreeLibrary(ptr->hLibrary); + ptr = tmp; + } +} + + + +/*********************************************************************** + * CoFreeUnusedLibraries [COMPOBJ.17] + */ +void WINAPI CoFreeUnusedLibraries(void) +{ + OpenDll *ptr, *tmp; + typedef HRESULT(*DllCanUnloadNowFunc)(void); + DllCanUnloadNowFunc DllCanUnloadNow; + + for (ptr = openDllList; ptr != NULL; ) { + DllCanUnloadNow = (DllCanUnloadNowFunc) + GetProcAddress(ptr->hLibrary, "DllCanUnloadNow"); + + if ( (DllCanUnloadNow != NULL) && + (DllCanUnloadNow() == S_OK) ) { + tmp=ptr->next; + CoFreeLibrary(ptr->hLibrary); + ptr = tmp; + } else { + ptr=ptr->next; + } + } +} + +/*********************************************************************** + * CoFileTimeNow [COMPOBJ.82, OLE32.10] + * RETURNS + * the current system time in lpFileTime + */ +HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) /* [out] the current time */ +{ + GetSystemTimeAsFileTime( lpFileTime ); + return S_OK; +} + +/*********************************************************************** + * CoTaskMemAlloc (OLE32.43) + * RETURNS + * pointer to newly allocated block + */ +LPVOID WINAPI CoTaskMemAlloc( + ULONG size /* [in] size of memoryblock to be allocated */ +) { + LPMALLOC lpmalloc; + HRESULT ret = CoGetMalloc(0,&lpmalloc); + + if (FAILED(ret)) + return NULL; + + return IMalloc_Alloc(lpmalloc,size); +} +/*********************************************************************** + * CoTaskMemFree (OLE32.44) + */ +VOID WINAPI CoTaskMemFree( + LPVOID ptr /* [in] pointer to be freed */ +) { + LPMALLOC lpmalloc; + HRESULT ret = CoGetMalloc(0,&lpmalloc); + + if (FAILED(ret)) + return; + + IMalloc_Free(lpmalloc, ptr); +} + +/*********************************************************************** + * CoTaskMemRealloc (OLE32.45) + * RETURNS + * pointer to newly allocated block + */ +LPVOID WINAPI CoTaskMemRealloc( + LPVOID pvOld, + ULONG size) /* [in] size of memoryblock to be allocated */ +{ + LPMALLOC lpmalloc; + HRESULT ret = CoGetMalloc(0,&lpmalloc); + + if (FAILED(ret)) + return NULL; + + return IMalloc_Realloc(lpmalloc, pvOld, size); +} + +/*********************************************************************** + * CoLoadLibrary (OLE32.30) + */ +HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree) +{ + HINSTANCE hLibrary; + OpenDll *ptr; + OpenDll *tmp; + + Print(MAX_TRACE, ("(%S, %d)\n", lpszLibName, bAutoFree)); + + hLibrary = LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH); + + if (!bAutoFree) + return hLibrary; + + if (openDllList == NULL) { + /* empty list -- add first node */ + openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll)); + openDllList->hLibrary=hLibrary; + openDllList->next = NULL; + } else { + /* search for this dll */ + int found = FALSE; + for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) { + if (ptr->hLibrary == hLibrary) { + found = TRUE; + break; + } + } + if (!found) { + /* dll not found, add it */ + tmp = openDllList; + openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll)); + openDllList->hLibrary = hLibrary; + openDllList->next = tmp; + } + } + + return hLibrary; +} + +/*********************************************************************** + * CoInitializeWOW (OLE32.27) + */ +HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) { + UNIMPLEMENTED; + return 0; +} + +/****************************************************************************** + * CoLockObjectExternal16 [COMPOBJ.63] + */ +HRESULT WINAPI CoLockObjectExternal16( + LPUNKNOWN pUnk, /* [in] object to be locked */ + BOOL fLock, /* [in] do lock */ + BOOL fLastUnlockReleases /* [in] ? */ +) { + UNIMPLEMENTED; + return S_OK; +} + +/****************************************************************************** + * CoLockObjectExternal [OLE32.31] + */ +HRESULT WINAPI CoLockObjectExternal( + LPUNKNOWN pUnk, /* [in] object to be locked */ + BOOL fLock, /* [in] do lock */ + BOOL fLastUnlockReleases) /* [in] unlock all */ +{ + + if (fLock) + { + /* + * Increment the external lock coutner, COM_ExternalLockAddRef also + * increment the object's internal lock counter. + */ + COM_ExternalLockAddRef( pUnk); + } + else + { + /* + * Decrement the external lock coutner, COM_ExternalLockRelease also + * decrement the object's internal lock counter. + */ + COM_ExternalLockRelease( pUnk, fLastUnlockReleases); + } + + return S_OK; +} + +/*********************************************************************** + * CoGetState16 [COMPOBJ.115] + */ +HRESULT WINAPI CoGetState16(LPDWORD state) +{ + UNIMPLEMENTED + return S_OK; +} +/*********************************************************************** + * CoSetState [COM32.42] + */ +HRESULT WINAPI CoSetState(LPDWORD state) +{ + UNIMPLEMENTED; + return S_OK; +} +/*********************************************************************** + * CoCreateFreeThreadedMarshaler [OLE32.5] + */ +HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN* ppunkMarshal) +{ + UNIMPLEMENTED; + return S_OK; +} + + +/*********************************************************************** + * DllGetClassObject [OLE32.63] + */ +HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) +{ + UNIMPLEMENTED; + *ppv = NULL; + return CLASS_E_CLASSNOTAVAILABLE; +} + + +/*** + * COM_RevokeAllClasses + * + * This method is called when the COM libraries are uninitialized to + * release all the references to the class objects registered with + * the library + */ +static void COM_RevokeAllClasses() +{ + while (firstRegisteredClass!=0) + { + CoRevokeClassObject(firstRegisteredClass->dwCookie); + } +} + +/**************************************************************************** + * COM External Lock methods implementation + */ + +/**************************************************************************** + * Public - Method that increments the count for a IUnknown* in the linked + * list. The item is inserted if not already in the list. + */ +static void COM_ExternalLockAddRef( + IUnknown *pUnk) +{ + COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk); + + /* + * Add an external lock to the object. If it was already externally + * locked, just increase the reference count. If it was not. + * add the item to the list. + */ + if ( externalLock == EL_NOT_FOUND ) + COM_ExternalLockInsert(pUnk); + else + externalLock->uRefCount++; + + /* + * Add an internal lock to the object + */ + IUnknown_AddRef(pUnk); +} + +/**************************************************************************** + * Public - Method that decrements the count for a IUnknown* in the linked + * list. The item is removed from the list if its count end up at zero or if + * bRelAll is TRUE. + */ +static void COM_ExternalLockRelease( + IUnknown *pUnk, + BOOL bRelAll) +{ + COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk); + + if ( externalLock != EL_NOT_FOUND ) + { + do + { + externalLock->uRefCount--; /* release external locks */ + IUnknown_Release(pUnk); /* release local locks as well */ + + if ( bRelAll == FALSE ) + break; /* perform single release */ + + } while ( externalLock->uRefCount > 0 ); + + if ( externalLock->uRefCount == 0 ) /* get rid of the list entry */ + COM_ExternalLockDelete(externalLock); + } +} +/**************************************************************************** + * Public - Method that frees the content of the list. + */ +static void COM_ExternalLockFreeList() +{ + COM_ExternalLock *head; + + head = elList.head; /* grab it by the head */ + while ( head != EL_END_OF_LIST ) + { + COM_ExternalLockDelete(head); /* get rid of the head stuff */ + + head = elList.head; /* get the new head... */ + } +} + +/**************************************************************************** + * Public - Method that dump the content of the list. + */ +void COM_ExternalLockDump() +{ + COM_ExternalLock *current = elList.head; + + Print(MAX_TRACE, ("\nExternal lock list contains:\n")); + + while ( current != EL_END_OF_LIST ) + { + Print(MAX_TRACE, ("\t%p with %lu references count.\n", current->pUnk, current->uRefCount)); + + /* Skip to the next item */ + current = current->next; + } + +} + +/**************************************************************************** + * Internal - Find a IUnknown* in the linked list + */ +static COM_ExternalLock* COM_ExternalLockFind( + IUnknown *pUnk) +{ + return COM_ExternalLockLocate(elList.head, pUnk); +} + +/**************************************************************************** + * Internal - Recursivity agent for IUnknownExternalLockList_Find + */ +static COM_ExternalLock* COM_ExternalLockLocate( + COM_ExternalLock *element, + IUnknown *pUnk) +{ + if ( element == EL_END_OF_LIST ) + return EL_NOT_FOUND; + + else if ( element->pUnk == pUnk ) /* We found it */ + return element; + + else /* Not the right guy, keep on looking */ + return COM_ExternalLockLocate( element->next, pUnk); +} + +/**************************************************************************** + * Internal - Insert a new IUnknown* to the linked list + */ +static BOOL COM_ExternalLockInsert( + IUnknown *pUnk) +{ + COM_ExternalLock *newLock = NULL; + COM_ExternalLock *previousHead = NULL; + + /* + * Allocate space for the new storage object + */ + newLock = HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock)); + + if (newLock!=NULL) + { + if ( elList.head == EL_END_OF_LIST ) + { + elList.head = newLock; /* The list is empty */ + } + else + { + /* + * insert does it at the head + */ + previousHead = elList.head; + elList.head = newLock; + } + + /* + * Set new list item data member + */ + newLock->pUnk = pUnk; + newLock->uRefCount = 1; + newLock->next = previousHead; + + return TRUE; + } + else + return FALSE; +} + +/**************************************************************************** + * Internal - Method that removes an item from the linked list. + */ +static void COM_ExternalLockDelete( + COM_ExternalLock *itemList) +{ + COM_ExternalLock *current = elList.head; + + if ( current == itemList ) + { + /* + * this section handles the deletion of the first node + */ + elList.head = itemList->next; + HeapFree( GetProcessHeap(), 0, itemList); + } + else + { + do + { + if ( current->next == itemList ) /* We found the item to free */ + { + current->next = itemList->next; /* readjust the list pointers */ + + HeapFree( GetProcessHeap(), 0, itemList); + break; + } + + /* Skip to the next item */ + current = current->next; + + } while ( current != EL_END_OF_LIST ); + } +} + +/*********************************************************************** + * COMPOBJ_DllEntryPoint [COMPOBJ.entry] + * + * Initialization code for the COMPOBJ DLL + * + * RETURNS: + */ +BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, DWORD hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2) +{ + Print(MAX_TRACE, ("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize, + res1, res2)); + switch(Reason) + { + case DLL_PROCESS_ATTACH: +#if 0 + if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst; +#endif + break; + + case DLL_PROCESS_DETACH: +#if 0 + if(!--COMPOBJ_Attach) + COMPOBJ_hInstance = 0; +#endif + break; + } + return TRUE; +} + +/****************************************************************************** + * OleGetAutoConvert [OLE32.104] + */ +HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew) +{ + HKEY hkey = 0; + char buf[200]; + WCHAR wbuf[200]; + DWORD len; + HRESULT res = S_OK; + + sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]); + if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey)) + { + res = REGDB_E_CLASSNOTREG; + goto done; + } + len = 200; + /* we can just query for the default value of AutoConvertTo key like that, + without opening the AutoConvertTo key and querying for NULL (default) */ + if (RegQueryValueA(hkey,"AutoConvertTo",buf,&len)) + { + res = REGDB_E_KEYMISSING; + goto done; + } + MultiByteToWideChar( CP_ACP, 0, buf, -1, wbuf, sizeof(wbuf)/sizeof(WCHAR) ); + CLSIDFromString(wbuf,pClsidNew); +done: + if (hkey) RegCloseKey(hkey); + + return res; +} + +/****************************************************************************** + * OleSetAutoConvert [OLE32.126] + */ +HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew) +{ + HKEY hkey = 0, hkeyConvert = 0; + char buf[200], szClsidNew[200]; + HRESULT res = S_OK; + + Print(MAX_TRACE, ("(%p,%p);\n", clsidOld, clsidNew)); + sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]); + WINE_StringFromCLSID(clsidNew, szClsidNew); + if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey)) + { + res = REGDB_E_CLASSNOTREG; + goto done; + } + if (RegCreateKeyA(hkey, "AutoConvertTo", &hkeyConvert)) + { + res = REGDB_E_WRITEREGDB; + goto done; + } + if (RegSetValueExA(hkeyConvert, NULL, 0, + REG_SZ, (LPBYTE)szClsidNew, strlen(szClsidNew)+1)) + { + res = REGDB_E_WRITEREGDB; + goto done; + } + +done: + if (hkeyConvert) RegCloseKey(hkeyConvert); + if (hkey) RegCloseKey(hkey); + + return res; +} + +/*********************************************************************** + * IsEqualGUID [OLE32.76] + * + * Compares two Unique Identifiers. + * + * RETURNS + * TRUE if equal + */ +#undef IsEqualGUID +BOOL WINAPI IsEqualGUID( + REFGUID rguid1, /* [in] unique id 1 */ + REFGUID rguid2 /* [in] unique id 2 */ + ) +{ + return !memcmp(rguid1,rguid2,sizeof(GUID)); +} diff --git a/lib/ole32/compositemoniker.c b/lib/ole32/compositemoniker.c new file mode 100644 index 0000000..337b096 --- /dev/null +++ b/lib/ole32/compositemoniker.c @@ -0,0 +1,1702 @@ +/*************************************************************************************** + * CompositeMonikers implementation + * + * Copyright 1999 Noomen Hamza + ***************************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +#define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */ + +/* CompositeMoniker data structure */ +typedef struct CompositeMonikerImpl{ + + ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/ + + /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether + * two monikers are equal. That's whay IROTData interface is implemented by monikers. + */ + ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/ + + ULONG ref; /* reference counter for this object */ + + IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */ + + ULONG tabSize; /* size of tabMoniker */ + + ULONG tabLastIndex; /* first free index in tabMoniker */ + +} CompositeMonikerImpl; + + +/* EnumMoniker data structure */ +typedef struct EnumMonikerImpl{ + + ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/ + + ULONG ref; /* reference counter for this object */ + + IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */ + + ULONG tabSize; /* size of tabMoniker */ + + ULONG currentPos; /* index pointer on the current moniker */ + +} EnumMonikerImpl; + + +/********************************************************************************/ +/* CompositeMoniker prototype functions : */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface); +static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface); + +/* IPersist prototype functions */ +static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID); + +/* IPersistStream prototype functions */ +static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface); +static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm); +static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty); +static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize); + +/* IMoniker prototype functions */ +static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced); +static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite); +static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker); +static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker); +static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash); +static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning); +static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime); +static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk); +static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix); +static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath); +static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName); +static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut); +static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys); + +/********************************************************************************/ +/* IROTData prototype functions */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject); +static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface); +static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface); + +/* IROTData prototype function */ +static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); + +/* Local function used by CompositeMoniker implementation */ +HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest); +HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface); + +/********************************************************************************/ +/* IEnumMoniker prototype functions */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface); +static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface); + +/* IEnumMoniker prototype functions */ +static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched); +static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt); +static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface); +static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum); + +HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk); + +/********************************************************************************/ +/* Virtual function table for the CompositeMonikerImpl class which includes */ +/* IPersist, IPersistStream and IMoniker functions. */ + +static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + CompositeMonikerImpl_QueryInterface, + CompositeMonikerImpl_AddRef, + CompositeMonikerImpl_Release, + CompositeMonikerImpl_GetClassID, + CompositeMonikerImpl_IsDirty, + CompositeMonikerImpl_Load, + CompositeMonikerImpl_Save, + CompositeMonikerImpl_GetSizeMax, + CompositeMonikerImpl_BindToObject, + CompositeMonikerImpl_BindToStorage, + CompositeMonikerImpl_Reduce, + CompositeMonikerImpl_ComposeWith, + CompositeMonikerImpl_Enum, + CompositeMonikerImpl_IsEqual, + CompositeMonikerImpl_Hash, + CompositeMonikerImpl_IsRunning, + CompositeMonikerImpl_GetTimeOfLastChange, + CompositeMonikerImpl_Inverse, + CompositeMonikerImpl_CommonPrefixWith, + CompositeMonikerImpl_RelativePathTo, + CompositeMonikerImpl_GetDisplayName, + CompositeMonikerImpl_ParseDisplayName, + CompositeMonikerImpl_IsSystemMoniker +}; + +/********************************************************************************/ +/* Virtual function table for the IROTData class. */ +static ICOM_VTABLE(IROTData) VT_ROTDataImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + CompositeMonikerROTDataImpl_QueryInterface, + CompositeMonikerROTDataImpl_AddRef, + CompositeMonikerROTDataImpl_Release, + CompositeMonikerROTDataImpl_GetComparaisonData +}; + +/********************************************************************************/ +/* Virtual function table for the IROTData class */ +static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + EnumMonikerImpl_QueryInterface, + EnumMonikerImpl_AddRef, + EnumMonikerImpl_Release, + EnumMonikerImpl_Next, + EnumMonikerImpl_Skip, + EnumMonikerImpl_Reset, + EnumMonikerImpl_Clone +}; + +/******************************************************************************* + * CompositeMoniker_QueryInterface + *******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS(CompositeMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream, riid) || + IsEqualIID(&IID_IMoniker, riid) + ) + *ppvObject = iface; + else if (IsEqualIID(&IID_IROTData, riid)) + *ppvObject = (IROTData*)&(This->lpvtbl2); + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + CompositeMonikerImpl_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * CompositeMoniker_AddRef + ******************************************************************************/ +ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface) +{ + ICOM_THIS(CompositeMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return ++(This->ref); +} + +/****************************************************************************** + * CompositeMoniker_Release + ******************************************************************************/ +ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface) +{ + ICOM_THIS(CompositeMonikerImpl,iface); + ULONG i; + + Print(MAX_TRACE, ("(%p)\n",This)); + + This->ref--; + + /* destroy the object if there's no more reference on it */ + if (This->ref==0){ + + /* release all the components before destroying this object */ + for (i=0;itabLastIndex;i++) + IMoniker_Release(This->tabMoniker[i]); + + CompositeMonikerImpl_Destroy(This); + + return 0; + } + return This->ref;; +} + +/****************************************************************************** + * CompositeMoniker_GetClassID + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) +{ + Print(MAX_TRACE, ("(%p,%p),stub!\n",iface,pClassID)); + + if (pClassID==NULL) + return E_POINTER; + + *pClassID = CLSID_CompositeMoniker; + + return S_OK; +} + +/****************************************************************************** + * CompositeMoniker_IsDirty + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface) +{ + /* Note that the OLE-provided implementations of the IPersistStream::IsDirty + method in the OLE-provided moniker interfaces always return S_FALSE because + their internal state never changes. */ + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return S_FALSE; +} + +/****************************************************************************** + * CompositeMoniker_Load + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm) +{ + HRESULT res; + DWORD constant; + CLSID clsid; + WCHAR string[1]={0}; + + ICOM_THIS(CompositeMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pStm)); + + /* this function call OleLoadFromStream function for each moniker within this object */ + + /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/ + res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL); + + if (SUCCEEDED(res)&& constant!=3) + return E_FAIL; + + while(1){ +#if 0 + res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]); +#endif + res=ReadClassStm(pStm,&clsid); + Print(MAX_TRACE, ("res=%ld",res)); + if (FAILED(res)) + break; + + if (IsEqualIID(&clsid,&CLSID_FileMoniker)){ + res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]); + if (FAILED(res)) + break; + res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm); + if (FAILED(res)) + break; + } + else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){ + CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]); + if (res!=S_OK) + break; + IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm); + if (FAILED(res)) + break; + } + else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){ + CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]); + if (FAILED(res)) + break; + IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm); + if (FAILED(res)) + break; + } + else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker)) + return E_FAIL; + + else + { + Print(MIN_TRACE, ("()\n")); + /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */ + break; + return E_NOTIMPL; + } + + /* resize the table if needed */ + if (++This->tabLastIndex==This->tabSize){ + + This->tabSize+=BLOCK_TAB_SIZE; + This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); + + if (This->tabMoniker==NULL) + return E_OUTOFMEMORY; + } + } + + return res; +} + +/****************************************************************************** + * CompositeMoniker_Save + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty) +{ + HRESULT res; + IEnumMoniker *enumMk; + IMoniker *pmk; + DWORD constant=3; + + Print(MAX_TRACE, ("(%p,%p,%d)\n",iface,pStm,fClearDirty)); + + /* this function call OleSaveToStream function for each moniker within this object */ + + /* when I tested this function in windows system ! I usually found this constant in the begining of */ + /* the stream I dont known why (there's no indication in specification) ! */ + res=IStream_Write(pStm,&constant,sizeof(constant),NULL); + + IMoniker_Enum(iface,TRUE,&enumMk); + + while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){ + + res=OleSaveToStream((IPersistStream*)pmk,pStm); + + IMoniker_Release(pmk); + + if (FAILED(res)){ + + IEnumMoniker_Release(pmk); + return res; + } + } + + IEnumMoniker_Release(enumMk); + + return S_OK; +} + +/****************************************************************************** + * CompositeMoniker_GetSizeMax + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize) +{ + IEnumMoniker *enumMk; + IMoniker *pmk; + ULARGE_INTEGER ptmpSize; + + /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */ + /* suming all returned sizemax */ + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pcbSize)); + + if (pcbSize!=NULL) + return E_POINTER; + + pcbSize->u.LowPart =0; + pcbSize->u.HighPart=0; + + IMoniker_Enum(iface,TRUE,&enumMk); + + while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){ + + IMoniker_GetSizeMax(pmk,&ptmpSize); + + IMoniker_Release(pmk); + + pcbSize->u.LowPart +=ptmpSize.u.LowPart; + pcbSize->u.HighPart+=ptmpSize.u.HighPart; + } + + IEnumMoniker_Release(enumMk); + + return S_OK; +} + +/****************************************************************************** + * Composite-Moniker_Construct (local function) + *******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest) +{ + DWORD mkSys; + IEnumMoniker *enumMoniker; + IMoniker *tempMk; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,pmkFirst,pmkRest)); + + /* Initialize the virtual fgunction table. */ + This->lpvtbl1 = &VT_CompositeMonikerImpl; + This->lpvtbl2 = &VT_ROTDataImpl; + This->ref = 0; + + This->tabSize=BLOCK_TAB_SIZE; + This->tabLastIndex=0; + + This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker)); + if (This->tabMoniker==NULL) + return E_OUTOFMEMORY; + + IMoniker_IsSystemMoniker(pmkFirst,&mkSys); + + /* put the first moniker contents in the begining of the table */ + if (mkSys!=MKSYS_GENERICCOMPOSITE){ + + This->tabMoniker[(This->tabLastIndex)++]=pmkFirst; + IMoniker_AddRef(pmkFirst); + } + else{ + + IMoniker_Enum(pmkFirst,TRUE,&enumMoniker); + + while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){ + + + if (++This->tabLastIndex==This->tabSize){ + + This->tabSize+=BLOCK_TAB_SIZE; + This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); + + if (This->tabMoniker==NULL) + return E_OUTOFMEMORY; + } + } + + IEnumMoniker_Release(enumMoniker); + } + + /* put the rest moniker contents after the first one and make simplification if needed */ + + IMoniker_IsSystemMoniker(pmkRest,&mkSys); + + if (mkSys!=MKSYS_GENERICCOMPOSITE){ + + /* add a simple moniker to the moniker table */ + + res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk); + + if (res==MK_E_NEEDGENERIC){ + + /* there's no simplification in this case */ + This->tabMoniker[This->tabLastIndex]=pmkRest; + + This->tabLastIndex++; + + IMoniker_AddRef(pmkRest); + } + else if (tempMk==NULL){ + + /* we have an antimoniker after a simple moniker so we can make a simplification in this case */ + IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); + + This->tabLastIndex--; + } + else if (SUCCEEDED(res)){ + + /* the non-generic composition was successful so we can make a simplification in this case */ + IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); + + This->tabMoniker[This->tabLastIndex-1]=tempMk; + } else + return res; + + /* resize tabMoniker if needed */ + if (This->tabLastIndex==This->tabSize){ + + This->tabSize+=BLOCK_TAB_SIZE; + + This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); + + if (This->tabMoniker==NULL) + return E_OUTOFMEMORY; + } + } + else{ + + /* add a composite moniker to the moniker table (do the same thing for each moniker within the */ + /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */ + IMoniker_Enum(pmkRest,TRUE,&enumMoniker); + + while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){ + + res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk); + + if (res==MK_E_NEEDGENERIC){ + + This->tabLastIndex++; + } + else if (tempMk==NULL){ + + IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); + IMoniker_Release(This->tabMoniker[This->tabLastIndex]); + This->tabLastIndex--; + } + else{ + + IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]); + + This->tabMoniker[This->tabLastIndex-1]=tempMk; + } + + if (This->tabLastIndex==This->tabSize){ + + This->tabSize+=BLOCK_TAB_SIZE; + + This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker)); + + if (This->tabMoniker==NULL) + return E_OUTOFMEMORY; + } + } + + IEnumMoniker_Release(enumMoniker); + } + + return S_OK; +} + +/****************************************************************************** + * CompositeMoniker_Destroy (local function) + *******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n",This)); + + HeapFree(GetProcessHeap(),0,This->tabMoniker); + + HeapFree(GetProcessHeap(),0,This); + + return S_OK; +} + +/****************************************************************************** + * CompositeMoniker_BindToObject + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + HRESULT res; + IRunningObjectTable *prot; + IMoniker *tempMk,*antiMk,*mostRigthMk; + IEnumMoniker *enumMoniker; + + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + + if (ppvResult==NULL) + return E_POINTER; + + *ppvResult=0; + /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */ + /* object for the requested interface pointer. */ + if(pmkToLeft==NULL){ + + res=IBindCtx_GetRunningObjectTable(pbc,&prot); + + if (SUCCEEDED(res)){ + + /* if the requested class was loaded befor ! we dont need to reload it */ + res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult); + + if (res==S_OK) + return res; + } + } + else{ + /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */ + /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */ + + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult); + + IMoniker_Release(tempMk); + IMoniker_Release(mostRigthMk); + } + + return res; +} + +/****************************************************************************** + * CompositeMoniker_BindToStorage + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + HRESULT res; + IMoniker *tempMk,*antiMk,*mostRigthMk; + IEnumMoniker *enumMoniker; + + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + + *ppvResult=0; + + /* This method recursively calls BindToStorage on the rightmost component of the composite, */ + /* passing the rest of the composite as the pmkToLeft parameter for that call. */ + + if (pmkToLeft!=NULL){ + + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult); + + IMoniker_Release(tempMk); + + IMoniker_Release(mostRigthMk); + + return res; + } + else + return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult); +} + +/****************************************************************************** + * CompositeMoniker_Reduce + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface, + IBindCtx* pbc, + DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, + IMoniker** ppmkReduced) +{ + HRESULT res; + IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk; + IEnumMoniker *enumMoniker; + + Print(MAX_TRACE, ("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced)); + + if (ppmkReduced==NULL) + return E_POINTER; + + /* This method recursively calls Reduce for each of its component monikers. */ + + if (ppmkToLeft==NULL){ + + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced); + } + else if (*ppmkToLeft==NULL) + + return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced); + + else{ + + /* separate the composite moniker in to left and right moniker */ + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + /* If any of the components reduces itself, the method returns S_OK and passes back a composite */ + /* of the reduced components */ + if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) && + CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk) + ) + + return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced); + + else{ + /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/ + + IMoniker_AddRef(iface); + + *ppmkReduced=iface; + + return MK_S_REDUCED_TO_SELF; + } + } +} + +/****************************************************************************** + * CompositeMoniker_ComposeWith + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface, + IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, + IMoniker** ppmkComposite) +{ + Print(MAX_TRACE, ("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite)); + + if ((ppmkComposite==NULL)||(pmkRight==NULL)) + return E_POINTER; + + *ppmkComposite=0; + + /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */ + /* otherwise, the method returns the result of combining the two monikers by calling the */ + /* CreateGenericComposite function */ + + if (fOnlyIfNotGeneric) + return MK_E_NEEDGENERIC; + + return CreateGenericComposite(iface,pmkRight,ppmkComposite); +} + +/****************************************************************************** + * CompositeMoniker_Enum + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) +{ + ICOM_THIS(CompositeMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%d,%p)\n",iface,fForward,ppenumMoniker)); + + if (ppenumMoniker == NULL) + return E_POINTER; + + return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker); +} + +/****************************************************************************** + * CompositeMoniker_IsEqual + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +{ + IEnumMoniker *enumMoniker1,*enumMoniker2; + IMoniker *tempMk1,*tempMk2; + HRESULT res1,res2,res; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pmkOtherMoniker)); + + if (pmkOtherMoniker==NULL) + return S_FALSE; + + /* This method returns S_OK if the components of both monikers are equal when compared in the */ + /* left-to-right order.*/ + IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1); + + if (enumMoniker1==NULL) + return S_FALSE; + + IMoniker_Enum(iface,TRUE,&enumMoniker2); + + while(1){ + + res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); + res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL); + + if((res1==S_OK)&&(res2==S_OK)){ + + if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){ + res= S_FALSE; + break; + } + else + continue; + } + else if ( (res1==S_FALSE) && (res2==S_FALSE) ){ + res = S_OK; + break; + } + else{ + res = S_FALSE; + break; + } + + if (res1==S_OK) + IMoniker_Release(tempMk1); + + if (res2==S_OK) + IMoniker_Release(tempMk2); + } + + IEnumMoniker_Release(enumMoniker1); + IEnumMoniker_Release(enumMoniker2); + + return res; +} +/****************************************************************************** + * CompositeMoniker_Hash + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) +{ + Print(MIN_TRACE, ("(),stub!\n")); + + return E_NOTIMPL; +} + +/****************************************************************************** + * CompositeMoniker_IsRunning + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + IRunningObjectTable* rot; + HRESULT res; + IMoniker *tempMk,*antiMk,*mostRigthMk; + IEnumMoniker *enumMoniker; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning)); + + /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/ + if (pmkToLeft!=NULL){ + + CreateGenericComposite(pmkToLeft,iface,&tempMk); + + res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning); + + IMoniker_Release(tempMk); + + return res; + } + else + /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */ + /* to this moniker */ + + if (pmkNewlyRunning!=NULL) + + if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK) + return S_OK; + + else + return S_FALSE; + + else{ + + if (pbc==NULL) + return E_POINTER; + + /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */ + /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */ + /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */ + /* the composite as the pmkToLeft parameter for that call. */ + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (FAILED(res)) + return res; + + res = IRunningObjectTable_IsRunning(rot,iface); + IRunningObjectTable_Release(rot); + + if(res==S_OK) + return S_OK; + + else{ + + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning); + + IMoniker_Release(tempMk); + IMoniker_Release(mostRigthMk); + + return res; + } + } +} + +/****************************************************************************** + * CompositeMoniker_GetTimeOfLastChange + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pCompositeTime) +{ + IRunningObjectTable* rot; + HRESULT res; + IMoniker *tempMk,*antiMk,*mostRigthMk; + IEnumMoniker *enumMoniker; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime)); + + if (pCompositeTime==NULL) + return E_INVALIDARG; + + /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */ + /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */ + /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */ + /* of the composite as the pmkToLeft parameter for that call. */ + if (pmkToLeft!=NULL){ + + res=CreateGenericComposite(pmkToLeft,iface,&tempMk); + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (FAILED(res)) + return res; + + if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK) + return res; + else + + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime); + + IMoniker_Release(tempMk); + IMoniker_Release(mostRigthMk); + + return res; + } + else + return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime); +} + +/****************************************************************************** + * CompositeMoniker_Inverse + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +{ + HRESULT res; + IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk; + IEnumMoniker *enumMoniker; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,ppmk)); + + if (ppmk==NULL) + return E_POINTER; + + /* This method returns a composite moniker that consists of the inverses of each of the components */ + /* of the original composite, stored in reverse order */ + + res=CreateAntiMoniker(&antiMk); + res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk); + IMoniker_Release(antiMk); + + if (tempMk==NULL) + + return IMoniker_Inverse(iface,ppmk); + + else{ + + IMoniker_Enum(iface,FALSE,&enumMoniker); + IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL); + IEnumMoniker_Release(enumMoniker); + + IMoniker_Inverse(mostRigthMk,&mostRigthInvMk); + CompositeMonikerImpl_Inverse(tempMk,&tempInvMk); + + res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk); + + IMoniker_Release(tempMk); + IMoniker_Release(mostRigthMk); + IMoniker_Release(tempInvMk); + IMoniker_Release(mostRigthInvMk); + + return res; + } +} + +/****************************************************************************** + * CompositeMoniker_CommonPrefixWith + ******************************************************************************/ +HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +{ + DWORD mkSys; + HRESULT res1,res2; + IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2; + IEnumMoniker *enumMoniker1,*enumMoniker2; + ULONG i,nbCommonMk=0; + + /* If the other moniker is a composite, this method compares the components of each composite from left */ + /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */ + /* of the leftmost components were common to both monikers. */ + + if (ppmkPrefix==NULL) + return E_POINTER; + + *ppmkPrefix=0; + + if (pmkOther==NULL) + return MK_E_NOPREFIX; + + IMoniker_IsSystemMoniker(pmkOther,&mkSys); + + if((mkSys==MKSYS_GENERICCOMPOSITE)){ + + IMoniker_Enum(iface,TRUE,&enumMoniker1); + IMoniker_Enum(pmkOther,TRUE,&enumMoniker2); + + while(1){ + + res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL); + res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL); + + if ((res1==S_FALSE) && (res2==S_FALSE)){ + + /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/ + *ppmkPrefix=iface; + IMoniker_AddRef(iface); + return MK_S_US; + } + else if ((res1==S_OK) && (res2==S_OK)){ + + if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK) + + nbCommonMk++; + + else + break; + + } + else if (res1==S_OK){ + + /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */ + /* ppmkPrefix to the other moniker. */ + *ppmkPrefix=pmkOther; + return MK_S_HIM; + } + else{ + /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */ + /* to this moniker. */ + *ppmkPrefix=iface; + return MK_S_ME; + } + } + + IEnumMoniker_Release(enumMoniker1); + IEnumMoniker_Release(enumMoniker2); + + /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */ + if (nbCommonMk==0) + return MK_E_NOPREFIX; + + IEnumMoniker_Reset(enumMoniker1); + + IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL); + + /* if we have more than one commun moniker the result will be a composite moniker */ + if (nbCommonMk>1){ + + /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/ + IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL); + CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix); + IMoniker_Release(tempMk1); + IMoniker_Release(tempMk2); + + /* compose all common monikers in a composite moniker */ + for(i=0;iref); + +} + +/****************************************************************************** + * EnumMonikerImpl_Release + ******************************************************************************/ +ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) +{ + ICOM_THIS(EnumMonikerImpl,iface); + ULONG i + ; + Print(MAX_TRACE, ("(%p)\n",This)); + + This->ref--; + + /* destroy the object if there's no more reference on it */ + if (This->ref==0){ + + for(i=0;itabSize;i++) + IMoniker_Release(This->tabMoniker[i]); + + HeapFree(GetProcessHeap(),0,This->tabMoniker); + HeapFree(GetProcessHeap(),0,This); + + return 0; + } + return This->ref;; +} + +/****************************************************************************** + * EnumMonikerImpl_Next + ******************************************************************************/ +HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){ + + ICOM_THIS(EnumMonikerImpl,iface); + ULONG i; + + /* retrieve the requested number of moniker from the current position */ + for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++) + + rgelt[i]=This->tabMoniker[This->currentPos++]; + + if (pceltFethed!=NULL) + *pceltFethed= i; + + if (i==celt) + return S_OK; + else + return S_FALSE; +} + +/****************************************************************************** + * EnumMonikerImpl_Skip + ******************************************************************************/ +HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){ + + ICOM_THIS(EnumMonikerImpl,iface); + + if ((This->currentPos+celt) >= This->tabSize) + return S_FALSE; + + This->currentPos+=celt; + + return S_OK; +} + +/****************************************************************************** + * EnumMonikerImpl_Reset + ******************************************************************************/ +HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){ + + ICOM_THIS(EnumMonikerImpl,iface); + + This->currentPos=0; + + return S_OK; +} + +/****************************************************************************** + * EnumMonikerImpl_Clone + ******************************************************************************/ +HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){ + + ICOM_THIS(EnumMonikerImpl,iface); + + return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum); +} + +/****************************************************************************** + * EnumMonikerImpl_CreateEnumMoniker + ******************************************************************************/ +HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, + ULONG tabSize, + ULONG currentPos, + BOOL leftToRigth, + IEnumMoniker ** ppmk) +{ + EnumMonikerImpl* newEnumMoniker; + int i; + + + newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); + + if (newEnumMoniker == 0) + return STG_E_INSUFFICIENTMEMORY; + + if (currentPos > tabSize) + return E_INVALIDARG; + + /* Initialize the virtual function table. */ + ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl; + newEnumMoniker->ref = 0; + + newEnumMoniker->tabSize=tabSize; + newEnumMoniker->currentPos=currentPos; + + newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker)); + + if (newEnumMoniker->tabMoniker==NULL) + return E_OUTOFMEMORY; + + if (leftToRigth) + for (i=0;itabMoniker[i]=tabMoniker[i]; + IMoniker_AddRef(tabMoniker[i]); + } + else + for (i=tabSize-1;i>=0;i--){ + + newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i]; + IMoniker_AddRef(tabMoniker[i]); + } + + *ppmk=(IEnumMoniker*)newEnumMoniker; + + return S_OK; +} + +/****************************************************************************** + * CreateGenericComposite [OLE.55] + ******************************************************************************/ +HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite) +{ + CompositeMonikerImpl* newCompositeMoniker = 0; + HRESULT hr = S_OK; + + Print(MAX_TRACE, ("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite)); + + if (ppmkComposite==NULL) + return E_POINTER; + + *ppmkComposite=0; + + if (pmkFirst==NULL && pmkRest!=NULL){ + + *ppmkComposite=pmkRest; + return S_OK; + } + else if (pmkFirst!=NULL && pmkRest==NULL){ + *ppmkComposite=pmkFirst; + return S_OK; + } + else if (pmkFirst==NULL && pmkRest==NULL) + return S_OK; + + newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl)); + + if (newCompositeMoniker == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest); + + if (FAILED(hr)){ + + HeapFree(GetProcessHeap(),0,newCompositeMoniker); + return hr; + } + if (newCompositeMoniker->tabLastIndex==1) + + hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite); + else + + hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite); + + return hr; +} + +/****************************************************************************** + * MonikerCommonPrefixWith [OLE.55] + ******************************************************************************/ +HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon) +{ + Print(MIN_TRACE, ("(),stub!\n")); + return E_NOTIMPL; +} + + diff --git a/lib/ole32/datacache.c b/lib/ole32/datacache.c new file mode 100644 index 0000000..e5c1ae1 --- /dev/null +++ b/lib/ole32/datacache.c @@ -0,0 +1,2030 @@ +/* + * OLE 2 Data cache + * + * Copyright 1999 Francis Beaudet + * Copyright 2000 Abey George + * + * NOTES: + * The OLE2 data cache supports a whole whack of + * interfaces including: + * IDataObject, IPersistStorage, IViewObject2, + * IOleCache2 and IOleCacheControl. + * + * Most of the implementation details are taken from: Inside OLE + * second edition by Kraig Brockschmidt, + * + * NOTES + * - This implementation of the datacache will let your application + * load documents that have embedded OLE objects in them and it will + * also retrieve the metafile representation of those objects. + * - This implementation of the datacache will also allow your + * application to save new documents with OLE objects in them. + * - The main thing that it doesn't do is allow you to activate + * or modify the OLE objects in any way. + * - I haven't found any good documentation on the real usage of + * the streams created by the data cache. In particular, How to + * determine what the XXX stands for in the stream name + * "\002OlePresXXX". It appears to just be a counter. + * - Also, I don't know the real content of the presentation stream + * header. I was able to figure-out where the extent of the object + * was stored and the aspect, but that's about it. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + + +/**************************************************************************** + * PresentationDataHeader + * + * This structure represents the header of the \002OlePresXXX stream in + * the OLE object strorage. + * + * Most fields are still unknown. + */ +typedef struct PresentationDataHeader +{ + DWORD unknown1; /* -1 */ + DWORD unknown2; /* 3, possibly CF_METAFILEPICT */ + DWORD unknown3; /* 4, possibly TYMED_ISTREAM */ + DVASPECT dvAspect; + DWORD unknown5; /* -1 */ + + DWORD unknown6; + DWORD unknown7; /* 0 */ + DWORD dwObjectExtentX; + DWORD dwObjectExtentY; + DWORD dwSize; +} PresentationDataHeader; + +/**************************************************************************** + * DataCache + */ +struct DataCache +{ + /* + * List all interface VTables here + */ + ICOM_VTABLE(IDataObject)* lpvtbl1; + ICOM_VTABLE(IUnknown)* lpvtbl2; + ICOM_VTABLE(IPersistStorage)* lpvtbl3; + ICOM_VTABLE(IViewObject2)* lpvtbl4; + ICOM_VTABLE(IOleCache2)* lpvtbl5; + ICOM_VTABLE(IOleCacheControl)* lpvtbl6; + + /* + * Reference count of this object + */ + ULONG ref; + + /* + * IUnknown implementation of the outer object. + */ + IUnknown* outerUnknown; + + /* + * This storage pointer is set through a call to + * IPersistStorage_Load. This is where the visual + * representation of the object is stored. + */ + IStorage* presentationStorage; + + /* + * The user of this object can setup ONE advise sink + * connection with the object. These parameters describe + * that connection. + */ + DWORD sinkAspects; + DWORD sinkAdviseFlag; + IAdviseSink* sinkInterface; + +}; + +typedef struct DataCache DataCache; + +/* + * Here, I define utility macros to help with the casting of the + * "this" parameter. + * There is a version to accomodate all of the VTables implemented + * by this object. + */ +#define _ICOM_THIS_From_IDataObject(class,name) class* this = (class*)name; +#define _ICOM_THIS_From_NDIUnknown(class, name) class* this = (class*)(((char*)name)-sizeof(void*)); +#define _ICOM_THIS_From_IPersistStorage(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*)); +#define _ICOM_THIS_From_IViewObject2(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*)); +#define _ICOM_THIS_From_IOleCache2(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*)); +#define _ICOM_THIS_From_IOleCacheControl(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*)); + +/* + * Prototypes for the methods of the DataCache class. + */ +static DataCache* DataCache_Construct(REFCLSID clsid, + LPUNKNOWN pUnkOuter); +static void DataCache_Destroy(DataCache* ptrToDestroy); +static HRESULT DataCache_ReadPresentationData(DataCache* this, + DWORD drawAspect, + PresentationDataHeader* header); +static HRESULT DataCache_OpenPresStream(DataCache *this, + DWORD drawAspect, + IStream **pStm); +static HMETAFILE DataCache_ReadPresMetafile(DataCache* this, + DWORD drawAspect); +static void DataCache_FireOnViewChange(DataCache* this, + DWORD aspect, + LONG lindex); + +/* + * Prototypes for the methods of the DataCache class + * that implement non delegating IUnknown methods. + */ +static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface( + IUnknown* iface, + REFIID riid, + void** ppvObject); +static ULONG WINAPI DataCache_NDIUnknown_AddRef( + IUnknown* iface); +static ULONG WINAPI DataCache_NDIUnknown_Release( + IUnknown* iface); + +/* + * Prototypes for the methods of the DataCache class + * that implement IDataObject methods. + */ +static HRESULT WINAPI DataCache_IDataObject_QueryInterface( + IDataObject* iface, + REFIID riid, + void** ppvObject); +static ULONG WINAPI DataCache_IDataObject_AddRef( + IDataObject* iface); +static ULONG WINAPI DataCache_IDataObject_Release( + IDataObject* iface); +static HRESULT WINAPI DataCache_GetData( + IDataObject* iface, + LPFORMATETC pformatetcIn, + STGMEDIUM* pmedium); +static HRESULT WINAPI DataCache_GetDataHere( + IDataObject* iface, + LPFORMATETC pformatetc, + STGMEDIUM* pmedium); +static HRESULT WINAPI DataCache_QueryGetData( + IDataObject* iface, + LPFORMATETC pformatetc); +static HRESULT WINAPI DataCache_GetCanonicalFormatEtc( + IDataObject* iface, + LPFORMATETC pformatectIn, + LPFORMATETC pformatetcOut); +static HRESULT WINAPI DataCache_IDataObject_SetData( + IDataObject* iface, + LPFORMATETC pformatetc, + STGMEDIUM* pmedium, + BOOL fRelease); +static HRESULT WINAPI DataCache_EnumFormatEtc( + IDataObject* iface, + DWORD dwDirection, + IEnumFORMATETC** ppenumFormatEtc); +static HRESULT WINAPI DataCache_DAdvise( + IDataObject* iface, + FORMATETC* pformatetc, + DWORD advf, + IAdviseSink* pAdvSink, + DWORD* pdwConnection); +static HRESULT WINAPI DataCache_DUnadvise( + IDataObject* iface, + DWORD dwConnection); +static HRESULT WINAPI DataCache_EnumDAdvise( + IDataObject* iface, + IEnumSTATDATA** ppenumAdvise); + +/* + * Prototypes for the methods of the DataCache class + * that implement IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface( + IPersistStorage* iface, + REFIID riid, + void** ppvObject); +static ULONG WINAPI DataCache_IPersistStorage_AddRef( + IPersistStorage* iface); +static ULONG WINAPI DataCache_IPersistStorage_Release( + IPersistStorage* iface); +static HRESULT WINAPI DataCache_GetClassID( + IPersistStorage* iface, + CLSID* pClassID); +static HRESULT WINAPI DataCache_IsDirty( + IPersistStorage* iface); +static HRESULT WINAPI DataCache_InitNew( + IPersistStorage* iface, + IStorage* pStg); +static HRESULT WINAPI DataCache_Load( + IPersistStorage* iface, + IStorage* pStg); +static HRESULT WINAPI DataCache_Save( + IPersistStorage* iface, + IStorage* pStg, + BOOL fSameAsLoad); +static HRESULT WINAPI DataCache_SaveCompleted( + IPersistStorage* iface, + IStorage* pStgNew); +static HRESULT WINAPI DataCache_HandsOffStorage( + IPersistStorage* iface); + +/* + * Prototypes for the methods of the DataCache class + * that implement IViewObject2 methods. + */ +static HRESULT WINAPI DataCache_IViewObject2_QueryInterface( + IViewObject2* iface, + REFIID riid, + void** ppvObject); +static ULONG WINAPI DataCache_IViewObject2_AddRef( + IViewObject2* iface); +static ULONG WINAPI DataCache_IViewObject2_Release( + IViewObject2* iface); +static HRESULT WINAPI DataCache_Draw( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hdcTargetDev, + HDC hdcDraw, + LPCRECTL lprcBounds, + LPCRECTL lprcWBounds, + IVO_ContCallback pfnContinue, + DWORD dwContinue); +static HRESULT WINAPI DataCache_GetColorSet( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hicTargetDevice, + LOGPALETTE** ppColorSet); +static HRESULT WINAPI DataCache_Freeze( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DWORD* pdwFreeze); +static HRESULT WINAPI DataCache_Unfreeze( + IViewObject2* iface, + DWORD dwFreeze); +static HRESULT WINAPI DataCache_SetAdvise( + IViewObject2* iface, + DWORD aspects, + DWORD advf, + IAdviseSink* pAdvSink); +static HRESULT WINAPI DataCache_GetAdvise( + IViewObject2* iface, + DWORD* pAspects, + DWORD* pAdvf, + IAdviseSink** ppAdvSink); +static HRESULT WINAPI DataCache_GetExtent( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + DVTARGETDEVICE* ptd, + LPSIZEL lpsizel); + +/* + * Prototypes for the methods of the DataCache class + * that implement IOleCache2 methods. + */ +static HRESULT WINAPI DataCache_IOleCache2_QueryInterface( + IOleCache2* iface, + REFIID riid, + void** ppvObject); +static ULONG WINAPI DataCache_IOleCache2_AddRef( + IOleCache2* iface); +static ULONG WINAPI DataCache_IOleCache2_Release( + IOleCache2* iface); +static HRESULT WINAPI DataCache_Cache( + IOleCache2* iface, + FORMATETC* pformatetc, + DWORD advf, + DWORD* pdwConnection); +static HRESULT WINAPI DataCache_Uncache( + IOleCache2* iface, + DWORD dwConnection); +static HRESULT WINAPI DataCache_EnumCache( + IOleCache2* iface, + IEnumSTATDATA** ppenumSTATDATA); +static HRESULT WINAPI DataCache_InitCache( + IOleCache2* iface, + IDataObject* pDataObject); +static HRESULT WINAPI DataCache_IOleCache2_SetData( + IOleCache2* iface, + FORMATETC* pformatetc, + STGMEDIUM* pmedium, + BOOL fRelease); +static HRESULT WINAPI DataCache_UpdateCache( + IOleCache2* iface, + LPDATAOBJECT pDataObject, + DWORD grfUpdf, + LPVOID pReserved); +static HRESULT WINAPI DataCache_DiscardCache( + IOleCache2* iface, + DWORD dwDiscardOptions); + +/* + * Prototypes for the methods of the DataCache class + * that implement IOleCacheControl methods. + */ +static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface( + IOleCacheControl* iface, + REFIID riid, + void** ppvObject); +static ULONG WINAPI DataCache_IOleCacheControl_AddRef( + IOleCacheControl* iface); +static ULONG WINAPI DataCache_IOleCacheControl_Release( + IOleCacheControl* iface); +static HRESULT WINAPI DataCache_OnRun( + IOleCacheControl* iface, + LPDATAOBJECT pDataObject); +static HRESULT WINAPI DataCache_OnStop( + IOleCacheControl* iface); + +/* + * Virtual function tables for the DataCache class. + */ +static ICOM_VTABLE(IUnknown) DataCache_NDIUnknown_VTable = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + DataCache_NDIUnknown_QueryInterface, + DataCache_NDIUnknown_AddRef, + DataCache_NDIUnknown_Release +}; + +static ICOM_VTABLE(IDataObject) DataCache_IDataObject_VTable = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + DataCache_IDataObject_QueryInterface, + DataCache_IDataObject_AddRef, + DataCache_IDataObject_Release, + DataCache_GetData, + DataCache_GetDataHere, + DataCache_QueryGetData, + DataCache_GetCanonicalFormatEtc, + DataCache_IDataObject_SetData, + DataCache_EnumFormatEtc, + DataCache_DAdvise, + DataCache_DUnadvise, + DataCache_EnumDAdvise +}; + +static ICOM_VTABLE(IPersistStorage) DataCache_IPersistStorage_VTable = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + DataCache_IPersistStorage_QueryInterface, + DataCache_IPersistStorage_AddRef, + DataCache_IPersistStorage_Release, + DataCache_GetClassID, + DataCache_IsDirty, + DataCache_InitNew, + DataCache_Load, + DataCache_Save, + DataCache_SaveCompleted, + DataCache_HandsOffStorage +}; + +static ICOM_VTABLE(IViewObject2) DataCache_IViewObject2_VTable = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + DataCache_IViewObject2_QueryInterface, + DataCache_IViewObject2_AddRef, + DataCache_IViewObject2_Release, + DataCache_Draw, + DataCache_GetColorSet, + DataCache_Freeze, + DataCache_Unfreeze, + DataCache_SetAdvise, + DataCache_GetAdvise, + DataCache_GetExtent +}; + +static ICOM_VTABLE(IOleCache2) DataCache_IOleCache2_VTable = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + DataCache_IOleCache2_QueryInterface, + DataCache_IOleCache2_AddRef, + DataCache_IOleCache2_Release, + DataCache_Cache, + DataCache_Uncache, + DataCache_EnumCache, + DataCache_InitCache, + DataCache_IOleCache2_SetData, + DataCache_UpdateCache, + DataCache_DiscardCache +}; + +static ICOM_VTABLE(IOleCacheControl) DataCache_IOleCacheControl_VTable = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + DataCache_IOleCacheControl_QueryInterface, + DataCache_IOleCacheControl_AddRef, + DataCache_IOleCacheControl_Release, + DataCache_OnRun, + DataCache_OnStop +}; + +/****************************************************************************** + * CreateDataCache [OLE32.54] + */ +HRESULT WINAPI CreateDataCache( + LPUNKNOWN pUnkOuter, + REFCLSID rclsid, + REFIID riid, + LPVOID* ppvObj) +{ + DataCache* newCache = NULL; + HRESULT hr = S_OK; + + Print(MAX_TRACE, ("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj)); + + /* + * Sanity check + */ + if (ppvObj==0) + return E_POINTER; + + *ppvObj = 0; + + /* + * If this cache is constructed for aggregation, make sure + * the caller is requesting the IUnknown interface. + * This is necessary because it's the only time the non-delegating + * IUnknown pointer can be returned to the outside. + */ + if ( (pUnkOuter!=NULL) && + (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) ) + return CLASS_E_NOAGGREGATION; + + /* + * Try to construct a new instance of the class. + */ + newCache = DataCache_Construct(rclsid, + pUnkOuter); + + if (newCache == 0) + return E_OUTOFMEMORY; + + /* + * Make sure it supports the interface required by the caller. + */ + hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj); + + /* + * Release the reference obtained in the constructor. If + * the QueryInterface was unsuccessful, it will free the class. + */ + IUnknown_Release((IUnknown*)&(newCache->lpvtbl2)); + + return hr; +} + +/********************************************************* + * Method implementation for DataCache class. + */ +static DataCache* DataCache_Construct( + REFCLSID clsid, + LPUNKNOWN pUnkOuter) +{ + DataCache* newObject = 0; + + /* + * Allocate space for the object. + */ + newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache)); + + if (newObject==0) + return newObject; + + /* + * Initialize the virtual function table. + */ + newObject->lpvtbl1 = &DataCache_IDataObject_VTable; + newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable; + newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable; + newObject->lpvtbl4 = &DataCache_IViewObject2_VTable; + newObject->lpvtbl5 = &DataCache_IOleCache2_VTable; + newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable; + + /* + * Start with one reference count. The caller of this function + * must release the interface pointer when it is done. + */ + newObject->ref = 1; + + /* + * Initialize the outer unknown + * We don't keep a reference on the outer unknown since, the way + * aggregation works, our lifetime is at least as large as it's + * lifetime. + */ + if (pUnkOuter==NULL) + pUnkOuter = (IUnknown*)&(newObject->lpvtbl2); + + newObject->outerUnknown = pUnkOuter; + + /* + * Initialize the other members of the structure. + */ + newObject->presentationStorage = NULL; + newObject->sinkAspects = 0; + newObject->sinkAdviseFlag = 0; + newObject->sinkInterface = 0; + + return newObject; +} + +static void DataCache_Destroy( + DataCache* ptrToDestroy) +{ + Print(MAX_TRACE, ("()\n")); + + if (ptrToDestroy->sinkInterface != NULL) + { + IAdviseSink_Release(ptrToDestroy->sinkInterface); + ptrToDestroy->sinkInterface = NULL; + } + + if (ptrToDestroy->presentationStorage != NULL) + { + IStorage_Release(ptrToDestroy->presentationStorage); + ptrToDestroy->presentationStorage = NULL; + } + + /* + * Free the datacache pointer. + */ + HeapFree(GetProcessHeap(), 0, ptrToDestroy); +} + +/************************************************************************ + * DataCache_ReadPresentationData + * + * This method will read information for the requested presentation + * into the given structure. + * + * Param: + * this - Pointer to the DataCache object + * drawAspect - The aspect of the object that we wish to draw. + * header - The structure containing information about this + * aspect of the object. + */ +static HRESULT DataCache_ReadPresentationData( + DataCache* this, + DWORD drawAspect, + PresentationDataHeader* header) +{ + IStream* presStream = NULL; + HRESULT hres; + + /* + * Open the presentation stream. + */ + hres = DataCache_OpenPresStream( + this, + drawAspect, + &presStream); + + if (FAILED(hres)) + return hres; + + /* + * Read the header. + */ + + hres = IStream_Read( + presStream, + header, + sizeof(PresentationDataHeader), + NULL); + + /* + * Cleanup. + */ + IStream_Release(presStream); + + /* + * We don't want to propagate any other error + * code than a failure. + */ + if (hres!=S_OK) + hres = E_FAIL; + + return hres; +} + +/************************************************************************ + * DataCache_FireOnViewChange + * + * This method will fire an OnViewChange notification to the advise + * sink registered with the datacache. + * + * See IAdviseSink::OnViewChange for more details. + */ +static void DataCache_FireOnViewChange( + DataCache* this, + DWORD aspect, + LONG lindex) +{ + Print(MAX_TRACE, ("(%p, %lx, %ld)\n", this, aspect, lindex)); + + /* + * The sink supplies a filter when it registers + * we make sure we only send the notifications when that + * filter matches. + */ + if ((this->sinkAspects & aspect) != 0) + { + if (this->sinkInterface != NULL) + { + IAdviseSink_OnViewChange(this->sinkInterface, + aspect, + lindex); + + /* + * Some sinks want to be unregistered automatically when + * the first notification goes out. + */ + if ( (this->sinkAdviseFlag & ADVF_ONLYONCE) != 0) + { + IAdviseSink_Release(this->sinkInterface); + + this->sinkInterface = NULL; + this->sinkAspects = 0; + this->sinkAdviseFlag = 0; + } + } + } +} + +/* Helper for DataCache_OpenPresStream */ +static BOOL DataCache_IsPresentationStream(const STATSTG *elem) +{ +#if 0 + /* The presentation streams have names of the form "\002OlePresXXX", + * where XXX goes from 000 to 999. */ + static const WCHAR OlePres[] = { 2,'O','l','e','P','r','e','s' }; + + LPCWSTR name = elem->pwcsName; + + return (elem->type == STGTY_STREAM) + && (elem->cbSize.u.LowPart >= sizeof(PresentationDataHeader)) + && (lstrlenW(name) == 11) + && (strncmpW(name, OlePres, 8) == 0) + && (name[8] >= '0') && (name[8] <= '9') + && (name[9] >= '0') && (name[9] <= '9') + && (name[10] >= '0') && (name[10] <= '9'); +#else + UNIMPLEMENTED; + return FALSE; +#endif +} + +/************************************************************************ + * DataCache_OpenPresStream + * + * This method will find the stream for the given presentation. It makes + * no attempt at fallback. + * + * Param: + * this - Pointer to the DataCache object + * drawAspect - The aspect of the object that we wish to draw. + * pStm - A returned stream. It points to the beginning of the + * - presentation data, including the header. + * + * Errors: + * S_OK The requested stream has been opened. + * OLE_E_BLANK The requested stream could not be found. + * Quite a few others I'm too lazy to map correctly. + * + * Notes: + * Algorithm: Scan the elements of the presentation storage, looking + * for presentation streams. For each presentation stream, + * load the header and check to see if the aspect maches. + * + * If a fallback is desired, just opening the first presentation stream + * is a possibility. + */ +static HRESULT DataCache_OpenPresStream( + DataCache *this, + DWORD drawAspect, + IStream **ppStm) +{ + STATSTG elem; + IEnumSTATSTG *pEnum; + HRESULT hr; + + if (!ppStm) return E_POINTER; + + hr = IStorage_EnumElements(this->presentationStorage, 0, NULL, 0, &pEnum); + if (FAILED(hr)) return hr; + + while ((hr = IEnumSTATSTG_Next(pEnum, 1, &elem, NULL)) == S_OK) + { + if (DataCache_IsPresentationStream(&elem)) + { + IStream *pStm; + + hr = IStorage_OpenStream(this->presentationStorage, elem.pwcsName, + NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, + &pStm); + if (SUCCEEDED(hr)) + { + PresentationDataHeader header; + ULONG actual_read; + + hr = IStream_Read(pStm, &header, sizeof(header), &actual_read); + + /* can't use SUCCEEDED(hr): S_FALSE counts as an error */ + if (hr == S_OK && actual_read == sizeof(header) + && header.dvAspect == drawAspect) + { + /* Rewind the stream before returning it. */ + LARGE_INTEGER offset; + offset.u.LowPart = 0; + offset.u.HighPart = 0; + IStream_Seek(pStm, offset, STREAM_SEEK_SET, NULL); + + *ppStm = pStm; + + CoTaskMemFree(elem.pwcsName); + IEnumSTATSTG_Release(pEnum); + + return S_OK; + } + + IStream_Release(pStm); + } + } + + CoTaskMemFree(elem.pwcsName); + } + + IEnumSTATSTG_Release(pEnum); + + return (hr == S_FALSE ? OLE_E_BLANK : hr); +} + +/************************************************************************ + * DataCache_ReadPresentationData + * + * This method will read information for the requested presentation + * into the given structure. + * + * Param: + * this - Pointer to the DataCache object + * drawAspect - The aspect of the object that we wish to draw. + * + * Returns: + * This method returns a metafile handle if it is successful. + * it will return 0 if not. + */ +static HMETAFILE DataCache_ReadPresMetafile( + DataCache* this, + DWORD drawAspect) +{ + LARGE_INTEGER offset; + IStream* presStream = NULL; + HRESULT hres; + void* metafileBits; + STATSTG streamInfo; + HMETAFILE newMetafile = 0; + + /* + * Open the presentation stream. + */ + hres = DataCache_OpenPresStream( + this, + drawAspect, + &presStream); + + if (FAILED(hres)) + return newMetafile; + + /* + * Get the size of the stream. + */ + hres = IStream_Stat(presStream, + &streamInfo, + STATFLAG_NONAME); + + /* + * Skip the header + */ + offset.u.HighPart = 0; + offset.u.LowPart = sizeof(PresentationDataHeader); + + hres = IStream_Seek( + presStream, + offset, + STREAM_SEEK_SET, + NULL); + + streamInfo.cbSize.u.LowPart -= offset.u.LowPart; + + /* + * Allocate a buffer for the metafile bits. + */ + metafileBits = HeapAlloc(GetProcessHeap(), + 0, + streamInfo.cbSize.u.LowPart); + + /* + * Read the metafile bits. + */ + hres = IStream_Read( + presStream, + metafileBits, + streamInfo.cbSize.u.LowPart, + NULL); + + /* + * Create a metafile with those bits. + */ + if (SUCCEEDED(hres)) + { + newMetafile = SetMetaFileBitsEx(streamInfo.cbSize.u.LowPart, metafileBits); + } + + /* + * Cleanup. + */ + HeapFree(GetProcessHeap(), 0, metafileBits); + IStream_Release(presStream); + + if (newMetafile==0) + hres = E_FAIL; + + return newMetafile; +} + +/********************************************************* + * Method implementation for the non delegating IUnknown + * part of the DataCache class. + */ + +/************************************************************************ + * DataCache_NDIUnknown_QueryInterface (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + * + * This version of QueryInterface will not delegate it's implementation + * to the outer unknown. + */ +static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface( + IUnknown* iface, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_NDIUnknown(DataCache, iface); + + /* + * Perform a sanity check on the parameters. + */ + if ( (this==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) + { + *ppvObject = iface; + } + else if (memcmp(&IID_IDataObject, riid, sizeof(IID_IDataObject)) == 0) + { + *ppvObject = (IDataObject*)&(this->lpvtbl1); + } + else if ( (memcmp(&IID_IPersistStorage, riid, sizeof(IID_IPersistStorage)) == 0) || + (memcmp(&IID_IPersist, riid, sizeof(IID_IPersist)) == 0) ) + { + *ppvObject = (IPersistStorage*)&(this->lpvtbl3); + } + else if ( (memcmp(&IID_IViewObject, riid, sizeof(IID_IViewObject)) == 0) || + (memcmp(&IID_IViewObject2, riid, sizeof(IID_IViewObject2)) == 0) ) + { + *ppvObject = (IViewObject2*)&(this->lpvtbl4); + } + else if ( (memcmp(&IID_IOleCache, riid, sizeof(IID_IOleCache)) == 0) || + (memcmp(&IID_IOleCache2, riid, sizeof(IID_IOleCache2)) == 0) ) + { + *ppvObject = (IOleCache2*)&(this->lpvtbl5); + } + else if (memcmp(&IID_IOleCacheControl, riid, sizeof(IID_IOleCacheControl)) == 0) + { + *ppvObject = (IOleCacheControl*)&(this->lpvtbl6); + } + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + { + Print(MID_TRACE, ( "() : asking for unsupported interface %s\n", PRINT_GUID(riid))); + return E_NOINTERFACE; + } + + /* + * Query Interface always increases the reference count by one when it is + * successful. + */ + IUnknown_AddRef((IUnknown*)*ppvObject); + + return S_OK;; +} + +/************************************************************************ + * DataCache_NDIUnknown_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + * + * This version of QueryInterface will not delegate it's implementation + * to the outer unknown. + */ +static ULONG WINAPI DataCache_NDIUnknown_AddRef( + IUnknown* iface) +{ + _ICOM_THIS_From_NDIUnknown(DataCache, iface); + + this->ref++; + + return this->ref; +} + +/************************************************************************ + * DataCache_NDIUnknown_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + * + * This version of QueryInterface will not delegate it's implementation + * to the outer unknown. + */ +static ULONG WINAPI DataCache_NDIUnknown_Release( + IUnknown* iface) +{ + _ICOM_THIS_From_NDIUnknown(DataCache, iface); + + /* + * Decrease the reference count on this object. + */ + this->ref--; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (this->ref==0) + { + DataCache_Destroy(this); + + return 0; + } + + return this->ref; +} + +/********************************************************* + * Method implementation for the IDataObject + * part of the DataCache class. + */ + +/************************************************************************ + * DataCache_IDataObject_QueryInterface (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static HRESULT WINAPI DataCache_IDataObject_QueryInterface( + IDataObject* iface, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_IDataObject(DataCache, iface); + + return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject); +} + +/************************************************************************ + * DataCache_IDataObject_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IDataObject_AddRef( + IDataObject* iface) +{ + _ICOM_THIS_From_IDataObject(DataCache, iface); + + return IUnknown_AddRef(this->outerUnknown); +} + +/************************************************************************ + * DataCache_IDataObject_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IDataObject_Release( + IDataObject* iface) +{ + _ICOM_THIS_From_IDataObject(DataCache, iface); + + return IUnknown_Release(this->outerUnknown); +} + +/************************************************************************ + * DataCache_GetData + * + * Get Data from a source dataobject using format pformatetcIn->cfFormat + * See Windows documentation for more details on GetData. + * TODO: Currently only CF_METAFILEPICT is implemented + */ +static HRESULT WINAPI DataCache_GetData( + IDataObject* iface, + LPFORMATETC pformatetcIn, + STGMEDIUM* pmedium) +{ + HRESULT hr = 0; + HRESULT hrRet = E_UNEXPECTED; + IPersistStorage *pPersistStorage = 0; + IStorage *pStorage = 0; + IStream *pStream = 0; + OLECHAR name[]={ 2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0}; + HGLOBAL hGlobalMF = 0; + void *mfBits = 0; + PresentationDataHeader pdh; + METAFILEPICT *mfPict; + HMETAFILE hMetaFile = 0; + + if (pformatetcIn->cfFormat == CF_METAFILEPICT) + { + /* Get the Persist Storage */ + + hr = IDataObject_QueryInterface(iface, &IID_IPersistStorage, (void**)&pPersistStorage); + + if (hr != S_OK) + goto cleanup; + + /* Create a doc file to copy the doc to a storage */ + + hr = StgCreateDocfile(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage); + + if (hr != S_OK) + goto cleanup; + + /* Save it to storage */ +#if 0 + hr = OleSave(pPersistStorage, pStorage, FALSE); +#else + Print(MIN_TRACE, ("OleSave() not found\n")); +#endif + + if (hr != S_OK) + goto cleanup; + + /* Open the Presentation data srteam */ + + hr = IStorage_OpenStream(pStorage, name, 0, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &pStream); + + if (hr != S_OK) + goto cleanup; + + /* Read the presentation header */ + + hr = IStream_Read(pStream, &pdh, sizeof(PresentationDataHeader), NULL); + + if (hr != S_OK) + goto cleanup; + + mfBits = HeapAlloc(GetProcessHeap(), 0, pdh.dwSize); + + /* Read the Metafile bits */ + + hr = IStream_Read(pStream, mfBits, pdh.dwSize, NULL); + + if (hr != S_OK) + goto cleanup; + + /* Create the metafile and place it in the STGMEDIUM structure */ + + hMetaFile = SetMetaFileBitsEx(pdh.dwSize, mfBits); + + hGlobalMF = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT)); + mfPict = (METAFILEPICT *)GlobalLock(hGlobalMF); +#if 0 + mfPict->hMF = hMetaFile; +#else + Print(MIN_TRACE, ("Depending on MetaFile implementation\n")); +#endif + + GlobalUnlock(hGlobalMF); + + pmedium->u.hGlobal = hGlobalMF; + pmedium->tymed = TYMED_MFPICT; + hrRet = S_OK; + +cleanup: + + if (mfBits) + HeapFree(GetProcessHeap(), 0, mfBits); + + if (pStream) + IStream_Release(pStream); + + if (pStorage) + IStorage_Release(pStorage); + + if (pPersistStorage) + IPersistStorage_Release(pPersistStorage); + + return hrRet; + } + + /* TODO: Other formats are not implemented */ + + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_GetDataHere( + IDataObject* iface, + LPFORMATETC pformatetc, + STGMEDIUM* pmedium) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_QueryGetData( + IDataObject* iface, + LPFORMATETC pformatetc) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/************************************************************************ + * DataCache_EnumFormatEtc (IDataObject) + * + * The data cache doesn't implement this method. + * + * See Windows documentation for more details on IDataObject methods. + */ +static HRESULT WINAPI DataCache_GetCanonicalFormatEtc( + IDataObject* iface, + LPFORMATETC pformatectIn, + LPFORMATETC pformatetcOut) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/************************************************************************ + * DataCache_IDataObject_SetData (IDataObject) + * + * This method is delegated to the IOleCache2 implementation. + * + * See Windows documentation for more details on IDataObject methods. + */ +static HRESULT WINAPI DataCache_IDataObject_SetData( + IDataObject* iface, + LPFORMATETC pformatetc, + STGMEDIUM* pmedium, + BOOL fRelease) +{ + IOleCache2* oleCache = NULL; + HRESULT hres; + + Print(MAX_TRACE, ("(%p, %p, %p, %d)\n", iface, pformatetc, pmedium, fRelease)); + + hres = IDataObject_QueryInterface(iface, &IID_IOleCache2, (void**)&oleCache); + + if (FAILED(hres)) + return E_UNEXPECTED; + + hres = IOleCache2_SetData(oleCache, pformatetc, pmedium, fRelease); + + IOleCache2_Release(oleCache); + + return hres;; +} + +/************************************************************************ + * DataCache_EnumFormatEtc (IDataObject) + * + * The data cache doesn't implement this method. + * + * See Windows documentation for more details on IDataObject methods. + */ +static HRESULT WINAPI DataCache_EnumFormatEtc( + IDataObject* iface, + DWORD dwDirection, + IEnumFORMATETC** ppenumFormatEtc) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/************************************************************************ + * DataCache_DAdvise (IDataObject) + * + * The data cache doesn't support connections. + * + * See Windows documentation for more details on IDataObject methods. + */ +static HRESULT WINAPI DataCache_DAdvise( + IDataObject* iface, + FORMATETC* pformatetc, + DWORD advf, + IAdviseSink* pAdvSink, + DWORD* pdwConnection) +{ + UNIMPLEMENTED; + return OLE_E_ADVISENOTSUPPORTED; +} + +/************************************************************************ + * DataCache_DUnadvise (IDataObject) + * + * The data cache doesn't support connections. + * + * See Windows documentation for more details on IDataObject methods. + */ +static HRESULT WINAPI DataCache_DUnadvise( + IDataObject* iface, + DWORD dwConnection) +{ + UNIMPLEMENTED; + return OLE_E_NOCONNECTION; +} + +/************************************************************************ + * DataCache_EnumDAdvise (IDataObject) + * + * The data cache doesn't support connections. + * + * See Windows documentation for more details on IDataObject methods. + */ +static HRESULT WINAPI DataCache_EnumDAdvise( + IDataObject* iface, + IEnumSTATDATA** ppenumAdvise) +{ + UNIMPLEMENTED; + return OLE_E_ADVISENOTSUPPORTED; +} + +/********************************************************* + * Method implementation for the IDataObject + * part of the DataCache class. + */ + +/************************************************************************ + * DataCache_IPersistStorage_QueryInterface (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface( + IPersistStorage* iface, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_IPersistStorage(DataCache, iface); + + return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject); +} + +/************************************************************************ + * DataCache_IPersistStorage_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IPersistStorage_AddRef( + IPersistStorage* iface) +{ + _ICOM_THIS_From_IPersistStorage(DataCache, iface); + + return IUnknown_AddRef(this->outerUnknown); +} + +/************************************************************************ + * DataCache_IPersistStorage_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IPersistStorage_Release( + IPersistStorage* iface) +{ + _ICOM_THIS_From_IPersistStorage(DataCache, iface); + + return IUnknown_Release(this->outerUnknown); +} + +/************************************************************************ + * DataCache_GetClassID (IPersistStorage) + * + * The data cache doesn't implement this method. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_GetClassID( + IPersistStorage* iface, + CLSID* pClassID) +{ + Print(MAX_TRACE, ("(%p, %p)\n", iface, pClassID)); + return E_NOTIMPL; +} + +/************************************************************************ + * DataCache_IsDirty (IPersistStorage) + * + * Until we actully connect to a running object and retrieve new + * information to it, we never get dirty. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_IsDirty( + IPersistStorage* iface) +{ + Print(MAX_TRACE, ("(%p)\n", iface)); + + return S_FALSE; +} + +/************************************************************************ + * DataCache_InitNew (IPersistStorage) + * + * The data cache implementation of IPersistStorage_InitNew simply stores + * the storage pointer. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_InitNew( + IPersistStorage* iface, + IStorage* pStg) +{ + Print(MAX_TRACE, ("(%p, %p)\n", iface, pStg)); + + return DataCache_Load(iface, pStg); +} + +/************************************************************************ + * DataCache_Load (IPersistStorage) + * + * The data cache implementation of IPersistStorage_Load doesn't + * actually load anything. Instead, it holds on to the storage pointer + * and it will load the presentation information when the + * IDataObject_GetData or IViewObject2_Draw methods are called. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_Load( + IPersistStorage* iface, + IStorage* pStg) +{ + _ICOM_THIS_From_IPersistStorage(DataCache, iface); + + Print(MAX_TRACE, ("(%p, %p)\n", iface, pStg)); + + if (this->presentationStorage != NULL) + { + IStorage_Release(this->presentationStorage); + } + + this->presentationStorage = pStg; + + if (this->presentationStorage != NULL) + { + IStorage_AddRef(this->presentationStorage); + } + return S_OK; +} + +/************************************************************************ + * DataCache_Save (IPersistStorage) + * + * Until we actully connect to a running object and retrieve new + * information to it, we never have to save anything. However, it is + * our responsability to copy the information when saving to a new + * storage. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_Save( + IPersistStorage* iface, + IStorage* pStg, + BOOL fSameAsLoad) +{ + _ICOM_THIS_From_IPersistStorage(DataCache, iface); + + Print(MAX_TRACE, ("(%p, %p, %d)\n", iface, pStg, fSameAsLoad)); + + if ( (!fSameAsLoad) && + (this->presentationStorage!=NULL) ) + { + return IStorage_CopyTo(this->presentationStorage, + 0, + NULL, + NULL, + pStg); + } + + return S_OK; +} + +/************************************************************************ + * DataCache_SaveCompleted (IPersistStorage) + * + * This method is called to tell the cache to release the storage + * pointer it's currentlu holding. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_SaveCompleted( + IPersistStorage* iface, + IStorage* pStgNew) +{ + Print(MAX_TRACE, ("(%p, %p)\n", iface, pStgNew)); + + if (pStgNew) + { + /* + * First, make sure we get our hands off any storage we have. + */ + + DataCache_HandsOffStorage(iface); + + /* + * Then, attach to the new storage. + */ + + DataCache_Load(iface, pStgNew); + } + + return S_OK; +} + +/************************************************************************ + * DataCache_HandsOffStorage (IPersistStorage) + * + * This method is called to tell the cache to release the storage + * pointer it's currentlu holding. + * + * See Windows documentation for more details on IPersistStorage methods. + */ +static HRESULT WINAPI DataCache_HandsOffStorage( + IPersistStorage* iface) +{ + _ICOM_THIS_From_IPersistStorage(DataCache, iface); + + Print(MAX_TRACE, ("(%p)\n", iface)); + + if (this->presentationStorage != NULL) + { + IStorage_Release(this->presentationStorage); + this->presentationStorage = NULL; + } + + return S_OK; +} + +/********************************************************* + * Method implementation for the IViewObject2 + * part of the DataCache class. + */ + +/************************************************************************ + * DataCache_IViewObject2_QueryInterface (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static HRESULT WINAPI DataCache_IViewObject2_QueryInterface( + IViewObject2* iface, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject); +} + +/************************************************************************ + * DataCache_IViewObject2_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IViewObject2_AddRef( + IViewObject2* iface) +{ + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + return IUnknown_AddRef(this->outerUnknown); +} + +/************************************************************************ + * DataCache_IViewObject2_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IViewObject2_Release( + IViewObject2* iface) +{ + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + return IUnknown_Release(this->outerUnknown); +} + +/************************************************************************ + * DataCache_Draw (IViewObject2) + * + * This method will draw the cached representation of the object + * to the given device context. + * + * See Windows documentation for more details on IViewObject2 methods. + */ +static HRESULT WINAPI DataCache_Draw( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hdcTargetDev, + HDC hdcDraw, + LPCRECTL lprcBounds, + LPCRECTL lprcWBounds, + IVO_ContCallback pfnContinue, + DWORD dwContinue) +{ + PresentationDataHeader presData; + HMETAFILE presMetafile = 0; + HRESULT hres; + + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + Print(MAX_TRACE, ("(%p, %lx, %ld, %p, %x, %x, %p, %p, %p, %lx)\n", + iface, + dwDrawAspect, + lindex, + pvAspect, + hdcTargetDev, + hdcDraw, + lprcBounds, + lprcWBounds, + pfnContinue, + dwContinue)); + + /* + * Sanity check + */ + if (lprcBounds==NULL) + return E_INVALIDARG; + + /* + * First, we need to retrieve the dimensions of the + * image in the metafile. + */ + hres = DataCache_ReadPresentationData(this, + dwDrawAspect, + &presData); + + if (FAILED(hres)) + return hres; + + /* + * Then, we can extract the metafile itself from the cached + * data. + * + * FIXME Unless it isn't a metafile. I think it could be any CF_XXX type, + * particularly CF_DIB. + */ + presMetafile = DataCache_ReadPresMetafile(this, + dwDrawAspect); + + /* + * If we have a metafile, just draw baby... + * We have to be careful not to modify the state of the + * DC. + */ + if (presMetafile!=0) + { + INT prevMapMode = SetMapMode(hdcDraw, MM_ANISOTROPIC); + SIZE oldWindowExt; + SIZE oldViewportExt; + POINT oldViewportOrg; + + SetWindowExtEx(hdcDraw, + presData.dwObjectExtentX, + presData.dwObjectExtentY, + &oldWindowExt); + + SetViewportExtEx(hdcDraw, + lprcBounds->right - lprcBounds->left, + lprcBounds->bottom - lprcBounds->top, + &oldViewportExt); + + SetViewportOrgEx(hdcDraw, + lprcBounds->left, + lprcBounds->top, + &oldViewportOrg); + + PlayMetaFile(hdcDraw, presMetafile); + + SetWindowExtEx(hdcDraw, + oldWindowExt.cx, + oldWindowExt.cy, + NULL); + + SetViewportExtEx(hdcDraw, + oldViewportExt.cx, + oldViewportExt.cy, + NULL); + + SetViewportOrgEx(hdcDraw, + oldViewportOrg.x, + oldViewportOrg.y, + NULL); + + SetMapMode(hdcDraw, prevMapMode); + + DeleteMetaFile(presMetafile); + } + + return S_OK; +} + +static HRESULT WINAPI DataCache_GetColorSet( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hicTargetDevice, + LOGPALETTE** ppColorSet) +{ +UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_Freeze( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DWORD* pdwFreeze) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_Unfreeze( + IViewObject2* iface, + DWORD dwFreeze) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/************************************************************************ + * DataCache_SetAdvise (IViewObject2) + * + * This sets-up an advisory sink with the data cache. When the object's + * view changes, this sink is called. + * + * See Windows documentation for more details on IViewObject2 methods. + */ +static HRESULT WINAPI DataCache_SetAdvise( + IViewObject2* iface, + DWORD aspects, + DWORD advf, + IAdviseSink* pAdvSink) +{ + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + Print(MAX_TRACE, ("(%p, %lx, %lx, %p)\n", iface, aspects, advf, pAdvSink)); + + /* + * A call to this function removes the previous sink + */ + if (this->sinkInterface != NULL) + { + IAdviseSink_Release(this->sinkInterface); + this->sinkInterface = NULL; + this->sinkAspects = 0; + this->sinkAdviseFlag = 0; + } + + /* + * Now, setup the new one. + */ + if (pAdvSink!=NULL) + { + this->sinkInterface = pAdvSink; + this->sinkAspects = aspects; + this->sinkAdviseFlag = advf; + + IAdviseSink_AddRef(this->sinkInterface); + } + + /* + * When the ADVF_PRIMEFIRST flag is set, we have to advise the + * sink immediately. + */ + if (advf & ADVF_PRIMEFIRST) + { + DataCache_FireOnViewChange(this, + DVASPECT_CONTENT, + -1); + } + + return S_OK; +} + +/************************************************************************ + * DataCache_GetAdvise (IViewObject2) + * + * This method queries the current state of the advise sink + * installed on the data cache. + * + * See Windows documentation for more details on IViewObject2 methods. + */ +static HRESULT WINAPI DataCache_GetAdvise( + IViewObject2* iface, + DWORD* pAspects, + DWORD* pAdvf, + IAdviseSink** ppAdvSink) +{ + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + Print(MAX_TRACE, ("(%p, %p, %p, %p)\n", iface, pAspects, pAdvf, ppAdvSink)); + + /* + * Just copy all the requested values. + */ + if (pAspects!=NULL) + *pAspects = this->sinkAspects; + + if (pAdvf!=NULL) + *pAdvf = this->sinkAdviseFlag; + + if (ppAdvSink!=NULL) + { + IAdviseSink_QueryInterface(this->sinkInterface, + &IID_IAdviseSink, + (void**)ppAdvSink); + } + + return S_OK; +} + +/************************************************************************ + * DataCache_GetExtent (IViewObject2) + * + * This method retrieves the "natural" size of this cached object. + * + * See Windows documentation for more details on IViewObject2 methods. + */ +static HRESULT WINAPI DataCache_GetExtent( + IViewObject2* iface, + DWORD dwDrawAspect, + LONG lindex, + DVTARGETDEVICE* ptd, + LPSIZEL lpsizel) +{ + PresentationDataHeader presData; + HRESULT hres = E_FAIL; + + _ICOM_THIS_From_IViewObject2(DataCache, iface); + + Print(MAX_TRACE, ("(%p, %lx, %ld, %p, %p)\n", + iface, dwDrawAspect, lindex, ptd, lpsizel)); + + /* + * Sanity check + */ + if (lpsizel==NULL) + return E_POINTER; + + /* + * Initialize the out parameter. + */ + lpsizel->cx = 0; + lpsizel->cy = 0; + + /* + * This flag should be set to -1. + */ + if (lindex!=-1) + Print(MIN_TRACE, ("Unimplemented flag lindex = %ld\n", lindex)); + + /* + * Right now, we suport only the callback from + * the default handler. + */ + if (ptd!=NULL) + Print(MIN_TRACE, ("Unimplemented ptd = %p\n", ptd)); + + /* + * Get the presentation information from the + * cache. + */ + hres = DataCache_ReadPresentationData(this, + dwDrawAspect, + &presData); + + if (SUCCEEDED(hres)) + { + lpsizel->cx = presData.dwObjectExtentX; + lpsizel->cy = presData.dwObjectExtentY; + } + + /* + * This method returns OLE_E_BLANK when it fails. + */ + if (FAILED(hres)) + hres = OLE_E_BLANK; + + return hres; +} + + +/********************************************************* + * Method implementation for the IOleCache2 + * part of the DataCache class. + */ + +/************************************************************************ + * DataCache_IOleCache2_QueryInterface (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static HRESULT WINAPI DataCache_IOleCache2_QueryInterface( + IOleCache2* iface, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_IOleCache2(DataCache, iface); + + return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject); +} + +/************************************************************************ + * DataCache_IOleCache2_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IOleCache2_AddRef( + IOleCache2* iface) +{ + _ICOM_THIS_From_IOleCache2(DataCache, iface); + + return IUnknown_AddRef(this->outerUnknown); +} + +/************************************************************************ + * DataCache_IOleCache2_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IOleCache2_Release( + IOleCache2* iface) +{ + _ICOM_THIS_From_IOleCache2(DataCache, iface); + + return IUnknown_Release(this->outerUnknown); +} + +static HRESULT WINAPI DataCache_Cache( + IOleCache2* iface, + FORMATETC* pformatetc, + DWORD advf, + DWORD* pdwConnection) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_Uncache( + IOleCache2* iface, + DWORD dwConnection) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_EnumCache( + IOleCache2* iface, + IEnumSTATDATA** ppenumSTATDATA) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_InitCache( + IOleCache2* iface, + IDataObject* pDataObject) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_IOleCache2_SetData( + IOleCache2* iface, + FORMATETC* pformatetc, + STGMEDIUM* pmedium, + BOOL fRelease) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_UpdateCache( + IOleCache2* iface, + LPDATAOBJECT pDataObject, + DWORD grfUpdf, + LPVOID pReserved) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_DiscardCache( + IOleCache2* iface, + DWORD dwDiscardOptions) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + + +/********************************************************* + * Method implementation for the IOleCacheControl + * part of the DataCache class. + */ + +/************************************************************************ + * DataCache_IOleCacheControl_QueryInterface (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface( + IOleCacheControl* iface, + REFIID riid, + void** ppvObject) +{ + _ICOM_THIS_From_IOleCacheControl(DataCache, iface); + + return IUnknown_QueryInterface(this->outerUnknown, riid, ppvObject); +} + +/************************************************************************ + * DataCache_IOleCacheControl_AddRef (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IOleCacheControl_AddRef( + IOleCacheControl* iface) +{ + _ICOM_THIS_From_IOleCacheControl(DataCache, iface); + + return IUnknown_AddRef(this->outerUnknown); +} + +/************************************************************************ + * DataCache_IOleCacheControl_Release (IUnknown) + * + * See Windows documentation for more details on IUnknown methods. + */ +static ULONG WINAPI DataCache_IOleCacheControl_Release( + IOleCacheControl* iface) +{ + _ICOM_THIS_From_IOleCacheControl(DataCache, iface); + + return IUnknown_Release(this->outerUnknown); +} + +static HRESULT WINAPI DataCache_OnRun( + IOleCacheControl* iface, + LPDATAOBJECT pDataObject) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +static HRESULT WINAPI DataCache_OnStop( + IOleCacheControl* iface) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + + diff --git a/lib/ole32/filemoniker.c b/lib/ole32/filemoniker.c new file mode 100644 index 0000000..d4aeb6d --- /dev/null +++ b/lib/ole32/filemoniker.c @@ -0,0 +1,1340 @@ +/*************************************************************************************** + * FileMonikers implementation + * + * Copyright 1999 Noomen Hamza + ***************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +/* filemoniker data structure */ +typedef struct FileMonikerImpl{ + + ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/ + + /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether + * two monikers are equal. That's whay IROTData interface is implemented by monikers. + */ + ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/ + + ULONG ref; /* reference counter for this object */ + + LPOLESTR filePathName; /* path string identified by this filemoniker */ + +} FileMonikerImpl; + +/********************************************************************************/ +/* FileMoniker prototype functions : */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface); +static ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface); + +/* IPersist prototype functions */ +static HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID); + +/* IPersistStream prototype functions */ +static HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface); +static HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface, IStream* pStm); +static HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty); +static HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize); + +/* IMoniker prototype functions */ +static HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced); +static HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite); +static HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker); +static HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker); +static HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash); +static HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning); +static HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pFileTime); +static HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk); +static HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix); +static HRESULT WINAPI FileMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath); +static HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName); +static HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut); +static HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys); + +/********************************************************************************/ +/* IROTData prototype functions */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject); +static ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData* iface); +static ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface); + +/* IROTData prototype function */ +static HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); + +/* Local function used by filemoniker implementation */ +HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* iface, LPCOLESTR lpszPathName); +HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* iface); +int WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** tabStr); + + +/********************************************************************************/ +/* Virtual function table for the FileMonikerImpl class which include IPersist,*/ +/* IPersistStream and IMoniker functions. */ +static ICOM_VTABLE(IMoniker) VT_FileMonikerImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + FileMonikerImpl_QueryInterface, + FileMonikerImpl_AddRef, + FileMonikerImpl_Release, + FileMonikerImpl_GetClassID, + FileMonikerImpl_IsDirty, + FileMonikerImpl_Load, + FileMonikerImpl_Save, + FileMonikerImpl_GetSizeMax, + FileMonikerImpl_BindToObject, + FileMonikerImpl_BindToStorage, + FileMonikerImpl_Reduce, + FileMonikerImpl_ComposeWith, + FileMonikerImpl_Enum, + FileMonikerImpl_IsEqual, + FileMonikerImpl_Hash, + FileMonikerImpl_IsRunning, + FileMonikerImpl_GetTimeOfLastChange, + FileMonikerImpl_Inverse, + FileMonikerImpl_CommonPrefixWith, + FileMonikerImpl_RelativePathTo, + FileMonikerImpl_GetDisplayName, + FileMonikerImpl_ParseDisplayName, + FileMonikerImpl_IsSystemMoniker +}; + +/********************************************************************************/ +/* Virtual function table for the IROTData class. */ +static ICOM_VTABLE(IROTData) VT_ROTDataImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + FileMonikerROTDataImpl_QueryInterface, + FileMonikerROTDataImpl_AddRef, + FileMonikerROTDataImpl_Release, + FileMonikerROTDataImpl_GetComparaisonData +}; + +/******************************************************************************* + * FileMoniker_QueryInterface + *******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS(FileMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream,riid) || + IsEqualIID(&IID_IMoniker, riid) + ) + *ppvObject = iface; + + else if (IsEqualIID(&IID_IROTData, riid)) + *ppvObject = (IROTData*)&(This->lpvtbl2); + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + FileMonikerImpl_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_AddRef + ******************************************************************************/ +ULONG WINAPI FileMonikerImpl_AddRef(IMoniker* iface) +{ + ICOM_THIS(FileMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return ++(This->ref); +} + +/****************************************************************************** + * FileMoniker_Release + ******************************************************************************/ +ULONG WINAPI FileMonikerImpl_Release(IMoniker* iface) +{ + ICOM_THIS(FileMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",iface)); + + This->ref--; + + /* destroy the object if there's no more reference on it */ + if (This->ref==0){ + + FileMonikerImpl_Destroy(This); + + return 0; + } + return This->ref;; +} + +/****************************************************************************** + * FileMoniker_GetClassID + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_GetClassID(IMoniker* iface, + CLSID *pClassID)/* Pointer to CLSID of object */ +{ + Print(MAX_TRACE, ("(%p,%p),stub!\n",iface,pClassID)); + + if (pClassID==NULL) + return E_POINTER; + + *pClassID = CLSID_FileMoniker; + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_IsDirty + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_IsDirty(IMoniker* iface) +{ + /* Note that the OLE-provided implementations of the IPersistStream::IsDirty + method in the OLE-provided moniker interfaces always return S_FALSE because + their internal state never changes. */ + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return S_FALSE; +} + +/****************************************************************************** + * FileMoniker_Load + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Load(IMoniker* iface,IStream* pStm) +{ + HRESULT res; + CHAR* filePathA; + WCHAR* filePathW; + ULONG bread; + WORD wbuffer; + DWORD dwbuffer,length,i,doubleLenHex,doubleLenDec; + + ICOM_THIS(FileMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pStm)); + + /* this function locates and reads from the stream the filePath string written by FileMonikerImpl_Save */ + + /* first WORD is non significative */ + res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); + if (bread!=sizeof(WORD) || wbuffer!=0) + return E_FAIL; + + /* read filePath string length (plus one) */ + res=IStream_Read(pStm,&length,sizeof(DWORD),&bread); + if (bread != sizeof(DWORD)) + return E_FAIL; + + /* read filePath string */ + filePathA=HeapAlloc(GetProcessHeap(),0,length); + res=IStream_Read(pStm,filePathA,length,&bread); + if (bread != length) + return E_FAIL; + + /* read the first constant */ + IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); + if (bread != sizeof(DWORD) || dwbuffer != 0xDEADFFFF) + return E_FAIL; + + length--; + + for(i=0;i<10;i++){ + res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); + if (bread!=sizeof(WORD) || wbuffer!=0) + return E_FAIL; + } + + if (length>8) + length=0; + + doubleLenHex=doubleLenDec=2*length; + if (length > 5) + doubleLenDec+=6; + + res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); + if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenDec) + return E_FAIL; + + if (length==0) + return res; + + res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),&bread); + if (bread!=sizeof(DWORD) || dwbuffer!=doubleLenHex) + return E_FAIL; + + res=IStream_Read(pStm,&wbuffer,sizeof(WORD),&bread); + if (bread!=sizeof(WORD) || wbuffer!=0x3) + return E_FAIL; + + filePathW=HeapAlloc(GetProcessHeap(),0,(length+1)*sizeof(WCHAR)); + filePathW[length]=0; + res=IStream_Read(pStm,filePathW,doubleLenHex,&bread); + if (bread!=doubleLenHex) + return E_FAIL; + + if (This->filePathName!=NULL) + HeapFree(GetProcessHeap(),0,This->filePathName); + + This->filePathName=filePathW; + + HeapFree(GetProcessHeap(),0,filePathA); + + return res; +} + +/****************************************************************************** + * FileMoniker_Save + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Save(IMoniker* iface, + IStream* pStm,/* pointer to the stream where the object is to be saved */ + BOOL fClearDirty)/* Specifies whether to clear the dirty flag */ +{ + /* this function saves data of this object. In the begining I thougth that I have just to write + * the filePath string on Stream. But, when I tested this function whith windows programs samples ! + * I noted that it was not the case. So I analysed data written by this function on Windows system and + * what did this function do exactly ! but I have no idear a bout its logic ! + * I guessed data who must be written on stream wich is: + * 1) WORD constant:zero 2) length of the path string ("\0" included) 3) path string type A + * 4) DWORD constant : 0xDEADFFFF 5) ten WORD constant: zero 6) DWORD: double-length of the the path + * string type W ("\0" not included) 7) WORD constant: 0x3 8) filePath unicode string. + * if the length(filePath) > 8 or.length(filePath) == 8 stop at step 5) + */ + + ICOM_THIS(FileMonikerImpl,iface); + + HRESULT res; + LPOLESTR filePathW=This->filePathName; + CHAR* filePathA; + DWORD len; + + DWORD constant1 = 0xDEADFFFF; /* these constants are detected after analysing the data structure written by */ + WORD constant2 = 0x3; /* FileMoniker_Save function in a windows program system */ + + WORD zero=0; + DWORD doubleLenHex; + DWORD doubleLenDec; + int i=0; + + Print(MAX_TRACE, ("(%p,%p,%d)\n",iface,pStm,fClearDirty)); + + if (pStm==NULL) + return E_POINTER; + + /* write a DWORD set to 0 : constant */ + res=IStream_Write(pStm,&zero,sizeof(WORD),NULL); + + /* write length of filePath string ( "\0" included )*/ + len = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL ); + res=IStream_Write(pStm,&len,sizeof(DWORD),NULL); + + /* write filePath string type A */ + filePathA=HeapAlloc(GetProcessHeap(),0,len); + WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, len, NULL, NULL ); + res=IStream_Write(pStm,filePathA,len,NULL); + HeapFree(GetProcessHeap(),0,filePathA); + + /* write a DWORD set to 0xDEADFFFF: constant */ + res=IStream_Write(pStm,&constant1,sizeof(DWORD),NULL); + + len--; + /* write 10 times a DWORD set to 0 : constants */ + for(i=0;i<10;i++) + res=IStream_Write(pStm,&zero,sizeof(WORD),NULL); + + if (len>8) + len=0; + + doubleLenHex=doubleLenDec=2*len; + if (len > 5) + doubleLenDec+=6; + + /* write double-length of the path string ( "\0" included )*/ + res=IStream_Write(pStm,&doubleLenDec,sizeof(DWORD),NULL); + + if (len==0) + return res; + + /* write double-length (hexa representation) of the path string ( "\0" included ) */ + res=IStream_Write(pStm,&doubleLenHex,sizeof(DWORD),NULL); + + /* write a WORD set to 0x3: constant */ + res=IStream_Write(pStm,&constant2,sizeof(WORD),NULL); + + /* write path unicode string */ + res=IStream_Write(pStm,filePathW,doubleLenHex,NULL); + + return res; +} + +/****************************************************************************** + * FileMoniker_GetSizeMax + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_GetSizeMax(IMoniker* iface, + ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ +{ + ICOM_THIS(FileMonikerImpl,iface); + DWORD len=lstrlenW(This->filePathName); + DWORD sizeMAx; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pcbSize)); + + if (pcbSize!=NULL) + return E_POINTER; + + /* for more details see FileMonikerImpl_Save coments */ + + sizeMAx = sizeof(WORD) + /* first WORD is 0 */ + sizeof(DWORD)+ /* length of filePath including "\0" in the end of the string */ + (len+1)+ /* filePath string */ + sizeof(DWORD)+ /* constant : 0xDEADFFFF */ + 10*sizeof(WORD)+ /* 10 zero WORD */ + sizeof(DWORD); /* size of the unicode filePath: "\0" not included */ + + if (len==0 || len > 8) + return S_OK; + + sizeMAx += sizeof(DWORD)+ /* size of the unicode filePath: "\0" not included */ + sizeof(WORD)+ /* constant : 0x3 */ + len*sizeof(WCHAR); /* unicde filePath string */ + + pcbSize->u.LowPart=sizeMAx; + pcbSize->u.HighPart=0; + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_Construct (local function) + *******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName) +{ + int nb=0,i; + int sizeStr=lstrlenW(lpszPathName); + LPOLESTR *tabStr=0; + WCHAR twoPoint[]={'.','.',0}; + WCHAR bkSlash[]={'\\',0}; + BYTE addBkSlash; + + Print(MAX_TRACE, ("(%p,%p)\n",This,lpszPathName)); + + /* Initialize the virtual fgunction table. */ + This->lpvtbl1 = &VT_FileMonikerImpl; + This->lpvtbl2 = &VT_ROTDataImpl; + This->ref = 0; + + This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1)); + + if (This->filePathName==NULL) + return E_OUTOFMEMORY; + + lstrcpyW(This->filePathName,lpszPathName); + + nb=FileMonikerImpl_DecomposePath(This->filePathName,&tabStr); + + if (nb > 0 ){ + + addBkSlash=1; + if (lstrcmpW(tabStr[0],twoPoint)!=0) + addBkSlash=0; + else + for(i=0;ifilePathName=HeapReAlloc(GetProcessHeap(),0,This->filePathName,(sizeStr+1)*sizeof(WCHAR)); + + *This->filePathName=0; + + for(i=0;tabStr[i]!=NULL;i++) + lstrcatW(This->filePathName,tabStr[i]); + + if (addBkSlash) + lstrcatW(This->filePathName,bkSlash); + } + + for(i=0; tabStr[i]!=NULL;i++) + CoTaskMemFree(tabStr[i]); + CoTaskMemFree(tabStr); + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_Destroy (local function) + *******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n",This)); + + if (This->filePathName!=NULL) + HeapFree(GetProcessHeap(),0,This->filePathName); + + HeapFree(GetProcessHeap(),0,This); + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_BindToObject + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_BindToObject(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + HRESULT res=E_FAIL; + CLSID clsID; + IUnknown* pObj=0; + IRunningObjectTable *prot=0; + IPersistFile *ppf=0; + IClassFactory *pcf=0; + IClassActivator *pca=0; + + ICOM_THIS(FileMonikerImpl,iface); + + *ppvResult=0; + + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + + if(pmkToLeft==NULL){ + + res=IBindCtx_GetRunningObjectTable(pbc,&prot); + + if (SUCCEEDED(res)){ + /* if the requested class was loaded befor ! we dont need to reload it */ + res = IRunningObjectTable_GetObject(prot,iface,&pObj); + + if (res==S_FALSE){ + /* first activation of this class */ + res=GetClassFile(This->filePathName,&clsID); + if (SUCCEEDED(res)){ + + res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IPersistFile,(void**)&ppf); + if (SUCCEEDED(res)){ + + res=IPersistFile_Load(ppf,This->filePathName,STGM_READ); + if (SUCCEEDED(res)){ + + pObj=(IUnknown*)ppf; + IUnknown_AddRef(pObj); + } + } + } + } + } + } + else{ + res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassFactory,(void**)&pcf); + + if (res==E_NOINTERFACE){ + + res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IClassActivator,(void**)&pca); + + if (res==E_NOINTERFACE) + return MK_E_INTERMEDIATEINTERFACENOTSUPPORTED; + } + if (pcf!=NULL){ + + IClassFactory_CreateInstance(pcf,NULL,&IID_IPersistFile,(void**)ppf); + + res=IPersistFile_Load(ppf,This->filePathName,STGM_READ); + + if (SUCCEEDED(res)){ + + pObj=(IUnknown*)ppf; + IUnknown_AddRef(pObj); + } + } + if (pca!=NULL){ + + Print(MIN_TRACE, ("()\n")); + + /*res=GetClassFile(This->filePathName,&clsID); + + if (SUCCEEDED(res)){ + + res=IClassActivator_GetClassObject(pca,&clsID,CLSCTX_ALL,0,&IID_IPersistFile,(void**)&ppf); + + if (SUCCEEDED(res)){ + + pObj=(IUnknown*)ppf; + IUnknown_AddRef(pObj); + } + }*/ + } + } + + if (pObj!=NULL){ + /* get the requested interface from the loaded class */ + res= IUnknown_QueryInterface(pObj,riid,ppvResult); + + IBindCtx_RegisterObjectBound(pbc,(IUnknown*)*ppvResult); + + IUnknown_Release(pObj); + } + + if (prot!=NULL) + IRunningObjectTable_Release(prot); + + if (ppf!=NULL) + IPersistFile_Release(ppf); + + if (pca!=NULL) + IClassActivator_Release(pca); + + if (pcf!=NULL) + IClassFactory_Release(pcf); + + return res; +} + +/****************************************************************************** + * FileMoniker_BindToStorage + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_BindToStorage(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvObject) +{ + LPOLESTR filePath=0; + IStorage *pstg=0; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject)); + + if (pmkToLeft==NULL){ + + if (IsEqualIID(&IID_IStorage, riid)){ + + /* get the file name */ + FileMonikerImpl_GetDisplayName(iface,pbc,pmkToLeft,&filePath); + + /* verifie if the file contains a storage object */ + res=StgIsStorageFile(filePath); + + if(res==S_OK){ + + res=StgOpenStorage(filePath,NULL,STGM_READWRITE|STGM_SHARE_DENY_WRITE,NULL,0,&pstg); + + if (SUCCEEDED(res)){ + + *ppvObject=pstg; + + IStorage_AddRef(pstg); + + return res; + } + } + CoTaskMemFree(filePath); + } + else + if ( (IsEqualIID(&IID_IStream, riid)) || (IsEqualIID(&IID_ILockBytes, riid)) ) + + return E_UNSPEC; + else + + return E_NOINTERFACE; + } + else { + + Print(MIN_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvObject)); + + return E_NOTIMPL; +} + return res; +} + +/****************************************************************************** + * FileMoniker_Reduce + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Reduce(IMoniker* iface, + IBindCtx* pbc, + DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, + IMoniker** ppmkReduced) +{ + Print(MAX_TRACE, ("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced)); + + if (ppmkReduced==NULL) + return E_POINTER; + + FileMonikerImpl_AddRef(iface); + + *ppmkReduced=iface; + + return MK_S_REDUCED_TO_SELF; +} +/****************************************************************************** + * FileMoniker_ComposeWith + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_ComposeWith(IMoniker* iface, + IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, + IMoniker** ppmkComposite) +{ + HRESULT res; + LPOLESTR str1=0,str2=0,*strDec1=0,*strDec2=0,newStr=0; + WCHAR twoPoint[]={'.','.',0}; + WCHAR bkSlash[]={'\\',0}; + IBindCtx *bind=0; + int i=0,j=0,lastIdx1=0,lastIdx2=0; + DWORD mkSys; + + Print(MAX_TRACE, ("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite)); + + if (ppmkComposite==NULL) + return E_POINTER; + + if (pmkRight==NULL) + return E_INVALIDARG; + + *ppmkComposite=0; + + IMoniker_IsSystemMoniker(pmkRight,&mkSys); + + /* check if we have two filemonikers to compose or not */ + if(mkSys==MKSYS_FILEMONIKER){ + + CreateBindCtx(0,&bind); + + FileMonikerImpl_GetDisplayName(iface,bind,NULL,&str1); + IMoniker_GetDisplayName(pmkRight,bind,NULL,&str2); + + /* decompose pathnames of the two monikers : (to prepare the path merge operation ) */ + lastIdx1=FileMonikerImpl_DecomposePath(str1,&strDec1)-1; + lastIdx2=FileMonikerImpl_DecomposePath(str2,&strDec2)-1; + + if ((lastIdx1==-1 && lastIdx2>-1)||(lastIdx1==1 && lstrcmpW(strDec1[0],twoPoint)==0)) + return MK_E_SYNTAX; + + if(lstrcmpW(strDec1[lastIdx1],bkSlash)==0) + lastIdx1--; + + /* for etch "..\" in the left of str2 remove the right element from str1 */ + for(i=0; ( (lastIdx1>=0) && (strDec2[i]!=NULL) && (lstrcmpW(strDec2[i],twoPoint)==0) ) ;i+=2){ + + lastIdx1-=2; + } + + /* the length of the composed path string is raised by the sum of the two paths lengths */ + newStr=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(lstrlenW(str1)+lstrlenW(str2)+1)); + + if (newStr==NULL) + return E_OUTOFMEMORY; + + /* new path is the concatenation of the rest of str1 and str2 */ + for(*newStr=0,j=0;j<=lastIdx1;j++) + lstrcatW(newStr,strDec1[j]); + + if ((strDec2[i]==NULL && lastIdx1>-1 && lastIdx2>-1) || lstrcmpW(strDec2[i],bkSlash)!=0) + lstrcatW(newStr,bkSlash); + + for(j=i;j<=lastIdx2;j++) + lstrcatW(newStr,strDec2[j]); + + /* create a new moniker with the new string */ + res=CreateFileMoniker(newStr,ppmkComposite); + + /* free all strings space memory used by this function */ + HeapFree(GetProcessHeap(),0,newStr); + + for(i=0; strDec1[i]!=NULL;i++) + CoTaskMemFree(strDec1[i]); + for(i=0; strDec2[i]!=NULL;i++) + CoTaskMemFree(strDec2[i]); + CoTaskMemFree(strDec1); + CoTaskMemFree(strDec2); + + CoTaskMemFree(str1); + CoTaskMemFree(str2); + + return res; + } + else if(mkSys==MKSYS_ANTIMONIKER){ + + *ppmkComposite=NULL; + return S_OK; + } + else if (fOnlyIfNotGeneric){ + + *ppmkComposite=NULL; + return MK_E_NEEDGENERIC; + } + else + + return CreateGenericComposite(iface,pmkRight,ppmkComposite); +} + +/****************************************************************************** + * FileMoniker_Enum + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) +{ + Print(MAX_TRACE, ("(%p,%d,%p)\n",iface,fForward,ppenumMoniker)); + + if (ppenumMoniker == NULL) + return E_POINTER; + + *ppenumMoniker = NULL; + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_IsEqual + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +{ + ICOM_THIS(FileMonikerImpl,iface); + CLSID clsid; + LPOLESTR filePath; + IBindCtx* bind; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pmkOtherMoniker)); + + if (pmkOtherMoniker==NULL) + return S_FALSE; + + IMoniker_GetClassID(pmkOtherMoniker,&clsid); + + if (!IsEqualCLSID(&clsid,&CLSID_FileMoniker)) + + return S_FALSE; + + res=CreateBindCtx(0,&bind); + if (FAILED(res)) + return res; + + IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&filePath); + + if (lstrcmpiW(filePath, + This->filePathName)!=0) + + return S_FALSE; + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_Hash + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) +{ + ICOM_THIS(FileMonikerImpl,iface); + + int h = 0,i,skip,len; + int off = 0; + LPOLESTR val; + + if (pdwHash==NULL) + return E_POINTER; + + val = This->filePathName; + len = lstrlenW(val); + + if (len < 16) { + for (i = len ; i > 0; i--) { + h = (h * 37) + val[off++]; + } + } else { + /* only sample some characters */ + skip = len / 8; + for (i = len ; i > 0; i -= skip, off += skip) { + h = (h * 39) + val[off]; + } +} + + *pdwHash=h; + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_IsRunning + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_IsRunning(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + IRunningObjectTable* rot; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning)); + + if ( (pmkNewlyRunning!=NULL) && (IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK) ) + return S_OK; + + if (pbc==NULL) + return E_POINTER; + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (FAILED(res)) + return res; + + res = IRunningObjectTable_IsRunning(rot,iface); + + IRunningObjectTable_Release(rot); + + return res; +} + +/****************************************************************************** + * FileMoniker_GetTimeOfLastChange + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_GetTimeOfLastChange(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pFileTime) +{ + ICOM_THIS(FileMonikerImpl,iface); + IRunningObjectTable* rot; + HRESULT res; + WIN32_FILE_ATTRIBUTE_DATA info; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pFileTime)); + + if (pFileTime==NULL) + return E_POINTER; + + if (pmkToLeft!=NULL) + return E_INVALIDARG; + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (FAILED(res)) + return res; + + res= IRunningObjectTable_GetTimeOfLastChange(rot,iface,pFileTime); + + if (FAILED(res)){ /* the moniker is not registred */ +#if 0 + if (!GetFileAttributesExW(This->filePathName,GetFileExInfoStandard,&info)) + return MK_E_NOOBJECT; +#else + Print(MIN_TRACE, ("GetFileAttributesExW() nowhere to be found\n")); +#endif + *pFileTime=info.ftLastWriteTime; +} + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_Inverse + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +{ + + Print(MAX_TRACE, ("(%p,%p)\n",iface,ppmk)); + + return CreateAntiMoniker(ppmk); +} + +/****************************************************************************** + * FileMoniker_CommonPrefixWith + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +{ + + LPOLESTR pathThis,pathOther,*stringTable1,*stringTable2,commonPath; + IBindCtx *pbind; + DWORD mkSys; + ULONG nb1,nb2,i,sameIdx; + BOOL machimeNameCase=FALSE; + + if (ppmkPrefix==NULL) + return E_POINTER; + + if (pmkOther==NULL) + return E_INVALIDARG; + + *ppmkPrefix=0; + + /* check if we have the same type of moniker */ + IMoniker_IsSystemMoniker(pmkOther,&mkSys); + + if(mkSys==MKSYS_FILEMONIKER){ + + CreateBindCtx(0,&pbind); + + /* create a string based on common part of the two paths */ + + IMoniker_GetDisplayName(iface,pbind,NULL,&pathThis); + IMoniker_GetDisplayName(pmkOther,pbind,NULL,&pathOther); + + nb1=FileMonikerImpl_DecomposePath(pathThis,&stringTable1); + nb2=FileMonikerImpl_DecomposePath(pathOther,&stringTable2); + + if (nb1==0 || nb2==0) + return MK_E_NOPREFIX; + + commonPath=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(min(lstrlenW(pathThis),lstrlenW(pathOther))+1)); + + *commonPath=0; + + for(sameIdx=0; ( (stringTable1[sameIdx]!=NULL) && + (stringTable2[sameIdx]!=NULL) && + (lstrcmpiW(stringTable1[sameIdx],stringTable2[sameIdx])==0)); sameIdx++); + + if (sameIdx > 1 && *stringTable1[0]=='\\' && *stringTable2[1]=='\\'){ + + machimeNameCase=TRUE; + + for(i=2;i 3 || nb2 > 3) ) + return MK_E_NOPREFIX; + + for(i=0;i0 && !(len1==1 && len2==1 && sameIdx==0)) + for(j=sameIdx;(tabStr1[j] != NULL); j++) + if (*tabStr1[j]!='\\') + lstrcatW(relPath,back); + + /* add items of the second path (similar items with the first path are not included) to the relativePath */ + for(j=sameIdx;tabStr2[j]!=NULL;j++) + lstrcatW(relPath,tabStr2[j]); + + res=CreateFileMoniker(relPath,ppmkRelPath); + + for(j=0; tabStr1[j]!=NULL;j++) + CoTaskMemFree(tabStr1[j]); + for(j=0; tabStr2[j]!=NULL;j++) + CoTaskMemFree(tabStr2[j]); + CoTaskMemFree(tabStr1); + CoTaskMemFree(tabStr2); + CoTaskMemFree(str1); + CoTaskMemFree(str2); + HeapFree(GetProcessHeap(),0,relPath); + + if (len1==0 || len2==0 || (len1==1 && len2==1 && sameIdx==0)) + return MK_S_HIM; + + return res; +} + +/****************************************************************************** + * FileMoniker_GetDisplayName + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_GetDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR *ppszDisplayName) +{ + ICOM_THIS(FileMonikerImpl,iface); + + int len=lstrlenW(This->filePathName); + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName)); + + if (ppszDisplayName==NULL) + return E_POINTER; + + if (pmkToLeft!=NULL) + return E_INVALIDARG; + + *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(len+1)); + if (*ppszDisplayName==NULL) + return E_OUTOFMEMORY; + + lstrcpyW(*ppszDisplayName,This->filePathName); + + return S_OK; +} + +/****************************************************************************** + * FileMoniker_ParseDisplayName + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_ParseDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR pszDisplayName, + ULONG* pchEaten, + IMoniker** ppmkOut) +{ + Print(MIN_TRACE, ("(%p,%p,%p,%p,%p,%p),stub!\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut)); + return E_NOTIMPL; +} + +/****************************************************************************** + * FileMoniker_IsSystemMoniker + ******************************************************************************/ +HRESULT WINAPI FileMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) +{ + Print(MAX_TRACE, ("(%p,%p)\n",iface,pwdMksys)); + + if (!pwdMksys) + return E_POINTER; + + (*pwdMksys)=MKSYS_FILEMONIKER; + + return S_OK; +} + +/******************************************************************************* + * FileMonikerIROTData_QueryInterface + *******************************************************************************/ +HRESULT WINAPI FileMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) +{ + + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + return FileMonikerImpl_QueryInterface(This, riid, ppvObject); +} + +/*********************************************************************** + * FileMonikerIROTData_AddRef + */ +ULONG WINAPI FileMonikerROTDataImpl_AddRef(IROTData *iface) +{ + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return FileMonikerImpl_AddRef(This); +} + +/*********************************************************************** + * FileMonikerIROTData_Release + */ +ULONG WINAPI FileMonikerROTDataImpl_Release(IROTData* iface) +{ + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return FileMonikerImpl_Release(This); +} + +/****************************************************************************** + * FileMonikerIROTData_GetComparaisonData + ******************************************************************************/ +HRESULT WINAPI FileMonikerROTDataImpl_GetComparaisonData(IROTData* iface, + BYTE* pbData, + ULONG cbMax, + ULONG* pcbData) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/****************************************************************************** + * CreateFileMoniker16 + ******************************************************************************/ +HRESULT WINAPI CreateFileMoniker16(LPCOLESTR16 lpszPathName,LPMONIKER* ppmk) +{ + + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/****************************************************************************** + * CreateFileMoniker + ******************************************************************************/ +HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk) +{ + FileMonikerImpl* newFileMoniker = 0; + HRESULT hr = E_FAIL; + IID riid=IID_IMoniker; + + Print(MAX_TRACE, ("(%p,%p)\n",lpszPathName,ppmk)); + + if (ppmk==NULL) + return E_POINTER; + + if(lpszPathName==NULL) + return MK_E_SYNTAX; + + *ppmk=0; + + newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl)); + + if (newFileMoniker == 0) + return E_OUTOFMEMORY; + + hr = FileMonikerImpl_Construct(newFileMoniker,lpszPathName); + + if (SUCCEEDED(hr)) + hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker,&riid,(void**)ppmk); + else + HeapFree(GetProcessHeap(),0,newFileMoniker); + + return hr; +} diff --git a/lib/ole32/include/compobj.h b/lib/ole32/include/compobj.h new file mode 100644 index 0000000..b58041b --- /dev/null +++ b/lib/ole32/include/compobj.h @@ -0,0 +1,15 @@ +#ifndef __WINE_OLE_COMPOBJ_H +#define __WINE_OLE_COMPOBJ_H + +/* All private prototype functions used by OLE will be added to this header file */ + +/* This function initialize the Running Object Table */ +HRESULT WINAPI RunningObjectTableImpl_Initialize(); + +/* This function uninitialize the Running Object Table */ +HRESULT WINAPI RunningObjectTableImpl_UnInitialize(); + +/* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */ +int WINAPI FileMonikerImpl_DecomposePath(LPOLESTR str, LPOLESTR** stringTable); + +#endif /* __WINE_OLE_COMPOBJ_H */ diff --git a/lib/ole32/include/debug.h b/lib/ole32/include/debug.h new file mode 100644 index 0000000..77a820b --- /dev/null +++ b/lib/ole32/include/debug.h @@ -0,0 +1,91 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_CHECK 0x00000100 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define Print(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { Print(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define Print(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + Print(MIN_TRACE, ("is unimplemented, please try again later.\n")); + +#define CHECKPOINT \ + Print(DEBUG_CHECK, ("\n")); + +#define CP CHECKPOINT + + +static char GuidBufferSpace[40]; + +static inline PCHAR PRINT_GUID( const GUID *id ) +{ + CHAR *str; + + if (!id) return "(null)"; + + str = &GuidBufferSpace[0]; + + if (!HIWORD(id)) + { + sprintf( str, "", LOWORD((ULONG)id) ); + } + else + { + sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + id->Data1, id->Data2, id->Data3, + id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3], + id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] ); + } + return str; +} + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/ole32/include/ole32_main.h b/lib/ole32/include/ole32_main.h new file mode 100644 index 0000000..97b000d --- /dev/null +++ b/lib/ole32/include/ole32_main.h @@ -0,0 +1,6 @@ +#ifndef __WINE_OLE32_MAIN_H +#define __WINE_OLE32_MAIN_H + +extern HINSTANCE OLE32_hInstance; + +#endif /* __WINE_OLE32_MAIN_H */ diff --git a/lib/ole32/include/storage32.h b/lib/ole32/include/storage32.h new file mode 100644 index 0000000..5a9589f --- /dev/null +++ b/lib/ole32/include/storage32.h @@ -0,0 +1,864 @@ +/* + * Compound Storage (32 bit version) + * + * Implemented using the documentation of the LAOLA project at + * + * (Thanks to Martin Schwartz ) + * + * This include file contains definitions of types and function + * prototypes that are used in the many files implementing the + * storage functionality + * + * Copyright 1998,1999 Francis Beaudet + * Copyright 1998,1999 Thuy Nguyen + */ +#ifndef __STORAGE32_H__ +#define __STORAGE32_H__ + +#include + +/* + * Definitions for the file format offsets. + */ +static const ULONG OFFSET_BIGBLOCKSIZEBITS = 0x0000001e; +static const ULONG OFFSET_SMALLBLOCKSIZEBITS = 0x00000020; +static const ULONG OFFSET_BBDEPOTCOUNT = 0x0000002C; +static const ULONG OFFSET_ROOTSTARTBLOCK = 0x00000030; +static const ULONG OFFSET_SBDEPOTSTART = 0x0000003C; +static const ULONG OFFSET_EXTBBDEPOTSTART = 0x00000044; +static const ULONG OFFSET_EXTBBDEPOTCOUNT = 0x00000048; +static const ULONG OFFSET_BBDEPOTSTART = 0x0000004C; +static const ULONG OFFSET_PS_NAME = 0x00000000; +static const ULONG OFFSET_PS_NAMELENGTH = 0x00000040; +static const ULONG OFFSET_PS_PROPERTYTYPE = 0x00000042; +static const ULONG OFFSET_PS_PREVIOUSPROP = 0x00000044; +static const ULONG OFFSET_PS_NEXTPROP = 0x00000048; +static const ULONG OFFSET_PS_DIRPROP = 0x0000004C; +static const ULONG OFFSET_PS_GUID = 0x00000050; +static const ULONG OFFSET_PS_TSS1 = 0x00000064; +static const ULONG OFFSET_PS_TSD1 = 0x00000068; +static const ULONG OFFSET_PS_TSS2 = 0x0000006C; +static const ULONG OFFSET_PS_TSD2 = 0x00000070; +static const ULONG OFFSET_PS_STARTBLOCK = 0x00000074; +static const ULONG OFFSET_PS_SIZE = 0x00000078; +static const WORD DEF_BIG_BLOCK_SIZE_BITS = 0x0009; +static const WORD DEF_SMALL_BLOCK_SIZE_BITS = 0x0006; +static const WORD DEF_BIG_BLOCK_SIZE = 0x0200; +static const WORD DEF_SMALL_BLOCK_SIZE = 0x0040; +static const ULONG BLOCK_EXTBBDEPOT = 0xFFFFFFFC; +static const ULONG BLOCK_SPECIAL = 0xFFFFFFFD; +static const ULONG BLOCK_END_OF_CHAIN = 0xFFFFFFFE; +static const ULONG BLOCK_UNUSED = 0xFFFFFFFF; +static const ULONG PROPERTY_NULL = 0xFFFFFFFF; + +#define PROPERTY_NAME_MAX_LEN 0x20 +#define PROPERTY_NAME_BUFFER_LEN 0x40 + +#define PROPSET_BLOCK_SIZE 0x00000080 + +/* + * Property type of relation + */ +#define PROPERTY_RELATION_PREVIOUS 0 +#define PROPERTY_RELATION_NEXT 1 +#define PROPERTY_RELATION_DIR 2 + +/* + * Property type constants + */ +#define PROPTYPE_STORAGE 0x01 +#define PROPTYPE_STREAM 0x02 +#define PROPTYPE_ROOT 0x05 + +/* + * These defines assume a hardcoded blocksize. The code will assert + * if the blocksize is different. Some changes will have to be done if it + * becomes the case. + */ +#define BIG_BLOCK_SIZE 0x200 +#define COUNT_BBDEPOTINHEADER 109 +#define LIMIT_TO_USE_SMALL_BLOCK 0x1000 +#define NUM_BLOCKS_PER_DEPOT_BLOCK 128 + +/* + * These are signatures to detect the type of Document file. + */ +static const BYTE STORAGE_magic[8] ={0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1}; +static const BYTE STORAGE_oldmagic[8] ={0xd0,0xcf,0x11,0xe0,0x0e,0x11,0xfc,0x0d}; + +/* + * Forward declarations of all the structures used by the storage + * module. + */ +typedef struct StorageBaseImpl StorageBaseImpl; +typedef struct StorageImpl StorageImpl; +typedef struct StorageInternalImpl StorageInternalImpl; +typedef struct BlockChainStream BlockChainStream; +typedef struct SmallBlockChainStream SmallBlockChainStream; +typedef struct IEnumSTATSTGImpl IEnumSTATSTGImpl; +typedef struct StgProperty StgProperty; +typedef struct StgStreamImpl StgStreamImpl; + +/* + * This utility structure is used to read/write the information in a storage + * property. + */ +struct StgProperty +{ + WCHAR name[PROPERTY_NAME_MAX_LEN]; + WORD sizeOfNameString; + BYTE propertyType; + ULONG previousProperty; + ULONG nextProperty; + ULONG dirProperty; + GUID propertyUniqueID; + ULONG timeStampS1; + ULONG timeStampD1; + ULONG timeStampS2; + ULONG timeStampD2; + ULONG startingBlock; + ULARGE_INTEGER size; +}; + +/************************************************************************* + * Big Block File support + * + * The big block file is an abstraction of a flat file separated in + * same sized blocks. The implementation for the methods described in + * this section appear in stg_bigblockfile.c + */ + +/* + * Declaration of the data structures + */ +typedef struct BigBlockFile BigBlockFile,*LPBIGBLOCKFILE; +typedef struct MappedPage MappedPage,*LPMAPPEDPAGE; + +struct BigBlockFile +{ + BOOL fileBased; + ULARGE_INTEGER filesize; + ULONG blocksize; + HANDLE hfile; + HANDLE hfilemap; + DWORD flProtect; + MappedPage *maplist; + MappedPage *victimhead, *victimtail; + ULONG num_victim_pages; + ILockBytes *pLkbyt; + HGLOBAL hbytearray; + LPVOID pbytearray; +}; + +/* + * Declaration of the functions used to manipulate the BigBlockFile + * data structure. + */ +BigBlockFile* BIGBLOCKFILE_Construct(HANDLE hFile, + ILockBytes* pLkByt, + DWORD openFlags, + ULONG blocksize, + BOOL fileBased); +void BIGBLOCKFILE_Destructor(LPBIGBLOCKFILE This); +void* BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index); +void* BIGBLOCKFILE_GetROBigBlock(LPBIGBLOCKFILE This, ULONG index); +void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock); +void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize); +ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This); + +/************************************************************************* + * Ole Convert support + */ + +void OLECONVERT_CreateOleStream(LPSTORAGE pStorage); +HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName); + +/**************************************************************************** + * Storage32BaseImpl definitions. + * + * This stucture defines the base information contained in all implementations + * of IStorage32 contained in this filee storage implementation. + * + * In OOP terms, this is the base class for all the IStorage32 implementations + * contained in this file. + */ +struct StorageBaseImpl +{ + ICOM_VFIELD(IStorage); /* Needs to be the first item in the stuct + * since we want to cast this in a Storage32 pointer */ + + /* + * Reference count of this object + */ + ULONG ref; + + /* + * Ancestor storage (top level) + */ + StorageImpl* ancestorStorage; + + /* + * Index of the property for the root of + * this storage + */ + ULONG rootPropertySetIndex; + + /* + * virtual Destructor method. + */ + void (*v_destructor)(StorageBaseImpl*); +}; + + +/* + * Prototypes for the methods of the Storage32BaseImpl class. + */ +HRESULT WINAPI StorageBaseImpl_QueryInterface( + IStorage* iface, + REFIID riid, + void** ppvObject); + +ULONG WINAPI StorageBaseImpl_AddRef( + IStorage* iface); + +ULONG WINAPI StorageBaseImpl_Release( + IStorage* iface); + +HRESULT WINAPI StorageBaseImpl_OpenStream( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + void* reserved1, /* [unique][in] */ + DWORD grfMode, /* [in] */ + DWORD reserved2, /* [in] */ + IStream** ppstm); /* [out] */ + +HRESULT WINAPI StorageBaseImpl_OpenStorage( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][unique][in] */ + IStorage* pstgPriority, /* [unique][in] */ + DWORD grfMode, /* [in] */ + SNB snbExclude, /* [unique][in] */ + DWORD reserved, /* [in] */ + IStorage** ppstg); /* [out] */ + +HRESULT WINAPI StorageBaseImpl_EnumElements( + IStorage* iface, + DWORD reserved1, /* [in] */ + void* reserved2, /* [size_is][unique][in] */ + DWORD reserved3, /* [in] */ + IEnumSTATSTG** ppenum); /* [out] */ + +HRESULT WINAPI StorageBaseImpl_Stat( + IStorage* iface, + STATSTG* pstatstg, /* [out] */ + DWORD grfStatFlag); /* [in] */ + +HRESULT WINAPI StorageBaseImpl_RenameElement( + IStorage* iface, + const OLECHAR* pwcsOldName, /* [string][in] */ + const OLECHAR* pwcsNewName); /* [string][in] */ + +HRESULT WINAPI StorageBaseImpl_CreateStream( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + DWORD grfMode, /* [in] */ + DWORD reserved1, /* [in] */ + DWORD reserved2, /* [in] */ + IStream** ppstm); /* [out] */ + +HRESULT WINAPI StorageBaseImpl_SetClass( + IStorage* iface, + REFCLSID clsid); /* [in] */ + +/**************************************************************************** + * Storage32Impl definitions. + * + * This implementation of the IStorage32 interface represents a root + * storage. Basically, a document file. + */ +struct StorageImpl +{ + ICOM_VFIELD(IStorage); /* Needs to be the first item in the stuct + * since we want to cast this in a Storage32 pointer */ + + /* + * Declare the member of the Storage32BaseImpl class to allow + * casting as a Storage32BaseImpl + */ + ULONG ref; + struct StorageImpl* ancestorStorage; + ULONG rootPropertySetIndex; + void (*v_destructor)(struct StorageImpl*); + + /* + * The following data members are specific to the Storage32Impl + * class + */ + HANDLE hFile; /* Physical support for the Docfile */ + + /* + * File header + */ + WORD bigBlockSizeBits; + WORD smallBlockSizeBits; + ULONG bigBlockSize; + ULONG smallBlockSize; + ULONG bigBlockDepotCount; + ULONG rootStartBlock; + ULONG smallBlockDepotStart; + ULONG extBigBlockDepotStart; + ULONG extBigBlockDepotCount; + ULONG bigBlockDepotStart[COUNT_BBDEPOTINHEADER]; + + ULONG blockDepotCached[NUM_BLOCKS_PER_DEPOT_BLOCK]; + ULONG indexBlockDepotCached; + ULONG prevFreeBlock; + + /* + * Abstraction of the big block chains for the chains of the header. + */ + BlockChainStream* rootBlockChain; + BlockChainStream* smallBlockDepotChain; + BlockChainStream* smallBlockRootChain; + + /* + * Pointer to the big block file abstraction + */ + BigBlockFile* bigBlockFile; +}; + +/* + * Method declaration for the Storage32Impl class + */ + +HRESULT WINAPI StorageImpl_CreateStorage( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + DWORD grfMode, /* [in] */ + DWORD dwStgFmt, /* [in] */ + DWORD reserved2, /* [in] */ + IStorage** ppstg); /* [out] */ + +HRESULT WINAPI StorageImpl_CopyTo( + IStorage* iface, + DWORD ciidExclude, /* [in] */ + const IID* rgiidExclude, /* [size_is][unique][in] */ + SNB snbExclude, /* [unique][in] */ + IStorage* pstgDest); /* [unique][in] */ + +HRESULT WINAPI StorageImpl_MoveElementTo( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + IStorage* pstgDest, /* [unique][in] */ + const OLECHAR* pwcsNewName, /* [string][in] */ + DWORD grfFlags); /* [in] */ + +HRESULT WINAPI StorageImpl_Commit( + IStorage* iface, + DWORD grfCommitFlags); /* [in] */ + +HRESULT WINAPI StorageImpl_Revert( + IStorage* iface); + +HRESULT WINAPI StorageImpl_DestroyElement( + IStorage* iface, + const OLECHAR* pwcsName); /* [string][in] */ + +HRESULT WINAPI StorageImpl_SetElementTimes( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + const FILETIME* pctime, /* [in] */ + const FILETIME* patime, /* [in] */ + const FILETIME* pmtime); /* [in] */ + +HRESULT WINAPI StorageImpl_SetStateBits( + IStorage* iface, + DWORD grfStateBits, /* [in] */ + DWORD grfMask); /* [in] */ + +void StorageImpl_Destroy( + StorageImpl* This); + +HRESULT StorageImpl_Construct( + StorageImpl* This, + HANDLE hFile, + ILockBytes* pLkbyt, + DWORD openFlags, + BOOL fileBased, + BOOL fileCreate); + +BOOL StorageImpl_ReadBigBlock( + StorageImpl* This, + ULONG blockIndex, + void* buffer); + +BOOL StorageImpl_WriteBigBlock( + StorageImpl* This, + ULONG blockIndex, + void* buffer); + +void* StorageImpl_GetROBigBlock( + StorageImpl* This, + ULONG blockIndex); + +void* StorageImpl_GetBigBlock( + StorageImpl* This, + ULONG blockIndex); + +void StorageImpl_ReleaseBigBlock( + StorageImpl* This, + void* pBigBlock); + +ULONG StorageImpl_GetNextFreeBigBlock( + StorageImpl* This); + +void StorageImpl_FreeBigBlock( + StorageImpl* This, + ULONG blockIndex); + +ULONG StorageImpl_GetNextBlockInChain( + StorageImpl* This, + ULONG blockIndex); + +void StorageImpl_SetNextBlockInChain( + StorageImpl* This, + ULONG blockIndex, + ULONG nextBlock); + +HRESULT StorageImpl_LoadFileHeader( + StorageImpl* This); + +void StorageImpl_SaveFileHeader( + StorageImpl* This); + +BOOL StorageImpl_ReadProperty( + StorageImpl* This, + ULONG index, + StgProperty* buffer); + +BOOL StorageImpl_WriteProperty( + StorageImpl* This, + ULONG index, + StgProperty* buffer); + +BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks( + StorageImpl* This, + SmallBlockChainStream** ppsbChain); + +ULONG Storage32Impl_GetNextExtendedBlock(StorageImpl* This, + ULONG blockIndex); + +void Storage32Impl_AddBlockDepot(StorageImpl* This, + ULONG blockIndex); + +ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This); + +ULONG Storage32Impl_GetExtDepotBlock(StorageImpl* This, + ULONG depotIndex); + +void Storage32Impl_SetExtDepotBlock(StorageImpl* This, + ULONG depotIndex, + ULONG blockIndex); +/**************************************************************************** + * Storage32InternalImpl definitions. + * + * Definition of the implementation structure for the IStorage32 interface. + * This one implements the IStorage32 interface for storage that are + * inside another storage. + */ +struct StorageInternalImpl +{ + ICOM_VFIELD(IStorage); /* Needs to be the first item in the stuct + * since we want to cast this in a Storage32 pointer */ + + /* + * Declare the member of the Storage32BaseImpl class to allow + * casting as a Storage32BaseImpl + */ + ULONG ref; + struct StorageImpl* ancestorStorage; + ULONG rootPropertySetIndex; + void (*v_destructor)(struct StorageInternalImpl*); + + /* + * There is no specific data for this class. + */ +}; + +/* + * Method definitions for the Storage32InternalImpl class. + */ +StorageInternalImpl* StorageInternalImpl_Construct( + StorageImpl* ancestorStorage, + ULONG rootTropertyIndex); + +void StorageInternalImpl_Destroy( + StorageInternalImpl* This); + +HRESULT WINAPI StorageInternalImpl_Commit( + IStorage* iface, + DWORD grfCommitFlags); /* [in] */ + +HRESULT WINAPI StorageInternalImpl_Revert( + IStorage* iface); + + +/**************************************************************************** + * IEnumSTATSTGImpl definitions. + * + * Definition of the implementation structure for the IEnumSTATSTGImpl interface. + * This class allows iterating through the content of a storage and to find + * specific items inside it. + */ +struct IEnumSTATSTGImpl +{ + ICOM_VFIELD(IEnumSTATSTG); /* Needs to be the first item in the stuct + * since we want to cast this in a IEnumSTATSTG pointer */ + + ULONG ref; /* Reference count */ + StorageImpl* parentStorage; /* Reference to the parent storage */ + ULONG firstPropertyNode; /* Index of the root of the storage to enumerate */ + + /* + * The current implementation of the IEnumSTATSTGImpl class uses a stack + * to walk the property sets to get the content of a storage. This stack + * is implemented by the following 3 data members + */ + ULONG stackSize; + ULONG stackMaxSize; + ULONG* stackToVisit; + +#define ENUMSTATSGT_SIZE_INCREMENT 10 +}; + +/* + * Method definitions for the IEnumSTATSTGImpl class. + */ +HRESULT WINAPI IEnumSTATSTGImpl_QueryInterface( + IEnumSTATSTG* iface, + REFIID riid, + void** ppvObject); + +ULONG WINAPI IEnumSTATSTGImpl_AddRef( + IEnumSTATSTG* iface); + +ULONG WINAPI IEnumSTATSTGImpl_Release( + IEnumSTATSTG* iface); + +HRESULT WINAPI IEnumSTATSTGImpl_Next( + IEnumSTATSTG* iface, + ULONG celt, + STATSTG* rgelt, + ULONG* pceltFetched); + +HRESULT WINAPI IEnumSTATSTGImpl_Skip( + IEnumSTATSTG* iface, + ULONG celt); + +HRESULT WINAPI IEnumSTATSTGImpl_Reset( + IEnumSTATSTG* iface); + +HRESULT WINAPI IEnumSTATSTGImpl_Clone( + IEnumSTATSTG* iface, + IEnumSTATSTG** ppenum); + +IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct( + StorageImpl* This, + ULONG firstPropertyNode); + +void IEnumSTATSTGImpl_Destroy( + IEnumSTATSTGImpl* This); + +void IEnumSTATSTGImpl_PushSearchNode( + IEnumSTATSTGImpl* This, + ULONG nodeToPush); + +ULONG IEnumSTATSTGImpl_PopSearchNode( + IEnumSTATSTGImpl* This, + BOOL remove); + +ULONG IEnumSTATSTGImpl_FindProperty( + IEnumSTATSTGImpl* This, + const OLECHAR* lpszPropName, + StgProperty* buffer); + +INT IEnumSTATSTGImpl_FindParentProperty( + IEnumSTATSTGImpl *This, + ULONG childProperty, + StgProperty *currentProperty, + ULONG *propertyId); + + +/**************************************************************************** + * StgStreamImpl definitions. + * + * This class imlements the IStream32 inteface and represents a stream + * located inside a storage object. + */ +struct StgStreamImpl +{ + ICOM_VFIELD(IStream); /* Needs to be the first item in the stuct + * since we want to cast this in a IStream pointer */ + + /* + * Reference count + */ + ULONG ref; + + /* + * Storage that is the parent(owner) of the stream + */ + StorageBaseImpl* parentStorage; + + /* + * Access mode of this stream. + */ + DWORD grfMode; + + /* + * Index of the property that owns (points to) this stream. + */ + ULONG ownerProperty; + + /* + * Helper variable that contains the size of the stream + */ + ULARGE_INTEGER streamSize; + + /* + * This is the current position of the cursor in the stream + */ + ULARGE_INTEGER currentPosition; + + /* + * The information in the stream is represented by a chain of small blocks + * or a chain of large blocks. Depending on the case, one of the two + * following variabled points to that information. + */ + BlockChainStream* bigBlockChain; + SmallBlockChainStream* smallBlockChain; +}; + +/* + * Method definition for the StgStreamImpl class. + */ +StgStreamImpl* StgStreamImpl_Construct( + StorageBaseImpl* parentStorage, + DWORD grfMode, + ULONG ownerProperty); + +void StgStreamImpl_Destroy( + StgStreamImpl* This); + +void StgStreamImpl_OpenBlockChain( + StgStreamImpl* This); + +HRESULT WINAPI StgStreamImpl_QueryInterface( + IStream* iface, + REFIID riid, /* [in] */ + void** ppvObject); /* [iid_is][out] */ + +ULONG WINAPI StgStreamImpl_AddRef( + IStream* iface); + +ULONG WINAPI StgStreamImpl_Release( + IStream* iface); + +HRESULT WINAPI StgStreamImpl_Read( + IStream* iface, + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead); /* [out] */ + +HRESULT WINAPI StgStreamImpl_Write( + IStream* iface, + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten); /* [out] */ + +HRESULT WINAPI StgStreamImpl_Seek( + IStream* iface, + LARGE_INTEGER dlibMove, /* [in] */ + DWORD dwOrigin, /* [in] */ + ULARGE_INTEGER* plibNewPosition); /* [out] */ + +HRESULT WINAPI StgStreamImpl_SetSize( + IStream* iface, + ULARGE_INTEGER libNewSize); /* [in] */ + +HRESULT WINAPI StgStreamImpl_CopyTo( + IStream* iface, + IStream* pstm, /* [unique][in] */ + ULARGE_INTEGER cb, /* [in] */ + ULARGE_INTEGER* pcbRead, /* [out] */ + ULARGE_INTEGER* pcbWritten); /* [out] */ + +HRESULT WINAPI StgStreamImpl_Commit( + IStream* iface, + DWORD grfCommitFlags); /* [in] */ + +HRESULT WINAPI StgStreamImpl_Revert( + IStream* iface); + +HRESULT WINAPI StgStreamImpl_LockRegion( + IStream* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI StgStreamImpl_UnlockRegion( + IStream* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI StgStreamImpl_Stat( + IStream* iface, + STATSTG* pstatstg, /* [out] */ + DWORD grfStatFlag); /* [in] */ + +HRESULT WINAPI StgStreamImpl_Clone( + IStream* iface, + IStream** ppstm); /* [out] */ + + +/******************************************************************************** + * The StorageUtl_ functions are miscelaneous utility functions. Most of which are + * abstractions used to read values from file buffers without having to worry + * about bit order + */ +void StorageUtl_ReadWord(void* buffer, ULONG offset, WORD* value); +void StorageUtl_WriteWord(void* buffer, ULONG offset, WORD value); +void StorageUtl_ReadDWord(void* buffer, ULONG offset, DWORD* value); +void StorageUtl_WriteDWord(void* buffer, ULONG offset, DWORD value); +void StorageUtl_ReadGUID(void* buffer, ULONG offset, GUID* value); +void StorageUtl_WriteGUID(void* buffer, ULONG offset, GUID* value); +void StorageUtl_CopyPropertyToSTATSTG(STATSTG* destination, + StgProperty* source, + int statFlags); + +/**************************************************************************** + * BlockChainStream definitions. + * + * The BlockChainStream class is a utility class that is used to create an + * abstraction of the big block chains in the storage file. + */ +struct BlockChainStream +{ + StorageImpl* parentStorage; + ULONG* headOfStreamPlaceHolder; + ULONG ownerPropertyIndex; + ULONG lastBlockNoInSequence; + ULONG lastBlockNoInSequenceIndex; + ULONG tailIndex; + ULONG numBlocks; +}; + +/* + * Methods for the BlockChainStream class. + */ +BlockChainStream* BlockChainStream_Construct( + StorageImpl* parentStorage, + ULONG* headOfStreamPlaceHolder, + ULONG propertyIndex); + +void BlockChainStream_Destroy( + BlockChainStream* This); + +ULONG BlockChainStream_GetHeadOfChain( + BlockChainStream* This); + +BOOL BlockChainStream_ReadAt( + BlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + void* buffer, + ULONG* bytesRead); + +BOOL BlockChainStream_WriteAt( + BlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + const void* buffer, + ULONG* bytesWritten); + +BOOL BlockChainStream_SetSize( + BlockChainStream* This, + ULARGE_INTEGER newSize); + +ULARGE_INTEGER BlockChainStream_GetSize( + BlockChainStream* This); + +ULONG BlockChainStream_GetCount( + BlockChainStream* This); + +/**************************************************************************** + * SmallBlockChainStream definitions. + * + * The SmallBlockChainStream class is a utility class that is used to create an + * abstraction of the small block chains in the storage file. + */ +struct SmallBlockChainStream +{ + StorageImpl* parentStorage; + ULONG ownerPropertyIndex; +}; + +/* + * Methods of the SmallBlockChainStream class. + */ +SmallBlockChainStream* SmallBlockChainStream_Construct( + StorageImpl* parentStorage, + ULONG propertyIndex); + +void SmallBlockChainStream_Destroy( + SmallBlockChainStream* This); + +ULONG SmallBlockChainStream_GetHeadOfChain( + SmallBlockChainStream* This); + +ULONG SmallBlockChainStream_GetNextBlockInChain( + SmallBlockChainStream* This, + ULONG blockIndex); + +void SmallBlockChainStream_SetNextBlockInChain( + SmallBlockChainStream* This, + ULONG blockIndex, + ULONG nextBlock); + +void SmallBlockChainStream_FreeBlock( + SmallBlockChainStream* This, + ULONG blockIndex); + +ULONG SmallBlockChainStream_GetNextFreeBlock( + SmallBlockChainStream* This); + +BOOL SmallBlockChainStream_ReadAt( + SmallBlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + void* buffer, + ULONG* bytesRead); + +BOOL SmallBlockChainStream_WriteAt( + SmallBlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + const void* buffer, + ULONG* bytesWritten); + +BOOL SmallBlockChainStream_SetSize( + SmallBlockChainStream* This, + ULARGE_INTEGER newSize); + +ULARGE_INTEGER SmallBlockChainStream_GetSize( + SmallBlockChainStream* This); + +ULONG SmallBlockChainStream_GetCount( + SmallBlockChainStream* This); + + +#endif /* __STORAGE32_H__ */ + + + diff --git a/lib/ole32/itemmoniker.c b/lib/ole32/itemmoniker.c new file mode 100644 index 0000000..01e7e13 --- /dev/null +++ b/lib/ole32/itemmoniker.c @@ -0,0 +1,973 @@ +/*************************************************************************************** + * ItemMonikers implementation + * + * Copyright 1999 Noomen Hamza + ***************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + + +/* ItemMoniker data structure */ +typedef struct ItemMonikerImpl{ + + ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/ + + /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether + * two monikers are equal. That's whay IROTData interface is implemented by monikers. + */ + ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/ + + ULONG ref; /* reference counter for this object */ + + LPOLESTR itemName; /* item name identified by this ItemMoniker */ + + LPOLESTR itemDelimiter; /* Delimiter string */ + +} ItemMonikerImpl; + +/********************************************************************************/ +/* ItemMoniker prototype functions : */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject); +static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface); +static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface); + +/* IPersist prototype functions */ +static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID); + +/* IPersistStream prototype functions */ +static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface); +static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm); +static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty); +static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize); + +/* IMoniker prototype functions */ +static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult); +static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced); +static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite); +static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker); +static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker); +static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash); +static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning); +static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime); +static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk); +static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix); +static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath); +static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName); +static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut); +static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys); + +/* Local function used by ItemMoniker implementation */ +HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName); +HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface); + +/********************************************************************************/ +/* IROTData prototype functions */ + +/* IUnknown prototype functions */ +static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject); +static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface); +static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface); + +/* IROTData prototype function */ +static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData); + +/********************************************************************************/ +/* Virtual function table for the ItemMonikerImpl class which include IPersist,*/ +/* IPersistStream and IMoniker functions. */ +static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl = + { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + ItemMonikerImpl_QueryInterface, + ItemMonikerImpl_AddRef, + ItemMonikerImpl_Release, + ItemMonikerImpl_GetClassID, + ItemMonikerImpl_IsDirty, + ItemMonikerImpl_Load, + ItemMonikerImpl_Save, + ItemMonikerImpl_GetSizeMax, + ItemMonikerImpl_BindToObject, + ItemMonikerImpl_BindToStorage, + ItemMonikerImpl_Reduce, + ItemMonikerImpl_ComposeWith, + ItemMonikerImpl_Enum, + ItemMonikerImpl_IsEqual, + ItemMonikerImpl_Hash, + ItemMonikerImpl_IsRunning, + ItemMonikerImpl_GetTimeOfLastChange, + ItemMonikerImpl_Inverse, + ItemMonikerImpl_CommonPrefixWith, + ItemMonikerImpl_RelativePathTo, + ItemMonikerImpl_GetDisplayName, + ItemMonikerImpl_ParseDisplayName, + ItemMonikerImpl_IsSystemMoniker +}; + +/********************************************************************************/ +/* Virtual function table for the IROTData class. */ +static ICOM_VTABLE(IROTData) VT_ROTDataImpl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + ItemMonikerROTDataImpl_QueryInterface, + ItemMonikerROTDataImpl_AddRef, + ItemMonikerROTDataImpl_Release, + ItemMonikerROTDataImpl_GetComparaisonData +}; + +/******************************************************************************* + * ItemMoniker_QueryInterface + *******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",This,riid,ppvObject)); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream, riid) || + IsEqualIID(&IID_IMoniker, riid) + ) + *ppvObject = iface; + + else if (IsEqualIID(&IID_IROTData, riid)) + *ppvObject = (IROTData*)&(This->lpvtbl2); + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* Query Interface always increases the reference count by one when it is successful */ + ItemMonikerImpl_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_AddRef + ******************************************************************************/ +ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + return ++(This->ref); +} + +/****************************************************************************** + * ItemMoniker_Release + ******************************************************************************/ +ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p)\n",This)); + + This->ref--; + + /* destroy the object if there's no more reference on it */ + if (This->ref==0){ + + ItemMonikerImpl_Destroy(This); + + return 0; + } + return This->ref;; +} + +/****************************************************************************** + * ItemMoniker_GetClassID + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) +{ + Print(MAX_TRACE, ("(%p,%p),stub!\n",iface,pClassID)); + + if (pClassID==NULL) + return E_POINTER; + + *pClassID = CLSID_ItemMoniker; + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_IsDirty + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface) +{ + /* Note that the OLE-provided implementations of the IPersistStream::IsDirty + method in the OLE-provided moniker interfaces always return S_FALSE because + their internal state never changes. */ + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return S_FALSE; +} + +/****************************************************************************** + * ItemMoniker_Load + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm) +{ + + ICOM_THIS(ItemMonikerImpl,iface); + HRESULT res; + DWORD delimiterLength,nameLength,lenW; + CHAR *itemNameA,*itemDelimiterA; + ULONG bread; + + /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */ + + /* read item delimiter string length + 1 */ + res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread); + if (bread != sizeof(DWORD)) + return E_FAIL; + + /* read item delimiter string */ + if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength))) + return E_OUTOFMEMORY; + res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread); + if (bread != delimiterLength) + { + HeapFree( GetProcessHeap(), 0, itemDelimiterA ); + return E_FAIL; + } + + lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 ); + This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR)); + if (!This->itemDelimiter) + { + HeapFree( GetProcessHeap(), 0, itemDelimiterA ); + return E_OUTOFMEMORY; + } + MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW ); + HeapFree( GetProcessHeap(), 0, itemDelimiterA ); + + /* read item name string length + 1*/ + res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread); + if (bread != sizeof(DWORD)) + return E_FAIL; + + /* read item name string */ + if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength))) + return E_OUTOFMEMORY; + res=IStream_Read(pStm,itemNameA,nameLength,&bread); + if (bread != nameLength) + { + HeapFree( GetProcessHeap(), 0, itemNameA ); + return E_FAIL; + } + + lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 ); + This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR)); + if (!This->itemName) + { + HeapFree( GetProcessHeap(), 0, itemNameA ); + return E_OUTOFMEMORY; + } + MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW ); + HeapFree( GetProcessHeap(), 0, itemNameA ); + + return res; +} + +/****************************************************************************** + * ItemMoniker_Save + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, + IStream* pStm,/* pointer to the stream where the object is to be saved */ + BOOL fClearDirty)/* Specifies whether to clear the dirty flag */ +{ + ICOM_THIS(ItemMonikerImpl,iface); + HRESULT res; + CHAR *itemNameA,*itemDelimiterA; + + /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */ + /* 2) String (type A): item delimiter string ('\0' included) */ + /* 3) DWORD : size of item name string ('\0' included) */ + /* 4) String (type A): item name string ('\0' included) */ + + DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL); + DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL); + itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength); + itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength); + WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL); + WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL); + + res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL); + res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL); + res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL); + res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL); + + return res; +} + +/****************************************************************************** + * ItemMoniker_GetSizeMax + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, + ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ +{ + ICOM_THIS(ItemMonikerImpl,iface); + DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1; + DWORD nameLength=lstrlenW(This->itemName)+1; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pcbSize)); + + if (pcbSize!=NULL) + return E_POINTER; + + /* for more details see ItemMonikerImpl_Save coments */ + + pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */ + delimiterLength + /* item delimiter string */ + sizeof(DWORD) + /* DWORD which contains item name length */ + nameLength + /* item name string */ + 34; /* this constant was added ! because when I tested this function it usually */ + /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */ + pcbSize->u.HighPart=0; + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_Construct (local function) + *******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem) +{ + + int sizeStr1=lstrlenW(lpszItem), sizeStr2; + static const OLECHAR emptystr[1]; + LPCOLESTR delim; + + Print(MAX_TRACE, ("(%p,%p)\n",This,lpszItem)); + + /* Initialize the virtual fgunction table. */ + This->lpvtbl1 = &VT_ItemMonikerImpl; + This->lpvtbl2 = &VT_ROTDataImpl; + This->ref = 0; + + This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1)); + if (!This->itemName) + return E_OUTOFMEMORY; + lstrcpyW(This->itemName,lpszItem); + + if (!lpszDelim) + Print(MIN_TRACE, ("lpszDelim is NULL. Using empty string which is possibly wrong.\n")); + + delim = lpszDelim ? lpszDelim : emptystr; + + sizeStr2=lstrlenW(delim); + This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1)); + if (!This->itemDelimiter) { + HeapFree(GetProcessHeap(),0,This->itemName); + return E_OUTOFMEMORY; + } + lstrcpyW(This->itemDelimiter,delim); + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_Destroy (local function) + *******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n",This)); + + if (This->itemName) + HeapFree(GetProcessHeap(),0,This->itemName); + + if (This->itemDelimiter) + HeapFree(GetProcessHeap(),0,This->itemDelimiter); + + HeapFree(GetProcessHeap(),0,This); + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_BindToObject + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + HRESULT res; + IID refid=IID_IOleItemContainer; + IOleItemContainer *poic=0; + + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + + if(ppvResult ==NULL) + return E_POINTER; + + if(pmkToLeft==NULL) + return E_INVALIDARG; + + *ppvResult=0; + + res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic); + + if (SUCCEEDED(res)){ + + res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult); + + IOleItemContainer_Release(poic); + } + + return res; +} + +/****************************************************************************** + * ItemMoniker_BindToStorage + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + REFIID riid, + VOID** ppvResult) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + HRESULT res; + IOleItemContainer *poic=0; + + Print(MAX_TRACE, ("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult)); + + *ppvResult=0; + + if(pmkToLeft==NULL) + return E_INVALIDARG; + + res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); + + if (SUCCEEDED(res)){ + + res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult); + + IOleItemContainer_Release(poic); + } + + return res; +} + +/****************************************************************************** + * ItemMoniker_Reduce + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface, + IBindCtx* pbc, + DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, + IMoniker** ppmkReduced) +{ + Print(MAX_TRACE, ("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced)); + + if (ppmkReduced==NULL) + return E_POINTER; + + ItemMonikerImpl_AddRef(iface); + + *ppmkReduced=iface; + + return MK_S_REDUCED_TO_SELF; +} +/****************************************************************************** + * ItemMoniker_ComposeWith + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface, + IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, + IMoniker** ppmkComposite) +{ + HRESULT res=S_OK; + DWORD mkSys,mkSys2; + IEnumMoniker* penumMk=0; + IMoniker *pmostLeftMk=0; + IMoniker* tempMkComposite=0; + + Print(MAX_TRACE, ("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite)); + + if ((ppmkComposite==NULL)||(pmkRight==NULL)) + return E_POINTER; + + *ppmkComposite=0; + + IMoniker_IsSystemMoniker(pmkRight,&mkSys); + + /* If pmkRight is an anti-moniker, the returned moniker is NULL */ + if(mkSys==MKSYS_ANTIMONIKER) + return res; + + else + /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ + /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ + + if(mkSys==MKSYS_GENERICCOMPOSITE){ + + res=IMoniker_Enum(pmkRight,TRUE,&penumMk); + + if (FAILED(res)) + return res; + + res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); + + IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); + + if(mkSys2==MKSYS_ANTIMONIKER){ + + IMoniker_Release(pmostLeftMk); + + tempMkComposite=iface; + IMoniker_AddRef(iface); + + while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ + + res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); + + IMoniker_Release(tempMkComposite); + IMoniker_Release(pmostLeftMk); + + tempMkComposite=*ppmkComposite; + IMoniker_AddRef(tempMkComposite); +} + return res; + } + else + return CreateGenericComposite(iface,pmkRight,ppmkComposite); + } + /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic + composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns + a NULL moniker and a return value of MK_E_NEEDGENERIC */ + else + if (!fOnlyIfNotGeneric) + return CreateGenericComposite(iface,pmkRight,ppmkComposite); + + else + return MK_E_NEEDGENERIC; +} + +/****************************************************************************** + * ItemMoniker_Enum + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) +{ + Print(MAX_TRACE, ("(%p,%d,%p)\n",iface,fForward,ppenumMoniker)); + + if (ppenumMoniker == NULL) + return E_POINTER; + + *ppenumMoniker = NULL; + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_IsEqual + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +{ + + CLSID clsid; + LPOLESTR dispName1,dispName2; + IBindCtx* bind; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p)\n",iface,pmkOtherMoniker)); + + if (pmkOtherMoniker==NULL) + return S_FALSE; + + /* This method returns S_OK if both monikers are item monikers and their display names are */ + /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */ + + IMoniker_GetClassID(pmkOtherMoniker,&clsid); + + if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) + return S_FALSE; + + res=CreateBindCtx(0,&bind); + if (FAILED(res)) + return res; + + IMoniker_GetDisplayName(iface,bind,NULL,&dispName1); + IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2); + + if (lstrcmpW(dispName1,dispName2)!=0) + return S_FALSE; + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_Hash + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + int h = 0,i,skip,len; + int off = 0; + LPOLESTR val; + + if (pdwHash==NULL) + return E_POINTER; + + val = This->itemName; + len = lstrlenW(val); + + if (len < 16) { + for (i = len ; i > 0; i--) { + h = (h * 37) + val[off++]; +} + } else { + /* only sample some characters */ + skip = len / 8; + for (i = len ; i > 0; i -= skip, off += skip) { + h = (h * 39) + val[off]; + } + } + + *pdwHash=h; + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_IsRunning + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + IRunningObjectTable* rot; + HRESULT res; + IOleItemContainer *poic=0; + ICOM_THIS(ItemMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning)); + + /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */ + /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */ + if (pmkToLeft==NULL) + if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK)) + return S_OK; + else { + if (pbc==NULL) + return E_POINTER; + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (FAILED(res)) + return res; + + res = IRunningObjectTable_IsRunning(rot,iface); + + IRunningObjectTable_Release(rot); + } + else{ + + /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */ + /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/ + /* passing the string contained within this moniker. */ + + res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); + + if (SUCCEEDED(res)){ + + res=IOleItemContainer_IsRunning(poic,This->itemName); + + IOleItemContainer_Release(poic); + } + } + + return res; +} + +/****************************************************************************** + * ItemMoniker_GetTimeOfLastChange + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pItemTime) +{ + IRunningObjectTable* rot; + HRESULT res; + IMoniker *compositeMk; + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime)); + + if (pItemTime==NULL) + return E_INVALIDARG; + + /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */ + if (pmkToLeft==NULL) + + return MK_E_NOTBINDABLE; + else { + + /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */ + /* the time of last change. If the object is not in the ROT, the method calls */ + /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */ + + res=CreateGenericComposite(pmkToLeft,iface,&compositeMk); + + res=IBindCtx_GetRunningObjectTable(pbc,&rot); + + if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK) + + res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime); + + IMoniker_Release(compositeMk); +} + + return res; +} + +/****************************************************************************** + * ItemMoniker_Inverse + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +{ + Print(MAX_TRACE, ("(%p,%p)\n",iface,ppmk)); + + if (ppmk==NULL) + return E_POINTER; + + return CreateAntiMoniker(ppmk); +} + +/****************************************************************************** + * ItemMoniker_CommonPrefixWith + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +{ + DWORD mkSys; + IMoniker_IsSystemMoniker(pmkOther,&mkSys); + /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */ + /* to this moniker and returns MK_S_US */ + + if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){ + + *ppmkPrefix=iface; + + IMoniker_AddRef(iface); + + return MK_S_US; + } + else + /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */ + /* the case where the other moniker is a generic composite. */ + return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix); +} + +/****************************************************************************** + * ItemMoniker_RelativePathTo + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) +{ + Print(MAX_TRACE, ("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath)); + + if (ppmkRelPath==NULL) + return E_POINTER; + + *ppmkRelPath=0; + + return MK_E_NOTBINDABLE; +} + +/****************************************************************************** + * ItemMoniker_GetDisplayName + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR *ppszDisplayName) +{ + ICOM_THIS(ItemMonikerImpl,iface); + + Print(MAX_TRACE, ("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName)); + + if (ppszDisplayName==NULL) + return E_POINTER; + + if (pmkToLeft!=NULL){ + return E_INVALIDARG; + } + + *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1)); + + if (*ppszDisplayName==NULL) + return E_OUTOFMEMORY; + + lstrcpyW(*ppszDisplayName,This->itemDelimiter); + lstrcatW(*ppszDisplayName,This->itemName); + + return S_OK; +} + +/****************************************************************************** + * ItemMoniker_ParseDisplayName + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + LPOLESTR pszDisplayName, + ULONG* pchEaten, + IMoniker** ppmkOut) +{ + IOleItemContainer* poic=0; + IParseDisplayName* ppdn=0; + LPOLESTR displayName; + HRESULT res; + ICOM_THIS(ItemMonikerImpl,iface); + + /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */ + if (pmkToLeft==NULL) + + return MK_E_SYNTAX; + + else{ + /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */ + /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */ + res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); + + if (SUCCEEDED(res)){ + + res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn); + + res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName); + + res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut); + + IOleItemContainer_Release(poic); + IParseDisplayName_Release(ppdn); + } +} + return res; +} + +/****************************************************************************** + * ItemMoniker_IsSystemMoniker + ******************************************************************************/ +HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) +{ + Print(MAX_TRACE, ("(%p,%p)\n",iface,pwdMksys)); + + if (!pwdMksys) + return E_POINTER; + + (*pwdMksys)=MKSYS_ITEMMONIKER; + + return S_OK; +} + +/******************************************************************************* + * ItemMonikerIROTData_QueryInterface + *******************************************************************************/ +HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) +{ + + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p,%p,%p)\n",iface,riid,ppvObject)); + + return ItemMonikerImpl_QueryInterface(This, riid, ppvObject); +} + +/*********************************************************************** + * ItemMonikerIROTData_AddRef + */ +ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface) +{ + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return ItemMonikerImpl_AddRef(This); +} + +/*********************************************************************** + * ItemMonikerIROTData_Release + */ +ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface) +{ + ICOM_THIS_From_IROTData(IMoniker, iface); + + Print(MAX_TRACE, ("(%p)\n",iface)); + + return ItemMonikerImpl_Release(This); +} + +/****************************************************************************** + * ItemMonikerIROTData_GetComparaisonData + ******************************************************************************/ +HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface, + BYTE* pbData, + ULONG cbMax, + ULONG* pcbData) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/****************************************************************************** + * CreateItemMoniker16 [OLE2.28] + ******************************************************************************/ +HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR lpszItem,LPMONIKER* ppmk) +{ + + Print(MIN_TRACE, ("(%s,%p),stub!\n",lpszDelim,ppmk)); + *ppmk = NULL; + return E_NOTIMPL; +} + +/****************************************************************************** + * CreateItemMoniker [OLE.55] + ******************************************************************************/ +HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk) +{ + ItemMonikerImpl* newItemMoniker = 0; + HRESULT hr = S_OK; + IID riid=IID_IMoniker; + + Print(MAX_TRACE, ("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk)); + + newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); + + if (newItemMoniker == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem); + + if (FAILED(hr)){ + + HeapFree(GetProcessHeap(),0,newItemMoniker); + return hr; + } + + return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk); +} diff --git a/lib/ole32/makefile b/lib/ole32/makefile new file mode 100644 index 0000000..7512be7 --- /dev/null +++ b/lib/ole32/makefile @@ -0,0 +1,47 @@ +# $Id$ +# +# Jurgen Van Gael [jurgen.vangael@student.kuleuven.ac.be] +# +# Makefile for ReactOS ole32.dll +# + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = ole32 + +TARGET_BASE = 0x77a50000 + +TARGET_DEFONLY = yes + +TARGET_CFLAGS = -fno-rtti -I./include + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a user32.a gdi32.a msvcrt.a + +TARGET_OBJECTS = \ + DllMain.o \ + CoXxx.o \ + Moniker.o \ + Ole2.o \ + OleAuto.o \ + Misc.o \ + Storage.o \ + storage32.o \ + stg_stream.o \ + stg_bigblockfile.o \ + compobj.o \ + memlockbytes.o \ + rpcrt4_main.o \ + filemoniker.o \ + bindctx.o \ + compositemoniker.o \ + itemmoniker.o \ + antimoniker.o \ + datacache.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/lib/ole32/memlockbytes.c b/lib/ole32/memlockbytes.c new file mode 100644 index 0000000..f877080 --- /dev/null +++ b/lib/ole32/memlockbytes.c @@ -0,0 +1,581 @@ +/****************************************************************************** + * + * Global memory implementation of ILockBytes. + * + * Copyright 1999 Thuy Nguyen + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/****************************************************************************** + * HGLOBALLockBytesImpl definition. + * + * This class imlements the ILockBytes inteface and represents a byte array + * object supported by an HGLOBAL pointer. + */ +struct HGLOBALLockBytesImpl +{ + /* + * Needs to be the first item in the stuct + * since we want to cast this in an ILockBytes pointer + */ + ICOM_VFIELD(ILockBytes); + + /* + * Reference count + */ + ULONG ref; + + /* + * Support for the LockBytes object + */ + HGLOBAL supportHandle; + + /* + * This flag is TRUE if the HGLOBAL is destroyed when the object + * is finally released. + */ + BOOL deleteOnRelease; + + /* + * Helper variable that contains the size of the byte array + */ + ULARGE_INTEGER byteArraySize; +}; + +typedef struct HGLOBALLockBytesImpl HGLOBALLockBytesImpl; + +/* + * Method definition for the HGLOBALLockBytesImpl class. + */ +HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct( + HGLOBAL hGlobal, + BOOL fDeleteOnRelease); + +void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This); + +HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface( + ILockBytes* iface, + REFIID riid, /* [in] */ + void** ppvObject); /* [iid_is][out] */ + +ULONG WINAPI HGLOBALLockBytesImpl_AddRef( + ILockBytes* iface); + +ULONG WINAPI HGLOBALLockBytesImpl_Release( + ILockBytes* iface); + +HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt( + ILockBytes* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead); /* [out] */ + +HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt( + ILockBytes* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten); /* [out] */ + +HRESULT WINAPI HGLOBALLockBytesImpl_Flush( + ILockBytes* iface); + +HRESULT WINAPI HGLOBALLockBytesImpl_SetSize( + ILockBytes* iface, + ULARGE_INTEGER libNewSize); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion( + ILockBytes* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion( + ILockBytes* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl_Stat( + ILockBytes* iface, + STATSTG* pstatstg, /* [out] */ + DWORD grfStatFlag); /* [in] */ + +/* + * Virtual function table for the HGLOBALLockBytesImpl class. + */ +static ICOM_VTABLE(ILockBytes) HGLOBALLockBytesImpl_Vtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + HGLOBALLockBytesImpl_QueryInterface, + HGLOBALLockBytesImpl_AddRef, + HGLOBALLockBytesImpl_Release, + HGLOBALLockBytesImpl_ReadAt, + HGLOBALLockBytesImpl_WriteAt, + HGLOBALLockBytesImpl_Flush, + HGLOBALLockBytesImpl_SetSize, + HGLOBALLockBytesImpl_LockRegion, + HGLOBALLockBytesImpl_UnlockRegion, + HGLOBALLockBytesImpl_Stat, +}; + +/****************************************************************************** + * CreateILockBytesOnHGlobal [OLE32.57] + */ +HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL hGlobal, + BOOL fDeleteOnRelease, + LPLOCKBYTES* ppLkbyt) +{ + HGLOBALLockBytesImpl* newLockBytes; + + newLockBytes = HGLOBALLockBytesImpl_Construct(hGlobal, fDeleteOnRelease); + + if (newLockBytes != NULL) + { + return IUnknown_QueryInterface((IUnknown*)newLockBytes, + &IID_ILockBytes, + (void**)ppLkbyt); + } + + return E_OUTOFMEMORY; +} + +/****************************************************************************** + * GetHGlobalFromILockBytes [OLE32.70] + */ +HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal) +{ + HGLOBALLockBytesImpl* const pMemLockBytes = (HGLOBALLockBytesImpl*)plkbyt; + + if (ICOM_VTBL(pMemLockBytes) == &HGLOBALLockBytesImpl_Vtbl) + *phglobal = pMemLockBytes->supportHandle; + else + *phglobal = 0; + + if (*phglobal == 0) + return E_INVALIDARG; + + return S_OK; +} + +/****************************************************************************** + * + * HGLOBALLockBytesImpl implementation + * + */ + +/****************************************************************************** + * This is the constructor for the HGLOBALLockBytesImpl class. + * + * Params: + * hGlobal - Handle that will support the stream. can be NULL. + * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released + * when the IStream object is destroyed. + */ +HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(HGLOBAL hGlobal, + BOOL fDeleteOnRelease) +{ + HGLOBALLockBytesImpl* newLockBytes; + newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl)); + + if (newLockBytes!=0) + { + /* + * Set up the virtual function table and reference count. + */ + ICOM_VTBL(newLockBytes) = &HGLOBALLockBytesImpl_Vtbl; + newLockBytes->ref = 0; + + /* + * Initialize the support. + */ + newLockBytes->supportHandle = hGlobal; + newLockBytes->deleteOnRelease = fDeleteOnRelease; + + /* + * This method will allocate a handle if one is not supplied. + */ + if (newLockBytes->supportHandle == 0) + { + newLockBytes->supportHandle = GlobalAlloc(GMEM_MOVEABLE | + GMEM_NODISCARD, + 0); + } + + /* + * Initialize the size of the array to the size of the handle. + */ + newLockBytes->byteArraySize.u.HighPart = 0; + newLockBytes->byteArraySize.u.LowPart = GlobalSize( + newLockBytes->supportHandle); + } + + return newLockBytes; +} + +/****************************************************************************** + * This is the destructor of the HGLOBALStreamImpl class. + * + * This method will clean-up all the resources used-up by the given + * HGLOBALLockBytesImpl class. The pointer passed-in to this function will be + * freed and will not be valid anymore. + */ +void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This) +{ + /* + * Release the HGlobal if the constructor asked for that. + */ + if (This->deleteOnRelease) + { + GlobalFree(This->supportHandle); + This->supportHandle = 0; + } + + /* + * Finally, free the memory used-up by the class. + */ + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** + * This implements the IUnknown method QueryInterface for this + * class + */ +HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface( + ILockBytes* iface, + REFIID riid, /* [in] */ + void** ppvObject) /* [iid_is][out] */ +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + /* + * Perform a sanity check on the parameters. + */ + if (ppvObject==0) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) + { + *ppvObject = (ILockBytes*)This; + } + else if (memcmp(&IID_ILockBytes, riid, sizeof(IID_ILockBytes)) == 0) + { + *ppvObject = (ILockBytes*)This; + } + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* + * Query Interface always increases the reference count by one when it is + * successful + */ + HGLOBALLockBytesImpl_AddRef(iface); + + return S_OK;; +} + +/****************************************************************************** + * This implements the IUnknown method AddRef for this + * class + */ +ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface) +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + This->ref++; + + return This->ref; +} + +/****************************************************************************** + * This implements the IUnknown method Release for this + * class + */ +ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface) +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + ULONG newRef; + + This->ref--; + + newRef = This->ref; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (newRef==0) + { + HGLOBALLockBytesImpl_Destroy(This); + } + + return newRef; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It reads a block of information from the byte array at the specified + * offset. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt( + ILockBytes* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead) /* [out] */ +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + void* supportBuffer; + ULONG bytesReadBuffer = 0; + ULONG bytesToReadFromBuffer; + + /* + * If the caller is not interested in the number of bytes read, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbRead == 0) + pcbRead = &bytesReadBuffer; + + /* + * Make sure the offset is valid. + */ + if (ulOffset.u.LowPart > This->byteArraySize.u.LowPart) + return E_FAIL; + + /* + * Using the known size of the array, calculate the number of bytes + * to read. + */ + bytesToReadFromBuffer = min(This->byteArraySize.u.LowPart - + ulOffset.u.LowPart, cb); + + /* + * Lock the buffer in position and copy the data. + */ + supportBuffer = GlobalLock(This->supportHandle); + + memcpy(pv, + (char *) supportBuffer + ulOffset.u.LowPart, + bytesToReadFromBuffer); + + /* + * Return the number of bytes read. + */ + *pcbRead = bytesToReadFromBuffer; + + /* + * Cleanup + */ + GlobalUnlock(This->supportHandle); + + /* + * The function returns S_OK if the specified number of bytes were read + * or the end of the array was reached. + * It returns STG_E_READFAULT if the number of bytes to read does not equal + * the number of bytes actually read. + */ + if(*pcbRead == cb) + return S_OK; + + return STG_E_READFAULT; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It writes the specified bytes at the specified offset. + * position. If the array is too small, it will be resized. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt( + ILockBytes* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten) /* [out] */ +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + void* supportBuffer; + ULARGE_INTEGER newSize; + ULONG bytesWritten = 0; + + /* + * If the caller is not interested in the number of bytes written, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbWritten == 0) + pcbWritten = &bytesWritten; + + if (cb == 0) + { + return S_OK; + } + else + { + newSize.u.HighPart = 0; + newSize.u.LowPart = ulOffset.u.LowPart + cb; + } + + /* + * Verify if we need to grow the stream + */ + if (newSize.u.LowPart > This->byteArraySize.u.LowPart) + { + /* grow stream */ + if (HGLOBALLockBytesImpl_SetSize(iface, newSize) == STG_E_MEDIUMFULL) + return STG_E_MEDIUMFULL; + } + + /* + * Lock the buffer in position and copy the data. + */ + supportBuffer = GlobalLock(This->supportHandle); + + memcpy((char *) supportBuffer + ulOffset.u.LowPart, pv, cb); + + /* + * Return the number of bytes written. + */ + *pcbWritten = cb; + + /* + * Cleanup + */ + GlobalUnlock(This->supportHandle); + + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_Flush(ILockBytes* iface) +{ + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It will change the size of the byte array. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_SetSize( + ILockBytes* iface, + ULARGE_INTEGER libNewSize) /* [in] */ +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + /* + * As documented. + */ + if (libNewSize.u.HighPart != 0) + return STG_E_INVALIDFUNCTION; + + if (This->byteArraySize.u.LowPart == libNewSize.u.LowPart) + return S_OK; + + /* + * Re allocate the HGlobal to fit the new size of the stream. + */ + This->supportHandle = GlobalReAlloc(This->supportHandle, + libNewSize.u.LowPart, + 0); + + if (This->supportHandle == 0) + return STG_E_MEDIUMFULL; + + This->byteArraySize.u.LowPart = libNewSize.u.LowPart; + + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * The global memory implementation of ILockBytes does not support locking. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion( + ILockBytes* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + return STG_E_INVALIDFUNCTION; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * The global memory implementation of ILockBytes does not support locking. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion( + ILockBytes* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + return STG_E_INVALIDFUNCTION; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * This method returns information about the current + * byte array object. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl_Stat( + ILockBytes* iface, + STATSTG* pstatstg, /* [out] */ + DWORD grfStatFlag) /* [in] */ +{ + HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; + + memset(pstatstg, 0, sizeof(STATSTG)); + + pstatstg->pwcsName = NULL; + pstatstg->type = STGTY_LOCKBYTES; + pstatstg->cbSize = This->byteArraySize; + + return S_OK; +} + diff --git a/lib/ole32/ole32.def b/lib/ole32/ole32.def new file mode 100644 index 0000000..9dd86d2 --- /dev/null +++ b/lib/ole32/ole32.def @@ -0,0 +1,307 @@ +LIBRARY ole32.dll + +EXPORTS +;BindMoniker @ 9 +;CLIPFORMAT_UserFree @ 10 +;CLIPFORMAT_UserMarshal @ 11 +;CLIPFORMAT_UserSize @ 12 +;CLIPFORMAT_UserUnmarshal @ 13 +CLSIDFromProgID@8 @ 14 +;CLSIDFromProgIDEx @ 15 +CLSIDFromString@8 @ 16 +CoAddRefServerProcess@0 @ 17 +CoAllowSetForegroundWindow@8 @ 18 +CoBuildVersion@0 @ 19 +CoCancelCall@8 @ 20 +CoCopyProxy@8 @ 21 +CoCreateFreeThreadedMarshaler@8 @ 22 +CoCreateGuid@4 @ 23 +CoCreateInstance@20 @ 24 +CoCreateInstanceEx@24 @ 25 +;CoCreateObjectInContext @ 26 +;CoDeactivateObject @ 27 +CoDisableCallCancellation@4 @ 28 +CoDisconnectObject@8 @ 29 +CoDosDateTimeToFileTime@12 @ 30 +CoEnableCallCancellation@4 @ 31 +CoFileTimeNow@4 @ 32 +CoFileTimeToDosDateTime@12 @ 33 +CoFreeAllLibraries@0 @ 34 +CoFreeLibrary@4 @ 35 +CoFreeUnusedLibraries@0 @ 36 +;CoGetApartmentID @ 37 +CoGetCallContext@8 @ 38 +;CoGetCallerTID @ 39 +CoGetCancelObject@12 @ 40 +CoGetClassObject@20 @ 41 +;CoGetClassVersion @ 42 +;CoGetCurrentLogicalThreadId @ 43 +CoGetCurrentProcess@0 @ 44 +CoGetInstanceFromFile@32 @ 45 +CoGetInstanceFromIStorage@28 @ 46 +CoGetInterfaceAndReleaseStream@12 @ 47 +CoGetMalloc@8 @ 48 +CoGetMarshalSizeMax@24 @ 49 +CoGetObject@16 @ 50 +CoGetObjectContext@8 @ 51 +CoGetPSClsid@8 @ 52 +CoGetStandardMarshal@24 @ 53 +;CoGetState @ 54 +CoGetStdMarshalEx@12 @ 55 +CoGetTreatAsClass@8 @ 56 +CoImpersonateClient@0 @ 57 +CoInitialize@4 @ 58 +CoInitializeEx@8 @ 59 +CoInitializeSecurity@36 @ 60 +CoInitializeWOW@8 @ 61 +;CoInstall @ 62 +CoIsHandlerConnected@4 @ 63 +;CoIsOle1Class @ 64 +CoLoadLibrary@8 @ 65 +CoLockObjectExternal@12 @ 66 +CoMarshalHresult@8 @ 67 +CoMarshalInterThreadInterfaceInStream@12 @ 68 +CoMarshalInterface@24 @ 69 +CoQueryAuthenticationServices@8 @ 70 +CoQueryClientBlanket@28 @ 71 +CoQueryProxyBlanket@32 @ 72 +;CoQueryReleaseObject @ 73 +;CoReactivateObject @ 74 +;CoRegisterChannelHook @ 75 +CoRegisterClassObject@20 @ 76 +CoRegisterMallocSpy@4 @ 77 +CoRegisterMessageFilter@8 @ 78 +CoRegisterPSClsid@8 @ 79 +;CoRegisterSurrogate @ 80 +;CoRegisterSurrogateEx @ 81 +CoReleaseMarshalData@4 @ 82 +CoReleaseServerProcess@0 @ 83 +CoResumeClassObjects@0 @ 84 +CoRevertToSelf@0 @ 85 +CoRevokeClassObject@4 @ 86 +CoRevokeMallocSpy@0 @ 87 +CoSetCancelObject@4 @ 88 +CoSetProxyBlanket@32 @ 89 +CoSetState@4 @ 90 +CoSuspendClassObjects@0 @ 91 +CoSwitchCallContext@8 @ 92 +CoTaskMemAlloc@4 @ 93 +CoTaskMemFree@4 @ 94 +CoTaskMemRealloc@8 @ 95 +CoTestCancel@0 @ 96 +CoTreatAsClass@8 @ 97 +CoUninitialize@0 @ 98 +;CoUnloadingWOW @ 99 +CoUnmarshalHresult@8 @ 100 +CoUnmarshalInterface@12 @ 101 +CoWaitForMultipleHandles@20 @ 102 +CreateAntiMoniker@4 @ 103 +CreateBindCtx@8 @ 104 +;CreateClassMoniker @ 105 +;CreateDataAdviseHolder @ 106 +CreateDataCache@16 @ 107 +;CreateErrorInfo @ 108 +CreateFileMoniker@8 @ 109 +CreateGenericComposite@12 @ 110 +CreateILockBytesOnHGlobal@12 @ 111 +CreateItemMoniker@12 @ 112 +;CreateObjrefMoniker @ 113 +;CreateOleAdviseHolder @ 114 +;CreatePointerMoniker @ 115 +;CreateStdProgressIndicator @ 116 +;CreateStreamOnHGlobal @ 117 +;DcomChannelSetHResult @ 118 +;DllDebugObjectRPCHook @ 119 +;DllGetClassObject @ 120 +;DllGetClassObjectWOW @ 121 +;DllRegisterServer @ 122 +;DoDragDrop @ 123 +;EnableHookObject @ 124 +;FmtIdToPropStgName @ 125 +;FreePropVariantArray @ 126 +GetClassFile@8 @ 127 +GetConvertStg@4 @ 128 +;GetDocumentBitStg @ 129 +;GetErrorInfo @ 130 +GetHGlobalFromILockBytes@8 @ 131 +;GetHGlobalFromStream @ 132 +;GetHookInterface @ 133 +GetRunningObjectTable@8 @ 134 +;HACCEL_UserFree @ 135 +;HACCEL_UserMarshal @ 136 +;HACCEL_UserSize @ 137 +;HACCEL_UserUnmarshal @ 138 +;HBITMAP_UserFree @ 139 +;HBITMAP_UserMarshal @ 140 +;HBITMAP_UserSize @ 141 +;HBITMAP_UserUnmarshal @ 142 +;HBRUSH_UserFree @ 143 +;HBRUSH_UserMarshal @ 144 +;HBRUSH_UserSize @ 145 +;HBRUSH_UserUnmarshal @ 146 +;HDC_UserFree @ 147 +;HDC_UserMarshal @ 148 +;HDC_UserSize @ 149 +;HDC_UserUnmarshal @ 150 +;HENHMETAFILE_UserFree @ 151 +;HENHMETAFILE_UserMarshal @ 152 +;HENHMETAFILE_UserSize @ 153 +;HENHMETAFILE_UserUnmarshal @ 154 +;HGLOBAL_UserFree @ 155 +;HGLOBAL_UserMarshal @ 156 +;HGLOBAL_UserSize @ 157 +;HGLOBAL_UserUnmarshal @ 158 +;HICON_UserFree @ 159 +;HICON_UserMarshal @ 160 +;HICON_UserSize @ 161 +;HICON_UserUnmarshal @ 162 +;HMENU_UserFree @ 163 +;HMENU_UserMarshal @ 164 +;HMENU_UserSize @ 165 +;HMENU_UserUnmarshal @ 166 +;HMETAFILEPICT_UserFree @ 167 +;HMETAFILEPICT_UserMarshal @ 168 +;HMETAFILEPICT_UserSize @ 169 +;HMETAFILEPICT_UserUnmarshal @ 170 +;HMETAFILE_UserFree @ 171 +;HMETAFILE_UserMarshal @ 172 +;HMETAFILE_UserSize @ 173 +;HMETAFILE_UserUnmarshal @ 174 +;HPALETTE_UserFree @ 175 +;HPALETTE_UserMarshal @ 176 +;HPALETTE_UserSize @ 177 +;HPALETTE_UserUnmarshal @ 178 +;HWND_UserFree @ 179 +;HWND_UserMarshal @ 180 +;HWND_UserSize @ 181 +;HWND_UserUnmarshal @ 182 +;HkOleRegisterObject @ 183 +;IIDFromString @ 184 +;IsAccelerator @ 185 +IsEqualGUID@8 @ 186 +;IsValidIid @ 187 +IsValidInterface@4 @ 188 +;IsValidPtrIn @ 189 +;IsValidPtrOut @ 190 +MkParseDisplayName@16 @ 191 +MonikerCommonPrefixWith@12 @ 192 +;MonikerRelativePathTo @ 193 +;OleBuildVersion @ 194 +OleConvertIStorageToOLESTREAM@8 @ 195 +;OleConvertIStorageToOLESTREAMEx @ 196 +OleConvertOLESTREAMToIStorage@12 @ 197 +;OleConvertOLESTREAMToIStorageEx @ 198 +;OleCreate @ 199 +;OleCreateDefaultHandler @ 200 +;OleCreateEmbeddingHelper @ 201 +;OleCreateEx @ 202 +;OleCreateFromData @ 203 +;OleCreateFromDataEx @ 204 +;OleCreateFromFile @ 205 +;OleCreateFromFileEx @ 206 +;OleCreateLink @ 207 +;OleCreateLinkEx @ 208 +;OleCreateLinkFromData @ 209 +;OleCreateLinkFromDataEx @ 210 +;OleCreateLinkToFile @211 +;OleCreateLinkToFileEx @ 212 +;OleCreateMenuDescriptor @ 213 +;OleCreateStaticFromData @ 214 +;OleDestroyMenuDescriptor @215 +;OleDoAutoConvert @ 216 +;OleDraw @ 217 +;OleDuplicateData @ 218 +;OleFlushClipboard @ 219 +OleGetAutoConvert@8 @ 220 +;OleGetClipboard @ 221 +;OleGetIconOfClass @ 222 +;OleGetIconOfFile @ 223 +;OleInitialize @ 224 +;OleInitializeWOW @ 225 +;OleIsCurrentClipboard @ 226 +;OleIsRunning @ 227 +;OleLoad @ 228 +OleLoadFromStream@12 @ 229 +;OleLockRunning @ 230 +;OleMetafilePictFromIconAndLabel @ 231 +;OleNoteObjectVisible @ 232 +;OleQueryCreateFromData @ 233 +;OleQueryLinkFromData @ 234 +;OleRegEnumFormatEtc @ 235 +;OleRegEnumVerbs @ 236 +;OleRegGetMiscStatus @ 237 +;OleRegGetUserType @ 238 +OleRun@4 @ 239 +;OleSave @ 240 +OleSaveToStream@8 @ 241 +OleSetAutoConvert@8 @ 242 +;OleSetClipboard @ 243 +;OleSetContainedObject @ 244 +;OleSetMenuDescriptor @ 245 +;OleTranslateAccelerator @ 246 +;OleUninitialize @ 247 +;OpenOrCreateStream @ 248 +ProgIDFromCLSID@8 @ 249 +;PropStgNameToFmtId @ 250 +;PropSysAllocString @ 251 +;PropSysFreeString @ 252 +;PropVariantChangeType @ 1 +;PropVariantClear @ 253 +;PropVariantCopy @ 254 +ReadClassStg@8 @ 255 +ReadClassStm@8 @ 256 +;ReadFmtUserTypeStg @ 257 +;ReadOleStg @ 258 +;ReadStringStream @ 259 +;RegisterDragDrop @ 260 +;ReleaseStgMedium @ 261 +;RevokeDragDrop @ 262 +;SNB_UserFree @ 263 +;SNB_UserMarshal @ 264 +;SNB_UserSize @ 265 +;SNB_UserUnmarshal @ 266 +;STGMEDIUM_UserFree @ 267 +;STGMEDIUM_UserMarshal @ 268 +;STGMEDIUM_UserSize @ 269 +;STGMEDIUM_UserUnmarshal @ 270 +;SetConvertStg @ 271 +;SetDocumentBitStg @ 272 +;SetErrorInfo @ 273 +;StgConvertPropertyToVariant @ 2 +;StgConvertVariantToProperty @ 3 +StgCreateDocfile@16 @ 274 +StgCreateDocfileOnILockBytes@16 @ 275 +;StgCreatePropSetStg @ 276 +;StgCreatePropStg @ 277 +;StgCreateStorageEx @ 278 +;StgGetIFillLockBytesOnFile @ 279 +;StgGetIFillLockBytesOnILockBytes @ 280 +StgIsStorageFile@4 @ 281 +StgIsStorageILockBytes@4 @ 282 +;StgOpenAsyncDocfileOnIFillLockBytes @ 283 +;StgOpenPropStg @ 284 +StgOpenStorage@24 @ 285 +;StgOpenStorageEx @ 286 +;StgOpenStorageOnHandle @ 287 +StgOpenStorageOnILockBytes@24 @ 288 +;StgPropertyLengthAsVariant @ 4 +StgSetTimes@16 @ 289 +StringFromCLSID@8 @ 290 +StringFromGUID2@12 @ 291 +;StringFromIID @ 292 +;UpdateDCOMSettings @ 293 +;UtConvertDvtd16toDvtd32 @ 294 +;UtConvertDvtd32toDvtd16 @ 295 +;UtGetDvtd16Info @ 296 +;UtGetDvtd32Info @ 297 +;WdtpInterfacePointer_UserFree @ 5 +;WdtpInterfacePointer_UserMarshal @ 6 +;WdtpInterfacePointer_UserSize @ 7 +;WdtpInterfacePointer_UserUnmarshal @ 8 +WriteClassStg@8 @ 298 +WriteClassStm@8 @ 299 +;WriteFmtUserTypeStg @ 300 +;WriteOleStg @ 301 +;WriteStringStream @ 302 + +; EOF diff --git a/lib/ole32/ole32.rc b/lib/ole32/ole32.rc new file mode 100644 index 0000000..aed7dca --- /dev/null +++ b/lib/ole32/ole32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "OLE for ReactOS\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ole32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ole32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/ole32/rpcrt4_main.c b/lib/ole32/rpcrt4_main.c new file mode 100644 index 0000000..f826c38 --- /dev/null +++ b/lib/ole32/rpcrt4_main.c @@ -0,0 +1,306 @@ +/* + * RPCRT4 + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/*********************************************************************** + * RPCRT4_LibMain + * + * PARAMS + * hinstDLL [I] handle to the DLL's instance + * fdwReason [I] + * lpvReserved [I] reserved, must be NULL + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ + +BOOL WINAPI +RPCRT4_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + + return TRUE; +} + +/************************************************************************* + * UuidCreate [RPCRT4] + * + * Creates a 128bit UUID. + * Implemented according the DCE specification for UUID generation. + * Code is based upon uuid library in e2fsprogs by Theodore Ts'o. + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * RETURNS + * + * S_OK if successful. + */ +RPC_STATUS WINAPI UuidCreate(UUID *Uuid) +{ +#if 1 + UNIMPLEMENTED; + return S_OK; +#else + static char has_init = 0; + unsigned char a[6]; + static int adjustment = 0; + static struct timeval last = {0, 0}; + static UINT16 clock_seq; + struct timeval tv; + unsigned long long clock_reg; + UINT clock_high, clock_low; + UINT16 temp_clock_seq, temp_clock_mid, temp_clock_hi_and_version; +#ifdef HAVE_NET_IF_H + int sd; + struct ifreq ifr, *ifrp; + struct ifconf ifc; + char buf[1024]; + int n, i; +#endif + + /* Have we already tried to get the MAC address? */ + if (!has_init) { +#ifdef HAVE_NET_IF_H + /* BSD 4.4 defines the size of an ifreq to be + * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len + * However, under earlier systems, sa_len isn't present, so + * the size is just sizeof(struct ifreq) + */ +#ifdef HAVE_SA_LEN +# ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +# endif +# define ifreq_size(i) max(sizeof(struct ifreq),\ +sizeof((i).ifr_name)+(i).ifr_addr.sa_len) +# else +# define ifreq_size(i) sizeof(struct ifreq) +# endif /* HAVE_SA_LEN */ + + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + /* if we can't open a socket, just use random numbers */ + /* set the multicast bit to prevent conflicts with real cards */ + a[0] = (rand() & 0xff) | 0x80; + a[1] = rand() & 0xff; + a[2] = rand() & 0xff; + a[3] = rand() & 0xff; + a[4] = rand() & 0xff; + a[5] = rand() & 0xff; + } else { + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + /* get the ifconf interface */ + if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { + close(sd); + /* no ifconf, so just use random numbers */ + /* set the multicast bit to prevent conflicts with real cards */ + a[0] = (rand() & 0xff) | 0x80; + a[1] = rand() & 0xff; + a[2] = rand() & 0xff; + a[3] = rand() & 0xff; + a[4] = rand() & 0xff; + a[5] = rand() & 0xff; + } else { + /* loop through the interfaces, looking for a valid one */ + n = ifc.ifc_len; + for (i = 0; i < n; i+= ifreq_size(*ifr) ) { + ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); + /* try to get the address for this interface */ +# ifdef SIOCGIFHWADDR + if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) + continue; + memcpy(a, (unsigned char *)&ifr.ifr_hwaddr.sa_data, 6); +# else +# ifdef SIOCGENADDR + if (ioctl(sd, SIOCGENADDR, &ifr) < 0) + continue; + memcpy(a, (unsigned char *) ifr.ifr_enaddr, 6); +# else + /* XXX we don't have a way of getting the hardware address */ + close(sd); + a[0] = 0; + break; +# endif /* SIOCGENADDR */ +# endif /* SIOCGIFHWADDR */ + /* make sure it's not blank */ + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) + continue; + + goto valid_address; + } + /* if we didn't find a valid address, make a random one */ + /* once again, set multicast bit to avoid conflicts */ + a[0] = (rand() & 0xff) | 0x80; + a[1] = rand() & 0xff; + a[2] = rand() & 0xff; + a[3] = rand() & 0xff; + a[4] = rand() & 0xff; + a[5] = rand() & 0xff; + + valid_address: + close(sd); + } + } +#else + /* no networking info, so generate a random address */ + a[0] = (rand() & 0xff) | 0x80; + a[1] = rand() & 0xff; + a[2] = rand() & 0xff; + a[3] = rand() & 0xff; + a[4] = rand() & 0xff; + a[5] = rand() & 0xff; +#endif /* HAVE_NET_IF_H */ + has_init = 1; + } + + /* generate time element of GUID */ + + /* Assume that the gettimeofday() has microsecond granularity */ +#define MAX_ADJUSTMENT 10 + + try_again: + gettimeofday(&tv, 0); + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { + clock_seq = ((rand() & 0xff) << 8) + (rand() & 0xff); + clock_seq &= 0x1FFF; + last = tv; + last.tv_sec--; + } + if ((tv.tv_sec < last.tv_sec) || + ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec < last.tv_usec))) { + clock_seq = (clock_seq+1) & 0x1FFF; + adjustment = 0; + } else if ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec == last.tv_usec)) { + if (adjustment >= MAX_ADJUSTMENT) + goto try_again; + adjustment++; + } else + adjustment = 0; + + clock_reg = tv.tv_usec*10 + adjustment; + clock_reg += ((unsigned long long) tv.tv_sec)*10000000; + clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; + + clock_high = clock_reg >> 32; + clock_low = clock_reg; + temp_clock_seq = clock_seq | 0x8000; + temp_clock_mid = (UINT16)clock_high; + temp_clock_hi_and_version = (clock_high >> 16) | 0x1000; + + /* pack the information into the GUID structure */ + + ((unsigned char*)&Uuid->Data1)[3] = (unsigned char)clock_low; + clock_low >>= 8; + ((unsigned char*)&Uuid->Data1)[2] = (unsigned char)clock_low; + clock_low >>= 8; + ((unsigned char*)&Uuid->Data1)[1] = (unsigned char)clock_low; + clock_low >>= 8; + ((unsigned char*)&Uuid->Data1)[0] = (unsigned char)clock_low; + + ((unsigned char*)&Uuid->Data2)[1] = (unsigned char)temp_clock_mid; + temp_clock_mid >>= 8; + ((unsigned char*)&Uuid->Data2)[0] = (unsigned char)temp_clock_mid; + + ((unsigned char*)&Uuid->Data3)[1] = (unsigned char)temp_clock_hi_and_version; + temp_clock_hi_and_version >>= 8; + ((unsigned char*)&Uuid->Data3)[0] = (unsigned char)temp_clock_hi_and_version; + + ((unsigned char*)Uuid->Data4)[1] = (unsigned char)temp_clock_seq; + temp_clock_seq >>= 8; + ((unsigned char*)Uuid->Data4)[0] = (unsigned char)temp_clock_seq; + + ((unsigned char*)Uuid->Data4)[2] = a[0]; + ((unsigned char*)Uuid->Data4)[3] = a[1]; + ((unsigned char*)Uuid->Data4)[4] = a[2]; + ((unsigned char*)Uuid->Data4)[5] = a[3]; + ((unsigned char*)Uuid->Data4)[6] = a[4]; + ((unsigned char*)Uuid->Data4)[7] = a[5]; + + Print(MAX_TRACE, ("%s\n", PRINT_GUID(Uuid))); + + return S_OK; +#endif +} + +/************************************************************************* + * RpcStringFreeA [RPCRT4.436] + * + * Frees a character string allocated by the RPC run-time library. + * + * RETURNS + * + * S_OK if successful. + */ +RPC_STATUS WINAPI RpcStringFreeA(unsigned char** String) +{ + HeapFree( GetProcessHeap(), 0, *String); + + return S_OK; +} + +/************************************************************************* + * UuidToStringA [RPCRT4.450] + * + * Converts a UUID to a string. + * + * UUID format is 8 hex digits, followed by a hyphen then three groups of + * 4 hex digits each followed by a hyphen and then 12 hex digits + * + * RETURNS + * + * S_OK if successful. + * S_OUT_OF_MEMORY if unsucessful. + */ +RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, unsigned char** StringUuid) +{ + *StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37); + + + /* FIXME: this should be RPC_S_OUT_OF_MEMORY */ + if(!(*StringUuid)) + return ERROR_OUTOFMEMORY; + + sprintf(*StringUuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + Uuid->Data1, Uuid->Data2, Uuid->Data3, + Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], + Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], + Uuid->Data4[6], Uuid->Data4[7] ); + + return S_OK; /*FIXME: this should be RPC_S_OK */ +} + +/*********************************************************************** + * NdrDllRegisterProxy (RPCRT4.@) + */ +HRESULT WINAPI NdrDllRegisterProxy( + HMODULE hDll, /* [in] */ + void **pProxyFileList, /* [???] FIXME: const ProxyFileInfo ** */ + const CLSID *pclsid /* [in] */ +) { + Print(MIN_TRACE, ("(%x,%p,%s), stub!\n",hDll,pProxyFileList,PRINT_GUID(pclsid))); + return S_OK; +} diff --git a/lib/ole32/stg_bigblockfile.c b/lib/ole32/stg_bigblockfile.c new file mode 100644 index 0000000..68dc3b9 --- /dev/null +++ b/lib/ole32/stg_bigblockfile.c @@ -0,0 +1,837 @@ +/****************************************************************************** + * + * BigBlockFile + * + * This is the implementation of a file that consists of blocks of + * a predetermined size. + * This class is used in the Compound File implementation of the + * IStorage and IStream interfaces. It provides the functionality + * to read and write any blocks in the file as well as setting and + * obtaining the size of the file. + * The blocks are indexed sequentially from the start of the file + * starting with -1. + * + * TODO: + * - Support for a transacted mode + * + * Copyright 1999 Thuy Nguyen + * + */ + +#include +#include +#include +#include + +#include +#include +#include "storage32.h" + +#include + +/*********************************************************** + * Data structures used internally by the BigBlockFile + * class. + */ + +/* We map in PAGE_SIZE-sized chunks. Must be a multiple of 4096. */ +#define PAGE_SIZE 131072 + +#define BLOCKS_PER_PAGE (PAGE_SIZE / BIG_BLOCK_SIZE) + +/* We keep a list of recently-discarded pages. This controls the + * size of that list. */ +#define MAX_VICTIM_PAGES 16 + +/* This structure provides one bit for each block in a page. + * Use BIGBLOCKFILE_{Test,Set,Clear}Bit to manipulate it. */ +typedef struct +{ + unsigned int bits[BLOCKS_PER_PAGE / (CHAR_BIT * sizeof(unsigned int))]; +} BlockBits; + +/*** + * This structure identifies the paged that are mapped + * from the file and their position in memory. It is + * also used to hold a reference count to those pages. + * + * page_index identifies which PAGE_SIZE chunk from the + * file this mapping represents. (The mappings are always + * PAGE_SIZE-aligned.) + */ +struct MappedPage +{ + MappedPage *next; + MappedPage *prev; + + DWORD page_index; + LPVOID lpBytes; + LONG refcnt; + + BlockBits readable_blocks; + BlockBits writable_blocks; +}; + +/*********************************************************** + * Prototypes for private methods + */ +static void* BIGBLOCKFILE_GetMappedView(LPBIGBLOCKFILE This, + DWORD page_index); +static void BIGBLOCKFILE_ReleaseMappedPage(LPBIGBLOCKFILE This, + MappedPage *page); +static void BIGBLOCKFILE_FreeAllMappedPages(LPBIGBLOCKFILE This); +static void BIGBLOCKFILE_UnmapAllMappedPages(LPBIGBLOCKFILE This); +static void BIGBLOCKFILE_RemapAllMappedPages(LPBIGBLOCKFILE This); +static void* BIGBLOCKFILE_GetBigBlockPointer(LPBIGBLOCKFILE This, + ULONG index, + DWORD desired_access); +static MappedPage* BIGBLOCKFILE_GetPageFromPointer(LPBIGBLOCKFILE This, + void* pBlock); +static MappedPage* BIGBLOCKFILE_CreatePage(LPBIGBLOCKFILE This, + ULONG page_index); +static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags); +static BOOL BIGBLOCKFILE_FileInit(LPBIGBLOCKFILE This, HANDLE hFile); +static BOOL BIGBLOCKFILE_MemInit(LPBIGBLOCKFILE This, ILockBytes* plkbyt); + +/* Note that this evaluates a and b multiple times, so don't + * pass expressions with side effects. */ +#define ROUNDUP(a, b) ((((a) + (b) - 1)/(b))*(b)) + +/*********************************************************** + * Blockbits functions. + */ +static inline BOOL BIGBLOCKFILE_TestBit(const BlockBits *bb, + unsigned int index) +{ + unsigned int array_index = index / (CHAR_BIT * sizeof(unsigned int)); + unsigned int bit_index = index % (CHAR_BIT * sizeof(unsigned int)); + + return bb->bits[array_index] & (1 << bit_index); +} + +static inline void BIGBLOCKFILE_SetBit(BlockBits *bb, unsigned int index) +{ + unsigned int array_index = index / (CHAR_BIT * sizeof(unsigned int)); + unsigned int bit_index = index % (CHAR_BIT * sizeof(unsigned int)); + + bb->bits[array_index] |= (1 << bit_index); +} + +static inline void BIGBLOCKFILE_ClearBit(BlockBits *bb, unsigned int index) +{ + unsigned int array_index = index / (CHAR_BIT * sizeof(unsigned int)); + unsigned int bit_index = index % (CHAR_BIT * sizeof(unsigned int)); + + bb->bits[array_index] &= ~(1 << bit_index); +} + +static inline void BIGBLOCKFILE_Zero(BlockBits *bb) +{ + memset(bb->bits, 0, sizeof(bb->bits)); +} + +/****************************************************************************** + * BIGBLOCKFILE_Construct + * + * Construct a big block file. Create the file mapping object. + * Create the read only mapped pages list, the writable mapped page list + * and the blocks in use list. + */ +BigBlockFile * BIGBLOCKFILE_Construct( + HANDLE hFile, + ILockBytes* pLkByt, + DWORD openFlags, + ULONG blocksize, + BOOL fileBased) +{ + LPBIGBLOCKFILE This; + + This = (LPBIGBLOCKFILE)HeapAlloc(GetProcessHeap(), 0, sizeof(BigBlockFile)); + + if (This == NULL) + return NULL; + + This->fileBased = fileBased; + + This->flProtect = BIGBLOCKFILE_GetProtectMode(openFlags); + + This->blocksize = blocksize; + + This->maplist = NULL; + This->victimhead = NULL; + This->victimtail = NULL; + This->num_victim_pages = 0; + + if (This->fileBased) + { + if (!BIGBLOCKFILE_FileInit(This, hFile)) + { + HeapFree(GetProcessHeap(), 0, This); + return NULL; + } + } + else + { + if (!BIGBLOCKFILE_MemInit(This, pLkByt)) + { + HeapFree(GetProcessHeap(), 0, This); + return NULL; + } + } + + return This; +} + +/****************************************************************************** + * BIGBLOCKFILE_FileInit + * + * Initialize a big block object supported by a file. + */ +static BOOL BIGBLOCKFILE_FileInit(LPBIGBLOCKFILE This, HANDLE hFile) +{ + This->pLkbyt = NULL; + This->hbytearray = 0; + This->pbytearray = NULL; + + This->hfile = hFile; + + if (This->hfile == INVALID_HANDLE_VALUE) + return FALSE; + + /* create the file mapping object + */ + This->hfilemap = CreateFileMappingA(This->hfile, + NULL, + This->flProtect, + 0, 0, + NULL); + + if (!This->hfilemap) + { + CloseHandle(This->hfile); + return FALSE; + } + + This->filesize.u.LowPart = GetFileSize(This->hfile, + &This->filesize.u.HighPart); + + This->maplist = NULL; + + Print(MAX_TRACE, ("file len %lu\n", This->filesize.u.LowPart)); + + return TRUE; +} + +/****************************************************************************** + * BIGBLOCKFILE_MemInit + * + * Initialize a big block object supported by an ILockBytes on HGLOABL. + */ +static BOOL BIGBLOCKFILE_MemInit(LPBIGBLOCKFILE This, ILockBytes* plkbyt) +{ + This->hfile = 0; + This->hfilemap = 0; + + /* + * Retrieve the handle to the byte array from the LockByte object. + */ + if (GetHGlobalFromILockBytes(plkbyt, &(This->hbytearray)) != S_OK) + { + Print(MIN_TRACE, ("May not be an ILockBytes on HGLOBAL\n")); + return FALSE; + } + + This->pLkbyt = plkbyt; + + /* + * Increment the reference count of the ILockByte object since + * we're keeping a reference to it. + */ + ILockBytes_AddRef(This->pLkbyt); + + This->filesize.u.LowPart = GlobalSize(This->hbytearray); + This->filesize.u.HighPart = 0; + + This->pbytearray = GlobalLock(This->hbytearray); + + Print(MAX_TRACE, ("mem on %p len %lu\n", This->pbytearray, This->filesize.u.LowPart)); + + return TRUE; +} + +/****************************************************************************** + * BIGBLOCKFILE_Destructor + * + * Destructor. Clean up, free memory. + */ +void BIGBLOCKFILE_Destructor( + LPBIGBLOCKFILE This) +{ + BIGBLOCKFILE_FreeAllMappedPages(This); + + if (This->fileBased) + { + CloseHandle(This->hfilemap); + CloseHandle(This->hfile); + } + else + { + GlobalUnlock(This->hbytearray); + ILockBytes_Release(This->pLkbyt); + } + + /* destroy this + */ + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** + * BIGBLOCKFILE_GetROBigBlock + * + * Returns the specified block in read only mode. + * Will return NULL if the block doesn't exists. + */ +void* BIGBLOCKFILE_GetROBigBlock( + LPBIGBLOCKFILE This, + ULONG index) +{ + /* + * block index starts at -1 + * translate to zero based index + */ + if (index == 0xffffffff) + index = 0; + else + index++; + + /* + * validate the block index + * + */ + if (This->blocksize * (index + 1) + > ROUNDUP(This->filesize.u.LowPart, This->blocksize)) + { + Print(MAX_TRACE, ("out of range %lu vs %lu\n", This->blocksize * (index + 1), + This->filesize.u.LowPart)); + return NULL; + } + + return BIGBLOCKFILE_GetBigBlockPointer(This, index, FILE_MAP_READ); +} + +/****************************************************************************** + * BIGBLOCKFILE_GetBigBlock + * + * Returns the specified block. + * Will grow the file if necessary. + */ +void* BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index) +{ + /* + * block index starts at -1 + * translate to zero based index + */ + if (index == 0xffffffff) + index = 0; + else + index++; + + /* + * make sure that the block physically exists + */ + if ((This->blocksize * (index + 1)) > This->filesize.u.LowPart) + { + ULARGE_INTEGER newSize; + + newSize.u.HighPart = 0; + newSize.u.LowPart = This->blocksize * (index + 1); + + BIGBLOCKFILE_SetSize(This, newSize); + } + + return BIGBLOCKFILE_GetBigBlockPointer(This, index, FILE_MAP_WRITE); +} + +/****************************************************************************** + * BIGBLOCKFILE_ReleaseBigBlock + * + * Releases the specified block. + */ +void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock) +{ + MappedPage *page; + + if (pBlock == NULL) + return; + + page = BIGBLOCKFILE_GetPageFromPointer(This, pBlock); + + if (page == NULL) + return; + + BIGBLOCKFILE_ReleaseMappedPage(This, page); +} + +/****************************************************************************** + * BIGBLOCKFILE_SetSize + * + * Sets the size of the file. + * + */ +void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize) +{ + if (This->filesize.u.LowPart == newSize.u.LowPart) + return; + + Print(MAX_TRACE, ("from %lu to %lu\n", This->filesize.u.LowPart, newSize.u.LowPart)); + /* + * unmap all views, must be done before call to SetEndFile + */ + BIGBLOCKFILE_UnmapAllMappedPages(This); + + if (This->fileBased) + { + char buf[10]; + + /* + * close file-mapping object, must be done before call to SetEndFile + */ + CloseHandle(This->hfilemap); + This->hfilemap = 0; + + /* + * BEGIN HACK + * This fixes a bug when saving through smbfs. + * smbmount a Windows shared directory, save a structured storage file + * to that dir: crash. + * + * The problem is that the SetFilePointer-SetEndOfFile combo below + * doesn't always succeed. The file is not grown. It seems like the + * operation is cached. By doing the WriteFile, the file is actually + * grown on disk. + * This hack is only needed when saving to smbfs. + */ + memset(buf, '0', 10); + SetFilePointer(This->hfile, newSize.u.LowPart, NULL, FILE_BEGIN); + WriteFile(This->hfile, buf, 10, NULL, NULL); + /* + * END HACK + */ + + /* + * set the new end of file + */ + SetFilePointer(This->hfile, newSize.u.LowPart, NULL, FILE_BEGIN); + SetEndOfFile(This->hfile); + + /* + * re-create the file mapping object + */ + This->hfilemap = CreateFileMappingA(This->hfile, + NULL, + This->flProtect, + 0, 0, + NULL); + } + else + { + GlobalUnlock(This->hbytearray); + + /* + * Resize the byte array object. + */ + ILockBytes_SetSize(This->pLkbyt, newSize); + + /* + * Re-acquire the handle, it may have changed. + */ + GetHGlobalFromILockBytes(This->pLkbyt, &This->hbytearray); + This->pbytearray = GlobalLock(This->hbytearray); + } + + This->filesize.u.LowPart = newSize.u.LowPart; + This->filesize.u.HighPart = newSize.u.HighPart; + + BIGBLOCKFILE_RemapAllMappedPages(This); +} + +/****************************************************************************** + * BIGBLOCKFILE_GetSize + * + * Returns the size of the file. + * + */ +ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This) +{ + return This->filesize; +} + +/****************************************************************************** + * BIGBLOCKFILE_AccessCheck [PRIVATE] + * + * block_index is the index within the page. + */ +static BOOL BIGBLOCKFILE_AccessCheck(MappedPage *page, ULONG block_index, + DWORD desired_access) +{ + assert(block_index < BLOCKS_PER_PAGE); + + if (desired_access == FILE_MAP_READ) + { + if (BIGBLOCKFILE_TestBit(&page->writable_blocks, block_index)) + return FALSE; + + BIGBLOCKFILE_SetBit(&page->readable_blocks, block_index); + } + else + { + assert(desired_access == FILE_MAP_WRITE); + + if (BIGBLOCKFILE_TestBit(&page->readable_blocks, block_index)) + return FALSE; + + BIGBLOCKFILE_SetBit(&page->writable_blocks, block_index); + } + + return TRUE; +} + +/****************************************************************************** + * BIGBLOCKFILE_GetBigBlockPointer [PRIVATE] + * + * Returns a pointer to the specified block. + */ +static void* BIGBLOCKFILE_GetBigBlockPointer( + LPBIGBLOCKFILE This, + ULONG block_index, + DWORD desired_access) +{ + DWORD page_index = block_index / BLOCKS_PER_PAGE; + DWORD block_on_page = block_index % BLOCKS_PER_PAGE; + + MappedPage *page = BIGBLOCKFILE_GetMappedView(This, page_index); + if (!page || !page->lpBytes) return NULL; + + if (!BIGBLOCKFILE_AccessCheck(page, block_on_page, desired_access)) + { + BIGBLOCKFILE_ReleaseMappedPage(This, page); + return NULL; + } + + return (LPBYTE)page->lpBytes + (block_on_page * This->blocksize); +} + +/****************************************************************************** + * BIGBLOCKFILE_GetMappedPageFromPointer [PRIVATE] + * + * pBlock is a pointer to a block on a page. + * The page has to be on the in-use list. (As oppsed to the victim list.) + * + * Does not increment the usage count. + */ +static MappedPage *BIGBLOCKFILE_GetPageFromPointer(LPBIGBLOCKFILE This, + void *pBlock) +{ + MappedPage *page; + + for (page = This->maplist; page != NULL; page = page->next) + { + if ((LPBYTE)pBlock >= (LPBYTE)page->lpBytes + && (LPBYTE)pBlock <= (LPBYTE)page->lpBytes + PAGE_SIZE) + break; + + } + + return page; +} + +/****************************************************************************** + * BIGBLOCKFILE_FindPageInList [PRIVATE] + * + */ +static MappedPage *BIGBLOCKFILE_FindPageInList(MappedPage *head, + ULONG page_index) +{ + for (; head != NULL; head = head->next) + { + if (head->page_index == page_index) + { + InterlockedIncrement(&head->refcnt); + break; + } + } + + return head; + +} + +static void BIGBLOCKFILE_UnlinkPage(MappedPage *page) +{ + if (page->next) page->next->prev = page->prev; + if (page->prev) page->prev->next = page->next; +} + +static void BIGBLOCKFILE_LinkHeadPage(MappedPage **head, MappedPage *page) +{ + if (*head) (*head)->prev = page; + page->next = *head; + page->prev = NULL; + *head = page; +} + +/****************************************************************************** + * BIGBLOCKFILE_GetMappedView [PRIVATE] + * + * Gets the page requested if it is already mapped. + * If it's not already mapped, this method will map it + */ +static void * BIGBLOCKFILE_GetMappedView( + LPBIGBLOCKFILE This, + DWORD page_index) +{ + MappedPage *page; + + page = BIGBLOCKFILE_FindPageInList(This->maplist, page_index); + if (!page) + { + page = BIGBLOCKFILE_FindPageInList(This->victimhead, page_index); + if (page) + { + This->num_victim_pages--; + + BIGBLOCKFILE_Zero(&page->readable_blocks); + BIGBLOCKFILE_Zero(&page->writable_blocks); + } + } + + if (page) + { + /* If the page is not already at the head of the list, move + * it there. (Also moves pages from victim to main list.) */ + if (This->maplist != page) + { + if (This->victimhead == page) This->victimhead = page->next; + if (This->victimtail == page) This->victimtail = page->prev; + + BIGBLOCKFILE_UnlinkPage(page); + + BIGBLOCKFILE_LinkHeadPage(&This->maplist, page); + } + + return page; + } + + page = BIGBLOCKFILE_CreatePage(This, page_index); + if (!page) return NULL; + + BIGBLOCKFILE_LinkHeadPage(&This->maplist, page); + + return page; +} + +static BOOL BIGBLOCKFILE_MapPage(LPBIGBLOCKFILE This, MappedPage *page) +{ + DWORD lowoffset = PAGE_SIZE * page->page_index; + + if (This->fileBased) + { + DWORD numBytesToMap; + DWORD desired_access; + + if (lowoffset + PAGE_SIZE > This->filesize.u.LowPart) + numBytesToMap = This->filesize.u.LowPart - lowoffset; + else + numBytesToMap = PAGE_SIZE; + + if (This->flProtect == PAGE_READONLY) + desired_access = FILE_MAP_READ; + else + desired_access = FILE_MAP_WRITE; + + page->lpBytes = MapViewOfFile(This->hfilemap, desired_access, 0, + lowoffset, numBytesToMap); + } + else + { + page->lpBytes = (LPBYTE)This->pbytearray + lowoffset; + } + + Print(MAX_TRACE, ("mapped page %lu to %p\n", page->page_index, page->lpBytes)); + + return page->lpBytes != NULL; +} + +static MappedPage *BIGBLOCKFILE_CreatePage(LPBIGBLOCKFILE This, + ULONG page_index) +{ + MappedPage *page; + + page = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage)); + if (page == NULL) + return NULL; + + page->page_index = page_index; + page->refcnt = 1; + + page->next = NULL; + page->prev = NULL; + + BIGBLOCKFILE_MapPage(This, page); + + BIGBLOCKFILE_Zero(&page->readable_blocks); + BIGBLOCKFILE_Zero(&page->writable_blocks); + + return page; +} + +static void BIGBLOCKFILE_UnmapPage(LPBIGBLOCKFILE This, MappedPage *page) +{ + Print(MAX_TRACE, ("%ld at %p\n", page->page_index, page->lpBytes)); + if (page->refcnt > 0) + Print(MIN_TRACE, ("unmapping inuse page %p\n", page->lpBytes)); + + if (This->fileBased && page->lpBytes) + UnmapViewOfFile(page->lpBytes); + + page->lpBytes = NULL; +} + +static void BIGBLOCKFILE_DeletePage(LPBIGBLOCKFILE This, MappedPage *page) +{ + BIGBLOCKFILE_UnmapPage(This, page); + + HeapFree(GetProcessHeap(), 0, page); +} + +/****************************************************************************** + * BIGBLOCKFILE_ReleaseMappedPage [PRIVATE] + * + * Decrements the reference count of the mapped page. + */ +static void BIGBLOCKFILE_ReleaseMappedPage( + LPBIGBLOCKFILE This, + MappedPage *page) +{ + assert(This != NULL); + assert(page != NULL); + + /* If the page is no longer refenced, move it to the victim list. + * If the victim list is too long, kick somebody off. */ + if (!InterlockedDecrement(&page->refcnt)) + { + if (This->maplist == page) This->maplist = page->next; + + BIGBLOCKFILE_UnlinkPage(page); + + if (MAX_VICTIM_PAGES > 0) + { + if (This->num_victim_pages >= MAX_VICTIM_PAGES) + { + MappedPage *victim = This->victimtail; + if (victim) + { + This->victimtail = victim->prev; + if (This->victimhead == victim) + This->victimhead = victim->next; + + BIGBLOCKFILE_UnlinkPage(victim); + BIGBLOCKFILE_DeletePage(This, victim); + } + } + else This->num_victim_pages++; + + BIGBLOCKFILE_LinkHeadPage(&This->victimhead, page); + if (This->victimtail == NULL) This->victimtail = page; + } + else + BIGBLOCKFILE_DeletePage(This, page); + } +} + +static void BIGBLOCKFILE_DeleteList(LPBIGBLOCKFILE This, MappedPage *list) +{ + while (list != NULL) + { + MappedPage *next = list->next; + + BIGBLOCKFILE_DeletePage(This, list); + + list = next; + } +} + +/****************************************************************************** + * BIGBLOCKFILE_FreeAllMappedPages [PRIVATE] + * + * Unmap all currently mapped pages. + * Empty mapped pages list. + */ +static void BIGBLOCKFILE_FreeAllMappedPages( + LPBIGBLOCKFILE This) +{ + BIGBLOCKFILE_DeleteList(This, This->maplist); + BIGBLOCKFILE_DeleteList(This, This->victimhead); + + This->maplist = NULL; + This->victimhead = NULL; + This->victimtail = NULL; + This->num_victim_pages = 0; +} + +static void BIGBLOCKFILE_UnmapList(LPBIGBLOCKFILE This, MappedPage *list) +{ + for (; list != NULL; list = list->next) + { + BIGBLOCKFILE_UnmapPage(This, list); + } +} + +static void BIGBLOCKFILE_UnmapAllMappedPages(LPBIGBLOCKFILE This) +{ + BIGBLOCKFILE_UnmapList(This, This->maplist); + BIGBLOCKFILE_UnmapList(This, This->victimhead); +} + +static void BIGBLOCKFILE_RemapList(LPBIGBLOCKFILE This, MappedPage *list) +{ + while (list != NULL) + { + MappedPage *next = list->next; + + if (list->page_index * PAGE_SIZE > This->filesize.u.LowPart) + { + Print(MAX_TRACE, ("discarding %lu\n", list->page_index)); + + /* page is entirely outside of the file, delete it */ + BIGBLOCKFILE_UnlinkPage(list); + BIGBLOCKFILE_DeletePage(This, list); + } + else + { + /* otherwise, remap it */ + BIGBLOCKFILE_MapPage(This, list); + } + + list = next; + } +} + +static void BIGBLOCKFILE_RemapAllMappedPages(LPBIGBLOCKFILE This) +{ + BIGBLOCKFILE_RemapList(This, This->maplist); + BIGBLOCKFILE_RemapList(This, This->victimhead); +} + +/**************************************************************************** + * BIGBLOCKFILE_GetProtectMode + * + * This function will return a protection mode flag for a file-mapping object + * from the open flags of a file. + */ +static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags) +{ + if (openFlags & (STGM_WRITE | STGM_READWRITE)) + return PAGE_READWRITE; + else + return PAGE_READONLY; +} diff --git a/lib/ole32/stg_stream.c b/lib/ole32/stg_stream.c new file mode 100644 index 0000000..fb4b9ab --- /dev/null +++ b/lib/ole32/stg_stream.c @@ -0,0 +1,835 @@ +/* + * Compound Storage (32 bit version) + * Stream implementation + * + * This file contains the implementation of the stream interface + * for streams contained in a compound storage. + * + * Copyright 1999 Francis Beaudet + * Copyright 1999 Thuy Nguyen + */ +#include +#include +#include + +#include +#include +#include +#include "storage32.h" + +#include + + +/* + * Virtual function table for the StgStreamImpl class. + */ +static ICOM_VTABLE(IStream) StgStreamImpl_Vtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + StgStreamImpl_QueryInterface, + StgStreamImpl_AddRef, + StgStreamImpl_Release, + StgStreamImpl_Read, + StgStreamImpl_Write, + StgStreamImpl_Seek, + StgStreamImpl_SetSize, + StgStreamImpl_CopyTo, + StgStreamImpl_Commit, + StgStreamImpl_Revert, + StgStreamImpl_LockRegion, + StgStreamImpl_UnlockRegion, + StgStreamImpl_Stat, + StgStreamImpl_Clone +}; + +/****************************************************************************** +** StgStreamImpl implementation +*/ + +/*** + * This is the constructor for the StgStreamImpl class. + * + * Params: + * parentStorage - Pointer to the storage that contains the stream to open + * ownerProperty - Index of the property that points to this stream. + */ +StgStreamImpl* StgStreamImpl_Construct( + StorageBaseImpl* parentStorage, + DWORD grfMode, + ULONG ownerProperty) +{ + StgStreamImpl* newStream; + + newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(StgStreamImpl)); + + if (newStream!=0) + { + /* + * Set-up the virtual function table and reference count. + */ + ICOM_VTBL(newStream) = &StgStreamImpl_Vtbl; + newStream->ref = 0; + + /* + * We want to nail-down the reference to the storage in case the + * stream out-lives the storage in the client application. + */ + newStream->parentStorage = parentStorage; + IStorage_AddRef((IStorage*)newStream->parentStorage); + + newStream->grfMode = grfMode; + newStream->ownerProperty = ownerProperty; + + /* + * Start the stream at the begining. + */ + newStream->currentPosition.u.HighPart = 0; + newStream->currentPosition.u.LowPart = 0; + + /* + * Initialize the rest of the data. + */ + newStream->streamSize.u.HighPart = 0; + newStream->streamSize.u.LowPart = 0; + newStream->bigBlockChain = 0; + newStream->smallBlockChain = 0; + + /* + * Read the size from the property and determine if the blocks forming + * this stream are large or small. + */ + StgStreamImpl_OpenBlockChain(newStream); + } + + return newStream; +} + +/*** + * This is the destructor of the StgStreamImpl class. + * + * This method will clean-up all the resources used-up by the given StgStreamImpl + * class. The pointer passed-in to this function will be freed and will not + * be valid anymore. + */ +void StgStreamImpl_Destroy(StgStreamImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n", This)); + + /* + * Release the reference we are holding on the parent storage. + */ + IStorage_Release((IStorage*)This->parentStorage); + This->parentStorage = 0; + + /* + * Make sure we clean-up the block chain stream objects that we were using. + */ + if (This->bigBlockChain != 0) + { + BlockChainStream_Destroy(This->bigBlockChain); + This->bigBlockChain = 0; + } + + if (This->smallBlockChain != 0) + { + SmallBlockChainStream_Destroy(This->smallBlockChain); + This->smallBlockChain = 0; + } + + /* + * Finally, free the memory used-up by the class. + */ + HeapFree(GetProcessHeap(), 0, This); +} + +/*** + * This implements the IUnknown method QueryInterface for this + * class + */ +HRESULT WINAPI StgStreamImpl_QueryInterface( + IStream* iface, + REFIID riid, /* [in] */ + void** ppvObject) /* [iid_is][out] */ +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + /* + * Perform a sanity check on the parameters. + */ + if (ppvObject==0) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) + { + *ppvObject = (IStream*)This; + } + else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0) + { + *ppvObject = (IStream*)This; + } + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* + * Query Interface always increases the reference count by one when it is + * successful + */ + StgStreamImpl_AddRef(iface); + + return S_OK;; +} + +/*** + * This implements the IUnknown method AddRef for this + * class + */ +ULONG WINAPI StgStreamImpl_AddRef( + IStream* iface) +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + This->ref++; + + return This->ref; +} + +/*** + * This implements the IUnknown method Release for this + * class + */ +ULONG WINAPI StgStreamImpl_Release( + IStream* iface) +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + ULONG newRef; + + This->ref--; + + newRef = This->ref; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (newRef==0) + { + StgStreamImpl_Destroy(This); + } + + return newRef; +} + +/*** + * This method will open the block chain pointed by the property + * that describes the stream. + * If the stream's size is null, no chain is opened. + */ +void StgStreamImpl_OpenBlockChain( + StgStreamImpl* This) +{ + StgProperty curProperty; + BOOL readSucessful; + + /* + * Make sure no old object is staying behind. + */ + if (This->smallBlockChain != 0) + { + SmallBlockChainStream_Destroy(This->smallBlockChain); + This->smallBlockChain = 0; + } + + if (This->bigBlockChain != 0) + { + BlockChainStream_Destroy(This->bigBlockChain); + This->bigBlockChain = 0; + } + + /* + * Read the information from the property. + */ + readSucessful = StorageImpl_ReadProperty(This->parentStorage->ancestorStorage, + This->ownerProperty, + &curProperty); + + if (readSucessful) + { + This->streamSize = curProperty.size; + + /* + * This code supports only streams that are <32 bits in size. + */ + assert(This->streamSize.u.HighPart == 0); + + if(curProperty.startingBlock == BLOCK_END_OF_CHAIN) + { + assert( (This->streamSize.u.HighPart == 0) && (This->streamSize.u.LowPart == 0) ); + } + else + { + if ( (This->streamSize.u.HighPart == 0) && + (This->streamSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK) ) + { + This->smallBlockChain = SmallBlockChainStream_Construct( + This->parentStorage->ancestorStorage, + This->ownerProperty); + } + else + { + This->bigBlockChain = BlockChainStream_Construct( + This->parentStorage->ancestorStorage, + NULL, + This->ownerProperty); + } + } + } +} + +/*** + * This method is part of the ISequentialStream interface. + * + * If reads a block of information from the stream at the current + * position. It then moves the current position at the end of the + * read block + * + * See the documentation of ISequentialStream for more info. + */ +HRESULT WINAPI StgStreamImpl_Read( + IStream* iface, + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead) /* [out] */ +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + ULONG bytesReadBuffer; + ULONG bytesToReadFromBuffer; + + Print(MAX_TRACE, ("(%p, %p, %ld, %p)\n", + iface, pv, cb, pcbRead)); + + /* + * If the caller is not interested in the nubmer of bytes read, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbRead==0) + pcbRead = &bytesReadBuffer; + + /* + * Using the known size of the stream, calculate the number of bytes + * to read from the block chain + */ + bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb); + + /* + * Depending on the type of chain that was opened when the stream was constructed, + * we delegate the work to the method that read the block chains. + */ + if (This->smallBlockChain!=0) + { + SmallBlockChainStream_ReadAt(This->smallBlockChain, + This->currentPosition, + bytesToReadFromBuffer, + pv, + pcbRead); + + } + else if (This->bigBlockChain!=0) + { + BlockChainStream_ReadAt(This->bigBlockChain, + This->currentPosition, + bytesToReadFromBuffer, + pv, + pcbRead); + } + else + { + /* + * Small and big block chains are both NULL. This case will happen + * when a stream starts with BLOCK_END_OF_CHAIN and has size zero. + */ + + *pcbRead = 0; + return S_OK; + } + + /* + * We should always be able to read the proper amount of data from the + * chain. + */ + assert(bytesToReadFromBuffer == *pcbRead); + + /* + * Advance the pointer for the number of positions read. + */ + This->currentPosition.u.LowPart += *pcbRead; + + /* + * The function returns S_OK if the buffer was filled completely + * it returns S_FALSE if the end of the stream is reached before the + * buffer is filled + */ + if(*pcbRead == cb) + return S_OK; + + return S_FALSE; +} + +/*** + * This method is part of the ISequentialStream interface. + * + * It writes a block of information to the stream at the current + * position. It then moves the current position at the end of the + * written block. If the stream is too small to fit the block, + * the stream is grown to fit. + * + * See the documentation of ISequentialStream for more info. + */ +HRESULT WINAPI StgStreamImpl_Write( + IStream* iface, + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten) /* [out] */ +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + ULARGE_INTEGER newSize; + ULONG bytesWritten = 0; + + Print(MAX_TRACE, ("(%p, %p, %ld, %p)\n", + iface, pv, cb, pcbWritten)); + + /* + * Do we have permission to write to this stream? + */ + if (!(This->grfMode & (STGM_WRITE | STGM_READWRITE))) { + return STG_E_ACCESSDENIED; + } + + /* + * If the caller is not interested in the number of bytes written, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbWritten == 0) + pcbWritten = &bytesWritten; + + /* + * Initialize the out parameter + */ + *pcbWritten = 0; + + if (cb == 0) + { + return S_OK; + } + else + { + newSize.u.HighPart = 0; + newSize.u.LowPart = This->currentPosition.u.LowPart + cb; + } + + /* + * Verify if we need to grow the stream + */ + if (newSize.u.LowPart > This->streamSize.u.LowPart) + { + /* grow stream */ + IStream_SetSize(iface, newSize); + } + + /* + * Depending on the type of chain that was opened when the stream was constructed, + * we delegate the work to the method that readwrites to the block chains. + */ + if (This->smallBlockChain!=0) + { + SmallBlockChainStream_WriteAt(This->smallBlockChain, + This->currentPosition, + cb, + pv, + pcbWritten); + + } + else if (This->bigBlockChain!=0) + { + BlockChainStream_WriteAt(This->bigBlockChain, + This->currentPosition, + cb, + pv, + pcbWritten); + } + else + assert(FALSE); + + /* + * Advance the position pointer for the number of positions written. + */ + This->currentPosition.u.LowPart += *pcbWritten; + + return S_OK; +} + +/*** + * This method is part of the IStream interface. + * + * It will move the current stream pointer according to the parameters + * given. + * + * See the documentation of IStream for more info. + */ +HRESULT WINAPI StgStreamImpl_Seek( + IStream* iface, + LARGE_INTEGER dlibMove, /* [in] */ + DWORD dwOrigin, /* [in] */ + ULARGE_INTEGER* plibNewPosition) /* [out] */ +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + ULARGE_INTEGER newPosition; + LARGE_INTEGER Position; + + Print(MAX_TRACE, ("(%p, %ld, %ld, %p)\n", + iface, dlibMove.u.LowPart, dwOrigin, plibNewPosition)); + + /* + * The caller is allowed to pass in NULL as the new position return value. + * If it happens, we assign it to a dynamic variable to avoid special cases + * in the code below. + */ + if (plibNewPosition == 0) + { + plibNewPosition = &newPosition; + } + + /* + * The file pointer is moved depending on the given "function" + * parameter. + */ + switch (dwOrigin) + { + case STREAM_SEEK_SET: + plibNewPosition->u.HighPart = 0; + plibNewPosition->u.LowPart = 0; + break; + case STREAM_SEEK_CUR: + *plibNewPosition = This->currentPosition; + break; + case STREAM_SEEK_END: + *plibNewPosition = This->streamSize; + break; + default: + return STG_E_INVALIDFUNCTION; + } + + Position = RtlLargeIntegerAdd( *((PLARGE_INTEGER)plibNewPosition), dlibMove ); + + plibNewPosition->QuadPart = Position.QuadPart; + + /* + * tell the caller what we calculated + */ + This->currentPosition = *plibNewPosition; + + return S_OK; +} + +/*** + * This method is part of the IStream interface. + * + * It will change the size of a stream. + * + * TODO: Switch from small blocks to big blocks and vice versa. + * + * See the documentation of IStream for more info. + */ +HRESULT WINAPI StgStreamImpl_SetSize( + IStream* iface, + ULARGE_INTEGER libNewSize) /* [in] */ +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + StgProperty curProperty; + BOOL Success; + + Print(MAX_TRACE, ("(%p, %ld)\n", iface, libNewSize.u.LowPart)); + + /* + * As documented. + */ + if (libNewSize.u.HighPart != 0) + return STG_E_INVALIDFUNCTION; + + /* + * Do we have permission? + */ + if (!(This->grfMode & (STGM_WRITE | STGM_READWRITE))) + return STG_E_ACCESSDENIED; + + if (This->streamSize.u.LowPart == libNewSize.u.LowPart) + return S_OK; + + /* + * This will happen if we're creating a stream + */ + if ((This->smallBlockChain == 0) && (This->bigBlockChain == 0)) + { + if (libNewSize.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK) + { + This->smallBlockChain = SmallBlockChainStream_Construct( + This->parentStorage->ancestorStorage, + This->ownerProperty); + } + else + { + This->bigBlockChain = BlockChainStream_Construct( + This->parentStorage->ancestorStorage, + NULL, + This->ownerProperty); + } + } + + /* + * Read this stream's property to see if it's small blocks or big blocks + */ + Success = StorageImpl_ReadProperty(This->parentStorage->ancestorStorage, + This->ownerProperty, + &curProperty); + /* + * Determine if we have to switch from small to big blocks or vice versa + */ + if ( (This->smallBlockChain!=0) && + (curProperty.size.u.LowPart < LIMIT_TO_USE_SMALL_BLOCK) ) + { + if (libNewSize.u.LowPart >= LIMIT_TO_USE_SMALL_BLOCK) + { + /* + * Transform the small block chain into a big block chain + */ + This->bigBlockChain = Storage32Impl_SmallBlocksToBigBlocks( + This->parentStorage->ancestorStorage, + &This->smallBlockChain); + } + } + + if (This->smallBlockChain!=0) + { + Success = SmallBlockChainStream_SetSize(This->smallBlockChain, libNewSize); + } + else + { + Success = BlockChainStream_SetSize(This->bigBlockChain, libNewSize); + } + + /* + * Write to the property the new information about this stream + */ + Success = StorageImpl_ReadProperty(This->parentStorage->ancestorStorage, + This->ownerProperty, + &curProperty); + + curProperty.size.u.HighPart = libNewSize.u.HighPart; + curProperty.size.u.LowPart = libNewSize.u.LowPart; + + if (Success) + { + StorageImpl_WriteProperty(This->parentStorage->ancestorStorage, + This->ownerProperty, + &curProperty); + } + + This->streamSize = libNewSize; + + return S_OK; +} + +/*** + * This method is part of the IStream interface. + * + * It will copy the 'cb' Bytes to 'pstm' IStream. + * + * See the documentation of IStream for more info. + */ +HRESULT WINAPI StgStreamImpl_CopyTo( + IStream* iface, + IStream* pstm, /* [unique][in] */ + ULARGE_INTEGER cb, /* [in] */ + ULARGE_INTEGER* pcbRead, /* [out] */ + ULARGE_INTEGER* pcbWritten) /* [out] */ +{ + HRESULT hr = S_OK; + BYTE tmpBuffer[128]; + ULONG bytesRead, bytesWritten, copySize; + ULARGE_INTEGER totalBytesRead; + ULARGE_INTEGER totalBytesWritten; + + Print(MAX_TRACE, ("(%p, %p, %ld, %p, %p)\n", + iface, pstm, cb.u.LowPart, pcbRead, pcbWritten)); + + /* + * Sanity check + */ + if ( pstm == 0 ) + return STG_E_INVALIDPOINTER; + + totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0; + totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0; + + /* + * use stack to store data temporarly + * there is surely more performant way of doing it, for now this basic + * implementation will do the job + */ + while ( cb.u.LowPart > 0 ) + { + if ( cb.u.LowPart >= 128 ) + copySize = 128; + else + copySize = cb.u.LowPart; + + IStream_Read(iface, tmpBuffer, copySize, &bytesRead); + + totalBytesRead.u.LowPart += bytesRead; + + IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten); + + totalBytesWritten.u.LowPart += bytesWritten; + + /* + * Check that read & write operations were succesfull + */ + if (bytesRead != bytesWritten) + { + hr = STG_E_MEDIUMFULL; + break; + } + + if (bytesRead!=copySize) + cb.u.LowPart = 0; + else + cb.u.LowPart -= bytesRead; + } + + /* + * Update number of bytes read and written + */ + if (pcbRead) + { + pcbRead->u.LowPart = totalBytesRead.u.LowPart; + pcbRead->u.HighPart = totalBytesRead.u.HighPart; + } + + if (pcbWritten) + { + pcbWritten->u.LowPart = totalBytesWritten.u.LowPart; + pcbWritten->u.HighPart = totalBytesWritten.u.HighPart; + } + return hr; +} + +/*** + * This method is part of the IStream interface. + * + * For streams contained in structured storages, this method + * does nothing. This is what the documentation tells us. + * + * See the documentation of IStream for more info. + */ +HRESULT WINAPI StgStreamImpl_Commit( + IStream* iface, + DWORD grfCommitFlags) /* [in] */ +{ + return S_OK; +} + +/*** + * This method is part of the IStream interface. + * + * For streams contained in structured storages, this method + * does nothing. This is what the documentation tells us. + * + * See the documentation of IStream for more info. + */ +HRESULT WINAPI StgStreamImpl_Revert( + IStream* iface) +{ + return S_OK; +} + +HRESULT WINAPI StgStreamImpl_LockRegion( + IStream* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT WINAPI StgStreamImpl_UnlockRegion( + IStream* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/*** + * This method is part of the IStream interface. + * + * This method returns information about the current + * stream. + * + * See the documentation of IStream for more info. + */ +HRESULT WINAPI StgStreamImpl_Stat( + IStream* iface, + STATSTG* pstatstg, /* [out] */ + DWORD grfStatFlag) /* [in] */ +{ + StgStreamImpl* const This=(StgStreamImpl*)iface; + + StgProperty curProperty; + BOOL readSucessful; + + /* + * Read the information from the property. + */ + readSucessful = StorageImpl_ReadProperty(This->parentStorage->ancestorStorage, + This->ownerProperty, + &curProperty); + + if (readSucessful) + { + StorageUtl_CopyPropertyToSTATSTG(pstatstg, + &curProperty, + grfStatFlag); + + pstatstg->grfMode = This->grfMode; + + return S_OK; + } + + return E_FAIL; +} + +HRESULT WINAPI StgStreamImpl_Clone( + IStream* iface, + IStream** ppstm) /* [out] */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} diff --git a/lib/ole32/storage32.c b/lib/ole32/storage32.c new file mode 100644 index 0000000..80987cd --- /dev/null +++ b/lib/ole32/storage32.c @@ -0,0 +1,6989 @@ +/* + * Compound Storage (32 bit version) + * Storage implementation + * + * This file contains the compound file implementation + * of the storage interface. + * + * Copyright 1999 Francis Beaudet + * Copyright 1999 Sylvain St-Germain + * Copyright 1999 Thuy Nguyen + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#if 1 + +/* From wingdi16.h of WINE */ + +typedef HANDLE HMETAFILE16; + +typedef struct +{ + INT16 mm; + INT16 xExt; + INT16 yExt; + HMETAFILE16 hMF; +} METAFILEPICT16, *LPMETAFILEPICT16; + +#endif + +/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ +#define OLESTREAM_ID 0x501 +#define OLESTREAM_MAX_STR_LEN 255 + +static const char rootPropertyName[] = "Root Entry"; + + +/* OLESTREAM memory structure to use for Get and Put Routines */ +/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ +typedef struct +{ + DWORD dwOleID; + DWORD dwTypeID; + DWORD dwOleTypeNameLength; + CHAR strOleTypeName[OLESTREAM_MAX_STR_LEN]; + CHAR *pstrOleObjFileName; + DWORD dwOleObjFileNameLength; + DWORD dwMetaFileWidth; + DWORD dwMetaFileHeight; + CHAR strUnknown[8]; /* don't know what is this 8 byts information in OLE stream. */ + DWORD dwDataLength; + BYTE *pData; +}OLECONVERT_OLESTREAM_DATA; + +/* CompObj Stream structure */ +/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ +typedef struct +{ + BYTE byUnknown1[12]; + CLSID clsid; + DWORD dwCLSIDNameLength; + CHAR strCLSIDName[OLESTREAM_MAX_STR_LEN]; + DWORD dwOleTypeNameLength; + CHAR strOleTypeName[OLESTREAM_MAX_STR_LEN]; + DWORD dwProgIDNameLength; + CHAR strProgIDName[OLESTREAM_MAX_STR_LEN]; + BYTE byUnknown2[16]; +}OLECONVERT_ISTORAGE_COMPOBJ; + + +/* Ole Presention Stream structure */ +/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ +typedef struct +{ + BYTE byUnknown1[28]; + DWORD dwExtentX; + DWORD dwExtentY; + DWORD dwSize; + BYTE *pData; +}OLECONVERT_ISTORAGE_OLEPRES; + + + +/*********************************************************************** + * Forward declaration of internal functions used by the method DestroyElement + */ +static HRESULT deleteStorageProperty( + StorageImpl *parentStorage, + ULONG foundPropertyIndexToDelete, + StgProperty propertyToDelete); + +static HRESULT deleteStreamProperty( + StorageImpl *parentStorage, + ULONG foundPropertyIndexToDelete, + StgProperty propertyToDelete); + +static HRESULT findPlaceholder( + StorageImpl *storage, + ULONG propertyIndexToStore, + ULONG storagePropertyIndex, + INT typeOfRelation); + +static HRESULT adjustPropertyChain( + StorageImpl *This, + StgProperty propertyToDelete, + StgProperty parentProperty, + ULONG parentPropertyId, + INT typeOfRelation); + +/*********************************************************************** + * Declaration of the functions used to manipulate StgProperty + */ + +static ULONG getFreeProperty( + StorageImpl *storage); + +static void updatePropertyChain( + StorageImpl *storage, + ULONG newPropertyIndex, + StgProperty newProperty); + +static LONG propertyNameCmp( + OLECHAR *newProperty, + OLECHAR *currentProperty); + + +/*********************************************************************** + * Declaration of miscellaneous functions... + */ +static HRESULT validateSTGM(DWORD stgmValue); + +static DWORD GetShareModeFromSTGM(DWORD stgm); +static DWORD GetAccessModeFromSTGM(DWORD stgm); +static DWORD GetCreationModeFromSTGM(DWORD stgm); + +/* + * Virtual function table for the IStorage32Impl class. + */ +static ICOM_VTABLE(IStorage) Storage32Impl_Vtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + StorageBaseImpl_QueryInterface, + StorageBaseImpl_AddRef, + StorageBaseImpl_Release, + StorageBaseImpl_CreateStream, + StorageBaseImpl_OpenStream, + StorageImpl_CreateStorage, + StorageBaseImpl_OpenStorage, + StorageImpl_CopyTo, + StorageImpl_MoveElementTo, + StorageImpl_Commit, + StorageImpl_Revert, + StorageBaseImpl_EnumElements, + StorageImpl_DestroyElement, + StorageBaseImpl_RenameElement, + StorageImpl_SetElementTimes, + StorageBaseImpl_SetClass, + StorageImpl_SetStateBits, + StorageBaseImpl_Stat +}; + +/* + * Virtual function table for the Storage32InternalImpl class. + */ +static ICOM_VTABLE(IStorage) Storage32InternalImpl_Vtbl = + { + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + StorageBaseImpl_QueryInterface, + StorageBaseImpl_AddRef, + StorageBaseImpl_Release, + StorageBaseImpl_CreateStream, + StorageBaseImpl_OpenStream, + StorageImpl_CreateStorage, + StorageBaseImpl_OpenStorage, + StorageImpl_CopyTo, + StorageImpl_MoveElementTo, + StorageInternalImpl_Commit, + StorageInternalImpl_Revert, + StorageBaseImpl_EnumElements, + StorageImpl_DestroyElement, + StorageBaseImpl_RenameElement, + StorageImpl_SetElementTimes, + StorageBaseImpl_SetClass, + StorageImpl_SetStateBits, + StorageBaseImpl_Stat +}; + +/* + * Virtual function table for the IEnumSTATSTGImpl class. + */ +static ICOM_VTABLE(IEnumSTATSTG) IEnumSTATSTGImpl_Vtbl = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IEnumSTATSTGImpl_QueryInterface, + IEnumSTATSTGImpl_AddRef, + IEnumSTATSTGImpl_Release, + IEnumSTATSTGImpl_Next, + IEnumSTATSTGImpl_Skip, + IEnumSTATSTGImpl_Reset, + IEnumSTATSTGImpl_Clone +}; + + + + + +/************************************************************************ +** Storage32BaseImpl implementatiion +*/ + +/************************************************************************ + * Storage32BaseImpl_QueryInterface (IUnknown) + * + * This method implements the common QueryInterface for all IStorage32 + * implementations contained in this file. + * + * See Windows documentation for more details on IUnknown methods. + */ +HRESULT WINAPI StorageBaseImpl_QueryInterface( + IStorage* iface, + REFIID riid, + void** ppvObject) +{ + ICOM_THIS(StorageBaseImpl,iface); + /* + * Perform a sanity check on the parameters. + */ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) + { + *ppvObject = (IStorage*)This; + } + else if (memcmp(&IID_IStorage, riid, sizeof(IID_IStorage)) == 0) + { + *ppvObject = (IStorage*)This; + } + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* + * Query Interface always increases the reference count by one when it is + * successful + */ + StorageBaseImpl_AddRef(iface); + + return S_OK; +} + +/************************************************************************ + * Storage32BaseImpl_AddRef (IUnknown) + * + * This method implements the common AddRef for all IStorage32 + * implementations contained in this file. + * + * See Windows documentation for more details on IUnknown methods. + */ +ULONG WINAPI StorageBaseImpl_AddRef( + IStorage* iface) +{ + ICOM_THIS(StorageBaseImpl,iface); + This->ref++; + + return This->ref; +} + +/************************************************************************ + * Storage32BaseImpl_Release (IUnknown) + * + * This method implements the common Release for all IStorage32 + * implementations contained in this file. + * + * See Windows documentation for more details on IUnknown methods. + */ +ULONG WINAPI StorageBaseImpl_Release( + IStorage* iface) +{ + ICOM_THIS(StorageBaseImpl,iface); + /* + * Decrease the reference count on this object. + */ + This->ref--; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (This->ref==0) + { + /* + * Since we are using a system of base-classes, we want to call the + * destructor of the appropriate derived class. To do this, we are + * using virtual functions to implement the destructor. + */ + This->v_destructor(This); + + return 0; + } + + return This->ref; +} + +/************************************************************************ + * Storage32BaseImpl_OpenStream (IStorage) + * + * This method will open the specified stream object from the current storage. + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageBaseImpl_OpenStream( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + void* reserved1, /* [unique][in] */ + DWORD grfMode, /* [in] */ + DWORD reserved2, /* [in] */ + IStream** ppstm) /* [out] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + IEnumSTATSTGImpl* propertyEnumeration; + StgStreamImpl* newStream; + StgProperty currentProperty; + ULONG foundPropertyIndex; + + Print(MAX_TRACE, ("(%p, %S, %p, %lx, %ld, %p)\n", + iface, pwcsName, reserved1, grfMode, reserved2, ppstm)); + + /* + * Perform a sanity check on the parameters. + */ + if ( (pwcsName==NULL) || (ppstm==0) ) + return E_INVALIDARG; + + /* + * Initialize the out parameter + */ + *ppstm = 0; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) )) + return STG_E_INVALIDFLAG; + + /* + * As documented. + */ + if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || + (grfMode & STGM_DELETEONRELEASE) || + (grfMode & STGM_TRANSACTED) ) + return STG_E_INVALIDFUNCTION; + + /* + * Create a property enumeration to search the properties + */ + propertyEnumeration = IEnumSTATSTGImpl_Construct( + This->ancestorStorage, + This->rootPropertySetIndex); + + /* + * Search the enumeration for the property with the given name + */ + foundPropertyIndex = IEnumSTATSTGImpl_FindProperty( + propertyEnumeration, + pwcsName, + ¤tProperty); + + /* + * Delete the property enumeration since we don't need it anymore + */ + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + + /* + * If it was found, construct the stream object and return a pointer to it. + */ + if ( (foundPropertyIndex!=PROPERTY_NULL) && + (currentProperty.propertyType==PROPTYPE_STREAM) ) + { + newStream = StgStreamImpl_Construct(This, grfMode, foundPropertyIndex); + + if (newStream!=0) + { + newStream->grfMode = grfMode; + *ppstm = (IStream*)newStream; + + /* + * Since we are returning a pointer to the interface, we have to + * nail down the reference. + */ + StgStreamImpl_AddRef(*ppstm); + + return S_OK; + } + + return E_OUTOFMEMORY; + } + + return STG_E_FILENOTFOUND; +} + +/************************************************************************ + * Storage32BaseImpl_OpenStorage (IStorage) + * + * This method will open a new storage object from the current storage. + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageBaseImpl_OpenStorage( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][unique][in] */ + IStorage* pstgPriority, /* [unique][in] */ + DWORD grfMode, /* [in] */ + SNB snbExclude, /* [unique][in] */ + DWORD reserved, /* [in] */ + IStorage** ppstg) /* [out] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + StorageInternalImpl* newStorage; + IEnumSTATSTGImpl* propertyEnumeration; + StgProperty currentProperty; + ULONG foundPropertyIndex; + + Print(MAX_TRACE, ("(%p, %S, %p, %lx, %p, %ld, %p)\n", + iface, pwcsName, pstgPriority, + grfMode, snbExclude, reserved, ppstg)); + + /* + * Perform a sanity check on the parameters. + */ + if ( (This==0) || (pwcsName==NULL) || (ppstg==0) ) + return E_INVALIDARG; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) )) + return STG_E_INVALIDFLAG; + + /* + * As documented. + */ + if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || + (grfMode & STGM_DELETEONRELEASE) || + (grfMode & STGM_PRIORITY) ) + return STG_E_INVALIDFUNCTION; + + /* + * Initialize the out parameter + */ + *ppstg = 0; + + /* + * Create a property enumeration to search the properties + */ + propertyEnumeration = IEnumSTATSTGImpl_Construct( + This->ancestorStorage, + This->rootPropertySetIndex); + + /* + * Search the enumeration for the property with the given name + */ + foundPropertyIndex = IEnumSTATSTGImpl_FindProperty( + propertyEnumeration, + pwcsName, + ¤tProperty); + + /* + * Delete the property enumeration since we don't need it anymore + */ + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + + /* + * If it was found, construct the stream object and return a pointer to it. + */ + if ( (foundPropertyIndex!=PROPERTY_NULL) && + (currentProperty.propertyType==PROPTYPE_STORAGE) ) + { + /* + * Construct a new Storage object + */ + newStorage = StorageInternalImpl_Construct( + This->ancestorStorage, + foundPropertyIndex); + + if (newStorage != 0) + { + *ppstg = (IStorage*)newStorage; + + /* + * Since we are returning a pointer to the interface, + * we have to nail down the reference. + */ + StorageBaseImpl_AddRef(*ppstg); + + return S_OK; + } + + return STG_E_INSUFFICIENTMEMORY; + } + + return STG_E_FILENOTFOUND; +} + +/************************************************************************ + * Storage32BaseImpl_EnumElements (IStorage) + * + * This method will create an enumerator object that can be used to + * retrieve informatino about all the properties in the storage object. + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageBaseImpl_EnumElements( + IStorage* iface, + DWORD reserved1, /* [in] */ + void* reserved2, /* [size_is][unique][in] */ + DWORD reserved3, /* [in] */ + IEnumSTATSTG** ppenum) /* [out] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + IEnumSTATSTGImpl* newEnum; + + Print(MAX_TRACE, ("(%p, %ld, %p, %ld, %p)\n", + iface, reserved1, reserved2, reserved3, ppenum)); + + /* + * Perform a sanity check on the parameters. + */ + if ( (This==0) || (ppenum==0)) + return E_INVALIDARG; + + /* + * Construct the enumerator. + */ + newEnum = IEnumSTATSTGImpl_Construct( + This->ancestorStorage, + This->rootPropertySetIndex); + + if (newEnum!=0) + { + *ppenum = (IEnumSTATSTG*)newEnum; + + /* + * Don't forget to nail down a reference to the new object before + * returning it. + */ + IEnumSTATSTGImpl_AddRef(*ppenum); + + return S_OK; + } + + return E_OUTOFMEMORY; +} + +/************************************************************************ + * Storage32BaseImpl_Stat (IStorage) + * + * This method will retrieve information about this storage object. + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageBaseImpl_Stat( + IStorage* iface, + STATSTG* pstatstg, /* [out] */ + DWORD grfStatFlag) /* [in] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + StgProperty curProperty; + BOOL readSuccessful; + + Print(MAX_TRACE, ("(%p, %p, %lx)\n", + iface, pstatstg, grfStatFlag)); + + /* + * Perform a sanity check on the parameters. + */ + if ( (This==0) || (pstatstg==0)) + return E_INVALIDARG; + + /* + * Read the information from the property. + */ + readSuccessful = StorageImpl_ReadProperty( + This->ancestorStorage, + This->rootPropertySetIndex, + &curProperty); + + if (readSuccessful) + { + StorageUtl_CopyPropertyToSTATSTG( + pstatstg, + &curProperty, + grfStatFlag); + + return S_OK; + } + + return E_FAIL; +} + +/************************************************************************ + * Storage32BaseImpl_RenameElement (IStorage) + * + * This method will rename the specified element. + * + * See Windows documentation for more details on IStorage methods. + * + * Implementation notes: The method used to rename consists of creating a clone + * of the deleted StgProperty object setting it with the new name and to + * perform a DestroyElement of the old StgProperty. + */ +HRESULT WINAPI StorageBaseImpl_RenameElement( + IStorage* iface, + const OLECHAR* pwcsOldName, /* [in] */ + const OLECHAR* pwcsNewName) /* [in] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + IEnumSTATSTGImpl* propertyEnumeration; + StgProperty currentProperty; + ULONG foundPropertyIndex; + + Print(MAX_TRACE, ("(%p, %S, %S)\n", + iface, pwcsOldName, pwcsNewName)); + + /* + * Create a property enumeration to search the properties + */ + propertyEnumeration = IEnumSTATSTGImpl_Construct(This->ancestorStorage, + This->rootPropertySetIndex); + + /* + * Search the enumeration for the new property name + */ + foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration, + pwcsNewName, + ¤tProperty); + + if (foundPropertyIndex != PROPERTY_NULL) + { + /* + * There is already a property with the new name + */ + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + return STG_E_FILEALREADYEXISTS; + } + + IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)propertyEnumeration); + + /* + * Search the enumeration for the old property name + */ + foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration, + pwcsOldName, + ¤tProperty); + + /* + * Delete the property enumeration since we don't need it anymore + */ + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + + if (foundPropertyIndex != PROPERTY_NULL) + { + StgProperty renamedProperty; + ULONG renamedPropertyIndex; + + /* + * Setup a new property for the renamed property + */ + renamedProperty.sizeOfNameString = + ( lstrlenW(pwcsNewName)+1 ) * sizeof(WCHAR); + + if (renamedProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN) + return STG_E_INVALIDNAME; + + lstrcpyW(renamedProperty.name, pwcsNewName); + + renamedProperty.propertyType = currentProperty.propertyType; + renamedProperty.startingBlock = currentProperty.startingBlock; + renamedProperty.size.u.LowPart = currentProperty.size.u.LowPart; + renamedProperty.size.u.HighPart = currentProperty.size.u.HighPart; + + renamedProperty.previousProperty = PROPERTY_NULL; + renamedProperty.nextProperty = PROPERTY_NULL; + + /* + * Bring the dirProperty link in case it is a storage and in which + * case the renamed storage elements don't require to be reorganized. + */ + renamedProperty.dirProperty = currentProperty.dirProperty; + + /* call CoFileTime to get the current time + renamedProperty.timeStampS1 + renamedProperty.timeStampD1 + renamedProperty.timeStampS2 + renamedProperty.timeStampD2 + renamedProperty.propertyUniqueID + */ + + /* + * Obtain a free property in the property chain + */ + renamedPropertyIndex = getFreeProperty(This->ancestorStorage); + + /* + * Save the new property into the new property spot + */ + StorageImpl_WriteProperty( + This->ancestorStorage, + renamedPropertyIndex, + &renamedProperty); + + /* + * Find a spot in the property chain for our newly created property. + */ + updatePropertyChain( + (StorageImpl*)This, + renamedPropertyIndex, + renamedProperty); + + /* + * At this point the renamed property has been inserted in the tree, + * now, before to Destroy the old property we must zeroed it's dirProperty + * otherwise the DestroyProperty below will zap it all and we do not want + * this to happen. + * Also, we fake that the old property is a storage so the DestroyProperty + * will not do a SetSize(0) on the stream data. + * + * This means that we need to tweek the StgProperty if it is a stream or a + * non empty storage. + */ + StorageImpl_ReadProperty(This->ancestorStorage, + foundPropertyIndex, + ¤tProperty); + + currentProperty.dirProperty = PROPERTY_NULL; + currentProperty.propertyType = PROPTYPE_STORAGE; + StorageImpl_WriteProperty( + This->ancestorStorage, + foundPropertyIndex, + ¤tProperty); + + /* + * Invoke Destroy to get rid of the ole property and automatically redo + * the linking of it's previous and next members... + */ + StorageImpl_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName); + + } + else + { + /* + * There is no property with the old name + */ + return STG_E_FILENOTFOUND; + } + + return S_OK; +} + +/************************************************************************ + * Storage32BaseImpl_CreateStream (IStorage) + * + * This method will create a stream object within this storage + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageBaseImpl_CreateStream( + IStorage* iface, + const OLECHAR* pwcsName, /* [string][in] */ + DWORD grfMode, /* [in] */ + DWORD reserved1, /* [in] */ + DWORD reserved2, /* [in] */ + IStream** ppstm) /* [out] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + IEnumSTATSTGImpl* propertyEnumeration; + StgStreamImpl* newStream; + StgProperty currentProperty, newStreamProperty; + ULONG foundPropertyIndex, newPropertyIndex; + + Print(MAX_TRACE, ("(%p, %S, %lx, %ld, %ld, %p)\n", + iface, pwcsName, grfMode, + reserved1, reserved2, ppstm)); + + /* + * Validate parameters + */ + if (ppstm == 0) + return STG_E_INVALIDPOINTER; + + if (pwcsName == 0) + return STG_E_INVALIDNAME; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) )) + return STG_E_INVALIDFLAG; + + /* + * As documented. + */ + if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || + (grfMode & STGM_DELETEONRELEASE) || + (grfMode & STGM_TRANSACTED) ) + return STG_E_INVALIDFUNCTION; + + /* + * Initialize the out parameter + */ + *ppstm = 0; + + /* + * Create a property enumeration to search the properties + */ + propertyEnumeration = IEnumSTATSTGImpl_Construct(This->ancestorStorage, + This->rootPropertySetIndex); + + foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration, + pwcsName, + ¤tProperty); + + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + + if (foundPropertyIndex != PROPERTY_NULL) + { + /* + * An element with this name already exists + */ + if (grfMode & STGM_CREATE) + { + IStorage_DestroyElement(iface, pwcsName); + } + else + return STG_E_FILEALREADYEXISTS; + } + + /* + * memset the empty property + */ + memset(&newStreamProperty, 0, sizeof(StgProperty)); + + newStreamProperty.sizeOfNameString = + ( lstrlenW(pwcsName)+1 ) * sizeof(WCHAR); + + if (newStreamProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN) + return STG_E_INVALIDNAME; + + lstrcpyW(newStreamProperty.name, pwcsName); + + newStreamProperty.propertyType = PROPTYPE_STREAM; + newStreamProperty.startingBlock = BLOCK_END_OF_CHAIN; + newStreamProperty.size.u.LowPart = 0; + newStreamProperty.size.u.HighPart = 0; + + newStreamProperty.previousProperty = PROPERTY_NULL; + newStreamProperty.nextProperty = PROPERTY_NULL; + newStreamProperty.dirProperty = PROPERTY_NULL; + + /* call CoFileTime to get the current time + newStreamProperty.timeStampS1 + newStreamProperty.timeStampD1 + newStreamProperty.timeStampS2 + newStreamProperty.timeStampD2 + */ + + /* newStreamProperty.propertyUniqueID */ + + /* + * Get a free property or create a new one + */ + newPropertyIndex = getFreeProperty(This->ancestorStorage); + + /* + * Save the new property into the new property spot + */ + StorageImpl_WriteProperty( + This->ancestorStorage, + newPropertyIndex, + &newStreamProperty); + + /* + * Find a spot in the property chain for our newly created property. + */ + updatePropertyChain( + (StorageImpl*)This, + newPropertyIndex, + newStreamProperty); + + /* + * Open the stream to return it. + */ + newStream = StgStreamImpl_Construct(This, grfMode, newPropertyIndex); + + if (newStream != 0) + { + *ppstm = (IStream*)newStream; + + /* + * Since we are returning a pointer to the interface, we have to nail down + * the reference. + */ + StgStreamImpl_AddRef(*ppstm); + } + else + { + return STG_E_INSUFFICIENTMEMORY; + } + + return S_OK; +} + +/************************************************************************ + * Storage32BaseImpl_SetClass (IStorage) + * + * This method will write the specified CLSID in the property of this + * storage. + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageBaseImpl_SetClass( + IStorage* iface, + REFCLSID clsid) /* [in] */ +{ + ICOM_THIS(StorageBaseImpl,iface); + HRESULT hRes = E_FAIL; + StgProperty curProperty; + BOOL success; + + Print(MAX_TRACE, ("(%p, %p)\n", iface, clsid)); + + success = StorageImpl_ReadProperty(This->ancestorStorage, + This->rootPropertySetIndex, + &curProperty); + if (success) + { + curProperty.propertyUniqueID = *clsid; + + success = StorageImpl_WriteProperty(This->ancestorStorage, + This->rootPropertySetIndex, + &curProperty); + if (success) + hRes = S_OK; + } + + return hRes; +} + +/************************************************************************ +** Storage32Impl implementation +*/ + +/************************************************************************ + * Storage32Impl_CreateStorage (IStorage) + * + * This method will create the storage object within the provided storage. + * + * See Windows documentation for more details on IStorage methods. + */ +HRESULT WINAPI StorageImpl_CreateStorage( + IStorage* iface, + const OLECHAR *pwcsName, /* [string][in] */ + DWORD grfMode, /* [in] */ + DWORD reserved1, /* [in] */ + DWORD reserved2, /* [in] */ + IStorage **ppstg) /* [out] */ +{ + StorageImpl* const This=(StorageImpl*)iface; + + IEnumSTATSTGImpl *propertyEnumeration; + StgProperty currentProperty; + StgProperty newProperty; + ULONG foundPropertyIndex; + ULONG newPropertyIndex; + HRESULT hr; + + Print(MAX_TRACE, ("(%p, %S, %lx, %ld, %ld, %p)\n", + iface, pwcsName, grfMode, + reserved1, reserved2, ppstg)); + + /* + * Validate parameters + */ + if (ppstg == 0) + return STG_E_INVALIDPOINTER; + + if (pwcsName == 0) + return STG_E_INVALIDNAME; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) ) || + (grfMode & STGM_DELETEONRELEASE) ) + return STG_E_INVALIDFLAG; + + /* + * Initialize the out parameter + */ + *ppstg = 0; + + /* + * Create a property enumeration and search the properties + */ + propertyEnumeration = IEnumSTATSTGImpl_Construct( This->ancestorStorage, + This->rootPropertySetIndex); + + foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration, + pwcsName, + ¤tProperty); + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + + if (foundPropertyIndex != PROPERTY_NULL) + { + /* + * An element with this name already exists + */ + if (grfMode & STGM_CREATE) + IStorage_DestroyElement(iface, pwcsName); + else + return STG_E_FILEALREADYEXISTS; + } + + /* + * memset the empty property + */ + memset(&newProperty, 0, sizeof(StgProperty)); + + newProperty.sizeOfNameString = (lstrlenW(pwcsName)+1)*sizeof(WCHAR); + + if (newProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN) + return STG_E_INVALIDNAME; + + lstrcpyW(newProperty.name, pwcsName); + + newProperty.propertyType = PROPTYPE_STORAGE; + newProperty.startingBlock = BLOCK_END_OF_CHAIN; + newProperty.size.u.LowPart = 0; + newProperty.size.u.HighPart = 0; + + newProperty.previousProperty = PROPERTY_NULL; + newProperty.nextProperty = PROPERTY_NULL; + newProperty.dirProperty = PROPERTY_NULL; + + /* call CoFileTime to get the current time + newProperty.timeStampS1 + newProperty.timeStampD1 + newProperty.timeStampS2 + newProperty.timeStampD2 + */ + + /* newStorageProperty.propertyUniqueID */ + + /* + * Obtain a free property in the property chain + */ + newPropertyIndex = getFreeProperty(This->ancestorStorage); + + /* + * Save the new property into the new property spot + */ + StorageImpl_WriteProperty( + This->ancestorStorage, + newPropertyIndex, + &newProperty); + + /* + * Find a spot in the property chain for our newly created property. + */ + updatePropertyChain( + This, + newPropertyIndex, + newProperty); + + /* + * Open it to get a pointer to return. + */ + hr = IStorage_OpenStorage( + iface, + (OLECHAR*)pwcsName, + 0, + grfMode, + 0, + 0, + ppstg); + + if( (hr != S_OK) || (*ppstg == NULL)) + { + return hr; + } + + + return S_OK; +} + + +/*************************************************************************** + * + * Internal Method + * + * Get a free property or create a new one. + */ +static ULONG getFreeProperty( + StorageImpl *storage) +{ + ULONG currentPropertyIndex = 0; + ULONG newPropertyIndex = PROPERTY_NULL; + BOOL readSuccessful = TRUE; + StgProperty currentProperty; + + do + { + /* + * Start by reading the root property + */ + readSuccessful = StorageImpl_ReadProperty(storage->ancestorStorage, + currentPropertyIndex, + ¤tProperty); + if (readSuccessful) + { + if (currentProperty.sizeOfNameString == 0) + { + /* + * The property existis and is available, we found it. + */ + newPropertyIndex = currentPropertyIndex; + } + } + else + { + /* + * We exhausted the property list, we will create more space below + */ + newPropertyIndex = currentPropertyIndex; + } + currentPropertyIndex++; + + } while (newPropertyIndex == PROPERTY_NULL); + + /* + * grow the property chain + */ + if (! readSuccessful) + { + StgProperty emptyProperty; + ULARGE_INTEGER newSize; + ULONG propertyIndex; + ULONG lastProperty = 0; + ULONG blockCount = 0; + + /* + * obtain the new count of property blocks + */ + blockCount = BlockChainStream_GetCount( + storage->ancestorStorage->rootBlockChain)+1; + + /* + * initialize the size used by the property stream + */ + newSize.u.HighPart = 0; + newSize.u.LowPart = storage->bigBlockSize * blockCount; + + /* + * add a property block to the property chain + */ + BlockChainStream_SetSize(storage->ancestorStorage->rootBlockChain, newSize); + + /* + * memset the empty property in order to initialize the unused newly + * created property + */ + memset(&emptyProperty, 0, sizeof(StgProperty)); + + /* + * initialize them + */ + lastProperty = storage->bigBlockSize / PROPSET_BLOCK_SIZE * blockCount; + + for( + propertyIndex = newPropertyIndex; + propertyIndex < lastProperty; + propertyIndex++) + { + StorageImpl_WriteProperty( + storage->ancestorStorage, + propertyIndex, + &emptyProperty); + } + } + + return newPropertyIndex; +} + +/**************************************************************************** + * + * Internal Method + * + * Case insensitive comparaison of StgProperty.name by first considering + * their size. + * + * Returns <0 when newPrpoerty < currentProperty + * >0 when newPrpoerty > currentProperty + * 0 when newPrpoerty == currentProperty + */ +static LONG propertyNameCmp( + OLECHAR *newProperty, + OLECHAR *currentProperty) +{ + LONG diff = lstrlenW(newProperty) - lstrlenW(currentProperty); + + if (diff == 0) + { + /* + * We compare the string themselves only when they are of the same lenght + */ + diff = lstrcmpiW( newProperty, currentProperty); + } + + return diff; +} + +/**************************************************************************** + * + * Internal Method + * + * Properly link this new element in the property chain. + */ +static void updatePropertyChain( + StorageImpl *storage, + ULONG newPropertyIndex, + StgProperty newProperty) +{ + StgProperty currentProperty; + + /* + * Read the root property + */ + StorageImpl_ReadProperty(storage->ancestorStorage, + storage->rootPropertySetIndex, + ¤tProperty); + + if (currentProperty.dirProperty != PROPERTY_NULL) + { + /* + * The root storage contains some element, therefore, start the research + * for the appropriate location. + */ + BOOL found = 0; + ULONG current, next, previous, currentPropertyId; + + /* + * Keep the StgProperty sequence number of the storage first property + */ + currentPropertyId = currentProperty.dirProperty; + + /* + * Read + */ + StorageImpl_ReadProperty(storage->ancestorStorage, + currentProperty.dirProperty, + ¤tProperty); + + previous = currentProperty.previousProperty; + next = currentProperty.nextProperty; + current = currentPropertyId; + + while (found == 0) + { + LONG diff = propertyNameCmp( newProperty.name, currentProperty.name); + + if (diff < 0) + { + if (previous != PROPERTY_NULL) + { + StorageImpl_ReadProperty(storage->ancestorStorage, + previous, + ¤tProperty); + current = previous; + } + else + { + currentProperty.previousProperty = newPropertyIndex; + StorageImpl_WriteProperty(storage->ancestorStorage, + current, + ¤tProperty); + found = 1; + } + } + else if (diff > 0) + { + if (next != PROPERTY_NULL) + { + StorageImpl_ReadProperty(storage->ancestorStorage, + next, + ¤tProperty); + current = next; + } + else + { + currentProperty.nextProperty = newPropertyIndex; + StorageImpl_WriteProperty(storage->ancestorStorage, + current, + ¤tProperty); + found = 1; + } + } + else + { + /* + * Trying to insert an item with the same name in the + * subtree structure. + */ + assert(FALSE); + } + + previous = currentProperty.previousProperty; + next = currentProperty.nextProperty; + } + } + else + { + /* + * The root storage is empty, link the new property to it's dir property + */ + currentProperty.dirProperty = newPropertyIndex; + StorageImpl_WriteProperty(storage->ancestorStorage, + storage->rootPropertySetIndex, + ¤tProperty); + } +} + + +/************************************************************************* + * CopyTo (IStorage) + */ +HRESULT WINAPI StorageImpl_CopyTo( + IStorage* iface, + DWORD ciidExclude, /* [in] */ + const IID* rgiidExclude, /* [size_is][unique][in] */ + SNB snbExclude, /* [unique][in] */ + IStorage* pstgDest) /* [unique][in] */ +{ + IEnumSTATSTG *elements = 0; + STATSTG curElement, strStat; + HRESULT hr; + IStorage *pstgTmp, *pstgChild; + IStream *pstrTmp, *pstrChild; + + if ((ciidExclude != 0) || (rgiidExclude != NULL) || (snbExclude != NULL)) + UNIMPLEMENTED; + + Print(MAX_TRACE, ("(%p, %ld, %p, %p, %p)\n", + iface, ciidExclude, rgiidExclude, + snbExclude, pstgDest)); + + /* + * Perform a sanity check + */ + if ( pstgDest == 0 ) + return STG_E_INVALIDPOINTER; + + /* + * Enumerate the elements + */ + hr = IStorage_EnumElements( iface, 0, 0, 0, &elements ); + + if ( hr != S_OK ) + return hr; + + /* + * set the class ID + */ + IStorage_Stat( iface, &curElement, STATFLAG_NONAME); + IStorage_SetClass( pstgDest, &curElement.clsid ); + + do + { + /* + * Obtain the next element + */ + hr = IEnumSTATSTG_Next( elements, 1, &curElement, NULL ); + + if ( hr == S_FALSE ) + { + hr = S_OK; /* done, every element has been copied */ + break; + } + + if (curElement.type == STGTY_STORAGE) + { + /* + * open child source storage + */ + hr = IStorage_OpenStorage( iface, curElement.pwcsName, NULL, + STGM_READ|STGM_SHARE_EXCLUSIVE, + NULL, 0, &pstgChild ); + + if (hr != S_OK) + break; + + /* + * Check if destination storage is not a child of the source + * storage, which will cause an infinite loop + */ + if (pstgChild == pstgDest) + { + IEnumSTATSTG_Release(elements); + + return STG_E_ACCESSDENIED; + } + + /* + * create a new storage in destination storage + */ + hr = IStorage_CreateStorage( pstgDest, curElement.pwcsName, + STGM_FAILIFTHERE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, + 0, 0, + &pstgTmp ); + /* + * if it already exist, don't create a new one use this one + */ + if (hr == STG_E_FILEALREADYEXISTS) + { + hr = IStorage_OpenStorage( pstgDest, curElement.pwcsName, NULL, + STGM_WRITE|STGM_SHARE_EXCLUSIVE, + NULL, 0, &pstgTmp ); + } + + if (hr != S_OK) + break; + + + /* + * do the copy recursively + */ + hr = IStorage_CopyTo( pstgChild, ciidExclude, rgiidExclude, + snbExclude, pstgTmp ); + + IStorage_Release( pstgTmp ); + IStorage_Release( pstgChild ); + } + else if (curElement.type == STGTY_STREAM) + { + /* + * create a new stream in destination storage. If the stream already + * exist, it will be deleted and a new one will be created. + */ + hr = IStorage_CreateStream( pstgDest, curElement.pwcsName, + STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, + 0, 0, &pstrTmp ); + + if (hr != S_OK) + break; + + /* + * open child stream storage + */ + hr = IStorage_OpenStream( iface, curElement.pwcsName, NULL, + STGM_READ|STGM_SHARE_EXCLUSIVE, + 0, &pstrChild ); + + if (hr != S_OK) + break; + + /* + * Get the size of the source stream + */ + IStream_Stat( pstrChild, &strStat, STATFLAG_NONAME ); + + /* + * Set the size of the destination stream. + */ + IStream_SetSize(pstrTmp, strStat.cbSize); + + /* + * do the copy + */ + hr = IStream_CopyTo( pstrChild, pstrTmp, strStat.cbSize, + NULL, NULL ); + + IStream_Release( pstrTmp ); + IStream_Release( pstrChild ); + } + else + { + Print(MIN_TRACE, ("unknown element type: %ld\n", curElement.type)); + } + + } while (hr == S_OK); + + /* + * Clean-up + */ + IEnumSTATSTG_Release(elements); + + return hr; +} + +/************************************************************************* + * MoveElementTo (IStorage) + */ +HRESULT WINAPI StorageImpl_MoveElementTo( + IStorage* iface, + const OLECHAR *pwcsName, /* [string][in] */ + IStorage *pstgDest, /* [unique][in] */ + const OLECHAR *pwcsNewName,/* [string][in] */ + DWORD grfFlags) /* [in] */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/************************************************************************* + * Commit (IStorage) + */ +HRESULT WINAPI StorageImpl_Commit( + IStorage* iface, + DWORD grfCommitFlags)/* [in] */ +{ + UNIMPLEMENTED; + return S_OK; +} + +/************************************************************************* + * Revert (IStorage) + */ +HRESULT WINAPI StorageImpl_Revert( + IStorage* iface) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/************************************************************************* + * DestroyElement (IStorage) + * + * Stategy: This implementation is build this way for simplicity not for speed. + * I always delete the top most element of the enumeration and adjust + * the deleted element pointer all the time. This takes longer to + * do but allow to reinvoke DestroyElement whenever we encounter a + * storage object. The optimisation reside in the usage of another + * enumeration stategy that would give all the leaves of a storage + * first. (postfix order) + */ +HRESULT WINAPI StorageImpl_DestroyElement( + IStorage* iface, + const OLECHAR *pwcsName)/* [string][in] */ +{ + StorageImpl* const This=(StorageImpl*)iface; + + IEnumSTATSTGImpl* propertyEnumeration; + HRESULT hr = S_OK; + BOOL res; + StgProperty propertyToDelete; + StgProperty parentProperty; + ULONG foundPropertyIndexToDelete; + ULONG typeOfRelation; + ULONG parentPropertyId; + + Print(MAX_TRACE, ("(%p, %S)\n", + iface, pwcsName)); + + /* + * Perform a sanity check on the parameters. + */ + if (pwcsName==NULL) + return STG_E_INVALIDPOINTER; + + /* + * Create a property enumeration to search the property with the given name + */ + propertyEnumeration = IEnumSTATSTGImpl_Construct( + This->ancestorStorage, + This->rootPropertySetIndex); + + foundPropertyIndexToDelete = IEnumSTATSTGImpl_FindProperty( + propertyEnumeration, + pwcsName, + &propertyToDelete); + + IEnumSTATSTGImpl_Destroy(propertyEnumeration); + + if ( foundPropertyIndexToDelete == PROPERTY_NULL ) + { + return STG_E_FILENOTFOUND; + } + + /* + * Find the parent property of the property to delete (the one that + * link to it). If This->dirProperty == foundPropertyIndexToDelete, + * the parent is This. Otherwise, the parent is one of it's sibling... + */ + + /* + * First, read This's StgProperty.. + */ + res = StorageImpl_ReadProperty( + This->ancestorStorage, + This->rootPropertySetIndex, + &parentProperty); + + assert(res==TRUE); + + /* + * Second, check to see if by any chance the actual storage (This) is not + * the parent of the property to delete... We never know... + */ + if ( parentProperty.dirProperty == foundPropertyIndexToDelete ) + { + /* + * Set data as it would have been done in the else part... + */ + typeOfRelation = PROPERTY_RELATION_DIR; + parentPropertyId = This->rootPropertySetIndex; + } + else + { + /* + * Create a property enumeration to search the parent properties, and + * delete it once done. + */ + IEnumSTATSTGImpl* propertyEnumeration2; + + propertyEnumeration2 = IEnumSTATSTGImpl_Construct( + This->ancestorStorage, + This->rootPropertySetIndex); + + typeOfRelation = IEnumSTATSTGImpl_FindParentProperty( + propertyEnumeration2, + foundPropertyIndexToDelete, + &parentProperty, + &parentPropertyId); + + IEnumSTATSTGImpl_Destroy(propertyEnumeration2); + } + + if ( propertyToDelete.propertyType == PROPTYPE_STORAGE ) + { + hr = deleteStorageProperty( + This, + foundPropertyIndexToDelete, + propertyToDelete); + } + else if ( propertyToDelete.propertyType == PROPTYPE_STREAM ) + { + hr = deleteStreamProperty( + This, + foundPropertyIndexToDelete, + propertyToDelete); + } + + if (hr!=S_OK) + return hr; + + /* + * Adjust the property chain + */ + hr = adjustPropertyChain( + This, + propertyToDelete, + parentProperty, + parentPropertyId, + typeOfRelation); + + return hr; +} + + +/********************************************************************* + * + * Internal Method + * + * Perform the deletion of a complete storage node + * + */ +static HRESULT deleteStorageProperty( + StorageImpl *parentStorage, + ULONG indexOfPropertyToDelete, + StgProperty propertyToDelete) +{ + IEnumSTATSTG *elements = 0; + IStorage *childStorage = 0; + STATSTG currentElement; + HRESULT hr; + HRESULT destroyHr = S_OK; + + /* + * Open the storage and enumerate it + */ + hr = StorageBaseImpl_OpenStorage( + (IStorage*)parentStorage, + propertyToDelete.name, + 0, + STGM_SHARE_EXCLUSIVE, + 0, + 0, + &childStorage); + + if (hr != S_OK) + { + return hr; + } + + /* + * Enumerate the elements + */ + IStorage_EnumElements( childStorage, 0, 0, 0, &elements); + + do + { + /* + * Obtain the next element + */ + hr = IEnumSTATSTG_Next(elements, 1, ¤tElement, NULL); + if (hr==S_OK) + { + destroyHr = StorageImpl_DestroyElement( + (IStorage*)childStorage, + (OLECHAR*)currentElement.pwcsName); + + CoTaskMemFree(currentElement.pwcsName); + } + + /* + * We need to Reset the enumeration every time because we delete elements + * and the enumeration could be invalid + */ + IEnumSTATSTG_Reset(elements); + + } while ((hr == S_OK) && (destroyHr == S_OK)); + + /* + * Invalidate the property by zeroing it's name member. + */ + propertyToDelete.sizeOfNameString = 0; + + StorageImpl_WriteProperty(parentStorage->ancestorStorage, + indexOfPropertyToDelete, + &propertyToDelete); + + IStorage_Release(childStorage); + IEnumSTATSTG_Release(elements); + + return destroyHr; +} + +/********************************************************************* + * + * Internal Method + * + * Perform the deletion of a stream node + * + */ +static HRESULT deleteStreamProperty( + StorageImpl *parentStorage, + ULONG indexOfPropertyToDelete, + StgProperty propertyToDelete) +{ + IStream *pis; + HRESULT hr; + ULARGE_INTEGER size; + + size.u.HighPart = 0; + size.u.LowPart = 0; + + hr = StorageBaseImpl_OpenStream( + (IStorage*)parentStorage, + (OLECHAR*)propertyToDelete.name, + NULL, + STGM_WRITE | STGM_SHARE_EXCLUSIVE, + 0, + &pis); + + if (hr!=S_OK) + { + return(hr); + } + + /* + * Zap the stream + */ + hr = IStream_SetSize(pis, size); + + if(hr != S_OK) + { + return hr; + } + + /* + * Release the stream object. + */ + IStream_Release(pis); + + /* + * Invalidate the property by zeroing it's name member. + */ + propertyToDelete.sizeOfNameString = 0; + + /* + * Here we should re-read the property so we get the updated pointer + * but since we are here to zap it, I don't do it... + */ + StorageImpl_WriteProperty( + parentStorage->ancestorStorage, + indexOfPropertyToDelete, + &propertyToDelete); + + return S_OK; +} + +/********************************************************************* + * + * Internal Method + * + * Finds a placeholder for the StgProperty within the Storage + * + */ +static HRESULT findPlaceholder( + StorageImpl *storage, + ULONG propertyIndexToStore, + ULONG storePropertyIndex, + INT typeOfRelation) +{ + StgProperty storeProperty; + HRESULT hr = S_OK; + BOOL res = TRUE; + + /* + * Read the storage property + */ + res = StorageImpl_ReadProperty( + storage->ancestorStorage, + storePropertyIndex, + &storeProperty); + + if(! res) + { + return E_FAIL; + } + + if (typeOfRelation == PROPERTY_RELATION_PREVIOUS) + { + if (storeProperty.previousProperty != PROPERTY_NULL) + { + return findPlaceholder( + storage, + propertyIndexToStore, + storeProperty.previousProperty, + typeOfRelation); + } + else + { + storeProperty.previousProperty = propertyIndexToStore; + } + } + else if (typeOfRelation == PROPERTY_RELATION_NEXT) + { + if (storeProperty.nextProperty != PROPERTY_NULL) + { + return findPlaceholder( + storage, + propertyIndexToStore, + storeProperty.nextProperty, + typeOfRelation); + } + else + { + storeProperty.nextProperty = propertyIndexToStore; + } + } + else if (typeOfRelation == PROPERTY_RELATION_DIR) + { + if (storeProperty.dirProperty != PROPERTY_NULL) + { + return findPlaceholder( + storage, + propertyIndexToStore, + storeProperty.dirProperty, + typeOfRelation); + } + else + { + storeProperty.dirProperty = propertyIndexToStore; + } + } + + hr = StorageImpl_WriteProperty( + storage->ancestorStorage, + storePropertyIndex, + &storeProperty); + + if(! hr) + { + return E_FAIL; + } + + return S_OK; +} + +/************************************************************************* + * + * Internal Method + * + * This method takes the previous and the next property link of a property + * to be deleted and find them a place in the Storage. + */ +static HRESULT adjustPropertyChain( + StorageImpl *This, + StgProperty propertyToDelete, + StgProperty parentProperty, + ULONG parentPropertyId, + INT typeOfRelation) +{ + ULONG newLinkProperty = PROPERTY_NULL; + BOOL needToFindAPlaceholder = FALSE; + ULONG storeNode = PROPERTY_NULL; + ULONG toStoreNode = PROPERTY_NULL; + INT relationType = 0; + HRESULT hr = S_OK; + BOOL res = TRUE; + + if (typeOfRelation == PROPERTY_RELATION_PREVIOUS) + { + if (propertyToDelete.previousProperty != PROPERTY_NULL) + { + /* + * Set the parent previous to the property to delete previous + */ + newLinkProperty = propertyToDelete.previousProperty; + + if (propertyToDelete.nextProperty != PROPERTY_NULL) + { + /* + * We also need to find a storage for the other link, setup variables + * to do this at the end... + */ + needToFindAPlaceholder = TRUE; + storeNode = propertyToDelete.previousProperty; + toStoreNode = propertyToDelete.nextProperty; + relationType = PROPERTY_RELATION_NEXT; + } + } + else if (propertyToDelete.nextProperty != PROPERTY_NULL) + { + /* + * Set the parent previous to the property to delete next + */ + newLinkProperty = propertyToDelete.nextProperty; + } + + /* + * Link it for real... + */ + parentProperty.previousProperty = newLinkProperty; + + } + else if (typeOfRelation == PROPERTY_RELATION_NEXT) + { + if (propertyToDelete.previousProperty != PROPERTY_NULL) + { + /* + * Set the parent next to the property to delete next previous + */ + newLinkProperty = propertyToDelete.previousProperty; + + if (propertyToDelete.nextProperty != PROPERTY_NULL) + { + /* + * We also need to find a storage for the other link, setup variables + * to do this at the end... + */ + needToFindAPlaceholder = TRUE; + storeNode = propertyToDelete.previousProperty; + toStoreNode = propertyToDelete.nextProperty; + relationType = PROPERTY_RELATION_NEXT; + } + } + else if (propertyToDelete.nextProperty != PROPERTY_NULL) + { + /* + * Set the parent next to the property to delete next + */ + newLinkProperty = propertyToDelete.nextProperty; + } + + /* + * Link it for real... + */ + parentProperty.nextProperty = newLinkProperty; + } + else /* (typeOfRelation == PROPERTY_RELATION_DIR) */ + { + if (propertyToDelete.previousProperty != PROPERTY_NULL) + { + /* + * Set the parent dir to the property to delete previous + */ + newLinkProperty = propertyToDelete.previousProperty; + + if (propertyToDelete.nextProperty != PROPERTY_NULL) + { + /* + * We also need to find a storage for the other link, setup variables + * to do this at the end... + */ + needToFindAPlaceholder = TRUE; + storeNode = propertyToDelete.previousProperty; + toStoreNode = propertyToDelete.nextProperty; + relationType = PROPERTY_RELATION_NEXT; + } + } + else if (propertyToDelete.nextProperty != PROPERTY_NULL) + { + /* + * Set the parent dir to the property to delete next + */ + newLinkProperty = propertyToDelete.nextProperty; + } + + /* + * Link it for real... + */ + parentProperty.dirProperty = newLinkProperty; + } + + /* + * Write back the parent property + */ + res = StorageImpl_WriteProperty( + This->ancestorStorage, + parentPropertyId, + &parentProperty); + if(! res) + { + return E_FAIL; + } + + /* + * If a placeholder is required for the other link, then, find one and + * get out of here... + */ + if (needToFindAPlaceholder) + { + hr = findPlaceholder( + This, + toStoreNode, + storeNode, + relationType); + } + + return hr; +} + + +/****************************************************************************** + * SetElementTimes (IStorage) + */ +HRESULT WINAPI StorageImpl_SetElementTimes( + IStorage* iface, + const OLECHAR *pwcsName,/* [string][in] */ + const FILETIME *pctime, /* [in] */ + const FILETIME *patime, /* [in] */ + const FILETIME *pmtime) /* [in] */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +/****************************************************************************** + * SetStateBits (IStorage) + */ +HRESULT WINAPI StorageImpl_SetStateBits( + IStorage* iface, + DWORD grfStateBits,/* [in] */ + DWORD grfMask) /* [in] */ +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +HRESULT StorageImpl_Construct( + StorageImpl* This, + HANDLE hFile, + ILockBytes* pLkbyt, + DWORD openFlags, + BOOL fileBased, + BOOL fileCreate) +{ + HRESULT hr = S_OK; + StgProperty currentProperty; + BOOL readSuccessful; + ULONG currentPropertyIndex; + + if ( FAILED( validateSTGM(openFlags) )) + return STG_E_INVALIDFLAG; + + memset(This, 0, sizeof(StorageImpl)); + + /* + * Initialize the virtual fgunction table. + */ + ICOM_VTBL(This) = &Storage32Impl_Vtbl; + This->v_destructor = &StorageImpl_Destroy; + + /* + * This is the top-level storage so initialize the ancester pointer + * to this. + */ + This->ancestorStorage = This; + + /* + * Initialize the physical support of the storage. + */ + This->hFile = hFile; + + /* + * Initialize the big block cache. + */ + This->bigBlockSize = DEF_BIG_BLOCK_SIZE; + This->smallBlockSize = DEF_SMALL_BLOCK_SIZE; + This->bigBlockFile = BIGBLOCKFILE_Construct(hFile, + pLkbyt, + openFlags, + This->bigBlockSize, + fileBased); + + if (This->bigBlockFile == 0) + return E_FAIL; + + if (fileCreate) + { + ULARGE_INTEGER size; + BYTE* bigBlockBuffer; + + /* + * Initialize all header variables: + * - The big block depot consists of one block and it is at block 0 + * - The properties start at block 1 + * - There is no small block depot + */ + memset( This->bigBlockDepotStart, + BLOCK_UNUSED, + sizeof(This->bigBlockDepotStart)); + + This->bigBlockDepotCount = 1; + This->bigBlockDepotStart[0] = 0; + This->rootStartBlock = 1; + This->smallBlockDepotStart = BLOCK_END_OF_CHAIN; + This->bigBlockSizeBits = DEF_BIG_BLOCK_SIZE_BITS; + This->smallBlockSizeBits = DEF_SMALL_BLOCK_SIZE_BITS; + This->extBigBlockDepotStart = BLOCK_END_OF_CHAIN; + This->extBigBlockDepotCount = 0; + + StorageImpl_SaveFileHeader(This); + + /* + * Add one block for the big block depot and one block for the properties + */ + size.u.HighPart = 0; + size.u.LowPart = This->bigBlockSize * 3; + BIGBLOCKFILE_SetSize(This->bigBlockFile, size); + + /* + * Initialize the big block depot + */ + bigBlockBuffer = StorageImpl_GetBigBlock(This, 0); + memset(bigBlockBuffer, BLOCK_UNUSED, This->bigBlockSize); + StorageUtl_WriteDWord(bigBlockBuffer, 0, BLOCK_SPECIAL); + StorageUtl_WriteDWord(bigBlockBuffer, sizeof(ULONG), BLOCK_END_OF_CHAIN); + StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); + } + else + { + /* + * Load the header for the file. + */ + hr = StorageImpl_LoadFileHeader(This); + + if (FAILED(hr)) + { + BIGBLOCKFILE_Destructor(This->bigBlockFile); + + return hr; + } + } + + /* + * There is no block depot cached yet. + */ + This->indexBlockDepotCached = 0xFFFFFFFF; + + /* + * Start searching for free blocks with block 0. + */ + This->prevFreeBlock = 0; + + /* + * Create the block chain abstractions. + */ + This->rootBlockChain = + BlockChainStream_Construct(This, &This->rootStartBlock, PROPERTY_NULL); + + This->smallBlockDepotChain = BlockChainStream_Construct( + This, + &This->smallBlockDepotStart, + PROPERTY_NULL); + + /* + * Write the root property + */ + if (fileCreate) + { + StgProperty rootProp; + /* + * Initialize the property chain + */ + memset(&rootProp, 0, sizeof(rootProp)); + MultiByteToWideChar( CP_ACP, 0, rootPropertyName, -1, rootProp.name, + sizeof(rootProp.name)/sizeof(WCHAR) ); + rootProp.sizeOfNameString = (lstrlenW(rootProp.name)+1) * sizeof(WCHAR); + rootProp.propertyType = PROPTYPE_ROOT; + rootProp.previousProperty = PROPERTY_NULL; + rootProp.nextProperty = PROPERTY_NULL; + rootProp.dirProperty = PROPERTY_NULL; + rootProp.startingBlock = BLOCK_END_OF_CHAIN; + rootProp.size.u.HighPart = 0; + rootProp.size.u.LowPart = 0; + + StorageImpl_WriteProperty(This, 0, &rootProp); + } + + /* + * Find the ID of the root int he property sets. + */ + currentPropertyIndex = 0; + + do + { + readSuccessful = StorageImpl_ReadProperty( + This, + currentPropertyIndex, + ¤tProperty); + + if (readSuccessful) + { + if ( (currentProperty.sizeOfNameString != 0 ) && + (currentProperty.propertyType == PROPTYPE_ROOT) ) + { + This->rootPropertySetIndex = currentPropertyIndex; + } + } + + currentPropertyIndex++; + + } while (readSuccessful && (This->rootPropertySetIndex == PROPERTY_NULL) ); + + if (!readSuccessful) + { + /* TODO CLEANUP */ + return E_FAIL; + } + + /* + * Create the block chain abstraction for the small block root chain. + */ + This->smallBlockRootChain = BlockChainStream_Construct( + This, + NULL, + This->rootPropertySetIndex); + + return hr; +} + +void StorageImpl_Destroy( + StorageImpl* This) +{ + Print(MAX_TRACE, ("(%p)\n", This)); + + BlockChainStream_Destroy(This->smallBlockRootChain); + BlockChainStream_Destroy(This->rootBlockChain); + BlockChainStream_Destroy(This->smallBlockDepotChain); + + BIGBLOCKFILE_Destructor(This->bigBlockFile); + return; +} + +/****************************************************************************** + * Storage32Impl_GetNextFreeBigBlock + * + * Returns the index of the next free big block. + * If the big block depot is filled, this method will enlarge it. + * + */ +ULONG StorageImpl_GetNextFreeBigBlock( + StorageImpl* This) +{ + ULONG depotBlockIndexPos; + void *depotBuffer; + ULONG depotBlockOffset; + ULONG blocksPerDepot = This->bigBlockSize / sizeof(ULONG); + ULONG nextBlockIndex = BLOCK_SPECIAL; + int depotIndex = 0; + ULONG freeBlock = BLOCK_UNUSED; + + depotIndex = This->prevFreeBlock / blocksPerDepot; + depotBlockOffset = (This->prevFreeBlock % blocksPerDepot) * sizeof(ULONG); + + /* + * Scan the entire big block depot until we find a block marked free + */ + while (nextBlockIndex != BLOCK_UNUSED) + { + if (depotIndex < COUNT_BBDEPOTINHEADER) + { + depotBlockIndexPos = This->bigBlockDepotStart[depotIndex]; + + /* + * Grow the primary depot. + */ + if (depotBlockIndexPos == BLOCK_UNUSED) + { + depotBlockIndexPos = depotIndex*blocksPerDepot; + + /* + * Add a block depot. + */ + Storage32Impl_AddBlockDepot(This, depotBlockIndexPos); + This->bigBlockDepotCount++; + This->bigBlockDepotStart[depotIndex] = depotBlockIndexPos; + + /* + * Flag it as a block depot. + */ + StorageImpl_SetNextBlockInChain(This, + depotBlockIndexPos, + BLOCK_SPECIAL); + + /* Save new header information. + */ + StorageImpl_SaveFileHeader(This); + } + } + else + { + depotBlockIndexPos = Storage32Impl_GetExtDepotBlock(This, depotIndex); + + if (depotBlockIndexPos == BLOCK_UNUSED) + { + /* + * Grow the extended depot. + */ + ULONG extIndex = BLOCK_UNUSED; + ULONG numExtBlocks = depotIndex - COUNT_BBDEPOTINHEADER; + ULONG extBlockOffset = numExtBlocks % (blocksPerDepot - 1); + + if (extBlockOffset == 0) + { + /* We need an extended block. + */ + extIndex = Storage32Impl_AddExtBlockDepot(This); + This->extBigBlockDepotCount++; + depotBlockIndexPos = extIndex + 1; + } + else + depotBlockIndexPos = depotIndex * blocksPerDepot; + + /* + * Add a block depot and mark it in the extended block. + */ + Storage32Impl_AddBlockDepot(This, depotBlockIndexPos); + This->bigBlockDepotCount++; + Storage32Impl_SetExtDepotBlock(This, depotIndex, depotBlockIndexPos); + + /* Flag the block depot. + */ + StorageImpl_SetNextBlockInChain(This, + depotBlockIndexPos, + BLOCK_SPECIAL); + + /* If necessary, flag the extended depot block. + */ + if (extIndex != BLOCK_UNUSED) + StorageImpl_SetNextBlockInChain(This, extIndex, BLOCK_EXTBBDEPOT); + + /* Save header information. + */ + StorageImpl_SaveFileHeader(This); + } + } + + depotBuffer = StorageImpl_GetROBigBlock(This, depotBlockIndexPos); + + if (depotBuffer != 0) + { + while ( ( (depotBlockOffset/sizeof(ULONG) ) < blocksPerDepot) && + ( nextBlockIndex != BLOCK_UNUSED)) + { + StorageUtl_ReadDWord(depotBuffer, depotBlockOffset, &nextBlockIndex); + + if (nextBlockIndex == BLOCK_UNUSED) + { + freeBlock = (depotIndex * blocksPerDepot) + + (depotBlockOffset/sizeof(ULONG)); + } + + depotBlockOffset += sizeof(ULONG); + } + + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + + depotIndex++; + depotBlockOffset = 0; + } + + This->prevFreeBlock = freeBlock; + + return freeBlock; +} + +/****************************************************************************** + * Storage32Impl_AddBlockDepot + * + * This will create a depot block, essentially it is a block initialized + * to BLOCK_UNUSEDs. + */ +void Storage32Impl_AddBlockDepot(StorageImpl* This, ULONG blockIndex) +{ + BYTE* blockBuffer; + + blockBuffer = StorageImpl_GetBigBlock(This, blockIndex); + + /* + * Initialize blocks as free + */ + memset(blockBuffer, BLOCK_UNUSED, This->bigBlockSize); + + StorageImpl_ReleaseBigBlock(This, blockBuffer); +} + +/****************************************************************************** + * Storage32Impl_GetExtDepotBlock + * + * Returns the index of the block that corresponds to the specified depot + * index. This method is only for depot indexes equal or greater than + * COUNT_BBDEPOTINHEADER. + */ +ULONG Storage32Impl_GetExtDepotBlock(StorageImpl* This, ULONG depotIndex) +{ + ULONG depotBlocksPerExtBlock = (This->bigBlockSize / sizeof(ULONG)) - 1; + ULONG numExtBlocks = depotIndex - COUNT_BBDEPOTINHEADER; + ULONG extBlockCount = numExtBlocks / depotBlocksPerExtBlock; + ULONG extBlockOffset = numExtBlocks % depotBlocksPerExtBlock; + ULONG blockIndex = BLOCK_UNUSED; + ULONG extBlockIndex = This->extBigBlockDepotStart; + + assert(depotIndex >= COUNT_BBDEPOTINHEADER); + + if (This->extBigBlockDepotStart == BLOCK_END_OF_CHAIN) + return BLOCK_UNUSED; + + while (extBlockCount > 0) + { + extBlockIndex = Storage32Impl_GetNextExtendedBlock(This, extBlockIndex); + extBlockCount--; + } + + if (extBlockIndex != BLOCK_UNUSED) + { + BYTE* depotBuffer; + + depotBuffer = StorageImpl_GetROBigBlock(This, extBlockIndex); + + if (depotBuffer != 0) + { + StorageUtl_ReadDWord(depotBuffer, + extBlockOffset * sizeof(ULONG), + &blockIndex); + + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + } + + return blockIndex; +} + +/****************************************************************************** + * Storage32Impl_SetExtDepotBlock + * + * Associates the specified block index to the specified depot index. + * This method is only for depot indexes equal or greater than + * COUNT_BBDEPOTINHEADER. + */ +void Storage32Impl_SetExtDepotBlock(StorageImpl* This, + ULONG depotIndex, + ULONG blockIndex) +{ + ULONG depotBlocksPerExtBlock = (This->bigBlockSize / sizeof(ULONG)) - 1; + ULONG numExtBlocks = depotIndex - COUNT_BBDEPOTINHEADER; + ULONG extBlockCount = numExtBlocks / depotBlocksPerExtBlock; + ULONG extBlockOffset = numExtBlocks % depotBlocksPerExtBlock; + ULONG extBlockIndex = This->extBigBlockDepotStart; + + assert(depotIndex >= COUNT_BBDEPOTINHEADER); + + while (extBlockCount > 0) + { + extBlockIndex = Storage32Impl_GetNextExtendedBlock(This, extBlockIndex); + extBlockCount--; + } + + if (extBlockIndex != BLOCK_UNUSED) + { + BYTE* depotBuffer; + + depotBuffer = StorageImpl_GetBigBlock(This, extBlockIndex); + + if (depotBuffer != 0) + { + StorageUtl_WriteDWord(depotBuffer, + extBlockOffset * sizeof(ULONG), + blockIndex); + + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + } +} + +/****************************************************************************** + * Storage32Impl_AddExtBlockDepot + * + * Creates an extended depot block. + */ +ULONG Storage32Impl_AddExtBlockDepot(StorageImpl* This) +{ + ULONG numExtBlocks = This->extBigBlockDepotCount; + ULONG nextExtBlock = This->extBigBlockDepotStart; + BYTE* depotBuffer = NULL; + ULONG index = BLOCK_UNUSED; + ULONG nextBlockOffset = This->bigBlockSize - sizeof(ULONG); + ULONG blocksPerDepotBlock = This->bigBlockSize / sizeof(ULONG); + ULONG depotBlocksPerExtBlock = blocksPerDepotBlock - 1; + + index = (COUNT_BBDEPOTINHEADER + (numExtBlocks * depotBlocksPerExtBlock)) * + blocksPerDepotBlock; + + if ((numExtBlocks == 0) && (nextExtBlock == BLOCK_END_OF_CHAIN)) + { + /* + * The first extended block. + */ + This->extBigBlockDepotStart = index; + } + else + { + int i; + /* + * Follow the chain to the last one. + */ + for (i = 0; i < (numExtBlocks - 1); i++) + { + nextExtBlock = Storage32Impl_GetNextExtendedBlock(This, nextExtBlock); + } + + /* + * Add the new extended block to the chain. + */ + depotBuffer = StorageImpl_GetBigBlock(This, nextExtBlock); + StorageUtl_WriteDWord(depotBuffer, nextBlockOffset, index); + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + + /* + * Initialize this block. + */ + depotBuffer = StorageImpl_GetBigBlock(This, index); + memset(depotBuffer, BLOCK_UNUSED, This->bigBlockSize); + StorageImpl_ReleaseBigBlock(This, depotBuffer); + + return index; +} + +/****************************************************************************** + * Storage32Impl_FreeBigBlock + * + * This method will flag the specified block as free in the big block depot. + */ +void StorageImpl_FreeBigBlock( + StorageImpl* This, + ULONG blockIndex) +{ + StorageImpl_SetNextBlockInChain(This, blockIndex, BLOCK_UNUSED); + + if (blockIndex < This->prevFreeBlock) + This->prevFreeBlock = blockIndex; +} + +/************************************************************************ + * Storage32Impl_GetNextBlockInChain + * + * This method will retrieve the block index of the next big block in + * in the chain. + * + * Params: This - Pointer to the Storage object. + * blockIndex - Index of the block to retrieve the chain + * for. + * + * Returns: This method returns the index of the next block in the chain. + * It will return the constants: + * BLOCK_SPECIAL - If the block given was not part of a + * chain. + * BLOCK_END_OF_CHAIN - If the block given was the last in + * a chain. + * BLOCK_UNUSED - If the block given was not past of a chain + * and is available. + * BLOCK_EXTBBDEPOT - This block is part of the extended + * big block depot. + * + * See Windows documentation for more details on IStorage methods. + */ +ULONG StorageImpl_GetNextBlockInChain( + StorageImpl* This, + ULONG blockIndex) +{ + ULONG offsetInDepot = blockIndex * sizeof (ULONG); + ULONG depotBlockCount = offsetInDepot / This->bigBlockSize; + ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize; + ULONG nextBlockIndex = BLOCK_SPECIAL; + void* depotBuffer; + ULONG depotBlockIndexPos; + + assert(depotBlockCount < This->bigBlockDepotCount); + + /* + * Cache the currently accessed depot block. + */ + if (depotBlockCount != This->indexBlockDepotCached) + { + This->indexBlockDepotCached = depotBlockCount; + + if (depotBlockCount < COUNT_BBDEPOTINHEADER) + { + depotBlockIndexPos = This->bigBlockDepotStart[depotBlockCount]; + } + else + { + /* + * We have to look in the extended depot. + */ + depotBlockIndexPos = Storage32Impl_GetExtDepotBlock(This, depotBlockCount); + } + + depotBuffer = StorageImpl_GetROBigBlock(This, depotBlockIndexPos); + + if (depotBuffer!=0) + { + int index; + + for (index = 0; index < NUM_BLOCKS_PER_DEPOT_BLOCK; index++) + { + StorageUtl_ReadDWord(depotBuffer, index*sizeof(ULONG), &nextBlockIndex); + This->blockDepotCached[index] = nextBlockIndex; + } + + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + } + + nextBlockIndex = This->blockDepotCached[depotBlockOffset/sizeof(ULONG)]; + + return nextBlockIndex; +} + +/****************************************************************************** + * Storage32Impl_GetNextExtendedBlock + * + * Given an extended block this method will return the next extended block. + * + * NOTES: + * The last ULONG of an extended block is the block index of the next + * extended block. Extended blocks are marked as BLOCK_EXTBBDEPOT in the + * depot. + * + * Return values: + * - The index of the next extended block + * - BLOCK_UNUSED: there is no next extended block. + * - Any other return values denotes failure. + */ +ULONG Storage32Impl_GetNextExtendedBlock(StorageImpl* This, ULONG blockIndex) +{ + ULONG nextBlockIndex = BLOCK_SPECIAL; + ULONG depotBlockOffset = This->bigBlockSize - sizeof(ULONG); + void* depotBuffer; + + depotBuffer = StorageImpl_GetROBigBlock(This, blockIndex); + + if (depotBuffer!=0) + { + StorageUtl_ReadDWord(depotBuffer, depotBlockOffset, &nextBlockIndex); + + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + + return nextBlockIndex; +} + +/****************************************************************************** + * Storage32Impl_SetNextBlockInChain + * + * This method will write the index of the specified block's next block + * in the big block depot. + * + * For example: to create the chain 3 -> 1 -> 7 -> End of Chain + * do the following + * + * Storage32Impl_SetNextBlockInChain(This, 3, 1); + * Storage32Impl_SetNextBlockInChain(This, 1, 7); + * Storage32Impl_SetNextBlockInChain(This, 7, BLOCK_END_OF_CHAIN); + * + */ +void StorageImpl_SetNextBlockInChain( + StorageImpl* This, + ULONG blockIndex, + ULONG nextBlock) +{ + ULONG offsetInDepot = blockIndex * sizeof (ULONG); + ULONG depotBlockCount = offsetInDepot / This->bigBlockSize; + ULONG depotBlockOffset = offsetInDepot % This->bigBlockSize; + ULONG depotBlockIndexPos; + void* depotBuffer; + + assert(depotBlockCount < This->bigBlockDepotCount); + assert(blockIndex != nextBlock); + + if (depotBlockCount < COUNT_BBDEPOTINHEADER) + { + depotBlockIndexPos = This->bigBlockDepotStart[depotBlockCount]; + } + else + { + /* + * We have to look in the extended depot. + */ + depotBlockIndexPos = Storage32Impl_GetExtDepotBlock(This, depotBlockCount); + } + + depotBuffer = StorageImpl_GetBigBlock(This, depotBlockIndexPos); + + if (depotBuffer!=0) + { + StorageUtl_WriteDWord(depotBuffer, depotBlockOffset, nextBlock); + StorageImpl_ReleaseBigBlock(This, depotBuffer); + } + + /* + * Update the cached block depot, if necessary. + */ + if (depotBlockCount == This->indexBlockDepotCached) + { + This->blockDepotCached[depotBlockOffset/sizeof(ULONG)] = nextBlock; + } +} + +/****************************************************************************** + * Storage32Impl_LoadFileHeader + * + * This method will read in the file header, i.e. big block index -1. + */ +HRESULT StorageImpl_LoadFileHeader( + StorageImpl* This) +{ + HRESULT hr = STG_E_FILENOTFOUND; + void* headerBigBlock = NULL; + int index; + + /* + * Get a pointer to the big block of data containing the header. + */ + headerBigBlock = StorageImpl_GetROBigBlock(This, -1); + + /* + * Extract the information from the header. + */ + if (headerBigBlock!=0) + { + /* + * Check for the "magic number" signature and return an error if it is not + * found. + */ + if (memcmp(headerBigBlock, STORAGE_oldmagic, sizeof(STORAGE_oldmagic))==0) + { + StorageImpl_ReleaseBigBlock(This, headerBigBlock); + return STG_E_OLDFORMAT; + } + + if (memcmp(headerBigBlock, STORAGE_magic, sizeof(STORAGE_magic))!=0) + { + StorageImpl_ReleaseBigBlock(This, headerBigBlock); + return STG_E_INVALIDHEADER; + } + + StorageUtl_ReadWord( + headerBigBlock, + OFFSET_BIGBLOCKSIZEBITS, + &This->bigBlockSizeBits); + + StorageUtl_ReadWord( + headerBigBlock, + OFFSET_SMALLBLOCKSIZEBITS, + &This->smallBlockSizeBits); + + StorageUtl_ReadDWord( + headerBigBlock, + OFFSET_BBDEPOTCOUNT, + &This->bigBlockDepotCount); + + StorageUtl_ReadDWord( + headerBigBlock, + OFFSET_ROOTSTARTBLOCK, + &This->rootStartBlock); + + StorageUtl_ReadDWord( + headerBigBlock, + OFFSET_SBDEPOTSTART, + &This->smallBlockDepotStart); + + StorageUtl_ReadDWord( + headerBigBlock, + OFFSET_EXTBBDEPOTSTART, + &This->extBigBlockDepotStart); + + StorageUtl_ReadDWord( + headerBigBlock, + OFFSET_EXTBBDEPOTCOUNT, + &This->extBigBlockDepotCount); + + for (index = 0; index < COUNT_BBDEPOTINHEADER; index ++) + { + StorageUtl_ReadDWord( + headerBigBlock, + OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index), + &(This->bigBlockDepotStart[index])); + } + + /* + * Make the bitwise arithmetic to get the size of the blocks in bytes. + */ + if ((1 << 2) == 4) + { + This->bigBlockSize = 0x000000001 << (DWORD)This->bigBlockSizeBits; + This->smallBlockSize = 0x000000001 << (DWORD)This->smallBlockSizeBits; + } + else + { + This->bigBlockSize = 0x000000001 >> (DWORD)This->bigBlockSizeBits; + This->smallBlockSize = 0x000000001 >> (DWORD)This->smallBlockSizeBits; + } + + /* + * Right now, the code is making some assumptions about the size of the + * blocks, just make sure they are what we're expecting. + */ + assert( (This->bigBlockSize==DEF_BIG_BLOCK_SIZE) && + (This->smallBlockSize==DEF_SMALL_BLOCK_SIZE)); + + /* + * Release the block. + */ + StorageImpl_ReleaseBigBlock(This, headerBigBlock); + + hr = S_OK; + } + + return hr; +} + +/****************************************************************************** + * Storage32Impl_SaveFileHeader + * + * This method will save to the file the header, i.e. big block -1. + */ +void StorageImpl_SaveFileHeader( + StorageImpl* This) +{ + BYTE headerBigBlock[BIG_BLOCK_SIZE]; + int index; + BOOL success; + + /* + * Get a pointer to the big block of data containing the header. + */ + success = StorageImpl_ReadBigBlock(This, -1, headerBigBlock); + + /* + * If the block read failed, the file is probably new. + */ + if (!success) + { + /* + * Initialize for all unknown fields. + */ + memset(headerBigBlock, 0, BIG_BLOCK_SIZE); + + /* + * Initialize the magic number. + */ + memcpy(headerBigBlock, STORAGE_magic, sizeof(STORAGE_magic)); + + /* + * And a bunch of things we don't know what they mean + */ + StorageUtl_WriteWord(headerBigBlock, 0x18, 0x3b); + StorageUtl_WriteWord(headerBigBlock, 0x1a, 0x3); + StorageUtl_WriteWord(headerBigBlock, 0x1c, (WORD)-2); + StorageUtl_WriteDWord(headerBigBlock, 0x38, (DWORD)0x1000); + StorageUtl_WriteDWord(headerBigBlock, 0x40, (DWORD)0x0001); + } + + /* + * Write the information to the header. + */ + if (headerBigBlock!=0) + { + StorageUtl_WriteWord( + headerBigBlock, + OFFSET_BIGBLOCKSIZEBITS, + This->bigBlockSizeBits); + + StorageUtl_WriteWord( + headerBigBlock, + OFFSET_SMALLBLOCKSIZEBITS, + This->smallBlockSizeBits); + + StorageUtl_WriteDWord( + headerBigBlock, + OFFSET_BBDEPOTCOUNT, + This->bigBlockDepotCount); + + StorageUtl_WriteDWord( + headerBigBlock, + OFFSET_ROOTSTARTBLOCK, + This->rootStartBlock); + + StorageUtl_WriteDWord( + headerBigBlock, + OFFSET_SBDEPOTSTART, + This->smallBlockDepotStart); + + StorageUtl_WriteDWord( + headerBigBlock, + OFFSET_EXTBBDEPOTSTART, + This->extBigBlockDepotStart); + + StorageUtl_WriteDWord( + headerBigBlock, + OFFSET_EXTBBDEPOTCOUNT, + This->extBigBlockDepotCount); + + for (index = 0; index < COUNT_BBDEPOTINHEADER; index ++) + { + StorageUtl_WriteDWord( + headerBigBlock, + OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index), + (This->bigBlockDepotStart[index])); + } + } + + /* + * Write the big block back to the file. + */ + StorageImpl_WriteBigBlock(This, -1, headerBigBlock); +} + +/****************************************************************************** + * Storage32Impl_ReadProperty + * + * This method will read the specified property from the property chain. + */ +BOOL StorageImpl_ReadProperty( + StorageImpl* This, + ULONG index, + StgProperty* buffer) +{ + BYTE currentProperty[PROPSET_BLOCK_SIZE]; + ULARGE_INTEGER offsetInPropSet; + BOOL readSuccessful; + ULONG bytesRead; + + offsetInPropSet.u.HighPart = 0; + offsetInPropSet.u.LowPart = index * PROPSET_BLOCK_SIZE; + + readSuccessful = BlockChainStream_ReadAt( + This->rootBlockChain, + offsetInPropSet, + PROPSET_BLOCK_SIZE, + currentProperty, + &bytesRead); + + if (readSuccessful) + { + memset(buffer->name, 0, sizeof(buffer->name)); + memcpy( + buffer->name, + currentProperty+OFFSET_PS_NAME, + PROPERTY_NAME_BUFFER_LEN ); + + memcpy(&buffer->propertyType, currentProperty + OFFSET_PS_PROPERTYTYPE, 1); + + StorageUtl_ReadWord( + currentProperty, + OFFSET_PS_NAMELENGTH, + &buffer->sizeOfNameString); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_PREVIOUSPROP, + &buffer->previousProperty); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_NEXTPROP, + &buffer->nextProperty); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_DIRPROP, + &buffer->dirProperty); + + StorageUtl_ReadGUID( + currentProperty, + OFFSET_PS_GUID, + &buffer->propertyUniqueID); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSS1, + &buffer->timeStampS1); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSD1, + &buffer->timeStampD1); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSS2, + &buffer->timeStampS2); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSD2, + &buffer->timeStampD2); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_STARTBLOCK, + &buffer->startingBlock); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_SIZE, + &buffer->size.u.LowPart); + + buffer->size.u.HighPart = 0; + } + + return readSuccessful; +} + +/********************************************************************* + * Write the specified property into the property chain + */ +BOOL StorageImpl_WriteProperty( + StorageImpl* This, + ULONG index, + StgProperty* buffer) +{ + BYTE currentProperty[PROPSET_BLOCK_SIZE]; + ULARGE_INTEGER offsetInPropSet; + BOOL writeSuccessful; + ULONG bytesWritten; + + offsetInPropSet.u.HighPart = 0; + offsetInPropSet.u.LowPart = index * PROPSET_BLOCK_SIZE; + + memset(currentProperty, 0, PROPSET_BLOCK_SIZE); + + memcpy( + currentProperty + OFFSET_PS_NAME, + buffer->name, + PROPERTY_NAME_BUFFER_LEN ); + + memcpy(currentProperty + OFFSET_PS_PROPERTYTYPE, &buffer->propertyType, 1); + + StorageUtl_WriteWord( + currentProperty, + OFFSET_PS_NAMELENGTH, + buffer->sizeOfNameString); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_PREVIOUSPROP, + buffer->previousProperty); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_NEXTPROP, + buffer->nextProperty); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_DIRPROP, + buffer->dirProperty); + + StorageUtl_WriteGUID( + currentProperty, + OFFSET_PS_GUID, + &buffer->propertyUniqueID); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_TSS1, + buffer->timeStampS1); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_TSD1, + buffer->timeStampD1); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_TSS2, + buffer->timeStampS2); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_TSD2, + buffer->timeStampD2); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_STARTBLOCK, + buffer->startingBlock); + + StorageUtl_WriteDWord( + currentProperty, + OFFSET_PS_SIZE, + buffer->size.u.LowPart); + + writeSuccessful = BlockChainStream_WriteAt(This->rootBlockChain, + offsetInPropSet, + PROPSET_BLOCK_SIZE, + currentProperty, + &bytesWritten); + return writeSuccessful; +} + +BOOL StorageImpl_ReadBigBlock( + StorageImpl* This, + ULONG blockIndex, + void* buffer) +{ + void* bigBlockBuffer; + + bigBlockBuffer = StorageImpl_GetROBigBlock(This, blockIndex); + + if (bigBlockBuffer!=0) + { + memcpy(buffer, bigBlockBuffer, This->bigBlockSize); + + StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); + + return TRUE; + } + + return FALSE; +} + +BOOL StorageImpl_WriteBigBlock( + StorageImpl* This, + ULONG blockIndex, + void* buffer) +{ + void* bigBlockBuffer; + + bigBlockBuffer = StorageImpl_GetBigBlock(This, blockIndex); + + if (bigBlockBuffer!=0) + { + memcpy(bigBlockBuffer, buffer, This->bigBlockSize); + + StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); + + return TRUE; + } + + return FALSE; +} + +void* StorageImpl_GetROBigBlock( + StorageImpl* This, + ULONG blockIndex) +{ + return BIGBLOCKFILE_GetROBigBlock(This->bigBlockFile, blockIndex); +} + +void* StorageImpl_GetBigBlock( + StorageImpl* This, + ULONG blockIndex) +{ + return BIGBLOCKFILE_GetBigBlock(This->bigBlockFile, blockIndex); +} + +void StorageImpl_ReleaseBigBlock( + StorageImpl* This, + void* pBigBlock) +{ + BIGBLOCKFILE_ReleaseBigBlock(This->bigBlockFile, pBigBlock); +} + +/****************************************************************************** + * Storage32Impl_SmallBlocksToBigBlocks + * + * This method will convert a small block chain to a big block chain. + * The small block chain will be destroyed. + */ +BlockChainStream* Storage32Impl_SmallBlocksToBigBlocks( + StorageImpl* This, + SmallBlockChainStream** ppsbChain) +{ + ULONG bbHeadOfChain = BLOCK_END_OF_CHAIN; + ULARGE_INTEGER size, offset; + ULONG cbRead, cbWritten, cbTotalRead, cbTotalWritten; + ULONG propertyIndex; + BOOL successRead, successWrite; + StgProperty chainProperty; + BYTE *buffer; + BlockChainStream *bbTempChain = NULL; + BlockChainStream *bigBlockChain = NULL; + + /* + * Create a temporary big block chain that doesn't have + * an associated property. This temporary chain will be + * used to copy data from small blocks to big blocks. + */ + bbTempChain = BlockChainStream_Construct(This, + &bbHeadOfChain, + PROPERTY_NULL); + + /* + * Grow the big block chain. + */ + size = SmallBlockChainStream_GetSize(*ppsbChain); + BlockChainStream_SetSize(bbTempChain, size); + + /* + * Copy the contents of the small block chain to the big block chain + * by small block size increments. + */ + offset.u.LowPart = 0; + offset.u.HighPart = 0; + cbTotalRead = 0; + cbTotalWritten = 0; + + buffer = (BYTE *) HeapAlloc(GetProcessHeap(),0,DEF_SMALL_BLOCK_SIZE); + do + { + successRead = SmallBlockChainStream_ReadAt(*ppsbChain, + offset, + DEF_SMALL_BLOCK_SIZE, + buffer, + &cbRead); + cbTotalRead += cbRead; + + successWrite = BlockChainStream_WriteAt(bbTempChain, + offset, + cbRead, + buffer, + &cbWritten); + cbTotalWritten += cbWritten; + + offset.u.LowPart += This->smallBlockSize; + + } while (successRead && successWrite); + HeapFree(GetProcessHeap(),0,buffer); + + assert(cbTotalRead == cbTotalWritten); + + /* + * Destroy the small block chain. + */ + propertyIndex = (*ppsbChain)->ownerPropertyIndex; + size.u.HighPart = 0; + size.u.LowPart = 0; + SmallBlockChainStream_SetSize(*ppsbChain, size); + SmallBlockChainStream_Destroy(*ppsbChain); + *ppsbChain = 0; + + /* + * Change the property information. This chain is now a big block chain + * and it doesn't reside in the small blocks chain anymore. + */ + StorageImpl_ReadProperty(This, propertyIndex, &chainProperty); + + chainProperty.startingBlock = bbHeadOfChain; + + StorageImpl_WriteProperty(This, propertyIndex, &chainProperty); + + /* + * Destroy the temporary propertyless big block chain. + * Create a new big block chain associated with this property. + */ + BlockChainStream_Destroy(bbTempChain); + bigBlockChain = BlockChainStream_Construct(This, + NULL, + propertyIndex); + + return bigBlockChain; +} + +/****************************************************************************** +** Storage32InternalImpl implementation +*/ + +StorageInternalImpl* StorageInternalImpl_Construct( + StorageImpl* ancestorStorage, + ULONG rootPropertyIndex) +{ + StorageInternalImpl* newStorage; + + /* + * Allocate space for the new storage object + */ + newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageInternalImpl)); + + if (newStorage!=0) + { + memset(newStorage, 0, sizeof(StorageInternalImpl)); + + /* + * Initialize the virtual function table. + */ + ICOM_VTBL(newStorage) = &Storage32InternalImpl_Vtbl; + newStorage->v_destructor = &StorageInternalImpl_Destroy; + + /* + * Keep the ancestor storage pointer and nail a reference to it. + */ + newStorage->ancestorStorage = ancestorStorage; + StorageBaseImpl_AddRef((IStorage*)(newStorage->ancestorStorage)); + + /* + * Keep the index of the root property set for this storage, + */ + newStorage->rootPropertySetIndex = rootPropertyIndex; + + return newStorage; + } + + return 0; +} + +void StorageInternalImpl_Destroy( + StorageInternalImpl* This) +{ + StorageBaseImpl_Release((IStorage*)This->ancestorStorage); + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** +** +** Storage32InternalImpl_Commit +** +** The non-root storages cannot be opened in transacted mode thus this function +** does nothing. +*/ +HRESULT WINAPI StorageInternalImpl_Commit( + IStorage* iface, + DWORD grfCommitFlags) /* [in] */ +{ + return S_OK; +} + +/****************************************************************************** +** +** Storage32InternalImpl_Revert +** +** The non-root storages cannot be opened in transacted mode thus this function +** does nothing. +*/ +HRESULT WINAPI StorageInternalImpl_Revert( + IStorage* iface) +{ + return S_OK; +} + +/****************************************************************************** +** IEnumSTATSTGImpl implementation +*/ + +IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct( + StorageImpl* parentStorage, + ULONG firstPropertyNode) +{ + IEnumSTATSTGImpl* newEnumeration; + + newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl)); + + if (newEnumeration!=0) + { + /* + * Set-up the virtual function table and reference count. + */ + ICOM_VTBL(newEnumeration) = &IEnumSTATSTGImpl_Vtbl; + newEnumeration->ref = 0; + + /* + * We want to nail-down the reference to the storage in case the + * enumeration out-lives the storage in the client application. + */ + newEnumeration->parentStorage = parentStorage; + IStorage_AddRef((IStorage*)newEnumeration->parentStorage); + + newEnumeration->firstPropertyNode = firstPropertyNode; + + /* + * Initialize the search stack + */ + newEnumeration->stackSize = 0; + newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT; + newEnumeration->stackToVisit = + HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG)*ENUMSTATSGT_SIZE_INCREMENT); + + /* + * Make sure the current node of the iterator is the first one. + */ + IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration); + } + + return newEnumeration; +} + +void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This) +{ + IStorage_Release((IStorage*)This->parentStorage); + HeapFree(GetProcessHeap(), 0, This->stackToVisit); + HeapFree(GetProcessHeap(), 0, This); +} + +HRESULT WINAPI IEnumSTATSTGImpl_QueryInterface( + IEnumSTATSTG* iface, + REFIID riid, + void** ppvObject) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + /* + * Perform a sanity check on the parameters. + */ + if (ppvObject==0) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) + { + *ppvObject = (IEnumSTATSTG*)This; + } + else if (memcmp(&IID_IStorage, riid, sizeof(IID_IEnumSTATSTG)) == 0) + { + *ppvObject = (IEnumSTATSTG*)This; + } + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* + * Query Interface always increases the reference count by one when it is + * successful + */ + IEnumSTATSTGImpl_AddRef((IEnumSTATSTG*)This); + + return S_OK; +} + +ULONG WINAPI IEnumSTATSTGImpl_AddRef( + IEnumSTATSTG* iface) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + This->ref++; + return This->ref; +} + +ULONG WINAPI IEnumSTATSTGImpl_Release( + IEnumSTATSTG* iface) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + ULONG newRef; + + This->ref--; + newRef = This->ref; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (newRef==0) + { + IEnumSTATSTGImpl_Destroy(This); + } + + return newRef;; +} + +HRESULT WINAPI IEnumSTATSTGImpl_Next( + IEnumSTATSTG* iface, + ULONG celt, + STATSTG* rgelt, + ULONG* pceltFetched) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + StgProperty currentProperty; + STATSTG* currentReturnStruct = rgelt; + ULONG objectFetched = 0; + ULONG currentSearchNode; + + /* + * Perform a sanity check on the parameters. + */ + if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) ) + return E_INVALIDARG; + + /* + * To avoid the special case, get another pointer to a ULONG value if + * the caller didn't supply one. + */ + if (pceltFetched==0) + pceltFetched = &objectFetched; + + /* + * Start the iteration, we will iterate until we hit the end of the + * linked list or until we hit the number of items to iterate through + */ + *pceltFetched = 0; + + /* + * Start with the node at the top of the stack. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + + while ( ( *pceltFetched < celt) && + ( currentSearchNode!=PROPERTY_NULL) ) + { + /* + * Remove the top node from the stack + */ + IEnumSTATSTGImpl_PopSearchNode(This, TRUE); + + /* + * Read the property from the storage. + */ + StorageImpl_ReadProperty(This->parentStorage, + currentSearchNode, + ¤tProperty); + + /* + * Copy the information to the return buffer. + */ + StorageUtl_CopyPropertyToSTATSTG(currentReturnStruct, + ¤tProperty, + STATFLAG_DEFAULT); + + /* + * Step to the next item in the iteration + */ + (*pceltFetched)++; + currentReturnStruct++; + + /* + * Push the next search node in the search stack. + */ + IEnumSTATSTGImpl_PushSearchNode(This, currentProperty.nextProperty); + + /* + * continue the iteration. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + } + + if (*pceltFetched == celt) + return S_OK; + + return S_FALSE; +} + + +HRESULT WINAPI IEnumSTATSTGImpl_Skip( + IEnumSTATSTG* iface, + ULONG celt) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + StgProperty currentProperty; + ULONG objectFetched = 0; + ULONG currentSearchNode; + + /* + * Start with the node at the top of the stack. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + + while ( (objectFetched < celt) && + (currentSearchNode!=PROPERTY_NULL) ) + { + /* + * Remove the top node from the stack + */ + IEnumSTATSTGImpl_PopSearchNode(This, TRUE); + + /* + * Read the property from the storage. + */ + StorageImpl_ReadProperty(This->parentStorage, + currentSearchNode, + ¤tProperty); + + /* + * Step to the next item in the iteration + */ + objectFetched++; + + /* + * Push the next search node in the search stack. + */ + IEnumSTATSTGImpl_PushSearchNode(This, currentProperty.nextProperty); + + /* + * continue the iteration. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + } + + if (objectFetched == celt) + return S_OK; + + return S_FALSE; +} + +HRESULT WINAPI IEnumSTATSTGImpl_Reset( + IEnumSTATSTG* iface) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + StgProperty rootProperty; + BOOL readSuccessful; + + /* + * Re-initialize the search stack to an empty stack + */ + This->stackSize = 0; + + /* + * Read the root property from the storage. + */ + readSuccessful = StorageImpl_ReadProperty( + This->parentStorage, + This->firstPropertyNode, + &rootProperty); + + if (readSuccessful) + { + assert(rootProperty.sizeOfNameString!=0); + + /* + * Push the search node in the search stack. + */ + IEnumSTATSTGImpl_PushSearchNode(This, rootProperty.dirProperty); + } + + return S_OK; +} + +HRESULT WINAPI IEnumSTATSTGImpl_Clone( + IEnumSTATSTG* iface, + IEnumSTATSTG** ppenum) +{ + IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; + + IEnumSTATSTGImpl* newClone; + + /* + * Perform a sanity check on the parameters. + */ + if (ppenum==0) + return E_INVALIDARG; + + newClone = IEnumSTATSTGImpl_Construct(This->parentStorage, + This->firstPropertyNode); + + + /* + * The new clone enumeration must point to the same current node as + * the ole one. + */ + newClone->stackSize = This->stackSize ; + newClone->stackMaxSize = This->stackMaxSize ; + newClone->stackToVisit = + HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG) * newClone->stackMaxSize); + + memcpy( + newClone->stackToVisit, + This->stackToVisit, + sizeof(ULONG) * newClone->stackSize); + + *ppenum = (IEnumSTATSTG*)newClone; + + /* + * Don't forget to nail down a reference to the clone before + * returning it. + */ + IEnumSTATSTGImpl_AddRef(*ppenum); + + return S_OK; +} + +INT IEnumSTATSTGImpl_FindParentProperty( + IEnumSTATSTGImpl *This, + ULONG childProperty, + StgProperty *currentProperty, + ULONG *thisNodeId) +{ + ULONG currentSearchNode; + ULONG foundNode; + + /* + * To avoid the special case, get another pointer to a ULONG value if + * the caller didn't supply one. + */ + if (thisNodeId==0) + thisNodeId = &foundNode; + + /* + * Start with the node at the top of the stack. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + + + while (currentSearchNode!=PROPERTY_NULL) + { + /* + * Store the current node in the returned parameters + */ + *thisNodeId = currentSearchNode; + + /* + * Remove the top node from the stack + */ + IEnumSTATSTGImpl_PopSearchNode(This, TRUE); + + /* + * Read the property from the storage. + */ + StorageImpl_ReadProperty( + This->parentStorage, + currentSearchNode, + currentProperty); + + if (currentProperty->previousProperty == childProperty) + return PROPERTY_RELATION_PREVIOUS; + + else if (currentProperty->nextProperty == childProperty) + return PROPERTY_RELATION_NEXT; + + else if (currentProperty->dirProperty == childProperty) + return PROPERTY_RELATION_DIR; + + /* + * Push the next search node in the search stack. + */ + IEnumSTATSTGImpl_PushSearchNode(This, currentProperty->nextProperty); + + /* + * continue the iteration. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + } + + return PROPERTY_NULL; +} + +ULONG IEnumSTATSTGImpl_FindProperty( + IEnumSTATSTGImpl* This, + const OLECHAR* lpszPropName, + StgProperty* currentProperty) +{ + ULONG currentSearchNode; + + /* + * Start with the node at the top of the stack. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + + while (currentSearchNode!=PROPERTY_NULL) + { + /* + * Remove the top node from the stack + */ + IEnumSTATSTGImpl_PopSearchNode(This, TRUE); + + /* + * Read the property from the storage. + */ + StorageImpl_ReadProperty(This->parentStorage, + currentSearchNode, + currentProperty); + + if ( propertyNameCmp( + (OLECHAR*)currentProperty->name, + (OLECHAR*)lpszPropName) == 0) + return currentSearchNode; + + /* + * Push the next search node in the search stack. + */ + IEnumSTATSTGImpl_PushSearchNode(This, currentProperty->nextProperty); + + /* + * continue the iteration. + */ + currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); + } + + return PROPERTY_NULL; +} + +void IEnumSTATSTGImpl_PushSearchNode( + IEnumSTATSTGImpl* This, + ULONG nodeToPush) +{ + StgProperty rootProperty; + BOOL readSuccessful; + + /* + * First, make sure we're not trying to push an unexisting node. + */ + if (nodeToPush==PROPERTY_NULL) + return; + + /* + * First push the node to the stack + */ + if (This->stackSize == This->stackMaxSize) + { + This->stackMaxSize += ENUMSTATSGT_SIZE_INCREMENT; + + This->stackToVisit = HeapReAlloc( + GetProcessHeap(), + 0, + This->stackToVisit, + sizeof(ULONG) * This->stackMaxSize); + } + + This->stackToVisit[This->stackSize] = nodeToPush; + This->stackSize++; + + /* + * Read the root property from the storage. + */ + readSuccessful = StorageImpl_ReadProperty( + This->parentStorage, + nodeToPush, + &rootProperty); + + if (readSuccessful) + { + assert(rootProperty.sizeOfNameString!=0); + + /* + * Push the previous search node in the search stack. + */ + IEnumSTATSTGImpl_PushSearchNode(This, rootProperty.previousProperty); + } +} + +ULONG IEnumSTATSTGImpl_PopSearchNode( + IEnumSTATSTGImpl* This, + BOOL remove) +{ + ULONG topNode; + + if (This->stackSize == 0) + return PROPERTY_NULL; + + topNode = This->stackToVisit[This->stackSize-1]; + + if (remove) + This->stackSize--; + + return topNode; +} + +/****************************************************************************** +** StorageUtl implementation +*/ + +void StorageUtl_ReadWord(void* buffer, ULONG offset, WORD* value) +{ + memcpy(value, (BYTE*)buffer+offset, sizeof(WORD)); +} + +void StorageUtl_WriteWord(void* buffer, ULONG offset, WORD value) +{ + memcpy((BYTE*)buffer+offset, &value, sizeof(WORD)); +} + +void StorageUtl_ReadDWord(void* buffer, ULONG offset, DWORD* value) +{ + memcpy(value, (BYTE*)buffer+offset, sizeof(DWORD)); +} + +void StorageUtl_WriteDWord(void* buffer, ULONG offset, DWORD value) +{ + memcpy((BYTE*)buffer+offset, &value, sizeof(DWORD)); +} + +void StorageUtl_ReadGUID(void* buffer, ULONG offset, GUID* value) +{ + StorageUtl_ReadDWord(buffer, offset, &(value->Data1)); + StorageUtl_ReadWord(buffer, offset+4, &(value->Data2)); + StorageUtl_ReadWord(buffer, offset+6, &(value->Data3)); + + memcpy(value->Data4, (BYTE*)buffer+offset+8, sizeof(value->Data4)); +} + +void StorageUtl_WriteGUID(void* buffer, ULONG offset, GUID* value) +{ + StorageUtl_WriteDWord(buffer, offset, value->Data1); + StorageUtl_WriteWord(buffer, offset+4, value->Data2); + StorageUtl_WriteWord(buffer, offset+6, value->Data3); + + memcpy((BYTE*)buffer+offset+8, value->Data4, sizeof(value->Data4)); +} + +void StorageUtl_CopyPropertyToSTATSTG( + STATSTG* destination, + StgProperty* source, + int statFlags) +{ + /* + * The copy of the string occurs only when the flag is not set + */ + if ((statFlags & STATFLAG_NONAME) != 0) + { + destination->pwcsName = 0; + } + else + { + destination->pwcsName = + CoTaskMemAlloc((lstrlenW(source->name)+1)*sizeof(WCHAR)); + + lstrcpyW((LPWSTR)destination->pwcsName, source->name); + } + + switch (source->propertyType) + { + case PROPTYPE_STORAGE: + case PROPTYPE_ROOT: + destination->type = STGTY_STORAGE; + break; + case PROPTYPE_STREAM: + destination->type = STGTY_STREAM; + break; + default: + destination->type = STGTY_STREAM; + break; + } + + destination->cbSize = source->size; +/* + currentReturnStruct->mtime = {0}; TODO + currentReturnStruct->ctime = {0}; + currentReturnStruct->atime = {0}; +*/ + destination->grfMode = 0; + destination->grfLocksSupported = 0; + destination->clsid = source->propertyUniqueID; + destination->grfStateBits = 0; + destination->reserved = 0; +} + +/****************************************************************************** +** BlockChainStream implementation +*/ + +BlockChainStream* BlockChainStream_Construct( + StorageImpl* parentStorage, + ULONG* headOfStreamPlaceHolder, + ULONG propertyIndex) +{ + BlockChainStream* newStream; + ULONG blockIndex; + + newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(BlockChainStream)); + + newStream->parentStorage = parentStorage; + newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder; + newStream->ownerPropertyIndex = propertyIndex; + newStream->lastBlockNoInSequence = 0xFFFFFFFF; + newStream->tailIndex = BLOCK_END_OF_CHAIN; + newStream->numBlocks = 0; + + blockIndex = BlockChainStream_GetHeadOfChain(newStream); + + while (blockIndex != BLOCK_END_OF_CHAIN) + { + newStream->numBlocks++; + newStream->tailIndex = blockIndex; + + blockIndex = StorageImpl_GetNextBlockInChain( + parentStorage, + blockIndex); + } + + return newStream; +} + +void BlockChainStream_Destroy(BlockChainStream* This) +{ + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** + * BlockChainStream_GetHeadOfChain + * + * Returns the head of this stream chain. + * Some special chains don't have properties, their heads are kept in + * This->headOfStreamPlaceHolder. + * + */ +ULONG BlockChainStream_GetHeadOfChain(BlockChainStream* This) +{ + StgProperty chainProperty; + BOOL readSuccessful; + + if (This->headOfStreamPlaceHolder != 0) + return *(This->headOfStreamPlaceHolder); + + if (This->ownerPropertyIndex != PROPERTY_NULL) + { + readSuccessful = StorageImpl_ReadProperty( + This->parentStorage, + This->ownerPropertyIndex, + &chainProperty); + + if (readSuccessful) + { + return chainProperty.startingBlock; + } + } + + return BLOCK_END_OF_CHAIN; +} + +/****************************************************************************** + * BlockChainStream_GetCount + * + * Returns the number of blocks that comprises this chain. + * This is not the size of the stream as the last block may not be full! + * + */ +ULONG BlockChainStream_GetCount(BlockChainStream* This) +{ + ULONG blockIndex; + ULONG count = 0; + + blockIndex = BlockChainStream_GetHeadOfChain(This); + + while (blockIndex != BLOCK_END_OF_CHAIN) + { + count++; + + blockIndex = StorageImpl_GetNextBlockInChain( + This->parentStorage, + blockIndex); + } + + return count; +} + +/****************************************************************************** + * BlockChainStream_ReadAt + * + * Reads a specified number of bytes from this chain at the specified offset. + * bytesRead may be NULL. + * Failure will be returned if the specified number of bytes has not been read. + */ +BOOL BlockChainStream_ReadAt(BlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + void* buffer, + ULONG* bytesRead) +{ + ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->bigBlockSize; + ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->bigBlockSize; + ULONG bytesToReadInBuffer; + ULONG blockIndex; + BYTE* bufferWalker; + BYTE* bigBlockBuffer; + + /* + * Find the first block in the stream that contains part of the buffer. + */ + if ( (This->lastBlockNoInSequence == 0xFFFFFFFF) || + (This->lastBlockNoInSequenceIndex == BLOCK_END_OF_CHAIN) || + (blockNoInSequence < This->lastBlockNoInSequence) ) + { + blockIndex = BlockChainStream_GetHeadOfChain(This); + This->lastBlockNoInSequence = blockNoInSequence; + } + else + { + ULONG temp = blockNoInSequence; + + blockIndex = This->lastBlockNoInSequenceIndex; + blockNoInSequence -= This->lastBlockNoInSequence; + This->lastBlockNoInSequence = temp; + } + + while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) + { + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); + + blockNoInSequence--; + } + + This->lastBlockNoInSequenceIndex = blockIndex; + + /* + * Start reading the buffer. + */ + *bytesRead = 0; + bufferWalker = buffer; + + while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) + { + /* + * Calculate how many bytes we can copy from this big block. + */ + bytesToReadInBuffer = + min(This->parentStorage->bigBlockSize - offsetInBlock, size); + + /* + * Copy those bytes to the buffer + */ + bigBlockBuffer = + StorageImpl_GetROBigBlock(This->parentStorage, blockIndex); + + memcpy(bufferWalker, bigBlockBuffer + offsetInBlock, bytesToReadInBuffer); + + StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer); + + /* + * Step to the next big block. + */ + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); + + bufferWalker += bytesToReadInBuffer; + size -= bytesToReadInBuffer; + *bytesRead += bytesToReadInBuffer; + offsetInBlock = 0; /* There is no offset on the next block */ + + } + + return (size == 0); +} + +/****************************************************************************** + * BlockChainStream_WriteAt + * + * Writes the specified number of bytes to this chain at the specified offset. + * bytesWritten may be NULL. + * Will fail if not all specified number of bytes have been written. + */ +BOOL BlockChainStream_WriteAt(BlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + const void* buffer, + ULONG* bytesWritten) +{ + ULONG blockNoInSequence = offset.u.LowPart / This->parentStorage->bigBlockSize; + ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->bigBlockSize; + ULONG bytesToWrite; + ULONG blockIndex; + BYTE* bufferWalker; + BYTE* bigBlockBuffer; + + /* + * Find the first block in the stream that contains part of the buffer. + */ + if ( (This->lastBlockNoInSequence == 0xFFFFFFFF) || + (This->lastBlockNoInSequenceIndex == BLOCK_END_OF_CHAIN) || + (blockNoInSequence < This->lastBlockNoInSequence) ) + { + blockIndex = BlockChainStream_GetHeadOfChain(This); + This->lastBlockNoInSequence = blockNoInSequence; + } + else + { + ULONG temp = blockNoInSequence; + + blockIndex = This->lastBlockNoInSequenceIndex; + blockNoInSequence -= This->lastBlockNoInSequence; + This->lastBlockNoInSequence = temp; + } + + while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) + { + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); + + blockNoInSequence--; + } + + This->lastBlockNoInSequenceIndex = blockIndex; + + /* + * Here, I'm casting away the constness on the buffer variable + * This is OK since we don't intend to modify that buffer. + */ + *bytesWritten = 0; + bufferWalker = (BYTE*)buffer; + + while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) + { + /* + * Calculate how many bytes we can copy from this big block. + */ + bytesToWrite = + min(This->parentStorage->bigBlockSize - offsetInBlock, size); + + /* + * Copy those bytes to the buffer + */ + bigBlockBuffer = StorageImpl_GetBigBlock(This->parentStorage, blockIndex); + + memcpy(bigBlockBuffer + offsetInBlock, bufferWalker, bytesToWrite); + + StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer); + + /* + * Step to the next big block. + */ + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); + + bufferWalker += bytesToWrite; + size -= bytesToWrite; + *bytesWritten += bytesToWrite; + offsetInBlock = 0; /* There is no offset on the next block */ + } + + return (size == 0); +} + +/****************************************************************************** + * BlockChainStream_Shrink + * + * Shrinks this chain in the big block depot. + */ +BOOL BlockChainStream_Shrink(BlockChainStream* This, + ULARGE_INTEGER newSize) +{ + ULONG blockIndex, extraBlock; + ULONG numBlocks; + ULONG count = 1; + + /* + * Reset the last accessed block cache. + */ + This->lastBlockNoInSequence = 0xFFFFFFFF; + This->lastBlockNoInSequenceIndex = BLOCK_END_OF_CHAIN; + + /* + * Figure out how many blocks are needed to contain the new size + */ + numBlocks = newSize.u.LowPart / This->parentStorage->bigBlockSize; + + if ((newSize.u.LowPart % This->parentStorage->bigBlockSize) != 0) + numBlocks++; + + blockIndex = BlockChainStream_GetHeadOfChain(This); + + /* + * Go to the new end of chain + */ + while (count < numBlocks) + { + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); + + count++; + } + + /* Get the next block before marking the new end */ + extraBlock = + StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); + + /* Mark the new end of chain */ + StorageImpl_SetNextBlockInChain( + This->parentStorage, + blockIndex, + BLOCK_END_OF_CHAIN); + + This->tailIndex = blockIndex; + This->numBlocks = numBlocks; + + /* + * Mark the extra blocks as free + */ + while (extraBlock != BLOCK_END_OF_CHAIN) + { + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, extraBlock); + + StorageImpl_FreeBigBlock(This->parentStorage, extraBlock); + extraBlock = blockIndex; + } + + return TRUE; +} + +/****************************************************************************** + * BlockChainStream_Enlarge + * + * Grows this chain in the big block depot. + */ +BOOL BlockChainStream_Enlarge(BlockChainStream* This, + ULARGE_INTEGER newSize) +{ + ULONG blockIndex, currentBlock; + ULONG newNumBlocks; + ULONG oldNumBlocks = 0; + + blockIndex = BlockChainStream_GetHeadOfChain(This); + + /* + * Empty chain. Create the head. + */ + if (blockIndex == BLOCK_END_OF_CHAIN) + { + blockIndex = StorageImpl_GetNextFreeBigBlock(This->parentStorage); + StorageImpl_SetNextBlockInChain(This->parentStorage, + blockIndex, + BLOCK_END_OF_CHAIN); + + if (This->headOfStreamPlaceHolder != 0) + { + *(This->headOfStreamPlaceHolder) = blockIndex; + } + else + { + StgProperty chainProp; + assert(This->ownerPropertyIndex != PROPERTY_NULL); + + StorageImpl_ReadProperty( + This->parentStorage, + This->ownerPropertyIndex, + &chainProp); + + chainProp.startingBlock = blockIndex; + + StorageImpl_WriteProperty( + This->parentStorage, + This->ownerPropertyIndex, + &chainProp); + } + + This->tailIndex = blockIndex; + This->numBlocks = 1; + } + + /* + * Figure out how many blocks are needed to contain this stream + */ + newNumBlocks = newSize.u.LowPart / This->parentStorage->bigBlockSize; + + if ((newSize.u.LowPart % This->parentStorage->bigBlockSize) != 0) + newNumBlocks++; + + /* + * Go to the current end of chain + */ + if (This->tailIndex == BLOCK_END_OF_CHAIN) + { + currentBlock = blockIndex; + + while (blockIndex != BLOCK_END_OF_CHAIN) + { + This->numBlocks++; + currentBlock = blockIndex; + + blockIndex = + StorageImpl_GetNextBlockInChain(This->parentStorage, currentBlock); + } + + This->tailIndex = currentBlock; + } + + currentBlock = This->tailIndex; + oldNumBlocks = This->numBlocks; + + /* + * Add new blocks to the chain + */ + if (oldNumBlocks < newNumBlocks) + { + while (oldNumBlocks < newNumBlocks) + { + blockIndex = StorageImpl_GetNextFreeBigBlock(This->parentStorage); + + StorageImpl_SetNextBlockInChain( + This->parentStorage, + currentBlock, + blockIndex); + + StorageImpl_SetNextBlockInChain( + This->parentStorage, + blockIndex, + BLOCK_END_OF_CHAIN); + + currentBlock = blockIndex; + oldNumBlocks++; + } + + This->tailIndex = blockIndex; + This->numBlocks = newNumBlocks; + } + + return TRUE; +} + +/****************************************************************************** + * BlockChainStream_SetSize + * + * Sets the size of this stream. The big block depot will be updated. + * The file will grow if we grow the chain. + * + * TODO: Free the actual blocks in the file when we shrink the chain. + * Currently, the blocks are still in the file. So the file size + * doesn't shrink even if we shrink streams. + */ +BOOL BlockChainStream_SetSize( + BlockChainStream* This, + ULARGE_INTEGER newSize) +{ + ULARGE_INTEGER size = BlockChainStream_GetSize(This); + + if (newSize.u.LowPart == size.u.LowPart) + return TRUE; + + if (newSize.u.LowPart < size.u.LowPart) + { + BlockChainStream_Shrink(This, newSize); + } + else + { + ULARGE_INTEGER fileSize = + BIGBLOCKFILE_GetSize(This->parentStorage->bigBlockFile); + + ULONG diff = newSize.u.LowPart - size.u.LowPart; + + /* + * Make sure the file stays a multiple of blocksize + */ + if ((diff % This->parentStorage->bigBlockSize) != 0) + diff += (This->parentStorage->bigBlockSize - + (diff % This->parentStorage->bigBlockSize) ); + + fileSize.u.LowPart += diff; + BIGBLOCKFILE_SetSize(This->parentStorage->bigBlockFile, fileSize); + + BlockChainStream_Enlarge(This, newSize); + } + + return TRUE; +} + +/****************************************************************************** + * BlockChainStream_GetSize + * + * Returns the size of this chain. + * Will return the block count if this chain doesn't have a property. + */ +ULARGE_INTEGER BlockChainStream_GetSize(BlockChainStream* This) +{ + StgProperty chainProperty; + + if(This->headOfStreamPlaceHolder == NULL) + { + /* + * This chain is a data stream read the property and return + * the appropriate size + */ + StorageImpl_ReadProperty( + This->parentStorage, + This->ownerPropertyIndex, + &chainProperty); + + return chainProperty.size; + } + else + { + /* + * this chain is a chain that does not have a property, figure out the + * size by making the product number of used blocks times the + * size of them + */ + ULARGE_INTEGER result; + result.u.HighPart = 0; + + result.u.LowPart = + BlockChainStream_GetCount(This) * + This->parentStorage->bigBlockSize; + + return result; + } +} + +/****************************************************************************** +** SmallBlockChainStream implementation +*/ + +SmallBlockChainStream* SmallBlockChainStream_Construct( + StorageImpl* parentStorage, + ULONG propertyIndex) +{ + SmallBlockChainStream* newStream; + + newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(SmallBlockChainStream)); + + newStream->parentStorage = parentStorage; + newStream->ownerPropertyIndex = propertyIndex; + + return newStream; +} + +void SmallBlockChainStream_Destroy( + SmallBlockChainStream* This) +{ + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** + * SmallBlockChainStream_GetHeadOfChain + * + * Returns the head of this chain of small blocks. + */ +ULONG SmallBlockChainStream_GetHeadOfChain( + SmallBlockChainStream* This) +{ + StgProperty chainProperty; + BOOL readSuccessful; + + if (This->ownerPropertyIndex) + { + readSuccessful = StorageImpl_ReadProperty( + This->parentStorage, + This->ownerPropertyIndex, + &chainProperty); + + if (readSuccessful) + { + return chainProperty.startingBlock; + } + + } + + return BLOCK_END_OF_CHAIN; +} + +/****************************************************************************** + * SmallBlockChainStream_GetNextBlockInChain + * + * Returns the index of the next small block in this chain. + * + * Return Values: + * - BLOCK_END_OF_CHAIN: end of this chain + * - BLOCK_UNUSED: small block 'blockIndex' is free + */ +ULONG SmallBlockChainStream_GetNextBlockInChain( + SmallBlockChainStream* This, + ULONG blockIndex) +{ + ULARGE_INTEGER offsetOfBlockInDepot; + DWORD buffer; + ULONG nextBlockInChain = BLOCK_END_OF_CHAIN; + ULONG bytesRead; + BOOL success; + + offsetOfBlockInDepot.u.HighPart = 0; + offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG); + + /* + * Read those bytes in the buffer from the small block file. + */ + success = BlockChainStream_ReadAt( + This->parentStorage->smallBlockDepotChain, + offsetOfBlockInDepot, + sizeof(DWORD), + &buffer, + &bytesRead); + + if (success) + { + StorageUtl_ReadDWord(&buffer, 0, &nextBlockInChain); + } + + return nextBlockInChain; +} + +/****************************************************************************** + * SmallBlockChainStream_SetNextBlockInChain + * + * Writes the index of the next block of the specified block in the small + * block depot. + * To set the end of chain use BLOCK_END_OF_CHAIN as nextBlock. + * To flag a block as free use BLOCK_UNUSED as nextBlock. + */ +void SmallBlockChainStream_SetNextBlockInChain( + SmallBlockChainStream* This, + ULONG blockIndex, + ULONG nextBlock) +{ + ULARGE_INTEGER offsetOfBlockInDepot; + DWORD buffer; + ULONG bytesWritten; + + offsetOfBlockInDepot.u.HighPart = 0; + offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG); + + StorageUtl_WriteDWord(&buffer, 0, nextBlock); + + /* + * Read those bytes in the buffer from the small block file. + */ + BlockChainStream_WriteAt( + This->parentStorage->smallBlockDepotChain, + offsetOfBlockInDepot, + sizeof(DWORD), + &buffer, + &bytesWritten); +} + +/****************************************************************************** + * SmallBlockChainStream_FreeBlock + * + * Flag small block 'blockIndex' as free in the small block depot. + */ +void SmallBlockChainStream_FreeBlock( + SmallBlockChainStream* This, + ULONG blockIndex) +{ + SmallBlockChainStream_SetNextBlockInChain(This, blockIndex, BLOCK_UNUSED); +} + +/****************************************************************************** + * SmallBlockChainStream_GetNextFreeBlock + * + * Returns the index of a free small block. The small block depot will be + * enlarged if necessary. The small block chain will also be enlarged if + * necessary. + */ +ULONG SmallBlockChainStream_GetNextFreeBlock( + SmallBlockChainStream* This) +{ + ULARGE_INTEGER offsetOfBlockInDepot; + DWORD buffer; + ULONG bytesRead; + ULONG blockIndex = 0; + ULONG nextBlockIndex = BLOCK_END_OF_CHAIN; + BOOL success = TRUE; + ULONG smallBlocksPerBigBlock; + + offsetOfBlockInDepot.u.HighPart = 0; + + /* + * Scan the small block depot for a free block + */ + while (nextBlockIndex != BLOCK_UNUSED) + { + offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG); + + success = BlockChainStream_ReadAt( + This->parentStorage->smallBlockDepotChain, + offsetOfBlockInDepot, + sizeof(DWORD), + &buffer, + &bytesRead); + + /* + * If we run out of space for the small block depot, enlarge it + */ + if (success) + { + StorageUtl_ReadDWord(&buffer, 0, &nextBlockIndex); + + if (nextBlockIndex != BLOCK_UNUSED) + blockIndex++; + } + else + { + ULONG count = + BlockChainStream_GetCount(This->parentStorage->smallBlockDepotChain); + + ULONG sbdIndex = This->parentStorage->smallBlockDepotStart; + ULONG nextBlock, newsbdIndex; + BYTE* smallBlockDepot; + + nextBlock = sbdIndex; + while (nextBlock != BLOCK_END_OF_CHAIN) + { + sbdIndex = nextBlock; + nextBlock = + StorageImpl_GetNextBlockInChain(This->parentStorage, sbdIndex); + } + + newsbdIndex = StorageImpl_GetNextFreeBigBlock(This->parentStorage); + if (sbdIndex != BLOCK_END_OF_CHAIN) + StorageImpl_SetNextBlockInChain( + This->parentStorage, + sbdIndex, + newsbdIndex); + + StorageImpl_SetNextBlockInChain( + This->parentStorage, + newsbdIndex, + BLOCK_END_OF_CHAIN); + + /* + * Initialize all the small blocks to free + */ + smallBlockDepot = + StorageImpl_GetBigBlock(This->parentStorage, newsbdIndex); + + memset(smallBlockDepot, BLOCK_UNUSED, This->parentStorage->bigBlockSize); + StorageImpl_ReleaseBigBlock(This->parentStorage, smallBlockDepot); + + if (count == 0) + { + /* + * We have just created the small block depot. + */ + StgProperty rootProp; + ULONG sbStartIndex; + + /* + * Save it in the header + */ + This->parentStorage->smallBlockDepotStart = newsbdIndex; + StorageImpl_SaveFileHeader(This->parentStorage); + + /* + * And allocate the first big block that will contain small blocks + */ + sbStartIndex = + StorageImpl_GetNextFreeBigBlock(This->parentStorage); + + StorageImpl_SetNextBlockInChain( + This->parentStorage, + sbStartIndex, + BLOCK_END_OF_CHAIN); + + StorageImpl_ReadProperty( + This->parentStorage, + This->parentStorage->rootPropertySetIndex, + &rootProp); + + rootProp.startingBlock = sbStartIndex; + rootProp.size.u.HighPart = 0; + rootProp.size.u.LowPart = This->parentStorage->bigBlockSize; + + StorageImpl_WriteProperty( + This->parentStorage, + This->parentStorage->rootPropertySetIndex, + &rootProp); + } + } + } + + smallBlocksPerBigBlock = + This->parentStorage->bigBlockSize / This->parentStorage->smallBlockSize; + + /* + * Verify if we have to allocate big blocks to contain small blocks + */ + if (blockIndex % smallBlocksPerBigBlock == 0) + { + StgProperty rootProp; + ULONG blocksRequired = (blockIndex / smallBlocksPerBigBlock) + 1; + + StorageImpl_ReadProperty( + This->parentStorage, + This->parentStorage->rootPropertySetIndex, + &rootProp); + + if (rootProp.size.u.LowPart < + (blocksRequired * This->parentStorage->bigBlockSize)) + { + rootProp.size.u.LowPart += This->parentStorage->bigBlockSize; + + BlockChainStream_SetSize( + This->parentStorage->smallBlockRootChain, + rootProp.size); + + StorageImpl_WriteProperty( + This->parentStorage, + This->parentStorage->rootPropertySetIndex, + &rootProp); + } + } + + return blockIndex; +} + +/****************************************************************************** + * SmallBlockChainStream_ReadAt + * + * Reads a specified number of bytes from this chain at the specified offset. + * bytesRead may be NULL. + * Failure will be returned if the specified number of bytes has not been read. + */ +BOOL SmallBlockChainStream_ReadAt( + SmallBlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + void* buffer, + ULONG* bytesRead) +{ + ULARGE_INTEGER offsetInBigBlockFile; + ULONG blockNoInSequence = + offset.u.LowPart / This->parentStorage->smallBlockSize; + + ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->smallBlockSize; + ULONG bytesToReadInBuffer; + ULONG blockIndex; + ULONG bytesReadFromBigBlockFile; + BYTE* bufferWalker; + + /* + * This should never happen on a small block file. + */ + assert(offset.u.HighPart==0); + + /* + * Find the first block in the stream that contains part of the buffer. + */ + blockIndex = SmallBlockChainStream_GetHeadOfChain(This); + + while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) + { + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + + blockNoInSequence--; + } + + /* + * Start reading the buffer. + */ + *bytesRead = 0; + bufferWalker = buffer; + + while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) + { + /* + * Calculate how many bytes we can copy from this small block. + */ + bytesToReadInBuffer = + min(This->parentStorage->smallBlockSize - offsetInBlock, size); + + /* + * Calculate the offset of the small block in the small block file. + */ + offsetInBigBlockFile.u.HighPart = 0; + offsetInBigBlockFile.u.LowPart = + blockIndex * This->parentStorage->smallBlockSize; + + offsetInBigBlockFile.u.LowPart += offsetInBlock; + + /* + * Read those bytes in the buffer from the small block file. + */ + BlockChainStream_ReadAt(This->parentStorage->smallBlockRootChain, + offsetInBigBlockFile, + bytesToReadInBuffer, + bufferWalker, + &bytesReadFromBigBlockFile); + + assert(bytesReadFromBigBlockFile == bytesToReadInBuffer); + + /* + * Step to the next big block. + */ + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + bufferWalker += bytesToReadInBuffer; + size -= bytesToReadInBuffer; + *bytesRead += bytesToReadInBuffer; + offsetInBlock = 0; /* There is no offset on the next block */ + } + + return (size == 0); +} + +/****************************************************************************** + * SmallBlockChainStream_WriteAt + * + * Writes the specified number of bytes to this chain at the specified offset. + * bytesWritten may be NULL. + * Will fail if not all specified number of bytes have been written. + */ +BOOL SmallBlockChainStream_WriteAt( + SmallBlockChainStream* This, + ULARGE_INTEGER offset, + ULONG size, + const void* buffer, + ULONG* bytesWritten) +{ + ULARGE_INTEGER offsetInBigBlockFile; + ULONG blockNoInSequence = + offset.u.LowPart / This->parentStorage->smallBlockSize; + + ULONG offsetInBlock = offset.u.LowPart % This->parentStorage->smallBlockSize; + ULONG bytesToWriteInBuffer; + ULONG blockIndex; + ULONG bytesWrittenFromBigBlockFile; + BYTE* bufferWalker; + + /* + * This should never happen on a small block file. + */ + assert(offset.u.HighPart==0); + + /* + * Find the first block in the stream that contains part of the buffer. + */ + blockIndex = SmallBlockChainStream_GetHeadOfChain(This); + + while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) + { + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + + blockNoInSequence--; + } + + /* + * Start writing the buffer. + * + * Here, I'm casting away the constness on the buffer variable + * This is OK since we don't intend to modify that buffer. + */ + *bytesWritten = 0; + bufferWalker = (BYTE*)buffer; + while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) + { + /* + * Calculate how many bytes we can copy to this small block. + */ + bytesToWriteInBuffer = + min(This->parentStorage->smallBlockSize - offsetInBlock, size); + + /* + * Calculate the offset of the small block in the small block file. + */ + offsetInBigBlockFile.u.HighPart = 0; + offsetInBigBlockFile.u.LowPart = + blockIndex * This->parentStorage->smallBlockSize; + + offsetInBigBlockFile.u.LowPart += offsetInBlock; + + /* + * Write those bytes in the buffer to the small block file. + */ + BlockChainStream_WriteAt(This->parentStorage->smallBlockRootChain, + offsetInBigBlockFile, + bytesToWriteInBuffer, + bufferWalker, + &bytesWrittenFromBigBlockFile); + + assert(bytesWrittenFromBigBlockFile == bytesToWriteInBuffer); + + /* + * Step to the next big block. + */ + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + bufferWalker += bytesToWriteInBuffer; + size -= bytesToWriteInBuffer; + *bytesWritten += bytesToWriteInBuffer; + offsetInBlock = 0; /* There is no offset on the next block */ + } + + return (size == 0); +} + +/****************************************************************************** + * SmallBlockChainStream_Shrink + * + * Shrinks this chain in the small block depot. + */ +BOOL SmallBlockChainStream_Shrink( + SmallBlockChainStream* This, + ULARGE_INTEGER newSize) +{ + ULONG blockIndex, extraBlock; + ULONG numBlocks; + ULONG count = 0; + + numBlocks = newSize.u.LowPart / This->parentStorage->smallBlockSize; + + if ((newSize.u.LowPart % This->parentStorage->smallBlockSize) != 0) + numBlocks++; + + blockIndex = SmallBlockChainStream_GetHeadOfChain(This); + + /* + * Go to the new end of chain + */ + while (count < numBlocks) + { + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + count++; + } + + /* + * If the count is 0, we have a special case, the head of the chain was + * just freed. + */ + if (count == 0) + { + StgProperty chainProp; + + StorageImpl_ReadProperty(This->parentStorage, + This->ownerPropertyIndex, + &chainProp); + + chainProp.startingBlock = BLOCK_END_OF_CHAIN; + + StorageImpl_WriteProperty(This->parentStorage, + This->ownerPropertyIndex, + &chainProp); + + /* + * We start freeing the chain at the head block. + */ + extraBlock = blockIndex; + } + else + { + /* Get the next block before marking the new end */ + extraBlock = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + + /* Mark the new end of chain */ + SmallBlockChainStream_SetNextBlockInChain( + This, + blockIndex, + BLOCK_END_OF_CHAIN); + } + + /* + * Mark the extra blocks as free + */ + while (extraBlock != BLOCK_END_OF_CHAIN) + { + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, extraBlock); + SmallBlockChainStream_FreeBlock(This, extraBlock); + extraBlock = blockIndex; + } + + return TRUE; +} + +/****************************************************************************** + * SmallBlockChainStream_Enlarge + * + * Grows this chain in the small block depot. + */ +BOOL SmallBlockChainStream_Enlarge( + SmallBlockChainStream* This, + ULARGE_INTEGER newSize) +{ + ULONG blockIndex, currentBlock; + ULONG newNumBlocks; + ULONG oldNumBlocks = 0; + + blockIndex = SmallBlockChainStream_GetHeadOfChain(This); + + /* + * Empty chain + */ + if (blockIndex == BLOCK_END_OF_CHAIN) + { + + StgProperty chainProp; + + StorageImpl_ReadProperty(This->parentStorage, This->ownerPropertyIndex, + &chainProp); + + chainProp.startingBlock = SmallBlockChainStream_GetNextFreeBlock(This); + + StorageImpl_WriteProperty(This->parentStorage, This->ownerPropertyIndex, + &chainProp); + + blockIndex = chainProp.startingBlock; + SmallBlockChainStream_SetNextBlockInChain( + This, + blockIndex, + BLOCK_END_OF_CHAIN); + } + + currentBlock = blockIndex; + + /* + * Figure out how many blocks are needed to contain this stream + */ + newNumBlocks = newSize.u.LowPart / This->parentStorage->smallBlockSize; + + if ((newSize.u.LowPart % This->parentStorage->smallBlockSize) != 0) + newNumBlocks++; + + /* + * Go to the current end of chain + */ + while (blockIndex != BLOCK_END_OF_CHAIN) + { + oldNumBlocks++; + currentBlock = blockIndex; + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, currentBlock); + } + + /* + * Add new blocks to the chain + */ + while (oldNumBlocks < newNumBlocks) + { + blockIndex = SmallBlockChainStream_GetNextFreeBlock(This); + SmallBlockChainStream_SetNextBlockInChain(This, currentBlock, blockIndex); + + SmallBlockChainStream_SetNextBlockInChain( + This, + blockIndex, + BLOCK_END_OF_CHAIN); + + currentBlock = blockIndex; + oldNumBlocks++; + } + + return TRUE; +} + +/****************************************************************************** + * SmallBlockChainStream_GetCount + * + * Returns the number of blocks that comprises this chain. + * This is not the size of this chain as the last block may not be full! + */ +ULONG SmallBlockChainStream_GetCount(SmallBlockChainStream* This) +{ + ULONG blockIndex; + ULONG count = 0; + + blockIndex = SmallBlockChainStream_GetHeadOfChain(This); + + while (blockIndex != BLOCK_END_OF_CHAIN) + { + count++; + + blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); + } + + return count; +} + +/****************************************************************************** + * SmallBlockChainStream_SetSize + * + * Sets the size of this stream. + * The file will grow if we grow the chain. + * + * TODO: Free the actual blocks in the file when we shrink the chain. + * Currently, the blocks are still in the file. So the file size + * doesn't shrink even if we shrink streams. + */ +BOOL SmallBlockChainStream_SetSize( + SmallBlockChainStream* This, + ULARGE_INTEGER newSize) +{ + ULARGE_INTEGER size = SmallBlockChainStream_GetSize(This); + + if (newSize.u.LowPart == size.u.LowPart) + return TRUE; + + if (newSize.u.LowPart < size.u.LowPart) + { + SmallBlockChainStream_Shrink(This, newSize); + } + else + { + SmallBlockChainStream_Enlarge(This, newSize); + } + + return TRUE; +} + +/****************************************************************************** + * SmallBlockChainStream_GetSize + * + * Returns the size of this chain. + */ +ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This) +{ + StgProperty chainProperty; + + StorageImpl_ReadProperty( + This->parentStorage, + This->ownerPropertyIndex, + &chainProperty); + + return chainProperty.size; +} + +/****************************************************************************** + * StgCreateDocfile [OLE32.144] + */ +HRESULT WINAPI StgCreateDocfile( + LPCOLESTR pwcsName, + DWORD grfMode, + DWORD reserved, + IStorage **ppstgOpen) +{ + StorageImpl* newStorage = 0; + HANDLE hFile = INVALID_HANDLE_VALUE; + HRESULT hr = S_OK; + DWORD shareMode; + DWORD accessMode; + DWORD creationMode; + DWORD fileAttributes; + WCHAR tempFileName[MAX_PATH]; + + Print(MAX_TRACE, ("(%S, %lx, %ld, %p)\n", + pwcsName, grfMode, + reserved, ppstgOpen)); + + /* + * Validate the parameters + */ + if (ppstgOpen == 0) + return STG_E_INVALIDPOINTER; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) )) + return STG_E_INVALIDFLAG; + + /* + * Generate a unique name. + */ + if (pwcsName == 0) + { + WCHAR tempPath[MAX_PATH]; + WCHAR prefix[] = { 'S', 'T', 'O', 0 }; + + if (!(grfMode & STGM_SHARE_EXCLUSIVE)) + return STG_E_INVALIDFLAG; + if (!(grfMode & (STGM_WRITE|STGM_READWRITE))) + return STG_E_INVALIDFLAG; + + memset(tempPath, 0, sizeof(tempPath)); + memset(tempFileName, 0, sizeof(tempFileName)); + + if ((GetTempPathW(MAX_PATH, tempPath)) == 0 ) + tempPath[0] = '.'; + + if (GetTempFileNameW(tempPath, prefix, 0, tempFileName) != 0) + pwcsName = tempFileName; + else + return STG_E_INSUFFICIENTMEMORY; + + creationMode = TRUNCATE_EXISTING; + } + else + { + creationMode = GetCreationModeFromSTGM(grfMode); + } + + /* + * Interpret the STGM value grfMode + */ + shareMode = GetShareModeFromSTGM(grfMode); + accessMode = GetAccessModeFromSTGM(grfMode); + + if (grfMode & STGM_DELETEONRELEASE) + fileAttributes = FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_DELETE_ON_CLOSE; + else + fileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS; + + if (grfMode & STGM_TRANSACTED) + UNIMPLEMENTED; + + /* + * Initialize the "out" parameter. + */ + *ppstgOpen = 0; + + hFile = CreateFileW(pwcsName, + accessMode, + shareMode, + NULL, + creationMode, + fileAttributes, + 0); + + if (hFile == INVALID_HANDLE_VALUE) + { + return E_FAIL; + } + + /* + * Allocate and initialize the new IStorage32object. + */ + newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); + + if (newStorage == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = StorageImpl_Construct( + newStorage, + hFile, + NULL, + grfMode, + TRUE, + TRUE); + + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, newStorage); + return hr; + } + + /* + * Get an "out" pointer for the caller. + */ + hr = StorageBaseImpl_QueryInterface( + (IStorage*)newStorage, + (REFIID)&IID_IStorage, + (void**)ppstgOpen); + + return hr; +} + +/****************************************************************************** + * StgOpenStorage [OLE32.148] + */ +HRESULT WINAPI StgOpenStorage( + const OLECHAR *pwcsName, + IStorage *pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage **ppstgOpen) +{ + StorageImpl* newStorage = 0; + HRESULT hr = S_OK; + HANDLE hFile = 0; + DWORD shareMode; + DWORD accessMode; + + Print(MAX_TRACE, ("(%S, %p, %lx, %p, %ld, %p)\n", + pwcsName, pstgPriority, grfMode, + snbExclude, reserved, ppstgOpen)); + + /* + * Perform a sanity check + */ + if (( pwcsName == 0) || (ppstgOpen == 0) ) + return STG_E_INVALIDPOINTER; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) )) + return STG_E_INVALIDFLAG; + + /* + * Interpret the STGM value grfMode + */ + shareMode = GetShareModeFromSTGM(grfMode); + accessMode = GetAccessModeFromSTGM(grfMode); + + /* + * Initialize the "out" parameter. + */ + *ppstgOpen = 0; + + hFile = CreateFileW( pwcsName, + accessMode, + shareMode, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + 0); + + + if (hFile==INVALID_HANDLE_VALUE) + { + HRESULT hr = E_FAIL; + DWORD last_error = GetLastError(); + + switch (last_error) + { + case ERROR_FILE_NOT_FOUND: + hr = STG_E_FILENOTFOUND; + break; + + case ERROR_PATH_NOT_FOUND: + hr = STG_E_PATHNOTFOUND; + break; + + case ERROR_ACCESS_DENIED: + case ERROR_WRITE_PROTECT: + hr = STG_E_ACCESSDENIED; + break; + + case ERROR_SHARING_VIOLATION: + hr = STG_E_SHAREVIOLATION; + break; + + default: + hr = E_FAIL; + } + + return hr; + } + + /* + * Allocate and initialize the new IStorage32object. + */ + newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); + + if (newStorage == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = StorageImpl_Construct( + newStorage, + hFile, + NULL, + grfMode, + TRUE, + FALSE); + + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, newStorage); + /* + * According to the docs if the file is not a storage, return STG_E_FILEALREADYEXISTS + */ + if(hr == STG_E_INVALIDHEADER) + return STG_E_FILEALREADYEXISTS; + return hr; + } + + /* + * Get an "out" pointer for the caller. + */ + hr = StorageBaseImpl_QueryInterface( + (IStorage*)newStorage, + (REFIID)&IID_IStorage, + (void**)ppstgOpen); + + return hr; +} + +/****************************************************************************** + * StgCreateDocfileOnILockBytes [OLE32.145] + */ +HRESULT WINAPI StgCreateDocfileOnILockBytes( + ILockBytes *plkbyt, + DWORD grfMode, + DWORD reserved, + IStorage** ppstgOpen) +{ + StorageImpl* newStorage = 0; + HRESULT hr = S_OK; + + /* + * Validate the parameters + */ + if ((ppstgOpen == 0) || (plkbyt == 0)) + return STG_E_INVALIDPOINTER; + + /* + * Allocate and initialize the new IStorage object. + */ + newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); + + if (newStorage == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = StorageImpl_Construct( + newStorage, + 0, + plkbyt, + grfMode, + FALSE, + TRUE); + + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, newStorage); + return hr; + } + + /* + * Get an "out" pointer for the caller. + */ + hr = StorageBaseImpl_QueryInterface( + (IStorage*)newStorage, + (REFIID)&IID_IStorage, + (void**)ppstgOpen); + + return hr; +} + +/****************************************************************************** + * StgOpenStorageOnILockBytes [OLE32.149] + */ +HRESULT WINAPI StgOpenStorageOnILockBytes( + ILockBytes *plkbyt, + IStorage *pstgPriority, + DWORD grfMode, + SNB snbExclude, + DWORD reserved, + IStorage **ppstgOpen) +{ + StorageImpl* newStorage = 0; + HRESULT hr = S_OK; + + /* + * Perform a sanity check + */ + if ((plkbyt == 0) || (ppstgOpen == 0)) + return STG_E_INVALIDPOINTER; + + /* + * Validate the STGM flags + */ + if ( FAILED( validateSTGM(grfMode) )) + return STG_E_INVALIDFLAG; + + /* + * Initialize the "out" parameter. + */ + *ppstgOpen = 0; + + /* + * Allocate and initialize the new IStorage object. + */ + newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); + + if (newStorage == 0) + return STG_E_INSUFFICIENTMEMORY; + + hr = StorageImpl_Construct( + newStorage, + 0, + plkbyt, + grfMode, + FALSE, + FALSE); + + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, newStorage); + return hr; + } + + /* + * Get an "out" pointer for the caller. + */ + hr = StorageBaseImpl_QueryInterface( + (IStorage*)newStorage, + (REFIID)&IID_IStorage, + (void**)ppstgOpen); + + return hr; +} + +/****************************************************************************** + * StgSetTimes [ole32.150] + * + * + */ +HRESULT WINAPI StgSetTimes(WCHAR * str, FILETIME * a, FILETIME * b, FILETIME *c ) +{ + + UNIMPLEMENTED; + return FALSE; +} + +/****************************************************************************** + * StgIsStorageILockBytes [OLE32.147] + * + * Determines if the ILockBytes contains a storage object. + */ +HRESULT WINAPI StgIsStorageILockBytes(ILockBytes *plkbyt) +{ + BYTE sig[8]; + ULARGE_INTEGER offset; + + offset.u.HighPart = 0; + offset.u.LowPart = 0; + + ILockBytes_ReadAt(plkbyt, offset, sig, sizeof(sig), NULL); + + if (memcmp(sig, STORAGE_magic, sizeof(STORAGE_magic)) == 0) + return S_OK; + + return S_FALSE; +} + +/****************************************************************************** + * WriteClassStg [OLE32.158] + * + * This method will store the specified CLSID in the specified storage object + */ +HRESULT WINAPI WriteClassStg(IStorage* pStg, REFCLSID rclsid) +{ + HRESULT hRes; + + assert(pStg != 0); + + hRes = IStorage_SetClass(pStg, rclsid); + + return hRes; +} + +/*********************************************************************** + * ReadClassStg + * + * This method reads the CLSID previously written to a storage object with the WriteClassStg. + */ +HRESULT WINAPI ReadClassStg(IStorage *pstg,CLSID *pclsid){ + + STATSTG pstatstg; + HRESULT hRes; + + Print(MAX_TRACE, ("()\n")); + + if(pclsid==NULL) + return E_POINTER; + /* + * read a STATSTG structure (contains the clsid) from the storage + */ + hRes=IStorage_Stat(pstg,&pstatstg,STATFLAG_DEFAULT); + + if(SUCCEEDED(hRes)) + *pclsid=pstatstg.clsid; + + return hRes; +} + +/*********************************************************************** + * OleLoadFromStream + * + * This function loads an object from stream + */ +HRESULT WINAPI OleLoadFromStream(IStream *pStm,REFIID iidInterface,void** ppvObj) +{ + CLSID clsid; + HRESULT res; + LPPERSISTSTREAM xstm; + + Print(MAX_TRACE, ("(%p,%s,%p)\n",pStm,PRINT_GUID(iidInterface),ppvObj)); + + res=ReadClassStm(pStm,&clsid); + if (!SUCCEEDED(res)) + return res; + res=CoCreateInstance(&clsid,NULL,CLSCTX_INPROC_SERVER,iidInterface,ppvObj); + if (!SUCCEEDED(res)) + return res; + res=IUnknown_QueryInterface((IUnknown*)*ppvObj,&IID_IPersistStream,(LPVOID*)&xstm); + if (!SUCCEEDED(res)) { + IUnknown_Release((IUnknown*)*ppvObj); + return res; + } + res=IPersistStream_Load(xstm,pStm); + IPersistStream_Release(xstm); + /* FIXME: all refcounts ok at this point? I think they should be: + * pStm : unchanged + * ppvObj : 1 + * xstm : 0 (released) + */ + return res; +} + +/*********************************************************************** + * OleSaveToStream + * + * This function saves an object with the IPersistStream interface on it + * to the specified stream. + */ +HRESULT WINAPI OleSaveToStream(IPersistStream *pPStm,IStream *pStm) +{ + + CLSID clsid; + HRESULT res; + + Print(MAX_TRACE, ("(%p,%p)\n",pPStm,pStm)); + + res=IPersistStream_GetClassID(pPStm,&clsid); + + if (SUCCEEDED(res)){ + + res=WriteClassStm(pStm,&clsid); + + if (SUCCEEDED(res)) + + res=IPersistStream_Save(pPStm,pStm,TRUE); + } + + Print(MAX_TRACE, ("Finished Save\n")); + return res; +} + +/**************************************************************************** + * This method validate a STGM parameter that can contain the values below + * + * STGM_DIRECT 0x00000000 + * STGM_TRANSACTED 0x00010000 + * STGM_SIMPLE 0x08000000 + * + * STGM_READ 0x00000000 + * STGM_WRITE 0x00000001 + * STGM_READWRITE 0x00000002 + * + * STGM_SHARE_DENY_NONE 0x00000040 + * STGM_SHARE_DENY_READ 0x00000030 + * STGM_SHARE_DENY_WRITE 0x00000020 + * STGM_SHARE_EXCLUSIVE 0x00000010 + * + * STGM_PRIORITY 0x00040000 + * STGM_DELETEONRELEASE 0x04000000 + * + * STGM_CREATE 0x00001000 + * STGM_CONVERT 0x00020000 + * STGM_FAILIFTHERE 0x00000000 + * + * STGM_NOSCRATCH 0x00100000 + * STGM_NOSNAPSHOT 0x00200000 + */ +static HRESULT validateSTGM(DWORD stgm) +{ + BOOL bSTGM_TRANSACTED = ((stgm & STGM_TRANSACTED) == STGM_TRANSACTED); + BOOL bSTGM_SIMPLE = ((stgm & STGM_SIMPLE) == STGM_SIMPLE); + BOOL bSTGM_DIRECT = ! (bSTGM_TRANSACTED || bSTGM_SIMPLE); + + BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE); + BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE); + BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE); + + BOOL bSTGM_SHARE_DENY_NONE = + ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE); + + BOOL bSTGM_SHARE_DENY_READ = + ((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ); + + BOOL bSTGM_SHARE_DENY_WRITE = + ((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE); + + BOOL bSTGM_SHARE_EXCLUSIVE = + ((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE); + + BOOL bSTGM_CREATE = ((stgm & STGM_CREATE) == STGM_CREATE); + BOOL bSTGM_CONVERT = ((stgm & STGM_CONVERT) == STGM_CONVERT); + + BOOL bSTGM_NOSCRATCH = ((stgm & STGM_NOSCRATCH) == STGM_NOSCRATCH); + BOOL bSTGM_NOSNAPSHOT = ((stgm & STGM_NOSNAPSHOT) == STGM_NOSNAPSHOT); + + /* + * STGM_DIRECT | STGM_TRANSACTED | STGM_SIMPLE + */ + if ( ! bSTGM_DIRECT ) + if( bSTGM_TRANSACTED && bSTGM_SIMPLE ) + return E_FAIL; + + /* + * STGM_WRITE | STGM_READWRITE | STGM_READ + */ + if ( ! bSTGM_READ ) + if( bSTGM_WRITE && bSTGM_READWRITE ) + return E_FAIL; + + /* + * STGM_SHARE_DENY_NONE | others + * (I assume here that DENY_READ implies DENY_WRITE) + */ + if ( bSTGM_SHARE_DENY_NONE ) + if ( bSTGM_SHARE_DENY_READ || + bSTGM_SHARE_DENY_WRITE || + bSTGM_SHARE_EXCLUSIVE) + return E_FAIL; + + /* + * STGM_CREATE | STGM_CONVERT + * if both are false, STGM_FAILIFTHERE is set to TRUE + */ + if ( bSTGM_CREATE && bSTGM_CONVERT ) + return E_FAIL; + + /* + * STGM_NOSCRATCH requires STGM_TRANSACTED + */ + if ( bSTGM_NOSCRATCH && ! bSTGM_TRANSACTED ) + return E_FAIL; + + /* + * STGM_NOSNAPSHOT requires STGM_TRANSACTED and + * not STGM_SHARE_EXCLUSIVE or STGM_SHARE_DENY_WRITE` + */ + if (bSTGM_NOSNAPSHOT) + { + if ( ! ( bSTGM_TRANSACTED && + !(bSTGM_SHARE_EXCLUSIVE || bSTGM_SHARE_DENY_WRITE)) ) + return E_FAIL; + } + + return S_OK; +} + +/**************************************************************************** + * GetShareModeFromSTGM + * + * This method will return a share mode flag from a STGM value. + * The STGM value is assumed valid. + */ +static DWORD GetShareModeFromSTGM(DWORD stgm) +{ + DWORD dwShareMode = 0; + BOOL bSTGM_SHARE_DENY_NONE = + ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE); + + BOOL bSTGM_SHARE_DENY_READ = + ((stgm & STGM_SHARE_DENY_READ) == STGM_SHARE_DENY_READ); + + BOOL bSTGM_SHARE_DENY_WRITE = + ((stgm & STGM_SHARE_DENY_WRITE) == STGM_SHARE_DENY_WRITE); + + BOOL bSTGM_SHARE_EXCLUSIVE = + ((stgm & STGM_SHARE_EXCLUSIVE) == STGM_SHARE_EXCLUSIVE); + + if ((bSTGM_SHARE_EXCLUSIVE) || (bSTGM_SHARE_DENY_READ)) + dwShareMode = 0; + + if (bSTGM_SHARE_DENY_NONE) + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + + if (bSTGM_SHARE_DENY_WRITE) + dwShareMode = FILE_SHARE_READ; + + return dwShareMode; +} + +/**************************************************************************** + * GetAccessModeFromSTGM + * + * This method will return an access mode flag from a STGM value. + * The STGM value is assumed valid. + */ +static DWORD GetAccessModeFromSTGM(DWORD stgm) +{ + DWORD dwDesiredAccess = GENERIC_READ; + BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE); + BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE); + BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE); + + if (bSTGM_READ) + dwDesiredAccess = GENERIC_READ; + + if (bSTGM_WRITE) + dwDesiredAccess |= GENERIC_WRITE; + + if (bSTGM_READWRITE) + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + + return dwDesiredAccess; +} + +/**************************************************************************** + * GetCreationModeFromSTGM + * + * This method will return a creation mode flag from a STGM value. + * The STGM value is assumed valid. + */ +static DWORD GetCreationModeFromSTGM(DWORD stgm) +{ + if ( stgm & STGM_CREATE) + return CREATE_ALWAYS; + if (stgm & STGM_CONVERT) { + UNIMPLEMENTED; + return CREATE_NEW; + } + /* All other cases */ + if (stgm & ~ (STGM_CREATE|STGM_CONVERT)) + Print(MIN_TRACE, ("unhandled storage mode : 0x%08lx\n",stgm & ~ (STGM_CREATE|STGM_CONVERT))); + return CREATE_NEW; +} + + +/************************************************************************* + * OLECONVERT_LoadOLE10 [Internal] + * + * Loads the OLE10 STREAM to memory + * + * PARAMS + * pOleStream [I] The OLESTREAM + * pData [I] Data Structure for the OLESTREAM Data + * + * RETURNS + * Success: S_OK + * Failure: CONVERT10_E_OLESTREAM_GET for invalid Get + * CONVERT10_E_OLESTREAM_FMT if the OLEID is invalide + * + * NOTES + * This function is used by OleConvertOLESTREAMToIStorage only. + * + * Memory allocated for pData must be freed by the caller + */ +HRESULT OLECONVERT_LoadOLE10(LPOLESTREAM pOleStream, OLECONVERT_OLESTREAM_DATA *pData, BOOL bStrem1) +{ + DWORD dwSize; + HRESULT hRes = S_OK; + int nTryCnt=0; + int max_try = 6; + + pData->pData = NULL; + pData->pstrOleObjFileName = (CHAR *) NULL; + + for( nTryCnt=0;nTryCnt < max_try; nTryCnt++) + { + /* Get the OleID */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwOleID), sizeof(pData->dwOleID)); + if(dwSize != sizeof(pData->dwOleID)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + else if(pData->dwOleID != OLESTREAM_ID) + { + hRes = CONVERT10_E_OLESTREAM_FMT; + } + else + { + hRes = S_OK; + break; + } + } + + if(hRes == S_OK) + { + /* Get the TypeID...more info needed for this field */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwTypeID), sizeof(pData->dwTypeID)); + if(dwSize != sizeof(pData->dwTypeID)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + if(hRes == S_OK) + { + if(pData->dwTypeID != 0) + { + /* Get the lenght of the OleTypeName */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *) &(pData->dwOleTypeNameLength), sizeof(pData->dwOleTypeNameLength)); + if(dwSize != sizeof(pData->dwOleTypeNameLength)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + + if(hRes == S_OK) + { + if(pData->dwOleTypeNameLength > 0) + { + /* Get the OleTypeName */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)pData->strOleTypeName, pData->dwOleTypeNameLength); + if(dwSize != pData->dwOleTypeNameLength) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + } + if(bStrem1) + { + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwOleObjFileNameLength), sizeof(pData->dwOleObjFileNameLength)); + if(dwSize != sizeof(pData->dwOleObjFileNameLength)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + if(hRes == S_OK) + { + if(pData->dwOleObjFileNameLength < 1) /* there is no file name exist */ + pData->dwOleObjFileNameLength = sizeof(pData->dwOleObjFileNameLength); + pData->pstrOleObjFileName = (CHAR *)malloc(pData->dwOleObjFileNameLength); + if(pData->pstrOleObjFileName) + { + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)(pData->pstrOleObjFileName),pData->dwOleObjFileNameLength); + if(dwSize != pData->dwOleObjFileNameLength) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + else + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + else + { + /* Get the Width of the Metafile */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwMetaFileWidth), sizeof(pData->dwMetaFileWidth)); + if(dwSize != sizeof(pData->dwMetaFileWidth)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + if(hRes == S_OK) + { + /* Get the Height of the Metafile */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwMetaFileHeight), sizeof(pData->dwMetaFileHeight)); + if(dwSize != sizeof(pData->dwMetaFileHeight)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + } + if(hRes == S_OK) + { + /* Get the Lenght of the Data */ + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)&(pData->dwDataLength), sizeof(pData->dwDataLength)); + if(dwSize != sizeof(pData->dwDataLength)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + + if(hRes == S_OK) /* I don't know what is this 8 byts information is we have to figure out */ + { + if(!bStrem1) /* if it is a second OLE stream data */ + { + pData->dwDataLength -= 8; + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)(pData->strUnknown), sizeof(pData->strUnknown)); + if(dwSize != sizeof(pData->strUnknown)) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + } + if(hRes == S_OK) + { + if(pData->dwDataLength > 0) + { + pData->pData = (BYTE *)HeapAlloc(GetProcessHeap(),0,pData->dwDataLength); + + /* Get Data (ex. IStorage, Metafile, or BMP) */ + if(pData->pData) + { + dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)pData->pData, pData->dwDataLength); + if(dwSize != pData->dwDataLength) + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + else + { + hRes = CONVERT10_E_OLESTREAM_GET; + } + } + } + } + } + return hRes; +} + +/************************************************************************* + * OLECONVERT_SaveOLE10 [Internal] + * + * Saves the OLE10 STREAM From memory + * + * PARAMS + * pData [I] Data Structure for the OLESTREAM Data + * pOleStream [I] The OLESTREAM to save + * + * RETURNS + * Success: S_OK + * Failure: CONVERT10_E_OLESTREAM_PUT for invalid Put + * + * NOTES + * This function is used by OleConvertIStorageToOLESTREAM only. + * + */ +HRESULT OLECONVERT_SaveOLE10(OLECONVERT_OLESTREAM_DATA *pData, LPOLESTREAM pOleStream) +{ + DWORD dwSize; + HRESULT hRes = S_OK; + + + /* Set the OleID */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwOleID), sizeof(pData->dwOleID)); + if(dwSize != sizeof(pData->dwOleID)) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + + if(hRes == S_OK) + { + /* Set the TypeID */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwTypeID), sizeof(pData->dwTypeID)); + if(dwSize != sizeof(pData->dwTypeID)) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + } + + if(pData->dwOleID == OLESTREAM_ID && pData->dwTypeID != 0 && hRes == S_OK) + { + /* Set the Lenght of the OleTypeName */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwOleTypeNameLength), sizeof(pData->dwOleTypeNameLength)); + if(dwSize != sizeof(pData->dwOleTypeNameLength)) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + + if(hRes == S_OK) + { + if(pData->dwOleTypeNameLength > 0) + { + /* Set the OleTypeName */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *) pData->strOleTypeName, pData->dwOleTypeNameLength); + if(dwSize != pData->dwOleTypeNameLength) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + } + } + + if(hRes == S_OK) + { + /* Set the width of the Metafile */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwMetaFileWidth), sizeof(pData->dwMetaFileWidth)); + if(dwSize != sizeof(pData->dwMetaFileWidth)) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + } + + if(hRes == S_OK) + { + /* Set the height of the Metafile */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwMetaFileHeight), sizeof(pData->dwMetaFileHeight)); + if(dwSize != sizeof(pData->dwMetaFileHeight)) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + } + + if(hRes == S_OK) + { + /* Set the lenght of the Data */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *)&(pData->dwDataLength), sizeof(pData->dwDataLength)); + if(dwSize != sizeof(pData->dwDataLength)) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + } + + if(hRes == S_OK) + { + if(pData->dwDataLength > 0) + { + /* Set the Data (eg. IStorage, Metafile, Bitmap) */ + dwSize = pOleStream->lpstbl->Put(pOleStream, (void *) pData->pData, pData->dwDataLength); + if(dwSize != pData->dwDataLength) + { + hRes = CONVERT10_E_OLESTREAM_PUT; + } + } + } + } + return hRes; +} + +/************************************************************************* + * OLECONVERT_GetOLE20FromOLE10[Internal] + * + * This function copies OLE10 Data (the IStorage in the OLESTREAM) to disk, + * opens it, and copies the content to the dest IStorage for + * OleConvertOLESTREAMToIStorage + * + * + * PARAMS + * pDestStorage [I] The IStorage to copy the data to + * pBuffer [I] Buffer that contains the IStorage from the OLESTREAM + * nBufferLength [I] The size of the buffer + * + * RETURNS + * Nothing + * + * NOTES + * + * + */ +void OLECONVERT_GetOLE20FromOLE10(LPSTORAGE pDestStorage, BYTE *pBuffer, DWORD nBufferLength) +{ + HRESULT hRes; + HANDLE hFile; + IStorage *pTempStorage; + DWORD dwNumOfBytesWritten; + WCHAR wstrTempDir[MAX_PATH], wstrTempFile[MAX_PATH]; + WCHAR wstrPrefix[] = {'s', 'i', 's', 0}; + + /* Create a temp File */ + GetTempPathW(MAX_PATH, wstrTempDir); + GetTempFileNameW(wstrTempDir, wstrPrefix, 0, wstrTempFile); + hFile = CreateFileW(wstrTempFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + + if(hFile != INVALID_HANDLE_VALUE) + { + /* Write IStorage Data to File */ + WriteFile(hFile, pBuffer, nBufferLength, &dwNumOfBytesWritten, NULL); + CloseHandle(hFile); + + /* Open and copy temp storage to the Dest Storage */ + hRes = StgOpenStorage(wstrTempFile, NULL, STGM_READ, NULL, 0, &pTempStorage); + if(hRes == S_OK) + { + hRes = StorageImpl_CopyTo(pTempStorage, 0, NULL, NULL, pDestStorage); + StorageBaseImpl_Release(pTempStorage); + } + DeleteFileW(wstrTempFile); + } +} + + +/************************************************************************* + * OLECONVERT_WriteOLE20ToBuffer [Internal] + * + * Saves the OLE10 STREAM From memory + * + * PARAMS + * pStorage [I] The Src IStorage to copy + * pData [I] The Dest Memory to write to. + * + * RETURNS + * The size in bytes allocated for pData + * + * NOTES + * Memory allocated for pData must be freed by the caller + * + * Used by OleConvertIStorageToOLESTREAM only. + * + */ +DWORD OLECONVERT_WriteOLE20ToBuffer(LPSTORAGE pStorage, BYTE **pData) +{ + HANDLE hFile; + HRESULT hRes; + DWORD nDataLength = 0; + IStorage *pTempStorage; + WCHAR wstrTempDir[MAX_PATH], wstrTempFile[MAX_PATH]; + WCHAR wstrPrefix[] = {'s', 'i', 's', 0}; + + *pData = NULL; + + /* Create temp Storage */ + GetTempPathW(MAX_PATH, wstrTempDir); + GetTempFileNameW(wstrTempDir, wstrPrefix, 0, wstrTempFile); + hRes = StgCreateDocfile(wstrTempFile, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pTempStorage); + + if(hRes == S_OK) + { + /* Copy Src Storage to the Temp Storage */ + StorageImpl_CopyTo(pStorage, 0, NULL, NULL, pTempStorage); + StorageBaseImpl_Release(pTempStorage); + + /* Open Temp Storage as a file and copy to memory */ + hFile = CreateFileW(wstrTempFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if(hFile != INVALID_HANDLE_VALUE) + { + nDataLength = GetFileSize(hFile, NULL); + *pData = (BYTE *) HeapAlloc(GetProcessHeap(),0,nDataLength); + ReadFile(hFile, *pData, nDataLength, &nDataLength, 0); + CloseHandle(hFile); + } + DeleteFileW(wstrTempFile); + } + return nDataLength; +} + +/************************************************************************* + * OLECONVERT_CreateOleStream [Internal] + * + * Creates the "\001OLE" stream in the IStorage if neccessary. + * + * PARAMS + * pStorage [I] Dest storage to create the stream in + * + * RETURNS + * Nothing + * + * NOTES + * This function is used by OleConvertOLESTREAMToIStorage only. + * + * This stream is still unknown, MS Word seems to have extra data + * but since the data is stored in the OLESTREAM there should be + * no need to recreate the stream. If the stream is manually + * deleted it will create it with this default data. + * + */ +void OLECONVERT_CreateOleStream(LPSTORAGE pStorage) +{ + HRESULT hRes; + IStream *pStream; + WCHAR wstrStreamName[] = {1,'O', 'l', 'e', 0}; + BYTE pOleStreamHeader [] = + { + 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + /* Create stream if not present */ + hRes = IStorage_CreateStream(pStorage, wstrStreamName, + STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); + + if(hRes == S_OK) + { + /* Write default Data */ + hRes = IStream_Write(pStream, pOleStreamHeader, sizeof(pOleStreamHeader), NULL); + IStream_Release(pStream); + } +} + + +/************************************************************************* + * OLECONVERT_CreateCompObjStream [Internal] + * + * Creates a "\001CompObj" is the destination IStorage if necessary. + * + * PARAMS + * pStorage [I] The dest IStorage to create the CompObj Stream + * if necessary. + * strOleTypeName [I] The ProgID + * + * RETURNS + * Success: S_OK + * Failure: REGDB_E_CLASSNOTREG if cannot reconstruct the stream + * + * NOTES + * This function is used by OleConvertOLESTREAMToIStorage only. + * + * The stream data is stored in the OLESTREAM and there should be + * no need to recreate the stream. If the stream is manually + * deleted it will attempt to create it by querying the registry. + * + * + */ +HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName) +{ + IStream *pStream; + HRESULT hStorageRes, hRes = S_OK; + OLECONVERT_ISTORAGE_COMPOBJ IStorageCompObj; + WCHAR wstrStreamName[] = {1,'C', 'o', 'm', 'p', 'O', 'b', 'j', 0}; + + BYTE pCompObjUnknown1[] = {0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; + BYTE pCompObjUnknown2[] = {0xF4, 0x39, 0xB2, 0x71}; + + /* Initialize the CompObj structure */ + memset(&IStorageCompObj, 0, sizeof(IStorageCompObj)); + memcpy(&(IStorageCompObj.byUnknown1), pCompObjUnknown1, sizeof(pCompObjUnknown1)); + memcpy(&(IStorageCompObj.byUnknown2), pCompObjUnknown2, sizeof(pCompObjUnknown2)); + + + /* Create a CompObj stream if it doesn't exist */ + hStorageRes = IStorage_CreateStream(pStorage, wstrStreamName, + STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); + if(hStorageRes == S_OK) + { + /* copy the OleTypeName to the compobj struct */ + IStorageCompObj.dwOleTypeNameLength = strlen(strOleTypeName)+1; + strcpy(IStorageCompObj.strOleTypeName, strOleTypeName); + + /* copy the OleTypeName to the compobj struct */ + /* Note: in the test made, these were Identical */ + IStorageCompObj.dwProgIDNameLength = strlen(strOleTypeName)+1; + strcpy(IStorageCompObj.strProgIDName, strOleTypeName); + + /* Get the CLSID */ + hRes = CLSIDFromProgID16(IStorageCompObj.strProgIDName, &(IStorageCompObj.clsid)); + + if(hRes == S_OK) + { + HKEY hKey; + LONG hErr; + /* Get the CLSID Default Name from the Registry */ + hErr = RegOpenKeyA(HKEY_CLASSES_ROOT, IStorageCompObj.strProgIDName, &hKey); + if(hErr == ERROR_SUCCESS) + { + char strTemp[OLESTREAM_MAX_STR_LEN]; + IStorageCompObj.dwCLSIDNameLength = OLESTREAM_MAX_STR_LEN; + hErr = RegQueryValueA(hKey, NULL, strTemp, &(IStorageCompObj.dwCLSIDNameLength)); + if(hErr == ERROR_SUCCESS) + { + strcpy(IStorageCompObj.strCLSIDName, strTemp); + } + RegCloseKey(hKey); + } + } + + /* Write CompObj Structure to stream */ + hRes = IStream_Write(pStream, IStorageCompObj.byUnknown1, sizeof(IStorageCompObj.byUnknown1), NULL); + + WriteClassStm(pStream,&(IStorageCompObj.clsid)); + + hRes = IStream_Write(pStream, &(IStorageCompObj.dwCLSIDNameLength), sizeof(IStorageCompObj.dwCLSIDNameLength), NULL); + if(IStorageCompObj.dwCLSIDNameLength > 0) + { + hRes = IStream_Write(pStream, IStorageCompObj.strCLSIDName, IStorageCompObj.dwCLSIDNameLength, NULL); + } + hRes = IStream_Write(pStream, &(IStorageCompObj.dwOleTypeNameLength) , sizeof(IStorageCompObj.dwOleTypeNameLength), NULL); + if(IStorageCompObj.dwOleTypeNameLength > 0) + { + hRes = IStream_Write(pStream, IStorageCompObj.strOleTypeName , IStorageCompObj.dwOleTypeNameLength, NULL); + } + hRes = IStream_Write(pStream, &(IStorageCompObj.dwProgIDNameLength) , sizeof(IStorageCompObj.dwProgIDNameLength), NULL); + if(IStorageCompObj.dwProgIDNameLength > 0) + { + hRes = IStream_Write(pStream, IStorageCompObj.strProgIDName , IStorageCompObj.dwProgIDNameLength, NULL); + } + hRes = IStream_Write(pStream, IStorageCompObj.byUnknown2 , sizeof(IStorageCompObj.byUnknown2), NULL); + IStream_Release(pStream); + } + return hRes; +} + + +/************************************************************************* + * OLECONVERT_CreateOlePresStream[Internal] + * + * Creates the "\002OlePres000" Stream with the Metafile data + * + * PARAMS + * pStorage [I] The dest IStorage to create \002OLEPres000 stream in. + * dwExtentX [I] Width of the Metafile + * dwExtentY [I] Height of the Metafile + * pData [I] Metafile data + * dwDataLength [I] Size of the Metafile data + * + * RETURNS + * Success: S_OK + * Failure: CONVERT10_E_OLESTREAM_PUT for invalid Put + * + * NOTES + * This function is used by OleConvertOLESTREAMToIStorage only. + * + */ +void OLECONVERT_CreateOlePresStream(LPSTORAGE pStorage, DWORD dwExtentX, DWORD dwExtentY , BYTE *pData, DWORD dwDataLength) +{ + HRESULT hRes; + IStream *pStream; + WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0}; + BYTE pOlePresStreamHeader [] = + { + 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + BYTE pOlePresStreamHeaderEmpty [] = + { + 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + + /* Create the OlePres000 Stream */ + hRes = IStorage_CreateStream(pStorage, wstrStreamName, + STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); + + if(hRes == S_OK) + { + DWORD nHeaderSize; + OLECONVERT_ISTORAGE_OLEPRES OlePres; + + memset(&OlePres, 0, sizeof(OlePres)); + /* Do we have any metafile data to save */ + if(dwDataLength > 0) + { + memcpy(OlePres.byUnknown1, pOlePresStreamHeader, sizeof(pOlePresStreamHeader)); + nHeaderSize = sizeof(pOlePresStreamHeader); + } + else + { + memcpy(OlePres.byUnknown1, pOlePresStreamHeaderEmpty, sizeof(pOlePresStreamHeaderEmpty)); + nHeaderSize = sizeof(pOlePresStreamHeaderEmpty); + } + /* Set width and height of the metafile */ + OlePres.dwExtentX = dwExtentX; + OlePres.dwExtentY = -dwExtentY; + + /* Set Data and Lenght */ + if(dwDataLength > sizeof(METAFILEPICT16)) + { + OlePres.dwSize = dwDataLength - sizeof(METAFILEPICT16); + OlePres.pData = &(pData[8]); + } + /* Save OlePres000 Data to Stream */ + hRes = IStream_Write(pStream, OlePres.byUnknown1, nHeaderSize, NULL); + hRes = IStream_Write(pStream, &(OlePres.dwExtentX), sizeof(OlePres.dwExtentX), NULL); + hRes = IStream_Write(pStream, &(OlePres.dwExtentY), sizeof(OlePres.dwExtentY), NULL); + hRes = IStream_Write(pStream, &(OlePres.dwSize), sizeof(OlePres.dwSize), NULL); + if(OlePres.dwSize > 0) + { + hRes = IStream_Write(pStream, OlePres.pData, OlePres.dwSize, NULL); + } + IStream_Release(pStream); + } +} + +/************************************************************************* + * OLECONVERT_CreateOle10NativeStream [Internal] + * + * Creates the "\001Ole10Native" Stream (should contain a BMP) + * + * PARAMS + * pStorage [I] Dest storage to create the stream in + * pData [I] Ole10 Native Data (ex. bmp) + * dwDataLength [I] Size of the Ole10 Native Data + * + * RETURNS + * Nothing + * + * NOTES + * This function is used by OleConvertOLESTREAMToIStorage only. + * + * Might need to verify the data and return appropriate error message + * + */ +void OLECONVERT_CreateOle10NativeStream(LPSTORAGE pStorage, BYTE *pData, DWORD dwDataLength) +{ + HRESULT hRes; + IStream *pStream; + WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0}; + + /* Create the Ole10Native Stream */ + hRes = IStorage_CreateStream(pStorage, wstrStreamName, + STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); + + if(hRes == S_OK) + { + /* Write info to stream */ + hRes = IStream_Write(pStream, &dwDataLength, sizeof(dwDataLength), NULL); + hRes = IStream_Write(pStream, pData, dwDataLength, NULL); + IStream_Release(pStream); + } + +} + +/************************************************************************* + * OLECONVERT_GetOLE10ProgID [Internal] + * + * Finds the ProgID (or OleTypeID) from the IStorage + * + * PARAMS + * pStorage [I] The Src IStorage to get the ProgID + * strProgID [I] the ProgID string to get + * dwSize [I] the size of the string + * + * RETURNS + * Success: S_OK + * Failure: REGDB_E_CLASSNOTREG if cannot reconstruct the stream + * + * NOTES + * This function is used by OleConvertIStorageToOLESTREAM only. + * + * + */ +HRESULT OLECONVERT_GetOLE10ProgID(LPSTORAGE pStorage, char *strProgID, DWORD *dwSize) +{ + HRESULT hRes; + IStream *pStream; + LARGE_INTEGER iSeekPos; + OLECONVERT_ISTORAGE_COMPOBJ CompObj; + WCHAR wstrStreamName[] = {1,'C', 'o', 'm', 'p', 'O', 'b', 'j', 0}; + + /* Open the CompObj Stream */ + hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream ); + if(hRes == S_OK) + { + + /*Get the OleType from the CompObj Stream */ + iSeekPos.u.LowPart = sizeof(CompObj.byUnknown1) + sizeof(CompObj.clsid); + iSeekPos.u.HighPart = 0; + + IStream_Seek(pStream, iSeekPos, STREAM_SEEK_SET, NULL); + IStream_Read(pStream, &CompObj.dwCLSIDNameLength, sizeof(CompObj.dwCLSIDNameLength), NULL); + iSeekPos.u.LowPart = CompObj.dwCLSIDNameLength; + IStream_Seek(pStream, iSeekPos, STREAM_SEEK_CUR , NULL); + IStream_Read(pStream, &CompObj.dwOleTypeNameLength, sizeof(CompObj.dwOleTypeNameLength), NULL); + iSeekPos.u.LowPart = CompObj.dwOleTypeNameLength; + IStream_Seek(pStream, iSeekPos, STREAM_SEEK_CUR , NULL); + + IStream_Read(pStream, dwSize, sizeof(*dwSize), NULL); + if(*dwSize > 0) + { + IStream_Read(pStream, strProgID, *dwSize, NULL); + } + IStream_Release(pStream); + } + else + { + STATSTG stat; + LPOLESTR wstrProgID; + + /* Get the OleType from the registry */ + REFCLSID clsid = &(stat.clsid); + IStorage_Stat(pStorage, &stat, STATFLAG_NONAME); + hRes = ProgIDFromCLSID(clsid, &wstrProgID); + if(hRes == S_OK) + { + *dwSize = WideCharToMultiByte(CP_ACP, 0, wstrProgID, -1, strProgID, *dwSize, NULL, FALSE); + } + + } + return hRes; +} + +/************************************************************************* + * OLECONVERT_GetOle10PresData [Internal] + * + * Converts IStorage "/001Ole10Native" stream to a OLE10 Stream + * + * PARAMS + * pStorage [I] Src IStroage + * pOleStream [I] Dest OleStream Mem Struct + * + * RETURNS + * Nothing + * + * NOTES + * This function is used by OleConvertIStorageToOLESTREAM only. + * + * Memory allocated for pData must be freed by the caller + * + * + */ +void OLECONVERT_GetOle10PresData(LPSTORAGE pStorage, OLECONVERT_OLESTREAM_DATA *pOleStreamData) +{ + + HRESULT hRes; + IStream *pStream; + WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0}; + + /* Initialize Default data for OLESTREAM */ + pOleStreamData[0].dwOleID = OLESTREAM_ID; + pOleStreamData[0].dwTypeID = 2; + pOleStreamData[1].dwOleID = OLESTREAM_ID; + pOleStreamData[1].dwTypeID = 0; + pOleStreamData[0].dwMetaFileWidth = 0; + pOleStreamData[0].dwMetaFileHeight = 0; + pOleStreamData[0].pData = NULL; + pOleStreamData[1].pData = NULL; + + /* Open Ole10Native Stream */ + hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream ); + if(hRes == S_OK) + { + + /* Read Size and Data */ + IStream_Read(pStream, &(pOleStreamData->dwDataLength), sizeof(pOleStreamData->dwDataLength), NULL); + if(pOleStreamData->dwDataLength > 0) + { + pOleStreamData->pData = (LPSTR) HeapAlloc(GetProcessHeap(),0,pOleStreamData->dwDataLength); + IStream_Read(pStream, pOleStreamData->pData, pOleStreamData->dwDataLength, NULL); + } + IStream_Release(pStream); + } + +} + + +/************************************************************************* + * OLECONVERT_GetOle20PresData[Internal] + * + * Converts IStorage "/002OlePres000" stream to a OLE10 Stream + * + * PARAMS + * pStorage [I] Src IStroage + * pOleStreamData [I] Dest OleStream Mem Struct + * + * RETURNS + * Nothing + * + * NOTES + * This function is used by OleConvertIStorageToOLESTREAM only. + * + * Memory allocated for pData must be freed by the caller + */ +void OLECONVERT_GetOle20PresData(LPSTORAGE pStorage, OLECONVERT_OLESTREAM_DATA *pOleStreamData) +{ + HRESULT hRes; + IStream *pStream; + OLECONVERT_ISTORAGE_OLEPRES olePress; + WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0}; + + /* Initialize Default data for OLESTREAM */ + pOleStreamData[0].dwOleID = OLESTREAM_ID; + pOleStreamData[0].dwTypeID = 2; + pOleStreamData[0].dwMetaFileWidth = 0; + pOleStreamData[0].dwMetaFileHeight = 0; + pOleStreamData[0].dwDataLength = OLECONVERT_WriteOLE20ToBuffer(pStorage, &(pOleStreamData[0].pData)); + pOleStreamData[1].dwOleID = OLESTREAM_ID; + pOleStreamData[1].dwTypeID = 0; + pOleStreamData[1].dwOleTypeNameLength = 0; + pOleStreamData[1].strOleTypeName[0] = 0; + pOleStreamData[1].dwMetaFileWidth = 0; + pOleStreamData[1].dwMetaFileHeight = 0; + pOleStreamData[1].pData = NULL; + pOleStreamData[1].dwDataLength = 0; + + + /* Open OlePress000 stream */ + hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, + STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream ); + if(hRes == S_OK) + { + LARGE_INTEGER iSeekPos; + METAFILEPICT16 MetaFilePict; + char strMetafilePictName[] = "METAFILEPICT"; + + /* Set the TypeID for a Metafile */ + pOleStreamData[1].dwTypeID = 5; + + /* Set the OleTypeName to Metafile */ + pOleStreamData[1].dwOleTypeNameLength = strlen(strMetafilePictName) +1; + strcpy(pOleStreamData[1].strOleTypeName, strMetafilePictName); + + iSeekPos.u.HighPart = 0; + iSeekPos.u.LowPart = sizeof(olePress.byUnknown1); + + /* Get Presentation Data */ + IStream_Seek(pStream, iSeekPos, STREAM_SEEK_SET, NULL); + IStream_Read(pStream, &(olePress.dwExtentX), sizeof(olePress.dwExtentX), NULL); + IStream_Read(pStream, &(olePress.dwExtentY), sizeof(olePress.dwExtentY), NULL); + IStream_Read(pStream, &(olePress.dwSize), sizeof(olePress.dwSize), NULL); + + /*Set width and Height */ + pOleStreamData[1].dwMetaFileWidth = olePress.dwExtentX; + pOleStreamData[1].dwMetaFileHeight = -olePress.dwExtentY; + if(olePress.dwSize > 0) + { + /* Set Length */ + pOleStreamData[1].dwDataLength = olePress.dwSize + sizeof(METAFILEPICT16); + + /* Set MetaFilePict struct */ + MetaFilePict.mm = 8; + MetaFilePict.xExt = olePress.dwExtentX; + MetaFilePict.yExt = olePress.dwExtentY; + MetaFilePict.hMF = 0; + + /* Get Metafile Data */ + pOleStreamData[1].pData = (BYTE *) HeapAlloc(GetProcessHeap(),0,pOleStreamData[1].dwDataLength); + memcpy(pOleStreamData[1].pData, &MetaFilePict, sizeof(MetaFilePict)); + IStream_Read(pStream, &(pOleStreamData[1].pData[sizeof(MetaFilePict)]), pOleStreamData[1].dwDataLength-sizeof(METAFILEPICT16), NULL); + } + IStream_Release(pStream); + } +} + +/************************************************************************* + * OleConvertOLESTREAMToIStorage [OLE32.87] + * + * Read info on MSDN + * + * TODO + * DVTARGETDEVICE paramenter is not handled + * Still unsure of some mem fields for OLE 10 Stream + * Still some unknowns for the IStorage: "\002OlePres000", "\001CompObj", + * and "\001OLE" streams + * + */ +HRESULT WINAPI OleConvertOLESTREAMToIStorage ( + LPOLESTREAM pOleStream, + LPSTORAGE pstg, + const DVTARGETDEVICE* ptd) +{ + int i; + HRESULT hRes=S_OK; + OLECONVERT_OLESTREAM_DATA pOleStreamData[2]; + + memset(pOleStreamData, 0, sizeof(pOleStreamData)); + + if(ptd != NULL) + { + Print(MIN_TRACE, ("DVTARGETDEVICE is not NULL, unhandled parameter\n")); + } + + if(pstg == NULL || pOleStream == NULL) + { + hRes = E_INVALIDARG; + } + + if(hRes == S_OK) + { + /* Load the OLESTREAM to Memory */ + hRes = OLECONVERT_LoadOLE10(pOleStream, &pOleStreamData[0], TRUE); + } + + if(hRes == S_OK) + { + /* Load the OLESTREAM to Memory (part 2)*/ + hRes = OLECONVERT_LoadOLE10(pOleStream, &pOleStreamData[1], FALSE); + } + + if(hRes == S_OK) + { + + if(pOleStreamData[0].dwDataLength > sizeof(STORAGE_magic)) + { + /* Do we have the IStorage Data in the OLESTREAM */ + if(memcmp(pOleStreamData[0].pData, STORAGE_magic, sizeof(STORAGE_magic)) ==0) + { + OLECONVERT_GetOLE20FromOLE10(pstg, pOleStreamData[0].pData, pOleStreamData[0].dwDataLength); + OLECONVERT_CreateOlePresStream(pstg, pOleStreamData[1].dwMetaFileWidth, pOleStreamData[1].dwMetaFileHeight, pOleStreamData[1].pData, pOleStreamData[1].dwDataLength); + } + else + { + /* It must be an original OLE 1.0 source */ + OLECONVERT_CreateOle10NativeStream(pstg, pOleStreamData[0].pData, pOleStreamData[0].dwDataLength); + } + } + else + { + /* It must be an original OLE 1.0 source */ + OLECONVERT_CreateOle10NativeStream(pstg, pOleStreamData[0].pData, pOleStreamData[0].dwDataLength); + } + + /* Create CompObj Stream if necessary */ + hRes = OLECONVERT_CreateCompObjStream(pstg, pOleStreamData[0].strOleTypeName); + if(hRes == S_OK) + { + /*Create the Ole Stream if necessary */ + OLECONVERT_CreateOleStream(pstg); + } + } + + + /* Free allocated memory */ + for(i=0; i < 2; i++) + { + if(pOleStreamData[i].pData != NULL) + { + HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData); + } + if(pOleStreamData[i].pstrOleObjFileName != NULL) + { + HeapFree(GetProcessHeap(),0,pOleStreamData[i].pstrOleObjFileName); + pOleStreamData[i].pstrOleObjFileName = NULL; + } + } + return hRes; +} + +/************************************************************************* + * OleConvertIStorageToOLESTREAM [OLE32.85] + * + * Read info on MSDN + * + * Read info on MSDN + * + * TODO + * Still unsure of some mem fields for OLE 10 Stream + * Still some unknowns for the IStorage: "\002OlePres000", "\001CompObj", + * and "\001OLE" streams. + * + */ +HRESULT WINAPI OleConvertIStorageToOLESTREAM ( + LPSTORAGE pstg, + LPOLESTREAM pOleStream) +{ + int i; + HRESULT hRes = S_OK; + IStream *pStream; + OLECONVERT_OLESTREAM_DATA pOleStreamData[2]; + WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0}; + + + memset(pOleStreamData, 0, sizeof(pOleStreamData)); + + if(pstg == NULL || pOleStream == NULL) + { + hRes = E_INVALIDARG; + } + if(hRes == S_OK) + { + /* Get the ProgID */ + pOleStreamData[0].dwOleTypeNameLength = OLESTREAM_MAX_STR_LEN; + hRes = OLECONVERT_GetOLE10ProgID(pstg, pOleStreamData[0].strOleTypeName, &(pOleStreamData[0].dwOleTypeNameLength)); + } + if(hRes == S_OK) + { + /*Was it originaly Ole10 */ + hRes = IStorage_OpenStream(pstg, wstrStreamName, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream); + if(hRes == S_OK) + { + IStream_Release(pStream); + /*Get Presentation Data for Ole10Native */ + OLECONVERT_GetOle10PresData(pstg, pOleStreamData); + } + else + { + /*Get Presentation Data (OLE20)*/ + OLECONVERT_GetOle20PresData(pstg, pOleStreamData); + } + + /* Save OLESTREAM */ + hRes = OLECONVERT_SaveOLE10(&(pOleStreamData[0]), pOleStream); + if(hRes == S_OK) + { + hRes = OLECONVERT_SaveOLE10(&(pOleStreamData[1]), pOleStream); + } + + } + + /* Free allocated memory */ + for(i=0; i < 2; i++) + { + if(pOleStreamData[i].pData != NULL) + { + HeapFree(GetProcessHeap(),0,pOleStreamData[i].pData); + } + } + + return hRes; +} + +/*********************************************************************** + * GetConvertStg (OLE32.68) + */ +HRESULT WINAPI GetConvertStg(LPGUID guid) { + UNIMPLEMENTED; + return E_FAIL; +} diff --git a/lib/oleaut32/.cvsignore b/lib/oleaut32/.cvsignore new file mode 100644 index 0000000..ec7bd12 --- /dev/null +++ b/lib/oleaut32/.cvsignore @@ -0,0 +1,3 @@ +oleaut32.coff +oleaut32.dll +oleaut32.nostrip.dll \ No newline at end of file diff --git a/lib/oleaut32/dllmain.c b/lib/oleaut32/dllmain.c new file mode 100644 index 0000000..a736927 --- /dev/null +++ b/lib/oleaut32/dllmain.c @@ -0,0 +1,37 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/oldaut32/misc/dllmain.c + * PURPOSE: Library main function + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + */ + +#include +#include + +#define NDEBUG +#include + +INT STDCALL +DllMain(PVOID hinstDll, + ULONG dwReason, + PVOID reserved) +{ + DPRINT("OLEAUT32: DllMain() called\n"); + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + + DPRINT("OLEAUT32: DllMain() done\n"); + + return TRUE; +} + + diff --git a/lib/oleaut32/makefile b/lib/oleaut32/makefile new file mode 100644 index 0000000..566ba31 --- /dev/null +++ b/lib/oleaut32/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_DEFONLY = yes + +TARGET_TYPE = dynlink + +TARGET_NAME = oleaut32 + +TARGET_BASE = 0x76260000 + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = dllmain.o stubs.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/lib/oleaut32/oleaut32.def b/lib/oleaut32/oleaut32.def new file mode 100644 index 0000000..6695606 --- /dev/null +++ b/lib/oleaut32/oleaut32.def @@ -0,0 +1,495 @@ +LIBRARY oleaut32.dll +EXPORTS +DllGetClassObject=DllGetClassObject@0 ; @ 1 +SysAllocString@4 ; @ 2 +SysReAllocString@8 ; @ 3 +SysAllocStringLen@8 ; @ 4 +SysReAllocStringLen@12 ; @ 5 +SysFreeString@4 ; @ 6 +SysStringLen@4 ; @ 7 +VariantInit@4 ; @ 8 +VariantClear@4 ; @ 9 +VariantCopy@8 ; @ 10 +VariantCopyInd@8 ; @ 11 +VariantChangeType@16 ; @ 12 +VariantTimeToDosDateTime=VariantTimeToDosDateTime@0 ; @ 13 +DosDateTimeToVariantTime@12 ; @ 14 +SafeArrayCreate@12 ; @ 15 +SafeArrayDestroy@4 ; @ 16 +SafeArrayGetDim@4 ; @ 17 +SafeArrayGetElemsize@4 ; @ 18 +SafeArrayGetUBound@12 ; @ 19 +SafeArrayGetLBound@12 ; @ 20 +SafeArrayLock@4 ; @ 21 +SafeArrayUnlock@4 ; @ 22 +SafeArrayAccessData@8 ; @ 23 +SafeArrayUnaccessData@4 ; @ 24 +SafeArrayGetElement@12 ; @ 25 +SafeArrayPutElement@12 ; @ 26 +SafeArrayCopy@8 ; @ 27 +DispGetParam@20 ; @ 28 +DispGetIDsOfNames@16 ; @ 29 +DispInvoke@32 ; @ 30 +CreateDispTypeInfo@12 ; @ 31 +CreateStdDispatch@16 ; @ 32 +RegisterActiveObject@16 ; @ 33 +RevokeActiveObject@8 ; @ 34 +GetActiveObject@12 ; @ 35 +SafeArrayAllocDescriptor@8 ; @ 36 +SafeArrayAllocData@4 ; @ 37 +SafeArrayDestroyDescriptor@4 ; @ 38 +SafeArrayDestroyData@4 ; @ 39 +SafeArrayRedim@8 ; @ 40 +OACreateTypeLib2=OACreateTypeLib2@0 ; @ 41 +OleAut32Ord42@0=UnknownOrdStub@0 ; @ 42 +OleAut32Ord43@0=UnknownOrdStub@0 ; @ 43 +OleAut32Ord44@0=UnknownOrdStub@0 ; @ 44 +OleAut32Ord45@0=UnknownOrdStub@0 ; @ 45 +VarParseNumFromStr=VarParseNumFromStr@0 ; @ 46 +VarNumFromParseNum=VarNumFromParseNum@0 ; @ 47 +VarI2FromUI1@8 ; @ 48 +VarI2FromI4@8 ; @ 49 +VarI2FromR4@8 ; @ 50 +VarI2FromR8@8 ; @ 51 +VarI2FromCy@8 ; @ 52 +VarI2FromDate@8 ; @ 53 +VarI2FromStr@16 ; @ 54 +VarI2FromDisp=VarI2FromDisp@0 ; @ 55 +VarI2FromBool@8 ; @ 56 +OleAut32Ord57@0=UnknownOrdStub@0 ; @ 57 +VarI4FromUI1@8 ; @ 58 +VarI4FromI2@8 ; @ 59 +VarI4FromR4@8 ; @ 60 +VarI4FromR8@8 ; @ 61 +VarI4FromCy@8 ; @ 62 +VarI4FromDate@8 ; @ 63 +VarI4FromStr@16 ; @ 64 +VarI4FromDisp=VarI4FromDisp@0 ; @ 65 +VarI4FromBool@8 ; @ 66 +OleAut32Ord67@0=UnknownOrdStub@0 ; @ 67 +VarR4FromUI1@8 ; @ 68 +VarR4FromI2@8 ; @ 69 +VarR4FromI4@8 ; @ 70 +VarR4FromR8@8 ; @ 71 +VarR4FromCy@8 ; @ 72 +VarR4FromDate@8 ; @ 73 +VarR4FromStr@16 ; @ 74 +VarR4FromDisp=VarR4FromDisp@0 ; @ 75 +VarR4FromBool@8 ; @ 76 +SafeArrayGetVarType@8 ; @ 77 +VarR8FromUI1@8 ; @ 78 +VarR8FromI2@8 ; @ 79 +VarR8FromI4@8 ; @ 80 +VarR8FromR4@8 ; @ 81 +VarR8FromCy@8 ; @ 82 +VarR8FromDate@8 ; @ 83 +VarR8FromStr@16 ; @ 84 +VarR8FromDisp ; @ 85 +VarR8FromBool@8 ; @ 86 +OleAut32Ord87@0=UnknownOrdStub@0 ; @ 87 +VarDateFromUI1@8 ; @ 88 +VarDateFromI2@8 ; @ 89 +VarDateFromI4@8 ; @ 90 +VarDateFromR4@8 ; @ 91 +VarDateFromR8@8 ; @ 92 +VarDateFromCy@8 ; @ 93 +VarDateFromStr@16 ; @ 94 +VarDateFromDisp=VarDateFromDisp@0 ; @ 95 +VarDateFromBool@8 ; @ 96 +OleAut32Ord97@0=UnknownOrdStub@0 ; @ 97 +VarCyFromUI1@8 ; @ 98 +VarCyFromI2@8 ; @ 99 +VarCyFromI4@8 ; @ 100 +VarCyFromR4@8 ; @ 101 +VarCyFromR8@8 ; @ 102 +VarCyFromDate@8 ; @ 103 +VarCyFromStr@16 ; @ 104 +VarCyFromDisp=VarCyFromDisp@0 ; @ 105 +VarCyFromBool@8 ; @ 106 +OleAut32Ord107@0=UnknownOrdStub@0 ; @ 107 +VarBstrFromUI1@16 ; @ 108 +VarBstrFromI2@16 ; @ 109 +VarBstrFromI4@16 ; @ 110 +VarBstrFromR4@16 ; @ 111 +VarBstrFromR8@16 ; @ 112 +VarBstrFromCy@16 ; @ 113 +VarBstrFromDate@16 ; @ 114 +VarBstrFromDisp=VarBstrFromDisp@0 ; @ 115 +VarBstrFromBool@16 ; @ 116 +OleAut32Ord117@0=UnknownOrdStub@0 ; @ 117 +VarBoolFromUI1@8 ; @ 118 +VarBoolFromI2@8 ; @ 119 +VarBoolFromI4@8 ; @ 120 +VarBoolFromR4@8 ; @ 121 +VarBoolFromR8@8 ; @ 122 +VarBoolFromDate@8 ; @ 123 +VarBoolFromCy@8 ; @ 124 +VarBoolFromStr@16 ; @ 125 +VarBoolFromDisp=VarBoolFromDisp@0 ; @ 126 +OleAut32Ord127@0=UnknownOrdStub@0 ; @ 127 +OleAut32Ord128@0=UnknownOrdStub@0 ; @ 128 +OleAut32Ord129@0=UnknownOrdStub@0 ; @ 129 +VarUI1FromI2@8 ; @ 130 +VarUI1FromI4@8 ; @ 131 +VarUI1FromR4@8 ; @ 132 +VarUI1FromR8@8 ; @ 133 +VarUI1FromCy@8 ; @ 134 +VarUI1FromDate@8 ; @ 135 +VarUI1FromStr@16 ; @ 136 +VarUI1FromDisp=VarUI1FromDisp@0 ; @ 137 +VarUI1FromBool@8 ; @ 138 +OleAut32Ord139@0=UnknownOrdStub@0 ; @ 139 +OleAut32Ord140@0=UnknownOrdStub@0 ; @ 140 +OleAut32Ord141@0=UnknownOrdStub@0 ; @ 141 +OleAut32Ord142@0=UnknownOrdStub@0 ; @ 142 +OleAut32Ord143@0=UnknownOrdStub@0 ; @ 143 +OleAut32Ord144@0=UnknownOrdStub@0 ; @ 144 +OleAut32Ord145@0=UnknownOrdStub@0 ; @ 145 +DispCallFunc=DispCallFunc@0 ; @ 146 +VariantChangeTypeEx@20 ; @ 147 +SafeArrayPtrOfIndex@12 ; @ 148 +SysStringByteLen@4 ; @ 149 +SysAllocStringByteLen@8 ; @ 150 +OleAut32Ord151@0=UnknownOrdStub@0 ; @ 151 +OleAut32Ord152@0=UnknownOrdStub@0 ; @ 152 +OleAut32Ord153@0=UnknownOrdStub@0 ; @ 153 +OleAut32Ord154@0=UnknownOrdStub@0 ; @ 154 +OleAut32Ord155@0=UnknownOrdStub@0 ; @ 155 +OleAut32Ord156@0=UnknownOrdStub@0 ; @ 156 +OleAut32Ord157@0=UnknownOrdStub@0 ; @ 157 +OleAut32Ord158@0=UnknownOrdStub@0 ; @ 158 +OleAut32Ord159@0=UnknownOrdStub@0 ; @ 159 +CreateTypeLib@12 ; @ 160 +LoadTypeLib@8 ; @ 161 +LoadRegTypeLib@20 ; @ 162 +RegisterTypeLib@12 ; @ 163 +QueryPathOfRegTypeLib@20 ; @ 164 +LHashValOfNameSys@12 ; @ 165 +LHashValOfNameSysA@12 ; @ 166 +OleAut32Ord167@0=UnknownOrdStub@0 ; @ 167 +OleAut32Ord168@0=UnknownOrdStub@0 ; @ 168 +OleAut32Ord169@0=UnknownOrdStub@0 ; @ 169 +OaBuildVersion@0 ; @ 170 +ClearCustData=ClearCustData@0 ; @ 171 +OleAut32Ord172@0=UnknownOrdStub@0 ; @ 172 +OleAut32Ord173@0=UnknownOrdStub@0 ; @ 173 +OleAut32Ord174@0=UnknownOrdStub@0 ; @ 174 +OleAut32Ord175@0=UnknownOrdStub@0 ; @ 175 +OleAut32Ord176@0=UnknownOrdStub@0 ; @ 176 +OleAut32Ord177@0=UnknownOrdStub@0 ; @ 177 +OleAut32Ord178@0=UnknownOrdStub@0 ; @ 178 +OleAut32Ord179@0=UnknownOrdStub@0 ; @ 179 +CreateTypeLib2=CreateTypeLib2@0 ; @ 180 +OleAut32Ord181@0=UnknownOrdStub@0 ; @ 181 +OleAut32Ord182@0=UnknownOrdStub@0 ; @ 182 +LoadTypeLibEx@12 ; @ 183 +SystemTimeToVariantTime=SystemTimeToVariantTime@0 ; @ 184 +VariantTimeToSystemTime=VariantTimeToSystemTime@0 ; @ 185 +UnRegisterTypeLib@20 ; @ 186 +OleAut32Ord187@0=UnknownOrdStub@0 ; @ 187 +OleAut32Ord188@0=UnknownOrdStub@0 ; @ 188 +OleAut32Ord189@0=UnknownOrdStub@0 ; @ 189 +VarDecFromUI1=VarDecFromUI1@0 ; @ 190 +VarDecFromI2=VarDecFromI2@0 ; @ 191 +VarDecFromI4 ; @ 192 (left off here with aliases) +VarDecFromR4 ; @ 193 +VarDecFromR8 ; @ 194 +VarDecFromDate ; @ 195 +VarDecFromCy ; @ 196 +VarDecFromStr ; @ 197 +VarDecFromDisp ; @ 198 +VarDecFromBool ; @ 199 +GetErrorInfo=ole32.GetErrorInfo ; @ 200 +SetErrorInfo=ole32.SetErrorInfo ; @ 201 +CreateErrorInfo=ole32.CreateErrorInfo ; @ 202 +OleAut32Ord203@0=UnknownOrdStub@0 ; @ 203 +OleAut32Ord204@0=UnknownOrdStub@0 ; @ 204 +VarI2FromI1@8 ; @ 205 +VarI2FromUI2@8 ; @ 206 +VarI2FromUI4@8 ; @ 207 +VarI2FromDec ; @ 208 +VarI4FromI1@8 ; @ 209 +VarI4FromUI2@8 ; @ 210 +VarI4FromUI4@8 ; @ 211 +VarI4FromDec ; @ 212 +VarR4FromI1@8 ; @ 213 +VarR4FromUI2@8 ; @ 214 +VarR4FromUI4@8 ; @ 215 +VarR4FromDec ; @ 216 +VarR8FromI1@8 ; @ 217 +VarR8FromUI2@8 ; @ 218 +VarR8FromUI4@8 ; @ 219 +VarR8FromDec ; @ 220 +VarDateFromI1@8 ; @ 221 +VarDateFromUI2@8 ; @ 222 +VarDateFromUI4@8 ; @ 223 +VarDateFromDec ; @ 224 +VarCyFromI1@8 ; @ 225 +VarCyFromUI2@8 ; @ 226 +VarCyFromUI4@8 ; @ 227 +VarCyFromDec ; @ 228 +VarBstrFromI1@16 ; @ 229 +VarBstrFromUI2@16 ; @ 230 +VarBstrFromUI4@16 ; @ 231 +VarBstrFromDec ; @ 232 +VarBoolFromI1@8 ; @ 233 +VarBoolFromUI2@8 ; @ 234 +VarBoolFromUI4@8 ; @ 235 +VarBoolFromDec ; @ 236 +VarUI1FromI1@8 ; @ 237 +VarUI1FromUI2@8 ; @ 238 +VarUI1FromUI4@8 ; @ 239 +VarUI1FromDec ; @ 240 +VarDecFromI1 ; @ 241 +VarDecFromUI2 ; @ 242 +VarDecFromUI4 ; @ 243 +VarI1FromUI1@8 ; @ 244 +VarI1FromI2@8 ; @ 245 +VarI1FromI4@8 ; @ 246 +VarI1FromR4@8 ; @ 247 +VarI1FromR8@8 ; @ 248 +VarI1FromDate@8 ; @ 249 +VarI1FromCy@8 ; @ 250 +VarI1FromStr@16 ; @ 251 +VarI1FromDisp ; @ 252 +VarI1FromBool@8 ; @ 253 +VarI1FromUI2@8 ; @ 254 +VarI1FromUI4@8 ; @ 255 +VarI1FromDec ; @ 256 +VarUI2FromUI1@8 ; @ 257 +VarUI2FromI2@8 ; @ 258 +VarUI2FromI4@8 ; @ 259 +VarUI2FromR4@8 ; @ 260 +VarUI2FromR8@8 ; @ 261 +VarUI2FromDate@8 ; @ 262 +VarUI2FromCy@8 ; @ 263 +VarUI2FromStr@16 ; @ 264 +VarUI2FromDisp ; @ 265 +VarUI2FromBool@8 ; @ 266 +VarUI2FromI1@8 ; @ 267 +VarUI2FromUI4@8 ; @ 268 +VarUI2FromDec ; @ 269 +VarUI4FromUI1@8 ; @ 270 +VarUI4FromI2@8 ; @ 271 +VarUI4FromI4@8 ; @ 272 +VarUI4FromR4@8 ; @ 273 +VarUI4FromR8@8 ; @ 274 +VarUI4FromDate@8 ; @ 275 +VarUI4FromCy@8 ; @ 276 +VarUI4FromStr@16 ; @ 277 +VarUI4FromDisp ; @ 278 +VarUI4FromBool@8 ; @ 279 +VarUI4FromI1@8 ; @ 280 +VarUI4FromUI2@8 ; @ 281 +VarUI4FromDec ; @ 282 +BSTR_UserSize ; @ 283 +BSTR_UserMarshal ; @ 284 +BSTR_UserUnmarshal ; @ 285 +BSTR_UserFree ; @ 286 +VARIANT_UserSize ; @ 287 +VARIANT_UserMarshal ; @ 288 +VARIANT_UserUnmarshal ; @ 289 +VARIANT_UserFree ; @ 290 +LPSAFEARRAY_UserSize ; @ 291 +LPSAFEARRAY_UserMarshal ; @ 292 +LPSAFEARRAY_UserUnmarshal ; @ 293 +LPSAFEARRAY_UserFree ; @ 294 +LPSAFEARRAY_Size ; @ 295 +LPSAFEARRAY_Marshal ; @ 296 +LPSAFEARRAY_Unmarshal ; @ 297 +OleAut32Ord298@0=UnknownOrdStub@0 ; @ 298 +OleAut32Ord299@0=UnknownOrdStub@0 ; @ 299 +OleAut32Ord300@0=UnknownOrdStub@0 ; @ 300 +OleAut32Ord301@0=UnknownOrdStub@0 ; @ 301 +OleAut32Ord302@0=UnknownOrdStub@0 ; @ 302 +OleAut32Ord303@0=UnknownOrdStub@0 ; @ 303 +OleAut32Ord304@0=UnknownOrdStub@0 ; @ 304 +OleAut32Ord305@0=UnknownOrdStub@0 ; @ 305 +OleAut32Ord306@0=UnknownOrdStub@0 ; @ 306 +OleAut32Ord307@0=UnknownOrdStub@0 ; @ 307 +OleAut32Ord308@0=UnknownOrdStub@0 ; @ 308 +OleAut32Ord309@0=UnknownOrdStub@0 ; @ 309 +OleAut32Ord310@0=UnknownOrdStub@0 ; @ 310 +OleAut32Ord311@0=UnknownOrdStub@0 ; @ 311 +OleAut32Ord312@0=UnknownOrdStub@0 ; @ 312 +OleAut32Ord313@0=UnknownOrdStub@0 ; @ 313 +OleAut32Ord314@0=UnknownOrdStub@0 ; @ 314 +OleAut32Ord315@0=UnknownOrdStub@0 ; @ 315 +OleAut32Ord316@0=UnknownOrdStub@0 ; @ 316 +OleAut32Ord317@0=UnknownOrdStub@0 ; @ 317 +OleAut32Ord318@0=UnknownOrdStub@0 ; @ 318 +OleAut32Ord319@0=UnknownOrdStub@0 ; @ 319 +DllRegisterServer@0 ; @ 320 +DllUnregisterServer@0 ; @ 321 +OleAut32Ord322@0=UnknownOrdStub@0 ; @ 322 +OleAut32Ord323@0=UnknownOrdStub@0 ; @ 323 +OleAut32Ord324@0=UnknownOrdStub@0 ; @ 324 +OleAut32Ord325@0=UnknownOrdStub@0 ; @ 325 +OleAut32Ord326@0=UnknownOrdStub@0 ; @ 326 +OleAut32Ord327@0=UnknownOrdStub@0 ; @ 327 +OleAut32Ord328@0=UnknownOrdStub@0 ; @ 328 +OleAut32Ord329@0=UnknownOrdStub@0 ; @ 329 +VarDateFromUdate ; @ 330 +VarUdateFromDate ; @ 331 +GetAltMonthNames ; @ 332 +OleAut32Ord333@0=UnknownOrdStub@0 ; @ 333 +OleAut32Ord334@0=UnknownOrdStub@0 ; @ 334 +OleAut32Ord335@0=UnknownOrdStub@0 ; @ 335 +OleAut32Ord336@0=UnknownOrdStub@0 ; @ 336 +OleAut32Ord337@0=UnknownOrdStub@0 ; @ 337 +OleAut32Ord338@0=UnknownOrdStub@0 ; @ 338 +OleAut32Ord339@0=UnknownOrdStub@0 ; @ 339 +OleAut32Ord340@0=UnknownOrdStub@0 ; @ 340 +OleAut32Ord341@0=UnknownOrdStub@0 ; @ 341 +OleAut32Ord342@0=UnknownOrdStub@0 ; @ 342 +OleAut32Ord343@0=UnknownOrdStub@0 ; @ 343 +OleAut32Ord344@0=UnknownOrdStub@0 ; @ 344 +OleAut32Ord345@0=UnknownOrdStub@0 ; @ 345 +OleAut32Ord346@0=UnknownOrdStub@0 ; @ 346 +OleAut32Ord347@0=UnknownOrdStub@0 ; @ 347 +OleAut32Ord348@0=UnknownOrdStub@0 ; @ 348 +OleAut32Ord349@0=UnknownOrdStub@0 ; @ 349 +OleAut32Ord350@0=UnknownOrdStub@0 ; @ 350 +OleAut32Ord351@0=UnknownOrdStub@0 ; @ 351 +OleAut32Ord352@0=UnknownOrdStub@0 ; @ 352 +OleAut32Ord353@0=UnknownOrdStub@0 ; @ 353 +OleAut32Ord354@0=UnknownOrdStub@0 ; @ 354 +OleAut32Ord355@0=UnknownOrdStub@0 ; @ 355 +OleAut32Ord356@0=UnknownOrdStub@0 ; @ 356 +OleAut32Ord357@0=UnknownOrdStub@0 ; @ 357 +OleAut32Ord358@0=UnknownOrdStub@0 ; @ 358 +OleAut32Ord359@0=UnknownOrdStub@0 ; @ 359 +OleAut32Ord360@0=UnknownOrdStub@0 ; @ 360 +OleAut32Ord361@0=UnknownOrdStub@0 ; @ 361 +OleAut32Ord362@0=UnknownOrdStub@0 ; @ 362 +OleAut32Ord363@0=UnknownOrdStub@0 ; @ 363 +OleAut32Ord364@0=UnknownOrdStub@0 ; @ 364 +OleAut32Ord365@0=UnknownOrdStub@0 ; @ 365 +OleAut32Ord366@0=UnknownOrdStub@0 ; @ 366 +OleAut32Ord367@0=UnknownOrdStub@0 ; @ 367 +OleAut32Ord368@0=UnknownOrdStub@0 ; @ 368 +OleAut32Ord369@0=UnknownOrdStub@0 ; @ 369 +OleAut32Ord370@0=UnknownOrdStub@0 ; @ 370 +OleAut32Ord371@0=UnknownOrdStub@0 ; @ 371 +OleAut32Ord372@0=UnknownOrdStub@0 ; @ 372 +OleAut32Ord373@0=UnknownOrdStub@0 ; @ 373 +OleAut32Ord374@0=UnknownOrdStub@0 ; @ 374 +OleAut32Ord375@0=UnknownOrdStub@0 ; @ 375 +OleAut32Ord376@0=UnknownOrdStub@0 ; @ 376 +OleAut32Ord377@0=UnknownOrdStub@0 ; @ 377 +OleAut32Ord378@0=UnknownOrdStub@0 ; @ 378 +OleAut32Ord379@0=UnknownOrdStub@0 ; @ 379 +UserHWND_from_local ; @ 380 +UserHWND_to_local ; @ 381 +UserHWND_free_inst ; @ 382 +UserHWND_free_local ; @ 383 +UserBSTR_from_local ; @ 384 +UserBSTR_to_local ; @ 385 +UserBSTR_free_inst ; @ 386 +UserBSTR_free_local ; @ 387 +UserVARIANT_from_local ; @ 388 +UserVARIANT_to_local ; @ 389 +UserVARIANT_free_inst ; @ 390 +UserVARIANT_free_local ; @ 391 +UserEXCEPINFO_from_local ; @ 392 +UserEXCEPINFO_to_local ; @ 393 +UserEXCEPINFO_free_inst ; @ 394 +UserEXCEPINFO_free_local ; @ 395 +UserMSG_from_local ; @ 396 +UserMSG_to_local ; @ 397 +UserMSG_free_inst ; @ 398 +UserMSG_free_local ; @ 399 +OleAut32Ord400@0=UnknownOrdStub@0 ; @ 400 +OleAut32Ord401@0=UnknownOrdStub@0 ; @ 401 +OleAut32Ord402@0=UnknownOrdStub@0 ; @ 402 +OleAut32Ord403@0=UnknownOrdStub@0 ; @ 403 +OleAut32Ord404@0=UnknownOrdStub@0 ; @ 404 +OleAut32Ord405@0=UnknownOrdStub@0 ; @ 405 +OleAut32Ord406@0=UnknownOrdStub@0 ; @ 406 +OleAut32Ord407@0=UnknownOrdStub@0 ; @ 407 +OleAut32Ord408@0=UnknownOrdStub@0 ; @ 408 +OleAut32Ord409@0=UnknownOrdStub@0 ; @ 409 +DllCanUnloadNow ; @ 410 +SafeArrayCreateVector@12 ; @ 411 +SafeArrayCopyData@8 ; @ 412 +VectorFromBstr ; @ 413 +BstrFromVector ; @ 414 +OleIconToCursor@8 ; @ 415 +OleCreatePropertyFrameIndirect@4 ; @ 416 +OleCreatePropertyFrame@44 ; @ 417 +OleLoadPicture@20 ; @ 418 +OleCreatePictureIndirect@16 ; @ 419 +OleCreateFontIndirect@12 ; @ 420 +OleTranslateColor@12 ; @ 421 +OleLoadPictureFile ; @ 422 +OleSavePictureFile ; @ 423 +OleLoadPicturePath ; @ 424 +OleLoadPictureEx@32 ; @ 425 +GetRecordInfoFromGuids@24 ; @ 426 +GetRecordInfoFromTypeInfo@8 ; @ 427 +OleLoadPictureFileEx ; @ 428 +SafeArrayAllocDescriptorEx ; @ 429 +SafeArrayCreateEx ; @ 430 +SafeArrayCreateVectorEx ; @ 431 +SafeArrayGetIID ; @ 432 +SafeArrayGetRecordInfo ; @ 433 +SafeArraySetIID ; @ 434 +SafeArraySetRecordInfo ; @ 435 +VarAbs@8 ; @ 436 +VarAdd@12 ; @ 437 +VarAnd@12 ; @ 438 +VarBstrCat@12 ; @ 439 +VarBstrCmp@16 ; @ 440 +VarCat@12 ; @ 441 +VarCmp@16 ; @ 442 +VarCyAbs ; @ 443 +VarCyAdd ; @ 444 +VarCyCmp ; @ 445 +VarCyCmpR8 ; @ 446 +VarCyFix ; @ 447 +VarCyInt ; @ 448 +VarCyMul ; @ 449 +VarCyMulI4 ; @ 450 +VarCyNeg ; @ 451 +VarCyRound ; @ 452 +VarCySub ; @ 453 +VarDateFromUdateEx@16 ; @ 454 +VarDecAbs@8 ; @ 455 +VarDecAdd@12 ; @ 456 +VarDecCmp@8 ; @ 457 +VarDecCmpR8@8 ; @ 458 +VarDecDiv@12 ; @ 459 +VarDecFix@8 ; @ 460 +VarDecInt@8 ; @ 461 +VarDecMul@12 ; @ 462 +VarDecNeg@8 ; @ 463 +VarDecRound@12 ; @ 464 +VarDecSub@12 ; @ 465 +VarDiv@12 ; @ 466 +VarEqv@12 ; @ 467 +VarFix@8 ; @ 468 +VarFormat@24 ; @ 469 +VarFormatCurrency@28 ; @ 470 +VarFormatDateTime@16 ; @ 471 +VarFormatFromTokens@24 ; @ 472 +VarFormatNumber@28 ; @ 473 +VarFormatPercent@28 ; @ 474 +VarIdiv@12 ; @ 475 +VarImp@12 ; @ 476 +VarInt@8 ; @ 477 +VarMod@12 ; @ 478 +VarMonthName@16 ; @ 479 +VarMul@12 ; @ 480 +VarNeg@8 ; @ 481 +VarNot@8 ; @ 482 +VarOr@12 ; @ 483 +VarPow@12 ; @ 484 +VarR4CmpR8 ; @ 485 +VarR8Pow@12 ; @ 486 +VarR8Round@12 ; @ 487 +VarRound@12 ; @ 488 +VarSub@12 ; @ 489 +VarTokenizeFormatString@28 ; @ 490 +VarWeekdayName@20 ; @ 491 +VarXor@12 ; @ 492 + diff --git a/lib/oleaut32/oleaut32.rc b/lib/oleaut32/oleaut32.rc new file mode 100644 index 0000000..f6cdfb9 --- /dev/null +++ b/lib/oleaut32/oleaut32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "OLE for ReactOS\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "oleaut32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "oleaut32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/oleaut32/stubs.c b/lib/oleaut32/stubs.c new file mode 100644 index 0000000..0b8fe5a --- /dev/null +++ b/lib/oleaut32/stubs.c @@ -0,0 +1,2160 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/oldaut32/stubs.c + * PURPOSE: Stubbed exports + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + */ + +#include +#include + +#define NDEBUG +#include + +#define FIXME \ + do \ + { \ + DbgPrint ("%s(%d):%s not implemented\n", __FILE__, __LINE__, __FUNCTION__); \ + } \ + while (0) + +VOID +DllGetClassObject (VOID) +{ + FIXME; +} + +VOID STDCALL +SysAllocString (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SysReAllocString (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +SysAllocStringLen (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +SysReAllocStringLen (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SysFreeString (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SysStringLen (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +VariantInit (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +VariantClear (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +VariantCopy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VariantCopyInd (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VariantChangeType (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VariantTimeToDosDateTime (VOID) +{ + FIXME; +} + +VOID STDCALL +DosDateTimeToVariantTime (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayCreate (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayDestroy (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetDim (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetElemsize (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetUBound (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetLBound (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayLock (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayUnlock (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayAccessData (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +SafeArrayUnaccessData (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetElement (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayPutElement (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayCopy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +DispGetParam (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +DispGetIDsOfNames (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +DispInvoke (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7, DWORD Unknown8) +{ + FIXME; +} + +VOID STDCALL +CreateDispTypeInfo (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +CreateStdDispatch (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +RegisterActiveObject (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +RevokeActiveObject (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +GetActiveObject (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayAllocDescriptor (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +SafeArrayAllocData (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayDestroyDescriptor (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayDestroyData (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SafeArrayRedim (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +OACreateTypeLib2 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarParseNumFromStr (VOID) +{ + FIXME; +} + +VOID STDCALL +VarNumFromParseNum (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI2FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarI2FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI2FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarI4FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI4FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarR4FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarR4FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetVarType (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarR8FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarR8FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarDateFromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDateFromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarCyFromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyFromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromUI1 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromI2 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromI4 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromR4 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromR8 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromCy (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromDate (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromBool (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +DispCallFunc (VOID) +{ + FIXME; +} + +VOID STDCALL +VariantChangeTypeEx (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +SafeArrayPtrOfIndex (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SysStringByteLen (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +SysAllocStringByteLen (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +CreateTypeLib (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +LoadTypeLib (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +LoadRegTypeLib (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +RegisterTypeLib (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +QueryPathOfRegTypeLib (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +LHashValOfNameSys (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +LHashValOfNameSysA (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +OaBuildVersion (VOID) +{ + FIXME; +} + +VOID STDCALL +ClearCustData (VOID) +{ + FIXME; +} + +VOID STDCALL +CreateTypeLib2 (VOID) +{ + FIXME; +} + +VOID STDCALL +LoadTypeLibEx (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SystemTimeToVariantTime (VOID) +{ + FIXME; +} + +VOID STDCALL +VariantTimeToSystemTime (VOID) +{ + FIXME; +} + +VOID STDCALL +UnRegisterTypeLib (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +VarDecFromUI1 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromI2 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromI4 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromR4 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromR8 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromDate (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromCy (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromStr (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromBool (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI2FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI2FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI4FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI4FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarR4FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR4FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarR8FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarR8FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDateFromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDateFromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyFromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarCyFromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromI1 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromUI2 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromUI4 (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarBstrFromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarBoolFromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI1FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromI1 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromUI2 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDecFromUI4 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI1FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarI1FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarI1FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarI1FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromUI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI2FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromUI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromI4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromR4 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromDate (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromCy (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromStr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromDisp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromBool (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromI1 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromUI2 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarUI4FromDec (VOID) +{ + FIXME; +} + +VOID STDCALL +BSTR_UserSize (VOID) +{ + FIXME; +} + +VOID STDCALL +BSTR_UserMarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +BSTR_UserUnmarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +BSTR_UserFree (VOID) +{ + FIXME; +} + +VOID STDCALL +VARIANT_UserSize (VOID) +{ + FIXME; +} + +VOID STDCALL +VARIANT_UserMarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +VARIANT_UserUnmarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +VARIANT_UserFree (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_UserSize (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_UserMarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_UserUnmarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_UserFree (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_Size (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_Marshal (VOID) +{ + FIXME; +} + +VOID STDCALL +LPSAFEARRAY_Unmarshal (VOID) +{ + FIXME; +} + +VOID STDCALL +DllRegisterServer (VOID) +{ + FIXME; +} + +VOID STDCALL +DllUnregisterServer (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDateFromUdate (VOID) +{ + FIXME; +} + +VOID STDCALL +VarUdateFromDate (VOID) +{ + FIXME; +} + +VOID STDCALL +GetAltMonthNames (VOID) +{ + FIXME; +} + +VOID STDCALL +UserHWND_from_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserHWND_to_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserHWND_free_inst (VOID) +{ + FIXME; +} + +VOID STDCALL +UserHWND_free_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserBSTR_from_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserBSTR_to_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserBSTR_free_inst (VOID) +{ + FIXME; +} + +VOID STDCALL +UserBSTR_free_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserVARIANT_from_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserVARIANT_to_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserVARIANT_free_inst (VOID) +{ + FIXME; +} + +VOID STDCALL +UserVARIANT_free_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserEXCEPINFO_from_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserEXCEPINFO_to_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserEXCEPINFO_free_inst (VOID) +{ + FIXME; +} + +VOID STDCALL +UserEXCEPINFO_free_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserMSG_from_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserMSG_to_local (VOID) +{ + FIXME; +} + +VOID STDCALL +UserMSG_free_inst (VOID) +{ + FIXME; +} + +VOID STDCALL +UserMSG_free_local (VOID) +{ + FIXME; +} + +VOID STDCALL +DllCanUnloadNow (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArrayCreateVector (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +SafeArrayCopyData (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VectorFromBstr (VOID) +{ + FIXME; +} + +VOID STDCALL +BstrFromVector (VOID) +{ + FIXME; +} + +VOID STDCALL +OleIconToCursor (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +OleCreatePropertyFrameIndirect (DWORD Unknown1) +{ + FIXME; +} + +VOID STDCALL +OleCreatePropertyFrame (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, + DWORD Unknown5, DWORD Unknown6, DWORD Unknown7, DWORD Unknown8, + DWORD Unknown9, DWORD Unknown10, DWORD Unknown11) +{ + FIXME; +} + +VOID STDCALL +OleLoadPicture (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +OleCreatePictureIndirect (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +OleCreateFontIndirect (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +OleTranslateColor (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +OleLoadPictureFile (VOID) +{ + FIXME; +} + +VOID STDCALL +OleSavePictureFile (VOID) +{ + FIXME; +} + +VOID STDCALL +OleLoadPicturePath (VOID) +{ + FIXME; +} + +VOID STDCALL +OleLoadPictureEx (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7, DWORD Unknown8) +{ + FIXME; +} + +VOID STDCALL +GetRecordInfoFromGuids (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + FIXME; +} + +VOID STDCALL +GetRecordInfoFromTypeInfo (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +OleLoadPictureFileEx (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArrayAllocDescriptorEx (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArrayCreateEx (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArrayCreateVectorEx (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetIID (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArrayGetRecordInfo (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArraySetIID (VOID) +{ + FIXME; +} + +VOID STDCALL +SafeArraySetRecordInfo (VOID) +{ + FIXME; +} + +VOID STDCALL +VarAbs (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarAdd (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarAnd (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarBstrCat (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarBstrCmp (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarCat (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarCmp (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarCyAbs (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyAdd (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyCmp (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyCmpR8 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyFix (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyInt (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyMul (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyMulI4 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyNeg (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCyRound (VOID) +{ + FIXME; +} + +VOID STDCALL +VarCySub (VOID) +{ + FIXME; +} + +VOID STDCALL +VarDateFromUdateEx (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarDecAbs (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDecAdd (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarDecCmp (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDecCmpR8 (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDecDiv (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarDecFix (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDecInt (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDecMul (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarDecNeg (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarDecRound (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarDecSub (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarDiv (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarEqv (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarFix (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarFormat (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + FIXME; +} + +VOID STDCALL +VarFormatCurrency (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + FIXME; +} + +VOID STDCALL +VarFormatDateTime (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarFormatFromTokens (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + FIXME; +} + +VOID STDCALL +VarFormatNumber (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + FIXME; +} + +VOID STDCALL +VarFormatPercent (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + FIXME; +} + +VOID STDCALL +VarIdiv (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarImp (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarInt (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarMod (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarMonthName (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + FIXME; +} + +VOID STDCALL +VarMul (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarNeg (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarNot (DWORD Unknown1, DWORD Unknown2) +{ + FIXME; +} + +VOID STDCALL +VarOr (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarPow (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarR4CmpR8 (VOID) +{ + FIXME; +} + +VOID STDCALL +VarR8Pow (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarR8Round (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarRound (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarSub (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +VarTokenizeFormatString (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + FIXME; +} + +VOID STDCALL +VarWeekdayName (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + FIXME; +} + +VOID STDCALL +VarXor (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + FIXME; +} + +VOID STDCALL +UnknownOrdStub (VOID) +{ + FIXME; +} + diff --git a/lib/packet/.cvsignore b/lib/packet/.cvsignore new file mode 100644 index 0000000..bbdfcbf --- /dev/null +++ b/lib/packet/.cvsignore @@ -0,0 +1,19 @@ +packet.coff +packet.dll +packet.nostrip.dll +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/packet/Packet32.c b/lib/packet/Packet32.c new file mode 100644 index 0000000..5f0a06d --- /dev/null +++ b/lib/packet/Packet32.c @@ -0,0 +1,2056 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define UNICODE 1 + +#include +#include +//#include +#include + +#include "trace.h" + + +/****** KERNEL Macro APIs ******************************************************/ + +#define GetInstanceModule(hInst) (HMODULE)(hInst) +#define GlobalPtrHandle(lp) ((HGLOBAL)GlobalHandle(lp)) +#define GlobalLockPtr(lp) ((BOOL)GlobalLock(GlobalPtrHandle(lp))) +#define GlobalUnlockPtr(lp) GlobalUnlock(GlobalPtrHandle(lp)) +#define GlobalAllocPtr(flags, cb) (GlobalLock(GlobalAlloc((flags), (cb)))) +#define GlobalReAllocPtr(lp, cbNew, flags) (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags)))) +#define GlobalFreePtr(lp) (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp))) + +#undef GMEM_MOVEABLE +#define GMEM_MOVEABLE 0 + + + +/// Title of error windows +TCHAR szWindowTitle[] = TEXT("PACKET.DLL"); + +#if DBG +#define ODS(_x) OutputDebugString(TEXT(_x)) +//#define ODSEx(_x, _y) +#define ODSEx TRACE +#else +#ifdef _DEBUG_TO_FILE +#include +/*! + \brief Macro to print a debug string. The behavior differs depending on the debug level +*/ +#define ODS(_x) { \ + FILE *f; \ + f = fopen("winpcap_debug.txt", "a"); \ + fprintf(f, "%s", _x); \ + fclose(f); \ +} +/*! + \brief Macro to print debug data with the printf convention. The behavior differs depending on + the debug level +*/ +#define ODSEx(_x, _y) { \ + FILE *f; \ + f = fopen("winpcap_debug.txt", "a"); \ + fprintf(f, _x, _y); \ + fclose(f); \ +} + +LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName); +#else +#define ODS(_x) +#define ODSEx(_x, _y) +#endif +#endif + +//service handles +SC_HANDLE scmHandle = NULL; +SC_HANDLE srvHandle = NULL; +LPCTSTR NPFServiceName = TEXT("NPF"); +LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter"); +LPCTSTR NPFDriverName = TEXT("\\npf.sys"); +LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF"); + + +//--------------------------------------------------------------------------- + +/*! + \brief The main dll function. +*/ + +BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved) +{ + BOOLEAN Status=TRUE; + + switch ( Reason ) + { + case DLL_PROCESS_ATTACH: + + ODS("\n************Packet32: DllMain************\n"); + +#ifdef _DEBUG_TO_FILE + // dump a bunch of registry keys useful for debug to file + PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", + "adapters.reg"); + PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip", + "tcpip.reg"); + PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF", + "npf.reg"); + PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services", + "services.reg"); +#endif + break; + + case DLL_PROCESS_DETACH: + break; + + default: + break; + } + + return Status; +} + +/*! + \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function. + \param string The string to convert. + \return The converted string. +*/ + +WCHAR* SChar2WChar(char* string) +{ + WCHAR* TmpStr; + TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR)); + + MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2)); + + return TmpStr; +} + +/*! + \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function. + \param AdapterObject Handle to the service control manager. + \return If the function succeeds, the return value is nonzero. + + The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory + without performing a copy. This function tries to increase the size of that buffer. +*/ + +BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject) +{ + BOOLEAN Status; + ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1); + PPACKET_OID_DATA OidData; + + OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength); + if (OidData == NULL) { + ODS("PacketSetMaxLookaheadsize failed\n"); + return FALSE; + } + + //set the size of the lookahead buffer to the maximum available by the the NIC driver + OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD; + OidData->Length=sizeof(ULONG); + Status=PacketRequest(AdapterObject,FALSE,OidData); + OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD; + Status=PacketRequest(AdapterObject,TRUE,OidData); + GlobalFreePtr(OidData); + return Status; +} + +/*! + \brief Retrieves the event associated in the driver with a capture instance and stores it in an + _ADAPTER structure. + \param AdapterObject Handle to the service control manager. + \return If the function succeeds, the return value is nonzero. + + This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl + call and set it in the _ADAPTER structure pointed by AdapterObject. +*/ + +BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject) +{ + DWORD BytesReturned; + WCHAR EventName[39]; + + // this tells the terminal service to retrieve the event from the global namespace + wcsncpy(EventName,L"Global\\",sizeof(L"Global\\")); + + // retrieve the name of the shared event from the driver + if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE; + + EventName[20]=0; // terminate the string + + // open the shared event + AdapterObject->ReadEvent=CreateEventW(NULL, + TRUE, + FALSE, + EventName); + + // in NT4 "Global\" is not automatically ignored: try to use simply the event name + if(GetLastError()!=ERROR_ALREADY_EXISTS){ + if(AdapterObject->ReadEvent != NULL) + CloseHandle(AdapterObject->ReadEvent); + + // open the shared event + AdapterObject->ReadEvent=CreateEventW(NULL, + TRUE, + FALSE, + EventName+7); + } + + if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){ + ODS("PacketSetReadEvt: error retrieving the event from the kernel\n"); + return FALSE; + } + + AdapterObject->ReadTimeOut=0; + + return TRUE; + +} + +/*! + \brief Installs the NPF device driver. + \param ascmHandle Handle to the service control manager. + \param ascmHandle A pointer to a handle that will receive the pointer to the driver's service. + \param driverPath The full path of the .sys file to load. + \return If the function succeeds, the return value is nonzero. + + This function installs the driver's service in the system using the CreateService function. +*/ + +BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath) +{ + BOOL result = FALSE; + ULONG err; + + ODS("installdriver\n"); + + if (GetFileAttributes(driverPath) != 0xffffffff) { + *srvHandle = CreateService(ascmHandle, + NPFServiceName, + NPFServiceDesc, + SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + driverPath, + NULL, NULL, NULL, NULL, NULL); + if (*srvHandle == NULL) { + if (GetLastError() == ERROR_SERVICE_EXISTS) { + //npf.sys already existed + result = TRUE; + } + } else { + //Created service for npf.sys + result = TRUE; + } + } + if (result == TRUE) { + if (*srvHandle != NULL) { + CloseServiceHandle(*srvHandle); + } + } + + if (result == FALSE){ + err = GetLastError(); + if (err != 2) { + ODSEx("PacketInstallDriver failed, Error=%d\n",err); + } + } + return result; + +} + +/*! + \brief Convert a Unicode dotted-quad to a 32-bit IP address. + \param cp A string containing the address. + \return the converted 32-bit numeric address. + + Doesn't check to make sure the address is valid. +*/ + + +ULONG inet_addrU(const WCHAR *cp) +{ + ULONG val, part; + WCHAR c; + int i; + + val = 0; + for (i = 0; i < 4; i++) { + part = 0; + while ((c = *cp++) != '\0' && c != '.') { + if (c < '0' || c > '9') + return -1; + part = part*10 + (c - '0'); + } + if (part > 255) + return -1; + val = val | (part << i*8); + if (i == 3) { + if (c != '\0') + return -1; // extra gunk at end of string + } else { + if (c == '\0') + return -1; // string ends early + } + } + return val; +} + +/*! + \brief Dumps a registry key to disk in text format. Uses regedit. + \param KeyName Name of the ket to dump. All its subkeys will be saved recursively. + \param FileName Name of the file that will contain the dump. + \return If the function succeeds, the return value is nonzero. + + For debugging purposes, we use this function to obtain some registry keys from the user's machine. +*/ + +#ifdef _DEBUG_TO_FILE + +LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName) +{ + CHAR Command[256]; + + strcpy(Command, "regedit /e "); + strcat(Command, FileName); + strcat(Command, " "); + strcat(Command, KeyName); + + /// Let regedit do the dirt work for us + system(Command); + + return TRUE; +} +#endif + +//--------------------------------------------------------------------------- +// PUBLIC API +//--------------------------------------------------------------------------- + +/** @ingroup packetapi + * @{ + */ + +/** @defgroup packet32 Packet.dll exported functions and variables + * @{ + */ + +/// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function. +char PacketLibraryVersion[] = "2.3"; + +/*! + \brief Returns a string with the dll version. + \return A char pointer to the version of the library. +*/ +PCHAR PacketGetVersion(){ + return PacketLibraryVersion; +} + +/*! + \brief Returns information about the MAC type of an adapter. + \param AdapterObject The adapter on which information is needed. + \param type Pointer to a NetType structure that will be filled by the function. + \return If the function succeeds, the return value is nonzero, otherwise the return value is zero. + + This function return the link layer technology and the speed (in bps) of an opened adapter. + The LinkType field of the type parameter can have one of the following values: + + - NdisMedium802_3: Ethernet (802.3) + - NdisMediumWan: WAN + - NdisMedium802_5: Token Ring (802.5) + - NdisMediumFddi: FDDI + - NdisMediumAtm: ATM + - NdisMediumArcnet878_2: ARCNET (878.2) +*/ +BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type) +{ + BOOLEAN Status; + ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1); + PPACKET_OID_DATA OidData; + + OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength); + if (OidData == NULL) { + ODS("PacketGetNetType failed\n"); + return FALSE; + } + //get the link-layer type + OidData->Oid = OID_GEN_MEDIA_IN_USE; + OidData->Length = sizeof (ULONG); + Status = PacketRequest(AdapterObject,FALSE,OidData); + type->LinkType=*((UINT*)OidData->Data); + + //get the link-layer speed + OidData->Oid = OID_GEN_LINK_SPEED; + OidData->Length = sizeof (ULONG); + Status = PacketRequest(AdapterObject,FALSE,OidData); + type->LinkSpeed=*((UINT*)OidData->Data)*100; + GlobalFreePtr (OidData); + + ODSEx("Media:%d ",type->LinkType); + ODSEx("Speed=%d\n",type->LinkSpeed); + + return Status; +} + +/*! + \brief Stops and unloads the WinPcap device driver. + \return If the function succeeds, the return value is nonzero, otherwise it is zero. + + This function can be used to unload the driver from memory when the application no more needs it. + Note that the driver is physically stopped and unloaded only when all the files on its devices + are closed, i.e. when all the applications that use WinPcap close all their adapters. +*/ +BOOL PacketStopDriver() +{ + SC_HANDLE scmHandle; + SC_HANDLE schService; + BOOL ret; + SERVICE_STATUS serviceStatus; + + scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if(scmHandle != NULL){ + + schService = OpenService (scmHandle, + NPFServiceName, + SERVICE_ALL_ACCESS + ); + + if (schService != NULL) + { + + ret = ControlService (schService, + SERVICE_CONTROL_STOP, + &serviceStatus + ); + if (!ret) + { + } + + CloseServiceHandle (schService); + + CloseServiceHandle(scmHandle); + + return ret; + } + } + + return FALSE; + +} + +/*! + \brief Opens an adapter. + \param AdapterName A string containing the name of the device to open. + Use the PacketGetAdapterNames() function to retrieve the list of available devices. + \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object, + otherwise the return value is NULL. + + This function tries to load and start the packet driver at the first invocation. In this way, + the management of the driver is transparent to the application, that simply needs to open an adapter to start + WinPcap. + + \note the Windows 95 version of the NPF driver works with the ASCII string format, while the Windows NT + version works with UNICODE. Therefore, AdapterName \b should be an ASCII string in Windows 95, and a UNICODE + string in Windows NT. This difference is not a problem if the string pointed by AdapterName was obtained + through the PacketGetAdapterNames function, because it returns the names of the adapters in the proper format. + Problems can arise in Windows NT when the string is obtained from ANSI C functions like scanf, because they + use the ASCII format. Since this could be a relevant problem during the porting of command-line applications + from UNIX, we included in the Windows NT version of PacketOpenAdapter the ability to detect ASCII strings and + convert them to UNICODE before sending them to the device driver. Therefore PacketOpenAdapter in Windows NT + accepts both the ASCII and the UNICODE format. If a ASCII string is received, it is converted to UNICODE + by PACKET.DLL before being passed to the driver. +*/ +LPADAPTER PacketOpenAdapter(LPTSTR AdapterName) +{ + LPADAPTER lpAdapter; + BOOLEAN Result; + char *AdapterNameA; + WCHAR *AdapterNameU; + DWORD error; + SC_HANDLE svcHandle = NULL; + TCHAR driverPath[512]; + TCHAR WinPath[256]; + LONG KeyRes; + HKEY PathKey; + SERVICE_STATUS SStat; + BOOLEAN QuerySStat; + WCHAR SymbolicLink[128]; + + ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName); + + scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if(scmHandle == NULL){ + error = GetLastError(); + ODSEx("OpenSCManager failed! Error=%d\n", error); + } else { + *driverPath = 0; + GetCurrentDirectory(512, driverPath); + wsprintf(driverPath + wcslen(driverPath), NPFDriverName); + + // check if the NPF registry key is already present + // this means that the driver is already installed and that we don't need to call PacketInstallDriver + KeyRes=RegOpenKeyEx(HKEY_LOCAL_MACHINE, + NPFRegistryLocation, + 0, + KEY_READ, + &PathKey); + + if(KeyRes != ERROR_SUCCESS){ + Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath); + } else { + Result = TRUE; + RegCloseKey(PathKey); + } + + if (Result) { + + srvHandle = OpenService(scmHandle, NPFServiceName, SERVICE_START | SERVICE_QUERY_STATUS ); + if (srvHandle != NULL){ + + QuerySStat = QueryServiceStatus(srvHandle, &SStat); + ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState); + + if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){ + ODS("Calling startservice\n"); + if (StartService(srvHandle, 0, NULL)==0){ + error = GetLastError(); + if (error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){ + SetLastError(error); + if (scmHandle != NULL) CloseServiceHandle(scmHandle); + error = GetLastError(); + ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error); + return NULL; + } + } + } + } else { + error = GetLastError(); + ODSEx("OpenService failed! Error=%d", error); + } + } else { + if (GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) { + return FALSE; + } + wsprintf(driverPath, TEXT("%s\\drivers%s"), WinPath, NPFDriverName); + + if (KeyRes != ERROR_SUCCESS) { + Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath); + } else { + Result = TRUE; + } + if (Result) { + srvHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START); + if (srvHandle != NULL) { + QuerySStat = QueryServiceStatus(srvHandle, &SStat); + ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState); + if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING) { + ODS("Calling startservice\n"); + if (StartService(srvHandle, 0, NULL) == 0) { + error = GetLastError(); + if (error != ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS) { + SetLastError(error); + if (scmHandle != NULL) CloseServiceHandle(scmHandle); + ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error); + return NULL; + } + } + } + } else { + error = GetLastError(); + ODSEx("OpenService failed! Error=%d", error); + } + } + } + } + if (scmHandle != NULL) CloseServiceHandle(scmHandle); + + AdapterNameA = (char*)AdapterName; + if (AdapterNameA[1] != 0) { // ASCII + AdapterNameU = SChar2WChar(AdapterNameA); + AdapterName = AdapterNameU; + } else { // Unicode + AdapterNameU = NULL; + } + + lpAdapter = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER)); + if (lpAdapter == NULL) { + ODS("PacketOpenAdapter: GlobalAlloc Failed\n"); + error = GetLastError(); + if (AdapterNameU != NULL) free(AdapterNameU); + //set the error to the one on which we failed + SetLastError(error); + ODS("PacketOpenAdapter: Failed to allocate the adapter structure\n"); + return NULL; + } + lpAdapter->NumWrites = 1; + + wsprintf(SymbolicLink,TEXT("\\\\.\\%s%s"), DOSNAMEPREFIX, &AdapterName[8]); + + // Copy only the bytes that fit in the adapter structure. + // Note that lpAdapter->SymbolicLink is present for backward compatibility but will + // never be used by the apps + memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH); + + //try if it is possible to open the adapter immediately + lpAdapter->hFile = CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0); + + if (lpAdapter->hFile != INVALID_HANDLE_VALUE) { + ODSEx("PacketOpenAdapter: CreateFile(%S) successfull\n", SymbolicLink); + if (PacketSetReadEvt(lpAdapter) == FALSE) { + error = GetLastError(); + ODS("PacketOpenAdapter: Unable to open the read event\n"); + if (AdapterNameU != NULL) + free(AdapterNameU); + GlobalFreePtr(lpAdapter); + //set the error to the one on which we failed + SetLastError(error); + ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=%d\n",error); + return NULL; + } + + PacketSetMaxLookaheadsize(lpAdapter); + if (AdapterNameU != NULL) + free(AdapterNameU); + return lpAdapter; + } + //this is probably the first request on the packet driver. + //We must create the dos device and set the access rights on it + else { + Result = DefineDosDevice(DDD_RAW_TARGET_PATH, + &SymbolicLink[4], + AdapterName); + if (Result) { + + ODSEx("PacketOpenAdapter: calling CreateFile(%S)\n", SymbolicLink); + + lpAdapter->hFile = CreateFile( + SymbolicLink, + GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0); + if (lpAdapter->hFile != INVALID_HANDLE_VALUE) { + if (PacketSetReadEvt(lpAdapter) == FALSE) { + error = GetLastError(); + ODS("PacketOpenAdapter: Unable to open the read event\n"); + if (AdapterNameU != NULL) + free(AdapterNameU); + GlobalFreePtr(lpAdapter); + //set the error to the one on which we failed + SetLastError(error); + ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=1,%d\n",error); + return NULL; + } + PacketSetMaxLookaheadsize(lpAdapter); + if (AdapterNameU != NULL) + free(AdapterNameU); + return lpAdapter; + } else { + ODS("PacketOpenAdapter: CreateFile failed\n"); + } + } else { + ODSEx("PacketOpenAdapter: DefineDosDevice(%S) failed\n", &SymbolicLink[4]); + } + } + error = GetLastError(); + if (AdapterNameU != NULL) + free(AdapterNameU); + GlobalFreePtr(lpAdapter); + //set the error to the one on which we failed + SetLastError(error); + ODSEx("PacketOpenAdapter: CreateFile failed, Error=2,%d\n",error); + return NULL; + +} + +/*! + \brief Closes an adapter. + \param lpAdapter the pointer to the adapter to close. + + PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure +*/ +VOID PacketCloseAdapter(LPADAPTER lpAdapter) +{ + CloseHandle(lpAdapter->hFile); + SetEvent(lpAdapter->ReadEvent); + CloseHandle(lpAdapter->ReadEvent); + GlobalFreePtr(lpAdapter); +} + +/*! + \brief Allocates a _PACKET structure. + \return On succeess, the return value is the pointer to a _PACKET structure otherwise the + return value is NULL. + + The structure returned will be passed to the PacketReceivePacket() function to receive the + packets from the driver. + + \warning The Buffer field of the _PACKET structure is not set by this function. + The buffer \b must be allocated by the application, and associated to the PACKET structure + with a call to PacketInitPacket. +*/ +LPPACKET PacketAllocatePacket(void) +{ + + LPPACKET lpPacket; + lpPacket = (LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET)); + if (lpPacket == NULL) { + ODS("PacketAllocatePacket: GlobalAlloc Failed\n"); + return NULL; + } + return lpPacket; +} + +/*! + \brief Frees a _PACKET structure. + \param lpPacket The structure to free. + + \warning the user-allocated buffer associated with the _PACKET structure is not deallocated + by this function and \b must be explicitly deallocated by the programmer. + +*/ +VOID PacketFreePacket(LPPACKET lpPacket) +{ + GlobalFreePtr(lpPacket); +} + +/*! + \brief Initializes a _PACKET structure. + \param lpPacket The structure to initialize. + \param Buffer A pointer to a user-allocated buffer that will contain the captured data. + \param Length the length of the buffer. This is the maximum buffer size that will be + transferred from the driver to the application using a single read. + + \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly + influence the performance of the capture process, since this buffer will contain the packets received + from the the driver. The driver is able to return several packets using a single read call + (see the PacketReceivePacket() function for details), and the number of packets transferable to the + application in a call is limited only by the size of the buffer associated with the PACKET structure + passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably + decrease the number of system calls, reducing the impcat of the capture process on the processor. +*/ + +VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length) +{ + lpPacket->Buffer = Buffer; + lpPacket->Length = Length; + lpPacket->ulBytesReceived = 0; + lpPacket->bIoComplete = FALSE; +} + +/*! + \brief Read data (packets or statistics) from the NPF driver. + \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which + the data is received. + \param lpPacket Pointer to a PACKET structure that will contain the data. + \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with + older applications. + \return If the function succeeds, the return value is nonzero. + + The data received with this function can be a group of packets or a static on the network traffic, + depending on the working mode of the driver. The working mode can be set with the PacketSetMode() + function. Give a look at that function if you are interested in the format used to return statistics + values, here only the normal capture mode will be described. + + The number of packets received with this function is variable. It depends on the number of packets + currently stored in the driver’s buffer, on the size of these packets and on the size of the buffer + associated to the lpPacket parameter. The following figure shows the format used by the driver to pass + packets to the application. + + \image html encoding.gif "method used to encode the packets" + + Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of + that structure is updated with the amount of data copied in the buffer. Each packet has a header + consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field + is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen + and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer. + + Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided + in the developer's pack, or in the pcap_read() function of wpcap. +*/ +BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync) +{ + BOOLEAN res; + if ((int)AdapterObject->ReadTimeOut != -1) + WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut); + res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL); + return res; +} + +/*! + \brief Sends one (or more) copies of a packet to the network. + \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will + send the packets. + \param lpPacket Pointer to a PACKET structure with the packet to send. + \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with + older applications. + \return If the function succeeds, the return value is nonzero. + + This function is used to send a raw packet to the network. 'Raw packet' means that the programmer + will have to include the protocol headers, since the packet is sent to the network 'as is'. + The CRC needs not to be calculated and put at the end of the packet, because it will be transparently + added by the network interface. + + The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(), + it is possible to change the number of times a single write must be repeated. The default is 1, + i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is + greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on + the network. This feature mitigates the overhead of the context switches and therefore can be used to generate + high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need + to obtain high network loads. + The optimized sending process is still limited to one packet at a time: for the moment it cannot be used + to send a buffer with multiple packets. + + \note The ability to write multiple packets is currently present only in the Windows NTx version of the + packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application + that uses the multiple write method will run in Windows 9x as well, but its performance will be very low + compared to the one of WindowsNTx. +*/ +BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync) +{ + DWORD BytesTransfered; + return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL); +} + + +/*! + \brief Sends a buffer of packets to the network. + \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will + send the packets. + \param PacketBuff Pointer to buffer with the packets to send. + \param Size Size of the buffer pointed by the PacketBuff argument. + \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as + fast as possible + \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an + error occurred during the send. The error can be caused by a driver/adapter problem or by an + inconsistent/bogus packet buffer. + + This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary + number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used + by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward. + 'Raw packets' means that the sending application will have to include the protocol headers, since every packet + is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be + transparently added by the network interface. + + \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are + buffered in the kernel driver, so the number of context switches is reduced. + + \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp. + This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds + (depending on the precision of the performance counter of the machine). Such a precision cannot be reached + sending the packets separately with PacketSendPacket(). +*/ +INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync) +{ + BOOLEAN Res; + DWORD BytesTransfered, TotBytesTransfered=0; + struct timeval BufStartTime; + LARGE_INTEGER StartTicks, CurTicks, TargetTicks, TimeFreq; + + + ODS("PacketSendPackets"); + + // Obtain starting timestamp of the buffer + BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec; + BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec; + + // Retrieve the reference time counters + QueryPerformanceCounter(&StartTicks); + QueryPerformanceFrequency(&TimeFreq); + + CurTicks.QuadPart = StartTicks.QuadPart; + + do{ + // Send the data to the driver + Res = DeviceIoControl(AdapterObject->hFile, + (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC, + (PCHAR)PacketBuff + TotBytesTransfered, + Size - TotBytesTransfered, + NULL, + 0, + &BytesTransfered, + NULL); + + TotBytesTransfered += BytesTransfered; + + // calculate the time interval to wait before sending the next packet + TargetTicks.QuadPart = StartTicks.QuadPart + + (LONGLONG) + ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 + + (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) * + (TimeFreq.QuadPart) / 1000000; + + // Exit from the loop on termination or error + if(TotBytesTransfered >= Size || Res != TRUE) + break; + + // Wait until the time interval has elapsed + while( CurTicks.QuadPart <= TargetTicks.QuadPart ) + QueryPerformanceCounter(&CurTicks); + + } + while(TRUE); + + return TotBytesTransfered; +} + +/*! + \brief Defines the minimum amount of data that will be received in a read. + \param AdapterObject Pointer to an _ADAPTER structure + \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to + release a read on this adapter. + \return If the function succeeds, the return value is nonzero. + + In presence of a large value for nbytes, the kernel waits for the arrival of several packets before + copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, + i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value + means that the kernel will copy the packets as soon as the application is ready to receive them. This is + suggested for real time applications (like, for example, a bridge) that need the better responsiveness from + the kernel. + + \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer + this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility. +*/ + +BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes) +{ + DWORD BytesReturned; + return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL); +} + +/*! + \brief Sets the working mode of an adapter. + \param AdapterObject Pointer to an _ADAPTER structure. + \param mode The new working mode of the adapter. + \return If the function succeeds, the return value is nonzero. + + The device driver of WinPcap has 4 working modes: + - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied + to the application when PacketReceivePacket() is called. This is the default working mode of an adapter. + - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at + precise intervals, statics values on the network traffic. The interval between the statistic samples is + by default 1 second but it can be set to any other value (with a 1 ms precision) with the + PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical + mode is shown in the following figure:

+ \image html stats.gif "data structure returned by statistical mode" + Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter + previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are + encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a + very low impact on system performance compared to capture mode. + - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This + method is much faster than saving the packets after having captured them. No data is returned + by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy + this filter are dumped to disk. + - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap + format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the + network traffic and on the amount of data saved to file, in a way similar to statistical mode. + The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in + the following figure:

+ \image html dump.gif "data structure returned by statistical dump mode" + Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the + effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are + dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly + by wpcap. + Look at the NetMeter example in the + WinPcap developer's pack to see how to use statistics mode. +*/ +BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode) +{ + DWORD BytesReturned; + return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL); +} + +/*! + \brief Sets the name of the file that will receive the packet when the adapter is in dump mode. + \param AdapterObject Pointer to an _ADAPTER structure. + \param name the file name, in ASCII or UNICODE. + \param len the length of the buffer containing the name, in bytes. + \return If the function succeeds, the return value is nonzero. + + This function defines the file name that the driver will open to store the packets on disk when + it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been + called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail. + If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver + closes the old file and opens the new one. +*/ + +BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len) +{ + DWORD BytesReturned; + WCHAR *FileName; + BOOLEAN res; + WCHAR NameWithPath[1024]; + int TStrLen; + WCHAR *NamePos; + + if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII + FileName=SChar2WChar(name); + len*=2; + } + else { //Unicode + FileName=name; + } + + TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos); + + len=TStrLen*2+2; //add the terminating null character + + // Try to catch malformed strings + if(len>2048){ + if(((PUCHAR)name)[1]!=0 && len>1) free(FileName); + return FALSE; + } + + res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL); + free(FileName); + return res; +} + +/*! + \brief Set the dump mode limits. + \param AdapterObject Pointer to an _ADAPTER structure. + \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit. + \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit. + \return If the function succeeds, the return value is nonzero. + + This function sets the limits after which the NPF driver stops to save the packets to file when an adapter + is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that + very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when + the first of the two is reached. + + \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush + correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter(). +*/ +BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks) +{ + DWORD BytesReturned; + UINT valbuff[2]; + + valbuff[0] = maxfilesize; + valbuff[1] = maxnpacks; + + return DeviceIoControl(AdapterObject->hFile, + pBIOCSETDUMPLIMITS, + valbuff, + sizeof valbuff, + NULL, + 0, + &BytesReturned, + NULL); +} + +/*! + \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached. + \param AdapterObject Pointer to an _ADAPTER structure. + \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately. + \return TRUE if the dump is ended, FALSE otherwise. + + PacketIsDumpEnded() informs the user about the limits that were set with a previous call to + PacketSetDumpLimits(). + + \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits + (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will + block the application on this call forever. +*/ +BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync) +{ + DWORD BytesReturned; + int IsDumpEnded; + BOOLEAN res; + + if(sync) + WaitForSingleObject(AdapterObject->ReadEvent, INFINITE); + + res = DeviceIoControl(AdapterObject->hFile, + pBIOCISDUMPENDED, + NULL, + 0, + &IsDumpEnded, + 4, + &BytesReturned, + NULL); + + if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished + + return (BOOLEAN)IsDumpEnded; +} + +/*! + \brief Returns the notification event associated with the read calls on an adapter. + \param AdapterObject Pointer to an _ADAPTER structure. + \return The handle of the event that the driver signals when some data is available in the kernel buffer. + + The event returned by this function is signaled by the driver if: + - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal + than the one set with the PacketSetMinToCopy() function is received from the network. + - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network + but the the timeout set with the PacketSetReadTimeout() function has elapsed. + - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the + PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available. + + In every case, a call to PacketReceivePacket() will return immediately. + The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects) + to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that + need to wait concurrently on several events. + +*/ +HANDLE PacketGetReadEvent(LPADAPTER AdapterObject) +{ + return AdapterObject->ReadEvent; +} + +/*! + \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network. + \param AdapterObject Pointer to an _ADAPTER structure. + \param nwrites Number of copies of a packet that will be physically sent by the interface. + \return If the function succeeds, the return value is nonzero. + + See PacketSendPacket() for details. +*/ +BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites) +{ + DWORD BytesReturned; + return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL); +} + +/*! + \brief Sets the timeout after which a read on an adapter returns. + \param AdapterObject Pointer to an _ADAPTER structure. + \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on + the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver. + Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives. + A timeout of -1 causes PacketReceivePacket() to always return immediately. + \return If the function succeeds, the return value is nonzero. + + \note This function works also if the adapter is working in statistics mode, and can be used to set the + time interval between two statistic reports. +*/ +BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout) +{ + DWORD BytesReturned; + int DriverTimeOut=-1; + + AdapterObject->ReadTimeOut=timeout; + + return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL); +} + +/*! + \brief Sets the size of the kernel-level buffer associated with a capture. + \param AdapterObject Pointer to an _ADAPTER structure. + \param dim New size of the buffer, in \b kilobytes. + \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to + allocate the new buffer. + + When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are + lost. + + Note: the dimension of the kernel buffer affects heavily the performances of the capture process. + An adequate buffer in the driver is able to keep the packets while the application is busy, compensating + the delays of the application and avoiding the loss of packets during bursts or high network activity. + The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to + set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture. +*/ +BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim) +{ + DWORD BytesReturned; + return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL); +} + +/*! + \brief Sets a kernel-level packet filter. + \param AdapterObject Pointer to an _ADAPTER structure. + \param fp Pointer to a filtering program that will be associated with this capture or monitoring + instance and that will be executed on every incoming packet. + \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs + or if the filter program is not accepted after a safeness check by the driver. The driver performs + the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non + conformat filters. + + This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a + set of bpf_insn instructions. + + A filter can be automatically created by using the pcap_compile() function of wpcap. This function + converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at + http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but + you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd + flags to obtain the pseudocode. + +*/ +BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp) +{ + DWORD BytesReturned; + return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL); +} + +/*! + \brief Returns a couple of statistic values about the current capture session. + \param AdapterObject Pointer to an _ADAPTER structure. + \param s Pointer to a user provided bpf_stat structure that will be filled by the function. + \return If the function succeeds, the return value is nonzero. + + With this function, the programmer can know the value of two internal variables of the driver: + + - the number of packets that have been received by the adapter AdapterObject, starting at the + time in which it was opened with PacketOpenAdapter. + - the number of packets that have been dropped by the driver. A packet is dropped when the kernel + buffer associated with the adapter is full. +*/ +BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s) +{ + BOOLEAN Res; + DWORD BytesReturned; + struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications + + Res = DeviceIoControl(AdapterObject->hFile, + pBIOCGSTATS, + NULL, + 0, + &tmpstat, + sizeof(struct bpf_stat), + &BytesReturned, + NULL); + + // Copy only the first two values retrieved from the driver + s->bs_recv = tmpstat.bs_recv; + s->bs_drop = tmpstat.bs_drop; + + return Res; +} + +/*! + \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats(). + \param AdapterObject Pointer to an _ADAPTER structure. + \param s Pointer to a user provided bpf_stat structure that will be filled by the function. + \return If the function succeeds, the return value is nonzero. + + With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus: + + - the number of drops by interface (not yet supported, always 0). + - the number of packets that reached the application, i.e that were accepted by the kernel filter and + that fitted in the kernel buffer. +*/ +BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s) +{ + BOOLEAN Res; + DWORD BytesReturned; + struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications + + Res = DeviceIoControl(AdapterObject->hFile, + pBIOCGSTATS, + NULL, + 0, + &tmpstat, + sizeof(struct bpf_stat), + &BytesReturned, + NULL); + + s->bs_recv = tmpstat.bs_recv; + s->bs_drop = tmpstat.bs_drop; + s->ps_ifdrop = tmpstat.ps_ifdrop; + s->bs_capt = tmpstat.bs_capt; + + return Res; +} + +/*! + \brief Performs a query/set operation on an internal variable of the network card driver. + \param AdapterObject Pointer to an _ADAPTER structure. + \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE). + \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data. + \return If the function succeeds, the return value is nonzero. + + \note not all the network adapters implement all the query/set functions. There is a set of mandatory + OID functions that is granted to be present on all the adapters, and a set of facultative functions, not + provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a + facultative function, be careful to enclose it in an if statement to check the result. +*/ +BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData) +{ + DWORD BytesReturned; + BOOLEAN Result; + + Result=DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? pBIOCSETOID : pBIOCQUERYOID, + OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData, + sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL); + + // output some debug info + ODSEx("PacketRequest, OID=%d ", OidData->Oid); + ODSEx("Length=%d ", OidData->Length); + ODSEx("Set=%d ", Set); + ODSEx("Res=%d\n", Result); + + return Result; +} + +/*! + \brief Sets a hardware filter on the incoming packets. + \param AdapterObject Pointer to an _ADAPTER structure. + \param Filter The identifier of the filter. + \return If the function succeeds, the return value is nonzero. + + The filter defined with this filter is evaluated by the network card, at a level that is under the NPF + device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h): + + - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter. + - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted. + - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted. + - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted. + - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted. + - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST +*/ +BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter) +{ + BOOLEAN Status; + ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1); + PPACKET_OID_DATA OidData; + + OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength); + if (OidData == NULL) { + ODS("PacketSetHwFilter: GlobalAlloc Failed\n"); + return FALSE; + } + OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER; + OidData->Length=sizeof(ULONG); + *((PULONG)OidData->Data)=Filter; + Status=PacketRequest(AdapterObject,TRUE,OidData); + GlobalFreePtr(OidData); + return Status; +} + +/*! + \brief Retrieve the list of available network adapters and their description. + \param pStr User allocated string that will be filled with the names of the adapters. + \param BufferSize Length of the buffer pointed by pStr. + \return If the function succeeds, the return value is nonzero. + + Usually, this is the first function that should be used to communicate with the driver. + It returns the names of the adapters installed on the system and supported by WinPcap. + After the names of the adapters, pStr contains a string that describes each of them. + + \b Warning: + the result of this function is obtained querying the registry, therefore the format + of the result in Windows NTx is different from the one in Windows 9x. Windows 9x uses the ASCII + encoding method to store a string, while Windows NTx uses UNICODE. After a call to PacketGetAdapterNames + in Windows 95x, pStr contains, in succession: + - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0" + - a double "\0" + - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number + of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and + so on. + - a double "\0". + + In Windows NTx, pStr contains: the names of the adapters, in UNICODE format, separated by a single UNICODE "\0" (i.e. 2 ASCII "\0"), a double UNICODE "\0", followed by the descriptions of the adapters, in ASCII format, separated by a single ASCII "\0" . The string is terminated by a double ASCII "\0". + - a variable number of UNICODE strings, each with the names of an adapter, separated by a UNICODE "\0" + - a double UNICODE "\0" + - a number of ASCII strings, each with the description of an adapter, separated by an ASCII "\0". + - a double ASCII "\0". +*/ + +BOOLEAN PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize) +{ + HKEY LinkageKey, AdapKey; + DWORD RegKeySize = 0; + LONG Status; + ULONG Result; + PTSTR BpStr; + char *TTpStr; + char *DpStr; + char *DescBuf; + LPADAPTER adapter; + PPACKET_OID_DATA OidData; + int i = 0, k, rewind; + DWORD dim; + TCHAR AdapName[256]; + + ODSEx("PacketGetAdapterNames: BufferSize=%d\n",*BufferSize); + + OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 512); + if (OidData == NULL) { + ODS("PacketGetAdapterNames: GlobalAlloc Failed\n"); + return FALSE; + } + + Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"), + 0, KEY_READ, &AdapKey); + + // Get the size to allocate for the original device names + while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) { + Status = RegOpenKeyEx(AdapKey, AdapName,0, KEY_READ, &LinkageKey); + Status = RegOpenKeyExW(LinkageKey, L"Linkage",0, KEY_READ, &LinkageKey); + Status = RegQueryValueExW(LinkageKey, L"Export", NULL, NULL, NULL, &dim); + i++; + if (Status!=ERROR_SUCCESS) continue; + RegKeySize += dim; + } + + // Allocate the memory for the original device names + ODSEx("Need %d bytes for the names\n", RegKeySize+2); + BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2); + if (BpStr == NULL || RegKeySize > *BufferSize) { + ODS("PacketGetAdapterNames: GlobalAlloc Failed\n"); + GlobalFreePtr(OidData); + return FALSE; + } + k = 0; + i = 0; + + ODS("PacketGetAdapterNames: Cycling through the adapters:\n"); + + // Copy the names to the buffer + while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) { + WCHAR UpperBindStr[64]; + + i++; + ODSEx(" %d) ", i); + + Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey); + Status = RegOpenKeyExW(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey); + + dim=sizeof(UpperBindStr); + Status=RegQueryValueExW(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim); + + ODSEx("UpperBind=%S ", UpperBindStr); + + if( Status!=ERROR_SUCCESS || _wcsicmp(UpperBindStr,L"NdisWan")==0 ){ + ODS("Name = SKIPPED\n"); + continue; + } + + dim=RegKeySize-k; + Status=RegQueryValueExW(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim); + if(Status!=ERROR_SUCCESS){ + ODS("Name = SKIPPED (error reading the key)\n"); + continue; + } + + ODSEx("Name = %S\n", (LPBYTE)BpStr+k); + + k+=dim-2; + } + + CloseHandle(AdapKey); + +#ifdef _DEBUG_TO_FILE + //dump BpStr for debug purposes + ODS("Dumping BpStr:"); + { + FILE *f; + f = fopen("winpcap_debug.txt", "a"); + for(i=0;i *BufferSize){ + // Input buffer too small + GlobalFreePtr(OidData); + GlobalFreePtr (BpStr); + GlobalFreePtr (DescBuf); + ODS("PacketGetAdapterNames: Input buffer too small!\n"); + return FALSE; + } + + // Create the device name + rewind=k; + memcpy(pStr+k,BpStr+i,16); + memcpy(pStr+k+8,TEXT("NPF_"),8); + i+=8; + k+=12; + while(BpStr[i-1]!=0){ + pStr[k++]=BpStr[i++]; + } + + // Open the adapter + adapter=PacketOpenAdapter(pStr+rewind); + if(adapter==NULL){ + k=rewind; + continue; + } + + // Retrieve the description + OidData->Oid = OID_GEN_VENDOR_DESCRIPTION; + OidData->Length = 256; + ZeroMemory(OidData->Data,256); + Status = PacketRequest(adapter,FALSE,OidData); + if(Status==0 || ((char*)OidData->Data)[0]==0){ + k=rewind; + continue; + } + + ODSEx("Adapter Description=%s\n\n",OidData->Data); + + // Copy the description + TTpStr=(char*)(OidData->Data); + while(*TTpStr!=0){ + *DpStr++=*TTpStr++; + } + *DpStr++=*TTpStr++; + + // Close the adapter + PacketCloseAdapter(adapter); + + } + *DpStr = 0; + + pStr[k++] = 0; + pStr[k] = 0; + + if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) { + memcpy(pStr + k, DescBuf, DpStr - DescBuf); + } else { + GlobalFreePtr(OidData); + GlobalFreePtr(BpStr); + GlobalFreePtr(DescBuf); + ODS("\nPacketGetAdapterNames: ended with failure\n"); + return FALSE; + } + + GlobalFreePtr(OidData); + GlobalFreePtr(BpStr); + GlobalFreePtr(DescBuf); + ODS("\nPacketGetAdapterNames: ended correctly\n"); + return TRUE; + } + else{ + DWORD RegType; + + ODS("Adapters not found under SYSTEM\\ControlSet001\\Control\\Class. Using the TCP/IP bindings.\n"); + + GlobalFreePtr(BpStr); + Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage"), + 0, KEY_READ, &LinkageKey); + if (Status == ERROR_SUCCESS) { + // Retrieve the length of the key + Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, NULL, &RegKeySize); + // Allocate the buffer + BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize + 2); + if (BpStr == NULL || RegKeySize > *BufferSize) { + GlobalFreePtr(OidData); + return FALSE; + } + Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, (LPBYTE)BpStr, &RegKeySize); + RegCloseKey(LinkageKey); + } else { + //ODS("SYSTEM\\ControlSet001\\Control\\Class - RegKey not found.\n"); + ODS("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage - RegKey not found.\n"); + } + if (Status == ERROR_SUCCESS) { + DescBuf = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096); + if (DescBuf == NULL) { + GlobalFreePtr(BpStr); + GlobalFreePtr(OidData); + return FALSE; + } + DpStr = DescBuf; + for (i = 0, k = 0; BpStr[i] != 0 || BpStr[i+1] != 0; ) { + if (k + wcslen(BpStr + i) + 30 > *BufferSize) { + // Input buffer too small + GlobalFreePtr(OidData); + GlobalFreePtr(BpStr); + GlobalFreePtr(DescBuf); + return FALSE; + } + + ODS("\tCreating a device name - started.\n"); + + // Create the device name + rewind = k; + memcpy(pStr + k,BpStr + i,16); + memcpy(pStr + k + 8, TEXT("NPF_"), 8); + i += 8; + k += 12; + while (BpStr[i - 1] != 0) { + pStr[k++] = BpStr[i++]; + } + // Open the adapter + adapter = PacketOpenAdapter(pStr+rewind); + if (adapter == NULL) { + k = rewind; + continue; + } + // Retrieve the description + OidData->Oid = OID_GEN_VENDOR_DESCRIPTION; + OidData->Length = 256; + Status = PacketRequest(adapter, FALSE, OidData); + if (Status == 0 || ((char*)OidData->Data)[0] == 0) { + k = rewind; + ODS("\tCreating a device name - Retrieve the description.\n"); + continue; + } + + // Copy the description + TTpStr = (char*)(OidData->Data); + while (*TTpStr != 0){ + *DpStr++ = *TTpStr++; + } + *DpStr++ = *TTpStr++; + // Close the adapter + PacketCloseAdapter(adapter); + + ODS("\tCreating a device name - completed.\n"); + } + *DpStr = 0; + + pStr[k++] = 0; + pStr[k] = 0; + + if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) { + memcpy(pStr + k, DescBuf, DpStr-DescBuf); + } else { + GlobalFreePtr(OidData); + GlobalFreePtr(BpStr); + GlobalFreePtr(DescBuf); + return FALSE; + } + + GlobalFreePtr(OidData); + GlobalFreePtr(BpStr); + GlobalFreePtr(DescBuf); + ODS("PacketGetAdapterNames() returning TRUE\n"); + return TRUE; + } else { + MessageBox(NULL,TEXT("Can not find TCP/IP bindings.\nIn order to run the packet capture driver you must install TCP/IP."),szWindowTitle,MB_OK); + ODS("Cannot find the TCP/IP bindings\n"); + return FALSE; + } + } +} + +/*! + \brief Returns comprehensive information the addresses of an adapter. + \param AdapterName String that contain _ADAPTER structure. + \param buffer A user allocated array of npf_if_addr that will be filled by the function. + \param NEntries Size of the array (in npf_if_addr). + \return If the function succeeds, the return value is nonzero. + + This function grabs from the registry information like the IP addresses, the netmasks + and the broadcast addresses of an interface. The buffer passed by the user is filled with + npf_if_addr structures, each of which contains the data for a single address. If the buffer + is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr) + if you want only the first address. +*/ + +BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries) +{ + char *AdapterNameA; + WCHAR *AdapterNameU; + WCHAR *ifname; + HKEY SystemKey; + HKEY InterfaceKey; + HKEY ParametersKey; + HKEY TcpIpKey; + HKEY UnderTcpKey; + LONG status; + WCHAR String[1024+1]; + DWORD RegType; + ULONG BufLen; + DWORD DHCPEnabled; + struct sockaddr_in *TmpAddr, *TmpBroad; + LONG naddrs,nmasks,StringPos; + DWORD ZeroBroadcast; + + AdapterNameA = (char*)AdapterName; + if(AdapterNameA[1] != 0) { //ASCII + AdapterNameU = SChar2WChar(AdapterNameA); + AdapterName = AdapterNameU; + } else { //Unicode + AdapterNameU = NULL; + } + ifname = wcsrchr(AdapterName, '\\'); + if (ifname == NULL) + ifname = AdapterName; + else + ifname++; + if (wcsncmp(ifname, L"NPF_", 4) == 0) + ifname += 4; + + if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"), + 0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS) + { + status = RegOpenKeyExW(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(UnderTcpKey); + goto fail; + } + } + else + { + + // Query the registry key with the interface's adresses + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\ControlSet001\\Services"), + 0,KEY_READ,&SystemKey); + if (status != ERROR_SUCCESS) + goto fail; + status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(SystemKey); + goto fail; + } + RegCloseKey(SystemKey); + status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(InterfaceKey); + goto fail; + } + RegCloseKey(InterfaceKey); + status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(ParametersKey); + goto fail; + } + RegCloseKey(ParametersKey); + BufLen = sizeof String; + } + + BufLen = 4; + /* Try to detect if the interface has a zero broadcast addr */ + status=RegQueryValueEx(TcpIpKey,TEXT("UseZeroBroadcast"),NULL,&RegType,(LPBYTE)&ZeroBroadcast,&BufLen); + if (status != ERROR_SUCCESS) + ZeroBroadcast=0; + + BufLen = 4; + /* See if DHCP is used by this system */ + status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen); + if (status != ERROR_SUCCESS) + DHCPEnabled=0; + + + /* Retrieve the adrresses */ + if(DHCPEnabled){ + + BufLen = sizeof String; + // Open the key with the addresses + status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen); + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + // scan the key to obtain the addresses + StringPos = 0; + for(naddrs = 0;naddrs <* NEntries;naddrs++){ + TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress); + + if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){ + TmpAddr->sin_family = AF_INET; + + TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast); + TmpBroad->sin_family = AF_INET; + if(ZeroBroadcast==0) + TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255 + else + TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0 + + while(*(String + StringPos) != 0)StringPos++; + StringPos++; + + if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen) + break; + } + else break; + } + + BufLen = sizeof String; + // Open the key with the netmasks + status = RegQueryValueEx(TcpIpKey,TEXT("DhcpSubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen); + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + // scan the key to obtain the masks + StringPos = 0; + for(nmasks = 0;nmasks < *NEntries;nmasks++){ + TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask); + + if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){ + TmpAddr->sin_family = AF_INET; + + while(*(String + StringPos) != 0)StringPos++; + StringPos++; + + if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen) + break; + } + else break; + } + + // The number of masks MUST be equal to the number of adresses + if(nmasks != naddrs){ + RegCloseKey(TcpIpKey); + goto fail; + } + + } + else{ + + BufLen = sizeof String; + // Open the key with the addresses + status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen); + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + // scan the key to obtain the addresses + StringPos = 0; + for(naddrs = 0;naddrs < *NEntries;naddrs++){ + TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress); + + if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){ + TmpAddr->sin_family = AF_INET; + + TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast); + TmpBroad->sin_family = AF_INET; + if(ZeroBroadcast==0) + TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255 + else + TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0 + + while(*(String + StringPos) != 0)StringPos++; + StringPos++; + + if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen) + break; + } + else break; + } + + BufLen = sizeof String; + // Open the key with the netmasks + status = RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen); + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + // scan the key to obtain the masks + StringPos = 0; + for(nmasks = 0;nmasks <* NEntries;nmasks++){ + TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask); + + if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){ + TmpAddr->sin_family = AF_INET; + + while(*(String + StringPos) != 0)StringPos++; + StringPos++; + + if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen) + break; + } + else break; + } + + // The number of masks MUST be equal to the number of adresses + if(nmasks != naddrs){ + RegCloseKey(TcpIpKey); + goto fail; + } + + } + + *NEntries = naddrs + 1; + + RegCloseKey(TcpIpKey); + + if (status != ERROR_SUCCESS) { + goto fail; + } + + + if (AdapterNameU != NULL) + free(AdapterNameU); + return TRUE; + +fail: + if (AdapterNameU != NULL) + free(AdapterNameU); + return FALSE; +} + +/*! + \brief Returns the IP address and the netmask of an adapter. + \param AdapterName String that contain _ADAPTER structure. + \param netp Pointer to a variable that will receive the IP address of the adapter. + \param maskp Pointer to a variable that will receive the netmask of the adapter. + \return If the function succeeds, the return value is nonzero. + + \note this function is obsolete and is maintained for backward compatibility. Use PacketGetNetInfoEx() instead. +*/ + +BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp) +{ + char *AdapterNameA; + WCHAR *AdapterNameU; + WCHAR *ifname; + HKEY SystemKey; + HKEY InterfaceKey; + HKEY ParametersKey; + HKEY TcpIpKey; + LONG status; + WCHAR String[1024+1]; + DWORD RegType; + ULONG BufLen; + DWORD DHCPEnabled; + ULONG TAddr,i; + + AdapterNameA = (char*)AdapterName; + if(AdapterNameA[1] != 0) { //ASCII + AdapterNameU = SChar2WChar(AdapterNameA); + AdapterName = AdapterNameU; + } else { //Unicode + AdapterNameU = NULL; + } + ifname = wcsrchr(AdapterName, '\\'); + if (ifname == NULL) + ifname = AdapterName; + else + ifname++; + if (wcsncmp(ifname, L"NPF_", 4) == 0) + ifname += 4; + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + TEXT("SYSTEM\\ControlSet001\\Services"), + 0,KEY_READ,&SystemKey); + if (status != ERROR_SUCCESS) + goto fail; + status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(SystemKey); + goto fail; + } + RegCloseKey(SystemKey); + status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(InterfaceKey); + goto fail; + } + RegCloseKey(InterfaceKey); + status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey); + if (status != ERROR_SUCCESS) { + RegCloseKey(ParametersKey); + goto fail; + } + RegCloseKey(ParametersKey); + + BufLen = 4; + /* See if DHCP is used by this system */ + status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen); + if (status != ERROR_SUCCESS) + DHCPEnabled=0; + + + /* Retrieve the netmask */ + if(DHCPEnabled){ + + BufLen = sizeof String; + status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen); + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + TAddr = inet_addrU(String); + // swap bytes for backward compatibility + for(i=0;i<4;i++){ + *((char*)netp+i) = *((char*)&TAddr+3-i); + } + + BufLen = sizeof String; + status=RegQueryValueEx(TcpIpKey,TEXT("DHCPSubnetMask"),NULL,&RegType, + (LPBYTE)String,&BufLen); + + TAddr = inet_addrU(String); + // swap bytes for backward compatibility + for(i=0;i<4;i++){ + *((char*)maskp+i) = *((char*)&TAddr+3-i); + } + + + } + else{ + + BufLen = sizeof String; + status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen); + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + TAddr = inet_addrU(String); + // swap bytes for backward compatibility + for(i=0;i<4;i++){ + *((char*)netp+i) = *((char*)&TAddr+3-i); + } + + BufLen = sizeof String; + status=RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType, + (LPBYTE)String,&BufLen); + + TAddr = inet_addrU(String); + // swap bytes for backward compatibility + for(i=0;i<4;i++){ + *((char*)maskp+i) = *((char*)&TAddr+3-i); + } + + + } + + if (status != ERROR_SUCCESS) { + RegCloseKey(TcpIpKey); + goto fail; + } + + + if (AdapterNameU != NULL) + free(AdapterNameU); + return TRUE; + +fail: + if (AdapterNameU != NULL) + free(AdapterNameU); + return FALSE; +} + +/* @} */ diff --git a/lib/packet/include/devioctl.h b/lib/packet/include/devioctl.h new file mode 100644 index 0000000..661fda0 --- /dev/null +++ b/lib/packet/include/devioctl.h @@ -0,0 +1,90 @@ +/*++ BUILD Version: 0004 // Increment this if a change has global effects + Copyright (c) 1992-1993 Microsoft Corporation + Module Name: + devioctl.h + Revision History: + -- */ +// begin_winioctl +#ifndef _DEVIOCTL_ +#define _DEVIOCTL_ +// begin_ntddk begin_nthal begin_ntifs +// +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +// +#define DEVICE_TYPE ULONG +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// +#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) +// +// Define the method codes for how buffers are passed for I/O and FS controls +// +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 +// +// Define the access check value for any access +// +// +// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in +// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these +// constants *MUST* always be in sync. +// +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe +#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe +// end_ntddk end_nthal end_ntifs +#endif // _DEVIOCTL_ +// end_winioctl diff --git a/lib/packet/include/ntddndis.h b/lib/packet/include/ntddndis.h new file mode 100644 index 0000000..77a53d7 --- /dev/null +++ b/lib/packet/include/ntddndis.h @@ -0,0 +1,1400 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + Copyright (c) 1990-1993 Microsoft Corporation + Module Name: + ntddndis.h + Abstract: + This is the include file that defines all constants and types for + accessing the Network driver interface device. + Author: + Steve Wood (stevewo) 27-May-1990 + Revision History: + Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0. + Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures + Kyle Brandon (kyleb) 09/24/96 added general co ndis oids. + -- */ +#ifndef _NTDDNDIS_ +#define _NTDDNDIS_ +// +// Device Name - this string is the name of the device. It is the name +// that should be passed to NtOpenFile when accessing the device. +// +// Note: For devices that support multiple units, it should be suffixed +// with the Ascii representation of the unit number. +// +#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN" +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code specify how the +// buffers are passed to the driver! +// +#define _NDIS_CONTROL_CODE(request,method) \ + CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS) +#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT ) +#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT ) +#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED ) +#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED ) +#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED ) +#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED ) +#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED ) +#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT ) +// +// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for +// this device. +// +// +// This is the type of an NDIS OID value. +// +typedef ULONG NDIS_OID, *PNDIS_OID; +// +// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed +// together (no padding is required since statistics all have +// four or eight bytes of data). +// +typedef struct _NDIS_STATISTICS_VALUE { + NDIS_OID Oid; + ULONG DataLength; + UCHAR Data[1]; // variable length + +} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE; + +// +// Structure used by TRANSLATE_NAME IOCTL +// +typedef struct _NET_PNP_ID { + ULONG ClassId; + ULONG Token; +} NET_PNP_ID, *PNET_PNP_ID; + +typedef struct _NET_PNP_TRANSLATE_LIST { + ULONG BytesNeeded; + NET_PNP_ID IdArray[ANYSIZE_ARRAY]; +} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST; + +// +// Structure used to define a self-contained variable data structure +// +typedef struct _NDIS_VAR_DATA_DESC { + USHORT Length; // # of octects of data + + USHORT MaximumLength; // # of octects available + + LONG Offset; // Offset of data relative to the descriptor + +} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC; + +// +// Object Identifiers used by NdisRequest Query/Set Information +// +// +// General Objects +// +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +// +// These are connection-oriented general OIDs. +// These replace the above OIDs for connection-oriented media. +// +#define OID_GEN_CO_SUPPORTED_LIST 0x00010101 +#define OID_GEN_CO_HARDWARE_STATUS 0x00010102 +#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_CO_MEDIA_IN_USE 0x00010104 +#define OID_GEN_CO_LINK_SPEED 0x00010105 +#define OID_GEN_CO_VENDOR_ID 0x00010106 +#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107 +#define OID_GEN_CO_DRIVER_VERSION 0x00010108 +#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109 +#define OID_GEN_CO_MAC_OPTIONS 0x0001010A +#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B +#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C +#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D +#define OID_GEN_CO_GET_TIME_CAPS 0x00010201 +#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202 +// +// These are connection-oriented statistics OIDs. +// +#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101 +#define OID_GEN_CO_RCV_PDUS_OK 0x00020102 +#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103 +#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104 +#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105 +#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201 +#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202 +#define OID_GEN_CO_BYTES_XMIT 0x00020203 +#define OID_GEN_CO_BYTES_RCV 0x00020204 +#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205 +#define OID_GEN_CO_NETCARD_LOAD 0x00020206 +// +// These are objects for Connection-oriented media call-managers and are not +// valid for ndis drivers. Under construction. +// +#define OID_CO_ADD_PVC 0xFF000001 +#define OID_CO_DELETE_PVC 0xFF000002 +#define OID_CO_GET_CALL_INFORMATION 0xFF000003 +#define OID_CO_ADD_ADDRESS 0xFF000004 +#define OID_CO_DELETE_ADDRESS 0xFF000005 +#define OID_CO_GET_ADDRESSES 0xFF000006 +#define OID_CO_ADDRESS_CHANGE 0xFF000007 +#define OID_CO_SIGNALING_ENABLED 0xFF000008 +#define OID_CO_SIGNALING_DISABLED 0xFF000009 +// +// 802.3 Objects (Ethernet) +// +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +// +// +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 +// +// 802.5 Objects (Token-Ring) +// +#define OID_802_5_PERMANENT_ADDRESS 0x02010101 +#define OID_802_5_CURRENT_ADDRESS 0x02010102 +#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103 +#define OID_802_5_CURRENT_GROUP 0x02010104 +#define OID_802_5_LAST_OPEN_STATUS 0x02010105 +#define OID_802_5_CURRENT_RING_STATUS 0x02010106 +#define OID_802_5_CURRENT_RING_STATE 0x02010107 +#define OID_802_5_LINE_ERRORS 0x02020101 +#define OID_802_5_LOST_FRAMES 0x02020102 +#define OID_802_5_BURST_ERRORS 0x02020201 +#define OID_802_5_AC_ERRORS 0x02020202 +#define OID_802_5_ABORT_DELIMETERS 0x02020203 +#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204 +#define OID_802_5_FREQUENCY_ERRORS 0x02020205 +#define OID_802_5_TOKEN_ERRORS 0x02020206 +#define OID_802_5_INTERNAL_ERRORS 0x02020207 +// +// FDDI Objects +// +#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101 +#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102 +#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103 +#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104 +#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105 +#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106 +#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107 +#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108 +#define OID_FDDI_ATTACHMENT_TYPE 0x03020101 +#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102 +#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103 +#define OID_FDDI_FRAME_ERRORS 0x03020104 +#define OID_FDDI_FRAMES_LOST 0x03020105 +#define OID_FDDI_RING_MGT_STATE 0x03020106 +#define OID_FDDI_LCT_FAILURES 0x03020107 +#define OID_FDDI_LEM_REJECTS 0x03020108 +#define OID_FDDI_LCONNECTION_STATE 0x03020109 +#define OID_FDDI_SMT_STATION_ID 0x03030201 +#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202 +#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203 +#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204 +#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205 +#define OID_FDDI_SMT_USER_DATA 0x03030206 +#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207 +#define OID_FDDI_SMT_MAC_CT 0x03030208 +#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209 +#define OID_FDDI_SMT_MASTER_CT 0x0303020A +#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B +#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C +#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D +#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E +#define OID_FDDI_SMT_T_NOTIFY 0x0303020F +#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210 +#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211 +#define OID_FDDI_SMT_PORT_INDEXES 0x03030212 +#define OID_FDDI_SMT_MAC_INDEXES 0x03030213 +#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214 +#define OID_FDDI_SMT_ECM_STATE 0x03030215 +#define OID_FDDI_SMT_CF_STATE 0x03030216 +#define OID_FDDI_SMT_HOLD_STATE 0x03030217 +#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218 +#define OID_FDDI_SMT_STATION_STATUS 0x03030219 +#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A +#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B +#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C +#define OID_FDDI_SMT_SET_COUNT 0x0303021D +#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E +#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F +#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220 +#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221 +#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222 +#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223 +#define OID_FDDI_MAC_CURRENT_PATH 0x03030224 +#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225 +#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226 +#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227 +#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228 +#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229 +#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A +#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B +#define OID_FDDI_MAC_INDEX 0x0303022C +#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D +#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E +#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F +#define OID_FDDI_MAC_T_REQ 0x03030230 +#define OID_FDDI_MAC_T_NEG 0x03030231 +#define OID_FDDI_MAC_T_MAX 0x03030232 +#define OID_FDDI_MAC_TVX_VALUE 0x03030233 +#define OID_FDDI_MAC_T_PRI0 0x03030234 +#define OID_FDDI_MAC_T_PRI1 0x03030235 +#define OID_FDDI_MAC_T_PRI2 0x03030236 +#define OID_FDDI_MAC_T_PRI3 0x03030237 +#define OID_FDDI_MAC_T_PRI4 0x03030238 +#define OID_FDDI_MAC_T_PRI5 0x03030239 +#define OID_FDDI_MAC_T_PRI6 0x0303023A +#define OID_FDDI_MAC_FRAME_CT 0x0303023B +#define OID_FDDI_MAC_COPIED_CT 0x0303023C +#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D +#define OID_FDDI_MAC_TOKEN_CT 0x0303023E +#define OID_FDDI_MAC_ERROR_CT 0x0303023F +#define OID_FDDI_MAC_LOST_CT 0x03030240 +#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241 +#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242 +#define OID_FDDI_MAC_LATE_CT 0x03030243 +#define OID_FDDI_MAC_RING_OP_CT 0x03030244 +#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245 +#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246 +#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247 +#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248 +#define OID_FDDI_MAC_RMT_STATE 0x03030249 +#define OID_FDDI_MAC_DA_FLAG 0x0303024A +#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B +#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C +#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D +#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E +#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F +#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250 +#define OID_FDDI_PATH_INDEX 0x03030251 +#define OID_FDDI_PATH_RING_LATENCY 0x03030252 +#define OID_FDDI_PATH_TRACE_STATUS 0x03030253 +#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254 +#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255 +#define OID_FDDI_PATH_CONFIGURATION 0x03030256 +#define OID_FDDI_PATH_T_R_MODE 0x03030257 +#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258 +#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259 +#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A +#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B +#define OID_FDDI_PORT_MY_TYPE 0x0303025C +#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D +#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E +#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F +#define OID_FDDI_PORT_CURRENT_PATH 0x03030260 +#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261 +#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262 +#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263 +#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264 +#define OID_FDDI_PORT_PMD_CLASS 0x03030265 +#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266 +#define OID_FDDI_PORT_INDEX 0x03030267 +#define OID_FDDI_PORT_MAINT_LS 0x03030268 +#define OID_FDDI_PORT_BS_FLAG 0x03030269 +#define OID_FDDI_PORT_PC_LS 0x0303026A +#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B +#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C +#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D +#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E +#define OID_FDDI_PORT_LEM_CT 0x0303026F +#define OID_FDDI_PORT_LER_CUTOFF 0x03030270 +#define OID_FDDI_PORT_LER_ALARM 0x03030271 +#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272 +#define OID_FDDI_PORT_PCM_STATE 0x03030273 +#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274 +#define OID_FDDI_PORT_LER_FLAG 0x03030275 +#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276 +#define OID_FDDI_SMT_STATION_ACTION 0x03030277 +#define OID_FDDI_PORT_ACTION 0x03030278 +#define OID_FDDI_IF_DESCR 0x03030279 +#define OID_FDDI_IF_TYPE 0x0303027A +#define OID_FDDI_IF_MTU 0x0303027B +#define OID_FDDI_IF_SPEED 0x0303027C +#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D +#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E +#define OID_FDDI_IF_OPER_STATUS 0x0303027F +#define OID_FDDI_IF_LAST_CHANGE 0x03030280 +#define OID_FDDI_IF_IN_OCTETS 0x03030281 +#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282 +#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283 +#define OID_FDDI_IF_IN_DISCARDS 0x03030284 +#define OID_FDDI_IF_IN_ERRORS 0x03030285 +#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286 +#define OID_FDDI_IF_OUT_OCTETS 0x03030287 +#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288 +#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289 +#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A +#define OID_FDDI_IF_OUT_ERRORS 0x0303028B +#define OID_FDDI_IF_OUT_QLEN 0x0303028C +#define OID_FDDI_IF_SPECIFIC 0x0303028D +// +// WAN objects +// +#define OID_WAN_PERMANENT_ADDRESS 0x04010101 +#define OID_WAN_CURRENT_ADDRESS 0x04010102 +#define OID_WAN_QUALITY_OF_SERVICE 0x04010103 +#define OID_WAN_PROTOCOL_TYPE 0x04010104 +#define OID_WAN_MEDIUM_SUBTYPE 0x04010105 +#define OID_WAN_HEADER_FORMAT 0x04010106 +#define OID_WAN_GET_INFO 0x04010107 +#define OID_WAN_SET_LINK_INFO 0x04010108 +#define OID_WAN_GET_LINK_INFO 0x04010109 +#define OID_WAN_LINE_COUNT 0x0401010A +#define OID_WAN_GET_BRIDGE_INFO 0x0401020A +#define OID_WAN_SET_BRIDGE_INFO 0x0401020B +#define OID_WAN_GET_COMP_INFO 0x0401020C +#define OID_WAN_SET_COMP_INFO 0x0401020D +#define OID_WAN_GET_STATS_INFO 0x0401020E +// +// LocalTalk objects +// +#define OID_LTALK_CURRENT_NODE_ID 0x05010102 +#define OID_LTALK_IN_BROADCASTS 0x05020101 +#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102 +#define OID_LTALK_OUT_NO_HANDLERS 0x05020201 +#define OID_LTALK_COLLISIONS 0x05020202 +#define OID_LTALK_DEFERS 0x05020203 +#define OID_LTALK_NO_DATA_ERRORS 0x05020204 +#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205 +#define OID_LTALK_FCS_ERRORS 0x05020206 +// +// Arcnet objects +// +#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101 +#define OID_ARCNET_CURRENT_ADDRESS 0x06010102 +#define OID_ARCNET_RECONFIGURATIONS 0x06020201 +// +// TAPI objects +// +#define OID_TAPI_ACCEPT 0x07030101 +#define OID_TAPI_ANSWER 0x07030102 +#define OID_TAPI_CLOSE 0x07030103 +#define OID_TAPI_CLOSE_CALL 0x07030104 +#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105 +#define OID_TAPI_CONFIG_DIALOG 0x07030106 +#define OID_TAPI_DEV_SPECIFIC 0x07030107 +#define OID_TAPI_DIAL 0x07030108 +#define OID_TAPI_DROP 0x07030109 +#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A +#define OID_TAPI_GET_ADDRESS_ID 0x0703010B +#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C +#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D +#define OID_TAPI_GET_CALL_INFO 0x0703010E +#define OID_TAPI_GET_CALL_STATUS 0x0703010F +#define OID_TAPI_GET_DEV_CAPS 0x07030110 +#define OID_TAPI_GET_DEV_CONFIG 0x07030111 +#define OID_TAPI_GET_EXTENSION_ID 0x07030112 +#define OID_TAPI_GET_ID 0x07030113 +#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114 +#define OID_TAPI_MAKE_CALL 0x07030115 +#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116 +#define OID_TAPI_OPEN 0x07030117 +#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118 +#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119 +#define OID_TAPI_SECURE_CALL 0x0703011A +#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B +#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C +#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D +#define OID_TAPI_SET_CALL_PARAMS 0x0703011E +#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F +#define OID_TAPI_SET_DEV_CONFIG 0x07030120 +#define OID_TAPI_SET_MEDIA_MODE 0x07030121 +#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122 +// +// ATM Connection Oriented Ndis +// +#define OID_ATM_SUPPORTED_VC_RATES 0x08010101 +#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102 +#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103 +#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104 +#define OID_ATM_MAX_ACTIVE_VCS 0x08010105 +#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106 +#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107 +#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108 +#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109 +#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A +#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B +#define OID_ATM_SIGNALING_VPIVCI 0x08010201 +#define OID_ATM_ASSIGNED_VPI 0x08010202 +#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203 +#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204 +#define OID_ATM_ILMI_VPIVCI 0x08010205 +#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206 +#define OID_ATM_GET_NEAREST_FLOW 0x08010207 +#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208 +// +// ATM specific statistics OIDs. +// +#define OID_ATM_RCV_CELLS_OK 0x08020101 +#define OID_ATM_XMIT_CELLS_OK 0x08020102 +#define OID_ATM_RCV_CELLS_DROPPED 0x08020103 +#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201 +#define OID_ATM_CELLS_HEC_ERROR 0x08020202 +#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203 +// +// PCCA (Wireless) object +// +// +// All WirelessWAN devices must support the following OIDs +// +#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101 +#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102 +#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103 +#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104 +#define OID_WW_GEN_INDICATION_REQUEST 0x09010105 +#define OID_WW_GEN_DEVICE_INFO 0x09010106 +#define OID_WW_GEN_OPERATION_MODE 0x09010107 +#define OID_WW_GEN_LOCK_STATUS 0x09010108 +#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109 +#define OID_WW_GEN_NETWORK_ID 0x0901010A +#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B +#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C +#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D +#define OID_WW_GEN_BASESTATION_ID 0x0901010E +#define OID_WW_GEN_CHANNEL_ID 0x0901010F +#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110 +#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111 +#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112 +#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113 +#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114 +#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115 +#define OID_WW_GEN_LATENCY 0x09010116 +#define OID_WW_GEN_BATTERY_LEVEL 0x09010117 +#define OID_WW_GEN_EXTERNAL_POWER 0x09010118 +// +// Network Dependent OIDs - Mobitex: +// +#define OID_WW_MBX_SUBADDR 0x09050101 +// OID 0x09050102 is reserved and may not be used +#define OID_WW_MBX_FLEXLIST 0x09050103 +#define OID_WW_MBX_GROUPLIST 0x09050104 +#define OID_WW_MBX_TRAFFIC_AREA 0x09050105 +#define OID_WW_MBX_LIVE_DIE 0x09050106 +#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107 +// +// Network Dependent OIDs - Pinpoint: +// +#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101 +#define OID_WW_PIN_LAST_LOCATION 0x09090102 +#define OID_WW_PIN_LOC_FIX 0x09090103 +// +// Network Dependent - CDPD: +// +#define OID_WW_CDPD_SPNI 0x090D0101 +#define OID_WW_CDPD_WASI 0x090D0102 +#define OID_WW_CDPD_AREA_COLOR 0x090D0103 +#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104 +#define OID_WW_CDPD_EID 0x090D0105 +#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106 +#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107 +#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108 +#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109 +#define OID_WW_CDPD_NEI 0x090D010A +#define OID_WW_CDPD_NEI_STATE 0x090D010B +#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C +#define OID_WW_CDPD_SLEEP_MODE 0x090D010D +#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E +#define OID_WW_CDPD_TEI 0x090D010F +#define OID_WW_CDPD_RSSI 0x090D0110 +// +// Network Dependent - Ardis: +// +#define OID_WW_ARD_SNDCP 0x09110101 +#define OID_WW_ARD_TMLY_MSG 0x09110102 +#define OID_WW_ARD_DATAGRAM 0x09110103 +// +// Network Dependent - DataTac: +// +#define OID_WW_TAC_COMPRESSION 0x09150101 +#define OID_WW_TAC_SET_CONFIG 0x09150102 +#define OID_WW_TAC_GET_STATUS 0x09150103 +#define OID_WW_TAC_USER_HEADER 0x09150104 +// +// Network Dependent - Metricom: +// +#define OID_WW_MET_FUNCTION 0x09190101 +// +// IRDA objects +// +#define OID_IRDA_RECEIVING 0x0A010100 +#define OID_IRDA_TURNAROUND_TIME 0x0A010101 +#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102 +#define OID_IRDA_LINK_SPEED 0x0A010103 +#define OID_IRDA_MEDIA_BUSY 0x0A010104 +#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200 +#define OID_IRDA_RATE_SNIFF 0x0A010201 +#define OID_IRDA_UNICAST_LIST 0x0A010202 +#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203 +#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204 +#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205 +// +// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/ +// OID_GEN_MEDIA_IN_USE). +// +typedef enum _NDIS_MEDIUM { + NdisMedium802_3, + NdisMedium802_5, + NdisMediumFddi, + NdisMediumWan, + NdisMediumLocalTalk, + NdisMediumDix, // defined for convenience, not a real medium + NdisMediumArcnetRaw, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMediumWirelessWan, + NdisMediumIrda, + NdisMediumMax // Not a real medium, defined as an upper-bound +} NDIS_MEDIUM, *PNDIS_MEDIUM; + +// +// Hardware status codes (OID_GEN_HARDWARE_STATUS). +// +typedef enum _NDIS_HARDWARE_STATUS { + NdisHardwareStatusReady, + NdisHardwareStatusInitializing, + NdisHardwareStatusReset, + NdisHardwareStatusClosing, + NdisHardwareStatusNotReady +} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS; + +// +// this is the type passed in the OID_GEN_GET_TIME_CAPS request +// +typedef struct _GEN_GET_TIME_CAPS { + ULONG Flags; // Bits defined below + + ULONG ClockPrecision; +} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS; + +#define READABLE_LOCAL_CLOCK 0x000000001 +#define CLOCK_NETWORK_DERIVED 0x000000002 +#define CLOCK_PRECISION 0x000000004 +#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008 +#define TIMED_SEND_CAPABLE 0x000000010 +#define TIME_STAMP_CAPABLE 0x000000020 +// +// +// this is the type passed in the OID_GEN_GET_NETCARD_TIME request +// +typedef struct _GEN_GET_NETCARD_TIME { + ULONG ReadTime; +} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME; + +// +// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE). +// +typedef enum _NDIS_FDDI_ATTACHMENT_TYPE { + NdisFddiTypeIsolated = 1, + NdisFddiTypeLocalA, + NdisFddiTypeLocalB, + NdisFddiTypeLocalAB, + NdisFddiTypeLocalS, + NdisFddiTypeWrapA, + NdisFddiTypeWrapB, + NdisFddiTypeWrapAB, + NdisFddiTypeWrapS, + NdisFddiTypeCWrapA, + NdisFddiTypeCWrapB, + NdisFddiTypeCWrapS, + NdisFddiTypeThrough +} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE; + +// +// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE). +// +typedef enum _NDIS_FDDI_RING_MGT_STATE { + NdisFddiRingIsolated = 1, + NdisFddiRingNonOperational, + NdisFddiRingOperational, + NdisFddiRingDetect, + NdisFddiRingNonOperationalDup, + NdisFddiRingOperationalDup, + NdisFddiRingDirected, + NdisFddiRingTrace +} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE; + +// +// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE). +// +typedef enum _NDIS_FDDI_LCONNECTION_STATE { + NdisFddiStateOff = 1, + NdisFddiStateBreak, + NdisFddiStateTrace, + NdisFddiStateConnect, + NdisFddiStateNext, + NdisFddiStateSignal, + NdisFddiStateJoin, + NdisFddiStateVerify, + NdisFddiStateActive, + NdisFddiStateMaintenance +} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE; + +// +// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE). +// +typedef enum _NDIS_WAN_MEDIUM_SUBTYPE { + NdisWanMediumHub, + NdisWanMediumX_25, + NdisWanMediumIsdn, + NdisWanMediumSerial, + NdisWanMediumFrameRelay, + NdisWanMediumAtm, + NdisWanMediumSonet, + NdisWanMediumSW56K +} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE; + +// +// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT). +// +typedef enum _NDIS_WAN_HEADER_FORMAT { + NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID + NdisWanHeaderEthernet // emulation of ethernet header +} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT; + +// +// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE). +// +typedef enum _NDIS_WAN_QUALITY { + NdisWanRaw, + NdisWanErrorControl, + NdisWanReliable +} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY; + +// +// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE). +// +typedef enum _NDIS_802_5_RING_STATE { + NdisRingStateOpened = 1, + NdisRingStateClosed, + NdisRingStateOpening, + NdisRingStateClosing, + NdisRingStateOpenFailure, + NdisRingStateRingFailure +} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE; + +// +// Defines the state of the LAN media +// +typedef enum _NDIS_MEDIA_STATE { + NdisMediaStateConnected, + NdisMediaStateDisconnected +} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE; + +// +// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority +// +typedef ULONG Priority_802_3; // 0-7 priority levels +// +// The following structure is used to query OID_GEN_CO_LINK_SPEED and +// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current +// link speed of the adapter. The second will return the minimum link speed +// the adapter is capable of. +// + +typedef struct _NDIS_CO_LINK_SPEED { + ULONG Outbound; + ULONG Inbound; +} NDIS_CO_LINK_SPEED, + +*PNDIS_CO_LINK_SPEED; +// +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). +// +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 +#define NDIS_PACKET_TYPE_SMT 0x0040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 +#define NDIS_PACKET_TYPE_GROUP 0x1000 +// +// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS). +// +#define NDIS_RING_SIGNAL_LOSS 0x00008000 +#define NDIS_RING_HARD_ERROR 0x00004000 +#define NDIS_RING_SOFT_ERROR 0x00002000 +#define NDIS_RING_TRANSMIT_BEACON 0x00001000 +#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800 +#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400 +#define NDIS_RING_REMOVE_RECEIVED 0x00000200 +#define NDIS_RING_COUNTER_OVERFLOW 0x00000100 +#define NDIS_RING_SINGLE_STATION 0x00000080 +#define NDIS_RING_RING_RECOVERY 0x00000040 +// +// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS). +// +#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001 +#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002 +#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004 +// +// Ndis MAC option bits (OID_GEN_MAC_OPTIONS). +// +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 +// +// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS. +// +#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001 +#ifdef IRDA +// +// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo +// This is the per-packet info specified on a per-packet basis +// +typedef struct _NDIS_IRDA_PACKET_INFO { + UINT ExtraBOFs; + UINT MinTurnAroundTime; +} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO; + +#endif +#ifdef WIRELESS_WAN +// +// Wireless WAN structure definitions +// +// +// currently defined Wireless network subtypes +// +typedef enum _NDIS_WW_NETWORK_TYPE { + NdisWWGeneric, + NdisWWMobitex, + NdisWWPinpoint, + NdisWWCDPD, + NdisWWArdis, + NdisWWDataTAC, + NdisWWMetricom, + NdisWWGSM, + NdisWWCDMA, + NdisWWTDMA, + NdisWWAMPS, + NdisWWInmarsat, + NdisWWpACT +} NDIS_WW_NETWORK_TYPE; + +// +// currently defined header formats +// +typedef enum _NDIS_WW_HEADER_FORMAT { + NdisWWDIXEthernetFrames, + NdisWWMPAKFrames, + NdisWWRDLAPFrames, + NdisWWMDC4800Frames +} NDIS_WW_HEADER_FORMAT; + +// +// currently defined encryption types +// +typedef enum _NDIS_WW_ENCRYPTION_TYPE { + NdisWWUnknownEncryption = -1, + NdisWWNoEncryption, + NdisWWDefaultEncryption +} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE; + +// +// OID_WW_GEN_INDICATION_REQUEST +// +typedef struct _NDIS_WW_INDICATION_REQUEST { + NDIS_OID Oid; // IN + + UINT uIndicationFlag; // IN + + UINT uApplicationToken; // IN OUT + + HANDLE hIndicationHandle; // IN OUT + + INT iPollingInterval; // IN OUT + + NDIS_VAR_DATA_DESC InitialValue; // IN OUT + + NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication + + NDIS_VAR_DATA_DESC TriggerValue; // IN + +} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST; + +#define OID_INDICATION_REQUEST_ENABLE 0x0000 +#define OID_INDICATION_REQUEST_CANCEL 0x0001 +// +// OID_WW_GEN_DEVICE_INFO +// +typedef struct _WW_DEVICE_INFO { + NDIS_VAR_DATA_DESC Manufacturer; + NDIS_VAR_DATA_DESC ModelNum; + NDIS_VAR_DATA_DESC SWVersionNum; + NDIS_VAR_DATA_DESC SerialNum; +} WW_DEVICE_INFO, *PWW_DEVICE_INFO; + +// +// OID_WW_GEN_OPERATION_MODE +// +typedef INT WW_OPERATION_MODE; // 0 = Normal mode + // 1 = Power saving mode + // -1 = mode unknown +// +// OID_WW_GEN_LOCK_STATUS +// + +typedef INT WW_LOCK_STATUS; // 0 = unlocked + // 1 = locked + // -1 = unknown lock status +// +// OID_WW_GEN_DISABLE_TRANSMITTER +// + +typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled + // 1 = transmitter disabled + // -1 = unknown value +// +// OID_WW_GEN_NETWORK_ID +// + +typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID; +// +// OID_WW_GEN_PERMANENT_ADDRESS +// +typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS; +// +// OID_WW_GEN_CURRENT_ADDRESS +// +typedef struct _WW_CURRENT_ADDRESS { + NDIS_WW_HEADER_FORMAT Format; + NDIS_VAR_DATA_DESC Address; +} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS; + +// +// OID_WW_GEN_SUSPEND_DRIVER +// +typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational + // 1 = driver suspended +// +// OID_WW_GEN_BASESTATION_ID +// + +typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID; +// +// OID_WW_GEN_CHANNEL_ID +// +typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID; +// +// OID_WW_GEN_ENCRYPTION_STATE +// +typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled + // 1 = if encryption is enabled +// +// OID_WW_GEN_CHANNEL_QUALITY +// + +typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact, + // 1-100 = Quality of Channel (100 is highest quality). + // -1 = channel quality is unknown +// +// OID_WW_GEN_REGISTRATION_STATUS +// + +typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied + // 1 = Registration pending + // 2 = Registered + // -1 = unknown registration status +// +// OID_WW_GEN_RADIO_LINK_SPEED +// + +typedef UINT WW_RADIO_LINK_SPEED; // Bits per second. +// +// OID_WW_GEN_LATENCY +// + +typedef UINT WW_LATENCY; // milliseconds +// +// OID_WW_GEN_BATTERY_LEVEL +// + +typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage + // (100=fully charged) + // -1 = unknown battery level. +// +// OID_WW_GEN_EXTERNAL_POWER +// + +typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected + // 1 = external power connected + // -1 = unknown +// +// OID_WW_MET_FUNCTION +// + +typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION; +// +// OID_WW_TAC_COMPRESSION +// +typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression + // is being used. +// +// OID_WW_TAC_SET_CONFIG +// + +typedef struct _WW_TAC_SETCONFIG { + NDIS_VAR_DATA_DESC RCV_MODE; + NDIS_VAR_DATA_DESC TX_CONTROL; + NDIS_VAR_DATA_DESC RX_CONTROL; + NDIS_VAR_DATA_DESC FLOW_CONTROL; + NDIS_VAR_DATA_DESC RESET_CNF; + NDIS_VAR_DATA_DESC READ_CNF; +} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG; + +// +// OID_WW_TAC_GET_STATUS +// +typedef struct _WW_TAC_GETSTATUS { + BOOLEAN Action; // Set = Execute command. + + NDIS_VAR_DATA_DESC Command; + NDIS_VAR_DATA_DESC Option; + NDIS_VAR_DATA_DESC Response; // The response to the requested command + // - max. length of string is 256 octets. + +} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS; + +// +// OID_WW_TAC_USER_HEADER +// +typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets. +// +// OID_WW_ARD_SNDCP +// + +typedef struct _WW_ARD_SNDCP { + NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported. + + INT BlockSize; // The block size used for SNDCP + + INT Window; // The window size used in SNDCP + +} WW_ARD_SNDCP, *PWW_ARD_SNDCP; + +// +// OID_WW_ARD_TMLY_MSG +// +typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel. +// +// OID_WW_ARD_DATAGRAM +// + +typedef struct _WW_ARD_DATAGRAM { + BOOLEAN LoadLevel; // Byte that contains the load level info. + + INT SessionTime; // Datagram session time remaining. + + NDIS_VAR_DATA_DESC HostAddr; // Host address. + + NDIS_VAR_DATA_DESC THostAddr; // Test host address. + +} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM; + +// +// OID_WW_CDPD_SPNI +// +typedef struct _WW_CDPD_SPNI { + UINT SPNI[10]; //10 16-bit service provider network IDs + + INT OperatingMode; // 0 = ignore SPNI, + // 1 = require SPNI from list, + // 2 = prefer SPNI from list. + // 3 = exclude SPNI from list. + +} WW_CDPD_SPNI, *PWW_CDPD_SPNI; + +// +// OID_WW_CDPD_WASI +// +typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID { + UINT WASI[10]; //10 16-bit wide area service IDs + + INT OperatingMode; // 0 = ignore WASI, + // 1 = Require WASI from list, + // 2 = prefer WASI from list + // 3 = exclude WASI from list. + +} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID; + +// +// OID_WW_CDPD_AREA_COLOR +// +typedef INT WW_CDPD_AREA_COLOR; +// +// OID_WW_CDPD_TX_POWER_LEVEL +// +typedef UINT WW_CDPD_TX_POWER_LEVEL; +// +// OID_WW_CDPD_EID +// +typedef NDIS_VAR_DATA_DESC WW_CDPD_EID; +// +// OID_WW_CDPD_HEADER_COMPRESSION +// +typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression, + // 1 = always compress headers, + // 2 = compress headers if MD-IS does + // -1 = unknown +// +// OID_WW_CDPD_DATA_COMPRESSION +// + +typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression, + // 1 = data compression enabled + // -1 = unknown +// +// OID_WW_CDPD_CHANNEL_SELECT +// + +typedef struct _WW_CDPD_CHANNEL_SELECT { + UINT ChannelID; // channel number + + UINT fixedDuration; // duration in seconds + +} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT; + +// +// OID_WW_CDPD_CHANNEL_STATE +// +typedef enum _WW_CDPD_CHANNEL_STATE { + CDPDChannelNotAvail, + CDPDChannelScanning, + CDPDChannelInitAcquired, + CDPDChannelAcquired, + CDPDChannelSleeping, + CDPDChannelWaking, + CDPDChannelCSDialing, + CDPDChannelCSRedial, + CDPDChannelCSAnswering, + CDPDChannelCSConnected, + CDPDChannelCSSuspended +} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE; + +// +// OID_WW_CDPD_NEI +// +typedef enum _WW_CDPD_NEI_FORMAT { + CDPDNeiIPv4, + CDPDNeiCLNP, + CDPDNeiIPv6 +} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT; +typedef enum _WW_CDPD_NEI_TYPE { + CDPDNeiIndividual, + CDPDNeiMulticast, + CDPDNeiBroadcast +} WW_CDPD_NEI_TYPE; +typedef struct _WW_CDPD_NEI { + UINT uNeiIndex; + WW_CDPD_NEI_FORMAT NeiFormat; + WW_CDPD_NEI_TYPE NeiType; + WORD NeiGmid; // group member identifier, only + // meaningful if NeiType == + // CDPDNeiMulticast + + NDIS_VAR_DATA_DESC NeiAddress; +} WW_CDPD_NEI; + +// +// OID_WW_CDPD_NEI_STATE +// +typedef enum _WW_CDPD_NEI_STATE { + CDPDUnknown, + CDPDRegistered, + CDPDDeregistered +} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE; +typedef enum _WW_CDPD_NEI_SUB_STATE { + CDPDPending, // Registration pending + CDPDNoReason, // Registration denied - no reason given + CDPDMDISNotCapable, // Registration denied - MD-IS not capable of + // handling M-ES at this time + CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to + // use this subnetwork + CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient + // authentication credentials + CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported + // authentication credentials + CDPDUsageExceeded, // Registration denied - NEI has exceeded usage + // limitations + CDPDDeniedThisNetwork // Registration denied on this network, service + // may be obtained on alternate Service Provider + // network +} WW_CDPD_NEI_SUB_STATE; +typedef struct _WW_CDPD_NEI_REG_STATE { + UINT uNeiIndex; + WW_CDPD_NEI_STATE NeiState; + WW_CDPD_NEI_SUB_STATE NeiSubState; +} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE; + +// +// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER +// +typedef struct _WW_CDPD_SERVICE_PROVIDER_ID { + UINT SPI[10]; //10 16-bit service provider IDs + + INT OperatingMode; // 0 = ignore SPI, + // 1 = require SPI from list, + // 2 = prefer SPI from list. + // 3 = exclude SPI from list. + +} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID; + +// +// OID_WW_CDPD_SLEEP_MODE +// +typedef INT WW_CDPD_SLEEP_MODE; +// +// OID_WW_CDPD_TEI +// +typedef ULONG WW_CDPD_TEI; +// +// OID_WW_CDPD_CIRCUIT_SWITCHED +// +typedef struct _WW_CDPD_CIRCUIT_SWITCHED { + INT service_preference; // -1 = unknown, + // 0 = always use packet switched CDPD, + // 1 = always use CS CDPD via AMPS, + // 2 = always use CS CDPD via PSTN, + // 3 = use circuit switched via AMPS only + // when packet switched is not available. + // 4 = use packet switched only when circuit + // switched via AMPS is not available. + // 5 = device manuf. defined service + // preference. + // 6 = device manuf. defined service + // preference. + + INT service_status; // -1 = unknown, + // 0 = packet switched CDPD, + // 1 = circuit switched CDPD via AMPS, + // 2 = circuit switched CDPD via PSTN. + + INT connect_rate; // CS connection bit rate (bits per second). + // 0 = no active connection, + // -1 = unknown + // Dial code last used to dial. + + NDIS_VAR_DATA_DESC dial_code[20]; + + UINT sid; // Current AMPS system ID + + INT a_b_side_selection; // -1 = unknown, + // 0 = no AMPS service + // 1 = AMPS "A" side channels selected + // 2 = AMPS "B" side channels selected + + INT AMPS_channel; // -1= unknown + // 0 = no AMPS service. + // 1-1023 = AMPS channel number in use + + UINT action; // 0 = no action + // 1 = suspend (hangup) + // 2 = dial + + // Default dial code for CS CDPD service + // encoded as specified in the CS CDPD + // implementor guidelines. + NDIS_VAR_DATA_DESC default_dial[20]; + + // Number for the CS CDPD network to call + // back the mobile, encoded as specified in + // the CS CDPD implementor guidelines. + NDIS_VAR_DATA_DESC call_back[20]; + + UINT sid_list[10]; // List of 10 16-bit preferred AMPS + // system IDs for CS CDPD. + + UINT inactivity_timer; // Wait time after last data before dropping + // call. + // 0-65535 = inactivity time limit (seconds). + + UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines. + + UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines. + + UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines. + +} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED; +typedef UINT WW_CDPD_RSSI; +// +// OID_WW_PIN_LOC_AUTHORIZE +// +typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized + // 1 = authorized + // -1 = unknown +// +// OID_WW_PIN_LAST_LOCATION +// OID_WW_PIN_LOC_FIX +// + +typedef struct _WW_PIN_LOCATION { + INT Latitude; // Latitude in hundredths of a second + + INT Longitude; // Longitude in hundredths of a second + + INT Altitude; // Altitude in feet + + INT FixTime; // Time of the location fix, since midnight, local time (of the + // current day), in tenths of a second + + INT NetTime; // Current local network time of the current day, since midnight, + // in tenths of a second + + INT LocQuality; // 0-100 = location quality + + INT LatReg; // Latitude registration offset, in hundredths of a second + + INT LongReg; // Longitude registration offset, in hundredths of a second + + INT GMTOffset; // Offset in minutes of the local time zone from GMT + +} WW_PIN_LOCATION, *PWW_PIN_LOCATION; + +// +// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox +// +typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag +// +// OID_WW_MBX_SUBADDR +// + +typedef struct _WW_MBX_PMAN { + BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN + + UINT MAN; + UCHAR PASSWORD[8]; // Password should be null for Logout and indications. + // Maximum length of password is 8 chars. + +} WW_MBX_PMAN, *PWW_MBX_PMAN; + +// +// OID_WW_MBX_FLEXLIST +// +typedef struct _WW_MBX_FLEXLIST { + INT count; // Number of MAN entries used. + // -1=unknown. + + UINT MAN[7]; // List of MANs. + +} WW_MBX_FLEXLIST; + +// +// OID_WW_MBX_GROUPLIST +// +typedef struct _WW_MBX_GROUPLIST { + INT count; // Number of MAN entries used. + // -1=unknown. + + UINT MAN[15]; // List of MANs. + +} WW_MBX_GROUPLIST; + +// +// OID_WW_MBX_TRAFFIC_AREA +// +typedef enum _WW_MBX_TRAFFIC_AREA { + unknown_traffic_area, // The driver has no information about the current traffic area. + in_traffic_area, // Mobile unit has entered a subscribed traffic area. + in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized. + unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized. +} WW_MBX_TRAFFIC_AREA; + +// +// OID_WW_MBX_LIVE_DIE +// +typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received + // 1 = LIVE last received + // -1 = unknown +// +// OID_WW_MBX_TEMP_DEFAULTLIST +// + +typedef struct _WW_MBX_CHANNEL_PAIR { + UINT Mobile_Tx; + UINT Mobile_Rx; +} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR; +typedef struct _WW_MBX_TEMPDEFAULTLIST { + UINT Length; + WW_MBX_CHANNEL_PAIR ChannelPair[1]; +} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST; + +#endif // WIRELESS_WAN +#endif // _NTDDNDIS_ diff --git a/lib/packet/include/packet32.h b/lib/packet/include/packet32.h new file mode 100644 index 0000000..bcb167a --- /dev/null +++ b/lib/packet/include/packet32.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** @ingroup packetapi + * @{ + */ + +/** @defgroup packet32h Packet.dll definitions and data structures + * Packet32.h contains the data structures and the definitions used by packet.dll. + * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included + * by the applications that use the functions of this library + * @{ + */ + +#ifndef __PACKET32 +#define __PACKET32 + +#include +#include "devioctl.h" + +// Working modes +#define PACKET_MODE_CAPT 0x0 ///< Capture mode +#define PACKET_MODE_STAT 0x1 ///< Statistical mode +#define PACKET_MODE_DUMP 0x10 ///< Dump mode +#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode + +// ioctls +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size. +#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program. +#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats. +#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout. +#define pBIOCSMODE 7412 ///< IOCTL code: set working mode. +#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app. +#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call. +#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value. +#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value. +#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only. +#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only. +#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode. +#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer. +#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets. +#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets. +#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function. +#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function. + +#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only. + + +/// Alignment macro. Defines the alignment size. +#define Packet_ALIGNMENT sizeof(int) +/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. +#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) + +/*! + \brief Network type structure. + + This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed. +*/ +typedef struct NetType +{ + UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information) + UINT LinkSpeed; ///< The speed of the network in bits per second +}NetType; + + +//some definitions stolen from libpcap + +#ifndef BPF_MAJOR_VERSION + +/*! + \brief A BPF pseudo-assembly program. + + The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. +*/ +struct bpf_program { + UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow. + struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program. +}; + +/*! + \brief A single BPF pseudo-instruction. + + bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver. +*/ +struct bpf_insn { + USHORT code; ///< Instruction type and addressing mode. + UCHAR jt; ///< Jump if true + UCHAR jf; ///< Jump if false + int k; ///< Generic field used for various purposes. +}; + +/*! + \brief Structure that contains a couple of statistics values on the current capture. + + It is used by packet.dll to return statistics about a capture session. +*/ +struct bpf_stat { + UINT bs_recv; ///< Number of packets that the driver received from the network adapter + ///< from the beginning of the current capture. This value includes the packets + ///< lost by the driver. + UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture. + ///< Basically, a packet is lost when the the buffer of the driver is full. + ///< In this situation the packet cannot be stored and the driver rejects it. + UINT ps_ifdrop; ///< drops by interface. XXX not yet supported + UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and + ///< thus reach the application. +}; + +/*! + \brief Packet header. + + This structure defines the header associated with every packet delivered to the application. +*/ +struct bpf_hdr { + struct timeval bh_tstamp; ///< The timestamp associated with the captured packet. + ///< It is stored in a TimeVal structure. + UINT bh_caplen; ///< Length of captured portion. The captured portion can be different + ///< from the original packet, because it is possible (with a proper filter) + ///< to instruct the driver to capture only a portion of the packets. + UINT bh_datalen; ///< Original length of packet + USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases, + ///< a padding could be added between the end of this structure and the packet + ///< data for performance reasons. This filed can be used to retrieve the actual data + ///< of the packet. +}; + +/*! + \brief Dump packet header. + + This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets(). + It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a + packet in a dump file. This makes straightforward sending WinPcap dump files to the network. +*/ +struct dump_bpf_hdr{ + struct timeval ts; ///< Time stamp of the packet + UINT caplen; ///< Length of captured portion. The captured portion can smaller than the + ///< the original packet, because it is possible (with a proper filter) to + ///< instruct the driver to capture only a portion of the packets. + UINT len; ///< Length of the original packet (off wire). +}; + + +#endif + +#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices +#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links +#define NMAX_PACKET 65535 + +/*! + \brief Describes a network adapter. + + This structure is the most important for the functioning of packet.dll, but the great part of its fields + should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters +*/ +typedef struct _ADAPTER { + HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver. + CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened. + int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated + ///< on the wire. + HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter. + ///< It can be passed to standard Win32 functions (like WaitForSingleObject + ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some + ///< data. It is particularly useful in GUI applications that need to wait + ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy() + ///< function can be used to define the minimum amount of data in the kernel buffer + ///< that will cause the event to be signalled. + + UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and + ///< ReadEvent will be signaled, also if no packets were captured +} ADAPTER, *LPADAPTER; + +/*! + \brief Structure that contains a group of packets coming from the driver. + + This structure defines the header associated with every packet delivered to the application. +*/ +typedef struct _PACKET { + HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications. + OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications. + PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for + ///< details about the organization of the data in this buffer + UINT Length; ///< Length of the buffer + DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data + ///< received by the last call to PacketReceivePacket() + BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications. +} PACKET, *LPPACKET; + +/*! + \brief Structure containing an OID request. + + It is used by the PacketRequest() function to send an OID to the interface card driver. + It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, + the list of the multicast groups defined on it, and so on. +*/ +struct _PACKET_OID_DATA { + ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h + ///< for a complete list of valid codes. + ULONG Length; ///< Length of the data field + UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received + ///< from the adapter. +}; +typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; + +/*! + \brief Addresses of a network adapter. + + This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with + an adapter. +*/ +typedef struct npf_if_addr { + struct sockaddr IPAddress; ///< IP address. + struct sockaddr SubnetMask; ///< Netmask for that address. + struct sockaddr Broadcast; ///< Broadcast address. +}npf_if_addr; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @} + */ + +//--------------------------------------------------------------------------- +// FUNCTIONS +//--------------------------------------------------------------------------- + +PCHAR PacketGetVersion(); +BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes); +BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites); +BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode); +BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout); +BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp); +BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s); +BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim); +BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type); +LPADAPTER PacketOpenAdapter(LPTSTR AdapterName); +BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync); +INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync); +LPPACKET PacketAllocatePacket(void); +VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length); +VOID PacketFreePacket(LPPACKET lpPacket); +BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync); +BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter); +BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize); +BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp); +BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries); +BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData); +HANDLE PacketGetReadEvent(LPADAPTER AdapterObject); +BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len); +BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks); +BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync); +BOOL PacketStopDriver(); +VOID PacketCloseAdapter(LPADAPTER lpAdapter); + +#ifdef __cplusplus +} +#endif + +#endif //__PACKET32 diff --git a/lib/packet/makefile b/lib/packet/makefile new file mode 100644 index 0000000..3682663 --- /dev/null +++ b/lib/packet/makefile @@ -0,0 +1,25 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = packet + +TARGET_BASE = 0x77780000 + +TARGET_CFLAGS = -I./include -DUNICODE -D_UNICODE -DLE -DDBG -D_DEBUG + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = \ + Packet32.o \ + trace.o + +TARGET_CLEAN = $(TARGET_OBJECTS) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/lib/packet/packet.def b/lib/packet/packet.def new file mode 100644 index 0000000..bba1a4c --- /dev/null +++ b/lib/packet/packet.def @@ -0,0 +1,34 @@ +LIBRARY packet + +DESCRIPTION 'Packet driver dll' + +EXPORTS + PacketLibraryVersion + PacketGetVersion + PacketOpenAdapter + PacketSendPacket + PacketSendPackets + PacketAllocatePacket + PacketInitPacket + PacketFreePacket + PacketReceivePacket + PacketCloseAdapter + PacketSetHwFilter + PacketGetAdapterNames + PacketRequest + PacketSetBuff + PacketSetBpf + PacketGetStats + PacketGetStatsEx + PacketGetNetType + PacketSetReadTimeout + PacketSetMode + PacketSetNumWrites + PacketGetNetInfo + PacketGetNetInfoEx + PacketSetMinToCopy + PacketGetReadEvent + PacketStopDriver + PacketSetDumpName + PacketSetDumpLimits + PacketIsDumpEnded diff --git a/lib/packet/packet.edf b/lib/packet/packet.edf new file mode 100644 index 0000000..d90c609 --- /dev/null +++ b/lib/packet/packet.edf @@ -0,0 +1,32 @@ +; PACKET.DLL - Windows Packet Capture DLL + +LIBRARY packet.dll + +EXPORTS +;WEP +PacketLibraryVersion=PacketLibraryVersion +PacketGetVersion=PacketGetVersion +PacketOpenAdapter=PacketOpenAdapter +PacketSendPacket=PacketSendPacket +PacketAllocatePacket=PacketAllocatePacket +PacketInitPacket=PacketInitPacket +PacketFreePacket=PacketFreePacket +PacketReceivePacket=PacketReceivePacket +PacketCloseAdapter=PacketCloseAdapter +PacketSetHwFilter=PacketSetHwFilter +PacketGetAdapterNames=PacketGetAdapterNames +PacketRequest=PacketRequest +PacketSetBuff=PacketSetBuff +PacketSetBpf=PacketSetBpf +PacketGetStats=PacketGetStats +PacketGetNetType=PacketGetNetType +PacketSetReadTimeout=PacketSetReadTimeout +PacketSetMode=PacketSetMode +PacketSetNumWrites=PacketSetNumWrites +PacketGetNetInfo=PacketGetNetInfo +PacketGetNetInfoEx=PacketGetNetInfoEx +PacketSetMinToCopy=PacketSetMinToCopy +PacketGetReadEvent=PacketGetReadEvent +PacketStopDriver=PacketStopDriver + +; EOF diff --git a/lib/packet/packet.rc b/lib/packet/packet.rc new file mode 100644 index 0000000..bfa5d12 --- /dev/null +++ b/lib/packet/packet.rc @@ -0,0 +1,44 @@ +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,3,0,33 + PRODUCTVERSION 2,3,0,33 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "WinPcap low level packet library\0" + VALUE "CompanyName", "Politecnico di Torino\0" + VALUE "FileDescription", "Packet\0" + VALUE "FileVersion", "2, 3, 0, 33\0" + VALUE "InternalName", "Packet\0" + VALUE "LegalCopyright", "Copyright © 1999-2002\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "Packet.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "WinPcap low level packet library\0" + VALUE "ProductVersion", "2, 3, 0, 33\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/packet/resource.h b/lib/packet/resource.h new file mode 100644 index 0000000..6cf0c78 --- /dev/null +++ b/lib/packet/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by version.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/lib/packet/trace.c b/lib/packet/trace.c new file mode 100644 index 0000000..8104ebc --- /dev/null +++ b/lib/packet/trace.c @@ -0,0 +1,53 @@ +///////////////////////////////////////////////////////////////////////////// +// Diagnostic Trace +// +#include +#include +#include +//#include +#include "trace.h" + +#ifdef _DEBUG + +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; + +void _DebugBreak(void) +{ + DebugBreak(); +} + +//void Trace(TCHAR* lpszFormat, ...) +void Trace(char* lpszFormat, ...) +{ + va_list args; + int nBuf; + char szBuffer[512]; + + va_start(args, lpszFormat); + nBuf = _vsnprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), lpszFormat, args); + OutputDebugStringA(szBuffer); + // was there an error? was the expanded string too long? + //ASSERT(nBuf >= 0); + va_end(args); +} + +void Assert(void* assert, const char* file, int line, void* msg) +{ + if (msg == NULL) { + printf("ASSERT -- %s occured on line %u of file %s.\n", + assert, line, file); + } else { + printf("ASSERT -- %s occured on line %u of file %s: Message = %s.\n", + assert, line, file, msg); + } +} + +#else + +//void Trace(TCHAR* lpszFormat, ...) { }; +void Trace(char* lpszFormat, ...) { }; +void Assert(void* assert, const char* file, int line, void* msg) { }; + +#endif //_DEBUG +///////////////////////////////////////////////////////////////////////////// diff --git a/lib/packet/trace.h b/lib/packet/trace.h new file mode 100644 index 0000000..a227b16 --- /dev/null +++ b/lib/packet/trace.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////// +// Diagnostic Trace +// +#ifndef __TRACE_H__ +#define __TRACE_H__ + +#ifdef _DEBUG + +#ifdef _X86_ +#define BreakPoint() _asm { int 3h } +#else +#define BreakPoint() _DebugBreak() +#endif + +#ifndef ASSERT +#define ASSERT(exp) \ +{ \ + if (!(exp)) { \ + Assert(#exp, __FILE__, __LINE__, NULL); \ + BreakPoint(); \ + } \ +} \ + +#define ASSERTMSG(exp, msg) \ +{ \ + if (!(exp)) { \ + Assert(#exp, __FILE__, __LINE__, msg); \ + BreakPoint(); \ + } \ +} +#endif + +//============================================================================= +// MACRO: TRACE() +//============================================================================= + +#define TRACE Trace + + +#else // _DEBUG + +//============================================================================= +// Define away MACRO's ASSERT() and TRACE() in non debug builds +//============================================================================= + +#ifndef ASSERT +#define ASSERT(exp) +#define ASSERTMSG(exp, msg) +#endif + +#define TRACE 0 ? (void)0 : Trace + +#endif // !_DEBUG + + +void Assert(void* assert, const char* file, int line, void* msg); +//void Trace(TCHAR* lpszFormat, ...); +void Trace(char* lpszFormat, ...); + + +#endif // __TRACE_H__ +///////////////////////////////////////////////////////////////////////////// diff --git a/lib/psapi/enum/module.c b/lib/psapi/enum/module.c new file mode 100644 index 0000000..dc9a0fa --- /dev/null +++ b/lib/psapi/enum/module.c @@ -0,0 +1,274 @@ +/* $Id$ +*/ +/* + * COPYRIGHT: See COPYING in the top level directory + * LICENSE: See LGPL.txt in the top level directory + * PROJECT: ReactOS system libraries + * FILE: reactos/lib/psapi/enum/module.c + * PURPOSE: Enumerate system and process modules + * PROGRAMMER: KJK::Hyperion + * UPDATE HISTORY: + * 10/06/2002: Created + * 29/08/2002: Generalized the interface to improve reusability, + * more efficient use of memory operations + */ + +#include +#include +#include +#include + +NTSTATUS +STDCALL +PsaEnumerateSystemModules +( + IN PSYSMOD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + ULONG nSize; + register NTSTATUS nErrCode = STATUS_SUCCESS; + register PULONG pnModuleCount = &nSize; + register PSYSTEM_MODULE_ENTRY psmeCurModule; + register ULONG nModuleCount; + + /* initial probe */ + nErrCode = NtQuerySystemInformation + ( + SystemModuleInformation, + pnModuleCount, + sizeof(nSize), + NULL + ); + + if(nErrCode != STATUS_INFO_LENGTH_MISMATCH && !NT_SUCCESS(nErrCode)) + { + /* failure */ + DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode); + return nErrCode; + } + + /* RATIONALE: the loading of a system module is a rare occurrence. To minimize + memory operations that could be expensive, or fragment the pool/heap, we try + to determine the buffer size in advance, knowing that the number of elements + is unlikely to change */ + nSize = sizeof(ULONG) + nSize * sizeof(SYSTEM_MODULE_ENTRY); + pnModuleCount = NULL; + + do + { + register void * pTmp; + + /* free the buffer, and reallocate it to the new size. RATIONALE: since we + ignore the buffer's content at this point, there's no point in a realloc(), + that could end up copying a large chunk of data we'd discard anyway */ + free(pnModuleCount); + pTmp = malloc(nSize); + + if(pTmp == NULL) + { + /* failure */ + nErrCode = STATUS_NO_MEMORY; + goto esm_Finalize; + } + + pnModuleCount = pTmp; + + /* query the information */ + nErrCode = NtQuerySystemInformation + ( + SystemModuleInformation, + pnModuleCount, + nSize, + NULL + ); + + /* double the buffer for the next loop */ + nSize += nSize; + } + /* repeat until the buffer is big enough */ + while(nErrCode == STATUS_INFO_LENGTH_MISMATCH); + + if(!NT_SUCCESS(nErrCode)) + { + /* failure */ + DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode); + goto esm_Finalize; + } + + /* the array of modules starts right after an ULONG storing their count */ + psmeCurModule = (PSYSTEM_MODULE_ENTRY)(pnModuleCount + 1); + + nModuleCount = *pnModuleCount; + + /* repeat until all modules have been returned */ + while(nModuleCount > 0) + { + /* return current module to the callback */ + nErrCode = Callback(nModuleCount, psmeCurModule, CallbackContext); + + if(!NT_SUCCESS(nErrCode)) + /* failure */ + goto esm_Finalize; + + /* next module */ + psmeCurModule ++; + nModuleCount --; + } + +esm_Finalize: + /* free the buffer */ + free(pnModuleCount); + + return (nErrCode); +} + +NTSTATUS +STDCALL +PsaEnumerateProcessModules +( + IN HANDLE ProcessHandle, + IN PPROCMOD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + register NTSTATUS nErrCode; + + /* current process - use direct memory copy */ + if(ProcessHandle == NtCurrentProcess()) + { + register PLIST_ENTRY pleListHead; + register PLIST_ENTRY pleCurEntry; + +#if 0 + /* FIXME: activate this when GCC supports SEH */ + __try + { +#endif + pleListHead = &(NtCurrentPeb()->Ldr->InLoadOrderModuleList); + pleCurEntry = pleListHead->Flink; + + while(pleCurEntry != pleListHead) + { + register PLDR_MODULE plmModule = CONTAINING_RECORD + ( + pleCurEntry, + LDR_MODULE, + InLoadOrderModuleList + ); + + /* return the current module to the callback */ + nErrCode = Callback(ProcessHandle, plmModule, CallbackContext); + + if(!NT_SUCCESS(nErrCode)) + /* failure */ + goto epm_Failure; + + pleCurEntry = plmModule->InLoadOrderModuleList.Flink; + } +#if 0 + /* FIXME: activate this when GCC supports SEH */ + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + return GetExceptionCode(); + } +#endif + } + /* another process */ + else + { + PROCESS_BASIC_INFORMATION pbiInfo; + PPEB_LDR_DATA ppldLdrData; + LDR_MODULE lmModule; + PLIST_ENTRY pleListHead; + PLIST_ENTRY pleCurEntry; + + /* query the process basic information (includes the PEB address) */ + nErrCode = NtQueryInformationProcess + ( + ProcessHandle, + ProcessBasicInformation, + &pbiInfo, + sizeof(pbiInfo), + NULL + ); + + if(!NT_SUCCESS(nErrCode)) + { + /* failure */ + DPRINT(FAILED_WITH_STATUS, "NtQueryInformationProcess", nErrCode); + goto epm_Failure; + } + + /* get the address of the PE Loader data */ + nErrCode = NtReadVirtualMemory + ( + ProcessHandle, + &(pbiInfo.PebBaseAddress->Ldr), + &ppldLdrData, + sizeof(ppldLdrData), + NULL + ); + + if(!NT_SUCCESS(nErrCode)) + { + /* failure */ + DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode); + goto epm_Failure; + } + + /* head of the module list: the last element in the list will point to this */ + pleListHead = &ppldLdrData->InLoadOrderModuleList; + + /* get the address of the first element in the list */ + nErrCode = NtReadVirtualMemory + ( + ProcessHandle, + &(ppldLdrData->InLoadOrderModuleList.Flink), + &pleCurEntry, + sizeof(pleCurEntry), + NULL + ); + + while(pleCurEntry != pleListHead) + { + /* read the current module */ + nErrCode = NtReadVirtualMemory + ( + ProcessHandle, + CONTAINING_RECORD(pleCurEntry, LDR_MODULE, InLoadOrderModuleList), + &lmModule, + sizeof(lmModule), + NULL + ); + + if(!NT_SUCCESS(nErrCode)) + { + /* failure */ + DPRINT(FAILED_WITH_STATUS, "NtReadVirtualMemory", nErrCode); + goto epm_Failure; + } + + /* return the current module to the callback */ + nErrCode = Callback(ProcessHandle, &lmModule, CallbackContext); + + if(!NT_SUCCESS(nErrCode)) + /* failure */ + goto epm_Failure; + + /* address of the next module in the list */ + pleCurEntry = lmModule.InLoadOrderModuleList.Flink; + } + + } + + /* success */ + return (STATUS_SUCCESS); + +epm_Failure: + /* failure */ + return (nErrCode); +} + +/* EOF */ diff --git a/lib/psapi/enum/process.c b/lib/psapi/enum/process.c new file mode 100644 index 0000000..f6e934d --- /dev/null +++ b/lib/psapi/enum/process.c @@ -0,0 +1,110 @@ +/* $Id$ +*/ +/* + * COPYRIGHT: See COPYING in the top level directory + * LICENSE: See LGPL.txt in the top level directory + * PROJECT: ReactOS system libraries + * FILE: reactos/lib/psapi/enum/process.c + * PURPOSE: Enumerate processes + * PROGRAMMER: KJK::Hyperion + * UPDATE HISTORY: + * 10/06/2002: Created + * 29/08/2002: Generalized the interface to improve reusability, + * more efficient use of memory operations + */ + +#include +#include +#include +#include + +NTSTATUS +STDCALL +PsaEnumerateProcesses +( + IN PPROC_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +) +{ + register NTSTATUS nErrCode = STATUS_SUCCESS; + PSYSTEM_PROCESS_INFORMATION pInfoBuffer = NULL; + PSYSTEM_PROCESS_INFORMATION pInfoHead = NULL; + ULONG nSize = 32768; + + /* FIXME: if the system has loaded several processes and threads, the buffer + could get really big. But if there's several processes and threads, the + system is already under stress, and a huge buffer could only make things + worse. The function should be profiled to see what's the average minimum + buffer size, to succeed on the first shot */ + do + { + void * pTmp; + + /* free the buffer, and reallocate it to the new size. RATIONALE: since we + ignore the buffer's contents at this point, there's no point in a realloc() + that could end up copying a large chunk of data we'd discard anyway */ + free(pInfoBuffer); + pTmp = malloc(nSize); + + if(pTmp == NULL) + { + /* failure */ + DPRINT(FAILED_WITH_STATUS, "malloc", STATUS_NO_MEMORY); + nErrCode = STATUS_NO_MEMORY; + goto esp_Finalize; + } + + pInfoBuffer = pTmp; + + /* query the information */ + nErrCode = NtQuerySystemInformation + ( + SystemProcessesAndThreadsInformation, + pInfoBuffer, + nSize, + NULL + ); + + /* double the buffer size */ + nSize += nSize; + } + /* repeat until the buffer is big enough */ + while(nErrCode == STATUS_INFO_LENGTH_MISMATCH); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) + { + DPRINT(FAILED_WITH_STATUS, "NtQuerySystemInformation", nErrCode); + goto esp_Finalize; + } + + /* list head */ + pInfoHead = pInfoBuffer; + + /* scan the list */ + while(1) + { + /* notify the callback */ + nErrCode = Callback(pInfoHead, CallbackContext); + + /* if the callback returned an error or this is the end of the process list, + break out */ + if(!NT_SUCCESS(nErrCode) || pInfoHead->RelativeOffset == 0) + break; + + /* move to the next process */ + pInfoHead = + (SYSTEM_PROCESS_INFORMATION*) + ((ULONG)pInfoHead + pInfoHead->RelativeOffset); + } + +esp_Finalize: + /* free the buffer */ + free(pInfoBuffer); + + /* return the last status */ + return (nErrCode); +} + +/* EOF */ + diff --git a/lib/psapi/include/internal/psapi.h b/lib/psapi/include/internal/psapi.h new file mode 100644 index 0000000..76e6fb9 --- /dev/null +++ b/lib/psapi/include/internal/psapi.h @@ -0,0 +1,90 @@ +/* $Id$ +*/ +/* + * internal/psapi.h + * + * Process Status Helper API, native interface + * + * This file is part of the ReactOS Operating System. + * + * Contributors: + * Created by KJK::Hyperion + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __INTERNAL_PSAPI_H_INCLUDED__ +#define __INTERNAL_PSAPI_H_INCLUDED__ + +/* INCLUDES */ +#include +#include + +/* OBJECTS */ + +/* TYPES */ +typedef NTSTATUS STDCALL (*PPROC_ENUM_ROUTINE) +( + IN PSYSTEM_PROCESS_INFORMATION CurrentProcess, + IN OUT PVOID CallbackContext +); + +typedef NTSTATUS STDCALL (*PSYSMOD_ENUM_ROUTINE) +( + IN ULONG ModuleCount, + IN PSYSTEM_MODULE_ENTRY CurrentModule, + IN OUT PVOID CallbackContext +); + +typedef NTSTATUS STDCALL (*PPROCMOD_ENUM_ROUTINE) +( + IN HANDLE ProcessHandle, + IN PLDR_MODULE CurrentModule, + IN OUT PVOID CallbackContext +); + +/* CONSTANTS */ +#define FAILED_WITH_STATUS DEFINE_DBG_MSG("%s() failed, status 0x%08X") + +/* PROTOTYPES */ +NTSTATUS +STDCALL +PsaEnumerateProcesses +( + IN PPROC_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +); + +NTSTATUS +STDCALL +PsaEnumerateSystemModules +( + IN PSYSMOD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +); + +NTSTATUS +STDCALL +PsaEnumerateProcessModules +( + IN HANDLE ProcessHandle, + IN PPROCMOD_ENUM_ROUTINE Callback, + IN OUT PVOID CallbackContext +); + +/* MACROS */ +#define DEFINE_DBG_MSG(__str__) "PSAPI: " __str__ "\n" + +#endif /* __INTERNAL_PSAPI_H_INCLUDED__ */ + +/* EOF */ + diff --git a/lib/psapi/makefile b/lib/psapi/makefile new file mode 100644 index 0000000..91b5995 --- /dev/null +++ b/lib/psapi/makefile @@ -0,0 +1,26 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = psapi + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_CFLAGS = -I./include -Wall + +TARGET_BASE = 0x68F70000 + +TARGET_OBJECTS = \ + misc/dllmain.o \ + misc/malloc.o \ + misc/stubs.o \ + misc/win32.o \ + enum/module.o \ + enum/process.o + +include $(PATH_TO_TOP)/rules.mak +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/lib/psapi/misc/dllmain.c b/lib/psapi/misc/dllmain.c new file mode 100644 index 0000000..cc7952a --- /dev/null +++ b/lib/psapi/misc/dllmain.c @@ -0,0 +1,32 @@ +/* $Id$ +*/ +/* + * COPYRIGHT: None + * LICENSE: Public domain + * PROJECT: ReactOS system libraries + * FILE: reactos/lib/psapi/misc/malloc.c + * PURPOSE: PSAPI.DLL main procedure + * PROGRAMMER: KJK::Hyperion + * UPDATE HISTORY: + * 28/11/2001: Created (Emanuele Aliberti ) + * 30/08/2002: Minimal tweak (KJK::Hyperion ) + */ +#include +#include + +BOOLEAN STDCALL DllMain +( + PVOID hinstDll, + ULONG dwReason, + PVOID reserved +) +{ + if(dwReason == DLL_PROCESS_ATTACH) + /* don't bother calling the entry point on thread startup - PSAPI.DLL doesn't + store any per-thread data */ + LdrDisableThreadCalloutsForDll(hinstDll); + + return (TRUE); +} + +/* EOF */ diff --git a/lib/psapi/misc/malloc.c b/lib/psapi/misc/malloc.c new file mode 100644 index 0000000..9baeb64 --- /dev/null +++ b/lib/psapi/misc/malloc.c @@ -0,0 +1,65 @@ +/* $Id$ + */ +/* + * COPYRIGHT: None + * LICENSE: Public domain + * PROJECT: ReactOS system libraries + * FILE: reactos/lib/psapi/misc/malloc.c + * PURPOSE: Memory allocator for PSAPI + * PROGRAMMER: KJK::Hyperion + * UPDATE HISTORY: + * 10/06/2002: Created + */ + +#include +#include +#include + +PVOID STDCALL MemAlloc +( + IN HANDLE Heap, + IN PVOID Ptr, + IN ULONG Size +) +{ + PVOID pBuf = NULL; + + if(Size == 0 && Ptr == NULL) + return (NULL); + + if(Heap == NULL) + Heap = NtCurrentPeb()->ProcessHeap; + + if(Size > 0) + { + if(Ptr == NULL) + /* malloc */ + pBuf = RtlAllocateHeap(Heap, 0, Size); + else + /* realloc */ + pBuf = RtlReAllocateHeap(Heap, 0, Ptr, Size); + } + else + /* free */ + RtlFreeHeap(Heap, 0, Ptr); + + return pBuf; +} + +void *malloc(size_t size) +{ + return MemAlloc(NULL, NULL, size); +} + +void *realloc(void *ptr, size_t size) +{ + return MemAlloc(NULL, ptr, size); +} + +void free(void *ptr) +{ + MemAlloc(NULL, ptr, 0); +} + +/* EOF */ + diff --git a/lib/psapi/misc/stubs.c b/lib/psapi/misc/stubs.c new file mode 100644 index 0000000..d720cc4 --- /dev/null +++ b/lib/psapi/misc/stubs.c @@ -0,0 +1,63 @@ +/* $Id$ */ +#include +#include + +#if 0 +BOOL STDCALL EnumPageFiles( + PENUM_PAGE_CALLBACKW pCallbackRoutine, + LPVOID lpContext +) +{ + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; +} + +BOOL STDCALL GetPerformanceInfo( + PPERFORMANCE_INFORMATION pPerformanceInformation, + DWORD cb + +) +{ + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; +} +#endif +BOOL STDCALL GetProcessMemoryInfo( + HANDLE Process, // handle to process + PPROCESS_MEMORY_COUNTERS ppsmemCounters, // buffer + DWORD cb // size of buffer +) +{ + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; +} + +BOOL STDCALL GetWsChanges( + HANDLE hProcess, // handle to process + PPSAPI_WS_WATCH_INFORMATION lpWatchInfo, // buffer + DWORD cb // size of buffer +) +{ + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; +} + +BOOL STDCALL InitializeProcessForWsWatch( + HANDLE hProcess // handle to process +) +{ + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; +} + +BOOL STDCALL QueryWorkingSet( + HANDLE hProcess, // handle to process + PVOID pv, // information buffer + DWORD cb // size of buffer +) +{ + SetLastError(ERROR_INVALID_FUNCTION); + return FALSE; +} + +/* EOF */ diff --git a/lib/psapi/misc/win32.c b/lib/psapi/misc/win32.c new file mode 100644 index 0000000..edb9a0c --- /dev/null +++ b/lib/psapi/misc/win32.c @@ -0,0 +1,938 @@ +/* $Id$ + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * LICENSE: See LGPL.txt in the top level directory + * PROJECT: ReactOS system libraries + * FILE: reactos/lib/psapi/misc/win32.c + * PURPOSE: Win32 interfaces for PSAPI + * PROGRAMMER: KJK::Hyperion + * UPDATE HISTORY: + * 10/06/2002: Created + */ + +#include +#include +#include +#include +#include +#include +#include + +/* EmptyWorkingSet */ +BOOL STDCALL EmptyWorkingSet(HANDLE hProcess) +{ + NTSTATUS nErrCode; + QUOTA_LIMITS qlProcessQuota; + + /* query the working set */ + nErrCode = NtQueryInformationProcess + ( + hProcess, + ProcessQuotaLimits, + &qlProcessQuota, + sizeof(qlProcessQuota), + NULL + ); + + /* failure */ + if(!NT_SUCCESS(nErrCode)) + goto fail; + + /* empty the working set */ + qlProcessQuota.MinimumWorkingSetSize = -1; + qlProcessQuota.MaximumWorkingSetSize = -1; + + /* set the working set */ + nErrCode = NtSetInformationProcess + ( + hProcess, + ProcessQuotaLimits, + &qlProcessQuota, + sizeof(qlProcessQuota) + ); + + /* success */ + if(NT_SUCCESS(nErrCode)) + return (TRUE); + +fail: + /* failure */ + SetLastError(RtlNtStatusToDosError(nErrCode)); + return (FALSE); +} + +/* EnumDeviceDrivers */ +/* callback context */ +typedef struct _ENUM_DEVICE_DRIVERS_CONTEXT +{ + LPVOID *lpImageBase; + DWORD nCount; +} ENUM_DEVICE_DRIVERS_CONTEXT, *PENUM_DEVICE_DRIVERS_CONTEXT; + +/* callback routine */ +NTSTATUS STDCALL EnumDeviceDriversCallback +( + IN ULONG ModuleCount, + IN PSYSTEM_MODULE_ENTRY CurrentModule, + IN OUT PVOID CallbackContext +) +{ + register PENUM_DEVICE_DRIVERS_CONTEXT peddcContext = + (PENUM_DEVICE_DRIVERS_CONTEXT)CallbackContext; + + /* no more buffer space */ + if(peddcContext->nCount == 0) + return STATUS_INFO_LENGTH_MISMATCH; + + /* return current module */ + *(peddcContext->lpImageBase) = CurrentModule->BaseAddress; + + /* go to next array slot */ + (peddcContext->lpImageBase) ++; + (peddcContext->nCount) --; + + return STATUS_SUCCESS; +} + +/* exported interface */ +BOOL STDCALL EnumDeviceDrivers +( + LPVOID *lpImageBase, + DWORD cb, + LPDWORD lpcbNeeded +) +{ + register NTSTATUS nErrCode; + ENUM_DEVICE_DRIVERS_CONTEXT eddcContext = {lpImageBase, cb / sizeof(PVOID)}; + + cb /= sizeof(PVOID); + + /* do nothing if the buffer is empty */ + if(cb == 0 || lpImageBase == NULL) + { + *lpcbNeeded = 0; + return (TRUE); + } + + /* enumerate the system modules */ + nErrCode = PsaEnumerateSystemModules(&EnumDeviceDriversCallback, &eddcContext); + + /* return the count of bytes returned */ + *lpcbNeeded = (cb - eddcContext.nCount) * sizeof(PVOID); + + /* success */ + if(NT_SUCCESS(nErrCode) || nErrCode == STATUS_INFO_LENGTH_MISMATCH) + return (TRUE); + else + { + /* failure */ + SetLastError(RtlNtStatusToDosError(nErrCode)); + return (FALSE); + } +} + +/* EnumProcesses */ +/* callback context */ +typedef struct _ENUM_PROCESSES_CONTEXT +{ + DWORD *lpidProcess; + DWORD nCount; +} ENUM_PROCESSES_CONTEXT, *PENUM_PROCESSES_CONTEXT; + +/* callback routine */ +NTSTATUS STDCALL EnumProcessesCallback +( + IN PSYSTEM_PROCESS_INFORMATION CurrentProcess, + IN OUT PVOID CallbackContext +) +{ + register PENUM_PROCESSES_CONTEXT pepcContext = + (PENUM_PROCESSES_CONTEXT)CallbackContext; + + /* no more buffer space */ + if(pepcContext->nCount == 0) + return STATUS_INFO_LENGTH_MISMATCH; + + /* return current process */ + *(pepcContext->lpidProcess) = CurrentProcess->ProcessId; + + /* go to next array slot */ + (pepcContext->lpidProcess) ++; + (pepcContext->nCount) --; + + return STATUS_SUCCESS; +} + +/* exported interface */ +BOOL STDCALL EnumProcesses +( + DWORD *lpidProcess, + DWORD cb, + LPDWORD lpcbNeeded +) +{ + register NTSTATUS nErrCode; + ENUM_PROCESSES_CONTEXT epcContext = {lpidProcess, cb / sizeof(DWORD)}; + + cb /= sizeof(DWORD); + + /* do nothing if the buffer is empty */ + if(cb == 0 || lpidProcess == NULL) + { + *lpcbNeeded = 0; + return (TRUE); + } + + /* enumerate the process ids */ + nErrCode = PsaEnumerateProcesses(&EnumProcessesCallback, &epcContext); + + *lpcbNeeded = (cb - epcContext.nCount) * sizeof(DWORD); + + /* success */ + if(NT_SUCCESS(nErrCode) || nErrCode == STATUS_INFO_LENGTH_MISMATCH) + return (TRUE); + else + { + /* failure */ + SetLastError(RtlNtStatusToDosError(nErrCode)); + return (FALSE); + } +} + +/* EnumProcessModules */ +/* callback context */ +typedef struct _ENUM_PROCESS_MODULES_CONTEXT +{ + HMODULE *lphModule; + DWORD nCount; +} ENUM_PROCESS_MODULES_CONTEXT, *PENUM_PROCESS_MODULES_CONTEXT; + +/* callback routine */ +NTSTATUS STDCALL EnumProcessModulesCallback +( + IN HANDLE ProcessHandle, + IN PLDR_MODULE CurrentModule, + IN OUT PVOID CallbackContext +) +{ + register PENUM_PROCESS_MODULES_CONTEXT pepmcContext = + (PENUM_PROCESS_MODULES_CONTEXT)CallbackContext; + + /* no more buffer space */ + if(pepmcContext->nCount == 0) + return STATUS_INFO_LENGTH_MISMATCH; + + /* return current process */ + *(pepmcContext->lphModule) = CurrentModule->BaseAddress; + + /* go to next array slot */ + (pepmcContext->lphModule) ++; + (pepmcContext->nCount) --; + + return STATUS_SUCCESS; +} + +/* exported interface */ +BOOL STDCALL EnumProcessModules( + HANDLE hProcess, + HMODULE *lphModule, + DWORD cb, + LPDWORD lpcbNeeded +) +{ + register NTSTATUS nErrCode; + ENUM_PROCESS_MODULES_CONTEXT epmcContext = {lphModule, cb / sizeof(HMODULE)}; + + cb /= sizeof(DWORD); + + /* do nothing if the buffer is empty */ + if(cb == 0 || lphModule == NULL) + { + *lpcbNeeded = 0; + return (TRUE); + } + + /* enumerate the process modules */ + nErrCode = PsaEnumerateProcessModules + ( + hProcess, + &EnumProcessModulesCallback, + &epmcContext + ); + + *lpcbNeeded = (cb - epmcContext.nCount) * sizeof(DWORD); + + /* success */ + if(NT_SUCCESS(nErrCode) || nErrCode == STATUS_INFO_LENGTH_MISMATCH) + return (TRUE); + else + { + /* failure */ + SetLastError(RtlNtStatusToDosError(nErrCode)); + return (FALSE); + } +} + +/* GetDeviceDriverBase/FileName */ +/* common callback context */ +typedef struct _GET_DEVICE_DRIVER_NAME_CONTEXT +{ + LPVOID ImageBase; + struct + { + ULONG bFullName:sizeof(ULONG) * 8 / 2; + ULONG bUnicode:sizeof(ULONG) * 8 / 2; + }; + DWORD nSize; + union + { + LPVOID lpName; + LPSTR lpAnsiName; + LPWSTR lpUnicodeName; + }; +} GET_DEVICE_DRIVER_NAME_CONTEXT, *PGET_DEVICE_DRIVER_NAME_CONTEXT; + +/* common callback routine */ +NTSTATUS STDCALL GetDeviceDriverNameCallback +( + IN ULONG ModuleCount, + IN PSYSTEM_MODULE_ENTRY CurrentModule, + IN OUT PVOID CallbackContext +) +{ + register PGET_DEVICE_DRIVER_NAME_CONTEXT pgddncContext = + (PGET_DEVICE_DRIVER_NAME_CONTEXT) CallbackContext; + + /* module found */ + if(pgddncContext->ImageBase == CurrentModule->BaseAddress) + { + register PCHAR pcModuleName; + register ULONG l; + + /* get the full name or just the filename part */ + if(pgddncContext->bFullName) + pcModuleName = &CurrentModule->Name[0]; + else + pcModuleName = &CurrentModule->Name[CurrentModule->PathLength]; + + /* get the length of the name */ + l = strlen(pcModuleName); + + /* if user buffer smaller than the name */ + if(pgddncContext->nSize <= l) + /* use the user buffer's length */ + l = pgddncContext->nSize; + /* if user buffer larger than the name */ + else + { + /* enough space for the null terminator */ + l ++; + pgddncContext->nSize = l; + } + + /* copy the string */ + if(pgddncContext->bUnicode) + { + /* Unicode: convert and copy */ + ANSI_STRING strAnsi = {l, l, pcModuleName}; + UNICODE_STRING wstrUnicode = + { + 0, + l * sizeof(WCHAR), + pgddncContext->lpUnicodeName + }; + /* driver names should always be in language-neutral ASCII, so we don't + bother calling AreFileApisANSI() */ + RtlAnsiStringToUnicodeString(&wstrUnicode, &strAnsi, FALSE); + } + else + /* ANSI/OEM: direct copy */ + memcpy(pgddncContext->lpAnsiName, pcModuleName, l); + + /* terminate the enumeration */ + return STATUS_NO_MORE_FILES; + } + /* continue searching */ + else + return STATUS_SUCCESS; +} + +/* common internal implementation */ +DWORD FASTCALL internalGetDeviceDriverName( + BOOLEAN bUnicode, + BOOLEAN bFullName, + LPVOID ImageBase, + LPVOID lpName, + DWORD nSize +) +{ + register NTSTATUS nErrCode; + GET_DEVICE_DRIVER_NAME_CONTEXT gddncContext = + { + ImageBase, + { bFullName, bUnicode }, + nSize, + { lpName } + }; + + /* empty buffer */ + if(lpName == NULL || nSize == 0) + return 0; + + /* invalid image base */ + if(ImageBase == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + + /* start the enumeration */ + nErrCode = PsaEnumerateSystemModules + ( + &GetDeviceDriverNameCallback, + &gddncContext + ); + + if(nErrCode == STATUS_NO_MORE_FILES) + /* module was found, return string size */ + return gddncContext.nSize; + else + { + if(NT_SUCCESS(nErrCode)) + /* module was not found */ + SetLastError(ERROR_INVALID_HANDLE); + else + /* an error occurred */ + SetLastError(RtlNtStatusToDosError(nErrCode)); + + /* failure */ + return 0; + } +} + +/* exported interfaces */ +/* + NOTES: + - nSize is not, as stated by Microsoft's documentation, the byte size, but the + count of characters in the buffer + - the return value is the count of characters copied into the buffer + - the functions don't attempt to null-terminate the string + */ +DWORD STDCALL GetDeviceDriverBaseNameA( + LPVOID ImageBase, + LPSTR lpBaseName, + DWORD nSize +) +{ + return internalGetDeviceDriverName(FALSE, FALSE, ImageBase, lpBaseName, nSize); +} + +DWORD STDCALL GetDeviceDriverFileNameA( + LPVOID ImageBase, + LPSTR lpFilename, + DWORD nSize +) +{ + return internalGetDeviceDriverName(FALSE, TRUE, ImageBase, lpFilename, nSize); +} + +DWORD STDCALL GetDeviceDriverBaseNameW( + LPVOID ImageBase, + LPWSTR lpBaseName, + DWORD nSize +) +{ + return internalGetDeviceDriverName(TRUE, FALSE, ImageBase, lpBaseName, nSize); +} + +DWORD STDCALL GetDeviceDriverFileNameW( + LPVOID ImageBase, + LPWSTR lpFilename, + DWORD nSize +) +{ + return internalGetDeviceDriverName(TRUE, TRUE, ImageBase, lpFilename, nSize); +} + +/* GetMappedFileName */ +/* common internal implementation */ +DWORD FASTCALL internalGetMappedFileName( + BOOLEAN bUnicode, + HANDLE hProcess, + LPVOID lpv, + LPVOID lpName, + DWORD nSize +) +{ + register NTSTATUS nErrCode; + register ULONG nBufSize; + PMEMORY_SECTION_NAME pmsnName; + + /* empty buffer */ + if(nSize == 0 || (LPSTR)lpName == NULL) + return 0; + + if(nSize > (0xFFFF / sizeof(WCHAR))) + /* if the user buffer contains more characters than would fit in an + UNICODE_STRING, limit the buffer size. RATIONALE: we don't limit buffer + size elsewhere because here superfluous buffer size will mean a larger + temporary buffer */ + nBufSize = 0xFFFF / sizeof(WCHAR); + else + nBufSize = nSize * sizeof(WCHAR); + + /* allocate the memory */ + pmsnName = malloc(nBufSize + offsetof(MEMORY_SECTION_NAME, NameBuffer)); + + if(pmsnName == NULL) + { + /* failure */ + SetLastError(ERROR_OUTOFMEMORY); + return 0; + } + + /* initialize the destination buffer */ + pmsnName->SectionFileName.Length = 0; + pmsnName->SectionFileName.Length = nBufSize; + +#if 0 + __try + { +#endif + /* query the name */ + nErrCode = NtQueryVirtualMemory + ( + hProcess, + lpv, + MemorySectionName, + pmsnName, + nBufSize, + NULL + ); + + if(!NT_SUCCESS(nErrCode)) + { + /* failure */ + SetLastError(RtlNtStatusToDosError(nErrCode)); +#if 0 +#else + /* free the buffer */ + free(pmsnName); +#endif + return 0; + } + + /* copy the name */ + if(bUnicode) + { + /* destination is an Unicode string: direct copy */ + memcpy + ( + (LPWSTR)lpName, + pmsnName->NameBuffer, + pmsnName->SectionFileName.Length + ); + +#if 0 +#else + /* free the buffer */ + free(pmsnName); +#endif + + if(pmsnName->SectionFileName.Length < nSize) + { + /* null-terminate the string */ + ((LPWSTR)lpName)[pmsnName->SectionFileName.Length] = 0; + return pmsnName->SectionFileName.Length + 1; + } + + return pmsnName->SectionFileName.Length; + } + else + { + ANSI_STRING strAnsi = {0, nSize, (LPSTR)lpName}; + + if(AreFileApisANSI()) + /* destination is an ANSI string: convert and copy */ + RtlUnicodeStringToAnsiString(&strAnsi, &pmsnName->SectionFileName, FALSE); + else + /* destination is an OEM string: convert and copy */ + RtlUnicodeStringToOemString(&strAnsi, &pmsnName->SectionFileName, FALSE); + +#if 0 +#else + /* free the buffer */ + free(pmsnName); +#endif + + if(strAnsi.Length < nSize) + { + /* null-terminate the string */ + ((LPSTR)lpName)[strAnsi.Length] = 0; + return strAnsi.Length + 1; + } + + return strAnsi.Length; + } + +#if 0 + } + __finally + { + free(pmsnName); + } +#endif +} + +/* exported interfaces */ +DWORD STDCALL GetMappedFileNameA( + HANDLE hProcess, + LPVOID lpv, + LPSTR lpFilename, + DWORD nSize +) +{ + return internalGetMappedFileName(FALSE, hProcess, lpv, lpFilename, nSize); +} + +DWORD STDCALL GetMappedFileNameW( + HANDLE hProcess, + LPVOID lpv, + LPWSTR lpFilename, + DWORD nSize +) +{ + return internalGetMappedFileName(TRUE, hProcess, lpv, lpFilename, nSize); +} + +/* GetModuleInformation */ +/* common callback context */ +typedef struct _GET_MODULE_INFORMATION_FLAGS +{ + ULONG bWantName:sizeof(ULONG) * 8 / 4; + ULONG bUnicode:sizeof(ULONG) * 8 / 4; + ULONG bFullName:sizeof(ULONG) * 8 / 4; +} GET_MODULE_INFORMATION_FLAGS, *PGET_MODULE_INFORMATION_FLAGS; + +typedef struct _GET_MODULE_INFORMATION_CONTEXT +{ + HMODULE hModule; + GET_MODULE_INFORMATION_FLAGS Flags; + DWORD nBufSize; + union + { + LPWSTR lpUnicodeName; + LPSTR lpAnsiName; + LPMODULEINFO lpmodinfo; + LPVOID lpBuffer; + }; +} GET_MODULE_INFORMATION_CONTEXT, *PGET_MODULE_INFORMATION_CONTEXT; + +/* common callback */ +NTSTATUS STDCALL GetModuleInformationCallback +( + IN HANDLE ProcessHandle, + IN PLDR_MODULE CurrentModule, + IN OUT PVOID CallbackContext +) +{ + register PGET_MODULE_INFORMATION_CONTEXT pgmicContext = + (PGET_MODULE_INFORMATION_CONTEXT)CallbackContext; + + /* found the module we were looking for */ + if(CurrentModule->BaseAddress == pgmicContext->hModule) + { + /* we want the module name */ + if(pgmicContext->Flags.bWantName) + { + register NTSTATUS nErrCode; + register PUNICODE_STRING pwstrSource; + register ULONG l; + + if(pgmicContext->Flags.bFullName) + /* full name */ + pwstrSource = &(CurrentModule->FullDllName); + else + /* base name only */ + pwstrSource = &(CurrentModule->BaseDllName); + + /* paranoia */ + pwstrSource->Length -= pwstrSource->Length % sizeof(WCHAR); + + /* l is the byte size of the user buffer */ + l = pgmicContext->nBufSize * sizeof(WCHAR); + + /* if the user buffer has room for the string and a null terminator */ + if(l >= (pwstrSource->Length + sizeof(WCHAR))) + { + /* limit the buffer size */ + l = pwstrSource->Length; + + /* null-terminate the string */ + if(pgmicContext->Flags.bUnicode) + pgmicContext->lpUnicodeName[l / sizeof(WCHAR)] = 0; + else + pgmicContext->lpAnsiName[l / sizeof(WCHAR)] = 0; + } + + if(pgmicContext->Flags.bUnicode) + { + /* Unicode: direct copy */ + /* NOTE: I've chosen not to check for ProcessHandle == NtCurrentProcess(), + this function is complicated enough as it is */ + nErrCode = NtReadVirtualMemory + ( + ProcessHandle, + pwstrSource->Buffer, + pgmicContext->lpUnicodeName, + l, + NULL + ); + + if(NT_SUCCESS(nErrCode)) + pgmicContext->nBufSize = l / sizeof(WCHAR); + else + { + pgmicContext->nBufSize = 0; + return nErrCode; + } + } + else + { + /* ANSI/OEM: convert and copy */ + register LPWSTR pwcUnicodeBuf; + ANSI_STRING strAnsi = {0, pgmicContext->nBufSize, pgmicContext->lpAnsiName}; + UNICODE_STRING wstrUnicodeBuf; + + /* allocate the local buffer */ + pwcUnicodeBuf = malloc(pwstrSource->Length); + +#if 0 + __try + { +#endif + if(pwcUnicodeBuf == NULL) + /* failure */ +#if 0 + return STATUS_NO_MEMORY; +#else + { + nErrCode = STATUS_NO_MEMORY; + goto exitWithStatus; + } +#endif + + /* copy the string in the local buffer */ + nErrCode = NtReadVirtualMemory + ( + ProcessHandle, + pwstrSource->Buffer, + pwcUnicodeBuf, + l, + NULL + ); + + if(!NT_SUCCESS(nErrCode)) + /* failure */ +#if 0 + return nErrCode; +#else + goto exitWithStatus; +#endif + + /* initialize Unicode string buffer */ + wstrUnicodeBuf.Length = wstrUnicodeBuf.MaximumLength = l; + wstrUnicodeBuf.Buffer = pwcUnicodeBuf; + + /* convert and copy */ + if(AreFileApisANSI()) + RtlUnicodeStringToAnsiString(&strAnsi, &wstrUnicodeBuf, FALSE); + else + RtlUnicodeStringToOemString(&strAnsi, &wstrUnicodeBuf, FALSE); + + /* return the string size */ + pgmicContext->nBufSize = strAnsi.Length; +#if 0 + } + __finally + { + /* free the buffer */ + free(pwcUnicodeBuf); + } +#else + /* success */ + nErrCode = STATUS_NO_MORE_FILES; + +exitWithStatus: + /* free the buffer */ + free(pwcUnicodeBuf); + return nErrCode; +#endif + } + + } + /* we want other module information */ + else + { + register ULONG nSize = pgmicContext->nBufSize; + + /* base address */ + if(nSize >= sizeof(CurrentModule->BaseAddress)) + { + pgmicContext->lpmodinfo->lpBaseOfDll = CurrentModule->BaseAddress; + nSize -= sizeof(CurrentModule->BaseAddress); + } + + /* image size */ + if(nSize >= sizeof(CurrentModule->SizeOfImage)) + { + pgmicContext->lpmodinfo->SizeOfImage = CurrentModule->SizeOfImage; + nSize -= sizeof(CurrentModule->SizeOfImage); + } + + /* entry point */ + if(nSize >= sizeof(CurrentModule->EntryPoint)) + /* ??? FIXME? is "EntryPoint" just the offset, or the real address? */ + pgmicContext->lpmodinfo->EntryPoint = (PVOID)CurrentModule->EntryPoint; + + pgmicContext->nBufSize = TRUE; + } + + return STATUS_NO_MORE_FILES; + } + + return STATUS_SUCCESS; +} + +/* common internal implementation */ +DWORD FASTCALL internalGetModuleInformation( + HANDLE hProcess, + HMODULE hModule, + GET_MODULE_INFORMATION_FLAGS Flags, + LPVOID lpBuffer, + DWORD nBufSize +) +{ + register NTSTATUS nErrCode; + GET_MODULE_INFORMATION_CONTEXT gmicContext = + { + hModule, + Flags, + nBufSize, + {lpBuffer} + }; + + + nErrCode = PsaEnumerateProcessModules + ( + hProcess, + &GetModuleInformationCallback, + &gmicContext + ); + + if(nErrCode == STATUS_NO_MORE_FILES) + return gmicContext.nBufSize; + else + { + if(NT_SUCCESS(nErrCode)) + SetLastError(ERROR_INVALID_HANDLE); + else + SetLastError(RtlNtStatusToDosError(nErrCode)); + + return 0; + } +} + +/* exported interfaces */ +DWORD STDCALL GetModuleBaseNameA( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPSTR lpBaseName, // base name buffer + DWORD nSize // maximum characters to retrieve +) +{ + register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, FALSE}; + return internalGetModuleInformation + ( + hProcess, + hModule, + Flags, + lpBaseName, + nSize + ); +} + +DWORD STDCALL GetModuleBaseNameW( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPWSTR lpBaseName, // base name buffer + DWORD nSize // maximum characters to retrieve +) +{ + register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, FALSE}; + return internalGetModuleInformation + ( + hProcess, + hModule, + Flags, + lpBaseName, + nSize + ); +} + +DWORD STDCALL GetModuleFileNameExA( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPSTR lpFilename, // path buffer + DWORD nSize // maximum characters to retrieve +) +{ + register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, FALSE, TRUE}; + return internalGetModuleInformation + ( + hProcess, + hModule, + Flags, + lpFilename, + nSize + ); +} + +DWORD STDCALL GetModuleFileNameExW( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPWSTR lpFilename, // path buffer + DWORD nSize // maximum characters to retrieve +) +{ + register GET_MODULE_INFORMATION_FLAGS Flags = {TRUE, TRUE, TRUE}; + return internalGetModuleInformation + ( + hProcess, + hModule, + Flags, + lpFilename, + nSize + ); +} + +BOOL STDCALL GetModuleInformation( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPMODULEINFO lpmodinfo, // information buffer + DWORD cb // size of buffer +) +{ + register GET_MODULE_INFORMATION_FLAGS Flags = {FALSE, FALSE, FALSE}; + return (BOOL)internalGetModuleInformation + ( + hProcess, + hModule, + Flags, + lpmodinfo, + cb + ); +} +/* EOF */ + diff --git a/lib/psapi/psapi.def b/lib/psapi/psapi.def new file mode 100644 index 0000000..bdf63eb --- /dev/null +++ b/lib/psapi/psapi.def @@ -0,0 +1,29 @@ +; $Id$ +; +; THIS SOFTWARE IS NOT COPYRIGHTED +; +; This source code is offered for use in the public domain. You may +; use, modify or distribute it freely. +; + +LIBRARY PSAPI.DLL +EXPORTS +EmptyWorkingSet @10 +EnumDeviceDrivers @2 +EnumProcessModules @3 +EnumProcesses @4 +GetDeviceDriverBaseNameA @5 +GetDeviceDriverBaseNameW @6 +GetDeviceDriverFileNameA @7 +GetDeviceDriverFileNameW @8 +GetMappedFileNameA @9 +GetMappedFileNameW @1 +GetModuleBaseNameA @11 +GetModuleBaseNameW @12 +GetModuleFileNameExA @13 +GetModuleFileNameExW @14 +GetModuleInformation @15 +GetProcessMemoryInfo @16 +GetWsChanges @17 +InitializeProcessForWsWatch @18 +QueryWorkingSet @19 diff --git a/lib/psapi/psapi.edf b/lib/psapi/psapi.edf new file mode 100644 index 0000000..94cf716 --- /dev/null +++ b/lib/psapi/psapi.edf @@ -0,0 +1,29 @@ +; $Id$ +; +; THIS SOFTWARE IS NOT COPYRIGHTED +; +; This source code is offered for use in the public domain. You may +; use, modify or distribute it freely. +; + +LIBRARY PSAPI.DLL +EXPORTS +EmptyWorkingSet=EmptyWorkingSet@4 @10 +EnumDeviceDrivers=EnumDeviceDrivers@12 @2 +EnumProcessModules=EnumProcessModules@16 @3 +EnumProcesses=EnumProcesses@12 @4 +GetDeviceDriverBaseNameA=GetDeviceDriverBaseNameA@12 @5 +GetDeviceDriverBaseNameW=GetDeviceDriverBaseNameW@12 @6 +GetDeviceDriverFileNameA=GetDeviceDriverFileNameA@12 @7 +GetDeviceDriverFileNameW=GetDeviceDriverFileNameW@12 @8 +GetMappedFileNameA=GetMappedFileNameA@16 @9 +GetMappedFileNameW=GetMappedFileNameW@16 @1 +GetModuleBaseNameA=GetModuleBaseNameA@16 @11 +GetModuleBaseNameW=GetModuleBaseNameW@16 @12 +GetModuleFileNameExA=GetModuleFileNameExA@16 @13 +GetModuleFileNameExW=GetModuleFileNameExW@16 @14 +GetModuleInformation=GetModuleInformation@16 @15 +GetProcessMemoryInfo=GetProcessMemoryInfo@12 @16 +GetWsChanges=GetWsChanges@12 @17 +InitializeProcessForWsWatch=InitializeProcessForWsWatch@4 @18 +QueryWorkingSet=QueryWorkingSet@12 @19 diff --git a/lib/psapi/psapi.rc b/lib/psapi/psapi.rc new file mode 100644 index 0000000..095c4f2 --- /dev/null +++ b/lib/psapi/psapi.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Process Status Helper\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "psapi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "psapi.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/rpcrt4/Makefile b/lib/rpcrt4/Makefile new file mode 100644 index 0000000..e4f6fa4 --- /dev/null +++ b/lib/rpcrt4/Makefile @@ -0,0 +1,137 @@ +# $Id$ +# +# ReactOS Operating System +# +PATH_TO_TOP = ../.. + +TARGET = midl rpcrt4 rpcss + +BASE_CFLAGS = -I../../include + +CFLAGS = $(CFLAGS) + +midl: + +DLLTARGET=$(TARGET).dll + + +all: $(DLLTARGET) + +SYNCH_OBJECTS = synch/critical.o synch/event.o synch/wait.o synch/intrlck.o synch/timer.o + +MISC_OBJECTS = misc/error.o misc/atom.o misc/handle.o misc/env.o misc/dllmain.o \ + misc/console.o misc/time.o misc/stubs.o misc/rtl.o misc/ldr.o misc/res.o + +FILE_OBJECTS = file/file.o file/curdir.o file/lfile.o file/dir.o \ + file/iocompl.o file/volume.o file/deviceio.o file/dosdev.o \ + file/create.o file/find.o file/copy.o file/pipe.o \ + file/move.o file/lock.o file/rw.o file/delete.o + +MEM_OBJECTS = mem/virtual.o mem/heap.o mem/utils.o mem/section.o mem/isbad.o mem/procmem.o + +NLS_OBJECTS = nls/codepage.o nls/cpmisc.o nls/cptable.o\ + nls/cp37.o nls/cp437.o nls/cp500.o nls/cp737.o nls/cp775.o nls/cp850.o nls/cp852.o nls/cp855.o nls/cp857.o\ + nls/cp860.o nls/cp861.o nls/cp863.o nls/cp865.o nls/cp866.o nls/cp869.o nls/cp875.o nls/cp1026.o\ + nls/cp1250.o nls/cp1251.o nls/cp1252.o nls/cp1253.o nls/cp1254.o nls/cp1255.o nls/cp1256.o nls/cp1257.o\ + nls/cp10000.o nls/cp10006.o nls/cp10007.o nls/cp10029.o nls/cp10079.o nls/cp10081.o\ + nls/lctable.o\ + nls/lcAFK.o nls/lcBEL.o nls/lcBGR.o nls/lcCAT.o nls/lcCSY.o nls/lcDAN.o\ + nls/lcDEA.o nls/lcDEC.o nls/lcDEL.o nls/lcDES.o nls/lcDEU.o\ + nls/lcELL.o\ + nls/lcENA.o nls/lcENB.o nls/lcENC.o nls/lcENG.o nls/lcENI.o nls/lcENJ.o nls/lcENL.o nls/lcENS.o nls/lcENT.o\ + nls/lcENU.o nls/lcENZ.o\ + nls/lcESA.o nls/lcESB.o nls/lcESC.o nls/lcESD.o nls/lcESE.o nls/lcESF.o nls/lcESG.o nls/lcESH.o nls/lcESI.o\ + nls/lcESL.o nls/lcESM.o nls/lcESN.o nls/lcESO.o nls/lcESP.o nls/lcESR.o nls/lcESS.o nls/lcESU.o nls/lcESV.o\ + nls/lcESY.o nls/lcESZ.o\ + nls/lcETI.o nls/lcEUQ.o nls/lcFIN.o nls/lcFOS.o\ + nls/lcFRA.o nls/lcFRB.o nls/lcFRC.o nls/lcFRL.o nls/lcFRS.o\ + nls/lcHRV.o nls/lcHUN.o nls/lcIND.o nls/lcISL.o nls/lcITA.o nls/lcITS.o nls/lcLTH.o nls/lcLVI.o nls/lcNLB.o\ + nls/lcNLD.o nls/lcNON.o nls/lcNOR.o nls/lcPLK.o nls/lcPTB.o nls/lcPTG.o nls/lcROM.o nls/lcRUS.o nls/lcSKY.o\ + nls/lcSLV.o nls/lcSQI.o nls/lcSRB.o nls/lcSRL.o nls/lcSVE.o nls/lcSVF.o nls/lcTRK.o nls/lcUKR.o\ + nls/locale.o nls/mbtowc.o nls/wctomb.o nls/ole2nls.o + +THREAD_OBJECTS = thread/thread.o thread/tls.o + +PROCESS_OBJECTS = process/proc.o process/cmdline.o process/create.o \ + process/lib.o + +STRING_OBJECTS = string/lstring.o + +INTERNAL_OBJECTS = internal/dprintf.o + +EXCEPT_OBJECTS = except/except.o + +RESOURCE_OBJECT = $(TARGET).coff + + +OBJECTS = $(MISC_OBJECTS) $(FILE_OBJECTS) $(THREAD_OBJECTS) \ + $(PROCESS_OBJECTS) $(STRING_OBJECTS) $(MEM_OBJECTS) \ + $(INTERNAL_OBJECTS) $(SYNCH_OBJECTS) $(EXCEPT_OBJECTS) \ + $(RESOURCE_OBJECT) + +CLEAN_FILES = except/*.o file/*.o internal/*.o mem/*.o misc/*.o nls/*.o \ + process/*.o string/*.o synch/*.o thread/*.o \ + $(TARGET).o $(TARGET).a junk.tmp base.tmp temp.exp \ + $(TARGET).dll $(TARGET).sym $(TARGET).coff + +nls/ole2nls.o: nls/ole2nls.c + $(CC) $(CFLAGS) -I. nls/ole2nls.c + +$(TARGET).coff: $(TARGET).rc ../../include/reactos/resource.h + +$(TARGET).a: $(OBJECTS) + $(AR) csr $(TARGET).a $(OBJECTS) + +$(TARGET).dll: $(DLLMAIN) $(OBJECTS) $(TARGET).def + $(LD) \ + -r $(OBJECTS) \ + -o $(TARGET).o + $(DLLTOOL) \ + --dllname $(TARGET).dll \ + --def $(TARGET).def \ + --kill-at \ + --output-lib $(TARGET).a + $(CC) \ + -specs=k32_specs \ + -mdll \ + -o junk.tmp \ + -Wl,--base-file,base.tmp \ + $(TARGET).o \ + ../ntdll/ntdll.a + - $(RM) junk.tmp + $(DLLTOOL) \ + --dllname $(TARGET).dll \ + --base-file base.tmp \ + --output-exp temp.exp \ + --def $(TARGET).edf + - $(RM) base.tmp + $(CC) \ + -specs=k32_specs \ + -mdll \ + -o $(TARGET).dll \ + $(TARGET).o \ + ../ntdll/ntdll.a \ + -Wl,--image-base,$(KERNEL32_BASE) \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,temp.exp + - $(RM) temp.exp + $(NM) --numeric-sort $(TARGET).dll > $(TARGET).sym + +clean: + - $(RM) $(CLEAN_FILES) + +.PHONY: clean + +install: $(FLOPPY_DIR)/dlls/$(TARGET).dll + +$(FLOPPY_DIR)/dlls/$(TARGET).dll: $(TARGET).dll + $(CP) $(TARGET).dll $(FLOPPY_DIR)/dlls/$(TARGET).dll + +dist: $(DIST_DIR)/dlls/$(TARGET).dll + +$(DIST_DIR)/dlls/$(TARGET).dll: $(TARGET).dll + $(CP) $(TARGET).dll ../../$(DIST_DIR)/dlls/$(TARGET).dll + +WARNINGS_ARE_ERRORS = yes +include ../../rules.mak diff --git a/lib/rpcrt4/include/rpc.h b/lib/rpcrt4/include/rpc.h new file mode 100644 index 0000000..7a59927 --- /dev/null +++ b/lib/rpcrt4/include/rpc.h @@ -0,0 +1,117 @@ +/* + * + */ + +#ifndef __LIB_RPCRT4_INCLUDE_RPC_H +#define __LIB_RPCRT4_INCLUDE_RPC_H + +#define RPC_MGR_EPV VOID +typedef RPC_BINDING_HANDLE handle_t + +/* + * RPC packet types + */ +#define RPC_REQUEST (0x0) +#define RPC_PING (0x1) +#define RPC_RESPONSE (0x2) +#define RPC_FAULT (0x3) +#define RPC_WORKING (0x4) +#define RPC_NOCALL (0x5) +#define RPC_REJECT (0x6) +#define RPC_ACK (0x7) +#define RPC_CL_CANCEL (0x8) +#define RPC_FACK (0x9) +#define RPC_CANCEL_ACK (0xa) +#define RPC_BIND (0xb) +#define RPC_BINDACK (0xc) +#define RPC_BINDNACK (0xd) +#define RPC_ALTCONT (0xe) +#define RPC_AUTH3 (0xf) +#define RPC_BINDCONT (0x10) +#define RPC_SHUTDOWN (0x10) +#define RPC_CO_CANCEL (0x11) +#define RPC_ORPHANED (0x12) + +/* + * Common RPC packet header + */ +typedef struct _RPC_HEADER_PACKET +{ + UCHAR MajorVersion; + UCHAR MinorVersion; + UCHAR PacketType; + UCHAR Flags; + ULONG DataRep; + USHORT FragLen; + USHORT AuthLen; + ULONG CallId; +} RPC_HEADER_PACKET, *PRPC_HEADER_PACKET; + +/* + * Additional header for a RPC request packet + */ +typedef struct _RPC_REQUEST_PACKET +{ + ULONG AllocHint; + USHORT ContextId; + USHORT Opcode; +} RPC_REQUEST_PACKET, *PRPC_REQUEST_PACKET; + +typedef struct _RPC_RESPONSE_PACKET +{ + ULONG AllocHint; + USHORT ContextId; + UCHAR CancelCount; + UCHAR Reserved; +} RPC_RESPONSE_PACKET, *PRPC_RESPONSE_PACKET; + +typedef struct _RPC_VERSION +{ + USHORT MajorVersion; + USHORT MinorVersion; +} RPC_VERSION, *PRPC_VERSION; + +typedef struct _RPC_SYNTAX_IDENTIFIER +{ + GUID SyntaxGuid; + RPC_VERSION SyntaxVersion; +} RPC_SYNTAX_IDENTIFIER, *PRPC_SYNTAX_IDENTIFIER; + +typedef struct _RPC_MESSAGE +{ + RPC_BINDING_HANDLE Handle; + ULONG DataRepresentation; + VOID* Buffer; + USHORT BufferLength; + USHORT ProcNum; + PRPC_SYNTAX_IDENTIFIER TransferSyntax; + VOID* RpcInterfaceInformation; + VOID* ReservedForRuntime; + RPC_MGR_EPV* ManagerEpv; + VOID* ImportContext; + ULONG RpcFlags; +} RPC_MESSAGE, *PRPC_MESSAGE; + +typedef VOID (*RPC_DISPATCH_FUNCTION)(PRPC_MESSAGE Message); + +typedef struct _RPC_DISPATCH_TABLE +{ + ULONG DispatchTableCount; + RPC_DISPATCH_FUNCTION* DispatchTable; + LONG Reserved; +} RPC_DISPATCH_TABLE, *PRPC_DISPATCH_TABLE; + +typedef struct _RPC_SERVER_INTERFACE +{ + ULONG Length; + RPC_SYNTAX_IDENTIFIER InterfaceId; + RPC_SYNTAX_IDENTIFIER TransferSyntax; + PRPC_DISPATCH_TABLE DispatchTable; + ULONG RpcProtseqEndpointCount; + PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint; + RPC_MGR_EPV* DefaultManagerEpv; + VOID CONST* InterpreterInfo; + ULONG Flags; +} RPC_SERVER_INTERFACE, *PRPC_SERVER_INTERFACE; + +#endif /* __LIB_RPCRT4_INCLUDE_RPC_H */ diff --git a/lib/rpcrt4/include/rpcrt4/rpc.h b/lib/rpcrt4/include/rpcrt4/rpc.h new file mode 100644 index 0000000..a7ce55e --- /dev/null +++ b/lib/rpcrt4/include/rpcrt4/rpc.h @@ -0,0 +1,43 @@ +#ifndef __INCLUDE_RPCRT4_RPC_H +#define __INCLUDE_RPCRT4_RPC_H + +typedef void* RPC_BINDING_HANDLE; +typedef long RPC_STATUS; + +typedef ULONG RPC_PROTOCOL_ID; +typedef ULONG RPC_PROTSEQ_ID; + +typedef struct +{ + RPC_PROTSEQ_ID ProtseqId; + ULONG Len; + sockaddr_t sa; +} *PRPC_ADDR; + +typedef struct _RPC_PROTOCOL_VERSION +{ + ULONG MajorVersion; + ULONG MinorVersion; +} RPC_PROTOCOL_VERSION, *PRPC_PROTOCOL_VERSION; + +typedef struct _RPC_BINDING_REP +{ + LIST_ENTRY ListEntry; + RPC_PROTOCOL_ID ProtocolId; + LONG ReferenceCount; + UUID ObjectId; + PRPC_ADDR RpcAddr; + BOOLEAN IsServer; + BOOLEAN AddrIsDynamic; + PVOID AuthInfo; + ULONG ExtendedBindFlag; + ULONG BoundServerInstance; + ULONG AddrHasEndpoint; + LONG CallsInProgress; + PVOID NsSpecific; + PRPC_PROTOCOL_VERSION ProtocolVersion; +} RPC_BINDING_REP, *PRPC_BINDING_REP; + + + +#endif /* __INCLUDE_RPCRT4_RPC_H */ diff --git a/lib/rpcrt4/midl/Makefile b/lib/rpcrt4/midl/Makefile new file mode 100644 index 0000000..f2cb30b --- /dev/null +++ b/lib/rpcrt4/midl/Makefile @@ -0,0 +1,51 @@ +# $Id$ +# +# ReactOS Operating System +# +TARGET=midl + +CFLAGS = + +all: midl$(EXE_POSTFIX) + +idl.tab.o: idl.y + bison -t -v -d idl.y + $(NATIVE_CC) -c idl.tab.c -o idl.tab.o + +lex.yy.o: idl.l idl.tab.h + flex idl.l + $(NATIVE_CC) -c lex.yy.c -o lex.yy.o + +midl.o: midl.c midl.h idl.tab.h + $(NATIVE_CC) -c midl.c -o midl.o + +option.o: option.c midl.h idl.tab.h + $(NATIVE_CC) -c option.c -o option.o + +interface.o: interface.c midl.h idl.tab.h + $(NATIVE_CC) -c interface.c -o interface.o + +types.o: types.c midl.h idl.tab.h types.h + $(NATIVE_CC) -c types.c -o types.o + +midl$(EXE_POSTFIX): idl.tab.o lex.yy.o midl.o option.o interface.o types.o + $(NATIVE_CC) midl.o idl.tab.o lex.yy.o option.o interface.o -lfl \ + types.o -o midl$(EXE_POSTFIX) + +include ../../../rules.mak + + + + + + + + + + + + + + + + diff --git a/lib/rpcrt4/midl/hello.idl b/lib/rpcrt4/midl/hello.idl new file mode 100644 index 0000000..cffab05 --- /dev/null +++ b/lib/rpcrt4/midl/hello.idl @@ -0,0 +1,34 @@ +[ +uuid(b574a080-aceb-11d3-95f9-aa43ded19f71), +version(1.0), +pointer_default(unique) +] +interface hello +{ + struct _hello_struct + { + int hello_member; + int hello1_member; + float hello3_member; + }; + + typedef struct _hello2_struct + { + int hello2_member; + } __hello2_struct; + + typedef struct + { + int hello3_member; + } hello3_typedef; + + typedef int hello_t; + + void Hello4Proc([in] hello3_typedef ii); + void Hello3Proc([in] __hello2_struct h); + void Hello2Proc([in] struct _hello_struct h); + void HelloProc([in] hello_t pszString); + void Shutdown(void); + void RpcBenchmark(handle_t Server, + [out, size_is(32768)] unsigned char* pcOutBuffer); +} diff --git a/lib/rpcrt4/midl/idl.l b/lib/rpcrt4/midl/idl.l new file mode 100644 index 0000000..8e1e3cd --- /dev/null +++ b/lib/rpcrt4/midl/idl.l @@ -0,0 +1,114 @@ +%{ +#include "midl.h" +#include "idl.tab.h" +#include + +int lineno = 1; +void yyerror(char* s); +char* current_file; +int nr_errors = 0; + +#define TOK(n) { yylval.token = n; return n; } + +%} + +DIGIT [0-9] +ID [a-zA-Z_][a-zA-Z0-9_]* +UUID [a-z0-9]* + +%% + +uuid { TOK(UUID_KEYWORD); } +version { TOK(VERSION_KEYWORD); } +pointer_default { TOK(POINTER_DEFAULT_KEYWORD); } +unique { TOK(UNIQUE_KEYWORD); } +interface { TOK(INTERFACE_KEYWORD); } +aggregatable { TOK(AGGREGATABLE_KEYWORD); } +allocate { TOK(ALLOCATE_KEYWORD); } +appobject { TOK(APPOBJECT_KEYWORD); } + + +all_nodes { TOK(ALL_NODES_KEYWORD); } +single_node { TOK(SINGLE_NODE_KEYWORD); } +free { TOK(FREE_KEYWORD); } +dont_free { TOK(DONT_FREE_KEYWORD); } + +typedef { TOK(TYPEDEF_KEYWORD); } +struct { TOK(STRUCT_KEYWORD); } +const { TOK(CONST_KEYWORD); } + +signed { TOK(SIGNED_KEYWORD); } +unsigned { TOK(UNSIGNED_KEYWORD); } + +in { TOK(IN_KEYWORD); } +out { TOK(OUT_KEYWORD); } +string { TOK(STRING_KEYWORD); } +implicit_handle { TOK(IMPLICIT_HANDLE_KEYWORD); } +auto_handle { TOK(AUTO_HANDLE_KEYWORD); } +size_is { TOK(SIZE_IS_KEYWORD); } +length_is { TOK(LENGTH_IS_KEYWORD); } + +{ID} { int n; + if ((n = token_to_type(yytext)) != 0) + { + yylval.tval = n; + return(TYPE_KEYWORD); + } + else + { + yylval.id = strdup(yytext); + return(ID_TOKEN); + } + } + +{DIGIT}+ { yylval.number = atoi(yytext); + return(NUMBER_TOKEN); } + +{DIGIT}+"."{DIGIT}+ { char* ebuf; + yylval.version.major = strtoul(yytext, &ebuf, 0); + yylval.version.minor = strtoul(ebuf + 1, NULL, 0); + return(VERSION_TOKEN); } + +{UUID}+"-"{UUID}+"-"{UUID}+"-"{UUID}+"-"{UUID}+ { yylval.uuid = strdup(yytext); + return(UUID_TOKEN); } + +";" { TOK(LINE_TERMINATOR); } + +"(" { TOK(LEFT_BRACKET); } + +")" { TOK(RIGHT_BRACKET); } + +"," { TOK(COMMA); } + +"{" { TOK(LCURLY_BRACKET); } + +"}" { TOK(RCURLY_BRACKET); } + +"[" { TOK(LSQBRACKET); } + +"]" { TOK(RSQBRACKET); } + +"*" { TOK(STAR); } + +"=" { TOK(ASSIGNMENT); } + +\n lineno++; + +[ \t\r]+ ; + +. yyerror("invalid character"); + +%% + +void yyerror(char* s) +{ + nr_errors++; + printf("%s:%d: %s at %s\n", current_file, lineno, s, yytext); +} + +void yyerror1(char* s) +{ + nr_errors++; + printf("%s:%d: %s\n", current_file, lineno, s); +} + diff --git a/lib/rpcrt4/midl/idl.y b/lib/rpcrt4/midl/idl.y new file mode 100644 index 0000000..e6b929e --- /dev/null +++ b/lib/rpcrt4/midl/idl.y @@ -0,0 +1,201 @@ +%{ +#include "midl.h" +%} + +%union { +int tval; +int token; +char* id; +int number; +char* uuid; +char operator; +char* string; +struct +{ +int minor; +int major; +} version; +} + +%token ID_LITERAL +%token UUID_LITERAL +%token NUMBER_LITERAL +%token VERSION_LITERAL +%token STRING_LITERAL + +%token ENDPOINT_KEYWORD +%token EXCEPTIONS_KEYWORD +%token LOCAL_KEYWORD +%token IMPORT_KEYWORD + +%token UUID_KEYWORD +%token VERSION_KEYWORD +%token POINTER_DEFAULT_KEYWORD +%token UNIQUE_KEYWORD +%token INTERFACE_KEYWORD +%token IMPLICIT_HANDLE_KEYWORD +%token AUTO_HANDLE_KEYWORD +%token AGGREGATABLE_KEYWORD +%token ALLOCATE_KEYWORD +%token APPOBJECT_KEYWORD + +%token ALL_NODES_KEYWORD +%token SINGLE_NODE_KEYWORD +%token FREE_KEYWORD +%token DONT_FREE_KEYWORD + +%token TYPEDEF_KEYWORD +%token STRUCT_KEYWORD +%token CONST_KEYWORD + +%token IN_KEYWORD +%token OUT_KEYWORD +%token STRING_KEYWORD +%token SIZE_IS_KEYWORD +%token LENGTH_IS_KEYWORD + +%token UNSIGNED_KEYWORD +%token SIGNED_KEYWORD + +%token LSQBRACKET, RSQBRACKET, LBRACKET, RBRACKET +%token LCURLY_BRACKET, RCURLY_BRACKET, LINE_TERMINATOR, COMMA +%token LEFT_BRACKET, RIGHT_BRACKET +%token STAR +%token ASSIGNMENT + +%token TYPE_KEYWORD + +%type type +%type sign +%type struct_def + +%% + +idl_file: + LSQBRACKET options RSQBRACKET interface + ; + +options: + option + | option COMMA options + ; + +option: + UUID_KEYWORD LEFT_BRACKET UUID_TOKEN RIGHT_BRACKET + { set_uuid($3); } + | VERSION_KEYWORD LEFT_BRACKET VERSION_TOKEN RIGHT_BRACKET + { set_version($3.major, $3.minor); } + | ENDPOINT_KEYWORD LEFT_BRACKET port_specs RIGHT_BRACKET + | EXCEPTIONS_KEYWORD LEFT_BRACKET excep_names RIGHT_BRACKET + | LOCAL_KEYWORD + | POINTER_DEFAULT_KEYWORD LEFT_BRACKET UNIQUE_KEYWORD RIGHT_BRACKET + { set_pointer_default($3); } + ; + +port_specs: + | STRING_TOKEN COMMA port_specs + ; + +excep_names: ID_TOKEN { } + | ID_TOKEN COMMA excep_names { } + ; + +interface: { start_interface(); } + INTERFACE_KEYWORD ID_TOKEN LCURLY_BRACKET interface_components + RCURLY_BRACKET + { end_interface($3); } + +interface_components: + | interface_component LINE_TERMINATOR interface_components + +interface_component: + | IMPORT_KEYWORD import_list + | function + | TYPEDEF_KEYWORD typedef + | CONST_KEYWORD type ID_TOKEN ASSIGNMENT const_expr + | STRUCT_KEYWORD struct_def RCURLY_BRACKET + ; + +import_list: STRING_TOKEN + | STRING_TOKEN COMMA import_list + ; + +const_expr: NUMBER_TOKEN + | STRING_TOKEN + ; + + + +typedef: type ID_TOKEN { add_typedef($2, $1); }; + +function: { start_function(); } + type ID_TOKEN LEFT_BRACKET argument_list RIGHT_BRACKET + { end_function($2, $3); } + ; + +argument_list: + | TYPE_KEYWORD { if ($1 != VOID_TYPE) + { + yyerror("parameter name ommitted"); + } + } + | argument + | argument COMMA argument_list + ; + +argument: arg_attrs type ID_TOKEN { add_argument($2, $3); } + | type ID_TOKEN { add_argument($1, $2); } + ; + +type: sign TYPE_KEYWORD STAR { $$ = $2 | POINTER_TYPE_OPTION | $1; } + | sign TYPE_KEYWORD { $$ = $2 | $1; } + | TYPE_KEYWORD { $$ = $1; } + | TYPE_KEYWORD STAR { $$ = $1 | POINTER_TYPE_OPTION; } + | STRUCT_KEYWORD struct_def RCURLY_BRACKET { $$ = $2; } + | STRUCT_KEYWORD ID_TOKEN { $$ = struct_to_type($2); } + ; + +struct_def: ID_TOKEN { start_struct($1); } LCURLY_BRACKET + struct_members { $$ = end_struct(); } + | { start_struct(NULL); } LCURLY_BRACKET + struct_members { $$ = end_struct(); } + ; + +struct_members: + | type ID_TOKEN LINE_TERMINATOR struct_members + { add_struct_member($2, $1); } + ; + +/* + * Rules for the optional sign for an integer type + */ +sign: UNSIGNED_KEYWORD { $$ = UNSIGNED_TYPE_OPTION; } + | SIGNED_KEYWORD { $$ = SIGNED_TYPE_OPTION; } + ; + +arg_attrs: LSQBRACKET arg_attr_list RSQBRACKET + ; + +/* + * Rules for the list of attributes for arguments + */ +arg_attr_list: arg_attr + | arg_attr COMMA arg_attr_list + ; + +/* + * Rules for the various attributes for arguments + */ +arg_attr: IN_KEYWORD + | OUT_KEYWORD + | STRING_KEYWORD + | LENGTH_IS_KEYWORD BRACKETED_QUANTITY + | SIZE_IS_KEYWORD BRACKETED_QUANTITY + ; + +/* + * + */ +BRACKETED_QUANTITY: LEFT_BRACKET NUMBER_TOKEN RIGHT_BRACKET + | LEFT_BRACKET ID_TOKEN RIGHT_BRACKET + ; diff --git a/lib/rpcrt4/midl/interface.c b/lib/rpcrt4/midl/interface.c new file mode 100644 index 0000000..21eee45 --- /dev/null +++ b/lib/rpcrt4/midl/interface.c @@ -0,0 +1,74 @@ +#include +#include +#include + +#include "midl.h" +#include "idl.tab.h" + +static interface* current_interface; +static function* current_function; + +void add_argument(int type, char* name) +{ + argument* arg; + + arg = malloc(sizeof(argument)); + + arg->type = type; + arg->name = strdup(name); + + arg->next = current_function->arguments; + current_function->arguments = arg; +} + +void start_interface(void) +{ + current_interface = (interface *)malloc(sizeof(interface)); +} + +void start_function(void) +{ + function* f; + + f = (function *)malloc(sizeof(function)); + + f->arguments = NULL; + + f->next = current_interface->function_list; + current_interface->function_list = f; + current_function = f; +} + +void end_function(int rtype, char* name) +{ + current_function->return_type = rtype; + current_function->name = strdup(name); +} + +void end_interface(char* name) +{ + function* cur; + argument* a; + + printf("interface_name: %s\n", name); + + current_interface->name = strdup(name); + cur = current_interface->function_list; + while (cur != NULL) + { + print_type(cur->return_type); + printf(" function_name: %s (\n", cur->name, cur); + + a = cur->arguments; + while (a != NULL) + { + printf("\t"); + print_type(a->type); + printf(" %s\n", a->name); + a = a->next; + } + printf(")\n"); + + cur = cur->next; + } +} diff --git a/lib/rpcrt4/midl/midl.c b/lib/rpcrt4/midl/midl.c new file mode 100644 index 0000000..d105bc4 --- /dev/null +++ b/lib/rpcrt4/midl/midl.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include + +extern FILE* yyin; +extern int yyparse(void); +extern int yydebug; +extern int nr_errors; +extern char* current_file; + +int main(int argc, char* argv[]) +{ + int fd; + char* tempname; + int n, p, status; + char* args[9]; + + if (argc == 1) + { + printf("Not enough arguments\n"); + exit(1); + } + + tempname = tempnam(NULL, "midl"); + + args[0] = strdup("/usr/bin/gcc"); + args[1] = strdup("-x"); + args[2] = strdup("c"); + args[3] = strdup("-P"); + args[4] = strdup("-E"); + args[5] = strdup(argv[1]); + args[6] = strdup("-o"); + args[7] = strdup(tempname); + args[8] = NULL; + + if ((n = fork()) == 0) + { + execv("/usr/bin/gcc", args); + perror("gcc"); + exit(1); + } + else if (n == -1) + { + perror("midl"); + exit(1); + } + + p = waitpid(n, &status, WUNTRACED); + if (p == -1 || p == 0 || !WIFEXITED(status)) + { + perror("midl"); + exit(1); + } + if (WEXITSTATUS(status) != 0) + { + printf("midl: the preprocessor %s failed\n"); + exit(1); + } + +// yydebug = 1; + + yyin = fopen(tempname, "r+b"); + if (yyin == NULL) + { + perror(argv[1]); + exit(1); + } + + current_file = strdup(argv[1]); + + if (yyparse() != 0 || nr_errors > 0) + { + exit(1); + } + + unlink(tempname); +} diff --git a/lib/rpcrt4/midl/midl.h b/lib/rpcrt4/midl/midl.h new file mode 100644 index 0000000..582a771 --- /dev/null +++ b/lib/rpcrt4/midl/midl.h @@ -0,0 +1,37 @@ +#ifndef __MIDL_H +#define __MIDL_H + +#include "types.h" + +typedef struct _argument +{ + int type; + char* name; + struct _argument* next; +} argument; + +typedef struct _function +{ + int return_type; + char* name; + argument* arguments; + struct _function* next; +} function; + +typedef struct +{ + char* name; + function* function_list; +} interface; + +void set_uuid(char* uuid); +void set_version(int major, int minor); +void set_pointer_default(int option); + +void start_interface(void); +void end_interface(char* name); +void start_function(void); +void end_function(int rtype, char* name); +void add_argument(int type, char* name); + +#endif __MIDL_H diff --git a/lib/rpcrt4/midl/option.c b/lib/rpcrt4/midl/option.c new file mode 100644 index 0000000..a2427cb --- /dev/null +++ b/lib/rpcrt4/midl/option.c @@ -0,0 +1,16 @@ +#include + +#include "midl.h" +#include "idl.tab.h" + +void set_uuid(char* uuid) +{ +} + +void set_version(int major, int minor) +{ +} + +void set_pointer_default(int option) +{ +} diff --git a/lib/rpcrt4/midl/types.c b/lib/rpcrt4/midl/types.c new file mode 100644 index 0000000..f45e328 --- /dev/null +++ b/lib/rpcrt4/midl/types.c @@ -0,0 +1,190 @@ +#include +#include +#include + +#include "midl.h" + +struct _type; + +typedef struct _struct_member +{ + char* name; + unsigned int value; + struct _struct_member* next; +} struct_member; + +typedef struct +{ + struct_member* member_list; + char* tag; + struct _type* type_value; +} struct_type; + +typedef struct _type +{ + char* name; + unsigned int value; + unsigned int default_sign; + struct_type* struct_desc; +} type; + +static struct_type struct_types[255]; + +static int next_struct_slot_free = 0; +static struct_type* current_struct; + +static type types[255] = { + {NULL, 0, 0}, + {"boolean", BOOLEAN_TYPE, UNSIGNED_TYPE_OPTION}, + {"byte", BYTE_TYPE, 0}, + {"char", CHAR_TYPE, UNSIGNED_TYPE_OPTION}, + {"double", DOUBLE_TYPE, 0}, + {"enum", ENUM_TYPE, 0}, + {"error_status_t", ERROR_STATUS_TYPE, UNSIGNED_TYPE_OPTION}, + {"float", FLOAT_TYPE, 0}, + {"handle_t", HANDLE_TYPE, 0}, + {"hyper", HYPER_TYPE, SIGNED_TYPE_OPTION}, + {"int", INT_TYPE, SIGNED_TYPE_OPTION}, + {"__int32", INT32_TYPE, SIGNED_TYPE_OPTION}, + {"__int3264", INT32OR64_TYPE, SIGNED_TYPE_OPTION}, + {"__int64", INT64_TYPE, SIGNED_TYPE_OPTION}, + {"long", LONG_TYPE, SIGNED_TYPE_OPTION}, + {"short", SHORT_TYPE, SIGNED_TYPE_OPTION}, + {"small", SMALL_TYPE, SIGNED_TYPE_OPTION}, + {"void", VOID_TYPE, 0}, + {"wchar_t", WCHAR_TYPE, UNSIGNED_TYPE_OPTION}, + {NULL, 0, 0} + }; + +static int next_free_slot = 18; + +unsigned int struct_to_type(char* tag) +{ + int i; + + for (i = 0; i < next_struct_slot_free; i++) + { + if (strcmp(tag, struct_types[i].tag) == 0) + { + return(struct_types[i].type_value->value); + } + } + return(0); +} + +void start_struct(char* tag) +{ + char* name; + + if (tag == NULL) + { + tag = malloc(255); + sprintf(tag, "__unnamed_struct%d", next_struct_slot_free); + } + + name = malloc(strlen("struct ") + strlen(tag) + 1); + strcpy(name, "struct "); + strcat(name, tag); + + struct_types[next_struct_slot_free].tag = strdup(tag); + struct_types[next_struct_slot_free].member_list = NULL; + current_struct = &struct_types[next_struct_slot_free]; + + types[next_free_slot].name = name; + types[next_free_slot].value = next_free_slot << 8; + types[next_free_slot].default_sign = 0; + types[next_free_slot].struct_desc = + &struct_types[next_struct_slot_free]; + + struct_types[next_struct_slot_free].type_value = &types[next_free_slot]; + + next_struct_slot_free++; + next_free_slot++; +} + +void add_struct_member(char* name, unsigned int type) +{ + struct_member* member; + + member = malloc(sizeof(struct_member)); + + member->name = strdup(name); + member->value = type; + member->next = current_struct->member_list; + current_struct->member_list = member; +} + +unsigned int end_struct(void) +{ + int n; + struct_member* cur; + + printf("Defining struct %s {\n", current_struct->tag); + + cur = current_struct->member_list; + while (cur != NULL) + { + print_type(cur->value); + printf(" %s\n", cur->name); + + cur = cur->next; + } + printf("}\n"); + + n = current_struct->type_value->value; + current_struct = NULL; + return(n); +} + +void add_typedef(char* name, int type) +{ + printf("Adding typedef %s to ", name); + print_type(type); + printf("\n"); + + types[next_free_slot].name = strdup(name); + types[next_free_slot].value = type; + types[next_free_slot].default_sign = 0; + next_free_slot++; +} + +void print_type(int tval) +{ + int i; + + for (i = 1; i < next_free_slot; i++) + { + if ((tval & BASE_TYPE_MASK) == types[i].value) + { + if (tval & UNSIGNED_TYPE_OPTION) + { + printf("unsigned "); + } + if (tval & SIGNED_TYPE_OPTION) + { + printf("signed "); + } + printf("%s", types[i].name); + if (tval & POINTER_TYPE_OPTION) + { + printf("*"); + } + return; + } + } + printf("unknown type"); +} + +int token_to_type(char* token) +{ + int i; + + for (i = 1; i < next_free_slot; i++) + { + if (strcmp(types[i].name, token) == 0) + { + return(types[i].value); + } + } + return(0); +} diff --git a/lib/rpcrt4/midl/types.h b/lib/rpcrt4/midl/types.h new file mode 100644 index 0000000..b556358 --- /dev/null +++ b/lib/rpcrt4/midl/types.h @@ -0,0 +1,42 @@ +#ifndef __TYPES_H +#define __TYPES_H + +#define BASE_TYPE_MASK (~0xff) + +#define BOOLEAN_TYPE (0x100) +#define BYTE_TYPE (0x200) +#define CHAR_TYPE (0x300) +#define DOUBLE_TYPE (0x400) +#define ERROR_STATUS_TYPE (0x500) +#define FLOAT_TYPE (0x600) +#define HANDLE_TYPE (0x700) +#define HYPER_TYPE (0x800) +#define INT_TYPE (0x900) +#define INT32_TYPE (0xA00) +#define INT32OR64_TYPE (0xB00) +#define INT64_TYPE (0xC00) +#define LONG_TYPE (0xD00) +#define SHORT_TYPE (0xE00) +#define SMALL_TYPE (0xF00) +#define VOID_TYPE (0x1000) +#define WCHAR_TYPE (0x1100) + +#define UNSIGNED_TYPE_OPTION (0x1) +#define SIGNED_TYPE_OPTION (0x2) +#define POINTER_TYPE_OPTION (0x4) + +#define IN_TYPE_OPTION (0x8) +#define OUT_TYPE_OPTION (0x10) +#define STRING_TYPE_OPTION (0x20) + +int token_to_type(char* token); +void print_type(int tval); +void add_typedef(char* name, int type); + +void start_struct(char* tag); +void add_struct_member(char* name, unsigned int type); +unsigned int end_struct(void); + +unsigned int struct_to_type(char* tag); + +#endif diff --git a/lib/secur32/.cvsignore b/lib/secur32/.cvsignore new file mode 100644 index 0000000..5cd856a --- /dev/null +++ b/lib/secur32/.cvsignore @@ -0,0 +1,3 @@ +secur32.dll +secur32.nostrip.dll +secur32.coff diff --git a/lib/secur32/Makefile b/lib/secur32/Makefile new file mode 100644 index 0000000..b7ae93d --- /dev/null +++ b/lib/secur32/Makefile @@ -0,0 +1,22 @@ +# $Id$ + + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = secur32 + +TARGET_BASE = 0x10000000 + +TARGET_SDKLIBS = ntdll.a + +TARGET_CFLAGS = -I./include -D__SECUR32__ + +TARGET_OBJECTS = lsa.o dllmain.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/lib/secur32/dllmain.c b/lib/secur32/dllmain.c new file mode 100644 index 0000000..b52cd67 --- /dev/null +++ b/lib/secur32/dllmain.c @@ -0,0 +1,42 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/secur32/lsa.c + * PURPOSE: Client-side LSA functions + * UPDATE HISTORY: + * Created 05/08/00 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +/* GLOBALS *******************************************************************/ + +HANDLE Secur32Heap; + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL DllMain(HINSTANCE hInstance, ULONG Reason, PVOID Reserved) +{ + switch (Reason) + { + case DLL_PROCESS_ATTACH: + Secur32Heap = RtlCreateHeap(0, NULL, 4096, 0, NULL, NULL); + if (Secur32Heap == 0) + { + return(FALSE); + } + break; + + case DLL_PROCESS_DETACH: + if (!RtlDestroyHeap(Secur32Heap)) + { + return(FALSE); + } + break; + } + return(TRUE); +} diff --git a/lib/secur32/lsa.c b/lib/secur32/lsa.c new file mode 100644 index 0000000..470f2de --- /dev/null +++ b/lib/secur32/lsa.c @@ -0,0 +1,309 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/secur32/lsa.c + * PURPOSE: Client-side LSA functions + * UPDATE HISTORY: + * Created 05/08/00 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +/* GLOBALS *******************************************************************/ + +extern HANDLE Secur32Heap; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +LsaDeregisterLogonProcess(HANDLE LsaHandle) +{ + LSASS_REQUEST Request; + LSASS_REPLY Reply; + NTSTATUS Status; + + Request.Header.DataSize = 0; + Request.Header.MessageSize = sizeof(LSASS_REQUEST); + Request.Type = LSASS_REQUEST_DEREGISTER_LOGON_PROCESS; + Status = NtRequestWaitReplyPort(LsaHandle, + &Request.Header, + &Reply.Header); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (!NT_SUCCESS(Reply.Status)) + { + return(Reply.Status); + } + + return(Status); +} + +NTSTATUS STDCALL +LsaConnectUntrusted(PHANDLE LsaHandle) +{ + return(STATUS_UNSUCCESSFUL); +} + +NTSTATUS STDCALL +LsaCallAuthenticationPackage(HANDLE LsaHandle, + ULONG AuthenticationPackage, + PVOID ProtocolSubmitBuffer, + ULONG SubmitBufferLength, + PVOID* ProtocolReturnBuffer, + PULONG ReturnBufferLength, + PNTSTATUS ProtocolStatus) +{ + PLSASS_REQUEST Request; + PLSASS_REPLY Reply; + UCHAR RawRequest[MAX_MESSAGE_DATA]; + UCHAR RawReply[MAX_MESSAGE_DATA]; + NTSTATUS Status; + ULONG OutBufferSize; + + Request = (PLSASS_REQUEST)RawRequest; + Reply = (PLSASS_REPLY)RawReply; + + Request->Header.DataSize = sizeof(LSASS_REQUEST) + SubmitBufferLength - + sizeof(LPC_MESSAGE_HEADER); + Request->Header.MessageSize = + Request->Header.DataSize + sizeof(LPC_MESSAGE_HEADER); + Request->Type = LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE; + Request->d.CallAuthenticationPackageRequest.AuthenticationPackage = + AuthenticationPackage; + Request->d.CallAuthenticationPackageRequest.InBufferLength = + SubmitBufferLength; + memcpy(Request->d.CallAuthenticationPackageRequest.InBuffer, + ProtocolSubmitBuffer, + SubmitBufferLength); + + Status = NtRequestWaitReplyPort(LsaHandle, + &Request->Header, + &Reply->Header); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (!NT_SUCCESS(Reply->Status)) + { + return(Reply->Status); + } + + OutBufferSize = Reply->d.CallAuthenticationPackageReply.OutBufferLength; + *ProtocolReturnBuffer = RtlAllocateHeap(Secur32Heap, + 0, + OutBufferSize); + *ReturnBufferLength = OutBufferSize; + memcpy(*ProtocolReturnBuffer, + Reply->d.CallAuthenticationPackageReply.OutBuffer, + *ReturnBufferLength); + + return(Status); +} + +NTSTATUS STDCALL +LsaFreeReturnBuffer(PVOID Buffer) +{ + return(RtlFreeHeap(Secur32Heap, 0, Buffer)); +} + +NTSTATUS STDCALL +LsaLookupAuthenticationPackage(HANDLE LsaHandle, + PLSA_STRING PackageName, + PULONG AuthenticationPackage) +{ + NTSTATUS Status; + PLSASS_REQUEST Request; + UCHAR RawRequest[MAX_MESSAGE_DATA]; + LSASS_REPLY Reply; + + Request = (PLSASS_REQUEST)RawRequest; + Request->Header.DataSize = sizeof(LSASS_REQUEST) + PackageName->Length - + sizeof(LPC_MESSAGE_HEADER); + Request->Header.MessageSize = Request->Header.DataSize + + sizeof(LPC_MESSAGE_HEADER); + Request->Type = LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE; + + Status = NtRequestWaitReplyPort(LsaHandle, + &Request->Header, + &Reply.Header); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (!NT_SUCCESS(Reply.Status)) + { + return(Reply.Status); + } + + *AuthenticationPackage = Reply.d.LookupAuthenticationPackageReply.Package; + + return(Reply.Status); +} + +NTSTATUS STDCALL +LsaLogonUser(HANDLE LsaHandle, + PLSA_STRING OriginName, + SECURITY_LOGON_TYPE LogonType, + ULONG AuthenticationPackage, + PVOID AuthenticationInformation, + ULONG AuthenticationInformationLength, + PTOKEN_GROUPS LocalGroups, + PTOKEN_SOURCE SourceContext, + PVOID* ProfileBuffer, + PULONG ProfileBufferLength, + PLUID LogonId, + PHANDLE Token, + PQUOTA_LIMITS Quotas, + PNTSTATUS SubStatus) +{ + ULONG RequestLength; + ULONG CurrentLength; + PLSASS_REQUEST Request; + UCHAR RawMessage[MAX_MESSAGE_DATA]; + PLSASS_REPLY Reply; + UCHAR RawReply[MAX_MESSAGE_DATA]; + NTSTATUS Status; + + RequestLength = sizeof(LSASS_REQUEST) - sizeof(LPC_MESSAGE_HEADER); + RequestLength = RequestLength + (OriginName->Length * sizeof(WCHAR)); + RequestLength = RequestLength + AuthenticationInformationLength; + RequestLength = RequestLength + + (LocalGroups->GroupCount * sizeof(SID_AND_ATTRIBUTES)); + + CurrentLength = 0; + Request = (PLSASS_REQUEST)RawMessage; + + Request->d.LogonUserRequest.OriginNameLength = OriginName->Length; + Request->d.LogonUserRequest.OriginName = (PWSTR)&RawMessage[CurrentLength]; + memcpy((PWSTR)&RawMessage[CurrentLength], + OriginName->Buffer, + OriginName->Length * sizeof(WCHAR)); + CurrentLength = CurrentLength + (OriginName->Length * sizeof(WCHAR)); + + Request->d.LogonUserRequest.LogonType = LogonType; + + Request->d.LogonUserRequest.AuthenticationPackage = + AuthenticationPackage; + + Request->d.LogonUserRequest.AuthenticationInformation = + (PVOID)&RawMessage[CurrentLength]; + Request->d.LogonUserRequest.AuthenticationInformationLength = + AuthenticationInformationLength; + memcpy((PVOID)&RawMessage[CurrentLength], + AuthenticationInformation, + AuthenticationInformationLength); + CurrentLength = CurrentLength + AuthenticationInformationLength; + + Request->d.LogonUserRequest.LocalGroupsCount = LocalGroups->GroupCount; + Request->d.LogonUserRequest.LocalGroups = + (PSID_AND_ATTRIBUTES)&RawMessage[CurrentLength]; + memcpy((PSID_AND_ATTRIBUTES)&RawMessage[CurrentLength], + LocalGroups->Groups, + LocalGroups->GroupCount * sizeof(SID_AND_ATTRIBUTES)); + + Request->d.LogonUserRequest.SourceContext = *SourceContext; + + Request->Type = LSASS_REQUEST_LOGON_USER; + Request->Header.DataSize = RequestLength - sizeof(LPC_MESSAGE_HEADER); + Request->Header.MessageSize = RequestLength + sizeof(LPC_MESSAGE_HEADER); + + Reply = (PLSASS_REPLY)RawReply; + + Status = NtRequestWaitReplyPort(LsaHandle, + &Request->Header, + &Reply->Header); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + *SubStatus = Reply->d.LogonUserReply.SubStatus; + + if (!NT_SUCCESS(Reply->Status)) + { + return(Status); + } + + *ProfileBuffer = RtlAllocateHeap(Secur32Heap, + 0, + Reply->d.LogonUserReply.ProfileBufferLength); + memcpy(*ProfileBuffer, + (PVOID)((ULONG)Reply->d.LogonUserReply.Data + + (ULONG)Reply->d.LogonUserReply.ProfileBuffer), + Reply->d.LogonUserReply.ProfileBufferLength); + *LogonId = Reply->d.LogonUserReply.LogonId; + *Token = Reply->d.LogonUserReply.Token; + memcpy(Quotas, + &Reply->d.LogonUserReply.Quotas, + sizeof(Reply->d.LogonUserReply.Quotas)); + + return(Status); +} + +NTSTATUS STDCALL +LsaRegisterLogonProcess(PLSA_STRING LsaLogonProcessName, + PHANDLE Handle, + PLSA_OPERATIONAL_MODE OperationalMode) +{ + UNICODE_STRING Portname = UNICODE_STRING_INITIALIZER(L"\\SeLsaCommandPort"); + ULONG ConnectInfoLength; + NTSTATUS Status; + LSASS_REQUEST Request; + LSASS_REPLY Reply; + + ConnectInfoLength = 0; + Status = NtConnectPort(Handle, + &Portname, + NULL, + NULL, + NULL, + NULL, + NULL, + &ConnectInfoLength); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Request.Type = LSASS_REQUEST_REGISTER_LOGON_PROCESS; + Request.Header.DataSize = sizeof(LSASS_REQUEST) - + sizeof(LPC_MESSAGE_HEADER); + Request.Header.MessageSize = sizeof(LSASS_REQUEST); + + Request.d.RegisterLogonProcessRequest.Length = LsaLogonProcessName->Length; + wcscpy(Request.d.RegisterLogonProcessRequest.LogonProcessNameBuffer, + LsaLogonProcessName->Buffer); + + Status = NtRequestWaitReplyPort(*Handle, + &Request.Header, + &Reply.Header); + if (!NT_SUCCESS(Status)) + { + NtClose(*Handle); + *Handle = INVALID_HANDLE_VALUE; + return(Status); + } + + if (!NT_SUCCESS(Reply.Status)) + { + NtClose(*Handle); + *Handle = INVALID_HANDLE_VALUE; + return(Status); + } + + *OperationalMode = Reply.d.RegisterLogonProcessReply.OperationalMode; + + return(Reply.Status); +} + diff --git a/lib/secur32/secur32.def b/lib/secur32/secur32.def new file mode 100644 index 0000000..f0d8ac0 --- /dev/null +++ b/lib/secur32/secur32.def @@ -0,0 +1,9 @@ +LIBRARY SECUR32.DLL +EXPORTS +LsaRegisterLogonProcess@12 +LsaLogonUser@56 +LsaDeregisterLogonProcess@4 +LsaConnectUntrusted@4 +LsaLookupAuthenticationPackage@12 +LsaFreeReturnBuffer@4 +LsaCallAuthenticationPackage@28 diff --git a/lib/secur32/secur32.edf b/lib/secur32/secur32.edf new file mode 100644 index 0000000..4595f48 --- /dev/null +++ b/lib/secur32/secur32.edf @@ -0,0 +1,9 @@ +LIBRARY KERNEL32.DLL +EXPORTS +LsaRegisterLogonProcess=LsaRegisterLogonProcess@12 +LsaLogonUser=LsaLogonUser@56 +LsaDeregisterLogonProcess=LsaDeregisterLogonProcess@4 +LsaConnectUntrusted=LsaConnectUntrusted@4 +LsaLookupAuthenticationPackage=LsaLookupAuthenticationPackage@12 +LsaFreeReturnBuffer=LsaFreeReturnBuffer@4 +LsaCallAuthenticationPackage=LsaCallAuthenticationPackage@28 diff --git a/lib/secur32/secur32.rc b/lib/secur32/secur32.rc new file mode 100644 index 0000000..e7c8ba8 --- /dev/null +++ b/lib/secur32/secur32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Security\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "secur32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "secur32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/shell32/.cvsignore b/lib/shell32/.cvsignore new file mode 100644 index 0000000..cffb70c --- /dev/null +++ b/lib/shell32/.cvsignore @@ -0,0 +1,19 @@ +shell32.coff +shell32.dll +shell32.nostrip.dll +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/shell32/control/control.c b/lib/shell32/control/control.c new file mode 100644 index 0000000..9698fd0 --- /dev/null +++ b/lib/shell32/control/control.c @@ -0,0 +1,551 @@ +/* + * ReactOS shell32 - Control Panel + * + * control.c + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +#include "control.h" +#include "framewnd.h" +#include "settings.h" + +#include "shell32.h" +#include "trace.h" + +//#define _USE_WINE_WND_ + +//WINE_DEFAULT_DEBUG_CHANNEL(shlctrl); + +//////////////////////////////////////////////////////////////////////////////// +// Global Variables: +// + +HINSTANCE hInst; +HWND hFrameWnd; +HWND hStatusBar; +HMENU hMenuFrame; + +TCHAR szTitle[MAX_LOADSTRING]; +TCHAR szWindowClass[MAX_LOADSTRING]; + + +//////////////////////////////////////////////////////////////////////////////// + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + RECT rect; + WNDCLASSEX wcFrame = { + sizeof(WNDCLASSEX), + CS_HREDRAW | CS_VREDRAW/*style*/, + FrameWndProc, + 0/*cbClsExtra*/, + 0/*cbWndExtra*/, + hInstance, + LoadIcon(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDI_CONTROL)), + LoadCursor(0, IDC_ARROW), + 0/*hbrBackground*/, + 0/*lpszMenuName*/, + szWindowClass, + (HICON)LoadImage(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDI_CONTROL), IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) + }; + ATOM hFrameWndClass = RegisterClassEx(&wcFrame); // register frame window class + + hMenuFrame = LoadMenu(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDR_CONTROL_MENU)); + + // Initialize the Windows Common Controls DLL + InitCommonControls(); + + if (LoadSettings(&rect)) { + hFrameWnd = CreateWindowEx(0, (LPCTSTR)(int)hFrameWndClass, szTitle, + WS_OVERLAPPEDWINDOW | WS_EX_CLIENTEDGE, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + NULL, hMenuFrame, hInstance, NULL/*lpParam*/); + } else { + hFrameWnd = CreateWindowEx(0, (LPCTSTR)(int)hFrameWndClass, szTitle, + WS_OVERLAPPEDWINDOW | WS_EX_CLIENTEDGE, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, hMenuFrame, hInstance, NULL/*lpParam*/); + } + + + if (!hFrameWnd) { + return FALSE; + } + + // Create the status bar + hStatusBar = CreateStatusWindow(WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|SBT_NOBORDERS, + _T(""), hFrameWnd, STATUS_WINDOW); + if (hStatusBar) { + // Create the status bar panes + SetupStatusBar(hFrameWnd, FALSE); + CheckMenuItem(GetSubMenu(hMenuFrame, ID_VIEW_MENU), ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED); + } + ShowWindow(hFrameWnd, nCmdShow); + UpdateWindow(hFrameWnd); + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// + +void ExitInstance(void) +{ + DestroyMenu(hMenuFrame); +} + + +int APIENTRY ControlMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPCTSTR pCmdLine, + int nCmdShow) +{ + MSG msg; + HACCEL hAccel; + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_CONTROL, szWindowClass, MAX_LOADSTRING); + + // Store instance handle in our global variable + hInst = hInstance; + + // Perform application initialization: + if (!InitInstance(hInstance, nCmdShow)) { + return FALSE; + } + hAccel = LoadAccelerators(hInstance, (LPCTSTR)IDC_CONTROL); + + // Main message loop: + while (GetMessage(&msg, (HWND)NULL, 0, 0)) { + if (!TranslateAccelerator(msg.hwnd, hAccel, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + ExitInstance(); + return msg.wParam; +} + +//////////////////////////////////////////////////////////////////////////////// + +CPlApplet* Control_UnloadApplet(CPlApplet* applet) +{ + unsigned i; + CPlApplet* next; + + for (i = 0; i < applet->count; i++) { + if (!applet->info[i].dwSize) continue; + applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData); + } + if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L); + FreeLibrary(applet->hModule); + next = applet->next; + HeapFree(GetProcessHeap(), 0, applet); + return next; +} + +CPlApplet* Control_LoadApplet(HWND hWnd, LPCTSTR cmd, CPlApplet** pListHead) +{ + CPlApplet* applet; + unsigned i; + CPLINFO info; + + if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) + return applet; + applet->hWnd = hWnd; + if (!(applet->hModule = LoadLibrary(cmd))) { + TRACE(_T("Cannot load control panel applet %s\n"), cmd); + goto theError; + } + if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) { +// if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "_CPlApplet@16"))) { + TRACE(_T("Not a valid control panel applet %s\n"), cmd); + goto theError; + } + if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) { + TRACE(_T("Init of applet has failed\n")); + goto theError; + } + if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) { + TRACE(_T("No subprogram in applet\n")); + goto theError; + } + applet = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet, +// sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOA)); + sizeof(*applet) + (applet->count - 0) * sizeof(NEWCPLINFO)); + for (i = 0; i < applet->count; i++) { +// applet->info[i].dwSize = sizeof(NEWCPLINFOA); + applet->info[i].dwSize = sizeof(NEWCPLINFO); + /* proc is supposed to return a null value upon success for + * CPL_INQUIRE and CPL_NEWINQUIRE + * However, real drivers don't seem to behave like this + * So, use introspection rather than return value + */ + applet->info[i].hIcon = 0; + applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&applet->info[i]); + if (applet->info[i].hIcon == 0) { + applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info); + if (info.idIcon == 0 || info.idName == 0) { + TRACE(_T("Couldn't get info from sp %u\n"), i); + applet->info[i].dwSize = 0; + } else { + /* convert the old data into the new structure */ + applet->info[i].dwFlags = 0; + applet->info[i].dwHelpContext = 0; + applet->info[i].lData = info.lData; +// applet->info[i].hIcon = LoadIcon(applet->hModule, (LPCTSTR)MAKEINTRESOURCEA(info.idIcon)); +// applet->info[i].hIcon = LoadIcon(applet->hModule, (LPCTSTR)MAKEINTRESOURCE(info.idIcon)); + applet->info[i].hIcon = LoadImage(applet->hModule, (LPCTSTR)info.idIcon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + + LoadString(applet->hModule, info.idName, applet->info[i].szName, sizeof(applet->info[i].szName)/sizeof(TCHAR)); + //LoadString(applet->hModule, info.idInfo, applet->info[i].szInfo, sizeof(applet->info[i].szInfo)/sizeof(TCHAR)); + //applet->info[i].szHelpFile[0] = '\0'; + LoadString(applet->hModule, info.idInfo, applet->info[i].szInfo, 192); + } + } else { + TRACE(_T("Using CPL_NEWINQUIRE data\n")); + } + } + applet->next = *pListHead; + *pListHead = applet; + return applet; +theError: + Control_UnloadApplet(applet); + return NULL; +} + +void Control_DoLaunch(CPlApplet** pListHead, HWND hWnd, LPCTSTR cmd) + /* forms to parse: + * foo.cpl,@sp,str + * foo.cpl,@sp + * foo.cpl,,str + * foo.cpl @sp + * foo.cpl str + */ +{ + TCHAR* buffer; + TCHAR* beg = NULL; + TCHAR* end; + TCHAR ch; + unsigned sp = 0; + TCHAR* extraPmts = NULL; + + buffer = HeapAlloc(GetProcessHeap(), 0, _tcslen(cmd) + 1); + if (!buffer) return; + + end = _tcscpy(buffer, cmd); + + for (;;) { + ch = *end; + if (ch == _T(' ') || ch == _T(',') || ch == _T('\0')) { + *end = _T('\0'); + if (beg) { + if (*beg == _T('@')) { + sp = _ttoi(beg + 1); + } else if (*beg == _T('\0')) { + sp = 0; + } else { + extraPmts = beg; + } + } + if (ch == _T('\0')) break; + beg = end + 1; + if (ch == _T(' ')) while (end[1] == _T(' ')) end++; + } + end++; + } +#if 1 + Control_LoadApplet(hWnd, buffer, pListHead); + if (*pListHead) { + CPlApplet* applet = *pListHead; + assert(applet && applet->next == NULL); + if (sp >= applet->count) { + TRACE(_T("Out of bounds (%u >= %u), setting to 0\n"), sp, applet->count); + sp = 0; + } + if (applet->info[sp].dwSize) { + if (!applet->proc(applet->hWnd, CPL_STARTWPARMS, sp, (LPARAM)extraPmts)) + applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData); + } + Control_UnloadApplet(applet); + } +#else + +//static void Control_LaunchApplet(HWND hWnd, CPlEntry* pCPlEntry) + +#endif + HeapFree(GetProcessHeap(), 0, buffer); +} + +//int APIENTRY ControlMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPCTSTR lpCmdLine, int nCmdShow); + +VOID Control_RunDLL(HWND hWnd, HINSTANCE hInst_unused, LPCTSTR lpCmdLine, DWORD nCmdShow) +{ + CPanel panel; +// TRACE("(0x%08x, 0x%08lx, %s, 0x%08lx)\n", hWnd, (DWORD)hInst, debugstr_a(lpCmdLine), nCmdShow); + + memset(&panel, 0, sizeof(panel)); + + if (!lpCmdLine || !*lpCmdLine) { +#ifdef _USE_WINE_WND_ + Control_DoWindow(&panel, hWnd, hInst); +#else + ControlMain(hInst, NULL, lpCmdLine, nCmdShow); +#endif + } else { + Control_DoLaunch(&panel.first, hWnd, lpCmdLine); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +#ifdef _USE_WINE_WND_ + +static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTA* cs) +{ + CPanel* panel = (CPanel*)cs->lpCreateParams; + + SetWindowLong(hWnd, 0, (LPARAM)panel); + panel->status = 0; + panel->hWnd = hWnd; +} + +#define XICON 32 +#define XSTEP 128 +#define YICON 32 +#define YSTEP 64 + +static BOOL Control_Localize(const CPanel* panel, unsigned cx, unsigned cy, + CPlApplet** papplet, unsigned* psp) +{ + unsigned i, x = (XSTEP-XICON)/2, y = 0; + CPlApplet* applet; + RECT rc; + + GetClientRect(panel->hWnd, &rc); + for (applet = panel->first; applet; applet = applet = applet->next) { + for (i = 0; i < applet->count; i++) { + if (!applet->info[i].dwSize) continue; + if (x + XSTEP >= rc.right - rc.left) { + x = (XSTEP-XICON)/2; + y += YSTEP; + } + if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP) { + *papplet = applet; + *psp = i; + return TRUE; + } + x += XSTEP; + } + } + return FALSE; +} + +static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam) +{ + HDC hdc; + PAINTSTRUCT ps; + RECT rc, txtRect; + unsigned i, x = 0, y = 0; + CPlApplet* applet; + HGDIOBJ hOldFont; + + hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps); + hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT)); + GetClientRect(panel->hWnd, &rc); + for (applet = panel->first; applet; applet = applet = applet->next) { + for (i = 0; i < applet->count; i++) { + if (x + XSTEP >= rc.right - rc.left) { + x = 0; + y += YSTEP; + } + if (!applet->info[i].dwSize) continue; + DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon); + txtRect.left = x; + txtRect.right = x + XSTEP; + txtRect.top = y + YICON; + txtRect.bottom = y + YSTEP; + DrawText(hdc, applet->info[i].szName, -1, &txtRect, + DT_CENTER | DT_VCENTER); + x += XSTEP; + } + } + SelectObject(hdc, hOldFont); + if (!wParam) EndPaint(panel->hWnd, &ps); + return 0; +} + +static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up) +{ + unsigned i; + CPlApplet* applet; + + if (Control_Localize(panel, LOWORD(lParam), HIWORD(lParam), &applet, &i)) { + if (up) { + if (panel->clkApplet == applet && panel->clkSP == i) { + applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData); + } + } else { + panel->clkApplet = applet; + panel->clkSP = i; + } + } + return 0; +} + +//static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg, +static LRESULT __stdcall Control_WndProc(HWND hWnd, UINT wMsg, + WPARAM lParam1, LPARAM lParam2) +{ + CPanel* panel = (CPanel*)GetWindowLongA(hWnd, 0); + + if (panel || wMsg == WM_CREATE) { + switch (wMsg) { + case WM_CREATE: + Control_WndProc_Create(hWnd, (CREATESTRUCTA*)lParam2); + return 0; + case WM_DESTROY: + while ((panel->first = Control_UnloadApplet(panel->first))); + break; + case WM_PAINT: + return Control_WndProc_Paint(panel, lParam1); + case WM_LBUTTONUP: + return Control_WndProc_LButton(panel, lParam2, TRUE); + case WM_LBUTTONDOWN: + return Control_WndProc_LButton(panel, lParam2, FALSE); +/* EPP case WM_COMMAND: */ +/* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */ + } + } + + return DefWindowProcA(hWnd, wMsg, lParam1, lParam2); +} + +static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst) +{ + WNDCLASS wc; + MSG msg; + + wc.style = CS_HREDRAW|CS_VREDRAW; + wc.lpfnWndProc = Control_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(CPlApplet*); + wc.hInstance = hInst; + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = "Shell_Control_WndClass"; + + if (!RegisterClass(&wc)) return; + + CreateWindowEx(0, wc.lpszClassName, "Wine Control Panel", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hWnd, (HMENU)0, hInst, panel); + if (!panel->hWnd) return; + while (GetMessage(&msg, panel->hWnd, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + if (!panel->first) break; + } +} + +static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst) +{ + HANDLE h; + WIN32_FIND_DATA fd; + TCHAR buffer[MAX_PATH]; + + /* TRACE: should grab path somewhere from configuration */ + if ((h = FindFirstFile("c:\\winnt\\system32\\*.cpl", &fd)) != 0) { + do { + sprintf(buffer, "c:\\winnt\\system32\\%s", fd.cFileName); + if (!strstr(fd.cFileName, "powercfg")) { + Control_LoadApplet(hWnd, buffer, panel); + } + } while (FindNextFile(h, &fd)); + FindClose(h); + } + + if (panel->first) Control_DoInterface(panel, hWnd, hInst); +} + +#endif // _USE_WINE_WND_ + +#if 0 +/************************************************************************* + * Control_RunDLL [SHELL32.@] + * + */ + +VOID WINAPI +Control_RunDLL(HWND hWnd, HINSTANCE hInst_unused, LPCSTR lpCmdLine, DWORD nCmdShow) +{ +// TRACE("(0x%08x, 0x%08lx, %s, 0x%08lx)\n", hWnd, (DWORD)hInst, debugstr_a(lpCmdLine), nCmdShow); +} + +/************************************************************************* + * Control_FillCache_RunDLL [SHELL32.@] + * + */ +HRESULT WINAPI +Control_FillCache_RunDLL(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) +{ + TRACE(_T("0x%04x 0x%04x 0x%04lx 0x%04lx stub\n"), hWnd, hModule, w, x); + return 0; +} + +/************************************************************************* + * RunDLL_CallEntry16 [SHELL32.122] + * the name is probably wrong + */ +HRESULT WINAPI +RunDLL_CallEntry16(DWORD v, DWORD w, DWORD x, DWORD y, DWORD z) +{ + TRACE(_T("0x%04lx 0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n"),v,w,x,y,z); + return 0; +} + +/************************************************************************* + * CallCPLEntry16 [SHELL32.166] + * + * called by desk.cpl on "Advanced" with: + * hMod("DeskCp16.Dll"), pFunc("CplApplet"), 0, 1, 0xc, 0 + * + */ +DWORD WINAPI +CallCPLEntry16(HMODULE hMod, FARPROC pFunc, DWORD dw3, DWORD dw4, DWORD dw5, DWORD dw6) +{ + TRACE(_T("(%04x, %p, %08lx, %08lx, %08lx, %08lx): stub.\n"), hMod, pFunc, dw3, dw4, dw5, dw6); + return 0x0deadbee; +} +#endif diff --git a/lib/shell32/control/control.h b/lib/shell32/control/control.h new file mode 100644 index 0000000..ca6157c --- /dev/null +++ b/lib/shell32/control/control.h @@ -0,0 +1,174 @@ +/* + * ReactOS shell32 - Control Panel + * + * control.h + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __CONTROL_H__ +#define __CONTROL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "resource.h" + +#define STATUS_WINDOW 2001 +#define TREE_WINDOW 2002 +#define LIST_WINDOW 2003 + +#define MAX_LOADSTRING 100 +#define SPLIT_WIDTH 5 +#define MAX_NAME_LEN 500 + +#define MAX_CPL_NAME 128 +#define MAX_CPL_INFO 128 + +//////////////////////////////////////////////////////////////////////////////// +/* +typedef struct tagNEWCPLINFO { + DWORD dwSize; + DWORD dwFlags; + DWORD dwHelpContext; + LONG lData; + HICON hIcon; + TCHAR szName[32]; + TCHAR szInfo[64]; + TCHAR szHelpFile[128]; +} NEWCPLINFO; + + */ +typedef struct tagCPLAppletINFO { + DWORD dwSize; + DWORD dwFlags; + DWORD dwHelpContext; + LONG lData; + HICON hIcon; + TCHAR szName[32]; + TCHAR szInfo[192]; +// TCHAR szHelpFile[128]; +} CPLAppletINFO; + + +typedef struct CPlApplet { + struct CPlApplet* next; /* linked list */ + HWND hWnd; + unsigned count; /* number of subprograms */ + HMODULE hModule; /* module of loaded applet */ + TCHAR filename[MAX_PATH]; + APPLET_PROC proc; /* entry point address */ + NEWCPLINFO info[1]; /* array of count information. dwSize field is 0 if entry is invalid */ +} CPlApplet; + +typedef struct CPlEntry { + CPlApplet* pCPlApplet; /* which cpl module we are associated with (contained in) */ + HWND hWnd; /* handle to existing window if we are already launched */ + unsigned nSubProg; /* which sub-program we are within the CPlApplet */ + unsigned nIconIndex; /* */ + long lData; +// union { +// NEWCPLINFO NewCplInfo; +// CPLAppletINFO AppletInfo; +// } info; +} CPlEntry; + +typedef struct CPanel { + CPlApplet* first; /* linked list */ + HWND hWnd; + unsigned status; + CPlApplet* clkApplet; + unsigned clkSP; +} CPanel; + +#ifndef CPL_STARTWPARMSW +#undef CPL_STARTWPARMS +#define CPL_STARTWPARMSW 10 +#ifdef UNICODE +#define CPL_STARTWPARMS CPL_STARTWPARMSW +#else +#define CPL_STARTWPARMS CPL_STARTWPARMSA +#endif +#endif + + +enum OPTION_FLAGS { + OPTIONS_AUTO_REFRESH = 0x01, + OPTIONS_READ_ONLY_MODE = 0x02, + OPTIONS_CONFIRM_ON_DELETE = 0x04, + OPTIONS_SAVE_ON_EXIT = 0x08, + OPTIONS_DISPLAY_BINARY_DATA = 0x10, + OPTIONS_VIEW_TREE_ONLY = 0x20, + OPTIONS_VIEW_DATA_ONLY = 0x40, +}; + +typedef struct { + HWND hWnd; + HWND hTreeWnd; + HWND hListWnd; + int nFocusPanel; // 0: left 1: right + int nSplitPos; + WINDOWPLACEMENT pos; + TCHAR szPath[MAX_PATH]; +} ChildWnd; + +//////////////////////////////////////////////////////////////////////////////// +// Global Variables: +// +extern HINSTANCE hInst; +extern HWND hFrameWnd; +extern HMENU hMenuFrame; +extern HWND hStatusBar; +extern HFONT hFont; +extern enum OPTION_FLAGS Options; + +extern TCHAR szTitle[]; +extern TCHAR szWindowClass[]; + +void Control_DoLaunch(CPlApplet** pListHead, HWND hWnd, LPCTSTR cmd); +CPlApplet* Control_LoadApplet(HWND hWnd, LPCTSTR cmd, CPlApplet** pListHead); +CPlApplet* Control_UnloadApplet(CPlApplet* applet); + + +#ifdef __GNUC__ +typedef struct tagNMITEMACTIVATE{ + NMHDR hdr; + int iItem; + int iSubItem; + UINT uNewState; + UINT uOldState; + UINT uChanged; + POINT ptAction; + LPARAM lParam; + UINT uKeyFlags; +} NMITEMACTIVATE, FAR *LPNMITEMACTIVATE; +#define HDITEM HD_ITEM +#define LPNMLISTVIEW LPNM_LISTVIEW +#define NMLISTVIEW NM_LISTVIEW +#define HDN_ENDDRAG TBN_ENDDRAG +#define LVSICF_NOSCROLL LVS_NOSCROLL +#define HDM_GETORDERARRAY (HDM_FIRST+19) // TODO: FIX ME +#endif + + +#ifdef __cplusplus +}; +#endif + +#endif // __CONTROL_H__ diff --git a/lib/shell32/control/framewnd.c b/lib/shell32/control/framewnd.c new file mode 100644 index 0000000..0a4d5fa --- /dev/null +++ b/lib/shell32/control/framewnd.c @@ -0,0 +1,458 @@ +/* + * ReactOS shell32 - Control Panel Frame Window implementation + * + * framewnd.c + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include +#include +#include +#include +#include +#include +#include + +#include "control.h" +#include "framewnd.h" +#include "settings.h" +#include "listview.h" +//#include +#include "trace.h" + + +#ifdef __GNUC__ +int WINAPI ShellAboutA(HWND,LPCSTR,LPCSTR,HICON); +int WINAPI ShellAboutW(HWND,LPCWSTR,LPCWSTR,HICON); +#else +int ShellAboutA(HWND,LPCSTR,LPCSTR,HICON); +int ShellAboutW(HWND,LPCWSTR,LPCWSTR,HICON); +#endif + + +//////////////////////////////////////////////////////////////////////////////// +// Global and Local Variables: +// + +DWORD nListStyle; +DWORD nSortOrder; + +static int nSelectedItem; +static HWND hListWnd; +static BOOL bInMenuLoop = FALSE; // Tells us if we are in the menu loop + +//////////////////////////////////////////////////////////////////////////////// +// Local module support methods +// + +static void resize_frame_rect(HWND hWnd, PRECT prect) +{ + RECT rt; +/* + if (IsWindowVisible(hToolBar)) { + SendMessage(hToolBar, WM_SIZE, 0, 0); + GetClientRect(hToolBar, &rt); + prect->top = rt.bottom+3; + prect->bottom -= rt.bottom+3; + } + */ + if (IsWindowVisible(hStatusBar)) { + SetupStatusBar(hWnd, TRUE); + GetClientRect(hStatusBar, &rt); + prect->bottom -= rt.bottom; + } + MoveWindow(hListWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE); +} + +void resize_frame_client(HWND hWnd) +{ + RECT rect; + + GetClientRect(hWnd, &rect); + resize_frame_rect(hWnd, &rect); +} + +//////////////////////////////////////////////////////////////////////////////// + +static void OnEnterMenuLoop(HWND hWnd) +{ + int nParts; + + // Update the status bar pane sizes + nParts = -1; + SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts); + bInMenuLoop = TRUE; + SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T("")); +} + +static void OnExitMenuLoop(HWND hwndLV, HWND hWnd) +{ + bInMenuLoop = FALSE; + // Update the status bar pane sizes + SetupStatusBar(hWnd, TRUE); + UpdateStatusBar(hwndLV, -1); +} + +static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu) +{ + TCHAR str[100]; + + _tcscpy(str, _T("")); + if (nFlags & MF_POPUP) { + if (hSysMenu != GetMenu(hWnd)) { + if (nItemID == 2) nItemID = 5; + } + } + if (LoadString(hInst, nItemID, str, 100)) { + // load appropriate string + LPTSTR lpsz = str; + // first newline terminates actual string + lpsz = _tcschr(lpsz, '\n'); + if (lpsz != NULL) + *lpsz = '\0'; + } + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str); +} + +void SetupStatusBar(HWND hWnd, BOOL bResize) +{ + RECT rc; + int nParts; + GetClientRect(hWnd, &rc); + nParts = rc.right; +// nParts = -1; + if (bResize) + SendMessage(hStatusBar, WM_SIZE, 0, 0); + SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts); +} + +void UpdateStatusBar(HWND hwndLV, int list_index) +{ + static int last_list_index; + TCHAR buffer[MAX_CPL_INFO]; + LVITEM item; + + if (list_index == -1) list_index = last_list_index; + last_list_index = list_index; + //LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam; + //CPlEntry* pCPlEntry pCPLInfo = pnmv->lParam + item.mask = LVIF_TEXT; + item.iItem = last_list_index; + item.pszText = buffer; + item.cchTextMax = MAX_CPL_INFO; + item.iSubItem = 1; + if (ListView_GetItem(hwndLV, &item)) { + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)buffer); + } +} + +static void toggle_child(HWND hWnd, UINT cmd, HWND hchild) +{ + BOOL vis = IsWindowVisible(hchild); + HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU); + + CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED); + ShowWindow(hchild, vis?SW_HIDE:SW_SHOW); + resize_frame_client(hWnd); +} + +static void OnPaint(HWND hWnd) +{ + PAINTSTRUCT ps; + RECT rt; + HDC hdc; + + GetClientRect(hWnd, &rt); + hdc = BeginPaint(hWnd, &ps); + FillRect(ps.hdc, &rt, GetStockObject(LTGRAY_BRUSH)); + EndPaint(hWnd, &ps); +} + +static void SetListSytle(DWORD view) +{ + HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU); + DWORD dwListStyle = GetWindowLong(hListWnd, GWL_STYLE); + dwListStyle &= ~(LVS_ICON | LVS_SMALLICON | LVS_LIST | LVS_REPORT); + nListStyle = view; + switch (view) { + case ID_VIEW_LARGE_ICONS: + dwListStyle |= LVS_ICON; + break; + case ID_VIEW_SMALL_ICONS: + dwListStyle |= LVS_SMALLICON; + break; + case ID_VIEW_LIST: + dwListStyle |= LVS_LIST; + break; + default: + nListStyle = ID_VIEW_DETAILS; + case ID_VIEW_DETAILS: + dwListStyle |= LVS_REPORT; + break; + } + SetWindowLong(hListWnd, GWL_STYLE, dwListStyle); + CheckMenuItem(hMenuView, ID_VIEW_LARGE_ICONS, MF_BYCOMMAND); + CheckMenuItem(hMenuView, ID_VIEW_SMALL_ICONS, MF_BYCOMMAND); + CheckMenuItem(hMenuView, ID_VIEW_LIST, MF_BYCOMMAND); + CheckMenuItem(hMenuView, ID_VIEW_DETAILS, MF_BYCOMMAND); + CheckMenuItem(hMenuView, nListStyle, MF_BYCOMMAND|MF_CHECKED); +} + +void SetViewArrangement(DWORD cmd) +{ + DWORD dwListStyle = GetWindowLong(hListWnd, GWL_STYLE); + HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU); + nSortOrder = cmd; + dwListStyle &= ~(LVS_AUTOARRANGE); + switch (cmd) { + case ID_VIEW_ARRANGE_BY_NAME: + SortListView(hListWnd, 0); + break; + case ID_VIEW_ARRANGE_BY_COMMENT: + SortListView(hListWnd, 1); + break; + default: + nSortOrder = ID_VIEW_ARRANGE_AUTO; + case ID_VIEW_ARRANGE_AUTO: + SortListView(hListWnd, -1); + dwListStyle |= LVS_AUTOARRANGE; + break; + } + SetWindowLong(hListWnd, GWL_STYLE, dwListStyle); + CheckMenuItem(hMenuView, ID_VIEW_ARRANGE_BY_NAME, MF_BYCOMMAND); + CheckMenuItem(hMenuView, ID_VIEW_ARRANGE_BY_COMMENT, MF_BYCOMMAND); + CheckMenuItem(hMenuView, ID_VIEW_ARRANGE_AUTO, MF_BYCOMMAND); + CheckMenuItem(hMenuView, nSortOrder, MF_BYCOMMAND|MF_CHECKED); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes WM_COMMAND messages for the main frame window. +// +// + +static void OnFileOpen(HWND hWnd) +{ + LVITEM item; + + item.mask = LVIF_PARAM; + item.iItem = nSelectedItem; + item.iSubItem = 0; + if (ListView_GetItem(hListWnd, &item)) { + Control_LaunchApplet(hListWnd, (CPlEntry*)item.lParam); + } +} + +static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) { + // Parse the menu selections: + case ID_FILE_OPEN: + OnFileOpen(hWnd); + break; + case ID_FILE_EXIT: + DestroyWindow(hWnd); + break; + case ID_VIEW_REFRESH: + RefreshListView(hListWnd, NULL); + break; + case ID_VIEW_LARGE_ICONS: + case ID_VIEW_SMALL_ICONS: + case ID_VIEW_LIST: + case ID_VIEW_DETAILS: + SetListSytle(LOWORD(wParam)); + break; + case ID_VIEW_STATUSBAR: + toggle_child(hWnd, LOWORD(wParam), hStatusBar); + break; + case ID_VIEW_ARRANGE_BY_NAME: + case ID_VIEW_ARRANGE_BY_COMMENT: + case ID_VIEW_ARRANGE_AUTO: + SetViewArrangement(LOWORD(wParam)); + break; + case ID_VIEW_LINE_UP_ICONS: + ListView_Arrange(hListWnd, LVA_DEFAULT ); + break; + case ID_HELP_ABOUT: +#ifdef UNICODE + ShellAboutW(hWnd, szTitle, L"", LoadIcon(hInst, (LPCTSTR)IDI_CONTROL)); +#else + ShellAboutA(hWnd, szTitle, "", LoadIcon(hInst, (LPCTSTR)IDI_CONTROL)); +#endif + break; + default: + return FALSE; + } + return TRUE; +} + +extern CPlApplet* pListHead; // holds pointer to linked list of cpl modules CPlApplet* + +static void OnLeftClick(HWND hWnd, NMITEMACTIVATE* nmitem) +{ + //HMENU hMenu = NULL; + LVHITTESTINFO info; + + info.pt.x = nmitem->ptAction.x; + info.pt.y = nmitem->ptAction.y; + if (ListView_HitTest(hListWnd, &info) != -1) { + LVITEM item; + item.mask = LVIF_PARAM; + item.iItem = info.iItem; + if (ListView_GetItem(hListWnd, &item)) { + //Control_LaunchApplet(hWnd, (CPlEntry*)item.lParam); + //hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTROL_CONTEXT_APPLET)); + } + } else { + TCHAR buffer[MAX_CPL_INFO]; + int obj_count = ListView_GetItemCount(hListWnd); + int cpl_count = 0; + int cpl_locked_count = 0; + CPlApplet* applet = pListHead; + while (applet) { + ++cpl_count; + if (applet->hModule) ++cpl_locked_count; + applet = applet->next; + } + + + TRACE(_T("OnLeftClick(0x%08X) - %u\n"), hWnd, obj_count); + + wsprintf(buffer, _T("%u applets in %u libraries (%u locked)"), obj_count, cpl_count, cpl_locked_count); + SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)buffer); + } +} + +static void OnRightClick(HWND hWnd, NMITEMACTIVATE* nmitem) +{ + HMENU hMenu = NULL; + LVHITTESTINFO info; + info.pt.x = nmitem->ptAction.x; + info.pt.y = nmitem->ptAction.y; + if (ListView_HitTest(hListWnd, &info) != -1) { + LVITEM item; + item.mask = LVIF_PARAM; + item.iItem = info.iItem; + if (ListView_GetItem(hListWnd, &item)) { + //Control_LaunchApplet(hWnd, (CPlEntry*)item.lParam); + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTROL_CONTEXT_APPLET)); + } + } + if (!hMenu) { + hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_CONTROL_CONTEXT)); + } + if (hMenu) { + HMENU hSubMenu = GetSubMenu(hMenu, 0); + if (hSubMenu) { + POINT pt; + GetCursorPos(&pt); + TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hWnd, NULL); + } + DestroyMenu(hMenu); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main frame window. +// +// WM_COMMAND - process the application menu +// WM_DESTROY - post a quit message and return +// +// + +LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + RECT rect; + + switch (message) { + case WM_CREATE: + hListWnd = CreateListView(hWnd, LIST_WINDOW); + SetListSytle(nListStyle); + SetViewArrangement(nSortOrder); + break; + case WM_NOTIFY: + { + NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam; + if (nmitem->hdr.idFrom == LIST_WINDOW) { + switch (((LPNMHDR)lParam)->code) { + case LVN_ITEMCHANGED: + nSelectedItem = ((LPNMLISTVIEW)lParam)->iItem; + UpdateStatusBar(hListWnd, ((LPNMLISTVIEW)lParam)->iItem); + break; + //case NM_DBLCLK: + //OnDblClick(hWnd, nmitem); + //break; + case NM_RETURN: + OnFileOpen(hWnd); + break; + case NM_CLICK: + OnLeftClick(hWnd, nmitem); + break; + case NM_RCLICK: + OnRightClick(hWnd, nmitem); + break; + //default: + //return FALSE; + } + if (ListViewNotifyProc(hListWnd, message, wParam, lParam)) + return TRUE; + } + } + return DefWindowProc(hWnd, message, wParam, lParam); + case WM_COMMAND: + if (!_CmdWndProc(hWnd, message, wParam, lParam)) { + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + case WM_PAINT: + OnPaint(hWnd); + return 0; + case WM_SIZE: + resize_frame_client(hWnd); + //if (nSortOrder == ID_VIEW_ARRANGE_AUTO) SetViewArrangement(nSortOrder); + //if (nSortOrder == ID_VIEW_ARRANGE_AUTO) ListView_Update(hListWnd, 0); + break; + case WM_TIMER: + break; + case WM_ENTERMENULOOP: + OnEnterMenuLoop(hWnd); + break; + case WM_EXITMENULOOP: + OnExitMenuLoop(hListWnd, hWnd); + break; + case WM_MENUSELECT: + OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam); + break; + case WM_DESTROY: + GetWindowRect(hWnd, &rect); + SaveSettings(&rect); + DestroyListView(hListWnd); + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} diff --git a/lib/shell32/control/framewnd.h b/lib/shell32/control/framewnd.h new file mode 100644 index 0000000..156a544 --- /dev/null +++ b/lib/shell32/control/framewnd.h @@ -0,0 +1,45 @@ +/* + * ReactOS shell32 - Control Panel Frame Window implementation + * + * framewnd.h + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __FRAMEWND_H__ +#define __FRAMEWND_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +LRESULT CALLBACK FrameWndProc(HWND, UINT, WPARAM, LPARAM); + +void SetupStatusBar(HWND hWnd, BOOL bResize); +void UpdateStatusBar(HWND hwndLV, int list_index); + + +#ifdef __cplusplus +}; +#endif + +#endif // __FRAMEWND_H__ diff --git a/lib/shell32/control/listview.c b/lib/shell32/control/listview.c new file mode 100644 index 0000000..82dec80 --- /dev/null +++ b/lib/shell32/control/listview.c @@ -0,0 +1,660 @@ +/* + * ReactOS shell32 - Control Panel ListCtrl implementation + * + * listview.c + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "control.h" +#include "listview.h" + +#include "assert.h" +#include "trace.h" + + +static int _GetSystemDirectory(LPTSTR buffer, int buflen) +{ +#if 0 + return GetSystemDirectory(buffer, buflen); +#else + return GetCurrentDirectory(buflen, buffer); +// if (lstrcpyn(buffer, szTestDirName, buflen - 1)) { +// return lstrlen(buffer); +// } +// return 0; +#endif +} + + +//////////////////////////////////////////////////////////////////////////////// +// Global and Local Variables: +// + +#define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1) +static int default_column_widths[MAX_LIST_COLUMNS] = { 250, 500 }; +static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_LEFT }; + +CPlApplet* pListHead; // holds pointer to linked list of cpl modules CPlApplet* +//static CPlApplet* pListHead; // holds pointer to linked list of cpl modules CPlApplet* + + +//////////////////////////////////////////////////////////////////////////////// +// Local module support methods +// + +static void AddAppletsToListView(HWND hwndLV, CPlApplet* pApplet) +{ + LVITEM item; + UINT count; + + for (count = 0; count < pApplet->count; count++) { + int index = 0; + NEWCPLINFO* pCPLInfo = &pApplet->info[count]; + + CPlEntry* pCPlEntry; + if (!(pCPlEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pCPlEntry)))) + return; + + pCPlEntry->hWnd = hwndLV; + pCPlEntry->nSubProg = count; + pCPlEntry->pCPlApplet = pApplet; + + if (pCPLInfo->hIcon) { // add the icon to an image list + HIMAGELIST hImageList; + hImageList = ListView_GetImageList(hwndLV, LVSIL_NORMAL); + index = ImageList_AddIcon(hImageList, pCPLInfo->hIcon); + hImageList = ListView_GetImageList(hwndLV, LVSIL_SMALL); + ImageList_AddIcon(hImageList, pCPLInfo->hIcon); + DestroyIcon(pCPLInfo->hIcon); + } + item.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE | LVIF_PARAM; + item.iItem = 0;//idx; + item.iSubItem = 0; + item.state = 0; + item.stateMask = 0; +// item.pszText = LPSTR_TEXTCALLBACK; +// item.cchTextMax = 50; + item.pszText = pCPLInfo->szName; + item.cchTextMax = _tcslen(item.pszText); + item.iImage = index; + item.lParam = (LPARAM)pCPlEntry; +#if (_WIN32_IE >= 0x0300) + item.iIndent = 0; +#endif + index = ListView_InsertItem(hwndLV, &item); + if (index != -1 && pCPLInfo->szInfo != NULL) { + ListView_SetItemText(hwndLV, index, 1, pCPLInfo->szInfo); + } + } +} + +static void CreateListColumns(HWND hwndLV) +{ + TCHAR szText[50]; + int index; + LV_COLUMN lvC; + + // Create columns. + lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvC.pszText = szText; + + // Load the column labels from the resource file. + for (index = 0; index < MAX_LIST_COLUMNS; index++) { + lvC.iSubItem = index; + lvC.cx = default_column_widths[index]; + lvC.fmt = column_alignment[index]; + LoadString(hInst, IDS_LIST_COLUMN_FIRST + index, szText, 50); + if (ListView_InsertColumn(hwndLV, index, &lvC) == -1) { + // TODO: handle failure condition... + break; + } + } +} + +// InitListViewImageLists - creates image lists for a list view control. +// This function only creates image lists. It does not insert the +// items into the control, which is necessary for the control to be +// visible. +// Returns TRUE if successful, or FALSE otherwise. +// hwndLV - handle to the list view control. +static BOOL InitListViewImageLists(HWND hwndLV) +{ +// HICON hiconItem; // icon for list view items + HIMAGELIST hLarge; // image list for icon view + HIMAGELIST hSmall; // image list for other views + + // Create the full-sized icon image lists. + hLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), + GetSystemMetrics(SM_CYICON), ILC_MASK, 1, 20); + hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 20); + + // Add an icon to each image list. +// hiconItem = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ITEM)); +// hiconItem = LoadIcon(hInst, MAKEINTRESOURCE(IDI_CONTROL)); +// ImageList_AddIcon(hLarge, hiconItem); +// ImageList_AddIcon(hSmall, hiconItem); +// DestroyIcon(hiconItem); + + /********************************************************* + Usually you have multiple icons; therefore, the previous + four lines of code can be inside a loop. The following code + shows such a loop. The icons are defined in the application's + header file as resources, which are numbered consecutively + starting with IDS_FIRSTICON. The number of icons is + defined in the header file as C_ICONS. + + for(index = 0; index < C_ICONS; index++) { + hIconItem = LoadIcon (hInst, MAKEINTRESOURCE (IDS_FIRSTICON + index)); + ImageList_AddIcon(hSmall, hIconItem); + ImageList_AddIcon(hLarge, hIconItem); + Destroy(hIconItem); + } + *********************************************************/ + + // Assign the image lists to the list view control. + ListView_SetImageList(hwndLV, hLarge, LVSIL_NORMAL); + ListView_SetImageList(hwndLV, hSmall, LVSIL_SMALL); + return TRUE; +} + +typedef LONG (WINAPI *CPlApplet_Ptr)(HWND, UINT, LONG, LONG); + +static void AddEntryToList(HWND hwndLV, LPTSTR szName, LPTSTR szInfo, CPlEntry* pCPlEntry) +{ + LVITEM item; + int index; + + assert(pCPlEntry); + memset(&item, 0, sizeof(LVITEM)); + item.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE | LVIF_PARAM; + if (szName != NULL) { + item.pszText = szName; + item.cchTextMax = _tcslen(item.pszText); + item.iImage = pCPlEntry->nIconIndex; + } else { + item.pszText = LPSTR_TEXTCALLBACK; + item.cchTextMax = MAX_CPL_NAME; + item.iImage = I_IMAGECALLBACK; + } + item.lParam = (LPARAM)pCPlEntry; +#if (_WIN32_IE >= 0x0300) + item.iIndent = 0; +#endif + index = ListView_InsertItem(hwndLV, &item); + if (index != -1) { + if (szInfo != NULL) { + ListView_SetItemText(hwndLV, index, 1, szInfo); + } else { + ListView_SetItemText(hwndLV, index, 1, LPSTR_TEXTCALLBACK); + } + } +} + +#if 0 +/* +static CPlApplet* Control_LoadApplet(HWND hwndLV, LPTSTR buffer, CPlApplet** pListHead) +{ + HMODULE hCpl; + hCpl = LoadLibrary(buffer); + if (hCpl) { + CPlApplet_Ptr pCPlApplet; + pCPlApplet = (CPlApplet_Ptr)(FARPROC)GetProcAddress(hCpl, "CPlApplet"); + if (pCPlApplet) { + if (pCPlApplet(hwndLV, CPL_INIT, 0, 0)) { + int nSubProgs = pCPlApplet(hwndLV, CPL_GETCOUNT, 0, 0); + if (nSubProgs == 0) { + TRACE(_T("No subprogram in applet\n")); + } + + { + CPlApplet* applet; + if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) { + return applet; + } + applet->next = *pListHead; + *pListHead = applet; + } + strncpy(applet->filename, buffer, MAX_PATH); + while (nSubProgs && nSubProgs--) { + CPLINFO cplInfo; + memset(&cplInfo, 0, sizeof(CPLINFO)); + pCPlApplet(hwndLV, CPL_INQUIRE, nSubProgs, (LPARAM)&cplInfo); + if (cplInfo.idName == CPL_DYNAMIC_RES) { +#if UNICODE + NEWCPLINFO cplNewInfo; + memset(&cplNewInfo, 0, sizeof(NEWCPLINFO)); + cplNewInfo.dwSize = sizeof(NEWCPLINFO); + pCPlApplet(hwndLV, CPL_NEWINQUIRE, nSubProgs, (LPARAM)&cplNewInfo); + cplNewInfo.lData = hCpl; + AddEntryToList(hwndLV, &cplNewInfo); +#endif + } else { + int index = 0; + NEWCPLINFO cplNewInfo; + memset(&cplNewInfo, 0, sizeof(NEWCPLINFO)); + cplNewInfo.dwSize = sizeof(NEWCPLINFO); + if (LoadString(hCpl, cplInfo.idName, cplNewInfo.szName, sizeof(cplNewInfo.szName)/sizeof(TCHAR))) { + } + if (LoadString(hCpl, cplInfo.idInfo, cplNewInfo.szInfo, sizeof(cplNewInfo.szInfo)/sizeof(TCHAR))) { + } + cplNewInfo.hIcon = LoadImage(hCpl, (LPCTSTR)cplInfo.idIcon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + cplNewInfo.lData = (LONG)hCpl; + AddEntryToList(hwndLV, &cplNewInfo); + } + } + return TRUE; + } else { + TRACE(_T("Init of applet has failed\n")); + } + } else { + TRACE(_T("Not a valid control panel applet %s\n"), buffer); + } + FreeLibrary(hCpl); + } else { + TRACE(_T("Cannot load control panel applet %s\n"), buffer); + } + return FALSE; +} + */ +#endif + +static void LoadApplet(HWND hwndLV, LPTSTR buffer, CPlApplet** pListHead) +{ + HMODULE hModule; + hModule = LoadLibrary(buffer); + if (hModule) { + CPlApplet_Ptr pCPlApplet; + pCPlApplet = (CPlApplet_Ptr)(FARPROC)GetProcAddress(hModule, "CPlApplet"); + if (pCPlApplet) { + if (pCPlApplet(hwndLV, CPL_INIT, 0, 0)) { + CPlApplet* applet; + int nSubProgs = pCPlApplet(hwndLV, CPL_GETCOUNT, 0, 0); + if (nSubProgs == 0) { + TRACE(_T("No subprogram in applet\n")); + } + if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) { + goto loadapplet_error; + } + applet->next = *pListHead; + *pListHead = applet; + _tcsncpy(applet->filename, buffer, MAX_PATH); + while (nSubProgs && nSubProgs--) { + NEWCPLINFO cplNewInfo; + memset(&cplNewInfo, 0, sizeof(NEWCPLINFO)); + cplNewInfo.dwSize = sizeof(NEWCPLINFO); + pCPlApplet(hwndLV, CPL_NEWINQUIRE, nSubProgs, (LPARAM)&cplNewInfo); + if (cplNewInfo.hIcon == 0) { + CPLINFO cplInfo; + memset(&cplInfo, 0, sizeof(CPLINFO)); + pCPlApplet(hwndLV, CPL_INQUIRE, nSubProgs, (LPARAM)&cplInfo); + if (cplInfo.idIcon == 0 || cplInfo.idName == 0) { + TRACE(_T("Couldn't get info from sp %u\n"), nSubProgs); + } else { + TCHAR szName[MAX_CPL_NAME]; + TCHAR szInfo[MAX_CPL_INFO]; + HICON hIcon = NULL; + CPlEntry* pCPlEntry; + if (!(pCPlEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPlEntry)))) { + goto loadapplet_error; + } + pCPlEntry->nSubProg = nSubProgs; + pCPlEntry->lData = cplInfo.lData; + pCPlEntry->pCPlApplet = applet; + hIcon = LoadImage(hModule, (LPCTSTR)cplInfo.idIcon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + LoadString(hModule, cplInfo.idName, szName, MAX_CPL_NAME); + LoadString(hModule, cplInfo.idInfo, szInfo, MAX_CPL_INFO); + if (hIcon) { // add the icon to an image list + HIMAGELIST hImageList; + hImageList = ListView_GetImageList(hwndLV, LVSIL_NORMAL); + pCPlEntry->nIconIndex = ImageList_AddIcon(hImageList, hIcon); + hImageList = ListView_GetImageList(hwndLV, LVSIL_SMALL); + ImageList_AddIcon(hImageList, hIcon); + DestroyIcon(hIcon); + } + AddEntryToList(hwndLV, szName, szInfo, pCPlEntry); + } + } else { + HIMAGELIST hImageList; + CPlEntry* pCPlEntry; + TRACE(_T("Using CPL_NEWINQUIRE data\n")); + if (!(pCPlEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPlEntry)))) { + goto loadapplet_error; + } + applet->hModule = LoadLibrary(buffer); + pCPlEntry->nSubProg = nSubProgs; + pCPlEntry->lData = cplNewInfo.lData; + pCPlEntry->pCPlApplet = applet; + hImageList = ListView_GetImageList(hwndLV, LVSIL_NORMAL); + pCPlEntry->nIconIndex = ImageList_AddIcon(hImageList, cplNewInfo.hIcon); + hImageList = ListView_GetImageList(hwndLV, LVSIL_SMALL); + ImageList_AddIcon(hImageList, cplNewInfo.hIcon); + DestroyIcon(cplNewInfo.hIcon); + AddEntryToList(hwndLV, NULL, NULL, pCPlEntry); + } + } + } else { + TRACE(_T("Init of applet has failed\n")); + } + } else { + TRACE(_T("Not a valid control panel applet %s\n"), buffer); + } +loadapplet_error: + FreeLibrary(hModule); + } else { + TRACE(_T("Cannot load control panel applet %s\n"), buffer); + } +} + + +static BOOL InitListViewItems(HWND hwndLV, LPTSTR szPath) +{ + WIN32_FIND_DATA data; + HANDLE hFind; + TCHAR buffer[MAX_PATH+10], *p; + UINT length; + + length = _GetSystemDirectory(buffer, sizeof(buffer)/sizeof(TCHAR)); + p = &buffer[length]; + lstrcpy(p, _T("\\*.cpl")); + memset(&data, 0, sizeof(WIN32_FIND_DATA)); + hFind = FindFirstFile(buffer, &data); + if (hFind != INVALID_HANDLE_VALUE) { + do { + if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { +#if 0 + CPlApplet* pApplet; + lstrcpy(p+1, data.cFileName); + pApplet = Control_LoadApplet(hwndLV, buffer, &pListHead); + if (pApplet != NULL) { + AddAppletsToListView(hwndLV, pApplet); + } +#else + lstrcpy(p+1, data.cFileName); + LoadApplet(hwndLV, buffer, &pListHead); +#endif + } + } while (FindNextFile(hFind, &data)); + FindClose(hFind); + } + return TRUE; +} + +// OnGetDispInfo - processes the LVN_GETDISPINFO notification message. +static void OnGetDispInfo(HWND hWnd, NMLVDISPINFO* plvdi) +{ + CPlEntry* pCPlEntry = (CPlEntry*)plvdi->item.lParam; + + plvdi->item.pszText = NULL; + plvdi->item.cchTextMax = 0; + if (pCPlEntry != NULL) { + CPlApplet* pApplet = pCPlEntry->pCPlApplet; + assert(pApplet); + if (pApplet->hModule) { + CPlApplet_Ptr pCPlApplet; + pCPlApplet = (CPlApplet_Ptr)(FARPROC)GetProcAddress(pApplet->hModule, "CPlApplet"); + if (pCPlApplet) { + static NEWCPLINFO cplNewInfo; + memset(&cplNewInfo, 0, sizeof(NEWCPLINFO)); + cplNewInfo.dwSize = sizeof(NEWCPLINFO); + pCPlApplet(hWnd, CPL_NEWINQUIRE, pCPlEntry->nSubProg, (LPARAM)&cplNewInfo); + + if (plvdi->item.mask && LVIF_IMAGE) { + if (cplNewInfo.hIcon) { // add the icon to an image list + HIMAGELIST hImageList; + hImageList = ListView_GetImageList(hWnd, LVSIL_NORMAL); + pCPlEntry->nIconIndex = ImageList_ReplaceIcon(hImageList, pCPlEntry->nIconIndex, cplNewInfo.hIcon); + hImageList = ListView_GetImageList(hWnd, LVSIL_SMALL); + ImageList_ReplaceIcon(hImageList, pCPlEntry->nIconIndex, cplNewInfo.hIcon); + DestroyIcon(cplNewInfo.hIcon); + } + plvdi->item.iImage = pCPlEntry->nIconIndex; + } + if (plvdi->item.mask && LVIF_STATE) { + } + if (plvdi->item.mask && LVIF_TEXT) { + switch (plvdi->item.iSubItem) { + case 0: + plvdi->item.pszText = cplNewInfo.szName; + plvdi->item.cchTextMax = _tcslen(plvdi->item.pszText); + break; + case 1: + plvdi->item.pszText = cplNewInfo.szInfo; + plvdi->item.cchTextMax = _tcslen(plvdi->item.pszText); + break; + case 2: + plvdi->item.pszText = _T(""); + plvdi->item.cchTextMax = _tcslen(plvdi->item.pszText); + break; + } + } + } + } + } +} + +static void OnDeleteItem(NMLISTVIEW* pnmlv) +{ + CPlEntry* pCPlEntry = (CPlEntry*)pnmlv->lParam; + if (pCPlEntry != NULL) { + HeapFree(GetProcessHeap(), 0, pCPlEntry); + } +} + +static void OnItemChanged(NMLISTVIEW* pnmlv) +{ +} + +void Control_LaunchApplet(HWND hwndLV, CPlEntry* pCPlEntry) +{ + CPlApplet_Ptr pCPlApplet; + CPlApplet* pApplet = pCPlEntry->pCPlApplet; + + assert(pApplet); + if (pApplet->hModule == NULL) { + pApplet->hModule = LoadLibrary(pApplet->filename); + pCPlApplet = (CPlApplet_Ptr)(FARPROC)GetProcAddress(pApplet->hModule, "CPlApplet"); + if (pCPlApplet) { + if (pCPlApplet(hwndLV, CPL_INIT, 0, 0)) { + unsigned int nSubProgs = pCPlApplet(hwndLV, CPL_GETCOUNT, 0, 0); + if (nSubProgs < pCPlEntry->nSubProg) { + TRACE(_T("Only %u subprograms in applet, requested %u\n"), nSubProgs, pCPlEntry->nSubProg); + return; + } + } else { + TRACE(_T("Init of applet has failed\n")); + return; + } + } else { + TRACE(_T("Not a valid control panel applet %s\n"), pApplet->filename); + return; + } + } + if (pApplet->hModule) { + pCPlApplet = (CPlApplet_Ptr)(FARPROC)GetProcAddress(pApplet->hModule, "CPlApplet"); + if (pCPlApplet) { + TCHAR* extraPmts = NULL; + if (!pCPlApplet(hwndLV, CPL_STARTWPARMS, pCPlEntry->nSubProg, (LPARAM)extraPmts)) + pCPlApplet(hwndLV, CPL_DBLCLK, pCPlEntry->nSubProg, pCPlEntry->lData); + } + + } +// NEWCPLINFO* pCPLInfo = &(pCPlEntry->pCPlApplet->info[pCPlEntry->nSubProg]); +// TCHAR* extraPmts = NULL; +// if (pCPLInfo->dwSize && pApplet->proc) { +// if (!pApplet->proc(pApplet->hWnd, CPL_STARTWPARMS, pCPlEntry->nSubProg, (LPARAM)extraPmts)) +// pApplet->proc(pApplet->hWnd, CPL_DBLCLK, pCPlEntry->nSubProg, pCPLInfo->lData); +// } +} + +static void OnDblClick(HWND hWnd, NMITEMACTIVATE* nmitem) +{ + LVHITTESTINFO info; +/* +#ifdef _MSC_VER + switch (nmitem->uKeyFlags) { + case LVKF_ALT: // The ALT key is pressed. + break; + case LVKF_CONTROL: // The CTRL key is pressed. + break; + case LVKF_SHIFT: // The SHIFT key is pressed. + break; + } +#endif + */ + info.pt.x = nmitem->ptAction.x; + info.pt.y = nmitem->ptAction.y; + if (ListView_HitTest(hWnd, &info) != -1) { + LVITEM item; + item.mask = LVIF_PARAM; + item.iItem = info.iItem; + if (ListView_GetItem(hWnd, &item)) { + Control_LaunchApplet(hWnd, (CPlEntry*)item.lParam); + } + } +} + +struct CompareData { + HWND hListWnd; + int nSortColumn; +}; + +static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + struct CompareData* pcd = (struct CompareData*)lParamSort; + + TCHAR buf1[MAX_CPL_INFO]; + TCHAR buf2[MAX_CPL_INFO]; + + ListView_GetItemText(pcd->hListWnd, lParam1, pcd->nSortColumn, buf1, sizeof(buf1)/sizeof(TCHAR)); + ListView_GetItemText(pcd->hListWnd, lParam2, pcd->nSortColumn, buf2, sizeof(buf2)/sizeof(TCHAR)); + return _tcscmp(buf1, buf2); +} + +/* +static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + TCHAR buf1[1000]; + TCHAR buf2[1000]; + + ListView_GetItemText((HWND)lParamSort, lParam1, 0, buf1, sizeof(buf1)/sizeof(TCHAR)); + ListView_GetItemText((HWND)lParamSort, lParam2, 0, buf2, sizeof(buf2)/sizeof(TCHAR)); + return _tcscmp(buf1, buf2); +} + +static void ListViewPopUpMenu(HWND hWnd, POINT pt) +{ +} + +BOOL ListView_SortItemsEx( + HWND hwnd, + PFNLVCOMPARE pfnCompare, + LPARAM lParamSort +); + + + */ +#ifdef __GNUC__ +//#define LVM_FIRST 0x1000 // ListView messages +#define LVM_SORTITEMSEX (0x1000 + 81) +#define ListView_SortItemsEx(hwndLV, _pfnCompare, _lPrm) \ + (BOOL)SendMessage((hwndLV), LVM_SORTITEMSEX, (WPARAM)(LPARAM)(_lPrm), (LPARAM)(PFNLVCOMPARE)(_pfnCompare)) +#endif + +BOOL SortListView(HWND hWnd, int nSortColumn) +{ + struct CompareData cd = { hWnd, nSortColumn }; + return ListView_SortItemsEx(hWnd, CompareFunc, &cd); +} + +BOOL ListViewNotifyProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + NMITEMACTIVATE* nmitem = (LPNMITEMACTIVATE)lParam; + + if (nmitem->hdr.idFrom == LIST_WINDOW) { + switch (((LPNMHDR)lParam)->code) { + case LVN_GETDISPINFO: + OnGetDispInfo(hWnd, (NMLVDISPINFO*)lParam); + break; + case LVN_DELETEITEM: + OnDeleteItem((NMLISTVIEW*)lParam); + //pnmv = (LPNMLISTVIEW) lParam + break; + case LVN_ITEMCHANGED: + OnItemChanged((NMLISTVIEW*)lParam); + break; + case NM_DBLCLK: + OnDblClick(hWnd, nmitem); + break; + //case NM_RCLICK: + //OnRightClick(hWnd, nmitem); + //break; + default: + return FALSE; + } + } + return TRUE; +} + +VOID DestroyListView(HWND hwndLV) +{ + if (pListHead) + while ((pListHead = Control_UnloadApplet(pListHead))); +} + +BOOL RefreshListView(HWND hwndLV, LPTSTR szPath) +{ + if (hwndLV != NULL) { + ListView_DeleteAllItems(hwndLV); + } + return InitListViewItems(hwndLV, szPath); +} + +HWND CreateListView(HWND hwndParent, int id) +{ + RECT rcClient; + HWND hwndLV; + + // Get the dimensions of the parent window's client area, and create the list view control. + GetClientRect(hwndParent, &rcClient); + hwndLV = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, _T("List View"), + WS_VISIBLE | WS_CHILD, + 0, 0, rcClient.right, rcClient.bottom, + hwndParent, (HMENU)id, hInst, NULL); + ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT); + CreateListColumns(hwndLV); + + // Initialize the image list, and add items to the control. + if (!InitListViewImageLists(hwndLV) || !InitListViewItems(hwndLV, NULL/*szPath*/)) { + DestroyWindow(hwndLV); + return FALSE; + } + return hwndLV; +} + diff --git a/lib/shell32/control/listview.h b/lib/shell32/control/listview.h new file mode 100644 index 0000000..9ce659f --- /dev/null +++ b/lib/shell32/control/listview.h @@ -0,0 +1,48 @@ +/* + * ReactOS shell32 - Control Panel ListCtrl implementation + * + * listview.h + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LISTVIEW_H__ +#define __LISTVIEW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +HWND CreateListView(HWND hwndParent, int id); +BOOL RefreshListView(HWND hwndTV, LPTSTR szPath); +//void OnGetDispInfo(NMLVDISPINFO* plvdi); +BOOL ListViewNotifyProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +VOID DestroyListView(HWND hwndLV); +BOOL SortListView(HWND hWnd, int nSortColumn); +void Control_LaunchApplet(HWND hwndLV, CPlEntry* pCPlEntry); + + +#ifdef __cplusplus +}; +#endif + +#endif // __LISTVIEW_H__ diff --git a/lib/shell32/control/settings.c b/lib/shell32/control/settings.c new file mode 100644 index 0000000..4d81d44 --- /dev/null +++ b/lib/shell32/control/settings.c @@ -0,0 +1,157 @@ +/* + * ReactOS shell32 - Control Panel + * + * settings.c + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include + +#include "control.h" +//#include "framewnd.h" +//#include "shell32.h" +#include "trace.h" + +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +//#include +//#include +//#include +//#define ASSERT assert + +//#include "control.h" +#include "settings.h" + + +//////////////////////////////////////////////////////////////////////////////// +// Global and Local Variables: +// + +extern DWORD nListStyle; +extern DWORD nSortOrder; + +//////////////////////////////////////////////////////////////////////////////// +// Local module support methods +// + +BOOL CheckResult(LONG error) +{ + if (error != ERROR_SUCCESS) { + PTSTR msg; + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) + MessageBox(NULL, msg, szTitle, MB_ICONERROR | MB_OK); + else + MessageBox(NULL, _T("Error"), szTitle, MB_ICONERROR | MB_OK); + LocalFree(msg); + return FALSE; + } + return TRUE; +} + +static BOOL CreateRegistryPath(LPTSTR szRegPath, int nMaxLen) +{ + LPTSTR pRegPath = szRegPath; + + // Initialise registry path string from application PATH and KEY resources + int nLength = LoadString(hInst, IDS_APP_REG_PATH, szRegPath, nMaxLen); + nLength += LoadString(hInst, IDS_APP_REG_KEY, szRegPath + nLength, nMaxLen - nLength); +// ASSERT(nLength < (nMaxLen - 1)); + szRegPath[nLength] = _T('\\'); + + // walk the registry path string creating the tree if required + while ((pRegPath = _tcschr(pRegPath, _T('\\')))) { + LONG result; + HKEY hKey = NULL; + *pRegPath = _T('\0'); + // Open (or create) the key + result = RegCreateKeyEx(HKEY_CURRENT_USER, szRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); + if (!CheckResult(result)) return FALSE; + RegCloseKey(hKey); + *pRegPath = _T('\\'); + pRegPath = pRegPath + 1; + } + szRegPath[nLength] = _T('\0'); + return TRUE; +} + +BOOL LoadSettings(RECT* prc) +{ + BOOL retval = TRUE; + TCHAR szRegPath[MAX_LOADSTRING]; + HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU); + + HKEY hKey; + DWORD dwSize; + LONG result; + + if (!CreateRegistryPath(szRegPath, MAX_LOADSTRING)) return FALSE; + + // Open the key + result = RegOpenKeyEx(HKEY_CURRENT_USER, szRegPath, 0, KEY_READ, &hKey); + if (!CheckResult(result)) return FALSE; + + // Read the settings + dwSize = sizeof(nListStyle); + result = RegQueryValueEx(hKey, _T("ListStyle"), NULL, NULL, (LPBYTE)&nListStyle, &dwSize); + dwSize = sizeof(nSortOrder); + result = RegQueryValueEx(hKey, _T("SortOrder"), NULL, NULL, (LPBYTE)&nSortOrder, &dwSize); + dwSize = sizeof(RECT); + result = RegQueryValueEx(hKey, _T("WindowPos"), NULL, NULL, (LPBYTE)prc, &dwSize); + if (result != ERROR_SUCCESS) { + retval = FALSE; + } + + // Close the key + RegCloseKey(hKey); + return retval; +} + +void SaveSettings(RECT* prc) +{ + TCHAR szRegPath[MAX_LOADSTRING]; + HKEY hKey = NULL; + LONG result; + + if (!CreateRegistryPath(szRegPath, MAX_LOADSTRING)) return; + + // Open the key + result = RegOpenKeyEx(HKEY_CURRENT_USER, szRegPath, 0, KEY_WRITE, &hKey); + if (!CheckResult(result)) return; + + // Save the settings + result = RegSetValueEx(hKey, _T("ListStyle"), 0, REG_DWORD, (LPBYTE)&nListStyle, sizeof(nListStyle)); + if (!CheckResult(result)) goto abort; + result = RegSetValueEx(hKey, _T("SortOrder"), 0, REG_DWORD, (LPBYTE)&nSortOrder, sizeof(nSortOrder)); + if (!CheckResult(result)) goto abort; + result = RegSetValueEx(hKey, _T("WindowPos"), 0, REG_BINARY, (LPBYTE)prc, sizeof(RECT)); + if (!CheckResult(result)) goto abort; + +abort: + // Close the key + RegCloseKey(hKey); +} diff --git a/lib/shell32/control/settings.h b/lib/shell32/control/settings.h new file mode 100644 index 0000000..a72c8c8 --- /dev/null +++ b/lib/shell32/control/settings.h @@ -0,0 +1,44 @@ +/* + * ReactOS shell32 - Control Panel + * + * settings.h + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SETTINGS_H__ +#define __SETTINGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +BOOL CheckResult(LONG error); +BOOL LoadSettings(RECT*); +void SaveSettings(RECT*); + + +#ifdef __cplusplus +}; +#endif + +#endif // __SETTINGS_H__ diff --git a/lib/shell32/control/trace.c b/lib/shell32/control/trace.c new file mode 100644 index 0000000..b5ac2d5 --- /dev/null +++ b/lib/shell32/control/trace.c @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////// +// Diagnostic Trace +// +#include +#include +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#include "trace.h" + + +#ifdef _DEBUG + +#ifdef WIN32 +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +//#include +//#include +//WINBASEAPI VOID WINAPI DebugBreak(VOID); +//WINBASEAPI VOID WINAPI OutputDebugStringA(LPCSTR lpOutputString); +//WINBASEAPI VOID WINAPI OutputDebugStringW(LPCWSTR lpOutputString); +//void __stdcall DebugBreak(void); +//void __stdcall OutputDebugStringA(char* lpOutputString); +//void __stdcall OutputDebugStringW(wchar_t* lpOutputString); +#ifdef UNICODE +#define OutputDebugString OutputDebugStringW +#else +#define OutputDebugString OutputDebugStringA +#endif // !UNICODE + +#else +#include "hardware.h" +#endif // WIN32 + + +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; + +void _DebugBreak(void) +{ + DebugBreak(); +} + +void Trace(TCHAR* lpszFormat, ...) +{ + va_list args; + int nBuf; + TCHAR szBuffer[512]; + + va_start(args, lpszFormat); +// nBuf = vsprintf(szBuffer, lpszFormat, args); +// nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args); +#ifdef _UNICODE + nBuf = _vsnwprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), lpszFormat, args); +#else + nBuf = _vsnprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), lpszFormat, args); +#endif + OutputDebugString(szBuffer); + // was there an error? was the expanded string too long? +// ASSERT(nBuf >= 0); + va_end(args); +} + +void Assert(void* assert, TCHAR* file, int line, void* msg) +{ + if (msg == NULL) { + printf("ASSERT -- %s occured on line %u of file %s.\n", + assert, line, file); + } else { + printf("ASSERT -- %s occured on line %u of file %s: Message = %s.\n", + assert, line, file, msg); + } +} + + +#else + +//inline void Trace(TCHAR* lpszFormat, ...) { }; +//inline void Assert(void* assert, TCHAR* file, int line, void* msg) { }; +void Trace(TCHAR* lpszFormat, ...) { }; +void Assert(void* assert, TCHAR* file, int line, void* msg) { }; + +#endif //_DEBUG +///////////////////////////////////////////////////////////////////////////// diff --git a/lib/shell32/control/trace.h b/lib/shell32/control/trace.h new file mode 100644 index 0000000..bbd863a --- /dev/null +++ b/lib/shell32/control/trace.h @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////// +// +#ifndef __TRACE_H__ +#define __TRACE_H__ + +#ifdef _DEBUG + +//============================================================================= +// BreakPoint() macro. +//============================================================================= + +#ifdef _X86_ +#define BreakPoint() _asm { int 3h } +#else +#define BreakPoint() _DebugBreak() +#endif + +//============================================================================= +// MACRO: ASSERT() +//============================================================================= + +#ifndef ASSERT +#define ASSERT(exp) \ +{ \ + if ( !(exp) ) \ + { \ + Assert(#exp, __FILE__, __LINE__, NULL); \ + BreakPoint(); \ + } \ +} \ + +#define ASSERTMSG(exp, msg) \ +{ \ + if ( !(exp) ) \ + { \ + Assert(#exp, __FILE__, __LINE__, msg); \ + BreakPoint(); \ + } \ +} +#endif + +//============================================================================= +// MACRO: TRACE() +//============================================================================= + +void Assert(void* assert, TCHAR* file, int line, void* msg); +void Trace(TCHAR* lpszFormat, ...); +void Trace1(int code, TCHAR* lpszFormat, ...); + +#define TRACE Trace +#define TRACE0 Trace + +#else // _DEBUG + +#ifndef ASSERT +#define ASSERT(exp) +#define ASSERTMSG(exp, msg) +#endif + +//#define TRACE0 TRACE +//#define TRACE1 TRACE + +void Assert(void* assert, TCHAR* file, int line, void* msg); +void Trace(TCHAR* lpszFormat, ...); + +#define TRACE 0 ? (void)0 : Trace + + +#endif // !_DEBUG + +#endif // __TRACE_H__ +///////////////////////////////////////////////////////////////////////////// diff --git a/lib/shell32/makefile b/lib/shell32/makefile new file mode 100644 index 0000000..09ba9c3 --- /dev/null +++ b/lib/shell32/makefile @@ -0,0 +1,55 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +SHELL32_ALIAS = roshel32 +COMCTL32_ALIAS = rosctl32 +#SHELL32_ALIAS = shell32 +#COMCTL32_ALIAS = comctl32 + +#TARGET_NAME = $(SHELL32_ALIAS) +TARGET_NAME = roshel32 + +TARGET_DEFNAME = shell32 + +TARGET_TYPE = dynlink + +#TARGET_SDKLIBS = ntdll.a kernel32.a user32.a gdi32.a advapi32.a $(COMCTL32_ALIAS).a msvcrt.a +TARGET_SDKLIBS = ntdll.a kernel32.a user32.a gdi32.a advapi32.a msvcrt.a + +TARGET_GCCLIBS = comctl32 comdlg32 version + +TARGET_CFLAGS = -D_WIN32_IE=0x0400 -DUNICODE -D_UNICODE -O2 -Wall -Wstrict-prototypes -fno-builtin -DDBG + +TARGET_CPPFLAGS = -D_WIN32_IE=0x0400 -DUNICODE -D_UNICODE -O2 -Wall -Wstrict-prototypes -fno-builtin -DDBG + +#TARGET_LFLAGS = -nostdlib + +TARGET_BASE = 0x77260000 + +MISC_OBJECTS = \ + misc/dllmain.o \ + misc/_stubs.o \ + misc/stubs.o + +CONTROL_OBJECTS = \ + control/framewnd.o \ + control/listview.o \ + control/control.o \ + control/settings.o \ + control/trace.o + +TARGET_OBJECTS = \ + $(MISC_OBJECTS) \ + $(CONTROL_OBJECTS) + +TARGET_CLEAN = $(TARGET_OBJECTS) $(TARGET_NAME).coff + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +MK_CFLAGS = -D_WIN32_IE=0x0400 -D_UNICODE -DUNICODE -I./ +MK_CPPFLAGS = -D_WIN32_IE=0x0400 -D_UNICODE -DUNICODE -I./ +MK_RCFLAGS = -D_WIN32_IE=0x0400 -D_UNICODE -DUNICODE + diff --git a/lib/shell32/misc/_stubs.cpp b/lib/shell32/misc/_stubs.cpp new file mode 100644 index 0000000..715573f --- /dev/null +++ b/lib/shell32/misc/_stubs.cpp @@ -0,0 +1,89 @@ +/* + * ReactOS shell32 - + * + * _stubs.cpp + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: stubs.cpp, + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/shell32/misc/stubs.c + * PURPOSE: C++ Stubbed exports + * PROGRAMMER: Robert Dickenson (robd@reactos.org) + */ + +//#include +#ifdef _MSC_VER +#include +#else +#include +#endif +//#define NDEBUG +//#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "shell32.h" + + +#define STUB \ + do \ + { \ + } \ + while (0) + +// DbgPrint ("%s(%d):%s not implemented\n", __FILE__, __LINE__, __FUNCTION__); + + +#ifndef __GNUC__ + +//long __stdcall +STDAPI +DllGetClassObject(const CLSID & rclsid, const IID & riid, void ** ppv) +{ + STUB; +/* +This function supports the standard return values: + E_INVALIDARG + E_OUTOFMEMORY + E_UNEXPECTED +as well as the following: + S_OK - The object was retrieved successfully + CLASS_E_CLASSNOTAVAILABLE - The DLL does not support the class (object definition) + */ + return CLASS_E_CLASSNOTAVAILABLE; +} + +#else + +//VOID STDCALL +long __stdcall +DllGetClassObject(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; + return CLASS_E_CLASSNOTAVAILABLE; +} + +#endif + +#ifdef __cplusplus +}; +#endif diff --git a/lib/shell32/misc/dllmain.c b/lib/shell32/misc/dllmain.c new file mode 100644 index 0000000..ae79e8a --- /dev/null +++ b/lib/shell32/misc/dllmain.c @@ -0,0 +1,71 @@ +/* + * ReactOS shell32 - main library entry point + * + * dllmain.c + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/shell32/misc/dllmain.c + * PURPOSE: Library main function + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + */ + +//#include +#include +#include +#include "..\control\control.h" + +//#define NDEBUG +//#include +#ifdef _MSC_VER +#pragma warning (disable:4273) // : inconsistent dll linkage. dllexport assumed. +#define STDCALL CALLBACK +#define WINBOOL BOOL + +#else +#endif +#define DPRINT(a) +#define DPRINT1(a) + + +INT STDCALL +DllMain(PVOID hinstDll, + ULONG dwReason, + PVOID reserved) +{ + DPRINT("SHELL32: DllMain() called\n"); + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + hInst = hinstDll; + break; + + case DLL_PROCESS_DETACH: + break; + } + + DPRINT1("SHELL32: DllMain() done\n"); + + return TRUE; +} + + diff --git a/lib/shell32/misc/shlwapi.h b/lib/shell32/misc/shlwapi.h new file mode 100644 index 0000000..af77b32 --- /dev/null +++ b/lib/shell32/misc/shlwapi.h @@ -0,0 +1,726 @@ +/* + * SHLWAPI.DLL functions + * + * Copyright (C) 2000 Juergen Schmied + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SHLWAPI_H +#define __WINE_SHLWAPI_H + +#ifdef __cplusplus +extern "C" { +#endif /* defined(__cplusplus) */ + +#ifndef NO_SHLWAPI_REG + +/* Registry functions */ + +DWORD WINAPI SHDeleteEmptyKeyA(HKEY,LPCSTR); +DWORD WINAPI SHDeleteEmptyKeyW(HKEY,LPCWSTR); +#define SHDeleteEmptyKey WINELIB_NAME_AW(SHDeleteEmptyKey) + +DWORD WINAPI SHDeleteKeyA(HKEY,LPCSTR); +DWORD WINAPI SHDeleteKeyW(HKEY,LPCWSTR); +#define SHDeleteKey WINELIB_NAME_AW(SHDeleteKey) + +DWORD WINAPI SHDeleteValueA(HKEY,LPCSTR,LPCSTR); +DWORD WINAPI SHDeleteValueW(HKEY,LPCWSTR,LPCWSTR); +#define SHDeleteValue WINELIB_NAME_AW(SHDeleteValue) + +DWORD WINAPI SHGetValueA(HKEY,LPCSTR,LPCSTR,LPDWORD,LPVOID,LPDWORD); +DWORD WINAPI SHGetValueW(HKEY,LPCWSTR,LPCWSTR,LPDWORD,LPVOID,LPDWORD); +#define SHGetValue WINELIB_NAME_AW(SHGetValue) + +DWORD WINAPI SHSetValueA(HKEY,LPCSTR,LPCSTR,DWORD,LPCVOID,DWORD); +DWORD WINAPI SHSetValueW(HKEY,LPCWSTR,LPCWSTR,DWORD,LPCVOID,DWORD); +#define SHSetValue WINELIB_NAME_AW(SHSetValue) + +DWORD WINAPI SHQueryValueExA(HKEY,LPCSTR,LPDWORD,LPDWORD,LPVOID,LPDWORD); +DWORD WINAPI SHQueryValueExW(HKEY,LPCWSTR,LPDWORD,LPDWORD,LPVOID,LPDWORD); +#define SHQueryValueEx WINELIB_NAME_AW(SHQueryValueEx) + +LONG WINAPI SHEnumKeyExA(HKEY,DWORD,LPSTR,LPDWORD); +LONG WINAPI SHEnumKeyExW(HKEY,DWORD,LPWSTR,LPDWORD); +#define SHEnumKeyEx WINELIB_NAME_AW(SHEnumKeyEx) + +LONG WINAPI SHEnumValueA(HKEY,DWORD,LPSTR,LPDWORD,LPDWORD,LPVOID,LPDWORD); +LONG WINAPI SHEnumValueW(HKEY,DWORD,LPWSTR,LPDWORD,LPDWORD,LPVOID,LPDWORD); +#define SHEnumValue WINELIB_NAME_AW(SHEnumValue) + +LONG WINAPI SHQueryInfoKeyA(HKEY,LPDWORD,LPDWORD,LPDWORD,LPDWORD); +LONG WINAPI SHQueryInfoKeyW(HKEY,LPDWORD,LPDWORD,LPDWORD,LPDWORD); +#define SHQueryInfoKey WINELIB_NAME_AW(SHQueryInfoKey) + +DWORD WINAPI SHRegGetPathA(HKEY,LPCSTR,LPCSTR,LPSTR,DWORD); +DWORD WINAPI SHRegGetPathW(HKEY,LPCWSTR,LPCWSTR,LPWSTR,DWORD); +#define SHRegGetPath WINELIB_NAME_AW(SHRegGetPath) + +DWORD WINAPI SHRegSetPathA(HKEY,LPCSTR,LPCSTR,LPCSTR,DWORD); +DWORD WINAPI SHRegSetPathW(HKEY,LPCWSTR,LPCWSTR,LPCWSTR,DWORD); +#define SHRegSetPath WINELIB_NAME_AW(SHRegSetPath) + +DWORD WINAPI SHCopyKeyA(HKEY,LPCSTR,HKEY,DWORD); +DWORD WINAPI SHCopyKeyW(HKEY,LPCWSTR,HKEY,DWORD); +#define SHCopyKey WINELIB_NAME_AW(SHCopyKey) + +/* Undocumented registry functions */ + +HKEY WINAPI SHRegDuplicateHKey(HKEY hKey); + +/* FIXME: SHDeleteOrphanKey */ + + +/* User registry functions */ + +typedef enum +{ + SHREGDEL_DEFAULT = 0, + SHREGDEL_HKCU = 0x1, + SHREGDEL_HKLM = 0x10, + SHREGDEL_BOTH = SHREGDEL_HKLM | SHREGDEL_HKCU +} SHREGDEL_FLAGS; + +typedef enum +{ + SHREGENUM_DEFAULT = 0, + SHREGENUM_HKCU = 0x1, + SHREGENUM_HKLM = 0x10, + SHREGENUM_BOTH = SHREGENUM_HKLM | SHREGENUM_HKCU +} SHREGENUM_FLAGS; + +#define SHREGSET_HKCU 0x1 /* Apply to HKCU if empty */ +#define SHREGSET_FORCE_HKCU 0x2 /* Always apply to HKCU */ +#define SHREGSET_HKLM 0x4 /* Apply to HKLM if empty */ +#define SHREGSET_FORCE_HKLM 0x8 /* Always apply to HKLM */ +#define SHREGSET_DEFAULT (SHREGSET_FORCE_HKCU | SHREGSET_HKLM) + +typedef HANDLE HUSKEY; +typedef HUSKEY *PHUSKEY; + +LONG WINAPI SHRegCreateUSKeyA(LPCSTR,REGSAM,HUSKEY,PHUSKEY,DWORD); +LONG WINAPI SHRegCreateUSKeyW(LPCWSTR,REGSAM,HUSKEY,PHUSKEY,DWORD); +#define SHRegCreateUSKey WINELIB_NAME_AW(SHRegCreateUSKey) + +LONG WINAPI SHRegOpenUSKeyA(LPCSTR,REGSAM,HUSKEY,PHUSKEY,BOOL); +LONG WINAPI SHRegOpenUSKeyW(LPCWSTR,REGSAM,HUSKEY,PHUSKEY,BOOL); +#define SHRegOpenUSKey WINELIB_NAME_AW(SHRegOpenUSKey) + +LONG WINAPI SHRegQueryUSValueA(HUSKEY,LPCSTR,LPDWORD,LPVOID,LPDWORD, + BOOL,LPVOID,DWORD); +LONG WINAPI SHRegQueryUSValueW(HUSKEY,LPCWSTR,LPDWORD,LPVOID,LPDWORD, + BOOL,LPVOID,DWORD); +#define SHRegQueryUSValue WINELIB_NAME_AW(SHRegQueryUSValue) + +LONG WINAPI SHRegWriteUSValueA(HUSKEY,LPCSTR,DWORD,LPVOID,DWORD,DWORD); +LONG WINAPI SHRegWriteUSValueW(HUSKEY,LPCWSTR,DWORD,LPVOID,DWORD,DWORD); +#define SHRegWriteUSValue WINELIB_NAME_AW(SHRegWriteUSValue) + +LONG WINAPI SHRegDeleteUSValueA(HUSKEY,LPCSTR,SHREGDEL_FLAGS); +LONG WINAPI SHRegDeleteUSValueW(HUSKEY,LPCWSTR,SHREGDEL_FLAGS); +#define SHRegDeleteUSValue WINELIB_NAME_AW(SHRegDeleteUSValue) + +LONG WINAPI SHRegDeleteEmptyUSKeyA(HUSKEY,LPCSTR,SHREGDEL_FLAGS); +LONG WINAPI SHRegDeleteEmptyUSKeyW(HUSKEY,LPCWSTR,SHREGDEL_FLAGS); +#define SHRegDeleteEmptyUSKey WINELIB_NAME_AW(SHRegDeleteEmptyUSKey) + +LONG WINAPI SHRegEnumUSKeyA(HUSKEY,DWORD,LPSTR,LPDWORD,SHREGENUM_FLAGS); +LONG WINAPI SHRegEnumUSKeyW(HUSKEY,DWORD,LPWSTR,LPDWORD,SHREGENUM_FLAGS); +#define SHRegEnumUSKey WINELIB_NAME_AW(SHRegEnumUSKey) + +LONG WINAPI SHRegEnumUSValueA(HUSKEY,DWORD,LPSTR,LPDWORD,LPDWORD, + LPVOID,LPDWORD,SHREGENUM_FLAGS); +LONG WINAPI SHRegEnumUSValueW(HUSKEY,DWORD,LPWSTR,LPDWORD,LPDWORD, + LPVOID,LPDWORD,SHREGENUM_FLAGS); +#define SHRegEnumUSValue WINELIB_NAME_AW(SHRegEnumUSValue) + +LONG WINAPI SHRegQueryInfoUSKeyA(HUSKEY,LPDWORD,LPDWORD,LPDWORD, + LPDWORD,SHREGENUM_FLAGS); +LONG WINAPI SHRegQueryInfoUSKeyW(HUSKEY,LPDWORD,LPDWORD,LPDWORD, + LPDWORD,SHREGENUM_FLAGS); +#define SHRegQueryInfoUSKey WINELIB_NAME_AW(SHRegQueryInfoUSKey) + +LONG WINAPI SHRegCloseUSKey(HUSKEY); + +LONG WINAPI SHRegGetUSValueA(LPCSTR,LPCSTR,LPDWORD,LPVOID,LPDWORD, + BOOL,LPVOID,DWORD); +LONG WINAPI SHRegGetUSValueW(LPCWSTR,LPCWSTR,LPDWORD,LPVOID,LPDWORD, + BOOL,LPVOID,DWORD); +#define SHRegGetUSValue WINELIB_NAME_AW(SHRegGetUSValue) + +LONG WINAPI SHRegSetUSValueA(LPCSTR,LPCSTR,DWORD,LPVOID,DWORD,DWORD); +LONG WINAPI SHRegSetUSValueW(LPCWSTR,LPCWSTR,DWORD,LPVOID,DWORD,DWORD); +#define SHRegSetUSValue WINELIB_NAME_AW(SHRegSetUSValue) + +BOOL WINAPI SHRegGetBoolUSValueA(LPCSTR,LPCSTR,BOOL,BOOL); +BOOL WINAPI SHRegGetBoolUSValueW(LPCWSTR,LPCWSTR,BOOL,BOOL); +#define SHRegGetBoolUSValue WINELIB_NAME_AW(SHRegGetBoolUSValue) + +#endif /* NO_SHLWAPI_REG */ + + +/* Path functions */ +#ifndef NO_SHLWAPI_PATH + +/* GetPathCharType return flags */ +#define GCT_INVALID 0x0 +#define GCT_LFNCHAR 0x1 +#define GCT_SHORTCHAR 0x2 +#define GCT_WILD 0x4 +#define GCT_SEPARATOR 0x8 + +LPSTR WINAPI PathAddBackslashA(LPSTR); +LPWSTR WINAPI PathAddBackslashW(LPWSTR); +#define PathAddBackslash WINELIB_NAME_AW(PathAddBackslash) + +BOOL WINAPI PathAddExtensionA(LPSTR,LPCSTR); +BOOL WINAPI PathAddExtensionW(LPWSTR,LPCWSTR); +#define PathAddExtension WINELIB_NAME_AW(PathAddExtension) + +BOOL WINAPI PathAppendA(LPSTR,LPCSTR); +BOOL WINAPI PathAppendW(LPWSTR,LPCWSTR); +#define PathAppend WINELIB_NAME_AW(PathAppend) + +LPSTR WINAPI PathBuildRootA(LPSTR,int); +LPWSTR WINAPI PathBuildRootW(LPWSTR,int); +#define PathBuildRoot WINELIB_NAME_AW(PathBuiltRoot) + +BOOL WINAPI PathCanonicalizeA(LPSTR,LPCSTR); +BOOL WINAPI PathCanonicalizeW(LPWSTR,LPCWSTR); +#define PathCanonicalize WINELIB_NAME_AW(PathCanonicalize) + +LPSTR WINAPI PathCombineA(LPSTR,LPCSTR,LPCSTR); +LPWSTR WINAPI PathCombineW(LPWSTR,LPCWSTR,LPCWSTR); +#define PathCombine WINELIB_NAME_AW(PathCombine) + +BOOL WINAPI PathCompactPathA(HDC,LPSTR,UINT); +BOOL WINAPI PathCompactPathW(HDC,LPWSTR,UINT); +#define PathCompactPath WINELIB_NAME_AW(PathCompactPath) + +BOOL WINAPI PathCompactPathExA(LPSTR,LPCSTR,UINT,DWORD); +BOOL WINAPI PathCompactPathExW(LPWSTR,LPCWSTR,UINT,DWORD); +#define PathCompactPathEx WINELIB_NAME_AW(PathCompactPathEx) + +int WINAPI PathCommonPrefixA(LPCSTR,LPCSTR,LPSTR); +int WINAPI PathCommonPrefixW(LPCWSTR,LPCWSTR,LPWSTR); +#define PathCommonPrefix WINELIB_NAME_AW(PathCommonPrefix) + +BOOL WINAPI PathFileExistsA(LPCSTR); +BOOL WINAPI PathFileExistsW(LPCWSTR); +#define PathFileExists WINELIB_NAME_AW(PathFileExists) + +LPSTR WINAPI PathFindExtensionA(LPCSTR); +LPWSTR WINAPI PathFindExtensionW(LPCWSTR); +#define PathFindExtension WINELIB_NAME_AW(PathFindExtension) + +LPSTR WINAPI PathFindFileNameA(LPCSTR); +LPWSTR WINAPI PathFindFileNameW(LPCWSTR); +#define PathFindFileName WINELIB_NAME_AW(PathFindFileName) + +LPSTR WINAPI PathFindNextComponentA(LPCSTR); +LPWSTR WINAPI PathFindNextComponentW(LPCWSTR); +#define PathFindNextComponent WINELIB_NAME_AW(PathFindNextComponent) + +BOOL WINAPI PathFindOnPathA(LPSTR,LPCSTR*); +BOOL WINAPI PathFindOnPathW(LPWSTR,LPCWSTR*); +#define PathFindOnPath WINELIB_NAME_AW(PathFindOnPath) + +LPSTR WINAPI PathGetArgsA(LPCSTR); +LPWSTR WINAPI PathGetArgsW(LPCWSTR); +#define PathGetArgs WINELIB_NAME_AW(PathGetArgs) + +UINT WINAPI PathGetCharTypeA(UCHAR); +UINT WINAPI PathGetCharTypeW(WCHAR); +#define PathGetCharType WINELIB_NAME_AW(PathGetCharType) + +int WINAPI PathGetDriveNumberA(LPCSTR); +int WINAPI PathGetDriveNumberW(LPCWSTR); +#define PathGetDriveNumber WINELIB_NAME_AW(PathGetDriveNumber) + +BOOL WINAPI PathIsDirectoryA(LPCSTR); +BOOL WINAPI PathIsDirectoryW(LPCWSTR); +#define PathIsDirectory WINELIB_NAME_AW(PathIsDirectory) + +BOOL WINAPI PathIsDirectoryEmptyA(LPCSTR); +BOOL WINAPI PathIsDirectoryEmptyW(LPCWSTR); +#define PathIsDirectoryEmpty WINELIB_NAME_AW(PathIsDirectoryEmpty) + +BOOL WINAPI PathIsFileSpecA(LPCSTR); +BOOL WINAPI PathIsFileSpecW(LPCWSTR); +#define PathIsFileSpec WINELIB_NAME_AW(PathIsFileSpec); + +BOOL WINAPI PathIsPrefixA(LPCSTR,LPCSTR); +BOOL WINAPI PathIsPrefixW(LPCWSTR,LPCWSTR); +#define PathIsPrefix WINELIB_NAME_AW(PathIsPrefix) + +BOOL WINAPI PathIsRelativeA(LPCSTR); +BOOL WINAPI PathIsRelativeW(LPCWSTR); +#define PathIsRelative WINELIB_NAME_AW(PathIsRelative) + +BOOL WINAPI PathIsRootA(LPCSTR); +BOOL WINAPI PathIsRootW(LPCWSTR); +#define PathIsRoot WINELIB_NAME_AW(PathIsRoot) + +BOOL WINAPI PathIsSameRootA(LPCSTR,LPCSTR); +BOOL WINAPI PathIsSameRootW(LPCWSTR,LPCWSTR); +#define PathIsSameRoot WINELIB_NAME_AW(PathIsSameRoot) + +BOOL WINAPI PathIsUNCA(LPCSTR); +BOOL WINAPI PathIsUNCW(LPCWSTR); +#define PathIsUNC WINELIB_NAME_AW(PathIsUNC) + +BOOL WINAPI PathIsUNCServerA(LPCSTR); +BOOL WINAPI PathIsUNCServerW(LPCWSTR); +#define PathIsUNCServer WINELIB_NAME_AW(PathIsUNCServer) + +BOOL WINAPI PathIsUNCServerShareA(LPCSTR); +BOOL WINAPI PathIsUNCServerShareW(LPCWSTR); +#define PathIsUNCServerShare WINELIB_NAME_AW(PathIsUNCServerShare) + +BOOL WINAPI PathIsContentTypeA(LPCSTR,LPCSTR); +BOOL WINAPI PathIsContentTypeW(LPCWSTR,LPCWSTR); +#define PathIsContentType WINELIB_NAME_AW(PathIsContentType) + +BOOL WINAPI PathIsURLA(LPCSTR); +BOOL WINAPI PathIsURLW(LPCWSTR); +#define PathIsURL WINELIB_NAME_AW(PathIsURL) + +BOOL WINAPI PathMakePrettyA(LPSTR); +BOOL WINAPI PathMakePrettyW(LPWSTR); +#define PathMakePretty WINELIB_NAME_AW(PathMakePretty) + +BOOL WINAPI PathMatchSpecA(LPCSTR,LPCSTR); +BOOL WINAPI PathMatchSpecW(LPCWSTR,LPCWSTR); +#define PathMatchSpec WINELIB_NAME_AW(PathMatchSpec) + +int WINAPI PathParseIconLocationA(LPSTR); +int WINAPI PathParseIconLocationW(LPWSTR); +#define PathParseIconLocation WINELIB_NAME_AW(PathParseIconLocation) + +VOID WINAPI PathQuoteSpacesA(LPSTR); +VOID WINAPI PathQuoteSpacesW(LPWSTR); +#define PathQuoteSpaces WINELIB_NAME_AW(PathQuoteSpaces) + +BOOL WINAPI PathRelativePathToA(LPSTR,LPCSTR,DWORD,LPCSTR,DWORD); +BOOL WINAPI PathRelativePathToW(LPWSTR,LPCWSTR,DWORD,LPCWSTR,DWORD); +#define PathRelativePathTo WINELIB_NAME_AW(PathRelativePathTo) + +VOID WINAPI PathRemoveArgsA(LPSTR); +VOID WINAPI PathRemoveArgsW(LPWSTR); +#define PathRemoveArgs WINELIB_NAME_AW(PathRemoveArgs) + +LPSTR WINAPI PathRemoveBackslashA(LPSTR); +LPWSTR WINAPI PathRemoveBackslashW(LPWSTR); +#define PathRemoveBackslash WINELIB_NAME_AW(PathRemoveBackslash) + +VOID WINAPI PathRemoveBlanksA(LPSTR); +VOID WINAPI PathRemoveBlanksW(LPWSTR); +#define PathRemoveBlanks WINELIB_NAME_AW(PathRemoveBlanks) + +VOID WINAPI PathRemoveExtensionA(LPSTR); +VOID WINAPI PathRemoveExtensionW(LPWSTR); +#define PathRemoveExtension WINELIB_NAME_AW(PathRemoveExtension) + +BOOL WINAPI PathRemoveFileSpecA(LPSTR); +BOOL WINAPI PathRemoveFileSpecW(LPWSTR); +#define PathRemoveFileSpec WINELIB_NAME_AW(PathRemoveFileSpec) + +BOOL WINAPI PathRenameExtensionA(LPSTR,LPCSTR); +BOOL WINAPI PathRenameExtensionW(LPWSTR,LPCWSTR); +#define PathRenameExtension WINELIB_NAME_AW(PathRenameExtension) + +BOOL WINAPI PathSearchAndQualifyA(LPCSTR,LPSTR,UINT); +BOOL WINAPI PathSearchAndQualifyW(LPCWSTR,LPWSTR,UINT); +#define PathSearchAndQualify WINELIB_NAME_AW(PathSearchAndQualify) + +VOID WINAPI PathSetDlgItemPathA(HWND,int,LPCSTR); +VOID WINAPI PathSetDlgItemPathW(HWND,int,LPCWSTR); +#define PathSetDlgItemPath WINELIB_NAME_AW(PathSetDlgItemPath) + +LPSTR WINAPI PathSkipRootA(LPCSTR); +LPWSTR WINAPI PathSkipRootW(LPCWSTR); +#define PathSkipRoot WINELIB_NAME_AW(PathSkipRoot) + +VOID WINAPI PathStripPathA(LPSTR); +VOID WINAPI PathStripPathW(LPWSTR); +#define PathStripPath WINELIB_NAME_AW(PathStripPath) + +BOOL WINAPI PathStripToRootA(LPSTR); +BOOL WINAPI PathStripToRootW(LPWSTR); +#define PathStripToRoot WINELIB_NAME_AW(PathStripToRoot) + +VOID WINAPI PathUnquoteSpacesA(LPSTR); +VOID WINAPI PathUnquoteSpacesW(LPWSTR); +#define PathUnquoteSpaces WINELIB_NAME_AW(PathUnquoteSpaces) + +BOOL WINAPI PathMakeSystemFolderA(LPCSTR); +BOOL WINAPI PathMakeSystemFolderW(LPCWSTR); +#define PathMakeSystemFolder WINELIB_NAME_AW(PathMakeSystemFolder) + +BOOL WINAPI PathUnmakeSystemFolderA(LPCSTR); +BOOL WINAPI PathUnmakeSystemFolderW(LPCWSTR); +#define PathUnmakeSystemFolder WINELIB_NAME_AW(PathUnmakeSystemFolder) + +BOOL WINAPI PathIsSystemFolderA(LPCSTR,DWORD); +BOOL WINAPI PathIsSystemFolderW(LPCWSTR,DWORD); +#define PathIsSystemFolder WINELIB_NAME_AW(PathIsSystemFolder) + +BOOL WINAPI PathIsNetworkPathA(LPCSTR); +BOOL WINAPI PathIsNetworkPathW(LPCWSTR); +#define PathIsNetworkPath WINELIB_NAME_AW(PathIsNetworkPath) + +BOOL WINAPI PathIsLFNFileSpecA(LPCSTR); +BOOL WINAPI PathIsLFNFileSpecW(LPCWSTR); +#define PathIsLFNFileSpec WINELIB_NAME_AW(PathIsLFNFileSpec) + +int WINAPI PathFindSuffixArrayA(LPCSTR,LPCSTR *,int); +int WINAPI PathFindSuffixArrayW(LPCWSTR,LPCWSTR *,int); +#define PathFindSuffixArray WINELIB_NAME_AW(PathFindSuffixArray) + +VOID WINAPI PathUndecorateA(LPSTR); +VOID WINAPI PathUndecorateW(LPWSTR); +#define PathUndecorate WINELIB_NAME_AW(PathUndecorate) + +BOOL WINAPI PathUnExpandEnvStringsA(LPCSTR,LPSTR,UINT); +BOOL WINAPI PathUnExpandEnvStringsW(LPCWSTR,LPWSTR,UINT); +#define PathUnExpandEnvStrings WINELIB_NAME_AW(PathUnExpandEnvStrings) + +/* Url functions */ + +/* These are used by UrlGetPart routine */ +typedef enum { + URL_PART_NONE = 0, + URL_PART_SCHEME = 1, + URL_PART_HOSTNAME, + URL_PART_USERNAME, + URL_PART_PASSWORD, + URL_PART_PORT, + URL_PART_QUERY +} URL_PART; + +#define URL_PARTFLAG_KEEPSCHEME 0x00000001 + +/* These are used by the UrlIs... routines */ +typedef enum { + URLIS_URL, + URLIS_OPAQUE, + URLIS_NOHISTORY, + URLIS_FILEURL, + URLIS_APPLIABLE, + URLIS_DIRECTORY, + URLIS_HASQUERY +} URLIS; + +/* This is used by the UrlApplyScheme... routines */ +#define URL_APPLY_FORCEAPPLY 0x00000008 +#define URL_APPLY_GUESSFILE 0x00000004 +#define URL_APPLY_GUESSSCHEME 0x00000002 +#define URL_APPLY_DEFAULT 0x00000001 + +/* The following are used by UrlEscape..., UrlUnEscape..., + * UrlCanonicalize..., and UrlCombine... routines + */ +#define URL_WININET_COMPATIBILITY 0x80000000 +#define URL_PLUGGABLE_PROTOCOL 0x40000000 +#define URL_ESCAPE_UNSAFE 0x20000000 +#define URL_UNESCAPE 0x10000000 + +#define URL_DONT_SIMPLIFY 0x08000000 +#define URL_NO_META URL_DONT_SIMPLIFY +#define URL_ESCAPE_SPACES_ONLY 0x04000000 +#define URL_DONT_ESCAPE_EXTRA_INFO 0x02000000 +#define URL_DONT_UNESCAPE_EXTRA_INFO URL_DONT_ESCAPE_EXTRA_INFO +#define URL_BROWSER_MODE URL_DONT_ESCAPE_EXTRA_INFO + +#define URL_INTERNAL_PATH 0x00800000 /* Will escape #'s in paths */ +#define URL_UNESCAPE_HIGH_ANSI_ONLY 0x00400000 +#define URL_CONVERT_IF_DOSPATH 0x00200000 +#define URL_UNESCAPE_INPLACE 0x00100000 + +#define URL_FILE_USE_PATHURL 0x00010000 + +#define URL_ESCAPE_SEGMENT_ONLY 0x00002000 +#define URL_ESCAPE_PERCENT 0x00001000 + +HRESULT WINAPI UrlApplySchemeA(LPCSTR,LPSTR,LPDWORD,DWORD); +HRESULT WINAPI UrlApplySchemeW(LPCWSTR,LPWSTR,LPDWORD,DWORD); +#define UrlApplyScheme WINELIB_NAME_AW(UrlApplyScheme) + +HRESULT WINAPI UrlCanonicalizeA(LPCSTR,LPSTR,LPDWORD,DWORD); +HRESULT WINAPI UrlCanonicalizeW(LPCWSTR,LPWSTR,LPDWORD,DWORD); +#define UrlCanonicalize WINELIB_NAME_AW(UrlCanoncalize) + +HRESULT WINAPI UrlCombineA(LPCSTR,LPCSTR,LPSTR,LPDWORD,DWORD); +HRESULT WINAPI UrlCombineW(LPCWSTR,LPCWSTR,LPWSTR,LPDWORD,DWORD); +#define UrlCombine WINELIB_NAME_AW(UrlCombine) + +INT WINAPI UrlCompareA(LPCSTR,LPCSTR,BOOL); +INT WINAPI UrlCompareW(LPCWSTR,LPCWSTR,BOOL); +#define UrlCompare WINELIB_NAME_AW(UrlCompare) + +HRESULT WINAPI UrlEscapeA(LPCSTR,LPSTR,LPDWORD,DWORD); +HRESULT WINAPI UrlEscapeW(LPCWSTR,LPWSTR,LPDWORD,DWORD); +#define UrlEscape WINELIB_NAME_AW(UrlEscape) + +#define UrlEscapeSpacesA(x,y,z) UrlCanonicalizeA(x, y, z, \ + URL_DONT_ESCAPE_EXTRA_INFO|URL_ESCAPE_SPACES_ONLY) +#define UrlEscapeSpacesW(x,y,z) UrlCanonicalizeW(x, y, z, \ + URL_DONT_ESCAPE_EXTRA_INFO|URL_ESCAPE_SPACES_ONLY) +#define UrlEscapeSpaces WINELIB_NAME_AW(UrlEscapeSpaces) + +LPCSTR WINAPI UrlGetLocationA(LPCSTR); +LPCWSTR WINAPI UrlGetLocationW(LPCWSTR); +#define UrlGetLocation WINELIB_NAME_AW(UrlGetLocation) + +HRESULT WINAPI UrlGetPartA(LPCSTR,LPSTR,LPDWORD,DWORD,DWORD); +HRESULT WINAPI UrlGetPartW(LPCWSTR,LPWSTR,LPDWORD,DWORD,DWORD); +#define UrlGetPart WINELIB_NAME_AW(UrlGetPart) + +BOOL WINAPI HashData(const unsigned char *,INT,unsigned char *lpDest,INT); + +HRESULT WINAPI UrlHashA(LPCSTR,unsigned char *,INT); +HRESULT WINAPI UrlHashW(LPCWSTR,unsigned char *,INT); +#define UrlHash WINELIB_NAME_AW(UrlHash) + +BOOL WINAPI UrlIsA(LPCSTR,URLIS); +BOOL WINAPI UrlIsW(LPCWSTR,URLIS); +#define UrlIs WINELIB_NAME_AW(UrlIs) + +BOOL WINAPI UrlIsNoHistoryA(LPCSTR); +BOOL WINAPI UrlIsNoHistoryW(LPCWSTR); +#define UrlIsNoHistory WINELIB_NAME_AW(UrlIsNoHistory) + +BOOL WINAPI UrlIsOpaqueA(LPCSTR); +BOOL WINAPI UrlIsOpaqueW(LPCWSTR); +#define UrlIsOpaque WINELIB_NAME_AW(UrlIsOpaque) + +#define UrlIsFileUrlA(x) UrlIsA(x, URLIS_FILEURL) +#define UrlIsFileUrlW(y) UrlIsW(x, URLIS_FILEURL) +#define UrlIsFileUrl WINELIB_NAME_AW(UrlIsFileUrl) + +HRESULT WINAPI UrlUnescapeA(LPCSTR,LPSTR,LPDWORD,DWORD); +HRESULT WINAPI UrlUnescapeW(LPCWSTR,LPWSTR,LPDWORD,DWORD); +#define UrlUnescape WINELIB_AW_NAME(UrlUnescape) + +#define UrlUnescapeInPlaceA(x,y) UrlUnescapeA(x, NULL, NULL, \ + y | URL_UNESCAPE_INPLACE) +#define UrlUnescapeInPlaceW(x,y) UrlUnescapeW(x, NULL, NULL, \ + y | URL_UNESCAPE_INPLACE) +#define UrlUnescapeInPlace WINELIB_AW_NAME(UrlUnescapeInPlace) + +HRESULT WINAPI UrlCreateFromPathA(LPCSTR,LPSTR,LPDWORD,DWORD); +HRESULT WINAPI UrlCreateFromPathW(LPCWSTR,LPWSTR,LPDWORD,DWORD); +#define UrlCreateFromPath WINELIB_AW_NAME(UrlCreateFromPath) + +#endif /* NO_SHLWAPI_PATH */ + + +/* String functions */ +#ifndef NO_SHLWAPI_STRFCNS + +/* StrToIntEx flags */ +#define STIF_DEFAULT 0x0L +#define STIF_SUPPORT_HEX 0x1L + +BOOL WINAPI ChrCmpIA (WORD w1, WORD w2); +BOOL WINAPI ChrCmpIW (WCHAR w1, WCHAR w2); +#define ChrCmpI WINELIB_NAME_AW(ChrCmpI) + +INT WINAPI StrCSpnA(LPCSTR,LPCSTR); +INT WINAPI StrCSpnW(LPCWSTR,LPCWSTR); +#define StrCSpn WINELIB_NAME_AW(StrCSpn) + +INT WINAPI StrCSpnIA(LPCSTR,LPCSTR); +INT WINAPI StrCSpnIW(LPCWSTR,LPCWSTR); +#define StrCSpnI WINELIB_NAME_AW(StrCSpnI) + +#define StrCatA lstrcatA +LPWSTR WINAPI StrCatW(LPWSTR,LPCWSTR); +#define StrCat WINELIB_NAME_AW(StrCat) + +LPSTR WINAPI StrCatBuffA(LPSTR,LPCSTR,INT); +LPWSTR WINAPI StrCatBuffW(LPWSTR,LPCWSTR,INT); +#define StrCatBuff WINELIB_NAME_AW(StrCatBuff) + +LPSTR WINAPI StrChrA(LPCSTR,WORD); +LPWSTR WINAPI StrChrW(LPCWSTR,WCHAR); +#define StrChr WINELIB_NAME_AW(StrChr) + +LPSTR WINAPI StrChrIA(LPCSTR,CHAR); +LPWSTR WINAPI StrChrIW(LPCWSTR,WCHAR); +#define StrChrI WINELIB_NAME_AW(StrChrI) + +#define StrCmpA lstrcmpA +int WINAPI StrCmpW(LPCWSTR,LPCWSTR); +#define StrCmp WINELIB_NAME_AW(StrCmp) + +#define StrCmpIA lstrcmpiA +int WINAPI StrCmpIW(LPCWSTR,LPCWSTR); +#define StrCmpI WINELIB_NAME_AW(StrCmpI) + +#define StrCpyA lstrcpyA +LPWSTR WINAPI StrCpyW(LPWSTR,LPCWSTR); +#define StrCpy WINELIB_NAME_AW(StrCpy) + +//#define StrCpyNA lstrcpynA +LPWSTR WINAPI StrCpyNW(LPWSTR,LPCWSTR,int); +#define StrCpyN WINELIB_NAME_AW(StrCpyN) +#define StrNCpy WINELIB_NAME_AW(StrCpyN) + +INT WINAPI StrCmpNA(LPCSTR,LPCSTR,INT); +INT WINAPI StrCmpNW(LPCWSTR,LPCWSTR,INT); +#define StrCmpN WINELIB_NAME_AW(StrCmpN) +#define StrNCmp WINELIB_NAME_AW(StrCmpN) + +INT WINAPI StrCmpNIA(LPCSTR,LPCSTR,INT); +INT WINAPI StrCmpNIW(LPCWSTR,LPCWSTR,INT); +#define StrCmpNI WINELIB_NAME_AW(StrCmpNI) +#define StrNCmpI WINELIB_NAME_AW(StrCmpNI) + +LPSTR WINAPI StrDupA(LPCSTR); +LPWSTR WINAPI StrDupW(LPCWSTR); +#define StrDup WINELIB_NAME_AW(StrDup) + +LPSTR WINAPI StrFormatByteSizeA (DWORD,LPSTR,UINT); +LPWSTR WINAPI StrFormatByteSizeW (DWORD,LPWSTR,UINT); +#define StrFormatByteSize WINELIB_NAME_AW(StrFormatByteSize) + +int WINAPI StrFromTimeIntervalA(LPSTR,UINT,DWORD,int); +int WINAPI StrFromTimeIntervalW(LPWSTR,UINT,DWORD,int); +#define StrFromTimeInterval WINELIB_NAME_AW(StrFromTimeInterval) + +BOOL WINAPI StrIsIntlEqualA(BOOL,LPCSTR,LPCSTR,int); +BOOL WINAPI StrIsIntlEqualW(BOOL,LPCWSTR,LPCWSTR,int); +#define StrIsIntlEqual WINELIB_NAME_AW(StrIsIntlEqual) + +#define StrIntlEqNA(a,b,c) StrIsIntlEqualA(TRUE,a,b,c) +#define StrIntlEqNW(a,b,c) StrIsIntlEqualW(TRUE,a,b,c) + +#define StrIntlEqNIA(a,b,c) StrIsIntlEqualA(FALSE,a,b,c) +#define StrIntlEqNIW(a,b,c) StrIsIntlEqualW(FALSE,a,b,c) + +LPSTR WINAPI StrNCatA(LPSTR,LPCSTR,int); +LPWSTR WINAPI StrNCatW(LPWSTR,LPCWSTR,int); +#define StrNCat WINELIB_NAME_AW(StrNCat) +#define StrCatN WINELIB_NAME_AW(StrNCat) + +LPSTR WINAPI StrPBrkA(LPCSTR,LPCSTR); +LPWSTR WINAPI StrPBrkW(LPCWSTR,LPCWSTR); +#define StrPBrk WINELIB_NAME_AW(StrPBrk) + +LPSTR WINAPI StrRChrA(LPCSTR,LPCSTR,WORD); +LPWSTR WINAPI StrRChrW(LPCWSTR,LPCWSTR,WORD); +#define StrRChr WINELIB_NAME_AW(StrRChr) + +LPSTR WINAPI StrRChrIA(LPCSTR,LPCSTR,WORD); +LPWSTR WINAPI StrRChrIW(LPCWSTR,LPCWSTR,WORD); +#define StrRChrI WINELIB_NAME_AW(StrRChrI) + +LPSTR WINAPI StrRStrIA(LPCSTR,LPCSTR,LPCSTR); +LPWSTR WINAPI StrRStrIW(LPCWSTR,LPCWSTR,LPCWSTR); +#define StrRStrI WINELIB_NAME_AW(StrRStrI) + +int WINAPI StrSpnA(LPCSTR,LPCSTR); +int WINAPI StrSpnW(LPCWSTR,LPCWSTR); +#define StrSpn WINELIB_NAME_AW(StrSpn) + +LPSTR WINAPI StrStrA(LPCSTR,LPCSTR); +LPWSTR WINAPI StrStrW(LPCWSTR,LPCWSTR); +#define StrStr WINELIB_NAME_AW(StrStr) + +LPSTR WINAPI StrStrIA(LPCSTR,LPCSTR); +LPWSTR WINAPI StrStrIW(LPCWSTR,LPCWSTR); +#define StrStrI WINELIB_NAME_AW(StrStrI) + +int WINAPI StrToIntA(LPCSTR); +int WINAPI StrToIntW(LPCWSTR); +#define StrToInt WINELIB_NAME_AW(StrToInt) +#define StrToLong WINELIB_NAME_AW(StrToInt) + +BOOL WINAPI StrToIntExA(LPCSTR,DWORD,int*); +BOOL WINAPI StrToIntExW(LPCWSTR,DWORD,int*); +#define StrToIntEx WINELIB_NAME_AW(StrToIntEx) + +BOOL WINAPI StrTrimA(LPSTR,LPCSTR); +BOOL WINAPI StrTrimW(LPWSTR,LPCWSTR); +#define StrTrim WINELIB_NAME_AW(StrTrim) + +INT WINAPI wvnsprintfA(LPSTR lpOut, INT cchLimitIn, LPCSTR lpFmt, va_list arglist); +INT WINAPI wvnsprintfW(LPWSTR lpOut, INT cchLimitIn, LPCWSTR lpFmt, va_list arglist); +#define wvnsprintf WINELIB_NAME_AW(wvnsprintf) + +INT WINAPIV wnsprintfA(LPSTR lpOut, INT cchLimitIn, LPCSTR lpFmt, ...); +INT WINAPIV wnsprintfW(LPWSTR lpOut, INT cchLimitIn, LPCWSTR lpFmt, ...); +#define wnsprintf WINELIB_NAME_AW(wnsprintf) + +/* Undocumented */ +struct _STRRET; +struct _ITEMIDLIST; +HRESULT WINAPI StrRetToBufA(struct _STRRET *src, const struct _ITEMIDLIST *pidl, LPSTR dest, DWORD len); +HRESULT WINAPI StrRetToBufW(struct _STRRET *src, const struct _ITEMIDLIST *pidl, LPWSTR dest, DWORD len); +#define StrRetToBuf WINELIB_NAME_AW(StrRetToBuf) + +#endif /* NO_SHLWAPI_STRFCNS */ + + +/* GDI functions */ +#ifndef NO_SHLWAPI_GDI + +HPALETTE WINAPI SHCreateShellPalette(HDC); + +COLORREF WINAPI ColorHLSToRGB(WORD,WORD,WORD); + +COLORREF WINAPI ColorAdjustLuma(COLORREF,int,BOOL); + +VOID WINAPI ColorRGBToHLS(COLORREF,LPWORD,LPWORD,LPWORD); + +#endif /* NO_SHLWAPI_GDI */ + + +/* Stream functions */ +#if !defined(NO_SHLWAPI_STREAM) && defined(IStream_IMETHODS) + +IStream * WINAPI SHOpenRegStreamA(HKEY,LPCSTR,LPCSTR,DWORD); +IStream * WINAPI SHOpenRegStreamW(HKEY,LPCWSTR,LPCWSTR,DWORD); +#define SHOpenRegStream WINELIB_NAME_AW(SHOpenRegStream) + +IStream * WINAPI SHOpenRegStream2A(HKEY,LPCSTR,LPCSTR,DWORD); +IStream * WINAPI SHOpenRegStream2W(HKEY,LPCWSTR,LPCWSTR,DWORD); +#define SHOpenRegStream2 WINELIB_NAME_AW(SHOpenRegStream2) + +#endif /* NO_SHLWAPI_STREAM */ + + +/* Version Information */ + +typedef struct _DllVersionInfo { + DWORD cbSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformID; +} DLLVERSIONINFO; + +#define DLLVER_PLATFORM_WINDOWS 0x01 /* Win9x */ +#define DLLVER_PLATFORM_NT 0x02 /* WinNT */ + +typedef HRESULT (CALLBACK *DLLGETVERSIONPROC)(DLLVERSIONINFO *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* __WINE_SHLWAPI_H */ diff --git a/lib/shell32/misc/stubs.c b/lib/shell32/misc/stubs.c new file mode 100644 index 0000000..461e363 --- /dev/null +++ b/lib/shell32/misc/stubs.c @@ -0,0 +1,2615 @@ +/* + * ReactOS shell32 - + * + * stubs.c + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/shell32/misc/stubs.c + * PURPOSE: Stubbed exports + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + */ + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "shell32.h" +#include + +#ifdef __GNUC__ +void* _alloca(size_t); +#endif + +#define NO_SHLWAPI_STREAM +#include "shlwapi.h" +//#include +//#include + +#define HDROP HANDLE +#define LPSHELLEXECUTEINFOA int* +#define LPSHELLEXECUTEINFOW int* +#define PNOTIFYICONDATAA int* +#define PNOTIFYICONDATAW int* +#define PAPPBARDATA int* +#define LPSHFILEOPSTRUCTA int* +#define LPSHFILEOPSTRUCTW int* +#define LPSHQUERYRBINFO int* +#define SHFILEINFOA int +#define SHFILEINFOW int + + +#define NDEBUG +//#include + +typedef struct _SHITEMID { + USHORT cb; + BYTE abID[1]; +} SHITEMID, * LPSHITEMID; +typedef const SHITEMID * LPCSHITEMID; + +typedef struct _ITEMIDLIST { + SHITEMID mkid; +} ITEMIDLIST, * LPITEMIDLIST; +typedef const ITEMIDLIST * LPCITEMIDLIST; + +int CALLBACK BrowseCallbackProc( + HWND hwnd, + UINT uMsg, + LPARAM lParam, + LPARAM lpData + ); + +typedef int (*BFFCALLBACK)(HWND, UINT, LPARAM, LPARAM); + +typedef struct _browseinfo { + HWND hwndOwner; + LPCITEMIDLIST pidlRoot; + LPTSTR pszDisplayName; + LPCTSTR lpszTitle; + UINT ulFlags; + BFFCALLBACK lpfn; + LPARAM lParam; + int iImage; +} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO; + + + +#undef DragQueryFile +#undef ShellExecute + +#define STUB \ + do \ + { \ + DbgPrint ("%s(%d):%s not implemented\n", __FILE__, __LINE__, __FUNCTION__); \ + } \ + while (0) + + + +VOID +WINAPI +SHChangeNotifyRegister(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +SHChangeNotifyDeregister(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHChangeNotifyUpdateEntryList(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +PifMgr_OpenProperties(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +PifMgr_GetProperties(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +PifMgr_SetProperties(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +PifMgr_CloseProperties(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ILGetDisplayName(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ILFindLastID(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILRemoveLastID(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILClone(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILCloneFirst(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILGlobalClone(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILIsEqual(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ILIsParent(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +ILFindChild(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ILCombine(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ILLoadFromStream(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ILSaveToStream(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHILCreateFromPath(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +BOOL WINAPI +PathIsRootA(LPCSTR path) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathIsRootW(LPCWSTR path) +{ + STUB; + return FALSE; +} + +LPSTR WINAPI +PathBuildRootA(LPSTR Unknown1, int Unknown2) +{ + STUB; + return 0; +} + +LPWSTR WINAPI +PathBuildRootW(LPWSTR Unknown1, int Unknown2) +{ + STUB; + return 0; +} + +BOOL WINAPI +PathAddExtensionA(LPSTR Unknown1, LPCSTR Unknown2) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathAddExtensionW(LPWSTR Unknown1, LPCWSTR Unknown2) +{ + STUB; + return FALSE; +} + + +LPSTR WINAPI +PathFindExtensionA(LPCSTR Unknown1) +{ + STUB; + return 0; +} + +LPWSTR WINAPI +PathFindExtensionW(LPCWSTR Unknown1) +{ + STUB; + return 0; +} + +LPSTR WINAPI +PathAddBackslashA(LPSTR Unknown1) +{ + STUB; + return 0; +} + +LPWSTR WINAPI +PathAddBackslashW(LPWSTR Unknown1) +{ + STUB; + return 0; +} + +VOID WINAPI +PathRemoveBlanksA(LPSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathRemoveBlanksW(LPWSTR Unknown1) +{ + STUB; +} + +LPSTR WINAPI +PathFindFileNameA(LPCSTR Unknown1) +{ + STUB; + return 0; +} + +LPWSTR WINAPI +PathFindFileNameW(LPCWSTR Unknown1) +{ + STUB; + return 0; +} + +BOOL WINAPI +PathRemoveFileSpecA(LPSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathRemoveFileSpecW(LPWSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathAppendA(LPSTR Unknown1, LPCSTR Unknown2) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathAppendW(LPWSTR Unknown1, LPCWSTR Unknown2) +{ + STUB; + return FALSE; +} + +LPSTR WINAPI +PathCombineA(LPSTR Unknown1, LPCSTR Unknown2, LPCSTR Unknown3) +{ + STUB; + return 0; +} + +LPWSTR WINAPI +PathCombineW(LPWSTR Unknown1, LPCWSTR Unknown2, LPCWSTR Unknown3) +{ + STUB; + return 0; +} + +VOID WINAPI +PathStripPathA(LPSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathStripPathW(LPWSTR Unknown1) +{ + STUB; +} + +BOOL WINAPI +PathIsUNCA(LPCSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathIsUNCW(LPCWSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathIsRelativeA(LPCSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathIsRelativeW(LPCWSTR Unknown1) +{ + STUB; + return FALSE; +} + +VOID WINAPI +PathIsExeA(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +PathIsExeW(DWORD Unknown1) +{ + STUB; +} + +BOOL WINAPI +PathFileExistsA(LPCSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathFileExistsW(LPCWSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathMatchSpecA(LPCSTR Unknown1, LPCSTR Unknown2) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathMatchSpecW(LPCWSTR Unknown1, LPCWSTR Unknown2) +{ + STUB; + return FALSE; +} + +VOID WINAPI +PathMakeUniqueNameA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +PathMakeUniqueNameW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +PathSetDlgItemPathA(HWND Unknown1, int Unknown2, LPCSTR Unknown3) +{ + STUB; +} + +VOID WINAPI +PathSetDlgItemPathW(HWND Unknown1, int Unknown2, LPCWSTR Unknown3) +{ + STUB; +} + +VOID WINAPI +PathQualifyA(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +PathQualifyW(DWORD Unknown1) +{ + STUB; +} + +BOOL WINAPI +PathStripToRootA(LPSTR Unknown1) +{ + STUB; + return FALSE; +} + +BOOL WINAPI +PathStripToRootW(LPWSTR Unknown1) +{ + STUB; + return FALSE; +} + +VOID WINAPI +PathResolveA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +PathResolveW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +LPSTR WINAPI +PathGetArgsA(LPCSTR Unknown1) +{ + STUB; + return 0; +} + +LPWSTR WINAPI +PathGetArgsW(LPCWSTR Unknown1) +{ + STUB; + return 0; +} + +DWORD WINAPI +DoEnvironmentSubst(LPTSTR pszString, UINT cbSize) +{ + STUB; + return 0; +} + +//VOID WINAPI +//DragAcceptFiles (HWND Unknown1, WINBOOL Unknown2) +VOID WINAPI +DragAcceptFiles(HWND hWnd, BOOL fAccept) +{ + STUB; +} + +VOID WINAPI +PathQuoteSpacesA(LPSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathQuoteSpacesW(LPWSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathUnquoteSpacesA(LPSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathUnquoteSpacesW(LPWSTR Unknown1) +{ + STUB; +} + +int WINAPI +PathGetDriveNumberA(LPCSTR Unknown1) +{ + STUB; + return 0; +} + +int WINAPI +PathGetDriveNumberW(LPCWSTR Unknown1) +{ + STUB; + return 0; +} + +VOID WINAPI +ParseField(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +RestartDialog(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +ExitWindowsDialog(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +RunFileDlg(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +PickIconDlg(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +GetFileNameFromBrowse(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + STUB; +} + +VOID WINAPI +DriveType(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +InvalidateDriveType(VOID) +{ + STUB; +} + +VOID WINAPI +IsNetDrive(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +Shell_MergeMenus(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +SHGetSetSettings(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHGetNetResource(VOID) +{ + STUB; +} + +VOID WINAPI +SHCreateDefClassObject(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +Shell_GetImageList(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +Shell_GetCachedImageIndex(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHShellFolderView_Message(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHCreateStdEnumFmtEtc(VOID) +{ + STUB; +} + +VOID WINAPI +PathYetAnotherMakeUniqueName(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +DragQueryInfo(VOID) +{ + STUB; +} + +VOID WINAPI +SHMapPIDLToSystemImageListIndex(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +OleStrToStrN(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +StrToOleStrN(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +CIDLData_CreateFromIDArray(VOID) +{ + STUB; +} + +VOID WINAPI +SHIsBadInterfacePtr(VOID) +{ + STUB; +} + +VOID WINAPI +SHRegisterDragDrop(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHRevokeDragDrop(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHDoDragDrop(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +SHCloneSpecialIDList(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHFindFiles(VOID) +{ + STUB; +} + +VOID WINAPI +SHFindComputer(VOID) +{ + STUB; +} + +VOID WINAPI +PathGetShortPath(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +Win32CreateDirectory(VOID) +{ + STUB; +} + +VOID WINAPI +Win32RemoveDirectory(VOID) +{ + STUB; +} + +VOID WINAPI +SHLogILFromFSIL(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +StrRetToStrN(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHWaitForFileToOpen(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHGetRealIDL(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SetAppStartingCursor(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHRestricted(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHCoCreateInstance(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +SignalFileOpen(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FileMenu_DeleteAllItems(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FileMenu_DrawItem(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_FindSubMenuByPidl(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_GetLastSelectedItemPidls(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +FileMenu_HandleMenuChar(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_InitMenuPopup(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FileMenu_InsertUsingPidl(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +FileMenu_Invalidate(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FileMenu_MeasureItem(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_ReplaceUsingPidl(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +FileMenu_Create(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +FileMenu_AppendItem(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +FileMenu_TrackPopupMenuEx(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +FileMenu_DeleteItemByCmd(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_Destroy(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +IsLFNDrive(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FileMenu_AbortInitMenu(VOID) +{ + STUB; +} + +VOID WINAPI +SHFlushClipboard(VOID) +{ + STUB; +} +/* +VOID WINAPI +RunDLL_CallEntry16(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + */ +VOID WINAPI +SHFreeUnusedLibraries(VOID) +{ + STUB; +} + +VOID WINAPI +FileMenu_AppendFilesForPidl(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +FileMenu_AddFilesForPidl(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + STUB; +} + +VOID WINAPI +SHOutOfMemoryMessageBox(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHWinHelp(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +/* +VOID WINAPI +DllGetClassObject(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + + This is now implemented in the C++ module _stubs.cpp as: + + STDAPI DllGetClassObject(const CLSID & rclsid, const IID & riid, void ** ppv); + + */ + +VOID WINAPI +DAD_AutoScroll(VOID) +{ + STUB; +} + +VOID WINAPI +DAD_DragEnter(VOID) +{ + STUB; +} + +VOID WINAPI +DAD_DragEnterEx(VOID) +{ + STUB; +} + +VOID WINAPI +DAD_DragLeave(VOID) +{ + STUB; +} + +VOID WINAPI +DragFinish(HDROP hDrop) +{ + STUB; +} +/* +unsigned int WINAPI +DragQueryFile(HDROP Unknown1, unsigned int Unknown2, char * Unknown3, unsigned int Unknown4) +{ + STUB; + return 0; +} + +unsigned int WINAPI +DragQueryFileA(HDROP Unknown1, unsigned int Unknown2, char * Unknown3, unsigned int Unknown4) +{ + STUB; + return 0; +} + +unsigned int WINAPI +DragQueryFileW(HDROP Unknown1, unsigned int Unknown2, LPCWSTR Unknown3, unsigned int Unknown4) +{ + STUB; +} + */ +UINT WINAPI +DragQueryFileA(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch) +{ + STUB; + return 0; +} + +UINT WINAPI +DragQueryFileW(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch) +{ + STUB; + return 0; +} + + +VOID WINAPI +DAD_DragMove(VOID) +{ + STUB; +} + +UINT WINAPI +DragQueryPoint(HDROP Unknown1, LPPOINT Unknown2) +{ + STUB; + return 0; +} + +VOID WINAPI +DAD_SetDragImage(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +DAD_ShowDragImage(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +Desktop_UpdateBriefcaseOnEvent(VOID) +{ + STUB; +} + +VOID WINAPI +FileMenu_DeleteItemByIndex(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_DeleteItemByFirstID(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileMenu_DeleteSeparator(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FileMenu_EnableItemByCmd(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +FileMenu_GetItemExtent(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +BOOL WINAPI +PathFindOnPathA(LPSTR Unknown1, LPCSTR* Unknown2) +{ + STUB; + return 0; +} + +BOOL WINAPI +PathFindOnPathW(LPWSTR Unknown1, LPCWSTR* Unknown2) +{ + STUB; + return 0; +} + +VOID WINAPI +RLBuildListOfPaths(VOID) +{ + STUB; +} + +VOID WINAPI +SHCLSIDFromString(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHFind_InitMenuPopup(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHLoadOLE(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILGetSize(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILGetNext(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILAppend(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +ILFree(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILGlobalFree(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +ILCreateFromPath(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +PathGetExtensionA(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +PathGetExtensionW(DWORD Unknown1) +{ + STUB; +} + +BOOL WINAPI +PathIsDirectoryA(LPCSTR Unknown1) +{ + STUB; + return 0; +} + +BOOL WINAPI +PathIsDirectoryW(LPCWSTR Unknown1) +{ + STUB; + return 0; +} + +VOID WINAPI +SHNetConnectionDialog(VOID) +{ + STUB; +} + +VOID WINAPI +SHRunControlPanel(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHSimpleIDListFromPath(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +StrToOleStr(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +Win32DeleteFile(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHCreateDirectory(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +DWORD WINAPI +CallCPLEntry16(HMODULE hMod, FARPROC pFunc, DWORD dw3, DWORD dw4, DWORD dw5, DWORD dw6) +//VOID WINAPI +//CallCPLEntry16(VOID) +{ + STUB; + return 0; +} + +VOID WINAPI +SHAddFromPropSheetExtArray(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHCreatePropSheetExtArray(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHDestroyPropSheetExtArray(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHReplaceFromPropSheetExtArray(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +PathCleanupSpecA(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHCreateLinks(VOID) +{ + STUB; +} + +VOID WINAPI +SHValidateUNC(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHCreateShellFolderViewEx(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHGetSpecialFolderPath(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHSetInstanceExplorer(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +DAD_SetDragImageFromListView(VOID) +{ + STUB; +} + +VOID WINAPI +SHObjectProperties(VOID) +{ + STUB; +} + +/* +//VOID WINAPI +//SHGetNewLinkInfo(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +#ifndef _MSC_VER +BOOL WINAPI +SHGetNewLinkInfo(LPCTSTR pszLinkTo, LPCTSTR pszDir, LPTSTR pszName, BOOL* pfMustCopy, UINT uFlags) +{ + STUB; +} +#endif + */ +#ifdef _MSC_VER +BOOL WINAPI +SHGetNewLinkInfoA(LPCTSTR pszLinkTo, LPCTSTR pszDir, LPTSTR pszName, BOOL* pfMustCopy, UINT uFlags) +#else +BOOL WINAPI +SHGetNewLinkInfoA(VOID) +#endif +{ + STUB; + return 0; +} + +#ifdef _MSC_VER +BOOL WINAPI +SHGetNewLinkInfoW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName, BOOL* pfMustCopy, UINT uFlags) +#else +BOOL WINAPI +SHGetNewLinkInfoW(VOID) +#endif +{ + STUB; + return 0; +} + +VOID WINAPI +RegisterShellHook(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID +ShellMessageBoxW(DWORD Unknown1, ...) +{ + STUB; +} + +VOID +ShellMessageBoxA(DWORD Unknown1, ...) +{ + STUB; +} + +VOID WINAPI +ArrangeWindows(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +SHHandleDiskFull(VOID) +{ + STUB; +} + +VOID WINAPI +SHFree(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHAlloc(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHGlobalDefect(VOID) +{ + STUB; +} + +VOID WINAPI +SHAbortInvokeCommand(VOID) +{ + STUB; +} + +VOID WINAPI +SHGetFileIcon(VOID) +{ + STUB; +} + +VOID WINAPI +SHLocalAlloc(VOID) +{ + STUB; +} + +VOID WINAPI +SHLocalFree(VOID) +{ + STUB; +} + +VOID WINAPI +SHLocalReAlloc(VOID) +{ + STUB; +} + +VOID WINAPI +AddCommasW(VOID) +{ + STUB; +} + +VOID WINAPI +ShortSizeFormatW(VOID) +{ + STUB; +} + +VOID WINAPI +Printer_LoadIconsW(VOID) +{ + STUB; +} + +VOID WINAPI +Link_AddExtraDataSection(VOID) +{ + STUB; +} + +VOID WINAPI +Link_ReadExtraDataSection(VOID) +{ + STUB; +} + +VOID WINAPI +Link_RemoveExtraDataSection(VOID) +{ + STUB; +} + +VOID WINAPI +Int64ToString(VOID) +{ + STUB; +} + +VOID WINAPI +LargeIntegerToString(VOID) +{ + STUB; +} + +VOID WINAPI +Printers_GetPidl(VOID) +{ + STUB; +} + +VOID WINAPI +Printer_AddPrinterPropPages(VOID) +{ + STUB; +} + +VOID WINAPI +Printers_RegisterWindowW(VOID) +{ + STUB; +} + +VOID WINAPI +Printers_UnregisterWindow(VOID) +{ + STUB; +} + +VOID WINAPI +SHStartNetConnectionDialog(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +shell32_243(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHInitRestricted(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHGetDataFromIDListA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +SHGetDataFromIDListW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +int WINAPI +PathParseIconLocationA(LPSTR Unknown1) +{ + STUB; + return 0; +} + +int WINAPI +PathParseIconLocationW(LPWSTR Unknown1) +{ + STUB; + return 0; +} + +VOID WINAPI +PathRemoveExtensionA(LPSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathRemoveExtensionW(LPWSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathRemoveArgsA(LPSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +PathRemoveArgsW(LPWSTR Unknown1) +{ + STUB; +} + +VOID WINAPI +SheChangeDirA(VOID) +{ + STUB; +} + +VOID WINAPI +SheChangeDirExA(VOID) +{ + STUB; +} + +VOID WINAPI +SheChangeDirExW(VOID) +{ + STUB; +} + +VOID WINAPI +SheChangeDirW(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SheConvertPathW(VOID) +{ + STUB; +} + +VOID WINAPI +SheFullPathA(VOID) +{ + STUB; +} + +VOID WINAPI +SheFullPathW(VOID) +{ + STUB; +} + +VOID WINAPI +SheGetCurDrive(VOID) +{ + STUB; +} + +VOID WINAPI +SheGetDirA(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SheGetDirExW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SheGetDirW(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SheGetPathOffsetW(VOID) +{ + STUB; +} + +VOID WINAPI +SheRemoveQuotesA(VOID) +{ + STUB; +} + +VOID WINAPI +SheRemoveQuotesW(VOID) +{ + STUB; +} + +VOID WINAPI +SheSetCurDrive(VOID) +{ + STUB; +} + +VOID WINAPI +SheShortenPathA(VOID) +{ + STUB; +} + +VOID WINAPI +SheShortenPathW(VOID) +{ + STUB; +} + +UINT WINAPI +ShellAboutA (HWND Unknown1, LPCSTR Unknown2, LPCSTR Unknown3, HICON Unknown4) +{ + STUB; + return 0; +} + +UINT WINAPI +//ShellAboutW (HWND Unknown1, const LPCWSTR Unknown2, const LPCWSTR Unknown3, HICON Unknown4) +ShellAboutW (HWND Unknown1, LPCWSTR Unknown2, LPCWSTR Unknown3, HICON Unknown4) +{ + STUB; + return 0; +} +/* +HINSTANCE WINAPI +ShellExecuteA (HWND Unknown1, const char * Unknown2, const char * Unknown3, char * Unknown4, const char * Unknown5, int Unknown6) +{ + STUB; +} + */ +/* +//VOID WINAPI +//ShellExecuteEx(DWORD Unknown1) +BOOL WINAPI +ShellExecuteEx(LPSHELLEXECUTEINFO lpExecInfo) +{ + STUB; + return 0; +} + */ +//VOID WINAPI +//ShellExecuteExA(DWORD Unknown1) +BOOL WINAPI +ShellExecuteExA(LPSHELLEXECUTEINFOA lpExecInfo) +{ + STUB; + return 0; +} + +//VOID WINAPI +//ShellExecuteExW(DWORD Unknown1) +BOOL WINAPI +ShellExecuteExW(LPSHELLEXECUTEINFOW lpExecInfo) +{ + STUB; + return 0; +} + +VOID WINAPI +ShellExecute (DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +HINSTANCE WINAPI +ShellExecuteW (HWND Unknown1, const LPCWSTR Unknown2, const LPCWSTR Unknown3, LPCWSTR Unknown4, const LPCWSTR Unknown5, int Unknown6) +{ + STUB; + return 0; +} +/* +//VOID WINAPI +//Shell_NotifyIcon(DWORD Unknown1, DWORD Unknown2) +BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage, PNOTIFYICONDATA pnid) +{ + STUB; + return 0; +} + */ +//VOID WINAPI +//Shell_NotifyIconA(DWORD Unknown1, DWORD Unknown2) +BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid) +{ + STUB; + return 0; +} + +//VOID WINAPI +//Shell_NotifyIconW(DWORD Unknown1, DWORD Unknown2) +//BOOL WINAPI Shell_NotifyIconW(DWORD,PNOTIFYICONDATAW); +BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid) +{ + STUB; + return 0; +} + +VOID WINAPI +Shl1632_ThunkData32(VOID) +{ + STUB; +} + +VOID WINAPI +Shl3216_ThunkData32(VOID) +{ + STUB; +} + +VOID WINAPI +StrCpyNA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +StrNCpyA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +StrRStrA(VOID) +{ + STUB; +} + +VOID WINAPI +StrRStrW(VOID) +{ + STUB; +} + +VOID WINAPI +SHRegCloseKey(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHRegOpenKeyA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHRegOpenKeyW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHRegQueryValueA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHRegQueryValueExA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +SHRegQueryValueW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHRegQueryValueExW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +SHRegDeleteKeyW(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHAllocShared(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +{ + STUB; +} + +VOID WINAPI +SHLockShared(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHUnlockShared(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHFreeShared(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +RealDriveType(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +RealDriveTypeFlags(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +NTSHChangeNotifyRegister(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6) +{ + STUB; +} + +VOID WINAPI +NTSHChangeNotifyDeregister(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHChangeNotifyReceive(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHChangeNotification_Lock(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHChangeNotification_Unlock(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHChangeRegistrationReceive(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +ReceiveAddToRecentDocs(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHWaitOp_Operate(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +BOOL WINAPI +PathIsSameRootA(LPCSTR Unknown1, LPCSTR Unknown2) +{ + STUB; + return 0; +} + +BOOL WINAPI +PathIsSameRootW(LPCWSTR Unknown1, LPCWSTR Unknown2) +{ + STUB; + return 0; +} + +VOID WINAPI +ReadCabinetState(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +WriteCabinetState(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +PathProcessCommand(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +shell32_654(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +FileIconInit(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +IsUserAdmin(VOID) +{ + STUB; +} + +VOID WINAPI +shell32_714(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +FOOBAR1217(VOID) +{ + STUB; +} + +VOID WINAPI +CheckEscapesA(VOID) +{ + STUB; +} + +VOID WINAPI +CheckEscapesW(VOID) +{ + STUB; +} + +LPWSTR WINAPI +CommandLineToArgvW(DWORD Unknown1, DWORD Unknown2) +//CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs) +{ +// lpCmdLine - pointer to a command-line string +// pNumArgs - receives the argument count + STUB; + return 0; +} +/* +HRESULT WINAPI +Control_FillCache_RunDLL(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) +//VOID WINAPI +//Control_FillCache_RunDLL(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; + return 0; +} + */ +//VOID WINAPI +//Control_FillCache_RunDLLA(VOID) +HRESULT WINAPI +Control_FillCache_RunDLLA(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) +{ + STUB; + return 0; +} + +//VOID WINAPI +//Control_FillCache_RunDLLW(VOID) +HRESULT WINAPI +Control_FillCache_RunDLLW(HWND hWnd, HANDLE hModule, DWORD w, DWORD x) +{ + STUB; + return 0; +} + +VOID Control_RunDLL(HWND hWnd, HINSTANCE hInst_unused, LPCWSTR lpCmdLine, DWORD nCmdShow); + +VOID WINAPI +Control_RunDLLA(HWND hWnd, HINSTANCE hInst_unused, LPCSTR lpCmdLine, DWORD nCmdShow) +{ + int reqSize = MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, 0, 0) * sizeof(TCHAR); + if (reqSize) { +// LPWSTR pCmdLine = (LPWSTR)malloc(reqSize + 10); + LPWSTR pCmdLine = (LPWSTR)_alloca(reqSize); + if (MultiByteToWideChar(CP_ACP, 0, lpCmdLine, -1, pCmdLine, reqSize)) { + Control_RunDLL(hWnd, hInst_unused, pCmdLine, nCmdShow); + } +// free(pCmdLine); + } +} + +VOID WINAPI +Control_RunDLLW(HWND hWnd, HINSTANCE hInst_unused, LPCWSTR lpCmdLine, DWORD nCmdShow) +{ + Control_RunDLL(hWnd, hInst_unused, lpCmdLine, nCmdShow); +} + +VOID WINAPI +DllInstall(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +/* +//VOID WINAPI +//DoEnvironmentSubstA(DWORD Unknown1, DWORD Unknown2) +DWORD WINAPI DoEnvironmentSubstA(LPCTSTR pszString, UINT cbSize) +{ + STUB; +} + */ +//VOID WINAPI +//DoEnvironmentSubstW(DWORD Unknown1, DWORD Unknown2) +DWORD WINAPI DoEnvironmentSubstW(LPCTSTR pszString, UINT cbSize) +{ + STUB; + return 0; +} + +VOID WINAPI +DragQueryFileAorW(VOID) +{ + STUB; +} + +HICON WINAPI +DuplicateIcon (HINSTANCE Unknown1, HICON Unknown2) +{ + STUB; + return 0; +} + +HICON WINAPI +ExtractAssociatedIconA(HINSTANCE Unknown1, LPCSTR Unknown2, PWORD Unknown3) +{ + STUB; + return 0; +} + +VOID WINAPI +ExtractAssociatedIconExA(VOID) +{ + STUB; +} + +VOID WINAPI +ExtractAssociatedIconExW(VOID) +{ + STUB; +} + +HICON WINAPI +ExtractAssociatedIconW (HINSTANCE Unknown1, LPCWSTR Unknown2, WORD * Unknown3) +{ + STUB; + return 0; +} + +HICON WINAPI +ExtractIconA (HINSTANCE Unknown1, const char * Unknown2, unsigned int Unknown3) +{ + STUB; + return 0; +} + +/* +//VOID WINAPI +//ExtractIconEx(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +UINT WINAPI ExtractIconEx(LPCTSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons) +{ +// lpszFile - file name +// nIconIndex - icon index +// phiconLarge - large icon array +// phiconSmall - small icon array +// nIcons - number of icons to extract + STUB; + return 0; +} + */ + +//VOID WINAPI +//ExtractIconExA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +//HICON WINAPI ExtractIconExA(LPCSTR,int,HICON*,HICON*,UINT); +//HICON WINAPI ExtractIconExA(LPCSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons) +#ifdef _MSC_VER +UINT +#else +HICON +#endif +WINAPI +ExtractIconExA(LPCSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons) +{ + STUB; + return 0; +} + +//VOID WINAPI +//ExtractIconExW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +//HICON WINAPI ExtractIconExW(LPCWSTR,int,HICON*,HICON*,UINT); // from ming header +//UINT WINAPI ExtractIconExW(LPCTSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons) +//HICON WINAPI ExtractIconExW(LPCWSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons) +#ifdef _MSC_VER +UINT +#else +HICON +#endif +WINAPI +ExtractIconExW(LPCWSTR lpszFile, int nIconIndex, HICON* phiconLarge, HICON* phiconSmall, UINT nIcons) +{ + STUB; + return 0; +} + +HICON +//WINAPI +WINAPI +ExtractIconW (HINSTANCE Unknown1, const LPCWSTR Unknown2, unsigned int Unknown3) +{ + STUB; + return 0; +} + +VOID WINAPI +ExtractIconResInfoA(VOID) +{ + STUB; +} + +VOID WINAPI +ExtractIconResInfoW(VOID) +{ + STUB; +} + +VOID WINAPI +ExtractVersionResource16W(VOID) +{ + STUB; +} + +VOID WINAPI +FindExeDlgProc(VOID) +{ + STUB; +} + +HINSTANCE +WINAPI +FindExecutableA(const char * Unknown1, const char * Unknown2, char * Unknown3) +{ + STUB; + return 0; +} + +HINSTANCE +WINAPI +// FindExecutableW(LPCWSTR,LPCWSTR,LPWSTR); +FindExecutableW(const LPCWSTR Unknown1, const LPCWSTR Unknown2, LPWSTR Unknown3) +{ + STUB; + return 0; +} + +VOID WINAPI +FreeIconList(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +InternalExtractIconListA(VOID) +{ + STUB; +} + +VOID WINAPI +InternalExtractIconListW(VOID) +{ + STUB; +} + +VOID WINAPI +OpenAs_RunDLL(VOID) +{ + STUB; +} + +VOID WINAPI +OpenAs_RunDLLA(VOID) +{ + STUB; +} + +VOID WINAPI +OpenAs_RunDLLW(VOID) +{ + STUB; +} + +VOID WINAPI +PrintersGetCommand_RunDLL(VOID) +{ + STUB; +} + +VOID WINAPI +PrintersGetCommand_RunDLLA(VOID) +{ + STUB; +} + +VOID WINAPI +PrintersGetCommand_RunDLLW(VOID) +{ + STUB; +} + +VOID WINAPI +RealShellExecuteA(VOID) +{ + STUB; +} + +VOID WINAPI +RealShellExecuteExA(VOID) +{ + STUB; +} + +VOID WINAPI +RealShellExecuteExW(VOID) +{ + STUB; +} + +VOID WINAPI +RealShellExecuteW(VOID) +{ + STUB; +} + +VOID WINAPI +RegenerateUserEnvironment(VOID) +{ + STUB; +} + +//void WINAPI +VOID WINAPI +SHAddToRecentDocs (UINT Unknown1, LPCVOID Unknown2) +{ + STUB; +} + +//VOID WINAPI +//SHAppBarMessage(DWORD Unknown1, DWORD Unknown2) +UINT WINAPI SHAppBarMessage(DWORD dwMessage, PAPPBARDATA pData) +{ + STUB; + return 0; +} + + + +LPITEMIDLIST +//WINAPI +WINAPI +SHBrowseForFolder(LPBROWSEINFO Unknown1) +{ + STUB; + return 0; +} + +VOID WINAPI +SHBrowseForFolderA(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHBrowseForFolderW(DWORD Unknown1) +{ + STUB; +} + +//void WINAPI +VOID WINAPI +SHChangeNotify (LONG Unknown1, UINT Unknown2, LPCVOID Unknown3, LPCVOID Unknown4) +{ + STUB; +} + +VOID WINAPI +ShellHookProc(VOID) +{ + STUB; +} + + +//VOID WINAPI +//SHEmptyRecycleBinA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +HRESULT WINAPI SHEmptyRecycleBinA(HWND hwnd, LPCTSTR pszRootPath, DWORD dwFlags) +{ + STUB; + return 0; +} + +//VOID WINAPI +//SHEmptyRecycleBinW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) +HRESULT WINAPI SHEmptyRecycleBinW(HWND hwnd, LPCTSTR pszRootPath, DWORD dwFlags) +{ + STUB; + return 0; +} +/* +int WINAPI +SHFileOperation (LPSHFILEOPSTRUCT Unknown1) +{ + STUB; + return 0; +} + */ +//VOID WINAPI +//SHFileOperationA(DWORD Unknown1) +//int WINAPI + +INT WINAPI +SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp) +{ + STUB; + return 0; +} + +//VOID WINAPI +//SHFileOperationW(DWORD Unknown1) +//int WINAPI +INT WINAPI +SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp) +{ + STUB; + return 0; +} + +VOID WINAPI +SHFormatDrive(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +//void WINAPI +VOID WINAPI +SHFreeNameMappings (HANDLE Unknown1) +{ + STUB; +} + +VOID WINAPI +SHGetDesktopFolder(DWORD Unknown1) +{ + STUB; +} +/* +//DWORD WINAPI +//SHGetFileInfo (LPCTSTR Unknown1, DWORD Unknown2, SHFILEINFO FAR * Unknown3, UINT Unknown4, UINT Unknown5) +DWORD_PTR WINAPI +SHGetFileInfo(LPCTSTR pszPath, DWORD dwFileAttributes, SHFILEINFO* psfi, UINT cbFileInfo, UINT uFlags) +{ + STUB; + return 0; +} + */ + +//VOID WINAPI +//SHGetFileInfoA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +//DWORD WINAPI SHGetFileInfoA(LPCSTR,DWORD,SHFILEINFOA*,UINT,UINT); +//DWORD_PTR WINAPI +//DWORD WINAPI +DWORD WINAPI +SHGetFileInfoA(LPCSTR pszPath, DWORD dwFileAttributes, SHFILEINFOA* psfi, UINT cbFileInfo, UINT uFlags) +{ + STUB; + return 0; +} + +//VOID WINAPI +//SHGetFileInfoW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +//DWORD_PTR WINAPI +//DWORD WINAPI +DWORD WINAPI +SHGetFileInfoW(LPCTSTR pszPath, DWORD dwFileAttributes, SHFILEINFOW* psfi, UINT cbFileInfo, UINT uFlags) +{ + STUB; + return 0; +} + +VOID WINAPI +SHGetInstanceExplorer(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHGetMalloc(DWORD Unknown1) +{ + STUB; +} + +//WINBOOL WINAPI +BOOL WINAPI +SHGetPathFromIDList (LPCITEMIDLIST Unknown1, LPTSTR Unknown2) +{ + STUB; + return 0; +} + +VOID WINAPI +SHGetPathFromIDListA(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHGetPathFromIDListW(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +VOID WINAPI +SHGetSettings(DWORD Unknown1, DWORD Unknown2) +{ + STUB; +} + +HRESULT +//WINAPI +WINAPI +SHGetSpecialFolderLocation (HWND Unknown1, int Unknown2, LPITEMIDLIST * Unknown3) +{ + STUB; + return 0; +} + +VOID WINAPI +SHHelpShortcuts_RunDLL(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHHelpShortcuts_RunDLLA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHHelpShortcuts_RunDLLW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHLoadInProc(DWORD Unknown1) +{ + STUB; +} + +//VOID WINAPI +//SHQueryRecycleBinA(DWORD Unknown1, DWORD Unknown2) +HRESULT WINAPI +SHQueryRecycleBinA(LPCTSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo) +{ + STUB; + return 0; +} + +//VOID WINAPI +//SHQueryRecycleBinW(DWORD Unknown1, DWORD Unknown2) +HRESULT WINAPI +SHQueryRecycleBinW(LPCTSTR pszRootPath, LPSHQUERYRBINFO pSHQueryRBInfo) +{ + STUB; + return 0; +} + +VOID WINAPI +SHUpdateRecycleBinIcon(VOID) +{ + STUB; +} + +VOID WINAPI +WOWShellExecute(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6, DWORD Unknown7) +{ + STUB; +} + +STDAPI +DllCanUnloadNow(VOID) +{ + STUB; + return 0; +} + +VOID WINAPI +DllGetVersion(DWORD Unknown1) +{ + STUB; +} + +VOID WINAPI +SHGetFreeDiskSpace(VOID) +{ + STUB; +} + +VOID WINAPI +SHGetSpecialFolderPathA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4) +{ + STUB; +} + +VOID WINAPI +SHGetFolderPathA(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +SHGetFolderPathW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + +VOID WINAPI +SHGetFolderLocation(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5) +{ + STUB; +} + + diff --git a/lib/shell32/res/control.ico b/lib/shell32/res/control.ico new file mode 100644 index 0000000000000000000000000000000000000000..57b16da0b65ed1abb203f5a0b8efe57527961dc2 GIT binary patch literal 1078 zcmeH`y-vb#6vcl<6NSO_4eVri3w#xy0H47AM+XyKnQ(SuL8B(7Z@}o_;^fC7CMFmm96jy1-)+->&V`5yNfP6Ds=$tX92a>#f~_^EtConnV#K;E1kEl-P*a@{ z3MZ>j3}jiRhD~nFJQ8(z$<4~R?m+DfHV@rGS-$we)(KQw`s)|BP?j$~|DUgN0@A=7 z_pkdKWtr zXFAUmFGrB5)se0zPFCUXbbd+=uJp1gI#l6#mi@W+RXf`I$zl)TW(?^8Ty&v#2ZLJ} K^&oHfp28Pe^}?9| literal 0 HcmV?d00001 diff --git a/lib/shell32/res/small.ico b/lib/shell32/res/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..576aec9ea6f347db5ed3dc1b57ff83e32401350c GIT binary patch literal 318 zcmc(Zu@Qhk2n3fI3m`H!v`k8)GrapxjZ6e~VIToQnVC55fYV)gbBW-Pp_kuOprUFw YS)(YrTZdW2j3=S=%KAC>AO7VV5BSA3qW}N^ literal 0 HcmV?d00001 diff --git a/lib/shell32/resource.h b/lib/shell32/resource.h new file mode 100644 index 0000000..63dcaee --- /dev/null +++ b/lib/shell32/resource.h @@ -0,0 +1,54 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by roshel32.rc +// +#define ID_FILE_MENU 0 +#define ID_VIEW_MENU 1 +#define ID_HELP_MENU 2 +#define IDC_MYICON 2 +#define IDS_LIST_COLUMN_FIRST 91 +#define IDS_LIST_COLUMN_NAME 91 +#define IDS_LIST_COLUMN_COMMENT 92 +#define IDS_LIST_COLUMN_LAST 92 +#define IDD_CONTROL_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDS_APP_TITLE 103 +#define IDI_CONTROL 107 +#define IDI_SMALL 108 +#define IDC_CONTROL 109 +#define IDS_APP_REG_KEY 110 +#define IDS_APP_REG_PATH 111 + +#define IDR_CONTROL_MENU 130 +#define ID_FILE_OPEN 32770 +#define ID_FILE_EXIT 32771 +#define ID_VIEW_TOOLBAR 32772 +#define ID_VIEW_STATUSBAR 32773 +#define ID_VIEW_LARGE_ICONS 32774 +#define ID_VIEW_SMALL_ICONS 32775 +#define ID_VIEW_LIST 32776 +#define ID_VIEW_DETAILS 32777 +#define ID_VIEW_ARRANGE_ICONS 32778 +#define ID_VIEW_ARRANGE_BY_NAME 32779 +#define ID_VIEW_ARRANGE_BY_COMMENT 32780 +#define ID_VIEW_ARRANGE_AUTO 32781 +#define ID_VIEW_LINE_UP_ICONS 32782 +#define ID_VIEW_REFRESH 32783 +#define ID_HELP_ABOUT 32784 +#define IDR_CONTROL_CONTEXT 32785 +#define IDR_CONTROL_CONTEXT_APPLET 32786 +#define ID_FILE_CREATE_SHORTCUT 32787 +#define ID_FILE_PASTE 32788 +#define ID_FILE_PASTE_SHORTCUT 32789 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32780 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/lib/shell32/roshel32.rc b/lib/shell32/roshel32.rc new file mode 100644 index 0000000..15e5bfd --- /dev/null +++ b/lib/shell32/roshel32.rc @@ -0,0 +1,290 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_CONTROL ICON DISCARDABLE "res/control.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_CONTROL_MENU MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Open", ID_FILE_OPEN + MENUITEM "&Create Shortcut", ID_FILE_CREATE_SHORTCUT, GRAYED + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_FILE_EXIT + END + POPUP "&View" + BEGIN + MENUITEM "&Tool Bar", ID_VIEW_TOOLBAR, GRAYED + MENUITEM "Status &Bar", ID_VIEW_STATUSBAR + MENUITEM SEPARATOR + MENUITEM "Lar&ge Icons", ID_VIEW_LARGE_ICONS + MENUITEM "S&mall Icons", ID_VIEW_SMALL_ICONS + MENUITEM "&List", ID_VIEW_LIST + MENUITEM "&Details", ID_VIEW_DETAILS + MENUITEM SEPARATOR + POPUP "Arrange &Icons" + BEGIN + MENUITEM "by &Name", ID_VIEW_ARRANGE_BY_NAME + MENUITEM "by &Comment", ID_VIEW_ARRANGE_BY_COMMENT + + MENUITEM SEPARATOR + MENUITEM "&Auto-Arrange", ID_VIEW_ARRANGE_AUTO + END + MENUITEM "Line &Up Icons", ID_VIEW_LINE_UP_ICONS + MENUITEM SEPARATOR + MENUITEM "&Refresh\tF5", ID_VIEW_REFRESH + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", ID_HELP_ABOUT + END +END + +IDR_CONTROL_CONTEXT MENU DISCARDABLE +BEGIN + POPUP "DUMMY" + BEGIN + POPUP "&View" + BEGIN + MENUITEM "Lar&ge Icons", ID_VIEW_LARGE_ICONS + MENUITEM "S&mall Icons", ID_VIEW_SMALL_ICONS + MENUITEM "&List", ID_VIEW_LIST + MENUITEM "&Details", ID_VIEW_DETAILS + END + MENUITEM SEPARATOR + POPUP "Arrange &Icons" + BEGIN + MENUITEM "by &Name", ID_VIEW_ARRANGE_BY_NAME + MENUITEM "by &Comment", ID_VIEW_ARRANGE_BY_COMMENT + + MENUITEM SEPARATOR + MENUITEM "&Auto-Arrange", ID_VIEW_ARRANGE_AUTO + END + MENUITEM "Line &Up Icons", ID_VIEW_LINE_UP_ICONS + MENUITEM SEPARATOR + MENUITEM "&Refresh", ID_VIEW_REFRESH + MENUITEM SEPARATOR + MENUITEM "&Paste", ID_FILE_PASTE, GRAYED + MENUITEM "Paste &Shortcut", ID_FILE_PASTE_SHORTCUT + , GRAYED + END +END + +IDR_CONTROL_CONTEXT_APPLET MENU DISCARDABLE +BEGIN + POPUP "DUMMY" + BEGIN + MENUITEM "&Open", ID_FILE_OPEN + MENUITEM SEPARATOR + MENUITEM "&Create Shortcut", ID_FILE_CREATE_SHORTCUT + , GRAYED + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 75 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About Control Panel" +FONT 8, "System" +BEGIN + ICON IDI_CONTROL,IDC_MYICON,14,9,16,16 + LTEXT "Control Panel Version 1.0",IDC_STATIC,49,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 2002",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +(1) VERSIONINFO + FILEVERSION 0,0,19,154 + PRODUCTVERSION 0,0,19,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Absolutely no warranties whatsoever - Use at your own risk\0" + VALUE "CompanyName", "ReactOS Development Team\0" + VALUE "FileDescription", "ReactOS Shell32 Dynamic Link Library\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "shell32\0" + VALUE "LegalCopyright", "Copyright © 2002 Robert Dickenson\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "shell32.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "ReactOS Operating System\0" + VALUE "ProductVersion", "0.0.19\0" + VALUE "SpecialBuild", "Non-versioned Development Beta Release\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0xc09, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LIST_COLUMN_NAME "Name" + IDS_LIST_COLUMN_COMMENT "Comment" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_MENU "Contains commands for working with the selected items" + ID_VIEW_MENU "Contains commands for manipulating the view" + ID_HELP_MENU "Contains commands for displaying help" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Shows or hides the tool bar" + ID_VIEW_STATUSBAR "Shows or hides the status bar" + ID_VIEW_LARGE_ICONS "Displays items using large icons" + ID_VIEW_SMALL_ICONS "Displays items using small icons" + ID_VIEW_LIST "Displays items in a list" + ID_VIEW_DETAILS "Displays information about each item in the list" + ID_VIEW_ARRANGE_ICONS "Contains commands for arranging items in the window" + ID_VIEW_ARRANGE_BY_NAME "Sorts items alphabetically by name" + ID_VIEW_ARRANGE_BY_COMMENT "Sorts items by the thier comment property" + ID_VIEW_ARRANGE_AUTO "Arranges the items automatically" + ID_VIEW_LINE_UP_ICONS "Arranges icons in a grid layout" + ID_VIEW_REFRESH "Refreshes the contents of the current page" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE "ReactOS Control Panel" + IDC_CONTROL "CONTROL" + IDS_APP_REG_KEY "\\Control Panel" + IDS_APP_REG_PATH "Software\\ReactWare" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (Australia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (Australia) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/lib/shell32/shell32.def b/lib/shell32/shell32.def new file mode 100644 index 0000000..8d7a9ad --- /dev/null +++ b/lib/shell32/shell32.def @@ -0,0 +1,381 @@ +; $Id: shell32.def +; +; shell32.def +; +; ReactOS Operating System +; +; +;LIBRARY shell32 +LIBRARY roshel32.dll +EXPORTS +SHChangeNotifyRegister@24 ; @ 2 +SHChangeNotifyDeregister ; @ 4 +SHChangeNotifyUpdateEntryList@16 ; @ 5 +PifMgr_OpenProperties@16 ; @ 9 +PifMgr_GetProperties@20 ; @ 10 +PifMgr_SetProperties@20 ; @ 11 +PifMgr_CloseProperties ; @ 13 +ILGetDisplayName ; @ 15 +ILFindLastID ; @ 16 +ILRemoveLastID ; @ 17 +ILClone ; @ 18 +ILCloneFirst ; @ 19 +ILGlobalClone ; @ 20 +ILIsEqual ; @ 21 +ILIsParent@12 ; @ 23 +ILFindChild ; @ 24 +ILCombine ; @ 25 +ILLoadFromStream ; @ 26 +ILSaveToStream ; @ 27 +SHILCreateFromPath@12 ; @ 28 +PathIsRootA ; @ 29 +PathBuildRootA ; @ 30 +PathFindExtensionA ; @ 31 +PathAddBackslashA ; @ 32 +PathRemoveBlanksA ; @ 33 +PathFindFileNameA ; @ 34 +PathRemoveFileSpecA ; @ 35 +PathAppendA ; @ 36 +PathCombineA@12 ; @ 37 +PathStripPathA ; @ 38 +PathIsUNCA ; @ 39 +PathIsRelativeA ; @ 40 +PathIsExeA ; @ 43 +PathFileExistsA ; @ 45 +PathMatchSpecA ; @ 46 +PathMakeUniqueNameA@20 ; @ 47 +PathSetDlgItemPathA@12 ; @ 48 +PathQualifyA ; @ 49 +PathStripToRootA ; @ 50 +PathResolveA@12 ; @ 51 +PathGetArgsA ; @ 52 +DoEnvironmentSubst ; @ 53 +DragAcceptFiles ; @ 54 +PathQuoteSpacesA ; @ 55 +PathUnquoteSpacesA ; @ 56 +PathGetDriveNumberA ; @ 57 +ParseField@16 ; @ 58 +RestartDialog@12 ; @ 59 +ExitWindowsDialog ; @ 60 +RunFileDlg@24 ; @ 61 +PickIconDlg@16 ; @ 62 +GetFileNameFromBrowse@28 ; @ 63 +DriveType ; @ 64 +InvalidateDriveType ; @ 65 +IsNetDrive ; @ 66 +Shell_MergeMenus@24 ; @ 67 +SHGetSetSettings@12 ; @ 68 +SHGetNetResource ; @ 69 +SHCreateDefClassObject@20 ; @ 70 +Shell_GetImageList ; @ 71 +Shell_GetCachedImageIndex@12 ; @ 72 +SHShellFolderView_Message@12 ; @ 73 +SHCreateStdEnumFmtEtc ; @ 74 +PathYetAnotherMakeUniqueName@16 ; @ 75 +DragQueryInfo ; @ 76 +SHMapPIDLToSystemImageListIndex@12 ; @ 77 +OleStrToStrN@16 ; @ 78 +StrToOleStrN@16 ; @ 79 +DragFinish ; @ 80 +;DragQueryFile@16 ; @ 81 +DragQueryFileA@16 ; @ 82 +CIDLData_CreateFromIDArray ; @ 83 +SHIsBadInterfacePtr ; @ 84 +; OpenRegStream=shlwapi.SHOpenRegStreamA ; @ 85 +SHRegisterDragDrop ; @ 86 +SHRevokeDragDrop ; @ 87 +SHDoDragDrop@20 ; @ 88 +SHCloneSpecialIDList@12 ; @ 89 +SHFindFiles ; @ 90 +SHFindComputer ; @ 91 +PathGetShortPath ; @ 92 +Win32CreateDirectory ; @ 93 +Win32RemoveDirectory ; @ 94 +SHLogILFromFSIL ; @ 95 +StrRetToStrN@16 ; @ 96 +SHWaitForFileToOpen@12 ; @ 97 +SHGetRealIDL@12 ; @ 98 +SetAppStartingCursor ; @ 99 +SHRestricted ; @ 100 +SHCoCreateInstance@20 ; @ 102 +SignalFileOpen ; @ 103 +FileMenu_DeleteAllItems ; @ 104 +FileMenu_DrawItem ; @ 105 +FileMenu_FindSubMenuByPidl ; @ 106 +FileMenu_GetLastSelectedItemPidls@12 ; @ 107 +FileMenu_HandleMenuChar ; @ 108 +FileMenu_InitMenuPopup ; @ 109 +FileMenu_InsertUsingPidl@24 ; @ 110 +FileMenu_Invalidate ; @ 111 +FileMenu_MeasureItem ; @ 112 +FileMenu_ReplaceUsingPidl@20 ; @ 113 +FileMenu_Create@20 ; @ 114 +FileMenu_AppendItem@24 ; @ 115 +FileMenu_TrackPopupMenuEx@24 ; @ 116 +FileMenu_DeleteItemByCmd ; @ 117 +FileMenu_Destroy ; @ 118 +IsLFNDrive ; @ 119 +FileMenu_AbortInitMenu ; @ 120 +SHFlushClipboard ; @ 121 +;RunDLL_CallEntry16@20 ; @ 122 +SHFreeUnusedLibraries ; @ 123 +FileMenu_AppendFilesForPidl@12 ; @ 124 +FileMenu_AddFilesForPidl@28 ; @ 125 +SHOutOfMemoryMessageBox@12 ; @ 126 +SHWinHelp@16 ; @ 127 +DllGetClassObject@12 ; @ 128 +DAD_AutoScroll ; @ 129 +DAD_DragEnter ; @ 130 +DAD_DragEnterEx ; @ 131 +DAD_DragLeave ; @ 132 +DragQueryFileW@16 ; @ 133 +DAD_DragMove ; @ 134 +DragQueryPoint ; @ 135 +DAD_SetDragImage ; @ 136 +DAD_ShowDragImage ; @ 137 +Desktop_UpdateBriefcaseOnEvent ; @ 139 +FileMenu_DeleteItemByIndex ; @ 140 +FileMenu_DeleteItemByFirstID ; @ 141 +FileMenu_DeleteSeparator ; @ 142 +FileMenu_EnableItemByCmd@12 ; @ 143 +FileMenu_GetItemExtent ; @ 144 +PathFindOnPathA ; @ 145 +RLBuildListOfPaths ; @ 146 +SHCLSIDFromString ; @ 147 +SHFind_InitMenuPopup@16 ; @ 149 +SHLoadOLE ; @ 151 +ILGetSize ; @ 152 +ILGetNext ; @ 153 +ILAppend@12 ; @ 154 +ILFree ; @ 155 +ILGlobalFree ; @ 156 +ILCreateFromPath ; @ 157 +PathGetExtensionA ; @ 158 +PathIsDirectoryA ; @ 159 +SHNetConnectionDialog ; @ 160 +SHRunControlPanel ; @ 161 +SHSimpleIDListFromPath ; @ 162 +StrToOleStr ; @ 163 +Win32DeleteFile ; @ 164 +SHCreateDirectory ; @ 165 +CallCPLEntry16@24 ; @ 166 +SHAddFromPropSheetExtArray@12 ; @ 167 +SHCreatePropSheetExtArray@12 ; @ 168 +SHDestroyPropSheetExtArray ; @ 169 +SHReplaceFromPropSheetExtArray@16 ; @ 170 +PathCleanupSpecA ; @ 171 +SHCreateLinks ; @ 172 +SHValidateUNC@12 ; @ 173 +SHCreateShellFolderViewEx ; @ 174 +SHGetSpecialFolderPath@16 ; @ 175 +SHSetInstanceExplorer ; @ 176 +DAD_SetDragImageFromListView ; @ 177 +SHObjectProperties ; @ 178 +SHGetNewLinkInfoA ; @ 179 +SHGetNewLinkInfoW ; @ 180 +RegisterShellHook ; @ 181 +ShellMessageBoxW ; @ 182 +ShellMessageBoxA ; @ 183 +ArrangeWindows@20 ; @ 184 +SHHandleDiskFull ; @ 185 +SHFree ; @ 195 +SHAlloc ; @ 196 +SHGlobalDefect ; @ 197 +SHAbortInvokeCommand ; @ 198 +SHGetFileIcon ; @ 199 +SHLocalAlloc ; @ 200 +SHLocalFree ; @ 201 +SHLocalReAlloc ; @ 202 +AddCommasW ; @ 203 +ShortSizeFormatW ; @ 204 +Printer_LoadIconsW ; @ 205 +Link_AddExtraDataSection ; @ 206 +Link_ReadExtraDataSection ; @ 207 +Link_RemoveExtraDataSection ; @ 208 +Int64ToString ; @ 209 +LargeIntegerToString ; @ 210 +Printers_GetPidl ; @ 211 +Printer_AddPrinterPropPages ; @ 212 +Printers_RegisterWindowW ; @ 213 +Printers_UnregisterWindow ; @ 214 +SHStartNetConnectionDialog@12 ; @ 215 +shell32_243 ; @ 243 +SHInitRestricted ; @ 244 +SHGetDataFromIDListA@20 ; @ 247 +SHGetDataFromIDListW@20 ; @ 248 +PathParseIconLocationA ; @ 249 +PathRemoveExtensionA ; @ 250 +PathRemoveArgsA ; @ 251 +SheChangeDirA ; @ 271 +SheChangeDirExA ; @ 272 +SheChangeDirExW ; @ 273 +SheChangeDirW ; @ 274 +SheConvertPathW ; @ 275 +SheFullPathA ; @ 276 +SheFullPathW ; @ 277 +SheGetCurDrive ; @ 278 +SheGetDirA ; @ 279 +SheGetDirExW@12 ; @ 280 +SheGetDirW ; @ 281 +SheGetPathOffsetW ; @ 282 +SheRemoveQuotesA ; @ 283 +SheRemoveQuotesW ; @ 284 +SheSetCurDrive ; @ 285 +SheShortenPathA ; @ 286 +SheShortenPathW ; @ 287 +ShellAboutA ; @ 288 +ShellAboutW ; @ 289 +;ShellExecuteA=ShellExecuteA@24 ; @ 290 +;ShellExecuteEx ; @ 291 +ShellExecuteExA=ShellExecuteExA ; @ 292 +ShellExecuteExW ; @ 293 +ShellExecuteW@24 ; @ 294 +;Shell_NotifyIcon ; @ 296 +Shell_NotifyIconA ; @ 297 +Shell_NotifyIconW ; @ 298 +Shl1632_ThunkData32 ; @ 299 +Shl3216_ThunkData32 ; @ 300 +; StrChrA=shlwapi.StrChrA ; @ 301 +; StrChrIA=shlwapi.StrChrIA ; @ 302 +; StrChrIW=shlwapi.StrChrIW ; @ 303 +; StrChrW=shlwapi.StrChrW ; @ 304 +; StrCmpNA=shlwapi.StrCmpNA ; @ 305 +; StrCmpNIA=shlwapi.StrCmpNIA ; @ 306 +; StrCmpNIW=shlwapi.StrCmpNIW ; @ 307 +; StrCmpNW=shlwapi.StrCmpNW ; @ 308 +StrCpyNA@12 ; @ 309 +; StrCpyNW=shlwapi.StrCpyNW ; @ 310 +; StrNCmpA=shlwapi.StrCmpNA ; @ 311 +; StrNCmpIA=shlwapi.StrCmpNIA ; @ 312 +; StrNCmpIW=shlwapi.StrCmpNIW ; @ 313 +; StrNCmpW=shlwapi.StrCmpNW ; @ 314 +StrNCpyA@12 ; @ 315 +; StrNCpyW=shlwapi.StrNCpyW ; @ 316 +; StrRChrA=shlwapi.StrRChrA ; @ 317 +; StrRChrIA=shlwapi.StrRChrIA ; @ 318 +; StrRChrIW=shlwapi.StrRChrIW ; @ 319 +; StrRChrW=shlwapi.StrRChrW ; @ 320 +StrRStrA ; @ 321 +; StrRStrIA=shlwapi.StrRStrIA ; @ 322 +; StrRStrIW=shlwapi.StrRStrIW ; @ 323 +StrRStrW ; @ 324 +; StrStrA=shlwapi.StrStrA ; @ 325 +; StrStrIA=shlwapi.StrStrIA ; @ 326 +; StrStrIW=shlwapi.StrStrIW ; @ 327 +; StrStrW=shlwapi.StrStrW ; @ 328 +SHRegCloseKey ; @ 505 +SHRegOpenKeyA@12 ; @ 506 +SHRegOpenKeyW@12 ; @ 507 +SHRegQueryValueA@16 ; @ 508 +SHRegQueryValueExA@24 ; @ 509 +SHRegQueryValueW@16 ; @ 510 +SHRegQueryValueExW@24 ; @ 511 +SHRegDeleteKeyW ; @ 512 +SHAllocShared@12 ; @ 520 +SHLockShared ; @ 521 +SHUnlockShared ; @ 522 +SHFreeShared ; @ 523 +RealDriveType ; @ 524 +RealDriveTypeFlags ; @ 525 +NTSHChangeNotifyRegister@24 ; @ 640 +NTSHChangeNotifyDeregister ; @ 641 +SHChangeNotifyReceive@16 ; @ 643 +SHChangeNotification_Lock@16 ; @ 644 +SHChangeNotification_Unlock ; @ 645 +SHChangeRegistrationReceive ; @ 646 +ReceiveAddToRecentDocs ; @ 647 +SHWaitOp_Operate ; @ 648 +PathIsSameRootA ; @ 650 +ReadCabinetState ; @ 651 +WriteCabinetState ; @ 652 +PathProcessCommand@16 ; @ 653 +shell32_654 ; @ 654 +FileIconInit ; @ 660 +IsUserAdmin ; @ 680 +shell32_714 ; @ 714 +FOOBAR1217 ; @ 1217 +CheckEscapesA@0 +CheckEscapesW@0 +CommandLineToArgvW@8 +;Control_FillCache_RunDLL@16 +Control_FillCache_RunDLLA@16 +Control_FillCache_RunDLLW@16 +;Control_RunDLL@16 +Control_RunDLLA +Control_RunDLLW +DllInstall@8 +;DoEnvironmentSubstA@8 +DoEnvironmentSubstW@8 +DragQueryFileAorW@0 +DuplicateIcon@8 +ExtractAssociatedIconA@12 +ExtractAssociatedIconExA@0 +ExtractAssociatedIconExW@0 +ExtractAssociatedIconW@12 +ExtractIconA=ExtractIconA@12 +;ExtractIconEx@20 +ExtractIconExA@20 +ExtractIconExW@20 +ExtractIconW@12 +ExtractIconResInfoA@0 +ExtractIconResInfoW@0 +ExtractVersionResource16W@0 +FindExeDlgProc@0 +FindExecutableA@12 +FindExecutableW@12 +FreeIconList@4 +InternalExtractIconListA@0 +InternalExtractIconListW@0 +OpenAs_RunDLL@0 +OpenAs_RunDLLA@0 +OpenAs_RunDLLW@0 +PrintersGetCommand_RunDLL@0 +PrintersGetCommand_RunDLLA@0 +PrintersGetCommand_RunDLLW@0 +RealShellExecuteA@0 +RealShellExecuteExA@0 +RealShellExecuteExW@0 +RealShellExecuteW@0 +RegenerateUserEnvironment@0 +SHAddToRecentDocs@8 +SHAppBarMessage@8 +SHBrowseForFolder@4 +SHBrowseForFolderA@4 +SHBrowseForFolderW@4 +SHChangeNotify@16 +ShellHookProc@0 +SHEmptyRecycleBinA@12 +SHEmptyRecycleBinW@12 +;SHFileOperation@4 +SHFileOperationA@4 +SHFileOperationW@4 +SHFormatDrive@16 +SHFreeNameMappings@4 +SHGetDesktopFolder@4 +;SHGetFileInfo@20 +SHGetFileInfoA@20 +SHGetFileInfoW@20 +SHGetInstanceExplorer@4 +SHGetMalloc=SHGetMalloc@4 +;SHGetNewLinkInfo@20 +SHGetPathFromIDList=SHGetPathFromIDList@8 +SHGetPathFromIDListA=SHGetPathFromIDListA@8 +SHGetPathFromIDListW=SHGetPathFromIDListW@8 +SHGetSettings@8 +SHGetSpecialFolderLocation=SHGetSpecialFolderLocation@12 +SHHelpShortcuts_RunDLL@16 +SHHelpShortcuts_RunDLLA@16 +SHHelpShortcuts_RunDLLW@16 +SHLoadInProc@4 +SHQueryRecycleBinA@8 +SHQueryRecycleBinW@8 +SHUpdateRecycleBinIcon@0 +WOWShellExecute@28 +DllCanUnloadNow@0 +DllGetVersion@4 +SHGetFreeDiskSpace@0 +SHGetSpecialFolderPathA@16 +SHGetFolderPathA@20 +SHGetFolderPathW@20 +SHGetFolderLocation@20 + diff --git a/lib/shell32/shell32.edf b/lib/shell32/shell32.edf new file mode 100644 index 0000000..863c5a4 --- /dev/null +++ b/lib/shell32/shell32.edf @@ -0,0 +1,381 @@ +; $Id: shell32.edf +; +; shell32.edf +; +; ReactOS Operating System +; +; +;LIBRARY shell32 +LIBRARY roshel32.dll +EXPORTS +SHChangeNotifyRegister@24 ; @ 2 +SHChangeNotifyDeregister@4 ; @ 4 +SHChangeNotifyUpdateEntryList@16 ; @ 5 +PifMgr_OpenProperties@16 ; @ 9 +PifMgr_GetProperties@20 ; @ 10 +PifMgr_SetProperties@20 ; @ 11 +PifMgr_CloseProperties@8 ; @ 13 +ILGetDisplayName@8 ; @ 15 +ILFindLastID@4 ; @ 16 +ILRemoveLastID@4 ; @ 17 +ILClone@4 ; @ 18 +ILCloneFirst@4 ; @ 19 +ILGlobalClone@4 ; @ 20 +ILIsEqual@8 ; @ 21 +ILIsParent@12 ; @ 23 +ILFindChild@8 ; @ 24 +ILCombine@8 ; @ 25 +ILLoadFromStream@8 ; @ 26 +ILSaveToStream@8 ; @ 27 +SHILCreateFromPath@12 ; @ 28 +PathIsRootA=PathIsRootA@4 ; @ 29 +PathBuildRootA=PathBuildRootA@8 ; @ 30 +PathFindExtensionA=PathFindExtensionA@4 ; @ 31 +PathAddBackslashA=PathAddBackslashA@4 ; @ 32 +PathRemoveBlanksA=PathRemoveBlanksA@4 ; @ 33 +PathFindFileNameA=PathFindFileNameA@4 ; @ 34 +PathRemoveFileSpecA=PathRemoveFileSpecA@4 ; @ 35 +PathAppendA=PathAppendA@8 ; @ 36 +PathCombineA=PathCombineA@12 ; @ 37 +PathStripPathA=PathStripPathA@4 ; @ 38 +PathIsUNCA=PathIsUNCA@4 ; @ 39 +PathIsRelativeA=PathIsRelativeA@4 ; @ 40 +PathIsExeA=PathIsExeA@4 ; @ 43 +PathFileExistsA=PathFileExistsA@4 ; @ 45 +PathMatchSpecA=PathMatchSpecA@8 ; @ 46 +PathMakeUniqueNameA=PathMakeUniqueNameA@20 ; @ 47 +PathSetDlgItemPathA=PathSetDlgItemPathA@12 ; @ 48 +PathQualifyA=PathQualifyA@4 ; @ 49 +PathStripToRootA=PathStripToRootA@4 ; @ 50 +PathResolveA=PathResolveA@12 ; @ 51 +PathGetArgsA=PathGetArgsA@4 ; @ 52 +DoEnvironmentSubst@8 ; @ 53 +DragAcceptFiles@8 ; @ 54 +PathQuoteSpacesA=PathQuoteSpacesA@4 ; @ 55 +PathUnquoteSpacesA=PathUnquoteSpacesA@4 ; @ 56 +PathGetDriveNumberA=PathGetDriveNumberA@4 ; @ 57 +ParseField@16 ; @ 58 +RestartDialog@12 ; @ 59 +ExitWindowsDialog@4 ; @ 60 +RunFileDlg@24 ; @ 61 +PickIconDlg@16 ; @ 62 +GetFileNameFromBrowse@28 ; @ 63 +DriveType@4 ; @ 64 +InvalidateDriveType@0 ; @ 65 +IsNetDrive@4 ; @ 66 +Shell_MergeMenus@24 ; @ 67 +SHGetSetSettings@12 ; @ 68 +SHGetNetResource@0 ; @ 69 +SHCreateDefClassObject@20 ; @ 70 +Shell_GetImageList@8 ; @ 71 +Shell_GetCachedImageIndex@12 ; @ 72 +SHShellFolderView_Message@12 ; @ 73 +SHCreateStdEnumFmtEtc@0 ; @ 74 +PathYetAnotherMakeUniqueName@16 ; @ 75 +DragQueryInfo@0 ; @ 76 +SHMapPIDLToSystemImageListIndex@12 ; @ 77 +OleStrToStrN@16 ; @ 78 +StrToOleStrN@16 ; @ 79 +DragFinish@4 ; @ 80 +;DragQueryFile@16 ; @ 81 +DragQueryFileA@16 ; @ 82 +CIDLData_CreateFromIDArray@0 ; @ 83 +SHIsBadInterfacePtr@0 ; @ 84 +; OpenRegStream=shlwapi.SHOpenRegStreamA ; @ 85 +SHRegisterDragDrop@8 ; @ 86 +SHRevokeDragDrop@4 ; @ 87 +SHDoDragDrop@20 ; @ 88 +SHCloneSpecialIDList@12 ; @ 89 +SHFindFiles@0 ; @ 90 +SHFindComputer@0 ; @ 91 +PathGetShortPath@4 ; @ 92 +Win32CreateDirectory@0 ; @ 93 +Win32RemoveDirectory@0 ; @ 94 +SHLogILFromFSIL@4 ; @ 95 +StrRetToStrN@16 ; @ 96 +SHWaitForFileToOpen@12 ; @ 97 +SHGetRealIDL@12 ; @ 98 +SetAppStartingCursor@8 ; @ 99 +SHRestricted@4 ; @ 100 +SHCoCreateInstance@20 ; @ 102 +SignalFileOpen@4 ; @ 103 +FileMenu_DeleteAllItems@4 ; @ 104 +FileMenu_DrawItem@8 ; @ 105 +FileMenu_FindSubMenuByPidl@8 ; @ 106 +FileMenu_GetLastSelectedItemPidls@12 ; @ 107 +FileMenu_HandleMenuChar@8 ; @ 108 +FileMenu_InitMenuPopup@4 ; @ 109 +FileMenu_InsertUsingPidl@24 ; @ 110 +FileMenu_Invalidate@4 ; @ 111 +FileMenu_MeasureItem@8 ; @ 112 +FileMenu_ReplaceUsingPidl@20 ; @ 113 +FileMenu_Create@20 ; @ 114 +FileMenu_AppendItem@24 ; @ 115 +FileMenu_TrackPopupMenuEx@24 ; @ 116 +FileMenu_DeleteItemByCmd@8 ; @ 117 +FileMenu_Destroy@4 ; @ 118 +IsLFNDrive@4 ; @ 119 +FileMenu_AbortInitMenu@0 ; @ 120 +SHFlushClipboard@0 ; @ 121 +;RunDLL_CallEntry16@20 ; @ 122 +SHFreeUnusedLibraries@0 ; @ 123 +FileMenu_AppendFilesForPidl@12 ; @ 124 +FileMenu_AddFilesForPidl@28 ; @ 125 +SHOutOfMemoryMessageBox@12 ; @ 126 +SHWinHelp@16 ; @ 127 +DllGetClassObject@12 ; @ 128 +DAD_AutoScroll@0 ; @ 129 +DAD_DragEnter@0 ; @ 130 +DAD_DragEnterEx@0 ; @ 131 +DAD_DragLeave@0 ; @ 132 +DragQueryFileW@16 ; @ 133 +DAD_DragMove@0 ; @ 134 +DragQueryPoint@8 ; @ 135 +DAD_SetDragImage@8 ; @ 136 +DAD_ShowDragImage@4 ; @ 137 +Desktop_UpdateBriefcaseOnEvent@0 ; @ 139 +FileMenu_DeleteItemByIndex@8 ; @ 140 +FileMenu_DeleteItemByFirstID@8 ; @ 141 +FileMenu_DeleteSeparator@4 ; @ 142 +FileMenu_EnableItemByCmd@12 ; @ 143 +FileMenu_GetItemExtent@8 ; @ 144 +PathFindOnPathA=PathFindOnPathA@8 ; @ 145 +RLBuildListOfPaths@0 ; @ 146 +SHCLSIDFromString@8 ; @ 147 +SHFind_InitMenuPopup@16 ; @ 149 +SHLoadOLE@4 ; @ 151 +ILGetSize@4 ; @ 152 +ILGetNext@4 ; @ 153 +ILAppend@12 ; @ 154 +ILFree@4 ; @ 155 +ILGlobalFree@4 ; @ 156 +ILCreateFromPath@4 ; @ 157 +PathGetExtensionA=PathGetExtensionA@4 ; @ 158 +PathIsDirectoryA=PathIsDirectoryA@4 ; @ 159 +SHNetConnectionDialog@0 ; @ 160 +SHRunControlPanel@8 ; @ 161 +SHSimpleIDListFromPath@4 ; @ 162 +StrToOleStr@8 ; @ 163 +Win32DeleteFile@4 ; @ 164 +SHCreateDirectory@8 ; @ 165 +CallCPLEntry16=CallCPLEntry16@24 ; @ 166 +SHAddFromPropSheetExtArray@12 ; @ 167 +SHCreatePropSheetExtArray@12 ; @ 168 +SHDestroyPropSheetExtArray@4 ; @ 169 +SHReplaceFromPropSheetExtArray@16 ; @ 170 +PathCleanupSpecA=PathCleanupSpecA@8 ; @ 171 +SHCreateLinks@0 ; @ 172 +SHValidateUNC@12 ; @ 173 +SHCreateShellFolderViewEx@8 ; @ 174 +SHGetSpecialFolderPath@16 ; @ 175 +SHSetInstanceExplorer@4 ; @ 176 +DAD_SetDragImageFromListView@0 ; @ 177 +SHObjectProperties@0 ; @ 178 +SHGetNewLinkInfoA@0 ; @ 179 +SHGetNewLinkInfoW@0 ; @ 180 +RegisterShellHook@8 ; @ 181 +ShellMessageBoxW ; @ 182 +ShellMessageBoxA ; @ 183 +ArrangeWindows@20 ; @ 184 +SHHandleDiskFull@0 ; @ 185 +SHFree@4 ; @ 195 +SHAlloc@4 ; @ 196 +SHGlobalDefect@0 ; @ 197 +SHAbortInvokeCommand@0 ; @ 198 +SHGetFileIcon@0 ; @ 199 +SHLocalAlloc@0 ; @ 200 +SHLocalFree@0 ; @ 201 +SHLocalReAlloc@0 ; @ 202 +AddCommasW@0 ; @ 203 +ShortSizeFormatW@0 ; @ 204 +Printer_LoadIconsW@0 ; @ 205 +Link_AddExtraDataSection@0 ; @ 206 +Link_ReadExtraDataSection@0 ; @ 207 +Link_RemoveExtraDataSection@0 ; @ 208 +Int64ToString@0 ; @ 209 +LargeIntegerToString@0 ; @ 210 +Printers_GetPidl@0 ; @ 211 +Printer_AddPrinterPropPages@0 ; @ 212 +Printers_RegisterWindowW@0 ; @ 213 +Printers_UnregisterWindow@0 ; @ 214 +SHStartNetConnectionDialog@12 ; @ 215 +shell32_243@8 ; @ 243 +SHInitRestricted@8 ; @ 244 +SHGetDataFromIDListA@20 ; @ 247 +SHGetDataFromIDListW@20 ; @ 248 +PathParseIconLocationA=PathParseIconLocationA@4 ; @ 249 +PathRemoveExtensionA=PathRemoveExtensionA@4 ; @ 250 +PathRemoveArgsA=PathRemoveArgsA@4 ; @ 251 +SheChangeDirA@0 ; @ 271 +SheChangeDirExA@0 ; @ 272 +SheChangeDirExW@0 ; @ 273 +SheChangeDirW@4 ; @ 274 +SheConvertPathW@0 ; @ 275 +SheFullPathA@0 ; @ 276 +SheFullPathW@0 ; @ 277 +SheGetCurDrive@0 ; @ 278 +SheGetDirA@8 ; @ 279 +SheGetDirExW@12 ; @ 280 +SheGetDirW@8 ; @ 281 +SheGetPathOffsetW@0 ; @ 282 +SheRemoveQuotesA@0 ; @ 283 +SheRemoveQuotesW@0 ; @ 284 +SheSetCurDrive@0 ; @ 285 +SheShortenPathA@0 ; @ 286 +SheShortenPathW@0 ; @ 287 +ShellAboutA=ShellAboutA@16 ; @ 288 +ShellAboutW=ShellAboutW@16 ; @ 289 +;ShellExecuteA=ShellExecuteA@24 ; @ 290 +;ShellExecuteEx@4 ; @ 291 +ShellExecuteExA=ShellExecuteExA@4 ; @ 292 +ShellExecuteExW@4 ; @ 293 +ShellExecuteW@24 ; @ 294 +;Shell_NotifyIcon@8 ; @ 296 +Shell_NotifyIconA@8 ; @ 297 +Shell_NotifyIconW@8 ; @ 298 +Shl1632_ThunkData32@0 ; @ 299 +Shl3216_ThunkData32@0 ; @ 300 +; StrChrA=shlwapi.StrChrA ; @ 301 +; StrChrIA=shlwapi.StrChrIA ; @ 302 +; StrChrIW=shlwapi.StrChrIW ; @ 303 +; StrChrW=shlwapi.StrChrW ; @ 304 +; StrCmpNA=shlwapi.StrCmpNA ; @ 305 +; StrCmpNIA=shlwapi.StrCmpNIA ; @ 306 +; StrCmpNIW=shlwapi.StrCmpNIW ; @ 307 +; StrCmpNW=shlwapi.StrCmpNW ; @ 308 +StrCpyNA=StrCpyNA@12 ; @ 309 +; StrCpyNW=shlwapi.StrCpyNW ; @ 310 +; StrNCmpA=shlwapi.StrCmpNA ; @ 311 +; StrNCmpIA=shlwapi.StrCmpNIA ; @ 312 +; StrNCmpIW=shlwapi.StrCmpNIW ; @ 313 +; StrNCmpW=shlwapi.StrCmpNW ; @ 314 +StrNCpyA@12 ; @ 315 +; StrNCpyW=shlwapi.StrNCpyW ; @ 316 +; StrRChrA=shlwapi.StrRChrA ; @ 317 +; StrRChrIA=shlwapi.StrRChrIA ; @ 318 +; StrRChrIW=shlwapi.StrRChrIW ; @ 319 +; StrRChrW=shlwapi.StrRChrW ; @ 320 +StrRStrA@0 ; @ 321 +; StrRStrIA=shlwapi.StrRStrIA ; @ 322 +; StrRStrIW=shlwapi.StrRStrIW ; @ 323 +StrRStrW@0 ; @ 324 +; StrStrA=shlwapi.StrStrA ; @ 325 +; StrStrIA=shlwapi.StrStrIA ; @ 326 +; StrStrIW=shlwapi.StrStrIW ; @ 327 +; StrStrW=shlwapi.StrStrW ; @ 328 +SHRegCloseKey@4 ; @ 505 +SHRegOpenKeyA@12 ; @ 506 +SHRegOpenKeyW@12 ; @ 507 +SHRegQueryValueA@16 ; @ 508 +SHRegQueryValueExA@24 ; @ 509 +SHRegQueryValueW@16 ; @ 510 +SHRegQueryValueExW@24 ; @ 511 +SHRegDeleteKeyW@8 ; @ 512 +SHAllocShared@12 ; @ 520 +SHLockShared@8 ; @ 521 +SHUnlockShared@4 ; @ 522 +SHFreeShared@8 ; @ 523 +RealDriveType@8 ; @ 524 +RealDriveTypeFlags@8 ; @ 525 +NTSHChangeNotifyRegister@24 ; @ 640 +NTSHChangeNotifyDeregister@4 ; @ 641 +SHChangeNotifyReceive@16 ; @ 643 +SHChangeNotification_Lock@16 ; @ 644 +SHChangeNotification_Unlock@4 ; @ 645 +SHChangeRegistrationReceive@8 ; @ 646 +ReceiveAddToRecentDocs@8 ; @ 647 +SHWaitOp_Operate@8 ; @ 648 +PathIsSameRootA=PathIsSameRootA@8 ; @ 650 +ReadCabinetState@8 ; @ 651 +WriteCabinetState@4 ; @ 652 +PathProcessCommand@16 ; @ 653 +shell32_654@8 ; @ 654 +FileIconInit@4 ; @ 660 +IsUserAdmin@0 ; @ 680 +shell32_714@4 ; @ 714 +FOOBAR1217@0 ; @ 1217 +CheckEscapesA@0 +CheckEscapesW@0 +CommandLineToArgvW@8 +;Control_FillCache_RunDLL=Control_FillCache_RunDLL@16 +Control_FillCache_RunDLLA=Control_FillCache_RunDLLA@16 +Control_FillCache_RunDLLW=Control_FillCache_RunDLLW@16 +;Control_RunDLL=Control_RunDLL@16 +Control_RunDLLA=Control_RunDLLA@16 +Control_RunDLLW=Control_RunDLLW@16 +DllInstall=DllInstall@8 +;DoEnvironmentSubstA=DoEnvironmentSubstA@8 +DoEnvironmentSubstW=DoEnvironmentSubstW@8 +DragQueryFileAorW@0 +DuplicateIcon@8 +ExtractAssociatedIconA@12 +ExtractAssociatedIconExA@0 +ExtractAssociatedIconExW@0 +ExtractAssociatedIconW@12 +ExtractIconA=ExtractIconA@12 +;ExtractIconEx@20 +ExtractIconExA@20 +ExtractIconExW@20 +ExtractIconW@12 +ExtractIconResInfoA@0 +ExtractIconResInfoW@0 +ExtractVersionResource16W@0 +FindExeDlgProc@0 +FindExecutableA@12 +FindExecutableW@12 +FreeIconList@4 +InternalExtractIconListA@0 +InternalExtractIconListW@0 +OpenAs_RunDLL@0 +OpenAs_RunDLLA@0 +OpenAs_RunDLLW@0 +PrintersGetCommand_RunDLL@0 +PrintersGetCommand_RunDLLA@0 +PrintersGetCommand_RunDLLW@0 +RealShellExecuteA@0 +RealShellExecuteExA@0 +RealShellExecuteExW@0 +RealShellExecuteW@0 +RegenerateUserEnvironment@0 +SHAddToRecentDocs@8 +SHAppBarMessage@8 +SHBrowseForFolder@4 +SHBrowseForFolderA@4 +SHBrowseForFolderW@4 +SHChangeNotify@16 +ShellHookProc@0 +SHEmptyRecycleBinA@12 +SHEmptyRecycleBinW@12 +;SHFileOperation@4 +SHFileOperationA@4 +SHFileOperationW@4 +SHFormatDrive@16 +SHFreeNameMappings@4 +SHGetDesktopFolder@4 +;SHGetFileInfo@20 +SHGetFileInfoA@20 +SHGetFileInfoW@20 +SHGetInstanceExplorer@4 +SHGetMalloc=SHGetMalloc@4 +;SHGetNewLinkInfo@20 +SHGetPathFromIDList=SHGetPathFromIDList@8 +SHGetPathFromIDListA=SHGetPathFromIDListA@8 +SHGetPathFromIDListW=SHGetPathFromIDListW@8 +SHGetSettings@8 +SHGetSpecialFolderLocation=SHGetSpecialFolderLocation@12 +SHHelpShortcuts_RunDLL@16 +SHHelpShortcuts_RunDLLA@16 +SHHelpShortcuts_RunDLLW@16 +SHLoadInProc@4 +SHQueryRecycleBinA@8 +SHQueryRecycleBinW@8 +SHUpdateRecycleBinIcon@0 +WOWShellExecute@28 +DllCanUnloadNow@0 +DllGetVersion@4 +SHGetFreeDiskSpace@0 +SHGetSpecialFolderPathA@16 +SHGetFolderPathA@20 +SHGetFolderPathW@20 +SHGetFolderLocation@20 + diff --git a/lib/shell32/shell32.h b/lib/shell32/shell32.h new file mode 100644 index 0000000..2048498 --- /dev/null +++ b/lib/shell32/shell32.h @@ -0,0 +1,104 @@ +/* + * ReactOS shell32 - + * + * shell32.h + * + * Copyright (C) 2002 Robert Dickenson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SHELL32_H__ +#define __SHELL32_H__ + + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include + +#ifdef _MSC_VER +#define inline +#pragma warning (disable:4273) // : inconsistent dll linkage. dllexport assumed. +#pragma warning (disable:4018) // : signed/unsigned mismatch +#pragma warning (disable:4141) // : 'dllexport' : used more than once + +#undef WINAPI +#define WINAPI __declspec(dllexport) +#define STDCALL __stdcall +#define WINBOOL BOOL + +#else + +//#define WINAPI STDCALL + +typedef struct _SHQUERYRBINFO { + DWORD cbSize; + __int64 i64Size; + __int64 i64NumItems; +} SHQUERYRBINFO, *LPSHQUERYRBINFO; + +#define DWORD_PTR DWORD* + +/* +#define STDAPI long __stdcall + +typedef struct _SHELLEXECUTEINFO{ + DWORD cbSize; + ULONG fMask; + HWND hwnd; + LPCTSTR lpVerb; + LPCTSTR lpFile; + LPCTSTR lpParameters; + LPCTSTR lpDirectory; + int nShow; + HINSTANCE hInstApp; + + // Optional members + LPVOID lpIDList; + LPCSTR lpClass; + HKEY hkeyClass; + DWORD dwHotKey; + union { + HANDLE hIcon; + HANDLE hMonitor; + }; + HANDLE hProcess; +} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO; + +typedef struct _NOTIFYICONDATA { + DWORD cbSize; + HWND hWnd; + UINT uID; + UINT uFlags; + UINT uCallbackMessage; + HICON hIcon; + TCHAR szTip[64]; + DWORD dwState; //Version 5.0 + DWORD dwStateMask; //Version 5.0 + TCHAR szInfo[256]; //Version 5.0 + union { + UINT uTimeout; //Version 5.0 + UINT uVersion; //Version 5.0 + } DUMMYUNIONNAME; + TCHAR szInfoTitle[64]; //Version 5.0 + DWORD dwInfoFlags; //Version 5.0 +} NOTIFYICONDATA, *PNOTIFYICONDATA; + + */ +/* + */ +#endif + + +#endif /* __SHELL32_H__ */ diff --git a/lib/shell32/shell32.rc b/lib/shell32/shell32.rc new file mode 100644 index 0000000..699027d --- /dev/null +++ b/lib/shell32/shell32.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Shell32 Common Library\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "shell32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "shell32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/snmpapi/.cvsignore b/lib/snmpapi/.cvsignore new file mode 100644 index 0000000..31883d6 --- /dev/null +++ b/lib/snmpapi/.cvsignore @@ -0,0 +1,23 @@ +snmpapi.a +snmpapi.dll +snmpapi.nostrip.dll +snmpapi.coff +base.tmp +junk.tmp +temp.exp +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/snmpapi/debug.h b/lib/snmpapi/debug.h new file mode 100644 index 0000000..13a623f --- /dev/null +++ b/lib/snmpapi/debug.h @@ -0,0 +1,65 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 Helper DLL for TCP/IP + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define WSH_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { WSH_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define WSH_DbgPrint(_t_, _x_) + +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + WSH_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \ + please try again later.\n", __FILE__, __LINE__, __FUNCTION__)); + +#define CHECKPOINT \ + WSH_DbgPrint(MIN_TRACE, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/snmpapi/makefile b/lib/snmpapi/makefile new file mode 100644 index 0000000..05b4b17 --- /dev/null +++ b/lib/snmpapi/makefile @@ -0,0 +1,19 @@ +# $Id: makefile + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = snmpapi + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = -DUNICODE + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/snmpapi/snmpapi.c b/lib/snmpapi/snmpapi.c new file mode 100644 index 0000000..eafecd5 --- /dev/null +++ b/lib/snmpapi/snmpapi.c @@ -0,0 +1,408 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Sockets 2 Simple Network Management Protocol API DLL + * FILE: snmpapi.c + * PURPOSE: DLL entry + * PROGRAMMERS: Robert Dickenson (robd@reactos.org) + * REVISIONS: + * RDD August 18, 2002 Created + */ +//#include "snmpapi.h" + + +#ifdef __GNUC__ +#include +#else +#include +#endif +#include + +#ifdef __GNUC__ +#define SNMP_FUNC_TYPE STDCALL +#endif +#include +#include "debug.h" + + +#ifdef __GNUC__ +#define EXPORT STDCALL +#else +#define EXPORT CALLBACK +#endif + + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + + +DWORD dwUptimeStartTicks; + + +/* To make the linker happy */ +//VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +BOOL +EXPORT +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + WSH_DbgPrint(MIN_TRACE, ("DllMain of snmpapi.dll\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications + so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +/* +? SnmpSvcAddrIsIpx +? SnmpSvcAddrToSocket +? SnmpSvcGetEnterpriseOID +? SnmpTfxClose +? SnmpTfxOpen +? SnmpTfxQuery +? SnmpUtilAnsiToUnicode +? SnmpUtilUTF8ToUnicode +? SnmpUtilUnicodeToAnsi +? SnmpUtilUnicodeToUTF8 + */ +//////////////////////////////////////////////////////////////////////////////// + +VOID +SNMP_FUNC_TYPE +SnmpSvcAddrIsIpx(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpSvcAddrToSocket(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpSvcGetEnterpriseOID(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +LPVOID +SNMP_FUNC_TYPE +SnmpUtilMemAlloc(UINT nBytes) +{ + VOID* pMem = NULL; + pMem = GlobalAlloc(GPTR, nBytes); + return pMem; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilMemFree(LPVOID pMem) +{ + GlobalFree(pMem); +} + +LPVOID +SNMP_FUNC_TYPE +SnmpUtilMemReAlloc(LPVOID pMem, UINT nBytes) +{ + pMem = GlobalReAlloc(pMem, nBytes, GPTR); + return pMem; +} + +VOID +SNMP_FUNC_TYPE +SnmpSvcInitUptime() +{ + dwUptimeStartTicks = GetTickCount(); +} + +DWORD +SNMP_FUNC_TYPE +SnmpSvcGetUptime() +{ + DWORD dwUptime; + DWORD dwTickCount = GetTickCount(); + dwUptime = dwTickCount - dwUptimeStartTicks; + return dwUptime; +} + +VOID +SNMP_FUNC_TYPE +SnmpSvcSetLogLevel(INT nLogLevel) +{ + switch (nLogLevel) { + case SNMP_LOG_SILENT: + break; + case SNMP_LOG_FATAL: + break; + case SNMP_LOG_ERROR: + break; + case SNMP_LOG_WARNING: + break; + case SNMP_LOG_TRACE: + break; + case SNMP_LOG_VERBOSE: + break; + } + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpSvcSetLogType(INT nLogType) +{ + switch (nLogType) { + case SNMP_OUTPUT_TO_CONSOLE: + break; + case SNMP_OUTPUT_TO_LOGFILE: + break; + case SNMP_OUTPUT_TO_DEBUGGER: + break; + } + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpTfxClose(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpTfxOpen(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpTfxQuery(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilAnsiToUnicode(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilAsnAnyCpy(AsnAny *pAnyDst, AsnAny *pAnySrc) +{ + UNIMPLEMENTED + return 0; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilAsnAnyFree(AsnAny *pAny) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilDbgPrint(INT nLogLevel, LPSTR szFormat, ...) +{ + switch (nLogLevel) { + case SNMP_LOG_SILENT: + break; + case SNMP_LOG_FATAL: + break; + case SNMP_LOG_ERROR: + break; + case SNMP_LOG_WARNING: + break; + case SNMP_LOG_TRACE: + break; + case SNMP_LOG_VERBOSE: + break; + } + UNIMPLEMENTED +} + +LPSTR +SNMP_FUNC_TYPE +SnmpUtilIdsToA(UINT *Ids, UINT IdLength) +{ + UNIMPLEMENTED + return 0; +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOctetsCmp(AsnOctetString *pOctets1, AsnOctetString *pOctets2) +{ + UNIMPLEMENTED + return 0; +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOctetsCpy(AsnOctetString *pOctetsDst, AsnOctetString *pOctetsSrc) +{ + UNIMPLEMENTED + return 0; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilOctetsFree(AsnOctetString *pOctets) +{ + UNIMPLEMENTED +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOctetsNCmp(AsnOctetString *pOctets1, AsnOctetString *pOctets2, UINT nChars) +{ + UNIMPLEMENTED + return 0; +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOidAppend(AsnObjectIdentifier *pOidDst, AsnObjectIdentifier *pOidSrc) +{ + //SnmpUtilMemReAlloc(pOidDst, sizeof(AsnObjectIdentifier)); + //SetLastError(SNMP_BERAPI_OVERFLOW); + SetLastError(SNMP_MEM_ALLOC_ERROR); + return 0; // failed +} + + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOidCmp(AsnObjectIdentifier *pOid1, AsnObjectIdentifier *pOid2) +{ + UNIMPLEMENTED + return 0; +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOidCpy(AsnObjectIdentifier *pOidDst, AsnObjectIdentifier *pOidSrc) +{ + UNIMPLEMENTED + return 0; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilOidFree(AsnObjectIdentifier *pOid) +{ + UNIMPLEMENTED +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilOidNCmp(AsnObjectIdentifier *pOid1, AsnObjectIdentifier *pOid2, UINT nSubIds) +{ + UNIMPLEMENTED + return 0; +} + +LPSTR +SNMP_FUNC_TYPE +SnmpUtilOidToA(AsnObjectIdentifier *Oid) +{ + UNIMPLEMENTED + return 0; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilPrintAsnAny(AsnAny *pAny) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilPrintOid(AsnObjectIdentifier *Oid) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilUTF8ToUnicode(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilUnicodeToAnsi(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilUnicodeToUTF8(void* unknown, void* unknown2) +{ + UNIMPLEMENTED +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilVarBindCpy(SnmpVarBind *pVbDst, SnmpVarBind *pVbSrc) +{ + UNIMPLEMENTED + return 0; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilVarBindFree(SnmpVarBind *pVb) +{ + UNIMPLEMENTED +} + +SNMPAPI +SNMP_FUNC_TYPE +SnmpUtilVarBindListCpy(SnmpVarBindList *pVblDst, SnmpVarBindList *pVblSrc) +{ + UNIMPLEMENTED + return 0; +} + +VOID +SNMP_FUNC_TYPE +SnmpUtilVarBindListFree(SnmpVarBindList *pVbl) +{ + UNIMPLEMENTED +} + +/* EOF */ + diff --git a/lib/snmpapi/snmpapi.def b/lib/snmpapi/snmpapi.def new file mode 100644 index 0000000..fa018b7 --- /dev/null +++ b/lib/snmpapi/snmpapi.def @@ -0,0 +1,43 @@ +; SNMPAPI.DLL - ReactOS Sockets 2 Simple Network Management Protocol API DLL + +LIBRARY snmpapi.dll + +EXPORTS +SnmpSvcAddrIsIpx +SnmpSvcAddrToSocket +SnmpSvcGetEnterpriseOID +SnmpSvcGetUptime +SnmpSvcInitUptime +SnmpSvcSetLogLevel +SnmpSvcSetLogType +SnmpTfxClose +SnmpTfxOpen +SnmpTfxQuery +SnmpUtilAnsiToUnicode +SnmpUtilAsnAnyCpy +SnmpUtilAsnAnyFree +SnmpUtilDbgPrint +SnmpUtilIdsToA +SnmpUtilMemAlloc +SnmpUtilMemFree +SnmpUtilMemReAlloc +SnmpUtilOctetsCmp +SnmpUtilOctetsCpy +SnmpUtilOctetsFree +SnmpUtilOctetsNCmp +SnmpUtilOidAppend +SnmpUtilOidCmp +SnmpUtilOidCpy +SnmpUtilOidFree +SnmpUtilOidNCmp +SnmpUtilOidToA +SnmpUtilPrintAsnAny +SnmpUtilPrintOid +SnmpUtilUTF8ToUnicode +SnmpUtilUnicodeToAnsi +SnmpUtilUnicodeToUTF8 +SnmpUtilVarBindCpy +SnmpUtilVarBindFree +SnmpUtilVarBindListCpy +SnmpUtilVarBindListFree +; EOF diff --git a/lib/snmpapi/snmpapi.edf b/lib/snmpapi/snmpapi.edf new file mode 100644 index 0000000..ec27c96 --- /dev/null +++ b/lib/snmpapi/snmpapi.edf @@ -0,0 +1,43 @@ +; SNMPAPI.DLL - ReactOS Sockets 2 Simple Network Management Protocol API DLL + +LIBRARY snmpapi.dll + +EXPORTS +SnmpSvcAddrIsIpx=SnmpSvcAddrIsIpx@8 +SnmpSvcAddrToSocket=SnmpSvcAddrToSocket@8 +SnmpSvcGetEnterpriseOID=SnmpSvcGetEnterpriseOID@8 +SnmpSvcGetUptime=SnmpSvcGetUptime@0 +SnmpSvcInitUptime=SnmpSvcInitUptime@0 +SnmpSvcSetLogLevel=SnmpSvcSetLogLevel@4 +SnmpSvcSetLogType=SnmpSvcSetLogType@4 +SnmpTfxClose=SnmpTfxClose@8 +SnmpTfxOpen=SnmpTfxOpen@8 +SnmpTfxQuery=SnmpTfxQuery@8 +SnmpUtilAnsiToUnicode=SnmpUtilAnsiToUnicode@8 +SnmpUtilAsnAnyCpy=SnmpUtilAsnAnyCpy@8 +SnmpUtilAsnAnyFree=SnmpUtilAsnAnyFree@4 +SnmpUtilDbgPrint=SnmpUtilDbgPrint@0 +SnmpUtilIdsToA=SnmpUtilIdsToA@8 +SnmpUtilMemAlloc=SnmpUtilMemAlloc@4 +SnmpUtilMemFree=SnmpUtilMemFree@4 +SnmpUtilMemReAlloc=SnmpUtilMemReAlloc@8 +SnmpUtilOctetsCmp=SnmpUtilOctetsCmp@8 +SnmpUtilOctetsCpy=SnmpUtilOctetsCpy@8 +SnmpUtilOctetsFree=SnmpUtilOctetsFree@4 +SnmpUtilOctetsNCmp=SnmpUtilOctetsNCmp@12 +SnmpUtilOidAppend=SnmpUtilOidAppend@8 +SnmpUtilOidCmp=SnmpUtilOidCmp@8 +SnmpUtilOidCpy=SnmpUtilOidCpy@8 +SnmpUtilOidFree=SnmpUtilOidFree@4 +SnmpUtilOidNCmp=SnmpUtilOidNCmp@12 +SnmpUtilOidToA=SnmpUtilOidToA@4 +SnmpUtilPrintAsnAny=SnmpUtilPrintAsnAny@4 +SnmpUtilPrintOid=SnmpUtilPrintOid@4 +SnmpUtilUTF8ToUnicode=SnmpUtilUTF8ToUnicode@8 +SnmpUtilUnicodeToAnsi=SnmpUtilUnicodeToAnsi@8 +SnmpUtilUnicodeToUTF8=SnmpUtilUnicodeToUTF8@8 +SnmpUtilVarBindCpy=SnmpUtilVarBindCpy@8 +SnmpUtilVarBindFree=SnmpUtilVarBindFree@4 +SnmpUtilVarBindListCpy=SnmpUtilVarBindListCpy@8 +SnmpUtilVarBindListFree=SnmpUtilVarBindListFree@4 +; EOF diff --git a/lib/snmpapi/snmpapi.rc b/lib/snmpapi/snmpapi.rc new file mode 100644 index 0000000..01b7b1c --- /dev/null +++ b/lib/snmpapi/snmpapi.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Sockets 2 SNMP Helper API\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "snmpapi\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "snmpapi.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/user32/.cvsignore b/lib/user32/.cvsignore new file mode 100644 index 0000000..b0d7240 --- /dev/null +++ b/lib/user32/.cvsignore @@ -0,0 +1,9 @@ +base.tmp +junk.tmp +user32.coff +user32.dll +user32.nostrip.dll +*.d +*.a +*.o +*.sym diff --git a/lib/user32/Makefile b/lib/user32/Makefile new file mode 100644 index 0000000..8bf5b11 --- /dev/null +++ b/lib/user32/Makefile @@ -0,0 +1,76 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = user32 + +TARGET_BASE = 0x77e70000 + +TARGET_SDKLIBS = ntdll.a kernel32.a gdi32.a + +TARGET_CFLAGS = -I./include -DUNICODE -Wall -Werror + +TARGET_OBJECTS = $(TARGET_NAME).o + +TARGET_CLEAN = misc/*.o windows/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +CONTROLS_OBJECTS = \ + controls/combobox.o \ + controls/listbox.o \ + controls/scrollbar.o + +MISC_OBJECTS = \ + misc/dde.o \ + misc/desktop.o \ + misc/display.o \ + misc/dllmain.o \ + misc/exit.o \ + misc/sprintf.o \ + misc/stubs.o \ + misc/winhelp.o \ + misc/win32k.o \ + misc/winsta.o \ + misc/resources.o \ + misc/object.o \ + misc/timer.o + +WINDOWS_OBJECTS = \ + windows/class.o \ + windows/message.o \ + windows/window.o \ + windows/defwnd.o \ + windows/accel.o \ + windows/bitmap.o \ + windows/clipboard.o \ + windows/cursor.o \ + windows/dc.o \ + windows/dialog.o \ + windows/draw.o \ + windows/font.o \ + windows/hook.o \ + windows/icon.o \ + windows/input.o \ + windows/mdi.o \ + windows/menu.o \ + windows/messagebox.o \ + windows/nonclient.o \ + windows/paint.o \ + windows/prop.o \ + windows/rect.o \ + windows/text.o + +OBJECTS = \ + $(MISC_OBJECTS) \ + $(WINDOWS_OBJECTS) \ + $(CONTROLS_OBJECTS) + +$(TARGET_NAME).o: $(OBJECTS) + $(LD) -r $(OBJECTS) -o $(TARGET_NAME).o + +# EOF diff --git a/lib/user32/controls/.cvsignore b/lib/user32/controls/.cvsignore new file mode 100644 index 0000000..c0b927e --- /dev/null +++ b/lib/user32/controls/.cvsignore @@ -0,0 +1,4 @@ +*.d +*.a +*.o +*.sym diff --git a/lib/user32/controls/combobox.c b/lib/user32/controls/combobox.c new file mode 100644 index 0000000..6ffdbdf --- /dev/null +++ b/lib/user32/controls/combobox.c @@ -0,0 +1,42 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/controls/combobox.c + * PURPOSE: Combo box + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +GetComboBoxInfo(HWND hwndCombo, + PCOMBOBOXINFO pcbi) +{ + return FALSE; +} diff --git a/lib/user32/controls/listbox.c b/lib/user32/controls/listbox.c new file mode 100644 index 0000000..fe44404 --- /dev/null +++ b/lib/user32/controls/listbox.c @@ -0,0 +1,41 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/controls/listbox.c + * PURPOSE: List box + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +DWORD STDCALL +GetListBoxInfo(HWND hwnd) +{ + return 0; +} diff --git a/lib/user32/controls/scrollbar.c b/lib/user32/controls/scrollbar.c new file mode 100644 index 0000000..45caa32 --- /dev/null +++ b/lib/user32/controls/scrollbar.c @@ -0,0 +1,103 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/controls/scrollbar.c + * PURPOSE: Scroll bar + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +GetScrollBarInfo(HWND hwnd, + LONG idObject, + PSCROLLBARINFO psbi) +{ + return FALSE; +} + +WINBOOL STDCALL +GetScrollInfo(HWND hwnd, + int fnBar, + LPSCROLLINFO lpsi) +{ + return FALSE; +} + +int STDCALL +GetScrollPos(HWND hWnd, + int nBar) +{ + return 0; +} + +WINBOOL STDCALL +GetScrollRange(HWND hWnd, + int nBar, + LPINT lpMinPos, + LPINT lpMaxPos) +{ + return FALSE; +} + +int STDCALL +SetScrollInfo(HWND hwnd, + int fnBar, + LPCSCROLLINFO lpsi, + WINBOOL fRedraw) +{ + return 0; +} + +int STDCALL +SetScrollPos(HWND hWnd, + int nBar, + int nPos, + WINBOOL bRedraw) +{ + return 0; +} + +WINBOOL STDCALL +SetScrollRange(HWND hWnd, + int nBar, + int nMinPos, + int nMaxPos, + WINBOOL bRedraw) +{ + return FALSE; +} + +WINBOOL STDCALL +ShowScrollBar(HWND hWnd, + int wBar, + WINBOOL bShow) +{ + return FALSE; +} diff --git a/lib/user32/include/debug.h b/lib/user32/include/debug.h new file mode 100644 index 0000000..dc957fc --- /dev/null +++ b/lib/user32/include/debug.h @@ -0,0 +1,72 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_CHECK 0x00000100 +#define DEBUG_OBJECT 0x00000200 +#define DEBUG_WINDOW 0x00000400 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define D(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { D(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); } +#endif /* NASSERT */ + +#define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x)) + +#else /* DBG */ + +#define D(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + D(MIN_TRACE, ("is unimplemented, please try again later.\n")); + +#define CHECKPOINT \ + D(DEBUG_CHECK, ("\n")); + +#define DPRINT(X...) D(DEBUG_CHECK, (X)) + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/user32/include/user32.h b/lib/user32/include/user32.h new file mode 100644 index 0000000..8d31631 --- /dev/null +++ b/lib/user32/include/user32.h @@ -0,0 +1,11 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: include/user32.h + * PURPOSE: Global user32 definitions + */ +#include +#include + + + diff --git a/lib/user32/include/window.h b/lib/user32/include/window.h new file mode 100644 index 0000000..02eb0eb --- /dev/null +++ b/lib/user32/include/window.h @@ -0,0 +1,13 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: include/window.h + * PURPOSE: Window management definitions + */ +#include + +#define IS_ATOM(x) \ + (((ULONG_PTR)(x) > 0x0) && ((ULONG_PTR)(x) < 0x10000)) + +VOID +UserSetupInternalPos(VOID); diff --git a/lib/user32/include/winsta.h b/lib/user32/include/winsta.h new file mode 100644 index 0000000..0271481 --- /dev/null +++ b/lib/user32/include/winsta.h @@ -0,0 +1,6 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: include/winsta.h + * PURPOSE: Window stations + */ diff --git a/lib/user32/misc/.cvsignore b/lib/user32/misc/.cvsignore new file mode 100644 index 0000000..3afcbd3 --- /dev/null +++ b/lib/user32/misc/.cvsignore @@ -0,0 +1,5 @@ +win32k.c +*.d +*.a +*.o +*.sym diff --git a/lib/user32/misc/dde.c b/lib/user32/misc/dde.c new file mode 100644 index 0000000..e14e12d --- /dev/null +++ b/lib/user32/misc/dde.c @@ -0,0 +1,332 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/dde.c + * PURPOSE: DDE + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +DdeAbandonTransaction(DWORD idInst, + HCONV hConv, + DWORD idTransaction) +{ + return FALSE; +} + +LPBYTE STDCALL +DdeAccessData(HDDEDATA hData, + LPDWORD pcbDataSize) +{ + return (LPBYTE)0; +} + +HDDEDATA STDCALL +DdeAddData(HDDEDATA hData, + LPBYTE pSrc, + DWORD cb, + DWORD cbOff) +{ + return (HDDEDATA)0; +} + +HDDEDATA STDCALL +DdeClientTransaction(LPBYTE pData, + DWORD cbData, + HCONV hConv, + HSZ hszItem, + UINT wFmt, + UINT wType, + DWORD dwTimeout, + LPDWORD pdwResult) +{ + return (HDDEDATA)0; +} + +int STDCALL +DdeCmpStringHandles(HSZ hsz1, + HSZ hsz2) +{ + return 0; +} + +HCONV STDCALL +DdeConnect(DWORD idInst, + HSZ hszService, + HSZ hszTopic, + PCONVCONTEXT pCC) +{ + return (HCONV)0; +} + +HCONVLIST STDCALL +DdeConnectList(DWORD idInst, + HSZ hszService, + HSZ hszTopic, + HCONVLIST hConvList, + PCONVCONTEXT pCC) +{ + return (HCONVLIST)0; +} + +HDDEDATA STDCALL +DdeCreateDataHandle(DWORD idInst, + LPBYTE pSrc, + DWORD cb, + DWORD cbOff, + HSZ hszItem, + UINT wFmt, + UINT afCmd) +{ + return (HDDEDATA)0; +} + +HSZ STDCALL +DdeCreateStringHandleA(DWORD idInst, + LPSTR psz, + int iCodePage) +{ + return (HSZ)0; +} + +HSZ STDCALL +DdeCreateStringHandleW(DWORD idInst, + LPWSTR psz, + int iCodePage) +{ + return (HSZ)0; +} + +WINBOOL STDCALL +DdeDisconnect(HCONV hConv) +{ + return FALSE; +} + +WINBOOL STDCALL +DdeDisconnectList(HCONVLIST hConvList) +{ + return FALSE; +} + +WINBOOL STDCALL +DdeEnableCallback(DWORD idInst, + HCONV hConv, + UINT wCmd) +{ + return FALSE; +} + +WINBOOL STDCALL +DdeFreeDataHandle(HDDEDATA hData) +{ + return FALSE; +} + +BOOL +DdeFreeStringHandle(DWORD idInst, + HSZ hsz) +{ + return FALSE; +} + +DWORD STDCALL +DdeGetData(HDDEDATA hData, + LPBYTE pDst, + DWORD cbMax, + DWORD cbOff) +{ + return 0; +} + +UINT STDCALL +DdeGetLastError(DWORD idInst) +{ + return 0; +} + +WINBOOL STDCALL +DdeImpersonateClient(HCONV hConv) +{ + return FALSE; +} + +UINT STDCALL +DdeInitializeA(LPDWORD pidInst, + PFNCALLBACK pfnCallback, + DWORD afCmd, + DWORD ulRes) +{ + return 0; +} + +UINT STDCALL +DdeInitializeW(LPDWORD pidInst, + PFNCALLBACK pfnCallback, + DWORD afCmd, + DWORD ulRes) +{ + return 0; +} + +WINBOOL STDCALL +DdeKeepStringHandle(DWORD idInst, + HSZ hsz) +{ + return FALSE; +} + +HDDEDATA STDCALL +DdeNameService(DWORD idInst, + HSZ hsz1, + HSZ hsz2, + UINT afCmd) +{ + return (HDDEDATA)0; +} + +WINBOOL STDCALL +DdePostAdvise(DWORD idInst, + HSZ hszTopic, + HSZ hszItem) +{ + return FALSE; +} + +UINT STDCALL +DdeQueryConvInfo(HCONV hConv, + DWORD idTransaction, + PCONVINFO pConvInfo) +{ + return 0; +} + +HCONV STDCALL +DdeQueryNextServer(HCONVLIST hConvList, + HCONV hConvPrev) +{ + return (HCONV)0; +} + +DWORD STDCALL +DdeQueryStringA(DWORD idInst, + HSZ hsz, + LPSTR psz, + DWORD cchMax, + int iCodePage) +{ + return 0; +} + +DWORD STDCALL +DdeQueryStringW(DWORD idInst, + HSZ hsz, + LPWSTR psz, + DWORD cchMax, + int iCodePage) +{ + return 0; +} + +HCONV STDCALL +DdeReconnect(HCONV hConv) +{ + return (HCONV)0; +} + +WINBOOL STDCALL +DdeSetQualityOfService(HWND hwndClient, + CONST SECURITY_QUALITY_OF_SERVICE *pqosNew, + PSECURITY_QUALITY_OF_SERVICE pqosPrev) +{ + return FALSE; +} + +WINBOOL STDCALL +DdeSetUserHandle(HCONV hConv, + DWORD id, + DWORD_PTR hUser) +{ + return FALSE; +} + +WINBOOL STDCALL +DdeUnaccessData(HDDEDATA hData) +{ + return FALSE; +} + +WINBOOL STDCALL +DdeUninitialize(DWORD idInst) +{ + return FALSE; +} + +WINBOOL STDCALL +FreeDDElParam(UINT msg, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL STDCALL +ImpersonateDdeClientWindow(HWND hWndClient, + HWND hWndServer) +{ + return FALSE; +} + +LPARAM STDCALL +PackDDElParam(UINT msg, + UINT_PTR uiLo, + UINT_PTR uiHi) +{ + return (LPARAM)0; +} + +LPARAM STDCALL +ReuseDDElParam(LPARAM lParam, + UINT msgIn, + UINT msgOut, + UINT_PTR uiLo, + UINT_PTR uiHi) +{ + return (LPARAM)0; +} + +WINBOOL STDCALL +UnpackDDElParam(UINT msg, + LPARAM lParam, + PUINT_PTR puiLo, + PUINT_PTR puiHi) +{ + return FALSE; +} diff --git a/lib/user32/misc/desktop.c b/lib/user32/misc/desktop.c new file mode 100644 index 0000000..6c9c5d7 --- /dev/null +++ b/lib/user32/misc/desktop.c @@ -0,0 +1,256 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/desktop.c + * PURPOSE: Desktops + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 06-06-2001 CSH Created + */ +#include +#include +#include +#include + +int STDCALL +GetSystemMetrics(int nIndex) +{ + return(NtUserGetSystemMetrics(nIndex)); +} + +WINBOOL STDCALL +SystemParametersInfoA(UINT uiAction, + UINT uiParam, + PVOID pvParam, + UINT fWinIni) +{ + return(SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni)); +} + +WINBOOL STDCALL +SystemParametersInfoW(UINT uiAction, + UINT uiParam, + PVOID pvParam, + UINT fWinIni) +{ + NONCLIENTMETRICS *nclm; + + /* FIXME: This should be obtained from the registry */ + static LOGFONT CaptionFont = + { 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET, + 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"Timmons" }; + + switch (uiAction) + { + case SPI_GETWORKAREA: + { + ((PRECT)pvParam)->left = 0; + ((PRECT)pvParam)->top = 0; + ((PRECT)pvParam)->right = 640; + ((PRECT)pvParam)->bottom = 480; + return(TRUE); + } + case SPI_GETNONCLIENTMETRICS: + { + nclm = pvParam; + memcpy(&nclm->lfCaptionFont, &CaptionFont, sizeof(LOGFONT)); + memcpy(&nclm->lfSmCaptionFont, &CaptionFont, sizeof(LOGFONT)); + return(TRUE); + } + } + return(FALSE); +} + + +WINBOOL +STDCALL +CloseDesktop( + HDESK hDesktop) +{ + return NtUserCloseDesktop(hDesktop); +} + +HDESK STDCALL +CreateDesktopA(LPCSTR lpszDesktop, + LPCSTR lpszDevice, + LPDEVMODEA pDevmode, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa) +{ + ANSI_STRING DesktopNameA; + UNICODE_STRING DesktopNameU; + HDESK hDesktop; + + if (lpszDesktop != NULL) + { + RtlInitAnsiString(&DesktopNameA, (LPSTR)lpszDesktop); + RtlAnsiStringToUnicodeString(&DesktopNameU, &DesktopNameA, TRUE); + } + else + { + RtlInitUnicodeString(&DesktopNameU, NULL); + } + /* FIXME: Need to convert the DEVMODE parameter. */ + + hDesktop = CreateDesktopW(DesktopNameU.Buffer, + NULL, + (LPDEVMODEW)pDevmode, + dwFlags, + dwDesiredAccess, + lpsa); + + RtlFreeUnicodeString(&DesktopNameU); + return(hDesktop); +} + +HDESK STDCALL +CreateDesktopW(LPCWSTR lpszDesktop, + LPCWSTR lpszDevice, + LPDEVMODEW pDevmode, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa) +{ + UNICODE_STRING DesktopName; + HWINSTA hWinSta; + HDESK hDesktop; + + hWinSta = NtUserGetProcessWindowStation(); + + RtlInitUnicodeString(&DesktopName, lpszDesktop); + + hDesktop = NtUserCreateDesktop(&DesktopName, + dwFlags, + dwDesiredAccess, + lpsa, + hWinSta); + + return(hDesktop); +} + +WINBOOL +STDCALL +EnumDesktopWindows( + HDESK hDesktop, + ENUMWINDOWSPROC lpfn, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDesktopsA( + HWINSTA hwinsta, + DESKTOPENUMPROC lpEnumFunc, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDesktopsW( + HWINSTA hwinsta, + DESKTOPENUMPROC lpEnumFunc, + LPARAM lParam) +{ + return FALSE; +} + +HDESK +STDCALL +GetThreadDesktop( + DWORD dwThreadId) +{ + return NtUserGetThreadDesktop(dwThreadId, 0); +} + +HDESK +STDCALL +OpenDesktopA( + LPSTR lpszDesktop, + DWORD dwFlags, + WINBOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + ANSI_STRING DesktopNameA; + UNICODE_STRING DesktopNameU; + HDESK hDesktop; + + if (lpszDesktop != NULL) { + RtlInitAnsiString(&DesktopNameA, lpszDesktop); + RtlAnsiStringToUnicodeString(&DesktopNameU, &DesktopNameA, TRUE); + } else { + RtlInitUnicodeString(&DesktopNameU, NULL); + } + + hDesktop = OpenDesktopW( + DesktopNameU.Buffer, + dwFlags, + fInherit, + dwDesiredAccess); + + RtlFreeUnicodeString(&DesktopNameU); + + return hDesktop; +} + +HDESK +STDCALL +OpenDesktopW( + LPWSTR lpszDesktop, + DWORD dwFlags, + WINBOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + UNICODE_STRING DesktopName; + + RtlInitUnicodeString(&DesktopName, lpszDesktop); + + return NtUserOpenDesktop( + &DesktopName, + dwFlags, + dwDesiredAccess); +} + +HDESK +STDCALL +OpenInputDesktop( + DWORD dwFlags, + WINBOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + return NtUserOpenInputDesktop( + dwFlags, + fInherit, + dwDesiredAccess); +} + +WINBOOL +STDCALL +PaintDesktop( + HDC hdc) +{ + return NtUserPaintDesktop(hdc); +} + +WINBOOL +STDCALL +SetThreadDesktop( + HDESK hDesktop) +{ + return NtUserSetThreadDesktop(hDesktop); +} + +WINBOOL +STDCALL +SwitchDesktop( + HDESK hDesktop) +{ + return NtUserSwitchDesktop(hDesktop); +} + +/* EOF */ diff --git a/lib/user32/misc/display.c b/lib/user32/misc/display.c new file mode 100644 index 0000000..966a49c --- /dev/null +++ b/lib/user32/misc/display.c @@ -0,0 +1,167 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/dde.c + * PURPOSE: DDE + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +EnumDisplayDevicesA( + LPCSTR lpDevice, + DWORD iDevNum, + PDISPLAY_DEVICE lpDisplayDevice, + DWORD dwFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDisplayDevicesW( + LPCWSTR lpDevice, + DWORD iDevNum, + PDISPLAY_DEVICE lpDisplayDevice, + DWORD dwFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDisplayMonitors( + HDC hdc, + LPRECT lprcClip, + MONITORENUMPROC lpfnEnum, + LPARAM dwData) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDisplaySettingsA( + LPCSTR lpszDeviceName, + DWORD iModeNum, + LPDEVMODEA lpDevMode) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDisplaySettingsExA( + LPCSTR lpszDeviceName, + DWORD iModeNum, + LPDEVMODEW lpDevMode, + DWORD dwFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDisplaySettingsExW( + LPCWSTR lpszDeviceName, + DWORD iModeNum, + LPDEVMODEA lpDevMode, + DWORD dwFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnumDisplaySettingsW( + LPCWSTR lpszDeviceName, + DWORD iModeNum, + LPDEVMODEW lpDevMode) +{ + return FALSE; +} +WINBOOL +STDCALL +GetMonitorInfoA( + HMONITOR hMonitor, + LPMONITORINFO lpmi) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetMonitorInfoW( + HMONITOR hMonitor, + LPMONITORINFO lpmi) +{ + return FALSE; +} +LONG +STDCALL +ChangeDisplaySettingsA( + LPDEVMODEA lpDevMode, + DWORD dwflags) +{ + return 0; +} + +LONG +STDCALL +ChangeDisplaySettingsExA( + LPCSTR lpszDeviceName, + LPDEVMODEA lpDevMode, + HWND hwnd, + DWORD dwflags, + LPVOID lParam) +{ + return 0; +} + +LONG +STDCALL +ChangeDisplaySettingsExW( + LPCWSTR lpszDeviceName, + LPDEVMODEW lpDevMode, + HWND hwnd, + DWORD dwflags, + LPVOID lParam) +{ + return 0; +} + +LONG +STDCALL +ChangeDisplaySettingsW( + LPDEVMODEW lpDevMode, + DWORD dwflags) +{ + return 0; +} diff --git a/lib/user32/misc/dllmain.c b/lib/user32/misc/dllmain.c new file mode 100644 index 0000000..eddbc97 --- /dev/null +++ b/lib/user32/misc/dllmain.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MIN_TRACE; + +#endif /* DBG */ + +/* To make the linker happy */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + +HWINSTA ProcessWindowStation; + +DWORD +Init(VOID) +{ + DWORD Status; + + /* Set up the kernel callbacks. */ + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_WINDOWPROC] = + (PVOID)User32CallWindowProcFromKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDASYNCPROC] = + (PVOID)User32CallSendAsyncProcForKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDNCCREATE] = + (PVOID)User32SendNCCREATEMessageForKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDCREATE] = + (PVOID)User32SendCREATEMessageForKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDGETMINMAXINFO] = + (PVOID)User32SendGETMINMAXINFOMessageForKernel; + NtCurrentPeb()->KernelCallbackTable[USER32_CALLBACK_SENDNCCALCSIZE] = + (PVOID)User32SendNCCALCSIZEMessageForKernel; + + UserSetupInternalPos(); + + GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL); + + return(Status); +} + +DWORD +Cleanup(VOID) +{ + DWORD Status; + + GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL); + + return(Status); +} + +INT STDCALL +DllMain(PVOID hinstDll, + ULONG dwReason, + PVOID reserved) +{ + D(MAX_TRACE, ("hinstDll (0x%X) dwReason (0x%X)\n", hinstDll, dwReason)); + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + Init(); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + Cleanup(); + break; + } + return(1); +} + diff --git a/lib/user32/misc/exit.c b/lib/user32/misc/exit.c new file mode 100644 index 0000000..e69d66a --- /dev/null +++ b/lib/user32/misc/exit.c @@ -0,0 +1,66 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/exit.c + * PURPOSE: Shutdown related functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +#include +//#include + +#include + + + +WINBOOL STDCALL +ExitWindowsEx(UINT uFlags, + DWORD dwReserved) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_EXIT_REACTOS; + Request.Data.ExitReactosRequest.Flags = uFlags; + Request.Data.ExitReactosRequest.Reserved = dwReserved; + + Status = CsrClientCallServer(&Request, + &Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + + return(TRUE); +} + + +WINBOOL STDCALL +RegisterServicesProcess(DWORD ServicesProcessId) +{ + CSRSS_API_REQUEST Request; + CSRSS_API_REPLY Reply; + NTSTATUS Status; + + Request.Type = CSRSS_REGISTER_SERVICES_PROCESS; + Request.Data.RegisterServicesProcessRequest.ProcessId = ServicesProcessId; + + Status = CsrClientCallServer(&Request, + &Reply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return(FALSE); + } + + return(TRUE); +} + +/* EOF */ diff --git a/lib/user32/misc/object.c b/lib/user32/misc/object.c new file mode 100644 index 0000000..f936954 --- /dev/null +++ b/lib/user32/misc/object.c @@ -0,0 +1,89 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/dde.c + * PURPOSE: DDE + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +SetUserObjectInformationA( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetUserObjectInformationW( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength) +{ + return FALSE; +} +WINBOOL +STDCALL +UserHandleGrantAccess( + HANDLE hUserHandle, + HANDLE hJob, + WINBOOL bGrant) +{ + return FALSE; +} +WINBOOL +STDCALL +GetUserObjectInformationA( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength, + LPDWORD lpnLengthNeeded) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetUserObjectInformationW( + HANDLE hObj, + int nIndex, + PVOID pvInfo, + DWORD nLength, + LPDWORD lpnLengthNeeded) +{ + return FALSE; +} diff --git a/lib/user32/misc/resources.c b/lib/user32/misc/resources.c new file mode 100644 index 0000000..47e5e54 --- /dev/null +++ b/lib/user32/misc/resources.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +int +STDCALL +LoadStringA( HINSTANCE hInstance, + UINT uID, + LPSTR lpBuffer, + int nBufferMax) +{ + HRSRC rsc; + PBYTE ptr; + int len; + int count, dest = uID % 16; + PWSTR pwstr; + UNICODE_STRING UString; + ANSI_STRING AString; + NTSTATUS Status; + + rsc = FindResource( (HMODULE)hInstance, + MAKEINTRESOURCE( (uID / 16) + 1 ), + RT_STRING ); + if( rsc == NULL ) + return 0; + // get pointer to string table + ptr = (PBYTE)LoadResource( (HMODULE)hInstance, rsc ); + if( ptr == NULL ) + return 0; + for( count = 0; count <= dest; count++ ) + { + // walk each of the 16 string slots in the string table + len = (*(USHORT *)ptr) * 2; // length is in unicode chars, convert to bytes + ptr += 2; // first 2 bytes are length, string follows + pwstr = (PWSTR)ptr; + ptr += len; + } + if( !len ) + return 0; // zero means no string is there + // convert unitocde to ansi, and copy string to caller buffer + UString.Length = UString.MaximumLength = len; + UString.Buffer = pwstr; + memset( &AString, 0, sizeof AString ); + Status = RtlUnicodeStringToAnsiString( &AString, &UString, TRUE ); + if( !NT_SUCCESS( Status ) ) + { + SetLastErrorByStatus( Status ); + return 0; + } + nBufferMax--; // save room for the null + if( nBufferMax > AString.Length ) + nBufferMax = AString.Length; + memcpy( lpBuffer, AString.Buffer, nBufferMax ); + lpBuffer[nBufferMax] = 0; + RtlFreeAnsiString( &AString ); + return nBufferMax; +} + diff --git a/lib/user32/misc/sprintf.c b/lib/user32/misc/sprintf.c new file mode 100644 index 0000000..6ddd417 --- /dev/null +++ b/lib/user32/misc/sprintf.c @@ -0,0 +1,940 @@ +/* $Id$ + * + * user32.dll + * + * wsprintf functions + * + * Copyright 1996 Alexandre Julliard + * + * 1999-05-01 (Emanuele Aliberti) + * Adapted from Wine to ReactOS + */ + +#include +#include +#include +#include + +#define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */ +#define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */ +#define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */ +#define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */ +#define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */ +#define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */ +#define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */ + +typedef enum +{ + WPR_UNKNOWN, + WPR_CHAR, + WPR_WCHAR, + WPR_STRING, + WPR_WSTRING, + WPR_SIGNED, + WPR_UNSIGNED, + WPR_HEXA + +} WPRINTF_TYPE; + + +typedef struct +{ + UINT flags; + UINT width; + UINT precision; + WPRINTF_TYPE type; + +} WPRINTF_FORMAT; + + +static const LPSTR null_stringA = "(null)"; +static const LPWSTR null_stringW = L"(null)"; + + +/* === COMMON === */ + + +/*********************************************************************** + * NAME PRIVATE + * WPRINTF_GetLen + * + * DESCRIPTION + * ? + * + * ARGUMENTS + * format + * ? + * arg + * ? + * number + * ? + * maxlen + * ? + * + * RETURN VALUE + * ? + */ +static +UINT +WPRINTF_GetLen( + WPRINTF_FORMAT *format, + LPCVOID arg, + LPSTR number, + UINT maxlen + ) +{ + UINT len; + + if (format->flags & WPRINTF_LEFTALIGN) + { + format->flags &= ~WPRINTF_ZEROPAD; + } + if (format->width > maxlen) + { + format->width = maxlen; + } + switch(format->type) + { + case WPR_CHAR: + case WPR_WCHAR: + return (format->precision = 1); + + case WPR_STRING: + if (!*(LPCSTR *)arg) + { + *(LPCSTR *)arg = null_stringA; + } + for ( len = 0; + (!format->precision || (len < format->precision)); + len++ + ) + { + if (!*(*(LPCSTR *)arg + len)) + { + break; + } + } + if (len > maxlen) + { + len = maxlen; + } + return (format->precision = len); + + case WPR_WSTRING: + if (!*(LPCWSTR *)arg) + { + *(LPCWSTR *)arg = null_stringW; + } + for ( len = 0; + (!format->precision || (len < format->precision)); + len++ + ) + { + if (!*(*(LPCWSTR *)arg + len)) + break; + } + if (len > maxlen) + { + len = maxlen; + } + return (format->precision = len); + + case WPR_SIGNED: + len = sprintf( + number, + "%d", + *(INT *) arg + ); + break; + + case WPR_UNSIGNED: + len = sprintf( + number, + "%u", + *(UINT *) arg + ); + break; + + case WPR_HEXA: + len = sprintf( + number, + ((format->flags & WPRINTF_UPPER_HEX) + ? "%X" + : "%x"), + *(UINT *) arg + ); + if (format->flags & WPRINTF_PREFIX_HEX) + { + len += 2; + } + break; + + default: + return 0; + } + if (len > maxlen) + { + len = maxlen; + } + if (format->precision < len) + { + format->precision = len; + } + if (format->precision > maxlen) + { + format->precision = maxlen; + } + if ( (format->flags & WPRINTF_ZEROPAD) + && (format->width > format->precision) + ) + { + format->precision = format->width; + } + return len; +} + + +/* === ANSI VERSION === */ + + +/*********************************************************************** + * NAME PRIVATE + * WPRINTF_ParseFormatA + * + * DESCRIPTION + * Parse a format specification. A format specification has the + * form: + * + * [-][#][0][width][.precision]type + * + * ARGUMENTS + * format + * ? + * res + * ? + * + * RETURN VALUE + * The length of the format specification in characters. + */ +static +INT +WPRINTF_ParseFormatA( + LPCSTR format, + WPRINTF_FORMAT *res + ) +{ + LPCSTR p = format; + + res->flags = 0; + res->width = 0; + res->precision = 0; + if (*p == '-') + { + res->flags |= WPRINTF_LEFTALIGN; + p++; + } + if (*p == '#') + { + res->flags |= WPRINTF_PREFIX_HEX; + p++; + } + if (*p == '0') + { + res->flags |= WPRINTF_ZEROPAD; + p++; + } + while ((*p >= '0') && (*p <= '9')) /* width field */ + { + res->width = + (res->width * 10) + + (*p - '0'); + p++; + } + if (*p == '.') /* precision field */ + { + p++; + while ((*p >= '0') && (*p <= '9')) + { + res->precision = + (res->precision * 10) + + (*p - '0'); + p++; + } + } + if (*p == 'l') + { + res->flags |= WPRINTF_LONG; + p++; + } + else if (*p == 'h') + { + res->flags |= WPRINTF_SHORT; + p++; + } + else if (*p == 'w') + { + res->flags |= WPRINTF_WIDE; + p++; + } + + switch (*p) + { + case 'c': + res->type = + (res->flags & WPRINTF_LONG) + ? WPR_WCHAR + : WPR_CHAR; + break; + + case 'C': + res->type = + (res->flags & WPRINTF_SHORT) + ? WPR_CHAR + : WPR_WCHAR; + break; + + case 'd': + case 'i': + res->type = WPR_SIGNED; + break; + + case 's': + res->type = + (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) + ? WPR_WSTRING + : WPR_STRING; + break; + + case 'S': + res->type = + (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) + ? WPR_STRING + : WPR_WSTRING; + break; + + case 'u': + res->type = WPR_UNSIGNED; + break; + + case 'X': + res->flags |= WPRINTF_UPPER_HEX; + /* fall through */ + + case 'x': + res->type = WPR_HEXA; + break; + + default: /* unknown format char */ + res->type = WPR_UNKNOWN; + p--; /* print format as normal char */ + break; + + } /* switch */ + + return (INT) (p - format) + 1; +} + + +/*********************************************************************** + * NAME PRIVATE + * wvsnprintfA (Not a Windows API) + */ +INT +STDCALL +wvsnprintfA( + LPSTR buffer, + UINT maxlen, + LPCSTR spec, + va_list args + ) +{ + WPRINTF_FORMAT format; + LPSTR p = buffer; + UINT i; + UINT len; + CHAR number [20]; + + while (*spec && (maxlen > 1)) + { + if (*spec != '%') + { + *p++ = *spec++; + maxlen--; + continue; + } + spec++; + if (*spec == '%') + { + *p++ = *spec++; + maxlen--; + continue; + } + spec += WPRINTF_ParseFormatA( + spec, + & format + ); + len = WPRINTF_GetLen( + & format, + args, + number, + (maxlen - 1) + ); + if (!(format.flags & WPRINTF_LEFTALIGN)) + { + for ( i = format.precision; + (i < format.width); + i++, maxlen-- + ) + { + *p++ = ' '; + } + } + switch (format.type) + { + case WPR_WCHAR: + if ((*p = (CHAR) (WCHAR) va_arg( args, int))) + { + p++; + } + else if (format.width > 1) + { + *p++ = ' '; + } + else + { + len = 0; + } + break; + + case WPR_CHAR: + if ((*p = (CHAR) va_arg( args, int ))) + { + p++; + } + else if (format.width > 1) + { + *p++ = ' '; + } + else + { + len = 0; + } + break; + + case WPR_STRING: + memcpy( + p, + va_arg( args, LPCSTR ), + len + ); + p += len; + break; + + case WPR_WSTRING: + { + LPCWSTR ptr = va_arg( args, LPCWSTR ); + + for ( i = 0; + (i < len); + i++ + ) + { + *p++ = (CHAR) *ptr++; + } + } + break; + + case WPR_HEXA: + if ( (format.flags & WPRINTF_PREFIX_HEX) + && (maxlen > 3) + ) + { + *p++ = '0'; + *p++ = (format.flags & WPRINTF_UPPER_HEX) + ? 'X' + : 'x'; + maxlen -= 2; + len -= 2; + format.precision -= 2; + format.width -= 2; + } + /* fall through */ + + case WPR_SIGNED: + case WPR_UNSIGNED: + for ( i = len; + (i < format.precision); + i++, maxlen-- + ) + { + *p++ = '0'; + } + memcpy( + p, + number, + len + ); + p += len; + (void) va_arg( args, INT ); /* Go to the next arg */ + break; + + case WPR_UNKNOWN: + continue; + } /* switch */ + + if (format.flags & WPRINTF_LEFTALIGN) + { + for ( i = format.precision; + (i < format.width); + i++, maxlen-- + ) + { + *p++ = ' '; + } + } + maxlen -= len; + } /* while */ + + *p = '\0'; + return (maxlen > 1) + ? (INT) (p - buffer) + : -1; +} + + +/*********************************************************************** + * NAME PUBLIC + * wsprintfA (USER32.585) + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +INT +CDECL +wsprintfA( + LPSTR buffer, + LPCSTR spec, + ... + ) +{ + va_list valist; + INT res; + + va_start( valist, spec ); + res = wvsnprintfA( + buffer, + 0xffffffff, + spec, + valist + ); + va_end( valist ); + return res; +} + + +/*********************************************************************** + * NAME PUBLIC + * wvsprintfA (USER32.587) + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +INT +STDCALL +wvsprintfA( + LPSTR buffer, + LPCSTR spec, + va_list args + ) +{ + return wvsnprintfA( + buffer, + 0xffffffff, + spec, + args + ); +} + + +/* === UNICODE VERSION === */ + + +/*********************************************************************** + * NAME PRIVATE + * WPRINTF_ParseFormatW + * + * DESCRIPTION + * Parse a format specification. A format specification has + * the form: + * + * [-][#][0][width][.precision]type + * + * ARGUMENTS + * format + * ? + * res + * ? + * + * RETURN VALUE + * The length of the format specification in characters. + */ +static +INT +WPRINTF_ParseFormatW( + LPCWSTR format, + WPRINTF_FORMAT *res + ) +{ + LPCWSTR p = format; + + res->flags = 0; + res->width = 0; + res->precision = 0; + if (*p == L'-') + { + res->flags |= WPRINTF_LEFTALIGN; + p++; + } + if (*p == L'#') + { + res->flags |= WPRINTF_PREFIX_HEX; + p++; + } + if (*p == L'0') + { + res->flags |= WPRINTF_ZEROPAD; + p++; + } + + while ((*p >= L'0') && (*p <= L'9')) /* width field */ + { + res->width = + (res->width * 10) + + (*p - L'0'); + p++; + } + + if (*p == L'.') /* precision field */ + { + p++; + while ((*p >= L'0') && (*p <= L'9')) + { + res->precision = + (res->precision * 10) + + (*p - '0'); + p++; + } + } + if (*p == L'l') + { + res->flags |= WPRINTF_LONG; + p++; + } + else if (*p == L'h') + { + res->flags |= WPRINTF_SHORT; + p++; + } + else if (*p == L'w') + { + res->flags |= WPRINTF_WIDE; + p++; + } + + switch ((CHAR)*p) + { + case L'c': + res->type = + (res->flags & WPRINTF_SHORT) + ? WPR_CHAR + : WPR_WCHAR; + break; + + case L'C': + res->type = + (res->flags & WPRINTF_LONG) + ? WPR_WCHAR + : WPR_CHAR; + break; + + case L'd': + case L'i': + res->type = WPR_SIGNED; + break; + + case L's': + res->type = + ((res->flags & WPRINTF_SHORT) + && !(res->flags & WPRINTF_WIDE) + ) + ? WPR_STRING + : WPR_WSTRING; + break; + + case L'S': + res->type = + (res->flags & (WPRINTF_LONG | WPRINTF_WIDE)) + ? WPR_WSTRING + : WPR_STRING; + break; + + case L'u': + res->type = WPR_UNSIGNED; + break; + + case L'X': + res->flags |= WPRINTF_UPPER_HEX; + /* fall through */ + + case L'x': + res->type = WPR_HEXA; + break; + + default: + res->type = WPR_UNKNOWN; + p--; /* print format as normal char */ + break; + } /* switch */ + + return (INT) (p - format) + 1; +} + + +/*********************************************************************** + * NAME PRIVATE + * wvsnprintfW (Not a Windows API) + */ +INT +wvsnprintfW( + LPWSTR buffer, + UINT maxlen, + LPCWSTR spec, + va_list args + ) +{ + WPRINTF_FORMAT format; + LPWSTR p = buffer; + UINT i; + UINT len; + CHAR number [20]; + + while (*spec && (maxlen > 1)) + { + if (*spec != L'%') + { + *p++ = *spec++; + maxlen--; + continue; + } + spec++; + if (*spec == L'%') + { + *p++ = *spec++; + maxlen--; + continue; + } + spec += WPRINTF_ParseFormatW( + spec, + & format + ); + len = WPRINTF_GetLen( + & format, + args, + number, + (maxlen - 1) + ); + if (!(format.flags & WPRINTF_LEFTALIGN)) + { + for ( i = format.precision; + (i < format.width); + i++, maxlen-- + ) + { + *p++ = L' '; + } + } + switch (format.type) + { + case WPR_WCHAR: + if ((*p = (WCHAR) va_arg( args, int))) + { + p++; + } + else if (format.width > 1) + { + *p++ = L' '; + } + else + { + len = 0; + } + break; + + case WPR_CHAR: + if ((*p = (WCHAR)(CHAR) va_arg( args, int ))) + { + p++; + } + else if (format.width > 1) + { + *p++ = L' '; + } + else + { + len = 0; + } + break; + + case WPR_STRING: + { + LPCSTR ptr = va_arg( args, LPCSTR ); + + for ( i = 0; + (i < len); + i++ + ) + { + *p++ = (WCHAR) *ptr++; + } + } + break; + + case WPR_WSTRING: + if (len) + { + memcpy( + p, + va_arg( args, LPCWSTR ), + (len * sizeof (WCHAR)) + ); + } + p += len; + break; + + case WPR_HEXA: + if ( (format.flags & WPRINTF_PREFIX_HEX) + && (maxlen > 3) + ) + { + *p++ = L'0'; + *p++ = (format.flags & WPRINTF_UPPER_HEX) + ? L'X' + : L'x'; + maxlen -= 2; + len -= 2; + format.precision -= 2; + format.width -= 2; + } + /* fall through */ + + case WPR_SIGNED: + case WPR_UNSIGNED: + for ( i = len; + (i < format.precision); + i++, maxlen-- + ) + { + *p++ = L'0'; + } + for ( i = 0; + (i < len); + i++ + ) + { + *p++ = (WCHAR) number[i]; + } + (void) va_arg( args, INT ); /* Go to the next arg */ + break; + + case WPR_UNKNOWN: + continue; + } /* switch */ + + if (format.flags & WPRINTF_LEFTALIGN) + { + for ( i = format.precision; + (i < format.width); + i++, maxlen-- + ) + { + *p++ = L' '; + } + } + maxlen -= len; + } /* while */ + + *p = L'\0'; + return (maxlen > 1) + ? (INT) (p - buffer) + : -1; +} + + +/*********************************************************************** + * NAME PUBLIC + * wsprintfW (USER32.586) + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +INT +CDECL +wsprintfW( + LPWSTR buffer, + LPCWSTR spec, + ... + ) +{ + va_list valist; + INT res; + + va_start( valist, spec ); + res = wvsnprintfW( + buffer, + 0xffffffff, + spec, + valist + ); + va_end( valist ); + return res; +} + + +/*********************************************************************** + * NAME PUBLIC + * wvsprintfW (USER32.588) + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +INT +STDCALL +wvsprintfW( + LPWSTR buffer, + LPCWSTR spec, + va_list args + ) +{ + return wvsnprintfW( + buffer, + 0xffffffff, + spec, + args + ); +} + + +/* EOF */ + diff --git a/lib/user32/misc/stubs.c b/lib/user32/misc/stubs.c new file mode 100644 index 0000000..4ca0484 --- /dev/null +++ b/lib/user32/misc/stubs.c @@ -0,0 +1,531 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/stubs.c + * PURPOSE: User32.dll stubs + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: If you implement a function, remove it from this file + * UPDATE HISTORY: + * 08-05-2001 CSH Created + */ +#include + +WINBOOL +STDCALL +AnyPopup(VOID) +{ + return FALSE; +} + +WINBOOL +STDCALL +AttachThreadInput( + DWORD idAttach, + DWORD idAttachTo, + WINBOOL fAttach) +{ + return FALSE; +} + +long +STDCALL +BroadcastSystemMessage( + DWORD dwFlags, + LPDWORD lpdwRecipients, + UINT uiMessage, + WPARAM wParam, + LPARAM lParam) +{ + return 0; +} + +long +STDCALL +BroadcastSystemMessageA( + DWORD dwFlags, + LPDWORD lpdwRecipients, + UINT uiMessage, + WPARAM wParam, + LPARAM lParam) +{ + return 0; +} + +long +STDCALL +BroadcastSystemMessageW( + DWORD dwFlags, + LPDWORD lpdwRecipients, + UINT uiMessage, + WPARAM wParam, + LPARAM lParam) +{ + return 0; +} + + + + + + + +WINBOOL +STDCALL +CheckRadioButton( + HWND hDlg, + int nIDFirstButton, + int nIDLastButton, + int nIDCheckButton) +{ + return FALSE; +} + +WINBOOL +STDCALL +ClientToScreen( + HWND hWnd, + LPPOINT lpPoint) +{ + return FALSE; +} + +WINBOOL +STDCALL +ClipCursor( + CONST RECT *lpRect) +{ + return FALSE; +} + +HANDLE +STDCALL +CopyImage( + HANDLE hImage, + UINT uType, + int cxDesired, + int cyDesired, + UINT fuFlags) +{ + return (HANDLE)0; +} + + + + +WINBOOL +STDCALL +DragDetect( + HWND hwnd, + POINT pt) +{ + return FALSE; +} + +WINBOOL +STDCALL +EnableScrollBar( + HWND hWnd, + UINT wSBflags, + UINT wArrows) +{ + return FALSE; +} + +HWND +STDCALL +GetActiveWindow(VOID) +{ + return (HWND)0; +} + +HWND +STDCALL +GetCapture(VOID) +{ + return (HWND)0; +} + + +UINT +STDCALL +GetDoubleClickTime(VOID) +{ + return 0; +} + +HWND +STDCALL +GetFocus(VOID) +{ + return (HWND)0; +} + +DWORD +STDCALL +GetGuiResources( + HANDLE hProcess, + DWORD uiFlags) +{ + return 0; +} + + + +int +STDCALL +GetMouseMovePointsEx( + UINT cbSize, + LPMOUSEMOVEPOINT lppt, + LPMOUSEMOVEPOINT lpptBuf, + int nBufPoints, + DWORD resolution) +{ + return 0; +} + + + + +DWORD +STDCALL +GetQueueStatus( + UINT flags) +{ + return 0; +} + + +DWORD +STDCALL +GetSysColor( + int nIndex) +{ + return 0; +} + +HMENU +STDCALL +GetSystemMenu( + HWND hWnd, + WINBOOL bRevert) +{ + return (HMENU)0; +} + + + + + + + + + + + + + + + + + + +WINBOOL +STDCALL +IsWindowEnabled( + HWND hWnd) +{ + return FALSE; +} + + + + + + + +int +STDCALL +LoadStringW( + HINSTANCE hInstance, + UINT uID, + LPWSTR lpBuffer, + int nBufferMax) +{ + return 0; +} + +WINBOOL +STDCALL +LockWindowUpdate( + HWND hWndLock) +{ + return FALSE; +} + +WINBOOL +STDCALL +LockWorkStation(VOID) +{ + return FALSE; +} + +WINBOOL +STDCALL +MessageBeep( + UINT uType) +{ + return FALSE; +} + + + +HMONITOR +STDCALL +MonitorFromPoint( + POINT pt, + DWORD dwFlags) +{ + return (HMONITOR)0; +} + +HMONITOR +STDCALL +MonitorFromRect( + LPRECT lprc, + DWORD dwFlags) +{ + return (HMONITOR)0; +} + +HMONITOR +STDCALL +MonitorFromWindow( + HWND hwnd, + DWORD dwFlags) +{ + return (HMONITOR)0; +} + +DWORD +STDCALL +MsgWaitForMultipleObjects( + DWORD nCount, + CONST LPHANDLE pHandles, + WINBOOL fWaitAll, + DWORD dwMilliseconds, + DWORD dwWakeMask) +{ + return 0; +} + +DWORD +STDCALL +MsgWaitForMultipleObjectsEx( + DWORD nCount, + CONST HANDLE pHandles, + DWORD dwMilliseconds, + DWORD dwWakeMask, + DWORD dwFlags) +{ + return 0; +} + + + + + + + +#if 0 +HDEVNOTIFY +STDCALL +RegisterDeviceNotificationA( + HANDLE hRecipient, + LPVOID NotificationFilter, + DWORD Flags) +{ + return (HDEVNOTIFY)0; +} + +HDEVNOTIFY +STDCALL +RegisterDeviceNotificationW( + HANDLE hRecipient, + LPVOID NotificationFilter, + DWORD Flags) +{ + return (HDEVNOTIFY)0; +} +#endif +WINBOOL +STDCALL +RegisterHotKey( + HWND hWnd, + int id, + UINT fsModifiers, + UINT vk) +{ + return FALSE; +} + + +WINBOOL +STDCALL +ReleaseCapture(VOID) +{ + return FALSE; +} + + + + + + +WINBOOL +STDCALL +ScrollWindow( + HWND hWnd, + int XAmount, + int YAmount, + CONST RECT *lpRect, + CONST RECT *lpClipRect) +{ + return FALSE; +} + +int +STDCALL +ScrollWindowEx( + HWND hWnd, + int dx, + int dy, + CONST RECT *prcScroll, + CONST RECT *prcClip, + HRGN hrgnUpdate, + LPRECT prcUpdate, + UINT flags) +{ + return 0; +} + + + +HWND +STDCALL +SetActiveWindow( + HWND hWnd) +{ + return (HWND)0; +} + +HWND +STDCALL +SetCapture( + HWND hWnd) +{ + return (HWND)0; +} + + + + + +WINBOOL +STDCALL +SetDoubleClickTime( + UINT uInterval) +{ + return FALSE; +} + +HWND +STDCALL +SetFocus( + HWND hWnd) +{ + return (HWND)0; +} +VOID +STDCALL +SetLastErrorEx( + DWORD dwErrCode, + DWORD dwType) +{ +} + + + + + +WINBOOL +STDCALL +SetSysColors( + int cElements, + CONST INT *lpaElements, + CONST COLORREF *lpaRgbValues) +{ + return FALSE; +} + + + + + + + + +WINBOOL +STDCALL +SwapMouseButton( + WINBOOL fSwap) +{ + return FALSE; +} + +WINBOOL +STDCALL +TrackMouseEvent( + LPTRACKMOUSEEVENT lpEventTrack) +{ + return FALSE; +} + + + + + + + +WINBOOL +STDCALL +UnregisterDeviceNotification( + HDEVNOTIFY Handle) +{ + return FALSE; +} + +WINBOOL +STDCALL +UnregisterHotKey( + HWND hWnd, + int id) +{ + return FALSE; +} + + + + + +DWORD +STDCALL +WaitForInputIdle( + HANDLE hProcess, + DWORD dwMilliseconds) +{ + return 0; +} + + +/* EOF */ diff --git a/lib/user32/misc/timer.c b/lib/user32/misc/timer.c new file mode 100644 index 0000000..4406d96 --- /dev/null +++ b/lib/user32/misc/timer.c @@ -0,0 +1,55 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/dde.c + * PURPOSE: DDE + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +KillTimer( + HWND hWnd, + UINT_PTR uIDEvent) +{ + return FALSE; +} +UINT_PTR +STDCALL +SetTimer( + HWND hWnd, + UINT_PTR nIDEvent, + UINT uElapse, + TIMERPROC lpTimerFunc) +{ + return (UINT_PTR)0; +} + diff --git a/lib/user32/misc/winhelp.c b/lib/user32/misc/winhelp.c new file mode 100644 index 0000000..756d1b4 --- /dev/null +++ b/lib/user32/misc/winhelp.c @@ -0,0 +1,148 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/winhelp.c + * PURPOSE: WinHelp + * PROGRAMMER: Robert Dickenson(robd@reactos.org) + * UPDATE HISTORY: + * 23-08-2002 RDD Created from wine sources + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +/* WinHelp internal structure */ +typedef struct +{ + WORD size; + WORD command; + LONG data; + LONG reserved; + WORD ofsFilename; + WORD ofsData; +} WINHELP,*LPWINHELP; + + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +WinHelpA(HWND hWnd, LPCSTR lpszHelp, UINT uCommand, DWORD dwData) +{ + static WORD WM_WINHELP = 0; + HWND hDest; + LPWINHELP lpwh; + HGLOBAL hwh; + int size,dsize,nlen; + + if (!WM_WINHELP) { + WM_WINHELP = RegisterWindowMessageA("WM_WINHELP"); + if (!WM_WINHELP) + return FALSE; + } + + hDest = FindWindowA("MS_WINHELP", NULL); + if (!hDest) { + if (uCommand == HELP_QUIT) return TRUE; + if (WinExec("winhlp32.exe -x", SW_SHOWNORMAL) < 32) { + //ERR("can't start winhlp32.exe -x ?\n"); + return FALSE; + } + if (!(hDest = FindWindowA("MS_WINHELP", NULL))) { + //FIXME("did not find MS_WINHELP (FindWindow() failed, maybe global window handling still unimplemented)\n"); + return FALSE; + } + } + switch (uCommand) { + case HELP_CONTEXT: + case HELP_SETCONTENTS: + case HELP_CONTENTS: + case HELP_CONTEXTPOPUP: + case HELP_FORCEFILE: + case HELP_HELPONHELP: + case HELP_FINDER: + case HELP_QUIT: + dsize=0; + break; + case HELP_KEY: + case HELP_PARTIALKEY: + case HELP_COMMAND: + dsize = dwData ? strlen( (LPSTR)dwData )+1: 0; + break; + case HELP_MULTIKEY: + dsize = ((LPMULTIKEYHELPA)dwData)->mkSize; + break; + case HELP_SETWINPOS: + dsize = ((LPHELPWININFOA)dwData)->wStructSize; + break; + default: + //FIXME("Unknown help command %d\n",uCommand); + return FALSE; + } + if (lpszHelp) + nlen = strlen(lpszHelp)+1; + else + nlen = 0; + size = sizeof(WINHELP) + nlen + dsize; + hwh = GlobalAlloc(0,size); + lpwh = GlobalLock(hwh); + lpwh->size = size; + lpwh->command = uCommand; + lpwh->data = dwData; + if (nlen) { + strcpy(((char*)lpwh) + sizeof(WINHELP), lpszHelp); + lpwh->ofsFilename = sizeof(WINHELP); + } else { + lpwh->ofsFilename = 0; + } + if (dsize) { + memcpy(((char*)lpwh)+sizeof(WINHELP)+nlen,(LPSTR)dwData,dsize); + lpwh->ofsData = sizeof(WINHELP)+nlen; + } else { + lpwh->ofsData = 0; + } + GlobalUnlock(hwh); + return SendMessage(hDest, WM_WINHELP, (WPARAM)hWnd, (LPARAM)hwh); +} + +WINBOOL +STDCALL +WinHelpW(HWND hWnd, LPCWSTR lpszHelp, UINT uCommand, DWORD dwData) +{ + INT len; + LPSTR file; + BOOL ret = FALSE; + + if (!lpszHelp) return WinHelpA(hWnd, NULL, uCommand, dwData); + + len = WideCharToMultiByte(CP_ACP, 0, lpszHelp, -1, NULL, 0, NULL, NULL); + if ((file = HeapAlloc(GetProcessHeap(), 0, len))) { + WideCharToMultiByte(CP_ACP, 0, lpszHelp, -1, file, len, NULL, NULL); + ret = WinHelpA(hWnd, file, uCommand, dwData); + HeapFree(GetProcessHeap(), 0, file); + } + return ret; +} + diff --git a/lib/user32/misc/winsta.c b/lib/user32/misc/winsta.c new file mode 100644 index 0000000..3c64432 --- /dev/null +++ b/lib/user32/misc/winsta.c @@ -0,0 +1,136 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/misc/winsta.c + * PURPOSE: Window stations + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 04-06-2001 CSH Created + */ +#include +#include +#include + + +WINBOOL STDCALL +CloseWindowStation(HWINSTA hWinSta) +{ + return(NtUserCloseWindowStation(hWinSta)); +} + +HWINSTA STDCALL +CreateWindowStationA(LPSTR lpwinsta, + DWORD dwReserved, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa) +{ + ANSI_STRING WindowStationNameA; + UNICODE_STRING WindowStationNameU; + HWINSTA hWinSta; + + if (lpwinsta != NULL) + { + RtlInitAnsiString(&WindowStationNameA, lpwinsta); + RtlAnsiStringToUnicodeString(&WindowStationNameU, &WindowStationNameA, + TRUE); + } + else + { + RtlInitUnicodeString(&WindowStationNameU, NULL); + } + + hWinSta = CreateWindowStationW(WindowStationNameU.Buffer, + dwReserved, + dwDesiredAccess, + lpsa); + + RtlFreeUnicodeString(&WindowStationNameU); + + return hWinSta; +} + +HWINSTA STDCALL +CreateWindowStationW(LPWSTR lpwinsta, + DWORD dwReserved, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpsa) +{ + UNICODE_STRING WindowStationName; + + RtlInitUnicodeString(&WindowStationName, lpwinsta); + + return NtUserCreateWindowStation(&WindowStationName, + dwDesiredAccess, + lpsa, 0, 0, 0); +} + +WINBOOL STDCALL +EnumWindowStationsA(ENUMWINDOWSTATIONPROC lpEnumFunc, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL STDCALL +EnumWindowStationsW(ENUMWINDOWSTATIONPROC lpEnumFunc, + LPARAM lParam) +{ + return FALSE; +} + +HWINSTA STDCALL +GetProcessWindowStation(VOID) +{ + return NtUserGetProcessWindowStation(); +} + +HWINSTA STDCALL +OpenWindowStationA(LPSTR lpszWinSta, + WINBOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + ANSI_STRING WindowStationNameA; + UNICODE_STRING WindowStationNameU; + HWINSTA hWinSta; + + if (lpszWinSta != NULL) + { + RtlInitAnsiString(&WindowStationNameA, lpszWinSta); + RtlAnsiStringToUnicodeString(&WindowStationNameU, &WindowStationNameA, + TRUE); + } + else + { + RtlInitUnicodeString(&WindowStationNameU, NULL); + } + + hWinSta = OpenWindowStationW(WindowStationNameU.Buffer, + fInherit, + dwDesiredAccess); + + RtlFreeUnicodeString(&WindowStationNameU); + + return hWinSta; +} + +HWINSTA STDCALL +OpenWindowStationW(LPWSTR lpszWinSta, + WINBOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + UNICODE_STRING WindowStationName; + + RtlInitUnicodeString(&WindowStationName, lpszWinSta); + + return NtUserOpenWindowStation(&WindowStationName, dwDesiredAccess); +} + +WINBOOL STDCALL +SetProcessWindowStation(HWINSTA hWinSta) +{ + return NtUserSetProcessWindowStation(hWinSta); +} + +/* EOF */ + diff --git a/lib/user32/resources/obm_btncorners.bmp b/lib/user32/resources/obm_btncorners.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e7838624b1af7a80d3dfb167ee2336afc103a0a8 GIT binary patch literal 118 zcmZ?rEn|QHJ0PV2#C%Z9$iN7Zz(M~1|DWOi9|k!7QNzIS!G?k1feb1JiGk#h)dB#{ CF&UWv literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_btsize.bmp b/lib/user32/resources/obm_btsize.bmp new file mode 100644 index 0000000000000000000000000000000000000000..076e4f870ee1329efc349e629897170d67d87262 GIT binary patch literal 122 tcmZ?rtzv)xJ0PV2#Qadq$iN7Zz(M~1{~s(<|A&DA9W&Gb#qeN|MgV8s6HNdB literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_check.bmp b/lib/user32/resources/obm_check.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e9e4fb5de772490ad65635a7fca3e2257b479b75 GIT binary patch literal 118 zcmZ?rEn|QHJ0PV2#C%Z9$iN7Zz(M~1|DWOi9|k!72W0=LVPN4%vIGoOKlL4d)5k)i&}{|R9FYklxP_m4pH_Fewx{Srvuz5LJj fCXjx8`JdlTApQOFKmST3K1?2_9;zQ|9?X0ItsA#R literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_close.bmp b/lib/user32/resources/obm_close.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f800b069add07cbc778fb05a66c9eea7c5d8f8ba GIT binary patch literal 478 zcmZXQF%H5o3`JcDiEc$~-5EFsJNIDhgc!XwOpqJ(B%Fbft$hFQ42U##UtjDt&FTE= zjN^)YL>v%%L}wdhvrDe?;U~Enrn&2e3`Dps%YucK)7CWzfh!bJ`5P8)+NKwTbGykU zz|E|MZJ^$4Efayxv$qK3`Yd#U+^#u-T+Ko!$cG-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP si=(j_1qET^0t^T?0|O&WTmYyI#uh|YgNqHa0cIw4wlNqOf!u=(0AHICT>t<8 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_dnarrowd.bmp b/lib/user32/resources/obm_dnarrowd.bmp new file mode 100644 index 0000000000000000000000000000000000000000..51b38e90f7576543ddcb28b729243df3ce2beaee GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP=upG|}Qrf)D`GfR8NzR0dPSzzAmx f09_0d2TC)-*n&uEaI!%*!^|YeR)PSKdSn0qN^lGH literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_dnarrowi.bmp b/lib/user32/resources/obm_dnarrowi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3cbf4fbba4cf728c361ad1a2ac2f24576df47145 GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP zivyX$f`V|ivLT!;q+|?dD=8@(Le&TXO@fOHDIu#zW+Ryiv;uBER<O#07Y~Y AfdBvi literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_lfarrow.bmp b/lib/user32/resources/obm_lfarrow.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6ceef25255015b43b5808ed4acedb2be38cbb6b7 GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP ri=(j_1qET^0!VD2Qkb{^5*zFzZ0ZG(^nz@Fslm=R1_L9IdyoMDRHhL> literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_lfarrowd.bmp b/lib/user32/resources/obm_lfarrowd.bmp new file mode 100644 index 0000000000000000000000000000000000000000..bb446c3e0400a3fda7cafbf0c98805a87529ec5b GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP=upG|}Qrf)D`GfR8NzR0dPSfM5$S hFfhWzfzog`vbZ3UdO>7!KsLk7B*<2R0FZiQ002|43=;qV literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_lfarrowi.bmp b/lib/user32/resources/obm_lfarrowi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c81363d484fc9f85582f6bf06e25db861776046e GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP zivyX$f`V|iGJ-9nXlw`*2kM5gg^<{SKsH>j5RzU&WH!(Wm^mPeG1H6J0PV2#Oy%K4aAHP{BSRo(IHzK->nzO;8%d2Z@8^{{b-o D&-V+@ literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_old_close.bmp b/lib/user32/resources/obm_old_close.bmp new file mode 100644 index 0000000000000000000000000000000000000000..905e927ec8202f049101aac4655c5f1fd3d7dc00 GIT binary patch literal 478 zcmc(au?>JQ3|5FaEC Il1Ek#0KB3fJpcdz literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_old_reduce.bmp b/lib/user32/resources/obm_old_reduce.bmp new file mode 100644 index 0000000000000000000000000000000000000000..cee2329995f66ac426c7498522c1ca7193aebad1 GIT binary patch literal 138 zcmZ?r?P7ocJ0PV2#F9WP48)8;h!6b#|DOSf8~*s0s0M$b}#{d8T literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_old_rgarrow.bmp b/lib/user32/resources/obm_old_rgarrow.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0c05d811730af4a1c9f1e9624d241299ff266e67 GIT binary patch literal 122 zcmZ?rtzv)xJ0PV2#Qadq$iN7Zz(M~1|DWOiKL$Ad2W0=N17e^-59END4?=_ZVDWzl HwIF=}aRMC8 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_old_uparrow.bmp b/lib/user32/resources/obm_old_uparrow.bmp new file mode 100644 index 0000000000000000000000000000000000000000..299fadb47a0717d4eb41e5b02cd69f64100ee6d8 GIT binary patch literal 122 zcmZ?rtzv)xJ0PV2#Qadq$iN7Zz(M~1|DWOiKL$AdQ^&x7j34kZFno|>VE6$v7$pAh JA3`li9{_Yx9SZ;e literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_old_zoom.bmp b/lib/user32/resources/obm_old_zoom.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c1b4eb68b886d63b1a981896c08eec585a9ffc86 GIT binary patch literal 138 zcmZ?r?P7ocJ0PV2#F9WP48)8;h!6b#|DOSf8^HJhkUjv!cW`0*hJP~h4gc%y8~*RB Php2lARQnx>p=JO82DU)i literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_reduce.bmp b/lib/user32/resources/obm_reduce.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d0dbf01a44a2b93b4b98a9f343604ec82afadfcc GIT binary patch literal 230 zcmZ?reZ~L*Wk5;;hy{R{4~Q8VSb!vMuz&x4hMPBUGSt`CGyMPmAGbn0GS0?eVBjPO Y20$99SWpm&hKZ9%D}jN53j{a-0A(f^f&c&j literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_reduced.bmp b/lib/user32/resources/obm_reduced.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c39f8e9505a2e450243f95d7fb58745fc217e1d3 GIT binary patch literal 230 zcmZ?reZ~L*Wk5;;hy{R{4~Q8VSb!vMuz&x4hMPBUGSt`CGyMPmAGbm*GA>ZSqyz>k Y%z{8$83mDOK@b4)$)t_JKm}$s08Dxn00000 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_restore.bmp b/lib/user32/resources/obm_restore.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a22d3ddff44ef854de968e9da099bdfe38a8c0df GIT binary patch literal 230 zcmZ?reZ~L*Wk5;;hy{R{4~Q8VSb!vMuz&x4hMPBUGSt`CGyMPmAGbn0GS0?eVBjPO n1_n+*%NYd)fwZ6?It`S7$RpE&V1+>aV2ub`2@DKeAix0tJ)swL literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_restored.bmp b/lib/user32/resources/obm_restored.bmp new file mode 100644 index 0000000000000000000000000000000000000000..6958dc2ca1553d2360b553650880d5946b326b8f GIT binary patch literal 230 zcmZ?reZ~L*Wk5;;hy{R{4~Q8VSb!vMuz&x4hMPBUGSt`CGyMPmAGbm*GA>ZSqyz>k r%z{8gf`UMrQBVM#WνG-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP xi=(j_1qI>a3~;sp0|O&W9LQ!sV#CD+1rh261(D4GS^+l`E87?hj6m)|1^`r|5kCL` literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_rgarrowd.bmp b/lib/user32/resources/obm_rgarrowd.bmp new file mode 100644 index 0000000000000000000000000000000000000000..abf3f7c99f207f9671776c128b51abdef8e23d52 GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP=upG|}Qrf)D`GfR8NzR0dNczzAmp fg^<~dFg3{Hf=KEGk<9_w3^S7;TL}U{>X88eQ*aCu literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_rgarrowi.bmp b/lib/user32/resources/obm_rgarrowi.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a90b836a7392e14ed6ede6e0ce1b9dd06fde2ddb GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP zivyX$f`V|ivLT#ptYi#h3n?in8$#6p*-A*_iZC|N5F~RHk=Q^h;O1jx8-sxnx~Bk4 CPZNOv literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_size.bmp b/lib/user32/resources/obm_size.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d4eedf965f338bd3d45156ce710ad56baeb73f1b GIT binary patch literal 114 rcmZ?rEnG-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP ti=(my7z71j;yBm>Ky7d}3=E8LHnMs_Mua&a8(?N)XB&fo5y(Br003eO5nTWP literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_uparrowd.bmp b/lib/user32/resources/obm_uparrowd.bmp new file mode 100644 index 0000000000000000000000000000000000000000..872dc323044903f728efb046520a9cb15b9f304a GIT binary patch literal 322 zcmZ?rbz)=ygEAng0mOn(%*en37RN>G-@l)szP=upG|}Qrf)D`GfRD|G-@l)szP_H}|NsBEln^D(qyzyV#mvZTK`>AP zivyX)hJrA*kP=q5u#u9mAykbJ&?LBeB_%~TTS!R|&K6WeVgs#!nGdoUlWhzJM(Cab E0AU&vp8x;= literal 0 HcmV?d00001 diff --git a/lib/user32/resources/obm_zoom.bmp b/lib/user32/resources/obm_zoom.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a3838ebaea15aa4c710af4cfc79153dbab26fd7e GIT binary patch literal 230 zcmZ?reZ~L*Wk5;;hy{R{4~Q8VSb!vMuz&x4hMPBUGSt`CGyMPmAGbn0GS0?eVBjPO c1_n+b%NYcLG>|Vq3Juc-rIoZSqyz>k h%z_|Aj6j-EP*9K*8m13M1GNhZsxTXafeJ_z1ONr$BZ!()}UC2Q#MrU<)b|f;FhI3`OlAh2D=SmzYC$);)2-nyT D3b=2o literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_cross.cur b/lib/user32/resources/ocr_cross.cur new file mode 100644 index 0000000000000000000000000000000000000000..79a64023b24592644f6d1c3ecdae3f861e2e315e GIT binary patch literal 326 zcmaKmF%p0v3NmoMBPy307beYH^69aDC}5 m+G%F3=-s9h0_MwP0MCKXXFSG^^oOx(F$<_rej=a04Yu5hW`Q06 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_dragobject.cur b/lib/user32/resources/ocr_dragobject.cur new file mode 100644 index 0000000000000000000000000000000000000000..45f593fb3e615e9372a3a4c67e8687ec69be3bb6 GIT binary patch literal 326 zcmb8pF$%&!6olc~L{UM|O6=UyGB+?s@fw;UrPuH%f`!*mynuF*2;;8?qG01&zTKU- zJXk4FP>fPn17$&)NScF|as<|^n&TbX-F6#3ZymxAeM~Wyl1xe?j<}=3rO7*~*kUQI td0(MG`HSf1;CvQ;_^z6G#R+G--rKi>U2QM|6IDQp9_Z;`GiDYj?FYCLbh7{e literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_hand.cur b/lib/user32/resources/ocr_hand.cur new file mode 100644 index 0000000000000000000000000000000000000000..00b031ff80779bb00fca3f7d8b6069706c65d538 GIT binary patch literal 326 zcma*hp$@_@6a~=xsHm8j!yuSME}2A(KWinQgPPu_@CnF@C3m;&$U-oC&FSrHUeW?5 z7`hJd0D1$?%A4p44>7G$ThwOXN$$;olW9D2jD=Tv&S<5Pi`-=pH)Wce0QZvkFF&b2 g9I6F@UkM|#PjTfN)vS!0r?SokCL>cT)-BCE0T*=ljw zYEkD}G_@ADhZbe5DUU71D;stvPw)mtU@ges@Lxm5+$YRk#B7N<>Uc~$GiKJf49cC? f%2fyDPL*=ST{#SDq`{2Q%Y@y@6TE>DSPOasXK--1 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_normal.cur b/lib/user32/resources/ocr_normal.cur new file mode 100644 index 0000000000000000000000000000000000000000..a7d5afc1b372130acadac529677c41d01565fd1f GIT binary patch literal 326 zcmb8pF%E+;3_wx485p}&Y{|&jv0IS12op0CVnD#rI9OHplSE?1(TnXkiX!q5l@KJw zTSZ<}4FXyyD@94Uxpp(Vnmg6OW$2zc+71IItk@3hDE&g7F``F{Gx)>3h-N>ZeW@3G XHnSS%W66{35mC;SnL`D}<`MA+1z2`7 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_size.cur b/lib/user32/resources/ocr_size.cur new file mode 100644 index 0000000000000000000000000000000000000000..bb8e4ea94f426a724e6643ca477f78fabdfdd385 GIT binary patch literal 326 zcmZ{eF%E)Y428d+Fu1|wM3gu=dII1qoTkO+qC`PYhV9D zL?F*0aX$oD1A7mrs62xEXrD5HIh)xGeqYi=4a60!a!6Cyv~aw`^G4WRiHfd?{VP>r z@nc_enwL&`?fHL$pRr(rbA4^rm1gbM?3GOMxR_;U8?ux2PTkO+qC`PYhV9D zL?F*0aX$oD1A7mrs62xEXrD5HIh)xGeqYi=4a60!a!6Cyv~aw`^G4WRiHfd?{VP>r z@nc_enwL&`?fHL$pRr(rbA4^rm1gbM?3GOMxR_;U8?ux2P|5JbmNP)0P=C>14T(nTq904@YU6dZt4 zvXm}F?W96d1+?@4N306A6~}32M-j_rhCK{0!UP}qLDKQiD>NGX3QzD0elafoa4yFc ZPYPM^9KXT8HJk4wzVU`{@O_Cgq6NEsf7$>5 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_sizens.cur b/lib/user32/resources/ocr_sizens.cur new file mode 100644 index 0000000000000000000000000000000000000000..f5ae7dc281a64d6f368db5a39716a4c6b77337f3 GIT binary patch literal 326 zcmaiuu?~Vj5JcY*3p=PRkcW)lZ4o4 Svo5suk6*8I&fD+*cJKk|X@4>R literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_sizenwse.cur b/lib/user32/resources/ocr_sizenwse.cur new file mode 100644 index 0000000000000000000000000000000000000000..a4933c51df8ab007e5c819ebcf9e0f7f7b271f1e GIT binary patch literal 326 zcma)$F%p6>6ht>zP&zi&43#A%c8-My@IokK;Q>4ax1jJ=4(khqp+oo2%VvLmCXq4) z6@|2=svzwp9e|cj5U5efrm(EGm$14UIBnq!C0wE7fs2&gr1uo{!k_SfI3BP45P$eX bftko1`s6!%ING1au4xgyfjs$qg}A0K(G7pv literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_sizewe.cur b/lib/user32/resources/ocr_sizewe.cur new file mode 100644 index 0000000000000000000000000000000000000000..6dd381d3cf1fb8eece6c15991d49a58e8256599b GIT binary patch literal 328 zcmb7;K@LDr3`E}-8$#@C{iUTFa1=M;CLEF2Scqzo*!t77)0sADA;RH36dH|#5~wxR zqSJI5H(q+gS4HF#f4e?|IZtsuA!_$A)?3D=?*XJr; G9)Js0{e7kY literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_up.cur b/lib/user32/resources/ocr_up.cur new file mode 100644 index 0000000000000000000000000000000000000000..906e8a0a6de35ef7a17109b7ee586feb2e27c764 GIT binary patch literal 326 zcmb8qJrY1L5QgD5%uwpIlu9??W*p5?96_lt^Vt=~Pv^@#*=&lP1QG&u4H?h|D6KZe zuINp$b>u9uxpzr-^Eu@s{LwAosyQkqaMz3!aNpP)UYRTD4^sQY!OV literal 0 HcmV?d00001 diff --git a/lib/user32/resources/ocr_wait.cur b/lib/user32/resources/ocr_wait.cur new file mode 100644 index 0000000000000000000000000000000000000000..21404185e1242e6c1a929c2e0df07bf257005014 GIT binary patch literal 326 zcmZvW%@Kk?428ed88|5?IWVKk(W4z;36@|9mOx3Au%%D}M{Y48AnNckFUiZ~4|W9V z8Va>rfD*VWwZvT+)F#Zq#p*?572jDix;j0e>fro>%K%Y%>>*FEZ|#87@+`sO>HRhr qJMXs{!?M%W$LkNjAm~>!Q!cW_z7QFr$k;e7x7t>()s}r0|L_JwFLC$) literal 0 HcmV?d00001 diff --git a/lib/user32/resources/oic_bang.ico b/lib/user32/resources/oic_bang.ico new file mode 100644 index 0000000000000000000000000000000000000000..2ce8dc18d63b93ebc39f3c227f13b4a689192d82 GIT binary patch literal 766 zcmZuvF>b>!3_QmLT%bcbb&b)fKpxRP$(zP#?`Moo2E6zw9y?~tP?WtBB~=AV=R_UJ zBN;$I$8Q`TA^SW4PxLRuNW2jp?sx)`x&JLP$xMvyc=Ad_Y}>|!r60_6Blsz#14C$x zykQ|sX$eM?vGlMu7DG5UbX|tOd@X#zd#W2Iub=TCz6_K1%X|)Sp6g=(+5y8e z%e~rBp7}>=Be@G^C@;D5sC_tHT&1JNB)M~FKbI##;$B{PmM4MoSzdXOOQ3m0o*LBY zWrJV2Z&0VJfXg-V#Ow6jpia*`rvD})J1_3bd3Y|j8_-|*#5M+E3A*p-I>vfo<3ka4 m;3!aY5~zO_zJQDH&1WSTI!Elygl%x_N3;E8cDZHXTfmXBRZ4t?EmP$xIZ8@O%H0_T@ub)+>?|met*`$j zC$>cbPv1X?+1s7SBl8p9<1cuSdq$BAciS=~OwQZHNQh@ymIXrn6;+FH9!uHa7RPZM zO3VZ@tBH7M+cteGV%tsAbZl$l05U^i6`^y4B6-gWNf-`=wJA~X8xMkfcFEZbj8?*F zR)#cyXSGl*n?~mew`3YSD2ttDMZ*Bhf`Sov&x%c8^k4W|kG%97I;x=SdiH%DTkgj9 z`tM%;hcl=z)t literal 0 HcmV?d00001 diff --git a/lib/user32/resources/oic_note.ico b/lib/user32/resources/oic_note.ico new file mode 100644 index 0000000000000000000000000000000000000000..7902c9e4be9e40b998ee1bfa5ae76bf8364535b3 GIT binary patch literal 766 zcma))Jx;_h5QQfM$#kKj-IUy7IZ`^)#T^aOUdbI4dx&&UrcAL~?>A#RC=p0Fc{B6o z*BV)*;p_WH(er&L@`Qc{J$M0)+#^K-vENT1NF;=;keDDyjFCXHUs6&F@Tp5hJ#MI0 z)_%u#@ovY{hP!UVy@z{W2hjSYyi9QNz)gaz2`6YuOLb(5!&yaVQ5CaQU|h}|v?h#b zb*P&C;HBXE_@N1aVOOw#XisFkiX1N@9anSA kYbTy#1cAwlKTd;Rb6Vgc^^?ef`XhZt`tkDGl%_+v0nu7itN;K2 literal 0 HcmV?d00001 diff --git a/lib/user32/resources/oic_ques.ico b/lib/user32/resources/oic_ques.ico new file mode 100644 index 0000000000000000000000000000000000000000..225d95112a2e36a17ed69735e5a34ce3ca57f447 GIT binary patch literal 766 zcmZ{iJ#K_B5QT>j$>~UycDKweHb8 zn?Ec>DxTxgGAv)t_35Cb(nRjkwD7eMv`d8lPgiY_yWq|fw3&p4}7Fz4S zb0;<*n&}HS)DhMXYdo{ha7|cZv=6ik)PQU%6OczEYP(OL9n1B;b%>9hlH&KvPw5-+ zQv(3aE?@zp{UY5( +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS User API Client Dll\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "user32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "user32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +OBM_CLOSE BITMAP "resources/obm_close.bmp" +OBM_REDUCE BITMAP "resources/obm_reduce.bmp" +OBM_ZOOM BITMAP "resources/obm_zoom.bmp" +OBM_RESTORE BITMAP "resources/obm_restore.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +MSGBOX DIALOG DISCARDABLE 100, 80, 216, 168 +STYLE DS_SYSMODAL | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +FONT 8, "MS Sans Serif" +BEGIN + ICON "", 1088, 9, 20, 16, 16, WS_CHILD | WS_VISIBLE + LTEXT "", 100, 48, 16, 176, 48, WS_CHILD | WS_VISIBLE | WS_GROUP + PUSHBUTTON "&OK", 1, 16, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "&Cancel", 2, 64, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "&Abort", 3, 112, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "&Retry", 4, 160, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "&Ignore", 5, 208, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "&Yes", 6, 206, 26, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + PUSHBUTTON "&No", 7, 304, 56, 40, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP +END + + diff --git a/lib/user32/windows/.cvsignore b/lib/user32/windows/.cvsignore new file mode 100644 index 0000000..c0b927e --- /dev/null +++ b/lib/user32/windows/.cvsignore @@ -0,0 +1,4 @@ +*.d +*.a +*.o +*.sym diff --git a/lib/user32/windows/accel.c b/lib/user32/windows/accel.c new file mode 100644 index 0000000..cafe18f --- /dev/null +++ b/lib/user32/windows/accel.c @@ -0,0 +1,128 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +int STDCALL +CopyAcceleratorTableA(HACCEL hAccelSrc, + LPACCEL lpAccelDst, + int cAccelEntries) +{ + return 0; +} + +int STDCALL +CopyAcceleratorTableW(HACCEL hAccelSrc, + LPACCEL lpAccelDst, + int cAccelEntries) +{ + return 0; +} + +HACCEL STDCALL +CreateAcceleratorTableA(LPACCEL lpaccl, + int cEntries) +{ + return (HACCEL)0; +} + +HACCEL STDCALL +CreateAcceleratorTableW(LPACCEL lpaccl, + int cEntries) +{ + return (HACCEL)0; +} + +WINBOOL STDCALL +DestroyAcceleratorTable(HACCEL hAccel) +{ + RtlFreeHeap(RtlGetProcessHeap(), 0, hAccel); + return(TRUE); +} + +HACCEL STDCALL +LoadAcceleratorsA(HINSTANCE hInstance, + LPCSTR lpTableName) +{ + LPWSTR lpTableNameW; + HACCEL Res; + UNICODE_STRING lpTableNameString; + RtlCreateUnicodeStringFromAsciiz(&lpTableNameString, (LPSTR)lpTableName); + lpTableNameW = lpTableNameString.Buffer; + Res = LoadAcceleratorsW(hInstance, lpTableNameW); + RtlFreeUnicodeString(&lpTableNameString); + return(Res); +} + +HACCEL STDCALL +LoadAcceleratorsW(HINSTANCE hInstance, + LPCWSTR lpTableName) +{ + HRSRC Rsrc; + HGLOBAL Mem; + PVOID AccelTableRsrc; + PVOID AccelTable; + ULONG Size; + + Rsrc = FindResourceW(hInstance, lpTableName, RT_ACCELERATOR); + if (Rsrc == NULL) + { + return(NULL); + } + else + { + Mem = LoadResource(hInstance, Rsrc); + Size = SizeofResource(hInstance, Rsrc); + AccelTableRsrc = LockResource(Mem); + AccelTable = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); + memcpy(AccelTable, AccelTableRsrc, Size); + return((HACCEL)AccelTable); + } +} + +int STDCALL +TranslateAcceleratorA(HWND hWnd, + HACCEL hAccTable, + LPMSG lpMsg) +{ + return 0; +} + +int STDCALL +TranslateAcceleratorW(HWND hWnd, + HACCEL hAccTable, + LPMSG lpMsg) +{ + return 0; +} diff --git a/lib/user32/windows/bitmap.c b/lib/user32/windows/bitmap.c new file mode 100644 index 0000000..9b8147b --- /dev/null +++ b/lib/user32/windows/bitmap.c @@ -0,0 +1,266 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HANDLE STDCALL +LoadImageA(HINSTANCE hinst, + LPCSTR lpszName, + UINT uType, + int cxDesired, + int cyDesired, + UINT fuLoad) +{ + LPWSTR lpszWName; + HANDLE Handle; + UNICODE_STRING NameString; + + if (HIWORD(lpszName)) + { + RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName); + lpszWName = NameString.Buffer; + Handle = LoadImageW(hinst, lpszWName, uType, cxDesired, + cyDesired, fuLoad); + RtlFreeUnicodeString(&NameString); + } + else + { + Handle = LoadImageW(hinst, lpszWName, uType, cxDesired, + cyDesired, fuLoad); + } + return(Handle); +} + +HANDLE STATIC +LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad) +{ + HANDLE hResource; + HANDLE hFile; + HANDLE hSection; + BITMAPINFO* BitmapInfo; + BITMAPINFO* PrivateInfo; + HDC hScreenDc; + HANDLE hBitmap; + ULONG HeaderSize; + ULONG ColourCount; + PVOID Data; + + if (!(fuLoad & LR_LOADFROMFILE)) + { + if (hInstance == NULL) + { + hInstance = GetModuleHandle(L"USER32"); + } + hResource = FindResourceW(hInstance, lpszName, RT_BITMAP); + if (hResource == NULL) + { + return(NULL); + } + hResource = LoadResource(hInstance, hResource); + if (hResource == NULL) + { + return(NULL); + } + BitmapInfo = LockResource(hResource); + if (BitmapInfo == NULL) + { + return(NULL); + } + } + else + { + hFile = CreateFile(lpszName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (hFile == NULL) + { + return(NULL); + } + hSection = CreateFileMapping(hFile, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + CloseHandle(hFile); + if (hSection == NULL) + { + return(NULL); + } + BitmapInfo = MapViewOfFile(hSection, + FILE_MAP_READ, + 0, + 0, + 0); + CloseHandle(hSection); + if (BitmapInfo == NULL) + { + return(NULL); + } + } + + if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo; + ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; + HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE); + } + else + { + ColourCount = BitmapInfo->bmiHeader.biClrUsed; + if (ColourCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8) + { + ColourCount = 1 << BitmapInfo->bmiHeader.biBitCount; + } + HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD); + } + Data = (PVOID)BitmapInfo + HeaderSize; + + PrivateInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, HeaderSize); + if (PrivateInfo == NULL) + { + if (fuLoad & LR_LOADFROMFILE) + { + UnmapViewOfFile(BitmapInfo); + } + return(NULL); + } + memcpy(PrivateInfo, BitmapInfo, HeaderSize); + + /* FIXME: Handle colour conversion and transparency. */ + + hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL); + if (hScreenDc == NULL) + { + if (fuLoad & LR_LOADFROMFILE) + { + UnmapViewOfFile(BitmapInfo); + } + return(NULL); + } + + if (fuLoad & LR_CREATEDIBSECTION) + { + DIBSECTION Dib; + + hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL, + 0, 0); + GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib); + SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo, + DIB_RGB_COLORS); + } + else + { + hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT, + Data, PrivateInfo, DIB_RGB_COLORS); + } + + RtlFreeHeap(RtlGetProcessHeap(), 0, PrivateInfo); + /*DeleteDC(hScreenDc);*/ + if (fuLoad & LR_LOADFROMFILE) + { + UnmapViewOfFile(BitmapInfo); + } + return(hBitmap); +} + +HANDLE STDCALL +LoadImageW(HINSTANCE hinst, + LPCWSTR lpszName, + UINT uType, + int cxDesired, + int cyDesired, + UINT fuLoad) +{ + if (fuLoad & LR_DEFAULTSIZE) + { + if (uType == IMAGE_ICON) + { + if (cxDesired == 0) + { + cxDesired = GetSystemMetrics(SM_CXICON); + } + if (cyDesired == 0) + { + cyDesired = GetSystemMetrics(SM_CYICON); + } + } + else if (uType == IMAGE_CURSOR) + { + if (cxDesired == 0) + { + cxDesired = GetSystemMetrics(SM_CXCURSOR); + } + if (cyDesired == 0) + { + cyDesired = GetSystemMetrics(SM_CYCURSOR); + } + } + } + + switch (uType) + { + case IMAGE_BITMAP: + { + return(LoadBitmapImage(hinst, lpszName, fuLoad)); + } + case IMAGE_CURSOR: + { + DbgPrint("FIXME: Need support for loading cursors.\n"); + return(NULL); + } + default: + DbgBreakPoint(); + break; + } + return(NULL); +} + + +HBITMAP STDCALL +LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName) +{ + return(LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0)); +} + +HBITMAP STDCALL +LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName) +{ + return(LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0)); +} diff --git a/lib/user32/windows/class.c b/lib/user32/windows/class.c new file mode 100644 index 0000000..5331101 --- /dev/null +++ b/lib/user32/windows/class.c @@ -0,0 +1,299 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/class.c + * PURPOSE: Window classes + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ +#include +#include +#include + + +WINBOOL +STDCALL +GetClassInfoA( + HINSTANCE hInstance, + LPCSTR lpClassName, + LPWNDCLASS lpWndClass) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetClassInfoExA( + HINSTANCE hinst, + LPCSTR lpszClass, + LPWNDCLASSEX lpwcx) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetClassInfoExW( + HINSTANCE hinst, + LPCWSTR lpszClass, + LPWNDCLASSEX lpwcx) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetClassInfoW( + HINSTANCE hInstance, + LPCWSTR lpClassName, + LPWNDCLASS lpWndClass) +{ + return FALSE; +} + +DWORD STDCALL +GetClassLongA(HWND hWnd, int nIndex) +{ + switch (nIndex) + { + case GCL_WNDPROC: + UNIMPLEMENTED; + return(0); + case GCL_MENUNAME: + UNIMPLEMENTED; + return(0); + default: + return(GetClassLongW(hWnd, nIndex)); + } +} + +DWORD STDCALL +GetClassLongW(HWND hWnd, int nIndex) +{ + return(NtUserGetClassLong(hWnd, nIndex)); +} + +int +STDCALL +GetClassNameA( + HWND hWnd, + LPSTR lpClassName, + int nMaxCount) +{ + return 0; +} + +int +STDCALL +GetClassNameW( + HWND hWnd, + LPWSTR lpClassName, + int nMaxCount) +{ + return 0; +} + +WORD +STDCALL +GetClassWord( + HWND hWnd, + int nIndex) +/* + * NOTE: Obsoleted in 32-bit windows + */ +{ + return 0; +} + +LONG STDCALL +GetWindowLongA(HWND hWnd, int nIndex) +{ + return 0; +} + +LONG STDCALL +GetWindowLongW(HWND hWnd, int nIndex) +{ + return(NtUserGetWindowLong(hWnd, nIndex)); +} + +UINT +STDCALL +RealGetWindowClass( + HWND hwnd, + LPSTR pszType, + UINT cchType) +{ + return 0; +} + +UINT +STDCALL +RealGetWindowClassA( + HWND hwnd, + LPSTR pszType, + UINT cchType) +{ + return 0; +} + +UINT +STDCALL +RealGetWindowClassW( + HWND hwnd, + LPWSTR pszType, + UINT cchType) +{ + return 0; +} + +ATOM STDCALL +RegisterClassA(CONST WNDCLASS *lpWndClass) +{ + WNDCLASSEX Class; + + RtlMoveMemory(&Class.style, lpWndClass, sizeof(WNDCLASS)); + Class.cbSize = sizeof(WNDCLASSEX); + Class.hIconSm = INVALID_HANDLE_VALUE; + return RegisterClassExA(&Class); +} + +ATOM STDCALL +RegisterClassExA(CONST WNDCLASSEX *lpwcx) +{ + UNICODE_STRING MenuName; + UNICODE_STRING ClassName; + WNDCLASSEX Class; + RTL_ATOM Atom; + + if (!RtlCreateUnicodeStringFromAsciiz(&MenuName, (PCSZ)lpwcx->lpszMenuName)) + { + RtlFreeUnicodeString(&MenuName); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return (ATOM)0; + } + + if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, (PCSZ)lpwcx->lpszClassName)) + { + RtlFreeUnicodeString(&ClassName); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return (ATOM)0; + } + + RtlMoveMemory(&Class, lpwcx, sizeof(WNDCLASSEX)); + Class.lpszMenuName = (LPCTSTR)MenuName.Buffer; + Class.lpszClassName = (LPCTSTR)ClassName.Buffer; + + Atom = NtUserRegisterClassExWOW(&Class, + FALSE, + 0, + 0, + 0, + 0); + + RtlFreeUnicodeString(&ClassName); + RtlFreeUnicodeString(&MenuName); + + return (ATOM)Atom; +} + +ATOM STDCALL +RegisterClassExW(CONST WNDCLASSEX *lpwcx) +{ + RTL_ATOM Atom; + + Atom = NtUserRegisterClassExWOW((WNDCLASSEX*)lpwcx, + TRUE, + 0, + 0, + 0, + 0); + + return (ATOM)Atom; +} + +ATOM STDCALL +RegisterClassW(CONST WNDCLASS *lpWndClass) +{ + WNDCLASSEX Class; + + RtlMoveMemory(&Class.style, lpWndClass, sizeof(WNDCLASS)); + Class.cbSize = sizeof(WNDCLASSEX); + Class.hIconSm = INVALID_HANDLE_VALUE; + return RegisterClassExW(&Class); +} + +DWORD +STDCALL +SetClassLongA( + HWND hWnd, + int nIndex, + LONG dwNewLong) +{ + return 0; +} + +DWORD +STDCALL +SetClassLongW( + HWND hWnd, + int nIndex, + LONG dwNewLong) +{ + return 0; +} + +WORD +STDCALL +SetClassWord( + HWND hWnd, + int nIndex, + WORD wNewWord) +/* + * NOTE: Obsoleted in 32-bit windows + */ +{ + return 0; +} + +LONG +STDCALL +SetWindowLongA( + HWND hWnd, + int nIndex, + LONG dwNewLong) +{ + return 0; +} + +LONG +STDCALL +SetWindowLongW( + HWND hWnd, + int nIndex, + LONG dwNewLong) +{ + return 0; +} + +WINBOOL +STDCALL +UnregisterClassA( + LPCSTR lpClassName, + HINSTANCE hInstance) +{ + return FALSE; +} + +WINBOOL +STDCALL +UnregisterClassW( + LPCWSTR lpClassName, + HINSTANCE hInstance) +{ + return FALSE; +} + +/* EOF */ diff --git a/lib/user32/windows/clipboard.c b/lib/user32/windows/clipboard.c new file mode 100644 index 0000000..920d0cd --- /dev/null +++ b/lib/user32/windows/clipboard.c @@ -0,0 +1,177 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +CloseClipboard(VOID) +{ + return FALSE; +} +int +STDCALL +CountClipboardFormats(VOID) +{ + return 0; +} +WINBOOL +STDCALL +EmptyClipboard(VOID) +{ + return FALSE; +} +UINT +STDCALL +EnumClipboardFormats( + UINT format) +{ + return 0; +} +HANDLE +STDCALL +GetClipboardData( + UINT uFormat) +{ + return (HANDLE)0; +} + +int +STDCALL +GetClipboardFormatNameA( + UINT format, + LPSTR lpszFormatName, + int cchMaxCount) +{ + return 0; +} + +int +STDCALL +GetClipboardFormatNameW( + UINT format, + LPWSTR lpszFormatName, + int cchMaxCount) +{ + return 0; +} + +HWND +STDCALL +GetClipboardOwner(VOID) +{ + return (HWND)0; +} + +DWORD +STDCALL +GetClipboardSequenceNumber(VOID) +{ + return 0; +} + +HWND +STDCALL +GetClipboardViewer(VOID) +{ + return (HWND)0; +} +HWND +STDCALL +GetOpenClipboardWindow(VOID) +{ + return (HWND)0; +} + +int +STDCALL +GetPriorityClipboardFormat( + UINT *paFormatPriorityList, + int cFormats) +{ + return 0; +} +WINBOOL +STDCALL +IsClipboardFormatAvailable( + UINT format) +{ + return FALSE; +} +WINBOOL +STDCALL +OpenClipboard( + HWND hWndNewOwner) +{ + return FALSE; +} +UINT +STDCALL +RegisterClipboardFormatA( + LPCSTR lpszFormat) +{ + return 0; +} + +UINT +STDCALL +RegisterClipboardFormatW( + LPCWSTR lpszFormat) +{ + return 0; +} +HANDLE +STDCALL +SetClipboardData( + UINT uFormat, + HANDLE hMem) +{ + return (HANDLE)0; +} + +HWND +STDCALL +SetClipboardViewer( + HWND hWndNewViewer) +{ + return (HWND)0; +} +WINBOOL +STDCALL +ChangeClipboardChain( + HWND hWndRemove, + HWND hWndNewNext) +{ + return FALSE; +} diff --git a/lib/user32/windows/cursor.c b/lib/user32/windows/cursor.c new file mode 100644 index 0000000..71c88e1 --- /dev/null +++ b/lib/user32/windows/cursor.c @@ -0,0 +1,191 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/cursor.c + * PURPOSE: Cursor + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +CreateCaret(HWND hWnd, + HBITMAP hBitmap, + int nWidth, + int nHeight) +{ + return FALSE; +} + +HCURSOR STDCALL +CreateCursor(HINSTANCE hInst, + int xHotSpot, + int yHotSpot, + int nWidth, + int nHeight, + CONST VOID *pvANDPlane, + CONST VOID *pvXORPlane) +{ + + return (HCURSOR)0; +} + +WINBOOL STDCALL +DestroyCaret(VOID) +{ + return FALSE; +} + +WINBOOL STDCALL +DestroyCursor(HCURSOR hCursor) +{ + return FALSE; +} + +UINT STDCALL +GetCaretBlinkTime(VOID) +{ + return 0; +} + +WINBOOL STDCALL +GetCaretPos(LPPOINT lpPoint) +{ + return FALSE; +} + +WINBOOL STDCALL +GetClipCursor(LPRECT lpRect) +{ + return FALSE; +} + +HCURSOR STDCALL +GetCursor(VOID) +{ + return (HCURSOR)0; +} + +WINBOOL STDCALL +GetCursorInfo(PCURSORINFO pci) +{ + return FALSE; +} + +WINBOOL STDCALL +GetCursorPos(LPPOINT lpPoint) +{ + return FALSE; +} + +WINBOOL STDCALL +HideCaret(HWND hWnd) +{ + return FALSE; +} + +HCURSOR STDCALL +LoadCursorA(HINSTANCE hInstance, + LPCSTR lpCursorName) +{ + return(LoadImageA(hInstance, lpCursorName, IMAGE_CURSOR, 0, 0, + LR_DEFAULTSIZE)); +} + +HCURSOR STDCALL +LoadCursorFromFileA(LPCSTR lpFileName) +{ + UNICODE_STRING FileName; + HCURSOR Result; + RtlCreateUnicodeStringFromAsciiz(&FileName, (LPSTR)lpFileName); + Result = LoadImageW(0, FileName.Buffer, IMAGE_CURSOR, 0, 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE); + RtlFreeUnicodeString(&FileName); + return(Result); +} + +HCURSOR STDCALL +LoadCursorFromFileW(LPCWSTR lpFileName) +{ + return(LoadImageW(0, lpFileName, IMAGE_CURSOR, 0, 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE)); +} + +HCURSOR STDCALL +LoadCursorW(HINSTANCE hInstance, + LPCWSTR lpCursorName) +{ + return(LoadImageW(hInstance, lpCursorName, IMAGE_CURSOR, 0, 0, + LR_DEFAULTSIZE)); +} + +WINBOOL STDCALL +SetCaretBlinkTime(UINT uMSeconds) +{ + return FALSE; +} + +WINBOOL STDCALL +SetCaretPos(int X, + int Y) +{ + return FALSE; +} + +HCURSOR STDCALL +SetCursor(HCURSOR hCursor) +{ + return (HCURSOR)0; +} + +WINBOOL STDCALL +SetCursorPos(int X, + int Y) +{ + return FALSE; +} + +WINBOOL STDCALL +SetSystemCursor(HCURSOR hcur, + DWORD id) +{ + return FALSE; +} + +WINBOOL STDCALL +ShowCaret(HWND hWnd) +{ + return FALSE; +} + +int STDCALL +ShowCursor(WINBOOL bShow) +{ + return 0; +} diff --git a/lib/user32/windows/dc.c b/lib/user32/windows/dc.c new file mode 100644 index 0000000..37bf923 --- /dev/null +++ b/lib/user32/windows/dc.c @@ -0,0 +1,75 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HDC +STDCALL +GetDC( + HWND hWnd) +{ + return NtUserGetDC(hWnd); +} + +HDC +STDCALL +GetDCEx( + HWND hWnd, + HRGN hrgnClip, + DWORD flags) +{ + return NtUserGetDCEx(hWnd, hrgnClip, flags); +} +HDC +STDCALL +GetWindowDC( + HWND hWnd) +{ + return (HDC)0; +} +int +STDCALL +ReleaseDC( + HWND hWnd, + HDC hDC) +{ + return 0; +} +HWND +STDCALL +WindowFromDC( + HDC hDC) +{ + return (HWND)0; +} diff --git a/lib/user32/windows/defwnd.c b/lib/user32/windows/defwnd.c new file mode 100644 index 0000000..631d63e --- /dev/null +++ b/lib/user32/windows/defwnd.c @@ -0,0 +1,1587 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/window.c + * PURPOSE: Window management + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +/* GLOBALS *******************************************************************/ + +static HBITMAP hbitmapClose; +static HBITMAP hbitmapMinimize; +static HBITMAP hbitmapMinimizeD; +static HBITMAP hbitmapMaximize; +static HBITMAP hbitmapMaximizeD; +static HBITMAP hbitmapRestore; +static HBITMAP hbitmapRestoreD; + +static COLORREF SysColours[] = + { + RGB(224, 224, 224) /* COLOR_SCROLLBAR */, + RGB(192, 192, 192) /* COLOR_BACKGROUND */, + RGB(0, 64, 128) /* COLOR_ACTIVECAPTION */, + RGB(255, 255, 255) /* COLOR_INACTIVECAPTION */, + RGB(255, 255, 255) /* COLOR_MENU */, + RGB(255, 255, 255) /* COLOR_WINDOW */, + RGB(0, 0, 0) /* COLOR_WINDOWFRAME */, + RGB(0, 0, 0) /* COLOR_MENUTEXT */, + RGB(0, 0, 0) /* COLOR_WINDOWTEXT */, + RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */, + RGB(128, 128, 128) /* COLOR_ACTIVEBORDER */, + RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */, + RGB(255, 255, 232) /* COLOR_APPWORKSPACE */, + RGB(224, 224, 224) /* COLOR_HILIGHT */, + RGB(0, 0, 0) /* COLOR_HILIGHTTEXT */, + RGB(192, 192, 192) /* COLOR_BTNFACE */, + RGB(128, 128, 128) /* COLOR_BTNSHADOW */, + RGB(192, 192, 192) /* COLOR_GRAYTEXT */, + RGB(0, 0, 0) /* COLOR_BTNTEXT */, + RGB(0, 0, 0) /* COLOR_INACTIVECAPTIONTEXT */, + RGB(255, 255, 255) /* COLOR_BTNHILIGHT */, + RGB(32, 32, 32) /* COLOR_3DDKSHADOW */, + RGB(192, 192, 192) /* COLOR_3DLIGHT */, + RGB(0, 0, 0) /* COLOR_INFOTEXT */, + RGB(255, 255, 192) /* COLOR_INFOBK */, + RGB(184, 180, 184) /* COLOR_ALTERNATEBTNFACE */, + RGB(0, 0, 255) /* COLOR_HOTLIGHT */, + RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */, + RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */, + }; + +static ATOM AtomInternalPos; + +/* FUNCTIONS *****************************************************************/ + +VOID +UserSetupInternalPos(VOID) +{ + LPSTR Str = "SysIP"; + AtomInternalPos = GlobalAddAtomA(Str); +} + +/* ReactOS extension */ +HPEN STDCALL +GetSysColorPen(int nIndex) +{ + return(CreatePen(PS_SOLID, 1, SysColours[nIndex])); +} + +HBRUSH STDCALL +GetSysColorBrush(int nIndex) +{ + return(CreateSolidBrush(SysColours[nIndex])); +} + + +LRESULT STDCALL +DefFrameProcA(HWND hWnd, + HWND hWndMDIClient, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + return((LRESULT)0); +} + +LRESULT STDCALL +DefFrameProcW(HWND hWnd, + HWND hWndMDIClient, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + return((LRESULT)0); +} + + +BOOL +DefWndRedrawIconTitle(HWND hWnd) +{ + PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd, + (LPSTR)(DWORD)AtomInternalPos); + if (lpPos != NULL) + { + if (lpPos->IconTitle != NULL) + { + SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0); + InvalidateRect(lpPos->IconTitle, NULL, TRUE); + return(TRUE); + } + } + return(FALSE); +} + +BOOL +UserHasMenu(HWND hWnd, ULONG Style) +{ + return(!(Style & WS_CHILD) && GetWindowLong(hWnd, GWL_ID) != 0); +} + +ULONG +UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle) +{ + return((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || + (ExStyle & WS_EX_DLGMODALFRAME) || + (!(Style & (WS_CHILD | WS_POPUP)))); +} + +ULONG +UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle) +{ + return((ExStyle & WS_EX_DLGMODALFRAME) || + ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME)))); +} + +ULONG +UserHasThickFrameStyle(ULONG Style, ULONG ExStyle) +{ + return((Style & WS_THICKFRAME) && + (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME))); +} + +ULONG +UserHasThinFrameStyle(ULONG Style, ULONG ExStyle) +{ + return((Style & WS_BORDER) || + (!(Style & (WS_CHILD | WS_POPUP)))); +} + +ULONG +UserHasBigFrameStyle(ULONG Style, ULONG ExStyle) +{ + return((Style & (WS_THICKFRAME | WS_DLGFRAME)) || + (ExStyle & WS_EX_DLGMODALFRAME)); +} + +static void UserGetInsideRectNC( HWND hwnd, RECT *rect ) +{ + RECT WindowRect; + ULONG Style; + ULONG ExStyle; + + Style = GetWindowLong(hwnd, GWL_STYLE); + ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + GetWindowRect(hwnd, &WindowRect); + rect->top = rect->left = 0; + rect->right = WindowRect.right - WindowRect.left; + rect->bottom = WindowRect.bottom - WindowRect.top; + + if (Style & WS_ICONIC) + { + return; + } + + /* Remove frame from rectangle */ + if (UserHasThickFrameStyle(Style, ExStyle )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), + -GetSystemMetrics(SM_CYFRAME) ); + } + else + { + if (UserHasDlgFrameStyle(Style, ExStyle )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), + -GetSystemMetrics(SM_CYDLGFRAME)); + /* FIXME: this isn't in NC_AdjustRect? why not? */ + if (ExStyle & WS_EX_DLGMODALFRAME) + InflateRect( rect, -1, 0 ); + } + else + { + if (UserHasThinFrameStyle(Style, ExStyle)) + { + InflateRect(rect, -GetSystemMetrics(SM_CXBORDER), + -GetSystemMetrics(SM_CYBORDER)); + } + } + } +} + +void UserDrawSysButton( HWND hwnd, HDC hdc, BOOL down ) +{ + RECT rect; + HDC hdcMem; + HBITMAP hbitmap; + ULONG Style; + + Style = GetWindowLong(hwnd, GWL_STYLE); + UserGetInsideRectNC( hwnd, &rect ); + hdcMem = CreateCompatibleDC( hdc ); + hbitmap = SelectObject( hdcMem, hbitmapClose ); + BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), + GetSystemMetrics(SM_CYSIZE), hdcMem, + (Style & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0, + down ? NOTSRCCOPY : SRCCOPY ); + SelectObject( hdcMem, hbitmap ); + DeleteDC( hdcMem ); +} + +static void UserDrawMaxButton( HWND hwnd, HDC hdc, BOOL down ) +{ + RECT rect; + HDC hdcMem; + + UserGetInsideRectNC( hwnd, &rect ); + hdcMem = CreateCompatibleDC( hdc ); + SelectObject( hdcMem, (IsZoomed(hwnd) + ? (down ? hbitmapRestoreD : hbitmapRestore) + : (down ? hbitmapMaximizeD : hbitmapMaximize)) ); + BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSMSIZE) - 1, rect.top, + GetSystemMetrics(SM_CXSMSIZE) + 1, GetSystemMetrics(SM_CYSMSIZE), hdcMem, 0, 0, + SRCCOPY ); + DeleteDC( hdcMem ); +} + +static void UserDrawMinButton( HWND hwnd, HDC hdc, BOOL down) +{ + RECT rect; + HDC hdcMem; + + UserGetInsideRectNC(hwnd, &rect); + hdcMem = CreateCompatibleDC(hdc); + SelectObject(hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize)); + if (GetWindowLong(hwnd, GWL_STYLE) & WS_MAXIMIZEBOX) + { + rect.right -= GetSystemMetrics(SM_CXSMSIZE)+1; + } + BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSMSIZE) - 1, rect.top, + GetSystemMetrics(SM_CXSMSIZE) + 1, GetSystemMetrics(SM_CYSMSIZE), + hdcMem, 0, 0, + SRCCOPY ); + DeleteDC( hdcMem ); +} + +static void UserDrawCaptionNC( HDC hdc, RECT *rect, HWND hwnd, + DWORD style, BOOL active ) +{ + RECT r = *rect; + char buffer[256]; + + if (!hbitmapClose) + { + hbitmapClose = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_CLOSE)); + hbitmapMinimize = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCE) ); + hbitmapMinimizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCED) ); + hbitmapMaximize = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOM) ); + hbitmapMaximizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOMD) ); + hbitmapRestore = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORE) ); + hbitmapRestoreD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORED) ); + } + + if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME) + { + HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) ); + PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY ); + PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY ); + PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY ); + r.left++; + r.right--; + SelectObject( hdc, hbrushOld ); + } + + MoveToEx( hdc, r.left, r.bottom, NULL ); + LineTo( hdc, r.right, r.bottom ); + + if (style & WS_SYSMENU) + { + UserDrawSysButton( hwnd, hdc, FALSE ); + r.left += GetSystemMetrics(SM_CXSIZE) + 1; + MoveToEx( hdc, r.left - 1, r.top, NULL ); + LineTo( hdc, r.left - 1, r.bottom ); + } + if (style & WS_MAXIMIZEBOX) + { + UserDrawMaxButton( hwnd, hdc, FALSE ); + r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1; + } + if (style & WS_MINIMIZEBOX) + { + UserDrawMinButton( hwnd, hdc, FALSE ); + r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1; + } + + FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : + COLOR_INACTIVECAPTION) ); + + if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) + { + NONCLIENTMETRICS nclm; + HFONT hFont, hOldFont; + + nclm.cbSize = sizeof(NONCLIENTMETRICS); + SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &nclm, 0); + if (style & WS_EX_TOOLWINDOW) + hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont); + else + hFont = CreateFontIndirectW(&nclm.lfCaptionFont); + hOldFont = SelectObject(hdc, hFont); + + if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) ); + else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ); + SetBkMode( hdc, TRANSPARENT ); + /*DrawTextA( hdc, buffer, -1, &r, + DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );*/ + TextOutA(hdc, r.left+5, r.top+2, buffer, strlen(buffer)); + DeleteObject (SelectObject (hdc, hOldFont)); + } +} + +VOID +UserDrawFrameNC(HDC hdc, RECT* rect, BOOL dlgFrame, BOOL active) +{ + INT width, height; + + if (dlgFrame) + { + width = GetSystemMetrics(SM_CXDLGFRAME) - 1; + height = GetSystemMetrics(SM_CYDLGFRAME) - 1; + SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : + COLOR_INACTIVECAPTION) ); + } + else + { + width = GetSystemMetrics(SM_CXFRAME) - 2; + height = GetSystemMetrics(SM_CYFRAME) - 2; + SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER : + COLOR_INACTIVEBORDER) ); + } + + /* Draw frame */ + PatBlt( hdc, rect->left, rect->top, + rect->right - rect->left, height, PATCOPY ); + PatBlt( hdc, rect->left, rect->top, + width, rect->bottom - rect->top, PATCOPY ); + PatBlt( hdc, rect->left, rect->bottom - 1, + rect->right - rect->left, -height, PATCOPY ); + PatBlt( hdc, rect->right - 1, rect->top, + -width, rect->bottom - rect->top, PATCOPY ); + + if (dlgFrame) + { + InflateRect( rect, -width, -height ); + } + else + { + INT decYOff = GetSystemMetrics(SM_CXFRAME) + + GetSystemMetrics(SM_CXSIZE) - 1; + INT decXOff = GetSystemMetrics(SM_CYFRAME) + + GetSystemMetrics(SM_CYSIZE) - 1; + + /* Draw inner rectangle */ + + SelectObject( hdc, GetStockObject(NULL_BRUSH) ); + Rectangle( hdc, rect->left + width, rect->top + height, + rect->right - width , rect->bottom - height ); + + /* Draw the decorations */ + + MoveToEx( hdc, rect->left, rect->top + decYOff, NULL ); + LineTo( hdc, rect->left + width, rect->top + decYOff ); + MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL ); + LineTo( hdc, rect->right - width - 1, rect->top + decYOff ); + MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL ); + LineTo( hdc, rect->left + width, rect->bottom - decYOff ); + MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL ); + LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff ); + + MoveToEx( hdc, rect->left + decXOff, rect->top, NULL ); + LineTo( hdc, rect->left + decXOff, rect->top + height); + MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL ); + LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 ); + MoveToEx( hdc, rect->right - decXOff, rect->top, NULL ); + LineTo( hdc, rect->right - decXOff, rect->top + height ); + MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL ); + LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 ); + + InflateRect( rect, -width - 1, -height - 1 ); + } +} + +VOID +DefWndDoPaintNC(HWND hWnd, HRGN clip) +{ + ULONG Active; + HDC hDc; + RECT rect; + ULONG Style; + ULONG ExStyle; + + Active = GetWindowLongW(hWnd, GWL_STYLE) & WIN_NCACTIVATED; + Style = GetWindowLong(hWnd, GWL_STYLE); + ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE); + + hDc = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW | + ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0)); + if (hDc == 0) + { + return; + } + + /* FIXME: Test whether we need to draw anything at all. */ + + GetWindowRect(hWnd, &rect); + rect.right = rect.right - rect.left; + rect.bottom = rect.bottom - rect.top; + rect.top = rect.left = 0; + + SelectObject(hDc, GetSysColorPen(COLOR_WINDOWFRAME)); + if (UserHasAnyFrameStyle(Style, ExStyle)) + { + SelectObject(hDc, GetStockObject(NULL_BRUSH)); + Rectangle(hDc, 0, 0, rect.right, rect.bottom); + InflateRect(&rect, -1, -1); + } + + if (UserHasThickFrameStyle(Style, ExStyle)) + { + UserDrawFrameNC(hDc, &rect, FALSE, Active); + } + else if (UserHasDlgFrameStyle(Style, ExStyle)) + { + UserDrawFrameNC(hDc, &rect, TRUE, Active); + } + + if (Style & WS_CAPTION) + { + RECT r = rect; + r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE); + rect.top += GetSystemMetrics(SM_CYSIZE) + + GetSystemMetrics(SM_CYBORDER); + UserDrawCaptionNC(hDc, &r, hWnd, Style, Active); + } + + /* FIXME: Draw menu bar. */ + + /* FIXME: Draw scroll bars. */ + + /* FIXME: Draw size box. */ + + ReleaseDC(hWnd, hDc); +} + +LRESULT +DefWndPaintNC(HWND hWnd, HRGN clip) +{ + if (IsWindowVisible(hWnd)) + { + if (IsIconic(hWnd)) + { + DefWndRedrawIconTitle(hWnd); + } + else + { + DefWndDoPaintNC(hWnd, clip); + } + } + return(0); +} + +LRESULT +DefWndHitTestNC(HWND hWnd, POINT Point) +{ + RECT WindowRect; + ULONG Style = GetWindowLong(hWnd, GWL_STYLE); + ULONG ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE); + + GetWindowRect(hWnd, &WindowRect); + + if (!PtInRect(&WindowRect, Point)) + { + return(HTNOWHERE); + } + if (Style & WS_MINIMIZE) + { + return(HTCAPTION); + } + if (UserHasThickFrameStyle(Style, ExStyle)) + { + InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME), + -GetSystemMetrics(SM_CYFRAME)); + if (!PtInRect(&WindowRect, Point)) + { + if (Point.y < WindowRect.top) + { + if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE))) + { + return(HTTOPLEFT); + } + if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE))) + { + return(HTTOPRIGHT); + } + return(HTTOP); + } + if (Point.y >= WindowRect.bottom) + { + if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE))) + { + return(HTBOTTOMLEFT); + } + if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE))) + { + return(HTBOTTOMRIGHT); + } + return(HTBOTTOM); + } + if (Point.x < WindowRect.left) + { + if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE))) + { + return(HTTOPLEFT); + } + if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE))) + { + return(HTBOTTOMLEFT); + } + return(HTLEFT); + } + if (Point.x >= WindowRect.right) + { + if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE))) + { + return(HTTOPRIGHT); + } + if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE))) + { + return(HTBOTTOMRIGHT); + } + return(HTRIGHT); + } + } + } + else + { + if (UserHasDlgFrameStyle(Style, ExStyle)) + { + InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME), + -GetSystemMetrics(SM_CYDLGFRAME)); + } + else if (UserHasThinFrameStyle(Style, ExStyle)) + { + InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER), + -GetSystemMetrics(SM_CYBORDER)); + } + if (!PtInRect(&WindowRect, Point)) + { + return(HTBORDER); + } + } + + if ((Style & WS_CAPTION) == WS_CAPTION) + { + WindowRect.top += GetSystemMetrics(SM_CYCAPTION) - + GetSystemMetrics(SM_CYBORDER); + if (!PtInRect(&WindowRect, Point)) + { + if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW)) + { + WindowRect.left += GetSystemMetrics(SM_CXSIZE); + } + if (Point.x <= WindowRect.left) + { + return(HTSYSMENU); + } + + if (Style & WS_MAXIMIZEBOX) + { + WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1; + } + if (Point.x >= WindowRect.right) + { + return(HTMAXBUTTON); + } + + if (Style & WS_MINIMIZEBOX) + { + WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1; + } + if (Point.x >= WindowRect.right) + { + return(HTMINBUTTON); + } + return(HTCAPTION); + } + } + + ScreenToClient(hWnd, &Point); + GetClientRect(hWnd, &WindowRect); + + if (PtInRect(&WindowRect, Point)) + { + return(HTCLIENT); + } + + if (Style & WS_VSCROLL) + { + WindowRect.right += GetSystemMetrics(SM_CXVSCROLL); + if (PtInRect(&WindowRect, Point)) + { + return(HTVSCROLL); + } + } + + if (Style & WS_HSCROLL) + { + WindowRect.bottom += GetSystemMetrics(SM_CYHSCROLL); + if (PtInRect(&WindowRect, Point)) + { + if ((Style & WS_VSCROLL) && + (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL)))) + { + return(HTSIZE); + } + return(HTHSCROLL); + } + } + + if (UserHasMenu(hWnd, Style)) + { + if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right) + { + return(HTMENU); + } + } + + return(HTNOWHERE); +} + +VOID +DefWndTrackMinMaxBox(HWND hWnd, WPARAM wParam) +{ + HDC hDC = GetWindowDC(hWnd); + BOOL Pressed = TRUE; + MSG Msg; + + SetCapture(hWnd); + + if (wParam == HTMINBUTTON) + { + UserDrawMinButton(hWnd, hDC, TRUE); + } + else + { + UserDrawMaxButton(hWnd, hDC, TRUE); + } + + for(;;) + { + BOOL OldState = Pressed; + + GetMessageA(hWnd, &Msg, 0, 0); + if (Msg.message == WM_LBUTTONUP) + { + break; + } + if (Msg.message != WM_MOUSEMOVE) + { + continue; + } + + Pressed = DefWndHitTestNC(hWnd, Msg.pt) == wParam; + if (Pressed != OldState) + { + if (wParam == HTMINBUTTON) + { + UserDrawMinButton(hWnd, hDC, Pressed); + } + else + { + UserDrawMaxButton(hWnd, hDC, Pressed); + } + } + } + + if (Pressed) + { + if (wParam == HTMINBUTTON) + { + UserDrawMinButton(hWnd, hDC, FALSE); + } + else + { + UserDrawMaxButton(hWnd, hDC, FALSE); + } + } + + ReleaseCapture(); + ReleaseDC(hWnd, hDC); + + if (!Pressed) + { + return; + } + + if (wParam == HTMINBUTTON) + { + SendMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, + MAKELONG(Msg.pt.x, Msg.pt.y)); + } + else + { + SendMessageA(hWnd, WM_SYSCOMMAND, + IsZoomed(hWnd) ? SC_RESTORE : SC_MAXIMIZE, + MAKELONG(Msg.pt.x, Msg.pt.y)); + } +} + +VOID +DefWndDrawSysButton(HWND hWnd, HDC hDC, BOOL Down) +{ + RECT Rect; + HDC hDcMem; + HBITMAP hSavedBitmap; + + UserGetInsideRectNC(hWnd, &Rect); + hDcMem = CreateCompatibleDC(hDC); + hSavedBitmap = SelectObject(hDcMem, hbitmapClose); + BitBlt(hDC, Rect.left, Rect.top, GetSystemMetrics(SM_CXSIZE), + GetSystemMetrics(SM_CYSIZE), hDcMem, + (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ? + GetSystemMetrics(SM_CXSIZE): 0, 0, Down ? NOTSRCCOPY : SRCCOPY); + SelectObject(hDcMem, hSavedBitmap); + DeleteDC(hDcMem); +} + +LRESULT +DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + switch (wParam) + { + case HTCAPTION: + { + HWND hTopWnd = GetAncestor(hWnd, GA_ROOT); + if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd) + { + SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam); + } + break; + } + case HTSYSMENU: + { + if (GetWindowLong(hWnd, GWL_STYLE) & WS_SYSMENU) + { + if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE)) + { + HDC hDC = GetWindowDC(hWnd); + DefWndDrawSysButton(hWnd, hDC, TRUE); + ReleaseDC(hWnd, hDC); + } + SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, + lParam); + } + break; + } + + case HTMENU: + SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); + break; + + case HTHSCROLL: + SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam); + break; + + case HTVSCROLL: + SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam); + break; + + case HTMINBUTTON: + case HTMAXBUTTON: + DefWndTrackMinMaxBox(hWnd, wParam); + break; + + case HTLEFT: + case HTRIGHT: + case HTTOP: + case HTBOTTOM: + case HTTOPLEFT: + case HTTOPRIGHT: + case HTBOTTOMLEFT: + case HTBOTTOMRIGHT: + SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam); + break; + } + return(0); +} + +LRESULT +DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + /* FIXME: Implement this. */ + return(0); +} + +LRESULT +DefWndHandleActiveNC(HWND hWnd, WPARAM wParam) +{ + /* FIXME: Implement this. */ + return(0); +} + +VOID +DefWndSetRedraw(HWND hWnd, WPARAM wParam) +{ +} + +LRESULT +DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + /* Not for child windows. */ + if (hWnd != (HWND)wParam) + { + return(0); + } + + switch(LOWORD(lParam)) + { + case HTERROR: + { + WORD Msg = HIWORD(lParam); + if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN || + Msg == WM_RBUTTONDOWN) + { + MessageBeep(0); + } + break; + } + + case HTCLIENT: + { + HICON hCursor = (HICON)GetClassLong(hWnd, GCL_HCURSOR); + if (hCursor) + { + SetCursor(hCursor); + return(TRUE); + } + return(FALSE); + } + + case HTLEFT: + case HTRIGHT: + { + return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE))); + } + + case HTTOP: + case HTBOTTOM: + { + return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS))); + } + + case HTTOPLEFT: + case HTBOTTOMRIGHT: + { + return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE))); + } + + case HTBOTTOMLEFT: + case HTTOPRIGHT: + { + return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW))); + } + } + return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW))); +} + +LRESULT +DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt) +{ + /* FIXME: Implement system commands. */ + return(0); +} + +VOID +DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle) +{ + if (Style & WS_ICONIC) + { + return; + } + + if (UserHasThickFrameStyle(Style, ExStyle)) + { + InflateRect(Rect, GetSystemMetrics(SM_CXFRAME), + GetSystemMetrics(SM_CYFRAME)); + } + else if (UserHasDlgFrameStyle(Style, ExStyle)) + { + InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME), + GetSystemMetrics(SM_CYDLGFRAME)); + } + else if (UserHasThinFrameStyle(Style, ExStyle)) + { + InflateRect(Rect, GetSystemMetrics(SM_CXBORDER), + GetSystemMetrics(SM_CYBORDER)); + } + if (Style & WS_CAPTION) + { + Rect->top -= GetSystemMetrics(SM_CYCAPTION) - + GetSystemMetrics(SM_CYBORDER); + } + if (Menu) + { + Rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER); + } + if (Style & WS_VSCROLL) + { + Rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1; + if (UserHasAnyFrameStyle(Style, ExStyle)) + { + Rect->right++; + } + } + if (Style & WS_HSCROLL) + { + Rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1; + if (UserHasAnyFrameStyle(Style, ExStyle)) + { + Rect->bottom++; + } + } +} + +LRESULT STDCALL +DefWndNCCalcSize(HWND hWnd, RECT* Rect) +{ + LRESULT Result; + LONG Style = GetClassLongW(hWnd, GCL_STYLE); + RECT TmpRect = {0, 0, 0, 0}; + + if (Style & CS_VREDRAW) + { + Result |= WVR_VREDRAW; + } + if (Style & CS_HREDRAW) + { + Result |= WVR_HREDRAW; + } + + if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE)) + { + DefWndAdjustRect(&TmpRect, GetWindowLong(hWnd, GWL_STYLE), + FALSE, GetWindowLong(hWnd, GWL_EXSTYLE)); + Rect->left -= TmpRect.left; + Rect->top -= TmpRect.top; + Rect->right -= TmpRect.right; + Rect->bottom -= TmpRect.bottom; + /* FIXME: Adjust if the window has a menu. */ + Rect->bottom = max(Rect->top, Rect->bottom); + Rect->right = max(Rect->left, Rect->right); + } + return(Result); +} + +LRESULT +DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos) +{ + /* FIXME: Implement this. */ + return(0); +} + +LRESULT STDCALL +User32DefWindowProc(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + BOOL bUnicode) +{ + switch (Msg) + { + case WM_NCPAINT: + { + return(DefWndPaintNC(hWnd, (HRGN)wParam)); + } + + case WM_NCHITTEST: + { + POINT Point; + Point.x = SLOWORD(lParam); + Point.y = SHIWORD(lParam); + return(DefWndHitTestNC(hWnd, Point)); + } + + case WM_NCLBUTTONDOWN: + { + return(DefWndHandleLButtonDownNC(hWnd, wParam, lParam)); + } + + case WM_LBUTTONDBLCLK: + case WM_NCLBUTTONDBLCLK: + { + return(DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam)); + } + + case WM_NCRBUTTONDOWN: + { + if (wParam == HTCAPTION) + { + SetCapture(hWnd); + } + break; + } + + case WM_RBUTTONUP: + { + POINT Pt; + if (hWnd == GetCapture()) + { + ReleaseCapture(); + } + Pt.x = SLOWORD(lParam); + Pt.y = SHIWORD(lParam); + ClientToScreen(hWnd, &Pt); + lParam = MAKELPARAM(Pt.x, Pt.y); + if (bUnicode) + { + SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam); + } + else + { + SendMessageA (hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam); + } + break; + } + + case WM_NCRBUTTONUP: + { + /* Wine does nothing here. */ + break; + } + + case WM_CONTEXTMENU: + { + if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) + { + if (bUnicode) + { + SendMessageW(GetParent(hWnd), Msg, wParam, lParam); + } + else + { + SendMessageA(hWnd, WM_CONTEXTMENU, wParam, lParam); + } + } + else + { + LONG HitCode; + POINT Pt; + + Pt.x = SLOWORD(lParam); + Pt.y = SHIWORD(lParam); + + if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) + { + ScreenToClient(GetParent(hWnd), &Pt); + } + + HitCode = DefWndHitTestNC(hWnd, Pt); + + if (HitCode == HTCAPTION || HitCode == HTSYSMENU) + { + TrackPopupMenu(GetSystemMenu(hWnd, FALSE), + TPM_LEFTBUTTON | TPM_RIGHTBUTTON, + Pt.x, Pt.y, 0, hWnd, NULL); + } + } + break; + } + + case WM_NCACTIVATE: + { + return(DefWndHandleActiveNC(hWnd, wParam)); + } + + case WM_NCDESTROY: + { + return(0); + } + + case WM_PRINT: + { + return(0); + } + + case WM_PAINTICON: + case WM_PAINT: + { + PAINTSTRUCT Ps; + HDC hDc = BeginPaint(hWnd, &Ps); + if (hDc) + { + HICON hIcon; + if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE && + (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL) + { + RECT WindowRect; + INT x, y; + GetWindowRect(hWnd, &WindowRect); + x = (WindowRect.right - WindowRect.left - + GetSystemMetrics(SM_CXICON)) / 2; + y = (WindowRect.bottom - WindowRect.top - + GetSystemMetrics(SM_CYICON)) / 2; + DrawIcon(hDc, x, y, hIcon); + } + EndPaint(hWnd, &Ps); + } + return(0); + } + + case WM_SYNCPAINT: + { + HRGN hRgn; + hRgn = CreateRectRgn(0, 0, 0, 0); + if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION) + { + RedrawWindow(hWnd, NULL, hRgn, + RDW_ERASENOW | RDW_ERASE | RDW_FRAME | + RDW_ALLCHILDREN); + } + DeleteObject(hRgn); + return(0); + } + + case WM_SETREDRAW: + { + DefWndSetRedraw(hWnd, wParam); + return(0); + } + + case WM_CLOSE: + { + DestroyWindow(hWnd); + return(0); + } + + case WM_MOUSEACTIVATE: + { + if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) + { + LONG Ret; + if (bUnicode) + { + Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE, + wParam, lParam); + } + else + { + Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE, + wParam, lParam); + } + if (Ret) + { + return(Ret); + } + } + return((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE); + } + + case WM_ACTIVATE: + { + if (LOWORD(lParam) != WA_INACTIVE && + GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE) + { + /* Check if the window is minimized. */ + SetFocus(hWnd); + } + break; + } + + case WM_MOUSEWHEEL: + { + if (GetWindowLong(hWnd, GWL_STYLE & WS_CHILD)) + { + if (bUnicode) + { + return(SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL, + wParam, lParam)); + } + else + { + return(SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL, + wParam, lParam)); + } + } + break; + } + + case WM_ERASEBKGND: + case WM_ICONERASEBKGND: + { + RECT Rect; + HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND); + GetClipBox((HDC)wParam, &Rect); + FillRect((HDC)wParam, &Rect, hBrush); + return(1); + } + + case WM_GETDLGCODE: + { + return(0); + } + + /* FIXME: Implement colour controls. */ + + case WM_SETCURSOR: + { + if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) + { + if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT) + { + BOOL bResult; + if (bUnicode) + { + bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR, + wParam, lParam); + } + else + { + bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR, + wParam, lParam); + } + if (bResult) + { + return(TRUE); + } + } + } + return(DefWndHandleSetCursor(hWnd, wParam, lParam)); + } + + case WM_SYSCOMMAND: + { + POINT Pt; + Pt.x = SLOWORD(lParam); + Pt.y = SHIWORD(lParam); + return(DefWndHandleSysCommand(hWnd, wParam, Pt)); + } + + /* FIXME: Handle key messages. */ + + case WM_SHOWWINDOW: + { + if (lParam) + { + return(0); + } + /* FIXME: Check for a popup window. */ + if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE && !wParam) || + (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE) && wParam)) + { + return(0); + } + ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE); + break; + } + + case WM_CANCELMODE: + { + /* FIXME: Check for a desktop. */ + if (GetCapture() == hWnd) + { + ReleaseCapture(); + } + break; + } + + case WM_VKEYTOITEM: + case WM_CHARTOITEM: + return(-1); + + case WM_DROPOBJECT: + /* FIXME: Implement this. */ + break; + + case WM_QUERYDROPOBJECT: + { + if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES) + { + return(1); + } + break; + } + + case WM_QUERYDRAGICON: + { + UINT Len; + HICON hIcon; + + hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON); + if (hIcon) + { + return((LRESULT)hIcon); + } + for (Len = 1; Len < 64; Len++) + { + if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCE(Len))) != NULL) + { + return((LRESULT)hIcon); + } + } + return((LRESULT)LoadIconW(0, IDI_APPLICATION)); + } + + /* FIXME: WM_ISACTIVEICON */ + + case WM_NOTIFYFORMAT: + { + if (IsWindowUnicode(hWnd)) + { + return(NFR_UNICODE); + } + else + { + return(NFR_ANSI); + } + } + + case WM_SETICON: + { + INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM; + HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index); + SetClassLongW(hWnd, Index, lParam); + SetWindowPos(hWnd, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | + SWP_NOACTIVATE | SWP_NOZORDER); + return((LRESULT)hOldIcon); + } + + case WM_GETICON: + { + INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM; + return(GetClassLongW(hWnd, Index)); + } + + case WM_HELP: + { + if (bUnicode) + { + SendMessageW(GetParent(hWnd), Msg, wParam, lParam); + } + else + { + SendMessageA(GetParent(hWnd), Msg, wParam, lParam); + } + break; + } + } + return 0; +} + +LRESULT STDCALL +DefWindowProcA(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + LRESULT Result; + static LPSTR WindowTextAtom = 0; + PSTR WindowText; + + switch (Msg) + { + case WM_NCCREATE: + { + CREATESTRUCTA* Cs = (CREATESTRUCTA*)lParam; + if (HIWORD(Cs->lpszName)) + { + WindowTextAtom = + (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA"); + WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0, + strlen(Cs->lpszName) * sizeof(CHAR)); + strcpy(WindowText, Cs->lpszName); + SetPropA(hWnd, WindowTextAtom, WindowText); + } + return(1); + } + + case WM_NCCALCSIZE: + { + return(DefWndNCCalcSize(hWnd, (RECT*)lParam)); + } + + case WM_WINDOWPOSCHANGING: + { + return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam)); + } + + case WM_GETTEXTLENGTH: + { + if (WindowTextAtom == 0 || + (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL) + { + return(0); + } + return(strlen(WindowText)); + } + + case WM_GETTEXT: + { + if (WindowTextAtom == 0 || + (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL) + { + if (wParam > 1) + { + ((PSTR)lParam) = '\0'; + } + return(0); + } + strncpy((LPSTR)lParam, WindowText, wParam); + return(min(wParam, strlen(WindowText))); + } + + case WM_SETTEXT: + { + if (WindowTextAtom != 0) + { + WindowTextAtom = + (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomW"); + } + if (WindowTextAtom != 0 && + (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText); + } + WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0, + strlen((PSTR)lParam) * sizeof(CHAR)); + strcpy(WindowText, (PSTR)lParam); + SetPropA(hWnd, WindowTextAtom, WindowText); + } + + case WM_NCDESTROY: + { + if (WindowTextAtom != 0 && + (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL) + { + RtlFreeHeap(GetProcessHeap(), 0, WindowText); + } + if (WindowTextAtom != 0) + { + GlobalDeleteAtom((ATOM)(ULONG)WindowTextAtom); + } + /* FIXME: Destroy scroll bars here as well. */ + return(0); + } + + default: + Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE); + break; + } + + return(Result); +} + +LRESULT STDCALL +DefWindowProcW(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + LRESULT Result; + static LPWSTR WindowTextAtom = 0; + PWSTR WindowText; + + switch (Msg) + { + case WM_NCCREATE: + { + CREATESTRUCTW* Cs = (CREATESTRUCTW*)lParam; + if (HIWORD(Cs->lpszName)) + { + WindowTextAtom = + (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW"); + WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0, + wcslen(Cs->lpszName) * sizeof(WCHAR)); + wcscpy(WindowText, Cs->lpszName); + SetPropW(hWnd, WindowTextAtom, WindowText); + } + return(1); + } + + case WM_NCCALCSIZE: + { + return(DefWndNCCalcSize(hWnd, (RECT*)lParam)); + } + + case WM_WINDOWPOSCHANGING: + { + return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam)); + } + + case WM_GETTEXTLENGTH: + { + if (WindowTextAtom == 0 || + (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL) + { + return(0); + } + return(wcslen(WindowText)); + } + + case WM_GETTEXT: + { + if (WindowTextAtom == 0 || + (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL) + { + if (wParam > 1) + { + ((PWSTR)lParam) = '\0'; + } + return(0); + } + wcsncpy((PWSTR)lParam, WindowText, wParam); + return(min(wParam, wcslen(WindowText))); + } + + case WM_SETTEXT: + { + if (WindowTextAtom != 0) + { + WindowTextAtom = + (LPWSTR)(DWORD)GlobalAddAtom(L"USER32!WindowTextAtomW"); + } + if (WindowTextAtom != 0 && + (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText); + } + WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0, + wcslen((PWSTR)lParam) * sizeof(WCHAR)); + wcscpy(WindowText, (PWSTR)lParam); + SetPropW(hWnd, WindowTextAtom, WindowText); + } + + case WM_NCDESTROY: + { + if (WindowTextAtom != 0 && + (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText); + } + if (WindowTextAtom != 0) + { + GlobalDeleteAtom((ATOM)(DWORD)WindowTextAtom); + } + /* FIXME: Destroy scroll bars here as well. */ + return(0); + } + + default: + Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE); + break; + } + + return(Result); +} diff --git a/lib/user32/windows/dialog.c b/lib/user32/windows/dialog.c new file mode 100644 index 0000000..4e2a6d7 --- /dev/null +++ b/lib/user32/windows/dialog.c @@ -0,0 +1,458 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HWND +STDCALL +CreateDialogIndirectParamA( + HINSTANCE hInstance, + LPCDLGTEMPLATE lpTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM lParamInit) +{ + return (HWND)0; +} + +HWND +STDCALL +CreateDialogIndirectParamAorW( + HINSTANCE hInstance, + LPCDLGTEMPLATE lpTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM lParamInit) +{ + return (HWND)0; +} + +HWND +STDCALL +CreateDialogIndirectParamW( + HINSTANCE hInstance, + LPCDLGTEMPLATE lpTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM lParamInit) +{ + return (HWND)0; +} + +HWND +STDCALL +CreateDialogParamA( + HINSTANCE hInstance, + LPCSTR lpTemplateName, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (HWND)0; +} + +HWND +STDCALL +CreateDialogParamW( + HINSTANCE hInstance, + LPCWSTR lpTemplateName, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (HWND)0; +} +LRESULT +STDCALL +DefDlgProcA( + HWND hDlg, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} + +LRESULT +STDCALL +DefDlgProcW( + HWND hDlg, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} +INT_PTR +STDCALL +DialogBoxIndirectParamA( + HINSTANCE hInstance, + LPCDLGTEMPLATE hDialogTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (INT_PTR)NULL; +} + +INT_PTR +STDCALL +DialogBoxIndirectParamAorW( + HINSTANCE hInstance, + LPCDLGTEMPLATE hDialogTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (INT_PTR)NULL; +} + +INT_PTR +STDCALL +DialogBoxIndirectParamW( + HINSTANCE hInstance, + LPCDLGTEMPLATE hDialogTemplate, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (INT_PTR)NULL; +} + +INT_PTR +STDCALL +DialogBoxParamA( + HINSTANCE hInstance, + LPCSTR lpTemplateName, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (INT_PTR)0; +} + +INT_PTR +STDCALL +DialogBoxParamW( + HINSTANCE hInstance, + LPCWSTR lpTemplateName, + HWND hWndParent, + DLGPROC lpDialogFunc, + LPARAM dwInitParam) +{ + return (INT_PTR)0; +} + +int +STDCALL +DlgDirListA( + HWND hDlg, + LPSTR lpPathSpec, + int nIDListBox, + int nIDStaticPath, + UINT uFileType) +{ + return 0; +} + +int +STDCALL +DlgDirListComboBoxA( + HWND hDlg, + LPSTR lpPathSpec, + int nIDComboBox, + int nIDStaticPath, + UINT uFiletype) +{ + return 0; +} + +int +STDCALL +DlgDirListComboBoxW( + HWND hDlg, + LPWSTR lpPathSpec, + int nIDComboBox, + int nIDStaticPath, + UINT uFiletype) +{ + return 0; +} + +int +STDCALL +DlgDirListW( + HWND hDlg, + LPWSTR lpPathSpec, + int nIDListBox, + int nIDStaticPath, + UINT uFileType) +{ + return 0; +} + +WINBOOL +STDCALL +DlgDirSelectComboBoxExA( + HWND hDlg, + LPSTR lpString, + int nCount, + int nIDComboBox) +{ + return FALSE; +} + +WINBOOL +STDCALL +DlgDirSelectComboBoxExW( + HWND hDlg, + LPWSTR lpString, + int nCount, + int nIDComboBox) +{ + return FALSE; +} + +WINBOOL +STDCALL +DlgDirSelectExA( + HWND hDlg, + LPSTR lpString, + int nCount, + int nIDListBox) +{ + return FALSE; +} + +WINBOOL +STDCALL +DlgDirSelectExW( + HWND hDlg, + LPWSTR lpString, + int nCount, + int nIDListBox) +{ + return FALSE; +} +WINBOOL +STDCALL +EndDialog( + HWND hDlg, + INT_PTR nResult) +{ + return FALSE; +} +LONG +STDCALL +GetDialogBaseUnits(VOID) +{ + return 0; +} + +int +STDCALL +GetDlgCtrlID( + HWND hwndCtl) +{ + return 0; +} + +HWND +STDCALL +GetDlgItem( + HWND hDlg, + int nIDDlgItem) +{ + return (HWND)0; +} + +UINT +STDCALL +GetDlgItemInt( + HWND hDlg, + int nIDDlgItem, + WINBOOL *lpTranslated, + WINBOOL bSigned) +{ + return 0; +} + +UINT +STDCALL +GetDlgItemTextA( + HWND hDlg, + int nIDDlgItem, + LPSTR lpString, + int nMaxCount) +{ + return 0; +} + +UINT +STDCALL +GetDlgItemTextW( + HWND hDlg, + int nIDDlgItem, + LPWSTR lpString, + int nMaxCount) +{ + return 0; +} +HWND +STDCALL +GetNextDlgGroupItem( + HWND hDlg, + HWND hCtl, + WINBOOL bPrevious) +{ + return (HWND)0; +} + +HWND +STDCALL +GetNextDlgTabItem( + HWND hDlg, + HWND hCtl, + WINBOOL bPrevious) +{ + return (HWND)0; +} +#if 0 +WINBOOL +STDCALL +IsDialogMessage( + HWND hDlg, + LPMSG lpMsg) +{ + return FALSE; +} +#endif + +WINBOOL +STDCALL +IsDialogMessageA( + HWND hDlg, + LPMSG lpMsg) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsDialogMessageW( + HWND hDlg, + LPMSG lpMsg) +{ + return FALSE; +} + +UINT +STDCALL +IsDlgButtonChecked( + HWND hDlg, + int nIDButton) +{ + return 0; +} +WINBOOL +STDCALL +MapDialogRect( + HWND hDlg, + LPRECT lpRect) +{ + return FALSE; +} +LRESULT +STDCALL +SendDlgItemMessageA( + HWND hDlg, + int nIDDlgItem, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} + +LRESULT +STDCALL +SendDlgItemMessageW( + HWND hDlg, + int nIDDlgItem, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} +WINBOOL +STDCALL +SetDlgItemInt( + HWND hDlg, + int nIDDlgItem, + UINT uValue, + WINBOOL bSigned) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetDlgItemTextA( + HWND hDlg, + int nIDDlgItem, + LPCSTR lpString) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetDlgItemTextW( + HWND hDlg, + int nIDDlgItem, + LPCWSTR lpString) +{ + return FALSE; +} +WINBOOL +STDCALL +CheckDlgButton( + HWND hDlg, + int nIDButton, + UINT uCheck) +{ + return FALSE; +} + diff --git a/lib/user32/windows/draw.c b/lib/user32/windows/draw.c new file mode 100644 index 0000000..806726f --- /dev/null +++ b/lib/user32/windows/draw.c @@ -0,0 +1,228 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* GLOBALS *******************************************************************/ + +#define COLOR_MAX (28) + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +GrayStringA( + HDC hDC, + HBRUSH hBrush, + GRAYSTRINGPROC lpOutputFunc, + LPARAM lpData, + int nCount, + int X, + int Y, + int nWidth, + int nHeight) +{ + return FALSE; +} + +WINBOOL +STDCALL +GrayStringW( + HDC hDC, + HBRUSH hBrush, + GRAYSTRINGPROC lpOutputFunc, + LPARAM lpData, + int nCount, + int X, + int Y, + int nWidth, + int nHeight) +{ + return FALSE; +} +WINBOOL +STDCALL +InvertRect( + HDC hDC, + CONST RECT *lprc) +{ + return FALSE; +} +LONG +STDCALL +TabbedTextOutA( + HDC hDC, + int X, + int Y, + LPCSTR lpString, + int nCount, + int nTabPositions, + CONST LPINT lpnTabStopPositions, + int nTabOrigin) +{ + return 0; +} + +LONG +STDCALL +TabbedTextOutW( + HDC hDC, + int X, + int Y, + LPCWSTR lpString, + int nCount, + int nTabPositions, + CONST LPINT lpnTabStopPositions, + int nTabOrigin) +{ + return 0; +} +int +STDCALL +FrameRect( + HDC hDC, + CONST RECT *lprc, + HBRUSH hbr) +{ + return 0; +} +WINBOOL +STDCALL +FlashWindow( + HWND hWnd, + WINBOOL bInvert) +{ + return FALSE; +} + +WINBOOL +STDCALL +FlashWindowEx( + PFLASHWINFO pfwi) +{ + return FALSE; +} + +int STDCALL +FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr) +{ + HBRUSH prevhbr; + /*if (hbr <= (HBRUSH)(COLOR_MAX + 1)) + { + hbr = GetSysColorBrush((INT)hbr - 1); + }*/ + if ((prevhbr = SelectObject(hDC, hbr)) == NULL) + { + return(FALSE); + } + PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, + lprc->bottom - lprc->top, PATCOPY); + SelectObject(hDC, prevhbr); + return(TRUE); +} + +WINBOOL +STDCALL +DrawAnimatedRects( + HWND hwnd, + int idAni, + CONST RECT *lprcFrom, + CONST RECT *lprcTo) +{ + return FALSE; +} + +WINBOOL +STDCALL +DrawCaption( + HWND hwnd, + HDC hdc, + LPRECT lprc, + UINT uFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +DrawEdge( + HDC hdc, + LPRECT qrc, + UINT edge, + UINT grfFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +DrawFocusRect( + HDC hDC, + CONST RECT *lprc) +{ + return FALSE; +} + + +WINBOOL +STDCALL +DrawStateA( + HDC hdc, + HBRUSH hbr, + DRAWSTATEPROC lpOutputFunc, + LPARAM lData, + WPARAM wData, + int x, + int y, + int cx, + int cy, + UINT fuFlags) +{ + return FALSE; +} + +WINBOOL +STDCALL +DrawStateW( + HDC hdc, + HBRUSH hbr, + DRAWSTATEPROC lpOutputFunc, + LPARAM lData, + WPARAM wData, + int x, + int y, + int cx, + int cy, + UINT fuFlags) +{ + return FALSE; +} diff --git a/lib/user32/windows/font.c b/lib/user32/windows/font.c new file mode 100644 index 0000000..0263e03 --- /dev/null +++ b/lib/user32/windows/font.c @@ -0,0 +1,108 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +DWORD +STDCALL +GetTabbedTextExtentA( + HDC hDC, + LPCSTR lpString, + int nCount, + int nTabPositions, + CONST LPINT lpnTabStopPositions) +{ + return 0; +} + +DWORD +STDCALL +GetTabbedTextExtentW( + HDC hDC, + LPCWSTR lpString, + int nCount, + int nTabPositions, + CONST LPINT lpnTabStopPositions) +{ + return 0; +} +int +STDCALL +DrawTextA( + HDC hDC, + LPCSTR lpString, + int nCount, + LPRECT lpRect, + UINT uFormat) +{ + return 0; +} + +int +STDCALL +DrawTextExA( + HDC hdc, + LPSTR lpchText, + int cchText, + LPRECT lprc, + UINT dwDTFormat, + LPDRAWTEXTPARAMS lpDTParams) +{ + return 0; +} + +int +STDCALL +DrawTextExW( + HDC hdc, + LPWSTR lpchText, + int cchText, + LPRECT lprc, + UINT dwDTFormat, + LPDRAWTEXTPARAMS lpDTParams) +{ + return 0; +} + +int +STDCALL +DrawTextW( + HDC hDC, + LPCWSTR lpString, + int nCount, + LPRECT lpRect, + UINT uFormat) +{ + return 0; +} diff --git a/lib/user32/windows/hook.c b/lib/user32/windows/hook.c new file mode 100644 index 0000000..f0a57d7 --- /dev/null +++ b/lib/user32/windows/hook.c @@ -0,0 +1,82 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL +STDCALL +UnhookWindowsHookEx( + HHOOK hhk) +{ + return FALSE; +} +#if 0 +WINBOOL +STDCALL +CallMsgFilter( + LPMSG lpMsg, + int nCode) +{ + return FALSE; +} +#endif + +WINBOOL +STDCALL +CallMsgFilterA( + LPMSG lpMsg, + int nCode) +{ + return FALSE; +} + +WINBOOL +STDCALL +CallMsgFilterW( + LPMSG lpMsg, + int nCode) +{ + return FALSE; +} + +LRESULT +STDCALL +CallNextHookEx( + HHOOK hhk, + int nCode, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} diff --git a/lib/user32/windows/icon.c b/lib/user32/windows/icon.c new file mode 100644 index 0000000..14ed6f8 --- /dev/null +++ b/lib/user32/windows/icon.c @@ -0,0 +1,167 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HICON +STDCALL +CopyIcon( + HICON hIcon) +{ + return (HICON)0; +} +HICON +STDCALL +CreateIcon( + HINSTANCE hInstance, + int nWidth, + int nHeight, + BYTE cPlanes, + BYTE cBitsPixel, + CONST BYTE *lpbANDbits, + CONST BYTE *lpbXORbits) +{ + return (HICON)0; +} + +HICON +STDCALL +CreateIconFromResource( + PBYTE presbits, + DWORD dwResSize, + WINBOOL fIcon, + DWORD dwVer) +{ + return (HICON)0; +} + +HICON +STDCALL +CreateIconFromResourceEx( + PBYTE pbIconBits, + DWORD cbIconBits, + WINBOOL fIcon, + DWORD dwVersion, + int cxDesired, + int cyDesired, + UINT uFlags) +{ + return (HICON)0; +} + +HICON +STDCALL +CreateIconIndirect( + PICONINFO piconinfo) +{ + return (HICON)0; +} +WINBOOL +STDCALL +DestroyIcon( + HICON hIcon) +{ + return FALSE; +} +WINBOOL +STDCALL +DrawIcon( + HDC hDC, + int X, + int Y, + HICON hIcon) +{ + return FALSE; +} + +WINBOOL +STDCALL +DrawIconEx( + HDC hdc, + int xLeft, + int yTop, + HICON hIcon, + int cxWidth, + int cyWidth, + UINT istepIfAniCur, + HBRUSH hbrFlickerFreeDraw, + UINT diFlags) +{ + return FALSE; +} +WINBOOL +STDCALL +GetIconInfo( + HICON hIcon, + PICONINFO piconinfo) +{ + return FALSE; +} +HICON +STDCALL +LoadIconA( + HINSTANCE hInstance, + LPCSTR lpIconName) +{ + return (HICON)0; +} + +HICON +STDCALL +LoadIconW( + HINSTANCE hInstance, + LPCWSTR lpIconName) +{ + return (HICON)0; +} +int +STDCALL +LookupIconIdFromDirectory( + PBYTE presbits, + WINBOOL fIcon) +{ + return 0; +} + +int +STDCALL +LookupIconIdFromDirectoryEx( + PBYTE presbits, + WINBOOL fIcon, + int cxDesired, + int cyDesired, + UINT Flags) +{ + return 0; +} diff --git a/lib/user32/windows/input.c b/lib/user32/windows/input.c new file mode 100644 index 0000000..29a16b6 --- /dev/null +++ b/lib/user32/windows/input.c @@ -0,0 +1,279 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HKL STDCALL +ActivateKeyboardLayout(HKL hkl, + UINT Flags) +{ + return (HKL)0; +} + +WINBOOL STDCALL +BlockInput(WINBOOL fBlockIt) +{ + return FALSE; +} + +WINBOOL STDCALL +EnableWindow(HWND hWnd, + WINBOOL bEnable) +{ + return FALSE; +} + +SHORT STDCALL +GetAsyncKeyState(int vKey) +{ + return 0; +} + +HKL STDCALL +GetKeyboardLayout(DWORD idThread) +{ + return (HKL)0; +} + +WINBOOL STDCALL GetInputState(VOID) +{ + return FALSE; +} + +UINT STDCALL +GetKBCodePage(VOID) +{ + return 0; +} + +int STDCALL +GetKeyNameTextA(LONG lParam, + LPSTR lpString, + int nSize) +{ + return 0; +} + +int STDCALL +GetKeyNameTextW(LONG lParam, + LPWSTR lpString, + int nSize) +{ + return 0; +} + +SHORT STDCALL +GetKeyState(int nVirtKey) +{ + return 0; +} + +UINT STDCALL +GetKeyboardLayoutList(int nBuff, + HKL FAR *lpList) +{ + return 0; +} + +WINBOOL STDCALL +GetKeyboardLayoutNameA(LPSTR pwszKLID) +{ + return FALSE; +} + +WINBOOL STDCALL +GetKeyboardLayoutNameW(LPWSTR pwszKLID) +{ + return FALSE; +} + +WINBOOL STDCALL +GetKeyboardState(PBYTE lpKeyState) +{ + return FALSE; +} + +int STDCALL +GetKeyboardType(int nTypeFlag) +{ + return 0; +} + +WINBOOL STDCALL +GetLastInputInfo(PLASTINPUTINFO plii) +{ + return FALSE; +} + +HKL STDCALL +LoadKeyboardLayoutA(LPCSTR pwszKLID, + UINT Flags) +{ + return (HKL)0; +} + +HKL STDCALL +LoadKeyboardLayoutW(LPCWSTR pwszKLID, + UINT Flags) +{ + return (HKL)0; +} + +UINT STDCALL +MapVirtualKeyA(UINT uCode, + UINT uMapType) +{ + return 0; +} + +UINT STDCALL +MapVirtualKeyExA(UINT uCode, + UINT uMapType, + HKL dwhkl) +{ + return 0; +} + +UINT STDCALL +MapVirtualKeyExW(UINT uCode, + UINT uMapType, + HKL dwhkl) +{ + return 0; +} + +UINT STDCALL +MapVirtualKeyW(UINT uCode, + UINT uMapType) +{ + return 0; +} + +DWORD STDCALL +OemKeyScan(WORD wOemChar) +{ + return 0; +} + +WINBOOL STDCALL +SetKeyboardState(LPBYTE lpKeyState) +{ + return FALSE; +} + +int STDCALL +ToAscii(UINT uVirtKey, + UINT uScanCode, + CONST PBYTE lpKeyState, + LPWORD lpChar, + UINT uFlags) +{ + return 0; +} + +int STDCALL +ToAsciiEx(UINT uVirtKey, + UINT uScanCode, + CONST PBYTE lpKeyState, + LPWORD lpChar, + UINT uFlags, + HKL dwhkl) +{ + return 0; +} + +int STDCALL +ToUnicode(UINT wVirtKey, + UINT wScanCode, + CONST PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags) +{ + return 0; +} + +int STDCALL +ToUnicodeEx(UINT wVirtKey, + UINT wScanCode, + CONST PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags, + HKL dwhkl) +{ + return 0; +} + +WINBOOL STDCALL +UnloadKeyboardLayout(HKL hkl) +{ + return FALSE; +} + +SHORT STDCALL +VkKeyScanA(CHAR ch) +{ + return 0; +} + +SHORT STDCALL +VkKeyScanExA(CHAR ch, + HKL dwhkl) +{ + return 0; +} + +SHORT STDCALL +VkKeyScanExW(WCHAR ch, + HKL dwhkl) +{ + return 0; +} + +SHORT STDCALL +VkKeyScanW(WCHAR ch) +{ + return 0; +} + +UINT +STDCALL +SendInput( + UINT nInputs, + LPINPUT pInputs, + int cbSize) +{ + return 0; +} diff --git a/lib/user32/windows/mdi.c b/lib/user32/windows/mdi.c new file mode 100644 index 0000000..1638f79 --- /dev/null +++ b/lib/user32/windows/mdi.c @@ -0,0 +1,98 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HWND +STDCALL +CreateMDIWindowA( + LPCSTR lpClassName, + LPCSTR lpWindowName, + DWORD dwStyle, + int X, + int Y, + int nWidth, + int nHeight, + HWND hWndParent, + HINSTANCE hInstance, + LPARAM lParam) +{ + return (HWND)0; +} + +HWND +STDCALL +CreateMDIWindowW( + LPCWSTR lpClassName, + LPCWSTR lpWindowName, + DWORD dwStyle, + int X, + int Y, + int nWidth, + int nHeight, + HWND hWndParent, + HINSTANCE hInstance, + LPARAM lParam) +{ + return (HWND)0; +} +LRESULT +STDCALL +DefMDIChildProcA( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} + +LRESULT +STDCALL +DefMDIChildProcW( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + return (LRESULT)0; +} +WINBOOL +STDCALL +TranslateMDISysAccel( + HWND hWndClient, + LPMSG lpMsg) +{ + return FALSE; +} diff --git a/lib/user32/windows/menu.c b/lib/user32/windows/menu.c new file mode 100644 index 0000000..586d827 --- /dev/null +++ b/lib/user32/windows/menu.c @@ -0,0 +1,583 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/menu.c + * PURPOSE: Menus + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* TYPES *********************************************************************/ + +typedef struct _MENUITEM +{ + UINT Type; + UINT State; + UINT Id; + HMENU SubMenu; + HBITMAP CheckBit; + HBITMAP UnCheckBit; + LPWSTR Text; + DWORD ItemData; + DWORD TypeData; + HBITMAP BmpItem; + RECT Rect; + UINT XTab; +} MENUITEM, *PMENUITEM; + +typedef struct _POPUP_MENU +{ + MENUITEM* Items; + WORD NrItems; +} POPUP_MENU, *PPOPUP_MENU; + +/* FUNCTIONS *****************************************************************/ + +static PPOPUP_MENU +MenuGetMenu(HMENU hMenu) +{ + PPOPUP_MENU Menu; + Menu = (PPOPUP_MENU)hMenu; + return(Menu); +} + +static MENUITEM* +MenuFindItem(HMENU* hMenu, UINT* nPos, UINT wFlags) +{ + POPUP_MENU* Menu; + ULONG i; + + if ((ULONG)(*hMenu) == 0xFFFF || (Menu = MenuGetMenu(*hMenu)) == NULL) + { + return(NULL); + } + if (wFlags & MF_BYPOSITION) + { + if ((*nPos) >= Menu->NrItems) + { + return(NULL); + } + return(&Menu->Items[*nPos]); + } + else + { + MENUITEM* Item = Menu->Items; + for (i = 0; i < Menu->NrItems; i++) + { + if (Item->Id == (*nPos)) + { + *nPos = i; + return(Item); + } + else if (Item->Type & MF_POPUP) + { + HMENU SubMenu = Item->SubMenu; + MENUITEM* SubItem = MenuFindItem(&SubMenu, nPos, wFlags); + if (SubItem) + { + *hMenu = SubMenu; + return(SubItem); + } + } + } + } + return(NULL); +} + +WINBOOL STDCALL +AppendMenuA(HMENU hMenu, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCSTR lpNewItem) +{ + DPRINT("AppendMenuA(hMenu 0x%X, uFlags 0x%X, uIDNewItem %d, " + "lpNewItem %s\n", hMenu, uFlags, uIDNewItem, lpNewItem); + return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, + lpNewItem)); +} + +WINBOOL STDCALL +AppendMenuW(HMENU hMenu, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCWSTR lpNewItem) +{ + DPRINT("AppendMenuW(hMenu 0x%X, uFlags 0x%X, uIDNewItem %d, " + "lpNewItem %S\n", hMenu, uFlags, uIDNewItem, lpNewItem); + return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, + lpNewItem)); +} + +DWORD STDCALL +CheckMenuItem(HMENU hmenu, + UINT uIDCheckItem, + UINT uCheck) +{ + MENUITEM* Item; + DWORD Ret; + + DPRINT("CheckMenuItem(hmenu 0x%X, uIDCheckItem %d, uCheck %d", + hmenu, uIDCheckItem, uCheck); + if ((Item = MenuFindItem(&hmenu, &uIDCheckItem, uCheck)) == NULL) + { + return(-1); + } + Ret = Item->State & MF_CHECKED; + if (uCheck & MF_CHECKED) + { + Item->State |= MF_CHECKED; + } + else + { + Item->State &= ~MF_CHECKED; + } + return(Ret); +} + +WINBOOL +STDCALL +CheckMenuRadioItem( + HMENU hmenu, + UINT idFirst, + UINT idLast, + UINT idCheck, + UINT uFlags) +{ + return FALSE; +} +HMENU +STDCALL +CreateMenu(VOID) +{ + return (HMENU)0; +} + +HMENU +STDCALL +CreatePopupMenu(VOID) +{ + return (HMENU)0; +} +WINBOOL +STDCALL +DeleteMenu( + HMENU hMenu, + UINT uPosition, + UINT uFlags) +{ + return FALSE; +} +WINBOOL +STDCALL +DestroyMenu( + HMENU hMenu) +{ + return FALSE; +} +WINBOOL +STDCALL +DrawMenuBar( + HWND hWnd) +{ + return FALSE; +} +WINBOOL +STDCALL +EnableMenuItem( + HMENU hMenu, + UINT uIDEnableItem, + UINT uEnable) +{ + return FALSE; +} +WINBOOL +STDCALL +EndMenu(VOID) +{ + return FALSE; +} +HMENU +STDCALL +GetMenu( + HWND hWnd) +{ + return (HMENU)0; +} + +WINBOOL +STDCALL +GetMenuBarInfo( + HWND hwnd, + LONG idObject, + LONG idItem, + PMENUBARINFO pmbi) +{ + return FALSE; +} + +LONG +STDCALL +GetMenuCheckMarkDimensions(VOID) +{ + return 0; +} + +UINT +STDCALL +GetMenuDefaultItem( + HMENU hMenu, + UINT fByPos, + UINT gmdiFlags) +{ + return 0; +} + +WINBOOL +STDCALL +GetMenuInfo( + HMENU hmenu, + LPCMENUINFO lpcmi) +{ + return FALSE; +} + +int +STDCALL +GetMenuItemCount( + HMENU hMenu) +{ + return 0; +} + +UINT +STDCALL +GetMenuItemID( + HMENU hMenu, + int nPos) +{ + return 0; +} + +WINBOOL +STDCALL +GetMenuItemInfoA( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPMENUITEMINFO lpmii) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetMenuItemInfoW( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPMENUITEMINFO lpmii) +{ + return FALSE; +} + +WINBOOL +STDCALL +GetMenuItemRect( + HWND hWnd, + HMENU hMenu, + UINT uItem, + LPRECT lprcItem) +{ + return FALSE; +} + +UINT +STDCALL +GetMenuState( + HMENU hMenu, + UINT uId, + UINT uFlags) +{ + return 0; +} + +int +STDCALL +GetMenuStringA( + HMENU hMenu, + UINT uIDItem, + LPSTR lpString, + int nMaxCount, + UINT uFlag) +{ + return 0; +} + +int +STDCALL +GetMenuStringW( + HMENU hMenu, + UINT uIDItem, + LPWSTR lpString, + int nMaxCount, + UINT uFlag) +{ + return 0; +} +HMENU +STDCALL +GetSubMenu( + HMENU hMenu, + int nPos) +{ + return (HMENU)0; +} +WINBOOL +STDCALL +HiliteMenuItem( + HWND hwnd, + HMENU hmenu, + UINT uItemHilite, + UINT uHilite) +{ + return FALSE; +} +WINBOOL +STDCALL +InsertMenuA( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCSTR lpNewItem) +{ + return FALSE; +} + +WINBOOL +STDCALL +InsertMenuItemA( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPCMENUITEMINFO lpmii) +{ + return FALSE; +} + +WINBOOL +STDCALL +InsertMenuItemW( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPCMENUITEMINFO lpmii) +{ + return FALSE; +} + +WINBOOL +STDCALL +InsertMenuW( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCWSTR lpNewItem) +{ + return FALSE; +} +WINBOOL +STDCALL +IsMenu( + HMENU hMenu) +{ + return FALSE; +} +HMENU +STDCALL +LoadMenuA( + HINSTANCE hInstance, + LPCSTR lpMenuName) +{ + return (HMENU)0; +} + +HMENU +STDCALL +LoadMenuIndirectA( + CONST MENUTEMPLATE *lpMenuTemplate) +{ + return (HMENU)0; +} + +HMENU +STDCALL +LoadMenuIndirectW( + CONST MENUTEMPLATE *lpMenuTemplate) +{ + return (HMENU)0; +} + +HMENU +STDCALL +LoadMenuW( + HINSTANCE hInstance, + LPCWSTR lpMenuName) +{ + return (HMENU)0; +} +int +STDCALL +MenuItemFromPoint( + HWND hWnd, + HMENU hMenu, + POINT ptScreen) +{ + return 0; +} +WINBOOL +STDCALL +ModifyMenuA( + HMENU hMnu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCSTR lpNewItem) +{ + return FALSE; +} + +WINBOOL +STDCALL +ModifyMenuW( + HMENU hMnu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCWSTR lpNewItem) +{ + return FALSE; +} +WINBOOL +STDCALL +RemoveMenu( + HMENU hMenu, + UINT uPosition, + UINT uFlags) +{ + return FALSE; +} +WINBOOL +STDCALL +SetMenu( + HWND hWnd, + HMENU hMenu) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetMenuDefaultItem( + HMENU hMenu, + UINT uItem, + UINT fByPos) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetMenuInfo( + HMENU hmenu, + LPCMENUINFO lpcmi) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetMenuItemBitmaps( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + HBITMAP hBitmapUnchecked, + HBITMAP hBitmapChecked) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetMenuItemInfoA( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPMENUITEMINFO lpmii) +{ + return FALSE; +} + +WINBOOL +STDCALL +SetMenuItemInfoW( + HMENU hMenu, + UINT uItem, + WINBOOL fByPosition, + LPMENUITEMINFO lpmii) +{ + return FALSE; +} + +WINBOOL +STDCALL +TrackPopupMenu( + HMENU hMenu, + UINT uFlags, + int x, + int y, + int nReserved, + HWND hWnd, + CONST RECT *prcRect) +{ + return FALSE; +} + +WINBOOL +STDCALL +TrackPopupMenuEx( + HMENU hmenu, + UINT fuFlags, + int x, + int y, + HWND hwnd, + LPTPMPARAMS lptpm) +{ + return FALSE; +} diff --git a/lib/user32/windows/message.c b/lib/user32/windows/message.c new file mode 100644 index 0000000..fe2a423 --- /dev/null +++ b/lib/user32/windows/message.c @@ -0,0 +1,497 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/message.c + * PURPOSE: Messages + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 06-06-2001 CSH Created + */ +#include +#include +#include +#include + +LPARAM +STDCALL +GetMessageExtraInfo(VOID) +{ + return (LPARAM)0; +} + +DWORD +STDCALL +GetMessagePos(VOID) +{ + return 0; +} + +LONG +STDCALL +GetMessageTime(VOID) +{ + return 0; +} +WINBOOL +STDCALL +InSendMessage(VOID) +{ + return FALSE; +} + +DWORD +STDCALL +InSendMessageEx( + LPVOID lpReserved) +{ + return 0; +} +WINBOOL +STDCALL +ReplyMessage( + LRESULT lResult) +{ + return FALSE; +} +LPARAM +STDCALL +SetMessageExtraInfo( + LPARAM lParam) +{ + return (LPARAM)0; +} + +VOID STATIC +User32FreeAsciiConvertedMessage(UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch(Msg) + { + case WM_GETTEXT: + { + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + LPSTR TempString; + LPSTR InString; + InString = (LPSTR)lParam; + TempString = RtlAllocateHeap(RtlGetProcessHeap(), 0, strlen(InString)); + strcpy(TempString, InString); + RtlInitAnsiString(&AnsiString, TempString); + UnicodeString.Length = wParam; + UnicodeString.MaximumLength = wParam; + UnicodeString.Buffer = (PWSTR)lParam; + RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); + RtlFreeHeap(RtlGetProcessHeap(), 0, TempString); + break; + } + case WM_NCCREATE: + { + CREATESTRUCTA* Cs; + + Cs = (CREATESTRUCTA*)lParam; + RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR)Cs->lpszName); + RtlFreeHeap(RtlGetProcessHeap(), 0, (LPSTR)Cs->lpszClass); + RtlFreeHeap(RtlGetProcessHeap(), 0, Cs); + break; + } + } +} + +VOID STATIC +User32ConvertToAsciiMessage(UINT* Msg, WPARAM* wParam, LPARAM* lParam) +{ + switch((*Msg)) + { + case WM_NCCREATE: + { + CREATESTRUCTA* CsA; + CREATESTRUCTW* CsW; + UNICODE_STRING UString; + ANSI_STRING AString; + + CsW = (CREATESTRUCTW*)(*lParam); + CsA = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(CREATESTRUCTA)); + memcpy(CsA, CsW, sizeof(CREATESTRUCTW)); + + RtlInitUnicodeString(&UString, CsW->lpszName); + RtlUnicodeStringToAnsiString(&AString, &UString, TRUE); + CsA->lpszName = AString.Buffer; + + RtlInitUnicodeString(&UString, CsW->lpszClass); + RtlUnicodeStringToAnsiString(&AString, &UString, TRUE); + CsA->lpszClass = AString.Buffer; + + (*lParam) = (LPARAM)CsA; + break; + } + } + return; +} + +VOID STATIC +User32FreeUnicodeConvertedMessage(UINT Msg, WPARAM wParam, LPARAM lParam) +{ +} + +VOID STATIC +User32ConvertToUnicodeMessage(UINT* Msg, WPARAM* wParam, LPARAM* lParam) +{ +} + +LRESULT STDCALL +CallWindowProcA(WNDPROC lpPrevWndFunc, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + if (IsWindowUnicode(hWnd)) + { + LRESULT Result; + User32ConvertToUnicodeMessage(&Msg, &wParam, &lParam); + Result = lpPrevWndFunc(hWnd, Msg, wParam, lParam); + User32FreeUnicodeConvertedMessage(Msg, wParam, lParam); + return(Result); + } + else + { + return(lpPrevWndFunc(hWnd, Msg, wParam, lParam)); + } +} + +LRESULT STDCALL +CallWindowProcW(WNDPROC lpPrevWndFunc, + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + if (!IsWindowUnicode(hWnd)) + { + LRESULT Result; + User32ConvertToAsciiMessage(&Msg, &wParam, &lParam); + Result = lpPrevWndFunc(hWnd, Msg, wParam, lParam); + User32FreeAsciiConvertedMessage(Msg, wParam, lParam); + return(Result); + } + else + { + return(lpPrevWndFunc(hWnd, Msg, wParam, lParam)); + } +} + + +BOOL +MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg) +{ + *UnicodeMsg = *AnsiMsg; + switch (AnsiMsg->message) + { + case WM_GETTEXT: + { + UnicodeMsg->wParam = UnicodeMsg->wParam / 2; + break; + } + } + return(TRUE); +} + +BOOL +MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT Result) +{ + switch (AnsiMsg->message) + { + case WM_GETTEXT: + { + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + LPWSTR TempString; + LPWSTR InString; + InString = (LPWSTR)UnicodeMsg->lParam; + TempString = RtlAllocateHeap(RtlGetProcessHeap(), 0, + wcslen(InString) * sizeof(WCHAR)); + wcscpy(TempString, InString); + RtlInitUnicodeString(&UnicodeString, TempString); + AnsiString.Length = AnsiMsg->wParam; + AnsiString.MaximumLength = AnsiMsg->wParam; + AnsiString.Buffer = (PSTR)AnsiMsg->lParam; + RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); + RtlFreeHeap(RtlGetProcessHeap(), 0, TempString); + break; + } + } + return(TRUE); +} + + +LRESULT STDCALL +DispatchMessageA(CONST MSG *lpmsg) +{ + return(NtUserDispatchMessage(lpmsg)); +} + +LRESULT STDCALL +DispatchMessageW(CONST MSG *lpmsg) +{ + return(NtUserDispatchMessage((LPMSG)lpmsg)); +} + +WINBOOL +STDCALL +GetMessageA( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax) +{ + return NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); +} + +WINBOOL +STDCALL +GetMessageW( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax) +{ + return NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); +} + +WINBOOL +STDCALL +PeekMessageA( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax, + UINT wRemoveMsg) +{ + return NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); +} + +WINBOOL +STDCALL +PeekMessageW( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax, + UINT wRemoveMsg) +{ + return NtUserPeekMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); +} + +WINBOOL +STDCALL +PostMessageA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return NtUserPostMessage(hWnd, Msg, wParam, lParam); +} + +WINBOOL +STDCALL +PostMessageW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return NtUserPostMessage(hWnd, Msg, wParam, lParam); +} + +VOID +STDCALL +PostQuitMessage( + int nExitCode) +{ +} + +WINBOOL +STDCALL +PostThreadMessageA( + DWORD idThread, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return NtUserPostThreadMessage(idThread, Msg, wParam, lParam); +} + +WINBOOL +STDCALL +PostThreadMessageW( + DWORD idThread, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return NtUserPostThreadMessage(idThread, Msg, wParam, lParam); +} + +LRESULT STDCALL +SendMessageW(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return(NtUserSendMessage(hWnd, Msg, wParam, lParam)); +} + + +LRESULT STDCALL +SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + MSG AnsiMsg; + MSG UcMsg; + LRESULT Result; + + AnsiMsg.hwnd = hWnd; + AnsiMsg.message = Msg; + AnsiMsg.wParam = wParam; + AnsiMsg.lParam = lParam; + + if (!MsgiAnsiToUnicodeMessage(&UcMsg, &AnsiMsg)) + { + return(FALSE); + } + Result = SendMessageW(UcMsg.hwnd, UcMsg.message, UcMsg.wParam, UcMsg.lParam); + if (!MsgiAnsiToUnicodeReply(&UcMsg, &AnsiMsg, Result)) + { + return(FALSE); + } + return(Result); +} + +WINBOOL +STDCALL +SendMessageCallbackA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC lpCallBack, + ULONG_PTR dwData) +{ + return NtUserSendMessageCallback( + hWnd, + Msg, + wParam, + lParam, + lpCallBack, + dwData); +} + +WINBOOL +STDCALL +SendMessageCallbackW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC lpCallBack, + ULONG_PTR dwData) +{ + return NtUserSendMessageCallback( + hWnd, + Msg, + wParam, + lParam, + lpCallBack, + dwData); +} + +LRESULT +STDCALL +SendMessageTimeoutA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + UINT fuFlags, + UINT uTimeout, + PDWORD_PTR lpdwResult) +{ + return (LRESULT)0; +} + +LRESULT +STDCALL +SendMessageTimeoutW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + UINT fuFlags, + UINT uTimeout, + PDWORD_PTR lpdwResult) +{ + return (LRESULT)0; +} + + + +WINBOOL +STDCALL +SendNotifyMessageA( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL +STDCALL +SendNotifyMessageW( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL STDCALL +TranslateMessage(CONST MSG *lpMsg) +{ + return(NtUserTranslateMessage((LPMSG)lpMsg, 0)); +} + +WINBOOL +STDCALL +WaitMessage(VOID) +{ + return FALSE; +} + +UINT STDCALL +RegisterWindowMessageA(LPCSTR lpString) +{ + UNICODE_STRING String; + BOOLEAN Result; + UINT Atom; + + Result = RtlCreateUnicodeStringFromAsciiz(&String, (PCSZ)lpString); + if (!Result) + { + return(0); + } + Atom = RegisterWindowMessageW(String.Buffer); + RtlFreeUnicodeString(&String); + return(Atom); +} + +UINT STDCALL +RegisterWindowMessageW(LPCWSTR lpString) +{ + return(NtUserRegisterWindowMessage(lpString)); +} + + +/* EOF */ diff --git a/lib/user32/windows/messagebox.c b/lib/user32/windows/messagebox.c new file mode 100644 index 0000000..24d1b87 --- /dev/null +++ b/lib/user32/windows/messagebox.c @@ -0,0 +1,97 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +int +STDCALL +MessageBoxA( + HWND hWnd, + LPCSTR lpText, + LPCSTR lpCaption, + UINT uType) +{ + return 0; +} + +int +STDCALL +MessageBoxExA( + HWND hWnd, + LPCSTR lpText, + LPCSTR lpCaption, + UINT uType, + WORD wLanguageId) +{ + return 0; +} + +int +STDCALL +MessageBoxExW( + HWND hWnd, + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType, + WORD wLanguageId) +{ + return 0; +} + +int +STDCALL +MessageBoxIndirectA( + CONST LPMSGBOXPARAMS lpMsgBoxParams) +{ + return 0; +} + +int +STDCALL +MessageBoxIndirectW( + CONST LPMSGBOXPARAMS lpMsgBoxParams) +{ + return 0; +} + +int +STDCALL +MessageBoxW( + HWND hWnd, + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType) +{ + return 0; +} diff --git a/lib/user32/windows/nonclient.c b/lib/user32/windows/nonclient.c new file mode 100644 index 0000000..1fd92ee --- /dev/null +++ b/lib/user32/windows/nonclient.c @@ -0,0 +1,478 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#if 0 +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* DEFINES ******************************************************************/ + +#define HAS_DLGFRAME(style,exStyle) \ + (((exStyle) & WS_EX_DLGMODALFRAME) || \ + (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME))) + +#define HAS_THICKFRAME(style,exStyle) \ + (((style) & WS_THICKFRAME) && \ + !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME)) + +#define HAS_THINFRAME(style) \ + (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP))) + +#define HAS_BIGFRAME(style,exStyle) \ + (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \ + ((exStyle) & WS_EX_DLGMODALFRAME)) + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +DrawFrameControl(HDC hDc, LPRECT Rect, UINT Type, UINT State) +{ +} + +/* Get the 'inside' rectangle of a window, i.e. the whole window rectangle + * but without the borders (if any). + * The rectangle is in window coordinates (for drawing with GetWindowDC()). + */ +void NC_GetInsideRect( HWND hwnd, RECT *rect ) +{ + DWORD Style, ExStyle; + + GetWindowRect(hwnd, rect); + Style = GetWindowLong(hwnd, GWL_STYLE); + ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + + rect->top = rect->left = 0; + rect->right = rect->right - rect->left; + rect->bottom = rect->bottom - rect->top; + +/* if (wndPtr->dwStyle & WS_ICONIC) goto END; */ + + /* Remove frame from rectangle */ + if (HAS_THICKFRAME(Style, ExStyle )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) ); + } + else if (HAS_DLGFRAME(Style, ExStyle )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME)); + } + else if (HAS_THINFRAME( Style )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) ); + } + + /* We have additional border information if the window + * is a child (but not an MDI child) */ + if ( (Style & WS_CHILD) && + ( (ExStyle & WS_EX_MDICHILD) == 0 ) ) + { + if (ExStyle & WS_EX_CLIENTEDGE) + InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE)); + if (ExStyle & WS_EX_STATICEDGE) + InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER)); + } + +END: + return; +} + +/* Draws the Win95 system icon. */ +BOOL +NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down) +{ + HICON hIcon = NC_IconForWindow( hwnd ); + + if (hIcon) + { + RECT rect; + NC_GetInsideRect( hwnd, &rect ); + DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL); + } + return (hIcon != 0); +} + +/* Draws the Win95 close button. */ +static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed) +{ + RECT rect; + + NC_GetInsideRect( hwnd, &rect ); + + /* A tool window has a smaller Close button */ + if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW) + { + INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */ + INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */ + INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION); + + rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2; + rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2; + rect.bottom = rect.top + iBmpHeight; + rect.right = rect.left + iBmpWidth; + } + else + { + rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1; + rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1; + rect.top += 2; + rect.right -= 2; + } + DrawFrameControl( hdc, &rect, DFC_CAPTION, + (DFCS_CAPTIONCLOSE | + (down ? DFCS_PUSHED : 0) | + (bGrayed ? DFCS_INACTIVE : 0)) ); +} + +/* Draws the maximize button for Win95 style windows. */ +static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed) +{ + RECT rect; + UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX; + + NC_GetInsideRect( hwnd, &rect ); + if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU) + rect.right -= GetSystemMetrics(SM_CXSIZE) + 1; + rect.left = rect.right - GetSystemMetrics(SM_CXSIZE); + rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1; + rect.top += 2; + rect.right -= 2; + if (down) flags |= DFCS_PUSHED; + if (bGrayed) flags |= DFCS_INACTIVE; + DrawFrameControl( hdc, &rect, DFC_CAPTION, flags ); +} + +/* Draws the minimize button for Win95 style windows. */ +static void NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed) +{ + RECT rect; + UINT flags = DFCS_CAPTIONMIN; + DWORD style = GetWindowLongA( hwnd, GWL_STYLE ); + + NC_GetInsideRect( hwnd, &rect ); + if (style & WS_SYSMENU) + rect.right -= GetSystemMetrics(SM_CXSIZE) + 1; + if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX)) + rect.right -= GetSystemMetrics(SM_CXSIZE) - 2; + rect.left = rect.right - GetSystemMetrics(SM_CXSIZE); + rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1; + rect.top += 2; + rect.right -= 2; + if (down) flags |= DFCS_PUSHED; + if (bGrayed) flags |= DFCS_INACTIVE; + DrawFrameControl( hdc, &rect, DFC_CAPTION, flags ); +} + +/* Draw a window frame inside the given rectangle, and update the rectangle. */ +static void NC_DrawFrame95( + HDC hdc, + RECT *rect, + BOOL active, + DWORD style, + DWORD exStyle) +{ + INT width, height; + + /* Firstly the "thick" frame */ + if (style & WS_THICKFRAME) + { + width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); + height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME); + +/* SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER : + COLOR_INACTIVEBORDER) ); */ + /* Draw frame */ + PatBlt( hdc, rect->left, rect->top, + rect->right - rect->left, height, PATCOPY ); + PatBlt( hdc, rect->left, rect->top, + width, rect->bottom - rect->top, PATCOPY ); + PatBlt( hdc, rect->left, rect->bottom - 1, + rect->right - rect->left, -height, PATCOPY ); + PatBlt( hdc, rect->right - 1, rect->top, + -width, rect->bottom - rect->top, PATCOPY ); + + InflateRect( rect, -width, -height ); + } + + /* Now the other bit of the frame */ + if ((style & (WS_BORDER|WS_DLGFRAME)) || + (exStyle & WS_EX_DLGMODALFRAME)) + { + width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE); + height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE); + /* This should give a value of 1 that should also work for a border */ + +/* SelectObject( hdc, GetSysColorBrush( + (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ? + COLOR_3DFACE : + (exStyle & WS_EX_STATICEDGE) ? + COLOR_WINDOWFRAME : + (style & (WS_DLGFRAME|WS_THICKFRAME)) ? + COLOR_3DFACE : + // else + COLOR_WINDOWFRAME)); */ + + /* Draw frame */ + PatBlt( hdc, rect->left, rect->top, + rect->right - rect->left, height, PATCOPY ); + PatBlt( hdc, rect->left, rect->top, + width, rect->bottom - rect->top, PATCOPY ); + PatBlt( hdc, rect->left, rect->bottom - 1, + rect->right - rect->left, -height, PATCOPY ); + PatBlt( hdc, rect->right - 1, rect->top, + -width, rect->bottom - rect->top, PATCOPY ); + + InflateRect( rect, -width, -height ); + } +} + +static HICON NC_IconForWindow( HWND hwnd ) +{ + HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM ); + if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON ); + + /* If there is no hIcon specified and this is a modal dialog, + * get the default one. + */ +/* if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME)) + hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); */ + return hIcon; +} + +/* Draw the window caption for Win95 style windows. The correct pen for the window frame must be selected in the DC. */ +static void NC_DrawCaption95( + HDC hdc, + RECT *rect, + HWND hwnd, + DWORD style, + DWORD exStyle, + BOOL active ) +{ + RECT r = *rect; + char buffer[256]; + HPEN hPrevPen; + HMENU hSysMenu; + +/* hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen( + ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE| + WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ? + COLOR_WINDOWFRAME : COLOR_3DFACE) ); */ + MoveToEx( hdc, r.left, r.bottom - 1, NULL ); + LineTo( hdc, r.right, r.bottom - 1 ); + SelectObject( hdc, hPrevPen ); + r.bottom--; + +/* FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : + COLOR_INACTIVECAPTION) ); */ + + if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) { + if (NC_DrawSysButton95 (hwnd, hdc, FALSE)) + r.left += GetSystemMetrics(SM_CYCAPTION) - 1; + } + + if (style & WS_SYSMENU) + { + UINT state; + + /* Go get the sysmenu */ + hSysMenu = GetSystemMenu(hwnd, FALSE); + state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); + + /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */ + NC_DrawCloseButton95 (hwnd, hdc, FALSE, + ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF))); + r.right -= GetSystemMetrics(SM_CYCAPTION) - 1; + + if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX)) + { + /* In win95 the two buttons are always there */ + /* But if the menu item is not in the menu they're disabled*/ + + NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX))); + r.right -= GetSystemMetrics(SM_CXSIZE) + 1; + + NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX))); + r.right -= GetSystemMetrics(SM_CXSIZE) + 1; + } + } + + if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) { + NONCLIENTMETRICS nclm; + HFONT hFont, hOldFont; + nclm.cbSize = sizeof(NONCLIENTMETRICS); + SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0); + if (exStyle & WS_EX_TOOLWINDOW) + hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont); + else + hFont = CreateFontIndirectA (&nclm.lfCaptionFont); + hOldFont = SelectObject (hdc, hFont); +/* if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) ); + else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ); */ + SetBkMode( hdc, TRANSPARENT ); + r.left += 2; + DrawTextA( hdc, buffer, -1, &r, + DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT ); + DeleteObject (SelectObject (hdc, hOldFont)); + } +} + +static void NC_DoNCPaint95( + HWND hwnd, + HRGN clip, + BOOL suppress_menupaint) +{ + HDC hdc; + RECT rfuzz, rect, rectClip; + BOOL active; + DWORD Style, ExStyle; + WORD Flags; + RECT ClientRect, WindowRect; + int has_menu; + + /* FIXME: Determine has_menu */ + Style = GetWindowLong(hwnd, GWL_STYLE); + ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + GetWindowRect(hwnd, &WindowRect); + GetClientRect(hwnd, &ClientRect); + +/* Flags = wndPtr->flags; */ + +/* if (Style & WS_MINIMIZE || + !WIN_IsWindowDrawable(hwnd, 0)) return; */ /* Nothing to do */ + + active = TRUE /* Flags & WIN_NCACTIVATED */; + + DPRINT("%04x %d\n", hwnd, active); + + /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in + the call to GetDCEx implying that it is allowed not to use it either. + However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN) + will cause clipRgn to be deleted after ReleaseDC(). + Now, how is the "system" supposed to tell what happened? + */ + + if (!(hdc = GetDCEx(hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW | + ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0)))) return; + + +/* if (ExcludeVisRect(hdc, ClientRect.left-WindowRect.left, + ClientRect.top-WindowRect.top, + ClientRect.right-WindowRect.left, + ClientRect.bottom-WindowRect.top) + == NULLREGION) + { + ReleaseDC(hwnd, hdc); + return; + } */ + + rect.top = rect.left = 0; + rect.right = WindowRect.right - WindowRect.left; + rect.bottom = WindowRect.bottom - WindowRect.top; + + if(clip > 1) + GetRgnBox(clip, &rectClip); + else + { + clip = 0; + rectClip = rect; + } + +/* SelectObject(hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME)); */ + +/* if (HAS_STATICOUTERFRAME(Style, ExStyle)) { + DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST); + } + else if (HAS_BIGFRAME(Style, ExStyle)) { + DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST); + } */ + + NC_DrawFrame95(hdc, &rect, active, Style, ExStyle); +/* + if ((Style & WS_CAPTION) == WS_CAPTION) + { + RECT r = rect; + if (ExStyle & WS_EX_TOOLWINDOW) { + r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION); + rect.top += GetSystemMetrics(SM_CYSMCAPTION); + } + else { + r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION); + rect.top += GetSystemMetrics(SM_CYCAPTION); + } + if(!clip || IntersectRect(&rfuzz, &r, &rectClip)) + NC_DrawCaption95 (hdc, &r, hwnd, Style, + ExStyle, active); + } +*/ +/* if (has_menu) + { + RECT r = rect; + r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); + + DPRINT("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n", + r.left, r.top, r.right, r.bottom); + + rect.top += MENU_DrawMenuBar(hdc, &r, hwnd, suppress_menupaint) + 1; + } +*/ + DPRINT("After MenuBar, rect is (%d, %d)-(%d, %d).\n", + rect.left, rect.top, rect.right, rect.bottom); + + if (ExStyle & WS_EX_CLIENTEDGE) + DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); + + /* Draw the scroll-bars */ +/* + if (Style & WS_VSCROLL) + SCROLL_DrawScrollBar(hwnd, hdc, SB_VERT, TRUE, TRUE); + if (Style & WS_HSCROLL) + SCROLL_DrawScrollBar(hwnd, hdc, SB_HORZ, TRUE, TRUE); +*/ + /* Draw the "size-box" */ + if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL)) + { + RECT r = rect; + r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1; + r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1; +/* FillRect(hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR)); */ + } + + ReleaseDC(hwnd, hdc); +} + +/* Handle a WM_NCPAINT message. Called from DefWindowProc(). */ +LONG NC_HandleNCPaint(HWND hwnd , HRGN clip) +{ + DWORD Style = GetWindowLongW(hwnd, GWL_STYLE); + + if(Style & WS_VISIBLE) + { +/* if(Style & WS_MINIMIZE) + WINPOS_RedrawIconTitle(hwnd); */ +/* else if (TWEAK_WineLook == WIN31_LOOK) + NC_DoNCPaint(hwnd, clip, FALSE); */ +/* else */ + NC_DoNCPaint95(hwnd, clip, FALSE); + } + return 0; +} +#endif diff --git a/lib/user32/windows/paint.c b/lib/user32/windows/paint.c new file mode 100644 index 0000000..b2df394 --- /dev/null +++ b/lib/user32/windows/paint.c @@ -0,0 +1,161 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +HDC +STDCALL +BeginPaint( + HWND hwnd, + LPPAINTSTRUCT lpPaint) +{ + return NtUserBeginPaint(hwnd, lpPaint); +} +WINBOOL +STDCALL +EndPaint( + HWND hWnd, + CONST PAINTSTRUCT *lpPaint) +{ + return NtUserEndPaint(hWnd, lpPaint); +} +int +STDCALL +ExcludeUpdateRgn( + HDC hDC, + HWND hWnd) +{ + return 0; +} +WINBOOL +STDCALL +GetUpdateRect( + HWND hWnd, + LPRECT lpRect, + WINBOOL bErase) +{ + return FALSE; +} + +int +STDCALL +GetUpdateRgn( + HWND hWnd, + HRGN hRgn, + WINBOOL bErase) +{ + return 0; +} +WINBOOL +STDCALL +InvalidateRect( + HWND hWnd, + CONST RECT *lpRect, + WINBOOL bErase) +{ + return FALSE; +} + +WINBOOL +STDCALL +InvalidateRgn( + HWND hWnd, + HRGN hRgn, + WINBOOL bErase) +{ + return FALSE; +} +WINBOOL +STDCALL +RedrawWindow( + HWND hWnd, + CONST RECT *lprcUpdate, + HRGN hrgnUpdate, + UINT flags) +{ + return FALSE; +} +WINBOOL +STDCALL +ScrollDC( + HDC hDC, + int dx, + int dy, + CONST RECT *lprcScroll, + CONST RECT *lprcClip, + HRGN hrgnUpdate, + LPRECT lprcUpdate) +{ + return FALSE; +} +int +STDCALL +SetWindowRgn( + HWND hWnd, + HRGN hRgn, + WINBOOL bRedraw) +{ + return 0; +} +WINBOOL +STDCALL +UpdateWindow( + HWND hWnd) +{ + return FALSE; +} +WINBOOL +STDCALL +ValidateRect( + HWND hWnd, + CONST RECT *lpRect) +{ + return FALSE; +} +WINBOOL +STDCALL +ValidateRgn( + HWND hWnd, + HRGN hRgn) +{ + return FALSE; +} +int +STDCALL +GetWindowRgn( + HWND hWnd, + HRGN hRgn) +{ + return 0; +} diff --git a/lib/user32/windows/prop.c b/lib/user32/windows/prop.c new file mode 100644 index 0000000..9de81de --- /dev/null +++ b/lib/user32/windows/prop.c @@ -0,0 +1,181 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + + +/* FUNCTIONS *****************************************************************/ + +int STDCALL +EnumPropsA(HWND hWnd, PROPENUMPROC lpEnumFunc) +{ + return 0; +} + +int STDCALL +EnumPropsExA(HWND hWnd, PROPENUMPROCEX lpEnumFunc, LPARAM lParam) +{ + return 0; +} + +int STDCALL +EnumPropsExW(HWND hWnd, PROPENUMPROCEX lpEnumFunc, LPARAM lParam) +{ + return 0; +} + +int STDCALL +EnumPropsW(HWND hWnd, PROPENUMPROC lpEnumFunc) +{ + return 0; +} + +HANDLE STDCALL +GetPropA(HWND hWnd, LPCSTR lpString) +{ + PWSTR lpWString; + UNICODE_STRING UString; + HANDLE Ret; + if (HIWORD(lpString)) + { + RtlCreateUnicodeStringFromAsciiz(&UString, (LPSTR)lpString); + lpWString = UString.Buffer; + if (lpWString == NULL) + { + return(FALSE); + } + Ret = GetPropW(hWnd, lpWString); + RtlFreeUnicodeString(&UString); + } + else + { + Ret = GetPropW(hWnd, (LPWSTR)lpString); + } + return(Ret); +} + +HANDLE STDCALL +GetPropW(HWND hWnd, LPCWSTR lpString) +{ + ATOM Atom; + if (HIWORD(lpString)) + { + Atom = GlobalFindAtomW(lpString); + } + else + { + Atom = LOWORD((DWORD)lpString); + } + return(NtUserGetProp(hWnd, Atom)); +} + +HANDLE STDCALL +RemovePropA(HWND hWnd, LPCSTR lpString) +{ + PWSTR lpWString; + UNICODE_STRING UString; + HANDLE Ret; + + if (HIWORD(lpString)) + { + RtlCreateUnicodeStringFromAsciiz(&UString, (LPSTR)lpString); + lpWString = UString.Buffer; + if (lpWString == NULL) + { + return(FALSE); + } + Ret = RemovePropW(hWnd, lpWString); + RtlFreeUnicodeString(&UString); + } + else + { + Ret = RemovePropW(hWnd, lpWString); + } + return(Ret); +} + +HANDLE STDCALL +RemovePropW(HWND hWnd, + LPCWSTR lpString) +{ + ATOM Atom; + if (HIWORD(lpString)) + { + Atom = GlobalFindAtomW(lpString); + } + else + { + Atom = LOWORD((DWORD)lpString); + } + return(NtUserRemoveProp(hWnd, Atom)); +} + +WINBOOL STDCALL +SetPropA(HWND hWnd, LPCSTR lpString, HANDLE hData) +{ + PWSTR lpWString; + UNICODE_STRING UString; + BOOL Ret; + + if (HIWORD(lpString)) + { + RtlCreateUnicodeStringFromAsciiz(&UString, (LPSTR)lpString); + lpWString = UString.Buffer; + if (lpWString == NULL) + { + return(FALSE); + } + Ret = SetPropW(hWnd, lpWString, hData); + RtlFreeUnicodeString(&UString); + } + else + { + Ret = SetPropW(hWnd, (LPWSTR)lpString, hData); + } + return(Ret); +} + +WINBOOL STDCALL +SetPropW(HWND hWnd, LPCWSTR lpString, HANDLE hData) +{ + ATOM Atom; + if (HIWORD(lpString)) + { + Atom = GlobalFindAtomW(lpString); + } + else + { + Atom = LOWORD((DWORD)lpString); + } + + return(NtUserSetProp(hWnd, Atom, hData)); +} diff --git a/lib/user32/windows/rect.c b/lib/user32/windows/rect.c new file mode 100644 index 0000000..4c99911 --- /dev/null +++ b/lib/user32/windows/rect.c @@ -0,0 +1,200 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +WINBOOL STDCALL +CopyRect(LPRECT lprcDst, CONST RECT *lprcSrc) +{ + if(lprcDst == NULL || lprcSrc == NULL) + return(FALSE); + + *lprcDst = *lprcSrc; + return(TRUE); +} + +WINBOOL +STDCALL +EqualRect( + CONST RECT *lprc1, + CONST RECT *lprc2) +{ + if ((lprc1->left == lprc2->left) + && (lprc1->top == lprc2->top) + && (lprc1->right == lprc2->right) + && (lprc1->bottom == lprc2->bottom)) + { + return TRUE; + } + /* TODO: return the correct error code. */ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +WINBOOL STDCALL +InflateRect(LPRECT rect, int dx, int dy) +{ + rect->left -= dx; + rect->top -= dy; + rect->right += dx; + rect->bottom += dy; + return(TRUE); +} + +WINBOOL STDCALL +IntersectRect(LPRECT lprcDst, + CONST RECT *lprcSrc1, + CONST RECT *lprcSrc2) +{ + if (IsRectEmpty(lprcSrc1) || IsRectEmpty(lprcSrc2) || + lprcSrc1->left >= lprcSrc2->right || + lprcSrc2->left >= lprcSrc1->right || + lprcSrc1->top >= lprcSrc2->bottom || + lprcSrc2->top >= lprcSrc1->bottom) + { + SetRectEmpty(lprcDst); + return(FALSE); + } + lprcDst->left = max(lprcSrc1->left, lprcSrc2->left); + lprcDst->right = min(lprcSrc1->right, lprcSrc2->right); + lprcDst->top = max(lprcSrc1->top, lprcSrc2->top); + lprcDst->bottom = min(lprcSrc1->bottom, lprcSrc2->bottom); + return(TRUE); +} + +WINBOOL STDCALL +IsRectEmpty(CONST RECT *lprc) +{ + return((lprc->left >= lprc->right) || (lprc->top >= lprc->bottom)); +} + +WINBOOL STDCALL +OffsetRect(LPRECT rect, int dx, int dy) +{ + if(rect == NULL) + return(FALSE); + + rect->left += dx; + rect->top += dy; + rect->right += dx; + rect->bottom += dy; + return(TRUE); +} + +WINBOOL STDCALL +PtInRect(CONST RECT *lprc, POINT pt) +{ + return((pt.x >= lprc->left) && (pt.x < lprc->right) && + (pt.y >= lprc->top) && (pt.y < lprc->bottom)); +} + +WINBOOL STDCALL +SetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom) +{ + lprc->left = xLeft; + lprc->top = yTop; + lprc->right = xRight; + lprc->bottom = yBottom; + return(TRUE); +} + +BOOL STDCALL +SetRectEmpty(LPRECT lprc) +{ + lprc->left = lprc->right = lprc->top = lprc->bottom = 0; + return(TRUE); +} + +WINBOOL STDCALL +SubtractRect(LPRECT lprcDst, CONST RECT *lprcSrc1, CONST RECT *lprcSrc2) +{ + RECT tempRect; + + if(lprcDst == NULL || lprcSrc1 == NULL || lprcSrc2 == NULL) + return(FALSE); + + CopyRect(lprcDst, lprcSrc1); + + if(!IntersectRect(&tempRect, lprcSrc1, lprcSrc2)) + return(FALSE); + + if(lprcDst->top == tempRect.top && lprcDst->bottom == tempRect.bottom) + { + if(lprcDst->left == tempRect.left) + lprcDst->left = tempRect.right; + else if(lprcDst->right == tempRect.right) + lprcDst->right = tempRect.left; + } + else if(lprcDst->left == tempRect.left && lprcDst->right == tempRect.right) + { + if(lprcDst->top == tempRect.top) + lprcDst->top = tempRect.bottom; + else if(lprcDst->right == tempRect.right) + lprcDst->right = tempRect.left; + } + + return(TRUE); +} + +WINBOOL STDCALL +UnionRect(LPRECT lprcDst, CONST RECT *lprcSrc1, CONST RECT *lprcSrc2) +{ + if (IsRectEmpty(lprcSrc1)) + { + if (IsRectEmpty(lprcSrc2)) + { + SetRectEmpty(lprcDst); + return(FALSE); + } + else + { + *lprcDst = *lprcSrc2; + } + } + else + { + if (IsRectEmpty(lprcSrc2)) + { + *lprcDst = *lprcSrc1; + } + else + { + lprcDst->left = min(lprcSrc1->left, lprcSrc2->left); + lprcDst->top = min(lprcSrc1->top, lprcSrc2->top); + lprcDst->right = max(lprcSrc1->right, lprcSrc2->right); + lprcDst->bottom = max(lprcSrc1->bottom, lprcSrc2->bottom); + } + } + return(TRUE); +} diff --git a/lib/user32/windows/text.c b/lib/user32/windows/text.c new file mode 100644 index 0000000..5ebd43a --- /dev/null +++ b/lib/user32/windows/text.c @@ -0,0 +1,297 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/input.c + * PURPOSE: Input + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 09-05-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +LPSTR +STDCALL +CharLowerA( + LPSTR lpsz) +{ + return (LPSTR)NULL; +} + +DWORD +STDCALL +CharLowerBuffA( + LPSTR lpsz, + DWORD cchLength) +{ + return 0; +} + +DWORD +STDCALL +CharLowerBuffW( + LPWSTR lpsz, + DWORD cchLength) +{ + return 0; +} + +LPWSTR +STDCALL +CharLowerW( + LPWSTR lpsz) +{ + return (LPWSTR)NULL; +} + +LPSTR +STDCALL +CharNextA( + LPCSTR lpsz) +{ + return (LPSTR)NULL; +} + +LPSTR +STDCALL +CharNextExA( + WORD CodePage, + LPCSTR lpCurrentChar, + DWORD dwFlags) +{ + return (LPSTR)NULL; +} + +LPWSTR +STDCALL +CharNextW( + LPCWSTR lpsz) +{ + return (LPWSTR)NULL; +} + +LPSTR +STDCALL +CharPrevA( + LPCSTR lpszStart, + LPCSTR lpszCurrent) +{ + return (LPSTR)NULL; +} + +LPWSTR +STDCALL +CharPrevW( + LPCWSTR lpszStart, + LPCWSTR lpszCurrent) +{ + return (LPWSTR)NULL; +} + +LPSTR +STDCALL +CharPrevExA( + WORD CodePage, + LPCSTR lpStart, + LPCSTR lpCurrentChar, + DWORD dwFlags) +{ + return (LPSTR)NULL; +} + +WINBOOL +STDCALL +CharToOemA( + LPCSTR lpszSrc, + LPSTR lpszDst) +{ + return FALSE; +} + +WINBOOL +STDCALL +CharToOemBuffA( + LPCSTR lpszSrc, + LPSTR lpszDst, + DWORD cchDstLength) +{ + return FALSE; +} + +WINBOOL +STDCALL +CharToOemBuffW( + LPCWSTR lpszSrc, + LPSTR lpszDst, + DWORD cchDstLength) +{ + return FALSE; +} + +WINBOOL +STDCALL +CharToOemW( + LPCWSTR lpszSrc, + LPSTR lpszDst) +{ + return FALSE; +} + +LPSTR +STDCALL +CharUpperA( + LPSTR lpsz) +{ + return (LPSTR)NULL; +} + +DWORD +STDCALL +CharUpperBuffA( + LPSTR lpsz, + DWORD cchLength) +{ + return 0; +} + +DWORD +STDCALL +CharUpperBuffW( + LPWSTR lpsz, + DWORD cchLength) +{ + return 0; +} + +LPWSTR +STDCALL +CharUpperW( + LPWSTR lpsz) +{ + return (LPWSTR)NULL; +} +WINBOOL +STDCALL +IsCharAlphaA( + CHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharAlphaNumericA( + CHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharAlphaNumericW( + WCHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharAlphaW( + WCHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharLowerA( + CHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharLowerW( + WCHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharUpperA( + CHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +IsCharUpperW( + WCHAR ch) +{ + return FALSE; +} + +WINBOOL +STDCALL +OemToCharA( + LPCSTR lpszSrc, + LPSTR lpszDst) +{ + return FALSE; +} + +WINBOOL +STDCALL +OemToCharBuffA( + LPCSTR lpszSrc, + LPSTR lpszDst, + DWORD cchDstLength) +{ + return FALSE; +} + +WINBOOL +STDCALL +OemToCharBuffW( + LPCSTR lpszSrc, + LPWSTR lpszDst, + DWORD cchDstLength) +{ + return FALSE; +} + +WINBOOL +STDCALL +OemToCharW( + LPCSTR lpszSrc, + LPWSTR lpszDst) +{ + return FALSE; +} diff --git a/lib/user32/windows/window.c b/lib/user32/windows/window.c new file mode 100644 index 0000000..c15da5d --- /dev/null +++ b/lib/user32/windows/window.c @@ -0,0 +1,939 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: lib/user32/windows/window.c + * PURPOSE: Window management + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +User32SendNCCALCSIZEMessageForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs; + SENDNCCALCSIZEMESSAGE_CALLBACK_RESULT Result; + WNDPROC Proc; + + DbgPrint("User32SendNCCALCSIZEMessageForKernel.\n"); + CallbackArgs = (PSENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(SENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS)) + { + DbgPrint("Wrong length.\n"); + return(STATUS_INFO_LENGTH_MISMATCH); + } + Proc = (WNDPROC)GetWindowLongW(CallbackArgs->Wnd, GWL_WNDPROC); + DbgPrint("Proc %X\n", Proc); + /* Call the window procedure; notice kernel messages are always unicode. */ + if (CallbackArgs->Validate) + { + Result.Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_NCCALCSIZE, + TRUE, + (LPARAM)&CallbackArgs->Params); + Result.Params = CallbackArgs->Params; + } + else + { + Result.Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_NCCALCSIZE, + FALSE, (LPARAM)&CallbackArgs->Rect); + Result.Rect = CallbackArgs->Rect; + } + DbgPrint("Returning result %d.\n", Result); + return(ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS)); +} + +NTSTATUS STDCALL +User32SendGETMINMAXINFOMessageForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDGETMINMAXINFO_CALLBACK_ARGUMENTS CallbackArgs; + SENDGETMINMAXINFO_CALLBACK_RESULT Result; + WNDPROC Proc; + + DbgPrint("User32SendGETMINAXINFOMessageForKernel.\n"); + CallbackArgs = (PSENDGETMINMAXINFO_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(SENDGETMINMAXINFO_CALLBACK_ARGUMENTS)) + { + DbgPrint("Wrong length.\n"); + return(STATUS_INFO_LENGTH_MISMATCH); + } + Proc = (WNDPROC)GetWindowLongW(CallbackArgs->Wnd, GWL_WNDPROC); + DbgPrint("Proc %X\n", Proc); + /* Call the window procedure; notice kernel messages are always unicode. */ + Result.Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_GETMINMAXINFO, + 0, (LPARAM)&CallbackArgs->MinMaxInfo); + Result.MinMaxInfo = CallbackArgs->MinMaxInfo; + DbgPrint("Returning result %d.\n", Result); + return(ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS)); +} + +NTSTATUS STDCALL +User32SendCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDCREATEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs; + WNDPROC Proc; + LRESULT Result; + + DbgPrint("User32SendCREATEMessageForKernel.\n"); + CallbackArgs = (PSENDCREATEMESSAGE_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(SENDCREATEMESSAGE_CALLBACK_ARGUMENTS)) + { + DbgPrint("Wrong length.\n"); + return(STATUS_INFO_LENGTH_MISMATCH); + } + Proc = (WNDPROC)GetWindowLongW(CallbackArgs->Wnd, GWL_WNDPROC); + DbgPrint("Proc %X\n", Proc); + /* Call the window procedure; notice kernel messages are always unicode. */ + Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_CREATE, 0, + (LPARAM)&CallbackArgs->CreateStruct); + DbgPrint("Returning result %d.\n", Result); + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + +NTSTATUS STDCALL +User32SendNCCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs; + WNDPROC Proc; + LRESULT Result; + + DbgPrint("User32SendNCCREATEMessageForKernel.\n"); + CallbackArgs = (PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS)) + { + DbgPrint("Wrong length.\n"); + return(STATUS_INFO_LENGTH_MISMATCH); + } + Proc = (WNDPROC)GetWindowLongW(CallbackArgs->Wnd, GWL_WNDPROC); + DbgPrint("Proc %X\n", Proc); + /* Call the window procedure; notice kernel messages are always unicode. */ + Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_NCCREATE, 0, + (LPARAM)&CallbackArgs->CreateStruct); + DbgPrint("Returning result %d.\n", Result); + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + +NTSTATUS STDCALL +User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PSENDASYNCPROC_CALLBACK_ARGUMENTS CallbackArgs; + + DbgPrint("User32CallSendAsyncProcKernel()\n"); + CallbackArgs = (PSENDASYNCPROC_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + CallbackArgs->Callback(CallbackArgs->Wnd, CallbackArgs->Msg, + CallbackArgs->Context, CallbackArgs->Result); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs; + LRESULT Result; + + CallbackArgs = (PWINDOWPROC_CALLBACK_ARGUMENTS)Arguments; + if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + if (CallbackArgs->Proc == NULL) + { + CallbackArgs->Proc = (WNDPROC)GetWindowLong(CallbackArgs->Wnd, + GWL_WNDPROC); + } + Result = CallWindowProcW(CallbackArgs->Proc, CallbackArgs->Wnd, + CallbackArgs->Msg, CallbackArgs->wParam, + CallbackArgs->lParam); + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + +WINBOOL STDCALL +AdjustWindowRect(LPRECT lpRect, + DWORD dwStyle, + WINBOOL bMenu) +{ + return(AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0)); +} + +WINBOOL STDCALL +AdjustWindowRectEx(LPRECT lpRect, + DWORD dwStyle, + WINBOOL bMenu, + DWORD dwExStyle) +{ + return(FALSE); +} + +WINBOOL STDCALL +AllowSetForegroundWindow(DWORD dwProcessId) +{ + return(FALSE); +} + +WINBOOL STDCALL +AnimateWindow(HWND hwnd, + DWORD dwTime, + DWORD dwFlags) +{ + return FALSE; +} + +UINT STDCALL +ArrangeIconicWindows(HWND hWnd) +{ + return 0; +} + +HDWP STDCALL +BeginDeferWindowPos(int nNumWindows) +{ + return (HDWP)0; +} + +WINBOOL STDCALL +BringWindowToTop(HWND hWnd) +{ + return FALSE; +} + +WORD STDCALL +CascadeWindows(HWND hwndParent, + UINT wHow, + CONST RECT *lpRect, + UINT cKids, + const HWND *lpKids) +{ + return 0; +} + +HWND STDCALL +ChildWindowFromPoint(HWND hWndParent, + POINT Point) +{ + return (HWND)0; +} + +HWND STDCALL +ChildWindowFromPointEx(HWND hwndParent, + POINT pt, + UINT uFlags) +{ + return (HWND)0; +} + +WINBOOL STDCALL +CloseWindow(HWND hWnd) +{ + return FALSE; +} + +HWND STDCALL +CreateWindowExA(DWORD dwExStyle, + LPCSTR lpClassName, + LPCSTR lpWindowName, + DWORD dwStyle, + int x, + int y, + int nWidth, + int nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam) +{ + UNICODE_STRING WindowName; + UNICODE_STRING ClassName; + HWND Handle; + INT sw; + + if (IS_ATOM(lpClassName)) + { + RtlInitUnicodeString(&ClassName, NULL); + ClassName.Buffer = (LPWSTR)lpClassName; + } + else + { + if (!RtlCreateUnicodeStringFromAsciiz(&(ClassName), (PCSZ)lpClassName)) + { + SetLastError(ERROR_OUTOFMEMORY); + return (HWND)0; + } + } + + if (!RtlCreateUnicodeStringFromAsciiz(&WindowName, (PCSZ)lpWindowName)) + { + if (!IS_ATOM(lpClassName)) + { + RtlFreeUnicodeString(&ClassName); + } + SetLastError(ERROR_OUTOFMEMORY); + return (HWND)0; + } + + /* Fixup default coordinates. */ + sw = SW_SHOW; + if (x == CW_USEDEFAULT || nWidth == CW_USEDEFAULT) + { + if (dwStyle & (WS_CHILD | WS_POPUP)) + { + if (x == CW_USEDEFAULT) + { + x = y = 0; + } + if (nWidth == CW_USEDEFAULT) + { + nWidth = nHeight = 0; + } + } + else + { + STARTUPINFOA info; + + GetStartupInfoA(&info); + + if (x == CW_USEDEFAULT) + { + if (y != CW_USEDEFAULT) + { + sw = y; + } + x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0; + y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0; + } + + if (nWidth == CW_USEDEFAULT) + { + if (info.dwFlags & STARTF_USESIZE) + { + nWidth = info.dwXSize; + nHeight = info.dwYSize; + } + else + { + RECT r; + + SystemParametersInfoA(SPI_GETWORKAREA, 0, &r, 0); + nWidth = (((r.right - r.left) * 3) / 4) - x; + nHeight = (((r.bottom - r.top) * 3) / 4) - y; + } + } + } + } + + Handle = NtUserCreateWindowEx(dwExStyle, + &ClassName, + &WindowName, + dwStyle, + x, + y, + nWidth, + nHeight, + hWndParent, + hMenu, + hInstance, + lpParam, + sw); + + RtlFreeUnicodeString(&WindowName); + + if (!IS_ATOM(lpClassName)) + { + RtlFreeUnicodeString(&ClassName); + } + + return Handle; +} + +HWND STDCALL +CreateWindowExW(DWORD dwExStyle, + LPCWSTR lpClassName, + LPCWSTR lpWindowName, + DWORD dwStyle, + int x, + int y, + int nWidth, + int nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam) +{ + UNICODE_STRING WindowName; + UNICODE_STRING ClassName; + HANDLE Handle; + UINT sw; + + if (IS_ATOM(lpClassName)) + { + RtlInitUnicodeString(&ClassName, NULL); + ClassName.Buffer = (LPWSTR)lpClassName; + } + else + { + RtlInitUnicodeString(&ClassName, lpClassName); + } + + RtlInitUnicodeString(&WindowName, lpWindowName); + + /* Fixup default coordinates. */ + sw = SW_SHOW; + if (x == CW_USEDEFAULT || nWidth == CW_USEDEFAULT) + { + if (dwStyle & (WS_CHILD | WS_POPUP)) + { + if (x == CW_USEDEFAULT) + { + x = y = 0; + } + if (nWidth == CW_USEDEFAULT) + { + nWidth = nHeight = 0; + } + } + else + { + STARTUPINFOW info; + + GetStartupInfoW(&info); + + if (x == CW_USEDEFAULT) + { + if (y != CW_USEDEFAULT) + { + sw = y; + } + x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0; + y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0; + } + + if (nWidth == CW_USEDEFAULT) + { + if (info.dwFlags & STARTF_USESIZE) + { + nWidth = info.dwXSize; + nHeight = info.dwYSize; + } + else + { + RECT r; + + SystemParametersInfoW(SPI_GETWORKAREA, 0, &r, 0); + nWidth = (((r.right - r.left) * 3) / 4) - x; + nHeight = (((r.bottom - r.top) * 3) / 4) - y; + } + } + } + } + + Handle = NtUserCreateWindowEx(dwExStyle, + &ClassName, + &WindowName, + dwStyle, + x, + y, + nWidth, + nHeight, + hWndParent, + hMenu, + hInstance, + lpParam, + 0); + + return (HWND)Handle; +} + +HDWP STDCALL +DeferWindowPos(HDWP hWinPosInfo, + HWND hWnd, + HWND hWndInsertAfter, + int x, + int y, + int cx, + int cy, + UINT uFlags) +{ + return (HDWP)0; +} + +WINBOOL STDCALL +DestroyWindow(HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +EndDeferWindowPos(HDWP hWinPosInfo) +{ + return FALSE; +} + +WINBOOL STDCALL +EnumChildWindows(HWND hWndParent, + ENUMWINDOWSPROC lpEnumFunc, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL STDCALL +EnumThreadWindows(DWORD dwThreadId, + ENUMWINDOWSPROC lpfn, + LPARAM lParam) +{ + return FALSE; +} + +WINBOOL STDCALL +EnumWindows(ENUMWINDOWSPROC lpEnumFunc, + LPARAM lParam) +{ + return FALSE; +} + +HWND STDCALL +FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName) +{ + //FIXME: FindWindow does not search children, but FindWindowEx does. + // what should we do about this? + return FindWindowExA (NULL, NULL, lpClassName, lpWindowName); +} + +HWND STDCALL +FindWindowExA(HWND hwndParent, + HWND hwndChildAfter, + LPCSTR lpszClass, + LPCSTR lpszWindow) +{ + return (HWND)0; +} + +HWND STDCALL +FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName) +{ + //FIXME: FindWindow does not search children, but FindWindowEx does. + // what should we do about this? + return FindWindowExW (NULL, NULL, lpClassName, lpWindowName); +} + +HWND STDCALL +FindWindowExW(HWND hwndParent, + HWND hwndChildAfter, + LPCWSTR lpszClass, + LPCWSTR lpszWindow) +{ + return (HWND)0; +} + +WINBOOL STDCALL +GetAltTabInfo(HWND hwnd, + int iItem, + PALTTABINFO pati, + LPTSTR pszItemText, + UINT cchItemText) +{ + return FALSE; +} + +WINBOOL STDCALL +GetAltTabInfoA(HWND hwnd, + int iItem, + PALTTABINFO pati, + LPSTR pszItemText, + UINT cchItemText) +{ + return FALSE; +} + +WINBOOL STDCALL +GetAltTabInfoW(HWND hwnd, + int iItem, + PALTTABINFO pati, + LPWSTR pszItemText, + UINT cchItemText) +{ + return FALSE; +} + +HWND STDCALL +GetAncestor(HWND hwnd, UINT gaFlags) +{ + return(NtUserGetAncestor(hwnd, gaFlags)); +} + +WINBOOL STDCALL +GetClientRect(HWND hWnd, LPRECT lpRect) +{ + return FALSE; +} + +HWND STDCALL +GetDesktopWindow(VOID) +{ + return (HWND)0; +} + +HWND STDCALL +GetForegroundWindow(VOID) +{ + return (HWND)0; +} + +WINBOOL STDCALL +GetGUIThreadInfo(DWORD idThread, + LPGUITHREADINFO lpgui) +{ + return FALSE; +} + +HWND STDCALL +GetLastActivePopup(HWND hWnd) +{ + return (HWND)0; +} + +HWND STDCALL +GetParent(HWND hWnd) +{ + return (HWND)0; +} + +WINBOOL STDCALL +GetProcessDefaultLayout(DWORD *pdwDefaultLayout) +{ + return FALSE; +} + +WINBOOL STDCALL +GetTitleBarInfo(HWND hwnd, + PTITLEBARINFO pti) +{ + return FALSE; +} + +HWND STDCALL +GetTopWindow(HWND hWnd) +{ + return (HWND)0; +} + +HWND STDCALL +GetWindow(HWND hWnd, + UINT uCmd) +{ + return (HWND)0; +} + +WINBOOL STDCALL +GetWindowInfo(HWND hwnd, + PWINDOWINFO pwi) +{ + return FALSE; +} + +UINT STDCALL +GetWindowModuleFileName(HWND hwnd, + LPSTR lpszFileName, + UINT cchFileNameMax) +{ + return 0; +} + +UINT STDCALL +GetWindowModuleFileNameA(HWND hwnd, + LPSTR lpszFileName, + UINT cchFileNameMax) +{ + return 0; +} + +UINT STDCALL +GetWindowModuleFileNameW(HWND hwnd, + LPWSTR lpszFileName, + UINT cchFileNameMax) +{ + return 0; +} + +WINBOOL STDCALL +GetWindowPlacement(HWND hWnd, + WINDOWPLACEMENT *lpwndpl) +{ + return FALSE; +} + +WINBOOL STDCALL +GetWindowRect(HWND hWnd, + LPRECT lpRect) +{ + return(NtUserGetWindowRect(hWnd, lpRect)); +} + +int STDCALL +GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount) +{ + return(SendMessageA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString)); +} + +int STDCALL +GetWindowTextLengthA(HWND hWnd) +{ + return(SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0)); +} + +int STDCALL +GetWindowTextLengthW(HWND hWnd) +{ + return 0; +} + +int STDCALL +GetWindowTextW(HWND hWnd, + LPWSTR lpString, + int nMaxCount) +{ + return 0; +} + +DWORD STDCALL +GetWindowThreadProcessId(HWND hWnd, + LPDWORD lpdwProcessId) +{ + return 0; +} + +WINBOOL STDCALL +IsChild(HWND hWndParent, + HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +IsIconic(HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +IsWindow(HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +IsWindowUnicode(HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +IsWindowVisible(HWND hWnd) +{ + while (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) + { + if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE)) + { + return(FALSE); + } + hWnd = GetAncestor(hWnd, GA_PARENT); + } + return(GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE); +} + +WINBOOL STDCALL +IsZoomed(HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +LockSetForegroundWindow(UINT uLockCode) +{ + return FALSE; +} + +WINBOOL STDCALL +MoveWindow(HWND hWnd, + int X, + int Y, + int nWidth, + int nHeight, + WINBOOL bRepaint) +{ + return FALSE; +} + +WINBOOL STDCALL +OpenIcon(HWND hWnd) +{ + return FALSE; +} + +HWND STDCALL +RealChildWindowFromPoint(HWND hwndParent, + POINT ptParentClientCoords) +{ + return (HWND)0; +} + +UINT +RealGetWindowClass(HWND hwnd, + LPTSTR pszType, + UINT cchType) +{ + return 0; +} + +WINBOOL STDCALL +SetForegroundWindow(HWND hWnd) +{ + return FALSE; +} + +WINBOOL STDCALL +SetLayeredWindowAttributes(HWND hwnd, + COLORREF crKey, + BYTE bAlpha, + DWORD dwFlags) +{ + return FALSE; +} + +HWND STDCALL +SetParent(HWND hWndChild, + HWND hWndNewParent) +{ + return (HWND)0; +} + +WINBOOL STDCALL +SetProcessDefaultLayout(DWORD dwDefaultLayout) +{ + return FALSE; +} + +WINBOOL STDCALL +SetWindowPlacement(HWND hWnd, + CONST WINDOWPLACEMENT *lpwndpl) +{ + return FALSE; +} + +WINBOOL STDCALL +SetWindowPos(HWND hWnd, + HWND hWndInsertAfter, + int X, + int Y, + int cx, + int cy, + UINT uFlags) +{ + return FALSE; +} + +WINBOOL STDCALL +SetWindowTextA(HWND hWnd, + LPCSTR lpString) +{ + return FALSE; +} + +WINBOOL STDCALL +SetWindowTextW(HWND hWnd, + LPCWSTR lpString) +{ + return FALSE; +} + +WINBOOL STDCALL +ShowOwnedPopups(HWND hWnd, + WINBOOL fShow) +{ + return FALSE; +} + +WINBOOL STDCALL +ShowWindow(HWND hWnd, + int nCmdShow) +{ + return NtUserShowWindow(hWnd, nCmdShow); +} + +WINBOOL STDCALL +ShowWindowAsync(HWND hWnd, + int nCmdShow) +{ + return FALSE; +} + +WORD STDCALL +TileWindows(HWND hwndParent, + UINT wHow, + CONST RECT *lpRect, + UINT cKids, + const HWND *lpKids) +{ + return 0; +} + +WINBOOL STDCALL +UpdateLayeredWindow(HWND hwnd, + HDC hdcDst, + POINT *pptDst, + SIZE *psize, + HDC hdcSrc, + POINT *pptSrc, + COLORREF crKey, + BLENDFUNCTION *pblend, + DWORD dwFlags) +{ + return FALSE; +} + +HWND STDCALL +WindowFromPoint(POINT Point) +{ + return (HWND)0; +} + +int STDCALL +MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints) +{ + POINT FromOffset, ToOffset; + LONG XMove, YMove; + ULONG i; + + NtUserGetClientOrigin(hWndFrom, &FromOffset); + NtUserGetClientOrigin(hWndTo, &ToOffset); + XMove = ToOffset.x - FromOffset.x; + YMove = ToOffset.y - FromOffset.y; + for (i = 0; i < cPoints; i++) + { + lpPoints[i].x += XMove; + lpPoints[i].y += YMove; + } + return(MAKELONG(LOWORD(XMove), LOWORD(YMove))); +} + + +WINBOOL STDCALL +ScreenToClient(HWND hWnd, LPPOINT lpPoint) +{ + return(MapWindowPoints(NULL, hWnd, lpPoint, 1)); +} + +/* EOF */ diff --git a/lib/version/.cvsignore b/lib/version/.cvsignore new file mode 100644 index 0000000..c189b50 --- /dev/null +++ b/lib/version/.cvsignore @@ -0,0 +1,3 @@ +version.coff +version.nostrip.dll +version.dll \ No newline at end of file diff --git a/lib/version/makefile b/lib/version/makefile new file mode 100644 index 0000000..770c8ff --- /dev/null +++ b/lib/version/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = version + +TARGET_BASE = 0x77a90000 + +TARGET_SDKLIBS = kernel32.a + +TARGET_OBJECTS = misc/libmain.o misc/stubs.o + +TARGET_CLEAN = misc/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/lib/version/misc/libmain.c b/lib/version/misc/libmain.c new file mode 100644 index 0000000..530b679 --- /dev/null +++ b/lib/version/misc/libmain.c @@ -0,0 +1,23 @@ +#include +INT +STDCALL +DllMain ( + PVOID hinstDll, + ULONG dwReason, + PVOID reserved + ) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return(1); +} + diff --git a/lib/version/misc/stubs.c b/lib/version/misc/stubs.c new file mode 100644 index 0000000..6ddeaa4 --- /dev/null +++ b/lib/version/misc/stubs.c @@ -0,0 +1,223 @@ +/* $Id$ + * + * version.dll stubs: remove from this file if + * you implement one of these functions. + */ +#include + +#ifndef HAVE_DLL_FORWARD +DWORD +STDCALL +GetFileVersionInfoSizeA ( + LPSTR lptstrFilename, + LPDWORD lpdwHandle + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +WINBOOL +STDCALL +GetFileVersionInfoA ( + LPSTR lptstrFilename, + DWORD dwHandle, + DWORD dwLen, + LPVOID lpData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +DWORD +STDCALL +GetFileVersionInfoSizeW ( + LPWSTR lptstrFilename, + LPDWORD lpdwHandle + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +GetFileVersionInfoW ( + LPWSTR lptstrFilename, + DWORD dwHandle, + DWORD dwLen, + LPVOID lpData + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +#endif /* ndef HAVE_DLL_FORWARD */ + + +DWORD +STDCALL +VerFindFileA ( + DWORD uFlags, + LPSTR szFileName, + LPSTR szWinDir, + LPSTR szAppDir, + LPSTR szCurDir, + PUINT lpuCurDirLen, + LPSTR szDestDir, + PUINT lpuDestDirLen + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerFindFileW ( + DWORD uFlags, + LPWSTR szFileName, + LPWSTR szWinDir, + LPWSTR szAppDir, + LPWSTR szCurDir, + PUINT lpuCurDirLen, + LPWSTR szDestDir, + PUINT lpuDestDirLen + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerInstallFileA ( + DWORD uFlags, + LPSTR szSrcFileName, + LPSTR szDestFileName, + LPSTR szSrcDir, + LPSTR szDestDir, + LPSTR szCurDir, + LPSTR szTmpFile, + PUINT lpuTmpFileLen + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerInstallFileW ( + DWORD uFlags, + LPWSTR szSrcFileName, + LPWSTR szDestFileName, + LPWSTR szSrcDir, + LPWSTR szDestDir, + LPWSTR szCurDir, + LPWSTR szTmpFile, + PUINT lpuTmpFileLen + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + + +DWORD +STDCALL +VerLanguageNameA ( + DWORD wLang, + LPSTR szLang, + DWORD nSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerLanguageNameW ( + DWORD wLang, + LPWSTR szLang, + DWORD nSize + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +WINBOOL +STDCALL +VerQueryValueA ( + const LPVOID pBlock, + LPSTR lpSubBlock, + LPVOID * lplpBuffer, + PUINT puLen + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +WINBOOL +STDCALL +VerQueryValueW ( + const LPVOID pBlock, + LPWSTR lpSubBlock, + LPVOID * lplpBuffer, + PUINT puLen + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + + +/* VerQueryValueIndex seems undocumented */ + +DWORD +STDCALL +VerQueryValueIndexA ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +DWORD +STDCALL +VerQueryValueIndexW ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5 + ) +{ + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + + +/* EOF */ diff --git a/lib/version/version.def b/lib/version/version.def new file mode 100644 index 0000000..07ecdac --- /dev/null +++ b/lib/version/version.def @@ -0,0 +1,19 @@ +; $Id$ +; ReactOS Operating System +; +LIBRARY version.dll +EXPORTS +GetFileVersionInfoA@16 +GetFileVersionInfoSizeA@8 +GetFileVersionInfoSizeW@8 +GetFileVersionInfoW@16 +VerFindFileA@32 +VerFindFileW@32 +VerInstallFileA@32 +VerInstallFileW@32 +VerLanguageNameA@12 +VerLanguageNameW@12 +VerQueryValueA@16 +VerQueryValueIndexA@24 +VerQueryValueIndexW@24 +VerQueryValueW@16 diff --git a/lib/version/version.edf b/lib/version/version.edf new file mode 100644 index 0000000..54ea9cf --- /dev/null +++ b/lib/version/version.edf @@ -0,0 +1,19 @@ +; $Id$ +; ReactOS Operating System +; +LIBRARY version.dll +EXPORTS +GetFileVersionInfoA=GetFileVersionInfoA@16 +GetFileVersionInfoSizeA=GetFileVersionInfoSizeA@8 +GetFileVersionInfoSizeW=GetFileVersionInfoSizeW@8 +GetFileVersionInfoW=GetFileVersionInfoW@16 +VerFindFileA=VerFindFileA@32 +VerFindFileW=VerFindFileW@32 +VerInstallFileA=VerInstallFileA@32 +VerInstallFileW=VerInstallFileW@32 +VerLanguageNameA=KERNEL32.VerLanguageNameA +VerLanguageNameW=KERNEL32.VerLanguageNameW +VerQueryValueA=VerQueryValueA@16 +VerQueryValueIndexA=VerQueryValueIndexA@24 +VerQueryValueIndexW=VerQueryValueIndexW@24 +VerQueryValueW=VerQueryValueW@16 diff --git a/lib/version/version.rc b/lib/version/version.rc new file mode 100644 index 0000000..13d54ec --- /dev/null +++ b/lib/version/version.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Version checking and file installation library\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "version\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "version.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/version/version_specs b/lib/version/version_specs new file mode 100644 index 0000000..e5c1a5f --- /dev/null +++ b/lib/version/version_specs @@ -0,0 +1,78 @@ +*asm: + + +*asm_final: + + +*cpp: +-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} + +*cc1: +%(cc1_spec) + +*cc1plus: + + +*endfile: + + +*link: +%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12} + +*lib: + + +*libgcc: +-lgcc + +*startfile: + + +*switches_need_spaces: + + +*signed_char: +%{funsigned-char:-D__CHAR_UNSIGNED__} + +*predefines: +-Di386 -D_WIN32 -DWIN32 -D__WIN32__ -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D_stdcall=__attribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)=__attribute__((x)) -Asystem(winnt) -Acpu(i386) -Amachine(i386) + +*cross_compile: +1 + +*version: +egcs-2.91.57 + +*multilib: +. ; + +*multilib_defaults: + + +*multilib_extra: + + +*multilib_matches: + + +*linker: +collect2 + +*cpp_486: +%{!ansi:-Di486} -D__i486 -D__i486__ + +*cpp_586: +%{!ansi:-Di586 -Dpentium} -D__i586 -D__i586__ -D__pentium -D__pentium__ + +*cpp_686: +%{!ansi:-Di686 -Dpentiumpro} -D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__ + +*cpp_cpu_default: +%(cpp_586) + +*cpp_cpu: +-Acpu(i386) -Amachine(i386) %{!ansi:-Di386} -D__i386 -D__i386__ %{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} %{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} %{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} %{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}} + +*cc1_cpu: +%{!mcpu*: %{m386:-mcpu=i386 -march=i386} %{mno-486:-mcpu=i386 -march=i386} %{m486:-mcpu=i486 -march=i486} %{mno-386:-mcpu=i486 -march=i486} %{mno-pentium:-mcpu=i486 -march=i486} %{mpentium:-mcpu=pentium} %{mno-pentiumpro:-mcpu=pentium} %{mpentiumpro:-mcpu=pentiumpro}} + diff --git a/lib/winmm/.cvsignore b/lib/winmm/.cvsignore new file mode 100644 index 0000000..a6baf4c --- /dev/null +++ b/lib/winmm/.cvsignore @@ -0,0 +1,4 @@ +*.coff +*.dll +*.o +*.sym diff --git a/lib/winmm/Makefile b/lib/winmm/Makefile new file mode 100644 index 0000000..20b4289 --- /dev/null +++ b/lib/winmm/Makefile @@ -0,0 +1,21 @@ +# $Id: makefile + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = winmm + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = \ + dllmain.o \ + misc/stubs.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/winmm/dllmain.c b/lib/winmm/dllmain.c new file mode 100644 index 0000000..2eb5093 --- /dev/null +++ b/lib/winmm/dllmain.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Media API DLL + * FILE: dllmain.c + * PURPOSE: DLL entry + * PROGRAMMERS: Steven Edwards (isolation@users.sourceforge.net) + * REVISIONS: + * SAE 9-24-02 Created + */ + +#include +#include + +#define NDEBUG +#include + +INT STDCALL +DllMain(PVOID hinstDll, + ULONG dwReason, + PVOID reserved) +{ + DbgPrint("WINMM: DllMain() called\n"); + + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + + DbgPrint("WINMM: DllMain() done\n"); + + return TRUE; +} diff --git a/lib/winmm/misc/stubs.c b/lib/winmm/misc/stubs.c new file mode 100644 index 0000000..9af5d8a --- /dev/null +++ b/lib/winmm/misc/stubs.c @@ -0,0 +1,32 @@ +/* + The stubs here are totaly wrong so please help a brother out + and fix this shit. sedwards 9-24-02 +*/ + +#include + +DECLARE_HANDLE(HWAVEOUT); // mmsystem.h + +UINT +WINAPI +waveOutReset(HWAVEOUT hWaveOut) +{ + DbgPrint("waveOutReset unimplemented\n"); + return 1; +} + +WINBOOL +STDCALL +sndPlaySoundA(LPCSTR pszSoundA, UINT uFlags) +{ + DbgPrint("waveOutReset unimplemented\n"); + return 1; +} + +WINBOOL +STDCALL +sndPlaySoundW(LPCSTR pszSoundA, UINT uFlags) +{ + DbgPrint("waveOutReset unimplemented\n"); + return 1; +} diff --git a/lib/winmm/winmm.def b/lib/winmm/winmm.def new file mode 100644 index 0000000..7d36f1f --- /dev/null +++ b/lib/winmm/winmm.def @@ -0,0 +1,6 @@ +LIBRARY WINMM.DLL +EXPORTS +; add more exports as needed +waveOutReset@4 +sndPlaySoundA@8 +sndPlaySoundW@8 \ No newline at end of file diff --git a/lib/winmm/winmm.edf b/lib/winmm/winmm.edf new file mode 100644 index 0000000..fee70d2 --- /dev/null +++ b/lib/winmm/winmm.edf @@ -0,0 +1,6 @@ +LIBRARY WINMM.DLL +EXPORTS +; add more exports as needed +waveOutReset=waveOutReset@4 +sndPlaySoundA=sndPlaySoundA@8 +sndPlaySoundW=sndPlaySoundW@8 \ No newline at end of file diff --git a/lib/winmm/winmm.rc b/lib/winmm/winmm.rc new file mode 100644 index 0000000..b40fb9e --- /dev/null +++ b/lib/winmm/winmm.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS MCI API Library\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "winmm\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "winmm.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/lib/ws2_32/.cvsignore b/lib/ws2_32/.cvsignore new file mode 100644 index 0000000..1e224b1 --- /dev/null +++ b/lib/ws2_32/.cvsignore @@ -0,0 +1,7 @@ +ws2_32.a +ws2_32.dll +ws2_32.nostrip.dll +ws2_32.coff +base.tmp +junk.tmp +temp.exp diff --git a/lib/ws2_32/include/catalog.h b/lib/ws2_32/include/catalog.h new file mode 100644 index 0000000..885c040 --- /dev/null +++ b/lib/ws2_32/include/catalog.h @@ -0,0 +1,60 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: include/catalog.h + * PURPOSE: Service Provider Catalog definitions + */ +#ifndef __CATALOG_H +#define __CATALOG_H + +#include +#include + +typedef struct _CATALOG_ENTRY { + LIST_ENTRY ListEntry; + ULONG ReferenceCount; + CRITICAL_SECTION Lock; + UNICODE_STRING LibraryName; + HMODULE hModule; + WSAPROTOCOL_INFOW ProtocolInfo; + PWINSOCK_MAPPING Mapping; + LPWSPSTARTUP WSPStartup; + WSPDATA WSPData; + WSPPROC_TABLE ProcTable; +} CATALOG_ENTRY, *PCATALOG_ENTRY; + +extern LIST_ENTRY Catalog; + + +VOID ReferenceProviderByPointer( + PCATALOG_ENTRY Provider); + +VOID DereferenceProviderByPointer( + PCATALOG_ENTRY Provider); + +PCATALOG_ENTRY CreateCatalogEntry( + LPWSTR LibraryName); + +INT DestroyCatalogEntry( + PCATALOG_ENTRY Provider); + +PCATALOG_ENTRY LocateProvider( + LPWSAPROTOCOL_INFOW lpProtocolInfo); + +PCATALOG_ENTRY LocateProviderById( + DWORD CatalogEntryId); + +INT LoadProvider( + PCATALOG_ENTRY Provider, + LPWSAPROTOCOL_INFOW lpProtocolInfo); + +INT UnloadProvider( + PCATALOG_ENTRY Provider); + +VOID CreateCatalog(VOID); + +VOID DestroyCatalog(VOID); + +#endif /* __CATALOG_H */ + +/* EOF */ diff --git a/lib/ws2_32/include/debug.h b/lib/ws2_32/include/debug.h new file mode 100644 index 0000000..c0ee7d9 --- /dev/null +++ b/lib/ws2_32/include/debug.h @@ -0,0 +1,66 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_CHECK 0x00000100 +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define WS_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { WS_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define WS_DbgPrint(_t_, _x_) + +#define ASSERT_IRQL(x) +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + WS_DbgPrint(MIN_TRACE, ("is unimplemented, please try again later.\n")); + +#define CHECKPOINT \ + WS_DbgPrint(DEBUG_CHECK, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/ws2_32/include/handle.h b/lib/ws2_32/include/handle.h new file mode 100644 index 0000000..ad0bb60 --- /dev/null +++ b/lib/ws2_32/include/handle.h @@ -0,0 +1,47 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: include/handle.h + * PURPOSE: Provider handle definitions + */ +#ifndef __HANDLE_H +#define __HANDLE_H + +#include +#include + +typedef struct _PROVIDER_HANDLE { + HANDLE Handle; + PCATALOG_ENTRY Provider; +} PROVIDER_HANDLE, *PPROVIDER_HANDLE; + +#define HANDLE_BLOCK_ENTRIES ((1024-sizeof(LIST_ENTRY))/sizeof(PROVIDER_HANDLE)) + +typedef struct _PROVIDER_HANDLE_BLOCK { + LIST_ENTRY Entry; + PROVIDER_HANDLE Handles[HANDLE_BLOCK_ENTRIES]; +} PROVIDER_HANDLE_BLOCK, *PPROVIDER_HANDLE_BLOCK; + +extern PPROVIDER_HANDLE_BLOCK ProviderHandleTable; + + +HANDLE +CreateProviderHandle(HANDLE Handle, + PCATALOG_ENTRY Provider); + +BOOL +ReferenceProviderByHandle(HANDLE Handle, + PCATALOG_ENTRY* Provider); + +BOOL +CloseProviderHandle(HANDLE Handle); + +BOOL +InitProviderHandleTable(VOID); + +VOID +FreeProviderHandleTable(VOID); + +#endif /* __HANDLE_H */ + +/* EOF */ diff --git a/lib/ws2_32/include/upcall.h b/lib/ws2_32/include/upcall.h new file mode 100644 index 0000000..965db92 --- /dev/null +++ b/lib/ws2_32/include/upcall.h @@ -0,0 +1,114 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: include/upcall.h + * PURPOSE: Upcall function defintions + */ +#ifndef __UPCALL_H +#define __UPCALL_H + +#include + +BOOL +WSPAPI +WPUCloseEvent( + IN WSAEVENT hEvent, + OUT LPINT lpErrno); + +INT +WSPAPI +WPUCloseSocketHandle( + IN SOCKET s, + OUT LPINT lpErrno); + +INT +WSPAPI +WPUCloseThread( + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +WSAEVENT +WSPAPI +WPUCreateEvent( + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WPUCreateSocketHandle( + IN DWORD dwCatalogEntryId, + IN DWORD dwContext, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WPUFDIsSet( + IN SOCKET s, + IN LPFD_SET set); + +INT +WSPAPI +WPUGetProviderPath( + IN LPGUID lpProviderId, + OUT LPWSTR lpszProviderDllPath, + IN OUT LPINT lpProviderDllPathLen, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WPUModifyIFSHandle( + IN DWORD dwCatalogEntryId, + IN SOCKET ProposedHandle, + OUT LPINT lpErrno); + +INT +WSPAPI +WPUOpenCurrentThread( + OUT LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WPUPostMessage( + IN HWND hWnd, + IN UINT Msg, + IN WPARAM wParam, + IN LPARAM lParam); + +INT +WSPAPI +WPUQueryBlockingCallback( + IN DWORD dwCatalogEntryId, + OUT LPBLOCKINGCALLBACK FAR* lplpfnCallback, + OUT LPDWORD lpdwContext, + OUT LPINT lpErrno); + +INT +WSPAPI +WPUQuerySocketHandleContext( + IN SOCKET s, + OUT LPDWORD lpContext, + OUT LPINT lpErrno); + +INT +WSPAPI +WPUQueueApc( + IN LPWSATHREADID lpThreadId, + IN LPWSAUSERAPC lpfnUserApc, + IN DWORD dwContext, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WPUResetEvent( + IN WSAEVENT hEvent, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WPUSetEvent( + IN WSAEVENT hEvent, + OUT LPINT lpErrno); + +#endif /* __UPCALL_H */ + +/* EOF */ diff --git a/lib/ws2_32/include/ws2_32.h b/lib/ws2_32/include/ws2_32.h new file mode 100644 index 0000000..254f702 --- /dev/null +++ b/lib/ws2_32/include/ws2_32.h @@ -0,0 +1,88 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: include/ws2_32.h + * PURPOSE: WinSock 2 DLL header + */ +#ifndef __WS2_32_H +#define __WS2_32_H + +#include +#include +#include +#include +#include + +/* Exported by ntdll.dll, but where is the prototype? */ +unsigned long strtoul(const char *nptr, char **endptr, int base); + + +#define EXPORT STDCALL + +extern HANDLE GlobalHeap; +extern WSPUPCALLTABLE UpcallTable; + + +typedef struct _WINSOCK_THREAD_BLOCK { + INT LastErrorValue; /* Error value from last function that failed */ + BOOL Initialized; /* TRUE if WSAStartup() has been successfully called */ + CHAR Intoa[16]; /* Buffer for inet_ntoa() */ +} WINSOCK_THREAD_BLOCK, *PWINSOCK_THREAD_BLOCK; + + +/* Macros */ + +#define WSAINITIALIZED (((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Initialized) + +#define WSASETINITIALIZED (((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Initialized = TRUE) + + +#ifdef LE + +/* DWORD network to host byte order conversion for little endian machines */ +#define DN2H(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* DWORD host to network byte order conversion for little endian machines */ +#define DH2N(dw) \ + ((((dw) & 0xFF000000L) >> 24) | \ + (((dw) & 0x00FF0000L) >> 8) | \ + (((dw) & 0x0000FF00L) << 8) | \ + (((dw) & 0x000000FFL) << 24)) + +/* WORD network to host order conversion for little endian machines */ +#define WN2H(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +/* WORD host to network byte order conversion for little endian machines */ +#define WH2N(w) \ + ((((w) & 0xFF00) >> 8) | \ + (((w) & 0x00FF) << 8)) + +#else /* LE */ + +/* DWORD network to host byte order conversion for big endian machines */ +#define DN2H(dw) \ + (dw) + +/* DWORD host to network byte order conversion big endian machines */ +#define DH2N(dw) \ + (dw) + +/* WORD network to host order conversion for big endian machines */ +#define WN2H(w) \ + (w) + +/* WORD host to network byte order conversion for big endian machines */ +#define WH2N(w) \ + (w) + +#endif /* LE */ + +#endif /* __WS2_32_H */ + +/* EOF */ diff --git a/lib/ws2_32/makefile b/lib/ws2_32/makefile new file mode 100644 index 0000000..5525bbd --- /dev/null +++ b/lib/ws2_32/makefile @@ -0,0 +1,26 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = ws2_32 + +TARGET_BASE = 0x77780000 + +TARGET_CFLAGS = -I./include -DUNICODE -DLE -DDBG + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = \ + misc/bsd.o misc/catalog.o misc/dllmain.o \ + misc/event.o misc/handle.o misc/ns.o \ + misc/sndrcv.o misc/stubs.o misc/upcall.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +TARGET_CLEAN = misc/*.o + +# EOF diff --git a/lib/ws2_32/misc/bsd.c b/lib/ws2_32/misc/bsd.c new file mode 100644 index 0000000..9675611 --- /dev/null +++ b/lib/ws2_32/misc/bsd.c @@ -0,0 +1,44 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/bsd.c + * PURPOSE: Legacy BSD sockets APIs + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 15/06-2001 Created + */ +#include + +ULONG +EXPORT +htonl( + IN ULONG hostlong) +{ + return DH2N(hostlong); +} + +USHORT +EXPORT +htons( + IN USHORT hostshort) +{ + return WH2N(hostshort); +} + +ULONG +EXPORT +ntohl( + IN ULONG netlong) +{ + return DN2H(netlong); +} + +USHORT +EXPORT +ntohs( + IN USHORT netshort) +{ + return WN2H(netshort); +} + +/* EOF */ diff --git a/lib/ws2_32/misc/catalog.c b/lib/ws2_32/misc/catalog.c new file mode 100644 index 0000000..da89f6e --- /dev/null +++ b/lib/ws2_32/misc/catalog.c @@ -0,0 +1,314 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/catalog.c + * PURPOSE: Service Provider Catalog + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include + + +LIST_ENTRY CatalogListHead; +CRITICAL_SECTION CatalogLock; + +VOID ReferenceProviderByPointer( + PCATALOG_ENTRY Provider) +{ + WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); + + //EnterCriticalSection(&Provider->Lock); + Provider->ReferenceCount++; + //LeaveCriticalSection(&Provider->Lock); +} + + +VOID DereferenceProviderByPointer( + PCATALOG_ENTRY Provider) +{ + WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); + +#ifdef DBG + if (Provider->ReferenceCount <= 0) { + WS_DbgPrint(MIN_TRACE, ("Provider at 0x%X has invalid reference count (%ld).\n", + Provider, Provider->ReferenceCount)); + } +#endif + + //EnterCriticalSection(&Provider->Lock); + Provider->ReferenceCount--; + //LeaveCriticalSection(&Provider->Lock); + + if (Provider->ReferenceCount == 0) { + WS_DbgPrint(MAX_TRACE, ("Provider at 0x%X has reference count 0 (unloading).\n", + Provider)); + + DestroyCatalogEntry(Provider); + } +} + + +PCATALOG_ENTRY CreateCatalogEntry( + LPWSTR LibraryName) +{ + PCATALOG_ENTRY Provider; + + WS_DbgPrint(MAX_TRACE, ("LibraryName (%S).\n", LibraryName)); + + Provider = HeapAlloc(GlobalHeap, 0, sizeof(CATALOG_ENTRY)); + if (!Provider) { + return NULL; + } + + ZeroMemory(Provider, sizeof(CATALOG_ENTRY)); + + if (!RtlCreateUnicodeString(&Provider->LibraryName, LibraryName)) { + RtlFreeHeap(GlobalHeap, 0, Provider); + return NULL; + } + + Provider->ReferenceCount = 1; + + InitializeCriticalSection(&Provider->Lock); + Provider->hModule = (HMODULE)INVALID_HANDLE_VALUE; + + Provider->Mapping = NULL; + + //EnterCriticalSection(&CatalogLock); + + InsertTailList(&CatalogListHead, &Provider->ListEntry); + + //LeaveCriticalSection(&CatalogLock); + + return Provider; +} + + +INT DestroyCatalogEntry( + PCATALOG_ENTRY Provider) +{ + INT Status; + + WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); + + //EnterCriticalSection(&CatalogLock); + RemoveEntryList(&Provider->ListEntry); + //LeaveCriticalSection(&CatalogLock); + + HeapFree(GlobalHeap, 0, Provider->Mapping); + + if (Provider->hModule) { + Status = UnloadProvider(Provider); + } else { + Status = NO_ERROR; + } + + //DeleteCriticalSection(&Provider->Lock); + + HeapFree(GlobalHeap, 0, Provider); + + return Status; +} + + +PCATALOG_ENTRY LocateProvider( + LPWSAPROTOCOL_INFOW lpProtocolInfo) +{ + PLIST_ENTRY CurrentEntry; + PCATALOG_ENTRY Provider; + UINT i; + + WS_DbgPrint(MAX_TRACE, ("lpProtocolInfo (0x%X).\n", lpProtocolInfo)); + + //EnterCriticalSection(&CatalogLock); + + CurrentEntry = CatalogListHead.Flink; + while (CurrentEntry != &CatalogListHead) { + Provider = CONTAINING_RECORD(CurrentEntry, + CATALOG_ENTRY, + ListEntry); + + for (i = 0; i < Provider->Mapping->Rows; i++) { + if ((lpProtocolInfo->iAddressFamily == Provider->Mapping->Mapping[i].AddressFamily) && + (lpProtocolInfo->iSocketType == Provider->Mapping->Mapping[i].SocketType) && + ((lpProtocolInfo->iProtocol == Provider->Mapping->Mapping[i].Protocol) || + (lpProtocolInfo->iSocketType == SOCK_RAW))) { + //LeaveCriticalSection(&CatalogLock); + WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X).\n", Provider)); + return Provider; + } + } + + CurrentEntry = CurrentEntry->Flink; + } + + //LeaveCriticalSection(&CatalogLock); + + return NULL; +} + + +PCATALOG_ENTRY LocateProviderById( + DWORD CatalogEntryId) +{ + PLIST_ENTRY CurrentEntry; + PCATALOG_ENTRY Provider; + UINT i; + + WS_DbgPrint(MAX_TRACE, ("CatalogEntryId (%d).\n", CatalogEntryId)); + + //EnterCriticalSection(&CatalogLock); + CurrentEntry = CatalogListHead.Flink; + while (CurrentEntry != &CatalogListHead) { + Provider = CONTAINING_RECORD(CurrentEntry, + CATALOG_ENTRY, + ListEntry); + + if (Provider->ProtocolInfo.dwCatalogEntryId == CatalogEntryId) { + //LeaveCriticalSection(&CatalogLock); + WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X) Name (%wZ).\n", + Provider, &Provider->LibraryName)); + return Provider; + } + + CurrentEntry = CurrentEntry->Flink; + } + //LeaveCriticalSection(&CatalogLock); + + WS_DbgPrint(MID_TRACE, ("Provider was not found.\n")); + + return NULL; +} + + +INT LoadProvider( + PCATALOG_ENTRY Provider, + LPWSAPROTOCOL_INFOW lpProtocolInfo) +{ + INT Status; + + WS_DbgPrint(MAX_TRACE, ("Loading provider at (0x%X) Name (%wZ).\n", + Provider, &Provider->LibraryName)); + + if (Provider->hModule == INVALID_HANDLE_VALUE) { + /* DLL is not loaded so load it now */ + Provider->hModule = LoadLibrary(Provider->LibraryName.Buffer); + if (Provider->hModule != INVALID_HANDLE_VALUE) { + Provider->WSPStartup = (LPWSPSTARTUP)GetProcAddress( + Provider->hModule, + "WSPStartup"); + if (Provider->WSPStartup) { + WS_DbgPrint(MAX_TRACE, ("Calling WSPStartup at (0x%X).\n", + Provider->WSPStartup)); + Status = Provider->WSPStartup( + MAKEWORD(2, 2), + &Provider->WSPData, + lpProtocolInfo, + UpcallTable, + &Provider->ProcTable); + + /* FIXME: Validate the procedure table */ + } else + Status = ERROR_BAD_PROVIDER; + } else + Status = ERROR_DLL_NOT_FOUND; + } else + Status = NO_ERROR; + + WS_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); + + return Status; +} + + +INT UnloadProvider( + PCATALOG_ENTRY Provider) +{ + INT Status = NO_ERROR; + + WS_DbgPrint(MAX_TRACE, ("Unloading provider at (0x%X)\n", Provider)); + + if (Provider->hModule) { + WS_DbgPrint(MAX_TRACE, ("Calling WSPCleanup at (0x%X).\n", + Provider->ProcTable.lpWSPCleanup)); + Provider->ProcTable.lpWSPCleanup(&Status); + + WS_DbgPrint(MAX_TRACE, ("Calling FreeLibrary(0x%X).\n", Provider->hModule)); + if (!FreeLibrary(Provider->hModule)) { + WS_DbgPrint(MIN_TRACE, ("Could not free library at (0x%X).\n", Provider->hModule)); + Status = GetLastError(); + } + + Provider->hModule = (HMODULE)INVALID_HANDLE_VALUE; + } + + WS_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); + + return Status; +} + + +VOID CreateCatalog(VOID) +{ + PCATALOG_ENTRY Provider; + + InitializeCriticalSection(&CatalogLock); + + InitializeListHead(&CatalogListHead); + + /* FIXME: Read service provider catalog from registry */ +#if 1 + Provider = CreateCatalogEntry(L"msafd.dll"); + if (!Provider) { + WS_DbgPrint(MIN_TRACE, ("Could not create catalog entry.\n")); + return; + } + + /* Assume one Service Provider with id 1 */ + Provider->ProtocolInfo.dwCatalogEntryId = 1; + + Provider->Mapping = HeapAlloc(GlobalHeap, + 0, + 3 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD)); + if (!Provider->Mapping) + return; + + Provider->Mapping->Rows = 3; + Provider->Mapping->Columns = 3; + + Provider->Mapping->Mapping[0].AddressFamily = AF_INET; + Provider->Mapping->Mapping[0].SocketType = SOCK_STREAM; + Provider->Mapping->Mapping[0].Protocol = IPPROTO_TCP; + + Provider->Mapping->Mapping[1].AddressFamily = AF_INET; + Provider->Mapping->Mapping[1].SocketType = SOCK_DGRAM; + Provider->Mapping->Mapping[1].Protocol = IPPROTO_UDP; + + Provider->Mapping->Mapping[2].AddressFamily = AF_INET; + Provider->Mapping->Mapping[2].SocketType = SOCK_RAW; + Provider->Mapping->Mapping[2].Protocol = 0; +#endif +} + + +VOID DestroyCatalog(VOID) +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PCATALOG_ENTRY Provider; + + CurrentEntry = CatalogListHead.Flink; + while (CurrentEntry != &CatalogListHead) { + NextEntry = CurrentEntry->Flink; + Provider = CONTAINING_RECORD(CurrentEntry, + CATALOG_ENTRY, + ListEntry); + DestroyCatalogEntry(Provider); + CurrentEntry = NextEntry; + } + //DeleteCriticalSection(&CatalogLock); +} + +/* EOF */ diff --git a/lib/ws2_32/misc/dllmain.c b/lib/ws2_32/misc/dllmain.c new file mode 100644 index 0000000..ed6b181 --- /dev/null +++ b/lib/ws2_32/misc/dllmain.c @@ -0,0 +1,578 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/dllmain.c + * PURPOSE: DLL entry point + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include +#include +#include + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MIN_TRACE; +//DWORD DebugTraceLevel = DEBUG_ULTRA; + +#endif /* DBG */ + +/* To make the linker happy */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +HANDLE GlobalHeap; +WSPUPCALLTABLE UpcallTable; + + +INT +EXPORT +WSAGetLastError(VOID) +{ + PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData; + + if (p) { + return p->LastErrorValue; + } else { + /* FIXME: What error code should we use here? Can this even happen? */ + return ERROR_BAD_ENVIRONMENT; + } +} + + +VOID +EXPORT +WSASetLastError( + IN INT iError) +{ + PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData; + + if (p) + p->LastErrorValue = iError; +} + + +INT +EXPORT +WSAStartup( + IN WORD wVersionRequested, + OUT LPWSADATA lpWSAData) +{ + WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n")); + + lpWSAData->wVersion = wVersionRequested; + lpWSAData->wHighVersion = 2; + lstrcpyA(lpWSAData->szDescription, "WinSock 2.0"); + lstrcpyA(lpWSAData->szSystemStatus, "Running"); + lpWSAData->iMaxSockets = 0; + lpWSAData->iMaxUdpDg = 0; + lpWSAData->lpVendorInfo = NULL; + + WSASETINITIALIZED; + + return NO_ERROR; +} + + +INT +EXPORT +WSACleanup(VOID) +{ + WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n")); + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return WSANOTINITIALISED; + } + + return NO_ERROR; +} + + +SOCKET +EXPORT +socket( + IN INT af, + IN INT type, + IN INT protocol) +{ + return WSASocketA(af, type, protocol, NULL, 0, 0); +} + + +SOCKET +EXPORT +WSASocketA( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags) +/* + * FUNCTION: Creates a new socket + */ +{ + WSAPROTOCOL_INFOW ProtocolInfoW; + LPWSAPROTOCOL_INFOW p; + UNICODE_STRING StringU; + ANSI_STRING StringA; + + WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", + af, type, protocol)); + + if (lpProtocolInfo) { + memcpy(&ProtocolInfoW, + lpProtocolInfo, + sizeof(WSAPROTOCOL_INFOA) - + sizeof(CHAR) * (WSAPROTOCOL_LEN + 1)); + RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol); + RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol); + RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE); + p = &ProtocolInfoW; + } else { + p = NULL; + } + + return WSASocketW(af, + type, + protocol, + p, + g, + dwFlags); +} + + +SOCKET +EXPORT +WSASocketW( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags) +/* + * FUNCTION: Creates a new socket descriptor + * ARGUMENTS: + * af = Address family + * type = Socket type + * protocol = Protocol type + * lpProtocolInfo = Pointer to protocol information + * g = Reserved + * dwFlags = Socket flags + * RETURNS: + * Created socket descriptor, or INVALID_SOCKET if it could not be created + */ +{ + INT Status; + SOCKET Socket; + PCATALOG_ENTRY Provider; + WSAPROTOCOL_INFOW ProtocolInfo; + + WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", + af, type, protocol)); + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return INVALID_SOCKET; + } + + if (!lpProtocolInfo) { + lpProtocolInfo = &ProtocolInfo; + ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW)); + + ProtocolInfo.iAddressFamily = af; + ProtocolInfo.iSocketType = type; + ProtocolInfo.iProtocol = protocol; + } + + Provider = LocateProvider(lpProtocolInfo); + if (!Provider) { + WSASetLastError(WSAEAFNOSUPPORT); + return INVALID_SOCKET; + } + + Status = LoadProvider(Provider, lpProtocolInfo); + if (Status != NO_ERROR) { + WSASetLastError(Status); + return INVALID_SOCKET; + } + + WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n", + Provider->ProcTable.lpWSPSocket)); + + assert(Provider->ProcTable.lpWSPSocket); + + Socket = Provider->ProcTable.lpWSPSocket( + af, + type, + protocol, + lpProtocolInfo, + g, + dwFlags, + &Status); + if (Status != NO_ERROR) { + WSASetLastError(Status); + return INVALID_SOCKET; + } + + return Socket; +} + + +INT +EXPORT +closesocket( + IN SOCKET s) +/* + * FUNCTION: Closes a socket descriptor + * ARGUMENTS: + * s = Socket descriptor + * RETURNS: + * 0, or SOCKET_ERROR if an error ocurred + */ +{ + PCATALOG_ENTRY Provider; + INT Status; + INT Errno; + + WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s)); + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + CloseProviderHandle((HANDLE)s); + + DereferenceProviderByPointer(Provider); + + Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno); + if (Status == SOCKET_ERROR) + WSASetLastError(Errno); + + return 0; +} + + +INT +EXPORT +select( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout) +/* + * FUNCTION: Returns status of one or more sockets + * ARGUMENTS: + * nfds = Always ignored + * readfds = Pointer to socket set to be checked for readability (optional) + * writefds = Pointer to socket set to be checked for writability (optional) + * exceptfds = Pointer to socket set to be checked for errors (optional) + * timeout = Pointer to a TIMEVAL structure indicating maximum wait time + * (NULL means wait forever) + * RETURNS: + * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred + */ +{ + PCATALOG_ENTRY Provider; + INT Count; + INT Errno; + ULONG i; + + WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n", + readfds, writefds, exceptfds)); + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + /* FIXME: Sockets in FD_SETs should be sorted by their provider */ + + /* FIXME: For now, assume only one service provider */ + if ((readfds != NULL) && (readfds->fd_count > 0)) { + if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + } else if ((writefds != NULL) && (writefds->fd_count > 0)) { + if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + } else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) { + if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + } else { + WSASetLastError(WSAEINVAL); + return SOCKET_ERROR; + } + + Count = Provider->ProcTable.lpWSPSelect( + nfds, readfds, writefds, exceptfds, timeout, &Errno); + + WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); + + DereferenceProviderByPointer(Provider); + + if (Errno != NO_ERROR) { + WSASetLastError(Errno); + return SOCKET_ERROR; + } + + return Count; +} + + +INT +EXPORT +bind( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen) +{ + PCATALOG_ENTRY Provider; + INT Status; + INT Errno; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + Status = Provider->ProcTable.lpWSPBind( + s, name, namelen, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Status == SOCKET_ERROR) { + WSASetLastError(Errno); + } + + return Status; +} + + +INT +EXPORT +listen( + IN SOCKET s, + IN INT backlog) +{ + PCATALOG_ENTRY Provider; + INT Status; + INT Errno; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + Status = Provider->ProcTable.lpWSPListen( + s, backlog, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Status == SOCKET_ERROR) { + WSASetLastError(Errno); + } + + return Status; +} + + +SOCKET +EXPORT +accept( + IN SOCKET s, + OUT LPSOCKADDR addr, + OUT INT FAR* addrlen) +{ + return WSAAccept(s, addr, addrlen, NULL, 0); +} + + +SOCKET +EXPORT +WSAAccept( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData) +{ + PCATALOG_ENTRY Provider; + SOCKET Socket; + INT Errno; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + Socket = Provider->ProcTable.lpWSPAccept( + s, addr, addrlen, lpfnCondition, dwCallbackData, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Socket == INVALID_SOCKET) { + WSASetLastError(Errno); + } + + return Socket; +} + + +INT +EXPORT +connect( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen) +{ + return WSAConnect(s, name, namelen, NULL, NULL, NULL, NULL); +} + + +INT +EXPORT +WSAConnect( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS) +{ + PCATALOG_ENTRY Provider; + INT Status; + INT Errno; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + Status = Provider->ProcTable.lpWSPConnect( + s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Status == SOCKET_ERROR) { + WSASetLastError(Errno); + } + + return Status; +} + + +BOOL +STDCALL +DllMain(HANDLE hInstDll, + ULONG dwReason, + LPVOID lpReserved) +{ + PWINSOCK_THREAD_BLOCK p; + + WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + GlobalHeap = GetProcessHeap(); + + CreateCatalog(); + + InitProviderHandleTable(); + + UpcallTable.lpWPUCloseEvent = WPUCloseEvent; + UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle; + UpcallTable.lpWPUCreateEvent = WPUCreateEvent; + UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle; + UpcallTable.lpWPUFDIsSet = WPUFDIsSet; + UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath; + UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle; + UpcallTable.lpWPUPostMessage = WPUPostMessage; + UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback; + UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext; + UpcallTable.lpWPUQueueApc = WPUQueueApc; + UpcallTable.lpWPUResetEvent = WPUResetEvent; + UpcallTable.lpWPUSetEvent = WPUSetEvent; + UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread; + UpcallTable.lpWPUCloseThread = WPUCloseThread; + + /* Fall through to thread attachment handler */ + + case DLL_THREAD_ATTACH: + p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK)); + + WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p)); + + if (!p) { + return FALSE; + } + + p->LastErrorValue = NO_ERROR; + p->Initialized = FALSE; + + NtCurrentTeb()->WinSockData = p; + break; + + case DLL_PROCESS_DETACH: + p = NtCurrentTeb()->WinSockData; + + if (p) + HeapFree(GlobalHeap, 0, p); + + DestroyCatalog(); + + FreeProviderHandleTable(); + break; + + case DLL_THREAD_DETACH: + p = NtCurrentTeb()->WinSockData; + + if (p) + HeapFree(GlobalHeap, 0, p); + break; + } + + WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n")); + + return TRUE; +} + +/* EOF */ diff --git a/lib/ws2_32/misc/event.c b/lib/ws2_32/misc/event.c new file mode 100644 index 0000000..671cdbd --- /dev/null +++ b/lib/ws2_32/misc/event.c @@ -0,0 +1,202 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/event.c + * PURPOSE: Event handling + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include + + +BOOL +EXPORT +WSACloseEvent( + IN WSAEVENT hEvent) +{ + BOOL Success; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return FALSE; + } + + Success = CloseHandle((HANDLE)hEvent); + + if (!Success) + WSASetLastError(WSA_INVALID_HANDLE); + + return Success; +} + + +WSAEVENT +EXPORT +WSACreateEvent(VOID) +{ + HANDLE Event; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return FALSE; + } + + Event = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (Event == INVALID_HANDLE_VALUE) + WSASetLastError(WSA_INVALID_HANDLE); + + return (WSAEVENT)Event; +} + + +BOOL +EXPORT +WSAResetEvent( + IN WSAEVENT hEvent) +{ + BOOL Success; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return FALSE; + } + + Success = ResetEvent((HANDLE)hEvent); + + if (!Success) + WSASetLastError(WSA_INVALID_HANDLE); + + return Success; +} + + +BOOL +EXPORT +WSASetEvent( + IN WSAEVENT hEvent) +{ + BOOL Success; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return FALSE; + } + + Success = SetEvent((HANDLE)hEvent); + + if (!Success) + WSASetLastError(WSA_INVALID_HANDLE); + + return Success; +} + + +DWORD +EXPORT +WSAWaitForMultipleEvents( + IN DWORD cEvents, + IN CONST WSAEVENT FAR* lphEvents, + IN BOOL fWaitAll, + IN DWORD dwTimeout, + IN BOOL fAlertable) +{ + DWORD Status; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return FALSE; + } + + Status = WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable); + if (Status == WAIT_FAILED) { + Status = GetLastError(); + + if (Status == ERROR_NOT_ENOUGH_MEMORY) + WSASetLastError(WSA_NOT_ENOUGH_MEMORY); + else if (Status == ERROR_INVALID_HANDLE) + WSASetLastError(WSA_INVALID_HANDLE); + else + WSASetLastError(WSA_INVALID_PARAMETER); + + return WSA_WAIT_FAILED; + } + + return Status; +} + + +INT +EXPORT +WSAEnumNetworkEvents( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents) +{ + PCATALOG_ENTRY Provider; + INT Status; + INT Errno; + + if (!lpNetworkEvents) { + WSASetLastError(WSAEINVAL); + return SOCKET_ERROR; + } + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + Status = Provider->ProcTable.lpWSPEnumNetworkEvents( + s, hEventObject, lpNetworkEvents, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Status == SOCKET_ERROR) + WSASetLastError(Errno); + + return Status; +} + + +INT +EXPORT +WSAEventSelect( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents) +{ + PCATALOG_ENTRY Provider; + INT Status; + INT Errno; + LONG i; + + if (!WSAINITIALIZED) { + WSASetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + Status = Provider->ProcTable.lpWSPEventSelect( + s, hEventObject, lNetworkEvents, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Status == SOCKET_ERROR) + WSASetLastError(Errno); + + return Status; +} + +/* EOF */ diff --git a/lib/ws2_32/misc/handle.c b/lib/ws2_32/misc/handle.c new file mode 100644 index 0000000..7e6dcc5 --- /dev/null +++ b/lib/ws2_32/misc/handle.c @@ -0,0 +1,277 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/handle.c + * PURPOSE: Provider handle management + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include +#include + +PPROVIDER_HANDLE_BLOCK ProviderHandleTable; +CRITICAL_SECTION ProviderHandleTableLock; + +PPROVIDER_HANDLE +GetProviderByHandle( + PPROVIDER_HANDLE_BLOCK HandleTable, + HANDLE Handle) +/* + * FUNCTION: Get the data structure for a handle + * ARGUMENTS: + * HandleTable = Pointer to handle table + * Handle = Handle to get data structure for + * RETURNS: + * Pointer to the data structure identified by the handle on success, + * NULL on failure + */ +{ + PPROVIDER_HANDLE_BLOCK Current; + PLIST_ENTRY CurrentEntry; + ULONG i; + + WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle)); + + CurrentEntry = HandleTable->Entry.Flink; + + while (CurrentEntry != &HandleTable->Entry) { + Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); + + for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) { + if ((Current->Handles[i].Provider != NULL) && + (Current->Handles[i].Handle == Handle)) { + return &Current->Handles[i]; + } + } + CurrentEntry = CurrentEntry->Flink; + } + + return NULL; +} + + +VOID +CloseAllHandles( + PPROVIDER_HANDLE_BLOCK HandleTable) +{ + PPROVIDER_HANDLE_BLOCK Current; + PLIST_ENTRY CurrentEntry; + PCATALOG_ENTRY Provider; + ULONG i; + + WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X).\n", HandleTable)); + + CurrentEntry = HandleTable->Entry.Flink; + + while (CurrentEntry != &HandleTable->Entry) { + Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); + + for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) { + Provider = Current->Handles[i].Provider; + if (Provider != NULL) { + DereferenceProviderByPointer(Provider); + Current->Handles[i].Handle = (HANDLE)0; + Current->Handles[i].Provider = NULL; + } + } + CurrentEntry = CurrentEntry->Flink; + } +} + + +VOID +DeleteHandleTable( + PPROVIDER_HANDLE_BLOCK HandleTable) +{ + PPROVIDER_HANDLE_BLOCK Current; + PLIST_ENTRY CurrentEntry; + + CloseAllHandles(HandleTable); + + CurrentEntry = RemoveHeadList(&HandleTable->Entry); + + while (CurrentEntry != &HandleTable->Entry) { + Current = CONTAINING_RECORD( + CurrentEntry, + PROVIDER_HANDLE_BLOCK, + Entry); + + HeapFree(GlobalHeap, 0, Current); + + CurrentEntry = RemoveHeadList(&HandleTable->Entry); + } +} + + +PCATALOG_ENTRY +DeleteProviderHandle(PPROVIDER_HANDLE_BLOCK HandleTable, + HANDLE Handle) +{ + PPROVIDER_HANDLE Entry; + PCATALOG_ENTRY Provider; + + WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle)); + + Entry = GetProviderByHandle(HandleTable, Handle); + if (!Entry) + return NULL; + + Provider = Entry->Provider; + Entry->Handle = (HANDLE)0; + Entry->Provider = NULL; + + return Provider; +} + + +HANDLE +CreateProviderHandleTable( + PPROVIDER_HANDLE_BLOCK HandleTable, + HANDLE Handle, + PCATALOG_ENTRY Provider) +{ + PPROVIDER_HANDLE_BLOCK NewBlock; + PLIST_ENTRY CurrentEntry; + ULONG i; + + WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X) Provider (0x%X).\n", + HandleTable, Handle, Provider)); + + /* Scan through the currently allocated handle blocks looking for a free slot */ + CurrentEntry = HandleTable->Entry.Flink; + while (CurrentEntry != &HandleTable->Entry) { + PPROVIDER_HANDLE_BLOCK Block = CONTAINING_RECORD( + CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); + + for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) { + WS_DbgPrint(MAX_TRACE, ("Considering slot %ld containing 0x%X.\n", + i, Block->Handles[i].Provider)); + if (Block->Handles[i].Provider == NULL) { + Block->Handles[i].Handle = Handle; + Block->Handles[i].Provider = Provider; + return Handle; + } + } + CurrentEntry = CurrentEntry->Flink; + } + + /* Add a new handle block to the end of the list */ + NewBlock = (PPROVIDER_HANDLE_BLOCK)HeapAlloc( + GlobalHeap, 0, sizeof(PROVIDER_HANDLE_BLOCK)); + + if (!NewBlock) + return (HANDLE)0; + + ZeroMemory(NewBlock, sizeof(PROVIDER_HANDLE_BLOCK)); + InsertTailList(&HandleTable->Entry, &NewBlock->Entry); + + NewBlock->Handles[0].Handle = Handle; + NewBlock->Handles[0].Provider = Provider; + + return Handle; +} + + +HANDLE +CreateProviderHandle( + HANDLE Handle, + PCATALOG_ENTRY Provider) +{ + HANDLE h; + + EnterCriticalSection(&ProviderHandleTableLock); + + h = CreateProviderHandleTable(ProviderHandleTable, Handle, Provider); + + LeaveCriticalSection(&ProviderHandleTableLock); + + if (h != NULL) + ReferenceProviderByPointer(Provider); + + return h; +} + + +BOOL +ReferenceProviderByHandle( + HANDLE Handle, + PCATALOG_ENTRY* Provider) +/* + * FUNCTION: Increments the reference count for a provider and returns a pointer to it + * ARGUMENTS: + * Handle = Handle for the provider + * Provider = Address of buffer to place pointer to provider + * RETURNS: + * TRUE if handle was valid, FALSE if not + */ +{ + PPROVIDER_HANDLE ProviderHandle; + + WS_DbgPrint(MAX_TRACE, ("Handle (0x%X) Provider (0x%X).\n", Handle, Provider)); + + EnterCriticalSection(&ProviderHandleTableLock); + + ProviderHandle = GetProviderByHandle(ProviderHandleTable, Handle); + + LeaveCriticalSection(&ProviderHandleTableLock); + + if (ProviderHandle) { + ReferenceProviderByPointer(ProviderHandle->Provider); + *Provider = ProviderHandle->Provider; + } + + return (ProviderHandle != NULL); +} + + +BOOL +CloseProviderHandle( + HANDLE Handle) +{ + PCATALOG_ENTRY Provider; + + WS_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", Handle)); + + EnterCriticalSection(&ProviderHandleTableLock); + + Provider = DeleteProviderHandle(ProviderHandleTable, Handle); + if (!Provider) + return FALSE; + + LeaveCriticalSection(&ProviderHandleTableLock); + + DereferenceProviderByPointer(Provider); + + return TRUE; +} + + +BOOL +InitProviderHandleTable(VOID) +{ + ProviderHandleTable = (PPROVIDER_HANDLE_BLOCK) + HeapAlloc(GlobalHeap, 0, sizeof(PROVIDER_HANDLE_BLOCK)); + if (!ProviderHandleTable) + return FALSE; + + ZeroMemory(ProviderHandleTable, sizeof(PROVIDER_HANDLE_BLOCK)); + + InitializeListHead(&ProviderHandleTable->Entry); + + InitializeCriticalSection(&ProviderHandleTableLock); + + return TRUE; +} + + +VOID +FreeProviderHandleTable(VOID) +{ + DeleteHandleTable(ProviderHandleTable); + + DeleteCriticalSection(&ProviderHandleTableLock); +} + +/* EOF */ diff --git a/lib/ws2_32/misc/ns.c b/lib/ws2_32/misc/ns.c new file mode 100644 index 0000000..61bf81b --- /dev/null +++ b/lib/ws2_32/misc/ns.c @@ -0,0 +1,515 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/ns.c + * PURPOSE: Namespace APIs + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +/* Name resolution APIs */ + +INT +EXPORT +WSAAddressToStringA( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + OUT LPSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAAddressToStringW( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAEnumNameSpaceProvidersA( + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSANAMESPACE_INFOA lpnspBuffer) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAEnumNameSpaceProvidersW( + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSANAMESPACE_INFOW lpnspBuffer) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAGetServiceClassInfoA( + IN LPGUID lpProviderId, + IN LPGUID lpServiceClassId, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSASERVICECLASSINFOA lpServiceClassInfo) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAGetServiceClassInfoW( + IN LPGUID lpProviderId, + IN LPGUID lpServiceClassId, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAGetServiceClassNameByClassIdA( + IN LPGUID lpServiceClassId, + OUT LPSTR lpszServiceClassName, + IN OUT LPDWORD lpdwBufferLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAGetServiceClassNameByClassIdW( + IN LPGUID lpServiceClassId, + OUT LPWSTR lpszServiceClassName, + IN OUT LPDWORD lpdwBufferLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAInstallServiceClassA( + IN LPWSASERVICECLASSINFOA lpServiceClassInfo) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAInstallServiceClassW( + IN LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSALookupServiceBeginA( + IN LPWSAQUERYSETA lpqsRestrictions, + IN DWORD dwControlFlags, + OUT LPHANDLE lphLookup) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSALookupServiceBeginW( + IN LPWSAQUERYSETW lpqsRestrictions, + IN DWORD dwControlFlags, + OUT LPHANDLE lphLookup) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSALookupServiceEnd( + IN HANDLE hLookup) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSALookupServiceNextA( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETA lpqsResults) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSALookupServiceNextW( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSARemoveServiceClass( + IN LPGUID lpServiceClassId) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSASetServiceA( + IN LPWSAQUERYSETA lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSASetServiceW( + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAStringToAddressA( + IN LPSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOA lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSAStringToAddressW( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength) +{ + UNIMPLEMENTED + + return 0; +} + + +/* WinSock 1.1 compatible name resolution APIs */ + +LPHOSTENT +EXPORT +gethostbyaddr( + IN CONST CHAR FAR* addr, + IN INT len, + IN INT type) +{ + UNIMPLEMENTED + + return (LPHOSTENT)NULL; +} + +LPHOSTENT +EXPORT +gethostbyname( + IN CONST CHAR FAR* name) +{ + UNIMPLEMENTED + + return (LPHOSTENT)NULL; +} + + +INT +EXPORT +gethostname( + OUT CHAR FAR* name, + IN INT namelen) +{ + UNIMPLEMENTED + + return 0; +} + + +LPPROTOENT +EXPORT +getprotobyname( + IN CONST CHAR FAR* name) +{ + UNIMPLEMENTED + + return (LPPROTOENT)NULL; +} + + +LPPROTOENT +EXPORT +getprotobynumber( + IN INT number) +{ + UNIMPLEMENTED + + return (LPPROTOENT)NULL; +} + +LPSERVENT +EXPORT +getservbyname( + IN CONST CHAR FAR* name, + IN CONST CHAR FAR* proto) +{ + UNIMPLEMENTED + + return (LPSERVENT)NULL; +} + + +LPSERVENT +EXPORT +getservbyport( + IN INT port, + IN CONST CHAR FAR* proto) +{ + UNIMPLEMENTED + + return (LPSERVENT)NULL; +} + + +ULONG +EXPORT +inet_addr( + IN CONST CHAR FAR* cp) +/* + * FUNCTION: Converts a string containing an IPv4 address to an unsigned long + * ARGUMENTS: + * cp = Pointer to string with address to convert + * RETURNS: + * Binary representation of IPv4 address, or INADDR_NONE + */ +{ + UINT i; + PCHAR p; + ULONG u = 0; + + p = (PCHAR)cp; + + if (strlen(p) == 0) + return INADDR_NONE; + + if (strcmp(p, " ") == 0) + return 0; + + for (i = 0; i <= 3; i++) { + u += (strtoul(p, &p, 0) << (i * 8)); + + if (strlen(p) == 0) + return u; + + if (p[0] != '.') + return INADDR_NONE; + + p++; + } + + return u; +} + + +CHAR FAR* +EXPORT +inet_ntoa( + IN IN_ADDR in) +{ + CHAR b[10]; + PCHAR p; + + p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa; + _itoa(in.S_un.S_addr & 0xFF, b, 10); + strcpy(p, b); + _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10); + strcat(p, "."); + strcat(p, b); + _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10); + strcat(p, "."); + strcat(p, b); + _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10); + strcat(p, "."); + strcat(p, b); + return (CHAR FAR*)p; +} + + +HANDLE +EXPORT +WSAAsyncGetHostByAddr( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* addr, + IN INT len, + IN INT type, + OUT CHAR FAR* buf, + IN INT buflen) +{ + UNIMPLEMENTED + + return (HANDLE)0; +} + + +HANDLE +EXPORT +WSAAsyncGetHostByName( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* name, + OUT CHAR FAR* buf, + IN INT buflen) +{ + UNIMPLEMENTED + + return (HANDLE)0; +} + + +HANDLE +EXPORT +WSAAsyncGetProtoByName( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* name, + OUT CHAR FAR* buf, + IN INT buflen) +{ + UNIMPLEMENTED + + return (HANDLE)0; +} + + +HANDLE +EXPORT +WSAAsyncGetProtoByNumber( + IN HWND hWnd, + IN UINT wMsg, + IN INT number, + OUT CHAR FAR* buf, + IN INT buflen) +{ + UNIMPLEMENTED + + return (HANDLE)0; +} + + +HANDLE +EXPORT +WSAAsyncGetServByName( + IN HWND hWnd, + IN UINT wMsg, + IN CONST CHAR FAR* name, + IN CONST CHAR FAR* proto, + OUT CHAR FAR* buf, + IN INT buflen) +{ + UNIMPLEMENTED + + return (HANDLE)0; +} + + +HANDLE +EXPORT +WSAAsyncGetServByPort( + IN HWND hWnd, + IN UINT wMsg, + IN INT port, + IN CONST CHAR FAR* proto, + OUT CHAR FAR* buf, + IN INT buflen) +{ + UNIMPLEMENTED + + return (HANDLE)0; +} + +/* EOF */ diff --git a/lib/ws2_32/misc/sndrcv.c b/lib/ws2_32/misc/sndrcv.c new file mode 100644 index 0000000..3f64254 --- /dev/null +++ b/lib/ws2_32/misc/sndrcv.c @@ -0,0 +1,280 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/sndrcv.c + * PURPOSE: Send/receive functions + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include + +INT +EXPORT +recv( + IN SOCKET s, + OUT CHAR FAR* buf, + IN INT len, + IN INT flags) +{ + DWORD BytesReceived; + WSABUF WSABuf; + + WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", + s, buf, len, flags)); + + WSABuf.len = len; + WSABuf.buf = (CHAR FAR*)buf; + + WSARecv(s, &WSABuf, 1, &BytesReceived, (LPDWORD)&flags, NULL, NULL); + + return BytesReceived; +} + + +INT +EXPORT +recvfrom( + IN SOCKET s, + OUT CHAR FAR* buf, + IN INT len, + IN INT flags, + OUT LPSOCKADDR from, + IN OUT INT FAR* fromlen) +{ + DWORD BytesReceived; + WSABUF WSABuf; + + WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", + s, buf, len, flags)); + + WSABuf.len = len; + WSABuf.buf = (CHAR FAR*)buf; + + WSARecvFrom(s, &WSABuf, 1, &BytesReceived, (LPDWORD)&flags, from, fromlen, NULL, NULL); + + return BytesReceived; +} + + +INT +EXPORT +send( + IN SOCKET s, + IN CONST CHAR FAR* buf, + IN INT len, + IN INT flags) +{ + DWORD BytesSent; + WSABUF WSABuf; + + WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", + s, buf, len, flags)); + + WSABuf.len = len; + WSABuf.buf = (CHAR FAR*)buf; + + return WSASend(s, &WSABuf, 1, &BytesSent, flags, NULL, NULL); +} + + +INT +EXPORT +sendto( + IN SOCKET s, + IN CONST CHAR FAR* buf, + IN INT len, + IN INT flags, + IN CONST LPSOCKADDR to, + IN INT tolen) +{ + DWORD BytesSent; + WSABUF WSABuf; + + WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", + s, buf, len, flags)); + + WSABuf.len = len; + WSABuf.buf = (CHAR FAR*)buf; + + return WSASendTo(s, &WSABuf, 1, &BytesSent, flags, to, tolen, NULL, NULL); +} + + +INT +EXPORT +WSARecv( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + PCATALOG_ENTRY Provider; + INT Errno; + INT Code; + + WS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + assert(Provider->ProcTable.lpWSPRecv); + + Code = Provider->ProcTable.lpWSPRecv(s, lpBuffers, dwBufferCount, + lpNumberOfBytesRecvd, lpFlags, lpOverlapped, + lpCompletionRoutine, NULL /* lpThreadId */, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Code == SOCKET_ERROR) + WSASetLastError(Errno); + + return Code; +} + + +INT +EXPORT +WSARecvDisconnect( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSARecvFrom( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromlen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + PCATALOG_ENTRY Provider; + INT Errno; + INT Code; + + WS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + assert(Provider->ProcTable.lpWSPRecvFrom); + + Code = Provider->ProcTable.lpWSPRecvFrom(s, lpBuffers, dwBufferCount, + lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, + lpCompletionRoutine, NULL /* lpThreadId */, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Code == SOCKET_ERROR) + WSASetLastError(Errno); + + return Code; +} + + +INT +EXPORT +WSASend( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + PCATALOG_ENTRY Provider; + INT Errno; + INT Code; + + WS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + assert(Provider->ProcTable.lpWSPSend); + + Code = Provider->ProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, + lpNumberOfBytesSent, dwFlags, lpOverlapped, + lpCompletionRoutine, NULL /* lpThreadId */, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Code == SOCKET_ERROR) + WSASetLastError(Errno); + + return Code; +} + + +INT +EXPORT +WSASendDisconnect( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +EXPORT +WSASendTo( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST LPSOCKADDR lpTo, + IN INT iToLen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + PCATALOG_ENTRY Provider; + INT Errno; + INT Code; + + WS_DbgPrint(MAX_TRACE, ("Called.\n")); + + if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) { + WSASetLastError(WSAENOTSOCK); + return SOCKET_ERROR; + } + + assert(Provider->ProcTable.lpWSPSendTo); + + Code = Provider->ProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, + lpNumberOfBytesSent, dwFlags, lpTo, iToLen, lpOverlapped, + lpCompletionRoutine, NULL /* lpThreadId */, &Errno); + + DereferenceProviderByPointer(Provider); + + if (Code == SOCKET_ERROR) + WSASetLastError(Errno); + + return Code; +} + +/* EOF */ diff --git a/lib/ws2_32/misc/stubs.c b/lib/ws2_32/misc/stubs.c new file mode 100644 index 0000000..f07ee3f --- /dev/null +++ b/lib/ws2_32/misc/stubs.c @@ -0,0 +1,457 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/stubs.c + * PURPOSE: Stubs + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include + +INT +EXPORT +getpeername( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT INT FAR* namelen) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +getsockname( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT INT FAR* namelen) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +getsockopt( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT INT FAR* optlen) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +ioctlsocket( + IN SOCKET s, + IN LONG cmd, + IN OUT ULONG FAR* argp) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +setsockopt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +shutdown( + IN SOCKET s, + IN INT how) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSAAsyncSelect( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSACancelBlockingCall(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSADuplicateSocketA( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOA lpProtocolInfo) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSADuplicateSocketW( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSAEnumProtocolsA( + IN LPINT lpiProtocols, + OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSAEnumProtocolsW( + IN LPINT lpiProtocols, + OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + UNIMPLEMENTED + + return 0; +} + +BOOL +EXPORT +WSAGetOverlappedResult( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags) +{ + UNIMPLEMENTED + + return 0; +} + +BOOL +EXPORT +WSAGetQOSByName( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS) +{ + UNIMPLEMENTED + + return FALSE; +} + +INT +EXPORT +WSAHtonl( + IN SOCKET s, + IN ULONG hostLONG, + OUT ULONG FAR* lpnetlong) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSAHtons( + IN SOCKET s, + IN USHORT hostshort, + OUT USHORT FAR* lpnetshort) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSAIoctl( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + UNIMPLEMENTED + + return 0; +} + +BOOL +EXPORT +WSAIsBlocking(VOID) +{ + UNIMPLEMENTED + + return FALSE; +} + +SOCKET +EXPORT +WSAJoinLeaf( + IN SOCKET s, + IN CONST LPSOCKADDR name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags) +{ + UNIMPLEMENTED + + return INVALID_SOCKET; +} + +INT +EXPORT +WSANtohl( + IN SOCKET s, + IN ULONG netlong, + OUT ULONG FAR* lphostlong) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSANtohs( + IN SOCKET s, + IN USHORT netshort, + OUT USHORT FAR* lphostshort) +{ + UNIMPLEMENTED + + return 0; +} + +FARPROC +EXPORT +WSASetBlockingHook( + IN FARPROC lpBlockFunc) +{ + UNIMPLEMENTED + + return (FARPROC)0; +} + +INT +EXPORT +WSAUnhookBlockingHook(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSAProviderConfigChange( + IN OUT LPHANDLE lpNotificationHandle, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSACancelAsyncRequest( + IN HANDLE hAsyncTaskHandle) +{ + UNIMPLEMENTED + + return 0; +} + +INT +#if 0 +PASCAL FAR +#else +EXPORT +#endif +__WSAFDIsSet(SOCKET s, LPFD_SET set) +{ + UNIMPLEMENTED + + return 0; +} + + +/* WinSock Service Provider support functions */ + +INT +EXPORT +WPUCompleteOverlappedRequest( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + IN DWORD dwError, + IN DWORD cbTransferred, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSPStartup( + IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCDeinstallProvider( + IN LPGUID lpProviderId, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCEnumProtocols( + IN LPINT lpiProtocols, + OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCGetProviderPath( + IN LPGUID lpProviderId, + OUT LPWSTR lpszProviderDllPath, + IN OUT LPINT lpProviderDllPathLen, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCInstallProvider( + IN CONST LPGUID lpProviderId, + IN CONST LPWSTR lpszProviderDllPath, + IN CONST LPWSAPROTOCOL_INFOW lpProtocolInfoList, + IN DWORD dwNumberOfEntries, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCEnableNSProvider( + IN LPGUID lpProviderId, + IN BOOL fEnable) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCInstallNameSpace( + IN LPWSTR lpszIdentifier, + IN LPWSTR lpszPathName, + IN DWORD dwNameSpace, + IN DWORD dwVersion, + IN LPGUID lpProviderId) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCUnInstallNameSpace( + IN LPGUID lpProviderId) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WSCWriteProviderOrder( + IN LPDWORD lpwdCatalogEntryId, + IN DWORD dwNumberOfEntries) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/lib/ws2_32/misc/upcall.c b/lib/ws2_32/misc/upcall.c new file mode 100644 index 0000000..227f59e --- /dev/null +++ b/lib/ws2_32/misc/upcall.c @@ -0,0 +1,220 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 DLL + * FILE: misc/upcall.c + * PURPOSE: Upcall functions + * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISIONS: + * CSH 01/09-2000 Created + */ +#include +#include + +BOOL +WSPAPI +WPUCloseEvent( + IN WSAEVENT hEvent, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return FALSE; +} + + +INT +WSPAPI +WPUCloseSocketHandle( + IN SOCKET s, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WPUCloseThread( + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +WSAEVENT +WSPAPI +WPUCreateEvent( + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return (WSAEVENT)0; +} + + +SOCKET +WSPAPI +WPUCreateSocketHandle( + IN DWORD dwCatalogEntryId, + IN DWORD dwContext, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return (SOCKET)0; +} + + +SOCKET +WSPAPI +WPUFDIsSet( + IN SOCKET s, + IN LPFD_SET set) +{ + UNIMPLEMENTED + + return (SOCKET)0; +} + + +INT +WSPAPI +WPUGetProviderPath( + IN LPGUID lpProviderId, + OUT LPWSTR lpszProviderDllPath, + IN OUT LPINT lpProviderDllPathLen, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +SOCKET +WSPAPI +WPUModifyIFSHandle( + IN DWORD dwCatalogEntryId, + IN SOCKET ProposedHandle, + OUT LPINT lpErrno) +{ + PCATALOG_ENTRY Provider; + SOCKET Socket; + + WS_DbgPrint(MAX_TRACE, ("dwCatalogEntryId (%d) ProposedHandle (0x%X).\n", + dwCatalogEntryId, ProposedHandle)); + + Provider = LocateProviderById(dwCatalogEntryId); + if (!Provider) { + WS_DbgPrint(MIN_TRACE, ("Provider with catalog entry id (%d) was not found.\n", + dwCatalogEntryId)); + *lpErrno = WSAEINVAL; + return INVALID_SOCKET; + } + + Socket = (SOCKET)CreateProviderHandle( + ProposedHandle, + Provider); + + *lpErrno = NO_ERROR; + + return Socket; +} + + +INT +WSPAPI +WPUOpenCurrentThread( + OUT LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +BOOL +WSPAPI +WPUPostMessage( + IN HWND hWnd, + IN UINT Msg, + IN WPARAM wParam, + IN LPARAM lParam) +{ + UNIMPLEMENTED + + return FALSE; +} + + +INT +WSPAPI +WPUQueryBlockingCallback( + IN DWORD dwCatalogEntryId, + OUT LPBLOCKINGCALLBACK FAR* lplpfnCallback, + OUT LPDWORD lpdwContext, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WPUQuerySocketHandleContext( + IN SOCKET s, + OUT LPDWORD lpContext, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +INT +WSPAPI +WPUQueueApc( + IN LPWSATHREADID lpThreadId, + IN LPWSAUSERAPC lpfnUserApc, + IN DWORD dwContext, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return 0; +} + + +BOOL +WSPAPI +WPUResetEvent( + IN WSAEVENT hEvent, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return FALSE; +} + + +BOOL +WSPAPI +WPUSetEvent( + IN WSAEVENT hEvent, + OUT LPINT lpErrno) +{ + UNIMPLEMENTED + + return FALSE; +} + +/* EOF */ diff --git a/lib/ws2_32/ws2_32.def b/lib/ws2_32/ws2_32.def new file mode 100644 index 0000000..4ccfc7d --- /dev/null +++ b/lib/ws2_32/ws2_32.def @@ -0,0 +1,116 @@ +; WS2_32.DLL - Windows Sockets 2 DLL + +LIBRARY ws2_32.dll + +EXPORTS +;WEP +WPUCompleteOverlappedRequest@20 +WSAAccept@20 +WSAAddressToStringA@20 +WSAAddressToStringW@20 +WSAAsyncGetHostByAddr@28 +WSAAsyncGetHostByName@20 +WSAAsyncGetProtoByName@20 +WSAAsyncGetProtoByNumber@20 +WSAAsyncGetServByName@24 +WSAAsyncGetServByPort@24 +WSAAsyncSelect@16 +WSACancelAsyncRequest@4 +WSACancelBlockingCall@0 +WSACleanup@0 +WSACloseEvent@4 +WSAConnect@28 +WSACreateEvent@0 +WSADuplicateSocketA@12 +WSADuplicateSocketW@12 +WSAEnumNameSpaceProvidersA@8 +WSAEnumNameSpaceProvidersW@8 +WSAEnumNetworkEvents@12 +WSAEnumProtocolsA@12 +WSAEnumProtocolsW@12 +WSAEventSelect@12 +WSAGetLastError@0 +WSAGetOverlappedResult@20 +WSAGetQOSByName@12 +WSAGetServiceClassInfoA@16 +WSAGetServiceClassInfoW@16 +WSAGetServiceClassNameByClassIdA@12 +WSAGetServiceClassNameByClassIdW@12 +WSAHtonl@12 +WSAHtons@12 +WSAInstallServiceClassA@4 +WSAInstallServiceClassW@4 +WSAIoctl@36 +WSAIsBlocking@0 +WSAJoinLeaf@32 +WSALookupServiceBeginA@12 +WSALookupServiceBeginW@12 +WSALookupServiceEnd@4 +WSALookupServiceNextA@16 +WSALookupServiceNextW@16 +WSANtohl@12 +WSANtohs@12 +WSAProviderConfigChange@12 +WSARecv@28 +WSARecvDisconnect@8 +WSARecvFrom@36 +WSARemoveServiceClass@4 +WSAResetEvent@4 +WSASend@28 +WSASendDisconnect@8 +WSASendTo@36 +WSASetBlockingHook@4 +WSASetEvent@4 +WSASetLastError@4 +WSASetServiceA@12 +WSASetServiceW@12 +WSASocketA@24 +WSASocketW@24 +WSAStartup@8 +WSAStringToAddressA@20 +WSAStringToAddressW@20 +WSAUnhookBlockingHook@0 +WSAWaitForMultipleEvents@20 +;WSApSetPostRoutine +WSCDeinstallProvider@8 +WSCEnableNSProvider@8 +WSCEnumProtocols@16 +WSCGetProviderPath@16 +WSCInstallNameSpace@20 +WSCInstallProvider@20 +WSCUnInstallNameSpace@4 +;WSCWriteNameSpaceOrder +WSCWriteProviderOrder@8 +__WSAFDIsSet@8 +accept@12 +bind@12 +closesocket@4 +connect@12 +gethostbyaddr@12 +gethostbyname@4 +gethostname@8 +getpeername@12 +getprotobyname@4 +getprotobynumber@4 +getservbyname@8 +getservbyport@8 +getsockname@12 +getsockopt@20 +htonl@4 +htons@4 +inet_addr@4 +inet_ntoa@4 +ioctlsocket@12 +listen@8 +ntohl@4 +ntohs@4 +recv@16 +recvfrom@24 +select@20 +send@16 +sendto@24 +setsockopt@20 +shutdown@8 +socket@12 + +; EOF diff --git a/lib/ws2_32/ws2_32.edf b/lib/ws2_32/ws2_32.edf new file mode 100644 index 0000000..8f6b723 --- /dev/null +++ b/lib/ws2_32/ws2_32.edf @@ -0,0 +1,116 @@ +; WS2_32.DLL - Windows Sockets 2 DLL + +LIBRARY ws2_32.dll + +EXPORTS +;WEP +WPUCompleteOverlappedRequest=WPUCompleteOverlappedRequest@20 +WSAAccept=WSAAccept@20 +WSAAddressToStringA=WSAAddressToStringA@20 +WSAAddressToStringW=WSAAddressToStringW@20 +WSAAsyncGetHostByAddr=WSAAsyncGetHostByAddr@28 +WSAAsyncGetHostByName=WSAAsyncGetHostByName@20 +WSAAsyncGetProtoByName=WSAAsyncGetProtoByName@20 +WSAAsyncGetProtoByNumber=WSAAsyncGetProtoByNumber@20 +WSAAsyncGetServByName=WSAAsyncGetServByName@24 +WSAAsyncGetServByPort=WSAAsyncGetServByPort@24 +WSAAsyncSelect=WSAAsyncSelect@16 +WSACancelAsyncRequest=WSACancelAsyncRequest@4 +WSACancelBlockingCall=WSACancelBlockingCall@0 +WSACleanup=WSACleanup@0 +WSACloseEvent=WSACloseEvent@4 +WSAConnect=WSAConnect@28 +WSACreateEvent=WSACreateEvent@0 +WSADuplicateSocketA=WSADuplicateSocketA@12 +WSADuplicateSocketW=WSADuplicateSocketW@12 +WSAEnumNameSpaceProvidersA=WSAEnumNameSpaceProvidersA@8 +WSAEnumNameSpaceProvidersW=WSAEnumNameSpaceProvidersW@8 +WSAEnumNetworkEvents=WSAEnumNetworkEvents@12 +WSAEnumProtocolsA=WSAEnumProtocolsA@12 +WSAEnumProtocolsW=WSAEnumProtocolsW@12 +WSAEventSelect=WSAEventSelect@12 +WSAGetLastError=WSAGetLastError@0 +WSAGetOverlappedResult=WSAGetOverlappedResult@20 +WSAGetQOSByName=WSAGetQOSByName@12 +WSAGetServiceClassInfoA=WSAGetServiceClassInfoA@16 +WSAGetServiceClassInfoW=WSAGetServiceClassInfoW@16 +WSAGetServiceClassNameByClassIdA=WSAGetServiceClassNameByClassIdA@12 +WSAGetServiceClassNameByClassIdW=WSAGetServiceClassNameByClassIdW@12 +WSAHtonl=WSAHtonl@12 +WSAHtons=WSAHtons@12 +WSAInstallServiceClassA=WSAInstallServiceClassA@4 +WSAInstallServiceClassW=WSAInstallServiceClassW@4 +WSAIoctl=WSAIoctl@36 +WSAIsBlocking=WSAIsBlocking@0 +WSAJoinLeaf=WSAJoinLeaf@32 +WSALookupServiceBeginA=WSALookupServiceBeginA@12 +WSALookupServiceBeginW=WSALookupServiceBeginW@12 +WSALookupServiceEnd=WSALookupServiceEnd@4 +WSALookupServiceNextA=WSALookupServiceNextA@16 +WSALookupServiceNextW=WSALookupServiceNextW@16 +WSANtohl=WSANtohl@12 +WSANtohs=WSANtohs@12 +WSAProviderConfigChange=WSAProviderConfigChange@12 +WSARecv=WSARecv@28 +WSARecvDisconnect=WSARecvDisconnect@8 +WSARecvFrom=WSARecvFrom@36 +WSARemoveServiceClass=WSARemoveServiceClass@4 +WSAResetEvent=WSAResetEvent@4 +WSASend=WSASend@28 +WSASendDisconnect=WSASendDisconnect@8 +WSASendTo=WSASendTo@36 +WSASetBlockingHook=WSASetBlockingHook@4 +WSASetEvent=WSASetEvent@4 +WSASetLastError=WSASetLastError@4 +WSASetServiceA=WSASetServiceA@12 +WSASetServiceW=WSASetServiceW@12 +WSASocketA=WSASocketA@24 +WSASocketW=WSASocketW@24 +WSAStartup=WSAStartup@8 +WSAStringToAddressA=WSAStringToAddressA@20 +WSAStringToAddressW=WSAStringToAddressW@20 +WSAUnhookBlockingHook=WSAUnhookBlockingHook@0 +WSAWaitForMultipleEvents=WSAWaitForMultipleEvents@20 +;WSApSetPostRoutine +WSCDeinstallProvider=WSCDeinstallProvider@8 +WSCEnableNSProvider=WSCEnableNSProvider@8 +WSCEnumProtocols=WSCEnumProtocols@16 +WSCGetProviderPath=WSCGetProviderPath@16 +WSCInstallNameSpace=WSCInstallNameSpace@20 +WSCInstallProvider=WSCInstallProvider@20 +WSCUnInstallNameSpace=WSCUnInstallNameSpace@4 +;WSCWriteNameSpaceOrder +WSCWriteProviderOrder=WSCWriteProviderOrder@8 +__WSAFDIsSet=__WSAFDIsSet@8 +accept=accept@12 +bind=bind@12 +closesocket=closesocket@4 +connect=connect@12 +gethostbyaddr=gethostbyaddr@12 +gethostbyname=gethostbyname@4 +gethostname=gethostname@8 +getpeername=getpeername@12 +getprotobyname=getprotobyname@4 +getprotobynumber=getprotobynumber@4 +getservbyname=getservbyname@8 +getservbyport=getservbyport@8 +getsockname=getsockname@12 +getsockopt=getsockopt@20 +htonl=htonl@4 +htons=htons@4 +inet_addr=inet_addr@4 +inet_ntoa=inet_ntoa@4 +ioctlsocket=ioctlsocket@12 +listen=listen@8 +ntohl=ntohl@4 +ntohs=ntohs@4 +recv=recv@16 +recvfrom=recvfrom@24 +select=select@20 +send=send@16 +sendto=sendto@24 +setsockopt=setsockopt@20 +shutdown=shutdown@8 +socket=socket@12 + +; EOF diff --git a/lib/ws2_32/ws2_32.rc b/lib/ws2_32/ws2_32.rc new file mode 100644 index 0000000..723083e --- /dev/null +++ b/lib/ws2_32/ws2_32.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Windows Sockets 2 DLL\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ws2_32\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ws2_32.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/ws2_32/ws2_32_specs b/lib/ws2_32/ws2_32_specs new file mode 100644 index 0000000..02ba08d --- /dev/null +++ b/lib/ws2_32/ws2_32_specs @@ -0,0 +1,78 @@ +*asm: + + +*asm_final: + + +*cpp: +-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} + +*cc1: +%(cc1_spec) + +*cc1plus: + + +*endfile: + + +*link: +%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMain@12} + +*lib: + + +*libgcc: +-lgcc + +*startfile: + + +*switches_need_spaces: + + +*signed_char: +%{funsigned-char:-D__CHAR_UNSIGNED__} + +*predefines: +-Di386 -D_WIN32 -DWIN32 -D__WIN32__ -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1 -D__stdcall=__attribute__((__stdcall__)) -D_stdcall=__attribute__((__stdcall__)) -D__cdecl=__attribute__((__cdecl__)) -D__declspec(x)=__attribute__((x)) -Asystem(winnt) -Acpu(i386) -Amachine(i386) + +*cross_compile: +1 + +*version: +egcs-2.91.57 + +*multilib: +. ; + +*multilib_defaults: + + +*multilib_extra: + + +*multilib_matches: + + +*linker: +collect2 + +*cpp_486: +%{!ansi:-Di486} -D__i486 -D__i486__ + +*cpp_586: +%{!ansi:-Di586 -Dpentium} -D__i586 -D__i586__ -D__pentium -D__pentium__ + +*cpp_686: +%{!ansi:-Di686 -Dpentiumpro} -D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__ + +*cpp_cpu_default: +%(cpp_586) + +*cpp_cpu: +-Acpu(i386) -Amachine(i386) %{!ansi:-Di386} -D__i386 -D__i386__ %{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} %{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} %{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} %{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}} + +*cc1_cpu: +%{!mcpu*: %{m386:-mcpu=i386 -march=i386} %{mno-486:-mcpu=i386 -march=i386} %{m486:-mcpu=i486 -march=i486} %{mno-386:-mcpu=i486 -march=i486} %{mno-pentium:-mcpu=i486 -march=i486} %{mpentium:-mcpu=pentium} %{mno-pentiumpro:-mcpu=pentium} %{mpentiumpro:-mcpu=pentiumpro}} + diff --git a/lib/ws2help/.cvsignore b/lib/ws2help/.cvsignore new file mode 100644 index 0000000..ac4ba22 --- /dev/null +++ b/lib/ws2help/.cvsignore @@ -0,0 +1,23 @@ +ws2help.a +ws2help.dll +ws2help.nostrip.dll +ws2help.coff +base.tmp +junk.tmp +temp.exp +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/ws2help/debug.h b/lib/ws2help/debug.h new file mode 100644 index 0000000..13a623f --- /dev/null +++ b/lib/ws2help/debug.h @@ -0,0 +1,65 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 Helper DLL for TCP/IP + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define WSH_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { WSH_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define WSH_DbgPrint(_t_, _x_) + +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + WSH_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \ + please try again later.\n", __FILE__, __LINE__, __FUNCTION__)); + +#define CHECKPOINT \ + WSH_DbgPrint(MIN_TRACE, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/ws2help/makefile b/lib/ws2help/makefile new file mode 100644 index 0000000..3bb2aa4 --- /dev/null +++ b/lib/ws2help/makefile @@ -0,0 +1,19 @@ +# $Id: makefile + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = ws2help + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = -DUNICODE + +TARGET_SDKLIBS = ntdll.a kernel32.a ws2_32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/ws2help/ws2help.c b/lib/ws2help/ws2help.c new file mode 100644 index 0000000..392d78b --- /dev/null +++ b/lib/ws2help/ws2help.c @@ -0,0 +1,327 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 Helper DLL for TCP/IP + * FILE: ws2help.c + * PURPOSE: DLL entry + * PROGRAMMERS: Robert D. Dickenson (robertdickenson@users.sourceforge.net) + * REVISIONS: + * RDD 18/06-2002 Created + */ +#include "ws2help.h" + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + +/* To make the linker happy */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +BOOL +EXPORT +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + WSH_DbgPrint(MIN_TRACE, ("DllMain of ws2help.dll\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications + so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + +INT +EXPORT +WahCloseApcHelper( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCloseHandleHelper( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCloseNotificationHelper( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCloseSocketHandle( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCloseThread( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCompleteRequest( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCreateHandleContextTable( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCreateNotificationTable( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahCreateSocketHandle( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahDestroyHandleContextTable( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahDisableNonIFSHandleSupport( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahEnableNonIFSHandleSupport( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahEnumerateHandleContexts( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahInsertHandleContext( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahNotifyAllProcesses( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahOpenApcHelper( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahOpenCurrentThread( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahOpenHandleHelper( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahOpenNotificationHandleHelper( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahQueueUserApc( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahReferenceContextByHandle( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahRemoveHandleContext( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +INT +EXPORT +WahWaitForNotification( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle + ) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/lib/ws2help/ws2help.def b/lib/ws2help/ws2help.def new file mode 100644 index 0000000..1c94673 --- /dev/null +++ b/lib/ws2help/ws2help.def @@ -0,0 +1,30 @@ +; WS2HELP.DLL - Windows Sockets 2 Helper DLL for TCP/IP + +LIBRARY ws2help.dll + +EXPORTS +WahCloseApcHelper@8 +WahCloseHandleHelper@8 +WahCloseNotificationHelper@8 +WahCloseSocketHandle@8 +WahCloseThread@8 +WahCompleteRequest@8 +WahCreateHandleContextTable@8 +WahCreateNotificationTable@8 +WahCreateSocketHandle@8 +WahDestroyHandleContextTable@8 +WahDisableNonIFSHandleSupport@8 +WahEnableNonIFSHandleSupport@8 +WahEnumerateHandleContexts@8 +WahInsertHandleContext@8 +WahNotifyAllProcesses@8 +WahOpenApcHelper@8 +WahOpenCurrentThread@8 +WahOpenHandleHelper@8 +WahOpenNotificationHandleHelper@8 +WahQueueUserApc@8 +WahReferenceContextByHandle@8 +WahRemoveHandleContext@8 +WahWaitForNotification@8 + +; EOF diff --git a/lib/ws2help/ws2help.edf b/lib/ws2help/ws2help.edf new file mode 100644 index 0000000..1e8a0a4 --- /dev/null +++ b/lib/ws2help/ws2help.edf @@ -0,0 +1,30 @@ +; WS2HELP.DLL - Windows Sockets 2 Helper DLL for TCP/IP + +LIBRARY ws2help.dll + +EXPORTS +WahCloseApcHelper=WahCloseApcHelper@8 +WahCloseHandleHelper=WahCloseHandleHelper@8 +WahCloseNotificationHelper=WahCloseNotificationHelper@8 +WahCloseSocketHandle=WahCloseSocketHandle@8 +WahCloseThread=WahCloseThread@8 +WahCompleteRequest=WahCompleteRequest@8 +WahCreateHandleContextTable=WahCreateHandleContextTable@8 +WahCreateNotificationTable=WahCreateNotificationTable@8 +WahCreateSocketHandle=WahCreateSocketHandle@8 +WahDestroyHandleContextTable=WahDestroyHandleContextTable@8 +WahDisableNonIFSHandleSupport=WahDisableNonIFSHandleSupport@8 +WahEnableNonIFSHandleSupport=WahEnableNonIFSHandleSupport@8 +WahEnumerateHandleContexts=WahEnumerateHandleContexts@8 +WahInsertHandleContext=WahInsertHandleContext@8 +WahNotifyAllProcesses=WahNotifyAllProcesses@8 +WahOpenApcHelper=WahOpenApcHelper@8 +WahOpenCurrentThread=WahOpenCurrentThread@8 +WahOpenHandleHelper=WahOpenHandleHelper@8 +WahOpenNotificationHandleHelper=WahOpenNotificationHandleHelper@8 +WahQueueUserApc=WahQueueUserApc@8 +WahReferenceContextByHandle=WahReferenceContextByHandle@8 +WahRemoveHandleContext=WahRemoveHandleContext@8 +WahWaitForNotification=WahWaitForNotification@8 + +; EOF diff --git a/lib/ws2help/ws2help.h b/lib/ws2help/ws2help.h new file mode 100644 index 0000000..3f875b6 --- /dev/null +++ b/lib/ws2help/ws2help.h @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 Helper DLL for TCP/IP + * FILE: include/ws2help.h + * PURPOSE: WinSock 2 Helper DLL for TCP/IP header + */ +#ifndef __WS2HELP_H +#define __WS2HELP_H + +#include +#include +#include +#include + +#define EXPORT STDCALL + +#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') + + +#endif /* __WS2HELP_H */ + +/* EOF */ diff --git a/lib/ws2help/ws2help.rc b/lib/ws2help/ws2help.rc new file mode 100644 index 0000000..a2aad15 --- /dev/null +++ b/lib/ws2help/ws2help.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Windows Sockets 2 Helper API\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ws2help\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ws2help.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/lib/wshirda/.cvsignore b/lib/wshirda/.cvsignore new file mode 100644 index 0000000..d699672 --- /dev/null +++ b/lib/wshirda/.cvsignore @@ -0,0 +1,23 @@ +wshirda.a +wshirda.dll +wshirda.nostrip.dll +wshirda.coff +base.tmp +junk.tmp +temp.exp +*.sys +*.exe +*.dll +*.cpl +*.a +*.o +*.d +*.coff +*.dsp +*.dsw +*.aps +*.ncb +*.opt +*.sym +*.plg +*.bak diff --git a/lib/wshirda/debug.h b/lib/wshirda/debug.h new file mode 100644 index 0000000..13a623f --- /dev/null +++ b/lib/wshirda/debug.h @@ -0,0 +1,65 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 Helper DLL for TCP/IP + * FILE: include/debug.h + * PURPOSE: Debugging support macros + * DEFINES: DBG - Enable debug output + * NASSERT - Disable assertions + */ +#ifndef __DEBUG_H +#define __DEBUG_H + +#define NORMAL_MASK 0x000000FF +#define SPECIAL_MASK 0xFFFFFF00 +#define MIN_TRACE 0x00000001 +#define MID_TRACE 0x00000002 +#define MAX_TRACE 0x00000003 + +#define DEBUG_ULTRA 0xFFFFFFFF + +#ifdef DBG + +extern DWORD DebugTraceLevel; + +#define WSH_DbgPrint(_t_, _x_) \ + if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ + ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ + DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x_; \ + } + +#ifdef ASSERT +#undef ASSERT +#endif + +#ifdef NASSERT +#define ASSERT(x) +#else /* NASSERT */ +#define ASSERT(x) if (!(x)) { WSH_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } +#endif /* NASSERT */ + +#else /* DBG */ + +#define WSH_DbgPrint(_t_, _x_) + +#define ASSERT(x) + +#endif /* DBG */ + + +#define assert(x) ASSERT(x) +#define assert_irql(x) ASSERT_IRQL(x) + + +#define UNIMPLEMENTED \ + WSH_DbgPrint(MIN_TRACE, ("(%s:%d)(%s) is unimplemented, \ + please try again later.\n", __FILE__, __LINE__, __FUNCTION__)); + +#define CHECKPOINT \ + WSH_DbgPrint(MIN_TRACE, ("\n")); + +#define CP CHECKPOINT + +#endif /* __DEBUG_H */ + +/* EOF */ diff --git a/lib/wshirda/makefile b/lib/wshirda/makefile new file mode 100644 index 0000000..76a240c --- /dev/null +++ b/lib/wshirda/makefile @@ -0,0 +1,19 @@ +# $Id: makefile + +PATH_TO_TOP = ../.. + +TARGET_TYPE = dynlink + +TARGET_NAME = wshirda + +TARGET_BASE = 0x777c0000 + +TARGET_CFLAGS = -DUNICODE + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/lib/wshirda/wshirda.c b/lib/wshirda/wshirda.c new file mode 100644 index 0000000..4976055 --- /dev/null +++ b/lib/wshirda/wshirda.c @@ -0,0 +1,206 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 IRDA Helper DLL + * FILE: wshirda.c + * PURPOSE: DLL entry + * PROGRAMMERS: Robert D. Dickenson (robertdickenson@users.sourceforge.net) + * REVISIONS: + * RDD 18/06-2002 Created + */ +#include "wshirda.h" + +#ifdef DBG + +/* See debug.h for debug/trace constants */ +DWORD DebugTraceLevel = MAX_TRACE; + +#endif /* DBG */ + +/* To make the linker happy */ +VOID STDCALL KeBugCheck (ULONG BugCheckCode) {} + + +BOOL +EXPORT +DllMain(HANDLE hInstDll, + ULONG dwReason, + PVOID Reserved) +{ + WSH_DbgPrint(MIN_TRACE, ("DllMain of wshirda.dll\n")); + + switch (dwReason) { + case DLL_PROCESS_ATTACH: + /* Don't need thread attach notifications + so disable them to improve performance */ + DisableThreadLibraryCalls(hInstDll); + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +INT +WINAPI +WSHEnumProtocols( + IN LPINT lpiProtocols OPTIONAL, + IN LPWSTR lpTransportKeyName, + IN OUT LPVOID lpProtocolBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHGetProviderGuid( + IN LPWSTR ProviderName, + OUT LPGUID ProviderGuid) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHGetSockaddrType( + IN PSOCKADDR Sockaddr, + IN DWORD SockaddrLength, + OUT PSOCKADDR_INFO SockaddrInfo) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHGetSocketInformation( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + OUT PCHAR OptionValue, + OUT INT OptionLength) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHGetWSAProtocolInfo( + IN LPWSTR ProviderName, + OUT LPWSAPROTOCOL_INFOW *ProtocolInfo, + OUT LPDWORD ProtocolInfoEntries) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHGetWildcardSockaddr( + IN PVOID HelperDllSocketContext, + OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +WINAPI +WSHGetWinsockMapping( + OUT PWINSOCK_MAPPING Mapping, + IN DWORD MappingLength) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHIoctl( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD IoControlCode, + IN LPVOID InputBuffer, + IN DWORD InputBufferLength, + IN LPVOID OutputBuffer, + IN DWORD OutputBufferLength, + OUT LPDWORD NumberOfBytesReturned, + IN LPWSAOVERLAPPED Overlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine, + OUT LPBOOL NeedsCompletion) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHNotify( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN DWORD NotifyEvent) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHOpenSocket( + IN OUT PINT AddressFamily, + IN OUT PINT SocketType, + IN OUT PINT Protocol, + OUT PUNICODE_STRING TransportDeviceName, + OUT PVOID HelperDllSocketContext, + OUT PDWORD NotificationEvents) +{ + UNIMPLEMENTED + + return 0; +} + +INT +WINAPI +WSHSetSocketInformation( + IN PVOID HelperDllSocketContext, + IN SOCKET SocketHandle, + IN HANDLE TdiAddressObjectHandle, + IN HANDLE TdiConnectionObjectHandle, + IN INT Level, + IN INT OptionName, + IN PCHAR OptionValue, + IN INT OptionLength) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/lib/wshirda/wshirda.def b/lib/wshirda/wshirda.def new file mode 100644 index 0000000..184d64c --- /dev/null +++ b/lib/wshirda/wshirda.def @@ -0,0 +1,19 @@ +; WSHIRDA.DLL - Windows Sockets 2 IRDA Helper DLL + +LIBRARY wshirda.dll + +EXPORTS + +WSHEnumProtocols@16 +WSHGetProviderGuid@8 +WSHGetSockaddrType@12 +WSHGetSocketInformation@32 +WSHGetWSAProtocolInfo@12 +WSHGetWildcardSockaddr@12 +WSHGetWinsockMapping@8 +WSHIoctl@52 +WSHNotify@20 +WSHOpenSocket@24 +WSHSetSocketInformation@32 + +; EOF diff --git a/lib/wshirda/wshirda.edf b/lib/wshirda/wshirda.edf new file mode 100644 index 0000000..a3d8825 --- /dev/null +++ b/lib/wshirda/wshirda.edf @@ -0,0 +1,18 @@ +; WSHIRDA.DLL - Windows Sockets 2 IRDA Helper DLL + +LIBRARY wshirda.dll + +EXPORTS +WSHEnumProtocols=WSHEnumProtocols@16 +WSHGetProviderGuid=WSHGetProviderGuid@8 +WSHGetSockaddrType=WSHGetSockaddrType@12 +WSHGetSocketInformation=WSHGetSocketInformation@32 +WSHGetWSAProtocolInfo=WSHGetWSAProtocolInfo@12 +WSHGetWildcardSockaddr=WSHGetWildcardSockaddr@12 +WSHGetWinsockMapping=WSHGetWinsockMapping@8 +WSHIoctl=WSHIoctl@52 +WSHNotify=WSHNotify@20 +WSHOpenSocket=WSHOpenSocket@24 +WSHSetSocketInformation=WSHSetSocketInformation@32 + +; EOF diff --git a/lib/wshirda/wshirda.h b/lib/wshirda/wshirda.h new file mode 100644 index 0000000..ffc4dfc --- /dev/null +++ b/lib/wshirda/wshirda.h @@ -0,0 +1,22 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 IRDA Helper DLL + * FILE: include/ws2help.h + * PURPOSE: WinSock 2 IRDA Helper DLL + */ +#ifndef __WSHIRDA_H +#define __WSHIRDA_H + +#include +#include +#include +#include + +#define EXPORT STDCALL + +#define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') + + +#endif /* __WSHIRDA_H */ + +/* EOF */ diff --git a/lib/wshirda/wshirda.rc b/lib/wshirda/wshirda.rc new file mode 100644 index 0000000..9b18a99 --- /dev/null +++ b/lib/wshirda/wshirda.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Windows Sockets 2 IRDA Helper API\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "wshirda\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "wshirda.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + diff --git a/loaders/boot/boot.asm b/loaders/boot/boot.asm new file mode 100644 index 0000000..ca626a1 --- /dev/null +++ b/loaders/boot/boot.asm @@ -0,0 +1,309 @@ +; +; File: +; boot.asm +; Description: +; DOS-C boot +; +; Copyright (c) 1997; +; Svante Frey +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation; either version +; 2, or (at your option) any later version. +; +; DOS-C is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +; the GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public +; License along with DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/boot/boot.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2002/10/31 14:31:06 lace +; :pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos +; +; Revision 1.4 2000/06/25 03:59:14 dwelch +; +; Removed from redundant files from the mm directory +; Added some preliminary work on the pager +; Fixed ntoskrnl/mm/npool.c (This may have been the cause of the +; problems reported with loading win32k.sys) +; Fixed problems with reporting space used to store physical page +; information +; Added code to support MmSafeCopy{To/From}User interface work +; (untested) +; Added Event member of the PHYSICAL_PAGE structure to implement Philip +; Susi's suggestion +; Reworked section page-in code (not really tested) +; Replaced inline string functions with gcc builtins to make debugging easier +; +; Revision 1.3 1998/08/25 04:37:43 rex +; new release cleanup +; +; Revision 1.1.1.2 1998/08/25 04:27:38 rex +; A much Needed Update +; +; +; Rev 1.5 10 Jan 1997 4:58:06 patv +; Corrected copyright +; +; Rev 1.4 10 Jan 1997 4:52:50 patv +; Re-written to support C drive and eliminate restrictions on IPL.SYS +; +; Rev 1.3 29 Aug 1996 13:06:50 patv +; Bug fixes for v0.91b +; +; Rev 1.2 01 Sep 1995 17:56:44 patv +; First GPL release. +; +; Rev 1.1 30 Jul 1995 20:37:38 patv +; Initialized stack before use. +; +; Rev 1.0 02 Jul 1995 10:57:52 patv +; Initial revision. +; + +section .text + + org 0 +Entry: jmp real_start + +; bp is initialized to 7c00h +%define oem [bp+3] +%define bytesPerSector [bp+0bh] +%define sectPerCluster [bp+0dh] +%define resSectors [bp+0eh] +%define nFats [bp+10h] +%define nRootDir [bp+11h] +%define nSectors [bp+13h] +%define MID [bp+15h] +%define sectPerFat [bp+16h] +%define sectPerTrack [bp+18h] +%define nHeads [bp+1ah] +%define nHidden [bp+1ch] +%define nHidden_hi [bp+1eh] +%define nSectorHuge [bp+20h] +%define drive [bp+24h] +%define extBoot [bp+26h] +%define volid [bp+27h] +%define vollabel [bp+2bh] +%define filesys 36h + +LOADSEG equ 2000h + +FATBUF equ 4000h ; offset of temporary buffer for FAT + ; chain +RETRYCOUNT equ 5 ; number of retries on disk errors + +; Some extra variables that are created on the stack frame + +%define fat_start [bp-4] ; first FAT sector +%define fat_start_hi [bp-2] +%define root_dir_start [bp-8] ; first root directory sector +%define root_dir_start_hi [bp-6] +%define data_start [bp-12] ; first data sector +%define data_start_hi [bp-10] + +; +; Include macros for filesystem access +; +%include "boot.inc" + +; +; +; + TIMES 3eh-($-$$) DB 0 + +%define tempbuf [bp+3eh] +load_seg dw LOADSEG + +real_start: cli + cld + mov ax, cs + mov ss, ax ; initialize stack + mov bp, 7c00h + lea sp, [bp-20h] + sti + + mov es, ax + mov ds, ax + mov drive, dl ; BIOS passes drive number in DL + + GETDRIVEPARMS + + FINDFILE ; locate file in root directory + jc boot_error ; fail if not found + + GETFATCHAIN ; read FAT chain + LOADFILE ; load file (jumps to boot_sucess if successful) + +boot_error: mov cx, ERRMSGLEN + mov si, errmsg+7c00h + +next_char: lodsb ; print error message + mov ah, 0eh + xor bh, bh + int 10h + loop next_char + + xor ah, ah + int 16h ; wait for keystroke + int 19h ; invoke bootstrap loader + +boot_success: mov dl, drive + + db 0eah ; far jump to LOADSEG:0000 + dw 0 + dw LOADSEG + + +; readDisk: Reads a number of sectors into memory. +; +; Call with: DX:AX = 32-bit DOS sector number +; DI = number of sectors to read +; ES:BX = destination buffer +; ES must be 64k aligned (1000h, 2000h etc). +; +; Returns: CF set on error +; ES:BX points one byte after the last byte read. + +readDisk: + push si +read_next: push dx + push ax + + ; + ; translate sector number to BIOS parameters + ; + + ; + ; abs = sector offset in track + ; + head * sectPerTrack offset in cylinder + ; + track * sectPerTrack * nHeads offset in platter + ; + ; t1 = abs / sectPerTrack (ax has t1) + ; sector = abs mod sectPerTrack (cx has sector) + ; + div word sectPerTrack + mov cx, dx + + ; + ; t1 = head + track * nHeads + ; + ; track = t1 / nHeads (ax has track) + ; head = t1 mod nHeads (dl has head) + ; + xor dx, dx + div word nHeads + + ; the following manipulations are necessary in order to + ; properly place parameters into registers. + ; ch = cylinder number low 8 bits + ; cl = 7-6: cylinder high two bits + ; 5-0: sector + mov dh, dl ; save head into dh for bios + ror ah, 1 ; move track high bits into + ror ah, 1 ; bits 7-6 (assumes top = 0) + xchg al, ah ; swap for later + mov dl, byte sectPerTrack + sub dl, cl + inc cl ; sector offset from 1 + or cx, ax ; merge cylinder into sector + mov al, dl ; al has # of sectors left + + ; Calculate how many sectors can be transfered in this read + ; due to dma boundary conditions. + push dx + + mov si, di ; temp register save + ; this computes remaining bytes because of modulo 65536 + ; nature of dma boundary condition + mov ax, bx ; get offset pointer + neg ax ; and convert to bytes + jz ax_min_1 ; started at seg:0, skip ahead + + xor dx, dx ; convert to sectors + div word bytesPerSector + + cmp ax, di ; check remainder vs. asked + jb ax_min_1 ; less, skip ahead + mov si, ax ; transfer only what we can + +ax_min_1: pop dx + + ; Check that request sectors do not exceed track boundary + mov si, sectPerTrack + inc si + mov ax, cx ; get the sector/cyl byte + and ax, 03fh ; and mask out sector + sub si, ax ; si has how many we can read + mov ax, di + cmp si, di ; see if asked <= available + jge ax_min_2 + mov ax, si ; get what can be xfered + +ax_min_2: mov si, RETRYCOUNT + mov ah, 2 + mov dl, drive + +retry: push ax + int 13h + pop ax + jnc read_ok + push ax + xor ax, ax ; reset the drive + int 13h + pop ax + dec si + jnz retry + stc + pop ax + pop dx + pop si + ret + +read_next_jmp: jmp short read_next +read_ok: xor ah, ah + mov si, ax ; AX = SI = number of sectors read + mul word bytesPerSector ; AX = number of bytes read + add bx, ax ; add number of bytes read to BX + jnc no_incr_es ; if overflow... + + mov ax, es + add ah, 10h ; ...add 1000h to ES + mov es, ax + +no_incr_es: pop ax + pop dx ; DX:AX = last sector number + + add ax, si + adc dx, 0 ; DX:AX = next sector to read + sub di, si ; if there is anything left to read, + jg read_next_jmp ; continue + + clc + pop si + ret + +errmsg db "Boot error" +ERRMSGLEN equ $ - errmsg + + +;filename db "OSLDR BIN" +filename db "KERNEL BIN" + + TIMES 510-($-$$) DB 0 +sign dw 0aa55h + + diff --git a/loaders/boot/boot.inc b/loaders/boot/boot.inc new file mode 100644 index 0000000..0491007 --- /dev/null +++ b/loaders/boot/boot.inc @@ -0,0 +1,196 @@ +; To save space, functions that are just called once are +; implemented as macros instead. Four bytes are saved by +; avoiding the call / ret instructions. + + +; FINDFILE: Searches for the file in the root directory. +; +; Returns: +; +; If file not found: CF set +; +; If file found: CF clear +; AX = first cluster of file + + +%macro FINDFILE 0 + ; First, read the whole root directory + ; into the temporary buffer. + + mov ax, word root_dir_start + mov dx, word root_dir_start_hi + mov di, nRootDir + xor bx, bx + mov es, tempbuf + call readDisk + jc ffDone + + xor di, di + +next_entry: mov cx, 11 + mov si, filename+7c00h + push di + repe cmpsb + pop di + mov ax, [es:di+1ah] ; get cluster number from directory entry + clc + je ffDone + + add di, 20h ; go to next directory entry + cmp byte [es:di], 0 ; if the first byte of the name is 0, + jnz next_entry ; there is no more files in the directory + + stc +ffDone: +%endmacro + +; GETDRIVEPARMS: Calculate start of some disk areas. + +%macro GETDRIVEPARMS 0 + mov si, word nHidden + mov di, word nHidden_hi + add si, word resSectors + adc di, 0 ; DI:SI = first FAT sector + + mov word fat_start, si + mov word fat_start_hi, di + + mov al, nFats + xor ah, ah + mul word sectPerFat ; DX:AX = total number of FAT sectors + + add si, ax + adc di, dx ; DI:SI = first root directory sector + mov word root_dir_start, si + mov word root_dir_start_hi, di + + ; Calculate how many sectors the root directory occupies. + mov bx, bytesPerSector + mov cl, 5 ; divide BX by 32 + shr bx, cl ; BX = directory entries per sector + + mov ax, nRootDir + xor dx, dx + div bx + + mov nRootDir, ax ; AX = sectors per root directory + + add si, ax + adc di, 0 ; DI:SI = first data sector + + mov data_start, si + mov data_start_hi, di +%endmacro + +; GETFATCHAIN: +; +; Reads the FAT chain and stores it in a temporary buffer in the first +; 64 kb. The FAT chain is stored an array of 16-bit cluster numbers, +; ending with 0. +; +; The file must fit in conventional memory, so it can't be larger than +; 640 kb. The sector size must be at least 512 bytes, so the FAT chain +; can't be larger than around 3 kb. +; +; Call with: AX = first cluster in chain +; +; Returns: CF clear on success, set on error + +%macro GETFATCHAIN 0 + push ax ; store first cluster number + + ; Load the complete FAT into memory. The FAT can't be larger + ; than 128 kb, so it should fit in the temporary buffer. + + mov es, tempbuf + xor bx, bx + mov di, sectPerFat + mov ax, word fat_start + mov dx, word fat_start_hi + call readDisk + pop ax ; restore first cluster number + jc boot_error + + ; Set ES:DI to the temporary storage for the FAT chain. + push ds + push es + pop ds + pop es + mov di, FATBUF + +next_clust: stosw ; store cluster number + mov si, ax ; SI = cluster number + cmp byte extBoot, 29h + jne fat_12 + cmp byte [bp+filesys+4], '6' ; check for FAT-16 system + je fat_16 + + ; This is a FAT-12 disk. + +fat_12: add si, si ; multiply cluster number by 3... + add si, ax + shr si, 1 ; ...and divide by 2 + lodsw + + ; If the cluster number was even, the cluster value is now in + ; bits 0-11 of AX. If the cluster number was odd, the cluster + ; value is in bits 4-15, and must be shifted right 4 bits. If + ; the number was odd, CF was set in the last shift instruction. + + jnc fat_even + mov cl, 4 + shr ax, cl ; shift the cluster number + +fat_even: and ah, 0fh ; mask off the highest 4 bits + cmp ax, 0fffh ; check for EOF + jmp short next_test + + ; This is a FAT-16 disk. The maximal size of a 16-bit FAT + ; is 128 kb, so it may not fit within a single 64 kb segment. + +fat_16: mov dx, tempbuf + add si, si ; multiply cluster number by two + jnc first_half ; if overflow... + add dh, 10h ; ...add 64 kb to segment value + +first_half: mov ds, dx ; DS:SI = pointer to next cluster + lodsw ; AX = next cluster + + cmp ax, 0fff8h ; >= FFF8 = 16-bit EOF +next_test: jb next_clust ; continue if not EOF + +finished: ; Mark end of FAT chain with 0, so we have a single + ; EOF marker for both FAT-12 and FAT-16 systems. + + xor ax, ax + stosw +fatError: +%endmacro + + +; loadFile: Loads the file into memory, one cluster at a time. + +%macro LOADFILE 0 + mov es, tempbuf ; set ES:BX to load address + xor bx, bx + + mov si, FATBUF ; set DS:SI to the FAT chain + push cs + pop ds + +next_cluster: lodsw ; AX = next cluster to read + or ax, ax ; if EOF... + je boot_success ; ...boot was successful + + dec ax ; cluster numbers start with 2 + dec ax + + mov di, word sectPerCluster + and di, 0ffh ; DI = sectors per cluster + mul di + add ax, data_start + adc dx, data_start_hi ; DX:AX = first sector to read + call readDisk + jnc next_cluster + +%endmacro diff --git a/loaders/boot/boot.mak b/loaders/boot/boot.mak new file mode 100644 index 0000000..ae42623 --- /dev/null +++ b/loaders/boot/boot.mak @@ -0,0 +1,77 @@ +# +# makefile for DOS-C boot +# +# $Header$ +# +# $Log$ +# Revision 1.1 2002/10/31 14:31:06 lace +# :pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos +# +# Revision 1.4 2000/06/25 03:59:14 dwelch +# +# Removed from redundant files from the mm directory +# Added some preliminary work on the pager +# Fixed ntoskrnl/mm/npool.c (This may have been the cause of the +# problems reported with loading win32k.sys) +# Fixed problems with reporting space used to store physical page +# information +# Added code to support MmSafeCopy{To/From}User interface work +# (untested) +# Added Event member of the PHYSICAL_PAGE structure to implement Philip +# Susi's suggestion +# Reworked section page-in code (not really tested) +# Replaced inline string functions with gcc builtins to make debugging easier +# +# Revision 1.3 1998/08/25 04:39:40 rex +# Release cleanup +# +# Revision 1.1.1.2 1998/08/25 04:27:38 rex +# A much Needed Update +# +# +# Rev 1.3 10 Jan 1997 4:51:54 patv +#Changed to use FreeDOS exe2bin and support new boot code +# +# Rev 1.2 17 Dec 1996 12:52:32 patv +#Converted to FreeDOS exe2bin. +#. +#d +# +# Rev 1.1 29 Aug 1996 13:06:50 patv +#Bug fixes for v0.91b +# +# Rev 1.0 02 Jul 1995 9:11:26 patv +#Initial revision. +# + +# +# Uncomment the following for a debug version +# +#AFLAGS = /zi /DDEBUG +#LFLAGS = /v + +PRODUCT = boot.bin + +all: $(PRODUCT) + +production: all + copy boot.bin ..\..\dist\boot.bin + del *.bin + del *.map + +boot.bin: boot.asm + tasm $(AFLAGS) boot,, + tlink $(LFLAGS) boot + ..\utils\exe2bin boot boot.bin + del boot.obj + del boot.exe + +clean: + del *.lst + del *.map + del *.bin + del *.bak + del *.las + del *.obj + del *.exe + diff --git a/loaders/boot/bootbk.asm b/loaders/boot/bootbk.asm new file mode 100644 index 0000000..b1edd9f --- /dev/null +++ b/loaders/boot/bootbk.asm @@ -0,0 +1,313 @@ +; +; File: +; boot.asm +; Description: +; DOS-C boot +; +; Copyright (c) 1997; +; Svante Frey +; All Rights Reserved +; +; This file is part of DOS-C. +; +; DOS-C is free software; you can redistribute it and/or +; modify it under the terms of the GNU General Public License +; as published by the Free Software Foundation; either version +; 2, or (at your option) any later version. +; +; DOS-C is distributed in the hope that it will be useful, but +; WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +; the GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public +; License along with DOS-C; see the file COPYING. If not, +; write to the Free Software Foundation, 675 Mass Ave, +; Cambridge, MA 02139, USA. +; +; $Logfile: C:/dos-c/src/boot/boot.asv $ +; +; $Header$ +; +; $Log$ +; Revision 1.1 2002/10/31 14:31:06 lace +; :pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos +; +; Revision 1.4 2000/06/25 03:59:14 dwelch +; +; Removed from redundant files from the mm directory +; Added some preliminary work on the pager +; Fixed ntoskrnl/mm/npool.c (This may have been the cause of the +; problems reported with loading win32k.sys) +; Fixed problems with reporting space used to store physical page +; information +; Added code to support MmSafeCopy{To/From}User interface work +; (untested) +; Added Event member of the PHYSICAL_PAGE structure to implement Philip +; Susi's suggestion +; Reworked section page-in code (not really tested) +; Replaced inline string functions with gcc builtins to make debugging easier +; +; Revision 1.3 1998/08/25 04:40:47 rex +; Release cleanup +; +; Revision 1.1.1.2 1998/08/25 04:27:38 rex +; A much Needed Update +; +; +; Rev 1.5 10 Jan 1997 4:58:06 patv +; Corrected copyright +; +; Rev 1.4 10 Jan 1997 4:52:50 patv +; Re-written to support C drive and eliminate restrictions on IPL.SYS +; +; Rev 1.3 29 Aug 1996 13:06:50 patv +; Bug fixes for v0.91b +; +; Rev 1.2 01 Sep 1995 17:56:44 patv +; First GPL release. +; +; Rev 1.1 30 Jul 1995 20:37:38 patv +; Initialized stack before use. +; +; Rev 1.0 02 Jul 1995 10:57:52 patv +; Initial revision. +; + +.text + +BASE equ 0 + + + org BASE +Entry: jmp real_start + +; bp is initialized to 7c00h +oem equ [bp+3] +bytesPerSector equ [bp+0bh] +sectPerCluster equ [bp+0dh] +resSectors equ [bp+0eh] +nFats equ [bp+10h] +nRootDir equ [bp+11h] +nSectors equ [bp+13h] +MID equ [bp+15h] +sectPerFat equ [bp+16h] +sectPerTrack equ [bp+18h] +nHeads equ [bp+1ah] +nHidden equ [bp+1ch] +nSectorHuge equ [bp+20h] +drive equ [bp+24h] +extBoot equ [bp+26h] +volid equ [bp+27h] +vollabel equ [bp+2bh] +filesys equ [bp+36h] + +LOADSEG equ 2000h + +FATBUF equ 4000h ; offset of temporary buffer for FAT + ; chain +RETRYCOUNT equ 5 ; number of retries on disk errors + +; Some extra variables that are created on the stack frame + +fat_start equ [bp-4] ; first FAT sector +root_dir_start equ [bp-8] ; first root directory sector +data_start equ [bp-12] ; first data sector + + +; +; Include macros for filesystem access +; +include boot.inc + +; +; +; + org BASE+3eh + +tempbuf equ [bp+3eh] +load_seg dw LOADSEG + +real_start: cli + cld + mov ax, cs + mov ss, ax ; initialize stack + mov bp, 7c00h + lea sp, [bp-20h] + sti + + mov es, ax + mov ds, ax + mov drive, dl ; BIOS passes drive number in DL + + GETDRIVEPARMS + + FINDFILE ; locate file in root directory + jc boot_error ; fail if not found + + GETFATCHAIN ; read FAT chain + LOADFILE ; load file (jumps to boot_sucess if successful) + +boot_error: mov cx, ERRMSGLEN + mov si, offset errmsg+7c00h + +next_char: lodsb ; print error message + mov ah, 0eh + xor bh, bh + int 10h + loop next_char + + xor ah, ah + int 16h ; wait for keystroke + int 19h ; invoke bootstrap loader + +boot_success: mov dl, drive + + db 0eah ; far jump to LOADSEG:0000 + dw 0 + dw LOADSEG + + +; readDisk: Reads a number of sectors into memory. +; +; Call with: DX:AX = 32-bit DOS sector number +; DI = number of sectors to read +; ES:BX = destination buffer +; ES must be 64k aligned (1000h, 2000h etc). +; +; Returns: CF set on error +; ES:BX points one byte after the last byte read. + +readDisk proc + push si +read_next: push dx + push ax + + ; + ; translate sector number to BIOS parameters + ; + + ; + ; abs = sector offset in track + ; + head * sectPerTrack offset in cylinder + ; + track * sectPerTrack * nHeads offset in platter + ; + ; t1 = abs / sectPerTrack (ax has t1) + ; sector = abs mod sectPerTrack (cx has sector) + ; + div word ptr sectPerTrack + mov cx, dx + + ; + ; t1 = head + track * nHeads + ; + ; track = t1 / nHeads (ax has track) + ; head = t1 mod nHeads (dl has head) + ; + xor dx, dx + div word ptr nHeads + + ; the following manipulations are necessary in order to + ; properly place parameters into registers. + ; ch = cylinder number low 8 bits + ; cl = 7-6: cylinder high two bits + ; 5-0: sector + mov dh, dl ; save head into dh for bios + ror ah, 1 ; move track high bits into + ror ah, 1 ; bits 7-6 (assumes top = 0) + xchg al, ah ; swap for later + mov dl, byte ptr sectPerTrack + sub dl, cl + inc cl ; sector offset from 1 + or cx, ax ; merge cylinder into sector + mov al, dl ; al has # of sectors left + + ; Calculate how many sectors can be transfered in this read + ; due to dma boundary conditions. + push dx + + mov si, di ; temp register save + ; this computes remaining bytes because of modulo 65536 + ; nature of dma boundary condition + mov ax, bx ; get offset pointer + neg ax ; and convert to bytes + jz ax_min_1 ; started at seg:0, skip ahead + + xor dx, dx ; convert to sectors + div word ptr bytesPerSector + + cmp ax, di ; check remainder vs. asked + jb ax_min_1 ; less, skip ahead + mov si, ax ; transfer only what we can + +ax_min_1: pop dx + + ; Check that request sectors do not exceed track boundary + mov si, sectPerTrack + inc si + mov ax, cx ; get the sector/cyl byte + and ax, 03fh ; and mask out sector + sub si, ax ; si has how many we can read + mov ax, di + cmp si, di ; see if asked <= available + jge ax_min_2 + mov ax, si ; get what can be xfered + +ax_min_2: mov si, RETRYCOUNT + mov ah, 2 + mov dl, drive + +retry: push ax + int 13h + pop ax + jnc read_ok + push ax + xor ax, ax ; reset the drive + int 13h + pop ax + dec si + jnz retry + stc + pop ax + pop dx + pop si + ret + +read_next_jmp: jmp short read_next +read_ok: xor ah, ah + mov si, ax ; AX = SI = number of sectors read + mul word ptr bytesPerSector ; AX = number of bytes read + add bx, ax ; add number of bytes read to BX + jnc no_incr_es ; if overflow... + + mov ax, es + add ah, 10h ; ...add 1000h to ES + mov es, ax + +no_incr_es: pop ax + pop dx ; DX:AX = last sector number + + add ax, si + adc dx, 0 ; DX:AX = next sector to read + sub di, si ; if there is anything left to read, + jg read_next_jmp ; continue + + clc + pop si + ret +readDisk endp + +errmsg db "Boot error" +ERRMSGLEN equ $ - errmsg + + +;filename db "OSLDR BIN" +filename db "KERNEL BIN" + + org BASE+01feh +sign dw 0aa55h + +TEXT ENDS + end + + diff --git a/loaders/boot/osldr.asm b/loaders/boot/osldr.asm new file mode 100644 index 0000000..0915d18 --- /dev/null +++ b/loaders/boot/osldr.asm @@ -0,0 +1,340 @@ +; +; Loads the kernel and any required modules +; + +org 0 + +; +; Segment where we are loaded +; +LOADSEG equ 02000h + +; +; Segment used for temporay storage +; +WORKSEG equ 01000h + + +KERNELBASE equ 05000h + +; +; Offsets of work areas +; +FAT_CHAIN equ 0h + +DIR_BUFFER equ 4000h +END_DIR_BUFFER equ 0ffe0h + +FAT_SEG equ 03000h + + +; +; These are all on the stack +; +%define oem [bp+3] +%define bytesPerSector [bp+0bh] +%define sectPerCluster [bp+0dh] +%define resSectors [bp+0eh] +%define nFats [bp+10h] +%define nRootDir [bp+11h] +%define nSectors [bp+13h] +%define MID [bp+15h] +%define sectPerFat [bp+16h] +%define sectPerTrack [bp+18h] +%define nHeads [bp+1ah] +%define nHidden [bp+1ch] +%define nHidden_hi [bp+1eh] +%define nSectorHuge [bp+20h] +%define drive [bp+24h] +%define extBoot [bp+26h] +%define volid [bp+27h] +%define vollabel [bp+2bh] +%define filesys 36h + +RETRYCOUNT equ 5 + +%define fat_start [bp-4] ; first FAT sector +%define fat_start_hi [bp-2] +%define root_dir_start [bp-8] ; first root directory sector +%define root_dir_start_hi [bp-6] +%define data_start [bp-12] ; first data sector +%define data_start_hi [bp-10] + + +entry: + mov drive,dl + + mov ax,LOADSEG + mov ds,ax + + + ; + ; Print out a message + ; + mov di,loadmsg + call printmsg + + + ; + ; Check here for shift pressed and if so display boot menu + ; + + ; + ; Load the entire fat + ; +; mov ax,fat_start +; mov dx,fat_start_hi +; mov di,sectPerFat +; mov ax,FAT_SEG +; mov es,ax +; mov bx,0 +; call readDisk + + + ; + ; Load root directory + ; + mov ax,WORKSEG + mov es,ax + + mov dx,root_dir_start_hi + mov ax,root_dir_start + mov bx,DIR_BUFFER + mov di,nRootDir + shr di,4 + mov di,1 + call readDisk + jc disk_error + + ; + ; Look for a directory called boot + ; + mov di,DIR_BUFFER + cld + mov cx,4 +l1: + mov si,boot_dir_name +; cmp byte [di],0 +; je boot_error + repe cmpsb + je found_it + or di,31 + inc di + cmp di,END_DIR_BUFFER + jge boot_error + jmp l1 + + +boot_error: + mov di,errormsg + call printmsg +l3: + jmp l3 + +disk_error: + mov di,errormsg1 + call printmsg + jmp l3 + + + +found_it: + mov di,msg1 + call printmsg + + ; + ; Load the boot directory found above + ; + sub di,4 + call readFile + +l2: + jmp l2 + +; +; readFile +; +%define file_length [di+01ch] +%define start_cluster [di+01ah] +readFile: + cmp byte extBoot, 29h + jne fat_12 + cmp byte [bp+filesys+4], '6' ; check for FAT-16 system + je fat_16 + +fat_12: + mov di,msg2 + call printmsg +l4: + jmp l4 + +fat_16: + mov di,msg3 + call printmsg + jmp l4 + + + +; readDisk: Reads a number of sectors into memory. +; +; Call with: DX:AX = 32-bit DOS sector number +; DI = number of sectors to read +; ES:BX = destination buffer +; ES must be 64k aligned (1000h, 2000h etc). +; +; Returns: CF set on error +; ES:BX points one byte after the last byte read. + +readDisk: + push bp + push si +read_next: push dx + push ax + + ; + ; translate sector number to BIOS parameters + ; + + ; + ; abs = sector offset in track + ; + head * sectPerTrack offset in cylinder + ; + track * sectPerTrack * nHeads offset in platter + ; + ; t1 = abs / sectPerTrack (ax has t1) + ; sector = abs mod sectPerTrack (cx has sector) + ; + div word sectPerTrack + mov cx, dx + + ; + ; t1 = head + track * nHeads + ; + ; track = t1 / nHeads (ax has track) + ; head = t1 mod nHeads (dl has head) + ; + xor dx, dx + div word nHeads + + ; the following manipulations are necessary in order to + ; properly place parameters into registers. + ; ch = cylinder number low 8 bits + ; cl = 7-6: cylinder high two bits + ; 5-0: sector + mov dh, dl ; save head into dh for bios + ror ah, 1 ; move track high bits into + ror ah, 1 ; bits 7-6 (assumes top = 0) + xchg al, ah ; swap for later + mov dl, byte sectPerTrack + sub dl, cl + inc cl ; sector offset from 1 + or cx, ax ; merge cylinder into sector + mov al, dl ; al has # of sectors left + + ; Calculate how many sectors can be transfered in this read + ; due to dma boundary conditions. + push dx + + mov si, di ; temp register save + ; this computes remaining bytes because of modulo 65536 + ; nature of dma boundary condition + mov ax, bx ; get offset pointer + neg ax ; and convert to bytes + jz ax_min_1 ; started at seg:0, skip ahead + + xor dx, dx ; convert to sectors + div word bytesPerSector + + cmp ax, di ; check remainder vs. asked + jb ax_min_1 ; less, skip ahead + mov si, ax ; transfer only what we can + +ax_min_1: pop dx + + ; Check that request sectors do not exceed track boundary + mov si, sectPerTrack + inc si + mov ax, cx ; get the sector/cyl byte + and ax, 03fh ; and mask out sector + sub si, ax ; si has how many we can read + mov ax, di + cmp si, di ; see if asked <= available + jge ax_min_2 + mov ax, si ; get what can be xfered + +ax_min_2: mov si, RETRYCOUNT + mov ah, 2 + mov dl, drive + +retry: push ax + int 13h + pop ax + jnc read_ok + push ax + xor ax, ax ; reset the drive + int 13h + pop ax + dec si + jnz retry + stc + pop ax + pop dx + pop si + pop bp + ret + +read_next_jmp: jmp short read_next +read_ok: xor ah, ah + mov si, ax ; AX = SI = number of sectors read + mul word bytesPerSector ; AX = number of bytes read + add bx, ax ; add number of bytes read to BX + jnc no_incr_es ; if overflow... + + mov ax, es + add ah, 10h ; ...add 1000h to ES + mov es, ax + +no_incr_es: pop ax + pop dx ; DX:AX = last sector number + + add ax, si + adc dx, 0 ; DX:AX = next sector to read + sub di, si ; if there is anything left to read, + jg read_next_jmp ; continue + + clc + pop si + pop bp + ret + +; +; Print string (DI = start) +; +printmsg: + push ax + push bx + push di + mov ah,0eh + mov bh,0 + mov bl,07h +.l1 + mov al,[di] + cmp al,0 + je .l2 + inc di + int 10h + jmp .l1 +.l2 + pop di + pop bx + pop ax + ret + + + +loadmsg db "Starting ReactOS...",0xd,0xa,0 +boot_dir_name db 'BOOT' +errormsg db "Files missing on boot disk",0 +errormsg1 db "Disk read error",0 +msg1 db "Found boot directory",0xd,0xa,0 +msg2 db 'FAT12',0 +msg3 db 'FAT16',0 diff --git a/loaders/boot/osldr.txt b/loaders/boot/osldr.txt new file mode 100644 index 0000000..8ef4f0d --- /dev/null +++ b/loaders/boot/osldr.txt @@ -0,0 +1,12 @@ +Mem layout for osldr + +0000 - 07C0 = BIOS data and stack +07C0 - 1000 = Boot sector +1000 - 1400 = Tempory storage for fat chains +1400 - 2000 = Tempory storage for directory entries +2000 - 3000 = OSLDR +3000 - 5000 = FAT +5000 - a000 = Kernel and modules load area + + + diff --git a/loaders/dos/loadros.asm b/loaders/dos/loadros.asm new file mode 100644 index 0000000..99f00e6 --- /dev/null +++ b/loaders/dos/loadros.asm @@ -0,0 +1,1302 @@ +; +; Pmode setup stub +; (A20 enable code and PIC reprogram from linux bootsector) +; + +; +; Base address of the kernel +; +LOAD_BASE equ 0200000h + +; +; Segment selectors +; +%define KERNEL_CS (0x8) +%define KERNEL_DS (0x10) +%define LOADER_CS (0x18) +%define LOADER_DS (0x20) + +struc multiboot_module +mbm_mod_start: resd 1 +mbm_mod_end: resd 1 +mbm_string: resd 1 +mbm_reserved: resd 1 +endstruc + +struc multiboot_address_range +mar_baselow: resd 1 +mar_basehigh: resd 1 +mar_lengthlow: resd 1 +mar_lengthhigh: resd 1 +mar_type: resd 1 +mar_reserved: resd 3 +endstruc + +; +; We are a .com program +; +org 100h + +; +; 16 bit code +; +BITS 16 + +%define NDEBUG 1 + +%macro DPRINT 1+ +%ifndef NDEBUG + jmp %%end_str + +%%str: db %1 + +%%end_str: + push di + push ds + push es + pop ds + mov di, %%str + call print_string + pop ds + pop di +%endif +%endmacro + +entry: + ;; + ;; Load stack + ;; + cli + push ds + pop ss + push ds + pop es + mov sp, real_stack_end + sti + + ;; + ;; Setup the 32-bit registers + ;; + mov ebx, 0 + mov eax, 0 + mov ecx, 0 + mov edx, 0 + mov esi, 0 + mov edi, 0 + + ;; + ;; Set the position for the first module to be loaded + ;; + mov dword [next_load_base], LOAD_BASE + + ;; + ;; Setup various variables + ;; + mov bx, ds + movzx eax, bx + shl eax, 4 + add [gdt_base], eax + + ;; + ;; Setup the loader code and data segments + ;; + mov eax, 0 + mov ax, cs + shl eax, 4 + mov [_loader_code_base_0_15], ax + shr eax, 16 + mov byte [_loader_code_base_16_23], al + + mov eax, 0 + mov ax, ds + shl eax, 4 + mov [_loader_data_base_0_15], ax + shr eax, 16 + mov byte [_loader_data_base_16_23], al + + ;; + ;; load gdt + ;; + lgdt [gdt_descr] + + ;; + ;; Enable the A20 address line (to allow access to over 1mb) + ;; + call empty_8042 + mov al, 0D1h ; command write + out 064h, al + call empty_8042 + mov al, 0DFh ; A20 on + out 060h, al + call empty_8042 + + ;; + ;; Make the argument list into a c string + ;; + mov di, 081h + mov si, dos_cmdline +.next_char + mov al, [di] + mov [si], al + cmp byte [di], 0dh + je .end_of_command_line + inc di + inc si + jmp .next_char + +.end_of_command_line: + mov byte [di], 0 + mov byte [si], 0 + mov [dos_cmdline_end], di + + ;; + ;; Make the argument list into a c string + ;; + mov di, 081h +.next_char2 + cmp byte [di], 0 + je .end_of_command_line2 + cmp byte [di], ' ' + jne .not_space + mov byte [di], 0 +.not_space + inc di + jmp .next_char2 +.end_of_command_line2 + + ;; + ;; Check if we want to skip the first character + ;; + cmp byte [081h], 0 + jne .first_char_is_zero + mov dx, 082h + jmp .start_loading +.first_char_is_zero + mov dx, 081h + + ;; + ;; Check if we have reached the end of the string + ;; +.start_loading + mov bx, dx + cmp byte [bx], 0 + jne .more_modules + jmp .done_loading + +.more_modules + ;; + ;; Process the arguments + ;; + cmp byte [di], '/' + jne .no_next_module + + mov si, _multiboot_kernel_cmdline +.find_end: + cmp byte [si], 0 + je .line_end + inc si + jmp .find_end + +.line_end + mov byte [si], ' ' + inc si +.line_copy + cmp di, [dos_cmdline_end] + je .done_copy + cmp byte [di], 0 + je .done_copy + mov al, byte [di] + mov byte [si], al + inc di + inc si + jmp .line_copy +.done_copy: + mov byte [si], 0 + jmp .next_module +.no_next_module: + + ;; + ;; Display a message saying we are loading the module + ;; + mov di, loading_msg + call print_string + mov di, dx + call print_string + + ;; + ;; Save the filename + ;; + mov si, di + mov edx, 0 + + mov dx, [_multiboot_mods_count] + shl dx, 8 + add dx, _multiboot_module_strings + mov bx, [_multiboot_mods_count] + imul bx, bx, multiboot_module_size + add bx, _multiboot_modules + mov eax, 0 + mov ax, ds + shl eax, 4 + add eax, edx + mov [bx + mbm_string], eax + + mov bx, dx +.copy_next_char + mov al, [si] + mov [bx], al + inc si + inc bx + cmp al, 0 + jne .copy_next_char + + ;; + ;; Load the file + ;; + push di + mov dx, di + + ; Check if it is a symbol file + cmp byte [bx-5],'.' + jne .checkForHive + cmp byte [bx-4],'s' + jne .checkForHive + cmp byte [bx-3],'y' + jne .checkForHive + cmp byte [bx-2],'m' + jne .checkForHive + + call sym_load_module + jmp .after_copy + +.checkForHive: + ; Check if it is a symbol file + cmp byte [bx-5],'.' + jne .lst_copy + cmp byte [bx-4],'h' + jne .lst_copy + cmp byte [bx-3],'i' + jne .lst_copy + cmp byte [bx-2],'v' + jne .lst_copy + + call sym_load_module + jmp .after_copy + +.lst_copy: + ;; Check for a module list file + cmp byte [bx-5],'.' + jne .pe_copy + cmp byte [bx-4],'l' + jne .pe_copy + cmp byte [bx-3],'s' + jne .pe_copy + cmp byte [bx-2],'t' + jne .pe_copy + + call sym_load_module + + push es + mov bx,0x9000 + push bx + pop es + xor edi,edi + +.lst_copy_bytes: + mov bx,_lst_name_local + +.lst_byte: + mov al,[es:di] + inc di + cmp al,' ' + jg .lst_not_space + mov byte [bx],0 + inc bx +.lst_space: + mov al,[es:di] + inc di + cmp al,' ' + jle .lst_space +.lst_not_space: + cmp al,'*' + je .lst_end + mov [bx],al + inc bx + jmp .lst_byte + +.lst_end: + ;; We are here because the terminator was encountered + mov byte [bx],0 ; Zero terminate + inc bx + mov byte [bx],0 + mov [dos_cmdline_end],bx ; Put in cmd_line_length + mov dx,_lst_name_local; Put this address in di + mov di,dx ; This, too, at the start of the + ; string + + pop es + + jmp .start_loading + +.pe_copy: + call pe_load_module + +.after_copy: + pop di + cmp eax, 0 + jne .load_success + jmp .exit +.load_success: + mov ah, 02h + mov dl, 0dh + int 021h + mov ah, 02h + mov dl, 0ah + int 021h + + ;; + ;; Move onto the next module name in the command line + ;; +.next_module + cmp di, [dos_cmdline_end] + je .done_loading + cmp byte [di], 0 + je .found_module_name + inc di + jmp .next_module +.found_module_name + inc di + mov dx, di + jmp .start_loading + +.done_loading + + ;; + ;; Initialize the multiboot information + ;; + mov eax, 0 + mov ax, ds + shl eax, 4 + + mov [_multiboot_info_base], eax + add dword [_multiboot_info_base], _multiboot_info + + mov dword [_multiboot_flags], 0xc + + mov [_multiboot_cmdline], eax + add dword [_multiboot_cmdline], _multiboot_kernel_cmdline + + ;; + ;; Hide the kernel's entry in the list of modules + ;; + mov [_multiboot_mods_addr], eax + mov ebx, _multiboot_modules + add ebx, multiboot_module_size + add dword [_multiboot_mods_addr], ebx + dec dword [_multiboot_mods_count] + + ;; + ;; get extended memory size in KB + ;; + push ebx + xor ebx,ebx + mov [_multiboot_mem_upper],ebx + mov [_multiboot_mem_lower],ebx + + mov ax, 0xe801 + int 015h + jc .oldstylemem + + cmp ax, 0 + je .cmem + + and ebx, 0xffff + shl ebx,6 + mov [_multiboot_mem_upper],ebx + and eax,0xffff + add dword [_multiboot_mem_upper],eax + jmp .done_mem + +.cmem: + cmp cx, 0 + je .oldstylemem + + and edx, 0xFFFF + shl edx, 6 + mov [_multiboot_mem_upper], edx + and ecx, 0xFFFF + add dword [_multiboot_mem_upper], ecx + jmp .done_mem + +.oldstylemem: + ;; int 15h opt e801 don't work , try int 15h, option 88h + mov ah, 088h + int 015h + cmp ax, 0 + je .cmosmem + mov [_multiboot_mem_upper],ax + jmp .done_mem +.cmosmem: + ;; int 15h opt 88h don't work , try read cmos + xor eax,eax + mov al, 0x31 + out 0x70, al + in al, 0x71 + and eax, 0xffff ; clear carry + shl eax,8 + mov [_multiboot_mem_upper],eax + xor eax,eax + mov al, 0x30 + out 0x70, al + in al, 0x71 + and eax, 0xffff ; clear carry + add [_multiboot_mem_lower],eax + +.done_mem: + + ;; + ;; Retrieve BIOS memory map if available + ;; + xor ebx,ebx + mov edi, _multiboot_address_ranges + +.mmap_next: + + mov edx, 'PAMS' + mov ecx, multiboot_address_range_size + mov eax, 0E820h + int 15h + jc .done_mmap + + cmp eax, 'PAMS' + jne .done_mmap + + add edi, multiboot_address_range_size + + cmp ebx, 0 + jne .mmap_next + + ;; + ;; Prepare multiboot memory map structures + ;; + + ;; Fill in the address descriptor size field + mov dword [_multiboot_address_range_descriptor_size], multiboot_address_range_size + + ;; Set flag and base address and length of memory map + or dword [_multiboot_flags], 40h + mov eax, edi + sub eax, _multiboot_address_ranges + mov dword [_multiboot_mmap_length], eax + + xor eax, eax + mov ax, ds + shl eax, 4 + mov [_multiboot_mmap_addr], eax + add dword [_multiboot_mmap_addr], _multiboot_address_ranges + +.done_mmap: + + pop ebx + + ;; + ;; Begin the pmode initalization + ;; + + ;; + ;; Save cursor position + ;; + mov ax, 3 ;! Reset video mode + int 10h + + mov bl, 10 + mov ah, 12 + int 10h + + mov ax, 1112h ;! Use 8x8 font + xor bl, bl + int 10h + mov ax, 1200h ;! Use alternate print screen + mov bl, 20h + int 10h + mov ah, 1h ;! Define cursor (scan lines 6 to 7) + mov cx, 0607h + int 10h + + mov ah, 1 + mov cx, 0600h + int 10h + + mov ah, 6 ; Scroll active page up + mov al, 32h ; Clear 50 lines + mov cx, 0 ; Upper left of scroll + mov dx, 314fh ; Lower right of scroll + mov bh, 1*10h+1 ; Use normal attribute on blanked lines + int 10h + + mov dx, 0 + mov dh, 0 + + mov ah, 2 + mov bh, 0 + int 10h + + mov dx, 0 + mov dh, 0 + + mov ah, 2 + mov bh, 0 + int 10h + + mov ah, 3 + mov bh, 0 + int 10h + movzx eax, dl +; mov [_cursorx], eax + movzx eax, dh +; mov [_cursory], eax + + cli + + ;; + ;; Load the absolute address of the multiboot information structure + ;; + mov ebx, [_multiboot_info_base] + + ;; + ;; Enter pmode and clear prefetch queue + ;; + mov eax,cr0 + or eax,0x10001 + mov cr0,eax + jmp .next +.next: + ;; + ;; NOTE: This must be position independant (no references to + ;; non absolute variables) + ;; + + ;; + ;; Initalize segment registers + ;; + mov ax,KERNEL_DS + mov ds,ax + mov ss,ax + mov es,ax + mov fs,ax + mov gs,ax + + ;; + ;; Initalize eflags + ;; + push dword 0 + popf + + ;; + ;; Load the multiboot magic value into eax + ;; + mov eax, 0x2badb002 + + ;; + ;; Jump to start of the kernel + ;; + jmp dword KERNEL_CS:(LOAD_BASE+0x1000) + + ;; + ;; Never get here + ;; + +.exit: + mov ax,04c00h + int 21h + + +; +; Print string in DS:DI +; +print_string: + push ebp + mov bp, sp + push eax + push edx + push edi + + mov ax, 0x0200 +.loop: + mov dl, [di] + cmp dl, 0 + je .end_loop + cmp dl, '%' + jne .print_char + inc di + mov dl, [di] + cmp dl, 'a' + jne .not_ax + push eax + mov eax, [ss:bp - 4] + call print_ax + pop eax + jmp .next_char + +.not_ax: + cmp dl, 'A' + jne .not_eax + push eax + mov eax, [ss:bp - 4] + call print_eax + pop eax + jmp .next_char + +.not_eax: + cmp dl, 'c' + jne .not_cx + push ax + mov ax, cx + call print_ax + pop ax + jmp .next_char + +.not_cx: + +.print_char: + int 0x21 + +.next_char: + inc di + jmp .loop + +.end_loop: + pop edi + pop edx + pop eax + pop ebp + ret + +; +; print_ax - print the number in the ax register +; + +print_ax: + push ax + push bx + push cx + push dx + + mov bx, ax + mov ax, 0x0200 + mov cx, 4 +.loop: + mov dx, bx + shr dx, 12 + and dl, 0x0f + cmp dl, 0x0a + jge .hex_val + add dl, '0' + jmp .not_hex + +.hex_val: + add dl, 'a' - 10 + +.not_hex: + int 0x21 + shl bx, 4 + dec cx + jnz .loop + + pop dx + pop cx + pop bx + pop ax + ret + +print_eax: + push eax + push ebx + push ecx + push edx + + mov ebx, eax + mov ax, 0x0200 + mov cx, 8 +.loop: + mov edx, ebx + shr edx, 28 + and dl, 0x0f + cmp dl, 0x0a + jge .hex_val + add dl, '0' + jmp .not_hex + +.hex_val: + add dl, 'a' - 10 + +.not_hex: + int 0x21 + shl ebx, 4 + dec cx + jnz .loop + + pop edx + pop ecx + pop ebx + pop eax + ret + +STRUC pe_doshdr +e_magic: resw 1 +e_cblp: resw 1 +e_cp: resw 1 +e_crlc: resw 1 +e_cparhdr: resw 1 +e_minalloc: resw 1 +e_maxalloc: resw 1 +e_ss: resw 1 +e_sp: resw 1 +e_csum: resw 1 +e_ip: resw 1 +e_cs: resw 1 +e_lfarlc: resw 1 +e_ovno: resw 1 +e_res: resw 4 +e_oemid: resw 1 +e_oeminfo: resw 1 +e_res2: resw 10 +e_lfanew: resd 1 +ENDSTRUC + + +_mb_magic: + dd 0 +_mb_flags: + dd 0 +_mb_checksum: + dd 0 +_mb_header_addr: + dd 0 +_mb_load_addr: + dd 0 +_mb_load_end_addr: + dd 0 +_mb_bss_end_addr: + dd 0 +_mb_entry_addr: + dd 0 + +_cpe_doshdr: + times pe_doshdr_size db 0 +_current_filehandle: + dw 0 +_current_size: + dd 0 +_current_file_size: + dd 0 + +_lst_name_local: + times 2048 db 0 + + ;; + ;; Load a SYM file + ;; DS:DX = Filename + ;; +sym_load_module: + call load_module1 + call load_module2 + mov edi, [next_load_base] + add edi, [_current_file_size] + + mov eax, edi + test di, 0xfff + jz .sym_no_round + and di, 0xf000 + add edi, 0x1000 + + ;; + ;; Clear unused space in the last page + ;; + mov esi, edi + mov ecx, edi + sub ecx, eax + +.sym_clear: + mov byte [esi],0 + inc esi + loop .sym_clear + +.sym_no_round: + + call load_module3 + ret + + ;; + ;; Load a PE file + ;; DS:DX = Filename + ;; +pe_load_module: + call load_module1 + + ;; + ;; Read in the DOS EXE header + ;; + mov ah, 0x3f + mov bx, [_current_filehandle] + mov cx, pe_doshdr_size + mov dx, _cpe_doshdr + int 0x21 + jnc .header_read + mov dx, error_file_read_failed + jmp error +.header_read + + ;; + ;; Check the DOS EXE magic + ;; + mov ax, word [_cpe_doshdr + e_magic] + cmp ax, 'MZ' + je .mz_hdr_good + mov dx, error_bad_mz + jmp error +.mz_hdr_good + + ;; + ;; Find the BSS size + ;; + mov ebx, dword [_multiboot_mods_count] + cmp ebx, 0 + jne .not_first + + mov edx, 0 + mov ax, 0x4200 + mov cx, 0 + mov dx, 0x1004 + mov bx, [_current_filehandle] + int 0x21 + jnc .start_seek1 + mov dx, error_file_seek_failed + jmp error +.start_seek1: + mov ah, 0x3F + mov bx, [_current_filehandle] + mov cx, 32 + mov dx, _mb_magic + int 0x21 + jnc .mb_header_read + mov dx, error_file_read_failed + jmp error +.mb_header_read: + jmp .first + +.not_first: + mov dword [_mb_bss_end_addr], 0 +.first: + + call load_module2 + call load_module3 + ret + +load_module1: + ;; + ;; Open file + ;; + mov ax, 0x3d00 + int 0x21 + jnc .file_opened + mov dx, error_file_open_failed + jmp error +.file_opened: + + ;; + ;; Save the file handle + ;; + mov [_current_filehandle], ax + + ;; + ;; Print space + ;; + mov ah,02h + mov dl,' ' + int 021h + + ;; + ;; Seek to the start of the file + ;; + mov ax, 0x4200 + mov bx, [_current_filehandle] + mov cx, 0 + mov dx, 0 + int 0x21 + jnc .seek_start + mov dx, error_file_seek_failed + jmp error +.seek_start: + ret + +load_module2: + ;; + ;; Seek to the end of the file to get the file size + ;; + mov edx, 0 + mov ax, 0x4202 + mov dx, 0 + mov cx, 0 + mov bx, [_current_filehandle] + int 0x21 + jnc .start_end + mov dx, error_file_seek_failed + jmp error +.start_end + shl edx, 16 + mov dx, ax + mov [_current_size], edx + mov [_current_file_size], edx + + mov edx, 0 + mov ax, 0x4200 + mov dx, 0 + mov cx, 0 + mov bx, [_current_filehandle] + int 0x21 + jnc .start_seek + mov dx, error_file_seek_failed + jmp error +.start_seek + + mov edi, [next_load_base] + +.read_next: + cmp dword [_current_size], 32768 + jle .read_tail + + ;; + ;; Read in the file data + ;; + push ds + mov ah, 0x3f + mov bx, [_current_filehandle] + mov cx, 32768 + mov dx, 0x9000 + mov ds, dx + mov dx, 0 + int 0x21 + jnc .read_data_succeeded + pop ds + mov dx, error_file_read_failed + jmp error +.read_data_succeeded: +%ifndef NDEBUG + mov ah,02h + mov dl,'#' + int 021h +%endif + + ;; + ;; Copy the file data just read in to high memory + ;; + pop ds + mov esi, 0x90000 + mov ecx, 32768 + call _himem_copy +%ifndef NDEBUG + mov ah,02h + mov dl,'$' + int 021h +%else + mov ah,02h + mov dl,'.' + int 021h +%endif + + sub dword [_current_size], 32768 + jmp .read_next + +.read_tail + ;; + ;; Read in the tailing part of the file data + ;; + push ds + mov eax, [_current_size] + mov cx, ax + mov ah, 0x3f + mov bx, [_current_filehandle] + mov dx, 0x9000 + mov ds, dx + mov dx, 0 + int 0x21 + jnc .read_last_data_succeeded + pop ds + mov dx, error_file_read_failed + jmp error +.read_last_data_succeeded: + ;; + ;; Close the file + ;; + mov bx, [_current_filehandle] + mov ah, 0x3e + int 0x21 +%ifndef NDEBUG + mov ah,02h + mov dl,'#' + int 021h +%endif + + ;; + ;; Copy the tailing part to high memory + ;; + pop ds + mov ecx, [_current_size] + mov esi, 0x90000 + call _himem_copy +%ifndef NDEBUG + mov ah,02h + mov dl,'$' + int 021h +%else + mov ah,02h + mov dl,'.' + int 021h +%endif + + mov edx, [_mb_bss_end_addr] + cmp edx, 0 + je .no_bss + mov edi, edx +.no_bss: + test di, 0xfff + jz .no_round + and di, 0xf000 + add edi, 0x1000 +.no_round: + ret + +load_module3: + mov bx, [_multiboot_mods_count] + imul bx, bx, multiboot_module_size + add bx, _multiboot_modules + + mov edx, [next_load_base] + mov [bx + mbm_mod_start], edx + mov [bx + mbm_mod_end], edi + mov [next_load_base], edi + mov dword [bx + mbm_reserved], 0 + + inc dword [_multiboot_mods_count] + + mov eax, 1 + + ret + + ;; + ;; On error print a message and return zero + ;; +error: + mov ah, 0x9 + int 0x21 + mov eax, 0 + ret + + ;; + ;; Copy to high memory + ;; ARGUMENTS + ;; ESI = Source address + ;; EDI = Destination address + ;; ECX = Byte count + ;; RETURNS + ;; EDI = End of the destination region + ;; ECX = 0 + ;; +_himem_copy: + push ds ; Save DS + push es ; Save ES + push eax + push esi + + cmp eax, 0 + je .l3 + + cli ; No interrupts during pmode + + mov eax, cr0 ; Entered protected mode + or eax, 0x1 + mov cr0, eax + + jmp .l1 ; Flush prefetch queue +.l1: + + mov eax, KERNEL_DS ; Load DS with a suitable selector + mov ds, ax + mov eax, KERNEL_DS + mov es, ax + + cld + a32 rep movsb +;.l2: +; mov al, [esi] ; Copy the data +; mov [edi], al +; dec ecx +; inc esi +; inc edi +; cmp ecx, 0 +; jne .l2 + + mov eax, cr0 ; Leave protected mode + and eax, 0xfffffffe + mov cr0, eax + + jmp .l3 +.l3: + sti + pop esi + pop eax + pop es + pop ds + ret + +; +; Loading message +; +loading_msg db 'Loading: ',0 + +;; +;; Next free address in high memory +;; +next_load_base dd 0 + +; +; Needed for enabling the a20 address line +; +empty_8042: + jmp empty_8042_1 +empty_8042_1: + jmp empty_8042_2 +empty_8042_2: + in al,064h + test al,02h + jnz empty_8042 + ret + +; +; GDT descriptor +; +align 8 +gdt_descr: +gdt_limit: + dw (5*8)-1 +gdt_base: + dd _gdt + + ;; + ;; Our initial stack + ;; +real_stack times 1024 db 0 +real_stack_end: + + ;; + ;; DOS commandline buffer + ;; +dos_cmdline times 256 db 0 +dos_cmdline_end dw 0 + + ;; + ;; Boot information structure + ;; +_multiboot_info_base: + dd 0x0 + +_multiboot_info: +_multiboot_flags: + dd 0x0 +_multiboot_mem_lower: + dd 0x0 +_multiboot_mem_upper: + dd 0x0 +_multiboot_boot_device: + dd 0x0 +_multiboot_cmdline: + dd 0x0 +_multiboot_mods_count: + dd 0x0 +_multiboot_mods_addr: + dd 0x0 +_multiboot_syms: + times 12 db 0 +_multiboot_mmap_length: + dd 0x0 +_multiboot_mmap_addr: + dd 0x0 +_multiboot_drives_count: + dd 0x0 +_multiboot_drives_addr: + dd 0x0 +_multiboot_config_table: + dd 0x0 +_multiboot_boot_loader_name: + dd 0x0 +_multiboot_apm_table: + dd 0x0 + +_multiboot_modules: + times (64*multiboot_module_size) db 0 +_multiboot_module_strings: + times (64*256) db 0 + +_multiboot_address_range_descriptor_size dd 0 + +_multiboot_address_ranges: + times (64*multiboot_address_range_size) db 0 + +_multiboot_kernel_cmdline: + db 'multi(0)disk(0)rdisk(0)partition(1)\reactos' + times 255-($-_multiboot_kernel_cmdline) db 0 + + ;; + ;; Global descriptor table + ;; +_gdt: + dw 0x0 ; Zero descriptor + dw 0x0 + dw 0x0 + dw 0x0 + + dw 0xffff ; Kernel code descriptor + dw 0x0000 + dw 0x9a00 + dw 0x00cf + + dw 0xffff ; Kernel data descriptor + dw 0x0000 + dw 0x9200 + dw 0x00cf + + dw 0xffff ; Loader code descriptor +_loader_code_base_0_15: + dw 0x0000 +_loader_code_base_16_23: + db 0x00 + db 0x9a + dw 0x0000 + + dw 0xffff ; Loader data descriptor +_loader_data_base_0_15: + dw 0x0000 +_loader_data_base_16_23: + db 0x00 + db 0x92 + dw 0x0000 + +error_pmode_already: + db 'Error: The processor is already in protected mode' + db 0xa, 0xd, '$' +error_file_open_failed: + db 'Error: Failed to open file' + db 0xa, 0xd, '$' +error_file_seek_failed: + db 'Error: File seek failed' + db 0xa, 0xd, '$' +error_file_read_failed: + db 'Error: File read failed' + db 0xa, 0xd, '$' +error_coff_load_failed: + db 'Error: Failed to load COFF file' + db 0xa, 0xd, '$' +error_bad_mz: + db 'Error: Bad DOS EXE magic' + db 0xa, 0xd, '$' diff --git a/loaders/dos/makefile b/loaders/dos/makefile new file mode 100644 index 0000000..eeb5f52 --- /dev/null +++ b/loaders/dos/makefile @@ -0,0 +1,31 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +include $(PATH_TO_TOP)/rules.mak + +all: loadros.com + +loadros.com: loadros.asm + $(NASM_CMD) -fbin -o loadros.com loadros.asm + +clean: + - $(RM) loadros.com + +.PHONY: clean + +install: $(INSTALL_DIR)/loadros.com + +$(INSTALL_DIR)/loadros.com: loadros.com + $(CP) loadros.com $(INSTALL_DIR)/loadros.com + +.PHONY: install + +dist: $(DIST_DIR)/loadros.com + +$(DIST_DIR)/loadros.com: loadros.com + $(CP) loadros.com $(DIST_DIR)/loadros.com + +.PHONY: dist + +# EOF diff --git a/makedisk.bat b/makedisk.bat new file mode 100644 index 0000000..f743e2b --- /dev/null +++ b/makedisk.bat @@ -0,0 +1,33 @@ +@echo off +echo copying latest files to a:... +copy /Y bootflop.bat a:\autoexec.bat > NUL: +echo bootflop.bat to a:\autoexec.bat +copy /Y loaders\dos\loadros.com a:\ > NUL: +echo loadros.com +copy /Y ntoskrnl\ntoskrnl.exe a:\ > NUL: +echo ntoskrnl.exe +copy /Y services\dd\ide\ide.sys a:\ > NUL: +echo ide.sys +copy /Y services\fs\vfat\vfatfsd.sys a:\ > NUL: +echo vfatfsd.sys +copy /Y services\dd\blue\blue.sys a:\drivers > NUL: +echo blue.sys +copy /Y services\dd\keyboard\keyboard.sys a:\drivers > NUL: +echo keyboard.sys +copy /Y subsys\smss\smss.exe a:\subsys > NUL: +echo smss.exe +copy /Y lib\ntdll\ntdll.dll a:\dlls > NUL: +echo lib\ntdll\ntdll.dll +copy /Y lib\kernel32\kernel32.dll a:\dlls > NUL: +echo lib\kernel32\kernel32.dll +copy /Y lib\advapi32\advapi32.dll a:\dlls > NUL: +echo lib\advapi32\advapi32.dll a: +copy /Y lib\user32\user32.dll a:\dlls > NUL: +echo lib\user32\user32.dll a: +copy /Y lib\crtdll\crtdll.dll a:\dlls > NUL: +echo lib\crtdll\crtdll.dll a: +copy /Y apps\shell\shell.exe a:\apps > NUL: +echo shell.exe + + + diff --git a/media/fonts/helb____.ttf b/media/fonts/helb____.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ecc9e80d898b6e9aeeb11698f63ed221627283ae GIT binary patch literal 51648 zcmdqK349yXy+3-+jAlmrzFCqj$+9im@*-Q_k|?&a?+GCx`{F=WvJgVZMo0{031Le@ zpzP4n(w5Q!xBd5agPMef-j>pZmJ5aU(#O4}djoB6)81Hm-*aXpjT42m_ulvUy!WKo z@<__eIluE;zrWx44WWb(HyI)Z^7xdAlNW9bKl30Vw1p7sSEo#zJ!#Ie+BbgKPaJ&M?-VIy!uK$;x9;3?#39{;<7WvGW1H9Q*w*^V=Kmt( zneP+g`ll^dU9pCA9>aHE#COEHt!wsdr-$f26Y|oh@&9An)@)s8cwBrA$KN7E_}ccX zuG#s;#eLr)1wFemh zw(8m7I~Fssn6l&mS&wIy>>=MB`rgpXLxth}Lk3(>93IXM*$vbpr3VM!Q7=9?IGDB@ zh(#L4AL;{dvGJIt*qPWHMk6(ugTY{-fL}O?z)vC=h$NjpEvUy9oKj~07yok*r?n{5 zV(Q!f`%~=k`~7_u3CF>{J#XBPbKt>0&mK5+O11{mgZVr^-k(1uM$B8Jv^MY3X+K^=E6{6h!FOhe>OB2l;z;y5W9qN55{AU z^rcBUZLtUzN0bZ>&wb};>}c#`u_tm*=9Uh{hND;!VlhWZg!J&|733hEFAlM%#Y8RU z0?y73im&(!f3uG)HTdQgLobqH{(KRCA0##WBlB5OASa1>8ut4nj?WT{5tJ(whKKWc ztV5wN`WPz%2C+oR!J(fI4-XBKmxo`**VYUl9FFGrSc>Ok^DX|3Vd|NcuP-hns}H_j zxT^W(SKmH!=FHo#y!!G z`1R$XleoIYtWscT%~0`F80*l%Ay9x#GhaA)@?`!j`^?Iw1!C#G`pWPIe6@Or@Hv-= z%*dQ4FB5iw7l+w-%-Mq{htC{vh$r(|ixI@-oUSn{Tc0u=)W6=vBJ^Vj`0B}%@2y|I zet$Nb4O(oF%9n#L2jA=4`mFlg_-x-h?5TeBz4iE3HoN}4liGh>e;}(}MZKzQjRe!% z2MYxzq4Md|7DZGnUuhK7c6xxrY>>2xxQ#aEcjsSn7ap+L#@)6_@`#)2pk3wh_A zL8C&AU{h;$%PVJh6_@3WvyjYJ&%R-l@nPToSB8gQ(PRiq+H(LO{{BD@`=5~EQ(&Y6 zSqsxneR~GaoM93^IEXVDP1-kioyzYop84(kFCb*6PH7B7ic_#-IEKMN!v8b-_0F(G zh5+I7SKc^%`pg@zymBs&87pM3+T)sL_T z(=tlbD8F&$9X=vH@jYjU&+NCJ-D8HPlVjS{_Vn?y@=3g!-^E292V1uE_4OGo#Atm9 ze7kMT{q%PBp>p;tQ*vj|s(Lra9&8=)NLwh3 z09Lj5Q1x((J)BPdGAu|V1+wvoBoaX!9E|0LM0tde^z@q~nFz|3Ep^k62v$LGoJyZc z+rURguvD3WOJ5eLBH=&hVipInIHUQ2{MEyp7WrW)ik}Z3#5=f#MZ}kehxuRpY7$mS z!8P7^1J|>t*E1M!vcc1*2L&UMAT5HK$mYUup*U9Anm1VU>BL}Su=erV$9Fv|v8&_S zP_H&(w2wc1@XUL`lV?tzd6^tMlRb@L+e~%j^fx+&jZp4>JvKB?kO}igwdr znlNjoSv3Au5R^XWEoYx2$#?(w$G6`4-uGTUX*W~5C5X`y*k-*6Dq1W41^HrMu)=-*&@;G6%ZGm< zLoyfqg2loNf9xR0`}22B48An@t-;gpfYif}5k@O>+6e*VkM|B_8I8?W5c!<9oQ;!p zZ}I=Pe!cD;ZU*+8edU!m-gxEI>pz1&gpSAZ=?#!Ec+PQp`smL=+fm=&vZZuvgMx1Frigb{aj2RmhMltFbqZoCJd6kZt z@ft20FN+ARJy_-&Zku&nV`iG6%tV|hUDHX?Z1H10oRZ~&bIgXLJLbdD9pnFx`ux&mR(d_XjeeAVf_{Mx z)9=&Y2(l0tvch6vgRomTCVWnKUihx?Q{i`_QA~*a;#_gFc#C+S_@wxv_yh5`;#q^$ z5HYkH1`L-PmKs(YHW+pqZZaG-e9Z89!wZI24L>vdUZRpqic3AxBJKq}(M>mKVxv<(=}am;n_+ z!q5XGq zVCs@kgZ2qKP#+ZEQ6Cy-YDee4sN)mCn{eES2`gxUmbMW)nAu5OSWgdZr;qqafCNbu z36U^HPz^N?7lOoLRTD6s^`wC$Nh5f;nWUhjTS*&fhcD7WI-!ueNH?r!FQjD*84E7Y zlJSTh21t%fAQQ8BbSi*6fd2Y7@;=US zsqP$}STGjR&M`)J4xHwH@SvDap5&>48mSpiE1pj3rkylPC)2fbAD;Vl&ja*EdW-fv z1eEF!=JEe+4qsd1P?a|sXWq!U@@9=688=>>5A|GF=D~~e--WpEB}mwA==k-JxSh}y zOtzS$t>dz`0kU{CByuw(?VFG|=-0yH!e0bM_%`_$@bOXb_yq9gGDzM-^s96^?V&sA z@9A^P9?(CbnM^rKT6Rr|JuB8vNvzozOl%yS+zS2%K1#m?O)KI%i*hkIJvo!07$n$Q zNfHIgz(N|C3Q*mYlBv7edxK;k+n#lfuz$2YJA#9eEa^zo85_R>7B$Y;xaQg1rAzu; zyo?(Dn)u?yE;hOhrlI01d>APaD9r!(iGifp$D zB9$Cg3!H7MY_{L>+S*DNcIq$eWEb{id|pLX5)H|QZdb;aSay%q zY?*JdSdJYNPQ2H5$>hnCC(Rq1|H^S96h`P_x{i;GBRA336 z4$19u*d@^*%YKW?sfcoUQ~^$sK$#%Ukv8@y(|?BveMhrt^Vbp zVuQP*ezxd&1N-;#&9Sg`YELv^MF+RAC?b);5WUs&G=I3dA9V|OZ@$FkJ&eM?@>F!G6 z(Vrj_!i8p7QhHVhe-FP|`ZGu>nAuk+Gy{!8gZ!moH>s3js7{vrmT zyF~a!A$U676)^$l^{P?9!@tS0HZ+CCE;9r=mi6-YR zXo^=S7e{R7?mpqfNWbvy8QDee&lljl5S!rn9m3Gq*K`T~3?HY>75CMV&5-%k6Ap6p?!AIRL5Q$c4&q{u3ozGh8y-Ss7pO8 zoS?(MdGDQ_tF|3{^G#fn;+kR1*iEM7{M6&gdCinKa9PRhu*(2Q9p#HMAz(~j?9_BLv7XMee)Bkrn)&pGeXr=qWia8deg2IS6#nn+v;t*m#)Ix z3xA`#>17y)ojjGhlsX(ar)-uCl-O-nqaqtbgJhOu7!X-jtQM=yY_nS|Ru~`r2l$?X z-A-&aJ1%H68%@k6nal!}45GyZ1wcz8-L4wbq6lB;wG#It^wLk(!6(astd8yH1z}-()b?NUheKO|r-U z`Ay6>F)GkNm@!;pm^t_Xg2_0_JJJlB`oh$9aq*E!){o4}N0!0JV27ZX6E*K|_`@GI zyiXUs|Ni>Zr!kI1VF@CRqlhf0=YrH^%9$l2Y=;PkL^2o&*Mr4XAJ9lP>Ut*q^-Sz~ z0nO`B5)-Y{j^4km=8~h=A8*99+~hm7oz8~_>d(319pohVeFhdQ<1(7>$BYyA`pPph z=&xYlGm87-Zd#pxm(ITh|GNo(-t&m+L^6=`6wizF06%Z>#LTI@=!ttlrl#Y^j~xRS z{u;}42e?oq^K&)oSydBaDVh+?NQfo+Xs!m_2WAj7RVR}3C&26hwI9g8eSqn1hEDkk zzXL|}V?^{pNMC?fRpmkeM{FKRa>*v2OsR?5)C;vk)o9ALcnuq=(i5qQ5sCJmXIZ$x z@lr3nslUBr;FiO=j?Ua|Yd2jX{D>Z0bNt>l2M(@z;K7xLWnF#k*O-AOpGqEZY7$nwQ_VVn3IO#`*6buwSOk6JXZl4Sr$(CB_g|+0fgXpu_F$Y9pPFkY2q5FPeTU*aww}-mS`??zk zZ@*#7n%uNSn+|W=ed}+ieb@N5E5)mX)s5}@q%A|~?p0e;=`CAtyk$4zRjiN+Tww0O8@gQReP>VWj7L&mUg9&fSV}VAK5iy8RZY!QUK=F&(+K38m1W*cVTw%`mS!~SILU+*I$`G|L**6!R2z#4%$uc%+K6)-+jA6 zZRy~$>=h@mIsy1U3dSELyWk73xW@0YTA~QPtWF1f9#{{n)h0{+C{e0Rvd8I=ZHPds zsNE*gXi3`n;xMO>tqvQuT@`%3LM6ip5KcdCHAcX?Fb@WNhoFG*n#y|I+evmMpAJp# zs0sI_TWgP|F#dO(6WZ1vxOw~Fq}dkw^75wo&h*4uddr?$y*IAE`i|!GGK(LpQd9VY zV1e9(5h*OqC1^`auGOZ5l}5=IlWY;$RVSN7IY5*^AS}2j^=T6s;Od0U1JhuhM9Gu& zkrw^XTNud!31iT*ugFb&$lcC3<1LX-D#>QWoqxJhNYxKi`^L;zo9*kLaOK?-x~TX} zv*D+$A%7s8PFMMY5y9HfIjwV6$CL@{H&2;*?TQEK-ltsF{NiM7d#0{A8P9aoLA?W8 z0MB``W_E6;m`@O-eR=LiAoPxI`(5ftRB5Q=!2InOiJ)JX*&Z;w96xd>T(9_#c51%SU5gi1;L_H#t zbP$|*#@!S9moFQby8ilUlQwOdJY!(&8k%yt!|r)re{C`~r*-VubbH@8!L_U>)84gs zb8E}t4dcg-$!-|9!r#55I#jbb5e#?a4@_+Bm^dljo?}+YS@;7z3!Y-J)H3i?DwS*T z8AC=TDLJE(FDzRVvIjH_fvY?LN}a{Yan!Hh_x2>ap?cLg zs3#M1Ipehr$=-8#>eDTWT(yt7n(E?fvttfkNyU7AaHsj*_K-gqVJuY@`BI{1QpZfi z@32k=Q{9ojJ%4oL>Sr2jJ3AANO^Hl8k;KfFz-Rak{Vmp1A(!Ri9G8M?&Acz>e8D4; z33KwHrD1z308=VHRAR65VJVS5ZJ}77TH9hV9h2<4JDmZ2F7rGC%}!enKO{{6(k#j$k@9SaL9=zM~^B} zqs2e%=;bbx!-kRN$I>W_&#?p7W=z22;QRb*;S7CE5Rh}&l53-ik~0FXGcYd=Zvo>K zWKaiX7x09Pf(V>P1ZstWmqt3Ef-X>qMZa3}qf2g)fhc-DP`GljQD1#`J$)^|n0_X2 zpl9g|FTObW7yZ8g_udlA2Gzbpg}M zAF^Ia=wTQ85gr^_&wl>8fhIOoriS6-)W9N^*yiHYK-TI!Y9w1}x8#$WK#IlmY~GM9 z(E^zsBDjPfAj=ac>vB!Bwlv~s#SoGW(Hc1xkFjvQ$i*Dt zH%vv&8gw*N>Q+tj+VsSY93C>nfM$C6&d={8JZQF(^b6T65T5oPKPH(A; zweJ;g{pPV_^p{(5OrCP(m-T8ky3W>O<@H=s>@N;Cerji}G zG@UjrH$5|TY(u@n4y4jz$ONQJRBACuIU-M1ax4U@foIH zIYO$TTH3O=kZJmfP2)VrjTP5F(4@T?!3Si98Rw!MV`{cHV~5#ekeB8}K}|JuGiAlW z9K0#GCbTxSCi~l(+Ap87+&4beaOvFLH!Z&Gi#JWZAvLMv)2l!B)1N+k#}&}amxt?x z-U$N>`zNixBtic)DLc7w%(Q`tb$xyLpTw#!nKJ3x=~GrOzvZScW_#wZe(PfozkS)# z!|Ru=sSDHo!Q7Sem(GPOyo>ce2y3Xo2V0Bvw^(vk!DKcn0zzDa$snm1m)QtD<^C5` z80wo!YJ|bba9c*nX36X$qpqitg)e``lSl%=q!#+UQ@{RP%kNsAqK{m%fJHBN-%UZB z{7;#EM6Ov_k8#jziO2N#bqjGN;OO_ajrO;MkRdA@jUrwXmDlU}9IOq+5?{>Q88n?J{W_df~u3$MaETm-wIqTWu2 zQ3^QhiU%HH*dT|kvL`HhC=F;7ggUR07?+l}Hq2Gqn|fCWo_7einf z3;xyAlI&g8)t>5HGii`1uytI=9?Y!`6yD0${c>&HHC#)URFumC;)2E;;R28Vw5v?#Kz2aW zQGCt$uQHu0EICU8GDrc_X?vK;k35q98}QBiU#JPNLVNxPjM_jm$Qu}uNOC!^4kyxZ z9GwcfC{X0VwfY`^Tt#naVWe=Heg|jv!k3IupD*XPTP>2!E>ThP;>wCsk)2LzvzBM5 zLgp$Y#TlwRJ)eHrd~Dgoj92k$hRK!jc)61--bd%BU6zOFZ`NlgP^aQ?nl{D*-SnNj z>)pU?`((6d-AM$|eA$JP%h~4Rs;lC!DtsDzEFUMH%?5j5xYH z852?-iZ79V=>6~Ie@9a%el+nREXd!eoc~q+GMbw-qK&T+!~HH#)|oI>Bs2Oyb&vO@@8DA1tq}m;Yty*JJ-#vl0^z4&0)46&*<~{ zJ(49Hk|Mh>6q=<{>B10;k_jcGf|X)Gcz|I}jCqQ1 zg{X*rpDWSwv)V+18?sy=J&7_W>N;F3ryxJtgzpo3z%i(Z>eChaSX$3GD;S+*CY9e3$Be-v`|D8=dG|h zAyt{Ec^igd>gMCuQ`xUl*~2EpQs1tG2)&YI6KQ+m+cCvwk?(opR1*!D4M(x&$H&^6 zYClEkVu<3}8DeYQ)=d5}*eg@veN43)5sGuC#+nXn>lOXiox6r5SYu+JW$z=$e&>=9G!JbQZQf>trFgK z$W~LpF9VLKz_N_2stD=r>-mVShodMcDZt$7+~-uik^R5Au6XF`?`%Tuc;QEDvGy9_fk4rkz2F|)^GIp$hxPMMK3=og}a zEkwPN)O=>urT}@Y?+xhuYKC9*3g23~G_|bl@vp5~^Tb1gD`(`-F3E;kGfUTWwzPCE zO9wkvU+Ri|>tml>w`tS5NA6vmUDK1BzOsMnwElIga?>rCFXR8Ku`+(dLM)!HsmVnx z7O6Vo6TOn3R7qlWK=yhfVVU@SjQdA>7lE=lXQosiPovCPKdBnd^YKoGpn~oFS~d+X zrVA^@UCuVz_t*V1y^18p9}P)#@`42q(cV>C?-Wive{+LxQef+4P2LuBZhkKRAM~S_ z&HDtCU#W0fSSI`sNHOCph7?DWZdr;}N!G?Bz(Kd-^vO;^P9&&Pq{-sil%e4wXs0bj zvJxZ=Kv<1v)ZB9>7D)6IJx~rYf#dK|=9BcJ?X@kNpNec=GHWL_dLI=IrD~E}9#3vr zHgE6E^H)Ch&Ss~txjWKg@7}p>Z0Bz_I6TSLP}19T_0C*hUv3D- z55-0{R_tRCc_hMMm2(yWYoJxOjP~r#$5h0)4_O0OA}q{!?U6U39!E|IV?o8{!k>ge zt_2suXJ=Xv1u9n2EV-PpCO&MO@OY>bwJ)Px4CXd5ua_-+QK=A8N!7VH+{TCqm>CMs z8;`k~9|_gWn;!PiNAkbO|2y>D-1+gkhDgp53|i^Id`AJ7(6S<$m_63O))Ei zVuWXD21PKUVlEd>4@jX)9ih}y&w^?s=Jzlgl0n_@k<3beOH<<~|M1YSgcHx?KXvuJ zH{5_qfD`Ph|AugEDe}ivh++~n6v~AiRSrsg3bBfcGZ=7*PFm%#1B{n3f?^_{yInjU zP(@s0DioFK#}VS9(5(%GTQv{H!%TpTVO`%e!&Vas-yaH9+XI6SzI-fgtg*Wv;fmkBL&4IS^)6?c7o=zU|XkX zKxAt%8$|^kBSXqc=7A4=bVLg;p`@ZvGpnD1niv%`0T2?At&;fuo1eeo+ONL;+b`dF z`#;lNboLK_nEzt_@Y%DBmOsb17GhjRG80)amLnCZ5&2o9HZV3LD=WbpnrN~`Ecz&A z{dj(sG%RF9u(EjUmLpI9?$KX@eO{-{`KkFcfY-jtuKJ(2>I_`f1k2vWBNWAi^tXy| zF$c~fD{7)epfY4jW*mixss!_>u?kl6T&j$gvh#zMB#n2+eH1>FnO>j2Pw30vOg}R6 zx$Efjhp)>Iu#D?GR0{0E*c7q^IXW)o96L3z%&}4ePXV3k1P*eh3pJU{mu2pJQAb)N zf#gnn9!=hJPad*Ax_`+EKGqv0=a~6!~%HqC&GFcEXyJss0bmQi1P;5G*bM zB2MPt93$Mk>+Id^+SducBCm(X6&#cemwn1K_L!bgOb0>fCxqg0Y*=m98E!mBg2@Q4$1 zGzXneNgwz}Xt}<#6Epdl&_(_kR20eBoRgoE@hDCUxLA`JoKvUuXoZBiClScp`k8Bh zE!_pNAR(UXvXeOS5-f6Nc?nOg&tpd9?re}E&9%_{2HD;y2O%@|Ad8#r0*w^SCkwv7 zj79xl!U{Eg7pah=pc){kaOgAB>4Ql~a2H24s=Yk{Ie|0`Of6j(@l`i@{N`K4#PHAD z5148vw$ASwv#5UGBEwc;-rQOBbXyfGTWK&$wtHX7|1p$k@FtR}d8?aTe*3a;xUP2+ zn`IWW90SVvNCGHdGp(!3)tg+{&MpzJ$0gRnu!SU34HA_yDkrf41$?QOw}Am>Pc&=* z;)Xew6(S*ZdZwu3Ivo`(I)szC^wl&mIt7!xPrR&WL$;@HU~6kbi`8)K?3kLWK%{qE zO_gxs*M`pd(>L#!x6JEr^n|>dJDbLjYfQH{_TLAV#j5>YunA6h`wPL-%-gryYV3;S z6R}LP%dWU;h!PBrN=|C)#3#Y@xwb;SO0K__n&kLxGQhk~wlpfD0Ze0`p|fsGb#P-{ ztWG)RxMAI%DH9Iwo7X?tCCYSKqOC1C{*kIkLb+no?CJZidmx#bfvxgbg*vQ40;|Br zeK|Z#Hg4)P_@L=%STZ}YUy{0HIUw8Zg3M5VwgyF$4jnw8)y6SL1B;Q>t%14HET9p3 zRey}v!v)l=YSCSzcYO4ykXpNCd|z+>){Qlr##RTe>|+bSpor|8`7^HCF=z4E{IN{a z!10czY_=JjegqN$p{CxyY5Uf^K)tBUz#LECv^1Ei;Oy zp$QGBSQM=?K_xddF%Q^F`X4Y7mH@2J*dKNo^EubwbL-{6t;#`H&p7I1nE@m=n8WFs zK5yHYeur<(n&Z>y$W@DWn(Sk@=dYo6GU|p4mkQMa=m7+lX`{9_gyK=JJ!&J(QdON7 z4zJ*pjd9tZl&h-+8+N}lomzCdz#$CCQ?(K25)fJ!T~(1b{RrFG2x&(2`ZUz8on}}l z)zi)5MwXWWgx8=;3?u5j`z}G8GhzJ|eUm-Hqt@Azy|ziy)(?%#ZQLDKcK2q-cK7sG z*U*vtOmE|0x~Zmqk*Pfuo;~L9hAU^xxgwr_WqM!F^qIXqwe=V{Q%z33BFl62d_|1F zEhKDvcEBN%T*Sr}#4MU9D-PEg#sRE_s&Q3luO!Uq$)ca2wgg&<0cg*PVO@zy_f8#H z)|NUxXYswli9d`V*S#YDbsF8VK980u0`@MUaS2An^0_PqDElPkd@iq7I%iC(lSI|p zld^MA!5;x9_?T=S!$UZ+cXnRHbqjwktRz3>*L86n%{bKVG8lmWv5YR?YXC=qD99x{ zT~6#c-~%XUbkzYc-K-6QX=zQ%87dPdA^JP`f-@*EMQ0v6c9|_$Yc?FCkIWKI>>IgT zsCBl{Z;kv38E3U}q5&hckj3!T${66eu-|!vQDZU=xa-YE1wT6Dg2*#B+Lvg#=aH|x z_`|OpY`+H{?VX?hM*hSbZBJno*at#>$m#UIg1rvhgY&b>ISQPEh(5taYT+k$@Om+; z-GMy1-v@Xm4mTqv)e^xdyCTriwef)8F4?GA#&q#da|oD@;P#O(15Y_ILBvmSDF`{g zh|H5w5Q;(C@B;?*s4+ETSS`WhO4J{vHQ`w2+NOaupFS?o*Kyx2_>HHvc{~XM?Ghs)_kL=Ecfh{w7#p{Z~QGSWGJmHZ!ZI5@7!+L-ZUd z#r7&(&h&E`$ZB%NUfCpIax{*r9Nn_=BcChT)!W4@&!P5QiKe4;%A9BJrI(EH+U}tv zW2U{G{{ankcZaUopQ_H~{|1>$z%u3p?3_oG$?!WCWr}{ugcP4umXY9t`!7&a(djC> zBBdOYsX|yuSpm4J$a*{+wJ2G>uHE;3bkE*z(ZvD(OTrkEs)9@<~zAvl7|E(i&u6;WCggGgF_UfD5!Uw zm~86vDizb?Y%5SdWyur#!OSNexaiC0lpC~;C%2bYRP(=E1+Abrb{ICt_Q3LuOn2exo$Xm53Rj?`#@jc_>Jp3 zq%E6wU?$!x9(eg|b+{pk+D3g3xU54l`9H=-uw zL}UpYot$WC!piAk!ij-*y3(5pm*%yCfqe=e z8=5zvZ^er7Gj5B8;vsL<{Hq$~PtC4+*Yydd#^da&bw{iXmn>;b*0(OIaoa7nVA$dH zG%j1#-t>PMz5Vz#S9l0{sH<}so`-{J#JWOuLo7-$OX$b5oL60 z@~upN<}$G;R)ytwp_A$d>a^kcIVw-F%$&{H$9(VcG~u6i&+_FC^OTh)8UH#6JqR-UqeqFvDa_#J|1ZK-enXE;A^b_c7kqP2O^)7t2DeVdIB z-Y2LvG8(%xaHNG}cV$^)G{cC%s@gy*V|Q3_6}$U9&@o3~;IV(Y^9yuj$C=Guquy*m&HSyIV6?x!RDn+`P1 z7`$`=y`yGu_785#i%XYmnDfoY*@z2&!icT-%K}8EntK=}+)fA8p*@#=v>+81pOQwZ zh|nb&LdRW;#OI%Ua{hu(ed?>98yx&BwR~{%%^&3de9t{>l?XJX5!VlqOK^QgF_R(W z2Z_8+H{0JyLM9_x6X~f1Vr8@H5K6Z3!^j1g5Nwm8-JOBX43r`S`ibhAlwhj~g&+As z!r!pya=0Awl0}`JbY%Im+v2m=Enb{At_ihXO$Vyq+J8M8ryak3fN@qt^zbf2H~}Z2 zux=EhSLS=wS7bhl4(3tmSYGu?75BXqD3cH9dE8FT@6(6!)RrH=hBoZln}7dWjI6nk zrFF$$W5ic~x+qQqirzFu6^ zohC4et7gp55Wy0ilE6LVw6QVQM3UH{3Nlss?V?MP1V$yZDO#h00M4gU@rq{BsJ~(( z6VUo1VZdyR(^y2uVGK?eyv0lgG%T%~FIWRpCbhH+OX(89YM-D{=+}=q+LdLE(HVJN(gyv>(UYn8$-!~tHhUY)`Q)_@yOc5{>D_okXrH6~-Xp-8X;Q1r|7 zbyZ@prdkOb6~$(dZMAYZEF$UZE*oh!TqfUYOsD?V5P3~jiu6abBK<_v0{27>+&Cy{ zpQ0j2$wY6as~5j|;>er9kYj3bB>_hxPQUSgS=Y`P-)4D|hHkv&j%6#ISJqrAEUfA8 zq*d4#{c%eo+@C z^y$pIjTDyBo6(QM3~XvMMiUI?sytRp03yY59L!gTizqrJuLmWAq7*O_AiF@2i!90k z9xO6jVQi97mwvQmAtb0@<{%TZKtEM$qGbgu3rAhu9~PBx=I+W950O48|sDKW}Z^Nav_OSF#7QD@x&R zTHq1>6+oXV?Iq-;J*=1w>x!{3V^|D*i_RV!5O?)B?MmL%`J*ZNc?=d)o_Y9lpL_Tj zLHXL(uFp&KznDz_zlXahs{FT*KhqaDr?-r%V`rHZqlB$VETPCa4g1;DY#Q=M+B&tj zm+Y*L%ef9IFW330mEL4`uTKg5`H@F9ZQ63(itColpU*hmP&h6A3e_$_AQp$PE1gwl zn1a@z)uNU|lBnda#|{!!70D5!Vo78|wuiCZO|-LGB!;LJbsa-3IJnG|9b+U7Lt>F$ z=~0Gm+!d-cSdy>!WcXn*Oo_4`=;|&W7$N!#fueYEZ2lCza^!5^&SRI&UAX*#`7^{L zD>_j^vlM{b4Mz_=cSE#&>lODsa^=qU{HNzkT(c@S^I34GkKRr`C%gm+XZxsG{u_l| z5DB74X6z+o=2DkFD;Y~nM(<5jNQA@U^ulpqxLi|WHkw%o%Ivnr@VLgQ=!JKI{oANR zfMkBy{_S(F``_EYjjRFsecXXrn-G(+I%wAK1FoouOQRe|Lgb52%#ufq#EgC)8d=!& z$y*4c8h`P%#i;nebT;_>h991;o?aEQ?p0}{9@MQGN9RsE`h(V{3E^;H+EF2t-6Zxk zPCa%c*WT+}0tkAXjHFydRd7CE;=3E%LE_9QO*-`SxALuLFpN>T`^Fkn{6pef#x z3U<(%zpFzDR+#)7ZKCf&1NY?YT<^h!!zQ;ipv|M7X5PtSL((4`yMdE11EWS#H=d^?sMXTBY391R}LyMv~&o$KFm*3yFMBC$Ty z!%G6|(mcE$`m5S}m-u{i_6pw|pHG}EOiRZbf<9?ykZn;Z+)S&4&j_~w!|Wmdn%ho$ zdvkr!#`-`G-@QX99{nN8SpYq27aBX}flQ==rbq@ zfWuy2hr%ugfQz4P4yvd zp}p%uT?}%={2Lq|?*6jqihIVSAMBt#{)Ffj>GKEnZfVEyko$1Q{tkyRBHXf);+5uq z6mq*mw1t|S?Q|vE+3E`Bf63o7=f6#p|Hc2b2NjVe%PQEsi|`;{`@5{du%_5fW19?1sAf8b?7w0cH6Q}BT|jGsV;`@D=5R4sw}d* zUiR0@q*ac<9Mr|oyTJ`8D|8o% z%l~zJO)wlAJ1$xUDB87f-ad;b+tEfBwj^iGJHGq6k4~HW+Th?%GEEc4H??P)2gWy{ z99vYYiNsCZcXT3Wk>%?eHC$AHe-JfOJmm5j2XWEtcGGE7}Og z#M%#xW)bX1cR)S27Qs@4GH6N!{^a#XD-Iui`_Q2$)hZ-$)BgSYQ===9V9SuZ`3le7 zIQX6z-baf;Du`*+URo&H=IK}Fo#;|qSTPkHz#ru`GLVX`v=S_Y>}5sLfN+z?j)^u4 zZ>9z3;@h%57qg}jJUmio%EgD5 zBVcJ%U$MMET@^YQ^>!s;sI~Mm;PH}s7yvVIAjd(GMFIfO%PTLKOeK5nw=Er$SukzQ zo?C9;(GaeQ#>8D4WUsN-?2Ux42q(t(`?oeU-rdmFGV!Xj?SUzCCoJ!7yMDKFqsLcQ z)sps1afD;Fwv;Rq)5snXd(Ujh41Hz9{kDS7hXKe;8PXA z(q4fnXHaO%u|cL;7QM@Tp?%;rUR}0G>|Bk0`Veq6lQ74 zp0Ver55G8k`{5T~JiPC-pWTNaYBYF^xm3139!m@i^jjv)Ua)@s9QQ=G#~>Vf@$l`# zFCISp;>Z#HU3{Oud0lF3Pa28F)-Ko7^$X@+?Qw!Dfu+&S^i@QfHu7X{9<|$Z4x^35 zcBPt4b{i72h~j6~97D0`+7oGL3mh9@ziLY(MQv$hq>{C?PS9891*FBmwD_vQ>c#M{ zyqI=9KifG!vnbV<9H9Kg^WgmX4?h3U{P_>j**6}TFlFeb>u=mYdCEbyTdsh{ivs$5 zV4u!RW)tn4t9@xiF)(DeFxrq zVF&u)7=@2;USj?3p3KeV{q9WdZ9oRo?dc9>*V^*4mmSMu16voj3<+ZdZZpTb(mF~=;(AJ(g837JoV3OahSVN-U-9# zS)`>{p)+2f$Y4lbi<}9050(aTl+TAOJ0cFA9)mXJ$^kg|^M_wNaT^%&_I*z=CVTp` ztq-(Y4B=0FWK7dFmf-TCs)MmWx7YLH;oD9yRur~By-)pSeoe&Xs-ix>L2xf?>^p9E zJ>@q{OS`RJrU(8?cfk8T$|=b@3Nd7ji6ZD#q)3q*6*>xu6)-c8ZjwpeBySsc*=6JK zlWiH_-_p{bqdOL|!*Sylo*CcLGJbqZsvqO|7ckOG!e)%eL9T%($h-)HQ9&a~NQt&h z8C668r+AwfnRSd|?LAO1<3LGTsiIDG1i8J|Ay#~WO1UI+B^RT+)CH^Cg>1;v-S58J z{Vx44dI+!o{_oxSJ>A`m*Uzt4MWrf>_VByJJuG)r=7&mo10`WE)~muNFDw;UXEi6^ zqr&pw5E`IPtg#nbnaKv!wDBN@qd)kXNUggnXTM8-VO=+Cbq}l0JxhK>K1z3BU5ZgOcIBF&oVCIY zpkU=F+EgKm)~n&!(U$gDw6%@y=!iz!Tcfq;iCy@1Aw?z^-oU!ET4uKHMh7eq0RV>u zN1Jl=aiOx!sFd>#e36+5GXIg`AVp%MJG)+y@jk3dfC(GN5qRlE4@F1Q$@}c?v_0|( z>Ig2HoC!n?Y;C6seYGrVib5;0C5`{#L(ApILbozJx=5-?3wN zr<9qgx_IjzdRyI3H%#S?DTEV8vyKH_#_@HjRJdvn{h)j76|=e;8d}G)$n0HA-;lm(q0aVhMuFqIOt#BP;Y5LDd1T;7VJ?pl=;xV)u|tZr8O)#PkYD&=Mu=q9M< zX#=|>kyiaI4VsK>;pl|}bG;3DTiz+ug`UuCJGIq>j-17&n_A4FAsKEb8aDIz1MQnd zGlle&D$P0nvDIVq)skcEVAPyTvQx3!s1}>(c=6z&LvP=D>m9mziCX}0wCSc)l%W5A zaidUp8wzbd^f4$!9>`7SNU+J{P*Y7dtIck*J75tVs4H}0TdbOP@~{PBYJzQS0LsR1Gjxy!h;9?Pai&{B7Zp{Bb&ve-Zlw z|NKJc6ZGD;4ahIuJ@o92$B$Dp%R<3!nhPm(Y56WRNE^8pwQlY0xpYliv<4of#Cp|| zfYg98fm+tXtIeS_d*tS@jEt6IwKj{jls0IlhjqW>(#2oclr%JmqasC<-$2^+y1Jc( zPaH8UI~^XiGJwbWOyth%>LSN&fhqfJ?hbq8m*xvMc=@Ek6k3$)3dRk>a~Ej!BB(u8 zxTSJ%RF(NuHnk%=JVy(*M`BM0iip@kvURkWS*LpuOUaeK4x-b+s_Nt`74uX=?3k%y zZ8D2bz}+jBU#{=A!i|;MaOLkDvBrAk5u^R^|K5mEuAR`2`0U4)t@_eA15S+|FVhNc za!+nD*KsgVPIR0%o@1gQAGjBr46bx@uZdxQOGGtyvH+=)#u zPP~AKIdlwKl1d!qi*LN`wzm!)%KvuMj5tKC%}6Mm0XF?pE(r?HcyY7~)Mn)uOaNek zR7a;2yHy4#L~=gb<>B6#EAgOz#fmA9Kdw1na1wEU9JbMvd5Yz$B1+`hWyS)$Yany4 z&XqKtcq+$lhDulE{*)_m`NvRC#IFkX2_E)$am{*>aip17%J80F=k5u`O%Yf`#g`3j zXjS(}+aSvJK{3|TtgB8@m+UHTpQv9Lt@W4Y5V;bqDu->xs5A!%-W-eTTQr_3@7!k4 zkY@cYMwG;8ti-toWem*p7b{ST+@rJljAe?tw^D7ivP1x^i@T!iOr8XX~4NK9QYT!mlG&VzD+g-B3>#_5Sga)Cx zDK5s!ZBmhM;iYg|Ib4ykoxI(Bsq-s*OFT3-_f;qf*E?letjOJG1}C4>O6397L-Q-M zWrx3m)z3+@H=oyDg%{KX`a<<^)h^I!MN~VjaDH`TpA743mPq94um(}d5kSLl2#QCx zhS6J{SXrmQqM^r>OGr7dcP}oAqr!F=9=wz`K=4$7=bWq>-GPASfyymdn0S5kL%OhB zbQVnT)LEd2>c2k=h+p6$vls`_oP5DqL@qpu;vAS1`%nk812`C~1G1be$F-6>#2UhL zLH5gz8tnCF`&7!sKc%H%VuQ7*B+eBpepJJ8u_>BWQUAsTX34}q_~G+BExZH?^nl+w z`L0OTDL05ZQ`~JMDFxMPQz9l zM-BD0VqA{aC1PT9biX5RQkhxRl66IuQryhGo)F$ax*01&xoH`X5U=+C3-i#hU%smcB*{?_i1Qu&ZP{=STNwX zGzO6uri~VJlHJtDj(*w{jfaf*2(}^?BgIcjZ`4T6ddU!%jpztzC0-GCJ1DjihRrHb zfblr)DS{`vzli!Qzo+j|q<&To_;p&@Nt*RGu9^ArG{D-TGkuJ9k;z^y%^6TKfbtl? z6xH@}QNM6Y=d=YYRzI+JvoNb;?xm|PfAseGt7&HLnvSN>XIFGINAf?f6JBeXv*p-B z>o?C37p4|n_Qc~GuAI3!Gjm}5isZIA6V@#1$bSP!v!HgZ;aa&0m{}9wKL-iG-IYYU zgiL`XRdFXC{WB5IVABrLyJeSx8ze3t#cCFP_aZ~3y>-lxqjwEYiXr<@Ze>H~`&X{G zX;eQO?(I}+Y4i7un>)gC0L|9_7sjo6M3u%Jf+qgSx#Lb%8g_}^O!r2}LEQC*^(GCR zt9emEfI|LY0Kj~t=+WEc5V{x8fFFTX*^@6VK-qB_<;9o0Dy3pKIPO(dUXEWqw32n@ zSUq}T+~uk?HBsZFO^8+eK%cJ7b@5#=RumfgJ)wY96-0)G?L3y;*iz--K$Gmjjl4vU zgKe)mr!7)R@e~=0yYQoZvI;wk%ACa;Bq3Q;^y!-)@rCEE@|)2p>7Ls*9Xj-rL%69# ze$~Q6dr$BxdV9X{KW{oJ406pvv3K)N==A;yI=)|tOmb^$uFd9+)_6UpRI}8Ah8MPa zR6RuGXsus%HOgWO8gRiEFL{$%&kHtMZWq}f+$k$92O+I`1<_~%b@8#+(JO?;ctgwfybt;l{j8BQXLxx%5R6?Kf)Qw_3b30Dv^7Xx zGy(KBOEIJDZjmE4D{kopFD*iY0g4@b0AsW|7FGkSwKFN13YIb{PP*uf#wtJ<%wzLt zyAl7Mz9w?}x*dPGSZ@=wXt^u@^u_y|T#N<=iA^7r@OjHLU}{C90RyBiNCPao)&ZKu z(H}+wh6)7!ej5Ddv)8UY@^_Hn)I|wUoIl%#(TIMuPv$P6ot?Q%s3~FyA<`b*>}S-5 zjE*KLpg>2pN(qbXYnP*%qv&)f*vlHFsB-cNG*N`OSmXkRV3A+ZlyVL!x{SqF)m*X= zMhjpPq*E^`om^5>|55t;N%onCm+fos+DD~}l8tQ&`OZZN2bn?rEd2mgu3prY4v@o$ z@N&7_gvQ?H#%K-2HV1>pC)JOWItF^BhI;H0aw0N-t7%lK zIFC-+u6dPM8Y>|wrKyo3bvj5+Pn{g6PJ(L+T_zB>z4`}4>}%9F&u6sJIX)ED&hdE- zvyJavlx!~qZAPghS{Dplmw)!6yu{D$qI|1vw6M9;+37SCFtQj&+q>cnt>n2Sjon z2LNg>Or~vg-t5^8!V54kKl(88gzEYxp$0{x&!3S6^rL6+1oYADr4uLSCN+;~!LG>h zQf9&!DXG>q1*FC#?gYo0nalM9GIHNaJ!z+@W{P5yjE*c^{uo2C@+P)Zi5K7T%Cj;- zGGwBjqb72W(iJ%c%6I$td+5VFSD3JTs()N_Dm$*#6T;0jBiCJ+P;{=LS2;! zWqIitsLRat0Gvv@oD-Uz*psW+qH<%u+%iRwedq;0V?td*X|%O8GUb&n(T)N1jD1QJ zEGjYnE)GUp_cWQQr{PRS!_sCJb_+UI!WYn9eZWuEdygPT#%l+3No4hggWOrJFM|7Y z&Wf7qgmA01zi(4dYoE_QHr;*wKo8B|JF_)hRc$=xoH=RXExmK@T+lmyY4ZA|%DC)h zVPDPsR(hq)7fPq%b@ZB)!yT67wQY?qZ)1bkxqALhCaGnd#pa*W*1ULWvh|WxDNn$) z%HfDKgzc8;M>76!q^24EtEG^ld31uX0M%kS54KM?RMi}^0BIzw(p8Z?QXFLr?4D|} z$syPIACn9r{O1Bd!s<(Ir^a^p1T4#Y&yQf%V$GoKT z+iiWBPMW-To;~t~3wPc61Whhlu*@K!T(4sDEr3zzTV>~7QkW!wdbaQ$Xd#QaIuf#o zG=b6xk5P8UWPc(ehk3B%7o6Om^=OmjTck7w;(@f<$4akpNDx8_T)4!YBv6LYfBAT}fkMDbGvO=$N|{$zCK~ z6MtygUhK8L24iJhnq{LE3ol@_ag3JH=pV?}fNHw&F)yzSdvMk(lI~*pnu&)FA*r{4 z4GKIoiLaa5>*@ty;wf?f-WI!eT?C+o!G}go{zR+>`@Wh3O;XB_kiZG3Hr8K#och+H=lZb3oWdH1wFJHImbFsHN-l!v8o}UOaMB(l7c(m`ehXaM4K-r zF4|2%)vdpnkOmGz>@{6yt56E0re*+f!o6X86Ffy=gO@ANFy!c|^Sf(7tiD*W!Peh9 zZVm$S_GJIvar0!%1;sX_P@sReF$afz%XlXUXbdRC(cEVF@}ba#fV1 z^^-~S$?y#^+>t01zOv-mh1P2a#Kk+)8!AS(0Xn+^*J(RQxy*D|oUcKX8dZm}9&aqi zQp>-5x`kizX=}xV}7x#2m60pi;1OxE z!Wtq3%~YHd%cD=GC+L?TTMpdA^D;Dfi$q|;Smn7#k*ZJ|jhp3|WrI`p8~jCOtXA%` zQEO(itOp2*=vOSlR*dZy?j1Gk@>=!Mzvh*{_+v4@KN|IGuQbs08s1=U#`1qF{)I6b z3cnUwgeq_xZZm`$&T-tUvDDXiOxTNOMd)m*F&oX6dTWEl(%|tLy*}dek%%NDBzshL z1#uT3uZuN)E8mAypXkxuLSC2d(Rp^oFvVBF$6*N^HO|8gxz!ma|L^wBJG!po&f~vV z^m>0!Pm=X)DMnY=mMqKN56KTKK(>XAn_O@MgAF)XB`(y2mJmqR5CSA8*#r_u7D5TZ zB?L%-EY*|*Ob-bd0tOj!ayU6DY!1=v=QsDs1$*~ocmLh7=c{>hr~KN?ojdo=Oz>#W zr(Wg+^Cuj0{rRoq+N!6IDiyE2=(I)cqdn{ErgV&~jhuhn$l;M^>*sf#bN&s{WbKTj zkDYnO=f69(jF=8G1TMBEwr84*X#q zC+~5p{gD8TjWN8QLXe2_BFA>-2Sy>foRhsA=+O61y1Qe!akFJ9L9HcaU`09%uhF_4Wzm0QLGH@_(b=evVasXK)DhAJePfbQtkd58t0{h<5GI zYkAh_vMnZE>95TGcMlruWROWS+O7@811t$Ge=AeNdpA!y#Ty>){%^IcQigi^{dyVd z>xceYqdYL^4j!T1m7g_+-u4{A?!E4gIAcD=u{&ZrOkcjTwdvevHSe)5qvhE%_SiSC zB2tyFsIDy3us{_4qI&FojvWy)h1zOgRiM(o_sOu!*x}ph9q0)6vpLiiVwC#_Oh-P~ zh(+#V>$LoAGDE*BuhgyfK0C3h>mO`*H#&cG zW%_BahmoL;O$W>>RuQ=U`bay+aTMRFq+=sTaAL)QzP(UAERa9AQ|HC<$aKm_&pxs| zNLAJC@7#557hR*Zxw@hCb}w^PNV@d z`^EehIehHE#;QctRB_&n{$evd9{hOJVgDViDD0&k_8*m?FU0CAvgpptL3Y$-?Tqlz zpmi)Xz;Oz_HxRVW)~#_Bx@HNd*KA-2f)F8*sLKm`3n?#tzh4jJ$I2=wifEav zBMIt^9cy^-aKwRZe5~v9)0x@iWJ4Cdkp5uD9OYFzE0>oD6-6yCfuMwZoU0B~aOKxR zm0NgmN$1Nu9Qk}4_omKP?vfq0fApHBQGr^tyhPbhU9Z4PFwC)R@WM0nA-q6yAR44t zxCrUK7vUh>SYDLHGB2=Z$$}R?j3peP5O_r~JY}<9zm$u8w<`d0;NG3;j%8@ppzUev_+&>Ibg59I|#K~X$Jp`j4V zN~kZ&>KR>#941GI&B!b-uokL7Z|F6uG$}8fOyu$s@kt;~MQllg^##Kc^~XY#98zAw z6sp|r=Y?;gaVp_(#5!fj(hM*5uj<8RTnz*lQCk%(@}nKu*FEe;6+@|X{~gN@WKz}g-sD770O{G$o4~FtRR4qS=fO(?AiD2&A;+ z2pS4TDb(^33@g#mXey=!C{eMvbsA}P6%Hq@l$94vqsC#;@{-9?1&$s$%E{P-Vu$e( z3r8}X{1}U}inIdVBx8waBBr`YQ3-9F&&PG0R+JqExD_FCjgAB(syA+YY+yjQjL-sE zHFFffHuGsdMMW+W560r~0=E)GR_fB!q$R;i!a9w#G)E#SOT1ol+maePmBi`YCCi7{ zmX}aCmWp8kx}7IxwcnA6g=ATkP%O$LlX4J;7kP`sf>v*q zmjt|IsVHZ8iE{jOAj4W~$YDS1Sb`ns;_wnG^OE7rOe_EwcX?6eSehe|wB<>!xfHq_ zMH0$Ou5yT%NIV_a`wCF;Xpc!7RMMv#`}fa)_6xwWxR&rMtW&lGa&XT-r1CkL5)Z zsd3;Uy0ey4=BWZl9}>@4UJ}ZSO=p1yl!!(v6BG+CNq)uBiBvqr14ts4r55ES#yuC! zv2275EfBdzM?+|k%7%EUq@uj#CB{0?U^X5Mz%#rgC{$RjB(zxTatJDp)$r|F$~uj; zG)LLFR-N+VlIZph(Ij_W$yb$m2}cvz1UI`-5?;aw^AbzOVtJL2U9N+5Ws>PQ>rl~6 zmJe6UywD-Q3lwnhxAGEJEn$NkP8XCE-~8rd60D+Yhy-J-iVWu91p!DZoJhe-5?;dP z=23Zom$Y@NoH9k(vVf^a8CK)KMN`U4RW((pUTFH+q{~aFB5c!HAX73HuSz1KWSsAZ zl!H_{kw#6)crKY>X>FLzN%$O>U?LIV={Kup&b>!%FdkK2)7&nrViKyR^+hl$$%ZP~ zh$@zdOFGOaZm5U*b~tV=Dw#*=l!Qwi;H6Aa&a$A_+_pp!xL8_wsji_4Trd(%G8;*c z$MHA;wtgRSG@w*GUY(-YWP%m?v=;XAPGnN4L@H59<&4dg7q}YYCCBcHiAX%0P`%mq zl&O$tbzDLie8ocq_bm?qyo-!{_fTPn?A^ZB+7 zzQjnqmg{4E`^xe5qJ>?aKihLt#KZFRLwrV-d$yW?c=njzde7r~>DdzCZ%PK(cXFL{ z;60vo=I`E{nVlPuqdfDO?;eoRp06=$H%%(>)9^ujr2M;zza#L?_~H1JCnL-73%pVD zs`qBzQt022Qsw)bT<_g#-tpcb?J(LJKOB_Z8Cej=b3lCYs}mDzj`i`d7eC9 zD_vyRT9z~MnpH0B&@n-Vc{fPAcQSvwrNO(Lj{+~`fa7kd_0E^$IuGtfl zV}0|)fv3^lwQ>~oH<2#uxn3rE>utU~*N)M_f0TshWEtb}%WC~g zz019O%q#LZGcRIRb4X(WO>g4l87!LLb7h&omam5%XHHc0@PPFrh;N|$jLML7ExuNE zMI^27M)4}2R<9Y-#F6D3Xq?8wEa|*2GZ*qT$$GCb_Y>ae$*`l#$GX}I{=dU6f8S&0 z4lx{4U^+=x=^Y8bs+S{p-!}6*^b+x|K~D#H%KR8zwe$B^_@`8NR!6F*13p4HVs)f? z8uHVSBM0joB_X+JR!;~%m*nM1lydF7KhKi8WM_QVgU z4u;wS#z0$2-_7EJkN6TWoc=5i&w29}=&)x|P||~Mf*DRjWew%v8(_}73OeRRu#wYh zgEG!^Gwe>A=fS-BJ?NN6xPhey-v+aTZ-I{42aX#wbUJx1v=(OV9`LXw3+w7(%{G74D&45!<^eEgZUQ+39IUZv>dYI2>n%Fw8p4e> zWv9(Gn|e8e*L(=(ku58qpsiA-vztIAT)fP8b^)^m44PZOkhu+vnIC|0a}k&@KLOMB zYR243IBUZ>w2+rd#Y$IGmn|V3LQrkv5&vX9cZg9E{m&|>HkF_|%{G4!y z4R_iaXWDXRq2;{H#?tcAW#dn>Dd*UF=US>xHeciFJS)BVmcj+*>%=THKLi(9?z(N> z#WwvC^E2X?nj64n<`>{8Rx-A>;d!0li6=tI(x&IH$k<% zYHVK9IPh3a-d8x6Du@hgu%#Ek1hv$VcMDj6uNu<-64bU_BR%HVV4qFdk4+Av-uJ=0 zxgIQ-mq4v+n5}CVd0!*!Aj4ts{vmH5)WT~?e-Bs(&9$U_2XxR*E%dz2e0_kPrvNXH zfN8TD%wRbM?0F5CGgp9lWL3b1-vMioLjfCp3M^1&fs%g#)>~{a1B4y38Eiz41$wia zz)o6FL1v-T0`_n_*k%3=oP(tm(DDahx4pUq+bE!4EqNLJMnRS%!{Ny44`7})GMsup z1eJ^7aPcljAmzUkZlv#OfZu0XK@l*0U=U6ndXMYC zm<`9xxr7tu0x(V6cPR4~Fl)XF=8&61@9|SGZ#uy$q~{>{tH2uiF$c+OSbGl#Ia~@3 zr!6@29(RFtW+PZ{Yi~eP4zwK&Hqw(g^d8>>N72$9cJurJIL4OWM33RnduaSvb2Hdt zz6p*)BaXD%T;pw;36|Q4Hq9h@A&1^W%bbEt9C{B8Ps0Ko?66lmZTgv(s##cwgSC7I?6Ox+qIEdf%$?v|`XxtBw!F`?w9U7< z7SPi=^d5JBi!43eww%Q_{SvE%rSugJ*0mEng&xDf##GKL7`-_39=pL+W;?i=`9h3oBe6!b{0bQ3KHiAd`oRLDiALJvk3fg}MI+L93T)&4+lURqpq+CKzWV!e&j^&;47%j~n*&q(EH%6|aVd*~=^>;o`Iu2IDQ9IV57N1=U1 z2OW*V+TR09^iiWp^CIY&2f-38WehP7gAV=b7@5aty@@f#U%;%z9K1J?W;a+z`Aw9p zsO_i;i+UZ@mfJ+j{Rq@H+k_+sz*Y2<%~1GzFisn6wtXGY?^w?X{O9? zfF;^{GctJ>)H27C{!vix&MkyL1RZ+9afDw09q4IA@_WII#Y)n&a`iN@8roWEHSdG9 z_G$yXw~}iSI0~7xV)JiepdB`}fjkJ+zU`}0Xw;9cm|07}7YdQCkB6@iQTuD1BVqFh`tFhi9ZSyWU2CAL}9qx2(*xMUm8eZC<{82DROKc;} zBVY|S*=FV3X64*Qu4{>DL_TfMJOFl~$2O=MU|)?m`&_hB+WlY#%WS922f-XIx1BQY z0c+?1+Uc41fOX_;r({LPTn;uuLpvou4bDP??MP!UsI|0H%Wv5?ID-bK)AJ92d2<<9 zjdrF}@_S${G*8FgUIiVq02~F6)3M$?;3S)O3Na<_H6MU+q)~$AbHEHec?p^|oMYrr zq83e)N2ew3FYkfXSWbz$ZUBc-Z;2ZBfOYhHC3sP6uqhq0j&LLPUxEhB+sxg$gvM_H zr@&VUPHzWi(F2#@^iHtLqK^7X=v{LyvNd+wG>hpCO6YwjxD-j2(7V#V9Lbc>?+45| z{-1}zG20sKFNHc@@+rbj@oI#6wQ95WT?}BmU*+KeyK<#Zh;N=a_;eOOf z{1adS+v}v9w?Kz6SSM}y0kDMKc2e3tumg+j!~&m}ndEvBERbdta>(Aw@Vk{N5KMZzl&VYfjYYA zBG=tu2}yQYs=CPg8sQc6lU=ln0dO_plaTgDGKX@W2DL5EA@8@r62079;_n9w*f8?| zNNFx%9L&AnqGGJhM4 zqnCwtB({)TcM>je7hZ_`e+$-IY@l5)B=2{@B7OKmdd|II3B4?&_T69ywy}s3c7ZxJ zUIev!LG5Q2k?RGp1b2%_`J{A{@@cR@nasaHVK*r?UdM0Uq}&E}p#5$nHUR2(mvHqRSxQ^G5zJb2kmOQY z#Oq)O*1Oc+%a)OM53?i%biIrcegzhh#xhEH2JE2T<)nEYbf9E8S8oDKHok*gD`>y_ zK!-N6f~y*%{nZNFQ>{P?^|BI5-UqX2VI}EzgL!OkCAsbgi}aQ&sp~hgiueIgt!owW zkC8u(gjbX6T~H}pP5k5FGE%N4RZ31J*ZZK(SDeb#2SMfWRQ{!;$KHK<7(YBgILC;c zXIZZHkp4Mv+~8j6wP||kmtG{SDSJuz7^ruaUQ#{;HrlJ>2H%lB((eGXgWJIz*4RhN zS3tFdK2q)j$FZYpKPm48GgwPM>3<657^C)+{#CFBuKUS#C)fz({p7OqcXn=*O(f(9 z-ouP4GiT!KU|zJBH_SKi29V#uY52Q%BQS~C=W6`-nYoSO*W$SzWyUVbm+i3$_`mX& zoO#s*d6OKFm70bBH4`sf&wPtFPkeWhy_dH(UHHd%?nVsG)QnNvr zTEvsSb_D+Kd``I)&#|S$FBTa=+=#10>P{1>FW{dL`AomaNPZtxkN-%d;Y?xL5r4i& zV>6z*jy?weipZ#i_+N;Oo`%0$m{!A6e^a|iGki5a!YcJIi?keve^+GO3nHy&TYj zvJ_gDl6Ki$BBz`tvOI_XKxD=9A}dL^3c0RcCUWW$k<*aJY4?e&A>ZkwJslp-=)(VA zWbL^k>yYJ{b41Qc;Xf8R`%fb4UlTc}fPYD3!&Z@=GevqQi1by9^b`L%{6@;&gj_c7 z6xl-E=TXM_C6NnAbHPUahLZL$SNK!!Q$!^D-xS9ItIfZu5*`##66Wd#I)C zj^Vl7b!>b@zu`K~)l&}pxU)Q14*Qv(xwIUvkXfE_<*;tbds#WmjJD?+wjPbp(zQ;- z0R5{Q=8Gy>Uk>|tO8RCw%-7kXXNsz;U=BQ54zq8W=e%;*EuU42{xGSOemCsW?}lCa z-LOl)8+Pe;!!G@9*rneM+wyO(A73mM>lbb5t)IL8jE#MpF4(krUC*ZG`q{l_w8-sJ z&*MSS{;TJo{Dl z2i)Azw_z>AoIZZ9b+6XjsDqM_y_{g~8c69`w|4!S`p&-I&3$KWT+@H{x{dXdTE^EO zoO!OSDN~|#tc9*M6w*m8y-?LBXF=r}I@Pnex{)iBcvu_H-~Vx?6Q;JbPHibpgZKYk zjT3mFY2i^$u_)7ACJqxonSHfp>r5{;b0oKmNKOOCBGmb@AwB}bmiYt&%Zf4gp5P04 z&bDC&Jj+aTCH7p!d|wUoaJ9@|4QIZo4ncf|-ItDHhKSi1Y8u5;I7f7&$gz+)4syry z%r_CSP3GBbD$ij>?68d|gz1cekEOlMKx4;M40!B@X z7}G3fRI-#2#VL#)R&cjp#l8DfIZf7hyz-db%KM-@<#KsV9+G?HUiq2ql%L9#vR!t_ zZ)B@HEZgMgoc#F%`I1~AUzTg+Uog!d%2(x!oQiq1TqTdnn{t!fA-Bknr)`~>6py1c@^?k{5=U*Vj}^>PlTx&hPqKBn_I z%w{7-y#+%$SI(333lF|A;)_nN$Ac=bzRzQ>IPvTg{`vnq VD*T<&v?CY*xB2~K+!hFc@}Km^@wWf~ literal 0 HcmV?d00001 diff --git a/media/fonts/timr____.ttf b/media/fonts/timr____.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6804dd28ae44512cbc91f2b98a9d750ed3de8ce7 GIT binary patch literal 61816 zcmd?S2bfz|xi-4iuIgP|z1JxkX-1>b^x4xqC`}I=fID{A&~G>ObH|hTl(L%CC$iT4(EUV=id9=`&`L0qpdCNy}oaK<^9T9 zCX^83AhSdu_fL*ZY{7n5iA>Y9L zNzWm?Aw9;o;P?!VlZTF7am}gM6MX)g0wMh1#rrQie#NqDuO{R>Dj~kxk6yBOHyM3r zfshxziSz2Q-PfF;chD~p@>>(WA3eVN*#0{%`6!R$c0#zHpSa}mE1q;reTtAj;5_~F ziOcq%_*lMUKOuj_$H|q1Bg9BKqcB^45Hc$W)F|D5cFo6)I%3p09In?UlgUalJ8hAP zNoVWbaOde0UYFy}w_Rhi8I8nf+)eJp^KIm9b8n9xj_UEWM{RT3DHA3lPLjku=bddK zE6MB0EzxV{1dbX7b#`{nf?J8UsEXI@p{h}vRUjsDR*gn&wMR6n&PpONO3@FTIPrm~ zUQhG}9jQI5vyE2*PpB}5&r*R1!dZ@^oG>?M6hVm&*TD&P52H+sa__{++GC=ZotL9$ zqV>niMhWMyx%p;6(BUf+=d|M!r*t4%5QI}Fv}2vlo6Sy7pVR4d+VLQ+UC`Cev+G+5 zs(J&vL;d^(a0HX5fYtUqAtDvEm1tx zx2h{=qiST9O^*T0A_nbgCw9U<7@hs&8Ka&U_2)>O#PE!hVfE!8zEoOV=28|_;%&D_8vukFj zXD9F+n;pei&&+D4!nitQkMT=;s<>bnip6*wkHuo~!Dux4vV}2r@sA1w>O9A;WmuS$ zL2cY@-#E6mf=Q+k_2XWO^ zmJI~Ms0qYLauNc_-m-z?>g*^uZQ)@X&cGPVKh7920s)7rI-{8d3y?9GO$2vP5L*#3}EgQ+NMXY2s$2Grjg3w8YUi%G8CSje8tt555`^v* zH{X2os%~};X5gH54kkhDolw=Y5Iy`h$T-)#WMZP1DftaXnHqJq%TD0&djn4lf=UQ` zOI6R9*)fxR6ZPlsPslQrbz6R^ zU0>F2&n(zPuQrq|zXUn^w%}guP^VFF`xSy*>D9E)BBTwSPY`k zh|eTu;`hhzzv|=KZE;g|R%a$UbMM?_^!2uz&O*9%Q?}kSW+O2hyGW6oJu{;gW(%`E zVu9G#o?+N}LS!TJh%o%%#TZ;jJ+@6!pSIMK_ zWX?m5PfXu^_w+mw)Z^zFr?VDhh0ZMi1gdRg=ZidYRsqh>z zk~z$+j>17)_NPDn=`u(C!Er?7=jM1GV~Wnq)l^j{;m)T|P4C+`ed;u`*-{}&Y&d=D z)RQMPjs*#)@yG%*-ut#9k1>cX%56)<<8Z7cT{$_DjoYkMwzZ^MbpN*YN-2At5nvJ)rg}E6v z&7}66Q9EZX#DuGPiP=y!8N7H|g_IOX0Wvd!$-^tiO?6f~&0yX?InB8CPfiD5iW{dp zFTA)w%;FhxcBb(-Yi94v{KGqEFL+19XMX(Mv(fsuqG#FMnT9dQ=gyp&Ju$mwb_JeG zX2)wTQ8gQ&42;AuNs!&Mny_oXc0;QOMw9HCw^kFgyJx>P_b8rE&V6@o_w1$QUW^Gu1##g&o&lk1({r|S7NcgT*{J`? zX*TMAa+(bbr<*U0*X-h&cN&Dx+A;xCzfSXH@=O%)ZhE?R`rnSS^D@lv1;>TL^aaPl z%cOA(+ij4K9;zKa`5Nu(w%+>JpT0q7BsyaO24i|IGM6RO(c9IlXAR7g_8z@?cJ`OO zw!#VRJ8TFiR-BtSzPnl0oIqWyFa7_z6z?yj4$;p%nN&5m`iI__O@ z;dy+&@p(2n-O;1H`(A(YP$+wqiA2(}kKT3XoU|%xZ3p&m~Q`v*!2eBe$@nG#8V#Ukz z=PhuF7d#~Lgv~}Nk;q=WZzKCzoJf8Qc*w3HXz%$*3mGJv$z|kv@@DcL@=@|A`4;&; z`8V<#@}JZ|{j`<#(`9rUJwmUeZ=`q8_t8($uh4JMf2V)t>|8rH#qHs4_}>b$5Eq7oEyCr(n}r92PY90+PYcfoKM|f6UJ|Kj z7eiuB928fG+r?wzjpCcc`^ArlpBJAHe<=P!{JnTi(n&5UBNe4FX_d5Fx>UMZx*em} z=#Wn1l^)djVIX>d6{kV%QADb*A#Wh3$venBTLI`7?Q$>Zq4yX$LLQDY}{- zqL&3m|W#UQkF7bWhXT`@s$MfP#k|?>Q zq|_}FI0 zvA=j|$F-M)tQ;L*2PYhj`}l{dgE;vRX0awI>?4@%S@vg|{!d^e!ac@ax#94!W0xGi zyrxk2UB#nZtyVTHUAeA+Y(f1|zYEu^Nem&u8qaYoam>6CAZR8_%?~<1wz_mSpS<98 z?VCL06MBO=1pbF(GsE0kF`st09w*`eH&KWO&d!G!4qyZ!SZhR{gvAL7k|ZgTCK-~2 z9Ji7-(oS-ugXG}@I|;*3-J}GmC_`iVNIw~XtPep(M!>C6GDgP91eqjD$P}bzDOpCA zlNCrhtRkz)8nTwGBkRcqvXN|perzFI$u_c`>>wABon#l-xSQEGYsj_aI_TaF`KDXRZRCykdpmg(dkc>@lRF^gZ$Uogt;ndn9rAt`xtsh8c_(=n zc{gPLUVP?0azA+hy8R$Dfspr-_mTIL50DSCuaggv50j5T>pw;wCLbrCAfF_kBAVS$e2sh^()Ad5T>JhLX?yCZ}VyOvH?fQyXY{En>aKxk;9o0T6B+GF-q z(ViHgS680+&;R5fI=5ql&*0wss;`iraNmN>^pI)QN4;Lv=kl2JB5xIW7w&84B}(=6 zn~vDdv)kFula7x1-SouUd^az^z-yM_YK(VPO@Lk(ylJGn80l2Gcz(!E($zfVE;eLmccwmIHddF6gG{-n z+*2xRR1~{BHIhoh6mPN*U!k`<-0_UJt?OVyZ{~H`K=d6-Anj}QxOVg#&7&rls3=^& z-D`*|p2TSTk(^aFSc9>2B(8X)sc8Gaew{gE@x6d81j0&dgP>KolocU2Lc4SXPy`QetwbDvaFLNIUJ6J zf+3H`YtS1Mw_?;8O)jU)Zg<$MHnZ8{b}J^6I}%1NT;wH-*`Sw1F%)#zIgv^MugB#S ziOHzrWxr41-3x-~8O&?{&NqJ3H+1M8oqwL2fAy&L{;QAKC!5}*Y@S~ISdi>!^Tb6p zSt}LG3H%gg?Z=&vi}*>D@iRhkio4i<@s**;&<*%me^Fq^{`%|H*9Wfu_V^MqV1#+X>Pdhu+E=y}mHm>MJAsdhReNKlQ6S>yL+u0Q9%>DyR!*nFk?gwBWMFvdx;4vbscrMhl^qI|e|yK$ zWFVAUHkA&Km>jKZR<%0K^p9KBO>2hNZXa2@c4Xb7Kl&Vf?>oQs@Wb8QTPpeU>xVXO zP&Z8Xzj1t^eewtYI?~2`a`g|~)7-Pbh$=AONwt@*TBWXztXw`imG_2+W@)Ky!T70X|b@3<=x@9JN7afX(a2#wer z;e^W`KEge_tbeF0(sJ~`iOmV>a#NG_z~qu{ecWM98wXl*32t;>Yi{~o2gg@0J$U}5 zQm#03*KV2)Wa-9;HyHAzR*b2e5gladr^(}xKo^-*J=E=172avF3kF^^Fz0CIsiDC_ zjdL*jq@h^`;%;V>o3Y7RcTtQ7Jw;EA+_!kb313IRx1~$qx7idfne=*t$ymO4sZQ=$ z>9Qk2rX*RNqDAgM5MvCh4r(^57S3qk;ol|rAgQkNc}yOgw1!+u#N0dtGaEwL=5Zs0 zWNPe|PJUwcj`68mKJjwp7uS17&%Whd*S&U0cn7&YZtX3@4SK%Vh}!TvofHH*(={&Yc?0 zwXd|OirH0&Mt$7(^8Q?>I}~bUywYk!($$UscZd@?aUQ9F>GJ7!PVVUKMmiZ7gu=C==8DK8ZC$ri=V+5&*?o}p%%f)!kd@^hB)*X_}`;iH2%YfN%{-5vvECX z5w4aS;1yW#;Y7d_iF<*FIqcwvMV1Uk12yXaROh3Z5iq6^!_>kV{9Z5(gm{|y<6-=9_LS|+ zU%At5G%lCAdP;Tx0(s+>;~{s~M9Y+J?@&uuB+9)Z(0l&Y4x2F`h{3jD`td0?w%k2$#k7&tExHy-)cvn}F|KOv(@L2Y zf{mi^xAI^gTld+@-#cfO zk0fsgS9R5w=o>K77P3Q4(AHM9&D9b%=t)a9;6Ncru%!f7O!COG$%Cm6G!%G#>T8&x zh8XJO4UpDmcDB~p3C#s!0+gynIp7A9|GFhr7;L}?6|lp<3vZ-u9Np& zl8U$bT!zC+J`p>(p57>@TSq&G*Sss89oyNbUUB>_c2~?59PViCT)$6nu^7jQDfm41 zBj}HrT&wnI-i$Yz40?e#nvEu%$xKiJH0xyEC`cmY#B74Klo9ywFr0`v_=d-0f^&hT zd_#vt3nXd*#Julc%n{O}9WerIMxx~8i!|S{eaEK1pa0HxxF1yt(_j7S3OZH!4AXK4 zX5c~Yabyeksu>yzsbOLZpbdb9TDoA61Oh>iAUh=k`e%p%SxsuG&%z)yu;%wz%wwr3 zJqtqX6Ja5t=7|VtdM_s!N}K0B#HYr3fHfz5F#f&b)l1gD{cuOLBP;FmOr&Bns}5ep zJ-+6Ie`x86!*`n<=~QP=erm^X(L|l#wG*TNEcYC=GD+5`A(~35X^A);M6|>Zr3g|; z;yjYUVQ7pxk3nmwycRS!4K~$0*i=nw>ax;+kv&B>ys)#YhQ2j8rQ9}M+|iL49Nx93 zw{ZOGPhPol$?C(N$Yj1`45#SZTb2y$o*A3mzVh(rZok{_+_bu4zJE=5MPZe9YJ5Go zFIRt0KfyhTobGnWzh1AR`$z`v(YVhG@DP|IftLx@f%9@R=bKG!6W38XZYD&pah=aN zA^Vv!{ltIte*Nin3FjF1R;#s+%w1)w;=<3Ky9Vvvf68Hi-bu^ zu(k`bQS=uDoQ()di(HCJjshYegy~ANLe_&FM1R^-Q_8w1D5TsxsItagU_#A$)PVcE zNB}7^fa7#QGMKvsigzP%0p-=udRu?b%E`m6iPBi8U{RQv% z`X2_uh1T-b>$%MG&W@cErOwu1Z)R|0?Y?~H^gvIjcf?yRSFS5BA8hOC4-IVEOyATQ zPYt$C?(Jc^tFQi&eiWQgkSE`uMrbyxwm33~dj%2_40z#)Nm4+vC}^~3!s3lMkAY$Q z)TuU*Y%|qaMzsevvb-QqTE+zosKq0QMl^MREpp#F(9%2IwV_z(8Qj0Ww{Y~bFVg-{ zYUH32nFxooI*ul$JKxzh*t_ZQl2toaUHp}sZne%vVW?CcH{AQ}9NU9#1MsKalizlM%Pc6UCTTR>#S2>F*F@C&)T*IGI#a2A77@ z0-`l0$s{a$%_c9WEC99Nj48JsqwcNv;ng z0^Zl71;)^?cbc7oCz|m2qG@N+=Lw}^`6Gj(;Al5_ljg9EBWaH>f)g?5tEu`jr{g%( zVUDQnRF+j8)zX(Ni^ODfce=!HPi7oquHFSHr)WfV5U$ARp&$rSFCY%Va&QAIqr%?6Q0+D=kSFn}mYm zg+Q~0KpOX*M`_$53DuN4hWo}!+^y$#aSxo|^_%|wPYw*!yvEBMux}F|`2Us{sSL!v?RL468%zTGd))k8jRq8{a;2V^*fNLJlUnDX`!HY`l69|lvo6(QE+C& z9549nvXYcrWl3pO7V@Z?)YoxjJ&(G8%$%gqJcxoe8Qq#uf;ojbsyQ+(7{g1JSnwpe zOKDF-FL36wJ6*o+kT;O@SO<5Ft=ZC+$+S{8b$VFb9ZUSA|9ky?sl448Gz}ZAp6Stz z7p)l{E_SO+B!lT-%Hxfvyq-Ap=B?G=@%!NE%&5d&u6ELi33akC-jj%15;k=lHrpz8|Ac>Kl z;#hJ@3x{fknVl?JXe}MS;5L!E)81mH-czR6wP#0iE&0S~u7&R2?jCAOuUmEXt?z&M z)_3d}?|lEvdw=rd2j0Br(CE}bl`D^qt{WUXye8qIoh`jn!{f=`@xjkkejE<1Su%Fz z^yFvWch8EFj%;*%|{hcA1Md*=8z|9#gO?-xZc z74(5vw#ZC3Ph0sQeY?uf&pdc876nU*2F>hPYAk$2|rbihT zO!M8DQmp0!HT_Az-qbR4b_i4tPBY%{+UtI=o9?B>?c*!&ePrqAuFCu9Bi)77`kr)b z&2~qjb!pN|+dR{ooLta1NT1!nJKMW9-|CLvv7=OQeQIS(O00ZWUPm8Tl8OqI|0%6x zR?JuZ6L&A{MvSahgESsj6Sk0*+R)wUF-lHe@;jpuKTkdNsmHX})#d^>?;-JK>f+ke z%52~aurS3yMv|$o3y0}~Xz4u%{r4B8*eqCRo6imH+f*R+%;>&gyEj_dQ$o0qH zU-@Eh+rEwy2bayRm|D8()`33m>ua}s>wz8X-D0_q{&Y2Gr}X^3nXNb7zHz(t{3iq8 zf3*T~_HkcB^!GM(LW};AiA*}F0PqTu+ab7|!GM`JiOAHsoL-n$ftQ4gltN}n@OdSx zEfSVe=@fN3P(QpN51|FzH6?|fvS%X#hjh+U-UOTZMWV*Cor$L>!D8?bbrm772&qav zwZj3bO)SFRuAaU7xqu-cU-KSs@a7qxpIdTYDEaO+ZK8$v&I zQM%_Zx{CsTYDt7w$)EOiK?*t8s#VB;B#>Dj(C`qY9z{&V{k#tik!F_@^(ZkMvY0_9 zf-t{=fLLNtj-=OlsL9B&v(9|KNIE45&9a9%CZq~9#K8h)Z6Hv@w0 z%$_?FP(ZwP!A8k70RS8?ajGR`@<&Gg{SzxCj}UOU1|B?i;D-aPA*IMY_P)_zr1IyB zE0rO|U-{1o*^R`FzH^X%r^{ub9;S7!>R-73gl%poyWy*IIkm%+^|+nX3W`Lpr&VZ^ z#W*jej8Zt<)|zS}ZC?MhBGX_^3+Lf>oaCCx$t|LXoe1&EOe0yrzzx?_SIG$G5-Ry_ zf9}iIu39#|`j+u!w7;D`uJ6nZxlPyH_R%AkJoVtj_;?HNr@z;Iedm_zZ{2gO^snvA zw8GeS1b#g|v-iUfJ?(b4?P2*B*w_Dw8SNn-RyS#}l&41~@tBwQ*utr#-Igun4ZPlF zl5BiiE0b`6Z?RhVtQZM^i&A zU^63t;YAxh0c&SdB&UR*LbmI}TdQ9!48v z{?ee*^)*4deD@xD`IP>$zP6L}nY`O3DVX?m74tgICyE}i17p!4ioOGxl!dGt?>1wI z0`K(zT-ee0FGv)t5|Hs}3=<9o>h7FE^Dpm<#ILp%ov%G!w z(=*B3_UqjamoqFTQ{2PguClFi``+P|o1JD;3?(`G=QWI{cyK?!D2IWImeY|DRn2x; z^UhM#$Qx{31N|Cf6}Ra3wYP~a*`l=z=GX5wB9(6#DCM$3yVToD`+M5>7OLZYUd13Z z@f`v=f}fhy)!|Xi;MM_CO%4|zwn#>rm3D+FEwj6@H`-jJ(NdwM-Q|o@*3vH!#u{#7 z$O*MSrPR%3fS5Fo%V5;LSRnf`o#XUD+O_A%F#VR;qb3}M$t#!M>GwswneNM;w)CD; z4${5-?$;HSz;Svm<+M@_BV9_r6*_Q9IxTnv-lg|jx>sDf=KfGHVe>;ed4)!;)NFWe zKUG9g5v|DffuGRz?cisC98)`JFsO#mc7X1Elh4cB(7O!oStXA{^5}U9Qtt73sKo2w zt-K8x7-7yzlY_b>Fk!{df-rbVu$f80I+N~3%r{Oxa5DsRv7=7$#Uh?s}_7*c&3t+m|H$j_{D&a+vDgh3X0VYIfU1>{p%4O!2 zSShjmQKt0B%YT0QzyUhAqx(=_d*u(G-n^H-i4za*WK=FBeLWQAM9DT1U( zg+BV!`OniEzEN>6^31B^0_6&AVno&RcH)pn5NhQoM8sx0>&)(@}`u*g8oDo z0c}oNH)gOF%y2UYUQ-qZ+??RV`{{dvuHG+~dtKH_C~WFGdU`-{(Y`V6iHe23uG?jS zUl+XT;L!OwZoJZ!v&m*?gc9-%(dQ?qmgQEef92i>?97&ztxy9r7E|Ns;I@TCom(V! z0JQ(AT*Fdi^$d=V#F_;=rn&4_Rczc0XEkSBx%Y0|_SScA-?a6jJMZ4UvGU~;rEFX8 zRmV%&Tpyiz$ARO=4&3{;gU5~^cz5M%2iM$i^R}x_Y`o#dEtevOM$CsoF7qczaw#gl zEL*I%I-EAE8&yh|jrc@8dV|mv2GEQQr(1HyBy&&_oRr~9*SyBo>b#hz2C}LdyakPQ zk$+4l!>q}TXa@#dvso#vW};OlSj1EAIkKNl>=+yy>YIseIZ7*!^?TfOY{gVMT8xaO z61UNB?c|+>($<}&PTTV{l8bZEke_~Xdb6qWoH5r58kOoa_b_VO4&X_a5oh@|;!HSg zBqB;4(c+LuK*HLk`9fhM@rTqJ0Kx(Z(jw?kOhS*ea&$e!S3Id#%}$Yfxbp19H%yFe z*>U$>+t$Ch`aPA;9xt`DmQP&CX6Vw-d+txnTy)br4;{b!@Vox9=RW=`ht^&!mEdIgj|}!f2Rr)HqbmdZ zKjZHVNE-^}HHYb+*7L5G{MME2@z8fiEGgMZSNwVv^`Qtros@f%rSfw=*|K(YJ@YzY zWW0WeYGj^VhFlQKccmmT&RslH*e!Q=$0WHwJbgOq2=?LIZl+y-2OGa zD>koPyScx--n-N56Mb&EHMgpLcu}cb8VJq5(ueHW_}%?y!rJ96+|!FT>}WJc>~M){E86A<2j$C?k)-eD0%-7*ChD_(gL9kdOtSXyBg0HtJ)XX1zk(VI`h#Po^FJ;*%mG!ZUz&cTZi+MQG+MrUFHIA{gO1<253s}hTtTV(vT z=q0TMEAtqV^@eHBG!IAUc1$~#x31l>nmf>4T)vLxzd(oLZlBw=^`c$3bg$!{5I{n2 z;`8G3S6=nWj*_HsyjvW}4wt%r^y8n?H78vTM$@mWf8d`11}u;_AcAL|l+lbw?{gdF zOpDH_*Bb$j&>bg;g?u=K6l2~haj}rdJ0-3qRS4SzP6Va-c}iKiLkrvH;SoatT57Rw zo0t!6IMMtfJ(WBn12%;&G!kG!Ye5~39L$k2D9wU8KFv!!m*E&T^183z+`Hl({oP(` zWSm~|$z|`j!{_$Xt*85gj$ia#8N6eM@1k&EgnOKFoWkYOm22;OaI?3_!*P0OyRUMP zzSHB!t_MCuJ95B&{>pdJ?#as4)HX%+`4+uf!%S7~tC06z@>XD`zCN`-+UECJ@+~17 z7K5VelusqaCQ-b);vI;Fg;ca8b#-?o<3fyjoqBYh(C&F|0Z>BP=YKBX znHE$rx27?y!Le@A*KE=IG}ytoupluoZ!$W(nS#Kc^G?Mh<8M7n%fexoM`ke!Iv!H@ z4D49W-;i6odiFglse7BUBri_Jp88zt7W(ke=9IMG8T{f7N`bs znxKG2IJ#y>-$b&H1ezryz$C+|+4rtu4=|6!T3x#EqlH@Z2g^rA#q#z&pO};bcUOMw zZr{2!H&_Za*EiOMaHbvTP;~5NNsxR&I+B?bw`D&WAli$g%D16f;E5GU%BMique*! z&;26DV+j?l{-OFin&F;9X^`c+1@xjJ7lET%trCmrv{t?OY9$0?zFrAH)VL%1`~d35(H#U4jg+HBG}}J%Y|erkM1dKE|c7 zWDQNK)xXit(LW-;UL*(AHrm~-mi&dN&*&EgvraI#3aLWA1@q~4rpm|)DKGsTw%<(k%mLlEFRCQ~16n$zi5sk{I*5kpF=Ut7iY^h!lEX!I&u>@mE zrIq2F=ykLWb`MUhh$ud*Js1slJBHSGjqYl_?qlU>x@)X3L=Rt_4I}a5@a6kbv1Joy zhy2E{;$OLRsB2Z9xBb)6T-#?Y@m3Z?yi$FIK8KEV57s>HRa3N)+HO zoD0zrQdDnGFY8@aXdN6qIC_Jm5Bm?iYegy)O;0U}9ps*^Jl&pJzhupkRU6BklrVdA zj@}ka+ zjf^Hy7f7Oc@Ci0}kCq0nr4t*y$1vy2$1w-U5Yta~_vCwr4t2J7w?@qdqb)lU^~W+3 zyGlwT)}>oHe&FKiHU4m}ClU-rMvF_9^-Z3Tw`7JOgZAnl>EF2TV=Zc%mLY3zS96Ad z*`Nc%IZ;A_%xH)U?v`wjM-!uzh73wRlaGV(o}Ug4;WEpoNuicWY^*G)TR}HzZzii< zlf<};A|ua4&n;&_L@nK~(FyOqKp+A%+HSSeT@$p+V0jPi(Z||%6|#l$o~iPYCCN}Y zy|Onmz`b6u`LgHlEeW=frLB^4?f8L%)9dr^X#e7p^2!aRvBJw8BcRuSIeG{^H;$$} zuq27d04hWL((gM^?kx82d(it#ae_YIPg6fpyPsS&apcg{n(sWYq}V;lqzOGL^gZ0KvDW2E zwVOuSN-Ud2OH~I$VgzL-H}8X`MxhO1lpG{d1YLlJ5NcDXN6ni$md_E)85sX{%>^f_}Fpo6pOe+?y`DbR)fYhlkgh z<5*uGJLmSLGMld26Ro^9k2UXTM6OnPBmrp+tTe(b9%8H7#4rQM$f{SjHAC2B z46|fKvk0zWA_$l;->MJHov2yG4AU%t2o@yIOJ$lZcw*`X8N3`h1gO!sZ(c?vhK+JbQJj84Zx&pFr?TNVHv^vtVF)W4ho;ImH z;HMoSFEw)L8fa8!fItCgYK+xVFg1B$@JxefU~*G@BQ6r(AeY7fXHVJ5P#I$@d<>E> zveqwMW?Zz_vT822IH=UKx>I)TQt9#?tHKKBvS#THTGnso+U(w*#K6dg&abc7M4wwK zS`*327Y`4$ZLtlSZ%o-udIv8mMr#Wd;<=H^^Ft1fcd%8AGS(`e<(`I?N3eFYRns1; zEJmDGn@w?`S5p=ZiWmf>Ga7udGvefJ6dkmUpj}J(*8-J#g{~H%)UDa#+5(DdG;8Tx zlslYFZAL|TWgN5|c3INY^UQVbKwNQ0(_X8wmnL(1r?aQBD~=WcJI6g0cPpW|+k;IB zxaw2YRpfhE-^((htj5MNqCSDMAy$D&n)q;! z-XRDMzpFrh*>12#nawxh=Ou8+rbQoiyXr8@qS<0I*lIGX39Ol5e=N2*U|w87^L*f; zEjnvVGdAyRHhT7&(QB4eM9HQV8Ixz*#8R63l1m!oxTMaNNS~iAA$^V51J&{h-%Ve} zDy$Ex>$Fu^9t#XiTe~ft@30j^K{N#n4T|Gqm_%KFpB~jSiekFpbY#*(cQGj$dt~Ey z9-EFxL+Xg1jt#X35meh?ayUBHfU@&-CuU(9Lc3sh=6#kny%)^m*dj}}=IxIg_6MsF zi(NJQGvBs_j#x}!T~nFR_h|1(cnf(MZBYl_n<|*h7mZHuEKJDi@z*NmOy6eR_D+*$ zUr(RcSfCGVX}2j`BIEA0Te$6XIAc{-($-Gi9*tje@lgKg2VaR>^jI7tx@DcE&!M;aBzA{_P0k`0+knssgoC+oSw}*tNpsc=~m5>vy3BhjTxTUZ2)1&Ohtjn zT4Pb@gv$xV5BP;t(kqKGyMYf$QHz;|ZAL0`*aCE3GU}F`F|}sT7)!CZ3&$EuYhH5R zuKi;ZoV};ac*xk-;0rj#63JkdX1j-JjhUt7^`i%FSyoPO=lVBVU1fAfzh!SW-f6PX zPaFC#zvK(Q>(nEA;52pptUs8Zs{DBrsKCL;veil6p&`+~(Vv5Q3;NvI>Y@lXz$Dlc z)g$NvDDhyW8n%jSEaKI`Gm8M`GvPWCX%_W}1~KRTH%MTMcC~RgfO8N1dGGMCOVq)W zm(L6j>AJ~$%Suu?=4(;kISF^4OevXYA>h=YD&Vj^E(l8xR#Z4&CjUPonG zhQHZL1s6fio`$D!Ul7$a%u{1}6oyuoB%SsHeXdQ(^{ugdd2e=ba?RZD7%jL7tq|NcIHQB^FJKMT% zN7mXU%ZAp|v6l5qww+kE+JG*u;Q8-&xV_v=Z|C|S1&5VFja72puFL2BbI|X;`%yx%G9Fn&|@V&C?rMq&|G1@v1Mp zfW9#d#Y*U#kish_o$da<#8p9rd~*ajq?zeW4c^ z3GIfgTj%d|10tUs>KWZgRH%7#j))0F6lPgSgaq`$$n8EXn`;G&qyR5v0+Kz~p5Z(S zMajI8=&!q4W~AAZ$*`t}wU><~RDyIgYh#C|jR|HoH0^6ZYxV|mM37X?!PZNcOmK^| z*X6x9>hX_XVjb@(47--O%xwFrsP-~ntZA^!#0J+189ANFNJ*3q$@V*^nychlX; z$`}0U7UP~1bbHL)iq#9%-y$FM3Vi{w_%&*YhQn&a>N3Nc82mngSZ!DiK~QmWIU#Sr ztyW%Ef;yyB6&gYY87&MA%fdQ18Z)B>pP_jS7$o85ISR8map#?Cw9sYK#>qY9>8147mCs)^PQ!WLS-B<8yIgT$-+|?28ts-G z8byDnPtxC@9=NN%dd;pkA`vb+?C@p5K)_+)dC7{d<)Gb)o^Nix2w0<`se`*INwQe+ zk4OB59T|YvP(y*e&`KzL0!1VoIA61SJQs}~&bT+PO4~l*yw9e0M(GQZRs;A0Isu=@o^1W(4%Cj=o*e0dy{jYOB<-;_F`YqHFIX~ni@jwqOcLEj zQPKsaKyQ1R@0LpCQd^6Vp#j#dCPE3zb?wvGR8v0|jLriXtyLD>VyPI7MRg997umR@ ztkpXhqHnOLhVWVK5q?FoB42_h!ZjAJ!V1AY)k4zpBdb$}aNF{(;cOw~QPy_({HlGN z>x$d5!zZFTB~9bm;)eG9M@QdOEcsu$uFn|dfN$K`U?LZd9JBhVi^Eaa(zoTqT{^D; z9O-mGu5#@$Ihd4#?M^Ec z1v}N{957Gq4fE7!#S|M* z>6x18u^<`-L(-c~650qT>(^Q^(REw5VDW05ShX&ZSBVI=<8HQju3A7;W`4<&D8<~` zQfaoN>cQJ?T!sRxlipDI{!fQ_d*vec^WU($r{89(tUCM-)JsWgb&w{}$;0}jGg_at zn9W3j0lN+9M7L9qZM73I!ed2~Bp^saO*GS(Hs(|y&e|pm+5ojlt4ncakv?fBx=9D9 zn{6qhC8cCH{?sNB-i9@sb~6W>D8Y}WueEwd$J+}40=-+P(WZ_craF7iT8{It$*QAQ z+6v;DmPs4u|D-J#G)&r+(Jvycs9zZ!9lX!UkPq2e{T+F~R)=cZ69J3XmM9xP&axFw1=(Awq{`qNvo zAwGy^SFjZc7GBUxj;N!tW=30Xt%+ex80&VVW>_JV464>i@GP#crV6P@66m)$VB8L`2yqM%x5b${cw`=7W6BMH2=xU%X(c+?xJCCK+U35K9v& zHY-n2vxeOe#Cm@ilS<|yG7JHh7fuuw7Vfg5jWzAfd0pFwOjHcVZ9d6obB4c}P+I+- znIR*!OqyMy)9tmGTD+-Lq%gcs);V1EV9Mn%CPGR$lV~5>%VQn8)tj(53~mQ%te0aG zv@5X>B3n6Y1a_?LV1pfwSan*j1NxOE)IQkua2)<86CG9_Vc(Ydv4m7P_jd=(|z(EnwY!imqXB-xrDjHrU*go z$YPSyP%qM|)hU}pC1xT4T=1Kj1kKn(sp>kFSR{4sWP1%UTTl=DGKz;e>qN zzGMOa3~&8|{*DtiZzAUPWpYkytdoy+by8b<+T)2u6(!wn<6YJ;_nj&CY)i=F4clG( zdiMjB(TNpw>&e6z+G@idC1^(me6S-D%rN`17b}(?zRn(}RV|!z?k1tdS zAXQqCex91e%k+s1y6?I!37mSJ{}A^rtfBi5xVnWLB`?vh;0}#-+FWBDX_8UmLqUn{QzNyg zQm$7bxz-l6lViB7Bd)XVonLbi_M2C_VS|@A)Rc(?mH=uQA`Rprl}-2P6MFh@W{+iL>{4IGdtU|% z2(VPiIJJw4tYIm$Yys?zmu^v~W0?@nIhYjHd%T zwmpT}^=Lb`v3*5lr^znJvPj(6-vym5jZ7)#sXms5a*{LyIZerA%pFLiBJBf*(dZR%MBAk>)D^V;|8ECX?94}gPFv`IH0}GPN74|8mamxw zZI`@;yz`4VqsCsZ%>I9{ylPdsXW7!9FE5vuujnZ+XEM!pEc*~mHuX25Qv+q-SA+BB zm|`(-P7&tN4^@uSP% zt-#G(^-na&hq*UlBt7Iu>IrS-Cm^*_$RnGR$zm;4PmdA-Ru0<&v8XM9Wnw72*vzHw z9N#XswGx3kP>2u(i#eGPf`M#CL@5s-TXtCx?dDozVWWtQT(?hh^_09Gx9DnbOQ)g{ zgRF1t3=Cj`e_E_M{|73qWqz2C&{`U5YeQ?F!f%hZ?m<`UEpCG3&P7&&8y2E_j^F(@v|*RlXN+I07`s=`01hv+@GAh>Hi79a`>KmD2j8}!`ri6bxqY*_%!`1iDF0R9@K8SGzmb0q0|}Ek(}U63Ek8r z2fCyXFB{N-Q|j)FN!Aw06Y_9Y1J-#o0{Hrpz=l(2`wKNUp48#pqVp501xs3c(5vei z40ykKIaLuG%oWqTt@4C;dMF(Y1PAW8vCDs8;IKM0Ja$lRO}3RTTi;VW|H5PpyIN1H zi6Ck_boF+}vjWZhDC8e}>O}X@(#eYtFI(+%_Z}J^nd8uf_)<7Ooq@@B)^VuZ!WoXoPYc0)M46=};!DbEcV>JfW1zj^(4evWfCYzza zWHS`d0I*nZO3>nFEMx!QZF_#!n~eFqiKK!AgkK3OPQN4i^Z%+7I+JFd(EQ1$*B8g8 zNwJbYj*TR3miS%&tT(!QW34xu!!D37lZSyn^yoyHP!;NQsxIO%z|~s?PL|DBE8f%& z$b_f~4GP5B%mSyz0=V>AhE8@WTH?p~@IYVO<4tsA=un<(;od$tsKlcmtK_&*Q@&AHwyRiRJ3-ES_mN7uC)vY5wSmKs!G@=s;mOd(OgQypTBzB%^!9qI|5;Mt$ z#It;l29X+xf?5r}F=kIh`P zWR(>w2(ec7CHg1yPYmM!!gvcZ(My)7Q`x?bY-TJG35Vb&%_78C92gRcenE^012$Q& zNcxoA9tpE#NhpXsi7FM!(nNa!*sEA4AJhYjkv>hO!1<_1HGWJ&Yn zEzu?qStyO-g#a5Mp5b~xGniwRm15SRSPT7F&|P0f&eF76J1#zb_t8Dh&eBE2WV_#; zk~mI`b%lK4_ui+^E-75+cH%$8ySO|QYz_KSo&nu$ipAd=OtjFA*%h6;`iI^AJT{f} z2SV-XQu>ybj*iJq&h6IGnR0J7m~=aA8RzQ9&5jN`@W8`}W^Utez?!Z;)mqm@6jXL@DLQZ*`^P*#?HWIflc(738U3db`qw&9L%?kyXX^Nb9np!DW?b zV#+z)KU5fLZ~I^6y$P6PRh93%Pt5a}G36MM8Ih6mJWrKb6jfPSb5+({R51@ylME`N z2o9~S2($u?vrVIb15Rk8D1&XIASwz13fLkDC7{xMugdjFp7&cjA~K_@vWmiYzxVF< zy@2ztlP6B>z1G@muRX7|p4xP_Wrg~LJCb%Hn-`zJe%p`poP)z{RVw0A^ovg;si>tF$UpxV)m1B#%-oprRj zt%C!W?gck`45Nz9-=#bYqbXgD7Yfv&hRO?cND9;_+XCk-mZub3zBn+K(k)Jc&To~I znrylK?rW~OTdw@gS6p%P%~xE0%e57*iH`AHCfzWVuL-qym#>;V`>gfhW#K62m?sM_ z-+hg|d&SMSe5+${plfnzb6db!8=5|6cEiC)kdoP84XUr|);gh1nvCg)8GfHCw97HP z@g7+;Ws`o31291(&icYMjFeLV%64n)~AxT}@cd132&VSY}mrF=?CL(si)xoiLAQD=f` zo&h=a_{61GWbXc^p)R?kZs}Xe@cG~W@wd;vwBj?*V^{u6)xQ)6Hg+{b1QCa0QbHmW z<_j5paae<6x}~PJG#^TLyF7PCdF~Ef>MY)~7If*rt6wn^bHDoya~w7mGk;Hnu=i^{ z>`}w&vy*F$k&($!M|)dyM|(%7tEIWQrK&Pi(@<}3WI0%&n5gG)Z@0CJMz-J9*jANv zbhP6>hzXlPN4BAh?i1RI&f-mdevYePZ)9LlXnAA-RO%SQ(=!0YUQ_vUaY>R&jg<2; zqD_)aT@-9j<6zO`h+Se;X<-<^+@piz(zHc+4ok~=C`(Q;QQv#6Mul&={PJ5qf7#_X z8x0@p@;OqUefMzl#oolOD^i#5jTxh&x>wzE*VUKbe9PsReeTw|7b20Ak&HPk;T_FG z#&vgoW0_X|izpuv#g(kyR zmWK&>BA$V@BVZdkZAGDFs|fD)trnIe1NaXKECi=1s8*q)aKr-Nf`K8%TY2$>bn)nY zBa{Vw1ZyUid8+@p=lK6Qi}9*yx!}2h-~M)B?pB#&GoRoj(tD0PiA1AJ!)00Mt(7f4 zEjIX%GAa9>57aHO{N&bKWt3)aw^ZTjE2K_iu3h$>a_hy#oK;SO+1YGJ`%M2R7-H9n zIFDC`x0u&a8#T%o7`%(@KQ$Uy6_o!9aR){XOI7{IH6tr$C&x~E&T{47eq`6^C|Pukkp)JU z8UJ5eV-(M!S)vI3`7oRA^m#e8$r1-EFjkx}q7i?WP47)eTpVCvFz>AU_MMqaFTdx` zhQ@7|8-ITB`9m-K@tNT-y-*mp{K+^AO;5ANE-PN*iwu{4;WR-rqb>F<-b3*lnr98t z5szmUPLnQd4waU@&@V3z$y19hu1g=R(0uDfW9(#MtRkInmcM%QWyos zz!O(GbZ%bj@{0sS6Rmrl(z~i~Ao%1H5Mc4l@ChoP%#q;<^5^XRs9=6!iTdi~CS!7P za;j>)f)L#k9js@&_;<;;dwe31ip5gnOU5T$6H8)aV=-!NbyatleV~7!tIC>j)Z$^n z=d>@GaI`c#d%J6m{&Y1i&W!%j$g@y?MUsWi-U(IV!zLj5)ns`mV^ViAqzlNfL{`xl zrcjMpQ+^$~`HT8g)tOaYbs@b+7;vds+#aflS?P3TvJPv6B9}1C+lka zdhNqQET_fn!QtLoE4~_WKftWk(kVLWZr?y(2B#r)MzUln8-GqI=o?D zs%H67eugKT9c|9W;oWCn@U(SVqAs0E)iq?(m8tqH?y0}@mV4*Sk;6R?w=|Db7CaB* z@-Y0q-@Fyi!#3SAJw_DBv=U$4qey&{F*Y_i?#N&R;=zXchKxH?kM}f7rXf@Bs&7!t zn6RajmCGb9PzP-7UABB}QoIqe>f)$~wlMC&DNdEks7ZN<;z%d8rljN2bEK)(gPLM1 z_1Xe2NxVjlm83mmeC)w+xPKuS-O0DX7vmD(4}{F#KJjo~%XX!$Jk z1QxR)2EADJBQRYxzxzNtdFYeBV~Gm!(SlKta5LjZsdK;(b70UI!0z-KJ2zWaIO3Hx zUEi*&zGb>1);0L834}iQZT5Kj#a$m0kPC&W@O2@eB-{^)bs;d294j-I;9T z_pvqr23(oc$Dk zKcTjuQD2D%ISg^!Y0uT#;&_mz9ZOmr&B@M==7p|P(Tg;8SJ(gfzCD5|R`%Q?yLJq{ zfq1?jDGsI4jY3bqH?DjBh2c)Y0Bir!!yhmBm)9n49Wdz!9U9oclcZOqZR+#WG%GA_@V;X6P4$-M_#T5h017Q8j2NJ_E#ja}_b07#&ftU`ICG-L_ruoX zdvPvwC13R%$C>lIlw?+W5h>Aw{69-d(sz6vQu;hI?caJ0Dd}$GtIiXVlJpk4)QyZ! zqz<*V&{yo>z%KUQ2-y79DLL;|j|)G$%UN9&tqb^_m?m$Bqm3=lUbd~J>l$;8HnvB# z8I>uE57)Y-m@KbTnacZ#p2cckp`Z9VB(>{2_eVbB+53;LA*^B-@wiHbUjwS&nbs?G zKV^zjvg?hdOD9hn8(lIn)=^zmXRB>*v9-0*ABos~eZ8Cq;pBFETePdL7P&d9mpI0m zRdHj@tMg5c?ykWB$9T*=F>bWBSXhvnKN7Qu(5Q|_RKijVT3nQx@1azwrRDAAQr#Ua z>!Bpd?!`apiPg*J>noWIj;HE>-;|8kHC0vA&RzW)BAuzs$n0@#rA#YV*3`e6JB}(6 z^+bG3YpYhH_7d+^PDRE2G<0zy21lwY#Vs<%jB_fH80Orj2rd{mg5t)xG#N%aSlj?B z+c2ePhuM;u-+7B}UF;+jI@QlUIynPzwA<;AE%!fo-jS}Six$YexCd(4Ybd;k?Wxf* zLW;a#b&g~v67o3J5&V?bozh~uSl%*@%2@I&!je%kCyTOVG(H$w*K`z51$*H*22bKk zU6&6|0ri@U_$f&Su@v|VGOXcHMNKsh)I&~Y5Se7*7_3888r4Z7OtjRJzX?(7QVEsV z!5w;et+y}Ypd?zT^~WruN6+`(@Db1X-lJG5)#_su6eGRg(~VfG*HSWXp|TR8ShP=s36%sU-zvI`=v+Ki4CqoMAwKyd{QrTNqwf)@sMC1ou3 zF5HWZgQH~=Q1i<(GL{pIw`gHDR@P@yiEMqsXv(MJwM|vA>ZcBu!%&;`owW=Q>Ir{7 zl*~w7Y@jY4?L6JqCA|ynQJJxC7++O4O|H?ts;cUvzTO_cHPRc2x}z2Kj1DsOP5DrL zYfGq;0YP;Y=hRu}s<(A@w&op8)yW=5#N!A$os1uvjNYo0>@@0Gm`E<1n-GC;Y2DVn z(?S=PM`bRSb@eUv$a)rYbanVJ7hySH)9!<8rKm08v>@ye{NSq#rt+a@#G^HnTnx5&I-z1>f681^I7I>I*P4lg*OCoGWI zdEFx|cCJdi`xkL{rF&OLhSogFQL`a)bjELw>8-hF&YnMx&*lOgg-2N7SLbQESfc_VviMOry3op4oAkBVrIQGW|t+8!Y+t;RV)iwk9?~=Re80Ub+v{vE_)4b>S03E9 zP#?9Gk{%cTm9@RDMK=)4yOP3ivk~OTeSYOmc1qJlELI)In|crX*s>CW>}yFPMvvx> z=Uv^}jHOQ|8i=2jOf{So$GebKCD4XjSzi(FLY?Y*yhq78ge_l}@G#lyV>`bm?{#^7 zexJ`@yk)0ZQe`s98hbcrC)NZZ6JoAp%<46aaA{traOOcPh<4+t18&K3L*RRbS+v5v zo^@sjq07h8F7)*3}WT$q639vLJ!XfN!W8W@ar7;Kj@SelR>7?vBBcjdS4xbm_y zmuFUVge!LK`S8I#OXps^aG<#=u==lw*-vKXzLZNh55BRl$@0~8%iq5Fs?*Niw7zQd z$-TpCt~>kuHS1d6u;KD8dji|>%rrE2+q`J zMjj5S;t!`aj#HMpT6=wlBfM>`we^lVk562eHQQ8krp|3;m8R71VazOgM2Fyr=8ix4 z|L{??eKFZcA60J|lNqkpb`x#vVi^6@aeYM>jQ;H>=rFn@5wZV=O9bQp|A|DTov@1{ zoS;OWr^T4N_V^;vt;WBdph(KJ#6jQj-IF7_@7T~y^Wn6MGxTtGSExN{%QrF^m2JTD zL`Qp?DQX`xFmXq#L$x+!yb?voIo~mQEj20cDLWVGKNee>*CUsYFhIt!>fC+D7frF< zIZ=JF;^X$eEzelrrJ6W#HL3S#PEAcNjZgMlEg?sf3W+=jbQfTIeVe^!+&-jTk9#>2 z<4{crE6bi0Bc0Cv$^Pba9B*&TCznp}=-MRprc;mbq_;%Jv3w4{RIN%I1(cd9Z>*-I zu@a98dD$v2)ImwqcNW=>yz8%zPRrzeESuyog;(mc3pV3G1J>U zGa5*)nf~WX-&+~)XBH&GWPWv)h&}0X){7IC?>QWCW5e759J8Oh)3|K4k+9iQUQf7x z?wi-0H2MBZjh(#}Vf!PQRAss;6|1#mQbP?K?2}ne8$MK@#e?s#dMi<^We1X{q29$J zQy+UwL zFB@!VYOe2{OXdP$9H|+rjBjq+E$vzqKPunXJ7n5v+b?1_kL(nz?aLB9P}Q=1!4~$} z!X38ezFq>4iU&)pPEu3f3sYF?zd7f-)Y zHcv4ljAR^or#5nly?R|a_z!z$y?beEPhKegZXqsb`BaDX3Q&s zHhV?4t&L5X#5}C7ayycJ#5Bw`8%ewrSQi{|9Hl6-Yp>Y3k#@YKD|j|7H#wuaf6Nxg zzf(BoetoX?9VaFpefoCp<0qyx^Y!R1d>xFd73vZsG(A1JvSV3ad!4VtZ%^4W)waxp zZFt#9_AH!<8TtL$zAn7Wz zW<9@REfwkSQl*Bf3QuK_KptmT_oa&m#R4ZLyAS!CDbK!an?6i7_t*)_ko}CN8^wijLOd>HYoVMkb+Qz3>Oj(n*_O?n#^U0l#0cJ|%tlEgt zY%#_canacYC-&20 zjRQNQb(OJrx;j260&Q8;>w5F0+UxpM_qgRv`QCy0d|&U5>PS4xIhynn1#z|><%NCC zaI#%{VfQz*N;~NyTKbobKjBYej5A*n8%551WyX5hoIW)bJExoW6iF zHtq=ZD2H#zk*{{LKiDxf*^oCv1gUQ+Y9}+f(rGC4C5rzr5Y!g12!~CJv@CYYi=KjX zB}zwM^k_L>&jIGb0I%R#d%o?IJ<8%CL3(M8O9=K8>t&Gmop!I?=1jK@_YUmrAK18d zp!Y@FGQ*l~+%VEuS5@74)7~Yg%nZ+*+4>G+=gzNoHRewW8FzP${>YN3GJc+IsLv6K zv|*g~V7+0j+SEN%S2cY98K*BD+Ax%Cbp)@tqiY`q}o!OnOwnWgzR>i7LXEg7qauW!t6u4M#f+)`Jp@>>ghlz=E zb>&7;`{~Fbq##}g=y&D^i%ZN4qvOJJ{?`4j!tTa|@h`Pit)tB&`zl-Q6-&D}?CI-R z+-dyns~bms%Um7H=v7tMyF6!E*DO0@5f}34P$mAkEQm=pK0U%|$TV1*B#vUIRY0gsvYFLX0C_hpf&zJrN^}8Xiw|M;Q@Da$KZjs|NjXO(iu8755^9dsBzk&ZfCHz#^Fp=IugNz?!+vdYCT3_EOcL@ivNU2KR= zwzN8$+`e?v!r8^b=()6rpy#ESa)Bx8SW(Ziiwv3uEv7JNDdxqq(<8WF7SvUAHRK>Fmpo#U|s<2ob53%NfGI zGHai579B@8A*aPfj0~w-^Jf5-aC}V<=ZY(yh2Ch9VT+2DTa=jYhf=W;41Bdic4EKF zo~eP4G9cMF-Fnw*Bk!tSMHTwR+@4XK8e4<@KBKM46D4M}1)sf2{k2Hx9->AIr7A)M zg`-K;bW(j5mNS&5OQ5~w&4oXNY>iM3IEJV^+7qvs$o1$*G7xBS6-*c41dx^56MEysx6;D<-#v_^BO%3s6 zO)j3O_AW3eeZT73Fem$ZV`(|%SD*OcQS72me28gq7iV!s*vqt9kIX7Zh6ke|kCj=o zs>+Ubdly@iN0>^p4a0CU!S*-J*7 zIS=Wp6#97u5uk-KUnEzVgY4q+MoBiIMaFLoPZkCz3{C68(0_?)%5|qHXz5n;w81$o}fJ-D%S@rxTZkTzLXN4K+yu7yDUSA0ONaAYlah<=4?Lnyy;dR3bY?>n zoqAj!TG~@}`W?sQaK0AJz4=&N+H~D{&hj<5ti#Lu5Yf3>bVNkoP+M!d(cYRKVse_m zP9dAGzuDPP?U3M34V{ODcRF&3P)v(1$fB9$Tzz>HtfL$r9_q>I7%a`47SAVPd@(SE z3B|*#@So2e9~xV7{@x{H6I1D`+?r+CnwtFd@@)0oQ&}R7WD|Wq$i))1dE$z=H_n{D z_vDo;Pu_RI^y)wCSh9I~c=e{K*<}O9^Re1=ERh*CD#SL|WE1R!`HMQ)_>=K1NAkY&s%b zc8}voi_wK6yL9QQOC;)y%KrX06d%n!EjNiYC#zJo`MB{LOOTcOG`=pbV?|TEV_F+( zXcB$oe5M*<4HtcB*HrM!$=^laArT>0VanZ<}#(Z)nyUiz4XuKZ?x{rJ=yIwza! zn%g3gktO@OPipx1$pk6*PG&>Ro!PGG`by*f8s2=-zLjh1#wsRzS~?~VE?=D9HB1Rk^`ci#m6K!uHyj{_We!fwMPRaKVmKnIR zjkh=SG_L5|^f_bD>Fzn*J+XJ9zP2KidnlW#sHtau_5S*3qM;$tkI((v8rzl{$pK4b z?)`m6B-m(w!~UMO$+`NF*B-t$N%$xRm#IiyI+4IC;xBl+@e@W5;yGi5dIvs(WgfpJ zlbjgH)!@Xe6?X;plb02S(#u-&R$Mv_JNw3*eKM$a`})+$Ees--mFj(Qw`O6M?}&3! z+SbnxC6+BRn}4ivwUae_eSjjNkCw7bczn0yM~$|BRqm&}xjM4ApK{AlgYTc7u;X&h zX8-@$_p%JjLR^oyJp{z&W3k!ooJqGz=nVc?_~4ZYuK^z7$2#Q=zQ->fe>rT-TDrO8 zb&i%ZbAgc(Z?87?M%alGOj0(7gbTLfP6)>Z9^wYN`I@)z17sC9ls3D}T{{&?aZ4C5 zWy7JTd`Os&5LWnGBdN;Asgc-77JJ#pW|z0gODT`Hz!T&Yd4e%vu=K(IJ|0cHOinu; zTvnn1ySc@eD3^yjNry1DC7!Hyi%Wh>G;C57GOWbKfhVsGzJw=&xUm*3fslnK8~(ZM zPJG`I#7*J6q`(7?j*C3u2VXueKAI=q(9{Y2Y=GAvd6!7V`U6j1AN1&q9S)ZZ(Qvdgi%ge_@KXBNMJM>clh0q|32kx{ zY8(&2BH_}TQvR~p+z(F_kDG{eZl~8R96DU?0#CNXd2$fKoDaz(C1H+o!q11@4^KW= z#_h2Sj{`WHp67|Ar0n3yVR!3~PctDj7XH?#dEyOCofL{LOw>sDM}74Np8NsSSw3i< z$0JohVyKt#g#Nmn4x)*!ifW!vVlVZ`fd?^Ru=Jtyp+Dqxdr&zqQBJ&WzgIYPy1kx&*Nb;OsS>Ce zibh?h3Zpn;LNrg@P)=^lL9a0GlV8{u{_nSSN+`b8h% z$wjnh`2-huDm)ORLSq1(K3y(SPGxnCx-rjFm?$bzrBMjCpZW0uPx@B{w(NEfF61LV zj}LwD6I#~i36i`|cDwpQK3|C^bP=7#hPZ42YMHcQE|-`~G*ZzvIXUw02ub@RJOv#= zpG%amz?07}`Y1d({rW?66Fx#%;ctz)j*;l%JZZ}$-jr3O;xL{NB87zj=Rfe|^SCPf z?AP^rgeSi@}{jbV29*r_3b zfS6xDtv@EM^r4pey{?$w>ks(6fq=sm@P-5Y<#+o6{)q78&^%GaC={xI+aAK4z!PnQ zXdwm>)2&PPt<66r~x~JVl)0pc@k|JcX1y5Ry8kc@pA- z!Kf}CA*}GXMz2uiaR)VVnkQkV_`yN5{-ArY1g4Y^O70CY#piV6?^p`0^l>=D8jc`;A~XM;Iv8Kzsg zlOD>7V&tu$in>_CDDo6mo=}*`pCRGNUEm?6RZc2SxbPs%hjx(}D^EyMCly9`DSbRz z0&KccDv|Oj`Kbdt9cIsg)1!GRm8jSr;Ry$}A*xY0Okkw|(ZBp5cnXK&p-@103MdQ- zri6X#4o=DY5Fq72$(Qkzf~UCV$s1G^u8OeN;qgg1MU*#0WC6{S*Db_{!<=s9BZNf? z4}a3weAUy z{fPn1A$fee{p~%af6X=KnDwXl;*ik}{?_EVp!KG?N9b5j@cjzwPm9m>ml}Rz{7<|~ z$g9&wTrqVf?tlrer6fRXgXJYof4oFX^`dGrCh_()sqDrVRLpWc{JyAiMhknaUR0y< z8{;wM=h|#MMhwZvl#9#D72%3DP~4nE&({>kzq(zrv#Egj0H z|NVsds__T5@V=41A2t7Ax!ruhdYAdU zMpYSWq4SN<*{poVf0-{KkC!Z8Hh*WlKz?_aPZ80?FwRmfMqKTdf5~^PWtsUuM4mzm z{28_mb)j)DK7^EchH<9aX1y09LK$#%@O?_l`%KE?F_jb<^4=QjMfk3lcefzd$MDqu z7<9!bn=dF%o*62Xp3Tu*rNHY~%ef`92R0nD>Fh&=6K5<`g(; zHi2X2AUL6M${gl?r#S)cGEV~c>Gb!Tcw1Bl%nW#td?U&^_bli`RuSlw`>>e?qh=o% zH-8Ey=l&C{oRj-%^KP)tgjSWF`wN&ge+_n;KL>~Beg}@4-v!6uG@{0J3KMg$aKBII zvfr%a{=l5Pe~{dxNMJeWgNrCMECVCv5STKX!D@2}m__nYWO6<@40lm@-w2NC`!REx z`w5Lx<_!1i%p1X-<~nefIScMKSAqL=*hIb@ zrH6(%dh#eZpm7-a$C1+W;Dk;bXgwA`wG`~&q=2yT*G&#k$4}*0Y)5syk zw@;`_e)~JHjvOob)q`Np{2JH@omJ?@i(uTmAI!mH6|}uboZPVaF)(VrAFMDx1E!#% zTBlP@IuCH4ql~Ia=Ud=3xm3gTZ@?|cq=s+rVr@Qbeg}-2Uk9az*7E*$SAb}=Us0Aljd8%l=)t; zQe&0=Rke8?Pil~DPSu)U2J3VRX^mO)a-QVOJlKe**qq9n`@tsjU%_VcLa@a=0JfUv zf^FulV7q?OLG8=IoxIbff7Na7<-W&!GuW%2^qIGC->-i=VBXCAp#JTU`EKrqHRU7b zCESmiCxc_=c5obvkwfxA&l1hcl=&X+m+Ehqn;+$Vh512nTHmiU|B?F{^Aq4I^Hbnz zeZL0FkW*{TFM#XJZ-DE~cYzx;g&WbjoZ3V==BWFh1UI8IIZEexaI2Q^HuH1bZ>I+3 z)DAQ)ho$;HxC_nCsZ-F&9QNvNaE~s*eYynq>l6-X86Kp38!6=vfIjGNq>P>btEs1r z=-z*VIde7GgavCv!aoN4G!Ez|!}`q;tV$zN+6a!B7lRYjltwiLosG!hWpEYx+NjoO z+(6%}QElWDP@~$UpKR5*jh46(UJijf(U3-Xxf(o0O@h14N5DP$&3&5M{aErwtjby7 zLAc1Hx6gtBB#_ruB9BJ>mishmqDSU8!BPE0+ReP~Gvq0qm${$CzU0+z#=T9X^C%dZ zyAq63YnqVEyajBih(X$`68)aw|TUL*OiRzZG5jHRtgi8hu#cHd2!(6!A9EdHZ`PwyO#9Zu&$EYeyGJ-P*d8W;blQe7xKRa%$aLJX{Wl-#vg)xShFtLsYk$_ z`pGW+=5F%s(iXl;-2+wK@c0bqL`%C#ISdA*u4? z&2CEV6W|2(y&K(r65OZL*>4VTe}Mi#H+r~{6A3xUJ1zZwDi02NmjcaUDzi=g~!kY7CkPUtuH zqaj1&^(+|Y`4BRB8cfq(50Sz*IB6TEr#ei^7lKi=Vi=l#1g6Zdf_3Iw!L<1gU=Eu$ z42Ay*E~nmcu8mR~MgsEfjClpPTBop)^oOyokAt)3o50Ojn_;Z$JHf5kw_*IV-vjQ@ zzuk%U4r7Zx0G>j_!w9wJ1+dQi4=@cEBT)EHU?bLJ zlvec+=!ecxQs9sxJbny}n$=(hRE?6(BVY;}I7(`dgH>qeC~3YEOhdycX|4wwsTZS2 z`}<%U^o&w31P9<{6lvT9PSc`|B8}_78J*WEYVjyCxe?q*e`XY!JO<99=cCBvX>f~v zUt}_hOl}9aQ;$ZG!}H*7cpOCz_cL~L(E}ON9F4)z2=@_Mz%e*#0V~XdV4NB{21g$R zE7907IQlYJM-O2Pj@}IB%oSjxxf5){LXN@Fzk_{nHwH&P0GBg19D}0|gDdGpkHOLD z;3{-!430hqZq)Q_g7Psqx&hn_cVlpL4Y-wZ8H1xQfZO%+9q>Db4S5dS1z%(E_$0WS z(j0@w?|}DFo5tbmJ77v<4huZ4B|i?G4{+ZHU*pjEb8siMb)3|G1n#CbO=u}iAf?Z9 zAEsrWAhnHP6iu5zN;iXX{bq{M!~{}$7_8E7*3nC!KuTwVIdc?jq?MT<_nW{rbbEr_ z<;ehgGJ%w?0jJGV!Ic_ksPz*_>DS0WRXHfI7U$+w&J{T6dK_ggic+mQAI zQj#=xXxesC;uD&$38Zv4_q!>h38eHj=E5Rq;}W>|EtoPd1Eu%Agm<3j451ILp5n=^ z;3!%;g-v)8oWL4PVOJjp_vv@`L+2EB_1AbJ&hhPX@Lq73(pk=LzX*;|3d{NJgWz&n z@a1Zn)@M1~y#lVKmMvH7^^* zM=mqucr7@}+}8{_-UCixfoI4u39is7i2P^Jx0gZ5eFlAd1zfG4Y+!C~hF+fw+^SLJ zFr&7!b74l)unN6>nf{`*o~zVaQdmWgB@NC(+bZ4+5of9zU0MxoFM={6UJY%(0Y{-> zHB|ivxSHRt)+wx3>u6C{YfV^9?($r6U#)hK@@k~fMc-7)dJQQ*4Q5Gy4Jm&b97eWl zNcp4S7<#*g^uG&E>F3KyXAN{EL6P$s===k?9WRw@bjhxvWS`|;N_H)2-VIJ8leJJ1 z0;Q+77J8DP^nus%+n1p@M=7jBwjogHT#r6H1*Yf^Fh0YUu7{F`z-fN99{Gj9SyEoF zHj~uYYZKTBI z`97WI0pz)f^j`q0$#D}Ye*+w*EH;tmr@=9FZxdzo;7WZzL&}@9rft%t zunB7~>1@|1J?BkWp~pcPM{FYB7pN7|&zwc`9{}UDIJ4w_GnmEN%tFHx;4rUfHq#2o^DOV+(6gC*52-Dr`~nz9Gq;fDSHK)rZVTz$29Cnx7SeeXoS=NS=yBOr-v14n zTFpCKdGm|l1X{gSm+V$b;T7(srf)@;(x8;`R=92gMbEeLpFH2rtj$)f)mzak`Sw2Q z;5ImY2^8(x20c%K!<51{=y?vDfZuIsdk7S5-=@>w#=l7}ktAbu+UxDS`BQK?d2Q!S zD=50XT}xm)G6-=mHEz46VLLR)o1zul)tA5>(C|2z#U}3{&D+3XbYlmU+yRc!8`(iF z9|uLNcfk80P&9A{(iYrES?|y#z607`RXgGCMKDY{J8AK61uM|5ok;ZoFo9O@WVYmC zu$neyC;2`LHtKge>80$1hHJoaTO^S`R~?L?S`sfaz9MJWw(|9JrrcJTT``Lw?4Zmg~xd!wCzR@1-EGw>$itA zp9OQYEPF`jX;69&d-VHzpe?QTL0b}(Re*g^$T$`XYrr`2+{bT!0m>@Ce%`DFBdkj7 z=gm&Af?w^&KFbs7tL*2^esG$Zy8Y1heQ<_S*bi+Z;5ypV{gl@)!7XNkIzXB&U}Wys zV3fJ{1El#~P-s3tYFDd+ypsTBP2?c&w1ToGa*%u<0A-|hkT=fRD2gJ?31iW?`MtZN~J2vqiRN}>I$W5DwV4BaJ{5dx{vEON@d=sRQ=;h zHGEX5EWgh|Pvg6l%Ac!LQ;Sl~Yn5tQu2d_$w2@calS*~4RjqSEsjd;Fx_Q>k``s@q z)$<0f2bAhfb6uoVA2jqYSVrK4*x6QW175IzDcPW(qGl1)M_6W>8xqu`hrqxKd02X zrCc{Ewf-ulHYAnW$U7T(e+JGh=zYR5J%{zaVX z6!O&Jkj%lZ2X57%=_z4H%Bz3YD}^`1th{($9>dOCC>MH2IdYe+$d{(J{;{6X#Ds?UIU;8(ut|Q;;uUG1yq2~rS!LN&-5m^n^AA@zg-NkzgD~%Tv@2#{} zP^dpPRvWG?-rLo*F;l!3=gyxh-m@Xa_@>TB9!Tnvr=XLzu5d4L#`YHPt;{3dQoOf8 z!)3*LJ8R*M#d|i~7#}L$7t*(~R?FrzW->UGrtb^%7w!x67w!x67w!x67w!x67w!x6 z7w&cXx2C&?hlkUfF5aJBbKV&j9Juh33oklr--T`ImHW@=P`9cylWfEKKk2|-jNwev zc|A{^f!GeH3)LlD7pb!_(ibxQn5I*^+ay-@=9<$WZr@pFo_AV$`GNfx9XRKL(+-|{)&=Rlj_&jk zsjMO80(tu&>`W*)jkK0)8ZH9QA@|d;#OLzu1$@(|BSxhUr}e~h?-}gq8tfP*O77p8 zZx1tc9rVToht*J#n?*%ZCJ@nh{b6+_U${F0f5P8#_>E0+d~DPc2b$?(zmJD)l0MeD z1MChAv98S8G3%W%Rtpof+bP!Ys?h%$*3{~dLq^pTEr&HM=Kb^Z9h=ePRtmcvdOM-J zo0-;Lq}b2QOa`g@lN%)x=VdoeM9}5x?O!;y;prz zeNFv>x_Y#MLH(0>m-LJl{Zd0eDE!UtYKSUpXpdP@cJg9!8eyq+`537gNPwAhYqy9-fsvc24M`!*~ zy#b9nAN}2nPJbGGdLz1Y0qTD-72!?l&FU@ctyGIk)!S*??@<4u-a$>jTwS5QWe^OV zQ_&8?X}Aox?c|FuIN-c^|9L%KQztpj*?Y;sbNdSa^xMxkw`ZVBW4Fd0jlF8Jp`s!h zjj+os#Fn!FTOMWenrsN=^n;acPXL?DhWtHM?!OYW literal 0 HcmV?d00001 diff --git a/media/nls/c_037.nls b/media/nls/c_037.nls new file mode 100644 index 0000000000000000000000000000000000000000..4c5651de2c67509887034c35952726ff81eaf7c6 GIT binary patch literal 66082 zcmeIwL$DYI6ouhGwr#sFNn^j*X4BYd)Yxil+cq29Y@EinZ8wW{rrT~i|G9HlcXhtG z5lBH00{HgOokNaB-# zge0OjztM-j^dl^>h{qrXGlZcGBLpD{#VAG-ld+6rJQE1cBqlS3sYE9RGl)xKW^t3- zT;~S2xWheOFo*QyAvNjfPD&o|kVo9-2~T;(W3G{e=yOIqDP6?Ltnzy{<6>sQ4NlH(knG0NG z=0Cp>Bxtbg0qHZu43Q#S_y`drMUE0RTAsX_QpS!Gm@0mPgo*P1+^buS7Ug@Csa3OV z^SY(#J%91?)$2EJ-@X6PwRY*AtpdC6+P!D*zWoOd9y)pI^q*(Wo;!cx=B?Xz?%uoq zVDt4Yt6FyXtxw;6{Ra#jGE5W`|0gBx$nbF+#>l zohEI%AHsx!^_rKW?A3 ze$DiYQ-^NYxM^v_M)eyvXfmT|`!;Rcb?(ry)3RTlJbm=+@s8eKzJB_=d`0!bMG6)z zRBT%D$`vYB`l(9QYQst#J@&`(BR5)Kxq9jH@DbMnjRFcNpnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0{=sSfPlb&?`srLKmi35P(T3%6i`3`1r$&~0RXvL_H`l_G$Yk&r7kOpgrhH99GYlKE> zltyce#wu3hG+q-lQIj-TQ?yZ=6tAt?tpiHdF&))$ozw}P(ixr8S)JDfUD8Ee))igT z4PDnw-PSGL*FB}^fed4bW@x77$TU{yh!$y{O#fw?t0;4`66I$uRkRsn&en3-O?T7H zjB^P#=WDeB{ZH$z)@r&I%Ez2)3paC^3$#Xo#x%uggZ3-J7HRV^JPlu?nBir38+Vit z@KCX~2F5If8exVl#h&7Ctdx)8XH+oOD?#hDOJGD#OwO9LeReN+$hm@oc+h%*R zeX$blN%n*GRXS`xWRJI}{tPy|OSbGea^}jNCvQI2{B8x@3wn4KDqO_N+oz~+F~8!5 zzgePWKwwa*(q)3nI?9!=5K^&H-9g$k1WKM~oabdd%3^apNaUoHTig z^@1y5-He%smRYkF&RY||-ZA&?^re=yVEK>79$3F^aXuQi?aZm|FTK3zm2 zg^Si}*Dhb#@w&D6=JgwISk|1k-hBJrci#Ks{SQC*=;KeOe)`$f&%gZQt8czOu=cxe zzyHCq5?}E8XWO@)Ej?Y?x$Eit`B~EQ%g*Y?3_CP361e>^edpf&lz;F1lfIhu@?W#w zN^FDx0tg_000IagfB*srAb2k-DEV+&WF34QWyN5=bE)66;$o>gt#F>3)An0stxO9yID;i=$$#hS zCzJH?ru2o>{3qx6^Dh}RDIs}BP1ID))LbppQmxclZPZrn)LtFbQJvITUDQ?G)LlK)Q@zw%ebiU|)L#QMP=hpB zLo`&wG+ZMzQlm6lV>DKW6savbt_YpgIgPgqx~NMUXX|uXS9L|#bX}|D3%sG5@_Et9 z@7>aEtyQS*>Ynb)^Jd!|TVRWAnXRz%3e$S6vJDojcD`^;w3)V9oqU~rYc$K|+B}C-Fo#K zG;GwkNz-P{TeNJ|x=q`5?K^br)VWL7ZrywI?A5zZ-+uiE3>-9g$k1WKM~oabddyh& zFLA=TS#Im%kg4n4(F04?xvcUSixfJ6efB*srAb{Ur-zbb?NuQ?Atr#ke}{+5X69I}l7 z0tg_000IagfB*srAb-mJ_ugB(_q2OkwY64jwXJs8 zz4zXG@4f79F|mm+Xqxy!67xMbx%uU}IXUO|$!(+9G(ULB$SDoM%eC`T!B)k&SzMX5?tS9MdmGL$Kw zveaEY)Kl5&r5yEEuKFlXeU+~Q^;3ThXxgYyMJiT_N>!$E4OE2&X|RT9s46u~!!<%9 zHAi=nxJ}3RD&jIvZkm}Q#DP~HA6EsOS3gcb2U%%wLlBCNQ<>Z zOSMePwL&YkN~^U-Yqd`6)z;csdyBLvi?$exwK$8n1nXdlmSoA+(Hu)L*E(5e>td;v zW?ikDrCWw&n$NPVyE)D-ZPI3KmFw(PknPkqxheiO${O4N8*Rz%ZZ*17-74E7e>cR; z##pdbTPquHp;lw#EYNl+!QJ3j;Rd8)?I>hxN2<>t#9C+j6asD{cV7GR%k_5Y$aA|Wmawjt-=P` zU>jmXtC5Wgqi1%noZh*8^7`f%^y@#sD=aE5DJ?4>STShukfD{shL0FIYV??~Rn_Ch z*VNWcsGry{Y4ViDsne#maka3YW146>(+b!Q;&O_HvjE; zTfA-FBlr8R^RC|A)UfB;16_|EcpYZFe3*SlpzXmUFoO{Y929tK`_9|$+j_^Xci#QP zQ{JnuA9L(+$DeTGNhhCj>S?E+apqZPpL6bp^UlBE!iz4xQ?DH?a{Oap(zWwg|AAbDl=l#F@`rGe+{Q1{A-rGBFy#1M5_T78eJx@OEz4ivq z2q1s}0tg_000IagfB*srAbxnM2b!{7&E(BT4>ccqH#Frp-TWUPi4i~m z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ R0R#|0009ILK;Wnn_y>V1hy4Hm literal 0 HcmV?d00001 diff --git a/media/nls/c_10029.nls b/media/nls/c_10029.nls new file mode 100644 index 0000000000000000000000000000000000000000..f46acc883ef0a35a6a4ea86a47b5ce467dce0b49 GIT binary patch literal 66082 zcmeIwXK)o&7{>AEO+u&%B@mL(mKz|nOK%B*LkSQd^p=DcAfZDNItc`O@4btn0)mJQ z3pNx*P;3+xK}4~jVxuX7dT)Ti89wkKGk#$HyR&dL2h)l+>n zP=Xq&ks7Osn#!+cYOWS)sa9&OHfpPOYOfATRFXO>S)J55@I_tJRo&EGDe9q~>ZMfm zRv-0Mn)<1~256uLX|RT9sD^2{Mkrkw%G5}W(rAs*SY>IP#%qGIm7|H8q{*71shXzg znxUD>Ri5%SOS3gcb2U%%wLlA1ph7LuVijqLHUAKZr0I~t&?@OL`$+B*3-J%YQ_0dte1uRR%yK&cuSRP18s)}S(-(8 zRlS;CEicB4^^R#v{eCvohFQ8LdP!b}4Yv`NWpQ3@Z=7Y?NZX)n%dxFmY(+NJwrRVj z*-YD|T+6e3n`N_Yk4~z+6Os%cZ%b8&RrA?mj7PbKf5brh~sa_uHYvM~)r~KDirj`s?J6KNUxAB^LOn#4E4> z0tg_000IagfB*srAbR`2Fs~kNnPU-|?0Ec-z-* zse3fA!_DXJa`&EdYZqkY@e6WSXE(Jj5Z^xg`23mp=9y5U@rl6fr=Ka&5==$_f%6J{ za^4Oa5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL UKmY**5I_I{1Q0*~f&W9`UpPyfK>z>% literal 0 HcmV?d00001 diff --git a/media/nls/c_1006.nls b/media/nls/c_1006.nls new file mode 100644 index 0000000000000000000000000000000000000000..195c32fd2dce7f4565da7a47efd284123d24f659 GIT binary patch literal 66082 zcmeIwWssLu6vy!&EIf2~ce8ZYrMtVkyK|RbV(HG^1(B9eL_|bHMWsPRL_|PDERYT# zJ^FWN$6??3!WT00y?4%Y&pA)by`OoK>26RQxtOUJMxd=YimM>SQ+#6)RL3ezmj)*Q`MxaMiT7HFXsX|a}Qsg`NER%oSG zX|>j9t=4J1A{418ZO}dMzW2a;=softdr!Ql-ZSsHm(U6m-|p}5 zr`lW#w|REo9@s+kkMEYxCthB$G9;>Gt8ButbzNz!D=Q>09lI!)Si=`&=^lsQY* zY}s?<%#}M&-hBBB6f9J@NYUV8#Y>bdRk}>sa^)*jtW>#5)oQMKjheM;*Qr~teuIXM z8aHX$ta*!;ty;Hf+pc|wj-5Jp>DsM(kDk4H_vzcO|A2vm1`ioJZ1{+gqehPzJ8t}h ziIYM?Cr_C=ZTgIvVY6n>nHxTD{(^;z7B5-4Z25|nt5&aByKa3%WYh-t!r1jfPKp2m z2q5sE3G9shrPl)G?%1uDzuNf9rdKy_*}84}j+g%|oB#m?5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q7T)0>Qy9I1mg35I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~f&Z1je)m?a{k-E2#j5`<-gif1dY?qE zr`(C?^_KfSrtjP@G1-0h;Nhb{{)hYhpL-+-yxaozr*n_@1kUhlAf7yZ=Jvj^&%Nmm zxVPOw_pUqa-g8IX2kt}nkvrx-cAvWA?xZ{I&bYJgoICG6a~Is_?qcBGF9LDt%gbL~ s`TFWN*W7h?!+q;+y6@a=_rs4rxu4w~cQ^2abN2%A{5L;3=MpXO7aN`ldjJ3c literal 0 HcmV?d00001 diff --git a/media/nls/c_10079.nls b/media/nls/c_10079.nls new file mode 100644 index 0000000000000000000000000000000000000000..29bb4a76a4b85cb139a055cc022e6c1e63c04dde GIT binary patch literal 66082 zcmeIwWmFbv7{>AIeX$i0K?PJCMgbL3uzPH=73=~P>`v_MPPf}!bB$eVb$7)A#m*({ z?(Tl~95GOiAC^y?|IC^5+%faa+`lu<3ir3kdVK1c!^tMuWS5gNDYLRDtFkG(aww;A z$yvGOqC9d{Ub)F#`IKJ;L12t5L8mY0GsHvK%xmu{DS}9av zYOOYEt9ELy4(g~*>Z~s6s&GZ9o4TuqA{C{c>ZRW5qrU2={u-cx8l=G*qM;h5;ToZl z8l`BB))b%bBf-dT^uIh@e z>4vWBj&AF&?rFakYO1Dbrc7h04r;z;%k){SS&A@Yl^}0(ks{3~bB314Zn~N-W{gvS zIY%qx=W{~0v`SMnPhRFETZoy(oU4`cGbSrWYqdwAwlJHU;cgT%3L74Vr*Tv9z7G{` zt7lBtc3si|Js2d*1pfaKneCl zdy;**_S=)~arVbQgU#-gDRY*r*|O)znaer1OCHy}ZtnT=7x3`(Dp;tncM-$KELzOh z&%bzyk^!XxOP2`>E?cgAg^HCbSE*X9dX1V^t=e_!)~ny3VMwFKO`0}q-lAoz(6H8R z+O})op<}1cUAl%xbnD(DGOA~<-hKM^>px)Nput0i4jVpVzO`tqwwUw`|}cRzf;chyfn{`||K zg9)#A{fq7EFP5IKY~A*J{_-sGcs5BLuTNcg zod4!nfBz$mCS?Q=NGE}R(`g^JK>z^+5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL kKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1pc4EBRlQBH2?qr literal 0 HcmV?d00001 diff --git a/media/nls/c_10081.nls b/media/nls/c_10081.nls new file mode 100644 index 0000000000000000000000000000000000000000..c675cb85a05680fc7a06f1380820d630becc944c GIT binary patch literal 66082 zcmeIwWpEW|6vpvqZ*T|@5+DhY%|a3&1cEz@6I_C80t9yrUU#M5sUW3jkrpeo#S@&O zjZxg)wWYT+34}XSnQ1z~DlwCQLQ@NB| zd6ZZA9FQYx)5l~K6L zs+=NJUKLbPl~h?(R8`efT{TowwNzVmoL^K|^;BOC)KHDoSWOhErfR0aPJBs6iU6AsVV-8mY;Wd$wQJVjgaN>qTgOnt3bYmQdPVR={u zto3eT)&i|jNYH8B)jG}8BKca=jYunpwNPsnV$RTdZPG!tGolPn)64WT{Y`Jv$GoHM z!H*PY1Q>xvgi+q;Y4kFJ%vJI=1I!3>qqb{m7*l)H^)0t z9ZQtxNOB}QR_m}M#gX7h`xy*}Tej>ua^}jNCvQIY`~?bn6!P>cT%@SCk8d$Q|A0U< z$SPhUI3%=WsnTI(!poM6C|{vsrOH*RR;ym4X06(F?7H>pH)zAp*{XG$ zw(X+Ycj(xubC<5&y7%bWD>|lkpT4pE`VSa5Xz-As!-kI-IcoHnvE#l=(`PT8 zzi`oh;o9XZyI!=H+`N9{CEK3+%FD05{@NQqz4`WA@4Wlo^!Gow`r*ePeRAv5L+d{O z?29jLJMr&dpPb^lo_g4|<67_D^Q80Zktg}-l=O6&q1v1w6aSsS?MJTn-Mjzb_dCD2 zcC%jnebyU^i4Z^l0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKp>L@!o%&K_lDc{ zfrH2Gefv+?Gmg%2?!4{s?k69o|4Ufl9Q4O5JnTy6Z1L&yt+rRC$4$<#G`;xqx+Y`c znzy(%(&}%V*Kfc3i$&T9AdpD{zhu%rY=Zy-2q1s}0tg_000IagfB*srAb42dqr1C1{ppnWq`O`p}nt^k)E(h)-gMFqB~oX9QshM|j3CmUxV30uz};7^X0lX-p>$ zahXLTQZR?>+~g|PxWO&D^Mw6mp&%K^OiI#mkDs~ET^{m?$2{N)$pYB|naD^1>JdU# zcCm*Y>|{54`HU0P4}3&g>QngL#;-WYAr5nZqa5QnN5~%dn6uOiq^A&MQ zr5Vj>K}(kNEj?+#BG$5oRoi`*))_7slMvf9STJ#t(W5q65C`Y;k34`gABu$q5 zlS*$NtZY-cXN9_-S8Uy&T*F_UJbm{3*B38ez3x`8e6M!FRXca>-m`b#{sRY3oIG{< z%-M72FI>NI^VaPFk$wC1A24vx;2}fDjvGH=;-tw_rp}wcVBw<0OO}@Y zcEpkJDN?3NohEL$_!%;0%KTBpNQtv$Pn0uP?mQ9l<^Q-qm^g+1EV69P+S%(yZTxP- zv|(Eht==|f^v`d;pR;NG%!|{9Z~kV>@+M6iHEY~_R@pB*bnMi%^H*JhEgwF*|G4}1 zKEMC*Tkl}7PVo{&OBO3NV@LHWRjbvmQL|RC%+X_qkI%i<{>Ps#T@41W1V5Nhe|W$C z?CbYmK6LNV>O-xa0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>|Cc~W zNHFBxF$yT4fC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36A zpnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim} z0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7j zD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7> d3Mim}0tzUgfC36Apnw7jD4>7>3j8O5zW_L;z$X9z literal 0 HcmV?d00001 diff --git a/media/nls/c_1250.nls b/media/nls/c_1250.nls new file mode 100644 index 0000000000000000000000000000000000000000..f4e65042c0511e3d31c4a07a69e2b8b6779c21f4 GIT binary patch literal 66082 zcmeIwb&yw87{>AE{q4e1OULd~cbAT(YnOP5rMtVkyGz8t#>PfPLPAhVu|O0N!2oGQ z5Jf~VKu`pAS9TqS8UAvHfBc?1bKd8~z31M~+(;b{H+kx%Yg(8|rjWuEu5?PT2xU-4 zWm0BkQKYgeo3bm1aw?Z{E06LjpQ04480A+16;vS=R-jnLsfdcIn2M`}N~)AftBlGj zUgcC?6;x4`R9RJ2Rn=5oHI$%4)l@CjR-NQGs;hdcuLep|Lp4%kHBnPFQ**UYOSMvK zwNYEOQ+st#M|DzXbx~J!Q+M@HPxVr7^-*8-Q-2N6Kn>Dh4be~y({PQ@NR85HjnP<* z(|AqLL`~9UP0>_M({#pWbXM6chb37PJE!w% zYZr7;U2U{o(pbB!E9!3tLa9H4g~GzqrH{yvF;nI&ky*24&yh1%?mT((MMcNtFHo>h z;UG4yNYP@&OOz~Cx=h*la^)*jtW>#5)oRsiBqY|XRlAPYtyjN6Qo}}#n>20KyhY1a zt=qJ1*S_f~e)xzV^<&5Vg!@T9<){73*_8Ej=l#M(_e*~HO3LuPuU~ro zgKtyPhu?kj$UdhyF;-4?OqEJNG}Ewm|)F0?%K6`wM^htNzyYvy2fy009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_Kd|Bpa?yg&AMy!(R>-RciNa+}|A=cCCV zfBU}xccrC!o=QtMt=@9ePP+D>C$1fk5kLR|1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL uKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009JUAn-TV?54Q@ literal 0 HcmV?d00001 diff --git a/media/nls/c_1251.nls b/media/nls/c_1251.nls new file mode 100644 index 0000000000000000000000000000000000000000..7339c4173feac97f7bbf2e26c9f878312ed94bd8 GIT binary patch literal 66082 zcmeIwS5S~g6o%ms`LHV}h=71Upx8hW1O>~lqFAtZ?7jEiP47ihO*e_r7)vyXn#A

(69jn@QC)Fe&T6iwAMP1g*~)GW=`9L?1{&DR1g)FLg`5-rs- zE!PUI)GDpk8m-kjt=9%saio)ip-v4lgCIx?b_F>>4HpJAUE8%B?IBJG5`*L*B}flq zgScR`($mUZ6pZ#*kMRU=QC*LBb#K*1Z_{=~c!%tr+NIsvqiWu(eX8ma-sJr{po1Fh z__Sd@q*0FYaF2A1>$$#T9p?s)cS9#Q(MfLPWT!aQjU716>CSKyH+80)xw%`orCT}6 z*>3GN&T(7kI?wH#?*g}X2N$}?9o@;D-Nm81x|_SZ*gf3SCGO?k?&H2LbwBs_01tG< zXNag0>8PsJs@JGlt9G5b(J}Sv$Hp~?Z{DSr!3X3{+>f9yl+O2zWkDevHdiUvD+OPkBfrADQ89HqEh>@epMvoagZv2Fa zlO|7@I&J!lnX_iknLBU(f`y9~FIl>5`HGdRRJHnm2 zcJB%I?kjKXKX9;oKU6V7LI8pPD{$ipC*E}TEjM3();Z^$8(w?r z;m4nT{^i%-e*fdozyAIwynW-zciwaBy?0%H<<(b(*Ije0&${8ZV?Dt<0tg_000Iag zfB*srAbNiRZ}8>00IagfB*srAbDuaBb4sWeds!LBYc!7-Q7sHAYEb?26muycXxwIcQ;5#C@Ci5jKI0T z87~}eeAc?y|M#6e``zm|D?Vppgb4q=iL#=HAVf5x6N8vM#^b~yHgSkcJmQmpgd`#{ zNk~dEl9Pgzq#`wGNJ~1>lYxu`M39NhWFafr$W9J&l8fBrA(Fi0BR>TwNFfSSgrXFq zI3*}aDW0G-W$yk_S;|qK3RL7tD)AIgQ<*AMr5e?#K}~8=n>y5`9`$KJLmJVTCN!lP z&1pePTG5&|JVRUB(Vh-;q!XR#LRY%cogVb$S$ff%=jcOU`q7^O3}g_48NyJ8F+CVg znqXuoLy#>9f{0*awERJ

G;UXaqw-@9-|Eg498}AbpT2NE##yjzr58(K=Kzs2du^ z&`|%-XvQ#>ag1jI6Pd(hrZAOhOlJl&nZ<18Fqe7EX8{XY#A24Plw~Yu1uI#_YSyrp zb*yIt8~K`V_?As)oEPH>V_oaPMQah7wO z=K|kzkxN|W3P128SGmS@Zg7)Z{KRd3<`;hDH-6_2?%cZzp=i-##C+`WSh3^8jTb*b z!bFLaBu$n)MaopE)1*z8K10SJB2(rpS+ix&kuz8BJdt_xNn1`ZlLWazN)@bH5*BK*#~52|o@R5(0(%-C_`Crq3)dCJsj z(`U?_HG9t7dGi-6T(o$}(q+q6tX#Ev&DwSAH*Ea+n{PL5-m-Pu_8mKS?cTF@-~Iy! z4;?;o^w{weCr_O|^WE8V=P!JJ@zUihKm2(0+VvYZZ~b)p=U;yP?e{>3vW6m^{__39zkV;h`T4!{ z$ezzXvPn?~eHyheE1-Y^3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7j zD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7> z3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36A zpnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim} i0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC38qgTSBEFu+Lw literal 0 HcmV?d00001 diff --git a/media/nls/c_1253.nls b/media/nls/c_1253.nls new file mode 100644 index 0000000000000000000000000000000000000000..40e21fc71e934c8113f16f33c98ee2211cf19a13 GIT binary patch literal 66082 zcmeIwS5Qz#6vpunk6p2X9lfApMX`(R+I#Q4_uhMni5esbhz(Iu1BeQuf{KdRdrM+^ zucr6jjgx2wA2Pm49{zhD_MF+B`Og04dg^v|54ra~Wm@JTc_^Dq*_A^%l}ovmM|qV` z`Q@nsDyTv#tRgBZFL|q&imQZ5s+3BrjC@p9<>bg$ek!jDswjU|Qe{<9RaH}U1*nE< zDp0jlTXj@d^;BOC)KEccq{eEZrfPO~qULI$mTINeYNNJlr}pZgj_Rb&>Y}ddrta#Y zp6aFE>Z88ur~VqCff}U28ls^Zrr{c)ks77Z8l$lqr}3JgiJGLznxd(irsqCX2Go7HwN>t8KFw+ip8-r`=Ml#aX=VvIN_0 zdu*>IT9WOvWZQ2C?4YGssvWY!cEr-`s2#K8mTo63!%o^MJ8fs|tevy-cEK*%CA(}_ z?5bU}>vqF#+MWCVf=4#Xo+D?j+wrbs`ZM*gzI(F*ZrE9nDJ$m-) z-KTHA{sRUM8a!m^u;C*{jv75??6~n0CQh0>W$Lu)GiJ`3J!kH``3n{7H+|V^);Sv9|Zj>ACZrv8MeTVDD#>MYS*u7_OV$!~3_rSrFRQK?aw7b{R-Hdye zAJ}d^&^@HN^N{l_IDR4vGKtJefkQi=c8?xA?w)W@o;rQz?78z7E?&BP~rq(FTD8D%dfop+Usw;`PSR-y!+n!AKd=%qmMuN^s~>u`0}f-zxnpN?|=C5r=NfM z^|#;u_%kb?K{f&iAbh`UHk5|WaP z@~g(yrB zic*Z?l;8nMQi{@)p)BQYoTxk%s7NI$Q-!KjqdGNskebxuA!<{Hy40gS4S1MGXhQ6JVq}b=Lve#hraZqKLZ%ZAOwco(W835|jCuPxzG2n8H*(XByL)!54hVOlC2gIm~4qUooErEMyUj z`I>K7!cvy;E#I-66|7_xt69TZ*0G)qWQ}ZO6Pww>R<^O79qeQmyV*l@q(x*e``FJ< z9N-{7bBMzn;TMi_jN_c(B&Wz0In5c)a*p#{;3Ai}%oVP3jY5%@k?S}Ag-D#Z@!}^) znCPy=Ns=Z@o+4$cyHlr0n=XBZjG6AqoF!|vAbXB`@5`C%{@i);=F1;dpkQ>N!bOS} zD_-J(lBG(QDO)ZqU!h{9%2ldXt6t;5nzbIPU8ion`VAg_q+z4RO`1O1ta*!;ty;Hf z+pc|wj-5Jp>DsM(kDib9di;srefsw6KVaaX!9#`)3x|g>YsAP=qhneaju{({`)K@x ziIXOO{K==EO_}=nwCOXx_;Ti~*>mR3`)dAzg^Lz{{mqi4%f9_?`HGdRR7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0{;(zsHpI*x1+-F)z_X1Uw`A7@VV#T zym9eo|GNB(H`B}S-%S76`^o=or`Q|48@relP(T3%6i`3`1r$&~0R5yk!6Y literal 0 HcmV?d00001 diff --git a/media/nls/c_1255.nls b/media/nls/c_1255.nls new file mode 100644 index 0000000000000000000000000000000000000000..2a4b615f9943507330368d691a14944384c7efc8 GIT binary patch literal 66082 zcmeIwWpEZ(6vpu<2?r+uf)ij9AZTz4wz#{yySq!Nmtv((af$~GB%vW_OIvEVB!S=o zYFJBKXd%-f^ks(640Qf?KkReP+?{*wZ#IJxQ+UaJ^vGlRcu8LJmXA`%lv1gbT4|J4 z>6Bg>GXzp^N+vMIZAD5r8Mw*r($d6iF&0u`kEDxiW2Rv{Hu5fxQ26<3H# zsH94%w92Tg%Bj36sG=$Y}ddrta#Yp6aFE>Z88ur~VqCff}U28ls^Zrr{c)ks77Z z8l$lqr}3JgiJGLznxd(irs)cEW+<04-z%>Z>^M%KbHKZlGgG0?EX~#&&DA{RaB?~U zP97)7@prN~@!mm!3sl)zs6|?=C0eRwTCNpZ=d9E!t=1Z?)k&>am^NsmHfgiAXsg1t zP1_ZrNJVLf?kZY46{B6+tEI@UA8Nh zXjko;UAKF>FJH&cd64`sczOGzu#~A%r%9VGeFk5@jF~d~XUUo^dybsBatGweo6iXh z%3q*haG}CQiWVy#Qlez3(q+n)D_@~vrO?V%s#dG+)~H#lcAdKQ>NjZEsBx2~&6>Ap z*{XG$w(Z(?=-8=qm#*Eq_vqQHcb~rf`VSa5Xz-As!-kI-IcoHnvE#;1m^f+jl&RCE zyEEKJYo|xQJsletf97n0XVW8pmXz<^cijgbz2_vp@|?`^B8~CpQ-}TNsa=`~ zyto2;_U_yN`4n{U7S{)a<{j~w;9&AIazE?&BPCGqOD>p%YV^Dn>NxOwaL zo!@@H`^TSu{k!eh@e?Ocd451f009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5cnSp z{QXZzi2K2ZA+Gz*{FmK#-+R@4{f+mN?)%!~JHM5j-u@&xJ)`%h?n}?;q$iL0_{owA z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ W0R#|0009ILKmY**5J2Fm0uKQ%y}uv; literal 0 HcmV?d00001 diff --git a/media/nls/c_1256.nls b/media/nls/c_1256.nls new file mode 100644 index 0000000000000000000000000000000000000000..858a72fe796db391bc3d19df85a3703ff43b314d GIT binary patch literal 66082 zcmeIwXLL_@9LMp`KjCX7VoL~af)El(h>;jKMutR)*n982#fVPTUAlCuo!WbAb?9C? zbXRp)Egf1_+DhybS2k*^AquSt)9*RHdnn($!Y& zl%e*@R0nlbCv{dAbyYWYR}b}6FZEU*^;JLh*8mOFAPv?K4b?CW*9eW&D2>(_jnz1f z*91+}Bu&;7O;whrX}V@;rm{6lE1hhs;LP(>cETLT332xNL_1j)=VW?j+kBg2Yb?+S za)O;oPN-AbDdXf=XvkcPcRG0d9DirKEs&or)FLg`5-rs-Emw|q+X}7JDy`NUt<^fM z*9L9WCT-RhZPhkav>n>1UD~ZGw#Py&)T&xFt8QUd!)jW%)w0?aVUbqHqAc2Ctgh9w zSgUUhY`+>>Ba5?mOR(nF!dlt^wX%asv?NQm6g#BDI-;XGrq-5f$8|z!*2dDUt({am z%dk^wZ>N=MXLMG@od9Q_UHln5KE4GCTA{*4iWc+pFCI{$WU10+%9bl17*wHRaHYys zoRH9})vAZps2N_Xc0^>IsOXrw^t z_WK`~?{cN;j=X^zFOJ^r-s_$B=!I~PxAwm0pAYwWOV@oWH$LOK&;8qTA^rW|4r&At zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I`W`3Ow=TpMOP0x(_`Z>AG|0-Q?c?z%B0V z+aApIxb+{C+r8<|$Gqvfy>GZ~CtZ5bBbOFr1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL yKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmdU&2%G~(2%)6_ literal 0 HcmV?d00001 diff --git a/media/nls/c_1257.nls b/media/nls/c_1257.nls new file mode 100644 index 0000000000000000000000000000000000000000..90db301f9d11787e9cc8cef03fb5fd1704b7a552 GIT binary patch literal 66082 zcmeIwXK+zYNq_(e37yb4E%e?AHS}IWCj>++h^W{RQF@cmyA&Hm z?20r&u>gu)k)mR`HxMT?jK7@WkMFv3_WJhP_s+TJnG>u_fhKqBqb!xpBvXL0DNsSm zt{lp#T*|FH%Bx`IQ+^dtL4_z(g;ZEYR8(OKS1}b=2}P)+O372CqEuRCR94X{r}Cnp7R|~aNE45Y| zwN*Q{R|j=eCv{dAbyYWYR}b}6l6tAP`lzq^slSpnKm#>MgEd4$HB7@bLL)Uwqcuij zHBRG|q6wO)Nt&!FnyP7(tHGD_tA3QHQlz zTeMZ%v|T&2Q@eCsd(_?bYM=J&fG#S~;!T#_4(gD?EX4BKQBAWV7G*Up#_C#sYhsCZ zOl|DAPUxgktdS+z2s^7(OS5wdvPx!_!_Mo1!Y$N-?UJTjQ7df;7Hjn^*_v82yR5c$ zMOSrA6RffIvXOQ}Gi;`v4!HF)SU|SGpzJwv=E|KXZ*ac+1qz0Q7Ajn%Xjpi$;w2(V zmhvK_N|z}cU9NnEnAnPO@s%o9samaijhYFyYS*b-uYLp9uuo#rM zweQfeQ|B&SyLIo;GpSeaK7IT3PaZIE(BL6MhYcSwa@6QCW5b#8t7hK;tk*R z>gUeA{ON07_)lK{%D*1@(z!RkIegKd{q@$jH~Tx^JNL?GH}l)y`TDy*_&2A2egCHq ze$E(w_)A9fEib(2+(*Cpcklg}IXmwCw)(U?>_<$WTpq7%}jT!-*w0Cl=Vi>WZjSvKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R;X<;BS43 Bq?Z5y literal 0 HcmV?d00001 diff --git a/media/nls/c_1258.nls b/media/nls/c_1258.nls new file mode 100644 index 0000000000000000000000000000000000000000..93d9e7556514643d53b3f6a39ace6757706b6629 GIT binary patch literal 66082 zcmeIwXHXVr6o%nv`LLj(AgF+#3n*3;yI^_ky@I{>-YfQ)9urGUH_?DyLBZZ@6kF67 zjg`a_D@Kjc*b{XUarkD)OeQ~^$;|!kk3G-X-8pBjS$CzlS~4##r8y2uvg9I%T$Mo? zl}VZ9rYy>;Y;sq2<&cLwl~Z2wRxagM9{I>ue#$F<1t_2L%T}O*6s!U&s1OxWVHHtP z6;pAAs)R}^Or=y>WmHz>R9+QSQQ?YEB~?}xReiouHC0y))l@CjRvpz|^Ms3wj?bSgY)k&SzMP1cR-PJ=q)l0qAM}5^#{WU-XHAsUs zL_;-9!!<%9HA1)ny5*Nw?sPjBdw{Lrs9_`gW?biXxaZrbJSRU39xjByN zm}0EsI-!#~rPDg2WF=S*$61}zd0mjhx~NOKtSh>zYf8~|S&kdJsax{2ZY$VvM|Tx# z-P3(N&_g}aV?9x#6=y$9{TD13hiit6nKHX&$(qeQdkzoJoL=6!a_8~!^~>uYkT1U- z7!+KfU`V0DMT!-Fx)x)w@sMe*Fgw95i^y&|$+zj2tyOdd%2y<0nj< zWG0&zXNoaXr%j)c8qF+YX3sG(v2*9mU$Ah|;w4Mt;+HK?NL;aU)#^2C*R9{Mant54 zTeofBvD56@owR4~zWoQx!9$155p(pIIey~gsnchYjX8Vn`~`FI(&Z~xuccf!H*VfC zx6Pfq=HC4W4<9{#V$4%xzWMp($mhj(zot$9rT*ZnfAiJX|M=1yPEUUL-6{U~hf^f{ zE%0u-5TB>pb#8w9i}~rV&iBs!H0ifAH6;QFAb^Xbi``&r)Z#G)%@}m?f|7f487$rrif-1^XNtIPa zRaH&ZRYNruty-$B7}Zf-)l;nMtAQFSPVq`mBPA+HjnzcSN>NCuN|URpnyI;3sHIvd zU14P?Q?1oTS!%0nwNra_P)BuAjyfw>UDP!=Q8#s05A{?p^;RGCRi65(zXoWa25GQ{ zXsGfvOv5!oBQ;8+HAZ7KPUBUe37V)$DpZjsYl@0hqNyrXnWkyFW@x5nX}0EQuI6dJ z7HFXsX|a}Qsg`NER%oSGX|>i!Ucqa6jK_MMCwiKvd$#BLT3_!Qe4}sj&A!FAdUEPE zj}Ik;@IGl3w(l4^hsXmMIL37 zeTo-*iBI)XFY{?W-Dmhr->$*d+S*tj%eHpb%i3CR>u8-U$2wcCb+N7%u_4yYx?2zH zY3(h`2HF7YV0kvk`dMG=Zy6S2b*!nyT765idgc~q@s?nXEYXszu{E(wOSTjXS*kU# zx|VLOtf4ixu(hye*3!!V3{e#-TBXWWs#dFBqh@ri+A($N){Cv*pkZ8mLZif_#!Zq_ zLaAxqv{~~OEnB6BGcsGZ$!eS3u6>7&opL(ocIg`F*1bp1UcLMD&Fj~Hz`#L+hYZah zHhjd$QKQF<9XGyU!o*31MU$r#mrN}!n>KyM%vrPN%$+xX!NNt0mn>bje8tLDtJg&S zqE7#F{q|r8M^)xxQRf`QUbZ6e-x0WG|5thQt=;dx^X_*)e)!SHpM3h+ z=U;sF^*7(X_rcr0{`AXlKYai58(-de*Yo$^bMJF6J^0YWk39O=<4-*G^fS-i_rTq+ zz5MFyFTU`~9ZyEi-~W01LI42-5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~fqzaQ z9FBy8Q2%#>0Y|u9bIWEZYK~C7Tc}vjt)`@#31_Tg5009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ p1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILK;YjY@H^)%kxl>r literal 0 HcmV?d00001 diff --git a/media/nls/c_28591.nls b/media/nls/c_28591.nls new file mode 100644 index 0000000000000000000000000000000000000000..995fdba84337fd5dfe20ef2a4704fc3b142a640c GIT binary patch literal 66082 zcmeIwL(muo5J2G<+qRuQNn_i#oi?^@+qP}nZfrYgW2cRpLp#%JubuaH_P+DYhGR{e zK;-*-_*X#!K_CJXgrEc?I3Wm0C_)p4u!JK#5r{}6A`^wEL?b#eh)FDB6Nk9OBR&a8 zNFoxGgrp=RIVngfj^km>CGLnhRWFafr$W9J&l8fBrA@7fi@>76<6rwOi zC`vJkQ-YF|qBLbFOF7C@fr?b3GF7NbHL6pCn$)5;b*M`{>eGORG~#D|p)pNpN;8_% zf|j(RHEn21JKEEMj&!0kUFb?Ty3>Q6^rAO?=u1EPGk}2%VlYD($}omAf{~13G-DXc zIL0%9iA-WLQ<%y$rZa|!^2*vmflbAW>!;xI=z$}x^}f|LBpDNb{Svz+5R7r4kJE^~#eT;n=7 zxXCSUbBDX!<30~~$Ri%}gx~m`r#$01FL=o-Uh{^xyyHC|_{b;z;7>mDg|B?$`#--B zC~%OV!Gebf87g#`u;Ic-h!`nyl&I07$A}p#cAU8J;wMO$C~=ac$&#l?nJRUfv;pbT zXZR^&rp#HgX3L%ej2@pkbq*e`(yLX|v`nTDEH4rfs|S9XfXE+@))`?mc?;>fNVrzy1RT4jMdU=&<1< zMvfXiX6(4}6DCfYJZ0*%=`&`|nmuRky!i_jE?T@~>9XZ3R<2sTX6?H58#Zp*yk+aQ z?K^hv+P!D*zWoOd9y)yF=&|D`PX2o8^qI5g&R@8A>GGAU*RJ2VdF%F_yZ7!tc=+h? zliz-S`t13Om#<#GdHe4DhmW8B`1A9Zuiw7sGX)e-Kmi35P(T3%6i`3`1r$&~0R7>3Mim}0tzUgfC36Apnw7j zD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7> z3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36A zpnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim} u0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3MlZO1pWdz7sZ4C literal 0 HcmV?d00001 diff --git a/media/nls/c_28592.nls b/media/nls/c_28592.nls new file mode 100644 index 0000000000000000000000000000000000000000..78e32e14ca501d6df7e80373b13e0f22ed1b2c87 GIT binary patch literal 66082 zcmeIwb&ytN6vy%3c^8&ky1RSnu0waTH0;6#4NJq)-Q5i;3I>XbiYK8+ji|xZ;P~8OR$}qWD{(clG~X;1KX{-*24}2 z_Nb3VS)7fxbAib=(IRZG_9x8=6 zP&=(*c2?&UZRgd=F6g2{?2>9)3cIW@yP}+SRk`h&t}DG|v_{s(y`2uu^Bnv2lI-^&c>B(BL6M=)CF=NLijGr)Z(&Q;qr%j(R zbJpxRbLY)puyE1hB}NRWEt>3V5)8;K(-F=(;_8p1Yce?LNOuG}uo?su0 zz59H>`vE`bhy3u7;L6cse*A>{X+L|;&-;aoe#!l^U-7Gc?Rs$k#!bI<+x?E;y%%iX z{pykD-~T39eemtaKYa3IuyX(KyN|yAtNMrey|3LLf64u^7eD>U{j;Bwj(z@%`#WE{ zpZxWSm))Ow?a5ca_~Yr%j*3zX`nZ@byRU`wRZ&!>jZN zAbDuedFhhw?tBrX5qaqD?p8uNr8|}GMghS9Nx=Xml#)i2FbE};6eSGU zV8btNZhmpQ?z6LV{%2?R&VD=bSlcZid^~unq682SK@_4Ajp)Q6Cb5W39O4p>XNXS% z5|W6-Bq1ruNKOh;l8V%%AuZ`hPX;oQiOggnE7{0S4sw!<+~gsWygW-j^79-8C`cg+ zQ-q=vqd3n~f)^eQenwWv)U>QayTG@v1kXiO8D z(v0S`pe3znO&i+Mju&}}_H>{lop_nfbfGKV=uQuM(u>~op)dV-h5ig+AcGjp5QZ|0 z;f!D;qZrK?#xjoaOyE^sV?C#& zGuXv$_OO?Ie8GMWaF9bB<_JeQMuy-xUy&v_!AVYWn$AJ9;5)wO3}-pVdEx}If(u;a z5|_EcRes`Uu5q0k+~gLw$r#+>SJDP|xyOAT&?RUdoQQb*8G?u?QKLnV5i?foIC0}W z6F))1M2V9mO_n@G%2cV-q)nGTL&i**vt-SdJx9)5x${KkeKueI=L!@oRJcgdV#S{? z@j}V4ROvEh%ayNCu~OwKRjXC6QL|R{2Jc9cmKho z9*^tuA3yuy$^Oau^>6Qd^yM#M_~!esuYGd%)(2tu?#EBkKd;~Z@%D#L-}vVDr&IXe zCx45E|5D(MKmW^a_EJCr1r$&~0R7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim} z0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7j zD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7> z3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36A cpnw7jD4>7>3Mim}0tzUgfC36A@UH~^0)64O;Q#;t literal 0 HcmV?d00001 diff --git a/media/nls/c_28594.nls b/media/nls/c_28594.nls new file mode 100644 index 0000000000000000000000000000000000000000..b49147815f4c60d5474200adc4b01bf76430c2f6 GIT binary patch literal 66082 zcmeIwXK+_V9EIWY3kfxWP!oEGBoI1Ds7noy(0eDeB-B9YCG_5VZz>8F1Q8XxbP>Tu z4~kSp1RG62@gG7QXZYm!(Rc6c?Afz>XYM?6{j@W|F9P5#QR9LlL&%B?&KP@wWEpYp4K3aXF_tB8uKn2M`}N~)AfD@ef#Q5lt0 zsLH9lDyX6=sj{l5s=^em2vt*c)lf~Y}ddrta#Y81+;y^;RGCRjlF^uYT&U0UD@58mt5j(NHC7 zn1*YFMrxEsYmCNfoW?6j6EsniG+9$LRns(GGc;4PG+T2tSMxMq3$##+v{*~DRLitn zE3{Ipv|4MlR_nB08?;fIbje8tLDtJkbuw|>LMP0qQ^&TZN1S=~0beTQe+<(a!v_9)bQ1J+9ry-#hpD&o8~>+^0W&@?h|AeV5vP_1m+~z3^t* zl`nqrr1wAk^4GNDx!2Rui*Ki-SKj;jk8l1=?aut3cIICF;O|KIPXcc}_4XsT^Qn#k z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5cnSngoe6M&txEg00IagfB*sr zAbq^mpt literal 0 HcmV?d00001 diff --git a/media/nls/c_28595.nls b/media/nls/c_28595.nls new file mode 100644 index 0000000000000000000000000000000000000000..49fe3a4aa964a1cfee1f42d030be4fd835a71f90 GIT binary patch literal 66082 zcmeIwRZtgL6vy!&aOh5HM37QYP)dY9B_JpY0-`9`-QC^YU7K#X<#u;>cXxO1x{m9^ zzV421et&oFnK>_a&iTys)yb(&a-2Q-S6rMVCppVSCRe%1T^{n3m%Qa8U-`*j0SZ)* zf)%1rg{hsw6`@E)DOxd#Rh-%@ULBO6M0He>l9i%VrKyuTD_t4tqOQtRmb$6CvX!G; zltyce#%i3#Yl0?fk|t}4rfQm|YldcOmS$^?=4zhiYk?MOkrr!- zmTH-nYlT*7l~!ww)@q&BYlAjwlQwIMwrZQUYln7fmv(E9_G+K@>wpgGkPhpJj_R14 z%-LMb%+=h?-8{_Gyv*Bt?1cQx-vTVqf-KlVEY!lRorPP3MOu_aTa3k8oVB-j>tG3% zXdNxdk}btjEzLSvXG^yX>tbCk)3U6ab+>HGv0TfueCuHa*3$~D$Q)K|C01%>R&Kql z!YZxGdRw*CSRd&MxNa=I-I? z42Z1RLA7b7Jenwr$&1W7{?xJ5AEmwj0%U>}ERcOf!>S^r{zqzn#7K z_utvseP$DIct8YEe-8eZ=n)V>G@=uOm;_=Gn>fTJ9`Q*)LK2afBqSvn$w@&^$tANh%-00k*TVTw?cViczYB`HN|%21Yal&8Xj z8&#wdm8n8is!^R9)T9=*sY6}rQJ)4hq!Ep2LQ|U2oEEgC6|HGQTiVf{4s@gwo#{eX zy3w5;^rRQP=|f-o(VqbfWDtWH!cc}WoDqy<6r&l#SjI7)2~6ZMCNY^QOl2C=nZZnE zF`GHeWghccz(N+Wm?bP_8OvG0N>;I&HLPVF>)F6YHnEv4Y-JnU*}+bBv77i|4}00i zehzSuLmcJ^M>)oEPH>WR;S{GiL#A++EFo*i7P5yNA!o=Ha)&%2Z^#$&hsaPM6bywz z;ZP(L4aGw7P$HBJr9$aYCY<9u7r4kJDuzm-a;OrjhH9aDs1a(0TA_BR6Y7R~p?+u( z8iq!pak$JCu5yj*+~6j+xXm5za*z9e{e_5V(PP96v0}%G8!vu>gozR-Nt!Hqij=8R zr%9VGeTIygGH1z}EqjifxpL>pn=gN4fr5n!7b#k-c!`pwN|z~Hu6%{4ij^u?samai zjheM;*Qr~teuIXM8aHX$ta*!;ty;Hf+pc|wj-5Jp>DsM(kDk4H_vzcO|A2vm1`ioJ zZ1{+gqehPzJ8t}hiH}X1JZ0*%=`&`|nmuRky!i_jE?T@~>9XZ3R<2sTX6?H58#Zp* zyk+aQ?K^hv+8woL@4o#94jwvuECr(D4I(;VUY}7yI-1!R^FFm4r`O4L6*Kgds zb^FfUd-osFcS!*S6!_l>JpS;DpLkF{8THiD&pi9w^Dn&k(#x;B`r7Mny!qDK@4Wlo z`yYJx(Z_%6{^ZloKL6s&ufG1~+wZ>r;m4nT{^i%-9zMlN0RVPid@zjy3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7> z3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36A zpnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim} z0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7j uD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36ApnwAZO5k^D7pSQK literal 0 HcmV?d00001 diff --git a/media/nls/c_28597.nls b/media/nls/c_28597.nls new file mode 100644 index 0000000000000000000000000000000000000000..54aef1ae19b35b25fc5ae092b4bcec0c695c269f GIT binary patch literal 66082 zcmeIwRcw%15QgEe3=YK$Em~ZQyZyMkySo*4hZe89vlOUPD5XGg_uXaP-Q9hm7rV(O zBwUgudFSNJ#mvR|^5nQG+uKFXKS%#5bCFz>Pp14Tpn@u-!YZPoDyHIcRSA_;DV0_k zl~p;psk|!4T^_2aN~)|Xs;X-8RCU!*P1RCu)lps5Q++j1Lp73@8moz#s+pRrg<7hW zTC0uPs-4=agF32{I_D+oqOR(u?&_hQ>ZRW5qrU2={u-cx8l=G*qM;h5;ToZl8l}-1 zqp=#N@tUBCnxx5^qN$pu>6)RLnx)yAqq&-=`C6cbS|o2R))Fn%GA-8%t<);5)*7wV zI<40RZPX@h))sBmHf@)We6>S6wM)CTM|-tTe)3m<0u`iSg(y^E3Ri?86{Tp!C{}Tb zSAyI_&5JTrAv$CRb*=3~B=qn)EI@UA8NB)vnofyJ0u&mff~HcGvFNgMa^mOFqkA zpkSfGMT!=Ro4YLx+=+Q&Q8?Gn~w$$Fdy9$;rF9&e^>FNZo&A@|eMc z$Lv@k@I(ZTXPQT^ztjOzV`YX zZ@%^RJMX^t{s$j^^zkR3e)jnnUw-xVH{X8u{SQC>^z$#j{`UJHfByCN6UoaX2q1s} z0tg_000IagfB*srAbIi3E{|OcdTA;7y_ujp)SSEn*Uj*u)_&@rX|X z5|W6-Bq1ruNKOh;@;0e>hcHr;hIdIzI?|JYjASA+S;$H_*~m@~a*~VO7CMr$|N>Yl_l%Xu;C{G0{Qi;k`p(@p=P7P{Oi`vwoF7>ES0~+!k@6(9J zd_WVL(v0S`pe3#Nkk+)JE$wJe2RhP;&UB$G-RMpadeV#Dd_*5UrZ4^I&j1E8h))>I z5QZ|0;f!D;qZrK?#xjoaOkg6D_>{>^VJg#@&J1QUi`mR!F7uer0v57}#Vlbd%UI3| zF0qnTtY!^sS;u-du#rt{W(!-{#&({ugPrVRH+%S;FWAdI_H%%P9O5uXILa}ObApqc z;xuPC%Q?<-fr}BHFLQ;fT;n=7xJi<*)4`eGY;Z0(A6y772A6`%!Ij`@a4onV+z4(4 zw}RWjo#1Y8FSs8(2p$HHg2%y=;A!xj7sL*W6ZZ0-U5FGp${WF(QKLnV@m9=OvE#&z z7e7J5M2V9mO_n@G%C}R!6P7y7yJ^#<&yX=w<}6vmvt`ebGgt0BdGqBjP_R(pB1MaZ zikB!^s&tvM<;qv6SgCTAs@1C3s9CFaox1hvH)#0Y`;8iZ(4=Xz<}F&b`mlAIw(Z(? z=-8=qm#*Eq_vqQH_eXs`?%S{bfPsTP89Zd@u;C*{jv75??6~n0CQkZv@|3C5rq7r; zYxbPE^X4yDxM=Z`rOTGD2(4VTdd=E(>o;uNw0X42dqd~g68-Arx>I0;^LApB)x>LHlyIUG0q)X{k8YBeiRAiwu4hv>n zxVxWs&f=VB^UgIV3LDx52>w0%E1?4rAQYhqLs-HQo(M!F5+4znC`2V1(TPD!ViB7- z#3df_NkBppk(eYTB^k*{K}u4Qnlz*(9qGwHMlz9^5I*J;vXGT*WG4qX$wh8Hz`KnKQi#HQP7#VyjN+7_B&8@#8OlHNAm8eV=s#1;W)ZhzhQj6Nup)U2P zPXij#h{iObDa~k33tG~O*0iB5?PyO2zT_*u<{LWFiOzJPE8XZ$4|>vz-t?g_{pimC z1~Q0m8O#udGK}GjU?ig$%^1cqj`2)jB9oZR6s9tb>C9jzvzW~s<}#1@EMOsvSj-ZZ zvW(@dU?r|iIm_<`N*VK4jG&jAi{h{GJ=C_j=k zaE#-e;3TIw%^A*ej`LjLB3S};1DCkW6|QoP>)hZbxA>LY+~F?w_>KEKAX(rck9f=z zp7M<6yx=9Tc+DHK2I>Xg{___Cp+biV8!mi=h><>u93^VB=rLl(iXA6zy!Z(cCQ6(n zX|m)gQl?6sCT+U(88T+d9P;reS+Zu!o+D?j+@F4yCvU#|1%d?&75=o#rMweRrdS6_eAu~X+R zUAuMf(X&_YK7IT3A24vxw}Xca9X5Q#$Wf!mj2$CNPmCOlAsGnZ`@ZU?#Je zO(GIAj})ZiKyWZP6dVqY1V@8o!SUcku#j97BO5vCOBPNBr-IYLnc!@2E;t`t2rdTc z$wUsa^E#^uCpVXZ%fXf4YH%&M9^43S21|LB%)H4Pp^e|>R?wYySirly$NMBr*PPeL zNC~o1oD8A)ThNkLw5APhX-9iHu!`-W`JXzhV=W!&L}$9tmA69Oy3zgL`RA}TH2-2Y z(LdC^M`ZV&^rAN_LmgK05g&(cGZwLgEv#S}o7urmcF~xotYJADIZhu+Qi{@)p)BPn zPX#K5DtEJoz3gK@{isA`s!)|`RHp_tsl_%76<6rwOiD9Q#N@`%SgVg7%AAuLMN!r{4cCkZmgj1@ah+<5U5BrH}u zUzTLaBeJGSohEIGMg#gZ?p&i^)uv6Vb!uL@#g9Mz{L8Pu{r=#OKYKT;(!Xm&-_O7J z@~f}E`S!c-4<0&vECr)0veC6u3>o;zGa$)=0F1-c~9x`;;@DU?NO`J4&%G7Do zXUtr|?eE8_`lgQMdfC37<_yQ$Ml`d1ZT=@zWYu2h=r*6Ia4H~v= z)w)gFcI`WKd-0cZ0|gXNKmi35P(T3%6i`3`1r$&~0R7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36A zpnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim} z0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7j zD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUg zfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7>3Mim}0tzUgfC36Apnw7jD4>7> a3Mim}0tzUgfC36Apnw7jD4@XqTHqfL&AtHu literal 0 HcmV?d00001 diff --git a/media/nls/c_437.nls b/media/nls/c_437.nls new file mode 100644 index 0000000000000000000000000000000000000000..667975b909370ff01e12fc5852124b2710732e98 GIT binary patch literal 66594 zcmeIycW_iy6vy#j^5{iE?~vVaml}E}aOu7GPC^n&Lhl_^R8&+*K(SM#qXH68il77# zv0*__lp?)K5u_--)eK=69QngxK)-kA+;jH4JMZ58yf>Rs2>}7JNgv%ZoIoi+fpU~W zDV0j8l}2fmPU)3F8TF7dDM*=>MOl?i*_A^%l}ovmM|qV``Bgv#6)cau3Q-{$`BYd% zR8+-OTqP8$k}9RrDxQP)kuxi zL`~I9&DBCJ)k>|^Ms3wj?bSgY)k&SzMP1cR-PJ?kicn8QDoWAnrQYhJzKT(-`l-JL zXrKmZu!d-;hH1D)XrxAIw8m(x#%a7JXri|1x{m9h4r#v*>!?oXq>kyV&ghg9wME-? zL|b)Hmvmm&bVWC`OM5j}^E6)zgX01Y=(H~As?KSrmT0XuDkx-`HfX)(XsOm|x`{LK zCeRcz5vHeUZ`zqi)5>%(-Aq^0#RQpbro1U(@)?;h)7|tiolRTQ*Yq;srlsj;dYe8b z%0!z^rlV-sQ^eU86kSiNPy1+su~x@Kx1U%@^(K<%{%%`@F%s%?`82 z)b`c%#rR@?K?IL|asLGKLDO0(WP*l$2!$p8Kg@c$nK z1Ue~Frb?YAZMyUsGCq_kD07yq*|O)znJagmy!rAMC>ZSVh7>Zs!bOS}D_$bBWU10+ z%9bl%p<<=VRjO7Ct6sy_tW~>C-Fo#KG;GwkNz-P{TeNJ|x=q`5?K^br)VWL7Zryu? zNA!%0itg3BPv4l>e*Fgw95i^y&|$+zj2tz3%-C_`Crq^eFmAm0@+~0#cE%<9!o24nwszK^3-7Dx_512H9Oj-29Q5yaJbBwg)*iF=L{ekFwI|Oc zU;N41!$4L6v$Yq_|J}v=ufO=VBVGLEwgzAS zQv!+hotwYsJGa{C#wIuRxUty{|5)``vL7bp50dhhq57U+(z)i;s7I``N7vlj?nL-s{HqZv5cJkIPrAbkoi8`^}010R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL IcrXP10PL?i2mk;8 literal 0 HcmV?d00001 diff --git a/media/nls/c_500.nls b/media/nls/c_500.nls new file mode 100644 index 0000000000000000000000000000000000000000..6edc46899f172fed40440d57a60eab40fd1b694d GIT binary patch literal 66082 zcmeIwQ?nQb5J2H`*U zM&MOI06~8b|0;L@1Q3kiOeHKs=*L7xGluU7PXr#y#uA?d zBqS02`H=w(WDwzqMLdQvoDqy<6d?&kXvXmqG5LjG8P5blFp0_h#uTCxgXzR2F@JD_ zTU_HhH@VGSo>Q9)HqA^WqN;8_%f|e{|6VLd} z7gn&GR((jP zx@wXV0C#ar4&gJ9qEh zFMX|6{kA=R958Uu;2}eY4gcxqUw$1wVdA98GiS}7Gk4zn1=}|rn-My3lBCI!#|RZG zb(*y4(uWNfFH`2YS+ix&5hhpeJb6PzFYvX{!sRP|U)gHSmes$F*m!W+=5b>meAxQO z+EvpoOc}Xu{f0$Nnl@_IxcT%JojY{w)V)jBZi`z!e)90?qiy{^fBE=n$Z3{>IeO^N!`ItizH;%>=rLD=OaTQHP(T3%6i`3`1r$&~0R+-w>1S6P(T3%6i`3`1r$&~0Rw^-h+K;a3}C^cXt92B)B`Yr4%RylHeMOI|O%kskcz4?%q;w zAJYtzzv#dWbeMk6oipdm?%lh0K6mG4(9NJ^@+V$O5*8#SQ;RtHLTGC!dO{n2M`}N~)AXR9aZb1Mp`PlcF!fd+g)2glic(+oQ-2Lmv<7OB25X3hYM6#=ghpzV zMr(}5YMjPvf+lK`CTogfEY{*|zAdnYw#XLS5?gA^Y`LwlmA1;_ZMChjwYJXI+XmZc zn{1aQ*lycndu^ZXw*z+24%uNlVn^+m9k&y9(oWkcJ7Z_*g}M?5?6K5cGi zwk>u`jlDaS$Gcy7y;Fh{6z}2{`1q>stKp0EMft*gVLos0b$8j_aCLpPeFJ>azEIyG zcg8L7ga+@^25og4Ju#j*PpoI2r;vBPC&3+YkM;=&D*V4c0k{7L$$~6-ij=8Rr%9VG zeTIygGH1z}EqjifxpL>pn=gNXf`x)T-oizkuV}I2B}$eGDP5*)x$+e%R;pa3YPIS$ zLTlFY*RE5yUi}6Q8#Qjyv{~~OEnBs2)3#mv4jnsn?$Whe_Z~fah4t|CjhH>3oRa|MRzh+#dNg>F|B@Ki$U~mLTwe z1U~bB{>7L6ul!$s~oI-zx;Mj3vS)z?(e_5%Oq0> z{D%T({JZb${(7K09>^1cyb;LLfxI1i{we-biS=Y+J)2mQmaB(edG+Ff{fA$E>B6z2 zN6wwUvUlIX7hb&l-1C>NzjiI@jfwp`f%;}3-w5PefqZ-Cu7p6j6Mx?6Xb?aE0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 J0D(tC;BS&qFUtS` literal 0 HcmV?d00001 diff --git a/media/nls/c_775.nls b/media/nls/c_775.nls new file mode 100644 index 0000000000000000000000000000000000000000..9b8876833d3229778e45a544acfdbe0f7a4e35ca GIT binary patch literal 66594 zcmeIyXK+8u6Cjj?UJ?k9o3NJ}dQV^>^xg@C76=4L=)HrAii%3L7X+k8ks=_~ z1}I`jnxa?$#jZ$Ev7DQP4Bwn__>%Fzci!{7yL->hncqEg!xR#1s}Baf(+HHT9mTnVKs>E!0x2)LL!SR_)YY z9n?{s)LC8BRo&EGJ=9aZ)LV(_qrOT~KlRrD4b&hdYp{kWMME`AsT!^k8mTm;Ym`Q7 zjK*r5#%qEmYLX^vil%CsrfY^~YL;eej^-+lxvq;c=A2^8d4-q+Q_S=>iKeQVZVu{@ zj_868tCP8+XtPpDrk^>XGrFc#I;E3Z?eSGHmo(GNGBZrss5M%z&DyB_+Nb7bgZ65% zU1FEoAX~xaGNC5ilr$-}n@zL>Y;}`t3ftnguB~Pxt!%uVVA4#I?P*8aRGVzO+EI44 z$!)?+gehfen89YENjGy$xDB-n?0mb>F0%9NF`ZRM)52WVaqUn`Q{OZ&aVFlhHbqS< z6A`sZTNN2~Ks&WoS5+=*iz1?TX}7j(n^xEr@_u|Z_Q&~$`BVKV{$zi2)G2$^p0)}8 zX8tsPx>aOqehPzJ8t}hiIXNznL2IyjG41$&zbA~W&G_Pdg5uf_Oe^&Hb3{%dUx&T zKd-wBzy9w2aL;eta4F;N2OeDF+@kD*K6B?EednAv}Q(aUeX4NNvI z`0}eCzROttVrfQrmwWGX?%_uQvjfL(ti66RvpakuBkzB9)#`Uo-Pj}%KmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#}Zr2?_BF4imOesu1aHCJ!x*&LRG1b)jw z&&s1B@E-*Zy6xF_e&ls8dG)ear@ea3tH5|6Gu*3L`ASwE%F3JL?LE#Nac-}3Z#cKl zxwo9#?c7o4-gNGro4=UVpY`&LS08)ziC3R)*}Bb(?D1E2M}q(Y2q1s}0tg_000Iag zfB*srAb>@K^@Is{l3+}+*XodkDxclcAA z-AWY~+;BtX?Wt4eboW%x^fO(PRCT>PWTP*|XkMO@hdkw_IEt%yimwDps6g>G)k*SdUCM9J<=0B&`UknTOHFW zJ=0`G=(xf?&g-@w>V@v>pk`^6)@z>TXsy<0qGoHg#+Yz3)_9uiW}`M~gJvq!1e->t zg_)$ON@3ENA||i#HZpaQ?e*&WZ2OgeYapJ~{pCDnP#7UASOP(TSs?=%Hrc0k8W2VgB zS+e^0y8Np>z^-wfr5n!7b#k-c!`n$r2bLp>5lRweQfeQ|B&SyLIo;vsdpvef#wvFmTY| zAw!1^w;yP4=dS&8|GLwUpRbrUZ`Qq;cb?sU{p#+OM=zefoIZcf?1wX!FI~3%$DhJS z92tG+@R?)BBMwfzc<#dG-~RsV=JgxD-@bPK%L!j>8~N3kufP3#)Hgp&{QkQGQ^rpk zduiO0KYp3~^JllN{`!H(zdwES{h^OL^3TUzj@1xA009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Y)ItzrXc&$Aeh8c{Ysz0Z+lds-@bhqq?f6`ifEmMXRA2g+EbaHBnPFQ**UYOSMvKwNYEO zQ+st#M|Dz+V%1q)6sNB0rta#Yo{Cp5^;RGCRX-)DzXm8#1C^v?4bor@(NGQ3aE;JN zjnZh1(O8YscumkmP10md(Ns;-bj{FA&C)hq)+rs=35{|Y-AOfdrxoL3-C0d>Tb03W zSA7@d&g+62x<)SE^>TZ4SOZ;>YvT4PyE~>cI;TrY=hC|wZl){b3cHn>>aw|hZiO~# zzF*)M`hYL%H*1TExV|pY$NKKRkDunIyIek>ujMQIVqQMl2V8`U_i=uRPxc8u#t-*P zmD}ZVIouBAbgkS@?NU)!$Y=9&{Tx5QjdZj9ZXMMgHFM2fYnR~qyEu1HUEOGRMMsqA z)@qfG1P%qZ1@;G)>7v$awU+BZV2tbGdb%ZkiNZg=qCyQqNulIWVkjY0y3~HZ!yoWX zLybd2L&HMRp$&ekUmT1swNA^l(k~Cr4=xNY2+j+ZEWIeW#&7aB_7e~&bJIToDgOs9 z5Roo@hK!jqXUUo^dybsBa_7mLFMol8g$frbTC8}9lBI&B%arw@a^)*jtW-I&O4VxB zYt*b&yH4GD^`ja@H*92$n>20KyhY1at=qJ1*S ze?a2Eq~t+^hYTGye8k96qsNRLH-5szNt35coi=^O%vts?>(B81$7a9$X7-lBZHpu@baPIos z&tI~i?WgO{G9!Qh0tg_000IagfB*srAbM&aJ>_*1L1l%Tq$eq)vzt8xj8l8OU<;gbA#D-vyEmSm~Arq z$m|WX9cCYz?Mi!LYJW7Ghr@L!b+*;7thv^vXqZ2CUh1tr>Z^Y0uK^mU zK^m+f%F|E{Q@)04gbFlLqg1HT8l$lqr|~M%1Wi=2CTX%tG(}T2P17|)Gc`-IHAizb zPxG}v3$;j#wM0v`Ov|-GE450iwMIiN(uP@-= zYNM^1jj?DOXEkiR)wDs@()w9*Yi%*s#%ftF3oOH8t-aN?9+qnDtd8x{0c~`f+-4W) zQe97T*2&_n*yXtbH`aBw`WEA2U4~0@2~IBCWm*F(bop+YD{)0`h@0uQE6W;Mwk22> zYh+!mv3ZMk(Qdt4=MrtOt#z#|$C9j@g)G;St-GaI2aB_|R@(+xn#G0osK2$aj#kh5 zSW_El>DJepS#N7%JG9MhQ~2d8Gsp@i2PHvqP!uF59dU=7E_eef;emcR&2hb1%H~+S~8G|KYBE*ZlhZ&sTi?`Hz>qx$UY? zc3->mqi=4%>!GKgeg4HGZ@u&02iM=W{g>~4y8Nrpez^2?zi#cxr>#Hp>~lA4+H$_X z@Z#g&5Kkb000IagfB*srAbjp^ z2fcsX`#Zfq?EPcjKUsERY5zvJz8cO~N@su5&3pfDkJaDH4)h2hfB*srAb-%)MVQC-zjeKk-+HBw_WQByTjbG1-QwNh)f zQCqcBwA!nKI;xX8tBbm-o4TuqdMZY})LXIYqrQq$KlRrD4b&hF)({QVFb&rTjnpWO z))~A`niJ-vIb}|pGv=&0XU>}o=AyY| zE}JXns<~#an;Yh)nXjcH(Q56`Y&*xs+YlRJ zH|t$((JIB-HnyYfZkPBove+E9qAg_$SlKAMSNqh(M%w{4&c@i*cCcNh13IWfI;3&iOOR$*qL^QU9Pj5ZqMt2F6xpl>xwq(ny%}HZt9k9>yFlHlfR4g${n`bUweh_ zYOB`yJKUme+Ncd$WEaVQ`Ks>K@cMdjUaS}6g@+~D{q}^d>(%xKdV{NIK7rO%KtQ|2sL zvt`ebGgt0BdGqBjP_R(put0c`2>^q8^Z#!r|yY4Vh*)7*cz`EG$*`1j&nOTXHE=BHn`x;1ZqyXxy-zWei!Z?69M z+uh&Y+Jx0V1ZVHvcmFX54jwvuEiT7@tb>}Z!yma}ByLSD?&0Dwc+#ltBeo#>$ zfB*uIiNN$Ho_uP?)6YCR^SS3=c=4r|Uzs&~PW;??ufF#B8*e@)C*&9iAb5O@>?_PC7?wtdpC-t*&q zKTi1ZksnEI)4$1m7|b68^T)xQJbkghnFByZp@8Z>y|hT!gQfk1!+cZasLLmjId?(XicMG8S$+^x8_ zbTdsm89vZY{XqM_J7>EJ1iYr(pR8pl>T4hvLxt`=&kR%)#_YO8h%S9^6(ggUB|BGp-4)KyW6RyTE55A{?p^;RGCRX_FD z01eb24b~71)i4d$2#wTEz0ftC*F~MxC0)^V-OyFt(QOs=Y}0n_)@AL`13l6`J=aqe z@f_1>J<(LfsI8}+=bUcozMko>4k@R{-?LE*G*9cbPLnlPYcroQQBrfH4lXpi=4mwwWI9ne8# zHYv;)Guq71K8-R*bVf&YSP$L)a(Dg5byBBvLO1nN3$;x1wb)(x2CdLcJ=Q8M(k!ji zYAw|gO)`_@etea6$~m2!NGHMxcLD=q%wBWCggK#3loRcQIBU!{^O-j!AodRP%q;IX z?*#97?^v&Y;6(2dv(CKPJHRK`|9%I={trApz6la0N}MEVvg9dJrb_LXCT+U(88T+d zoF!|v>^XA!2Y3T>9y!rAMC>T_zaFL?LiU*e{S*moIvgJa`SFoWK!zxv-Qngz3 z8Z~Rxu2Z*O{RRyiHEz&ihmZVn?0Afwe&Ou-OJ806?#8w2Ut4?b-AV8482#S3D<8Z)=KY(KKl;#4 zyEkRR#fgu;`C{tlZ&`cm^^c!1^VR;BAHRC$b@T6kcwLts0tg_000IagfB*srAb*`ej{0rmiGj2ZZ#;Lfu zU9@<~UuA6mJ^q9m0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL cKmY**5I_I{1Q0*~0R#|0009ILcmo9f0R0h2N&o-= literal 0 HcmV?d00001 diff --git a/media/nls/c_860.nls b/media/nls/c_860.nls new file mode 100644 index 0000000000000000000000000000000000000000..b8f912acc0ae9a2a566e7a136a7ffdf39cb69774 GIT binary patch literal 66594 zcmeIycW_iy6vy!&dGy|U+1+rL8hR&iL+`yqfP@qvq4y3dDk>@vQ0x??tAG@xNR^IC zQ$UoaQUsMIf+)TWJA^-QWE{tV@q2d8ob&Fz`}WLd-@FV8caq5lKDsBIASs!Gf4R$&?WRYXNq zOvP0~B^9DlDy=dqt8yx@3aY3|s;nxis%omPP}NXPccL)WQf<{yUDZ>4HBdt}Qe!ny zQ#Dg_wNOj7QfswQTeVYrbx=ojQfGBhxVoyFx+_AF>Y*q_D@L*Esb1=>IK``v`l_G$ zYk&r7kOpgrhH99GYlKE>ltyce#%i3#YrAggoKESqPH2B~5-K6KcAd?xwS8YkHel6Jc7KKBlMXWui@t z>0~;Z)~1b#H*qGnNpB{ZiDt5yVkVen&T%C;8=bk%7H6flI`f>F&O&E}Q_#1~S?Lt> zMf#R0#ux4L1bc(8tD$eH^7vLOuW!6(xn`MJa{qi)^H=xB_+$N1{s_O%bJ*-QM@(&h zm_N=R?+^8_FVRL=4**r;GODC@J{ni@fPw;_bxZ<%%lAT1O@-^pMb>oL9!qx zd5V;&Qm09qE`5fKnKEa|nk{>doVjx6$(t{Kfr5oRUSDuw<1bRQSn(1iLrRq{Q?^|B z3Kc6=u2QvH_0SqMZCI_^b?Vlu-=JZm#!Z?wYu=(|tJZDWwrk&^W2eqt!n=0s9ue6i zDmo^%XRqFI@qPOC>px)Nput0i4jVpV-0`=aqcg>+Mc7C{e?ZE>(K3>0W+x9&xSADc^|L)H| z-*x!QPwzb#=#RVgn44d@`L&zhEM2zTEqCLOyB!Sz2q1s}0tg_000IagfB*srAbZv^E`0sOe_9ngEmCR4^q?ej^iNx|<%Ri)m;2m}nDbTA9A4m+5UH zO_b?uI+-@6t%)@;Cb!98CYwoSikWIAnkCLb#XIYrInG9Bxe}bY&P->4v&<>z-RvxP zih0AmOBCge^acibf-b3%cd_z#S1PY}Lf}%(GPC6V`Ksot?u+t8`yzZ{K5yV|v(4-= zb$qpaF}_$|h;NliFf%+Mfh#mmi_Cn_G*7%I&NJ0h$UEJ$)T}WN_Z#3J^uK=t62Aw2 z{!WUNsZys&n=XBZjF~bAWXYN>dybsBa_7mLFMol8g#ta^pu)yiq-e3?B}xXDDqW^* zx$+e%R;pa3YPISiHEP;gwd>TaSHD5SMva>^ZPvU+%T}%1v~AbEL&r{?yL9aq+Pz0u zc+ZH)sOVn3`^3cd?bm<6z(IqD3>`Ln#K=*j$BZ2}euBNr_~TvsYSNPT-U+t$@-Nq| zJ#MeKz4sR_wDav-);{-q+(bLo?YwR6GuFPd_^O zDLdQRDb~IjZ>L{;#m;%*k(o2@vitp*e&c>@%AOC7z>&nGoJu~=QEN|HdpfCc$l5bM zB~Sif?XeT~Y;uDN0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5J(aT4z|H= z{9EJNJ#O^+J+5QfKPB+{RrgLmCg1Jn~UkG8;N7tU&(%wls6>hO-cFIw0+gLyS9F~a`iVmKmB;^ zn$252U%uj_ufE>)<&MvGfA__$3zO=DZr@}B%s(S(oq2^N)Z&q zf`#6D2Sr6x6zk-eLn7jlKRg^T-?!)Py>s8&nKz%Avsn~o`N>K8D8;b+B|rJgQX1Jx zt8_}Q49ciX%B(EPs%#2ScI8k`x~Oh!HxR|%C= zDV0_k1*@#esk|zvqAIDfs;H`}sk&;YrfMlfwN=O6QC-zjeKk-+HBw_WQByTjbG1-Q zwNh)fQCqcBdv#Dpg{qS}tBbm-o4TuqdMZr46s`#MR-~d7tr+!DU-eV0;?!RQG*E*y zSVJ^a!!%qYG*Y89T4OX;<1}6qG*OeZ)81w8w)fb3?S1xs`+$AWK4c%ZkJv};WA<_T zgniOJWuLas*k|o?_Idk)ebK&TU$*CIz7}XvV7%WcUC}k&&{gfyQmxl!1q3bECT-MQ zEz<_gF!3hA_?u!T!t^$sOsI)8?M!FW)ATUiO@PT|Dw{HCzO~g_qixngYqqt- zT5T2aZnxH0CA|^em5TO8c>{wyLD$vPyF&TB>r}uyDR7nMm^pGEzH0hv`J#O>zDQrV z&l`Bq>@bH+eP3N)tS`YeFXWj31o`wj39 zO7(9*;{So4zm>*Ln=XBZjF~cL$(k)7dybsBa_7mLFMol8g$frb8tCx`6*Io#B}$em zT_(6}x$+e%R;pa3YPIS$YSs#=UB{_guYQAujT$#;+N^ntmaSU1Y1^)ShmN70I(O;X zt$UB2VZFj5dPhb@$MosjFE+0KfPsSs4;eaa_=u6CMvoagZv2FalbnAUzrXgvi_S}l zix$4VG}v)|y!xx-oOfr(mCbKNpU>atzUKKx!*rH&ioV;_fq-F zy|fwja`y#JCtmVW@^#NT&PB($oYXk!IA45~JbA`(&RuY>BsZv1wZP;D9(-uZ!;d^V z^|8mFnD*pTPfwo_pD=UQGtbU`?)g;h!p$Rq00IagfB*srAbf#!*@1q-2TBQYu3KKYxj=NcYb{Ez-K8JCe~VJqam5Lhl_^R8&+*K(QkrMNoQ?CIV6w zET|wTh=r!0f+EH8cHAKhgX8!Q1Nyx?XV1Ck?%R9!^WJP$ML8j|!Iy3tPN)>3P&rDY zv`VM+%AkzOq|C~qth!Ix6sGLTp`6O4+{&Z8%BTD)pn@u-!YZPo^2jTn!c|O0eic^< zl~gH}RvAU8tjejpDyX6=sj{l5s;a5FYN)1aDN?mn$30P9)l+>nP(w9RV>MAzHB)o7 zP)oH^Yqe2ZwNra_P)BuAXLV6mbyIisP*3$zZ$&9uG3ujO#VKA1>Z^Y0uS6wjfCg%i z25X3hYM6#=ghpzVMr(}5YMjPvf+lK`CTq8@>x@onyH04GPU)=9>9j8Byz+XsX_5A7 zkM`-3_UoXo>53NUkdA4d=Ie-#Dmi4K*65qJ(?Q+&S zC4Dizm5TSp`8?s?@XKoITcP~E^(x?->{+F`X0F_uubTc^{&;_aKh_`Z_jwMR{pN_N z@2~4m^e6cv{Tt0rGus>KS?6jjGmE`5y(!*g?+kBI-z@Jcv)SC+Pe5q+|NaRG{2zpb zI%(3TOP?WQrp#Hg-j^*bdybsBa_7mLFMol8g$frb>hb!*iy43M5+zHOE)!9?M3_2bJl+OkbN*Pd*rbP zrafxy^vB(LUW&E9*k|THeScu(t{X4kbtmFLcU0hHV7D`=TYhcrX=~308z-zicRqFT zD{H?wWxr2tP$7T-0tg_000IagfB*srAbkp z2;}-5+J|lat-zIQ?iJsqUUeb0yj^wqcFjQV2Wv0>^mmJQUw_FhN4oU$Ee)psDS@4K z^^M>2nOnW(#x^&OxUs{Hz*zHFvfG3C?O=WqeIftx=VtdG0-m>Wmk_}q;zR;*m*rW@n;8x;it2q1s}0tg_000Iag zfB*srAbok|asU zl%eRagST3}V$oWymX+^5>wo`u@Be?FyVvKOb>k>JIEq}vr9X|}ASsH16s)LnP(w9RV>MAzHB)o7P)oH^xLT`?+Nzz}tAjeKlRB%5x~iMHtA~23 zmwKy@`l_G$Yk&r7kOpgrhH99GYlKE>mDVdoXv)y30R@5rB?6fOIRmK!1p@H{A%Vn! z2wnHr-}gh&RXP z+hPm%T6=B0wq850z1P9(=ymcsdj~9)x7ya(221BH&?p;iV{N?cvu|P;k^}Ui26- zW5o`M6E|M`1PK!*PLecP@)RjkrB0JJUHS~688f-eS+Zu!o+D>iuH1R@=F4B8V4=cA ziWVzgqGTyox=h(}C-Fo#KG;GwkNz-P{TeNHy-nvcOcI`WK z?9{nS*KXZ=^z7BUPv3t12MioEc*xLU!$*vC4<55-J2!Wpdw<~~cXWy0Hsh=L&W)OO zcf)A^^X2I;K5+Bb53JlP9E+&men=l>1RgVi7w&VOsrOl934wnmusm}6Mt`~`^3vaD z-~4syQsjkItJkc3Yu(%H-`Nm|TwsO(0tg_000IagfB*srAb5)5WMBwoe81J6?<1iEbZ_oQN$&bl?Jm<%q@yxyC zo{h*8BJ$G_`QJ_BBHhj+&6ps700IagfB*srAbx5DjqZ@N8hrQ7TFx&7{d`_yf62i<1(nS0M2a%bJ=?y$f23qOu;J96%)^Iu+n z*PU=T+_&zQJLzt^@7x7<%3XHfyDRSW&p)^`SAVZ^eos*xJ2iJGdJ znyZCcs+C%+joPZ6+N*;)s*^gai@K_tx~qqJDqIojrAS37S~2RaKI*Gj#i^hAYk&r7 zkOpgrhH99GYlKE>ltyce#%i3#Yl0?ftFG&q4(Oov>5z`-xK8M(&gisGDp8xYO^3Bb z7j#kQbWK-uLp!xcmo--S>V82f3ysql3c4)EIYJ-A8mTJA$X^xg?o~E04lVAc( zVH06`nGUACi8QTEN7LPOGhI!P$!;o`k|w{A2{S!RPt(P;Gkr~r2{)}wKhxXvF;OPk zbT*w#8`IXrnOKwCWH3|AWHZ%FGn346XRi{Rjm}(Wle0>R&U|N`KtS(eKEdBU%1a3yvuAiyG&PgwA3EznZ4&@DfY1cvZLQjM>ej2@pkbrNO`0}q-lAoz)@|ChYu}+`r_NovcI)1wXLv-f z$f)R;-hKMU#`WtzVBny^Lxv6;K4Rpk(PPGr8$V&9{flwqb^GF*zt5Tf#^O+GFQ5Iz z+Qas$wF~UhC3a!brKg^bpJb=`7kVuzKWATZ-=DX3|HHE%vXdW~{^;WmPI>IfIa8mo z^Jc!9U}s!>;n}&*JYelC|F`a;^vXSS7LM{S2pmY-^H}o62dzD7?Qwr&pS34WCtv*0 z+CxX|spJL~0tg_000IagfB*srAb`^nn#=l<;Cz1LrK+mSB(d|QK$|0#h) z`_|3h^Q~KLaATtzyWQC2M$%aMN3tLI^ZWk1*`IGspRE0Q=eD=ky!+LcAHKJK-IlE% zuUh@ijxV-<_W4JS=-aDwMsHjwXK}A7D zMO0A4jum?ad+)t>T_%Cyn;-au{Ljvrb7uGMoqKyrP`{ax~iv0)mH;GRFoPiT8$N>SjDM{;?-2ml%PZfl%!;($SJ7iYN3{D zrPfMSNNvI5jaHt^SiCj0W|m-y7O*5s zwiI&~wC2{rT3Rb>ZK)QrHrCeKS$peX9WBi|S!e5FU9Fp?TZUy?ck5xEZEzdiCKv8f zT%jv+qunT1>~dV5o9HIE@h;LuxipvR;+tyAn6n zjd3H~NLTL4T#T#j*19!rom=l#yDaNz+1AT?TOaFd{j9$Yuz@zn2HOxDYQrqda?C8( zs#%`ZwS3#9*rdIRONtI`(^j`t{>N8(Fe6wJEDaV13xY|BhulGT*kuQ^f@Q(-U}kWi zJK(kiG86Y`yLP%AfenF8fsKLnfrO;Zf!%JuJGoClc=9QK0*?F-!onl0O4VxBYt*b& zyH4GDk@XuijA|6!I3_l(Nqp0035kKE%6fcxX5TBXK6&@vdtZL(iTm%{|JdVC z-?itS7hXL0-1AQzdhOZc2Uhm)`1MUc-|+J-Ki}SU`)39GD literal 0 HcmV?d00001 diff --git a/media/nls/c_869.nls b/media/nls/c_869.nls new file mode 100644 index 0000000000000000000000000000000000000000..67499be9bdf7f372efe165fca9254ce6ff22023a GIT binary patch literal 66594 zcmeIyg^yK77{=k3{cv}ey}(>_ac5z0cXxMpcNQ&0b{F^J?(Xi?Td2FcdwWT@W&Z(^ zlK$r8%ll2vWHNcqOCTTjDBiFzDS^UdN~lCitRzaRWJ<0SN~u&ztu#ujbV{!b z%BW1rtSri^Y|5@2%Bft+tvm`>KzWr<`Q;Q;0Toms6;=@yRfLMExJsy`N~yHUsI1DV zyeg=oDygy}RYg@pC#t6Es-c>yrP`{ax~ix8YM_Q{q{eEZrfR0Y$G5q|WN1uIi@l>Y<+MrQYhJzUrs`8lZt1q`?}Zp&F*)8ljOIrO_Iru^OlGnxKiA zq{*71shXzgnxUDB(k#ukIXb4@+N!MK*}~^qrto<--*(ypi&3l=+AiCnMRrh!wA(gm zkL|U6cGDKyZM$PjEZSl$)|T2bTW)8x!dBWYozfB)?P6S*%kNg%YFlG#t*2}5+Pcne zovpXDE~6{sin^RmF4AqVjn=`na{XN&*UdF^gWM+DY+G!rZL{sR!w%R%J7ig1N;lU< zxx;qErn#eb%#Pa$J87rvw4JfDcFxY*1-oPy?XpGL9v#pXyK2{Lo37g|+pq1qVYh6* z-L(yFgF+u)m4cOny@P#%J%inXdBg9yTkgKA5v&#*5F8kc44!nC-O@m0_)%@sZnr(K zBoGsb4lEAj$r~Fu=uW%G`v!#N``_Py2mgZvVU{pa;v`9vB~OtuRq8Zp)1}XlF;nI& zS+ix&kuz8BJmG=7`SQD9fr5n!7bzN1tayo%rAn76TdsVCij^uyR;lW%Rj*OAR_!`< z>(y`2uu=)C zF=NM#pD=OKJ zvOo0iVO|M!=R$QpRQE%5DO3-};lIOQjLQpgc_l96$DNbj-|+sF_t(8Y?fq@0S?h3eI~x!-@_;6Lqy{3HH^9svXpKmY**5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~ z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY** z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0 z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{ t1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5O@p({sIS@F>(L^ literal 0 HcmV?d00001 diff --git a/media/nls/c_874.nls b/media/nls/c_874.nls new file mode 100644 index 0000000000000000000000000000000000000000..79a6291a71b770780107ae2840a098f535e1af9b GIT binary patch literal 66082 zcmeI%RZtgL6vy!&peO5itIgQX(M;Vz**<>l$my*}fEH}B!LoL)&o@%Am@=_al%SXO4 z`N>~x)lLBlRC{$$kb)JWjtW(n!WE%NITWR6#VA&BidTXX)k&R|q%Lx*tCE$XRHZ3h z8Ol_ax+z;Z%2jvuP*3%0&L~g$Do~+{)LVU2tP+)~Oy%mU3iVT^s#L8S^;fOxG(h!g z&_Fe6kOpgrhH99GYlKE>ltyce#%i3#Yl50IQIj-TQ#4i6G+i?^Q?oQ%b2L};G+zs} zP>Zx!OSDw`9Luy^E3{Jaj#XN%HCn56TCWY-s7>0eEedvoIKmv^j%Y`KBhax`+q7Lf zv{SpZTYI!uZsu+t*1}qvr?s-y=4EZn+kDK|%>2yX+FCmcus~~X9W2O#EyOxnsD)X$ zMOdUcEXtxS#$qkb;w`}vt&?@OBuSlCVyTv9>6T%cmSx>6+j1<|_UnKS>X2NP zXZcoOg;r#}t&bI3iIrNJm0Mq{uzpr)RaR{^*57Ka&IVY$HP}FFv_W=QM|4!j{(TE> z?j9{#dbVoq)yCV$*Zln3whIVs-ytYCq+@7UctoTlDmo@ME>fRn;~9YwHHoHwR-}U|j2M?V#=Zn*KLn{T=Gw%hNx^RBz^x%a;NA9(PghaY+LvB#fy@~NkvdG@*I zUwHAQmtT4Hwb$Qx^R2hvdH00Ed+&en;YS~T^66)vfAQs4Uw`xMci;c;<4-^T^6PKE z|MBNvXA={(Ab5H;5XbRPIoz#4ixt=6ZeQHp-MzqYcc@ZI-HjD0w1pa4io4A{lguTV`!Z?R zmh2DU7nb*3^5k+)a(SLtu9CdWMb1B||3qZ^eoYOnTbzYgf2%B!~O%1{0Z&>;n?luE0Nf)%1#3RAcu z6seMmR*Yg5rZ6uwqeg13Sc|iGORz*svSd4I zDK~zv3UK%g6l8-;xzzffi&(Y`%J_ ziTbOB`l_+KZGjeQkrr!-mTH-nYlU(x&+@InPTLvF(Mow~l~!wwp3z#Z(|Vn?b9UY? zSfO3C0`1lYZPX@h))sBmHf>jtU9!t|#je_QOHr0(+ey1;r|f|}wEOnRuGtN{X}9dQ z-LV}Spn)2s!5X5W8m8eIp={l?V9T*O9>$v^iqF((54f~JVvt!n(@w>*%nLXBP{-_0CfAj5k z-~aIAPe1>%eeUSpYn+`|uU)@!^VaPjYBKl=ESPd^*^-pqNc zx9!`1;GnmUub+QNXjpheWK?v_vnj`pr>3Q6Tv_@2(J~&58aHX`TDo@2R;}B#Emyv7 zhmP)@yL9bVwnxuiy-U{Y_vc2($#I-_zgYX5^W|6f94GkA&wovJ9>*WfTYndv2t3sS zd)K|ae#0hbv$JLEg8>5v4IVOd*zge(CQh0>W$Lu)&WweN7B5-4Z25}Zy!_J-0}cfq z4muJW7oU)rbRsh=`{adFg%^u1UA|v%?#$WqPc;LNM*sl?5I_I{1Q0*~0R#|0009IL zKmY**5I_I{1Q0*~fhQ~A>FIcSKIb@(-g&ZfnT7xY2q1s}0tg_000IagfB*srAbSfHX*QlLG;Asi6b{mjnW#lhA7dB(%_b2Ne|+m13{h#fn(4 z_uhN&y?4cq%NQB>g5&T()c@Hzd(OUP=iT3IEzPbNrAYaueIgiElq#sAOqEnwRa8~g zR9!VxQ?*oEbrh|-s;ByjQ3EwpBgHCC@k&sl8moztl&lnml&UnjnyQ)7)m$yqQW*-X zm0GKf+Nzz}D^nfRQJvITS?Z#$%2qdZ4^GrWIm%T}^-`XCtB>;4SN+sq12j;BG+0Aa zph6ARFb&rTjnpWO))$9kftd4^|twy*VdzTP+ZM&IO{eTyfjZuPiO zd?-Iu5-JUCRZ8l1?a)r`(hx83LNBnPKFo*v2p{RAe6)}8u|Cen`vfoYVxQus6V!FpMH%d^gwWnHYRWm`AvZV?-7JuJs^t*3Rg zb~eEJTPMr6f!5dhSU+oJ(N@=*T8uTYG^=lJu@-0XmSBn2*qT_9wYFqSv5=)&L#t;Q z*3ueTx`nN|HM160{xd{XsA!ccSE*X9dX1X3YS)RbTd#ghgNBV_YUZ3Yj(Hpksdj@J$vQ#?vvlQU;hCE2Mr!lP&jnh z@DU?NjUF?0-1rGa#SJ6*+s)$T@p%2NCBU#9p={@ZS-*cK=U#>+M}1y!+nwKYjG^C!c=y`4?Y) z{mr-Ez5n4mzy18{?jL{n<;}0|y8DF(?!E8%mmhlgkw+hU{D~)@e&*Td?tk!}*I#+< zjh9}0_0Fdv7wrE&o)AC)0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILK;WMf2!|u# zAc_CGz{#ilErC-Hu==#q4={O%Pi;B#5I-QtJ1Bv*k;C@xKRoD;2y$JJM+SLRkbC0j zKT2eMc|E4Q9$Q}bEnCk!|H6wdzU0zvmtB6vl~-N8{hA%uU4O&Q8*jS#mRoPTecy%U z{c%Cv5ajVeo)F}T8#iqZ%HB9>Z%2aw0tg_000IagfB*srAblMaWl0t@Gg&NkOBPrb+LCP*}IYr~lL4YFG8CY6M%DQWKW-=gnSu`xETXe<|Z& zuo|$MuoPG-tQM>`tPZR$tRAdBtO2YctP!j+tO=|stQo91tOcwktQD*^tPQL!tR1X9 ztOKkgtP`v=tP89wEDe?p>jvu%%YgNO^@R0;^@jC<^@a6=^@k0B4TJ%(L9oHFOxO_E zP}nfoaM%dgNZ2UYXxJFoSlGB~jmEy<;8DS=v8D@c5VYdH7@lS?xVT=Sb!Ah_boCG() zOYjqdgfJmWh!c{8G$BjK6N-c~p-QL|nuIo?OXMc>2}8n|FeS_hOTwD4CF}_>0VNy> zXCg1*O1KlAgg23&@FfZo{zM=VOoS5QL?ls|C`v>Vu|#pABvG1(C(07#iHbyJ;-6Hz zy4q*h7ucVw*Zk*2{QK1WpWOuiuQ~klH{n;!|MSW4|0;w5HGrBx!$jl6N1%P8L!wKf zMj{TB0UKfC6H8&^6892WiO;|npd6?GQh*!qT0m`}4)6(R)wOBYCW$c#Y9b?@oaoUt zqifr)?YegC+No>ZM7=~ypcODWF*ZR;P!e^4dO&@k0niX=1T+Sk08N2rK!Zf1#5&mb z)z6@JuuchjddEcP1UH?R-Z_0p`otdNd#r^G?wZ*(CG9~XHE}y}Cs8YrlBk`ipXi!c z0;}DlR*&Nur!!7v9L_kDF)w3o#)gdb89Os}WQ^|G90;cc(?V&Hv=+eMCR#VWL3&=g zD;-RS()*5O!Ax-eao-adV7 zdZ+ZE>3!4t{i;siG@z@jhopzFN7t@tT{r*bm*9EEuUq~W<4qII63r7W5-k(060H+$ z5^WRh62H_lEs>t+mgt_yNc2ebO!P|hPV`CiP4r9jPYg&5OaO^NiNT4?#E`_$#IVHh z#E8Vm#He3Mn2?y5n3R~Dn39;9n3kBHn30&7n3b5Fn3I4f5D8=gl|Uyj32XwF$WGuB zgak2>^A`ydfQi5)U@|ZTmKpa3+00k8lL$OiBL0U!c7 z00|%i6o3lQ06M?`m;ei40~~-0@Bls_0EB=D5CalG3djICpa7JB3Qz+YKnv)ATtE*P z03%=m%zy>30ye-7fB*zI04IlyFKUr7)!^C7KdTDNZR#DNTu|l%vLIz)%A%CTDN9n8 zrYuYOHRW|F>r*zQY)sjdvN`3ulr1S+Q?{jSPuY>OGi6uG?vy<#dsFtO97s8sawz3+ z%8`_#zp4LgdH?(3O;ektHcxGl+A_6OYK_#^scll*rnXCMpV}d{V``_=&Z%8eyQZe4 zrl)pG?Vg&E+9S1RYOmDZseMxWruIwipE@9QVCvsLXCQS@>fqGO)FG)uQ&FkIQirFG zNFA9vDs^<~nAEY=b;qSP}^fX2qGmVwTPUEC;(|Bq8G(lPxY({3w%=FATnQb$B zW~O8g%S2`3GaF_0$n2KcH*;p@=*+Ur^2~}%e`X-_K<2#6U+ZYBPU!@60a~Y>%uGvL zIC#UZqE=>yW6Rlj2|O7EK9C4G1Gdv@>YclTdQ zOUD2IBTxo!jZ4YNitfR7VDw_WC8h^8j*bx0u$+E}l_7n~;W`$BKgT2dp7?nj1v5@M zLp0{SDQ22?nf>wB%u3UDZVzb_wH_D7(<{-)uGmx*chZ8RlYvj}; z-=a5R$QdoTwFKMb2#s9xQNPOk+`Qk`*uiqw%*O={!O@r^_#*f%{CeBo;PYG<{3T(& zbVP8lp%;`74lJ91l4Eva?_h6de8I?!pMnA?HU|(Zgq|@@9 z)_sA;Q5l9@zRl1K9?AV=?;&lQor>!uYVRCf_JFty!v#IMD@B_#C`E!;4q_$5ek)4fl_>m@5R$Fv7a7Sn6wdkfYV`30*m zd8jN{^Xh-gCKET3-cozfm$BZkc8goe{PLCxqT-?=OI5?71Y-TC+X<${Uv-sF+8Nij7bzY8H7jM{5ZATd+dF%y?_mHQ>>Tsv9Y8!LH)9f&qcsogJHan` zdwd6@ElMty9EZ0@-1FSbo=G@H_(=Vc)`wn5XVT9wnlsNZM{>Rm`%j2-xoi14iCjKg zlc&{~7l9vK`9=O{x$h-v7rHfZ19k(cHHFUr1#2V)xyK!Nx6->LvZYikSz2->Zvj5R zJC)Zs453}wso3+>JIt-@G5ity?INXWTdv4Z>N)2T6{G~71{V|+Mg=i0X#?3Tm{SZd zjlh@R4P2F&zY>gpODrJ{h&& zu-GG3mihsMV%wnM_)!iLVu)`;`$IC5`Cm%(lwHj zs;4fXcVVy?yBOD4OwL&zhF`@WC&GyE;&fR|Hbu5p-Bxo?+d!8v%rmB$o|uPOUs%g+ zT(AP#;5p%4;d2C0g^{9A(flG#^n9#WNn3CPyf1bO`2=N|YPNQaZW;MUYlDKl(PqWi zVnT5ZL}P>kQ-yZwSg5-u&3-tu;8EX{pd(K@>7v6FH0sgmPf0_`W9u&0^ zo5fbmbUlky-9c~ONeg(|dN=xX1t~ay{=^<7nyU7|UQhPfxuXeC4dAj;g)~#_}eLmEwEiTzQIGYglclYiw`+V&a+~aY)MTm?`APlyl76%yz7< z(ww|O-Wvt)!!=}!^*QmS@D=ct@Hk>F;w*9+>a9V6dW*th(lA!ckC>G>h;WBIoHmm- zkdCBF=v`Pu&Me_x@jm5K<#XM8TP=HC5bk^zyc0>p@Fh8=FW@&&{mFK&L@=KGimMTL zR7k$vbP#zTJq`bb(j&5v(@iv1G(>IJ@6^vS9y4zRPe4{T%`-CpY~XCD3)U8Ev(2{>7|H zLqx2OF#^jCUWGdfn%eN?78G9`d4=wPUEyruU1&Y&zZ2wQ-0lhbeTZGiX6VT%46Z-^ z2UR{EMP$+(G!0$L;4zjl*0V;j#T*%TBEN-{s~KzfXqs&GikE|p*fgeJ46&b`>nc9Ffk9T+T*5$p0k3{xBa*!s} z2s8`51lI&#i*O>Rin^Zhp7ENgWOWqu7MhhSl><~Qb7i@Db3@%STfV1V{$1ZWKP#w- z7^1l17NxlrlTekI4HzS}2d#rND0Qg5s3w_*gD`KE7a4`a8zApvOxUXIvqU!OC1nM* zCv60C3TF*3TY5%$%(T%x&vwW50)pqcypIcphYv@2#Vsle;bC|q#B|II>^SVe93O2S zt&+Zk?-%B%?YR}+g zgG1rxQ+Q#~oM;xTR&hzm<ORp(+1lXdK;$!d^*=+nSLQW2!ewfjOTbnzQzmES- za#1tNECnaV<8UP6D5f?}MtMkiM)}Aq5v$ZSbCKR?<3i4xmn9btQ_zxAwRNXW& zBWNkggYvKWazjl^R&rKw^FUaud(11$J>0eI9|^~aM~Mj{k~D{0liHX1 zJ*^YH4r?HXOj^U)$$88v=P^ZDFr%o6c#3LguGi;% z<~{7Y?mH3vR4fza!^a>B5J(iBR7IN3sKJ`ZO%olLZWoVJ?o?mU?9CmeZ)nT3{a`P2 zR0NP>Yef?pA-`{VmEpa=fb?TD1^yEA4nK%^G-n~nL$^w6%XVpg@Kusv&f7*M@(r&X zWRPb%J6jrqC8$&~pT#XG<46_b^li+wY@PCt`K7_bdCP-ckX7hWWDL(FAF7-kIuhy| zc>wMs4WfOZkA`2uxJk2^gLq!i6Xk8y0E5WBpa30;mNZ9wj}c-MBsXiMaHSa*yPACp z!~aI^{}^cy`6lHVq6Xs&bFgHO{P;gdA96A&& z3+;g;5K~YSFcDf~<^|paaRVt!)x&Z!1cfhP+7Wk?&Ppiy0hYMQLa0%u$3@$eW*jy{DSLO4N4Cyk&Uq<>*Ec-g$klFdq$hGp2|Q08w5b&U+l zeuMu~{B7L-PnnGbQPEQc)}pg1!H1q(#W>fxz-aOa#2v&YL>*k$oExMkr2RBFV<2lS zXBPJvKQ73Xyp&{WwraZQsQQQcO!Gba8gRLDxo4Djg+Cq`9J~>#6Wa#g3r|672tN@T zklSmvDQk$>D`)8PO}DLb_rxGJ z)HKpI5{OdO2TJQu1Qa=EK5uEkwWyRegV#=Q5NcDrC;G+hkQvzTNv+}i0-jtceQFFR*)!bM7)_j(zmQ<&jqrI z$5}SmPnl+CqXH~ zwGqQD(`j>=nPHm&5g@T+hvTF3pj%#0BPa>RA{}GROHU(X1V7`veW;w zt-{FYGgvfUKk0^oF2U~+RPr(3X-=sbjfuLosQoMgNkpnoZp23M$iYkS_QXC!xftag zhigSxM0`QVF!%C?f;hqW=z)@6r5HqQ!WU9g+dA?TCa7*q&gfBCx@=0U>da{WIkU!|uRU{&3%W<@B<#!nNL!Z~~@w zHWz=8IiK~A0~g(qkff{RPj$}?%Z=O3V{M0Q$McH3q{zMO!-R3PRh%f-Cfp<%t~u=O zj(ng4@EvFzx`9g8%mBE$(j!al<|Ng3)VFFL?1Q`gYM*v*Y$_L zf|rnP({?h)a9{Esi$!@l_h>IX^g4W|q>ZqLypQS;hW3c zmb9TX5p5&w6{8tzKDQH3DnlzrX-4VPwvqN+yVkYad)@0ScwJB$))mz(eo%H0jc2{l zw&Jt0SsthNO(pSa3q{IZzt8rfDC{A=Kn=WPKD&LiCee=4}u3aBehXBUu8u zOo)F+=tt^j?xU=ay%*Y8z6uUUkdYeXBy@#uI<`BZl+=k@L|sLFN9{uM(Kj(ivCgp8 z@W+c?xqf{E!)^04u%`E+ce1}l@LRBc7Hmtff9P_kapeOsfqj>);k=PLv>l9s;MvGF z=_~A3+Cui6z|+9wa4t$j=uO0tW7Ln5fTg2mhwrYRRJ>K*39(zWP6lW`M&YQY*r5bG zVI`4H4%1>BGA~VP)ZT)g`dS7*2j@gGa!2JZM=z#!!K;bQ>CKTjsFl_IeH#% z5(or5v554RoKM+7FJks*D|nOmJNUQw-)k>RWYV}qCO@LU&@O9q`WZ&75pBF=QkVfW z%OP;ycQ*E>=1=uC@uviv1ltvAqy3A4(#u6Bkr&You{8;e$x9d&?9P%6x(9|gwp0fu z=nUT`*D24!#Aq96WfHxTrQ5B)Z#*aZNx90K!eIM;Hco7>T~}VHjtP_eir)(_YzOi3cPn@YxPY1Ba*_= zSG7)|rv6MbvP#+e6~(4W@K4lP@ay>b*~{qrWsS_AZJGAn_Vt07XJOtOikG>H?ege& zcg5o*!_-4^r{-v^tH6~duMzvHH<)1-o+IP!*Una+ux+#T4$KKPLVm!9bDY(EU@8Gy z@mcwu?-k*;PZ(_%w7Tx=AL)8K1|m4<9L!1PY2GohSzBla(FVbd3nb4Ev-8Z7lRdX;XyUTE;{e7Zp7zGh`D9 z_w#l{hakG6XJSrbu3>6Z`>{hDD{q__E}pJjqkO8uY9?6vflr*vdmu6< z_g3$ApEXF0T`O)N9APR!jw7$8xpg#Q+8L)*Yn*tuikfydYW}mb58#~ z*emiXT;_P1*S~BpR!sA8$dXp_CBE~%(ZvYPTXiG&W%zA;Um`c>1ZgQMg<3{!P1iDY z)%|}N9Wwa^OM!bMtZ?EIY^ZYDnL&Gt*h)=@>%5c0kdNfv@y@9ZhA!W8#NQoZPO;ZQ+ zi>Ql3wY7t55E|5Y0*k7m)~6ld^?;9cdWuL_xog@h?1d8HK+Xeh+a3vz6JG zw?cd%unHlu?5?N-XEJQkzOoih6}As=O8hmY$heYxh}6+FQ+n3X(ool4LM$*f6L-~J zL8lYb6g1^EUC$V!yn(=)(>7-jsu9+VZOpx;eHSPWzbX5HNKqb?&OsgJ?>7HrX2!Nv zo4ve0bYF_Eg^cMKDW3PFuotVOUjJk}iVs!Pne+%1F?})%a z9176~br^jdvxsD-&ZUElORRdlt3006CmE(1t{S94>My#By)%QM;LpJW(E?X1q8m;` zG=_V;S%Id-tB@vYl(?0&g?g1$#oEih&YdZ^ENCFvEG<;@(yTFft3UOh;W+BBd(!gj z`#C{#w0?<&5n>Lm?*DBc+e9hWzu?T zqDGV(HswXH8wx5nBczOj9CBVBd^P+kG7WwL^^8=)vGaFGx~L{r zI;4rVEsmqln)@P)F)`k8$r(ka`mw!FU_lgLR#`z;Pau>?2AZkG_u<13`H1gO>(JXM z9qH>;WAx|2A>r?$Z=>~Nu?lA8Vy;@$2E71%M83~`lsbzZWOS3wP>eIZG0SY}Tn7d9TV#;KlH!Wg_ohC*KJZSfsIBoc)hF*M_vF z@K*3X@Imll@G$b}AMpUu9@z`o64?itfvkn>hIp$MovObL#FU> zNF;JPG6$KB6eDwyHe@N%iQI@>kNl&U{64uyk;jl5ko%CAkT;PJkWZ2Kkk61GkUt~q zp=zLNqFSR`p<1HaqtZ~LP{UDUP@_>)z4L)}K<@}8icR=)$kK>dvR zf=Wd zFxH5*VYOHXHi*r`9>&hcZow|XuEZX|9>FgCM*4qOVE17cVs~M8U@v1IU>{aehfN-5~pKy!toKQvhK=?@bMEFdoNvuz7 zO6)*f%+Db9Blaf_CXOJEBc3zhh)5!wm_sBGnM68~M-&qU#NT(H{!yiKiFRT+k&0M> zSU_A)JVbm7P$_& zF1Zo81-UCZo!pB&f;^HufjpHACu7J+GJ>oiiOEtj6Rsue$v$$3Tu6=+SCF@pHG!;!pgJ>YlO7qg(v=GfjtDu$8ifMCcOKGcUJ7||^ zA8Ge#?`bb-H)tE^30fMRPS1k1qc^4ZrZ=V!qIaOTqW7iupf{n9qUX>j(1mmzokpKY zpGu!YXVE9o+4PBYFEYQ_o1 zF~(8GJH`>le#RljHpX#=-g=Vpka3UkmQlrc!$>ebGd?lCR6EPoW!7UhVm4&9WOiWw zK0EzUr8_gzn0=T7m;iGyGm|-i31?E7EGCIbXY!dQCdl+KEzB@8!i+L6Fd=3k^Lyr5 z=62?3W`cQ$d4YX|d7XKJd5pP_d6*ez9%VLUJ!8IP_GHy$)nz?r{>((O#^__#c7(l%y^QT_e?tEwH8KeO9%I&x}px^ud5`f`SFhH{2;hH*x4W@)B#vN<@; z91ej)TrXcQSVdcLJBnrEu9?9+%IhahY5>7vj3Pey)e>;1+YsxqG==xktIX zxI4Iiltq7^+ymS#+)Lc6+}qqN?nCYq?hEeE+;`k2yw<$VydJ!syb-Yhye!@@-UQwV z-f-Sj9+gMu5qT^go9E%ldCPbvo{;C`MM}k_yb%M^qr-GKk9|iS=&4qh~-GnWKlZ6e1O5reJu5g-=DI^NH!s)^h!gOI! zSRkA$bO`4Q7gT@y_$_QPVVk_|!u`U1!Y#rL!j;0C!n49#!sWuN!XJbmg|$Sj^Qwf+ zMXg1H;$1`|M8iebwIfB(il>PtiDrn9BBBT@B8g}shA3C07g8uhCh0GgN(V^WNtIHXbey!CR3z;y)k^0` zyGSQVM@iw*?$U&`lXQd>lrEPROOHywlb)CEl&+B;kgk_rkY1Dqq>H5cq?OVMvSzZ` z@}H#drC+33vRBeUvggvlvJ=v8!TQzycd{0;chWqWL6$4C%WN{4j3j$4lgL1sNk)+Q zWg*!<8CSMJwm>#dwotZJc1X5dc1w0q_LJ;_?6T~o?3wJEte(7qyh_$gUPInQ{zcY7 z-d?Vjb&|K0caa0~aq_`(l$<3mk%#4Lew<^~w z_bU%64=7J5&nfRJZ!7O8KPcZRn;_e$>Z>}cTB|y#hNuRrdaE*2<5X}JLUp+UuM(>G zD!D3GrBNAG2GtSO2GuFmcGVu$1JyItP1SsLEwxOYp?H^M zrBU!(C>pJT)bUkz(bi;KcbklS>I=)V%Bk4FgtInd+>-@TWT}U@qSD{<0 z+pOEF+pXK7+o{{GJFGjY`(AfdcU^Z+_e}Rm*D$wvZV!Fe+&=m#x&B;rZeFe_w=~z6 zyC8Q{?(*CM#(ZPg7%)0i>02WfhFBC)xx!mwhXn5v`n%L zw`9QvTSi%U7K$a?LbVVrITpP|Xc1UU7NZ5STr`_4s{>Yx+v2fQ4=q`OmWZX$61Dg( zaZ8zHgmsj4igmVijumc2T2WS<6>B9}X;!+GZxvX1)?6!S&9hd2sBd*yebz#2g|*yT zYF%JmV_k3EYF%yJY~5m2Gux~-hb_tOF~?`9uppY@0JiT}RmN`7>zeViR*N7+Bw6n3ed zW9Qn{cF69wd+jzmXrF5@vM;nRu+!`j`!f4l`zHG?`xg67`yTr~`!@Sg`$_v*`xX0T z`w{z9`z`xz`y+dm{iFShy#`nltOeEq>w}HJreJHZH`o^(0cL{ZK_W;1DPRsr1KD5} zj0y5VAt(X|fC^9t=7JWm01SgGz)EmCxDvbr-UDxe=fF4MYp@E8Kq=5i@B?@gtPNcU z>p@q*q0kVhH8dC+1dWGALP%%|G!W_wwSn3~PN)=G4pl<)p(xZ1@}L3$6n|iRL5}}dIdFdq&vDgc0wZ@wVfX!iKCBWj3dYC zaOfN&$0~=^0XhVZsg8aQnM3aw>Nw_LI<`7?J1QMl948&y9akM^9D5yy9G4vP9BIyk zR6l(#nTXkIt>io6SXH}jt4{gjsl zyOnn>?|EKxS8Z2a7tEF7`k2?uRnOJP^&zjmYlth$HQY7YmEr2`YVV@EXs%q>Y!}?6 zcHv!om()dcVO%Vi&{fMl-&N@XU29y&T{~TSTxVRDqAOenTpL`6U58xTUC&*wT(@0K z+>P8{TyI_PT#eo5T+Q6A-L2f|?lkux_b~TJcTe|d_hk1(H`+~fQ{7Cr$ZdC9+!bz( z+w9)tR=PoV%pG>Gc9*#4y9?Y4-D};u-Rs=@-3Qzk+?U-~+&A1G+%-L)+;7~E-LKrK zo`#o}HfEo;{wcp6i|)o=2WHp7)*}7hLUeN3CF7?jyhP;csi@l}Z1>OVRliq#atKJ{I zuf31FS+M)wm)@57x4n10@4Pp?*Srn$>*Tl3zvFG4-!#8Xe%JiW{1vet`F-=p<@d^; zkUu*gkq^(Gk)NGU%FoFc<}r3BD}fbl+?r z+=ukxd`zF%m+Le5K%d9w^m%;+KEJQfXYv*MIx$!Imiu=4*84X2R{J*lj`;Ta?)&cf zuKGUvs(c@PsRgwP>KD{0Xj0IqplJcTvPHp3U(15l1-t@DfucZFU@s^s*jKQtU|YfI zf~y6W3QiPUD>z>8L&1*)w+ikRd@88xujfw`bnU$#3_&{7%2apYQkjBmR)T&|l(T?w{vh>0j$V z=c=D+9vsD$qR8F3=*-G0-K@Ap}`>_G&7VPB7|5WPDl_^ zg_NQEkS7F&=7&~<)`XUaHib5ZwuSbD_J)pzj)%^KE`@G|?u4#|K81b`y$y8^Cqga5 z{lcxn&BD|$K0GBnBg_s@4;O{A!n4B2a9KDSj)ddkobc)J*6?@XC*dZMs_^8jTC}8SRnd;3?L}LQb`>2fdMn#sbh79~ z(Z!+*MVE@M7u_j(P;|E_E!rzOAUZHQF*-Ynh|Y@YqU0zwN{P~<+^8}tjuu3VqeanJ zba`}1bX|0PbZvBFbaQk|bZhif^mz1W^kj67=X$hJ>|*poG&NQ`RyWon);QKI)+E+C z)-KjP)+YwUM#jd*#>FPbrpBhnCdOvO$T5119plFMv2$oqOcB$^oH0|(9y7%9V)?N^ zEEp?`EsZUXEr@N1ZH(=Y9f}=^9gkg)J&hqMU&U@2-o}28H7RabJfgUJaa!^4;<3e3 zixI`Mibch;V)-}X|Dh;W7psbw7q2N^SG>9SK=J#G!a7 z9*xK1mGQaprSXmNJ@I4lt?@(g)A6(MbMbreyYc(+3-LSgQDv{3YcW%bKa%LbHnD9b48UY1q{luaueTsF0ATv<*Ty^L3;Ez2!?RQ6NZi?Vv< zb<2OOo`$S;d7ttgT zV!5*1Q|>BXQ7$Vtl$Vw-EMHc>zWhM>-tz6`TgtbUA1XgxzOVdB`T6qqlHUEZdBZ^cu?`U;(0|D>`lenigy(sDn3?xs`y+{r?PJ4ciL8!X_fsd$5qa(L|0-f zS(VkUwUvxYZY8f$Tq&&7RVpjBl|_|hm2)cx5)KQ9LALrjszmWe5lYHU5=atA68QHd z;I(x0Opmz3*BwU@+vS6}NBAGYAGuR#z2JA?pQFqCFh6DbnP7Rpx28A=*$2#rVkj&_qqp*!hb`c3*pdRN9PdNamw2EZt0 zv|uh~{>-AY%h{*c@aoCQTX9Eo>v0EgJ9E2pIb1xK$ZcMw;+Amda@TWrbE~+GdA&by zdE0qt{vKWp{$&1Xev2x;pk-CD;BNJlup;49p-N~G-WA>#UJ_-A$>Kb*OngkGi*dfSRfHs4LYqG%^jSEz?$L zXAO@G9jkscR2Vx|O*fOx-dh5mHTk~J|-uRjqXbZYko%VOH%BbQ6Zw7l*wF>nNT@8I7x*2*JdKS7LdJw7| zZW^v19u*!R9utO#iD6WDWSAFT64r%t!;iw>hp&XsgnL$94Brl)4`)QuA|J!Osyas! z;ZBj75qSh3Sr|DKxfyvM8B{o>aC%|5==z7=Rprq&(ahNB*reE;7$Sy>;bQn=PH~^A zzEwR-`c+kwz)P=`UN6@>p_ECr=_J0P5;-78)d=%*^#6F{o_X8#&z`1 zj$Zw1#*MOI|Ln-o|Ne2KZ^Qn7Z}jTh(D2_|3mELv|M#na|IaKu_ZNQD#di2#JZt)Y z&B?c$zoyKt-oN`x-ap%><$ox__E+`)V-@g!R+D7CB!MJ>B!Pc_0+rPsd-JM2`4&J6 zp+(SQXi2sA-m+@%z7^0)Xce>?S_5Ul)!SE z9fS^5e}QxaItm?wjzcG)lhq!8r>o1KfzCqbs@HbA09}MG{i^<7%ladZr&iB{{$Fq7 z9TOZA9g`fB9a9|B9Mc^$95WrW9J3vB9B>E1fpnl8Xa~lDb>JM?4!nclAUbj!BnR0+ zaZnvJ2i+leC>%sy!HUt9=#?4x_{5Fgq*`o5No1%?LRh4yPl};c~bg9*5VF z@9;Sa9DYZ@5p;yAb<_S`{r+pslQ~HONdid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid% zNdid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid%Ndid% zNdid%Ndid%Ndid%Ndid%Ndid%Ndid%|Goq$_CNWt_pjc_Uwy~_v_j*b&X#BAe+_@O zzx}gMIoru(dN zbS!twb*%W!91HWlrmS?#{~E4xEc_a-aV+>6u68VPZ2Nk&>Fa*2V~JzO*Q4*g?$vIF@}4w|?F4`nvyX{Wkt4<*#$UrQ>^Eh8UFYw|KmCsSrS_8FQTp$<`;X^(tK0Pai`#wk zRo?6B{i}bmPD3T^|p zgFC>T;4W}CxCh(|?gRIO2f%~iA@DGG1Uw2J1CN6zz?0x9@HBV^JPV!!&x04hi{K^j zd+;)N1-uGg1FwTOz?d`JKZArT~oB#;!6L2^g|DIpc4hBS~C z(m}b99x^~i$OM@o3uJ@r5C}n#19C!nkPC7{9>@#jLq4bg@YkD0M9F}X0VM-U29yja z8Bj8yWI)M)k^varaETK&&2PHn}!-=rqh~kszr`US2xub_YlzCR7UMq z_cn8zXNm5lqcH1)NutgImA~4cnT`MDcbi+{H^HxTZFm3H<*6pfUuuU!o-pnp%uZ^X z-J|T?R7)8pVaI@v*e>WtIP;cLJ3Fzhuufq zBb`Sf`K(VgS`m$(W)aW@bz$pi_&Y{Ej#GPr+HR_O=3+GCP4mrXAwP}#jC&bbZ#8_x z98bAVx|>C=XBej&&sxs87dsMcJ+`6M-3F^U$au{1)^(lYD|$ZfJ_|1w;c+vsgh_va zBj{zX;s1?!ZZ?A~%#;1!%op7^$kQ8rht}&jXkSh-75#QoeS+VFyXvnwmE-U~zuPbK zh^MilVdP_wd46^#s?B9=<#m)S?oot2tk)SW$!<1AtP@O!4ZUD>+tN*SPO~6;4f@Hh zOYSS~_lB$PUVmNpyD}f`?t8?wN%?f#5SlygFIZFjFZNvbO~^qv)dT2n;;zd^Fs2*2 zTj1`yYmuFWxF3SMjk`V@LQZZ`mbU25%jO|@k*?l|%;PjVzS1ap*%0$FcrCr2(E5(m zZ?{B+m#Nu>w67LrpJJ?6?iXmgsUB0i&+-iYOZRiBh3ymcgHaDQ=WF*HLdgC1GQDG2 zEwVq_kp%Yoy2srg2wjg{UqsxiU~?thP4(Wr8Y>-v?mNxqoBl0(U6y@@ z9Hrb#vL77ttTDF*`mj6gj=Jx;GVUry6(fpMC7ES8!M}S%1S_*23A;S|$^FfJTUN(+ z9bbi)FYX^qe@7qXnl5^`miYb2*cI@92~jp#V%F~%|CjJLnxgqF_^hDvK1cD{vx)q! z;!F)Q{;>ZkLl$EwQkM+XVzoQnJv}-1MMF1LfL6AE8pjd$@<@_96i+u*cTW%E_aWJ<1Fzk@+|f&^h69xJ!xlD zmYHQ9HP@8nZKrv;X9ZQq3V88b&$-sIhx}+#dkLESwbHY_;}Xqlm1m8}ZlfuS^pj1XDDbrd+MgLfEq1kx`FJ?LhI1KG8k}PNtfMY6>^^=ZSr|GXdND#XMt>QNH`Zz zPDW1S9Iey)J$reMZq@}nUQiz9@?+d_ZKSpPrN2Nm^ObBik<4LQX4`1k;@Jv|WjQ>X zNjJc~ojv@fd~O3b1fy=wHi24#nVrUo)(6<9yf=3+9?zY$H0pk2a;ImP_7Jd*7%60G z_9Ps8f!bx><++Qs-R;@U^TngC1@6 zkQns{sAHa^f=iNARnI`px5jr`eRij%PG>=GZ+MQ;dR=GCF7kR4+$Z?^=gUB|y9L~Rc**kF zfhVc{wixZM=MLz#=5c(IuF>3+@VJfHV`R}TutplUFy3(E1EH}yj~G_y`nqZ@=j=IN zCkZzbSxOqeLE;3}iVT<#(_`3GYw9dH{Uv>Zd_MPdw{}`~>$aI*c%FGKYT}mT#u{TE zipi|qWS9dFFU4q*=U3on>t=A}Y&Oi&y|(t&9I%~rb~kujGi{w>wuN|6xsWAb7tzg; z=jmrue$pD&oB4D|lKo4n z&f?f|s-tX#ZmLeq@4GB-A3X1X*@`IBo-dyFjQ`}htUpJQe`d*7^xv7bWZePx5Ed@QMub4rJ_*vJ4I;`2e)`Y{An=RLD`o zP}y#hH2uA5wygkqi|oy;VE1qRNN-Q@!pu^tO&+*RkF0{a5O75k}xZ(!U9Xf}A)dDoZOweVB* zA?o=!ol|+sO)}g@?{xCJS;(}4(g>r}HbwTK55+i7Xj5jlF^IE(nuT^O5 zfxk50HR$lFialhgiMuO3)!!)bD-agA(Wd%ag^H(8+Zdwt~j zjU&J#guFpeTX1j1?IPql%{J0Dq1{dt-bAQhQF5|0dyh1}7N^%FvRzOT*)H#HvfImE zx~W<~MTN~h+AU*v*YEM}^PV^K6xw{oo!QbAI7Gg-8(i5DG}eCavyw4O(WTsBvQ^8n zbI^MPvPz1*h&@WUB44DALDS1HMSDVqI0@RF&0|iH{J2b8w3Vm>q&ZFP8Lv0%$x6}< zlz|MNhv&Sl-m^fo5h`y#mTE59xPJ1z#Jm^(;_o7BFR|`2_gAS;$#UKzc4w%gLGy(o>@dv|wGyYXZ+D;SkGI?cx1OwL+cwxv*l+Pz*LV)sWN4hh*cGG2ST~@%Li$=>?{~3TKr7cy@+YhfX7{l@-q^hNybrvONYg~|Ut`@<$fncG zzF`LML~PF?e}=me=oj8s-j`(i2JJ&{m}n`&x8B!+#@n&64zpckiFi+&-!*O!=iPJo zk9nisxHsWV3VcdXlBau)v^SK^=iss?BXkp8L$R*cJhM#aEFInq?@CSCOk9-o=*h-YM9NTe2&i-+L)P1D>h$);EOU?_5}sV9m0S_s#dn6ixq5o|y4zpb z@5$!VoANb4AiJr?(z!I9Ds>-_d!Xwn)A#W;WiL@}jAcJ_Ld*a<|pl=Xx6(v3;`>~pRSfBooUvdr;GtYa@w>yQ8 zUrg0uoco}+3Ju<+$~+G(;ZI|JBOn<@(jmTK;_MvExM#Alqq1{!jBl*W({7&oNZ&y5 zZQ5MQ`)CPBpW&PNFPP7$ zqS?M#e?iRoi%jzPzO0Vt0r!GVGMs4Gl{IWPzs!CC_uFc~Iv~4cwD|U#tUjBsz44@_9um9nkgWwPyAQX6yu5={y7u#W@5LBSXk578 z@JhG|DWNXYnTgL+CDq~ad3`U81I=G;i_AamJ?z(XKDIFF{Gd8vb;q_JnObNJ__p{$ zz8oY$XvWG;RE`5HR%5$Lvsq^G%JPb*11z@t9>Hb=&laDqXr!Ig<~{s#+svr1+FeBL z{zt1lh&6w;ARiMfQLN2g-%fF|+((qlsWSKZ4)|V!+Lvwd?T5cZB|Z;=J6s|u_$}>^ zlwi)-S~$;nR7`W!cZv`v(Ef0I7bn&J>}Jm3ao-}W$*~eYd21`L@M+Sesdn3lzTi9K z8=*bxyW+d-yW~61wyo4(WDak$$iPoAVrks}%pHbR>231n!`=s5!f8#{dnxi6?9>H%aAyU3sT zj%JT#fb+2jRoK^hpDSmPaV4$UdGVZ!_`XraN)g4ys3AJjW4@>_ z0a=Dm_`;mmbL~j{V(hu=;M*-dXpAj{P5M&458^Z!M?0j0yk~rAUjQ+D5o4`@_MPCm zsXq90ki3^kq;Woi-)aBkJL~vdrYS@v^@p_Q97F71ecyl?XgI9>?mMoZ=IZbIuKfwg zR>U^QaDd`^O&K^SVss0to2tY5%Q232&|qY76<7H$*|^JXZJgg5czVAp%g=>IqiKj? zX2~ffMfcnH$5$sZpY{E44H9oeoxU9TpGm9H-JhRTFMn@PJ#kNQ95VIw_wn~&4W3y3 z{zO->WRQOVsDb{$Xg6ryTZf?c>c4A7W5l8UKbX&R%w(8$X{cH;(Z)Ifl{~>)H>Bh5m z07jibUM8?)7WtV7Za->f68g!cnS$0yd9U(M1zkb)15an}#ut zCTopjI_VFaX5f6D!PuGTKU3Ykp^VS*2Q+)kv;DLDQ}qw9hvxg|0#W1N;fk?Ok7=HN zu5B{cL94CKU(3GmmJX`kA7^BK)(ic9$4Wvk^8XU6dfv8!=6V|O4W+p(_7C9QC)tg} zUKz+0mG|>Q+ecXECHR%dzr;A+If3F2YF7Hsz?+8r;#)ltm4yBwo=JQCD_Ap>{4FPL zDOxX9a&?JSVVpw0-mmdD0I`Z9-sE3R5w3$|qd(zVO6&U2vW9)E(KY(_nm20H{-2u7 zEIWWXZeY6LwVO&?BGLPuemhAlEI0dqVwYHnI|vWMsOG%91|GkTG-ok;lYcGf-x{0W z;jg1i>@*zL82oO(%YO)#&6Z8#9IM7U8F_?aEXV_70e{GU4*sO;jIlMl!~fCh6WHyb zej%e<{o67-2rzy$fTl*^i9{+xS3@g{nmKs|NQ-xSQ zn)dl0Q>F`&d_NQWa5u1R6yE_*KIG#DD&~ClLE|p}PDoaucBRYjA1U5;@{-GzGyaR& zm6qc`9q}JU8#kWtpGKd*j`@2duP2E=j5h21L-mEf>++xTKg3Kfab6Ayo6ou?p5amL zh3qLI@20xoZ)5ICp=ax>#9w9(Z-@SC{`3AzB)yLI22rhkKjOdWe`FbMIOrcGo+wYC zO;PpT_TTZ}CG2CgkBAC5k0JjLKu_0?q?Ncw^5d>{|D(o-pl|x``=9!!>2Hy|F!$Ab z77q|-@(a?xVN?)V{pET~+$*%tabL|o^S@?&!H?AMr|1r2{br!f!v2@QL>TAe6XF2x z$_&eoi`q<)B<*iDB>i!J%-`XU`rni6kJ!ob(aPzMg#EyN%e6bPGrmCg$)E815zA-L z-~HeGKm1?)Kg(=>`G5PNm}u;4UP)2O8k5N1!m? z2VSq9Ea?>(uj>uEPoQt$F<0m<%Eeo*v58Ktsh_aN^W1zU6~;N0MityL^cR{du--u# z{zQHTlBNRfAfg5c zHLekXk%6%Rt!-3bgy9v)g86(6>b+bej72=Tk z&D!qf*@5}6nu9xltS<=kFly)|E#Uf?CP_NuT=FeRml@{;E>gZ`30bpw0;7#GY%p)qOtdTuOqXS5CT#9l*O0G#9@f%$4UnuS=`o82{RW~p zQJcqAIlf@Vn^`iDLi6S6gLLB==AY}A7ODMM}6+{iYvX0|x*@}m@5y|9!drx2r! zB?juX0gFH^6jZ?)PglsSEN`>xN}gpp$W5%9#q05jtK{Whs|4RGFuphf&XN+ZIN8OX zlTdb8tmCsq;vFR(oZxOlyQRx`YK{oIp~NCT@+hMhQjgFKr+T=RJtB)`n9av}KY9~t zb-KMLPO(oIt5y~fzFWhpY!3v5w>hpIL~ljAO-L~h%Wa<97Dy{u(}X@GL+uXi3G}tK zkffKfS!gCw{p|z4GjIs)LEHyedzkv8flsLMBP_#vyrAUyE~k$%>Uh8`!=DPAlyUCB z>A-&Cmy5TNGl8>#*1);I`9LS0XrpQ6vyOeTmAFl7a6$OF9JrIMM;_PmPP!Dh7+7S# z5;(&AwZK)zp45(}ah}N5V>Yj-9V1)^Zoj!7v}+wVg#Y5qZU%0#^tfZS?=rj6iBbIkmh=!0}lJQ4EWsGVovo(jqHz>B~i+UHr@Xsceg+Soug zt4#YTE_{0+u!R|K(YzJ1yQr}-hBw6THk?F7v}a#~I|ZuMxr=w`@W$@>KHtPcc@V+~26OMx28 zSxb;~h^V3`@b#4A=m=y2A4&fS?YqF^Y!B`Gz=yy?v0e?1Ir`6pc%D57k7p2}bk&Qe zh{Rn%J$(uMAlwbj*T8q8B+WOXbZmvc2DM&l{26$`!9Ee#!bd-c3TGrv$7`){wgduH24gfZBD0im9w{TI9X>X7j=-242}tohU^zvtwY{N zfEy*o7)z8#>=>WxTH_nTY1H#e^6`aMVgjM&BU9soyDj5`pG_~F6N8h2jjjl<%v3^* z$IKSnD}#F5t3VhzU4ZdsirT0G=B(+W;Gu)$H~7iurvOnpwg5!9}2=94S7HWv|kHJ&%kpVapy|H;aR2 zd!_Rfvh~9}g{!a~wKkZds0-FIz8?JoqL-qbM^p{kg~8cq^|1Kqylng`b|yaW5p8l- z!FM8i+j`wL`(Hn2e5M&5Hdlz}q%^zbG|~ivzoZIQ2JPAg(iG}<4Y)6yqZ;iV8heiR z4)v>o8}&7MgDr`StN`vZpIZ2CBDfa(E!{wUEPGm8!>2xeK_TD23>K`y7+M3oMUf0| z@|?NC$i?0S#39WF#^vRX;70Im$fh3sT3IbfdOKvB8GpD@L)1jhp$?oD_oko)?KxhX zciyDlPirIDH$wB(+Ecq1HtRr}gAJ4?W6%oDi29XZozNYGe0uhp(-q8t3xZ2golL<@ zL&2@!cLY6XE5!L_vh5D~A=!yry0&ni=f;`$5PwM2uq59VJR@7LTDOxhO~EIWc{gz< zoq=Ev^A)R&xb4*Ded7BP^S+=(8xoapAm|P52ckLXL%SDuiwu8`>D!p^Hlk0lJ zVkQOeQa@MZupo6hjt8&PKEbXHR)RVbYzv-;hYz;aU|N>T3^H~xcnq4Wx|6}xyfW+T zr-L_8L5G7!gNJDRq3#vh6GUAIj*{g=8Zp7EyqfmJ140dRKc@a2t;l%uBjWH3F-fww!Dl2(pp6NeH-eHdufg3#-Zx6;Drufm8y2W!@SFX;;82CZj$oX4JM6|{ zkG&u+8f-;=?>K)3GcxoR{Z`Fd%4j>JA4F{DO&`Jk2>vo!Njtb??cYK7Df>D2oje^C zyFEYGVmnv&l@NJJci?W=zOdw*(0ml5O1KZf&w~FXFgTO4>$I~uimXhY_x(GVLXH0_ zk#`RjB3Z`rKj?G8&Jxr>p!(r92x(to*N3Q{g2($$uy?4Jj4zB(=qsS>Bc9KabWrFI z<)?pW0NH)T?7r~~ciT@W_cP$7FI;?Bn~f;A%rLXwY?-s3}?^&y*%7s%+^P#tsi=of_+h8BmmYvy1!OGw_wI9I!rsHwJ_-ogky zb<5ZaPgYPJjz-?;S8OXnajffitnnXuO0~0QrLZV?$@i;6t4On!^=tkCS86434JF71 zgQ1OOl5)=*=@~T6F-KM*m+U{X->g-p2KHKRa~X4O;g!Pk z6eF}!#kk?)XZEvgb7-<*A+oBGjcoy~75wk)d7N@;omEJrF&gRF)mvvKsWGGrt)uGr zh5WYidGOSxC#@Z=E!2}N_EPMp42F_l9<&-A$TCtmCfGY?@;W`TA=5R`Qlo9$%3^8afOg^Ge?I4ulRtHlAiV z#V{QEe-cJeJ37Uz8fcVW+6m?(6hYBnfjS9!E_;FB7={9WOdt<}Iv(ntld!L#vDw;W z?;HgW^1cUQM^n8nrnt_MxAW}t0>y*x{J6*aN~kS#j0jT_$~n|tThVpiLcu@*zG+^NvD(0E%PiccQ#QRH8v zy=S;+Iun}8St#h|qW({lH++W?GMG++e+&M3$gW#}Ogsv`4()3kuIUf2CotP5p*@y6 zp?je!ev>Nr!7n4BzPXpMtN`*Md&K*Mpd{pO+C9%guS%qNYr&|OD6(zi{91AkZQB>xF(Gtw`R-P{Isjq$Fz-;}u51 zI}r4v!eeBp@iH2JuYk;tgk%tV9$TVaum5Ek9-cteHm*cd96_QchbNM@lG>?^oDkL; z`jPDkS&s49)inu-s_-{tdkUxlxCiGn>AcVBY(1O$namAAd_!?pgP+E-S?FglJ)f#% zKDe6j9JKSo4{Qrqm-p+izOxMDS#IakycUT15>#_{0soee>?W8q~@5d3yQR`T@7X51BSB@y9mz809@;Rd}k&oip;|)+I zA1S0d5y^(|K~%zefjYwe@L9F&sZkmS_NQ#`U;YbrOl~a3`$HMf!v8N`hrFLnVI7UB zr$|PN$neyHyurRP+!($JulHy_=pnl&-W|&$k@(*w-c95i-}s>KE6#iaOYs|y%gl6B zN737YF0-&O$|@`eQ#?f*yU;j@8jqQb5EzHeCG;Lp50MQgdUx1>dE108?{B5oDWc$VPPNH~E! z7_f^kqwbF4KCBrjKJV3o-^HU8V#RwLR{EeA=K`M~TlI$^dtf*cJ}h)c1y!_$Jxh=O zMLQXhoDlMpg4#wkbQQChm^;nVZ&WR(1ZEP~@NwOl@Ht4&3Qd0WR`B=W=e&@oFxnLC zqJTKNE`%?J+k{@Sdq-7&)pmkUI{8d4hX-0O5qgwcEz7VRgKwlt{1tUK!dF@IzZFoM*l|B_L;K2N_b zd*a~j&Go8myf@&hX!YNMx+fd$Wq4|C9A)CX^)*{f=Q^q8zA$DK`uBvL22GgJcvqmg zT(d_=(#i6fWStTy{2oR)$=gQEEFKQHW&pFlWQ_`A{agQ?&h=z?7L70`H=BCACvcw* zKXN_RW$kmg;xZzJcc4BB?%&41_aTh?5KimoX+D87o8O0DAlkXPui zUx+?U`{lck=STV>_@Hdg^APnMq7Y642%qj3@XtK zjtq?qA&CdM8xCq1ahEWkg*ZS#z)3Q+5&yFW5GScC#zjlHP^*yb-*<#G9j|c+C)Bg zLp}&6er05jYo2}zY$it@*{je`#a)|wPM^)bn`VNW7I|l@Mqj-8(2kzNvgwf-pk_yA zMS9aSWU8eKm0d}g8kyZ(qUXsZ3qa48@k?YodTAtSuY+zO=@&;PQ`}1;iz2OD0kx5O z=%!-KYjln+C*(3}rC3*hYBKJl8g|)Mg1bRa#MO)lxmF1*-iBmvS@;eFnhlYSkwvm+ z=z7T3;a(G2i?#u`{AvWh3HRnQxg1lVH4$AzA29%FB(%1RjhQ8;5{;#VyTrTC9J_gc(zJ}PG^RnK98I?B|Mh?(DAPMF8x^U<-$c~~5W_OkY| z{RH}xggnLg7o4|;=+E-{YpFWU5JFAWcAeT*lAMd2jpPu^6>YP4HWcSqq%ITsLZs4s zkjH3?T#Q^I>3M34SUGhiauwQrh$X`7yHQq`OLN!$#kT0@dgPW2w;B8CBJy%OvJkP{ zAk9sgzG#=H?g`!9$Q?nKqS{G*pV|lifWdnPG!KRL7M&RdKTAxPsj457{ur&>6QZA@ zeHnQkd4c{JNeVW2bC&V1Wpn}YhGcIe$DCoA_MImcn=I<%GJOJclm6jfQ21>yvYe}aiS3bLK95)QBT>DuE;Ur)dHGVVV*JYj zna_-D#5`_A*?ubZdPBVPN%EB?*n_U= z2Vv5%9*P~=0gv_cN#moiEkyL0B{xt5Pt9M2{+poiJ(r;8qxS!R`%RJ^{1nJWelQ{z z`6;kZ?B9w0B_#MZE?OA3yzd@u;QiQ1_zXS$Bvh|1Ha%H#Q?HRn@!T9q`umz6 z){yYlP%@A8;6@2A1@B(nXp)U(%{cV^DYo%4?1bn<;-2c-HJ5DtOdCq(i(f7zE7_V{ z*Hlv!lgTPW{t6>bN6b}_PmO9IuQFGHZlD^TLTH?dGEW67d;$`6(Z6iRR+HUN_?Q;G zB0DwqQeE|QOpnfpE{66Bt;?+FOdhA`yGVVYnazoQ6r;^!bWQYuX1;!IbcVr-Rf;?2 zlY9}4QOlTn<^`IQnmxi+^1I+Kqt!+0qd#P`TnNkp@%FHoEwrezO*Gdf(Qni*g(iy` z-a<{hF@NJ~S@xF^)K(qxydt_Px;(nFMBhVJyM=kLj`m^cW?j8&tqi}8>A~Xda6L<$ zT6MGm^v38Kw40*M$nIuPjkq`DzIwIjHMpfq7uAD0;xeH9kiKIwMorPBnE!E`Il7Um zw4Ze|dJFUutyZ>@EVpCcm7dksL!#oYQl4zUY{Bis-3W{$x{a;u=@mJ zKJtQEBQm|hya9FUXUnA6P149NNPW=&>Hhp>UrLy!=wR44**)<6Ot(F{73d@OU~~=s zQ98bx!u`F(@;Hwq*-F<=@VkU;FQ^vWyQ6zZ)*Rg-bRj_%Z1epc$3tG3BS0L)eTKBJZFU;K(@K1G^4 zke`dTBLgd8eKLBQq-WTw;91_clI|j} zs*JnEbX)YH=UVgvaW`dp$;W;0*D?P)EWb5o<^Uu<_Y@OxL=eYUq&x8|0?>XMDw-y^>GTmWd8!`5N z(ng^FBSzzw-`7xIF&^Olju?M~~{T=-ghu$(1d*X+%yh@Q4vW;)hN%I@+AKY2o z8&NO0=mHu+i@jcfyL${VIA<9;35|D!SR8YoNHZOQY)IF7Q%|7Ujk67#j2hihM-On) zHPbTH`J-fCO47~7m#E^tvDdDr(DjQ=#Y`*M;=XCW!1pIvh3Tw*mZf)W05~n3V0~h> zh;VRhcudE+kh~6J5BSY3rUPyc`7yXoH;y2U4s#hQF!;uT=zwiVY#^w9+9;yHIZ?>2 z3@OPA*C?5M4AUcJvO4`C%ea`4)@DY`fHl`He<|)v1S3$iFr(m&5qT8 z{$-s{Hgl-O_t}mcbROLx&#&m|IS;yANoCAsv^27b&b$uW0+ua_)y9^}^!S`x!bvth zitoB{F*NnDWwAO!OcPIv-Zc7L;upo%k#-f@wYXQu8e%KaSH;?CJ#N6)8bU0m7WHVU z#~KX~-b|QxZ}Vu&2GVbeZKi&GY$M|f`CAcFL!ymoNbaQ=2FU6sk86ZhAJfH5=q-et zXf#kS>8&waY!ZH*vqR#IO|Uu9J7TVw8@)%Md@;YE3!^Ljf0TinsLTNJ7W`}OLXeuV z()nvkY-?;AB->+6gx(q3L47l|1=OzC?h?KwwkNhX_SUeFR(%O}*&$SynJQ@>sCV{# zv3F(v;uR-->>#{sbRCEtjvWHE5PRha`cA6y{8&e2n zYZurDf|AC2Si%)z-9_HsiPP>eP?cDnM93#i^TfCLzEG**jRU5pcAoFEE(I575{~&>|}SdZ0+%#3gOzZ z4i$JFcEr-)Z*z_x=o@Kv@7ZFPz8drV5PJvAeB^9_A%#;oDV}-w>&_D26m{cQpr;_l z!nF*T=luLH$i7n)pJU%*A3=SI^`U$|q{_=Rej;rFo9}-@_KV~vFe~Xg#nss-K1oEO zq4-bhu9|1KTbw^)59nMj^(5yO>VB7vm6h>-WONR6AIxg97z@APidpuI%e~@z4Z(Mk zkHv^%qoX&Zz2dcog|heAg54-#fzQnG3c-D(8TAA2HuNRw0M;F}ZgKP!d3|9S0{PJR zK-S_N1Jq!_)$yv0hGe*qZbA*{o&D&|Xc$RH#z(Mrnsbc6Nl}g^ZVW~oN7Mwgl|)U9 zkB?W{CxM*td>N=~7KiV7P{CY>fBidNyk|#W#~C@3T=xmyYroJ60pK zT0u#u&HP4u1=-QdH2t*)>1|8G=;Frsd}Lr6Mt+1$_Z27KYW)lBKm+X3kjt;Fe4fZ< z5^d2~<7wAR%GxxH9fa*;jUTNyZb56pZN?ojcIaH3zk9sfCHp#zV~^W_$X}kgBkmR) zKH28(I$iN6nt;|v(tyw{DtmX@8s8J&%i7&yu9DZo!sZjncQd~W{r31av|Hk#_lkjp1_fyV!i{?0u=8##o zKynoKnfNi%;T?c`d^1ASA?EjSe^+}Tej4;a=B07Zg5DqZ%g#FuKWR_MP!jSE^H;d{ zp;nv}&kR(^OWbY3;yK0r0K4rH%brnA>TK5qrZDUGsFCvpl;)AXzvBkDbGTi(t1Q2d z{sPmI-NpDxs+emmyBzQ5ycvHZ*0@!MEsT@zZ$opdM60tu0RLLZf?U^OlH6ta!?=<2 zQuOx&5ogB-k|g69^i}`(7lio;`opTb?1}k>Y>UzTCjN8$ zf|wV+y(q)v(YGx#tzL z^{D1aiKz)Ytwj~%dT?Kzm`(D@i790sDv2K!>Op^%JH1Rht&Go)=tTUdBQyT0E5tPO zU$nClkMSH>#5FJ{v0D5!qXV*&@cu_%&Cl;1i z%?CG0wo^*+c*jpn6%|~Ys7tJ5>&1y>GCzxCbh(Em&@D|o!5GUyRU!T*`l+&0Zk4dD zgtURU)roaNdQyzPhGc6KvmDRtYN0QTm$T?0Yb1FF)w~H*g>y6U8_;e{XcGqFbkyQK zD6yU?$;UE8W(U7ZoJs}HRz}%m=znz-x{(_C;IXKSkhQ=ebAy5^N`_Ko4 z6wk|qgSai!zQBC^ptdq1z`YcO7xW>-?vlxn2g=%x5?LYU30MUBFpVv>|0o} zll%Q8h)u3T;CGR1H*5BxKbSbcTr>Ch*H)m;2(CDCfjasxI=q*W_6TE6CQgB>K>bXm zU3H?wb{n{@veW8#;&kE|WM>)GnmAX2FGSFmIGLxSptE%{at<1IT);^kdUa^0L@)EAdwB=SlQbxlI}=LM^K1A#wN7 znq=ofd*W{574mQ=@kpR?;?le4E1ZKbg!BnhM=Xy)JrnYKOg%^cQb?syKTusgh3r-0 z4Qbl-573_%aptr48nWkx@2BKf#+s&>7AySDm<{)w-T}epZk#s9%?*r)f#N!hVGCsihk-4JZ$=Ph; zbBXke;Jzll3A$*3=OLuON%K>t{|@?7;)hHk+5AZyOUrE~dM8$0esv~Z>vC+@BZ>DN z+|t#H`krWe6EzIg(}$?O)E0d7OP)mrmLh-sNxsc7!(IVuKyo*K0vX6ppMj*;8LRAr zK-D5A#cMF>Bz|bp1z$swGvIX?NrzKAB6+XGVkAjNp&gwZLv+#G->AA0Yka2wn{mnU zGRx1DnSSO8GFhpoiL9AahG@l1|5zsr=~D1Z5PuaU+wi2Ef_{5$80Dif`NJ}ZGBOp? zYTQqGUmBpF20nicq-Voxt}Z7mzB%Whx~C_bs0L@6&DLjPug?&6vq8-fT;A7NLz`t5 zWY0~LsW$V{nS|2gX}J(HpPyVt@fqm}Z9qHEJuf*o*%xEZ(^b32YhQ@b@PBAf3^lTG zYC+c}7odFtKT~KwnT&n;iMj~#R?KB8ogJg0UCOo{K%X-&1h*{tPQN(0B)KzJ&$_Vr z8hs`i0;`uLb^DS0RwFCTxx?ghC2W?H-CRDO&YSORS3t6oa(JC0LS+1=xGK3hc?8H! z$z8eiNnLUSkn3<~t!v2(zTZXP-DReHG=N@1@;$kYNjoxep0b6#D6NTeg(i$sX*)%$ zVS79oLB%06utbespERP~qt_;v;M{pg-c8A6936f;f!0BITXK|awebA}N%L#>hW8ZS zBS`9$=_G`gco$kv(#^WPv}QhV2QX?N=}$J2{}Ai*o|p5y@Q#q&LYl3~X}a^VUzqbY z;@=AdW(-M7u8HK6X)bv$_+}UXThI>3cj6un+vemhLhYt@PjWBy1+>!t=QA*X>bphc zZ$GGgf@?y(9RN27=f^?xhj1Sj+9QH`MzvZP^`+^k(Bx%0LyP-ZnXG_5o~(47fbP6Z zf0F3aEIE}t18RozZ1S88)5>(4kPXr%FdK~{Y*;G3pIYE}t+{Q#lx){NG+#_!OM0vk z%;ie*YH~2D{(5q~{WU%1KiMbQF2mDIXNTryvY)%nI-T~m#drhK1B7{z>_`1i%(k{< zH{D5A8m*|@SPO*QXcLl?@ z4H0KgaUK!2Im%}*PTi98x`@nEQO3*VpTzm$zoByc@kOF%CsetD{jkjuasv`bT~NV<~R6{+F2)kGCz z$9s&BtR+g1lef2iU8*6a78*JJzlxr1UXSti8aME$8@Ug8g5q1MO(}D1bE=nhfO!hP zN#d=Fa1R|1tU-Ea^rxz?zU{3#!_9~uLM8G`xjAnLhI zNBZUP`V$c}rN+1_F_XuRx0+CDOKNLsTk4dpr!~^J6Zq!T)(*-48Tj4>-lmxgY9BJS z0=0B3w>veE_5?C&d2HN6BkZGgqiJtyfTaTHDBgE(xDG)2*?uT>FttCmA^HG20N+wU zb|iI}@DhI%)L2o?g?V-D-_n?aabg^U#Z&P#I1cUvdpk*ecaE;;BVG2L06q)w`^0$8 zY7twY&XTX=bUKXGp8|K9N3n}KSwu4`Sm0E`JkE&~#-0?BoMYP}wv=im{Yid=9_0T5&~5)>Q96>uwc9SHMw{LkSK2L9XILfVQ;!d|UY31gl%%ZsJZ+^?pEQU7-4u@cYG19w+mE2k6%_ z{(kB%d%VXz{w^=oPV{f!9ttVW`qX2=-L2l|lcJ z=xfk@O5I?DPgkRXRYwG2N13CA@U4|7ux^D{wzj z58!c#^9kBVxbNd`$6dT0Gv}lFy9e%f>NTAKizr7Da)!goI|-+vZbmkndY)TNS$Rd) zZ`jAcE_>ro${=b#Kc>;#J>8R5_;v0j?EaXZ<$9!hLGm=$j$BTsvBSomIJ-JiKWUUo zI>-8umE@&&y04%MGs$sQDk=Xdti@tlkAnU&W-u@v=18lp{n$hQE}rrhgHUM$pnJ;} z*t?JvuL?;g+p|SYp7NBPoLaD%$UH>`^UrxnSf z@G-tjJ1#v)eIX#Ir zVbd<##1ho>5-#txS|&^Ih||(jA^nLA&X8&Gu1ehObdqqXF7Z9o&PxC0ck#UUMd>+Y zGY@SI?zzMj=QCf%*9y80RK4I9rx&J|q?dtTDr7|u3ibbI22OO@xd~L(^7LRnt5={F zE;?4G2k<_gD7}Yj)4505RnV-)y(Yc3q+Zs6d!k*eU1K9z3UO}CYt+J%{2as<+$bTGYz{CC$Z zGy6?XwOffphOrXcneKtyZ%bdqy5Dl`w)xXdcn>*1K3CEkNx>t2ozfkKq#tx)OLzP| zNmF{D)+C;OOSC)Tu{pgXy#a`qhKT7Mom4$(ZJ)BQ-RTxQ$9D19cxTA9r1zxvg5QUG zf4akUAbk+jHS;NclMI*>RBPj1?=)jg&*A$B^oP?n6`1$|uu%>9?*&_=M>) zA17Tt`t7by;u$dj@kGo=#gqIP@;Zg<@10ABI8VWHy1@ToiJ-;Vo1dMWbx2-I?3 zyT_pMn;@;ZL_JBrfaDoTCH^^4Hto~&OCfs&>S`n2lGAU5EI*$pzcajL`AmBHMv04{ z4HIR-H&`!Z6&*{*8K3u3-X=(!M4KWiU50)p-YW{0nKDE{UhF&4J-No-r%z#}KBYej zn_j$f=MnuC$4ToJ?6q}<&6wLN&e|8keojwyCAIhMFSuU(=G&-^l_HnYXx|C>P5917 zP~+SqYD|*U(uhCOUkO*|(7Jw>SzreW$)9xEvQoQB`&&p-+JhMNdoE3xs3hNSc-Q4e z{DE3|!I5RzE|>01chBJ4#7qyg{~ebLtKLhD)f-eF!SxkXc_jTa{h+J(M}0Z|tNkYZ zg?xWnt>ILI1E2>uNex2bPeMk-!ElGf*ze2PLfg7{?0w;N*x1!EXm}f%IR^L@vNUf{UqilqOZ(M zWo~k2N~VhFYP4-7GnIS$@1VaJr)8#R8u;mk@3v8K#cKvdIhp6bz&%*7=!_B>SL|#+pZVHE8GJoR3C>g<3S%Fsh`>) zwcS)9?n_78@>gjoW-Bn;1a3P~O_?3&cj9i&?8@xU>|y=hObe({p?%C3J^hT16m{NR zd(dzovp=()&z}P7Q08#vAS{oNwVJg@!TE%30sBvVZ~Eq;CvtTx(*x~4T_?IkC?U@_ z_JYmH%x=eV(x1wlF2kM4oGp`_18;N=!m0V&FogC(ZyL8%;4XmbBVsu(I>N_sC1$>V=GcP4uhGOPNeU&2~J`d}(|GX}CmV(%#C9 z(MX7Bi5%~(nYWoiT|S}VmkCiB&*+ICli9^(H2&B85-uNWu}wmo`d35|`~Mzw3Ykk| zcE|8M`H;!*JUgf#=Ddg;-Yq$cCe?nmpzgNq!1B{>q0n-&yvJ z`Y&jGsG852gT`h?$VVyC>*9Xvjo+@b2v!{bo4`g_bt)k?Wl||`tJ`-Kbdw_*>1`s2gwix+rdIM1XKlcUuiZ& z!M)|W9tnC>#|YL-*26o-f*Xc=v`m`!JBB6WWtwp^x-fdapID-q1a2}(X45H{$4uzR zSl&_gD@)L&p8ky+&^e`}ifpI;AA0yV@BekWYKr!-ei}zT9sNF>s544tF_XAi9kYdW zZpWOCiO66LBp+m-IOc(WF5~BS1nEs~K}Q|g)(a2vIn{O;47Z%?oj-hd{|WiT$+lY~ zN8#7Gj#}N~jwKySI|g<-uwKj9+k^0P*hDPLJ63kAfNYf*Wi?T21TXnpE4X!_8amWy z*W=#Mv9V*5&=p7C+|ekL_7dmCOY8%!OjER&XVLvtuK%mFVAq{K8yo%sW9%41{}aix zJIu=ok z!4l~|`BLOc29yja8Bj8yWI)M)k^vc;PpkzSFfRX_v14;&z3@8~;GN5EY z$$*jpB?C$Zlnf{tP%@xoK*@lT0VM-U29yja8Bj8yWI)M)k^vc;PpkzSF zfRX_v14;&z3@8~;GN5EY$$*jpB?C$Zlnf{tP%@xoK*@lT0VM-U29yja8Bj8yWI)M) zk^vc;PpkzSFfRX_v14;&z3@8~;GN5EY$$*jpB?C$Zlnf{tP%@xoK*@lT z0VM-U29yja8Bj8yWI)M)k^vc;PpkzSFfRX_v14;&z3@8~;GN5EY$$*jp zB?C$Zlnf{tP%@xoK*@lT0VM-U29yja8Bj8yWI)M)k^vc;PpkzSFfRX_v z14;&z3@8~;GN5EY$$*jpB?C$Zlnf{tP%@xoK*@lT0VM-U29yja8Bj8yWI)M)k^vc;PpkzSFfRX_v1OIa}5YGP3iRJ&_NHV$q`nj32zN|lcDElm%&UR$SI+@_o+XUzq2q1=|-?%bi=k=)VTiQL27i(E(UXYN<-Pp+c#zdk}`1SJDX z29yja8Bj8yWI)M)l7avI3{*6X&DtBx4YmeH!Wc}4XYb^H&iwZRS#1S zSC3GSRF6`RR*zASRgY8mZRppqzM-LELqq=tS3{M0s=8V|O+8&bLp@VHOFdgXM_r?y ztDdKxuU??8RoAKO)eF^&)Qi@)YyOm?3+e*X~Is;b}jmdjF=O3r6lk(AYv{(os;hUH&hNdqjFES9X6 zB#YIO&63@c!;;gI%aYrY$CB5Q&ywF#z*5js$Wqu+#8T8!%u?J^!cx*w%2L`=#!}W& z&Qjh|!BWwZY)P?HvZPvUmdchYma3L&mg<%omYSAYmfDs&7Qm8bscWfcsc&guX=rI= zX>4g?X=-U^X>Ms@X_;A~R+iS5HkP)Qc9!;*4wjCVPL|G=E|#vAZkFyAyTxGvEszDa zI4v%V+k#j;7S!UkU>4lsvk(^2;U3)@TBE7&XAlkJu4mF?B+we5B6Y4&>d2KGkw=JrbTE_TT7wtMWD9k&PVAv|r}+7wn=vVvpJ-yKL9&hCOCC?Qwe#drx~WdvALm zdtZBh`vChu`yl&Z`w;t3`*8axd%9(UeVTo`eWrbmeXf0;eX)I&eZ75yeWQJgeVcu| zeTRLgeUE*weV_e={fzy*{eu0H{g(Z<{f_;C{gM4I`!o9s`y2b;_P6%;_D}Y2_V4x| z_Fwjl%*HFLBgtWPWOHP9IpU5Uj-HNQj=qioj)9Irj-ifWj^U0`jxmmLjtP!Qj>(Rxj%kh=j+u^G zjyaBbj`@y-jzy0D)o%Zn`7Lp*cC2-5aBOsJa%^^NacpyJckFQNbnJ5McI?c06!Aay)T7bv$#ta=doDb9``o za(s4taeQ@rcl>nxa{P8AGJj06fLXyL&b zSOP2qmIKR!6~Pp+5||2B0c(JDKmbew>w@*b`d|aFA=n6P3^oCqfi1vvuoc)EYy-9f z+k+jz&R`d?E7%N z6`Tf62WNmY!CByJa1J;ZoCnSa7k~@FMc@)}8Mq2u4Xy>(f$PBy;6`vWxCPt_ZUeW2 zJHVabo=pBft-atra6fneJO~~F4}(X*qu?>{ICug)37!H^gJ;0A;5qODcoDn=UIwp# zSHbJx4e%y-8@vPF1@D3P!3W?&@DcbJd;&fNpMx*Jm*6Y#E%*+64}JhYfnUI{;5YC) z_yha}{suF^MCK_)7APx}1X-bMP);b_k_*ZW<%RM=`Jn<(L8uT^1S$#@gNj2XppsB2 zs5DdtDhri^%0m^Picktv2}*@*P-UnJR28ZQRflRoHKAHiZKw_eKxt52s2)@wY5+Ba z8bOVrCQwtT8PptV0kwqMKpmkjP&dd9IUo>%At&U4P{<465CM^p9|}Me6oP1og~AXI z36KnFP%o$-)E^oQ4S|M1!=X{oXlNWX9-076geF5%pc&9CXf8Alnh!067DLOR<!SM9fA%+N1+qYDd;S84!Qtcf-XZ>psUa|=z1pqpVkfN zCUgtB1Koq}Lyw@x&{OCy=o$1JdI7zJUPFIF@1YOSC+I7b0a@W}a4t9xoEI(t7lezz zMd4y_S-3o00ZxWf;7YI!t_)X!tHU+nI&d0X7p@OCfSbcD;dXF)xC7h~?gV#+yTW$Z z0mHBpcEcVRh0`rw7=v+`fcZp4Ud7x!sFoa@I-hLJO!Q#PlKn!GvJx`DlFl;D zvd;3(3eFT~s?+AI;;ibd=B(kY>8$0f;{=>(&brQe&ic*<&W6rL&c@E>&KAyA&Nj|= z&JND5&Th``PSELcqE4?9cM?v<$vFjQ#2IyJPSe@b+1uI2+1J_6Ilwv4IoLVeIl?*0 zInFsglYfG9qH~gSvU7@ansd5yrgOG)j&q)KfpejAiF3Jgm2o+eqjQsU zvvZ4ct8=?^hjXWMmvfJEuXCUCfb+2Pi1VoPnDe;vob$Z%g7cE|vh%9*mh+DDuJfMr zq4SaRne&tLhcm;O$h?@z>dNNI;mYGG>MH3fq>E@x@@lMF2GgK)zH<*)zsC( zmF{ZoYU66>YVYdk>g?*~>h7|;94^R(xd<2O^1A{q$`x`kuCR-D2`{A(lyF8)-};J*)`oY!!^e>&o$q*z_rlz=lx&gTIyQo z+Thyc+UnZo+V0xv+U45g+UGj#I_f&*I_Q#oZ;`CEcam zrQK!S<=o}n72L^go4c|*-BQ(E&0WJ?%U#!9-`&97(B0VG#NE{0%-zD>%H77@-rdpN z$=%i6&E4H?cRSpW8+JS0F1N>xy1j19jk^gq>Grz=?w~v5=G?qnbjxnVt-3Y0?l#;# z-M!p>-TmD|-NW2t++*G2+!NfB+>_l?-P7FD-Lu@Y-SgZF+zZ`{+>6~y+)Lfd+$-EG z-K*TI-D})y-Rs=z-5cDS+*{n++&kR6+hMP+%Md3+<&{@x!=1#xxcu-xxc%AxPQ8TxfAZJND^X2 zvLS!o|LjN(BsY==$%hm~3L%A&B1loB7*ZT5fs{f@BW00tNJS(WNkME#Wuz)n4XKXQ zKx!j(5CEx%G(Z|5jgh8EbEE~*5^06BM%o~4k#4bDfx*%N<2Ld7x0wYeu zjUWhy;0S?`h#v_cR3?82VGtGxBT+;`WJEzUL`MuHhQyH`NKd2}(iiE6^hX9D1Cc?< zU}Oj~92tR(L`ET_kuk_vWCAh~nS@M1rXtgj>BtOZCNc||jm$yjBJ+^>$O2>`vItp% zEJcEUC3@^FR~BWj~qY_B8QN} z$Pwfyatt|+oIp+@r;#(rS>zmY9=U*AL@pthk*mlxy%2V1?##7Ey-c!+&>`C#YdTgG`o+_Rio-|KgPkm1VPeV^5Ph(GWPYX}F zr?sc8r=6$0r-P@Hr?aQ42lhBUE|1%TcuYMMtVkh#(Kti#(O4sCVHlLrh2A%rh8_1W_o6M=6L3M=6U9O zmU>orR(aNV)_XR1HhMODwtBXCwtIGZc6oMt_IUPs_IdVu4tNfFj(CoGj(LuIPIyjw zPI=CF&U!9*E_yC|u6eF|ZhP){?s*=19(f*no_hZBJo7yFyzspAyz;#E{Ox(?dGGn) z`RMuV`QrKN`RV!P$?zmRSDqchI}&J@h{M0DXu)LLZ|~(ZA4V=yUW1`VxJE zzD3`oAJ9+eXY?!j4gG=sM1P^b(F`<^*&Uk2o8-;r&F;{hmrg$rPD|@SYYkC21U2i>a18+lbGw+}GzlFD@H{ILH+t%CO z+rit#+s)hE3wmL%)9dx(UZ0onl3u@;@`k*$m-U9doR{|sUeO!zM!k|(_9|Z0t9fJI zxVM+Lx3`bCpSQnvfOn{Oq<6G;jCY)Oymx|kqIZgSs&|HWmUp&yj(4tizITClp?8sY zStkE-?;7t~?*{Ki?`H27?^f?N?{@DF?=J5i?_TeI?*Z>Y?;-DD?-B1&?{V)5?@8|& z?^*9T?|JW4?=|mD?``ir?|ttB??dk+?-TD|-e=wy-k082-Z$RAy>GqmyzjjqydS-v zyq~>aykEWFyg$6ZyuZB}ncdh~vD{c5EFYF1D}WWm3S&jFVpwsk1XchcrdTtq1=bQv$68};u(nt`tUcBd z>x6a1x?$ZhJLbSZ48mZ{iMcQY^I$0E#c<4r5g3X2u>khx{im=HMq>=dVjRX}A{N1- zn1sogf~lB>=~xe}C)OM5gZ0JwVFR#%*dS~$HUt}r4a0_GBe0R!C~Pz~1{;fw!^UG1 zu!-1YYzj6Nn}$utW?(b1IoMom9yT9afGxxpVT-XP*ivj6wj5i5t;AMiYcl!QV(YN= z*amDPwguaUZO3+EyRhBZ9&9hRA3J~@#*Sb|v18bA>;!fSJB^*i&SB@V3)n^MGIkZa zj@`s=VYjin*gfn%_6U1|J;k13&#{--YwQj7H})2Lhkd|4VxO?j*ca?8_6_@v{lI== zzp&p}2A0Si%E*Fe#glL=o(<2A=fHE~x$!)BUOXS3A1{Cx#0%kt@gjIpyck{*FNK%J z%iv}4a(H>X0$veM##8W0cq(qgE8|u0s(3ZLI$i^>iPyqw<8^QVPs8is4e*9|W4sC8 z6mNz%$6Men@pQa3-Ue@rx5L}x9q^9$pZC8L-Wl(Lcg4Hm-Elkaz+oK0Nj!j4co^q! z5s%^$F5?<*;3gi&d*D6s-gqCpAKo7ygb%|<;bZY}_yl|+J_(-Y`)CVmUQ zjo-l^;E(Xf_+R)l{006Je}%us-{5cY_xK0=BmN2hjDNwu;=l2X%z>z^z9e5ZUk+bR zUmjmxUp`-cUqN4CUlCskUnyT1UwK~zUqxTCuad8_ud1(_uez^>ua>X2uZ|D!)%Df$ zHSjg`HS)FfwexlGb@X-fb@#zOr_bd>d>$X_!+f~U=OcW6U(iSU!amN&`vjlpi}<2G z#i#jnpW%!7OkdpB!`Iu_$Jf`_&o{s~*f+#C)HlpG+&9uU$~W3K&NtpS$v4?I)i>8S z&o|$U*%ipTkqT8+vMBg+veNp+vVHs+vD5kJK#IyJM25^ zJLWs?JK;O&JLNm$JL@~=JMX*TyXd>@yW+d*yXL#@yWzX#yY0KyYGA8d*plU zd**xLd*yrW``h={_ulux_tE#s_u2Qw_tp2!_ucoy_sjR&m*Gof4kM;pvJh4x8>>O>8qCQ*j~ zh%}-uQIBXqG$a}kjfo~iQ=%EsoJc2H5v_?fL|dXA(Vpl)bRs$v-3dG4AV2~lV8Thb z2seQc9>PmtgpVKzKM^1(B1nV?nqUZ)2ooG35K%%R6hb95LMLK`NyLdBL{Fj@(VOT) z^da4gcwQ;BZd^r7Vl**^7)y*J#uF2WiNqvgGBJgiN=zfB6Elce z#B5>?F^`x}EXd^l(^^O@A{G-%h^53bVmYybSV^oRRugN8wZuANJ+Xn?ZaQdx?F-e&PUekT^sfCXNuth~vZw;v{j3I8B@(&JpK{3&cg@5^_-kH2a$uxq2vg1Bsqp0OO7Kaku%8I~40)D3N1i7ykXOj7wA)k_ek){W<)({CWNP{Q3O_{e}HS{l)#I z{H6V6{pI}S{mK3me-y{Y>-!t{8~Pjh8~dC2Tlic0)BUae zZTxNh?fmWi9sC{ro&25sUHo1B-TdACcE7_9`CWdmAM@jWpP%&m{Q-Z-&-lZB&M*2U zzwFoihCk*v{XP7>{C)lX{Qdod{lolY{p0-O{S*C@{ZstY{ImSC{d4{E{PX<_{EPgH z{Y(5y{mcBz{VV;e{cHT|{Tuun{hR!o{agIo{5$+R{k#0T{rmj;{RjL9{fGR={U`jV z{HOir{FnV#{8#Q{ZIXW`Jek=_+R_q`rr9K_&@qT`M>zT`oH^s z_<#9x1pd7LIRm)@c>;L@1p|cwMFJ%PB?F}cSxk3N#Kh2{a9~2(%2e3bYHf4|E8040H-~4s;203)lmW02FWrTmdBD37`Qy;0ure ze;^Q`0!)AnNC7pV1&lx}5D)YV49Mgk7#I{78W>6u2C?61Wz)9=I8}9k>^G77Kp^8$)sS;F4suWd*Dod54 z%2UZy3T30JQq`#HR86WDRhz0q0aO}Qm#RnAry5WVsYX;|stMJUYDP7uT2L*iR#a=M z4b_%vN42LqP=DV4j#Ou=E7hHHP#^_UPRd0gl!rnoFNIM!<)cW-PX#E73Q;u0P%On$ z0wq!rDoRO|OsSMc>6Ag4R1c~r)r;y)^`ZJw{iy!b0BRsLh#E`{p@ve!sNvKIY9uv^ z8bghx##0lhiPR)&GBq`me;PHNnnBH^W>K@LIn+FAKDB^aNG+lkQ%k6&)G}%nwVGN> zt)tdc8>o%cCTcUah1yDOqjpd`sa@1=Y7e!S+D{#z4pN7yBh*pq7q3HZR!qnm%2yYryfubsYldf>IwCfdPY5`UQjQoSJZ3j4fQwm zmU>6Mr#?_0sZZ1w>MQk)`cD0zep0`v-&98CEl*j3S%XPIYcN|dM=)2gNU&(IRIqHY zT(EqwVz5%MaVMsgL8s&gY$xmgUf=;gDZopf@_28g6o4Df}4Vy zgIj{zg4=^Tg1dtIf(L>JGx-k(PY2HjF9xp$?*{J$9|Ru;p9Eh9Uj^R%7!Y3s)VYAYKCfs zYKMSOTBu&AeyBmHVW?54aj03Sd8lP5J=7}HI@B)IG1Mv4B?N`wkTc{8At6r)4S7RY z2oL!}L?{rVLrjPbaUmfjh9V(3q=dAP9x_6)P>)d0P@hoWP`^zXy|z8MCerLbm&azV(4<{O6Y3ndgw;zX6RPvcIZy%Zs>mKQRqqN zY3Q%ev(WRdszbS^qKosZ5> z7orQ(#pvR63A!X*iY`r;qbtxUbR{~KPPf?TDs)x48eM~~P1m6TI*qPN*P|QI4e3U7 zW4a05jBZZ1q+8K#=(cocx+~p{?oQij2My8??WEl_LVIX0jnO#mqY2ti2WW~8(jl6r z8JeXzTA)QbLQAwvE3`^$v`!mzj5g^w-J9-1_oe&M{pkVpKzcAej2=Ocq({-C=`r+J zdK^8ToAmzmdOv-TK1?5>kI~2J6ZA>?6n&aLL!YNF(wFHg^i}#AeUrYG$^WNyo4!Ne zrSH=Z=!f)U`YHX4eonujU(&DW*Yq3uZ~86$j($&npg+=|=+E>Q`YZj7{!ag(f6~9` z-*g6@ptCSpnIy)_WMi^3IhdSGZYB?tm&wQEX9_R{nLs!TPeI#ZLW#Q;niQ&P$nJ!FMraNP2Kn7-sv&n1TC_R zCR>{Y*t%>zwh`NyZNfHXo3Sm}bhZ`ShHb~TXFISR*-mU{whP;xwX+}#u_&8){|Ae+ zK9*ofHoyki5X-P(mS+W4WFu^pRauSI*%;e{?aB6L`>=i4{_FsDAUl{H$_`^kup`+~ z>}Yl@JB}UCPGBdoli4ZkRCWeClbyxRX6LZ;*!k=Nb|JfnUCb_Fm$J*)mFy~ZHM@pg z%dTfPup8M;>}GZ=yN%t>?qGMZyV*VLUUolwfIY|_Vh^)N*rV(*_BeZjJ;|P8PqSy( zv+OzcJbQt?$X;SEvsc)w>^1f}dxO2j-ed2x57>w7Bla=-gni0BW1q7x*;njq_6_?t z`<8vrerCV0-`F4QPxd#PC7d;!6#mohr(3MyY~k$T9O1m-{NV!OLgB*UBH`lUlHpR} z(&4h<^5Kf%G8J-=UA6^h%7+w-y7G4=%6J8hI z7~T}#65bi!72X}*6W$x%7v3K}5Iz(>8a@_29zGF189o(09X=C28$K7l8on039=;vE zAAT5q9DWl1EBq|{Jp3~JD*Pt=clbm2bNEa6YxrCEd-zBAXZTk*BbT?aa zhFnvw8JEs=a{aje+yHJ6H-sC`jo?Odqqx!B7;Y>#j+?+ug4tJNk$KB^1a*wzt+*9r^ z?iu%-d%?ZrUU9FvH{4t91NV{p#C_qua^JY0+;1*}OJq(?$jT@2Rz5qQgU`w5;&bzP z`2u_)z6f8GFUA+=OYkN6QhaH?3}2Qn$Cu}m`4qkqZ{sWTRrsoWHNHAugRjZg=Iiij zd|kdC-+*t(H{u)fP5EYgbG{|tif_%g<=gS?`3`(Xz7yY>@4|QGyYbz5JMZ8@9^zr% z$-8-kM|m%g^FH3s|9Sr@KFHHN!-si}=XrsT@KIjo6<*_Y-r!@r$@k)W^L_b#e1Co* zKbRlNkK#x3WB76Wczyyuk)Om*=BM$~`I-DIel9X{04p#znS04Z{v6HJNaGw9)52o|2}>{e}F&4ALftnNBLv?asC8I)5p zMnYquiO^JNCNvk)g;qjqp^ea1XfJdSItiVHE<#tKo6udb3l0GiV8JQ41h;?)9sv{n zy#GFd5J-H!U8Aof*^=OM2HHKAPb713A$hiF~Jn#LJy&r&|By$^b`6E z1BF4tU}2~*Oc*YV5Jn24gwetnVXQD-m?TUVrU+AoX~GO)rZ7vGEzA+-3iE{d!a`w@ zuvl0kEESez@-G)w2&;s(!a8BSutC@;Y!WsLTZFB`HetK4L)a5?%{$gujKi!aL!;@Im+}d=fqjUxcs1 zH{rYRL-;BD5`GIALLzf&Qx-9+m?T=oY+`mXhnQ2$CFU0Mh zVnea9*i39Lwh+_BR$^Uh>Dnqi$0MM zNzpF`L`vjDUKGWM7!@T^78OwyHBlE0F(#T~Tz!cvA9HBDlQY3iz~#H;%ae?xK>;zt`|3m8^ulH zHgSizQ`{x)7WasI#eL!d@vwMAJSH9&PlzYQQ{ox%oOnUJDBciniFd@i;yv-c_&|Il zJ{F&dPsP8)XX115h4@;0BmOPE6W@y;#82WE@vHbv{2~4ne~B4lB6B)hmPpn}Qp6g` z8OasN9mx~P8_6Fj94Qeg8z~nlAE_9r6tP8WL~2HAMbaYmA`K&rB26MqBh4bsBP}E8 zk+zX`k@k^Jk*<+$k?s+D#1VlaaKsrwB535#`|pilkzgbgVIpiK91$atNHiiv8(mygFG9)rQGAc4UGBz?UGBGkKGBq+SGCeXQGAlACGB+|WvLLc3 zvLdo3vOcmQvL&)LvMsVbvMX{RaxiizayW7Q8lVX^=K?=MteqkMSDm4 zM*BtkM+Za)Mh8cSM2AI(M@L0RN5@9TM<+xlMW;olM`uK5MrTFmL>EPuM%P5wMmIz^ zMmI;dM7Kq^M|VbdMR!N{ME6GbMGr;~MGr?$L{COfMgP42XQSt$=c5;*m!g-WSE5&= z*Q2+hx1)EW_oI)ZkE2hc&!W$xFQPA_Z=!Fb@1h@~pQ4|mU!vclKcc^*8PP=MM9(Zz zRw+rcO4+3xQcfwClt(Hc6_$!f#iWu_DXEN9Rw^%5kW!?|QWdGHR9&hm)s_G$O{ym~ zkkTy;rAAT{shQMVY9Y0h(xp~XYpIRYUg{uqlsZYBr7lueshi}GKnapy$t`&#uY^fH ziI7MsAW>3K3Q4rYNURi=IEj}8DI!HBSyCib(j;9nq?lw%ajA#YQ|cx4mikD2r2*1F zX^=ET8ZM2HMoFWkG16FRoHS9IBu$p4NK>V0(sXI2G)tN-&6Va!3#5h8VrhxAOj;qW zlvYb?q_xsIX@j&`+A8gkc1nAsebRpEfOJ?oA{~{ENhhR}(kbbTbXGbiU63wG*Q6WL zP3g9DN4hILmYzv3rB~8x>5cTa^fr_KPwSoZUiu(?ls-#eq_5I9>4)@F`X&9AGNgoL zk+aB2vQ^F|=a6&Cx#c`^UOAtfUoI#Yk_*elC3UacXB3F`a za%H)STve_q*Omdfu3TSkAUBd5%T45_ax=NP+(J&5Tgk2EHgdY9t=vv-FL#nV%U$Gd zvR!t_pbW{d?37)yTSjD$?3FPYmkHS~2V_bP$+XPKVVRS8S&&6JBFnNOtFkV~WK)jI zJ>}kVU%8*$UmhS2ln2R!<)QL0dAK}E9xacTC&&}!N%CZQiab@GCQp}V$TQ_x@@#po zJWrl4FOV0>i{&NqQhAxYLS8Aal2^-X z$@}Gl@?rUid{jOrAD2(ar{vS}8TqVyPChSRkT1(ul2FMp6f%Ae%V@)!B5{7wEY|B!#mzvSO? zhMdTp)SX4isw62^C7Y66$)V&_aw)l$JW5_ApORlGpcGUJD@Bx|N-?FlQbH-Ilv2tn z<&^SD1*M{rtfVNZicP7kR8gub)s*T=x}}CvQ>mrYR_Z8#lBU#E>M8Y=hDsx)vC>p& zrZiVtC@qzArIpfJX`{4N+9~ao4oXL*lhRq~qI6ZdD|Q7`AO%*Oic4`Th~iOD#j9Wn zuJ{x}@hbs^Qi4iIp%q49m9WAoydo%)qAHrAD~1wRdMdq?-b!C(pfX4qtPD|xDZ`Z! z%4lVbGFBO{Oi(5&la=Yp3}u!wTbZZKR~9G>l|{;8Wr?y>S*9#kRwyf#Rmuisld?tG zs%%qsDf^WD$`R$La!fg{oK#LLXOy$bIpw@^LAj`0QZ6f3l&i`$<+^e!lmAcaj&fJI zr#w&|Dvy-M%2VZ~^0)F%d9Qp>J}RG-&&n6&oAN{Xsr*thltku){w!)%HA%Iq+0^W6 z4mGEmN6o9|Q}e3@)Iw@uwWwM`Eu)rI%ct)f;{tEtu18fs0o zmReh_tJYKNtLc^oY9qC=+C*)tHdC9cE!383y4p%@t+r9ys_oPcYDcw`+F9+Yc2^xL zs6r~NI#rkIRuR>sqN-QLR9q!gzZy^}HK>MEM&(sO71f9uRb^FCRn<^qs;S1+o@#Hk zkJ?Y|uMSWLs)N+Q>QHrN<73xg7!SKdo!(b@hgNQ@y3$R_~~H)qCoF z^`ZJmeXKrF|5Bf;FVvUnEA_SdMt!TkQ{Sr})Q{>X^|Sg#{i=Rbf2cpzU+Ql)Lrr8p z>LH7kRZG&WS~e|*mQ%~6<<|0Od9{36eyxC3P%ESr){1CFwPIRvt%O!mE2Wjz(k*4Q zvRZkqf>u#W)>5=eTB>H#Dr;4=YFZ7gmR4Jn< z2d%T#MeC~BHHQXjkml4}np^W|sD^1ijno2KNTW4I<1|4NwTKqg6iwB1&CpCOuJzD* zYkjo7+8}MPHdGs?4cA6!BegNwIBkM9QJbty(WYwCwCUOmZKgI$o2|{!=4$h_1=>Pw zk+xV{qAk^yY0I@0+DdJewpv@KZPYeto3*XlE^W8AN879I)Anlzw4>TF?YMSQJEfi0 z&S>Ygi`r%Figs1IrrpqPX}2@^|IxoU0u~?(kQLZ&Ihpl%))kf{ARAD$BAF;&v2w+d z6-!ktTd`clqChbqCy)!s4demx0{MXaKmnjQPy#3j6aqF{u3NrZ8m3f9shUzKr9evc zlxitCQyQg|PFb2_OR1PrxYEp&8Y#6?sFZFgol;t)luHSuNGWm(ox-G)Pic@+Kc!9O zR+Tqc>Q<~*F)7)aSYmmQc$fexF1Hj<&R#iN<HHIk^b%?`8kz_;ibstR`#8da{umOE#0^$vu*LCjX~#8Id|NbyVu;)G?`JQ^%!_ zPo0oDF?CYvg-e_HI{0o##4Kw_Dt=S+B>yRYTwj;sr^$2 zqz+6SlsY(dNb1nkVX4DY1F2MMFg27)r!uK*YB-fk!#GLR5!J*t#0MI zRq9r)TdnTD><=VU$-(4MGM&sMv&rFPE}2gjlEwd98UNGr{CaNW>Cu$^WCTb;WC+Z}CL|US5qF$nYqCuizqEVu8qDi7@ zqFJJOqD7)*B0bS6(K^v4(KgX8(LT{3(J|2}(K*p2(KXR6(LG^LI1*q2O27$c!j*6* zkc20JCcFtOfhT+kBJnu!-$(k-r~jWK&>Cn1v<2D$?ST$JN1zkX8R!CZ1-b#<0XyIT zKmY<@zzMhjH-G>h00q1N2H=1XAOI5Z0|9^nfC}1=&1{e#B z1I7arfQi5)VDdjL{r|KxorS<6U@@=+SPCoymIEt*mB1=sHLwO)3#&iz$Rcb zum#u(Yy-9fJAj?QE?_sX2iObj1NH+4fP=sx;4p9mI0_sCjsquvlfWt9G;jtu3!DSa z0~dgcz$M@^a0R#uTm!BHH-MYKE#NkA2e=E|1MUM4fQP^%;4$z7cnbUlJOiEsFMyZ8 zE8sQo2KXCz3%mo~10R5oz$f4{@a3Oc@IRpzOiY@TG&yNX($u7BNz;>NB+X2kl{7nP zPSV_@c}eq=79=f9TAZ{bX=&23q~%E~l2#`D=WWQwq)kbileQ#nP1=^UJ!wbM&ZJ#Q zyOZ`L?M>R3v_I)U(!r#|Nk@{7CLK#Uo^&GVsjkt8(1N0Lu(^zV`~#@Q)@G8b88E0OKZBdm9@3CjkT?{owdESgSDfzleM$8 zi?yq@o3*>uZgu>>r2pT}{eSkmr?Q^TdNXU0ip470DmJK?Ejd^6wB+f@Gm>W}7fY#- zQYi&aVN=2>`%^$0WP@!^o6F|5AvTWe`^o>{Uyw4BTGz)~d33rm?S&n-2wys=!! z^4iip%SX$lEFUrlZGTvn5QWLl}T(rIPV%BGb|E1y;& ztzueoT1r}_wA3_PTIIAVX;sszrTxbg|NpQ|22y}ZKq_DZDg#x3sz5bhaoutC#@Cxu zZ*IML^%mAUQtw>7i}fzmyIK#(c$9dOdB&QYoR)cAQ?TNHp!)^P2Ic_2feau!Fc+8y zbk69K(KVx6M)wSRh9d*afHL3=SB5(S$?#-&Gq4Oi!_uXv)L-!s@SU9s@baB zYS?PpYT0Vr>ev8Vnys#_o~^#Efvusfk*%?kbYiOdJM zX4S2FHa)wZL(i$_((~wf^?Z5(y`Wx5FRT~UOX{Wc(s~8GqFzZ))hp{&^s0I-y^ap( zb@h6B1HGZ%RBxs?*IVeV^wxSCy{+C(Z?AXIJL;YEbW3Nwi{4f5rrULg4(U$arMq=R zM|H1`>A3FG37ypaI;98okWTB2&gx;E(|KLcMP1SrUCm76AN|`Spy|49=rP^Y<9ZLh zr`}8Nt@qLU>izWr`apeTDzpp>kAL)F@QA`X~Lf{zd=#kN^L!`u|P;uK&<~>c8~gdWN3Jd{}c9BdcLGau_*{JVst4pON1v zWE3`v7)6a@MscHrQPL=7lr_p3<&6qPMI+g$WTYBZjA}*=qn1&}NHgjhjf}=d6Qilo z%xGb>G}4V$MjNB8(avaZbTB#^os7;#7o)4u&FF5VTkM9z01e214X5EU5Cb&`BVbTQ z&tu zG0YfYj5J0WV~nxJcw?e5$(U?RF{T>RjOoSYvEJBVY&13*n~g2TR%4s7-PmF5G1oJT;yf&y5$x zOXHRC+IVBUGu|5?{_+3cRsTO4pN((EcjJfg)A(ilHZn3F)}AGnHI@|17Rw&X5z86N z70VsV6U!URA1fFu94i_t7Aqbr5i1ib7b_pD7)y?-#7W0hl7V%1}{WA$SVV@+bs zV=ZFovDUFRv9_^xu@140vCgqBvFiF)9{}g<^Cp z9OGhqOpHZh(U=sIV@gbo>9JVMjKyQUV!dO1Vtr%%Vgq6WV}oKtVnbuYGt>A-|Mm!s zh>eVmij9eljg5;h^>sRimi=pi*1kXitUc=j~$2| zj2(-ej-82}i=B^Mh+T|bj$M!4jNOXeiQSFek3EPzj6IFLh`o-ziTxdW8~YIZ82cRi z68jqa7W)zV8T%c}h-EdcW_B}&nQqBx<}&k``ON%g0ke=<*eqfeHH(|2&9Y`Wv%HyX zRx+!YRn3}aZL^Md47*}`mXwlUjfrty#d?Gb2ib}&1doy^W=7qhEr zHytKuLMCiFO}FVWQPXQ;CT6`?dA@1r@71AZSFDmn)}QH=0WqY z*~Ohc?Xah6=$tE;`+#er+0AS|^zV4TL1TNQX)~sconAFE693`I6`IcO@ckIjiCZ@y zD|^oT4k64M^?m;#BQ}AI_Y}2RUOT8;2oAn+R&izTEka9TpNK2L(__u)qk^Rd5T3@< zgZ&$8ea-XXer5++aoEP*36|(Jk$I!nr1fCUK?7&>4|md};F(~3$77?5a~^!E-?9m{ z$zj|ae!#$s{Vs7wdyE+dO&trSj=4AJ-hgb*!Xp{@-|pN0s3VV<$IX-GY4ePE*}Q7r zG;f)A%)912^MU!$d}Ka0pO}A{&&=oM3-hJ<%6x6UG2fXV&Cli+^Q-y8{AvC+6PbVQ zku{za&lb-f&mGSj&mS)kFBmTrFB~rtFB&fvFCH%uFBvZrFB>lxFCR~iSBj^`ZSgAc z>hT)!bW6>6?Klumi`R|Ui`S1gi8qV4h_{TV$J@l)#oNa_#5=`1$GgP4#=FJ4$L(=P z9F9BVuDCmn#658|?v4B6Lxz5zcGr=Nsx#-}8-q)OTiBjs#?HyE$>E7THU%JO3FnCM zX9koTyKqWA@PwAb`zlaMT|L6(eLJXTxN7fe#MgecVxJ@IxNqZ|PiQv(idbr5(cXRh z%X?fK(qiaU@uql9%t8()zsKH8C79g)qyG8h52A+#_Md=HTRVN{_~QL*j%^*>@3`S4 zoh!z#9KU*e_X#;T!9QalH{#ly(Nqn%x*740VJ^wfrG0oOItFckj)Y6uPxkCHbF=b4 z%Efv1CSK?RW*Wx$gH{-YBcjNcs_u~)Z593ebM`I?rTYoTkE&V*Wb;_d% z<~$4+pbt%%(z}kM4B2o{@&ALlvkGc#3)V2>?(Xhq+?8>kI0Oh15<*}|aM|u|2{RC6 zW*B#OcXxMpclXQNeZO_9&Z&OM%TBWETivx*ukQXyiEN*I!jn-P;*2!^u(*VK)*8BU z(XOOmD4YckDLFY2hfk*n}FeQcWrr*Z=#;cM;xEr zkP;NP!#RnUiyA4d@eg@Rb+rSF3aiIA{12R6pX5Btd6Dxr=UvYGoDVslaz5vL&H0}5 zBj;z%ubgr~d7uJN5vT-I2C4$pfSN!ppf*qsXaF<;ngK0=)<7GeEzln540Hv$0X=}8 zKyRQA&==?r3;>1$!N4eBG%yAj3ycRQ0+WErz!YE_pa+bA8L$9hKsXQq1P9rGNFW-B z0qj65-~gOJ9N+@t0XL8UBmyZwDv$=G0~tUjkOgD|0006I00St10XRSaBtQW)FvQv- za!@p$j~nI@lsVcpE~|G)8w0B{j*`3;ubpL7$N18{~@`~ z*EljE{(X$-nHV5dkB}Sp4m@KGpI+NB(GsSs20gbkDK})?(b6v$KLX2HK4q10HZj{h zcYV!bQj3QY_*_9hBr;Atj4yWWP9105U`*mFMa{GAc6f3#v#M*Yp)#=`d{p-hV{_{0 zUXv|MKa6S9mzjC3eE!+M{^Yno#DAdwj{#VK0|Y<Vnz%pPtumV^KtO8a8Yk;-DW?&1j71##s0CobqfZf1eU>|S*I0zg9jsQo2W56lk zG;jtu3!Dco02hHPz*XQHa09pr+yZU`cYwRVJ>Wj@0C-r+{}J#Qcmg~Ho&zs{m%wY_ z4e%Ct2fPP90-u2|z&GGK@Dun2{09C2e@o?~%7W#<@?b@<5?C3m0#*g9fz`p0z%s+t zoZ4|u#PZ<}owuWKXn104{a~svq>pY*RsrOQmZIP0H!}^kNU7P*_W6{xLws-|pIa&9 zqjxRVR_N<^hi%U4Oz#Iy1xkDqW4~semgAC!m<(#0r0GN&^FFkq`HZfa?!2)8k#j2{ z2lcpiAD#`lkZBf{nn&U=y$@ z*bHnAwg6j!t-&^6Td*D20qh8N0y~3Uz^-67@E@={*aPed_5yo@eZan8e{cXe5F7*! z28V;e;An6RI2IfSP5>u^Q^2XFcx%z!9j6gJeUYh2a`Y# zm<*9f*R-tbHN#4Yx{8Guw$?; z#Qe>_&3S});_BfUuYY5|@4X`rjycJhW7;?)jIp#cA;{!(PSoleW<}q{7*g;1xL^jWhl2!*u#j$uE3UUCrP_>5IH~@%s^*9r@9{tQ7MP z+# zwam;br<_s;r_Tkl`PaT0%02V{7sdbk_sj(Iz);LWCU^_H4c-Cof%m}&;A8L^_@b2mEAS2Y9{d1)1V4eF z!7t!f@H_Ye{0062|AJ+p@=yh+5>y$g0#${oL$#pVP#vf)R1azZHG~>NO`v8_bEu5& zZT1_pn3r8xb8h$iV%q|_t**IlmC?x@h+Sr?mQbKivhOsu^hO#3jsjO~V7$`Ee=X~` z-p&E8?^rJA8LPUl(8qL;5*|+vN@s z*>=W^IQ0Iqxp+~cy*d$W>`T;-%qr^bRZ8`*{%vakwSw9}ZK3v12dE>|3F-`Wfx1H7 zpnst5P!Fgl)C=kj^?~|9{h6TUOV0~}(w{n-ddXh$RcC>-aR8vfxI7O`y&Kj=ing<4?gJdi9lx?9r zHo%8B#r>A-(3+u-<-sm0u_*6KwwRnA-8gH!`@H)vG>6DmTg4s$9WJLT7@L|F6XD75G*}0l;Sksghr^L@G#mrR!cI62cERzm8%}@|;puP^?18;-3Y-dO zz?pD148RbKz$lEvBuv3H%)lJX!vZYA5-h_Ctie7wI4BpM0nda3a3Nd-7sIpQ5_m2= z4_*i_f)~SU;I;5Ncmuo<-VASnx5C@u9q>+g7rYzZ1Mh|R!3W@j@FDnsHJB(!cpNp< zHP_^|7tfugU!{4BD{b{+o<~J{-aFc;X~yMwe@t^dcd4uC3#^R0yV@#zw(lsNZ&Bf1 z`rV#5+xhT%b03*caLbAZD)WhPF0AlJ=+QtA)2&Q{>AtP3v#c1ZJLl+X|B;YkEVRut z9uVilT#*5PYoD6hQ=MeQqnr6tGY^T~t>XYw%-p#@@)LZ+X5E*8?9mCg+%MGr>Tr|f zyODf4p+f#^|L@S*?(f1;-!aR-&;Kxd3_cE@fKS4w;WO}A_#Auzz64)}ufSK~Yw%6@ z7JLW33*Unuzz^X^@Kg91{2YD>zk*-GZ{c_F2lylW3H}U!fxp4u;UDl%_&5BwRN%D? zQWhzPlt(Hc6_LtF6{IRs1F4DBM(QASk$Omdqyf?hX^b>Mf`ghO&5-6u3#28|8fk;H zMcN_lkq$^_qzlpw`3LEa^gwzdy^!8WAEYnR59yB#Kn5a%ks-)XWEe6W8G(#OwiPGZ za=aZqi**}qe6cfkS?pT>^MY=c&E5;P-$p4U1b>I`iks$q@7fcq+N-8nJ(D~=!@cgV z)a5WObh`2~>9!vYZ$x}GCwj9ib3$_Hv-F^ZJ)mL<(O0%y$QG5dfsLMR-XyiQ7*{ex z4GukDayd(gxtE?`|7BUG>pDGFFxgXmhb-4pK`ywYtJi019J2ruL)Pm1Wel?vo0}MF zS`dp)_d6yc^GjF~bDzlM&!wM0LjME(zhjWG$T(y?G69*0OhP6jQ;?~M4$&h9#E6&> zGh#tPkWj>mgdyQb1Y$!Xktie@i9zg0EaE_%NF3rq;t@BJfFvT*ktD=}c#&iz1xZEH zkaQ#q$wqPz009vQ!4MoF5E7vf8etF?;Sj!*zko=Hj3|hTXowH-BQudaB!Cnl#mFpV z9x@+Uh%7;tBFm8F$Vy}tvKm>7tV1>-n~^QZR%9Ep1KEjmiqUcZge-E*(5>(cbgZYY zT6E?S8RwISX4N${G~brbB}%1I#c#ZNYulu?8Rmp*zIwRBxzOG|Kb%JN3{6W5k#nH9mBO*r6GJ3yyM=3+SP4r2rTj_?5^Y$7Aom2q)X&hnw zVIATIvW7!%!Ti$r_ix)?WFK+>IfxuWjv&X8lgJt5EOHJxk6b`5BA1YB$PMHsavQmW z+(#ZD50OX6W8?|)6nT!kKwcuRkk`l?SztLCRz)vjh5=qp>@%EXnnK++7NAoHb$GEP0?m( zbF>B85^aUHLEEA2(GF-wv@_ZT?TY?`c1L@lz0lrhAG9yp5ABZ*Ko!DO^xd~FWwG3* znXGd5YMh<~LaDVo#=fDuiWc_9N?iN)=9vx_0vsfjRyK= zV&;s`YHxMF*du>6{N+Ee{~w4BLIofeqH)=ew}c1-(1EYh9uPw+Cul_GY9R)~9-_cCX(zA1S>{elP; z^~3LAxGCI~m5cjm-%E1@ht5YApbODO=wfs!x(r>8u0U6!tI*ZxT67({9^HU$L^q+E z(Jkm!bQ`)I-GS~zccHt{J?LI^AG#ksfF48-p@-2U=uz|-dK^80oZI%CVC6Kjov};qW94I=mYd2`UriDK0%+N&(P=S3-l%W z3Vn^fLEob9(D&#E^dtHS{fvG=zoOsJ@8}P7c;p7tc-mpCN!xO=Hnk9X;mn5SVS$X-1>*>3*#zlg~C+Lxpgynh82;CY_1aYBs@W`{M9OG@ZrPee5 zz5cQJseM(d+hlN#DQOka(J(M4$NT_efl!Jw-3gn`LZf z`5F0dNB`iUpXe|2H~I(tiw0q3u(DV=tUOi$tB6&?Dq~f!s#rCwI#vU#iPgetV|B2) zSUs#h)&OgWHNqNWO|Yg|Gpsq*0&9u2!dhc(u(nt`tUcBN>xgy2I%8e1u2?thAFMmp z1M7+P!g^zUu)bJ7tUopY8;A|U24lfNL$G1kaBKt?jE%%bV`H$f*f?xFHW8bIO~$5R zQ?Y574%1@>%!rvVGiJd;uu#m3g<;`X1ZKk`u_)|>{vj0Mz3=xG6CnXhta+^^DCW5{ zC-JQ@A-1ZiYuGiD&RPSgma{cFC-xp*g{$P#OY-DvG@fgpq3Vq5B*=Xhv#I*!`bx?fx7LQkli z+?mmjghAnJtTmm_)VGAyngcJ_zl_;!8k5BlUGa%=yYqQa(yOg~*axs*} z=)yB3)AAtwsBk@uA7<@cF z0iTFZ!YAWX@TvGTT!-s%6K=+ZqE4}Na-6kd{CMZP&{vK`$HnOS0or=p!H2ZrCzA_( z@geJJmpfFw%}kG|mGH#z2CfrGHO@}yrTlgt6EDP8#1EuCPOgxdm-s9FMD!VdBlmP~ zv~#1$kzR)I=pTnq&%K^H$9utK(0vVf^D*`W&=YNAoMAl>ClfI8!t=gVFl4K-(7Y^x zOg~fd9{!fT6Rej~F;nM0mAh#6Fi@l|bS+DxgyA~Tyxued;LKf2f#|fOmX`I1XoWprs zz(rifRosXB@mzccKC|>PE`S%{g?JG@3!jb8!x!KS@x}NOd>OtRUxBa0SK+JiHTe3{ z{KrOo6TTVWf^Wrl;5+d>_&)pqeh@!|AHk2}$MEC$N&GZ^7C(od$1mU)@hkXM{5pOE zzlq<%Z{v6H2lzw$LDorV2C~?*B{0iGXFj()*IS4U^c`Pn{_*JM_PO51(Kgp0@=x9r z`>xc3*c#-xkxW>Rq)_d3obPNd7QaSUL0KL*nYdvn$U2ku*tXjjpTg;=IA{Kq=pt7m z(*faF>Oxb^jJ}x#?yo?@f_}Q4{yVczdT$y>sVyvL92+v;(_aG2+=F=o^u_ooV`<4+ zV09!{_{983H#@mX=BC6Xz*iKW)!5WNdzAO1+iNVEJB28+41@QU=D+@JdxSs5pW!d? zm-s9EHU1X=fPcb2<6rQv_&5AJ{saGw|H1#_Wr<2eWugjEm8eP7BI*$Jh^9m{q6N{C zXhpOk+7a!EZp1%CccKT;ljueCA^H)6i6O)=Vgxag7)6XF#t{>UiNqvAN9YLyVI<5% z2oXwHiPHJcgpG(KqKIfBhOiT{rQ32R5l6U)c*0F25J`lG@Dj;H3Xw{r6B$G%kws(^ zIRrp}1Vq3DLZAc}V5|=u69PzL`G~S{7vWkdQvypUhnX$(M~kT&opEM8N6wyEq5ypg z-m0Tjyd*k>0YhTO2YNU%iyK&O=PlG9cDW*BBOBmGuBS(i;WHj3|HYm}Hgit5JxR_o zr|IT7U0L%T$-a*I^SULTE!YmZ1+#;<;zRxI@|VN&i@yoOnPy(D_!cIF?<|>>Q3jwm zPcc>8EVPm3q%~Eyq$JdQ%vXh+ku#&{4R=4e9{Vfa5!>xQF#ic7NP;3*LLekUB{afE z_=#L%29ZbP69q&OQ9>*vmJmycWyC6C9kG$vOl%>x5!;EK#9`tnaf~=loFGmTXNhyf zdEx?bk+?)$Caw{8iF?EY;vw;bctd<9z7pSwpTr;HFA+qRA`ZncyOQ0=?qmQAa$Z{Wk#`^ zO~}rzQV^Fm-%}-LM#QN6vq>7>DgK;odw6lgv;435uXNR!B4*X}yV=-Ds|S$7}JC1IT z!cQm73|kW)5`EVc65HARCObaIojxA=>v&-?Smxy|^f!;#h&A+#(Pf9%CMJek%>%Rc z1WtsucGe*g`}h1SUWbJ&VvWxueiLiL>lJi0JoXHWyz8**gUv8m(Z3_P8+*)=8NCPC z90xl;$25+>b6b@JN9vuU3DlMxGC6-*KI>g(zvsS_e%na?2lO8=k(bFUPU5>x==l+KGYCu7&V*< zrb^czHHsQdjiJU-vl8U0DDLWNQIVdL; zN4cnY%1tFwPaStWwsfy!P2O&-9%=T@HkOac3}0cYYtIM|#2dJ|SzVn^V&5V^UTQ@D*N0R&(o1+|G4CinT5J<)>y+c~m|Xpo*zkR0%bYT0kwNmQow2&D0iZ2ep&hMeU{b zQ3t4l)M4rfb(}g!U7@a1H>lgx1L`UDjCxMJpk7h0sW;R+>I3zW`b>SHzLoO-LH(kB zQ-7$xR1jU2u143OYtwbV8WY zVbV>vey3_M8PTteUosEL`p8)8FArZhKB6BmcGgQ@J`!p&I)3CG(Q$Mv^PJwmT(b6a zm$N3v$9sD#x8v)iwsH?iYM9W}u`|4!?vSx!$_2O2lWjbiFd^KX6rWWysy1nud(|}& z90leU=crUXcv7lV2pdREGQ=f5BSN6^9aD0(zKmL5k>q$kr; z=&AHHT1T7d5IU5$(qVKs9Ys6nR631Lr!(kGI*ZPxK^mel8m9@Gq$!%F8JedBTB2oI zp;g*P`{`UdkItt9bOBvN7t?d-x%7N`0lko3L@%b7&`ar6^lEwy9UQcl-c0YL_t1Ok z1N1@q5PgI`Mjxk7(x>S&^f~%GeSyA6U#73p*XbMdP5KV~fPP3nqMy)D>1Xsy`W5|} zPPGsBW~IkFw7kQ4W6b+~7<^aPQNeVVO4jFX%$sJ4OmX_hdHX4K!lp*GPMVao!fmry zNChtn8^{icS>Tv3eQBmgZP=%k)p93JX@nUBh2Tp4F>RB~y92zOJX8hL+@Q z)^E@~0sCb>GHs_W#O(%e+enY80QR-@j44Izsg+nu*@9jB-mKD z-d`?rwC6_Xl-$D}Ssh|N!hMKet4)kdD{lQCxc_-WzokFYpXkr@7y2vxgZ@eXqW{o; z=^&;oQ-P_(RA#C$RhimMU8WvWpJ~7}WEwF|n5IlKrX|ygY0b1@+A{5!E=*UZ8}kp- zo$0~!WO^}un7&Lurav=)8ORJ~hA=~!5lk>Mk{QK}X2vjMnQ_bnW+F3*2@aafOkt)n z(-gb8KBm?$QiiDB%FgNb8YOg!Ue5}4^sGLyojGU-evlf!@v%plAa z^MD9>?m~5^xw3U>;TZR<+~b}E_@VwMP*_r0aC0i4dfqjAN!XkV? z+QBr@c+veR^HEr1*VfSGa&}Rw<1+T${yOzl*nZs(-RYR81wVC*n{d?jXaoYp;d z)pQJ^k26kM<@3_EByYD}zzU4VotNAqF_>;3)HOmjDtx^!Ll@<789Rt6z8-^Nsn={9t}EznMQw5L<>V%eK@z zUB-lqA)R#fk4@p3xDwkD`GfgE4zAZlW*46fuN5-{ zd>PhI_t!1!UOQ$=E&O{;J>zeMctXqiFY8qOiQLqpTAs4eW9*A;N5sqW0M`^pph&R& zwF%B1Ay>^Evr*$e>;m`31Sx5TW2Wztxh{3y>&uGQ>C{x)+_bf9Zv6H5bUcVZUDA4P zbYxHWJ71lI7_PSrdzd}K9%YZQC)kthDfTpbhCR<-DCK{Ny~18)ud&zJ8|+Q?HhYJ? z%id$}vk%yZ>|^!``;>jgzF=Rnuh`e@8}=>xj(yL5U_Y{-*w5@2_AC314Y3b2)gUZ! zsX~{m3eoivJ~^5foH7qjFQfGH#OBn5dRSKFK!wezPjU!Q-@QL|tt&rnKxhm5e(;;Q zg$_>Qh#$6xAvZ&Z=!faki#|qS?mpXKIpVbqhMTvx6e z_Yc>d>%sNpdU3tEK3rd}AJ?B7zzyUEb3?eH+;DCL7tD?1f`dkJqq#BMSZ*9Qo}0i; zGxhdRK&cvCy5H6Ina$#IJXX7HdC@zMxbFrM0i{o5eJm=;TxI}I`=gny8oTAmz z&JdTVRgQP&cb@3nuHj|ush(-p$#GrPZrRV1ZB}CXyDV=?ccrotZ+)9IL)Zu`aDF$h zPL1<~g>{W98+I>Y7Fj#w3ewoHLp$Z2tG-P2IcIq`+*j@g_mlg@{pS91W%%-Z1->F*jjztvc)&i^DHEMuaqU z9<^NOhIz|HJjt9bOiyYUK2_-%gC#G|Knn-yzNRX+0${i^B0i9P(mu;JDWZ}tgq-e? zGv@0=w-F~|ez=;suf;IoWg`B4|8K%K<6H2p_||-Tz9Zj>@631QyYc_<-T9t;FTM}o zm+#LH;0N)8`62u;emFmpAH|R6$M9qMar}6GGCzf%#_M?lZ{$t9g%9CF`7l0$xABpD z6d%pU@UgsukLTTd0-wlF=aYC3@8whYG(Mfr;IsJPpd23HK_239p5RHI;W?h?MPA|+ zUgLedpU>rI@OgYbAK(l5BEFcP#n0yF@Fn~_em=i|U&t@wPe-kZNi#nwxa}L4@F}!s z$X)vo-L#ZX*iot`b1A%)zN>yj1R2a6rYr*8||EEZb{Y9uhBFW zKjokC&-s`9EB-bAmVd{;=Rfct`A__3{tN$=|5nQX2mh1*#sB92@c)ErgarE1|W}P6&ch?A4=1`y8@C z_$@n=_BM4zvcW^7Gt*ZK-J|WgjS;g$9_BUj{zQrbwH!wD6>g%(cSnSqNw6{E5cvy4kZAVcRV2Rf{l?`jD@AJI0)f7!jWsSeMZwW3L$^*`oRQ z3R_OV5ZH@-%U)p4&Mzuj504eYl4Et3a2NPQ{%AjKS*ZgHzedGQKWnICiB&o=Q9${E z$)-1!g`q+Df_Jm+h}T@IfBJ7*d!d8SQRpOe7P<&sg>J$>LU*Bu&{OCo^cMOG{e=F) z0AZjoNEjjv6^08VgkWKmFj^QRj29*d6NO2_WMPV+6ZC>XFbXEYEQAQ5LYNRC*n~(S zN{AL>1iKI~xP|G0S4a`kgbX25$P%&zKmY|u2o8b;L?8rO-~?U}1xZi@P4EeRAy=3w zn^l$Vf z_;B~(kjnY{z<}@&n;TZ$5mXStH4cRf{W06*LyR@|y7{%s7af@uXHQ1)h!@yvEYY_# zWT9=9{iKWe5A^@864nT7g>}LPVWY4~*eq-jwh7yX9l}mwx3EXpE9?^v3WtQF!ZG25 za8fuWoEFXs=Y;dZMd6BYRk$JC6mAK(g*(DM;lA)hcq%*>UI;IRSHf%Ijqq0ZAbb|S z2w#OC!cXD1@K*>D%ZTN~@?r(CqF70+ECvTv5vz&S#TsHwv6fgztS>eY8;Xs@#$t1^ zh1gPTCAJpZitWVqVn?x)*jel%{v&o5dx$;7-eMoIuh?H4C|2=1v%BQnz%mPFvGKM{ z=tW?paMI*UTM_fh^+5h@q@|l~Hx-^fn`;;q zF0Az)4xG0X>$b>M(so;_1n#DO_nyn{psNqm<(Ef(i4Kxx7uF1Dse3(R!^u-m~N>nBev}QuOn)B)popZ=jRso$f*w zY#f*{B8Bj$l7aB-|G?~`LE>O>h&WUnCJq-zh{57WakMx_94C$!Cx{cpN#bO2ia1rA zChA1JXb_E}Ni>TVF+>a%tzwuME=GtpF;a{Y?P9Fx5S?P2=n~yxf|w{y7n4Mf=oOR2 z6fspy6Vt^EF;mPEv&9?{5J3?Vky8Gsh>3(qiHyjKyeNpGD2cMDh^nZGKG84ciZjHS zVxE{U2E+ofP%ILQ#aZHPagJCb&K2j0^Ti2qog!WST&SILBYc%5s8sTa6oZIfiMr4M z#K813xm%1ex~#&0v#IWj`D6SPvU&IhZ;6U&OECH}Sjpqm=(o@t62p{3HGq%SdIVa#DGzf>cqeELD-JO4X$5 zQVpr5R7ODO(BDEwhx--7LRH&f? z~QK2lE<>PMV}5-)xL8+%SVsm9pu67M@^lx(CEhc zdG@C6+n&DNGbnjdZWZ@Q^GCB$e?0fSe9VkQAMic$YPtj2Tw*lWG`1oY zuD_!n;YVgyiEWWwKbZ{(y514b0yTAbLK-%dP%*dK2l$) zpVVI(APtlTNrR;!(okubG+YXnMoOck(b5=ctTav~ z0;7!Qe3@)iZb!l6SMro6@S=u6Pm9|OSr5(~vX_vHH z+9U0i_DTDt1Eu^AN{6Jw(h=#XbWA!fosdpSr=-);8R@KaPC74LkSq|4G3>8f;1 zx-Q+2Zc4YL+tMBBu5?ejFFlYRO84`=<#*1hkgzOKwoKD)OFbrs#mO$##y~?1&ulw$ z?k9m#A+pDFHha0Nz}G!0Bytc}Il*pj?6?lul7C~Zrr(27WBR7Fj!~S;yrJ&Oy4ukl z)vLOFM8E9Wft!x*@t9+mCrfpwCF0|aJn_n$>@ReDu)O1nd=-dB`Hk4?zHsm9jJd8> zIpwoD0YAx>s*txtpYPtDbwaLG(9<~~zkgsG)6O|6hm3ibF6!#rGhJ^T&ZJ=1zt8`X z^jLZ#J(ZqG&!rdAOX-#LT6!bBmEKA3r4Q0a>67$X`XYUmzDeJuAJR|hm-JiuBmI?v zGr76k zLT)Lyl3UAdL*-%eaCw9rERU2&$)n{l@>qGC+$s8K)_MPac@8zl-P6_E(wKjovw$c|j`B>= z9mS>+pR#Kt29n&4VFpG&(pt&sNZO;mFh6r`!>-0Ob#8TjBtMbKc=PD%kpoOn{By7= z)LAV`y_9t)d8cOv)LnNt`(Di4yd2>eb{gDEoX-8AYou>QC0Oo6_3@sP7bBUzLZWH( z49oiLBHOU|MaB0rx+dJ@db_)3e3Ng=wf*0ro26o;haAgudWR0xS(*3l<)(dH5A|D~ z@juZ2HC~<|Pn0LgljSM$RC$`Lll8JeHp(X1EL-FdIaIdFVRE<}A=~6gIZBR}V`RG= zD?4PTT_*g?3I({6ggE+lhfr4IaAJ(v*jEakU<%eVHuH88Iy6DkV%=6 zX_=8(nJeYb%YrP*k}S)Ltje0~ll^k8JVTx-=gIkUKrWCAN# zOF9&}m~61UAZsLBZRKWNPUxx?*nVL{?VGXf{!~>Te%g5#+^Cw&XI-J-VR>la5VkXq z!uo}Zxk2vfc-6=(f9LooQ3m}TcZ4BQZ?G^ol_-DkjCOSd>u3s)Q-wicN`BqLgSQMzJeSB~EcE@rqkX zP!g5WO_h?Yq$sIMnv$+$Dp^XllB2*1qM!<<;0mFT3au~-r|?Q?|ED4=s-h`A#joTl zGnAQ1z7kLhlp>{AnWfBD<|rk~TxFgzUs<3mR2C_Vl_knjWtp;ES)r^{Rw=6$Raad% z(pX#fH+r18fv!;3QrBme$Cen{S+@fW)-^Cs&~*NJHf6iAL)oe9 zQg$nQl)cJ6WxsMjIj9^`4l75LqslSmxN<@{shm3R4b{K)hcRLwVGO8t)a%~ zt@=Lt;reWSrao6M>S?`CkLh9k3O%Az;{&_C4Q(x2Dg)qm4>F-$dl z)c<3sW$0n(Zup~bZm4ePVCZbX3}Xx-hKUB9!DE08iw#Q+%MCjWR}2-6uMMvZPYiDi zm5kMlw{^okVS1PTjDFtS@t#a1+4wu^cu8RqX{;aq-BiO|NvdsrX>1Z6Vw|T7HEz@; z3yXx!y87e=fdKp2$_d->mB#hP-Ns$U|MkOv>r+j&mReh_qt;dHsrA(cYD2Y=+E{I( zHdULc&DGYbQ8lSnHAZ!*32LG`UG=ERYKoesrmKJos*nn+h>EJ1imQZ5skF+eyeg=o zs;H`}sXo=O&QNEn`D#EdPz%)}wOE~{&Q|BBCF(qNzFK)g|gub(y+cU7@a2 zSE;MjHR@V*ow`BYqHa~Ut2@=*>OOV9dO$s_9#xO2$JG<+Y4x0XLA|J6QjZz~#s$X3 z#(DA*d8xcY-Xw39x5@|PgYrrFtb9hkAYYU($yelS@^$%^d{@3FKa!ux&*eArJNcvh zMgA`TlK;v8f;7dMG`W zK1yGuzcN5cG(+YVfwqA*f!=|xf#HE+fzg3U0ZSkz;0|~K>4D6E5KsdJfpvib|1AF; zf02Kcf4+Z{f1`hkf5(4d{?}#ontENmrQTETs}I!2>J#;;`dodjzER()@6`|LC-sZ^ zOZ}t%RfDuLT3M}}R$i;9RnjVJ)wCK~O|7<8N2{yV(;8?EwMJTFt%=rDYo;~VT5D~z z_F4z6qt;35taa16YrV8ST3@Z7Hb5Jw4bp~c!?Y1v>8jVpXydf;+Ei_trqlGAK{IO> zEkp~|tXh~Bq1m)ZElP{lVl=xJt2s2M7N@y1x0awy*OIhkElu0zU*|vTKkVP*Kj%N> zKkC2ef8u}OzvaK`zv+MJf9wC_FQ3~sw`Fd-+}^o8a|h>+$sM0t!!$a4foYX#wP}y( zujQQSis_x{uK7*c>6}l|pN+qaJ!fq(mx+nUdK)#>y4*UywBc}9*x|7AVO^~MSi4&L zS_fNuSbJI{twXJ&t%+9Fnq=jyh!wUbSiRP4Yld~Tb&*xEZm^!UF12p5&a}?6UbbGd z-mqS`Ua)SnezLx`ezQKZ-nRZ*UjM(po1tZCIU1mW8l=G*s$m+TQ5vl=8m9@Gs7acv zDVnNjTCO%jo2lh%0j)qQ)QYrXZI(7io2$*!=4%VIh1w!*v9?58sx8x&Yb&(X+8S-0 zwqDz)ZPGStTePj(Hf_7MQ`@EO*7j(7wSC%t?LaC2gW4hOuy#Z{svXmgYbUgm+9~a{ zc2+y5o!2gC7qv^;W$lV~RlBBL*KTMxwOiV4?T&U=yQkgP9%v7>M_RS88ezY!udP90 zEyJ3GjSXuZ<_hzKkzrz3aTpP{tf6;MUgN@^RmhgwG+ zqfSr{sX}TiwT3!Louc+r%c)J&d};+XmpVk9p%zj1sVekW>Je3ou0-FWK2aB_YgBdm zCv}mkLpP->()H;E^gZe_)tolcHae27OwXW)(f#P&^ej4>?n&$E3G^5`h8{^bqV05d zdI;T@j;CFv^{@Z7J=UIRPqk;-bM1xpQhTMn*4}7uwRhTk?SuAF`=ou=zGz>yZ`yb5 zhxSwZrTy0aXn(aJUm0InUpZfSUj<)9UnO5sm-)P?$-&kJ)-HcA8 zJ@j$R^nagE2NH=Nu$~a!x3r9Ff#X0g$HSbnZdJjAjNAl!bBt5s0^A6-+|6SHt-hM3bup;;dnR!j(`*4Fn9sH z683~c;C*m1JPY=L%i%`21-=9q!|iY#TnZP!XWkqvNd8RzT>e7-O8#2@9y$mef_{jOKu4mZQ48c3UQdKy5%(9`H|Cn=XK7@oDVxc za`tzQa87p4cJ^^Tn-_qY-E%8ihuqK>za(j3Q_p8jmKTd(eGo5}J(4Q53~d z5>=oK%Ao=(p-OZ=szx=a7S*A8Gz~qBW}-vFxoBf#J;r901?rwXz?drBG+n#Ux*ld*9K(lpbTg|qanVDIbEi)Tu zw%yFqY=YTrGti7Q3pMjMb1~!0cr(~6#LUf1G;1+CY*t~GZPsR{HA^*XH|sD9Fgsv& z(yY*|)U3hGXx43Z%1m!|&`fQ1+N{~^jM-T8%VuAjzcl;A{Jz^F<)cuW4^@P+~n09>}zZsHW8bI zO~$5R-(XX*Y1njZ1~wD>7W*EXjs1Yl!RBH=V)L+{u%EGCum#w!*g|X(wisK2Eyb2& z^UN*GgUv(CL(P9M|K8lje6M+%Ib@z;o^PID4wx&=qs=?bG4n|CUh`t}5_8g=HNR&5 z*u2*KD~ne1>*hDiJIpVcpEf^Xe%rjy{GR!J^9J)q^DE{L%`cjh@-Hn0Sq!mw%VMI% z1dCVZGK(n|Gc9&l%(vKXF~eemg_DJ)g^k5}3p0y23l|H23onaEizo}kg0MJh(P7bL zaoXaX#Y2nh7Edi+TfDP<@b>q&f4+T~-59%1?1tOTvirqu!9T%B&JLZ9TVLn(O7J)@#QCKVnU?2uzFcya;V0*A+OpXy4iBXsW zqcH|!F#!`X2~%SGu@p>=X|PmGi|H^umWCa|(y-yKOB%AkR6a0 za4g_>KzTq@Kx05#z?Fd80apX=1w06N9Pn1){eS_1&;AMC|GI=-#;#yjv1{0M>;`rd zyM^7x?qGMZd)R&K0rn7kggwTdU{A4U*mLX!_7Z!Ay~bqtTlm}f0Q?>NU3?(^9zF3&%x*7KjQQ7pYZwk&-gF+0{mBe zA-)J-j4#2L;>+;m_zL`az^8#D0>=do4*W9ki@=eA;{)dhP70h6_*3Alz|Dah0{fS5 z3G@#13ycmN3r@1U%uKX=+tQhJXFXU?b|>q_db2@nD7%}DWnng+-NPoaD2uTKOR^Lj zYlqqGwNuz>?DpH`+vV7m*k##mOKP)gwd=9FVt381061Y^Yu{<#Y(K!^mi;>p=j<=q zzp{VVVW7h``5a|%%u+-tr-~U(Q ztMJwM8hkCj4quONz&GNX@Xh!Zd@H^UH^a?w3w%4i1GmJjaBJKKx5e#nd)xtc#QUeq z;x4!=?uNVL9=IpI6ZgWsaUa|l_rrJL{&)Z$hzH{#{R3@v&m0VwB=j#TdnBiWwUh1&nl>>uu(3)qv@>3!C_)BBnCb?;l=8Q$&Qx4mC^zxnvni6@JhT2uf}Wf zI=milz#H)zm=r_@4Eh>37~&A@ z_HFi+`&RfWeVzPP`mOSt=r_{usqc4wKl-in3-X)h_rBj$zeK+zzkPmTegS?_ei44H zes4bhgNYA_A;eJPLt+^55iy+jm>5BPLX0Fv5uXyHi7~`y#8~2U;tS$S;w$27VjMA^ zm_SS=qcB32V?i2nJX#5!UqMK04e{HkLO2*3LF=HbpVh?5En#v=0Io*#E-&+5nc2 zWs;@d@}T7b%Qqi?Z^DQ0CH#n8gg+5L1QJ0+FcCt85@AF*5kW)}QN(T{nusA{34j0z zh=2)%h$G^O1R{~xL+mB?5lKWcff5*j69hpL6rmt!f+1LfBX~j}L_#8z#C{@$P!R_R zHK8F=2`!-`^u$3Ttv~*Uh{MDY;wX_$WDuD|7LiTl5V=Giag4|(3W!3Yh$tpXh*F}A zC?_h2&4b1Z9ccLvUar&wBBO9&DzO2m<#2? zxCkzW+s(yt0Eci1+#U|)aE{;<9K-RPz=@oa+s~=E1DuA_a?0qG=mXK3XkE1apJ4uH z6VXhx5UoTT(N1&_Cy6e?Kp2T`qK7y|oF>i?y~J7K9C4nwKwKpHh)cv};tFw>98P{rjvzlFN0Ot+Ps!2b81gf6EcrS41^FfU75Oze zjvP-;ASaTO$jRgs@*8q0IgOl7&LC%!-;#%;)1ynG%c9GpE23+o>!TZ@TcSInyP|ud z&qkk%z7l;s`d0Mq=)2MPqKC#jihdUTJo;7iTQP6P42XFzW>CxrF+*a8#SD-6IOfxs zF)^RVjE(s!W?anpmI-Hl!_S zN7|DPq$BA>I+HG>E9pkMlOCiexs&uJeMn!@uRs2~NPjYb3?zfdU^0XZCBw*YGJ=dG zqsZN4G#Nw2k^l*k5DAkQsUR7$nrtT9$qurcyhJ`HKc~K?#s+;Bv?RzTXnT-(kY!M4 zkWWx_kPws{6dMEt#Ru&Tl7e(W`XDq&8`Kt55Oj^cPT!!{yKi&1b6@T5>8^2)ci-tA z=+3xn-GkkA?vndq_r30+?osY{+~4;wxDWQY>YnaC#KY*Gyk`9_}8CJr;Vb^;qLE)g#A4?h)h> z>OpvTc~p4#dcN@Z%JXZ_ryg(q{y&BKf%=tNMy;mSQRb8t8XR%B3T-Bh&oIip^j4NR0fqvWl`Bw4wXygQOBr! zs(>n_il}0$ges-VsB)@;I!>LSDyb@}nyR5{sXD5jn&^4Q;{(sPJhyvZ@c78n-*djF zgXdCDTTj^2%QM!K@eK2vt-=VNnSSf52whB9igTh(i zs&G?yDSQ;Z3O~gzg})+D5vB-NL?|K^QHtG)Xhn=7RskqL1*Cu#@rp#n9z~KoSuU3| za!%fq{DIS_PGgn+#Yu6JAqyNz)R za3A0{(oN=u?0W3>h1(prS#CeN&2<|XYwu>}w#03dn}wUB+jh55H`r~To7PQqD{<>_ zJLPuC?W)`Cq#u%gO!_71*QCWsE0R_wtxj5#v?^&sl6jJ4QgvcoVtrymVpC#sVoPFc z|Idji18f7_0{jA^17ZT;fV}}p0rCJmV36}{=k$Mq^?&v$k`3@vf_Gw{BJ03 zDsCz6DDEomDIO>uDxN5wDV{4{C|)XFE8eCD(C^ZN=?~~3^hfk?`eXVNdL;cRJ(?av ze@2g`zo5UOzor+t7+l_oz2!sI2ucuz`dcWsA(0i!&Nbk|!W4u4}9_KyPd!qL= z@7dmSUCmv+TsH)44X_CKKENq%)K+Dz5KF`s#SV5aj?IWoi#;5h9h(<>Ird8I)!1vX zJ+T$BCt{7Ujj>&^AGx27y&iiv_Cf5;*rC9Oz`fWPu_N6-2CVk|2z&|507e6|fz`lz zU>gtwSOQjnKi~j(0#U$jzz1*#Htfi;N&r9r15WxL01g5Tz-0G2ps;`ayEmQ2(c|d} z^hA0RJ(-?De?w2Dr_(d&Z|U#oS@aL|9C|MOBR!A)nf`@dK>tcFq8HOk=%w^BdO5v< zUP-T_SJP|gwe&iAJ-vb6NN=Jy(_3gW+MM1_@1U({8`_q(r=4jR+KqOnJ?NdZ7wt{^ z(7v=Ey^Hpz7s&$XU^S4I+ET^N7FHMEDg{g4bd*{9F!cNOj`+m*K~ZCA#wE4%7;edIsFf0X}s{i$I@UY3Iu3M- zjg5&VydQbL@Oc#aBvcmme%PmBqr--WrMb=w`#kK6u=!y>hy4=vRoH^CNnta>CWK85 z+Zg5(W)ZeMY;xGrrGy;_%M8m8(}Z<|8N+JBZiL+ndpG<+ z*og3n;a`T&3FnnhrRUNM>2An7p+iHThP)R#DD<C6mfCi5-x9rHaiiA zv1V)-TgHyDXB-$urhgHA#)WZZ+!%MpgYjf`GG2@~7hBH#i2h3FAm-qye@ckuyt@iaCk5jyd%aj#y)2C9*>xy82^~?7$7D(rZJ>1 zWOf2V#*y*lUUCn)k4z%vBubJbO;RLB@}xi>Ak}0Vd5}Cz9wLvD>0~CEP3Dq$VzQJxLDrD9WF1*gHjs^E6WKzxl5ONkvXks0jiiC>A|*?x049(LV)io049-vt%N$^IjGj5jq%nt>!^{!pD3i`)Fqupilg;EX zxlA5&jLByTm_nwADP~HTQl^Y4XDXQE%n7EFsbZ>`8m5-1W9pd(rjco8T9^)|lj&l5 zm{ZJY<}7oLInP{RF80U2kGaHLWv(&TnH$Va<`#3Cxx?IL?lJe72h2m}5%ZXN!aQZ3 zG0&M7%uD7K^O}*dZ?SK)1K4-iciDmLd+b&6I(dt{P2MLTkPpent3b zD0j+(@}zcBUX(ZGNBL6$R3P;;bvg7#XszO8_|5PO;n%|lMy#?O5b<`zml2=*6RiI| zh<%?O%znTQVLxPtvBTMq*%9m~>_~PL`zbq`9m9Ucj%7b*zhJ*)zhb{;$Fbwt3G766 z5<8il!hXX}Wv8*z*%|Ci_B-}_b{0FE{ehjs&SigO=dnMr^Vy%-U)Tlguk1p05xbaO z!Y*Z(vCG*N>`HbOyP93Y_K*Lv>)7?|26iL6iQUX@VYjl|SPOPLyMwi4typW;hPCZq zNZFosU>#W})`fLr1KBV(oQ-6oS&)U;M0S3}yofCk&60-Q6_F5<972S!A?lDbL1%+z z1b;1!m%fpvO4Fq2(hO;~G)wwX`bnB6&6j?b7D`K`rP6X~rL;;~Ev=E(N$aJJ(iX{F z+Adj1){>26Cpk-QlDp&~c}hDaFUec-mwco^2@fWN6~X(1#o$B12ZFPLvxAQXp9szf zP7gjFToK$E+!%Zz_)74l;ETc6gD(dU2)P^lBKURiMS%1WKziJkdYx{ zLf-V%zeu)^O=dZkX9ZSdC05DqXH!@edw^B5sjQaOvj^EU_7HoRJ;EMk)7cC*lg(nY z*&H^P&0~+T`D_7O$QH51YzbS+ma*k*1$&%5!B(<#uN zdyBoz-eK>u_t^XF1NI^Nh<(gHVV|;NLl%UL5BWM|amdV&??V=a%nexqAr>KCA$}osF_$93BElnLBjO?wBB+Sei2V_VB6JalBeEh~5mLgxhB2`W)PMhb)9D%eoPEK*WM8qbSsC{h_ck|xdxv|M8_2!K4dUMC26G>9L%5;b zhukpkBW^hNF*kzygd53?;y&d@b7Q#AxUt;l+!x%J+*jP!+&FGLH-VeTP2whVQ@C%q zsoXSfIyZxx$$iUx$9>Pu;%0L{aC5l1+>hKm?k8@MY(Doh_Y1dx`;}YBE#ek)OSq-n zGHyAyf?LV0;#PBOxV79mZauew+sJL=Hgj9Jt=u-wj5Fsfxb55y&XP-H_AyC}oFN&G z;TefhGAWFT(J-mZhB&i0?>OJMn7D|zsJO^DU0hP!-nc_?Vw^VaK-|GNB2FKd8+Rfu zC$1?jJ+2@wBkpKiZCrC)cHGstyK(p8ZpPh@Yl#~Xe^U*f-vpA`RX{AckC<5$PeiJuieHGW?FqIfWVeEjbC==jKZhxlFb>*Ian z_r`CFcaD#WcZs)*ca10FkH+ib+xpkPdDF>?v*v6#Th5NN=Nvdk&WUs8TsT+GjdSNb zI8SaT=fwqZ5SPd$amgIXQ5?&qa(eC{m&P694s%Diqg*DJ#bt9jTs~LG6>}wADR-PZ z!Buh9Tn$&t)p3nn6W7eOaBW-%carPmx;P`(&Gm4n`s06^JHwsj&T|*Ii(DUfnY+SW z<*sozxLe#E?k;zayU#t~9&(Sk$J`U{8TW#F$-UxUb29!d{%!sp{#||`UlpGakHjC2 zr{kgcwD`XGL-9HBS@HGp?eWF&t?^~?b@4s%*W%B{--;iVFe2eq{NRMK3F8vxCoD+# zF=lDZ@|YDdAA!#zUPcUx91!_Vp8kriYjXV~4C{m2nMIw<0BZWv+WLji) zWNT!3WJBcX$nMC#$V-veB8No1ihL0{ENWEL2mQZ)_@>i){QLZ1{sVppKa~HF|A-&X zf6RZvkK{-3pYo&mG5lxzSpIYV3;s*~YknL*o}b81;wSS{_;2{B{4{<#KZBpif6IT* z&*FdJ=kRm+ANhIwPyBrTXZ}}yA-{-U%&+9v^6U8Z{6>B=zm?y{oAVa@c76wM$y@P@ zWY)Y5Z_C^9_Phh{$UE`QybJHjyYcS42k*)6Z2F_|$@QEObWC^1TilA=^m znNdYi#Zl!^)lm&mjZrmGl~G+$SE77Dom**4Q_RVjzL;|{mtwBQ+={s$^CT*Cck1pV zyH`c?(Z{50DKH66B9pMBj3oCYpQKg$*6dr0ZN@fYn=qID_ut-hisEUa%L6>f zLp;nQd>kLoC-8~<9)2&sk5A&0c{z{r7?1M=Px2J6;Ax)WS)Sv0Uf@Mu;+6b-h%0k#FLg`4+yFZ{yqf4*n$H$#?Mv-pF_JJ-id< zi0#5WF+XfK7L5g9L0CAp4?{2%OTsWrg&n{SVu!IK*ikG8%f<>Y^L^3Mv83xs?6(pTV>P+fN>P|Y7)Rfem)RR<|bR+3;(vzeMNl%lWCtXZ>Klx?SC&^zV zf0aBV`P<|P$=@aaoV+-Be)8PpUz2AguSs5#yfk@B^48?F$-9z6lB1ISl7o_wWO*`~ zj3x`oQgYZnaNnMN$UbHtxsP}4Ogxj=op`E${gXGHPVuMtGkh<9mOsaz=P&RV`9A&< zf0@6+U*)gy*ZCX#P5u^to4>=~6Agm;C3!h6CX;eBDS@PRNy7%F@y3==*Qh6^7HBZNPKoqzEeEfS?gl1+AbH^g^0&SU4i23mHPDkR@ab zIYO?GClm;ULXl7`oDeF7Dxq4a6YBf@f75A!@T;&;SR^bKmIzCQWx{e{g|JdsC9D?K z2y2CP!g^tYuu<3~Y!yoK&?qzs%|eUN zE_4Vdg)YG$7==^9X`xp*FGSG@jnOzw(nsku`T(6tXVV#6I+w@okaD>Ku81q=%D76d zf~)5mxK?fjzl>kSui;no8~82!6=o>=Eo;u2vAx_m?h<#KyUso5ZgNk#LHsa&1pgI3 zfiIRyq+g;zDPBsD_DZXA-Kr=_z}uXJ9zDqWWPq-)Y`X}ofV@;l{xz`!gb+>a8tM?+!pQ#cZGYxec^%dPK&io?W@#Npz{;t25* zailm({8St*juAf-$BLheUx;6dUx{Cf@!|w=qBu#MEKU)>5vPjN#OdM;ai;jK z_?`H@I7^%@{vgf~=ZZgy^TeOT`Qp#wFX966S8<`ZNL(x~5tsJcFs1)Ifo0-yafP^2 zTqUj+*NAJyb>ez)gSb)LByJYBh+D;NqM2weT8P`l9ipXZC0dI%qOE8r+KUdNqv#|$ zi!P$8=q9?09-^nXQ}hzOMIX^u^b>c9{$hX_C5sJh@?n~3Xv8Wkrg?S7X?uiB~dBv z7gI!)DgOVZ^Z$UT7Byn3s11VxD+R%ohv9 zLa|6J7E8oZu}mx%E5zgC39(YF605};u~w`T>%|7KQEU>M#TKzuY!lnX4)LVeDRzkl z(I|F{J>n_xw0K7B70-(2`eS!qydYi_`@~D)W$}u5RlFu%7jK9+#arTS@s4;`yeHll zABYddN8)4giTG4}CO#Kmh%d!g;%iYRy(PUZ{pZhpQ_V%P0n$6tyV5}EJ!z2izBE|+ zKpG+ql|Gb)NgqkWrH`c%(kIeLX_WM-G+G)XeI|{SK9|0bzLX|PQ>1UD@1;4?FVX^O zv9v+jENzvxNoJCTWGUH7_L76-C^<>4lCR_^1xP_suoNPNN?}sC6d^@QQPOTHwm)`& z1WB-jNO4l4v`5+}B}vJWTtX#GA|*;vNVLRAti(yYBuJ99UrLcw(g8^=X(X+rll0O- zQ~du+*MFLHNIEPXk&a5~QihZ%Wl1?wu9PR`O9fJqR4SE8YjoTQwroTB_jIaN7LIbAtZ`K|JM<*a{#XQ+SW`^aqN56U^pxym1v zKPi7!E>JE~E>$j5u28O2u2Qa6u2HU4u2Zg8ZcuJiZc=VlZc~~m&6O6)?aCcW zOQn_4T4|%SRoW@-l@3ZrrIXTG>7sO1x+&e29!gK;PNkR9Tj`_pRr)D+DgBiJ%0Ok1 zGFTa+3{{5p$1YqMp^Q{UDR(QQm4FgdCMlDZawV$7l(>>ml1fUcP|`|9DJVsyq)bt& zln0b*rA9g9Y4}s>>E)+)pZ+V;fAf7G@@(j{51$QtHvHL$XP-P9{p_n}Uq2i7Y{IjN z&!#;4=GoL|Z@!2ByL%v$y^_5pds{X@_Kxgb*+AKQvO%)PzQ`u|$6%&mCRaZBeRv+ z$?RqQQ|e?+GH02K%vI(l>wi63<|*4L^OAYXd}O{dKiMvszbrr&C<~GW%R*%RFW|_+ zWf8JSS(I$IELs-xU;6g?{kd@^<=>8Oq-cNJ|66|MZ?-R_l>Je%NT&W>{`a;2PxIw} zRbQ=B>3&~Zr%Tlp^h*xu4*pS|t~>IFd_{l#Y+YvmQT}g|*ZqA=`J>+N?fiLO^A|eW zzc~JL?L{*Ee^CCH`io@6f2dLN$C`)#nEPw(|45SYU#R;Z+5Vp^KhW<*TK{&mf6MCM za{9O2{w=S6JJ!GbzmW?615eBTgYthRN~!(VrzT~wZplCJY3V;G`&aVyU!|`psjAci zsp?csYHF%BRhOzyJ(!x7dMNd9>XFo=sp+X1sf%QpsadJnsX3{+sd=f#`j3B~%2O*+ zkEfnUtxT;-txl~;txc^NIjX_nc9_V_>20#xAotV z*J}Tf)fBBtdqAt!YP6|ZomQ_ss7=!z(jL|x(H_;NYcsT&+AM9hHb;M|-!wZ(aYefB&fOrZN)&69E$e69E$e69E$e69E$e z69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e z69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E$e69E%}|E&aU^#3-GeVOiH%5vSI z{@JNVQjY#M2R%I{W{~&Kg4JC@8b05{l57(qh_i9bFKf`qr0kms{5)3s)wpas>iA)s;8=Fs^_W~ zs(hfz|2*YI%CnT0zj?k!w^p}KxBl<)`A2sC zRm$rAEXLLSM^%52Z1|(!4ZleYDQ8kP>Y9JcZ|W~=>d&1>sZ6O&sYz-3P1^q3=l}2d z*_7Ut<0j$5i>M0#%`^NL8#VQI)F7ROPA))p6B{zuCsWB6YQ1qfgaq^*X&?e^8&M zKcqjbKcYXXPuFMYGxb^eY<-SCSD&Xprq9FzEoePFV|P-kLyq9EA>_S zYJH8qR$r&D*Ei@J^-cO_eT%+T-==TZcj!;*JM~?9gWjm`*7xX7=}+s==zH~N_2=~G z^%wLP^?mwF`pfz&`m6eD`s?}|`kVS&`rCherZCf)>nwEJbvtyHIxC&E&PHdev(wq@ z9CVI4C!Mp-Mdzw>)4A(Bbe_7MIxn5K&PV5~^V99p`Rf97fw~}Fur5Rw`Va22VY+Z# zgf3DSrQ5BG*2U@o9jJqJuny71>Ei!TFF}{6+w(VVJW6@^AKo3Gq&)sBoxQq!e`W7M z%Kbm+-T7^QFXirE)%#oLSduPTC)c5WW$$n4{(af)lv}^GhW!`q{QVaGR>}GPHqZSZ zdHJ_$n`9;eCITh`CITh`CITh`CITh`CITh`CITh`CITh`CITh`CIbJ6KuU@#cUl%$lV5V}_>nJHN*MJdI<8>u68)Ndn&i}g$N zOZCh2%k?YtEA^}NtN%E5`;XfFQ(1~yr9Plmt2OFWwN|ZD>(vLSOABb%DB2U8F8nm#9nCW$JQuh5ESqgt}5)rLI=jsB6`A>Uwp9 zx>4PvZdSLbTh(pqc6EpPq`Fhxr8cOI>TY$9`jq;#`i#0)eO7%=eO`S*eNo+~zNEga zzM{UWzNWsezM;OUzNNmczN5aYzNfyg{!@SdE$66r(!1&1fAcg&qtYDEs5Kf*sz$5P zY4nCzZ9MoqV-M{`PZT60Fz zt2wJVr#Y{=pt-2&(_GSA)?CqC)m+nD*WA$D)ZEhC*4)wD)!ftE*F4ZX)I8Gs$qNU) zv)<*;B2}rY(pBqfbhWxVUA?YB*QjgKHS1b*t-3Z{yRJibQrD^L(iwC{UAL}BcS?6! zcShH%JF7dVJFmN-yQu5aUD93FUC~|rA00pblSii9n;_7qx}>_Sx}v(Ox~96Wx}mzM zy7d?T8?*Yev+Pau@xQ;#HUAIz_}@?QpRI+p`gMOduIu$1^c#OG-Sl^L{%`!*{5Py@ z`AxP}zwNiZ+27FkziGjwYa(DGU?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5 zU?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5U?N~5 zU?N~5U?N~5U?N~5@UKRouq`EbG0{2P}a46Wf8~B|Cr& zL-z5$HcQ}0XLpnKa*I~Yymr<)KFP+uPU=Gz4>yp zJ>UR10#3lyI%mKIC^NVMZh$-B0eAvCfqNBg6<)yA8gIY{@CE#UU4TCj00aU-KrnEq zIs^y>!hmof0*C~nfco;?z?Jr=C!>Lix>va=hVJ&qrLjO&ho-RH(ARXN1OPxlXMlj} zR(%T$AV3^YY`ATF)L2j&4-^(_3eL7Y%RF0XD3A_h0GYrO zLwQ>kkPTdIDlK}Er^!3rk^|%ddB8CsAL#C^Y`KP7BZqv;plv2XGQ7Y--F&>3Y!B-rfoHHFN<@1qMK6JY_uF{?c$K z?{U{F!!tvQ@xlos&<*6aKQNp&_5jZfr+~i7)4&;^rK}e?3*2e#Nk0di2U?3#jTZoo z@gmR%Tmmiwhm1#zSAaBQe%)2z8gL!Z8*@8v05^eKz?m$a@iy?X><-XScNaKlya#BF z_kjmMy73|K2*}8N3_Jmz0{Z-CKv~;!-~~|D{1SKtR8%YmPZZxcc{a1A`g-YM;}Y0o({~0yl#fGPZzQ!EK;1`(|#o(F`;P zEx_$yO6d;J60`!(7@MkJl^ru$gEpWoXb0MZUG*>X9Kal-BbaAAka4a(-{=HZwm5^i zMiUKQJqO7w8WLfEC6- zFbE6=L%>il3=9V&z(_C(+zm#9vET_~ZUz9B8bJ^O^K)SEehC7`f$?BX!@Yu*wgm9F zF%jGYUMb!Sre*B|lfY!K(s;c@4ptcpjlCyOu*6tyEHh#t4iX>?m1+`$2Q3uu=)2j5~K`;$G1Re%!jYq(v zU^V?h*39L41vR;)ogDqey*aqetYX>{P7iA~GPOu9!fKSqmU^mzU zo&ryUXTVm6@G^J>yb4|euY)(ho8Y7DTVRv%HrQ-bWw#jbfOo;( z?0evS@B#P`d<2%KKL($GPr+y4bMOWD5^Oc*)V=~2Lrb8g&@yN_v;tZQt%6oVYoN8z zI%qw#0on*{f;K~2pu5dmp>2>EWDZ$C+o3k&4#*O+f-1|cAsfgRvV-g)2gng}f}9~2 z$Q9}|9;tPM+#wIh6FO<^Fm@StLSB$J3&*$er^`*Jc`Qv%eF(@Bu%PoKkq2rCWjCYJhP%%^j zW#yDYIk{y}IaC21hfYB1l1iuwx?WQa)j(-AwNM>YpPrWgwEVoW9x5u!%x{1U`SmSN zGA>s2mR!uK>1u?Yv|cJYQ`ZDFL&ZgxjF$~9P%G4Zq776_(tA?n3vVvsL$@ zqOO$g2T*?bL+D=4mGVc>W9VVg6X<02Q|KA=9C`u0gkC|5;U(}=_;mR)_~nV^@Cx`? zQD)vscolp*Z#BFIUJI{-*TWm&8^(=rN!2F!aA|$vW_Sx+m$MbF?dfXS2In^xr9aAg zTv*q0w7?9$*pZuaKc~~sQezHVz@2$5)m?_|@X^v8uq9mBV=!33)^J11kwP2T7Pf;+ zuD6swEWg)r@>q7ZJ^V1s0d|B-YMo$b*adE>bcNkuci33@yvzf>li>*)4Ndtw;o=-G z*cD6IyINXwdpg01KgwHfY!F5%;;b=G(24E0AYk=T01{g-*UPBxl4=2E{(i7p!C41ll zbq|X6!u#MPI2q13CWle@)-epmVFD&$3Rb{0%)l(n!RHM;Twg4}7Y!E-A}qm5ct4y1 zzo=Bf2Vga*R=5prhmZGkz!{|{;ZC>< zHo!)>8!kH01D}FV!)M^`>R$LPd=5SjUw|*deefmtGJFNT3ZLk?249D7z&GJr@NM`G zd>6iA?5e#7--jQ-+4*;xYC0amkKo7f6Zl1XTlQ1f*zyd14!?k3!dH#2;QBMyjf;^b z$Wmk(l5RL!n31s@>B?#{tUy*GtsSe7)ks$H?b0(KYcDsQ zD!iWVgg7HE$ic$HEv`s<#>KAEE;mGz^Pr;nggfGa=rcW$yv&_QUq)tc(MetDp^B4+ zj0!KL!_d*>jhyZFLCTtZ5kDl`aO8MO`+=riNOn2cea*|s9f$-W!AJ;l zu{sn9L$q1p$i3Vb4bRFVkVxclSrn4rdakwFup5a+Vi5oV5eR{iGnohyhxC=jBXf+O_?0wEC!Q6MzJAS}|*!y!B( zAR?lvkq{-aA2BqiAg^kgGF8X{M2%>WRHU>0Qf7KlYkOLKcAgf|A$mlWcMwTK`sxlL zDK)3+E@s?mIgGSc9zl*G=}2YItDFoZ6X`Ck%)eN2vpfsQ?ak>e>})AEo~%hfkXu`- zYsl)&t7~h|Mw$(|ZIuNj^(75CNM7%qob29QBo8@;JZ#TLI zijYH%&yU|Pcu-c+c(3_bZ)I~aQdW`Qd#9oVDMiYVmnG#$Z+S!G}U^4<#MMDKCr z1add8HoY^qBd-!URPeH)qco%bK~)u^>#XdpM$R{7Wz`_H$cv_&>^h{n=}tjCa;~WX zDQ;~2J+T=go-QC?i-;}4j`y5*VyRj8p>_%x35WDlc_ciujdu`uHlCx!`Ycy#r z$&)mmG?6so@+P(Wd`aCtf719+ASsv>N(v`UCPk8_lA=j%zA;~ES1hT;+2w2Xd7I)% z(@E29%g*h_MAA&saLsH|vu`fR?VC>;XPRbZ`J6DoAYpVO}%2$)ZLu*Mb zzM6{6+V!N3r0x0+U#D*~smHgKw4Jn*w41aC@c1Tudx2r!kgshxMQO)2b>2k02hHvz*Ko@ zQ`|S!mR0X^T?VcI-rDu$?Hm1a1MhfjhumpuF%N;BzK?_knuP10dY{ z5O@SU2A%-R9o5B8fsFiTz;oaQ@Dg|hEclu`7k#gRH^7YVE$|L_4}1VV0-u1G?=$cP z_zHXjrhVUmIp4gmy7C9`6Ik;70)7L_zCS=})-_B5ooy6A1M9xzd1}1ycQK z{{QQedh&pLpx7VoEC34pg+NAap1-2Y?r&}@0*Zm$x?KN^GvAr*F9Aw{GGNtL4ixz- z04GrHuLP=qY9Ob$!e0Z_0)^eJ&N?99Uk@|@jerYi0-AvqV6&$cXam}T4xkfo16@Ej z&;vO9y};H$AF$@@2d0_^fE@oIu+~2Wl={p3!@vkI3XB0Bz~vA0i~|#Z7pU_406);? zZ}$g)AP@p-{5F4DTfILF6#6HD2rvaiff&%*-sq15CH`rkqbmV4cDVh`{s#XH(BYp2 zoc>yWoqrCP2b%l~z#`D%Z}l$$o&IH@(!T<%0&BoJumKEo4Ei^LA%CBL3)lvBfL&k@ zxEJj4cUA2J_k+Fu17JgW)5t;aKkyKE7(4`S-0Ehh-!Asy}@CrEYAMsxWuYuRW)uH^N8(?DiCRo{V3%m`E`R{;RU3bBI z;C*n^`2c(fJ^~+uPr#?(Gw?b10(=R+0$+mx|AarM?+y4CdAmVRp{|6?400@GUeh7p?1Vq95 zaty>l0wlpHf7DNbG{}G~$bmd4fFc<4hx`&Kg9@mE8mNN?SnHhXG(ihY2IKw|FcnM# z)4>cd6U+j$K^tfX9bgWa3+93O;6`@=SO^w@#b60o3YLN8UWU+6~-{cO0W2GT53{HX(a0-lq3;r0GKM)6} z!OXhe;siJYW_Hc{XTdpe9$fTyRxE&v;ATaYd&$29E`uxJK=ZPH6)YTB12bAz{VV=; za0A=~x4><12iyhsKzpHm(0=FubP)OvIs_etjzDYvqtG#^-hCW80iA@>+fPBKp)=4~ zXl!8EGwL}9jd-Ri#yu0Bk&^S!1!&B35xN9jhOR(YA&)1y$mh8RU5C~yZ$M>3HzB|0 z7IYiB1Kou-YVJYzp~|ucP>(0Kv#_?La(%eJ_965LdJH{*oSqX z%J?WW26>>8mT_nT@MV&tacCM!Kr>K& z?JP70%|i>&BIN5`f|j8bXccNGU4z!44QLbEg0`U@XcyW8?}hil`{4udK{#vtKll)Q z7(N0Yg^$6<;mwYv=@alt_!KF2J5f^o3I5Z!zpkooCc@E z8SsE76V8IOVH-SFV22%W4m{||h4bKixBxDMi{N6o1TKZk;Bt7#Qvo~SO1Q>Z1y{p0 za4lR1*TW5PBkY2k;AXf5ZiU<6y4H5M1MY;~a2MPS*S5E{_P|BMz3@g`AKVYO)DFOd z@Vavd9)_#>M&MC+4EDg|@C59IeXuj=hck);a1bsp2*F`^5{|%AaB+DQc6G<#I6Ms} z;HlA!?x1@Ho`q*d{iSnoMc+KU09RHl!b|WnyaHDQ%Yv)$Qt=v`=(Kk(maW5uBh$T= z&J8%TeG}e-%iP=W4(#d+*Y;EeN_XKV?;d0?vJcshG<&N&2awU;gUEkKq`AvATXqN; zFFTAJLAGoC!$*;o=3~flq^h9RTTngR+3r1ow0Tb=r;yXg8RRUIC^?5rw4FyTAPxB! zkxR&B@B@*dggO^$p(W*a{upODYU z7bGq675RpIM}8o?|CcWgyMH3TkovOi$(_m6$ZzBiGU3XK{6+pDnUN#}KtKdSU<5%L z8&SmDj3GE;ix3EjPza4M2#at?nTtmRL_|^|RqYZYBMPD-q3XtpjL2Y5UYCaGNOmMY zVjvlPCSt43iC9Q7l7gfnX-Hlq9qFyhKr)fezAPjgu_2jNcEo|?Ah}2$l8+Q1g-8)n zjFcdyNI|3wS?w!FDi9~qFYDsv;}MDzb*GBeBX2WE0s!wvioV7ukc>ME0Wl(EaEE)EPO5{)d*; z9YPPIN6@3_G4wck0zHYILeu(dBg<`#k<;iI)D=04oa%dI!CW-b3%B5739`Bec5lG5Q33iatZ1qc6~xsH?Fd@(O*8zCquj@6h+? z2lONQ3H^+ILBFEk(C=t{XpuK1xIuPlP^rHjl zAUcE&qa)}jI)-}CadZOpqCV7*2GAfHLc{1J8bPPfC>lfK=ro!@2O~4+`sge=hYm&N z(FJr7T|$@96?7F{Lx&^l=mxrpZlT-g4!Vo(!S-VNu>IHp>>&0Zb_nYqo`@XAypiGB zo`ECS&~T)9u463HIMOwo(sLB+Zajt^$9$2Rs)h?5bKGuT;d zx_x%?95x;~kFAtlz%F8!u*+Da^$KWI5?`&St1SPH{lI==4UNCBTxZI_Z|o2D7yE}LVE_hV5C&u3 zmONLY5W#vYPz=K=CtK@rjKJ~+NsPj1jKNr}YLdfhCV5Q2L`=eDOurD8Q*^TTOaI+lTDV#z&O*l1feX2Z5hM%zLR9&EY27prqOHS}R~ll_>hVSaJ|8^ngNVQd5&#m2Dp zNw?dBRkw{}6POqCVSX%t1+me-tUw40W0P0}OY~1+@s5S&C>F!w*ff^F9Dx~Z7MsH| z1KELjYyq|dRTY_z!mmO7jolhw&r$QM@>C4Bx0dj#mUu;3x6Q zz$yGReg;2_pTp1NHGvEGMf?(e8NY&G#j66>@ay;u{3d=2zl}Ey-NEnT_wf7p1N!*SeOOyCW@Bu?Qp z&fu*97U%Hh0FMi}h)cMPHw6^DG0+fD@wx&H*Kq?cA9Mvw+`^Ob6g(C02&CcZcm|${ zXW`kn4Y%W+f%bp{&%tx?JUkySzzgvrd~>cCFTwi*eSy-JQoIZ=$189rUWr%X)p!kF zi`U_8fqJ|F?+P^HJpmWqgg4_Ycq`t9x8ognC+^0(@PR-#-WzZSdhlMnJJ5&s;{*60 zJ{TCnhw%}76d%Jq_&7d+dvPD`#{+l}9}0x=kW!6 z5nsZW@fCa(U&Gh&;lKvIiErT}fo*&T-^KS3dx?F-e&PUekob={L>wlL5J!n)#Bt&T zagsPioF>i?XNhyfdEx>w7Pv@UA}$kGh^xdk;yQ7IxJle1ZWDKiyM!ljkGM}fARZEr zh{wbeBDw1+@r-y*ydYi@uZY*g8{#eTj(AUeAU+ZkQ=f>e;)$Wp#22Elx3K6d@r_8U zSQ>6?@z&&4d?$vxeh@#2*}`tmFTz>X+t=FR&i_sPA?CXO690%K0w6#lG&)la5irqL z(9>R3h!B|__A->nXvYYgAc)j%lAwrnfBWE;pC%Y$(_i1T)yWbC^&9@sP+p;H$Wy`* zJRuMwArUg65Gt`=oIIovI$;ndVG()VbNR_c3bE}^CDMp=B7?{zk^`wlSwuFm;_ zA}vr)G!W^5M#4p81PY3qh-RXNXeHW+cA|smB-}(7(M|Lay+j|;PqdX+H^*HAL`vZx z(bqFXc%~XFhx=Xq!$hc}J2*m&5@ST(u!l&r^cRd16GUNgZ_rEl2tTpdliSb}3=qNE zjQ-)0zF@p0NX#_ul!u7i@-Wfg)Lk|ZoFpQ|6cHu*gRP|-!!aUGOcM!WhDdkM5_7~n zu|O;mBf%wND7f8TQd`kK7+fY+h*e^Z7!Ixz8^k8DMQjs0#4fRi+)M5wbL(5{_LB$5 zgXDkYA@VTk362GAbw|jfWLNz$@;G^dJV}lRPm!m|GvrzF9C@C+Kwcy-k(bFUHhG7qilj+~WJ!+XNr4neiIho&R7s80NrQ|`nq;h^pu{4p8lsa^ld;KUGKEYf z(@1w;I+;OclJP)SPZpW$&L$^&ZKR!SFPtuLkc$N~O*v#P**KWrpGS@d^2q|Skemn< zk)FO{vZAP?poAC{Rx}kl{ch=^~rRW^$vyg={6;$ab=W>?9`xZZfC0i|i&Nft0QuvX|^5 z`^f=vkemt(kqsrorV?l3OQKh4^qaz%Q1mnT!;4Zm` z+Dokk_fh+)<>1P|Qt$wEkjiQLkJ=n;XsRnbL>;E)f=8&uU|xMy$5HASm0YqBJWidU zPErL`3&DY&ih-5jP{nHS6m^<9L-n_urOr|3sSDIaYCd?0x=dZ6u2R>i@!{l|>(mWu zJ$RE!pVMiw-dQS~iX3i}4e4sv3X)|8uT4{2quymm_v*Ht#(w*G$nfgNY)qbVE zQ46KtsmmZVUrR2r2|Wl)(^7L`rKTJl3S%1${bTg{w1hsve$ zsC=q`TBYzF)H7lnM3pDGRc z$^ukzD5Wk)g{Uy)3{6rIYKn?dF)B_?QweH@nx*Ebd1`@Lq?V{JQ~bSYg%m(vxrldhzz=xVx#uBGefdb+5ofo`N-bQ9f7x6rM08{JNK z(4DlK?xMTthENaPOZU$MJkB*o7=|op%e5z-o zeWKQsOK12V)q{$t8(4>5+)~H?3(ZzqF{S^$c^C3Fe<;&NHiJ7nqC8X456+GP6{A zh3OmYDXOZv%3NcvGdV>!n48Qk<~FlX)0=;Xxy#&R?lTXVhs;o4s6Bo75mV|eEv=~a z3_fNu%ZHnuFi)9hOrLkOcCewYaEcn2D zWIi!NC7+ou%vUDM^^NKGI(uV9-XMr>3Ks?t z24%A98rz4x+k+UBUx70@t=Sy}GwQ9bB^ipL8HOot&K%BfZ*;NDP*Gn6$MB56h)ns= zcDy)WVq`{PR3=iZF*>u{X)q>ZG0DuBJB3MQ(wN$zu7-4`t1G25x2NA#STf>W87!;n zugqXFnY8>Yrm!hdoXyx6JF_t8U~-t9crKI2v@xA^ z^BwKXLRDpDSxE=e$+(%7rY{<34JL^5qPJ0KtF0h%!7uiefW%detm9^K_)Ldh) zvwhV!*qiJv_BI>y-eGeG?y_F*JvQ#W&pu!uvX9u>y2ot7yHpq}&un`(R=yW#!K{$c;J4W0kkK>loT5(}^(3$ZYZu+B-8#aNsrSdz`_p;(%oE@ar`X_j5~ zaxBk=+LpXy`N@521p=GbDY6nPvkI%S8mqJOUV}~RFj5&t+sZvJ*=~1*W1hXv1z`3 zc7PpZhuFg5VRnQaWye?#TUIpAPOx6q$2Qjc*#O(ol3o}q4zl*)5F2JE*$A6(O|dDy zR9}=$_r=&EXPlj86KsZWhV|CXvU6->+dR9#F0xDPGP}aAvZIBOmNhohx6Y2YY_OZ` z7Q4-6`BJ8L*j;uHx0l<;^>^&&4sZuKo9{m^+joeoFFed0;f`|0xZ~Uj?j(1LJI$Tp z&T{9t^V|jQB6o?q%w6HGa@V-)+zsv~cZ<8twKv`2?sE6I``iQWA@_)T%-MZUxToAR z?m72@d&#}xUUTCEZ@9PIJMKOAfva!*$bI5Ib6>cx+&At!_k;V%{o;Oee>jKlFZYj2 z;s6fh=4&7h=5l9FZ@zUwRc7od;ag~!?dIiPNTvOTZAj7d7$MKxNwO5Fo z#AWulmt{`jdP-DIPCOwQuUrmORlxfHImI+ZJ|PveFPvWn8V3@(%FD^F?5 z;&i)-SVIs4#JK?~Q)wQ)rWUw%7RlIY+%IX72U+QoI(cXOL71wB1n zFE=^Z$Mtvha|7I5b+BlVvzHHXrGvv<^~?y@T{_BDbTssgaUO1*o8Y{hkMnZ@uDUG9 zg}Bm0c6*qccC{HvtlqI5EjEi&A+)j@(k>Dy5lfyIIELWA7qt~!xu zUgVazWp0IA<<_`$ZiDl7ZE~$uTiiA`*qU9^R#P=JHL%0&a=E<=J>~I=xHDej+{5qX z_woDrg7%f#1N=dL)BPWRh(F99;g9ll@ngI*zb1a1Kf$Nho#apPr}@hG8GfhmEWg$m ztvtt{=P&TXeal_7@r(Q={xV+`zrtVTuknrX>wHU3QU4A8CVz{+%{zp2DZ{X?!|A+n&K^@>zT~pVw59Z{zK}gU{h}`GI&I zpU)TYg?tfT%$M+`d>P*#_br$66}*$Lm>=Os`7z$ZkMk3}m-q30KEMb05I@%* z=7-|L|DOy@@)3TDkMc1-&QJ3Rek4A_&+?=3IewmB;1~HNewnWvSm8HY%KEm;SNS!* zA->L!7jE#I{C2|@zdjJ@oE_fgclcd?kFZzRC+rs*273A%rW6^Q@AB;R^Arw2>zbC!abp&?Y_`Ikk$G?cqnv~KN4!9 zRc()jCqiZPsW4mD-{UHrEPf_bMV|{Vgx0~A!Ykpm@J4tmG?l&+s-x@eqN>moZHa0^MN6nm7uuqRFj3nVH3dr;jwTC((ebM8Do->;NEOnA zbRk2?6taYD!5g&+W6{k5yWkLVgj^v{$QKHPLZL_~7Dn=mT%F~?=9<<(Yl%=QlnLF@ zf#^`QTv(_WiLMM+2wN_vFdnTGs)Sf!wNN9}3cb-fpYE?LvppDfpspp}u`I+9h-gJwmULHrOY`3n~Y@qCL_4(*9__FcB@U8xYpo z2ZgMTAz@e;Z(gYz5k`eE!6S?dvFL>06?{T!k6#D~K_MiBg-IbIEJou)Q$kdT32|Xs zNC-26KN^V63Uk7|u+iJ$+$diV7KMfKfq}W`k}w-hMCU8|IwR4HuEpAAp*(*fIv-sT z>V{W^aCA+`cBi(j3+0ub>UeZR*c7&eZDB{)750dG#eL#_F&GU+C!-}LQ_-fD>F7)} zzdCpLfVdt#DE=oN5)X?<#G~Rd@wm7WJt5}1SEDDzQ{rjyjCfW&C!QBCh!;g?{UtFP zy)2eB&gWkduZq{i>*5XZrg%%dEiOmzhAB#`Kr{Xj5x%fhS zDZUb4i+ycx#JA!*v8&PF6{&kKeh@#3pTwn(&*DU9NzWJYs~BkiCN4$4i$BDl;xF;H z_(%LJ{u7f#KulDD;zkq_VG$8g5fgFI+enC$&7`RwtHK*NY8e zqv#Tw#AdNYY!%zYcCkb36t|;0QMcG7c8kfe97;Z@IxRVB3u4aL8R@K)-f&JjFI|xGVi%>R@=H=q?6Nf8UmPom zmBp?|SEXxGOYFLIL%J#5l5R_Pq~^M&*j?$KlpnhQezC2iei{l8pEZ6N~N9Ql6AA6-b3rk>n{X zmRe&aQmIrXl}iv7zq-v=~$}Ovv>ZE$9L28s-Qj^pywMeZ}o766K#5!XgQm5pW zx}j_;Mw*rCTjr#BX+c_)mZW8AMOu~mVr$a6v>|OuThg|) zBaOydi*}{{*dBSWyieXQACTv}56b_^hh%r`uzW;5Dj$=N%O~WM@+tYWd`3PiuN9q> z&&wC&i}EG;vV27zid~hj$z!qW@(uZ>T-Ql?~DW@J|8WL_3zQI=#`R%BJyWL-97Q?}$} zIYmyD)8uqHL(Y`5HiOY*Y3BA2yv6_-}l^`s_N zs?63NQ;sVq zl#@zE;*@e)$xPUK&M4(AXO(kGwEVnsLAj`0QZ6f3l&i`$<+^f1xvAVzvJ$tIJIY<< zo^oG#pgdF_DHTIIgB``yh2gHL=EuqtCE$LlJX4-4FO-+cE9JHFMtQ5eQ{F2dl#j|M zWu^GDQrF?D`l5VQzA4|8U@R1i_fE!sC>zD$*iWUXH`v}&_)Ce#ek*^Jzsf%)5}S%8 zDS%Qm1S*gME3sHShA60lDY!x?(=k$^6k1^vR^b$05tKwsR3t@K6h&1uMOO?ZFHzCd zRcb0reU_4}q$sIMnv$+$D6=J*%4lUlB1_3uLVY&Ht~it&C07Y`3wE1|l%9fO#okz=lqzLPxl*AN3_6ucrAnz*YLr@~PN`SYrt6&zN~7XZ zoSjWdv(loZPq!+W(``z-(xGHccPehBOUan-R(h0PrBCTs29!Z1d)hv2n;uezl@VoB z8B-k79;LgzWMrXnTuEE6S>}rmQO)ioJVN*;2L@f2gHxN2ze`DtpwuYH@EM6mQL|$f+JF z@^tM}_p5cC2h@Y=e`+)o3oW}3sfX1g>QVKWn$vk)Evh=9#zQC7>Ch?lv^v&vMm?*Z zQ@5JO%Fe47R9{Pb-%!^@H5^KWE~$%c^+lJ}E9z9}s(MWgHBW}Ft2fl5nMmlSdP}{n z-cgI%?y8Zdd+L4lfm%}WP_1lyq=rJ(O=HaF>O1wlTG6xG@RPL+YO1apYH_!zW`%RZlMR-dtQME1sHtk2nyzN3nd)M7 zmYNdIR&8p`X$#v`hw2FDsJZG+sduO_oTui5^VI^iP)!aOsk4<6?v$3cred{3U8^ru z)52wHQH!Ixx;i~vuC@#Z3oBH6xUniP>{O>K^TSz91>s7yO08CF)X-pRZLR7I*QsUU zdbKj#pf;-2VVByZ4mCHcEo!r~qpnqLQ`^<#^5SrZ+NrwLE;V_eTkTO(ox9b&YM)%b=qzrMx{nttQmYu&Z}QomHKEbLzaB z<6KY|)dA;{x~#6KtLmD%t~Q2eN;cF@bxU;**M)bwYs1^>j=HOk*SB}>(e`TlwEfyt z`vL8s_Mdi08+IMm2L4|Q9?_0!$F!DkefYTM3g?uZ&`xTj{in3%@M-Ogc2+y5ZS;kT z&uhh%7qpAoY}+NRruedUMZ2mcDz9no-s{>-XUWVB?WT51yRF^P?rQh6``Tp71MQ*q zNPDbh4Ls30!h^#N;ip=9byN76_FRkfztGyk>uoQ!S6WT@wf07v?0>7h({@|hO5bbS z14V_y;SbtJ?UUBf^;vU=zi3rmUo}tpH|@JN6#k*L*Z$OgX}`6u{y$ox@vrtzOVR)h z)F2Jk5UsUoB#dg9hHHdIYLrH6jOKE8hgpr&cumj-!h>N^+jUA>q+8Y$t#(k=G)>p~ z!iHvQmX@rgXsKG7mab)JnOc_C6VBFbT36VvIkX%tSIg7#wF0eBE7FR!60KA#)5^69 zZPIOPcWRYdm6lpptz}gAhikN2t+l*PtJfN|M$M&7g^LH8v}UbEYt`DccCAD6ggZ62 z)}_tWcWXUbEZnR0X;Xdu+JNQ@4{HAKkT$H@x<|B8ZA|lM6CLB)ShzPlp-qOp+IVXy z?9=?(lq(nxXn}B03u$3(yC@o-)FRrH7S#eJF)gl5Yn{UhZAP2bBH=mBQ8};m4R?30 zPcLZU@S?V)tyU~+E842&9vTgghc_F%;We$J!ByAOu&%8X6n1WCo7$GPt?g*L+8%wc zzE9t;caDTo{-9+zf_=bK{zop;S@91~+d-{F-f&Ng>bv@D_>reEV@KgPn{#<{d zuZEYyyA3b(iSR3ZKKxqWZGWS?2H)!M^o8(y{e%8d|D=D`zvy4}&E9YNcm0R{Q~#y^ z*8k|!;Y9ea{!dTR7sG&V?*es5hjm0pbxg-~LML@f?`WcRMrZZ^$8)-~f!76H)Z<}E zmvu#NuUBO;CKe^?*U(xt&Aw$X>1wW#*Ptj_Sfwii$ik%`%`>1)$JZ_#aPnxI9(`L+l#++_C zYo0UDo3XMB=0)?8dD*;TUNx_o*UcN|P4kx7)?4npZQe2On)l56W?SNc`Os`nJTmJl zI}(r0V8U52TK2?zYCbccn=j0l<}35H`Nn)}zB4PT-khY~AYU1qo0WA>VTW}t?t=4fKf z^qAvjP5y-GHGQVv446T4I1w^O5@B=FjF{oXlo>T+X55@M6XuLLYtETft@GxBxo9q# z%jSx?YOa~<=7!l)ziDon+vbkBYmO)Uy?d;^);?>$b-+4k{bwDr4qHboPvWR`%sOtJ zu;vC%S`&#=)@kdEb=Ep(owu4j7p#lcCF`xK2wdS$(~-dJy~ch-CBgZ0t+WPP^2SYNGg)_3cN_0#%g z{kD9GKh|ICpOs_*7HB~hY#|nE`4gCxF^pSvO@u{SlvOpIn@?Me#ahcX<>h&OL-`ve zoK-Z!TaFIFnh1%OWXYCdsg`ExmZLe6Z&;>fSWemg4oU0&A|T&?>TutrBZKz8o*L%B=0Sa;w5h zZE;$aR+TlK*%aD zO9aB!q!qDd0#jD;@N8f%(AgigVpiOmwi4EiHES&d7Ha1MeI;|&ytQDJ6)ajy*0Qx? zEd>?>tJb!2%~}quTN~DIXa5h)(w;iw@wEbs0WIJqI z39JQ<*pAxjO6$9`+E)YXgWLV9Z4Yc|!R+8e+asGj_}KQu_SDwaGc%Oc=mZ*2Zp zPS6&7YkOyVZ~I`gR~8L?w0*LDwtcaEwSBXFxBamFwEeREw*9gFwdDu@*^+E|LBJM> zfi}nn+Ynnp5Vc`8+(y_)8)c(yjIA)p+Bh3;6KtYQvdK2ZrrI={ZYv5VcN(_hplP#g zd+dAd`|SJe2kZy!|Je`O58IE}kJ^vfOM=JkC+sKfr|hTgyFF*@XYK6`=j;pp=j|)* z3-*h4|I{V>WqV-iiv6nnn*F-HzUGGgru~-vwmsf($9~s-&mNw-Z+~D9O+B@V%Xsj|wU?pO9eeQfHr{f+&tJv#Ny{@%Vkm0I}0{?Y!){@EU% z`eKhveYJnHf4Bdz|FkEjrl*{3zwE#5;lV%l$*JtJsj0vAfA%ChUU^Q6k(4Ik#@>X+Zp@J6l-6c;_M4kyj`%1c7MKPm+gvOwXaNRcHM5+O}k~^1X?b6j`aaNKmcD!-Cb)-h$Io>-yI6gW)IX*kS zIKDc*Ileo7IDR^QIet6-IQ}~RIg%WJBO?kr(xZ?gGrHznpGu3uj`>zw8{+sMLua+! z#-aq#Uo$f^Gc&Wj%*@Po=-hzCG-76EX*462Mg}<+Ih=L#5B<Z} zUjpSQT%ZC~iK;?XqiRsKs5(?ViWI;H2!RGvBdQ72jA}u(qS{dHs18&osteVP>Ou9Q z`cVBSN?-srh#Eo-qef7ps4>(yY63NhnnF#ZW>B-JIn+FA0kw!)LM@|KP^+jl6gjYt z+CXihwou!s9n>yr54Dd{Qx8ygFNY}9%Ml7Idcd+J$0&#L1a*o!L!F~8P?xAHlv0Iz zxJKQeZc%Y){6jpNEs_!w(23|IbTT>xor+FF6CTph8R$%O78)^TqjS)?=sa{jx&U2> zE<*o+i_ye~5;W zny>#)-h%!QK)>*Ct!TjaRUy@z84uDnG(u`eYXtYC4mA21Mejs+q3uXF8uQ$P?nU>Z z`_Z2W1L#3C{&@&JjK)19%n>y9nW7p+kD$V}HrQ;Dqo?NSlpuz9_H{%p6QECJ&R3DZn^%j+a6Vh8UpuUwkj`M6MV2 z3!hkoDaLqSo{c4#QjATZW8oQPm~u=7Ch&s1cwgS&D=}|PfS$s-lT=}MTJtaY1njZ1~wC$g~f!jvA9qUHW!?U>#yN%t! z?qc7I_OSa{pUE3K!1_Xm*dy#Q_5^#1J;R=3FR+)`D{O>+jlIFz^taeJoYoW&#^W&h z1e{-&h)cq8pXpeVQKfYS_g0pU%fMygE5()J*n+p@a@u?ac9@l_- zBWuJp;ex?tTnp|c7z#4@tvDjP4fh;u$93R3ab37>To0}n*N5xJ4d4cG(O@_@gd4_< z;6`zNqk}(&iv-7U6Szs-Yj6tp&iGC{jhn&E;$p!$oQ6M-Tfi;imj1yuz6GP~C)W4i z3htX?6=&0~;nr~*IHCE~xQY86+`?_+c5uIfySP2vKJEZ_h&#d^<4$ltf-J{50git%aqbbJOr z6Q708#^>O3@p<@sd;z`?&nFk*i}5A+56?8qyXXI&OYvp+a{N6%OsK$D;;Zo0_!@jI z{(sN!pQ-9Pd_Df-^EX}tz7gMqZ^pOaTk&o9c6{8V(-QG;R&LC zyhuENkC~*TK|EeQgdfI_;J-YN;>Yk`l;ilj=L!5IehNR0pTT2|vv}0=9A5A`k6*wq z;+OEt_!ayreht5l-@tF;xA5C|v26#xi{HcV;}7tM_#^x={sjMyc#1#6pX2ZN{?G;f z5`Tri#^2xpnO=8`|7?mQguliUEUW|qpBee8Ab-Io5|RkXgcJfsmP$w?kb~(2N-%?v zNys8(6Mm>Lln5ILKJu{A96~N3kC0C&AQTd)!6HI2;Z;Onmk>$`Wdug>yRe*~(N+*X znQ1|Ku#(``RuR}iPOzFF2-Xm433UWXu$~|as)7My13?;WBs3AkK~}Jt&_cKuwi4P1 z?F5migV0I1m+B1MATP)d3WHsQADnK&8)6Tkm(WM(Cj_Vi1Wj;|Fhm$8j1aWJQGzTu zMoKft_UiFQ-o>43}KcqM~JEC2@8Zp!V+PbutHcRtP$1;8-z{57C{#b zbMbn4kRsV8>=1SddxU+$0pXBvMEJ@$CY%sX31@^C;W^=ga7nl#ToY~xw}d!iJTZZ2 z3MLZ2l9GtYL=q2$y_csDQ;BF?8qp9;CuR^ciH}M*DT`VxKBHZh0zlax!e1oMd2 zU_KEF77!JwAC6*D(i50|G;WGmaG87N^N@5kUnpi`$1#5|Q#Cl=_@lnu7 zY$6JY&BPXBD=~&`BeoMeh>jr02@pGpUBqr;4^b)XCH4{fiEvQB9v}`9hluvzFmZ%9 zN*p7O6DNq1#3|x5afUccoFmQ?7l1@V%2MZ6~75O0ZbqLam{dY4C6$rNNfo3@QWdG1R70vI z)sgB+4WvdA5^N$hlUhivq&5;u_V5(qw385N2kG(YS=34DB6X8`NKa3_q@XDH)JN(k z4Uh&&L!@ES2x*iwMtXS~Cryz2=E&0|X^IqjdVc!)^v)cTKFgy|)1>gz3~82hubv~l zKH)_3qy^F~5^^cIj9gBxAXk#B$kpWEPc`IPaviyz+&~WM z(UwO}BN-MeXia2~hAD3*)08dbRvXj0^-XgzIZM0GBMoJTbRYxZhBARH zAREX5a)CS`A1D9{fg+$7_{%K;N`W$<9H;;)fhwRHr~zt$I^Zq09%uj>fhM3CXaQP* zHlQ8o0Dj6kfi8e$>;`&(UZ4-4v8XJbu^$)!-m(V)jFJ=@0)~MRU=$bw#sLR&0+5p@ zfhk}bm;q*iIba@G02YCei62=4mH|Oz1yBO3z#6a)h$7<11|Y+30>a1^AdQ6N+rSR6 z3&U+uy`>zSFET+B?OQ;TfDb*4wqgo??w44e@DyWrId!&l$id0i; zsI}BOYCW}q+DL7pHd9-utyD*(joME2MBI@MYA4ke>7qWcyQyCZJyd6;m)b}DB<`n% z83WWo>JW99`WP9Zj#9^{Kb*O3Q?aU8`Mqe7S$K=M;;qAQje%e zyB9UZT3N4kEMhivKX&-qR zv`ktSEt{4@gMnBimzGD1M)GL|v_hJVSVSwPmC#-z-y)^7GFmz9d!&L^NvopKIMuWo z+C8V1R!6I+HP9MqAz>4(nbtyUrTvPu(SAnSX&tmqS{JRG)@eVRT)pQYO+_&{ffQ+*SG-T`F3q zn}`JC27QyhMb|{tQEe2IZ_{_^y67&QYjB$O==<~o`XSv(IieraPv`*mlzv91bM?_X z);axxeo4QgU(?;h8~QEX5H&`>u;Li;3{y0Lk;q75*rLe{a}47K@$amqMj*f{5m3&thmigC@jVcas}nDNX6W+F3*naoUKrZUr* z>C6mfCNqnf&CFruGV_@E%mQX1vxr&DEMb;1%b4ZN3T7po>WNtCH|3!UwnS0EA<^l7NdBi+so-j|DXUucv z1@n@5#k^+TFmIW0taw%eE0LANN@k_7Qdw!NbXEo{la{@mmyPn;^ zZe%yHo7pYwR(2b^o!!CiWOuQ<**)xDb|1T+J-{Ah53z^YBkWQ37<-&O!JcGKv8UNH z>{+(w+Z=nIy}({%FR^iyW%detmA%GZX9uGj>`nF-dz-z(-evEx_t^*RL-rB-n0>-N zWuLLn*%$0f_7(e@eZ#(G$8q9037kYu5+|9H!b#<%and;%oJ>v@C!3SQ$>rp6@;L>Z zLQWBEZNp`Z)cZ0nQ+2h%?L?;f!*|IOCiN&LrnKI>njh%y54AIjo=lC)zK+T>ab6FpwF4 z{D1vQhE76Iy+LL8&K=^Xe+S-cQ3%5O&XO?+N;HB& zo>@N45(klM6bc3w`N;UD!6D0>?;1QpKzKwVLPGvZ?^I4c1>xdCgcS~eP!XG%WBi9V zpCf6c5M2{E{snm#=5Hn&ytca8eBCN;;#|&(8aFQ*~ zHfM*k%h}`Xa}GG{$RURl;YN-)$D9++Dd&uH&bi=Ra;`Yn96R;9@`iKE30QEnIIf*X zd5-74qa<(>xk=n)F7-Ku3p^XKsoXSfIyZxx$)!J=j9<-J+-z9=T2}Z zxl`O}t~4r(&T!??S?(Nnp1Z(Zk&1(vwW+>q}@zruA!SGfw+8h4$$!F3Tfxm(i@h@g76^L~WX#2wx)Z;!XnJK!Di zeuj>C$Gj8XDesJT&b#1U@~(K-yc^yvFOH87;)3z~1in*l*Cq0~a*HvE@0KL<9h^6e z6n-i{ji1iX;Air=k6HX|{(DUh-)+j}i^&#%^QZ#y`0U632vX`7Q$9aRkx>fxh5RBu z!eCKEkHviPBNeM=m+*y;fApn%$zvJ6oG*Q>;8*fhlqx>&QSkUGHJg-1yhi;9s5Fn& z{Ews>el5R_U(avg6L7l64~j;96Tg|?!f)lb@!R?T$~PW6_}WK@Q1$p;W_j^M_VEL3iO&28Jw5@J$9_JIIl#AQ2Kf~15FdVo z1jGCh{wRNpe`gx!Pw*%CPT~}Qn*Yk9GG_R*eDKls=rlZt3#9%}@(g8RohLA{_s&?uk+R<%#?_3`BqR7jLzY?I*iv02a}Xce>x+6A%4 z4gntDDd-Y(3wi`jpjYtiu}{!17!V8!h6KZcC)|i&R3KEm7kp5U3C0Bzf=R)Y;K$>% zU`FuvX;u&x&Ix`#&I=Xb!%_5yf+GQ>I~JS>P6dA+&ji07&jlBPOTm@kT5uz{6~qbSg$cq$VUjRem?BIS zrU}!98Ny6qmM~kGBV-VAg?Yk!A@-p_SSU1@i-cdIQ9`k>L|7^;6P63PCZ4H6SShR$ zRtsx{wZeO&j8!N6U$kEMQTH+WDcT_X9F?;i`bJ@suvyq5Y!y1CE@_*vUC4`c2>r57 zVOY^6>=yP2dxd?%ej(XSln)34Dw}Cgh>D`4nCOsjSU4ga72=~~LMDw6^bOpSxAen2!hz`Bw7m12RC8AOh0}?_^s7zEYa;QF-Dnx3iQlx~c zMAaf4TLLce1A_heP)rsmwB8Uyy#0{cGQIm+RpP`ju@gi`UKP7xoHKvKwn*Fr{lmxyApK@R9Yg&*n`A$$nx5%r3=Y%A0! z`iUh|eUKjN7YQH}6qPvH1EN9EkZ4#$myU==MPni+Zd~+MKOveFfzXs_T4aP~M0C-t z$PUek=0yvlMbVOoXU6c!6s`CZ-wj!yN5}vzi&jK1v?}_*GDB-3C$uiw5P2Xkv?=-y zZHcx;F6b?cKs%yc(Vl2ubRaqu9f^)bC!$l)BSSzu6P=6R@e%w_=t2~RE=6CVE75Q0 z8G6wL@c-VfBp%5x=tdNTZbfn8c=0zVL7XU#K}q6d@jF%&N)f~ORB@U(U7R7#6i1*} zMgS7fv&0cjwm3(eE6x+=iw%r>=m9DahoD#J2Sg+limeia{ulZKebK*x-@zZ?knTPF zAN)V~ldecyEG`k3ip#|1;tH{p_6e>OSBc3m4kp6Y;u>+SxK3OzZV)$$v9L)8KhA9sVDGLA)r|!3=mw zyewW3YvENfle#8e7aLg{;-9Qd@s?Od+ZOMLcg1^R8N4qR!UtkDd?-E=AB*L9K71mU z!|(A%_*8r*J{Pm#3-P7+N~{rS;A`=X_*NVziI*5)H&;YSkR(cyB*~H#i3(Q3sgg8F zx@xz^xE=jkf zN75_llZfGd$$(@~;)K1tA<3|0L^3KFlZ;CyB$E;sJSCZy%t&S>bCP+atF%q36}3yFaEG*0+9iz|Bk&8{E$xv$!M)P2aGx{)_e%$) z&zeE$kaSo&BDF}K;Zf<>zv$GsbVB+7hvk#fAUq|VmMU>G(pl-8bY8k3U6hhJOHw)` z1TRZhq~G9G=_~vQuSwUX8`4ebmh@S;E!~msN`Jw7(tYWH^iX;vJ(iwGPo-zlbLoZj zz5P;pC4FbVmflEjrE#)&S%NH4mLyA-rN~lcX|nHdx-3JMDa(?5;5WlgeXS&OVy z)+TG0b;wxapYU(^FZ|a28LPr|%DQCTvL0El?9SdN>z57424(-*$;_{kA=$8OL^diL zla0$JWRtQf*|cm%_QpOdo0EO8&&w8Mi?SuzC;PH&MYbwilda1>+BamIvMt&F?Ax*( z*{*C)wl6!79m7;K=p_ zInJIaPm(9gQ{<`gG-$@@1D~eUc znqpnCp+JY<((yd3P|Vv@Y$-6|ZN-jaSFxwqSKMn36o-l<1*|_-oG4Be%*Qjux#B`` zskl;HD{d6G3O@lGj#J{o@yY}xN|vZhQYI@?l&Q)zWx5if5yGS}G3=Go)c7z_rq(_2 zGL)IhEM>MbN13b4Q}R_n_!UbD=PL`8g~}pjv62-oQL6E!$}(lSvO-y@tWt8dv~abu zMp>(@Q`RdP;d?`avQbG7lf&#VGu))4hMScwN^w{a7KK}tZAw{~7v_Z9l^x1Xr7+y3 z>{j+DdzF34U#5QLfO1gD4G$@Qh#k^lr6eq(Vo4*)Q6)bt4Qs-t@R)L3X{JvoCzVr5 zV;E9S|6A~9l(R}**btsm&MOy`i^?#tq+C|6C|8y8@S1X6xuH~rfABVyuu&0KhSgzx zcuTph+)-M?4E?ThPr0u=P(F|kl_A-Y(n~RikCi9NQ>7&ghT*U+e5O2CLg5SLrSeL7 zt<-9@;Txq?d8<^bKAGZFo^ZU%#!pZ=!-=XS6^8Q^wuh5du5gMfRh6a+gws_Ss!Uau z${o&D<*1Nwt}0LE59g~2RQKURRgtP#$$QL%2*;uBuQ~s;X4gsv6au-WQJH zYgKisaJXLeMbn^aR5huZRk3i3s#VpdlF-{#Kf)cVPF0txTh*iLRlS7!RQ;;g@b~b~ z@PKMiHKZC=ji^RdW2$jgBs`%Cg(p>0s%h0P+KlQKX;w9-npZ8TzJ|YrgW>1!qH0OC zta=Rp7g#{FRBt2estr{%yr}{uTdHlQr^6 zI#*q&zVk0tSE_5(jp|kvr;b-AsQ-i$)k*6AMLtE|N0QaQ!zt=ib(;E1BwhVElA+F2 zXQ{K*FfT`)t42ri)cI;`q(EJ$E>ah(OVn>7rRp+uxf&O_i&Us9)m7?hb&VPm`5Q(> zYSne>dUb=kQQf3&R^uZr>Q;4|x?N3-bf`PkUFvT2$4HO5SKX)XR}&%w>Ou98niLsU zkElo0W9o7BgnCjvrJh#Ls41FR^_+TMy`Tmni|QryvU)}R!@8NrijCP9;^ zNzx>1QZ%WWG)=lDLzAh=(qwD+&pDc0O`axSQ=lo-Fd{{oVhuA=qAAssX+CSqH5Hml z&0SQasnS$yYBaT)I!(Psqk*&ynnq2NrdiXXY1OFIZJKtCiP@pyYdbYvnr=;xrdQLa z>DRbv_b#4}7oy?^G=rKTjvpG*aHImluqJFB(R`4PY6PJ%&A4VlGpR9{rZm%<8O^L_ zP9qF)qN32e=FT7vEoeAcZgf$zq~S%EH7lCm#D4`8!ZpphW<#^7p)0mD+nODXSF@|x z)9h;wG>00e@!xi_@aj@!AA!qV_$Iq)pbQ zXj8RmT3IMvo1x9rW@+W2Y;BGl17 zwo?0Qt3h?a+2= zyR_Zf9<3>)4fSfZQkSq#+pitadU(I7gW4gjJ~XT~hDNlb+A*!3ILtxO4rPPJ#+bM1we>ATckX|J_V=tgS~-D=}>@wxe6(M zP`WNd=Tm3uvUJ(H99^z1PnWMN&=u;6bj7+7U8$~2SFWqjRqCpA)w&v8t*%a2uWQgX z>V(kw0v(x;|aMZa_Dv8`2HyMs%aPG2OUsLN}?K z(oO4Jp&8w*Zcg`2HLv@uThRRqE$WtZcwkw#qFdFi>DF}{x=r1dZdC^QY`b>S6K3kuo z&(-JY^YsP#LVc0GSYM(q)tBkZ^%eR`eU-jiU!(uUuu*IEeyWwPmjxa;oEYo=;o;%& zp-%tw5PW!k`1&Ab*6SPejrw1)CVjKMMgJ$(s{b2n)BldO>pS$F`Yyej*{y%``hnP^ z@74F|`}J>M2lRvbA^p48Vf~1HRF8ie(~s*X^ppB2{j`2YKdYb9&+8ZTi+Y20Nx!UL z(XZ;)^y~Tu>xO<)zop;S@91~+d-{F-f&Nf`q(9c5=uh=$`g8q-{!)LXzt-RAZ}oA8 zcte6A(U4?FHl!F*4QYmSLxv&KkY&g=kRdV21BEv$#eTII+fML)uWEeJ# z7)A|ahH=A$VbU;Vm^RE9W({+OdBcKX(XeD#Hmn#{4QqyV!-iqguw~db>=gQ7)}jm2E6gyaACMKTp6wnH-=k7oH5>*U`#Y78Iz4E##G~9J)}r8rW-Si znZ_(*wlT+;YZS=xjQPd_W1+FgSZpjYmKw{9<;DtQrLoFbZLBfY8taVp#s*`fvB}tM zY%#VP+l=kT4r8aW%h+w~G4>k!jQz#|r>V=-ZR#=gn)*!rrUBES zX~;Be8ZnKU#!Ta;3Dcx$$~0}7G0mFhOdnq7O$(+)(~@b~v|?H{t(n$M8>UUumTB9x zW7;+Cnf6TwrbE+_>DY8)IyIe{&P^AlOVgF<+H_;OHN~0Z%?aj2bCNmPoMKKjrKPx0qYaZRU1!hq=?-W$rfjn0w8A=6>^ldC)v$9yX7dN6lmAar1=L?{#FYm~n2#Grjar;Ac>x{Q?FxU&%J!g<1XYJuM*R zQ@*j@o9;jq$PpoCvh33Q$>@-OHKIX>Nk+ti81TycsKbGHkN_HFMDUA@1d>5D;j4)P zV(DlS08+tcDn=X7(Lg@%p#F-dgADN6{K$k>)83&C$B5y<1x&0-Kx+?XG9IDrKGL(9BNK zx-8w69!syq>gu!fTLvtHmT2rVE{q?t3|mGlqn0ttxMji;i%nXlEZ<_&mKn>eMN4~) z%~|mLdCP)j(XwP&wyaoIEk9ywmUYX9<$G+?vSrz}>{xa!dzO96f#uM0WI48+SWYcx zmUGL6<tJYlpSd+GXvw_E>wZ zeb#>KfOXJ1WF5ASSVyg6)^Y2Eb<#Rzowm+cXRUMAdFz68(Yj<^wys!Lt!vhG>xOmH zx@FzA?pSxNd)9sHf%VXOWIeW?SWm5I)^qEH_0oD}y|&(1Z>@1)JeU9`f=OU9m;$DP zX<#~-0cL_(U^bWo5^)bk8juU(s3QD}L8*qYa$}4xGf^m51zF_6(Wt*oF6tY~PX_p4 zd-$P1(tYECEYFBdrYl z7A*%WK!>>!tO7$(EMPFIffrFVSOeCAbznW%05*b6U^B=kw1BN(IC@8D1KYt4uoGk& zzKOfQZmzM*Bhf){2pk4Sz)^4v90w=BNpK33E2hC2a29+onFHs+1#l5u z0++!Ra1~qw*TD^N6Wju0(QVLUW(zs79q=DUI<^P$WBVX4b^y{$+}I&_1RjGdgCKSS zDq^SL8F&s}fNJb_(j_R3$zoR^B)kT1z*{iRCX9(<@wNn;I3|xJ+MFy&>?e?9OSYxh zG%piO8C+J<(ZU1$&5hYp}a=m4Q_`!;7+&;?uL8dUbqkLhX>$6cnBVbN8nL-3?7Fk;7NE2 zo`z@OS$GbfhZo>QcnMyHSKw864PJ*g;7xc7-iCMJU3d@PhY#RG_y|6RPvBGd3_gc1 z;7j-lzJ_n$TR6@hZ%?o%+LP?b_7r=nJV3*?Gtt>_bYMIK4t$Xw&Sl%zGs*E_U#AuL%V@5#Jyu2*^lifc8dAberA^|m2#O( zuTc2pKEL4Heqn#3rTnvOFYOxNl^syNnAAR)bZuuTZ|qthjeKj5b9_{Ksqqe>OiQrJ zpA0(R10}(c=ty#?e94X!N2(*uk?zQF7=3?~9Mz6{T#X}227MNv)yE;#I_ezt4xtY6 zH8>g_c3+dD+0o)?b+kF!9k35C?r^-*bvn8nHea`+$Iq zLgo?2sAJ4A?wD{)I;I>h-?Rh5{nE}j+&-^w)-mUpcPuzOzD389!{=LetT-YxlIrbd~j-Q}fBNiMwjvUX}W5sDndwB?vYgq@94Fd#XXDXwoq5iD=X>@STY*g|6C2q0VrPjHV=Hz3pq4qYwsL2Mv(j1Rq!X&0HO^Y+f22BRy|cmD=wy&_wkBt@ zv&9)Bw>t5*HfOuD!`bQVa&|j=oW0IIXTNj6Ip`d64m(Gjqs}qsxO2ie>6GH8oYT%3 z=d6=xn{&=P7n}qe$+qZRaxObpoU6_?=el#lx#`?;ZaXQq9Vgkg>)dnhI}e=CAif3pV63@Z}tj*NB=~BMH5{jR+1~( zmEuZuebuD7(p`E=hAY#hG<;TMxw2hvV{c*~X@8?8d5$aBmFIdN({b`$4}=2OXXS_3 zyBLxAF;?jM6jL$*zKiXWe~uNoid`kH|6>1(y$DKOWv+5pg{#ta7prnHh}Ev3xyEHC zeu<%DwXQlBDu#(^HTA9rSEH-R)$D3FRQIyRb1_tjE>s>T~tG z23&(Kd~C=y>>|X7F;Z;AHR>93jk_o@a%{pi>6&s)yMWk?Yt}XAns+U@7F|oOW!H*p z)wSkYcS-RZE`wev+jM>9SWH+Qo4e(DVQ&8`1=)4&x%OQLu0z+6>)3VT`V5@9&RplN zi+>=QE7!H_#&zq8bH}?A+==cacd|Rho$5|=r@J%UneHriwmZk2>&|oMy9?Zf?jm=w zyTo1UE_0W=E8LatDtEQJ#$D^KbJx2Y+>P!gceA_2-Rf?0x4S#so$fAox4XyP>+W;+ zy9eBZ?jiTEd&E8J9&?YoC)|_nDfhH{#y#tvbI-dM+>7od_p*D%z3N_bue&$go9-?5 zwtL6D>)vzkyARxl?j!fH`^0_fK69VDFWi^zEBCeg#(nFK^Tc}+Jc*tpPqHV)lj=$H zq&f%vdkQ>-o+3}Nr^Hk0Df5(jDm;~*Do?ei##8I5^VEA9JdK_v zPqU}R)9PvSw0k-{ot`dFx92;f$J6WS^YnWLJcFJg&#-62GwK=hjC&?Llb$Khv}eXM z>zVV+dlo#4o+Zz+XT>9WUG=Pa);$}ZP0yBR+q2`@_3U}}JqMmc&ynZYbK*JmoO#YY z7oJPcmFL=Xna-b8PbH`yzGP4T9B)4b{43~#14%bV@Z@#cE-y!qY&Z=tuy zTkI|ImU_#)<=zT!rMJpk?XB@jUTeK|-g<9?x6#|=ZT7Z!TfJ@Gc5jEb)7$0k_V##t zy?x$(?|^sEJLDbqj(A7CW8QJ^gm=Ag|E_A<*WA9_-cK1zItDS zuhG}!YxcGHT77N4c3+3D)7Rze_VxIBeSN-u-+*t>Cw(3A4f{rXqrNfUxNpKY>6`LR z`(}KzzB%8#Z^5_dTkAUh>`)+))*IQqlKi;3|FRDYU3-Jjvl^k@0A{W<nZMj$;ji>p`K$dk{#t*Xzuw>ASG+d*oBYlG7JsY1&EM|t@OS#V{N4T@ zf3LsK-|rvr5Bi7v!~PNfsDI2q?w{~a`ltNU{u%$Qf6hPeU+^#bm;B5A75}P#&A;y7 z@NfFJ{M-H=|E_<}zwbZrANr5{$Nm%lssGG>?!WL~`mg-**K7Zc|JEOe#3KnvB9eq8 zBPmEKa{nz2Nk=k}Oe71*Msko`BoE0)3Xnpi2q{KNkW!=!DMu=hN~8*@Mrx2+qz0WDnU#4v<6S2suVhkW=IgIY%y#OXLc< zMsAQ>BrXsiNC+ebk^;$rlt5}AEs!3_2xJDb0@;C_fbumrkQc}g6a)$bMS>=lzbIv(uD00p@gFA}*({)#5MNBA&pdunD23&VtP-If~#O{gK;oNiI z+^SP`PCYMf-FvF5Yi4?SdTP2qFMI0y?eqTgf%C!hq4VMMk@L~>E$|d<1NP|h>NBtd zo`VF3`2$?N^%?vL{sLdX-++040#3n)2VcSN8{_3K zx4vzB14}zMo=l#ff$!iP(0~Cf;K0;54*-B*`h4bG03wip0%S0Iu7VqT8=DAVpn*$A zI#}5^fC=W#EntI7@CWz_s%yp*3SNer4<8-sx30h?cok}gKSTSS1HRmzKfeaA!{0Z4 zfyTbJ`zyQwjTPA#p-dPP&O|VgOcWE%#4xeUMUsuv zjpy5^am>;3i&rbZOV4&rU+-Teo_p~8^u_7+lb?>>ZLt^0NOw=slb5IQ%+)*c+Tp#u z(^sckZ}(3VnAfMf2M4Ezr*BT*p1wOcIyGNtD$K*5MSpieXd^>)8M>$Xr<)ilxizM|ok!fO@na|5DOe@pIaL4V;+UmWx9gMxw$#gON@$-vip3|q@3^?v#dYL|^ zpBZ4_@gO4{GaE-QKkpAQ!^{XX%8W7N%mg#ZOfl2U3^U8jG2h=@+MH*^;{|4s`L^rC zO2^LZ+3t@+7uJ<^W0f^`)`OLgf4jN5@5y?x`$yia59`bNvHolT8^{K+!E6Z2?}oBr zY&aXiMzT?CG#kSz$FXc2yLB4RCa_mF64@m75lUuL*vDuC9c-ntYtK#((%5wN)9a@P zzdhKyo53nDlg(ncFSftgMCM91o5MaqxojRQ-p*$W*h035EoMvDQnrjOXDisJsFJN> ztJxa1maSv!S?0}E2^|J#k+8<=EA>rs3boa>+JIs!-%Kcx_4K&J*vE%HYTNCUg`(a~>on~j)S$2-S zwmZ*0*k525Strh!bKzV$H_n~&;5<1m?lvWoHTHaJk&t zdLEb0-C8f;zTGb5inyIS#oVJuhfmI)lyIfo%MWE-Iak5KwMwpvtLAFBTCR?(=Nh<1 zPJejipox2Zvzcq*TDdl^ox6!UxK6H%>*jj6UapVp=a%sRH^>cf!`uk>%j;3@=FKr~ zoSWco;T1f|{f?)&X>Nvlu`|ofar4{)x5zp1&iwwm3-8L`!EU@e@4?jr z{?BDU{x3I3K}B@=<&=AH&D;aeO?Vz$fxad@`THr}Alh zI-kL3@>zT~pTpP5_U&Gh(b$mVFz&G+u{N-1B z&zkw`_twtup5Hs)TyNo9`8K|t@8FfgPJaLGhv!{|nwNgx@dfK-qM(m@8u1X&;(SGT2Ke-K?7(6O`sXHfL723+Cc~C1YMvT^nhN_2l~MP7z9IL7>s~X zFb2lK1egReMTSuh9Y!2(zWPS6>;Kv(Dn-QmjNl~rcP62bn;F8dmO|Gu|-_v5N9 ze!cl}_lJ1-?Tt-tV{3bP{gQO_zytmyQIaRTEIm2Az3l~e_O3|YaQV&CM<*|R;F5Gz zIywNWKT8hjuiMw8>yj_DZv7(Nkgh)SgZ?l82Erg13`1Zj41?h?0!G3p7!6}!ER2Kk zFaajQB$y0SU@A<5=`aIk!Yr5#b6_sagZZ!k7Q!M}48Pwgfu+#FUE{8EW$+iS99FS9aR$kP=T383`VFPT0O>pgGA2-7m*b3WVJM4g+unTs>9@q=}U_Tsy zgK!8A!x1H-pQ+z_b=8i7Nbu0T|`&WO>`GML{HI6^cH|w-#UL?Q3=u=cFfm+=5F^DXF#U`;?Y!O?< zHnCmo5Ie;#v0LmBd&NGnUmOqz#UXK691%ywF>zd+5GTbcaax=aXT>>jUR)3tMJLHw za*4KUP_P> zr6eg?N|92fG$~!mkTRt#DO<{sa-}>eUn-Car6Q?VDv?U1GO1jukSe7rsamR$YNa}< zUTTmUr6#FaYLQx{HmP0ekUFI!(!C7%5zdq!<19H_&XG6q2HwKCa-RGI z=gS3hplPZlzo$SIaf>Uu(5;om?+B$c=K7{1!LMN4Q09 zmD}WY`5o?%JLN99TmFE1be?KoT$cwU*@&|TSTohNuO>tK|l+V~x@lw2%Ke3PEtN1DYN`Mlm1S!Evh!U!V zDSzQ`B|?c*zThY&T8U9&l{h6{Nl+4%Bqdo%QFcG2Drw5K59vyVlBr}V*-DO*tK=#8 z8-F)nDNqWPBE^2h+<%UDwx8i*Q=Qv(lopDs4);(xG%JT}rpoqx33$O20Co3@Ss)uri{IDr3sHGNDW=Q_8e5 zqs%IE%Dl3mEGkZ_v+AO{s&1;g>Y;k7UaGh1qx!0Ts=peb2C6}7uo|La7OF*Rv09>*s%2`q zTA@~|Rcf_bqt>c*YQ5T^HmXf(v)ZDzs%>h!+M#x;U23=5qxPzOYQH+54yr@yusWiS zs$=T7I-yRgQ|h!jqt2>x>b$z3E~-w*8Mz==L08Kt09l!nq#2FgTPC>!OVT$G3MQ2{DMMW`5+ zpi)$Z%25TXL{+F7)u38bhw4!SYD7(_8MUBR)P~wo2kJy!s2la5Uet&B(Eu7mLueR{ zpiwl2#?b_tL{n%Q&7fH{hvv}&T0~CR8M|Ot?1tU32lm8X*cY>oQBhJ2F}D;I2-5ST%3pVaRDyGMYtH3 z;8I+M%W(y+#8tQ&*Wg-QhwE_zZp5c=ns77TM=f||^EGP4ZTJ8kqBrO*YR4V;9qPo_ zm*1l<`~iJL$EX{BLVuth+>85gKmLp^eyi*c;J?rp^fx*|r|2sZ9)Ck;7wHnu5sd~h zgN87RxQneHc?1wd0uqsgWTc><*GI655W+}9qj(ID;|V;8jb}PCkcq5|O*E#ljeej@ z_$N%^%lHbO!LxV?U&TLTuBA0saB?yYZY3hR;5*IHCnA!r`2l>TBFvaHES(e ztJbEqYaLpr)}?i8JzB5Ur}b+C+MqV14QnIXs5YjJYZKa}HlmItN?xlO{KDw{&r~B&xdY~Sp2kRkvs2-+=>k)dS9;HX?F?y^Xr^o9F zdZM1BC+jJCs-C8&>lu2co~38&IeM<1r|0VhdZAvV7waW@sa~d+>lJ#XUZq#-HF~XH zr`PKZdZXT?H|s5WtKO!!>m7Qh-lcczJ$kR+r}ygv`k+3f59=fPs6M8T>l6B z8x=;SQDsycHAbybXVe=FMx)VWG#f2OtI=k(8y!Zc(PeZSJw~t5XY?Bb#-K4|3>zcH zs4-@Y8xzK)F=b2}GsdhjXUrQ5#-ib5I-4%0tLbLCn;xd8>1BGGKBlkfXZo7~W}q2l z2Ad&fs2OI4n-OND8D&PBF=nhOZv7@KJ-8|8PvXqAr}q!y&1K=1up;~}+!h`jB$(Vm zqIpMH6|TNbG7tCGgnPnW;lA)dNH$YUcI}~XelOKr7aj@p`eWfDCAP3BJQ22p+s~c~ z+d`VTBPdVP&1XV}nQ3O3&xLIBh42vPn7hJDVNb|4UkQ0;zFA-vn)|~0dqw7J;XpVP z-Ux4nBjKI!K`1s$%qwr+3#H~qq0B5dE6hr>%B(hP%v!U~tT*qecQ+f%M)NCfGMmj7 zv(@~D&v2XBZhprdW~bR@cAGtBuX&Dt-|RE{%>i@J95RQ^5p&cWGZ{Q?vUtLrG^fmI zbH2+xNq)a4W)!w7!0fvZAdROL}qs__7dd9p8(y;;kDy309(&Wc{+0Y^7Kn<}tvj zmVhBnvqYS3WmpQ%v}BxRNm#|%R*scxlTLo63Rb&-gC040bW|dnsUtuvk%U4`50Ivb*gbyVvfs z`|SaH&>pgf?GfA9`1$TRKWdNJ<2G~mua6V>Y z5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y z5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y z5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y z5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y z5g-CYfCvx)B0vO)01+SpM1Tko0U|&IhyW2F0z`la5CI}U1c(3;AOb{y2oM1xKm>>Y z5g-CYfCvx)B0vO)!2d4-v-bb1Bc1yfM>hX2zW0CAVc|a+4)Ii|7Bo{>Poy5APp77cIU&{Qg(F|Brwlf&WL3|N2X$2N56wM1Tko z0V41}O(5JME&cN!%96VDW$EuFVM$y%Svp+;OK|CI>HE^xrEg2;OY{=6#9s9JkCNrc zcH}s69eIv?M}eczQRFCg{PQ0rj#5XNqx_;);iz;}IjS8sj#@{Zqu$ZrXmm6=njI~U z){CcYj&?_fqw}Ih%70Jb67>^BQQt3Jp_Ztt)X$WIx<*~6exYtqzf!+ZH>qXn7PUhC zPTi(fsXNpfb(gwF-KQQ<52XVi1*1+`1Pr1q#+)IRl^ zI-m}zH`H6|hzDp}GyI?2i@wBMig5g(A|02he`TKk2HrOY AE&u=k literal 0 HcmV?d00001 diff --git a/media/nls/c_949.nls b/media/nls/c_949.nls new file mode 100644 index 0000000000000000000000000000000000000000..387311f95842b921e300221b1f11cb66c9324ef3 GIT binary patch literal 196642 zcmeFZd9+ODyYE}9g&+umAeyyQEnP5cmA>x2bdt}`6$36DGcb}?Jqn>)IKJW8=zu&iJ{a3{zWJdl-tN-i1 ztkj9H|ni8p(=eN2*1lkys=rQaw^5QZrI3Qakcqq)w!6q+SGw z#3Q+pM5KPCL8M`%QKWICNu+6{S)_TSMWp4w6t#}DiL{Nhi?ok)h;)o}io74`9O)A2 z8u=j7Ez&*GBl2OSXQWr8cjTi;pGehDL@(hDSz3 zMn*n3xPiDdoct125L8zvhinw?CSaNuBL~>+uRC083Omb{;TylJJLULkqQgU)~T5@`FW^z_?ZgPI|v*d#0!sMdl z(&WnI7s<8Bb;RUGik|RPuE4`{dc=56Sb% z3(1SgACs4omy=hL*OJ$hHf9;^UX1S^4+!75-Dmg6+VL;QL?~uq*fh z*bVFs_5gc=y};gJAFwajFAv`z8~_dkKLH1UgTW!-r{FMf1UM2L1&#*CfMdaN;COHn zI2oJ@P6KCybHKUaJa8en7+eN^4lV~*fGfe(;2Ll(xDH$oZU8reo4~KZ&EOVrEBFn# z4crdy0C$1A!9Cz!a38oIJO~~F4}(X*qu?>{IG6-M5CUNk0Z|YGagYE>kOCQy1v!uh z1yBSfPzE(n2UDO4TA%~Epa=S30EXZR@D%txcm_NRo&$dX&x04hi{K^jGI#~N3SI-R zgEzpN;4SbM@HTh{ybJyc-UIK055V8Rhu|adG59<91bhlU%j3g;RQ}Jw7vSIEOE5o_ z0cAo3pn^~#s0j2XR2(V+y#=5wsXu0xgA>K`Wq@&==4uXf?D3S_`d%)GgN{Q<2!tRAh7bsaFbIbTh=eGJ zh8T#2IEaU2NQE>=hf z2j_<~;7qsx{Hnf!aACLzTois2E)JJ~OTwk#((v1G8MrK54t@tN4_AOI!tcVB;L30n zxGJ0lXT#O<@KHDh=fKtB8gNax7F-*y3)h3=Z~|@sH-sC(jo~J6Q@9!25^fE*hdaO> z;ZATDxGVet+zsvy_kerCz2M&PM{pmwFWe9Q814@bfCs{Z;UVy+@KAUdJRBYckA}y< zW8rb|cz6Ol5uOB3hNr+&;c4)6cm_NZo(0c_=fLye`S54(0(c?32wnm&g_pt0;T7;o zcon=FUITv#uZ7pa>*0;?CirW33%nKn2Hpm5hj+j`;a%`+04UxY8gm*Fe$Pw>?|y05|4;h*6f@J;v@dLU%1hDal%G13HSiZnx-BQ21YNGqf@(gtaZv_m=~osiB*SEL)#1Nji?iS$DH zA|E3Ikb%f2$Y5j$@+mSD8HNl;Mj#`RQOIay3^EoOhm1!iAQO>E$Yf*+G8LJIOh;xQ zGm%-yY-A2H7nz65M;0QBkR`}cWErv?S%IuXzCczXtC2OxI^-*4BeDtk8rh6&LAD}0 zke$dbWIu8sj}NbU@;d8-$RXq~atuKb451JjVG$1D5fPCP8Bq`w(GVRm5f||g9|@2U zIf0zYqx&>+204qIL(U@?kc-HV$R*@5as|1HTtluSKO;AhTgWfSZR8Ge7x@*rhulXV zAiw3|A0m&C$H?!<6XYrK4EY236M2rjK>kAhMqVOmB!cEc^P?GPCRzY3h!#SNpvBPQ zXbH3=`ZihyEsK^zE1;FpDri+S3(ZDz(CTPSv=&+$t%KG@>!AP|M|05x+7NAuHba}E zEzp)|E3_@z4()(;L_49K(Jp9L^aHdT+8ynI_CkB3ebIhse{=vk5FLaLMu(t7(P8Lt zbObsQ9fgiY$Dm`;ap-t-0y+_$gic1Mpi|Ll=yY@jIuo6R&PL~<^U($9LUa+j1YL%H zjxI-6pexbU=$Gg^bUpeNx&hscZb7%A+tBUk4s<8_I&=P~S-a5P=pJ-0x)0rt9zYMG zhtR|5QS=yk98IDi3ZXEHpeTx=I7*--N})8$rY4l7U{w#V9{Q*6XUO+FRm(icltLQcKI{Gtu1HFmfLhqn= z(R=89^a1)1eS|(ne@CC7Ptj-SALw)RFZ3mvMk820EI*ck6~qc*g|Q-7F|0UN0(%Q9 ziIu`iV`Z^-unJg3>|Lx9RvD{;WntM^H7tt7upF#9Rs*Yv)xv6H?_qVYx>!97z~Wdg zmcSZd4Y5X8W2_0*6l;dHz*=Ihu+~@`tS#0KYmarnI%1u$_p#1c7pyDx0oD!cj`hGk z#Cl@Au-@25SRbq})(`8C4ZsFsgRsHa5Ns$m3>%J(z(!)Du+i8!Y&!dU@NgNu+`Wa>`QDdwl0tE z_1H#i6Sf)Kf^EfiVBcapv0d11Y#(+2JB%H{j$+3#5Q8unLop1)F%qLNIuFlaEXH9x zCSW2aVKSy*DyCsNW?(7I#4OCkJS@OM>;!faJB@vhox#px=dcUdkJx4G3icCr6}yhz z!fs=Cu-~wU*dy#I_80ay_7cmFXW#|!f_NdkFkS>Niob~$!;9l3@KShLyd3@xULLQ2 zSHvsfmGLTgRXhvN#;f5`Jcj4s)$tm5O}rLf8-EY4gV)9D;Q$`TbMXXTA8&v+#2ev_ z@g{gvycymcZ-KYOTj8zoHh5dS9o`=AfOo_@;qT*}@h*5*`~$oj-W~6Oe~9Vm@cH;>_yT+( zz6f86ufSL0U*N0o)%Y5GZ64k0@b&lxd?UUI-;8g;x8mR6+wkr94*XkuC%y~cjqk(v z;|K7A_#yl-eiT23AIHHwJcPqIf}=Qw<2ZqnIEB+VgR?k?^SFSExP;5Nf~&ZO>$r(q zxP!ZRfS6^TkjWugj^MPw7zh$s;wa)|0gE#f_*4pEn=M*u{e z$R!d)1EL|(h-geSA(|4+h~`8Kq9xIaXic;s+7j)E_QXGB@;dt+h>k=j;(eks(S_(r zd_Z&~x)VK!UPN!A57C$CNAxEK5Ce%%h(W|)VhAye7(tB6qkA+lh8RnXBgPXGiAls{ zVhS;pm_|$|W)L%pS;TB&4l$RQN6aTaBNh+~iABT`Vrd?J8Sy!>oLE7uBvuiti8aKR z#9CqB6bsdh`q!HJH%b$KJgpzhV~iRZ)% z;xFQF;w6zLB4j=?Kbb*hk_E_uWFhhmvM^bMEK0sf79)$3CCInPl4L2eG+CA`N0uim zkd?^Sne#u*s!UcPtCCq{Hd&3#A#0QGk#)$rWIZyMOpp!8hGZkM3E7lvMm8r~kS)np zWLvUh9^IYD_sPy=7qUCqgX~H6B72j4$i8Gh@?)|;Ie;8U4km|@!^sikNOBZ8njAxp zCCBCA$CDGtiR2`5GC75uN=_rElQYPf5wkzks*1CJWYO2 zo*~bY=g9Nq1@a>KBYBCuOkN>>BCnFy$m`_KJusIJrpR5z+S)r0zw>PhvYdQ%@!eW<=vKk8$uKQ(|FNPR*Lq6Sk#s86Y()G%r| zHIf=dji$y@!|hASJVb-BejY8n%Yclp|(=rP}`{O)DCJF zwVT>Y?W6Wn2dP8UVd@BVlsZO%6hy%kLSYn65fn*L6iqP{OK}uW36w}lluRjKye0b)LFFU8H`bF6GgE znYu##L|vt>QP-)TsTK642b(^|F-KBn|?os!t2h>CA5%rjQLOrFPQGZg;^YAaI zzo@^dmsFa{PiN4XbV0fh{RUl_EKP8Xcu$bPipeu0_|T>(F)SIGsx;==yX6x*^?&Zb~<&ThJ}( zR&;B+4c(S*M|Yq*(w*qebQiiS-Hq-}_n<$dd(yq=-gIBOAN?`ipB_LDq(7kt(SzwB z^iX;jJ)9m%kD^D@W9f19czOaok)A|Prl-*}=vnk^dJa98o=4B87t)L9CG=8y8NHld zL9e90pjXkW={58^dK3LMy_w!l@1S?myXe=M^FPhnP4A`m(fjEG^g;R%eV9H*Lo`ey zG)iMMPE#~ZvouHZv_OlrM9Z{7t9f*5v`!mziZ*GRc4?3H>3|OD6ZCiVN%|Chn*N?X zL!YJ3(Ld1V=?nBl`bYXw9{w_Yh5m`YN?)U|(?8QU=$rH{`WN~(eTTkF-=`nY59vqr zWBLjGlzvA4LH|iVr(e)7>HJIvlgSid3Nl5QqD(QSI8%Zt$&_MBGjB6xn6gYcrULUW zQ<ywoE&w z1JjY|#JtaRX1Xw4nGcw5On0US^C8oV`H1Pm^kw=nA2a=#0n9*VFf)W1$_!(MGb5Q% z%xGo|GnN_0jAte>QUnEA{CW+AhPS60U3ya8I-{ooFN&Cp&6Fp7@iRrF%K^>GNUmDV=@+F zGY;c29uqJjbAma^oMKKhXPC3hIpzoEJad7$$o$A$W`1I>G1r-&nH$Va<`#2@xy#&R z?lTXVhs-19G4ng~gn7z5W1cgAF)x`k6JhhQ`PmG%09%kP#J<56W{a>z**Do@Y;m>( z`xaZ0Eyb2*-)76OW!Z9UdA0&uk$sn~#8zgjuvu(2TaAsfF*b*-&emXSvbEUS?0ak- zwk}(b1=u*7%O=?RYy-9-+lXzd$S+0eb~NiKlXLz{7|k~XJCq&94rfQOBiT{xXm%Vsft|!oW~Z=I z*=g)_b{0FEoy*Q+=d%m)=w8S!Vi&VZ*rn_;b_M$dyN3OeUC(~SZeTaEo7k_}&FmI- zEBg(*jor@fV83N|vb*x|yV*VLUUnb5pFO}HWDl{2*(2;x_85Ddg;{<34dx8Cty~6&)USn^vx7ge49riAJ zkG;=6V1HvDvX9uu>{Ipy`xpB+`;tww`MC@(lPka#gS%H(zSJ8@mO54axOhg?st z7uT2T$Mxq1a09tP++c19_bE4&8^#UiMsee~@!SM%A~%VfoJaRGZaO!Uo5juM=5q76 z`P^sR0&XF+-hzOx0YMSt>?btHgFsB@SC`=xy{@bZY%c{Npe{g?t&$$=e-`q#b@;k`Js#lWd@i5h8}Uu}rhF^DHQ$DB%eUh@^6&Fq_^$j1 ze0RPl-z$&q-h3avFW-;v&kx`S@}Ka7_`&=T{!@M!KY}00kK#x3WB9TBIDR}ok)Om* z=BMye^YGL7>HG|SCO?ax&ClWI^7Hul{Ac_Eej&ezU(7Gzm-5T_&-vy23VtQOieJsI z;n(u(`1Sk-ej~q$|C-;-Z{fG{-|*Y`?fee@TYe|Mi{H)f;rH_U`2GAr{t$ndKgu8D zkMkf8@i33@D39?tPx2Jc@GQ^qJTLGfFYz+3@*1!6Dc-^9B4gMy7i~ohc&EMhg^1t%;`1||= z{x|+1|A>Fg|IR<*pYqT6=ll!)Z~i5pPxz-yUS~f;$P@|)1%*OF5uv#7mQYG4EtD53 z2vvnFAzP>>Q1`9)kPlchvFk!ebLKrEG5=IMS zgt5XnVZ1Owm?%sVCJR%9slqg2x-dhSDa;aP3v-0I!aQNV@R_hcSSTzK77I&+rNS~{ zg|JdsC9D?K3hRZhgbl(*VUw^$_(s?vd@Jk}b_u(MeZqd>pm0byDjXAz3rPVKAORLI zff8te5ma98+MxF_5f9tgh)4~0jL zVso*D*ivjIwh`Nk?ZozC2eG5rN$eta6}ySu#U5f$v6t9e{7CF0_7(ey1H^&iC*mM+ zusB5gR2(V}6Nif<#ZlsDajZB_94}4~CyJBA$>J1osyI!YF3u2VinGMo;v8|VI8U4} zekLvu7mAC-rQ$Mixwt}HBYr8a71xRD#f{?E;udkM_>H(j+$ru7cZ++(z2ZJ`zj#nQ zBpw!zh)2a^;&Cx4f+8fsA}V4cE)pUsQX(y~A}8{qAc~?S%Az8wq9*F1A*MuAv_xBU zL|61gUkt=hJRyE3p3LLJtDe5j`jmKDJS(0P&x;qti{d5mvUo-ONxUjv6R(Rui#NoZ z;w|wP@s4;`{8hXs-WMN;5A*1LBt90Oh)>05;-BJk@rC%8__z2{OpE!X{8FY=P%0$7 zAr+R2NJXXMQVFS~R7xr>y}G|LQdy~-^o~?ssvuRADoa(REGb*6CPk%~lp|G_YDhJu zT2gK4J*kdVSE?rgQe4WF5>kDsfz(iHBsG?rNKK_?Qgf+=)KY3CwU*jQZKZZnN2!z4 zS?VHnmAXkiqz|Q@QZK2u)K~gg`a~Ke4VH#T!=&NTNNJQbS{f^jmnKLPrAg9cX__=k znk~(d=1TLVh0-EviL_K&CM}m%NGqi;q*c;tX^pf_+9++3zLqviTcoYhc4>$7t+Z3x zCGD2>NPDGy(thcHbWl1Z9hQzt$E4#@QUWDNf+a*kB}~F4LLwzfqVxFhswc0rW+YbP zBwi9EQIaHCQY2ND(k9%x7x+~q2?n@7(-=v4qBk8g9yYwUv|5SP={UQA+J(pfce@TB! zFQv2;k@L$La;98BE+`k0i^xUgH|1h-ak+&2mRwRUC6|`pmdnUx<#KWbxw2eEt}18A z*>W{GD#zp;xw>3Kt|`}&Ys>G+b>zBoJsFVWa;}_^>&p$~hH@jhvD`#%DmRmx%Pr)V zax1y5+)nNwca%HHo#ifaSNQ|Eo7`RQA@`Dd%OA;o<$m(Va({V%JW&2b9wZNzhsdAG zL*-%eaCwA0QXVCbmdD6r<#F|1P4Z@W zi@a6-M&2fGmv_kD$~*Ju-X-sr_sDzYee!oBU9IBtMpam!HT_ zvXpG4ni5rFN{&)psiD+VYALmq_mnzH zU8SA^C~+lMNhtM|21-MvkSDJ_(iN-O1`GI^c-)=C?ttjxsk7KTnyje5Nc=7AlLB#mW+8sj^J@ zTv@KHP*y5mD65p!${OWMWv#MKS+8tVHYuBxEy`A9o3dTmp?s_CRCX!5m3_(q<&bh% zIieg@jw#0#NI?}$p%q496;9z5NzoKtF%(m=6j$+-Knax-%1Pyva$5ObIis9a&M6m^ z%gPnyC*`VgO}VbzRBkD^l{?B^<(_h1d7%8JJX9VjkCms&AIfv(h4Pp3xAIa+EBVy? zYKB@sEvOb!3#&!cqUxJ!F}1i_LM^G5QcJ6Et7X-4>N{$AwSrnv%~G?~m|8=vsn$|! zt98}ane#u*%2g9;eYJtwNNuV%Q(LGl)mCa7wXNDtZLfAvJF1=3E^2qRhx(z~Q|+bp zR{N^`^62ib4p0ZGgVe$55cN}as5(p?u8va2spHiN>O^&tI$52nPE)6=Gu2t@Y;~?W zPo1BK|4dz=E>st(i`6CSQgxa7xw=AKseYlZQdg^M)b;8Hb)&jT-K=g^zfrfT+tnTF zE_IK(Pu;H`P!Fkx)nn>$6;vS=R#6pGag|U>l~QSyQCXE!c~wv)RaO;MRW(&tQ>v+2 zs-wE9rv_@Mo>0G2PpYTX)9M-Zta@I(pk7peR4=KQ)hp^%^_qHJy`kPzZ>hJ{JL+Ba zSM{EHUwxoHQh!&Us87{r>L2Q#>T~sl`ch4+`Lz66hE_l;s1?%Q&><$wbj~b?X?bhba&J`X`Qt$T377@t((?e>!J11dTV{OzFI%6 zzcxS{sC}Xh(gtfow4vHCZMZf<8v$WaT9Br;P zPn)kT)D~+?wPo7p+H!4$wo+TItJ)@tjt_1Xq)qqa%=THCB`(Y9*awC&or+AeLk zwny8m?bG&ahqS}mQSF#^T!S=NLo`&wG+d)JM&mSI6EsniG+9$LRns(GGqjXuYL;ee zj^=8f=4*i#YA3Ysw3FH??X>p2c1Am^ozs5M&TAL6i`r%Figs1IrrpqPYPYmswA1FkDdU?HqUQw^4SJtcORrM@ATd$_)=+*UFdTsqZy^da2ucrfgT+hv;JE7Ot8|V%7 zMtWntiQZIirZ?AH=q>eDdTYIn-d1m?x7R!Bo%Hwh&UzQUtNwxBEf3#a@1cLF_tbmo zz4eduK6+ohpZ>AlUmu_k)IZS&>4Wtl`ltF(eV9I6AEA%bN9m*War$_DqCQEVtWVXa z>ofG3`Ye66K2M*oFVq+5i}fY?Qhk}eTwkHD)K}@N^)>oheVx8u|4QGWZ`3#GU+bIo zE&5jd8-1I;UEiU9tMAlz>AUqk`d)pXzF$9}AJh-&hxH@+QT>>HTuYA?WhMv+*-O_E{(OuoseLc`a{e=FVeo{ZBpVq(E z&**3MbNYomKKxTY|Ev2K^-KC?{i=Rl|5?AG-_&pEcl5jZuljxcf&QERP=BO9)}QLn z^gs3I`V0Lp{crtc9^Gj@V&pUO8yQBXQNSo@6fz1MMU0}xn?^CCxKY9=X_PWb8*dwB zjIu^K;~k^CQNeh1PZf=KjY>vkql!`0$TG5xYDUb+F{&FijG9I*qqb4UsB6?S;zq8K zFd7&QjYdXeqlwYfXlArDS{bd4Hbz^cozdRtV01J(8J&$TMpxqlqnpv)=wW#;3+mW0*1A7-ft$#v0>{@y0}Bk}=tsVoWur z8Pknf#%yDbG0&K9d}b^#78;9;CB{-?nen-?+*o0(G`=ua8LN#o#+SxgW1X?y_{!K| zY&13*n~g2TR^uCEo3Y*4VeB+^8M}==#$IEevEMjg95fCYhm9k~(L6r9>dEV@j~T~} zqyZX`0UL;c8km6_gh3jVK^v^W8N4AHk|7(4p&FW@8-|g}quVqr!!{hlH9W&N0wXj| z7~dHujZ?;H<9p+ban?9z{9v3nE*KY$AB{`KW#dX7{wL$Aam~1H{A}DXZW_0YUyM7( zUE^2do^juJU_3G&8&8a<#xvtjSQ@c{TQ+reUQu|W}QU_Cq zQioGVQpZxqQ^^#Vf>Lk_Nuen$g{P=Iy6F^`l2b}bO=&4T<)wnuiPWjo>C~Cj+0?nz z`P7Bf#ng|fOR3ALE2(R#pHnwexAO46q;99~r0%93q#mXor5>lAr2a_#nR=djk;-po zn3-l_vxr&LEM^urOPD3iQf6uMZL^G7)+}dMFe{mr%_?S9Gt102tC=}wb+e{f%dBnI zGvj8i+0blkHZ_}@EzFi?E3>WH&g@`zG&`A{%`RqF^8>S++1>16_A>jL{mhTe{^kI4 zpgGtaVh%NjnZwNy=16mtIocd!jy1=b}XYMx- zng5i@>+ByfkD15KqzRgk37eRSo1{sZw8@)-DVmZgo0@5urfHeB>6otRnPDE?C(M)P zDf6^>#yo4DGk-A8n-|QB=4JDWdCk0T{%qbbZ<@EvJLX;Uo_XJVU_LY-<>4Qjznf3Y zr{**Bx%tBU%Y133&4`uH%5P;@1+79>VXKH$)GB5bw@O%VStYGfR%xrO^^R4+s%X7y zRkA8uRjh2QniaEhtm;-xtCm&Ude5q3)wSwbxmJCvq1D)GVl}mzSuL$rRvW9W)z0c* zb+kHJ?^~U%u2y&JL#w|vz#3=`vIbj2tfAI0Yq&MS8flHPMq6X8an=NDqBY5yY)!GI zTGOoQ)+}qbHP@PF&9@d=i>)QrQfq~^#`@A)Ypu67TAQrR);4R0^{utj+GXvw_F0Fm zBi2#tn04HOEZ9OV%)%|wqAc2aojL#0EXHCj&f+b}(k$IFtdwP1mgQQW6<8;%lh!Hg zwDrAp#yV@Av(8%=tc%uw)!~_0W1` zJ+^+go>)(u>9&mA3NR8Fm4?pk2r=Y!|iPw2Rrr?Gkn=`)#|N z{f=GUu3%TRE8A7UEO*V#X4 zAF>bIN9|+waXV>)He|y#Vxu-@<2GTFHf7T`W3x7A^R{HmwqmP!bZfS5r)<-Ilhi2(V4`~V$^ zRn4h-B$5Gukup_d+0E0rGh=&Wdt!JDi-|EIwlV9gtPNS4vcAqL4UEekpIsrlMRuj^2HCZ< z-^+d@yJ+@`?3LL|vzKMp%C4DRJ-bHswe;)E`JZOJ<&<(tJ8wH>oU%?ir@T|asp!1x zRB|diRh+6$mXqyNbD~bn$#JSXHJqAGEvL5g>RNT2x=uX@aNtEoz6}dr>paU)6MDb^l*APy`4TzU#Fkb z-x=TxbUtwgIfI=c&M;?$GtwF5jCRI2W1Vr%cxR$B$(ih&%KH9ae}j{eO+*I&>k{%q z{!95UV87$SI!lZcgPKDpIv-R@Kc}TeG%hZOQs3YhupW zoN+l5au(&jn_D)^N@Qngi60VKS;?wUzfn(hra9A{na(U{wll|>>&$cJI}4nJ z&LU^Av&32IEOS10mOCq)mCkBsjkDHS=d90@-v(!+v&s3|+3aj_wmRFLZ=GGvZfB3P z*V*UncMdoQokPxH=ZJIEIp!R9k`CxVd3e}C9Mr)a+#wv&p&Z&_9M<6+-Vq$pksR64 z9NkGdrsFuC<2!*9Iwzb{&iBqa=LhGalP{e=osrH=7f2UO7fQd8E}SlsE}DKbT`XNZ zT_XKfx@5Xkx^(*ObeVM7bh-39>GJ6c>5A!h)0NVd(^b+{(^={4bhUIe9ZTn=tEX$E zYo=?ZYp35!*Gbn+*GmKGcse(oNY_s{NH?mG9KN6usCcjt-o)OqGScV0MuJ1?EIlh4iX zX1JN|t0%jFThJ}!7IBNaCET~%l5Q!tv|Gk4>y~rNyA|Au?z?U!x3XKst?FjE*={vA z>c;Z$Ic{~ghFi<6?Y`&MaqGJET)>UHxo*O(?>2B7x{ch%ZWFhu+stk5ws2dzt=!gb z8@H|7&Ta2@a67v3cy2rquODv^Zy0YBZyawDZyIkFZys+EZy9eDZyj$FZyRqHZy)av z?-=hCe?Q(i-X-2O{z1H3ynDPy{KI(9c&~Wx_($jSq_tkB^9tjE{l$7XLiHJia2nGX6z;ReW`PP5jIF+W5Not3Lim)t%h; z-Og?ox2xOT?cw%xd%3;cK5k#PpZl@f-yPr%bO*b`+~MvBcceSY9qo>F$K}ayygR|2 z=uUDcyHnh$?lgD0JHwsn&T?nFbKJS^Ja@kPnY++k>o zJ?u`&nwm8&YkJm-@W`aYiQQ6tl?QBvPNc&${L+DCTr{~@BSa3 z+mNv_V^hZ08JjbE`vo#FgD{(oHW zb-zC19(9ko$K9k0x{wRIh>N@45Hg z2kvj~L-&#U*nQ$Yb)UI^xPQ9O-52g(?%(c9H|<8ed|rMp!^`vvcm=&eUSY3@7m4MM zy%~Ee_D<~W*t@a!V$oRrSo2uESVpWwtaPkmtX!;GED@_6YZmJos~W2ps}XAyYZa>$ z17fjQ<5=5RsaVNag;@Dm*;tua@mR4~V{KyXV(nucVjW|hV(-T~$GXH`cW(c0%`57?=@s*ednLS*UMa7%SH>&r zmGjDb6}*bxyIv))vRB2+_NsYNFXrWV)x8>CP4Cs&wY=KidtM!{u2;_kyttR^CA|7x z1Fxai$ZPC1@tS(gyyjjDucg<@Ywfl5+Ij8s@EyF4UMH`M*VXIhb@zIBJ-uFDZ|@_o zkJs1h=MC@%dY^cMy&>MG-cWCtH{2WPjq*l&W4y86IB&c+!P}hJlGvIko%Kz^NbFA> zNE}QYN^DDPPwYs1o7kDymDruwlh~Wsmv9qn6YCP|6DJa1BvvKt#Not|1d>1#SOQNF z2{J(?=me8s6N?i|5=#@y5}zly1fLKRVnRyDiLVkH5*rhn5??2BvXq3HSe;mt_%d-e zkxGCGC;=xfCXObKC5|VOiA#y^5~mY-!b$v?FcYsj^`Enz=uPq_dsDor-ZXEzH^ZCh z&GKe@^St@qXWjyDp|{9e>@D$@dds}ez2)8tZ>9G|p8QsMtGzYem)=@$owwfm%G=;= z^fq~4dz-y2-d67$Z=1K>+u`l>c6qzKJ>Fh#pSM2`f51EF9r6x)N4%rnG4HsS^gs{t zU=Q(75A$%3@JNsHXpi+ckM{&m^dwLA6i@XuPxlPZjC>b47RkxiDw6xJN2`2o^8FC$ zm5+;Dj*QCJ*%N?FOB6no&sNB)HV{*slj>{dNJ0W*s?xftwxl?kd=1$9< zo;xFVX6~%q*|~Fa=jP7KouB(%^kno@^mO$5=$Yu*=(*?*(eu#@(TmX^qnDzWqgSFo zMXyG$MXyJHj^2pgjNXd=61^S$G&(doEIK?oB04fUDmpqkCOS4cE;>FsAv!TSDJn*K zXML0v6?s~s^_q_Yw1MfHQq4&sp?EUUN z@t%6myg$4@z31Kw@2@=k-`-0v?M3{2ettj0&-4rU1^q()8-8KGh+ot%?w9aO`lbBR zei^^4U(SEWFYj0IEBclFDt=YJnjiIVMoQ-UEmA#SJYOPT<9x02waxcOq<6k6k(ZIt z`MT!oobO-9A~%0-Ms8+qf!u<*g>v7>Eu32@ye%;>D>?C6~6+~~aM{OD)V1<{4kMbX94CDEl(HiAX)$c(CssxGOz zwCb{|pI7~lNj&e=n4ja<@@xBb{Ca-e&-D|2eZPU<&~M~7^;`L^{WgAEzn$OF@8oy( zyZBxGZhm+F)fIa9ANoE0UVd-CuRp*a=zro5@(24v{Gt9Zf4D!=AMKCz$NA&^3I0TX zl0Vs>>QBqVPxoi|v;5iq9DlAq&!6vq<}dIU`iuO<{t|zwzs&#KU+%B)SNdQ0tNhje z8vjdwt-sD+?|k1ZDxVfjPijU>-0Z_zYM8ECdz-i-9G;QeYYIIj|g90jvbR09FC3 zfi=LFz*=A(upamd*Z^zJf0w`8-|O%5_xlI@gZ?4^ zuz$>leAq{P)W>|>r+nIH^W?|*yf6BaFZ+tG`kJr%rf>VM@A|AGI|f8;;* zfA^pGPyJ{9AO4^IbN_|^m;blF7uW~v2Mz!SfkVJy;0SOOI0hUCk^l%m01O}i3Sa;Z z5C92K01Yqz3vd7r2!IGkfD9;r3TS{17(faz0SmAJ2XFxo@PPmbffK-Yz)9c~a2og? zI0Kvo&H+CF=Yb2rMc_x^5^x!~0{jGA1+D?tfuDgJz)j#5@C$GoxC7h;eg*CU_kjn% zZ@@#~5%3uJ9e4sf{ZDxcUixW2666mug3O>mP%tPI6bXt3#e(8NiJ)XqDkvSi9h3>m z2IYbZ!Mj1_ph{3Rc=ZHl1=&HhAQt2V)q|Qrt)O;LC#W0L3xFUV^>!=Pu-E9f13 z6!Z!D2K|DMgZ{yQU|=vP7#s`<-pVYQSt_%1=G&QNGV^7Y%`BJsPG}H%o>?BGiznm&U`PkPG;TAdYP~8=HJ&qW;`=DGm%+8 zvq5Ih%!ZkbG8<<$$!wb0EVFrLi_Dgptuk9@w#jUp*)FqvW{1p;6^stX1Y?77!T4ZOFeR84Ob=!RGlN;d>|ky% zFPI;E7Ay!B28)8ldGcElEDe?gp9jl>6~W42Rj@i(6MPx04b}zggRg=O!Ny=yuqD_U zYzwvrJA$3Tu3&c_eowGB*ca>%4h2VoW5Mwt8Gr#4zyTUy0Ui(m8BhToFaaBI0Uro~ z7)XH}D1jPifgYstto3@G`~Sx@Gq3_XZ~`~*f*=Tk6T!*gRB$@@J~$Jc4bBBW1m}Yb z!NuUm;8JioxDxynT+QS8wcvX2b8sWL8QcnP2X}(I!M)&q@E~{?JPIBMzXwl(r@^z} zdGJ^8GDruJFkhHIeAT&(us~QaEEE=Aw#_6&Q4y~B^f zK4IUmUpOEf7!C>thr`0*;fQc#I4T?+jteK`;U|TY!ztm^a9TJ$oE6Rv=Z5pb`Qd_a zVYnz<94-l$hRebg;TPfRa83ASxHeoDt`9eco5IcEmT+shEzes2b36XupL*4S?ct8_ z+i+*NE8HFK3lD{d!z1C*@K|^}ghDt(LNvreJS0Lgq(VAmLN?^`c+Q7HD27rfhf1i0 zdT4~H&bd6iPd7rUk&*jll@VrRv! zihUIaDh^gqDrgn<6^AO=70wkd6|NQB3SNbv!mC195l|6U@jZ_}D)t5Z0Dm9|2nNJJ z2oMT{0}((Z5CuqpXdniN1LA=MAQ4CgQh-z-4UhuqKxPm9vVd$r2IK&_Kpv0}6aaFd z5GVqQffC>_Pzsa*M}TtRDDWq695?}-1pWd}0cU#Tp9RhV3P1@|0F^)$Pz}@owLl$k z9;gS@fCgv)8UZcP1T+IJKr5gF+JJUI4;TO=U;@lQC(s3iS437sRY)olE0QWQDzp_% z70nf`6&)3pitY-a0<3^4E>v8sxKeSy;!(wuiq{qID?U{WsI;jZS~D%q9Jl^&J6%J9nA%EZdlN?B!2WkF?WrMgm6sjY0S zG*+4_&6Qo1-Idl#wDL;j{mKWG&nsV4zOH;<*-O=1)mJq{HC#1XHCZ)9HBYrewNtf6 zwNG_GMN!$Q>{SjbM-{V&5Au)F-vV?4RsaA%00LkD0Z;$~aDV_V02hHvz-8bHa22=) zTnGLJZUJ|IyTCo*K@a^N0*`>lz!Tsp@C<9J-2Y@!dH(S8y0O92^Ob0!M>mz_H*sZ~{0HoCHn=r+`zzY2b8l z2KXB|6PyLk2Iqit!Fk|(Z~?dwTm(9+qEr%9tSV8Jp~_Tct8!FDs$x}%s#I03I;uLR z`crjUbw+hgrBEqV6{<>Am8wQntEy9}Ra#YtO0P1iOe(VqR6#0KbwPDQbw_1WHLz-M z)sU*;RU@lLRgJHjP&KJ)a@CZonN_o@W>?LtT2!^7YGu{xsx?(>tF}~at=dtwr;1iZ zud=UlsA5#Ht6ZzXs=}+Hs$#3+t5U1ds?w`6t8%OIs`9Ifs!FR)S6QmSDzxfK)zuz8 z$lr7FZ^plaOTeYzGH^Ng2e=Ac4Xy>(f$PDI;3jZ0xCPt_ZUeW2yTCo*K5##H06Yj% zKxz;D=%6iV2ReXQO&M)trk>! zRg0>{)lt=n)k)Q9)w1fG>ip`W>f-8>>Z8@is*hKntp2O|Y_+0VRb5+csy0_!s=;cw z`a<=^>dVzvtN*UPU45teZuR}@N7aw3pHx4sepdae`gQf2>UY)etI6sQ)gP|!>D1^uxmIqE;SxCydFNd|EA{OV-;(8D2ZSc5?0X+Ih9}YZun8sHN4?Ywc?pwXU_?TK8IBt*|z>Hnp~_ z_C)RJT19PLZGEk#wzamS)>I4DVzpOluh!nEy;Xa=_HOOt+9$QoYG2g8uN_@Crfz)Q zq`Jvcbt~%D{Gagu><9IS20%8@Kxhy&7#afo3JrsXLnEM( z&?sm$GzJeuHL0v!L0~9B3{y51J1xfEGfF zpvBPd&=P1l^ar#OS_Q3!)Vz3?S=M1`ymQMh3JqiWCuAw zhag9Y0Wl#bhy`&VSI7-=hddx2#D_c~FUTA6fqbDYbzAGU*X^j=S+~FLK;6MQTAh6z zyUw}JrOvgETX(eXSlx-b({*R-&ef^vs_JU$YU}Fi8tb%mO?9nx9d(wv?mD0jtb^(< z)IF{netyLH(dWmXpM8GO`4#8)ocA~{IA40c?EKO5C(fTcuQ*?I9zFm3{Oj}Y&-beD zUEi;MUj6*~MfFSSm)5VTUt7PvenrML>~|1d4`Y zpjapliiZ-QBq$k5fzlvp5B<`i3@8)Ig0dkQlmq2Lc~Cx70Lh_3s0b>CN}$6~DO3g> zfy$vjq2tg==r8D0kNh*xS?C<3fRs=LR0&l>wa|H}9#TUZs1a&{nxPg*2em=%PzR)k z43H5rL1w5E>Vhm#H)MqXsHncUzO?>m{ptEM_2=pp^~(C%`nq~`y|Lb0|G551{qy?Q z^`GiL*MF_=rS7dBpteyDR1Z-PSC3auP)|}%QO{D(R?kx}Qm;_2RIgUAQLj~RQSVUG z)plyO+F9+Y_D~DezG{DUpgK$)rOs5JR;$#tYPGsmty8zF^=gY6RHN#v>g(#8>ig;k z>c{Hm>i23={Zai{-B&YSGhMSmvr)4}vqN)0L)FkV3=LDm*0^c}8m}Hcc>kv6-(!Ig z1i=sjp%4b)5CL6;ELt{fzLq~(D;X=d3hEF|w@V@8d-;5W)3*q14CGawMIs6B_5?%$b zhS$Jr;dStOcoVz@-Ue@ncfdR0UGQ#rFT4-l4Zf*us<9C2f{&cFf4+_a0na< zhr!`+1RM!R!4fzcj)CLh1ULy!hEw1)SPG}Z8E~)0zKug0hc%999N##(aeCwY#)XY5 z8do;1YFyK}zHvk2#>P#JI~sR3?rz-Mc(9S$NNcojWHfRc-5Z6Csf`(pvc?mQryCWG zwT<)`WnJ=_2{!cA~9tb^O(4p zYwa8DTkU)8CvD%ReoX_K1~v_E8r?LjX;IUbraeu2n+`P5nix&YCXXgTQ*2XQQ({v} zQ)*LMle9_Jl+%>gRM1r1RMJ%1bfQVsq;5i+u%-)5SDGF)J#Tv5^uDQA^DoW)nujzG zZ64k{x_NT*l;&y8JDPVk?`b~JOlh`nc4&5NW;Q!DvzlF-xy>Fue31UlG5kx9r@_T=Udyu_7^7kS8kpsv< zgo02J8bU{G5j(^laX=0sjtB!`B2EYkVI$562XR4M5ia6}xFa4258)%8hyd|I1kK*f z0nLHU!Ofy(adTvIRI{WxwmGpmqdBuVyIIzp(_GYC+8*@bcB^Zvpw+8Y)|%6r-&)jqwDnl)@z#^AidJQ7Wvi;SrnR=UuJwGYwza9X zrM0zH*Q#$dwVGQktzheg){Cu|Td%ZUZN1&Y2j_cE|IOGN@j--$FXD&zBLPSt5`+XJ zB1DXYAfZSY5{^V5kw`QWgTx{6NCJ|CBqJ$3^h-t35Gj(5WFfgo9+Hm~AabM-DM1b+ zWylev965&ki5y2xASaQ(kWhs->l}0p z9b4z25_CAx=dY`PNvJ($#tc=GF`dunC_(RwC;>fp;PIabR9aA z&Z0wggzkdwhVHiRzV5m1h3=K^lkT&wS6knX>GE$qPD|rWo;+gPPUzHQ?x1DYTN4C>f1DJSK6+&-DtbjcDwCS+vBz;ZO__X zw7qS6-$u55Z2Q#KtKFu3VEd5vq3xsEN4Jk@AKyN?eOCMI_Id5|+jq7L+P&I^?E&pU z?P2ZV?NRNL_Qdwo_Kfz{_6zM7+pn}=Z@Z`_TjFL6m}0Q5s4| zZBe@(`q`rn=pob*WuQ#d31y+qCxxu_fJj`C1G>WK^BD5GSK@X#) zXc@YqV?)Qrjy)Y79lQ=fhpb3eNeY3tpuh$#&M!iXI)_3YHdTS3Kgnv`>@3D@c<>*oL82TrA96f=aME^oh zp{LQa=s8q@D$xqG5>=s9Xf;}c)}nRjd9)r?_s~y+HlU5D7HvYC(H687)uC-@JKBNj zQ3Gm3O{f{|M7z*#)QSQqgu*C-Vm8g>}=7-$B%!OmcBa4@h9&IVV5(BN+fG=v$#4N-#+6MCTugd72Aew$97`7u-(`mY%jJC+mBH&8fJ^xVfL5d89rrxH$CL7bB9_Qe{=k(udS0!)D>ktxg+VTv`ynG#G%resr!DczJ| z$~5Jh%1q^^W2Vz4t*Ob>VKSL4Ce(zP2-8K=4bx52ZPOdmC(~zBFLPgWKXZTc5c5#; zF!KoWc=ICj3Ny`2H`|*TW>+)U>~0pC1I!|GlsVO$X3j9n%thv6^I>zDxz(&QcbJW4 zleyCjnjtgN;~ezAsrmO~HKAb{D&c zJ-{AfkFY1$(;oUg!=7U=u$R~?>@D^l`+$AKK4G7+FW6VC5B>|@5ATl;zz5=k@WJ>H zd?@}aJ`5j;e~&*FABT^}C*TwDN%$0eDn1RLf&Yfj#AoAk@VWRrd_KMaUx+Wlf5(^L zOYvp+a{Lc`1-=qrg|Eif;p=hCjGHf-FPX2HubOX||2E$?-!nfpKQTWuKR3THzc-WS zPv%~oHk|`I2X_wX9NIa$bA0Fg&I6qXJ87Nvo$OBMPM1#CPHv~5Q_`8(S=6cRZ0c<7 z?C7*~c6S1uP$$xPq4Q$rjn2oNuRCqJhIftb8s9a&Yev`Bu036QyAE{Gx)@!|F6St5G`t|6A8mf@DsmdTbWmKm1cEORaMEb}dkEWcZpTGm+BTGsd2 z2md`M|7N@q--K_*x8mFI?f4FS7rqC3rL*gU9yBkHh2f zL_8T!!Bg=xT#BdTS$H;{gXiLTcmXcQ3-Kbn7%#yOejGo6pTz&dPvK|q zv-k$fM$0D44$Dr<9?JoXy~V-eXkl2G7FUahg>Mm90xV)nk)_yDYB_2-Z8>8(XHi&` zmRd`lMQzbqIxKpN(PFlM7SwXv^4Rj+(!1NHdtmpF?&00zyC-x{>Yma)t9xGeqVBcb z>~7a?k8WYNZ?}JUV0Tz|YIlBjL3dGiY4?fllijDf&vdK0JGw31VE6s*$KB7n-*=PU zAG<$y_qEzshge5jCs?OjXIN)h=UJCpms$U?uI#Z7?%&k>d#rP~60g83@hZF;ufc2a zI{Z9dkE`(pT#Gm1&3FsmitF$;yd5{-M%;{d;$1!T>&C4(fP*-UBRGcR_yznDei^@l zU&XKC*YTV9-}o*34t^KEhd;m{;*aph_>&&_Pw{8?3;ZSi3V)5i#oyuYaT5Q4f5gAw zU-8~VAL19HAJLx}K-drii9y6*VhAym_>~w&3@1hsqlnQ2!^*U>tu9tqE7vNpdRcv} zzE+V{Yz?zUSre^E))Z@+Rc6hx=39%bN3F-K$E_!oz#70FZ~zzp8}I;lfG6Mu z1OS162nYjWfg~UUI0l>sR6qxC1Gov?2JQpTffv9l;0^Ez=mqu#M}XtO#o!8XCAbFM z(BnJ!_nQ2h@fcz(F^-r>Od_TbQ;BKB4B|IpCNYbcP0S(Y5(|h$#P7rsVkxnVSWf&w ztRhwuYl-i#Zym9o*hp+5HWOQjt;9BBJF%14MeHH=5&MY)#6f~WPzhVYj&LBH2o}L6 zoC!{kd>6uv@F4hvCm|rb2_M3j@FV<*Kq80;Cd5Pt5lVy+;Y0)xNkkJdL@W_cBoK*2 z5|K=#5KtY?JPDo#6<{q`2iAicuocvS z9iRy`gCGcj2#A6hcm=!)-T-fdkHIJ4Gw?b10(=h+g_c6gpcT*>XdSc#+6rxlc0fC! z1JFT;2H8Vw$Qg2hxR3x6LQzm6lnNb%jzK4&(~t_Pf@+{Tr~%SKt@KSgMyaC<_Z-%$Rdti2tb@1;w{Ws%GB8$i-a)?|akH{wq2su$mln|xF5u%(p zN*p8pB#!sc>)*V#{|%N091F+6iEt_`gLB{lxD-ALpMVu`6|9CeuoiBCTj4g?1e@V5 z7=G@+&eN8I6oZCL>djX~=YB1~MC&hs;M7 zAxn`p$XaAQvH{tM>_B!RQHTVIMG}z=BooO-WJnHDgcKvC$Wi1pat1kvD3Mx3jcAb$ zM30ydGXf$PkekRYC8=*j4N{b_ctUJ;q*RZ?Jb5iS@#J<9%@(d^kP=ABB&`$KaFk={@d) z|9@rw{pEkdz$|<*z6M{5Z@{*|;a}g$Lk)xCl?clkf~Y z6PMxnco|-fAHz@M3S5P2@J74?*W)JKfuqB-Rich#kakVlP1>=!89Sh;Sqr1e0(jxP&{wBfJP95kQED zC_+NS5vfEPkwM6aBBGc$OqBhfo>%`j-2eBR{}}ku3~ZzZQ+Lxy+ELqQc4GTG_5%;; zzO@BU`PKxy-t(E~0iXYAC$J&na(v$e$JEr+RZ>$1kohs|ZZ=lD-d1GS*WTOJgRAuc zf+xl`q`_&&3lgYNdZSHNA%d+0U7|D-rM z1P@7xJQ?4W*o!=smtGL-@F$Dz*qf}0(!|u|%%e5h?PT9~hTZ(!FL~VanC_F&@5hh?DT4Zn!zI4aXJXUS zMCtA_dRdxVgwWofCRrCVQyN9z$1RJTknWh9k*D~!4P`2=nbx1Kv+cHxu?uiaV3crj zTtc`CuGK@x^XE76U-JtEDZWVoF9OO%Cq*3I1@VsZD?N2yO~OxN zSx9u~=7{{5Ut*8NX2;!){~Z53L6@{FwKnyn^cS);`}aJf+_UIH$*A%t_J?^d`PqUk z5vwy?%bp+da2(;>pI;^D7JTuWCpwaP`>;URmpol^m@1?P(#vh_S$CXiuD-4>+)lZ# z=Uohrh&Z17XGV76a>`AXja#Yb717VY|BtQ#3P%!Bq}9^oLon`$4eD=Rm*`(FM`5NLq|Op*8JX#+8D3#lPD+yFPa7Ba>41(r4IRWZdH1 z;IHv5326JabWMwV5zETw+Z}fIi8(}xrR`%}V=Qo;%l&qw$!qK3Y}R;5Rjf<)2?|8} zc6``j2(#VJ^7bxN_MC0mtu#KbBD)Mc2b-v zM#>9nDE*7=kLK=Yz~5qb%kGX{mi_2MV#hxnjjR-Bkn@Rq!Hv#Sdp_{&@}l_|d>;F3 z6PEdf1rR~<;9o>7p$|esB4Q*1V?V|9iyst!J>D(#kMvI&tyv>vRWgs<^SN;G&XNbE zL|JM1V8<=&&V-|d=L&0&OtLSEI1zI(wL9yktQTVsyU4vfqJlNbB|M@cA}d~zHHWsw z_PuSWosHuww;=aH-&z!{4n1k-7%WH%$-)ZOeQR43;O{H7WbH5RPloctd}=d(2L69^ z4I2&*ARpN+cBC*3?jOA#2JZ}Oh|ouTi4rGfrv+!Ol$|d4XuI2Sx7an(k}x&bhGcl} zr|-8-v7P32K_K=jmg{LJY;W7Pb5HQr3ch+pi}puq;vXecr>#wgviBAbBs(dEOxR-t zKg)ZCC@#Dy{7igwYD}t2+8}aH-e78{-E7xDw;#${#(P2qTo5A1)_M-aZ#8!MjRLRENpA|?(jX~5#a@qy(A5i)R_LUi(@ll$4jZ{ zdon^ZXXMSw`@4u<{A$G&zPGOO7MQlV7A0$cf}6axy9BPazKlP9>+2x8&1Fs(XaHqumTL z+tbx6*zY%TwRk2ui=0jV4E+D-8iq>dkaNkP)XqcWo#v7A$pz#>auKU9y_gDn$tnCs~#GLOk(se1hj9gAKMSqYh$d%+Oay7Yz zgo@Xa>&W%w267|0iQG(XA-9s-$n9ji{|<5|*%DWs{law@xtrw2?IHJ)o7wxw{p11i zAW0#qB#oq#51eL8BRz*pY)L!Po^&7&k&fi&SO&=?H?Z#rH`_J%O=PZ0_|e?`4ESp) z=PA3W6%OOSZQnZNQqQ}~i}kMaIq3H!^jXBzsB4n0sp<@={PK|`R=rD&>quHJ z+oiT+9al0O8Nae!*>BnD&VO-oU9_$v+|%60d2Ijh{qG;>mq7~Jyf669@I(D>`+o_% z5)vL-6}~>AZ{nG>CmF9Y_hkJd8!fYweU=@}3z1(bgnjx4FoOOJ5(K-4wuIk~JRBXH zeuiOmA8z&6csrNxl~Yt_5=?8xx&L@0=IK95S9F zw(ILN(q~h^q@cygQ;!_5J)TW-zT>foH`eEo|MsZT=Rg?x|tp)7~x$JRTXtF%0C{KPRa&y&Qn*@ z-`H-mf6VdYZgSJ}E_r|PUl4vJX=bXjz^%l)r0|IK$YEOpKh$SRz`}61>}`cIZZEf) zyqW$#oV$Nu{Qc+}_6DYjUQ7IApC-=9o+;ax*F+y@d)#)2uPLA{)y#?KRrs{|Z;BEJ z-=?ghl80Q#ZwGdrC%aY$FODpUvBvC*ohn|1M6OZMu`}rN0^EW+!`d<~WxURKCr_qaqCI8doMN6ea9fBnbYJYJ#2?Mw&ww8# zn|nC3`~qXElN)=K_a)z9{_8`QNLEKrORakJEMTC>RmA*e z((MzrD4kQ}OaI+1OfIJ`q)l*s=&P12$WC|J!5t^ylF4$|Ha+$V-9qPhO^#@myhsqs zFHz^)7TFE6|J8xVKIKaBJS`CV#s$3(>Mu$VxsiX1g;C)#>X@_yAoXUdB?rv;TW&r) z#Xi~}3@j3TNIIK!T<%y}ex%T|%l8k_{kXA(i^6^e{(p20T@lkGbECXGyhSg?+OYd! ziemf2jYqDr95~bcOXJQZq{;?R4%*Fkf}JTYZrqLTUi?q|uYL>t-2;w~W<)~riI)SXY z{1VS30pQ~iD2}PmxRntn+j-a~PMUE*zNO^k5f|1d;iTY~A=g8OB%Y<`r5&Uf(7!b{ z6XXl~hE5M{kvx{T71kZm`~7I{eg^yzNhj$;?IrfV^2_*hy~_PsLUKaKCA1}$r+DQQ z<-RVBPpzQl(y!YZm>W3`+%S)Dj|x8MIpdqn@ns*EAa2lB(VEc9q2pq;@%<8drO!*x z$e8CT6M6z4@Pj?q`7I3owk1uGM&P?(XYsD+squXhypxVgTQcSra?4ILE*u#_`_*>6 zJ=G!QzxAJg;Q1p&I7l*B!ikk8#}+)3f3+_YlGho zzk#8_QCTr5Nx!DQ%jOooK2pydxwj!Wfz@Lc2FDQpcsBFc{}h?*2FjawC;nDi){lBb9r7sz4Eq?iD14V>QT&Y*G<#&xv!Zre)a|6lEI;~x&wu}b{!t-a znN>M%xlc>BAD&6er0sJ&&78;H%?Wkc?6!%g;pun-`RSgeUTuE*uo;rGv9WOr<7?uN zC1xZqkd90LOSW7tD<4XGMRg}h$0C<2Zn^IMp4~@q>gbsiV@^>7%oUQ8C(ZJGNaO>x|1#&+PE)IipMA1;Wa%Q$5XyV%US@ChGxl?~r#me89Pnr0LeawL$BBJXev`quuS$nfE>NCP zlW2!*{cY#i%j|DBE@bkZel&MK1HKbW%(AdbIeaq2EtGeP=jVIUZ&lEo$jwo!VrX&n zxRSUn@x}3H5`K{$&A6NKF+-Huka=HrC1x*)@tA&i%-X#Yq>6F71jIxfpff_@-{;gf>OS|`W{T*&OTt4)O;l>={^oaF= z)tCLsc_F9RWs0l7y_8qUd+YhpQz?k_DHamKnSKKUb_Vwe+Z4Vf+%;Sm{vdLkBuJ7R zJ2XBk0ZKF`Ur(h;InpWVS2FmS%IveUPes>@%Z}``^&&@mdjI$R=O4KL7tt2j2D06G z4#Ljhnc^~WVPt7ySkBVIP)e>xgAXV0OwvG#54qR#sbHL6dHnb!pVW8masDH7D~kqE z>S+LN8hw|;S%-0lwy-9!Z?M;Jq@1IiHqI+ox`6A=@Y@))C8#y%eF!hSDiV!(mHIj@ zSjx?~mNB`I!)OwH&M-O%Np8e%lA!pYplRaSVqbDXWD?^eL+hN)InR-~IJoAz#ke2j z>o{w-TQskWx7<$>*juzilp<;o z2}90?Uy?XPpN@%$tBG41KQZ}nidcFpGfb9~J3Ieiam8VQ9i46O)ghekyU=e){Nbea zX^W+2r4Qwv10zuHG0{Uv2+W~-H3f5fL53a-Artw|)^MlFY z%OSl(g^@pc?)(|>55)$>^5Tw4b92U0{xS8pa;M z{@ZzrTY~#&kH!2NfmWF6Tj@6~;KVn(!8zh=ah7;O$cV@rkqe`yOV&yjCHW=|NM0cw zD&xxPWc9gk3s;vAR3Y2NGsm|)DkFMq`q<2AG9T7w=b;|0iEP=;qLkotR*7r0=QZDH z(!Zp=WkZTq+Xj&IfUGciUO+05^OQ>1eRjBXDBkfiqs=Lmb&lQ2p3Uja{TcZG(KQTp z+wYd@KG|axFO0X=Tk5kyIKg+B|GmHmL1DoIMAf1>A>7c`aL0&;5t^uMi9*7SJ`yuO zZdrmX@lxW$BzdYzDobCJy-k)N6XwWsHM!~XQ}WYtT;8kDrbu3lluSH~+C?)aFauaE zEXdc%zdUe;NFz#${hV;qImP9y%Qn}?ypaNbFFWrvpOwC^d~XGR2~mU|j2tbQ88V zN}EbyQ0~#L+U~ZCaT~z*itd-nk!MmT*sVI$#XRA(hD~7~WcT5WaM|wK#9PAO#&7m~ z?KwI4@6dJO`k4I0?nHSSU+N{jDRsz*$aw9DvWB_%yFPIn>LvGK`y~d#kq#-0^eV4xGJ82|0(bfF(>>F2_^1UTv5W=Bx}+yDTAcvvJPhllKSjr z%oD7;tTfjLtikMdmpI|i!2ge~A&7k8J2+sXxHA5&w3V{eE||P1A0|9P>7d%uIS#X( z?z2a@F@u`o&nA3HW~NS&ZkFriqlyQXIhPG$)UcbJcW`dHj^W;P@8dn&uTPGB9;Ik_ zX=r&GOU)kWPUY_rYzWoKGYjpD$`2po^-k}~(iW_AIK#%B>o|q{10k;yj0Ffo>t+p_ zSN5FpJ9C)pdVYe>z3@3@d3LS#?T%xeCvkCprEg|fbbOI~M`5B}l$+eW+ILX&{uKldlbNLJTlb}2>w;Frib!kDG8Zu!LiUy1iT6)zOuUnn znH5U{dja~bcM z)0}EqS>#(zHYp=%?(5xi$cvON$B%qOW~{$T~A zIP#W6PA-WqBoC%u&nhB|$r6&4dzgG%T1u9YN5~}CB;RtfD)17~NRD*yPm#L7y@{vEGvt28S@ImIb`Eq=kkk2D z{BW-duQkF~!c~4-{V(}X3Rn_A3%ni}5UeCwq6!ifnL;QLdC`@mihL38Dz#=;k$dv0 z$q9uuWG%UkvVc}c+SuN-d&Tz^cKQzrjtO;(sEEIs)F=5oiKexrcaPc^>>z0w-b3f8T%pf$E&a z>z3OW&+)q}Iumg=;!fPfji`*+9nFdE6&n!OMm|f4 zOPij~l(mzwGTY*4?s6ZI@3iRIX;s+}RY@!SAG=4#G=_$y=4|5@cxCu{`knX74|EgF z6E6}6$F4~*Cl1QW&%2h_L1t0t)DYSNy2-A~?v-5%3t`P-PvpjPU-MW&g~3}yZ6UPq zoN!Hee@RnJdOViINp8#DEqfz-n3E*GFMlA%Z9QF{@RsqH2-tzEB6PArML85bY3qH& zN9LavI6hV#Zsb6>kB3D^1t`N{m225k;@6hZNEsXMb>Wd_ns&M2BxX5%T%xUb<2^fZyE=Os@w$@Oyc(g^4Jc9LuSy8avg|G@aa z>Axy?b+CnGiom2-)5obBdQ75C2oaw_^un66Cnt?1BsAMe-7PnT(13)opTsK$4kq zg*@u$<+__&@6#-e&8?C%Dbws9`7TZhkiRN?T7Q(X@xte*Od7XUe zJjsRSGQ;%-d6WE`yhUybx)Xex3=nsV?~otE?~+4e|AjO&XCR+OU$R3iRld#9px9>0J|q-ll_fDADMdA7?*ArKfkBsGtyhK zGT}Lymz*hmLHZVk7QQ53k-aER)MzTnxWoI?Z;ecqrz!qOdCZV9FEY2fz9!$0qa)su z)P(j79({-1kLK=Yz<)=+CrPrK;$`c=YKccF>ugWko0(skG?pWa&2o3$!|n1b4)6<1 z4t^)96YIhjO8Uhv-1WG7anb}~;>@J{Bp~T(>ZnXbPH4f;!2ge~p;Vsv z&3t*Dql$IVjpn&gkSEyahxkbXW<={!k7W$Z-d|2BUmTPj*)5%zx0_0#E~m%ZgUkX> zotxOx&ug4_g>a(Z#h?YjO=5NAO3A%=GQlzNT@p)LnURt;L8g{jm-l)&ktrQ$VWx;QB0KxBHPGSU#4 z9qlLGl)X25b8cSlZ+Q#zKgykoe2S(P53pU}R^-O?^$6*VXpIb!xY{+d3ps22H33CY zBMP$)UpsQrJ;Ea-r8lL3qNK2CV%i@2c4i4{3rER$$BA>%yRLKJ%oFh}ybyjE|BI)< zE6v;8XN$1a_rC8mKaStjfMWq!!JmWIiCLj3VOimWBP0>cQCX7R@qMHZrAIOr=j_Y5 zki*Zl` zpHtsUcVuPec*qaSHx?c!+E;F+?xJ_m&)6yXZD0crLAwb;L#G>chnZ7kz&h{T{JRQYu*%?GyJi z@c*N0Sdg_cD>`p{K8;Fqyz6|5v(Vi;W<7;U&89lht};7fz3m0|UmU2+V%9b1OB`qZ zGS3&D3k3It%YFCxW%}0#+z3t)ABgHBStR*WGA;gc@_K2KG$2!&^+)zH870RyXGcC* zOh%lH>ZJCj8|Ws-XRMEGCV!*1lds(GvHy@jfAOt|-%@AD#Ii2=*W%s@izzQDyHdMz zBzBj*eY~~`BNC4=vbbOP&)lvCj1U{ew$bXuz3DcY`za6qd;a?e=Kpi{OC7g35-z>n z2e|utEaBbfMexf!Ydqb2T!kgVMgDg}XNT<#cMP8(`7^dp+^e{<`1<(qDH+mFWZ%r@ z%plq8kO>j1BkZF?V+S~(4r0a<_uoAB^7r$71&6&7eP;Vs`E>^iM8`xdu||9|WNK)7 z=-u#v(Nm&7#w|%IOkF31G9G2AvX{%0dG7LH`GCSi>I=JvOtaGj4n<)2){^c)cy7e; zxF^XEGc1`;vdej6JU^4~93B0yN|t2*=&|!N;J?i?$m?8QaufYWQ;Mk5XlA?X4*t$h zooD!X_;iJpM1CRnW_4!y$@aQ$^4JoZ7_lTTCf~bUH}JIRlBgqMWK?`~byQJw zN&28nN&fKS1I24?ue0uYEcX0e@`ToI7tUaCncNRt1@B_Sx9uV618Fm8V%ud78=P)% z0$f&bIlLkKRs28s-CiAj%l*d&&j`tjSR2QT#}l-Pb+qS>t*rYjFPCHPbHeH*R}y9< z8FSv`Na=4p5B<0Q>mL~Zii{3=BeTiXA$cmtjbEVSCUmN+X09UkOaWqdj&ueM6X0)Cs9a%1&#U69n2kE zfFQMUJSAD_SUx0i3ZY3QD4qRioE_$EyVbRmu&u-uBIDY7i@^bjdO*d@ZEImP;JaOBn zzJ315KfB1hRCk;9+TZ$y=*(L;be&S(`oTLNx$~oUoxP|1A>*SR^k1@*my|E$zx$gn ze)Yw-Ui^)hfA{4#U-rKGi8p`!tq&jk`h(wiH1pV@Z;pNQZ@)dr-uRsh-`W1oZ(RPf z(+BSS+=a}czdhso;TH}CkH32N`qSTd=HX`=Pc%{Qss8=%cftPed%(5;Cr`OINbASE#Ew`We z-W?rx51#A3&-P&I!IKaD{$pQ$Y~=CmZe)?G54YC^(CytzQ zochF>V|V@|{co@8-|)Zj*Vi67^7&)my8ah3H=O##O!&65r~PO8?v3C3#}__%;diRv z|Go?M|K#@$9ew|Gr?3Cg@i$K%JbT0W+VdTczjEoW8~=)u-1>osKlP;g`J*@d&21fb zzH;-2Z@KrL_hjz8c=e&gk&oT@M<>2|@~N}u?@rwP(Qi(`|0-bk1>I%+>+j8s+$O#E z#oOL{`@uuMar6(b|KO$LCm*`weHrhAhrfB>(D|BaK6-tTzj>?DfNv@r)qD@-1hL9@ZFz2_t*D-;=(^X^6(S2wD*PI zdHqihfA;z(&V1?q$OYB&^6!55rJslU*H2rAkG*>KQ1r;vx88Zpdyl<(;`-aafAe#LC&xGzieNO-2|9&L!pZ(R#%P-|$fARZYxTW#5 z|MZ8?zyJPU%4}To_~E;bA31sC%`pEFAxU;ET=J=gey z>6`C3@xqC<+poX-kMFIy_xH~qdm{0~i?6)&%C)arU%UVC=f9gj^jAk)kKTIh(y@-a zn$Ec%KTW^&(!;Ml`oj+#9X&ez(CkyvS8T6*{Z+}qU%n=GFK6EOy6oVwYa5QfeEm%~-g$Gw&7&tDzVqR8e{w$k zbmZClFD+c6FGt^KeY5-UC-3;kwU69#&6%s1tDn&v{P5Ab>*gQ$?HB*!wO@YY`ZwNq z%H5jt z>;r8N>^$(74}b09&pm$X@jvAd^QNKh0_d%phs zOZP23aOZ`uFp{TFKJ$UglFKzOE8n>1(DlcIC(fK~IDO;AuY9Ne#phl-c<`lz-#Ti) zA#=myH#U9!FOGlW)R#{E%IPzwSI*vfZt~o9_iW$uy?cZAF5UZ$^HcZ#*@c@f1TVb& z(AOUw|JFyp9ePqupJjX4gHIiQ>cZ0xKX=#j+LuMI-~PJg#79m&{NhbFedzSoxliA7 z;KFCWpFi$7@u6=H9{t_px7=;L`(x)^=im4Eqfhh|_WIvzRu*e4IZdF!@6%oQz~k)YJKy}XxBlgv<(^MJ@R{ewUr8Lg`WEH!ubtRD@%JaM zKKZ%RpFb_Tv+wTX_l(_h>fWpGd+Wl}5A}WXFTQn{x&G-xmtS~w;D>*ABye5!mP^M^ zo%r5~t&^uuzvs+bcg4=t-FyE0T@T##?QZHH7~50IOM}ldhwp#j)tk@W_1^Erjy`qW zH*WsY?H6w!JN=_OUN|>=?&ksjpSBMFa)0BK55D-dH|wwYy=&h*^1-A3di2?2L&px> z^8E2nojHA<|AF^i_8v|izU_vI8{T{0ckj#Ir@Qz+Ev-(eXHQ>s-`b`B_1*3te)yVyzRh_4^n+)fy6wcl=eB=v)uGKpA2{-fbK6f^ ze)!v`|K#lJ=j{)^=jfwf|E0%2a_NuGe(LNO&wldg`4gWyXMf@YwBy>qp|_5mz0Q2y z>W#mA^RM0V#>v-De*Dxer{_<igfjQ2&40{`a3dUnJTQ z{etKhMeh;4SM)y7`$fMb`he({MZY5YRnf1BeqHoI(T7C8A^NcBH%0$L^jo6e7JWqY zJEGqe{hsLeMSmdrpQ8UI`l#p+MSmpve?)&Q`V-NgivCRW=c2z5{lB8W6n#weSE9cb z{f+2vMSmyyd(p>5|6BC`iT*+KkD^bA{*UOBqJI+ov*=$$|0?>F=+l7zzllC0`mE@4 zqR)%IAo`-{D$$ojUlx5u^i|Q-qOXY#imnmCuds;@i;jqnijIk{6J0O5L3E?&Ceh8J zuZzARx#m4SxTo5$BJi_=fTAQHaB}I&W|R_*L@lX>SykD}&yE&9Uy}66`eg&MLD`UO zST-UXm5s^9Wk#7vW|mFJCS_AHiwrWm%qp|V>@tVUDRaSC*g~?fEFzng&B^9v3$jJo zl5APFB3qS3WieS?mXNIh{kkkEOUX85o3bt0cG-R*ub)I;q1}%w6fA9xR;rb0(>UfGuogwqz!8$+F9+Kc3!)nUDPgVm$fU}Rc%xo)5f(4?Hb7D z+*iK+WUsDO5vU?iMWBj66@e-ORRpRCR1v5mP(`4MKox;10#yX62viZMB2Y!3ia-^C zDgspmst8mOs3K5Bpo%~hfhq!31gZ#B5vU?iMWBj66@e-ORRpRCR1v5mP(`4MKox;1 z0#yX62viZMB2Y!3ia-^CpH~F_2L2xZ0r>MbA~pQY_5-3iaXotK#Cr6!N^JP=p~}Q^ zG*gO1Gpvq?N6S`RW#iI4KZ#Mg;@=FlPj#CdU6oDr{! zlQ7Z?b`FWx2qlL~tvFsX-VZ6qK9qf8J6i1*4-l$Vag_A;Hq8Wr+;oW`>$hzs-%?>SWqr1mz2xO73Hcjs*EY)%7k)FxvoqqQ_2lN z%~((^s+LsCsuk6$DyoX9;;MvdO|`B{s#2s^l`5)ty10u6>LOH3NQd*SLN~_YQv@0D-r_!Z# zD?LiD(x>z*1Iig?P#IE&l@aBva!xrf(7G~a!dbCgE0@S?<-$3xUn3utkI3ufQhC3; zPhKyV%ZKGda=lz8ACwQsb#jHgQ$8jim$%4`a+BO3SIN8OX8DA?O+G1~k~hLX`D2k! z%Uk7La;w}XZ;-3ycDX~|F7J^$-L_RBT z-X%}DeE&Dc!+T_WPKJ;;2-$H!G9nq37$xJ9F^OpxbwnIS8MIx}M%L!UvuLhW(n98D z!~t zlyrdc8u5vU?iMWBj66@e-ORRpRCR1v5mP(`4M zKox;10#yX62viaHuZMtGED_g;mE;?^Msbt4S==IS6}O4o#U0{KaTlzuhz;TfLi6rw zDOO9=HEO9^rk1M}YNcAGR;x8?t-4lSr>sP|E$UWvo4Q@yq3%?7 zsk_xZ>Rxr9x?eq@9#jvhht(tMQT3R5Ty0dF)MoXBdQv^5wy3AoR<%uSS3A^BwM*?* zd(>XFPwiI+)HCX!I;0M(BkEc8oO)ippk7ojsh8C&>Q!}A9aG2E3H6$KU7b|#t+QAo z(bQ<98kt6}QE>lMy+*CkXtbJIO`WD*qtoa$22F#eQPZSp*0g9^HEo)9O^2pa)1~Rw z^k{lDeVTsFfM!rLq#4$XXht<-nsJR$W73#46PiiQl*Xc&)>t(*ja}o=I5jSfTjSAq zH9n1B6VS|Pf|`&ftchr5HFKJI&4Ol8v!q$ptY}s>QB6z}*CaG+nsrT5lhSNxHZ^-| z@snGDA1+I4q*AF&Dwis_|3!dQE!9Z1(pqVqv|g%{>ZJy0gS1iFByEESe(8X8P&yX166 zE~#7Uk$R;*sb3n9&PapOkTfifNN1&U(s}8EbWyq_U6!s$SEW&DOd6Laq-)Z3X;PY! zZb&z!TheW5TAGn&r8#L{x+DF`q4KlBS+6pv8dQy{CRMYlMb)ZmQ?;u)RGq3WRkx}~ z)vM}L^{WO{gQ_9buxdm#sv1*`tBfj>YUXF;+jYItplnb!Dw~we$`)m-vQ62p>`-

gqigATeVN#g! z?=H0~Iut&IUlC9=D_Rt-3Y)^Na44J#mqM(NC~6ckg+`%O)GF!}^$MLruP`VY6padn zLa9(G)QT=ew_;8)uUJqlDng2|BBJO~^eXxk{fYs_pkhcdtQb*@Dkc<@iYbLfF|DvF zJPNNOB3V_)6+uN@5t4K&qKYQ+dsJ2KSUFgMNAFfM|O{hvyH7)RFx#T3X{*GiJVb zKvbU-TjAddCTrY^WkEZAK$M;+QsrU2C(xd4138Lq8Ync8;7Va8GqGiq%@tRLz0mjp zk;zt^2`zK|h_800I0t{L*;p9W+Y8SP2k3`5_6BNJ;osg|Iv`RkZ!UFY4~Ui)On}n? z(fkzm*%#nGwX@u($+ZSj&P+%%hI#mxsWaSMS7y{?j@vO`ZiZ_T(41=);LSJ1>@*tb zkp;2{1IttoNG6T)G~81e?GJ=EebEhHTd*)c0s1wi3VpA&$srYRE$*BL8J98ItHxfe z@w$L^8EI79v7VN#&cNLA!pfAzx8ybDi)-(+=k)SBLY@PnX25p_d}aX98w`lSMtob1 zalIOAOKftRpBr6njcM0pYZG7vu61HxNY5>=I{f`5=f6Qb@er1CQJRov_9N>cx zhr@w*CbVZ1CPSM*lLMa`1QgcLS+g(`FN+#Ij%Wvx&jT9vfu9Uu+hyD_?6<8*26;XX zn#;lS#!X6~^}-*8w*_#UpIlFPVCVG0fHScfSmdOv+~j2vEZ}j?xWY6>@CIuLY$-#h zbNuQ6p9vI=LheyGdGDs%oQzKbl7X#K8Y_x8Zf*;sz^^N@{@W#d#WNv4PqE)~e4`or z?E%s1LJT}E0XX%PXh~|a4HqgG%BFMw6 z7C-}Aym4`01uDsMF0;AOnXu(Mf&-v$`&9c@(q+cBsw1(%^MO1f$nFaWxjf{wy6Je# zX`fw|Y_FJmocb(Bzly7m!M8e3Dqs=$Hg1pJ-LD=Ww!qS%(j zHDPZk*H7$e2l~;}@?vs>qX?jU8n<$ND_{rt&EFEYEr4Hvhj1;6G|H2>13L+1-Uf+_ zZEH)5ld5PpK7rpK$Gj#sxtVOBW2(izM)2q6lt8gf zB2)o7O?V2s=Yu?#!c!JqCp*()RE6fpxbkD}S&ytyn8{9yCzTN0&8Z#a zfpwASLSH_Nq-wx8%=+Vrwao;=Y6CI{AO-6-kV_7KdIWV~5+rd4g=ab3wpAm_UOnSF z(0>WE=UWt_ZIWQTT_MNtl#t`dstatPAQ)+u4aj3T%EV-sKr_e}a2wpKc}wsDtch=0 zmQ=~$)HGN+BCriuA`JJ(%@nHtU`xT8eW7PVGFfk~!Mf?pJ8Lyl^`RQDpM1PyYk7S% zU?q8L4BcGI zz)K;>IpIiWR*GV$o#YD0f2OZ+l1#@zk>-^-?RU7Bh*k5C-DA-B2866FL+%_Wti@{Y>0!z6wxuNP@Ufs z+@>4uDQl%%>OUH$TWaMJl`;X~yqP3gTr8 zS5@#a#Q%InwyK0w8Sbk>_(fS=OXxzbJY>i)casIK%Q2^0yAwim@f6zo=L zD~pSB186-ET}P*I^IOCwJYDJ2Hle{cg8{I;9$CkLY@4)B1D9SL5q^}7lCd?QZrl~| zr99!y2Ycc)LL>!#YK1#hp;kBg|`i%&u41RxWg7GbfFu9)Hwu|rO@mX^A5h>Rgz!K zfh5WcL39pJQ+Tefc4t>W*KL8n(2TtI%bCCK_pBo)tpO@Q7y;+LALpPnNgEt_gw)91F4w+#C&Ks|%JKq=U_0d|}q zciJTK8|~KMN+_xcju6xvrh7nUu9=8$_TU>A+%o3o{AR&@CRHLOw`&7MOLTD>o-U#- zuSelIkF2f6)(qlYR7%5*+;CD2iX1=s~ zL1nBjtKRT^HRz@S*;l~RjhqsIU{d#pJ9E0DWvOPP=f{CGArg1pd+QLuw& zHEktx$wd7`)7o@=ba4&pKHqG{?%;N0Y1sf0@hugE+dR}(8M2N#Gca!mX~uzbq(e|& z9N~3{14qoTygB7wHF}ifj#7ht+6x*^r0q)<Yued4~MEwC#TV!ZOm1;JpL6cffWZFVB_8Bvf>HTP|0`xl~?MP=2 zAj!2Ygk+)LfMn+S8(=j#WRRv!FUcd^yd6os47IqXOx_vr?<;RxQ#R~Bd+kw|-A}#X zKiQCk%mzWi9+>Ne`0DnUq1Wap@am1jHz5Swz4({Ux0T>IQl_0A_!rxPZxJKqfT-96 zNeayaez9I5!{o`02)-M$Z=X^3Fzeo*2Xm z*V^pwY$s#~zl)%ogcfO^p39ssM`rDAXr6P%0r43tL{`$u`I)+F)@tf?_BHsE!hU zZ3Y>&c`L*K*ZO8xKn5+5U^rLYUFg+f6om8b5DPP2t91m)FI*A!C&v4>8&T$L^tELs z!Lu52%gZav8RXvu%2_1g0`lE4B4d>F;OEbffBKNL(~zg6*vrQS6x&uM&bKWPGd8Rl zFNuFPHlsCm3bOwy)FG}J1w4Av^^ReI&#RF~s=&+O#*Xtw%i1>1g>Lr@*m!h%7_IXs zanE@H4;UfK4b9t;OmX9k09^&j5DS<$w|9)7ISsMY1%E=5y$KK88J+$FWHGQ4zCWr; ze88FMgVo-W8U_D{ZX6AB2w`q_E%=>I;ECKE-(=uzb+BIVf$xjTEUvH`fd3$PW-UIy zuuF_&f^YZdVt{TcncVJ6)CY7(i(s-Ize{qowO*(c=mxAr=ezvwMF+N17`$@^<-cHV z)LD!DKR#nMrD3Je61EYqom9^hXg_6lmqhzW&fyE@c&C&2 z1ypB;1L4rMRfpvaK{Ray8^EU>#2aNMp3~mX&DBu28|Ca$no;DV35cXkgiHcQNe{-m zhny11>7tf=2hw>m?OExA2ydNUgPqpMya44={^g@6{{Ak5WKk!kO6(B^X%txhxlkI% z-{wLT#c*S;AKAgTt2Sq@rsR~7^LT_Qy57sjw?8XqHs=3WzgTOy_NZw9B+{Kp@I4kvf8n@S1iu?x1 zInJdu+>Zm&!saA4;b+IunUF!i`yqDWghHDGl!uIs=&UY?+A)NjcSR3bV!+hBWyJdm z)G0u|#m)7tNgLt>l@~IF1^&Q_OFz+%Bx%eJqZ2k!URr=0IEA(0=xnBXaz1>|pQ=Z> zcwoaN$jKbt5{`-_Wb>@O1NnItTPvAg&&$!N9A&YMp*>cxpAszG=dr`*ERq<0u7Gb^ z5$w60kOjDwAm|N3>~L*rT$5Q@*FKaIYy<0W1r4(~?6b4j6E(zhyFl(Wq6N>V6=&35uxTciLJ=4No%_o? zdC^|yZ4R{vvPw^IAiE4mN+5&Eag1?X7m2@akRE^9-p_GllQ6~>IHK_i`b;Aau8-vK zYL4jCX<9C^@9f+fik=Y6Zl&9hZZ3h$mCjeCi?eP_+lBQRc5!Qw*$I>}xV{@n#Pt^3 zZPNqDB6FT8$QEvk3nD6D)TXj9TG~u5Y9|v3s28bGZ}Egmz1|61WYV$$9=r|~T|w4{ ztO)&LlSe$@F|u{R4D=^RoEPS^*jtNKZ{JhFxm+6)@GkCh#m6Amwz`ryE{ZE$uL*gp z6rq;1jN+^e?-g%@Ik$Jo=Oon`syUAKRjfVCASwvKB`3(0{s;T+O;9`X?1 z#xT|yKqi2AO_4ljwQnTrkiU$AXC%#&8_BtTu+Wt@3yz*O$WwCSsr+t_TO;7L0P)DR z-nk}0b{s6T7r$3!8qV{5Ko$6_=i0Hp#reH^Gk}Q&yspq%VU$|T6JLkz$u*t?oAW7+7krHsL5=F>ck( zY>;;`ZnX(}kDZ_a6*iS4SV6vm47##42C{X6j?;pb0{14t&Su1W($NmSIfgJ(qkKD% zaNxXa1;6ORJF?)5K|vLRDr4P3IkDYtPKL-z3i}FoUM+A|3p{2OTV@kZUcj=M_Ow^|OYoP4+sy0BBOqf6<)M17TVRQHG?ylFCTA8V`a!x{ z6mcBy^n$V^2ZRAzuC0$tkzWtmcnRQ5#newE?Euc6xC=Z-;g<{iwij!lbBqJu44k|} z>aGswkyZbqzg z!7F;4U6uqG_65BNnI#nc1}CpqepiNALK5%5d~{U>+*Rv?XiqpC$F~{_szq+W9mlgc z;2HD`fi4-ryAk-6SqCy1yn|V&Pawa{y^uBfZNR&EzAoqyWRrqCO}_1*o^VKjxBFbf zByYAs#^{aorW5F7FUUEIFad79B|**_O7ulcIWw`l5im7jznK)!@fdiawzxA;Kh`$# zX>38br!BPPW^+T?g-9F3|2B$=S}BxkN#0<#0etK6LF zdpB4xOOW8#_~$x8V*|;vy%M81E?|WyT1Hj@JyAs0?UHsH)xt)Cx8K>GQN+4{%LdYQk@yz8PXKl`76+-@ zMJf2+b{Z;^H*K^5r4OX)hWL--EEk*RsOCfIvaA;cy}f`~1CGfpi!R7fhJl9@q)($r z^n>Rdv zpT=nNv;4CjonS>+){pC^+X4Ru=RhQ%^pLxe7xe-V3s=%2;Vi1UTQlP%6BYL@PIxg| z{9FgJI5%1oWSzolOJ*4I3A}%pl!#}>m`>+SJK*<)HYJGo7@%ginZX}gb5kXr##8V2 zH1D#{beXl`jSx_BW1kLyRm+;an~hZM98(l&`Gjz(-V2y(_ax_xl-8-g1HH?~KnQ2fFU{N!f$Zwj38ic}hsFN<@9 zo)K>LYZW;U?b=h5_6AqL0&8%0SawVBE(>72ZP{KtvdSbJJYTpCM zX)~6M22!!gCE9=7E%4=u^~N%vhxaD%g&466$E#6rQX}yTv?B1tZm`%Ak-s2=ZqmIq zkE)7WV5|M*E3B%4eiTsJzbOC3+a}7{ z#hLQnltVbPY>$;-CtTaFZ_Mzk;$8OAgO&Lf1!-0U8X53fr+|j14d-jYPrbWpIls<5 zb%My@#tN_++%WSEC02&}VSa*0r~`jcK$PhBMMeTSq&Zi+9*Wl`hkYwJ`vgf&D@dUv zw}ef59`W;Idsy&}<=IK77Ck5`=fg_kZH4{(rvvJ>MSx4XOfQ~}f9f3ubk1Uso6&%$ z`B09n2ag><{+@$)8o=0Xt{8}}s~}ew{Fy;DsnyoK5{Jx^@UQvTQHJTpa`PvZKZmmo zgjf06{^LAIRBRf^3`3BcRx8xTA{D&%Ad3oT%KIvWX=k8GkP{OSO=0-U9gTa)x(4fd zgdN9C2B=M^xn3UesF`2O>Wp<|Rer$?C?oqj5mhhPG=k$;jI(SPiglI6gs|L+!2co` zb~G<%(x!PAzEzFjEMo+ur`<;DmP_T?Mj0#+s9#r+99XVrVLXcP>LXb8A-TD=q(8F^ zw%zOq^_XobGx+ahP6GMRNA&DS*+EVN*}?5v2Z~KVV+Q-}I`sMG+m3B5f?s8(xtUIs z89XSCmOaCsKIGHQ0@V3^`#neIv?SwBiWtBhnvLAn{>szUZH zaMYt%tFtXg2l7}&yR>I}t$+*;34J~sg~aPJ45C!x1SZh3{hSMr%el{Je# zXG<)~?~cT|UTm^^(-7RrX>c56Feambq_ZR&)!4QZO1!#&@>&nBU;Fx^VoPAqLxW{jm*{z2Lnu9yUtB3xa{XXLz=o%l@b2%kO}Yhp4$ z`JK0QVrMtbMdJi>$cyFcRb6@cs6?obhx=mWke_-RgjYHNAuKL2(bL%TGa)lkJ3R@fvL5|ZjAT)|Rp6AOw z`>bY=cnhpl-lk!<%Qog)LvhrBJW7UTG!w*n*7Sf&2HVVtaI=FKS8BHOIP$bnk~KN1 z#atI~-2vox1UmK;zix(JttqoG1*O?G#3KasH7H|2!~#Mw>>W*r&opRgPq#1FSGMd6@otoX z;5RmKPF-@uN)YHEk`~T2qDbLoXejdm% zOW+&A){OmOB&sFVxv=g>9>(<*fEw2_DF4ITILao4IbXgZI)-H{%q$|0?kSPdn~4}z zAgLV7(dH}A_O6Xa2TCHKFkk$vMfgoXrR18JWK^Cal~rKWHo?MHEFr&I=@}q;6;=({ zo-0_U!fZ1>5#FznKLiE2u9U0EYsQ&w6!}XOi>l!u^t!nvyErpX(rzrdbSE ztW$A_;TjT4YoP!BtrKjq47r1E-Jr`l8aE;@sRMLctR{ii7btx&(-e(Bq-o(aKRR(q zkg2=C2U{n-OInnJcnXt4iM4wK_9I5%hyX0&KaL|wQ{J7_+M-D#Gke-Gc z)L_Yq5m|b}T%gwFl@Nt}C{Hhi$9;{fy@<0itDNE}R?B4L=3-!%Y_PC@IUYdtgD`Fb zT*vKUXFZ_PS|J|H!~%uAp3TA&ep4sz3FpvgDq9QK%z|`vmZ)z6cBB(c6FHQ%vQEd; zhJOtrFAua^Br2A(zNJ2pX?G)NQu^Qd}j`!+`;Lv46+njKaR;}@PS@9V+VV| zG~|cv?JOV**|5w?EoEcKnHBVE_i=k0$(j6#{BsL=82AO^wh107ops=hJdZQ00-g&q zeGol^s7@MvL%3en#N{hB#wA=`vlc1D)QTXk_)`kcMr;v?d8FSwoGAlplQl}bxg9KE zU!U8ElN{3so&k2SPvYzwA^sIwYhL9~*vUE}3iV(qy^)_Yz^K>^#(t!0DAj~G4utwa zqpgyhRisv8-T9eu!WH64P^$ym>hu<%)`GBawK|ZM-L|1v0^8dFtMD7OV25ptH8*Y{ zl8?h(rgzhiw2RonU@052H-GXR_DOy$d=7xla)^gM6r+WeO+WC%{^P^9f8m}&-?+!h zAYj5b-J&kFoQ#2OIzR?J_H2H2@29#%;w=3&a=^!s4%{qur zr4HjtHz=Pyu4SW~rowA9&KCfTE&j(f2XtYDL7TXHMS|6gfLX^Gpra@k`d!LQm zlU2xv{Yz#f$pqMC0OH(4EMM5Wiuss`hvkAw(9#->gJqrIMcd+1NNwYsS-;f`D^863ZrO!1F5sEQ`-<~3nPR`Z7oY40nWiB>TKG3i z$YqsVa34Oa0*e|zi!NmI39K*NmT`Wn#94)Cxs`siXOEkX8>7WhsR`F|Zrvri*P=Yi z)2xJZ$QEgYq=%eYSa+tx5XJCw;YptU%AT#*a|YatBvV2~jBG=M=&{Tlm}jjuw780H z43OP}`|*#En@VM>E%3{?Z-({Fq!+~^N4q14@R@C>@LO-kK_$?Lr}YT(C_l$P%7bqfEC=DB(7~tD+XpoWt=V1|MkJ7i*4Qo2$(! zi0`zbx&XDAWTS+m9z}%=a?ct><2z|e%y$;)-zd<{C5Y*D0awMII4a9lADC;a6gS&ph#6 z8_H~H@U=p#gDg|IwUQHOAV!@P{Epiv&c)&`u;+|Gg3A2(S^r!%&-KTGg_$vw0n`xt zCP6I?Vt%eENv_-05MCe}6n1s`ny2jonq{8Ho#N4VHdAl2VNgU!pEsz27JlatU==QGRG95u?88|iGAXIR4UnDU z_ZOdiNe#@-B3U})Vv-$-6kKlx5OQKkyTCW+OlwhYKD-9sW zoM2sBAeQwAa)OYO@5kWYGbFh0aq~+MX92h^fhRytmk1=)3VgFZ(dFQ|ls+|O{EDm1 zX|BHkdW=me;;W#=vez`RxM7EL%%I5**1Wg_bgh6Tx4sjEH{FsOy1y)YNh{=XGrnOd z!8f?pi1g%oE>9a|4He?3LvjovG~u3(Yiwah@l%C)*wG#*vJ>P!!m&Wv6?Y(CO+ofo z$J-#jmWXwDUT&N(`LXahjM3~N)?X~kCqnAC>n|f8FQ@9SfICN14>ke66Znu5>Eeox z>}lg7Z&#|pQHwpM+g_Y6^aj>u%8)9jD2!LIm$_4=>+>i-@pCQvR3nZiEAZS&LBFuS z2Kl%fc(@XS*s6sUmq1S&#Nax%a$(hrwDQ>plTLDThdNJk*jfp%!XEC^4pCRBxe(sP zl_|eF(IDUq-!1LJu}CfKDNqK~LhQ7IR}X^Z4RagW&{8np2^N%iYCu=QR_$Wz(FnZnE*=;MH!@C>R|@Y|V4F2~k#pb??ejqq*~aO|4oc~yF@ z$6K(i76p3>lsOzJLGZs}(6zj^hBY7w*P4tL@Slm)7K)-_@XHR18Zz2=)auL#vL{D7 zgleD3k|X#E`Q|~NImnUYL2fp`t^fir#Uj;sOdTP@f%f-S)Bh(T?F?7a~Lx$=UXq7_8t&_)n>#2jS4 z0Ma+%uBlir(}3^bx)Ev3pTIq(h`No$Q(;XXS;;BEznhWGyn@pU>+J|D6^eku%mA`X zq0fK1k>6@?gbtw_#u7*{glKzhJy#fMJiqD_ZX;mj9QbeVu4vkgjs)M^T2YL{ebePY zw}ai3yJysE7PM;wynF?`YX{|l5JW^0;%-6UgTlQ#sDgG{AaB9h&5$u#!OQtJDDanV z982v2&vW5SVhW~l-19pj0`kTFqSJ+P5!~6Zueam48X;BQybAdO{`BB;6tLo$Srl;L z`GsQ2%{+=7eg?A3HhjB6V%50|wHU%?68LjXwq%D>hCsXaXcy=XcVeVT2VU3X{15jM z6GWjqS2041rx$zOh+ARYiMZ7Y-h$v;aj?ZQ@Z{PcWHRsztZyDa3v0zsF~npS+-_8x zg*mCfK1C{FPwE)nfO-}h#!?UA_YaO{DYfdb5?ghx`ob##A7qOjn456+2&CsZYJgXv zo;Tw9D*;?w-8rO%pBkZ80+vc7z2 z9bv`OCZlejnIPraY9qEPP}G5DUgB3Hf~e;?06rj5y{iVrYaF4QLqtQQ($vA+IsLRPXPrdguO8iGilL1}k%W|E6JOF3~#%J;UG!G|e zi4_2?iuW9jYXtIzF**x4aLo!aQEUzVRTN8YVDlEtnOmJOx=}Boi`K57KcWex~8(~d>?N{W!yVte619A^;)q>Tpu&HAiNgW*4-Q4rtx9Sd#ps;B0bmBV4Bid;iwa7WWzi>a1ZQ6 zxgnYhuI@m5jx4Fs{fpm|5M&O(3H+mOLyd6cD6*hi&#DU${Li&Hoc#un#!!1J;KZM> zB9_Mt{?+ZXXPJN;{@m#@V(FWfJ)PCC4;awHbL4 zPb)!dF@fiA3;H}&;b{WQjd-^-H*U5$Ye0`6@%1sRyI+9(&W08v#PP5|)FfO3+fMTK zPtHuvWgebSwtxdR<=N2e+?i zE9fo5IM+h0fp3OElWjnI1lgV6J06OFr30ic^7F-~2~cqZr(r8(ZUKh%giiuT1XL8k zt+SbAha#_aqTTvr+g1`;$cWzHiZuK8{HR{Fq0b^^7IbI>TY#20CluC#!6Hqu*9(!{ znb*(6iLcZI+e*B@K&wv__du+gg(I*oKB?E9h-3t(&I&Mq?_=!#k~rD4wP0Ug@b(Zi zN;$(>D1K7#&$ty9AWAfub0P&mg!GCnsR1Pr7^lTu0iVD)jhT@F^z&s5P1 zoe=wP*J@Fw(Y&okxl8ORsc>H4$Ml-bJ?vl!a*Eb-@+i>mJtoVV%P&Y ze!bFj2x$^oi&fBwr#F%O<|f&!kK7JcK^nfT2bwRSO$ztULd%vQ;hFNnouGSJkE~drXhA-=0QQ z4F!wy?MAL|5!}>@Yj4-{f&B`tkLU$)PQ0tIrrOi9r67k2!9ZrMs@a-Y|;hG6DnkUo)mK`!pt#&}nCXpU$67>bTQIty~u`U$ng*m9YC}$N$=CWvz zm(}zv@r~(xA4pi*yrAtEpfpJ`QgJ;hh(raFu47(|t=NXv0^rqr3nQQDtDv`1z`Gyp z;!0W(V(w&N?=XJyoT|?&MZgQOB5Yb14-oq=fGzsL;xh0x`>uQ11o89n5}SEQt>-z< zWFz>EhMy5Wv)hw|Q(<0LmJ=5s+m9hX7VazW*Kcn^erfjC$F_-9tpP;b1 z5#--1LH<0rFQQE1#o4|%|FhGZ1I#uEN>-EyIq8fjo77LWA#4VA<&&ZYdg2AckPr86 zA(XRA*R_CMp}7eceujIllN zl1=bE?&-o-uP^ZhAw{MB7|H1q)_&y2m8jrkEJ69I7-3$RH9(y!G>KrApDR2YfTj^4 zlrrjUhGdH%OP5k|qg4UI3o*k!@(K4wVOLU6g^Fuofo&#G#6 zDxS5Q!*B(arR_WP^v&CX80MuIu`z+jFp`C2 z+gc9wP3R#%=<{8GXf2Ap1-NTZK(-HW#WzNf9~x|N;IasGlQAdCQ}SS+!xxGqX4lqy z3hXbrbmaE>D7-?L z7H}CRKE==1`QA_Uj^>GaAZ0Mcj_tQipau8`Iqgx^&{oJYVr>hXKQ z0_3kNZ*wSDDli*&U3=8Zd z+#4wK^BEX7;~cgb9=GP=gBCr=Is{%C0DlM}d|Ht-7IWJ>^f~yR0gzHU6p*``O6)OO zlA{{0D5JC?+w$6MlxXaS=&9K!uZ##P3ddm_Vk&|2K(GuG@Ct}?u35+#!R#EWItg6w zcquABS4pnfy}p9c-o0W(ah^bu){{HeZaRKOypJ_DQ2pa6_kK$E#LR(gUf5}<5Q!F) zo5bkuu$#YSPrkYFJigZycTJSlw&Kc__eKGY_I(h!a!yss|0)RVpzkq+(#qjR4DXZz z-!((_oW^lH0U5-VcBg~mx#Tt>%Z=~Yzc^`s`o?FEV?dB-X4kSw@M@)^Gp zLbHPvVlkdhP0kBqr;|j$P^#t%>H~kmyY=iM_sn4w*FwHxTz?$6&i5f?gcS2Q-?hy~ zArIFH&-io$J3c4=(e#r+Y1(MNr+3b@+RIn9yY?x$&wq) z43eOry%AU0MuM3+I*n|uT5g|}B&Xp-BOo%r))(zuw3M8&kT9W}gBs{V8yELSv;@8a|mb`(ETNkw46YF zAKVE?cG+eVRe#}rEzo(e)`fW~_SRNnu?$4Y7LJF(5?XG@D#2=pNDc3Auv?AZL^?gW zk~cCNMt`oP@+whG&7(PE3B6ESzTXD*+zJw<1s=e!l|HSLrQ>B(t86gag`=Q!eZSEN z(R2n|jHmYQLb}DquU*M=4*B3Td5@7|{{5LyHky$n*5D3Nli31an1DYUaIaXww2KSQ z#chufpSHO*w97twoxg<{Mukb%_a;n6Fw=cr|@f@gJKfsbyY+RdGm7UZe$hLvO>UWz4T^&Q}8LR#|k z@Kf`AvCs83!Lz22PDxWY_QE>A0N%@xhT~Y)?%diw8kh2X_eV=_Q!$#bRo>ajQ{k;t zVTWx`{xzsB3;D`Wju6hgJADiB<#K)!l#wGP8BbnT%L;qM5aosDnOMony#enWj(>ih zdj`o~wO}<^c5@T%DD8W%xLTF&D~yIw68qQh94`)_kH}#pun2^9QW*oyiq5} zK*BYyzqKbe<&^*Z#*1(x?uFW5F3Y1F5=o!V4c`k3YWLpwbnfBP!X1MoE`_tJuygJT zcEjxhS4rXSz4{${cyt#!$!FdI&33mLTqU`ciRkY2pWMupK%N?ssmyN^J#~BLb)lpa z6>KY9uiURkRkE;V%|};!|Ea79l^JW*{8Oy6l{MXO){nJb!j_Oiy^LHD5=P4`rdt^DeJ&jkCoeDc@kZt?P9cl;PzYD9AKUO3PWvTY72viZMB2Y!3 zia-^CDgspmst8mOs3K5Bpo%~hfhq!31gZ#B5vU?iMWBj66@e-OKN$qXI*INx)Mu$0 z-RG#!Q&OEwC)X)-U!cB7T}6F~`ZA@|sdQ?cMyJ))>gsg$y01_=onB|qHRu|3U!|_5 znsi^I4pP@p&AMx;L)2mF2z8V?MqNj>=vsBxQ*F9-U5D-l>PG4&>LhiFx|QnGb?I)S zZl}6+r>Qg49aN9*PUK>r_bQh=xsfVbCsYj?sseavK z6h+b0fR3S9>LN9$dy0CRdWL$IxHzOGRmTx)>(Bn zot#ooO3JQNQEEyv z?bM8}gX*M$x{$7m>ZW?AUaF7krv|97E}|QxW_5GAdEF2-OpQ0J3TGWkGM#@Aj z>CDswHAyY&rYH+FO<5@$Wv3jJlUmWas8yYt@=#vNNBOA$HA4lds4k`pQDG{si%_#v zLbs-yqtGSk`^!@Y$^aZ*>{~-Mk{V?6Ae}sON zevEF?Q#4I8G)rHkpQ4|ppP`%e&(baWOZ0Q}^Yjb!cj)iZm+2SjR(+fPCHiH$UH?7$ z6}m&;sqfNv>tCf`qhF`rpnLSa`ab=ebie-l^niX){}%lN`iJz7=zph&^uu~FEulyB zHMEqL(W81ft)P{(idNGaT1(f`b#y(gqsR2)dOdBR8|X&5iEgHi`WCvCZll}j4!V=> zqPyuHx|i;w`{@CCkRGCk=@ELAHtEOcaoR|mXfr)QPtsGgSwEq-(9`s!-b&kOJ3Xa$ z&`#P#yJ-*YrG2zTKdtxER(*h;p@VdY4$~2OmY$<+`gwYRUZm~%C3=}&p&j~FI!edr zIGv!^=yf_tr|1oOlis4Y=`@|8vviKm(>t_N@6vyU`7Gnse~$S)K|erX6E$s`bU@r z{iDod48_n4!z}8T^enTizsRiUSM^UZPczRjQT?+_Odr=L^p}`5{d3Io%nQuA{yR)k z|6S%X^CI&S^D>jtZ|J|rZ0fi4+xl0SSDDwCwElJG4JM<{>fdC(&*b!PF+X5_$mI1u zV*Z^GGZLnTkuox7M=v(W8Hu6BAT=l$C8J{0jE2!NGK1Vu%hWOTjE>PW21a3MU>cbw zrkQDBTA4Pco#|jYnJ%WA>0x@AKBk`;U`AGlgt!jVWt@? zV`J=$gK;u0#?5#bFXLnUOn{kTf=q}}8dL_gA|N|x_HOnZdk=drd!D_Iy`O!6y}&-m zKEyuEKEgiAKE_fk%`z;@USywQpJtz7dknpXXW2_^pW!*S-|##;V0eN34*Om9GW#O? z68kbcXc#hlj~zC=!j2e54P%B^+1J?D**Dm6gVFFN`+fE;_6O__*&nec!@sj)R>Ib> zQdY*wSp}9b=~r?w;{VUEU2Rph0002|HoFxAj5ia( zAZ*`^-Q69hySvj)L@`iQq`^QeL|ymJf6N}B6PQSL0egXcz<%HWa1b~I90ra6M}cF& zWO6Fm4IBr0fL`DPa1xkK&LmF(r-9jIAJ7jB0CUMf;0$mUI0u{uE&vyS`Q$?K5^x## zn7jg91+D?t0RR922>6tQ0R%vS&q)lx0Rs4vBmoMb0R~_J4&Z^s(FAOR$S6p#ioKo-aWd7uD% zOMXulffDc|Sq6S4E5NU06KpJK_yPO`egVrsFcnIL zQ@?>oY6bWML{qU;Je5fO1^xl6z}4UyFqulF)`IC&CY4R)Qu)+6u#j307E`5EIkf@Y z2v$;?z|G(mu$tNmZUeW2JHQTbC%6l&rRu5OU?bH`wNiV)POuBy3+@B=gYDFf)B*4y zcr$efJPaNIZ>5fc$G~pzIM@UBf+xV+sgvL-@HE&5-bwX?1K=Qd20RO%1J8pOz>DA| z@G^J>yb4|euY&*xf)EIU2#A6hh=T-3f)q%D49J2U$b$kXf)aQ)buT4@_frp23aEk_ z_%Nk|k5Z3Q255p7XoEwkCn*OwoO+simU4nF&<%P(FF2BVo_dk;fqw91DgXw-5cnz; z1|wh;jDc}50VcuG)az6Ve3KeWy-lUT444ITU>+=h?^5qmMX&^pr^;Xjtb!j>HLwmg zz$VxN+u#jwA~l)13El#yQq!s1;2m%#br-w`-Unw>55R}uBXBPD7#sqhfWzQZ@EJG) zJ_lcbFTq#fDEJzD1CD`j!FS+$a2)&qPJol(6gZz+NKJz?;K$S~I0w#ypHd6p=hR2= z6ZjeY0xp7IQj4jt;Mdd=xRm+^eg}VmKf!OQ@2MZDU*IzM8~mAC0snx1!C$F=;3{Y} zv<6xWt%KG>8=#HQCTKIXoZ13yg|NaItFz^$Dtmm7dio*gib-Hp+2Y|8h{3&GtlqUS?C;e9$HCVfG$Fppg*b0&=u$^ zbPc)=0T2lNP5nzjkRuI42!uiyghK>GLKNgoyV5koK<+dPaS#uA(gGwx5+p+kq(T~` zL*BFj`O+rjPg{@;IUpzGg4|Fb9ZY*5FBD4qAU_mNN74Z(2!)_96oH~p42q^>={OWm zC!j<+38kPkl!3BP4oar;Pys4JC8!Klpej^@>QDn}LM^Bb-GFXFx1ih59q2BUO5cO- zLl2;b&?D$EGz6v7PoQDwDfA2)fu2JzpqJ1qXcT%4y@AG{x6nK2Jv0t|fF__xXbPH! zW}sPU4w{D+piKHB^a=V5Wz%1vMd&M(OD{p+pzqKR=qL0GT88rJLi#tf0{wyhLjRyu z@M?GsycS*u7t^KmdUyl85#9uEhPS}w^j3HqydB;FcfdR0U2r8`P49;Hz@2a{-39N3 z_rd$&1Moq(o^GTM!H3~y`Urd!J_fha?evXwH+&rKfqUT-@XhqC^hx-3`V@R8eK&m? z?t}Z`d+7oAetHl-1D}N-q|d?U;S2D?^hNj*d>Ot1Uxly1*I@t#VF-p{1V&*D#$f^` zVG5?-*Gzasr06$5K@Nim!Wmth#Sc9LYpQUwpByGUY(8G~Q#uK!;53|pvv3a1!=KY%(gk=i{WZOmF2W_a3|HVPT!X)*>u>{Z z!Y#NB-+*tzx8U3G9r!MM555mSfFHt-;K%R~`~)6`pTf`J5%@X$0)7dMq=HnD8<`qXM;b^IX(4Uo267X*h1^E&Aa{{_$bIAi z@(_81JVu6)o0%ubF!B_6hKwN3kr&9V%uD1IGK$>Jyhh$2W5}J%TjU+`9vMeIAQQ+W zayN4?GlksGOd~VMEHa18BMZn!rovrh=rH;eeTI&p^O=RrbM#~81^OxT5`Be^ zqOZ|6=otDr^A>%FzDLK=59kCsiB6%@=nOiG&Y|<@0{RjCgnmZ9po{2NbP4^2en)?x zKha<4GWsR6nE8#apkFh8(7)(X=3C|;x(Zv3t-;n}>#+6M_soyX2JC0%S7tf$JF^kn zgl)#QU|X@3%%99QY&-ThvjgkEc4GfByRhBZ9;_4V!uDeOFh|yz-H*Al?yM(!06T~s z!VY6cFmKkE^=FS_$FM-Q8#|8mV8LuJb^<$zox)CIeONyh%7(K8SR@?(E*yN&@Eh(Q>PAsC8b7>*GbiBTAhF&K++7>@~_+w__6i%tUSn^tG3+h& z4ttM{V;`^yY!aKorm-1p7MsK7v76Zi>?8IG`;2|T7O}6`67~)Ij{U%XV!yCu>^HW8 z{lWfX|FBi~YJ3g87GH<2$2Z^`@lE(_6aKY$;^58;RLBluDL7~YNF%O1yj@Lv1`eiA>0-_M@L`|y5z03XE9;Aim% z*>m`L`~rRvzl2}Lui#hlYxs2>z(E|sVI09x9K&&(z#nEwoWg0G!C9Qcd0fCnT*75s z!Bt$tb=<&B+`?_#fje;*?#4a17x&?Q{82W52k{X8I2*H}PBeZTt>?7r%$!#~@NOlgN z#~1LA`19;1{4@RqU&O!SOZYeZJN^UziT}cv@!$9g{s;ey|HD@itBEzlT4Eisp4dQa zBsLM7i7mudVjHoY*gjXf&&c4Zl z1Vq5ZSQa5r0wZvOAV`8DXo4YFf+KiBAVfkUWI`cSLL+p-AWXs{Y{Ee}2^ZleJcO6< z5q=^-1c|rVci9jTCf;WwM3flMe#pj%IFTTdM2big8Db(knavVY*&LB43Ph185oMx6 zREguI&mb1UJE7?EUU&J!;oA{gk zmv!WvxfS9M;mZ9b{t>H4cWyPghFnXoBiEA~$c>~Y=gn;*eK~(FklRddA-9s-$nE3~ zGMEeHI>?=5IJb-3P3|E($u4p)xsTjW9v}~rhseX^5%MS*$sHr3xo+|}*+ce{C&-iJ zDe^SgNA{BgZtgaDhrCPP%iSaIlMl#;s;ft(>F=N8DPxsT+t+$Zug`Gs60zmiMjNbVc?o%}&Q&;2BSk;~+7a)tau z{w4pBtEkn~8fq=Ij#^J`pf*x3a+|2l)D~(hwT;?N?VviSozyOBH?@cAq`IiR)IMrI zb$~iZ9ik3XN2sIJF{+z7PQA?aP`%U%>LhiFI!*OauX6p=05wRB=FU)OsdLop+02hfz31P~$n0q9~gBkYgy8;wYXH zD3OvVnVQHc)MQSjrg9pkQwC*H7G+b@xtW}Ua#FK77v-ir)LhO>`6xdXpn_D03RCmB zgLzuI z`jWd%-J$MM_o(~S1L`5Qn0rJ$riQ2|)G+mwdPa><#GOX?LhO1-AuP-E0v>K*l- z8mB%`6VxO%MNLyP)GYNix0IWs=BaPF1?nU9iTa-VOnspisjt)$^^N*Y{mA{Geo{Yk zzo=iiW$HJzLj9rsQvays-0$2fdNsY0TSKp<*U^7+>*)>jMtT#ynchNgrT^ys<+jm| z{C3)z-$8fKJLz5YZh8;x%DeNObQkT(@1^(A`)P0f0DX`?L?5P)&`0TGv@h?^chiCV zaXOd}<$LH}I-HN>PtYgnQ}k)NkM5@j=t24neU?5)pQkU-7wJp%W%>$zmA*z_rvVzI zAsVI;8l^EBrwKZmkL5|4qT_j*W@wg9#U19UZC%LnOtK14V2&3u@S(5-xwZs%|0 zZ{}lkoW7M$&`CN)-_ED$44tKObe=BIMfy(uZoWj{%iqsG$Un@N=?Yz?YjmA{lz*IW z&`r8Ux9J=7O?oJQi@r_Yq3_c7==<~o`XT*@eoPP1Pv|H4Vfrckj2@w%(=X_k^ecLl zeoeoj$LP28JNi96PJf^$=t+8to~CE$S$dA1rx)mt^e6f={e@nnztT(eH+ne#H2Y-Qf(w=vt99ZUzali9`WX2$a$@_U$x{A7MA-^p|_dzpRAe&zr(ouA1c zWDYU2`NPZ+<|s3lKgM)3$C)0cmpQ?lWKJ=snLcJdzmWf!?`J;c2be+T40D$GoIl5$ zXD%=onM=%N<_dF_xyD>)00v|r24)ZjWiSS32!>=RhGrOsWjKas1m;VAF)uP-^GkV& zkr{>gmRFhYd5zH-gE1M4`H}ybx0zpg2eX`aGA_o=co;9^V}9rTOn?b8EBO!;W+F_K zi7{~|!6ca!lV&nZmdP=BrojBk|IHVf5>sX>OqHoIb*8~InHJM#ZZJ2QTg+|d4s(~e z$J}QgFb|nW%wuMVdBO}cPnl=T2=knI!MtQ%F{8}C{A=b7GsZXyZ<%+@d&XH9XFf0! z%p^0#OfxggEaNK7G48@V<0&jKADK_gXXXpD$ao81nI+~M<12h;elR~7f8iIi%=~6n zm_N*4<{z_)4HQ7tFZNg%4)36HVOu7vKDKz4%W%KSU2loy{wP* zvjH~9hS)G0VWVt}Z5HBef=#lmLW)hZ8Ma->vN<--7T6+NV$1A}LWQleHw!hk&NkR4 z+hW`74fZB`t8k0G&E8>e7w)q6*!%3A!UOgp`-pwa4zW+zVfJp}Df^7QR~TWRvoF|} z>??MZea*gM$Jn>*JN7+0&VFDg*hzMZon~j)S$2+{XBXIy>?ig!`-NR(zp_j0H}*UG zgZ;_=Vwc(bg$IS->MG3LCiR zg^k>c!X|Dr_p*Kx_mJ0pc0Qaph$erQNa_6}7+y(9;cZs{qUE!{B*SPP6>m0y=9K^vK z!l4|-;T*w{9L3Qb!?7I4@tnYkoW#kT!l|6b>72otoWYA?{Zp%tg56!tX+qTPei2IG5m(T#EZs_*+PG{|Xt-QFIowT#n0g1+K`sitb{G zD|4P=g{yMjqOVxv>Rf|saxJdS-QfJiK=CFQEQX5V;w|nrcZa*n-Q(_akz%y?fP2Wr zijTO*+z=NpKH-MBr`$7cgnQ1t;9hcx;wvs$Ocm3`QSLSOhRYPkxVK!k_>OzejdQu; z2X2C!jgpWH8QnadXo#bWU{S1PV> zf4IL~x%iJ;#jobq@N4;X{Cd7ptQI%$wc* zf0jSTpXV>|7x_#4W&R3(mA}Sc=K&t%ZxkUO<`Ev{F&^g${$}x3k>n}K@m^8oHD2cp-sCOb<{i9~ck%a&Zr;Ot`3FTG@8<)2kPq=;KEg-& z7$4^oe3DP`X+Fbe`5d3;3w)6;@nyckKP)~fR{0wLxLD^K{7~^pak%)j*yLM$o4>)| z=FEBqh+FaM8UC9D?S7T*=u2y2D+#dX4ZVS_MU+$d}kHVa#Xt->~8 zyRbv(5OxZ?gx$i2;vS(>=o0n{`-J_%MDc)dP&gz^77q(YgrmY#@tDvp92a_oUg3mr zQkX8D5>5*<#Xe!S*e?tSgTfi%tZ+`4E6x|s3m1fi;zi+-a9Q|Rydqo`t_jx#KmY|u z_*DE{goQ6fL_h^hzy(4e1xla=MqmX_-~~Yt1xb(vMNkDz&;>&<1xv66hu{=kf?Mzi zUco2$g@6zgLPA(rEPgFUgs8Aoj0tfeA$%()h400bkQOpRR>%oIia(2a;a9OBEEj(l zSBgcUB$S1U@Td5-jc6$SGXtK z7aj-?1%D|}3YH!TkA+ZaNO&R)3*pjJ;h8WZJQrRFFNIe^q!cZU3b9hWlqkIx-UwsD zTj8DXUPzWwrE%edFd<9|Q^K?`Bg_hO!o08`d=x$jpM`Yki?Aqs6_$i=!gt|^@Kg9D zEDOJd72%KYSNJEa5?70B#I@o&alN=f+$e4mH;Y@ut>QLuySPK_5O<2Z#NFZ^u~Y04 z_lo<(OetI1FCGwcrGw%jF<&Z_4vR;`qvA2KTRblIh{aN`ctR|d%B4!_qsECQR5-t)VDN-UWGGe{d zD6t|Z@}eM$q9n?qBC4V$>Y^cOF)60Rw3rdIVouD91+gfW#Ijfst71*8iw&_U-YVTLwZyh~r*uQSDc%zA zmTrr8#Jl1>@xJ&#d??;4-7h^7AB#icgVGamSbQoz6Gz17;tTPm_(~iVUyE4bDrIwhT!`lNnoKpK=DmCi_KrE}7G>4J1ox+Gne zu1Hs36pT?afy&fiIQlEkyvS{^rXZ|yfj=ABvF#2rzKfZBvsNR zT{0w7dRDR|TN)`jq~|547n#UdMph|Po!b#sq{=5 zk)BI0q?ghwX;gYGy^+SGx6(W5y)-U;kS3%_X-b-wW~5nZPMVh%q>s`k>9h1jT9m#@ zOVT&#yYxf)DgBa`rQgzu^rG}f`YZjDR>`a7HS$_{oxEP&Aa9g6$(!XZ@>Y49yj|WQ zcgQ>Cm!)0uZh4Q~DR;?x0L>ZW%+$ckyTlf$4k0w$fj(`w(O9d@`uty$t6#g-11b(BYS0^ z?3V*_P@XQ$ltS`sX|5EOBl3J{q4crzsT7rCa$HWxN%?c>ODQEUmcEvjN@+PGXXS6D zoSc`xmwuEAa#8+SD#>NJBL6B?<(gcV8*)=_$!&SL^t*IJUMc-4{Vm;;Z^^giJMvxm zp8T)mDBqVK$j33_Ay3M|@{~L+&&ad#oIEct$f5E_`IG!v{vwCVi}F`_N&Y5(mw(8S za2PW@~yn6d@p}hmXvSGcjbrjQ~6Q;S^lLgE5FLWl@(>V{JZ=| z`K$a>R;jDiHR@V*rTnM7PW@Y6ul_40^{9GG?N*PgJ*v0jtMsZTRDb29dP+U51}c4O zzdE1}s%O-*>Nz!7Ij>$&FRGW+Q020EMZKzCQ?ILl8m>etpbDwc3alb3s>UjqimQZ5 zs+3Brj2f>bDy*8UaB8Z;tAZ-3k}9i;nyzFjs;a5FYN)1aso9FHI#j3XQr)UY^{Tmw zPxY($Ndnfn$_I5qom8jPX>~@uUAa@aTbWhwRp!+D zm3ehR{iuFYA5=c84=ax@dgYiqRUl^2zlm9^SB?Nw#Hwn5vdjaD{ko3$<4R&ATMUE86(uDq#qXgjsB z%G=5=ZMU{Z>(simz1lu)zji=7s2$P{Ye%%B+A*zLJFfL;z1j)wq;^U>t@UaB+JH8w zy{nwj&T8kh^V$XNqIOBUtXctz86?L)=TOwH0JDz-LRacEA>rMWeaHdUFfcr~9kQ<<&!wSX4XLRwgh zXmgdQ7SrO|d?leJwUo9{NoyG`tL3!3R?v!CNh@m=t*X_uy4KK|T1#tdH?*7DE$y~; zN4u-t)9z~zw1?Uw?XfnbJ<*1>r`j`ZM0>8i&|Yev+81q6`>HKz-?Z=A5ACP+OIy}{Yb)9x?XUK!^11R) zTcv-gtk&1)iE9~fE1UH#`d0l%Wt+ZT-=TNtJM~@q&&sdL zZheowT$tqxvzuTR*P%=)Wty`U(A{eo8;B_v!umN@YMF z)X(T=^>g}p{epf`zocK*ujp6xYx;E^&_Ny2VI9%`R8Sq$ah=dfoziLjZ-voWozwqS zcwNv%-BFcvSyyyb*K}PsbZ6C7HFZn3b%*ZMUAkNM=w98YyQ_XZpa=Dk9@ZmzRFCO# zJ)tM{l%CczdREWrdA*<)^^#uJD|%J0>2O`! zKA}(QQ~I<%qtEJddZaq9FX$ijPx@#5i@vBwt6%jc{hR(>|DpfXf9cEmZ+%7oqyN?a z>8p&@#u{U-vCdd;Y%n$&n~crI7GtZi&Dd_lsymDhW2X_X?lN{8dyGz_%h+q|Gxi$? zjDyA@X}v8uyI* z#slM_@yNJYy;Xf|3>mkpcdB=*PmFuj`_%{4VdJUs%os5qRv%R#SDzb0)hE^A>I>tg z@yd8weO4VcMyk)NuZ=gxi|Uy1)_7;UtiCtKjSt3zF=tIis8 z#=Nm$d^A28Z>#UBpN%iZ`|6_c)mSpdtKW?8#)s+;MC=#I#*q7t})k|^VN0cdUJ!hP~B*5GB=xB%&q1&bGy02{8;TUcbdD*-R2&% z)9f<$n)}TC=BMiC>H+hh`K7v8J!F2ZE>*u(zgG{NN6e$91Wf zFPm4)tL8QHx*4biYoQuohHIb+nXnnDA!f7|tDz=l;wE9nYl&L2ma3&|nHp(QCT(VG zxmvzfs4*sMa%Qo{n}R8trJ7{Qredn5X6mM4mTQ%oX;y2snq}Ii!*rT1(`|apdaY6O znm)5x^P2%PXtrwY+KpPsyjcsI5%X5E}2uc zZ{~ONhdEvQY5p>o&EMvV`N#Zg&eUdW|IE4CDr>&B+FE0+wbohdtqs;f?PG1DwaNNa z+iY#IwpyQSUuuiBZPs>cht*;2w7%AsYP+m&wcXbD+8(RZ>azA)`>g%ekJ``L0qdak zt9HmbY#p(dYe%hPR=0KB>alvQ6V~tAO6{a|%KB6LTRUy_S^d_4HE5l&{?#1yv(`Dw zSwC-Gur6Az`X%eKb;Y`BU9+xRfaR`x>YxQ#u;r~I7HVM@ZV?t~`Re{UWzklk&RDF) zS;0DQ36^L{mTW1OYK7|Ix@JY{x)rS(mT6g*Z8K@B$`K)B!Zw0KN z6|%xs#EM#}db%F7GWEEXttYHpJ!z$^w3V^)^+G*s<*Z^oZxyVfRjQY)vQ@FFR?RBc z>sF;+tv9S%y=m3!je4`*s<-Pm>No4R>Mg5n-LP)gZ(6sk+t!`>9qX=j&$@3tupU~E zth@Ec){u3t{=^!#o?6eW5$n12!g^`luRo~2vPP|k_1D%LYs`97e_S7`zqQ_3@2zp` zNqxBfwEn?*Rv)Q9ufM2ISd-S2^|C%~y{eDaXRKN4b$!lyQy;6ptI>FK>y!1_ z`eMDWkJlHi5A})qWPPgs)mpN?S>LT6)^vTQ{?qzp&DNK#-`0vXSN~)Ewf>u@m_96SQeZ)R$AG3efyY1t4kNvCOYoD-B+ROD*_G!D%?zac* zLHmq-);?#Sw=dWi?MwD$`-*+lzGh#y0sD7-r4HJV{ihDwh>hBR>zMtoj@yJy+LTS( zj)t?r*sca^yBnScXY;mTi?(EY8@`5YE4II(+M2D~freq5wq@J4!*<#(JJ<*{+;+I( zu_Fzy?X&%Mzz*6WJK6}_5j$$f8ZkR=C+v75X{YS8ow2ia&d%G3MzT?`i*~A!Zj|h@ zU9qcn&92*-M#FB}ExT>suy5M8?A!Jo`>uV@zHdLUAKH)X$M%r@#2&Vv+Ry9}`?>wX zerdn5N9}AQ*LZEevGa{F`>p-XE;QcT#m2b(!Je=u?J2v|C^x3ZHfoJ}W7eLt z=j}$L*=RKu?2q;*`?LMUUbNedulADt&Hirxuz%XW>}C5#nAw$53O? zamI1han5nxal!GVG2FQ5xa4@+xa_#%xazp(xb6TPpaXKi4#a^vFbD1+9HfJCJZsPn z#=$x`2k#IZBaP<`(IGirG-QY3P#rHDuNtEb&7nIChv~2!uN!X~wqvZZ%K5gj+PTKL z*168P-nqf~uCdX%$+_9N#ktkF&AHvV!`b27>D=Yq?cC$+bapxSI`=vEI}bSDHx4=v zIS)IJIFCAyIlGU4c-d~S5P_PV|__PO@E4!9N@2VI9;hh0ZpM_tEU-L9{VrN(jBw?>ca zd!yHN!gbPh%5~b+=jwM2xCUKkTxVV9T<2XETo+xJT$f!}TvuJ!T-RNI3v@v)*oC-I z7v{oUgo|`hF51Poel&hISQqE|)!)pZT2KPqyCiiA{s2Of|ecpY+ebIf%ec64*ebs%< zU20x;18&d_xnVcrM%|bjcN1>XO}S||<7VBQn|BLt(Ji@Ux8hdanp<}pZqseKZTBkA zYR?+aTF*L9xmjth_iXS~n;SiwJexhW<`&OZ&o<9?&kj$AXQ!v$Y&3Uyn$1?T-Q4Zj zntd2TfKdk%OGdJcIGdyaUHdX9OzJ;yygo?g!h&q>cI&uLGer{6Q+8T8z2 zp7EUZob#ObT<~1<+-hF(T=rb?T=iV@T=xJT&;xm358^>Rm)q$w@4eqV;63O)gd%Xw7j-= zm2b6gjc=`Qo$p0+y>EkWqwi&NlW((ci|TIH`MQ0_eLcQj-wEGI-znc|U!SkvH{cueo$;OZo%5ad zUGTkWUi4k^UG`n^UG-h_jWypkuloSsyC&#^e6a6*6Y-%w%!m63AL*lfc{-J zpYW4@%1`?lKkMiGynnVS_(i|um;H)g^=p3JZ}?5W<+uH-0;>aS0&4^70_y`C0viLH z0-FO{0$T&y0^0*S0&~rdz|O#~!0y1FKxd#Uus5(Tus?7ha4>Kva5!)zFyA~HI2KrF zb_YH-j|X}Jy@3;flYvu#(}BJ~e_$Xm7&sF+8#os@AGi>>7`PO;9Jms=8n_m?9smMh z01ChXB!C9603IL$WPl2MYJP6g0VeRJ$p*LpA6RS(0Wly2%rFw!~|JRR%{MqB;CSZg2{Zw&^|1kVP~1SIde8`( zK`UqnSA|xG)`ZrEQmu4rU1)tM)7lW)7}^xdwl;^hgtmsZg|>%wggQdGR=%|}RA?1j zrPi*{?$Dl4XQ(T*H&kv_TKhu#L)F%S(8185P_1=1bR={%bS%^zIv(l?)mx2LZ>ZTi z5o)zghE9b}hx$VOp@C4lH5fV*IvcvtIu|-0x)8b;x)iz`x)Qn?x)!<~0zzO23c(>H zbhCwqun-<1LS%>v(V<%{Cd7ug(Cro<5<+4~3dtcQq=vMR9x_5^$O_q^RpHg)HQ_t0 zwc&N)_2CWSjp0qn0vZQgo^WUQVe3(=EBv^% zH$2qZ7v3K}5Iz__6h0h&(mE188a@^tZgq!`hkL?LTfN~E;gjK0;nU&1aDR9pJQzL` zJ{vw4e%3l4z7W0`z7)P3z7oC~z81b72Et$%3d3O}jE1o=9wx$Mmd2bNi`Lr6y2$#-hRDXqrpV^V%hs#bmdI#p zYvgrnTV#7=N2DXNGqNl4rnNh=C(;?|itLT-i|mgah#ZU@iX4s{i5!g_i*!fETE`1FO$jQj5$mvL5q(3qc8H~Jby=$F`oQ=G1or|20T!@UfE=DdzE=R6Ju12m!u17w! zCR#vbvIRz_T2KUzAQ3czMexXUi-?dBDndt?2pi!dd_;(d5h)@^l!zM9B6`G#m=P;7 z)3PJ0qN}58qHCk;qU)oxtqswQ(M{30*5>Gz=+@}A==SK2Xh(EsbXRnDbWgN1+7;a! z-51>-JrF$@Jrq40JrX?{Jr_({sp#owU$j3u5FL!3iGFH* zZk>&OX`PEMw$4W{L@!1!MK4FMM8CGKMz2M$N0(Ya6pTXAZ!I{AMA0Y~#iK-&jDBxX zQ98;*+31fJ7v-ZuRE$bdIr_8ptEEKM=yFSo>QN*5yJbeLs2yDuTOC^yTN_(x{b{X> z{cWv}{cCNAZH#S-ZH{e;ZH;YArCU!PW z@uTr$@oKv}emve2?~R{`pNyZ1pN{v%`{M)g!T6c@+4#Bm`S^wS#rUQ8<@lBO)%dme z^*9g*|F4*E9EqcGERM&CI2o_C>uoAd#~W=X&c>VVR-23SaUm|orMMhd;_dd0wi>_L zzSX|n*5Z2Hh?{XMZpZJm@3vPZRwwSY*Cf^^)+O$@*C#e4HYPSDHYc_uwk965AGWt8 z9<{e89=CTSIubh*yArz-dlEzK&O}#YZ{kUNUt)jaKw`LkFmWhxIB_I#G;u7^op{=Q z);^vXX+LkjX!j&~6DJZU6Q>fV6EE9+iT=buVlZ(gaW-)-aXxV&aWQczaXE1%aW!!* zaXkSf!2gpeoInz20!!ctB0(mo#H;pbn@%u^*KIbzCHTafwvZ4LQbJBB2{oZ5#@cV& zdg5K%NW5>G2`gbIRwY*_*CfZ=AKGh^>yi`g^~nv%jmgROrsU@2mgLstw&eEYj^tFk zBe^rVE4e#4-QJVzOm-#rCif-xCuiCRk_VHAl82K=l1G!rlHJMU$)03y@KG4 zvM<@697ql(&m?EtXOriW=aUzb7n7HgbM4E?E6JRO^BIUJ25kBCuU}rTxPZpGZon~sE?UR>Xy}Q z2H7&i{Wtdk?&5A{PGm$aGa|prU1b)N#-uYDOeXUVzK2;%HuC}IFu6<~^AYAV1xz7R z#1u0nOeymTeuibt7g)}Gg%wOCQ^iy>HB2q@4c0OBOat>BHZo02Gjj-Am{z8ZX=gf^ zPNs|LW_p-jrjO}oe!u}{kQriznGt4``3c9Eab|*z%=9qbAfmvjhm}O># zS!LFkb!LOvWR74M8_q_sk!%zj&HjSFVGJ9~{(*69Je$D&g^6quo6M%LscagX&TgS& zD1!wklRb{I*lae3&1Li0eD(w?U<=tI_9QB1OW0EO6e?rO*$TFjtzxU$8um1*W$V~_ zwt;PAo7iTyg>7Zq*mm{|I*U5kPWBw?V!PQM_B`rk``CVVfE{Fq*kSepx`;;DQFe^I zgvQwkc9NZ9r`Z{HmYrkg*#&lyU1FEn6?TmRk6gSPyaI@Stn&alV1#XdB z;+DA;Zk1c(*0~LClMCa+`3OFekK&{G7(SN2f#UdhK7mi}i}+%`gfHdG_;S92ujH%vYQBcA+L2q9945~76| zAy$YJ;)MhuQAiS!g;yv=NEOnAbRk2?6taZZC|k%8a)mc2PskSvghHW6C>BbDQlU&J z7b=8Gp-QM0YJ^&$PN)|eghruBXck(8U9^W7rC#7^-u>Jq=8 zZm~z~75l_~aX|cv2E`$9SR4^Y#W8VQoDe6)DREky5og6Yab8>y7sVxUSzHlU#WitV z+z>a#FezO6hQ6Z+DN;H_QBt%NBmF?JQk)boB}j=Mol=+7E%ivfQlHc>4M>C1kTfifNTbr2G%ig@lhTwlEzL-?(wsCeEl9^O zz>Ct7bQ~{BE7GcT0694(*5F>8z<#L655nsZUa+Q1; zSIaf>6?_%f$_%cP>*WTyQErl1%;9F4$1QTJ+$Oin9df7KC3njL?vZ=tK3T;5@_;-j zOL#~gmPh1Kc}yOcCuA8bcv7B{r{x)WR-TjR`14N)#8DDrHK!atBu^l}eRTt<)&BN}X~S z-^2CFef$7F#0^TL(xfyiElR8M2tUScO1sjbbShm+x6-5ZDt$`7GN249L&~r+qKqnI z%D6J2Oe#~#v@)a2Ds#%bvY;#~OUkmcqO2-w%DS?lY${=DxEi5Gs!?jR8l%RlacaDp zpeCwGYOa7OF*RvHAkP#3kx0{2IT( zrD~a4u2!g(YL&W+_i(jZqxx~JTBp{l0o3qZR$RLi`&%$+@S_>r`n}< zt37J3+NXwazdE1}s_*cSI;@VU@A0TQrjDx<>ZCfQPOBgAM?9m>s-N&@Jg3g93+ke} zq%Nyp@QS*suBq$lhPtVSX&qXn%02_7|6F;zRc%dM*EY0GEldyBBlJi;N{`lK^jIB`I6YoZ(2tWu zJxNd2Q}k3lO;6V|^h`ZV&(?GFTs=?E*9-JQy+|+COY~B`OfT0@kP5w0uhLJFYQ09U z)lZQ+y_0yzHKSSE}4!u+F(!2E@y;twk&ysVbUmwuVlRVL3 zqr@mR%8YWO!l*Q=jB2CCs5R=0dZWQ;G@1;aG#f2Ot09m!quuB*MAB(=8Qn&Y(QEV> z{f0yaj6p*tL&mT%VvHJN#<($IOd1NAGNz3gLnX7uoH1``WWiW8mW*X%#aK1g44teS z8-_tP4U>eK;bw#xX-1jRrbS}RSToMFNxYe0CYlaOGLy{|Gu2Ep)6EPM5=1ghOtQ>u zGsny|^UQp+z$`S2%wn^|EH%r_a&$wy!E7{}%x1I2Y&F}=cC*9m zG`q}hv&ZZ;38AFV>^HBG0dvqCGOv?ibHp4q$INka!kjd>$qh1P-XzoJEiz-ynses7 zxnM4ux5*A!GM7ysSut15HPa>Q=7zaxhFNz=xD{dDCHF|Ab)Q684@k5XW5rr=R=ky9 zJtU7vqLpMlCdpQcm1;d9X;!+GVP#rbR<@O6JtfabuJxR}ATLRtm2VYTg;tSOY`r2S zR;g8Hm0J~7rB!8BTQyd#RcF;(4OXMoWHnnYR;$%!wOg-Aht+9yS>0BT)ob-x{nmgr zXboAz)`&G~jalQ?gf(eRS<}{xHEYdT^VWj3Xf0XG){3=ity$~VhP7$EA-g2Z4!8G6 zgdJ%|*?tmj2S|(^YscB~c7nZ6-jYQ7fF#*Ll5D5gsdk#3ZfDpb@{VNMS@wI9ZRgmz z_6L$@=i3E#pl#@`;q%pGlehg_PSBcBNfqSKBrASMrV2+I9AKQg1idjrJjF zvYYJ|yVY*9+wBhf2l+`l?IZGw{3cy?x7}m++I@Dv{f7+LgZ7a9mkiq@_Ncu@$Lw)? z!k)CJ>}h+(p0$tBIeXq-uovwmd)Z#GSM4=>-3IhH-LN<96Ew^TcOsmVG}4K3qMaD$ z6peM_oYV9Sjd#w{1m_%0bdsE8=R8euQk@I*B29DBol7*s$#k-u%QV}`adMqJC*LV> z3Y{XS*eP+Y&{F3rEpy793a8Ska;hDMvb4sjbvRn*)H@AMqtoOxJ1tJD)8@209Zsjy z<#and?QsO!>-0JO&VV!M3^^i|=&&>5$aK^hbH*KoPB@d!lr!zjIJ3^2Gw-N$!O`gA zKjSP*&a$)OtU7DXKVuJc!`XDgph?4F1dN0hje^lI2FAiT7!MO*BD84|bZ9b6fvGSJ zro#-F39}%ih-Skah-og&gZYrq0$2!(U@@e$1eU^Uv<#NR>$C!H(@Izct6>eSg>~=- zt%nV;5#FRtuohPP=C?1g=>AMVfrI0%Q}FdTuS&_`W52FKwY zIsqr)6ue8P;S8LGb8sFmz(u$Om*EOrg=_F0U56WR6NaI16oKy32Q(5zp@%dY#h_U9 zh{mCKlzZeVp83kwy+NW>n0S(et)P~wo2kJy! zC`8}UZuFk^pbxYc^`U@M>G;g;bR$J9mBe zd=Gt3d{2GPe9wI^d@p^keQ$ibzCEAcx9@xFJMaa4?|dJ8AAO&F-+f2E-@ZS-zrJHG za8J3X-81f4_ndpdz3S?&?K&=Wu}fU)UURRz+wM*GmV4XXaec1q-f{1`_uTvL1NV{p z*nRH4a9_Ev-CcLj^}7Lg-+k*IxIy=$`^o+6esRCL-`qp@hwH!l`|gQ*=k8s+C*Hq# zfBV7i1N3C~$%&^Yp51%)_1W*|f1fiiUcK0V@#*D-SMOeZd$YBBX7}RWmA$Kb(w?%X z?!moVdpmpX-u=C!y zQ~wM9EB~&4&+qr|`w#p<0XS!$4qvfB)nDr~SkIpZmY||L&i9d;aZ>w})@7gS~^V2Zsm0 z5B?q;51tC137!qgK_#dKt)LymK@z+XydB&L`hsroVen+=ROoEzQs{E%O6Y2c3yC2) zWQME|3gOVT(Dl&0(6i9<(5ujHC=l8Y9fp2{jzU}Sj=cl#-oJbDUi*CX`O245U*CWI z`u+QN@sJ+gIehZt<%1AM>*cfeh658MY2z(eo|JO)p|`K@Q*Id}nHf>+=*cmsC99`J(z z*avUH0SJN+cn98t58xyC1U`c=;4AnBzJo*X1N;O>;1~D}{(zIm{(Eoje=FbKy0P_l S>o55Cziw_l{pb9@#{U3#XA4RI literal 0 HcmV?d00001 diff --git a/media/nls/c_950.nls b/media/nls/c_950.nls new file mode 100644 index 0000000000000000000000000000000000000000..ac0d9ebae4b25a55767fa9d6c34597a4d7eba36c GIT binary patch literal 196642 zcmeFaRa7I}yY`!I+TC4%ZrTN!c6aYoq#_khMJkZ0xC=1|A%qB$1nGLX>eMc4yVT%a7LU7XU17@R$KCe1phTM z{C^`v?cZ7gwFGJj)DoyAP)neeKrMk<0<{Ec3Dgp(B~VMCmOw3mS^~8MY6;X5s3lNK zpq4-_fm#B!1ZoM?5~w9mOQ4oOErD7BwFGJj)DoyAP)neeKrMk<0<{Ec3Dgp(B~VMC zmOw3mS^~8MY6;X5s3lNKpq4-_fm#B!1ZoM?5~w9mOW=PW0bFvkSe@j$$t_}ipQ6O##85&(LNFmeA)F9NC{BnbBqjDrY#FPG{MD;5 zKGr@_QdKYZB-SSRe(XW4ek?u~m(VyNtt!1rT6HD0EVVqfBK2(QAF2M-Kv%%rR&cT#qeCn=ERPs&U3CFLf0lX8;ACk;;;l+-(^ zTT)>XE~#!(QBt#{R!QxWIwfIA)${&aElW})$&(04oTT(5e$vCFM@dhT9w#Z2R7vWj zRP7ovr6GRE(1SCO{kd}~;oS57zxp#6>a-ZbB z$^DZ1Cr=?yC(j@!#1dn@V!dNYu|BcBv3{}su>rAxu|cuHu_3XcvE*1vY*;KcHas>W zHZnFUHaa#YHa0dTHZ?XaHa#{YHZwLWHaj*aHa9jeHb1r?hK~U;LW~$A#mF%*Mu}1X z1^uVR=rJh9h=tfT0+}5~laogi|#O;jR6}LNXPu$+PeR2Ea4#XXbI~;c;?r7Yx zxZ`mr;_9a~NNJeTD5Y^qla!_@%~G1Dv`A^0QWO1emC`z;O-kF8b}8*sI;3<=>6Fqr zrAtcJlx`{AQ+lNIOo>lPNJ&iTmC`#UDWy+J-;{nS{Znq#JyG{$-D7o6)vdmR)$!G@ z@&8{193H~g!N=jJ;n{dM-iP0bpF|W9rNsOHZ2eS+R7z@3oaqghJU z9rhFUJNA3_2X+-(#i`;n<+kN6fNLUmYkVtwbNpa@GJXtx9)1kVgAd`0@cH;c{384T z{C@l){89Wd{2Ba7{3-ll{50YeB0|K7G9pTh5I++ekQ$O2k$#Y>NHJ0e@)+`L@~nT3 zdk#61e2RRMe1`mz-X9tW4S)tiAhR{AH)||Q&icqUb7Gu!-1gi<+(z(7cpi+0hl;XA z5z!LS4$%|QTX7?#9}+KxrAFx~>1F9HX-jlCDpd?njZ}?O%~C-srfRh+SKS$36ZxxG zqXWJ@z8$_3ejI)Q9>C-APw?0Am+@EdSMk^IkMNK2H}H4yGlP>0~sCwRitA{`-kOtC06sC(gp7osljQx~dmlMZPb1a-X z+)mt%+#}p3Fc}765=?}bik^ywAcK$r$UtN;B9NYuwnkf_qtPkoWOO3BPL-+7QQy`) z)pXMK)b`W%*CuOIw8ONi+FY$ww^p}L_gZ&L|4{!yKi0U{s4<-~^}zSUlkjAG8on66 z1pg;~DL#g840HyX0PTV1Kr5g%&=Po$|BU~Ee~bTs|AnsuGzI1mXAx%-XA>pFn#fnd1&xL>Ap_)stdJ3MLJo+=q%*Ub9%dFZ zhxwh^fn{XfWjEmHI2um%y#H3Wqn>R@8;6&s79J8#2@ePl z3irWN@oIc7z7$`9UxixqusR0SZ71cz`s(41|FUAOM5_695uP zL<%vDs3+=(2I3y#FXA}TXwoRsSW+@+2x%l~3TZEC7l}j$$z(E-EGFy82C|WSm3*0e zjjRT>U`^z&UX3tl0E<97Xa@CQCYTSpK?@iJm7osvfh8aeO2Ayu3i`qCR2NN8OQ)sL z_%tz1NVCwoL35y4&}?Wr1VVeEUC?D{2ecNt03C(SLua5<&?V?3v<}(?U4)K6T&9pI zU`CiF%qX*rS(3j=>&oi@w}&Ue6XD6Q4L$*%h7ZI0;DhiE_#%7@UIkx*FTy_DUxSartKqZoMA0(QZqav9J8@faGjRiPU2zLBPTW%5Ufe`n6ZxxG zqoKGt(iFjvT%-t5B4vmg(IeSNITAtShyt-8IYHbVP;pl8U8>)Fy3< zc10hd&(RO)2J|%g1l@%0LHDA&(TC_N^a^?j-Hskccc2H*wdghU2>K4)hwefjptsPI z=xX#0dKiXw_^LqDoWkSDjVeP+e1ocW!c)JByuboO_&=&K=GT&ehJP&UMc1&c)94&b`iU zPP|*`?oN_;PWjIUE(b0Iwgk5aHw3o^kA*IT^hNffZsEz{N#Swf>EW8lU%eVr!#l#y z!=wl&Qi)%KUyFYLYys8*`+)nv1>hWT2RH<51+D}4fRn&AU@dSSI1C&FZUSe4yTCSp zM$9LMhzp5$(lpXs(gML_14cODmvJAR+`n zc!&VqhOR>~=n?cBieo&1{(^2oPoX-DA5a=|G4oI666PZ2Qf3_%o&~TLu;#IDur9K` zu)A}TI6XO5&O*+gobQ}Q+`(KC*Tc=?dbzpWY_5-+!)?Rs&Wq3ac}V#aSXYHyhAP{=aHAlR%9LW33-9MK@KAq zkj=O95w-)h>gU$VxQ14SYK>3)*l;!jlf!91F=<#or+D0)rxhBHHz(uwTdN* zWR*%KS7}r)RQFX6RNK@i)w|Ri)o0ZE)tl5^w1c&PcD@#`ou^%;U7}s8U8G&CHR#;B zY@J7UTz6D=NOwe6NB>RtRo7VGR9~h0scWdet*>inXJ}?6giBscWro#aSC$8(QmG8(2r%{I-3zdiI*gU%eWw?9J`1?IZ11?N97C z?T74#?WgSz?6>S^?RV{u?RV@S9f{6o&Nx?n*CXdG=Tm1r*Ar)5S7X;j=QZa$XC2pV z=Vj*w=UwL|=RM~eX9E|(ZFHO6Cieo5)Z@sxoYTl#*Bj@p@GbOd^3-{o^UnBB``-qh z1|A0f3Oor^&--untH9rZ$ARa8lfkpW1HnVVd7-(XGa+XYAv`ZUKfE9eN75pvBCjGJ zB6Xt6qqm~>qT%A=Vmf{kz8Rr8p%>u|(1(yj_zLtVbRaY!j3@LYbRo1Mv?hH2X9M(h zgnoo~KmwsDp);Wq;REm*7)%&Ir~(EO8WSwUCB&t~MZ`12)5N31Q$#9>MFL4o5}P!D zY$I2a%gOi1&%sudI+RhApWqYlJ=lQq9c)K=0loqsfQ>1y!M|!`{Hq?rr(j=7L&`6( zB_)nlk9LrDnRbeHh}M|i5~4wLhyk@`bYgU4^kj5pv}L@6;u*ad{TWG&W{k!RDU;4x z&)me^%G}Ic%iO};!Q9TQ$0D*QECTBl>lf<>>o3-G)?3zRRvq?7)@$})&Opv8&Kk}# zP6{`l8{!7J5U+aPf2##N5s$#5@GxE)PtMEaRq{%BdAvfNkC(*@^Jc*x;6{QNj2BE4 z3>8oWQw1{xfMAYbtbibxAQ&JRDCj3xAeb+hEt(@L799{B5lt1(5d-3BVv=~ic!qe2 z_^Y@b(jMvf&j$sgC9@?nC1lAM$y5m_=`YzN=_r{mAxb7lJ|YCkWXX8RG|2$T3`tu_ zC&?6vSDGW;ChdjxMf;(B(B9}q}{7MqCKYFsNJO9qus6Dp*^VGuFci0*PYaz(Vf-x*Z0)N>-*_n=#ve74WkX+ z4Z{ti4At}gTb*PWY=}4XGz>FPj07Xk$Td=p93$IEGct^ijgO4ajQ5OBjW3MXjhQBo z>4vF+xwSdRl3?vyIGrCJ6pS2$J)5ILfaAB0b2umCwqH) zXM0Ec1p6fWJ9}NnTYG)SEBi-#1IJhU2YVyOFMAWmPx~ADE5}O*&e_U2z&X&_&pF7s z%Q?_Ra)GY7uF)=nYmRG#Yq$$=4ReigjdXQ%O?IWY`njgLY9fF2YJhI9d!@U;y~Mr3 z?Q<`7m$?-ly~p8kdaNF!r<1ppw}rQvx4pNCx1+bMw}ZE(x3zb+&*U@u{_rjG>GM|m zFZwV0&-ph5>I54EzXWi>?}3kjxZtlq{ovO?QSd?VPVixn6j~6PAG#j86S@|<9l8;6 z6~SRam|r9FUuKvc7KZ6zPIy=NVRUuz@{;Q%Nu|R|$CqZ{O#~}}MVLjHMwm}v5atj> z1RViSpb)eK4M9%;2rUV60!CmFi->QD=_EPnBIyR{I_V0j6}ct3GkFquGI=8T5c#Kg zCMBIBrc9@BD16E^%3Mkcg-QV^6v|MFkTRMwguq6jFdlqnP%r4g+utugH$tvo#a~TTeG3F8G zVdg>RKITzoV^$+pLl%$4VzF5b*$vn&*j?Ej*oo}c?EdU_?9S}o?7r-d?1${poROSV z&M3|{&UVgL&KAyI&Is-(E{%(F)3{P@gj>w5;6}NBa2ImRxHjHmUJh>|Z#nN2Z!_;H zZ%>Vk|3`Sccw2b4dAoVnc~^KxdG~nRc{h2-cwOMG@N9UYV3|NA2n!YomJ0L&L=Y9M z6etBN1UUkipj03gEEi-7Jc44uAA;3_d_h297nlWU0*SyRV2h|Cq6iYvL|h6WqKhaZ zP*f%=6|EMX6P*&B7M&Hb#SF1fED?*v9Pu~tHBwi^Az3F`Bq@+=k=P_U$p*h&M{8EtHKp^ z8C;88Vb>nlDp$VC>nd>NxE8wfF0;$>FBt#bu4OKYJDq#Xz2Cjneb~Llebjx*y}`ZC zeZo!lRCqj|Ri1oL*puhU^%Ud;at3(2dwY44yeZzn-k#pB-bC*lAH%o8x7xSLx7@eV zx6Fs+iSzd6?aaI7zvu59Y#!_q>=^77>>2DHY!z%D>=BF)whSf)I|RE1+XZW)|IdT3 zg1>^a(Am(Z(9_VP(6i91(2Gz`QF>S#R)-B?MOYKoh4o=Hyg&R`_(k}>>7J=>G%m_0 zeNv{auvILr*j2HJkVnWO6ca)OJ0VPn5=sa-DyBQcj6doRl)kN=hLmo03a$Q8rQ5QYtAEDH|yzlwFk7lns;&N)BZerI^y3Hk3Yq zKAhg0o=i`nC(ygo`TVnb4E2l>hK-TWC}k{TsF_OUMdoSdCFXf%6IN4J z3Tr-_z#h(?#s0;f!I{9B%$df?;GE{I|RxypKEy{~fOd|1+;KAIERQ?+MR=7YlrXbAtVX7lIRlqk=Pn>UsaIz9@Jk zI4^i0xGH!hcrDNgJ_`O4+!Bz4HwE7W9FbTAiv*&OC@5Mdl8F^!jaVm^i$h|QI76%# zSBYcdo=A7(yX1=GzT~>(nxuZ(J;^7@YsoXoH_1iGd&wioDajd0^RzZ;Ez(X%Zc1cn zKO_^SW2FKqc*;v^i*)&;q*+khXSxw}xUX2`CXBl25kWH7VWN9+4th2Ij10=w*5d-kILv-m%`1UaFVxbNbf#cKbH@_V^C? zcKP=EHv6{uw)*z@w)?z!S$U4Uvw3&&PUYRqyO4J}?^fQ?ydVCr{-6G`z>wgGU`lXw za9D6;ux{v6uyLp=CEon+Qh;dkL!v+X%Y|>j=jPHjKM+HfK6YVKNY z7k*3rY<^Gv2VPhHH(ninBR-x#pFf?yfIpExoZpwYrOF6XCYPiNYSj0m8w; z3Bp0bmcnkrcEaYuk-`qbj=}~)R8%QiFN%nB#MxqxI4sT-N5y&KIHWKQORI_gGt%^F zyfiRPo0gpBOq-h~Nt32=(#UDXGcx7FUZAgu{MD;r)TirFJxedrOZ2e*wcc-7Z-^M82A?6vU@?RY z1qPeJWV9I_#zC2TjNMFKO!206rkW+unYa&z6^+-xa(%e zWjDxfk_~z8c`kcycy4>Hd+vB1cusn*crJR%avtSKy(+KTEB2;&72a&G#VhbG^eVks zUd#)7WnR>4^qRdBy%I0%^ZIgpCw<3!$9;!=8-0g-2Yp9;5AyEiJ0tdMGV)A~Y(WmOnawLjL6ZiTTX@dHKS8V*c>_Ir$6nXXKB`pOnwYj}}G4h2f&` zneeIbiSWtrm++79xA5mMHKK{=BCVpWqiv&2qHUthqCcY_qt)~NTm36q72Q<4p?Gug zgOV3z&WaY5Z7bs|pAlXYo)E4QUJ-5*t`N=UT%%{xf%!ka!%zMn{ESQza&So_B|?LcD>Mm- zLPR)RhzZR?mFN%AHPKbkBJpx@xwtHCd0J80fwZ-0m(ot9m8NY=+m*H|ZFAcBv@>aI z(oU!SnRX~`aoQZ|d}%70DsLyRlC_n8l=YWSl*h{l$y>_n$`j?)^p5*~^fB2RSp#{B ze6)O+yqCPae4u=&+#??#e<`aYe=j>N`ywk;7AvhvuQF4aubimLSA|v6)daOrBhaL4 z6dFuZPaD$q)iu{O)iu_&)jiNX(q-zcdYhiFKVYadEHi8}tS~G#_>BQ$o^gmN#kA72 z!t~1Y#`K4|$ee4|nj_|NbD=q4-fqq|XPS3d_E`2>c3Ib3%dC5>d#wwtC#{>U8?76x zJFSbX`>b26+pTM?7p=#vtF1MWzj`$kw)?gRwtF^?ong*~2-{c_MRP=F!ZX~ z{i$Rso=T%?s3WOEsmcGmfmhNi=$q(e^tJRA^grns)R_5$(Ukd#(Tv%M`I`BX`GWa3 zQ^*pr%Grf%n8W4pIS)BEIrlhsIFC5@IkUM+?l$fgu8xoJWqdZD!gtol_-ElO_)>lb ze;Gf>U&Z(HSMy8wOZbKSwfrG)nouq@3M+&gg&tv0xL&waSRgDCt`O!6*9zANR|!jm ztA)kFMZ!%&tw=92h}Mc%i8qTkhJULfhsa&nx zpj@t`s!COOHBFtS$-y_@>U!(?=n`~^x)R+^-D90!pRM=l zL;76(DZ>%NPQyvVUc(i`Zo_%QB-41)WYYxGDAPF8I@4Oy8uJG8Ve@A5QS&kL0rNuh zY4b_Ted|Z-8|x42b?Zy(9qV)JBkN7;UF!>Lh4qH@z4e<_Yt!4-*{bLLxB7*xkG<4U z<|ub8bd)%vj*eLqvbtow&K#6AIIC?|>#SZ`30dv3UjDN@Etc6J%bBgo)@Adu#o2~z zNj8*C%buT2{^#a&wx?B2!<;rbZFAb^G|AcRz34sWJ?t&=p7MV6ZuFk;9`x?>uJ>N` zp7Cz=?(p97&iCPcsPDe-uJ5VuvG1ktmG7bNk?*$eFW&F*xs8t575ALtVp5a<@@@h_PFB?Z!gvY;f01@*z?(BM$tP)aB}loQGg zxk5+scja%(|0{oW{^R@u`J3{0=U>b}mj5 zeR?{a&QG70J}Z4hIyZfGIwaLg>!Szd8{~h~$o!{z3=hed$PdVu$v4UO%Xi4P%Kwxv zly8>rRi03uS6);eS6)%>P@YxZP~KJ^QXW=H)Mc8*ny98yQ=xgNX{K$i9j+U#8>@S! zd!k#Yuh3WOm+GGzZW>-1o*Di$E->LuGfneN^GrKUH_WXqC(Mt{x6BXBFU(KPS1ea8 zO){$I{kOVxMx%_b8ND)kWOUDHoY5-7XxnIeYkOyVZR=;>D8681!PorMf}sV81wZo#7St=~Qcx55t5>5{L7#$zg7yVN z3OX0;Dq0p^9$p!~5^fP`9qABh9%&nC8DU0P5pg6MNsf+=j*E_p4vvnA_KvnH?pNHS zxNC7jahKv(#Se?$6>l%uUGk&kRY||nP-*+}Ugdqt`<1sT?^=Gn;&Me^Wm)9_VozcM zaTxIv$xpRYgVZc)Hnn=*f2#x3EA&hB3-q(}Waa>7Z>EVkiX~y~X76P0VQ*(kIrF)D zxF`4r`N#NA`KS29;NkFD;Ys0j;eFv-;ZxyD;XC0&;VYq2lkIMVX5vrLgg<7Rvp;@o_Q?pz%Q#VyNU-y@8lYXUsy?*t-;QG%p z{Tlrn{TIV`!$-p#LmlHX<4PmVw9nMg(%e#I{$g%sxo^I2xox>?d1$$3xna3u8ImzE zV`j#vjA0qmG6rT$$VkbUkufD>c*dBF*%>1;CS?rGm~Q)E`)O0!Rd$74ZdconIu1E@ zIu1JaJN7yDI8HeBI-WZkJC)9rSvArB%&d&8vaC>6Vb;2=(yZ*P*ONyXV%+ZIwI4H_4~= zefRzH{q%kH{qQZ%o8zD7pY5OPpB|VPm>QT7m=v%Dt-;KoBj^m;gJVLALlvR2(1HSI zLB9fR!Q28-!MuV_1sMfs0kc3+z$gFW4aJNX0$im2_$js>0 z=!oJvB{h-1dNpFjYfD#^t}Is+d?guksS89;1lQvc~ zRaD6vD89>ED_SakD1R!elwXy4wN|}Mvrp4rOV!bJ)${&aP15br@6+$n@7A|4t~K&a zu!(0nY&v2ZXz6PiVCiA$Wl69+vw#_t3{D0kgP%dlfHG#=zS(}*^md*7jN_c6iSu06 zimWqP=d(^^tVowJ(SnkKNWtZzt3~IFt`t2C z-wxjh-wNLi_l_)%{28f<{MD(LmK)MOQ6S8PwJD{#$KQ@6nvp zJkn%q-P(UnE_KKBosAoeQd62~qGgh0v}J;2lx4C-nt^2)Gtx5BGqP;zjIFjEw(Yj- zju%;Xvi{1tlJz+2N!FLFAKCRi%{||;tFn1H+#G5SCud47E0>--Czp|n&joU4=0drR z@|xsX{3?I8U*|{tCcnlH2JnG30dFujxFNJQ^q}BE!M%b*1;-0+7u+ehTJW&oOu_Yn z#|764o)_FM+8llq9uVmp;YV&qendDma{aS<4Czs3ba!+{@toogC7nx}mp(6jR(iGc zR%uQ-zg$(GUXGUMS41ibDmGVqB`v3Jqi&^crtYRbrcY*0V_KP?nJ3s^`QQ1SMD0YK zMNh?jk(cQc70HTWidHJK`kV&ViFAF81B`==1C7T_pH1^E(<}=tZ!B*uYXjB{OO4F` zoEh_NIQvb9*!d&tTUKlL_pAo)rtXIBChm5g_8wu*&YZ6~id-~ToGZ`e=1Oy0<~7gD z@jLukey4wP=v1gvVO-&_f(J#(k;73^F|l}g@xYSgl2IiiO4^n+FEdtbsd!#7w31sX zsN`3UB90~=pzfz0q_%@l)*1FseigsFsGF!r^g{e2y`J=Y`bOz|MOW1_)m6=9O`7hK zo?r=N_%e3eI=TnDySRIK59*4HyL>rt|h~6wcm57a^yKb|5>EnA+KXz$Y0>+2WE$+7ZM9eg%ctZBZndfBGTwT zH{_HoD7jeDrF2eNO4-D+ab=gvuayt4L@U!P3oB1kud;D)FVR5J0MScvE9p(mNt4hb zu!t-L8R3k=jE9cV?n&+xk2g0M3|6Qwa!ZA^qG6@JQdRkZ(?Kdwpca{BoM(T|AN~U&RiUC#8RZmTE$LNy zxwms*-bbt zIJul0j*sKvf%RYz1s>WI2PU8v4ikJXOR7HW&M4&4OfaC?!x*dDa!+so`hXTX`|^gBb& zf*RTX#p`rAGo1$CiNL-{g(10{eFZ~z7%2$TVZKn0KwIDsNS3dn#8;%?$z;t0|(QYvXCDTTC~)P&rW zJf56SE+l7zHqZfvKqu${rJxDS07W1QYCtiV2g*S{$OEIG07O6`_=Wn7DyOMv7)?r3 z(iAiu%}&$O%rrGkLxXE%|D*ptmj9DS5}K9P44MILfp$XYptI0M=rnWy+6wK44nbF; z4bUEFKXe@03>|}DrifX3Yh?Y`a9$H$M_wwg z3$F)n5HFF}oY#ssgx8kWn%9iinAeTh4xRw7fj7e!;Jxrlcq@DoUJGx6*TK8s74Uj^ zJ3K+OT(nEnSo~8|Puxb_Nc=+-CvGZkF0L>BC2B2hCH^dKf@C2m;z#lk9b!hJh#Sd7 zG)NxeLrh2|5<-d*7h**mhygJog-DXrF3phMm3Bu9(3j}n=xg)_x)r^Qu0fxn+tBmq zL3Ag22tA6vLf`)j#{Y}x9dtA5Maxk;dKcY~CSzyNW9WMH8+s0XfnGoh6;VZ&qCnwR zWGX_6u)?V*QMeT8s;jC~s_Uu~s@tlIs>`aIs?(|qswL__)N9m#su!sjs#mMa)ps<{ zHIuZHwG*{IZB)BX_d)kg_g42w_f`K>|4six|Gh>&|M;SxYMf*|VlbXo)$g>904u? z8-WwRDc}Hb8MqDH0CoYJfLp*Z;3}{a*bnRgUINoeb4dG12T2pi7IK6fCKr>V6t74#8$1ubXJXPswVXPstUW1V8%s*(Ml?y_#OPOy%#PO`4DF0n4N&asZO zj-ZJ&oEBV zR?trH9d0l90l$T(h^C2FiuQ>{iW9`c#3RJr#C^nx;#BcK@mO(p@o@1N@epxKq!n@i zd5;`NcK!?A|8FC^kgv#fWIwVEIfDF+JVx#zTaYuzCgcn98F`I7LJlH3kh91$jRy|k!t-7cBOZ8OsNR_2Ntv;we zu0EpPq28+AqTa0jTfI+xOubiqNPSejU42UZQuA6fL_146Tf0oVQft&5)-}?{>Feq1 z>znAm=zi$F>z?VK>l+wa8`>D^8(JA!8d?|{8{!OY4Rek2jq{8%jMI%*jAxAJj8~0k zjrJN@|McI-@_+Iu!*s!fGuJVjEC!3wVzbyS4ojT1k+qJMZVTD+Y#?8of~?dR=B?2qg>?6>VF?N{t4?C0#)>`(1y>@i1zv(S0NS>^oZZ0LIK z#JR3G$GZM@UUhzSzH~ltzIT3dHgo-Oes;cf{#7IMzsJt|&hO3-&R0&oTjRF4)$S=C zya(~5d(u3Ya_V^-dR2Lk0uKVO1NQ^(f_sAdf>(k^f_sCLSPsO6T{^2 z+%P`egHWH)kkFQpNJu7hC42%t0;z;igh7PQz!#t+p&KEd(3dcRFqDu&XhC2Q3yB59 zlf=WsBgEsxvqV0LK_ZbjBrb_Uf=OpcEyxw*K9q-GM@k#YGw=iW80k zDfKDu{srTI6Uqs1 z({|7f&{{xqq0WpBjKPc{jP{I{jE;;Zj2?_s2FhHE&ZWSAsXGEOp20!TVYQY76Z zBP0VQgC#>Hc*%6ha7lMb8%aA!A4xyS5Xl0`SV@v3UNT5JR61CiA{{Qpq)xj>`c(S( zU$FlFx%83rq4b$F2{mB?Oo-{Q<`^H#$LJW0VVE2XVR_ga%!au!4u)VnEP^R83&zEq zSQHzINw8cj1G8h9SO?67nK3J-#e&#v#U;fB#T~^d#TeT|#Wlr6#a+dH#bw1A#Sz6( z#WBTA#aYDz#Z;9+^`DGb|5Kw^=~OuNchyH#mFlzVgX)K>j{1`NhWd&6s(QEjnfj6X zh5EMoqWYHlvigqtruv%ty85~LuI8TRqvn$)LCe%~wd=J9w7ay2wfnXEv|F`1wO-u` zU3Yy~eJg!ieH(o*eQSMteP?|aeWJdvzL#N;A<;0xFx1e`FvKv>kYMOUW z(+C(@MzWD)BpUxVzBJx9zBaxx{$;#vylcE;benQaS*Bc*&*U{_o35K$ng3^&|NGDD zncJG{n_HS2nVXnfm>Zkhm@_RQi`U|_cr1CAEK3h-cWY~F3u`B92WwkvPiq@%OKUSL z%f`2HY&;v=#>|37TvXR2*A!PDS2tH;jqHCg)rEI;bq#Pea*cN_aCLC?cE!6!xrVy>yJop&xaPaa zt{$#Iu6eG$uGucKo8(^PUhWRN^V}hKg*)3Fal75Q?h<#Fd#StF{fB#*yT~1N``zX4 zpu5mL%`@GDd9)s#N9D15lpdQ$?s0iCJQ|P1)5bf?NAsC|OMHucx;#VPmb`6wTk|gX zFZrtip8|D*vA~Z&z2MKl=fKtA{osw@&ETWpz2KAJ_28}GwczdG;~*jQf4|@V^FQK4 zK*+ zflEjuNC^UhkT8=lnII#m2{ZzcaGoe7VI-6!BV8q3A`K>&k+l>ZWjtj8g+Lij89*UY zV9H3!2ud=AM43VPpKkt>=gla?C?X1;GKMmnGMF-sGMO@u(uCHK_Jh`r{*d;WcANH* zhNHit{h~FZf2B30f1sVCHKf0$J)*s*J)ym%J)pIq|D?5|Kcm&5H>1C!y`a6NHK*63 zvmhRW&Y&<528S`4F@k|H2n;Sm#6THjhLAyHOk=PaB*t_GlQEm&XG~-)V2okRXDAqH zj9CmKgUXo7U@=ro8S?;hKNDj0U^iuVXLn)8vzxK|v758|u#?y=+5bu2n$;w;+pv4F zd$NbHCvt{!HgGm`c5pUwHgQIBM{`TLVQwYY%M0?{yuG~jyq&yDyvw|EyvMv7ygR(( zybZityluRbynVbwyfeK0ykP>7z$Od^x4 zm8_Cb)8vxHlGTzG60Jld*(eD}^pbpuMIx1`Br7F$iBggwDV2mJxsrvF9LW-iL1LDK zBtD5(VwH@Prb0KdH=0Gr9G{^pgpe*=yG(IbYt{G^@H^(`eFLv`c(Y{eUg5heuRFufn=CtSYViI zm~ZG~m|-9oghs@eW=uBp6&LdZ@QNCJfHLI{fyjG`!th>8mY5HxC3Tu@L@TyOz#{ST4$>+Su%``r7N=YRYC zpFH!-%$ak}oH_HGne)E9A#d0-**~#AVNYadaI!gB96M(=_gC&u+#k5Va2IjE;ZEhw z<1XR;#tq~y=g#4N$&KM>^38k;-^8!wyZQC}Mt&3jDE~OWhW}aeK+ONuY>ZDHo4h1> zLGse%j|BmOF@mvzX@buL-w4JFJ{No_m?HR8@P%MR%1kW7ZwUt zLY6R5m?xwP(}V(HrqCcv5@raCgj}Ies1#a+CgEnGLdX+3gjoG#s_r+dUpD7!6NZ!keKp&3vsQ~|X^g-|6_4Yfeyp=PKSngW$V zBZED`BSS}o=7ko32^NMq!ivM_VT)k7VY)C`SX$W5FhQ6-OdFOL#tl=3<%jXZGQ)Dh z)M3NdO@;pmABgoI10N5c0-p%~68>=AQg{G-9DFQ%7CaFC1AIFCXZTO>Y4C60bKvOp zTM-!u8-j(%MOYCGL_UIpa3HoIG7%++9}yx%DngGCA{2-s1RKFcC=q5v8bXJ#AZ{S* zk#3|1*@Ub`HXw(G&j|k!wE#sx%|op~1)^r7f>EncVW?TCUr-^aUs2zo)}!X5enu@r z{e+r}nu+=W6@*%ZS{N}e0v?$k>4>>=4eb^j63F7%-xtXF=u0DV&kxQECw5n zjmKiKN~{HI#gC0o$)u~ zyW-!&osRE`zZu^e-yQz}?tR?-_?Gw~xVreaaAe$$_z}1}@kioE;U2{|#y^XH8s8p2 z4EHwfBV0rLvG@z|7vrzRKZtLNe-r14?}+~p7l1n&|1)6@A&@YakU`KB41`R=KEhqX zJ;Hs$j15mWE+#G^enwnIlo96=ezIN~hg3Stm3m^g>{25~wu z;&1T&r+8vG5l#G#_$4ulNFfr4KNG(o&LD;ovBW7v1`$J~6T^s1VhAyoIGgwb5kZ_l z8Bh6^@`OB{@*QO&C4lk;WhUh_%9oU1C}Sxr5)cWp1bKoaL7bpS7@0UMaYo`7iQgs8 zN}Q57GjUqthcEGpSFg z-zJfgHY8n7I+xUvbS>#Z(xs%*eKmareI@-Oy^|ir zz%a0kaK=Ukg@I=f8Ds{I5zmNVL^G(&L}mh$%zT~oHtP-6aMmD}fpv}5%398z!(PZ< z%3jG{%?@J2*^Ah@94n`glf!{?N!%E2C>O?!x8O>{xn zCiDtl2wQ}1VT16r@S(6qI8^kW=%R3h=uOc<;r#*m`~Q^ivGAy{Nq9r}f#{I1Q+Qig zEqo$8BfKIUD>^THF7!&SNUljvO0G)INp46kNN!4+C7qHE$r(wzq)D<=29t%!_Q=l2 z%4NG{RkBK1nXE##OSVt8UG|#1MwThhmh0sgjZ_Mh$;v&-N~KF#uH2~t9uI^UfRClR6)eqDi>S^iUr+=INrsf;X zAkB;Pr|EBLdefhzzovm`hG+(B-q4^m7)_)mS`(#tP5ZVsK>LRF6YXT}d)nbzh<2p* zh31*&P3<7<6z%KUaoS1RG1`x`gSDfz>`YarGBZ6>n#IeK4aoa{|Mq5OxSBIVJO)mIKZPGfR3qGo zJ&4_iZHS!+7h*r+7-BEt$lu`oU%L=hh+4!BL>ZzUQI1GQoJM+)XOW+U&kCoYVo=Lb zSX2UP11bU)kBUP@qwb>CM68Zj9HNaG4n99G2dd|#(aVa!USNZV1{9?$Be~H$9#@?7em5o zu_v*TSY>QxYe#2n&&VkxnaSWDCs zONe&j63SXi2qlIRMVUuIQKBgc6b1!PK~v^a;FJZF6%;Zhk^-fKQU+rE7gAPH5R^3u zssv?%CLujRoiI0Xe&U?OUlM~7mnSYuTu5C`T|o_@22Q1_q^f2jJl7Y69c7YZ~ zkEBP@L+CI%f{vrd(bv+~(>KyD)1?d}BZHB~5HT_tVupl~!w@o<3XXUc2tedP@Hio^CO=aWQ32ZDokxgNf z*=RO{O=HKfw{v!IwsK@#2{)Om;_|s-E{m(?vbjPohpXgfa7A1$SIgbVC-CF=@%#<^ ze7=KUz(3D#=6{}y5kv{-f^Y#&fD}Xv5(J;eMF?nuH~~p8AnPwc3qDO*ma;G?SiI}1^kxGOW1&e}25>cFJhG>RVR5lS>f93lEq^o!_w5lgf{ z#1PFCEfP%?ofWPSeJh$TnkI@Akwrg?R*P1OLPR9dVUb!iN3=xrgJ_m0Uc?hE6n!m< z60H>xMNrW&=^$y3WVrOP)h1)z%$ve`)($g}xtX|e2yC^#^J147? zHOj8UBHqST~RVX7dNn#xL@ zt6ZU6uEZ)a%2=gDDN>4+b;@`ZPNh*PRcck5N~O}NGF0g*t?I7ovZ_7Of>~ zztgVO#%Q711np{VsCK0mrk$y^WtuasnWju_mM%+^rO#@}dYttv>rvLjtVBIs&(J66 z-^+d{``zp<+1=T_*;@_U4KBk@L$T3mM4E1xZ<()~ldaFJ*PtHg8E8B7KJ+~F2J`~7 z6?zid3B3!w1HB5p41Kk=8;IWC;N%cNNJq%ckQt#{LZ`q!gbjy{ggp&=4>k_=8tenu z>#)aRpTY*gUWE0A$>AJ$Iy@ULfeYY#I2Epdv*1#=2CjzF;3;q!oDI)_r@^1Y3G15? zw-IfKQ-~XgbBJ4rn~3{}D~QX8^N3EwMZ^WfSwuVH5`vDrj2ws=Tt&u&r=XHiT$BXG zLJ3fGR4Pi2lA(Ag4oZb$qWCCy#QKQP2yaAF#F>bOh~|h>5oaS#M0g?=MlOgXMV3W= zgZ>gd4;_J~pcBy{=umV5dILHcO+~Lov(QL17Ci@zN2Ad&^wj7n(O*Y@jah|3Vo(?= zhK5PNBx1OjBup$OAF~>hf{DO{V^&~7F;N&OhK~uvY`_pO>oHgi9g~RNgw2WF6l;qe z95*QLi@0sLGF;7oy#MsoFx-S|z-8fFxGlH}oCasWsc{836|M+ZiQ9_XkE_P*!{y;T zxN=-A&WJmXE5+$>n{hcfEAA{#k4wiL#O=g6a7S><39ASz2v&lPu!(SpP)&GFXdpf$ zb`jqo1&|&QedXWM4CaG zOPWo(NgP6Ym$ZO1nDmU;P5hZOj`WoH3+Xe`JEZZXw@9Cpq?B}uoRUltQ&K2t6gEXd z5m5A$g$bbv`h?5`UBZIIRf)lgD-)xsiBt+TiJCx-qY|l*q}P+)Na7}?Cyl1PMH^20 zkT!z$HfbzGh+v%m{G{!F`Nu5!@=0Z*uuzV^yb~doO1{r-HMGQ^4KDJ;=3lH**hgtGI``7H$K#ntO!n z=GJkya?80{+zPIZo6jxb7IAa9HQYr075-Iz8~@^fJpY)Kj7knqmJ1{Tp+G8736uhb z;KLNXC{L6lvWfPH8bk+0TSO%yr>I=CLv%n?FWM|JinfUwMHW$kXs;+&lp#7QsuP(+ zMWU^uLeXhawx~>WT(n7aM&uEl5SduVGD|v9`lXa04U$fmj+cHe9U~npT_F8N zI#2qWbg^`Tbf)wx=``tF=}74>((k0RrSqkerBkFoNhe7^k?f)+xIwv&eJgHn~;aA-^eampfApsftu>YFcVm>aWUpB~E!t zd0cr$nWY-4eqH@S^^W?P>TUHK>LKbk)q~Z~RS@+c_4{cf(%wybCvBo;oMwXN3(aSm zPc@%tCTTv`jMcC-2^yv*QRC3&X=z%MmZjaK&CqVvs`^(<>TBFvfWoq?WzSge2 ztyODNw3*smEmtek=4ey360K5e&=zQUTB){3YtbsS)3nyCoU9jFa6MPg()08}eX>49 z&(@3d0zF^fps&}D&MwX_$$s4cF$^(S3}(Y2L%CtEVUOXUVV~isVVm))@w)LhQ=loz zgf>N*y3F^?56uPE7tl9?X9Pcjz8O3uxEuN$IxKj2@H6P!!HN)NNLR?6kfpHsu$8dc zuz9fMuw}5tF!+GH|LD~)M8JYzvtYl%zJdJ)`w8|H>=)Q4>zr^4d>ecd+z#Ig-vW2Q zbKo!FFAxt9&k#L`Zp0hNM~K&vy@=P4Ly&`!?;+#D4JbXzhSH*PQ94v6Y7@$g%0U@X zRunD*6%iE?9&w+0KH_3TOT@Cs?U4$!5Y0qyL%YzqX!(GA{$WDv&|A^PXd7CK-i*#c ztI)CNQuMTFB8H5~!fe8bF?x&{lZH`XQZY)59b?19W42+kF*Ga-%fzy=+p(qCow2Ui zqS)=RyJ9!TZjFWD-^71}Z^J#peTeVEwc;k=U*I}%S8!wTpW>h6rr_`4ZsSJbdvMor zLHM`u*Kkj8@8F-}ZsLaG2jM@)2jJhscjG4Ghu|OJM&pAC4uYMKOUNg@wgIx?1>yA# z^GK6PJd%`jgrpsi>))%bzltO$DM`_!H6$?!LCPZ0NE=8gq%cwfDTD+its`ZSbR-lB zLPC=WBrYkAluimIDM&aHpOi_8A<;>A5}UN0vXx?@xG0+_MoJN7C&fZ>P^^?ZN)BZ+ z#Y`!nlv1)2j0y0>ki>|@$i%2bR3b7Forp+WKOpaaiB6PK<(%Aqo; zZzT;$;w1&p#?!{oKBbMLO{9H7`;s=6W~NzaR+@>XqNma2bQ!&#v6pe2QO9UvG%!4j zV~j(LYDNvi$jo7GVw#z`OcRqv_?fkxwS!g4+QoLWE7@Dv4eYJ#a&|3yC;Kqx7^jZo z=JasSb8m33bI)*FxNqB;wPf7#g9dAiHD0Hh`tiv6MZP|5#1Es7d;h?6yFeah(?Q_i@p?pDxNNWUHnWm zUfeDEPCQwBUDPhRE4m}<6@4t8Af6!}CLSaHRvbMbpZ~+8F;a|_E^Uz}O5xJAQlvCQ zik2dz!O{rnMk!tjm9CaXN>Nghbc2*7B}&7kSm_!mTbd+|mc~hOQiN=BsPI*CjUAakRR^_NnstM|e>Hzg5^>p=z>apt4 z>JjQO>dERUe}m`$qtqkSAFDr5k5hl7{zUyv+N89P(>_U?kTx-GblOL0iRt8YQhHoE zA^ls;*P5xCuQW3?lQq*dVvR(Tsu5^XG$Kv1rcrxHTdl3qp4FCVk88WMm$Y7OhxUy2 zg0@b3M|)7)uC3J`(>7?YY3sG8v^Cnx+Kbxj+9vJE0lEI~)V64kXm@BinOicQnI)O7 z%)G4Jtdm)T^>684*CX_)dbM7rZ`2>xkI()zdvf;F>@Tw?WRK0BlD$3qEyLsN5r$EQ z(T0x<9~zns^@ihylLn8W!BAs3ZSWf0hBJmbL#eUTc++^_c+c2nTx?okiZfA76jQ8; zW=b-VP4Om-X@lvh`LX$#`GvX1Jj4RA^qQZT-?9w046+EVC#~<<-nWel{vi0H;7@`_ z1YZpPKC~s242yyh{|49pL|7~=2DTBF0E>XpVdK_~U3Uz=4_*V`58nen2(N%2fq#S? zgB*+e961X40rGw1Xylj3PmmLk+5gifNBd$fXN3=z(h^&aTpbODi=)>q8=p*O@=sNVC0lEI~NAE@}(PuEHF^!nx zm>SGJj2v?aa~^Xaa~3lT%g1uCx!7Z|m9bT^wXyElT)qz2M4QUs}*w2x#Z)shNHgUAk2 z326^$3u!ayIB7p=_ut_9pG&GCIZ5@Tt)%TF7wItNAZ0&gH{~>?igJMBrg$i|l%tg6 zlzkL0rGj#Va*lGIVo9(j;1XjK;}SO{ViO68_(VR{NZmxuplYd^)Ew%tq~xS;Y13%m z(SD`PqRpkvrp=_ypzWnyqZ#QIdJf%8H_>zHc6uh=Fd*Om)YC68Iv8z?8;pyLtBmuE z7RD9EEyg9rWkw!zA!{jX39F2?o3)d*jkSw)k$shYoqd6QirvOO$8Kl$vOVk@>?`bM z_D!~zeTjX7`+)Z@ZyfJK-Y2{-c*A(_@kaCB;f>-2 z@FwvV@Y#G0pT*zCzr+73d1~^8dMSG)cPi5H78;(6j|@j`L1c!@Yh{F@jlrifRIiQ*)2m^e-x zC02@K#VGMwF;=`m93#O>FcOnAO{$mbq*|#=Dv)MLv!zU_RBD%srRh?Q)FKs0Go)sz zQ7V^?mrs_@kWZ6Omrs#@C;vh|RX$Pvt^6DLXYwxjgrd~)LrD#pP zlzKPySn9>pmelst7pZqrpQLJ(T4lQOq4Kt}OL|ySjIDZtbVK$Jzkh2fAKukM?`r z>$*w07uu=1pLMf!U+G5ahW`!T|2s_gTsu?;(LK?Q)>UNIXI5sGXYR=?%iN#2Gjm^N zQI;obn0}=GeZ4`i*JtSO>L2N6XMdYLGkcQZGs6_aRD;!U+t6ufGqf7+8m<~{7&;8s z4durD#vR7J#%|+dW3REtILnl55}TwZj)`Ytn^H_Vlh%}OVwo~cueNtz_U4*orU1)F zmI;>emQj|emQO7oTfVToZy96x%p$W&tWs-@M`=(%>UJFWa5SRLVO-xgXiP(@kYEDuf%KdNJ24T=!QB{ z5$OTRL%K?8Cfy=kCtV|5B;6xjAYCD~lUgWUly=HJN-O0qztvSH#o0x9IAid!-AuN3PFbenSw|OPZ5ff z#cARKai(~aSRuBH+2TC0QEdGi#DBV&BbJME#4IsGyiTkZXNe_ZmDnJ*hy~(Yaf(n=UDB=6YH6)>hqO$( zU%FemPkK?hT{>GnOFmcrn|z);ME;|EzPwnzRbC>$C%-QrKOpZv{8%wsF+wp|F--A= z;yuMk#fOR^igy%mDc)3!Q+%NKM6pImRwgJZN|G{DnW5}el2ohJtJI-tsCuP(iF!d= zP?|WMm;RH+sL9osGzN`LlcTX{HfeHnLfuv!MhDX^(Q$NeUAT^>Tc(5Rf^|{4jk+}5 zN*!Lu)UDHn=|XgCbQB$3$JU{B5xN*%oGw|nTDM+zG_xwRCi76{;mlo`C0VYlEm;%v zpXoo=f2tp&H|lfrX8o(3-GS(B)m!wZ^d5beeqQ#%?B&_ZvKM79$PO@kZTQCUm0^}) zrr}$|G{bj>8HQ|w-H>B=-T2t>z|dppH9RtO8=e@R8J-)S8s0Eg8lM}V8DBF!H7+$7 zO@$__$z;km<(M3%Jd?zfYuaSmYMN!4XNj}?V3}_D*7BX@C(Dch`Td7Qmid+imftKt zT7oRUS|0MJSyHWXtIF!K9 zUOyL!3&)37p*BVkBfRKK=v(O9=q~gP^j-8#^l5Yl`UPeX_8I08<~8ga*r%8b?0M|D z*z>X8*u(g8{62gO{s?{#z6`$$e-yt1UyP3+)DVVk7(yOSeuw-Tc`$ht`Cal05`_GO zG@1OA)I)lk{93{bN-yP&gl81mfIRcriRUFPaz03+6@f*6~7lJNc#j9{wYKQgV~v#DF~iY7|7K zM5OEx9}!oH4~Y+oOT|0I`@~1Z)#CkPx41!kOng|pOH+cSoR3p@AHA;c7wj=(p%g^o4q-K2N`SK;mDn-l0FE zKdV2j_v#<(q1nONA=$gL=NaZ2elfgf9A+G9e8)J*IKue0aj4@o&X}{@!X{Two>7=R5RBb9Z?K6d2LM>}7%PmOD3d?#6%(Bw5 z&Jto-Yl*bLEeMO+s8Pe;HqgZ^EC&yYZLs&G<(AP5g0uJ^ms-ir^v)-!O(eg*<^gn*25SbMhDDiR7u| zkI0kAKj$-&&j?NlFe&Jin3S91F7Yk#S#gWFU3^Y_M%*dBCw?UMiZ6+;ikrnv z;=AH&;ydDt;wxf^?6LF>S+}%DI#f1XHca-W?5XrE*$e60ve#wNa)cZyUnfV)!{u-} zO1@q$lkbw3$-CuH#Ztv`MUWy?0aL71tWbmv$oUA7_{8|3F~In#aguSY z@eAVw;}qjW<9OpZ<0#`n<1o|Prgu%lO+T7$m~NUbn=YDKP1j6UOm|Hl(-~8zso8Ya z)Mh$mYB8NN(JcZ?szqdxStyod3&SF@C@e|~*FvyRElC!#1!oak5-n^?iiKohTKE>J zCEk)@)mW>nPp#8zLAH6eRW_JyoeggLF?9Ri;Q8-PSSjo(d=c^p>L}`V#GQz$$ODnR z=#Q|Yu^(bTz+S?($6k$XjlGY*i@$+y$M@p9@VD`I@N>zt$={NHB!5r-jy#|I6FHFl z3;Abq5P1%H7I_}|gM?8Dg$dk5PU0S_leU>wNxMa>qc_lx)9dN?=mE@$%qh$-nUk1P z2ju*3XA)W9xx7anrNAptig-ng0;`Bq zY*dt}Bx;#jq+Xu}OIw!~mIhBlq^Z&uXy$2lX?AM1Yf3f4GCs(7qMMNMUdE`5=eiFw z-p}|lV@$?784q=kj2_*PjCV6eXN=5vtQ(r~NcVQei@(A1pQpOv8Qr=O8E%)Fd= zDRa91TYb5Hul||-xjrg8Iy)viGW$UG!EC5uwPC$srD263)G*Wdz41HaH^#4wKNzPP zryGAVPBR`g)*6o(-#3jkjW7)}zh&+*4K|N7KQaZGhnU|rziIx+Jjy)OY_k|Fc@~RB zYst2xTTBCT|G&wSVKG}aTlAJ3i_wy6DYRHEcFTTCktNHLZz-@CtR}0`+GcIFUbkMe z&ah3lA#G8%2ph__-lnnr68tl`VbF&hg6)GYJAl<0rsIG`-=&{(>2~Y8F5FX(n zgazb<WV|F`KtBI`wfH|(_Ni>FY=Uf( zY@Fc%NIZjTL6XcKOOa()+NWoID74NG?skW-rYNa|N4Vi{YTdY~AS)?h~1ZK?1 z_#tCz#;+N3GiGG`obgr0j~U-&1Z8}e(U#eoc{Ovk{uljzeTyEGU6XwzyDA%QfEj)^ z{%TxoTxgtcoM-%HV1EC|Sa1B$^pWXf(`eH#rV!KD=1sKIGB2S^3Q1>D}$4}m zFfxq1jvPWBpYT~iQ35~FOFczBOFcu~NGqnzX6|5;SrpbfPB>>h2gyPF4SxUN0jGoNM=fYkbEQiQZ`xkl`KF;k?)sR%Ad%23Xvj3AyJ4Ge8q>V zOm&9ZsMe~})mdu2Iw~zXZHZ=O1~g-N#)^zJ8A~!2Wh~8Dma#Y^P=8gA&&FlDv)3As zhSkPU<67fN;~L{qs ze{Y^?{?+`0`Ml+X<)Y=B#cgS{G+UZ1mn4+cwKK(>C8m zuw~kEZNCN^LfYZi;R)+kA-$+?Wosf|i+&?|Q1n!605%JIGj;@FB;h?mEdfbJkiSSs zNfaas6Uj6WJ&qI0$>eQF`9%^W`B^eo@||RkFyngTc++R538oM;+zd4@H?K0U zFo&7fn^&4wo1a*EEO#tdEjKNXEUlJqON-^U<(lQ5<*wz5rPK1ja^KQ!xn((MZM5FA z-nYJK8)y5;_M`0w+XCAf+pEQ{m%S-AvW;jX*-pahVXKiF!>3_y#omtnfDlPWlTqX- z^2CJm)HdoV`cKSV%rYjPqvy%_8&eiYevC{WFa0e2XC{tA;B<401M>Sv zuZCeZ&%`tEE(=-&izQ1WOC?M>OU{wALyd)tqRin3K$-tRGmrt#1#=`sdl=$yjm^2QT?e_Ny#VW>uJ#Md}*$3VmWWHM=ew zZEzYe##m#Vagymn>qpk5wjt5u2~!eQN($8}8Oa%f44g6EINdbHIyGU1#HJ8tFwMKH zNi>3yW&YHPBjd?=R-SE{E!!qwlxvU6_QFG=3OJ7uYXf2f)&)cbYzT-6Km_0dPyrzU zn1HZ=hyZ*5IshIJ7k~^14ZsG#0wMzl0nq{L1L6b11A+sf0UHB|0ptKufG*(G*3RGC zkANQmKLUOP{0R6F@FUgFY1Tq#f4)Q5vJmfRT1jy%*FCY^klOO?*$&e|K zFCkMQUqQZxd;^&VnGX3DG6V7*WF}-5At8`Z$XZAk1O@@GQiXt@dVnAy z;KkmM2nhJ$BM2G-eg*-8fnXuAkT^&@1P1|+%pe;e;5C>K@Xo^S@6uy<-0pf9d~X z0O$VSpM_u3kANS6e}+J%JrGi1-)G+s>cf9ItH0~-1u}p7e}}+A`y%^d`x5(7`!f4- z`wII?`zrft`x-mc9&8V>huYVI^$4@W?Cb1s`+7UVj{M8|gxgW}2z#VG%8s^2+hgn) zJJud+kF&?yady0&VBY}rH`k0*0Y3tM z1pEm25%446N5GGO9|1oCegymo_!00U;77oZfFA)r0)7Pi2>223Bj88CkANQmKLUOP z{0R6F@FUk0*0Y3tM1pEm25%446N5GGO9|1oCegymo_!00U;77oZfFFT>4+N%x z@9_shU^(!dzB&-%$jSG8FSQ`2@Gsv_U752YXVG7HFXy<$$94Wm=K2%;?}5Yr)XSEC zt8Z~G&kcke=wFi+fd2PM<+*!u_vTjQ?#r#r-Je^Pdm#7VfcoE^^B|`u=b;aqM>)MY zPjVjrf4_JC`RdR616NN!0_StubFTa7XP|uA&uz_V%jxvdxB5AK_U`1|{!{CpkMOU! z&HqKub2%6Oka}~@{z3mMTmSd`d;PZW|BErM{R{qoHDbsAMW6r5o?qriz>k0*f&V@N zbP&}Ue?<0w^ken&*!?x9zvlMWN&WTjJ*a22%n=)Ko_x%X!8gWfB>*L&~wUhKWq+uhsRd!zS$Z%gmv z-Y31!dY|@g$t}(;$wmCjNE@9SlZ(m4=Emm6<;LgYa>==*Tw?CV+zq*eTztQm&wFXP z%zx_fzMP7GY5DiLl;!OFPdfW^D*qF2Z_b{6Ua7C%m9yhN>HKc<&vjvLQLZz0^FQ_P z&wBqgU7oZ1zct!_ZRLL|y$i>oNW=UJ4q*~dAQTb+A2_ek#1++(>lxwX0OS9}in?}+064?a`vNp_l@ZfDq;c9xxO z=h(S+o;}B&Yq#6;><)Xry}({*FS2j8JMCNS#r6{WR=dl-&A#1UYTsesX)m+yvhTK+ z+xPri{pZ8~4=d-N!~Zq{Rey<%|J(lf#~%m;!g68%@>&MX4bBbmN!R{Mo&Sjs>;8$A zP#^DR&JEx0TJujd{wE{&b^QqV5%446N5GGO9|1oCegymo_!00U;77oZfFA)r0)7Pi z2>223Bj88CkANQmKLUOP{0R6F@FUk0*0Y3tM1pEm25%446N5GGO9|1oCegymo z_!00U;77oZfFA)r0)7Pi2>22BcS9g3Z+>1NWC6&1X;BRHgj{yC0M0+sp~By3IMB(SIvR~%P;bv3YGQ9RG5F|TG(UPK>F%Zd zmik(*ysdd5HQVxb0p9k!(!8}bp*1`6%0O$!pR@uY%N;8mD;=vG%N$S#9$*(+gR2R4 zpuvdoptahu#k%N_vT9*{d6+iD&;b^>mB zO_@(tT64qE>F5Qr+YV<Fb3CrMGau z+wE=yD^%xp7oPI1R6}98`*h)McZK_q`+)mm;n~7c_fGfu!sCTy?t|_cx2JHgdx!gE z;V$=?!aZQGo&de-L2fRrc3&tw1~^CDweE9;mG13;u5vdO9(LCi9tHG&m0-^0&OZ6& z`u6%j$TDZJ69wA0>pSbOgLYq9;k;FUwSK)5>V!Kl0^SXfTk6+3uYmeOJ<_?_xz4!? z^tn{u3OG0G!<-?`YxM|cM}1rU8fUmO)Vb2R)HlXo{kQ}4&lDdh4umv;e7d-?@pz-B z@l<0qXw`$e+ppjhlKb~hd`MtY7EpKd%= z>?y7-ZfHCMG>)3N?>V?67?87y@LLc%@Kp6#wMPnm1IC&aVE1@n}KN%`H&TgvZW-c{ZWc#ki;%8SdNUVd_UC+PnGa31aLYy~I2wRbP*3-aC8Tdmhx zy8-oh@AcM)d!OyS(R#D>$=;`XyIOCz-T}IOX>;YH_JYcX?M0Q&%0NhWdm$)$+JQxo z10l4keVz2Gy`3N~ckbyd2Q`>aXHr#Pz57o2oj^!?>#jSDs>nk(yE?nTj;!`pA9z^x zaKmB3;l>_tCi2jEGzf|Uh{VCSfy8|I; z;L&AZ>tgYxev2UX0h_S?C^* zV{7r1;+EnzK*#%bJQ&Bf!wxqGwY=={d~Zo*Z#$S(9>O=v-|hUhu6EUfU0V+J!2Fv1 zKy$rgodfRk?Ya+%Re7rcH`-^TD(^tv!Mw^E1dtPe*NXuH`)d~FFUsHNo5Pa)1^rkC zLN?TPZrPzhahwH^R8{7I3zTVhge66^nxTEm~kX&o* z1m!1E9R(-rNb|Agn&u{O29KA`Ynk7&w|q}I z;%c8}P{q88`4tN*?zP@;T~P7T=2ozpF5fP>)ph9M!G}#?->&J$JluiwVY$?YOO+3$ zumV`Y+Jbcjq*}5MnSXfp52~y16hP!InEAc>4bJ=Zg#MZ0K#lLGZ~ZZ=qb?%Y1+}h? zp0;f@u47HfH?$0PL-W5^8o6kueAW|kcIub2Y^|`g6uE{%=7vqQqmN(WM@}UXtU<&UQJ}A8J+c88RHmAVsLx8p$ zWUK=Nv=e+tcl&hu#tDS11HI!Mv5uAbtMU_T*8~3$AomnLD(nSXBBye^gHfUXVSvitjXb_U}kA1Mg|z750zoz~YvD zzIpfATnu*79T5FqCOEJj4}AV}YVz&VK2B&JHm@PC9(Z&7PaXwAo&c{O7e4KuA;pIS zSWhtillCVEK(F0UfCn_8fKrfC8v&?<0()(2 zK@6Z+wb2FnwOBymK<-OX1-XBmAm$&`OWE(`P4^A=nxb3oJMLEZb@y#Iw5U(g;%)=$ z1+I4PWeqEeRy8~;yykvhxUy(b(L5l(;$B#^tSF@Ds=L{}py-1863|@?_)Ckp*=S*-u ztzXb!cdlu0I0GR}kilOx4f7l5fO=e??_A!%ajtAAawa-?PPQ|sA;-D6VMznand_wa zbo=y^oX>r`^yNt4RQtyHy#@RL?S)NGin~Ch=x%&a98~h4@lJ7X@$=#*fb+QcnQwPK zZ+uw%5VZT!{H6s>U>_IHYr0>&pak3#0Dc$HTHMsz_^h$Jcz(&_#;3(WO-q_`!0BDo zw6NrE@zcipK_+zOAkT&lT4t7sqqnmFv0YqIuXJ zmgin^i^~C|g`PxEwu2K>}m%ZFVj^(opGJm2JZJ=Oi!EZvdiu{)i3q@q4m3VUrq5Oc<}w_^GxZv(j@QgQij)C zO7UJSZ7tomvrp$rDbahU^nB^nQkwTnGuul7`mx?b??!J+Dbv^YLTOj&4dC~s(q>Rz z2btyF;7#ySz42bU_iSk#(7IfDx3seq=e-7`fsk9J9i?r6BKMEo$Ghp1fXLn41g=My zn`@g-Hn){sE4x_M+}vJvyt$#duK8kfbD6ifzWGww>E?4~Cz{VTp9i{N(b`7sca!dimC)nP@;!Sc%T zwJrP0SGPbxI~3$Y~hH9+fSTHQ}UE1tJ*uM7gV`_iHgaO&E@U0LP)j1 zJlt8`$*nrn$*cN(!~>lNJ6TmZRU99u3f$R34}!bgJA3Zzzq1eA*Y3Sj3CcgGs6+R< z?svhe!M$+Z+rHManm!)a!Eu1URq`Y9kJg~_kN9}Zf+7$h z3w=?NUcmB2&;rn6^vBYdw(h#Yd3UcZdf5VZ_aN3RZCci}sARG46zSp=@|AP3dKi`ErA1e^yT-*fl4yWRKQPulFrd+wp18w{=GFC4 zy+F(94D09rZh4DyEr_kaqOSx`W}NVb2tbE5tZzUzpc>Wz8rBfp5YkZW41{cTmN-Kj z!uxf9w*l_Dfb1U$+7Jq2Z%EU+rq!ShZi0exEy(buB_+#C`t;T`g@JZoT2`_gP%h^l z4-C|+Kwet1vS0R6W1BA~cDnAm4tTbD_IbKo`vK=L$TdDmm1l>i0#LP{W1dP+xo5j4 z-|O-`bnWtVyY9J)J%>CyeR`#yBcA&pUer*<0j&T$&50C#Ah$pX7PFOAA5E?sa&%-UooQ-Mh_O;=NzmQ~IcMMU&I} zu=Ihe*vs>}yjy`@Dad!gj@kn1|CkEA*P9=d^_1N!yViW8xee%amUWk1X}(+50qEOh zx5_%3@08sJ^v&j*zUT(-5XIAbyggU5;ppYQeU^T0G?uKF#Qs_!f8z8qg=p<9r-&r}TSW zv7&8V1*~FKTL_3ot3eKK3$FktwGs)+8xf$(|EE_YQ;m%e=_-?j+dH!B`zP|e=q3o_`Gz7_t78M`$u5SFO)Zz)Z3R0Dw%6{db@og9EX5U(07`4>me!GrLhBaR zt?)&h*rG*sn4*<+(7G5P4X#@bxT`=;D8d!3tqTDZv1milvN}T1lDfrp_@ekCO3}t5 zEYMvIWaR*bDkrI7w==FG2CQjfLo_J&IyW>_Iu8I@g_GQ{AJniCS_1}1!2L_Z#s*45 zQbR%mp@Hb*#5Wvr;u~-c)P_AyY{NmIy$|HyQ+P=d5wp__tB zkbt+gBm{6`nnFv~`SjqRMEEFhLi%e|Q$+tdf~x_bJf2?HLGMY=HQ&kwZ3A~MfO_tF z?7HQ-;JFOw1>0_Tu6Ulf76RFIPn%EgwCAShlII+t8$F$#X3udz&EMAIx$U{=IpI0u zX#nkcK>xhQ>v`&G0<8|uGq4}ddQJfvL;zp;``m(d>;(~Lx3|W-&sz(q`8!@pj(89K zDH2tCk9yspebrO%U2*~VwWGmX=B)yp!#=HfI~MM!^B(u^@$T}q%Y9{~x5B#!*gNKH z?FZ!n?@sUI=10x*cLnWQaG|$(;f0_JJb1eqQ#h>}lDP=6M%-%jWF@S1S;u zo;Tlbe%k!FZ2pCZ%}>e}fsy~5h%HyjTgtDNvs%b4v=%}OvxU*ZX-R6iSWaze1!r$# z%Oy~JB=?+6BENC%=L6x4?+!$FDcSPROg&cdqWou1B< zo$EoXpb9+c?QG~g-Fd1rAJC1R;F(MRUDw+Fd!hq(9(O(IdfFB4i(4pAE_m>N*m)1G z#G0iI^!~FuI%C#xlB3S(m~+nA|6(8~K@cQIm7D|w1Ox;IkRYO{nfRdw%;GqBz5F>XTG&AanESBY|u?+m*W$SIS%u3Zwzsh=g!A$o-r z5#@j)K%~vl%Dr1m3$%IKS42m-XyMD9>;ZUO9(!NKt>NcRtFbRJSZ5=A3_WN{4>bCL zXHM%7cY54MNOSr{%sfwCATOa7Qw}k^)F2_ES!QU(+--nG+A?jGwnST_tq@OsdEyB} z$2ex_8Apsk`;z5FHf$fV_aPFxh-m0$_pEWfi80C^CNvwfkFZCvr$5*?*i~dD z?nlB_&A|D??eMU41S{@|F_h|@1~>D7mU`cy_d>Hdz>D}PHf5~2~ zaSXlH2Cd=9pfPAEN^mNJilV0I3?~K+MGyX;Wf=a@Yw9%Z&<0F>rVi7HY1}kq>Nb&R zgC;Vq$JB57Zt60PnJ8Eh74X9}YTBmlg8FZTVcE6NEjt#HWy7*&!R^RGv#g-DF(?)) zYO-bBvTCt1wk@0Ba1*nzi29%NO|cOzfN}d6dlL4VW={db3XsjPr|oRZEcl6X55R`p>9hs)-D&akt?M2=TDg_3 z4({*Mr_)aE<7xZr9C!!BxHqoES@tY?_K_bt%bj`8uFg_tm+H><m6p)NXuzekt?2Yh<6^ zU=UEd2#YW5(n&NDl~iuk5ivE7oox*)?k?>v@A?o0$kT{*j^$@#JLe{Ay3>ztZK7a+AqtSax-n zMcO3$^&40phgMzok6kv&#c0D5SFr9?z&QZt55;D%81xjg!D_H$^~bMStlYLw@YklosZ2(=cNm=Dd`+?-&}GgIh~wMP9@8;58}y5$GTw&nT8_#x0nI?H=Zx4X z+!c1u;T0TG0Bbi=99XZ!;zirz;X2_h$S{OQ)Co6s1G_=UxTHP!S5UtVxfA_O#C$WR zS<@V{;Q>uZn>LAFE#qTI;c2V(RrtXQEHT1ubd7SGURU4wy4$_P4lBZPto0XmaY4Em zGsx$YTqRbdJNw()F~7_*#x0)JWBD zhl{XHqdtT+x(rszsli6*ETt`(7EKb`Ax%tMz}z@77;?)6~;3q zt0y?i26Zr4~$MBgjM7Q4XMX4@>A_B4aczGmbZIR=Ss zw@}zA%%UcG{r$|psYULtoeZC$+No?d`?HH_-?1-qKf*^@YzCW+mQSEbsF`e^)Kp$Z*l!_^}`d_xjWneez%LxeK`B-+UAnDo7^w1 zUe|!D&Wm%!_4{m#OXV`Tov!<{9@iT8@vPtVbk>fi_hNLbtIb6rW+rpLyBORq*DkjM zZ8Yv6zmNY5e)kRB#=kwgtic$6ivPy@Q8>YW=bhmX1ggECg(LiNehr>l>wWK?<9|Us z)q9)0Z@oW2wFqbV72XeM?G#S)-wT^S&GW0g&u63jO3)2}CgCUH5Wf-Bhu2sfhK}XZ zA=HGY;q$`*HR5?ZFiH6T81Q%W91V26_ID7O?VIq8cqX7F=r-X%N< zJH`aPoP6m)mu{i|A~+IiYHS0Tfp+lHrKDL-iBY69>28cA-HENo)?!9EBet5nxU%8h zV;iG30pTlXEZ+jPp5!Y-;8v1rNrBQS-&Z>1Lghx%`ufK7^2{=};;wM~kFU;&tCL(5 zBXNqVV^^0~2g=A*{K}Ry&l!NtIb&{!_)0XY8PN=DdbIV$UTsAoq&3}MXyX&m;LH#3;fwYx3EVz zA6N`5V6Qx|raN3GK10onv0;-_tU{!0RUay`=GRjtPUIY($xgG;9JCvT!{Q_&bkDxW z=5QDJAH5Ou+}w=>S^Sd{z{(!|91&f zQk0*Rydh(_HN+`*cxH%l1018|3|T{zQZ!sroU|b28nT4Jk2Pi~SB8S&f)WA!6Vjw1 z1)QNIC|8uUAx#NT&M8T>{cj~qlbeL5b6SqJZxWlNCWR>lt4U0J(@&ZRc~WWef|r@1 zvr;G?UZ(C3ejA&1T9ZHwOrB!CLb+83!?psmZ7C-FXFM|AFyofr46dEae#`V&LY8Mn(Bij5Eip@p@rzN(+-F}{9vD?j?`wv9 zV({2^nAvR!SX`Df%ejSTf5*hmSt6E8%kBUA%oj~mY`I;*R;I=TSa4z~;0 z`*wp}W!Kn`3CX{&d?@t}out82O*dn5!QxtH@WQ-gfVhcPX&J zAM;Ln*ZCdZ3GcXfli%W9;qRb*i$8*%U0xD@+B@u>@v`^~{-AdNvOaI8cNaaj`G@we z;Dv!!?;4-ZUqLLA`4oPecgnjQ==Og1()c~zALxNMAN2pvWtzy&>j7@yAV3d{3nhUO z;VNcY3-k)dgu8)B;gpaBo)-`WM$xxlxD(h2hy&CBEwCBj2N(fCfQ9w}p*K7%926b~ z_5w`sSV7>km=l-~QoxZ33BHaB`-Iu>et->r`&ITwuO#w^FB}8D3V#$c`KfRtGIzN& zh_4~_hku68!-;USI34aKR)sIx;b{1iSRCUZ>*T|^@E0*FwkKsHH;2L(;XpVN4u)^S z@5Nl{2XPB#3uB%P0DnP5U@m&ri}_M|@*pON3Blp(ZcKpLBvKLZp_CKj#iTKnQ~_>3 z_RY(a9>(_2Pc0S2n#4lsB{7c}t#YYSDw9e<9Y`gyeW?c2Kg*fiE2kwR@({A4TON=z zl76`h^f`cX+g~Oj!XG zmz(S2T9C+2xi;`PeZ6Kb=hc(Bd>((nyX@WL&v}>N4fB8*!k49lUwsu9!%?|bDvRl) zM^Z&h9#h7+ghqSG+*S5UtJEoLiFL*ZearK&ym}R%zt5Lpma|+`8!W}qeuS)b#`SPl zy=&fC;cd88%)?xXT@eXBNK>0|ZdhuWUTC@Q74YYvhbpEfyeWUxrOw~~#2gya4XqAq zPhs81Y=_-ux7$zHR{NiI`?=>_sw=?taW|mHrdLj^qg~uaM8Wly7rRwos4FxV@ufju zkD2h)-9u==CbNk50}gqQoYiOa_l5%Hm*LUyV0gk=_EL&8y-8=XKvTSP(eN86&0sn* znN9b!H}n&e*7Qs>no2a2>5=wCvze@>W78e&mi8Mx|1LSpEp-3DY+_znu0effHZb#+ z_soxkE;o=gGVd+T;65=kmV)KZlC`8E#qU;@B2oXD%f{BTO>FElzy%8!*iK*zIGhf^ zZo8SF|MX|NLR^N6$qS zj{{_{l)vNMf=mY4F6wew!9FPhi^3)0f>0aK1eAd_!h_TS3E^c&0aajGI4@ik>RxkI z2lnDVTngWXzrE(B@;u+gy4XqVgoyWJsXnHS8Kg(peZ5ozd>l*4<8nz-439ZX@__|_ za!DY*FXcbw`^lL6ASp~r3Au>Cg{zl7$4W$3?nvp&`E%XsNlgQMc7nLueJp;0Ck$$_ zBgISLP|2dB-!tyvVemFCnMb}s#Mw<>n0EFhEQI$<{6?bSEBU5<8Z59bd<;Jj*(<%f zPj;9p>G)Lz@L+kg;8tfpvpd*M?7}IVL!6p%%%O%|RQ!{`YUo#3M(Ek29@1Xnc~X*$ zBq7O3V)!F=0seTW7m$U7Uta6;`Wt;gf2-${bNZtGWo2dj+whz6YmVqsL7NQ^<5?`bxhveWW*|PYiJoHTg|Wlh0HS{sZ70J!lG;Txj`351ZVk7Wz+9 z737U{uPI{s0;-1I0DOTS|Gj*-b}&bnxSd-Yt-Z{8>vv|Ab%6QF`fRDN{u%Yo`pfds z+GFizR$JR3{cY*8c3bePR&(=X^JF|y5!Tic>!#w5k);h}UV|H5KSjU+|%sOJ8 zG3Ezrt+k)oVf_OB2ea2&WBtZ#w>De5m@U>;=96WZ8D)1e-&>okmE|6QR$^q!>#TpY z`Oo#0J;l!05nJ{UI}I=JfsWeKz+QXN?s|>R8+#U#oISw)$&P`F+w=AW>WKZ^9FeVf)c9WWQiv+ke_G?3e5?q+a&<>r?)- zhW{?r!b|xsf$I?UiAx78cgb8CuF7R|?SZqqG%lA*@4Dh1yAs?dZh;FQ<=%3+XtTIZ zT_%?k6mIJ-p3C7N;`>T@qK3 zd*J%Xz2;`Q3RjS=^rm0O{=2R({0&+)Ua!~UbtA6qe3{q5HzP8SyiTu$&+xjuTK>NG zn16&;4}j&hdTm}kU&oiAmyLe_Z1HyGf0t$eZ9;WhAuUcOi7 zHS;xmFaN}Qj2?d%ruT$@>Xmxs<#Aqvm+p1)U3{MR(5v#E@)*Mk<*zl`~NbeTH) ztBw5^RS1xgMe_lF;3D8f-n(Vrqb3YKX$X8F6+M`|O8l}I&kTVzAnC9aHgg06|Q zMEb>@$ob#Fy@`ASo)UkI^h74ab&((9hDdv4Nc=7`Chie8Mczi9kXKtH!{YA9@9+Rd zeMbL5aaH6)q%raybho%GGAV8b)eFF{z~L{EKJmDCR9q4H8W|zZmR|8EqOIKC@fY<+ zR~Jqed(0dQ$AU34aq`4sr?E4sA9DCc%olS>v!K(lK+HnOBC*SuU3wOC#tbow)QvHT zm`7@iWnvexc;YB&D>l)gR(2%W$H7(uk^|{nc|gAS#GPzJY1PT{kpop zaws3Kj7p30ZRYN(8Z%S^%B4@8$PKGU)Gu7GI-Wz$%w6UN)xlgOHvoAEl9w{1?gt;p zg>$i2*~h~BLMu-9uZ1s#X4JF9DgV;@Lt#c^R(>u_YuXB*3QdKJ*D+J*(^&Xg#5cTR zOJNwdfcE0I;+J9@B%c8<#eUmbOlV_T>+K8gKyA6T-NwEc)SbT26)1Uz_hq8G7y;&_ecEjDxWk@cx)&c zOkNQC_kg`^$T*dFYsihN+Y3v&?5=`zNUo%Qqko4U_^par#*cX7OWA*oYkT}rKBms$ zh9V~JB56|xJq4`?tW(TE=sk^bPxdT3gR>^+I(G$Jeq?nYk=cXZus6sLc?0|l==_Vw zAA^yh$S|VuCRT`@ORrE3fE9*ZmAoj>jnpPs ztp)JO*i8Ls{7U_1Y{Sj*8=wKwCTa)p7iuf`Dsv6>2epOz-dImOnilE9^g;R%eSuzMo~A#TewilebMz-uJ$fxLS1_WFUI)6#d~a$tzcG)~ zi>5L927MMS1=E6cnZ8c1Fju3;CVh!MLhpjSA8=>troV?YZ_1f|o32f3^jr2k{n^xm zHZr`sTpH2-cUiY?VgGimOTc(@veK%4W5xyGz>u$Uw(%erQrBiir;$0l>zx@=vw zk}%hXb%Qx=rJ{{Nw68)&WlmV>%w;BpSS5t`^`&SB?7}ujIMIgZ`>bw?Yv5N z%Js{YbG>u_;8pWFctuyib>sTX%epeIT3*6c?XKrtyM{4$FE8%u;&t){dH1d!-Y3U{ ztD9HhuHxOgT6sy=SM>P8YveWX65h9%ALlWV-JTGoO=$bSlnTK&UY397eL{q%ylH-d zU+2s4ulZN}TYi)8ov%E{wfB)<W>ukNTcpDJakN=>6<#@WuHbeFZ!*4`}t}_!YjQ_t{$` zsPa|%^4_F)D-b-SgAAIk9pNO{qw$dx_8{(<> zB{$d|tPaYMpSyx}!FpuPW8rX6E&KuMZSX`W7k&!X1{;EXL6LAY*c(&{TZ1Mdn;V6? zm#iK<6t)B#gYChApcxX0@C(K^1+}0x!Vkf3!Tw-P@MBOa{2tT`mBRNyg|I64IXD!2 z=I@EW2FD|9!NK5>usJ9e8iaZ2JB;oGluO5J{h!xCkFdlWk=@9)7^h)`1H2@ji0nnU z;+e<}POQ1eeuNWQ5O0Y;$Jycy@f2k2$c~s15k(dvo8a)?9$`k-F%n+~B8%dAF_oZK zBTJEGwDSPMh#;~mK8$RNDQKIHJjPZaT^2LNH1V346q%3E#gxddm@J+{J1w#mnT?Rd z+z3Ci7NMf&iZ~=CM;>s#v%vk&vKV<6e;J4`xdW^zlo>Nw+-BL>|^{xyfa=C&qDHdxk=)lsCbsYNu`q& zic+#x@m6u0Y|i{jR;C`4$>e?VU8*|uTV9oVr>IxJD*?~RYQ+P_Ws(Kp-^nUPrQ%8c zMsZ!{VpqvrvLaPXrjqY7Z&TUi6QnQYV!Ho@vc^l|E%y`7QG)a}N2} zOiSi_CITv;yik70Tq=XgnDR{7mcdsI08Z~*8PBMTxjRr(>O$@&mnCF($y{z)od!Lj zzRyjnuX35(b#6|L+Xnz~ms{3!6$T0`nvTMvW==CySi*gCUh|{SQ|K-96$T6VtFc^X zVL{Vh7%p^!E0@mVsJ6Q}rX4PJ6+4P}n=1Ae2a5g0q2hONBig>=U~#0_Q*_>*-k#lh zZ*l*)_1wBpC$%p#z@Kz!;x_v8E_s)_ThSqhlrBs79rC`YW8LrFv+r;3TaN~gb{@tb z@ZImh_F#XwCGJP%8IH*nhI0J_Cw>>s?_NL`=x%BcsF%`a{$_45e=>i0JsEd#T9(T; zQGYe>&_A0$n78PyX#Z#?(c549K?f^-2>>7#UQbuV4R{Wd$K*2)nEOngl?$HB-m&hOM*SW=|7V%ty(hB#2X`atHg~Xraq?{6m_Y_R8y)p)uQ;Ss7ZZIeM~hg z8WkT>?^ESIpA?@`P3Zj|(46|9Xn^!f>a(IX)t34~%#u)Ml^vO0#CCTkrA#X0${(Q1 z5x_0T%#`#|{0F0ord;SpMKBY;iUHIKVP zzF!!xCs!Iy$OF`VY9F;55nV2HJd;8Hj`$Q?vA0$+Q-b=CDYZ(V$F^h3vFZ5CL0)qI za8L0%++FTZf@#D7{9G{R8};EG%Qpf%?jr|DK^mS;4N`)KVm+RJ5)q4!BXiir`S=4g zX-|D4c4@Y-p_wU67bXi+g|v3On7u2(8c)!Wq(3H+vBGkBYj|gPq44#G(6$%2$H=4) z7>B5R#zE?kv7eB4ndR0_b3fL=!fN*D1Lhvky?_oghyKINruTvF2H+dKRmPNKWjd<@ z>(m02Rw+|sRe}0vp*l#gF~!lwY2~zVb{#aw7tU7>*)inaanRB7r}Vl95#a;wN#6>r z0BeBjb5Ho@2^-Dvdfff)1<ti9O|#HQNBRTFy))^&HHA3 zErMm=XF&*2iFE~;K{{+35r&0q)Qq4ZA`xE@ZCG)T1DQEuj6A~1Qn4wrNJLI~dz7$`Muf*5mTSR+Tsw35zYE^ts^`yE}Kd?9bnSso;5^qe(z6@>~>gU|D zdJ|r~rJ2x97AJ~<+uYr%?q?}cN|sJYN7i=EB5%~KCsFjjv3qzoeBH5e?rK#>&6~a2#)64_I(qOeI(y^K@X(80;;b~u;E+t z?f6!GU4nJru8;0(7yJ-(2s&RqqxH4MDK8WTe+nhoZ!SOzC>LIEACxR84vK<@K|zoY zP9BWGKMp{pgqOm!@CsZ)7${qs9?X10-t7a`hPp%X zUD2N!2GW{S%3%n&GirO8+27Yc9kxOWw+fwwj9@@wjf z{M&p@ezAZZ0lbtQ&D<+Jsr@6%Xs_?Cv^RJ8yTYAK$GbO>Ce2cZ%(1~!1UnVGnl;`2 zy%FD5rp(>jYys947y+ycf=D>6E?8-tiGJlWMjfY48YhS-I-t**r_D3wKN^;6pVd$3Y-H;33F`-Mc)}>*@vt0|GWyh?wwEUS(x2Bh&@6LM`+zm$L{vUMU;J z?v=|N_K2(@5og}I?vyk~=tbpuBO1aoQ^sjR>v^+?en>Bm5E8gdS(!GbnQ4Kp=Y;kF ztLZPjHPCRFGXh;1JU!@1&N#>5&^g99qnrWGiR0Lzbxff3$T0{!1i)X;@wVLCZWeFd zz3JX{@3=P*p)?*HD>?9u2}T8bzF}B;-#0Gc`z8cj-;iKLAi#QgJ`SJgeBpf&>6G`4M9uL94rcLK~wNFXbj#8bHZ!Hkp9&s`05@x7Kb87;`4|O>plru zgF$%6iTENCi1>&I;>HDWVSGQ%i|@s&WN&4)vN{<*UM=IqYh+sSLHwQU<@w{V>{x0p zHIbT4O{KaOGlZpk;8neV>C_~_m;2r;=ZOd@DVH(}nMHzrP`=F4gh<&^zX!%$P~Dv0 zR5#{7fU74Y6wPvhs+mHRG~}mWVh4hE*Cf0hAPX>qR_uac zO5h?H$TbGs*^Co-6A;s3F{YDw$|Spujwxav*gO&}kKdhqGqAVNHw}!NWw2f*iHqWg zaWN4qWf|_J(E1~x6J{(<auysETu1+W%Lzzbj<2!`j`o8+#15Of`pfPfy35_HEPB8V&;YQoOx*t z5H00(SshM?-C=|0o&w6n<#0PJpv`~<&LVX5I2@q&V5>975@-HZYkJvh0Sq_O&33cg zJhybqHOr*&CYcQMhgW~zz@BXZHdBkK)znIADK)4V zQVb}TQ){Vp$cJJ3H>w@@!IN?=^Q^2;m7nulxt&?h{8DaZRx_KK4Z^ou^7yQ--d5w^ z%L8z8g5Rta$`lRxXQi+TdcL?+TqrIUFW}4g)k~W$@o}px>F)0z?gx*&q%d|!18YTL z6CY^`9xSKh`=T{zT_)_W^(_c$M3t)D%z9zD=zq<>Tjo{sx_Q&QVO}#U(Ep`Gm<8;8 z#+m}gw>tt~GGolVHD}FQ)7C5NjWzn0NBkMJj_2%hb~s^&-{HmnZ*dOYtDK-C;<$8N zIDC$6PRJ2(tZ-ru5+~}|;GCn+CT9(!{%1MlAp(h5+jk4xLQo?2fm;lz1T>#$`PWe= zzD0oz>(>G7fFs{AF#OeL@fm$0-jYD?Gx?SUW}ktO|2;Yjixqv#xq<)K z#kq)6d=y!F)&@qVVD!r!)2E!4Ykb*5B4&u)-BHL&V;L^$DDSumJRT+&YR59w+B0kJ{sKAm8V3f%%+* zBjd`t8O5Yx3K{iJ5x}ndnR*o;^+AT0;iAS{aGtKF zs%fzEOCc911(pUruGuN>7PoN<-`_pJ@;K{AwT3xZnq)qr>*!>{)^BV%=Cd_VSoeT) z@3?b3IfR^&kSBwgj63|6iW;F4QUdf%U%)Rfhg(P#^V+ zed2~_BP`G(>&EH?DQDajKaKNKywpKzAM2ZYU6(M^pb}*ciIp(aOsryoxWm|Wq1Sv} zp0&dEXYO+S+aY@OfHEiEKP3K_o?St}w<9?JOS3BIb1rU*2L54td{NYrU=btvm`=g^ z3t0Cxv(omKnE#El(s_uP-#KfXRnC_uRy*H1pB-XOt+V1)f;TMp5%1isfkj;IV_+4) z<_@^+Zi`z7S`9dLd)!*ynfrw2bz9wTx6kcxo83lO68B32hyK#^@|C*q#eEck$sP8Q z1VJBD5b-etQ6Eb{6|e;~cp@D@2E_gv`J!Ww=mXaJIaCvB3{{8vup9NSdr=$e1=k#U zA8H6Sh3Z0K@uyIi=;Lea%jg%}iM{$MZUat;-vfV$UWi+wU!twinD|rlBP93@T^tgB zjz+}o(eL2DMw_Ei!nPxLO)a-~5WW7M)f?}{-uvO}eT0V($bz8V@woUL^-DPe)h!w( z+WUbAWkbM=ia^{G9|h(6t0yvCN&?Tpd6$}3$WqG+O-h^+rjAk{RVxa0N|ahsNKhtwZJ$yRoHu5gq240Bp-||fG z86O88nerukVMzBt`yZ13;-6pPZT+Gzp#f1#Xb|35E=h4u^hdNini8kQUH|Z!5V6}A zz+Qr;IoEE2y^Tm0>(Q)*gBhE+X2WP8O$&qqY|Hw#rcM`S`2z~-v zd2XJQ=jEO8PGP}_I|kXM+s2E#b8b5?>b`Pk+zwvK?cteuE?&ZI;-%38ryqf_lfHtF zCwTDP`Le!}k1xoHQ@Hf5#!Ie)Uu<(Qe zDfZ@185VVhx^%8orwNMpOt7qJQb9W00(Fg+N<@xJ=h0@uL@e{r~v?ZUGA!G0mKE7>In~ z<30I)`(8$eQlqLcvEvf#t+;Sl*w$uX|F@-kU7exaM^9fM?#WF=w(fR*cXl~Dokq?N zX9x21H8RGt?~Q*XG#Z)|O^Jp>W1*qY1fus1{(tjn(JCToU3MMcfZx*;k<>*hoVv_J zGm%#>lfX+3HPXVn(t}QXZzUV)270sYiMScQxAo!)CQiZK^Liqj^KRWY?xNd|tXAoN z>#y+RPA8fOjfW;fv!WRy&lloF#MGwjCLT@E6)W)1<-9~AE66lb&0aBkd!x0HKiGaV z2b>m8zq1cBn_-n-SjTVoox9`?@b29~-jn;m{pb$iIdXvlIqV&tR4!AYY2>5L=vzsJ zq*AgLUB~)1q7QiDV|+_iir>ZWVMRqQ@7Toipfka%>z2^sMk)K&LmJ zXXraaWXvsSunp_774cLInIQ3M*&KEe@k5?7(#>yKEtr4!)rzN_A*YM*1nje?+$+MX z^t=NV#@sKZ+F#?Z@~g1&a+!x^7XVe*)1Byc^d0Iy7O!S>Pe+%Y~%d)w!`USRH>mxg=5x7Dd&V(L<)`&&Xb)g<)RASKlS$5`1so zxCp#LT`;auSE>$CNMs$&h=8d?3e4qH31Cw2Z_+dI~P?W?WJR?TW)b=#U* zO)UHlVXFuJVSCT2Vhs{K|IF%xZKIqsj+-;;408OOal-Ba&X{w=Iq8gWE;zODrYYxy z(?jfnmvfFf1PBxSpLzb&?>(2;mnu&UcBmHc!PDreN8RN4=!x-?ylT+RfCPHQc@3UA z&{5vczxMLaJST#WcrN<-4X^u(JG*}iUZfYiCt4c(I)PE}!GA1h^4Ca?1dV=^Kr7Jv z)f+n!T0s9bz+7lMw2XQ-v?kgSZGc(?Y!WfJF4_#Oh?Yewp$(B4qt`?8p;ghAXq#v) z>(D5v#f~>g$naixM3fS(m+VFxB=jgPN`mNN&}}dO2ny3y_Mg{Z|2K7s0-i=at*(@tKEkW=WnY@WZm0`cMoSe zAH3B=|Kxu!SySaQesD3)CFe6?P5d=|>YV%mUV!TIE|z;+)cjA#`s@KQo#t6(SeNpeBvnn!FOiMeM9 z|4PAkesYqWG~q)tgsj!`#q-sZ=4E(Syw9F2uLYjb=5L2~-~43k76m{GQOg)Q?4tfm z*u6ecov2GRBx(~ic=B!PE>%kL6#~U|CZ8$5Mmza!SVjxG=n5KO5>D%bq7b&JF6By+ z`!IO}k+-3WV6APQ?|5FtQN7`11r3HKLzMj9&`9vx#vS9@U%%~c8MiQQo4RgXHLe&p zjGNR=yY5)WZSW=5!5*F zw5^NvjrEz;#`?kR{t0Nho{>!;92oJ@e1(uPS0=NGjG^4 zIp6;-~vvf?@xT zf5gA!j|k@cA;jFgzY{*Y3qVW>w)_izrhnRhg81P05sy`_>70mis{xN^Qe+vEj z{5^h~faD+bQ^C>vXM%vhD+miV{XW5>e-JW<;D>+P&+rfUF9du38Av7oc0sJ1AN>j7 zW&gRrEeHynf=j`Qf5^Y)@AZ?>=bwfBZ+zE3_+#i72(^ezs0|@Oh$hm7ydhPHD>@4) zLQ#P=qzt)3dm<`gogU($mocOXorjJ>2OxO8AwFm({!0mg=py6{SuhU2B80>tx`-K~h_oSANKMFu zAwN;$yAno}%l<3>!f`^b5IfW@aS~^Pn!wDcA=)O9M0L^c5_z;;!ik!r?5GNDETUZz zJ&7Jg#Zf_YA3Q&L9Cbvc(Qgub`vq?VbV?4Qdr@Vy2QtL1EEe$>DqK<`fK`g`a}9qAy&v0kEzzQOwmM)Zy+#!+e?4WzR6Z) zKV{!#e`PAN$nZFOiLK$fU7xMV-ey{|yXb|pMODhw zV$7FpL-u!uqS{e4W}h=(v-g>|+4tGU%u@#YtG>(7R9f{WF`_(*tU6Ke=Mjnd-8?Gn=5E#BSYP35+D z`|I}cR#d#jf5H8Hdvkja>Cx*hw>P_<^odD6orPJF%DU_LP)o70$uW~123Pap%2u*O)UEGog5Wq*p+sd6fa z6Q*KM?X2FDI*s7WP8smqJ&RNClsJ`6gY(F#fuwfNI&ddWv9oHg za_`Tajr$}|!#-^2VR&lytM@lOG!MnI>tT9W9*$?vv*D@Q-}Y>I*q)mG9Z%iBL&`W-Cx2xAOg20q$ZUnV;*w5*+w*0r1ScE@%Co-M_ST4$hR3fz~8p?+>BAG}kx(aDUkx(p@3#EyC zSd1p45~6>3u2D%KT8IXt1IS-~WTDIGd2~qPj$TKHCD~{$>WNNB;*eiN6Hy=Pn`k;3 zi@KsCk}GiIl00xKIw<*xIuh-dc%$KHCK>{Vw*>;fXsnVYL%f6}!A-Cd^n_YQO^ivl z5=t2*p^z~Xw8UY8pI|5U6A~FCAx~^4b`s)*RHjJCWy-`};w*ZQ;3Px|!E5dzCk|z@ zgjlwlkjeVf!i4l6IjJWtk|`Bq=^^;fK)O3U^_nlV$Sxh};q*wlEBzxq4ry*!TnTSkdQET#6aKStL-#beM~K;>Q4UBw-~HfZ18 zJ!tQ>CGESrkELeB^83=8yAP%6yC%>NB~PhT^6TzPkKh#dk2?9i?EV+N*nc~ke4sp# zAE*y8GTnwR#ZDU$OVAxYTyv+qkCVq)478LB*Yh4Rq4ul%H}GklNR`mw%+Ue}4HZwi z1meA1n6?a^ZDZLckTvX>@yuDb=XRcg@;e<)r?Y+!8Upa^n6qim=kz#T&W63lJ@4z& z@dmWdL*%vWt36-#wV;rFJfHS8p!PkV_Z1$AN9GZF2iQE>Y&k!tmuMTO9P=q6MQojp7t2Cay` zW06I49n$&@q7zXmbQjW#jH27n5n4=t#U`E=otKoKRC!r(i4!!sD0y>Pirz;jCDV}q zj^0LRB{PzT=yUWbIwyG~;?3fpBF3l_`os}zYEBqrx`YN1Vgl%7#>BDgM5ayXWroC2 z;y7`VSRnetuhZ*@27_WLy@L8gF_T_Ey_`N$=oM?}x%7N`H9ebNOdl&|;mtEyp=v36 zNSuuas=2IKHBb2XLUtLo2y%D6th*Q3nRgNNY2K4R%P(df1ZUP<6>^2^LaLB1WDEI% zMPt$!HJL)PU?}e4lrj=$R^8n%ZNuG@w)U?6jtXDzu&_i?fWLr55hj(``=K12N(zq+dvsTokW}7(?Qhl4seqLASV4)2M>bZ zu=u5@?!xDPCcHo35BlGt{Q|3s0HS`6-|fHjS004@A@FYwehF$0{Qh&l7hDA~(^GlZ z1hp3-k&lQ07jR7E26l+TqM+yklt*+fa*9qxA1<0MsxInbp@`_?MO5S^M$~|BzG%33 zf6;gm5LI8C5mH#_a#^w_L9T!;Ns^|^4bWCuGq_zz!zCG9xvZe}i`IcxC7Y6M$&!R3 z*#WmDsYlP3;zmR{UNe;!wL9UHMH2pmQ5H=E5-wQ~yL2iGCoHm1!j-_E>7||MWdoc6 zPSJXnFv&a#Z^D=G$j%cNiA%`*GKYecW~8a<%``K;g{Y$d%nGN1g&MlT1HFn<1t(2Q z+Z5YrpJFGyoAxWt6n4yNQS7D9(Zi)+r|k;2!UI~P+Rd`E^eht|t5lJI8Cj`{lGUnq zveYamOHR|W+gX`vD=Sy+WfdxRR;}7ZFV+9o-kEnr?X3I$zO$=>C@LT`$UMj>0)l`7 zzLx}4rpDHWK-+fHQ(6U4w9!Th5HQezgieQahIU%_+X438zx&5NcinT&UhAAwtJYIf zDwV3w^E_3Rv;+M1NrForCHIr@~A(;1+5G4)x30mx)o^`WHSB6KCPa% zBJsaX;0acnRjd*3V@3Q;VLu*$^{|0NG8-0gjzMRLJB@_u0o~@;A?>4M@K7qfgoNy&x z<2gz)N4u|D<1XpB^g`NM zT1YUk_LHQVOeU{jv{UKHi9W2A{f-)Et#dEB8~ud-+FUKJCReNLwyPOq#5tZh!U&HS zZ!m?7yjjc?F{O;ODQ*@p*O@%#aI=KD$>cN2Vq#HVOya3WixT2PNR>U7609RL9*1Wd zV<|?y6mk@ou>!=s$8p|!h*yF`@4olIyXO_-yWT`x!Zi^-{@p8h=dl(nNDSgdiC>zt zSB90qV&YBU9sXm3w*d|QXFzmFD!CE7s^w}Mp=;V#`{ef$9^(!d!BcRaV2h1vbDEuj zw_LVR{(soDGWY%K!W1m4!`1Gp=4(K1*5j6rye}npVjA@?)&?B+p{wuFI;Rl*3_Yzw zqPG4Mn-%t6a=ck?r?8XFGUV#`M!ueJ;BWJ_d<);iH}g(U8R+BP9J)A(C&3xt^1Vu2 zMNS5B5BR>4R$*y3w0!NlmWQ7ROKf`G>6wW^$9^;(J%HV9#O}a0zToMduCIu{#bWkI zes0z?+GZN|0_`)k%*kdYV{G2xYcLuWwdQ7O^T%d#)7q?N>KJ|V7V1wH+jw=co4?Cj zu$lB?53enD@#f+^z8w@g`P5=7-@*6t`eGl-=fObR=bkE|L8ufOF{cWlMrac1g*u@Y zrE;O#p64yZsyE^N8NVoIi5EmG{v&=_yd?gL=ZNWewy1b@ujbX_DR0u7iW_k~{yY8$ zEKb1U7=jU_6p{AehhFLX(!o*?gqEazl(FAPVaX@Gmi!Vc38>j!3S_P()&lPX9|Io( zzJw?75+3J;fNSEix*hzP`~ge-8oa1pP|akP`YX8=OeZg?R`Oer3;s@S2LIrCwps-L z+zu5WE{0&Y3>9iTY0s;4S+>@!F&oV$GY8gRXJ+n;SRpHHu~s#Fp)h?jU6Ag?-eM*_JCT@r;246%HlY_W+Tc8lHroB|#5QeP>2htywqjiD zu8WWD+BMj@xQpCnE{D6pVNK+&A-=@@g5BgIhre^cWph`!-7_d3e3c=4)u!S~ai*AMS6q*qYCEQz+R-$_SHAEXuOt@K_xTw2Av<92;C@Ffs{ ze%Ay3#HYaLK#qDvy{hsclB>cZf_tF~tx_x3%CuYBZfGmDnc`C0sc)&BR0T9sX_Ol| zY_s`{y=`8#u0SvUy6|kG8T@c6b)Pg46jhdTqO}s#g^Cs$6SFyvbD)@2*ADnu(`hGPz^>KA=^%Ls<8kn`YwGoGF zZOrk=F${|thm1OC#FS%x4JT9NGNHpMMb&7l^DgYD-I<6cqj#J~(c@^F^R`otb~=@4 zm$SvTu}tglv4dET3wOH)T!L+1k6eSU5!XG`b-Q|9qptnfebvh0qZ4?+vD@RLT&-#^}MwC0WR<@uo?Is{2B-*qS9Vafb|KXeXI^V&X3#d z7R%ULDP8UcoucL9<-%pWAwh5kSb4fKvof)=F!2&?CRf}O)3!br?K?6pKCi}BQ&Z8^ zFRSaTCsR7~so6TUXR`Kc%?%Abg@z^|9^}1iONbvke28HkXS&Pe6S0?TC()nLbQJ$s zLi9)USG3oO6*j6xdz|;2M)Y^oie}nTE;V)-Q)0;&4PA+`qu9cl96OFlu{&qv%eZx^ zoGanRTz8pbu9B3?V z&?~eHT|&@vN9YiGgifJN=*C)6DPHwmQ_IA1u~aPNuJ~?=C1Q>**HElgotWpV7puf-@fvLBy01pOfpin2<)p9DHz~EWf&6)RlVB6C6MSGLu@iWkc$ZjC zL=xNB^$Rekn`%DdB6UA_5UkVUp+dD*I|%Kk4pK{D0rUJ0sWGnN6qReev0h`%%8JxP z-deqB_*LZ9gaPX)!^r(%@5Hp@v8$Jf2Tjxk*8FRi*0DxA2b>R`*~mR`4nqH@A!~iY z^$Sd%x+YzhHl|&FViz{d*pw@4BXd2CD?egZ>OR|?=yN`@Xb412iM5;a<{o| zZh*VXJpjY|OcSoObA!mYaYM{QrW56ROdm7I-AAsUYsr)$12*x@Gy0i6u9<7)dQf{F zUJ465em&wt{5#&oH)LkTm%A(7x82WCk8gnPYIlpf3iYR<+3iOCEZ^u}Wo@JyHyo(hA)fItaz!UxZSFe;1*MX;draLZTf8y6|DRlJGXSQ@tC zD?7V>TP*SQicMm(nC}}CD}4Rp1F=s`NZsO~cwcN28^uwv-1i8p*bt;k>=av&X2M-@ zSnLoVinLuWMt=k1h|~_L+N9lDVWwNhw?YiGAv#Y)M)2p=7|i zf1|vMbVs@*V_%d1NXL>a?MWB>SVg20>9>^SzltDOFtz8B|-XO`_jH0pA$MwkEBmH4a5@rfp}mm zu^W&R-xC{&uZca>CIY*Oj|o1pp1>cS2}ps@s1qUI5^=1sj>cBrjtr&_DtQrpxHts1on^l=>gkWhlnYKtld+tp&! zmO=g+`ZS#KG%3`J6sJv1#?EsG`8G`r-P0Pi+uC8MALTBsM^i$n&`GFWYexAvlnB*p zM`$gElA&%*L#|W1ujxoLp%rcJLjE4K)FoX{{YtfHKT?OO3wkJgocfbWVMW5X^>8N6 z)(wuY#dmblreiiX2><^zkG0zvI_^RMp zNBUHJB3Ah(u<}ld)n}`5o_t-_u%6_~*W?_3j+`%Fm2b$3z4EAtPZC-nkvIt?6G|W% zPy<)6+TzpL z6#i|Sisi#6Wy_Vz<;$l}oL#{hF@Y6j!nv|E@odGh;-B!L{P(c2y1Dv$>f7qqRs4Q2 z^%MPEnC4dhAUzL}wOPkAhtu&IA9)>)FwVm4S`cw2jN6)`oR`;W=VNEiI{x&TbHq97 z9JA|B+c;dg8}qKK(B}1x=dNoT)66s13)ig6<(hLjq1{ZlvhkD|#c5^CKC#f;3^Tz@ zG9%n0j^f6dC(!m3^VrsTl>f+o;yc`((EK{z?%sfYzj?kQ_Sh$YSHd*(JOx3o{;U21 zIoFTVDm0pc=!q0|nQqlQTbK2~#c7=EomVh&yf<$!E(bHtJ>i})vy78@&OGMsy1U(7 z_yPZp`!jz!R?agc-juKTjX;muucm{&>W`omys!QY_F+GHpqW7ny{}@;!#n@w8Ox`MAL@2xc}CsK~J*a7)_$O5rU=*Osi zVD1zP{Y4l{HtHLEKSR&Y-jj+^x5vJ4PHtg!7_ z5(2^-AtbyO!a`7p2sKZ%RV1qD0; zzY~=DJ2L2*$Ff{T=9Z?^s7eWvJw%b#n0bA2(q}O!VB_tDiKw<%O7`DK=Xgf8_5}U)qK|vv_{rA)X}_6x z&Zbf>XJeG}cAm!!E98rzr|NIm%MCqGFJTKU#^G_ja^-K#GYm7sEiicN2dfeH4$t%3 z{GfZtJ?wsf8tkpYu4m7t^h#{?Er<-p<`Hk(jH>*2Hy6F)OVN$m7SvUu=9XNFxXNZ% ziMYaF=D&rSa>#kOjPYGla+F-=d0!G&|0lr zz_s6){b`s51BZGobTyOKjwbyj`OEuSQowspFw>Ck_m^N zm=Hb7e?|HZ+W8=U6km%g;v4avOr!*?{N`rC%E7qSth0>(BR7PD? z7c#m~=T#@t7iwPU8PYij)=X_)yByBsa>8?(TU*i=G#|9)fxN`e0E-%f+$%`EUaK#M zYxE|)0h(F~SL?TsR_UwZI{jU^Q6DlM8JT__7*#A~++s(K5u=hFHY(VMs2?>c^AT3F zVbjA7nIq;H^0fKDd}zL8i>x@bUTp2N2eyAlt!t41Xul(~Vx~JIbLshXC>=~cjI934 zY$7w0e+-lMIpmPXdl}@&BYD0-r=P?-&;|V3ciZ2AT$kM9$GefzDZADDPyp02p+#>7 zDd^0OY0#)<$IT=56)Uob?7G#6c}|_3b6(n7$%WrPapPN+Z9lSyvs0|1VpMGN5BLUQ zA2IQZ_!%~Z_d&TA&+d`C2(xTjkP2f!taY5*n>Q!&T8$IYZqy;rryAlp#T&;S$ z-e!+y%y?pq8;_00ruS@hEwM_iGVD6nBTW$|J&lnK`P%(H^zg*q*Td;+7~gPY#(59V zT|#}to@wU4^>Lu}mavWS9(xj=ui``B1K$Ql*^bfp)u0+si$g`BLX4=EodAg%cG8?c zuQwu}EwAf{&x{;jEQB3_x97Zvd$+`I;;ubYta5fb;^Rfm&TWc2;CK^{P``pWl|`!a3kPkYbABXWm-Sbm7wM}NE0p>)~g?jY`0x|Kepy-JUA7ilLX zD|iWhl^whoypPg(c%!a>z*}_{aVEUa@K7s4uaUCqJH%l%q?U(DLnUXs-T9sPB}M(9 zeb%mp*T65T#kA|;PslAp-fCa8RirE0y7o@X4POo88<+M*`-nRGDQD?v>5krQ>oQX+ z`@f#jrT6K*dZ#{s79Efe;d^Io@9OWv_w9WDSq=6vW6JhotQSZfhSR9Gtzy=AhVrB_ zW7M5l$r3wfJ~Lg=9b>*gJPQf1&&_$$&(4@Vx)WvefOrZrZTi?-R<%`URay10tx8Ba zL}F{KV^(G>tXh;#!#680vWe1H>x*5tVa2RlfAjq6bd{ZdfOsf9n0|<~FVY`bPQU+K zoAaLjJET6>GwztjyQf=1j9;Vd7`wjkT~IxWM-Y-85xyXa`=Trg;sNq;@yPZL%BP44 zanyGx9*d7`A2}y71FP@$qgS~T@whxCJ5bYu{G|Luo|PY?G%epjc}(s?eAhp5<|mWN zLuFWbq>R7^25digpgdMa?c8Pf$5Ulo$q7DD1{GQvLoH=r$vpRyx~|4-FZqbLGW1nl zQ@54u5D@g;UjHdJAfx_ zXggX0sRa2BQM7ICt0p72sU2#(mee@yM);eytL>pK6Gmb2!w?!Wt3TF9^dbGJ{zxCw zAL>*3pib#e^a*`he}L=Hbf-S4JM?kn14bBr&;TC@8E=e;(a3rYm+``AW|s`V@yeLP zRktyNmh(mv>p|%ygfW7M7YvWd8m|qXv1q(9edeMWL_e$8=TFq9gm0&yJ1@|mJ>TX-zR-e^jHCbJ#yJPiQJ@`YqZC0bzV&z8)A`PfLu(qsy zYtQ;_an_C%w{|Vw+D5$qsey;oLh93X>Be+JdL%uZUO;&f!ls8JBiM;Pq(>3|*9l9m z)3L6F--7YYNFhe=cO`iIuH{bJUf`6U%g^L#WlFgc+)-zgZQBMltuS01KC$hg2v+r6 zcj+(mW#cwaIP@%=3q=B3!?n zesng(TI{{?S-5m(4Ky)*P{ht%tY=zk*`+i*g=T0aLT^-=d7#wMSM<+MQlcr#$(=Lp7~^ zG9KCWPrzwjIZ}UUKeb<)4?go!Z)3gsD}6oe(Z68EpTp}$)M#fr>^&#Ku9_@zW7fDu zTa;CTSxJ^`9b3hb)^ta@J>6!{FnTu6bM}8t`#>5rLQDE*(0t9l2T45X?4Ex6Dm)hY z`hY9cKke(UJ(Ch4KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5< z03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex z2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5 zga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk| zKnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa z0)zk|KnM^5ga9Ex2oM5<03kpK5CVh%AwUQa0)zk|KnM^5ga9Ex2oM5<03kpK5CVh% zAwUQa0)zk|KnVQ%2wZ#nYwO?F1G$?JAOr{jLVyq;1pcQIxJH#z|NDPcQdLwPRZlfh z%~UJZMs-qmsBWr<>ZAIpL28H^rbf`}G(@P^)H1a~y`kPx)l?ppPZi)=Ayq^bQzgia zQjaK#qNy=zoO(yCQtzp4YKP*fU1|?kFVQ#XJUX8~?~SDY7J*z)b5L3IReBb=8mg9h zMtz_zQfpK;^@n;!JL%{23))4`(epGzFVKth6)K1NOvR`#)Kw~%{y?wMAL&nYlwPMl z(_iQqy+MDaztNjCM{m*F^bXC_yYwFYofhbQ`hbqpBD8bC)=(HvJfx3kiI(YOIzcOR zl2+*xTBB36P8+mITXdTKLI0$G(ZA_G^o6mDW0%IV#u}(ns*(DRyZ@($9Qq1KhCm|w I|I6n84_F!(O#lD@ literal 0 HcmV?d00001 diff --git a/media/nls/l_intl.nls b/media/nls/l_intl.nls new file mode 100644 index 0000000000000000000000000000000000000000..d977b03fff85bb9154bf5e719f4a890d79265375 GIT binary patch literal 4870 zcmeHJJ8#rL5T0Ed0i8=k$%`o>$NW#0pb9NNW`Ke644dCmgtKV zcMSBdVavU3YwgGXiyO#9?w}B((i&?CGLo@IM`+?=c@j<*{Wq8IdoSf<)L2!=rxpT&}%G5T8^DvxqvVVt>N>Qqo)dF;eYOm-L6M^R~+k;K$#@ zlu9+vBNe_mnzA)Vxa|8~^GtjO!*K?~vF}D{nhMOh+5CO>B@mswsCr*DhU}(sTAjm)CAEa>1)S$6@#FzGJF(BGQxhG)=qI)3gyXlh zj%lx1$xGUzTJ&NUJj?F&wQIgP$J$g|8uUGWsriNE>Inkisd`aX-%x9lbJ+V^RhgnU z0Wh4fO{G7ny#t*+n*;uOr_aRCV81bn;V*%uW!b}$GZt#^z&Tw>^?0)XxpUXdxsu}m z4pm?oqq%&Q;|R)PrysQp%W%EK3amhi=p$|+Xi$ED!&H4zMTwUu2X1uiBxE1z=Z~iwL_w>H|AkCerNzBkTf+&1Iou{obbD z8p#5CMdGkulo57}wr8YV33(A+Eqi4L*bmZR;B|xb*{8iGo4XFn3gpYM?<{cAIwC1Z z&x3Jby3LO6;gYhG>pC6XbS2kA{iL<4cWW8Eg}Eb!_OMCY?S)D$06JjPyo7(tUEa4` zhV|x%yNcsT(s(<`|5|J7u&yP*Rak>prSAT=Ms@0jt#38HQ7i2^IS)&lvjckvo0T;_-E>_O;qt8W-a5IX zd{kpxw#pfM2j7%C{V3Z12=Q~q`&?B9vv}Hn58-FE7V!hbuNe`kO4S`iUH%7OO`a>; RkGDBv1kK<$l1KjnzXA2gq1gZc literal 0 HcmV?d00001 diff --git a/ntoskrnl/.cvsignore b/ntoskrnl/.cvsignore new file mode 100644 index 0000000..3eff845 --- /dev/null +++ b/ntoskrnl/.cvsignore @@ -0,0 +1,11 @@ +base.tmp +junk.tmp +ntoskrnl.coff +objects +temp.exp +ntoskrnl.dbg +bugcodes.rc +msg*.bin +ntoskrnl.map +*.o +*.sym diff --git a/ntoskrnl/Makefile b/ntoskrnl/Makefile new file mode 100644 index 0000000..b371e8e --- /dev/null +++ b/ntoskrnl/Makefile @@ -0,0 +1,710 @@ +# $Id$ +# +# ReactOS Operating System +# + +# +# Path to the directory containing the root makefile +# +PATH_TO_TOP := .. + +# +# Include details of the host OS configuration +# +include $(PATH_TO_TOP)/config + +CONFIG := + +ifeq ($(DBG), 1) +CFLAGS_DBG := -g +LINKER_SCRIPT := ntoskrnl.lnk +STRIP_FLAGS := -Wl,-s +else +CFLAGS_DBG := +LINKER_SCRIPT := ntoskrnl.lnk +STRIP_FLAGS := -Wl,-s +endif + +ifeq ($(KDBG), 1) +OBJECTS_KDBG := dbg/kdb.o dbg/kdb_keyboard.o dbg/rdebug.o \ + dbg/i386/kdb_help.o dbg/kdb_stabs.o +else +OBJECTS_KDBG := +endif + +ifeq ($(strip $(SDK_PATH_INC)),) +ASFLAGS += -I./include +CFLAGS += -I./include -D__NTOSKRNL__ $(CFLAGS_DBG) -Wall -Werror +else +ASFLAGS += -I./include -I$(SDK_PATH_INC) +CFLAGS += -I./include -I$(SDK_PATH_INC) -D__NTOSKRNL__ $(CFLAGS_DBG) -Wall -Werror +endif + +# +# Build configuration +# +include $(PATH_TO_TOP)/rules.mak + + +TARGETNAME := ntoskrnl + +OBJECTS_PATH = objects + +all: \ + $(OBJECTS_PATH) \ + bugcodes.rc \ + $(TARGETNAME).nostrip.exe \ + $(TARGETNAME).exe \ + $(TARGETNAME).sym \ + ntoskrnl.map + +# +# Architecture specific Makefile +# Defines $(OBJECTS_ARCH) +# +include Makefile.$(ARCH) + +# System API (Nt/Zw) +OBJECTS_NT = \ + nt/channel.o \ + nt/evtpair.o \ + nt/mutant.o \ + nt/misc.o \ + nt/nt.o \ + nt/ntevent.o \ + nt/ntsem.o \ + nt/nttimer.o \ + nt/plugplay.o \ + nt/profile.o \ + nt/zw.o \ + nt/vdm.o + +# Run-Time Library (Rtl) +OBJECTS_RTL = \ + rtl/atom.o \ + rtl/bitmap.o \ + rtl/compress.o \ + rtl/ctype.o \ + rtl/dos8dot3.o \ + rtl/error.o \ + rtl/handle.o \ + rtl/largeint.o \ + rtl/mem.o \ + rtl/memchr.o \ + rtl/memcpy.o \ + rtl/memmove.o \ + rtl/memset.o \ + rtl/message.o \ + rtl/nls.o \ + rtl/purecall.o \ + rtl/qsort.o \ + rtl/regio.o \ + rtl/sprintf.o \ + rtl/stdlib.o \ + rtl/string.o \ + rtl/swprintf.o \ + rtl/time.o \ + rtl/timezone.o \ + rtl/unicode.o \ + rtl/wstring.o \ + rtl/memcmp.o \ + rtl/capture.o + +OBJECTS_RTL := $(filter-out $(RTL_EXCLUDE_FILTER), $(OBJECTS_RTL)) + + +# Kernel (Ke) +OBJECTS_KE = \ + ke/apc.o \ + ke/bug.o \ + ke/catch.o \ + ke/critical.o \ + ke/dpc.o \ + ke/error.o \ + ke/event.o \ + ke/kqueue.o \ + ke/main.o \ + ke/mutex.o \ + ke/process.o \ + ke/sem.o \ + ke/spinlock.o \ + ke/timer.o \ + ke/wait.o \ + ke/kthread.o \ + ke/queue.o + +# Memory Manager (Mm) +OBJECTS_MM = \ + mm/aspace.o \ + mm/cont.o \ + mm/drvlck.o \ + mm/freelist.o \ + mm/iospace.o \ + mm/marea.o \ + mm/mdl.o \ + mm/mm.o \ + mm/ncache.o \ + mm/npool.o \ + mm/pagfault.o \ + mm/pagefile.o \ + mm/paging.o \ + mm/pool.o \ + mm/ppool.o \ + mm/section.o \ + mm/virtual.o \ + mm/pager.o \ + mm/wset.o \ + mm/mminit.o \ + mm/kmap.o \ + mm/mpw.o \ + mm/pageop.o \ + mm/balance.o \ + mm/rmap.o \ + mm/slab.o \ + mm/anonmem.o \ + mm/region.o + +# I/O Subsystem (Io) +OBJECTS_IO = \ + io/adapter.o \ + io/arcname.o \ + io/buildirp.o \ + io/cancel.o \ + io/cleanup.o \ + io/cntrller.o \ + io/create.o \ + io/device.o \ + io/dir.o \ + io/driver.o \ + io/errlog.o \ + io/error.o \ + io/event.o \ + io/file.o \ + io/flush.o \ + io/fs.o \ + io/iocomp.o \ + io/ioctrl.o \ + io/iomgr.o \ + io/iowork.o \ + io/irp.o \ + io/lock.o \ + io/mailslot.o \ + io/mdl.o \ + io/npipe.o \ + io/page.o \ + io/parttab.o \ + io/pnpmgr.o \ + io/pnproot.o \ + io/process.o \ + io/queue.o \ + io/resource.o \ + io/rw.o \ + io/share.o \ + io/shutdown.o \ + io/symlink.o \ + io/timer.o \ + io/vpb.o \ + io/xhaldisp.o \ + io/xhaldrv.o + +# Object Manager (Ob) +OBJECTS_OB = \ + ob/dirobj.o \ + ob/handle.o \ + ob/namespc.o \ + ob/ntobj.o \ + ob/object.o \ + ob/security.o + +# Process Manager (Ps) +OBJECTS_PS = \ + ps/create.o \ + ps/idle.o \ + ps/kill.o \ + ps/locale.o \ + ps/process.o \ + ps/psmgr.o \ + ps/thread.o \ + ps/tinfo.o \ + ps/debug.o \ + ps/suspend.o \ + ps/win32.o \ + ps/w32call.o + +# Executive Subsystem (Ex) +OBJECTS_EX = \ + ex/btree.o \ + ex/callback.o \ + ex/fmutex.o \ + ex/hashtab.o \ + ex/init.o \ + ex/interlck.o \ + ex/list.o \ + ex/lookas.o \ + ex/napi.o \ + ex/power.o \ + ex/resource.o \ + ex/time.o \ + ex/stree.o \ + ex/sysinfo.o \ + ex/win32k.o \ + ex/work.o \ + ex/zone.o + +# Installable File System Run-Time Library (FsRtl) +OBJECTS_FS = \ + fs/dbcsname.o \ + fs/filelock.o \ + fs/mcb.o \ + fs/mdl.o \ + fs/name.o \ + fs/notify.o \ + fs/oplock.o \ + fs/pool.o \ + fs/tunnel.o \ + fs/unc.o \ + fs/util.o + +# Security Subsystem +OBJECTS_SE = \ + se/access.o \ + se/acl.o \ + se/lsa.o \ + se/luid.o \ + se/priv.o \ + se/sd.o \ + se/semgr.o \ + se/sid.o \ + se/token.o + +# Configuration Manager (Registry) +OBJECTS_CM = \ + cm/import.o \ + cm/registry.o \ + cm/ntfunc.o \ + cm/rtlfunc.o \ + cm/regfile.o \ + cm/regobj.o + +# Debugger Support (Dbg) +OBJECTS_DBG = \ + dbg/dbgctrl.o \ + dbg/errinfo.o \ + dbg/print.o \ + dbg/user.o \ + $(OBJECTS_KDBG) + +# Loader +OBJECTS_LDR = \ + ldr/init.o \ + ldr/loader.o \ + ldr/resource.o \ + ldr/rtl.o \ + ldr/sysdll.o \ + ldr/userldr.o + +# Local Procedure Call (Lpc) +OBJECTS_LPC = \ + lpc/close.o \ + lpc/complete.o \ + lpc/connect.o \ + lpc/create.o \ + lpc/listen.o \ + lpc/port.o \ + lpc/query.o \ + lpc/queue.o \ + lpc/receive.o \ + lpc/reply.o \ + lpc/send.o + +# Nation Language Support Library (Nls) +OBJECTS_NLS = nls/nls.o + +# Power Management (Po) +OBJECTS_PO = po/power.o + +# Cache Manager (Cc) +OBJECTS_CC = \ + cc/cacheman.o \ + cc/view.o \ + cc/copy.o \ + cc/pin.o \ + cc/misc.o + +# Kernel Debugger Support (Kd) +OBJECTS_KD = \ + kd/kdebug.o \ + kd/service.o \ + kd/dlog.o \ + kd/gdbstub.o kd/mda.o + +DEP_OBJECTS := $(OBJECTS_NT) $(OBJECTS_MM) $(OBJECTS_ARCH) \ + $(OBJECTS_IO) $(OBJECTS_KE) $(OBJECTS_OB) \ + $(OBJECTS_PS) $(OBJECTS_EX) $(OBJECTS_CC) $(OBJECTS_FS) $(OBJECTS_SE) \ + $(OBJECTS_DBG) $(OBJECTS_CM) $(OBJECTS_LDR) $(OBJECTS_LPC) \ + $(OBJECTS_PO) $(OBJECTS_KD) $(OBJECTS_RTL) + +TAG_OBJECTS := $(join $(dir $(DEP_OBJECTS)),$(patsubst %.o, .%.TAG, $(notdir $(DEP_OBJECTS)))) + +# +# Include automatic dependancy tracking +# +DEP_EXCLUDE_FILTER := ex/napi.% nt/zw.% +include $(PATH_TO_TOP)/tools/depend.mk + + +# Resources +OBJECTS_RESOURCE = \ + $(TARGETNAME).coff + +# IMPORTS/EXPORTS +IE_DATA = \ + $(TARGETNAME).def \ + $(TARGETNAME).edf + +$(OBJECTS_PATH): + mkdir $(OBJECTS_PATH) + +$(OBJECTS_RESOURCE): $(TARGETNAME).rc bugcodes.rc $(PATH_TO_TOP)/include/reactos/resource.h + +# +# Build subsystem intermediate objects +# +$(OBJECTS_PATH)/arch.o: $(OBJECTS_ARCH) + $(LD) -r -o $(OBJECTS_PATH)/arch.o $(OBJECTS_ARCH) + +$(OBJECTS_PATH)/io.o: $(OBJECTS_IO) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/io.o \ + $(OBJECTS_IO) + +$(OBJECTS_PATH)/ke.o: $(OBJECTS_KE) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/ke.o \ + $(OBJECTS_KE) + +$(OBJECTS_PATH)/rtl.o: $(OBJECTS_RTL) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/rtl.o \ + $(OBJECTS_RTL) + +$(OBJECTS_PATH)/mm.o: $(OBJECTS_MM) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/mm.o \ + $(OBJECTS_MM) + +$(OBJECTS_PATH)/ob.o: $(OBJECTS_OB) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/ob.o \ + $(OBJECTS_OB) + +$(OBJECTS_PATH)/ps.o: $(OBJECTS_PS) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/ps.o \ + $(OBJECTS_PS) + +$(OBJECTS_PATH)/ex.o: $(OBJECTS_EX) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/ex.o \ + $(OBJECTS_EX) + +$(OBJECTS_PATH)/fs.o: $(OBJECTS_FS) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/fs.o \ + $(OBJECTS_FS) + +$(OBJECTS_PATH)/se.o: $(OBJECTS_SE) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/se.o \ + $(OBJECTS_SE) + +$(OBJECTS_PATH)/cm.o: $(OBJECTS_CM) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/cm.o \ + $(OBJECTS_CM) + +$(OBJECTS_PATH)/dbg.o: $(OBJECTS_DBG) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/dbg.o \ + $(OBJECTS_DBG) + +$(OBJECTS_PATH)/ldr.o: $(OBJECTS_LDR) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/ldr.o \ + $(OBJECTS_LDR) + +$(OBJECTS_PATH)/lpc.o: $(OBJECTS_LPC) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/lpc.o \ + $(OBJECTS_LPC) + +$(OBJECTS_PATH)/nls.o: $(OBJECTS_NLS) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/nls.o \ + $(OBJECTS_NLS) + +$(OBJECTS_PATH)/nt.o: $(OBJECTS_NT) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/nt.o \ + $(OBJECTS_NT) + +$(OBJECTS_PATH)/po.o: $(OBJECTS_PO) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/po.o \ + $(OBJECTS_PO) + +$(OBJECTS_PATH)/cc.o: $(OBJECTS_CC) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/cc.o \ + $(OBJECTS_CC) + +$(OBJECTS_PATH)/kd.o: $(OBJECTS_KD) + $(LD) \ + -r \ + -o $(OBJECTS_PATH)/kd.o \ + $(OBJECTS_KD) + +# Note: arch.o MUST be the first file!!! +OBJECTS := \ + $(OBJECTS_PATH)/arch.o \ + $(OBJECTS_PATH)/ke.o \ + $(OBJECTS_PATH)/cc.o \ + $(OBJECTS_PATH)/cm.o \ + $(OBJECTS_PATH)/dbg.o \ + $(OBJECTS_PATH)/ex.o \ + $(OBJECTS_PATH)/lpc.o \ + $(OBJECTS_PATH)/fs.o \ + $(OBJECTS_PATH)/io.o \ + $(OBJECTS_PATH)/kd.o \ + $(OBJECTS_PATH)/ldr.o \ + $(OBJECTS_PATH)/mm.o \ + $(OBJECTS_PATH)/nls.o \ + $(OBJECTS_PATH)/nt.o \ + $(OBJECTS_PATH)/ob.o \ + $(OBJECTS_PATH)/po.o \ + $(OBJECTS_PATH)/ps.o \ + $(OBJECTS_PATH)/rtl.o \ + $(OBJECTS_PATH)/se.o \ + $(OBJECTS_RESOURCE) + + +$(TARGETNAME).nostrip.exe: $(TARGETNAME).o $(IE_DATA) + $(CC) \ + -Wl,-T,ntoskrnl.lnk \ + -nostartfiles \ + -nostdlib \ + -mdll \ + -o junk.tmp \ + -Wl,--subsystem,native \ + -Wl,--image-base,0xc0000000 \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,--base-file,base.tmp \ + $(TARGETNAME).o -lgcc \ + $(DDK_PATH_LIB)/hal.a + - $(RM) junk.tmp + $(DLLTOOL) \ + --dllname $(TARGETNAME).exe \ + --base-file base.tmp \ + --output-exp temp.exp \ + --def $(TARGETNAME).edf \ + --kill-at + - $(RM) base.tmp + $(CC) \ + -nostartfiles \ + -nostdlib \ + -Wl,-T,ntoskrnl.lnk \ + -mdll \ + -o $(TARGETNAME).nostrip.exe \ + -Wl,--subsystem,native \ + -Wl,--image-base,0xc0000000 \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,temp.exp \ + $(TARGETNAME).o -lgcc \ + $(DDK_PATH_LIB)/hal.a + - $(RM) temp.exp + +$(TARGETNAME).exe: $(TARGETNAME).o $(LINKER_SCRIPT) $(DDK_PATH_LIB)/hal.a + - $(CC) \ + -Wl,-T,$(LINKER_SCRIPT) \ + -nostartfiles \ + -nostdlib \ + -mdll \ + -o junk.tmp \ + -Wl,--subsystem,native \ + -Wl,--image-base,0xc0000000 \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,--base-file,base.tmp \ + $(TARGETNAME).o -lgcc \ + $(DDK_PATH_LIB)/hal.a + - $(RM) junk.tmp + $(DLLTOOL) \ + --dllname $(TARGETNAME).exe \ + --base-file base.tmp \ + --output-exp temp.exp \ + --def $(TARGETNAME).edf \ + --kill-at + - $(RM) base.tmp + $(CC) \ + -Wl,-T,$(LINKER_SCRIPT) $(STRIP_FLAGS)\ + -nostartfiles \ + -nostdlib \ + -mdll \ + -o $(TARGETNAME).exe \ + -Wl,--subsystem,native \ + -Wl,--image-base,0xc0000000 \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,temp.exp \ + $(TARGETNAME).o -lgcc \ + $(DDK_PATH_LIB)/hal.a + - $(RM) temp.exp + +$(TARGETNAME).dbg.o: $(TARGETNAME).o + $(STRIP) --strip-debug -o $(TARGETNAME).dbg.o $(TARGETNAME).o + +$(TARGETNAME).dbg: $(TARGETNAME).dbg.o $(TARGETNAME).a $(TARGETNAME).dbg.lnk + $(CC) \ + -Wl,-T,$(TARGETNAME).dbg.lnk \ + -nostartfiles \ + -nostdlib \ + -mdll \ + -o junk.tmp \ + -Wl,--subsystem,native \ + -Wl,--image-base,0xc0000000 \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,--base-file,base.tmp \ + $(TARGETNAME).dbg.o -lgcc \ + $(DDK_PATH_LIB)/hal.a + - $(RM) junk.tmp + $(DLLTOOL) \ + --dllname $(TARGETNAME).dbg \ + --base-file base.tmp \ + --output-exp temp.exp \ + --def $(TARGETNAME).edf \ + --kill-at + - $(RM) base.tmp + $(CC) \ + -Wl,-T,$(TARGETNAME).dbg.lnk \ + -nostartfiles \ + -nostdlib \ + -mdll \ + -o $(TARGETNAME).dbg \ + -Wl,--subsystem,native \ + -Wl,--image-base,0xc0000000 \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,temp.exp \ + $(TARGETNAME).dbg.o -lgcc \ + $(DDK_PATH_LIB)/hal.a + - $(RM) temp.exp + +$(TARGETNAME).sym: $(TARGETNAME).nostrip.exe + $(RSYM) $(TARGETNAME).nostrip.exe $(TARGETNAME).sym + +TAGS: $(TAG_OBJECTS) + etags $(addprefix -i , $(TAG_OBJECTS)) + +ntoskrnl.map: $(TARGETNAME).nostrip.exe + $(NM) --numeric-sort $(TARGETNAME).nostrip.exe > ntoskrnl.map + +$(TARGETNAME).o: $(OBJECTS) + $(LD) \ + -r \ + -o $(TARGETNAME).o \ + $(OBJECTS) + +bugcodes.rc: ntoskrnl.mc + $(MC) \ + -H $(PATH_TO_TOP)/include/reactos/bugcodes.h \ + -o bugcodes.rc \ + $(TARGETNAME).mc + +$(DDK_PATH_LIB)/$(TARGETNAME).a: $(TARGETNAME).def + - $(DLLTOOL) \ + --dllname $(TARGETNAME).exe \ + --def $(TARGETNAME).def \ + --output-lib $(DDK_PATH_LIB)/$(TARGETNAME).a \ + --kill-at + +implib: $(DDK_PATH_LIB)/$(TARGETNAME).a + +clean: + - $(RM) $(OBJECTS_PATH)/*.o cc/*.o cm/*.o dbg/*.o dbg/i386/*.o ex/*.o \ + ex/i386/*.o io/*.o ke/*.o ldr/*.o mm/*.o nt/*.o ob/*.o ps/*.o \ + rtl/*.o se/*.o ke/i386/*.o mm/i386/*.o fs/*.o po/*.o nls/*.o \ + lpc/*.o kd/*.o $(TARGETNAME).o junk.tmp base.tmp temp.exp \ + $(TARGETNAME).exe $(TARGETNAME).nostrip.exe $(TARGETNAME).sym ntoskrnl.map \ + $(TARGETNAME).coff bugcodes.rc msg?????.bin $(DEP_FILES) \ + $(TAG_OBJECTS) + + +.PHONY: clean + +install: all $(INSTALL_DIR)/system32/$(TARGETNAME).exe $(INSTALL_DIR)/symbols/$(TARGETNAME).sym + +$(INSTALL_DIR)/system32/$(TARGETNAME).exe: $(TARGETNAME).exe + $(CP) $(TARGETNAME).exe $(INSTALL_DIR)/system32/$(TARGETNAME).exe + +$(INSTALL_DIR)/symbols/$(TARGETNAME).sym: $(TARGETNAME).sym + $(CP) $(TARGETNAME).sym $(INSTALL_DIR)/symbols/$(TARGETNAME).sym + +.PHONY: install + +dist: $(DIST_DIR)/$(TARGETNAME).exe + +$(DIST_DIR)/$(TARGETNAME).exe: $(TARGETNAME).exe + $(CP) $(TARGETNAME).exe $(DIST_DIR)/$(TARGETNAME).exe + +.PHONY: dist + +ex/napi.o: ex/napi.c $(PATH_TO_TOP)/include/ntdll/napi.h + +ke/main.o: ke/main.c $(PATH_TO_TOP)/include/reactos/buildno.h + +%.o: %.cc + $(CC) $(CFLAGS) -c $< -o $@ +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ +%.o: %.S + $(AS) $(ASFLAGS) -c $< -o $@ +%.o: %.s + $(AS) $(ASFLAGS) -c $< -o $@ +%.o: %.asm + $(NASM_CMD) $(NFLAGS) $< -o $@ +%.coff: %.rc + $(RC) $(RCINC) $< -o $@ + +# +# +# +.%.TAG: %.S + etags -o $@ $< + +.%.TAG: %.s + etags -o $@ $< + +.%.TAG: %.c + etags -o $@ $^ + +# EOF diff --git a/ntoskrnl/Makefile.i386 b/ntoskrnl/Makefile.i386 new file mode 100644 index 0000000..9a12a5c --- /dev/null +++ b/ntoskrnl/Makefile.i386 @@ -0,0 +1,54 @@ +# +# Hardware Abstraction Layer (Hal) for x86 systems +# + +# Defines $(OBJECTS_HAL) +# include hal/x86/sources + +OBJECTS_BOOT := ke/i386/multiboot.o + +OBJECTS_EX_I386 := \ + ex/i386/interlck.o + +OBJECTS_KE_I386 := \ + ke/i386/exp.o \ + ke/i386/irq.o \ + ke/i386/irqhand.o \ + ke/i386/thread.o \ + ke/i386/usercall.o \ + ke/i386/trap.o \ + ke/i386/bthread.o \ + ke/i386/syscall.o \ + ke/i386/tskswitch.o \ + ke/i386/v86m.o \ + ke/i386/v86m_sup.o \ + ke/i386/bios.o \ + ke/i386/i386-mcount.o \ + ke/i386/gdt.o \ + ke/i386/idt.o \ + ke/i386/ldt.o \ + ke/i386/brkpoint.o \ + ke/i386/kernel.o \ + ke/i386/fpu.o \ + ke/i386/tss.o \ + ke/i386/usertrap.o \ + ke/i386/stkswitch.o + +OBJECTS_MM_I386 := \ + mm/i386/memsafe.o \ + mm/i386/page.o \ + mm/i386/pfault.o + +OBJECTS_RTL_I386 := \ + rtl/i386/memset.o \ + rtl/i386/memcpy.o \ + rtl/i386/except.o \ + rtl/i386/exception.o \ + rtl/i386/seh.o + +RTL_EXCLUDE_FILTER := \ + rtl/memset.o \ + rtl/memcpy.o + +OBJECTS_ARCH = $(OBJECTS_BOOT) $(OBJECTS_EX_I386) $(OBJECTS_KE_I386) $(OBJECTS_MM_I386) $(OBJECTS_RTL_I386) + diff --git a/ntoskrnl/cc/.cvsignore b/ntoskrnl/cc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/cc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/cc/cacheman.c b/ntoskrnl/cc/cacheman.c new file mode 100644 index 0000000..5592f1c --- /dev/null +++ b/ntoskrnl/cc/cacheman.c @@ -0,0 +1,42 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cc/cacheman.c + * PURPOSE: Cache manager + * PROGRAMMER: David Welch (welch@cwcom.net) + * PORTABILITY: Checked + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID +CcInit(VOID) +{ + CcInitView(); +} diff --git a/ntoskrnl/cc/copy.c b/ntoskrnl/cc/copy.c new file mode 100644 index 0000000..158c160 --- /dev/null +++ b/ntoskrnl/cc/copy.c @@ -0,0 +1,671 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cc/copy.c + * PURPOSE: Implements cache managers copy interface + * PROGRAMMER: Hartmut Birr + * UPDATE HISTORY: + * Created 05.10.2001 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define ROUND_DOWN(N, S) ((N) - ((N) % (S))) + +static PHYSICAL_ADDRESS CcZeroPage = (PHYSICAL_ADDRESS)0LL; + +/* FUNCTIONS *****************************************************************/ + +VOID +CcInitCacheZeroPage(VOID) +{ + NTSTATUS Status; + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &CcZeroPage); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Can't allocate CcZeroPage.\n"); + KeBugCheck(0); + } + Status = MiZeroPage(CcZeroPage); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Can't zero out CcZeroPage.\n"); + KeBugCheck(0); + } +} + +NTSTATUS +ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length, + PVOID Buffer) +{ + PCACHE_SEGMENT head; + PCACHE_SEGMENT current; + PCACHE_SEGMENT previous; + IO_STATUS_BLOCK Iosb; + LARGE_INTEGER SegOffset; + NTSTATUS Status; + ULONG TempLength; + KEVENT Event; + + Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + current = head; + while (current != NULL) + { + /* + * If the current segment is valid then copy it into the + * user buffer. + */ + if (current->Valid) + { + TempLength = min(Bcb->CacheSegmentSize, Length); + memcpy(Buffer, current->BaseAddress, TempLength); + Buffer += TempLength; + Length = Length - TempLength; + previous = current; + current = current->NextInChain; + CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); + } + /* + * Otherwise read in as much as we can. + */ + else + { + PCACHE_SEGMENT current2; + ULONG current_size; + PMDL Mdl; + ULONG i; + ULONG offset; + + /* + * Count the maximum number of bytes we could read starting + * from the current segment. + */ + current2 = current; + current_size = 0; + while (current2 != NULL && !current2->Valid) + { + current2 = current2->NextInChain; + current_size += Bcb->CacheSegmentSize; + } + + /* + * Create an MDL which contains all their pages. + */ + Mdl = MmCreateMdl(NULL, NULL, current_size); + Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ); + current2 = current; + offset = 0; + while (current2 != NULL && !current2->Valid) + { + for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++) + { + PVOID address; + PHYSICAL_ADDRESS page; + address = current2->BaseAddress + (i * PAGE_SIZE); + page = MmGetPhysicalAddressForProcess(NULL, address); + ((PULONG)(Mdl + 1))[offset] = page.u.LowPart; + offset++; + } + current2 = current2->NextInChain; + } + + /* + * Read in the information. + */ + SegOffset.QuadPart = current->FileOffset; + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageRead(Bcb->FileObject, + Mdl, + &SegOffset, + &Event, + &Iosb); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = Iosb.Status; + } + if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) + { + while (current != NULL) + { + previous = current; + current = current->NextInChain; + CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE); + } + return(Status); + } + while (current != NULL && !current->Valid) + { + previous = current; + current = current->NextInChain; + TempLength = min(Bcb->CacheSegmentSize, Length); + memcpy(Buffer, previous->BaseAddress, TempLength); + Buffer += TempLength; + Length = Length - TempLength; + CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); + } + } + } + return(STATUS_SUCCESS); +} + +NTSTATUS +ReadCacheSegment(PCACHE_SEGMENT CacheSeg) +{ + ULONG Size; + PMDL Mdl; + NTSTATUS Status; + LARGE_INTEGER SegOffset; + IO_STATUS_BLOCK IoStatus; + KEVENT Event; + + SegOffset.QuadPart = CacheSeg->FileOffset; + Size = CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset; + if (Size > CacheSeg->Bcb->CacheSegmentSize) + { + Size = CacheSeg->Bcb->CacheSegmentSize; + } + Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size); + MmBuildMdlForNonPagedPool(Mdl); + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, & Event, &IoStatus); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) + { + CcRosReleaseCacheSegment(CacheSeg->Bcb, CacheSeg, FALSE, FALSE, FALSE); + DPRINT1("IoPageRead failed, Status %x\n", Status); + return Status; + } + if (CacheSeg->Bcb->CacheSegmentSize > Size) + { + memset (CacheSeg->BaseAddress + Size, 0, + CacheSeg->Bcb->CacheSegmentSize - Size); + } + return STATUS_SUCCESS; +} + +NTSTATUS +WriteCacheSegment(PCACHE_SEGMENT CacheSeg) +{ + ULONG Size; + PMDL Mdl; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatus; + LARGE_INTEGER SegOffset; + KEVENT Event; + + CacheSeg->Dirty = FALSE; + SegOffset.QuadPart = CacheSeg->FileOffset; + Size = CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset; + if (Size > CacheSeg->Bcb->CacheSegmentSize) + { + Size = CacheSeg->Bcb->CacheSegmentSize; + } + Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size); + MmBuildMdlForNonPagedPool(Mdl); + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("IoPageWrite failed, Status %x\n", Status); + CacheSeg->Dirty = TRUE; + return(Status); + } + return(STATUS_SUCCESS); +} + +BOOLEAN STDCALL +CcCopyRead (IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus) +{ + ULONG ReadOffset; + ULONG TempLength; + NTSTATUS Status = STATUS_SUCCESS; + PVOID BaseAddress; + PCACHE_SEGMENT CacheSeg; + BOOLEAN Valid; + ULONG ReadLength = 0; + PBCB Bcb; + KIRQL oldirql; + PLIST_ENTRY current_entry; + PCACHE_SEGMENT current; + + DPRINT("CcCopyRead(FileObject %x, FileOffset %x, " + "Length %d, Wait %d, Buffer %x, IoStatus %x)\n", + FileObject, (ULONG)FileOffset->QuadPart, Length, Wait, + Buffer, IoStatus); + + Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb; + ReadOffset = FileOffset->QuadPart; + + DPRINT("AllocationSize %d, FileSize %d\n", + (ULONG)Bcb->AllocationSize.QuadPart, + (ULONG)Bcb->FileSize.QuadPart); + + /* + * Check for the nowait case that all the cache segments that would + * cover this read are in memory. + */ + if (!Wait) + { + KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + if (!current->Valid && current->FileOffset < ReadOffset + Length + && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset) + { + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + IoStatus->Status = STATUS_UNSUCCESSFUL; + IoStatus->Information = 0; + return FALSE; + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + } + + TempLength = ReadOffset % Bcb->CacheSegmentSize; + if (TempLength != 0) + { + TempLength = min (Length, Bcb->CacheSegmentSize - TempLength); + Status = CcRosRequestCacheSegment(Bcb, + ROUND_DOWN(ReadOffset, + Bcb->CacheSegmentSize), + &BaseAddress, &Valid, &CacheSeg); + if (!NT_SUCCESS(Status)) + { + IoStatus->Information = 0; + IoStatus->Status = Status; + DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status); + return FALSE; + } + if (!Valid) + { + Status = ReadCacheSegment(CacheSeg); + if (!NT_SUCCESS(Status)) + { + IoStatus->Information = 0; + IoStatus->Status = Status; + return FALSE; + } + } + memcpy (Buffer, BaseAddress + ReadOffset % Bcb->CacheSegmentSize, + TempLength); + CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE); + ReadLength += TempLength; + Length -= TempLength; + ReadOffset += TempLength; + Buffer += TempLength; + } + while (Length > 0) + { + TempLength = min(max(Bcb->CacheSegmentSize, 65536), Length); + ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer); + ReadLength += TempLength; + Length -= TempLength; + ReadOffset += TempLength; + Buffer += TempLength; + } + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = ReadLength; + DPRINT("CcCopyRead O.K.\n"); + return TRUE; +} + +BOOLEAN STDCALL +CcCopyWrite (IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN PVOID Buffer) +{ + NTSTATUS Status; + ULONG WriteOffset; + KIRQL oldirql; + PBCB Bcb; + PLIST_ENTRY current_entry; + PCACHE_SEGMENT CacheSeg; + ULONG TempLength; + PVOID BaseAddress; + BOOLEAN Valid; + + DPRINT("CcCopyWrite(FileObject %x, FileOffset %x, " + "Length %d, Wait %d, Buffer %x)\n", + FileObject, (ULONG)FileOffset->QuadPart, Length, Wait, Buffer); + + Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb; + WriteOffset = (ULONG)FileOffset->QuadPart; + + if (!Wait) + { + /* testing, if the requested datas are available */ + KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + if (!CacheSeg->Valid) + { + if ((WriteOffset >= CacheSeg->FileOffset && + WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize) + || (WriteOffset + Length > CacheSeg->FileOffset && + WriteOffset + Length <= CacheSeg->FileOffset + + Bcb->CacheSegmentSize)) + { + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + /* datas not available */ + return(FALSE); + } + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + } + + TempLength = WriteOffset % Bcb->CacheSegmentSize; + if (TempLength != 0) + { + ULONG ROffset; + ROffset = ROUND_DOWN(WriteOffset, Bcb->CacheSegmentSize); + TempLength = min (Length, Bcb->CacheSegmentSize - TempLength); + Status = CcRosRequestCacheSegment(Bcb, ROffset, + &BaseAddress, &Valid, &CacheSeg); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + if (!Valid) + { + if (!NT_SUCCESS(ReadCacheSegment(CacheSeg))) + { + return(FALSE); + } + } + memcpy (BaseAddress + WriteOffset % Bcb->CacheSegmentSize, + Buffer, TempLength); + CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE); + + Length -= TempLength; + WriteOffset += TempLength; + Buffer += TempLength; + } + + while (Length > 0) + { + TempLength = min (Bcb->CacheSegmentSize, Length); + Status = CcRosRequestCacheSegment(Bcb, WriteOffset, + &BaseAddress, &Valid, &CacheSeg); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + if (!Valid && TempLength < Bcb->CacheSegmentSize) + { + if (!NT_SUCCESS(ReadCacheSegment(CacheSeg))) + { + return FALSE; + } + } + memcpy (BaseAddress, Buffer, TempLength); + CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE); + Length -= TempLength; + WriteOffset += TempLength; + Buffer += TempLength; + } + return(TRUE); +} + +BOOLEAN STDCALL +CcZeroData (IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER StartOffset, + IN PLARGE_INTEGER EndOffset, + IN BOOLEAN Wait) +{ + NTSTATUS Status; + LARGE_INTEGER WriteOffset; + ULONG Length; + PMDL Mdl; + ULONG i; + IO_STATUS_BLOCK Iosb; + KEVENT Event; + + DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, " + "Wait %d\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart, + Wait); + + Length = EndOffset->u.LowPart - StartOffset->u.LowPart; + + /* + * FIXME: NT uses the shared cache map field for cached/non cached detection + */ + if (FileObject->SectionObjectPointers->SharedCacheMap == NULL) + { + /* File is not cached */ + WriteOffset.QuadPart = StartOffset->QuadPart; + + while (Length > 0) + { + if (Length + WriteOffset.u.LowPart % PAGE_SIZE > 262144) + { + Mdl = MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, + 262144 - WriteOffset.u.LowPart % PAGE_SIZE); + WriteOffset.QuadPart += + (262144 - WriteOffset.u.LowPart % PAGE_SIZE); + Length -= (262144 - WriteOffset.u.LowPart % PAGE_SIZE); + } + else + { + Mdl = + MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart, + Length - WriteOffset.u.LowPart % PAGE_SIZE); + WriteOffset.QuadPart += + (Length - WriteOffset.u.LowPart % PAGE_SIZE); + Length = 0; + } + if (Mdl == NULL) + { + return(FALSE); + } + Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ); + for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++) + { + ((PULONG)(Mdl + 1))[i] = CcZeroPage.u.LowPart; + } + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageWrite(FileObject, Mdl, StartOffset, &Event, &Iosb); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = Iosb.Status; + } + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + } + } + else + { + /* File is cached */ + KIRQL oldirql; + PBCB Bcb; + PLIST_ENTRY current_entry; + PCACHE_SEGMENT CacheSeg, current, previous; + ULONG TempLength; + ULONG Start; + ULONG count; + ULONG size; + PHYSICAL_ADDRESS page; + + Start = StartOffset->u.LowPart; + Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb; + if (Wait) + { + /* testing, if the requested datas are available */ + KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + if (!CacheSeg->Valid) + { + if ((Start >= CacheSeg->FileOffset && + Start < CacheSeg->FileOffset + Bcb->CacheSegmentSize) + || (Start + Length > CacheSeg->FileOffset && + Start + Length <= + CacheSeg->FileOffset + Bcb->CacheSegmentSize)) + { + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + /* datas not available */ + return(FALSE); + } + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + } + + while (Length > 0) + { + ULONG RStart = ROUND_DOWN(Start, Bcb->CacheSegmentSize); + WriteOffset.QuadPart = ROUND_DOWN(Start, Bcb->CacheSegmentSize); + if (Start % Bcb->CacheSegmentSize + Length > 262144) + { + Mdl = MmCreateMdl(NULL, NULL, 262144); + if (Mdl == NULL) + { + return FALSE; + } + Status = CcRosGetCacheSegmentChain (Bcb, RStart, + 262144, &CacheSeg); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Mdl); + return(FALSE); + } + } + else + { + ULONG RLength; + RLength = Start % Bcb->CacheSegmentSize + Length; + RLength = ROUND_UP(RLength, Bcb->CacheSegmentSize); + Mdl = MmCreateMdl(NULL, (PVOID)RStart, RLength); + if (Mdl == NULL) + { + return(FALSE); + } + Status = CcRosGetCacheSegmentChain (Bcb, RStart, RLength, + &CacheSeg); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Mdl); + return(FALSE); + } + } + Mdl->MdlFlags |= (MDL_PAGES_LOCKED|MDL_IO_PAGE_READ); + current = CacheSeg; + count = 0; + while (current != NULL) + { + if ((Start % Bcb->CacheSegmentSize) != 0 || + Start % Bcb->CacheSegmentSize + Length < + Bcb->CacheSegmentSize) + { + if (!current->Valid) + { + /* Segment lesen */ + Status = ReadCacheSegment(current); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ReadCacheSegment failed, status %x\n", + Status); + } + } + TempLength = min (Length, Bcb->CacheSegmentSize - + Start % Bcb->CacheSegmentSize); + memset (current->BaseAddress + Start % Bcb->CacheSegmentSize, + 0, TempLength); + } + else + { + TempLength = Bcb->CacheSegmentSize; + memset (current->BaseAddress, 0, Bcb->CacheSegmentSize); + } + Start += TempLength; + Length -= TempLength; + + size = ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); + for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE) && + count < size; i++) + { + PVOID Address; + Address = current->BaseAddress + (i * PAGE_SIZE); + page = + MmGetPhysicalAddressForProcess(NULL, Address); + ((PULONG)(Mdl + 1))[count++] = page.u.LowPart; + } + current = current->NextInChain; + } + + /* Write the Segment */ + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + Status = Iosb.Status; + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("IoPageWrite failed, status %x\n", Status); + } + current = CacheSeg; + while (current != NULL) + { + previous = current; + current = current->NextInChain; + CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE); + } + } + } + return(TRUE); +} + diff --git a/ntoskrnl/cc/misc.c b/ntoskrnl/cc/misc.c new file mode 100644 index 0000000..18bf9cf --- /dev/null +++ b/ntoskrnl/cc/misc.c @@ -0,0 +1,109 @@ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME INTERNAL + * CcMdlReadCompleteDev@8 + * + * DESCRIPTION + * + * ARGUMENTS + * MdlChain + * DeviceObject + * + * RETURN VALUE + * None. + * + * NOTE + * Used by CcMdlReadComplete@8 and FsRtl + */ +VOID STDCALL +CcMdlReadCompleteDev (IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject) +{ + UNIMPLEMENTED; +} + + +/********************************************************************** + * NAME EXPORTED + * CcMdlReadComplete@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * None. + * + * NOTE + * From Bo Branten's ntifs.h v13. + */ +VOID STDCALL +CcMdlReadComplete (IN PFILE_OBJECT FileObject, + IN PMDL MdlChain) +{ + PDEVICE_OBJECT DeviceObject = NULL; + + DeviceObject = IoGetRelatedDeviceObject (FileObject); + /* FIXME: try fast I/O first */ + CcMdlReadCompleteDev (MdlChain, + DeviceObject); +} + +VOID STDCALL +CcSetFileSizes (IN PFILE_OBJECT FileObject, + IN PCC_FILE_SIZES FileSizes) +{ + KIRQL oldirql; + PBCB Bcb; + PLIST_ENTRY current_entry; + PCACHE_SEGMENT current; + + DPRINT("CcSetFileSizes(FileObject %x, FileSizes %x)\n", + FileObject, FileSizes); + DPRINT("AllocationSize %d, FileSize %d, ValidDataLength %d\n", + (ULONG)FileSizes->AllocationSize.QuadPart, + (ULONG)FileSizes->FileSize.QuadPart, + (ULONG)FileSizes->ValidDataLength.QuadPart); + + Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb; + + KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + + if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart) + { + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + current_entry = current_entry->Flink; + if (current->FileOffset > FileSizes->AllocationSize.QuadPart) + { + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); + CcRosFreeCacheSegment(Bcb, current); + KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); + current_entry = Bcb->BcbSegmentListHead.Flink; + } + } + } + Bcb->AllocationSize = FileSizes->AllocationSize; + Bcb->FileSize = FileSizes->FileSize; + KeReleaseSpinLock(&Bcb->BcbLock, oldirql); +} + diff --git a/ntoskrnl/cc/pin.c b/ntoskrnl/cc/pin.c new file mode 100644 index 0000000..c29c2b2 --- /dev/null +++ b/ntoskrnl/cc/pin.c @@ -0,0 +1,127 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cc/pin.c + * PURPOSE: Implements cache managers pinning interface + * PROGRAMMER: Hartmut Birr + * UPDATE HISTORY: + * Created 05.10.2001 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define ROUND_DOWN(N, S) ((N) - ((N) % (S))) + +/* FUNCTIONS *****************************************************************/ + +typedef struct _INTERNAL_BCB +{ + PUBLIC_BCB PFCB; + PCACHE_SEGMENT CacheSegment; + BOOLEAN Dirty; +} INTERNAL_BCB, *PINTERNAL_BCB; + +BOOLEAN STDCALL +CcMapData (IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + OUT PVOID *pBcb, + OUT PVOID *pBuffer) +{ + ULONG ReadOffset; + BOOLEAN Valid; + PBCB Bcb; + PCACHE_SEGMENT CacheSeg; + NTSTATUS Status; + PINTERNAL_BCB iBcb; + ULONG ROffset; + + DPRINT("CcMapData(FileObject %x, FileOffset %d, Length %d, Wait %d," + " pBcb %x, pBuffer %x)\n", FileObject, (ULONG)FileOffset->QuadPart, + Length, Wait, pBcb, pBuffer); + + ReadOffset = FileOffset->QuadPart; + Bcb = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->Bcb; + + DPRINT("AllocationSize %d, FileSize %d\n", + (ULONG)Bcb->AllocationSize.QuadPart, + (ULONG)Bcb->FileSize.QuadPart); + + if (ReadOffset % Bcb->CacheSegmentSize + Length > Bcb->CacheSegmentSize) + { + return(FALSE); + } + ROffset = ROUND_DOWN (ReadOffset, Bcb->CacheSegmentSize); + Status = CcRosRequestCacheSegment(Bcb, + ROffset, + pBuffer, + &Valid, + &CacheSeg); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + if (!Valid) + { + if (!Wait) + { + CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); + return(FALSE); + } + if (!NT_SUCCESS(ReadCacheSegment(CacheSeg))) + { + CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE); + return(FALSE); + } + } + *pBuffer += ReadOffset % Bcb->CacheSegmentSize; + iBcb = ExAllocatePool (NonPagedPool, sizeof(INTERNAL_BCB)); + if (iBcb == NULL) + { + CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE); + return FALSE; + } + iBcb->CacheSegment = CacheSeg; + iBcb->Dirty = FALSE; + iBcb->PFCB.MappedLength = Length; + iBcb->PFCB.MappedFileOffset.QuadPart = FileOffset->QuadPart; + *pBcb = (PVOID)iBcb; + return(TRUE); +} + +VOID STDCALL +CcUnpinData (IN PVOID Bcb) +{ + PINTERNAL_BCB iBcb = Bcb; + CcRosReleaseCacheSegment(iBcb->CacheSegment->Bcb, iBcb->CacheSegment, TRUE, + iBcb->Dirty, FALSE); + ExFreePool(iBcb); +} + +VOID STDCALL +CcSetDirtyPinnedData (IN PVOID Bcb, + IN PLARGE_INTEGER Lsn) +{ + PINTERNAL_BCB iBcb = Bcb; +#if 0 + iBcb->Dirty = TRUE; +#else + WriteCacheSegment(iBcb->CacheSegment); +#endif +} + diff --git a/ntoskrnl/cc/view.c b/ntoskrnl/cc/view.c new file mode 100644 index 0000000..7a91f81 --- /dev/null +++ b/ntoskrnl/cc/view.c @@ -0,0 +1,916 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cc/view.c + * PURPOSE: Cache manager + * PROGRAMMER: David Welch (welch@mcmail.com) + * PORTABILITY: Checked + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* NOTES ********************************************************************** + * + * This is not the NT implementation of a file cache nor anything much like + * it. + * + * The general procedure for a filesystem to implement a read or write + * dispatch routine is as follows + * + * (1) If caching for the FCB hasn't been initiated then so do by calling + * CcInitializeFileCache. + * + * (2) For each 4k region which is being read or written obtain a cache page + * by calling CcRequestCachePage. + * + * (3) If either the page is being read or not completely written, and it is + * not up to date then read its data from the underlying medium. If the read + * fails then call CcReleaseCachePage with VALID as FALSE and return a error. + * + * (4) Copy the data into or out of the page as necessary. + * + * (5) Release the cache page + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#define ROUND_DOWN(N, S) (((N) % (S)) ? ROUND_UP(N, S) - S : N) + +#define TAG_CSEG TAG('C', 'S', 'E', 'G') +#define TAG_BCB TAG('B', 'C', 'B', ' ') + +static LIST_ENTRY DirtySegmentListHead; +static LIST_ENTRY CacheSegmentListHead; +static LIST_ENTRY CacheSegmentLRUListHead; + +static FAST_MUTEX ViewLock; + +void * alloca(size_t size); + +NTSTATUS STDCALL +CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg); + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STATIC +CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSegment) +{ + NTSTATUS Status; + KIRQL oldIrql; + Status = WriteCacheSegment(CacheSegment); + if (NT_SUCCESS(Status)) + { + ExAcquireFastMutex(&ViewLock); + KeAcquireSpinLock(&CacheSegment->Bcb->BcbLock, &oldIrql); + CacheSegment->Dirty = FALSE; + RemoveEntryList(&CacheSegment->DirtySegmentListEntry); + CacheSegment->ReferenceCount--; + KeReleaseSpinLock(&CacheSegment->Bcb->BcbLock, oldIrql); + ExReleaseFastMutex(&ViewLock); + } + return(Status); +} + +NTSTATUS +CcRosFlushDirtyPages(ULONG Target, PULONG Count) +{ + PLIST_ENTRY current_entry; + PCACHE_SEGMENT current; + ULONG PagesPerSegment; + BOOLEAN Locked; + NTSTATUS Status; + + DPRINT("CcRosFlushDirtyPages(Target %d)\n", Target); + + (*Count) = 0; + + ExAcquireFastMutex(&ViewLock); + current_entry = DirtySegmentListHead.Flink; + while (current_entry != &DirtySegmentListHead && Target > 0) + { + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + DirtySegmentListEntry); + current_entry = current_entry->Flink; + Locked = ExTryToAcquireFastMutex(¤t->Lock); + if (!Locked) + { + continue; + } + assert(current->Dirty); + if (current->ReferenceCount > 1) + { + ExReleaseFastMutex(¤t->Lock); + continue; + } + ExReleaseFastMutex(&ViewLock); + PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE; + Status = CcRosFlushCacheSegment(current); + ExReleaseFastMutex(¤t->Lock); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CC: Failed to flush cache segment.\n"); + } + else + { + (*Count) += PagesPerSegment; + Target -= PagesPerSegment; + } + ExAcquireFastMutex(&ViewLock); + current_entry = DirtySegmentListHead.Flink; + } + ExReleaseFastMutex(&ViewLock); + DPRINT("CcRosTrimCache() finished\n"); + return(STATUS_SUCCESS); +} + +NTSTATUS +CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed) +/* + * FUNCTION: Try to free some memory from the file cache. + * ARGUMENTS: + * Target - The number of pages to be freed. + * Priority - The priority of free (currently unused). + * NrFreed - Points to a variable where the number of pages + * actually freed is returned. + */ +{ + PLIST_ENTRY current_entry; + PCACHE_SEGMENT current; + ULONG PagesPerSegment; + ULONG PagesFreed; + KIRQL oldIrql; + LIST_ENTRY FreeList; + + DPRINT("CcRosTrimCache(Target %d)\n", Target); + + *NrFreed = 0; + + InitializeListHead(&FreeList); + + ExAcquireFastMutex(&ViewLock); + current_entry = CacheSegmentLRUListHead.Flink; + while (current_entry != &CacheSegmentLRUListHead && Target > 0) + { + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + CacheSegmentLRUListEntry); + current_entry = current_entry->Flink; + + KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql); + if (current->ReferenceCount == 0) + { + RemoveEntryList(¤t->BcbSegmentListEntry); + KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); + RemoveEntryList(¤t->CacheSegmentListEntry); + RemoveEntryList(¤t->CacheSegmentLRUListEntry); + InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry); + } + else + { + KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); + } + } + ExReleaseFastMutex(&ViewLock); + + while (!IsListEmpty(&FreeList)) + { + current_entry = RemoveHeadList(&FreeList); + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE; + PagesFreed = min(PagesPerSegment, Target); + Target -= PagesFreed; + (*NrFreed) += PagesFreed; + CcRosInternalFreeCacheSegment(current); + } + + DPRINT("CcRosTrimCache() finished\n"); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CcRosReleaseCacheSegment(PBCB Bcb, + PCACHE_SEGMENT CacheSeg, + BOOLEAN Valid, + BOOLEAN Dirty, + BOOLEAN Mapped) +{ + BOOLEAN WasDirty = CacheSeg->Dirty; + KIRQL oldIrql; + + DPRINT("CcReleaseCacheSegment(Bcb %x, CacheSeg %x, Valid %d)\n", + Bcb, CacheSeg, Valid); + + CacheSeg->Valid = Valid; + CacheSeg->Dirty = CacheSeg->Dirty || Dirty; + + ExAcquireFastMutex(&ViewLock); + if (!WasDirty && CacheSeg->Dirty) + { + InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); + } + RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry); + InsertTailList(&CacheSegmentLRUListHead, &CacheSeg->CacheSegmentLRUListEntry); + + if (Mapped) + { + CacheSeg->MappedCount++; + } + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + CacheSeg->ReferenceCount--; + if (Mapped && CacheSeg->MappedCount == 1) + { + CacheSeg->ReferenceCount++; + } + if (!WasDirty && CacheSeg->Dirty) + { + CacheSeg->ReferenceCount++; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + ExReleaseFastMutex(&ViewLock); + ExReleaseFastMutex(&CacheSeg->Lock); + + return(STATUS_SUCCESS); +} + +PCACHE_SEGMENT CcRosLookupCacheSegment(PBCB Bcb, ULONG FileOffset) +{ + PLIST_ENTRY current_entry; + PCACHE_SEGMENT current; + KIRQL oldIrql; + + DPRINT("CcRosLookupCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset); + + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + if (current->FileOffset <= FileOffset && + (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset) + { + current->ReferenceCount++; + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + return(current); + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + return(NULL); +} + +NTSTATUS +CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset) +{ + PCACHE_SEGMENT CacheSeg; + KIRQL oldIrql; + + DPRINT("CcRosMarkDirtyCacheSegment(Bcb %x, FileOffset %d)\n", Bcb, FileOffset); + + CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset); + if (CacheSeg == NULL) + { + KeBugCheck(0); + } + ExAcquireFastMutex(&CacheSeg->Lock); + if (!CacheSeg->Dirty) + { + ExAcquireFastMutex(&ViewLock); + InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); + ExReleaseFastMutex(&ViewLock); + } + else + { + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + CacheSeg->ReferenceCount--; + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + } + + + CacheSeg->Dirty = TRUE; + ExReleaseFastMutex(&CacheSeg->Lock); + + return(STATUS_SUCCESS); +} + +NTSTATUS +CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty) +{ + PCACHE_SEGMENT CacheSeg; + BOOLEAN WasDirty; + KIRQL oldIrql; + + DPRINT("CcRosUnmapCacheSegment(Bcb %x, FileOffset %d, NowDirty %d)\n", + Bcb, FileOffset, NowDirty); + + CacheSeg = CcRosLookupCacheSegment(Bcb, FileOffset); + if (CacheSeg == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + ExAcquireFastMutex(&CacheSeg->Lock); + + WasDirty = CacheSeg->Dirty; + CacheSeg->Dirty = CacheSeg->Dirty || NowDirty; + + CacheSeg->MappedCount--; + + if (!WasDirty && NowDirty) + { + ExAcquireFastMutex(&ViewLock); + InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); + ExReleaseFastMutex(&ViewLock); + } + + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + CacheSeg->ReferenceCount--; + if (!WasDirty && NowDirty) + { + CacheSeg->ReferenceCount++; + } + if (CacheSeg->MappedCount == 0) + { + CacheSeg->ReferenceCount--; + } + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + + ExReleaseFastMutex(&CacheSeg->Lock); + return(STATUS_SUCCESS); +} + +NTSTATUS STATIC +CcRosCreateCacheSegment(PBCB Bcb, + ULONG FileOffset, + PCACHE_SEGMENT* CacheSeg, + BOOLEAN Lock) +{ + ULONG i; + PCACHE_SEGMENT current; + PLIST_ENTRY current_entry; + NTSTATUS Status; + KIRQL oldIrql; + + DPRINT("CcRosCreateCacheSegment()\n"); + + current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT), + TAG_CSEG); + current->Valid = FALSE; + current->Dirty = FALSE; + current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize); + current->Bcb = Bcb; + current->MappedCount = 0; + current->DirtySegmentListEntry.Flink = NULL; + current->DirtySegmentListEntry.Blink = NULL; + current->ReferenceCount = 1; + ExInitializeFastMutex(¤t->Lock); + ExAcquireFastMutex(¤t->Lock); + ExAcquireFastMutex(&ViewLock); + + *CacheSeg = current; + /* There is window between the call to CcRosLookupCacheSegment + * and CcRosCreateCacheSegment. We must check if a segment on + * the fileoffset exist. If there exist a segment, we release + * our new created segment and return the existing one. + */ + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) + { + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, + BcbSegmentListEntry); + if (current->FileOffset <= FileOffset && + (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset) + { + current->ReferenceCount++; + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + ExReleaseFastMutex(&(*CacheSeg)->Lock); + ExReleaseFastMutex(&ViewLock); + ExFreePool(*CacheSeg); + *CacheSeg = current; + if (Lock) + { + ExAcquireFastMutex(¤t->Lock); + } + return STATUS_SUCCESS; + } + current_entry = current_entry->Flink; + } + /* There was no existing segment. */ + current = *CacheSeg; + InsertTailList(&Bcb->BcbSegmentListHead, ¤t->BcbSegmentListEntry); + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry); + InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry); + ExReleaseFastMutex(&ViewLock); + + MmLockAddressSpace(MmGetKernelAddressSpace()); + current->BaseAddress = NULL; + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_CACHE_SEGMENT, + ¤t->BaseAddress, + Bcb->CacheSegmentSize, + PAGE_READWRITE, + (PMEMORY_AREA*)¤t->MemoryArea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++) + { + PHYSICAL_ADDRESS Page; + + Status = MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + + Status = MmCreateVirtualMapping(NULL, + current->BaseAddress + (i * PAGE_SIZE), + PAGE_READWRITE, + Page, + TRUE); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + if (!Lock) + { + ExReleaseFastMutex(¤t->Lock); + } + + return(STATUS_SUCCESS); +} + +NTSTATUS +CcRosGetCacheSegmentChain(PBCB Bcb, + ULONG FileOffset, + ULONG Length, + PCACHE_SEGMENT* CacheSeg) +{ + PCACHE_SEGMENT current; + ULONG i; + PCACHE_SEGMENT* CacheSegList; + PCACHE_SEGMENT Previous = NULL; + + DPRINT("CcRosGetCacheSegmentChain()\n"); + + Length = ROUND_UP(Length, Bcb->CacheSegmentSize); + + CacheSegList = alloca(sizeof(PCACHE_SEGMENT) * + (Length / Bcb->CacheSegmentSize)); + + /* + * Look for a cache segment already mapping the same data. + */ + for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++) + { + ULONG CurrentOffset = FileOffset + (i * Bcb->CacheSegmentSize); + current = CcRosLookupCacheSegment(Bcb, CurrentOffset); + if (current != NULL) + { + CacheSegList[i] = current; + } + else + { + CcRosCreateCacheSegment(Bcb, CurrentOffset, ¤t, FALSE); + CacheSegList[i] = current; + } + } + + for (i = 0; i < (Length / Bcb->CacheSegmentSize); i++) + { + ExAcquireFastMutex(&CacheSegList[i]->Lock); + if (i == 0) + { + *CacheSeg = CacheSegList[i]; + Previous = CacheSegList[i]; + } + else + { + Previous->NextInChain = CacheSegList[i]; + Previous = CacheSegList[i]; + } + } + Previous->NextInChain = NULL; + + return(STATUS_SUCCESS); +} + +NTSTATUS +CcRosGetCacheSegment(PBCB Bcb, + ULONG FileOffset, + PULONG BaseOffset, + PVOID* BaseAddress, + PBOOLEAN UptoDate, + PCACHE_SEGMENT* CacheSeg) +{ + PCACHE_SEGMENT current; + NTSTATUS Status; + + DPRINT("CcRosGetCacheSegment()\n"); + + /* + * Look for a cache segment already mapping the same data. + */ + current = CcRosLookupCacheSegment(Bcb, FileOffset); + if (current != NULL) + { + ExAcquireFastMutex(¤t->Lock); + } + else + { + /* + * Otherwise create a new segment. + */ + Status = CcRosCreateCacheSegment(Bcb, FileOffset, ¤t, TRUE); + } + /* + * Return information about the segment to the caller. + */ + *UptoDate = current->Valid; + *BaseAddress = current->BaseAddress; + DPRINT("*BaseAddress 0x%.8X\n", *BaseAddress); + *CacheSeg = current; + *BaseOffset = current->FileOffset; + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CcRosRequestCacheSegment(PBCB Bcb, + ULONG FileOffset, + PVOID* BaseAddress, + PBOOLEAN UptoDate, + PCACHE_SEGMENT* CacheSeg) +/* + * FUNCTION: Request a page mapping for a BCB + */ +{ + ULONG BaseOffset; + + if ((FileOffset % Bcb->CacheSegmentSize) != 0) + { + CPRINT("Bad fileoffset %x should be multiple of %x", + FileOffset, Bcb->CacheSegmentSize); + KeBugCheck(0); + } + + return(CcRosGetCacheSegment(Bcb, + FileOffset, + &BaseOffset, + BaseAddress, + UptoDate, + CacheSeg)); +} + +STATIC VOID +CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty) +{ + assert(SwapEntry == 0); + if (PhysAddr.QuadPart != 0) + { + MmReleasePageMemoryConsumer(MC_CACHE, PhysAddr); + } +} + +NTSTATUS STDCALL +CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg) +/* + * FUNCTION: Releases a cache segment associated with a BCB + */ +{ + + DPRINT("Freeing cache segment %x\n", CacheSeg); + + MmLockAddressSpace(MmGetKernelAddressSpace()); + MmFreeMemoryArea(MmGetKernelAddressSpace(), + CacheSeg->BaseAddress, + CacheSeg->Bcb->CacheSegmentSize, + CcFreeCachePage, + NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + ExFreePool(CacheSeg); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg) +{ + NTSTATUS Status; + KIRQL oldIrql; + + DPRINT("CcRosFreeCacheSegment(Bcb %x, CacheSeg %x)\n", + Bcb, CacheSeg); + + ExAcquireFastMutex(&ViewLock); + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + RemoveEntryList(&CacheSeg->BcbSegmentListEntry); + RemoveEntryList(&CacheSeg->CacheSegmentListEntry); + RemoveEntryList(&CacheSeg->CacheSegmentLRUListEntry); + if (CacheSeg->Dirty) + { + RemoveEntryList(&CacheSeg->DirtySegmentListEntry); + } + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + ExReleaseFastMutex(&ViewLock); + + Status = CcRosInternalFreeCacheSegment(CacheSeg); + return(Status); +} + +VOID STDCALL +CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointers, + IN PLARGE_INTEGER FileOffset OPTIONAL, + IN ULONG Length, + OUT PIO_STATUS_BLOCK IoStatus) +{ + PBCB Bcb; + LARGE_INTEGER Offset; + PCACHE_SEGMENT current; + NTSTATUS Status; + KIRQL oldIrql; + + DPRINT("CcFlushCache(SectionObjectPointers %x, FileOffset %x, Length %d, IoStatus %x)\n", + SectionObjectPointers, FileOffset, Length, IoStatus); + + if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap) + { + Bcb = (PBCB)SectionObjectPointers->SharedCacheMap; + if (FileOffset) + { + Offset = *FileOffset; + } + else + { + Offset.QuadPart = 0LL; + Length = Bcb->FileSize.u.LowPart; + } + + if (IoStatus) + { + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = 0; + } + + while (Length > 0) + { + current = CcRosLookupCacheSegment (Bcb, Offset.u.LowPart); + if (current != NULL) + { + ExAcquireFastMutex(¤t->Lock); + if (current->Dirty) + { + Status = CcRosFlushCacheSegment(current); + if (!NT_SUCCESS(Status) && IoStatus != NULL) + { + IoStatus->Status = Status; + } + } + ExReleaseFastMutex(¤t->Lock); + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + current->ReferenceCount--; + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + } + + Offset.QuadPart += Bcb->CacheSegmentSize; + if (Length > Bcb->CacheSegmentSize) + { + Length -= Bcb->CacheSegmentSize; + } + else + { + Length = 0; + } + } + } + else + { + if (IoStatus) + { + IoStatus->Status = STATUS_INVALID_PARAMETER; + } + } +} + +NTSTATUS STDCALL +CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb) +/* + * FUNCTION: Releases the BCB associated with a file object + */ +{ + PLIST_ENTRY current_entry; + PCACHE_SEGMENT current; + NTSTATUS Status; + LIST_ENTRY FreeList; + KIRQL oldIrql; + + DPRINT("CcRosDeleteFileCache(FileObject %x, Bcb %x)\n", + Bcb->FileObject, Bcb); + + ExReleaseFastMutex(&ViewLock); + + CcFlushCache(FileObject->SectionObjectPointers, NULL, 0, NULL); + + ExAcquireFastMutex(&ViewLock); + + if (Bcb->RefCount == 0) + { + MmFreeSectionSegments(Bcb->FileObject); + + /* + * Release all cache segments. + */ + InitializeListHead(&FreeList); + + FileObject->SectionObjectPointers->SharedCacheMap = NULL; + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + current_entry = Bcb->BcbSegmentListHead.Flink; + while (!IsListEmpty(&Bcb->BcbSegmentListHead)) + { + current_entry = RemoveTailList(&Bcb->BcbSegmentListHead); + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); + RemoveEntryList(¤t->CacheSegmentListEntry); + RemoveEntryList(¤t->CacheSegmentLRUListEntry); + if (current->Dirty) + { + RemoveEntryList(¤t->DirtySegmentListEntry); + } + InsertHeadList(&FreeList, ¤t->BcbSegmentListEntry); + + } + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + while (!IsListEmpty(&FreeList)) + { + current_entry = RemoveTailList(&FreeList); + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); + Status = CcRosInternalFreeCacheSegment(current); + } + + ObDereferenceObject (Bcb->FileObject); + ExFreePool(Bcb); + } + return(STATUS_SUCCESS); +} + +VOID CcRosReferenceCache(PFILE_OBJECT FileObject) +{ + PBCB Bcb; + ExAcquireFastMutex(&ViewLock); + Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap; + Bcb->RefCount++; + ExReleaseFastMutex(&ViewLock); +} + +VOID CcRosDereferenceCache(PFILE_OBJECT FileObject) +{ + PBCB Bcb; + ExAcquireFastMutex(&ViewLock); + Bcb = (PBCB)FileObject->SectionObjectPointers->SharedCacheMap; + Bcb->RefCount--; + if (Bcb->RefCount == 0) + { + CcRosDeleteFileCache(FileObject, Bcb); + } + ExReleaseFastMutex(&ViewLock); +} + +NTSTATUS STDCALL +CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb) +/* + * FUNCTION: Called by the file system when a handle to a file object + * has been closed. + */ +{ + ExAcquireFastMutex(&ViewLock); + + if (FileObject->SectionObjectPointers->SharedCacheMap != NULL) + { + if (FileObject->PrivateCacheMap != NULL) + { + FileObject->PrivateCacheMap = NULL; + Bcb->RefCount--; + } + if (Bcb->RefCount == 0) + { + CcRosDeleteFileCache(FileObject, Bcb); + } + } + ExReleaseFastMutex(&ViewLock); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +CcRosInitializeFileCache(PFILE_OBJECT FileObject, + PBCB* Bcb, + ULONG CacheSegmentSize) +/* + * FUNCTION: Initializes a BCB for a file object + */ +{ + DPRINT("CcRosInitializeFileCache(FileObject %x, *Bcb %x, CacheSegmentSize %d)\n", + FileObject, Bcb, CacheSegmentSize); + + ExAcquireFastMutex(&ViewLock); + + if (*Bcb == NULL) + { + (*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB); + if ((*Bcb) == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + ObReferenceObjectByPointer(FileObject, + FILE_ALL_ACCESS, + NULL, + KernelMode); + (*Bcb)->FileObject = FileObject; + (*Bcb)->CacheSegmentSize = CacheSegmentSize; + if (FileObject->FsContext) + { + (*Bcb)->AllocationSize = + ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize; + (*Bcb)->FileSize = + ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize; + } + KeInitializeSpinLock(&(*Bcb)->BcbLock); + InitializeListHead(&(*Bcb)->BcbSegmentListHead); + FileObject->SectionObjectPointers->SharedCacheMap = *Bcb; + } + if (FileObject->PrivateCacheMap == NULL) + { + FileObject->PrivateCacheMap = *Bcb; + (*Bcb)->RefCount++; + } + ExReleaseFastMutex(&ViewLock); + + return(STATUS_SUCCESS); +} + +PFILE_OBJECT STDCALL +CcGetFileObjectFromSectionPtrs(IN PSECTION_OBJECT_POINTERS SectionObjectPointers) +{ + PBCB Bcb; + if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap) + { + Bcb = (PBCB)SectionObjectPointers->SharedCacheMap; + return Bcb->FileObject; + } + return NULL; +} + +VOID +CcInitView(VOID) +{ + DPRINT("CcInitView()\n"); + InitializeListHead(&CacheSegmentListHead); + InitializeListHead(&DirtySegmentListHead); + InitializeListHead(&CacheSegmentLRUListHead); + ExInitializeFastMutex(&ViewLock); + MmInitializeMemoryConsumer(MC_CACHE, CcRosTrimCache); + CcInitCacheZeroPage(); +} + +/* EOF */ + + + + + + + diff --git a/ntoskrnl/cm/.cvsignore b/ntoskrnl/cm/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/cm/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/cm/cm.h b/ntoskrnl/cm/cm.h new file mode 100644 index 0000000..69a345d --- /dev/null +++ b/ntoskrnl/cm/cm.h @@ -0,0 +1,499 @@ +#ifndef __INCLUDE_CM_H +#define __INCLUDE_CM_H + +#ifdef DBG +#define CHECKED 1 +#else +#define CHECKED 0 +#endif + +#define REG_ROOT_KEY_NAME L"\\Registry" +#define REG_MACHINE_KEY_NAME L"\\Registry\\Machine" +#define REG_HARDWARE_KEY_NAME L"\\Registry\\Machine\\HARDWARE" +#define REG_DESCRIPTION_KEY_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION" +#define REG_DEVICEMAP_KEY_NAME L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP" +#define REG_RESOURCEMAP_KEY_NAME L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP" +#define REG_CLASSES_KEY_NAME L"\\Registry\\Machine\\Software\\Classes" +#define REG_SYSTEM_KEY_NAME L"\\Registry\\Machine\\System" +#define REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software" +#define REG_SAM_KEY_NAME L"\\Registry\\Machine\\Sam" +#define REG_SEC_KEY_NAME L"\\Registry\\Machine\\Security" +#define REG_USERS_KEY_NAME L"\\Registry\\User" +#define REG_USER_KEY_NAME L"\\Registry\\User\\CurrentUser" +#define SYSTEM_REG_FILE L"\\SystemRoot\\System32\\Config\\SYSTEM" +#define SOFTWARE_REG_FILE L"\\SystemRoot\\System32\\Config\\SOFTWARE" +#define USER_REG_FILE L"\\SystemRoot\\System32\\Config\\DEFAULT" +#define SAM_REG_FILE L"\\SystemRoot\\System32\\Config\\SAM" +#define SEC_REG_FILE L"\\SystemRoot\\System32\\Config\\SECURITY" + +#define REG_BLOCK_SIZE 4096 +#define REG_HBIN_DATA_OFFSET 32 +#define REG_BIN_ID 0x6e696268 +#define REG_INIT_BLOCK_LIST_SIZE 32 +#define REG_INIT_HASH_TABLE_SIZE 3 +#define REG_EXTEND_HASH_TABLE_SIZE 4 +#define REG_VALUE_LIST_CELL_MULTIPLE 4 +#define REG_KEY_CELL_ID 0x6b6e +#define REG_HASH_TABLE_BLOCK_ID 0x666c +#define REG_VALUE_CELL_ID 0x6b76 +#define REG_LINK_KEY_CELL_TYPE 0x10 +#define REG_KEY_CELL_TYPE 0x20 +#define REG_ROOT_KEY_CELL_TYPE 0x2c +#define REG_HIVE_ID 0x66676572 + +#define REGISTRY_FILE_MAGIC "REGEDIT4" + +#define REG_MACHINE_STD_HANDLE_NAME "HKEY_LOCAL_MACHINE" +#define REG_CLASSES_STD_HANDLE_NAME "HKEY_CLASSES_ROOT" +#define REG_USERS_STD_HANDLE_NAME "HKEY_USERS" +#define REG_USER_STD_HANDLE_NAME "HKEY_CURRENT_USER" +#define REG_CONFIG_STD_HANDLE_NAME "HKEY_CURRENT_CONFIG" +#define REG_DYN_STD_HANDLE_NAME "HKEY_DYN_DATA" +#define MAX_REG_STD_HANDLE_NAME 19 + +// BLOCK_OFFSET = offset in file after header block +typedef DWORD BLOCK_OFFSET; + +/* header for registry hive file : */ +typedef struct _HIVE_HEADER +{ + /* Hive identifier "regf" (0x66676572) */ + ULONG BlockId; + + /* File version ? */ + ULONG Version; + + /* File version ? - same as Version */ + ULONG VersionOld; + + /* When this hive file was last modified */ + FILETIME DateModified; + + /* Registry format version ? (1?) */ + ULONG Unused3; + + /* Registry format version ? (3?) */ + ULONG Unused4; + + /* Registry format version ? (0?) */ + ULONG Unused5; + + /* Registry format version ? (1?) */ + ULONG Unused6; + + /* Offset into file from the byte after the end of the base block. + If the hive is volatile, this is the actual pointer to the KEY_CELL */ + BLOCK_OFFSET RootKeyCell; + + /* Size of each hive block ? */ + ULONG BlockSize; + + /* (1?) */ + ULONG Unused7; + + /* Name of hive file */ + WCHAR FileName[64]; + + /* ? */ + ULONG Unused8[83]; + + /* Checksum of first 0x200 bytes */ + ULONG Checksum; +} __attribute__((packed)) HIVE_HEADER, *PHIVE_HEADER; + +typedef struct _HBIN +{ + /* Bin identifier "hbin" (0x6E696268) */ + ULONG BlockId; + + /* Block offset of this bin */ + BLOCK_OFFSET BlockOffset; + + /* Size in bytes, multiple of the block size (4KB) */ + ULONG BlockSize; + + /* ? */ + ULONG Unused1; + + /* When this bin was last modified */ + FILETIME DateModified; + + /* ? */ + ULONG Unused2; +} __attribute__((packed)) HBIN, *PHBIN; + +typedef struct _CELL_HEADER +{ + /* <0 if used, >0 if free */ + LONG CellSize; +} __attribute__((packed)) CELL_HEADER, *PCELL_HEADER; + +typedef struct _KEY_CELL +{ + /* Size of this cell */ + LONG CellSize; + + /* Key cell identifier "kn" (0x6b6e) */ + USHORT Id; + + /* ? */ + USHORT Type; + + /* Time of last flush */ + FILETIME LastWriteTime; + + /* ? */ + ULONG UnUsed1; + + /* Block offset of parent key cell */ + BLOCK_OFFSET ParentKeyOffset; + + /* Count of sub keys for the key in this key cell */ + ULONG NumberOfSubKeys; + + /* ? */ + ULONG UnUsed2; + + /* Block offset of has table for FIXME: subkeys/values? */ + BLOCK_OFFSET HashTableOffset; + + /* ? */ + ULONG UnUsed3; + + /* Count of values contained in this key cell */ + ULONG NumberOfValues; + + /* Block offset of VALUE_LIST_CELL */ + BLOCK_OFFSET ValuesOffset; + + /* Block offset of security cell */ + BLOCK_OFFSET SecurityKeyOffset; + + /* Block offset of registry key class */ + BLOCK_OFFSET ClassNameOffset; + + /* ? */ + ULONG Unused4[5]; + + /* Size in bytes of key name */ + USHORT NameSize; + + /* Size of class name in bytes */ + USHORT ClassSize; + + /* Name of key (not zero terminated) */ + UCHAR Name[0]; +} __attribute__((packed)) KEY_CELL, *PKEY_CELL; + +// hash record : +// HashValue=four letters of value's name +typedef struct _HASH_RECORD +{ + BLOCK_OFFSET KeyOffset; + ULONG HashValue; +} __attribute__((packed)) HASH_RECORD, *PHASH_RECORD; + +typedef struct _HASH_TABLE_CELL +{ + LONG CellSize; + USHORT Id; + USHORT HashTableSize; + HASH_RECORD Table[0]; +} __attribute__((packed)) HASH_TABLE_CELL, *PHASH_TABLE_CELL; + +typedef struct _VALUE_LIST_CELL +{ + LONG CellSize; + BLOCK_OFFSET Values[0]; +} __attribute__((packed)) VALUE_LIST_CELL, *PVALUE_LIST_CELL; + +typedef struct _VALUE_CELL +{ + LONG CellSize; + USHORT Id; // "kv" + USHORT NameSize; // length of Name + LONG DataSize; // length of datas in the cell pointed by DataOffset + BLOCK_OFFSET DataOffset;// datas are here if high bit of DataSize is set + ULONG DataType; + USHORT Flags; + USHORT Unused1; + UCHAR Name[0]; /* warning : not zero terminated */ +} __attribute__((packed)) VALUE_CELL, *PVALUE_CELL; + +typedef struct _DATA_CELL +{ + LONG CellSize; + UCHAR Data[0]; +} __attribute__((packed)) DATA_CELL, *PDATA_CELL; + +typedef struct _REGISTRY_HIVE +{ + ULONG Flags; + UNICODE_STRING Filename; + ULONG FileSize; + PFILE_OBJECT FileObject; + PVOID Bcb; + PHIVE_HEADER HiveHeader; + ULONG BlockListSize; + PHBIN *BlockList; + ULONG FreeListSize; + ULONG FreeListMax; + PCELL_HEADER *FreeList; + BLOCK_OFFSET *FreeListOffset; +// KSPIN_LOCK RegLock; + KSEMAPHORE RegSem; +// NTSTATUS (*Extend)(ULONG NewSize); +// PVOID (*Flush)(VOID); +} REGISTRY_HIVE, *PREGISTRY_HIVE; + +/* REGISTRY_HIVE.Flags constants */ +#define HIVE_VOLATILE 0x00000001 + +#define IsVolatileHive(Hive)(Hive->Flags & HIVE_VOLATILE) +#define IsPermanentHive(Hive)(!(Hive->Flags & HIVE_VOLATILE)) + +#define IsFreeCell(Cell)(Cell->CellSize >= 0) +#define IsUsedCell(Cell)(Cell->CellSize < 0) + + +/* KEY_OBJECT.Flags */ + +/* When set, the key is scheduled for deletion, and all + attempts to access the key must not succeed */ +#define KO_MARKED_FOR_DELETE 0x00000001 + + +/* Type defining the Object Manager Key Object */ +typedef struct _KEY_OBJECT +{ + /* Fields used by the Object Manager */ + CSHORT Type; + CSHORT Size; + + /* Key flags */ + ULONG Flags; + + /* Length of Name */ + USHORT NameSize; + + /* Name of key */ + PCHAR Name; + + /* Registry hive the key belongs to */ + PREGISTRY_HIVE RegistryHive; + + /* Block offset of the key cell this key belongs in */ + BLOCK_OFFSET BlockOffset; + + /* KEY_CELL this key belong in */ + PKEY_CELL KeyCell; + + /* Link to the parent KEY_OBJECT for this key */ + struct _KEY_OBJECT *ParentKey; + + /* Subkeys loaded in SubKeys */ + ULONG NumberOfSubKeys; + + /* Space allocated in SubKeys */ + ULONG SizeOfSubKeys; + + /* List of subkeys loaded */ + struct _KEY_OBJECT **SubKeys; +} KEY_OBJECT, *PKEY_OBJECT; + +/* Bits 31-22 (top 10 bits) of the cell index is the directory index */ +#define CmiDirectoryIndex(CellIndex)(CellIndex & 0xffc000000) +/* Bits 21-12 (middle 10 bits) of the cell index is the table index */ +#define CmiTableIndex(Cellndex)(CellIndex & 0x003ff000) +/* Bits 11-0 (bottom 12 bits) of the cell index is the byte offset */ +#define CmiByteOffset(Cellndex)(CellIndex & 0x00000fff) + + +extern BOOLEAN CmiDoVerify; +extern PREGISTRY_HIVE CmiVolatileHive; +extern POBJECT_TYPE CmiKeyType; +extern KSPIN_LOCK CmiKeyListLock; + + +VOID +CmiVerifyBinCell(PHBIN BinCell); +VOID +CmiVerifyKeyCell(PKEY_CELL KeyCell); +VOID +CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell); +VOID +CmiVerifyKeyObject(PKEY_OBJECT KeyObject); +VOID +CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive); + +#ifdef DBG +#define VERIFY_BIN_CELL CmiVerifyBinCell +#define VERIFY_KEY_CELL CmiVerifyKeyCell +#define VERIFY_ROOT_KEY_CELL CmiVerifyRootKeyCell +#define VERIFY_VALUE_CELL CmiVerifyValueCell +#define VERIFY_VALUE_LIST_CELL CmiVerifyValueListCell +#define VERIFY_KEY_OBJECT CmiVerifyKeyObject +#define VERIFY_REGISTRY_HIVE CmiVerifyRegistryHive +#else +#define VERIFY_BIN_CELL(x) +#define VERIFY_KEY_CELL(x) +#define VERIFY_ROOT_KEY_CELL(x) +#define VERIFY_VALUE_CELL(x) +#define VERIFY_VALUE_LIST_CELL(x) +#define VERIFY_KEY_OBJECT(x) +#define VERIFY_REGISTRY_HIVE(x) +#endif + +NTSTATUS STDCALL +CmiObjectParse(IN PVOID ParsedObject, + OUT PVOID *NextObject, + IN PUNICODE_STRING FullPath, + IN OUT PWSTR *Path, + IN ULONG Attribute); + +NTSTATUS STDCALL +CmiObjectCreate(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes); + +VOID STDCALL +CmiObjectDelete(PVOID DeletedObject); + +VOID +CmiAddKeyToList(PKEY_OBJECT ParentKey, + IN PKEY_OBJECT NewKey); + +NTSTATUS +CmiRemoveKeyFromList(IN PKEY_OBJECT NewKey); + +PKEY_OBJECT CmiScanKeyList(IN PKEY_OBJECT Parent, + IN PCHAR KeyNameBuf, + IN ULONG Attributes); + +NTSTATUS +CmiCreateRegistryHive(PWSTR Filename, + PREGISTRY_HIVE *RegistryHive, + BOOLEAN CreateNew); + +ULONG +CmiGetMaxNameLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +ULONG +CmiGetMaxClassLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +ULONG +CmiGetMaxValueNameLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +ULONG +CmiGetMaxValueDataLength(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell); + +NTSTATUS +CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + OUT PKEY_CELL *SubKeyCell, + OUT BLOCK_OFFSET *BlockOffset, + IN PCHAR KeyName, + IN ACCESS_MASK DesiredAccess, + IN ULONG Attributes); + +NTSTATUS +CmiAddSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_OBJECT Parent, + OUT PKEY_OBJECT SubKey, + IN PWSTR NewSubKeyName, + IN USHORT NewSubKeyNameSize, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class, + IN ULONG CreateOptions); + +NTSTATUS +CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName, + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset); + +NTSTATUS +CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN ULONG Index, + OUT PVALUE_CELL *ValueCell); + +NTSTATUS +CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueNameBuf, + OUT PVALUE_CELL *pValueCell, + OUT BLOCK_OFFSET *pVBOffset); + +NTSTATUS +CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName); + +NTSTATUS +CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive, + OUT PHASH_TABLE_CELL *HashBlock, + OUT BLOCK_OFFSET *HBOffset, + IN ULONG HashTableSize); + +PKEY_CELL +CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, +PHASH_TABLE_CELL HashBlock, +ULONG Index); + +NTSTATUS +CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + PKEY_CELL NewKeyCell, + BLOCK_OFFSET NKBOffset); + +NTSTATUS +CmiAllocateValueCell(IN PREGISTRY_HIVE RegistryHive, + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset, + IN PCHAR ValueNameBuf); + +NTSTATUS +CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, + PVALUE_CELL ValueCell, + BLOCK_OFFSET VBOffset); + +NTSTATUS +CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, + PVOID *Block, + LONG BlockSize, + BLOCK_OFFSET * pBlockOffset); + +NTSTATUS +CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block, + BLOCK_OFFSET Offset); + +PVOID +CmiGetBlock(PREGISTRY_HIVE RegistryHive, + BLOCK_OFFSET BlockOffset, + OUT PHBIN * ppBin); + +VOID +CmiLockBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block); + +VOID +CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block); + +NTSTATUS +CmiAddFree(PREGISTRY_HIVE RegistryHive, + PCELL_HEADER FreeBlock, + BLOCK_OFFSET FreeOffset); + +NTSTATUS +CmiInitHives(BOOLEAN SetUpBoot); + +#endif /*__INCLUDE_CM_H*/ diff --git a/ntoskrnl/cm/import.c b/ntoskrnl/cm/import.c new file mode 100644 index 0000000..1221d19 --- /dev/null +++ b/ntoskrnl/cm/import.c @@ -0,0 +1,610 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/import.c + * PURPOSE: Registry functions + * PROGRAMMERS: Rex Jolliff + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "cm.h" + +static PCHAR +checkAndSkipMagic (PCHAR regChunk) +{ + if (strncmp (regChunk, + REGISTRY_FILE_MAGIC, + strlen (REGISTRY_FILE_MAGIC)) != 0) + { + CPRINT ("incorrect magic number in registry chunk. expected: %s got:%.*s\n", + REGISTRY_FILE_MAGIC, + strlen (REGISTRY_FILE_MAGIC), + regChunk); + return 0; + } + regChunk += strlen (REGISTRY_FILE_MAGIC); + DPRINT ("Found regsitry chunk magic value\n"); + + return regChunk; +} + +static PCHAR +skipWhitespaceInChunk (PCHAR regChunk) +{ + while (*regChunk && isspace (*regChunk)) + regChunk++; + + return *regChunk ? regChunk : 0; +} + +static int +computeKeyNameSize (PCHAR regChunk) +{ + int copyCount = 0; + + while (*regChunk != 0 && *regChunk != ']') + { + copyCount++; + regChunk++; + } + + return copyCount; +} + +static BOOLEAN +allocateKeyName (PUNICODE_STRING newKeyName, int newKeySize) +{ + if (newKeyName->MaximumLength < (newKeySize + 1) * sizeof (WCHAR)) + { + if (newKeyName->Buffer != 0) + ExFreePool (newKeyName->Buffer); + newKeyName->Length = 0; + newKeyName->MaximumLength = (newKeySize + 1) * sizeof (WCHAR); + newKeyName->Buffer = ExAllocatePool (NonPagedPool, newKeyName->MaximumLength); + if (newKeyName->Buffer == 0) + { + CPRINT ("Could not allocate space for key name\n"); + return FALSE; + } + newKeyName->Buffer [0] = 0; + } + else + { + newKeyName->Length = 0; + newKeyName->Buffer [0] = 0; + } + + return TRUE; +} + +static PCHAR +skipToNextKeyInChunk (PCHAR regChunk) +{ + while (*regChunk != 0 && *regChunk != '[') + { + while (*regChunk != 0 && *regChunk != '\n') + { + regChunk++; + } + regChunk++; + } + + return *regChunk ? regChunk : 0; +} + +static PCHAR +getKeyNameFromChunk (PCHAR regChunk, PUNICODE_STRING newKeyName) +{ + int index = 0; + + while (*regChunk != 0 && *regChunk != ']') + { + newKeyName->Buffer [index++] = *regChunk++; + } + newKeyName->Buffer [index] = '\0'; + newKeyName->Length = index * sizeof (WCHAR); + + return *regChunk ? regChunk : 0; +} + +static HANDLE +createNewKey (PUNICODE_STRING newKeyName) +{ + NTSTATUS status; + OBJECT_ATTRIBUTES attributes; + HANDLE handleToReturn; + + DPRINT ("Creating key (%wZ)\n", newKeyName); + InitializeObjectAttributes (&attributes, + newKeyName, + 0, + 0, + NULL); + status = NtCreateKey (&handleToReturn, + KEY_ALL_ACCESS, + &attributes, + 0, + NULL, + REG_OPTION_VOLATILE, + NULL); + if (!NT_SUCCESS(status)) + { + CPRINT ("Could not crete key (%wZ)\n", newKeyName); + return INVALID_HANDLE_VALUE; + } + + return handleToReturn; +} + +static PCHAR +skipToNextKeyValueInChunk (PCHAR regChunk) +{ + while (*regChunk != 0 && *regChunk != '\n') + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + + return regChunk; +} + +static int +computeKeyValueNameSize (PCHAR regChunk) +{ + int size = 0; + + if (*regChunk != '\"') + return 0; + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + size++; + regChunk++; + } + + return regChunk ? size : 0; +} + +static PCHAR +getKeyValueNameFromChunk (PCHAR regChunk, PUNICODE_STRING newKeyName) +{ + int index = 0; + + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + newKeyName->Buffer [index++] = *regChunk++; + } + newKeyName->Buffer [index] = '\0'; + newKeyName->Length = index * sizeof (WCHAR); + regChunk++; + + return *regChunk ? regChunk : 0; +} + +static PCHAR +getKeyValueTypeFromChunk (PCHAR regChunk, PCHAR dataFormat, int *keyValueType) +{ + if (*regChunk == '\"') + { + strcpy (dataFormat, "string"); + *keyValueType = REG_SZ; + } + else if (strncmp (regChunk, "hex", 3) == 0) + { + strcpy (dataFormat, "hex"); + regChunk += 3; + if (*regChunk == '(') + { + regChunk++; + *keyValueType = atoi (regChunk); + while (*regChunk != 0 && *regChunk != ')') + regChunk++; + regChunk++; + } + else + *keyValueType = REG_BINARY; + if (*regChunk == ':') + regChunk++; + } + else if (strncmp (regChunk, "dword", 5) == 0) + { + strcpy (dataFormat, "dword"); + *keyValueType = REG_DWORD; + regChunk += 5; + if (*regChunk == ':') + regChunk++; + } + else if (strncmp (regChunk, "multi", 5) == 0) + { + strcpy (dataFormat, "multi"); + *keyValueType = REG_MULTI_SZ; + regChunk += 5; + if (*regChunk == ':') + regChunk++; + } + else if (strncmp (regChunk, "expand", 6) == 0) + { + strcpy (dataFormat, "expand"); + *keyValueType = REG_EXPAND_SZ; + regChunk += 6; + if (*regChunk == ':') + regChunk++; + } + else + { + UNIMPLEMENTED; + } + + return *regChunk ? regChunk : 0; +} + +static int +computeKeyValueDataSize (PCHAR regChunk, PCHAR dataFormat) +{ + int dataSize = 0; + + if (strcmp (dataFormat, "string") == 0) + { + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + dataSize++; + dataSize++; + regChunk++; + } + dataSize++; + dataSize++; + } + else if (strcmp (dataFormat, "hex") == 0) + { + while (*regChunk != 0 && isxdigit(*regChunk)) + { + regChunk++; + regChunk++; + dataSize++; + if (*regChunk == ',') + { + regChunk++; + if (*regChunk == '\\') + { + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + } + } + } + } + else if (strcmp (dataFormat, "dword") == 0) + { + dataSize = sizeof(DWORD); + while (*regChunk != 0 && isxdigit(*regChunk)) + { + regChunk++; + } + } + else if (strcmp (dataFormat, "multi") == 0) + { + while (*regChunk == '\"') + { + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + dataSize++; + dataSize++; + regChunk++; + } + regChunk++; + dataSize++; + dataSize++; + if (*regChunk == ',') + { + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + if (*regChunk == '\\') + { + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + } + } + else + break; + } + dataSize++; + dataSize++; + } + else if (strcmp (dataFormat, "expand") == 0) + { + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + dataSize++; + dataSize++; + regChunk++; + } + dataSize++; + dataSize++; + } + else + { + UNIMPLEMENTED; + } + + return dataSize; +} + +static BOOLEAN +allocateDataBuffer (PVOID * data, int * dataBufferSize, int dataSize) +{ + if (*dataBufferSize < dataSize) + { + if (*dataBufferSize > 0) + ExFreePool (*data); + *data = ExAllocatePool (NonPagedPool, dataSize); + *dataBufferSize = dataSize; + } + + return TRUE; +} + +static PCHAR +getKeyValueDataFromChunk (PCHAR regChunk, PCHAR dataFormat, PCHAR data) +{ + char dataValue; + ULONG ulValue; + PWCHAR ptr; + + if (strcmp (dataFormat, "string") == 0) + { + /* convert quoted string to zero-terminated Unicode string */ + ptr = (PWCHAR)data; + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + *ptr++ = (WCHAR)*regChunk++; + } + *ptr = 0; + regChunk++; + } + else if (strcmp (dataFormat, "hex") == 0) + { + while (*regChunk != 0 && isxdigit (*regChunk)) + { + dataValue = (isdigit (*regChunk) ? *regChunk - '0' : + tolower(*regChunk) - 'a' + 10) << 4; + regChunk++; + dataValue += (isdigit (*regChunk) ? *regChunk - '0' : + tolower(*regChunk) - 'a' + 10); + regChunk++; + *data++ = dataValue; + if (*regChunk == ',') + { + regChunk++; + if (*regChunk == '\\') + { + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + } + } + } + } + else if (strcmp (dataFormat, "dword") == 0) + { + ulValue = 0; + while (*regChunk != 0 && isxdigit(*regChunk)) + { + dataValue = (isdigit (*regChunk) ? *regChunk - '0' : + tolower(*regChunk) - 'a' + 10); + ulValue = (ulValue << 4) + dataValue; + regChunk++; + } + memcpy(data, &ulValue, sizeof(ULONG)); + } + else if (strcmp (dataFormat, "multi") == 0) + { + ptr = (PWCHAR)data; + while (*regChunk == '\"') + { + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + *ptr++ = (WCHAR)*regChunk++; + } + regChunk++; + *ptr++ = 0; + if (*regChunk == ',') + { + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + if (*regChunk == '\\') + { + regChunk++; + regChunk = skipWhitespaceInChunk (regChunk); + } + } + else + break; + } + *ptr = 0; + } + else if (strcmp (dataFormat, "expand") == 0) + { + /* convert quoted string to zero-terminated Unicode string */ + ptr = (PWCHAR)data; + regChunk++; + while (*regChunk != 0 && *regChunk != '\"') + { + *ptr++ = (WCHAR)*regChunk++; + } + *ptr = 0; + regChunk++; + } + else + { + UNIMPLEMENTED; + } + + return *regChunk ? regChunk : 0; +} + +static BOOLEAN +setKeyValue (HANDLE currentKey, + PUNICODE_STRING newValueName, + ULONG keyValueType, + PVOID data, + ULONG dataSize) +{ + NTSTATUS status; + + DPRINT ("Adding value (%wZ) to current key, with data type %d size %d\n", + newValueName, + keyValueType, + dataSize); + status = NtSetValueKey (currentKey, + newValueName, + 0, + keyValueType, + data, + dataSize); + if (!NT_SUCCESS(status)) + { + CPRINT ("could not set key value, rc:%08x\n", status); + return FALSE; + } + + return TRUE; +} + +VOID +CmImportHive(PCHAR ChunkBase, + ULONG ChunkSize) +{ + HANDLE currentKey = INVALID_HANDLE_VALUE; + int newKeySize; + UNICODE_STRING newKeyName = {0, 0, 0}; + char dataFormat [10]; + int keyValueType; + int dataSize = 0; + int dataBufferSize = 0; + PVOID data = 0; + PCHAR regChunk; + + DPRINT("ChunkBase %p ChunkSize %lx\n", ChunkBase, ChunkSize); + + regChunk = checkAndSkipMagic (ChunkBase); + if (regChunk == 0) + return; + + while (regChunk != 0 && *regChunk != 0 && (((ULONG)regChunk-(ULONG)ChunkBase) < ChunkSize)) + { + regChunk = skipWhitespaceInChunk (regChunk); + if (regChunk == 0) + continue; + + if (*regChunk == '[') + { + if (currentKey != INVALID_HANDLE_VALUE) + { + DPRINT("Closing current key: 0x%lx\n", currentKey); + NtClose (currentKey); + currentKey = INVALID_HANDLE_VALUE; + } + + regChunk++; + + newKeySize = computeKeyNameSize (regChunk); + if (!allocateKeyName (&newKeyName, newKeySize)) + { + regChunk = 0; + continue; + } + + regChunk = getKeyNameFromChunk (regChunk, &newKeyName); + if (regChunk == 0) + continue; + + currentKey = createNewKey (&newKeyName); + if (currentKey == INVALID_HANDLE_VALUE) + { + regChunk = skipToNextKeyInChunk (regChunk); + continue; + } + + regChunk++; + } + else + { + if (currentKey == INVALID_HANDLE_VALUE) + { + regChunk = skipToNextKeyInChunk (regChunk); + continue; + } + + newKeySize = computeKeyValueNameSize (regChunk); + if (!allocateKeyName (&newKeyName, newKeySize)) + { + regChunk = 0; + continue; + } + + regChunk = getKeyValueNameFromChunk (regChunk, &newKeyName); + if (regChunk == 0) + continue; + + if (*regChunk != '=') + { + regChunk = skipToNextKeyValueInChunk (regChunk); + continue; + } + regChunk++; + + regChunk = getKeyValueTypeFromChunk (regChunk, dataFormat, &keyValueType); + if (regChunk == 0) + continue; + + dataSize = computeKeyValueDataSize (regChunk, dataFormat); + if (!allocateDataBuffer (&data, &dataBufferSize, dataSize)) + { + regChunk = 0; + continue; + } + + regChunk = getKeyValueDataFromChunk (regChunk, dataFormat, data); + if (regChunk == 0) + continue; + + if (!setKeyValue (currentKey, &newKeyName, keyValueType, data, dataSize)) + { + regChunk = 0; + continue; + } + } + } + + if (currentKey != INVALID_HANDLE_VALUE) + { + NtClose (currentKey); + } + if (newKeyName.Buffer != 0) + { + ExFreePool (newKeyName.Buffer); + } + if (data != 0) + { + ExFreePool (data); + } + + return; +} + + diff --git a/ntoskrnl/cm/ntfunc.c b/ntoskrnl/cm/ntfunc.c new file mode 100644 index 0000000..a419b74 --- /dev/null +++ b/ntoskrnl/cm/ntfunc.c @@ -0,0 +1,1601 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/ntfunc.c + * PURPOSE: Ntxxx function for registry access + * UPDATE HISTORY: +*/ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "cm.h" + + +/* GLOBALS ******************************************************************/ + +extern POBJECT_TYPE CmiKeyType; +extern PREGISTRY_HIVE CmiVolatileHive; + +static BOOLEAN CmiRegistryInitialized = FALSE; + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +NtCreateKey(OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class, + IN ULONG CreateOptions, + OUT PULONG Disposition) +{ + UNICODE_STRING RemainingPath; + PKEY_OBJECT KeyObject; + NTSTATUS Status; + PVOID Object; + PWSTR End; + + DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n", + ObjectAttributes->ObjectName, + KeyHandle, + ObjectAttributes->RootDirectory); + + /* FIXME: check for standard handle prefix and adjust objectAttributes accordingly */ + + Status = ObFindObject(ObjectAttributes, &Object, &RemainingPath, CmiKeyType); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + DPRINT("RemainingPath %wZ\n", &RemainingPath); + + if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0)) + { + /* Fail if the key has been deleted */ + if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE) + { + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + if (Disposition) + *Disposition = REG_OPENED_EXISTING_KEY; + + Status = ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + KeyHandle); + + DPRINT("Status %x\n", Status); + ObDereferenceObject(Object); + return Status; + } + + /* If RemainingPath contains \ we must return error + because NtCreateKey don't create trees */ + if (RemainingPath.Buffer[0] == '\\') + End = wcschr(RemainingPath.Buffer + 1, '\\'); + else + End = wcschr(RemainingPath.Buffer, '\\'); + + if (End != NULL) + { + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath.Buffer, Object); + + Status = ObCreateObject(KeyHandle, + DesiredAccess, + NULL, + CmiKeyType, + (PVOID*)&KeyObject); + + if (!NT_SUCCESS(Status)) + return(Status); + + KeyObject->ParentKey = Object; + + if (CreateOptions & REG_OPTION_VOLATILE) + KeyObject->RegistryHive = CmiVolatileHive; + else + KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive; + + KeyObject->Flags = 0; + KeyObject->NumberOfSubKeys = 0; + KeyObject->SizeOfSubKeys = 0; + KeyObject->SubKeys = NULL; +// KeAcquireSpinLock(&Key->RegistryHive->RegLock, &OldIrql); + /* add key to subkeys of parent if needed */ + Status = CmiAddSubKey(KeyObject->RegistryHive, + KeyObject->ParentKey, + KeyObject, + RemainingPath.Buffer, + RemainingPath.Length, + TitleIndex, + Class, + CreateOptions); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(KeyObject); + ObDereferenceObject(Object); + return STATUS_UNSUCCESSFUL; + } + + KeyObject->Name = KeyObject->KeyCell->Name; + KeyObject->NameSize = KeyObject->KeyCell->NameSize; + + if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive) + { + KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset; + KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset; + } + else + { + KeyObject->KeyCell->ParentKeyOffset = -1; + KeyObject->KeyCell->SecurityKeyOffset = -1; + /* This key must rest in memory unless it is deleted + or file is unloaded */ + ObReferenceObjectByPointer(KeyObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + } + + CmiAddKeyToList(KeyObject->ParentKey, KeyObject); +// KeReleaseSpinLock(&KeyObject->RegistryHive->RegLock, OldIrql); + + ObDereferenceObject(KeyObject); + ObDereferenceObject(Object); + + if (Disposition) + *Disposition = REG_CREATED_NEW_KEY; + + VERIFY_KEY_OBJECT(KeyObject); + + return Status; +} + + +NTSTATUS STDCALL +NtDeleteKey(IN HANDLE KeyHandle) +{ + PKEY_OBJECT KeyObject; + NTSTATUS Status; + + DPRINT("KeyHandle %x\n", KeyHandle); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_WRITE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Set the marked for delete bit in the key object */ + KeyObject->Flags |= KO_MARKED_FOR_DELETE; + + /* Dereference the object */ + ObDereferenceObject(KeyObject); + if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive) + ObDereferenceObject(KeyObject); + /* Close the handle */ + ObDeleteHandle(PsGetCurrentProcess(), KeyHandle); + /* FIXME: I think that ObDeleteHandle should dereference the object */ + ObDereferenceObject(KeyObject); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +NtEnumerateKey( + IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength + ) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell, SubKeyCell; + PHASH_TABLE_CELL HashTableBlock; + PKEY_BASIC_INFORMATION BasicInformation; + PKEY_NODE_INFORMATION NodeInformation; + PKEY_FULL_INFORMATION FullInformation; + PDATA_CELL pClassData; + + DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n", + KeyHandle, + Index, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_ENUMERATE_SUB_KEYS, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + + /* Get pointer to SubKey */ + if (Index >= KeyCell->NumberOfSubKeys) + { + if (RegistryHive == CmiVolatileHive) + { + ObDereferenceObject (KeyObject); + DPRINT("No more volatile entries\n"); + return STATUS_NO_MORE_ENTRIES; + } + else + { + ULONG i; + PKEY_OBJECT CurKey = NULL; + + /* Search volatile keys */ + for (i = 0; i < KeyObject->NumberOfSubKeys; i++) + { + CurKey = KeyObject->SubKeys[i]; + if (CurKey->RegistryHive == CmiVolatileHive) + { + if (Index-- == KeyObject->NumberOfSubKeys) + break; + } + } + if(Index >= KeyCell->NumberOfSubKeys) + { + ObDereferenceObject (KeyObject); + DPRINT("No more non-volatile entries\n"); + return STATUS_NO_MORE_ENTRIES; + } + SubKeyCell = CurKey->KeyCell; + } + } + else + { + HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive, + HashTableBlock, + Index); + } + + if (SubKeyCell == NULL) + { + ObDereferenceObject (KeyObject); + DPRINT("No more entries\n"); + return STATUS_NO_MORE_ENTRIES; + } + + Status = STATUS_SUCCESS; + switch (KeyInformationClass) + { + case KeyBasicInformation: + /* Check size of buffer */ + *ResultLength = sizeof(KEY_BASIC_INFORMATION) + + (SubKeyCell->NameSize ) * sizeof(WCHAR); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* Fill buffer with requested info */ + BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation; + BasicInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime; + BasicInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime; + BasicInformation->TitleIndex = Index; + BasicInformation->NameLength = SubKeyCell->NameSize * sizeof(WCHAR); + mbstowcs(BasicInformation->Name, + SubKeyCell->Name, + SubKeyCell->NameSize * 2); +// BasicInformation->Name[SubKeyCell->NameSize] = 0; + } + break; + + case KeyNodeInformation: + /* Check size of buffer */ + *ResultLength = sizeof(KEY_NODE_INFORMATION) + + SubKeyCell->NameSize * sizeof(WCHAR) + + SubKeyCell->ClassSize; + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* Fill buffer with requested info */ + NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation; + NodeInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime; + NodeInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime; + NodeInformation->TitleIndex = Index; + NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + + SubKeyCell->NameSize * sizeof(WCHAR); + NodeInformation->ClassLength = SubKeyCell->ClassSize; + NodeInformation->NameLength = SubKeyCell->NameSize * sizeof(WCHAR); + mbstowcs(NodeInformation->Name, + SubKeyCell->Name, + SubKeyCell->NameSize * 2); +// NodeInformation->Name[SubKeyCell->NameSize] = 0; + if (SubKeyCell->ClassSize != 0) + { + pClassData=CmiGetBlock(KeyObject->RegistryHive, + SubKeyCell->ClassNameOffset, + NULL); + wcsncpy(NodeInformation->Name + SubKeyCell->NameSize , + (PWCHAR) pClassData->Data, + SubKeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); + } + } + break; + + case KeyFullInformation: + /* check size of buffer */ + *ResultLength = sizeof(KEY_FULL_INFORMATION) + + SubKeyCell->ClassSize; + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* fill buffer with requested info */ + FullInformation = (PKEY_FULL_INFORMATION) KeyInformation; + FullInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime; + FullInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime; + FullInformation->TitleIndex = Index; + FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - + sizeof(WCHAR); + FullInformation->ClassLength = SubKeyCell->ClassSize; + FullInformation->SubKeys = SubKeyCell->NumberOfSubKeys; + FullInformation->MaxNameLen = + CmiGetMaxNameLength(RegistryHive, SubKeyCell); + FullInformation->MaxClassLen = + CmiGetMaxClassLength(RegistryHive, SubKeyCell); + FullInformation->Values = SubKeyCell->NumberOfValues; + FullInformation->MaxValueNameLen = + CmiGetMaxValueNameLength(RegistryHive, SubKeyCell); + FullInformation->MaxValueDataLen = + CmiGetMaxValueDataLength(RegistryHive, SubKeyCell); + if (SubKeyCell->ClassSize != 0) + { + pClassData = CmiGetBlock(KeyObject->RegistryHive, + SubKeyCell->ClassNameOffset, + NULL); + wcsncpy(FullInformation->Class, + (PWCHAR) pClassData->Data, + SubKeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); + } + } + break; + } + CmiReleaseBlock(RegistryHive, SubKeyCell); + ObDereferenceObject (KeyObject); + + DPRINT("Returning status %x\n", Status); + + return Status; +} + + +NTSTATUS STDCALL +NtEnumerateValueKey(IN HANDLE KeyHandle, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell; + PVALUE_CELL ValueCell; + PDATA_CELL DataCell; + PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; + PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; + PKEY_VALUE_FULL_INFORMATION ValueFullInformation; + + DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n", + KeyHandle, + Index, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + + /* Get Value block of interest */ + Status = CmiGetValueFromKeyByIndex(RegistryHive, + KeyCell, + Index, + &ValueCell); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(KeyObject); + return Status; + } + else if (ValueCell != NULL) + { + switch (KeyValueInformationClass) + { + case KeyValueBasicInformation: + *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + + (ValueCell->NameSize + 1) * sizeof(WCHAR); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION) + KeyValueInformation; + ValueBasicInformation->TitleIndex = 0; + ValueBasicInformation->Type = ValueCell->DataType; + ValueBasicInformation->NameLength = + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueBasicInformation->Name, + ValueCell->Name, + ValueCell->NameSize * 2); + ValueBasicInformation->Name[ValueCell->NameSize] = 0; + } + break; + + case KeyValuePartialInformation: + *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + + (ValueCell->DataSize & LONG_MAX); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) + KeyValueInformation; + ValuePartialInformation->TitleIndex = 0; + ValuePartialInformation->Type = ValueCell->DataType; + ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX; + if(ValueCell->DataSize >0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(ValuePartialInformation->Data, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory(ValuePartialInformation->Data, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + } + break; + + case KeyValueFullInformation: + *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + + ValueCell->NameSize * sizeof(WCHAR) + (ValueCell->DataSize & LONG_MAX); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) + KeyValueInformation; + ValueFullInformation->TitleIndex = 0; + ValueFullInformation->Type = ValueCell->DataType; + ValueFullInformation->DataOffset = + (DWORD)ValueFullInformation->Name - (DWORD) ValueFullInformation + + (ValueCell->NameSize + 1) * sizeof(WCHAR); + ValueFullInformation->DataOffset = + (ValueFullInformation->DataOffset + 3) & 0xfffffffc; + ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX; + ValueFullInformation->NameLength = + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueFullInformation->Name, + ValueCell->Name, + ValueCell->NameSize * 2); + ValueFullInformation->Name[ValueCell->NameSize] = 0; + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } + } + break; + } + } + else + { + Status = STATUS_UNSUCCESSFUL; + } + ObDereferenceObject(KeyObject); + + return Status; +} + + +NTSTATUS STDCALL +NtFlushKey(IN HANDLE KeyHandle) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + WCHAR LogName[MAX_PATH]; + UNICODE_STRING TmpFileName; + HANDLE FileHandle; + // HANDLE FileHandleLog; + OBJECT_ATTRIBUTES ObjectAttributes; + // KIRQL OldIrql; + LARGE_INTEGER fileOffset; + DWORD * pEntDword; + ULONG i; + + DPRINT("KeyHandle %x\n", KeyHandle); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + RegistryHive = KeyObject->RegistryHive; +// KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql); + /* Then write changed blocks in .log */ + wcscpy(LogName,RegistryHive->Filename.Buffer); + wcscat(LogName,L".log"); + RtlInitUnicodeString (&TmpFileName, LogName); + InitializeObjectAttributes(&ObjectAttributes, + &TmpFileName, + 0, + NULL, + NULL); + +/* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files + so we can't create log file + Status = ZwCreateFile(&FileHandleLog, + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + 0, + NULL, + 0); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(KeyObject); + return Status; + } + + Status = ZwWriteFile(FileHandleLog, + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandleLog); + ObDereferenceObject(KeyObject); + return Status; + } + + for (i = 0; i < RegistryHive->BlockListSize ; i++) + { + if ( RegistryHive->BlockList[i]->DateModified.dwHighDateTime + > RegistryHive->HiveHeader->DateModified.dwHighDateTime + || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime + == RegistryHive->HiveHeader->DateModified.dwHighDateTime + && RegistryHive->BlockList[i]->DateModified.dwLowDateTime + > RegistryHive->HiveHeader->DateModified.dwLowDateTime + ) + ) + + Status = ZwWriteFile(FileHandleLog, + 0, + 0, + 0, + 0, + RegistryHive->BlockList[i], + RegistryHive->BlockList[i]->BlockSize , + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandleLog); + ObDereferenceObject(KeyObject); + return Status; + } + } + ZwClose(FileHandleLog); +END FIXME*/ + + /* Update header of RegistryHive with Version >VersionOld */ + /* this allow recover if system crash while updating hove file */ + InitializeObjectAttributes(&ObjectAttributes, + &RegistryHive->Filename, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(KeyObject); + return Status; + } + + RegistryHive->HiveHeader->Version++; + + Status = ZwWriteFile(FileHandle, + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + ObDereferenceObject(KeyObject); + return Status; + } + + /* Update changed blocks in file */ + fileOffset.u.HighPart = 0; + for (i = 0; i < RegistryHive->BlockListSize ; i++) + { + if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime + > RegistryHive->HiveHeader->DateModified.dwHighDateTime + || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime + == RegistryHive->HiveHeader->DateModified.dwHighDateTime + && RegistryHive->BlockList[i]->DateModified.dwLowDateTime + > RegistryHive->HiveHeader->DateModified.dwLowDateTime + ) + ) + { + fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096; + Status = NtWriteFile(FileHandle, + 0, + 0, + 0, + 0, + RegistryHive->BlockList[i], + RegistryHive->BlockList[i]->BlockSize , + &fileOffset, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + ObDereferenceObject(KeyObject); + return Status; + } + } + } + + /* Change version in header */ + RegistryHive->HiveHeader->VersionOld = RegistryHive->HiveHeader->Version; + ZwQuerySystemTime((PTIME) &RegistryHive->HiveHeader->DateModified); + + /* Calculate checksum */ + RegistryHive->HiveHeader->Checksum = 0; + pEntDword = (DWORD *) RegistryHive->HiveHeader; + for (i = 0; i < 127 ; i++) + { + RegistryHive->HiveHeader->Checksum ^= pEntDword[i]; + } + + /* Write new header */ + fileOffset.u.LowPart = 0; + Status = ZwWriteFile(FileHandle, + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + &fileOffset, + 0); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + ObDereferenceObject(KeyObject); + return Status; + } + + ZwClose(FileHandle); +// KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql); + ObDereferenceObject(KeyObject); + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +NtOpenKey(OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + UNICODE_STRING RemainingPath; + NTSTATUS Status; + PVOID Object; + + DPRINT("KH %x DA %x OA %x OA->ON %x\n", + KeyHandle, + DesiredAccess, + ObjectAttributes, + ObjectAttributes ? ObjectAttributes->ObjectName : NULL); + + RemainingPath.Buffer = NULL; + Status = ObFindObject(ObjectAttributes, + &Object, + &RemainingPath, + CmiKeyType); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + VERIFY_KEY_OBJECT((PKEY_OBJECT) Object); + + DPRINT("RemainingPath.Buffer %x\n", RemainingPath.Buffer); + + if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0)) + { + ObDereferenceObject(Object); + return(STATUS_UNSUCCESSFUL); + } + + /* Fail if the key has been deleted */ + if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE) + { + ObDereferenceObject(Object); + return(STATUS_UNSUCCESSFUL); + } + + Status = ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + KeyHandle); + ObDereferenceObject(Object); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtQueryKey(IN HANDLE KeyHandle, + IN KEY_INFORMATION_CLASS KeyInformationClass, + OUT PVOID KeyInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + PKEY_BASIC_INFORMATION BasicInformation; + PKEY_NODE_INFORMATION NodeInformation; + PKEY_FULL_INFORMATION FullInformation; + PREGISTRY_HIVE RegistryHive; + PDATA_CELL pClassData; + PKEY_OBJECT KeyObject; + PKEY_CELL KeyCell; + NTSTATUS Status; + + DPRINT("KH %x KIC %x KI %x L %d RL %x\n", + KeyHandle, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_READ, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + + Status = STATUS_SUCCESS; + switch (KeyInformationClass) + { + case KeyBasicInformation: + /* Check size of buffer */ + if (Length < sizeof(KEY_BASIC_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR)) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* Fill buffer with requested info */ + BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation; + BasicInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime; + BasicInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime; + BasicInformation->TitleIndex = 0; + BasicInformation->NameLength = (KeyObject->NameSize) * sizeof(WCHAR); + mbstowcs(BasicInformation->Name, + KeyObject->Name, + KeyObject->NameSize*sizeof(WCHAR)); + *ResultLength = sizeof(KEY_BASIC_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR); + } + break; + + case KeyNodeInformation: + /* Check size of buffer */ + if (Length < sizeof(KEY_NODE_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR) + + KeyCell->ClassSize) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* Fill buffer with requested info */ + NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation; + NodeInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime; + NodeInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime; + NodeInformation->TitleIndex = 0; + NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR); + NodeInformation->ClassLength = KeyCell->ClassSize; + NodeInformation->NameLength = KeyObject->NameSize * sizeof(WCHAR); + mbstowcs(NodeInformation->Name, + KeyObject->Name, + KeyObject->NameSize * sizeof(WCHAR)); + + if (KeyCell->ClassSize != 0) + { + pClassData = CmiGetBlock(KeyObject->RegistryHive, + KeyCell->ClassNameOffset, + NULL); + wcsncpy(NodeInformation->Name + KeyObject->NameSize * sizeof(WCHAR), + (PWCHAR)pClassData->Data, + KeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); + } + *ResultLength = sizeof(KEY_NODE_INFORMATION) + + KeyObject->NameSize * sizeof(WCHAR) + + KeyCell->ClassSize; + } + break; + + case KeyFullInformation: + /* Check size of buffer */ + if (Length < sizeof(KEY_FULL_INFORMATION) + KeyCell->ClassSize) + { + Status = STATUS_BUFFER_OVERFLOW; + } + else + { + /* Fill buffer with requested info */ + FullInformation = (PKEY_FULL_INFORMATION) KeyInformation; + FullInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime; + FullInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime; + FullInformation->TitleIndex = 0; + FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR); + FullInformation->ClassLength = KeyCell->ClassSize; + FullInformation->SubKeys = KeyCell->NumberOfSubKeys; + FullInformation->MaxNameLen = + CmiGetMaxNameLength(RegistryHive, KeyCell); + FullInformation->MaxClassLen = + CmiGetMaxClassLength(RegistryHive, KeyCell); + FullInformation->Values = KeyCell->NumberOfValues; + FullInformation->MaxValueNameLen = + CmiGetMaxValueNameLength(RegistryHive, KeyCell); + FullInformation->MaxValueDataLen = + CmiGetMaxValueDataLength(RegistryHive, KeyCell); + if (KeyCell->ClassSize != 0) + { + pClassData=CmiGetBlock(KeyObject->RegistryHive, + KeyCell->ClassNameOffset, + NULL); + wcsncpy(FullInformation->Class, + (PWCHAR)pClassData->Data, + KeyCell->ClassSize); + CmiReleaseBlock(RegistryHive, pClassData); + } + *ResultLength = sizeof(KEY_FULL_INFORMATION) + KeyCell->ClassSize; + } + break; + } + + ObDereferenceObject(KeyObject); + + return Status; +} + +NTSTATUS STDCALL +NtQueryValueKey(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell; + PVALUE_CELL ValueCell; + PDATA_CELL DataCell; + PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation; + PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation; + PKEY_VALUE_FULL_INFORMATION ValueFullInformation; + char ValueName2[MAX_PATH]; + + DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n", + KeyHandle, ValueName->Buffer, Length); + + wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1); + ValueName2[ValueName->Length >> 1] = 0; + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + /* Get Value block of interest */ + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + ValueName2, + &ValueCell,NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT("CmiScanKeyForValue() failed with status %x\n", Status); + ObDereferenceObject(KeyObject); + return Status; + } + else if (ValueCell != NULL) + { + switch (KeyValueInformationClass) + { + case KeyValueBasicInformation: + *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + + ValueCell->NameSize * sizeof(WCHAR); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION) + KeyValueInformation; + ValueBasicInformation->TitleIndex = 0; + ValueBasicInformation->Type = ValueCell->DataType; + ValueBasicInformation->NameLength = + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueBasicInformation->Name, + ValueCell->Name,ValueCell->NameSize * 2); + ValueBasicInformation->Name[ValueCell->NameSize] = 0; + } + break; + + case KeyValuePartialInformation: + *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + + (ValueCell->DataSize & LONG_MAX); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION) + KeyValueInformation; + ValuePartialInformation->TitleIndex = 0; + ValuePartialInformation->Type = ValueCell->DataType; + ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX; + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(ValuePartialInformation->Data, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory(ValuePartialInformation->Data, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } + } + break; + + case KeyValueFullInformation: + *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) + + (ValueCell->NameSize -1) * sizeof(WCHAR) + + (ValueCell->DataSize & LONG_MAX); + if (Length < *ResultLength) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION) + KeyValueInformation; + ValueFullInformation->TitleIndex = 0; + ValueFullInformation->Type = ValueCell->DataType; + ValueFullInformation->DataOffset = + (DWORD)ValueFullInformation->Name - (DWORD)ValueFullInformation + + (ValueCell->NameSize + 1) * sizeof(WCHAR); + ValueFullInformation->DataOffset = + (ValueFullInformation->DataOffset + 3) &0xfffffffc; + ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX; + ValueFullInformation->NameLength = + (ValueCell->NameSize + 1) * sizeof(WCHAR); + mbstowcs(ValueFullInformation->Name, ValueCell->Name,ValueCell->NameSize*2); + ValueFullInformation->Name[ValueCell->NameSize] = 0; + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + DataCell->Data, + ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory((PCHAR) ValueFullInformation + + ValueFullInformation->DataOffset, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } + } + break; + } + } + else + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + ObDereferenceObject(KeyObject); + + return Status; +} + + +NTSTATUS STDCALL +NtSetValueKey(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN ULONG TitleIndex, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize) +{ + NTSTATUS Status; + PKEY_OBJECT KeyObject; + PREGISTRY_HIVE RegistryHive; + PKEY_CELL KeyCell; + PVALUE_CELL ValueCell; + BLOCK_OFFSET VBOffset; + char ValueName2[MAX_PATH]; + PDATA_CELL DataCell; + PDATA_CELL NewDataCell; + PHBIN pBin; + ULONG DesiredAccess; +// KIRQL OldIrql; + + DPRINT("KeyHandle %x ValueName %S Type %d\n", + KeyHandle, ValueName? ValueName->Buffer : NULL, Type); + + wcstombs(ValueName2,ValueName->Buffer, ValueName->Length >> 1); + ValueName2[ValueName->Length>>1] = 0; + + DesiredAccess = KEY_SET_VALUE; + if (Type == REG_LINK) + DesiredAccess |= KEY_CREATE_LINK; + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + DesiredAccess, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to key cell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + ValueName2, + &ValueCell, + &VBOffset); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Value not found. Status 0x%X\n", Status); + + ObDereferenceObject(KeyObject); + return(Status); + } + +// KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql); + + if (ValueCell == NULL) + { + Status = CmiAddValueToKey(RegistryHive, + KeyCell, + ValueName2, + &ValueCell, + &VBOffset); + } + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Cannot add value. Status 0x%X\n", Status); + + ObDereferenceObject(KeyObject); + return(Status); + } + else + { + DPRINT("DataSize (%d)\n", DataSize); + + /* If datasize <= 4 then write in valueblock directly */ + if (DataSize <= 4) + { + DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize); + if ((ValueCell->DataSize >= 0) && + (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) + { + CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); + } + + RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize); + ValueCell->DataSize = DataSize | 0x80000000; + ValueCell->DataType = Type; + RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize); + } + /* If new data size is <= current then overwrite current data */ + else if (DataSize <= (ValueCell->DataSize & 0x7fffffff)) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin); + RtlCopyMemory(DataCell->Data, Data, DataSize); + ValueCell->DataSize = DataSize; + ValueCell->DataType = Type; + CmiReleaseBlock(RegistryHive, DataCell); + /* Update time of heap */ + if (IsPermanentHive(RegistryHive)) + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + } + else + { + BLOCK_OFFSET NewOffset; + + /* Destroy current data block and allocate a new one */ + if ((ValueCell->DataSize >= 0) && + (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL))) + { + CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset); + } + Status = CmiAllocateBlock(RegistryHive, + (PVOID *)&NewDataCell, + DataSize, + &NewOffset); + RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize); + ValueCell->DataSize = DataSize; + ValueCell->DataType = Type; + CmiReleaseBlock(RegistryHive, NewDataCell); + ValueCell->DataOffset = NewOffset; + } + + if (strcmp(ValueName2, "SymbolicLinkValue") == 0) + { + KeyCell->Type = REG_LINK_KEY_CELL_TYPE; + } + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin)) + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + } + +// KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql); + + ObDereferenceObject(KeyObject); + + DPRINT("Return Status 0x%X\n", Status); + + return(Status); +} + + +NTSTATUS STDCALL +NtDeleteValueKey(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName) +{ + PREGISTRY_HIVE RegistryHive; + CHAR ValueName2[MAX_PATH]; + PKEY_OBJECT KeyObject; + PKEY_CELL KeyCell; + NTSTATUS Status; +// KIRQL OldIrql; + + wcstombs(ValueName2, ValueName->Buffer, ValueName->Length >> 1); + ValueName2[ValueName->Length>>1] = 0; + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *)&KeyObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; +// KeAcquireSpinLock(&RegistryHive->RegLock, &OldIrql); + Status = CmiDeleteValueFromKey(RegistryHive, KeyCell, ValueName2); +// KeReleaseSpinLock(&RegistryHive->RegLock, OldIrql); + ObDereferenceObject(KeyObject); + + return Status; +} + + +NTSTATUS STDCALL +NtLoadKey(PHANDLE KeyHandle, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + return NtLoadKey2(KeyHandle, ObjectAttributes, 0); +} + + +NTSTATUS STDCALL +NtLoadKey2(IN PHANDLE KeyHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Flags) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtNotifyChangeKey( + IN HANDLE KeyHandle, + IN HANDLE Event, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CompletionFilter, + IN BOOLEAN Asynchroneous, + OUT PVOID ChangeBuffer, + IN ULONG Length, + IN BOOLEAN WatchSubtree) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtQueryMultipleValueKey(IN HANDLE KeyHandle, + IN OUT PKEY_VALUE_ENTRY ValueList, + IN ULONG NumberOfValues, + OUT PVOID Buffer, + IN OUT PULONG Length, + OUT PULONG ReturnLength) +{ + PREGISTRY_HIVE RegistryHive; + UCHAR ValueName[MAX_PATH]; + PVALUE_CELL ValueCell; + PKEY_OBJECT KeyObject; + PDATA_CELL DataCell; + ULONG BufferLength = 0; + PKEY_CELL KeyCell; + NTSTATUS Status; + PUCHAR DataPtr; + ULONG i; + + /* Verify that the handle is valid and is a registry key */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmiKeyType, + UserMode, + (PVOID *) &KeyObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status); + return(Status); + } + + VERIFY_KEY_OBJECT(KeyObject); + + /* Get pointer to KeyCell */ + KeyCell = KeyObject->KeyCell; + RegistryHive = KeyObject->RegistryHive; + + DataPtr = (PUCHAR) Buffer; + + for (i = 0; i < NumberOfValues; i++) + { + wcstombs(ValueName, + ValueList[i].ValueName->Buffer, + ValueList[i].ValueName->Length >> 1); + ValueName[ValueList[i].ValueName->Length >> 1] = 0; + + DPRINT("ValueName: '%s'\n", ValueName); + + /* Get Value block of interest */ + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + ValueName, + &ValueCell, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT("CmiScanKeyForValue() failed with status %x\n", Status); + break; + } + else if (ValueCell == NULL) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + break; + } + + BufferLength = (BufferLength + 3) & 0xfffffffc; + + if (BufferLength + (ValueCell->DataSize & LONG_MAX) <= *Length) + { + DataPtr = (PUCHAR)(((ULONG)DataPtr + 3) & 0xfffffffc); + + ValueList[i].Type = ValueCell->DataType; + ValueList[i].DataLength = ValueCell->DataSize & LONG_MAX; + ValueList[i].DataOffset = (ULONG) DataPtr - (ULONG) Buffer; + + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(DataPtr, DataCell->Data, ValueCell->DataSize & LONG_MAX); + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory(DataPtr, + &ValueCell->DataOffset, + ValueCell->DataSize & LONG_MAX); + } + + DataPtr += ValueCell->DataSize & LONG_MAX; + } + else + { + Status = STATUS_BUFFER_TOO_SMALL; + } + + BufferLength += ValueCell->DataSize & LONG_MAX; + } + + if (NT_SUCCESS(Status)) + *Length = BufferLength; + + *ReturnLength = BufferLength; + + ObDereferenceObject(KeyObject); + + DPRINT("Return Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS STDCALL +NtReplaceKey( + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE Key, + IN POBJECT_ATTRIBUTES ReplacedObjectAttributes + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtRestoreKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle, + IN ULONG RestoreFlags + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtSaveKey( + IN HANDLE KeyHandle, + IN HANDLE FileHandle) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtSetInformationKey( + IN HANDLE KeyHandle, + IN CINT KeyInformationClass, + IN PVOID KeyInformation, + IN ULONG KeyInformationLength) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtUnloadKey(IN HANDLE KeyHandle) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtInitializeRegistry(IN BOOLEAN SetUpBoot) +{ + NTSTATUS Status = STATUS_ACCESS_DENIED; + + if (CmiRegistryInitialized == FALSE) + { + /* FIXME: save boot log file */ + + Status = CmiInitHives(SetUpBoot); + + CmiRegistryInitialized = TRUE; + } + + return(Status); +} + +/* EOF */ diff --git a/ntoskrnl/cm/regfile.c b/ntoskrnl/cm/regfile.c new file mode 100644 index 0000000..db89135 --- /dev/null +++ b/ntoskrnl/cm/regfile.c @@ -0,0 +1,1906 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/regfile.c + * PURPOSE: Registry file manipulation routines + * UPDATE HISTORY: +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "cm.h" + + + +BOOLEAN CmiDoVerify = FALSE; + +VOID +CmiCreateDefaultHiveHeader(PHIVE_HEADER Header) +{ + assert(Header); + RtlZeroMemory(Header, sizeof(HIVE_HEADER)); + Header->BlockId = REG_HIVE_ID; + Header->DateModified.dwLowDateTime = 0; + Header->DateModified.dwHighDateTime = 0; + Header->Version = 1; + Header->Unused3 = 1; + Header->Unused4 = 3; + Header->Unused5 = 0; + Header->Unused6 = 1; + Header->Unused7 = 1; + Header->RootKeyCell = 0; + Header->BlockSize = REG_BLOCK_SIZE; + Header->Unused6 = 1; + Header->Checksum = 0; +} + + +VOID +CmiCreateDefaultBinCell(PHBIN BinCell) +{ + assert(BinCell); + RtlZeroMemory(BinCell, sizeof(HBIN)); + BinCell->BlockId = REG_BIN_ID; + BinCell->DateModified.dwLowDateTime = 0; + BinCell->DateModified.dwHighDateTime = 0; + BinCell->BlockSize = REG_BLOCK_SIZE; +} + + +VOID +CmiCreateDefaultRootKeyCell(PKEY_CELL RootKeyCell) +{ + assert(RootKeyCell); + RtlZeroMemory(RootKeyCell, sizeof(KEY_CELL)); + RootKeyCell->CellSize = -sizeof(KEY_CELL); + RootKeyCell->Id = REG_KEY_CELL_ID; + RootKeyCell->Type = REG_ROOT_KEY_CELL_TYPE; + ZwQuerySystemTime((PTIME) &RootKeyCell->LastWriteTime); + RootKeyCell->ParentKeyOffset = 0; + RootKeyCell->NumberOfSubKeys = 0; + RootKeyCell->HashTableOffset = -1; + RootKeyCell->NumberOfValues = 0; + RootKeyCell->ValuesOffset = -1; + RootKeyCell->SecurityKeyOffset = 0; + RootKeyCell->ClassNameOffset = -1; + RootKeyCell->NameSize = 0; + RootKeyCell->ClassSize = 0; +} + + +VOID +CmiVerifyBinCell(PHBIN BinCell) +{ + if (CmiDoVerify) + { + + assert(BinCell); + + if (BinCell->BlockId != REG_BIN_ID) + { + DbgPrint("BlockId is %.08x (should be %.08x)\n", + BinCell->BlockId, REG_BIN_ID); + assert(BinCell->BlockId == REG_BIN_ID); + } + + //BinCell->DateModified.dwLowDateTime + + //BinCell->DateModified.dwHighDateTime + + + if (BinCell->BlockSize != REG_BLOCK_SIZE) + { + DbgPrint("BlockSize is %.08x (should be %.08x)\n", + BinCell->BlockSize, REG_BLOCK_SIZE); + assert(BinCell->BlockSize == REG_BLOCK_SIZE); + } + + } +} + + +VOID +CmiVerifyKeyCell(PKEY_CELL KeyCell) +{ + if (CmiDoVerify) + { + + assert(KeyCell); + + if (KeyCell->CellSize == 0) + { + DbgPrint("CellSize is %d (must not be 0)\n", + KeyCell->CellSize); + assert(KeyCell->CellSize != 0); + } + + if (KeyCell->Id != REG_KEY_CELL_ID) + { + DbgPrint("Id is %.08x (should be %.08x)\n", + KeyCell->Id, REG_KEY_CELL_ID); + assert(KeyCell->Id == REG_KEY_CELL_ID); + } + + if ((KeyCell->Type != REG_KEY_CELL_TYPE) + && (KeyCell->Type != REG_ROOT_KEY_CELL_TYPE)) + { + DbgPrint("Type is %.08x (should be %.08x or %.08x)\n", + KeyCell->Type, REG_KEY_CELL_TYPE, REG_ROOT_KEY_CELL_TYPE); + assert(FALSE); + } + + //KeyCell->LastWriteTime; + + if (KeyCell->ParentKeyOffset < 0) + { + DbgPrint("ParentKeyOffset is %d (must not be < 0)\n", + KeyCell->ParentKeyOffset); + assert(KeyCell->ParentKeyOffset >= 0); + } + + if (KeyCell->NumberOfSubKeys < 0) + { + DbgPrint("NumberOfSubKeys is %d (must not be < 0)\n", + KeyCell->NumberOfSubKeys); + assert(KeyCell->NumberOfSubKeys >= 0); + } + + //KeyCell->HashTableOffset; + + if (KeyCell->NumberOfValues < 0) + { + DbgPrint("NumberOfValues is %d (must not be < 0)\n", + KeyCell->NumberOfValues); + assert(KeyCell->NumberOfValues >= 0); + } + + //KeyCell->ValuesOffset = -1; + + if (KeyCell->SecurityKeyOffset < 0) + { + DbgPrint("SecurityKeyOffset is %d (must not be < 0)\n", + KeyCell->SecurityKeyOffset); + assert(KeyCell->SecurityKeyOffset >= 0); + } + + //KeyCell->ClassNameOffset = -1; + + //KeyCell->NameSize + + //KeyCell->ClassSize + + } +} + + +VOID +CmiVerifyRootKeyCell(PKEY_CELL RootKeyCell) +{ + if (CmiDoVerify) + { + + CmiVerifyKeyCell(RootKeyCell); + + if (RootKeyCell->Type != REG_ROOT_KEY_CELL_TYPE) + { + DbgPrint("Type is %.08x (should be %.08x)\n", + RootKeyCell->Type, REG_ROOT_KEY_CELL_TYPE); + assert(RootKeyCell->Type == REG_ROOT_KEY_CELL_TYPE); + } + + } +} + + +VOID +CmiVerifyValueCell(PVALUE_CELL ValueCell) +{ + if (CmiDoVerify) + { + + assert(ValueCell); + + if (ValueCell->CellSize == 0) + { + DbgPrint("CellSize is %d (must not be 0)\n", + ValueCell->CellSize); + assert(ValueCell->CellSize != 0); + } + + if (ValueCell->Id != REG_VALUE_CELL_ID) + { + DbgPrint("Id is %.08x (should be %.08x)\n", + ValueCell->Id, REG_VALUE_CELL_ID); + assert(ValueCell->Id == REG_VALUE_CELL_ID); + } + + //ValueCell->NameSize; + //ValueCell->LONG DataSize; + //ValueCell->DataOffset; + //ValueCell->ULONG DataType; + //ValueCell->USHORT Flags; + //ValueCell->USHORT Unused1; + //ValueCell->UCHAR Name[0]; + } +} + + +VOID +CmiVerifyValueListCell(PVALUE_LIST_CELL ValueListCell) +{ + if (CmiDoVerify) + { + + if (ValueListCell->CellSize == 0) + { + DbgPrint("CellSize is %d (must not be 0)\n", + ValueListCell->CellSize); + assert(ValueListCell->CellSize != 0); + } + + } +} + + +VOID +CmiVerifyKeyObject(PKEY_OBJECT KeyObject) +{ + if (CmiDoVerify) + { + + if (KeyObject->RegistryHive == NULL) + { + DbgPrint("RegistryHive is NULL (must not be NULL)\n", + KeyObject->RegistryHive); + assert(KeyObject->RegistryHive != NULL); + } + + if (KeyObject->KeyCell == NULL) + { + DbgPrint("KeyCell is NULL (must not be NULL)\n", + KeyObject->KeyCell); + assert(KeyObject->KeyCell != NULL); + } + + if (KeyObject->ParentKey == NULL) + { + DbgPrint("ParentKey is NULL (must not be NULL)\n", + KeyObject->ParentKey); + assert(KeyObject->ParentKey != NULL); + } + + } +} + + +VOID +CmiVerifyHiveHeader(PHIVE_HEADER Header) +{ + if (CmiDoVerify) + { + + if (Header->BlockId != REG_HIVE_ID) + { + DbgPrint("BlockId is %.08x (must be %.08x)\n", + Header->BlockId, + REG_HIVE_ID); + assert(Header->BlockId == REG_HIVE_ID); + } + + if (Header->Unused3 != 1) + { + DbgPrint("Unused3 is %.08x (must be 1)\n", + Header->Unused3); + assert(Header->Unused3 == 1); + } + + if (Header->Unused4 != 3) + { + DbgPrint("Unused4 is %.08x (must be 3)\n", + Header->Unused4); + assert(Header->Unused4 == 3); + } + + if (Header->Unused5 != 0) + { + DbgPrint("Unused5 is %.08x (must be 0)\n", + Header->Unused5); + assert(Header->Unused5 == 0); + } + + if (Header->Unused6 != 1) + { + DbgPrint("Unused6 is %.08x (must be 1)\n", + Header->Unused6); + assert(Header->Unused6 == 1); + } + + if (Header->Unused7 != 1) + { + DbgPrint("Unused7 is %.08x (must be 1)\n", + Header->Unused7); + assert(Header->Unused7 == 1); + } + + } +} + + +VOID +CmiVerifyRegistryHive(PREGISTRY_HIVE RegistryHive) +{ + if (CmiDoVerify) + { + + CmiVerifyHiveHeader(RegistryHive->HiveHeader); + + } +} + + +NTSTATUS +CmiPopulateHive(HANDLE FileHandle) +{ + IO_STATUS_BLOCK IoStatusBlock; + LARGE_INTEGER FileOffset; + PCELL_HEADER FreeCell; + NTSTATUS Status; + PHBIN BinCell; + PCHAR tBuf; + ULONG i; + + tBuf = (PCHAR) ExAllocatePool(NonPagedPool, REG_BLOCK_SIZE); + if (tBuf == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + BinCell = (PHBIN) tBuf; + FreeCell = (PCELL_HEADER) (tBuf + REG_HBIN_DATA_OFFSET); + + CmiCreateDefaultBinCell(BinCell); + + // The whole block is free + FreeCell->CellSize = REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET; + + // Add free blocks so we don't need to expand + // the file for a while + for (i = 0; i < 50; i++) + { + // Block offset of this bin + BinCell->BlockOffset = (2 + i) * REG_BLOCK_SIZE; + + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = (2 + i) * REG_BLOCK_SIZE; + + Status = ZwWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + tBuf, + REG_BLOCK_SIZE, + &FileOffset, + NULL); + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + if (!NT_SUCCESS(Status)) + { + ExFreePool(tBuf); + return Status; + } + } + + ExFreePool(tBuf); + + return Status; +} + + +NTSTATUS +CmiCreateNewRegFile(HANDLE FileHandle) +{ + IO_STATUS_BLOCK IoStatusBlock; + PCELL_HEADER FreeCell; + PHIVE_HEADER HiveHeader; + PKEY_CELL RootKeyCell; + NTSTATUS Status; + PHBIN BinCell; + PCHAR tBuf; + + tBuf = (PCHAR) ExAllocatePool(NonPagedPool, 2 * REG_BLOCK_SIZE); + if (tBuf == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + HiveHeader = (PHIVE_HEADER) tBuf; + BinCell = (PHBIN) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE); + RootKeyCell = (PKEY_CELL) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET); + FreeCell = (PCELL_HEADER) ((ULONG_PTR) tBuf + REG_BLOCK_SIZE + REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); + + CmiCreateDefaultHiveHeader(HiveHeader); + CmiCreateDefaultBinCell(BinCell); + CmiCreateDefaultRootKeyCell(RootKeyCell); + + // First block + BinCell->BlockOffset = 0; + + // Offset to root key block + HiveHeader->RootKeyCell = REG_HBIN_DATA_OFFSET; + + // The rest of the block is free + FreeCell->CellSize = REG_BLOCK_SIZE - (REG_HBIN_DATA_OFFSET + sizeof(KEY_CELL)); + + Status = ZwWriteFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + tBuf, + 2 * REG_BLOCK_SIZE, + 0, + NULL); + + ExFreePool(tBuf); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + +#if 1 + if (NT_SUCCESS(Status)) + { + CmiPopulateHive(FileHandle); + } +#endif + + return Status; +} + + +NTSTATUS +CmiInitPermanentRegistryHive(PREGISTRY_HIVE RegistryHive, + PWSTR Filename, + BOOLEAN CreateNew) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + FILE_STANDARD_INFORMATION fsi; + PCELL_HEADER FreeBlock; + LARGE_INTEGER FileOffset; + BLOCK_OFFSET BlockOffset; + ULONG CreateDisposition; + IO_STATUS_BLOCK IoSB; + HANDLE FileHandle; + DWORD FreeOffset; + NTSTATUS Status; + //BOOLEAN Success; + PHBIN tmpBin; + ULONG i, j; + + /* Duplicate Filename */ + Status = RtlCreateUnicodeString(&RegistryHive->Filename, Filename); + if (!NT_SUCCESS(Status)) + return Status; + + InitializeObjectAttributes(&ObjectAttributes, + &RegistryHive->Filename, + 0, + NULL, + NULL); + + if (CreateNew) + CreateDisposition = FILE_OPEN_IF; + else + CreateDisposition = FILE_OPEN; + + Status = NtCreateFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoSB, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + CreateDisposition, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + if ((CreateNew) && (IoSB.Information == FILE_CREATED)) + { + Status = CmiCreateNewRegFile(FileHandle); + } + + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_ALL_ACCESS, + IoFileObjectType, + UserMode, + (PVOID*) &RegistryHive->FileObject, + NULL); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = 0; + Status = ZwReadFile(FileHandle, + 0, + 0, + 0, + 0, + RegistryHive->HiveHeader, + sizeof(HIVE_HEADER), + &FileOffset, + 0); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + + Status = ZwQueryInformationFile(FileHandle, + &IoSB, + &fsi, + sizeof(fsi), + FileStandardInformation); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } +#if 0 + /* We have a reference to the file object so we don't need the handle anymore */ + ZwClose(FileHandle); +#endif + + RegistryHive->FileSize = fsi.EndOfFile.u.LowPart; + RegistryHive->BlockListSize = (RegistryHive->FileSize / 4096) - 1; + + DPRINT("Space needed for block list describing hive: 0x%x\n", + sizeof(PHBIN *) * RegistryHive->BlockListSize); + + RegistryHive->BlockList = ExAllocatePool(NonPagedPool, + sizeof(PHBIN *) * RegistryHive->BlockListSize); + + if (RegistryHive->BlockList == NULL) + { + ExFreePool(RegistryHive->BlockList); + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#if 0 + /* Map hive into cache memory (readonly) (skip the base block) */ + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = 4096; + Success = CcMapData(RegistryHive->FileObject, /* File object */ + &FileOffset, /* File offset */ + RegistryHive->FileSize - 4096, /* Region length */ + TRUE, /* Wait if needed */ + &RegistryHive->Bcb, /* OUT: Buffer Control Block */ + (PVOID*) &RegistryHive->BlockList[0]); /* OUT: Mapped data pointer */ + + assertmsg(Success, ("Success: %d\n", Success)); + + if (!Success) + { + ExFreePool(RegistryHive->BlockList); + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return Status; + } + +#else + + RegistryHive->BlockList[0] = ExAllocatePool(PagedPool, + RegistryHive->FileSize - 4096); + + if (RegistryHive->BlockList[0] == NULL) + { + ExFreePool(RegistryHive->BlockList); + ObDereferenceObject(RegistryHive->FileObject); + RtlFreeUnicodeString(&RegistryHive->Filename); + return STATUS_INSUFFICIENT_RESOURCES; + } + + FileOffset.u.HighPart = 0; + FileOffset.u.LowPart = 4096; + + Status = ZwReadFile(FileHandle, + 0, + 0, + 0, + 0, + (PVOID) RegistryHive->BlockList[0], + RegistryHive->FileSize - 4096, + &FileOffset, + 0); + + assertmsg(NT_SUCCESS(Status), ("Status: 0x%X\n", Status)); + +#endif + + RegistryHive->FreeListSize = 0; + RegistryHive->FreeListMax = 0; + RegistryHive->FreeList = NULL; + + BlockOffset = 0; + for (i = 0; i < RegistryHive->BlockListSize; i++) + { + RegistryHive->BlockList[i] = (PHBIN) (((ULONG_PTR) RegistryHive->BlockList[0]) + BlockOffset); + tmpBin = (PHBIN) (((ULONG_PTR) RegistryHive->BlockList[i])); + if (tmpBin->BlockId != REG_BIN_ID) + { + DPRINT("Bad BlockId %x, offset %x\n", tmpBin->BlockId, BlockOffset); + KeBugCheck(0); + } + + assertmsg((tmpBin->BlockSize % 4096) == 0, ("BlockSize (0x%.08x) must be multiplum of 4K\n", tmpBin->BlockSize)); + + if (tmpBin->BlockSize > 4096) + { + for (j = 1; j < tmpBin->BlockSize / 4096; j++) + { + RegistryHive->BlockList[i + j] = RegistryHive->BlockList[i]; + } + i = i + j - 1; + } + + /* Search free blocks and add to list */ + FreeOffset = REG_HBIN_DATA_OFFSET; + while (FreeOffset < tmpBin->BlockSize) + { + FreeBlock = (PCELL_HEADER) ((ULONG_PTR) RegistryHive->BlockList[i] + FreeOffset); + if (FreeBlock->CellSize > 0) + { + Status = CmiAddFree(RegistryHive, + FreeBlock, + RegistryHive->BlockList[i]->BlockOffset + FreeOffset); + + if (!NT_SUCCESS(Status)) + { + /* FIXME: */ + assert(FALSE); + } + + FreeOffset += FreeBlock->CellSize; + } + else + { + FreeOffset -= FreeBlock->CellSize; + } + } + BlockOffset += tmpBin->BlockSize; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiInitVolatileRegistryHive(PREGISTRY_HIVE RegistryHive) +{ + PKEY_CELL RootKeyCell; + + RegistryHive->Flags |= HIVE_VOLATILE; + + CmiCreateDefaultHiveHeader(RegistryHive->HiveHeader); + + RootKeyCell = (PKEY_CELL) ExAllocatePool(NonPagedPool, sizeof(KEY_CELL)); + + if (RootKeyCell == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + CmiCreateDefaultRootKeyCell(RootKeyCell); + + RegistryHive->HiveHeader->RootKeyCell = (BLOCK_OFFSET) RootKeyCell; + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiCreateRegistryHive(PWSTR Filename, + PREGISTRY_HIVE *RegistryHive, + BOOLEAN CreateNew) +{ + PREGISTRY_HIVE Hive; + NTSTATUS Status; + + DPRINT("CmiCreateRegistryHive(Filename %S)\n", Filename); + + *RegistryHive = NULL; + + Hive = ExAllocatePool(NonPagedPool, sizeof(REGISTRY_HIVE)); + if (Hive == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + DPRINT("Hive %x\n", Hive); + + RtlZeroMemory(Hive, sizeof(REGISTRY_HIVE)); + + Hive->HiveHeader = (PHIVE_HEADER) + ExAllocatePool(NonPagedPool, sizeof(HIVE_HEADER)); + + if (Hive->HiveHeader == NULL) + { + ExFreePool(Hive); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (Filename != NULL) + { + Status = CmiInitPermanentRegistryHive(Hive, Filename, CreateNew); + } + else + { + Status = CmiInitVolatileRegistryHive(Hive); + } + + if (!NT_SUCCESS(Status)) + { + ExFreePool(Hive->HiveHeader); + ExFreePool(Hive); + return(Status); + } + + KeInitializeSemaphore(&Hive->RegSem, 1, 1); + VERIFY_REGISTRY_HIVE(Hive); + + *RegistryHive = Hive; + + return(STATUS_SUCCESS); +} + + +ULONG +CmiGetMaxNameLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PHASH_TABLE_CELL HashBlock; + PKEY_CELL CurSubKeyCell; + ULONG MaxName; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + MaxName = 0; + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + if (HashBlock == NULL) + { + return 0; + } + + for (i = 0; i < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset != 0) + { + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset, + NULL); + if (MaxName < CurSubKeyCell->NameSize) + { + MaxName = CurSubKeyCell->NameSize; + } + CmiReleaseBlock(RegistryHive, CurSubKeyCell); + } + } + + CmiReleaseBlock(RegistryHive, HashBlock); + + return MaxName; +} + + +ULONG +CmiGetMaxClassLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PHASH_TABLE_CELL HashBlock; + PKEY_CELL CurSubKeyCell; + ULONG MaxClass; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + MaxClass = 0; + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + if (HashBlock == NULL) + { + return 0; + } + + for (i = 0; i < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset != 0) + { + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset, + NULL); + if (MaxClass < CurSubKeyCell->ClassSize) + { + MaxClass = CurSubKeyCell->ClassSize; + } + CmiReleaseBlock(RegistryHive, CurSubKeyCell); + } + } + + CmiReleaseBlock(RegistryHive, HashBlock); + + return MaxClass; +} + + +ULONG +CmiGetMaxValueNameLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + ULONG MaxValueName; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + MaxValueName = 0; + if (ValueListCell == NULL) + { + return 0; + } + + for (i = 0; i < KeyCell->NumberOfValues; i++) + { + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[i], + NULL); + if (CurValueCell != NULL && + MaxValueName < CurValueCell->NameSize) + { + MaxValueName = CurValueCell->NameSize; + } + CmiReleaseBlock(RegistryHive, CurValueCell); + } + + CmiReleaseBlock(RegistryHive, ValueListCell); + + return MaxValueName; +} + + +ULONG +CmiGetMaxValueDataLength(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + ULONG MaxValueData; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + MaxValueData = 0; + if (ValueListCell == NULL) + { + return 0; + } + + for (i = 0; i < KeyCell->NumberOfValues; i++) + { + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[i],NULL); + if ((CurValueCell != NULL) && + (MaxValueData < (CurValueCell->DataSize & LONG_MAX))) + { + MaxValueData = CurValueCell->DataSize & LONG_MAX; + } + CmiReleaseBlock(RegistryHive, CurValueCell); + } + + CmiReleaseBlock(RegistryHive, ValueListCell); + + return MaxValueData; +} + + +NTSTATUS +CmiScanForSubKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + OUT PKEY_CELL *SubKeyCell, + OUT BLOCK_OFFSET *BlockOffset, + IN PCHAR KeyName, + IN ACCESS_MASK DesiredAccess, + IN ULONG Attributes) +{ + PHASH_TABLE_CELL HashBlock; + PKEY_CELL CurSubKeyCell; + WORD KeyLength; + ULONG i; + + VERIFY_KEY_CELL(KeyCell); + + DPRINT("Scanning for sub key %s\n", KeyName); + + assert(RegistryHive); + + KeyLength = strlen(KeyName); + + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + *SubKeyCell = NULL; + if (HashBlock == NULL) + { + return STATUS_SUCCESS; + } + + for (i = 0; (i < KeyCell->NumberOfSubKeys) + && (i < HashBlock->HashTableSize); i++) + { + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if ((HashBlock->Table[i].KeyOffset != 0) && + (HashBlock->Table[i].KeyOffset != -1) && + (_strnicmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4) == 0)) + { + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset, + NULL); + if ((CurSubKeyCell->NameSize == KeyLength) + && (_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength) == 0)) + { + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; + break; + } + else + { + CmiReleaseBlock(RegistryHive, CurSubKeyCell); + } + } + } + else + { + if (HashBlock->Table[i].KeyOffset != 0 && + HashBlock->Table[i].KeyOffset != -1 && + !strncmp(KeyName, (PCHAR) &HashBlock->Table[i].HashValue, 4)) + { + CurSubKeyCell = CmiGetBlock(RegistryHive, + HashBlock->Table[i].KeyOffset,NULL); + if (CurSubKeyCell->NameSize == KeyLength + && !_strnicmp(KeyName, CurSubKeyCell->Name, KeyLength)) + { + *SubKeyCell = CurSubKeyCell; + *BlockOffset = HashBlock->Table[i].KeyOffset; + break; + } + else + { + CmiReleaseBlock(RegistryHive, CurSubKeyCell); + } + } + } + } + + CmiReleaseBlock(RegistryHive, HashBlock); + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiAddSubKey(PREGISTRY_HIVE RegistryHive, + PKEY_OBJECT Parent, + PKEY_OBJECT SubKey, + PWSTR NewSubKeyName, + USHORT NewSubKeyNameSize, + ULONG TitleIndex, + PUNICODE_STRING Class, + ULONG CreateOptions) +{ + PHASH_TABLE_CELL NewHashBlock; + PHASH_TABLE_CELL HashBlock; + BLOCK_OFFSET NKBOffset; + PKEY_CELL NewKeyCell; + ULONG NewBlockSize; + PKEY_CELL KeyCell; + NTSTATUS Status; + USHORT NameSize; + + KeyCell = Parent->KeyCell; + + VERIFY_KEY_CELL(KeyCell); + + if (NewSubKeyName[0] == L'\\') + { + NewSubKeyName++; + NameSize = NewSubKeyNameSize / 2 - 1; + } + else + { + NameSize = NewSubKeyNameSize / 2; + } + Status = STATUS_SUCCESS; + + NewBlockSize = sizeof(KEY_CELL) + NameSize; + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &NewKeyCell, + NewBlockSize, + &NKBOffset); + + if (NewKeyCell == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NewKeyCell->Id = REG_KEY_CELL_ID; + NewKeyCell->Type = REG_KEY_CELL_TYPE; + ZwQuerySystemTime((PTIME) &NewKeyCell->LastWriteTime); + NewKeyCell->ParentKeyOffset = -1; + NewKeyCell->NumberOfSubKeys = 0; + NewKeyCell->HashTableOffset = -1; + NewKeyCell->NumberOfValues = 0; + NewKeyCell->ValuesOffset = -1; + NewKeyCell->SecurityKeyOffset = -1; + NewKeyCell->NameSize = NameSize; + wcstombs(NewKeyCell->Name, NewSubKeyName, NameSize); + NewKeyCell->ClassNameOffset = -1; + + VERIFY_KEY_CELL(NewKeyCell); + + if (Class) + { + PDATA_CELL pClass; + + NewKeyCell->ClassSize = Class->Length + sizeof(WCHAR); + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &pClass, + NewKeyCell->ClassSize, + &NewKeyCell->ClassNameOffset); + wcsncpy((PWSTR) pClass->Data, Class->Buffer, Class->Length); + ((PWSTR) (pClass->Data))[Class->Length] = 0; + } + } + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + SubKey->KeyCell = NewKeyCell; + SubKey->BlockOffset = NKBOffset; + + /* Don't modify hash table if key is volatile and parent is not */ + if (IsVolatileHive(RegistryHive) && (!IsVolatileHive(Parent->RegistryHive))) + { + return Status; + } + + if (KeyCell->HashTableOffset == -1) + { + Status = CmiAllocateHashTableBlock(RegistryHive, + &HashBlock, + &KeyCell->HashTableOffset, + REG_INIT_HASH_TABLE_SIZE); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + HashBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL); + if (((KeyCell->NumberOfSubKeys + 1) >= HashBlock->HashTableSize)) + { + BLOCK_OFFSET HTOffset; + + /* Reallocate the hash table block */ + Status = CmiAllocateHashTableBlock(RegistryHive, + &NewHashBlock, + &HTOffset, + HashBlock->HashTableSize + + REG_EXTEND_HASH_TABLE_SIZE); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + RtlZeroMemory(&NewHashBlock->Table[0], + sizeof(NewHashBlock->Table[0]) * NewHashBlock->HashTableSize); + RtlCopyMemory(&NewHashBlock->Table[0], + &HashBlock->Table[0], + sizeof(NewHashBlock->Table[0]) * HashBlock->HashTableSize); + CmiDestroyBlock(RegistryHive, HashBlock, KeyCell->HashTableOffset); + KeyCell->HashTableOffset = HTOffset; + HashBlock = NewHashBlock; + } + } + + Status = CmiAddKeyToHashTable(RegistryHive, HashBlock, NewKeyCell, NKBOffset); + if (NT_SUCCESS(Status)) + { + KeyCell->NumberOfSubKeys++; + } + + return Status; +} + + +NTSTATUS +CmiScanKeyForValue(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName, + OUT PVALUE_CELL *ValueCell, + OUT BLOCK_OFFSET *VBOffset) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + ULONG Length; + ULONG i; + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + *ValueCell = NULL; + + if (ValueListCell == NULL) + { + DPRINT("ValueListCell is NULL\n"); + return STATUS_SUCCESS; + } + + VERIFY_VALUE_LIST_CELL(ValueListCell); + + for (i = 0; i < KeyCell->NumberOfValues; i++) + { + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[i], + NULL); + /* FIXME: perhaps we must not ignore case if NtCreateKey has not been */ + /* called with OBJ_CASE_INSENSITIVE flag ? */ + Length = strlen(ValueName); + if ((CurValueCell != NULL) && + (CurValueCell->NameSize == Length) && + (_strnicmp(CurValueCell->Name, ValueName, Length) == 0)) + { + *ValueCell = CurValueCell; + if (VBOffset) + *VBOffset = ValueListCell->Values[i]; + DPRINT("Found value %s\n", ValueName); + break; + } + CmiReleaseBlock(RegistryHive, CurValueCell); + } + + CmiReleaseBlock(RegistryHive, ValueListCell); + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN ULONG Index, + OUT PVALUE_CELL *ValueCell) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + *ValueCell = NULL; + + if (ValueListCell == NULL) + { + return STATUS_NO_MORE_ENTRIES; + } + + VERIFY_VALUE_LIST_CELL(ValueListCell); + + if (Index >= KeyCell->NumberOfValues) + { + return STATUS_NO_MORE_ENTRIES; + } + + CurValueCell = CmiGetBlock(RegistryHive, + ValueListCell->Values[Index], + NULL); + + if (CurValueCell != NULL) + { + *ValueCell = CurValueCell; + } + + CmiReleaseBlock(RegistryHive, CurValueCell); + CmiReleaseBlock(RegistryHive, ValueListCell); + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueNameBuf, + OUT PVALUE_CELL *pValueCell, + OUT BLOCK_OFFSET *pVBOffset) +{ + PVALUE_LIST_CELL NewValueListCell; + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL NewValueCell; + BLOCK_OFFSET VLBOffset; + BLOCK_OFFSET VBOffset; + NTSTATUS Status; + + Status = CmiAllocateValueCell(RegistryHive, + &NewValueCell, + &VBOffset, + ValueNameBuf); + *pVBOffset = VBOffset; + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + if (ValueListCell == NULL) + { + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &ValueListCell, + sizeof(BLOCK_OFFSET) * 3, + &VLBOffset); + + if (!NT_SUCCESS(Status)) + { + CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset); + return Status; + } + KeyCell->ValuesOffset = VLBOffset; + } + else if ((KeyCell->NumberOfValues + >= ((LONG) (ValueListCell->CellSize - 4)) / (LONG) sizeof(BLOCK_OFFSET))) + { + Status = CmiAllocateBlock(RegistryHive, + (PVOID) &NewValueListCell, + sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE), + &VLBOffset); + + if (!NT_SUCCESS(Status)) + { + CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset); + return Status; + } + + RtlCopyMemory(&NewValueListCell->Values[0], + &ValueListCell->Values[0], + sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues); + CmiDestroyBlock(RegistryHive, ValueListCell, KeyCell->ValuesOffset); + KeyCell->ValuesOffset = VLBOffset; + ValueListCell = NewValueListCell; + } + + DPRINT("KeyCell->NumberOfValues %d, ValueListCell->CellSize %d (%d %x)\n", + KeyCell->NumberOfValues, ValueListCell->CellSize, + -(ValueListCell->CellSize - 4) / sizeof(BLOCK_OFFSET), + -(ValueListCell->CellSize - 4) / sizeof(BLOCK_OFFSET)); + + ValueListCell->Values[KeyCell->NumberOfValues] = VBOffset; + KeyCell->NumberOfValues++; + CmiReleaseBlock(RegistryHive, ValueListCell); + CmiReleaseBlock(RegistryHive, NewValueCell); + *pValueCell = NewValueCell; + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, + IN PKEY_CELL KeyCell, + IN PCHAR ValueName) +{ + PVALUE_LIST_CELL ValueListCell; + PVALUE_CELL CurValueCell; + ULONG i; + + ValueListCell = CmiGetBlock(RegistryHive, KeyCell->ValuesOffset, NULL); + + if (ValueListCell == NULL) + { + return STATUS_SUCCESS; + } + + VERIFY_VALUE_LIST_CELL(ValueListCell); + + for (i = 0; i < KeyCell->NumberOfValues; i++) + { + CurValueCell = CmiGetBlock(RegistryHive, ValueListCell->Values[i], NULL); + if ((CurValueCell != NULL) && + (CurValueCell->NameSize == strlen(ValueName)) && + (memcmp(CurValueCell->Name, ValueName, strlen(ValueName)) == 0)) + { + if ((KeyCell->NumberOfValues - 1) < i) + { + RtlCopyMemory(&ValueListCell->Values[i], + &ValueListCell->Values[i + 1], + sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i)); + } + else + { + RtlZeroMemory(&ValueListCell->Values[i], sizeof(BLOCK_OFFSET)); + } + + KeyCell->NumberOfValues -= 1; + CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->Values[i]); + break; + } + CmiReleaseBlock(RegistryHive, CurValueCell); + } + + CmiReleaseBlock(RegistryHive, ValueListCell); + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiAllocateHashTableBlock(IN PREGISTRY_HIVE RegistryHive, + OUT PHASH_TABLE_CELL *HashBlock, + OUT BLOCK_OFFSET *HBOffset, + IN ULONG HashTableSize) +{ + PHASH_TABLE_CELL NewHashBlock; + ULONG NewHashSize; + NTSTATUS Status; + + Status = STATUS_SUCCESS; + *HashBlock = NULL; + NewHashSize = sizeof(HASH_TABLE_CELL) + + (HashTableSize - 1) * sizeof(HASH_RECORD); + Status = CmiAllocateBlock(RegistryHive, + (PVOID*) &NewHashBlock, + NewHashSize, + HBOffset); + + if ((NewHashBlock == NULL) || (!NT_SUCCESS(Status))) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NewHashBlock->Id = REG_HASH_TABLE_BLOCK_ID; + NewHashBlock->HashTableSize = HashTableSize; + *HashBlock = NewHashBlock; + } + + return Status; +} + + +PKEY_CELL +CmiGetKeyFromHashByIndex(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + ULONG Index) +{ + BLOCK_OFFSET KeyOffset; + PKEY_CELL KeyCell; + + if (HashBlock == NULL) + return NULL; + + if (IsVolatileHive(RegistryHive)) + { + KeyCell = (PKEY_CELL) HashBlock->Table[Index].KeyOffset; + } + else + { + KeyOffset = HashBlock->Table[Index].KeyOffset; + KeyCell = CmiGetBlock(RegistryHive, KeyOffset, NULL); + } + CmiLockBlock(RegistryHive, KeyCell); + + return KeyCell; +} + + +NTSTATUS +CmiAddKeyToHashTable(PREGISTRY_HIVE RegistryHive, + PHASH_TABLE_CELL HashBlock, + PKEY_CELL NewKeyCell, + BLOCK_OFFSET NKBOffset) +{ + ULONG i; + + for (i = 0; i < HashBlock->HashTableSize; i++) + { + if (HashBlock->Table[i].KeyOffset == 0) + { + HashBlock->Table[i].KeyOffset = NKBOffset; + RtlCopyMemory(&HashBlock->Table[i].HashValue, NewKeyCell->Name, 4); + return STATUS_SUCCESS; + } + } + + return STATUS_UNSUCCESSFUL; +} + + +NTSTATUS +CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive, + PVALUE_CELL *ValueCell, + BLOCK_OFFSET *VBOffset, + IN PCHAR ValueNameBuf) +{ + PVALUE_CELL NewValueCell; + ULONG NewValueSize; + NTSTATUS Status; + + Status = STATUS_SUCCESS; + + NewValueSize = sizeof(VALUE_CELL) + strlen(ValueNameBuf); + Status = CmiAllocateBlock(RegistryHive, + (PVOID*) &NewValueCell, + NewValueSize, + VBOffset); + + if ((NewValueCell == NULL) || (!NT_SUCCESS(Status))) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + NewValueCell->Id = REG_VALUE_CELL_ID; + NewValueCell->NameSize = strlen(ValueNameBuf); + memcpy(NewValueCell->Name, ValueNameBuf, strlen(ValueNameBuf)); + NewValueCell->DataType = 0; + NewValueCell->DataSize = 0; + NewValueCell->DataOffset = 0xffffffff; + *ValueCell = NewValueCell; + } + + return Status; +} + + +NTSTATUS +CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, + PVALUE_CELL ValueCell, + BLOCK_OFFSET VBOffset) +{ + NTSTATUS Status; + PVOID pBlock; + PHBIN pBin; + + VERIFY_VALUE_CELL(ValueCell); + + /* First, release datas: */ + if (ValueCell->DataSize > 0) + { + pBlock = CmiGetBlock(RegistryHive, ValueCell->DataOffset, &pBin); + Status = CmiDestroyBlock(RegistryHive, pBlock, ValueCell->DataOffset); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive)) + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + + Status = CmiDestroyBlock(RegistryHive, ValueCell, VBOffset); + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin)) + { + ZwQuerySystemTime((PTIME) &pBin->DateModified); + } + + return Status; +} + + +NTSTATUS +CmiAddBin(PREGISTRY_HIVE RegistryHive, + PVOID *NewBlock, + BLOCK_OFFSET *NewBlockOffset) +{ + PCELL_HEADER tmpBlock; + PHBIN * tmpBlockList; + PHBIN tmpBin; + + tmpBin = ExAllocatePool(PagedPool, REG_BLOCK_SIZE); + if (tmpBin == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + tmpBin->BlockId = REG_BIN_ID; + tmpBin->BlockOffset = RegistryHive->FileSize - REG_BLOCK_SIZE; + RegistryHive->FileSize += REG_BLOCK_SIZE; + tmpBin->BlockSize = REG_BLOCK_SIZE; + tmpBin->Unused1 = 0; + ZwQuerySystemTime((PTIME) &tmpBin->DateModified); + tmpBin->Unused2 = 0; + + /* Increase size of list of blocks */ + tmpBlockList = ExAllocatePool(NonPagedPool, + sizeof(PHBIN *) * (RegistryHive->BlockListSize + 1)); + if (tmpBlockList == NULL) + { + ExFreePool(tmpBin); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (RegistryHive->BlockListSize > 0) + { + memcpy(tmpBlockList, + RegistryHive->BlockList, + sizeof(PHBIN *)*(RegistryHive->BlockListSize)); + ExFreePool(RegistryHive->BlockList); + } + + RegistryHive->BlockList = tmpBlockList; + RegistryHive->BlockList[RegistryHive->BlockListSize++] = tmpBin; + + /* Initialize a free block in this heap : */ + tmpBlock = (PCELL_HEADER)((ULONG_PTR) tmpBin + REG_HBIN_DATA_OFFSET); + tmpBlock->CellSize = (REG_BLOCK_SIZE - REG_HBIN_DATA_OFFSET); + *NewBlock = (PVOID) tmpBlock; + + if (NewBlockOffset) + *NewBlockOffset = tmpBin->BlockOffset + REG_HBIN_DATA_OFFSET; + + /* FIXME: set first dword to block_offset of another free bloc */ + + return STATUS_SUCCESS; +} + + +NTSTATUS +CmiAllocateBlock(PREGISTRY_HIVE RegistryHive, + PVOID *Block, + LONG BlockSize, + BLOCK_OFFSET * pBlockOffset) +{ + PCELL_HEADER NewBlock; + NTSTATUS Status; + PHBIN pBin; + + Status = STATUS_SUCCESS; + + /* Round to 16 bytes multiple */ + BlockSize = (BlockSize + sizeof(DWORD) + 15) & 0xfffffff0; + + /* Handle volatile hives first */ + if (IsVolatileHive(RegistryHive)) + { + NewBlock = ExAllocatePool(NonPagedPool, BlockSize); + + if (NewBlock == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + RtlZeroMemory(NewBlock, BlockSize); + NewBlock->CellSize = BlockSize; + CmiLockBlock(RegistryHive, NewBlock); + *Block = NewBlock; + if (pBlockOffset) + *pBlockOffset = (BLOCK_OFFSET) NewBlock; + } + } + else + { + ULONG i; + + /* first search in free blocks */ + NewBlock = NULL; + for (i = 0; i < RegistryHive->FreeListSize; i++) + { + if (RegistryHive->FreeList[i]->CellSize >= BlockSize) + { + PVOID Temp; + NewBlock = RegistryHive->FreeList[i]; + + if (pBlockOffset) + *pBlockOffset = RegistryHive->FreeListOffset[i]; + + /* Update time of heap */ + Temp = CmiGetBlock(RegistryHive, RegistryHive->FreeListOffset[i], &pBin); + + if (Temp) + ZwQuerySystemTime((PTIME) &pBin->DateModified); + + if ((i + 1) < RegistryHive->FreeListSize) + { + RtlMoveMemory(&RegistryHive->FreeList[i], + &RegistryHive->FreeList[i + 1], + sizeof(RegistryHive->FreeList[0]) + * (RegistryHive->FreeListSize - i - 1)); + RtlMoveMemory(&RegistryHive->FreeListOffset[i], + &RegistryHive->FreeListOffset[i + 1], + sizeof(RegistryHive->FreeListOffset[0]) + * (RegistryHive->FreeListSize - i - 1)); + } + RegistryHive->FreeListSize--; + break; + } + } + + /* Need to extend hive file : */ + if (NewBlock == NULL) + { + /* Add a new block */ + Status = CmiAddBin(RegistryHive, (PVOID *) &NewBlock , pBlockOffset); + } + + if (NT_SUCCESS(Status)) + { + *Block = NewBlock; + + /* Split the block in two parts */ + if (NewBlock->CellSize > BlockSize) + { + NewBlock = (PCELL_HEADER) ((ULONG_PTR) NewBlock+BlockSize); + NewBlock->CellSize = ((PCELL_HEADER) (*Block))->CellSize - BlockSize; + CmiAddFree(RegistryHive, NewBlock, *pBlockOffset + BlockSize); + } + else if (NewBlock->CellSize < BlockSize) + { + return STATUS_UNSUCCESSFUL; + } + RtlZeroMemory(*Block, BlockSize); + ((PCELL_HEADER) (*Block))->CellSize = -BlockSize; + CmiLockBlock(RegistryHive, *Block); + } + } + return Status; +} + + +NTSTATUS +CmiDestroyBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block, + BLOCK_OFFSET Offset) +{ + NTSTATUS Status; + PHBIN pBin; + + Status = STATUS_SUCCESS; + + if (IsVolatileHive(RegistryHive)) + { + CmiReleaseBlock(RegistryHive, Block); + ExFreePool(Block); + } + else + { + PCELL_HEADER pFree = Block; + + if (pFree->CellSize < 0) + pFree->CellSize = -pFree->CellSize; + + CmiAddFree(RegistryHive, Block, Offset); + CmiReleaseBlock(RegistryHive, Block); + + /* Update time of heap */ + if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, Offset,&pBin)) + ZwQuerySystemTime((PTIME) &pBin->DateModified); + + /* FIXME: Set first dword to block_offset of another free block ? */ + /* FIXME: Concatenate with previous and next block if free */ + } + + return Status; +} + + +NTSTATUS +CmiAddFree(PREGISTRY_HIVE RegistryHive, + PCELL_HEADER FreeBlock, + BLOCK_OFFSET FreeOffset) +{ + PCELL_HEADER *tmpList; + BLOCK_OFFSET *tmpListOffset; + LONG minInd; + LONG maxInd; + LONG medInd; + + assert(RegistryHive); + assert(FreeBlock); + + DPRINT("FreeBlock %.08x FreeOffset %.08x\n", + FreeBlock, FreeOffset); +DPRINT("\n"); + if ((RegistryHive->FreeListSize + 1) > RegistryHive->FreeListMax) + { +DPRINT("\n"); + tmpList = ExAllocatePool(PagedPool, + sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax + 32)); +DPRINT("\n"); + + if (tmpList == NULL) + return STATUS_INSUFFICIENT_RESOURCES; +DPRINT("\n"); + + tmpListOffset = ExAllocatePool(PagedPool, + sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax + 32)); +DPRINT("\n"); + + if (tmpListOffset == NULL) + { + ExFreePool(tmpList); + return STATUS_INSUFFICIENT_RESOURCES; + } +DPRINT("\n"); + + if (RegistryHive->FreeListMax) + { +DPRINT("\n"); + RtlMoveMemory(tmpList, RegistryHive->FreeList, + sizeof(PCELL_HEADER) * (RegistryHive->FreeListMax)); +DPRINT("\n"); + RtlMoveMemory(tmpListOffset, RegistryHive->FreeListOffset, + sizeof(BLOCK_OFFSET *) * (RegistryHive->FreeListMax)); +DPRINT("\n"); + ExFreePool(RegistryHive->FreeList); +DPRINT("\n"); + ExFreePool(RegistryHive->FreeListOffset); +DPRINT("\n"); + } +DPRINT("\n"); + RegistryHive->FreeList = tmpList; + RegistryHive->FreeListOffset = tmpListOffset; + RegistryHive->FreeListMax += 32; +DPRINT("\n"); + } +DPRINT("\n"); + + /* Add new offset to free list, maintaining list in ascending order */ + if ((RegistryHive->FreeListSize == 0) + || (RegistryHive->FreeListOffset[RegistryHive->FreeListSize-1] < FreeOffset)) + { +DPRINT("\n"); + /* Add to end of list */ + RegistryHive->FreeList[RegistryHive->FreeListSize] = FreeBlock; + RegistryHive->FreeListOffset[RegistryHive->FreeListSize++] = FreeOffset; + } + else if (RegistryHive->FreeListOffset[0] > FreeOffset) + { +DPRINT("\n"); + /* Add to begin of list */ + RtlMoveMemory(&RegistryHive->FreeList[1], + &RegistryHive->FreeList[0], + sizeof(RegistryHive->FreeList[0]) * RegistryHive->FreeListSize); + RtlMoveMemory(&RegistryHive->FreeListOffset[1], + &RegistryHive->FreeListOffset[0], + sizeof(RegistryHive->FreeListOffset[0]) * RegistryHive->FreeListSize); + RegistryHive->FreeList[0] = FreeBlock; + RegistryHive->FreeListOffset[0] = FreeOffset; + RegistryHive->FreeListSize++; + } + else + { +DPRINT("\n"); + /* Search where to insert */ + minInd = 0; + maxInd = RegistryHive->FreeListSize - 1; + while ((maxInd - minInd) > 1) + { + medInd = (minInd + maxInd) / 2; + if (RegistryHive->FreeListOffset[medInd] > FreeOffset) + maxInd = medInd; + else + minInd = medInd; + } + + /* Insert before maxInd */ + RtlMoveMemory(&RegistryHive->FreeList[maxInd+1], + &RegistryHive->FreeList[maxInd], + sizeof(RegistryHive->FreeList[0]) * (RegistryHive->FreeListSize - minInd)); + RtlMoveMemory(&RegistryHive->FreeListOffset[maxInd + 1], + &RegistryHive->FreeListOffset[maxInd], + sizeof(RegistryHive->FreeListOffset[0]) * (RegistryHive->FreeListSize-minInd)); + RegistryHive->FreeList[maxInd] = FreeBlock; + RegistryHive->FreeListOffset[maxInd] = FreeOffset; + RegistryHive->FreeListSize++; + } +DPRINT("\n"); + + return STATUS_SUCCESS; +} + + +PVOID +CmiGetBlock(PREGISTRY_HIVE RegistryHive, + BLOCK_OFFSET BlockOffset, + PHBIN * ppBin) +{ + if (ppBin) + *ppBin = NULL; + + if ((BlockOffset == 0) || (BlockOffset == -1)) + return NULL; + + if (IsVolatileHive(RegistryHive)) + { + return (PVOID) BlockOffset; + } + else + { + PHBIN pBin; + + pBin = RegistryHive->BlockList[BlockOffset / 4096]; + if (ppBin) + *ppBin = pBin; + return ((PVOID) ((ULONG_PTR) pBin + (BlockOffset - pBin->BlockOffset))); + } +} + + +VOID +CmiPrepareForWrite(PREGISTRY_HIVE RegistryHive, + PHBIN pBin) +{ + if (IsVolatileHive(RegistryHive)) + { + /* No need to do anything special for volatile hives */ + return; + } + else + { + + } +} + + +VOID +CmiLockBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block) +{ + if (IsPermanentHive(RegistryHive)) + { + /* FIXME: Implement */ + } +} + + +VOID +CmiReleaseBlock(PREGISTRY_HIVE RegistryHive, + PVOID Block) +{ + if (IsPermanentHive(RegistryHive)) + { + /* FIXME: Implement */ + } +} diff --git a/ntoskrnl/cm/registry.c b/ntoskrnl/cm/registry.c new file mode 100644 index 0000000..d0d9c1d --- /dev/null +++ b/ntoskrnl/cm/registry.c @@ -0,0 +1,779 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/registry.c + * PURPOSE: Registry functions + * PROGRAMMERS: Rex Jolliff + * Matt Pyne + * Jean Michault + * UPDATE HISTORY: + * Created 22/05/98 + */ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "cm.h" + +/* ------------------------------------------------- File Statics */ + +POBJECT_TYPE CmiKeyType = NULL; +PREGISTRY_HIVE CmiVolatileHive = NULL; +KSPIN_LOCK CmiKeyListLock; + +static PKEY_OBJECT CmiRootKey = NULL; +static PKEY_OBJECT CmiMachineKey = NULL; +static PKEY_OBJECT CmiUserKey = NULL; +static PKEY_OBJECT CmiHardwareKey = NULL; + +static GENERIC_MAPPING CmiKeyMapping = + {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS}; + + +VOID +CmiCheckKey(BOOLEAN Verbose, + HANDLE Key); + +static NTSTATUS +CmiCreateCurrentControlSetLink(VOID); + +/* FUNCTIONS ****************************************************************/ + +VOID +CmiCheckSubKeys(BOOLEAN Verbose, + HANDLE Key) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_NODE_INFORMATION KeyInfo; + WCHAR KeyBuffer[MAX_PATH]; + UNICODE_STRING KeyPath; + WCHAR Name[MAX_PATH]; + ULONG BufferSize; + ULONG ResultSize; + NTSTATUS Status; + HANDLE SubKey; + ULONG Index; + + Index = 0; + while (TRUE) + { + BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; + KeyInfo = ExAllocatePool(PagedPool, BufferSize); + + Status = NtEnumerateKey(Key, + Index, + KeyNodeInformation, + KeyInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + ExFreePool(KeyInfo); + if (Status == STATUS_NO_MORE_ENTRIES) + Status = STATUS_SUCCESS; + break; + } + + wcsncpy(Name, + KeyInfo->Name, + KeyInfo->NameLength / sizeof(WCHAR)); + + if (Verbose) + { + DbgPrint("Key: %S\n", Name); + } + + /* FIXME: Check info. */ + + ExFreePool(KeyInfo); + + wcscpy(KeyBuffer, L"\\Registry\\"); + wcscat(KeyBuffer, Name); + + RtlInitUnicodeString(&KeyPath, KeyBuffer); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&SubKey, + KEY_ALL_ACCESS, + &ObjectAttributes); + + assert(NT_SUCCESS(Status)); + + CmiCheckKey(Verbose, SubKey); + + NtClose(SubKey); + + Index++; + } + + assert(NT_SUCCESS(Status)); +} + + +VOID +CmiCheckValues(BOOLEAN Verbose, + HANDLE Key) +{ + PKEY_NODE_INFORMATION ValueInfo; + WCHAR Name[MAX_PATH]; + ULONG BufferSize; + ULONG ResultSize; + NTSTATUS Status; + ULONG Index; + + Index = 0; + while (TRUE) + { + BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096; + ValueInfo = ExAllocatePool(PagedPool, BufferSize); + + Status = NtEnumerateValueKey(Key, + Index, + KeyNodeInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ValueInfo); + if (Status == STATUS_NO_MORE_ENTRIES) + Status = STATUS_SUCCESS; + break; + } + + wcsncpy(Name, + ValueInfo->Name, + ValueInfo->NameLength / sizeof(WCHAR)); + + if (Verbose) + { + DbgPrint("Value: %S\n", Name); + } + + /* FIXME: Check info. */ + + ExFreePool(ValueInfo); + + Index++; + } + + assert(NT_SUCCESS(Status)); +} + + +VOID +CmiCheckKey(BOOLEAN Verbose, + HANDLE Key) +{ + CmiCheckValues(Verbose, Key); + CmiCheckSubKeys(Verbose, Key); +} + + +VOID +CmiCheckByName(BOOLEAN Verbose, + PWSTR KeyName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR KeyPathBuffer[MAX_PATH]; + UNICODE_STRING KeyPath; + NTSTATUS Status; + HANDLE Key; + + wcscpy(KeyPathBuffer, L"\\Registry\\"); + wcscat(KeyPathBuffer, KeyName); + + RtlInitUnicodeString(&KeyPath, KeyPathBuffer); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&Key, + KEY_ALL_ACCESS, + &ObjectAttributes); + + if (CHECKED) + { + if (!NT_SUCCESS(Status)) + { + DbgPrint("KeyPath %wZ Status: %.08x", KeyPath, Status); + DbgPrint("KeyPath %S Status: %.08x", KeyPath.Buffer, Status); + assert(NT_SUCCESS(Status)); + } + } + + CmiCheckKey(Verbose, Key); + + NtClose(Key); +} + + +VOID +CmiCheckRegistry(BOOLEAN Verbose) +{ + if (Verbose) + DbgPrint("Checking registry internals\n"); + + CmiCheckByName(Verbose, L"Machine"); + CmiCheckByName(Verbose, L"User"); +} + + +VOID +CmInitializeRegistry(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING RootKeyName; + HANDLE RootKeyHandle; + PKEY_OBJECT NewKey; + HANDLE KeyHandle; + NTSTATUS Status; + + /* Initialize the Key object type */ + CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + assert(CmiKeyType); + CmiKeyType->TotalObjects = 0; + CmiKeyType->TotalHandles = 0; + CmiKeyType->MaxObjects = LONG_MAX; + CmiKeyType->MaxHandles = LONG_MAX; + CmiKeyType->PagedPoolCharge = 0; + CmiKeyType->NonpagedPoolCharge = sizeof(KEY_OBJECT); + CmiKeyType->Mapping = &CmiKeyMapping; + CmiKeyType->Dump = NULL; + CmiKeyType->Open = NULL; + CmiKeyType->Close = NULL; + CmiKeyType->Delete = CmiObjectDelete; + CmiKeyType->Parse = CmiObjectParse; + CmiKeyType->Security = NULL; + CmiKeyType->QueryName = NULL; + CmiKeyType->OkayToClose = NULL; + CmiKeyType->Create = CmiObjectCreate; + CmiKeyType->DuplicationNotify = NULL; + RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key"); + + /* Build volatile registry store */ + Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE); + assert(NT_SUCCESS(Status)); + + /* Build the Root Key Object */ + RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME); + InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL); + Status = ObCreateObject(&RootKeyHandle, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + CmiKeyType, + (PVOID *) &NewKey); + assert(NT_SUCCESS(Status)); + CmiRootKey = NewKey; + Status = ObReferenceObjectByHandle(RootKeyHandle, + STANDARD_RIGHTS_REQUIRED, + CmiKeyType, + KernelMode, + (PVOID *) &CmiRootKey, + NULL); + assert(NT_SUCCESS(Status)); + CmiRootKey->RegistryHive = CmiVolatileHive; + NewKey->BlockOffset = CmiVolatileHive->HiveHeader->RootKeyCell; + NewKey->KeyCell = CmiGetBlock(CmiVolatileHive, NewKey->BlockOffset, NULL); + CmiRootKey->Flags = 0; + CmiRootKey->NumberOfSubKeys = 0; + CmiRootKey->SubKeys = NULL; + CmiRootKey->SizeOfSubKeys = 0; + CmiRootKey->Name = ExAllocatePool(PagedPool, strlen("Registry")); + CmiRootKey->NameSize = strlen("Registry"); + memcpy(CmiRootKey->Name, "Registry", strlen("Registry")); + + KeInitializeSpinLock(&CmiKeyListLock); + + /* Create initial predefined symbolic links */ + + /* HKEY_LOCAL_MACHINE */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiRootKey, + NewKey, + L"Machine", + wcslen(L"Machine") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("Machine")); + NewKey->NameSize = strlen("Machine"); + memcpy(NewKey->Name, "Machine", strlen("Machine")); + CmiAddKeyToList(CmiRootKey, NewKey); + CmiMachineKey = NewKey; + + /* HKEY_USERS */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiRootKey, + NewKey, + L"User", + wcslen(L"User") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("User")); + NewKey->NameSize = strlen("User"); + memcpy(NewKey->Name, "User", strlen("User")); + CmiAddKeyToList(CmiRootKey, NewKey); + CmiUserKey = NewKey; + + /* Create '\\Registry\\Machine\\HARDWARE' key. */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*)&NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiMachineKey, + NewKey, + L"HARDWARE", + wcslen(L"HARDWARE") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("HARDWARE")); + NewKey->NameSize = strlen("HARDWARE"); + memcpy(NewKey->Name, "HARDWARE", strlen("HARDWARE")); + CmiAddKeyToList(CmiMachineKey, NewKey); + CmiHardwareKey = NewKey; + + /* Create '\\Registry\\Machine\\HARDWARE\\DESCRIPTION' key. */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiHardwareKey, + NewKey, + L"DESCRIPTION", + wcslen(L"DESCRIPTION") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("DESCRIPTION")); + NewKey->NameSize = strlen("DESCRIPTION"); + memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION")); + CmiAddKeyToList(CmiHardwareKey, NewKey); + + /* Create '\\Registry\\Machine\\HARDWARE\\DEVICEMAP' key. */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiHardwareKey, + NewKey, + L"DEVICEMAP", + wcslen(L"DEVICEMAP") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("DEVICEMAP")); + NewKey->NameSize = strlen("DEVICEMAP"); + memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP")); + CmiAddKeyToList(CmiHardwareKey,NewKey); + + /* Create '\\Registry\\Machine\\HARDWARE\\RESOURCEMAP' key. */ + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*) &NewKey); + assert(NT_SUCCESS(Status)); + Status = CmiAddSubKey(CmiVolatileHive, + CmiHardwareKey, + NewKey, + L"RESOURCEMAP", + wcslen(L"RESOURCEMAP") * sizeof(WCHAR), + 0, + NULL, + 0); + assert(NT_SUCCESS(Status)); + NewKey->RegistryHive = CmiVolatileHive; + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = NULL; + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen("RESOURCEMAP")); + NewKey->NameSize = strlen("RESOURCEMAP"); + memcpy(NewKey->Name, "RESOURCEMAP", strlen("RESOURCEMAP")); + CmiAddKeyToList(CmiHardwareKey, NewKey); + + /* FIXME: create remaining structure needed for default handles */ + /* FIXME: load volatile registry data from ROSDTECT */ +} + + +VOID +CmInit2(PCHAR CommandLine) +{ + PCHAR p1, p2; + ULONG PiceStart; + + /* FIXME: Store current command line */ + + /* Create the 'CurrentControlSet' link. */ + CmiCreateCurrentControlSetLink(); + + + /* Set PICE 'Start' value to 1, if PICE debugging is enabled */ + PiceStart = 4; + p1 = (PCHAR)CommandLine; + while (p1 && (p2 = strchr(p1, '/'))) + { + p2++; + if (_strnicmp(p2, "DEBUGPORT", 9) == 0) + { + p2 += 9; + if (*p2 == '=') + { + p2++; + if (_strnicmp(p2, "PICE", 4) == 0) + { + p2 += 4; + PiceStart = 1; + } + } + } + p1 = p2; + } + + RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, + L"\\Pice", + L"Start", + REG_DWORD, + &PiceStart, + sizeof(ULONG)); + +} + + +static NTSTATUS +CmiCreateCurrentControlSetLink(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[5]; + WCHAR TargetNameBuffer[80]; + ULONG TargetNameLength; + UNICODE_STRING LinkName; + UNICODE_STRING LinkValue; + ULONG CurrentSet; + ULONG DefaultSet; + ULONG Failed; + ULONG LastKnownGood; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + + DPRINT("CmiCreateCurrentControlSetLink() called\n"); + + RtlZeroMemory(&QueryTable, sizeof(QueryTable)); + + QueryTable[0].Name = L"Current"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &CurrentSet; + + QueryTable[1].Name = L"Default"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[1].EntryContext = &DefaultSet; + + QueryTable[2].Name = L"Failed"; + QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[2].EntryContext = &Failed; + + QueryTable[3].Name = L"LastKnownGood"; + QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[3].EntryContext = &LastKnownGood; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, + L"\\Registry\\Machine\\SYSTEM\\Select", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("Current %ld Default %ld\n", CurrentSet, DefaultSet); + + swprintf(TargetNameBuffer, + L"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu", + CurrentSet); + TargetNameLength = wcslen(TargetNameBuffer) * sizeof(WCHAR); + + DPRINT("Link target '%S'\n", TargetNameBuffer); + + RtlInitUnicodeStringFromLiteral(&LinkName, + L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet"); + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK, + NULL, + NULL); + Status = NtCreateKey(&KeyHandle, + KEY_ALL_ACCESS | KEY_CREATE_LINK, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); + return(Status); + } + + RtlInitUnicodeStringFromLiteral(&LinkValue, + L"SymbolicLinkValue"); + Status=NtSetValueKey(KeyHandle, + &LinkValue, + 0, + REG_LINK, + (PVOID)TargetNameBuffer, + TargetNameLength); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status); + } + + NtClose(KeyHandle); + + return(Status); +} + + +NTSTATUS +CmiConnectHive(PWSTR FileName, + PWSTR FullName, + PCHAR KeyName, + PKEY_OBJECT Parent, + BOOLEAN CreateNew) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PREGISTRY_HIVE RegistryHive = NULL; + UNICODE_STRING uKeyName; + PKEY_OBJECT NewKey; + HANDLE KeyHandle; + NTSTATUS Status; + + DPRINT("Called. FileName %S\n", FullName); + + Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew); + if (!NT_SUCCESS(Status)) + return(Status); + + RtlInitUnicodeString(&uKeyName, FullName); + + InitializeObjectAttributes(&ObjectAttributes, + &uKeyName, + 0, + NULL, + NULL); + + Status = ObCreateObject(&KeyHandle, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + CmiKeyType, + (PVOID*)&NewKey); + if (!NT_SUCCESS(Status)) + return(Status); + + NewKey->RegistryHive = RegistryHive; + NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell; + NewKey->KeyCell = CmiGetBlock(RegistryHive, NewKey->BlockOffset, NULL); + NewKey->Flags = 0; + NewKey->NumberOfSubKeys = 0; + NewKey->SubKeys = ExAllocatePool(PagedPool, + NewKey->KeyCell->NumberOfSubKeys * sizeof(DWORD)); + + if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0)) + { + /* FIXME: Cleanup from CmiCreateRegistryHive() */ + DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys); + ZwClose(NewKey); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys; + NewKey->Name = ExAllocatePool(PagedPool, strlen(KeyName)); + + if ((NewKey->Name == NULL) && (strlen(KeyName) != 0)) + { + /* FIXME: Cleanup from CmiCreateRegistryHive() */ + DPRINT("strlen(KeyName) %d\n", strlen(KeyName)); + if (NewKey->SubKeys != NULL) + ExFreePool(NewKey->SubKeys); + ZwClose(NewKey); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + NewKey->NameSize = strlen(KeyName); + memcpy(NewKey->Name, KeyName, strlen(KeyName)); + CmiAddKeyToList(Parent, NewKey); + + VERIFY_KEY_OBJECT(NewKey); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +CmiInitializeHive(PWSTR FileName, + PWSTR FullName, + PCHAR KeyName, + PKEY_OBJECT Parent, + BOOLEAN CreateNew) +{ + NTSTATUS Status; + + DPRINT("CmiInitializeHive(%s) called\n", KeyName); + + /* Try to connect the hive */ + //Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE); + Status = CmiConnectHive(FileName, FullName, KeyName, Parent, CreateNew); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Status %.08x\n", Status); +#if 0 + WCHAR AltFileName[MAX_PATH]; + + CPRINT("WARNING! Registry file %S not found\n", FileName); + + wcscpy(AltFileName, FileName); + wcscat(AltFileName, L".alt"); + + /* Try to connect the alternative hive */ + Status = CmiConnectHive(AltFileName, FullName, KeyName, Parent, TRUE); + + if (!NT_SUCCESS(Status)) + { + CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName); + DPRINT("Status %.08x\n", Status); + } +#endif + } + + DPRINT("CmiInitializeHive() done\n"); + + return(Status); +} + + +NTSTATUS +CmiInitHives(BOOLEAN SetUpBoot) +{ + NTSTATUS Status; + + DPRINT("CmiInitHives() called\n"); + + CmiDoVerify = TRUE; + + /* FIXME: Delete temporary \Registry\Machine\System */ + + /* Connect the SYSTEM hive */ + /* FIXME: Don't overwrite the existing 'System' hive yet */ +// Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey); +// assert(NT_SUCCESS(Status)); + + /* Connect the SOFTWARE hive */ + Status = CmiInitializeHive(SOFTWARE_REG_FILE, REG_SOFTWARE_KEY_NAME, "Software", CmiMachineKey, SetUpBoot); + //assert(NT_SUCCESS(Status)); + + /* Connect the SAM hive */ + Status = CmiInitializeHive(SAM_REG_FILE,REG_SAM_KEY_NAME, "Sam", CmiMachineKey, SetUpBoot); + //assert(NT_SUCCESS(Status)); + + /* Connect the SECURITY hive */ + Status = CmiInitializeHive(SEC_REG_FILE, REG_SEC_KEY_NAME, "Security", CmiMachineKey, SetUpBoot); + //assert(NT_SUCCESS(Status)); + + /* Connect the DEFAULT hive */ + Status = CmiInitializeHive(USER_REG_FILE, REG_USER_KEY_NAME, ".Default", CmiUserKey, SetUpBoot); + //assert(NT_SUCCESS(Status)); + + /* FIXME : initialize standards symbolic links */ + +// CmiCheckRegistry(TRUE); + + DPRINT("CmiInitHives() done\n"); + + return(STATUS_SUCCESS); +} + + +VOID +CmShutdownRegistry(VOID) +{ + DPRINT("CmShutdownRegistry() called\n"); + + /* Note: + * Don't call UNIMPLEMENTED() here since this function is + * called by NtShutdownSystem(). + */ +} + +/* EOF */ diff --git a/ntoskrnl/cm/regobj.c b/ntoskrnl/cm/regobj.c new file mode 100644 index 0000000..41cfcbd --- /dev/null +++ b/ntoskrnl/cm/regobj.c @@ -0,0 +1,470 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/regobj.c + * PURPOSE: Registry object manipulation routines. + * UPDATE HISTORY: +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "cm.h" + + +static NTSTATUS +CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell, + PUNICODE_STRING TargetPath); + +/* FUNCTONS *****************************************************************/ + +NTSTATUS STDCALL +CmiObjectParse(PVOID ParsedObject, + PVOID *NextObject, + PUNICODE_STRING FullPath, + PWSTR *Path, + ULONG Attributes) +{ + BLOCK_OFFSET BlockOffset; + PKEY_OBJECT FoundObject; + PKEY_OBJECT ParsedKey; + PKEY_CELL SubKeyCell; + CHAR cPath[MAX_PATH]; + NTSTATUS Status; + PWSTR end; + UNICODE_STRING LinkPath; + UNICODE_STRING TargetPath; + + ParsedKey = ParsedObject; + + VERIFY_KEY_OBJECT(ParsedKey); + + *NextObject = NULL; + + if ((*Path) == NULL) + { + DPRINT("*Path is NULL\n"); + return STATUS_UNSUCCESSFUL; + } + + DPRINT("Path '%S'\n", *Path); + + if ((*Path[0]) == '\\') + { + end = wcschr((*Path) + 1, '\\'); + if (end != NULL) + *end = 0; + wcstombs(cPath, (*Path) + 1, wcslen((*Path) + 1)); + cPath[wcslen((*Path) + 1)] = 0; + } + else + { + end = wcschr((*Path), '\\'); + if (end != NULL) + *end = 0; + wcstombs(cPath, (*Path), wcslen((*Path))); + cPath[wcslen((*Path))] = 0; + } + + FoundObject = CmiScanKeyList(ParsedKey, cPath, Attributes); + if (FoundObject == NULL) + { + Status = CmiScanForSubKey(ParsedKey->RegistryHive, + ParsedKey->KeyCell, + &SubKeyCell, + &BlockOffset, + cPath, + 0, + Attributes); + if (!NT_SUCCESS(Status) || (SubKeyCell == NULL)) + { + if (end != NULL) + { + *end = '\\'; + } + return(STATUS_UNSUCCESSFUL); + } + + if ((SubKeyCell->Type == REG_LINK_KEY_CELL_TYPE) && + !((Attributes & OBJ_OPENLINK) && (end == NULL))) + { + RtlInitUnicodeString(&LinkPath, NULL); + Status = CmiGetLinkTarget(ParsedKey->RegistryHive, + SubKeyCell, + &LinkPath); + if (NT_SUCCESS(Status)) + { + DPRINT("LinkPath '%wZ'\n", &LinkPath); + + /* build new FullPath for reparsing */ + TargetPath.MaximumLength = LinkPath.MaximumLength; + if (end != NULL) + { + *end = '\\'; + TargetPath.MaximumLength += (wcslen(end) * sizeof(WCHAR)); + } + TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR); + TargetPath.Buffer = ExAllocatePool(NonPagedPool, + TargetPath.MaximumLength); + wcscpy(TargetPath.Buffer, LinkPath.Buffer); + if (end != NULL) + { + wcscat(TargetPath.Buffer, end); + } + + RtlFreeUnicodeString(FullPath); + RtlFreeUnicodeString(&LinkPath); + FullPath->Length = TargetPath.Length; + FullPath->MaximumLength = TargetPath.MaximumLength; + FullPath->Buffer = TargetPath.Buffer; + + DPRINT("FullPath '%wZ'\n", FullPath); + + /* reinitialize Path for reparsing */ + *Path = FullPath->Buffer; + + *NextObject = NULL; + return(STATUS_REPARSE); + } + } + + /* Create new key object and put into linked list */ + DPRINT("CmiObjectParse %s\n", cPath); + Status = ObCreateObject(NULL, + STANDARD_RIGHTS_REQUIRED, + NULL, + CmiKeyType, + (PVOID*)&FoundObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + FoundObject->Flags = 0; + FoundObject->Name = SubKeyCell->Name; + FoundObject->NameSize = SubKeyCell->NameSize; + FoundObject->KeyCell = SubKeyCell; + FoundObject->BlockOffset = BlockOffset; + FoundObject->RegistryHive = ParsedKey->RegistryHive; + CmiAddKeyToList(ParsedKey, FoundObject); + DPRINT("Created object 0x%x\n", FoundObject); + } + else + { + if ((FoundObject->KeyCell->Type == REG_LINK_KEY_CELL_TYPE) && + !((Attributes & OBJ_OPENLINK) && (end == NULL))) + { + RtlInitUnicodeString(&LinkPath, NULL); + Status = CmiGetLinkTarget(FoundObject->RegistryHive, + FoundObject->KeyCell, + &LinkPath); + if (NT_SUCCESS(Status)) + { + DPRINT("LinkPath '%wZ'\n", &LinkPath); + + /* build new FullPath for reparsing */ + TargetPath.MaximumLength = LinkPath.MaximumLength; + if (end != NULL) + { + *end = '\\'; + TargetPath.MaximumLength += (wcslen(end) * sizeof(WCHAR)); + } + TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR); + TargetPath.Buffer = ExAllocatePool(NonPagedPool, + TargetPath.MaximumLength); + wcscpy(TargetPath.Buffer, LinkPath.Buffer); + if (end != NULL) + { + wcscat(TargetPath.Buffer, end); + } + + RtlFreeUnicodeString(FullPath); + RtlFreeUnicodeString(&LinkPath); + FullPath->Length = TargetPath.Length; + FullPath->MaximumLength = TargetPath.MaximumLength; + FullPath->Buffer = TargetPath.Buffer; + + DPRINT("FullPath '%wZ'\n", FullPath); + + /* reinitialize Path for reparsing */ + *Path = FullPath->Buffer; + + *NextObject = NULL; + return(STATUS_REPARSE); + } + } + + ObReferenceObjectByPointer(FoundObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + } + + DPRINT("CmiObjectParse %s\n", FoundObject->Name); + + if (end != NULL) + { + *end = '\\'; + *Path = end; + } + else + { + *Path = NULL; + } + + VERIFY_KEY_OBJECT(FoundObject); + + *NextObject = FoundObject; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +CmiObjectCreate(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes) +{ + PKEY_OBJECT pKey = ObjectBody; + + pKey->ParentKey = Parent; + if (RemainingPath) + { + if(RemainingPath[0]== L'\\') + { + pKey->Name = (PCHAR)(&RemainingPath[1]); + pKey->NameSize = wcslen(RemainingPath) - 1; + } + else + { + pKey->Name = (PCHAR)RemainingPath; + pKey->NameSize = wcslen(RemainingPath); + } + } + else + { + pKey->NameSize = 0; + } + + return STATUS_SUCCESS; +} + + +VOID STDCALL +CmiObjectDelete(PVOID DeletedObject) +{ + PKEY_OBJECT KeyObject; + + DPRINT("Delete object key\n"); + + KeyObject = (PKEY_OBJECT) DeletedObject; + + if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject))) + { + DPRINT1("Key not found in parent list ???\n"); + } + + if (KeyObject->Flags & KO_MARKED_FOR_DELETE) + { + DPRINT("delete really key\n"); + CmiDestroyBlock(KeyObject->RegistryHive, + KeyObject->KeyCell, + KeyObject->BlockOffset); + } + else + { + CmiReleaseBlock(KeyObject->RegistryHive, KeyObject->KeyCell); + } +} + + +VOID +CmiAddKeyToList(PKEY_OBJECT ParentKey, + PKEY_OBJECT NewKey) +{ + KIRQL OldIrql; + + DPRINT("ParentKey %.08x\n", ParentKey); + + KeAcquireSpinLock(&CmiKeyListLock, &OldIrql); + + if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys) + { + PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool, + (ParentKey->NumberOfSubKeys + 1) * sizeof(DWORD)); + + if (ParentKey->NumberOfSubKeys > 0) + { + memcpy(tmpSubKeys, + ParentKey->SubKeys, + ParentKey->NumberOfSubKeys * sizeof(DWORD)); + } + + if (ParentKey->SubKeys) + ExFreePool(ParentKey->SubKeys); + + ParentKey->SubKeys = tmpSubKeys; + ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1; + } + + /* FIXME: Please maintain the list in alphabetic order */ + /* to allow a dichotomic search */ + ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey; + + DPRINT("Reference parent key: 0x%x\n", ParentKey); + + ObReferenceObjectByPointer(ParentKey, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + NewKey->ParentKey = ParentKey; + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); +} + + +NTSTATUS +CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove) +{ + PKEY_OBJECT ParentKey; + KIRQL OldIrql; + DWORD Index; + + ParentKey = KeyToRemove->ParentKey; + KeAcquireSpinLock(&CmiKeyListLock, &OldIrql); + /* FIXME: If list maintained in alphabetic order, use dichotomic search */ + for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++) + { + if (ParentKey->SubKeys[Index] == KeyToRemove) + { + if (Index < ParentKey->NumberOfSubKeys-1) + RtlMoveMemory(&ParentKey->SubKeys[Index], + &ParentKey->SubKeys[Index + 1], + (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT)); + ParentKey->NumberOfSubKeys--; + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + + DPRINT("Dereference parent key: 0x%x\n", ParentKey); + + ObDereferenceObject(ParentKey); + return STATUS_SUCCESS; + } + } + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + + return STATUS_UNSUCCESSFUL; +} + + +PKEY_OBJECT +CmiScanKeyList(PKEY_OBJECT Parent, + PCHAR KeyName, + ULONG Attributes) +{ + PKEY_OBJECT CurKey; + KIRQL OldIrql; + WORD NameSize; + DWORD Index; + + DPRINT("Scanning key list for %s (Parent %s)\n", + KeyName, Parent->Name); + + NameSize = strlen(KeyName); + KeAcquireSpinLock(&CmiKeyListLock, &OldIrql); + /* FIXME: if list maintained in alphabetic order, use dichotomic search */ + for (Index=0; Index < Parent->NumberOfSubKeys; Index++) + { + CurKey = Parent->SubKeys[Index]; + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if ((NameSize == CurKey->NameSize) + && (_strnicmp(KeyName, CurKey->Name, NameSize) == 0)) + { + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + return CurKey; + } + } + else + { + if ((NameSize == CurKey->NameSize) + && (strncmp(KeyName,CurKey->Name,NameSize) == 0)) + { + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + return CurKey; + } + } + } + KeReleaseSpinLock(&CmiKeyListLock, OldIrql); + + return NULL; +} + + +static NTSTATUS +CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive, + PKEY_CELL KeyCell, + PUNICODE_STRING TargetPath) +{ + PVALUE_CELL ValueCell; + PDATA_CELL DataCell; + NTSTATUS Status; + + /* Get Value block of interest */ + Status = CmiScanKeyForValue(RegistryHive, + KeyCell, + "SymbolicLinkValue", + &ValueCell, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (ValueCell->DataType != REG_LINK) + { + DPRINT1("Type != REG_LINK\n!"); + return(STATUS_UNSUCCESSFUL); + } + + if (TargetPath->Buffer == NULL && TargetPath->MaximumLength == 0) + { + TargetPath->Length = 0; + TargetPath->MaximumLength = ValueCell->DataSize + sizeof(WCHAR); + TargetPath->Buffer = ExAllocatePool(NonPagedPool, + TargetPath->MaximumLength); + } + + TargetPath->Length = min(TargetPath->MaximumLength - sizeof(WCHAR), + ValueCell->DataSize); + + if (ValueCell->DataSize > 0) + { + DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL); + RtlCopyMemory(TargetPath->Buffer, + DataCell->Data, + TargetPath->Length); + TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0; + CmiReleaseBlock(RegistryHive, DataCell); + } + else + { + RtlCopyMemory(TargetPath->Buffer, + &ValueCell->DataOffset, + TargetPath->Length); + TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0; + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/cm/rtlfunc.c b/ntoskrnl/cm/rtlfunc.c new file mode 100644 index 0000000..4c68311 --- /dev/null +++ b/ntoskrnl/cm/rtlfunc.c @@ -0,0 +1,747 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cm/rtlfunc.c + * PURPOSE: Rtlxxx function for registry access + * UPDATE HISTORY: +*/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "cm.h" + +NTSTATUS STDCALL +RtlCheckRegistryKey(IN ULONG RelativeTo, + IN PWSTR Path) +{ + HANDLE KeyHandle; + NTSTATUS Status; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + FALSE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + NtClose(KeyHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCreateRegistryKey(IN ULONG RelativeTo, + IN PWSTR Path) +{ + HANDLE KeyHandle; + NTSTATUS Status; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + NtClose(KeyHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlDeleteRegistryValue(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ValueName) +{ + HANDLE KeyHandle; + NTSTATUS Status; + UNICODE_STRING Name; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + RtlInitUnicodeString(&Name, + ValueName); + + NtDeleteValueKey(KeyHandle, + &Name); + + NtClose(KeyHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, + OUT PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyPath = UNICODE_STRING_INITIALIZER(L"\\Registry\\User\\.Default"); + NTSTATUS Status; + + Status = RtlFormatCurrentUserKeyPath(&KeyPath); + if (NT_SUCCESS(Status)) + { + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(KeyHandle, + DesiredAccess, + &ObjectAttributes); + RtlFreeUnicodeString(&KeyPath); + if (NT_SUCCESS(Status)) + return(STATUS_SUCCESS); + } + + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(KeyHandle, + DesiredAccess, + &ObjectAttributes); + return(Status); +} + + +NTSTATUS STDCALL +RtlQueryRegistryValues(IN ULONG RelativeTo, + IN PWSTR Path, + IN PRTL_QUERY_REGISTRY_TABLE QueryTable, + IN PVOID Context, + IN PVOID Environment) +{ + NTSTATUS Status; + HANDLE BaseKeyHandle; + HANDLE CurrentKeyHandle; + PRTL_QUERY_REGISTRY_TABLE QueryEntry; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + PKEY_VALUE_FULL_INFORMATION FullValueInfo; + ULONG BufferSize; + ULONG ResultSize; + ULONG Index; + ULONG StringLen; + PWSTR StringPtr; + + DPRINT("RtlQueryRegistryValues() called\n"); + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + FALSE, + &BaseKeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status); + return(Status); + } + + CurrentKeyHandle = BaseKeyHandle; + QueryEntry = QueryTable; + while ((QueryEntry->QueryRoutine != NULL) || + (QueryEntry->Name != NULL)) + { +/* TODO: (from RobD) + + packet.sys has this code which calls this (and fails here) with: + + RtlZeroMemory(ParamTable, sizeof(ParamTable)); + // + // change to the linkage key + // + ParamTable[0].QueryRoutine = NULL; // NOTE: QueryRoutine is set to NULL + ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; + ParamTable[0].Name = L"Linkage"; + // + // Get the name of the mac driver we should bind to + // + ParamTable[1].QueryRoutine = PacketQueryRegistryRoutine; + ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND; + ParamTable[1].Name = L"Bind"; + ParamTable[1].EntryContext = (PVOID)MacDriverName; + ParamTable[1].DefaultType = REG_MULTI_SZ; + + Status = RtlQueryRegistryValues( + IN ULONG RelativeTo = RTL_REGISTRY_ABSOLUTE, + IN PWSTR Path = Path, + IN PRTL_QUERY_REGISTRY_TABLE QueryTable = ParamTable, + IN PVOID Context = NULL, + IN PVOID Environment = NULL); + + */ + //CSH: Was: + //if ((QueryEntry->QueryRoutine == NULL) && + // ((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT)) != 0)) + // Which is more correct? + if ((QueryEntry->QueryRoutine == NULL) && + ((QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) != 0)) + { + DPRINT("Bad parameters\n"); + Status = STATUS_INVALID_PARAMETER; + break; + } + + DPRINT("Name: %S\n", QueryEntry->Name); + + if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) && + (BaseKeyHandle != CurrentKeyHandle)) + { + NtClose(CurrentKeyHandle); + CurrentKeyHandle = BaseKeyHandle; + } + + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY) + { + DPRINT("Open new subkey: %S\n", QueryEntry->Name); + + RtlInitUnicodeString(&KeyName, + QueryEntry->Name); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + BaseKeyHandle, + NULL); + Status = NtOpenKey(&CurrentKeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + break; + } + else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT) + { + DPRINT("Query value directly: %S\n", QueryEntry->Name); + + RtlInitUnicodeString(&KeyName, + QueryEntry->Name); + + BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096; + ValueInfo = ExAllocatePool(PagedPool, BufferSize); + if (ValueInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + Status = ZwQueryValueKey(CurrentKeyHandle, + &KeyName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED) + { + ExFreePool(ValueInfo); + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto ByeBye; + } + + if (QueryEntry->DefaultType == REG_SZ) + { + PUNICODE_STRING ValueString; + PUNICODE_STRING SourceString; + + SourceString = (PUNICODE_STRING)QueryEntry->DefaultData; + ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; + if (ValueString->Buffer == 0) + { + ValueString->Length = SourceString->Length; + ValueString->MaximumLength = SourceString->MaximumLength; + ValueString->Buffer = ExAllocatePool(PagedPool, + ValueString->MaximumLength); + if (!ValueString->Buffer) + break; + ValueString->Buffer[0] = 0; + memcpy(ValueString->Buffer, + SourceString->Buffer, + SourceString->MaximumLength); + } + else + { + ValueString->Length = RtlMin(SourceString->Length, + ValueString->MaximumLength - sizeof(WCHAR)); + memcpy(ValueString->Buffer, + SourceString->Buffer, + ValueString->Length); + ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; + } + } + else + { + memcpy(QueryEntry->EntryContext, + QueryEntry->DefaultData, + QueryEntry->DefaultLength); + } + Status = STATUS_SUCCESS; + } + else + { + if (ValueInfo->Type == REG_SZ || + ValueInfo->Type == REG_MULTI_SZ || + ValueInfo->Type == REG_EXPAND_SZ) + { + PUNICODE_STRING ValueString; + + ValueString = (PUNICODE_STRING)QueryEntry->EntryContext; + if (ValueString->Buffer == 0) + { + RtlInitUnicodeString(ValueString, + NULL); + ValueString->MaximumLength = ValueInfo->DataLength + sizeof(WCHAR); //256 * sizeof(WCHAR); + ValueString->Buffer = ExAllocatePool(PagedPool, + ValueString->MaximumLength); + if (!ValueString->Buffer) + break; + ValueString->Buffer[0] = 0; + } + ValueString->Length = RtlMin(ValueInfo->DataLength, + ValueString->MaximumLength - sizeof(WCHAR)); + memcpy(ValueString->Buffer, + ValueInfo->Data, + ValueString->Length); + ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0; + } + else + { + memcpy(QueryEntry->EntryContext, + ValueInfo->Data, + ValueInfo->DataLength); + } + } + + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) + { + DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name); + + } + + ExFreePool(ValueInfo); + } + else + { + DPRINT("Query value via query routine: %S\n", QueryEntry->Name); + + if (QueryEntry->Name != NULL) + { + DPRINT("Callback\n"); + + RtlInitUnicodeString(&KeyName, + QueryEntry->Name); + + BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096; + ValueInfo = ExAllocatePool(PagedPool, + BufferSize); + if (ValueInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + Status = NtQueryValueKey(CurrentKeyHandle, + &KeyName, + KeyValuePartialInformation, + ValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + QueryEntry->DefaultType, + QueryEntry->DefaultData, + QueryEntry->DefaultLength, + Context, + QueryEntry->EntryContext); + } + else if ((ValueInfo->Type == REG_MULTI_SZ) && + !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + DPRINT("Expand REG_MULTI_SZ type\n"); + StringPtr = (PWSTR)ValueInfo->Data; + while (*StringPtr != 0) + { + StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR); + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + REG_SZ, + (PVOID)StringPtr, + StringLen, + Context, + QueryEntry->EntryContext); + if(!NT_SUCCESS(Status)) + break; + StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen); + } + } + else + { + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + ValueInfo->Type, + ValueInfo->Data, + ValueInfo->DataLength, + Context, + QueryEntry->EntryContext); + } + + if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE) + { + DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name); + + } + + ExFreePool(ValueInfo); + + if (!NT_SUCCESS(Status)) + break; + } + else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOVALUE) + { + DPRINT("Simple callback\n"); + Status = QueryEntry->QueryRoutine(NULL, + REG_NONE, + NULL, + 0, + Context, + QueryEntry->EntryContext); + if (!NT_SUCCESS(Status)) + break; + } + else + { + DPRINT("Enumerate values\n"); + + BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096; + FullValueInfo = ExAllocatePool(PagedPool, + BufferSize); + if (FullValueInfo == NULL) + { + Status = STATUS_NO_MEMORY; + break; + } + + Index = 0; + while (TRUE) + { + Status = NtEnumerateValueKey(CurrentKeyHandle, + Index, + KeyValueFullInformation, + FullValueInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + if ((Status == STATUS_NO_MORE_ENTRIES) && + (Index == 0) && + (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + else if (Status == STATUS_NO_MORE_ENTRIES) + { + Status = STATUS_SUCCESS; + } + break; + } + + if ((FullValueInfo->Type == REG_MULTI_SZ) && + !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND)) + { + DPRINT("Expand REG_MULTI_SZ type\n"); + StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset); + while (*StringPtr != 0) + { + StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR); + Status = QueryEntry->QueryRoutine(QueryEntry->Name, + REG_SZ, + (PVOID)StringPtr, + StringLen, + Context, + QueryEntry->EntryContext); + if(!NT_SUCCESS(Status)) + break; + StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen); + } + } + else + { + Status = QueryEntry->QueryRoutine(FullValueInfo->Name, + FullValueInfo->Type, + (PVOID)FullValueInfo + FullValueInfo->DataOffset, + FullValueInfo->DataLength, + Context, + QueryEntry->EntryContext); + } + + if (!NT_SUCCESS(Status)) + break; + + /* FIXME: How will these be deleted? */ + + Index++; + } + + ExFreePool(FullValueInfo); + + if (!NT_SUCCESS(Status)) + break; + } + } + + QueryEntry++; + } + +ByeBye: + + if (CurrentKeyHandle != BaseKeyHandle) + NtClose(CurrentKeyHandle); + + NtClose(BaseKeyHandle); + + return(Status); +} + + +NTSTATUS STDCALL +RtlWriteRegistryValue(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength) +{ + HANDLE KeyHandle; + NTSTATUS Status; + UNICODE_STRING Name; + + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + return(Status); + + RtlInitUnicodeString(&Name, + ValueName); + + NtSetValueKey(KeyHandle, + &Name, + 0, + ValueType, + ValueData, + ValueLength); + + NtClose(KeyHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath) +{ + /* FIXME: !!! */ + RtlCreateUnicodeString(KeyPath, + L"\\Registry\\User\\.Default"); + + return(STATUS_SUCCESS); +} + +/* ------------------------------------------ Private Implementation */ + + +NTSTATUS +RtlpGetRegistryHandle(ULONG RelativeTo, + PWSTR Path, + BOOLEAN Create, + PHANDLE KeyHandle) +{ + UNICODE_STRING KeyName; + WCHAR KeyBuffer[MAX_PATH]; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + if (RelativeTo & RTL_REGISTRY_HANDLE) + { + Status = NtDuplicateObject(PsGetCurrentProcessId(), + (HANDLE)Path, + PsGetCurrentProcessId(), + KeyHandle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS); + return(Status); + } + + if (RelativeTo & RTL_REGISTRY_OPTIONAL) + RelativeTo &= ~RTL_REGISTRY_OPTIONAL; + + if (RelativeTo >= RTL_REGISTRY_MAXIMUM) + return STATUS_INVALID_PARAMETER; + + KeyName.Length = 0; + KeyName.MaximumLength = MAX_PATH; + KeyName.Buffer = KeyBuffer; + KeyBuffer[0] = 0; + + switch (RelativeTo) + { + case RTL_REGISTRY_SERVICES: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + break; + + case RTL_REGISTRY_CONTROL: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\"); + break; + + case RTL_REGISTRY_WINDOWS_NT: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\"); + break; + + case RTL_REGISTRY_DEVICEMAP: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\Hardware\\DeviceMap\\"); + break; + + case RTL_REGISTRY_USER: + Status = RtlFormatCurrentUserKeyPath(&KeyName); + if (!NT_SUCCESS(Status)) + return(Status); + break; + + /* ReactOS specific */ + case RTL_REGISTRY_ENUM: + RtlAppendUnicodeToString(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + break; + } + + if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) + { + Path++; + } + RtlAppendUnicodeToString(&KeyName, + Path); + + DPRINT("KeyName '%wZ'\n", &KeyName); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + NULL, + NULL); + + if (Create == TRUE) + { + Status = NtCreateKey(KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + 0, + NULL); + } + else + { + Status = NtOpenKey(KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes); + } + + return(Status); +} + + +NTSTATUS +RtlpCreateRegistryKeyPath(PWSTR Path) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR KeyBuffer[MAX_PATH]; + UNICODE_STRING KeyName; + HANDLE KeyHandle; + NTSTATUS Status; + PWCHAR Current; + PWCHAR Next; + + if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0) + { + return(STATUS_INVALID_PARAMETER); + } + + wcsncpy(KeyBuffer, Path, MAX_PATH-1); + RtlInitUnicodeString(&KeyName, KeyBuffer); + + /* Skip \\Registry\\ */ + Current = KeyName.Buffer; + Current = wcschr(Current, '\\') + 1; + Current = wcschr(Current, '\\') + 1; + + do { + Next = wcschr(Current, '\\'); + if (Next == NULL) + { + /* The end */ + } + else + { + *Next = 0; + } + + InitializeObjectAttributes( + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + DPRINT("Create '%S'\n", KeyName.Buffer); + + Status = NtCreateKey( + &KeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + 0, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtCreateKey() failed with status %x\n", Status); + return Status; + } + + NtClose(KeyHandle); + + if (Next != NULL) + { + *Next = L'\\'; + } + + Current = Next + 1; + } while (Next != NULL); + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/ntoskrnl/dbg/.cvsignore b/ntoskrnl/dbg/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/dbg/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/dbg/dbgctrl.c b/ntoskrnl/dbg/dbgctrl.c new file mode 100644 index 0000000..6dbc5d2 --- /dev/null +++ b/ntoskrnl/dbg/dbgctrl.c @@ -0,0 +1,63 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/dbgctrl.c + * PURPOSE: System debug control + * PORTABILITY: Checked + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtSystemDebugControl(DEBUG_CONTROL_CODE ControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + PULONG ReturnLength) +{ + switch (ControlCode) { + case DebugGetTraceInformation: + case DebugSetInternalBreakpoint: + case DebugSetSpecialCalls: + case DebugClearSpecialCalls: + case DebugQuerySpecialCalls: + case DebugDbgBreakPoint: + break; +#ifdef KDBG + case DebugDbgLoadSymbols: + KdbLdrLoadUserModuleSymbols((PLDR_MODULE) InputBuffer); +#endif /* KDBG */ + break; + default: + break; + } + return STATUS_SUCCESS; +} diff --git a/ntoskrnl/dbg/errinfo.c b/ntoskrnl/dbg/errinfo.c new file mode 100644 index 0000000..1e1653f --- /dev/null +++ b/ntoskrnl/dbg/errinfo.c @@ -0,0 +1,281 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/errinfo.c + * PURPOSE: Print information descriptions of error messages + * PORTABILITY: Checked + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +/* GLOBALS *******************************************************************/ + +static PCHAR SeverityCodes[] = {"SUC", "INF", "ERR", "WRN"}; + +static struct _FACLIST +{ + ULONG Code; + PCHAR Name; +} FacList[] = +{ + {0, "KERNEL"}, + {0, NULL} +}; + +static struct _ERRLIST +{ + NTSTATUS Code; + PCHAR Name; + PCHAR Text; +} ErrList[] = +{ + {STATUS_SUCCESS, "SUCCESS", NULL}, + {STATUS_INSUFFICIENT_RESOURCES, "INSUFFICIENT_RESOURCES", NULL}, + {STATUS_OBJECT_NAME_EXISTS, "OBJECT_NAME_EXISTS", NULL}, + {STATUS_OBJECT_NAME_COLLISION, "OBJECT_NAME_COLLISION", NULL}, + {STATUS_CTL_FILE_NOT_SUPPORTED, "CTL_FILE_NOT_SUPPORTED", NULL}, + {STATUS_PORT_ALREADY_SET, "PORT_ALREADY_SET", NULL}, + {STATUS_SECTION_NOT_IMAGE, "SECTION_NOT_IMAGE", NULL}, + {STATUS_BAD_WORKING_SET_LIMIT, "BAD_WORKING_SET_LIMIT", NULL}, + {STATUS_INCOMPATIBLE_FILE_MAP, "INCOMPATIBLE_FILE_MAP", NULL}, + {STATUS_HANDLE_NOT_WAITABLE, "HANDLE_NOT_WAITABLE", NULL}, + {STATUS_PORT_DISCONNECTED, "PORT_DISCONNECTED", NULL}, + {STATUS_NOT_LOCKED, "NOT_LOCKED", NULL}, + {STATUS_NOT_MAPPED_VIEW, "NOT_MAPPED_VIEW", NULL}, + {STATUS_UNABLE_TO_FREE_VM, "UNABLE_TO_FREE_VM", NULL}, + {STATUS_UNABLE_TO_DELETE_SECTION, "UNABLE_TO_DELETE_SECTION", NULL}, + {STATUS_MORE_PROCESSING_REQUIRED, "MORE_PROCESSING_REQUIRED", NULL}, + {STATUS_INVALID_CID, "INVALID_CID", NULL}, + {STATUS_BAD_INITIAL_STACK, "BAD_INITIAL_STACK", NULL}, + {STATUS_INVALID_VOLUME_LABEL, "INVALID_VOLUME_LABEL", NULL}, + {STATUS_SECTION_NOT_EXTENDED, "SECTION_NOT_EXTENDED", NULL}, + {STATUS_NOT_MAPPED_DATA, "NOT_MAPPED_DATA", NULL}, + {STATUS_INFO_LENGTH_MISMATCH, "INFO_LENGTH_MISMATCH", NULL}, + {STATUS_INVALID_INFO_CLASS, "INVALID_INFO_CLASS", NULL}, + {STATUS_SUSPEND_COUNT_EXCEEDED, "SUSPEND_COUNT_EXCEEDED", NULL}, + {STATUS_NOTIFY_ENUM_DIR, "NOTIFY_ENUM_DIR", NULL}, + {STATUS_REGISTRY_RECOVERED, "REGISTRY_RECOVERED", NULL}, + {STATUS_REGISTRY_IO_FAILED, "REGISTRY_IO_FAILED", NULL}, + {STATUS_KEY_DELETED, "KEY_DELETED", NULL}, + {STATUS_NO_LOG_SPACE, "NO_LOG_SPACE", NULL}, + {STATUS_KEY_HAS_CHILDREN, "KEY_HAS_CHILDREN", NULL}, + {STATUS_CHILD_MUST_BE_VOLATILE, "CHILD_MUST_BE_VOLATILE", NULL}, + {STATUS_REGISTRY_CORRUPT, "REGISTRY_CORRUPT", NULL}, + {STATUS_DLL_NOT_FOUND, "DLL_NOT_FOUND", NULL}, + {STATUS_DLL_INIT_FAILED, "DLL_INIT_FAILED", NULL}, + {STATUS_ORDINAL_NOT_FOUND, "ORDINAL_NOT_FOUND", NULL}, + {STATUS_ENTRYPOINT_NOT_FOUND, "ENTRYPOINT_NOT_FOUND", NULL}, + {STATUS_MORE_ENTRIES, "MORE_ENTRIES", NULL}, + {STATUS_BUFFER_OVERFLOW, "BUFFER_OVERFLOW", NULL}, + {STATUS_NO_MORE_FILES, "NO_MORE_FILES", NULL}, + {STATUS_NO_INHERITANCE, "NO_INHERITANCE", NULL}, + {STATUS_NO_MORE_EAS, "NO_MORE_EAS", NULL}, + {STATUS_NO_MORE_ENTRIES, "NO_MORE_ENTRIES", NULL}, + {STATUS_GUIDS_EXHAUSTED, "GUIDS_EXHAUSTED", NULL}, + {STATUS_AGENTS_EXHAUSTED, "AGENTS_EXHAUSTED", NULL}, + {STATUS_UNSUCCESSFUL, "UNSUCCESSFUL", NULL}, + {STATUS_NOT_IMPLEMENTED, "NOT_IMPLEMENTED", NULL}, + {STATUS_ILLEGAL_FUNCTION, "ILLEGAL_FUNCTION", NULL}, + {STATUS_PAGEFILE_QUOTA, "PAGEFILE_QUOTA", NULL}, + {STATUS_COMMITMENT_LIMIT, "COMMITMENT_LIMIT", NULL}, + {STATUS_SECTION_TOO_BIG, "SECTION_TOO_BIG", NULL}, + {RPC_NT_SS_IN_NULL_CONTEXT, "RPC_NT_SS_IN_NULL_CONTEXT", NULL}, + {RPC_NT_INVALID_BINDING, "RPC_NT_INVALID_BINDING", NULL}, + {STATUS_OBJECT_FILE_MISMATCH, "OBJECT_FILE_MISMATCH", NULL}, + {STATUS_FILE_CLOSED, "FILE_CLOSED", NULL}, + {STATUS_INVALID_PORT_HANDLE, "INVALID_PORT_HANDLE", NULL}, + {STATUS_NOT_COMMITTED, "NOT_COMMITTED", NULL}, + {STATUS_INVALID_PARAMETER, "INVALID_PARAMETER", NULL}, + {STATUS_INVALID_PARAMETER_1, "INVALID_PARAMETER_1", NULL}, + {STATUS_INVALID_PARAMETER_2, "INVALID_PARAMETER_2", NULL}, + {STATUS_INVALID_PARAMETER_3, "INVALID_PARAMETER_3", NULL}, + {STATUS_INVALID_PARAMETER_4, "INVALID_PARAMETER_4", NULL}, + {STATUS_INVALID_PARAMETER_5, "INVALID_PARAMETER_5", NULL}, + {STATUS_INVALID_PARAMETER_6, "INVALID_PARAMETER_6", NULL}, + {STATUS_INVALID_PARAMETER_7, "INVALID_PARAMETER_7", NULL}, + {STATUS_INVALID_PARAMETER_8, "INVALID_PARAMETER_8", NULL}, + {STATUS_INVALID_PARAMETER_9, "INVALID_PARAMETER_9", NULL}, + {STATUS_INVALID_PARAMETER_10, "INVALID_PARAMETER_10", NULL}, + {STATUS_INVALID_PARAMETER_11, "INVALID_PARAMETER_11", NULL}, + {STATUS_INVALID_PARAMETER_12, "INVALID_PARAMETER_12", NULL}, + {STATUS_INVALID_PARAMETER_MAX, "INVALID_PARAMETER_MAX", NULL}, + {STATUS_INVALID_PAGE_PROTECTION, "INVALID_PAGE_PROTECTION", NULL}, + {STATUS_RESOURCE_DATA_NOT_FOUND, "RESOURCE_DATA_NOT_FOUND", NULL}, + {STATUS_RESOURCE_TYPE_NOT_FOUND, "RESOURCE_TYPE_NOT_FOUND", NULL}, + {STATUS_RESOURCE_NAME_NOT_FOUND, "RESOURCE_NAME_NOT_FOUND", NULL}, + {STATUS_RESOURCE_LANG_NOT_FOUND, "RESOURCE_LANG_NOT_FOUND", NULL}, + {STATUS_NO_SUCH_DEVICE, "NO_SUCH_DEVICE", NULL}, + {STATUS_NO_SUCH_FILE, "NO_SUCH_FILE", NULL}, + {STATUS_INVALID_DEVICE_REQUEST, "INVALID_DEVICE_REQUEST", NULL}, + {STATUS_END_OF_FILE, "END_OF_FILE", NULL}, + {STATUS_FILE_FORCED_CLOSED, "FILE_FORCED_CLOSED", NULL}, + {STATUS_WRONG_VOLUME, "WRONG_VOLUME", NULL}, + {STATUS_NO_MEDIA, "NO_MEDIA", NULL}, + {STATUS_NO_MEDIA_IN_DEVICE, "NO_MEDIA_IN_DEVICE", NULL}, + {STATUS_NONEXISTENT_SECTOR, "NONEXISTENT_SECTOR", NULL}, + {STATUS_WORKING_SET_QUOTA, "WORKING_SET_QUOTA", NULL}, + {STATUS_CONFLICTING_ADDRESS, "CONFLICTING_ADDRESS", NULL}, + {STATUS_INVALID_SYSTEM_SERVICE, "INVALID_SYSTEM_SERVICE", NULL}, + {STATUS_THREAD_IS_TERMINATING, "THREAD_IS_TERMINATING", NULL}, + {STATUS_PROCESS_IS_TERMINATING, "PROCESS_IS_TERMINATING", NULL}, + {STATUS_INVALID_LOCK_SEQUENCE, "INVALID_LOCK_SEQUENCE", NULL}, + {STATUS_INVALID_VIEW_SIZE, "INVALID_VIEW_SIZE", NULL}, + {STATUS_ALREADY_COMMITTED, "ALREADY_COMMITTED", NULL}, + {STATUS_ACCESS_DENIED, "ACCESS_DENIED", NULL}, + {STATUS_FILE_IS_A_DIRECTORY, "FILE_IS_A_DIRECTORY", NULL}, + {STATUS_CANNOT_DELETE, "CANNOT_DELETE", NULL}, + {STATUS_INVALID_COMPUTER_NAME, "INVALID_COMPUTER_NAME", NULL}, + {STATUS_FILE_DELETED, "FILE_DELETED", NULL}, + {STATUS_DELETE_PENDING, "DELETE_PENDING", NULL}, + {STATUS_PORT_CONNECTION_REFUSED, "PORT_CONNECTION_REFUSED", NULL}, + {STATUS_NO_SUCH_PRIVILEGE, "NO_SUCH_PRIVILEGE", NULL}, + {STATUS_PRIVILEGE_NOT_HELD, "PRIVILEGE_NOT_HELD", NULL}, + {STATUS_CANNOT_IMPERSONATE, "CANNOT_IMPERSONATE", NULL}, + {STATUS_LOGON_FAILURE, "LOGON_FAILURE", NULL}, + {STATUS_ACCOUNT_RESTRICTION, "ACCOUNT_RESTRICTION", NULL}, + {STATUS_INVALID_LOGON_HOURS, "INVALID_LOGON_HOURS", NULL}, + {STATUS_INVALID_WORKSTATION, "INVALID_WORKSTATION", NULL}, + {STATUS_BUFFER_TOO_SMALL, "BUFFER_TOO_SMALL", NULL}, + {STATUS_UNABLE_TO_DECOMMIT_VM, "UNABLE_TO_DECOMMIT_VM", NULL}, + {STATUS_DISK_CORRUPT_ERROR, "DISK_CORRUPT_ERROR", NULL}, + {STATUS_OBJECT_NAME_INVALID, "OBJECT_NAME_INVALID", NULL}, + {STATUS_OBJECT_NAME_NOT_FOUND, "OBJECT_NAME_NOT_FOUND", NULL}, + {STATUS_OBJECT_PATH_INVALID, "OBJECT_PATH_INVALID", NULL}, + {STATUS_OBJECT_PATH_NOT_FOUND, "OBJECT_PATH_NOT_FOUND", NULL}, + {STATUS_DFS_EXIT_PATH_FOUND, "DFS_EXIT_PATH_FOUND", NULL}, + {STATUS_PATH_SYNTAX_BAD, "PATH_SYNTAX_BAD", NULL}, + {STATUS_DATA_OVERRUN, "DATA_OVERRUN", NULL}, + {STATUS_DATA_LATE_ERROR, "DATA_LATE_ERROR", NULL}, + {STATUS_DATA_ERROR, "DATA_ERROR", NULL}, + {STATUS_CRC_ERROR, "CRC_ERROR", NULL}, + {STATUS_SHARING_VIOLATION, "SHARING_VIOLATION", NULL}, + {STATUS_QUOTA_EXCEEDED, "QUOTA_EXCEEDED", NULL}, + {STATUS_MUTANT_NOT_OWNED, "MUTANT_NOT_OWNED", NULL}, + {STATUS_SEMAPHORE_LIMIT_EXCEEDED, "SEMAPHORE_LIMIT_EXCEEDED", NULL}, + {STATUS_DISK_FULL, "DISK_FULL", NULL}, + {STATUS_LOCK_NOT_GRANTED, "LOCK_NOT_GRANTED", NULL}, + {STATUS_DEVICE_NOT_READY, "DEVICE_NOT_READY", NULL}, + {STATUS_IO_TIMEOUT, "IO_TIMEOUT", NULL}, + {STATUS_MEDIA_WRITE_PROTECTED, "MEDIA_WRITE_PROTECTED", NULL}, + {STATUS_NO_MEDIA_IN_DRIVE, "NO_MEDIA_IN_DRIVE", NULL}, + {STATUS_VERIFY_REQUIRED, "VERIFY_REQUIRED", NULL}, + {STATUS_UNRECOGNIZED_MEDIA, "UNRECOGNIZED_MEDIA", NULL}, + {STATUS_UNRECOGNIZED_VOLUME, "UNRECOGNIZED_VOLUME", NULL}, + {STATUS_FS_DRIVER_REQUIRED, "FS_DRIVER_REQUIRED", NULL}, + {STATUS_NOT_SUPPORTED, "NOT_SUPPORTED", NULL}, + {STATUS_DISK_OPERATION_FAILED, "DISK_OPERATION_FAILED", NULL}, + {STATUS_FS_QUERY_REQUIRED, "FS_QUERY_REQUIRED", NULL}, + {0, NULL, NULL} +}; + +/* FUNCTIONS *****************************************************************/ + +VOID +DbgGetErrorText(NTSTATUS ErrorCode, PUNICODE_STRING ErrorText, ULONG Flags) +{ + int i; + char TempBuf[255], NumBuf[32]; + ANSI_STRING AnsiString; + + TempBuf[0] = '\0'; + if (Flags & DBG_GET_SHOW_FACILITY) + { + if (NT_CUSTOMER(ErrorCode)) + { + sprintf(TempBuf, + "%%CUST-%s-", + SeverityCodes[NT_SEVERITY(ErrorCode)]); + } + else + { + for (i = 0; FacList[i].Name != NULL; i++) + { + if (FacList[i].Code == NT_FACILITY(ErrorCode)) + { + break; + } + } + if (FacList[i].Name != NULL) + { + sprintf(TempBuf, "%%%s-%s-", + FacList[i].Name, + SeverityCodes[NT_SEVERITY(ErrorCode)]); + } + else + { + sprintf(TempBuf, "%%UNKNOWN-%s-", + SeverityCodes[NT_SEVERITY(ErrorCode)]); + } + } + } + for (i = 0; ErrList[i].Name != NULL; i++) + { + if (ErrorCode == ErrList[i].Code) + { + break; + } + } + if (ErrList[i].Name != NULL) + { + if (Flags & DBG_GET_SHOW_FACILITY) + { + strcat(TempBuf, ErrList[i].Name); + strcat(TempBuf, " "); + } + if (ErrList[i].Text != NULL) + { + strcat(TempBuf, ErrList[i].Text); + } + else + { + strcat(TempBuf, ErrList[i].Name); + } + } + else + { + if (Flags & DBG_GET_SHOW_FACILITY) + { + sprintf(NumBuf, "%08lx", ErrorCode); + strcat(TempBuf, NumBuf); + strcat(TempBuf, " "); + } + sprintf(NumBuf, "Unknown Message #%08lx", ErrorCode); + strcat(TempBuf, NumBuf); + } + RtlInitAnsiString(&AnsiString, TempBuf); + RtlAnsiStringToUnicodeString(ErrorText, &AnsiString, TRUE); +} + +VOID +DbgPrintErrorMessage(NTSTATUS ErrorCode) +{ + UNICODE_STRING ErrorText; + + DbgGetErrorText(ErrorCode, &ErrorText, 0xf); + DbgPrint("%wZ\n", &ErrorText); + RtlFreeUnicodeString(&ErrorText); +} + + diff --git a/ntoskrnl/dbg/i386/.cvsignore b/ntoskrnl/dbg/i386/.cvsignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/ntoskrnl/dbg/i386/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/ntoskrnl/dbg/i386/kdb_help.S b/ntoskrnl/dbg/i386/kdb_help.S new file mode 100644 index 0000000..9eee6a3 --- /dev/null +++ b/ntoskrnl/dbg/i386/kdb_help.S @@ -0,0 +1,89 @@ +#include +#include + +.globl _KdbEnter +_KdbEnter: + /* + * Set up a stack frame + */ + pushl %ebp + movl %esp, %ebp + + /* + * Save registers + */ + pushl %edi + pushl %esi + pushl %ebx + + /* + * Set up a trap frame + */ + pushl $0 /* V86_Gs */ + pushl $0 /* V86_Fs */ + pushl $0 /* V86_Ds */ + pushl $0 /* V86_Es */ + pushl %ss /* Ss */ + pushl %ebp /* Esp */ + pushfl /* Eflags */ + pushl %cs /* Cs */ + pushl 4(%ebp) /* Eip */ + pushl $0 /* ErrorCode */ + pushl 0(%ebp) /* Ebp */ + pushl %ebx /* Ebx */ + pushl %esi /* Esi */ + pushl %edi /* Edi */ + pushl %fs /* Fs */ + pushl $0 /* ExceptionList */ + pushl $0 /* PreviousMode */ + pushl %eax /* Eax */ + pushl %ecx /* Ecx */ + pushl %edx /* Edx */ + pushl %ds /* Ds */ + pushl %es /* Es */ + pushl %gs /* Gs */ + pushl $0 /* Dr7 */ + pushl $0 /* Dr6 */ + pushl $0 /* Dr3 */ + pushl $0 /* Dr2 */ + pushl $0 /* Dr1 */ + pushl $0 /* Dr0 */ + pushl $0 /* TempEip */ + pushl $0 /* TempCs */ + pushl $0 /* DebugPointer */ + pushl $0 /* DebugArgMark */ + pushl $0 /* DebugEip */ + pushl $0 /* DebugEbp */ + + /* + * Push a pointer to the trap frame + */ + pushl %esp + + /* + * Call KDB + */ + call _KdbInternalEnter + + /* + * Pop the argument and destroy the trap frame + */ + popl %eax + addl $KTRAP_FRAME_SIZE, %esp + + /* + * Restore registers + */ + popl %ebx + popl %esi + popl %edi + + /* + * Return + */ + popl %ebp + ret + + + + diff --git a/ntoskrnl/dbg/kdb.c b/ntoskrnl/dbg/kdb.c new file mode 100644 index 0000000..c70eed3 --- /dev/null +++ b/ntoskrnl/dbg/kdb.c @@ -0,0 +1,689 @@ +/* + * ReactOS kernel + * Copyright (C) 2001 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/kdb.c + * PURPOSE: Kernel debugger + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 01/03/01 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "kdb.h" + +#define NDEBUG +#include + +/* TYPES *********************************************************************/ + +/* GLOBALS *******************************************************************/ + +ULONG +DbgContCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgDRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgCRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgBugCheckCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgBackTraceCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgProcessListCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgProcessHelpCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgShowFilesCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgEnableFileCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +ULONG +DbgDisableFileCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); + +struct +{ + PCH Name; + PCH Syntax; + PCH Help; + ULONG (*Fn)(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf); +} DebuggerCommands[] = { + {"cont", "cont", "Exit the debugger", DbgContCommand}, + {"regs", "regs", "Display general purpose registers", DbgRegsCommand}, + {"dregs", "dregs", "Display debug registers", DbgDRegsCommand}, + {"cregs", "cregs", "Display control registers", DbgCRegsCommand}, + {"bugcheck", "bugcheck", "Bugcheck the system", DbgBugCheckCommand}, + {"bt", "bt [*frame-address]|[thread-id]","Do a backtrace", DbgBackTraceCommand}, + {"plist", "plist", "Display processes in the system", DbgProcessListCommand}, + {"sfiles", "sfiles", "Show files that print debug prints", DbgShowFilesCommand}, + {"efile", "efile ", "Enable debug prints from file", DbgEnableFileCommand}, + {"dfile", "dfile ", "Disable debug prints from file", DbgDisableFileCommand}, + {"help", "help", "Display help screen", DbgProcessHelpCommand}, + {NULL, NULL, NULL} +}; + +/* FUNCTIONS *****************************************************************/ + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = ULONG_MAX; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return acc; +} + + +char* +strpbrk(const char* s, const char* accept) +{ + int i; + for (; (*s) != 0; s++) + { + for (i = 0; accept[i] != 0; i++) + { + if (accept[i] == (*s)) + { + return((char *)s); + } + } + } + return(NULL); +} + +VOID +KdbGetCommand(PCH Buffer) +{ + CHAR Key; + + for (;;) + { + while ((Key = KdbTryGetCharKeyboard()) == -1); + + if (Key == '\r' || Key == '\n') + { + DbgPrint("\n"); + *Buffer = 0; + return; + } + + DbgPrint("%c", Key); + + *Buffer = Key; + Buffer++; + } +} + +ULONG +DbgProcessHelpCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + ULONG i, j, len; + + DbgPrint("Kernel debugger commands:\n"); + for (i = 0; DebuggerCommands[i].Name != NULL; i++) + { + DbgPrint(" %s", DebuggerCommands[i].Syntax); + len = strlen(DebuggerCommands[i].Syntax); + if (len < 35) + { + for (j = 0; j < 35 - len; j++) + { + DbgPrint(" "); + } + } + DbgPrint(" - %s\n", DebuggerCommands[i].Help); + } + return(1); +} + +ULONG +DbgProcessListCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + extern LIST_ENTRY PsProcessListHead; + PLIST_ENTRY current_entry; + PEPROCESS current; + ULONG i = 1; + + if (PsProcessListHead.Flink == NULL) + { + DbgPrint("No processes.\n"); + return(1); + } + + DbgPrint("Process list: "); + current_entry = PsProcessListHead.Flink; + while (current_entry != &PsProcessListHead) + { + current = CONTAINING_RECORD(current_entry, EPROCESS, ProcessListEntry); + DbgPrint("%d %.8s", current->UniqueProcessId, + current->ImageFileName); + i++; + if ((i % 4) == 0) + { + DbgPrint("\n"); + } + current_entry = current_entry->Flink; + } + return(1); +} + +VOID +DbgPrintBackTrace(PULONG Frame, ULONG StackBase, ULONG StackLimit) +{ + ULONG i = 1; + + DbgPrint("Frames: "); + while (Frame != NULL && (ULONG)Frame >= StackLimit && + (ULONG)Frame < StackBase) + { +#if 0 + DbgPrint("%.8x ", Frame[1]); +#else + KdbPrintAddress((PVOID)Frame[1]); +#endif + Frame = (PULONG)Frame[0]; + i++; + } + + if ((i % 10) != 0) + { + DbgPrint("\n"); + } +} + +ULONG +DbgBackTraceCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + ULONG StackBase, StackLimit; + extern unsigned int init_stack, init_stack_top; + + /* Without an argument we print the current stack. */ + if (Argc == 1) + { + if (PsGetCurrentThread() != NULL) + { + StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackBase; + StackLimit = PsGetCurrentThread()->Tcb.StackLimit; + } + else + { + StackBase = (ULONG)&init_stack_top; + StackLimit = (ULONG)&init_stack; + } + DbgPrintBackTrace((PULONG)Tf->Ebp, StackBase, StackLimit); + } + /* + * If there are two arguments and the second begins with a asterik treat it + * as the address of a frame to start printing the back trace from. + */ + else if (Argc == 2 && Argv[1][0] == '*') + { + PULONG Frame; + Frame = (PULONG)strtoul(&Argv[1][1], NULL, 0); + DbgPrintBackTrace(Frame, ULONG_MAX, 0); + } + /* + * Otherwise treat the argument as the id of a thread whose back trace is to + * be printed. + */ + else + { + } + return(1); +} + +VOID +DbgPrintCr0(ULONG Cr0) +{ + ULONG i; + + DbgPrint("CR0:"); + if (Cr0 & (1 << 0)) + { + DbgPrint(" PE"); + } + if (Cr0 & (1 << 1)) + { + DbgPrint(" MP"); + } + if (Cr0 & (1 << 2)) + { + DbgPrint(" EM"); + } + if (Cr0 & (1 << 3)) + { + DbgPrint(" TS"); + } + if (!(Cr0 & (1 << 4))) + { + DbgPrint(" !BIT5"); + } + if (Cr0 & (1 << 5)) + { + DbgPrint(" NE"); + } + for (i = 6; i < 16; i++) + { + if (Cr0 & (1 << i)) + { + DbgPrint(" BIT%d", i); + } + } + if (Cr0 & (1 << 16)) + { + DbgPrint(" WP"); + } + if (Cr0 & (1 << 17)) + { + DbgPrint(" BIT17"); + } + if (Cr0 & (1 << 18)) + { + DbgPrint(" AM"); + } + for (i = 19; i < 29; i++) + { + if (Cr0 & (1 << i)) + { + DbgPrint(" BIT%d", i); + } + } + if (Cr0 & (1 << 29)) + { + DbgPrint(" NW"); + } + if (Cr0 & (1 << 30)) + { + DbgPrint(" CD"); + } + if (Cr0 & (1 << 31)) + { + DbgPrint(" PG"); + } + DbgPrint("\n"); +} + +ULONG +DbgCRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + ULONG Cr0, Cr1, Cr2, Cr3, Cr4; + ULONG Ldtr; + USHORT Tr; + + __asm__ __volatile__ ("movl %%cr0, %0\n\t" : "=d" (Cr0)); + /* __asm__ __volatile__ ("movl %%cr1, %0\n\t" : "=d" (Cr1)); */ + Cr1 = 0; + __asm__ __volatile__ ("movl %%cr2, %0\n\t" : "=d" (Cr2)); + __asm__ __volatile__ ("movl %%cr3, %0\n\t" : "=d" (Cr3)); + __asm__ __volatile__ ("movl %%cr4, %0\n\t" : "=d" (Cr4)); + __asm__ __volatile__ ("str %0\n\t" : "=d" (Tr)); + __asm__ __volatile__ ("sldt %0\n\t" : "=d" (Ldtr)); + DbgPrintCr0(Cr0); + DbgPrint("CR1 %.8x CR2 %.8x CR3 %.8x CR4 %.8x TR %.8x LDTR %.8x\n", + Cr1, Cr2, Cr3, Cr4, (ULONG)Tf, Ldtr); + return(1); +} + +ULONG +DbgDRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + DbgPrint("DR0 %.8x DR1 %.8x DR2 %.8x DR3 %.8x DR6 %.8x DR7 %.8x\n", + Tf->Dr0, Tf->Dr1, Tf->Dr2, Tf->Dr3, Tf->Dr6, Tf->Dr7); + return(1); +} + +ULONG +DbgContCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + /* Not too difficult. */ + return(0); +} + +VOID +DbgPrintEflags(ULONG Eflags) +{ + DbgPrint("EFLAGS:"); + if (Eflags & (1 << 0)) + { + DbgPrint(" CF"); + } + if (!(Eflags & (1 << 1))) + { + DbgPrint(" !BIT1"); + } + if (Eflags & (1 << 2)) + { + DbgPrint(" PF"); + } + if (Eflags & (1 << 3)) + { + DbgPrint(" BIT3"); + } + if (Eflags & (1 << 4)) + { + DbgPrint(" AF"); + } + if (Eflags & (1 << 5)) + { + DbgPrint(" BIT5"); + } + if (Eflags & (1 << 6)) + { + DbgPrint(" ZF"); + } + if (Eflags & (1 << 7)) + { + DbgPrint(" SF"); + } + if (Eflags & (1 << 8)) + { + DbgPrint(" TF"); + } + if (Eflags & (1 << 9)) + { + DbgPrint(" IF"); + } + if (Eflags & (1 << 10)) + { + DbgPrint(" DF"); + } + if (Eflags & (1 << 11)) + { + DbgPrint(" OF"); + } + if ((Eflags & ((1 << 12) | (1 << 13))) == 0) + { + DbgPrint(" IOPL0"); + } + else if ((Eflags & ((1 << 12) | (1 << 13))) == 1) + { + DbgPrint(" IOPL1"); + } + else if ((Eflags & ((1 << 12) | (1 << 13))) == 2) + { + DbgPrint(" IOPL2"); + } + else if ((Eflags & ((1 << 12) | (1 << 13))) == 3) + { + DbgPrint(" IOPL3"); + } + if (Eflags & (1 << 14)) + { + DbgPrint(" NT"); + } + if (Eflags & (1 << 15)) + { + DbgPrint(" BIT15"); + } + if (Eflags & (1 << 16)) + { + DbgPrint(" RF"); + } + if (Eflags & (1 << 17)) + { + DbgPrint(" VF"); + } + if (Eflags & (1 << 18)) + { + DbgPrint(" AC"); + } + if (Eflags & (1 << 19)) + { + DbgPrint(" VIF"); + } + if (Eflags & (1 << 20)) + { + DbgPrint(" VIP"); + } + if (Eflags & (1 << 21)) + { + DbgPrint(" ID"); + } + if (Eflags & (1 << 22)) + { + DbgPrint(" BIT22"); + } + if (Eflags & (1 << 23)) + { + DbgPrint(" BIT23"); + } + if (Eflags & (1 << 24)) + { + DbgPrint(" BIT24"); + } + if (Eflags & (1 << 25)) + { + DbgPrint(" BIT25"); + } + if (Eflags & (1 << 26)) + { + DbgPrint(" BIT26"); + } + if (Eflags & (1 << 27)) + { + DbgPrint(" BIT27"); + } + if (Eflags & (1 << 28)) + { + DbgPrint(" BIT28"); + } + if (Eflags & (1 << 29)) + { + DbgPrint(" BIT29"); + } + if (Eflags & (1 << 30)) + { + DbgPrint(" BIT30"); + } + if (Eflags & (1 << 31)) + { + DbgPrint(" BIT31"); + } + DbgPrint("\n"); +} + +ULONG +DbgRegsCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + DbgPrint("CS:EIP %.4x:%.8x, EAX %.8x EBX %.8x ECX %.8x EDX %.8x\n", + Tf->Cs & 0xFFFF, Tf->Eip, Tf->Eax, Tf->Ebx, Tf->Ecx, Tf->Edx); + DbgPrint("ESI %.8x EDI %.8x EBP %.8x SS:ESP %.4x:%.8x\n", + Tf->Esi, Tf->Edi, Tf->Ebp, Tf->Ss & 0xFFFF, Tf->Esp); + DbgPrintEflags(Tf->Eflags); + return(1); +} + +ULONG +DbgBugCheckCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + KeBugCheck(1); + return(1); +} + +ULONG +DbgShowFilesCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + DbgShowFiles(); + return(1); +} + +ULONG +DbgEnableFileCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + if (Argc == 2) + { + if (strlen(Argv[1]) > 0) + { + DbgEnableFile(Argv[1]); + } + } + return(1); +} + +ULONG +DbgDisableFileCommand(ULONG Argc, PCH Argv[], PKTRAP_FRAME Tf) +{ + if (Argc == 2) + { + if (strlen(Argv[1]) > 0) + { + DbgDisableFile(Argv[1]); + } + } + return(1); +} + +ULONG +KdbDoCommand(PCH CommandLine, PKTRAP_FRAME Tf) +{ + ULONG i; + PCH s1; + PCH s; + static PCH Argv[256]; + ULONG Argc; + static CHAR OrigCommand[256]; + + strcpy(OrigCommand, CommandLine); + + Argc = 0; + s = CommandLine; + while ((s1 = strpbrk(s, "\t ")) != NULL) + { + Argv[Argc] = s; + *s1 = 0; + s = s1 + 1; + Argc++; + } + Argv[Argc] = s; + Argc++; + + for (i = 0; DebuggerCommands[i].Name != NULL; i++) + { + if (strcmp(DebuggerCommands[i].Name, Argv[0]) == 0) + { + return(DebuggerCommands[i].Fn(Argc, Argv, Tf)); + } + } + DbgPrint("Command '%s' is unknown.", OrigCommand); + return(1); +} + +VOID +KdbMainLoop(PKTRAP_FRAME Tf) +{ + CHAR Command[256]; + ULONG s; + + DbgPrint("\nEntered kernel debugger (type \"help\" for a list of commands)\n"); + do + { + DbgPrint("\nkdb:> "); + + KdbGetCommand(Command); + + s = KdbDoCommand(Command, Tf); + } while (s != 0); +} + +VOID +KdbInternalEnter(PKTRAP_FRAME Tf) +{ + __asm__ __volatile__ ("cli\n\t"); + (VOID)KdbMainLoop(Tf); + __asm__ __volatile__("sti\n\t"); +} + +KD_CONTINUE_TYPE +KdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME TrapFrame) +{ + DbgPrint("Entered debugger on exception number %d.\n", + TrapFrame->DebugArgMark); + KdbInternalEnter(TrapFrame); + return(kdHandleException); +} diff --git a/ntoskrnl/dbg/kdb.h b/ntoskrnl/dbg/kdb.h new file mode 100644 index 0000000..570759e --- /dev/null +++ b/ntoskrnl/dbg/kdb.h @@ -0,0 +1,12 @@ +ULONG +KdbTryGetCharKeyboard(VOID); +VOID +KdbEnter(VOID); +VOID +DbgRDebugInit(VOID); +VOID +DbgShowFiles(VOID); +VOID +DbgEnableFile(PCH Filename); +VOID +DbgDisableFile(PCH Filename); diff --git a/ntoskrnl/dbg/kdb_keyboard.c b/ntoskrnl/dbg/kdb_keyboard.c new file mode 100644 index 0000000..087dc4a --- /dev/null +++ b/ntoskrnl/dbg/kdb_keyboard.c @@ -0,0 +1,354 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/kdb_keyboard.c + * PURPOSE: Keyboard driver + * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com) + * Jason Filby (jasonfilby@yahoo.com) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +#if 1 + +#define KBD_STATUS_REG 0x64 +#define KBD_CNTL_REG 0x64 +#define KBD_DATA_REG 0x60 + +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ + +#define kbd_read_input() READ_PORT_UCHAR((PUCHAR)KBD_DATA_REG) +#define kbd_read_status() READ_PORT_UCHAR((PUCHAR)KBD_STATUS_REG) + +static unsigned char keyb_layout[2][128] = +{ + "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */ + "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */ + "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */ + "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/" /* 0x60 - 0x6f */ + , + "\000\033!@#$%^&*()_+\177\t" /* 0x00 - 0x0f */ + "QWERTYUIOP{}\r\000AS" /* 0x10 - 0x1f */ + "DFGHJKL:\"`\000\\ZXCV" /* 0x20 - 0x2f */ + "BNM<>?\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */ + "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ + "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ + "\r\000/" /* 0x60 - 0x6f */ +}; + +typedef BYTE byte_t; + +CHAR +KdbTryGetCharKeyboard() +{ + static byte_t last_key = 0; + static byte_t shift = 0; + char c; + while(1) { + unsigned char status = kbd_read_status(); + while (status & KBD_STAT_OBF) { + byte_t scancode; + scancode = kbd_read_input(); + /* check for SHIFT-keys */ + if (((scancode & 0x7F) == 42) || ((scancode & 0x7F) == 54)) + { + shift = !(scancode & 0x80); + continue; + } + /* ignore all other RELEASED-codes */ + if (scancode & 0x80) + last_key = 0; + else if (last_key != scancode) + { + //printf("kbd: %d, %d, %c\n", scancode, last_key, keyb_layout[shift][scancode]); + last_key = scancode; + c = keyb_layout[shift][scancode]; + if (c > 0) return c; + } + } + } +} + +#endif + +#if 0 + +/* GLOBALS *******************************************************************/ + +/* + * Keyboard I/O ports. + */ +#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ +#define K_STATUS 0x64 /* keybd status (read-only) */ +#define K_CMD 0x64 /* keybd ctlr command (write-only) */ + +/* + * Bit definitions for K_STATUS port. + */ +#define K_OBUF_FUL 0x01 /* output (from keybd) buffer full */ +#define K_IBUF_FUL 0x02 /* input (to keybd) buffer full */ +#define K_SYSFLAG 0x04 /* "System Flag" */ +#define K_CMD_DATA 0x08 /* 1 = input buf has cmd, 0 = data */ +#define K_KBD_INHIBIT 0x10 /* 0 if keyboard inhibited */ +#define K_AUX_OBUF_FUL 0x20 /* 1 = obuf holds aux device data */ +#define K_TIMEOUT 0x40 /* timout error flag */ +#define K_PARITY_ERROR 0x80 /* parity error flag */ + +/* + * Keyboard controller commands (sent to K_CMD port). + */ +#define KC_CMD_READ 0x20 /* read controller command byte */ +#define KC_CMD_WRITE 0x60 /* write controller command byte */ +#define KC_CMD_DIS_AUX 0xa7 /* disable auxiliary device */ +#define KC_CMD_ENB_AUX 0xa8 /* enable auxiliary device */ +#define KC_CMD_TEST_AUX 0xa9 /* test auxiliary device interface */ +#define KC_CMD_SELFTEST 0xaa /* keyboard controller self-test */ +#define KC_CMD_TEST 0xab /* test keyboard interface */ +#define KC_CMD_DUMP 0xac /* diagnostic dump */ +#define KC_CMD_DISABLE 0xad /* disable keyboard */ +#define KC_CMD_ENABLE 0xae /* enable keyboard */ +#define KC_CMD_RDKBD 0xc4 /* read keyboard ID */ +#define KC_CMD_WIN 0xd0 /* read output port */ +#define KC_CMD_WOUT 0xd1 /* write output port */ +#define KC_CMD_ECHO 0xee /* used for diagnostic testing */ +#define KC_CMD_PULSE 0xff /* pulse bits 3-0 based on low nybble */ + +/* + * Keyboard commands (send to K_RDWR). + */ +#define K_CMD_LEDS 0xed /* set status LEDs (caps lock, etc.) */ +#define K_CMD_TYPEMATIC 0xf3 /* set key repeat and delay */ + +/* + * Bit definitions for controller command byte (sent following + * KC_CMD_WRITE command). + * + * Bits 0x02 and 0x80 unused, always set to 0. + */ +#define K_CB_ENBLIRQ 0x01 /* enable data-ready intrpt */ +#define K_CB_SETSYSF 0x04 /* Set System Flag */ +#define K_CB_INHBOVR 0x08 /* Inhibit Override */ +#define K_CB_DISBLE 0x10 /* disable keyboard */ +#define K_CB_IGNPARITY 0x20 /* ignore parity from keyboard */ +#define K_CB_SCAN 0x40 /* standard scan conversion */ + +/* + * Bit definitions for "Indicator Status Byte" (sent after a + * K_CMD_LEDS command). If the bit is on, the LED is on. Undefined + * bit positions must be 0. + */ +#define K_LED_SCRLLK 0x1 /* scroll lock */ +#define K_LED_NUMLK 0x2 /* num lock */ +#define K_LED_CAPSLK 0x4 /* caps lock */ + +/* + * Bit definitions for "Miscellaneous port B" (K_PORTB). + */ +/* read/write */ +#define K_ENABLETMR2 0x01 /* enable output from timer 2 */ +#define K_SPKRDATA 0x02 /* direct input to speaker */ +#define K_ENABLEPRTB 0x04 /* "enable" port B */ +#define K_EIOPRTB 0x08 /* enable NMI on parity error */ +/* read-only */ +#define K_REFRESHB 0x10 /* refresh flag from INLTCONT PAL */ +#define K_OUT2B 0x20 /* timer 2 output */ +#define K_ICKB 0x40 /* I/O channel check (parity error) */ + +/* + * Bit definitions for the keyboard controller's output port. + */ +#define KO_SYSRESET 0x01 /* processor reset */ +#define KO_GATE20 0x02 /* A20 address line enable */ +#define KO_AUX_DATA_OUT 0x04 /* output data to auxiliary device */ +#define KO_AUX_CLOCK 0x08 /* auxiliary device clock */ +#define KO_OBUF_FUL 0x10 /* keyboard output buffer full */ +#define KO_AUX_OBUF_FUL 0x20 /* aux device output buffer full */ +#define KO_CLOCK 0x40 /* keyboard clock */ +#define KO_DATA_OUT 0x80 /* output data to keyboard */ + +/* + * Keyboard return codes. + */ +#define K_RET_RESET_DONE 0xaa /* BAT complete */ +#define K_RET_ECHO 0xee /* echo after echo command */ +#define K_RET_ACK 0xfa /* ack */ +#define K_RET_RESET_FAIL 0xfc /* BAT error */ +#define K_RET_RESEND 0xfe /* resend request */ + +#define SHIFT -1 +#define CTRL -2 +#define META -3 + +static char keymap[128][2] = { + {0}, /* 0 */ + {27, 27}, /* 1 - ESC */ + {'1', '!'}, /* 2 */ + {'2', '@'}, + {'3', '#'}, + {'4', '$'}, + {'5', '%'}, + {'6', '^'}, + {'7', '&'}, + {'8', '*'}, + {'9', '('}, + {'0', ')'}, + {'-', '_'}, + {'=', '+'}, + {8, 8}, /* 14 - Backspace */ + {'\t', '\t'}, /* 15 */ + {'q', 'Q'}, + {'w', 'W'}, + {'e', 'E'}, + {'r', 'R'}, + {'t', 'T'}, + {'y', 'Y'}, + {'u', 'U'}, + {'i', 'I'}, + {'o', 'O'}, + {'p', 'P'}, + {'[', '{'}, + {']', '}'}, /* 27 */ + {'\r', '\r'}, /* 28 - Enter */ + {CTRL, CTRL}, /* 29 - Ctrl */ + {'a', 'A'}, /* 30 */ + {'s', 'S'}, + {'d', 'D'}, + {'f', 'F'}, + {'g', 'G'}, + {'h', 'H'}, + {'j', 'J'}, + {'k', 'K'}, + {'l', 'L'}, + {';', ':'}, + {'\'', '"'}, /* 40 */ + {'`', '~'}, /* 41 */ + {SHIFT, SHIFT}, /* 42 - Left Shift */ + {'\\', '|'}, /* 43 */ + {'z', 'Z'}, /* 44 */ + {'x', 'X'}, + {'c', 'C'}, + {'v', 'V'}, + {'b', 'B'}, + {'n', 'N'}, + {'m', 'M'}, + {',', '<'}, + {'.', '>'}, + {'/', '?'}, /* 53 */ + {SHIFT, SHIFT}, /* 54 - Right Shift */ + {0, 0}, /* 55 - Print Screen */ + {META, META}, /* 56 - Alt */ + {' ', ' '}, /* 57 - Space bar */ + {0, 0}, /* 58 - Caps Lock */ + {0, 0}, /* 59 - F1 */ + {0, 0}, /* 60 - F2 */ + {0, 0}, /* 61 - F3 */ + {0, 0}, /* 62 - F4 */ + {0, 0}, /* 63 - F5 */ + {0, 0}, /* 64 - F6 */ + {0, 0}, /* 65 - F7 */ + {0, 0}, /* 66 - F8 */ + {0, 0}, /* 67 - F9 */ + {0, 0}, /* 68 - F10 */ + {0, 0}, /* 69 - Num Lock */ + {0, 0}, /* 70 - Scroll Lock */ + {'7', '7'}, /* 71 - Numeric keypad 7 */ + {'8', '8'}, /* 72 - Numeric keypad 8 */ + {'9', '9'}, /* 73 - Numeric keypad 9 */ + {'-', '-'}, /* 74 - Numeric keypad '-' */ + {'4', '4'}, /* 75 - Numeric keypad 4 */ + {'5', '5'}, /* 76 - Numeric keypad 5 */ + {'6', '6'}, /* 77 - Numeric keypad 6 */ + {'+', '+'}, /* 78 - Numeric keypad '+' */ + {'1', '1'}, /* 79 - Numeric keypad 1 */ + {'2', '2'}, /* 80 - Numeric keypad 2 */ + {'3', '3'}, /* 81 - Numeric keypad 3 */ + {'0', '0'}, /* 82 - Numeric keypad 0 */ + {'.', '.'}, /* 83 - Numeric keypad '.' */ +}; + +/* FUNCTIONS *****************************************************************/ + +/* + * Quick poll for a pending input character. + * Returns a character if available, -1 otherwise. This routine can return + * false negatives in the following cases: + * + * - a valid character is in transit from the keyboard when called + * - a key release is received (from a previous key press) + * - a SHIFT key press is received (shift state is recorded however) + * - a key press for a multi-character sequence is received + * + * Yes, this is horrible. + */ +ULONG +KdbTryGetCharKeyboard(VOID) +{ + static unsigned shift_state, ctrl_state, meta_state; + unsigned scan_code, ch; + + /* See if a scan code is ready, returning if none. */ + if ((READ_PORT_UCHAR((PUCHAR)K_STATUS) & K_OBUF_FUL) == 0) { + return -1; + } + scan_code = READ_PORT_UCHAR((PUCHAR)K_RDWR); + + /* Handle key releases - only release of SHIFT is important. */ + if (scan_code & 0x80) { + scan_code &= 0x7f; + if (keymap[scan_code][0] == SHIFT) + shift_state = 0; + else if (keymap[scan_code][0] == CTRL) + ctrl_state = 0; + else if (keymap[scan_code][0] == META) + meta_state = 0; + ch = -1; + } else { + /* Translate the character through the keymap. */ + ch = keymap[scan_code][shift_state] | meta_state; + if (ch == SHIFT) { + shift_state = 1; + ch = -1; + } else if (ch == CTRL) { + ctrl_state = 1; + ch = -1; + } else if (ch == META) { + meta_state = 0200; + ch = -1; + } else if (ch == 0) + ch = -1; + else if (ctrl_state) + ch = (keymap[scan_code][1] - '@') | meta_state; + } + + return ch; +} + +#endif diff --git a/ntoskrnl/dbg/kdb_stabs.c b/ntoskrnl/dbg/kdb_stabs.c new file mode 100644 index 0000000..88b5bab --- /dev/null +++ b/ntoskrnl/dbg/kdb_stabs.c @@ -0,0 +1,885 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/exp.c + * PURPOSE: Handling exceptions + * PROGRAMMER: David Welch (welch@cwcom.net) + * REVISION HISTORY: + * ??/??/??: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +typedef struct _SYMBOLFILE_HEADER { + unsigned long StabsOffset; + unsigned long StabsLength; + unsigned long StabstrOffset; + unsigned long StabstrLength; +} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; + +typedef struct _IMAGE_SYMBOL_INFO_CACHE { + LIST_ENTRY ListEntry; + UNICODE_STRING FullName; + PVOID FileBuffer; + PVOID SymbolsBase; + ULONG SymbolsLength; + PVOID SymbolStringsBase; + ULONG SymbolStringsLength; +} IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE; + + +typedef struct _STAB_ENTRY { + unsigned long n_strx; /* index into string table of name */ + unsigned char n_type; /* type of symbol */ + unsigned char n_other; /* misc info (usually empty) */ + unsigned short n_desc; /* description field */ + unsigned long n_value; /* value of symbol */ +} _STAB_ENTRY, *PSTAB_ENTRY; + +/* + * Desc - Line number + * Value - Relative virtual address + */ +#define N_FUN 0x24 + +/* + * Desc - Line number + * Value - Relative virtual address + */ +#define N_SLINE 0x44 + +/* + * String - First containing a '/' is the compillation directory (CD) + * Not containing a '/' is a source file relative to CD + */ +#define N_SO 0x64 + +static LIST_ENTRY SymbolListHead; +static KSPIN_LOCK SymbolListLock; + +NTSTATUS +LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo, + IN ULONG_PTR RelativeAddress, + OUT PULONG LineNumber, + OUT PCH FileName OPTIONAL, + OUT PCH FunctionName OPTIONAL); + +VOID +KdbLdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo); + +/* FUNCTIONS ****************************************************************/ + +BOOLEAN +KdbPrintUserAddress(PVOID address) +{ + PLIST_ENTRY current_entry; + PLDR_MODULE current; + PEPROCESS CurrentProcess; + PPEB Peb = NULL; + ULONG_PTR RelativeAddress; + NTSTATUS Status; + ULONG LineNumber; + CHAR FileName[256]; + CHAR FunctionName[256]; + + CurrentProcess = PsGetCurrentProcess(); + if (NULL != CurrentProcess) + { + Peb = CurrentProcess->Peb; + } + + if (NULL == Peb) + { + DbgPrint("<%x>", address); + return(TRUE); + } + + current_entry = Peb->Ldr->InLoadOrderModuleList.Flink; + + while (current_entry != &Peb->Ldr->InLoadOrderModuleList && + current_entry != NULL) + { + current = + CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList); + + if (address >= (PVOID)current->BaseAddress && + address < (PVOID)(current->BaseAddress + current->SizeOfImage)) + { + RelativeAddress = (ULONG_PTR) address - (ULONG_PTR)current->BaseAddress; + Status = LdrGetAddressInformation(¤t->SymbolInfo, + RelativeAddress, + &LineNumber, + FileName, + FunctionName); + if (NT_SUCCESS(Status)) + { + DbgPrint("<%wZ: %x (%s:%d (%s))>", + ¤t->BaseDllName, RelativeAddress, FileName, LineNumber, FunctionName); + } + else + { + DbgPrint("<%wZ: %x>", ¤t->BaseDllName, RelativeAddress); + } + return(TRUE); + } + + current_entry = current_entry->Flink; + } + return(FALSE); +} + +BOOLEAN +KdbPrintAddress(PVOID address) +{ + PLIST_ENTRY current_entry; + MODULE_TEXT_SECTION* current; + extern LIST_ENTRY ModuleTextListHead; + ULONG_PTR RelativeAddress; + NTSTATUS Status; + ULONG LineNumber; + CHAR FileName[256]; + CHAR FunctionName[256]; + + current_entry = ModuleTextListHead.Flink; + + while (current_entry != &ModuleTextListHead && + current_entry != NULL) + { + current = + CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry); + + if (address >= (PVOID)current->Base && + address < (PVOID)(current->Base + current->Length)) + { + RelativeAddress = (ULONG_PTR) address - current->Base; + Status = LdrGetAddressInformation(¤t->SymbolInfo, + RelativeAddress, + &LineNumber, + FileName, + FunctionName); + if (NT_SUCCESS(Status)) + { + DbgPrint("<%ws: %x (%s:%d (%s))>", + current->Name, RelativeAddress, FileName, LineNumber, FunctionName); + } + else + { + DbgPrint("<%ws: %x>", current->Name, RelativeAddress); + } + return(TRUE); + } + current_entry = current_entry->Flink; + } + return(FALSE); +} + +VOID +KdbFreeSymbolsProcess(PPEB Peb) +{ + PLIST_ENTRY CurrentEntry; + PLDR_MODULE Current; + PIMAGE_SYMBOL_INFO SymbolInfo; + + assert (Peb); + assert (Peb->Ldr); + + CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink; + while (CurrentEntry != &Peb->Ldr->InLoadOrderModuleList && + CurrentEntry != NULL) + { + Current = CONTAINING_RECORD(CurrentEntry, LDR_MODULE, + InLoadOrderModuleList); + + SymbolInfo = &Current->SymbolInfo; + KdbLdrUnloadModuleSymbols(SymbolInfo); + + CurrentEntry = CurrentEntry->Flink; + } +} + +VOID +KdbLdrInit(MODULE_TEXT_SECTION* NtoskrnlTextSection, + MODULE_TEXT_SECTION* LdrHalTextSection) +{ + RtlZeroMemory(&NtoskrnlTextSection->SymbolInfo, + sizeof(NtoskrnlTextSection->SymbolInfo)); + NtoskrnlTextSection->SymbolInfo.ImageBase = + NtoskrnlTextSection->OptionalHeader->ImageBase; + NtoskrnlTextSection->SymbolInfo.ImageSize = NtoskrnlTextSection->Length; + + RtlZeroMemory(&LdrHalTextSection->SymbolInfo, + sizeof(LdrHalTextSection->SymbolInfo)); + LdrHalTextSection->SymbolInfo.ImageBase = + LdrHalTextSection->OptionalHeader->ImageBase; + LdrHalTextSection->SymbolInfo.ImageSize = LdrHalTextSection->Length; + + InitializeListHead(&SymbolListHead); + KeInitializeSpinLock(&SymbolListLock); +} + +VOID +LdrpParseImageSymbols(PIMAGE_SYMBOL_INFO SymbolInfo) +/* Note: It is important that the symbol strings buffer not be released after + this function is called because the strings are still referenced */ +{ + PSYMBOL CurrentFileNameSymbol; + PSYMBOL CurrentFunctionSymbol; + PSYMBOL CurrentLineNumberSymbol; + PSYMBOL Symbol; + PSTAB_ENTRY StabEntry; + PVOID StabsEnd; + PCHAR String; + ULONG_PTR FunRelativeAddress; + ULONG FunLineNumber; + ULONG_PTR ImageBase; + + assert(SymbolInfo); + + DPRINT("Parsing symbols.\n"); + + SymbolInfo->FileNameSymbols.SymbolCount = 0; + SymbolInfo->FileNameSymbols.Symbols = NULL; + SymbolInfo->FunctionSymbols.SymbolCount = 0; + SymbolInfo->FunctionSymbols.Symbols = NULL; + SymbolInfo->LineNumberSymbols.SymbolCount = 0; + SymbolInfo->LineNumberSymbols.Symbols = NULL; + StabsEnd = SymbolInfo->SymbolsBase + SymbolInfo->SymbolsLength; + StabEntry = (PSTAB_ENTRY) SymbolInfo->SymbolsBase; + ImageBase = SymbolInfo->ImageBase; + FunRelativeAddress = 0; + FunLineNumber = 0; + CurrentFileNameSymbol = NULL; + CurrentFunctionSymbol = NULL; + CurrentLineNumberSymbol = NULL; + while ((ULONG_PTR) StabEntry < (ULONG_PTR) StabsEnd) + { + Symbol = NULL; + + if (StabEntry->n_type == N_FUN) + { + if (StabEntry->n_desc > 0) + { + assert(StabEntry->n_value >= ImageBase); + + FunRelativeAddress = StabEntry->n_value - ImageBase; + FunLineNumber = StabEntry->n_desc; + + Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL)); + assert(Symbol); + Symbol->Next = NULL; + Symbol->SymbolType = ST_FUNCTION; + Symbol->RelativeAddress = FunRelativeAddress; + Symbol->LineNumber = FunLineNumber; + String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx; + RtlInitAnsiString(&Symbol->Name, String); + + DPRINT("FUN found. '%s' %d @ %x\n", + Symbol->Name.Buffer, FunLineNumber, FunRelativeAddress); + } + } + else if (StabEntry->n_type == N_SLINE) + { + Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL)); + assert(Symbol); + Symbol->Next = NULL; + Symbol->SymbolType = ST_LINENUMBER; + Symbol->RelativeAddress = FunRelativeAddress + StabEntry->n_value; + Symbol->LineNumber = StabEntry->n_desc; + + DPRINT("SLINE found. %d @ %x\n", + Symbol->LineNumber, Symbol->RelativeAddress); + } + else if (StabEntry->n_type == N_SO) + { + Symbol = ExAllocatePool(NonPagedPool, sizeof(SYMBOL)); + assert(Symbol); + Symbol->Next = NULL; + Symbol->SymbolType = ST_FILENAME; + Symbol->RelativeAddress = StabEntry->n_value - ImageBase; + Symbol->LineNumber = 0; + String = (PCHAR)SymbolInfo->SymbolStringsBase + StabEntry->n_strx; + RtlInitAnsiString(&Symbol->Name, String); + + DPRINT("SO found. '%s' @ %x\n", + Symbol->Name.Buffer, Symbol->RelativeAddress); + } + + if (Symbol != NULL) + { + switch (Symbol->SymbolType) + { + case ST_FILENAME: + if (SymbolInfo->FileNameSymbols.Symbols == NULL) + SymbolInfo->FileNameSymbols.Symbols = Symbol; + else + CurrentFileNameSymbol->Next = Symbol; + + CurrentFileNameSymbol = Symbol; + + SymbolInfo->FileNameSymbols.SymbolCount++; + break; + case ST_FUNCTION: + if (SymbolInfo->FunctionSymbols.Symbols == NULL) + SymbolInfo->FunctionSymbols.Symbols = Symbol; + else + CurrentFunctionSymbol->Next = Symbol; + + CurrentFunctionSymbol = Symbol; + + SymbolInfo->FunctionSymbols.SymbolCount++; + break; + case ST_LINENUMBER: + if (SymbolInfo->LineNumberSymbols.Symbols == NULL) + SymbolInfo->LineNumberSymbols.Symbols = Symbol; + else + CurrentLineNumberSymbol->Next = Symbol; + + CurrentLineNumberSymbol = Symbol; + + SymbolInfo->LineNumberSymbols.SymbolCount++; + break; + } + } + + StabEntry++; + } +} + +static NTSTATUS +LdrpGetFileName(IN PIMAGE_SYMBOL_INFO SymbolInfo, + IN ULONG_PTR RelativeAddress, + OUT PCH FileName) +{ + PSYMBOL NextSymbol; + ULONG_PTR NextAddress; + PSYMBOL Symbol; + + Symbol = SymbolInfo->FileNameSymbols.Symbols; + while (Symbol != NULL) + { + NextSymbol = Symbol->Next; + if (NextSymbol != NULL) + NextAddress = NextSymbol->RelativeAddress; + else + NextAddress = SymbolInfo->ImageSize; + + DPRINT("FN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n", + Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress); + + if ((Symbol->SymbolType == ST_FILENAME) && + (RelativeAddress >= Symbol->RelativeAddress) && + (RelativeAddress < NextAddress)) + { + DPRINT("FN found\n"); + strcpy(FileName, Symbol->Name.Buffer); + return STATUS_SUCCESS; + } + Symbol = NextSymbol; + } + + DPRINT("FN not found\n"); + + return STATUS_UNSUCCESSFUL; +} + +static NTSTATUS +LdrpGetFunctionName(IN PIMAGE_SYMBOL_INFO SymbolInfo, + IN ULONG_PTR RelativeAddress, + OUT PCH FunctionName) +{ + PSYMBOL NextSymbol; + ULONG_PTR NextAddress; + PSYMBOL Symbol; + + Symbol = SymbolInfo->FunctionSymbols.Symbols; + while (Symbol != NULL) + { + NextSymbol = Symbol->Next; + if (NextSymbol != NULL) + NextAddress = NextSymbol->RelativeAddress; + else + NextAddress = SymbolInfo->ImageSize; + + DPRINT("FUN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n", + Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress); + + if ((Symbol->SymbolType == ST_FUNCTION) && + (RelativeAddress >= Symbol->RelativeAddress) && + (RelativeAddress < NextAddress)) + { + PCHAR ExtraInfo; + ULONG Length; + + DPRINT("FUN found\n"); + + /* Remove the extra information from the function name */ + ExtraInfo = strchr(Symbol->Name.Buffer, ':'); + if (ExtraInfo != NULL) + Length = ExtraInfo - Symbol->Name.Buffer; + else + Length = strlen(Symbol->Name.Buffer); + + strncpy(FunctionName, Symbol->Name.Buffer, Length); + return STATUS_SUCCESS; + } + Symbol = NextSymbol; + } + + DPRINT("FUN not found\n"); + + return STATUS_UNSUCCESSFUL; +} + +static NTSTATUS +LdrpGetLineNumber(IN PIMAGE_SYMBOL_INFO SymbolInfo, + IN ULONG_PTR RelativeAddress, + OUT PULONG LineNumber) +{ + PSYMBOL NextSymbol; + ULONG_PTR NextAddress; + PSYMBOL Symbol; + + Symbol = SymbolInfo->LineNumberSymbols.Symbols; + while (Symbol != NULL) + { + NextSymbol = Symbol->Next; + if (NextSymbol != NULL) + NextAddress = NextSymbol->RelativeAddress; + else + NextAddress = SymbolInfo->ImageSize; + + DPRINT("LN SEARCH: Type %d RelativeAddress %x >= Symbol->RelativeAddress %x < NextAddress %x\n", + Symbol->SymbolType, RelativeAddress, Symbol->RelativeAddress, NextAddress); + + if ((Symbol->SymbolType == ST_LINENUMBER) && + (RelativeAddress >= Symbol->RelativeAddress) && + (RelativeAddress < NextAddress)) + { + DPRINT("LN found\n"); + *LineNumber = Symbol->LineNumber; + return STATUS_SUCCESS; + } + Symbol = NextSymbol; + } + + DPRINT("LN not found\n"); + + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS +LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo, + IN ULONG_PTR RelativeAddress, + OUT PULONG LineNumber, + OUT PCH FileName OPTIONAL, + OUT PCH FunctionName OPTIONAL) +{ + NTSTATUS Status; + + *LineNumber = 0; + + DPRINT("RelativeAddress %p\n", RelativeAddress); + + if (RelativeAddress >= SymbolInfo->ImageSize) + { + DPRINT("Address is not within .text section. RelativeAddress %p Length 0x%x\n", + RelativeAddress, SymbolInfo->ImageSize); + return STATUS_UNSUCCESSFUL; + } + + if (!AreSymbolsParsed(SymbolInfo)) + { + LdrpParseImageSymbols(SymbolInfo); + } + + Status = LdrpGetLineNumber(SymbolInfo, RelativeAddress, LineNumber); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + if (FileName) + { + Status = LdrpGetFileName(SymbolInfo, RelativeAddress, FileName); + if (!NT_SUCCESS(Status)) + { + strcpy(FileName, ""); + } + } + + if (FunctionName) + { + Status = LdrpGetFunctionName(SymbolInfo, RelativeAddress, FunctionName); + if (!NT_SUCCESS(Status)) + { + strcpy(FunctionName, ""); + } + } + + return STATUS_SUCCESS; +} + +VOID +LdrpLoadModuleSymbols(PUNICODE_STRING FileName, + PIMAGE_SYMBOL_INFO SymbolInfo) +{ + FILE_STANDARD_INFORMATION FileStdInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR TmpFileName[MAX_PATH]; + UNICODE_STRING SymFileName; + LPWSTR Start, Ext; + HANDLE FileHandle; + PVOID FileBuffer; + NTSTATUS Status; + ULONG Length; + IO_STATUS_BLOCK IoStatusBlock; + PSYMBOLFILE_HEADER SymbolFileHeader; + + /* Get the path to the symbol store */ + wcscpy(TmpFileName, L"\\SystemRoot\\symbols\\"); + + /* Get the symbol filename from the module name */ + Start = wcsrchr(FileName->Buffer, L'\\'); + if (Start == NULL) + Start = FileName->Buffer; + else + Start++; + + Ext = wcsrchr(FileName->Buffer, L'.'); + if (Ext != NULL) + Length = Ext - Start; + else + Length = wcslen(Start); + + wcsncat(TmpFileName, Start, Length); + wcscat(TmpFileName, L".sym"); + RtlInitUnicodeString(&SymFileName, TmpFileName); + + /* Open the file */ + InitializeObjectAttributes(&ObjectAttributes, + &SymFileName, + 0, + NULL, + NULL); + + Status = ZwOpenFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not open symbol file: %wZ\n", &SymFileName); + return; + } + + CPRINT("Loading symbols from %wZ...\n", &SymFileName); + + /* Get the size of the file */ + Status = ZwQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileStdInfo, + sizeof(FileStdInfo), + FileStandardInformation); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not get file size\n"); + ZwClose(FileHandle); + return; + } + + /* Allocate nonpageable memory for symbol file */ + FileBuffer = ExAllocatePool(NonPagedPool, + FileStdInfo.EndOfFile.u.LowPart); + + if (FileBuffer == NULL) + { + DPRINT("Could not allocate memory for symbol file\n"); + ZwClose(FileHandle); + return; + } + + /* Load file into memory chunk */ + Status = ZwReadFile(FileHandle, + 0, 0, 0, + &IoStatusBlock, + FileBuffer, + FileStdInfo.EndOfFile.u.LowPart, + 0, 0); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not read symbol file into memory (Status 0x%x)\n", Status); + ExFreePool(FileBuffer); + ZwClose(FileHandle); + return; + } + + ZwClose(FileHandle); + + SymbolFileHeader = (PSYMBOLFILE_HEADER) FileBuffer; + SymbolInfo->FileBuffer = FileBuffer; + SymbolInfo->SymbolsBase = FileBuffer + SymbolFileHeader->StabsOffset; + SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength; + SymbolInfo->SymbolStringsBase = FileBuffer + SymbolFileHeader->StabstrOffset; + SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength; +} + +VOID +KdbLdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo) +{ + PSYMBOL NextSymbol; + PSYMBOL Symbol; + + DPRINT("Unloading symbols\n"); + + if (SymbolInfo != NULL) + { + Symbol = SymbolInfo->FileNameSymbols.Symbols; + while (Symbol != NULL) + { + NextSymbol = Symbol->Next; + RtlFreeAnsiString(&Symbol->Name); + ExFreePool(Symbol); + Symbol = NextSymbol; + } + + SymbolInfo->FileNameSymbols.SymbolCount = 0; + SymbolInfo->FileNameSymbols.Symbols = NULL; + + Symbol = SymbolInfo->FunctionSymbols.Symbols; + while (Symbol != NULL) + { + NextSymbol = Symbol->Next; + RtlFreeAnsiString(&Symbol->Name); + ExFreePool(Symbol); + Symbol = NextSymbol; + } + + SymbolInfo->FunctionSymbols.SymbolCount = 0; + SymbolInfo->FunctionSymbols.Symbols = NULL; + + Symbol = SymbolInfo->LineNumberSymbols.Symbols; + while (Symbol != NULL) + { + NextSymbol = Symbol->Next; + RtlFreeAnsiString(&Symbol->Name); + ExFreePool(Symbol); + Symbol = NextSymbol; + } + + SymbolInfo->LineNumberSymbols.SymbolCount = 0; + SymbolInfo->LineNumberSymbols.Symbols = NULL; +#if 0 + /* Don't free buffers because we cache symbol buffers + (eg. they are shared across processes) */ + /* FIXME: We can free them if we do reference counting */ + if (SymbolInfo->FileBuffer != NULL) + { + ExFreePool(SymbolInfo->FileBuffer); + SymbolInfo->FileBuffer = NULL; + SymbolInfo->SymbolsBase = NULL; + SymbolInfo->SymbolsLength = 0; + } +#endif + } +} + + +PIMAGE_SYMBOL_INFO_CACHE +LdrpLookupUserSymbolInfo(PLDR_MODULE LdrModule) +{ + PIMAGE_SYMBOL_INFO_CACHE Current; + PLIST_ENTRY CurrentEntry; + KIRQL Irql; + + DPRINT("Searching symbols for %S\n", LdrModule->FullDllName.Buffer); + + KeAcquireSpinLock(&SymbolListLock, &Irql); + + CurrentEntry = SymbolListHead.Flink; + while (CurrentEntry != (&SymbolListHead)) + { + Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry); + + if (RtlEqualUnicodeString(&Current->FullName, &LdrModule->FullDllName, TRUE)) + { + KeReleaseSpinLock(&SymbolListLock, Irql); + return Current; + } + + CurrentEntry = CurrentEntry->Flink; + } + + KeReleaseSpinLock(&SymbolListLock, Irql); + + return(NULL); +} + +VOID +KdbLdrLoadUserModuleSymbols(PLDR_MODULE LdrModule) +{ + PIMAGE_SYMBOL_INFO_CACHE CacheEntry; + + DPRINT("LdrModule %p\n", LdrModule); + + RtlZeroMemory(&LdrModule->SymbolInfo, sizeof(LdrModule->SymbolInfo)); + LdrModule->SymbolInfo.ImageBase = (ULONG_PTR) LdrModule->BaseAddress; + LdrModule->SymbolInfo.ImageSize = LdrModule->SizeOfImage; + + CacheEntry = LdrpLookupUserSymbolInfo(LdrModule); + if (CacheEntry != NULL) + { + DPRINT("Symbol cache hit for %S\n", CacheEntry->FullName.Buffer); + + LdrModule->SymbolInfo.FileBuffer = CacheEntry->FileBuffer; + LdrModule->SymbolInfo.SymbolsBase = CacheEntry->SymbolsBase; + LdrModule->SymbolInfo.SymbolsLength = CacheEntry->SymbolsLength; + LdrModule->SymbolInfo.SymbolStringsBase = CacheEntry->SymbolStringsBase; + LdrModule->SymbolInfo.SymbolStringsLength = CacheEntry->SymbolStringsLength; + } + else + { + CacheEntry = ExAllocatePool(NonPagedPool, sizeof(IMAGE_SYMBOL_INFO_CACHE)); + assert(CacheEntry); + RtlZeroMemory(CacheEntry, sizeof(IMAGE_SYMBOL_INFO_CACHE)); + + RtlCreateUnicodeString(&CacheEntry->FullName, LdrModule->FullDllName.Buffer); + assert(CacheEntry->FullName.Buffer); + LdrpLoadModuleSymbols(&LdrModule->FullDllName, &LdrModule->SymbolInfo); + InsertTailList(&SymbolListHead, &CacheEntry->ListEntry); + } +} + +VOID +KdbLoadDriver(PUNICODE_STRING Filename, PMODULE_OBJECT Module) +{ + /* Load symbols for the image if available */ + LdrpLoadModuleSymbols(Filename, &Module->TextSection->SymbolInfo); +} + +VOID +KdbUnloadDriver(PMODULE_OBJECT ModuleObject) +{ + /* Unload symbols for module if available */ + KdbLdrUnloadModuleSymbols(&ModuleObject->TextSection->SymbolInfo); +} + +VOID +KdbProcessSymbolFile(PVOID ModuleLoadBase, PCHAR FileName, ULONG Length) +{ + PMODULE_OBJECT ModuleObject; + UNICODE_STRING ModuleName; + CHAR TmpBaseName[MAX_PATH]; + CHAR TmpFileName[MAX_PATH]; + PSYMBOLFILE_HEADER SymbolFileHeader; + PIMAGE_SYMBOL_INFO SymbolInfo; + ANSI_STRING AnsiString; + + DPRINT("Module %s is a symbol file\n", FileName); + + strncpy(TmpBaseName, FileName, Length); + TmpBaseName[Length] = '\0'; + + DPRINT("base: %s (Length %d)\n", TmpBaseName, Length); + + strcpy(TmpFileName, TmpBaseName); + strcat(TmpFileName, ".sys"); + RtlInitAnsiString(&AnsiString, TmpFileName); + + RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE); + ModuleObject = LdrGetModuleObject(&ModuleName); + RtlFreeUnicodeString(&ModuleName); + if (ModuleObject == NULL) + { + strcpy(TmpFileName, TmpBaseName); + strcat(TmpFileName, ".exe"); + RtlInitAnsiString(&AnsiString, TmpFileName); + RtlAnsiStringToUnicodeString(&ModuleName, &AnsiString, TRUE); + ModuleObject = LdrGetModuleObject(&ModuleName); + RtlFreeUnicodeString(&ModuleName); + } + if (ModuleObject != NULL) + { + SymbolInfo = (PIMAGE_SYMBOL_INFO) &ModuleObject->TextSection->SymbolInfo; + SymbolFileHeader = (PSYMBOLFILE_HEADER) ModuleLoadBase; + SymbolInfo->FileBuffer = ModuleLoadBase; + SymbolInfo->SymbolsBase = ModuleLoadBase + SymbolFileHeader->StabsOffset; + SymbolInfo->SymbolsLength = SymbolFileHeader->StabsLength; + SymbolInfo->SymbolStringsBase = ModuleLoadBase + SymbolFileHeader->StabstrOffset; + SymbolInfo->SymbolStringsLength = SymbolFileHeader->StabstrLength; + } +} + +VOID +KdbInitializeDriver(PMODULE_TEXT_SECTION ModuleTextSection) +{ + RtlZeroMemory(&ModuleTextSection->SymbolInfo, sizeof(ModuleTextSection->SymbolInfo)); + ModuleTextSection->SymbolInfo.ImageBase = + ModuleTextSection->OptionalHeader->ImageBase; + ModuleTextSection->SymbolInfo.ImageSize = ModuleTextSection->Length; +} + +VOID +KdbLdrLoadAutoConfigDrivers(VOID) +{ + UNICODE_STRING ModuleName; + PMODULE_OBJECT ModuleObject; + + /* + * Load symbols for ntoskrnl.exe and hal.dll because \SystemRoot + * is created after their module entries + */ + + RtlInitUnicodeStringFromLiteral(&ModuleName, KERNEL_MODULE_NAME); + ModuleObject = LdrGetModuleObject(&ModuleName); + if (ModuleObject != NULL) + { + LdrpLoadModuleSymbols(&ModuleName, + &ModuleObject->TextSection->SymbolInfo); + } + + RtlInitUnicodeStringFromLiteral(&ModuleName, HAL_MODULE_NAME); + ModuleObject = LdrGetModuleObject(&ModuleName); + if (ModuleObject != NULL) + { + LdrpLoadModuleSymbols(&ModuleName, + &ModuleObject->TextSection->SymbolInfo); + } +} diff --git a/ntoskrnl/dbg/print.c b/ntoskrnl/dbg/print.c new file mode 100644 index 0000000..f0c755d --- /dev/null +++ b/ntoskrnl/dbg/print.c @@ -0,0 +1,98 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/print.c + * PURPOSE: Debug output + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * PORTABILITY: Unchecked + * UPDATE HISTORY: + * 14/10/99: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + + +/* FUNCTIONS ****************************************************************/ + +#if 0 +ULONG DbgService (ULONG Service, PVOID Context1, PVOID Context2); +__asm__ ("\n\t.global _DbgService\n\t" + "_DbgService:\n\t" + "mov 4(%esp), %eax\n\t" + "mov 8(%esp), %ecx\n\t" + "mov 12(%esp), %edx\n\t" + "int $0x2D\n\t" + "ret\n\t"); +#endif + +/* + * Note: DON'T CHANGE THIS FUNCTION!!! + * DON'T CALL HalDisplayString OR SOMETING ELSE!!! + * You'll only break the serial/bochs debugging feature!!! + */ + +ULONG +DbgPrint(PCH Format, ...) +{ + ANSI_STRING DebugString; + CHAR Buffer[1024]; + va_list ap; + + /* init ansi string */ + DebugString.Buffer = Buffer; + DebugString.MaximumLength = sizeof(Buffer); + + va_start (ap, Format); + DebugString.Length = _vsnprintf (Buffer, sizeof( Buffer ), Format, ap); + va_end (ap); + + KdpPrintString (&DebugString); + + return (ULONG)DebugString.Length; +} + + +VOID STDCALL +DbgPrompt (PCH OutputString, + PCH InputString, + USHORT InputSize) +{ + ANSI_STRING Output; + ANSI_STRING Input; + + Input.Length = 0; + Input.MaximumLength = InputSize; + Input.Buffer = InputString; + + Output.Length = strlen (OutputString); + Output.MaximumLength = Output.Length + 1; + Output.Buffer = OutputString; + + /* FIXME: Not implemented yet! */ + // KdpPromptString (&Output, + // &Input); +} + +/* EOF */ diff --git a/ntoskrnl/dbg/rdebug.c b/ntoskrnl/dbg/rdebug.c new file mode 100644 index 0000000..b360ff2 --- /dev/null +++ b/ntoskrnl/dbg/rdebug.c @@ -0,0 +1,154 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/rdebug.c + * PURPOSE: Runtime debugging support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 01-05-2001 CSH Created + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +typedef struct _RDEBUG_ENTRY { + LIST_ENTRY ListEntry; + CHAR Filename[MAX_PATH]; +} RDEBUG_ENTRY, *PRDEBUG_ENTRY; + +LIST_ENTRY RDebugListHead; +BOOLEAN RDebugInitialized = FALSE; + +/* FUNCTIONS ****************************************************************/ + +PRDEBUG_ENTRY +DbgpFind(PCH Filename) +{ + PLIST_ENTRY Current; + PRDEBUG_ENTRY Entry; + + Current = RDebugListHead.Flink; + while (Current != &RDebugListHead) + { + Entry = CONTAINING_RECORD(Current, RDEBUG_ENTRY, ListEntry); + + if (strcmp(Filename, Entry->Filename) == 0) + { + return Entry; + } + Current = Current->Flink; + } + + return(NULL); +} + +VOID +DbgRDebugInit(VOID) +{ + if (RDebugInitialized) + return; + + InitializeListHead(&RDebugListHead); + RDebugInitialized = TRUE; +} + +VOID +DbgShowFiles(VOID) +{ + PLIST_ENTRY Current; + PRDEBUG_ENTRY Entry; + ULONG Count; + + if (!RDebugInitialized) + return; + + Count = 0; + Current = RDebugListHead.Flink; + while (Current != &RDebugListHead) + { + Entry = CONTAINING_RECORD(Current, RDEBUG_ENTRY, ListEntry); + + DbgPrint(" %s\n", Entry->Filename); + Count++; + + Current = Current->Flink; + } + + if (Count == 1) + { + DbgPrint(" 1 file listed\n"); + } + else + { + DbgPrint(" %d files listed\n", Count); + } +} + +VOID +DbgEnableFile(PCH Filename) +{ + PRDEBUG_ENTRY Entry; + + if (!RDebugInitialized) + return; + + if (!DbgpFind(Filename)) + { + Entry = ExAllocatePool(NonPagedPool, sizeof(RDEBUG_ENTRY)); + assert(Entry); + RtlMoveMemory(Entry->Filename, Filename, strlen(Filename) + 1); + InsertTailList(&RDebugListHead, &Entry->ListEntry); + } +} + +VOID +DbgDisableFile(PCH Filename) +{ + PRDEBUG_ENTRY Entry; + + if (!RDebugInitialized) + return; + + Entry = DbgpFind(Filename); + + if (Entry) + { + RemoveEntryList(&Entry->ListEntry); + } +} + +BOOLEAN +DbgShouldPrint(PCH Filename) +{ + if (!RDebugInitialized) + return FALSE; + + return(DbgpFind(Filename) != NULL); +} + +/* EOF */ diff --git a/ntoskrnl/dbg/user.c b/ntoskrnl/dbg/user.c new file mode 100644 index 0000000..3641fff --- /dev/null +++ b/ntoskrnl/dbg/user.c @@ -0,0 +1,110 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/user.c + * PURPOSE: User mode debugging + * PROGRAMMER: David Welch (welch@cwcom.net) + * PORTABILITY: Unchecked + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID +DbgkCreateThread(PVOID StartAddress) +{ + LPC_DBG_MESSAGE Message; + LPC_DBG_MESSAGE Reply; + NTSTATUS Status; + + if (PsGetCurrentThread()->ThreadsProcess->DebugPort == NULL) + { + return; + } + + Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE); + Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) - + sizeof(LPC_MESSAGE_HEADER); + Message.Type = DBG_EVENT_CREATE_THREAD; + Message.Status = STATUS_SUCCESS; + Message.Data.CreateThread.Reserved = 0; + Message.Data.CreateThread.StartAddress = StartAddress; + + /* FIXME: Freeze all threads in process */ + + /* Send the message to the process's debug port and wait for a reply */ + Status = + LpcSendDebugMessagePort(PsGetCurrentThread()->ThreadsProcess->DebugPort, + &Message, + &Reply); + if (!NT_SUCCESS(Status)) + { + return; + } + + /* FIXME: Examine reply */ + return; +} + +ULONG +DbgkForwardException(EXCEPTION_RECORD Er, ULONG FirstChance) +{ + LPC_DBG_MESSAGE Message; + LPC_DBG_MESSAGE Reply; + NTSTATUS Status; + + if (PsGetCurrentThread()->ThreadsProcess->DebugPort == NULL) + { + return(0); + } + + Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE); + Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) - + sizeof(LPC_MESSAGE_HEADER); + Message.Type = DBG_EVENT_EXCEPTION; + Message.Status = STATUS_SUCCESS; + Message.Data.Exception.ExceptionRecord = Er; + Message.Data.Exception.FirstChance = FirstChance; + + /* FIXME: Freeze all threads in process */ + + /* Send the message to the process's debug port and wait for a reply */ + Status = + LpcSendDebugMessagePort(PsGetCurrentThread()->ThreadsProcess->DebugPort, + &Message, + &Reply); + if (!NT_SUCCESS(Status)) + { + return(0); + } + + /* FIXME: Examine reply */ + return(0); +} + +/* EOF */ diff --git a/ntoskrnl/ex/.cvsignore b/ntoskrnl/ex/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/ex/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/ex/btree.c b/ntoskrnl/ex/btree.c new file mode 100644 index 0000000..98ab9a9 --- /dev/null +++ b/ntoskrnl/ex/btree.c @@ -0,0 +1,662 @@ +/* + * ReactOS kernel + * Copyright (C) 1998-2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: btree.c + * PURPOSE: Binary tree support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 15-03-2002 CSH Created + */ +#include +#include + +#define NDEBUG +#include + +/* DATA **********************************************************************/ + +typedef struct _BINARY_TREE_NODE +{ + struct _BINARY_TREE_NODE * Parent; + struct _BINARY_TREE_NODE * LeftChild; + struct _BINARY_TREE_NODE * RightChild; + PVOID Key; + PVOID Value; +} BINARY_TREE_NODE, *PBINARY_TREE_NODE; + +typedef struct _TRAVERSE_CONTEXT { + PTRAVERSE_ROUTINE Routine; + PVOID Context; +} TRAVERSE_CONTEXT, *PTRAVERSE_CONTEXT; + +/* FUNCTIONS ****************************************************************/ + +#define ExpBinaryTreeRootNode(Tree)(((PBINARY_TREE) (Tree))->RootNode) +#define ExpBinaryTreeIsExternalNode(Node)(((Node)->LeftChild == NULL) && ((Node)->RightChild == NULL)) +#define ExpBinaryTreeIsInternalNode(Node)(!ExpBinaryTreeIsExternalNode(Node)) +#define ExpBinaryTreeNodeKey(Node)((Node)->Key) +#define ExpBinaryTreeNodeValue(Node)((Node)->Value) +#define ExpBinaryTreeParentNode(Node)((Node)->Parent) +#define ExpBinaryTreeLeftChildNode(Node)((Node)->LeftChild) +#define ExpBinaryTreeRightChildNode(Node)((Node)->RightChild) +#define ExpBinaryTreeNodeEqual(Equality)((Equality) == 0) +#define ExpBinaryTreeNodeLess(Equality)((Equality) < 0) +#define ExpBinaryTreeNodeMore(Equality)((Equality) > 0) + + +/* + * Lock the binary tree + */ +inline VOID +ExpLockBinaryTree(PBINARY_TREE Tree, + PKIRQL OldIrql) +{ + if (Tree->UseNonPagedPool) + { + KeAcquireSpinLock(&Tree->Lock.NonPaged, OldIrql); + } + else + { + ExAcquireFastMutex(&Tree->Lock.Paged); + } +} + + +/* + * Unlock the binary tree + */ +inline VOID +ExpUnlockBinaryTree(PBINARY_TREE Tree, + PKIRQL OldIrql) +{ + if (Tree->UseNonPagedPool) + { + KeReleaseSpinLock(&Tree->Lock.NonPaged, *OldIrql); + } + else + { + ExReleaseFastMutex(&Tree->Lock.Paged); + } +} + + +/* + * Allocate resources for a new node and initialize it. + */ +inline PBINARY_TREE_NODE +ExpCreateBinaryTreeNode(PBINARY_TREE Tree, + PBINARY_TREE_NODE Parent, + PVOID Value) +{ + PBINARY_TREE_NODE Node; + + if (Tree->UseNonPagedPool) + { + Node = (PBINARY_TREE_NODE) ExAllocateFromNPagedLookasideList(&Tree->List.NonPaged); + } + else + { + Node = (PBINARY_TREE_NODE) ExAllocateFromPagedLookasideList(&Tree->List.Paged); + } + + if (Node) + { + ExpBinaryTreeParentNode(Node) = Parent; + ExpBinaryTreeLeftChildNode(Node) = NULL; + ExpBinaryTreeRightChildNode(Node) = NULL; + ExpBinaryTreeNodeValue(Node) = Value; + } + + return Node; +} + + +/* + * Release resources for the node. + */ +inline VOID +ExpDestroyBinaryTreeNode(PBINARY_TREE Tree, + PBINARY_TREE_NODE Node) +{ + if (Tree->UseNonPagedPool) + { + ExFreeToNPagedLookasideList(&Tree->List.NonPaged, Node); + } + else + { + ExFreeToPagedLookasideList(&Tree->List.Paged, Node); + } +} + + +/* + * Replaces a child node of a node with a new node. + * The lock for the tree must be acquired when this routine is called. + */ +inline VOID +ExpBinaryTreeReplaceChildNode(PBINARY_TREE_NODE Child, + PBINARY_TREE_NODE NewChild) +{ + if (ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Child)) == Child) + { + ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Child)) = NewChild; + } + else + { + ExpBinaryTreeRightChildNode(ExpBinaryTreeParentNode(Child)) = NewChild; + } +} + + +/* + * Returns the sibling node of a node. + * The lock for the tree must be acquired when this routine is called. + */ +inline PBINARY_TREE_NODE +ExpSiblingBinaryTreeNode(PBINARY_TREE Tree, + PBINARY_TREE_NODE Node) +{ + if (Node == ExpBinaryTreeRootNode(Tree)) + { + return NULL; + } + else + { + if (ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Node)) == Node) + { + return ExpBinaryTreeRightChildNode(ExpBinaryTreeParentNode(Node)); + } + else + { + return ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Node)); + } + } +} + + +/* + * Expands an external node to an internal node. + * The lock for the tree must be acquired when this routine is called. + */ +VOID +ExpExpandExternalBinaryTreeNode(PBINARY_TREE Tree, + PBINARY_TREE_NODE Node) +{ + ExpBinaryTreeLeftChildNode(Node) = ExpCreateBinaryTreeNode(Tree, Node, NULL); + + if (!ExpBinaryTreeLeftChildNode(Node)) + { + /* FIXME: Throw exception */ + DbgPrint("ExpCreateBinaryTreeNode() failed\n"); + } + + ExpBinaryTreeRightChildNode(Node) = ExpCreateBinaryTreeNode(Tree, Node, NULL); + + if (!ExpBinaryTreeRightChildNode(Node)) + { + ExpDestroyBinaryTreeNode(Tree, ExpBinaryTreeLeftChildNode(Node)); + /* FIXME: Throw exception */ + DbgPrint("ExpCreateBinaryTreeNode() failed\n"); + } +} + + +/* + * Searches a tree for a node with the specified key. If a node with the + * specified key is not found, the external node where it should be is + * returned. + * The lock for the tree must be acquired when this routine is called. + */ +inline PBINARY_TREE_NODE +ExpSearchBinaryTree(PBINARY_TREE Tree, + PVOID Key, + PBINARY_TREE_NODE Node) +{ + LONG Equality; + + /* FIXME: Possibly do this iteratively due to the small kernel-mode stack */ + + if (ExpBinaryTreeIsExternalNode(Node)) + { + return Node; + } + + Equality = (*Tree->Compare)(Key, ExpBinaryTreeNodeKey(Node)); + + if (ExpBinaryTreeNodeEqual(Equality)) + { + return Node; + } + + if (ExpBinaryTreeNodeLess(Equality)) + { + return ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeLeftChildNode(Node)); + } + +/* if (ExpBinaryTreeNodeMore(Equality)) */ + { + return ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeRightChildNode(Node)); + } +} + + +/* + * Removes an external node and it's parent node from the tree. + * The lock for the tree must be acquired when this routine is called. + */ +VOID +ExpRemoveAboveExternalBinaryTreeNode(PBINARY_TREE Tree, + PBINARY_TREE_NODE Node) +{ + assertmsg(ExpBinaryTreeIsExternalNode(Node), ("Node is not external")); + + if (Node == ExpBinaryTreeRootNode(Tree)) + { + return; + } + else + { + PBINARY_TREE_NODE GrandParent; + PBINARY_TREE_NODE NewChild; + + GrandParent = ExpBinaryTreeParentNode(ExpBinaryTreeParentNode(Node)); + NewChild = ExpSiblingBinaryTreeNode(Tree, Node); + + if (GrandParent != NULL) + { + ExpBinaryTreeReplaceChildNode(ExpBinaryTreeParentNode(Node), NewChild); + } + + ExpDestroyBinaryTreeNode(Tree, ExpBinaryTreeParentNode(Node)); + ExpDestroyBinaryTreeNode(Tree, Node); + } +} + + +/* + * Release resources used by nodes of a binary (sub)tree. + */ +VOID +ExpDeleteBinaryTree(PBINARY_TREE Tree, + PBINARY_TREE_NODE Node) +{ + /* FIXME: Possibly do this iteratively due to the small kernel-mode stack */ + + if (ExpBinaryTreeIsInternalNode(Node)) + { + ExpDeleteBinaryTree(Tree, ExpBinaryTreeLeftChildNode(Node)); + ExpDeleteBinaryTree(Tree, ExpBinaryTreeRightChildNode(Node)); + } + + ExpDestroyBinaryTreeNode(Tree, Node); +} + + +/* + * Traverse a binary tree using preorder traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + * The lock for the tree must be acquired when this routine is called. + */ +BOOLEAN +ExpTraverseBinaryTreePreorder(PTRAVERSE_CONTEXT Context, + PBINARY_TREE_NODE Node) +{ + if (ExpBinaryTreeIsInternalNode(Node)) + { + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpBinaryTreeNodeKey(Node), + ExpBinaryTreeNodeValue(Node))) + { + return FALSE; + } + + /* Traverse left subtree */ + ExpTraverseBinaryTreePreorder(Context, ExpBinaryTreeLeftChildNode(Node)); + + /* Traverse right subtree */ + ExpTraverseBinaryTreePreorder(Context, ExpBinaryTreeRightChildNode(Node)); + } + + return TRUE; +} + + +/* + * Traverse a binary tree using inorder traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + * The lock for the tree must be acquired when this routine is called. + */ +BOOLEAN +ExpTraverseBinaryTreeInorder(PTRAVERSE_CONTEXT Context, + PBINARY_TREE_NODE Node) +{ + if (ExpBinaryTreeIsInternalNode(Node)) + { + /* Traverse left subtree */ + ExpTraverseBinaryTreeInorder(Context, ExpBinaryTreeLeftChildNode(Node)); + + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpBinaryTreeNodeKey(Node), + ExpBinaryTreeNodeValue(Node))) + { + return FALSE; + } + + /* Traverse right subtree */ + ExpTraverseBinaryTreeInorder(Context, ExpBinaryTreeRightChildNode(Node)); + } + + return TRUE; +} + + +/* + * Traverse a binary tree using postorder traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + * The lock for the tree must be acquired when this routine is called. + */ +BOOLEAN +ExpTraverseBinaryTreePostorder(PTRAVERSE_CONTEXT Context, + PBINARY_TREE_NODE Node) +{ + if (ExpBinaryTreeIsInternalNode(Node)) + { + /* Traverse left subtree */ + ExpTraverseBinaryTreePostorder(Context, ExpBinaryTreeLeftChildNode(Node)); + + /* Traverse right subtree */ + ExpTraverseBinaryTreePostorder(Context, ExpBinaryTreeRightChildNode(Node)); + + /* Call the traversal routine */ + return (*Context->Routine)(Context->Context, + ExpBinaryTreeNodeKey(Node), + ExpBinaryTreeNodeValue(Node)); + } + + return TRUE; +} + + +/* + * Default key compare function. Compares the integer values of the two keys. + */ +LONG STDCALL +ExpBinaryTreeDefaultCompare(PVOID Key1, + PVOID Key2) +{ + if (Key1 == Key2) + return 0; + + return (((LONG_PTR) Key1 < (LONG_PTR) Key2) ? -1 : 1); +} + + +/* + * Initializes a binary tree. + */ +BOOLEAN STDCALL +ExInitializeBinaryTree(IN PBINARY_TREE Tree, + IN PKEY_COMPARATOR Compare, + IN BOOLEAN UseNonPagedPool) +{ + RtlZeroMemory(Tree, sizeof(BINARY_TREE)); + + Tree->Compare = (Compare == NULL) + ? ExpBinaryTreeDefaultCompare : Compare; + + Tree->UseNonPagedPool = UseNonPagedPool; + + if (UseNonPagedPool) + { + ExInitializeNPagedLookasideList( + &Tree->List.NonPaged, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(BINARY_TREE_NODE), /* Size of each entry */ + TAG('E','X','B','T'), /* Tag */ + 0); /* Depth */ + + KeInitializeSpinLock(&Tree->Lock.NonPaged); + } + else + { + ExInitializePagedLookasideList( + &Tree->List.Paged, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(BINARY_TREE_NODE), /* Size of each entry */ + TAG('E','X','B','T'), /* Tag */ + 0); /* Depth */ + + ExInitializeFastMutex(&Tree->Lock.Paged); + } + + ExpBinaryTreeRootNode(Tree) = ExpCreateBinaryTreeNode(Tree, NULL, NULL); + + if (ExpBinaryTreeRootNode(Tree) == NULL) + { + if (UseNonPagedPool) + { + ExDeleteNPagedLookasideList(&Tree->List.NonPaged); + } + else + { + ExDeletePagedLookasideList(&Tree->List.Paged); + } + return FALSE; + } + else + { + return TRUE; + } +} + + +/* + * Release resources used by a binary tree. + */ +VOID STDCALL +ExDeleteBinaryTree(IN PBINARY_TREE Tree) +{ + /* Remove all nodes */ + ExpDeleteBinaryTree(Tree, ExpBinaryTreeRootNode(Tree)); + + if (Tree->UseNonPagedPool) + { + ExDeleteNPagedLookasideList(&Tree->List.NonPaged); + } + else + { + ExDeletePagedLookasideList(&Tree->List.Paged); + } +} + + +/* + * Insert a value in a binary tree. + */ +VOID STDCALL +ExInsertBinaryTree(IN PBINARY_TREE Tree, + IN PVOID Key, + IN PVOID Value) +{ + PBINARY_TREE_NODE Node; + KIRQL OldIrql; + + /* FIXME: Use SEH for error reporting */ + + ExpLockBinaryTree(Tree, &OldIrql); + Node = ExpBinaryTreeRootNode(Tree); + do + { + Node = ExpSearchBinaryTree(Tree, Key, Node); + + if (ExpBinaryTreeIsExternalNode(Node)) + { + break; + } + else + { + Node = ExpBinaryTreeRightChildNode(Node); + } + } while (TRUE); + ExpExpandExternalBinaryTreeNode(Tree, Node); + ExpBinaryTreeNodeKey(Node) = Key; + ExpBinaryTreeNodeValue(Node) = Value; + ExpUnlockBinaryTree(Tree, &OldIrql); +} + + +/* + * Search for a value associated with a given key in a binary tree. + */ +BOOLEAN STDCALL +ExSearchBinaryTree(IN PBINARY_TREE Tree, + IN PVOID Key, + OUT PVOID * Value) +{ + PBINARY_TREE_NODE Node; + KIRQL OldIrql; + + ExpLockBinaryTree(Tree, &OldIrql); + Node = ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeRootNode(Tree)); + + if (ExpBinaryTreeIsInternalNode(Node)) + { + *Value = ExpBinaryTreeNodeValue(Node); + ExpUnlockBinaryTree(Tree, &OldIrql); + return TRUE; + } + else + { + ExpUnlockBinaryTree(Tree, &OldIrql); + return FALSE; + } +} + + +/* + * Remove a value associated with a given key from a binary tree. + */ +BOOLEAN STDCALL +ExRemoveBinaryTree(IN PBINARY_TREE Tree, + IN PVOID Key, + IN PVOID * Value) +{ + PBINARY_TREE_NODE Node; + KIRQL OldIrql; + + ExpLockBinaryTree(Tree, &OldIrql); + + Node = ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeRootNode(Tree)); + + if (ExpBinaryTreeIsExternalNode(Node)) + { + ExpUnlockBinaryTree(Tree, &OldIrql); + return FALSE; + } + else + { + *Value = ExpBinaryTreeNodeValue(Node); + if (ExpBinaryTreeIsExternalNode(ExpBinaryTreeLeftChildNode(Node))) + { + Node = ExpBinaryTreeLeftChildNode(Node); + } + else if (ExpBinaryTreeIsExternalNode(ExpBinaryTreeRightChildNode(Node))) + { + Node = ExpBinaryTreeRightChildNode(Node); + } + else + { + // Node has internal children + PBINARY_TREE_NODE SwapNode; + + SwapNode = Node; + Node = ExpBinaryTreeRightChildNode(SwapNode); + do + { + Node = ExpBinaryTreeLeftChildNode(Node); + } while (ExpBinaryTreeIsInternalNode(Node)); + } + + ExpRemoveAboveExternalBinaryTreeNode(Tree, Node); + ExpUnlockBinaryTree(Tree, &OldIrql); + return TRUE; + } +} + + +/* + * Traverse a binary tree using either preorder, inorder or postorder + * traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + */ +BOOLEAN STDCALL +ExTraverseBinaryTree(IN PBINARY_TREE Tree, + IN TRAVERSE_METHOD Method, + IN PTRAVERSE_ROUTINE Routine, + IN PVOID Context) +{ + TRAVERSE_CONTEXT tc; + BOOLEAN Status; + KIRQL OldIrql; + + tc.Routine = Routine; + tc.Context = Context; + + ExpLockBinaryTree(Tree, &OldIrql); + + switch (Method) + { + case TraverseMethodPreorder: + Status = ExpTraverseBinaryTreePreorder(&tc, ExpBinaryTreeRootNode(Tree)); + break; + + case TraverseMethodInorder: + Status = ExpTraverseBinaryTreeInorder(&tc, ExpBinaryTreeRootNode(Tree)); + break; + + case TraverseMethodPostorder: + Status = ExpTraverseBinaryTreePostorder(&tc, ExpBinaryTreeRootNode(Tree)); + break; + + default: + Status = FALSE; + break; + } + + ExpUnlockBinaryTree(Tree, &OldIrql); + + return Status; +} + +/* EOF */ diff --git a/ntoskrnl/ex/callback.c b/ntoskrnl/ex/callback.c new file mode 100644 index 0000000..dd4ddae --- /dev/null +++ b/ntoskrnl/ex/callback.c @@ -0,0 +1,87 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/callback.c + * PURPOSE: Executive callbacks + * PROGRAMMER: David Welch (welch@mcmail.com) + * PORTABILITY: Checked. + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* + * NOTE: + * These funtions are not implemented in NT4. + * They are implemented in Win2k. + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +ExCreateCallback ( + OUT PCALLBACK_OBJECT * CallbackObject, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN Create, + IN BOOLEAN AllowMultipleCallbacks + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +VOID +STDCALL +ExNotifyCallback ( + IN PVOID CallbackObject, + IN PVOID Argument1, + IN PVOID Argument2 + ) +{ + return; +} + +PVOID +STDCALL +ExRegisterCallback ( + IN PCALLBACK_OBJECT CallbackObject, + IN PCALLBACK_FUNCTION CallbackFunction, + IN PVOID CallbackContext + ) +{ + return NULL; +} + +VOID +STDCALL +ExUnregisterCallback ( + IN PVOID CallbackRegistration + ) +{ + return; +} + +/* EOF */ diff --git a/ntoskrnl/ex/fmutex.c b/ntoskrnl/ex/fmutex.c new file mode 100644 index 0000000..6c38af9 --- /dev/null +++ b/ntoskrnl/ex/fmutex.c @@ -0,0 +1,67 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/fmutex.c + * PURPOSE: Implements fast mutexes + * PROGRAMMER: David Welch (welch@cwcom.net) + * PORTABILITY: Checked. + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID FASTCALL +ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex) +{ + assert(FastMutex->Owner != KeGetCurrentThread()); + InterlockedIncrement(&FastMutex->Contention); + while (InterlockedExchange(&FastMutex->Count, 0) == 0) + { + KeWaitForSingleObject(&FastMutex->Event, + Executive, + KernelMode, + FALSE, + NULL); + } + InterlockedDecrement(&FastMutex->Contention); + FastMutex->Owner = KeGetCurrentThread(); +} + +VOID FASTCALL +ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex) +{ + assert(FastMutex->Owner == KeGetCurrentThread()); + FastMutex->Owner = NULL; + if (FastMutex->Contention > 0) + { + KeSetEvent(&FastMutex->Event, 0, FALSE); + } + InterlockedExchange(&FastMutex->Count, 1); +} + +/* EOF */ diff --git a/ntoskrnl/ex/hashtab.c b/ntoskrnl/ex/hashtab.c new file mode 100644 index 0000000..207fa44 --- /dev/null +++ b/ntoskrnl/ex/hashtab.c @@ -0,0 +1,320 @@ +/* + * ReactOS kernel + * Copyright (C) 1998-2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: hashtab.c + * PURPOSE: Hash table support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: The hash function is from: + * Bob Jenkins + * http://burtleburtle.net/bob/hash/doobs.html + * UPDATE HISTORY: + * 15-03-2002 CSH Created + */ +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +#define ExpHashTableSize(n) ((ULONG)1 << (n)) +#define ExpHashTableMask(n) (ExpHashTableSize(n) - 1) + +#define ExpHashMix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c >> 13); \ + b -= c; b -= a; b ^= (a << 8); \ + c -= a; c -= b; c ^= (b >> 13); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 16); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 3); \ + b -= c; b -= a; b ^= (a << 10); \ + c -= a; c -= b; c ^= (b >> 15); \ +} + + +ULONG +ExpHash(PUCHAR Key, + ULONG KeyLength) +{ + register ULONG a, b, c, len; + + /* Set up the internal state */ + len = KeyLength; + a = b = 0x9e3779b9; /* The golden ratio; an arbitrary value */ + c = 0; + + /* Handle most of the key */ + while (len >= 12) + { + a += (Key[0] + ((ULONG)Key[1]<<8) + ((ULONG)Key[2]<<16) + ((ULONG)Key[3]<<24)); + b += (Key[4] + ((ULONG)Key[5]<<8) + ((ULONG)Key[6]<<16) + ((ULONG)Key[7]<<24)); + c += (Key[8] + ((ULONG)Key[9]<<8) + ((ULONG)Key[10]<<16)+ ((ULONG)Key[11]<<24)); + ExpHashMix(a, b, c); + Key += 12; len -= 12; + } + + /* Handle the last 11 bytes */ + c += KeyLength; + switch(len) /* All the case statements fall through */ + { + case 11: c += ((ULONG)Key[10] << 24); + case 10: c += ((ULONG)Key[9] << 16); + case 9 : c += ((ULONG)Key[8] << 8); + /* The first byte of c is reserved for the length */ + case 8 : b += ((ULONG)Key[7] << 24); + case 7 : b += ((ULONG)Key[6] << 16); + case 6 : b += ((ULONG)Key[5] << 8); + case 5 : b += Key[4]; + case 4 : a += ((ULONG)Key[3] << 24); + case 3 : a += ((ULONG)Key[2] << 16); + case 2 : a += ((ULONG)Key[1] << 8); + case 1 : a += Key[0]; + /* case 0: nothing left to add */ + } + + ExpHashMix(a, b, c); + + return c; +} + + +/* + * Lock the hash table + */ +inline VOID +ExpLockHashTable(PHASH_TABLE HashTable, + PKIRQL OldIrql) +{ + if (HashTable->UseNonPagedPool) + { + KeAcquireSpinLock(&HashTable->Lock.NonPaged, OldIrql); + } + else + { + ExAcquireFastMutex(&HashTable->Lock.Paged); + } +} + + +/* + * Unlock the hash table + */ +inline VOID +ExpUnlockHashTable(PHASH_TABLE HashTable, + PKIRQL OldIrql) +{ + if (HashTable->UseNonPagedPool) + { + KeReleaseSpinLock(&HashTable->Lock.NonPaged, *OldIrql); + } + else + { + ExReleaseFastMutex(&HashTable->Lock.Paged); + } +} + + +/* + * Insert a value in a hash table. + */ +inline VOID STDCALL +ExpInsertHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + IN PVOID Value) +{ + ULONG Index; + + Index = (ExpHash(Key, KeyLength) & ExpHashTableMask(HashTable->HashTableSize)); + + ExInsertSplayTree(&HashTable->HashTrees[Index], Key, Value); +} + + +/* + * Search for a value associated with a given key in a hash table. + */ +inline BOOLEAN STDCALL +ExpSearchHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + OUT PVOID * Value) +{ + ULONG Index; + + Index = (ExpHash(Key, KeyLength) & ExpHashTableMask(HashTable->HashTableSize)); + + return ExSearchSplayTree(&HashTable->HashTrees[Index], Key, Value); +} + + +/* + * Remove a value associated with a given key from a hash table. + */ +BOOLEAN STDCALL +ExpRemoveHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + IN PVOID * Value) +{ + ULONG Index; + + Index = (ExpHash(Key, KeyLength) & ExpHashTableMask(HashTable->HashTableSize)); + + return ExRemoveSplayTree(&HashTable->HashTrees[Index], Key, Value); +} + + +/* + * Initializes a hash table. + */ +BOOLEAN STDCALL +ExInitializeHashTable(IN PHASH_TABLE HashTable, + IN ULONG HashTableSize, + IN PKEY_COMPARATOR Compare OPTIONAL, + IN BOOLEAN UseNonPagedPool) +{ + BOOLEAN Status; + LONG Index; + + RtlZeroMemory(HashTable, sizeof(HASH_TABLE)); + + HashTable->HashTableSize = HashTableSize; + + HashTable->UseNonPagedPool = UseNonPagedPool; + + if (UseNonPagedPool) + { + KeInitializeSpinLock(&HashTable->Lock.NonPaged); + HashTable->HashTrees = ExAllocatePool(NonPagedPool, ExpHashTableSize(HashTableSize) * sizeof(SPLAY_TREE)); + } + else + { + ExInitializeFastMutex(&HashTable->Lock.Paged); + HashTable->HashTrees = ExAllocatePool(PagedPool, ExpHashTableSize(HashTableSize) * sizeof(SPLAY_TREE)); + } + + if (HashTable->HashTrees == NULL) + { + return FALSE; + } + + for (Index = 0; Index < ExpHashTableSize(HashTableSize); Index++) + { + Status = ExInitializeSplayTree(&HashTable->HashTrees[Index], Compare, FALSE, UseNonPagedPool); + + if (!Status) + { + LONG i; + + for (i = Index - 1; i >= 0; i--) + { + ExDeleteSplayTree(&HashTable->HashTrees[i]); + } + + ExFreePool(HashTable->HashTrees); + + return FALSE; + } + } + + return TRUE; +} + + +/* + * Release resources used by a hash table. + */ +VOID STDCALL +ExDeleteHashTable(IN PHASH_TABLE HashTable) +{ + ULONG Index; + + for (Index = 0; Index < ExpHashTableSize(HashTable->HashTableSize); Index++) + { + ExDeleteSplayTree(&HashTable->HashTrees[Index]); + } + + ExFreePool(HashTable->HashTrees); +} + + +/* + * Insert a value in a hash table. + */ +VOID STDCALL +ExInsertHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + IN PVOID Value) +{ + KIRQL OldIrql; + + /* FIXME: Use SEH for error reporting */ + + ExpLockHashTable(HashTable, &OldIrql); + ExpInsertHashTable(HashTable, Key, KeyLength, Value); + ExpUnlockHashTable(HashTable, &OldIrql); +} + + +/* + * Search for a value associated with a given key in a hash table. + */ +BOOLEAN STDCALL +ExSearchHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + OUT PVOID * Value) +{ + BOOLEAN Status; + KIRQL OldIrql; + + ExpLockHashTable(HashTable, &OldIrql); + Status = ExpSearchHashTable(HashTable, Key, KeyLength, Value); + ExpUnlockHashTable(HashTable, &OldIrql); + + return Status; +} + + +/* + * Remove a value associated with a given key from a hash table. + */ +BOOLEAN STDCALL +ExRemoveHashTable(IN PHASH_TABLE HashTable, + IN PVOID Key, + IN ULONG KeyLength, + IN PVOID * Value) +{ + BOOLEAN Status; + KIRQL OldIrql; + + ExpLockHashTable(HashTable, &OldIrql); + Status = ExpRemoveHashTable(HashTable, Key, KeyLength, Value); + ExpUnlockHashTable(HashTable, &OldIrql); + + return Status; +} + +/* EOF */ diff --git a/ntoskrnl/ex/i386/.cvsignore b/ntoskrnl/ex/i386/.cvsignore new file mode 100644 index 0000000..31dc307 --- /dev/null +++ b/ntoskrnl/ex/i386/.cvsignore @@ -0,0 +1,2 @@ +*.d +*.o diff --git a/ntoskrnl/ex/i386/interlck.c b/ntoskrnl/ex/i386/interlck.c new file mode 100644 index 0000000..e5f23a6 --- /dev/null +++ b/ntoskrnl/ex/i386/interlck.c @@ -0,0 +1,162 @@ +/* $Id$ + * + * reactos/ntoskrnl/ex/i386/interlck.c + * + */ +#include + + +INTERLOCKED_RESULT FASTCALL +Exfi386InterlockedIncrementLong(IN PLONG Addend); + +__asm__("\n\t.global @Exfi386InterlockedIncrementLong@4\n\t" + "@Exfi386InterlockedIncrementLong@4:\n\t" + "addl $1,(%ecx)\n\t" + "lahf\n\t" + "andl $0xC000, %eax\n\t" + "ret\n\t"); + + +INTERLOCKED_RESULT FASTCALL +Exfi386InterlockedDecrementLong(IN PLONG Addend); + +__asm__("\n\t.global @Exfi386InterlockedDecrementLong@4\n\t" + "@Exfi386InterlockedDecrementLong@4:\n\t" + "subl $1,(%ecx)\n\t" + "lahf\n\t" + "andl $0xC000, %eax\n\t" + "ret\n\t"); + + +ULONG FASTCALL +Exfi386InterlockedExchangeUlong(IN PULONG Target, + IN ULONG Value); + +__asm__("\n\t.global @Exfi386InterlockedExchangeUlong@8\n\t" + "@Exfi386InterlockedExchangeUlong@8:\n\t" + "movl (%ecx),%eax\n" + "xchgl %edx,(%ecx)\n\t" + "ret\n\t"); + + + +INTERLOCKED_RESULT STDCALL +Exi386InterlockedIncrementLong(IN PLONG Addend); + +__asm__("\n\t.global _Exi386InterlockedIncrementLong@4\n\t" + "_Exi386InterlockedIncrementLong@4:\n\t" + "movl 4(%esp),%eax\n\t" + "addl $1,(%eax)\n\t" + "lahf\n\t" + "andl $0xC000, %eax\n\t" + "ret $4\n\t"); + + +INTERLOCKED_RESULT STDCALL +Exi386InterlockedDecrementLong(IN PLONG Addend); + +__asm__("\n\t.global _Exi386InterlockedDecrementLong@4\n\t" + "_Exi386InterlockedDecrementLong@4:\n\t" + "movl 4(%esp),%eax\n\t" + "subl $1,(%eax)\n\t" + "lahf\n\t" + "andl $0xC000, %eax\n\t" + "ret $4\n\t"); + + +ULONG STDCALL +Exi386InterlockedExchangeUlong(IN PULONG Target, + IN ULONG Value); + +__asm__("\n\t.global _Exi386InterlockedExchangeUlong@8\n\t" + "_Exi386InterlockedExchangeUlong@8:\n\t" + "movl 4(%esp),%edx\n\t" + "movl 8(%esp),%eax\n\t" + "xchgl %eax,(%edx)\n\t" + "ret $8\n\t"); + + +/********************************************************************** + * FASTCALL: @InterlockedIncrement@4 + * STDCALL : _InterlockedIncrement@4 + */ +LONG FASTCALL +InterlockedIncrement(PLONG Addend); +/* + * FUNCTION: Increments a caller supplied variable of type LONG as an + * atomic operation + * ARGUMENTS: + * Addend = Points to a variable whose value is to be increment + * RETURNS: The incremented value + */ + +__asm__("\n\t.global @InterlockedIncrement@4\n\t" + "@InterlockedIncrement@4:\n\t" + "movl $1,%eax\n\t" + "xaddl %eax,(%ecx)\n\t" + "incl %eax\n\t" + "ret\n\t"); + + +/********************************************************************** + * FASTCALL: @InterlockedDecrement@4 + * STDCALL : _InterlockedDecrement@4 + */ +LONG FASTCALL +InterlockedDecrement(PLONG Addend); + +__asm__("\n\t.global @InterlockedDecrement@4\n\t" + "@InterlockedDecrement@4:\n\t" + "movl $-1,%eax\n\t" + "xaddl %eax,(%ecx)\n\t" + "decl %eax\n\t" + "ret\n\t"); + + +/********************************************************************** + * FASTCALL: @InterlockedExchange@8 + * STDCALL : _InterlockedExchange@8 + */ + +LONG FASTCALL +InterlockedExchange(PLONG Target, + LONG Value); + +__asm__("\n\t.global @InterlockedExchange@8\n\t" + "@InterlockedExchange@8:\n\t" + "movl (%ecx),%eax\n" + "xchgl %edx,(%ecx)\n\t" + "ret\n\t"); + + +/********************************************************************** + * FASTCALL: @InterlockedExchangeAdd@8 + * STDCALL: _InterlockedExchangeAdd@8 + */ +LONG FASTCALL +InterlockedExchangeAdd(PLONG Addend, + LONG Value); + +__asm__("\n\t.global @InterlockedExchangeAdd@8\n\t" + "@InterlockedExchangeAdd@8:\n\t" + "xaddl %edx,(%ecx)\n\t" + "movl %edx,%eax\n\t" + "ret\n\t"); + + +/********************************************************************** + * FASTCALL: @InterlockedCompareExchange@12 + * STDCALL: _InterlockedCompareExchange@12 + */ +LONG FASTCALL +InterlockedCompareExchange(PLONG Destination, + LONG Exchange, + LONG Comperand); + +__asm__("\n\t.global @InterlockedCompareExchange@12\n\t" + "@InterlockedCompareExchange@12:\n\t" + "movl 4(%esp),%eax\n\t" + "cmpxchg %edx,(%ecx)\n\t" + "ret $4\n\t"); + +/* EOF */ diff --git a/ntoskrnl/ex/init.c b/ntoskrnl/ex/init.c new file mode 100644 index 0000000..c9a8c3e --- /dev/null +++ b/ntoskrnl/ex/init.c @@ -0,0 +1,67 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: kernel/ex/init.c + * PURPOSE: executive initalization + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * PORTABILITY: Checked. + * UPDATE HISTORY: + * Created 11/09/99 + */ + +#include +#include + +#define NDEBUG +#include + +/* DATA **********************************************************************/ + +/* FUNCTIONS ****************************************************************/ + +VOID +ExInit (VOID) +{ + ExInitTimeZoneInfo(); + ExInitializeWorkerThreads(); + ExpInitLookasideLists(); + ExpWin32kInit(); +} + + +BOOLEAN STDCALL +ExIsProcessorFeaturePresent (IN ULONG ProcessorFeature) +{ + if (ProcessorFeature >= 32) + return FALSE; + + return FALSE; +} + + +VOID STDCALL +ExPostSystemEvent (ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +{ + /* doesn't do anything */ +} + +/* EOF */ diff --git a/ntoskrnl/ex/interlck.c b/ntoskrnl/ex/interlck.c new file mode 100644 index 0000000..f3fa44e --- /dev/null +++ b/ntoskrnl/ex/interlck.c @@ -0,0 +1,216 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/interlck.c + * PURPOSE: Implements interlocked functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + + +/* FUNCTIONS *****************************************************************/ + +INTERLOCKED_RESULT STDCALL +ExInterlockedDecrementLong (PLONG Addend, + PKSPIN_LOCK Lock) +/* + * Obsolete, use InterlockedDecrement instead + */ +{ + KIRQL oldlvl; + LONG oldval; + + KeAcquireSpinLock (Lock, &oldlvl); + + oldval = *Addend; + (*Addend)--; + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + + +ULONG STDCALL +ExInterlockedExchangeUlong (PULONG Target, + ULONG Value, + PKSPIN_LOCK Lock) +/* + * Obsolete, use InterlockedExchange instead + */ +{ + KIRQL oldlvl; + LONG oldval; + + KeAcquireSpinLock (Lock, &oldlvl); + + oldval = *Target; + *Target = Value; + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + + +ULONG STDCALL +ExInterlockedAddUlong (PULONG Addend, + ULONG Increment, + PKSPIN_LOCK Lock) +/* + * ExInterlockedAddUlong adds an unsigned long value to a given unsigned + * integer as an atomic operation. + * + * ADDEND = Points to an unsigned long integer whose value is to be adjusted + * by the Increment value. + * + * INCREMENT = Is an unsigned long integer to be added. + * + * LOCK = Points to a spinlock to be used to synchronize access to ADDEND. + * + * Returns: + * + * The original value of the unsigned integer pointed to by ADDEND. + */ +{ + KIRQL oldlvl; + ULONG oldval; + + KeAcquireSpinLock (Lock, &oldlvl); + + oldval = *Addend; + *Addend += Increment; + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + +LARGE_INTEGER STDCALL +ExInterlockedAddLargeInteger (PLARGE_INTEGER Addend, + LARGE_INTEGER Increment, + PKSPIN_LOCK Lock) +/* + * Adds two large integer values as an atomic operation. + * + * ADDEND = Pointer to a large integer value that will have INCREMENT added. + * + * INCREMENT = Value to be added. + * + * LOCK = Spinlock used to synchronize access to ADDEND. + * + * Returns: + * + * The original value of the large integer pointed to by ADDEND. + */ +{ + KIRQL oldlvl; + LARGE_INTEGER oldval; + + + KeAcquireSpinLock (Lock, &oldlvl); + + + oldval.QuadPart = Addend->QuadPart; + Addend->QuadPart += Increment.QuadPart; + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + +INTERLOCKED_RESULT STDCALL +ExInterlockedIncrementLong (PLONG Addend, + PKSPIN_LOCK Lock) +/* + * Obsolete, use InterlockedIncrement instead. + */ +{ + KIRQL oldlvl; + LONG oldval; + + KeAcquireSpinLock (Lock, &oldlvl); + + oldval = *Addend; + (*Addend)++; + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + +VOID FASTCALL +ExInterlockedAddLargeStatistic (IN PLARGE_INTEGER Addend, + IN ULONG Increment) +/* + * Undocumented in DDK. + */ +{ + Addend->QuadPart += Increment; +} + +LONGLONG FASTCALL +ExInterlockedCompareExchange64 (IN OUT PLONGLONG Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand, + IN PKSPIN_LOCK Lock) +/* + * Undocumented in DDK. + */ +{ + KIRQL oldlvl; + LONGLONG oldval; + + KeAcquireSpinLock (Lock, &oldlvl); + + oldval = *Destination; + if (*Destination == *Comparand) + { + *Destination = *Exchange; + } + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + +ULONG FASTCALL +ExfInterlockedAddUlong(PULONG Addend, + ULONG Increment, + PKSPIN_LOCK Lock) +/* + * ExInterlockedAddUlong adds an unsigned long value to a given unsigned + * integer as an atomic operation. + * + * ADDEND = Points to an unsigned long integer whose value is to be adjusted + * by the Increment value. + * + * INCREMENT = Is an unsigned long integer to be added. + * + * LOCK = Points to a spinlock to be used to synchronize access to ADDEND. + * + * Returns: + * + * The original value of the unsigned integer pointed to by ADDEND. + */ +{ + KIRQL oldlvl; + ULONG oldval; + + KeAcquireSpinLock (Lock, &oldlvl); + + oldval = *Addend; + *Addend += Increment; + + KeReleaseSpinLock (Lock, oldlvl); + + return oldval; +} + +/* EOF */ diff --git a/ntoskrnl/ex/list.c b/ntoskrnl/ex/list.c new file mode 100644 index 0000000..d4b0e1c --- /dev/null +++ b/ntoskrnl/ex/list.c @@ -0,0 +1,377 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/list.c + * PURPOSE: Manages double linked lists, single linked lists and + * sequenced lists + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 02-07-2001 CSH Implemented sequenced lists + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *************************************************************/ + + +PLIST_ENTRY STDCALL +ExInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts an entry at the head of a doubly linked list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + PLIST_ENTRY Old; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(ListHead)) + { + Old = NULL; + } + else + { + Old = ListHead->Flink; + } + InsertHeadList(ListHead,ListEntry); + KeReleaseSpinLock(Lock,oldlvl); + + return(Old); +} + + +PLIST_ENTRY STDCALL +ExInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts an entry at the tail of a doubly linked list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + PLIST_ENTRY Old; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(ListHead)) + { + Old = NULL; + } + else + { + Old = ListHead->Blink; + } + InsertTailList(ListHead,ListEntry); + KeReleaseSpinLock(Lock,oldlvl); + + return(Old); +} + + +PLIST_ENTRY STDCALL +ExInterlockedRemoveHeadList(PLIST_ENTRY Head, + PKSPIN_LOCK Lock) +/* + * FUNCTION: Removes the head of a double linked list + * ARGUMENTS: + * Head = Points to the head of the list + * Lock = Lock for synchronizing access to the list + * RETURNS: The removed entry + */ +{ + PLIST_ENTRY ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(Head)) + { + ret = NULL; + } + else + { + ret = RemoveHeadList(Head); + } + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PLIST_ENTRY +ExInterlockedRemoveTailList(PLIST_ENTRY Head, + PKSPIN_LOCK Lock) +/* + * FUNCTION: Removes the tail of a double linked list + * ARGUMENTS: + * Head = Points to the head of the list + * Lock = Lock for synchronizing access to the list + * RETURNS: The removed entry + */ +{ + PLIST_ENTRY ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(Head)) + { + ret = NULL; + } + else + { + ret = RemoveTailList(Head); + } + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PSINGLE_LIST_ENTRY FASTCALL +ExInterlockedPopEntrySList(IN PSLIST_HEADER ListHead, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Removes (pops) an entry from a sequenced list + * ARGUMENTS: + * ListHead = Points to the head of the list + * Lock = Lock for synchronizing access to the list + * RETURNS: The removed entry + */ +{ + PSINGLE_LIST_ENTRY ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + ret = PopEntryList(&ListHead->s.Next); + if (ret) + { + ListHead->s.Depth--; + ListHead->s.Sequence++; + } + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PSINGLE_LIST_ENTRY FASTCALL +ExInterlockedPushEntrySList(IN PSLIST_HEADER ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts (pushes) an entry into a sequenced list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + KIRQL oldlvl; + PSINGLE_LIST_ENTRY ret; + + KeAcquireSpinLock(Lock,&oldlvl); + ret=ListHead->s.Next.Next; + PushEntryList(&ListHead->s.Next,ListEntry); + ListHead->s.Depth++; + ListHead->s.Sequence++; + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PSINGLE_LIST_ENTRY STDCALL +ExInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Removes (pops) an entry from a singly list + * ARGUMENTS: + * ListHead = Points to the head of the list + * Lock = Lock for synchronizing access to the list + * RETURNS: The removed entry + */ +{ + PSINGLE_LIST_ENTRY ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + ret = PopEntryList(ListHead); + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PSINGLE_LIST_ENTRY STDCALL +ExInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts (pushes) an entry into a singly linked list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + KIRQL oldlvl; + PSINGLE_LIST_ENTRY ret; + + KeAcquireSpinLock(Lock,&oldlvl); + ret=ListHead->Next; + PushEntryList(ListHead,ListEntry); + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PLIST_ENTRY FASTCALL +ExfInterlockedInsertHeadList(IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts an entry at the head of a doubly linked list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + PLIST_ENTRY Old; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(ListHead)) + { + Old = NULL; + } + else + { + Old = ListHead->Flink; + } + InsertHeadList(ListHead,ListEntry); + KeReleaseSpinLock(Lock,oldlvl); + + return(Old); +} + + +PLIST_ENTRY FASTCALL +ExfInterlockedInsertTailList(IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts an entry at the tail of a doubly linked list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + PLIST_ENTRY Old; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(ListHead)) + { + Old = NULL; + } + else + { + Old = ListHead->Blink; + } + InsertTailList(ListHead,ListEntry); + KeReleaseSpinLock(Lock,oldlvl); + + return(Old); +} + + +PSINGLE_LIST_ENTRY FASTCALL +ExfInterlockedPopEntryList(IN PSINGLE_LIST_ENTRY ListHead, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Removes (pops) an entry from a singly list + * ARGUMENTS: + * ListHead = Points to the head of the list + * Lock = Lock for synchronizing access to the list + * RETURNS: The removed entry + */ +{ + PSINGLE_LIST_ENTRY ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + ret = PopEntryList(ListHead); + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PSINGLE_LIST_ENTRY FASTCALL +ExfInterlockedPushEntryList(IN PSINGLE_LIST_ENTRY ListHead, + IN PSINGLE_LIST_ENTRY ListEntry, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Inserts (pushes) an entry into a singly linked list + * ARGUMENTS: + * ListHead = Points to the head of the list + * ListEntry = Points to the entry to be inserted + * Lock = Caller supplied spinlock used to synchronize access + * RETURNS: The previous head of the list + */ +{ + KIRQL oldlvl; + PSINGLE_LIST_ENTRY ret; + + KeAcquireSpinLock(Lock,&oldlvl); + ret=ListHead->Next; + PushEntryList(ListHead,ListEntry); + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +PLIST_ENTRY FASTCALL +ExfInterlockedRemoveHeadList(IN PLIST_ENTRY Head, + IN PKSPIN_LOCK Lock) +/* + * FUNCTION: Removes the head of a double linked list + * ARGUMENTS: + * Head = Points to the head of the list + * Lock = Lock for synchronizing access to the list + * RETURNS: The removed entry + */ +{ + PLIST_ENTRY ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + if (IsListEmpty(Head)) + { + ret = NULL; + } + else + { + ret = RemoveHeadList(Head); + } + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + +/* EOF */ diff --git a/ntoskrnl/ex/lookas.c b/ntoskrnl/ex/lookas.c new file mode 100644 index 0000000..ef82f83 --- /dev/null +++ b/ntoskrnl/ex/lookas.c @@ -0,0 +1,320 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/lookas.c + * PURPOSE: Lookaside lists + * PROGRAMMERS: David Welch (welch@mcmail.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 22-05-1998 DW Created + * 02-07-2001 CSH Implemented lookaside lists + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +LIST_ENTRY ExpNonPagedLookasideListHead; +KSPIN_LOCK ExpNonPagedLookasideListLock; + +LIST_ENTRY ExpPagedLookasideListHead; +KSPIN_LOCK ExpPagedLookasideListLock; + +PLOOKASIDE_MINMAX_ROUTINE ExpMinMaxRoutine; + +/* FUNCTIONS *****************************************************************/ + +VOID ExpDefaultMinMax( + POOL_TYPE PoolType, + ULONG Size, + PUSHORT MinimumDepth, + PUSHORT MaximumDepth) +/* + * FUNCTION: Determines the minimum and maximum depth of a new lookaside list + * ARGUMENTS: + * Type = Type of executive pool + * Size = Size in bytes of each element in the new lookaside list + * MinimumDepth = Buffer to store minimum depth of the new lookaside list in + * MaximumDepth = Buffer to store maximum depth of the new lookaside list in + */ +{ + /* FIXME: Could probably do some serious computing here */ + if ((PoolType == NonPagedPool) || + (PoolType == NonPagedPoolMustSucceed)) + { + *MinimumDepth = 10; + *MaximumDepth = 100; + } + else + { + *MinimumDepth = 20; + *MaximumDepth = 200; + } +} + + +PVOID STDCALL +ExpDefaultAllocate(POOL_TYPE PoolType, + ULONG NumberOfBytes, + ULONG Tag) +/* + * FUNCTION: Default allocate function for lookaside lists + * ARGUMENTS: + * Type = Type of executive pool + * NumberOfBytes = Number of bytes to allocate + * Tag = Tag to use + * RETURNS: + * Pointer to allocated memory, or NULL if there is not enough free resources + */ +{ + return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); +} + + +VOID STDCALL +ExpDefaultFree(PVOID Buffer) +/* + * FUNCTION: Default free function for lookaside lists + * ARGUMENTS: + * Buffer = Pointer to memory to free + */ +{ + return ExFreePool(Buffer); +} + + +VOID +ExpInitLookasideLists() +{ + InitializeListHead(&ExpNonPagedLookasideListHead); + KeInitializeSpinLock(&ExpNonPagedLookasideListLock); + + InitializeListHead(&ExpPagedLookasideListHead); + KeInitializeSpinLock(&ExpPagedLookasideListLock); + + /* FIXME: Possibly configure the algorithm using the registry */ + ExpMinMaxRoutine = ExpDefaultMinMax; +} + +PVOID +STDCALL +ExAllocateFromPagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside + ) +{ + PVOID Entry; + + /* Try to obtain an entry from the lookaside list. If that fails, try to + allocate a new entry with the allocate method for the lookaside list */ + + Lookaside->TotalAllocates++; + +// ExAcquireFastMutex(&Lookaside->Lock); + + Entry = PopEntrySList(&Lookaside->ListHead); + +// ExReleaseFastMutex(&Lookaside->Lock); + + if (Entry) + return Entry; + + Lookaside->AllocateMisses++; + + Entry = (*Lookaside->Allocate)(Lookaside->Type, + Lookaside->Size, + Lookaside->Tag); + + return Entry; +} + +VOID +STDCALL +ExDeleteNPagedLookasideList ( + PNPAGED_LOOKASIDE_LIST Lookaside + ) +{ + KIRQL OldIrql; + PVOID Entry; + + /* Pop all entries off the stack and release the resources allocated + for them */ + while ((Entry = ExInterlockedPopEntrySList( + &Lookaside->ListHead, + &Lookaside->Lock)) != NULL) + { + (*Lookaside->Free)(Entry); + } + + KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql); + RemoveEntryList(&Lookaside->ListEntry); + KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql); +} + +VOID +STDCALL +ExDeletePagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside + ) +{ + KIRQL OldIrql; + PVOID Entry; + + /* Pop all entries off the stack and release the resources allocated + for them */ + for (;;) + { + +// ExAcquireFastMutex(&Lookaside->Lock); + + Entry = PopEntrySList(&Lookaside->ListHead); + if (!Entry) + break; + +// ExReleaseFastMutex(&Lookaside->Lock); + + (*Lookaside->Free)(Entry); + } + + KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql); + RemoveEntryList(&Lookaside->ListEntry); + KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql); +} + +VOID +STDCALL +ExFreeToPagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside, + PVOID Entry + ) +{ + Lookaside->TotalFrees++; + + if (ExQueryDepthSList(&Lookaside->ListHead) >= Lookaside->MinimumDepth) + { + Lookaside->FreeMisses++; + (*Lookaside->Free)(Entry); + } + else + { +// ExAcquireFastMutex(&Lookaside->Lock); + PushEntrySList(&Lookaside->ListHead, (PSINGLE_LIST_ENTRY)Entry); +// ExReleaseFastMutex(&Lookaside->Lock); + } +} + +VOID +STDCALL +ExInitializeNPagedLookasideList ( + PNPAGED_LOOKASIDE_LIST Lookaside, + PALLOCATE_FUNCTION Allocate, + PFREE_FUNCTION Free, + ULONG Flags, + ULONG Size, + ULONG Tag, + USHORT Depth) +{ + DPRINT("Initializing nonpaged lookaside list at 0x%X\n", Lookaside); + + Lookaside->TotalAllocates = 0; + Lookaside->AllocateMisses = 0; + Lookaside->TotalFrees = 0; + Lookaside->FreeMisses = 0; + Lookaside->Type = NonPagedPool; + Lookaside->Tag = Tag; + + /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in + the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */ + if (Size < sizeof(SINGLE_LIST_ENTRY)) + Lookaside->Size = sizeof(SINGLE_LIST_ENTRY); + else + Lookaside->Size = Size; + + if (Allocate) + Lookaside->Allocate = Allocate; + else + Lookaside->Allocate = ExpDefaultAllocate; + + if (Free) + Lookaside->Free = Free; + else + Lookaside->Free = ExpDefaultFree; + + ExInitializeSListHead(&Lookaside->ListHead); + KeInitializeSpinLock(&Lookaside->Lock); + + /* Determine minimum and maximum number of entries on the lookaside list + using the configured algorithm */ + (*ExpMinMaxRoutine)( + NonPagedPool, + Lookaside->Size, + &Lookaside->MinimumDepth, + &Lookaside->MaximumDepth); + + ExInterlockedInsertTailList( + &ExpNonPagedLookasideListHead, + &Lookaside->ListEntry, + &ExpNonPagedLookasideListLock); +} + +VOID +STDCALL +ExInitializePagedLookasideList ( + PPAGED_LOOKASIDE_LIST Lookaside, + PALLOCATE_FUNCTION Allocate, + PFREE_FUNCTION Free, + ULONG Flags, + ULONG Size, + ULONG Tag, + USHORT Depth + ) +{ + DPRINT("Initializing paged lookaside list at 0x%X\n", Lookaside); + + Lookaside->TotalAllocates = 0; + Lookaside->AllocateMisses = 0; + Lookaside->TotalFrees = 0; + Lookaside->FreeMisses = 0; + Lookaside->Type = PagedPool; + Lookaside->Tag = Tag; + + /* We use a field of type SINGLE_LIST_ENTRY as a link to the next entry in + the lookaside list so we must allocate at least sizeof(SINGLE_LIST_ENTRY) */ + if (Size < sizeof(SINGLE_LIST_ENTRY)) + Lookaside->Size = sizeof(SINGLE_LIST_ENTRY); + else + Lookaside->Size = Size; + + if (Allocate) + Lookaside->Allocate = Allocate; + else + Lookaside->Allocate = ExpDefaultAllocate; + + if (Free) + Lookaside->Free = Free; + else + Lookaside->Free = ExpDefaultFree; + + ExInitializeSListHead(&Lookaside->ListHead); + //ExInitializeFastMutex(&Lookaside->Lock); + + /* Determine minimum and maximum number of entries on the lookaside list + using the configured algorithm */ + (*ExpMinMaxRoutine)( + PagedPool, + Lookaside->Size, + &Lookaside->MinimumDepth, + &Lookaside->MaximumDepth); + + ExInterlockedInsertTailList( + &ExpPagedLookasideListHead, + &Lookaside->ListEntry, + &ExpPagedLookasideListLock); +} + +/* EOF */ diff --git a/ntoskrnl/ex/napi.c b/ntoskrnl/ex/napi.c new file mode 100644 index 0000000..ae64d80 --- /dev/null +++ b/ntoskrnl/ex/napi.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/napi.c + * PURPOSE: Native API support routines + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +/* GLOBALS ******************************************************************/ + +#include +#include + +/* GLOBALS *****************************************************************/ + +KE_SERVICE_DESCRIPTOR_TABLE_ENTRY +__declspec(dllexport) +KeServiceDescriptorTable[SSDT_MAX_ENTRIES] = +{ + { MainSSDT, NULL, NUMBER_OF_SYSCALLS, MainSSPT }, + { NULL, NULL, 0, NULL }, + { NULL, NULL, 0, NULL }, + { NULL, NULL, 0, NULL } +}; + +KE_SERVICE_DESCRIPTOR_TABLE_ENTRY +KeServiceDescriptorTableShadow[SSDT_MAX_ENTRIES] = +{ + { MainSSDT, NULL, NUMBER_OF_SYSCALLS, MainSSPT }, + { NULL, NULL, 0, NULL }, + { NULL, NULL, 0, NULL }, + { NULL, NULL, 0, NULL } +}; diff --git a/ntoskrnl/ex/power.c b/ntoskrnl/ex/power.c new file mode 100644 index 0000000..34c63a6 --- /dev/null +++ b/ntoskrnl/ex/power.c @@ -0,0 +1,68 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/power.c + * PURPOSE: Power managment + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + * Added reboot support 30/01/99 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtSetSystemPowerState(IN POWER_ACTION SystemAction, + IN SYSTEM_POWER_STATE MinSystemState, + IN ULONG Flags) +{ + /* Windows 2000 only */ + return(STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS STDCALL +NtShutdownSystem(IN SHUTDOWN_ACTION Action) +{ + if (Action > ShutdownPowerOff) + return STATUS_INVALID_PARAMETER; + + IoShutdownRegisteredDevices(); + CmShutdownRegistry(); + IoShutdownRegisteredFileSystems(); + PiShutdownProcessManager(); + MiShutdownMemoryManager(); + + if (Action == ShutdownNoReboot) + { +#if 0 + /* Switch off */ + HalReturnToFirmware (FIRMWARE_OFF); +#else + PopSetSystemPowerState(PowerSystemShutdown); +#endif + } + else if (Action == ShutdownReboot) + { + HalReturnToFirmware (FIRMWARE_REBOOT); + } + else + { + HalReturnToFirmware (FIRMWARE_HALT); + } + + return STATUS_SUCCESS; +} + +/* EOF */ + diff --git a/ntoskrnl/ex/resource.c b/ntoskrnl/ex/resource.c new file mode 100644 index 0000000..d0cbb1f --- /dev/null +++ b/ntoskrnl/ex/resource.c @@ -0,0 +1,798 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/resource.c + * PURPOSE: Resource synchronization construct + * PROGRAMMER: Unknown + * UPDATE HISTORY: + * Created 22/05/98 + */ + + +/* + * Usage of ERESOURCE members is not documented. + * From names of members and functionnalities, we can assume : + * + * OwnerTable = list of threads who have shared access(if more than one) + * ActiveCount = number of threads who have access to the resource + * Flag = bits : ResourceOwnedExclusive=0x80 + * ResourceNeverExclusive=0x10 + * ResourceReleaseByOtherThread=0x20 + * ResourceDisableBoost=0x08 + * SharedWaiters = semaphore, used to manage wait list of shared waiters. + * ExclusiveWaiters = event, used to manage wait list of exclusive waiters. + * OwnerThreads[0]= thread who have exclusive access + * OwnerThreads[1]= if only one thread own the resource + * thread who have shared access + * else + * OwnerThread=0 + * and TableSize = number of entries in the owner table + * NumberOfExclusiveWaiters = number of threads waiting for exclusive access. + * NumberOfSharedWaiters = number of threads waiting for exclusive access. + * + */ + +#define ResourceOwnedExclusive 0x80 +#define ResourceDisableBoost 0x08 + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_OWNER_TABLE TAG('R', 'O', 'W', 'N') +#define TAG_EXCLUSIVE_LOCK TAG('E', 'R', 'E', 'L') +#define TAG_SHARED_SEM TAG('E', 'R', 'S', 'S') + +/* FUNCTIONS *****************************************************************/ + + +BOOLEAN +STDCALL +ExTryToAcquireResourceExclusiveLite ( + PERESOURCE Resource + ) +/* + * FUNCTION: Attempts to require the resource for exclusive access + * ARGUMENTS: + * Resource = Points to the resource of be acquired + * RETURNS: TRUE if the resource was acquired for the caller + * NOTES: Must be acquired at IRQL < DISPATCH_LEVEL + */ +{ + return(ExAcquireResourceExclusiveLite(Resource,FALSE)); +} + +BOOLEAN +STDCALL +ExAcquireResourceExclusive ( + PERESOURCE Resource, + BOOLEAN Wait + ) +{ + return(ExAcquireResourceExclusiveLite(Resource,Wait)); +} + +BOOLEAN +STDCALL +ExAcquireResourceExclusiveLite ( + PERESOURCE Resource, + BOOLEAN Wait + ) +/* + * FUNCTION: Acquires a resource exclusively for the calling thread + * ARGUMENTS: + * Resource = Points to the resource to acquire + * Wait = Is set to TRUE if the caller should wait to acquire the + * resource if it can't be acquired immediately + * RETURNS: TRUE if the resource was acquired, + * FALSE otherwise + * NOTES: Must be called at IRQL < DISPATCH_LEVEL + */ +{ + KIRQL oldIrql; + + DPRINT("ExAcquireResourceExclusiveLite(Resource %x, Wait %d)\n", + Resource, Wait); + + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + + /* resource already locked */ + if((Resource->Flag & ResourceOwnedExclusive) + && Resource->OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) + { + /* it's ok : same lock for same thread */ + Resource->OwnerThreads[0].a.OwnerCount++; + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n"); + return(TRUE); + } + + if (Resource->ActiveCount && !Wait) + { + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceExclusiveLite() = FALSE\n"); + return(FALSE); + } + + /* + * This is slightly better than it looks because other exclusive + * threads who are waiting won't be woken up but there is a race + * with new threads trying to grab the resource so we must have + * the spinlock, still normally this loop will only be executed + * once + * NOTE: We might want to set a timeout to detect deadlock + * (10 minutes?) + */ + while (Resource->ActiveCount) + { + Resource->NumberOfExclusiveWaiters++; + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + KeWaitForSingleObject(Resource->ExclusiveWaiters, + Executive, + KernelMode, + FALSE, + NULL); + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + Resource->NumberOfExclusiveWaiters--; + } + Resource->Flag |= ResourceOwnedExclusive; + Resource->ActiveCount = 1; + Resource->OwnerThreads[0].OwnerThread = ExGetCurrentResourceThread(); + Resource->OwnerThreads[0].a.OwnerCount = 1; + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceExclusiveLite() = TRUE\n"); + return(TRUE); +} + +static BOOLEAN EiRemoveSharedOwner(PERESOURCE Resource, + ERESOURCE_THREAD ResourceThreadId) +/* + * FUNCTION: Removes the current thread from the shared owners of the resource + * ARGUMENTS: + * Resource = Pointer to the resource for which the thread is to be + * added + * NOTE: Must be called with the resource spinlock held + */ +{ + ULONG i; + + if (Resource->OwnerThreads[1].OwnerThread == ResourceThreadId) + { + Resource->OwnerThreads[1].a.OwnerCount--; + if (Resource->OwnerThreads[1].a.OwnerCount == 0) + { + Resource->ActiveCount--; + Resource->OwnerThreads[1].OwnerThread = 0; + } + return(TRUE); + } + + if (Resource->OwnerThreads[1].OwnerThread) + { + /* Oh dear, the caller didn't own the resource after all */ + return(FALSE);; + } + + for (i=0; iOwnerThreads[1].a.TableSize; i++) + { + if (Resource->OwnerTable[i].OwnerThread == ResourceThreadId) + { + Resource->OwnerTable[i].a.OwnerCount--; + if (Resource->OwnerTable[i].a.OwnerCount == 0) + { + Resource->ActiveCount--; + Resource->OwnerTable[i].OwnerThread = 0; + } + return TRUE; + } + } + return(FALSE); +} + +static BOOLEAN EiAddSharedOwner(PERESOURCE Resource) +/* + * FUNCTION: Adds the current thread to the shared owners of the resource + * ARGUMENTS: + * Resource = Pointer to the resource for which the thread is to be + * added + * NOTE: Must be called with the resource spinlock held + */ +{ + ERESOURCE_THREAD CurrentThread = ExGetCurrentResourceThread(); + POWNER_ENTRY freeEntry; + ULONG i = 0; + + DPRINT("EiAddSharedOwner(Resource %x)\n", Resource); + + if (Resource->ActiveCount == 0) + { + /* no owner, it's easy */ + Resource->OwnerThreads[1].OwnerThread = ExGetCurrentResourceThread(); + Resource->OwnerThreads[1].a.OwnerCount = 1; + if (Resource->OwnerTable != NULL) + { + ExFreePool(Resource->OwnerTable); + } + Resource->OwnerTable = NULL; + Resource->ActiveCount = 1; + DPRINT("EiAddSharedOwner() = TRUE\n"); + return(TRUE); + } + + /* + * now, we must search if this thread has already acquired this resource + * then increase ownercount if found, else create new entry or reuse free + * entry + */ + if (Resource->OwnerTable == NULL) + { + DPRINT("Creating owner table\n"); + + /* allocate ownertable,memset to 0, initialize first entry */ + Resource->OwnerTable = + ExAllocatePoolWithTag(NonPagedPool, sizeof(OWNER_ENTRY)*3, + TAG_OWNER_TABLE); + if (Resource->OwnerTable == NULL) + { + KeBugCheck(0); + return(FALSE); + } + memset(Resource->OwnerTable,0,sizeof(OWNER_ENTRY)*3); + memcpy(&Resource->OwnerTable[0], &Resource->OwnerThreads[1], + sizeof(OWNER_ENTRY)); + + Resource->OwnerThreads[1].OwnerThread = 0; + Resource->OwnerThreads[1].a.TableSize = 3; + + Resource->OwnerTable[1].OwnerThread = CurrentThread; + Resource->OwnerTable[1].a.OwnerCount = 1; + Resource->ActiveCount++; + + return(TRUE); + } + + DPRINT("Search free entries\n"); + + DPRINT("Number of entries %d\n", + Resource->OwnerThreads[1].a.TableSize); + + freeEntry = NULL; + for (i=0; iOwnerThreads[1].a.TableSize; i++) + { + if (Resource->OwnerTable[i].OwnerThread == CurrentThread) + { + DPRINT("Thread already owns resource\n"); + Resource->OwnerTable[i].a.OwnerCount++; + return(TRUE); + } + if (Resource->OwnerTable[i].OwnerThread == 0) + { + freeEntry = &Resource->OwnerTable[i]; + break; + } + } + + DPRINT("Found free entry %x\n", freeEntry); + + if (!freeEntry) + { + DPRINT("Allocating new entry\n"); + + /* reallocate ownertable with one more entry */ + freeEntry = + ExAllocatePoolWithTag(NonPagedPool, + sizeof(OWNER_ENTRY)* + (Resource->OwnerThreads[1].a.TableSize+1), + TAG_OWNER_TABLE); + if (freeEntry == NULL) + { + KeBugCheck(0); + return(FALSE); + } + memcpy(freeEntry,Resource->OwnerTable, + sizeof(OWNER_ENTRY)*(Resource->OwnerThreads[1].a.TableSize)); + ExFreePool(Resource->OwnerTable); + Resource->OwnerTable=freeEntry; + freeEntry=&Resource->OwnerTable[Resource->OwnerThreads[1].a.TableSize]; + Resource->OwnerThreads[1].a.TableSize++; + } + DPRINT("Creating entry\n"); + freeEntry->OwnerThread=ExGetCurrentResourceThread(); + freeEntry->a.OwnerCount=1; + Resource->ActiveCount++; + return(TRUE); +} + +BOOLEAN +STDCALL +ExAcquireResourceSharedLite ( + PERESOURCE Resource, + BOOLEAN Wait + ) +/* + * FUNCTION: Acquires the given resource for shared access by the calling + * thread + * ARGUMENTS: + * Resource = Points to the resource to acquire + * Wait = Is set to TRUE if the caller should be put into wait state + * until the resource can be acquired if it cannot be acquired + * immediately + * RETURNS: TRUE, if the resource is acquire + * FALSE otherwise + */ +{ + KIRQL oldIrql; + + DPRINT("ExAcquireResourceSharedLite(Resource %x, Wait %d)\n", + Resource, Wait); + + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + + /* first, resolve trivial cases */ + if (Resource->ActiveCount == 0) + { + EiAddSharedOwner(Resource); + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceSharedLite() = TRUE\n"); + return(TRUE); + } + + if ((Resource->Flag & ResourceOwnedExclusive) + && Resource->OwnerThreads[0].OwnerThread==ExGetCurrentResourceThread()) + { + /* exclusive, but by same thread : it's ok */ + /* + * NOTE: Is this correct? Seems the same as ExConvertExclusiveToShared + */ + Resource->OwnerThreads[0].a.OwnerCount++; + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceSharedLite() = TRUE\n"); + return(TRUE); + } + + if ((Resource->Flag & ResourceOwnedExclusive) + || Resource->NumberOfExclusiveWaiters) + { + /* exclusive by another thread , or thread waiting for exclusive */ + if (!Wait) + { + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceSharedLite() = FALSE\n"); + return(FALSE); + } + else + { + Resource->NumberOfSharedWaiters++; + do + { + /* wait for the semaphore */ + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + KeWaitForSingleObject(Resource->SharedWaiters,0, KernelMode, FALSE, NULL); + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + /* the spin lock was released we must check again */ + } + while ((Resource->Flag & ResourceOwnedExclusive) + || Resource->NumberOfExclusiveWaiters); + Resource->NumberOfSharedWaiters--; + } + } + + EiAddSharedOwner(Resource); + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireResourceSharedLite() = TRUE\n"); + return(TRUE); +} + +VOID +STDCALL +ExConvertExclusiveToSharedLite ( + PERESOURCE Resource + ) +/* + * FUNCTION: Converts a given resource from acquired for exclusive access + * to acquire for shared access + * ARGUMENTS: + * Resource = Points to the resource for which the access should be + * converted + * NOTES: Caller must be running at IRQL < DISPATCH_LEVEL + */ +{ + ULONG oldWaiters; + KIRQL oldIrql; + + DPRINT("ExConvertExclusiveToSharedLite(Resource %x)\n", Resource); + + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + + oldWaiters = Resource->NumberOfSharedWaiters; + + if (!(Resource->Flag & ResourceOwnedExclusive)) + { + /* Might not be what the caller expects, better bug check */ + KeBugCheck(0); + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + return; + } + + //transfer infos from entry 0 to entry 1 and erase entry 0 + Resource->OwnerThreads[1].OwnerThread=Resource->OwnerThreads[0].OwnerThread; + Resource->OwnerThreads[1].a.OwnerCount=Resource->OwnerThreads[0].a.OwnerCount; + Resource->OwnerThreads[0].OwnerThread=0; + Resource->OwnerThreads[0].a.OwnerCount=0; + /* erase exclusive flag */ + Resource->Flag &= (~ResourceOwnedExclusive); + /* if no shared waiters, that's all */ + if (!oldWaiters) + { + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + return; + } + /* else, awake the waiters */ + KeReleaseSemaphore(Resource->SharedWaiters,0,oldWaiters,0); + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExConvertExclusiveToSharedLite() finished\n"); +} + +VOID +STDCALL +ExDisableResourceBoostLite ( + PERESOURCE Resource + ) +{ + Resource->Flag |= ResourceDisableBoost; +} + +ULONG +STDCALL +ExGetExclusiveWaiterCount ( + PERESOURCE Resource + ) +{ + return(Resource->NumberOfExclusiveWaiters); +} + +BOOLEAN +STDCALL +ExAcquireSharedStarveExclusive ( + PERESOURCE Resource, + BOOLEAN Wait + ) +/* + * FUNCTION: Acquires a given resource for shared access without waiting + * for any pending attempts to acquire exclusive access to the + * same resource + * ARGUMENTS: + * Resource = Points to the resource to be acquired for shared access + * Wait = Is set to TRUE if the caller will wait until the resource + * becomes available when access can't be granted immediately + * RETURNS: TRUE if the requested access is granted. The routine returns + * FALSE if the input Wait is FALSE and shared access can't be + * granted immediately + */ +{ + KIRQL oldIrql; + + DPRINT("ExAcquireSharedStarveExclusive(Resource %x, Wait %d)\n", + Resource, Wait); + + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + + /* no owner, it's easy */ + if (Resource->ActiveCount == 0) + { + Resource->OwnerThreads[1].OwnerThread=ExGetCurrentResourceThread(); + Resource->OwnerThreads[1].a.OwnerCount=1; + Resource->ActiveCount=1; + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n"); + return(TRUE); + } + + if ((Resource->Flag & ResourceOwnedExclusive) + && Resource->OwnerThreads[0].OwnerThread==ExGetCurrentResourceThread()) + { + /* exclusive, but by same thread : it's ok */ + Resource->OwnerThreads[0].a.OwnerCount++; + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n"); + return(TRUE); + } + + if (Resource->Flag & ResourceOwnedExclusive) + { + /* exclusive by another thread */ + if (!Wait) + { + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireSharedStarveExclusive() = FALSE\n"); + return(FALSE); + } + else + { + Resource->NumberOfSharedWaiters++; + /* wait for the semaphore */ + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + KeWaitForSingleObject(Resource->SharedWaiters,0,0,0,0); + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + Resource->NumberOfSharedWaiters--; + } + } + EiAddSharedOwner(Resource); + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExAcquireSharedStarveExclusive() = TRUE\n"); + return(TRUE); +} + +BOOLEAN +STDCALL +ExAcquireSharedWaitForExclusive ( + PERESOURCE Resource, + BOOLEAN Wait + ) +{ + return(ExAcquireResourceSharedLite(Resource,Wait)); +} + +NTSTATUS +STDCALL +ExDeleteResource ( + PERESOURCE Resource + ) +{ + return(ExDeleteResourceLite(Resource)); +} + +NTSTATUS +STDCALL +ExDeleteResourceLite ( + PERESOURCE Resource + ) +{ + DPRINT("ExDeleteResourceLite(Resource %x)\n", Resource); + if (Resource->OwnerTable) ExFreePool(Resource->OwnerTable); + if (Resource->SharedWaiters) ExFreePool(Resource->SharedWaiters); + if (Resource->ExclusiveWaiters) ExFreePool(Resource->ExclusiveWaiters); + return(STATUS_SUCCESS);; +} + +ULONG +STDCALL +ExGetSharedWaiterCount ( + PERESOURCE Resource + ) +{ + return(Resource->NumberOfSharedWaiters); +} + +NTSTATUS +STDCALL +ExInitializeResource ( + PERESOURCE Resource + ) +{ + return(ExInitializeResourceLite(Resource)); +} + +NTSTATUS STDCALL +ExInitializeResourceLite (PERESOURCE Resource) +{ + DPRINT("ExInitializeResourceLite(Resource %x)\n", Resource); + memset(Resource,0,sizeof(ERESOURCE)); + Resource->NumberOfSharedWaiters = 0; + Resource->NumberOfExclusiveWaiters = 0; + KeInitializeSpinLock(&Resource->SpinLock); + Resource->Flag = 0; + Resource->ExclusiveWaiters = + ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_EXCLUSIVE_LOCK); + KeInitializeEvent(Resource->ExclusiveWaiters, + SynchronizationEvent, + FALSE); + Resource->SharedWaiters = + ExAllocatePoolWithTag(NonPagedPool ,sizeof(KSEMAPHORE), TAG_SHARED_SEM); + KeInitializeSemaphore(Resource->SharedWaiters,0,0x7fffffff); + Resource->ActiveCount = 0; + return(0); +} + +BOOLEAN +STDCALL +ExIsResourceAcquiredExclusiveLite ( + PERESOURCE Resource + ) +/* + * FUNCTION: Returns whether the current thread has exclusive access to + * a given resource + * ARGUMENTS: + * Resource = Points to the resource to be queried + * RETURNS: TRUE if the caller has exclusive access to the resource, + * FALSE otherwise + */ +{ + return((Resource->Flag & ResourceOwnedExclusive) + && Resource->OwnerThreads[0].OwnerThread==ExGetCurrentResourceThread()); +} + +ULONG +STDCALL +ExIsResourceAcquiredSharedLite ( + PERESOURCE Resource + ) +/* + * FUNCTION: Returns whether the current thread has shared access to a given + * resource + * ARGUMENTS: + * Resource = Points to the resource to be queried + * RETURNS: The number of times the caller has acquired shared access to the + * given resource + */ +{ + ULONG i; + if (Resource->OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) + { + return(Resource->OwnerThreads[0].a.OwnerCount); + } + if (Resource->OwnerThreads[1].OwnerThread == ExGetCurrentResourceThread()) + { + return(Resource->OwnerThreads[1].a.OwnerCount); + } + if (!Resource->OwnerThreads[1].a.TableSize) + { + return(0); + } + for (i=0; iOwnerThreads[1].a.TableSize; i++) + { + if (Resource->OwnerTable[i].OwnerThread==ExGetCurrentResourceThread()) + { + return Resource->OwnerTable[i].a.OwnerCount; + } + } + return(0); +} + +VOID +STDCALL +ExReinitializeResourceLite ( + PERESOURCE Resource + ) +{ + Resource->NumberOfSharedWaiters = 0; + Resource->NumberOfExclusiveWaiters = 0; + KeInitializeSpinLock(&Resource->SpinLock); + Resource->Flag=0; + KeInitializeEvent(Resource->ExclusiveWaiters,SynchronizationEvent, + FALSE); + KeInitializeSemaphore(Resource->SharedWaiters,0,0x7fffffff); + Resource->ActiveCount = 0; + if (Resource->OwnerTable) + { + ExFreePool(Resource->OwnerTable); + } + Resource->OwnerThreads[0].OwnerThread=0; + Resource->OwnerThreads[0].a.OwnerCount=0; + Resource->OwnerThreads[1].OwnerThread=0; + Resource->OwnerThreads[1].a.OwnerCount=0; +} + +VOID +FASTCALL +ExReleaseResourceLite ( + PERESOURCE Resource + ) +{ + return(ExReleaseResourceForThreadLite(Resource, + ExGetCurrentResourceThread())); +} + +VOID +STDCALL +ExReleaseResourceForThread ( + PERESOURCE Resource, + ERESOURCE_THREAD ResourceThreadId + ) +{ + return(ExReleaseResourceForThreadLite(Resource,ResourceThreadId)); +} + +VOID +STDCALL +ExReleaseResourceForThreadLite ( + PERESOURCE Resource, + ERESOURCE_THREAD ResourceThreadId + ) +/* + * FUNCTION: Releases a resource for the given thread + * ARGUMENTS: + * Resource = Points to the release to release + * ResourceThreadId = Identifies the thread that originally acquired + * the resource + * NOTES: Must be running at IRQL < DISPATCH_LEVEL + * BUG: We don't support starving exclusive waiters + */ +{ + KIRQL oldIrql; + + DPRINT("ExReleaseResourceForThreadLite(Resource %x, ResourceThreadId %x)\n", + Resource, ResourceThreadId); + + KeAcquireSpinLock(&Resource->SpinLock, &oldIrql); + + if (Resource->Flag & ResourceOwnedExclusive) + { + DPRINT("Releasing from exclusive access\n"); + + Resource->OwnerThreads[0].a.OwnerCount--; + if (Resource->OwnerThreads[0].a.OwnerCount > 0) + { + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExReleaseResourceForThreadLite() finished\n"); + return; + } + + Resource->OwnerThreads[0].OwnerThread = 0; + Resource->ActiveCount--; + Resource->Flag &=(~ResourceOwnedExclusive); + assert(Resource->ActiveCount == 0); + DPRINT("Resource->NumberOfExclusiveWaiters %d\n", + Resource->NumberOfExclusiveWaiters); + if (Resource->NumberOfExclusiveWaiters) + { + /* get resource to first exclusive waiter */ + KeSetEvent(Resource->ExclusiveWaiters, + IO_NO_INCREMENT, + FALSE); + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExReleaseResourceForThreadLite() finished\n"); + return; + } + DPRINT("Resource->NumberOfSharedWaiters %d\n", + Resource->NumberOfSharedWaiters); + if (Resource->NumberOfSharedWaiters) + { + DPRINT("Releasing semaphore\n"); + KeReleaseSemaphore(Resource->SharedWaiters, + IO_NO_INCREMENT, + Resource->NumberOfSharedWaiters, + FALSE); + } + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExReleaseResourceForThreadLite() finished\n"); + return; + } + + EiRemoveSharedOwner(Resource, ResourceThreadId); + + if (Resource->ActiveCount == 0) + { + if (Resource->NumberOfExclusiveWaiters) + { + /* get resource to first exclusive waiter */ + KeSetEvent(Resource->ExclusiveWaiters, + IO_NO_INCREMENT, + FALSE); + } + } + + KeReleaseSpinLock(&Resource->SpinLock, oldIrql); + DPRINT("ExReleaseResourceForThreadLite() finished\n"); +} + + +VOID +STDCALL +ExSetResourceOwnerPointer ( + IN PERESOURCE Resource, + IN PVOID OwnerPointer + ) +{ + +} + +/* EOF */ diff --git a/ntoskrnl/ex/stree.c b/ntoskrnl/ex/stree.c new file mode 100644 index 0000000..2342756 --- /dev/null +++ b/ntoskrnl/ex/stree.c @@ -0,0 +1,1356 @@ +/* + * ReactOS kernel + * Copyright (C) 1998-2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: stree.c + * PURPOSE: Splay tree support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: Based on a splay tree implementation by + * Daniel Stenberg + * http://www.contactor.se/~dast/stuff/dsplay-1.2.tar.gz + * UPDATE HISTORY: + * 15-03-2002 CSH Created + */ +#include +#include + +#define NDEBUG +#include + +/* DATA **********************************************************************/ + +#define WEIGHT 1 +#undef UNIQUE_KEYS + +typedef struct _SPLAY_TREE_NODE +{ + /* Children on this branch that has smaller keys than this node */ + struct _SPLAY_TREE_NODE * SmallerChild; + + /* Children on this branch that has larger keys than this node */ + struct _SPLAY_TREE_NODE * LargerChild; + + /* Points to a node with identical key */ + struct _SPLAY_TREE_NODE * Same; + + /* Key of this node */ + PVOID Key; + + /* Value of this node */ + PVOID Value; + + /* The number of nodes rooted here */ + LONG Weight; +} SPLAY_TREE_NODE, *PSPLAY_TREE_NODE; + +typedef struct _TRAVERSE_CONTEXT { + PTRAVERSE_ROUTINE Routine; + PVOID Context; +} TRAVERSE_CONTEXT, *PTRAVERSE_CONTEXT; + +#define SPLAY_INDEX 0 +#define SEARCH_INDEX 1 +#define INSERT_INDEX 2 +#define REMOVE_INDEX 3 + +typedef PSPLAY_TREE_NODE (*PSPLAY_TREE_SPLAY)(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node); + +typedef BOOLEAN (*PSPLAY_TREE_SEARCH)(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * ReturnNode); + +typedef PSPLAY_TREE_NODE (*PSPLAY_TREE_INSERT)(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE New); + +typedef PSPLAY_TREE_NODE (*PSPLAY_TREE_REMOVE)(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * RemovedNode); + +/* FUNCTIONS ****************************************************************/ + +#define ExpSplayTreeRootNode(Tree)(((PSPLAY_TREE) (Tree))->RootNode) +#define ExpSplayTreeNodeKey(Node)((Node)->Key) +#define ExpSplayTreeNodeValue(Node)((Node)->Value) +#define ExpSplayTreeSmallerChildNode(Node)((Node)->SmallerChild) +#define ExpSplayTreeLargerChildNode(Node)((Node)->LargerChild) +#define ExpSplayTreeNodeEqual(Equality)((Equality) == 0) +#define ExpSplayTreeNodeLess(Equality)((Equality) < 0) +#define ExpSplayTreeNodeMore(Equality)((Equality) > 0) +#define ExpSplayTreeNodeSame(Node)((Node)->Same) +#define ExpSplayTreeNodeWeight(Node)((Node)->Weight) +#define ExpSplayTreeNodeGetWeight(Node)(((Node) == NULL) ? 0 : ((Node)->Weight)) +#define ExpSplayTreeNodeSetWeight(Node, _Weight)((Node)->Weight = (_Weight)) + +#define KEY_NOTUSED (PVOID)-1 + + +/* + * Lock the splay tree + */ +inline VOID +ExpLockSplayTree(PSPLAY_TREE Tree, + PKIRQL OldIrql) +{ + if (Tree->UseNonPagedPool) + { + KeAcquireSpinLock(&Tree->Lock.NonPaged, OldIrql); + } + else + { + ExAcquireFastMutex(&Tree->Lock.Paged); + } +} + + +/* + * Unlock the splay tree + */ +inline VOID +ExpUnlockSplayTree(PSPLAY_TREE Tree, + PKIRQL OldIrql) +{ + if (Tree->UseNonPagedPool) + { + KeReleaseSpinLock(&Tree->Lock.NonPaged, *OldIrql); + } + else + { + ExReleaseFastMutex(&Tree->Lock.Paged); + } +} + + +/* + * Allocate resources for a new node and initialize it. + */ +inline PSPLAY_TREE_NODE +ExpCreateSplayTreeNode(PSPLAY_TREE Tree, + PVOID Value) +{ + PSPLAY_TREE_NODE Node; + + if (Tree->UseNonPagedPool) + { + Node = (PSPLAY_TREE_NODE) ExAllocateFromNPagedLookasideList(&Tree->List.NonPaged); + } + else + { + Node = (PSPLAY_TREE_NODE) ExAllocateFromPagedLookasideList(&Tree->List.Paged); + } + + if (Node) + { + ExpSplayTreeSmallerChildNode(Node) = NULL; + ExpSplayTreeLargerChildNode(Node) = NULL; + ExpSplayTreeNodeValue(Node) = Value; + } + + return Node; +} + +/* + * Release resources for the node. + */ +inline VOID +ExpDestroySplayTreeNode(PSPLAY_TREE Tree, + PSPLAY_TREE_NODE Node) +{ + if (Tree->UseNonPagedPool) + { + ExFreeToNPagedLookasideList(&Tree->List.NonPaged, Node); + } + else + { + ExFreeToPagedLookasideList(&Tree->List.Paged, Node); + } +} + + +/* + * Splay using the key 'Key' (which may or may not be in the tree). The starting + * root is Node. + * The lock for the tree must be acquired when this routine is called. + * This routine does not maintain weight information. + */ +PSPLAY_TREE_NODE +ExpSplayTreeNoWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node) +{ + PSPLAY_TREE_NODE l; + PSPLAY_TREE_NODE r; + PSPLAY_TREE_NODE y; + LONG ChildEquality; + SPLAY_TREE_NODE N; + LONG Equality; + + if (Node == NULL) + return Node; + + ExpSplayTreeSmallerChildNode(&N) = NULL; + ExpSplayTreeLargerChildNode(&N) = NULL; + l = &N; + r = &N; + + for (;;) + { + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + + if (ExpSplayTreeNodeLess(Equality)) + { + if (ExpSplayTreeSmallerChildNode(Node) == NULL) + break; + + ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeSmallerChildNode(Node))); + if (ExpSplayTreeNodeLess(ChildEquality)) + { + y = ExpSplayTreeSmallerChildNode(Node); /* Rotate smaller */ + ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(y); + ExpSplayTreeLargerChildNode(y) = Node; + + Node = y; + if (ExpSplayTreeSmallerChildNode(Node) == NULL) + break; + } + + ExpSplayTreeSmallerChildNode(r) = Node; /* Link smaller */ + r = Node; + Node = ExpSplayTreeSmallerChildNode(Node); + } + else if (ExpSplayTreeNodeMore(Equality)) + { + if (ExpSplayTreeLargerChildNode(Node) == NULL) + break; + + ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeLargerChildNode(Node))); + if (ExpSplayTreeNodeMore(ChildEquality)) + { + y = ExpSplayTreeLargerChildNode(Node); /* Rotate larger */ + ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(y); + ExpSplayTreeSmallerChildNode(y) = Node; + + Node = y; + if (ExpSplayTreeLargerChildNode(Node) == NULL) + break; + } + + ExpSplayTreeLargerChildNode(l) = Node; /* Link larger */ + l = Node; + Node = ExpSplayTreeLargerChildNode(Node); + } + else + { + break; + } + } + + ExpSplayTreeLargerChildNode(l) = NULL; + ExpSplayTreeSmallerChildNode(r) = NULL; + + ExpSplayTreeLargerChildNode(l) = ExpSplayTreeSmallerChildNode(Node); /* Assemble */ + ExpSplayTreeSmallerChildNode(r) = ExpSplayTreeLargerChildNode(Node); + ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(&N); + ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(&N); + + return Node; +} + + +/* + * Splay using the key 'Key' (which may or may not be in the tree). The starting + * root is Node. + * The lock for the tree must be acquired when this routine is called. + * This routine maintains weight information. + */ +PSPLAY_TREE_NODE +ExpSplayTreeWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node) +{ + PSPLAY_TREE_NODE l; + PSPLAY_TREE_NODE r; + PSPLAY_TREE_NODE y; + LONG ChildEquality; + SPLAY_TREE_NODE N; + LONG Equality; +#ifdef WEIGHT + LONG RootWeight; + LONG Weight1; + LONG Weight2; +#endif + + if (Node == NULL) + return Node; + + ExpSplayTreeSmallerChildNode(&N) = NULL; + ExpSplayTreeLargerChildNode(&N) = NULL; + l = &N; + r = &N; + +#ifdef WEIGHT + RootWeight = ExpSplayTreeNodeGetWeight(Node); + Weight1 = 0; + Weight2 = 0; +#endif + + for (;;) + { + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + + if (ExpSplayTreeNodeLess(Equality)) + { + if (ExpSplayTreeSmallerChildNode(Node) == NULL) + break; + + ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeSmallerChildNode(Node))); + if (ExpSplayTreeNodeLess(ChildEquality)) + { + y = ExpSplayTreeSmallerChildNode(Node); /* Rotate smaller */ + ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(y); + ExpSplayTreeLargerChildNode(y) = Node; + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(Node, ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)) + + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)) + 1); +#endif + + Node = y; + if (ExpSplayTreeSmallerChildNode(Node) == NULL) + break; + } + + ExpSplayTreeSmallerChildNode(r) = Node; /* Link smaller */ + r = Node; + Node = ExpSplayTreeSmallerChildNode(Node); + +#ifdef WEIGHT + Weight2 += 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(r)); +#endif + } + else if (ExpSplayTreeNodeMore(Equality)) + { + if (ExpSplayTreeLargerChildNode(Node) == NULL) + break; + + ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeLargerChildNode(Node))); + if (ExpSplayTreeNodeMore(ChildEquality)) + { + y = ExpSplayTreeLargerChildNode(Node); /* Rotate larger */ + ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(y); + ExpSplayTreeSmallerChildNode(y) = Node; + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(Node, ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)) + + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)) + 1); +#endif + + Node = y; + if (ExpSplayTreeLargerChildNode(Node) == NULL) + break; + } + + ExpSplayTreeLargerChildNode(l) = Node; /* Link larger */ + l = Node; + Node = ExpSplayTreeLargerChildNode(Node); + +#ifdef WEIGHT + Weight1 += 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(l)); +#endif + + } + else + { + break; + } + } + +#ifdef WEIGHT + Weight1 += ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)); /* Now Weight1 and Weight2 are the weights of */ + Weight2 += ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)); /* The 'smaller' and 'larger' trees we just built. */ + ExpSplayTreeNodeSetWeight(Node, Weight1 + Weight2 + 1); +#endif + + ExpSplayTreeLargerChildNode(l) = NULL; + ExpSplayTreeSmallerChildNode(r) = NULL; + +#ifdef WEIGHT + /* The following two loops correct the weight fields of the right path from + * the left child of the root and the right path from the left child of the + * root. + */ + for (y = ExpSplayTreeLargerChildNode(&N); y != NULL; y = ExpSplayTreeLargerChildNode(y)) { + ExpSplayTreeNodeSetWeight(y, Weight1); + Weight1 -= 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(y)); + } + for (y = ExpSplayTreeSmallerChildNode(&N); y != NULL; y = ExpSplayTreeSmallerChildNode(y)) { + ExpSplayTreeNodeSetWeight(y, Weight2); + Weight2 -= 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(y)); + } +#endif + + ExpSplayTreeLargerChildNode(l) = ExpSplayTreeSmallerChildNode(Node); /* Assemble */ + ExpSplayTreeSmallerChildNode(r) = ExpSplayTreeLargerChildNode(Node); + ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(&N); + ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(&N); + + return Node; +} + + +inline PSPLAY_TREE_NODE +ExpSplayTree(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node) +{ + return (*((PSPLAY_TREE_SPLAY)Tree->Reserved[SPLAY_INDEX]))(Tree, Key, Node); +} + + +/* + * The lock for the tree must be acquired when this routine is called. + * This routine does not maintain weight information. + */ +BOOLEAN +ExpSearchSplayTreeNoWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * ReturnNode) +{ + LONG Equality; + + if (Node == NULL) + return FALSE; + + Node = ExpSplayTree(Tree, Key, Node); + + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + if (ExpSplayTreeNodeEqual(Equality)) + { + /* Found the key */ + + *ReturnNode = Node; + return TRUE; + } + else + { + *ReturnNode = NULL; /* No match */ + return FALSE; /* It wasn't there */ + } +} + + +/* + * The lock for the tree must be acquired when this routine is called. + * This routine maintains weight information. + */ +BOOLEAN +ExpSearchSplayTreeWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * ReturnNode) +{ + PSPLAY_TREE_NODE x = NULL; + LONG Equality; +#ifdef WEIGHT + LONG tweight; +#endif + + if (Node == NULL) + return FALSE; + +#ifdef WEIGHT + tweight = ExpSplayTreeNodeGetWeight(Node); +#endif + + Node = ExpSplayTree(Tree, Key, Node); + + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + if (ExpSplayTreeNodeEqual(Equality)) + { + /* Found the key */ + +#ifdef WEIGHT + if (x != NULL) + { + ExpSplayTreeNodeSetWeight(x, tweight - 1); + } +#endif + + *ReturnNode = Node; + return TRUE; + } + else + { + *ReturnNode = NULL; /* No match */ + return FALSE; /* It wasn't there */ + } +} + + +inline BOOLEAN +ExpSearchSplayTree(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * ReturnNode) +{ + return (*((PSPLAY_TREE_SEARCH)Tree->Reserved[SEARCH_INDEX]))(Tree, Key, Node, ReturnNode); +} + + +/* + * The lock for the tree must be acquired when this routine is called. + * This routine does not maintain weight information. + */ +PSPLAY_TREE_NODE +ExpInsertSplayTreeNoWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE New) +{ + if (New == NULL) + return Node; + + if (Node != NULL) + { + LONG Equality; + + Node = ExpSplayTree(Tree, Key, Node); + + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + if (ExpSplayTreeNodeEqual(Equality)) + { + +#ifdef UNIQUE_KEYS + + /* This is how to prevent the same node key getting added twice */ + return NULL; + +#else + + /* It already exists one of this size */ + + ExpSplayTreeNodeSame(New) = Node; + ExpSplayTreeNodeKey(New) = Key; + ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); + ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); + + ExpSplayTreeSmallerChildNode(Node) = New; + ExpSplayTreeNodeKey(Node) = KEY_NOTUSED; + + /* New root node */ + return New; + +#endif + + } + } + + if (Node == NULL) + { + ExpSplayTreeSmallerChildNode(New) = NULL; + ExpSplayTreeLargerChildNode(New) = NULL; + } + else if (ExpSplayTreeNodeLess((*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)))) + { + ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); + ExpSplayTreeLargerChildNode(New) = Node; + ExpSplayTreeSmallerChildNode(Node) = NULL; + } + else + { + ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); + ExpSplayTreeSmallerChildNode(New) = Node; + ExpSplayTreeLargerChildNode(Node) = NULL; + } + + ExpSplayTreeNodeKey(New) = Key; + +#ifndef UNIQUE_KEYS + /* No identical nodes (yet) */ + ExpSplayTreeNodeSame(New) = NULL; +#endif + + return New; +} + + +/* + * The lock for the tree must be acquired when this routine is called. + * This routine maintains weight information. + */ +PSPLAY_TREE_NODE +ExpInsertSplayTreeWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE New) +{ + if (New == NULL) + return Node; + + if (Node != NULL) + { + LONG Equality; + + Node = ExpSplayTree(Tree, Key, Node); + + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + if (ExpSplayTreeNodeEqual(Equality)) + { + +#ifdef UNIQUE_KEYS + + /* This is how to prevent the same node key getting added twice */ + return NULL; + +#else + + /* It already exists one of this size */ + + ExpSplayTreeNodeSame(New) = Node; + ExpSplayTreeNodeKey(New) = Key; + ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); + ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(New, ExpSplayTreeNodeGetWeight(Node)); +#endif + + ExpSplayTreeSmallerChildNode(Node) = New; + ExpSplayTreeNodeKey(Node) = KEY_NOTUSED; + + /* New root node */ + return New; + +#endif + + } + } + + if (Node == NULL) + { + ExpSplayTreeSmallerChildNode(New) = NULL; + ExpSplayTreeLargerChildNode(New) = NULL; + } + else if (ExpSplayTreeNodeLess((*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)))) + { + ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); + ExpSplayTreeLargerChildNode(New) = Node; + ExpSplayTreeSmallerChildNode(Node) = NULL; + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(Node, 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node))); +#endif + + } + else + { + ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); + ExpSplayTreeSmallerChildNode(New) = Node; + ExpSplayTreeLargerChildNode(Node) = NULL; + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(Node, 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node))); +#endif + + } + + ExpSplayTreeNodeKey(New) = Key; + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(New, 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(New)) + + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(New))); +#endif + +#ifndef UNIQUE_KEYS + /* No identical nodes (yet) */ + ExpSplayTreeNodeSame(New) = NULL; +#endif + + return New; +} + + +inline PSPLAY_TREE_NODE +ExpInsertSplayTree(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE New) +{ + return (*((PSPLAY_TREE_INSERT)Tree->Reserved[INSERT_INDEX]))(Tree, Key, Node, New); +} + + +/* + * Deletes the node with key 'Key' from the tree if it's there. + * Return a pointer to the resulting tree. + * The lock for the tree must be acquired when this routine is called. + * This routine does not maintain weight information. + */ +PSPLAY_TREE_NODE +ExpRemoveSplayTreeNoWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * RemovedNode) +{ + PSPLAY_TREE_NODE x; + LONG Equality; + + if (Node == NULL) + return NULL; + + Node = ExpSplayTree(Tree, Key, Node); + + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + if (ExpSplayTreeNodeEqual(Equality)) + { + /* Found the key */ + +#ifndef UNIQUE_KEYS + /* FIRST! Check if there is a list with identical sizes */ + x = ExpSplayTreeNodeSame(Node); + if (x) + { + /* There is several, pick one from the list */ + + /* 'x' is the new root node */ + + ExpSplayTreeNodeKey(x) = ExpSplayTreeNodeKey(Node); + ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); + ExpSplayTreeSmallerChildNode(x) = ExpSplayTreeSmallerChildNode(Node); + + *RemovedNode = Node; + return x; + } +#endif + + if (ExpSplayTreeSmallerChildNode(Node) == NULL) + { + x = ExpSplayTreeLargerChildNode(Node); + } + else + { + x = ExpSplayTree(Tree, Key, ExpSplayTreeSmallerChildNode(Node)); + ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); + } + *RemovedNode = Node; + + return x; + } + else + { + *RemovedNode = NULL; /* No match */ + return Node; /* It wasn't there */ + } +} + + +/* + * Deletes the node with key 'Key' from the tree if it's there. + * Return a pointer to the resulting tree. + * The lock for the tree must be acquired when this routine is called. + * This routine maintains weight information. + */ +PSPLAY_TREE_NODE +ExpRemoveSplayTreeWeight(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * RemovedNode) +{ + PSPLAY_TREE_NODE x; + LONG Equality; + +#ifdef WEIGHT + LONG tweight; +#endif + + if (Node == NULL) + return NULL; + +#ifdef WEIGHT + tweight = ExpSplayTreeNodeGetWeight(Node); +#endif + + Node = ExpSplayTree(Tree, Key, Node); + + Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); + if (ExpSplayTreeNodeEqual(Equality)) + { + /* Found the key */ + +#ifndef UNIQUE_KEYS + /* FIRST! Check if there is a list with identical sizes */ + x = ExpSplayTreeNodeSame(Node); + if (x) + { + /* There is several, pick one from the list */ + + /* 'x' is the new root node */ + + ExpSplayTreeNodeKey(x) = ExpSplayTreeNodeKey(Node); + ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); + ExpSplayTreeSmallerChildNode(x) = ExpSplayTreeSmallerChildNode(Node); + +#ifdef WEIGHT + ExpSplayTreeNodeSetWeight(x, ExpSplayTreeNodeGetWeight(Node)); +#endif + + *RemovedNode = Node; + return x; + } +#endif + + if (ExpSplayTreeSmallerChildNode(Node) == NULL) + { + x = ExpSplayTreeLargerChildNode(Node); + } + else + { + x = ExpSplayTree(Tree, Key, ExpSplayTreeSmallerChildNode(Node)); + ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); + } + *RemovedNode = Node; + +#ifdef WEIGHT + if (x != NULL) + { + ExpSplayTreeNodeSetWeight(x, tweight - 1); + } +#endif + + return x; + } + else + { + *RemovedNode = NULL; /* No match */ + return Node; /* It wasn't there */ + } +} + + +inline PSPLAY_TREE_NODE +ExpRemoveSplayTree(PSPLAY_TREE Tree, + PVOID Key, + PSPLAY_TREE_NODE Node, + PSPLAY_TREE_NODE * RemovedNode) +{ + return (*((PSPLAY_TREE_REMOVE)Tree->Reserved[REMOVE_INDEX]))(Tree, Key, Node, RemovedNode); +} + + +/* + * The lock for the tree must be acquired when this routine is called. + */ +ULONG +ExpPrintSplayTree(PSPLAY_TREE Tree, + PSPLAY_TREE_NODE Node, + ULONG Distance) +{ + PSPLAY_TREE_NODE n; + ULONG d = 0; + ULONG i; + + if (Node == NULL) + return 0; + + Distance += ExpPrintSplayTree(Tree, ExpSplayTreeLargerChildNode(Node), Distance + 1); + + for (i = 0; i < Distance; i++) + { + DbgPrint(" "); + } + + if (Tree->Weighted) + { + DbgPrint("%d(%d)[%d]", ExpSplayTreeNodeKey(Node), ExpSplayTreeNodeGetWeight(Node), i); + } + else + { + DbgPrint("%d[%d]", ExpSplayTreeNodeKey(Node), i); + } + + for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) + { + d += i; + + DbgPrint(" [+]"); + } + + d += i; + + d += ExpPrintSplayTree(Tree, ExpSplayTreeSmallerChildNode(Node), Distance + 1); + + return d; +} + + +#define MAX_DIFF 4 + +#ifdef WEIGHT + +/* + * The lock for the tree must be acquired when this routine is called. + * Returns the new root of the tree. + * Use of this routine could improve performance, or it might not. + * FIXME: Do some performance tests + */ +PSPLAY_TREE_NODE +ExpSplayTreeMaxTreeWeight(PSPLAY_TREE Tree, + PSPLAY_TREE_NODE Node) +{ + PSPLAY_TREE_NODE First = Node; + LONG Diff; + + do + { + Diff = ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)) + - ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)); + + if (Diff >= MAX_DIFF) + { + Node = ExpSplayTreeSmallerChildNode(Node); + } + else if (Diff <= -MAX_DIFF) + { + Node = ExpSplayTreeLargerChildNode(Node); + } + else + break; + } while (abs(Diff) >= MAX_DIFF); + + if (Node != First) + return ExpSplayTree(Tree, ExpSplayTreeNodeKey(Node), First); + else + return First; +} + +#endif + + +/* + * Traverse a splay tree using preorder traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + * The lock for the tree must be acquired when this routine is called. + */ +BOOLEAN +ExpTraverseSplayTreePreorder(PTRAVERSE_CONTEXT Context, + PSPLAY_TREE_NODE Node) +{ + PSPLAY_TREE_NODE n; + + if (Node == NULL) + return TRUE; + + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpSplayTreeNodeKey(Node), + ExpSplayTreeNodeValue(Node))) + { + return FALSE; + } + + for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) + { + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpSplayTreeNodeKey(n), + ExpSplayTreeNodeValue(n))) + { + return FALSE; + } + } + + /* Traverse 'smaller' subtree */ + ExpTraverseSplayTreePreorder(Context, ExpSplayTreeSmallerChildNode(Node)); + + /* Traverse 'larger' subtree */ + ExpTraverseSplayTreePreorder(Context, ExpSplayTreeLargerChildNode(Node)); + + return TRUE; +} + + +/* + * Traverse a splay tree using inorder traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + * The lock for the tree must be acquired when this routine is called. + */ +BOOLEAN +ExpTraverseSplayTreeInorder(PTRAVERSE_CONTEXT Context, + PSPLAY_TREE_NODE Node) +{ + PSPLAY_TREE_NODE n; + + if (Node == NULL) + return TRUE; + + /* Traverse 'smaller' subtree */ + ExpTraverseSplayTreeInorder(Context, ExpSplayTreeSmallerChildNode(Node)); + + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpSplayTreeNodeKey(Node), + ExpSplayTreeNodeValue(Node))) + { + return FALSE; + } + + for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) + { + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpSplayTreeNodeKey(n), + ExpSplayTreeNodeValue(n))) + { + return FALSE; + } + } + + /* Traverse right subtree */ + ExpTraverseSplayTreeInorder(Context, ExpSplayTreeLargerChildNode(Node)); + + return TRUE; +} + + +/* + * Traverse a splay tree using postorder traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + * The lock for the tree must be acquired when this routine is called. + */ +BOOLEAN +ExpTraverseSplayTreePostorder(PTRAVERSE_CONTEXT Context, + PSPLAY_TREE_NODE Node) +{ + PSPLAY_TREE_NODE n; + + if (Node == NULL) + return TRUE; + + /* Traverse 'smaller' subtree */ + ExpTraverseSplayTreePostorder(Context, ExpSplayTreeSmallerChildNode(Node)); + + /* Traverse 'larger' subtree */ + ExpTraverseSplayTreePostorder(Context, ExpSplayTreeLargerChildNode(Node)); + + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpSplayTreeNodeKey(Node), + ExpSplayTreeNodeValue(Node))) + { + return FALSE; + } + + for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) + { + /* Call the traversal routine */ + if (!(*Context->Routine)(Context->Context, + ExpSplayTreeNodeKey(n), + ExpSplayTreeNodeValue(n))) + { + return FALSE; + } + } + + return TRUE; +} + + +/* + * Default key compare function. Compares the integer values of the two keys. + */ +LONG STDCALL +ExpSplayTreeDefaultCompare(IN PVOID Key1, + IN PVOID Key2) +{ + if (Key1 == Key2) + return 0; + + return (((LONG_PTR) Key1 < (LONG_PTR) Key2) ? -1 : 1); +} + + +/* + * Initializes a splay tree. + */ +BOOLEAN STDCALL +ExInitializeSplayTree(IN PSPLAY_TREE Tree, + IN PKEY_COMPARATOR Compare, + IN BOOLEAN Weighted, + IN BOOLEAN UseNonPagedPool) +{ + RtlZeroMemory(Tree, sizeof(SPLAY_TREE)); + + Tree->Compare = (Compare == NULL) + ? ExpSplayTreeDefaultCompare : Compare; + + Tree->Weighted = Weighted; + + if (Weighted) + { + Tree->Reserved[SPLAY_INDEX] = (PVOID) ExpSplayTreeWeight; + Tree->Reserved[SEARCH_INDEX] = (PVOID) ExpSearchSplayTreeWeight; + Tree->Reserved[INSERT_INDEX] = (PVOID) ExpInsertSplayTreeWeight; + Tree->Reserved[REMOVE_INDEX] = (PVOID) ExpRemoveSplayTreeWeight; + } + else + { + Tree->Reserved[SPLAY_INDEX] = (PVOID) ExpSplayTreeNoWeight; + Tree->Reserved[SEARCH_INDEX] = (PVOID) ExpSearchSplayTreeNoWeight; + Tree->Reserved[INSERT_INDEX] = (PVOID) ExpInsertSplayTreeNoWeight; + Tree->Reserved[REMOVE_INDEX] = (PVOID) ExpRemoveSplayTreeNoWeight; + } + + Tree->UseNonPagedPool = UseNonPagedPool; + + if (UseNonPagedPool) + { + ExInitializeNPagedLookasideList( + &Tree->List.NonPaged, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(SPLAY_TREE_NODE), /* Size of each entry */ + TAG('E','X','S','T'), /* Tag */ + 0); /* Depth */ + + KeInitializeSpinLock(&Tree->Lock.NonPaged); + } + else + { + ExInitializePagedLookasideList( + &Tree->List.Paged, /* Lookaside list */ + NULL, /* Allocate routine */ + NULL, /* Free routine */ + 0, /* Flags */ + sizeof(SPLAY_TREE_NODE), /* Size of each entry */ + TAG('E','X','S','T'), /* Tag */ + 0); /* Depth */ + + ExInitializeFastMutex(&Tree->Lock.Paged); + } + + return TRUE; +} + + +/* + * Release resources used by a splay tree. + */ +VOID STDCALL +ExDeleteSplayTree(IN PSPLAY_TREE Tree) +{ + PSPLAY_TREE_NODE RemovedNode; + PSPLAY_TREE_NODE Node; + + /* Remove all nodes */ + Node = ExpSplayTreeRootNode(Tree); + while (Node != NULL) + { + Node = ExpRemoveSplayTree(Tree, Node->Key, Node, &RemovedNode); + + if (RemovedNode != NULL) + { + ExpDestroySplayTreeNode(Tree, RemovedNode); + } + } + + if (Tree->UseNonPagedPool) + { + ExDeleteNPagedLookasideList(&Tree->List.NonPaged); + } + else + { + ExDeletePagedLookasideList(&Tree->List.Paged); + } +} + + +/* + * Insert a value in a splay tree. + */ +VOID STDCALL +ExInsertSplayTree(IN PSPLAY_TREE Tree, + IN PVOID Key, + IN PVOID Value) +{ + PSPLAY_TREE_NODE Node; + PSPLAY_TREE_NODE NewNode; + KIRQL OldIrql; + + /* FIXME: Use SEH for error reporting */ + + NewNode = ExpCreateSplayTreeNode(Tree, Value); + + ExpLockSplayTree(Tree, &OldIrql); + Node = ExpInsertSplayTree(Tree, Key, ExpSplayTreeRootNode(Tree), NewNode); + ExpSplayTreeRootNode(Tree) = Node; + ExpUnlockSplayTree(Tree, &OldIrql); +} + + +/* + * Search for a value associated with a given key in a splay tree. + */ +BOOLEAN STDCALL +ExSearchSplayTree(IN PSPLAY_TREE Tree, + IN PVOID Key, + OUT PVOID * Value) +{ + PSPLAY_TREE_NODE Node; + BOOLEAN Status; + KIRQL OldIrql; + + ExpLockSplayTree(Tree, &OldIrql); + Status = ExpSearchSplayTree(Tree, Key, ExpSplayTreeRootNode(Tree), &Node); + + if (Status) + { + ExpSplayTreeRootNode(Tree) = Node; + *Value = ExpSplayTreeNodeValue(Node); + ExpUnlockSplayTree(Tree, &OldIrql); + return TRUE; + } + else + { + ExpUnlockSplayTree(Tree, &OldIrql); + return FALSE; + } +} + + +/* + * Remove a value associated with a given key from a splay tree. + */ +BOOLEAN STDCALL +ExRemoveSplayTree(IN PSPLAY_TREE Tree, + IN PVOID Key, + IN PVOID * Value) +{ + PSPLAY_TREE_NODE RemovedNode; + PSPLAY_TREE_NODE Node; + KIRQL OldIrql; + + ExpLockSplayTree(Tree, &OldIrql); + Node = ExpRemoveSplayTree(Tree, Key, ExpSplayTreeRootNode(Tree), &RemovedNode); + ExpSplayTreeRootNode(Tree) = Node; + ExpUnlockSplayTree(Tree, &OldIrql); + + if (RemovedNode != NULL) + { + *Value = ExpSplayTreeNodeValue(RemovedNode); + ExpDestroySplayTreeNode(Tree, RemovedNode); + return TRUE; + } + else + { + return FALSE; + } +} + + +/* + * Return the weight of the root node in the splay tree. + * The returned value is the number of nodes in the tree. + */ +BOOLEAN STDCALL +ExWeightOfSplayTree(IN PSPLAY_TREE Tree, + OUT PULONG Weight) +{ + KIRQL OldIrql; + + ExpLockSplayTree(Tree, &OldIrql); + + if (!Tree->Weighted) + { + ExpUnlockSplayTree(Tree, &OldIrql); + return FALSE; + } + + *Weight = ExpSplayTreeNodeWeight(ExpSplayTreeRootNode(Tree)); + ExpUnlockSplayTree(Tree, &OldIrql); + + return TRUE; +} + + +/* + * Traverse a splay tree using either preorder, inorder or postorder + * traversal method. + * Returns FALSE, if the traversal was terminated prematurely or + * TRUE if the callback routine did not request that the traversal + * be terminated prematurely. + */ +BOOLEAN STDCALL +ExTraverseSplayTree(IN PSPLAY_TREE Tree, + IN TRAVERSE_METHOD Method, + IN PTRAVERSE_ROUTINE Routine, + IN PVOID Context) +{ + TRAVERSE_CONTEXT tc; + BOOLEAN Status; + KIRQL OldIrql; + + tc.Routine = Routine; + tc.Context = Context; + + ExpLockSplayTree(Tree, &OldIrql); + + if (ExpSplayTreeRootNode(Tree) == NULL) + { + ExpUnlockSplayTree(Tree, &OldIrql); + return TRUE; + } + + switch (Method) + { + case TraverseMethodPreorder: + Status = ExpTraverseSplayTreePreorder(&tc, ExpSplayTreeRootNode(Tree)); + break; + + case TraverseMethodInorder: + Status = ExpTraverseSplayTreeInorder(&tc, ExpSplayTreeRootNode(Tree)); + break; + + case TraverseMethodPostorder: + Status = ExpTraverseSplayTreePostorder(&tc, ExpSplayTreeRootNode(Tree)); + break; + + default: + Status = FALSE; + break; + } + + ExpUnlockSplayTree(Tree, &OldIrql); + + return Status; +} + +/* EOF */ diff --git a/ntoskrnl/ex/sysinfo.c b/ntoskrnl/ex/sysinfo.c new file mode 100644 index 0000000..4ea6d53 --- /dev/null +++ b/ntoskrnl/ex/sysinfo.c @@ -0,0 +1,1163 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/sysinfo.c + * PURPOSE: System information functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +extern ULONG NtGlobalFlag; /* FIXME: it should go in a ddk/?.h */ + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtQuerySystemEnvironmentValue (IN PUNICODE_STRING UnsafeName, + OUT PVOID UnsafeValue, + IN ULONG Length, + IN OUT PULONG UnsafeReturnLength) +{ + NTSTATUS Status; + ANSI_STRING AName; + UNICODE_STRING WName; + BOOLEAN Result; + PCH Value; + ANSI_STRING AValue; + UNICODE_STRING WValue; + ULONG ReturnLength; + + /* + * Copy the name to kernel space if necessary and convert it to ANSI. + */ + if (ExGetPreviousMode() != KernelMode) + { + Status = RtlCaptureUnicodeString(&WName, UnsafeName); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + else + { + Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + + /* + * Create a temporary buffer for the value + */ + Value = ExAllocatePool(NonPagedPool, Length); + if (Value == NULL) + { + RtlFreeAnsiString(&AName); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + } + return(STATUS_NO_MEMORY); + } + + /* + * Get the environment variable + */ + Result = HalGetEnvironmentVariable(AName.Buffer, Value, Length); + if (!Result) + { + RtlFreeAnsiString(&AName); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + } + ExFreePool(Value); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Convert the result to UNICODE. + */ + RtlInitAnsiString(&AValue, Value); + Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, TRUE); + if (!NT_SUCCESS(Status)) + { + RtlFreeAnsiString(&AName); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + } + ExFreePool(Value); + return(Status); + } + ReturnLength = WValue.Length; + + /* + * Copy the result back to the caller. + */ + if (ExGetPreviousMode() != KernelMode) + { + Status = MmCopyToCaller(UnsafeValue, WValue.Buffer, ReturnLength); + if (!NT_SUCCESS(Status)) + { + RtlFreeAnsiString(&AName); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + } + ExFreePool(Value); + RtlFreeUnicodeString(&WValue); + return(Status); + } + + Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + RtlFreeAnsiString(&AName); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + } + ExFreePool(Value); + RtlFreeUnicodeString(&WValue); + return(Status); + } + } + else + { + memcpy(UnsafeValue, WValue.Buffer, ReturnLength); + memcpy(UnsafeReturnLength, &ReturnLength, sizeof(ULONG)); + } + + /* + * Free temporary buffers. + */ + RtlFreeAnsiString(&AName); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + } + ExFreePool(Value); + RtlFreeUnicodeString(&WValue); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetSystemEnvironmentValue (IN PUNICODE_STRING UnsafeName, + IN PUNICODE_STRING UnsafeValue) +{ + UNICODE_STRING WName; + ANSI_STRING AName; + UNICODE_STRING WValue; + ANSI_STRING AValue; + BOOLEAN Result; + NTSTATUS Status; + + /* + * Check for required privilege. + */ + /* FIXME: Not implemented. */ + + /* + * Copy the name to kernel space if necessary and convert it to ANSI. + */ + if (ExGetPreviousMode() != KernelMode) + { + Status = RtlCaptureUnicodeString(&WName, UnsafeName); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + else + { + Status = RtlUnicodeStringToAnsiString(&AName, UnsafeName, TRUE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + + /* + * Copy the value to kernel space and convert to ANSI. + */ + if (ExGetPreviousMode() != KernelMode) + { + Status = RtlCaptureUnicodeString(&WValue, UnsafeValue); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&WName); + RtlFreeAnsiString(&AName); + return(Status); + } + Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&WName); + RtlFreeAnsiString(&AName); + RtlFreeUnicodeString(&WValue); + return(Status); + } + } + else + { + Status = RtlUnicodeStringToAnsiString(&AValue, UnsafeValue, TRUE); + if (!NT_SUCCESS(Status)) + { + RtlFreeAnsiString(&AName); + return(Status); + } + } + + /* + * Set the environment variable + */ + Result = HalSetEnvironmentVariable(AName.Buffer, AValue.Buffer); + + /* + * Free everything and return status. + */ + RtlFreeAnsiString(&AName); + RtlFreeAnsiString(&AValue); + if (ExGetPreviousMode() != KernelMode) + { + RtlFreeUnicodeString(&WName); + RtlFreeUnicodeString(&WValue); + } + + if (!Result) + { + return(STATUS_UNSUCCESSFUL); + } + return(STATUS_SUCCESS); +} + + +/* --- Query/Set System Information --- */ + + +/* + * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols + * so the stack is popped only in one place on x86 platform. + */ +#define QSI_USE(n) QSI##n +#define QSI_DEF(n) \ +static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize) + +#define SSI_USE(n) SSI##n +#define SSI_DEF(n) \ +static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size) + +/* Class 0 - Basic Information */ +QSI_DEF(SystemBasicInformation) +{ + PSYSTEM_BASIC_INFORMATION Sbi + = (PSYSTEM_BASIC_INFORMATION) Buffer; + + *ReqSize = sizeof (SYSTEM_BASIC_INFORMATION); + /* + * Check user buffer's size + */ + if (Size < sizeof (SYSTEM_BASIC_INFORMATION)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + + Sbi->Reserved = 0; + Sbi->TimerResolution = 0; /* FIXME */ + Sbi->PageSize = PAGE_SIZE; /* FIXME: it should be PAGE_SIZE */ + Sbi->NumberOfPhysicalPages = 0; /* FIXME */ + Sbi->LowestPhysicalPageNumber = 0; /* FIXME */ + Sbi->HighestPhysicalPageNumber = 0; /* FIXME */ + Sbi->AllocationGranularity = 65536; /* hard coded on Intel? */ + Sbi->MinimumUserModeAddress = 0; /* FIXME */ + Sbi->MaximumUserModeAddress = 0; /* FIXME */ + Sbi->ActiveProcessorsAffinityMask = 0x00000001; /* FIXME */ + Sbi->NumberOfProcessors = 1; /* FIXME */ + + return (STATUS_SUCCESS); +} + +/* Class 1 - Processor Information */ +QSI_DEF(SystemProcessorInformation) +{ + PSYSTEM_PROCESSOR_INFORMATION Spi + = (PSYSTEM_PROCESSOR_INFORMATION) Buffer; + + *ReqSize = sizeof (SYSTEM_PROCESSOR_INFORMATION); + /* + * Check user buffer's size + */ + if (Size < sizeof (SYSTEM_PROCESSOR_INFORMATION)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + + /* FIXME: add CPU type detection code */ + Spi->ProcessorArchitecture = 0; /* FIXME */ + Spi->ProcessorLevel = 0; /* FIXME */ + Spi->ProcessorRevision = 0; /* FIXME */ + Spi->Reserved = 0; + Spi->ProcessorFeatureBits = 0x00000000; /* FIXME */ + + return (STATUS_SUCCESS); +} + +/* Class 2 - Performance Information */ +QSI_DEF(SystemPerformanceInformation) +{ + PSYSTEM_PERFORMANCE_INFO Spi + = (PSYSTEM_PERFORMANCE_INFO) Buffer; + + *ReqSize = sizeof (SYSTEM_PERFORMANCE_INFO); + /* + * Check user buffer's size + */ + if (Size < sizeof (SYSTEM_PERFORMANCE_INFO)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + + Spi->IdleProcessorTime.QuadPart = 0; /* FIXME */ + Spi->IoReadTransferCount.QuadPart = 0; /* FIXME */ + Spi->IoWriteTransferCount.QuadPart = 0; /* FIXME */ + Spi->IoOtherTransferCount.QuadPart = 0; /* FIXME */ + Spi->IoReadOperationCount = 0; /* FIXME */ + Spi->IoWriteOperationCount = 0; /* FIXME */ + Spi->IoOtherOperationCount = 0; /* FIXME */ + Spi->AvailablePages = 0; /* FIXME */ + Spi->CommitedPages = 0; /* FIXME */ + Spi->CommitLimit = 0; /* FIXME */ + Spi->PeakCommitment = 0; /* FIXME */ + Spi->PageFaultCount = 0; /* FIXME */ + Spi->CopyOnWriteCount = 0; /* FIXME */ + Spi->TransitionCount = 0; /* FIXME */ + Spi->CacheTransitionCount = 0; /* FIXME */ + Spi->DemandZeroCount = 0; /* FIXME */ + Spi->PageReadCount = 0; /* FIXME */ + Spi->PageReadIoCount = 0; /* FIXME */ + Spi->CacheReadCount = 0; /* FIXME */ + Spi->CacheIoCount = 0; /* FIXME */ + Spi->DirtyPagesWriteCount = 0; /* FIXME */ + Spi->DirtyWriteIoCount = 0; /* FIXME */ + Spi->MappedPagesWriteCount = 0; /* FIXME */ + Spi->MappedWriteIoCount = 0; /* FIXME */ + Spi->PagedPoolPages = 0; /* FIXME */ + Spi->NonPagedPoolPages = 0; /* FIXME */ + Spi->Unknown6 = 0; /* FIXME */ + Spi->Unknown7 = 0; /* FIXME */ + Spi->Unknown8 = 0; /* FIXME */ + Spi->Unknown9 = 0; /* FIXME */ + Spi->MmTotalSystemFreePtes = 0; /* FIXME */ + Spi->MmSystemCodepage = 0; /* FIXME */ + Spi->MmTotalSystemDriverPages = 0; /* FIXME */ + Spi->MmTotalSystemCodePages = 0; /* FIXME */ + Spi->Unknown10 = 0; /* FIXME */ + Spi->Unknown11 = 0; /* FIXME */ + Spi->Unknown12 = 0; /* FIXME */ + Spi->MmSystemCachePage = 0; /* FIXME */ + Spi->MmPagedPoolPage = 0; /* FIXME */ + Spi->MmSystemDriverPage = 0; /* FIXME */ + Spi->CcFastReadNoWait = 0; /* FIXME */ + Spi->CcFastReadWait = 0; /* FIXME */ + Spi->CcFastReadResourceMiss = 0; /* FIXME */ + Spi->CcFastReadNotPossible = 0; /* FIXME */ + Spi->CcFastMdlReadNoWait = 0; /* FIXME */ + Spi->CcFastMdlReadWait = 0; /* FIXME */ + Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */ + Spi->CcFastMdlReadNotPossible = 0; /* FIXME */ + Spi->CcMapDataNoWait = 0; /* FIXME */ + Spi->CcMapDataWait = 0; /* FIXME */ + Spi->CcMapDataNoWaitMiss = 0; /* FIXME */ + Spi->CcMapDataWaitMiss = 0; /* FIXME */ + Spi->CcPinMappedDataCount = 0; /* FIXME */ + Spi->CcPinReadNoWait = 0; /* FIXME */ + Spi->CcPinReadWait = 0; /* FIXME */ + Spi->CcPinReadNoWaitMiss = 0; /* FIXME */ + Spi->CcPinReadWaitMiss = 0; /* FIXME */ + Spi->CcCopyReadNoWait = 0; /* FIXME */ + Spi->CcCopyReadWait = 0; /* FIXME */ + Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */ + Spi->CcCopyReadWaitMiss = 0; /* FIXME */ + Spi->CcMdlReadNoWait = 0; /* FIXME */ + Spi->CcMdlReadWait = 0; /* FIXME */ + Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */ + Spi->CcMdlReadWaitMiss = 0; /* FIXME */ + Spi->CcReadaheadIos = 0; /* FIXME */ + Spi->CcLazyWriteIos = 0; /* FIXME */ + Spi->CcLazyWritePages = 0; /* FIXME */ + Spi->CcDataFlushes = 0; /* FIXME */ + Spi->CcDataPages = 0; /* FIXME */ + Spi->ContextSwitches = 0; /* FIXME */ + Spi->Unknown13 = 0; /* FIXME */ + Spi->Unknown14 = 0; /* FIXME */ + Spi->SystemCalls = 0; /* FIXME */ + + return (STATUS_SUCCESS); +} + +/* Class 3 - Time Of Day Information */ +QSI_DEF(SystemTimeOfDayInformation) +{ + PSYSTEM_TIMEOFDAY_INFORMATION Sti + = (PSYSTEM_TIMEOFDAY_INFORMATION) Buffer; + + *ReqSize = sizeof (SYSTEM_TIMEOFDAY_INFORMATION); + /* + * Check user buffer's size + */ + if (Size < sizeof (SYSTEM_TIMEOFDAY_INFORMATION)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + + Sti->BootTime.QuadPart = 0; /* FIXME */ + Sti->CurrentTime.QuadPart = 0; /* FIXME */ + Sti->TimeZoneBias.QuadPart = 0; /* FIXME */ + Sti->TimeZoneId = 0; /* FIXME */ + Sti->Reserved = 0; /* FIXME */ + + return (STATUS_SUCCESS); +} + +/* Class 4 - Path Information */ +QSI_DEF(SystemPathInformation) +{ + /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */ + return (STATUS_BREAKPOINT); +} + +/* Class 5 - Process Information */ +QSI_DEF(SystemProcessInformation) +{ + /* FIXME: scan the process+thread list */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 6 - Call Count Information */ +QSI_DEF(SystemCallCountInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 7 - Device Information */ +QSI_DEF(SystemDeviceInformation) +{ + PSYSTEM_DEVICE_INFORMATION Sdi + = (PSYSTEM_DEVICE_INFORMATION) Buffer; + PCONFIGURATION_INFORMATION ConfigInfo; + + *ReqSize = sizeof (SYSTEM_DEVICE_INFORMATION); + /* + * Check user buffer's size + */ + if (Size < sizeof (SYSTEM_DEVICE_INFORMATION)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + + ConfigInfo = IoGetConfigurationInformation (); + + Sdi->NumberOfDisks = ConfigInfo->DiskCount; + Sdi->NumberOfFloppies = ConfigInfo->FloppyCount; + Sdi->NumberOfCdRoms = ConfigInfo->CDRomCount; + Sdi->NumberOfTapes = ConfigInfo->TapeCount; + Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount; + Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount; + + return (STATUS_SUCCESS); +} + +/* Class 8 - Processor Performance Information */ +QSI_DEF(SystemProcessorPerformanceInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 9 - Flags Information */ +QSI_DEF(SystemFlagsInformation) +{ + if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size) + { + * ReqSize = sizeof (SYSTEM_FLAGS_INFORMATION); + return (STATUS_INFO_LENGTH_MISMATCH); + } + ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag; + return (STATUS_SUCCESS); +} + +SSI_DEF(SystemFlagsInformation) +{ + if (sizeof (SYSTEM_FLAGS_INFORMATION) != Size) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags; + return (STATUS_SUCCESS); +} + +/* Class 10 - Call Time Information */ +QSI_DEF(SystemCallTimeInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 11 - Module Information */ +QSI_DEF(SystemModuleInformation) +{ + return LdrpQueryModuleInformation(Buffer, Size, ReqSize); +} + +/* Class 12 - Locks Information */ +QSI_DEF(SystemLocksInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 13 - Stack Trace Information */ +QSI_DEF(SystemStackTraceInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 14 - Paged Pool Information */ +QSI_DEF(SystemPagedPoolInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 15 - Non Paged Pool Information */ +QSI_DEF(SystemNonPagedPoolInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 16 - Handle Information */ +QSI_DEF(SystemHandleInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 17 - Information */ +QSI_DEF(SystemObjectInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 18 - Information */ +QSI_DEF(SystemPageFileInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 19 - Vdm Instemul Information */ +QSI_DEF(SystemVdmInstemulInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 20 - Vdm Bop Information */ +QSI_DEF(SystemVdmBopInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 21 - File Cache Information */ +QSI_DEF(SystemFileCacheInformation) +{ + if (Size < sizeof (SYSTEM_CACHE_INFORMATION)) + { + * ReqSize = sizeof (SYSTEM_CACHE_INFORMATION); + return (STATUS_INFO_LENGTH_MISMATCH); + } + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +SSI_DEF(SystemFileCacheInformation) +{ + if (Size < sizeof (SYSTEM_CACHE_INFORMATION)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 22 - Pool Tag Information */ +QSI_DEF(SystemPoolTagInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 23 - Interrupt Information */ +QSI_DEF(SystemInterruptInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 24 - DPC Behaviour Information */ +QSI_DEF(SystemDpcBehaviourInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +SSI_DEF(SystemDpcBehaviourInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 25 - Full Memory Information */ +QSI_DEF(SystemFullMemoryInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 26 - Load Image */ +SSI_DEF(SystemLoadImage) +{ + PSYSTEM_LOAD_IMAGE Sli = (PSYSTEM_LOAD_IMAGE)Buffer; + + if (sizeof(SYSTEM_LOAD_IMAGE) != Size) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + + return(LdrpLoadImage(&Sli->ModuleName, + &Sli->ModuleBase, + &Sli->SectionPointer, + &Sli->EntryPoint, + &Sli->ExportDirectory)); +} + +/* Class 27 - Unload Image */ +SSI_DEF(SystemUnloadImage) +{ + PSYSTEM_UNLOAD_IMAGE Sui = (PSYSTEM_UNLOAD_IMAGE)Buffer; + + if (sizeof(SYSTEM_UNLOAD_IMAGE) != Size) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + + return(LdrpUnloadImage(Sui->ModuleBase)); +} + +/* Class 28 - Time Adjustment Information */ +QSI_DEF(SystemTimeAdjustmentInformation) +{ + if (sizeof (SYSTEM_TIME_ADJUSTMENT_INFO) > Size) + { + * ReqSize = sizeof (SYSTEM_TIME_ADJUSTMENT_INFO); + return (STATUS_INFO_LENGTH_MISMATCH); + } + /* FIXME: */ + return (STATUS_NOT_IMPLEMENTED); +} + +SSI_DEF(SystemTimeAdjustmentInformation) +{ + if (sizeof (SYSTEM_TIME_ADJUSTMENT_INFO) > Size) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + /* FIXME: */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 29 - Summary Memory Information */ +QSI_DEF(SystemSummaryMemoryInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 30 - Next Event Id Information */ +QSI_DEF(SystemNextEventIdInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 31 - Event Ids Information */ +QSI_DEF(SystemEventIdsInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 32 - Crach Dump Information */ +QSI_DEF(SystemCrashDumpInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 33 - Exception Information */ +QSI_DEF(SystemExceptionInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 34 - Crach Dump State Information */ +QSI_DEF(SystemCrashDumpStateInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 35 - Kernel Debugger Information */ +QSI_DEF(SystemKernelDebuggerInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 36 - Context Switch Information */ +QSI_DEF(SystemContextSwitchInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 37 - Registry Quota Information */ +QSI_DEF(SystemRegistryQuotaInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +SSI_DEF(SystemRegistryQuotaInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 38 - Load And Call Image */ +SSI_DEF(SystemLoadAndCallImage) +{ + PSYSTEM_LOAD_AND_CALL_IMAGE Slci = (PSYSTEM_LOAD_AND_CALL_IMAGE)Buffer; + + if (sizeof(SYSTEM_LOAD_AND_CALL_IMAGE) != Size) + { + return(STATUS_INFO_LENGTH_MISMATCH); + } + + return(LdrpLoadAndCallImage(&Slci->ModuleName)); +} + +/* Class 39 - Priority Seperation */ +SSI_DEF(SystemPrioritySeperation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 40 - Plug Play Bus Information */ +QSI_DEF(SystemPlugPlayBusInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 41 - Dock Information */ +QSI_DEF(SystemDockInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 42 - Power Information */ +QSI_DEF(SystemPowerInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 43 - Processor Speed Information */ +QSI_DEF(SystemProcessorSpeedInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* Class 44 - Current Time Zone Information */ +QSI_DEF(SystemCurrentTimeZoneInformation) +{ + * ReqSize = sizeof (TIME_ZONE_INFORMATION); + + if (sizeof (TIME_ZONE_INFORMATION) != Size) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + /* Copy the time zone information struct */ + memcpy ( + Buffer, + & SystemTimeZoneInfo, + sizeof (TIME_ZONE_INFORMATION) + ); + + return (STATUS_SUCCESS); +} + + +SSI_DEF(SystemCurrentTimeZoneInformation) +{ + /* + * Check user buffer's size + */ + if (Size < sizeof (TIME_ZONE_INFORMATION)) + { + return (STATUS_INFO_LENGTH_MISMATCH); + } + /* Copy the time zone information struct */ + memcpy ( + & SystemTimeZoneInfo, + (TIME_ZONE_INFORMATION *) Buffer, + sizeof (TIME_ZONE_INFORMATION) + ); + return (STATUS_SUCCESS); +} + + +/* Class 45 - Lookaside Information */ +QSI_DEF(SystemLookasideInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 46 - Set time slip event */ +SSI_DEF(SystemSetTimeSlipEvent) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 47 - Create a new session (TSE) */ +SSI_DEF(SystemCreateSession) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 48 - Delete an existing session (TSE) */ +SSI_DEF(SystemDeleteSession) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 49 - UNKNOWN */ +QSI_DEF(SystemInvalidInfoClass4) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 50 - System range start address */ +QSI_DEF(SystemRangeStartInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 51 - Driver verifier information */ +QSI_DEF(SystemVerifierInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +SSI_DEF(SystemVerifierInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 52 - Add a driver verifier */ +SSI_DEF(SystemAddVerifier) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Class 53 - A session's processes */ +QSI_DEF(SystemSessionProcessesInformation) +{ + /* FIXME */ + return (STATUS_NOT_IMPLEMENTED); +} + + +/* Query/Set Calls Table */ +typedef +struct _QSSI_CALLS +{ + NTSTATUS (* Query) (PVOID,ULONG,PULONG); + NTSTATUS (* Set) (PVOID,ULONG); + +} QSSI_CALLS; + +// QS Query & Set +// QX Query +// XQ Set +// XX unknown behaviour +// +#define SI_QS(n) {QSI_USE(n),SSI_USE(n)} +#define SI_QX(n) {QSI_USE(n),NULL} +#define SI_XS(n) {NULL,SSI_USE(n)} +#define SI_XX(n) {NULL,NULL} + +static +QSSI_CALLS +CallQS [] = +{ + SI_QX(SystemBasicInformation), + SI_QX(SystemProcessorInformation), + SI_QX(SystemPerformanceInformation), + SI_QX(SystemTimeOfDayInformation), + SI_QX(SystemPathInformation), /* should be SI_XX */ + SI_QX(SystemProcessInformation), + SI_QX(SystemCallCountInformation), + SI_QX(SystemDeviceInformation), + SI_QX(SystemProcessorPerformanceInformation), + SI_QS(SystemFlagsInformation), + SI_QX(SystemCallTimeInformation), /* should be SI_XX */ + SI_QX(SystemModuleInformation), + SI_QX(SystemLocksInformation), + SI_QX(SystemStackTraceInformation), /* should be SI_XX */ + SI_QX(SystemPagedPoolInformation), /* should be SI_XX */ + SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */ + SI_QX(SystemHandleInformation), + SI_QX(SystemObjectInformation), + SI_QX(SystemPageFileInformation), + SI_QX(SystemVdmInstemulInformation), + SI_QX(SystemVdmBopInformation), /* it should be SI_XX */ + SI_QS(SystemFileCacheInformation), + SI_QX(SystemPoolTagInformation), + SI_QX(SystemInterruptInformation), + SI_QS(SystemDpcBehaviourInformation), + SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */ + SI_XS(SystemLoadImage), + SI_XS(SystemUnloadImage), + SI_QS(SystemTimeAdjustmentInformation), + SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */ + SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */ + SI_QX(SystemEventIdsInformation), /* it should be SI_XX */ + SI_QX(SystemCrashDumpInformation), + SI_QX(SystemExceptionInformation), + SI_QX(SystemCrashDumpStateInformation), + SI_QX(SystemKernelDebuggerInformation), + SI_QX(SystemContextSwitchInformation), + SI_QS(SystemRegistryQuotaInformation), + SI_XS(SystemLoadAndCallImage), + SI_XS(SystemPrioritySeperation), + SI_QX(SystemPlugPlayBusInformation), /* it should be SI_XX */ + SI_QX(SystemDockInformation), /* it should be SI_XX */ + SI_QX(SystemPowerInformation), /* it should be SI_XX */ + SI_QX(SystemProcessorSpeedInformation), /* it should be SI_XX */ + SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */ + SI_QX(SystemLookasideInformation), + SI_XS(SystemSetTimeSlipEvent), + SI_XS(SystemCreateSession), + SI_XS(SystemDeleteSession), + SI_QX(SystemInvalidInfoClass4), /* it should be SI_XX */ + SI_QX(SystemRangeStartInformation), + SI_QS(SystemVerifierInformation), + SI_XS(SystemAddVerifier), + SI_QX(SystemSessionProcessesInformation) +}; + + +NTSTATUS STDCALL +NtQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + OUT PVOID UnsafeSystemInformation, + IN ULONG Length, + OUT PULONG UnsafeResultLength) +{ + ULONG ResultLength; + PVOID SystemInformation; + NTSTATUS Status; + NTSTATUS FStatus; + + if (ExGetPreviousMode() == KernelMode) + { + SystemInformation = UnsafeSystemInformation; + } + else + { + SystemInformation = ExAllocatePool(NonPagedPool, Length); + if (SystemInformation == NULL) + { + return(STATUS_NO_MEMORY); + } + } + + /* Clear user buffer. */ + RtlZeroMemory(SystemInformation, Length); + + /* + * Check the request is valid. + */ + if ((SystemInformationClass >= SystemInformationClassMin) && + (SystemInformationClass < SystemInformationClassMax)) + { + if (NULL != CallQS [SystemInformationClass].Query) + { + /* + * Hand the request to a subhandler. + */ + FStatus = CallQS [SystemInformationClass].Query(SystemInformation, + Length, + &ResultLength); + if (ExGetPreviousMode() != KernelMode) + { + Status = MmCopyToCaller(UnsafeSystemInformation, + SystemInformation, + Length); + ExFreePool(SystemInformation); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + if (UnsafeResultLength != NULL) + { + if (ExGetPreviousMode() == KernelMode) + { + *UnsafeResultLength = ResultLength; + } + else + { + Status = MmCopyToCaller(UnsafeResultLength, + &ResultLength, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + } + return(FStatus); + } + } + return (STATUS_INVALID_INFO_CLASS); +} + + +NTSTATUS +STDCALL +NtSetSystemInformation ( + IN SYSTEM_INFORMATION_CLASS SystemInformationClass, + IN PVOID SystemInformation, + IN ULONG SystemInformationLength + ) +{ + /* + * If called from user mode, check + * possible unsafe arguments. + */ +#if 0 + if (KernelMode != KeGetPreviousMode()) + { + // Check arguments + //ProbeForWrite( + // SystemInformation, + // Length + // ); + //ProbeForWrite( + // ResultLength, + // sizeof (ULONG) + // ); + } +#endif + /* + * Check the request is valid. + */ + if ( (SystemInformationClass >= SystemInformationClassMin) + && (SystemInformationClass < SystemInformationClassMax) + ) + { + if (NULL != CallQS [SystemInformationClass].Set) + { + /* + * Hand the request to a subhandler. + */ + return CallQS [SystemInformationClass].Set ( + SystemInformation, + SystemInformationLength + ); + } + } + return (STATUS_INVALID_INFO_CLASS); +} + + +NTSTATUS +STDCALL +NtFlushInstructionCache ( + IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN UINT NumberOfBytesToFlush + ) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/ex/time.c b/ntoskrnl/ex/time.c new file mode 100644 index 0000000..17c4e56 --- /dev/null +++ b/ntoskrnl/ex/time.c @@ -0,0 +1,135 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ex/time.c + * PURPOSE: Time + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#include + + +#define TICKSPERMINUTE 600000000 + +/* GLOBALS ******************************************************************/ + +/* Note: Bias[minutes] = UTC - local time */ +TIME_ZONE_INFORMATION _SystemTimeZoneInfo; + + +/* FUNCTIONS ****************************************************************/ + +VOID +ExInitTimeZoneInfo (VOID) +{ + /* Initialize system time zone information */ + memset (& _SystemTimeZoneInfo, 0, sizeof(TIME_ZONE_INFORMATION)); + + /* FIXME: Read time zone information from the registry */ + +} + + +NTSTATUS STDCALL +NtSetSystemTime (IN PLARGE_INTEGER UnsafeNewSystemTime, + OUT PLARGE_INTEGER UnsafeOldSystemTime OPTIONAL) + /* + * FUNCTION: Sets the system time. + * PARAMETERS: + * NewTime - Points to a variable that specified the new time + * of day in the standard time format. + * OldTime - Optionally points to a variable that receives the + * old time of day in the standard time format. + * RETURNS: Status + */ +{ + NTSTATUS Status; + LARGE_INTEGER OldSystemTime; + LARGE_INTEGER NewSystemTime; + + /* FIXME: Check for SeSystemTimePrivilege */ + + Status = MmCopyFromCaller(&NewSystemTime, UnsafeNewSystemTime, + sizeof(NewSystemTime)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (UnsafeOldSystemTime != NULL) + { + KeQuerySystemTime(&OldSystemTime); + } + HalSetRealTimeClock ((PTIME_FIELDS)&NewSystemTime); + + if (UnsafeOldSystemTime != NULL) + { + Status = MmCopyToCaller(UnsafeOldSystemTime, &OldSystemTime, + sizeof(OldSystemTime)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtQuerySystemTime (OUT TIME* UnsafeCurrentTime) + /* + * FUNCTION: Retrieves the system time. + * PARAMETERS: + * CurrentTime - Points to a variable that receives the current + * time of day in the standard time format. + */ +{ + LARGE_INTEGER CurrentTime; + NTSTATUS Status; + + KeQuerySystemTime(&CurrentTime); + Status = MmCopyToCaller(UnsafeCurrentTime, &CurrentTime, + sizeof(CurrentTime)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + return STATUS_SUCCESS; +} + + +VOID +STDCALL +ExLocalTimeToSystemTime ( + PLARGE_INTEGER LocalTime, + PLARGE_INTEGER SystemTime + ) +{ + SystemTime->QuadPart = LocalTime->QuadPart + + _SystemTimeZoneInfo.Bias * TICKSPERMINUTE; +} + + +VOID +STDCALL +ExSystemTimeToLocalTime ( + PLARGE_INTEGER SystemTime, + PLARGE_INTEGER LocalTime + ) +{ + LocalTime->QuadPart = SystemTime->QuadPart - + _SystemTimeZoneInfo.Bias * TICKSPERMINUTE; +} + +/* EOF */ diff --git a/ntoskrnl/ex/win32k.c b/ntoskrnl/ex/win32k.c new file mode 100644 index 0000000..d8461e7 --- /dev/null +++ b/ntoskrnl/ex/win32k.c @@ -0,0 +1,318 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: kernel/ex/win32k.c + * PURPOSE: Executive Win32 subsystem support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 04-06-2001 CSH Created + */ +#include +#include +#include +#include + +#define NDEBUG +#include + +/* DATA **********************************************************************/ + +POBJECT_TYPE EXPORTED ExWindowStationObjectType = NULL; +POBJECT_TYPE EXPORTED ExDesktopObjectType = NULL; + +static GENERIC_MAPPING ExpWindowStationMapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_ALL_ACCESS }; + +static GENERIC_MAPPING ExpDesktopMapping = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_ALL_ACCESS }; + +/* FUNCTIONS ****************************************************************/ + + +NTSTATUS STDCALL +ExpWinStaObjectCreate(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes) +{ + PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)ObjectBody; + UNICODE_STRING UnicodeString; + NTSTATUS Status; + + if (RemainingPath == NULL) + { + return STATUS_SUCCESS; + } + + if (wcschr((RemainingPath + 1), '\\') != NULL) + { + return STATUS_UNSUCCESSFUL; + } + + RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1)); + + DPRINT("Creating window station (0x%X) Name (%wZ)\n", WinSta, &UnicodeString); + + Status = RtlCreateUnicodeString(&WinSta->Name, UnicodeString.Buffer); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + KeInitializeSpinLock(&WinSta->Lock); + + InitializeListHead(&WinSta->DesktopListHead); + +#if 1 + WinSta->AtomTable = NULL; +#endif + + Status = RtlCreateAtomTable(37, &WinSta->AtomTable); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&WinSta->Name); + return Status; + } + + DPRINT("Window station successfully created. Name (%wZ)\n", &WinSta->Name); + + return STATUS_SUCCESS; +} + +VOID STDCALL +ExpWinStaObjectDelete(PVOID DeletedObject) +{ + PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeletedObject; + + DPRINT("Deleting window station (0x%X)\n", WinSta); + + RtlDestroyAtomTable(WinSta->AtomTable); + + RtlFreeUnicodeString(&WinSta->Name); +} + +PVOID +ExpWinStaObjectFind(PWINSTATION_OBJECT WinStaObject, + PWSTR Name, + ULONG Attributes) +{ + PLIST_ENTRY Current; + PDESKTOP_OBJECT CurrentObject; + + DPRINT("WinStaObject (0x%X) Name (%wS)\n", WinStaObject, Name); + + if (Name[0] == 0) + { + return NULL; + } + + Current = WinStaObject->DesktopListHead.Flink; + while (Current != &WinStaObject->DesktopListHead) + { + CurrentObject = CONTAINING_RECORD(Current, DESKTOP_OBJECT, ListEntry); + DPRINT("Scanning %wZ for %wS\n", &CurrentObject->Name, Name); + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if (_wcsicmp(CurrentObject->Name.Buffer, Name) == 0) + { + DPRINT("Found desktop at (0x%X)\n", CurrentObject); + return CurrentObject; + } + } + else + { + if (wcscmp(CurrentObject->Name.Buffer, Name) == 0) + { + DPRINT("Found desktop at (0x%X)\n", CurrentObject); + return CurrentObject; + } + } + Current = Current->Flink; + } + + DPRINT("Returning NULL\n"); + + return NULL; +} + +NTSTATUS STDCALL +ExpWinStaObjectParse(PVOID Object, + PVOID *NextObject, + PUNICODE_STRING FullPath, + PWSTR *Path, + ULONG Attributes) +{ + PVOID FoundObject; + NTSTATUS Status; + PWSTR End; + + DPRINT("Object (0x%X) Path (0x%X) *Path (%wS)\n", Object, Path, *Path); + + *NextObject = NULL; + + if ((Path == NULL) || ((*Path) == NULL)) + { + return STATUS_SUCCESS; + } + + End = wcschr((*Path) + 1, '\\'); + if (End != NULL) + { + DPRINT("Name contains illegal characters\n"); + return STATUS_UNSUCCESSFUL; + } + + FoundObject = ExpWinStaObjectFind(Object, (*Path) + 1, Attributes); + if (FoundObject == NULL) + { + DPRINT("Name was not found\n"); + return STATUS_UNSUCCESSFUL; + } + + Status = ObReferenceObjectByPointer( + FoundObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + + *Path = NULL; + + return Status; +} + +NTSTATUS STDCALL +ExpDesktopObjectCreate(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + struct _OBJECT_ATTRIBUTES* ObjectAttributes) +{ + PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody; + UNICODE_STRING UnicodeString; + + if (RemainingPath == NULL) + { + return STATUS_SUCCESS; + } + + if (wcschr((RemainingPath + 1), '\\') != NULL) + { + return STATUS_UNSUCCESSFUL; + } + + RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1)); + + DPRINT("Creating desktop (0x%X) Name (%wZ)\n", Desktop, &UnicodeString); + + KeInitializeSpinLock(&Desktop->Lock); + + Desktop->WindowStation = (PWINSTATION_OBJECT)Parent; + + /* Put the desktop on the window station's list of associcated desktops */ + ExInterlockedInsertTailList( + &Desktop->WindowStation->DesktopListHead, + &Desktop->ListEntry, + &Desktop->WindowStation->Lock); + + return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer); +} + +VOID STDCALL +ExpDesktopObjectDelete(PVOID DeletedObject) +{ + PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject; + KIRQL OldIrql; + + DPRINT("Deleting desktop (0x%X)\n", Desktop); + + /* Remove the desktop from the window station's list of associcated desktops */ + KeAcquireSpinLock(&Desktop->WindowStation->Lock, &OldIrql); + RemoveEntryList(&Desktop->ListEntry); + KeReleaseSpinLock(&Desktop->WindowStation->Lock, OldIrql); + + RtlFreeUnicodeString(&Desktop->Name); +} + +VOID +ExpWin32kInit(VOID) +{ + /* Create window station object type */ + ExWindowStationObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + if (ExWindowStationObjectType == NULL) + { + CPRINT("Could not create window station object type\n"); + KeBugCheck(0); + } + + ExWindowStationObjectType->Tag = TAG('W', 'I', 'N', 'S'); + ExWindowStationObjectType->TotalObjects = 0; + ExWindowStationObjectType->TotalHandles = 0; + ExWindowStationObjectType->MaxObjects = ULONG_MAX; + ExWindowStationObjectType->MaxHandles = ULONG_MAX; + ExWindowStationObjectType->PagedPoolCharge = 0; + ExWindowStationObjectType->NonpagedPoolCharge = sizeof(WINSTATION_OBJECT); + ExWindowStationObjectType->Mapping = &ExpWindowStationMapping; + ExWindowStationObjectType->Dump = NULL; + ExWindowStationObjectType->Open = NULL; + ExWindowStationObjectType->Close = NULL; + ExWindowStationObjectType->Delete = ExpWinStaObjectDelete; + ExWindowStationObjectType->Parse = ExpWinStaObjectParse; + ExWindowStationObjectType->Security = NULL; + ExWindowStationObjectType->QueryName = NULL; + ExWindowStationObjectType->OkayToClose = NULL; + ExWindowStationObjectType->Create = ExpWinStaObjectCreate; + ExWindowStationObjectType->DuplicationNotify = NULL; + RtlInitUnicodeStringFromLiteral(&ExWindowStationObjectType->TypeName, L"WindowStation"); + + /* Create desktop object type */ + ExDesktopObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + if (ExDesktopObjectType == NULL) + { + CPRINT("Could not create desktop object type\n"); + KeBugCheck(0); + } + + ExDesktopObjectType->Tag = TAG('D', 'E', 'S', 'K'); + ExDesktopObjectType->TotalObjects = 0; + ExDesktopObjectType->TotalHandles = 0; + ExDesktopObjectType->MaxObjects = ULONG_MAX; + ExDesktopObjectType->MaxHandles = ULONG_MAX; + ExDesktopObjectType->PagedPoolCharge = 0; + ExDesktopObjectType->NonpagedPoolCharge = sizeof(DESKTOP_OBJECT); + ExDesktopObjectType->Mapping = &ExpDesktopMapping; + ExDesktopObjectType->Dump = NULL; + ExDesktopObjectType->Open = NULL; + ExDesktopObjectType->Close = NULL; + ExDesktopObjectType->Delete = ExpDesktopObjectDelete; + ExDesktopObjectType->Parse = NULL; + ExDesktopObjectType->Security = NULL; + ExDesktopObjectType->QueryName = NULL; + ExDesktopObjectType->OkayToClose = NULL; + ExDesktopObjectType->Create = ExpDesktopObjectCreate; + ExDesktopObjectType->DuplicationNotify = NULL; + RtlInitUnicodeStringFromLiteral(&ExDesktopObjectType->TypeName, L"Desktop"); +} + +/* EOF */ diff --git a/ntoskrnl/ex/work.c b/ntoskrnl/ex/work.c new file mode 100644 index 0000000..0d8ea7d --- /dev/null +++ b/ntoskrnl/ex/work.c @@ -0,0 +1,194 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: mkernel/kernel/work.c + * PURPOSE: Manage system work queues + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 29/06/98: Created + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include + +#define NDEBUG +#include + +/* DEFINES *******************************************************************/ + +#define NUMBER_OF_WORKER_THREADS (5) + +/* TYPES *********************************************************************/ + +typedef struct _WORK_QUEUE +{ + /* + * PURPOSE: Head of the list of waiting work items + */ + LIST_ENTRY Head; + + /* + * PURPOSE: Sychronize access to the work queue + */ + KSPIN_LOCK Lock; + + /* + * PURPOSE: Worker threads with nothing to do wait on this event + */ + KSEMAPHORE Sem; + + /* + * PURPOSE: Thread associated with work queue + */ + HANDLE Thread[NUMBER_OF_WORKER_THREADS]; +} WORK_QUEUE, *PWORK_QUEUE; + +/* GLOBALS *******************************************************************/ + +/* + * PURPOSE: Queue of items waiting to be processed at normal priority + */ +WORK_QUEUE EiNormalWorkQueue; + +WORK_QUEUE EiCriticalWorkQueue; + +WORK_QUEUE EiHyperCriticalWorkQueue; + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS STDCALL +ExWorkerThreadEntryPoint(PVOID context) +/* + * FUNCTION: Entry point for a worker thread + * ARGUMENTS: + * context = Parameters + * RETURNS: Status + * NOTE: To kill a worker thread you must queue an item whose callback + * calls PsTerminateSystemThread + */ +{ + PWORK_QUEUE queue = (PWORK_QUEUE)context; + PWORK_QUEUE_ITEM item; + PLIST_ENTRY current; + + for(;;) + { + current = ExInterlockedRemoveHeadList(&queue->Head, + &queue->Lock); + if (current!=NULL) + { + item = CONTAINING_RECORD(current,WORK_QUEUE_ITEM,Entry); + item->Routine(item->Context); + } + else + { + KeWaitForSingleObject((PVOID)&queue->Sem, + Executive, + KernelMode, + FALSE, + NULL); + DPRINT("Woke from wait\n"); + } + } +} + +static VOID ExInitializeWorkQueue(PWORK_QUEUE WorkQueue, + KPRIORITY Priority) +{ + ULONG i; + PETHREAD Thread; + + InitializeListHead(&WorkQueue->Head); + KeInitializeSpinLock(&WorkQueue->Lock); + KeInitializeSemaphore(&WorkQueue->Sem, + 0, + 256); + for (i=0; iThread[i], + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + ExWorkerThreadEntryPoint, + WorkQueue); + ObReferenceObjectByHandle(WorkQueue->Thread[i], + THREAD_ALL_ACCESS, + PsThreadType, + KernelMode, + (PVOID*)&Thread, + NULL); + KeSetPriorityThread(&Thread->Tcb, + Priority); + ObDereferenceObject(Thread); + } +} + +VOID ExInitializeWorkerThreads(VOID) +{ + ExInitializeWorkQueue(&EiNormalWorkQueue, + LOW_PRIORITY); + ExInitializeWorkQueue(&EiCriticalWorkQueue, + LOW_REALTIME_PRIORITY); + ExInitializeWorkQueue(&EiHyperCriticalWorkQueue, + HIGH_PRIORITY); +} + +VOID STDCALL +ExQueueWorkItem (PWORK_QUEUE_ITEM WorkItem, + WORK_QUEUE_TYPE QueueType) +/* + * FUNCTION: Inserts a work item in a queue for one of the system worker + * threads to process + * ARGUMENTS: + * WorkItem = Item to insert + * QueueType = Queue to insert it in + */ +{ + assert(WorkItem!=NULL); + ASSERT_IRQL(DISPATCH_LEVEL); + + /* + * Insert the item in the appropiate queue and wake up any thread + * waiting for something to do + */ + switch(QueueType) + { + case DelayedWorkQueue: + ExInterlockedInsertTailList(&EiNormalWorkQueue.Head, + &WorkItem->Entry, + &EiNormalWorkQueue.Lock); + KeReleaseSemaphore(&EiNormalWorkQueue.Sem, + IO_NO_INCREMENT, + 1, + FALSE); + break; + + case CriticalWorkQueue: + ExInterlockedInsertTailList(&EiCriticalWorkQueue.Head, + &WorkItem->Entry, + &EiCriticalWorkQueue.Lock); + KeReleaseSemaphore(&EiCriticalWorkQueue.Sem, + IO_NO_INCREMENT, + 1, + FALSE); + break; + + case HyperCriticalWorkQueue: + ExInterlockedInsertTailList(&EiHyperCriticalWorkQueue.Head, + &WorkItem->Entry, + &EiHyperCriticalWorkQueue.Lock); + KeReleaseSemaphore(&EiHyperCriticalWorkQueue.Sem, + IO_NO_INCREMENT, + 1, + FALSE); + break; + + } +} + +/* EOF */ diff --git a/ntoskrnl/ex/zone.c b/ntoskrnl/ex/zone.c new file mode 100644 index 0000000..404f7fe --- /dev/null +++ b/ntoskrnl/ex/zone.c @@ -0,0 +1,107 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/zone.c + * PURPOSE: Implements zone buffers + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ****************************************************************/ + +#include + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS +STDCALL +ExExtendZone ( + PZONE_HEADER Zone, + PVOID Segment, + ULONG SegmentSize + ) +{ + PZONE_ENTRY entry; + PZONE_SEGMENT seg; + unsigned int i; + + seg = (PZONE_SEGMENT)Segment; + seg->size = SegmentSize; + + PushEntryList(&Zone->SegmentList,&seg->Entry); + + entry = (PZONE_ENTRY)( ((PVOID)seg) + sizeof(ZONE_SEGMENT) ); + + for (i=0;i<(SegmentSize / Zone->BlockSize);i++) + { + PushEntryList(&Zone->FreeList,&entry->Entry); + entry = (PZONE_ENTRY)(((PVOID)entry) + sizeof(ZONE_ENTRY) + + Zone->BlockSize); + } + return(STATUS_SUCCESS); +} + + +NTSTATUS +STDCALL +ExInterlockedExtendZone ( + PZONE_HEADER Zone, + PVOID Segment, + ULONG SegmentSize, + PKSPIN_LOCK Lock + ) +{ + NTSTATUS ret; + KIRQL oldlvl; + + KeAcquireSpinLock(Lock,&oldlvl); + ret = ExExtendZone(Zone,Segment,SegmentSize); + KeReleaseSpinLock(Lock,oldlvl); + return(ret); +} + + +NTSTATUS +STDCALL +ExInitializeZone ( + PZONE_HEADER Zone, + ULONG BlockSize, + PVOID InitialSegment, + ULONG InitialSegmentSize + ) +/* + * FUNCTION: Initalizes a zone header + * ARGUMENTS: + * Zone = zone header to be initialized + * BlockSize = Size (in bytes) of the allocation size of the zone + * InitialSegment = Initial segment of storage allocated by the + * caller + * InitialSegmentSize = Initial size of the segment + */ +{ + unsigned int i; + PZONE_SEGMENT seg; + PZONE_ENTRY entry; + + Zone->FreeList.Next=NULL; + Zone->SegmentList.Next=NULL; + Zone->BlockSize=BlockSize; + Zone->TotalSegmentSize = InitialSegmentSize; + + seg = (PZONE_SEGMENT)InitialSegment; + seg->size = InitialSegmentSize; + + PushEntryList(&Zone->SegmentList,&seg->Entry); + + entry = (PZONE_ENTRY)( ((PVOID)seg) + sizeof(ZONE_SEGMENT) ); + + for (i=0;i<(InitialSegmentSize / BlockSize);i++) + { + PushEntryList(&Zone->FreeList,&entry->Entry); + entry = (PZONE_ENTRY)(((PVOID)entry) + sizeof(ZONE_ENTRY) + BlockSize); + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/fs/.cvsignore b/ntoskrnl/fs/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/fs/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/fs/dbcsname.c b/ntoskrnl/fs/dbcsname.c new file mode 100644 index 0000000..b3e1575 --- /dev/null +++ b/ntoskrnl/fs/dbcsname.c @@ -0,0 +1,126 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/dbcsname.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDissectDbcs@16 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlDissectDbcs ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDoesDbcsContainWildCards@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlDoesDbcsContainWildCards ( + DWORD Unknown0 + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlIsDbcsInExpression@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlIsDbcsInExpression ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlIsFatDbcsLegal@20 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlIsFatDbcsLegal ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlIsHpfsDbcsLegal@20 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlIsHpfsDbcsLegal ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + return FALSE; +} + + +/* EOF */ diff --git a/ntoskrnl/fs/filelock.c b/ntoskrnl/fs/filelock.c new file mode 100644 index 0000000..5629977 --- /dev/null +++ b/ntoskrnl/fs/filelock.c @@ -0,0 +1,381 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/filelock.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlCheckLockForReadAccess@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE (Bo Branten) + * All this really does is pick out the lock parameters from + * the irp (io stack location?), get IoGetRequestorProcess, + * and pass values on to FsRtlFastCheckLockForRead. + * + */ +BOOLEAN +STDCALL +FsRtlCheckLockForReadAccess ( + IN PFILE_LOCK FileLock, + IN PIRP Irp + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlCheckLockForWriteAccess@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE (Bo Branten) + * All this really does is pick out the lock parameters from + * the irp (io stack location?), get IoGetRequestorProcess, + * and pass values on to FsRtlFastCheckLockForWrite. + */ +BOOLEAN +STDCALL +FsRtlCheckLockForWriteAccess ( + IN PFILE_LOCK FileLock, + IN PIRP Irp + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlFastCheckLockForRead@24 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlFastCheckLockForRead ( + IN PFILE_LOCK FileLock, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlFastCheckLockForWrite@24 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlFastCheckLockForWrite ( + IN PFILE_LOCK FileLock, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN ULONG Key, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlFastUnlockAll@16 + * FsRtlFastUnlockAllByKey@20 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +static +NTSTATUS +STDCALL +FsRtlpFastUnlockAllByKey ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN DWORD Key, /* FIXME: guess */ + IN BOOLEAN UseKey, /* FIXME: guess */ + IN PVOID Context OPTIONAL + ) +{ + /* FIXME: */ + return (STATUS_RANGE_NOT_LOCKED); +} + + +NTSTATUS +STDCALL +FsRtlFastUnlockAll ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN PVOID Context OPTIONAL + ) +{ + return FsRtlpFastUnlockAllByKey ( + FileLock, + FileObject, + Process, + 0, /* Key */ + FALSE, /* Do NOT use Key */ + Context + ); +} + + +NTSTATUS +STDCALL +FsRtlFastUnlockAllByKey ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PEPROCESS Process, + IN ULONG Key, + IN PVOID Context OPTIONAL + ) +{ + return FsRtlpFastUnlockAllByKey ( + FileLock, + FileObject, + Process, + Key, + TRUE, /* Use Key */ + Context + ); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlFastUnlockSingle@32 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS +STDCALL +FsRtlFastUnlockSingle ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN PVOID Context OPTIONAL, + IN BOOLEAN AlreadySynchronized + ) +{ + return (STATUS_RANGE_NOT_LOCKED); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlGetNextFileLock@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * NULL if no more locks. + * + * NOTE (Bo Branten) + * Internals: FsRtlGetNextFileLock uses + * FileLock->LastReturnedLockInfo and FileLock->LastReturnedLock + * as storage. LastReturnedLock is a pointer to the 'raw' lock + * inkl. double linked list, and FsRtlGetNextFileLock needs this + * to get next lock on subsequent calls with Restart = FALSE. + */ +PFILE_LOCK_INFO +STDCALL +FsRtlGetNextFileLock ( + IN PFILE_LOCK FileLock, + IN BOOLEAN Restart + ) +{ + return (NULL); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlInitializeFileLock@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlInitializeFileLock ( + IN PFILE_LOCK FileLock, + IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, + IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlPrivateLock@48 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * IoStatus->Status: STATUS_PENDING, STATUS_LOCK_NOT_GRANTED + * + * NOTE (Bo Branten) + * -Calls IoCompleteRequest if Irp + * -Uses exception handling / ExRaiseStatus with + * STATUS_INSUFFICIENT_RESOURCES + */ +BOOLEAN +STDCALL +FsRtlPrivateLock ( + IN PFILE_LOCK FileLock, + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PLARGE_INTEGER Length, + IN PEPROCESS Process, + IN ULONG Key, + IN BOOLEAN FailImmediately, + IN BOOLEAN ExclusiveLock, + OUT PIO_STATUS_BLOCK IoStatus, + IN PIRP Irp OPTIONAL, + IN PVOID Context, + IN BOOLEAN AlreadySynchronized + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlProcessFileLock@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * -STATUS_INVALID_DEVICE_REQUEST + * -STATUS_RANGE_NOT_LOCKED from unlock routines. + * -STATUS_PENDING, STATUS_LOCK_NOT_GRANTED from FsRtlPrivateLock + * (redirected IoStatus->Status). + * + * NOTE (Bo Branten) + * -switch ( Irp->CurrentStackLocation->MinorFunction ) + * lock: return FsRtlPrivateLock; + * unlocksingle: return FsRtlFastUnlockSingle; + * unlockall: return FsRtlFastUnlockAll; + * unlockallbykey: return FsRtlFastUnlockAllByKey; + * default: IofCompleteRequest with STATUS_INVALID_DEVICE_REQUEST; + * return STATUS_INVALID_DEVICE_REQUEST; + * + * -'AllwaysZero' is passed thru as 'AllwaysZero' to lock / unlock routines. + * -'Irp' is passet thru as 'Irp' to FsRtlPrivateLock. + */ +NTSTATUS +STDCALL +FsRtlProcessFileLock ( + IN PFILE_LOCK FileLock, + IN PIRP Irp, + IN PVOID Context OPTIONAL + ) +{ + return (STATUS_NOT_IMPLEMENTED); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlUninitializeFileLock@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlUninitializeFileLock ( + IN PFILE_LOCK FileLock + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAllocateFileLock@8 + * + * DESCRIPTION + * Only present in NT 5.0 or later. + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +PFILE_LOCK +STDCALL +FsRtlAllocateFileLock ( + IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, + IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL + ) +{ + return NULL; +} + +/* EOF */ diff --git a/ntoskrnl/fs/mcb.c b/ntoskrnl/fs/mcb.c new file mode 100644 index 0000000..184e49b --- /dev/null +++ b/ntoskrnl/fs/mcb.c @@ -0,0 +1,228 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/mcb.c + * + */ +#include +#include + +#include + +/********************************************************************** + * NAME EXPORTED + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTES + */ +BOOLEAN STDCALL +FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Lbn, + IN LONGLONG SectorCount) +{ + UNIMPLEMENTED + return(FALSE); +} + + +VOID +STDCALL +FsRtlAddMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ + UNIMPLEMENTED +} + + +BOOLEAN STDCALL +FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, + IN ULONG RunIndex, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG SectorCount) +{ + UNIMPLEMENTED + return(FALSE); +} + + +VOID +STDCALL +FsRtlGetNextMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + UNIMPLEMENTED +} + + +VOID STDCALL +FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, + IN POOL_TYPE PoolType) +{ + UNIMPLEMENTED + Mcb->PoolType = PoolType; +} + + +VOID +STDCALL +FsRtlInitializeMcb ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + UNIMPLEMENTED +} + + +BOOLEAN STDCALL +FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + OUT PLONGLONG Lbn OPTIONAL, + OUT PLONGLONG SectorCountFromLbn OPTIONAL, + OUT PLONGLONG StartingLbn OPTIONAL, + OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, + OUT PULONG Index OPTIONAL) +{ + UNIMPLEMENTED + return(FALSE); +} + + +BOOLEAN STDCALL +FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn) +{ + UNIMPLEMENTED + return(FALSE); +} + + +VOID +STDCALL +FsRtlLookupLastMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + UNIMPLEMENTED +} + + +VOID +STDCALL +FsRtlLookupMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + UNIMPLEMENTED +} + + +ULONG STDCALL +FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb) +{ + UNIMPLEMENTED + return(0); +} + + +VOID +STDCALL +FsRtlNumberOfRunsInMcb ( + DWORD Unknown0 + ) +{ + UNIMPLEMENTED +} + + +VOID STDCALL +FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount) +{ + UNIMPLEMENTED +} + + +VOID +STDCALL +FsRtlRemoveMcbEntry ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + UNIMPLEMENTED +} + + +BOOLEAN STDCALL +FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Amount) +{ + UNIMPLEMENTED + return(FALSE); +} + + +VOID STDCALL +FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, + IN LONGLONG Vbn) +{ + UNIMPLEMENTED +} + + +VOID +STDCALL +FsRtlTruncateMcb ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + UNIMPLEMENTED +} + + +VOID STDCALL +FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +FsRtlUninitializeMcb ( + DWORD Unknown0 + ) +{ + UNIMPLEMENTED +} + + +/* EOF */ + diff --git a/ntoskrnl/fs/mdl.c b/ntoskrnl/fs/mdl.c new file mode 100644 index 0000000..f64cbba --- /dev/null +++ b/ntoskrnl/fs/mdl.c @@ -0,0 +1,270 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/mdl.c + * + */ +#include +#include +#include + +/********************************************************************** + * NAME EXPORTED + * FsRtlMdlRead@24 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlMdlRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus + ) +{ + return FALSE; /* FIXME: call FsRtlMdlReadDev ? */ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlMdlReadComplete@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN STDCALL +FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject, + IN OUT PMDL Mdl) +{ + PDEVICE_OBJECT DeviceObject [2] = {NULL}; + PDRIVER_OBJECT DriverObject = NULL; + + /* + * Try fast I/O first + */ + DeviceObject [0] = IoGetRelatedDeviceObject (FileObject); + DriverObject = DeviceObject [0]->DriverObject; + if (NULL != DriverObject->FastIoDispatch) + { +#if 0 + if (IRP_MJ_READ <= DriverObject->FastIoDispatch->Count) + { + return FALSE; + } + if (NULL == DriverObject->FastIoDispatch->Dispatch [IRP_MJ_READ]) + { + return FALSE; + } + return DriverObject->FastIoDispatch->Dispatch + [IRP_MJ_READ] ( + Mdl, + NULL /* FIXME: how to get the IRP? */ + ); +#endif + } + /* + * Default I/O path + */ + DeviceObject [1] = IoGetBaseFileSystemDeviceObject (FileObject); + /* + * Did IoGetBaseFileSystemDeviceObject () + * returned the same device + * IoGetRelatedDeviceObject () returned? + */ + if (DeviceObject [1] != DeviceObject [0]) + { +#if 0 + DriverObject = DeviceObject [1]->DriverObject; + if (NULL != DriverObject->FastIoDispatch) + { + /* + * Check if the driver provides + * IRP_MJ_READ. + */ + if (IRP_MJ_READ <= DriverObject->FastIoDispatch->Count) + { + if (NULL == DriverObject->FastIoDispatch->Dispatch [IRP_MJ_READ]) + { + return FALSE; + } + } + } +#endif + DeviceObject [0] = DeviceObject [1]; + } + return FsRtlMdlReadCompleteDev ( + FileObject, + Mdl, + DeviceObject [0] + ); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlMdlReadCompleteDev@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v13. + * (CcMdlReadCompleteDev declared in internal/cc.h) + */ +BOOLEAN +STDCALL +FsRtlMdlReadCompleteDev ( + IN PFILE_OBJECT FileObject, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject + ) +{ + FileObject = FileObject; /* unused parameter */ + CcMdlReadCompleteDev (MdlChain, DeviceObject); + return TRUE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlMdlReadDev@28 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlMdlReadDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlMdlWriteComplete@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlMdlWriteComplete ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain + ) +{ + return FALSE; /* FIXME: call FsRtlMdlWriteCompleteDev ? */ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlMdlWriteCompleteDev@16 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlMdlWriteCompleteDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlPrepareMdlWrite@24 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlPrepareMdlWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus + ) +{ + return FALSE; /* call FsRtlPrepareMdlWriteDev ? */ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlPrepareMdlWriteDev@28 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN +STDCALL +FsRtlPrepareMdlWriteDev ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN ULONG LockKey, + OUT PMDL *MdlChain, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ) +{ + return FALSE; +} + + +/* EOF */ diff --git a/ntoskrnl/fs/name.c b/ntoskrnl/fs/name.c new file mode 100644 index 0000000..2a9e907 --- /dev/null +++ b/ntoskrnl/fs/name.c @@ -0,0 +1,112 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/name.c + * + */ +#include + +/* DATA */ + +PUCHAR * FsRtlLegalAnsiCharacterArray = NULL; + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAreNamesEqual@16 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v25. + * + */ +BOOLEAN +STDCALL +FsRtlAreNamesEqual ( + IN PUNICODE_STRING Name1, + IN PUNICODE_STRING Name2, + IN BOOLEAN IgnoreCase, + IN PWCHAR UpcaseTable OPTIONAL + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDissectName@16 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlDissectName ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3 + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDoesNameContainWildCards@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v12. + */ +BOOLEAN +STDCALL +FsRtlDoesNameContainWildCards ( + IN PUNICODE_STRING Name + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlIsNameInExpression@16 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v12. + */ +BOOLEAN +STDCALL +FsRtlIsNameInExpression ( + IN PUNICODE_STRING Expression, + IN PUNICODE_STRING Name, + IN BOOLEAN IgnoreCase, + IN PWCHAR UpcaseTable OPTIONAL + ) +{ + return FALSE; +} + + +/* EOF */ diff --git a/ntoskrnl/fs/notify.c b/ntoskrnl/fs/notify.c new file mode 100644 index 0000000..adb8087 --- /dev/null +++ b/ntoskrnl/fs/notify.c @@ -0,0 +1,248 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/notify.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyChangeDirectory@28 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlNotifyChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN PLIST_ENTRY NotifyList, + IN BOOLEAN WatchTree, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp + ) +{ + FsRtlNotifyFullChangeDirectory ( + NotifySync, + NotifyList, + FsContext, + FullDirectoryName, + WatchTree, + TRUE, /* IgnoreBuffer */ + CompletionFilter, + NotifyIrp, + NULL, + NULL + ); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyCleanup@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlNotifyCleanup ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyFullChangeDirectory@40 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlNotifyFullChangeDirectory ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PVOID FsContext, + IN PSTRING FullDirectoryName, + IN BOOLEAN WatchTree, + IN BOOLEAN IgnoreBuffer, + IN ULONG CompletionFilter, + IN PIRP NotifyIrp, + IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, + IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL + ) +{ + DbgPrint("%s()\n", __FUNCTION__); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyFullReportChange@36 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlNotifyFullReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN USHORT TargetNameOffset, + IN PSTRING StreamName OPTIONAL, + IN PSTRING NormalizedParentName OPTIONAL, + IN ULONG FilterMatch, + IN ULONG Action, + IN PVOID TargetContext + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyInitializeSync@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlNotifyInitializeSync ( + IN PNOTIFY_SYNC * NotifySync + ) +{ + *NotifySync = NULL; + *NotifySync = ExAllocatePoolWithTag ( + 0x10, // PoolType??? + sizeof (NOTIFY_SYNC), // NumberOfBytes = 0x28 + FSRTL_TAG + ); +#if 0 + *NotifySync->Unknown0 = 1; + *NotifySync->Unknown2 = 0; + *NotifySync->Unknown3 = 1; + *NotifySync->Unknown4 = 4; + *NotifySync->Unknown5 = 0; + *NotifySync->Unknown9 = 0; + *NotifySync->Unknown10 = 0; +#endif +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyReportChange@20 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlNotifyReportChange ( + IN PNOTIFY_SYNC NotifySync, + IN PLIST_ENTRY NotifyList, + IN PSTRING FullTargetName, + IN PUSHORT FileNamePartLength, + IN ULONG FilterMatch + ) +{ + FsRtlNotifyFullReportChange ( + NotifySync, + NotifyList, + FullTargetName, + (FullTargetName->Length - *FileNamePartLength), /*?*/ + NULL, + NULL, + FilterMatch, + 0, /* Action ? */ + NULL + ); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyUninitializeSync@4 + * + * DESCRIPTION + * Uninitialize a NOTIFY_SYNC object. + * + * ARGUMENTS + * NotifySync is the address of a pointer + * to a PNOTIFY_SYNC object previously initialized by + * FsRtlNotifyInitializeSync(). + * + * RETURN VALUE + * None. + */ +VOID +STDCALL +FsRtlNotifyUninitializeSync ( + IN OUT PNOTIFY_SYNC * NotifySync + ) +{ + if (NULL != *NotifySync) + { + ExFreePool (*NotifySync); + *NotifySync = NULL; + } +} + +/********************************************************************** + * NAME EXPORTED + * FsRtlNotifyVolumeEvent@8 + * + * DESCRIPTION + * NOTE: Only present in NT 5+. + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS +STDCALL +FsRtlNotifyVolumeEvent ( + IN PFILE_OBJECT FileObject, + IN ULONG EventCode + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/fs/oplock.c b/ntoskrnl/fs/oplock.c new file mode 100644 index 0000000..94c754e --- /dev/null +++ b/ntoskrnl/fs/oplock.c @@ -0,0 +1,123 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/oplock.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlCheckOplock@20 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +FsRtlCheckOplock(IN POPLOCK Oplock, + IN PIRP Irp, + IN PVOID Context, + IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, + IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlCurrentBatchOplock@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN STDCALL +FsRtlCurrentBatchOplock(IN POPLOCK Oplock) +{ + return(FALSE); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlInitializeOplock@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * Obsolete function. + */ +VOID STDCALL +FsRtlInitializeOplock(IN OUT POPLOCK Oplock) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlOplockFsctrl@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +FsRtlOplockFsctrl(IN POPLOCK Oplock, + IN PIRP Irp, + IN ULONG OpenCount) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlOplockIsFastIoPossible@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +BOOLEAN STDCALL +FsRtlOplockIsFastIoPossible(IN POPLOCK Oplock) +{ + return(FALSE); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlUninitializeOplock@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID STDCALL +FsRtlUninitializeOplock(IN POPLOCK Oplock) +{ +} + +/* EOF */ diff --git a/ntoskrnl/fs/pool.c b/ntoskrnl/fs/pool.c new file mode 100644 index 0000000..e3d735b --- /dev/null +++ b/ntoskrnl/fs/pool.c @@ -0,0 +1,151 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/pool.c + * + */ +#include +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAllocatePool@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * IFS_POOL_TAG is "FSrt" in mem view. + * + */ +PVOID +STDCALL +FsRtlAllocatePool ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes + ) +{ + PVOID Address; + + Address = ExAllocatePoolWithTag ( + PoolType, + NumberOfBytes, + IFS_POOL_TAG + ); + if (NULL == Address) + { + ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); + } + return Address; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAllocatePoolWithQuota@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * IFS_POOL_TAG is "FSrt" in mem view. + */ +PVOID +STDCALL +FsRtlAllocatePoolWithQuota ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes + ) +{ + PVOID Address; + + Address = ExAllocatePoolWithQuotaTag ( + PoolType, + NumberOfBytes, + IFS_POOL_TAG + ); + if (NULL == Address) + { + ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); + } + return Address; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAllocatePoolWithQuotaTag@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +PVOID +STDCALL +FsRtlAllocatePoolWithQuotaTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag + ) +{ + PVOID Address; + + Address = ExAllocatePoolWithQuotaTag ( + PoolType, + NumberOfBytes, + Tag + ); + if (NULL == Address) + { + ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); + } + return Address; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAllocatePoolWithTag@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +PVOID +STDCALL +FsRtlAllocatePoolWithTag ( + IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag + ) +{ + PVOID Address; + + Address = ExAllocatePoolWithTag ( + PoolType, + NumberOfBytes, + Tag + ); + if (NULL == Address) + { + ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES); + } + return Address; +} + + + +/* EOF */ diff --git a/ntoskrnl/fs/tunnel.c b/ntoskrnl/fs/tunnel.c new file mode 100644 index 0000000..2c6f96c --- /dev/null +++ b/ntoskrnl/fs/tunnel.c @@ -0,0 +1,123 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/tunnel.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAddToTunnelCache@32 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlAddToTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey, + IN PUNICODE_STRING ShortName, + IN PUNICODE_STRING LongName, + IN BOOLEAN KeyByShortName, + IN ULONG DataLength, + IN PVOID Data + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDeleteKeyFromTunnelCache@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlDeleteKeyFromTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDeleteTunnelCache@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlDeleteTunnelCache ( + IN PTUNNEL Cache + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlFindInTunnelCache@32 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlFindInTunnelCache ( + IN PTUNNEL Cache, + IN ULONGLONG DirectoryKey, + IN PUNICODE_STRING Name, + OUT PUNICODE_STRING ShortName, + OUT PUNICODE_STRING LongName, + IN OUT PULONG DataLength, + OUT PVOID Data + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlInitializeTunnelCache@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlInitializeTunnelCache ( + IN PTUNNEL Cache + ) +{ +} + + +/* EOF */ diff --git a/ntoskrnl/fs/unc.c b/ntoskrnl/fs/unc.c new file mode 100644 index 0000000..d3ea2c6 --- /dev/null +++ b/ntoskrnl/fs/unc.c @@ -0,0 +1,47 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/unc.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlDeregisterUncProvider@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID STDCALL +FsRtlDeregisterUncProvider(IN HANDLE Handle) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlRegisterUncProvider@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +FsRtlRegisterUncProvider(IN OUT PHANDLE Handle, + IN PUNICODE_STRING RedirectorDeviceName, + IN BOOLEAN MailslotsSupported) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +/* EOF */ diff --git a/ntoskrnl/fs/util.c b/ntoskrnl/fs/util.c new file mode 100644 index 0000000..c4599cc --- /dev/null +++ b/ntoskrnl/fs/util.c @@ -0,0 +1,317 @@ +/* $Id$ + * + * reactos/ntoskrnl/fs/util.c + * + */ +#include +#include + + +/********************************************************************** + * NAME EXPORTED + * FsRtlIsTotalDeviceFailure@4 + * + * DESCRIPTION + * Check if an NTSTATUS error code represents a + * disk hardware failure. + * + * ARGUMENTS + * NtStatus + * NTSTATUS to test. + * + * RETURN VALUE + * FALSE if either (NtStatus >= STATUS_SUCCESS), + * STATUS_CRC_ERROR, STATUS_DEVICE_DATA_ERROR; + * TRUE otherwise. + * + */ +BOOLEAN +STDCALL +FsRtlIsTotalDeviceFailure ( + IN NTSTATUS NtStatus + ) +{ + return ( + (NT_SUCCESS(NtStatus)) + || (STATUS_CRC_ERROR == NtStatus) + || (STATUS_DEVICE_DATA_ERROR == NtStatus) + ? FALSE + : TRUE + ); +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlIsNtstatusExpected/1 + * stack32 = 4 + * + * DESCRIPTION + * Check an NTSTATUS value is expected by the FS kernel + * subsystem. + * + * ARGUMENTS + * NtStatus + * NTSTATUS to test. + * + * RETURN VALUE + * TRUE if NtStatus is NOT one out of: + * - STATUS_ACCESS_VIOLATION + * - STATUS_ILLEGAL_INSTRUCTION + * - STATUS_DATATYPE_MISALIGNMENT + * - STATUS_INSTRUCTION_MISALIGNMENT + * which are the forbidden return stati in the FsRtl + * subsystem; FALSE otherwise. + * + * REVISIONS + * 2002-01-17 Fixed a bad bug reported by Bo Brantén. + * Up to version 1.8, this function's semantics was + * exactly the opposite! Thank you Bo. + */ +BOOLEAN +STDCALL +FsRtlIsNtstatusExpected ( + IN NTSTATUS NtStatus + ) +{ + return ( + (STATUS_DATATYPE_MISALIGNMENT == NtStatus) + || (STATUS_ACCESS_VIOLATION == NtStatus) + || (STATUS_ILLEGAL_INSTRUCTION == NtStatus) + || (STATUS_INSTRUCTION_MISALIGNMENT == NtStatus) + ) + ? FALSE + : TRUE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlNormalizeNtstatus@8 + * + * DESCRIPTION + * Normalize an NTSTATUS value for using in the FS subsystem. + * + * ARGUMENTS + * NtStatusToNormalize + * NTSTATUS to normalize. + * NormalizedNtStatus + * NTSTATUS to return if the NtStatusToNormalize + * value is unexpected by the FS kernel subsystem. + * + * RETURN VALUE + * NtStatusToNormalize if it is an expected value, + * otherwise NormalizedNtStatus. + */ +NTSTATUS +STDCALL +FsRtlNormalizeNtstatus ( + IN NTSTATUS NtStatusToNormalize, + IN NTSTATUS NormalizedNtStatus + ) +{ + return + (TRUE == FsRtlIsNtstatusExpected(NtStatusToNormalize)) + ? NtStatusToNormalize + : NormalizedNtStatus; +} + + +/********************************************************************** + * Miscellanea (they may fit somewhere else) + *********************************************************************/ + + +/********************************************************************** + * NAME EXPORTED + * FsRtlAllocateResource@0 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +DWORD +STDCALL +FsRtlAllocateResource (VOID) +{ + return 0; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlBalanceReads@4 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +DWORD +STDCALL +FsRtlBalanceReads ( + DWORD Unknown0 + ) +{ + return 0; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlCopyRead@32 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v12. + * + */ +BOOLEAN +STDCALL +FsRtlCopyRead ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + OUT PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlCopyWrite@32 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v12. + */ +BOOLEAN +STDCALL +FsRtlCopyWrite ( + IN PFILE_OBJECT FileObject, + IN PLARGE_INTEGER FileOffset, + IN ULONG Length, + IN BOOLEAN Wait, + IN ULONG LockKey, + IN PVOID Buffer, + OUT PIO_STATUS_BLOCK IoStatus, + IN PDEVICE_OBJECT DeviceObject + ) +{ + return FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlGetFileSize@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS +STDCALL +FsRtlGetFileSize ( + IN PFILE_OBJECT FileObject, + IN OUT PLARGE_INTEGER FileSize + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlPostPagingFileStackOverflow@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlPostPagingFileStackOverflow ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlPostStackOverflow@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +VOID +STDCALL +FsRtlPostStackOverflow ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ +} + + +/********************************************************************** + * NAME EXPORTED + * FsRtlSyncVolumes@12 + * + * DESCRIPTION + * Obsolete function. + * + * ARGUMENTS + * + * RETURN VALUE + * It always returns STATUS_SUCCESS. + */ +NTSTATUS +STDCALL +FsRtlSyncVolumes ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + return STATUS_SUCCESS; +} + + +/* EOF */ + diff --git a/ntoskrnl/include/internal/arch/ke.h b/ntoskrnl/include/internal/arch/ke.h new file mode 100644 index 0000000..2973640 --- /dev/null +++ b/ntoskrnl/include/internal/arch/ke.h @@ -0,0 +1,30 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_ARCH_KE_H +#define __NTOSKRNL_INCLUDE_INTERNAL_ARCH_KE_H + +#ifdef i386 +#include "../i386/ke.h" +#else +#error "Unknown processor" +#endif + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_ARCH_KE_H */ + +/* EOF */ diff --git a/ntoskrnl/include/internal/arch/mm.h b/ntoskrnl/include/internal/arch/mm.h new file mode 100644 index 0000000..1622a69 --- /dev/null +++ b/ntoskrnl/include/internal/arch/mm.h @@ -0,0 +1,28 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_ARCH_MM_H +#define __NTOSKRNL_INCLUDE_INTERNAL_ARCH_MM_H + +#ifdef i386 +#include +#else +#error "Unknown processor" +#endif + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_ARCH_MM_H */ diff --git a/ntoskrnl/include/internal/arch/ps.h b/ntoskrnl/include/internal/arch/ps.h new file mode 100644 index 0000000..8d3d0ef --- /dev/null +++ b/ntoskrnl/include/internal/arch/ps.h @@ -0,0 +1,33 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_ARCH_PS_H +#define __NTOSKRNL_INCLUDE_INTERNAL_ARCH_PS_H + +#ifdef i386 +#include +#define KiArchContextSwitch Ki386ContextSwitch +#define KiArchInitThread Ke386InitThread +#define KiArchInitThreadWithContext Ke386InitThreadWithContext +#else +#error "Unknown processor" +#endif + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_ARCH_PS_H */ + +/* EOF */ diff --git a/ntoskrnl/include/internal/cc.h b/ntoskrnl/include/internal/cc.h new file mode 100644 index 0000000..b698d24 --- /dev/null +++ b/ntoskrnl/include/internal/cc.h @@ -0,0 +1,89 @@ +#ifndef __INCLUDE_INTERNAL_CC_H +#define __INCLUDE_INTERNAL_CC_H +/* $Id$ */ +#include + +typedef struct _BCB +{ + LIST_ENTRY BcbSegmentListHead; + PFILE_OBJECT FileObject; + ULONG CacheSegmentSize; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + KSPIN_LOCK BcbLock; + ULONG RefCount; +} BCB; + +typedef struct _CACHE_SEGMENT +{ + /* Base address of the region where the cache segment data is mapped. */ + PVOID BaseAddress; + /* + * Memory area representing the region where the cache segment data is + * mapped. + */ + struct _MEMORY_AREA* MemoryArea; + /* Are the contents of the cache segment data valid. */ + BOOLEAN Valid; + /* Are the contents of the cache segment data newer than those on disk. */ + BOOLEAN Dirty; + ULONG MappedCount; + /* Entry in the list of segments for this BCB. */ + LIST_ENTRY BcbSegmentListEntry; + /* Entry in the list of segments which are dirty. */ + LIST_ENTRY DirtySegmentListEntry; + /* Entry in the list of segments. */ + LIST_ENTRY CacheSegmentListEntry; + LIST_ENTRY CacheSegmentLRUListEntry; + /* Offset in the file which this cache segment maps. */ + ULONG FileOffset; + /* Lock. */ + FAST_MUTEX Lock; + /* Number of references. */ + ULONG ReferenceCount; + /* Pointer to the BCB for the file which this cache segment maps data for. */ + PBCB Bcb; + /* Pointer to the next cache segment in a chain. */ + struct _CACHE_SEGMENT* NextInChain; +} CACHE_SEGMENT; + +VOID STDCALL +CcMdlReadCompleteDev (IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject); +NTSTATUS +CcRosGetCacheSegment(PBCB Bcb, + ULONG FileOffset, + PULONG BaseOffset, + PVOID* BaseAddress, + PBOOLEAN UptoDate, + PCACHE_SEGMENT* CacheSeg); +VOID +CcInitView(VOID); + + +NTSTATUS STDCALL CcRosFreeCacheSegment(PBCB, PCACHE_SEGMENT); + +NTSTATUS ReadCacheSegment(PCACHE_SEGMENT CacheSeg); + +NTSTATUS WriteCacheSegment(PCACHE_SEGMENT CacheSeg); + +VOID CcInit(VOID); +NTSTATUS +CcRosUnmapCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty); +NTSTATUS +CcRosSuggestFreeCacheSegment(PBCB Bcb, ULONG FileOffset, BOOLEAN NowDirty); +NTSTATUS +CcRosGetCacheSegmentChain(PBCB Bcb, + ULONG FileOffset, + ULONG Length, + PCACHE_SEGMENT* CacheSeg); +VOID CcInitCacheZeroPage(VOID); +NTSTATUS +CcRosMarkDirtyCacheSegment(PBCB Bcb, ULONG FileOffset); +NTSTATUS +CcRosFlushDirtyPages(ULONG Target, PULONG Count); + +VOID CcRosDereferenceCache(PFILE_OBJECT FileObject); +VOID CcRosReferenceCache(PFILE_OBJECT FileObject); + +#endif diff --git a/ntoskrnl/include/internal/config.h b/ntoskrnl/include/internal/config.h new file mode 100644 index 0000000..c92a509 --- /dev/null +++ b/ntoskrnl/include/internal/config.h @@ -0,0 +1,7 @@ +#ifndef __DEPRECATED_INTERNAL_CONFIG_H +#define __DEPRECATED__INTERNAL_CONFIG_H + +/* Moved to /include/roscfg.h */ +#include + +#endif /* __DEPRECATED_INTERNAL_CONFIG_H */ diff --git a/ntoskrnl/include/internal/ctype.h b/ntoskrnl/include/internal/ctype.h new file mode 100644 index 0000000..8b36906 --- /dev/null +++ b/ntoskrnl/include/internal/ctype.h @@ -0,0 +1,76 @@ +#ifndef _LINUX_CTYPE_H +#define _LINUX_CTYPE_H + + +#ifdef USE_OLD_CTYPE_IMPLEMENTATION + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +extern unsigned char _ctype[]; +extern char _ctmp; + +#define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D)) +#define isalpha(c) ((_ctype+1)[c]&(_U|_L)) +#define iscntrl(c) ((_ctype+1)[c]&(_C)) +#define isdigit(c) ((_ctype+1)[c]&(_D)) +#define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D)) +#define islower(c) ((_ctype+1)[c]&(_L)) +#define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP)) +#define ispunct(c) ((_ctype+1)[c]&(_P)) +#define isspace(c) ((_ctype+1)[c]&(_S)) +#define isupper(c) ((_ctype+1)[c]&(_U)) +#define isxdigit(c) ((_ctype+1)[c]&(_D|_X)) + +#define isascii(c) (((unsigned) c)<=0x7f) +#define toascii(c) (((unsigned) c)&0x7f) + +#define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp) +#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp) + +#else + +#define upalpha ('A' - 'a') + +extern inline int isspace(char c) +{ + return(c==' '||c=='\t'); +} + +extern inline char toupper(char c) +{ + if ((c>='a') && (c<='z')) return (c+upalpha); + return(c); +} + +extern inline int islower(char c) +{ + if ((c>='a') && (c<='z')) return 1; + return 0; +} + +extern inline int isdigit(char c) +{ + if ((c>='0') && (c<='9')) return 1; + return 0; +} + +extern inline int isxdigit(char c) +{ + if (((c>='0') && (c<='9')) || ((toupper(c)>='A') && (toupper(c)<='Z'))) + { + return 1; + } + return 0; +} + + +#endif + +#endif diff --git a/ntoskrnl/include/internal/dbg.h b/ntoskrnl/include/internal/dbg.h new file mode 100644 index 0000000..87b3d1e --- /dev/null +++ b/ntoskrnl/include/internal/dbg.h @@ -0,0 +1,19 @@ +#ifndef __INCLUDE_INTERNAL_DBG_H +#define __INCLUDE_INTERNAL_DBG_H + +#include +#include +#include + +NTSTATUS STDCALL +LpcSendDebugMessagePort(PEPORT Port, + PLPC_DBG_MESSAGE Message, + PLPC_DBG_MESSAGE Reply); +VOID +DbgkCreateThread(PVOID StartAddress); +ULONG +DbgkForwardException(EXCEPTION_RECORD Er, ULONG FirstChance); +BOOLEAN +DbgShouldPrint(PCH Filename); + +#endif /* __INCLUDE_INTERNAL_DBG_H */ diff --git a/ntoskrnl/include/internal/debug.h b/ntoskrnl/include/internal/debug.h new file mode 100644 index 0000000..148da1b --- /dev/null +++ b/ntoskrnl/include/internal/debug.h @@ -0,0 +1,93 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/debug.h + * PURPOSE: Useful debugging macros + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 28/05/98: Created + */ + +/* + * NOTES: Define DBG in configuration file for "checked" version + * Define NDEBUG before including this header to disable debugging + * macros + * Define NASSERT before including this header to disable assertions + */ + +#ifndef __INTERNAL_DEBUG +#define __INTERNAL_DEBUG + +#include +#include +#include + +#define UNIMPLEMENTED do {DbgPrint("%s at %s:%d is unimplemented, have a nice day\n",__FUNCTION__,__FILE__,__LINE__); for(;;); } while(0); + + +#ifdef DBG + +/* Assert only on "checked" version */ +#ifndef NASSERT +#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); } + +#define assertmsg(_c_, _m_) \ + if (!(_c_)) { \ + DbgPrint("(%s:%d)(%s) ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _m_ ; \ + KeBugCheck(0); \ + } + +#else + +#define assert(x) +#define assertmsg(_c_, _m_) + +#endif + +/* Print if using a "checked" version */ +#define CPRINT(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); + +#else /* DBG */ + +#define CPRINT(args...) +#define assert(x) +#define assertmsg(_c_, _m_) + +#endif /* DBG */ + +#define DPRINT1(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT1 do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0); + +#if defined(KDBG) && defined(NDEBUG) && defined(__NTOSKRNL__) + +#define DPRINT(args...) do { \ + if (DbgShouldPrint(__FILE__)) { \ + DbgPrint("(%s:%d) ",__FILE__,__LINE__); \ + DbgPrint(args); \ + } \ +} while(0); + +#define CHECKPOINT + +#else /* KDBG && NDEBUG && __NTOSKRNL__ */ + +#ifndef NDEBUG +#define DPRINT(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT do { DbgPrint("%s:%d\n",__FILE__,__LINE__); ExAllocatePool(NonPagedPool,0); } while(0); +#else /* NDEBUG */ +#define DPRINT(args...) +#define CHECKPOINT +#endif /* NDEBUG */ + +#endif /* KDBG && NDEBUG */ + +/* + * FUNCTION: Assert a maximum value for the current irql + * ARGUMENTS: + * x = Maximum irql + */ +#define ASSERT_IRQL(x) assert(KeGetCurrentIrql()<=(x)) +#define assert_irql(x) assert(KeGetCurrentIrql()<=(x)) + +#endif /* __INTERNAL_DEBUG */ diff --git a/ntoskrnl/include/internal/ex.h b/ntoskrnl/include/internal/ex.h new file mode 100644 index 0000000..75cc857 --- /dev/null +++ b/ntoskrnl/include/internal/ex.h @@ -0,0 +1,68 @@ +/* + * internal executive prototypes + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H +#define __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H + +#include +#include + +typedef struct _WINSTATION_OBJECT +{ + CSHORT Type; + CSHORT Size; + + KSPIN_LOCK Lock; + UNICODE_STRING Name; + LIST_ENTRY DesktopListHead; + PRTL_ATOM_TABLE AtomTable; + PVOID HandleTable; + struct _DESKTOP_OBJECT* ActiveDesktop; + /* FIXME: Clipboard */ +} WINSTATION_OBJECT, *PWINSTATION_OBJECT; + +typedef struct _DESKTOP_OBJECT +{ + CSHORT Type; + CSHORT Size; + LIST_ENTRY ListEntry; + KSPIN_LOCK Lock; + UNICODE_STRING Name; + /* Pointer to the associated window station. */ + struct _WINSTATION_OBJECT *WindowStation; + /* Head of the list of windows in this desktop. */ + LIST_ENTRY WindowListHead; + /* Pointer to the active queue. */ + PVOID ActiveMessageQueue; + /* Handle of the desktop window. */ + HANDLE DesktopWindow; + HANDLE PrevActiveWindow; +} DESKTOP_OBJECT, *PDESKTOP_OBJECT; + + +typedef VOID (*PLOOKASIDE_MINMAX_ROUTINE)( + POOL_TYPE PoolType, + ULONG Size, + PUSHORT MinimumDepth, + PUSHORT MaximumDepth); + +/* GLOBAL VARIABLES *********************************************************/ + +TIME_ZONE_INFORMATION SystemTimeZoneInfo; + +/* INITIALIZATION FUNCTIONS *************************************************/ + +VOID +ExpWin32kInit(VOID); + +VOID +ExInit (VOID); +VOID +ExInitTimeZoneInfo (VOID); +VOID +ExInitializeWorkerThreads(VOID); +VOID +ExpInitLookasideLists(VOID); + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */ diff --git a/ntoskrnl/include/internal/hal/bus.h b/ntoskrnl/include/internal/hal/bus.h new file mode 100644 index 0000000..5fb87c5 --- /dev/null +++ b/ntoskrnl/include/internal/hal/bus.h @@ -0,0 +1,121 @@ +/* + + */ + +#ifndef __INTERNAL_HAL_BUS_H +#define __INTERNAL_HAL_BUS_H + +struct _BUS_HANDLER; + +typedef NTSTATUS (STDCALL *pAdjustResourceList) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN OUT PCM_RESOURCE_LIST Resources + ); + +typedef NTSTATUS (STDCALL *pAssignSlotResources) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ); + +typedef ULONG (STDCALL *pGetSetBusData) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +typedef ULONG (STDCALL *pGetInterruptVector) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +typedef ULONG (STDCALL *pTranslateBusAddress) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +typedef struct _BUS_HANDLER +{ + LIST_ENTRY Entry; + INTERFACE_TYPE InterfaceType; + BUS_DATA_TYPE BusDataType; + ULONG BusNumber; + ULONG RefCount; + + pGetSetBusData GetBusData; + pGetSetBusData SetBusData; + pAdjustResourceList AdjustResourceList; + pAssignSlotResources AssignSlotResources; + pGetInterruptVector GetInterruptVector; + pTranslateBusAddress TranslateBusAddress; +} BUS_HANDLER, *PBUS_HANDLER; + + +/* FUNCTIONS *****************************************************************/ + +/* bus.c */ +PBUS_HANDLER +HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType, + BUS_DATA_TYPE BusDataType, + ULONG BusNumber); + +/* sysbus.h */ +ULONG STDCALL +HalpGetSystemInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity); + +BOOLEAN STDCALL +HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + +/* isa.c */ +BOOLEAN STDCALL +HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + +/* time.c */ +ULONG STDCALL +HalpGetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +ULONG STDCALL +HalpSetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +#endif /* __INTERNAL_HAL_BUS_H */ + +/* EOF */ \ No newline at end of file diff --git a/ntoskrnl/include/internal/hal/hal.h b/ntoskrnl/include/internal/hal/hal.h new file mode 100644 index 0000000..675a5d5 --- /dev/null +++ b/ntoskrnl/include/internal/hal/hal.h @@ -0,0 +1,48 @@ +/* + * + */ + +#ifndef __INTERNAL_HAL_HAL_H +#define __INTERNAL_HAL_HAL_H + +#include +#include + +/* + * FUNCTION: Probes for a BIOS32 extension + */ +VOID Hal_bios32_probe(VOID); + +/* + * FUNCTION: Determines if a a bios32 service is present + */ +BOOLEAN Hal_bios32_is_service_present(ULONG service); + +VOID HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock); +VOID HalResetDisplay (VOID); + +VOID HalpInitBusHandlers (VOID); + +/* irql.c */ +VOID HalpInitPICs(VOID); + +/* udelay.c */ +VOID HalpCalibrateStallExecution(VOID); + +/* pci.c */ +VOID HalpInitPciBus (VOID); + +/* enum.c */ +VOID HalpStartEnumerator (VOID); + +struct _ADAPTER_OBJECT { + int Channel; + PVOID PagePort; + PVOID CountPort; + PVOID OffsetPort; + KSPIN_LOCK SpinLock; + PVOID Buffer; + BOOLEAN Inuse; +}; + +#endif /* __INTERNAL_HAL_HAL_H */ diff --git a/ntoskrnl/include/internal/hal/mps.h b/ntoskrnl/include/internal/hal/mps.h new file mode 100644 index 0000000..6fc8e47 --- /dev/null +++ b/ntoskrnl/include/internal/hal/mps.h @@ -0,0 +1,435 @@ +#ifndef __INCLUDE_HAL_MPS +#define __INCLUDE_HAL_MPS + +#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */ +#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */ + +/* APIC Register Address Map */ +#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */ +#define APIC_VER 0x0030 /* Local APIC Version Register (R) */ +#define APIC_TPR 0x0080 /* Task Priority Register (R/W) */ +#define APIC_APR 0x0090 /* Arbitration Priority Register (R) */ +#define APIC_PPR 0x00A0 /* Processor Priority Register (R) */ +#define APIC_EOI 0x00B0 /* EOI Register (W) */ +#define APIC_LDR 0x00D0 /* Logical Destination Register (R/W) */ +#define APIC_DFR 0x00E0 /* Destination Format Register (0-27 R, 28-31 R/W) */ +#define APIC_SIVR 0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */ +#define APIC_ISR 0x0100 /* Interrupt Service Register 0-255 (R) */ +#define APIC_TMR 0x0180 /* Trigger Mode Register 0-255 (R) */ +#define APIC_IRR 0x0200 /* Interrupt Request Register 0-255 (r) */ +#define APIC_ESR 0x0280 /* Error Status Register (R) */ +#define APIC_ICR0 0x0300 /* Interrupt Command Register 0-31 (R/W) */ +#define APIC_ICR1 0x0310 /* Interrupt Command Register 32-63 (R/W) */ +#define APIC_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */ +#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */ +#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */ +#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */ +#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */ +#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */ +#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */ +#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */ + +#define APIC_ID_MASK (0xF << 24) +#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24) +#define APIC_VER_MASK 0xFF00FF +#define GET_APIC_VERSION(x)((x) & 0xFF) +#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF) + +#define APIC_TPR_PRI 0xFF +#define APIC_TPR_INT 0xF0 +#define APIC_TPR_SUB 0xF +#define APIC_TPR_MAX 0xFF /* Maximum priority */ +#define APIC_TPR_MIN 0x20 /* Minimum priority */ + +#define APIC_LDR_MASK (0xFF << 24) + +#define APIC_SIVR_ENABLE (0x1 << 8) +#define APIC_SIVR_FOCUS (0x1 << 9) + +#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */ + +#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */ +#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */ +#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */ +#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */ +#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */ +#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */ +#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */ + +/* Delivery Modes */ +#define APIC_DM_FIXED (0x0 << 8) +#define APIC_DM_LOWEST (0x1 << 8) +#define APIC_DM_SMI (0x2 << 8) +#define APIC_DM_REMRD (0x3 << 8) +#define APIC_DM_NMI (0x4 << 8) +#define APIC_DM_INIT (0x5 << 8) +#define APIC_DM_STARTUP (0x6 << 8) +#define APIC_DM_EXTINT (0x7 << 8) +#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) +#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8)) + +/* Destination Shorthand values */ +#define APIC_ICR0_DESTS_FIELD (0x0 << 0) +#define APIC_ICR0_DESTS_SELF (0x1 << 18) +#define APIC_ICR0_DESTS_ALL (0x2 << 18) +#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18) + +#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */ +#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */ + +#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) +#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24) + +#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3) +#define SET_APIC_TIMER_BASE(x) ((x) << 18) +#define APIC_TIMER_BASE_CLKIN 0x0 +#define APIC_TIMER_BASE_TMBASE 0x1 +#define APIC_TIMER_BASE_DIV 0x2 + +#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */ +#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */ +#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */ +#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */ +#define APIC_LVT_MASKED (0x1 << 16) /* Mask */ +#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */ + +#define APIC_LVT3_DM (0x7 << 8) +#define APIC_LVT3_IIPP (0x1 << 13) +#define APIC_LVT3_TM (0x1 << 15) +#define APIC_LVT3_MASKED (0x1 << 16) +#define APIC_LVT3_OS (0x1 << 17) + +#define APIC_TDCR_TMBASE (0x1 << 2) +#define APIC_TDCR_MASK 0x0F +#define APIC_TDCR_2 0x00 +#define APIC_TDCR_4 0x01 +#define APIC_TDCR_8 0x02 +#define APIC_TDCR_16 0x03 +#define APIC_TDCR_32 0x08 +#define APIC_TDCR_64 0x09 +#define APIC_TDCR_128 0x0A +#define APIC_TDCR_1 0x0B + +#define APIC_TARGET_SELF 0x100 +#define APIC_TARGET_ALL 0x200 +#define APIC_TARGET_ALL_BUT_SELF 0x300 + +#define IPI_CACHE_FLUSH 0x40 +#define IPI_INV_TLB 0x41 +#define IPI_INV_PTE 0x42 +#define IPI_INV_RESCHED 0x43 +#define IPI_STOP 0x44 + + +#define APIC_INTEGRATED(version) (version & 0xF0) + + +/* I/O APIC Register Address Map */ +#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */ +#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */ + +#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */ +#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */ +#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */ +#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */ + +#define IOAPIC_ID_MASK (0xF << 24) +#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24) +#define SET_IOAPIC_ID(x) ((x) << 24) + +#define IOAPIC_VER_MASK (0xFF) +#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK)) +#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */ +#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16) + +#define IOAPIC_ARB_MASK (0xF << 24) +#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24) + +#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */ +#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */ +#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */ +#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */ +#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */ +#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */ +#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */ +#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */ +#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */ +#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */ + +typedef struct _IOAPIC_ROUTE_ENTRY { + ULONG vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest priority + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { struct { ULONG + __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + + struct { ULONG + __reserved_1 : 24, + logical_dest : 8; + } logical; + } dest; +} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY; + +typedef struct _IOAPIC_INFO +{ + ULONG ApicId; /* APIC ID */ + ULONG ApicVersion; /* APIC version */ + ULONG ApicAddress; /* APIC address */ + ULONG EntryCount; /* Number of redirection entries */ +} IOAPIC_INFO, *PIOAPIC_INFO; + + +/* + * Local APIC timer IRQ vector is on a different priority level, + * to work around the 'lost local interrupt if more than 2 IRQ + * sources per level' errata. + */ +#define LOCAL_TIMER_VECTOR 0xEF + +#define CALL_FUNCTION_VECTOR 0xFB +#define RESCHEDULE_VECTOR 0xFC +#define INVALIDATE_TLB_VECTOR 0xFD +#define ERROR_VECTOR 0xFE +#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ + +/* + * First APIC vector available to drivers: (vectors 0x30-0xEE) + * we start at 0x31 to spread out vectors evenly between priority + * levels. + */ +#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_SYSTEM_VECTOR 0xEF +#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) + + +/* MP Floating Pointer Structure */ +#define MPF_SIGNATURE (('_' << 24) | ('P' << 16) | ('M' << 8) | '_') + +typedef struct __attribute__((packed)) _MP_FLOATING_POINTER +{ + ULONG Signature; /* _MP_ */ + ULONG Address; /* Physical Address Pointer (0 means no configuration table exist) */ + UCHAR Length; /* Structure length in 16-byte paragraphs */ + UCHAR Specification; /* Specification revision */ + UCHAR Checksum; /* Checksum */ + UCHAR Feature1; /* MP System Configuration Type */ + UCHAR Feature2; /* Bit 7 set for IMCR|PIC */ + UCHAR Feature3; /* Unused (0) */ + UCHAR Feature4; /* Unused (0) */ + UCHAR Feature5; /* Unused (0) */ +} __attribute__((packed)) MP_FLOATING_POINTER, *PMP_FLOATING_POINTER; + +#define FEATURE2_IMCRP 0x80 + +/* MP Configuration Table Header */ +#define MPC_SIGNATURE (('P' << 24) | ('M' << 16) | ('C' << 8) | 'P') + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_TABLE +{ + ULONG Signature; /* PCMP */ + USHORT Length; /* Size of configuration table */ + CHAR Specification; /* Specification Revision */ + CHAR Checksum; /* Checksum */ + CHAR Oem[8]; /* OEM ID */ + CHAR ProductId[12]; /* Product ID */ + ULONG OemTable; /* 0 if not present */ + USHORT OemTableSize; /* 0 if not present */ + USHORT EntryCount; /* Number of entries */ + ULONG LocalAPICAddress; /* Local APIC address */ + USHORT ExtTableLength; /* Extended Table Length */ + UCHAR ExtTableChecksum; /* Extended Table Checksum */ + UCHAR Reserved; /* Reserved */ +} __attribute__((packed)) MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE; + +/* MP Configuration Table Entries */ +#define MPCTE_PROCESSOR 0 /* One entry per processor */ +#define MPCTE_BUS 1 /* One entry per bus */ +#define MPCTE_IOAPIC 2 /* One entry per I/O APIC */ +#define MPCTE_INTSRC 3 /* One entry per bus interrupt source */ +#define MPCTE_LINTSRC 4 /* One entry per system interrupt source */ + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_PROCESSOR +{ + UCHAR Type; /* 0 */ + UCHAR ApicId; /* Local APIC ID for the processor */ + UCHAR ApicVersion; /* Local APIC version */ + UCHAR CpuFlags; /* CPU flags */ + ULONG CpuSignature; /* CPU signature */ + ULONG FeatureFlags; /* CPUID feature value */ + ULONG Reserved[2]; /* Reserved (0) */ +} __attribute__((packed)) MP_CONFIGURATION_PROCESSOR, + *PMP_CONFIGURATION_PROCESSOR; + +#define CPU_FLAG_ENABLED 1 /* Processor is available */ +#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */ + +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_BUS +{ + UCHAR Type; /* 1 */ + UCHAR BusId; /* Bus ID */ + UCHAR BusType[6]; /* Bus type */ +} __attribute__((packed)) MP_CONFIGURATION_BUS, *PMP_CONFIGURATION_BUS; + +#define MAX_BUS 32 + +#define MP_BUS_ISA 1 +#define MP_BUS_EISA 2 +#define MP_BUS_PCI 3 +#define MP_BUS_MCA 4 + +#define BUSTYPE_EISA "EISA" +#define BUSTYPE_ISA "ISA" +#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ +#define BUSTYPE_MCA "MCA" +#define BUSTYPE_VL "VL" /* Local bus */ +#define BUSTYPE_PCI "PCI" +#define BUSTYPE_PCMCIA "PCMCIA" +#define BUSTYPE_CBUS "CBUS" +#define BUSTYPE_CBUSII "CBUSII" +#define BUSTYPE_FUTURE "FUTURE" +#define BUSTYPE_MBI "MBI" +#define BUSTYPE_MBII "MBII" +#define BUSTYPE_MPI "MPI" +#define BUSTYPE_MPSA "MPSA" +#define BUSTYPE_NUBUS "NUBUS" +#define BUSTYPE_TC "TC" +#define BUSTYPE_VME "VME" +#define BUSTYPE_XPRESS "XPRESS" + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_IOAPIC +{ + UCHAR Type; /* 2 */ + UCHAR ApicId; /* I/O APIC ID */ + UCHAR ApicVersion; /* I/O APIC version */ + UCHAR ApicFlags; /* I/O APIC flags */ + ULONG ApicAddress; /* I/O APIC base address */ +} __attribute__((packed)) MP_CONFIGURATION_IOAPIC, *PMP_CONFIGURATION_IOAPIC; + +#define MAX_IOAPIC 2 + +#define MP_IOAPIC_USABLE 0x01 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTSRC +{ + UCHAR Type; /* 3 */ + UCHAR IrqType; /* Interrupt type */ + USHORT IrqFlag; /* Interrupt flags */ + UCHAR SrcBusId; /* Source bus ID */ + UCHAR SrcBusIrq; /* Source bus interrupt */ + UCHAR DstApicId; /* Destination APIC ID */ + UCHAR DstApicInt; /* Destination interrupt */ +} __attribute__((packed)) MP_CONFIGURATION_INTSRC, *PMP_CONFIGURATION_INTSRC; + +#define MAX_IRQ_SOURCE 128 + +#define INT_VECTORED 0 +#define INT_NMI 1 +#define INT_SMI 2 +#define INT_EXTINT 3 + +#define IRQDIR_DEFAULT 0 +#define IRQDIR_HIGH 1 +#define IRQDIR_LOW 3 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_INTLOCAL +{ + UCHAR Type; /* 4 */ + UCHAR IrqType; /* Interrupt type */ + USHORT IrqFlag; /* Interrupt flags */ + UCHAR SrcBusId; /* Source bus ID */ + UCHAR SrcBusIrq; /* Source bus interrupt */ + UCHAR DstApicId; /* Destination local APIC ID */ + UCHAR DstApicLInt; /* Destination local APIC interrupt */ +} MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL; + +#define MP_APIC_ALL 0xFF + + +static inline VOID ReadPentiumClock(PULARGE_INTEGER Count) +{ + register ULONG nLow; + register ULONG nHigh; + + __asm__ __volatile__ ("rdtsc" : "=a" (nLow), "=d" (nHigh)); + + Count->u.LowPart = nLow; + Count->u.HighPart = nHigh; +} + + +#define MAX_CPU 32 + + +typedef struct _CPU_INFO +{ + UCHAR Flags; /* CPU flags */ + UCHAR APICId; /* Local APIC ID */ + UCHAR APICVersion; /* Local APIC version */ + UCHAR MaxLVT; /* Number of LVT registers */ + ULONG BusSpeed; /* BUS speed */ + ULONG CoreSpeed; /* Core speed */ + UCHAR Padding[16-12]; /* Padding to 16-byte */ +} CPU_INFO, *PCPU_INFO; + +/* CPU flags */ +#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */ +#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */ +#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */ + + +typedef enum { + amPIC = 0, /* IMCR and PIC compatibility mode */ + amVWIRE /* Virtual Wire compatibility mode */ +} APIC_MODE; + + +#define pushfl(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) +#define popfl(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") + + +#define PIC_IRQS 16 + +/* Prototypes */ + +VOID HalpInitMPS(VOID); +volatile ULONG IOAPICRead(ULONG Apic, ULONG Offset); +VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value); +VOID IOAPICMaskIrq(ULONG Apic, ULONG Irq); +VOID IOAPICUnmaskIrq(ULONG Apic, ULONG Irq); +volatile inline ULONG APICRead(ULONG Offset); +inline VOID APICWrite(ULONG Offset, ULONG Value); +inline VOID APICSendEOI(VOID); +inline ULONG ThisCPU(VOID); +VOID APICSendIPI(ULONG Target, + ULONG DeliveryMode, + ULONG IntNum, + ULONG Level); +/* For debugging */ +VOID IOAPICDump(VOID); +VOID APICDump(VOID); + +#endif /* __INCLUDE_HAL_MPS */ + +/* EOF */ diff --git a/ntoskrnl/include/internal/handle.h b/ntoskrnl/include/internal/handle.h new file mode 100644 index 0000000..8d1f436 --- /dev/null +++ b/ntoskrnl/include/internal/handle.h @@ -0,0 +1,26 @@ +#ifndef __INTERNAL_HANDLE_H +#define __INTERNAL_HANDLE_H + + +typedef struct _RTL_HANDLE +{ + struct _RTL_HANDLE *Next; /* pointer to next free handle */ + PVOID Object; /* pointer to object */ +} RTL_HANDLE, *PRTL_HANDLE; + +typedef struct _RTL_HANDLE_TABLE +{ + ULONG TableSize; /* maximum number of handles */ + PRTL_HANDLE Handles; /* pointer to handle array */ + PRTL_HANDLE Limit; /* limit of pointers */ + PRTL_HANDLE FirstFree; /* pointer to first free handle */ + PRTL_HANDLE LastUsed; /* pointer to last allocated handle */ +} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE; + +VOID RtlpInitializeHandleTable(ULONG TableSize, PRTL_HANDLE_TABLE HandleTable); +VOID RtlpDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable); +BOOLEAN RtlpAllocateHandle(PRTL_HANDLE_TABLE HandleTable, PVOID Object, PULONG Index); +BOOLEAN RtlpFreeHandle(PRTL_HANDLE_TABLE HandleTable, ULONG Index); +PVOID RtlpMapHandleToPointer(PRTL_HANDLE_TABLE HandleTable, ULONG Index); + +#endif /* __INTERNAL_HANDLE_H */ diff --git a/ntoskrnl/include/internal/i386/fpu.h b/ntoskrnl/include/internal/i386/fpu.h new file mode 100644 index 0000000..9c38d53 --- /dev/null +++ b/ntoskrnl/include/internal/i386/fpu.h @@ -0,0 +1,28 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H +#define __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H + +extern ULONG HardwareMathSupport; + +VOID +KiCheckFPU(VOID); + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H */ diff --git a/ntoskrnl/include/internal/i386/ke.h b/ntoskrnl/include/internal/i386/ke.h new file mode 100644 index 0000000..89d81e6 --- /dev/null +++ b/ntoskrnl/include/internal/i386/ke.h @@ -0,0 +1,138 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H +#define __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H + +#define KTRAP_FRAME_DEBUGEBP (0x0) +#define KTRAP_FRAME_DEBUGEIP (0x4) +#define KTRAP_FRAME_DEBUGARGMARK (0x8) +#define KTRAP_FRAME_DEBUGPOINTER (0xC) +#define KTRAP_FRAME_TEMPCS (0x10) +#define KTRAP_FRAME_TEMPEIP (0x14) +#define KTRAP_FRAME_DR0 (0x18) +#define KTRAP_FRAME_DR1 (0x1C) +#define KTRAP_FRAME_DR2 (0x20) +#define KTRAP_FRAME_DR3 (0x24) +#define KTRAP_FRAME_DR6 (0x28) +#define KTRAP_FRAME_DR7 (0x2C) +#define KTRAP_FRAME_GS (0x30) +#define KTRAP_FRAME_RESERVED1 (0x32) +#define KTRAP_FRAME_ES (0x34) +#define KTRAP_FRAME_RESERVED2 (0x36) +#define KTRAP_FRAME_DS (0x38) +#define KTRAP_FRAME_RESERVED3 (0x3A) +#define KTRAP_FRAME_EDX (0x3C) +#define KTRAP_FRAME_ECX (0x40) +#define KTRAP_FRAME_EAX (0x44) +#define KTRAP_FRAME_PREVIOUS_MODE (0x48) +#define KTRAP_FRAME_EXCEPTION_LIST (0x4C) +#define KTRAP_FRAME_FS (0x50) +#define KTRAP_FRAME_RESERVED4 (0x52) +#define KTRAP_FRAME_EDI (0x54) +#define KTRAP_FRAME_ESI (0x58) +#define KTRAP_FRAME_EBX (0x5C) +#define KTRAP_FRAME_EBP (0x60) +#define KTRAP_FRAME_ERROR_CODE (0x64) +#define KTRAP_FRAME_EIP (0x68) +#define KTRAP_FRAME_CS (0x6C) +#define KTRAP_FRAME_EFLAGS (0x70) +#define KTRAP_FRAME_ESP (0x74) +#define KTRAP_FRAME_SS (0x78) +#define KTRAP_FRAME_RESERVED5 (0x7A) +#define KTRAP_FRAME_V86_ES (0x7C) +#define KTRAP_FRAME_RESERVED6 (0x7E) +#define KTRAP_FRAME_V86_DS (0x80) +#define KTRAP_FRAME_RESERVED7 (0x82) +#define KTRAP_FRAME_V86_FS (0x84) +#define KTRAP_FRAME_RESERVED8 (0x86) +#define KTRAP_FRAME_V86_GS (0x88) +#define KTRAP_FRAME_RESERVED9 (0x8A) +#define KTRAP_FRAME_SIZE (0x8C) + +#ifndef __ASM__ + +typedef struct _KTRAP_FRAME +{ + PVOID DebugEbp; + PVOID DebugEip; + PVOID DebugArgMark; + PVOID DebugPointer; + PVOID TempCs; + PVOID TempEip; + PVOID Dr0; + PVOID Dr1; + PVOID Dr2; + PVOID Dr3; + PVOID Dr6; + PVOID Dr7; + USHORT Gs; + USHORT Reserved1; + USHORT Es; + USHORT Reserved2; + USHORT Ds; + USHORT Reserved3; + ULONG Edx; + ULONG Ecx; + ULONG Eax; + ULONG PreviousMode; + PVOID ExceptionList; + USHORT Fs; + USHORT Reserved4; + ULONG Edi; + ULONG Esi; + ULONG Ebx; + ULONG Ebp; + ULONG ErrorCode; + ULONG Eip; + ULONG Cs; + ULONG Eflags; + ULONG Esp; + USHORT Ss; + USHORT Reserved5; + USHORT V86_Es; + USHORT Reserved6; + USHORT V86_Ds; + USHORT Reserved7; + USHORT V86_Fs; + USHORT Reserved8; + USHORT V86_Gs; + USHORT Reserved9; +} KTRAP_FRAME, *PKTRAP_FRAME; + +struct _KPCR; +VOID +KiInitializeGdt(struct _KPCR* Pcr); +VOID +Ki386ApplicationProcessorInitializeTSS(VOID); +VOID +Ki386BootInitializeTSS(VOID); +VOID +KiGdtPrepareForApplicationProcessorInit(ULONG Id); +VOID +Ki386InitializeLdt(VOID); +ULONG KeAllocateGdtSelector(ULONG Desc[2]); +VOID KeFreeGdtSelector(ULONG Entry); +VOID +NtEarlyInitVdm(VOID); + +#endif /* __ASM__ */ + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H */ + +/* EOF */ diff --git a/ntoskrnl/include/internal/i386/mm.h b/ntoskrnl/include/internal/i386/mm.h new file mode 100644 index 0000000..39f6485 --- /dev/null +++ b/ntoskrnl/include/internal/i386/mm.h @@ -0,0 +1,57 @@ +/* + * Lowlevel memory managment definitions + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_MM_H +#define __NTOSKRNL_INCLUDE_INTERNAL_I386_MM_H + +struct _EPROCESS; + +#if 0 +/* + * Page access attributes (or these together) + */ +#define PA_READ (1<<0) +#define PA_WRITE ((1<<0)+(1<<1)) +#define PA_EXECUTE PA_READ +#define PA_PCD (1<<4) +#define PA_PWT (1<<3) + +/* + * Page attributes + */ +#define PA_USER (1<<2) +#define PA_SYSTEM (0) +#endif + +#define PAGE_SIZE (4096) + +PULONG MmGetPageEntry(PVOID Address); + +#define KERNEL_BASE (0xc0000000) + +#define FLUSH_TLB __asm__("movl %cr3,%eax\n\tmovl %eax,%cr3\n\t") + +PULONG MmGetPageDirectory(VOID); + +#if 0 +extern inline PULONG get_page_directory(void) +{ + unsigned int page_dir=0; + __asm__("movl %%cr3,%0\n\t" + : "=r" (page_dir)); + return((PULONG)page_dir); +} +#endif + + +/* + * Amount of memory that can be mapped by a page table + */ +#define PAGE_TABLE_SIZE (4*1024*1024) + +#define PAGE_MASK(x) (x&(~0xfff)) +#define VADDR_TO_PT_OFFSET(x) (((x/1024)%4096)) +#define VADDR_TO_PD_OFFSET(x) ((x)/(4*1024*1024)) + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_MM_H */ diff --git a/ntoskrnl/include/internal/i386/ps.h b/ntoskrnl/include/internal/i386/ps.h new file mode 100644 index 0000000..f7eac43 --- /dev/null +++ b/ntoskrnl/include/internal/i386/ps.h @@ -0,0 +1,94 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_PS_H +#define __NTOSKRNL_INCLUDE_INTERNAL_I386_PS_H + +/* + * Defines for accessing KPCR and KTHREAD structure members + */ +#define KTHREAD_INITIAL_STACK 0x18 +#define KTHREAD_STACK_LIMIT 0x1C +#define KTHREAD_TEB 0x20 +#define KTHREAD_KERNEL_STACK 0x28 +#define KTHREAD_PREVIOUS_MODE 0x137 +#define KTHREAD_TRAP_FRAME 0x128 +#define KTHREAD_CALLBACK_STACK 0x120 + +#define ETHREAD_THREADS_PROCESS 0x234 + +#define KPROCESS_DIRECTORY_TABLE_BASE 0x18 + +#define KPCR_BASE 0xFF000000 + +#define KPCR_EXCEPTION_LIST 0x0 +#define KPCR_SELF 0x18 +#define KPCR_TSS 0x28 +#define KPCR_CURRENT_THREAD 0x124 + +#ifndef __ASM__ + +/* + * Processor Control Region + */ +typedef struct _KPCR +{ + PVOID ExceptionList; /* 00 */ + PVOID StackBase; /* 04 */ + PVOID StackLimit; /* 08 */ + PVOID SubSystemTib; /* 0C */ + PVOID Reserved1; /* 10 */ + PVOID ArbitraryUserPointer; /* 14 */ + struct _KPCR* Self; /* 18 */ + UCHAR ProcessorNumber; /* 1C */ + KIRQL Irql; /* 1D */ + UCHAR Reserved2[0x2]; /* 1E */ + PUSHORT IDT; /* 20 */ + PUSHORT GDT; /* 24 */ + KTSS* TSS; /* 28 */ + UCHAR Reserved3[0xF8]; /* 2C */ + struct _KTHREAD* CurrentThread; /* 124 */ +} __attribute__((packed)) KPCR, *PKPCR; + +static inline PKPCR KeGetCurrentKPCR(VOID) +{ + ULONG value; + + __asm__ __volatile__ ("movl %%fs:0x18, %0\n\t" + : "=r" (value) + : /* no inputs */ + ); + return((PKPCR)value); +} + +VOID +Ki386ContextSwitch(struct _KTHREAD* NewThread, + struct _KTHREAD* OldThread); +NTSTATUS +Ke386InitThread(struct _KTHREAD* Thread, PKSTART_ROUTINE fn, + PVOID StartContext); +NTSTATUS +Ke386InitThreadWithContext(struct _KTHREAD* Thread, PCONTEXT Context); +NTSTATUS +Ki386ValidateUserContext(PCONTEXT Context); + +#endif /* __ASM__ */ + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_PS_H */ + +/* EOF */ diff --git a/ntoskrnl/include/internal/i386/segment.h b/ntoskrnl/include/internal/i386/segment.h new file mode 100644 index 0000000..3e217d5 --- /dev/null +++ b/ntoskrnl/include/internal/i386/segment.h @@ -0,0 +1,50 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/include/internal/i386/segment.h + * PURPOSE: Segment selector definitions + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_SEGMENT_H +#define __NTOSKRNL_INCLUDE_INTERNAL_i386_SEGMENT_H + +#define NULL_SELECTOR (0x0) +#define KERNEL_CS (0x8) +#define KERNEL_DS (0x10) +#define USER_CS (0x18 + 0x3) +#define USER_DS (0x20 + 0x3) +/* Task State Segment */ +#define TSS_SELECTOR (0x28) +/* Processor Control Region */ +#define PCR_SELECTOR (0x30) +/* Thread Environment Block */ +#define TEB_SELECTOR (0x38 + 0x3) +#define RESERVED_SELECTOR (0x40) +/* Local Descriptor Table */ +#define LDT_SELECTOR (0x48) +#define TRAP_TSS_SELECTOR (0x50) + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_SEGMENT_H */ + +/* EOF */ + + diff --git a/ntoskrnl/include/internal/id.h b/ntoskrnl/include/internal/id.h new file mode 100644 index 0000000..43a2958 --- /dev/null +++ b/ntoskrnl/include/internal/id.h @@ -0,0 +1,19 @@ +/* + * Structure ids + */ + +#define InternalBaseType (0xcc) +#define InternalNotificationEvent (InternalBaseType + 1) +#define InternalSynchronizationEvent (InternalBaseType + 2) +#define InternalSemaphoreType (InternalBaseType + 3) +#define InternalProcessType (InternalBaseType + 4) +#define InternalThreadType (InternalBaseType + 5) +#define InternalFileType (InternalBaseType + 6) +#define InternalDriverType (InternalBaseType + 7) +#define InternalDeviceType (InternalBaseType + 8) +#define InternalMutexType (InternalBaseType + 9) +#define InternalNotificationTimer (InternalBaseType + 10) +#define InternalSynchronizationTimer (InternalBaseType + 11) +#define InternalQueueType (InternalBaseType + 12) + + diff --git a/ntoskrnl/include/internal/ifs.h b/ntoskrnl/include/internal/ifs.h new file mode 100644 index 0000000..c389266 --- /dev/null +++ b/ntoskrnl/include/internal/ifs.h @@ -0,0 +1,8 @@ +#ifndef __INCLUDE_INTERNAL_IFS_H +#define __INCLUDE_INTERNAL_IFS_H +/* $Id$ */ + +/* Look for "FSrt" in mem view */ +#define IFS_POOL_TAG 0x74725346 + +#endif diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h new file mode 100644 index 0000000..42532b9 --- /dev/null +++ b/ntoskrnl/include/internal/io.h @@ -0,0 +1,350 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/io.h + * PURPOSE: Internal io manager declarations + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 28/05/97: Created + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_IO_H +#define __NTOSKRNL_INCLUDE_INTERNAL_IO_H + +#include +#include + +typedef struct _DEVICE_NODE +{ + struct _DEVICE_NODE *Parent; + struct _DEVICE_NODE *PrevSibling; + struct _DEVICE_NODE *NextSibling; + struct _DEVICE_NODE *Child; + PDRIVER_OBJECT DriverObject; + PDEVICE_OBJECT Pdo; + UNICODE_STRING InstancePath; + UNICODE_STRING ServiceName; + //TargetDeviceNotifyList? + PDEVICE_CAPABILITIES CapabilityFlags; + ULONG Flags; + ULONG UserFlags; + ULONG DisableableDepends; + ULONG Problem; + PCM_RESOURCE_LIST CmResourceList; + PCM_RESOURCE_LIST BootResourcesList; + PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList; + /* Not NT's */ + UNICODE_STRING DeviceID; + UNICODE_STRING InstanceID; + UNICODE_STRING HardwareIDs; + UNICODE_STRING CompatibleIDs; + UNICODE_STRING DeviceText; + UNICODE_STRING DeviceTextLocation; + PPNP_BUS_INFORMATION BusInformation; +} DEVICE_NODE, *PDEVICE_NODE; + +/* For Flags field */ +#define DNF_PROCESSED 0x00000001 +#define DNF_STARTED 0x00000002 +#define DNF_START_FAILED 0x00000004 +#define DNF_ENUMERATED 0x00000008 +#define DNF_DELETED 0x00000010 +#define DNF_MADEUP 0x00000020 +#define DNF_START_REQUEST_PENDING 0x00000040 +#define DNF_NO_RESOURCE_REQUIRED 0x00000080 +#define DNF_INSUFFICIENT_RESOURCES 0x00000100 +#define DNF_RESOURCE_ASSIGNED 0x00000200 +#define DNF_RESOURCE_REPORTED 0x00000400 +#define DNF_HAL_NODE 0x00000800 // ??? +#define DNF_ADDED 0x00001000 +#define DNF_ADD_FAILED 0x00002000 +#define DNF_LEGACY_DRIVER 0x00004000 +#define DNF_STOPPED 0x00008000 +#define DNF_WILL_BE_REMOVED 0x00010000 +#define DNF_NEED_TO_ENUM 0x00020000 +#define DNF_NOT_CONFIGURED 0x00040000 +#define DNF_REINSTALL 0x00080000 +#define DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED 0x00100000 // ??? +#define DNF_DISABLED 0x00200000 +#define DNF_RESTART_OK 0x00400000 +#define DNF_NEED_RESTART 0x00800000 +#define DNF_VISITED 0x01000000 +#define DNF_ASSIGNING_RESOURCES 0x02000000 +#define DNF_BEEING_ENUMERATED 0x04000000 +#define DNF_NEED_ENUMERATION_ONLY 0x08000000 +#define DNF_LOCKED 0x10000000 +#define DNF_HAS_BOOT_CONFIG 0x20000000 +#define DNF_BOOT_CONFIG_RESERVED 0x40000000 +#define DNF_HAS_PROBLEM 0x80000000 // ??? + +/* For UserFlags field */ +#define DNUF_DONT_SHOW_IN_UI 0x0002 +#define DNUF_NOT_DISABLEABLE 0x0008 + +/* For Problem field */ +#define CM_PROB_NOT_CONFIGURED 1 +#define CM_PROB_FAILED_START 10 +#define CM_PROB_NORMAL_CONFLICT 12 +#define CM_PROB_NEED_RESTART 14 +#define CM_PROB_REINSTALL 18 +#define CM_PROB_WILL_BE_REMOVED 21 +#define CM_PROB_DISABLED 22 +#define CM_PROB_FAILED_INSTALL 28 +#define CM_PROB_FAILED_ADD 31 + +/* + * VOID + * IopDeviceNodeSetFlag( + * PDEVICE_NODE DeviceNode, + * ULONG Flag); + */ +#define IopDeviceNodeSetFlag(DeviceNode, Flag)((DeviceNode)->Flags |= (Flag)) + +/* + * VOID + * IopDeviceNodeClearFlag( + * PDEVICE_NODE DeviceNode, + * ULONG Flag); + */ +#define IopDeviceNodeClearFlag(DeviceNode, Flag)((DeviceNode)->Flags &= ~(Flag)) + +/* + * BOOLEAN + * IopDeviceNodeHasFlag( + * PDEVICE_NODE DeviceNode, + * ULONG Flag); + */ +#define IopDeviceNodeHasFlag(DeviceNode, Flag)(((DeviceNode)->Flags & (Flag)) > 0) + +/* + * VOID + * IopDeviceNodeSetUserFlag( + * PDEVICE_NODE DeviceNode, + * ULONG UserFlag); + */ +#define IopDeviceNodeSetUserFlag(DeviceNode, UserFlag)((DeviceNode)->UserFlags |= (UserFlag)) + +/* + * VOID + * IopDeviceNodeClearUserFlag( + * PDEVICE_NODE DeviceNode, + * ULONG UserFlag); + */ +#define IopDeviceNodeClearUserFlag(DeviceNode, UserFlag)((DeviceNode)->UserFlags &= ~(UserFlag)) + +/* + * BOOLEAN + * IopDeviceNodeHasUserFlag( + * PDEVICE_NODE DeviceNode, + * ULONG UserFlag); + */ +#define IopDeviceNodeHasUserFlag(DeviceNode, UserFlag)(((DeviceNode)->UserFlags & (UserFlag)) > 0) + + /* + * VOID + * IopDeviceNodeSetProblem( + * PDEVICE_NODE DeviceNode, + * ULONG Problem); + */ +#define IopDeviceNodeSetProblem(DeviceNode, Problem)((DeviceNode)->Problem |= (Problem)) + +/* + * VOID + * IopDeviceNodeClearProblem( + * PDEVICE_NODE DeviceNode, + * ULONG Problem); + */ +#define IopDeviceNodeClearProblem(DeviceNode, Problem)((DeviceNode)->Problem &= ~(Problem)) + +/* + * BOOLEAN + * IopDeviceNodeHasProblem( + * PDEVICE_NODE DeviceNode, + * ULONG Problem); + */ +#define IopDeviceNodeHasProblem(DeviceNode, Problem)(((DeviceNode)->Problem & (Problem)) > 0) + + +/* + Called on every visit of a node during a preorder-traversal of the device + node tree. + If the routine returns STATUS_UNSUCCESSFUL the traversal will stop and + STATUS_SUCCESS is returned to the caller who initiated the tree traversal. + Any other returned status code will be returned to the caller. If a status + code that indicates an error (other than STATUS_UNSUCCESSFUL) is returned, + the traversal is stopped immediately and the status code is returned to + the caller. + */ +typedef NTSTATUS (*DEVICETREE_TRAVERSE_ROUTINE)( + PDEVICE_NODE DeviceNode, + PVOID Context); + +/* Context information for traversing the device tree */ +typedef struct _DEVICETREE_TRAVERSE_CONTEXT +{ + /* Current device node during a traversal */ + PDEVICE_NODE DeviceNode; + /* Initial device node where we start the traversal */ + PDEVICE_NODE FirstDeviceNode; + /* Action routine to be called for every device node */ + DEVICETREE_TRAVERSE_ROUTINE Action; + /* Context passed to the action routine */ + PVOID Context; +} DEVICETREE_TRAVERSE_CONTEXT, *PDEVICETREE_TRAVERSE_CONTEXT; + +/* + * VOID + * IopInitDeviceTreeTraverseContext( + * PDEVICETREE_TRAVERSE_CONTEXT DeviceTreeTraverseContext, + * PDEVICE_NODE DeviceNode, + * DEVICETREE_TRAVERSE_ROUTINE Action, + * PVOID Context); + */ +#define IopInitDeviceTreeTraverseContext( \ + _DeviceTreeTraverseContext, _DeviceNode, _Action, _Context) { \ + (_DeviceTreeTraverseContext)->FirstDeviceNode = (_DeviceNode); \ + (_DeviceTreeTraverseContext)->Action = (_Action); \ + (_DeviceTreeTraverseContext)->Context = (_Context); } + + +extern PDEVICE_NODE IopRootDeviceNode; + +extern POBJECT_TYPE IoSymbolicLinkType; + +VOID +PnpInit(VOID); + +VOID +IopInitDriverImplementation(VOID); + +NTSTATUS +IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject); +NTSTATUS +IopCreateDeviceNode(PDEVICE_NODE ParentNode, + PDEVICE_OBJECT PhysicalDeviceObject, + PDEVICE_NODE *DeviceNode); +NTSTATUS +IopFreeDeviceNode(PDEVICE_NODE DeviceNode); +NTSTATUS +IopInterrogateBusExtender(PDEVICE_NODE DeviceNode, + PDEVICE_OBJECT Pdo, + BOOLEAN BootDriversOnly); +VOID +IopLoadBootStartDrivers(VOID); +NTSTATUS +IopCreateDriverObject(PDRIVER_OBJECT *DriverObject, + PUNICODE_STRING ServiceName, + BOOLEAN FileSystemDriver); +NTSTATUS +IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode); +NTSTATUS +IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry, + PDEVICE_NODE DeviceNode, + BOOLEAN FileSystemDriver); +VOID +IoInitCancelHandling(VOID); +VOID +IoInitSymbolicLinkImplementation(VOID); +VOID +IoInitFileSystemImplementation(VOID); +VOID +IoInitVpbImplementation(VOID); + +NTSTATUS +IoMountVolume(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN AllowRawMount); +POBJECT IoOpenSymlink(POBJECT SymbolicLink); +POBJECT IoOpenFileOnDevice(POBJECT SymbolicLink, PWCHAR Name); + +VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost); + +NTSTATUS STDCALL +IopCreateFile(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes); +NTSTATUS STDCALL +IopCreateDevice(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes); +NTSTATUS IoAttachVpb(PDEVICE_OBJECT DeviceObject); + +PIRP IoBuildSynchronousFsdRequestWithMdl(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PMDL Mdl, + PLARGE_INTEGER StartingOffset, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG PagingIo); + +VOID IoInitShutdownNotification(VOID); +VOID IoShutdownRegisteredDevices(VOID); +VOID IoShutdownRegisteredFileSystems(VOID); + +NTSTATUS STDCALL +IoPageWrite(PFILE_OBJECT FileObject, + PMDL Mdl, + PLARGE_INTEGER Offset, + PKEVENT Event, + PIO_STATUS_BLOCK StatusBlock); + +NTSTATUS +IoCreateArcNames(VOID); + +NTSTATUS +IoCreateSystemRootLink(PCHAR ParameterLine); + +NTSTATUS +IopInitiatePnpIrp( + PDEVICE_OBJECT DeviceObject, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG MinorFunction, + PIO_STACK_LOCATION Stack); + +BOOLEAN +IopCreateUnicodeString( + PUNICODE_STRING Destination, + PWSTR Source, + POOL_TYPE PoolType); + + +NTSTATUS +IoCreateDriverList(VOID); + +NTSTATUS +IoDestroyDriverList(VOID); + + +/* pnproot.c */ + +NTSTATUS +STDCALL +PnpRootDriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath); + +NTSTATUS +PnpRootCreateDevice( + PDEVICE_OBJECT *PhysicalDeviceObject); + +#endif diff --git a/ntoskrnl/include/internal/kd.h b/ntoskrnl/include/internal/kd.h new file mode 100644 index 0000000..06d525d --- /dev/null +++ b/ntoskrnl/include/internal/kd.h @@ -0,0 +1,107 @@ +/* $Id$ + * + * kernel debugger prototypes + */ + +#ifndef __INCLUDE_INTERNAL_KERNEL_DEBUGGER_H +#define __INCLUDE_INTERNAL_KERNEL_DEBUGGER_H + +#include +#include + +#define KD_DEBUG_DISABLED 0x00 +#define KD_DEBUG_GDB 0x01 +#define KD_DEBUG_PICE 0x02 +#define KD_DEBUG_SCREEN 0x04 +#define KD_DEBUG_SERIAL 0x08 +#define KD_DEBUG_BOCHS 0x10 +#define KD_DEBUG_FILELOG 0x20 +#define KD_DEBUG_MDA 0x40 +#define KD_DEBUG_KDB 0x80 + +extern ULONG KdDebugState; + +KD_PORT_INFORMATION GdbPortInfo; +KD_PORT_INFORMATION LogPortInfo; + +typedef enum _KD_CONTINUE_TYPE +{ + kdContinue = 0, + kdDoNotHandleException, + kdHandleException +} KD_CONTINUE_TYPE; + +ULONG +KdpPrintString (PANSI_STRING String); + +VOID +DebugLogWrite(PCH String); +VOID +DebugLogInit(VOID); +VOID +DebugLogInit2(VOID); + +VOID +KdInit1(VOID); + +VOID +KdInit2(VOID); + +VOID +KdPutChar(UCHAR Value); + +UCHAR +KdGetChar(VOID); + +VOID +KdGdbStubInit(); + +VOID +KdGdbDebugPrint (LPSTR Message); + +VOID +KdDebugPrint (LPSTR Message); + +KD_CONTINUE_TYPE +KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME TrapFrame); +VOID KdInitializeMda(VOID); +VOID KdPrintMda(PCH pch); + +#ifndef KDBG +#define KDB_DELETEPROCESS_HOOK(PROCESS) +#define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) +#define KDB_UNLOADDRIVER_HOOK(MODULE) +#define KDB_LOADERINIT_HOOK(NTOS, HAL) +#define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) +#else +#define KDB_DELETEPROCESS_HOOK(PROCESS) KdbFreeSymbolsProcess(PROCESS) +#define KDB_LOADDRIVER_HOOK(FILENAME, MODULE) KdbLoadDriver(FILENAME, MODULE) +#define KDB_UNLOADDRIVER_HOOK(MODULE) KdbUnloadDriver(MODULE) +#define KDB_LOADERINIT_HOOK(NTOS, HAL) KdbLdrInit(NTOS, HAL) +#define KDB_SYMBOLFILE_HOOK(LOADBASE, FILENAME, LENGTH) \ + KdbProcessSymbolFile(LOADBASE, FILENAME, LENGTH) +#endif /* KDBG */ + +VOID +KdbLdrLoadUserModuleSymbols(PLDR_MODULE LdrModule); +VOID +KdbProcessSymbolFile(PVOID ModuleLoadBase, PCHAR FileName, ULONG Length); +VOID +KdbLdrInit(MODULE_TEXT_SECTION* NtoskrnlTextSection, + MODULE_TEXT_SECTION* LdrHalTextSection); +VOID +KdbUnloadDriver(PMODULE_OBJECT ModuleObject); +VOID +KdbLoadDriver(PUNICODE_STRING Filename, PMODULE_OBJECT Module); +VOID +KdbFreeSymbolsProcess(PPEB Peb); +BOOLEAN +KdbPrintAddress(PVOID address); +KD_CONTINUE_TYPE +KdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME TrapFrame); + +#endif /* __INCLUDE_INTERNAL_KERNEL_DEBUGGER_H */ diff --git a/ntoskrnl/include/internal/ke.h b/ntoskrnl/include/internal/ke.h new file mode 100644 index 0000000..102b9c5 --- /dev/null +++ b/ntoskrnl/include/internal/ke.h @@ -0,0 +1,112 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_KE_H +#define __NTOSKRNL_INCLUDE_INTERNAL_KE_H + +/* INCLUDES *****************************************************************/ + +#ifndef __ASM__ +#include + +#include +#endif /* not __ASM__ */ + +#include "arch/ke.h" + +/* INTERNAL KERNEL FUNCTIONS ************************************************/ + +#ifndef __ASM__ + +struct _KTHREAD; + +VOID KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip); + +VOID KeAcquireDispatcherDatabaseLock(BOOLEAN Wait); +VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait); +BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr); +VOID STDCALL KeExpireTimers(PKDPC Apc, + PVOID Arg1, + PVOID Arg2, + PVOID Arg3); +VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, ULONG Type, + ULONG Size, ULONG SignalState); +VOID KeDumpStackFrames(PULONG Frame); +BOOLEAN KiTestAlert(VOID); +VOID KeRemoveAllWaitsThread(struct _ETHREAD* Thread, NTSTATUS WaitStatus); +PULONG KeGetStackTopThread(struct _ETHREAD* Thread); +VOID KeContextToTrapFrame(PCONTEXT Context, + PKTRAP_FRAME TrapFrame); +VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait); +VOID +KiDeliverNormalApc(VOID); + +BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc); + +/* INITIALIZATION FUNCTIONS *************************************************/ + +VOID KeInitExceptions(VOID); +VOID KeInitInterrupts(VOID); +VOID KeInitTimer(VOID); +VOID KeInitDpc(VOID); +VOID KeInitDispatcher(VOID); +VOID KeInitializeDispatcher(VOID); +VOID KeInitializeTimerImpl(VOID); +VOID KeInitializeBugCheck(VOID); +VOID Phase1Initialization(PVOID Context); + +VOID KeInit1(VOID); +VOID KeInit2(VOID); + +BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame); +VOID +KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Pc); +VOID +KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME Tf, + KPROCESSOR_MODE PreviousMode, + BOOLEAN SearchFrames); +VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame, + PCONTEXT Context); +VOID +KeApplicationProcessorInit(); +VOID +KePrepareForApplicationProcessorInit(ULONG id); +ULONG +KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2); +VOID STDCALL +KePushAndStackSwitchAndSysRet(ULONG Push, PVOID NewStack); +VOID STDCALL +KeStackSwitchAndRet(PVOID NewStack); +VOID STDCALL +KeBugCheckWithTf(ULONG BugCheckCode, + ULONG BugCheckParameter1, + ULONG BugCheckParameter2, + ULONG BugCheckParameter3, + ULONG BugCheckParameter4, + PKTRAP_FRAME Tf); +VOID +KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG ExceptionNr, ULONG cr2); + +#endif /* not __ASM__ */ + +#define MAXIMUM_PROCESSORS 32 + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */ diff --git a/ntoskrnl/include/internal/ldr.h b/ntoskrnl/include/internal/ldr.h new file mode 100644 index 0000000..207e635 --- /dev/null +++ b/ntoskrnl/include/internal/ldr.h @@ -0,0 +1,133 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/ldr.h + * PURPOSE: Header for loader module + */ + +#ifndef __INCLUDE_INTERNAL_LDR_H +#define __INCLUDE_INTERNAL_LDR_H + +#include +#include +#include +#include + +#define KERNEL_MODULE_NAME L"ntoskrnl.exe" +#define HAL_MODULE_NAME L"hal.dll" +#define DRIVER_ROOT_NAME L"\\Driver\\" +#define FILESYSTEM_ROOT_NAME L"\\FileSystem\\" + + +extern ULONG_PTR LdrHalBase; + + +NTSTATUS +LdrLoadInitialProcess ( + VOID + ); +VOID +LdrLoadAutoConfigDrivers ( + VOID + ); +VOID +LdrInitModuleManagement ( + VOID + ); + +NTSTATUS +LdrInitializeBootStartDriver(IN PVOID ModuleLoadBase, + IN PCHAR FileName, + IN ULONG ModuleLength); + +NTSTATUS +LdrpMapSystemDll ( + HANDLE ProcessHandle, + PVOID * LdrStartupAddress + ); +PVOID +LdrpGetSystemDllEntryPoint (VOID); +PVOID +LdrpGetSystemDllApcDispatcher(VOID); +PVOID +LdrpGetSystemDllExceptionDispatcher(VOID); +PVOID +LdrpGetSystemDllCallbackDispatcher(VOID); +NTSTATUS +LdrpMapImage ( + HANDLE ProcessHandle, + HANDLE SectionHandle, + PVOID * ImageBase + ); + + +NTSTATUS STDCALL +LdrGetProcedureAddress (IN PVOID BaseAddress, + IN PANSI_STRING Name, + IN ULONG Ordinal, + OUT PVOID *ProcedureAddress); + +NTSTATUS +LdrpLoadImage(PUNICODE_STRING DriverName, + PVOID *ModuleBase, + PVOID *SectionPointer, + PVOID *EntryPoint, + PVOID *ExportDirectory); + +NTSTATUS +LdrpUnloadImage(PVOID ModuleBase); + +NTSTATUS +LdrpLoadAndCallImage(PUNICODE_STRING DriverName); + +NTSTATUS +LdrpQueryModuleInformation(PVOID Buffer, + ULONG Size, + PULONG ReqSize); + +PVOID STDCALL +RtlImageDirectoryEntryToData ( + IN PVOID BaseAddress, + IN BOOLEAN ImageLoaded, + IN ULONG Directory, + OUT PULONG Size); +VOID +LdrInit1(VOID); +VOID +LdrInitDebug(PLOADER_MODULE Module, PWCH Name); + +PVOID LdrSafePEProcessModule( + PVOID ModuleLoadBase, + PVOID DriverBase, + PVOID ImportModuleBase, + PULONG DriverSize); + +NTSTATUS +LdrLoadModule(PUNICODE_STRING Filename, + PMODULE_OBJECT *ModuleObject); + +NTSTATUS +LdrUnloadModule(PMODULE_OBJECT ModuleObject); + +PMODULE_OBJECT +LdrGetModuleObject(PUNICODE_STRING ModuleName); + +NTSTATUS +LdrGetAddressInformation(IN PIMAGE_SYMBOL_INFO SymbolInfo, + IN ULONG_PTR RelativeAddress, + OUT PULONG LineNumber, + OUT PCH FileName OPTIONAL, + OUT PCH FunctionName OPTIONAL); + + +#ifdef DBG + +VOID +LdrLoadUserModuleSymbols(PLDR_MODULE LdrModule); + +VOID +LdrUnloadModuleSymbols(PIMAGE_SYMBOL_INFO SymbolInfo); + +#endif /* DBG */ + +#endif /* __INCLUDE_INTERNAL_LDR_H */ diff --git a/ntoskrnl/include/internal/mm.h b/ntoskrnl/include/internal/mm.h new file mode 100644 index 0000000..bfe8408 --- /dev/null +++ b/ntoskrnl/include/internal/mm.h @@ -0,0 +1,610 @@ +/* + * Higher level memory managment definitions + */ + +#ifndef __INCLUDE_INTERNAL_MM_H +#define __INCLUDE_INTERNAL_MM_H + +#include +#include + +/* TYPES *********************************************************************/ + +struct _EPROCESS; + +struct _MM_RMAP_ENTRY; +struct _MM_PAGEOP; +typedef ULONG SWAPENTRY; + +#define MEMORY_AREA_INVALID (0) +#define MEMORY_AREA_SECTION_VIEW (1) +#define MEMORY_AREA_CONTINUOUS_MEMORY (2) +#define MEMORY_AREA_NO_CACHE (3) +#define MEMORY_AREA_IO_MAPPING (4) +#define MEMORY_AREA_SYSTEM (5) +#define MEMORY_AREA_MDL_MAPPING (7) +#define MEMORY_AREA_VIRTUAL_MEMORY (8) +#define MEMORY_AREA_CACHE_SEGMENT (9) +#define MEMORY_AREA_SHARED_DATA (10) +#define MEMORY_AREA_KERNEL_STACK (11) +#define MEMORY_AREA_PAGED_POOL (12) + +#define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \ + ((x) / (4*1024*1024)) +#define PAGE_TO_SECTION_PAGE_TABLE_OFFSET(x) \ + ((((x)) % (4*1024*1024)) / (4*1024)) + +#define NR_SECTION_PAGE_TABLES (1024) +#define NR_SECTION_PAGE_ENTRIES (1024) + + +/* + * Additional flags for protection attributes + */ +#define PAGE_WRITETHROUGH (1024) +#define PAGE_SYSTEM (2048) +#define PAGE_FLAGS_VALID_FROM_USER_MODE (PAGE_READONLY | \ + PAGE_READWRITE | \ + PAGE_WRITECOPY | \ + PAGE_EXECUTE | \ + PAGE_EXECUTE_READ | \ + PAGE_EXECUTE_READWRITE | \ + PAGE_EXECUTE_WRITECOPY | \ + PAGE_GUARD | \ + PAGE_NOACCESS | \ + PAGE_NOCACHE) + +typedef struct +{ + ULONG Entry[NR_SECTION_PAGE_ENTRIES]; +} SECTION_PAGE_TABLE, *PSECTION_PAGE_TABLE; + +typedef struct +{ + PSECTION_PAGE_TABLE PageTables[NR_SECTION_PAGE_TABLES]; +} SECTION_PAGE_DIRECTORY, *PSECTION_PAGE_DIRECTORY; + +#define SEC_PHYSICALMEMORY (0x80000000) + +#define MM_PAGEFILE_SEGMENT (0x1) +#define MM_DATAFILE_SEGMENT (0x2) + +#define MM_SECTION_SEGMENT_BSS (0x1) + +typedef struct _MM_SECTION_SEGMENT +{ + ULONG FileOffset; + ULONG Protection; + ULONG Attributes; + ULONG Length; + ULONG RawLength; + KMUTEX Lock; + ULONG ReferenceCount; + SECTION_PAGE_DIRECTORY PageDirectory; + ULONG Flags; + PVOID VirtualAddress; + ULONG Characteristics; + BOOLEAN WriteCopy; +} MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT; + +typedef struct +{ + CSHORT Type; + CSHORT Size; + LARGE_INTEGER MaximumSize; + ULONG SectionPageProtection; + ULONG AllocationAttributes; + PFILE_OBJECT FileObject; + LIST_ENTRY ViewListHead; + KSPIN_LOCK ViewListLock; + KMUTEX Lock; + ULONG NrSegments; + PMM_SECTION_SEGMENT Segments; + PVOID ImageBase; + PVOID EntryPoint; + ULONG StackReserve; + ULONG StackCommit; + ULONG Subsystem; + ULONG MinorSubsystemVersion; + ULONG MajorSubsystemVersion; + ULONG ImageCharacteristics; + USHORT Machine; + BOOLEAN Executable; +} SECTION_OBJECT, *PSECTION_OBJECT; + +typedef struct +{ + ULONG Type; + PVOID BaseAddress; + ULONG Length; + ULONG Attributes; + LIST_ENTRY Entry; + ULONG LockCount; + struct _EPROCESS* Process; + BOOLEAN DeleteInProgress; + ULONG PageOpCount; + union + { + struct + { + SECTION_OBJECT* Section; + ULONG ViewOffset; + LIST_ENTRY ViewListEntry; + PMM_SECTION_SEGMENT Segment; + BOOLEAN WriteCopyView; + LIST_ENTRY RegionListHead; + } SectionData; + struct + { + LIST_ENTRY RegionListHead; + } VirtualMemoryData; + } Data; +} MEMORY_AREA, *PMEMORY_AREA; + +typedef struct _MADDRESS_SPACE +{ + LIST_ENTRY MAreaListHead; + FAST_MUTEX Lock; + ULONG LowestAddress; + struct _EPROCESS* Process; + PUSHORT PageTableRefCountTable; + ULONG PageTableRefCountTableSize; +} MADDRESS_SPACE, *PMADDRESS_SPACE; + +/* FUNCTIONS */ + +VOID MmLockAddressSpace(PMADDRESS_SPACE AddressSpace); +VOID MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace); +VOID MmInitializeKernelAddressSpace(VOID); +PMADDRESS_SPACE MmGetCurrentAddressSpace(VOID); +PMADDRESS_SPACE MmGetKernelAddressSpace(VOID); +NTSTATUS MmInitializeAddressSpace(struct _EPROCESS* Process, + PMADDRESS_SPACE AddressSpace); +NTSTATUS MmDestroyAddressSpace(PMADDRESS_SPACE AddressSpace); +PVOID STDCALL MmAllocateSection (IN ULONG Length); +NTSTATUS MmCreateMemoryArea(struct _EPROCESS* Process, + PMADDRESS_SPACE AddressSpace, + ULONG Type, + PVOID* BaseAddress, + ULONG Length, + ULONG Attributes, + MEMORY_AREA** Result, + BOOL FixedAddress); +MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace, + PVOID Address); +NTSTATUS MmInitMemoryAreas(VOID); +VOID ExInitNonPagedPool(ULONG BaseAddress); +NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, + ULONG Length, + VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, + PVOID Address, PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, + BOOLEAN Dirty), + PVOID FreePageContext); +VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead); +NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea); +NTSTATUS MmUnlockMemoryArea(MEMORY_AREA* MemoryArea); +NTSTATUS MmInitSectionImplementation(VOID); + +#define MM_LOWEST_USER_ADDRESS (4096) + +PMEMORY_AREA MmSplitMemoryArea(struct _EPROCESS* Process, + PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA OriginalMemoryArea, + PVOID BaseAddress, + ULONG Length, + ULONG NewType, + ULONG NewAttributes); +PVOID +MmInitializePageList(PVOID FirstPhysKernelAddress, + PVOID LastPhysKernelAddress, + ULONG MemorySizeInPages, + ULONG LastKernelBase, + PADDRESS_RANGE BIOSMemoryMap, + ULONG AddressRangeCount); +PHYSICAL_ADDRESS +MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry); +VOID MmDereferencePage(PHYSICAL_ADDRESS PhysicalAddress); +VOID MmReferencePage(PHYSICAL_ADDRESS PhysicalAddress); +VOID MmDeletePageTable(struct _EPROCESS* Process, + PVOID Address); +NTSTATUS MmCopyMmInfo(struct _EPROCESS* Src, + struct _EPROCESS* Dest); +NTSTATUS MmReleaseMmInfo(struct _EPROCESS* Process); +NTSTATUS Mmi386ReleaseMmInfo(struct _EPROCESS* Process); +VOID +MmDeleteVirtualMapping(struct _EPROCESS* Process, + PVOID Address, + BOOL FreePage, + BOOL* WasDirty, + PHYSICAL_ADDRESS* PhysicalPage); + +#define MM_PAGE_CLEAN (0) +#define MM_PAGE_DIRTY (1) + +VOID MmBuildMdlFromPages(PMDL Mdl, PULONG Pages); +PVOID MmGetMdlPageAddress(PMDL Mdl, PVOID Offset); +VOID MiShutdownMemoryManager(VOID); +PHYSICAL_ADDRESS +MmGetPhysicalAddressForProcess(struct _EPROCESS* Process, + PVOID Address); +NTSTATUS STDCALL +MmUnmapViewOfSection(struct _EPROCESS* Process, PVOID BaseAddress); +VOID MmInitPagingFile(VOID); + +/* FIXME: it should be in ddk/mmfuncs.h */ +NTSTATUS +STDCALL +MmCreateSection ( + OUT PSECTION_OBJECT * SectionObject, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL, + IN PFILE_OBJECT File OPTIONAL + ); + +NTSTATUS MmPageFault(ULONG Cs, + PULONG Eip, + PULONG Eax, + ULONG Cr2, + ULONG ErrorCode); + +NTSTATUS +MmAccessFault(KPROCESSOR_MODE Mode, + ULONG Address, + BOOLEAN FromMdl); +NTSTATUS +MmNotPresentFault(KPROCESSOR_MODE Mode, + ULONG Address, + BOOLEAN FromMdl); +NTSTATUS +MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked); +NTSTATUS +MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked); +NTSTATUS MmWaitForPage(PVOID Page); +VOID MmClearWaitPage(PVOID Page); +VOID MmSetWaitPage(PVOID Page); +BOOLEAN MmIsDirtyPage(struct _EPROCESS* Process, PVOID Address); +BOOLEAN MmIsPageTablePresent(PVOID PAddress); +NTSTATUS +MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + struct _MM_PAGEOP* PageOp); +NTSTATUS +MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + struct _MM_PAGEOP* PageOp); +MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, + PVOID Address, + ULONG Length); +PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length); +VOID ExUnmapPage(PVOID Addr); +PVOID ExAllocatePage(VOID); + +VOID MmInitPagingFile(VOID); +BOOLEAN MmReserveSwapPages(ULONG Nr); +VOID MmDereserveSwapPages(ULONG Nr); +SWAPENTRY MmAllocSwapPage(VOID); +VOID MmFreeSwapPage(SWAPENTRY Entry); + +VOID MmInit1(ULONG FirstKernelPhysAddress, + ULONG LastKernelPhysAddress, + ULONG LastKernelAddress, + PADDRESS_RANGE BIOSMemoryMap, + ULONG AddressRangeCount); +VOID MmInit2(VOID); +VOID MmInit3(VOID); +NTSTATUS MmInitPagerThread(VOID); + +VOID MmInitKernelMap(PVOID BaseAddress); +NTSTATUS MmCreatePageTable(PVOID PAddress); + +typedef struct +{ + ULONG NrTotalPages; + ULONG NrSystemPages; + ULONG NrReservedPages; + ULONG NrUserPages; + ULONG NrFreePages; + ULONG NrDirtyPages; + ULONG NrLockedPages; + ULONG PagingRequestsInLastMinute; + ULONG PagingRequestsInLastFiveMinutes; + ULONG PagingRequestsInLastFifteenMinutes; +} MM_STATS; + +extern MM_STATS MmStats; + +PVOID +MmGetDirtyPagesFromWorkingSet(struct _EPROCESS* Process); +NTSTATUS +MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl); +NTSTATUS +MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl); +VOID +MmSetFlagsPage(PHYSICAL_ADDRESS PhysicalAddress, ULONG Flags); +ULONG +MmGetFlagsPage(PHYSICAL_ADDRESS PhysicalAddress); +VOID MmSetSavedSwapEntryPage(PHYSICAL_ADDRESS PhysicalAddress, + SWAPENTRY SavedSwapEntry); +SWAPENTRY MmGetSavedSwapEntryPage(PHYSICAL_ADDRESS PhysicalAddress); +VOID MmSetCleanPage(struct _EPROCESS* Process, PVOID Address); +VOID MmLockPage(PHYSICAL_ADDRESS PhysicalPage); +VOID MmUnlockPage(PHYSICAL_ADDRESS PhysicalPage); + +NTSTATUS MmSafeCopyFromUser(PVOID Dest, PVOID Src, ULONG Count); +NTSTATUS MmSafeCopyToUser(PVOID Dest, PVOID Src, ULONG Count); +NTSTATUS +MmCreatePhysicalMemorySection(VOID); +PHYSICAL_ADDRESS +MmGetContinuousPages(ULONG NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress, + ULONG Alignment); + +#define MM_PHYSICAL_PAGE_MPW_PENDING (0x8) + +NTSTATUS +MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked); +ULONG +MmGetPageProtect(struct _EPROCESS* Process, PVOID Address); +PVOID +ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage); +ULONG +MmGetReferenceCountPage(PHYSICAL_ADDRESS PhysicalAddress); +BOOLEAN +MmIsUsablePage(PHYSICAL_ADDRESS PhysicalAddress); + +#define MM_PAGEOP_PAGEIN (1) +#define MM_PAGEOP_PAGEOUT (2) +#define MM_PAGEOP_PAGESYNCH (3) +#define MM_PAGEOP_ACCESSFAULT (4) + +typedef struct _MM_PAGEOP +{ + /* Type of operation. */ + ULONG OpType; + /* Number of threads interested in this operation. */ + ULONG ReferenceCount; + /* Event that will be set when the operation is completed. */ + KEVENT CompletionEvent; + /* Status of the operation once it is completed. */ + NTSTATUS Status; + /* TRUE if the operation was abandoned. */ + BOOLEAN Abandoned; + /* The memory area to be affected by the operation. */ + PMEMORY_AREA MArea; + ULONG Hash; + struct _MM_PAGEOP* Next; + struct _ETHREAD* Thread; + /* + * These fields are used to identify the operation if it is against a + * virtual memory area. + */ + ULONG Pid; + PVOID Address; + /* + * These fields are used to identify the operation if it is against a + * section mapping. + */ + PMM_SECTION_SEGMENT Segment; + ULONG Offset; +} MM_PAGEOP, *PMM_PAGEOP; + +VOID +MmReleasePageOp(PMM_PAGEOP PageOp); + +PMM_PAGEOP +MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, + PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType); + +VOID +MiDebugDumpNonPagedPool(BOOLEAN NewOnly); +VOID +MiDebugDumpNonPagedPoolStats(BOOLEAN NewOnly); +VOID +MmMarkPageMapped(PHYSICAL_ADDRESS PhysicalAddress); +VOID +MmMarkPageUnmapped(PHYSICAL_ADDRESS PhysicalAddress); +VOID +MmFreeSectionSegments(PFILE_OBJECT FileObject); + +typedef struct _MM_IMAGE_SECTION_OBJECT +{ + ULONG NrSegments; + MM_SECTION_SEGMENT Segments[0]; +} MM_IMAGE_SECTION_OBJECT, *PMM_IMAGE_SECTION_OBJECT; + +VOID +MmFreeVirtualMemory(struct _EPROCESS* Process, PMEMORY_AREA MemoryArea); +NTSTATUS +MiCopyFromUserPage(PHYSICAL_ADDRESS DestPhysPage, PVOID SourceAddress); +NTSTATUS +MiZeroPage(PHYSICAL_ADDRESS PhysPage); +BOOLEAN +MmIsAccessedAndResetAccessPage(struct _EPROCESS* Process, PVOID Address); + +#define STATUS_MM_RESTART_OPERATION (0xD0000001) + +NTSTATUS +MmCreateVirtualMappingForKernel(PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress); +NTSTATUS MmCommitPagedPoolAddress(PVOID Address); +NTSTATUS MmCreateVirtualMapping(struct _EPROCESS* Process, + PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress, + BOOLEAN MayWait); +NTSTATUS +MmCreateVirtualMappingUnsafe(struct _EPROCESS* Process, + PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress, + BOOLEAN MayWait); + +VOID MmSetPageProtect(struct _EPROCESS* Process, + PVOID Address, + ULONG flProtect); +BOOLEAN MmIsPagePresent(struct _EPROCESS* Process, + PVOID Address); + +/* Memory balancing. */ +VOID +MmInitializeMemoryConsumer(ULONG Consumer, + NTSTATUS (*Trim)(ULONG Target, ULONG Priority, + PULONG NrFreed)); +VOID +MmInitializeBalancer(ULONG NrAvailablePages); +NTSTATUS +MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page); +NTSTATUS +MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, + PHYSICAL_ADDRESS* AllocatedPage); + +#define MC_CACHE (0) +#define MC_USER (1) +#define MC_PPOOL (2) +#define MC_NPPOOL (3) +#define MC_MAXIMUM (4) + +VOID +MmSetRmapListHeadPage(PHYSICAL_ADDRESS PhysicalAddress, + struct _MM_RMAP_ENTRY* ListHead); +struct _MM_RMAP_ENTRY* +MmGetRmapListHeadPage(PHYSICAL_ADDRESS PhysicalAddress); +VOID +MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process, + PVOID Address); +VOID +MmDeleteAllRmaps(PHYSICAL_ADDRESS PhysicalAddress, PVOID Context, + VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process, PVOID Address)); +VOID +MmDeleteRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process, + PVOID Address); +VOID +MmInitializeRmapList(VOID); +PHYSICAL_ADDRESS +MmGetLRUNextUserPage(PHYSICAL_ADDRESS PreviousPhysicalAddress); +PHYSICAL_ADDRESS +MmGetLRUFirstUserPage(VOID); +NTSTATUS +MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress); +NTSTATUS +MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages); + +VOID +MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr); +VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address); +VOID +MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, + SWAPENTRY* SwapEntry); +NTSTATUS +MmCreatePageFileMapping(PEPROCESS Process, + PVOID Address, + SWAPENTRY SwapEntry); +BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address); +VOID +MmTransferOwnershipPage(PHYSICAL_ADDRESS PhysicalAddress, ULONG NewConsumer); +VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address); +VOID +MmInitializeMdlImplementation(VOID); +extern PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress; +PMM_PAGEOP +MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, + PMM_SECTION_SEGMENT Segment, ULONG Offset); +struct _KTRAP_FRAME; +NTSTATUS STDCALL +MmDumpToPagingFile(ULONG BugCode, + ULONG BugCodeParameter1, + ULONG BugCodeParameter2, + ULONG BugCodeParameter3, + ULONG BugCodeParameter4, + struct _KTRAP_FRAME* TrapFrame); + +typedef VOID (*PMM_ALTER_REGION_FUNC)(PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, ULONG Length, + ULONG OldType, ULONG OldProtect, + ULONG NewType, ULONG NewProtect); + +typedef struct _MM_REGION +{ + ULONG Type; + ULONG Protect; + ULONG Length; + LIST_ENTRY RegionListEntry; +} MM_REGION, *PMM_REGION; + +NTSTATUS +MmAlterRegion(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress, + PLIST_ENTRY RegionListHead, PVOID StartAddress, ULONG Length, + ULONG NewType, ULONG NewProtect, + PMM_ALTER_REGION_FUNC AlterFunc); +VOID +MmInitialiseRegion(PLIST_ENTRY RegionListHead, ULONG Length, ULONG Type, + ULONG Protect); +PMM_REGION +MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address, + PVOID* RegionBaseAddress); +NTSTATUS STDCALL +MmQueryAnonMem(PMEMORY_AREA MemoryArea, + PVOID Address, + PMEMORY_BASIC_INFORMATION Info, + PULONG ResultLength); +NTSTATUS STDCALL +MmQuerySectionView(PMEMORY_AREA MemoryArea, + PVOID Address, + PMEMORY_BASIC_INFORMATION Info, + PULONG ResultLength); +NTSTATUS +MmProtectAnonMem(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID BaseAddress, + ULONG Length, + ULONG Protect, + PULONG OldProtect); +NTSTATUS +MmProtectSectionView(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID BaseAddress, + ULONG Length, + ULONG Protect, + PULONG OldProtect); +NTSTATUS +MmWritePageSectionView(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MArea, + PVOID Address, + PMM_PAGEOP PageOp); +NTSTATUS +MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MArea, + PVOID Address, + PMM_PAGEOP PageOp); +VOID +MmSetCleanAllRmaps(PHYSICAL_ADDRESS PhysicalAddress); +VOID +MmSetDirtyAllRmaps(PHYSICAL_ADDRESS PhysicalAddress); +NTSTATUS +MmWritePagePhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress); +BOOL +MmIsDirtyPageRmap(PHYSICAL_ADDRESS PhysicalAddress); +NTSTATUS MmInitMpwThread(VOID); +BOOLEAN +MmIsAvailableSwapPage(VOID); +VOID +MmShowOutOfSpaceMessagePagingFile(VOID); + +#endif diff --git a/ntoskrnl/include/internal/module.h b/ntoskrnl/include/internal/module.h new file mode 100644 index 0000000..b9f0c9c --- /dev/null +++ b/ntoskrnl/include/internal/module.h @@ -0,0 +1,61 @@ + +#ifndef __MODULE_H +#define __MODULE_H + +#include +#include +#include +#include + +typedef struct _MODULE_TEXT_SECTION +{ + ULONG Base; + ULONG Length; + LIST_ENTRY ListEntry; + PWCH Name; + PIMAGE_OPTIONAL_HEADER OptionalHeader; +#ifdef KDBG + IMAGE_SYMBOL_INFO SymbolInfo; +#endif /* KDBG */ +} MODULE_TEXT_SECTION, *PMODULE_TEXT_SECTION; + +typedef struct _MODULE_OBJECT +{ + CSHORT ObjectType; + CSHORT ObjectSize; + PVOID Base; + ULONG Length; + ULONG Flags; + PVOID EntryPoint; + LIST_ENTRY ListEntry; + UNICODE_STRING FullName; + UNICODE_STRING BaseName; + PMODULE_TEXT_SECTION TextSection; + union + { + struct + { + PIMAGE_FILE_HEADER FileHeader; + PIMAGE_OPTIONAL_HEADER OptionalHeader; + PIMAGE_SECTION_HEADER SectionList; + } PE; + } Image; +} MODULE_OBJECT, *PMODULE_OBJECT; + +typedef MODULE_OBJECT MODULE, *PMODULE; + +#define MODULE_FLAG_BIN 0x0001 +#define MODULE_FLAG_MZ 0x0002 +#define MODULE_FLAG_NE 0x0004 +#define MODULE_FLAG_PE 0x0008 +#define MODULE_FLAG_COFF 0x0010 + +typedef struct _INSTANCE +{ + HANDLE ModuleHandle; +} INSTANCE, *PINSTANCE; + +BOOLEAN process_boot_module(unsigned int start); + +#endif + diff --git a/ntoskrnl/include/internal/nt.h b/ntoskrnl/include/internal/nt.h new file mode 100644 index 0000000..1276503 --- /dev/null +++ b/ntoskrnl/include/internal/nt.h @@ -0,0 +1,7 @@ +VOID NtInitializeEventImplementation(VOID); +VOID NtInitializeEventPairImplementation(VOID); +VOID NtInitializeSemaphoreImplementation(VOID); +VOID NtInitializeMutantImplementation(VOID); +VOID NtInitializeTimerImplementation(VOID); +NTSTATUS NiInitPort(VOID); +VOID NtInitializeProfileImplementation(VOID); diff --git a/ntoskrnl/include/internal/ntoskrnl.h b/ntoskrnl/include/internal/ntoskrnl.h new file mode 100644 index 0000000..7481602 --- /dev/null +++ b/ntoskrnl/include/internal/ntoskrnl.h @@ -0,0 +1,67 @@ +/* + * Various useful prototypes + */ + +#ifndef __INCLUDE_INTERNAL_NTOSKRNL_H +#define __INCLUDE_INTERNAL_NTOSKRNL_H + +#ifndef __ASM__ + +#include + +#include + +/* + * Use these to place a function in a specific section of the executable + */ +#define PLACE_IN_SECTION(s) __attribute__((section (s))) +#define INIT_FUNCTION (PLACE_IN_SECTION("init")) +#define PAGE_LOCKED_FUNCTION (PLACE_IN_SECTION("pagelk")) +#define PAGE_UNLOCKED_FUNCTION (PLACE_IN_SECTION("pagepo")) + +/* + * Defines a descriptor as it appears in the processor tables + */ +typedef struct _DESCRIPTOR +{ + ULONG a; + ULONG b; +} __attribute__ ((packed)) IDT_DESCRIPTOR, GDT_DESCRIPTOR; + +extern IDT_DESCRIPTOR KiIdt[256]; +//extern GDT_DESCRIPTOR KiGdt[256]; + + +VOID NtInitializeEventImplementation(VOID); +VOID NtInit(VOID); + +/* + * Initalization functions (called once by main()) + */ +VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress); +VOID IoInit(VOID); +VOID ObInit(VOID); +VOID PsInit(VOID); +VOID CmInitializeRegistry(VOID); +VOID CmInit2(PCHAR CommandLine); +VOID CmShutdownRegistry(VOID); +VOID CmImportHive(PCHAR ChunkBase, ULONG ChunkSize); +VOID KdInitSystem(ULONG Reserved, PLOADER_PARAMETER_BLOCK LoaderBlock); + +VOID RtlpInitNlsTables(VOID); + +NTSTATUS RtlpInitNlsSections(ULONG Mod1Start, + ULONG Mod1End, + ULONG Mod2Start, + ULONG Mod2End, + ULONG Mod3Start, + ULONG Mod3End); + +#endif /* __ASM__ */ + +/* + * + */ +#define MM_STACK_SIZE (3*4096) + +#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */ diff --git a/ntoskrnl/include/internal/ob.h b/ntoskrnl/include/internal/ob.h new file mode 100644 index 0000000..b8ad6b7 --- /dev/null +++ b/ntoskrnl/include/internal/ob.h @@ -0,0 +1,112 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/objmgr.h + * PURPOSE: Object manager definitions + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +#ifndef __INCLUDE_INTERNAL_OBJMGR_H +#define __INCLUDE_INTERNAL_OBJMGR_H + +#include + +struct _EPROCESS; + +typedef struct +{ + CSHORT Type; + CSHORT Size; +} COMMON_BODY_HEADER, *PCOMMON_BODY_HEADER; + +typedef PVOID POBJECT; + +typedef struct _DIRECTORY_OBJECT +{ + CSHORT Type; + CSHORT Size; + + /* + * PURPOSE: Head of the list of our subdirectories + */ + LIST_ENTRY head; + KSPIN_LOCK Lock; +} DIRECTORY_OBJECT, *PDIRECTORY_OBJECT; + + +typedef struct _TYPE_OBJECT +{ + CSHORT Type; + CSHORT Size; + + /* pointer to object type data */ + POBJECT_TYPE ObjectType; +} TYPE_OBJECT, *PTYPE_OBJECT; + + +/* + * Enumeration of object types + */ +enum +{ + OBJTYP_INVALID, + OBJTYP_TYPE, + OBJTYP_DIRECTORY, + OBJTYP_SYMLNK, + OBJTYP_DEVICE, + OBJTYP_THREAD, + OBJTYP_FILE, + OBJTYP_PROCESS, + OBJTYP_SECTION, + OBJTYP_MAX, +}; + + +#define OBJECT_ALLOC_SIZE(type) (type->NonpagedPoolCharge+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)) + + +extern PDIRECTORY_OBJECT NameSpaceRoot; + + +POBJECT_HEADER BODY_TO_HEADER(PVOID body); +PVOID HEADER_TO_BODY(POBJECT_HEADER obj); + +VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, + POBJECT_HEADER Header, + PWSTR Name); +VOID ObpRemoveEntryDirectory(POBJECT_HEADER Header); + + + +NTSTATUS ObCreateHandle(struct _EPROCESS* Process, + PVOID ObjectBody, + ACCESS_MASK GrantedAccess, + BOOLEAN Inherit, + PHANDLE Handle); +VOID ObCreateHandleTable(struct _EPROCESS* Parent, + BOOLEAN Inherit, + struct _EPROCESS* Process); +NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, + PVOID* ReturnedObject, + PUNICODE_STRING RemainingPath, + POBJECT_TYPE ObjectType); +VOID ObCloseAllHandles(struct _EPROCESS* Process); +VOID ObDeleteHandleTable(struct _EPROCESS* Process); +PVOID ObDeleteHandle(struct _EPROCESS* Process, + HANDLE Handle); + +NTSTATUS +ObpCreateTypeObject(POBJECT_TYPE ObjectType); + +ULONG +ObGetObjectHandleCount(PVOID Object); +NTSTATUS +ObDuplicateObject(PEPROCESS SourceProcess, + PEPROCESS TargetProcess, + HANDLE SourceHandle, + PHANDLE TargetHandle, + ACCESS_MASK DesiredAccess, + BOOLEAN InheritHandle, + ULONG Options); + +#endif /* __INCLUDE_INTERNAL_OBJMGR_H */ diff --git a/ntoskrnl/include/internal/po.h b/ntoskrnl/include/internal/po.h new file mode 100644 index 0000000..ffed376 --- /dev/null +++ b/ntoskrnl/include/internal/po.h @@ -0,0 +1,27 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: include/internal/po.h + * PURPOSE: Internal power manager declarations + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 01/05/2001 Created + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_PO_H +#define __NTOSKRNL_INCLUDE_INTERNAL_PO_H + +#include +#include + +extern PDEVICE_NODE PopSystemPowerDeviceNode; + +VOID +PoInit(VOID); + +NTSTATUS +PopSetSystemPowerState( + SYSTEM_POWER_STATE PowerState); + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */ diff --git a/ntoskrnl/include/internal/pool.h b/ntoskrnl/include/internal/pool.h new file mode 100644 index 0000000..cf70928 --- /dev/null +++ b/ntoskrnl/include/internal/pool.h @@ -0,0 +1,28 @@ +#ifndef __INTERNAL_POOL_H +#define __INTERNAL_POOL_H + +PVOID STDCALL ExAllocateNonPagedPoolWithTag (POOL_TYPE type, + ULONG size, + ULONG Tag, + PVOID Caller); + +PVOID STDCALL ExAllocatePagedPoolWithTag (POOL_TYPE Type, + ULONG size, + ULONG Tag); +VOID STDCALL ExFreeNonPagedPool (PVOID block); + +VOID STDCALL +ExFreePagedPool(IN PVOID Block); +VOID MmInitializePagedPool(VOID); + +extern PVOID MmPagedPoolBase; +extern ULONG MmPagedPoolSize; + +#define MM_PAGED_POOL_SIZE (100*1024*1024) + +/* + * Maximum size of the kmalloc area (this is totally arbitary) + */ +#define NONPAGED_POOL_SIZE (100*1024*1024) + +#endif /* __INTERNAL_POOL_H */ diff --git a/ntoskrnl/include/internal/port.h b/ntoskrnl/include/internal/port.h new file mode 100644 index 0000000..b987c3b --- /dev/null +++ b/ntoskrnl/include/internal/port.h @@ -0,0 +1,146 @@ +#ifndef __INCLUDE_INTERNAL_PORT_H +#define __INCLUDE_INTERNAL_PORT_H + +#include + +typedef struct _EPORT_LISTENER +{ + HANDLE ListenerPid; + LIST_ENTRY ListenerListEntry; +} EPORT_LISTENER, *PEPORT_LISTENER; + +typedef struct _EPORT +{ + KSPIN_LOCK Lock; + KSEMAPHORE Semaphore; + + ULONG State; + + struct _EPORT * OtherPort; + + ULONG QueueLength; + LIST_ENTRY QueueListHead; + + ULONG ConnectQueueLength; + LIST_ENTRY ConnectQueueListHead; + + ULONG MaxDataLength; + ULONG MaxConnectInfoLength; + + /* + * List of processes that can receive connection requests on this port. + */ + LIST_ENTRY ListenerListHead; +} EPORT, * PEPORT; + + +typedef struct _EPORT_TERMINATION_REQUEST +{ + LIST_ENTRY ThreadListEntry; + PEPORT Port; +} EPORT_TERMINATION_REQUEST, *PEPORT_TERMINATION_REQUEST; + + +typedef struct _EPORT_CONNECT_REQUEST_MESSAGE +{ + LPC_MESSAGE_HEADER MessageHeader; + PEPROCESS ConnectingProcess; + struct _SECTION_OBJECT* SendSectionObject; + LARGE_INTEGER SendSectionOffset; + ULONG SendViewSize; + ULONG ConnectDataLength; + UCHAR ConnectData[0]; +} EPORT_CONNECT_REQUEST_MESSAGE, *PEPORT_CONNECT_REQUEST_MESSAGE; + +typedef struct _EPORT_CONNECT_REPLY_MESSAGE +{ + LPC_MESSAGE_HEADER MessageHeader; + PVOID SendServerViewBase; + ULONG ReceiveClientViewSize; + PVOID ReceiveClientViewBase; + ULONG MaximumMessageSize; + ULONG ConnectDataLength; + UCHAR ConnectData[0]; +} EPORT_CONNECT_REPLY_MESSAGE, *PEPORT_CONNECT_REPLY_MESSAGE; + +NTSTATUS STDCALL +LpcRequestPort (PEPORT Port, + PLPC_MESSAGE LpcMessage); +NTSTATUS +STDCALL +LpcSendTerminationPort (PEPORT Port, + TIME CreationTime); + + +/* EPORT.State */ + +#define EPORT_INACTIVE (0) +#define EPORT_WAIT_FOR_CONNECT (1) +#define EPORT_WAIT_FOR_ACCEPT (2) +#define EPORT_WAIT_FOR_COMPLETE_SRV (3) +#define EPORT_WAIT_FOR_COMPLETE_CLT (4) +#define EPORT_CONNECTED_CLIENT (5) +#define EPORT_CONNECTED_SERVER (6) +#define EPORT_DISCONNECTED (7) + +typedef struct _QUEUEDMESSAGE +{ + PEPORT Sender; + LIST_ENTRY QueueListEntry; + LPC_MESSAGE Message; + UCHAR MessageData [MAX_MESSAGE_DATA]; +} QUEUEDMESSAGE, *PQUEUEDMESSAGE; + +/* Code in ntoskrnl/lpc/close.h */ + +VOID STDCALL +NiClosePort (PVOID ObjectBody, + ULONG HandleCount); +VOID STDCALL +NiDeletePort (IN PVOID ObjectBody); + +/* Code in ntoskrnl/lpc/queue.c */ + +VOID STDCALL +EiEnqueueConnectMessagePort (IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message); +VOID STDCALL +EiEnqueueMessagePort (IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message); +VOID STDCALL +EiEnqueueMessageAtHeadPort (IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message); +PQUEUEDMESSAGE +STDCALL +EiDequeueConnectMessagePort (IN OUT PEPORT Port); +PQUEUEDMESSAGE STDCALL +EiDequeueMessagePort (IN OUT PEPORT Port); + +/* Code in ntoskrnl/lpc/create.c */ + +NTSTATUS STDCALL +NiCreatePort (PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes); + +/* Code in ntoskrnl/lpc/port.c */ + +NTSTATUS STDCALL +NiInitializePort (IN OUT PEPORT Port); +NTSTATUS +NiInitPort (VOID); + +extern POBJECT_TYPE ExPortType; +extern ULONG EiNextLpcMessageId; + +/* Code in ntoskrnl/lpc/reply.c */ + +NTSTATUS STDCALL +EiReplyOrRequestPort (IN PEPORT Port, + IN PLPC_MESSAGE LpcReply, + IN ULONG MessageType, + IN PEPORT Sender); + + +#endif /* __INCLUDE_INTERNAL_PORT_H */ diff --git a/ntoskrnl/include/internal/ps.h b/ntoskrnl/include/internal/ps.h new file mode 100644 index 0000000..26df5e5 --- /dev/null +++ b/ntoskrnl/include/internal/ps.h @@ -0,0 +1,508 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * FILE: ntoskrnl/ke/kthread.c + * PURPOSE: Process manager definitions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +#ifndef __INCLUDE_INTERNAL_PS_H +#define __INCLUDE_INTERNAL_PS_H + +#ifndef __ASM__ + +/* Forward declarations. */ +struct _KTHREAD; +struct _KTRAPFRAME; + +#endif /* __ASM__ */ + +#include + +#ifndef __ASM__ + +#include +#include + +#define KeGetCurrentProcessorNumber() (KeGetCurrentKPCR()->ProcessorNumber) + +extern HANDLE SystemProcessHandle; + +extern LCID PsDefaultThreadLocaleId; +extern LCID PsDefaultSystemLocaleId; + +typedef struct _KAPC_STATE +{ + LIST_ENTRY ApcListHead[2]; + struct _KPROCESS* Process; + UCHAR KernelApcInProgress; + UCHAR KernelApcPending; + USHORT UserApcPending; +} __attribute__((packed)) KAPC_STATE, *PKAPC_STATE; + +typedef struct _KTHREAD +{ + /* For waiting on thread exit */ + DISPATCHER_HEADER DispatcherHeader; /* 00 */ + + /* List of mutants owned by the thread */ + LIST_ENTRY MutantListHead; /* 10 */ + PVOID InitialStack; /* 18 */ + ULONG StackLimit; /* 1C */ + + /* Pointer to the thread's environment block in user memory */ + PTEB Teb; /* 20 */ + + /* Pointer to the thread's TLS array */ + PVOID TlsArray; /* 24 */ + PVOID KernelStack; /* 28 */ + UCHAR DebugActive; /* 2C */ + + /* Thread state (one of THREAD_STATE_xxx constants below) */ + UCHAR State; /* 2D */ + UCHAR Alerted[2]; /* 2E */ + UCHAR Iopl; /* 30 */ + UCHAR NpxState; /* 31 */ + UCHAR Saturation; /* 32 */ + CHAR Priority; /* 33 */ + KAPC_STATE ApcState; /* 34 */ + ULONG ContextSwitches; /* 4C */ + ULONG WaitStatus; /* 50 */ + KIRQL WaitIrql; /* 54 */ + UCHAR WaitMode; /* 55 */ + UCHAR WaitNext; /* 56 */ + UCHAR WaitReason; /* 57 */ + PKWAIT_BLOCK WaitBlockList; /* 58 */ + LIST_ENTRY WaitListEntry; /* 5C */ + ULONG WaitTime; /* 64 */ + CHAR BasePriority; /* 68 */ + UCHAR DecrementCount; /* 69 */ + UCHAR PriorityDecrement; /* 6A */ + UCHAR Quantum; /* 6B */ + KWAIT_BLOCK WaitBlock[4]; /* 6C */ + PVOID LegoData; /* CC */ + LONG KernelApcDisable; /* D0 */ + KAFFINITY UserAffinity; /* D4 */ + UCHAR SystemAffinityActive;/* D8 */ + UCHAR Pad[7]; /* D9 */ + PKQUEUE Queue; /* E0 */ + KSPIN_LOCK ApcQueueLock; /* E4 */ + KTIMER Timer; /* E8 */ + LIST_ENTRY QueueListEntry; /* 110 */ + KAFFINITY Affinity; /* 118 */ + UCHAR Preempted; /* 11C */ + UCHAR ProcessReadyQueue; /* 11D */ + UCHAR KernelStackResident; /* 11E */ + UCHAR NextProcessor; /* 11F */ + PVOID CallbackStack; /* 120 */ + BOOL Win32Thread; /* 124 */ + struct _KTRAP_FRAME* TrapFrame; /* 128 */ + PVOID ApcStatePointer[2]; /* 12C */ + UCHAR EnableStackSwap; /* 134 */ + UCHAR LargeStack; /* 135 */ + UCHAR ResourceIndex; /* 136 */ + UCHAR PreviousMode; /* 137 */ + ULONG KernelTime; /* 138 */ + ULONG UserTime; /* 13C */ + KAPC_STATE SavedApcState; /* 140 */ + UCHAR Alertable; /* 158 */ + UCHAR ApcStateIndex; /* 159 */ + UCHAR ApcQueueable; /* 15A */ + UCHAR AutoAlignment; /* 15B */ + PVOID StackBase; /* 15C */ + KAPC SuspendApc; /* 160 */ + KSEMAPHORE SuspendSemaphore; /* 190 */ + LIST_ENTRY ThreadListEntry; /* 1A4 */ + CHAR FreezeCount; /* 1AC */ + UCHAR SuspendCount; /* 1AD */ + UCHAR IdealProcessor; /* 1AE */ + UCHAR DisableBoost; /* 1AF */ + + /* + * Below here are thread structure members that are specific to ReactOS + */ + + /* Added by Phillip Susi for list of threads in a process */ + LIST_ENTRY ProcessThreadListEntry; /* 1B0 */ +} __attribute__((packed)) KTHREAD, *PKTHREAD; + +/* Top level irp definitions. */ +#define FSRTL_FSP_TOP_LEVEL_IRP (0x01) +#define FSRTL_CACHE_TOP_LEVEL_IRP (0x02) +#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP (0x03) +#define FSRTL_FAST_IO_TOP_LEVEL_IRP (0x04) +#define FSRTL_MAX_TOP_LEVEL_IRP_FLAG (0x04) + +typedef struct _TOP_LEVEL_IRP +{ + PIRP TopLevelIrp; + ULONG TopLevelIrpConst; +} TOP_LEVEL_IRP; + +typedef struct +{ + PACCESS_TOKEN Token; // 0x0 + UCHAR Unknown1; // 0x4 + UCHAR Unknown2; // 0x5 + UCHAR Pad[2]; // 0x6 + SECURITY_IMPERSONATION_LEVEL Level; // 0x8 +} PS_IMPERSONATION_INFO, *PPS_IMPERSONATION_INFO; + +typedef struct _ETHREAD +{ + KTHREAD Tcb; /* 000 */ + TIME CreateTime; /* 1B0/1B8 */ + union + { + TIME ExitTime; /* 1B8/1E4 */ + LIST_ENTRY LpcReplyChain; /* 1B8/1E4 */ + } u1; + NTSTATUS ExitStatus; /* 1C0/1EC */ + LIST_ENTRY PostBlockList; /* 1C4/1F0 */ + LIST_ENTRY TerminationPortList; /* 1CC/1F8 */ + KSPIN_LOCK ActiveTimerListLock; /* 1D4/200 */ + LIST_ENTRY ActiveTimerListHead; /* 1D8/204 */ + CLIENT_ID Cid; /* 1E0/20C */ + KSEMAPHORE LpcReplySemaphore; /* 1E8/214 */ + PVOID LpcReplyMessage; /* 1FC/228 */ + PLARGE_INTEGER LpcReplyMessageId; /* 200/22C */ + ULONG PerformanceCounterLow; /* 204/230 */ + PPS_IMPERSONATION_INFO ImpersonationInfo; /* 208/234 */ + LIST_ENTRY IrpList; /* 20C/238 */ + TOP_LEVEL_IRP* TopLevelIrp; /* 214/240 */ + PDEVICE_OBJECT DeviceToVerify; /* 218/244 */ + ULONG ReadClusterSize; /* 21C/248 */ + UCHAR ForwardClusterOnly; /* 220/24C */ + UCHAR DisablePageFaultClustering; /* 221/24D */ + UCHAR DeadThread; /* 222/24E */ + UCHAR HasTerminated; /* 223/24F */ + PVOID EventPair; /* 224/250 */ + ACCESS_MASK GrantedAccess; /* 228/254 */ + struct _EPROCESS* ThreadsProcess; /* 22C/258 */ + PKSTART_ROUTINE StartAddress; /* 230/25C */ + union + { + LPTHREAD_START_ROUTINE Win32StartAddress; /* 234/260 */ + ULONG LpcReceiveMessageId; /* 234/260 */ + } u2; + UCHAR LpcExitThreadCalled; /* 238/264 */ + UCHAR HardErrorsAreDisabled; /* 239/265 */ + UCHAR LpcReceivedMsgIdValid; /* 23A/266 */ + UCHAR ActiveImpersonationInfo; /* 23B/267 */ + ULONG PerformanceCountHigh; /* 23C/268 */ + + /* + * Added by David Welch (welch@cwcom.net) + */ + struct _EPROCESS* OldProcess; /* 240/26C */ + + struct _W32THREAD* Win32Thread; + +} __attribute__((packed)) ETHREAD, *PETHREAD; + + +typedef struct _KPROCESS +{ + /* So it's possible to wait for the process to terminate */ + DISPATCHER_HEADER DispatcherHeader; /* 000 */ + /* + * Presumably a list of profile objects associated with this process, + * currently unused. + */ + LIST_ENTRY ProfileListHead; /* 010 */ + /* + * We use the first member of this array to hold the physical address of + * the page directory for this process. + */ + PHYSICAL_ADDRESS DirectoryTableBase; /* 018 */ + /* + * Presumably a descriptor for the process's LDT, currently unused. + */ + ULONG LdtDescriptor[2]; /* 020 */ + /* + * Presumably for processing int 0x21 from V86 mode DOS, currently + * unused. + */ + ULONG Int21Descriptor[2]; /* 028 */ + /* Don't know. */ + USHORT IopmOffset; /* 030 */ + /* + * Presumably I/O privilege level to be used for this process, currently + * unused. + */ + UCHAR Iopl; /* 032 */ + /* Set if this process is a virtual dos machine? */ + UCHAR VdmFlag; /* 033 */ + /* Bitmask of the processors being used by this process's threads? */ + ULONG ActiveProcessors; /* 034 */ + /* Aggregate of the time this process's threads have spent in kernel mode? */ + ULONG KernelTime; /* 038 */ + /* Aggregate of the time this process's threads have spent in user mode? */ + ULONG UserTime; /* 03C */ + /* List of this process's threads that are ready for execution? */ + LIST_ENTRY ReadyListHead; /* 040 */ + /* List of this process's threads that have their stacks swapped out? */ + LIST_ENTRY SwapListEntry; /* 048 */ + /* List of this process's threads? */ + LIST_ENTRY ThreadListHead; /* 050 */ + /* Maybe a lock for this data structure, the type is assumed. */ + KSPIN_LOCK ProcessLock; /* 058 */ + /* Default affinity mask for this process's threads? */ + ULONG Affinity; /* 05C */ + /* Count of the stacks allocated for this process's threads? */ + USHORT StackCount; /* 060 */ + /* Base priority for this process's threads? */ + KPRIORITY BasePriority; /* 062 */ + /* Default quantum for this process's threads */ + UCHAR ThreadQuantum; /* 063 */ + /* Unknown. */ + UCHAR AutoAlignment; /* 064 */ + /* Process execution state, currently either active or terminated. */ + UCHAR State; /* 065 */ + /* Seed for generating thread ids for this process's threads? */ + UCHAR ThreadSeed; /* 066 */ + /* Disable priority boosts? */ + UCHAR DisableBoost; /* 067 */ +} KPROCESS, *PKPROCESS; + +struct _EPROCESS +{ + /* Microkernel specific process state. */ + KPROCESS Pcb; /* 000 */ + /* Exit status of the process. */ + NTSTATUS ExitStatus; /* 068 */ + /* Unknown. */ + KEVENT LockEvent; /* 06C */ + /* Unknown. */ + ULONG LockCount; /* 07C */ + /* Time of process creation. */ + TIME CreateTime; /* 080 */ + /* Time of process exit. */ + TIME ExitTime; /* 088 */ + /* Unknown. */ + PVOID LockOwner; /* 090 */ + /* Process id. */ + ULONG UniqueProcessId; /* 094 */ + /* Unknown. */ + LIST_ENTRY ActiveProcessLinks; /* 098 */ + /* Unknown. */ + ULONG QuotaPeakPoolUsage[2]; /* 0A0 */ + /* Unknown. */ + ULONG QuotaPoolUsage[2]; /* 0A8 */ + /* Unknown. */ + ULONG PagefileUsage; /* 0B0 */ + /* Unknown. */ + ULONG CommitCharge; /* 0B4 */ + /* Unknown. */ + ULONG PeakPagefileUsage; /* 0B8 */ + /* Unknown. */ + ULONG PeakVirtualSize; /* 0BC */ + /* Unknown. */ + LARGE_INTEGER VirtualSize; /* 0C0 */ + struct + { + ULONG LastTrimTime; + ULONG LastTrimFaultCount; + ULONG PageFaultCount; + ULONG PeakWorkingSetSize; + ULONG WorkingSetSize; + ULONG MinimumWorkingSetSize; + ULONG MaximumWorkingSetSize; + ULONG VmWorkingSetList; + LIST_ENTRY WorkingSetExpansionList; + UCHAR AllowWorkingSetAdjustment; + UCHAR AddressSpaceBeingDeleted; + UCHAR ForegroundPrioritySwitch; + UCHAR MemoryPriority; + } Vm; + PVOID LastProtoPteFault; + struct _EPORT* DebugPort; + struct _EPORT* ExceptionPort; + PVOID ObjectTable; + PVOID Token; + /* FAST_MUTEX WorkingSetLock; */ + KMUTEX WorkingSetLock; + PVOID WorkingSetPage; + UCHAR ProcessOutswapEnabled; + UCHAR ProcessOutswapped; + UCHAR AddressSpaceInitialized; + UCHAR AddressSpaceDeleted; + FAST_MUTEX AddressCreationLock; + KSPIN_LOCK HyperSpaceLock; + PETHREAD ForkInProgress; + USHORT VmOperation; + UCHAR ForkWasSuccessful; + UCHAR MmAgressiveWsTrimMask; + PKEVENT VmOperationEvent; + PVOID PageDirectoryPte; + ULONG LastFaultCount; + PVOID VadRoot; + PVOID VadHint; + PVOID CloneRoot; + ULONG NumberOfPrivatePages; + ULONG NumberOfLockedPages; + USHORT NextProcessColour; + UCHAR ExitProcessCalled; + UCHAR CreateProcessReported; + HANDLE SectionHandle; + PPEB Peb; + PVOID SectionBaseAddress; + PVOID QuotaBlock; + NTSTATUS LastThreadExitStatus; + PVOID WorkingSetWatch; + HANDLE InheritedFromUniqueProcessId; + ACCESS_MASK GrantedAccess; + ULONG DefaultHardErrorProcessing; + PVOID LdtInformation; + ULONG VadFreeHint; + PVOID VdmObjects; + KMUTANT ProcessMutant; + CHAR ImageFileName[16]; + ULONG VmTrimFaultValue; + UCHAR SetTimerResolution; + UCHAR PriorityClass; + UCHAR SubSystemMinorVersion; + UCHAR SubSystemMajorVersion; + USHORT SubSystemVersion; + struct _W32PROCESS* Win32Process; + HANDLE Win32WindowStation; + + /* + * Added by David Welch (welch@mcmail.com) + */ + HANDLE Win32Desktop; + MADDRESS_SPACE AddressSpace; + HANDLE_TABLE HandleTable; + LIST_ENTRY ProcessListEntry; + + /* + * Added by Philip Susi for list of threads in process + */ + LIST_ENTRY ThreadListHead; +}; + +#define PROCESS_STATE_TERMINATED (1) +#define PROCESS_STATE_ACTIVE (2) + +VOID PiInitDefaultLocale(VOID); +VOID PiInitProcessManager(VOID); +VOID PiShutdownProcessManager(VOID); +VOID PsInitThreadManagment(VOID); +VOID PsInitProcessManagment(VOID); +VOID PsInitIdleThread(VOID); +VOID PsDispatchThreadNoLock(ULONG NewThreadStatus); +VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus); +VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus); +VOID PsReleaseThread(PETHREAD Thread); +VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext); +VOID PsBeginThreadWithContextInternal(VOID); +VOID PiKillMostProcesses(VOID); +NTSTATUS STDCALL PiTerminateProcess(PEPROCESS Process, NTSTATUS ExitStatus); +VOID PiInitApcManagement(VOID); +VOID STDCALL PiDeleteThread(PVOID ObjectBody); +VOID PsReapThreads(VOID); +NTSTATUS +PsInitializeThread(HANDLE ProcessHandle, + PETHREAD* ThreadPtr, + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + BOOLEAN First); + +PACCESS_TOKEN PsReferenceEffectiveToken(PETHREAD Thread, + PTOKEN_TYPE TokenType, + PUCHAR b, + PSECURITY_IMPERSONATION_LEVEL Level); + +NTSTATUS PsOpenTokenOfProcess(HANDLE ProcessHandle, + PACCESS_TOKEN* Token); + +NTSTATUS PsSuspendThread(PETHREAD Thread, PULONG PreviousCount); +NTSTATUS PsResumeThread(PETHREAD Thread, PULONG PreviousCount); + + +#define THREAD_STATE_INITIALIZED (0) +#define THREAD_STATE_READY (1) +#define THREAD_STATE_RUNNING (2) +#define THREAD_STATE_SUSPENDED (3) +#define THREAD_STATE_FROZEN (4) +#define THREAD_STATE_TERMINATED_1 (5) +#define THREAD_STATE_TERMINATED_2 (6) +#define THREAD_STATE_BLOCKED (7) +#define THREAD_STATE_MAX (8) + + +/* + * Internal thread priorities, added by Phillip Susi + * TODO: rebalence these to make use of all priorities... the ones above 16 + * can not all be used right now + */ +#define PROCESS_PRIO_IDLE 3 +#define PROCESS_PRIO_NORMAL 8 +#define PROCESS_PRIO_HIGH 13 +#define PROCESS_PRIO_RT 18 + + +VOID +KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First); +NTSTATUS KeReleaseThread(PETHREAD Thread); +VOID STDCALL PiDeleteProcess(PVOID ObjectBody); +VOID PsReapThreads(VOID); +VOID PsUnfreezeOtherThread(PETHREAD Thread); +VOID PsFreezeOtherThread(PETHREAD Thread); +VOID PsFreezeProcessThreads(PEPROCESS Process); +VOID PsUnfreezeProcessThreads(PEPROCESS Process); +PEPROCESS PsGetNextProcess(PEPROCESS OldProcess); +VOID +PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode, + BOOLEAN DispatcherLock, KIRQL WaitIrql); +VOID +PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus); +VOID +PsApplicationProcessorInit(VOID); +VOID +PsPrepareForApplicationProcessorInit(ULONG Id); +NTSTATUS STDCALL +PsIdleThreadMain(PVOID Context); + +VOID STDCALL +PiSuspendThreadRundownRoutine(PKAPC Apc); +VOID STDCALL +PiSuspendThreadKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2); +VOID STDCALL +PiSuspendThreadNormalRoutine(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2); +VOID STDCALL +PsDispatchThread(ULONG NewThreadStatus); +VOID +PsInitialiseSuspendImplementation(VOID); + +extern ULONG PiNrThreadsAwaitingReaping; + +#endif /* ASSEMBLER */ + +#endif /* __INCLUDE_INTERNAL_PS_H */ diff --git a/ntoskrnl/include/internal/registry.h b/ntoskrnl/include/internal/registry.h new file mode 100644 index 0000000..1921071 --- /dev/null +++ b/ntoskrnl/include/internal/registry.h @@ -0,0 +1,14 @@ + +#ifndef __INCLUDE_INTERNAL_REGISTRY_H +#define __INCLUDE_INTERNAL_REGISTRY_H + +NTSTATUS +RtlpGetRegistryHandle(ULONG RelativeTo, + PWSTR Path, + BOOLEAN Create, + PHANDLE KeyHandle); + +NTSTATUS +RtlpCreateRegistryKeyPath(PWSTR Path); + +#endif /* __INCLUDE_INTERNAL_REGISTRY_H */ diff --git a/ntoskrnl/include/internal/safe.h b/ntoskrnl/include/internal/safe.h new file mode 100644 index 0000000..d20c7a7 --- /dev/null +++ b/ntoskrnl/include/internal/safe.h @@ -0,0 +1,16 @@ +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_SAFE_H +#define __NTOSKRNL_INCLUDE_INTERNAL_SAFE_H + +NTSTATUS MmSafeCopyFromUser(PVOID Dest, PVOID Src, ULONG NumberOfBytes); +NTSTATUS MmSafeCopyToUser(PVOID Dest, PVOID Src, ULONG NumberOfBytes); + +NTSTATUS STDCALL +MmCopyFromCaller(PVOID Dest, PVOID Src, ULONG NumberOfBytes); +NTSTATUS STDCALL +MmCopyToCaller(PVOID Dest, PVOID Src, ULONG NumberOfBytes); + +NTSTATUS +RtlCaptureUnicodeString(PUNICODE_STRING Dest, + PUNICODE_STRING UnsafeSrc); + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_SAFE_Hb */ diff --git a/ntoskrnl/include/internal/se.h b/ntoskrnl/include/internal/se.h new file mode 100644 index 0000000..98fb83c --- /dev/null +++ b/ntoskrnl/include/internal/se.h @@ -0,0 +1,127 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_SE_H +#define __NTOSKRNL_INCLUDE_INTERNAL_SE_H + + +extern POBJECT_TYPE SepTokenObjectType; + +/* SID Authorities */ +extern SID_IDENTIFIER_AUTHORITY SeNullSidAuthority; +extern SID_IDENTIFIER_AUTHORITY SeWorldSidAuthority; +extern SID_IDENTIFIER_AUTHORITY SeLocalSidAuthority; +extern SID_IDENTIFIER_AUTHORITY SeCreatorSidAuthority; +extern SID_IDENTIFIER_AUTHORITY SeNtSidAuthority; + +/* SIDs */ +extern PSID SeNullSid; +extern PSID SeWorldSid; +extern PSID SeLocalSid; +extern PSID SeCreatorOwnerSid; +extern PSID SeCreatorGroupSid; +extern PSID SeCreatorOwnerServerSid; +extern PSID SeCreatorGroupServerSid; +extern PSID SeNtAuthoritySid; +extern PSID SeDialupSid; +extern PSID SeNetworkSid; +extern PSID SeBatchSid; +extern PSID SeInteractiveSid; +extern PSID SeServiceSid; +extern PSID SeAnonymousLogonSid; +extern PSID SePrincipalSelfSid; +extern PSID SeLocalSystemSid; +extern PSID SeAuthenticatedUserSid; +extern PSID SeRestrictedCodeSid; +extern PSID SeAliasAdminsSid; +extern PSID SeAliasUsersSid; +extern PSID SeAliasGuestsSid; +extern PSID SeAliasPowerUsersSid; +extern PSID SeAliasAccountOpsSid; +extern PSID SeAliasSystemOpsSid; +extern PSID SeAliasPrintOpsSid; +extern PSID SeAliasBackupOpsSid; + +/* Privileges */ +extern LUID SeCreateTokenPrivilege; +extern LUID SeAssignPrimaryTokenPrivilege; +extern LUID SeLockMemoryPrivilege; +extern LUID SeIncreaseQuotaPrivilege; +extern LUID SeUnsolicitedInputPrivilege; +extern LUID SeTcbPrivilege; +extern LUID SeSecurityPrivilege; +extern LUID SeTakeOwnershipPrivilege; +extern LUID SeLoadDriverPrivilege; +extern LUID SeCreatePagefilePrivilege; +extern LUID SeIncreaseBasePriorityPrivilege; +extern LUID SeSystemProfilePrivilege; +extern LUID SeSystemtimePrivilege; +extern LUID SeProfileSingleProcessPrivilege; +extern LUID SeCreatePermanentPrivilege; +extern LUID SeBackupPrivilege; +extern LUID SeRestorePrivilege; +extern LUID SeShutdownPrivilege; +extern LUID SeDebugPrivilege; +extern LUID SeAuditPrivilege; +extern LUID SeSystemEnvironmentPrivilege; +extern LUID SeChangeNotifyPrivilege; +extern LUID SeRemoteShutdownPrivilege; + +/* DACLs */ +extern PACL SePublicDefaultUnrestrictedDacl; +extern PACL SePublicOpenDacl; +extern PACL SePublicOpenUnrestrictedDacl; +extern PACL SeUnrestrictedDacl; + + +/* Functions */ + +BOOLEAN SeInit1(VOID); +BOOLEAN SeInit2(VOID); + +VOID SepInitLuid(VOID); +VOID SepInitPrivileges(VOID); +BOOLEAN SepInitSecurityIDs(VOID); +BOOLEAN SepInitDACLs(VOID); +BOOLEAN SepInitSDs(VOID); + +VOID SepInitializeTokenImplementation(VOID); + +NTSTATUS SepCreateSystemProcessToken(struct _EPROCESS* Process); +NTSTATUS SepInitializeNewProcess(struct _EPROCESS* NewProcess, + struct _EPROCESS* ParentProcess); + +NTSTATUS SeExchangePrimaryToken(struct _EPROCESS* Process, + PACCESS_TOKEN NewToken, + PACCESS_TOKEN* OldTokenP); + +NTSTATUS SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, + ULONG PrivilegeCount, + KPROCESSOR_MODE PreviousMode, + PLUID_AND_ATTRIBUTES AllocatedMem, + ULONG AllocatedLength, + POOL_TYPE PoolType, + ULONG d, + PLUID_AND_ATTRIBUTES* Dest, + PULONG Length); + + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_SE_H */ + +/* EOF */ diff --git a/ntoskrnl/include/internal/trap.h b/ntoskrnl/include/internal/trap.h new file mode 100644 index 0000000..6588b32 --- /dev/null +++ b/ntoskrnl/include/internal/trap.h @@ -0,0 +1,58 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/include/internal/trap.h + * PURPOSE: Trap definitions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 10/12/00 + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H +#define __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H + +#define TF_SAVED_ORIG_STACK (0x8C) +#define TF_REGS (0x90) +#define TF_ORIG_EBP (0x94) + + +#ifndef __ASM__ + +#include + +typedef struct _KV86M_TRAP_FRAME +{ + KTRAP_FRAME Tf; + + ULONG SavedInitialStack; + + /* + * These are put on the top of the stack by the routine that entered + * v86 mode so the exception handlers can find the control information + */ + struct _KV86M_REGISTERS* regs; + ULONG orig_ebp; +} KV86M_TRAP_FRAME, *PKV86M_TRAP_FRAME; + +ULONG +KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address); + +#endif /* not __ASM__ */ + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H */ diff --git a/ntoskrnl/include/internal/v86m.h b/ntoskrnl/include/internal/v86m.h new file mode 100644 index 0000000..43f80f4 --- /dev/null +++ b/ntoskrnl/include/internal/v86m.h @@ -0,0 +1,101 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/include/internal/v86m.h + * PURPOSE: V86 mode support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 10/12/00 + */ + +#ifndef __NTOSKRNL_INCLUDE_INTERNAL_V86M_H +#define __NTOSKRNL_INCLUDE_INTERNAL_V86M_H + +#ifndef __ASM__ + +/* Emulate cli/sti instructions */ +#define KV86M_EMULATE_CLI_STI (0x1) +/* Allow the v86 mode code to access i/o ports */ +#define KV86M_ALLOW_IO_PORT_ACCESS (0x2) + +typedef struct _KV86M_REGISTERS +{ + /* + * General purpose registers + */ + + ULONG Ebp; + ULONG Edi; + ULONG Esi; + ULONG Edx; + ULONG Ecx; + ULONG Ebx; + ULONG Eax; + ULONG Ds; + ULONG Es; + ULONG Fs; + ULONG Gs; + + /* + * Control registers + */ + ULONG Eip; + ULONG Cs; + ULONG Eflags; + ULONG Esp; + ULONG Ss; + + /* + * Control structures + */ + ULONG RecoveryAddress; + UCHAR RecoveryInstruction[4]; + ULONG Vif; + ULONG Flags; + PNTSTATUS PStatus; +} KV86M_REGISTERS, *PKV86M_REGISTERS; + +NTSTATUS STDCALL +Ke386CallBios(UCHAR Int, PKV86M_REGISTERS Regs); + +#else /* ASSEMBLER */ + +/* + * Definitions for the offsets of members in the KV86M_REGISTERS + */ +#define KV86M_REGISTERS_EBP (0x0) +#define KV86M_REGISTERS_EDI (0x4) +#define KV86M_REGISTERS_ESI (0x8) +#define KV86M_REGISTERS_EDX (0xC) +#define KV86M_REGISTERS_ECX (0x10) +#define KV86M_REGISTERS_EBX (0x14) +#define KV86M_REGISTERS_EAX (0x18) +#define KV86M_REGISTERS_DS (0x1C) +#define KV86M_REGISTERS_ES (0x20) +#define KV86M_REGISTERS_FS (0x24) +#define KV86M_REGISTERS_GS (0x28) +#define KV86M_REGISTERS_EIP (0x2C) +#define KV86M_REGISTERS_CS (0x30) +#define KV86M_REGISTERS_EFLAGS (0x34) +#define KV86M_REGISTERS_ESP (0x38) +#define KV86M_REGISTERS_SS (0x3C) + +#endif /* ASSEMBLER */ + +#endif /* __NTOSKRNL_INCLUDE_INTERNAL_V86M_H */ diff --git a/ntoskrnl/include/internal/xhal.h b/ntoskrnl/include/internal/xhal.h new file mode 100644 index 0000000..55a3f17 --- /dev/null +++ b/ntoskrnl/include/internal/xhal.h @@ -0,0 +1,39 @@ +#ifndef __INCLUDE_INTERNAL_XHAL_H +#define __INCLUDE_INTERNAL_XHAL_H + +NTSTATUS +xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName, + OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo); + +VOID FASTCALL +xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG MBRTypeIdentifier, + OUT PVOID *Buffer); + +VOID FASTCALL +xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PSTRING NtDeviceName, + OUT PUCHAR NtSystemPath, + OUT PSTRING NtSystemPathString); + +NTSTATUS FASTCALL +xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + BOOLEAN ReturnRecognizedPartitions, + PDRIVE_LAYOUT_INFORMATION *PartitionBuffer); + +NTSTATUS FASTCALL +xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG PartitionNumber, + IN ULONG PartitionType); + +NTSTATUS FASTCALL +xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG SectorsPerTrack, + IN ULONG NumberOfHeads, + IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer); + +#endif diff --git a/ntoskrnl/io/.cvsignore b/ntoskrnl/io/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/io/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/io/adapter.c b/ntoskrnl/io/adapter.c new file mode 100644 index 0000000..394bac8 --- /dev/null +++ b/ntoskrnl/io/adapter.c @@ -0,0 +1,44 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/adapter.c + * PURPOSE: DMA handling + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* DATA **********************************************************************/ + +POBJECT_TYPE EXPORTED IoAdapterObjectType = NULL; /* FIXME */ +POBJECT_TYPE EXPORTED IoDeviceHandlerObjectType = NULL; /* FIXME */ +USHORT EXPORTED IoDeviceHandlerObjectSize = 0; /* FIXME */ + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +IoAllocateAdapterChannel (PADAPTER_OBJECT AdapterObject, + PDEVICE_OBJECT DeviceObject, + ULONG NumberOfMapRegisters, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context) +{ + return HalAllocateAdapterChannel( AdapterObject, + DeviceObject, + NumberOfMapRegisters, + ExecutionRoutine, + Context ); +} + + +/* NOTE: Missing IoXXXAdapter finctions in HAL.DLL */ + + +/* EOF */ diff --git a/ntoskrnl/io/arcname.c b/ntoskrnl/io/arcname.c new file mode 100644 index 0000000..2d9d14e --- /dev/null +++ b/ntoskrnl/io/arcname.c @@ -0,0 +1,420 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/arcname.c + * PURPOSE: creates ARC names for boot devices + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + + +/* INCLUDES *****************************************************************/ + +#include + +#include "internal/io.h" +#include "internal/xhal.h" + +#define NDEBUG +#include + +/* MACROS *******************************************************************/ + +#define FS_VOLUME_BUFFER_SIZE (MAX_PATH + sizeof(FILE_FS_VOLUME_INFORMATION)) + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +IoCreateArcNames(VOID) +{ + PCONFIGURATION_INFORMATION ConfigInfo; + PDRIVE_LAYOUT_INFORMATION LayoutInfo = NULL; + WCHAR DeviceNameBuffer[80]; + WCHAR ArcNameBuffer[80]; + UNICODE_STRING DeviceName; + UNICODE_STRING ArcName; + ULONG i, j; + NTSTATUS Status; + + DPRINT("IoCreateArcNames() called\n"); + + ConfigInfo = IoGetConfigurationInformation(); + + /* create ARC names for floppy drives */ + DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount); + for (i = 0; i < ConfigInfo->FloppyCount; i++) + { + swprintf(DeviceNameBuffer, + L"\\Device\\Floppy%lu", + i); + RtlInitUnicodeString(&DeviceName, + DeviceNameBuffer); + + swprintf(ArcNameBuffer, + L"\\ArcName\\multi(0)disk(0)fdisk(%lu)", + i); + RtlInitUnicodeString(&ArcName, + ArcNameBuffer); + DPRINT("%wZ ==> %wZ\n", + &ArcName, + &DeviceName); + + Status = IoAssignArcName(&ArcName, + &DeviceName); + if (!NT_SUCCESS(Status)) + return(Status); + } + + /* create ARC names for hard disk drives */ + DPRINT("Disk drives: %lu\n", ConfigInfo->DiskCount); + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + swprintf(DeviceNameBuffer, + L"\\Device\\Harddisk%lu\\Partition0", + i); + RtlInitUnicodeString(&DeviceName, + DeviceNameBuffer); + + swprintf(ArcNameBuffer, + L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(0)", + i); + RtlInitUnicodeString(&ArcName, + ArcNameBuffer); + DPRINT("%wZ ==> %wZ\n", + &ArcName, + &DeviceName); + + Status = IoAssignArcName(&ArcName, + &DeviceName); + if (!NT_SUCCESS(Status)) + return(Status); + + Status = xHalQueryDriveLayout(&DeviceName, + &LayoutInfo); + if (!NT_SUCCESS(Status)) + return(Status); + + DPRINT("Number of partitions: %u\n", LayoutInfo->PartitionCount); + + for (j = 0;j < LayoutInfo->PartitionCount; j++) + { + swprintf(DeviceNameBuffer, + L"\\Device\\Harddisk%lu\\Partition%lu", + i, + j + 1); + RtlInitUnicodeString(&DeviceName, + DeviceNameBuffer); + + swprintf(ArcNameBuffer, + L"\\ArcName\\multi(0)disk(0)rdisk(%lu)partition(%lu)", + i, + j + 1); + RtlInitUnicodeString(&ArcName, + ArcNameBuffer); + DPRINT("%wZ ==> %wZ\n", + &ArcName, + &DeviceName); + + Status = IoAssignArcName(&ArcName, + &DeviceName); + if (!NT_SUCCESS(Status)) + return(Status); + } + + ExFreePool(LayoutInfo); + LayoutInfo = NULL; + } + + /* create ARC names for cdrom drives */ + DPRINT("CD-ROM drives: %lu\n", ConfigInfo->CDRomCount); + for (i = 0; i < ConfigInfo->CDRomCount; i++) + { + swprintf(DeviceNameBuffer, + L"\\Device\\CdRom%lu", + i); + RtlInitUnicodeString(&DeviceName, + DeviceNameBuffer); + + swprintf(ArcNameBuffer, + L"\\ArcName\\multi(0)disk(0)cdrom(%lu)", + i); + RtlInitUnicodeString(&ArcName, + ArcNameBuffer); + DPRINT("%wZ ==> %wZ\n", + &ArcName, + &DeviceName); + + Status = IoAssignArcName(&ArcName, + &DeviceName); + if (!NT_SUCCESS(Status)) + return(Status); + } + + DPRINT("IoCreateArcNames() done\n"); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +IopCheckCdromDevices(PULONG DeviceNumber) +{ + PFILE_FS_VOLUME_INFORMATION FileFsVolume; + PCONFIGURATION_INFORMATION ConfigInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DeviceName; + WCHAR DeviceNameBuffer[32]; + HANDLE Handle; + ULONG i; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + USHORT Buffer[FS_VOLUME_BUFFER_SIZE]; + + FileFsVolume = (PFILE_FS_VOLUME_INFORMATION)Buffer; + + ConfigInfo = IoGetConfigurationInformation(); + for (i = 0; i < ConfigInfo->CDRomCount; i++) + { + swprintf(DeviceNameBuffer, + L"\\Device\\CdRom%lu\\", + i); + RtlInitUnicodeString(&DeviceName, + DeviceNameBuffer); + + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + + Status = NtOpenFile(&Handle, + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + 0); + DPRINT("NtOpenFile() DeviceNumber %lu Status %lx\n", i, Status); + if (NT_SUCCESS(Status)) + { + Status = NtQueryVolumeInformationFile(Handle, + &IoStatusBlock, + FileFsVolume, + FS_VOLUME_BUFFER_SIZE, + FileFsVolumeInformation); + DPRINT("NtQueryVolumeInformationFile() Status %lx\n", Status); + if (NT_SUCCESS(Status)) + { + DPRINT("VolumeLabel: '%S'\n", FileFsVolume->VolumeLabel); + if (_wcsicmp(FileFsVolume->VolumeLabel, L"REACTOS") == 0) + { + NtClose(Handle); + *DeviceNumber = i; + return(STATUS_SUCCESS); + } + } + NtClose(Handle); + } + } + + *DeviceNumber = (ULONG)-1; + + return(STATUS_UNSUCCESSFUL); +} + + +NTSTATUS +IoCreateSystemRootLink(PCHAR ParameterLine) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING LinkName; + UNICODE_STRING DeviceName; + UNICODE_STRING ArcName; + UNICODE_STRING BootPath; + PCHAR ParamBuffer; + PWCHAR ArcNameBuffer; + PCHAR p; + NTSTATUS Status; + ULONG Length; + HANDLE Handle; + + /* Create local parameter line copy */ + ParamBuffer = ExAllocatePool(PagedPool, 256); + strcpy(ParamBuffer, (char *)ParameterLine); + + DPRINT("%s\n", ParamBuffer); + /* Format: \ [options...] */ + + /* cut options off */ + p = strchr(ParamBuffer, ' '); + if (p) + *p = 0; + DPRINT("%s\n", ParamBuffer); + + /* extract path */ + p = strchr(ParamBuffer, '\\'); + if (p) + { + DPRINT("Boot path: %s\n", p); + RtlCreateUnicodeStringFromAsciiz(&BootPath, p); + *p = 0; + } + else + { + DPRINT("Boot path: %s\n", "\\"); + RtlCreateUnicodeStringFromAsciiz(&BootPath, "\\"); + } + DPRINT("ARC name: %s\n", ParamBuffer); + + p = strstr(ParamBuffer, "cdrom"); + if (p != NULL) + { + ULONG DeviceNumber; + + DPRINT("Booting from CD-ROM!\n"); + Status = IopCheckCdromDevices(&DeviceNumber); + if (!NT_SUCCESS(Status)) + { + CPRINT("Failed to find setup disk!\n"); + return(Status); + } + + sprintf(p, "cdrom(%lu)", DeviceNumber); + + DPRINT("New ARC name: %s\n", ParamBuffer); + + /* Adjust original command line */ + p = strstr(ParameterLine, "cdrom"); + if (p != NULL); + { + char temp[256]; + char *q; + + q = strchr(p, ')'); + if (q != NULL) + { + + q++; + strcpy(temp, q); + sprintf(p, "cdrom(%lu)", DeviceNumber); + strcat(p, temp); + } + } + } + + /* Only arc name left - build full arc name */ + ArcNameBuffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR)); + swprintf(ArcNameBuffer, + L"\\ArcName\\%S", ParamBuffer); + RtlInitUnicodeString(&ArcName, ArcNameBuffer); + DPRINT("Arc name: %wZ\n", &ArcName); + + /* free ParamBuffer */ + ExFreePool(ParamBuffer); + + /* allocate device name string */ + DeviceName.Length = 0; + DeviceName.MaximumLength = 256 * sizeof(WCHAR); + DeviceName.Buffer = ExAllocatePool(PagedPool, 256 * sizeof(WCHAR)); + + InitializeObjectAttributes(&ObjectAttributes, + &ArcName, + OBJ_OPENLINK, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&BootPath); + RtlFreeUnicodeString(&DeviceName); + CPRINT("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n", + &ArcName, + Status); + RtlFreeUnicodeString(&ArcName); + + return(Status); + } + RtlFreeUnicodeString(&ArcName); + + Status = NtQuerySymbolicLinkObject(Handle, + &DeviceName, + &Length); + NtClose (Handle); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&BootPath); + RtlFreeUnicodeString(&DeviceName); + CPRINT("NtQuerySymbolicObject() failed (Status %x)\n", + Status); + + return(Status); + } + DPRINT("Length: %lu DeviceName: %wZ\n", Length, &DeviceName); + + RtlAppendUnicodeStringToString(&DeviceName, + &BootPath); + + RtlFreeUnicodeString(&BootPath); + DPRINT("DeviceName: %wZ\n", &DeviceName); + + /* create the '\SystemRoot' link */ + RtlInitUnicodeStringFromLiteral(&LinkName, + L"\\SystemRoot"); + + Status = IoCreateSymbolicLink(&LinkName, + &DeviceName); + RtlFreeUnicodeString (&DeviceName); + if (!NT_SUCCESS(Status)) + { + CPRINT("IoCreateSymbolicLink() failed (Status %x)\n", + Status); + + return(Status); + } + + /* Check whether '\SystemRoot'(LinkName) can be opened */ + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + 0, + NULL, + NULL); + + Status = NtOpenFile(&Handle, + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + CPRINT("NtOpenFile() failed to open '\\SystemRoot' (Status %x)\n", + Status); + return(Status); + } + + NtClose(Handle); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/io/buildirp.c b/ntoskrnl/io/buildirp.c new file mode 100644 index 0000000..f095690 --- /dev/null +++ b/ntoskrnl/io/buildirp.c @@ -0,0 +1,521 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/buildirp.c + * PURPOSE: Building various types of irp + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + * Fixed IO method handling 04/03/99 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +#define TAG_SYS_BUF TAG('S', 'B', 'U', 'F') + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS IoPrepareIrpBuffer(PIRP Irp, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + ULONG MajorFunction) +/* + * FUNCTION: Prepares the buffer to be used for an IRP + */ +{ + Irp->UserBuffer = Buffer; + if (DeviceObject->Flags & DO_BUFFERED_IO) + { + DPRINT("Doing buffer i/o\n"); + Irp->AssociatedIrp.SystemBuffer = + (PVOID)ExAllocatePoolWithTag(NonPagedPool,Length, TAG_SYS_BUF); + if (Irp->AssociatedIrp.SystemBuffer==NULL) + { + IoFreeIrp(Irp); + return(STATUS_NOT_IMPLEMENTED); + } + /* FIXME: should copy buffer in on other ops */ + if (MajorFunction == IRP_MJ_WRITE) + { + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length); + } + } + if (DeviceObject->Flags & DO_DIRECT_IO) + { + DPRINT("Doing direct i/o\n"); + + Irp->MdlAddress = MmCreateMdl(NULL,Buffer,Length); + if (MajorFunction == IRP_MJ_READ) + { + MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess); + } + else + { + MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoReadAccess); + } + Irp->UserBuffer = NULL; + Irp->AssociatedIrp.SystemBuffer = NULL; + } + return(STATUS_SUCCESS); +} + + +PIRP STDCALL +IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock) +/* + * FUNCTION: Allocates and sets up an IRP to be sent to lower level drivers + * ARGUMENTS: + * MajorFunction = One of IRP_MJ_READ, IRP_MJ_WRITE, + * IRP_MJ_FLUSH_BUFFERS or IRP_MJ_SHUTDOWN + * DeviceObject = Device object to send the irp to + * Buffer = Buffer into which data will be read or written + * Length = Length in bytes of the irp to be allocated + * StartingOffset = Starting offset on the device + * IoStatusBlock (OUT) = Storage for the result of the operation + * RETURNS: The IRP allocated on success, or + * NULL on failure + */ +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + + DPRINT("IoBuildAsynchronousFsdRequest(MajorFunction %x, DeviceObject %x, " + "Buffer %x, Length %x, StartingOffset %x, " + "IoStatusBlock %x\n",MajorFunction,DeviceObject,Buffer,Length, + StartingOffset,IoStatusBlock); + + Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE); + if (Irp==NULL) + { + return(NULL); + } + + Irp->UserIosb = IoStatusBlock; + DPRINT("Irp->UserIosb %x\n", Irp->UserIosb); + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = MajorFunction; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + + if (Buffer != NULL) + { + IoPrepareIrpBuffer(Irp, + DeviceObject, + Buffer, + Length, + MajorFunction); + } + + if (MajorFunction == IRP_MJ_READ) + { + StackPtr->Parameters.Read.Length = Length; + if (StartingOffset!=NULL) + { + StackPtr->Parameters.Read.ByteOffset = *StartingOffset; + } + else + { + StackPtr->Parameters.Read.ByteOffset.u.LowPart = 0; + StackPtr->Parameters.Read.ByteOffset.u.LowPart = 0; + } + } + else if (MajorFunction == IRP_MJ_WRITE) + { + StackPtr->Parameters.Write.Length = Length; + if (StartingOffset!=NULL) + { + StackPtr->Parameters.Write.ByteOffset = *StartingOffset; + } + else + { + StackPtr->Parameters.Write.ByteOffset.QuadPart = 0; + } + } + + Irp->UserIosb = IoStatusBlock; + + return(Irp); +} + + +PIRP STDCALL +IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock) +/* + * FUNCTION: Allocates and sets up an IRP to be sent to drivers + * ARGUMENTS: + * IoControlCode = Device io control code + * DeviceObject = Device object to send the irp to + * InputBuffer = Buffer from which data will be read by the driver + * InputBufferLength = Length in bytes of the input buffer + * OutputBuffer = Buffer into which data will be written by the driver + * OutputBufferLength = Length in bytes of the output buffer + * InternalDeviceIoControl = Determines weather + * IRP_MJ_INTERNAL_DEVICE_CONTROL or + * IRP_MJ_DEVICE_CONTROL will be used + * Event = Event used to notify the caller of completion + * IoStatusBlock (OUT) = Storage for the result of the operation + * RETURNS: The IRP allocated on success, or + * NULL on failure + */ +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + ULONG BufferLength; + + DPRINT("IoBuildDeviceIoRequest(IoControlCode %x, DeviceObject %x, " + "InputBuffer %x, InputBufferLength %x, OutputBuffer %x, " + "OutputBufferLength %x, InternalDeviceIoControl %x " + "Event %x, IoStatusBlock %x\n",IoControlCode,DeviceObject, + InputBuffer,InputBufferLength,OutputBuffer,OutputBufferLength, + InternalDeviceIoControl,Event,IoStatusBlock); + + Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE); + if (Irp==NULL) + { + return(NULL); + } + + Irp->UserEvent = Event; + Irp->UserIosb = IoStatusBlock; + DPRINT("Irp->UserIosb %x\n", Irp->UserIosb); + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = InternalDeviceIoControl ? + IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode; + StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength; + StackPtr->Parameters.DeviceIoControl.OutputBufferLength = + OutputBufferLength; + + switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) + { + case METHOD_BUFFERED: + DPRINT("Using METHOD_BUFFERED!\n"); + + if (InputBufferLength > OutputBufferLength) + { + BufferLength = InputBufferLength; + } + else + { + BufferLength = OutputBufferLength; + } + if (BufferLength) + { + Irp->AssociatedIrp.SystemBuffer = (PVOID) + ExAllocatePoolWithTag(NonPagedPool,BufferLength, TAG_SYS_BUF); + + if (Irp->AssociatedIrp.SystemBuffer == NULL) + { + IoFreeIrp(Irp); + return(NULL); + } + } + + if (InputBuffer && InputBufferLength) + { + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, + InputBuffer, + InputBufferLength); + } + Irp->UserBuffer = OutputBuffer; + break; + + case METHOD_IN_DIRECT: + DPRINT("Using METHOD_IN_DIRECT!\n"); + + /* build input buffer (control buffer) */ + if (InputBuffer && InputBufferLength) + { + Irp->AssociatedIrp.SystemBuffer = (PVOID) + ExAllocatePoolWithTag(NonPagedPool,InputBufferLength, + TAG_SYS_BUF); + + if (Irp->AssociatedIrp.SystemBuffer == NULL) + { + IoFreeIrp(Irp); + return(NULL); + } + + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, + InputBuffer, + InputBufferLength); + } + + /* build output buffer (data transfer buffer) */ + if (OutputBuffer && OutputBufferLength) + { + Irp->MdlAddress = IoAllocateMdl(OutputBuffer, + OutputBufferLength, + FALSE, + FALSE, + Irp); + MmProbeAndLockPages (Irp->MdlAddress,UserMode,IoReadAccess); + } + break; + + case METHOD_OUT_DIRECT: + DPRINT("Using METHOD_OUT_DIRECT!\n"); + + /* build input buffer (control buffer) */ + if (InputBuffer && InputBufferLength) + { + Irp->AssociatedIrp.SystemBuffer = (PVOID) + ExAllocatePoolWithTag(NonPagedPool,InputBufferLength, + TAG_SYS_BUF); + + if (Irp->AssociatedIrp.SystemBuffer==NULL) + { + IoFreeIrp(Irp); + return(NULL); + } + + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, + InputBuffer, + InputBufferLength); + } + + /* build output buffer (data transfer buffer) */ + if (OutputBuffer && OutputBufferLength) + { + Irp->MdlAddress = IoAllocateMdl(OutputBuffer, + OutputBufferLength, + FALSE, + FALSE, + Irp); + MmProbeAndLockPages(Irp->MdlAddress,UserMode,IoWriteAccess); + } + break; + + case METHOD_NEITHER: + DPRINT("Using METHOD_NEITHER!\n"); + + Irp->UserBuffer = OutputBuffer; + StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer; + break; + } + + return(Irp); +} + + +PIRP STDCALL +IoBuildSynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock) +/* + * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower + * level driver(s) + * ARGUMENTS: + * MajorFunction = Major function code, one of IRP_MJ_READ, + * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN + * DeviceObject = Target device object + * Buffer = Buffer containing data for a read or write + * Length = Length in bytes of the information to be transferred + * StartingOffset = Offset to begin the read/write from + * Event (OUT) = Will be set when the operation is complete + * IoStatusBlock (OUT) = Set to the status of the operation + * RETURNS: The IRP allocated on success, or + * NULL on failure + */ +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + + DPRINT("IoBuildSynchronousFsdRequest(MajorFunction %x, DeviceObject %x, " + "Buffer %x, Length %x, StartingOffset %x, Event %x, " + "IoStatusBlock %x\n",MajorFunction,DeviceObject,Buffer,Length, + StartingOffset,Event,IoStatusBlock); + + Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE); + if (Irp==NULL) + { + return(NULL); + } + + Irp->UserEvent = Event; + Irp->UserIosb = IoStatusBlock; + DPRINT("Irp->UserIosb %x\n", Irp->UserIosb); + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = MajorFunction; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + + if (Buffer != NULL) + { + IoPrepareIrpBuffer(Irp, + DeviceObject, + Buffer, + Length, + MajorFunction); + } + + if (MajorFunction == IRP_MJ_READ) + { + if (StartingOffset != NULL) + { + StackPtr->Parameters.Read.ByteOffset = *StartingOffset; + } + else + { + StackPtr->Parameters.Read.ByteOffset.QuadPart = 0; + } + StackPtr->Parameters.Read.Length = Length; + } + else + { + if (StartingOffset!=NULL) + { + StackPtr->Parameters.Write.ByteOffset = *StartingOffset; + } + else + { + StackPtr->Parameters.Write.ByteOffset.QuadPart = 0; + } + StackPtr->Parameters.Write.Length = Length; + } + + return(Irp); +} + + +PIRP +IoBuildSynchronousFsdRequestWithMdl(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PMDL Mdl, + PLARGE_INTEGER StartingOffset, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock, + BOOLEAN PagingIo) +/* + * FUNCTION: Allocates and builds an IRP to be sent synchronously to lower + * level driver(s) + * ARGUMENTS: + * MajorFunction = Major function code, one of IRP_MJ_READ, + * IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS, IRP_MJ_SHUTDOWN + * DeviceObject = Target device object + * Buffer = Buffer containing data for a read or write + * Length = Length in bytes of the information to be transferred + * StartingOffset = Offset to begin the read/write from + * Event (OUT) = Will be set when the operation is complete + * IoStatusBlock (OUT) = Set to the status of the operation + * RETURNS: The IRP allocated on success, or + * NULL on failure + */ +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + + DPRINT("IoBuildSynchronousFsdRequestWithMdl(MajorFunction %x, " + "DeviceObject %x, " + "Mdl %x, StartingOffset %x, Event %x, " + "IoStatusBlock %x\n",MajorFunction,DeviceObject,Mdl, + StartingOffset,Event,IoStatusBlock); + + Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE); + if (Irp==NULL) + { + return(NULL); + } + + Irp->UserEvent = Event; + Irp->UserIosb = IoStatusBlock; + DPRINT("Irp->UserIosb %x\n", Irp->UserIosb); + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + if (PagingIo) + { + Irp->Flags = IRP_PAGING_IO; + } + else + { + Irp->Flags = 0; + } + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = MajorFunction; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + + Irp->MdlAddress = Mdl; + Irp->UserBuffer = NULL; + Irp->AssociatedIrp.SystemBuffer = NULL; + + if (MajorFunction == IRP_MJ_READ) + { + if (StartingOffset != NULL) + { + StackPtr->Parameters.Read.ByteOffset = *StartingOffset; + } + else + { + StackPtr->Parameters.Read.ByteOffset.QuadPart = 0; + } + StackPtr->Parameters.Read.Length = MmGetMdlByteCount(Mdl); + } + else + { + if (StartingOffset!=NULL) + { + StackPtr->Parameters.Write.ByteOffset = *StartingOffset; + } + else + { + StackPtr->Parameters.Write.ByteOffset.QuadPart = 0; + } + StackPtr->Parameters.Write.Length = MmGetMdlByteCount(Mdl); + } + + return(Irp); +} + +/* EOF */ diff --git a/ntoskrnl/io/cancel.c b/ntoskrnl/io/cancel.c new file mode 100644 index 0000000..0b711fd --- /dev/null +++ b/ntoskrnl/io/cancel.c @@ -0,0 +1,85 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/cancel.c + * PURPOSE: Cancel routine + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static KSPIN_LOCK CancelSpinLock; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtCancelIoFile (IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock) +{ + UNIMPLEMENTED; +} + +BOOLEAN STDCALL +IoCancelIrp(PIRP Irp) +{ + KIRQL oldlvl; + + DPRINT("IoCancelIrp(Irp %x)\n",Irp); + + IoAcquireCancelSpinLock(&oldlvl); + Irp->Cancel = TRUE; + if (Irp->CancelRoutine == NULL) + { + return(FALSE); + } + Irp->CancelRoutine(Irp->Stack[0].DeviceObject, Irp); + IoReleaseCancelSpinLock(oldlvl); + return(TRUE); +} + +VOID +IoInitCancelHandling(VOID) +{ + KeInitializeSpinLock(&CancelSpinLock); +} + +VOID STDCALL +IoAcquireCancelSpinLock(PKIRQL Irql) +{ + KeAcquireSpinLock(&CancelSpinLock,Irql); +} + +VOID STDCALL +IoReleaseCancelSpinLock(KIRQL Irql) +{ + KeReleaseSpinLock(&CancelSpinLock,Irql); +} + +/* EOF */ diff --git a/ntoskrnl/io/cleanup.c b/ntoskrnl/io/cleanup.c new file mode 100644 index 0000000..c1be188 --- /dev/null +++ b/ntoskrnl/io/cleanup.c @@ -0,0 +1,268 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/cleanup.c + * PURPOSE: IRP cleanup + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 30/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +VOID STDCALL +IopCompleteRequest1(struct _KAPC* Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) +{ + PIRP Irp; + CCHAR PriorityBoost; + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + + DPRINT("IopCompleteRequest1()\n"); + + Irp = (PIRP)(*SystemArgument1); + PriorityBoost = (CCHAR)(LONG)(*SystemArgument2); + + IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation]; + FileObject = IoStack->FileObject; + + (*SystemArgument1) = (PVOID)Irp->UserIosb; + (*SystemArgument2) = (PVOID)Irp->IoStatus.Information; + + if (Irp->UserIosb!=NULL) + { + *Irp->UserIosb=Irp->IoStatus; + } + + if (Irp->UserEvent) + { + KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE); + } + + if (!(Irp->Flags & IRP_PAGING_IO) && FileObject) + { + // if the event is not the one in the file object, it needs dereferenced + if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event) + ObDereferenceObject(Irp->UserEvent); + + if (IoStack->MajorFunction != IRP_MJ_CLOSE) + { + ObDereferenceObject(FileObject); + } + } + + IoFreeIrp(Irp); + +} + +VOID IoDeviceControlCompletion(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PIO_STACK_LOCATION IoStack) +{ + ULONG IoControlCode; + + IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode; + + switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) + { + case METHOD_BUFFERED: + DPRINT ("Using METHOD_BUFFERED!\n"); + + /* copy output buffer back and free it */ + if (Irp->AssociatedIrp.SystemBuffer) + { + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength) + { + RtlCopyMemory(Irp->UserBuffer, + Irp->AssociatedIrp.SystemBuffer, + IoStack->Parameters.DeviceIoControl. + OutputBufferLength); + } + ExFreePool (Irp->AssociatedIrp.SystemBuffer); + } + break; + + case METHOD_IN_DIRECT: + DPRINT ("Using METHOD_IN_DIRECT!\n"); + + /* free input buffer (control buffer) */ + if (Irp->AssociatedIrp.SystemBuffer) + ExFreePool (Irp->AssociatedIrp.SystemBuffer); + + /* free output buffer (data transfer buffer) */ + if (Irp->MdlAddress) + IoFreeMdl (Irp->MdlAddress); + break; + + case METHOD_OUT_DIRECT: + DPRINT ("Using METHOD_OUT_DIRECT!\n"); + + /* free input buffer (control buffer) */ + if (Irp->AssociatedIrp.SystemBuffer) + ExFreePool (Irp->AssociatedIrp.SystemBuffer); + + /* free output buffer (data transfer buffer) */ + if (Irp->MdlAddress) + IoFreeMdl (Irp->MdlAddress); + break; + + case METHOD_NEITHER: + DPRINT ("Using METHOD_NEITHER!\n"); + /* nothing to do */ + break; + } +} + +VOID IoReadWriteCompletion(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PIO_STACK_LOCATION IoStack) +{ + PFILE_OBJECT FileObject; + + FileObject = IoStack->FileObject; + + if (DeviceObject->Flags & DO_BUFFERED_IO) + { + if (IoStack->MajorFunction == IRP_MJ_READ) + { + DPRINT("Copying buffered io back to user\n"); + memcpy(Irp->UserBuffer,Irp->AssociatedIrp.SystemBuffer, + IoStack->Parameters.Read.Length); + } + ExFreePool(Irp->AssociatedIrp.SystemBuffer); + } + if (DeviceObject->Flags & DO_DIRECT_IO) + { + /* FIXME: Is the MDL destroyed on a paging i/o, check all cases. */ + DPRINT("Tearing down MDL\n"); + if (Irp->MdlAddress->MappedSystemVa != NULL) + { + MmUnmapLockedPages(Irp->MdlAddress->MappedSystemVa, + Irp->MdlAddress); + } + MmUnlockPages(Irp->MdlAddress); + ExFreePool(Irp->MdlAddress); + } +} + +VOID IoVolumeInformationCompletion(PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PIO_STACK_LOCATION IoStack) +{ +} + +VOID IoSecondStageCompletion(PIRP Irp, CCHAR PriorityBoost) +/* + * FUNCTION: Performs the second stage of irp completion for read/write irps + * ARGUMENTS: + * Irp = Irp to completion + * FromDevice = True if the operation transfered data from the device + */ +{ + PIO_STACK_LOCATION IoStack; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + + DPRINT("IoSecondStageCompletion(Irp %x, PriorityBoost %d)\n", + Irp, PriorityBoost); + + IoStack = &Irp->Stack[(ULONG)Irp->CurrentLocation]; + FileObject = IoStack->FileObject; + + DeviceObject = IoStack->DeviceObject; + + switch (IoStack->MajorFunction) + { + case IRP_MJ_CREATE: + case IRP_MJ_FLUSH_BUFFERS: + /* NOP */ + break; + + case IRP_MJ_READ: + case IRP_MJ_WRITE: + IoReadWriteCompletion(DeviceObject,Irp,IoStack); + break; + + case IRP_MJ_DEVICE_CONTROL: + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + IoDeviceControlCompletion(DeviceObject, Irp, IoStack); + break; + + case IRP_MJ_QUERY_VOLUME_INFORMATION: + case IRP_MJ_SET_VOLUME_INFORMATION: + IoVolumeInformationCompletion(DeviceObject, Irp, IoStack); + break; + + default: + break; + } + + if (Irp->Overlay.AsynchronousParameters.UserApcRoutine != NULL) + { + PKTHREAD Thread; + PKNORMAL_ROUTINE UserApcRoutine; + PVOID UserApcContext; + + DPRINT("Dispatching APC\n"); + Thread = &Irp->Tail.Overlay.Thread->Tcb; + UserApcRoutine = (PKNORMAL_ROUTINE) + Irp->Overlay.AsynchronousParameters.UserApcRoutine; + UserApcContext = (PVOID) + Irp->Overlay.AsynchronousParameters.UserApcContext; + KeInitializeApc(&Irp->Tail.Apc, + Thread, + 0, + IopCompleteRequest1, + NULL, + UserApcRoutine, + UserMode, + UserApcContext); + KeInsertQueueApc(&Irp->Tail.Apc, + Irp, + (PVOID)(LONG)PriorityBoost, + KernelMode); + return; + } + + DPRINT("Irp->UserIosb %x &Irp->UserIosb %x\n", + Irp->UserIosb, + &Irp->UserIosb); + if (Irp->UserIosb!=NULL) + { + *Irp->UserIosb=Irp->IoStatus; + } + + if (Irp->UserEvent) + { + KeSetEvent(Irp->UserEvent,PriorityBoost,FALSE); + } + + if (!(Irp->Flags & IRP_PAGING_IO) && FileObject) + { + // if the event is not the one in the file object, it needs dereferenced + if (Irp->UserEvent && Irp->UserEvent != &FileObject->Event) + ObDereferenceObject(Irp->UserEvent); + + if (IoStack->MajorFunction != IRP_MJ_CLOSE) + { + ObDereferenceObject(FileObject); + } + } + + IoFreeIrp(Irp); +} diff --git a/ntoskrnl/io/cntrller.c b/ntoskrnl/io/cntrller.c new file mode 100644 index 0000000..3e0893e --- /dev/null +++ b/ntoskrnl/io/cntrller.c @@ -0,0 +1,166 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/cntrller.c + * PURPOSE: Implements the controller object + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_CQE TAG('C', 'Q', 'E', ' ') +#define TAG_CONTROLLER TAG('C', 'N', 'T', 'R') +#define TAG_CONTROLLER_EXTENSION TAG('C', 'E', 'X', 'T') + +/* TYPES ********************************************************************/ + +typedef struct +/* + * PURPOSE: A entry in the queue waiting for a controller object + */ +{ + KDEVICE_QUEUE_ENTRY Entry; + PDEVICE_OBJECT DeviceObject; + PDRIVER_CONTROL ExecutionRoutine; + PVOID Context; +} CONTROLLER_QUEUE_ENTRY, *PCONTROLLER_QUEUE_ENTRY; + +/* FUNCTIONS *****************************************************************/ + +VOID +STDCALL +IoAllocateController(PCONTROLLER_OBJECT ControllerObject, + PDEVICE_OBJECT DeviceObject, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context) +/* + * FUNCTION: Sets up a call to a driver-supplied ControllerControl routine + * as soon as the device controller, represented by the given controller + * object, is available to carry out an I/O operation for the target device, + * represented by the given device object. + * ARGUMENTS: + * ControllerObject = Driver created controller object + * DeviceObject = Target device for the current irp + * ExecutionRoutine = Routine to be called when the device is available + * Context = Driver supplied context to be passed on to the above routine + * NOTE: Is the below implementation correct. + */ +{ + PCONTROLLER_QUEUE_ENTRY entry; + IO_ALLOCATION_ACTION Result; + + assert(KeGetCurrentIrql() == DISPATCH_LEVEL); + + entry = + ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_QUEUE_ENTRY), + TAG_CQE); + assert(entry!=NULL); + + entry->DeviceObject = DeviceObject; + entry->ExecutionRoutine = ExecutionRoutine; + entry->Context = Context; + + if (KeInsertDeviceQueue(&ControllerObject->DeviceWaitQueue,&entry->Entry)) + { + return; + } + Result = ExecutionRoutine(DeviceObject,DeviceObject->CurrentIrp, + NULL,Context); + if (Result == DeallocateObject) + { + IoFreeController(ControllerObject); + } + ExFreePool(entry); +} + +PCONTROLLER_OBJECT +STDCALL +IoCreateController(ULONG Size) +/* + * FUNCTION: Allocates memory and initializes a controller object + * ARGUMENTS: + * Size = Size (in bytes) to be allocated for the controller extension + * RETURNS: A pointer to the created object + */ +{ + PCONTROLLER_OBJECT controller; + + assert_irql(PASSIVE_LEVEL); + + controller = + ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROLLER_OBJECT), + TAG_CONTROLLER); + if (controller==NULL) + { + return(NULL); + } + + controller->ControllerExtension = + ExAllocatePoolWithTag(NonPagedPool, Size, TAG_CONTROLLER_EXTENSION); + if (controller->ControllerExtension==NULL) + { + ExFreePool(controller); + return(NULL); + } + + KeInitializeDeviceQueue(&controller->DeviceWaitQueue); + return(controller); +} + +VOID +STDCALL +IoDeleteController(PCONTROLLER_OBJECT ControllerObject) +/* + * FUNCTION: Removes a given controller object from the system + * ARGUMENTS: + * ControllerObject = Controller object to be released + */ +{ + assert_irql(PASSIVE_LEVEL); + + ExFreePool(ControllerObject->ControllerExtension); + ExFreePool(ControllerObject); +} + +VOID +STDCALL +IoFreeController(PCONTROLLER_OBJECT ControllerObject) +/* + * FUNCTION: Releases a previously allocated controller object when a + * device has finished an I/O request + * ARGUMENTS: + * ControllerObject = Controller object to be released + */ +{ + PKDEVICE_QUEUE_ENTRY QEntry; + CONTROLLER_QUEUE_ENTRY* Entry; + IO_ALLOCATION_ACTION Result; + + do + { + QEntry = KeRemoveDeviceQueue(&ControllerObject->DeviceWaitQueue); + Entry = CONTAINING_RECORD(QEntry,CONTROLLER_QUEUE_ENTRY,Entry); + if (QEntry==NULL) + { + return; + } + Result = Entry->ExecutionRoutine(Entry->DeviceObject, + Entry->DeviceObject->CurrentIrp, + NULL, + Entry->Context); + ExFreePool(Entry); + } while (Result == DeallocateObject); +} + + +/* EOF */ diff --git a/ntoskrnl/io/create.c b/ntoskrnl/io/create.c new file mode 100644 index 0000000..e2a0400 --- /dev/null +++ b/ntoskrnl/io/create.c @@ -0,0 +1,554 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/create.c + * PURPOSE: Handling file create/open apis + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 24/05/98: Created + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_FILE_NAME TAG('F', 'N', 'A', 'M') + +/* FUNCTIONS *************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * NtDeleteFile@4 + * + * DESCRIPTION + * + * ARGUMENTS + * ObjectAttributes + * ? + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + UNIMPLEMENTED; +} + + +/********************************************************************** + * NAME INTERNAL + * IopCreateFile + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +IopCreateFile(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Parent; + PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody; + NTSTATUS Status; + + DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, + Parent, + RemainingPath); + + if (NULL == DeviceObject) + { + /* This is probably an attempt to create a meta fileobject (eg. for FAT) + for the cache manager, so return STATUS_SUCCESS */ + DPRINT("DeviceObject was NULL\n"); + return(STATUS_SUCCESS); + } + + if (IoDeviceObjectType != BODY_TO_HEADER(Parent)->ObjectType) + { + CPRINT("Parent is a %S which is not a device type\n", + BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer); + return(STATUS_UNSUCCESSFUL); + } + + Status = ObReferenceObjectByPointer(DeviceObject, + STANDARD_RIGHTS_REQUIRED, + IoDeviceObjectType, + UserMode); + if (!NT_SUCCESS(Status)) + { + CPRINT("Failed to reference device object %x\n", DeviceObject); + return(Status); + } + + DeviceObject = IoGetAttachedDevice(DeviceObject); + DPRINT("DeviceObject %x\n", DeviceObject); + + if (NULL == RemainingPath) + { + FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN; + FileObject->FileName.Buffer = 0; + FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0; + } + else + { + if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM) + && (DeviceObject->DeviceType != FILE_DEVICE_DISK) + && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) + && (DeviceObject->DeviceType != FILE_DEVICE_TAPE) + && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK) + && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE) + && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT)) + { + CPRINT("Device was wrong type\n"); + return(STATUS_UNSUCCESSFUL); + } + + if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK + && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE) + && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT)) + { + if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED)) + { + DPRINT("Mount the logical volume\n"); + Status = IoMountVolume(DeviceObject, FALSE); + DPRINT("Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + CPRINT("Failed to mount logical volume (Status %x)\n", + Status); + return(Status); + } + } + DeviceObject = DeviceObject->Vpb->DeviceObject; + DPRINT("FsDeviceObject %lx\n", DeviceObject); + } + RtlCreateUnicodeString(&(FileObject->FileName), + RemainingPath); + } + + DPRINT("FileObject->FileName %wZ\n", + &FileObject->FileName); + FileObject->DeviceObject = DeviceObject; + DPRINT("FileObject %x DeviceObject %x\n", + FileObject, + DeviceObject); + FileObject->Vpb = DeviceObject->Vpb; + FileObject->Type = InternalFileType; + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * IoCreateStreamFileObject@8 + * + * DESCRIPTION + * + * ARGUMENTS + * FileObject + * ? + * + * DeviceObject + * ? + * + * RETURN VALUE + * + * NOTE + * + * REVISIONS + * + */ +PFILE_OBJECT STDCALL +IoCreateStreamFileObject(PFILE_OBJECT FileObject, + PDEVICE_OBJECT DeviceObject) +{ + HANDLE FileHandle; + PFILE_OBJECT CreatedFileObject; + NTSTATUS Status; + + DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n", + FileObject, DeviceObject); + + assert_irql(PASSIVE_LEVEL); + + Status = ObCreateObject(&FileHandle, + STANDARD_RIGHTS_REQUIRED, + NULL, + IoFileObjectType, + (PVOID*)&CreatedFileObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not create FileObject\n"); + return (NULL); + } + + if (FileObject != NULL) + { + DeviceObject = FileObject->DeviceObject; + } + DeviceObject = IoGetAttachedDevice(DeviceObject); + + DPRINT("DeviceObject %x\n", DeviceObject); + + CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject; + CreatedFileObject->Vpb = DeviceObject->Vpb; + CreatedFileObject->Type = InternalFileType; + CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN; + + // shouldn't we initialize the lock event, and several other things here too? + KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE); + + ZwClose(FileHandle); + + return(CreatedFileObject); +} + + +/********************************************************************** + * NAME EXPORTED + * IoCreateFile@56 + * + * DESCRIPTION + * Either causes a new file or directory to be created, or it + * opens an existing file, device, directory or volume, giving + * the caller a handle for the file object. This handle can be + * used by subsequent calls to manipulate data within the file + * or the file object's state of attributes. + * + * ARGUMENTS + * FileHandle (OUT) + * Points to a variable which receives the file handle + * on return; + * + * DesiredAccess + * Desired access to the file; + * + * ObjectAttributes + * Structure describing the file; + * + * IoStatusBlock (OUT) + * Receives information about the operation on return; + * + * AllocationSize [OPTIONAL] + * Initial size of the file in bytes; + * + * FileAttributes + * Attributes to create the file with; + * + * ShareAccess + * Type of shared access the caller would like to the + * file; + * + * CreateDisposition + * Specifies what to do, depending on whether the + * file already exists; + * + * CreateOptions + * Options for creating a new file; + * + * EaBuffer [OPTIONAL] + * Undocumented; + * + * EaLength + * Undocumented; + * + * CreateFileType + * Type of file (normal, named pipe, mailslot) to create; + * + * ExtraCreateParameters [OPTIONAL] + * Additional creation data for named pipe and mailsots; + * + * Options + * Undocumented. + * + * RETURN VALUE + * Status + * + * NOTE + * Prototype taken from Bo Branten's ntifs.h v15. + * Description taken from old NtCreateFile's which is + * now a wrapper of this call. + * + * REVISIONS + * + */ +NTSTATUS STDCALL +IoCreateFile(OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength, + IN CREATE_FILE_TYPE CreateFileType, + IN PVOID ExtraCreateParameters OPTIONAL, + IN ULONG Options) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + PIRP Irp; + PIO_STACK_LOCATION StackLoc; + IO_STATUS_BLOCK IoSB; + IO_SECURITY_CONTEXT SecurityContext; + + DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, " + "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n", + FileHandle,DesiredAccess,ObjectAttributes, + ObjectAttributes->ObjectName->Buffer); + + assert_irql(PASSIVE_LEVEL); + + *FileHandle = 0; + + Status = ObCreateObject(FileHandle, + DesiredAccess, + ObjectAttributes, + IoFileObjectType, + (PVOID*)&FileObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObCreateObject() failed! (Status %lx)\n", Status); + return(Status); + } + if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT) + { + FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO); + } + if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT) + { + FileObject->Flags |= FO_SYNCHRONOUS_IO; + } + + if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING ) + FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING; + + SecurityContext.SecurityQos = NULL; /* ?? */ + SecurityContext.AccessState = NULL; /* ?? */ + SecurityContext.DesiredAccess = DesiredAccess; + SecurityContext.FullCreateOptions = 0; /* ?? */ + + KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE); + KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE); + + DPRINT("FileObject %x\n", FileObject); + DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject); + /* + * Create a new IRP to hand to + * the FS driver: this may fail + * due to resource shortage. + */ + Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE); + if (Irp == NULL) + { + ZwClose(*FileHandle); + return (STATUS_UNSUCCESSFUL); + } + + Irp->UserIosb = &IoSB; //return iostatus + Irp->AssociatedIrp.SystemBuffer = EaBuffer; + Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->UserEvent = &FileObject->Event; + if (AllocationSize) + { + Irp->Overlay.AllocationSize = *AllocationSize; + } + + /* + * Get the stack location for the new + * IRP and prepare it. + */ + StackLoc = IoGetNextIrpStackLocation(Irp); + switch (CreateFileType) + { + default: + case CreateFileTypeNone: + StackLoc->MajorFunction = IRP_MJ_CREATE; + break; + + case CreateFileTypeNamedPipe: + StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE; + break; + + case CreateFileTypeMailslot: + StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT; + break; + } + StackLoc->MinorFunction = 0; + StackLoc->Flags = Options; + StackLoc->Control = 0; + StackLoc->DeviceObject = FileObject->DeviceObject; + StackLoc->FileObject = FileObject; + StackLoc->Parameters.Create.SecurityContext = &SecurityContext; + StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS); + StackLoc->Parameters.Create.Options |= (CreateDisposition << 24); + StackLoc->Parameters.Create.FileAttributes = FileAttributes; + StackLoc->Parameters.Create.ShareAccess = ShareAccess; + StackLoc->Parameters.Create.EaLength = EaLength; + + /* + * Now call the driver and + * possibly wait if it can + * not complete the request + * immediately. + */ + Status = IofCallDriver(FileObject->DeviceObject, Irp ); + + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoSB.Status; + } + if (!NT_SUCCESS(Status)) + { + DPRINT("Failing create request with status %x\n", Status); + ZwClose(*FileHandle); + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + assert_irql(PASSIVE_LEVEL); + + DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle)); + + return (Status); +} + + +/********************************************************************** + * NAME EXPORTED + * NtCreateFile@44 + * + * DESCRIPTION + * Entry point to call IoCreateFile with + * default parameters. + * + * ARGUMENTS + * See IoCreateFile. + * + * RETURN VALUE + * See IoCreateFile. + * + * REVISIONS + * 2000-03-25 (ea) + * Code originally in NtCreateFile moved in IoCreateFile. + */ +NTSTATUS STDCALL +NtCreateFile(PHANDLE FileHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + PLARGE_INTEGER AllocateSize, + ULONG FileAttributes, + ULONG ShareAccess, + ULONG CreateDisposition, + ULONG CreateOptions, + PVOID EaBuffer, + ULONG EaLength) +{ + return IoCreateFile(FileHandle, + DesiredAccess, + ObjectAttributes, + IoStatusBlock, + AllocateSize, + FileAttributes, + ShareAccess, + CreateDisposition, + CreateOptions, + EaBuffer, + EaLength, + CreateFileTypeNone, + NULL, + 0); +} + + +/********************************************************************** + * NAME EXPORTED + * NtOpenFile@24 + * + * DESCRIPTION + * Opens an existing file (simpler than NtCreateFile). + * + * ARGUMENTS + * FileHandle (OUT) + * Variable that receives the file handle on return; + * + * DesiredAccess + * Access desired by the caller to the file; + * + * ObjectAttributes + * Structue describing the file to be opened; + * + * IoStatusBlock (OUT) + * Receives details about the result of the + * operation; + * + * ShareAccess + * Type of shared access the caller requires; + * + * OpenOptions + * Options for the file open. + * + * RETURN VALUE + * Status. + * + * NOTE + * Undocumented. + */ +NTSTATUS STDCALL +NtOpenFile(PHANDLE FileHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG ShareAccess, + ULONG OpenOptions) +{ + return IoCreateFile(FileHandle, + DesiredAccess, + ObjectAttributes, + IoStatusBlock, + NULL, + 0, + ShareAccess, + FILE_OPEN, + OpenOptions, + NULL, + 0, + CreateFileTypeNone, + NULL, + 0); +} + +/* EOF */ diff --git a/ntoskrnl/io/device.c b/ntoskrnl/io/device.c new file mode 100644 index 0000000..a2ebf77 --- /dev/null +++ b/ntoskrnl/io/device.c @@ -0,0 +1,737 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/device.c + * PURPOSE: Manage devices + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 15/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NDEBUG +//#define DBG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_DRIVER TAG('D', 'R', 'V', 'R') +#define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E') +#define TAG_DEVICE_EXTENSION TAG('D', 'E', 'X', 'T') + +#define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +IoAttachDeviceByPointer(IN PDEVICE_OBJECT SourceDevice, + IN PDEVICE_OBJECT TargetDevice) +{ + PDEVICE_OBJECT AttachedDevice; + + DPRINT("IoAttachDeviceByPointer(SourceDevice %x, TargetDevice %x)\n", + SourceDevice, + TargetDevice); + + AttachedDevice = IoAttachDeviceToDeviceStack (SourceDevice, + TargetDevice); + if (AttachedDevice == NULL) + return STATUS_NO_SUCH_DEVICE; + + return STATUS_SUCCESS; +} + + +VOID STDCALL +IoDeleteDevice(PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_OBJECT Previous; + + if (DeviceObject->Flags & DO_SHUTDOWN_REGISTERED) + IoUnregisterShutdownNotification(DeviceObject); + + /* remove the timer if it exists */ + if (DeviceObject->Timer) + { + IoStopTimer(DeviceObject); + ExFreePool(DeviceObject->Timer); + } + + /* free device extension */ + if (DeviceObject->DeviceObjectExtension) + ExFreePool (DeviceObject->DeviceObjectExtension); + + /* remove device from driver device list */ + Previous = DeviceObject->DriverObject->DeviceObject; + if (Previous == DeviceObject) + { + DeviceObject->DriverObject->DeviceObject = DeviceObject->NextDevice; + } + else + { + while (Previous->NextDevice != DeviceObject) + Previous = Previous->NextDevice; + Previous->NextDevice = DeviceObject->NextDevice; + } + + ObDereferenceObject (DeviceObject); +} + + +PDEVICE_OBJECT +STDCALL +IoGetRelatedDeviceObject ( + IN PFILE_OBJECT FileObject + ) +{ + return (FileObject->DeviceObject); +} + + +NTSTATUS +STDCALL +IoGetDeviceObjectPointer ( + IN PUNICODE_STRING ObjectName, + IN ACCESS_MASK DesiredAccess, + OUT PFILE_OBJECT * FileObject, + OUT PDEVICE_OBJECT * DeviceObject) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK StatusBlock; + PFILE_OBJECT LocalFileObject; + HANDLE FileHandle; + NTSTATUS Status; + + DPRINT("IoGetDeviceObjectPointer(ObjectName %wZ, DesiredAccess %x, FileObject %p DeviceObject %p)\n", + ObjectName, + DesiredAccess, + FileObject, + DeviceObject); + + InitializeObjectAttributes (&ObjectAttributes, + ObjectName, + 0, + NULL, + NULL); + + Status = NtOpenFile (&FileHandle, + DesiredAccess, + &ObjectAttributes, + &StatusBlock, + 0, + FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS(Status)) + return Status; + + Status = ObReferenceObjectByHandle (FileHandle, + 0, + IoFileObjectType, + KernelMode, + (PVOID*)&LocalFileObject, + NULL); + if (NT_SUCCESS(Status)) + { + *DeviceObject = IoGetRelatedDeviceObject (LocalFileObject); + *FileObject = LocalFileObject; + } + NtClose (FileHandle); + + return Status; +} + + +VOID +STDCALL +IoDetachDevice(PDEVICE_OBJECT TargetDevice) +{ +// UNIMPLEMENTED; + DPRINT("IoDetachDevice(TargetDevice %x) - UNIMPLEMENTED\n", TargetDevice); +} + + +PDEVICE_OBJECT +STDCALL +IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_OBJECT Current = DeviceObject; + +// DPRINT("IoGetAttachedDevice(DeviceObject %x)\n",DeviceObject); + + while (Current->AttachedDevice!=NULL) + { + Current = Current->AttachedDevice; +// DPRINT("Current %x\n",Current); + } + +// DPRINT("IoGetAttachedDevice() = %x\n",DeviceObject); + return(Current); +} + +PDEVICE_OBJECT +STDCALL +IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_OBJECT Current = DeviceObject; + + while (Current->AttachedDevice!=NULL) + { + Current = Current->AttachedDevice; + } + + ObReferenceObject(Current); + return(Current); +} + +PDEVICE_OBJECT STDCALL +IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice) +{ + PDEVICE_OBJECT AttachedDevice; + + DPRINT("IoAttachDeviceToDeviceStack(SourceDevice %x, TargetDevice %x)\n", + SourceDevice,TargetDevice); + + AttachedDevice = IoGetAttachedDevice(TargetDevice); + AttachedDevice->AttachedDevice = SourceDevice; + SourceDevice->AttachedDevice = NULL; + SourceDevice->StackSize = AttachedDevice->StackSize + 1; + SourceDevice->Vpb = AttachedDevice->Vpb; + return(AttachedDevice); +} + +VOID STDCALL +IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject, + PDRIVER_REINITIALIZE ReinitRoutine, + PVOID Context) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +IopDefaultDispatchFunction(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS +IopCreateDriverObject(PDRIVER_OBJECT *DriverObject, + PUNICODE_STRING ServiceName, + BOOLEAN FileSystem) +{ + PDRIVER_OBJECT Object; + HANDLE DriverHandle = 0; + ULONG i; + WCHAR NameBuffer[MAX_PATH]; + UNICODE_STRING DriverName; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + DPRINT("IopCreateDriverObject(%p '%wZ' %x)\n", DriverObject, ServiceName, FileSystem); + + *DriverObject = NULL; + + /* Create ModuleName string */ + if (ServiceName != NULL) + { + if (FileSystem == TRUE) + wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME); + else + wcscpy(NameBuffer, DRIVER_ROOT_NAME); + wcscat(NameBuffer, ServiceName->Buffer); + + RtlInitUnicodeString(&DriverName, + NameBuffer); + DPRINT("Driver name: '%wZ'\n", &DriverName); + } + + /* Initialize ObjectAttributes for ModuleObject */ + InitializeObjectAttributes(&ObjectAttributes, + (ServiceName != NULL)? &DriverName : NULL, + OBJ_PERMANENT, + NULL, + NULL); + + /* Create module object */ + Status = ObCreateObject(&DriverHandle, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + IoDriverObjectType, + (PVOID*)&Object); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + NtClose(DriverHandle); + + /* Create driver extension */ + Object->DriverExtension = (PDRIVER_EXTENSION) + ExAllocatePoolWithTag(NonPagedPool, + sizeof(DRIVER_EXTENSION), + TAG_DRIVER_EXTENSION); + if (Object->DriverExtension == NULL) + { + ExFreePool(Object); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION)); + + Object->Type = InternalDriverType; + + for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++) + { + Object->MajorFunction[i] = (PDRIVER_DISPATCH) IopDefaultDispatchFunction; + } + + *DriverObject = Object; + + return STATUS_SUCCESS; +} + +NTSTATUS +IopAttachFilterDrivers(PDEVICE_NODE DeviceNode, + BOOLEAN Lower) +{ + return STATUS_SUCCESS; +} + +NTSTATUS +IopInitializeDevice(PDEVICE_NODE DeviceNode, + BOOLEAN BootDriversOnly) +{ + IO_STATUS_BLOCK IoStatusBlock; + PDRIVER_OBJECT DriverObject; + IO_STACK_LOCATION Stack; + PDEVICE_OBJECT Fdo; + NTSTATUS Status; + + DriverObject = DeviceNode->DriverObject; + + if (DriverObject->DriverExtension->AddDevice) + { + /* This is a Plug and Play driver */ + DPRINT("Plug and Play driver found\n"); + + assert(DeviceNode->Pdo); + + DPRINT("Calling driver AddDevice entrypoint at %08lx\n", + DriverObject->DriverExtension->AddDevice); + Status = DriverObject->DriverExtension->AddDevice( + DriverObject, DeviceNode->Pdo); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); + + DPRINT("Sending IRP_MN_START_DEVICE to driver\n"); + + Fdo = IoGetAttachedDeviceReference(DeviceNode->Pdo); + + if (Fdo == DeviceNode->Pdo) + { + /* FIXME: What do we do? Unload the driver or just disable the device? */ + DbgPrint("An FDO was not attached\n"); + KeBugCheck(0); + } + + /* FIXME: Put some resources in the IRP for the device */ + Stack.Parameters.StartDevice.AllocatedResources = NULL; + Stack.Parameters.StartDevice.AllocatedResourcesTranslated = NULL; + + Status = IopInitiatePnpIrp( + Fdo, + &IoStatusBlock, + IRP_MN_START_DEVICE, + &Stack); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopInitiatePnpIrp() failed\n"); + ObDereferenceObject(Fdo); + return(Status); + } + + if (Fdo->DeviceType == FILE_DEVICE_BUS_EXTENDER) + { + DPRINT("Bus extender found\n"); + + Status = IopInterrogateBusExtender( + DeviceNode, Fdo, BootDriversOnly); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Fdo); + return(Status); + } + } + else if (Fdo->DeviceType == FILE_DEVICE_ACPI) + { +#ifdef ACPI + static BOOLEAN SystemPowerDeviceNodeCreated = FALSE; + + /* There can be only one system power device */ + if (!SystemPowerDeviceNodeCreated) + { + PopSystemPowerDeviceNode = DeviceNode; + SystemPowerDeviceNodeCreated = TRUE; + } +#endif /* ACPI */ + } + ObDereferenceObject(Fdo); + } + + return STATUS_SUCCESS; +} + +NTSTATUS +IopInitializeService( + PDEVICE_NODE DeviceNode, + PUNICODE_STRING ImagePath) +{ + PMODULE_OBJECT ModuleObject; + NTSTATUS Status; + + ModuleObject = LdrGetModuleObject(&DeviceNode->ServiceName); + if (ModuleObject == NULL) + { + /* The module is currently not loaded, so load it now */ + + Status = LdrLoadModule(ImagePath, &ModuleObject); + if (!NT_SUCCESS(Status)) + { + /* FIXME: Log the error */ + CPRINT("Driver load failed\n"); + return(Status); + } + + Status = IopInitializeDriver(ModuleObject->EntryPoint, DeviceNode, FALSE); + if (!NT_SUCCESS(Status)) + { + LdrUnloadModule(ModuleObject); + + /* FIXME: Log the error */ + CPRINT("A driver failed to initialize\n"); + return(Status); + } + } + + Status = IopInitializeDevice(DeviceNode, TRUE); + + return(Status); +} + +NTSTATUS +IopInitializeDeviceNodeService(PDEVICE_NODE DeviceNode) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + UNICODE_STRING ImagePath; + HANDLE KeyHandle; + NTSTATUS Status; + + Status = RtlpGetRegistryHandle( + RTL_REGISTRY_SERVICES, + DeviceNode->ServiceName.Buffer, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); + return(Status); + } + + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + + RtlInitUnicodeString(&ImagePath, NULL); + + QueryTable[0].Name = L"ImagePath"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &ImagePath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + NtClose(KeyHandle); + + DPRINT("RtlQueryRegistryValues() returned status %x\n", Status); + + if (NT_SUCCESS(Status)) + { + DPRINT("Got ImagePath %S\n", ImagePath.Buffer); + + Status = IopInitializeService(DeviceNode, &ImagePath); + + RtlFreeUnicodeString(&ImagePath); + } + + return(Status); +} + +NTSTATUS +IopInitializeDriver(PDRIVER_INITIALIZE DriverEntry, + PDEVICE_NODE DeviceNode, + BOOLEAN FileSystemDriver) +/* + * FUNCTION: Called to initalize a loaded driver + * ARGUMENTS: + * DriverEntry = Pointer to driver entry routine + * DeviceNode = Pointer to device node + */ +{ + WCHAR RegistryKeyBuffer[MAX_PATH]; + PDRIVER_OBJECT DriverObject; + UNICODE_STRING RegistryKey; + NTSTATUS Status; + + DPRINT("IopInitializeDriver(DriverEntry %08lx, DeviceNode %08lx)\n", + DriverEntry, DeviceNode); + + Status = IopCreateDriverObject(&DriverObject, + &DeviceNode->ServiceName, + FileSystemDriver); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DeviceNode->DriverObject = DriverObject; + + if (DeviceNode->ServiceName.Buffer) + { + wcscpy(RegistryKeyBuffer, DRIVER_REGISTRY_KEY_BASENAME); + wcscat(RegistryKeyBuffer, DeviceNode->ServiceName.Buffer); + RtlInitUnicodeString(&RegistryKey, RegistryKeyBuffer); + } + else + { + RtlInitUnicodeString(&RegistryKey, NULL); + } + + DPRINT("RegistryKey: %wZ\n", &RegistryKey); + DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry); + + Status = DriverEntry(DriverObject, &RegistryKey); + if (!NT_SUCCESS(Status)) + { + DeviceNode->DriverObject = NULL; + ExFreePool(DriverObject->DriverExtension); + ObMakeTemporaryObject(DriverObject); + ObDereferenceObject(DriverObject); + return(Status); + } + + Status = IopInitializeDevice(DeviceNode, TRUE); + + return(Status); +} + + +NTSTATUS STDCALL +IoAttachDevice(PDEVICE_OBJECT SourceDevice, + PUNICODE_STRING TargetDevice, + PDEVICE_OBJECT* AttachedDevice) +/* + * FUNCTION: Layers a device over the highest device in a device stack + * ARGUMENTS: + * SourceDevice = Device to attached + * TargetDevice = Name of the target device + * AttachedDevice (OUT) = Caller storage for the device attached to + */ +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +IopCreateDevice(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + + DPRINT("IopCreateDevice(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + DEVICE_TYPE DeviceType, + ULONG DeviceCharacteristics, + BOOLEAN Exclusive, + PDEVICE_OBJECT* DeviceObject) +/* + * FUNCTION: Allocates memory for and intializes a device object for use for + * a driver + * ARGUMENTS: + * DriverObject : Driver object passed by iomgr when the driver was + * loaded + * DeviceExtensionSize : Number of bytes for the device extension + * DeviceName : Unicode name of device + * DeviceType : Device type + * DeviceCharacteristics : Bit mask of device characteristics + * Exclusive : True if only one thread can access the device at a + * time + * RETURNS: + * Success or failure + * DeviceObject : Contains a pointer to allocated device object + * if the call succeeded + * NOTES: See the DDK documentation for more information + */ +{ + PDEVICE_OBJECT CreatedDeviceObject; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE DeviceHandle; + NTSTATUS Status; + + assert_irql(PASSIVE_LEVEL); + + if (DeviceName != NULL) + { + DPRINT("IoCreateDevice(DriverObject %x, DeviceName %S)\n",DriverObject, + DeviceName->Buffer); + } + else + { + DPRINT("IoCreateDevice(DriverObject %x)\n",DriverObject); + } + + if (DeviceName != NULL) + { + InitializeObjectAttributes(&ObjectAttributes,DeviceName,0,NULL,NULL); + Status = ObCreateObject(&DeviceHandle, + 0, + &ObjectAttributes, + IoDeviceObjectType, + (PVOID*)&CreatedDeviceObject); + } + else + { + Status = ObCreateObject(&DeviceHandle, + 0, + NULL, + IoDeviceObjectType, + (PVOID*)&CreatedDeviceObject); + } + + *DeviceObject = NULL; + + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateDevice() ObCreateObject failed, status: 0x%08X\n", Status); + return(Status); + } + + if (DriverObject->DeviceObject == NULL) + { + DriverObject->DeviceObject = CreatedDeviceObject; + CreatedDeviceObject->NextDevice = NULL; + } + else + { + CreatedDeviceObject->NextDevice = DriverObject->DeviceObject; + DriverObject->DeviceObject = CreatedDeviceObject; + } + + CreatedDeviceObject->Type = DeviceType; + CreatedDeviceObject->DriverObject = DriverObject; + CreatedDeviceObject->CurrentIrp = NULL; + CreatedDeviceObject->Flags = 0; + + CreatedDeviceObject->DeviceExtension = + ExAllocatePoolWithTag(NonPagedPool, DeviceExtensionSize, + TAG_DEVICE_EXTENSION); + if (DeviceExtensionSize > 0 && CreatedDeviceObject->DeviceExtension == NULL) + { + ExFreePool(CreatedDeviceObject); + DPRINT("IoCreateDevice() ExAllocatePoolWithTag failed, returning: 0x%08X\n", STATUS_INSUFFICIENT_RESOURCES); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + if (DeviceExtensionSize > 0) + { + RtlZeroMemory(CreatedDeviceObject->DeviceExtension, + DeviceExtensionSize); + } + + CreatedDeviceObject->AttachedDevice = NULL; + CreatedDeviceObject->DeviceType = DeviceType; + CreatedDeviceObject->StackSize = 1; + CreatedDeviceObject->AlignmentRequirement = 1; + KeInitializeDeviceQueue(&CreatedDeviceObject->DeviceQueue); + + KeInitializeEvent(&CreatedDeviceObject->DeviceLock, + SynchronizationEvent, + TRUE); + + /* FIXME: Do we need to add network drives too?! */ + if (CreatedDeviceObject->DeviceType == FILE_DEVICE_DISK || + CreatedDeviceObject->DeviceType == FILE_DEVICE_CD_ROM || + CreatedDeviceObject->DeviceType == FILE_DEVICE_TAPE) + { + IoAttachVpb(CreatedDeviceObject); + } + + *DeviceObject = CreatedDeviceObject; + + return(STATUS_SUCCESS); +} + + +NTSTATUS +STDCALL +IoOpenDeviceInstanceKey ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4 + ) +{ + UNIMPLEMENTED; + return(STATUS_NOT_IMPLEMENTED); +} + + +DWORD +STDCALL +IoQueryDeviceEnumInfo ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + UNIMPLEMENTED; + return 0; +} + + +/* EOF */ diff --git a/ntoskrnl/io/dir.c b/ntoskrnl/io/dir.c new file mode 100644 index 0000000..174eb03 --- /dev/null +++ b/ntoskrnl/io/dir.c @@ -0,0 +1,173 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/dir.c + * PURPOSE: Directory functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + + + +NTSTATUS +STDCALL +NtNotifyChangeDirectoryFile ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG BufferSize, + IN ULONG CompletionFilter, + IN BOOLEAN WatchTree + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtQueryDirectoryFile( + IN HANDLE FileHandle, + IN HANDLE PEvent OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FileInformation, + IN ULONG Length, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN BOOLEAN ReturnSingleEntry, + IN PUNICODE_STRING FileName OPTIONAL, + IN BOOLEAN RestartScan + ) +/* + * FUNCTION: Queries a directory file. + * ARGUMENTS: + * FileHandle = Handle to a directory file + * EventHandle = Handle to the event signaled on completion + * ApcRoutine = Asynchroneous procedure callback, called on completion + * ApcContext = Argument to the apc. + * IoStatusBlock = Caller supplies storage for extended status information. + * FileInformation = Caller supplies storage for the resulting information. + * + * FileNameInformation FILE_NAMES_INFORMATION + * FileDirectoryInformation FILE_DIRECTORY_INFORMATION + * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION + * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION + * + * Length = Size of the storage supplied + * FileInformationClass = Indicates the type of information requested. + * ReturnSingleEntry = Specify true if caller only requests the first + * directory found. + * FileName = Initial directory name to query, that may contain wild + * cards. + * RestartScan = Number of times the action should be repeated + * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES, + * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW, + * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ] + */ +{ + PIRP Irp; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + NTSTATUS Status; + PIO_STACK_LOCATION IoStack; + IO_STATUS_BLOCK IoSB; + + DPRINT("NtQueryDirectoryFile()\n"); + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_LIST_DIRECTORY, + IoFileObjectType, + UserMode, + (PVOID *)&FileObject, + NULL); + + if (Status != STATUS_SUCCESS) + { + ObDereferenceObject(FileObject); + return(Status); + } + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + if (Irp==NULL) + { + ObDereferenceObject(FileObject); + return STATUS_UNSUCCESSFUL; + } + + + Irp->UserIosb = &IoSB; + Irp->UserEvent = &FileObject->Event; + KeResetEvent( &FileObject->Event ); + Irp->UserBuffer=FileInformation; + + IoStack = IoGetNextIrpStackLocation(Irp); + + IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; + IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY; + IoStack->Flags = 0; + IoStack->Control = 0; + IoStack->DeviceObject = DeviceObject; + IoStack->FileObject = FileObject; + + if (RestartScan) + { + IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN; + } + if (ReturnSingleEntry) + { + IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY; + } + if (((PFILE_DIRECTORY_INFORMATION)FileInformation)->FileIndex != 0) + { + IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED; + } + + IoStack->Parameters.QueryDirectory.FileInformationClass = + FileInformationClass; + IoStack->Parameters.QueryDirectory.FileName = FileName; + IoStack->Parameters.QueryDirectory.Length = Length; + + Status = IoCallDriver(FileObject->DeviceObject,Irp); + if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO)) + { + if (FileObject->Flags & FO_ALERTABLE_IO) + { + KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,TRUE,NULL); + } + else + { + KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,FALSE,NULL); + } + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + return(Status); +} + +NTSTATUS STDCALL NtQueryOleDirectoryFile(VOID) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/io/driver.c b/ntoskrnl/io/driver.c new file mode 100644 index 0000000..7db3e0d --- /dev/null +++ b/ntoskrnl/io/driver.c @@ -0,0 +1,605 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/driver.c + * PURPOSE: Manage devices + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 15/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NDEBUG +#include + + +typedef struct _SERVICE_GROUP +{ + LIST_ENTRY GroupListEntry; + UNICODE_STRING GroupName; + + BOOLEAN ServicesRunning; + +} SERVICE_GROUP, *PSERVICE_GROUP; + + +typedef struct _SERVICE +{ + LIST_ENTRY ServiceListEntry; + UNICODE_STRING ServiceName; + UNICODE_STRING RegistryPath; + UNICODE_STRING ServiceGroup; + UNICODE_STRING ImagePath; + + ULONG Start; + ULONG Type; + ULONG ErrorControl; + ULONG Tag; + + BOOLEAN ServiceRunning; // needed ?? + +} SERVICE, *PSERVICE; + + +/* GLOBALS *******************************************************************/ + +static LIST_ENTRY GroupListHead = {NULL, NULL}; +static LIST_ENTRY ServiceListHead = {NULL, NULL}; + +POBJECT_TYPE EXPORTED IoDriverObjectType = NULL; + +#define TAG_DRIVER TAG('D', 'R', 'V', 'R') +#define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E') + + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +IopCreateDriver(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, + Parent, + RemainingPath); + if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID +IopInitDriverImplementation(VOID) +{ + /* Register the process object type */ + IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R'); + IoDriverObjectType->TotalObjects = 0; + IoDriverObjectType->TotalHandles = 0; + IoDriverObjectType->MaxObjects = ULONG_MAX; + IoDriverObjectType->MaxHandles = ULONG_MAX; + IoDriverObjectType->PagedPoolCharge = 0; + IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT); + IoDriverObjectType->Dump = NULL; + IoDriverObjectType->Open = NULL; + IoDriverObjectType->Close = NULL; + IoDriverObjectType->Delete = NULL; + IoDriverObjectType->Parse = NULL; + IoDriverObjectType->Security = NULL; + IoDriverObjectType->QueryName = NULL; + IoDriverObjectType->OkayToClose = NULL; + IoDriverObjectType->Create = IopCreateDriver; + IoDriverObjectType->DuplicationNotify = NULL; + RtlInitUnicodeStringFromLiteral(&IoDriverObjectType->TypeName, L"Driver"); +} + +/********************************************************************** + * NAME EXPORTED + * NtLoadDriver + * + * DESCRIPTION + * Loads a device driver. + * + * ARGUMENTS + * DriverServiceName + * Name of the service to load (registry key). + * + * RETURN VALUE + * Status. + * + * REVISIONS + */ +NTSTATUS STDCALL +NtLoadDriver(IN PUNICODE_STRING DriverServiceName) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[3]; + WCHAR FullImagePathBuffer[MAX_PATH]; + UNICODE_STRING ImagePath; + UNICODE_STRING FullImagePath; + NTSTATUS Status; + ULONG Type; + PDEVICE_NODE DeviceNode; + PMODULE_OBJECT ModuleObject; + LPWSTR Start; + + DPRINT("NtLoadDriver(%wZ) called\n", DriverServiceName); + + RtlInitUnicodeString(&ImagePath, NULL); + + /* Get service data */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"Type"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &Type; + + QueryTable[1].Name = L"ImagePath"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[1].EntryContext = &ImagePath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, + DriverServiceName->Buffer, + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + RtlFreeUnicodeString(&ImagePath); + return(Status); + } + + if (ImagePath.Length == 0) + { + wcscpy(FullImagePathBuffer, L"\\SystemRoot\\system32\\drivers"); + wcscat(FullImagePathBuffer, wcsrchr(DriverServiceName->Buffer, L'\\')); + wcscat(FullImagePathBuffer, L".sys"); + } + else if (ImagePath.Buffer[0] != L'\\') + { + wcscpy(FullImagePathBuffer, L"\\SystemRoot\\"); + wcscat(FullImagePathBuffer, ImagePath.Buffer); + } + else + { + wcscpy(FullImagePathBuffer, ImagePath.Buffer); + } + + RtlFreeUnicodeString(&ImagePath); + RtlInitUnicodeString(&FullImagePath, FullImagePathBuffer); + + DPRINT("FullImagePath: '%S'\n", FullImagePathBuffer); + DPRINT("Type %lx\n", Type); + + /* Use IopRootDeviceNode for now */ + Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); + return(Status); + } + + ModuleObject = LdrGetModuleObject(DriverServiceName); + if (ModuleObject != NULL) + { + return(STATUS_IMAGE_ALREADY_LOADED); + } + + Status = LdrLoadModule(&FullImagePath, &ModuleObject); + if (!NT_SUCCESS(Status)) + { + DPRINT1("LdrLoadModule() failed (Status %lx)\n", Status); + IopFreeDeviceNode(DeviceNode); + return(Status); + } + + /* Set a service name for the device node */ + Start = wcsrchr(DriverServiceName->Buffer, L'\\'); + if (Start == NULL) + Start = DriverServiceName->Buffer; + else + Start++; + RtlCreateUnicodeString(&DeviceNode->ServiceName, Start); + + Status = IopInitializeDriver(ModuleObject->EntryPoint, + DeviceNode, + (Type == 2 || Type == 8)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status); + LdrUnloadModule(ModuleObject); + IopFreeDeviceNode(DeviceNode); + } + + return(Status); +} + + +NTSTATUS STDCALL +NtUnloadDriver(IN PUNICODE_STRING DriverServiceName) +{ + DPRINT("DriverServiceName: '%wZ'\n", DriverServiceName); + + return(STATUS_NOT_IMPLEMENTED); +} + + +static NTSTATUS STDCALL +IopCreateGroupListEntry(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + PSERVICE_GROUP Group; + + if (ValueType == REG_SZ) + { + DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData); + + Group = ExAllocatePool(NonPagedPool, + sizeof(SERVICE_GROUP)); + if (Group == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(Group, sizeof(SERVICE_GROUP)); + + if (!RtlCreateUnicodeString(&Group->GroupName, + (PWSTR)ValueData)) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + + InsertTailList(&GroupListHead, + &Group->GroupListEntry); + } + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +IopCreateServiceListEntry(PUNICODE_STRING ServiceName) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[6]; + PSERVICE Service; + NTSTATUS Status; + + DPRINT("ServiceName: '%wZ'\n", ServiceName); + + /* Allocate service entry */ + Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE)); + if (Service == NULL) + { + DPRINT1("ExAllocatePool() failed\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + RtlZeroMemory(Service, sizeof(SERVICE)); + + /* Get service data */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"Start"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &Service->Start; + + QueryTable[1].Name = L"Type"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[1].EntryContext = &Service->Type; + + QueryTable[2].Name = L"ErrorControl"; + QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[2].EntryContext = &Service->ErrorControl; + + QueryTable[3].Name = L"Group"; + QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[3].EntryContext = &Service->ServiceGroup; + + QueryTable[4].Name = L"ImagePath"; + QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[4].EntryContext = &Service->ImagePath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + ServiceName->Buffer, + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status) || Service->Start > 1) + { + RtlFreeUnicodeString(&Service->ServiceGroup); + RtlFreeUnicodeString(&Service->ImagePath); + ExFreePool(Service); + return(Status); + } + + /* Copy service name */ + Service->ServiceName.Length = ServiceName->Length; + Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR); + Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool, + Service->ServiceName.MaximumLength); + RtlCopyMemory(Service->ServiceName.Buffer, + ServiceName->Buffer, + ServiceName->Length); + Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0; + + /* Build registry path */ + Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR); + Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool, + MAX_PATH * sizeof(WCHAR)); + wcscpy(Service->RegistryPath.Buffer, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + wcscat(Service->RegistryPath.Buffer, + Service->ServiceName.Buffer); + Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR); + + DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName); + DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); + DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); + DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath); + DPRINT("Start %lx Type %lx ErrorControl %lx\n", + Service->Start, Service->Type, Service->ErrorControl); + + /* Append service entry */ + InsertTailList(&ServiceListHead, + &Service->ServiceListEntry); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +IoCreateDriverList(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + PKEY_BASIC_INFORMATION KeyInfo = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING ServicesKeyName; + UNICODE_STRING SubKeyName; + HANDLE KeyHandle; + NTSTATUS Status; + ULONG Index; + + ULONG KeyInfoLength = 0; + ULONG ReturnedLength; + + DPRINT("IoCreateDriverList() called\n"); + + /* Initialize basic variables */ + InitializeListHead(&GroupListHead); + InitializeListHead(&ServiceListHead); + + /* Build group order list */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"List"; + QueryTable[0].QueryRoutine = IopCreateGroupListEntry; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"ServiceGroupOrder", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Enumerate services and create the service list */ + RtlInitUnicodeStringFromLiteral(&ServicesKeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"); + + InitializeObjectAttributes(&ObjectAttributes, + &ServicesKeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&KeyHandle, + 0x10001, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR); + KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength); + if (KeyInfo == NULL) + { + NtClose(KeyHandle); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Index = 0; + while (TRUE) + { + Status = NtEnumerateKey(KeyHandle, + Index, + KeyBasicInformation, + KeyInfo, + KeyInfoLength, + &ReturnedLength); + if (NT_SUCCESS(Status)) + { + if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR)) + { + + SubKeyName.Length = KeyInfo->NameLength; + SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR); + SubKeyName.Buffer = KeyInfo->Name; + SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0; + + DPRINT("KeyName: '%wZ'\n", &SubKeyName); + IopCreateServiceListEntry(&SubKeyName); + } + } + + if (!NT_SUCCESS(Status)) + break; + + Index++; + } + + ExFreePool(KeyInfo); + NtClose(KeyHandle); + + DPRINT("IoCreateDriverList() done\n"); + + return(STATUS_SUCCESS); +} + + +VOID +LdrLoadAutoConfigDrivers(VOID) +{ + PLIST_ENTRY GroupEntry; + PLIST_ENTRY ServiceEntry; + PSERVICE_GROUP CurrentGroup; + PSERVICE CurrentService; + NTSTATUS Status; + + CHAR TextBuffer [256]; + ULONG x, y, cx, cy; + + DPRINT("LdrLoadAutoConfigDrivers() called\n"); + + GroupEntry = GroupListHead.Flink; + while (GroupEntry != &GroupListHead) + { + CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); + + DPRINT("Group: %wZ\n", &CurrentGroup->GroupName); + + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + if ((RtlCompareUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE) == 0) && + (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/)) + { + + HalQueryDisplayParameters(&x, &y, &cx, &cy); + RtlFillMemory(TextBuffer, x, ' '); + TextBuffer[x] = '\0'; + HalSetDisplayParameters(0, y-1); + HalDisplayString(TextBuffer); + + sprintf(TextBuffer, "Loading %S...\n", CurrentService->ServiceName.Buffer); + HalSetDisplayParameters(0, y-1); + HalDisplayString(TextBuffer); + HalSetDisplayParameters(cx, cy); + + DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); + Status = NtLoadDriver(&CurrentService->RegistryPath); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtLoadDriver() failed (Status %lx)\n", Status); +#if 0 + if (CurrentService->ErrorControl == 1) + { + /* Log error */ + + } + else if (CurrentService->ErrorControl == 2) + { + if (IsLastKnownGood == FALSE) + { + /* Boot last known good configuration */ + + } + } + else if (CurrentService->ErrorControl == 3) + { + if (IsLastKnownGood == FALSE) + { + /* Boot last known good configuration */ + + } + else + { + /* BSOD! */ + + } + } +#endif + } + } + ServiceEntry = ServiceEntry->Flink; + } + + GroupEntry = GroupEntry->Flink; + } + + DPRINT("LdrLoadAutoConfigDrivers() done\n"); +} + + +NTSTATUS +IoDestroyDriverList(VOID) +{ + PLIST_ENTRY GroupEntry; + PLIST_ENTRY ServiceEntry; + PSERVICE_GROUP CurrentGroup; + PSERVICE CurrentService; + + DPRINT("IoDestroyDriverList() called\n"); + + /* Destroy group list */ + GroupEntry = GroupListHead.Flink; + while (GroupEntry != &GroupListHead) + { + CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); + + RtlFreeUnicodeString(&CurrentGroup->GroupName); + RemoveEntryList(GroupEntry); + ExFreePool(CurrentGroup); + + GroupEntry = GroupListHead.Flink; + } + + /* Destroy service list */ + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + RtlFreeUnicodeString(&CurrentService->ServiceName); + RtlFreeUnicodeString(&CurrentService->RegistryPath); + RtlFreeUnicodeString(&CurrentService->ServiceGroup); + RtlFreeUnicodeString(&CurrentService->ImagePath); + RemoveEntryList(ServiceEntry); + ExFreePool(CurrentService); + + ServiceEntry = ServiceListHead.Flink; + } + + DPRINT("IoDestroyDriverList() done\n"); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/io/errlog.c b/ntoskrnl/io/errlog.c new file mode 100644 index 0000000..4bbf0d0 --- /dev/null +++ b/ntoskrnl/io/errlog.c @@ -0,0 +1,60 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/errlog.c + * PURPOSE: Error logging + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +#include + +/* TYPES *********************************************************************/ + +#define LOG_FILE_APPLICATION L"\\SystemRoot\\System32\\Config\\AppEvent.Evt" +#define LOG_FILE_SECURITY L"\\SystemRoot\\System32\\Config\\SecEvent.Evt" +#define LOG_FILE_SYSTEM L"\\SystemRoot\\System32\\Config\\SysEvent.Evt" + +typedef struct _IO_ERROR_LOG_PACKET +{ + UCHAR MajorFunctionCode; + UCHAR RetryCount; + USHORT DumpDataSize; + USHORT NumberOfStrings; + USHORT StringOffset; + USHORT EventCategory; + NTSTATUS ErrorCode; + ULONG UniqueErrorValue; + NTSTATUS FinalStatus; + ULONG SequenceNumber; + ULONG IoControlCode; + LARGE_INTEGER DeviceOffset; + ULONG DumpData[1]; +} IO_ERROR_LOG_PACKET, *PIO_ERROR_LOG_PACKET; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS IoInitErrorLog(VOID) +{ + return(STATUS_SUCCESS); +} + +PVOID STDCALL IoAllocateErrorLogEntry(PVOID IoObject, UCHAR EntrySize) +{ + UNIMPLEMENTED; +} + +VOID STDCALL IoWriteErrorLogEntry(PVOID ElEntry) +{ +} + + +/* EOF */ diff --git a/ntoskrnl/io/error.c b/ntoskrnl/io/error.c new file mode 100644 index 0000000..ab78daf --- /dev/null +++ b/ntoskrnl/io/error.c @@ -0,0 +1,62 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/error.c + * PURPOSE: Handle media errors + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + + +VOID STDCALL +IoRaiseHardError(PIRP Irp, + PVPB Vpb, + PDEVICE_OBJECT RealDeviceObject) +{ + UNIMPLEMENTED; +} + +BOOLEAN +IoIsTotalDeviceFailure(NTSTATUS Status) +{ + UNIMPLEMENTED; +} + +BOOLEAN STDCALL +IoRaiseInformationalHardError(NTSTATUS ErrorStatus, + PUNICODE_STRING String, + PKTHREAD Thread) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/io/event.c b/ntoskrnl/io/event.c new file mode 100644 index 0000000..329edbc --- /dev/null +++ b/ntoskrnl/io/event.c @@ -0,0 +1,97 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/event.c + * PURPOSE: Implements named events + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +PKEVENT STDCALL +IoCreateNotificationEvent(PUNICODE_STRING EventName, + PHANDLE EventHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PKEVENT Event; + HANDLE Handle; + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, + EventName, + OBJ_OPENIF, + NULL, + NULL); + + Status = NtCreateEvent(&Handle, + EVENT_ALL_ACCESS, + &ObjectAttributes, + FALSE, + TRUE); + if (!NT_SUCCESS(Status)) + { + return NULL; + } + + ObReferenceObjectByHandle(Handle, + 0, + ExEventObjectType, + KernelMode, + (PVOID*)&Event, + NULL); + ObDereferenceObject(Event); + + *EventHandle = Handle; + + return Event; +} + +PKEVENT STDCALL +IoCreateSynchronizationEvent(PUNICODE_STRING EventName, + PHANDLE EventHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PKEVENT Event; + HANDLE Handle; + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, + EventName, + OBJ_OPENIF, + NULL, + NULL); + + Status = NtCreateEvent(&Handle, + EVENT_ALL_ACCESS, + &ObjectAttributes, + TRUE, + TRUE); + if (!NT_SUCCESS(Status)) + { + return NULL; + } + + ObReferenceObjectByHandle(Handle, + 0, + ExEventObjectType, + KernelMode, + (PVOID*)&Event, + NULL); + ObDereferenceObject(Event); + + *EventHandle = Handle; + + return Event; +} + +/* EOF */ diff --git a/ntoskrnl/io/file.c b/ntoskrnl/io/file.c new file mode 100644 index 0000000..99e932b --- /dev/null +++ b/ntoskrnl/io/file.c @@ -0,0 +1,351 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/file.c + * PURPOSE: Graceful system shutdown if a bug is detected + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +#define TAG_SYSB TAG('S', 'Y', 'S', 'B') + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtQueryInformationFile(HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass) +{ + PFILE_OBJECT FileObject; + NTSTATUS Status; + PIRP Irp; + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION StackPtr; + PVOID SystemBuffer; + IO_STATUS_BLOCK IoSB; + + assert(IoStatusBlock != NULL); + assert(FileInformation != NULL); + + DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d " + "Class %d)\n", FileHandle, IoStatusBlock, FileInformation, + Length, FileInformationClass); + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_READ_ATTRIBUTES, + IoFileObjectType, + UserMode, + (PVOID *)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + DPRINT("FileObject %x\n", FileObject); + + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize, + TRUE); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (SystemBuffer == NULL) + { + IoFreeIrp(Irp); + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irp->AssociatedIrp.SystemBuffer = SystemBuffer; + Irp->UserIosb = &IoSB; + Irp->UserEvent = &FileObject->Event; + KeResetEvent( &FileObject->Event ); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = FileObject; + + StackPtr->Parameters.QueryFile.FileInformationClass = + FileInformationClass; + StackPtr->Parameters.QueryFile.Length = Length; + + Status = IoCallDriver(FileObject->DeviceObject, + Irp); + if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO)) + { + KeWaitForSingleObject(&FileObject->Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + + if (NT_SUCCESS(Status)) + { + DPRINT("Information %lu\n", IoStatusBlock->Information); + MmSafeCopyToUser(FileInformation, + SystemBuffer, + IoStatusBlock->Information); + } + + ExFreePool(SystemBuffer); + return(Status); +} + + +NTSTATUS STDCALL +IoQueryFileInformation(IN PFILE_OBJECT FileObject, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + OUT PVOID FileInformation, + OUT PULONG ReturnedLength) +{ + IO_STATUS_BLOCK IoStatusBlock; + PIRP Irp; + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + + assert(FileInformation != NULL) + + Status = ObReferenceObjectByPointer(FileObject, + FILE_READ_ATTRIBUTES, + IoFileObjectType, + KernelMode); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("FileObject %x\n", FileObject); + + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize, + TRUE); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Irp->AssociatedIrp.SystemBuffer = FileInformation; + Irp->UserIosb = &IoStatusBlock; + Irp->UserEvent = &FileObject->Event; + KeResetEvent( &FileObject->Event ); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = FileObject; + + StackPtr->Parameters.QueryFile.FileInformationClass = + FileInformationClass; + StackPtr->Parameters.QueryFile.Length = Length; + + Status = IoCallDriver(FileObject->DeviceObject, + Irp); + if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO)) + { + KeWaitForSingleObject(&FileObject->Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + if (ReturnedLength != NULL) + { + *ReturnedLength = IoStatusBlock.Information; + } + + + return Status; +} + + +NTSTATUS STDCALL +NtSetInformationFile(HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass) +{ + PIO_STACK_LOCATION StackPtr; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + NTSTATUS Status; + PVOID SystemBuffer; + IO_STATUS_BLOCK IoSB; + + assert(IoStatusBlock != NULL) + assert(FileInformation != NULL) + + DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d " + "Class %d)\n", FileHandle, IoStatusBlock, FileInformation, + Length, FileInformationClass); + + /* Get the file object from the file handle */ + Status = ObReferenceObjectByHandle(FileHandle, + FILE_WRITE_ATTRIBUTES, + IoFileObjectType, + UserMode, + (PVOID *)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + DPRINT("FileObject %x\n", FileObject); + + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize, + TRUE); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (SystemBuffer == NULL) + { + IoFreeIrp(Irp); + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + MmSafeCopyFromUser(SystemBuffer, + FileInformation, + Length); + + Irp->AssociatedIrp.SystemBuffer = SystemBuffer; + Irp->UserIosb = &IoSB; + Irp->UserEvent = &FileObject->Event; + KeResetEvent( &FileObject->Event ); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = FileObject; + + StackPtr->Parameters.SetFile.FileInformationClass = + FileInformationClass; + StackPtr->Parameters.SetFile.Length = Length; + + /* + * Pass the IRP to the FSD (and wait for + * it if required) + */ + DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject); + Status = IoCallDriver(FileObject->DeviceObject, + Irp); + if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO)) + { + KeWaitForSingleObject(&FileObject->Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + ExFreePool(SystemBuffer); + + return Status; +} + + +NTSTATUS STDCALL +NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_BASIC_INFORMATION FileInformation) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS STDCALL +NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS STDCALL +NtQueryEaFile(IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN BOOLEAN ReturnSingleEntry, + IN PVOID EaList OPTIONAL, + IN ULONG EaListLength, + IN PULONG EaIndex OPTIONAL, + IN BOOLEAN RestartScan) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS STDCALL +NtSetEaFile(IN HANDLE FileHandle, + IN PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID EaBuffer, + IN ULONG EaBufferSize) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/io/flush.c b/ntoskrnl/io/flush.c new file mode 100644 index 0000000..078f5ea --- /dev/null +++ b/ntoskrnl/io/flush.c @@ -0,0 +1,86 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/flush.c + * PURPOSE: Flushing file buffer + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS +STDCALL +NtFlushWriteBuffer(VOID) +{ + KeFlushWriteBuffer(); + return STATUS_SUCCESS; +} + +NTSTATUS +STDCALL +NtFlushBuffersFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ) +/* + * FUNCTION: Flushes cached file data to disk + * ARGUMENTS: + * FileHandle = Points to the file + * IoStatusBlock = Caller must supply storage to receive the result of + * the flush buffers operation. The information field is + * set to number of bytes flushed to disk. + * RETURNS: Status + * REMARKS: This function maps to the win32 FlushFileBuffers + */ +{ + PFILE_OBJECT FileObject = NULL; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + IO_STATUS_BLOCK IoSB; + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_WRITE_DATA, + NULL, + UserMode, + (PVOID*)&FileObject, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + KeResetEvent( &FileObject->Event ); + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, + FileObject->DeviceObject, + NULL, + 0, + NULL, + &FileObject->Event, + &IoSB); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + + Status = IoCallDriver(FileObject->DeviceObject,Irp); + if (Status==STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,FALSE,NULL); + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + return(Status); +} diff --git a/ntoskrnl/io/fs.c b/ntoskrnl/io/fs.c new file mode 100644 index 0000000..0365f62 --- /dev/null +++ b/ntoskrnl/io/fs.c @@ -0,0 +1,733 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/fs.c + * PURPOSE: Filesystem functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* TYPES *******************************************************************/ + +typedef struct _FILE_SYSTEM_OBJECT +{ + PDEVICE_OBJECT DeviceObject; + LIST_ENTRY Entry; +} FILE_SYSTEM_OBJECT, *PFILE_SYSTEM_OBJECT; + +typedef struct _FS_CHANGE_NOTIFY_ENTRY +{ + LIST_ENTRY FsChangeNotifyList; + PDRIVER_OBJECT DriverObject; + PFSDNOTIFICATIONPROC FSDNotificationProc; +} FS_CHANGE_NOTIFY_ENTRY, *PFS_CHANGE_NOTIFY_ENTRY; + + +/* GLOBALS ******************************************************************/ + +static KSPIN_LOCK FileSystemListLock; +static LIST_ENTRY FileSystemListHead; + +static KSPIN_LOCK FsChangeNotifyListLock; +static LIST_ENTRY FsChangeNotifyListHead; + +#define TAG_FILE_SYSTEM TAG('F', 'S', 'Y', 'S') +#define TAG_FS_CHANGE_NOTIFY TAG('F', 'S', 'C', 'N') + + +static VOID +IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject, + BOOLEAN DriverActive); + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtFsControlFile ( + IN HANDLE DeviceHandle, + IN HANDLE EventHandle OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferSize + ) +{ + NTSTATUS Status; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + PKEVENT ptrEvent; + IO_STATUS_BLOCK IoSB; + + DPRINT("NtFsControlFile(DeviceHandle %x EventHandle %x ApcRoutine %x " + "ApcContext %x IoStatusBlock %x IoControlCode %x " + "InputBuffer %x InputBufferSize %x OutputBuffer %x " + "OutputBufferSize %x)\n", + DeviceHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock, + IoControlCode,InputBuffer,InputBufferSize,OutputBuffer, + OutputBufferSize); + + Status = ObReferenceObjectByHandle(DeviceHandle, + FILE_READ_DATA | FILE_WRITE_DATA, + NULL, + KernelMode, + (PVOID *) &FileObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (EventHandle != NULL) + { + Status = ObReferenceObjectByHandle (EventHandle, + SYNCHRONIZE, + ExEventObjectType, + UserMode, + (PVOID*)&ptrEvent, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + return Status; + } + } + else + { + KeResetEvent (&FileObject->Event); + ptrEvent = &FileObject->Event; + } + + + DeviceObject = FileObject->DeviceObject; + + Irp = IoBuildDeviceIoControlRequest(IoControlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutputBufferSize, + FALSE, + ptrEvent, + &IoSB); + + Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; + Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + StackPtr->DeviceObject = DeviceObject; + StackPtr->Parameters.FileSystemControl.InputBufferLength = InputBufferSize; + StackPtr->Parameters.FileSystemControl.OutputBufferLength = + OutputBufferSize; + StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; + + Status = IoCallDriver(DeviceObject,Irp); + if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO)) + { + KeWaitForSingleObject(ptrEvent,Executive,KernelMode,FALSE,NULL); + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + return(Status); +} + + +VOID +IoInitFileSystemImplementation(VOID) +{ + InitializeListHead(&FileSystemListHead); + KeInitializeSpinLock(&FileSystemListLock); + + InitializeListHead(&FsChangeNotifyListHead); + KeInitializeSpinLock(&FsChangeNotifyListLock); +} + + +VOID +IoShutdownRegisteredFileSystems(VOID) +{ + KIRQL oldlvl; + PLIST_ENTRY current_entry; + FILE_SYSTEM_OBJECT* current; + PIRP Irp; + KEVENT Event; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + DPRINT("IoShutdownRegisteredFileSystems()\n"); + + KeAcquireSpinLock(&FileSystemListLock,&oldlvl); + KeInitializeEvent(&Event,NotificationEvent,FALSE); + + current_entry = FileSystemListHead.Flink; + while (current_entry!=(&FileSystemListHead)) + { + current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry); + + /* send IRP_MJ_SHUTDOWN */ + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, + current->DeviceObject, + NULL, + 0, + 0, + &Event, + &IoStatusBlock); + + Status = IoCallDriver(current->DeviceObject,Irp); + if (Status==STATUS_PENDING) + { + KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL); + } + + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&FileSystemListLock,oldlvl); +} + + +static NTSTATUS +IopMountFileSystem(PDEVICE_OBJECT DeviceObject, + PDEVICE_OBJECT DeviceToMount) +{ + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION StackPtr; + PKEVENT Event; + PIRP Irp; + NTSTATUS Status; + + DPRINT("IoAskFileSystemToMountDevice(DeviceObject %x, DeviceToMount %x)\n", + DeviceObject,DeviceToMount); + + assert_irql(PASSIVE_LEVEL); + Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); + if (Event == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + KeInitializeEvent(Event, NotificationEvent, FALSE); + + Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + if (Irp==NULL) + { + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irp->UserIosb = &IoStatusBlock; + DPRINT("Irp->UserIosb %x\n", Irp->UserIosb); + Irp->UserEvent = Event; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; + StackPtr->MinorFunction = IRP_MN_MOUNT_VOLUME; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + + StackPtr->Parameters.MountVolume.Vpb = DeviceToMount->Vpb; + StackPtr->Parameters.MountVolume.DeviceObject = DeviceToMount; + + Status = IoCallDriver(DeviceObject,Irp); + if (Status==STATUS_PENDING) + { + KeWaitForSingleObject(Event,Executive,KernelMode,FALSE,NULL); + Status = IoStatusBlock.Status; + } + + ExFreePool(Event); + + return(Status); +} + + +static NTSTATUS +IopLoadFileSystem(IN PDEVICE_OBJECT DeviceObject) +{ + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION StackPtr; + PKEVENT Event; + PIRP Irp; + NTSTATUS Status; + + DPRINT("IopLoadFileSystem(DeviceObject %x)\n", DeviceObject); + + assert_irql(PASSIVE_LEVEL); + Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); + if (Event == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + KeInitializeEvent(Event, NotificationEvent, FALSE); + + Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + if (Irp==NULL) + { + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irp->UserIosb = &IoStatusBlock; + DPRINT("Irp->UserIosb %x\n", Irp->UserIosb); + Irp->UserEvent = Event; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; + StackPtr->MinorFunction = IRP_MN_LOAD_FILE_SYSTEM; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + + Status = IoCallDriver(DeviceObject,Irp); + if (Status==STATUS_PENDING) + { + KeWaitForSingleObject(Event,Executive,KernelMode,FALSE,NULL); + Status = IoStatusBlock.Status; + } + + ExFreePool(Event); + + return(Status); +} + + +NTSTATUS +IoMountVolume(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN AllowRawMount) +/* + * FUNCTION: Mounts a logical volume + * ARGUMENTS: + * DeviceObject = Device to mount + * RETURNS: Status + */ +{ + KIRQL oldlvl; + PLIST_ENTRY current_entry; + FILE_SYSTEM_OBJECT* current; + NTSTATUS Status; + DEVICE_TYPE MatchingDeviceType; + + assert_irql(PASSIVE_LEVEL); + + DPRINT("IoMountVolume(DeviceObject %x AllowRawMount %x)\n", + DeviceObject, AllowRawMount); + + switch (DeviceObject->DeviceType) + { + case FILE_DEVICE_DISK: + case FILE_DEVICE_VIRTUAL_DISK: /* ?? */ + MatchingDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM; + break; + + case FILE_DEVICE_CD_ROM: + MatchingDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM; + break; + + case FILE_DEVICE_NETWORK: + MatchingDeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM; + break; + + case FILE_DEVICE_TAPE: + MatchingDeviceType = FILE_DEVICE_TAPE_FILE_SYSTEM; + break; + + default: + CPRINT("No matching file system type found for device type: %x\n", + DeviceObject->DeviceType); + return(STATUS_UNRECOGNIZED_VOLUME); + } + + KeAcquireSpinLock(&FileSystemListLock,&oldlvl); + current_entry = FileSystemListHead.Flink; + while (current_entry!=(&FileSystemListHead)) + { + current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry); + if (current->DeviceObject->DeviceType != MatchingDeviceType) + { + current_entry = current_entry->Flink; + continue; + } + KeReleaseSpinLock(&FileSystemListLock,oldlvl); + Status = IopMountFileSystem(current->DeviceObject, + DeviceObject); + KeAcquireSpinLock(&FileSystemListLock,&oldlvl); + switch (Status) + { + case STATUS_FS_DRIVER_REQUIRED: + KeReleaseSpinLock(&FileSystemListLock,oldlvl); + Status = IopLoadFileSystem(current->DeviceObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeAcquireSpinLock(&FileSystemListLock,&oldlvl); + current_entry = FileSystemListHead.Flink; + continue; + + case STATUS_SUCCESS: + DeviceObject->Vpb->Flags = DeviceObject->Vpb->Flags | + VPB_MOUNTED; + KeReleaseSpinLock(&FileSystemListLock,oldlvl); + return(STATUS_SUCCESS); + + case STATUS_UNRECOGNIZED_VOLUME: + default: + current_entry = current_entry->Flink; + } + } + KeReleaseSpinLock(&FileSystemListLock,oldlvl); + + return(STATUS_UNRECOGNIZED_VOLUME); +} + + +/********************************************************************** + * NAME EXPORTED + * IoVerifyVolume + * + * DESCRIPTION + * Verify the file system type and volume information or mount + * a file system. + * + * ARGUMENTS + * DeviceObject + * Device to verify or mount + * + * AllowRawMount + * ... + * + * RETURN VALUE + * Status + */ +NTSTATUS STDCALL +IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject, + IN BOOLEAN AllowRawMount) +{ + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION StackPtr; + PKEVENT Event; + PIRP Irp; + NTSTATUS Status; + + DPRINT("IoVerifyVolume(DeviceObject %x AllowRawMount %x)\n", + DeviceObject, AllowRawMount); + + Status = STATUS_SUCCESS; + + KeWaitForSingleObject(&DeviceObject->DeviceLock, + Executive, + KernelMode, + FALSE, + NULL); + + DeviceObject->Flags &= ~DO_VERIFY_VOLUME; + + if (DeviceObject->Vpb->Flags & VPB_MOUNTED) + { + /* Issue verify request to the FSD */ + Event = ExAllocatePool(NonPagedPool, + sizeof(KEVENT)); + if (Event == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + KeInitializeEvent(Event, + NotificationEvent, + FALSE); + + Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + if (Irp==NULL) + { + ExFreePool(Event); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irp->UserIosb = &IoStatusBlock; + Irp->UserEvent = Event; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; + StackPtr->MinorFunction = IRP_MN_VERIFY_VOLUME; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = NULL; + StackPtr->CompletionRoutine = NULL; + + StackPtr->Parameters.VerifyVolume.Vpb = DeviceObject->Vpb; + StackPtr->Parameters.VerifyVolume.DeviceObject = DeviceObject; + + Status = IoCallDriver(DeviceObject, + Irp); + if (Status==STATUS_PENDING) + { + KeWaitForSingleObject(Event,Executive,KernelMode,FALSE,NULL); + Status = IoStatusBlock.Status; + } + ExFreePool(Event); + + if (NT_SUCCESS(Status)) + { + KeSetEvent(&DeviceObject->DeviceLock, + IO_NO_INCREMENT, + FALSE); + return(STATUS_SUCCESS); + } + } + + if (Status == STATUS_WRONG_VOLUME) + { + /* Clean existing VPB. This unmounts the filesystem (in an ugly way). */ + DPRINT("Wrong volume!\n"); + + DeviceObject->Vpb->DeviceObject = NULL; + DeviceObject->Vpb->Flags &= ~VPB_MOUNTED; + } + + /* Start mount sequence */ + Status = IoMountVolume(DeviceObject, + AllowRawMount); + + KeSetEvent(&DeviceObject->DeviceLock, + IO_NO_INCREMENT, + FALSE); + + return(Status); +} + + +PDEVICE_OBJECT STDCALL +IoGetDeviceToVerify(IN PETHREAD Thread) +/* + * FUNCTION: Returns a pointer to the device, representing a removable-media + * device, that is the target of the given thread's I/O request + */ +{ + return(Thread->DeviceToVerify); +} + + +VOID STDCALL +IoSetDeviceToVerify(IN PETHREAD Thread, + IN PDEVICE_OBJECT DeviceObject) +{ + Thread->DeviceToVerify = DeviceObject; +} + + +VOID STDCALL +IoSetHardErrorOrVerifyDevice(IN PIRP Irp, + IN PDEVICE_OBJECT DeviceObject) +{ + Irp->Tail.Overlay.Thread->DeviceToVerify = DeviceObject; +} + + +VOID STDCALL +IoRegisterFileSystem(IN PDEVICE_OBJECT DeviceObject) +{ + PFILE_SYSTEM_OBJECT Fs; + + DPRINT("IoRegisterFileSystem(DeviceObject %x)\n",DeviceObject); + + Fs = ExAllocatePoolWithTag(NonPagedPool, + sizeof(FILE_SYSTEM_OBJECT), + TAG_FILE_SYSTEM); + assert(Fs!=NULL); + + Fs->DeviceObject = DeviceObject; + ExInterlockedInsertTailList(&FileSystemListHead, + &Fs->Entry, + &FileSystemListLock); + IopNotifyFileSystemChange(DeviceObject, + TRUE); +} + + +VOID STDCALL +IoUnregisterFileSystem(IN PDEVICE_OBJECT DeviceObject) +{ + KIRQL oldlvl; + PLIST_ENTRY current_entry; + PFILE_SYSTEM_OBJECT current; + + DPRINT("IoUnregisterFileSystem(DeviceObject %x)\n",DeviceObject); + + KeAcquireSpinLock(&FileSystemListLock,&oldlvl); + current_entry = FileSystemListHead.Flink; + while (current_entry!=(&FileSystemListHead)) + { + current = CONTAINING_RECORD(current_entry,FILE_SYSTEM_OBJECT,Entry); + if (current->DeviceObject == DeviceObject) + { + RemoveEntryList(current_entry); + ExFreePool(current); + KeReleaseSpinLock(&FileSystemListLock,oldlvl); + IopNotifyFileSystemChange(DeviceObject, FALSE); + return; + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&FileSystemListLock,oldlvl); +} + + +/********************************************************************** + * NAME EXPORTED + * IoGetBaseFileSystemDeviceObject@4 + * + * DESCRIPTION + * Get the DEVICE_OBJECT associated to + * a FILE_OBJECT. + * + * ARGUMENTS + * FileObject + * + * RETURN VALUE + * + * NOTE + * From Bo Branten's ntifs.h v13. + */ +PDEVICE_OBJECT STDCALL +IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject) +{ + PDEVICE_OBJECT DeviceObject = NULL; + PVPB Vpb = NULL; + + /* + * If the FILE_OBJECT's VPB is defined, + * get the device from it. + */ + if (NULL != (Vpb = FileObject->Vpb)) + { + if (NULL != (DeviceObject = Vpb->DeviceObject)) + { + /* Vpb->DeviceObject DEFINED! */ + return DeviceObject; + } + } + /* + * If that failed, try the VPB + * in the FILE_OBJECT's DeviceObject. + */ + DeviceObject = FileObject->DeviceObject; + if (NULL == (Vpb = DeviceObject->Vpb)) + { + /* DeviceObject->Vpb UNDEFINED! */ + return DeviceObject; + } + /* + * If that pointer to the VPB is again + * undefined, return directly the + * device object from the FILE_OBJECT. + */ + return ( + (NULL == Vpb->DeviceObject) + ? DeviceObject + : Vpb->DeviceObject + ); +} + + +static VOID +IopNotifyFileSystemChange(PDEVICE_OBJECT DeviceObject, + BOOLEAN DriverActive) +{ + PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; + PLIST_ENTRY Entry; + KIRQL oldlvl; + + KeAcquireSpinLock(&FsChangeNotifyListLock,&oldlvl); + Entry = FsChangeNotifyListHead.Flink; + while (Entry != &FsChangeNotifyListHead) + { + ChangeEntry = CONTAINING_RECORD(Entry, FS_CHANGE_NOTIFY_ENTRY, FsChangeNotifyList); + + (ChangeEntry->FSDNotificationProc)(DeviceObject, DriverActive); + + Entry = Entry->Flink; + } + KeReleaseSpinLock(&FsChangeNotifyListLock,oldlvl); +} + + +NTSTATUS STDCALL +IoRegisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, + IN PFSDNOTIFICATIONPROC FSDNotificationProc) +{ + PFS_CHANGE_NOTIFY_ENTRY Entry; + + Entry = ExAllocatePoolWithTag(NonPagedPool, + sizeof(FS_CHANGE_NOTIFY_ENTRY), + TAG_FS_CHANGE_NOTIFY); + if (Entry == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); + + Entry->DriverObject = DriverObject; + Entry->FSDNotificationProc = FSDNotificationProc; + + ExInterlockedInsertHeadList(&FsChangeNotifyListHead, + &Entry->FsChangeNotifyList, + &FsChangeNotifyListLock); + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +IoUnregisterFsRegistrationChange(IN PDRIVER_OBJECT DriverObject, + IN PFSDNOTIFICATIONPROC FSDNotificationProc) +{ + PFS_CHANGE_NOTIFY_ENTRY ChangeEntry; + PLIST_ENTRY Entry; + KIRQL oldlvl; + + Entry = FsChangeNotifyListHead.Flink; + while (Entry != &FsChangeNotifyListHead) + { + ChangeEntry = CONTAINING_RECORD(Entry, FS_CHANGE_NOTIFY_ENTRY, FsChangeNotifyList); + if (ChangeEntry->DriverObject == DriverObject && + ChangeEntry->FSDNotificationProc == FSDNotificationProc) + { + KeAcquireSpinLock(&FsChangeNotifyListLock,&oldlvl); + RemoveEntryList(Entry); + KeReleaseSpinLock(&FsChangeNotifyListLock,oldlvl); + + ExFreePool(Entry); + return; + } + + Entry = Entry->Flink; + } +} + +/* EOF */ diff --git a/ntoskrnl/io/iocomp.c b/ntoskrnl/io/iocomp.c new file mode 100644 index 0000000..21b672d --- /dev/null +++ b/ntoskrnl/io/iocomp.c @@ -0,0 +1,83 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/iocomp.c + * PURPOSE: + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + Changed NtQueryIoCompletion + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +NtCreateIoCompletion ( + OUT PHANDLE CompletionPort, + IN ACCESS_MASK DesiredAccess, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NumberOfConcurrentThreads + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtOpenIoCompletion ( + OUT PHANDLE CompletionPort, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes + ) +{ + return(STATUS_SUCCESS); +} + + +NTSTATUS +STDCALL +NtQueryIoCompletion ( + IN HANDLE CompletionPort, + IN ULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PULONG NumberOfBytesTransferred + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtRemoveIoCompletion ( + IN HANDLE CompletionPort, + OUT PULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PULONG CompletionStatus, + PLARGE_INTEGER WaitTime + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtSetIoCompletion ( + IN HANDLE CompletionPort, + IN ULONG CompletionKey, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG NumberOfBytesToTransfer, + OUT PULONG NumberOfBytesTransferred + ) +{ + UNIMPLEMENTED; +} diff --git a/ntoskrnl/io/ioctrl.c b/ntoskrnl/io/ioctrl.c new file mode 100644 index 0000000..9262d7e --- /dev/null +++ b/ntoskrnl/io/ioctrl.c @@ -0,0 +1,117 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/ioctrl.c + * PURPOSE: Device IO control + * PROGRAMMER: David Welch (welch@mcmail.com) + * Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 22/05/98 + * Filled in ZwDeviceIoControlFile 22/02/99 + * Fixed IO method handling 08/03/99 + * Added APC support 05/11/99 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL NtDeviceIoControlFile (IN HANDLE DeviceHandle, + IN HANDLE Event, + IN PIO_APC_ROUTINE UserApcRoutine, + IN PVOID UserApcContext, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferSize, + OUT PVOID OutputBuffer, + IN ULONG OutputBufferSize) +{ + NTSTATUS Status; + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + PKEVENT ptrEvent; + IO_STATUS_BLOCK IoSB; + + DPRINT("NtDeviceIoControlFile(DeviceHandle %x Event %x UserApcRoutine %x " + "UserApcContext %x IoStatusBlock %x IoControlCode %x " + "InputBuffer %x InputBufferSize %x OutputBuffer %x " + "OutputBufferSize %x)\n", + DeviceHandle,Event,UserApcRoutine,UserApcContext,IoStatusBlock, + IoControlCode,InputBuffer,InputBufferSize,OutputBuffer, + OutputBufferSize); + + Status = ObReferenceObjectByHandle(DeviceHandle, + FILE_READ_DATA | FILE_WRITE_DATA, + IoFileObjectType, + KernelMode, + (PVOID *) &FileObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (Event != NULL) + { + Status = ObReferenceObjectByHandle (Event, + SYNCHRONIZE, + ExEventObjectType, + UserMode, + (PVOID*)&ptrEvent, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + return Status; + } + } + else + { + KeResetEvent (&FileObject->Event); + ptrEvent = &FileObject->Event; + } + + DeviceObject = FileObject->DeviceObject; + + Irp = IoBuildDeviceIoControlRequest(IoControlCode, + DeviceObject, + InputBuffer, + InputBufferSize, + OutputBuffer, + OutputBufferSize, + FALSE, + ptrEvent, + Event ? IoStatusBlock : &IoSB); + + Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine; + Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext; + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + StackPtr->DeviceObject = DeviceObject; + StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferSize; + StackPtr->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferSize; + + Status = IoCallDriver(DeviceObject,Irp); + if (Event == NULL && Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO)) + { + KeWaitForSingleObject(ptrEvent,Executive,KernelMode,FALSE,NULL); + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + return(Status); +} + +/* EOF */ diff --git a/ntoskrnl/io/iomgr.c b/ntoskrnl/io/iomgr.c new file mode 100644 index 0000000..4c5a358 --- /dev/null +++ b/ntoskrnl/io/iomgr.c @@ -0,0 +1,279 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/iomgr.c + * PURPOSE: Initializes the io manager + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 29/07/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_DEVICE_TYPE TAG('D', 'E', 'V', 'T') +#define TAG_FILE_TYPE TAG('F', 'I', 'L', 'E') + +/* DATA ********************************************************************/ + + +POBJECT_TYPE EXPORTED IoDeviceObjectType = NULL; +POBJECT_TYPE EXPORTED IoFileObjectType = NULL; +ULONG EXPORTED IoReadOperationCount = 0; /* FIXME: unknown type */ +ULONG EXPORTED IoReadTransferCount = 0; /* FIXME: unknown type */ +ULONG EXPORTED IoWriteOperationCount = 0; /* FIXME: unknown type */ +ULONG EXPORTED IoWriteTransferCount = 0; /* FIXME: unknown type */ +ULONG EXPORTED IoStatisticsLock = 0; /* FIXME: unknown type */ + +static GENERIC_MAPPING IopFileMapping = {FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE, + FILE_ALL_ACCESS}; + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +IopCloseFile(PVOID ObjectBody, + ULONG HandleCount) +{ + PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + + DPRINT("IopCloseFile()\n"); + + if (HandleCount > 0) + { + return; + } + + ObReferenceObjectByPointer(FileObject, + STANDARD_RIGHTS_REQUIRED, + IoFileObjectType, + UserMode); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLEANUP, + FileObject->DeviceObject, + NULL, + 0, + NULL, + NULL, + NULL); + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + + Status = IoCallDriver(FileObject->DeviceObject, Irp); +} + +VOID STDCALL +IopDeleteFile(PVOID ObjectBody) +{ + PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + + DPRINT("IopDeleteFile()\n"); + + ObReferenceObjectByPointer(ObjectBody, + STANDARD_RIGHTS_REQUIRED, + IoFileObjectType, + UserMode); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLOSE, + FileObject->DeviceObject, + NULL, + 0, + NULL, + NULL, + NULL); + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + + Status = IoCallDriver(FileObject->DeviceObject, Irp); + + if (FileObject->FileName.Buffer != NULL) + { + ExFreePool(FileObject->FileName.Buffer); + FileObject->FileName.Buffer = 0; + } +} + + +VOID IoInit (VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DirName; + UNICODE_STRING LinkName; + HANDLE Handle; + + IopInitDriverImplementation(); + + /* + * Register iomgr types: DeviceObjectType + */ + IoDeviceObjectType = ExAllocatePool (NonPagedPool, + sizeof (OBJECT_TYPE)); + + IoDeviceObjectType->Tag = TAG_DEVICE_TYPE; + IoDeviceObjectType->TotalObjects = 0; + IoDeviceObjectType->TotalHandles = 0; + IoDeviceObjectType->MaxObjects = ULONG_MAX; + IoDeviceObjectType->MaxHandles = ULONG_MAX; + IoDeviceObjectType->PagedPoolCharge = 0; + IoDeviceObjectType->NonpagedPoolCharge = sizeof (DEVICE_OBJECT); + IoDeviceObjectType->Mapping = &IopFileMapping; + IoDeviceObjectType->Dump = NULL; + IoDeviceObjectType->Open = NULL; + IoDeviceObjectType->Close = NULL; + IoDeviceObjectType->Delete = NULL; + IoDeviceObjectType->Parse = NULL; + IoDeviceObjectType->Security = NULL; + IoDeviceObjectType->QueryName = NULL; + IoDeviceObjectType->OkayToClose = NULL; + IoDeviceObjectType->Create = IopCreateDevice; + IoDeviceObjectType->DuplicationNotify = NULL; + + RtlInitUnicodeStringFromLiteral(&IoDeviceObjectType->TypeName, L"Device"); + + /* + * Register iomgr types: FileObjectType + * (alias DriverObjectType) + */ + IoFileObjectType = ExAllocatePool (NonPagedPool, sizeof (OBJECT_TYPE)); + + IoFileObjectType->Tag = TAG_FILE_TYPE; + IoFileObjectType->TotalObjects = 0; + IoFileObjectType->TotalHandles = 0; + IoFileObjectType->MaxObjects = ULONG_MAX; + IoFileObjectType->MaxHandles = ULONG_MAX; + IoFileObjectType->PagedPoolCharge = 0; + IoFileObjectType->NonpagedPoolCharge = sizeof(FILE_OBJECT); + IoFileObjectType->Mapping = &IopFileMapping; + IoFileObjectType->Dump = NULL; + IoFileObjectType->Open = NULL; + IoFileObjectType->Close = IopCloseFile; + IoFileObjectType->Delete = IopDeleteFile; + IoFileObjectType->Parse = NULL; + IoFileObjectType->Security = NULL; + IoFileObjectType->QueryName = NULL; + IoFileObjectType->OkayToClose = NULL; + IoFileObjectType->Create = IopCreateFile; + IoFileObjectType->DuplicationNotify = NULL; + + RtlInitUnicodeStringFromLiteral(&IoFileObjectType->TypeName, L"File"); + + /* + * Create the '\Driver' object directory + */ + RtlInitUnicodeStringFromLiteral(&DirName, L"\\Driver"); + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + NtCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + + /* + * Create the '\FileSystem' object directory + */ + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\FileSystem"); + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + NtCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + + /* + * Create the '\Device' directory + */ + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\Device"); + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + ZwCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + + /* + * Create the '\??' directory + */ + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\??"); + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + ZwCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + + /* + * Create the '\ArcName' directory + */ + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\ArcName"); + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + ZwCreateDirectoryObject(&Handle, + 0, + &ObjectAttributes); + + /* + * Initialize remaining subsubsystem + */ + IoInitCancelHandling(); + IoInitSymbolicLinkImplementation(); + IoInitFileSystemImplementation(); + IoInitVpbImplementation(); + IoInitShutdownNotification(); + + /* + * Create link from '\DosDevices' to '\??' directory + */ + RtlInitUnicodeStringFromLiteral(&LinkName, + L"\\DosDevices"); + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\??"); + IoCreateSymbolicLink(&LinkName, + &DirName); + + /* + * Initialize PnP manager + */ + PnpInit(); +} + + +PGENERIC_MAPPING STDCALL +IoGetFileObjectGenericMapping(VOID) +{ + return(&IopFileMapping); +} + +/* EOF */ diff --git a/ntoskrnl/io/iowork.c b/ntoskrnl/io/iowork.c new file mode 100644 index 0000000..03dbf4c --- /dev/null +++ b/ntoskrnl/io/iowork.c @@ -0,0 +1,91 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: reactos/ntoskrnl/io/iowork.c + * PURPOSE: Manage IO system work queues + * PROGRAMMER: David Welch (welch@mcmail.com) + * Robert Dickenson (odin@pnc.com.au) + * REVISION HISTORY: + * 28/09/2002: (RDD) Created from copy of ex/work.c + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* TYPES ********************************************************************/ + +typedef struct _IO_WORKITEM +{ + WORK_QUEUE_ITEM Item; + PDEVICE_OBJECT DeviceObject; + PIO_WORKITEM_ROUTINE WorkerRoutine; + PVOID Context; +} IO_WORKITEM; + +/* GLOBALS ******************************************************************/ + +#define TAG_IOWI TAG('I', 'O', 'W', 'I') + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL STATIC +IoWorkItemCallback(PVOID Parameter) +{ + PIO_WORKITEM IoWorkItem = (PIO_WORKITEM)Parameter; + IoWorkItem->WorkerRoutine(IoWorkItem->DeviceObject, IoWorkItem->Context); + ObDereferenceObject(IoWorkItem->DeviceObject); +} + +VOID STDCALL +IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, + IN PIO_WORKITEM_ROUTINE WorkerRoutine, + IN WORK_QUEUE_TYPE QueueType, + IN PVOID Context) +/* + * FUNCTION: Inserts a work item in a queue for one of the system worker + * threads to process + * ARGUMENTS: + * IoWorkItem = Item to insert + * QueueType = Queue to insert it in + */ +{ + ExInitializeWorkItem(&IoWorkItem->Item, IoWorkItemCallback, + (PVOID)IoWorkItem); + IoWorkItem->WorkerRoutine = WorkerRoutine; + IoWorkItem->Context = Context; + ObReferenceObjectByPointer(IoWorkItem->DeviceObject, + FILE_ALL_ACCESS, + NULL, + KernelMode); + ExQueueWorkItem(&IoWorkItem->Item, QueueType); +} + +VOID STDCALL +IoFreeWorkItem(PIO_WORKITEM IoWorkItem) +{ + ExFreePool(IoWorkItem); +} + +PIO_WORKITEM STDCALL +IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject) +{ + PIO_WORKITEM IoWorkItem = NULL; + + IoWorkItem = + ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_WORKITEM), TAG_IOWI); + if (IoWorkItem == NULL) + { + return(NULL); + } + RtlZeroMemory(IoWorkItem, sizeof(IO_WORKITEM)); + IoWorkItem->DeviceObject = DeviceObject; + return(IoWorkItem); +} + +/* EOF */ diff --git a/ntoskrnl/io/irp.c b/ntoskrnl/io/irp.c new file mode 100644 index 0000000..ae8f6be --- /dev/null +++ b/ntoskrnl/io/irp.c @@ -0,0 +1,397 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/irp.c + * PURPOSE: Handle IRPs + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 24/05/98: Created + */ + +/* NOTES ******************************************************************* + * + * Layout of an IRP + * + * ################ + * # Headers # + * ################ + * # # + * # Variable # + * # length list # + * # of io stack # + * # locations # + * # # + * ################ + * + * + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_IRP TAG('I', 'R', 'P', ' ') + + +/* FUNCTIONS ****************************************************************/ + + +VOID STDCALL +IoFreeIrp(PIRP Irp) +/* + * FUNCTION: Releases a caller allocated irp + * ARGUMENTS: + * Irp = Irp to free + */ +{ + ExFreePool(Irp); +} + + +PIRP STDCALL +IoMakeAssociatedIrp(PIRP Irp, + CCHAR StackSize) +/* + * FUNCTION: Allocates and initializes an irp to associated with a master irp + * ARGUMENTS: + * Irp = Master irp + * StackSize = Number of stack locations to be allocated in the irp + * RETURNS: The irp allocated + */ +{ + PIRP AssocIrp; + + AssocIrp = IoAllocateIrp(StackSize,FALSE); + UNIMPLEMENTED; +} + + +VOID STDCALL +IoInitializeIrp(PIRP Irp, + USHORT PacketSize, + CCHAR StackSize) +/* + * FUNCTION: Initalizes an irp allocated by the caller + * ARGUMENTS: + * Irp = IRP to initalize + * PacketSize = Size in bytes of the IRP + * StackSize = Number of stack locations in the IRP + */ +{ + assert(Irp != NULL); + + memset(Irp, 0, PacketSize); + Irp->Size = PacketSize; + Irp->StackCount = StackSize; + Irp->CurrentLocation = StackSize; + Irp->Tail.Overlay.CurrentStackLocation = &Irp->Stack[(ULONG)StackSize]; +} + + +NTSTATUS FASTCALL +IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Sends an IRP to the next lower driver + */ +{ + NTSTATUS Status; + PDRIVER_OBJECT DriverObject; + PIO_STACK_LOCATION Param; + + DPRINT("IofCallDriver(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); + + assert(Irp); + assert(DeviceObject); + + DriverObject = DeviceObject->DriverObject; + + assert(DriverObject); + + Param = IoGetNextIrpStackLocation(Irp); + + DPRINT("IrpSp 0x%X\n", Param); + + Irp->Tail.Overlay.CurrentStackLocation--; + Irp->CurrentLocation--; + + DPRINT("MajorFunction %d\n", Param->MajorFunction); + DPRINT("DriverObject->MajorFunction[Param->MajorFunction] %x\n", + DriverObject->MajorFunction[Param->MajorFunction]); + Status = DriverObject->MajorFunction[Param->MajorFunction](DeviceObject, + Irp); + + return(Status); +} + + +NTSTATUS +STDCALL +IoCallDriver (PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + return(IofCallDriver(DeviceObject, + Irp)); +} + + +PIRP STDCALL +IoAllocateIrp(CCHAR StackSize, + BOOLEAN ChargeQuota) +/* + * FUNCTION: Allocates an IRP + * ARGUMENTS: + * StackSize = the size of the stack required for the irp + * ChargeQuota = Charge allocation to current threads quota + * RETURNS: Irp allocated + */ +{ + PIRP Irp; + +#if 0 + DbgPrint("IoAllocateIrp(StackSize %d ChargeQuota %d)\n", + StackSize, + ChargeQuota); + KeDumpStackFrames(0,8); +#endif + + if (ChargeQuota) + { +// Irp = ExAllocatePoolWithQuota(NonPagedPool,IoSizeOfIrp(StackSize)); + Irp = ExAllocatePoolWithTag(NonPagedPool, + IoSizeOfIrp(StackSize), + TAG_IRP); + } + else + { + Irp = ExAllocatePoolWithTag(NonPagedPool, + IoSizeOfIrp(StackSize), + TAG_IRP); + } + + if (Irp==NULL) + { + return(NULL); + } + + IoInitializeIrp(Irp, + IoSizeOfIrp(StackSize), + StackSize); + +// DPRINT("Irp %x Irp->StackPtr %d\n", Irp, Irp->CurrentLocation); + + return(Irp); +} + + +VOID STDCALL +IopCompleteRequest(struct _KAPC* Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) +{ + DPRINT("IopCompleteRequest(Apc %x, SystemArgument1 %x, (*SystemArgument1) %x\n", + Apc, + SystemArgument1, + *SystemArgument1); + IoSecondStageCompletion((PIRP)(*SystemArgument1), + (KPRIORITY)(*SystemArgument2)); +} + + +VOID FASTCALL +IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost) +/* + * FUNCTION: Indicates the caller has finished all processing for a given + * I/O request and is returning the given IRP to the I/O manager + * ARGUMENTS: + * Irp = Irp to be cancelled + * PriorityBoost = Increment by which to boost the priority of the + * thread making the request + */ +{ + unsigned int i; + NTSTATUS Status; + + DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n", + Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread()); + + for (i=Irp->CurrentLocation;iStackCount;i++) + { + if (Irp->Stack[i].CompletionRoutine != NULL) + { + Status = Irp->Stack[i].CompletionRoutine( + Irp->Stack[i].DeviceObject, + Irp, + Irp->Stack[i].CompletionContext); + if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + return; + } + } + if (Irp->Stack[i].Control & SL_PENDING_RETURNED) + { + Irp->PendingReturned = TRUE; + } + if (Irp->CurrentLocation < Irp->StackCount - 1) + { + IoSkipCurrentIrpStackLocation(Irp); + } + } + if (Irp->PendingReturned) + { + DPRINT("Dispatching APC\n"); + KeInitializeApc(&Irp->Tail.Apc, + &Irp->Tail.Overlay.Thread->Tcb, + 0, + IopCompleteRequest, + NULL, + (PKNORMAL_ROUTINE) + NULL, + KernelMode, + NULL); + KeInsertQueueApc(&Irp->Tail.Apc, + (PVOID)Irp, + (PVOID)(ULONG)PriorityBoost, + KernelMode); + DPRINT("Finished dispatching APC\n"); + } + else + { + DPRINT("Calling completion routine directly\n"); + IoSecondStageCompletion(Irp,PriorityBoost); + DPRINT("Finished completition routine\n"); + } +} + + +VOID STDCALL +IoCompleteRequest(PIRP Irp, + CCHAR PriorityBoost) +{ + IofCompleteRequest(Irp, + PriorityBoost); +} + + +/********************************************************************** + * NAME EXPORTED + * IoIsOperationSynchronous@4 + * + * DESCRIPTION + * Check if the I/O operation associated with the given IRP + * is synchronous. + * + * ARGUMENTS + * Irp Packet to check. + * + * RETURN VALUE + * TRUE if Irp's operation is synchronous; otherwise FALSE. + */ +BOOLEAN STDCALL +IoIsOperationSynchronous(IN PIRP Irp) +{ + PFILE_OBJECT FileObject = NULL; + ULONG Flags = 0; + + /* Check the FILE_OBJECT's flags first. */ + FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject; + if (!(FO_SYNCHRONOUS_IO & FileObject->Flags)) + { + /* Check IRP's flags. */ + Flags = Irp->Flags; + if (!((IRP_SYNCHRONOUS_API | IRP_SYNCHRONOUS_PAGING_IO) & Flags)) + { + return(FALSE); + } + } + + /* Check more IRP's flags. */ + Flags = Irp->Flags; + if (!(IRP_PAGING_IO & Flags) + || (IRP_SYNCHRONOUS_PAGING_IO & Flags)) + { + return(TRUE); + } + + /* Otherwise, it is an asynchronous operation. */ + return(FALSE); +} + + +VOID STDCALL +IoEnqueueIrp(IN PIRP Irp) +{ + UNIMPLEMENTED; +} + + +VOID STDCALL +IoSetTopLevelIrp(IN PIRP Irp) +{ + PETHREAD Thread; + + Thread = PsGetCurrentThread(); + Thread->TopLevelIrp->TopLevelIrp = Irp; +} + + +PIRP STDCALL +IoGetTopLevelIrp(VOID) +{ + return(PsGetCurrentThread()->TopLevelIrp->TopLevelIrp); +} + + +VOID STDCALL +IoQueueThreadIrp(IN PIRP Irp) +{ + UNIMPLEMENTED; +} + +/* +NTSTATUS +STDCALL +IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable) +{ + UNIMPLEMENTED; + return 0; +} + +NTSTATUS +STDCALL +IoGetDeviceProperty( + IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_REGISTRY_PROPERTY DeviceProperty, + IN ULONG BufferLength, + OUT PVOID PropertyBuffer, + OUT PULONG ResultLength) +{ + UNIMPLEMENTED; + return 0; +} + +NTSTATUS +STDCALL +IoOpenDeviceRegistryKey( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DevInstKeyType, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE DevInstRegKey) +{ + UNIMPLEMENTED; + return 0; +} + */ +/* EOF */ diff --git a/ntoskrnl/io/lock.c b/ntoskrnl/io/lock.c new file mode 100644 index 0000000..f27ca8d --- /dev/null +++ b/ntoskrnl/io/lock.c @@ -0,0 +1,49 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/bug.c + * PURPOSE: Graceful system shutdown if a bug is detected + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +NtLockFile ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + IN PULONG Key, + IN BOOLEAN FailImmediatedly, + IN BOOLEAN ExclusiveLock + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtUnlockFile ( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER ByteOffset, + IN PLARGE_INTEGER Length, + OUT PULONG Key OPTIONAL + ) +{ + UNIMPLEMENTED; +} diff --git a/ntoskrnl/io/mailslot.c b/ntoskrnl/io/mailslot.c new file mode 100644 index 0000000..93d9c7e --- /dev/null +++ b/ntoskrnl/io/mailslot.c @@ -0,0 +1,67 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/bug.c + * PURPOSE: Graceful system shutdown if a bug is detected + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + Changed NtCreateMailslotFile + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtCreateMailslotFile(OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG CreateOptions, + IN ULONG Param, /* FIXME: ??? */ + IN ULONG MaxMessageSize, + IN PLARGE_INTEGER TimeOut) +{ + IO_MAILSLOT_CREATE_BUFFER Buffer; + + DPRINT("NtCreateMailslotFile(FileHandle %x, DesiredAccess %x, " + "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n", + FileHandle,DesiredAccess,ObjectAttributes, + ObjectAttributes->ObjectName->Buffer); + + assert_irql(PASSIVE_LEVEL); + + if (TimeOut != NULL) + { + Buffer.TimeOut.QuadPart = TimeOut->QuadPart; + } + else + { + Buffer.TimeOut.QuadPart = 0; + } + Buffer.Param = Param; /* FIXME: ??? */ + Buffer.MaxMessageSize = MaxMessageSize; + + return IoCreateFile(FileHandle, + DesiredAccess, + ObjectAttributes, + IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, + CreateOptions, + NULL, + 0, + CreateFileTypeMailslot, + (PVOID)&Buffer, + 0); +} + +/* EOF */ diff --git a/ntoskrnl/io/mdl.c b/ntoskrnl/io/mdl.c new file mode 100644 index 0000000..0c6cb8d --- /dev/null +++ b/ntoskrnl/io/mdl.c @@ -0,0 +1,85 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/mdl.c + * PURPOSE: Io manager mdl functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_MDL TAG('M', 'D', 'L', ' ') + +/* FUNCTIONS *****************************************************************/ + +PMDL +STDCALL +IoAllocateMdl(PVOID VirtualAddress, + ULONG Length, + BOOLEAN SecondaryBuffer, + BOOLEAN ChargeQuota, + PIRP Irp) +{ + PMDL Mdl; + + if (ChargeQuota) + { +// Mdl = ExAllocatePoolWithQuota(NonPagedPool, +// MmSizeOfMdl(VirtualAddress,Length)); + Mdl = ExAllocatePoolWithTag(NonPagedPool, + MmSizeOfMdl(VirtualAddress,Length), + TAG_MDL); + } + else + { + Mdl = ExAllocatePoolWithTag(NonPagedPool, + MmSizeOfMdl(VirtualAddress,Length), + TAG_MDL); + } + MmInitializeMdl(Mdl,VirtualAddress,Length); + if (Irp!=NULL && !SecondaryBuffer) + { + Irp->MdlAddress = Mdl; + } + return(Mdl); +} + +VOID +STDCALL +IoBuildPartialMdl(PMDL SourceMdl, + PMDL TargetMdl, + PVOID VirtualAddress, + ULONG Length) +{ + PULONG TargetPages = (PULONG)(TargetMdl + 1); + PULONG SourcePages = (PULONG)(SourceMdl + 1); + ULONG Va; + ULONG Delta = (PAGE_ROUND_DOWN(VirtualAddress) - (ULONG)SourceMdl->StartVa)/ + PAGE_SIZE; + + for (Va = 0; Va < (PAGE_ROUND_UP(Length)/PAGE_SIZE); Va++) + { + TargetPages[Va] = SourcePages[Va+Delta]; + } +} + +VOID STDCALL +IoFreeMdl(PMDL Mdl) +{ + MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl), Mdl); + MmUnlockPages(Mdl); + ExFreePool(Mdl); +} + + +/* EOF */ diff --git a/ntoskrnl/io/npipe.c b/ntoskrnl/io/npipe.c new file mode 100644 index 0000000..e45596a --- /dev/null +++ b/ntoskrnl/io/npipe.c @@ -0,0 +1,76 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/npipe.c + * PURPOSE: Named pipe helper function + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtCreateNamedPipeFile(PHANDLE FileHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG ShareAccess, + ULONG CreateDisposition, + ULONG CreateOptions, + BOOLEAN WriteModeMessage, + BOOLEAN ReadModeMessage, + BOOLEAN NonBlocking, + ULONG MaxInstances, + ULONG InBufferSize, + ULONG OutBufferSize, + PLARGE_INTEGER TimeOut) +{ + IO_PIPE_CREATE_BUFFER Buffer; + + DPRINT("NtCreateNamedPipeFile(FileHandle %x, DesiredAccess %x, " + "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n", + FileHandle,DesiredAccess,ObjectAttributes, + ObjectAttributes->ObjectName->Buffer); + + assert_irql(PASSIVE_LEVEL); + + if (TimeOut != NULL) + { + Buffer.TimeOut.QuadPart = TimeOut->QuadPart; + } + else + { + Buffer.TimeOut.QuadPart = 0; + } + Buffer.WriteModeMessage = WriteModeMessage; + Buffer.ReadModeMessage = ReadModeMessage; + Buffer.NonBlocking = NonBlocking; + Buffer.MaxInstances = MaxInstances; + Buffer.InBufferSize = InBufferSize; + Buffer.OutBufferSize = OutBufferSize; + + return IoCreateFile(FileHandle, + DesiredAccess, + ObjectAttributes, + IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + ShareAccess, + CreateDisposition, + CreateOptions, + NULL, + 0, + CreateFileTypeNamedPipe, + (PVOID)&Buffer, + 0); +} + +/* EOF */ diff --git a/ntoskrnl/io/page.c b/ntoskrnl/io/page.c new file mode 100644 index 0000000..c3e5f3e --- /dev/null +++ b/ntoskrnl/io/page.c @@ -0,0 +1,128 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/page.c + * PURPOSE: + * PROGRAMMER: + * UPDATE HISTORY: + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +IoPageWrite(PFILE_OBJECT FileObject, + PMDL Mdl, + PLARGE_INTEGER Offset, + PKEVENT Event, + PIO_STATUS_BLOCK StatusBlock) +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + + DPRINT("IoPageWrite(FileObject %x, Mdl %x)\n", + FileObject, Mdl); + + Irp = IoBuildSynchronousFsdRequestWithMdl(IRP_MJ_WRITE, + FileObject->DeviceObject, + Mdl, + Offset, + Event, + StatusBlock, + TRUE); + if (Irp == NULL) + { + return (STATUS_INSUFFICIENT_RESOURCES); + } + Irp->Flags = IRP_NOCACHE|IRP_PAGING_IO; + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + DPRINT("Before IoCallDriver\n"); + Status = IofCallDriver(FileObject->DeviceObject,Irp); + DPRINT("Status %d STATUS_PENDING %d\n",Status,STATUS_PENDING); + return(Status); +} + + +NTSTATUS STDCALL +IoPageRead(PFILE_OBJECT FileObject, + PMDL Mdl, + PLARGE_INTEGER Offset, + PKEVENT Event, + PIO_STATUS_BLOCK StatusBlock) +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + + DPRINT("IoPageRead(FileObject %x, Mdl %x)\n", + FileObject, Mdl); + + Irp = IoBuildSynchronousFsdRequestWithMdl(IRP_MJ_READ, + FileObject->DeviceObject, + Mdl, + Offset, + Event, + StatusBlock, + TRUE); + if (Irp == NULL) + { + return (STATUS_INSUFFICIENT_RESOURCES); + } + Irp->Flags = IRP_NOCACHE|IRP_PAGING_IO; + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + DPRINT("Before IoCallDriver\n"); + Status = IofCallDriver(FileObject->DeviceObject, Irp); + DPRINT("Status %d STATUS_PENDING %d\n",Status,STATUS_PENDING); + + return(Status); +} + + +NTSTATUS STDCALL +IoSynchronousPageWrite (PFILE_OBJECT FileObject, + PMDL Mdl, + PLARGE_INTEGER Offset, + PKEVENT Event, + PIO_STATUS_BLOCK StatusBlock) +{ + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + NTSTATUS Status; + + DPRINT("IoSynchronousPageWrite(FileObject %x, Mdl %x)\n", + FileObject, Mdl); + + Irp = IoBuildSynchronousFsdRequestWithMdl(IRP_MJ_WRITE, + FileObject->DeviceObject, + Mdl, + Offset, + Event, + StatusBlock, + TRUE); + if (Irp == NULL) + { + return (STATUS_INSUFFICIENT_RESOURCES); + } + Irp->Flags = IRP_NOCACHE|IRP_PAGING_IO|IRP_SYNCHRONOUS_PAGING_IO; + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + DPRINT("Before IoCallDriver\n"); + Status = IofCallDriver(FileObject->DeviceObject,Irp); + DPRINT("Status %d STATUS_PENDING %d\n",Status,STATUS_PENDING); + return(Status); +} + + +/* EOF */ diff --git a/ntoskrnl/io/parttab.c b/ntoskrnl/io/parttab.c new file mode 100644 index 0000000..81290f1 --- /dev/null +++ b/ntoskrnl/io/parttab.c @@ -0,0 +1,62 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/parttab.c + * PURPOSE: Handling fixed disks (partition table functions) + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + * 2000-03-25 (ea) + * Moved here from ntoskrnl/io/fdisk.c + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +IoReadPartitionTable(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + BOOLEAN ReturnRecognizedPartitions, + PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) +{ + return HalDispatchTable.HalIoReadPartitionTable(DeviceObject, + SectorSize, + ReturnRecognizedPartitions, + PartitionBuffer); +} + + +NTSTATUS STDCALL +IoSetPartitionInformation(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG PartitionNumber, + ULONG PartitionType) +{ + return HalDispatchTable.HalIoSetPartitionInformation(DeviceObject, + SectorSize, + PartitionNumber, + PartitionType); +} + + +NTSTATUS STDCALL +IoWritePartitionTable(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG SectorsPerTrack, + ULONG NumberOfHeads, + PDRIVE_LAYOUT_INFORMATION PartitionBuffer) +{ + return HalDispatchTable.HalIoWritePartitionTable(DeviceObject, + SectorSize, + SectorsPerTrack, + NumberOfHeads, + PartitionBuffer); +} + +/* EOF */ diff --git a/ntoskrnl/io/pnpmgr.c b/ntoskrnl/io/pnpmgr.c new file mode 100644 index 0000000..90c52d1 --- /dev/null +++ b/ntoskrnl/io/pnpmgr.c @@ -0,0 +1,1217 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnpmgr.c + * PURPOSE: Initializes the PnP manager + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 16/04/2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +//#include +#ifdef DEFINE_GUID +DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73); +DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18); +#endif // DEFINE_GUID + + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +PDEVICE_NODE IopRootDeviceNode; +KSPIN_LOCK IopDeviceTreeLock; + +/* DATA **********************************************************************/ + +PDRIVER_OBJECT IopRootDriverObject; + +/* FUNCTIONS *****************************************************************/ + +VOID +STDCALL +IoInitializeRemoveLockEx( + IN PIO_REMOVE_LOCK Lock, + IN ULONG AllocateTag, + IN ULONG MaxLockedMinutes, + IN ULONG HighWatermark, + IN ULONG RemlockSize) +{ +} + +NTSTATUS +STDCALL +IoAcquireRemoveLockEx( + IN PIO_REMOVE_LOCK RemoveLock, + IN OPTIONAL PVOID Tag, + IN LPCSTR File, + IN ULONG Line, + IN ULONG RemlockSize) +{ + return STATUS_NOT_IMPLEMENTED; +} + +VOID +STDCALL +IoReleaseRemoveLockEx( + IN PIO_REMOVE_LOCK RemoveLock, + IN PVOID Tag, + IN ULONG RemlockSize) +{ +} + +VOID +STDCALL +IoReleaseRemoveLockAndWaitEx( + IN PIO_REMOVE_LOCK RemoveLock, + IN PVOID Tag, + IN ULONG RemlockSize) +{ +} + +VOID +STDCALL +IoAdjustPagingPathCount( + IN PLONG Count, + IN BOOLEAN Increment) +{ +} + +NTSTATUS +STDCALL +IoGetDeviceInterfaceAlias( + IN PUNICODE_STRING SymbolicLinkName, + IN CONST GUID *AliasInterfaceClassGuid, + OUT PUNICODE_STRING AliasSymbolicLinkName) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoGetDeviceInterfaces( + IN CONST GUID *InterfaceClassGuid, + IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, + IN ULONG Flags, + OUT PWSTR *SymbolicLinkList) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoGetDeviceProperty( + IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_REGISTRY_PROPERTY DeviceProperty, + IN ULONG BufferLength, + OUT PVOID PropertyBuffer, + OUT PULONG ResultLength) +{ + return STATUS_NOT_IMPLEMENTED; +} + +VOID +STDCALL +IoInvalidateDeviceRelations( + IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_RELATION_TYPE Type) +{ +} + +VOID +STDCALL +IoInvalidateDeviceState( + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ +} + +NTSTATUS +STDCALL +IoOpenDeviceInterfaceRegistryKey( + IN PUNICODE_STRING SymbolicLinkName, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE DeviceInterfaceKey) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoOpenDeviceRegistryKey( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DevInstKeyType, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE DevInstRegKey) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoRegisterDeviceInterface( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN CONST GUID *InterfaceClassGuid, + IN PUNICODE_STRING ReferenceString OPTIONAL, + OUT PUNICODE_STRING SymbolicLinkName) +{ + PWCHAR KeyNameString = L"\\Device\\Serenum"; + + if (IsEqualGUID(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR)) { + RtlInitUnicodeString(SymbolicLinkName, KeyNameString); + return STATUS_SUCCESS; + } + return STATUS_INVALID_DEVICE_REQUEST; +// return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoRegisterPlugPlayNotification( + IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, + IN ULONG EventCategoryFlags, + IN PVOID EventCategoryData OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine, + IN PVOID Context, + OUT PVOID *NotificationEntry) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoReportDetectedDevice( + IN PDRIVER_OBJECT DriverObject, + IN INTERFACE_TYPE LegacyBusType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PCM_RESOURCE_LIST ResourceList, + IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL, + IN BOOLEAN ResourceAssigned, + IN OUT PDEVICE_OBJECT *DeviceObject) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoReportResourceForDetection( + IN PDRIVER_OBJECT DriverObject, + IN PCM_RESOURCE_LIST DriverList OPTIONAL, + IN ULONG DriverListSize OPTIONAL, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN PCM_RESOURCE_LIST DeviceList OPTIONAL, + IN ULONG DeviceListSize OPTIONAL, + OUT PBOOLEAN ConflictDetected) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoReportTargetDeviceChange( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PVOID NotificationStructure) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoReportTargetDeviceChangeAsynchronous( + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PVOID NotificationStructure, + IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, + IN PVOID Context OPTIONAL) +{ + return STATUS_NOT_IMPLEMENTED; +} + +VOID +STDCALL +IoRequestDeviceEject( + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ +} + +NTSTATUS +STDCALL +IoSetDeviceInterfaceState( + IN PUNICODE_STRING SymbolicLinkName, + IN BOOLEAN Enable) +{ + return STATUS_SUCCESS; + +// return STATUS_OBJECT_NAME_EXISTS; +// return STATUS_OBJECT_NAME_NOT_FOUND; +// return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +IoUnregisterPlugPlayNotification( + IN PVOID NotificationEntry) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +BOOLEAN +IopCreateUnicodeString( + PUNICODE_STRING Destination, + PWSTR Source, + POOL_TYPE PoolType) +{ + ULONG Length; + + if (!Source) + { + RtlInitUnicodeString(Destination, NULL); + return TRUE; + } + + Length = (wcslen(Source) + 1) * sizeof(WCHAR); + + Destination->Buffer = ExAllocatePool(PoolType, Length); + + if (Destination->Buffer == NULL) + { + return FALSE; + } + + RtlCopyMemory(Destination->Buffer, Source, Length); + + Destination->MaximumLength = Length; + + Destination->Length = Length - sizeof(WCHAR); + + return TRUE; +} + +NTSTATUS +IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) +{ + KIRQL OldIrql; + + assert(PopSystemPowerDeviceNode); + + KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql); + *DeviceObject = PopSystemPowerDeviceNode->Pdo; + KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql); + + return STATUS_SUCCESS; +} + +/********************************************************************** + * DESCRIPTION + * Creates a device node + * + * ARGUMENTS + * ParentNode = Pointer to parent device node + * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL + * to have the root device node create one + * (eg. for legacy drivers) + * DeviceNode = Pointer to storage for created device node + * + * RETURN VALUE + * Status + */ +NTSTATUS +IopCreateDeviceNode(PDEVICE_NODE ParentNode, + PDEVICE_OBJECT PhysicalDeviceObject, + PDEVICE_NODE *DeviceNode) +{ + PDEVICE_NODE Node; + NTSTATUS Status; + KIRQL OldIrql; + + DPRINT("ParentNode %x PhysicalDeviceObject %x\n", + ParentNode, PhysicalDeviceObject); + + Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE)); + if (!Node) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(Node, sizeof(DEVICE_NODE)); + + if (!PhysicalDeviceObject) + { + Status = PnpRootCreateDevice(&PhysicalDeviceObject); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Node); + return Status; + } + + /* This is for drivers passed on the command line to ntoskrnl.exe */ + IopDeviceNodeSetFlag(Node, DNF_STARTED); + IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER); + } + + Node->Pdo = PhysicalDeviceObject; + + if (ParentNode) + { + KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql); + Node->Parent = ParentNode; + Node->NextSibling = ParentNode->Child; + if (ParentNode->Child != NULL) + { + ParentNode->Child->PrevSibling = Node; + } + ParentNode->Child = Node; + KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql); + } + + *DeviceNode = Node; + + return STATUS_SUCCESS; +} + +NTSTATUS +IopFreeDeviceNode(PDEVICE_NODE DeviceNode) +{ + KIRQL OldIrql; + + /* All children must be deleted before a parent is deleted */ + assert(!DeviceNode->Child); + + KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql); + + assert(DeviceNode->Pdo); + + ObDereferenceObject(DeviceNode->Pdo); + + /* Unlink from parent if it exists */ + + if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode)) + { + DeviceNode->Parent->Child = DeviceNode->NextSibling; + } + + /* Unlink from sibling list */ + + if (DeviceNode->PrevSibling) + { + DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling; + } + + if (DeviceNode->NextSibling) + { + DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling; + } + + KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql); + + RtlFreeUnicodeString(&DeviceNode->InstancePath); + + RtlFreeUnicodeString(&DeviceNode->ServiceName); + + if (DeviceNode->CapabilityFlags) + { + ExFreePool(DeviceNode->CapabilityFlags); + } + + if (DeviceNode->CmResourceList) + { + ExFreePool(DeviceNode->CmResourceList); + } + + if (DeviceNode->BootResourcesList) + { + ExFreePool(DeviceNode->BootResourcesList); + } + + if (DeviceNode->ResourceRequirementsList) + { + ExFreePool(DeviceNode->ResourceRequirementsList); + } + + RtlFreeUnicodeString(&DeviceNode->DeviceID); + + RtlFreeUnicodeString(&DeviceNode->InstanceID); + + RtlFreeUnicodeString(&DeviceNode->HardwareIDs); + + RtlFreeUnicodeString(&DeviceNode->CompatibleIDs); + + RtlFreeUnicodeString(&DeviceNode->DeviceText); + + RtlFreeUnicodeString(&DeviceNode->DeviceTextLocation); + + if (DeviceNode->BusInformation) + { + ExFreePool(DeviceNode->BusInformation); + } + + ExFreePool(DeviceNode); + + return STATUS_SUCCESS; +} + +NTSTATUS +IopInitiatePnpIrp( + PDEVICE_OBJECT DeviceObject, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG MinorFunction, + PIO_STACK_LOCATION Stack OPTIONAL) +{ + PDEVICE_OBJECT TopDeviceObject; + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + /* Always call the top of the device stack */ + TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); + + KeInitializeEvent( + &Event, + NotificationEvent, + FALSE); + + /* PNP IRPs are always initialized with a status code of + STATUS_NOT_IMPLEMENTED */ + IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED; + IoStatusBlock->Information = 0; + + Irp = IoBuildSynchronousFsdRequest( + IRP_MJ_PNP, + TopDeviceObject, + NULL, + 0, + NULL, + &Event, + IoStatusBlock); + + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->MinorFunction = MinorFunction; + + if (Stack) + { + RtlMoveMemory( + &IrpSp->Parameters, + &Stack->Parameters, + sizeof(Stack->Parameters)); + } + + Status = IoCallDriver(TopDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject( + &Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock->Status; + } + + ObDereferenceObject(TopDeviceObject); + + return Status; +} + + +NTSTATUS +IopQueryCapabilities( + PDEVICE_OBJECT Pdo, + PDEVICE_CAPABILITIES *Capabilities) +{ + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_CAPABILITIES Caps; + IO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n"); + + *Capabilities = NULL; + + Caps = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES)); + if (!Caps) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(Caps, sizeof(DEVICE_CAPABILITIES)); + Caps->Size = sizeof(DEVICE_CAPABILITIES); + Caps->Version = 1; + Caps->Address = -1; + Caps->UINumber = -1; + + Stack.Parameters.DeviceCapabilities.Capabilities = Caps; + + Status = IopInitiatePnpIrp( + Pdo, + &IoStatusBlock, + IRP_MN_QUERY_CAPABILITIES, + &Stack); + if (NT_SUCCESS(Status)) + { + *Capabilities = Caps; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + } + + return Status; +} + + +NTSTATUS +IopTraverseDeviceTreeNode( + PDEVICETREE_TRAVERSE_CONTEXT Context) +{ + PDEVICE_NODE ParentDeviceNode; + PDEVICE_NODE ChildDeviceNode; + NTSTATUS Status; + + /* Copy context data so we don't overwrite it in subsequent calls to this function */ + ParentDeviceNode = Context->DeviceNode; + + /* Call the action routine */ + Status = (Context->Action)(ParentDeviceNode, Context->Context); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Traversal of all children nodes */ + for (ChildDeviceNode = ParentDeviceNode->Child; + ChildDeviceNode != NULL; + ChildDeviceNode = ChildDeviceNode->NextSibling) + { + /* Pass the current device node to the action routine */ + Context->DeviceNode = ChildDeviceNode; + + Status = IopTraverseDeviceTreeNode(Context); + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + + return Status; +} + + +NTSTATUS +IopTraverseDeviceTree( + PDEVICETREE_TRAVERSE_CONTEXT Context) +{ + NTSTATUS Status; + + DPRINT("Context %x\n", Context); + + DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n", + Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context); + + /* Start from the specified device node */ + Context->DeviceNode = Context->FirstDeviceNode; + + /* Recursively traverse the device tree */ + Status = IopTraverseDeviceTreeNode(Context); + if (Status == STATUS_UNSUCCESSFUL) + { + /* The action routine just wanted to terminate the traversal with status + code STATUS_SUCCESS */ + Status = STATUS_SUCCESS; + } + + return Status; +} + + +NTSTATUS +IopActionInterrogateDeviceStack( + PDEVICE_NODE DeviceNode, + PVOID Context) +/* + * FUNCTION: Retrieve information for all (direct) child nodes of a parent node + * ARGUMENTS: + * DeviceNode = Pointer to device node + * Context = Pointer to parent node to retrieve child node information for + * NOTES: + * We only return a status code indicating an error (STATUS_UNSUCCESSFUL) + * when we reach a device node which is not a direct child of the device node + * for which we retrieve information of child nodes for. Any errors that occur + * is logged instead so that all child services have a chance of beeing + * interrogated. + */ +{ + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_NODE ParentDeviceNode; + WCHAR InstancePath[MAX_PATH]; + IO_STACK_LOCATION Stack; + NTSTATUS Status; + + DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context); + + DPRINT("PDO %x\n", DeviceNode->Pdo); + + + ParentDeviceNode = (PDEVICE_NODE)Context; + + /* We are called for the parent too, but we don't need to do special + handling for this node */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } + + /* Make sure this device node is a direct child of the parent device node + that is given as an argument */ + if (DeviceNode->Parent != ParentDeviceNode) + { + /* Stop the traversal immediately and indicate successful operation */ + DPRINT("Stop\n"); + return STATUS_UNSUCCESSFUL; + } + + + /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */ + + + DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n"); + + Stack.Parameters.QueryId.IdType = BusQueryDeviceID; + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_ID, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->DeviceID, + (LPWSTR)IoStatusBlock.Information); + + /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */ + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->DeviceID, NULL); + } + + + DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n"); + + Stack.Parameters.QueryId.IdType = BusQueryInstanceID; + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_ID, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->InstanceID, + (LPWSTR)IoStatusBlock.Information); + + /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */ + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->InstanceID, NULL); + } + + + /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */ + /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */ + + + Status = IopQueryCapabilities(DeviceNode->Pdo, &DeviceNode->CapabilityFlags); + if (NT_SUCCESS(Status)) + { + } + else + { + } + + + DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n"); + + Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription; + Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_DEVICE_TEXT, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->DeviceText, + (LPWSTR)IoStatusBlock.Information); + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->DeviceText, NULL); + } + + + DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n"); + + Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation; + Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_DEVICE_TEXT, + &Stack); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString( + &DeviceNode->DeviceTextLocation, + (LPWSTR)IoStatusBlock.Information); + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + RtlInitUnicodeString(&DeviceNode->DeviceTextLocation, NULL); + } + + + DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n"); + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_BUS_INFORMATION, + NULL); + if (NT_SUCCESS(Status)) + { + DeviceNode->BusInformation = + (PPNP_BUS_INFORMATION)IoStatusBlock.Information; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + DeviceNode->BusInformation = NULL; + } + + + DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n"); + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_RESOURCES, + NULL); + if (NT_SUCCESS(Status)) + { + DeviceNode->BootResourcesList = + (PCM_RESOURCE_LIST)IoStatusBlock.Information; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + DeviceNode->BootResourcesList = NULL; + } + + + DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n"); + + Status = IopInitiatePnpIrp( + DeviceNode->Pdo, + &IoStatusBlock, + IRP_MN_QUERY_RESOURCE_REQUIREMENTS, + NULL); + if (NT_SUCCESS(Status)) + { + DeviceNode->ResourceRequirementsList = + (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information; + } + else + { + DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); + DeviceNode->ResourceRequirementsList = NULL; + } + + + /* Assemble the instance path for the device */ + + wcscpy(InstancePath, DeviceNode->DeviceID.Buffer); + wcscat(InstancePath, L"\\"); + wcscat(InstancePath, DeviceNode->InstanceID.Buffer); + + if (!DeviceNode->CapabilityFlags->UniqueID) + { + DPRINT("Instance ID is not unique\n"); + /* FIXME: Add information from parent bus driver to InstancePath */ + } + + if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool)) { + DPRINT("No resources\n"); + /* FIXME: Cleanup and disable device */ + } + + DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer); + + return STATUS_SUCCESS; +} + + +NTSTATUS +IopActionConfigureChildServices( + PDEVICE_NODE DeviceNode, + PVOID Context) +/* + * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node + * ARGUMENTS: + * DeviceNode = Pointer to device node + * Context = Pointer to parent node to retrieve child node configuration for + * NOTES: + * We only return a status code indicating an error (STATUS_UNSUCCESSFUL) + * when we reach a device node which is not a direct child of the device + * node for which we configure child services for. Any errors that occur is + * logged instead so that all child services have a chance of beeing + * configured. + */ +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + PDEVICE_NODE ParentDeviceNode; + PUNICODE_STRING Service; + HANDLE KeyHandle; + NTSTATUS Status; + + DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context); + + ParentDeviceNode = (PDEVICE_NODE)Context; + + /* We are called for the parent too, but we don't need to do special + handling for this node */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } + + /* Make sure this device node is a direct child of the parent device node + that is given as an argument */ + if (DeviceNode->Parent != ParentDeviceNode) + { + /* Stop the traversal immediately and indicate successful operation */ + DPRINT("Stop\n"); + return STATUS_UNSUCCESSFUL; + } + + /* Retrieve configuration from Enum key */ + + Service = &DeviceNode->ServiceName; + + Status = RtlpGetRegistryHandle( + RTL_REGISTRY_ENUM, + DeviceNode->InstancePath.Buffer, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); + return Status; + } + + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + + RtlInitUnicodeString(Service, NULL); + + QueryTable[0].Name = L"Service"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = Service; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + NtClose(KeyHandle); + + DPRINT("RtlQueryRegistryValues() returned status %x\n", Status); + + if (!NT_SUCCESS(Status)) + { + /* FIXME: Log the error */ + CPRINT("Could not retrieve configuration for device %S (Status %x)\n", + DeviceNode->InstancePath.Buffer, Status); + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + return STATUS_SUCCESS; + } + + DPRINT("Got Service %S\n", Service->Buffer); + + return STATUS_SUCCESS; +} + + +NTSTATUS +IopActionInitChildServices( + PDEVICE_NODE DeviceNode, + PVOID Context) +/* + * FUNCTION: Initialize the service for all (direct) child nodes of a parent node + * ARGUMENTS: + * DeviceNode = Pointer to device node + * Context = Pointer to parent node to initialize child node services for + * NOTES: + * If the driver image for a service is not loaded and initialized + * it is done here too. + * We only return a status code indicating an error (STATUS_UNSUCCESSFUL) + * when we reach a device node which is not a direct child of the device + * node for which we initialize child services for. Any errors that occur is + * logged instead so that all child services have a chance of beeing + * initialized. + */ +{ + PDEVICE_NODE ParentDeviceNode; + NTSTATUS Status; + + DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context); + + ParentDeviceNode = (PDEVICE_NODE)Context; + + /* We are called for the parent too, but we don't need to do special + handling for this node */ + if (DeviceNode == ParentDeviceNode) + { + DPRINT("Success\n"); + return STATUS_SUCCESS; + } + + /* Make sure this device node is a direct child of the parent device node + that is given as an argument */ + if (DeviceNode->Parent != ParentDeviceNode) + { + /* Stop the traversal immediately and indicate successful operation */ + DPRINT("Stop\n"); + return STATUS_UNSUCCESSFUL; + } + + if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) && + !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) && + !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED)) + { + Status = IopInitializeDeviceNodeService(DeviceNode); + if (NT_SUCCESS(Status)) + { + IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + } + else + { + IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); + + /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */ + CPRINT("Initialization of service %S failed (Status %x)\n", + DeviceNode->ServiceName.Buffer, Status); + } + } + else + { + DPRINT("Service %S is disabled or already initialized\n", + DeviceNode->ServiceName.Buffer); + } + + return STATUS_SUCCESS; +} + + +NTSTATUS +IopInterrogateBusExtender( + PDEVICE_NODE DeviceNode, + PDEVICE_OBJECT Pdo, + BOOLEAN BootDriversOnly) +{ + DEVICETREE_TRAVERSE_CONTEXT Context; + PDEVICE_RELATIONS DeviceRelations; + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_NODE ChildDeviceNode; + IO_STACK_LOCATION Stack; + NTSTATUS Status; + ULONG i; + + DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode, Pdo, BootDriversOnly); + + DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n"); + + Stack.Parameters.QueryDeviceRelations.Type = BusRelations; + + Status = IopInitiatePnpIrp( + Pdo, + &IoStatusBlock, + IRP_MN_QUERY_DEVICE_RELATIONS, + &Stack); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopInitiatePnpIrp() failed\n"); + return Status; + } + + DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information; + + if ((!DeviceRelations) || (DeviceRelations->Count <= 0)) + { + DPRINT("No PDOs\n"); + if (DeviceRelations) + { + ExFreePool(DeviceRelations); + } + return STATUS_SUCCESS; + } + + DPRINT("Got %d PDOs\n", DeviceRelations->Count); + + /* Create device nodes for all discovered devices */ + for (i = 0; i < DeviceRelations->Count; i++) + { + Status = IopCreateDeviceNode( + DeviceNode, + DeviceRelations->Objects[i], + &ChildDeviceNode); + if (!NT_SUCCESS(Status)) + { + DPRINT("No resources\n"); + for (i = 0; i < DeviceRelations->Count; i++) + ObDereferenceObject(DeviceRelations->Objects[i]); + ExFreePool(DeviceRelations); + return STATUS_INSUFFICIENT_RESOURCES; + } + } + + ExFreePool(DeviceRelations); + + + /* Retrieve information about all discovered children from the bus driver */ + + IopInitDeviceTreeTraverseContext( + &Context, + DeviceNode, + IopActionInterrogateDeviceStack, + DeviceNode); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); + return Status; + } + + + /* Retrieve configuration from the registry for discovered children */ + + IopInitDeviceTreeTraverseContext( + &Context, + DeviceNode, + IopActionConfigureChildServices, + DeviceNode); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); + return Status; + } + + + /* Initialize services for discovered children */ + + IopInitDeviceTreeTraverseContext( + &Context, + DeviceNode, + IopActionInitChildServices, + DeviceNode); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); + return Status; + } + + return Status; +} + + +VOID IopLoadBootStartDrivers(VOID) +{ + IopInterrogateBusExtender( + IopRootDeviceNode, + IopRootDeviceNode->Pdo, + TRUE); +} + +VOID PnpInit(VOID) +{ + PDEVICE_OBJECT Pdo; + NTSTATUS Status; + + DPRINT("Called\n"); + + KeInitializeSpinLock(&IopDeviceTreeLock); + + Status = IopCreateDriverObject(&IopRootDriverObject, NULL, FALSE); + if (!NT_SUCCESS(Status)) + { + CPRINT("IoCreateDriverObject() failed\n"); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + Status = IoCreateDevice( + IopRootDriverObject, + 0, + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Pdo); + if (!NT_SUCCESS(Status)) + { + CPRINT("IoCreateDevice() failed\n"); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + Status = IopCreateDeviceNode( + NULL, + Pdo, + &IopRootDeviceNode); + if (!NT_SUCCESS(Status)) + { + CPRINT("Insufficient resources\n"); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + IopRootDeviceNode->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + + IopRootDeviceNode->DriverObject = IopRootDriverObject; + + PnpRootDriverEntry(IopRootDriverObject, NULL); + + IopRootDriverObject->DriverExtension->AddDevice( + IopRootDriverObject, + IopRootDeviceNode->Pdo); +} + +/* EOF */ diff --git a/ntoskrnl/io/pnproot.c b/ntoskrnl/io/pnproot.c new file mode 100644 index 0000000..65a05a2 --- /dev/null +++ b/ntoskrnl/io/pnproot.c @@ -0,0 +1,965 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/pnproot.c + * PURPOSE: PnP manager root device + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 16/04/2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define ENUM_NAME_ROOT L"Root" + +/* DATA **********************************************************************/ + +typedef struct _PNPROOT_DEVICE { + // Entry on device list + LIST_ENTRY ListEntry; + // Physical Device Object of device + PDEVICE_OBJECT Pdo; + // Service name + UNICODE_STRING ServiceName; + // Device ID + UNICODE_STRING DeviceID; + // Instance ID + UNICODE_STRING InstanceID; + // Device description + UNICODE_STRING DeviceDescription; +} PNPROOT_DEVICE, *PPNPROOT_DEVICE; + +typedef enum { + dsStopped, + dsStarted, + dsPaused, + dsRemoved, + dsSurpriseRemoved +} PNPROOT_DEVICE_STATE; + + +typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION +{ + // Pointer to device object, this device extension is associated with + PDEVICE_OBJECT DeviceObject; + // Wether this device extension is for an FDO or PDO + BOOLEAN IsFDO; + // Wether the device is removed + BOOLEAN Removed; + // Current device power state for the device + DEVICE_POWER_STATE DevicePowerState; +} __attribute((packed)) PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION; + +/* Physical Device Object device extension for a child device */ +typedef struct _PNPROOT_PDO_DEVICE_EXTENSION +{ + // Common device data + PNPROOT_COMMON_DEVICE_EXTENSION Common; + // Device ID + UNICODE_STRING DeviceID; + // Instance ID + UNICODE_STRING InstanceID; +} __attribute((packed)) PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION; + +/* Functional Device Object device extension for the PCI driver device object */ +typedef struct _PNPROOT_FDO_DEVICE_EXTENSION +{ + // Common device data + PNPROOT_COMMON_DEVICE_EXTENSION Common; + // Physical Device Object + PDEVICE_OBJECT Pdo; + // Lower device object + PDEVICE_OBJECT Ldo; + // Current state of the driver + PNPROOT_DEVICE_STATE State; + // Namespace device list + LIST_ENTRY DeviceListHead; + // Number of (not removed) devices in device list + ULONG DeviceListCount; + // Lock for namespace device list + // FIXME: Use fast mutex instead? + KSPIN_LOCK DeviceListLock; +} __attribute((packed)) PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION; + + +PDEVICE_OBJECT PnpRootDeviceObject; + + +/* FUNCTIONS *****************************************************************/ + +/* Physical Device Object routines */ + +NTSTATUS +PnpRootCreateDevice( + PDEVICE_OBJECT *PhysicalDeviceObject) +{ + PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; + PPNPROOT_DEVICE Device; + NTSTATUS Status; + + /* This function should be obsoleted soon */ + + DPRINT("Called\n"); + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension; + + Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE)); + if (!Device) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE)); + + Status = IoCreateDevice( + PnpRootDeviceObject->DriverObject, + sizeof(PNPROOT_PDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Device->Pdo); + if (!NT_SUCCESS(Status)) { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + ExFreePool(Device); + return Status; + } + + Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + + Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; + + //Device->Pdo->Flags |= DO_POWER_PAGABLE; + + PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; + + RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION)); + + PdoDeviceExtension->Common.IsFDO = FALSE; + + PdoDeviceExtension->Common.DeviceObject = Device->Pdo; + + PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0; + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->DeviceID, + ENUM_NAME_ROOT \ + L"\\LEGACY_UNKNOWN", + PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->InstanceID, + L"0000", + PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + ExInterlockedInsertTailList( + &DeviceExtension->DeviceListHead, + &Device->ListEntry, + &DeviceExtension->DeviceListLock); + + DeviceExtension->DeviceListCount++; + + *PhysicalDeviceObject = Device->Pdo; + + return STATUS_SUCCESS; +} + + +NTSTATUS +PdoQueryId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; + UNICODE_STRING String; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + +// Irp->IoStatus.Information = 0; + + Status = STATUS_SUCCESS; + + RtlInitUnicodeString(&String, NULL); + + switch (IrpSp->Parameters.QueryId.IdType) { + case BusQueryDeviceID: + Status = IopCreateUnicodeString( + &String, + DeviceExtension->DeviceID.Buffer, + PagedPool); + + DPRINT("DeviceID: %S\n", String.Buffer); + + Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; + break; + + case BusQueryHardwareIDs: + case BusQueryCompatibleIDs: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case BusQueryInstanceID: + Status = IopCreateUnicodeString( + &String, + DeviceExtension->InstanceID.Buffer, + PagedPool); + + DPRINT("InstanceID: %S\n", String.Buffer); + + Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; + break; + + case BusQueryDeviceSerialNumber: + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; +} + + +NTSTATUS +PnpRootPdoPnpControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { +#if 0 + case IRP_MN_CANCEL_REMOVE_DEVICE: + break; + + case IRP_MN_CANCEL_STOP_DEVICE: + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + break; + + case IRP_MN_EJECT: + break; + + case IRP_MN_QUERY_BUS_INFORMATION: + break; + + case IRP_MN_QUERY_CAPABILITIES: + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + /* FIXME: Possibly handle for RemovalRelations */ + break; + + case IRP_MN_QUERY_DEVICE_TEXT: + break; +#endif + case IRP_MN_QUERY_ID: + Status = PdoQueryId(DeviceObject, Irp, IrpSp); + break; +#if 0 + case IRP_MN_QUERY_PNP_DEVICE_STATE: + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: + break; + + case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: + break; + + case IRP_MN_QUERY_RESOURCES: + break; + + case IRP_MN_QUERY_STOP_DEVICE: + break; + + case IRP_MN_REMOVE_DEVICE: + break; + + case IRP_MN_SET_LOCK: + break; + + case IRP_MN_START_DEVICE: + break; + + case IRP_MN_STOP_DEVICE: + break; + + case IRP_MN_SURPRISE_REMOVAL: + break; +#endif + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + break; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + +NTSTATUS +PnpRootPdoPowerControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the child device + * ARGUMENTS: + * DeviceObject = Pointer to physical device object of the child device + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + break; + } + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +/* Functional Device Object routines */ + +NTSTATUS +PnpRootFdoReadDeviceInfo( + PPNPROOT_DEVICE Device) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + PUNICODE_STRING DeviceDesc; + WCHAR KeyName[MAX_PATH]; + HANDLE KeyHandle; + NTSTATUS Status; + + DPRINT("Called\n"); + + /* Retrieve configuration from Enum key */ + + DeviceDesc = &Device->DeviceDescription; + + wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); + wcscat(KeyName, ENUM_NAME_ROOT); + wcscat(KeyName, L"\\"); + wcscat(KeyName, Device->ServiceName.Buffer); + wcscat(KeyName, L"\\"); + wcscat(KeyName, Device->InstanceID.Buffer); + + DPRINT("KeyName %S\n", KeyName); + + Status = RtlpGetRegistryHandle( + RTL_REGISTRY_ABSOLUTE, + KeyName, + FALSE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); + return Status; + } + + RtlZeroMemory(QueryTable, sizeof(QueryTable)); + + RtlInitUnicodeString(DeviceDesc, NULL); + + QueryTable[0].Name = L"DeviceDesc"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = DeviceDesc; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + + NtClose(KeyHandle); + + DPRINT("RtlQueryRegistryValues() returned status %x\n", Status); + + if (!NT_SUCCESS(Status)) + { + /* FIXME: */ + } + + DPRINT("Got device description: %S\n", DeviceDesc->Buffer); + + return STATUS_SUCCESS; +} + + +NTSTATUS +PnpRootFdoEnumerateDevices( + PDEVICE_OBJECT DeviceObject) +{ + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_BASIC_INFORMATION KeyInfo; + UNICODE_STRING KeyName; + PPNPROOT_DEVICE Device; + WCHAR Buffer[MAX_PATH]; + HANDLE KeyHandle; + ULONG BufferSize; + ULONG ResultSize; + NTSTATUS Status; + ULONG Index; + + DPRINT("Called\n"); + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR); + KeyInfo = ExAllocatePool(PagedPool, BufferSize); + if (!KeyInfo) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlInitUnicodeStringFromLiteral( + &KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" \ + ENUM_NAME_ROOT); + + InitializeObjectAttributes( + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtOpenKey() failed (Status %x)\n", Status); + ExFreePool(KeyInfo); + return Status; + } + + /* FIXME: Disabled due to still using the old method of auto loading drivers e.g. + there are more entries in the list than found in the registry as some + drivers are passed on the command line */ +// DeviceExtension->DeviceListCount = 0; + + Index = 0; + do { + Status = ZwEnumerateKey( + KeyHandle, + Index, + KeyBasicInformation, + KeyInfo, + BufferSize, + &ResultSize); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwEnumerateKey() (Status %x)\n", Status); + break; + } + + /* Terminate the string */ + KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0; + + Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE)); + if (!Device) + { + /* FIXME: */ + break; + } + + RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE)); + + if (!IopCreateUnicodeString(&Device->ServiceName, KeyInfo->Name, PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + wcscpy(Buffer, ENUM_NAME_ROOT); + wcscat(Buffer, L"\\"); + wcscat(Buffer, KeyInfo->Name); + + if (!IopCreateUnicodeString(&Device->DeviceID, Buffer, PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + DPRINT("Got entry: %S\n", Device->DeviceID.Buffer); + + if (!IopCreateUnicodeString( + &Device->InstanceID, + L"0000", + PagedPool)) + { + /* FIXME: */ + DPRINT("IopCreateUnicodeString() failed\n"); + } + + Status = PnpRootFdoReadDeviceInfo(Device); + if (!NT_SUCCESS(Status)) + { + DPRINT("PnpRootFdoReadDeviceInfo() failed with status %x\n", Status); + /* FIXME: */ + } + + ExInterlockedInsertTailList( + &DeviceExtension->DeviceListHead, + &Device->ListEntry, + &DeviceExtension->DeviceListLock); + + DeviceExtension->DeviceListCount++; + + Index++; + } while (TRUE); + + DPRINT("Entries found: %d\n", Index); + + NtClose(KeyHandle); + + ExFreePool(KeyInfo); + + return STATUS_SUCCESS; +} + + +NTSTATUS +PnpRootQueryBusRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp) +{ + PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; + PDEVICE_RELATIONS Relations; + PLIST_ENTRY CurrentEntry; + PPNPROOT_DEVICE Device; + NTSTATUS Status; + ULONG Size; + ULONG i; + + DPRINT("Called\n"); + + Status = PnpRootFdoEnumerateDevices(DeviceObject); + if (!NT_SUCCESS(Status)) + return Status; + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (Irp->IoStatus.Information) + { + /* FIXME: Another bus driver has already created a DEVICE_RELATIONS + structure so we must merge this structure with our own */ + } + + Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) * + (DeviceExtension->DeviceListCount - 1); + + Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); + if (!Relations) + return STATUS_INSUFFICIENT_RESOURCES; + + Relations->Count = DeviceExtension->DeviceListCount; + + i = 0; + CurrentEntry = DeviceExtension->DeviceListHead.Flink; + while (CurrentEntry != &DeviceExtension->DeviceListHead) + { + Device = CONTAINING_RECORD(CurrentEntry, PNPROOT_DEVICE, ListEntry); + + if (!Device->Pdo) + { + /* Create a physical device object for the + device as it does not already have one */ + Status = IoCreateDevice( + DeviceObject->DriverObject, + sizeof(PNPROOT_PDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_CONTROLLER, + 0, + FALSE, + &Device->Pdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + ExFreePool(Relations); + return Status; + } + + DPRINT("Created PDO %x\n", Device->Pdo); + + Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + + Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; + + //Device->Pdo->Flags |= DO_POWER_PAGABLE; + + PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; + + RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION)); + + PdoDeviceExtension->Common.IsFDO = FALSE; + + PdoDeviceExtension->Common.DeviceObject = Device->Pdo; + + PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0; + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->DeviceID, + Device->DeviceID.Buffer, + PagedPool)) + { + DPRINT("Insufficient resources\n"); + /* FIXME: */ + } + + DPRINT("DeviceID: %S PDO %x\n", + PdoDeviceExtension->DeviceID.Buffer, + Device->Pdo); + + if (!IopCreateUnicodeString( + &PdoDeviceExtension->InstanceID, + Device->InstanceID.Buffer, + PagedPool)) + { + DPRINT("Insufficient resources\n"); + /* FIXME: */ + } + + } + + /* Reference the physical device object. The PnP manager + will dereference it again when it is no longer needed */ + ObReferenceObject(Device->Pdo); + + Relations->Objects[i] = Device->Pdo; + + i++; + + CurrentEntry = CurrentEntry->Flink; + } + + if (NT_SUCCESS(Status)) + { + Irp->IoStatus.Information = (ULONG_PTR)Relations; + } + else + { + Irp->IoStatus.Information = 0; + } + + return Status; +} + + +NTSTATUS +PnpRootQueryDeviceRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp) +{ + NTSTATUS Status; + + DPRINT("Called\n"); + + switch (IrpSp->Parameters.QueryDeviceRelations.Type) { + case BusRelations: + Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp); + break; + + default: + Status = STATUS_NOT_IMPLEMENTED; + } + + return Status; +} + + +NTSTATUS +STDCALL +PnpRootFdoPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs for the root bus device object + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the root bus driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + Status = Irp->IoStatus.Status; + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + case IRP_MN_QUERY_DEVICE_RELATIONS: + Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp); + break; + + case IRP_MN_START_DEVICE: + DeviceExtension->State = dsStarted; + Status = STATUS_SUCCESS; + break; + + case IRP_MN_STOP_DEVICE: + /* Root device cannot be stopped */ + Status = STATUS_UNSUCCESSFUL; + break; + + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +PnpRootFdoPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle power management IRPs for the root bus device object + * ARGUMENTS: + * DeviceObject = Pointer to functional device object of the root bus driver + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PIO_STACK_LOCATION IrpSp; + NTSTATUS Status; + + DPRINT("Called\n"); + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + + switch (IrpSp->MinorFunction) { + default: + DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction); + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + if (Status != STATUS_PENDING) { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + + DPRINT("Leaving. Status 0x%X\n", Status); + + return Status; +} + + +NTSTATUS +STDCALL +PnpRootPnpControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle Plug and Play IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + DPRINT("DeviceObject %x DeviceExtension %x IsFDO %d\n", + DeviceObject, + DeviceExtension, + DeviceExtension->IsFDO); + + if (DeviceExtension->IsFDO) { + Status = PnpRootFdoPnpControl(DeviceObject, Irp); + } else { + Status = PnpRootPdoPnpControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +PnpRootPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +/* + * FUNCTION: Handle power management IRPs + * ARGUMENTS: + * DeviceObject = Pointer to PDO or FDO + * Irp = Pointer to IRP that should be handled + * RETURNS: + * Status + */ +{ + PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceExtension->IsFDO) { + Status = PnpRootFdoPowerControl(DeviceObject, Irp); + } else { + Status = PnpRootPdoPowerControl(DeviceObject, Irp); + } + + return Status; +} + + +NTSTATUS +STDCALL +PnpRootAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DPRINT("Called\n"); + + Status = IoCreateDevice( + DriverObject, + sizeof(PNPROOT_FDO_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_BUS_EXTENDER, + FILE_DEVICE_SECURE_OPEN, + TRUE, + &PnpRootDeviceObject); + if (!NT_SUCCESS(Status)) { + CPRINT("IoCreateDevice() failed with status 0x%X\n", Status); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension; + + RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION)); + + DeviceExtension->Common.IsFDO = TRUE; + + DeviceExtension->State = dsStopped; + + DeviceExtension->Ldo = IoAttachDeviceToDeviceStack( + PnpRootDeviceObject, + PhysicalDeviceObject); + + if (!PnpRootDeviceObject) { + CPRINT("PnpRootDeviceObject 0x%X\n", PnpRootDeviceObject); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + if (!PhysicalDeviceObject) { + CPRINT("PhysicalDeviceObject 0x%X\n", PhysicalDeviceObject); + KeBugCheck(PHASE1_INITIALIZATION_FAILED); + } + + InitializeListHead(&DeviceExtension->DeviceListHead); + + DeviceExtension->DeviceListCount = 0; + + KeInitializeSpinLock(&DeviceExtension->DeviceListLock); + + PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE; + + DPRINT("Done AddDevice()\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +PnpRootDriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT("Called\n"); + + DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PnpRootPnpControl; + DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PnpRootPowerControl; + DriverObject->DriverExtension->AddDevice = PnpRootAddDevice; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/ntoskrnl/io/process.c b/ntoskrnl/io/process.c new file mode 100644 index 0000000..50a5fb9 --- /dev/null +++ b/ntoskrnl/io/process.c @@ -0,0 +1,92 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/process.c + * PURPOSE: Process functions that, bizarrely, are in the iomgr + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +PVOID STDCALL +IoGetInitialStack(VOID) +{ + return(PsGetCurrentThread()->Tcb.InitialStack); +} + + +VOID STDCALL +IoGetStackLimits(OUT PULONG LowLimit, + OUT PULONG HighLimit) +{ + *LowLimit = (ULONG)NtCurrentTeb()->Tib.StackLimit; + *HighLimit = (ULONG)NtCurrentTeb()->Tib.StackBase; +} + + +PEPROCESS STDCALL +IoThreadToProcess(IN PETHREAD Thread) +{ + return(Thread->ThreadsProcess); +} + + +PEPROCESS STDCALL +IoGetRequestorProcess(IN PIRP Irp) +{ + return(Irp->Tail.Overlay.Thread->ThreadsProcess); +} + + +/********************************************************************** + * NAME EXPORTED + * IoSetThreadHardErrorMode@4 + * + * ARGUMENTS + * HardErrorEnabled + * TRUE : enable hard errors processing; + * FALSE: do NOT process hard errors. + * + * RETURN VALUE + * Previous value for the current thread's hard errors + * processing policy. + */ +BOOLEAN STDCALL EXPORTED +IoSetThreadHardErrorMode(IN BOOLEAN HardErrorEnabled) +{ + BOOLEAN PreviousHEM = NtCurrentTeb()->HardErrorDisabled; + + NtCurrentTeb()->HardErrorDisabled = ((TRUE == HardErrorEnabled) ? FALSE : TRUE); + + return((TRUE == PreviousHEM) ? FALSE : TRUE); +} + +/* EOF */ diff --git a/ntoskrnl/io/queue.c b/ntoskrnl/io/queue.c new file mode 100644 index 0000000..2d798f4 --- /dev/null +++ b/ntoskrnl/io/queue.c @@ -0,0 +1,138 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/queue.c + * PURPOSE: Implement device queueing + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID +STDCALL +IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject, + BOOLEAN Cancelable, + ULONG Key) +/* + * FUNCTION: Dequeues the next packet from the given device object's + * associated device queue according to a specified sort-key value and calls + * the drivers StartIo routine with that IRP + * ARGUMENTS: + * DeviceObject = Device object for which the irp is to dequeued + * Cancelable = True if IRPs in the key can be canceled + * Key = Sort key specifing which entry to remove from the queue + */ +{ + PKDEVICE_QUEUE_ENTRY entry; + PIRP Irp; + + entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue, + Key); + + if (entry != NULL) + { + Irp = CONTAINING_RECORD(entry, + IRP, + Tail.Overlay.DeviceQueueEntry); + DeviceObject->CurrentIrp = Irp; + DPRINT("Next irp is %x\n", Irp); + DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp); + } + else + { + DPRINT("No next irp\n"); + DeviceObject->CurrentIrp = NULL; + } +} + +VOID +STDCALL +IoStartNextPacket(PDEVICE_OBJECT DeviceObject, BOOLEAN Cancelable) +/* + * FUNCTION: Removes the next packet from the device's queue and calls + * the driver's StartIO + * ARGUMENTS: + * DeviceObject = Device + * Cancelable = True if irps in the queue can be canceled + */ +{ + PKDEVICE_QUEUE_ENTRY entry; + PIRP Irp; + + DPRINT("IoStartNextPacket(DeviceObject %x, Cancelable %d)\n", + DeviceObject,Cancelable); + + entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue); + + if (entry!=NULL) + { + Irp = CONTAINING_RECORD(entry,IRP,Tail.Overlay.DeviceQueueEntry); + DeviceObject->CurrentIrp = Irp; + DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp); + } + else + { + DeviceObject->CurrentIrp = NULL; + } +} + +VOID +STDCALL +IoStartPacket(PDEVICE_OBJECT DeviceObject, + PIRP Irp, PULONG Key, PDRIVER_CANCEL CancelFunction) +/* + * FUNCTION: Either call the device's StartIO routine with the packet or, + * if the device is busy, queue it. + * ARGUMENTS: + * DeviceObject = Device to start the packet on + * Irp = Irp to queue + * Key = Where to insert the irp + * If zero then insert in the tail of the queue + * CancelFunction = Optional function to cancel the irqp + */ +{ + BOOLEAN stat; + KIRQL oldirql; + + DPRINT("IoStartPacket(Irp %x)\n", Irp); + + ASSERT_IRQL(DISPATCH_LEVEL); + + IoAcquireCancelSpinLock(&oldirql); + + if (CancelFunction != NULL) + { + Irp->CancelRoutine = CancelFunction; + } + + if (Key!=0) + { + stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry, + *Key); + } + else + { + stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry); + } + + IoReleaseCancelSpinLock(oldirql); + + if (!stat) + { + DeviceObject->CurrentIrp = Irp; + DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp); + } +} + + +/* EOF */ diff --git a/ntoskrnl/io/resource.c b/ntoskrnl/io/resource.c new file mode 100644 index 0000000..8f7ab25 --- /dev/null +++ b/ntoskrnl/io/resource.c @@ -0,0 +1,265 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/resource.c + * PURPOSE: Hardware resource managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + + +#include + +/* GLOBALS *******************************************************************/ + +static CONFIGURATION_INFORMATION +SystemConfigurationInformation = {0, 0, 0, 0, 0, 0, 0, FALSE, FALSE}; + +/* FUNCTIONS *****************************************************************/ + +PCONFIGURATION_INFORMATION STDCALL +IoGetConfigurationInformation(VOID) +{ + return(&SystemConfigurationInformation); +} + +NTSTATUS STDCALL +IoReportResourceUsage(PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PCM_RESOURCE_LIST DriverList, + ULONG DriverListSize, + PDEVICE_OBJECT DeviceObject, + PCM_RESOURCE_LIST DeviceList, + ULONG DeviceListSize, + BOOLEAN OverrideConflict, + PBOOLEAN ConflictDetected) + /* + * FUNCTION: Reports hardware resources in the + * \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently + * loaded driver cannot attempt to use the same resources. + * ARGUMENTS: + * DriverClassName - The class of driver under which the resource + * information should be stored. + * DriverObject - The driver object that was input to the + * DriverEntry. + * DriverList - Resources that claimed for the driver rather than + * per-device. + * DriverListSize - Size in bytes of the DriverList. + * DeviceObject - The device object for which resources should be + * claimed. + * DeviceList - List of resources which should be claimed for the + * device. + * DeviceListSize - Size of the per-device resource list in bytes. + * OverrideConflict - True if the resources should be cliamed + * even if a conflict is found. + * ConflictDetected - Points to a variable that receives TRUE if + * a conflict is detected with another driver. + */ +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +IoAssignResources(PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, + PCM_RESOURCE_LIST* AllocatedResources) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, + PVOID Context) +{ +#if 0 + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + PWCH BaseKeyName[] = + L"\\Registry\\Machine\\Hardware\\MultifunctionAdapter\\0"; + HANDLE BaseKeyHandle; + ULONG i; + struct + { + KEY_BASIC_INFORMATION BasicInfo; + WCH Name[255]; + } BasicInfo; + + BaseKeyName = L"\\Registry\\Machine\\Hardware\\MultifunctionAdapter"; + InitializeObjectAttributes(&ObjectAttributes, + BaseKeyName, + 0, + NULL, + NULL); + Status = ZwOpenKey(&BaseKeyHandle, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEY, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + i = 0; + for (;;) + { + Status = ZwEnumerateKey(BaseKeyHandle, + i, + KeyBasicInformation, + &BasicInfo, + sizeof(BasicInfo), + &ResultLength); + if (!NT_SUCCESS(Status)) + { + break; + } + + + } +#endif + return(STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS STDCALL +IoReportHalResourceUsage(PUNICODE_STRING HalDescription, + PCM_RESOURCE_LIST RawList, + PCM_RESOURCE_LIST TranslatedList, + ULONG ListSize) +/* + * FUNCTION: + * Reports hardware resources of the HAL in the + * \Registry\Machine\Hardware\ResourceMap tree. + * ARGUMENTS: + * HalDescription: Descriptive name of the HAL. + * RawList: List of raw (bus specific) resources which should be + * claimed for the HAL. + * TranslatedList: List of translated (system wide) resources which + * should be claimed for the HAL. + * ListSize: Size in bytes of the raw and translated resource lists. + * Both lists have the same size. + * RETURNS: + * Status. + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name; + ULONG Disposition; + NTSTATUS Status; + HANDLE ResourcemapKey; + HANDLE HalKey; + HANDLE DescriptionKey; + + /* Open/Create 'RESOURCEMAP' key. */ + RtlInitUnicodeStringFromLiteral(&Name, + L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + 0, + NULL); + Status = NtCreateKey(&ResourcemapKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Open/Create 'Hardware Abstraction Layer' key */ + RtlInitUnicodeStringFromLiteral(&Name, + L"Hardware Abstraction Layer"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + ResourcemapKey, + NULL); + Status = NtCreateKey(&HalKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + NtClose(ResourcemapKey); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Create 'HalDescription' key */ + InitializeObjectAttributes(&ObjectAttributes, + HalDescription, + OBJ_CASE_INSENSITIVE, + HalKey, + NULL); + Status = NtCreateKey(&DescriptionKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + NtClose(HalKey); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Add '.Raw' value. */ + RtlInitUnicodeStringFromLiteral(&Name, + L".Raw"); + Status = NtSetValueKey(DescriptionKey, + &Name, + 0, + REG_RESOURCE_LIST, + RawList, + ListSize); + if (!NT_SUCCESS(Status)) + { + NtClose(DescriptionKey); + return(Status); + } + + /* Add '.Translated' value. */ + RtlInitUnicodeStringFromLiteral(&Name, + L".Translated"); + Status = NtSetValueKey(DescriptionKey, + &Name, + 0, + REG_RESOURCE_LIST, + TranslatedList, + ListSize); + NtClose(DescriptionKey); + + return(Status); +} + +/* EOF */ diff --git a/ntoskrnl/io/rw.c b/ntoskrnl/io/rw.c new file mode 100644 index 0000000..38f1b83 --- /dev/null +++ b/ntoskrnl/io/rw.c @@ -0,0 +1,360 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/rw.c + * PURPOSE: Implements read/write APIs + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 30/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + + +/********************************************************************** + * NAME EXPORTED + * NtReadFile + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL NtReadFile(HANDLE FileHandle, + HANDLE EventHandle, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK UserIoStatusBlock, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER ByteOffset, + PULONG Key) +{ + NTSTATUS Status; + PFILE_OBJECT FileObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + PKEVENT Event = NULL; + IO_STATUS_BLOCK Iosb; + PIO_STATUS_BLOCK IoStatusBlock; + + DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, " + "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset, + IoStatusBlock); + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_READ_DATA, + IoFileObjectType, + UserMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (ByteOffset == NULL) + { + ByteOffset = &FileObject->CurrentByteOffset; + } + + if (EventHandle != NULL) + { + Status = ObReferenceObjectByHandle(EventHandle, + SYNCHRONIZE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + return(Status); + } + } + else + { + Event = &FileObject->Event; + KeResetEvent(Event); + } + + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + IoStatusBlock = &Iosb; + } + else + { + IoStatusBlock = UserIoStatusBlock; + } + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + FileObject->DeviceObject, + Buffer, + Length, + ByteOffset, + Event, + IoStatusBlock); + + Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; + Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + if (Key != NULL) + { + StackPtr->Parameters.Read.Key = *Key; + } + else + { + StackPtr->Parameters.Read.Key = 0; + } + + Status = IoCallDriver(FileObject->DeviceObject, Irp); + if (Status == STATUS_PENDING && FileObject->Flags & FO_SYNCHRONOUS_IO) + { + BOOLEAN Alertable; + + if (FileObject->Flags & FO_ALERTABLE_IO) + { + Alertable = TRUE; + } + else + { + Alertable = FALSE; + } + + Status = KeWaitForSingleObject(Event, + Executive, + UserMode, + Alertable, + NULL); + if (Status != STATUS_WAIT_0) + { + /* Wait failed. */ + return(Status); + } + Status = Iosb.Status; + return(Status); + } + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + *UserIoStatusBlock = Iosb; + } + return(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * NtWriteFile + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL NtWriteFile(HANDLE FileHandle, + HANDLE EventHandle, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK UserIoStatusBlock, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER ByteOffset, + PULONG Key) +{ + NTSTATUS Status; + PFILE_OBJECT FileObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; + PKEVENT Event = NULL; + IO_STATUS_BLOCK Iosb; + PIO_STATUS_BLOCK IoStatusBlock; + + DPRINT("NtReadFile(FileHandle %x Buffer %x Length %x ByteOffset %x, " + "IoStatusBlock %x)\n", FileHandle, Buffer, Length, ByteOffset, + IoStatusBlock); + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_READ_DATA, + IoFileObjectType, + UserMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (ByteOffset == NULL) + { + ByteOffset = &FileObject->CurrentByteOffset; + } + + if (EventHandle != NULL) + { + Status = ObReferenceObjectByHandle(EventHandle, + SYNCHRONIZE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + return(Status); + } + } + else + { + Event = &FileObject->Event; + KeResetEvent(Event); + } + + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + IoStatusBlock = &Iosb; + } + else + { + IoStatusBlock = UserIoStatusBlock; + } + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, + FileObject->DeviceObject, + Buffer, + Length, + ByteOffset, + Event, + IoStatusBlock); + + Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; + Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + if (Key != NULL) + { + StackPtr->Parameters.Write.Key = *Key; + } + else + { + StackPtr->Parameters.Write.Key = 0; + } + + Status = IoCallDriver(FileObject->DeviceObject, Irp); + if (Status == STATUS_PENDING && FileObject->Flags & FO_SYNCHRONOUS_IO) + { + BOOLEAN Alertable; + + if (FileObject->Flags & FO_ALERTABLE_IO) + { + Alertable = TRUE; + } + else + { + Alertable = FALSE; + } + + Status = KeWaitForSingleObject(Event, + Executive, + UserMode, + Alertable, + NULL); + if (Status != STATUS_WAIT_0) + { + /* Wait failed. */ + return(Status); + } + Status = Iosb.Status; + return(Status); + } + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + *UserIoStatusBlock = Iosb; + } + return(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * NtReadFileScatter + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtReadFileScatter ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, + IN PVOID UserApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK UserIoStatusBlock, + IN FILE_SEGMENT_ELEMENT BufferDescription [], + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ) +{ + UNIMPLEMENTED; +} + + +/********************************************************************** + * NAME EXPORTED + * NtWriteFileGather + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS +STDCALL +NtWriteFileGather ( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN FILE_SEGMENT_ELEMENT BufferDescription [], + IN ULONG BufferLength, + IN PLARGE_INTEGER ByteOffset, + IN PULONG Key OPTIONAL + ) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/io/share.c b/ntoskrnl/io/share.c new file mode 100644 index 0000000..2b2ff07 --- /dev/null +++ b/ntoskrnl/io/share.c @@ -0,0 +1,342 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/share.c + * PURPOSE: + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +IoUpdateShareAccess(PFILE_OBJECT FileObject, + PSHARE_ACCESS ShareAccess) +{ + if ((FileObject->ReadAccess == FALSE) && + (FileObject->WriteAccess == FALSE) && + (FileObject->DeleteAccess == FALSE)) + { + return; + } + + ShareAccess->OpenCount++; + + if (FileObject->ReadAccess == TRUE) + { + ShareAccess->Readers++; + } + + if (FileObject->WriteAccess == TRUE) + { + ShareAccess->Writers++; + } + + if (FileObject->DeleteAccess == TRUE) + { + ShareAccess->Deleters++; + } + + if (FileObject->SharedRead == TRUE) + { + ShareAccess->SharedRead++; + } + + if (FileObject->SharedWrite == TRUE) + { + ShareAccess->SharedWrite++; + } + + if (FileObject->SharedDelete == TRUE) + { + ShareAccess->SharedDelete++; + } +} + + +NTSTATUS STDCALL +IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, + IN ULONG DesiredShareAccess, + IN PFILE_OBJECT FileObject, + IN PSHARE_ACCESS ShareAccess, + IN BOOLEAN Update) +{ + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + + ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)); + WriteAccess = (DesiredAccess & (FILE_READ_DATA | FILE_APPEND_DATA)); + DeleteAccess = (DesiredAccess & DELETE); + + FileObject->ReadAccess = ReadAccess; + FileObject->WriteAccess = WriteAccess; + FileObject->DeleteAccess = DeleteAccess; + + if (!ReadAccess && !WriteAccess && !DeleteAccess) + { + return(STATUS_SUCCESS); + } + + SharedRead = (DesiredShareAccess & FILE_SHARE_READ); + SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE); + SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE); + + FileObject->SharedRead = SharedRead; + FileObject->SharedWrite = SharedWrite; + FileObject->SharedDelete = SharedDelete; + + if (ReadAccess) + { + if (ShareAccess->SharedRead < ShareAccess->OpenCount) + return(STATUS_SHARING_VIOLATION); + } + + if (WriteAccess) + { + if (ShareAccess->SharedWrite < ShareAccess->OpenCount) + return(STATUS_SHARING_VIOLATION); + } + + if (DeleteAccess) + { + if (ShareAccess->SharedDelete < ShareAccess->OpenCount) + return(STATUS_SHARING_VIOLATION); + } + + if (ShareAccess->Readers != 0) + { + if (SharedRead == FALSE) + return(STATUS_SHARING_VIOLATION); + } + + if (ShareAccess->Writers != 0) + { + if (SharedWrite == FALSE) + return(STATUS_SHARING_VIOLATION); + } + + if (ShareAccess->Deleters != 0) + { + if (SharedDelete == FALSE) + return(STATUS_SHARING_VIOLATION); + } + + if (Update == TRUE) + { + ShareAccess->OpenCount++; + + if (ReadAccess == TRUE) + ShareAccess->Readers++; + + if (WriteAccess == TRUE) + ShareAccess->Writers++; + + if (DeleteAccess == TRUE) + ShareAccess->Deleters++; + + if (SharedRead == TRUE) + ShareAccess->SharedRead++; + + if (SharedWrite == TRUE) + ShareAccess->SharedWrite++; + + if (SharedDelete == TRUE) + ShareAccess->SharedDelete++; + } + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +IoRemoveShareAccess(IN PFILE_OBJECT FileObject, + IN PSHARE_ACCESS ShareAccess) +{ + if ((FileObject->ReadAccess == FALSE) && + (FileObject->WriteAccess == FALSE) && + (FileObject->DeleteAccess == FALSE)) + { + return; + } + + ShareAccess->OpenCount--; + + if (FileObject->ReadAccess == TRUE) + { + ShareAccess->Readers--; + } + + if (FileObject->WriteAccess == TRUE) + { + ShareAccess->Writers--; + } + + if (FileObject->DeleteAccess == TRUE) + { + ShareAccess->Deleters--; + } + + if (FileObject->SharedRead == TRUE) + { + ShareAccess->SharedRead--; + } + + if (FileObject->SharedWrite == TRUE) + { + ShareAccess->SharedWrite--; + } + + if (FileObject->SharedDelete == TRUE) + { + ShareAccess->SharedDelete--; + } +} + + +VOID STDCALL +IoSetShareAccess(IN ACCESS_MASK DesiredAccess, + IN ULONG DesiredShareAccess, + IN PFILE_OBJECT FileObject, + OUT PSHARE_ACCESS ShareAccess) +{ + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + + ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)); + WriteAccess = (DesiredAccess & (FILE_READ_DATA | FILE_APPEND_DATA)); + DeleteAccess = (DesiredAccess & DELETE); + + FileObject->ReadAccess = ReadAccess; + FileObject->WriteAccess = WriteAccess; + FileObject->DeleteAccess = DeleteAccess; + + if (!ReadAccess && !WriteAccess && !DeleteAccess) + { + FileObject->SharedRead = FALSE; + FileObject->SharedWrite = FALSE; + FileObject->SharedDelete = FALSE; + + ShareAccess->OpenCount = 0; + ShareAccess->Readers = 0; + ShareAccess->Writers = 0; + ShareAccess->Deleters = 0; + + ShareAccess->SharedRead = 0; + ShareAccess->SharedWrite = 0; + ShareAccess->SharedDelete = 0; + } + else + { + SharedRead = (DesiredShareAccess & FILE_SHARE_READ); + SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE); + SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE); + + FileObject->SharedRead = SharedRead; + FileObject->SharedWrite = SharedWrite; + FileObject->SharedDelete = SharedDelete; + + ShareAccess->OpenCount = 1; + ShareAccess->Readers = (ReadAccess) ? 1 : 0; + ShareAccess->Writers = (WriteAccess) ? 1 : 0; + ShareAccess->Deleters = (DeleteAccess) ? 1 : 0; + + ShareAccess->SharedRead = (SharedRead) ? 1 : 0; + ShareAccess->SharedWrite = (SharedWrite) ? 1 : 0; + ShareAccess->SharedDelete = (SharedDelete) ? 1 : 0; + } +} + + +NTSTATUS STDCALL +IoCheckDesiredAccess(IN OUT PACCESS_MASK DesiredAccess, + IN ACCESS_MASK GrantedAccess) +{ + RtlMapGenericMask(DesiredAccess, + IoFileObjectType->Mapping); + if ((*DesiredAccess & GrantedAccess) != GrantedAccess) + return(STATUS_ACCESS_DENIED); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +IoCheckEaBufferValidity(IN PFILE_FULL_EA_INFORMATION EaBuffer, + IN ULONG EaLength, + OUT PULONG ErrorOffset) +{ + UNIMPLEMENTED; + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +IoCheckFunctionAccess(IN ACCESS_MASK GrantedAccess, + IN UCHAR MajorFunction, + IN UCHAR MinorFunction, + IN ULONG IoControlCode, + IN PFILE_INFORMATION_CLASS FileInformationClass OPTIONAL, + IN PFS_INFORMATION_CLASS FsInformationClass OPTIONAL) +{ + UNIMPLEMENTED; + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +IoSetInformation(IN PFILE_OBJECT FileObject, + IN FILE_INFORMATION_CLASS FileInformationClass, + IN ULONG Length, + OUT PVOID FileInformation) +{ + UNIMPLEMENTED; + return(STATUS_NOT_IMPLEMENTED); +} + + +BOOLEAN STDCALL +IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + IN ULONG OpenOptions, + OUT PIO_STATUS_BLOCK IoStatus, + OUT PFILE_NETWORK_OPEN_INFORMATION Buffer) +{ + UNIMPLEMENTED; + return(FALSE); +} + +/* EOF */ diff --git a/ntoskrnl/io/shutdown.c b/ntoskrnl/io/shutdown.c new file mode 100644 index 0000000..ef369b7 --- /dev/null +++ b/ntoskrnl/io/shutdown.c @@ -0,0 +1,128 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/shutdown.c + * PURPOSE: Implements shutdown notification + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* LOCAL DATA ***************************************************************/ + +typedef struct _SHUTDOWN_ENTRY +{ + LIST_ENTRY ShutdownList; + PDEVICE_OBJECT DeviceObject; +} SHUTDOWN_ENTRY, *PSHUTDOWN_ENTRY; + +static LIST_ENTRY ShutdownListHead; +static KSPIN_LOCK ShutdownListLock; + +#define TAG_SHUTDOWN_ENTRY TAG('S', 'H', 'U', 'T') + +/* FUNCTIONS *****************************************************************/ + +VOID IoInitShutdownNotification (VOID) +{ + InitializeListHead(&ShutdownListHead); + KeInitializeSpinLock(&ShutdownListLock); +} + +VOID IoShutdownRegisteredDevices(VOID) +{ + PSHUTDOWN_ENTRY ShutdownEntry; + PLIST_ENTRY Entry; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + KEVENT Event; + NTSTATUS Status; + + Entry = ShutdownListHead.Flink; + while (Entry != &ShutdownListHead) + { + ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList); + + KeInitializeEvent (&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN, + ShutdownEntry->DeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + + Status = IoCallDriver (ShutdownEntry->DeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject (&Event, + Executive, + KernelMode, + FALSE, + NULL); + } + + Entry = Entry->Flink; + } +} + +NTSTATUS STDCALL IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject) +{ + PSHUTDOWN_ENTRY Entry; + + Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_ENTRY), + TAG_SHUTDOWN_ENTRY); + if (Entry == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + Entry->DeviceObject = DeviceObject; + + ExInterlockedInsertHeadList(&ShutdownListHead, + &Entry->ShutdownList, + &ShutdownListLock); + + DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED; + + return STATUS_SUCCESS; +} + +VOID STDCALL IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject) +{ + PSHUTDOWN_ENTRY ShutdownEntry; + PLIST_ENTRY Entry; + KIRQL oldlvl; + + Entry = ShutdownListHead.Flink; + while (Entry != &ShutdownListHead) + { + ShutdownEntry = CONTAINING_RECORD(Entry, SHUTDOWN_ENTRY, ShutdownList); + if (ShutdownEntry->DeviceObject == DeviceObject) + { + DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED; + + KeAcquireSpinLock(&ShutdownListLock,&oldlvl); + RemoveEntryList(Entry); + KeReleaseSpinLock(&ShutdownListLock,oldlvl); + + ExFreePool(Entry); + return; + } + + Entry = Entry->Flink; + } +} + +/* EOF */ diff --git a/ntoskrnl/io/symlink.c b/ntoskrnl/io/symlink.c new file mode 100644 index 0000000..694babc --- /dev/null +++ b/ntoskrnl/io/symlink.c @@ -0,0 +1,453 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/symlink.c + * PURPOSE: Implements symbolic links + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +typedef struct +{ + CSHORT Type; + CSHORT Size; + UNICODE_STRING TargetName; + OBJECT_ATTRIBUTES Target; +} SYMLNK_OBJECT, *PSYMLNK_OBJECT; + +POBJECT_TYPE IoSymbolicLinkType = NULL; + +static GENERIC_MAPPING IopSymbolicLinkMapping = { + STANDARD_RIGHTS_READ|SYMBOLIC_LINK_QUERY, + STANDARD_RIGHTS_WRITE, + STANDARD_RIGHTS_EXECUTE|SYMBOLIC_LINK_QUERY, + SYMBOLIC_LINK_ALL_ACCESS}; + +#define TAG_SYMLINK_TTARGET TAG('S', 'Y', 'T', 'T') +#define TAG_SYMLINK_TARGET TAG('S', 'Y', 'M', 'T') + +/* FUNCTIONS *****************************************************************/ + + +/********************************************************************** + * NAME INTERNAL + * IopCreateSymbolicLink + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURNN VALUE + * Status. + * + * REVISIONS + */ +NTSTATUS STDCALL +IopCreateSymbolicLink(PVOID Object, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME INTERNAL + * IopParseSymbolicLink + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + */ +NTSTATUS STDCALL +IopParseSymbolicLink(PVOID Object, + PVOID * NextObject, + PUNICODE_STRING FullPath, + PWSTR * RemainingPath, + ULONG Attributes) +{ + PSYMLNK_OBJECT SymlinkObject = (PSYMLNK_OBJECT) Object; + UNICODE_STRING TargetPath; + + DPRINT("IopParseSymbolicLink (RemainingPath %S)\n", *RemainingPath); + /* + * Stop parsing if the entire path has been parsed and + * the desired object is a symbolic link object. + */ + if (((*RemainingPath == NULL) || (**RemainingPath == 0)) && + (Attributes & OBJ_OPENLINK)) + { + DPRINT("Parsing stopped!\n"); + *NextObject = NULL; + return STATUS_SUCCESS; + } + + /* build the expanded path */ + TargetPath.MaximumLength = SymlinkObject->TargetName.Length + sizeof(WCHAR); + if (RemainingPath && *RemainingPath) + { + TargetPath.MaximumLength += (wcslen(*RemainingPath) * sizeof(WCHAR)); + } + TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR); + TargetPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, + TargetPath.MaximumLength, + TAG_SYMLINK_TTARGET); + wcscpy(TargetPath.Buffer, SymlinkObject->TargetName.Buffer); + if (RemainingPath && *RemainingPath) + { + wcscat(TargetPath.Buffer, *RemainingPath); + } + + /* transfer target path buffer into FullPath */ + RtlFreeUnicodeString(FullPath); + FullPath->Length = TargetPath.Length; + FullPath->MaximumLength = TargetPath.MaximumLength; + FullPath->Buffer = TargetPath.Buffer; + + /* reinitialize RemainingPath for reparsing */ + *RemainingPath = FullPath->Buffer; + + *NextObject = NULL; + return STATUS_REPARSE; +} + +/********************************************************************** + * NAME INTERNAL + * IoInitSymbolicLinkImplementation + * + * DESCRIPTION + * + * ARGUMENTS + * None. + * + * RETURNN VALUE + * None. + * + * REVISIONS + */ +VOID IoInitSymbolicLinkImplementation (VOID) +{ + IoSymbolicLinkType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + IoSymbolicLinkType->Tag = TAG('S', 'Y', 'M', 'T'); + IoSymbolicLinkType->TotalObjects = 0; + IoSymbolicLinkType->TotalHandles = 0; + IoSymbolicLinkType->MaxObjects = ULONG_MAX; + IoSymbolicLinkType->MaxHandles = ULONG_MAX; + IoSymbolicLinkType->PagedPoolCharge = 0; + IoSymbolicLinkType->NonpagedPoolCharge = sizeof (SYMLNK_OBJECT); + IoSymbolicLinkType->Mapping = &IopSymbolicLinkMapping; + IoSymbolicLinkType->Dump = NULL; + IoSymbolicLinkType->Open = NULL; + IoSymbolicLinkType->Close = NULL; + IoSymbolicLinkType->Delete = NULL; + IoSymbolicLinkType->Parse = IopParseSymbolicLink; + IoSymbolicLinkType->Security = NULL; + IoSymbolicLinkType->QueryName = NULL; + IoSymbolicLinkType->OkayToClose = NULL; + IoSymbolicLinkType->Create = IopCreateSymbolicLink; + IoSymbolicLinkType->DuplicationNotify = NULL; + + RtlInitUnicodeStringFromLiteral(&IoSymbolicLinkType->TypeName, + L"SymbolicLink"); +} + + +/********************************************************************** + * NAME EXPORTED + * NtOpenSymbolicLinkObject + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n", + ObjectAttributes->ObjectName); + + return(ObOpenObjectByName(ObjectAttributes, + IoSymbolicLinkType, + NULL, + UserMode, + DesiredAccess, + NULL, + LinkHandle)); +} + + +/********************************************************************** + * NAME EXPORTED + * NtQuerySymbolicLinkObject + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtQuerySymbolicLinkObject(IN HANDLE LinkHandle, + IN OUT PUNICODE_STRING LinkTarget, + OUT PULONG ReturnedLength OPTIONAL) +{ + PSYMLNK_OBJECT SymlinkObject; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(LinkHandle, + SYMBOLIC_LINK_QUERY, + IoSymbolicLinkType, + UserMode, + (PVOID *)&SymlinkObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + RtlCopyUnicodeString(LinkTarget, + SymlinkObject->Target.ObjectName); + if (ReturnedLength != NULL) + { + *ReturnedLength = SymlinkObject->Target.Length; + } + ObDereferenceObject(SymlinkObject); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * IoCreateUnprotectedSymbolicLink + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +IoCreateUnprotectedSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName) +{ + return(IoCreateSymbolicLink(SymbolicLinkName, + DeviceName)); +} + + +/********************************************************************** + * NAME EXPORTED + * IoCreateSymbolicLink + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PSYMLNK_OBJECT SymbolicLink; + NTSTATUS Status; + + assert_irql(PASSIVE_LEVEL); + + DPRINT( + "IoCreateSymbolicLink(SymbolicLinkName %S, DeviceName %S)\n", + SymbolicLinkName->Buffer, + DeviceName->Buffer + ); + + InitializeObjectAttributes( + & ObjectAttributes, + SymbolicLinkName, + OBJ_PERMANENT, + NULL, + NULL + ); + Status = ObCreateObject( + NULL, + SYMBOLIC_LINK_ALL_ACCESS, + & ObjectAttributes, + IoSymbolicLinkType, + (PVOID*)&SymbolicLink + ); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + SymbolicLink->TargetName.Length = 0; + SymbolicLink->TargetName.MaximumLength = + ((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR)); + SymbolicLink->TargetName.Buffer = + ExAllocatePoolWithTag(NonPagedPool, + SymbolicLink->TargetName.MaximumLength, + TAG_SYMLINK_TARGET); + RtlCopyUnicodeString( + & (SymbolicLink->TargetName), + DeviceName + ); + + DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer); + + InitializeObjectAttributes( + & (SymbolicLink->Target), + & (SymbolicLink->TargetName), + 0, + NULL, + NULL + ); + + DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__); + ObDereferenceObject( SymbolicLink ); + return STATUS_SUCCESS; +} + + +/********************************************************************** + * NAME EXPORTED + * IoDeleteSymbolicLink + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + NTSTATUS Status; + + assert_irql(PASSIVE_LEVEL); + + DPRINT("IoDeleteSymbolicLink (SymbolicLinkName %S)\n", + SymbolicLinkName->Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + SymbolicLinkName, + OBJ_OPENLINK, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return(Status); + + Status = NtMakeTemporaryObject(Handle); + NtClose(Handle); + + return(Status); +} + + +/********************************************************************** + * NAME (EXPORTED as Zw) + * NtCreateSymbolicLinkObject + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PUNICODE_STRING DeviceName) +{ + PSYMLNK_OBJECT SymbolicLink; + NTSTATUS Status; + + assert_irql(PASSIVE_LEVEL); + + DPRINT("NtCreateSymbolicLinkObject(SymbolicLinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, DeviceName %S)\n", + SymbolicLinkHandle, + DesiredAccess, + ObjectAttributes, + DeviceName->Buffer); + + Status = ObCreateObject(SymbolicLinkHandle, + DesiredAccess, + ObjectAttributes, + IoSymbolicLinkType, + (PVOID*)&SymbolicLink); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + SymbolicLink->TargetName.Length = 0; + SymbolicLink->TargetName.MaximumLength = + ((wcslen(DeviceName->Buffer) + 1) * sizeof(WCHAR)); + SymbolicLink->TargetName.Buffer = + ExAllocatePoolWithTag(NonPagedPool, + SymbolicLink->TargetName.MaximumLength, + TAG_SYMLINK_TARGET); + RtlCopyUnicodeString(&SymbolicLink->TargetName, + DeviceName); + + DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer); + + InitializeObjectAttributes(&SymbolicLink->Target, + &SymbolicLink->TargetName, + 0, + NULL, + NULL); + + DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__); + ObDereferenceObject(SymbolicLink); + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/io/timer.c b/ntoskrnl/io/timer.c new file mode 100644 index 0000000..7ef009a --- /dev/null +++ b/ntoskrnl/io/timer.c @@ -0,0 +1,87 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/timer.c + * PURPOSE: io timers + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* GLBOALS *******************************************************************/ + +#define TAG_IO_TIMER TAG('I', 'O', 'T', 'M') + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +IoInitializeTimer(PDEVICE_OBJECT DeviceObject, + PIO_TIMER_ROUTINE TimerRoutine, + PVOID Context) +/* + * FUNCTION: Sets up a driver-supplied IoTimer routine associated with a given + * device object + * ARGUMENTS: + * DeviceObject = Device object whose timer is be initialized + * TimerRoutine = Driver supplied routine which will be called once per + * second if the timer is active + * Context = Driver supplied context to be passed to the TimerRoutine + * RETURNS: Status + */ +{ + DeviceObject->Timer = ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_TIMER), + TAG_IO_TIMER); + KeInitializeTimer(&(DeviceObject->Timer->timer)); + KeInitializeDpc(&(DeviceObject->Timer->dpc), + (PKDEFERRED_ROUTINE)TimerRoutine,Context); + + return(STATUS_SUCCESS); +} + +VOID +STDCALL +IoStartTimer(PDEVICE_OBJECT DeviceObject) +/* + * FUNCTION: Starts a timer so the driver-supplied IoTimer routine will be + * called once per second + * ARGUMENTS: + * DeviceObject = Device whose timer is to be started + */ +{ + long long int lli; + LARGE_INTEGER li; + + lli = -1000000; + li = *(LARGE_INTEGER *)&lli; + + KeSetTimerEx(&DeviceObject->Timer->timer, + li, + 1000, + &(DeviceObject->Timer->dpc)); +} + +VOID +STDCALL +IoStopTimer(PDEVICE_OBJECT DeviceObject) +/* + * FUNCTION: Disables for a specified device object so the driver-supplied + * IoTimer is not called + * ARGUMENTS: + * DeviceObject = Device whose timer is to be stopped + */ +{ + KeCancelTimer(&(DeviceObject->Timer->timer)); +} + + +/* EOF */ diff --git a/ntoskrnl/io/vpb.c b/ntoskrnl/io/vpb.c new file mode 100644 index 0000000..72744a5 --- /dev/null +++ b/ntoskrnl/io/vpb.c @@ -0,0 +1,365 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/vpb.c + * PURPOSE: Volume Parameter Block managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static KSPIN_LOCK IoVpbLock; + +#define TAG_VPB TAG('V', 'P', 'B', ' ') +#define TAG_SYSB TAG('S', 'Y', 'S', 'B') + +/* FUNCTIONS *****************************************************************/ + +VOID +IoInitVpbImplementation(VOID) +{ + KeInitializeSpinLock(&IoVpbLock); +} + +NTSTATUS +IoAttachVpb(PDEVICE_OBJECT DeviceObject) +{ + PVPB Vpb; + + Vpb = ExAllocatePoolWithTag(NonPagedPool, + sizeof(VPB), + TAG_VPB); + if (Vpb == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + Vpb->Type = 0; + Vpb->Size = sizeof(VPB) / sizeof(DWORD); + Vpb->Flags = 0; + Vpb->VolumeLabelLength = 0; + Vpb->DeviceObject = NULL; + Vpb->RealDevice = DeviceObject; + Vpb->SerialNumber = 0; + Vpb->ReferenceCount = 0; + RtlZeroMemory(Vpb->VolumeLabel, + sizeof(WCHAR) * MAXIMUM_VOLUME_LABEL_LENGTH); + + DeviceObject->Vpb = Vpb; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtQueryVolumeInformationFile(IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass) + +/* + * FUNCTION: Queries the volume information + * ARGUMENTS: + * FileHandle = Handle to a file object on the target volume + * ReturnLength = DataWritten + * FsInformation = Caller should supply storage for the information + * structure. + * Length = Size of the information structure + * FsInformationClass = Index to a information structure + * + * FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION + * FileFsLabelInformation FILE_FS_LABEL_INFORMATION + * FileFsSizeInformation FILE_FS_SIZE_INFORMATION + * FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION + * FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION + * FileFsControlInformation + * FileFsQuotaQueryInformation -- + * FileFsQuotaSetInformation -- + * FileFsMaximumInformation + * + * RETURNS: Status + */ +{ + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + NTSTATUS Status; + PIO_STACK_LOCATION StackPtr; + PVOID SystemBuffer; + IO_STATUS_BLOCK IoSB; + + assert(IoStatusBlock != NULL); + assert(FsInformation != NULL); + + DPRINT("FsInformation %p\n", FsInformation); + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_READ_ATTRIBUTES, + IoFileObjectType, + UserMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize, + TRUE); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (SystemBuffer == NULL) + { + IoFreeIrp(Irp); + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irp->AssociatedIrp.SystemBuffer = SystemBuffer; + KeResetEvent( &FileObject->Event ); + Irp->UserEvent = &FileObject->Event; + Irp->UserIosb = &IoSB; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = FileObject; + StackPtr->Parameters.QueryVolume.Length = Length; + StackPtr->Parameters.QueryVolume.FsInformationClass = + FsInformationClass; + + Status = IoCallDriver(DeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, + UserRequest, + KernelMode, + FALSE, + NULL); + Status = IoSB.Status; + } + DPRINT("Status %x\n", Status); + + if (NT_SUCCESS(Status)) + { + DPRINT("Information %lu\n", IoStatusBlock->Information); + MmSafeCopyToUser(FsInformation, + SystemBuffer, + IoSB.Information); + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + ExFreePool(SystemBuffer); + + return(Status); +} + + +NTSTATUS STDCALL +IoQueryVolumeInformation(IN PFILE_OBJECT FileObject, + IN FS_INFORMATION_CLASS FsInformationClass, + IN ULONG Length, + OUT PVOID FsInformation, + OUT PULONG ReturnedLength) +{ + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION StackPtr; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + NTSTATUS Status; + + assert(FsInformation != NULL); + + DPRINT("FsInformation %p\n", FsInformation); + + Status = ObReferenceObjectByPointer(FileObject, + FILE_READ_ATTRIBUTES, + IoFileObjectType, + KernelMode); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize, + TRUE); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irp->AssociatedIrp.SystemBuffer = FsInformation; + KeResetEvent( &FileObject->Event ); + Irp->UserEvent = &FileObject->Event; + Irp->UserIosb = &IoStatusBlock; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = FileObject; + StackPtr->Parameters.QueryVolume.Length = Length; + StackPtr->Parameters.QueryVolume.FsInformationClass = + FsInformationClass; + + Status = IoCallDriver(DeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, + UserRequest, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + DPRINT("Status %x\n", Status); + + if (ReturnedLength != NULL) + { + *ReturnedLength = IoStatusBlock.Information; + } + + return(Status); +} + + +NTSTATUS STDCALL +NtSetVolumeInformationFile(IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID FsInformation, + IN ULONG Length, + IN FS_INFORMATION_CLASS FsInformationClass) +{ + PFILE_OBJECT FileObject; + PDEVICE_OBJECT DeviceObject; + PIRP Irp; + NTSTATUS Status; + PIO_STACK_LOCATION StackPtr; + PVOID SystemBuffer; + IO_STATUS_BLOCK IoSB; + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_WRITE_ATTRIBUTES, + NULL, + UserMode, + (PVOID*)&FileObject, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + DeviceObject = FileObject->DeviceObject; + + Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (SystemBuffer == NULL) + { + IoFreeIrp(Irp); + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + MmSafeCopyFromUser(SystemBuffer, + FsInformation, + Length); + + Irp->AssociatedIrp.SystemBuffer = SystemBuffer; + KeResetEvent( &FileObject->Event ); + Irp->UserEvent = &FileObject->Event; + Irp->UserIosb = &IoSB; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION; + StackPtr->MinorFunction = 0; + StackPtr->Flags = 0; + StackPtr->Control = 0; + StackPtr->DeviceObject = DeviceObject; + StackPtr->FileObject = FileObject; + StackPtr->Parameters.SetVolume.Length = Length; + StackPtr->Parameters.SetVolume.FsInformationClass = + FsInformationClass; + + Status = IoCallDriver(DeviceObject,Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, + UserRequest, + KernelMode, + FALSE, + NULL); + Status = IoSB.Status; + } + if (IoStatusBlock) + { + *IoStatusBlock = IoSB; + } + ExFreePool(SystemBuffer); + + return(Status); +} + + +VOID STDCALL +IoAcquireVpbSpinLock(OUT PKIRQL Irql) +{ + KeAcquireSpinLock(&IoVpbLock, + Irql); +} + + +VOID STDCALL +IoReleaseVpbSpinLock(IN KIRQL Irql) +{ + KeReleaseSpinLock(&IoVpbLock, + Irql); +} + +/* EOF */ diff --git a/ntoskrnl/io/xhaldisp.c b/ntoskrnl/io/xhaldisp.c new file mode 100644 index 0000000..91d00ed --- /dev/null +++ b/ntoskrnl/io/xhaldisp.c @@ -0,0 +1,49 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/xhaldisp.c + * PURPOSE: Hal dispatch tables + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 19/06/2000 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* DATA **********************************************************************/ + + +HAL_DISPATCH EXPORTED HalDispatchTable = +{ + HAL_DISPATCH_VERSION, + (pHalQuerySystemInformation) NULL, // HalQuerySystemInformation + (pHalSetSystemInformation) NULL, // HalSetSystemInformation + (pHalQueryBusSlots) NULL, // HalQueryBusSlots + (pHalDeviceControl) NULL, // HalDeviceControl + (pHalExamineMBR) xHalExamineMBR, + (pHalIoAssignDriveLetters) xHalIoAssignDriveLetters, + (pHalIoReadPartitionTable) xHalIoReadPartitionTable, + (pHalIoSetPartitionInformation) xHalIoSetPartitionInformation, + (pHalIoWritePartitionTable) xHalIoWritePartitionTable, + (pHalHandlerForBus) NULL, // HalReferenceHandlerForBus + (pHalReferenceBusHandler) NULL, // HalReferenceBusHandler + (pHalReferenceBusHandler) NULL // HalDereferenceBusHandler +}; + + +HAL_PRIVATE_DISPATCH EXPORTED HalPrivateDispatchTable = +{ + HAL_PRIVATE_DISPATCH_VERSION + // HalHandlerForBus + // HalHandlerForConfigSpace + // HalCompleteDeviceControl + // HalRegisterBusHandler + // any more?? +}; + +/* EOF */ + diff --git a/ntoskrnl/io/xhaldrv.c b/ntoskrnl/io/xhaldrv.c new file mode 100644 index 0000000..39973e0 --- /dev/null +++ b/ntoskrnl/io/xhaldrv.c @@ -0,0 +1,808 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/xhaldrv.c + * PURPOSE: Hal drive routines + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 19/06/2000 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* LOCAL MACROS and TYPES ***************************************************/ + +#define AUTO_DRIVE ((ULONG)-1) + +#define PARTITION_MAGIC 0xaa55 +#define PART_MAGIC_OFFSET 0x01fe +#define PARTITION_OFFSET 0x01be +#define SIGNATURE_OFFSET 0x01b8 +#define PARTITION_TBL_SIZE 4 + + +typedef struct _PARTITION +{ + unsigned char BootFlags; + unsigned char StartingHead; + unsigned char StartingSector; + unsigned char StartingCylinder; + unsigned char PartitionType; + unsigned char EndingHead; + unsigned char EndingSector; + unsigned char EndingCylinder; + unsigned int StartingBlock; + unsigned int SectorCount; +} PARTITION, *PPARTITION; + +typedef struct _PARTITION_TABLE +{ + PARTITION Partition[PARTITION_TBL_SIZE]; + unsigned short Magic; +} PARTITION_TABLE, *PPARTITION_TABLE; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName, + OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo) +{ + IO_STATUS_BLOCK StatusBlock; + DISK_GEOMETRY DiskGeometry; + PDEVICE_OBJECT DeviceObject = NULL; + PFILE_OBJECT FileObject; + KEVENT Event; + PIRP Irp; + NTSTATUS Status; + + DPRINT("xHalpQueryDriveLayout %wZ %p\n", + DeviceName, + LayoutInfo); + + /* Get the drives sector size */ + Status = IoGetDeviceObjectPointer(DeviceName, + FILE_READ_DATA, + &FileObject, + &DeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Status %x\n",Status); + return(Status); + } + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, + DeviceObject, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY), + FALSE, + &Event, + &StatusBlock); + if (Irp == NULL) + { + ObDereferenceObject(FileObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = IoCallDriver(DeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = StatusBlock.Status; + } + if (!NT_SUCCESS(Status)) + { + if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + DiskGeometry.BytesPerSector = 512; + } + else + { + ObDereferenceObject(FileObject); + return(Status); + } + } + + DPRINT("DiskGeometry.BytesPerSector: %d\n", + DiskGeometry.BytesPerSector); + + /* read the partition table */ + Status = IoReadPartitionTable(DeviceObject, + DiskGeometry.BytesPerSector, + FALSE, + LayoutInfo); + + if ((!NT_SUCCESS(Status) || (*LayoutInfo)->PartitionCount == 0) && + DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) + { + PDRIVE_LAYOUT_INFORMATION Buffer; + + if (NT_SUCCESS(Status)) + { + ExFreePool(*LayoutInfo); + } + + /* Allocate a partition list for a single entry. */ + Buffer = ExAllocatePool(NonPagedPool, + sizeof(DRIVE_LAYOUT_INFORMATION)); + if (Buffer != NULL) + { + RtlZeroMemory(Buffer, + sizeof(DRIVE_LAYOUT_INFORMATION)); + Buffer->PartitionCount = 1; + *LayoutInfo = Buffer; + + Status = STATUS_SUCCESS; + } + } + + ObDereferenceObject(FileObject); + + return(Status); +} + + +VOID FASTCALL +xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG MBRTypeIdentifier, + OUT PVOID *Buffer) +{ + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + LARGE_INTEGER Offset; + PUCHAR LocalBuffer; + PIRP Irp; + NTSTATUS Status; + + DPRINT("xHalExamineMBR()\n"); + *Buffer = NULL; + + if (SectorSize < 512) + SectorSize = 512; + if (SectorSize > 4096) + SectorSize = 4096; + + LocalBuffer = (PUCHAR)ExAllocatePool(PagedPool, + SectorSize); + if (LocalBuffer == NULL) + return; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Offset.QuadPart = 0; + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + LocalBuffer, + SectorSize, + &Offset, + &Event, + &StatusBlock); + + Status = IoCallDriver(DeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = StatusBlock.Status; + } + + if (!NT_SUCCESS(Status)) + { + DPRINT("xHalExamineMBR failed (Status = 0x%08lx)\n", + Status); + ExFreePool(LocalBuffer); + return; + } + + if (LocalBuffer[0x1FE] != 0x55 || LocalBuffer[0x1FF] != 0xAA) + { + DPRINT("xHalExamineMBR: invalid MBR signature\n"); + ExFreePool(LocalBuffer); + return; + } + + if (LocalBuffer[0x1C2] != MBRTypeIdentifier) + { + DPRINT("xHalExamineMBR: invalid MBRTypeIdentifier\n"); + ExFreePool(LocalBuffer); + return; + } + + *Buffer = (PVOID)LocalBuffer; +} + + +static VOID +HalpAssignDrive(IN PUNICODE_STRING PartitionName, + IN ULONG DriveNumber, + IN UCHAR DriveType) +{ + WCHAR DriveNameBuffer[8]; + UNICODE_STRING DriveName; + ULONG i; + + DPRINT("HalpAssignDrive()\n"); + + if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 24)) + { + /* Force assignment */ + if ((SharedUserData->DosDeviceMap & (1 << DriveNumber)) != 0) + { + DbgPrint("Drive letter already used!\n"); + return; + } + } + else + { + /* Automatic assignment */ + DriveNumber = AUTO_DRIVE; + + for (i = 2; i < 24; i++) + { + if ((SharedUserData->DosDeviceMap & (1 << i)) == 0) + { + DriveNumber = i; + break; + } + } + + if (DriveNumber == AUTO_DRIVE) + { + DbgPrint("No drive letter available!\n"); + return; + } + } + + DPRINT("DriveNumber %d\n", DriveNumber); + + /* Update the shared user page */ + SharedUserData->DosDeviceMap |= (1 << DriveNumber); + SharedUserData->DosDeviceDriveType[DriveNumber] = DriveType; + + /* Build drive name */ + swprintf(DriveNameBuffer, + L"\\??\\%C:", + 'A' + DriveNumber); + RtlInitUnicodeString(&DriveName, + DriveNameBuffer); + + DPRINT(" %wZ ==> %wZ\n", + &DriveName, + PartitionName); + + /* Create symbolic link */ + IoCreateSymbolicLink(&DriveName, + PartitionName); +} + + +VOID FASTCALL +xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PSTRING NtDeviceName, + OUT PUCHAR NtSystemPath, + OUT PSTRING NtSystemPathString) +{ + PDRIVE_LAYOUT_INFORMATION *LayoutArray; + PCONFIGURATION_INFORMATION ConfigInfo; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK StatusBlock; + UNICODE_STRING UnicodeString1; + UNICODE_STRING UnicodeString2; + HANDLE FileHandle; + PWSTR Buffer1; + PWSTR Buffer2; + ULONG i; + NTSTATUS Status; + ULONG j; + + DPRINT("xHalIoAssignDriveLetters()\n"); + + ConfigInfo = IoGetConfigurationInformation(); + + Buffer1 = (PWSTR)ExAllocatePool(PagedPool, + 64 * sizeof(WCHAR)); + Buffer2 = (PWSTR)ExAllocatePool(PagedPool, + 32 * sizeof(WCHAR)); + + /* Create PhysicalDrive links */ + DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount); + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + swprintf(Buffer1, + L"\\Device\\Harddisk%d\\Partition0", + i); + RtlInitUnicodeString(&UnicodeString1, + Buffer1); + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString1, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + 0x10001, + &ObjectAttributes, + &StatusBlock, + 1, + FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS(Status)) + { + NtClose(FileHandle); + + swprintf(Buffer2, + L"\\??\\PhysicalDrive%d", + i); + RtlInitUnicodeString(&UnicodeString2, + Buffer2); + + DPRINT("Creating link: %S ==> %S\n", + Buffer2, + Buffer1); + + IoCreateSymbolicLink(&UnicodeString2, + &UnicodeString1); + } + } + + /* Initialize layout array */ + LayoutArray = ExAllocatePool(NonPagedPool, + ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION)); + RtlZeroMemory(LayoutArray, + ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION)); + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + swprintf(Buffer1, + L"\\Device\\Harddisk%d\\Partition0", + i); + RtlInitUnicodeString(&UnicodeString1, + Buffer1); + + Status = xHalQueryDriveLayout(&UnicodeString1, + &LayoutArray[i]); + if (!NT_SUCCESS(Status)) + { + DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n", + Status); + LayoutArray[i] = NULL; + continue; + } + } + +#ifndef NDEBUG + /* Dump layout array */ + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + DPRINT("Harddisk %d:\n", + i); + + if (LayoutArray[i] == NULL) + continue; + + DPRINT("Logical partitions: %d\n", + LayoutArray[i]->PartitionCount); + + for (j = 0; j < LayoutArray[i]->PartitionCount; j++) + { + DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n", + j, + LayoutArray[i]->PartitionEntry[j].PartitionNumber, + LayoutArray[i]->PartitionEntry[j].BootIndicator, + LayoutArray[i]->PartitionEntry[j].PartitionType, + LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart, + LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart); + } + } +#endif + + /* Assign pre-assigned (registry) partitions */ + + + /* Assign bootable partition on first harddisk */ + DPRINT("Assigning bootable primary partition on first harddisk:\n"); + if (ConfigInfo->DiskCount > 0) + { + /* Search for bootable partition */ + for (j = 0; j < LayoutArray[0]->PartitionCount; j++) + { + if ((LayoutArray[0]->PartitionEntry[j].BootIndicator == TRUE) && + IsRecognizedPartition(LayoutArray[0]->PartitionEntry[j].PartitionType)) + { + swprintf(Buffer2, + L"\\Device\\Harddisk0\\Partition%d", + LayoutArray[0]->PartitionEntry[j].PartitionNumber); + RtlInitUnicodeString(&UnicodeString2, + Buffer2); + + /* Assign drive */ + DPRINT(" %wZ\n", &UnicodeString2); + HalpAssignDrive(&UnicodeString2, + AUTO_DRIVE, + DOSDEVICE_DRIVE_FIXED); + } + } + } + + /* Assign remaining primary partitions */ + DPRINT("Assigning remaining primary partitions:\n"); + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + /* Search for primary partitions */ + for (j = 0; (j < PARTITION_TBL_SIZE) && (j < LayoutArray[i]->PartitionCount); j++) + { + if ((i == 0) && (LayoutArray[i]->PartitionEntry[j].BootIndicator == TRUE)) + continue; + + if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType)) + { + swprintf(Buffer2, + L"\\Device\\Harddisk%d\\Partition%d", + i, + LayoutArray[i]->PartitionEntry[j].PartitionNumber); + RtlInitUnicodeString(&UnicodeString2, + Buffer2); + + /* Assign drive */ + DPRINT(" %wZ\n", + &UnicodeString2); + HalpAssignDrive(&UnicodeString2, + AUTO_DRIVE, + DOSDEVICE_DRIVE_FIXED); + } + } + } + + /* Assign extended (logical) partitions */ + DPRINT("Assigning extended (logical) partitions:\n"); + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + if (LayoutArray[i]) + { + /* Search for extended partitions */ + for (j = PARTITION_TBL_SIZE; j < LayoutArray[i]->PartitionCount; j++) + { + if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) && + (LayoutArray[i]->PartitionEntry[j].PartitionNumber != 0)) + { + swprintf(Buffer2, + L"\\Device\\Harddisk%d\\Partition%d", + i, + LayoutArray[i]->PartitionEntry[j].PartitionNumber); + RtlInitUnicodeString(&UnicodeString2, + Buffer2); + + /* Assign drive */ + DPRINT(" %wZ\n", + &UnicodeString2); + HalpAssignDrive(&UnicodeString2, + AUTO_DRIVE, + DOSDEVICE_DRIVE_FIXED); + } + } + } + } + + /* Assign removable disk drives */ + DPRINT("Assigning removable disk drives:\n"); + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + /* Search for virtual partitions */ + if (LayoutArray[i]->PartitionCount == 1 && + LayoutArray[i]->PartitionEntry[0].PartitionType == 0) + { + swprintf(Buffer2, + L"\\Device\\Harddisk%d\\Partition1", + i); + RtlInitUnicodeString(&UnicodeString2, + Buffer2); + + /* Assign drive */ + DPRINT(" %wZ\n", + &UnicodeString2); + HalpAssignDrive(&UnicodeString2, + AUTO_DRIVE, + DOSDEVICE_DRIVE_REMOVABLE); + } + } + + /* Free layout array */ + for (i = 0; i < ConfigInfo->DiskCount; i++) + { + if (LayoutArray[i] != NULL) + ExFreePool(LayoutArray[i]); + } + ExFreePool(LayoutArray); + + /* Assign floppy drives */ + DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount); + for (i = 0; i < ConfigInfo->FloppyCount; i++) + { + swprintf(Buffer1, + L"\\Device\\Floppy%d", + i); + RtlInitUnicodeString(&UnicodeString1, + Buffer1); + + /* Assign drive letters A: or B: or first free drive letter */ + DPRINT(" %wZ\n", + &UnicodeString1); + HalpAssignDrive(&UnicodeString1, + (i < 2) ? i : AUTO_DRIVE, + DOSDEVICE_DRIVE_REMOVABLE); + } + + /* Assign cdrom drives */ + DPRINT("CD-Rom drives: %d\n", ConfigInfo->CDRomCount); + for (i = 0; i < ConfigInfo->CDRomCount; i++) + { + swprintf(Buffer1, + L"\\Device\\CdRom%d", + i); + RtlInitUnicodeString(&UnicodeString1, + Buffer1); + + /* Assign first free drive letter */ + DPRINT(" %wZ\n", &UnicodeString1); + HalpAssignDrive(&UnicodeString1, + AUTO_DRIVE, + DOSDEVICE_DRIVE_CDROM); + } + + /* Anything else ?? */ + + ExFreePool(Buffer2); + ExFreePool(Buffer1); +} + + +NTSTATUS FASTCALL +xHalIoReadPartitionTable(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + BOOLEAN ReturnRecognizedPartitions, + PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) +{ + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + ULARGE_INTEGER PartitionOffset; + ULARGE_INTEGER nextPartitionOffset; + ULARGE_INTEGER containerOffset; + PUCHAR SectorBuffer; + PIRP Irp; + NTSTATUS Status; + PPARTITION_TABLE PartitionTable; + PDRIVE_LAYOUT_INFORMATION LayoutBuffer; + ULONG i; + ULONG Count = 0; + ULONG Number = 1; + BOOLEAN ExtendedFound = FALSE; + + DPRINT("xHalIoReadPartitionTable(%p %lu %x %p)\n", + DeviceObject, + SectorSize, + ReturnRecognizedPartitions, + PartitionBuffer); + + *PartitionBuffer = NULL; + + SectorBuffer = (PUCHAR)ExAllocatePool(PagedPool, + SectorSize); + if (SectorBuffer == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)ExAllocatePool(NonPagedPool, + 0x1000); + if (LayoutBuffer == NULL) + { + ExFreePool(SectorBuffer); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(LayoutBuffer, + 0x1000); + + PartitionOffset.QuadPart = 0; + containerOffset.QuadPart = 0; + + do + { + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + DPRINT("PartitionOffset: %I64u\n", PartitionOffset.QuadPart / SectorSize); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, + DeviceObject, + SectorBuffer, + SectorSize, + (PLARGE_INTEGER)&PartitionOffset, + &Event, + &StatusBlock); + Status = IoCallDriver(DeviceObject, + Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = StatusBlock.Status; + } + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to read partition table sector (Status = 0x%08lx)\n", + Status); + ExFreePool(SectorBuffer); + ExFreePool(LayoutBuffer); + return(Status); + } + + PartitionTable = (PPARTITION_TABLE)(SectorBuffer + PARTITION_OFFSET); + + /* check the boot sector id */ + DPRINT("Magic %x\n", PartitionTable->Magic); + if (PartitionTable->Magic != PARTITION_MAGIC) + { + DbgPrint("Invalid partition table magic\n"); + ExFreePool(SectorBuffer); + *PartitionBuffer = LayoutBuffer; + return(STATUS_SUCCESS); + } + +#ifndef NDEBUG + for (i = 0; i < PARTITION_TBL_SIZE; i++) + { + DPRINT1(" %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n", + i, + PartitionTable->Partition[i].BootFlags, + PartitionTable->Partition[i].PartitionType, + PartitionTable->Partition[i].StartingHead, + PartitionTable->Partition[i].StartingSector & 0x3f, + (((PartitionTable->Partition[i].StartingSector) & 0xc0) << 2) + + PartitionTable->Partition[i].StartingCylinder, + PartitionTable->Partition[i].EndingHead, + PartitionTable->Partition[i].EndingSector, + PartitionTable->Partition[i].EndingCylinder, + PartitionTable->Partition[i].StartingBlock, + PartitionTable->Partition[i].SectorCount); + } +#endif + + if (ExtendedFound == FALSE); + { + LayoutBuffer->Signature = *((PULONG)(SectorBuffer + SIGNATURE_OFFSET)); + } + + ExtendedFound = FALSE; + + for (i = 0; i < PARTITION_TBL_SIZE; i++) + { + if ((ReturnRecognizedPartitions == FALSE) || + ((ReturnRecognizedPartitions == TRUE) && + IsRecognizedPartition(PartitionTable->Partition[i].PartitionType))) + { + /* handle normal partition */ + DPRINT("Partition %u: Normal Partition\n", i); + Count = LayoutBuffer->PartitionCount; + DPRINT("Logical Partition %u\n", Count); + if (PartitionTable->Partition[i].StartingBlock == 0) + { + LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = 0; + } + else if (IsContainerPartition(PartitionTable->Partition[i].PartitionType)) + { + LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = + (ULONGLONG)PartitionOffset.QuadPart; + } + else + { + LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart = + (ULONGLONG)PartitionOffset.QuadPart + + ((ULONGLONG)PartitionTable->Partition[i].StartingBlock * (ULONGLONG)SectorSize); + } + LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart = + (ULONGLONG)PartitionTable->Partition[i].SectorCount * (ULONGLONG)SectorSize; + LayoutBuffer->PartitionEntry[Count].HiddenSectors = 0; + + if (IsRecognizedPartition(PartitionTable->Partition[i].PartitionType)) + { + LayoutBuffer->PartitionEntry[Count].PartitionNumber = Number; + Number++; + } + else + { + LayoutBuffer->PartitionEntry[Count].PartitionNumber = 0; + } + + LayoutBuffer->PartitionEntry[Count].PartitionType = + PartitionTable->Partition[i].PartitionType; + LayoutBuffer->PartitionEntry[Count].BootIndicator = + (PartitionTable->Partition[i].BootFlags & 0x80)?TRUE:FALSE; + LayoutBuffer->PartitionEntry[Count].RecognizedPartition = + IsRecognizedPartition (PartitionTable->Partition[i].PartitionType); + LayoutBuffer->PartitionEntry[Count].RewritePartition = FALSE; + + DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x\n", + Count, + LayoutBuffer->PartitionEntry[Count].PartitionNumber, + LayoutBuffer->PartitionEntry[Count].BootIndicator, + LayoutBuffer->PartitionEntry[Count].PartitionType, + LayoutBuffer->PartitionEntry[Count].StartingOffset.QuadPart, + LayoutBuffer->PartitionEntry[Count].PartitionLength.QuadPart); + + LayoutBuffer->PartitionCount++; + } + + if (IsContainerPartition(PartitionTable->Partition[i].PartitionType)) + { + ExtendedFound = TRUE; + if ((ULONGLONG) containerOffset.QuadPart == (ULONGLONG) 0) + { + containerOffset = PartitionOffset; + } + nextPartitionOffset.QuadPart = (ULONGLONG) containerOffset.QuadPart + + (ULONGLONG) PartitionTable->Partition[i].StartingBlock * + (ULONGLONG) SectorSize; + } + } + PartitionOffset = nextPartitionOffset; + } + while (ExtendedFound == TRUE); + + *PartitionBuffer = LayoutBuffer; + ExFreePool(SectorBuffer); + + return(STATUS_SUCCESS); +} + + +NTSTATUS FASTCALL +xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG PartitionNumber, + IN ULONG PartitionType) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS FASTCALL +xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, + IN ULONG SectorSize, + IN ULONG SectorsPerTrack, + IN ULONG NumberOfHeads, + IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer) +{ + return(STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/ntoskrnl/kd/.cvsignore b/ntoskrnl/kd/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/kd/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/kd/dlog.c b/ntoskrnl/kd/dlog.c new file mode 100644 index 0000000..e03cef7 --- /dev/null +++ b/ntoskrnl/kd/dlog.c @@ -0,0 +1,222 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/kd/kdebug.c + * PURPOSE: Kernel debugger + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * 21/10/99: Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +/* GLOBALS *******************************************************************/ + +#define DEBUGLOG_SIZE (32*1024) + +#ifdef DBGPRINT_FILE_LOG + +static CHAR DebugLog[DEBUGLOG_SIZE]; +static ULONG DebugLogStart; +static ULONG DebugLogEnd; +static ULONG DebugLogCount; +static KSPIN_LOCK DebugLogLock; +static ULONG DebugLogOverflow; +static HANDLE DebugLogThreadHandle; +static CLIENT_ID DebugLogThreadCid; +static HANDLE DebugLogFile; +static KSEMAPHORE DebugLogSem; + +#endif /* DBGPRINT_FILE_LOG */ + +/* FUNCTIONS *****************************************************************/ + +#ifdef DBGPRINT_FILE_LOG + +VOID +DebugLogInit(VOID) +{ + KeInitializeSpinLock(&DebugLogLock); + DebugLogStart = 0; + DebugLogEnd = 0; + DebugLogOverflow = 0; + DebugLogCount = 0; + KeInitializeSemaphore(&DebugLogSem, 0, 255); +} + +NTSTATUS +DebugLogThreadMain(PVOID Context) +{ + KIRQL oldIrql; + IO_STATUS_BLOCK Iosb; + static CHAR Buffer[256]; + ULONG WLen; + + for (;;) + { + KeWaitForSingleObject(&DebugLogSem, + 0, + KernelMode, + FALSE, + NULL); + KeAcquireSpinLock(&DebugLogLock, &oldIrql); + while (DebugLogCount > 0) + { + if (DebugLogStart > DebugLogEnd) + { + WLen = min(256, DEBUGLOG_SIZE - DebugLogStart); + memcpy(Buffer, &DebugLog[DebugLogStart], WLen); + DebugLogStart = + (DebugLogStart + WLen) % DEBUGLOG_SIZE; + DebugLogCount = DebugLogCount - WLen; + KeReleaseSpinLock(&DebugLogLock, oldIrql); + NtWriteFile(DebugLogFile, + NULL, + NULL, + NULL, + &Iosb, + Buffer, + WLen, + NULL, + NULL); + } + else + { + WLen = min(256, DebugLogEnd - DebugLogStart); + memcpy(Buffer, &DebugLog[DebugLogStart], WLen); + DebugLogStart = + (DebugLogStart + WLen) % DEBUGLOG_SIZE; + DebugLogCount = DebugLogCount - WLen; + KeReleaseSpinLock(&DebugLogLock, oldIrql); + NtWriteFile(DebugLogFile, + NULL, + NULL, + NULL, + &Iosb, + Buffer, + WLen, + NULL, + NULL); + } + KeAcquireSpinLock(&DebugLogLock, &oldIrql); + } + KeReleaseSpinLock(&DebugLogLock, oldIrql); + } +} + +VOID +DebugLogInit2(VOID) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING FileName; + IO_STATUS_BLOCK Iosb; + + RtlInitUnicodeStringFromLiteral(&FileName, L"\\SystemRoot\\debug.log"); + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + 0, + NULL, + NULL); + + Status = NtCreateFile(&DebugLogFile, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to create debug log file\n"); + return; + } + + Status = PsCreateSystemThread(&DebugLogThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + &DebugLogThreadCid, + DebugLogThreadMain, + NULL); +} + + VOID + DebugLogWrite(PCH String) + { + KIRQL oldIrql; + + if (KeGetCurrentIrql() > DISPATCH_LEVEL) + { + DebugLogOverflow++; + return; + } + + KeAcquireSpinLock(&DebugLogLock, &oldIrql); + + if (DebugLogCount == DEBUGLOG_SIZE) + { + DebugLogOverflow++; + KeReleaseSpinLock(&DebugLogLock, oldIrql); + if (oldIrql < DISPATCH_LEVEL) + { + KeReleaseSemaphore(&DebugLogSem, IO_NO_INCREMENT, 1, FALSE); + } + return; + } + + while ((*String) != 0) + { + DebugLog[DebugLogEnd] = *String; + String++; + DebugLogCount++; + if (DebugLogCount == DEBUGLOG_SIZE) + { + DebugLogOverflow++; + KeReleaseSpinLock(&DebugLogLock, oldIrql); + if (oldIrql < DISPATCH_LEVEL) + { + KeReleaseSemaphore(&DebugLogSem, IO_NO_INCREMENT, 1, FALSE); + } + return; + } + DebugLogEnd = (DebugLogEnd + 1) % DEBUGLOG_SIZE; + } + + KeReleaseSpinLock(&DebugLogLock, oldIrql); + if (oldIrql < DISPATCH_LEVEL) + { + KeReleaseSemaphore(&DebugLogSem, IO_NO_INCREMENT, 1, FALSE); + } + } + + #else /* not DBGPRINT_FILE_LOG */ + + VOID + DebugLogInit(VOID) + { + } + +VOID +DebugLogInit2(VOID) +{ +} + +VOID +DebugLogWrite(PCH String) +{ +} + +#endif /* DBGPRINT_FILE_LOG */ + diff --git a/ntoskrnl/kd/gdbstub.c b/ntoskrnl/kd/gdbstub.c new file mode 100644 index 0000000..2d1ec76 --- /dev/null +++ b/ntoskrnl/kd/gdbstub.c @@ -0,0 +1,1348 @@ +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Modified for ReactOS by Casper S. Hornstrup + * + * To enable debugger support, two things need to happen. One, setting + * up a routine so that it is in the exception path, is necessary in order + * to allow any breakpoints or error conditions to be properly intercepted + * and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. + * + * Because gdb will sometimes write to the stack area to execute function + * calls, this program cannot rely on using the supervisor stack so it + * uses it's own stack area. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU Registers hex data or ENN + * G set the value of the CPU Registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * Checksum. A packet consists of + * + * $#. + * + * where + * :: + * :: < two hex digits computed as modulo 256 sum of > + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +extern LIST_ENTRY PiThreadListHead; + + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 1000 + +static BOOLEAN GspInitialized; +#if 0 +static PKINTERRUPT GspInterrupt; +#endif + +static BOOLEAN GspRemoteDebug; + +static CONST CHAR HexChars[]="0123456789abcdef"; + +static PETHREAD GspRunThread; /* NULL means run all threads */ +static PETHREAD GspDbgThread; +static PETHREAD GspEnumThread; + +/* Number of Registers. */ +#define NUMREGS 16 + +enum REGISTER_NAMES +{ + EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + PC /* also known as eip */, + PS /* also known as eflags */, + CS, SS, DS, ES, FS, GS +}; + +typedef struct _CPU_REGISTER +{ + DWORD Size; + DWORD OffsetInTF; +} CPU_REGISTER, *PCPU_REGISTER; + +#define KTRAP_FRAME_X86 KTRAP_FRAME + +#define EIP_REGNO 8 + +static CPU_REGISTER GspRegisters[NUMREGS] = +{ + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eax) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ecx) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edx) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebx) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esp) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ebp) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Esi) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Edi) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eip) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Eflags) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Cs) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ss) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Ds) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Es) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Fs) }, + { 4, FIELD_OFFSET (KTRAP_FRAME_X86, Gs) } +}; + +static PCHAR GspThreadStates[THREAD_STATE_MAX] = +{ + "Initialized", /* THREAD_STATE_INITIALIZED */ + "Ready", /* THREAD_STATE_READY */ + "Running", /* THREAD_STATE_RUNNING */ + "Suspended", /* THREAD_STATE_SUSPENDED */ + "Frozen", /* THREAD_STATE_FROZEN */ + "Terminated 1", /* THREAD_STATE_TERMINATED_1 */ + "Terminated 2", /* THREAD_STATE_TERMINATED_2 */ + "Blocked" /* THREAD_STATE_BLOCKED */ +}; + +char * +strtok(char *s, const char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s++; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + + +LONG +HexValue (CHAR ch) +{ + if ((ch >= '0') && (ch <= '9')) return (ch - '0'); + if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10); + if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10); + return (-1); +} + +static CHAR GspInBuffer[BUFMAX]; +static CHAR GspOutBuffer[BUFMAX]; + +/* scan for the sequence $# */ + +PCHAR +GspGetPacket() +{ + PCHAR Buffer = &GspInBuffer[0]; + CHAR Checksum; + CHAR XmitChecksum; + ULONG Count; + CHAR ch; + + while (TRUE) + { + /* wait around for the start character, ignore all other characters */ + while ((ch = KdGetChar ()) != '$'); + + retry: + Checksum = 0; + XmitChecksum = -1; + Count = 0; + + /* now, read until a # or end of Buffer is found */ + while (Count < BUFMAX) + { + ch = KdGetChar (); + if (ch == '$') + goto retry; + if (ch == '#') + break; + Checksum = Checksum + ch; + Buffer[Count] = ch; + Count = Count + 1; + } + Buffer[Count] = 0; + + if (ch == '#') + { + ch = KdGetChar (); + XmitChecksum = HexValue (ch) << 4; + ch = KdGetChar (); + XmitChecksum += HexValue (ch); + + if (Checksum != XmitChecksum) + { + KdPutChar ('-'); /* failed checksum */ + } + else + { + KdPutChar ('+'); /* successful transfer */ + + /* if a sequence char is present, reply the sequence ID */ + if (Buffer[2] == ':') + { + KdPutChar (Buffer[0]); + KdPutChar (Buffer[1]); + + return &Buffer[3]; + } + + return &Buffer[0]; + } + } + } +} + +/* send the packet in Buffer. */ + +VOID +GspPutPacket (PCHAR Buffer) +{ + CHAR Checksum; + LONG Count; + CHAR ch; + + /* $#. */ + do + { + KdPutChar ('$'); + Checksum = 0; + Count = 0; + + while ((ch = Buffer[Count])) + { + KdPutChar (ch); + Checksum += ch; + Count += 1; + } + + KdPutChar ('#'); + KdPutChar (HexChars[(Checksum >> 4) & 0xf]); + KdPutChar (HexChars[Checksum & 0xf]); + } + while (KdGetChar () != '+'); +} + + +VOID +GspPutPacketNoWait (PCHAR Buffer) +{ + CHAR Checksum; + LONG Count; + CHAR ch; + + /* $#. */ + KdPutChar ('$'); + Checksum = 0; + Count = 0; + + while ((ch = Buffer[Count])) + { + KdPutChar (ch); + Checksum += ch; + Count += 1; + } + + KdPutChar ('#'); + KdPutChar (HexChars[(Checksum >> 4) & 0xf]); + KdPutChar (HexChars[Checksum & 0xf]); +} + + +VOID +GspDebugError(LPSTR Message) +{ + DbgPrint ("%s\n", Message); +} + +/* Address of a routine to RTE to if we get a memory fault. */ +static VOID (*volatile MemoryFaultRoutine) () = NULL; + +/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an + error. */ +static volatile BOOLEAN GspMemoryError = FALSE; + + +/* Currently not used */ +VOID +GspSetMemoryError() +{ + GspMemoryError = TRUE; +} + + +/* These are separate functions so that they are so short and sweet + that the compiler won't save any Registers (if there is a fault + to MemoryFaultRoutine, they won't get restored, so there better + not be any saved). */ +CHAR +GspGetChar (PCHAR Address) +{ + return *Address; +} + + +VOID +GspSetChar (PCHAR Address, + CHAR Value) +{ + *Address = Value; +} + + +/* Convert the memory pointed to by Address into hex, placing result in Buffer */ +/* Return a pointer to the last char put in Buffer (null) */ +/* If MayFault is TRUE, then we should set GspMemoryError in response to + a fault; if FALSE treat a fault like any other fault in the stub. */ +PCHAR +GspMem2Hex (PCHAR Address, + PCHAR Buffer, + LONG Count, + BOOLEAN MayFault) +{ + ULONG i; + CHAR ch; + + if (MayFault) + MemoryFaultRoutine = GspSetMemoryError; + for (i = 0; i < Count; i++) + { + ch = GspGetChar (Address++); + if (MayFault && GspMemoryError) + return (Buffer); + *Buffer++ = HexChars[(ch >> 4) & 0xf]; + *Buffer++ = HexChars[ch & 0xf]; + } + *Buffer = 0; + if (MayFault) + MemoryFaultRoutine = NULL; + return (Buffer); +} + + +/* Convert the hex array pointed to by Buffer into binary to be placed at Address */ +/* Return a pointer to the character AFTER the last byte read from Buffer */ +PCHAR +GspHex2Mem (PCHAR Buffer, + PCHAR Address, + ULONG Count, + BOOLEAN MayFault) +{ + ULONG i; + CHAR ch; + + if (MayFault) + MemoryFaultRoutine = GspSetMemoryError; + for (i = 0; i < Count; i++) + { + ch = HexValue (*Buffer++) << 4; + ch = ch + HexValue (*Buffer++); + GspSetChar (Address++, ch); + if (MayFault && GspMemoryError) + return (Buffer); + } + if (MayFault) + MemoryFaultRoutine = NULL; + return (Buffer); +} + + +/* This function takes the 386 exception vector and attempts to + translate this number into a unix compatible signal value */ +ULONG +GspComputeSignal (NTSTATUS ExceptionCode) +{ + ULONG SigVal; + + switch (ExceptionCode) + { + case STATUS_INTEGER_DIVIDE_BY_ZERO: + SigVal = 8; + break; /* divide by zero */ + case STATUS_SINGLE_STEP: + SigVal = 5; + break; /* debug exception */ + case STATUS_BREAKPOINT: + SigVal = 5; + break; /* breakpoint */ + case STATUS_INTEGER_OVERFLOW: + SigVal = 16; + break; /* into instruction (overflow) */ + case STATUS_ARRAY_BOUNDS_EXCEEDED: + SigVal = 16; + break; /* bound instruction */ + case STATUS_ILLEGAL_INSTRUCTION: + SigVal = 4; + break; /* Invalid opcode */ +#if 0 + case STATUS_FLT_INVALID_OPERATION: + SigVal = 8; + break; /* coprocessor not available */ +#endif + case STATUS_STACK_OVERFLOW: + SigVal = 11; + break; /* stack exception */ + case STATUS_DATATYPE_MISALIGNMENT: + SigVal = 11; + break; /* page fault */ + default: + SigVal = 7; /* "software generated" */ + } + return (SigVal); +} + + +/**********************************************/ +/* WHILE WE FIND NICE HEX CHARS, BUILD A LONG */ +/* RETURN NUMBER OF CHARS PROCESSED */ +/**********************************************/ +LONG +GspHex2Long (PCHAR *Address, + PLONG Value) +{ + LONG NumChars = 0; + LONG Hex; + + *Value = 0; + + while (**Address) + { + Hex = HexValue (**Address); + if (Hex >= 0) + { + *Value = (*Value << 4) | Hex; + NumChars++; + } + else + break; + + (*Address)++; + } + + return (NumChars); +} + + +VOID +GspLong2Hex (PCHAR *Address, + LONG Value) +{ + LONG Save; + + Save = (((Value >> 0) & 0xf) << 24) | + (((Value >> 8) & 0xf) << 16) | + (((Value >> 16) & 0xf) << 8) | + (((Value >> 24) & 0xf) << 0); + *Address = GspMem2Hex ((PCHAR) &Save, *Address, 4, FALSE); +} + + +VOID +GspGetRegistersFromTrapFrame(PCHAR Address, + PKTRAP_FRAME TrapFrame) +{ + PCPU_REGISTER Regs; + ULONG Value; + PCHAR Buffer; + PULONG p; + DWORD i; + + Buffer = Address; + Regs = &GspRegisters[0]; + for (i = 0; i < NUMREGS; i++) + { + if (TrapFrame) + { + p = (PULONG) ((ULONG_PTR) TrapFrame + Regs[i].OffsetInTF); + Value = *p; + } + else if (i == EIP_REGNO) + { + /* + * This thread has not been sheduled yet so assume it + * is still in PsBeginThreadWithContextInternal(). + */ + Value = (ULONG) PsBeginThreadWithContextInternal; + } + else + { + Value = 0; + } + Buffer = GspMem2Hex ((PCHAR) &Value, Buffer, Regs[i].Size, FALSE); + } +} + + +VOID +GspSetRegistersInTrapFrame(PCHAR Address, + PKTRAP_FRAME TrapFrame) +{ + PCPU_REGISTER Regs; + ULONG Value; + PCHAR Buffer; + PULONG p; + DWORD i; + + if (!TrapFrame) + return; + + Buffer = Address; + Regs = &GspRegisters[0]; + for (i = 0; i < NUMREGS; i++) + { + p = (PULONG) ((ULONG_PTR) TrapFrame + Regs[i].OffsetInTF); + Value = 0; + Buffer = GspHex2Mem (Buffer, (PCHAR) &Value, Regs[i].Size, FALSE); + *p = Value; + } +} + + +VOID +GspSetSingleRegisterInTrapFrame(PCHAR Address, + LONG Number, + PKTRAP_FRAME TrapFrame) +{ + ULONG Value; + PULONG p; + + if (!TrapFrame) + return; + + p = (PULONG) ((ULONG_PTR) TrapFrame + GspRegisters[Number].OffsetInTF); + Value = 0; + GspHex2Mem (Address, (PCHAR) &Value, GspRegisters[Number].Size, FALSE); + *p = Value; +} + + +BOOLEAN +GspFindThread(PCHAR Data, + PETHREAD *Thread) +{ + PETHREAD ThreadInfo = NULL; + + if (strcmp (Data, "-1") == 0) + { + /* All threads */ + ThreadInfo = NULL; + } + else if (strcmp (Data, "0") == 0) + { + /* Pick any thread, pick the first thread, + * which is what most people are interested in + */ + ThreadInfo = CONTAINING_RECORD (PiThreadListHead.Flink, + ETHREAD, Tcb.ThreadListEntry); + } + else + { + ULONG ThreadId; + PCHAR ptr = &Data[0]; + + GspHex2Long (&ptr, (PLONG) &ThreadId); + + if (!NT_SUCCESS (PsLookupThreadByThreadId ((PVOID) ThreadId, &ThreadInfo))) + { + *Thread = NULL; + return FALSE; + } + } + *Thread = ThreadInfo; + return TRUE; +} + + +VOID +GspSetThread(PCHAR Request) +{ + PETHREAD ThreadInfo; + PCHAR ptr = &Request[1]; + + switch (Request[0]) + { + case 'c': /* Run thread */ + if (GspFindThread (ptr, &ThreadInfo)) + { + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = 'K'; + GspRunThread = ThreadInfo; + } + else + { + GspOutBuffer[0] = 'E'; + } + break; + case 'g': /* Debug thread */ + if (GspFindThread (ptr, &ThreadInfo)) + { + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = 'K'; + GspDbgThread = ThreadInfo; + } + else + { + GspOutBuffer[0] = 'E'; + } + break; + default: + break; + } +} + + +VOID +GspQuery(PCHAR Request) +{ + PCHAR Command; + ULONG Value; + + Command = strtok (Request, ","); + if (strncmp (Command, "C", 1) == 0) + { + PCHAR ptr = &GspOutBuffer[2]; + + /* Get current thread id */ + GspOutBuffer[0] = 'Q'; + GspOutBuffer[1] = 'C'; + Value = (ULONG) GspDbgThread->Cid.UniqueThread; + GspLong2Hex (&ptr, Value); + } + else if (strncmp (Command, "fThreadInfo", 11) == 0) + { + PCHAR ptr = &GspOutBuffer[1]; + + /* Get first thread id */ + GspOutBuffer[0] = 'm'; + GspEnumThread = CONTAINING_RECORD (PiThreadListHead.Flink, + ETHREAD, Tcb.ThreadListEntry); + Value = (ULONG) GspEnumThread->Cid.UniqueThread; + GspLong2Hex (&ptr, Value); + } + else if (strncmp (Command, "sThreadInfo", 11) == 0) + { + PCHAR ptr = &GspOutBuffer[1]; + + /* Get next thread id */ + if ((GspEnumThread) && (GspEnumThread->Tcb.ThreadListEntry.Flink != PiThreadListHead.Flink)) + { + GspEnumThread = CONTAINING_RECORD (GspEnumThread->Tcb.ThreadListEntry.Flink, + ETHREAD, Tcb.ThreadListEntry); + GspOutBuffer[0] = 'm'; + Value = (ULONG) GspEnumThread->Cid.UniqueThread; + GspLong2Hex (&ptr, Value); + } + else + { + GspOutBuffer[0] = '1'; + } + } + else if (strncmp (Command, "ThreadExtraInfo", 15) == 0) + { + PETHREAD ThreadInfo; + PCHAR ptr = &Command[15]; + + /* Get thread information */ + if (GspFindThread (ptr, &ThreadInfo)) + { + PCHAR String = GspThreadStates[ThreadInfo->Tcb.State]; + GspMem2Hex (String, &GspOutBuffer[0], strlen (String), FALSE); + } + } +#if 0 + else if (strncmp (Command, "L", 1) == 0) + { + PLIST_ENTRY CurrentEntry; + PETHREAD Current; + ULONG MaxThreads = 0; + ULONG ThreadId = 0; + ULONG ThreadCount = 0; + + /* List threads */ + GspHex2Mem (&Request[1], (PCHAR) &MaxThreads, 2, TRUE); + GspHex2Mem (&Request[3], (PCHAR) &Value, 4, TRUE); + GspHex2Mem (&Request[11], (PCHAR) &ThreadId, 4, TRUE); + + GspOutBuffer[0] = 'q'; + GspOutBuffer[1] = 'M'; + Value = 0; + GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[5], 4, TRUE); + GspMem2Hex ((PCHAR) &ThreadId, &GspOutBuffer[13], 4, TRUE); + + CurrentEntry = PiThreadListHead.Flink; + while ((CurrentEntry != &PiThreadListHead) && (ThreadCount < MaxThreads)) + { + Current = CONTAINING_RECORD (CurrentEntry, ETHREAD, Tcb.ThreadListEntry); + Value = 0; + GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[21+ThreadCount*16], 4, TRUE); + Value = (ULONG) Current->Cid.UniqueThread; + GspMem2Hex ((PCHAR) &Value, &GspOutBuffer[21+ThreadCount*16+8], 4, TRUE); + CurrentEntry = CurrentEntry->Flink; + ThreadCount++; + } + + if (CurrentEntry != &PiThreadListHead) + { + GspOutBuffer[4] = '0'; + } + else + { + GspOutBuffer[4] = '1'; + } + + GspMem2Hex ((PCHAR) &ThreadCount, &GspOutBuffer[2], 1, TRUE); + } +#endif + else if (strncmp (Command, "Offsets", 7) == 0) + { + strcpy (GspOutBuffer, "Text=0;Data=0;Bss=0"); + } +} + +VOID +GspQueryThreadStatus(PCHAR Request) +{ + PETHREAD ThreadInfo; + PCHAR ptr = &Request[0]; + + if (GspFindThread (ptr, &ThreadInfo)) + { + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = 'K'; + GspOutBuffer[2] = '\0'; + } + else + { + GspOutBuffer[0] = 'E'; + GspOutBuffer[1] = '\0'; + } +} + + +typedef struct _GsHwBreakPoint +{ + BOOLEAN Enabled; + ULONG Type; + ULONG Length; + ULONG Address; +} GsHwBreakPoint; + +GsHwBreakPoint GspBreakpoints[4] = +{ + { Enabled : FALSE }, + { Enabled : FALSE }, + { Enabled : FALSE }, + { Enabled : FALSE } +}; + +VOID +GspCorrectHwBreakpoint() +{ + ULONG BreakpointNumber; + BOOLEAN CorrectIt; + BOOLEAN Bit; + ULONG dr7; + + asm volatile ( + "movl %%db7, %0\n" : "=r" (dr7) : ); + do + { + ULONG addr0, addr1, addr2, addr3; + + asm volatile ( + "movl %%db0, %0\n" + "movl %%db1, %1\n" + "movl %%db2, %2\n" + "movl %%db3, %3\n" + : "=r" (addr0), "=r" (addr1), + "=r" (addr2), "=r" (addr3) : ); + } while (FALSE); + CorrectIt = FALSE; + for (BreakpointNumber = 0; BreakpointNumber < 3; BreakpointNumber++) + { + Bit = 2 << (BreakpointNumber << 1); + if (!(dr7 & Bit) && GspBreakpoints[BreakpointNumber].Enabled) { + CorrectIt = TRUE; + dr7 |= Bit; + dr7 &= ~(0xf0000 << (BreakpointNumber << 2)); + dr7 |= (((GspBreakpoints[BreakpointNumber].Length << 2) | + GspBreakpoints[BreakpointNumber].Type) << 16) << (BreakpointNumber << 2); + switch (BreakpointNumber) { + case 0: + asm volatile ("movl %0, %%dr0\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + + case 1: + asm volatile ("movl %0, %%dr1\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + + case 2: + asm volatile ("movl %0, %%dr2\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + + case 3: + asm volatile ("movl %0, %%dr3\n" + : : "r" (GspBreakpoints[BreakpointNumber].Address) ); + break; + } + } + else if ((dr7 & Bit) && !GspBreakpoints[BreakpointNumber].Enabled) + { + CorrectIt = TRUE; + dr7 &= ~Bit; + dr7 &= ~(0xf0000 << (BreakpointNumber << 2)); + } + } + if (CorrectIt) + { + asm volatile ( "movl %0, %%db7\n" : : "r" (dr7)); + } +} + +ULONG +GspRemoveHwBreakpoint(ULONG BreakpointNumber) +{ + if (!GspBreakpoints[BreakpointNumber].Enabled) + { + return -1; + } + GspBreakpoints[BreakpointNumber].Enabled = 0; + return 0; +} + + +ULONG +GspSetHwBreakpoint(ULONG BreakpointNumber, + ULONG Type, + ULONG Length, + ULONG Address) +{ + if (GspBreakpoints[BreakpointNumber].Enabled) + { + return -1; + } + GspBreakpoints[BreakpointNumber].Enabled = TRUE; + GspBreakpoints[BreakpointNumber].Type = Type; + GspBreakpoints[BreakpointNumber].Length = Length; + GspBreakpoints[BreakpointNumber].Address = Address; + return 0; +} + + +/* + * This function does all command procesing for interfacing to gdb. + */ +KD_CONTINUE_TYPE +KdEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME TrapFrame) +{ + BOOLEAN Stepping; + LONG Address; + LONG Length; + LONG SigVal; + LONG NewPC; + PCHAR ptr; + + /* FIXME: Stop on other CPUs too */ + /* Disable hardware debugging while we are inside the stub */ + __asm__("movl %0,%%db7" : /* no output */ : "r" (0)); + + /* reply to host that an exception has occurred */ + SigVal = GspComputeSignal (ExceptionRecord->ExceptionCode); + + ptr = &GspOutBuffer[0]; + + *ptr++ = 'T'; /* notify gdb with signo, PC, FP and SP */ + *ptr++ = HexChars[(SigVal >> 4) & 0xf]; + *ptr++ = HexChars[SigVal & 0xf]; + + *ptr++ = HexChars[ESP]; + *ptr++ = ':'; + ptr = GspMem2Hex ((PCHAR) &TrapFrame->Esp, ptr, 4, 0); /* SP */ + *ptr++ = ';'; + + *ptr++ = HexChars[EBP]; + *ptr++ = ':'; + ptr = GspMem2Hex ((PCHAR) &TrapFrame->Ebp, ptr, 4, 0); /* FP */ + *ptr++ = ';'; + + *ptr++ = HexChars[PC]; + *ptr++ = ':'; + ptr = GspMem2Hex((PCHAR) &TrapFrame->Eip, ptr, 4, 0); /* PC */ + *ptr++ = ';'; + + *ptr = '\0'; + + GspPutPacket (&GspOutBuffer[0]); + + Stepping = FALSE; + + while (TRUE) + { + /* Zero the buffer now so we don't have to worry about the terminating zero character */ + memset (GspOutBuffer, 0, sizeof (GspInBuffer)); + ptr = GspGetPacket (); + + switch (*ptr++) + { + case '?': + GspOutBuffer[0] = 'S'; + GspOutBuffer[1] = HexChars[SigVal >> 4]; + GspOutBuffer[2] = HexChars[SigVal % 16]; + GspOutBuffer[3] = 0; + break; + case 'd': + GspRemoteDebug = !GspRemoteDebug; /* toggle debug flag */ + break; + case 'g': /* return the value of the CPU Registers */ + if (GspDbgThread) + GspGetRegistersFromTrapFrame (&GspOutBuffer[0], GspDbgThread->Tcb.TrapFrame); + else + GspGetRegistersFromTrapFrame (&GspOutBuffer[0], TrapFrame); + break; + case 'G': /* set the value of the CPU Registers - return OK */ + if (GspDbgThread) + GspSetRegistersInTrapFrame (ptr, GspDbgThread->Tcb.TrapFrame); + else + GspSetRegistersInTrapFrame (ptr, TrapFrame); + strcpy (GspOutBuffer, "OK"); + break; + case 'P': /* set the value of a single CPU register - return OK */ + { + LONG Register; + + if ((GspHex2Long (&ptr, &Register)) && (*ptr++ == '=')) + if ((Register >= 0) && (Register < NUMREGS)) + { + if (GspDbgThread) + GspSetSingleRegisterInTrapFrame (ptr, Register, + GspDbgThread->Tcb.TrapFrame); + else + GspSetSingleRegisterInTrapFrame (ptr, Register, TrapFrame); + strcpy (GspOutBuffer, "OK"); + break; + } + + strcpy (GspOutBuffer, "E01"); + break; + } + + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + case 'm': + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + if (GspHex2Long (&ptr, &Address)) + if (*(ptr++) == ',') + if (GspHex2Long (&ptr, &Length)) + { + ptr = 0; + GspMemoryError = FALSE; + GspMem2Hex ((PCHAR) Address, GspOutBuffer, Length, 1); + if (GspMemoryError) + { + strcpy (GspOutBuffer, "E03"); + GspDebugError ("memory fault"); + } + } + + if (ptr) + { + strcpy (GspOutBuffer, "E01"); + } + break; + + /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + case 'M': + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + if (GspHex2Long (&ptr, &Address)) + if (*(ptr++) == ',') + if (GspHex2Long (&ptr, &Length)) + if (*(ptr++) == ':') + { + GspMemoryError = FALSE; + GspHex2Mem (ptr, (PCHAR) Address, Length, TRUE); + + if (GspMemoryError) + { + strcpy (GspOutBuffer, "E03"); + GspDebugError ("memory fault"); + } + else + { + strcpy (GspOutBuffer, "OK"); + } + + ptr = NULL; + } + if (ptr) + { + strcpy (GspOutBuffer, "E02"); + } + break; + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + case 's': + Stepping = TRUE; + case 'c': + { + ULONG BreakpointNumber; + ULONG dr6; + + /* try to read optional parameter, pc unchanged if no parm */ + if (GspHex2Long (&ptr, &Address)) + Context->Eip = Address; + + NewPC = Context->Eip; + + /* clear the trace bit */ + Context->EFlags &= 0xfffffeff; + + /* set the trace bit if we're Stepping */ + if (Stepping) + Context->EFlags |= 0x100; + + asm volatile ("movl %%db6, %0\n" : "=r" (dr6) : ); + if (!(dr6 & 0x4000)) + { + for (BreakpointNumber = 0; BreakpointNumber < 4; ++BreakpointNumber) + { + if (dr6 & (1 << BreakpointNumber)) + { + if (GspBreakpoints[BreakpointNumber].Type == 0) + { + /* Set restore flag */ + Context->EFlags |= 0x10000; + break; + } + } + } + } + GspCorrectHwBreakpoint(); + asm volatile ("movl %0, %%db6\n" : : "r" (0)); + + return kdHandleException; + break; + } + case 'k': /* kill the program */ + strcpy (GspOutBuffer, "OK"); + break; + /* kill the program */ + case 'H': /* Set thread */ + GspSetThread (ptr); + break; + case 'q': /* Query */ + GspQuery (ptr); + break; + case 'T': /* Query thread status */ + GspQueryThreadStatus (ptr); + break; + case 'Y': + { + ULONG Number; + ULONG Length; + ULONG Type; + ULONG Address; + + ptr = &GspOutBuffer[1]; + GspHex2Long (&ptr, &Number); + ptr++; + GspHex2Long (&ptr, &Type); + ptr++; + GspHex2Long (&ptr, &Length); + ptr++; + GspHex2Long (&ptr, &Address); + if (GspSetHwBreakpoint (Number & 0x3, Type & 0x3 , Length & 0x3, Address) == 0) + { + strcpy (GspOutBuffer, "OK"); + } + else + { + strcpy (GspOutBuffer, "E"); + } + break; + /* Remove hardware breakpoint */ + } + case 'y': + { + ULONG Number; + + ptr = &GspOutBuffer[1]; + GspHex2Long(&ptr, &Number); + if (GspRemoveHwBreakpoint (Number & 0x3) == 0) + { + strcpy (GspOutBuffer, "OK"); + } + else + { + strcpy (GspOutBuffer, "E"); + } + break; + } + default: + break; + } /* switch */ + + /* reply to the request */ + GspPutPacket (&GspOutBuffer[0]); + } + + return kdDoNotHandleException; +} + + +BOOLEAN +STDCALL +GspBreakIn(PKINTERRUPT Interrupt, + PVOID ServiceContext) +{ + PKTRAP_FRAME TrapFrame; + BOOLEAN DoBreakIn; + CONTEXT Context; + KIRQL OldIrql; + CHAR Value; + + DPRINT ("Break In\n"); + + DoBreakIn = FALSE; + while (KdPortGetByteEx (&GdbPortInfo, &Value)) + { + if (Value == 0x03) + DoBreakIn = TRUE; + } + + if (!DoBreakIn) + return TRUE; + + KeRaiseIrql (HIGH_LEVEL, &OldIrql); + + TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame; + + KeTrapFrameToContext (TrapFrame, &Context); + + KdEnterDebuggerException (NULL, &Context, TrapFrame); + + KeContextToTrapFrame (&Context, TrapFrame); + + KeLowerIrql (OldIrql); + + return TRUE; +} + + +extern ULONG KdpPortIrq; + +/* Initialize the GDB stub */ +VOID +KdGdbStubInit(ULONG Phase) +{ +#if 0 + KAFFINITY Affinity; + NTSTATUS Status; + ULONG MappedIrq; + KIRQL Dirql; +#endif + + if (Phase == 0) + { + DbgPrint("Module 'hal.dll' loaded at 0x%.08x.\n", LdrHalBase); + + GspInitialized = TRUE; + GspRunThread = PsGetCurrentThread(); + GspDbgThread = PsGetCurrentThread(); + GspEnumThread = NULL; + + DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C); + } + else if (Phase == 1) + { +#if 0 + /* Hook an interrupt handler to allow the debugger to break into + the system */ + MappedIrq = HalGetInterruptVector (Internal, + 0, + 0, + KdpPortIrq, + &Dirql, + &Affinity); + + Status = IoConnectInterrupt(&GspInterrupt, + GspBreakIn, + NULL, + NULL, + MappedIrq, + Dirql, + Dirql, + 0, + FALSE, + Affinity, + FALSE); + if (!NT_SUCCESS (Status)) + { + DPRINT1("Could not connect to IRQ line %d (0x%x)\n", + KdpPortIrq, Status); + return; + } + + KdPortEnableInterrupts(); + + DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C); +#endif + } +} + + +VOID +KdGdbDebugPrint(LPSTR Message) +{ +#if 0 + /* This can be quite annoying! */ + if (GspInitialized) + { + ULONG Length; + + GspOutBuffer[0] = 'O'; + GspOutBuffer[1] = '\0'; + strcat (&GspOutBuffer[0], Message); + Length = strlen (Message); + GspOutBuffer[2 + Length] = '\n'; + GspOutBuffer[3 + Length] = '\0'; + GspPutPacketNoWait (&GspOutBuffer[0]); + } +#else + HalDisplayString(Message); +#endif +} + + +extern LIST_ENTRY ModuleListHead; + +VOID +KdGdbListModules() +{ + PLIST_ENTRY CurrentEntry; + PMODULE_OBJECT Current; + ULONG ModuleCount; + + DPRINT1("\n"); + + ModuleCount = 0; + + CurrentEntry = ModuleListHead.Flink; + while (CurrentEntry != (&ModuleListHead)) + { + Current = CONTAINING_RECORD (CurrentEntry, MODULE_OBJECT, ListEntry); + + DbgPrint ("Module %S Base 0x%.08x Length 0x%.08x\n", + Current->BaseName.Buffer, Current->Base, Current->Length); + + ModuleCount++; + CurrentEntry = CurrentEntry->Flink; + } + + DbgPrint ("%d modules listed\n", ModuleCount); +} diff --git a/ntoskrnl/kd/kdebug.c b/ntoskrnl/kd/kdebug.c new file mode 100644 index 0000000..694616f --- /dev/null +++ b/ntoskrnl/kd/kdebug.c @@ -0,0 +1,456 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/kd/kdebug.c + * PURPOSE: Kernel debugger + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * 21/10/99: Created + */ + +#include +#include +#include +#include +#include +#include "../dbg/kdb.h" + +/* serial debug connection */ +#define DEFAULT_DEBUG_PORT 2 /* COM2 */ +#define DEFAULT_DEBUG_COM1_IRQ 4 /* COM1 IRQ */ +#define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */ +#define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */ + +/* bochs debug output */ +#define BOCHS_LOGGER_PORT (0xe9) + +/* VARIABLES ***************************************************************/ + +BOOLEAN +__declspec(dllexport) +KdDebuggerEnabled = FALSE; /* EXPORTED */ + +BOOLEAN +__declspec(dllexport) +KdDebuggerNotPresent = TRUE; /* EXPORTED */ + + +static BOOLEAN KdpBreakPending = FALSE; +ULONG KdDebugState = KD_DEBUG_DISABLED; +ULONG KdpPortIrq = 0; + +KD_PORT_INFORMATION GdbPortInfo; +KD_PORT_INFORMATION LogPortInfo; + +/* PRIVATE FUNCTIONS ********************************************************/ + +static VOID +PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + HalDisplayString(buffer); +} + + +VOID +KdInitSystem(ULONG Reserved, + PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + KD_PORT_INFORMATION PortInfo; + ULONG Value; + PCHAR p1, p2; + +#ifdef KDBG + /* Initialize runtime debugging if available */ + DbgRDebugInit(); +#endif + +#ifdef KDBG + /* Initialize the local kernel debugger. */ + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_KDB; +#endif + + /* Set debug port default values */ + PortInfo.ComPort = DEFAULT_DEBUG_PORT; + PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE; + KdpPortIrq = DEFAULT_DEBUG_COM2_IRQ; + + /* Set serial log port default values */ + LogPortInfo.ComPort = DEFAULT_DEBUG_PORT; + LogPortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE; + + /* Parse kernel command line */ + + /* Check for 'DEBUGPORT' */ + p1 = (PCHAR)LoaderBlock->CommandLine; + while (p1 && (p2 = strchr(p1, '/'))) + { + p2++; + if (!_strnicmp(p2, "DEBUGPORT", 9)) + { + p2 += 9; + if (*p2 == '=') + { + p2++; + if (!_strnicmp(p2, "SCREEN", 6)) + { + p2 += 6; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_SCREEN; + } + else if (!_strnicmp(p2, "BOCHS", 5)) + { + p2 += 5; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_BOCHS; + } + else if (!_strnicmp(p2, "GDB", 3)) + { + p2 += 3; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_GDB; + + /* Reset port information to defaults */ + RtlMoveMemory(&GdbPortInfo, &PortInfo, sizeof(KD_PORT_INFORMATION)); + PortInfo.ComPort = DEFAULT_DEBUG_PORT; + PortInfo.BaudRate = DEFAULT_DEBUG_BAUD_RATE; + } + else if (!_strnicmp(p2, "PICE", 4)) + { + p2 += 4; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_PICE; + } + else if (!_strnicmp(p2, "COM", 3)) + { + p2 += 3; + Value = (ULONG)atol(p2); + if (Value > 0 && Value < 5) + { + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_SERIAL; + LogPortInfo.ComPort = Value; + } + } + else if (!_strnicmp(p2, "FILE", 4)) + { + p2 += 4; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_FILELOG; + } + else if (!_strnicmp(p2, "MDA", 3)) + { + p2 += 3; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_MDA; + } + } + } + else if (!_strnicmp(p2, "DEBUG", 5)) + { + p2 += 5; + KdDebuggerEnabled = TRUE; + KdDebugState |= KD_DEBUG_SERIAL; + } + else if (!_strnicmp(p2, "NODEBUG", 7)) + { + p2 += 7; + KdDebuggerEnabled = FALSE; + KdDebugState = KD_DEBUG_DISABLED; + } + else if (!_strnicmp(p2, "CRASHDEBUG", 10)) + { + p2 += 10; + KdDebuggerEnabled = FALSE; + KdDebugState = KD_DEBUG_DISABLED; + } + else if (!_strnicmp(p2, "BREAK", 5)) + { + p2 += 5; + KdpBreakPending = TRUE; + } + else if (!_strnicmp(p2, "COM", 3)) + { + p2 += 3; + if (*p2 != '=') + { + p2++; + Value = (ULONG)atol(p2); + if (Value > 0 && Value < 5) + { + PortInfo.ComPort = Value; + } + } + } + else if (!_strnicmp(p2, "BAUDRATE", 8)) + { + p2 += 8; + if (*p2 != '=') + { + p2++; + Value = (ULONG)atol(p2); + if (Value > 0) + { + PortInfo.BaudRate = Value; + } + } + else if (!_strnicmp(p2, "IRQ", 3)) + { + p2 += 3; + if (*p2 != '=') + { + p2++; + Value = (ULONG)atol(p2); + if (Value > 0) + { + KdpPortIrq = Value; + } + } + } + } + p1 = p2; + } + + /* Print some information */ + if (KdDebuggerEnabled == TRUE) + { + if (KdDebugState & KD_DEBUG_GDB) + PrintString("\n GDB debugging enabled. COM%ld %ld Baud\n\n", + GdbPortInfo.ComPort, GdbPortInfo.BaudRate); + + if (KdDebugState & KD_DEBUG_PICE) + PrintString("\n Private ICE debugger enabled\n\n"); + + if (KdDebugState & KD_DEBUG_SCREEN) + PrintString("\n Screen debugging enabled\n\n"); + + if (KdDebugState & KD_DEBUG_BOCHS) + PrintString("\n Bochs debugging enabled\n\n"); + + if (KdDebugState & KD_DEBUG_SERIAL) + PrintString("\n Serial debugging enabled. COM%ld %ld Baud\n\n", + LogPortInfo.ComPort, LogPortInfo.BaudRate); + + if (KdDebugState & KD_DEBUG_FILELOG) + PrintString("\n File log debugging enabled\n\n"); + if (KdDebugState & KD_DEBUG_MDA) + PrintString("\n MDA debugging enabled\n\n"); + } + + /* Perform any initialization nescessary */ + if (KdDebuggerEnabled == TRUE) + { + if (KdDebugState & KD_DEBUG_GDB) + KdPortInitializeEx(&GdbPortInfo, 0, 0); + + if (KdDebugState & KD_DEBUG_SERIAL) + KdPortInitializeEx(&LogPortInfo, 0, 0); + + if (KdDebugState & KD_DEBUG_FILELOG) + DebugLogInit(); + + if (KdDebugState & KD_DEBUG_MDA) + KdInitializeMda(); + } +} + + +VOID +KdInit1(VOID) +{ + /* Initialize kernel debugger (phase 0) */ + if ((KdDebuggerEnabled == TRUE) && + (KdDebugState & KD_DEBUG_GDB)) + { + KdGdbStubInit(0); + } +} + + +VOID KdInit2(VOID) +{ + /* Initialize kernel debugger (phase 1) */ + if ((KdDebuggerEnabled == TRUE) && + (KdDebugState & KD_DEBUG_GDB)) + { + KdGdbStubInit(1); + } +} + +VOID +KdSerialDebugPrint (LPSTR Message) +{ + PCHAR pch = (PCHAR) Message; + + while (*pch != 0) + { + if (*pch == '\n') + { + KdPortPutByteEx (&LogPortInfo, '\r'); + } + KdPortPutByteEx (&LogPortInfo, *pch); + pch++; + } +} + + +VOID +KdBochsDebugPrint(IN LPSTR Message) +{ + while (*Message != 0) + { + if (*Message == '\n') + { + WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, '\r'); + } + WRITE_PORT_UCHAR((PUCHAR)BOCHS_LOGGER_PORT, *Message); + Message++; + } +} + + +ULONG +KdpPrintString(PANSI_STRING String) +{ + PCH pch = String->Buffer; + + if (KdDebugState & KD_DEBUG_GDB) + KdGdbDebugPrint(pch); + + if (KdDebugState & KD_DEBUG_SCREEN) + HalDisplayString(pch); + + if (KdDebugState & KD_DEBUG_SERIAL) + KdSerialDebugPrint(pch); + + if (KdDebugState & KD_DEBUG_BOCHS) + KdBochsDebugPrint(pch); + + if (KdDebugState & KD_DEBUG_FILELOG) + DebugLogWrite(pch); + + if (KdDebugState & KD_DEBUG_MDA) + KdPrintMda(pch); + + return((ULONG)String->Length); +} + +/* PUBLIC FUNCTIONS *********************************************************/ + +/* NTOSKRNL.KdPollBreakIn */ + +BOOLEAN STDCALL +KdPollBreakIn(VOID) +{ + if ((!KdDebuggerEnabled) || (!(KdDebugState & KD_DEBUG_SERIAL))) + return FALSE; + return KdpBreakPending; +} + +VOID STDCALL +KeEnterKernelDebugger(VOID) +{ + HalDisplayString("\n\n *** Entered kernel debugger ***\n"); + + for (;;) + __asm__("hlt\n\t"); +} + +VOID STDCALL +KdSystemDebugControl(ULONG Code) +{ + extern VOID PsDumpThreads(BOOLEAN IncludeSystem); + + /* A - Dump the entire contents of the non-paged pool. */ + if (Code == 0) + { + MiDebugDumpNonPagedPool(FALSE); + } + /* B - Bug check the system. */ + else if (Code == 1) + { + KeBugCheck(0); + } + /* + * C - Dump statistics about the distribution of tagged blocks in + * the non-paged pool. + */ + else if (Code == 2) + { + MiDebugDumpNonPagedPoolStats(FALSE); + } + /* + * D - Dump the blocks created in the non-paged pool since the last + * SysRq + D and SysRq + E command. + */ + else if (Code == 3) + { + MiDebugDumpNonPagedPool(TRUE); + } + /* E - Dump statistics about the tags of newly created blocks. */ + else if (Code == 4) + { + MiDebugDumpNonPagedPoolStats(TRUE); + } + /* F */ + else if (Code == 5) + { + PsDumpThreads(TRUE); + } + /* G */ + else if (Code == 6) + { + PsDumpThreads(FALSE); + } + /* H */ + else if (Code == 7) + { + } + /* I */ + else if (Code == 8) + { + } + /* J */ + else if (Code == 9) + { + } + /* K - Enter the system debugger. */ + else if (Code == 10) + { +#ifdef KDBG + KdbEnter(); +#else /* KDBG */ + DbgPrint("No local kernel debugger\n"); +#endif /* not KDBG */ + } +} + + +/* Support routines for the GDB stubs */ + +VOID +KdPutChar(UCHAR Value) +{ + KdPortPutByteEx (&GdbPortInfo, Value); +} + + +UCHAR +KdGetChar(VOID) +{ + UCHAR Value; + + while (!KdPortGetByteEx (&GdbPortInfo, &Value)); + + return Value; +} + +/* EOF */ diff --git a/ntoskrnl/kd/mda.c b/ntoskrnl/kd/mda.c new file mode 100644 index 0000000..28615c8 --- /dev/null +++ b/ntoskrnl/kd/mda.c @@ -0,0 +1,151 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/kd/mda.c + * PURPOSE: Support for debugging using an MDA card. + * PROGRAMMER: David Welch + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include "../dbg/kdb.h" + +/* VARIABLES ***************************************************************/ + +STATIC ULONG MdaIndexPort; +STATIC ULONG MdaValuePort; +STATIC ULONG MdaStatusPort; +STATIC ULONG MdaGfxPort; +STATIC ULONG MdaModePort; +STATIC PUSHORT VideoBuffer; + +#define MDA_COLUMNS (80) +#define MDA_LINES (25) + +STATIC ULONG MdaCursorX, MdaCursorY; + +/* PRIVATE FUNCTIONS ********************************************************/ + +#if 0 +VOID STATIC +KdWriteByteMDA(ULONG Reg, ULONG Value) +{ + WRITE_PORT_UCHAR((PUCHAR)MdaIndexPort, (CHAR)Reg); + WRITE_PORT_UCHAR((PUCHAR)MdaValuePort, (CHAR)Value); +} + +VOID STATIC +KdWriteWordMDA(ULONG Reg, ULONG Value) +{ + WRITE_PORT_UCHAR((PUCHAR)MdaIndexPort, (CHAR)Reg); + WRITE_PORT_UCHAR((PUCHAR)MdaValuePort, (CHAR)(Value >> 8)); + WRITE_PORT_UCHAR((PUCHAR)MdaIndexPort, (CHAR)(Reg + 1)); + WRITE_PORT_UCHAR((PUCHAR)MdaValuePort, (CHAR)(Value & 0xFF)); +} +#endif + +VOID +KdInitializeMda(VOID) +{ + /* Setup the variables for the various port addresses. */ + MdaIndexPort = 0x3b4; + MdaValuePort = 0x3b5; + MdaModePort = 0x3b8; + MdaStatusPort = 0x3ba; + MdaGfxPort = 0x3bf; + + VideoBuffer = (PUSHORT)(0xd0000000 + 0xb0000); + + MdaCursorX = MdaCursorY = 0; +} + +VOID STATIC +KdScrollMda(VOID) +{ + memmove(&VideoBuffer[(MDA_COLUMNS * 0) + 0], + &VideoBuffer[(MDA_COLUMNS * 1) + 0], + MDA_COLUMNS * (MDA_LINES - 1) * 2); + memset(&VideoBuffer[(MDA_COLUMNS * (MDA_LINES - 1)) + 0], 0, + MDA_COLUMNS * 2); +} + +VOID STATIC +KdPutCharMda(CHAR Ch) +{ + if (Ch == '\n') + { + if (MdaCursorY == (MDA_LINES - 1)) + { + KdScrollMda(); + } + else + { + MdaCursorY++; + } + MdaCursorX = 0; + return; + } + VideoBuffer[(MdaCursorY * MDA_COLUMNS) + MdaCursorX] = (Ch & 0xFF) | 0x0700; + MdaCursorX++; + if (MdaCursorX == (MDA_COLUMNS - 1)) + { + if (MdaCursorY == (MDA_LINES - 1)) + { + KdScrollMda(); + } + else + { + MdaCursorY++; + } + MdaCursorX = 0; + } +} + +VOID +KdPrintMda(PCH pch) +{ + while((*pch) != 0) + { + if ((*pch) == '\t') + { + KdPutCharMda(' '); + KdPutCharMda(' '); + KdPutCharMda(' '); + KdPutCharMda(' '); + } + if ((*pch) == '\r') + { + /* Nothing. */ + } + else + { + KdPutCharMda(*pch); + } + pch++; + } +} + +/* EOF */ diff --git a/ntoskrnl/kd/service.c b/ntoskrnl/kd/service.c new file mode 100644 index 0000000..31139af --- /dev/null +++ b/ntoskrnl/kd/service.c @@ -0,0 +1,116 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/kd/service.c + * PURPOSE: Debug service dispatcher + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * 17/01/2000: Created + */ + +#include +#include +#include + +/* FUNCTIONS ***************************************************************/ + +/* + * Note: DON'T CHANGE THIS FUNCTION!!! + * DON'T CALL HalDisplayString OR SOMETING ELSE!!! + * You'll only break the serial/bochs debugging feature!!! + */ + +ULONG +KdpServiceDispatcher ( + ULONG Service, + PVOID Context1, + PVOID Context2) +{ + ULONG Result = 0; + + switch (Service) + { + case 1: /* DbgPrint */ + Result = KdpPrintString ((PANSI_STRING)Context1); + break; + + default: + HalDisplayString ("Invalid debug service call!\n"); + break; + } + + return Result; +} + + +#define _STR(x) #x +#define STR(x) _STR(x) + +void interrupt_handler2d(void); + __asm__("\n\t.global _interrupt_handler2d\n\t" + "_interrupt_handler2d:\n\t" + + /* Save the user context */ + "pushl %ebp\n\t" /* Ebp */ + + "pushl %eax\n\t" /* Eax */ + "pushl %ecx\n\t" /* Ecx */ + "pushl %edx\n\t" /* Edx */ + "pushl %ebx\n\t" /* Ebx */ + "pushl %esi\n\t" /* Esi */ + "pushl %edi\n\t" /* Edi */ + + "pushl %ds\n\t" /* SegDs */ + "pushl %es\n\t" /* SegEs */ + "pushl %fs\n\t" /* SegFs */ + "pushl %gs\n\t" /* SegGs */ + + "subl $112,%esp\n\t" /* FloatSave */ + + "pushl $0\n\t" /* Dr7 */ + "pushl $0\n\t" /* Dr6 */ + "pushl $0\n\t" /* Dr3 */ + "pushl $0\n\t" /* Dr2 */ + "pushl $0\n\t" /* Dr1 */ + "pushl $0\n\t" /* Dr0 */ + + "pushl $0\n\t" /* ContextFlags */ + + /* Set ES to kernel segment */ + "movw $"STR(KERNEL_DS)",%bx\n\t" + "movw %bx,%es\n\t" + + /* FIXME: check to see if SS is valid/inrange */ + + /* DS is now also kernel segment */ + "movw %bx,%ds\n\t" + + /* Call debug service dispatcher */ + "pushl %edx\n\t" + "pushl %ecx\n\t" + "pushl %eax\n\t" + "call _KdpServiceDispatcher\n\t" + "addl $12,%esp\n\t" /* restore stack pointer */ + + /* Restore the user context */ + "addl $4,%esp\n\t" /* UserContext */ + "addl $24,%esp\n\t" /* Dr[0-3,6-7] */ + "addl $112,%esp\n\t" /* FloatingSave */ + "popl %gs\n\t" /* SegGs */ + "popl %fs\n\t" /* SegFs */ + "popl %es\n\t" /* SegEs */ + "popl %ds\n\t" /* SegDs */ + + "popl %edi\n\t" /* Edi */ + "popl %esi\n\t" /* Esi */ + "popl %ebx\n\t" /* Ebx */ + "popl %edx\n\t" /* Edx */ + "popl %ecx\n\t" /* Ecx */ + "addl $4,%esp\n\t" /* Eax (Not restored) */ + + "popl %ebp\n\t" /* Ebp */ + + "iret\n\t"); + +/* EOF */ diff --git a/ntoskrnl/ke/.cvsignore b/ntoskrnl/ke/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/ke/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/ke/apc.c b/ntoskrnl/ke/apc.c new file mode 100644 index 0000000..8a8a633 --- /dev/null +++ b/ntoskrnl/ke/apc.c @@ -0,0 +1,562 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/apc.c + * PURPOSE: Possible implementation of APCs + * PROGRAMMER: David Welch (welch@cwcom.net) + * PORTABILITY: Unchecked + * UPDATE HISTORY: + * Created 22/05/98 + * 12/11/99: Phillip Susi: Reworked the APC code + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +KSPIN_LOCK PiApcLock; +extern KSPIN_LOCK PiThreadListLock; + +VOID PsTerminateCurrentThread(NTSTATUS ExitStatus); + +#define TAG_KAPC TAG('K', 'A', 'P', 'C') + +/* FUNCTIONS *****************************************************************/ + +VOID KiRundownThread(VOID) +/* + * FUNCTION: + */ +{ +} + +BOOLEAN KiTestAlert(VOID) +/* + * FUNCTION: Tests whether there are any pending APCs for the current thread + * and if so the APCs will be delivered on exit from kernel mode + */ +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&PiApcLock, &oldIrql); + if (KeGetCurrentThread()->ApcState.UserApcPending == 0) + { + KeReleaseSpinLock(&PiApcLock, oldIrql); + return(FALSE); + } + KeGetCurrentThread()->Alerted[0] = 1; + KeReleaseSpinLock(&PiApcLock, oldIrql); + return(TRUE); +} + +VOID +KiDeliverNormalApc(VOID) +{ + PETHREAD Thread = PsGetCurrentThread(); + PLIST_ENTRY current; + PKAPC Apc; + KIRQL oldlvl; + PKNORMAL_ROUTINE NormalRoutine; + PVOID NormalContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0]))) + { + current = Thread->Tcb.ApcState.ApcListHead[0].Blink; + Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); + if (Apc->NormalRoutine == NULL) + { + DbgPrint("Exiting kernel with kernel APCs pending.\n"); + KeBugCheck(0); + } + (VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]); + Apc->Inserted = FALSE; + Thread->Tcb.ApcState.KernelApcInProgress++; + Thread->Tcb.ApcState.KernelApcPending--; + + KeReleaseSpinLock(&PiApcLock, oldlvl); + + NormalRoutine = Apc->NormalRoutine; + NormalContext = Apc->NormalContext; + SystemArgument1 = Apc->SystemArgument1; + SystemArgument2 = Apc->SystemArgument2; + Apc->KernelRoutine(Apc, + &NormalRoutine, + &NormalContext, + &SystemArgument1, + &SystemArgument2); + NormalRoutine(NormalContext, SystemArgument1, SystemArgument2); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + Thread->Tcb.ApcState.KernelApcInProgress--; + } + KeReleaseSpinLock(&PiApcLock, oldlvl); +} + +BOOLEAN +KiDeliverUserApc(PKTRAP_FRAME TrapFrame) +/* + * FUNCTION: Tests whether there are any pending APCs for the current thread + * and if so the APCs will be delivered on exit from kernel mode. + * ARGUMENTS: + * Thread = Thread to test for alerts + * UserContext = The user context saved on entry to kernel mode + */ +{ + PLIST_ENTRY current_entry; + PKAPC Apc; + PULONG Esp; + PCONTEXT Context; + KIRQL oldlvl; + PKTHREAD Thread; + + DPRINT("KiDeliverUserApc(TrapFrame %x/%x)\n", TrapFrame, + KeGetCurrentThread()->TrapFrame); + Thread = KeGetCurrentThread(); + + /* + * Check for thread termination + */ + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + + current_entry = Thread->ApcState.ApcListHead[1].Flink; + + /* + * Shouldn't happen but check anyway. + */ + if (current_entry == &Thread->ApcState.ApcListHead[1]) + { + KeReleaseSpinLock(&PiApcLock, oldlvl); + DbgPrint("KiDeliverUserApc called but no APC was pending\n"); + return(FALSE); + } + + while (!IsListEmpty(&Thread->ApcState.ApcListHead[1])) + { + current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]); + Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry); + Apc->Inserted = FALSE; + KeReleaseSpinLock(&PiApcLock, oldlvl); + + /* + * Save the thread's current context (in other words the registers + * that will be restored when it returns to user mode) so the + * APC dispatcher can restore them later + */ + Context = (PCONTEXT)(((PUCHAR)TrapFrame->Esp) - sizeof(CONTEXT)); + memset(Context, 0, sizeof(CONTEXT)); + Context->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | + CONTEXT_SEGMENTS | CONTEXT_i386; + Context->SegGs = TrapFrame->Gs; + Context->SegFs = TrapFrame->Fs; + Context->SegEs = TrapFrame->Es; + Context->SegDs = TrapFrame->Ds; + Context->Edi = TrapFrame->Edi; + Context->Esi = TrapFrame->Esi; + Context->Ebx = TrapFrame->Ebx; + Context->Edx = TrapFrame->Edx; + Context->Ecx = TrapFrame->Ecx; + Context->Eax = TrapFrame->Eax; + Context->Ebp = TrapFrame->Ebp; + Context->Eip = TrapFrame->Eip; + Context->SegCs = TrapFrame->Cs; + Context->EFlags = TrapFrame->Eflags; + Context->Esp = TrapFrame->Esp; + Context->SegSs = TrapFrame->Ss; + + /* + * Setup the trap frame so the thread will start executing at the + * APC Dispatcher when it returns to user-mode + */ + Esp = (PULONG)(((PUCHAR)TrapFrame->Esp) - + (sizeof(CONTEXT) + (6 * sizeof(ULONG)))); + + Esp[0] = 0xdeadbeef; + Esp[1] = (ULONG)Apc->NormalRoutine; + Esp[2] = (ULONG)Apc->NormalContext; + Esp[3] = (ULONG)Apc->SystemArgument1; + Esp[4] = (ULONG)Apc->SystemArgument2; + Esp[5] = (ULONG)Context; + TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher(); + TrapFrame->Esp = (ULONG)Esp; + + /* + * We've dealt with one pending user-mode APC + */ + Thread->ApcState.UserApcPending--; + + /* + * Now call for the kernel routine for the APC, which will free + * the APC data structure, we can't do this ourselves because + * the APC may be embedded in some larger structure e.g. an IRP + * We also give the kernel routine a last chance to modify the + * arguments to the user APC routine. + */ + Apc->KernelRoutine(Apc, + (PKNORMAL_ROUTINE*)&Esp[1], + (PVOID*)&Esp[2], + (PVOID*)&Esp[3], + (PVOID*)&Esp[4]); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + } + Thread->Alerted[0] = 0; + KeReleaseSpinLock(&PiApcLock, oldlvl); + + return(TRUE); +} + +VOID STDCALL +KiDeliverApc(ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +/* + * FUNCTION: Deliver an APC to the current thread. + * NOTES: This is called from the IRQL switching code if the current thread + * is returning from an IRQL greater than or equal to APC_LEVEL to + * PASSIVE_LEVEL and there are kernel-mode APCs pending. This means any + * pending APCs will be delivered after a thread gets a new quantum and + * after it wakes from a wait. + */ +{ + PETHREAD Thread = PsGetCurrentThread(); + PLIST_ENTRY current_entry; + PKAPC Apc; + KIRQL oldlvl; + + DPRINT("KiDeliverApc()\n"); + KeAcquireSpinLock(&PiApcLock, &oldlvl); + current_entry = Thread->Tcb.ApcState.ApcListHead[0].Flink; + while(current_entry != &Thread->Tcb.ApcState.ApcListHead[0]) + { + Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry); + if (Apc->NormalRoutine == NULL) + { + current_entry = current_entry->Flink; + Apc->Inserted = FALSE; + RemoveEntryList(&Apc->ApcListEntry); + Thread->Tcb.ApcState.KernelApcInProgress++; + Thread->Tcb.ApcState.KernelApcPending--; + + KeReleaseSpinLock(&PiApcLock, oldlvl); + + Apc->KernelRoutine(Apc, + &Apc->NormalRoutine, + &Apc->NormalContext, + &Apc->SystemArgument1, + &Apc->SystemArgument2); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + Thread->Tcb.ApcState.KernelApcInProgress--; + } + else + { + current_entry = current_entry->Flink; + } + } + KeReleaseSpinLock(&PiApcLock, oldlvl); +} + +VOID STDCALL +KeInsertQueueApc (PKAPC Apc, + PVOID SystemArgument1, + PVOID SystemArgument2, + UCHAR Mode) +/* + * FUNCTION: Queues an APC for execution + * ARGUMENTS: + * Apc = APC to be queued + * SystemArgument[1-2] = TBD + * Mode = TBD + */ +{ + KIRQL oldlvl; + PKTHREAD TargetThread; + + DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, " + "SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1, + SystemArgument2,Mode); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + + Apc->SystemArgument1 = SystemArgument1; + Apc->SystemArgument2 = SystemArgument2; + + if (Apc->Inserted) + { + DbgPrint("KeInsertQueueApc(): multiple APC insertations\n"); + KeBugCheck(0); + } + + TargetThread = Apc->Thread; + if (Apc->ApcMode == KernelMode) + { + InsertTailList(&TargetThread->ApcState.ApcListHead[0], + &Apc->ApcListEntry); + TargetThread->ApcState.KernelApcPending++; + } + else + { + InsertTailList(&TargetThread->ApcState.ApcListHead[1], + &Apc->ApcListEntry); + TargetThread->ApcState.UserApcPending++; + } + Apc->Inserted = TRUE; + + /* + * If this is a kernel-mode APC for the current thread and we are not + * inside a critical section or at APC level then call it, in fact we + * rely on the side effects of dropping the IRQL level when we release + * the spinlock + */ + if (Apc->ApcMode == KernelMode && TargetThread == KeGetCurrentThread() && + Apc->NormalRoutine == NULL) + { + KeReleaseSpinLock(&PiApcLock, oldlvl); + return; + } + + /* + * If this is a kernel-mode APC and it is waiting at PASSIVE_LEVEL and + * not inside a critical section then wake it up. Otherwise it will + * execute the APC as soon as it returns to PASSIVE_LEVEL. + * FIXME: If the thread is running on another processor then send an + * IPI. + * FIXME: Check if the thread is terminating. + */ + if (Apc->ApcMode == KernelMode && TargetThread->WaitIrql < APC_LEVEL && + Apc->NormalRoutine == NULL) + { + KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb), + STATUS_KERNEL_APC); + } + + /* + * If this is a 'funny' user-mode APC then mark the thread as + * alerted so it will execute the APC on exit from kernel mode. If it + * is waiting alertably then wake it up so it can return to user mode. + */ + if (Apc->ApcMode == KernelMode && Apc->NormalRoutine != NULL) + { + TargetThread->Alerted[1] = 1; + if (TargetThread->Alertable == TRUE && + TargetThread->WaitMode == UserMode) + { + PETHREAD Thread; + + Thread = CONTAINING_RECORD(TargetThread, ETHREAD, Tcb); + KeRemoveAllWaitsThread(Thread, STATUS_USER_APC); + } + } + + /* + * If the thread is waiting alertably then wake it up and it will + * return to to user-mode executing the APC in the process. Otherwise the + * thread will execute the APC next time it enters an alertable wait. + */ + if (Apc->ApcMode == UserMode && TargetThread->Alertable == TRUE && + TargetThread->WaitMode == UserMode) + { + NTSTATUS Status; + + DPRINT("Resuming thread for user APC\n"); + + Status = STATUS_USER_APC; + TargetThread->Alerted[0] = 1; + KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb), + STATUS_USER_APC); + } + KeReleaseSpinLock(&PiApcLock, oldlvl); +} + +BOOLEAN STDCALL +KeRemoveQueueApc (PKAPC Apc) +/* + * FUNCTION: Removes APC object from the apc queue + * ARGUMENTS: + * Apc = APC to remove + * RETURNS: TRUE if the APC was in the queue + * FALSE otherwise + * NOTE: This function is not exported. + */ +{ + KIRQL oldIrql; + PKTHREAD TargetThread; + + KeAcquireSpinLockAtDpcLevel(&PiApcLock); + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + if (Apc->Inserted == FALSE) + { + KeReleaseSpinLock(&PiApcLock, oldIrql); + return(FALSE); + } + + TargetThread = Apc->Thread; + RemoveEntryList(&Apc->ApcListEntry); + if (Apc->ApcMode == KernelMode) + { + TargetThread->ApcState.KernelApcPending--; + } + else + { + TargetThread->ApcState.UserApcPending--; + } + Apc->Inserted = FALSE; + + KeReleaseSpinLock(&PiApcLock, oldIrql); + return(TRUE); +} + + +VOID STDCALL +KeInitializeApc(PKAPC Apc, + PKTHREAD Thread, + UCHAR StateIndex, + PKKERNEL_ROUTINE KernelRoutine, + PKRUNDOWN_ROUTINE RundownRoutine, + PKNORMAL_ROUTINE NormalRoutine, + UCHAR Mode, + PVOID Context) +/* + * FUNCTION: Initialize an APC object + * ARGUMENTS: + * Apc = Pointer to the APC object to initialized + * Thread = Thread the APC is to be delivered to + * StateIndex = TBD + * KernelRoutine = Routine to be called for a kernel-mode APC + * RundownRoutine = Routine to be called if the thread has exited with + * the APC being executed + * NormalRoutine = Routine to be called for a user-mode APC + * Mode = APC mode + * Context = Parameter to be passed to the APC routine + */ +{ + DPRINT("KeInitializeApc(Apc %x, Thread %x, StateIndex %d, " + "KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, " + "Context %x)\n",Apc,Thread,StateIndex,KernelRoutine,RundownRoutine, + NormalRoutine,Mode,Context); + + memset(Apc, 0, sizeof(KAPC)); + Apc->Thread = Thread; + Apc->ApcListEntry.Flink = NULL; + Apc->ApcListEntry.Blink = NULL; + Apc->KernelRoutine = KernelRoutine; + Apc->RundownRoutine = RundownRoutine; + Apc->NormalRoutine = NormalRoutine; + Apc->NormalContext = Context; + Apc->Inserted = FALSE; + Apc->ApcStateIndex = StateIndex; + if (Apc->NormalRoutine != NULL) + { + Apc->ApcMode = Mode; + } + else + { + Apc->ApcMode = KernelMode; + } +} + +VOID STDCALL +NtQueueApcRundownRoutine(PKAPC Apc) +{ + ExFreePool(Apc); +} + +VOID STDCALL +NtQueueApcKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) +{ + ExFreePool(Apc); +} + +NTSTATUS STDCALL +NtQueueApcThread(HANDLE ThreadHandle, + PKNORMAL_ROUTINE ApcRoutine, + PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PKAPC Apc; + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_ALL_ACCESS, /* FIXME */ + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_KAPC); + if (Apc == NULL) + { + ObDereferenceObject(Thread); + return(STATUS_NO_MEMORY); + } + + KeInitializeApc(Apc, + &Thread->Tcb, + 0, + NtQueueApcKernelRoutine, + NtQueueApcRundownRoutine, + ApcRoutine, + UserMode, + NormalContext); + KeInsertQueueApc(Apc, + SystemArgument1, + SystemArgument2, + UserMode); + + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL NtTestAlert(VOID) +{ + KiTestAlert(); + return(STATUS_SUCCESS); +} + +VOID PiInitApcManagement(VOID) +{ + KeInitializeSpinLock(&PiApcLock); +} + diff --git a/ntoskrnl/ke/bug.c b/ntoskrnl/ke/bug.c new file mode 100644 index 0000000..4b3f76c --- /dev/null +++ b/ntoskrnl/ke/bug.c @@ -0,0 +1,184 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/bug.c + * PURPOSE: Graceful system shutdown if a bug is detected + * PROGRAMMER: David Welch (welch@cwcom.net) + * PORTABILITY: Unchecked + * UPDATE HISTORY: + * Created 22/05/98 + * Phillip Susi: 12/8/99: Minor fix + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include + +/* GLOBALS ******************************************************************/ + +static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL}; +static ULONG InBugCheck; + +VOID PsDumpThreads(VOID); + +/* FUNCTIONS *****************************************************************/ + +VOID +KeInitializeBugCheck(VOID) +{ + InitializeListHead(&BugcheckCallbackListHead); + InBugCheck = 0; +} + +BOOLEAN STDCALL +KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord) +{ + UNIMPLEMENTED; +} + +BOOLEAN STDCALL +KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord, + PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine, + PVOID Buffer, + ULONG Length, + PUCHAR Component) +{ + InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry); + CallbackRecord->Length = Length; + CallbackRecord->Buffer = Buffer; + CallbackRecord->Component = Component; + CallbackRecord->CallbackRoutine = CallbackRoutine; + return(TRUE); +} + +VOID STDCALL +KeBugCheckWithTf(ULONG BugCheckCode, + ULONG BugCheckParameter1, + ULONG BugCheckParameter2, + ULONG BugCheckParameter3, + ULONG BugCheckParameter4, + PKTRAP_FRAME Tf) +{ + KIRQL oldIrql; + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + DbgPrint("Bug detected code: 0x%X\n", BugCheckCode); + KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2); + MmDumpToPagingFile(BugCheckCode, BugCheckParameter1, + BugCheckParameter2, BugCheckParameter3, + BugCheckParameter4, Tf); + for(;;); +} + +VOID STDCALL +KeBugCheckEx(ULONG BugCheckCode, + ULONG BugCheckParameter1, + ULONG BugCheckParameter2, + ULONG BugCheckParameter3, + ULONG BugCheckParameter4) +/* + * FUNCTION: Brings the system down in a controlled manner when an + * inconsistency that might otherwise cause corruption has been detected + * ARGUMENTS: + * BugCheckCode = Specifies the reason for the bug check + * BugCheckParameter[1-4] = Additional information about bug + * RETURNS: Doesn't + */ +{ + PRTL_MESSAGE_RESOURCE_ENTRY Message; + NTSTATUS Status; + + __asm__("cli\n\t"); + DbgPrint("Bug detected (code %x param %x %x %x %x)\n", + BugCheckCode, + BugCheckParameter1, + BugCheckParameter2, + BugCheckParameter3, + BugCheckParameter4); + + Status = RtlFindMessage((PVOID)KERNEL_BASE, //0xC0000000, + 11, //RT_MESSAGETABLE, + 0x09, //0x409, + BugCheckCode, + &Message); + if (NT_SUCCESS(Status)) + { + if (Message->Flags == 0) + DbgPrint(" %s\n", Message->Text); + else + DbgPrint(" %S\n", (PWSTR)Message->Text); + } + else + { + DbgPrint(" No message text found!\n\n"); + } + + if (InBugCheck == 1) + { + DbgPrint("Recursive bug check halting now\n"); + for (;;) + { + __asm__("hlt\n\t"); + } + } + InBugCheck = 1; + if (PsGetCurrentProcess() != NULL) + { + DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId); + DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName); + } + if (PsGetCurrentThread() != NULL) + { + DbgPrint("Thrd: %x Tid: %x\n", + PsGetCurrentThread(), + PsGetCurrentThread()->Cid.UniqueThread); + } + KeDumpStackFrames((PULONG)__builtin_frame_address(0)); + MmDumpToPagingFile(BugCheckCode, BugCheckParameter1, + BugCheckParameter2, BugCheckParameter3, + BugCheckParameter4, NULL); + + if (KdDebuggerEnabled) + { + __asm__("sti\n\t"); + DbgBreakPoint(); + } + + for(;;); +} + +VOID STDCALL +KeBugCheck(ULONG BugCheckCode) +/* + * FUNCTION: Brings the system down in a controlled manner when an + * inconsistency that might otherwise cause corruption has been detected + * ARGUMENTS: + * BugCheckCode = Specifies the reason for the bug check + * RETURNS: Doesn't + */ +{ + KeBugCheckEx(BugCheckCode, 0, 0, 0, 0); +} + +/* EOF */ diff --git a/ntoskrnl/ke/catch.c b/ntoskrnl/ke/catch.c new file mode 100644 index 0000000..96c671e --- /dev/null +++ b/ntoskrnl/ke/catch.c @@ -0,0 +1,209 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/catch.c + * PURPOSE: Exception handling + * PROGRAMMER: David Welch (welch@mcmail.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context); + +VOID +KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, + PCONTEXT Context, + PKTRAP_FRAME Tf, + KPROCESSOR_MODE PreviousMode, + BOOLEAN SearchFrames) +{ + EXCEPTION_DISPOSITION Value; + CONTEXT TContext; + + DPRINT("KiDispatchException() called\n"); + + /* PCR->KeExceptionDispatchCount++; */ + + if (Context == NULL) + { + TContext.ContextFlags = CONTEXT_FULL; + if (PreviousMode == UserMode) + { + TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER; + } + + KeTrapFrameToContext(Tf, &TContext); + + Context = &TContext; + } + +#if 0 + if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) + { + Context->Eip--; + } +#endif + if (PreviousMode == UserMode) + { + if (SearchFrames) + { + PULONG Stack; + ULONG CDest; + + /* FIXME: Give the kernel debugger a chance */ + + /* FIXME: Forward exception to user mode debugger */ + + /* FIXME: Check user mode stack for enough space */ + + + /* + * Let usermode try and handle the exception + */ + Tf->Esp = Tf->Esp - + (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)); + Stack = (PULONG)Tf->Esp; + CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4); + /* Return address */ + Stack[0] = 0; + /* Pointer to EXCEPTION_RECORD structure */ + Stack[1] = (ULONG)&Stack[3]; + /* Pointer to CONTEXT structure */ + Stack[2] = (ULONG)&Stack[CDest]; + memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD)); + memcpy(&Stack[CDest], Context, sizeof(CONTEXT)); + + Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher(); + return; + } + + /* FIXME: Forward the exception to the debugger */ + + /* FIXME: Forward the exception to the process exception port */ + + /* Terminate the offending thread */ + ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode); + + /* If that fails then bugcheck */ + DbgPrint("Could not terminate thread\n"); + KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED); + } + else + { + KD_CONTINUE_TYPE Action = kdContinue; + + /* PreviousMode == KernelMode */ + + if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB) + { + Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf); + } +#ifdef KDBG + else if (KdDebuggerEnable && KdDebugState & KD_DEBUG_KDB) + { + Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf); + } +#endif /* KDBG */ + if (Action != kdHandleException) + { + Value = RtlpDispatchException (ExceptionRecord, Context); + + DPRINT("RtlpDispatchException() returned with 0x%X\n", Value); + /* + * If RtlpDispatchException() does not handle the exception then + * bugcheck + */ + if (Value != ExceptionContinueExecution) + { + KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED); + } + } + else + { + KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame); + } + } +} + +VOID STDCALL +ExRaiseAccessViolation (VOID) +{ + ExRaiseStatus (STATUS_ACCESS_VIOLATION); +} + +VOID STDCALL +ExRaiseDatatypeMisalignment (VOID) +{ + ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT); +} + +VOID STDCALL +ExRaiseStatus (IN NTSTATUS Status) +{ + EXCEPTION_RECORD ExceptionRecord; + + DPRINT("ExRaiseStatus(%x)\n", Status); + + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.NumberParameters = 0; + ExceptionRecord.ExceptionCode = Status; + ExceptionRecord.ExceptionFlags = 0; + + RtlRaiseException(&ExceptionRecord); +} + + +NTSTATUS STDCALL +NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN BOOLEAN SearchFrames) +{ + KiDispatchException(ExceptionRecord, + Context, + PsGetCurrentThread()->Tcb.TrapFrame, + ExGetPreviousMode(), + SearchFrames); + return(STATUS_SUCCESS); +} + + +VOID STDCALL +RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord) +{ + ZwRaiseException(ExceptionRecord, NULL, TRUE); +} + +/* EOF */ diff --git a/ntoskrnl/ke/critical.c b/ntoskrnl/ke/critical.c new file mode 100644 index 0000000..d6179ab --- /dev/null +++ b/ntoskrnl/ke/critical.c @@ -0,0 +1,34 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/critical.c + * PURPOSE: Implement critical regions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL KeEnterCriticalRegion (VOID) +{ + DPRINT("KeEnterCriticalRegion()\n"); + KeGetCurrentThread()->KernelApcDisable -= 1; +} + +VOID STDCALL KeLeaveCriticalRegion (VOID) +{ + DPRINT("KeLeaveCriticalRegion()\n"); + KeGetCurrentThread()->KernelApcDisable += 1; +} + +/* EOF */ diff --git a/ntoskrnl/ke/dpc.c b/ntoskrnl/ke/dpc.c new file mode 100644 index 0000000..7a0e56f --- /dev/null +++ b/ntoskrnl/ke/dpc.c @@ -0,0 +1,231 @@ +/* + * ReactOS kernel + * Copyright (C) 2000, 1999, 1998 David Welch , + * Philip Susi , + * Eric Kohl + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/dpc.c + * PURPOSE: Handle DPCs (Delayed Procedure Calls) + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 28/05/98: Created + * 12/3/99: Phillip Susi: Fixed IRQL problem + */ + +/* + * NOTE: See also the higher level support routines in ntoskrnl/io/dpc.c + */ + +/* INCLUDES ***************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +/* GLOBALS ******************************************************************/ + +static LIST_ENTRY DpcQueueHead; /* Head of the list of pending DPCs */ +static KSPIN_LOCK DpcQueueLock; /* Lock for the above list */ +/* + * Number of pending DPCs. This is inspected by + * the idle thread to determine if the queue needs to + * be run down + */ +ULONG DpcQueueSize = 0; + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +KeInitializeDpc (PKDPC Dpc, + PKDEFERRED_ROUTINE DeferredRoutine, + PVOID DeferredContext) +/* + * FUNCTION: Initalizes a DPC + * ARGUMENTS: + * Dpc = Caller supplied DPC to be initialized + * DeferredRoutine = Associated DPC callback + * DeferredContext = Parameter to be passed to the callback + * NOTE: Callers must be running at IRQL PASSIVE_LEVEL + */ +{ + Dpc->Type = 0; + Dpc->DeferredRoutine = DeferredRoutine; + Dpc->DeferredContext = DeferredContext; + Dpc->Lock = 0; +} + +VOID STDCALL +KiDispatchInterrupt(VOID) +/* + * FUNCTION: Called to execute queued dpcs + */ +{ + PLIST_ENTRY current_entry; + PKDPC current; + KIRQL oldlvl; + + assert_irql(DISPATCH_LEVEL); + + if (DpcQueueSize == 0) + { + return; + } + + KeRaiseIrql(HIGH_LEVEL, &oldlvl); + KeAcquireSpinLockAtDpcLevel(&DpcQueueLock); + current_entry = RemoveHeadList(&DpcQueueHead); + if (current_entry != &DpcQueueHead) + { + DpcQueueSize--; + } + KeReleaseSpinLockFromDpcLevel(&DpcQueueLock); + current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry); + current->Lock=FALSE; + KeLowerIrql(oldlvl); + while (current_entry!=(&DpcQueueHead)) + { + current->DeferredRoutine(current,current->DeferredContext, + current->SystemArgument1, + current->SystemArgument2); + + KeRaiseIrql(HIGH_LEVEL, &oldlvl); + KeAcquireSpinLockAtDpcLevel(&DpcQueueLock); + current_entry = RemoveHeadList(&DpcQueueHead); + if (current_entry != &DpcQueueHead) + { + DpcQueueSize--; + } + KeReleaseSpinLockFromDpcLevel(&DpcQueueLock); + current = CONTAINING_RECORD(current_entry,KDPC,DpcListEntry); + current->Lock=FALSE; + KeLowerIrql(oldlvl); + } +} + +BOOLEAN STDCALL +KeRemoveQueueDpc (PKDPC Dpc) +/* + * FUNCTION: Removes DPC object from the system dpc queue + * ARGUMENTS: + * Dpc = DPC to remove + * RETURNS: TRUE if the DPC was in the queue + * FALSE otherwise + */ +{ + KIRQL oldIrql; + + KeAcquireSpinLockAtDpcLevel(&DpcQueueLock); + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + if (!Dpc->Lock) + { + KeReleaseSpinLock(&DpcQueueLock, oldIrql); + return(FALSE); + } + RemoveEntryList(&Dpc->DpcListEntry); + DpcQueueSize--; + Dpc->Lock=0; + KeReleaseSpinLock(&DpcQueueLock, oldIrql); + return(TRUE); +} + +BOOLEAN STDCALL +KeInsertQueueDpc (PKDPC Dpc, + PVOID SystemArgument1, + PVOID SystemArgument2) +/* + * FUNCTION: Queues a DPC for execution when the IRQL of a processor + * drops below DISPATCH_LEVEL + * ARGUMENTS: + * Dpc = Initalizes DPC + * SystemArguments[1-2] = Undocumented + * RETURNS: TRUE if the DPC object wasn't already in the queue + * FALSE otherwise + */ +{ + KIRQL oldlvl; + DPRINT("KeInsertQueueDpc(dpc %x, SystemArgument1 %x, SystemArgument2 %x)\n", + Dpc, SystemArgument1, SystemArgument2); + + assert(KeGetCurrentIrql()>=DISPATCH_LEVEL); + + Dpc->Number=0; + Dpc->Importance=MediumImportance; + Dpc->SystemArgument1=SystemArgument1; + Dpc->SystemArgument2=SystemArgument2; + if (Dpc->Lock) + { + return(FALSE); + } + KeRaiseIrql(HIGH_LEVEL, &oldlvl); + KeAcquireSpinLockAtDpcLevel(&DpcQueueLock); + InsertHeadList(&DpcQueueHead,&Dpc->DpcListEntry); + DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink); + DpcQueueSize++; + Dpc->Lock=(PULONG)1; + KeReleaseSpinLock( &DpcQueueLock, oldlvl ); + DPRINT("DpcQueueHead.Flink %x\n",DpcQueueHead.Flink); + DPRINT("Leaving KeInsertQueueDpc()\n",0); + return(TRUE); +} + +/* + * FUNCTION: Specifies the DPCs importance + * ARGUMENTS: + * Dpc = Initalizes DPC + * Importance = DPC importance + * RETURNS: None + */ +VOID STDCALL +KeSetImportanceDpc (IN PKDPC Dpc, + IN KDPC_IMPORTANCE Importance) +{ + Dpc->Importance = Importance; +} + +/* + * FUNCTION: Specifies on which processor the DPC will run + * ARGUMENTS: + * Dpc = Initalizes DPC + * Number = Processor number + * RETURNS: None + */ +VOID STDCALL +KeSetTargetProcessorDpc (IN PKDPC Dpc, + IN CCHAR Number) +{ + UNIMPLEMENTED; +} + +VOID +KeInitDpc(VOID) +/* + * FUNCTION: Initialize DPC handling + */ +{ + InitializeListHead(&DpcQueueHead); + KeInitializeSpinLock(&DpcQueueLock); +} + +/* EOF */ diff --git a/ntoskrnl/ke/error.c b/ntoskrnl/ke/error.c new file mode 100644 index 0000000..f0f82a4 --- /dev/null +++ b/ntoskrnl/ke/error.c @@ -0,0 +1,38 @@ +/* $Id $ + * + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel v0.0.2 + * FILE: ntoskrnl/ke/error.c + * PURPOSE: Error reason setting/getting + * PROGRAMMER: David Welch + * UPDATE HISTORY: + * 16/4/98: Created + */ + +/* INCLUDE *****************************************************************/ + +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +NtRaiseHardError(IN NTSTATUS Status, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6) +{ + DPRINT1("Hard error %x\n", Status); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtSetDefaultHardErrorPort(IN HANDLE PortHandle) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/ke/event.c b/ntoskrnl/ke/event.c new file mode 100644 index 0000000..adb7d1b --- /dev/null +++ b/ntoskrnl/ke/event.c @@ -0,0 +1,93 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/event.c + * PURPOSE: Implements events + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL KeClearEvent (PKEVENT Event) +{ + DPRINT("KeClearEvent(Event %x)\n", Event); + Event->Header.SignalState = FALSE; +} + +VOID STDCALL KeInitializeEvent (PKEVENT Event, + EVENT_TYPE Type, + BOOLEAN State) +{ + ULONG IType; + + if (Type == NotificationEvent) + { + IType = InternalNotificationEvent; + } + else if (Type == SynchronizationEvent) + { + IType = InternalSynchronizationEvent; + } + else + { + assert(FALSE); + return; + } + + KeInitializeDispatcherHeader(&(Event->Header), + IType, + sizeof(Event)/sizeof(ULONG),State); + InitializeListHead(&(Event->Header.WaitListHead)); +} + +LONG STDCALL KeReadStateEvent (PKEVENT Event) +{ + return(Event->Header.SignalState); +} + +LONG STDCALL KeResetEvent (PKEVENT Event) +{ + return(InterlockedExchange(&(Event->Header.SignalState),0)); +} + +LONG STDCALL KeSetEvent (PKEVENT Event, + KPRIORITY Increment, + BOOLEAN Wait) +{ + int ret; + + DPRINT("KeSetEvent(Event %x, Wait %x)\n",Event,Wait); + KeAcquireDispatcherDatabaseLock(Wait); + ret = InterlockedExchange(&(Event->Header.SignalState),1); + KeDispatcherObjectWake((DISPATCHER_HEADER *)Event); + KeReleaseDispatcherDatabaseLock(Wait); + return(ret); +} + +NTSTATUS STDCALL KePulseEvent (PKEVENT Event, + KPRIORITY Increment, + BOOLEAN Wait) +{ + int ret; + + DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait); + KeAcquireDispatcherDatabaseLock(Wait); + ret = InterlockedExchange(&(Event->Header.SignalState),1); + KeDispatcherObjectWake((DISPATCHER_HEADER *)Event); + InterlockedExchange(&(Event->Header.SignalState),0); + KeReleaseDispatcherDatabaseLock(Wait); + return((NTSTATUS)ret); +} + +/* EOF */ diff --git a/ntoskrnl/ke/i386/.cvsignore b/ntoskrnl/ke/i386/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/ke/i386/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/ke/i386/bios.c b/ntoskrnl/ke/i386/bios.c new file mode 100644 index 0000000..bcc6c5e --- /dev/null +++ b/ntoskrnl/ke/i386/bios.c @@ -0,0 +1,94 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/bios.c + * PURPOSE: Support for calling the BIOS in v86 mode + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TRAMPOLINE_BASE (0x10000) + +extern VOID Ki386RetToV86Mode(PKV86M_REGISTERS InRegs, + PKV86M_REGISTERS OutRegs); + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +Ke386CallBios(UCHAR Int, PKV86M_REGISTERS Regs) +{ + PUCHAR Ip; + KV86M_REGISTERS ORegs; + NTSTATUS Status; + + /* + * Set up a trampoline for executing the BIOS interrupt + */ + Ip = (PUCHAR)TRAMPOLINE_BASE; + Ip[0] = 0xCD; /* int XX */ + Ip[1] = Int; + Ip[2] = 0x63; /* arpl ax, ax */ + Ip[3] = 0xC0; + Ip[4] = 0x90; /* nop */ + Ip[5] = 0x90; /* nop */ + + /* + * Munge the registers + */ + Regs->Eip = 0; + Regs->Cs = TRAMPOLINE_BASE / 16; + Regs->Esp = 0xFFFF; + Regs->Ss = TRAMPOLINE_BASE / 16; + Regs->Eflags = (1 << 1) | (1 << 17) | (1 << 9); /* VM, IF */ + Regs->RecoveryAddress = TRAMPOLINE_BASE + 2; + Regs->RecoveryInstruction[0] = 0x63; /* arpl ax, ax */ + Regs->RecoveryInstruction[1] = 0xC0; + Regs->RecoveryInstruction[2] = 0x90; /* nop */ + Regs->RecoveryInstruction[3] = 0x90; /* nop */ + Regs->Flags = KV86M_EMULATE_CLI_STI | KV86M_ALLOW_IO_PORT_ACCESS; + Regs->Vif = 1; + Regs->PStatus = &Status; + + /* + * Execute the BIOS interrupt + */ + Ki386RetToV86Mode(Regs, &ORegs); + + /* + * Copy the return values back to the caller + */ + memcpy(Regs, &ORegs, sizeof(KV86M_REGISTERS)); + + return(Status); +} + + + + + diff --git a/ntoskrnl/ke/i386/brkpoint.c b/ntoskrnl/ke/i386/brkpoint.c new file mode 100644 index 0000000..5f2f7eb --- /dev/null +++ b/ntoskrnl/ke/i386/brkpoint.c @@ -0,0 +1,46 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/dbg/brkpoints.c + * PURPOSE: Handles breakpoints + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +DbgBreakPoint(VOID) +{ + __asm__("int $3\n\t"); +} + +VOID STDCALL +DbgBreakPointWithStatus(ULONG Status) +{ + __asm__("mov %0, %%eax\n\t" + "int $3\n\t" + ::"m"(Status)); +} diff --git a/ntoskrnl/ke/i386/bthread.S b/ntoskrnl/ke/i386/bthread.S new file mode 100644 index 0000000..662d575 --- /dev/null +++ b/ntoskrnl/ke/i386/bthread.S @@ -0,0 +1,146 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/bthread.S + * PURPOSE: Trap handlers + * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +/* Values for contextflags */ +#define CONTEXT_i386 0x10000 +#define CONTEXT_CONTROL (CONTEXT_i386 | 1) +#define CONTEXT_INTEGER (CONTEXT_i386 | 2) +#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4) +#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10) +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) + +/* FUNCTIONS *****************************************************************/ + +/* + * + */ + +.globl _PsBeginThreadWithContextInternal +.globl _PsBeginThread + +_PsBeginThread: + /* + * This isn't really a function, we are called as the return address + * of the context switch function + */ + + /* + * Do the necessary prolog after a context switch + */ + call _PiBeforeBeginThread + + /* + * Call the actual start of the thread + */ + movl 4(%esp), %ebx /* Start routine */ + movl 8(%esp), %eax /* Start context */ + pushl %eax + call *%ebx /* Call the start routine */ + addl $4, %esp + + /* + * Terminate the thread + */ + pushl %eax + call _PsTerminateSystemThread@4 + addl $4, %esp + + /* + * If that fails then bug check + */ + pushl $0 + call _KeBugCheck@4 + addl $4, %esp + + /* + * And if that fails then loop + */ +.1: + jmp .1 + + +_PsBeginThreadWithContextInternal: + /* + * This isn't really a function, we are called as the return + * address of a context switch + */ + + /* + * Do the necessary prolog before the context switch + */ + call _PiBeforeBeginThread + + /* + * Load the context flags. + */ + popl %ebx + + /* + * Load the debugging registers + */ + testl $CONTEXT_DEBUG_REGISTERS, %ebx + jz .L1 + popl %eax /* Dr0 */ + movl %eax, %dr0 + popl %eax /* Dr1 */ + movl %eax, %dr1 + popl %eax /* Dr2 */ + movl %eax, %dr2 + popl %eax /* Dr3 */ + movl %eax, %dr3 + popl %eax /* Dr6 */ + movl %eax, %dr6 + popl %eax /* Dr7 */ + movl %eax, %dr7 + jmp .L3 +.L1: + addl $24, %esp +.L3: + + /* + * Load the floating point registers + */ + movl (_HardwareMathSupport), %eax + jz .L2 + testl $CONTEXT_FLOATING_POINT, %ebx + jz .L2 + frstor (%esp) +.L2: + addl $112, %esp + + /* Load the rest of the thread's user mode context. */ + movl $0, %eax + jmp KeReturnFromSystemCallWithHook + diff --git a/ntoskrnl/ke/i386/exp.c b/ntoskrnl/ke/i386/exp.c new file mode 100644 index 0000000..c8da711 --- /dev/null +++ b/ntoskrnl/ke/i386/exp.c @@ -0,0 +1,629 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/exp.c + * PURPOSE: Handling exceptions + * PROGRAMMER: David Welch (welch@cwcom.net) + * REVISION HISTORY: + * ??/??/??: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +#define _STR(x) #x +#define STR(x) _STR(x) + +extern void interrupt_handler2e(void); +extern void interrupt_handler2d(void); + +extern VOID KiTrap0(VOID); +extern VOID KiTrap1(VOID); +extern VOID KiTrap2(VOID); +extern VOID KiTrap3(VOID); +extern VOID KiTrap4(VOID); +extern VOID KiTrap5(VOID); +extern VOID KiTrap6(VOID); +extern VOID KiTrap7(VOID); +extern VOID KiTrap8(VOID); +extern VOID KiTrap9(VOID); +extern VOID KiTrap10(VOID); +extern VOID KiTrap11(VOID); +extern VOID KiTrap12(VOID); +extern VOID KiTrap13(VOID); +extern VOID KiTrap14(VOID); +extern VOID KiTrap15(VOID); +extern VOID KiTrap16(VOID); +extern VOID KiTrapUnknown(VOID); + +extern ULONG init_stack; +extern ULONG init_stack_top; + +static char *ExceptionTypeStrings[] = + { + "Divide Error", + "Debug Trap", + "NMI", + "Breakpoint", + "Overflow", + "BOUND range exceeded", + "Invalid Opcode", + "No Math Coprocessor", + "Double Fault", + "Unknown(9)", + "Invalid TSS", + "Segment Not Present", + "Stack Segment Fault", + "General Protection", + "Page Fault", + "Math Fault", + "Alignment Check", + "Machine Check" + }; + +static NTSTATUS ExceptionToNtStatus[] = + { + STATUS_INTEGER_DIVIDE_BY_ZERO, + STATUS_SINGLE_STEP, + STATUS_ACCESS_VIOLATION, + STATUS_BREAKPOINT, + STATUS_INTEGER_OVERFLOW, + STATUS_ARRAY_BOUNDS_EXCEEDED, + STATUS_ILLEGAL_INSTRUCTION, + STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */ + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_STACK_OVERFLOW, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, + STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */ + STATUS_DATATYPE_MISALIGNMENT, + STATUS_ACCESS_VIOLATION + }; + +extern unsigned int _text_start__, _text_end__; + +/* FUNCTIONS ****************************************************************/ + +STATIC BOOLEAN +print_address(PVOID address) +{ + PLIST_ENTRY current_entry; + MODULE_TEXT_SECTION* current; + extern LIST_ENTRY ModuleTextListHead; + ULONG_PTR RelativeAddress; + + current_entry = ModuleTextListHead.Flink; + + while (current_entry != &ModuleTextListHead && + current_entry != NULL) + { + current = + CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry); + + if (address >= (PVOID)current->Base && + address < (PVOID)(current->Base + current->Length)) + { + RelativeAddress = (ULONG_PTR) address - current->Base; + DbgPrint("<%ws: %x>", current->Name, RelativeAddress); + return(TRUE); + } + current_entry = current_entry->Flink; + } + return(FALSE); +} + +ULONG +KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) +{ + EXCEPTION_RECORD Er; + + Er.ExceptionFlags = 0; + Er.ExceptionRecord = NULL; + Er.ExceptionAddress = (PVOID)Tf->Eip; + + if (ExceptionNr == 14) + { + Er.NumberParameters = 2; + Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1; + Er.ExceptionInformation[1] = (ULONG)Cr2; + } + else + { + if (ExceptionNr < 16) + { + Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr]; + } + else + { + Er.ExceptionCode = STATUS_ACCESS_VIOLATION; + } + Er.NumberParameters = 0; + } + + KiDispatchException(&Er, 0, Tf, KernelMode, TRUE); + + return(0); +} + +ULONG +KiDoubleFaultHandler(VOID) +{ + unsigned int cr2; + ULONG StackLimit; + ULONG StackBase; + ULONG Esp0; + ULONG ExceptionNr = 8; + KTSS* OldTss; + PULONG Frame; + ULONG OldCr3; +#if 0 + ULONG i, j; + static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)]; + static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)]; + static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)]; + ULONG TraceLength; + BOOLEAN FoundRepeat; +#endif + + OldTss = KeGetCurrentKPCR()->TSS; + Esp0 = OldTss->Esp; + + /* Get CR2 */ + __asm__("movl %%cr2,%0\n\t" : "=d" (cr2)); + + if (PsGetCurrentThread() != NULL && + PsGetCurrentThread()->ThreadsProcess != NULL) + { + OldCr3 = + PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart; + } + else + { + OldCr3 = 0xBEADF0AL; + } + + /* + * Check for stack underflow + */ + if (PsGetCurrentThread() != NULL && + Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit) + { + DbgPrint("Stack underflow (tf->esp %x Limit %x)\n", + Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit); + ExceptionNr = 12; + } + + /* + * Print out the CPU registers + */ + if (ExceptionNr < 19) + { + DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr], + ExceptionNr, 0); + } + else + { + DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0); + } + DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip); + print_address((PVOID)OldTss->Eip); + DbgPrint("\n"); + DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3); + DbgPrint("Proc: %x ",PsGetCurrentProcess()); + if (PsGetCurrentProcess() != NULL) + { + DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId); + DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName); + } + if (PsGetCurrentThread() != NULL) + { + DbgPrint("Thrd: %x Tid: %x", + PsGetCurrentThread(), + PsGetCurrentThread()->Cid.UniqueThread); + } + DbgPrint("\n"); + DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es, + OldTss->Fs, OldTss->Gs); + DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx, + OldTss->Ecx); + DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", OldTss->Edx, OldTss->Ebp, + OldTss->Esi); + DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags); + if (OldTss->Cs == KERNEL_CS) + { + DbgPrint("kESP %.8x ", Esp0); + if (PsGetCurrentThread() != NULL) + { + DbgPrint("kernel stack base %x\n", + PsGetCurrentThread()->Tcb.StackLimit); + + } + } + else + { + DbgPrint("User ESP %.8x\n", OldTss->Esp); + } + if ((OldTss->Cs & 0xffff) == KERNEL_CS) + { + DbgPrint("ESP %x\n", Esp0); + if (PsGetCurrentThread() != NULL) + { + StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase; + StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit; + } + else + { + StackLimit = (ULONG)&init_stack_top; + StackBase = (ULONG)&init_stack; + } + +#if 1 + DbgPrint("Frames: "); + Frame = (PULONG)OldTss->Ebp; + while (Frame != NULL && (ULONG)Frame >= StackBase) + { + print_address((PVOID)Frame[1]); + Frame = (PULONG)Frame[0]; + DbgPrint(" "); + } +#else + DbgPrint("Frames: "); + i = 0; + Frame = (PULONG)OldTss->Ebp; + while (Frame != NULL && (ULONG)Frame >= StackBase) + { + StackTrace[i] = (PVOID)Frame[1]; + Frame = (PULONG)Frame[0]; + i++; + } + TraceLength = i; + + i = 0; + while (i < TraceLength) + { + StackRepeatCount[i] = 0; + j = i + 1; + FoundRepeat = FALSE; + while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE) + { + if (memcmp(&StackTrace[i], &StackTrace[j], + (j - i) * sizeof(PVOID)) == 0) + { + StackRepeatCount[i] = 2; + StackRepeatLength[i] = j - i; + FoundRepeat = TRUE; + } + else + { + j++; + } + } + if (FoundRepeat == FALSE) + { + i++; + continue; + } + j = j + StackRepeatLength[i]; + while ((TraceLength - j) >= StackRepeatLength[i] && + FoundRepeat == TRUE) + { + if (memcmp(&StackTrace[i], &StackTrace[j], + StackRepeatLength[i] * sizeof(PVOID)) == 0) + { + StackRepeatCount[i]++; + j = j + StackRepeatLength[i]; + } + else + { + FoundRepeat = FALSE; + } + } + i = j; + } + + i = 0; + while (i < TraceLength) + { + if (StackRepeatCount[i] == 0) + { + print_address(StackTrace[i]); + i++; + } + else + { + DbgPrint("{"); + if (StackRepeatLength[i] == 0) + { + for(;;); + } + for (j = 0; j < StackRepeatLength[i]; j++) + { + print_address(StackTrace[i + j]); + } + DbgPrint("}*%d", StackRepeatCount[i]); + i = i + StackRepeatLength[i] * StackRepeatCount[i]; + } + } +#endif + } + + DbgPrint("\n"); + for(;;); +} + +VOID +KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2) +{ + ULONG cr3; + ULONG i; + ULONG StackLimit; + PULONG Frame; + ULONG Esp0; + ULONG ExceptionNr = (ULONG)Tf->DebugArgMark; + ULONG cr2 = (ULONG)Tf->DebugPointer; + + Esp0 = (ULONG)Tf; + + /* + * Print out the CPU registers + */ + if (ExceptionNr < 19) + { + DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr], + ExceptionNr, Tf->ErrorCode&0xffff); + } + else + { + DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff); + } + DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(), + Tf->Cs&0xffff, Tf->Eip); + print_address((PVOID)Tf->Eip); + DbgPrint("\n"); + __asm__("movl %%cr3,%0\n\t" : "=d" (cr3)); + DbgPrint("cr2 %x cr3 %x ", cr2, cr3); + DbgPrint("Proc: %x ",PsGetCurrentProcess()); + if (PsGetCurrentProcess() != NULL) + { + DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId); + DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName); + } + if (PsGetCurrentThread() != NULL) + { + DbgPrint("Thrd: %x Tid: %x", + PsGetCurrentThread(), + PsGetCurrentThread()->Cid.UniqueThread); + } + DbgPrint("\n"); + DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff, + Tf->Fs&0xffff, Tf->Gs&0xfff); + DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx); + DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi); + DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags); + if ((Tf->Cs&0xffff) == KERNEL_CS) + { + DbgPrint("kESP %.8x ", Esp0); + if (PsGetCurrentThread() != NULL) + { + DbgPrint("kernel stack base %x\n", + PsGetCurrentThread()->Tcb.StackLimit); + + } + } + + DbgPrint("ESP %x\n", Esp0); + + if (PsGetCurrentThread() != NULL) + { + StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase; + } + else + { + StackLimit = (ULONG)&init_stack_top; + } + + /* + * Dump the stack frames + */ + DbgPrint("Frames: "); + i = 1; + Frame = (PULONG)Tf->Ebp; + while (Frame != NULL) + { + print_address((PVOID)Frame[1]); + Frame = (PULONG)Frame[0]; + i++; + DbgPrint(" "); + } +} + +ULONG +KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr) +/* + * FUNCTION: Called by the lowlevel execption handlers to print an amusing + * message and halt the computer + * ARGUMENTS: + * Complete CPU context + */ +{ + unsigned int cr2; + NTSTATUS Status; + ULONG Esp0; + + /* Store the exception number in an unused field in the trap frame. */ + Tf->DebugArgMark = (PVOID)ExceptionNr; + + /* Use the address of the trap frame as approximation to the ring0 esp */ + Esp0 = (ULONG)&Tf->Eip; + + /* Get CR2 */ + __asm__("movl %%cr2,%0\n\t" : "=d" (cr2)); + Tf->DebugPointer = (PVOID)cr2; + + /* + * If this was a V86 mode exception then handle it specially + */ + if (Tf->Eflags & (1 << 17)) + { + return(KeV86Exception(ExceptionNr, Tf, cr2)); + } + + /* + * Check for stack underflow, this may be obsolete + */ + if (PsGetCurrentThread() != NULL && + Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit) + { + DbgPrint("Stack underflow (tf->esp %x Limit %x)\n", + Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit); + ExceptionNr = 12; + } + + /* + * Maybe handle the page fault and return + */ + if (ExceptionNr == 14) + { + __asm__("sti\n\t"); + Status = MmPageFault(Tf->Cs&0xffff, + &Tf->Eip, + &Tf->Eax, + cr2, + Tf->ErrorCode); + if (NT_SUCCESS(Status)) + { + return(0); + } + + } + + /* + * Handle user exceptions differently + */ + if ((Tf->Cs & 0xFFFF) == USER_CS) + { + return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2)); + } + else + { + return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2)); + } +} + +VOID +KeDumpStackFrames(PULONG Frame) +{ + ULONG i; + + DbgPrint("Frames: "); + i = 1; + while (Frame != NULL) + { + print_address((PVOID)Frame[1]); + Frame = (PULONG)Frame[0]; + i++; + DbgPrint(" "); + } +} + +static void set_system_call_gate(unsigned int sel, unsigned int func) +{ + DPRINT("sel %x %d\n",sel,sel); + KiIdt[sel].a = (((int)func)&0xffff) + + (KERNEL_CS << 16); + KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000); + DPRINT("idt[sel].b %x\n",KiIdt[sel].b); +} + +static void set_interrupt_gate(unsigned int sel, unsigned int func) +{ + DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func); + KiIdt[sel].a = (((int)func)&0xffff) + + (KERNEL_CS << 16); + KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000); +} + +static void +set_task_gate(unsigned int sel, unsigned task_sel) +{ + KiIdt[sel].a = task_sel << 16; + KiIdt[sel].b = 0x8500; +} + +VOID +KeInitExceptions(VOID) +/* + * FUNCTION: Initalize CPU exception handling + */ +{ + int i; + + DPRINT("KeInitExceptions()\n"); + + /* + * Set up the other gates + */ + set_interrupt_gate(0, (ULONG)KiTrap0); + set_interrupt_gate(1, (ULONG)KiTrap1); + set_interrupt_gate(2, (ULONG)KiTrap2); + set_interrupt_gate(3, (ULONG)KiTrap3); + set_interrupt_gate(4, (ULONG)KiTrap4); + set_interrupt_gate(5, (ULONG)KiTrap5); + set_interrupt_gate(6, (ULONG)KiTrap6); + set_interrupt_gate(7, (ULONG)KiTrap7); + set_task_gate(8, TRAP_TSS_SELECTOR); + set_interrupt_gate(9, (ULONG)KiTrap9); + set_interrupt_gate(10, (ULONG)KiTrap10); + set_interrupt_gate(11, (ULONG)KiTrap11); + set_interrupt_gate(12, (ULONG)KiTrap12); + set_interrupt_gate(13, (ULONG)KiTrap13); + set_interrupt_gate(14, (ULONG)KiTrap14); + set_interrupt_gate(15, (ULONG)KiTrap15); + set_interrupt_gate(16, (ULONG)KiTrap16); + + for (i=17;i<256;i++) + { + set_interrupt_gate(i,(int)KiTrapUnknown); + } + + set_system_call_gate(0x2d,(int)interrupt_handler2d); + set_system_call_gate(0x2e,(int)interrupt_handler2e); +} diff --git a/ntoskrnl/ke/i386/fpu.c b/ntoskrnl/ke/i386/fpu.c new file mode 100644 index 0000000..44472db --- /dev/null +++ b/ntoskrnl/ke/i386/fpu.c @@ -0,0 +1,74 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/fpu.c + * PURPOSE: Handles the FPU + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +ULONG HardwareMathSupport; + +/* FUNCTIONS *****************************************************************/ + +VOID +KiCheckFPU(VOID) +{ + unsigned short int status; + int cr0; + + HardwareMathSupport = 0; + + __asm__("movl %%cr0, %0\n\t" : "=a" (cr0)); + /* Set NE and MP. */ + cr0 = cr0 | 0x22; + /* Clear EM */ + cr0 = cr0 & (~0x4); + __asm__("movl %0, %%cr0\n\t" : : "a" (cr0)); + + __asm__("clts\n\t"); + __asm__("fninit\n\t"); + __asm__("fstsw %0\n\t" : "=a" (status)); + if (status != 0) + { + __asm__("movl %%cr0, %0\n\t" : "=a" (cr0)); + /* Set the EM flag in CR0 so any FPU instructions cause a trap. */ + cr0 = cr0 | 0x4; + __asm__("movl %0, %%cr0\n\t" : + : "a" (cr0)); + return; + } + /* fsetpm for i287, ignored by i387 */ + __asm__(".byte 0xDB, 0xE4\n\t"); + HardwareMathSupport = 1; +} diff --git a/ntoskrnl/ke/i386/gdt.c b/ntoskrnl/ke/i386/gdt.c new file mode 100644 index 0000000..f0a052c --- /dev/null +++ b/ntoskrnl/ke/i386/gdt.c @@ -0,0 +1,212 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/gdt.c + * PURPOSE: GDT managment + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +PUSHORT KiGdtArray[MAXIMUM_PROCESSORS]; + +USHORT KiBootGdt[11 * 4] = +{ + 0x0, 0x0, 0x0, 0x0, /* Null */ + 0xffff, 0x0, 0x9a00, 0xcf, /* Kernel CS */ + 0xffff, 0x0, 0x9200, 0xcf, /* Kernel DS */ + 0x0, 0x0, 0xfa00, 0xcc, /* User CS */ + 0x0, 0x0, 0xf200, 0xcc, /* User DS */ + 0x0, 0x0, 0x0, 0x0, /* TSS */ + 0x1000, 0x0000, 0x9200, 0xff00, /* PCR */ + 0x1000, 0x0, 0xf200, 0x0, /* TEB */ + 0x0, 0x0, 0x0, 0x0, /* Reserved */ + 0x0, 0x0, 0x0, 0x0, /* LDT */ + 0x0, 0x0, 0x0, 0x0 /* Trap TSS */ +}; + +struct +{ + USHORT Length; + ULONG Base; +} __attribute__((packed)) KiGdtDescriptor = { 11 * 8, (ULONG)KiBootGdt }; + +static KSPIN_LOCK GdtLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +KiGdtPrepareForApplicationProcessorInit(ULONG Id) +{ + KiGdtArray[Id] = ExAllocatePool(NonPagedPool, sizeof(USHORT) * 4 * 11); +} + +VOID +KiInitializeGdt(PKPCR Pcr) +{ + PUSHORT Gdt; + struct + { + USHORT Length; + ULONG Base; + } __attribute__((packed)) Descriptor; + ULONG Entry; + ULONG Base; + + if (Pcr == NULL) + { + KiGdtArray[0] = KiBootGdt; + return; + } + + /* + * Allocate a GDT + */ + Gdt = KiGdtArray[Pcr->ProcessorNumber]; + if (Gdt == NULL) + { + DbgPrint("No GDT (%d)\n", Pcr->ProcessorNumber); + KeBugCheck(0); + } + + /* + * Copy the boot processor's GDT onto this processor's GDT. Note that + * the only entries that can change are the PCR, TEB and LDT descriptors. + * We will be initializing these later so their current values are + * irrelevant. + */ + memcpy(Gdt, KiBootGdt, sizeof(USHORT) * 4 * 11); + Pcr->GDT = Gdt; + + /* + * Set the base address of the PCR + */ + Base = (ULONG)Pcr; + Entry = PCR_SELECTOR / 2; + Gdt[Entry + 1] = ((ULONG)Base) & 0xffff; + + Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff); + Gdt[Entry + 2] = Gdt[Entry + 2] | ((((ULONG)Base) & 0xff0000) >> 16); + + Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00); + Gdt[Entry + 3] = Gdt[Entry + 3] | ((((ULONG)Base) & 0xff000000) >> 16); + + /* + * Load the GDT + */ + Descriptor.Length = 8 * 11; + Descriptor.Base = (ULONG)Gdt; + __asm__ ("lgdt %0\n\t" : /* no output */ : "m" (Descriptor)); + + /* + * Reload the selectors + */ + __asm__ ("movl %0, %%ds\n\t" + "movl %0, %%es\n\t" + "movl %1, %%fs\n\t" + "movl %0, %%gs\n\t" + : /* no output */ + : "a" (KERNEL_DS), "b" (PCR_SELECTOR)); + __asm__ ("pushl %0\n\t" + "pushl $.l4\n\t" + "lret\n\t" + ".l4:\n\t" + : /* no output */ + : "a" (KERNEL_CS)); +} + +VOID +KeSetBaseGdtSelector(ULONG Entry, + PVOID Base) +{ + KIRQL oldIrql; + PUSHORT Gdt = KeGetCurrentKPCR()->GDT; + + DPRINT("KeSetBaseGdtSelector(Entry %x, Base %x)\n", + Entry, Base); + + KeAcquireSpinLock(&GdtLock, &oldIrql); + + Entry = (Entry & (~0x3)) / 2; + + Gdt[Entry + 1] = ((ULONG)Base) & 0xffff; + + Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff); + Gdt[Entry + 2] = Gdt[Entry + 2] | + ((((ULONG)Base) & 0xff0000) >> 16); + + Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00); + Gdt[Entry + 3] = Gdt[Entry + 3] | + ((((ULONG)Base) & 0xff000000) >> 16); + + DPRINT("%x %x %x %x\n", + Gdt[Entry + 0], + Gdt[Entry + 1], + Gdt[Entry + 2], + Gdt[Entry + 3]); + + KeReleaseSpinLock(&GdtLock, oldIrql); +} + +VOID +KeDumpGdtSelector(ULONG Entry) +{ + USHORT a, b, c, d; + ULONG RawLimit; + + a = KiBootGdt[Entry*4]; + b = KiBootGdt[Entry*4 + 1]; + c = KiBootGdt[Entry*4 + 2]; + d = KiBootGdt[Entry*4 + 3]; + + DbgPrint("Base: %x\n", b + ((c & 0xff) * (1 << 16)) + + ((d & 0xff00) * (1 << 16))); + RawLimit = a + ((d & 0xf) * (1 << 16)); + if (d & 0x80) + { + DbgPrint("Limit: %x\n", RawLimit * 4096); + } + else + { + DbgPrint("Limit: %x\n", RawLimit); + } + DbgPrint("Accessed: %d\n", (c & 0x100) >> 8); + DbgPrint("Type: %x\n", (c & 0xe00) >> 9); + DbgPrint("System: %d\n", (c & 0x1000) >> 12); + DbgPrint("DPL: %d\n", (c & 0x6000) >> 13); + DbgPrint("Present: %d\n", (c & 0x8000) >> 15); + DbgPrint("AVL: %x\n", (d & 0x10) >> 4); + DbgPrint("D: %d\n", (d & 0x40) >> 6); + DbgPrint("G: %d\n", (d & 0x80) >> 7); +} + +/* EOF */ diff --git a/ntoskrnl/ke/i386/i386-mcount.S b/ntoskrnl/ke/i386/i386-mcount.S new file mode 100644 index 0000000..8f87398 --- /dev/null +++ b/ntoskrnl/ke/i386/i386-mcount.S @@ -0,0 +1,52 @@ +/* i386-specific implemetation of profiling support. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* We need a special version of the `mcount' function since for ix86 it + must not clobber any register. This has several reasons: + - there is a bug in gcc as of version 2.7.2.2 which prohibits the + use of profiling together with nested functions + - the ELF `fixup' function uses GCC's regparm feature + - some (future) systems might want to pass parameters in registers. */ +/* dwelch: Altered for ReactOS to output the files to port 0xe9 for processing + by bochs. */ + + +.globl _mcount +_mcount: + /* Save the caller-clobbered registers. */ + pushl %eax + pushl %ecx + pushl %edx + + movw $0xe9, %dx + movl 4(%ebp), %eax + outl %eax, %dx + movl 12(%esp), %eax + outl %eax, %dx + + /* Pop the saved registers. Please note that `mcount' has no + return value. */ + popl %edx + popl %ecx + popl %eax + ret + + + diff --git a/ntoskrnl/ke/i386/idt.c b/ntoskrnl/ke/i386/idt.c new file mode 100644 index 0000000..1e2e291 --- /dev/null +++ b/ntoskrnl/ke/i386/idt.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/idt.c + * PURPOSE: IDT managment + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +IDT_DESCRIPTOR KiIdt[256]; + +struct +{ + USHORT Length; + ULONG Base; +} __attribute__((packed)) KiIdtDescriptor = {256 * 8, (ULONG)KiIdt}; + + +/* FUNCTIONS *****************************************************************/ + + diff --git a/ntoskrnl/ke/i386/irq.c b/ntoskrnl/ke/i386/irq.c new file mode 100644 index 0000000..286ef5e --- /dev/null +++ b/ntoskrnl/ke/i386/irq.c @@ -0,0 +1,718 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/irq.c + * PURPOSE: IRQ handling + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 29/05/98: Created + */ + +/* + * NOTE: In general the PIC interrupt priority facilities are used to + * preserve the NT IRQL semantics, global interrupt disables are only used + * to keep the PIC in a consistent state + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#ifdef MP +#include +#endif /* MP */ + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +#ifdef MP + +/* + * FIXME: This does not work if we have more than 24 IRQs (ie. more than one + * I/O APIC) + */ +#define VECTOR2IRQ(vector) (((vector) - 0x31) / 8) +#define VECTOR2IRQL(vector) (4 + VECTOR2IRQ(vector)) + +#define IRQ_BASE FIRST_DEVICE_VECTOR +#define NR_IRQS 0x100 - 0x30 + +#define __STR(x) #x +#define STR(x) __STR(x) + +#define INT_NAME(intnum) _KiUnexpectedInterrupt##intnum +#define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum + +#define BUILD_COMMON_INTERRUPT_HANDLER() \ +__asm__( \ + "_KiCommonInterrupt:\n\t" \ + "cld\n\t" \ + "pushl %ds\n\t" \ + "pushl %es\n\t" \ + "pushl %fs\n\t" \ + "pushl %gs\n\t" \ + "movl $0xceafbeef,%eax\n\t" \ + "pushl %eax\n\t" \ + "movl $" STR(KERNEL_DS) ",%eax\n\t" \ + "movl %eax,%ds\n\t" \ + "movl %eax,%es\n\t" \ + "movl $" STR(PCR_SELECTOR) ",%eax\n\t" \ + "movl %eax,%fs\n\t" \ + "pushl %esp\n\t" \ + "pushl %ebx\n\t" \ + "call _KiInterruptDispatch\n\t" \ + "popl %eax\n\t" \ + "popl %eax\n\t" \ + "popl %eax\n\t" \ + "popl %gs\n\t" \ + "popl %fs\n\t" \ + "popl %es\n\t" \ + "popl %ds\n\t" \ + "popa\n\t" \ + "iret\n\t"); + +#define BUILD_INTERRUPT_HANDLER(intnum) \ +VOID INT_NAME2(intnum)(VOID); \ +__asm__( \ + STR(INT_NAME(intnum)) ":\n\t" \ + "pusha\n\t" \ + "movl $0x" STR(intnum) ",%ebx\n\t" \ + "jmp _KiCommonInterrupt"); + + +/* Interrupt handlers and declarations */ + +#define B(x,y) \ + BUILD_INTERRUPT_HANDLER(x##y) + +#define B16(x) \ + B(x,0) B(x,1) B(x,2) B(x,3) \ + B(x,4) B(x,5) B(x,6) B(x,7) \ + B(x,8) B(x,9) B(x,A) B(x,B) \ + B(x,C) B(x,D) B(x,E) B(x,F) + + +BUILD_COMMON_INTERRUPT_HANDLER() +B16(3) B16(4) B16(5) B16(6) +B16(7) B16(8) B16(9) B16(A) +B16(B) B16(C) B16(D) B16(E) +B16(F) + +#undef B +#undef B16 + + +/* Interrupt handler list */ + +#define L(x,y) \ + (ULONG)& INT_NAME2(x##y) + +#define L16(x) \ + L(x,0), L(x,1), L(x,2), L(x,3), \ + L(x,4), L(x,5), L(x,6), L(x,7), \ + L(x,8), L(x,9), L(x,A), L(x,B), \ + L(x,C), L(x,D), L(x,E), L(x,F) + +static ULONG irq_handler[NR_IRQS] = { + L16(3), L16(4), L16(5), L16(6), + L16(7), L16(8), L16(9), L16(A), + L16(B), L16(C), L16(D), L16(E), + L16(F) +}; + +#undef L +#undef L16 + +#else /* MP */ + +#define NR_IRQS (16) +#define IRQ_BASE (0x40) + + void irq_handler_0(void); + void irq_handler_1(void); + void irq_handler_2(void); + void irq_handler_3(void); + void irq_handler_4(void); + void irq_handler_5(void); + void irq_handler_6(void); + void irq_handler_7(void); + void irq_handler_8(void); + void irq_handler_9(void); + void irq_handler_10(void); + void irq_handler_11(void); + void irq_handler_12(void); + void irq_handler_13(void); + void irq_handler_14(void); + void irq_handler_15(void); + +static unsigned int irq_handler[NR_IRQS]= + { + (int)&irq_handler_0, + (int)&irq_handler_1, + (int)&irq_handler_2, + (int)&irq_handler_3, + (int)&irq_handler_4, + (int)&irq_handler_5, + (int)&irq_handler_6, + (int)&irq_handler_7, + (int)&irq_handler_8, + (int)&irq_handler_9, + (int)&irq_handler_10, + (int)&irq_handler_11, + (int)&irq_handler_12, + (int)&irq_handler_13, + (int)&irq_handler_14, + (int)&irq_handler_15, + }; + +#endif /* MP */ + +/* + * PURPOSE: Object describing each isr + * NOTE: The data in this table is only modified at passsive level but can + * be accessed at any irq level. + */ + +static LIST_ENTRY isr_table[NR_IRQS]={{NULL,NULL},}; +static PKSPIN_LOCK isr_lock[NR_IRQS] = {NULL,}; +static KSPIN_LOCK isr_table_lock = {0,}; + +#define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L') +#define TAG_KINTERRUPT TAG('K', 'I', 'S', 'R') + +/* FUNCTIONS ****************************************************************/ + +#define PRESENT (0x8000) +#define I486_INTERRUPT_GATE (0xe00) + +VOID KeInitInterrupts (VOID) +{ + int i; + +#ifdef MP + + /* + * Setup the IDT entries to point to the interrupt handlers + */ + for (i=0;iFs = IrqTrapFrame->Fs; + TrapFrame->Fs = IrqTrapFrame->Es; + TrapFrame->Ds = IrqTrapFrame->Ds; + TrapFrame->Eax = IrqTrapFrame->Eax; + TrapFrame->Ecx = IrqTrapFrame->Ecx; + TrapFrame->Edx = IrqTrapFrame->Edx; + TrapFrame->Ebx = IrqTrapFrame->Ebx; + TrapFrame->Esp = IrqTrapFrame->Esp; + TrapFrame->Ebp = IrqTrapFrame->Ebp; + TrapFrame->Esi = IrqTrapFrame->Esi; + TrapFrame->Edi = IrqTrapFrame->Edi; + TrapFrame->Eip = IrqTrapFrame->Eip; + TrapFrame->Cs = IrqTrapFrame->Cs; + TrapFrame->Eflags = IrqTrapFrame->Eflags; +} + +#endif + +#ifdef MP + +VOID +KiInterruptDispatch (ULONG Vector, PKIRQ_TRAPFRAME Trapframe) +/* + * FUNCTION: Calls the irq specific handler for an irq + * ARGUMENTS: + * Vector = Interrupt vector + * Trapframe = CPU context + */ +{ + KIRQL old_level; + PKINTERRUPT isr; + PLIST_ENTRY current; + ULONG irq; + +#ifdef DBG + + KTRAP_FRAME KernelTrapFrame; + + KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); + KeGetCurrentThread()->TrapFrame = &KernelTrapFrame; + +#endif /* DBG */ + + DPRINT("I(%d) ", Vector); + + /* + * Notify the rest of the kernel of the raised irq level + */ + HalBeginSystemInterrupt (Vector, + VECTOR2IRQL(Vector), + &old_level); + + irq = VECTOR2IRQ(Vector); + + /* + * Enable interrupts + * NOTE: Only higher priority interrupts will get through + */ + __asm__("sti\n\t"); + + if (irq == 0) + { + if (KeGetCurrentProcessorNumber() == 0) + { + KiUpdateSystemTime(old_level, Trapframe->Eip); + } + } + else + { + DPRINT("KiInterruptDispatch(Vector %d)\n", Vector); + /* + * Iterate the list until one of the isr tells us its device interrupted + */ + current = isr_table[irq].Flink; + isr = CONTAINING_RECORD(current,KINTERRUPT,Entry); + //DPRINT("current %x isr %x\n",current,isr); + while (current!=(&isr_table[irq]) && + !isr->ServiceRoutine(isr,isr->ServiceContext)) + { + current = current->Flink; + isr = CONTAINING_RECORD(current,KINTERRUPT,Entry); + //DPRINT("current %x isr %x\n",current,isr); + } + } + /* + * Disable interrupts + */ + __asm__("cli\n\t"); + + /* + * Unmask the related irq + */ + HalEnableSystemInterrupt (Vector, 0, 0); + + /* + * If the processor level will drop below dispatch level on return then + * issue a DPC queue drain interrupt + */ + + __asm__("sti\n\t"); + + if (old_level < DISPATCH_LEVEL) + { + + HalEndSystemInterrupt (DISPATCH_LEVEL, 0); + + if (KeGetCurrentThread() != NULL) + { + KeGetCurrentThread()->LastEip = Trapframe->Eip; + } + KiDispatchInterrupt(); + if (KeGetCurrentThread() != NULL && + KeGetCurrentThread()->Alerted[1] != 0 && + Trapframe->Cs != KERNEL_CS) + { + HalEndSystemInterrupt (APC_LEVEL, 0); + KiDeliverNormalApc(); + } + } + + HalEndSystemInterrupt (old_level, 0); +} + +#else /* MP */ + +VOID STDCALL +KiInterruptDispatch2 (ULONG Irq, KIRQL old_level) +/* + * FUNCTION: Calls all the interrupt handlers for a given irq. + * ARGUMENTS: + * Irq - The number of the irq to call handlers for. + * old_level - The irql of the processor when the irq took place. + * NOTES: Must be called at DIRQL. + */ +{ + PKINTERRUPT isr; + PLIST_ENTRY current; + + if (Irq == 0) + { + KiUpdateSystemTime(old_level, 0); + } + else + { + /* + * Iterate the list until one of the isr tells us its device interrupted + */ + current = isr_table[Irq].Flink; + isr = CONTAINING_RECORD(current,KINTERRUPT,Entry); + while (current != &isr_table[Irq] && + !isr->ServiceRoutine(isr, isr->ServiceContext)) + { + current = current->Flink; + isr = CONTAINING_RECORD(current,KINTERRUPT,Entry); + } + } +} + +VOID +KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe) +/* + * FUNCTION: Calls the irq specific handler for an irq + * ARGUMENTS: + * irq = IRQ that has interrupted + */ +{ + KIRQL old_level; + + /* + * At this point we have interrupts disabled, nothing has been done to + * the PIC. + */ + + /* + * Notify the rest of the kernel of the raised irq level. For the + * default HAL this will send an EOI to the PIC and alter the IRQL. + */ + if (!HalBeginSystemInterrupt (irq + IRQ_BASE, + PROFILE_LEVEL - irq, + &old_level)) + { + return; + } + + /* + * Enable interrupts + * NOTE: Only higher priority interrupts will get through + */ + __asm__("sti\n\t"); + + /* + * Actually call the ISR. + */ + KiInterruptDispatch2(irq, old_level); + + /* + * End the system interrupt. + */ + HalEndSystemInterrupt (old_level, 0); + + /* + * Maybe do a reschedule as well. + */ + if (old_level < DISPATCH_LEVEL && irq == 0) + { + PsDispatchThread(THREAD_STATE_READY); + } +} + +#endif /* MP */ + +static VOID +KeDumpIrqList(VOID) +{ + PKINTERRUPT current; + PLIST_ENTRY current_entry; + unsigned int i; + + for (i=0;iFlink; + current = CONTAINING_RECORD(current_entry,KINTERRUPT,Entry); + } + DPRINT("\n",0); + } +} + +NTSTATUS STDCALL +KeConnectInterrupt(PKINTERRUPT InterruptObject) +{ + KIRQL oldlvl; + KIRQL synch_oldlvl; + PKINTERRUPT ListHead; + ULONG Vector; + + DPRINT("KeConnectInterrupt()\n"); + + Vector = InterruptObject->Vector; + + /* + * Acquire the table spinlock + */ + KeAcquireSpinLock(&isr_table_lock,&oldlvl); + + /* + * Check if the vector is already in use that we can share it + */ + ListHead = CONTAINING_RECORD(isr_table[Vector].Flink,KINTERRUPT,Entry); + if (!IsListEmpty(&isr_table[Vector]) && + (InterruptObject->Shareable == FALSE || ListHead->Shareable==FALSE)) + { + KeReleaseSpinLock(&isr_table_lock,oldlvl); + return(STATUS_INVALID_PARAMETER); + } + else + { + isr_lock[Vector] = + ExAllocatePoolWithTag(NonPagedPool, sizeof(KSPIN_LOCK), + TAG_ISR_LOCK); + KeInitializeSpinLock(isr_lock[Vector]); + } + + InterruptObject->IrqLock = isr_lock[Vector]; + + KeRaiseIrql(InterruptObject->SynchLevel,&synch_oldlvl); + KeAcquireSpinLockAtDpcLevel(InterruptObject->IrqLock); + DPRINT("%x %x\n",isr_table[Vector].Flink,isr_table[Vector].Blink); + InsertTailList(&isr_table[Vector],&InterruptObject->Entry); + DPRINT("%x %x\n",InterruptObject->Entry.Flink, + InterruptObject->Entry.Blink); + KeReleaseSpinLockFromDpcLevel(InterruptObject->IrqLock); + KeLowerIrql(synch_oldlvl); + + /* + * Release the table spinlock + */ + KeReleaseSpinLock(&isr_table_lock,oldlvl); + + KeDumpIrqList(); + + return STATUS_SUCCESS; +} + + +VOID STDCALL +KeDisconnectInterrupt(PKINTERRUPT InterruptObject) +/* + * FUNCTION: Releases a drivers isr + * ARGUMENTS: + * InterruptObject = isr to release + */ +{ + KIRQL oldlvl; + + KeRaiseIrql(InterruptObject->SynchLevel,&oldlvl); + KeAcquireSpinLockAtDpcLevel(InterruptObject->IrqLock); + RemoveEntryList(&InterruptObject->Entry); + KeReleaseSpinLockFromDpcLevel(InterruptObject->IrqLock); + KeLowerIrql(oldlvl); +} + + +NTSTATUS +STDCALL +KeInitializeInterrupt(PKINTERRUPT InterruptObject, + PKSERVICE_ROUTINE ServiceRoutine, + PVOID ServiceContext, + PKSPIN_LOCK SpinLock, + ULONG Vector, + KIRQL Irql, + KIRQL SynchronizeIrql, + KINTERRUPT_MODE InterruptMode, + BOOLEAN ShareVector, + KAFFINITY ProcessorEnableMask, + BOOLEAN FloatingSave) +{ + InterruptObject->ServiceContext = ServiceContext; + InterruptObject->ServiceRoutine = ServiceRoutine; + InterruptObject->Vector = Vector; + InterruptObject->ProcessorEnableMask = ProcessorEnableMask; + InterruptObject->SynchLevel = SynchronizeIrql; + InterruptObject->Shareable = ShareVector; + InterruptObject->FloatingSave = FALSE; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +IoConnectInterrupt(PKINTERRUPT* InterruptObject, + PKSERVICE_ROUTINE ServiceRoutine, + PVOID ServiceContext, + PKSPIN_LOCK SpinLock, + ULONG Vector, + KIRQL Irql, + KIRQL SynchronizeIrql, + KINTERRUPT_MODE InterruptMode, + BOOLEAN ShareVector, + KAFFINITY ProcessorEnableMask, + BOOLEAN FloatingSave) +/* + * FUNCTION: Registers a driver's isr to be called when its device interrupts + * ARGUMENTS: + * InterruptObject (OUT) = Points to the interrupt object created on + * return + * ServiceRoutine = Routine to be called when the device interrupts + * ServiceContext = Parameter to be passed to ServiceRoutine + * SpinLock = Initalized spinlock that will be used to synchronize + * access between the isr and other driver routines. This is + * required if the isr handles more than one vector or the + * driver has more than one isr + * Vector = Interrupt vector to allocate + * (returned from HalGetInterruptVector) + * Irql = DIRQL returned from HalGetInterruptVector + * SynchronizeIrql = DIRQL at which the isr will execute. This must + * be the highest of all the DIRQLs returned from + * HalGetInterruptVector if the driver has multiple + * isrs + * InterruptMode = Specifies if the interrupt is LevelSensitive or + * Latched + * ShareVector = Specifies if the vector can be shared + * ProcessorEnableMask = Processors on the isr can run + * FloatingSave = TRUE if the floating point stack should be saved when + * the isr runs. Must be false for x86 drivers + * RETURNS: Status + * IRQL: PASSIVE_LEVEL + */ +{ + PKINTERRUPT Interrupt; + NTSTATUS Status = STATUS_SUCCESS; + + ASSERT_IRQL(PASSIVE_LEVEL); + + DPRINT("IoConnectInterrupt(Vector %x)\n",Vector); + + /* + * Check the parameters + */ + if (Vector >= NR_IRQS) + { + return(STATUS_INVALID_PARAMETER); + } + if (FloatingSave == TRUE) + { + return(STATUS_INVALID_PARAMETER); + } + + /* + * Initialize interrupt object + */ + Interrupt=ExAllocatePoolWithTag(NonPagedPool,sizeof(KINTERRUPT), + TAG_KINTERRUPT); + if (Interrupt==NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Status = KeInitializeInterrupt(Interrupt, + ServiceRoutine, + ServiceContext, + SpinLock, + Vector, + Irql, + SynchronizeIrql, + InterruptMode, + ShareVector, + ProcessorEnableMask, + FloatingSave); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Interrupt); + return Status; + } + + Status = KeConnectInterrupt(Interrupt); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Interrupt); + return Status; + } + + *InterruptObject = Interrupt; + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +IoDisconnectInterrupt(PKINTERRUPT InterruptObject) +/* + * FUNCTION: Releases a drivers isr + * ARGUMENTS: + * InterruptObject = isr to release + */ +{ + KeDisconnectInterrupt(InterruptObject); + ExFreePool(InterruptObject); +} + +/* EOF */ diff --git a/ntoskrnl/ke/i386/irqhand.s b/ntoskrnl/ke/i386/irqhand.s new file mode 100644 index 0000000..d54a97c --- /dev/null +++ b/ntoskrnl/ke/i386/irqhand.s @@ -0,0 +1,403 @@ + +#include + +.global _irq_handler_0 +_irq_handler_0: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $0 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_1 +_irq_handler_1: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $1 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_2 +_irq_handler_2: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $2 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_3 +_irq_handler_3: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $3 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_4 +_irq_handler_4: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $4 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_5 +_irq_handler_5: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $5 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_6 +_irq_handler_6: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $6 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_7 +_irq_handler_7: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $7 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_8 +_irq_handler_8: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $8 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_9 +_irq_handler_9: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $9 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_10 +_irq_handler_10: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $10 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_11 +_irq_handler_11: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $11 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_12 +_irq_handler_12: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $12 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_13 +_irq_handler_13: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $13 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_14 +_irq_handler_14: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $14 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_15 +_irq_handler_15: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movl $PCR_SELECTOR, %eax + movl %eax, %fs + pushl %esp + pushl $15 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + diff --git a/ntoskrnl/ke/i386/kernel.c b/ntoskrnl/ke/i386/kernel.c new file mode 100644 index 0000000..2d049ee --- /dev/null +++ b/ntoskrnl/ke/i386/kernel.c @@ -0,0 +1,142 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/kernel.c + * PURPOSE: Initializes the kernel + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +ULONG KiPcrInitDone = 0; +static ULONG PcrsAllocated = 0; +static PHYSICAL_ADDRESS PcrPages[MAXIMUM_PROCESSORS]; + +/* FUNCTIONS *****************************************************************/ + +VOID +KePrepareForApplicationProcessorInit(ULONG Id) +{ + MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PcrPages[Id]); + KiGdtPrepareForApplicationProcessorInit(Id); +} + +VOID +KeApplicationProcessorInit(VOID) +{ + PKPCR KPCR; + ULONG Offset; + + /* + * Create a PCR for this processor + */ + Offset = InterlockedIncrement(&PcrsAllocated) - 1; + KPCR = (PKPCR)(KPCR_BASE + (Offset * PAGE_SIZE)); + MmCreateVirtualMappingForKernel((PVOID)KPCR, + PAGE_READWRITE, + PcrPages[Offset]); + memset(KPCR, 0, PAGE_SIZE); + KPCR->ProcessorNumber = Offset; + KPCR->Self = KPCR; + KPCR->Irql = HIGH_LEVEL; + + /* Mark the end of the exception handler list */ + KPCR->ExceptionList = (PVOID)-1; + + /* + * Initialize the GDT + */ + KiInitializeGdt(KPCR); + + /* + * It is now safe to process interrupts + */ + KeLowerIrql(DISPATCH_LEVEL); + + /* + * Initialize the TSS + */ + Ki386ApplicationProcessorInitializeTSS(); + + /* + * Initialize a default LDT + */ + Ki386InitializeLdt(); + + __asm__ __volatile__ ("sti\n\t"); +} + +VOID +KeInit1(VOID) +{ + PKPCR KPCR; + extern USHORT KiBootGdt[]; + extern KTSS KiBootTss; + + KiCheckFPU(); + + KiInitializeGdt (NULL); + Ki386BootInitializeTSS(); + KeInitExceptions (); + KeInitInterrupts (); + + /* + * Initialize the initial PCR region. We can't allocate a page + * with MmAllocPage() here because MmInit1() has not yet been + * called, so we use a predefined page in low memory + */ + KPCR = (PKPCR)KPCR_BASE; + memset(KPCR, 0, PAGE_SIZE); + KPCR->Self = (PKPCR)KPCR_BASE; + KPCR->Irql = HIGH_LEVEL; + KPCR->GDT = (PUSHORT)&KiBootGdt; + KPCR->IDT = (PUSHORT)&KiIdt; + KPCR->TSS = &KiBootTss; + KPCR->ProcessorNumber = 0; + KiPcrInitDone = 1; + PcrsAllocated++; + + /* Mark the end of the exception handler list */ + KPCR->ExceptionList = (PVOID)-1; + + Ki386InitializeLdt(); +} + +VOID +KeInit2(VOID) +{ + KeInitDpc(); + KeInitializeBugCheck(); + KeInitializeDispatcher(); + KeInitializeTimerImpl(); +} diff --git a/ntoskrnl/ke/i386/ldt.c b/ntoskrnl/ke/i386/ldt.c new file mode 100644 index 0000000..b1e33d5 --- /dev/null +++ b/ntoskrnl/ke/i386/ldt.c @@ -0,0 +1,72 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/ldt.c + * PURPOSE: LDT managment + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +/* + * Empty LDT shared by every process that doesn't have its own. + */ +STATIC UCHAR KiNullLdt[8]; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtSetLdtEntries (HANDLE Thread, + ULONG FirstEntry, + PULONG Entries) +{ + return(STATUS_NOT_IMPLEMENTED); +} + +VOID +Ki386InitializeLdt(VOID) +{ + PUSHORT Gdt = KeGetCurrentKPCR()->GDT; + unsigned int base, length; + + /* + * Set up an a descriptor for the LDT + */ + base = (unsigned int)&KiNullLdt; + length = sizeof(KiNullLdt) - 1; + + Gdt[(LDT_SELECTOR / 2) + 0] = (length & 0xFFFF); + Gdt[(LDT_SELECTOR / 2) + 1] = (base & 0xFFFF); + Gdt[(LDT_SELECTOR / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8200; + Gdt[(LDT_SELECTOR / 2) + 3] = ((length & 0xF0000) >> 16) | + ((base & 0xFF000000) >> 16); +} diff --git a/ntoskrnl/ke/i386/multiboot.S b/ntoskrnl/ke/i386/multiboot.S new file mode 100644 index 0000000..c612394 --- /dev/null +++ b/ntoskrnl/ke/i386/multiboot.S @@ -0,0 +1,368 @@ +#include +#include +#include +#include + +#define KERNEL_BASE (0xc0000000) + +#define MULTIBOOT_HEADER_MAGIC (0x1BADB002) + +#define MULTIBOOT_HEADER_FLAGS (0x00010003) + +#define V2P(x) (x - 0xc0000000 + 0x200000) + +#ifdef MP + +#define AP_MAGIC (0x12481020) + +#endif /* MP */ + +.globl _NtProcessStartup +.globl _start +.globl _init_stack +.globl _init_stack_top +.globl _trap_stack +.globl _trap_stack_top +.globl _unmap_me +.globl _unmap_me2 +.globl _unmap_me3 +.globl _unmap_me4 + + /* + * This is called by the realmode loader, with protected mode + * enabled, paging disabled and the segment registers pointing + * a 4Gb, 32-bit segment starting at zero. + * + * EAX = Multiboot magic or application processor magic + * + * EBX = Points to a structure in lowmem with data from the + * loader + */ + +_NtProcessStartup: +_start: + jmp _multiboot_entry + + /* Align 32 bits boundary */ + .align 4 + + /* Multiboot header */ +multiboot_header: + /* magic */ + .long MULTIBOOT_HEADER_MAGIC + /* flags */ + .long MULTIBOOT_HEADER_FLAGS + /* checksum */ + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + /* header_addr */ + .long (0x200000 + multiboot_header - KERNEL_BASE) + /* load_addr */ + .long 0x200000 + /* load_end_addr */ + .long (__bss_start__ + 0x200000 - KERNEL_BASE) + /* bss_end_addr */ + .long (__bss_end__ + 0x200000 - KERNEL_BASE) + /* entry_addr */ + .long (0x200000 + _start - KERNEL_BASE) + +_multiboot_entry: + /* + * This must be PIC because we haven't set up paging yet + */ + + /* + * Gcc expects this at all times + */ + cld + +#ifdef MP + + /* + * Save the multiboot or application processor magic + */ + movl %eax, %edx + + cmpl $AP_MAGIC, %edx + je .m1 + +#endif /* MP */ + + /* + * Zero the BSS + */ + movl %eax, %edx + movl $0, %eax + movl $__bss_end__, %ecx + subl $__bss_start__, %ecx + shr $2, %ecx + movl $__bss_start__, %edi + subl $0xc0000000, %edi + addl $0x200000, %edi + rep + stosl + + /* + * Initialize the page directory + */ + movl $V2P(startup_pagedirectory), %esi + movl $(V2P(lowmem_pagetable) + 0x7), 0x0(%esi) + movl $(V2P(kernel_pagetable) + 0x7), 0xC00(%esi) + movl $(V2P(kernel_pagetable+4096) + 0x7), 0xC04(%esi) + movl $(V2P(kernel_pagetable+2*4096) + 0x7), 0xC08(%esi) + movl $(V2P(kernel_pagetable+3*4096) + 0x7), 0xC0c(%esi) + movl $(V2P(kernel_pagetable+4*4096) + 0x7), 0xC10(%esi) + movl $(V2P(kernel_pagetable+5*4096) + 0x7), 0xC14(%esi) + movl $(V2P(kernel_pagetable+6*4096) + 0x7), 0xC18(%esi) + movl $(V2P(kernel_pagetable+7*4096) + 0x7), 0xC1c(%esi) + movl $(V2P(kernel_pagetable+8*4096) + 0x7), 0xC20(%esi) + movl $(V2P(kernel_pagetable+9*4096) + 0x7), 0xC24(%esi) + movl $(V2P(kernel_pagetable+10*4096) + 0x7), 0xC28(%esi) + movl $(V2P(kernel_pagetable+11*4096) + 0x7), 0xC2c(%esi) + movl $(V2P(kernel_pagetable+12*4096) + 0x7), 0xC30(%esi) + movl $(V2P(kernel_pagetable+13*4096) + 0x7), 0xC34(%esi) + movl $(V2P(kernel_pagetable+14*4096) + 0x7), 0xC38(%esi) + movl $(V2P(kernel_pagetable+15*4096) + 0x7), 0xC3c(%esi) + movl $(V2P(kernel_pagetable+16*4096) + 0x7), 0xC40(%esi) + movl $(V2P(kernel_pagetable+17*4096) + 0x7), 0xC44(%esi) + movl $(V2P(kernel_pagetable+18*4096) + 0x7), 0xC48(%esi) + movl $(V2P(kernel_pagetable+19*4096) + 0x7), 0xC4c(%esi) + movl $(V2P(kernel_pagetable+20*4096) + 0x7), 0xC50(%esi) + movl $(V2P(kernel_pagetable+21*4096) + 0x7), 0xC54(%esi) + movl $(V2P(kernel_pagetable+22*4096) + 0x7), 0xC58(%esi) + movl $(V2P(kernel_pagetable+23*4096) + 0x7), 0xC5c(%esi) + movl $(V2P(kernel_pagetable+24*4096) + 0x7), 0xC60(%esi) + movl $(V2P(kernel_pagetable+25*4096) + 0x7), 0xC64(%esi) + movl $(V2P(kernel_pagetable+26*4096) + 0x7), 0xC68(%esi) + movl $(V2P(kernel_pagetable+27*4096) + 0x7), 0xC6c(%esi) + movl $(V2P(kernel_pagetable+28*4096) + 0x7), 0xC70(%esi) + movl $(V2P(kernel_pagetable+29*4096) + 0x7), 0xC74(%esi) + movl $(V2P(kernel_pagetable+30*4096) + 0x7), 0xC78(%esi) + movl $(V2P(kernel_pagetable+31*4096) + 0x7), 0xC7c(%esi) + + movl $(V2P(lowmem_pagetable) + 0x7), 0xD00(%esi) + movl $(V2P(startup_pagedirectory) + 0x7), 0xF00(%esi) +#ifdef MP + movl $(V2P(apic_pagetable) + 0x7), 0xFEC(%esi) +#endif /* MP */ + movl $(V2P(kpcr_pagetable) + 0x7), 0xFF0(%esi) + + /* + * Initialize the page table that maps low memory + */ + movl $V2P(lowmem_pagetable), %esi + movl $0x7, %eax + movl $0, %edi +.l3: + movl %eax, (%esi, %edi) + addl $0x1000, %eax + addl $4, %edi + cmpl $4096, %edi + jl .l3 + + /* + * Initialize the page table that maps kernel memory + */ + movl $V2P(kernel_pagetable), %esi + movl $0x200007, %eax + movl $0, %edi +.l4: + movl %eax, (%esi, %edi) + addl $0x1000, %eax + addl $4, %edi + cmpl $8192, %edi + jl .l4 + +#ifdef MP + + /* + * Initialize the page table that maps the APIC register address space + */ + + /* + * FIXME: APIC register address space can be non-standard so do the + * mapping later + */ + movl $V2P(apic_pagetable), %esi + movl $0, %edi + movl $0xFEC0001B, %eax + movl %eax, (%esi, %edi) + movl $0x800, %edi + movl $0xFEE0001B, %eax + movl %eax, (%esi, %edi) + +#endif /* MP */ + + /* + * Initialize the page table that maps the initial KPCR (at FF000000) + */ + movl $V2P(kpcr_pagetable), %esi + movl $0, %edi + movl $0x1007, %eax + movl %eax, (%esi, %edi) + +#ifdef MP + +.m1: + +#endif /* MP */ + + /* + * Set up the PDBR + */ + movl $(V2P(startup_pagedirectory)), %eax + movl %eax, %cr3 + + /* + * Enable paging and set write protect + */ + movl %cr0, %eax + orl $0x80010000, %eax + movl %eax, %cr0 + + /* + * Do an absolute jump because we now want to execute above 0xc0000000 + */ + movl $.l2, %eax + jmp *%eax +.l2: + + /* + * Load the GDTR and IDTR with new tables located above + * 0xc0000000 + */ + + /* FIXME: Application processors should have their own GDT/IDT */ + lgdt _KiGdtDescriptor + lidt _KiIdtDescriptor + + /* + * Reload the data segment registers + */ + movl $KERNEL_DS, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %gs + movl %eax, %ss + movl $0, %eax + movl %eax, %fs + +#ifdef MP + + cmpl $AP_MAGIC, %edx + jne .m2 + + /* + * This is an application processor executing + */ + + /* + * Initialize EFLAGS + */ + pushl $0 + popfl + + /* + * Call the application processor initialization code + */ + pushl $0 + pushl $.l7 + pushl $KERNEL_CS + pushl $_KiSystemStartup + lret + + /* + * Catch illegal returns from KiSystemStartup + */ +.l7: + popl %eax + pushl $0 + call _KeBugCheck@4 + popl %eax +.l8: + jmp .l8 + + +.m2: + +#endif /* MP */ + + /* + * Load the PCR selector + */ + movl $PCR_SELECTOR, %eax + movl %eax, %fs + + /* + * Load the initial kernel stack + */ + movl $_init_stack_top, %esp + + /* + * Initialize EFLAGS + */ + pushl $0 + popfl + + /* + * Call the main kernel initialization + */ + movl $0, %ebp + pushl %ebx + pushl %edx + pushl $.l5 + pushl $KERNEL_CS + pushl $__main + lret + + /* + * Catch illegal returns from main, try bug checking the system, + * if that fails then loop forever. + */ +.l5: + popl %eax + popl %eax + pushl $0 + call _KeBugCheck@4 + popl %eax +.l6: + jmp .l6 + + + /* + * This needs to be page aligned so put it at the beginning of the bss + * segment + */ +.bss +startup_pagedirectory: + .fill 4096, 1, 0 + +lowmem_pagetable: + .fill 4096, 1, 0 + +kernel_pagetable: + .fill 32*4096, 1, 0 + +#ifdef MP +apic_pagetable: + .fill 4096, 1, 0 +#endif /* MP */ + +kpcr_pagetable: + .fill 4096, 1, 0 + +_unmap_me: + .fill 4096, 1, 0 + +_init_stack: + .fill 3*4096, 1, 0 +_init_stack_top: + +_unmap_me2: + .fill 4096, 1, 0 + +_trap_stack: + .fill 3*4096, 1, 0 +_trap_stack_top: + +_unmap_me3: + .fill 4096, 1, 0 diff --git a/ntoskrnl/ke/i386/stkswitch.S b/ntoskrnl/ke/i386/stkswitch.S new file mode 100644 index 0000000..440b848 --- /dev/null +++ b/ntoskrnl/ke/i386/stkswitch.S @@ -0,0 +1,82 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/ke/i386/tskswitch.S + * PURPOSE: Microkernel thread support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 09/10/00 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +/* FUNCTIONS ****************************************************************/ + +/* + * FUNCTION: KeStackSwitchAndRet + * PURPOSE: Switch to a new stack and return from the first frame on + * the new stack which was assumed to a stdcall function with + * 8 bytes of arguments and which saved edi, esi and ebx. + */ +.globl _KeStackSwitchAndRet@4 +_KeStackSwitchAndRet@4: + pushl %ebp + movl %esp, %ebp + + cli + + movl 8(%ebp), %esp + + sti + + popl %edi + popl %esi + popl %ebx + + popl %ebp + ret $8 + +.globl _KePushAndStackSwitchAndSysRet@8 +_KePushAndStackSwitchAndSysRet@8: + pushl %ebp + movl %esp, %ebp + + pushl %ebx + pushl %esi + pushl %edi + + cli + + pushl 8(%ebp) + + movl %fs:KPCR_CURRENT_THREAD, %ebx + movl %esp, KTHREAD_CALLBACK_STACK(%ebx) + movl 12(%ebp), %esp + + sti + + push $0 + call _KeLowerIrql@4 + + jmp KeReturnFromSystemCall + diff --git a/ntoskrnl/ke/i386/syscall.S b/ntoskrnl/ke/i386/syscall.S new file mode 100644 index 0000000..eb4f068 --- /dev/null +++ b/ntoskrnl/ke/i386/syscall.S @@ -0,0 +1,254 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * FILE: ntoskrnl/hal/x86/syscall.s + * PURPOSE: 2E trap handler + * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + * UPDATE HISTORY: + * ??? + */ + +#include +#include +#include +#include + +/* + * + */ +.globl KeReturnFromSystemCall +.globl KeReturnFromSystemCallWithHook +.globl _interrupt_handler2e +_interrupt_handler2e: + + /* Construct a trap frame on the stack */ + + /* Error code */ + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + pushl %fs + /* Load PCR selector into fs */ + movl $PCR_SELECTOR, %ebx + movl %ebx, %fs + + /* Save the old exception list */ + movl %fs:KPCR_EXCEPTION_LIST, %ebx + pushl %ebx + /* Set the exception handler chain terminator */ + movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST + /* Get a pointer to the current thread */ + movl %fs:KPCR_CURRENT_THREAD, %esi + /* Save the old previous mode */ + movl $0, %ebx + movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl + pushl %ebx + /* Set the new previous mode based on the saved CS selector */ + movl 0x24(%esp), %ebx + andl $0x0000FFFF, %ebx + cmpl $KERNEL_CS, %ebx + jne L1 + movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) + jmp L3 +L1: + movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) +L3: + + /* Save other registers */ + pushl %eax + pushl %ecx + pushl %edx + pushl %ds + pushl %es + pushl %gs + pushl $0 /* DR7 */ + pushl $0 /* DR6 */ + pushl $0 /* DR3 */ + pushl $0 /* DR2 */ + pushl $0 /* DR1 */ + pushl $0 /* DR0 */ + pushl $0 /* XXX: TempESP */ + pushl $0 /* XXX: TempCS */ + pushl $0 /* XXX: DebugPointer */ + pushl $0 /* XXX: DebugArgMark */ + movl 0x60(%esp), %ebx + pushl %ebx /* DebugEIP */ + pushl %ebp /* DebugEBP */ + + /* Load the segment registers */ + movl $KERNEL_DS, %ebx + movl %ebx, %ds + movl %ebx, %es + movl %ebx, %gs + + /* + * Save the old trap frame pointer over where we would save the EDX + * register. + */ + movl KTHREAD_TRAP_FRAME(%esi), %ebx + movl %ebx, 0x3C(%esp) + + /* Save a pointer to the trap frame in the TCB */ + movl %esp, KTHREAD_TRAP_FRAME(%esi) + + /* Set ES to kernel segment */ + movw $KERNEL_DS,%bx + movw %bx,%es + + /* Allocate new Kernel stack frame */ + movl %esp,%ebp + + /* Users's current stack frame pointer is source */ + movl %edx,%esi + + /* Determine system service table to use */ + cmpl $0x0fff, %eax + ja new_useShadowTable + + /* Check to see if EAX is valid/inrange */ + cmpl %es:_KeServiceDescriptorTable + 8, %eax + jbe new_serviceInRange + movl $STATUS_INVALID_SYSTEM_SERVICE, %eax + jmp KeReturnFromSystemCall + +new_serviceInRange: + + /* Allocate room for argument list from kernel stack */ + movl %es:_KeServiceDescriptorTable + 12, %ecx + movl %es:(%ecx, %eax, 4), %ecx + subl %ecx, %esp + + /* Copy the arguments from the user stack to the kernel stack */ + movl %esp,%edi + rep movsb + + /* DS is now also kernel segment */ + movw %bx, %ds + + /* Call system call hook */ + pushl %eax + call _KiSystemCallHook + popl %eax + + /* Make the system service call */ + movl %es:_KeServiceDescriptorTable, %ecx + movl %es:(%ecx, %eax, 4), %eax + call *%eax + +#if CHECKED + /* Bump Service Counter */ +#endif + + /* Deallocate the kernel stack frame */ + movl %ebp,%esp + + /* Call the post system call hook and deliver any pending APCs */ + pushl %ebp + pushl %eax + call _KiAfterSystemCallHook + addl $8,%esp + + jmp KeReturnFromSystemCall + +new_useShadowTable: + + subl $0x1000, %eax + + /* Check to see if EAX is valid/inrange */ + cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax + jbe new_shadowServiceInRange + movl $STATUS_INVALID_SYSTEM_SERVICE, %eax + jmp KeReturnFromSystemCall + +new_shadowServiceInRange: + + /* Allocate room for argument list from kernel stack */ + movl %es:_KeServiceDescriptorTableShadow + 28, %ecx + movl %es:(%ecx, %eax, 4), %ecx + subl %ecx, %esp + + /* Copy the arguments from the user stack to the kernel stack */ + movl %esp,%edi + rep movsb + + /* DS is now also kernel segment */ + movw %bx,%ds + + /* Call system call hook */ + pushl %eax + call _KiSystemCallHook + popl %eax + + /* Make the system service call */ + movl %es:_KeServiceDescriptorTableShadow + 16, %ecx + movl %es:(%ecx, %eax, 4), %eax + call *%eax + +#if CHECKED + /* Bump Service Counter */ +#endif + + /* Deallocate the kernel stack frame */ + movl %ebp,%esp + +KeReturnFromSystemCallWithHook: + /* Call the post system call hook and deliver any pending APCs */ + pushl %esp + pushl %eax + call _KiAfterSystemCallHook + addl $8,%esp + +KeReturnFromSystemCall: + + /* Restore the user context */ + /* Get a pointer to the current thread */ + movl %fs:0x124, %esi + + /* Restore the old trap frame pointer */ + movl 0x3c(%esp), %ebx + movl %ebx, KTHREAD_TRAP_FRAME(%esi) + + /* Skip debug information and unsaved registers */ + addl $0x30, %esp + popl %gs + popl %es + popl %ds + popl %edx + popl %ecx + addl $0x4, %esp /* Don't restore eax */ + + /* Restore the old previous mode */ + popl %ebx + movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) + + /* Restore the old exception handler list */ + popl %ebx + movl %ebx, %fs:KPCR_EXCEPTION_LIST + + popl %fs + popl %edi + popl %esi + popl %ebx + popl %ebp + addl $0x4, %esp /* Ignore error code */ + + iret diff --git a/ntoskrnl/ke/i386/thread.c b/ntoskrnl/ke/i386/thread.c new file mode 100644 index 0000000..33a3792 --- /dev/null +++ b/ntoskrnl/ke/i386/thread.c @@ -0,0 +1,198 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/thread.c + * PURPOSE: Architecture multitasking functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * REVISION HISTORY: + * 27/06/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define FLAG_NT (1<<14) +#define FLAG_VM (1<<17) +#define FLAG_IF (1<<9) +#define FLAG_IOPL ((1<<12)+(1<<13)) + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +Ki386ValidateUserContext(PCONTEXT Context) +/* + * FUNCTION: Validates a processor context + * ARGUMENTS: + * Context = Context to validate + * RETURNS: Status + * NOTE: This only validates the context as not violating system security, it + * doesn't guararantee the thread won't crash at some point + * NOTE2: This relies on there only being two selectors which can access + * system space + */ +{ + if (Context->Eip >= KERNEL_BASE) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegCs == KERNEL_CS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegDs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegEs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegFs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if (Context->SegGs == KERNEL_DS) + { + return(STATUS_UNSUCCESSFUL); + } + if ((Context->EFlags & FLAG_IOPL) != 0 || + (Context->EFlags & FLAG_NT) || + (Context->EFlags & FLAG_VM) || + (!(Context->EFlags & FLAG_IF))) + { + return(STATUS_UNSUCCESSFUL); + } + return(STATUS_SUCCESS); +} + +NTSTATUS +Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context) +{ + PULONG KernelStack; + ULONG InitSize; + PKTRAP_FRAME TrapFrame; + + /* + * Setup a stack frame for exit from the task switching routine + */ + + InitSize = 5 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) + + sizeof(FLOATING_SAVE_AREA) + sizeof(KTRAP_FRAME); + KernelStack = (PULONG)(Thread->KernelStack - InitSize); + + /* Set up the initial frame for the return from the dispatcher. */ + KernelStack[0] = 0; /* EDI */ + KernelStack[1] = 0; /* ESI */ + KernelStack[2] = 0; /* EBX */ + KernelStack[3] = 0; /* EBP */ + KernelStack[4] = (ULONG)PsBeginThreadWithContextInternal; /* EIP */ + + /* Save the context flags. */ + KernelStack[5] = Context->ContextFlags; + + /* Set up the initial values of the debugging registers. */ + KernelStack[6] = Context->Dr0; + KernelStack[7] = Context->Dr1; + KernelStack[8] = Context->Dr2; + KernelStack[9] = Context->Dr3; + KernelStack[10] = Context->Dr6; + KernelStack[11] = Context->Dr7; + + /* Set up the initial floating point state. */ + memcpy((PVOID)&KernelStack[12], (PVOID)&Context->FloatSave, + sizeof(FLOATING_SAVE_AREA)); + + /* Set up a trap frame from the context. */ + TrapFrame = (PKTRAP_FRAME) + ((PVOID)KernelStack + 12 * sizeof(DWORD) + sizeof(FLOATING_SAVE_AREA)); + TrapFrame->DebugEbp = (PVOID)Context->Ebp; + TrapFrame->DebugEip = (PVOID)Context->Eip; + TrapFrame->DebugArgMark = 0; + TrapFrame->DebugPointer = 0; + TrapFrame->TempCs = 0; + TrapFrame->TempEip = 0; + TrapFrame->Gs = Context->SegGs; + TrapFrame->Es = Context->SegEs; + TrapFrame->Ds = Context->SegDs; + TrapFrame->Edx = Context->Edx; + TrapFrame->Ecx = Context->Ecx; + TrapFrame->Eax = Context->Eax; + TrapFrame->PreviousMode = UserMode; + TrapFrame->ExceptionList = (PVOID)0xFFFFFFFF; + TrapFrame->Fs = TEB_SELECTOR; + TrapFrame->Edi = Context->Edi; + TrapFrame->Esi = Context->Esi; + TrapFrame->Ebx = Context->Ebx; + TrapFrame->Ebp = Context->Ebp; + TrapFrame->ErrorCode = 0; + TrapFrame->Cs = Context->SegCs; + TrapFrame->Eip = Context->Eip; + TrapFrame->Eflags = Context->EFlags | FLAG_IF; + TrapFrame->Eflags &= ~(FLAG_VM | FLAG_NT | FLAG_IOPL); + TrapFrame->Esp = Context->Esp; + TrapFrame->Ss = Context->SegSs; + /* FIXME: Should check for a v86 mode context here. */ + + /* Save back the new value of the kernel stack. */ + Thread->KernelStack = (PVOID)KernelStack; + + return(STATUS_SUCCESS); +} + +NTSTATUS +Ke386InitThread(PKTHREAD Thread, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext) + /* + * Initialize a thread + */ +{ + PULONG KernelStack; + + /* + * Setup a stack frame for exit from the task switching routine + */ + + KernelStack = (PULONG)(Thread->KernelStack - (8*4)); + KernelStack[0] = 0; /* EDI */ + KernelStack[1] = 0; /* ESI */ + KernelStack[2] = 0; /* EBX */ + KernelStack[3] = 0; /* EBP */ + KernelStack[4] = (ULONG)PsBeginThread; /* EIP */ + KernelStack[5] = 0; /* Return EIP */ + KernelStack[6] = (ULONG)StartRoutine; /* First argument to PsBeginThread */ + KernelStack[7] = (ULONG)StartContext; /* Second argument to PsBeginThread */ + Thread->KernelStack = (VOID*)KernelStack; + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ke/i386/trap.s b/ntoskrnl/ke/i386/trap.s new file mode 100644 index 0000000..7a1acd2 --- /dev/null +++ b/ntoskrnl/ke/i386/trap.s @@ -0,0 +1,345 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/trap.s + * PURPOSE: Exception handlers + * PROGRAMMER: David Welch + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +/* + * Epilog for exception handlers + */ +_KiTrapEpilog: + cmpl $1, %eax /* Check for v86 recovery */ + jne _KiTrapRet + jmp _KiV86Complete +_KiTrapRet: + /* Skip debug information and unsaved registers */ + addl $0x30, %esp + popl %gs + popl %es + popl %ds + popl %edx + popl %ecx + popl %eax + + /* Restore the old previous mode */ + popl %ebx + movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) + + /* Restore the old exception handler list */ + popl %ebx + movl %ebx, %fs:KPCR_EXCEPTION_LIST + + popl %fs + popl %edi + popl %esi + popl %ebx + popl %ebp + addl $0x4, %esp /* Ignore error code */ + + iret + +.globl _KiTrapProlog +_KiTrapProlog: + pushl %edi + pushl %fs + + /* + * Check that the PCR exists, very early in the boot process it may + * not + */ + cmpl $0, %ss:_KiPcrInitDone + je .L5 + + /* Load the PCR selector into fs */ + movl $PCR_SELECTOR, %ebx + movl %ebx, %fs + + /* Save the old exception list */ + movl %fs:KPCR_EXCEPTION_LIST, %ebx + pushl %ebx + + /* Put the exception handler chain terminator */ + movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST + + /* Get a pointer to the current thread */ + movl %fs:KPCR_CURRENT_THREAD, %edi + + /* The current thread may be NULL early in the boot process */ + cmpl $0, %edi + je .L4 + + /* Save the old previous mode */ + movl $0, %ebx + movb %ss:KTHREAD_PREVIOUS_MODE(%edi), %bl + pushl %ebx + + /* Set the new previous mode based on the saved CS selector */ + movl 0x24(%esp), %ebx + cmpl $KERNEL_CS, %ebx + jne .L1 + movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%edi) + jmp .L3 +.L1: + movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%edi) +.L3: + + /* Save other registers */ + pushl %eax + pushl %ecx + pushl %edx + pushl %ds + pushl %es + pushl %gs + pushl $0 /* DR7 */ + pushl $0 /* DR6 */ + pushl $0 /* DR3 */ + pushl $0 /* DR2 */ + pushl $0 /* DR1 */ + pushl $0 /* DR0 */ + pushl $0 /* XXX: TempESP */ + pushl $0 /* XXX: TempCS */ + pushl $0 /* XXX: DebugPointer */ + pushl $0 /* XXX: DebugArgMark */ + movl 0x60(%esp), %ebx + pushl %ebx /* XXX: DebugEIP */ + pushl %ebp /* XXX: DebugEBP */ + + /* Load the segment registers */ + movl $KERNEL_DS, %ebx + movl %ebx, %ds + movl %ebx, %es + movl %ebx, %gs + + /* Set ES to kernel segment */ + movw $KERNEL_DS,%bx + movw %bx,%es + + movl %esp, %ebx + movl %esp, %ebp + + /* Save the old trap frame. */ + cmpl $0, %edi + je .L7 + movl %ss:KTHREAD_TRAP_FRAME(%edi), %edx + pushl %edx + jmp .L8 +.L7: + pushl $0 +.L8: + + /* Save a pointer to the trap frame in the current KTHREAD */ + cmpl $0, %edi + je .L6 + movl %ebx, %ss:KTHREAD_TRAP_FRAME(%edi) +.L6: + + /* Call the C exception handler */ + pushl %esi + pushl %ebx + call _KiTrapHandler + addl $4, %esp + addl $4, %esp + + /* Get a pointer to the current thread */ + movl %fs:0x124, %esi + + /* Restore the old trap frame pointer */ + popl %ebx + movl %ebx, KTHREAD_TRAP_FRAME(%esi) + + /* Return to the caller */ + jmp _KiTrapEpilog + + /* Handle the no-pcr case out of line */ +.L5: + pushl $0 + + /* Handle the no-thread case out of line */ +.L4: + pushl $0 + jmp .L3 + +.globl _KiTrap0 +_KiTrap0: + /* No error code */ + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $0, %esi + jmp _KiTrapProlog + +.globl _KiTrap1 +_KiTrap1: + /* No error code */ + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $1, %esi + jmp _KiTrapProlog + +.globl _KiTrap2 +_KiTrap2: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $2, %esi + jmp _KiTrapProlog + +.globl _KiTrap3 +_KiTrap3: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $3, %esi + jmp _KiTrapProlog + +.globl _KiTrap4 +_KiTrap4: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $4, %esi + jmp _KiTrapProlog + +.globl _KiTrap5 +_KiTrap5: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $5, %esi + jmp _KiTrapProlog + +.globl _KiTrap6 +_KiTrap6: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $6, %esi + jmp _KiTrapProlog + +.globl _KiTrap7 +_KiTrap7: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $7, %esi + jmp _KiTrapProlog + +.globl _KiTrap8 +_KiTrap8: + call _KiDoubleFaultHandler + iret + +.globl _KiTrap9 +_KiTrap9: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $9, %esi + jmp _KiTrapProlog + +.globl _KiTrap10 +_KiTrap10: + pushl %ebp + pushl %ebx + pushl %esi + movl $10, %esi + jmp _KiTrapProlog + +.globl _KiTrap11 +_KiTrap11: + pushl %ebp + pushl %ebx + pushl %esi + movl $11, %esi + jmp _KiTrapProlog + +.globl _KiTrap12 +_KiTrap12: + pushl %ebp + pushl %ebx + pushl %esi + movl $12, %esi + jmp _KiTrapProlog + +.globl _KiTrap13 +_KiTrap13: + pushl %ebp + pushl %ebx + pushl %esi + movl $13, %esi + jmp _KiTrapProlog + +.globl _KiTrap14 +_KiTrap14: + pushl %ebp + pushl %ebx + pushl %esi + movl $14, %esi + jmp _KiTrapProlog + +.globl _KiTrap15 +_KiTrap15: + pushl %ebp + pushl %ebx + pushl %esi + movl $15, %esi + jmp _KiTrapProlog + +.globl _KiTrap16 +_KiTrap16: + pushl %ebp + pushl %ebx + pushl %esi + movl $16, %esi + jmp _KiTrapProlog + +.globl _KiTrapUnknown +_KiTrapUnknown: + pushl $0 + pushl %ebp + pushl %ebx + pushl %esi + movl $255, %esi + jmp _KiTrapProlog + + +/* EOF */ diff --git a/ntoskrnl/ke/i386/tskswitch.S b/ntoskrnl/ke/i386/tskswitch.S new file mode 100644 index 0000000..7409948 --- /dev/null +++ b/ntoskrnl/ke/i386/tskswitch.S @@ -0,0 +1,155 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/ke/i386/tskswitch.S + * PURPOSE: Microkernel thread support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 09/10/00 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +/* FUNCTIONS ****************************************************************/ + +.globl _Ki386ContextSwitch +_Ki386ContextSwitch: +/* + * FUNCTIONS: Switches to another thread's context + * ARGUMENTS: + * Thread = Thread to switch to + * OldThread = Thread to switch from + */ + pushl %ebp + movl %esp, %ebp + + /* + * Save callee save registers. + */ + pushl %ebx + pushl %esi + pushl %edi + + /* + * This is a critical section for this processor. + */ + cli + + /* + * Get the pointer to the new thread. + */ + movl 8(%ebp), %ebx + + /* + * Set the base of the TEB selector to the base of the TEB for + * this thread. + */ + pushl %ebx + pushl KTHREAD_TEB(%ebx) + pushl $TEB_SELECTOR + call _KeSetBaseGdtSelector + addl $8, %esp + popl %ebx + + /* + * Load the PCR selector. + */ + movl $PCR_SELECTOR, %eax + movl %eax, %fs + + /* + * Set the current thread information in the PCR. + */ + movl %ebx, %fs:KPCR_CURRENT_THREAD + + /* + * FIXME: Save debugging state. + */ + + /* + * FIXME: Save floating point state. + */ + + /* + * Switch stacks + */ + movl 12(%ebp), %ebx + movl %esp, KTHREAD_KERNEL_STACK(%ebx) + movl 8(%ebp), %ebx + movl KTHREAD_KERNEL_STACK(%ebx), %esp + movl KTHREAD_STACK_LIMIT(%ebx), %edi + + /* + * Set the stack pointer in this processors TSS + */ + movl KTHREAD_INITIAL_STACK(%ebx), %eax + movl %fs:KPCR_TSS, %esi + movl %eax, KTSS_ESP0(%esi) + + /* + * Change the address space + */ + movl ETHREAD_THREADS_PROCESS(%ebx), %ebx + movl KPROCESS_DIRECTORY_TABLE_BASE(%ebx), %eax + movl %eax, %cr3 + + /* + * Set up the PDE for the top of the new stack. + */ + movl $0, %ebx +.L2: movl %edi, %esi + shr $22, %esi + movl 0xF03C0000(,%esi, 4), %eax + cmpl $0, %eax + jne .L1 + movl _MmGlobalKernelPageDirectory(,%esi, 4), %eax + movl %eax, 0xF03C0000(,%esi, 4) +.L1: + addl $4096, %edi + incl %ebx + cmp $(MM_STACK_SIZE / 4096), %ebx + jl .L2 + + /* + * FIXME: Restore floating point state + */ + + /* + * FIXME: Restore debugging state + */ + + /* + * Exit the critical section + */ + sti + + /* + * Restore the saved register and exit + */ + popl %edi + popl %esi + popl %ebx + + popl %ebp + ret diff --git a/ntoskrnl/ke/i386/tss.c b/ntoskrnl/ke/i386/tss.c new file mode 100644 index 0000000..46b75a2 --- /dev/null +++ b/ntoskrnl/ke/i386/tss.c @@ -0,0 +1,208 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/tss.c + * PURPOSE: TSS managment + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static KTSS* Ki386TssArray[MAXIMUM_PROCESSORS]; +PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; +static KTSS* Ki386TrapTssArray[MAXIMUM_PROCESSORS]; +static PVOID Ki386TrapStackArray[MAXIMUM_PROCESSORS]; + +KTSS KiBootTss; +static KTSS KiBootTrapTss; + +extern USHORT KiBootGdt[]; + +extern VOID KiTrap8(VOID); + +/* FUNCTIONS *****************************************************************/ + +VOID +Ki386ApplicationProcessorInitializeTSS(VOID) +{ + ULONG cr3; + KTSS* Tss; + KTSS* TrapTss; + PVOID TrapStack; + ULONG Id; + PUSHORT Gdt; + ULONG base, length; + + Id = KeGetCurrentProcessorNumber(); + Gdt = KeGetCurrentKPCR()->GDT; + + __asm__("movl %%cr3,%0\n\t" : "=d" (cr3)); + + Tss = ExAllocatePool(NonPagedPool, sizeof(KTSS)); + TrapTss = ExAllocatePool(NonPagedPool, sizeof(KTSS)); + TrapStack = ExAllocatePool(NonPagedPool, MM_STACK_SIZE); + + Ki386TssArray[Id] = Tss; + Ki386TrapTssArray[Id] = TrapTss; + Ki386TrapStackArray[Id] = TrapStack; + KeGetCurrentKPCR()->TSS = Tss; + + /* Initialize the boot TSS. */ + Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id]; + Tss->Ss0 = KERNEL_DS; + Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */ + Tss->IoBitmap[0] = 0xFF; + Tss->Ldt = LDT_SELECTOR; + + /* + * Initialize a descriptor for the TSS + */ + base = (ULONG)Tss; + length = sizeof(KTSS) - 1; + + Gdt[(TSS_SELECTOR / 2) + 0] = (length & 0xFFFF); + Gdt[(TSS_SELECTOR / 2) + 1] = (base & 0xFFFF); + Gdt[(TSS_SELECTOR / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900; + Gdt[(TSS_SELECTOR / 2) + 3] = ((length & 0xF0000) >> 16) | + ((base & 0xFF000000) >> 16); + + /* Initialize the TSS used for handling double faults. */ + TrapTss->Eflags = 0; + TrapTss->Esp0 = ((ULONG)TrapStack + MM_STACK_SIZE); + TrapTss->Ss0 = KERNEL_DS; + TrapTss->Esp = ((ULONG)TrapStack + MM_STACK_SIZE); + TrapTss->Cs = KERNEL_CS; + TrapTss->Eip = (ULONG)KiTrap8; + TrapTss->Ss = KERNEL_DS; + TrapTss->Ds = KERNEL_DS; + TrapTss->Es = KERNEL_DS; + TrapTss->Fs = PCR_SELECTOR; + TrapTss->IoMapBase = 0xFFFF; /* No i/o bitmap */ + TrapTss->IoBitmap[0] = 0xFF; + TrapTss->Ldt = LDT_SELECTOR; + TrapTss->Cr3 = cr3; + + /* + * Initialize a descriptor for the trap TSS. + */ + base = (ULONG)TrapTss; + length = sizeof(KTSS) - 1; + + Gdt[(TRAP_TSS_SELECTOR / 2) + 0] = (length & 0xFFFF); + Gdt[(TRAP_TSS_SELECTOR / 2) + 1] = (base & 0xFFFF); + Gdt[(TRAP_TSS_SELECTOR / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900; + Gdt[(TRAP_TSS_SELECTOR / 2) + 3] = ((length & 0xF0000) >> 16) | + ((base & 0xFF000000) >> 16); + + /* + * Load the task register + */ + __asm__("ltr %%ax" + : /* no output */ + : "a" (TSS_SELECTOR)); +} + +VOID +Ki386BootInitializeTSS(VOID) +{ + ULONG cr3; + extern unsigned int init_stack, init_stack_top; + extern unsigned int trap_stack, trap_stack_top; + unsigned int base, length; + + __asm__("movl %%cr3,%0\n\t" : "=d" (cr3)); + + Ki386TssArray[0] = &KiBootTss; + Ki386TrapTssArray[0] = &KiBootTrapTss; + Ki386TrapStackArray[0] = (PVOID)&trap_stack; + Ki386InitialStackArray[0] = (PVOID)&init_stack; + + /* Initialize the boot TSS. */ + KiBootTss.Esp0 = (ULONG)&init_stack_top; + KiBootTss.Ss0 = KERNEL_DS; + // KiBootTss.IoMapBase = FIELD_OFFSET(KTSS, IoBitmap); + KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */ + KiBootTss.IoBitmap[0] = 0xFF; + KiBootTss.Ldt = LDT_SELECTOR; + + /* + * Initialize a descriptor for the TSS + */ + base = (unsigned int)&KiBootTss; + length = sizeof(KiBootTss) - 1; + + KiBootGdt[(TSS_SELECTOR / 2) + 0] = (length & 0xFFFF); + KiBootGdt[(TSS_SELECTOR / 2) + 1] = (base & 0xFFFF); + KiBootGdt[(TSS_SELECTOR / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900; + KiBootGdt[(TSS_SELECTOR / 2) + 3] = ((length & 0xF0000) >> 16) | + ((base & 0xFF000000) >> 16); + + /* Initialize the TSS used for handling double faults. */ + KiBootTrapTss.Eflags = 0; + KiBootTrapTss.Esp0 = (ULONG)&trap_stack_top; + KiBootTrapTss.Ss0 = KERNEL_DS; + KiBootTrapTss.Esp = (ULONG)&trap_stack_top; + KiBootTrapTss.Cs = KERNEL_CS; + KiBootTrapTss.Eip = (ULONG)KiTrap8; + KiBootTrapTss.Ss = KERNEL_DS; + KiBootTrapTss.Ds = KERNEL_DS; + KiBootTrapTss.Es = KERNEL_DS; + KiBootTrapTss.Fs = PCR_SELECTOR; + KiBootTrapTss.IoMapBase = 0xFFFF; /* No i/o bitmap */ + KiBootTrapTss.IoBitmap[0] = 0xFF; + KiBootTrapTss.Ldt = LDT_SELECTOR; + KiBootTrapTss.Cr3 = cr3; + + /* + * Initialize a descriptor for the trap TSS. + */ + base = (unsigned int)&KiBootTrapTss; + length = sizeof(KiBootTrapTss) - 1; + + KiBootGdt[(TRAP_TSS_SELECTOR / 2) + 0] = (length & 0xFFFF); + KiBootGdt[(TRAP_TSS_SELECTOR / 2) + 1] = (base & 0xFFFF); + KiBootGdt[(TRAP_TSS_SELECTOR / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900; + KiBootGdt[(TRAP_TSS_SELECTOR / 2) + 3] = ((length & 0xF0000) >> 16) | + ((base & 0xFF000000) >> 16); + + /* + * Load the task register + */ + __asm__("ltr %%ax" + : /* no output */ + : "a" (TSS_SELECTOR)); +} + + + + + diff --git a/ntoskrnl/ke/i386/usercall.c b/ntoskrnl/ke/i386/usercall.c new file mode 100644 index 0000000..64e1472 --- /dev/null +++ b/ntoskrnl/ke/i386/usercall.c @@ -0,0 +1,101 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/usercall.c + * PURPOSE: 2E interrupt handler + * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + * UPDATE HISTORY: + * ??? + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include +#include + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +VOID KiSystemCallHook(ULONG Nr, ...) +{ +#if 0 + va_list ap; + ULONG i; + + va_start(ap, Nr); + + DbgPrint("%x/%d ", KeServiceDescriptorTable[0].SSDT[Nr].SysCallPtr, Nr); + DbgPrint("%x (", KeServiceDescriptorTable[0].SSPT[Nr].ParamBytes); + for (i = 0; i < KeServiceDescriptorTable[0].SSPT[Nr].ParamBytes / 4; i++) + { + DbgPrint("%x, ", va_arg(ap, ULONG)); + } + DbgPrint(")\n"); + assert_irql(PASSIVE_LEVEL); + va_end(ap); +#endif +} + +ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame) +{ + if (KeGetCurrentThread()->Alerted[1] != 0 && TrapFrame->Cs != KERNEL_CS) + { + KiDeliverNormalApc(); + } + if (KeGetCurrentThread()->Alerted[0] != 0 && TrapFrame->Cs != KERNEL_CS) + { + KiDeliverUserApc(TrapFrame); + } + return(NtStatus); +} + +// This function should be used by win32k.sys to add its own user32/gdi32 services +// TableIndex is 0 based +// ServiceCountTable its not used at the moment +BOOLEAN STDCALL +KeAddSystemServiceTable ( + PSSDT SSDT, + PULONG ServiceCounterTable, + ULONG NumberOfServices, + PSSPT SSPT, + ULONG TableIndex + ) +{ + if (TableIndex > SSDT_MAX_ENTRIES - 1) + return FALSE; + + /* check if descriptor table entry is free */ + if ((KeServiceDescriptorTable[TableIndex].SSDT != NULL) || + (KeServiceDescriptorTableShadow[TableIndex].SSDT != NULL)) + return FALSE; + + /* initialize the shadow service descriptor table */ + KeServiceDescriptorTableShadow[TableIndex].SSDT = SSDT; + KeServiceDescriptorTableShadow[TableIndex].SSPT = SSPT; + KeServiceDescriptorTableShadow[TableIndex].NumberOfServices = NumberOfServices; + KeServiceDescriptorTableShadow[TableIndex].ServiceCounterTable = ServiceCounterTable; + + /* initialize the service descriptor table (not for win32k services) */ + if (TableIndex != 1) + { + KeServiceDescriptorTable[TableIndex].SSDT = SSDT; + KeServiceDescriptorTable[TableIndex].SSPT = SSPT; + KeServiceDescriptorTable[TableIndex].NumberOfServices = NumberOfServices; + KeServiceDescriptorTable[TableIndex].ServiceCounterTable = ServiceCounterTable; + } + + return TRUE; +} + +/* EOF */ diff --git a/ntoskrnl/ke/i386/usertrap.c b/ntoskrnl/ke/i386/usertrap.c new file mode 100644 index 0000000..19a300b --- /dev/null +++ b/ntoskrnl/ke/i386/usertrap.c @@ -0,0 +1,149 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/usertrap.c + * PURPOSE: Handling usermode exceptions. + * PROGRAMMER: David Welch (welch@cwcom.net) + * REVISION HISTORY: + * 18/11/01: Split from ntoskrnl/ke/i386/exp.c + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +BOOLEAN +print_user_address(PVOID address) +{ + PLIST_ENTRY current_entry; + PLDR_MODULE current; + PEPROCESS CurrentProcess; + PPEB Peb = NULL; + ULONG_PTR RelativeAddress; + PPEB_LDR_DATA Ldr; + NTSTATUS Status; + + CurrentProcess = PsGetCurrentProcess(); + if (NULL != CurrentProcess) + { + Peb = CurrentProcess->Peb; + } + + if (NULL == Peb) + { + DbgPrint("<%x>", address); + return(TRUE); + } + + Status = MmSafeCopyFromUser(&Ldr, &Peb->Ldr, sizeof(PPEB_LDR_DATA)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("<%x>", address); + return(TRUE); + } + current_entry = Ldr->InLoadOrderModuleList.Flink; + + while (current_entry != &Ldr->InLoadOrderModuleList && + current_entry != NULL) + { + current = + CONTAINING_RECORD(current_entry, LDR_MODULE, InLoadOrderModuleList); + + if (address >= (PVOID)current->BaseAddress && + address < (PVOID)(current->BaseAddress + current->SizeOfImage)) + { + RelativeAddress = + (ULONG_PTR) address - (ULONG_PTR)current->BaseAddress; + DbgPrint("<%wZ: %x>", ¤t->BaseDllName, RelativeAddress); + return(TRUE); + } + + current_entry = current_entry->Flink; + } + return(FALSE); +} + +ULONG +KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2) +{ + EXCEPTION_RECORD Er; + + if (ExceptionNr == 0) + { + Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO; + } + else if (ExceptionNr == 1) + { + Er.ExceptionCode = STATUS_SINGLE_STEP; + } + else if (ExceptionNr == 3) + { + Er.ExceptionCode = STATUS_BREAKPOINT; + } + else if (ExceptionNr == 4) + { + Er.ExceptionCode = STATUS_INTEGER_OVERFLOW; + } + else if (ExceptionNr == 5) + { + Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED; + } + else if (ExceptionNr == 6) + { + Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; + } + else + { + Er.ExceptionCode = STATUS_ACCESS_VIOLATION; + } + Er.ExceptionFlags = 0; + Er.ExceptionRecord = NULL; + Er.ExceptionAddress = (PVOID)Tf->Eip; + if (ExceptionNr == 14) + { + Er.NumberParameters = 2; + Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1; + Er.ExceptionInformation[1] = (ULONG)Cr2; + } + else + { + Er.NumberParameters = 0; + } + + + KiDispatchException(&Er, 0, Tf, UserMode, TRUE); + return(0); +} diff --git a/ntoskrnl/ke/i386/v86m.c b/ntoskrnl/ke/i386/v86m.c new file mode 100644 index 0000000..42e8605 --- /dev/null +++ b/ntoskrnl/ke/i386/v86m.c @@ -0,0 +1,812 @@ +/* + * ReactOS kernel + * Copyright (C) 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/i386/v86m.c + * PURPOSE: Support for v86 mode + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define IOPL_FLAG ((1 << 12) | (1 << 13)) +#define INTERRUPT_FLAG (1 << 9) +#define TRAP_FLAG (1 << 8) +#define DIRECTION_FLAG (1 << 10) + +#define VALID_FLAGS (0xDFF) + +/* FUNCTIONS *****************************************************************/ + +ULONG +KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) +{ + PUCHAR ip; + PUSHORT sp; + PULONG dsp; + BOOL BigDataPrefix = FALSE; + BOOL BigAddressPrefix = FALSE; + BOOL RepPrefix = FALSE; + ULONG i = 0; + BOOL Exit = FALSE; + + ip = (PUCHAR)((Tf->Cs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF)); + sp = (PUSHORT)((Tf->Ss & 0xFFFF) * 16 + (Tf->Esp & 0xFFFF)); + dsp = (PULONG)sp; + + DPRINT("KeV86GPF handling %x at %x:%x ss:sp %x:%x Flags %x\n", + ip[0], Tf->Cs, Tf->Eip, Tf->Ss, Tf->Esp, VTf->regs->Flags); + + while (!Exit) + { + switch (ip[i]) + { + /* 32-bit data prefix */ + case 0x66: + BigDataPrefix = TRUE; + i++; + Tf->Eip++; + break; + + /* 32-bit address prefix */ + case 0x67: + BigAddressPrefix = TRUE; + i++; + Tf->Eip++; + break; + + /* rep prefix */ + case 0xFC: + RepPrefix = TRUE; + i++; + Tf->Eip++; + break; + + /* sti */ + case 0xFB: + if (BigDataPrefix || BigAddressPrefix || RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) + { + Tf->Eip++; + VTf->regs->Vif = 1; + return(0); + } + Exit = TRUE; + break; + + /* cli */ + case 0xFA: + if (BigDataPrefix || BigAddressPrefix || RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) + { + Tf->Eip++; + VTf->regs->Vif = 0; + return(0); + } + Exit = TRUE; + break; + + /* pushf */ + case 0x9C: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) + { + Tf->Eip++; + if (!BigAddressPrefix) + { + Tf->Esp = Tf->Esp - 2; + sp = sp - 1; + sp[0] = Tf->Eflags & 0xFFFF; + if (VTf->regs->Vif == 1) + { + sp[0] = sp[0] | INTERRUPT_FLAG; + } + else + { + sp[0] = sp[0] & (~INTERRUPT_FLAG); + } + } + else + { + Tf->Esp = Tf->Esp - 4; + dsp = dsp - 1; + dsp[0] = Tf->Eflags; + dsp[0] = dsp[0] & VALID_FLAGS; + if (VTf->regs->Vif == 1) + { + dsp[0] = dsp[0] | INTERRUPT_FLAG; + } + else + { + dsp[0] = dsp[0] & (~INTERRUPT_FLAG); + } + } + return(0); + } + Exit = TRUE; + break; + + /* popf */ + case 0x9D: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) + { + Tf->Eip++; + if (!BigAddressPrefix) + { + Tf->Eflags = Tf->Eflags & (~0xFFFF); + Tf->Eflags = Tf->Eflags | (sp[0] & VALID_FLAGS); + if (Tf->Eflags & INTERRUPT_FLAG) + { + VTf->regs->Vif = 1; + } + else + { + VTf->regs->Vif = 0; + } + Tf->Eflags = Tf->Eflags | INTERRUPT_FLAG; + Tf->Esp = Tf->Esp + 2; + } + else + { + Tf->Eflags = Tf->Eflags | (dsp[0] & VALID_FLAGS); + if (dsp[0] & INTERRUPT_FLAG) + { + VTf->regs->Vif = 1; + } + else + { + VTf->regs->Vif = 0; + } + Tf->Eflags = Tf->Eflags | INTERRUPT_FLAG; + Tf->Esp = Tf->Esp + 2; + } + return(0); + } + Exit = TRUE; + break; + + /* iret */ + case 0xCF: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) + { + Tf->Eip = sp[0]; + Tf->Cs = sp[1]; + Tf->Eflags = Tf->Eflags & (~0xFFFF); + Tf->Eflags = Tf->Eflags | sp[2]; + if (Tf->Eflags & INTERRUPT_FLAG) + { + VTf->regs->Vif = 1; + } + else + { + VTf->regs->Vif = 0; + } + Tf->Eflags = Tf->Eflags & (~INTERRUPT_FLAG); + Tf->Esp = Tf->Esp + 6; + return(0); + } + Exit = TRUE; + break; + + /* out imm8, al */ + case 0xE6: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[i + 1], + Tf->Eax & 0xFF); + Tf->Eip = Tf->Eip + 2; + return(0); + } + Exit = TRUE; + break; + + /* out imm8, ax */ + case 0xE7: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + if (!BigDataPrefix) + { + WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], Tf->Eax & 0xFFFF); + } + else + { + WRITE_PORT_ULONG((PULONG)(ULONG)ip[1], Tf->Eax); + } + Tf->Eip = Tf->Eip + 2; + return(0); + } + Exit = TRUE; + break; + + /* out dx, al */ + case 0xEE: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), Tf->Eax & 0xFF); + Tf->Eip = Tf->Eip + 1; + return(0); + } + Exit = TRUE; + break; + + /* out dx, ax */ + case 0xEF: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + if (!BigDataPrefix) + { + WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF), + Tf->Eax & 0xFFFF); + } + else + { + WRITE_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF), + Tf->Eax); + } + Tf->Eip = Tf->Eip + 1; + return(0); + } + Exit = TRUE; + break; + + /* in al, imm8 */ + case 0xE4: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + UCHAR v; + + v = READ_PORT_UCHAR((PUCHAR)(ULONG)ip[1]); + Tf->Eax = Tf->Eax & (~0xFF); + Tf->Eax = Tf->Eax | v; + Tf->Eip = Tf->Eip + 2; + return(0); + } + Exit = TRUE; + break; + + /* in ax, imm8 */ + case 0xE5: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + USHORT v; + + v = READ_PORT_USHORT((PUSHORT)(ULONG)ip[1]); + Tf->Eax = Tf->Eax & (~0xFFFF); + Tf->Eax = Tf->Eax | v; + Tf->Eip = Tf->Eip + 2; + return(0); + } + Exit = TRUE; + break; + + /* in al, dx */ + case 0xEC: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + UCHAR v; + + v = READ_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF)); + Tf->Eax = Tf->Eax & (~0xFF); + Tf->Eax = Tf->Eax | v; + Tf->Eip = Tf->Eip + 1; + return(0); + } + Exit = TRUE; + break; + + /* in ax, dx */ + case 0xED: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + USHORT v; + + v = READ_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF)); + Tf->Eax = Tf->Eax & (~0xFFFF); + Tf->Eax = Tf->Eax | v; + Tf->Eip = Tf->Eip + 1; + return(0); + } + Exit = TRUE; + break; + + /* outsb */ + case 0x6E: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUCHAR Buffer; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + Buffer = (PUCHAR)((Tf->Es * 16) + Offset); + for (; Count > 0; Count--) + { + WRITE_PORT_UCHAR(Port, *Buffer); + if (Tf->Eflags & DIRECTION_FLAG) + { + Buffer++; + } + else + { + Buffer--; + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; + + /* insw/insd */ + case 0x6F: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUSHORT BufferS = NULL; + PULONG BufferL = NULL; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + if (BigDataPrefix) + { + BufferL = (PULONG)((Tf->Es * 16) + Offset); + } + else + { + BufferS = (PUSHORT)((Tf->Es * 16) + Offset); + } + for (; Count > 0; Count--) + { + if (BigDataPrefix) + { + WRITE_PORT_ULONG((PULONG)Port, *BufferL); + } + else + { + WRITE_PORT_USHORT((PUSHORT)Port, *BufferS); + } + if (Tf->Eflags & DIRECTION_FLAG) + { + if (BigDataPrefix) + { + BufferL++; + } + else + { + BufferS++; + } + } + else + { + if (BigDataPrefix) + { + BufferL--; + } + else + { + BufferS--; + } + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; + + /* insb */ + case 0x6C: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUCHAR Buffer; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + Buffer = (PUCHAR)((Tf->Es * 16) + Offset); + for (; Count > 0; Count--) + { + *Buffer = READ_PORT_UCHAR(Port); + if (Tf->Eflags & DIRECTION_FLAG) + { + Buffer++; + } + else + { + Buffer--; + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; + + /* insw/insd */ + case 0x6D: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUSHORT BufferS = NULL; + PULONG BufferL = NULL; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + if (BigDataPrefix) + { + BufferL = (PULONG)((Tf->Es * 16) + Offset); + } + else + { + BufferS = (PUSHORT)((Tf->Es * 16) + Offset); + } + for (; Count > 0; Count--) + { + if (BigDataPrefix) + { + *BufferL = READ_PORT_ULONG((PULONG)Port); + } + else + { + *BufferS = READ_PORT_USHORT((PUSHORT)Port); + } + if (Tf->Eflags & DIRECTION_FLAG) + { + if (BigDataPrefix) + { + BufferL++; + } + else + { + BufferS++; + } + } + else + { + if (BigDataPrefix) + { + BufferL--; + } + else + { + BufferS--; + } + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; + + /* Int nn */ + case 0xCD: + { + unsigned int inum; + unsigned int entry; + + inum = ip[1]; + entry = ((unsigned int *)0)[inum]; + + Tf->Esp = Tf->Esp - 6; + sp = sp - 3; + + sp[0] = (Tf->Eip & 0xFFFF) + 2; + sp[1] = Tf->Cs & 0xFFFF; + sp[2] = Tf->Eflags & 0xFFFF; + if (VTf->regs->Vif == 1) + { + sp[2] = sp[2] | INTERRUPT_FLAG; + } + DPRINT("sp[0] %x sp[1] %x sp[2] %x\n", sp[0], sp[1], sp[2]); + Tf->Eip = entry & 0xFFFF; + Tf->Cs = entry >> 16; + Tf->Eflags = Tf->Eflags & (~TRAP_FLAG); + + return(0); + } + } + + /* FIXME: Also emulate ins and outs */ + /* FIXME: Handle opcode prefixes */ + /* FIXME: Don't allow the BIOS to write to sensitive I/O ports */ + } + + DPRINT1("V86GPF unhandled (was %x)\n", ip[i]); + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); +} + +ULONG +KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address) +{ + PUCHAR Ip; + PKV86M_TRAP_FRAME VTf; + + VTf = (PKV86M_TRAP_FRAME)Tf; + + /* + * Check if we have reached the recovery instruction + */ + Ip = (PUCHAR)((Tf->Cs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF)); + if (ExceptionNr != 14) + { + DPRINT("ExceptionNr %d Ip[0] %x Ip[1] %x Ip[2] %x Ip[3] %x Tf->Cs %x " + "Tf->Eip %x\n", ExceptionNr, Ip[0], Ip[1], Ip[2], Ip[3], Tf->Cs, + Tf->Eip); + DPRINT("VTf %x VTf->regs %x\n", VTf, VTf->regs); + } + if (ExceptionNr == 6 && + memcmp(Ip, VTf->regs->RecoveryInstruction, 4) == 0 && + (Tf->Cs * 16 + Tf->Eip) == VTf->regs->RecoveryAddress) + { + *VTf->regs->PStatus = STATUS_SUCCESS; + return(1); + } + + /* + * Handle the exceptions + */ + switch (ExceptionNr) + { + /* Divide error */ + case 0: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Single step */ + case 1: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* NMI */ + case 2: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Breakpoint */ + case 3: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Overflow */ + case 4: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Array bounds check */ + case 5: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Invalid opcode */ + case 6: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Device not available */ + case 7: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Double fault */ + case 8: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Intel reserved */ + case 9: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Invalid TSS */ + case 10: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Segment not present */ + case 11: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;; + return(1); + + /* Stack fault */ + case 12: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* General protection fault */ + case 13: + return(KeV86GPF(VTf, Tf)); + + /* Page fault */ + case 14: + { + NTSTATUS Status; + + Status = MmPageFault(USER_CS, + &Tf->Eip, + NULL, + address, + Tf->ErrorCode); + if (!NT_SUCCESS(Status)) + { + DPRINT("V86Exception, halting due to page fault\n"); + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } + return(0); + } + + /* Intel reserved */ + case 15: + case 16: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + /* Alignment check */ + case 17: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + + default: + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } +} + + + diff --git a/ntoskrnl/ke/i386/v86m_sup.S b/ntoskrnl/ke/i386/v86m_sup.S new file mode 100644 index 0000000..0ee3663 --- /dev/null +++ b/ntoskrnl/ke/i386/v86m_sup.S @@ -0,0 +1,213 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/ke/i386/vm86_sup.S + * PURPOSE: V86 mode support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 09/10/00 + */ + +#include +#include +#include +#include + +.globl _Ki386RetToV86Mode +.globl _KiV86Complete + + /* + * VOID Ki386RetToV86Mode(KV86M_REGISTERS* InRegs, + * KV86M_REGISTERS* OutRegs); + * + * Starts in v86 mode with the registers set to the + * specified values. + */ +_Ki386RetToV86Mode: + /* + * Setup a stack frame + */ + pushl %ebp + movl %esp, %ebp + + /* + * Save registers + */ + pusha + + /* + * Get a pointer to IN_REGS + */ + movl 8(%ebp), %ebx + + /* + * Save ebp + */ + pushl %ebp + + /* + * Save a pointer to IN_REGS which the v86m exception handler will + * use to handle exceptions + */ + pushl %ebx + + /* + * Since we are going to fiddle with the stack pointer this must be + * a critical section for this processor + */ + + /* + * Save the old initial stack + */ + movl %fs:KPCR_CURRENT_THREAD, %esi + movl KTHREAD_INITIAL_STACK(%esi), %edi + pushl %edi + + /* + * We also need to set the stack in the kthread structure + */ + movl %esp, KTHREAD_INITIAL_STACK(%esi) + + /* + * The stack used for handling exceptions from v86 mode in this thread + * will be the current stack adjusted so we don't overwrite the + * existing stack frames + */ + movl %fs:KPCR_TSS, %esi + movl %esp, KTSS_ESP0(%esi) + + /* + * Create the stack frame for an iret to v86 mode + */ + pushl KV86M_REGISTERS_GS(%ebx) + pushl KV86M_REGISTERS_FS(%ebx) + pushl KV86M_REGISTERS_DS(%ebx) + pushl KV86M_REGISTERS_ES(%ebx) + pushl KV86M_REGISTERS_SS(%ebx) + pushl KV86M_REGISTERS_ESP(%ebx) + pushl KV86M_REGISTERS_EFLAGS(%ebx) + pushl KV86M_REGISTERS_CS(%ebx) + pushl KV86M_REGISTERS_EIP(%ebx) + + /* + * Setup the CPU registers + */ + movl KV86M_REGISTERS_EAX(%ebx), %eax + movl KV86M_REGISTERS_ECX(%ebx), %ecx + movl KV86M_REGISTERS_EDX(%ebx), %edx + movl KV86M_REGISTERS_ESI(%ebx), %esi + movl KV86M_REGISTERS_EDI(%ebx), %edi + movl KV86M_REGISTERS_EBP(%ebx), %ebp + movl KV86M_REGISTERS_EBX(%ebx), %ebx + + /* + * Go to v86 mode + */ + iret + + /* + * Handle the completion of a vm86 routine. We are called from + * an exception handler with the registers at the point of the + * exception on the stack. + */ +_KiV86Complete: + /* Restore the original ebp */ + movl TF_ORIG_EBP(%esp), %ebp + + /* Get a pointer to the OUT_REGS structure */ + movl 12(%ebp), %ebx + + /* Skip debug information and unsaved registers */ + addl $0x30, %esp + + /* Ignore 32-bit segment registers */ + addl $12, %esp + + /* Save the vm86 registers into the OUT_REGS structure */ + popl KV86M_REGISTERS_EDX(%ebx) + popl KV86M_REGISTERS_ECX(%ebx) + popl KV86M_REGISTERS_EAX(%ebx) + + /* Ignore the previous mode */ + addl $4, %esp + + /* Ignore old exception handler list */ + addl $4, %esp + + /* Ignore the 32-bit fs register */ + addl $4, %esp + + popl KV86M_REGISTERS_EDI(%ebx) + popl KV86M_REGISTERS_ESI(%ebx) + popl KV86M_REGISTERS_EBX(%ebx) + popl KV86M_REGISTERS_EBP(%ebx) + + /* Ignore error code */ + addl $4, %esp + + popl KV86M_REGISTERS_EIP(%ebx) + popl KV86M_REGISTERS_CS(%ebx) + popl KV86M_REGISTERS_EFLAGS(%ebx) + popl KV86M_REGISTERS_ESP(%ebx) + popl KV86M_REGISTERS_SS(%ebx) + popl KV86M_REGISTERS_ES(%ebx) + popl KV86M_REGISTERS_DS(%ebx) + popl KV86M_REGISTERS_FS(%ebx) + popl KV86M_REGISTERS_GS(%ebx) + + /* + * We are going to fiddle with the stack so this must be a critical + * section for this process + */ + cli + + /* + * Restore the initial stack + */ + popl %eax + movl %fs:KPCR_TSS, %esi + movl %eax, KTSS_ESP0(%esi) + + /* + * We also need to set the stack in the kthread structure + */ + movl %fs:KPCR_CURRENT_THREAD, %esi + movl KTHREAD_INITIAL_STACK(%esi), %edi + movl %eax, KTHREAD_INITIAL_STACK(%esi) + + /* Exit the critical section */ + sti + + /* Ignore IN_REGS pointer */ + addl $4, %esp + + /* Ignore ebp restored above */ + addl $4, %esp + + /* Return to caller */ + popa + movl %ebp, %esp + popl %ebp + ret + + + + + + diff --git a/ntoskrnl/ke/kqueue.c b/ntoskrnl/ke/kqueue.c new file mode 100644 index 0000000..6c8d685 --- /dev/null +++ b/ntoskrnl/ke/kqueue.c @@ -0,0 +1,198 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: ReactOS kernel + * FILE: ntoskrnl/ke/kqueue.c + * PURPOSE: Implement device queues + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 08/07/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID +InsertBeforeEntryInList(PLIST_ENTRY Head, PLIST_ENTRY After, PLIST_ENTRY Entry) +{ + InsertHeadList(After, Entry); +} + +BOOLEAN STDCALL +KeInsertByKeyDeviceQueue (PKDEVICE_QUEUE DeviceQueue, + PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, + ULONG SortKey) +{ + KIRQL oldlvl; + PLIST_ENTRY current; + PKDEVICE_QUEUE_ENTRY entry; + + DPRINT("KeInsertByKeyDeviceQueue()\n"); + + DeviceQueueEntry->Key=SortKey; + + KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl); + + if (!DeviceQueue->Busy) + { + DeviceQueue->Busy=TRUE; + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(FALSE); + } + + current=DeviceQueue->ListHead.Flink; + while (current!=(&DeviceQueue->ListHead)) + { + entry = CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,Entry); + if (entry->Key < SortKey) + { + InsertBeforeEntryInList(&DeviceQueue->ListHead, + &DeviceQueueEntry->Entry, + current); + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(TRUE); + } + current = current->Flink; + } + InsertTailList(&DeviceQueue->ListHead,&DeviceQueueEntry->Entry); + + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(TRUE); +} + +PKDEVICE_QUEUE_ENTRY +STDCALL +KeRemoveByKeyDeviceQueue ( + PKDEVICE_QUEUE DeviceQueue, + ULONG SortKey + ) +{ + KIRQL oldlvl; + PLIST_ENTRY current; + PKDEVICE_QUEUE_ENTRY entry; + + assert_irql(DISPATCH_LEVEL); + assert(DeviceQueue!=NULL); + assert(DeviceQueue->Busy); + + KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl); + + current = DeviceQueue->ListHead.Flink; + while (current != &DeviceQueue->ListHead) + { + entry = CONTAINING_RECORD(current,KDEVICE_QUEUE_ENTRY,Entry); + if (entry->Key < SortKey || + current->Flink == &DeviceQueue->ListHead) + { + RemoveEntryList(current); + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(entry); + } + current = current->Flink; + } + DeviceQueue->Busy = FALSE; + KeReleaseSpinLock(&DeviceQueue->Lock, oldlvl); + return(NULL); +} + +PKDEVICE_QUEUE_ENTRY +STDCALL +KeRemoveDeviceQueue ( + PKDEVICE_QUEUE DeviceQueue + ) +/* + * FUNCTION: Removes an entry from a device queue + * ARGUMENTS: + * DeviceQueue = Queue to remove the entry + * RETURNS: The removed entry + */ +{ + KIRQL oldlvl; + PLIST_ENTRY list_entry; + PKDEVICE_QUEUE_ENTRY entry; + + DPRINT("KeRemoveDeviceQueue(DeviceQueue %x)\n",DeviceQueue); + + assert_irql(DISPATCH_LEVEL); + assert(DeviceQueue!=NULL); + assert(DeviceQueue->Busy); + + KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl); + + list_entry = RemoveHeadList(&DeviceQueue->ListHead); + if (list_entry==(&DeviceQueue->ListHead)) + { + DeviceQueue->Busy=FALSE; + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(NULL); + } + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + + entry = CONTAINING_RECORD(list_entry,KDEVICE_QUEUE_ENTRY,Entry); + return(entry); +} + +VOID +STDCALL +KeInitializeDeviceQueue ( + PKDEVICE_QUEUE DeviceQueue + ) +/* + * FUNCTION: Intializes a device queue + * ARGUMENTS: + * DeviceQueue = Device queue to initialize + */ +{ + assert(DeviceQueue!=NULL); + InitializeListHead(&DeviceQueue->ListHead); + DeviceQueue->Busy=FALSE; + KeInitializeSpinLock(&DeviceQueue->Lock); +} + +BOOLEAN +STDCALL +KeInsertDeviceQueue ( + PKDEVICE_QUEUE DeviceQueue, + PKDEVICE_QUEUE_ENTRY DeviceQueueEntry + ) +/* + * FUNCTION: Inserts an entry in a device queue + * ARGUMENTS: + * DeviceQueue = Queue to insert the entry in + * DeviceQueueEntry = Entry to insert + * RETURNS: False is the device queue wasn't busy + * True otherwise + */ +{ + KIRQL oldlvl; + + KeAcquireSpinLock(&DeviceQueue->Lock,&oldlvl); + + if (!DeviceQueue->Busy) + { + DeviceQueue->Busy=TRUE; + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(FALSE); + } + + InsertTailList(&DeviceQueue->ListHead, + &DeviceQueueEntry->Entry); + DeviceQueueEntry->Key=0; + + KeReleaseSpinLock(&DeviceQueue->Lock,oldlvl); + return(TRUE); +} + + +BOOLEAN STDCALL +KeRemoveEntryDeviceQueue(PKDEVICE_QUEUE DeviceQueue, + PKDEVICE_QUEUE_ENTRY DeviceQueueEntry) +{ + UNIMPLEMENTED; + return(FALSE); +} diff --git a/ntoskrnl/ke/kthread.c b/ntoskrnl/ke/kthread.c new file mode 100644 index 0000000..d0b1ddc --- /dev/null +++ b/ntoskrnl/ke/kthread.c @@ -0,0 +1,238 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * FILE: ntoskrnl/ke/kthread.c + * PURPOSE: Microkernel thread support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID +KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty) +{ + assert(SwapEntry == 0); + if (PhysAddr.QuadPart != 0) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr); + } +} + +NTSTATUS +KeReleaseThread(PETHREAD Thread) +/* + * FUNCTION: Releases the resource allocated for a thread by + * KeInitializeThread + * NOTE: The thread had better not be running when this is called + */ +{ + extern unsigned int init_stack; + + if (Thread->Tcb.StackLimit != (ULONG)&init_stack) + { + MmLockAddressSpace(MmGetKernelAddressSpace()); + MmFreeMemoryArea(MmGetKernelAddressSpace(), + (PVOID)Thread->Tcb.StackLimit, + MM_STACK_SIZE, + KeFreeStackPage, + NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + } + Thread->Tcb.StackLimit = 0; + Thread->Tcb.InitialStack = NULL; + Thread->Tcb.StackBase = NULL; + Thread->Tcb.KernelStack = NULL; + return(STATUS_SUCCESS); +} + +VOID +KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) +/* + * FUNCTION: Initialize the microkernel state of the thread + */ +{ + PVOID KernelStack; + NTSTATUS Status; + extern unsigned int init_stack_top; + extern unsigned int init_stack; + PMEMORY_AREA StackArea; + ULONG i; + + KeInitializeDispatcherHeader(&Thread->DispatcherHeader, + InternalThreadType, + sizeof(ETHREAD), + FALSE); + InitializeListHead(&Thread->MutantListHead); + if (!First) + { + KernelStack = NULL; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_KERNEL_STACK, + &KernelStack, + MM_STACK_SIZE, + 0, + &StackArea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create thread stack\n"); + KeBugCheck(0); + } + for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) + { + PHYSICAL_ADDRESS Page; + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + Status = MmCreateVirtualMapping(NULL, + KernelStack + (i * PAGE_SIZE), + PAGE_EXECUTE_READWRITE, + Page, + TRUE); + } + Thread->InitialStack = KernelStack + MM_STACK_SIZE; + Thread->StackBase = KernelStack + MM_STACK_SIZE; + Thread->StackLimit = (ULONG)KernelStack; + Thread->KernelStack = KernelStack + MM_STACK_SIZE; + } + else + { + Thread->InitialStack = (PVOID)&init_stack_top; + Thread->StackBase = (PVOID)&init_stack_top; + Thread->StackLimit = (ULONG)&init_stack; + Thread->KernelStack = (PVOID)&init_stack_top; + } + + /* + * The Native API function will initialize the TEB field later + */ + Thread->Teb = NULL; + Thread->TlsArray = NULL; + Thread->DebugActive = 0; + Thread->State = THREAD_STATE_INITIALIZED; + Thread->Alerted[0] = 0; + Thread->Alerted[1] = 0; + Thread->Iopl = 0; + /* + * FIXME: Think how this might work + */ + Thread->NpxState = 0; + + Thread->Saturation = 0; + Thread->Priority = 0; + InitializeListHead(&Thread->ApcState.ApcListHead[0]); + InitializeListHead(&Thread->ApcState.ApcListHead[1]); + Thread->ApcState.Process = Process; + Thread->ApcState.KernelApcInProgress = 0; + Thread->ApcState.KernelApcPending = 0; + Thread->ApcState.UserApcPending = 0; + Thread->ContextSwitches = 0; + Thread->WaitStatus = STATUS_SUCCESS; + Thread->WaitIrql = 0; + Thread->WaitMode = 0; + Thread->WaitNext = 0; + Thread->WaitBlockList = NULL; + Thread->WaitListEntry.Flink = NULL; + Thread->WaitListEntry.Blink = NULL; + Thread->WaitTime = 0; + Thread->BasePriority = 0; + Thread->DecrementCount = 0; + Thread->PriorityDecrement = 0; + Thread->Quantum = 0; + memset(Thread->WaitBlock, 0, sizeof(KWAIT_BLOCK)*4); + Thread->LegoData = 0; + /* + * FIXME: Why this? + */ + Thread->KernelApcDisable = 1; + Thread->UserAffinity = Process->Affinity; + Thread->SystemAffinityActive = 0; + Thread->Queue = NULL; + KeInitializeSpinLock(&Thread->ApcQueueLock); + memset(&Thread->Timer, 0, sizeof(KTIMER)); + Thread->QueueListEntry.Flink = NULL; + Thread->QueueListEntry.Blink = NULL; + Thread->Affinity = Process->Affinity; + Thread->Preempted = 0; + Thread->ProcessReadyQueue = 0; + Thread->KernelStackResident = 1; + Thread->NextProcessor = 0; + Thread->CallbackStack = NULL; + Thread->Win32Thread = 0; + Thread->TrapFrame = NULL; + Thread->ApcStatePointer[0] = NULL; + Thread->ApcStatePointer[1] = NULL; + Thread->EnableStackSwap = 0; + Thread->LargeStack = 0; + Thread->ResourceIndex = 0; + Thread->PreviousMode = KernelMode; + Thread->KernelTime = 0; + Thread->UserTime = 0; + memset(&Thread->SavedApcState, 0, sizeof(KAPC_STATE)); + Thread->Alertable = 1; + Thread->ApcStateIndex = 0; + Thread->ApcQueueable = 0; + Thread->AutoAlignment = 0; + KeInitializeApc(&Thread->SuspendApc, + Thread, + 0, + PiSuspendThreadKernelRoutine, + PiSuspendThreadRundownRoutine, + PiSuspendThreadNormalRoutine, + KernelMode, + NULL); + KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128); + Thread->ThreadListEntry.Flink = NULL; + Thread->ThreadListEntry.Blink = NULL; + Thread->FreezeCount = 0; + Thread->SuspendCount = 0; + + /* + * Initialize ReactOS specific members + */ + Thread->ProcessThreadListEntry.Flink = NULL; + Thread->ProcessThreadListEntry.Blink = NULL; + + /* + * Do x86 specific part + */ +} + diff --git a/ntoskrnl/ke/main.c b/ntoskrnl/ke/main.c new file mode 100644 index 0000000..894f925 --- /dev/null +++ b/ntoskrnl/ke/main.c @@ -0,0 +1,764 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/main.c + * PURPOSE: Initalizes the kernel + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 28/05/98: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../dbg/kdb.h" +#include +#include + +#ifdef HALDBG +#include +#else +#define ps(args...) +#endif + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD; +ULONG EXPORTED NtGlobalFlag = 0; +CHAR EXPORTED KeNumberProcessors; +LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock; +ULONG EXPORTED KeDcacheFlushCount = 0; +ULONG EXPORTED KeIcacheFlushCount = 0; +static LOADER_MODULE KeLoaderModules[64]; +static UCHAR KeLoaderModuleStrings[64][256]; +static UCHAR KeLoaderCommandLine[256]; +static ADDRESS_RANGE KeMemoryMap[64]; +static ULONG KeMemoryMapRangeCount; +static ULONG FirstKrnlPhysAddr; +static ULONG LastKrnlPhysAddr; +static ULONG LastKernelAddress; +volatile BOOLEAN Initialized = FALSE; + +extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; + + +/* FUNCTIONS ****************************************************************/ + +static BOOLEAN +RtlpCheckFileNameExtension(PCHAR FileName, + PCHAR Extension) +{ + PCHAR Ext; + + Ext = strrchr(FileName, '.'); + if ((Extension == NULL) || (*Extension == 0)) + { + if (Ext == NULL) + return TRUE; + else + return FALSE; + } + if (*Extension != '.') + Ext++; + + if (_stricmp(Ext, Extension) == 0) + return TRUE; + else + return FALSE; +} + + +static VOID +InitSystemSharedUserPage (PCSZ ParameterLine) +{ + UNICODE_STRING ArcDeviceName; + UNICODE_STRING ArcName; + UNICODE_STRING BootPath; + UNICODE_STRING DriveDeviceName; + UNICODE_STRING DriveName; + WCHAR DriveNameBuffer[20]; + PCHAR ParamBuffer; + PWCHAR ArcNameBuffer; + PCHAR p; + NTSTATUS Status; + ULONG Length; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE Handle; + ULONG i; + BOOLEAN BootDriveFound; + + /* + * NOTE: + * The shared user page has been zeroed-out right after creation. + * There is NO need to do this again. + */ + + SharedUserData->NtProductType = NtProductWinNt; + + BootDriveFound = FALSE; + + /* + * Retrieve the current dos system path + * (e.g.: C:\reactos) from the given arc path + * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos) + * Format: "\ [options...]" + */ + + /* create local parameter line copy */ + ParamBuffer = ExAllocatePool (PagedPool, 256); + strcpy (ParamBuffer, (char *)ParameterLine); + DPRINT("%s\n", ParamBuffer); + + /* cut options off */ + p = strchr (ParamBuffer, ' '); + if (p) + { + *p = 0; + } + DPRINT("%s\n", ParamBuffer); + + /* extract path */ + p = strchr (ParamBuffer, '\\'); + if (p) + { + DPRINT("Boot path: %s\n", p); + RtlCreateUnicodeStringFromAsciiz (&BootPath, p); + *p = 0; + } + else + { + DPRINT("Boot path: %s\n", "\\"); + RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\"); + } + DPRINT("Arc name: %s\n", ParamBuffer); + + /* Only arc name left - build full arc name */ + ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR)); + swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer); + RtlInitUnicodeString (&ArcName, ArcNameBuffer); + DPRINT("Arc name: %wZ\n", &ArcName); + + /* free ParamBuffer */ + ExFreePool (ParamBuffer); + + /* allocate arc device name string */ + ArcDeviceName.Length = 0; + ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR); + ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR)); + + InitializeObjectAttributes (&ObjectAttributes, + &ArcName, + OBJ_OPENLINK, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject (&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + RtlFreeUnicodeString (&ArcName); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString (&BootPath); + RtlFreeUnicodeString (&ArcDeviceName); + CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", + Status); + + KeBugCheck (0x0); + } + + Status = NtQuerySymbolicLinkObject (Handle, + &ArcDeviceName, + &Length); + NtClose (Handle); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString (&BootPath); + RtlFreeUnicodeString (&ArcDeviceName); + CPRINT("NtQuerySymbolicObject() failed (Status %x)\n", + Status); + + KeBugCheck (0x0); + } + DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName); + + + /* allocate device name string */ + DriveDeviceName.Length = 0; + DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR); + DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR)); + + for (i = 0; i < 26; i++) + { + swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i); + RtlInitUnicodeString (&DriveName, + DriveNameBuffer); + + InitializeObjectAttributes (&ObjectAttributes, + &DriveName, + OBJ_OPENLINK, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject (&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to open link %wZ\n", + &DriveName); + continue; + } + + Status = NtQuerySymbolicLinkObject (Handle, + &DriveDeviceName, + &Length); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed query open link %wZ\n", + &DriveName); + continue; + } + DPRINT("Opened link: %wZ ==> %wZ\n", + &DriveName, &DriveDeviceName); + + if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) + { + DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath); + swprintf(SharedUserData->NtSystemRoot, + L"%C:%wZ", 'A' + i, &BootPath); + + BootDriveFound = TRUE; + } + + NtClose (Handle); + } + + RtlFreeUnicodeString (&BootPath); + RtlFreeUnicodeString (&DriveDeviceName); + RtlFreeUnicodeString (&ArcDeviceName); + + DPRINT("DosDeviceMap: 0x%x\n", SharedUserData->DosDeviceMap); + + if (BootDriveFound == FALSE) + { + DbgPrint("No system drive found!\n"); + KeBugCheck (0x0); + } +} + +VOID +ExpInitializeExecutive(VOID) +{ + ULONG BootDriverCount; + ULONG i; + ULONG start; + ULONG length; + PCHAR name; + CHAR str[50]; + NTSTATUS Status; + + /* + * Fail at runtime if someone has changed various structures without + * updating the offsets used for the assembler code. + */ + assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK); + assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB); + assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK); + assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE); + assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME); + assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK); + assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS); + assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == + KPROCESS_DIRECTORY_TABLE_BASE); + assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9); + assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS); + assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP); + + assert(FIELD_OFFSET(KPCR, ExceptionList) == KPCR_EXCEPTION_LIST); + assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF); + assert(FIELD_OFFSET(KPCR, CurrentThread) == KPCR_CURRENT_THREAD); + + LdrInit1(); + + KeLowerIrql(DISPATCH_LEVEL); + + NtEarlyInitVdm(); + + MmInit1(FirstKrnlPhysAddr, + LastKrnlPhysAddr, + LastKernelAddress, + (PADDRESS_RANGE)&KeMemoryMap, + KeMemoryMapRangeCount); + + /* create default nls tables */ + RtlpInitNlsTables(); + + /* + * Initialize the kernel debugger + */ + KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); + + MmInit2(); + KeInit2(); + + KeLowerIrql(PASSIVE_LEVEL); + + if (!SeInit1()) + KeBugCheck(SECURITY_INITIALIZATION_FAILED); + + ObInit(); + + if (!SeInit2()) + KeBugCheck(SECURITY1_INITIALIZATION_FAILED); + + PiInitProcessManager(); + + KdInit1(); + + if (KdPollBreakIn ()) + { + DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C); + } + + /* + * Display version number and copyright/warranty message + */ + HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build " + KERNEL_VERSION_BUILD_STR")\n"); + HalDisplayString(RES_STR_LEGAL_COPYRIGHT); + HalDisplayString("\n\nReactOS is free software, covered by the GNU General " + "Public License, and you\n"); + HalDisplayString("are welcome to change it and/or distribute copies of it " + "under certain\n"); + HalDisplayString("conditions. There is absolutely no warranty for " + "ReactOS.\n\n"); + + /* Initialize all processors */ + KeNumberProcessors = 0; + + while (!HalAllProcessorsStarted()) + { + PVOID ProcessorStack; + + if (KeNumberProcessors != 0) + { + KePrepareForApplicationProcessorInit(KeNumberProcessors); + PsPrepareForApplicationProcessorInit(KeNumberProcessors); + } + /* Allocate a stack for use when booting the processor */ + /* FIXME: The nonpaged memory for the stack is not released after use */ + ProcessorStack = + ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE; + Ki386InitialStackArray[((int)KeNumberProcessors)] = + (PVOID)(ProcessorStack - MM_STACK_SIZE); + HalInitializeProcessor(KeNumberProcessors, ProcessorStack); + KeNumberProcessors++; + } + + if (KeNumberProcessors > 1) + { + sprintf(str, + "Found %d system processors. [%lu MB Memory]\n", + KeNumberProcessors, + (KeLoaderBlock.MemHigher + 1088)/ 1024); + } + else + { + sprintf(str, + "Found 1 system processor. [%lu MB Memory]\n", + (KeLoaderBlock.MemHigher + 1088)/ 1024); + } + HalDisplayString(str); + + /* + * Initialize various critical subsystems + */ + HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); + + ExInit(); + IoInit(); + PoInit(); + LdrInitModuleManagement(); + CmInitializeRegistry(); + NtInit(); + MmInit3(); + CcInit(); + KdInit2(); + + /* Report all resources used by hal */ + HalReportResourceUsage(); + + /* + * Initalize services loaded at boot time + */ + DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount); + for (i=0; i < KeLoaderBlock.ModsCount; i++) + { + CPRINT("Module: '%s' at %08lx, length 0x%08lx\n", + KeLoaderModules[i].String, + KeLoaderModules[i].ModStart, + KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart); + } + + /* Pass 1: load nls files */ + for (i = 1; i < KeLoaderBlock.ModsCount; i++) + { + name = (PCHAR)KeLoaderModules[i].String; + if (RtlpCheckFileNameExtension(name, ".nls")) + { + ULONG Mod2Start = 0; + ULONG Mod2End = 0; + ULONG Mod3Start = 0; + ULONG Mod3End = 0; + + name = (PCHAR)KeLoaderModules[i+1].String; + if (RtlpCheckFileNameExtension(name, ".nls")) + { + Mod2Start = (ULONG)KeLoaderModules[i+1].ModStart; + Mod2End = (ULONG)KeLoaderModules[i+1].ModEnd; + + name = (PCHAR)KeLoaderModules[i+2].String; + if (RtlpCheckFileNameExtension(name, ".nls")) + { + Mod3Start = (ULONG)KeLoaderModules[i+2].ModStart; + Mod3End = (ULONG)KeLoaderModules[i+2].ModEnd; + } + } + + /* Initialize nls sections */ + RtlpInitNlsSections((ULONG)KeLoaderModules[i].ModStart, + (ULONG)KeLoaderModules[i].ModEnd, + Mod2Start, + Mod2End, + Mod3Start, + Mod3End); + break; + } + } + + /* Pass 2: load registry chunks passed in */ + for (i = 1; i < KeLoaderBlock.ModsCount; i++) + { + start = KeLoaderModules[i].ModStart; + length = KeLoaderModules[i].ModEnd - start; + name = (PCHAR)KeLoaderModules[i].String; + if (RtlpCheckFileNameExtension(name, "") || + RtlpCheckFileNameExtension(name, ".hiv")) + { + CPRINT("Process registry chunk at %08lx\n", start); + CmImportHive((PCHAR)start, length); + } + } + + /* Initialize volatile registry settings */ + CmInit2((PCHAR)KeLoaderBlock.CommandLine); + + /* + * Enter the kernel debugger before starting up the boot drivers + */ +#ifdef KDBG + KdbEnter(); +#endif /* KDBG */ + + IoCreateDriverList(); + + /* Pass 3: process boot loaded drivers */ + BootDriverCount = 0; + for (i=1; i < KeLoaderBlock.ModsCount; i++) + { + start = KeLoaderModules[i].ModStart; + length = KeLoaderModules[i].ModEnd - start; + name = (PCHAR)KeLoaderModules[i].String; + if (RtlpCheckFileNameExtension(name, ".sys") || + RtlpCheckFileNameExtension(name, ".sym")) + { + CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n", + name, start, length); + LdrInitializeBootStartDriver((PVOID)start, name, length); + } + if (RtlpCheckFileNameExtension(name, ".sys")) + BootDriverCount++; + } + + if (BootDriverCount == 0) + { + DbgPrint("No boot drivers available.\n"); + KeBugCheck(0); + } + + /* Create ARC names for boot devices */ + IoCreateArcNames(); + + /* Create the SystemRoot symbolic link */ + CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine); + Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine); + if (!NT_SUCCESS(Status)) + KeBugCheck(INACCESSIBLE_BOOT_DEVICE); + +#ifdef DBGPRINT_FILE_LOG + /* On the assumption that we can now access disks start up the debug + logger thread */ + DebugLogInit2(); +#endif /* DBGPRINT_FILE_LOG */ + + + PiInitDefaultLocale(); + + /* + * Start the motherboard enumerator (the HAL) + */ + HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); +#if 0 + /* + * Load boot start drivers + */ + IopLoadBootStartDrivers(); +#else + /* + * Load Auto configured drivers + */ + LdrLoadAutoConfigDrivers(); +#endif + + IoDestroyDriverList(); + + /* + * Assign drive letters + */ + IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock, + NULL, + NULL, + NULL); + + /* + * Initialize shared user page: + * - set dos system path, dos device map, etc. + */ + InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine); + + /* + * Launch initial process + */ + LdrLoadInitialProcess(); + + PsTerminateSystemThread(STATUS_SUCCESS); +} + + +VOID +KiSystemStartup(BOOLEAN BootProcessor) +{ + HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); + + if (BootProcessor) + { + /* Never returns */ + ExpInitializeExecutive(); + KeBugCheck(0); + } + /* Do application processor initialization */ + KeApplicationProcessorInit(); + PsApplicationProcessorInit(); + KeLowerIrql(PASSIVE_LEVEL); + PsIdleThreadMain(NULL); + KeBugCheck(0); + for(;;); +} + +VOID +_main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) +/* + * FUNCTION: Called by the boot loader to start the kernel + * ARGUMENTS: + * LoaderBlock = Pointer to boot parameters initialized by the boot + * loader + * NOTE: The boot parameters are stored in low memory which will become + * invalid after the memory managment is initialized so we make a local copy. + */ +{ + ULONG i; + ULONG size; + ULONG last_kernel_address; + extern ULONG _bss_end__; + ULONG HalBase; + ULONG DriverBase; + ULONG DriverSize; + + /* Low level architecture specific initialization */ + KeInit1(); + + /* + * Copy the parameters to a local buffer because lowmem will go away + */ + memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK)); + memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr, + sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount); + KeLoaderBlock.ModsCount++; + KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules; + + /* + * Convert a path specification in the grub format to one understood by the + * rest of the kernel. + */ + if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(') + { + ULONG DiskNumber = 0, PartNumber = 0; + PCH p; + CHAR Temp[256]; + PCH options; + PCH s1; + + if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' && + ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd') + { + DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0'; + PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0'; + } + strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]); + if ((options = strchr(Temp, ' ')) != NULL) + { + *options = 0; + options++; + } + else + { + options = ""; + } + if ((s1 = strrchr(Temp, '/')) != NULL) + { + *s1 = 0; + if ((s1 = strrchr(Temp, '/')) != NULL) + { + *s1 = 0; + } + } + sprintf(KeLoaderCommandLine, + "multi(0)disk(0)rdisk(%ld)partition(%ld)%s %s", + DiskNumber, PartNumber + 1, Temp, options); + + p = KeLoaderCommandLine; + while (*p != 0 && *p != ' ') + { + if ((*p) == '/') + { + (*p) = '\\'; + } + p++; + } + DPRINT1("Command Line: %s\n", KeLoaderCommandLine); + } + else + { + strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine); + } + KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine; + + strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe"); + KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0]; + KeLoaderModules[0].ModStart = 0xC0000000; + KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__); + for (i = 1; i < KeLoaderBlock.ModsCount; i++) + { + CHAR* s; + if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0) + { + strcpy(KeLoaderModuleStrings[i], s + 1); + } + else + { + strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String); + } + KeLoaderModules[i].ModStart -= 0x200000; + KeLoaderModules[i].ModStart += 0xc0000000; + KeLoaderModules[i].ModEnd -= 0x200000; + KeLoaderModules[i].ModEnd += 0xc0000000; + KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i]; + } + +#ifdef HAL_DBG + HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); +#endif + + HalBase = KeLoaderModules[1].ModStart; + DriverBase = + PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd); + + /* + * Process hal.dll + */ + LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize); + + LdrHalBase = (ULONG_PTR)DriverBase; + last_kernel_address = DriverBase + DriverSize; + + /* + * Process ntoskrnl.exe + */ + LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize); + + FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000; + LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000; + LastKernelAddress = last_kernel_address; + +#ifndef ACPI + /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */ + KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO; +#endif + + KeMemoryMapRangeCount = 0; + if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) + { + /* We have a memory map from the nice BIOS */ + size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG))); + i = 0; + while (i < KeLoaderBlock.MmapLength) + { + memcpy (&KeMemoryMap[KeMemoryMapRangeCount], + (PVOID)(KeLoaderBlock.MmapAddr + i), + sizeof(ADDRESS_RANGE)); + KeMemoryMapRangeCount++; + i += size; + } + } + + KiSystemStartup(1); +} + +/* EOF */ + diff --git a/ntoskrnl/ke/mutex.c b/ntoskrnl/ke/mutex.c new file mode 100644 index 0000000..b387df5 --- /dev/null +++ b/ntoskrnl/ke/mutex.c @@ -0,0 +1,169 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/mutex.c + * PURPOSE: Implements mutex + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +KeInitializeMutex(IN PKMUTEX Mutex, + IN ULONG Level) +{ + KeInitializeDispatcherHeader(&Mutex->Header, + InternalMutexType, + sizeof(KMUTEX) / sizeof(ULONG), + 1); + Mutex->MutantListEntry.Flink = NULL; + Mutex->MutantListEntry.Blink = NULL; + Mutex->OwnerThread = NULL; + Mutex->Abandoned = FALSE; + Mutex->ApcDisable = 1; +} + +LONG STDCALL +KeReadStateMutex(IN PKMUTEX Mutex) +{ + return(Mutex->Header.SignalState); +} + +LONG STDCALL +KeReleaseMutex(IN PKMUTEX Mutex, + IN BOOLEAN Wait) +{ + KeAcquireDispatcherDatabaseLock(Wait); + if (Mutex->OwnerThread != KeGetCurrentThread()) + { + DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutex %p\n", Mutex); + KeBugCheck(0); /* THREAD_NOT_MUTEX_OWNER */ + } + Mutex->Header.SignalState++; + assert(Mutex->Header.SignalState <= 1); + if (Mutex->Header.SignalState == 1) + { + Mutex->OwnerThread = NULL; + if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink) + RemoveEntryList(&Mutex->MutantListEntry); + KeDispatcherObjectWake(&Mutex->Header); + } + KeReleaseDispatcherDatabaseLock(Wait); + return(0); +} + +NTSTATUS STDCALL +KeWaitForMutexObject(IN PKMUTEX Mutex, + IN KWAIT_REASON WaitReason, + IN KPROCESSOR_MODE WaitMode, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Timeout) +{ + return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout)); +} + + +VOID STDCALL +KeInitializeMutant(IN PKMUTANT Mutant, + IN BOOLEAN InitialOwner) +{ + if (InitialOwner == TRUE) + { + KeInitializeDispatcherHeader(&Mutant->Header, + InternalMutexType, + sizeof(KMUTANT) / sizeof(ULONG), + 0); + InsertTailList(&KeGetCurrentThread()->MutantListHead, + &Mutant->MutantListEntry); + Mutant->OwnerThread = KeGetCurrentThread(); + } + else + { + KeInitializeDispatcherHeader(&Mutant->Header, + InternalMutexType, + sizeof(KMUTANT) / sizeof(ULONG), + 1); + Mutant->MutantListEntry.Flink = NULL; + Mutant->MutantListEntry.Blink = NULL; + Mutant->OwnerThread = NULL; + } + Mutant->Abandoned = FALSE; + Mutant->ApcDisable = 0; +} + +LONG STDCALL +KeReadStateMutant(IN PKMUTANT Mutant) +{ + return(Mutant->Header.SignalState); +} + +LONG STDCALL +KeReleaseMutant(IN PKMUTANT Mutant, + IN KPRIORITY Increment, + IN BOOLEAN Abandon, + IN BOOLEAN Wait) +{ + KeAcquireDispatcherDatabaseLock(Wait); + if (Abandon == FALSE) + { + if (Mutant->OwnerThread != NULL && Mutant->OwnerThread != KeGetCurrentThread()) + { + DbgPrint("THREAD_NOT_MUTEX_OWNER: Mutant->OwnerThread %p CurrentThread %p\n", + Mutant->OwnerThread, + KeGetCurrentThread()); + KeBugCheck(0); /* THREAD_NOT_MUTEX_OWNER */ + } + Mutant->Header.SignalState++; + assert(Mutant->Header.SignalState <= 1); + } + else + { + if (Mutant->OwnerThread != NULL) + { + Mutant->Header.SignalState = 1; + Mutant->Abandoned = TRUE; + } + } + + if (Mutant->Header.SignalState == 1) + { + Mutant->OwnerThread = NULL; + if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink) + RemoveEntryList(&Mutant->MutantListEntry); + KeDispatcherObjectWake(&Mutant->Header); + } + + KeReleaseDispatcherDatabaseLock(Wait); + return(0); +} + +/* EOF */ diff --git a/ntoskrnl/ke/process.c b/ntoskrnl/ke/process.c new file mode 100644 index 0000000..18acafd --- /dev/null +++ b/ntoskrnl/ke/process.c @@ -0,0 +1,102 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/process.c + * PURPOSE: Microkernel process management + * PROGRAMMER: David Welch (welch@cwcom.net) + * PORTABILITY: No. + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +KeAttachProcess (PEPROCESS Process) +{ + KIRQL oldlvl; + PETHREAD CurrentThread; + ULONG PageDir; + + DPRINT("KeAttachProcess(Process %x)\n",Process); + + CurrentThread = PsGetCurrentThread(); + + if (CurrentThread->OldProcess != NULL) + { + DbgPrint("Invalid attach (thread is already attached)\n"); + KeBugCheck(0); + } + + KeRaiseIrql(DISPATCH_LEVEL, &oldlvl); + + CurrentThread->OldProcess = PsGetCurrentProcess(); + CurrentThread->ThreadsProcess = Process; + PageDir = CurrentThread->ThreadsProcess->Pcb.DirectoryTableBase.u.LowPart; + DPRINT("Switching process context to %x\n",PageDir) + __asm__("movl %0,%%cr3\n\t" + : /* no inputs */ + : "r" (PageDir)); + + + KeLowerIrql(oldlvl); +} + +VOID STDCALL +KeDetachProcess (VOID) +{ + KIRQL oldlvl; + PETHREAD CurrentThread; + ULONG PageDir; + + DPRINT("KeDetachProcess()\n"); + + CurrentThread = PsGetCurrentThread(); + + if (CurrentThread->OldProcess == NULL) + { + DbgPrint("Invalid detach (thread was not attached)\n"); + KeBugCheck(0); + } + + KeRaiseIrql(DISPATCH_LEVEL, &oldlvl); + + CurrentThread->ThreadsProcess = CurrentThread->OldProcess; + CurrentThread->OldProcess = NULL; + PageDir = CurrentThread->ThreadsProcess->Pcb.DirectoryTableBase.u.LowPart; + __asm__("movl %0,%%cr3\n\t" + : /* no inputs */ + : "r" (PageDir)); + + KeLowerIrql(oldlvl); +} + +/* EOF */ diff --git a/ntoskrnl/ke/queue.c b/ntoskrnl/ke/queue.c new file mode 100644 index 0000000..7b4bea5 --- /dev/null +++ b/ntoskrnl/ke/queue.c @@ -0,0 +1,97 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/queue.c + * PURPOSE: Implements kernel queues + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 04/01/2002 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +KeInitializeQueue(IN PKQUEUE Queue, + IN ULONG Count OPTIONAL) +{ + KeInitializeDispatcherHeader(&Queue->Header, + InternalQueueType, + sizeof(KQUEUE)/sizeof(ULONG), + 0); + InitializeListHead(&Queue->EntryListHead); + InitializeListHead(&Queue->ThreadListEntry); + Queue->CurrentCount = 0; + Queue->MaximumCount = (Count == 0) ? KeNumberProcessors : Count; +} + + +LONG STDCALL +KeReadStateQueue(IN PKQUEUE Queue) +{ + return(Queue->Header.SignalState); +} + + +LONG STDCALL +KeInsertHeadQueue(IN PKQUEUE Queue, + IN PLIST_ENTRY Entry) +{ + UNIMPLEMENTED; + return 0; +} + + +LONG STDCALL +KeInsertQueue(IN PKQUEUE Queue, + IN PLIST_ENTRY Entry) +{ + UNIMPLEMENTED; + return 0; +} + + +PLIST_ENTRY STDCALL +KeRemoveQueue(IN PKQUEUE Queue, + IN KPROCESSOR_MODE WaitMode, + IN PLARGE_INTEGER Timeout OPTIONAL) +{ + UNIMPLEMENTED; + return NULL; +} + + +PLIST_ENTRY STDCALL +KeRundownQueue(IN PKQUEUE Queue) +{ + UNIMPLEMENTED; + return NULL; +} + +/* EOF */ diff --git a/ntoskrnl/ke/sem.c b/ntoskrnl/ke/sem.c new file mode 100644 index 0000000..5481811 --- /dev/null +++ b/ntoskrnl/ke/sem.c @@ -0,0 +1,108 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/sem.c + * PURPOSE: Implements kernel semaphores + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +KeInitializeSemaphore (PKSEMAPHORE Semaphore, + LONG Count, + LONG Limit) +{ + KeInitializeDispatcherHeader(&Semaphore->Header, + InternalSemaphoreType, + sizeof(KSEMAPHORE)/sizeof(ULONG), + Count); + Semaphore->Limit=Limit; +} + +LONG STDCALL +KeReadStateSemaphore (PKSEMAPHORE Semaphore) +{ + return(Semaphore->Header.SignalState); +} + +LONG STDCALL +KeReleaseSemaphore (PKSEMAPHORE Semaphore, + KPRIORITY Increment, + LONG Adjustment, + BOOLEAN Wait) +/* + * FUNCTION: KeReleaseSemaphore releases a given semaphore object. This + * routine supplies a runtime priority boost for waiting threads. If this + * call sets the semaphore to the Signaled state, the semaphore count is + * augmented by the given value. The caller can also specify whether it + * will call one of the KeWaitXXX routines as soon as KeReleaseSemaphore + * returns control. + * ARGUMENTS: + * Semaphore = Points to an initialized semaphore object for which the + * caller provides the storage. + * Increment = Specifies the priority increment to be applied if + * releasing the semaphore causes a wait to be + * satisfied. + * Adjustment = Specifies a value to be added to the current semaphore + * count. This value must be positive + * Wait = Specifies whether the call to KeReleaseSemaphore is to be + * followed immediately by a call to one of the KeWaitXXX. + * RETURNS: If the return value is zero, the previous state of the semaphore + * object is Not-Signaled. + */ +{ + ULONG InitialState; + + DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, " + "Wait %d)\n", Semaphore, Increment, Adjustment, Wait); + + KeAcquireDispatcherDatabaseLock(Wait); + + InitialState = Semaphore->Header.SignalState; + if (Semaphore->Limit < InitialState + Adjustment || + InitialState > InitialState + Adjustment) + { + ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED); + } + + Semaphore->Header.SignalState += Adjustment; + if (InitialState == 0) + { + KeDispatcherObjectWake(&Semaphore->Header); + } + + KeReleaseDispatcherDatabaseLock(Wait); + return(InitialState); +} + +/* EOF */ diff --git a/ntoskrnl/ke/spinlock.c b/ntoskrnl/ke/spinlock.c new file mode 100644 index 0000000..2e10122 --- /dev/null +++ b/ntoskrnl/ke/spinlock.c @@ -0,0 +1,115 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/spinlock.c + * PURPOSE: Implements spinlocks + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 3/6/98: Created + */ + +/* + * NOTE: On a uniprocessor machine spinlocks are implemented by raising + * the irq level + */ + +/* INCLUDES ****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN STDCALL +KeSynchronizeExecution (PKINTERRUPT Interrupt, + PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, + PVOID SynchronizeContext) +/* + * FUNCTION: Synchronizes the execution of a given routine with the ISR + * of a given interrupt object + * ARGUMENTS: + * Interrupt = Interrupt object to synchronize with + * SynchronizeRoutine = Routine to call whose execution is + * synchronized with the ISR + * SynchronizeContext = Parameter to pass to the synchronized routine + * RETURNS: TRUE if the operation succeeded + */ +{ + KIRQL oldlvl; + BOOLEAN ret; + + KeRaiseIrql(Interrupt->SynchLevel,&oldlvl); + KeAcquireSpinLockAtDpcLevel(Interrupt->IrqLock); + + ret = SynchronizeRoutine(SynchronizeContext); + + KeReleaseSpinLockFromDpcLevel(Interrupt->IrqLock); + KeLowerIrql(oldlvl); + + return(ret); +} + +VOID STDCALL +KeInitializeSpinLock (PKSPIN_LOCK SpinLock) +/* + * FUNCTION: Initalizes a spinlock + * ARGUMENTS: + * SpinLock = Caller supplied storage for the spinlock + */ +{ + SpinLock->Lock = 0; +} + +VOID STDCALL +KeAcquireSpinLockAtDpcLevel (PKSPIN_LOCK SpinLock) +/* + * FUNCTION: Acquires a spinlock when the caller is already running at + * dispatch level + * ARGUMENTS: + * SpinLock = Spinlock to acquire + */ +{ + ULONG i; + + /* + * FIXME: This depends on gcc assembling this test to a single load from + * the spinlock's value. + */ + if ((ULONG)SpinLock->Lock >= 2) + { + DbgPrint("Lock %x has bad value %x\n", SpinLock, SpinLock->Lock); + KeBugCheck(0); + } + + while ((i = InterlockedExchange(&SpinLock->Lock, 1)) == 1) + { +#ifndef MP + DbgPrint("Spinning on spinlock %x current value %x\n", SpinLock, i); + KeBugCheck(0); +#else /* not MP */ + /* Avoid reading the value again too fast */ +#endif /* MP */ + } +} + +VOID STDCALL +KeReleaseSpinLockFromDpcLevel (PKSPIN_LOCK SpinLock) +/* + * FUNCTION: Releases a spinlock when the caller was running at dispatch + * level before acquiring it + * ARGUMENTS: + * SpinLock = Spinlock to release + */ +{ + if (SpinLock->Lock != 1) + { + DbgPrint("Releasing unacquired spinlock %x\n", SpinLock); + KeBugCheck(0); + } + (void)InterlockedExchange(&SpinLock->Lock, 0); +} + +/* EOF */ diff --git a/ntoskrnl/ke/timer.c b/ntoskrnl/ke/timer.c new file mode 100644 index 0000000..d66ef4a --- /dev/null +++ b/ntoskrnl/ke/timer.c @@ -0,0 +1,459 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ke/timer.c + * PURPOSE: Handle timers + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 28/05/98: Created + * 12/3/99: Phillip Susi: enabled the timers, fixed spin lock + */ + +/* NOTES ******************************************************************/ +/* + * System time units are 100-nanosecond intervals + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *****************************************************************/ + +#define TIMER_IRQ 0 + +/* GLOBALS ****************************************************************/ + +/* + * Current time + */ +static unsigned long long boot_time = 0; +static unsigned long long system_time = 0; + +/* + * Number of timer interrupts since initialisation + */ +volatile ULONGLONG KeTickCount = 0; +volatile ULONG KiRawTicks = 0; + +/* + * The increment in the system clock every timer tick (in system time units) + * + * = (1/18.2)*10^9 + * + * RJJ was 54945055 + */ +#define CLOCK_INCREMENT (100000) + +/* + * PURPOSE: List of timers + */ +static LIST_ENTRY TimerListHead; +static KSPIN_LOCK TimerListLock; +static KDPC ExpireTimerDpc; + +/* must raise IRQL to HIGH_LEVEL and grab spin lock there, to sync with ISR */ + +extern ULONG PiNrRunnableThreads; + +#define MICROSECONDS_PER_TICK (10000) +#define TICKS_TO_CALIBRATE (1) +#define CALIBRATE_PERIOD (MICROSECONDS_PER_TICK * TICKS_TO_CALIBRATE) +#define SYSTEM_TIME_UNITS_PER_MSEC (10000) + +static BOOLEAN TimerInitDone = FALSE; + +/* FUNCTIONS **************************************************************/ + + +NTSTATUS STDCALL +NtQueryTimerResolution(OUT PULONG MinimumResolution, + OUT PULONG MaximumResolution, + OUT PULONG ActualResolution) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtSetTimerResolution(IN ULONG RequestedResolution, + IN BOOL SetOrUnset, + OUT PULONG ActualResolution) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtQueryPerformanceCounter(IN PLARGE_INTEGER Counter, + IN PLARGE_INTEGER Frequency) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtDelayExecution(IN ULONG Alertable, + IN TIME* Interval) +{ + NTSTATUS Status; + LARGE_INTEGER Timeout; + + Timeout = *((PLARGE_INTEGER)Interval); + DPRINT("NtDelayExecution(Alertable %d, Internal %x) IntervalP %x\n", + Alertable, Internal, Timeout); + + DPRINT("Execution delay is %d/%d\n", + Timeout.u.HighPart, Timeout.u.LowPart); + Status = KeDelayExecutionThread(UserMode, Alertable, &Timeout); + return(Status); +} + + +NTSTATUS STDCALL +KeDelayExecutionThread (KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval) +/* + * FUNCTION: Puts the current thread into an alertable or nonalertable + * wait state for a given internal + * ARGUMENTS: + * WaitMode = Processor mode in which the caller is waiting + * Altertable = Specifies if the wait is alertable + * Interval = Specifies the interval to wait + * RETURNS: Status + */ +{ + PKTHREAD Thread = KeGetCurrentThread(); + + KeInitializeTimer(&Thread->Timer); + KeSetTimer(&Thread->Timer, *Interval, NULL); + return (KeWaitForSingleObject(&Thread->Timer, + Executive, + UserMode, + Alertable, + NULL)); +} + + +ULONG STDCALL +KeQueryTimeIncrement(VOID) +/* + * FUNCTION: Gets the increment (in 100-nanosecond units) that is added to + * the system clock every time the clock interrupts + * RETURNS: The increment + */ +{ + return(CLOCK_INCREMENT); +} + + +VOID STDCALL +KeQuerySystemTime(PLARGE_INTEGER CurrentTime) +/* + * FUNCTION: Gets the current system time + * ARGUMENTS: + * CurrentTime (OUT) = The routine stores the current time here + * NOTE: The time is the number of 100-nanosecond intervals since the + * 1st of January, 1601. + */ +{ + CurrentTime->QuadPart = system_time; +} + + +NTSTATUS STDCALL +NtGetTickCount (PULONG UpTime) +{ + LARGE_INTEGER TickCount; + if (UpTime == NULL) + return(STATUS_INVALID_PARAMETER); + KeQueryTickCount(&TickCount); + *UpTime = TickCount.u.LowPart; + return (STATUS_SUCCESS); +} + + +BOOLEAN STDCALL +KeSetTimer (PKTIMER Timer, + LARGE_INTEGER DueTime, + PKDPC Dpc) +/* + * FUNCTION: Sets the absolute or relative interval at which a timer object + * is to be set to the signaled state and optionally supplies a + * CustomTimerDpc to be executed when the timer expires. + * ARGUMENTS: + * Timer = Points to a previously initialized timer object + * DueTimer = If positive then absolute time to expire at + * If negative then the relative time to expire at + * Dpc = If non-NULL then a dpc to be called when the timer expires + * RETURNS: True if the timer was already in the system timer queue + * False otherwise + */ +{ + return(KeSetTimerEx(Timer, DueTime, 0, Dpc)); +} + +BOOLEAN STDCALL +KeSetTimerEx (PKTIMER Timer, + LARGE_INTEGER DueTime, + LONG Period, + PKDPC Dpc) +/* + * FUNCTION: Sets the absolute or relative interval at which a timer object + * is to be set to the signaled state and optionally supplies a + * CustomTimerDpc to be executed when the timer expires. + * ARGUMENTS: + * Timer = Points to a previously initialized timer object + * DueTimer = If positive then absolute time to expire at + * If negative then the relative time to expire at + * Dpc = If non-NULL then a dpc to be called when the timer expires + * RETURNS: True if the timer was already in the system timer queue + * False otherwise + */ +{ + KIRQL oldlvl; + + DPRINT("KeSetTimerEx(Timer %x), DueTime: \n",Timer); + KeAcquireSpinLock( &TimerListLock, &oldlvl ); + + Timer->Dpc = Dpc; + if (DueTime.QuadPart < 0) + { + Timer->DueTime.QuadPart = system_time - DueTime.QuadPart; + } + else + { + Timer->DueTime.QuadPart = DueTime.QuadPart; + } + Timer->Period = Period; + Timer->Header.SignalState = FALSE; + if (Timer->TimerListEntry.Flink != NULL) + { + KeReleaseSpinLock(&TimerListLock, oldlvl); + return(TRUE); + } + InsertTailList(&TimerListHead,&Timer->TimerListEntry); + KeReleaseSpinLock(&TimerListLock, oldlvl); + + return(FALSE); +} + +BOOLEAN STDCALL +KeCancelTimer (PKTIMER Timer) +/* + * FUNCTION: Removes a timer from the system timer list + * ARGUMENTS: + * Timer = timer to cancel + * RETURNS: True if the timer was running + * False otherwise + */ +{ + KIRQL oldlvl; + + DPRINT("KeCancelTimer(Timer %x)\n",Timer); + + KeRaiseIrql(HIGH_LEVEL, &oldlvl); + KeAcquireSpinLockAtDpcLevel( &TimerListLock ); + + if (Timer->TimerListEntry.Flink == NULL) + { + KeReleaseSpinLock(&TimerListLock, oldlvl); + return(FALSE); + } + RemoveEntryList(&Timer->TimerListEntry); + Timer->TimerListEntry.Flink = Timer->TimerListEntry.Blink = NULL; + KeReleaseSpinLock(&TimerListLock, oldlvl); + + return(TRUE); +} + +BOOLEAN STDCALL +KeReadStateTimer (PKTIMER Timer) +{ + return(Timer->Header.SignalState); +} + +VOID STDCALL +KeInitializeTimer (PKTIMER Timer) +/* + * FUNCTION: Initalizes a kernel timer object + * ARGUMENTS: + * Timer = caller supplied storage for the timer + * NOTE: This function initializes a notification timer + */ +{ + KeInitializeTimerEx(Timer, NotificationTimer); +} + +VOID STDCALL +KeInitializeTimerEx (PKTIMER Timer, + TIMER_TYPE Type) +/* + * FUNCTION: Initializes a kernel timer object + * ARGUMENTS: + * Timer = caller supplied storage for the timer + * Type = the type of timer (notification or synchronization) + * NOTE: When a notification type expires all waiting threads are released + * and the timer remains signalled until it is explicitly reset. When a + * syncrhonization timer expires its state is set to signalled until a + * single waiting thread is released and then the timer is reset. + */ +{ + ULONG IType; + + if (Type == NotificationTimer) + { + IType = InternalNotificationTimer; + } + else if (Type == SynchronizationTimer) + { + IType = InternalSynchronizationTimer; + } + else + { + assert(FALSE); + return; + } + + KeInitializeDispatcherHeader(&Timer->Header, + IType, + sizeof(KTIMER) / sizeof(ULONG), + FALSE); + Timer->TimerListEntry.Flink = Timer->TimerListEntry.Blink = NULL; +} + +VOID STDCALL +KeQueryTickCount(PLARGE_INTEGER TickCount) +/* + * FUNCTION: Returns the number of ticks since the system was booted + * ARGUMENTS: + * TickCount (OUT) = Points to storage for the number of ticks + */ +{ + TickCount->QuadPart = KeTickCount; +} + +STATIC VOID +HandleExpiredTimer(PKTIMER current) +{ + DPRINT("HandleExpiredTime(current %x)\n",current); + if (current->Dpc != NULL) + { + DPRINT("current->Dpc %x current->Dpc->DeferredRoutine %x\n", + current->Dpc, current->Dpc->DeferredRoutine); + KeInsertQueueDpc(current->Dpc, + NULL, + NULL); + DPRINT("Finished dpc routine\n"); + } + KeAcquireDispatcherDatabaseLock(FALSE); + current->Header.SignalState = TRUE; + KeDispatcherObjectWake(¤t->Header); + KeReleaseDispatcherDatabaseLock(FALSE); + if (current->Period != 0) + { + current->DueTime.QuadPart += + current->Period * SYSTEM_TIME_UNITS_PER_MSEC; + } + else + { + RemoveEntryList(¤t->TimerListEntry); + current->TimerListEntry.Flink = current->TimerListEntry.Blink = NULL; + } +} + +VOID STDCALL +KeExpireTimers(PKDPC Dpc, + PVOID Context1, + PVOID Arg1, + PVOID Arg2) +{ + PLIST_ENTRY current_entry = NULL; + PKTIMER current = NULL; + ULONG Eip = (ULONG)Arg1; + + DPRINT("KeExpireTimers()\n"); + + current_entry = TimerListHead.Flink; + + KeAcquireSpinLockAtDpcLevel(&TimerListLock); + + while (current_entry != &TimerListHead) + { + current = CONTAINING_RECORD(current_entry, KTIMER, TimerListEntry); + + current_entry = current_entry->Flink; + + if (system_time >= current->DueTime.QuadPart) + { + HandleExpiredTimer(current); + } + } + + KiAddProfileEvent(ProfileTime, Eip); + + KeReleaseSpinLockFromDpcLevel(&TimerListLock); +} + + +VOID +KiUpdateSystemTime(KIRQL oldIrql, + ULONG Eip) +/* + * FUNCTION: Handles a timer interrupt + */ +{ + KiRawTicks++; + + if (TimerInitDone == FALSE) + { + return; + } + /* + * Increment the number of timers ticks + */ + KeTickCount++; + SharedUserData->TickCountLow++; + system_time = system_time + CLOCK_INCREMENT; + + /* + * Queue a DPC that will expire timers + */ + KeInsertQueueDpc(&ExpireTimerDpc, (PVOID)Eip, 0); +} + + +VOID +KeInitializeTimerImpl(VOID) +/* + * FUNCTION: Initializes timer irq handling + * NOTE: This is only called once from main() + */ +{ + TIME_FIELDS TimeFields; + LARGE_INTEGER SystemBootTime; + + DPRINT("KeInitializeTimerImpl()\n"); + InitializeListHead(&TimerListHead); + KeInitializeSpinLock(&TimerListLock); + KeInitializeDpc(&ExpireTimerDpc, KeExpireTimers, 0); + TimerInitDone = TRUE; + /* + * Calculate the starting time for the system clock + */ + HalQueryRealTimeClock(&TimeFields); + RtlTimeFieldsToTime(&TimeFields, &SystemBootTime); + boot_time=SystemBootTime.QuadPart; + system_time=boot_time; + + DPRINT("Finished KeInitializeTimerImpl()\n"); +} diff --git a/ntoskrnl/ke/wait.c b/ntoskrnl/ke/wait.c new file mode 100644 index 0000000..12dcd29 --- /dev/null +++ b/ntoskrnl/ke/wait.c @@ -0,0 +1,877 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS project + * FILE: ntoskrnl/ke/wait.c + * PURPOSE: Manages non-busy waiting + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 21/07/98: Created + * 12/1/99: Phillip Susi: Fixed wake code in KeDispatcherObjectWake + * so that things like KeWaitForXXX() return the correct value + */ + +/* NOTES ******************************************************************** + * + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +static KSPIN_LOCK DispatcherDatabaseLock; +static BOOLEAN WaitSet = FALSE; +static KIRQL oldlvl = PASSIVE_LEVEL; +static PKTHREAD Owner = NULL; + +/* FUNCTIONS *****************************************************************/ + +VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header, + ULONG Type, + ULONG Size, + ULONG SignalState) +{ + Header->Type = Type; + Header->Absolute = 0; + Header->Inserted = 0; + Header->Size = Size; + Header->SignalState = SignalState; + InitializeListHead(&(Header->WaitListHead)); +} + +VOID KeAcquireDispatcherDatabaseLock(BOOLEAN Wait) +/* + * PURPOSE: Acquires the dispatcher database lock for the caller + */ +{ + DPRINT("KeAcquireDispatcherDatabaseLock(Wait %x)\n",Wait); + if (WaitSet && Owner == KeGetCurrentThread()) + { + return; + } + KeAcquireSpinLock(&DispatcherDatabaseLock, &oldlvl); + WaitSet = Wait; + Owner = KeGetCurrentThread(); +} + +VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait) +{ + DPRINT("KeReleaseDispatcherDatabaseLockAtDpcLevel(Wait %x)\n", Wait); + assert(Wait == WaitSet); + if (!Wait) + { + Owner = NULL; + KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock); + } +} + +VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait) +{ + DPRINT("KeReleaseDispatcherDatabaseLock(Wait %x)\n",Wait); + assert(Wait==WaitSet); + if (!Wait) + { + Owner = NULL; + KeReleaseSpinLock(&DispatcherDatabaseLock, oldlvl); + } +} + +static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr, + PKTHREAD Thread, + PBOOLEAN Abandoned) +/* + * FUNCTION: Perform side effects on object before a wait for a thread is + * satisfied + */ +{ + if (Abandoned != NULL) + *Abandoned = FALSE; + + switch (hdr->Type) + { + case InternalSynchronizationEvent: + hdr->SignalState = 0; + break; + + case InternalSemaphoreType: + hdr->SignalState--; + break; + + case InternalProcessType: + break; + + case InternalThreadType: + break; + + case InternalNotificationEvent: + break; + + case InternalSynchronizationTimer: + hdr->SignalState = FALSE; + break; + + case InternalNotificationTimer: + break; + + case InternalMutexType: + { + PKMUTEX Mutex; + + Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header); + hdr->SignalState--; + assert(hdr->SignalState <= 1); + if (hdr->SignalState == 0) + { + if (Thread == NULL) + { + DPRINT1("Thread == NULL!\n"); + KeBugCheck(0); + } + if (Abandoned != NULL) + *Abandoned = Mutex->Abandoned; + if (Thread != NULL) + InsertTailList(&Thread->MutantListHead, + &Mutex->MutantListEntry); + Mutex->OwnerThread = Thread; + Mutex->Abandoned = FALSE; + } + } + break; + + default: + DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", + __FILE__,__LINE__,hdr); + KeBugCheck(0); + } +} + +static BOOLEAN +KiIsObjectSignalled(DISPATCHER_HEADER* hdr, + PKTHREAD Thread, + PBOOLEAN Abandoned) +{ + if (Abandoned != NULL) + *Abandoned = FALSE; + + if (hdr->Type == InternalMutexType) + { + PKMUTEX Mutex; + + Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header); + + assert(hdr->SignalState <= 1); + if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) || + hdr->SignalState == 1) + { + KiSideEffectsBeforeWake(hdr, + Thread, + Abandoned); + return(TRUE); + } + else + { + return(FALSE); + } + } + if (hdr->SignalState <= 0) + { + return(FALSE); + } + else + { + KiSideEffectsBeforeWake(hdr, + Thread, + Abandoned); + return(TRUE); + } +} + +VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus) +{ + PKWAIT_BLOCK WaitBlock; + BOOLEAN WasWaiting = FALSE; + + KeAcquireDispatcherDatabaseLock(FALSE); + + WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList; + if (WaitBlock != NULL) + { + WasWaiting = TRUE; + } + while (WaitBlock != NULL) + { + RemoveEntryList(&WaitBlock->WaitListEntry); + WaitBlock = WaitBlock->NextWaitBlock; + } + Thread->Tcb.WaitBlockList = NULL; + + if (WasWaiting) + { + PsUnblockThread(Thread, &WaitStatus); + } + + KeReleaseDispatcherDatabaseLock(FALSE); +} + +static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr) +{ + PKWAIT_BLOCK current; + PLIST_ENTRY current_entry; + PKWAIT_BLOCK PrevBlock; + NTSTATUS Status; + BOOLEAN Abandoned; + + DPRINT("KeDispatcherObjectWakeAll(hdr %x)\n",hdr); + + if (IsListEmpty(&hdr->WaitListHead)) + { + return(FALSE); + } + + while (!IsListEmpty(&hdr->WaitListHead)) + { + current_entry = RemoveHeadList(&hdr->WaitListHead); + current = CONTAINING_RECORD(current_entry, + KWAIT_BLOCK, + WaitListEntry); + DPRINT("Waking %x\n",current->Thread); + if (current->WaitType == WaitAny) + { + DPRINT("WaitAny: Remove all wait blocks.\n"); + for(PrevBlock = current->Thread->WaitBlockList; PrevBlock; + PrevBlock = PrevBlock->NextWaitBlock) + { + if (PrevBlock != current) + RemoveEntryList(&PrevBlock->WaitListEntry); + } + current->Thread->WaitBlockList = 0; + } + else + { + DPRINT("WaitAll: Remove the current wait block only.\n"); + + PrevBlock = current->Thread->WaitBlockList; + if (PrevBlock == current) + { + DPRINT( "WaitAll: Current block is list head.\n" ); + current->Thread->WaitBlockList = current->NextWaitBlock; + } + else + { + DPRINT( "WaitAll: Current block is not list head.\n" ); + while (PrevBlock && PrevBlock->NextWaitBlock != current) + { + PrevBlock = PrevBlock->NextWaitBlock; + } + if (PrevBlock) + { + PrevBlock->NextWaitBlock = current->NextWaitBlock; + } + } + } + KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned); + Status = current->WaitKey; + if (Abandoned) + Status += STATUS_ABANDONED_WAIT_0; + if (current->Thread->WaitBlockList == NULL) + { + PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), + &Status); + } + } + return(TRUE); +} + +static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr) +{ + PKWAIT_BLOCK current; + PLIST_ENTRY current_entry; + PKWAIT_BLOCK PrevBlock; + NTSTATUS Status; + BOOLEAN Abandoned; + + DPRINT("KeDispatcherObjectWakeOn(hdr %x)\n",hdr); + DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n", + hdr->WaitListHead.Flink,hdr->WaitListHead.Blink); + if (IsListEmpty(&(hdr->WaitListHead))) + { + return(FALSE); + } + current_entry = RemoveHeadList(&(hdr->WaitListHead)); + current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK, + WaitListEntry); + DPRINT("current_entry %x current %x\n",current_entry,current); + + if (current->WaitType == WaitAny) + { + DPRINT("WaitAny: Remove all wait blocks.\n"); + for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; PrevBlock = PrevBlock->NextWaitBlock ) + if( PrevBlock != current ) + RemoveEntryList( &(PrevBlock->WaitListEntry) ); + current->Thread->WaitBlockList = 0; + } + else + { + DPRINT("WaitAll: Remove the current wait block only.\n"); + + PrevBlock = current->Thread->WaitBlockList; + if (PrevBlock == current) + { + DPRINT( "WaitAll: Current block is list head.\n" ); + current->Thread->WaitBlockList = current->NextWaitBlock; + } + else + { + DPRINT( "WaitAll: Current block is not list head.\n" ); + while ( PrevBlock && PrevBlock->NextWaitBlock != current) + { + PrevBlock = PrevBlock->NextWaitBlock; + } + if (PrevBlock) + { + PrevBlock->NextWaitBlock = current->NextWaitBlock; + } + } + } + + DPRINT("Waking %x\n",current->Thread); + KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned); + Status = current->WaitKey; + if (Abandoned) + Status += STATUS_ABANDONED_WAIT_0; + PsUnblockThread(CONTAINING_RECORD(current->Thread, ETHREAD, Tcb), + &Status); + return(TRUE); +} + +BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr) +/* + * FUNCTION: Wake threads waiting on a dispatcher object + * NOTE: The exact semantics of waking are dependant on the type of object + */ +{ + BOOL Ret; + + DPRINT("Entering KeDispatcherObjectWake(hdr %x)\n",hdr); +// DPRINT("hdr->WaitListHead %x hdr->WaitListHead.Flink %x\n", +// &hdr->WaitListHead,hdr->WaitListHead.Flink); + DPRINT("hdr->Type %x\n",hdr->Type); + switch (hdr->Type) + { + case InternalNotificationEvent: + return(KeDispatcherObjectWakeAll(hdr)); + + case InternalNotificationTimer: + return(KeDispatcherObjectWakeAll(hdr)); + + case InternalSynchronizationEvent: + return(KeDispatcherObjectWakeOne(hdr)); + + case InternalSynchronizationTimer: + return(KeDispatcherObjectWakeOne(hdr)); + + case InternalSemaphoreType: + DPRINT("hdr->SignalState %d\n", hdr->SignalState); + if(hdr->SignalState>0) + { + do + { + DPRINT("Waking one semaphore waiter\n"); + Ret = KeDispatcherObjectWakeOne(hdr); + } while(hdr->SignalState > 0 && Ret) ; + return(Ret); + } + else return FALSE; + + case InternalProcessType: + return(KeDispatcherObjectWakeAll(hdr)); + + case InternalThreadType: + return(KeDispatcherObjectWakeAll(hdr)); + + case InternalMutexType: + return(KeDispatcherObjectWakeOne(hdr)); + } + DbgPrint("Dispatcher object %x has unknown type %d\n", hdr, hdr->Type); + KeBugCheck(0); + return(FALSE); +} + + +NTSTATUS STDCALL +KeWaitForSingleObject(PVOID Object, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout) +/* + * FUNCTION: Puts the current thread into a wait state until the + * given dispatcher object is set to signalled + * ARGUMENTS: + * Object = Object to wait on + * WaitReason = Reason for the wait (debugging aid) + * WaitMode = Can be KernelMode or UserMode, if UserMode then + * user-mode APCs can be delivered and the thread's + * stack can be paged out + * Altertable = Specifies if the wait is a alertable + * Timeout = Optional timeout value + * RETURNS: Status + */ +{ + DISPATCHER_HEADER* hdr = (DISPATCHER_HEADER *)Object; + PKTHREAD CurrentThread; + NTSTATUS Status; + KIRQL WaitIrql; + BOOLEAN Abandoned; + + CurrentThread = KeGetCurrentThread(); + WaitIrql = KeGetCurrentIrql(); + + /* + * Set up the timeout + * FIXME: Check for zero timeout + */ + if (Timeout != NULL) + { + KeInitializeTimer(&CurrentThread->Timer); + KeSetTimer(&CurrentThread->Timer, *Timeout, NULL); + } + + do + { + KeAcquireDispatcherDatabaseLock(FALSE); + + /* + * If we are going to wait alertably and a user apc is pending + * then return + */ + if (Alertable && KiTestAlert()) + { + KeReleaseDispatcherDatabaseLock(FALSE); + return(STATUS_USER_APC); + } + + /* + * If the object is signalled + */ + if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned)) + { + KeReleaseDispatcherDatabaseLock(FALSE); + if (Timeout != NULL) + { + KeCancelTimer(&KeGetCurrentThread()->Timer); + } + if (Abandoned == TRUE) + return(STATUS_ABANDONED_WAIT_0); + return(STATUS_WAIT_0); + } + + /* + * Check if we have already timed out + */ + if (Timeout != NULL && + KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL)) + { + KeReleaseDispatcherDatabaseLock(FALSE); + if (Timeout != NULL) + { + KeCancelTimer(&KeGetCurrentThread()->Timer); + } + return(STATUS_TIMEOUT); + } + + /* + * Set up for a wait + */ + CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL; + /* Append wait block to the KTHREAD wait block list */ + CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0]; + CurrentThread->WaitBlock[0].Object = Object; + CurrentThread->WaitBlock[0].Thread = CurrentThread; + CurrentThread->WaitBlock[0].WaitKey = STATUS_WAIT_0; + CurrentThread->WaitBlock[0].WaitType = WaitAny; + InsertTailList(&hdr->WaitListHead, + &CurrentThread->WaitBlock[0].WaitListEntry); + if (Timeout != NULL) + { + CurrentThread->WaitBlock[0].NextWaitBlock = + &CurrentThread->WaitBlock[1]; + CurrentThread->WaitBlock[1].Object = (PVOID)&CurrentThread->Timer; + CurrentThread->WaitBlock[1].Thread = CurrentThread; + CurrentThread->WaitBlock[1].WaitKey = STATUS_TIMEOUT; + CurrentThread->WaitBlock[1].WaitType = WaitAny; + CurrentThread->WaitBlock[1].NextWaitBlock = NULL; + InsertTailList(&CurrentThread->Timer.Header.WaitListHead, + &CurrentThread->WaitBlock[1].WaitListEntry); + } + else + { + CurrentThread->WaitBlock[0].NextWaitBlock = NULL; + } + PsBlockThread(&Status, (UCHAR)Alertable, WaitMode, TRUE, WaitIrql); + } while (Status == STATUS_KERNEL_APC); + + if (Timeout != NULL) + { + KeCancelTimer(&KeGetCurrentThread()->Timer); + } + + DPRINT("Returning from KeWaitForSingleObject()\n"); + return(Status); +} + + +NTSTATUS STDCALL +KeWaitForMultipleObjects(ULONG Count, + PVOID Object[], + WAIT_TYPE WaitType, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout, + PKWAIT_BLOCK WaitBlockArray) +{ + DISPATCHER_HEADER* hdr; + PKWAIT_BLOCK blk; + PKTHREAD CurrentThread; + ULONG CountSignaled; + ULONG i; + NTSTATUS Status; + KIRQL WaitIrql; + BOOLEAN Abandoned; + + DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) " + "PsGetCurrentThread() %x\n",Count,Object,PsGetCurrentThread()); + + CountSignaled = 0; + CurrentThread = KeGetCurrentThread(); + WaitIrql = KeGetCurrentIrql(); + + /* + * Work out where we are going to put the wait blocks + */ + if (WaitBlockArray == NULL) + { + if (Count > THREAD_WAIT_OBJECTS) + { + DbgPrint("(%s:%d) Too many objects!\n", + __FILE__,__LINE__); + return(STATUS_UNSUCCESSFUL); + } + blk = &CurrentThread->WaitBlock[0]; + } + else + { + if (Count > EX_MAXIMUM_WAIT_OBJECTS) + { + DbgPrint("(%s:%d) Too many objects!\n", + __FILE__,__LINE__); + return(STATUS_UNSUCCESSFUL); + } + blk = WaitBlockArray; + } + + /* + * Set up the timeout if required + */ + if (Timeout != NULL) + { + KeInitializeTimer(&CurrentThread->Timer); + KeSetTimer(&CurrentThread->Timer, *Timeout, NULL); + } + + do + { + KeAcquireDispatcherDatabaseLock(FALSE); + + /* + * If we are going to wait alertably and a user apc is pending + * then return + */ + if (Alertable && KiTestAlert()) + { + KeReleaseDispatcherDatabaseLock(FALSE); + return(STATUS_USER_APC); + } + + /* + * Check if the wait is already satisfied + */ + for (i = 0; i < Count; i++) + { + hdr = (DISPATCHER_HEADER *)Object[i]; + + if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned)) + { + CountSignaled++; + + if (WaitType == WaitAny) + { + KeReleaseDispatcherDatabaseLock(FALSE); + DPRINT("One object is already signaled!\n"); + if (Abandoned == TRUE) + return(STATUS_ABANDONED_WAIT_0 + i); + return(STATUS_WAIT_0 + i); + } + } + } + + if ((WaitType == WaitAll) && (CountSignaled == Count)) + { + KeReleaseDispatcherDatabaseLock(FALSE); + DPRINT("All objects are already signaled!\n"); + return(STATUS_WAIT_0); + } + + /* + * Check if we have already timed out + */ + if (Timeout != NULL && + KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL)) + { + KeReleaseDispatcherDatabaseLock(FALSE); + if (Timeout != NULL) + { + KeCancelTimer(&KeGetCurrentThread()->Timer); + } + return(STATUS_TIMEOUT); + } + + /* Append wait block to the KTHREAD wait block list */ + CurrentThread->WaitBlockList = blk; + + /* + * Set up the wait + */ + for (i = 0; i < Count; i++) + { + hdr = (DISPATCHER_HEADER *)Object[i]; + + blk->Object = Object[i]; + blk->Thread = CurrentThread; + blk->WaitKey = STATUS_WAIT_0 + i; + blk->WaitType = WaitType; + if (i == (Count - 1)) + { + if (Timeout != NULL) + { + blk->NextWaitBlock = &CurrentThread->WaitBlock[3]; + } + else + { + blk->NextWaitBlock = NULL; + } + } + else + { + blk->NextWaitBlock = blk + 1; + } + + InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry); + + blk = blk->NextWaitBlock; + } + if (Timeout != NULL) + { + CurrentThread->WaitBlock[3].Object = (PVOID)&CurrentThread->Timer; + CurrentThread->WaitBlock[3].Thread = CurrentThread; + CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT; + CurrentThread->WaitBlock[3].WaitType = WaitAny; + CurrentThread->WaitBlock[3].NextWaitBlock = NULL; + InsertTailList(&CurrentThread->Timer.Header.WaitListHead, + &CurrentThread->WaitBlock[3].WaitListEntry); + } + + PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql); + } while(Status == STATUS_KERNEL_APC); + + if (Timeout != NULL) + { + KeCancelTimer(&KeGetCurrentThread()->Timer); + } + + DPRINT("Returning from KeWaitForMultipleObjects()\n"); + return(Status); +} + +VOID KeInitializeDispatcher(VOID) +{ + KeInitializeSpinLock(&DispatcherDatabaseLock); +} + +NTSTATUS STDCALL +NtWaitForMultipleObjects(IN ULONG Count, + IN HANDLE Object [], + IN CINT WaitType, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time) +{ + KWAIT_BLOCK WaitBlockArray[EX_MAXIMUM_WAIT_OBJECTS]; + PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS]; + NTSTATUS Status; + ULONG i, j; + + DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, " + "Time %x)\n", Count,Object,Alertable,Time); + + if (Count > EX_MAXIMUM_WAIT_OBJECTS) + return STATUS_UNSUCCESSFUL; + + /* reference all objects */ + for (i = 0; i < Count; i++) + { + Status = ObReferenceObjectByHandle(Object[i], + SYNCHRONIZE, + NULL, + UserMode, + &ObjectPtrArray[i], + NULL); + if (Status != STATUS_SUCCESS) + { + /* dereference all referenced objects */ + for (j = 0; j < i; j++) + { + ObDereferenceObject(ObjectPtrArray[j]); + } + + return(Status); + } + } + + Status = KeWaitForMultipleObjects(Count, + ObjectPtrArray, + WaitType, + UserRequest, + UserMode, + Alertable, + Time, + WaitBlockArray); + + /* dereference all objects */ + for (i = 0; i < Count; i++) + { + ObDereferenceObject(ObjectPtrArray[i]); + } + + return(Status); +} + + +NTSTATUS STDCALL +NtWaitForSingleObject(IN HANDLE Object, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time) +{ + PVOID ObjectPtr; + NTSTATUS Status; + + DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n", + Object,Alertable,Time); + + Status = ObReferenceObjectByHandle(Object, + SYNCHRONIZE, + NULL, + UserMode, + &ObjectPtr, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = KeWaitForSingleObject(ObjectPtr, + UserMode, + UserMode, + Alertable, + Time); + + ObDereferenceObject(ObjectPtr); + + return(Status); +} + + +NTSTATUS STDCALL +NtSignalAndWaitForSingleObject(IN HANDLE SignalObject, + IN HANDLE WaitObject, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Time) +{ + KPROCESSOR_MODE ProcessorMode; + DISPATCHER_HEADER* hdr; + PVOID SignalObj; + PVOID WaitObj; + NTSTATUS Status; + + ProcessorMode = ExGetPreviousMode(); + Status = ObReferenceObjectByHandle(SignalObject, + 0, + NULL, + ProcessorMode, + &SignalObj, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = ObReferenceObjectByHandle(WaitObject, + SYNCHRONIZE, + NULL, + ProcessorMode, + &WaitObj, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(SignalObj); + return Status; + } + + hdr = (DISPATCHER_HEADER *)SignalObj; + switch (hdr->Type) + { + case InternalNotificationEvent: + case InternalSynchronizationEvent: + KeSetEvent(SignalObj, + EVENT_INCREMENT, + TRUE); + break; + + case InternalMutexType: + KeReleaseMutex(SignalObj, + TRUE); + break; + + case InternalSemaphoreType: + KeReleaseSemaphore(SignalObj, + SEMAPHORE_INCREMENT, + 1, + TRUE); + break; + + default: + ObDereferenceObject(SignalObj); + ObDereferenceObject(WaitObj); + return STATUS_OBJECT_TYPE_MISMATCH; + } + + Status = KeWaitForSingleObject(WaitObj, + UserRequest, + ProcessorMode, + Alertable, + Time); + + ObDereferenceObject(SignalObj); + ObDereferenceObject(WaitObj); + + return Status; +} diff --git a/ntoskrnl/ldr/.cvsignore b/ntoskrnl/ldr/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/ldr/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/ldr/init.c b/ntoskrnl/ldr/init.c new file mode 100644 index 0000000..ad0e8f3 --- /dev/null +++ b/ntoskrnl/ldr/init.c @@ -0,0 +1,376 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ldr/init.c + * PURPOSE: Loaders for PE executables + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + * UPDATE HISTORY: + * DW 22/05/98 Created + * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE + * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF + * RJJ 10/12/98 Rolled in David's code to load COFF drivers + * JM 14/12/98 Built initial PE user module loader + * RJJ 06/03/99 Moved user PE loader into NTDLL + * EA 19990717 LdrGetSystemDirectory() + * EK 20000618 Using SystemRoot link instead of LdrGetSystemDirectory() + * HYP 20020911 Code to determine smss's path from the registry + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/* + * TODO: Read the location of the initial process from command line before + * trying the registry - embedded setups, like the installation CD-ROM, may not + * have a SYSTEM hive + */ +NTSTATUS LdrLoadInitialProcess (VOID) +{ + NTSTATUS Status; + HANDLE ProcessHandle; + UNICODE_STRING ProcessName = {0, 0, NULL}; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE FileHandle; + HANDLE SectionHandle; + PIMAGE_NT_HEADERS NTHeaders; + PEPROCESS Process; + CONTEXT Context; + HANDLE ThreadHandle; + INITIAL_TEB InitialTeb; + ULONG OldPageProtection; + SECTION_IMAGE_INFORMATION Sii; + ULONG ResultLength; + PVOID ImageBaseAddress; + ULONG InitialStack[5]; +#if 0 + /* FIXME: Test this please */ + HANDLE RootDir; + PWSTR Environment = L"SystemRoot=\\SystemRoot\0"; + RTL_QUERY_REGISTRY_TABLE RegistryValues[] = { + { + NULL, + RTL_QUERY_REGISTRY_DIRECT, + L"Path", + &ProcessName, + REG_SZ, + L"\\SystemRoot\\system32\\smss.exe" + sizeof(L"\\SystemRoot\\system32\\smss.exe") - sizeof(WCHAR) + }, + { NULL, 0, NULL, NULL, 0, NULL, 0 } + }; + + /* try to query the SMSS path from the registry */ + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"Session Manager", + RegistryValues, + NULL, + Environment); + + /* failure or invalid data: use default */ + if(!NT_SUCCESS(Status) || ProcessName.Length < sizeof(WCHAR)) + RtlInitUnicodeStringFromLiteral(&ProcessName, + L"\\SystemRoot\\system32\\smss.exe"); + /* relative path: open \SystemRoot\system32 */ + else if(ProcessName.Buffer[0] != L'\\') + { + UNICODE_STRING DirPath; + + RtlInitUnicodeStringFromLiteral(&DirPath, L"\\SystemRoot\\system32"); + + InitializeObjectAttributes(&ObjectAttributes, + &DirPath, + 0, + NULL, + NULL); + + if(!NT_SUCCESS(ZwOpenFile(&RootDir, 0, &ObjectAttributes, NULL, 0, 0))) + /* failure: use default */ + RtlInitUnicodeStringFromLiteral(&ProcessName, + L"\\SystemRoot\\system32\\smss.exe"); + } + + InitializeObjectAttributes(&ObjectAttributes, + &ProcessName, + 0, + RootDir, + NULL); +#else + /* + * Get the absolute path to smss.exe using the + * SystemRoot link. + */ + RtlInitUnicodeStringFromLiteral(&ProcessName, + L"\\SystemRoot\\system32\\smss.exe"); + /* + * Open process image to determine ImageBase + * and StackBase/Size. + */ + InitializeObjectAttributes(&ObjectAttributes, + &ProcessName, + 0, + NULL, + NULL); +#endif + DPRINT("Opening image file %S\n", ObjectAttributes.ObjectName->Buffer); + Status = ZwOpenFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + NULL, + 0, + 0); +#if 0 + /* FIXME? ExFreePool() should ignore non-pool data */ + RtlFreeUnicodeString(&ProcessName); + NtClose(RootDir); +#endif + if (!NT_SUCCESS(Status)) + { + DPRINT("Image open failed (Status was %x)\n", Status); + return Status; + } + + /* + * Create a section for the image + */ + DPRINT("Creating section\n"); + Status = ZwCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_READWRITE, + SEC_COMMIT | SEC_IMAGE, + FileHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwCreateSection failed (Status %x)\n", Status); + ZwClose(FileHandle); + return(Status); + } + ZwClose(FileHandle); + + /* + * Get information about the process image. + */ + Status = ZwQuerySection(SectionHandle, + SectionImageInformation, + &Sii, + sizeof(Sii), + &ResultLength); + if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii)) + { + DPRINT("ZwQuerySection failed (Status %X)\n", Status); + ZwClose(SectionHandle); + return(Status); + } + + DPRINT("Creating process\n"); + Status = ZwCreateProcess(&ProcessHandle, + PROCESS_ALL_ACCESS, + NULL, + SystemProcessHandle, + FALSE, + SectionHandle, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not create process\n"); + return Status; + } + + /* + * Create initial stack and thread + */ + + /* + * Create page backed section for stack + */ + DPRINT("Allocating stack\n"); + + DPRINT("Referencing process\n"); + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_ALL_ACCESS, + PsProcessType, + KernelMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByProcess() failed (Status %x)\n", Status); + return(Status); + } + + DPRINT("Attaching to process\n"); + KeAttachProcess(Process); + ImageBaseAddress = Process->Peb->ImageBaseAddress; + NTHeaders = RtlImageNtHeader(ImageBaseAddress); + DPRINT("NTHeaders %x\n", NTHeaders); + InitialTeb.StackReserve = NTHeaders->OptionalHeader.SizeOfStackReserve; + /* FIXME: use correct commit size */ + InitialTeb.StackCommit = NTHeaders->OptionalHeader.SizeOfStackReserve - PAGE_SIZE; + // InitialTeb.StackCommit = NTHeaders->OptionalHeader.SizeOfStackCommit; + /* add guard page size */ + InitialTeb.StackCommit += PAGE_SIZE; + DPRINT("StackReserve 0x%lX StackCommit 0x%lX\n", + InitialTeb.StackReserve, InitialTeb.StackCommit); + KeDetachProcess(); + DPRINT("Dereferencing process\n"); + ObDereferenceObject(Process); + + DPRINT("Allocating stack\n"); + InitialTeb.StackAllocate = NULL; + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackAllocate, + 0, + &InitialTeb.StackReserve, + MEM_RESERVE, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Stack allocation failed (Status %x)", Status); + return(Status); + } + + DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n", + InitialTeb.StackAllocate, InitialTeb.StackReserve); + + InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve); + InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit); + + DPRINT("StackBase: %p StackCommit: 0x%lX\n", + InitialTeb.StackBase, InitialTeb.StackCommit); + + /* Commit stack */ + Status = NtAllocateVirtualMemory(ProcessHandle, + &InitialTeb.StackLimit, + 0, + &InitialTeb.StackCommit, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error comitting stack page!\n"); + return(Status); + } + + DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n", + InitialTeb.StackLimit, + InitialTeb.StackCommit); + + /* Protect guard page */ + Status = NtProtectVirtualMemory(ProcessHandle, + InitialTeb.StackLimit, + PAGE_SIZE, + PAGE_GUARD | PAGE_READWRITE, + &OldPageProtection); + if (!NT_SUCCESS(Status)) + { + /* release the stack space */ + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + DPRINT("Error protecting guard page!\n"); + return(Status); + } + + /* + * Initialize context to point to LdrStartup + */ + memset(&Context,0,sizeof(CONTEXT)); + Context.Eip = (ULONG)(ImageBaseAddress + (ULONG)Sii.EntryPoint); + Context.SegCs = USER_CS; + Context.SegDs = USER_DS; + Context.SegEs = USER_DS; + Context.SegFs = TEB_SELECTOR; + Context.SegGs = USER_DS; + Context.SegSs = USER_DS; + Context.EFlags = 0x202; + Context.Esp = (ULONG)InitialTeb.StackBase - 20; + + /* + * Write in the initial stack. + */ + InitialStack[0] = 0; + InitialStack[1] = PEB_BASE; + Status = ZwWriteVirtualMemory(ProcessHandle, + (PVOID)Context.Esp, + InitialStack, + sizeof(InitialStack), + &ResultLength); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to write initial stack.\n"); + return(Status); + } + + /* + * FIXME: Create process and let 'er rip + */ + DPRINT("Creating thread for initial process\n"); + Status = ZwCreateThread(&ThreadHandle, + THREAD_ALL_ACCESS, + NULL, + ProcessHandle, + NULL, + &Context, + &InitialTeb, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT("Thread creation failed (Status %x)\n", Status); + + NtFreeVirtualMemory(ProcessHandle, + InitialTeb.StackAllocate, + &InitialTeb.StackReserve, + MEM_RELEASE); + + /* FIXME: unmap the section here */ + /* FIXME: destroy the section here */ + /* FIXME: Kill the process here */ + + return(Status); + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ldr/loader.c b/ntoskrnl/ldr/loader.c new file mode 100644 index 0000000..eba5f27 --- /dev/null +++ b/ntoskrnl/ldr/loader.c @@ -0,0 +1,1611 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ldr/loader.c + * PURPOSE: Loaders for PE executables + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + * Jason Filby (jasonfilby@yahoo.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * DW 22/05/98 Created + * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE + * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF + * RJJ 10/12/98 Rolled in David's code to load COFF drivers + * JM 14/12/98 Built initial PE user module loader + * RJJ 06/03/99 Moved user PE loader into NTDLL + * JF 26/01/2000 Recoded some parts to retrieve export details correctly + * DW 27/06/2000 Removed redundant header files + * CSH 11/04/2001 Added automatic loading of module symbols if they exist + */ + + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HALDBG +#include +#else +#define ps(args...) +#endif + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +LIST_ENTRY ModuleListHead; +KSPIN_LOCK ModuleListLock; + +LIST_ENTRY ModuleTextListHead; +STATIC MODULE_TEXT_SECTION NtoskrnlTextSection; +STATIC MODULE_TEXT_SECTION LdrHalTextSection; +ULONG_PTR LdrHalBase; + +#define TAG_DRIVER_MEM TAG('D', 'R', 'V', 'M') + +/* FORWARD DECLARATIONS ******************************************************/ + +NTSTATUS +LdrProcessModule(PVOID ModuleLoadBase, + PUNICODE_STRING ModuleName, + PMODULE_OBJECT *ModuleObject); + +PVOID +LdrGetExportAddress(PMODULE_OBJECT ModuleObject, + char *Name, + unsigned short Hint); + +static VOID +LdrpBuildModuleBaseName(PUNICODE_STRING BaseName, + PUNICODE_STRING FullName); + +static LONG +LdrpCompareModuleNames(IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2); + + +/* PE Driver load support */ +static NTSTATUS LdrPEProcessModule(PVOID ModuleLoadBase, + PUNICODE_STRING FileName, + PMODULE_OBJECT *ModuleObject); +static PVOID +LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject, + PCHAR Name, + USHORT Hint); + +static PVOID +LdrSafePEGetExportAddress(PVOID ImportModuleBase, + PCHAR Name, + USHORT Hint); + +static PVOID +LdrPEFixupForward(PCHAR ForwardName); + + +/* FUNCTIONS *****************************************************************/ + +VOID +LdrInitDebug(PLOADER_MODULE Module, PWCH Name) +{ + PLIST_ENTRY current_entry; + MODULE_TEXT_SECTION* current; + + current_entry = ModuleTextListHead.Flink; + while (current_entry != &ModuleTextListHead) + { + current = + CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry); + if (wcscmp(current->Name, Name) == 0) + { + break; + } + current_entry = current_entry->Flink; + } + + if (current_entry == &ModuleTextListHead) + { + return; + } +} + +VOID +LdrInit1(VOID) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_FILE_HEADER FileHeader; + PIMAGE_OPTIONAL_HEADER OptionalHeader; + PIMAGE_SECTION_HEADER SectionList; + + InitializeListHead(&ModuleTextListHead); + + /* Setup ntoskrnl.exe text section */ + DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE; + FileHeader = + (PIMAGE_FILE_HEADER) ((DWORD)KERNEL_BASE + + DosHeader->e_lfanew + sizeof(ULONG)); + OptionalHeader = (PIMAGE_OPTIONAL_HEADER) + ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER)); + SectionList = (PIMAGE_SECTION_HEADER) + ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER)); + NtoskrnlTextSection.Base = KERNEL_BASE; + NtoskrnlTextSection.Length = SectionList[0].Misc.VirtualSize + + SectionList[0].VirtualAddress; + NtoskrnlTextSection.Name = KERNEL_MODULE_NAME; + NtoskrnlTextSection.OptionalHeader = OptionalHeader; + InsertTailList(&ModuleTextListHead, &NtoskrnlTextSection.ListEntry); + + /* Setup hal.dll text section */ + DosHeader = (PIMAGE_DOS_HEADER)LdrHalBase; + FileHeader = + (PIMAGE_FILE_HEADER) ((DWORD)LdrHalBase + + DosHeader->e_lfanew + sizeof(ULONG)); + OptionalHeader = (PIMAGE_OPTIONAL_HEADER) + ((DWORD)FileHeader + sizeof(IMAGE_FILE_HEADER)); + SectionList = (PIMAGE_SECTION_HEADER) + ((DWORD)OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER)); + LdrHalTextSection.Base = LdrHalBase; + LdrHalTextSection.Length = SectionList[0].Misc.VirtualSize + + SectionList[0].VirtualAddress; + LdrHalTextSection.Name = HAL_MODULE_NAME; + LdrHalTextSection.OptionalHeader = OptionalHeader; + InsertTailList(&ModuleTextListHead, &LdrHalTextSection.ListEntry); + + /* Hook for KDB on initialization of the loader. */ + KDB_LOADERINIT_HOOK(&NtoskrnlTextSection, &LdrHalTextSection); +} + + +VOID +LdrInitModuleManagement(VOID) +{ + PIMAGE_DOS_HEADER DosHeader; + PMODULE_OBJECT ModuleObject; + + /* Initialize the module list and spinlock */ + InitializeListHead(&ModuleListHead); + KeInitializeSpinLock(&ModuleListLock); + + /* Create module object for NTOSKRNL */ + ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT)); + assert(ModuleObject != NULL); + RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT)); + + /* Initialize ModuleObject data */ + ModuleObject->Base = (PVOID) KERNEL_BASE; + ModuleObject->Flags = MODULE_FLAG_PE; + RtlCreateUnicodeString(&ModuleObject->FullName, + KERNEL_MODULE_NAME); + LdrpBuildModuleBaseName(&ModuleObject->BaseName, + &ModuleObject->FullName); + + DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE; + ModuleObject->Image.PE.FileHeader = + (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base + + DosHeader->e_lfanew + sizeof(ULONG)); + ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER) + ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER)); + ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER) + ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER)); + ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base + + ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint); + DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint); + ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage; + ModuleObject->TextSection = &NtoskrnlTextSection; + + InsertTailList(&ModuleListHead, + &ModuleObject->ListEntry); + + /* Create module object for HAL */ + ModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT)); + assert(ModuleObject != NULL); + RtlZeroMemory(ModuleObject, sizeof(MODULE_OBJECT)); + + /* Initialize ModuleObject data */ + ModuleObject->Base = (PVOID) LdrHalBase; + ModuleObject->Flags = MODULE_FLAG_PE; + + RtlCreateUnicodeString(&ModuleObject->FullName, + HAL_MODULE_NAME); + LdrpBuildModuleBaseName(&ModuleObject->BaseName, + &ModuleObject->FullName); + + DosHeader = (PIMAGE_DOS_HEADER) LdrHalBase; + ModuleObject->Image.PE.FileHeader = + (PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base + + DosHeader->e_lfanew + sizeof(ULONG)); + ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER) + ((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER)); + ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER) + ((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER)); + ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base + + ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint); + DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint); + ModuleObject->Length = ModuleObject->Image.PE.OptionalHeader->SizeOfImage; + ModuleObject->TextSection = &LdrHalTextSection; + + InsertTailList(&ModuleListHead, + &ModuleObject->ListEntry); +} + +NTSTATUS +LdrpLoadImage(PUNICODE_STRING DriverName, + PVOID *ModuleBase, + PVOID *SectionPointer, + PVOID *EntryPoint, + PVOID *ExportSectionPointer) +{ + PMODULE_OBJECT ModuleObject; + NTSTATUS Status; + + ModuleObject = LdrGetModuleObject(DriverName); + if (ModuleObject == NULL) + { + Status = LdrLoadModule(DriverName, &ModuleObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + + if (ModuleBase) + *ModuleBase = ModuleObject->Base; + +// if (SectionPointer) +// *SectionPointer = ModuleObject-> + + if (EntryPoint) + *EntryPoint = ModuleObject->EntryPoint; + +// if (ExportSectionPointer) +// *ExportSectionPointer = ModuleObject-> + + return(STATUS_SUCCESS); +} + + +NTSTATUS +LdrpUnloadImage(PVOID ModuleBase) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS +LdrpLoadAndCallImage(PUNICODE_STRING ModuleName) +{ + PDRIVER_INITIALIZE DriverEntry; + PMODULE_OBJECT ModuleObject; + NTSTATUS Status; + + ModuleObject = LdrGetModuleObject(ModuleName); + if (ModuleObject != NULL) + { + return(STATUS_IMAGE_ALREADY_LOADED); + } + + Status = LdrLoadModule(ModuleName, &ModuleObject); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DriverEntry = (PDRIVER_INITIALIZE)ModuleObject->EntryPoint; + + Status = DriverEntry(NULL, NULL); + if (!NT_SUCCESS(Status)) + { + LdrUnloadModule(ModuleObject); + } + + return(Status); +} + + +NTSTATUS +LdrLoadModule(PUNICODE_STRING Filename, + PMODULE_OBJECT *ModuleObject) +{ + PVOID ModuleLoadBase; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + PMODULE_OBJECT Module; + FILE_STANDARD_INFORMATION FileStdInfo; + IO_STATUS_BLOCK IoStatusBlock; + + *ModuleObject = NULL; + + DPRINT("Loading Module %wZ...\n", Filename); + + /* Open the Module */ + InitializeObjectAttributes(&ObjectAttributes, + Filename, + 0, + NULL, + NULL); + CHECKPOINT; + Status = NtOpenFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); + CHECKPOINT; + if (!NT_SUCCESS(Status)) + { + CPRINT("Could not open module file: %wZ\n", Filename); + return(Status); + } + CHECKPOINT; + + /* Get the size of the file */ + Status = NtQueryInformationFile(FileHandle, + &IoStatusBlock, + &FileStdInfo, + sizeof(FileStdInfo), + FileStandardInformation); + if (!NT_SUCCESS(Status)) + { + CPRINT("Could not get file size\n"); + NtClose(FileHandle); + return(Status); + } + CHECKPOINT; + + /* Allocate nonpageable memory for driver */ + ModuleLoadBase = ExAllocatePoolWithTag(NonPagedPool, + FileStdInfo.EndOfFile.u.LowPart, + TAG_DRIVER_MEM); + if (ModuleLoadBase == NULL) + { + CPRINT("Could not allocate memory for module"); + NtClose(FileHandle); + return(STATUS_INSUFFICIENT_RESOURCES); + } + CHECKPOINT; + + /* Load driver into memory chunk */ + Status = NtReadFile(FileHandle, + 0, 0, 0, + &IoStatusBlock, + ModuleLoadBase, + FileStdInfo.EndOfFile.u.LowPart, + 0, 0); + if (!NT_SUCCESS(Status)) + { + CPRINT("Could not read module file into memory"); + ExFreePool(ModuleLoadBase); + NtClose(FileHandle); + return(Status); + } + CHECKPOINT; + + NtClose(FileHandle); + + Status = LdrProcessModule(ModuleLoadBase, + Filename, + &Module); + if (!NT_SUCCESS(Status)) + { + CPRINT("Could not process module"); + ExFreePool(ModuleLoadBase); + return(Status); + } + + /* Cleanup */ + ExFreePool(ModuleLoadBase); + + *ModuleObject = Module; + + /* Hook for KDB on loading a driver. */ + KDB_LOADDRIVER_HOOK(Filename, Module); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +LdrUnloadModule(PMODULE_OBJECT ModuleObject) +{ + KIRQL Irql; + + /* Remove the module from the module list */ + KeAcquireSpinLock(&ModuleListLock,&Irql); + RemoveEntryList(&ModuleObject->ListEntry); + KeReleaseSpinLock(&ModuleListLock, Irql); + + /* Hook for KDB on unloading a driver. */ + KDB_UNLOADDRIVER_HOOK(ModuleObject); + + /* Free text section */ + if (ModuleObject->TextSection != NULL) + { + ExFreePool(ModuleObject->TextSection->Name); + RemoveEntryList(&ModuleObject->TextSection->ListEntry); + ExFreePool(ModuleObject->TextSection); + ModuleObject->TextSection = NULL; + } + + /* Free module section */ +// MmFreeSection(ModuleObject->Base); + + ExFreePool(ModuleObject); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +LdrInitializeBootStartDriver(PVOID ModuleLoadBase, + PCHAR FileName, + ULONG ModuleLength) +{ + PMODULE_OBJECT ModuleObject; + UNICODE_STRING ModuleName; + PDEVICE_NODE DeviceNode; + NTSTATUS Status; + + WCHAR Buffer[MAX_PATH]; + ULONG Length; + LPWSTR Start; + LPWSTR Ext; + PCHAR FileExt; + CHAR TextBuffer [256]; + ULONG x, y, cx, cy; + + HalQueryDisplayParameters(&x, &y, &cx, &cy); + RtlFillMemory(TextBuffer, x, ' '); + TextBuffer[x] = '\0'; + HalSetDisplayParameters(0, y-1); + HalDisplayString(TextBuffer); + + sprintf(TextBuffer, "Initializing %s...\n", FileName); + HalSetDisplayParameters(0, y-1); + HalDisplayString(TextBuffer); + HalSetDisplayParameters(cx, cy); + + /* Split the filename into base name and extension */ + FileExt = strrchr(FileName, '.'); + if (FileExt != NULL) + Length = FileExt - FileName; + else + Length = strlen(FileName); + + if ((FileExt != NULL) && (strcmp(FileExt, ".sym") == 0)) + { + KDB_SYMBOLFILE_HOOK(ModuleLoadBase, FileName, Length); + return(STATUS_SUCCESS); + } + else if ((FileExt != NULL) && !(strcmp(FileExt, ".sys") == 0)) + { + CPRINT("Ignoring non-driver file %s\n", FileName); + return STATUS_SUCCESS; + } + + /* Use IopRootDeviceNode for now */ + Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode); + if (!NT_SUCCESS(Status)) + { + CPRINT("Driver load failed, status (%x)\n", Status); + return(Status); + } + + RtlCreateUnicodeStringFromAsciiz(&ModuleName, + FileName); + Status = LdrProcessModule(ModuleLoadBase, + &ModuleName, + &ModuleObject); + RtlFreeUnicodeString(&ModuleName); + if (ModuleObject == NULL) + { + IopFreeDeviceNode(DeviceNode); + CPRINT("Driver load failed, status (%x)\n", Status); + return(STATUS_UNSUCCESSFUL); + } + + + /* Get the service name from the module name */ + Start = wcsrchr(ModuleObject->BaseName.Buffer, L'\\'); + if (Start == NULL) + Start = ModuleObject->BaseName.Buffer; + else + Start++; + + Ext = wcsrchr(ModuleObject->BaseName.Buffer, L'.'); + if (Ext != NULL) + Length = Ext - Start; + else + Length = wcslen(Start); + + wcsncpy(Buffer, Start, Length); + RtlCreateUnicodeString(&DeviceNode->ServiceName, Buffer); + + Status = IopInitializeDriver(ModuleObject->EntryPoint, + DeviceNode, FALSE); + if (!NT_SUCCESS(Status)) + { + IopFreeDeviceNode(DeviceNode); + CPRINT("Driver load failed, status (%x)\n", Status); + } + + return(Status); +} + + +NTSTATUS +LdrProcessModule(PVOID ModuleLoadBase, + PUNICODE_STRING ModuleName, + PMODULE_OBJECT *ModuleObject) +{ + PIMAGE_DOS_HEADER PEDosHeader; + + /* If MZ header exists */ + PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase; + if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L) + { + return LdrPEProcessModule(ModuleLoadBase, + ModuleName, + ModuleObject); + } + + CPRINT("Module wasn't PE\n"); + return STATUS_UNSUCCESSFUL; +} + + +PVOID +LdrGetExportAddress(PMODULE_OBJECT ModuleObject, + char *Name, + unsigned short Hint) +{ + if (ModuleObject->Flags & MODULE_FLAG_PE) + { + return LdrPEGetExportAddress(ModuleObject, Name, Hint); + } + else + { + return 0; + } +} + + +NTSTATUS +LdrpQueryModuleInformation(PVOID Buffer, + ULONG Size, + PULONG ReqSize) +{ + PLIST_ENTRY current_entry; + PMODULE_OBJECT current; + ULONG ModuleCount = 0; + PSYSTEM_MODULE_INFORMATION Smi; + ANSI_STRING AnsiName; + PCHAR p; + KIRQL Irql; + + KeAcquireSpinLock(&ModuleListLock,&Irql); + + /* calculate required size */ + current_entry = ModuleListHead.Flink; + while (current_entry != (&ModuleListHead)) + { + ModuleCount++; + current_entry = current_entry->Flink; + } + + *ReqSize = sizeof(SYSTEM_MODULE_INFORMATION)+ + (ModuleCount - 1) * sizeof(SYSTEM_MODULE_ENTRY); + + if (Size < *ReqSize) + { + KeReleaseSpinLock(&ModuleListLock, Irql); + return(STATUS_INFO_LENGTH_MISMATCH); + } + + /* fill the buffer */ + memset(Buffer, '=', Size); + + Smi = (PSYSTEM_MODULE_INFORMATION)Buffer; + Smi->Count = ModuleCount; + + ModuleCount = 0; + current_entry = ModuleListHead.Flink; + while (current_entry != (&ModuleListHead)) + { + current = CONTAINING_RECORD(current_entry,MODULE_OBJECT,ListEntry); + + Smi->Module[ModuleCount].Unknown2 = 0; /* Always 0 */ + Smi->Module[ModuleCount].BaseAddress = current->Base; + Smi->Module[ModuleCount].Size = current->Length; + Smi->Module[ModuleCount].Flags = 0; /* Flags ??? (GN) */ + Smi->Module[ModuleCount].EntryIndex = ModuleCount; + + AnsiName.Length = 0; + AnsiName.MaximumLength = 256; + AnsiName.Buffer = Smi->Module[ModuleCount].Name; + RtlUnicodeStringToAnsiString(&AnsiName, + ¤t->FullName, + FALSE); + + p = strrchr(AnsiName.Buffer, '\\'); + if (p == NULL) + { + Smi->Module[ModuleCount].PathLength = 0; + Smi->Module[ModuleCount].NameLength = strlen(AnsiName.Buffer); + } + else + { + p++; + Smi->Module[ModuleCount].PathLength = p - AnsiName.Buffer; + Smi->Module[ModuleCount].NameLength = strlen(p); + } + + ModuleCount++; + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&ModuleListLock, Irql); + + return(STATUS_SUCCESS); +} + + +static VOID +LdrpBuildModuleBaseName(PUNICODE_STRING BaseName, + PUNICODE_STRING FullName) +{ + UNICODE_STRING Name; + PWCHAR p; + PWCHAR q; + + DPRINT("LdrpBuildModuleBaseName()\n"); + DPRINT("FullName %wZ\n", FullName); + + p = wcsrchr(FullName->Buffer, L'\\'); + if (p == NULL) + { + p = FullName->Buffer; + } + else + { + p++; + } + + DPRINT("p %S\n", p); + + RtlCreateUnicodeString(&Name, p); + + q = wcschr(Name.Buffer, L'.'); + if (q != NULL) + { + *q = (WCHAR)0; + } + + DPRINT("p %S\n", p); + + RtlCreateUnicodeString(BaseName, Name.Buffer); + RtlFreeUnicodeString(&Name); +} + + +static LONG +LdrpCompareModuleNames(IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2) +{ + ULONG len1, len2, i; + PWCHAR s1, s2, p; + WCHAR c1, c2; + + if (String1 && String2) + { + /* Search String1 for last path component */ + len1 = String1->Length / sizeof(WCHAR); + s1 = String1->Buffer; + for (i = 0, p = String1->Buffer; i < String1->Length; i = i + sizeof(WCHAR), p++) + { + if (*p == L'\\') + { + if (i == String1->Length - sizeof(WCHAR)) + { + s1 = NULL; + len1 = 0; + } + else + { + s1 = p + 1; + len1 = (String1->Length - i) / sizeof(WCHAR); + } + } + } + + /* Search String2 for last path component */ + len2 = String2->Length / sizeof(WCHAR); + s2 = String2->Buffer; + for (i = 0, p = String2->Buffer; i < String2->Length; i = i + sizeof(WCHAR), p++) + { + if (*p == L'\\') + { + if (i == String2->Length - sizeof(WCHAR)) + { + s2 = NULL; + len2 = 0; + } + else + { + s2 = p + 1; + len2 = (String2->Length - i) / sizeof(WCHAR); + } + } + } + + /* Compare last path components */ + if (s1 && s2) + { + while (1) + { + c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0; + c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0; + if ((c1 == 0 && c2 == L'.') || (c1 == L'.' && c2 == 0)) + return(0); + if (!c1 || !c2 || c1 != c2) + return(c1 - c2); + } + } + } + + return(0); +} + + +PMODULE_OBJECT +LdrGetModuleObject(PUNICODE_STRING ModuleName) +{ + PMODULE_OBJECT Module; + PLIST_ENTRY Entry; + KIRQL Irql; + + DPRINT("LdrpGetModuleObject(%wZ) called\n", ModuleName); + + KeAcquireSpinLock(&ModuleListLock,&Irql); + + Entry = ModuleListHead.Flink; + while (Entry != &ModuleListHead) + { + Module = CONTAINING_RECORD(Entry, MODULE_OBJECT, ListEntry); + + DPRINT("Comparing %wZ and %wZ\n", + &Module->BaseName, + ModuleName); + + if (!LdrpCompareModuleNames(&Module->BaseName, ModuleName)) + { + DPRINT("Module %wZ\n", &Module->BaseName); + KeReleaseSpinLock(&ModuleListLock, Irql); + return(Module); + } + + Entry = Entry->Flink; + } + + KeReleaseSpinLock(&ModuleListLock, Irql); + + DPRINT("Could not find module '%wZ'\n", ModuleName); + + return(NULL); +} + + +/* ---------------------------------------------- PE Module support */ + +static NTSTATUS +LdrPEProcessModule(PVOID ModuleLoadBase, + PUNICODE_STRING FileName, + PMODULE_OBJECT *ModuleObject) +{ + unsigned int DriverSize, Idx; + ULONG RelocDelta, NumRelocs; + DWORD CurrentSize, TotalRelocs; + PVOID DriverBase; + PULONG PEMagic; + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_FILE_HEADER PEFileHeader; + PIMAGE_OPTIONAL_HEADER PEOptionalHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + PRELOCATION_DIRECTORY RelocDir; + PRELOCATION_ENTRY RelocEntry; + PMODULE_OBJECT LibraryModuleObject; + PMODULE_OBJECT CreatedModuleObject; + PVOID *ImportAddressList; + PULONG FunctionNameList; + PCHAR pName; + WORD Hint; + UNICODE_STRING ModuleName; + UNICODE_STRING NameString; + WCHAR NameBuffer[60]; + MODULE_TEXT_SECTION* ModuleTextSection; + NTSTATUS Status; + KIRQL Irql; + + DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase); + + /* Get header pointers */ + PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase; + PEMagic = (PULONG) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew); + PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew + sizeof(ULONG)); + PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)); + PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + + sizeof(IMAGE_OPTIONAL_HEADER)); + CHECKPOINT; + + /* Check file magic numbers */ + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC) + { + CPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic); + return STATUS_UNSUCCESSFUL; + } + if (PEDosHeader->e_lfanew == 0) + { + CPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew); + return STATUS_UNSUCCESSFUL; + } + if (*PEMagic != IMAGE_PE_MAGIC) + { + CPRINT("Incorrect PE magic: %08x\n", *PEMagic); + return STATUS_UNSUCCESSFUL; + } + if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386) + { + CPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine); + return STATUS_UNSUCCESSFUL; + } + CHECKPOINT; + + /* FIXME: if image is fixed-address load, then fail */ + + /* FIXME: check/verify OS version number */ + + DPRINT("OptionalHdrMagic:%04x LinkVersion:%d.%d\n", + PEOptionalHeader->Magic, + PEOptionalHeader->MajorLinkerVersion, + PEOptionalHeader->MinorLinkerVersion); + DPRINT("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint); + CHECKPOINT; + + /* Determine the size of the module */ + DriverSize = PEOptionalHeader->SizeOfImage; + DPRINT("DriverSize %x\n",DriverSize); + + /* Allocate a virtual section for the module */ + DriverBase = MmAllocateSection(DriverSize); + if (DriverBase == 0) + { + CPRINT("Failed to allocate a virtual section for driver\n"); + return STATUS_UNSUCCESSFUL; + } + DbgPrint("DriverBase for %wZ: %x\n", FileName, DriverBase); + CHECKPOINT; + /* Copy headers over */ + memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders); + CurrentSize = 0; + /* Copy image sections into virtual section */ + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + // Copy current section into current offset of virtual section + if (PESectionHeaders[Idx].Characteristics & + (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA)) + { + DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n", + PESectionHeaders[Idx].VirtualAddress + DriverBase); + memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase, + (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData), + PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData + ? PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize ); + } + else + { + DPRINT("PESectionHeaders[Idx].VirtualAddress + DriverBase %x\n", + PESectionHeaders[Idx].VirtualAddress + DriverBase); + memset(PESectionHeaders[Idx].VirtualAddress + DriverBase, + '\0', PESectionHeaders[Idx].Misc.VirtualSize); + + } + CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, + PEOptionalHeader->SectionAlignment); + + +// CurrentBase = (PVOID)((DWORD)CurrentBase + + // ROUND_UP(PESectionHeaders[Idx].SizeOfRawData.Misc.VirtualSize, + // PEOptionalHeader->SectionAlignment)); + } + + /* Perform relocation fixups */ + RelocDelta = (DWORD) DriverBase - PEOptionalHeader->ImageBase; + RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[ + IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); + DPRINT("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n", + DriverBase, + PEOptionalHeader->ImageBase, + RelocDelta); + DPRINT("RelocDir %x\n",RelocDir); +#if 1 + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + if (PESectionHeaders[Idx].VirtualAddress == (DWORD)RelocDir) + { + DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n", + PESectionHeaders[Idx].Name, + PESectionHeaders[Idx].PointerToRawData); + RelocDir = PESectionHeaders[Idx].PointerToRawData + + ModuleLoadBase; + CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize; + break; + } + } +#else + RelocDir = RelocDir + (ULONG)DriverBase; + CurrentSize = PEOptionalHeader->DataDirectory + [IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; +#endif + DPRINT("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize); + TotalRelocs = 0; + while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0) + { + NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) / + sizeof(WORD); +/* DPRINT("RelocDir at %08lx for VA %08lx with %08lx relocs\n", + RelocDir, + RelocDir->VirtualAddress, + NumRelocs);*/ + RelocEntry = (PRELOCATION_ENTRY) ((DWORD)RelocDir + + sizeof(RELOCATION_DIRECTORY)); + for (Idx = 0; Idx < NumRelocs; Idx++) + { + ULONG Offset; + ULONG Type; + PDWORD RelocItem; + + Offset = RelocEntry[Idx].TypeOffset & 0xfff; + Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf; + RelocItem = (PDWORD)(DriverBase + RelocDir->VirtualAddress + + Offset); +/* DPRINT(" reloc at %08lx %x %s old:%08lx new:%08lx\n", + RelocItem, + Type, + Type ? "HIGHLOW" : "ABS", + *RelocItem, + (*RelocItem) + RelocDelta); */ + if (Type == 3) + { + (*RelocItem) += RelocDelta; + } + else if (Type != 0) + { + CPRINT("Unknown relocation type %x at %x\n",Type, &Type); + return STATUS_UNSUCCESSFUL; + } + } + TotalRelocs += RelocDir->SizeOfBlock; + RelocDir = (PRELOCATION_DIRECTORY)((DWORD)RelocDir + + RelocDir->SizeOfBlock); +// DPRINT("TotalRelocs: %08lx CurrentSize: %08lx\n", TotalRelocs, CurrentSize); + } + + DPRINT("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n", + PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); + /* Perform import fixups */ + if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) + { + PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory; + + /* Process each import module */ + ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY) + ((DWORD)DriverBase + PEOptionalHeader-> + DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + DPRINT("Processeing import directory at %p\n", ImportModuleDirectory); + while (ImportModuleDirectory->dwRVAModuleName) + { + /* Check to make sure that import lib is kernel */ + pName = (PCHAR) DriverBase + + ImportModuleDirectory->dwRVAModuleName; + + RtlCreateUnicodeStringFromAsciiz(&ModuleName, pName); + DPRINT("Import module: %wZ\n", &ModuleName); + + LibraryModuleObject = LdrGetModuleObject(&ModuleName); + if (LibraryModuleObject == NULL) + { + CPRINT("Module '%wZ' not loaded yet\n", &ModuleName); + wcscpy(NameBuffer, L"\\SystemRoot\\system32\\drivers\\"); + wcscat(NameBuffer, ModuleName.Buffer); + RtlInitUnicodeString(&NameString, NameBuffer); + Status = LdrLoadModule(&NameString, &LibraryModuleObject); + if (!NT_SUCCESS(Status)) + { + CPRINT("Unknown import module: %wZ (Status %lx)\n", &ModuleName, Status); + return(Status); + } + } + /* Get the import address list */ + ImportAddressList = (PVOID *) ((DWORD)DriverBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + + /* Get the list of functions to import */ + if (ImportModuleDirectory->dwRVAFunctionNameList != 0) + { + FunctionNameList = (PULONG) ((DWORD)DriverBase + + ImportModuleDirectory->dwRVAFunctionNameList); + } + else + { + FunctionNameList = (PULONG) ((DWORD)DriverBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + } + /* Walk through function list and fixup addresses */ + while (*FunctionNameList != 0L) + { + if ((*FunctionNameList) & 0x80000000) // hint + { + pName = NULL; + + + Hint = (*FunctionNameList) & 0xffff; + } + else // hint-name + { + pName = (PCHAR)((DWORD)DriverBase + + *FunctionNameList + 2); + Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList); + } + DPRINT(" Hint:%04x Name:%s\n", Hint, pName); + + /* Fixup the current import symbol */ + if (LibraryModuleObject != NULL) + { + *ImportAddressList = LdrGetExportAddress(LibraryModuleObject, + pName, + Hint); + } + else + { + CPRINT("Unresolved kernel symbol: %s\n", pName); + return STATUS_UNSUCCESSFUL; + } + ImportAddressList++; + FunctionNameList++; + } + + RtlFreeUnicodeString(&ModuleName); + + ImportModuleDirectory++; + } + } + + /* Set the protections for the various parts of the driver */ + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + ULONG Characteristics = PESectionHeaders[Idx].Characteristics; + ULONG Length; + PVOID BaseAddress; + ULONG i; + Length = + max(PESectionHeaders[Idx].Misc.VirtualSize, + PESectionHeaders[Idx].SizeOfRawData); + BaseAddress = PESectionHeaders[Idx].VirtualAddress + DriverBase; + if (Characteristics & IMAGE_SECTION_CHAR_CODE && + !(Characteristics & IMAGE_SECTION_CHAR_WRITABLE || + Characteristics & IMAGE_SECTION_CHAR_DATA || + Characteristics & IMAGE_SECTION_CHAR_BSS)) + { + for (i = 0; i < PAGE_ROUND_DOWN(Length) / PAGE_SIZE; i++) + { + MmSetPageProtect(NULL, BaseAddress + (i * PAGE_SIZE), + PAGE_READONLY); + } + } + } + + /* Create the module */ + CreatedModuleObject = ExAllocatePool(NonPagedPool, sizeof(MODULE_OBJECT)); + if (CreatedModuleObject == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlZeroMemory(CreatedModuleObject, sizeof(MODULE_OBJECT)); + + /* Initialize ModuleObject data */ + CreatedModuleObject->Base = DriverBase; + CreatedModuleObject->Flags = MODULE_FLAG_PE; + + RtlCreateUnicodeString(&CreatedModuleObject->FullName, + FileName->Buffer); + LdrpBuildModuleBaseName(&CreatedModuleObject->BaseName, + &CreatedModuleObject->FullName); + + CreatedModuleObject->EntryPoint = + (PVOID)((DWORD)DriverBase + + PEOptionalHeader->AddressOfEntryPoint); + CreatedModuleObject->Length = DriverSize; + DPRINT("EntryPoint at %x\n", CreatedModuleObject->EntryPoint); + + CreatedModuleObject->Image.PE.FileHeader = + (PIMAGE_FILE_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG)); + + DPRINT("FileHeader at %x\n", CreatedModuleObject->Image.PE.FileHeader); + CreatedModuleObject->Image.PE.OptionalHeader = + (PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) + + sizeof(IMAGE_FILE_HEADER)); + DPRINT("OptionalHeader at %x\n", CreatedModuleObject->Image.PE.OptionalHeader); + CreatedModuleObject->Image.PE.SectionList = + (PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase + PEDosHeader->e_lfanew + sizeof(ULONG) + + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER)); + DPRINT("SectionList at %x\n", CreatedModuleObject->Image.PE.SectionList); + + /* Insert module */ + KeAcquireSpinLock(&ModuleListLock, &Irql); + InsertTailList(&ModuleListHead, + &CreatedModuleObject->ListEntry); + KeReleaseSpinLock(&ModuleListLock, Irql); + + + ModuleTextSection = ExAllocatePool(NonPagedPool, + sizeof(MODULE_TEXT_SECTION)); + assert(ModuleTextSection); + RtlZeroMemory(ModuleTextSection, sizeof(MODULE_TEXT_SECTION)); + ModuleTextSection->Base = (ULONG)DriverBase; + ModuleTextSection->Length = DriverSize; + ModuleTextSection->Name = ExAllocatePool(NonPagedPool, + (wcslen(CreatedModuleObject->BaseName.Buffer) + 1) * sizeof(WCHAR)); + wcscpy(ModuleTextSection->Name, CreatedModuleObject->BaseName.Buffer); + ModuleTextSection->OptionalHeader = + CreatedModuleObject->Image.PE.OptionalHeader; + InsertTailList(&ModuleTextListHead, &ModuleTextSection->ListEntry); + + CreatedModuleObject->TextSection = ModuleTextSection; + + *ModuleObject = CreatedModuleObject; + + DPRINT("Loading Module %wZ...\n", FileName); + + if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_GDB)) + { + DPRINT("Module %wZ loaded at 0x%.08x.\n", + FileName, CreatedModuleObject->Base); + } + + return STATUS_SUCCESS; +} + + +PVOID +LdrSafePEProcessModule(PVOID ModuleLoadBase, + PVOID DriverBase, + PVOID ImportModuleBase, + PULONG DriverSize) +{ + unsigned int Idx; + ULONG RelocDelta, NumRelocs; + ULONG CurrentSize, TotalRelocs; + PULONG PEMagic; + PIMAGE_DOS_HEADER PEDosHeader; + PIMAGE_FILE_HEADER PEFileHeader; + PIMAGE_OPTIONAL_HEADER PEOptionalHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + PRELOCATION_DIRECTORY RelocDir; + PRELOCATION_ENTRY RelocEntry; + PVOID *ImportAddressList; + PULONG FunctionNameList; + PCHAR pName; + USHORT Hint; + + ps("Processing PE Module at module base:%08lx\n", ModuleLoadBase); + + /* Get header pointers */ + PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase; + PEMagic = (PULONG) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew); + PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew + sizeof(ULONG)); + PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER)); + PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) ModuleLoadBase + + PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + + sizeof(IMAGE_OPTIONAL_HEADER)); + CHECKPOINT; + + /* Check file magic numbers */ + if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC) + { + return 0; + } + if (PEDosHeader->e_lfanew == 0) + { + return 0; + } + if (*PEMagic != IMAGE_PE_MAGIC) + { + return 0; + } + if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386) + { + return 0; + } + + ps("OptionalHdrMagic:%04x LinkVersion:%d.%d\n", + PEOptionalHeader->Magic, + PEOptionalHeader->MajorLinkerVersion, + PEOptionalHeader->MinorLinkerVersion); + ps("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint); + + /* Determine the size of the module */ + *DriverSize = PEOptionalHeader->SizeOfImage; + ps("DriverSize %x\n",*DriverSize); + + /* Copy headers over */ + if (DriverBase != ModuleLoadBase) + { + memcpy(DriverBase, ModuleLoadBase, PEOptionalHeader->SizeOfHeaders); + } + + ps("Hdr: 0x%X\n", (ULONG)PEOptionalHeader); + ps("Hdr->SizeOfHeaders: 0x%X\n", (ULONG)PEOptionalHeader->SizeOfHeaders); + ps("FileHdr->NumberOfSections: 0x%X\n", (ULONG)PEFileHeader->NumberOfSections); + + /* Ntoskrnl.exe need no relocation fixups since it is linked to run at the same + address as it is mapped */ + if (DriverBase != ModuleLoadBase) + { + CurrentSize = 0; + + /* Copy image sections into virtual section */ + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + // Copy current section into current offset of virtual section + if (PESectionHeaders[Idx].Characteristics & + (IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA)) + { + //ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n", + //PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase); + memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase, + (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData), + PESectionHeaders[Idx].Misc.VirtualSize > PESectionHeaders[Idx].SizeOfRawData ? + PESectionHeaders[Idx].SizeOfRawData : PESectionHeaders[Idx].Misc.VirtualSize ); + } + else + { + ps("PESectionHeaders[Idx].VirtualAddress (%X) + DriverBase %x\n", + PESectionHeaders[Idx].VirtualAddress, PESectionHeaders[Idx].VirtualAddress + DriverBase); + memset(PESectionHeaders[Idx].VirtualAddress + DriverBase, + '\0', + PESectionHeaders[Idx].Misc.VirtualSize); + } + CurrentSize += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, + PEOptionalHeader->SectionAlignment); + } + + /* Perform relocation fixups */ + RelocDelta = (ULONG) DriverBase - PEOptionalHeader->ImageBase; + RelocDir = (PRELOCATION_DIRECTORY)(PEOptionalHeader->DataDirectory[ + IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); + ps("DrvrBase:%08lx ImgBase:%08lx RelocDelta:%08lx\n", + DriverBase, + PEOptionalHeader->ImageBase, + RelocDelta); + ps("RelocDir %x\n",RelocDir); + + for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++) + { + if (PESectionHeaders[Idx].VirtualAddress == (ULONG)RelocDir) + { + DPRINT("Name %.8s PESectionHeader[Idx].PointerToRawData %x\n", + PESectionHeaders[Idx].Name, + PESectionHeaders[Idx].PointerToRawData); + RelocDir = PESectionHeaders[Idx].PointerToRawData + ModuleLoadBase; + CurrentSize = PESectionHeaders[Idx].Misc.VirtualSize; + break; + } + } + + ps("RelocDir %08lx CurrentSize %08lx\n", RelocDir, CurrentSize); + + TotalRelocs = 0; + while (TotalRelocs < CurrentSize && RelocDir->SizeOfBlock != 0) + { + NumRelocs = (RelocDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) / + sizeof(USHORT); + RelocEntry = (PRELOCATION_ENTRY)((ULONG)RelocDir + + sizeof(RELOCATION_DIRECTORY)); + for (Idx = 0; Idx < NumRelocs; Idx++) + { + ULONG Offset; + ULONG Type; + PDWORD RelocItem; + + Offset = RelocEntry[Idx].TypeOffset & 0xfff; + Type = (RelocEntry[Idx].TypeOffset >> 12) & 0xf; + RelocItem = (PULONG)(DriverBase + RelocDir->VirtualAddress + Offset); + if (Type == 3) + { + (*RelocItem) += RelocDelta; + } + else if (Type != 0) + { + CPRINT("Unknown relocation type %x at %x\n",Type, &Type); + return(0); + } + } + TotalRelocs += RelocDir->SizeOfBlock; + RelocDir = (PRELOCATION_DIRECTORY)((ULONG)RelocDir + + RelocDir->SizeOfBlock); + } + + ps("PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] %x\n", + PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + .VirtualAddress); + } + + /* Perform import fixups */ + if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) + { + PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory; + + /* Process each import module */ + ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY) + ((ULONG)DriverBase + PEOptionalHeader-> + DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + ps("Processeing import directory at %p\n", ImportModuleDirectory); + + /* Check to make sure that import lib is kernel */ + pName = (PCHAR)DriverBase + ImportModuleDirectory->dwRVAModuleName; + + ps("Import module: %s\n", pName); + + /* Get the import address list */ + ImportAddressList = (PVOID *)((ULONG)DriverBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + + ps(" ImportModuleDirectory->dwRVAFunctionAddressList: 0x%X\n", + ImportModuleDirectory->dwRVAFunctionAddressList); + ps(" ImportAddressList: 0x%X\n", ImportAddressList); + + /* Get the list of functions to import */ + if (ImportModuleDirectory->dwRVAFunctionNameList != 0) + { + ps("Using function name list.\n"); + + FunctionNameList = (PULONG)((ULONG)DriverBase + + ImportModuleDirectory->dwRVAFunctionNameList); + } + else + { + ps("Using function address list.\n"); + + FunctionNameList = (PULONG)((ULONG)DriverBase + + ImportModuleDirectory->dwRVAFunctionAddressList); + } + + /* Walk through function list and fixup addresses */ + while (*FunctionNameList != 0L) + { + if ((*FunctionNameList) & 0x80000000) + { + /* Hint */ + pName = NULL; + Hint = (*FunctionNameList) & 0xffff; + } + else + { + /* Hint name */ + pName = (PCHAR)((ULONG)DriverBase + *FunctionNameList + 2); + Hint = *(PWORD)((ULONG)DriverBase + *FunctionNameList); + } + //ps(" Hint:%04x Name:%s(0x%X)(%x)\n", Hint, pName, pName, ImportAddressList); + + *ImportAddressList = LdrSafePEGetExportAddress(ImportModuleBase, + pName, + Hint); + + ImportAddressList++; + FunctionNameList++; + } + } + + ps("Finished importing.\n"); + + return(0); +} + + +static PVOID +LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject, + PCHAR Name, + USHORT Hint) +{ + PIMAGE_EXPORT_DIRECTORY ExportDir; + ULONG ExportDirSize; + USHORT Idx; + PVOID ExportAddress; + PWORD OrdinalList; + PDWORD FunctionList, NameList; + + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData(ModuleObject->Base, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportDirSize); + DPRINT("ExportDir %p ExportDirSize %lx\n", ExportDir, ExportDirSize); + if (ExportDir == NULL) + { + return NULL; + } + + FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ModuleObject->Base); + NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ModuleObject->Base); + OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ModuleObject->Base); + + ExportAddress = 0; + + if (Name != NULL) + { + for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++) + { +#if 0 + DPRINT(" Name:%s NameList[%d]:%s\n", + Name, + Idx, + (DWORD) ModuleObject->Base + NameList[Idx]); + +#endif + if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx]))) + { + ExportAddress = (PVOID) ((DWORD)ModuleObject->Base + + FunctionList[OrdinalList[Idx]]); + if (((ULONG)ExportAddress >= (ULONG)ExportDir) && + ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize)) + { + DPRINT("Forward: %s\n", (PCHAR)ExportAddress); + ExportAddress = LdrPEFixupForward((PCHAR)ExportAddress); + DPRINT("ExportAddress: %p\n", ExportAddress); + } + + break; + } + } + } + else /* use hint */ + { + ExportAddress = (PVOID) ((DWORD)ModuleObject->Base + + FunctionList[Hint - ExportDir->Base]); + } + + if (ExportAddress == NULL) + { + CPRINT("Export not found for %d:%s\n", + Hint, + Name != NULL ? Name : "(Ordinal)"); + KeBugCheck(0); + } + + return(ExportAddress); +} + + +static PVOID +LdrSafePEGetExportAddress(PVOID ImportModuleBase, + PCHAR Name, + USHORT Hint) +{ + USHORT Idx; + PVOID ExportAddress; + PWORD OrdinalList; + PDWORD FunctionList, NameList; + PIMAGE_EXPORT_DIRECTORY ExportDir; + ULONG ExportDirSize; + + static BOOLEAN EP = FALSE; + + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData(ImportModuleBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportDirSize); + + if (!EP) { + EP = TRUE; + ps("ExportDir %x\n", ExportDir); + } + + FunctionList = (PDWORD)((DWORD)ExportDir->AddressOfFunctions + ImportModuleBase); + NameList = (PDWORD)((DWORD)ExportDir->AddressOfNames + ImportModuleBase); + OrdinalList = (PWORD)((DWORD)ExportDir->AddressOfNameOrdinals + ImportModuleBase); + + ExportAddress = 0; + + if (Name != NULL) + { + for (Idx = 0; Idx < ExportDir->NumberOfNames; Idx++) + { + if (!strcmp(Name, (PCHAR) ((DWORD)ImportModuleBase + NameList[Idx]))) + { + ExportAddress = (PVOID) ((DWORD)ImportModuleBase + + FunctionList[OrdinalList[Idx]]); + break; + } + } + } + else /* use hint */ + { + ExportAddress = (PVOID) ((DWORD)ImportModuleBase + + + FunctionList[Hint - ExportDir->Base]); + } + + if (ExportAddress == 0) + { + ps("Export not found for %d:%s\n", + Hint, + Name != NULL ? Name : "(Ordinal)"); + KeBugCheck(0); + } + return ExportAddress; +} + + +static PVOID +LdrPEFixupForward(PCHAR ForwardName) +{ + CHAR NameBuffer[128]; + UNICODE_STRING ModuleName; + PCHAR p; + PMODULE_OBJECT ModuleObject; + + DPRINT("LdrPEFixupForward (%s)\n", ForwardName); + + strcpy(NameBuffer, ForwardName); + p = strchr(NameBuffer, '.'); + if (p == NULL) + { + return NULL; + } + + *p = 0; + + DPRINT("Driver: %s Function: %s\n", NameBuffer, p+1); + + RtlCreateUnicodeStringFromAsciiz(&ModuleName, + NameBuffer); + ModuleObject = LdrGetModuleObject(&ModuleName); + RtlFreeUnicodeString(&ModuleName); + + DPRINT("ModuleObject: %p\n", ModuleObject); + + if (ModuleObject == NULL) + { + CPRINT("LdrPEFixupForward: failed to find module %s\n", NameBuffer); + return NULL; + } + + return(LdrPEGetExportAddress(ModuleObject, p+1, 0)); +} + +/* EOF */ diff --git a/ntoskrnl/ldr/resource.c b/ntoskrnl/ldr/resource.c new file mode 100644 index 0000000..2107463 --- /dev/null +++ b/ntoskrnl/ldr/resource.c @@ -0,0 +1,184 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ldr/resource.c + * PURPOSE: Resource loader + * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS STDCALL +LdrAccessResource(IN PVOID BaseAddress, + IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry, + OUT PVOID *Resource OPTIONAL, + OUT PULONG Size OPTIONAL) +{ + PIMAGE_SECTION_HEADER Section; + PIMAGE_NT_HEADERS NtHeader; + ULONG SectionRva; + ULONG SectionVa; + ULONG DataSize; + ULONG Offset = 0; + ULONG Data; + + Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_RESOURCE, + &DataSize); + if (Data == 0) + return STATUS_RESOURCE_DATA_NOT_FOUND; + + if ((ULONG)BaseAddress & 1) + { + /* loaded as ordinary file */ + NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL)); + Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + Section = RtlImageRvaToSection (NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); + if (Section == NULL) + { + return STATUS_RESOURCE_DATA_NOT_FOUND; + } + + if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) + { + SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress; + SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL); + Offset = SectionRva - SectionVa + Data - Section->VirtualAddress; + } + } + + if (Resource) + { + *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress); + } + + if (Size) + { + *Size = ResourceDataEntry->Size; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +LdrFindResource_U(PVOID BaseAddress, + PLDR_RESOURCE_INFO ResourceInfo, + ULONG Level, + PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry) +{ + PIMAGE_RESOURCE_DIRECTORY ResDir; + PIMAGE_RESOURCE_DIRECTORY ResBase; + PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry; + NTSTATUS Status = STATUS_SUCCESS; + ULONG EntryCount; + PWCHAR ws; + ULONG i; + ULONG Id; + + DPRINT ("LdrFindResource_U()\n"); + + /* Get the pointer to the resource directory */ + ResDir = (PIMAGE_RESOURCE_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, + TRUE, + IMAGE_DIRECTORY_ENTRY_RESOURCE, + &i); + if (ResDir == NULL) + { + return STATUS_RESOURCE_DATA_NOT_FOUND; + } + + DPRINT("ResourceDirectory: %x\n", (ULONG)ResDir); + + ResBase = ResDir; + + /* Let's go into resource tree */ + for (i = 0; i < Level; i++) + { + DPRINT("ResDir: %x\n", (ULONG)ResDir); + Id = ((PULONG)ResourceInfo)[i]; + EntryCount = ResDir->NumberOfNamedEntries; + ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1); + DPRINT("ResEntry %x\n", (ULONG)ResEntry); + if (Id & 0xFFFF0000) + { + /* Resource name is a unicode string */ + for (; EntryCount--; ResEntry++) + { + /* Scan entries for equal name */ + if (ResEntry->Name & 0x80000000) + { + ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF)); + if (!wcsncmp((PWCHAR)Id, ws + 1, *ws ) && + wcslen((PWCHAR)Id) == (int)*ws ) + { + goto found; + } + } + } + } + else + { + /* We use ID number instead of string */ + ResEntry += EntryCount; + EntryCount = ResDir->NumberOfIdEntries; + for (; EntryCount--; ResEntry++) + { + /* Scan entries for equal name */ + if (ResEntry->Name == Id) + { + DPRINT("ID entry found %x\n", Id); + goto found; + } + } + } + DPRINT("Error %lu\n", i); + + switch (i) + { + case 0: + return STATUS_RESOURCE_TYPE_NOT_FOUND; + + case 1: + return STATUS_RESOURCE_NAME_NOT_FOUND; + + case 2: + if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) + { + /* Use the first available language */ + ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1); + break; + } + return STATUS_RESOURCE_LANG_NOT_FOUND; + + case 3: + return STATUS_RESOURCE_DATA_NOT_FOUND; + + default: + return STATUS_INVALID_PARAMETER; + } +found:; + ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase + + (ResEntry->OffsetToData & 0x7FFFFFFF)); + } + DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir); + + if (ResourceDataEntry) + { + *ResourceDataEntry = (PVOID)ResDir; + } + + return Status; +} + +/* EOF */ diff --git a/ntoskrnl/ldr/rtl.c b/ntoskrnl/ldr/rtl.c new file mode 100644 index 0000000..4427372 --- /dev/null +++ b/ntoskrnl/ldr/rtl.c @@ -0,0 +1,235 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ldr/loader.c + * PURPOSE: Loader utilities + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + + +PIMAGE_NT_HEADERS STDCALL +RtlImageNtHeader (IN PVOID BaseAddress) +{ + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NTHeaders; + + DosHeader = (PIMAGE_DOS_HEADER)BaseAddress; + NTHeaders = (PIMAGE_NT_HEADERS)(BaseAddress + DosHeader->e_lfanew); + if ((DosHeader->e_magic != IMAGE_DOS_MAGIC) + || (DosHeader->e_lfanew == 0L) + || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC)) + { + return(NULL); + } + return(NTHeaders); +} + + +PVOID STDCALL +RtlImageDirectoryEntryToData (IN PVOID BaseAddress, + IN BOOLEAN ImageLoaded, + IN ULONG Directory, + OUT PULONG Size) +{ + PIMAGE_NT_HEADERS NtHeader; + PIMAGE_SECTION_HEADER SectionHeader; + ULONG Va; + ULONG Count; + + NtHeader = RtlImageNtHeader (BaseAddress); + if (NtHeader == NULL) + return NULL; + + if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes) + return NULL; + + Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress; + if (Va == 0) + return NULL; + + if (Size) + *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size; + + if (ImageLoaded) + return (PVOID)(BaseAddress + Va); + + /* image mapped as ordinary file, we must find raw pointer */ + SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1); + Count = NtHeader->FileHeader.NumberOfSections; + while (Count--) + { + if (SectionHeader->VirtualAddress == Va) + return (PVOID)(BaseAddress + SectionHeader->PointerToRawData); + SectionHeader++; + } + + return NULL; +} + + +PIMAGE_SECTION_HEADER +STDCALL +RtlImageRvaToSection ( + PIMAGE_NT_HEADERS NtHeader, + PVOID BaseAddress, + ULONG Rva + ) +{ + PIMAGE_SECTION_HEADER Section; + ULONG Va; + ULONG Count; + + Count = NtHeader->FileHeader.NumberOfSections; + Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader + + NtHeader->FileHeader.SizeOfOptionalHeader); + while (Count) + { + Va = Section->VirtualAddress; + if ((Va <= Rva) && + (Rva < Va + Section->SizeOfRawData)) + return Section; + Section++; + } + return NULL; +} + + +ULONG +STDCALL +RtlImageRvaToVa ( + PIMAGE_NT_HEADERS NtHeader, + PVOID BaseAddress, + ULONG Rva, + PIMAGE_SECTION_HEADER *SectionHeader + ) +{ + PIMAGE_SECTION_HEADER Section = NULL; + + if (SectionHeader) + Section = *SectionHeader; + + if (Section == NULL || + Rva < Section->VirtualAddress || + Rva >= Section->VirtualAddress + Section->SizeOfRawData) + { + Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva); + if (Section == NULL) + return 0; + + if (SectionHeader) + *SectionHeader = Section; + } + + return (ULONG)(BaseAddress + + Rva + + Section->PointerToRawData - + Section->VirtualAddress); +} + +#define RVA(m, b) ((ULONG)b + m) + +NTSTATUS STDCALL +LdrGetProcedureAddress (IN PVOID BaseAddress, + IN PANSI_STRING Name, + IN ULONG Ordinal, + OUT PVOID *ProcedureAddress) +{ + PIMAGE_EXPORT_DIRECTORY ExportDir; + PUSHORT OrdinalPtr; + PULONG NamePtr; + PULONG AddressPtr; + ULONG i = 0; + + /* get the pointer to the export directory */ + ExportDir = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData (BaseAddress, TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, &i); + + if (!ExportDir || !i || !ProcedureAddress) + { + return(STATUS_INVALID_PARAMETER); + } + + AddressPtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfFunctions); + if (Name && Name->Length) + { + ULONG minn, maxn; + + /* by name */ + OrdinalPtr = + (PUSHORT)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals); + NamePtr = (PULONG)RVA(BaseAddress, ExportDir->AddressOfNames); + + minn = 0; maxn = ExportDir->NumberOfNames; + while (minn <= maxn) + { + ULONG mid; + LONG res; + + mid = (minn + maxn) / 2; + res = _strnicmp(Name->Buffer, (PCH)RVA(BaseAddress, NamePtr[mid]), + Name->Length); + if (res == 0) + { + *ProcedureAddress = + (PVOID)RVA(BaseAddress, AddressPtr[OrdinalPtr[mid]]); + return(STATUS_SUCCESS); + } + else if (res > 0) + { + maxn = mid - 1; + } + else + { + minn = mid + 1; + } + } + + for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++) + { + if (!_strnicmp(Name->Buffer, + (char*)(BaseAddress + *NamePtr), Name->Length)) + { + *ProcedureAddress = + (PVOID)((ULONG)BaseAddress + + (ULONG)AddressPtr[*OrdinalPtr]); + return STATUS_SUCCESS; + } + } + CPRINT("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name); + } + else + { + /* by ordinal */ + Ordinal &= 0x0000FFFF; + if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions) + { + *ProcedureAddress = + (PVOID)((ULONG)BaseAddress + + (ULONG)AddressPtr[Ordinal - ExportDir->Base]); + return STATUS_SUCCESS; + } + CPRINT("LdrGetProcedureAddress: Can't resolve symbol @%d\n", + Ordinal); + } + + return STATUS_PROCEDURE_NOT_FOUND; +} + +/* EOF */ diff --git a/ntoskrnl/ldr/sysdll.c b/ntoskrnl/ldr/sysdll.c new file mode 100644 index 0000000..11a8fa6 --- /dev/null +++ b/ntoskrnl/ldr/sysdll.c @@ -0,0 +1,288 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ldr/sysdll.c + * PURPOSE: Loaders for PE executables + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + * UPDATE HISTORY: + * DW 26/01/00 Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static PVOID SystemDllEntryPoint = NULL; +static PVOID SystemDllApcDispatcher = NULL; +static PVOID SystemDllCallbackDispatcher = NULL; +static PVOID SystemDllExceptionDispatcher = NULL; + +/* FUNCTIONS *****************************************************************/ + +PVOID LdrpGetSystemDllExceptionDispatcher(VOID) +{ + return(SystemDllExceptionDispatcher); +} + +PVOID LdrpGetSystemDllCallbackDispatcher(VOID) +{ + return(SystemDllCallbackDispatcher); +} + +PVOID LdrpGetSystemDllEntryPoint(VOID) +{ + return(SystemDllEntryPoint); +} + +PVOID LdrpGetSystemDllApcDispatcher(VOID) +{ + return(SystemDllApcDispatcher); +} + +NTSTATUS LdrpMapSystemDll(HANDLE ProcessHandle, + PVOID* LdrStartupAddr) +/* + * FUNCTION: LdrpMapSystemDll maps the system dll into the specified process + * address space and returns its startup address. + * PARAMETERS: + * ProcessHandle + * Points to the process to map the system dll into + * + * LdrStartupAddress + * Receives the startup address of the system dll on function + * completion + * + * RETURNS: Status + */ +{ + CHAR BlockBuffer [1024]; + DWORD ImageBase; + ULONG ImageSize; + NTSTATUS Status; + OBJECT_ATTRIBUTES FileObjectAttributes; + HANDLE FileHandle; + HANDLE NTDllSectionHandle; + UNICODE_STRING DllPathname = UNICODE_STRING_INITIALIZER(L"\\SystemRoot\\system32\\ntdll.dll"); + PIMAGE_DOS_HEADER DosHeader; + PIMAGE_NT_HEADERS NTHeaders; + PEPROCESS Process; + ANSI_STRING ProcedureName; + ULONG ViewSize; + IO_STATUS_BLOCK Iosb; + + /* + * Locate and open NTDLL to determine ImageBase + * and LdrStartup + */ + InitializeObjectAttributes(&FileObjectAttributes, + &DllPathname, + 0, + NULL, + NULL); + DPRINT("Opening NTDLL\n"); + Status = ZwOpenFile(&FileHandle, + FILE_ALL_ACCESS, + &FileObjectAttributes, + NULL, + FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NTDLL open failed (Status %x)\n", Status); + return Status; + } + Status = ZwReadFile(FileHandle, + 0, + 0, + 0, + &Iosb, + BlockBuffer, + sizeof(BlockBuffer), + 0, + 0); + if (!NT_SUCCESS(Status) || Iosb.Information != sizeof(BlockBuffer)) + { + DbgPrint("NTDLL header read failed (Status %x)\n", Status); + ZwClose(FileHandle); + return Status; + } + + /* + * FIXME: this will fail if the NT headers are + * more than 1024 bytes from start. + */ + DosHeader = (PIMAGE_DOS_HEADER) BlockBuffer; + NTHeaders = (PIMAGE_NT_HEADERS) (BlockBuffer + DosHeader->e_lfanew); + if ((DosHeader->e_magic != IMAGE_DOS_MAGIC) + || (DosHeader->e_lfanew == 0L) + || (*(PULONG) NTHeaders != IMAGE_PE_MAGIC)) + { + DbgPrint("NTDLL format invalid\n"); + ZwClose(FileHandle); + return(STATUS_UNSUCCESSFUL); + } + ImageBase = NTHeaders->OptionalHeader.ImageBase; + ImageSize = NTHeaders->OptionalHeader.SizeOfImage; + + /* + * Create a section for NTDLL + */ + DPRINT("Creating section\n"); + Status = ZwCreateSection(&NTDllSectionHandle, + SECTION_ALL_ACCESS, + NULL, + NULL, + PAGE_READWRITE, + SEC_IMAGE | SEC_COMMIT, + FileHandle); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NTDLL create section failed (Status %x)\n", Status); + ZwClose(FileHandle); + return(Status); + } + ZwClose(FileHandle); + + /* + * Map the NTDLL into the process + */ + ViewSize = 0; + ImageBase = 0; + Status = ZwMapViewOfSection(NTDllSectionHandle, + ProcessHandle, + (PVOID*)&ImageBase, + 0, + ViewSize, + NULL, + &ViewSize, + 0, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NTDLL map view of secion failed (Status %x)", Status); + ZwClose(NTDllSectionHandle); + return(Status); + } + + DPRINT("Referencing process\n"); + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_ALL_ACCESS, + PsProcessType, + KernelMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("ObReferenceObjectByProcess() failed (Status %x)\n", Status); + return(Status); + } + + DPRINT("Attaching to Process\n"); + KeAttachProcess(Process); + + /* + * retrieve ntdll's startup address + */ + if (SystemDllEntryPoint == NULL) + { + RtlInitAnsiString (&ProcedureName, + "LdrInitializeThunk"); + Status = LdrGetProcedureAddress ((PVOID)ImageBase, + &ProcedureName, + 0, + &SystemDllEntryPoint); + if (!NT_SUCCESS(Status)) + { + DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + KeDetachProcess(); + ObDereferenceObject(Process); + ZwClose(NTDllSectionHandle); + return (Status); + } + *LdrStartupAddr = SystemDllEntryPoint; + } + + /* + * Retrieve the offset of the APC dispatcher from NTDLL + */ + if (SystemDllApcDispatcher == NULL) + { + RtlInitAnsiString (&ProcedureName, + "KiUserApcDispatcher"); + Status = LdrGetProcedureAddress ((PVOID)ImageBase, + &ProcedureName, + 0, + &SystemDllApcDispatcher); + if (!NT_SUCCESS(Status)) + { + DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + KeDetachProcess(); + ObDereferenceObject(Process); + ZwClose(NTDllSectionHandle); + return (Status); + } + } + + /* + * Retrieve the offset of the exception dispatcher from NTDLL + */ + if (SystemDllExceptionDispatcher == NULL) + { + RtlInitAnsiString (&ProcedureName, + "KiUserExceptionDispatcher"); + Status = LdrGetProcedureAddress ((PVOID)ImageBase, + &ProcedureName, + 0, + &SystemDllExceptionDispatcher); + if (!NT_SUCCESS(Status)) + { + DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + KeDetachProcess(); + ObDereferenceObject(Process); + ZwClose(NTDllSectionHandle); + return (Status); + } + } + + /* + * Retrieve the offset of the callback dispatcher from NTDLL + */ + if (SystemDllCallbackDispatcher == NULL) + { + RtlInitAnsiString (&ProcedureName, + "KiUserCallbackDispatcher"); + Status = LdrGetProcedureAddress ((PVOID)ImageBase, + &ProcedureName, + 0, + &SystemDllCallbackDispatcher); + if (!NT_SUCCESS(Status)) + { + DbgPrint ("LdrGetProcedureAddress failed (Status %x)\n", Status); + KeDetachProcess(); + ObDereferenceObject(Process); + ZwClose(NTDllSectionHandle); + return (Status); + } + } + + KeDetachProcess(); + ObDereferenceObject(Process); + + ZwClose(NTDllSectionHandle); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ldr/userldr.c b/ntoskrnl/ldr/userldr.c new file mode 100644 index 0000000..3856b6e --- /dev/null +++ b/ntoskrnl/ldr/userldr.c @@ -0,0 +1,69 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ldr/sysdll.c + * PURPOSE: Loaders for PE executables + * PROGRAMMERS: Jean Michault + * Rex Jolliff (rex@lvcablemodem.com) + * UPDATE HISTORY: + * DW 26/01/00 Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS LdrpMapImage(HANDLE ProcessHandle, + HANDLE SectionHandle, + PVOID* ReturnedImageBase) +/* + * FUNCTION: LdrpMapImage maps a user-mode image into an address space + * PARAMETERS: + * ProcessHandle + * Points to the process to map the image into + * + * SectionHandle + * Points to the section to map + * + * RETURNS: Status + */ +{ + ULONG ViewSize; + PVOID ImageBase; + NTSTATUS Status; + + ViewSize = 0; + ImageBase = 0; + + Status = ZwMapViewOfSection(SectionHandle, + ProcessHandle, + (PVOID*)&ImageBase, + 0, + ViewSize, + NULL, + &ViewSize, + 0, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + CPRINT("Image map view of section failed (Status %x)", Status); + return(Status); + } + + *ReturnedImageBase = ImageBase; + + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/lpc/.cvsignore b/ntoskrnl/lpc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/lpc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/lpc/close.c b/ntoskrnl/lpc/close.c new file mode 100644 index 0000000..20283c8 --- /dev/null +++ b/ntoskrnl/lpc/close.c @@ -0,0 +1,98 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/close.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +VOID STDCALL +NiClosePort (PVOID ObjectBody, ULONG HandleCount) +{ + PEPORT Port = (PEPORT)ObjectBody; + LPC_MESSAGE Message; + + /* + * If the client has just closed its handle then tell the server what + * happened and disconnect this port. + */ + if (HandleCount == 0 && Port->State == EPORT_CONNECTED_CLIENT && + ObGetObjectPointerCount(Port) == 2) + { + Message.MessageSize = sizeof(LPC_MESSAGE); + Message.DataSize = 0; + EiReplyOrRequestPort (Port->OtherPort, + &Message, + LPC_PORT_CLOSED, + Port); + Port->OtherPort->OtherPort = NULL; + Port->OtherPort->State = EPORT_DISCONNECTED; + KeReleaseSemaphore( &Port->OtherPort->Semaphore, + IO_NO_INCREMENT, + 1, + FALSE ); + ObDereferenceObject (Port); + } + + /* + * If the server has closed all of its handles then disconnect the port, + * don't actually notify the client until it attempts an operation. + */ + if (HandleCount == 0 && Port->State == EPORT_CONNECTED_SERVER && + ObGetObjectPointerCount(Port) == 2) + { + Port->OtherPort->OtherPort = NULL; + Port->OtherPort->State = EPORT_DISCONNECTED; + ObDereferenceObject(Port->OtherPort); + } +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +VOID STDCALL +NiDeletePort (PVOID ObjectBody) +{ + // PEPORT Port = (PEPORT)ObjectBody; + + // DPRINT1("Deleting port %x\n", Port); +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/complete.c b/ntoskrnl/lpc/complete.c new file mode 100644 index 0000000..a28a9f1 --- /dev/null +++ b/ntoskrnl/lpc/complete.c @@ -0,0 +1,60 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/complete.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/*********************************************************************** + * NAME EXPORTED + * NtCompleteConnectPort@4 + * + * + */ +EXPORTED NTSTATUS STDCALL +NtCompleteConnectPort (HANDLE PortHandle) +{ + NTSTATUS Status; + PEPORT OurPort; + + DPRINT("NtCompleteConnectPort(PortHandle %x)\n", PortHandle); + + Status = ObReferenceObjectByHandle (PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&OurPort, + NULL); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + + OurPort->State = EPORT_CONNECTED_SERVER; + + KeReleaseSemaphore(&OurPort->OtherPort->Semaphore, IO_NO_INCREMENT, 1, + FALSE); + + ObDereferenceObject (OurPort); + + return (STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/connect.c b/ntoskrnl/lpc/connect.c new file mode 100644 index 0000000..4d02d3d --- /dev/null +++ b/ntoskrnl/lpc/connect.c @@ -0,0 +1,755 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/connect.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_LPC_CONNECT_MESSAGE TAG('L', 'P', 'C', 'C') + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +EiConnectPort(IN PEPORT* ConnectedPort, + IN PEPORT NamedPort, + IN PSECTION_OBJECT Section, + IN LARGE_INTEGER SectionOffset, + IN ULONG ViewSize, + OUT PVOID* ClientSendViewBase, + OUT PVOID* ServerSendViewBase, + OUT PULONG ReceiveViewSize, + OUT PVOID* ReceiveViewBase, + OUT PULONG MaximumMessageSize, + IN OUT PVOID ConnectData, + IN OUT PULONG ConnectDataLength) +{ + PEPORT_CONNECT_REQUEST_MESSAGE RequestMessage; + ULONG RequestConnectDataLength; + PEPORT OurPort; + PQUEUEDMESSAGE Reply; + PEPORT_CONNECT_REPLY_MESSAGE CReply; + NTSTATUS Status; + KIRQL oldIrql; + + if (ConnectDataLength == NULL) + { + RequestConnectDataLength = 0; + } + else + { + RequestConnectDataLength = *ConnectDataLength; + } + + /* + * Create a port to represent our side of the connection + */ + Status = ObCreateObject (NULL, + PORT_ALL_ACCESS, + NULL, + ExPortType, + (PVOID*)&OurPort); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + NiInitializePort(OurPort); + + /* + * Allocate a request message. + */ + RequestMessage = ExAllocatePool(NonPagedPool, + sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + + RequestConnectDataLength); + if (RequestMessage == NULL) + { + ObDereferenceObject(OurPort); + return(STATUS_NO_MEMORY); + } + + /* + * Initialize the request message. + */ + RequestMessage->MessageHeader.DataSize = + sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength - + sizeof(LPC_MESSAGE_HEADER); + RequestMessage->MessageHeader.MessageSize = + sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength; + DPRINT("RequestMessageSize %d\n", + RequestMessage->MessageHeader.MessageSize); + RequestMessage->MessageHeader.SharedSectionSize = 0; + RequestMessage->ConnectingProcess = PsGetCurrentProcess(); + ObReferenceObjectByPointer(RequestMessage->ConnectingProcess, + PROCESS_VM_OPERATION, + NULL, + KernelMode); + RequestMessage->SendSectionObject = (struct _SECTION_OBJECT*)Section; + RequestMessage->SendSectionOffset = SectionOffset; + RequestMessage->SendViewSize = ViewSize; + RequestMessage->ConnectDataLength = RequestConnectDataLength; + if (RequestConnectDataLength > 0) + { + memcpy(RequestMessage->ConnectData, ConnectData, + RequestConnectDataLength); + } + + /* + * Queue the message to the named port + */ + EiReplyOrRequestPort(NamedPort, + &RequestMessage->MessageHeader, + LPC_CONNECTION_REQUEST, + OurPort); + KeReleaseSemaphore(&NamedPort->Semaphore, IO_NO_INCREMENT, 1, FALSE); + ExFreePool(RequestMessage); + + /* + * Wait for them to accept our connection + */ + KeWaitForSingleObject(&OurPort->Semaphore, + UserRequest, + UserMode, + FALSE, + NULL); + + /* + * Dequeue the response + */ + KeAcquireSpinLock (&OurPort->Lock, &oldIrql); + Reply = EiDequeueMessagePort (OurPort); + KeReleaseSpinLock (&OurPort->Lock, oldIrql); + CReply = (PEPORT_CONNECT_REPLY_MESSAGE)&Reply->Message; + + /* + * Do some initial cleanup. + */ + ObDereferenceObject(PsGetCurrentProcess()); + + /* + * Check for connection refusal. + */ + if (CReply->MessageHeader.MessageType == LPC_CONNECTION_REFUSED) + { + ObDereferenceObject(OurPort); + ExFreePool(Reply); + /* + * FIXME: Check what NT does here. Giving the user data back on + * connect failure sounds reasonable; it probably wouldn't break + * anything anyway. + */ + if (ConnectDataLength != NULL) + { + *ConnectDataLength = CReply->ConnectDataLength; + memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength); + } + return(STATUS_PORT_CONNECTION_REFUSED); + } + + /* + * Otherwise we are connected. Copy data back to the client. + */ + *ServerSendViewBase = CReply->SendServerViewBase; + *ReceiveViewSize = CReply->ReceiveClientViewSize; + *ReceiveViewBase = CReply->ReceiveClientViewBase; + *MaximumMessageSize = CReply->MaximumMessageSize; + if (ConnectDataLength != NULL) + { + *ConnectDataLength = CReply->ConnectDataLength; + memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength); + } + + /* + * Create our view of the send section object. + */ + if (Section != NULL) + { + *ClientSendViewBase = 0; + Status = MmMapViewOfSection(Section, + PsGetCurrentProcess(), + ClientSendViewBase, + 0, + ViewSize, + &SectionOffset, + &ViewSize, + ViewUnmap, + 0 /* MEM_TOP_DOWN? */, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + /* FIXME: Cleanup here. */ + return(Status); + } + } + + /* + * Do the final initialization of our port. + */ + OurPort->State = EPORT_CONNECTED_CLIENT; + + /* + * Cleanup. + */ + ExFreePool(Reply); + *ConnectedPort = OurPort; + return(STATUS_SUCCESS); +} + +/********************************************************************** + * NAME EXPORTED + * NtConnectPort@32 + * + * DESCRIPTION + * Connect to a named port and wait for the other side to + * accept the connection. + * + * ARGUMENTS + * ConnectedPort + * PortName + * Qos + * WriteMap + * ReadMap + * MaxMessageSize + * ConnectInfo + * UserConnectInfoLength + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +NtConnectPort (PHANDLE UnsafeConnectedPortHandle, + PUNICODE_STRING PortName, + PSECURITY_QUALITY_OF_SERVICE Qos, + PLPC_SECTION_WRITE UnsafeWriteMap, + PLPC_SECTION_READ UnsafeReadMap, + PULONG UnsafeMaximumMessageSize, + PVOID UnsafeConnectData, + PULONG UnsafeConnectDataLength) +{ + HANDLE ConnectedPortHandle; + LPC_SECTION_WRITE WriteMap; + LPC_SECTION_READ ReadMap; + ULONG MaximumMessageSize; + PVOID ConnectData; + ULONG ConnectDataLength; + PSECTION_OBJECT SectionObject; + LARGE_INTEGER SectionOffset; + PEPORT ConnectedPort; + NTSTATUS Status; + PEPORT NamedPort; + + /* + * Copy in write map and partially validate. + */ + if (UnsafeWriteMap != NULL) + { + Status = MmCopyFromCaller(&WriteMap, UnsafeWriteMap, + sizeof(LPC_SECTION_WRITE)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (WriteMap.Length != sizeof(LPC_SECTION_WRITE)) + { + return(STATUS_INVALID_PARAMETER_4); + } + SectionOffset.QuadPart = WriteMap.SectionOffset; + } + else + { + WriteMap.SectionHandle = INVALID_HANDLE_VALUE; + } + + /* + * Handle connection data. + */ + if (UnsafeConnectData == NULL) + { + ConnectDataLength = 0; + ConnectData = NULL; + } + else + { + if (ExGetPreviousMode() == KernelMode) + { + ConnectDataLength = *UnsafeConnectDataLength; + ConnectData = UnsafeConnectData; + } + else + { + Status = MmCopyFromCaller(&ConnectDataLength, + UnsafeConnectDataLength, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength); + if (ConnectData == NULL && ConnectDataLength != 0) + { + return(STATUS_NO_MEMORY); + } + Status = MmCopyFromCaller(ConnectData, + UnsafeConnectData, + ConnectDataLength); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ConnectData); + return(Status); + } + } + } + + /* + * Reference the named port. + */ + Status = ObReferenceObjectByName (PortName, + 0, + NULL, + PORT_ALL_ACCESS, /* DesiredAccess */ + ExPortType, + UserMode, + NULL, + (PVOID*)&NamedPort); + if (!NT_SUCCESS(Status)) + { + if (KeGetPreviousMode() != KernelMode) + { + ExFreePool(ConnectData); + } + return(Status); + } + + /* + * Reference the send section object. + */ + if (WriteMap.SectionHandle != INVALID_HANDLE_VALUE) + { + Status = ObReferenceObjectByHandle(WriteMap.SectionHandle, + SECTION_MAP_READ | SECTION_MAP_WRITE, + MmSectionObjectType, + UserMode, + (PVOID*)&SectionObject, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(NamedPort); + if (KeGetPreviousMode() != KernelMode) + { + ExFreePool(ConnectData); + } + return(Status); + } + } + else + { + SectionObject = NULL; + } + + /* + * Do the connection establishment. + */ + Status = EiConnectPort(&ConnectedPort, + NamedPort, + SectionObject, + SectionOffset, + WriteMap.ViewSize, + &WriteMap.ViewBase, + &WriteMap.TargetViewBase, + &ReadMap.ViewSize, + &ReadMap.ViewBase, + &MaximumMessageSize, + ConnectData, + &ConnectDataLength); + if (!NT_SUCCESS(Status)) + { + /* FIXME: Again, check what NT does here. */ + if (UnsafeConnectDataLength != NULL) + { + if (ExGetPreviousMode() != KernelMode) + { + MmCopyToCaller(UnsafeConnectData, ConnectData, + ConnectDataLength); + ExFreePool(ConnectData); + } + MmCopyToCaller(UnsafeConnectDataLength, &ConnectDataLength, + sizeof(ULONG)); + } + return(Status); + } + + /* + * Do some initial cleanup. + */ + if (SectionObject != NULL) + { + ObDereferenceObject(SectionObject); + SectionObject = NULL; + } + ObDereferenceObject(NamedPort); + NamedPort = NULL; + + /* + * Copy the data back to the caller. + */ + if (ExGetPreviousMode() != KernelMode) + { + if (UnsafeConnectDataLength != NULL) + { + if (ExGetPreviousMode() != KernelMode) + { + Status = MmCopyToCaller(UnsafeConnectData, ConnectData, + ConnectDataLength); + ExFreePool(ConnectData); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + Status = MmCopyToCaller(UnsafeConnectDataLength, &ConnectDataLength, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + } + Status = ObInsertObject(ConnectedPort, + NULL, + PORT_ALL_ACCESS, + 0, + NULL, + &ConnectedPortHandle); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Status = MmCopyToCaller(UnsafeConnectedPortHandle, &ConnectedPortHandle, + sizeof(HANDLE)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (UnsafeWriteMap != NULL) + { + Status = MmCopyToCaller(UnsafeWriteMap, &WriteMap, + sizeof(LPC_SECTION_WRITE)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + if (UnsafeReadMap != NULL) + { + Status = MmCopyToCaller(UnsafeReadMap, &ReadMap, + sizeof(LPC_SECTION_READ)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + if (UnsafeMaximumMessageSize != NULL) + { + Status = MmCopyToCaller(UnsafeMaximumMessageSize, + &MaximumMessageSize, + sizeof(LPC_SECTION_WRITE)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + + /* + * All done. + */ + ObDereferenceObject(ConnectedPort); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * NtAcceptConnectPort@24 + * + * DESCRIPTION + * + * ARGUMENTS + * ServerPortHandle + * NamedPortHandle + * LpcMessage + * AcceptIt + * WriteMap + * ReadMap + * + * RETURN VALUE + * + */ +EXPORTED NTSTATUS STDCALL +NtAcceptConnectPort (PHANDLE ServerPortHandle, + HANDLE NamedPortHandle, + PLPC_MESSAGE LpcMessage, + BOOLEAN AcceptIt, + PLPC_SECTION_WRITE WriteMap, + PLPC_SECTION_READ ReadMap) +{ + NTSTATUS Status; + PEPORT NamedPort; + PEPORT OurPort = NULL; + PQUEUEDMESSAGE ConnectionRequest; + KIRQL oldIrql; + PEPORT_CONNECT_REQUEST_MESSAGE CRequest; + PEPORT_CONNECT_REPLY_MESSAGE CReply; + + CReply = ExAllocatePool(NonPagedPool, + sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize); + if (CReply == NULL) + { + return(STATUS_NO_MEMORY); + } + + Status = ObReferenceObjectByHandle(NamedPortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&NamedPort, + NULL); + if (!NT_SUCCESS(Status)) + { + ExFreePool(CReply); + return (Status); + } + + /* + * Create a port object for our side of the connection + */ + if (AcceptIt == 1) + { + Status = ObCreateObject(ServerPortHandle, + PORT_ALL_ACCESS, + NULL, + ExPortType, + (PVOID*)&OurPort); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(NamedPort); + return(Status); + } + NiInitializePort(OurPort); + } + + /* + * Dequeue the connection request + */ + KeAcquireSpinLock(&NamedPort->Lock, &oldIrql); + ConnectionRequest = EiDequeueConnectMessagePort (NamedPort); + KeReleaseSpinLock(&NamedPort->Lock, oldIrql); + CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message); + + /* + * Prepare the reply. + */ + if (LpcMessage != NULL) + { + memcpy(&CReply->MessageHeader, LpcMessage, sizeof(LPC_MESSAGE_HEADER)); + memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1), + LpcMessage->DataSize); + CReply->MessageHeader.MessageSize = + sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize; + CReply->MessageHeader.DataSize = CReply->MessageHeader.MessageSize - + sizeof(LPC_MESSAGE_HEADER); + CReply->ConnectDataLength = LpcMessage->DataSize; + } + else + { + CReply->MessageHeader.MessageSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE); + CReply->MessageHeader.DataSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE) - + sizeof(LPC_MESSAGE_HEADER); + CReply->ConnectDataLength = 0; + } + if (AcceptIt != 1) + { + EiReplyOrRequestPort(ConnectionRequest->Sender, + &CReply->MessageHeader, + LPC_CONNECTION_REFUSED, + NamedPort); + KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore, + IO_NO_INCREMENT, + 1, + FALSE); + ObDereferenceObject(ConnectionRequest->Sender); + ExFreePool(ConnectionRequest); + ExFreePool(CReply); + ObDereferenceObject(NamedPort); + return (STATUS_SUCCESS); + } + + /* + * Prepare the connection. + */ + if (WriteMap != NULL) + { + PSECTION_OBJECT SectionObject; + LARGE_INTEGER SectionOffset; + + Status = ObReferenceObjectByHandle(WriteMap->SectionHandle, + SECTION_MAP_READ | SECTION_MAP_WRITE, + MmSectionObjectType, + UserMode, + (PVOID*)&SectionObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + SectionOffset.QuadPart = WriteMap->SectionOffset; + WriteMap->TargetViewBase = 0; + CReply->ReceiveClientViewSize = WriteMap->ViewSize; + Status = MmMapViewOfSection(SectionObject, + CRequest->ConnectingProcess, + &WriteMap->TargetViewBase, + 0, + CReply->ReceiveClientViewSize, + &SectionOffset, + &CReply->ReceiveClientViewSize, + ViewUnmap, + 0 /* MEM_TOP_DOWN? */, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + WriteMap->ViewBase = 0; + Status = MmMapViewOfSection(SectionObject, + PsGetCurrentProcess(), + &WriteMap->ViewBase, + 0, + WriteMap->ViewSize, + &SectionOffset, + &WriteMap->ViewSize, + ViewUnmap, + 0 /* MEM_TOP_DOWN? */, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + ObDereferenceObject(SectionObject); + } + if (ReadMap != NULL && CRequest->SendSectionObject != NULL) + { + LARGE_INTEGER SectionOffset; + + SectionOffset = CRequest->SendSectionOffset; + ReadMap->ViewSize = CRequest->SendViewSize; + ReadMap->ViewBase = 0; + Status = MmMapViewOfSection(CRequest->SendSectionObject, + PsGetCurrentProcess(), + &ReadMap->ViewBase, + 0, + CRequest->SendViewSize, + &SectionOffset, + &CRequest->SendViewSize, + ViewUnmap, + 0 /* MEM_TOP_DOWN? */, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + + /* + * Finish the reply. + */ + if (ReadMap != NULL) + { + CReply->SendServerViewBase = ReadMap->ViewBase; + } + else + { + CReply->SendServerViewBase = 0; + } + if (WriteMap != NULL) + { + CReply->ReceiveClientViewBase = WriteMap->TargetViewBase; + } + CReply->MaximumMessageSize = 0x148; + + + /* + * Connect the two ports + */ + OurPort->OtherPort = ConnectionRequest->Sender; + OurPort->OtherPort->OtherPort = OurPort; + EiReplyOrRequestPort(ConnectionRequest->Sender, + (PLPC_MESSAGE)CReply, + LPC_REPLY, + OurPort); + ExFreePool(ConnectionRequest); + + ObDereferenceObject(OurPort); + ObDereferenceObject(NamedPort); + + return (STATUS_SUCCESS); +} + +/********************************************************************** + * NAME EXPORTED + * NtSecureConnectPort@36 + * + * DESCRIPTION + * Connect to a named port and wait for the other side to + * accept the connection. Possibly verify that the server + * matches the ServerSid (trusted server). + * Present in w2k+. + * + * ARGUMENTS + * ConnectedPort + * PortName + * Qos + * WriteMap + * ServerSid + * ReadMap + * MaxMessageSize + * ConnectInfo + * UserConnectInfoLength + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +NtSecureConnectPort (OUT PHANDLE ConnectedPort, + IN PUNICODE_STRING PortName, + IN PSECURITY_QUALITY_OF_SERVICE Qos, + IN OUT PLPC_SECTION_WRITE WriteMap OPTIONAL, + IN PSID ServerSid OPTIONAL, + IN OUT PLPC_SECTION_READ ReadMap OPTIONAL, + OUT PULONG MaxMessageSize OPTIONAL, + IN OUT PVOID ConnectInfo OPTIONAL, + IN OUT PULONG UserConnectInfoLength OPTIONAL) +{ + return (STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/ntoskrnl/lpc/create.c b/ntoskrnl/lpc/create.c new file mode 100644 index 0000000..2ae22a6 --- /dev/null +++ b/ntoskrnl/lpc/create.c @@ -0,0 +1,178 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/create.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +STATIC NTSTATUS STDCALL +VerifyCreateParameters (IN PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectInfoLength, + IN ULONG MaxDataLength, + IN ULONG Reserved) +{ + if (NULL == PortHandle) + { + return (STATUS_INVALID_PARAMETER_1); + } + if (NULL == ObjectAttributes) + { + return (STATUS_INVALID_PARAMETER_2); + } + if ((ObjectAttributes->Attributes & OBJ_OPENLINK) + || (ObjectAttributes->Attributes & OBJ_OPENIF) + || (ObjectAttributes->Attributes & OBJ_EXCLUSIVE) + || (ObjectAttributes->Attributes & OBJ_PERMANENT) + || (ObjectAttributes->Attributes & OBJ_INHERIT)) + { + return (STATUS_INVALID_PORT_ATTRIBUTES); + } + if (MaxConnectInfoLength > 0x104) /* FIXME: use a macro! */ + { + return (STATUS_INVALID_PARAMETER_3); + } + if (MaxDataLength > 0x148) /* FIXME: use a macro! */ + { + return (STATUS_INVALID_PARAMETER_4); + } + /* FIXME: some checking is done also on Reserved */ + return (STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NiCreatePort (PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + if (RemainingPath == NULL) + { + return (STATUS_SUCCESS); + } + + if (wcschr(RemainingPath+1, '\\') != NULL) + { + return (STATUS_UNSUCCESSFUL); + } + + return (STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * NtCreatePort@20 + * + * DESCRIPTION + * + * ARGUMENTS + * PortHandle, + * ObjectAttributes, + * MaxConnectInfoLength, + * MaxDataLength, + * Reserved + * + * RETURN VALUE + * + */ +EXPORTED NTSTATUS STDCALL +NtCreatePort (PHANDLE PortHandle, + POBJECT_ATTRIBUTES ObjectAttributes, + ULONG MaxConnectInfoLength, + ULONG MaxDataLength, + ULONG Reserved) +{ + PEPORT Port; + NTSTATUS Status; + + DPRINT("NtCreatePort() Name %x\n", ObjectAttributes->ObjectName->Buffer); + + /* Verify parameters */ + Status = VerifyCreateParameters (PortHandle, + ObjectAttributes, + MaxConnectInfoLength, + MaxDataLength, + Reserved); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + /* Ask Ob to create the object */ + Status = ObCreateObject (PortHandle, + PORT_ALL_ACCESS, + ObjectAttributes, + ExPortType, + (PVOID*)&Port); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + + Status = NiInitializePort (Port); + Port->MaxConnectInfoLength = 260; /* FIXME: use a macro! */ + Port->MaxDataLength = 328; /* FIXME: use a macro! */ + + ObDereferenceObject (Port); + + return (Status); +} + +/********************************************************************** + * NAME EXPORTED + * NtCreateWaitablePort@20 + * + * DESCRIPTION + * Waitable ports can be connected to with NtSecureConnectPort. + * No port interface can be used with waitable ports but + * NtReplyWaitReceivePort and NtReplyWaitReceivePortEx. + * Present only in w2k+. + * + * ARGUMENTS + * PortHandle, + * ObjectAttributes, + * MaxConnectInfoLength, + * MaxDataLength, + * Reserved + * + * RETURN VALUE + * + */ +EXPORTED NTSTATUS STDCALL +NtCreateWaitablePort (OUT PHANDLE PortHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG MaxConnectInfoLength, + IN ULONG MaxDataLength, + IN ULONG Reserved) +{ + NTSTATUS Status; + + /* Verify parameters */ + Status = VerifyCreateParameters (PortHandle, + ObjectAttributes, + MaxConnectInfoLength, + MaxDataLength, + Reserved); + if (STATUS_SUCCESS != Status) + { + return (Status); + } + /* TODO */ + return (STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/ntoskrnl/lpc/listen.c b/ntoskrnl/lpc/listen.c new file mode 100644 index 0000000..6995c22 --- /dev/null +++ b/ntoskrnl/lpc/listen.c @@ -0,0 +1,79 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/listen.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * NtListenPort@8 + * + * DESCRIPTION + * Listen on a named port and wait for a connection attempt. + * + * ARGUMENTS + * PortHandle [IN] LPC port to listen on. + * + * ConnectMsg [IN] User provided storage for a + * possible connection request LPC message. + * + * RETURN VALUE + * STATUS_SUCCESS if a connection request is received + * successfully; otherwise an error code. + * + * The buffer ConnectMessage is filled with the connection + * request message queued by NtConnectPort() in PortHandle. + * + * NOTE + * + */ +EXPORTED NTSTATUS STDCALL +NtListenPort (IN HANDLE PortHandle, + IN PLPC_MESSAGE ConnectMsg) +{ + NTSTATUS Status; + + /* + * Wait forever for a connection request. + */ + for (;;) + { + Status = NtReplyWaitReceivePort(PortHandle, + NULL, + NULL, + ConnectMsg); + /* + * Accept only LPC_CONNECTION_REQUEST requests. + * Drop any other message. + */ + if (!NT_SUCCESS(Status) || + LPC_CONNECTION_REQUEST == ConnectMsg->MessageType) + { + DPRINT("Got message (type %x)\n", LPC_CONNECTION_REQUEST); + break; + } + DPRINT("Got message (type %x)\n", ConnectMsg->MessageType); + } + + return (Status); +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/port.c b/ntoskrnl/lpc/port.c new file mode 100644 index 0000000..6ce2e3d --- /dev/null +++ b/ntoskrnl/lpc/port.c @@ -0,0 +1,131 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/port.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + * + * 2000-06-04 (ea) + * ntoskrnl/nt/port.c moved in ntoskrnl/lpc/port.c + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE ExPortType = NULL; +ULONG EiNextLpcMessageId = 0; + +static GENERIC_MAPPING ExpPortMapping = { + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE, + 0, + PORT_ALL_ACCESS}; + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS NiInitPort (VOID) +{ + ExPortType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlInitUnicodeStringFromLiteral(&ExPortType->TypeName,L"Port"); + + ExPortType->Tag = TAG('L', 'P', 'R', 'T'); + ExPortType->MaxObjects = ULONG_MAX; + ExPortType->MaxHandles = ULONG_MAX; + ExPortType->TotalObjects = 0; + ExPortType->TotalHandles = 0; + ExPortType->PagedPoolCharge = 0; + ExPortType->NonpagedPoolCharge = sizeof(EPORT); + ExPortType->Mapping = &ExpPortMapping; + ExPortType->Dump = NULL; + ExPortType->Open = NULL; + ExPortType->Close = NiClosePort; + ExPortType->Delete = NiDeletePort; + ExPortType->Parse = NULL; + ExPortType->Security = NULL; + ExPortType->QueryName = NULL; + ExPortType->OkayToClose = NULL; + ExPortType->Create = NiCreatePort; + ExPortType->DuplicationNotify = NULL; + + EiNextLpcMessageId = 0; + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME INTERNAL + * NiInitializePort + * + * DESCRIPTION + * Initialize the EPORT object attributes. The Port + * object enters the inactive state. + * + * ARGUMENTS + * Port Pointer to an EPORT object to initialize. + * + * RETURN VALUE + * STATUS_SUCCESS if initialization succedeed. An error code + * otherwise. + */ +NTSTATUS STDCALL +NiInitializePort (IN OUT PEPORT Port) +{ + memset (Port, 0, sizeof(EPORT)); + KeInitializeSpinLock (& Port->Lock); + KeInitializeSemaphore( &Port->Semaphore, 0, LONG_MAX ); + Port->OtherPort = NULL; + Port->QueueLength = 0; + Port->ConnectQueueLength = 0; + Port->State = EPORT_INACTIVE; + InitializeListHead (& Port->QueueListHead); + InitializeListHead (& Port->ConnectQueueListHead); + + return (STATUS_SUCCESS); +} + + +/* MISCELLANEA SYSTEM SERVICES */ + + +/********************************************************************** + * NAME SYSTEM + * NtImpersonateClientOfPort@8 + * + * DESCRIPTION + * + * ARGUMENTS + * PortHandle, + * ClientMessage + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +NtImpersonateClientOfPort (HANDLE PortHandle, + PLPC_MESSAGE ClientMessage) +{ + UNIMPLEMENTED; +} + + + +/* EOF */ diff --git a/ntoskrnl/lpc/query.c b/ntoskrnl/lpc/query.c new file mode 100644 index 0000000..f9197ba --- /dev/null +++ b/ntoskrnl/lpc/query.c @@ -0,0 +1,74 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/query.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * NtQueryInformationPort@20 + * + * DESCRIPTION + * + * ARGUMENTS + * PortHandle [IN] + * PortInformationClass [IN] + * PortInformation [OUT] + * PortInformationLength [IN] + * ReturnLength [OUT] + * + * RETURN VALUE + * STATUS_SUCCESS if the call succedeed. An error code + * otherwise. + * + * NOTES + * P. Dabak reports that this system service seems to return + * no information. + */ +EXPORTED NTSTATUS STDCALL +NtQueryInformationPort (IN HANDLE PortHandle, + IN CINT PortInformationClass, + OUT PVOID PortInformation, + IN ULONG PortInformationLength, + OUT PULONG ReturnLength) +{ + NTSTATUS Status; + PEPORT Port; + + Status = ObReferenceObjectByHandle (PortHandle, + PORT_ALL_ACCESS, /* AccessRequired */ + ExPortType, + UserMode, + (PVOID *) & Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtQueryInformationPort() = %x\n", Status); + return (Status); + } + /* + * FIXME: NT does nothing here! + */ + ObDereferenceObject (Port); + return STATUS_SUCCESS; +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/queue.c b/ntoskrnl/lpc/queue.c new file mode 100644 index 0000000..e081dd1 --- /dev/null +++ b/ntoskrnl/lpc/queue.c @@ -0,0 +1,88 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/queue.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +EiEnqueueMessagePort (IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message) +{ + InsertTailList (&Port->QueueListHead, + &Message->QueueListEntry); + Port->QueueLength++; +} + +VOID STDCALL +EiEnqueueMessageAtHeadPort (IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message) +{ + InsertTailList (&Port->QueueListHead, + &Message->QueueListEntry); + Port->QueueLength++; +} + +PQUEUEDMESSAGE STDCALL +EiDequeueMessagePort (IN OUT PEPORT Port) +{ + PQUEUEDMESSAGE Message; + PLIST_ENTRY entry; + + if (IsListEmpty(&Port->QueueListHead)) + { + return(NULL); + } + entry = RemoveHeadList (&Port->QueueListHead); + Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry); + Port->QueueLength--; + + return (Message); +} + + +VOID STDCALL +EiEnqueueConnectMessagePort (IN OUT PEPORT Port, + IN PQUEUEDMESSAGE Message) +{ + InsertTailList (&Port->ConnectQueueListHead, + &Message->QueueListEntry); + Port->ConnectQueueLength++; +} + + +PQUEUEDMESSAGE STDCALL +EiDequeueConnectMessagePort (IN OUT PEPORT Port) +{ + PQUEUEDMESSAGE Message; + PLIST_ENTRY entry; + + if (IsListEmpty(&Port->ConnectQueueListHead)) + { + return(NULL); + } + entry = RemoveHeadList (&Port->ConnectQueueListHead); + Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry); + Port->ConnectQueueLength--; + + return (Message); +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/receive.c b/ntoskrnl/lpc/receive.c new file mode 100644 index 0000000..1b37b20 --- /dev/null +++ b/ntoskrnl/lpc/receive.c @@ -0,0 +1,46 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/receive.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME SYSTEM + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + */ +NTSTATUS STDCALL +NtReadRequestData (HANDLE PortHandle, + PLPC_MESSAGE Message, + ULONG Index, + PVOID Buffer, + ULONG BufferLength, + PULONG Returnlength) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/reply.c b/ntoskrnl/lpc/reply.c new file mode 100644 index 0000000..04f850e --- /dev/null +++ b/ntoskrnl/lpc/reply.c @@ -0,0 +1,338 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/reply.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_LPC_MESSAGE TAG('L', 'P', 'C', 'M') + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +EiReplyOrRequestPort (IN PEPORT Port, + IN PLPC_MESSAGE LpcReply, + IN ULONG MessageType, + IN PEPORT Sender) +{ + KIRQL oldIrql; + PQUEUEDMESSAGE MessageReply; + + if (Port == NULL) + { + KeBugCheck(0); + } + + MessageReply = ExAllocatePoolWithTag(NonPagedPool, sizeof(QUEUEDMESSAGE), + TAG_LPC_MESSAGE); + MessageReply->Sender = Sender; + + if (LpcReply != NULL) + { + memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize); + } + + MessageReply->Message.Cid.UniqueProcess = PsGetCurrentProcessId(); + MessageReply->Message.Cid.UniqueThread = PsGetCurrentThreadId(); + MessageReply->Message.MessageType = MessageType; + MessageReply->Message.MessageId = InterlockedIncrement(&EiNextLpcMessageId); + + KeAcquireSpinLock(&Port->Lock, &oldIrql); + EiEnqueueMessagePort(Port, MessageReply); + KeReleaseSpinLock(&Port->Lock, oldIrql); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtReplyPort (IN HANDLE PortHandle, + IN PLPC_MESSAGE LpcReply) +{ + NTSTATUS Status; + PEPORT Port; + + DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, /* AccessRequired */ + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtReplyPort() = %x\n", Status); + return(Status); + } + + Status = EiReplyOrRequestPort(Port->OtherPort, + LpcReply, + LPC_REPLY, + Port); + KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE); + + ObDereferenceObject(Port); + + return(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * NtReplyWaitReceivePortEx + * + * DESCRIPTION + * Can be used with waitable ports. + * Present only in w2k+. + * + * ARGUMENTS + * PortHandle + * PortId + * LpcReply + * LpcMessage + * Timeout + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtReplyWaitReceivePortEx(IN HANDLE PortHandle, + OUT PULONG PortId, + IN PLPC_MESSAGE LpcReply, + OUT PLPC_MESSAGE LpcMessage, + IN PLARGE_INTEGER Timeout) +{ + NTSTATUS Status; + PEPORT Port; + KIRQL oldIrql; + PQUEUEDMESSAGE Request; + BOOLEAN Disconnected; + LARGE_INTEGER to; + + DPRINT("NtReplyWaitReceivePortEx(PortHandle %x, LpcReply %x, " + "LpcMessage %x)\n", PortHandle, LpcReply, LpcMessage); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status); + return(Status); + } + if( Port->State == EPORT_DISCONNECTED ) + { + /* If the port is disconnected, force the timeout to be 0 + * so we don't wait for new messages, because there won't be + * any, only try to remove any existing messages + */ + Disconnected = TRUE; + to.QuadPart = 0; + Timeout = &to; + } + else Disconnected = FALSE; + + /* + * Send the reply, only if port is connected + */ + if (LpcReply != NULL && !Disconnected) + { + Status = EiReplyOrRequestPort(Port->OtherPort, + LpcReply, + LPC_REPLY, + Port); + KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, + FALSE); + + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Port); + DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status); + return(Status); + } + } + + /* + * Want for a message to be received + */ + Status = KeWaitForSingleObject(&Port->Semaphore, + UserRequest, + UserMode, + FALSE, + Timeout); + if( Status == STATUS_TIMEOUT ) + { + /* + * if the port is disconnected, and there are no remaining messages, + * return STATUS_PORT_DISCONNECTED + */ + ObDereferenceObject(Port); + return(Disconnected ? STATUS_PORT_DISCONNECTED : STATUS_TIMEOUT); + } + + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status); + ObDereferenceObject(Port); + return(Status); + } + + /* + * Dequeue the message + */ + KeAcquireSpinLock(&Port->Lock, &oldIrql); + Request = EiDequeueMessagePort(Port); + + if (Request->Message.MessageType == LPC_CONNECTION_REQUEST) + { + LPC_MESSAGE_HEADER Header; + PEPORT_CONNECT_REQUEST_MESSAGE CRequest; + + CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)&Request->Message; + memcpy(&Header, &Request->Message, sizeof(LPC_MESSAGE_HEADER)); + Header.DataSize = CRequest->ConnectDataLength; + Header.MessageSize = Header.DataSize + sizeof(LPC_MESSAGE_HEADER); + Status = MmCopyToCaller(LpcMessage, &Header, sizeof(LPC_MESSAGE)); + if (!NT_SUCCESS(Status)) + { + Status = MmCopyToCaller((PVOID)(LpcMessage + 1), + CRequest->ConnectData, + CRequest->ConnectDataLength); + } + } + else + { + Status = MmCopyToCaller(LpcMessage, &Request->Message, + Request->Message.MessageSize); + } + if (!NT_SUCCESS(Status)) + { + /* + * Copying the message to the caller's buffer failed so + * undo what we did and return. + * FIXME: Also increment semaphore. + */ + EiEnqueueMessageAtHeadPort(Port, Request); + KeReleaseSpinLock(&Port->Lock, oldIrql); + ObDereferenceObject(Port); + return(Status); + } + if (Request->Message.MessageType == LPC_CONNECTION_REQUEST) + { + EiEnqueueConnectMessagePort(Port, Request); + KeReleaseSpinLock(&Port->Lock, oldIrql); + } + else + { + KeReleaseSpinLock(&Port->Lock, oldIrql); + ExFreePool(Request); + } + + /* + * Dereference the port + */ + ObDereferenceObject(Port); + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * NtReplyWaitReceivePort + * + * DESCRIPTION + * Can be used with waitable ports. + * + * ARGUMENTS + * PortHandle + * PortId + * LpcReply + * LpcMessage + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtReplyWaitReceivePort (IN HANDLE PortHandle, + OUT PULONG PortId, + IN PLPC_MESSAGE LpcReply, + OUT PLPC_MESSAGE LpcMessage) +{ + return(NtReplyWaitReceivePortEx (PortHandle, + PortId, + LpcReply, + LpcMessage, + NULL)); +} + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtReplyWaitReplyPort (HANDLE PortHandle, + PLPC_MESSAGE ReplyMessage) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/lpc/send.c b/ntoskrnl/lpc/send.c new file mode 100644 index 0000000..2b38132 --- /dev/null +++ b/ntoskrnl/lpc/send.c @@ -0,0 +1,317 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/lpc/send.c + * PURPOSE: Communication mechanism + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +LpcSendTerminationPort (IN PEPORT Port, + IN TIME CreationTime) +{ + NTSTATUS Status; + LPC_TERMINATION_MESSAGE Msg; + + Msg.CreationTime = CreationTime; + Status = LpcRequestPort (Port, &Msg.Header); + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +LpcSendDebugMessagePort (IN PEPORT Port, + IN PLPC_DBG_MESSAGE Message, + OUT PLPC_DBG_MESSAGE Reply) +{ + NTSTATUS Status; + KIRQL oldIrql; + PQUEUEDMESSAGE ReplyMessage; + + Status = EiReplyOrRequestPort(Port, + &Message->Header, + LPC_REQUEST, + Port); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Port); + return(Status); + } + KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE); + + /* + * Wait for a reply + */ + KeWaitForSingleObject(&Port->Semaphore, + UserRequest, + UserMode, + FALSE, + NULL); + + /* + * Dequeue the reply + */ + KeAcquireSpinLock(&Port->Lock, &oldIrql); + ReplyMessage = EiDequeueMessagePort(Port); + KeReleaseSpinLock(&Port->Lock, oldIrql); + memcpy(Reply, &ReplyMessage->Message, ReplyMessage->Message.MessageSize); + ExFreePool(ReplyMessage); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL LpcRequestPort (IN PEPORT Port, + IN PLPC_MESSAGE LpcMessage) +{ + NTSTATUS Status; + + DPRINT("LpcRequestPort(PortHandle %x LpcMessage %x)\n", Port, LpcMessage); + + Status = EiReplyOrRequestPort(Port, + LpcMessage, + LPC_DATAGRAM, + Port); + KeReleaseSemaphore( &Port->Semaphore, IO_NO_INCREMENT, 1, FALSE ); + + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle, + IN PLPC_MESSAGE LpcMessage) +{ + NTSTATUS Status; + PEPORT Port; + + DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle, + LpcMessage); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtRequestPort() = %x\n", Status); + return(Status); + } + + Status = LpcRequestPort(Port->OtherPort, + LpcMessage); + + ObDereferenceObject(Port); + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtRequestWaitReplyPort (IN HANDLE PortHandle, + PLPC_MESSAGE UnsafeLpcRequest, + PLPC_MESSAGE UnsafeLpcReply) +{ + NTSTATUS Status; + PEPORT Port; + PQUEUEDMESSAGE Message; + KIRQL oldIrql; + PLPC_MESSAGE LpcRequest; + USHORT LpcRequestMessageSize; + + DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, " + "LpcReply %x)\n", PortHandle, UnsafeLpcRequest, UnsafeLpcReply); + + Status = ObReferenceObjectByHandle(PortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&Port, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = MmCopyFromCaller(&LpcRequestMessageSize, + &UnsafeLpcRequest->MessageSize, + sizeof(USHORT)); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Port); + return(Status); + } + if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA)) + { + ObDereferenceObject(Port); + return(STATUS_PORT_MESSAGE_TOO_LONG); + } + LpcRequest = ExAllocatePool(NonPagedPool, LpcRequestMessageSize); + if (LpcRequest == NULL) + { + ObDereferenceObject(Port); + return(STATUS_NO_MEMORY); + } + Status = MmCopyFromCaller(LpcRequest, UnsafeLpcRequest, + LpcRequestMessageSize); + if (!NT_SUCCESS(Status)) + { + ExFreePool(LpcRequest); + ObDereferenceObject(Port); + return(Status); + } + LpcRequestMessageSize = LpcRequest->MessageSize; + if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA)) + { + ExFreePool(LpcRequest); + ObDereferenceObject(Port); + return(STATUS_PORT_MESSAGE_TOO_LONG); + } + if (LpcRequest->DataSize != (LpcRequest->MessageSize - sizeof(LPC_MESSAGE))) + { + ExFreePool(LpcRequest); + ObDereferenceObject(Port); + return(STATUS_PORT_MESSAGE_TOO_LONG); + } + + Status = EiReplyOrRequestPort(Port->OtherPort, + LpcRequest, + LPC_REQUEST, + Port); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Enqueue failed\n"); + ExFreePool(LpcRequest); + ObDereferenceObject(Port); + return(Status); + } + ExFreePool(LpcRequest); + KeReleaseSemaphore (&Port->OtherPort->Semaphore, IO_NO_INCREMENT, + 1, FALSE); + + /* + * Wait for a reply + */ + KeWaitForSingleObject(&Port->Semaphore, + UserRequest, + UserMode, + FALSE, + NULL); + + /* + * Dequeue the reply + */ + KeAcquireSpinLock(&Port->Lock, &oldIrql); + Message = EiDequeueMessagePort(Port); + KeReleaseSpinLock(&Port->Lock, oldIrql); + DPRINT("Message->Message.MessageSize %d\n", + Message->Message.MessageSize); + Status = MmCopyToCaller(UnsafeLpcReply, &Message->Message, + Message->Message.MessageSize); + ExFreePool(Message); + + ObDereferenceObject(Port); + + return(Status); +} + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle, + PLPC_MESSAGE Message, + ULONG Index, + PVOID Buffer, + ULONG BufferLength, + PULONG ReturnLength) +{ + UNIMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/mkconfig.c b/ntoskrnl/mkconfig.c new file mode 100644 index 0000000..56bb885 --- /dev/null +++ b/ntoskrnl/mkconfig.c @@ -0,0 +1,112 @@ +#include +#include +#include + +#define max(a, b) ((a) > (b) ? (a) : (b)) + +int +write_if_change(char* outbuf, char* filename) +{ + FILE* out; + unsigned int end; + char* cmpbuf; + unsigned int stat; + + out = fopen(filename, "rb"); + if (out == NULL) + { + out = fopen(filename, "wb"); + if (out == NULL) + { + fprintf(stderr, "Unable to create output file\n"); + return(1); + } + fputs(outbuf, out); + fclose(out); + return(0); + } + + fseek(out, 0, SEEK_END); + end = ftell(out); + cmpbuf = malloc(end); + if (cmpbuf == NULL) + { + fprintf(stderr, "Out of memory\n"); + fclose(out); + return(1); + } + + fseek(out, 0, SEEK_SET); + stat = fread(cmpbuf, 1, end, out); + if (stat != end) + { + fprintf(stderr, "Failed to read data\n"); + fclose(out); + return(1); + } + if (end == strlen(outbuf) && memcmp(cmpbuf, outbuf, end) == 0) + { + fclose(out); + return(0); + } + + fclose(out); + out = fopen(filename, "wb"); + if (out == NULL) + { + fprintf(stderr, "Unable to create output file\n"); + return(1); + } + + stat = fwrite(outbuf, 1, strlen(outbuf), out); + if (strlen(outbuf) != stat) + { + fprintf(stderr, "Unable to write output file\n"); + fclose(out); + return(1); + } + fclose(out); + return(0); +} + +int +main(int argc, char* argv[]) +{ + unsigned int i; + char* outbuf; + char* s; + char config[512]; + + if (argc == 1) + { + fprintf(stderr, "Not enough arguments\n"); + return(1); + } + + outbuf = malloc(256 * 1024); + if (outbuf == NULL) + { + fprintf(stderr, "Out of memory 1\n"); + return(1); + } + + s = outbuf; + s = s + sprintf(s, "/* Automatically generated, "); + s = s + sprintf(s, "Edit the Makefile to change configuration */\n"); + s = s + sprintf(s, "#ifndef __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H\n"); + s = s + sprintf(s, "#define __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H\n"); + strcpy(config, ""); + for (i = 2; i < argc; i++) + { + s = s + sprintf(s, "#define %s\n", argv[i]); + strcat(config, argv[i]); + if (i != (argc - 1)) + { + strcat(config, " "); + } + } + s = s + sprintf(s, "#define CONFIG \"%s\"\n", config); + s = s + sprintf(s, "#endif /* __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H */\n"); + + return(write_if_change(outbuf, argv[1])); +} diff --git a/ntoskrnl/mm/.cvsignore b/ntoskrnl/mm/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/mm/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/mm/anonmem.c b/ntoskrnl/mm/anonmem.c new file mode 100644 index 0000000..0737009 --- /dev/null +++ b/ntoskrnl/mm/anonmem.c @@ -0,0 +1,877 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/anonmem.c + * PURPOSE: Implementing anonymous memory. + * PROGRAMMER: David Welch + */ + +/* INCLUDE *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + PMM_PAGEOP PageOp) +{ + SWAPENTRY SwapEntry; + LARGE_INTEGER PhysicalAddress; + PMDL Mdl; + NTSTATUS Status; + + /* + * Check for paging out from a deleted virtual memory area. + */ + if (MemoryArea->DeleteInProgress) + { + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + PhysicalAddress = + MmGetPhysicalAddressForProcess(AddressSpace->Process, Address); + + /* + * Get that the page actually is dirty. + */ + if (!MmIsDirtyPage(MemoryArea->Process, Address)) + { + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * Speculatively set the mapping to clean. + */ + MmSetCleanPage(MemoryArea->Process, Address); + + /* + * If necessary, allocate an entry in the paging file for this page + */ + SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress); + if (SwapEntry == 0) + { + SwapEntry = MmAllocSwapPage(); + if (SwapEntry == 0) + { + MmSetDirtyPage(MemoryArea->Process, Address); + PageOp->Status = STATUS_PAGEFILE_QUOTA_EXCEEDED; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_PAGEFILE_QUOTA_EXCEEDED); + } + } + + /* + * Write the page to the pagefile + */ + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress); + Status = MmWriteToSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", + Status); + MmSetDirtyPage(MemoryArea->Process, Address); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Otherwise we have succeeded. + */ + MmSetSavedSwapEntryPage(PhysicalAddress, SwapEntry); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); +} + +NTSTATUS +MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + PMM_PAGEOP PageOp) +{ + PHYSICAL_ADDRESS PhysicalAddress; + BOOL WasDirty; + SWAPENTRY SwapEntry; + NTSTATUS Status; + PMDL Mdl; + + DPRINT("MmPageOutVirtualMemory(Address 0x%.8X) PID %d\n", + Address, MemoryArea->Process->UniqueProcessId); + + /* + * Check for paging out from a deleted virtual memory area. + */ + if (MemoryArea->DeleteInProgress) + { + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Disable the virtual mapping. + */ + MmDisableVirtualMapping(MemoryArea->Process, Address, + &WasDirty, &PhysicalAddress); + if (PhysicalAddress.QuadPart == 0) + { + KeBugCheck(0); + } + + /* + * Paging out non-dirty data is easy. + */ + if (!WasDirty) + { + MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL); + MmDeleteAllRmaps(PhysicalAddress, NULL, NULL); + if ((SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress)) != 0) + { + MmCreatePageFileMapping(MemoryArea->Process, Address, SwapEntry); + MmSetSavedSwapEntryPage(PhysicalAddress, 0); + } + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * If necessary, allocate an entry in the paging file for this page + */ + SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress); + if (SwapEntry == 0) + { + SwapEntry = MmAllocSwapPage(); + if (SwapEntry == 0) + { + MmShowOutOfSpaceMessagePagingFile(); + MmEnableVirtualMapping(MemoryArea->Process, Address); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + } + + /* + * Write the page to the pagefile + */ + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress); + Status = MmWriteToSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", + Status); + MmEnableVirtualMapping(MemoryArea->Process, Address); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Otherwise we have succeeded, free the page + */ + DPRINT("MM: Swapped out virtual memory page 0x%.8X!\n", PhysicalAddress); + MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL); + MmCreatePageFileMapping(MemoryArea->Process, Address, SwapEntry); + MmDeleteAllRmaps(PhysicalAddress, NULL, NULL); + MmSetSavedSwapEntryPage(PhysicalAddress, 0); + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); +} + +NTSTATUS +MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked) +/* + * FUNCTION: Move data into memory to satisfy a page not present fault + * ARGUMENTS: + * AddressSpace = Address space within which the fault occurred + * MemoryArea = The memory area within which the fault occurred + * Address = The absolute address of fault + * RETURNS: Status + * NOTES: This function is called with the address space lock held. + */ +{ + PHYSICAL_ADDRESS Page; + NTSTATUS Status; + PMM_REGION Region; + PMM_PAGEOP PageOp; + + /* + * There is a window between taking the page fault and locking the + * address space when another thread could load the page so we check + * that. + */ + if (MmIsPagePresent(NULL, Address)) + { + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + return(STATUS_SUCCESS); + } + + /* + * Check for the virtual memory area being deleted. + */ + if (MemoryArea->DeleteInProgress) + { + return(STATUS_UNSUCCESSFUL); + } + + /* + * Get the segment corresponding to the virtual address + */ + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + Address, NULL); + if (Region->Type == MEM_RESERVE) + { + return(STATUS_UNSUCCESSFUL); + } + + /* + * Get or create a page operation + */ + PageOp = MmGetPageOp(MemoryArea, (ULONG)PsGetCurrentProcessId(), + (PVOID)PAGE_ROUND_DOWN(Address), NULL, 0, + MM_PAGEOP_PAGEIN); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed"); + KeBugCheck(0); + } + + /* + * Check if someone else is already handling this fault, if so wait + * for them + */ + if (PageOp->Thread != PsGetCurrentThread()) + { + MmUnlockAddressSpace(AddressSpace); + Status = KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + /* + * Check for various strange conditions + */ + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op\n"); + KeBugCheck(0); + } + if (PageOp->Status == STATUS_PENDING) + { + DPRINT1("Woke for page op before completion\n"); + KeBugCheck(0); + } + /* + * If this wasn't a pagein then we need to restart the handling + */ + if (PageOp->OpType != MM_PAGEOP_PAGEIN) + { + MmLockAddressSpace(AddressSpace); + MmReleasePageOp(PageOp); + return(STATUS_MM_RESTART_OPERATION); + } + /* + * If the thread handling this fault has failed then we don't retry + */ + if (!NT_SUCCESS(PageOp->Status)) + { + MmLockAddressSpace(AddressSpace); + MmReleasePageOp(PageOp); + return(Status); + } + MmLockAddressSpace(AddressSpace); + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * Try to allocate a page + */ + Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); + if (Status == STATUS_NO_MEMORY) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + MmLockAddressSpace(AddressSpace); + } + + /* + * Handle swapped out pages. + */ + if (MmIsPageSwapEntry(NULL, Address)) + { + SWAPENTRY SwapEntry; + PMDL Mdl; + + MmDeletePageFileMapping(NULL, Address, &SwapEntry); + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&Page); + Status = MmReadFromSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + MmSetSavedSwapEntryPage(Page, SwapEntry); + } + + /* + * Set the page. If we fail because we are out of memory then + * try again + */ + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + MemoryArea->Attributes, + Page, + FALSE); + while (Status == STATUS_NO_MEMORY) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + MemoryArea->Attributes, + Page, + TRUE); + MmLockAddressSpace(AddressSpace); + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); + KeBugCheck(0); + return(Status); + } + + /* + * Add the page to the process's working set + */ + MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address)); + + /* + * Finish the operation + */ + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); +} + +VOID STATIC +MmModifyAttributes(PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, + ULONG RegionSize, + ULONG OldType, + ULONG OldProtect, + ULONG NewType, + ULONG NewProtect) +/* + * FUNCTION: Modify the attributes of a memory region + */ +{ + /* + * If we are switching a previously committed region to reserved then + * free any allocated pages within the region + */ + if (NewType == MEM_RESERVE && OldType == MEM_COMMIT) + { + ULONG i; + + for (i=0; i <= (RegionSize/PAGE_SIZE); i++) + { + LARGE_INTEGER PhysicalAddr; + + if (MmIsPageSwapEntry(AddressSpace->Process, + BaseAddress + (i * PAGE_SIZE))) + { + SWAPENTRY SwapEntry; + + MmDeletePageFileMapping(AddressSpace->Process, + BaseAddress + (i * PAGE_SIZE), + &SwapEntry); + MmFreeSwapPage(SwapEntry); + } + else + { + PhysicalAddr = MmGetPhysicalAddress(BaseAddress + (i*PAGE_SIZE)); + MmDeleteVirtualMapping(AddressSpace->Process, + BaseAddress + (i*PAGE_SIZE), + FALSE, NULL, NULL); + if (PhysicalAddr.QuadPart != 0) + { + SWAPENTRY SavedSwapEntry; + SavedSwapEntry = MmGetSavedSwapEntryPage(PhysicalAddr); + if (SavedSwapEntry != 0) + { + MmFreeSwapPage(SavedSwapEntry); + MmSetSavedSwapEntryPage(PhysicalAddr, 0); + } + MmDeleteRmap(PhysicalAddr, AddressSpace->Process, + BaseAddress + (i * PAGE_SIZE)); + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddr); + } + } + } + } + + /* + * If we are changing the protection attributes of a committed region then + * alter the attributes for any allocated pages within the region + */ + if (NewType == MEM_COMMIT && OldType == MEM_COMMIT && + OldProtect != NewProtect) + { + ULONG i; + + for (i=0; i <= (RegionSize/PAGE_SIZE); i++) + { + if (MmIsPagePresent(AddressSpace->Process, + BaseAddress + (i*PAGE_SIZE))) + { + MmSetPageProtect(AddressSpace->Process, + BaseAddress + (i*PAGE_SIZE), + NewProtect); + } + } + } +} + +NTSTATUS STDCALL +NtAllocateVirtualMemory(IN HANDLE ProcessHandle, + IN OUT PVOID* UBaseAddress, + IN ULONG ZeroBits, + IN OUT PULONG URegionSize, + IN ULONG AllocationType, + IN ULONG Protect) +/* + * FUNCTION: Allocates a block of virtual memory in the process address space + * ARGUMENTS: + * ProcessHandle = The handle of the process which owns the virtual memory + * BaseAddress = A pointer to the virtual memory allocated. If you + * supply a non zero value the system will try to + * allocate the memory at the address supplied. It round + * it down to a multiple of the page size. + * ZeroBits = (OPTIONAL) You can specify the number of high order bits + * that must be zero, ensuring that the memory will be + * allocated at a address below a certain value. + * RegionSize = The number of bytes to allocate + * AllocationType = Indicates the type of virtual memory you like to + * allocated, can be a combination of MEM_COMMIT, + * MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN. + * Protect = Indicates the protection type of the pages allocated, can be + * a combination of PAGE_READONLY, PAGE_READWRITE, + * PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE, PAGE_GUARD, + * PAGE_NOACCESS + * RETURNS: Status + */ +{ + PEPROCESS Process; + MEMORY_AREA* MemoryArea; + ULONG Type; + NTSTATUS Status; + PMADDRESS_SPACE AddressSpace; + PVOID BaseAddress; + ULONG RegionSize; + PVOID PBaseAddress; + ULONG PRegionSize; + + DPRINT("NtAllocateVirtualMemory(*UBaseAddress %x, " + "ZeroBits %d, *URegionSize %x, AllocationType %x, Protect %x)\n", + *UBaseAddress,ZeroBits,*URegionSize,AllocationType, + Protect); + + /* + * Check the validity of the parameters + */ + if ((Protect & PAGE_FLAGS_VALID_FROM_USER_MODE) != Protect) + { + return(STATUS_INVALID_PAGE_PROTECTION); + } + if ((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == 0) + { + return(STATUS_INVALID_PARAMETER); + } + + PBaseAddress = *UBaseAddress; + PRegionSize = *URegionSize; + + BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress); + RegionSize = PAGE_ROUND_UP(PBaseAddress + PRegionSize) - + PAGE_ROUND_DOWN(PBaseAddress); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + + Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE; + DPRINT("Type %x\n", Type); + + AddressSpace = &Process->AddressSpace; + MmLockAddressSpace(AddressSpace); + + if (PBaseAddress != 0) + { + MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, + BaseAddress); + + if (MemoryArea != NULL && + MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY && + MemoryArea->Length >= RegionSize) + { + Status = + MmAlterRegion(&Process->AddressSpace, + MemoryArea->BaseAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + PBaseAddress, RegionSize, + Type, Protect, MmModifyAttributes); + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + else if (MemoryArea != NULL) + { + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + } + + Status = MmCreateMemoryArea(Process, + &Process->AddressSpace, + MEMORY_AREA_VIRTUAL_MEMORY, + &BaseAddress, + RegionSize, + Protect, + &MemoryArea, + PBaseAddress != 0); + + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + DPRINT("NtAllocateVirtualMemory() = %x\n",Status); + return(Status); + } + MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead, + RegionSize, Type, Protect); + + if ((AllocationType & MEM_COMMIT) && + ((Protect & PAGE_READWRITE) || + (Protect & PAGE_EXECUTE_READWRITE))) + { + MmReserveSwapPages(RegionSize); + } + + *UBaseAddress = BaseAddress; + *URegionSize = RegionSize; + DPRINT("*UBaseAddress %x *URegionSize %x\n", BaseAddress, RegionSize); + + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_SUCCESS); +} + +VOID STATIC +MmFreeVirtualMemoryPage(PVOID Context, + MEMORY_AREA* MemoryArea, + PVOID Address, + PHYSICAL_ADDRESS PhysicalAddr, + SWAPENTRY SwapEntry, + BOOLEAN Dirty) +{ + PEPROCESS Process = (PEPROCESS)Context; + + if (PhysicalAddr.QuadPart != 0) + { + SWAPENTRY SavedSwapEntry; + SavedSwapEntry = MmGetSavedSwapEntryPage(PhysicalAddr); + if (SavedSwapEntry != 0) + { + MmFreeSwapPage(SavedSwapEntry); + MmSetSavedSwapEntryPage(PhysicalAddr, 0); + } + MmDeleteRmap(PhysicalAddr, Process, Address); + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddr); + } + else if (SwapEntry != 0) + { + MmFreeSwapPage(SwapEntry); + } +} + +VOID +MmFreeVirtualMemory(PEPROCESS Process, + PMEMORY_AREA MemoryArea) +{ + PLIST_ENTRY current_entry; + PMM_REGION current; + ULONG i; + + DPRINT("MmFreeVirtualMemory(Process %p MemoryArea %p)\n", Process, + MemoryArea); + + /* Mark this memory area as about to be deleted. */ + MemoryArea->DeleteInProgress = TRUE; + + /* + * Wait for any ongoing paging operations. Notice that since we have + * flagged this memory area as deleted no more page ops will be added. + */ + if (MemoryArea->PageOpCount > 0) + { + for (i = 0; i < (PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE); i++) + { + PMM_PAGEOP PageOp; + + if (MemoryArea->PageOpCount == 0) + { + break; + } + + PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId, + MemoryArea->BaseAddress + (i * PAGE_SIZE), + NULL, 0); + if (PageOp != NULL) + { + NTSTATUS Status; + MmUnlockAddressSpace(&Process->AddressSpace); + Status = KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op\n"); + KeBugCheck(0); + } + MmLockAddressSpace(&Process->AddressSpace); + MmReleasePageOp(PageOp); + } + } + } + + /* Free all the individual segments. */ + current_entry = MemoryArea->Data.VirtualMemoryData.RegionListHead.Flink; + while (current_entry != &MemoryArea->Data.VirtualMemoryData.RegionListHead) + { + current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry); + current_entry = current_entry->Flink; + ExFreePool(current); + } + + /* Actually free the memory area. */ + MmFreeMemoryArea(&Process->AddressSpace, + MemoryArea->BaseAddress, + 0, + MmFreeVirtualMemoryPage, + (PVOID)Process); +} + +NTSTATUS STDCALL +NtFreeVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID* PBaseAddress, + IN PULONG PRegionSize, + IN ULONG FreeType) +/* + * FUNCTION: Frees a range of virtual memory + * ARGUMENTS: + * ProcessHandle = Points to the process that allocated the virtual + * memory + * BaseAddress = Points to the memory address, rounded down to a + * multiple of the pagesize + * RegionSize = Limits the range to free, rounded up to a multiple of + * the paging size + * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE + * RETURNS: Status + */ +{ + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + PEPROCESS Process; + PMADDRESS_SPACE AddressSpace; + PVOID BaseAddress; + ULONG RegionSize; + + DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *PBaseAddress %x, " + "*PRegionSize %x, FreeType %x)\n",ProcessHandle,*PBaseAddress, + *PRegionSize,FreeType); + + BaseAddress = (PVOID)PAGE_ROUND_DOWN((*PBaseAddress)); + RegionSize = PAGE_ROUND_UP((*PBaseAddress) + (*PRegionSize)) - + PAGE_ROUND_DOWN((*PBaseAddress)); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + UserMode, + (PVOID*)(&Process), + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + AddressSpace = &Process->AddressSpace; + + MmLockAddressSpace(AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, + BaseAddress); + if (MemoryArea == NULL) + { + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + switch (FreeType) + { + case MEM_RELEASE: + /* We can only free a memory area in one step. */ + if (MemoryArea->BaseAddress != BaseAddress) + { + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + MmFreeVirtualMemory(Process, MemoryArea); + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_SUCCESS); + + case MEM_DECOMMIT: + Status = + MmAlterRegion(AddressSpace, + MemoryArea->BaseAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, + RegionSize, + MEM_RESERVE, + PAGE_NOACCESS, + MmModifyAttributes); + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(Status); + } + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS +MmProtectAnonMem(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID BaseAddress, + ULONG Length, + ULONG Protect, + PULONG OldProtect) +{ + PMM_REGION Region; + NTSTATUS Status; + + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, NULL); + *OldProtect = Region->Protect; + Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + BaseAddress, Length, Region->Type, Protect, + MmModifyAttributes); + return(Status); +} + +NTSTATUS STDCALL +MmQueryAnonMem(PMEMORY_AREA MemoryArea, + PVOID Address, + PMEMORY_BASIC_INFORMATION Info, + PULONG ResultLength) +{ + PMM_REGION Region; + PVOID RegionBase; + + Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address); + + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.VirtualMemoryData.RegionListHead, + Address, &RegionBase); + Info->AllocationBase = RegionBase; + Info->AllocationProtect = Region->Protect; /* FIXME */ + Info->RegionSize = Region->Length; + Info->State = Region->Type; + Info->Protect = Region->Protect; + Info->Type = MEM_PRIVATE; + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/mm/aspace.c b/ntoskrnl/mm/aspace.c new file mode 100644 index 0000000..b4fbdf3 --- /dev/null +++ b/ntoskrnl/mm/aspace.c @@ -0,0 +1,109 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/aspace.c + * PURPOSE: Manages address spaces + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#include + +/* GLOBALS ******************************************************************/ + +STATIC MADDRESS_SPACE KernelAddressSpace; + +#define TAG_PTRC TAG('P', 'T', 'R', 'C') + +/* FUNCTIONS *****************************************************************/ + +VOID +MmLockAddressSpace(PMADDRESS_SPACE AddressSpace) +{ + /* + * Don't bother with locking if we are the first thread. + */ + if (KeGetCurrentThread() == NULL) + { + return; + } + ExAcquireFastMutex(&AddressSpace->Lock); +} + +VOID +MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace) +{ + /* + * Don't bother locking if we are the first thread. + */ + if (KeGetCurrentThread() == NULL) + { + return; + } + ExReleaseFastMutex(&AddressSpace->Lock); +} + +VOID +MmInitializeKernelAddressSpace(VOID) +{ + MmInitializeAddressSpace(NULL, &KernelAddressSpace); +} + +PMADDRESS_SPACE MmGetCurrentAddressSpace(VOID) +{ + return(&PsGetCurrentProcess()->AddressSpace); +} + +PMADDRESS_SPACE MmGetKernelAddressSpace(VOID) +{ + return(&KernelAddressSpace); +} + +NTSTATUS +MmInitializeAddressSpace(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace) +{ + InitializeListHead(&AddressSpace->MAreaListHead); + ExInitializeFastMutex(&AddressSpace->Lock); + if (Process != NULL) + { + AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS; + } + else + { + AddressSpace->LowestAddress = KERNEL_BASE; + } + AddressSpace->Process = Process; + if (Process != NULL) + { + AddressSpace->PageTableRefCountTable = + ExAllocatePoolWithTag(NonPagedPool, 768 * sizeof(USHORT), + TAG_PTRC); + AddressSpace->PageTableRefCountTableSize = 768; + } + else + { + AddressSpace->PageTableRefCountTable = NULL; + AddressSpace->PageTableRefCountTableSize = 0; + } + return(STATUS_SUCCESS); +} + +NTSTATUS +MmDestroyAddressSpace(PMADDRESS_SPACE AddressSpace) +{ + if (AddressSpace->PageTableRefCountTable != NULL) + { + ExFreePool(AddressSpace->PageTableRefCountTable); + } + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/mm/balance.c b/ntoskrnl/mm/balance.c new file mode 100644 index 0000000..989baf0 --- /dev/null +++ b/ntoskrnl/mm/balance.c @@ -0,0 +1,294 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/balance.c + * PURPOSE: kernel memory managment functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 27/12/01 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES ********************************************************************/ + +typedef struct _MM_MEMORY_CONSUMER +{ + ULONG PagesUsed; + ULONG PagesTarget; + NTSTATUS (*Trim)(ULONG Target, ULONG Priority, PULONG NrFreed); +} MM_MEMORY_CONSUMER, *PMM_MEMORY_CONSUMER; + +typedef struct _MM_ALLOCATION_REQUEST +{ + PHYSICAL_ADDRESS Page; + LIST_ENTRY ListEntry; + KEVENT Event; +} MM_ALLOCATION_REQUEST, *PMM_ALLOCATION_REQUEST; + +/* GLOBALS ******************************************************************/ + +static MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM]; +static ULONG MiMinimumAvailablePages; +static ULONG MiNrAvailablePages; +static ULONG MiNrTotalPages; +static LIST_ENTRY AllocationListHead; +static KSPIN_LOCK AllocationListLock; +static ULONG NrWorkingThreads = 0; +static HANDLE WorkerThreadId; +static ULONG MiPagesRequired = 0; +static ULONG MiMinimumPagesPerRun = 1; + +/* FUNCTIONS ****************************************************************/ + +VOID MmPrintMemoryStatistic(VOID) +{ + DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d\n", + MiMemoryConsumers[MC_CACHE].PagesUsed, + MiMemoryConsumers[MC_USER].PagesUsed, + MiMemoryConsumers[MC_PPOOL].PagesUsed, + MiMemoryConsumers[MC_NPPOOL].PagesUsed); +} + +VOID +MmInitializeBalancer(ULONG NrAvailablePages) +{ + memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers)); + InitializeListHead(&AllocationListHead); + KeInitializeSpinLock(&AllocationListLock); + + MiNrAvailablePages = MiNrTotalPages = NrAvailablePages; + + /* Set up targets. */ + MiMinimumAvailablePages = 64; + MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 2; + MiMemoryConsumers[MC_USER].PagesTarget = + NrAvailablePages - MiMinimumAvailablePages; + MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2; + MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF; +} + +VOID +MmInitializeMemoryConsumer(ULONG Consumer, + NTSTATUS (*Trim)(ULONG Target, ULONG Priority, + PULONG NrFreed)) +{ + MiMemoryConsumers[Consumer].Trim = Trim; +} + +NTSTATUS +MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page) +{ + PMM_ALLOCATION_REQUEST Request; + PLIST_ENTRY Entry; + KIRQL oldIrql; + + if (Page.QuadPart == 0LL) + { + DPRINT1("Tried to release page zero.\n"); + KeBugCheck(0); + } + + KeAcquireSpinLock(&AllocationListLock, &oldIrql); + if (MmGetReferenceCountPage(Page) == 1) + { + InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed); + InterlockedIncrement(&MiNrAvailablePages); + InterlockedDecrement(&MiPagesRequired); + if (IsListEmpty(&AllocationListHead)) + { + KeReleaseSpinLock(&AllocationListLock, oldIrql); + MmDereferencePage(Page); + } + else + { + Entry = RemoveHeadList(&AllocationListHead); + Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry); + KeReleaseSpinLock(&AllocationListLock, oldIrql); + Request->Page = Page; + KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE); + } + } + else + { + KeReleaseSpinLock(&AllocationListLock, oldIrql); + MmDereferencePage(Page); + } + + return(STATUS_SUCCESS); +} + +VOID +MiTrimMemoryConsumer(ULONG Consumer) +{ + LONG Target; + ULONG NrFreedPages; + + Target = MiMemoryConsumers[Consumer].PagesUsed - + MiMemoryConsumers[Consumer].PagesTarget; + if (Target < 0) + { + Target = 1; + } + + if (MiMemoryConsumers[Consumer].Trim != NULL) + { + MiMemoryConsumers[Consumer].Trim(Target, 0, &NrFreedPages); + } +} + +VOID +MiRebalanceMemoryConsumers(VOID) +{ + LONG Target; + ULONG i; + ULONG NrFreedPages; + NTSTATUS Status; + + Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired; + Target = min(Target, MiMinimumPagesPerRun); + + for (i = 0; i < MC_MAXIMUM && Target > 0; i++) + { + if (MiMemoryConsumers[i].Trim != NULL) + { + Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + Target = Target - NrFreedPages; + } + } + if (Target > 0) + { + KeBugCheck(0); + } +} + +NTSTATUS +MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, + PHYSICAL_ADDRESS* AllocatedPage) +{ + ULONG OldUsed; + ULONG OldAvailable; + PHYSICAL_ADDRESS Page; + KIRQL oldIrql; + + /* + * Make sure we don't exceed our individual target. + */ + OldUsed = InterlockedIncrement(&MiMemoryConsumers[Consumer].PagesUsed); + if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) && + WorkerThreadId != PsGetCurrentThreadId()) + { + if (!CanWait) + { + InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed); + return(STATUS_NO_MEMORY); + } + MiTrimMemoryConsumer(Consumer); + } + + /* + * Make sure we don't exceed global targets. + */ + OldAvailable = InterlockedDecrement(&MiNrAvailablePages); + if (OldAvailable < MiMinimumAvailablePages) + { + MM_ALLOCATION_REQUEST Request; + + if (!CanWait) + { + InterlockedIncrement(&MiNrAvailablePages); + InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed); + return(STATUS_NO_MEMORY); + } + + /* Insert an allocation request. */ + Request.Page.QuadPart = 0LL; + KeInitializeEvent(&Request.Event, NotificationEvent, FALSE); + InterlockedIncrement(&MiPagesRequired); + + KeAcquireSpinLock(&AllocationListLock, &oldIrql); + if (NrWorkingThreads == 0) + { + InsertTailList(&AllocationListHead, &Request.ListEntry); + NrWorkingThreads++; + KeReleaseSpinLock(&AllocationListLock, oldIrql); + WorkerThreadId = PsGetCurrentThreadId(); + MiRebalanceMemoryConsumers(); + KeAcquireSpinLock(&AllocationListLock, &oldIrql); + NrWorkingThreads--; + WorkerThreadId = 0; + KeReleaseSpinLock(&AllocationListLock, oldIrql); + } + else + { + if (WorkerThreadId == PsGetCurrentThreadId()) + { + Page = MmAllocPage(Consumer, 0); + KeReleaseSpinLock(&AllocationListLock, oldIrql); + if (Page.QuadPart == 0LL) + { + KeBugCheck(0); + } + *AllocatedPage = Page; + return(STATUS_SUCCESS); + } + InsertTailList(&AllocationListHead, &Request.ListEntry); + KeReleaseSpinLock(&AllocationListLock, oldIrql); + } + KeWaitForSingleObject(&Request.Event, + 0, + KernelMode, + FALSE, + NULL); + + Page = Request.Page; + if (Page.QuadPart == 0LL) + { + KeBugCheck(0); + } + MmTransferOwnershipPage(Page, Consumer); + *AllocatedPage = Page; + return(STATUS_SUCCESS); + } + + /* + * Actually allocate the page. + */ + Page = MmAllocPage(Consumer, 0); + if (Page.QuadPart == 0LL) + { + KeBugCheck(0); + } + *AllocatedPage = Page; + + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/mm/cont.c b/ntoskrnl/mm/cont.c new file mode 100644 index 0000000..37af4a1 --- /dev/null +++ b/ntoskrnl/mm/cont.c @@ -0,0 +1,153 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/cont.c + * PURPOSE: Manages continuous memory + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STATIC +MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, + BOOLEAN Dirty) +{ + assert(SwapEntry == 0); + if (PhysAddr.QuadPart != 0) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr); + } +} + +PVOID STDCALL +MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes, + IN PHYSICAL_ADDRESS HighestAcceptableAddress, + IN ULONG Alignment) +{ + PMEMORY_AREA MArea; + NTSTATUS Status; + PVOID BaseAddress = 0; + PHYSICAL_ADDRESS PBase; + ULONG i; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_CONTINUOUS_MEMORY, + &BaseAddress, + NumberOfBytes, + 0, + &MArea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + DPRINT( "Base = %x\n", BaseAddress ); + PBase = MmGetContinuousPages(NumberOfBytes, + HighestAcceptableAddress, + Alignment); + if (PBase.QuadPart == 0LL) + { + MmFreeMemoryArea(MmGetKernelAddressSpace(), + BaseAddress, + 0, + NULL, + NULL); + return(NULL); + } + for (i = 0; i < (PAGE_ROUND_UP(NumberOfBytes) / 4096); i++) + { + MmCreateVirtualMapping(NULL, + BaseAddress + (i * 4096), + PAGE_EXECUTE_READWRITE | PAGE_SYSTEM, + (LARGE_INTEGER)(PBase.QuadPart + (i * 4096)), + TRUE); + } + return(BaseAddress); +} + +/********************************************************************** + * NAME EXPORTED + * MmAllocateContiguousMemory@12 + * + * DESCRIPTION + * Allocates a range of physically contiguous cache aligned + * memory from the non-paged pool. + * + * ARGUMENTS + * NumberOfBytes + * Size of the memory block to allocate; + * + * HighestAcceptableAddress + * Highest address valid for the caller. + * + * RETURN VALUE + * The virtual address of the memory block on success; + * NULL on error. + * + * NOTE + * Description taken from include/ddk/mmfuncs.h. + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +PVOID STDCALL +MmAllocateContiguousMemory (IN ULONG NumberOfBytes, + IN PHYSICAL_ADDRESS HighestAcceptableAddress) +{ + return(MmAllocateContiguousAlignedMemory(NumberOfBytes, + HighestAcceptableAddress, + PAGE_SIZE)); +} + + +/********************************************************************** + * NAME EXPORTED + * MmFreeContiguousMemory@4 + * + * DESCRIPTION + * Releases a range of physically contiguous memory allocated + * with MmAllocateContiguousMemory. + * + * ARGUMENTS + * BaseAddress + * Virtual address of the memory to be freed. + * + * RETURN VALUE + * None. + * + * NOTE + * Description taken from include/ddk/mmfuncs.h. + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +VOID STDCALL +MmFreeContiguousMemory(IN PVOID BaseAddress) +{ + MmFreeMemoryArea(MmGetKernelAddressSpace(), + BaseAddress, + 0, + MmFreeContinuousPage, + NULL); +} + + +/* EOF */ diff --git a/ntoskrnl/mm/drvlck.c b/ntoskrnl/mm/drvlck.c new file mode 100644 index 0000000..6ae010a --- /dev/null +++ b/ntoskrnl/mm/drvlck.c @@ -0,0 +1,86 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/drvlck.c + * PURPOSE: Managing driver managing + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +#if 0 +VOID +MmUnlockPagableImageSection(IN PVOID ImageSectionHandle) +/* + * FUNCTION: Releases a section of driver code or driver data, previously + * locked into system space with MmLockPagableCodeSection, + * MmLockPagableDataSection or MmLockPagableSectionByHandle + * ARGUMENTS: + * ImageSectionHandle = Handle returned by MmLockPagableCodeSection or + * MmLockPagableDataSection + */ +{ +// MmUnlockMemoryArea((MEMORY_AREA *)ImageSectionHandle); + UNIMPLEMENTED; +} +#endif + + +VOID STDCALL +MmLockPagableSectionByHandle(IN PVOID ImageSectionHandle) +{ +// MmLockMemoryArea((MEMORY_AREA *)ImageSectionHandle); + UNIMPLEMENTED; +} + + +#if 0 +PVOID +MmLockPagableCodeSection(IN PVOID AddressWithinSection) +{ + PVOID Handle; + Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection); + MmLockPagableSectionByHandle(Handle); + return(Handle); +} +#endif + + +PVOID STDCALL +MmLockPagableDataSection(IN PVOID AddressWithinSection) +{ + PVOID Handle; + Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection); + MmLockPagableSectionByHandle(Handle); + return(Handle); +} + + +VOID STDCALL +MmUnlockPagableImageSection(IN PVOID ImageSectionHandle) +{ +} + + +VOID STDCALL +MmPageEntireDriver(IN PVOID AddressWithinSection) +{ +} + + +VOID STDCALL +MmResetDriverPaging(IN PVOID AddressWithinSection) +{ +} + +/* EOF */ diff --git a/ntoskrnl/mm/freelist.c b/ntoskrnl/mm/freelist.c new file mode 100644 index 0000000..7eff3ab --- /dev/null +++ b/ntoskrnl/mm/freelist.c @@ -0,0 +1,824 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/freelist.c + * PURPOSE: Handle the list of free physical pages + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 27/05/98: Created + * 18/08/98: Added a fix from Robert Bergkvist + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +#define MM_PHYSICAL_PAGE_FREE (0x1) +#define MM_PHYSICAL_PAGE_USED (0x2) +#define MM_PHYSICAL_PAGE_BIOS (0x3) + +#define MM_PTYPE(x) ((x) & 0x3) + +typedef struct _PHYSICAL_PAGE +{ + ULONG Flags; + LIST_ENTRY ListEntry; + ULONG ReferenceCount; + SWAPENTRY SavedSwapEntry; + ULONG LockCount; + ULONG MapCount; + struct _MM_RMAP_ENTRY* RmapListHead; +} PHYSICAL_PAGE, *PPHYSICAL_PAGE; + +/* GLOBALS ****************************************************************/ + +static PPHYSICAL_PAGE MmPageArray; + +static KSPIN_LOCK PageListLock; +static LIST_ENTRY UsedPageListHeads[MC_MAXIMUM]; +static LIST_ENTRY FreeZeroedPageListHead; +static LIST_ENTRY FreeUnzeroedPageListHead; +static LIST_ENTRY BiosPageListHead; + +/* FUNCTIONS *************************************************************/ + +VOID +MmTransferOwnershipPage(PHYSICAL_ADDRESS PhysicalAddress, ULONG NewConsumer) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + RemoveEntryList(&MmPageArray[Start].ListEntry); + InsertTailList(&UsedPageListHeads[NewConsumer], + &MmPageArray[Start].ListEntry); + KeReleaseSpinLock(&PageListLock, oldIrql); + MiZeroPage(PhysicalAddress); +} + +PHYSICAL_ADDRESS +MmGetLRUFirstUserPage(VOID) +{ + PLIST_ENTRY NextListEntry; + PHYSICAL_ADDRESS Next; + PHYSICAL_PAGE* PageDescriptor; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + NextListEntry = UsedPageListHeads[MC_USER].Flink; + if (NextListEntry == &UsedPageListHeads[MC_USER]) + { + KeReleaseSpinLock(&PageListLock, oldIrql); + return((LARGE_INTEGER)0LL); + } + PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry); + Next.QuadPart = (ULONG)((ULONG)PageDescriptor - (ULONG)MmPageArray); + Next.QuadPart = (Next.QuadPart / sizeof(PHYSICAL_PAGE)) * PAGE_SIZE; + KeReleaseSpinLock(&PageListLock, oldIrql); + return(Next); +} + +PHYSICAL_ADDRESS +MmGetLRUNextUserPage(PHYSICAL_ADDRESS PreviousPhysicalAddress) +{ + ULONG Start = PreviousPhysicalAddress.u.LowPart / PAGE_SIZE; + PLIST_ENTRY NextListEntry; + PHYSICAL_ADDRESS Next; + PHYSICAL_PAGE* PageDescriptor; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + if (!(MmPageArray[Start].Flags & MM_PHYSICAL_PAGE_USED)) + { + NextListEntry = UsedPageListHeads[MC_USER].Flink; + } + else + { + NextListEntry = MmPageArray[Start].ListEntry.Flink; + } + if (NextListEntry == &UsedPageListHeads[MC_USER]) + { + KeReleaseSpinLock(&PageListLock, oldIrql); + return((LARGE_INTEGER)0LL); + } + PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry); + Next.QuadPart = (ULONG)((ULONG)PageDescriptor - (ULONG)MmPageArray); + Next.QuadPart = (Next.QuadPart / sizeof(PHYSICAL_PAGE)) * PAGE_SIZE; + KeReleaseSpinLock(&PageListLock, oldIrql); + return(Next); +} + +PHYSICAL_ADDRESS +MmGetContinuousPages(ULONG NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress, + ULONG Alignment) +{ + ULONG NrPages; + ULONG i; + ULONG start; + ULONG length; + KIRQL oldIrql; + + NrPages = PAGE_ROUND_UP(NumberOfBytes) / PAGE_SIZE; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + start = -1; + length = 0; + for (i = 0; i < (HighestAcceptableAddress.QuadPart / PAGE_SIZE); ) + { + if (MM_PTYPE(MmPageArray[i].Flags) == MM_PHYSICAL_PAGE_FREE) + { + if (start == -1) + { + start = i; + length = 1; + } + else + { + length++; + } + i++; + if (length == NrPages) + { + break; + } + } + else + { + start = -1; + /* + * Fast forward to the base of the next aligned region + */ + i = ROUND_UP((i + 1), (Alignment / PAGE_SIZE)); + } + } + if (start == -1 || length != NrPages) + { + KeReleaseSpinLock(&PageListLock, oldIrql); + return((LARGE_INTEGER)(LONGLONG)0); + } + for (i = start; i < (start + length); i++) + { + RemoveEntryList(&MmPageArray[i].ListEntry); + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED; + MmPageArray[i].ReferenceCount = 1; + MmPageArray[i].LockCount = 0; + MmPageArray[i].MapCount = 0; + MmPageArray[i].SavedSwapEntry = 0; + InsertTailList(&UsedPageListHeads[MC_NPPOOL], + &MmPageArray[i].ListEntry); + } + KeReleaseSpinLock(&PageListLock, oldIrql); + return((LARGE_INTEGER)((LONGLONG)start * 4096)); +} + +VOID +MiParseRangeToFreeList(PADDRESS_RANGE Range) +{ + ULONG i, first, last; + + /* FIXME: Not 64-bit ready */ + + DPRINT("Range going to free list (Base 0x%X, Length 0x%X, Type 0x%X)\n", + Range->BaseAddrLow, + Range->LengthLow, + Range->Type); + + first = (Range->BaseAddrLow + PAGE_SIZE - 1) / PAGE_SIZE; + last = first + ((Range->LengthLow + PAGE_SIZE - 1) / PAGE_SIZE); + for (i = first; i < last; i++) + { + if (MmPageArray[i].Flags == 0) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE; + MmPageArray[i].ReferenceCount = 0; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[i].ListEntry); + } + } +} + +VOID +MiParseRangeToBiosList(PADDRESS_RANGE Range) +{ + ULONG i, first, last; + + /* FIXME: Not 64-bit ready */ + + DPRINT("Range going to bios list (Base 0x%X, Length 0x%X, Type 0x%X)\n", + Range->BaseAddrLow, + Range->LengthLow, + Range->Type); + + first = (Range->BaseAddrLow + PAGE_SIZE - 1) / PAGE_SIZE; + last = first + ((Range->LengthLow + PAGE_SIZE - 1) / PAGE_SIZE); + for (i = first; i < last; i++) + { + /* Remove the page from the free list if it is there */ + if (MmPageArray[i].Flags == MM_PHYSICAL_PAGE_FREE) + { + RemoveEntryList(&MmPageArray[i].ListEntry); + } + + if (MmPageArray[i].Flags != MM_PHYSICAL_PAGE_BIOS) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_BIOS; + MmPageArray[i].ReferenceCount = 1; + InsertTailList(&BiosPageListHead, + &MmPageArray[i].ListEntry); + } + } +} + +VOID +MiParseBIOSMemoryMap(ULONG MemorySizeInPages, + PADDRESS_RANGE BIOSMemoryMap, + ULONG AddressRangeCount) +{ + PADDRESS_RANGE p; + ULONG i; + + p = BIOSMemoryMap; + for (i = 0; i < AddressRangeCount; i++) + { + if (((p->BaseAddrLow + PAGE_SIZE - 1) / PAGE_SIZE) < MemorySizeInPages) + { + if (p->Type == 1) + { + MiParseRangeToFreeList(p); + } + else + { + MiParseRangeToBiosList(p); + } + } + p += 1; + } +} + +PVOID +MmInitializePageList(PVOID FirstPhysKernelAddress, + PVOID LastPhysKernelAddress, + ULONG MemorySizeInPages, + ULONG LastKernelAddress, + PADDRESS_RANGE BIOSMemoryMap, + ULONG AddressRangeCount) +/* + * FUNCTION: Initializes the page list with all pages free + * except those known to be reserved and those used by the kernel + * ARGUMENTS: + * PageBuffer = Page sized buffer + * FirstKernelAddress = First physical address used by the kernel + * LastKernelAddress = Last physical address used by the kernel + */ +{ + ULONG i; + ULONG Reserved; + NTSTATUS Status; + + DPRINT("MmInitializePageList(FirstPhysKernelAddress %x, " + "LastPhysKernelAddress %x, " + "MemorySizeInPages %x, LastKernelAddress %x)\n", + FirstPhysKernelAddress, + LastPhysKernelAddress, + MemorySizeInPages, + LastKernelAddress); + + for (i = 0; i < MC_MAXIMUM; i++) + { + InitializeListHead(&UsedPageListHeads[i]); + } + KeInitializeSpinLock(&PageListLock); + InitializeListHead(&FreeUnzeroedPageListHead); + InitializeListHead(&FreeZeroedPageListHead); + InitializeListHead(&BiosPageListHead); + + LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress); + + Reserved = + PAGE_ROUND_UP((MemorySizeInPages * sizeof(PHYSICAL_PAGE))) / PAGE_SIZE; + MmPageArray = (PHYSICAL_PAGE *)LastKernelAddress; + + DPRINT("Reserved %d\n", Reserved); + + LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress); + LastKernelAddress = ((ULONG)LastKernelAddress + (Reserved * PAGE_SIZE)); + LastPhysKernelAddress = (PVOID)PAGE_ROUND_UP(LastPhysKernelAddress); + LastPhysKernelAddress = LastPhysKernelAddress + (Reserved * PAGE_SIZE); + + MmStats.NrTotalPages = 0; + MmStats.NrSystemPages = 0; + MmStats.NrUserPages = 0; + MmStats.NrReservedPages = 0; + MmStats.NrFreePages = 0; + MmStats.NrLockedPages = 0; + + for (i = 0; i < Reserved; i++) + { + PVOID Address = (PVOID)(ULONG)MmPageArray + (i * PAGE_SIZE); + if (!MmIsPagePresent(NULL, Address)) + { + ULONG PhysicalAddress; + PhysicalAddress = (ULONG)LastPhysKernelAddress - + (Reserved * PAGE_SIZE) + (i * PAGE_SIZE); + Status = + MmCreateVirtualMappingUnsafe(NULL, + Address, + PAGE_READWRITE, + (PHYSICAL_ADDRESS)(LONGLONG)PhysicalAddress, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + } + memset((PVOID)MmPageArray + (i * PAGE_SIZE), 0, PAGE_SIZE); + } + + /* + * Page zero is reserved + */ + MmPageArray[0].Flags = MM_PHYSICAL_PAGE_BIOS; + MmPageArray[0].ReferenceCount = 0; + InsertTailList(&BiosPageListHead, + &MmPageArray[0].ListEntry); + + /* + * Page one is reserved for the initial KPCR + */ + MmPageArray[1].Flags = MM_PHYSICAL_PAGE_BIOS; + MmPageArray[1].ReferenceCount = 0; + InsertTailList(&BiosPageListHead, + &MmPageArray[1].ListEntry); + + i = 2; + if ((ULONG)FirstPhysKernelAddress < 0xa0000) + { + MmStats.NrFreePages += (((ULONG)FirstPhysKernelAddress/PAGE_SIZE) - 1); + for (; i<((ULONG)FirstPhysKernelAddress/PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE; + MmPageArray[i].ReferenceCount = 0; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[i].ListEntry); + } + MmStats.NrSystemPages += + ((((ULONG)LastPhysKernelAddress) / PAGE_SIZE) - i); + for (; i<((ULONG)LastPhysKernelAddress / PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED; + MmPageArray[i].ReferenceCount = 1; + InsertTailList(&UsedPageListHeads[MC_NPPOOL], + &MmPageArray[i].ListEntry); + } + MmStats.NrFreePages += ((0xa0000/PAGE_SIZE) - i); + for (; i<(0xa0000/PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE; + MmPageArray[i].ReferenceCount = 0; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[i].ListEntry); + } + MmStats.NrReservedPages += ((0x100000/PAGE_SIZE) - i); + for (; i<(0x100000 / PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_BIOS; + MmPageArray[i].ReferenceCount = 1; + InsertTailList(&BiosPageListHead, + &MmPageArray[i].ListEntry); + } + } + else + { + MmStats.NrFreePages += ((0xa0000 / PAGE_SIZE) - 1); + for (; i<(0xa0000 / PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE; + MmPageArray[i].ReferenceCount = 0; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[i].ListEntry); + } + MmStats.NrReservedPages += (0x60000 / PAGE_SIZE); + for (; i<(0x100000 / PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_BIOS; + MmPageArray[i].ReferenceCount = 1; + InsertTailList(&BiosPageListHead, + &MmPageArray[i].ListEntry); + } + MmStats.NrFreePages += (((ULONG)FirstPhysKernelAddress/PAGE_SIZE) - i); + for (; i<((ULONG)FirstPhysKernelAddress/PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_FREE; + MmPageArray[i].ReferenceCount = 0; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[i].ListEntry); + } + MmStats.NrSystemPages += + (((ULONG)LastPhysKernelAddress/PAGE_SIZE) - i); + for (; i<((ULONG)LastPhysKernelAddress/PAGE_SIZE); i++) + { + MmPageArray[i].Flags = MM_PHYSICAL_PAGE_USED; + MmPageArray[i].ReferenceCount = 1; + InsertTailList(&UsedPageListHeads[MC_NPPOOL], + &MmPageArray[i].ListEntry); + } + } + + MmStats.NrFreePages += (MemorySizeInPages - i); + for (; i 0)) + { + MiParseBIOSMemoryMap( + MemorySizeInPages, + BIOSMemoryMap, + AddressRangeCount); + } + + MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages + + MmStats.NrReservedPages + MmStats.NrUserPages; + MmInitializeBalancer(MmStats.NrFreePages); + return((PVOID)LastKernelAddress); +} + +VOID +MmSetFlagsPage(PHYSICAL_ADDRESS PhysicalAddress, ULONG Flags) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + MmPageArray[Start].Flags = Flags; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +VOID +MmSetRmapListHeadPage(PHYSICAL_ADDRESS PhysicalAddress, + struct _MM_RMAP_ENTRY* ListHead) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + + MmPageArray[Start].RmapListHead = ListHead; +} + +struct _MM_RMAP_ENTRY* +MmGetRmapListHeadPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + + return(MmPageArray[Start].RmapListHead); +} + +VOID +MmMarkPageMapped(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + MmPageArray[Start].MapCount++; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +VOID +MmMarkPageUnmapped(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + MmPageArray[Start].MapCount--; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +ULONG +MmGetFlagsPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + ULONG Flags; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + Flags = MmPageArray[Start].Flags; + KeReleaseSpinLock(&PageListLock, oldIrql); + + return(Flags); +} + + +VOID +MmSetSavedSwapEntryPage(PHYSICAL_ADDRESS PhysicalAddress, + SWAPENTRY SavedSwapEntry) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + MmPageArray[Start].SavedSwapEntry = SavedSwapEntry; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +SWAPENTRY +MmGetSavedSwapEntryPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + SWAPENTRY SavedSwapEntry; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + SavedSwapEntry = MmPageArray[Start].SavedSwapEntry; + KeReleaseSpinLock(&PageListLock, oldIrql); + + return(SavedSwapEntry); +} + +VOID +MmReferencePage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + DPRINT("MmReferencePage(PhysicalAddress %x)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Referencing non-used page\n"); + KeBugCheck(0); + } + + MmPageArray[Start].ReferenceCount++; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +ULONG +MmGetReferenceCountPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + ULONG RCount; + + DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Getting reference count for free page\n"); + KeBugCheck(0); + } + + RCount = MmPageArray[Start].ReferenceCount; + + KeReleaseSpinLock(&PageListLock, oldIrql); + return(RCount); +} + +BOOLEAN +MmIsUsablePage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + + DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED && + MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_BIOS) + { + return(FALSE); + } + + return(TRUE); +} + +VOID +MmDereferencePage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + DPRINT("MmDereferencePage(PhysicalAddress %I64x)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Dereferencing free page\n"); + KeBugCheck(0); + } + + MmPageArray[Start].ReferenceCount--; + if (MmPageArray[Start].ReferenceCount == 0) + { + MmStats.NrFreePages++; + MmStats.NrSystemPages--; + RemoveEntryList(&MmPageArray[Start].ListEntry); + if (MmPageArray[Start].RmapListHead != NULL) + { + DbgPrint("Freeing page with rmap entries.\n"); + KeBugCheck(0); + } + if (MmPageArray[Start].MapCount != 0) + { + DbgPrint("Freeing mapped page (0x%I64x count %d)\n", + PhysicalAddress, MmPageArray[Start].MapCount); + KeBugCheck(0); + } + if (MmPageArray[Start].LockCount > 0) + { + DbgPrint("Freeing locked page\n"); + KeBugCheck(0); + } + if (MmPageArray[Start].SavedSwapEntry != 0) + { + DbgPrint("Freeing page with swap entry.\n"); + KeBugCheck(0); + } + if (MmPageArray[Start].Flags != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Freeing page with flags %x\n", + MmPageArray[Start].Flags); + KeBugCheck(0); + } + MmPageArray[Start].Flags = MM_PHYSICAL_PAGE_FREE; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[Start].ListEntry); + } + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +ULONG +MmGetLockCountPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + ULONG LockCount; + + DPRINT("MmGetLockCountPage(PhysicalAddress %x)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Getting lock count for free page\n"); + KeBugCheck(0); + } + + LockCount = MmPageArray[Start].LockCount; + KeReleaseSpinLock(&PageListLock, oldIrql); + + return(LockCount); +} + +VOID +MmLockPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + DPRINT("MmLockPage(PhysicalAddress %x)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Locking free page\n"); + KeBugCheck(0); + } + + MmPageArray[Start].LockCount++; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +VOID +MmUnlockPage(PHYSICAL_ADDRESS PhysicalAddress) +{ + ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; + KIRQL oldIrql; + + DPRINT("MmUnlockPage(PhysicalAddress %llx)\n", PhysicalAddress); + + if (PhysicalAddress.u.LowPart == 0) + { + KeBugCheck(0); + } + + KeAcquireSpinLock(&PageListLock, &oldIrql); + + if (MM_PTYPE(MmPageArray[Start].Flags) != MM_PHYSICAL_PAGE_USED) + { + DbgPrint("Unlocking free page\n"); + KeBugCheck(0); + } + + MmPageArray[Start].LockCount--; + KeReleaseSpinLock(&PageListLock, oldIrql); +} + +PHYSICAL_ADDRESS +MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry) +{ + PHYSICAL_ADDRESS PageOffset; + PLIST_ENTRY ListEntry; + PPHYSICAL_PAGE PageDescriptor; + KIRQL oldIrql; + BOOLEAN NeedClear = FALSE; + + DPRINT("MmAllocPage()\n"); + + KeAcquireSpinLock(&PageListLock, &oldIrql); + if (IsListEmpty(&FreeZeroedPageListHead)) + { + if (IsListEmpty(&FreeUnzeroedPageListHead)) + { + DPRINT1("MmAllocPage(): Out of memory\n"); + KeReleaseSpinLock(&PageListLock, oldIrql); + return((PHYSICAL_ADDRESS)0LL); + } + ListEntry = RemoveTailList(&FreeUnzeroedPageListHead); + + PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry); + KeReleaseSpinLock(&PageListLock, oldIrql); + + NeedClear = TRUE; + } + else + { + ListEntry = RemoveTailList(&FreeZeroedPageListHead); + KeReleaseSpinLock(&PageListLock, oldIrql); + + PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry); + } + + if (PageDescriptor->Flags != MM_PHYSICAL_PAGE_FREE) + { + DbgPrint("Got non-free page from freelist\n"); + KeBugCheck(0); + } + PageDescriptor->Flags = MM_PHYSICAL_PAGE_USED; + PageDescriptor->ReferenceCount = 1; + PageDescriptor->LockCount = 0; + PageDescriptor->MapCount = 0; + PageDescriptor->SavedSwapEntry = SavedSwapEntry; + ExInterlockedInsertTailList(&UsedPageListHeads[Consumer], ListEntry, + &PageListLock); + + MmStats.NrSystemPages++; + MmStats.NrFreePages--; + + PageOffset.QuadPart = (ULONG)((ULONG)PageDescriptor - (ULONG)MmPageArray); + PageOffset.QuadPart = + (PageOffset.QuadPart / sizeof(PHYSICAL_PAGE)) * PAGE_SIZE; + if (NeedClear) + { + MiZeroPage(PageOffset); + } + return(PageOffset); +} diff --git a/ntoskrnl/mm/i386/.cvsignore b/ntoskrnl/mm/i386/.cvsignore new file mode 100644 index 0000000..31dc307 --- /dev/null +++ b/ntoskrnl/mm/i386/.cvsignore @@ -0,0 +1,2 @@ +*.d +*.o diff --git a/ntoskrnl/mm/i386/memsafe.s b/ntoskrnl/mm/i386/memsafe.s new file mode 100644 index 0000000..f1c610f --- /dev/null +++ b/ntoskrnl/mm/i386/memsafe.s @@ -0,0 +1,83 @@ +.globl _MmSafeCopyFromUser +.globl _MmSafeCopyFromUserUnsafeStart +.globl _MmSafeCopyFromUserRestart +.globl _MmSafeCopyToUser +.globl _MmSafeCopyToUserUnsafeStart +.globl _MmSafeCopyToUserRestart + + /* + * NTSTATUS MmSafeCopyFromUser(PVOID Dest, PVOID Src, + * ULONG NumberOfBytes) + */ +_MmSafeCopyFromUser: + pushl %ebp + movl %esp,%ebp + + pushl %esi + pushl %edi + pushl %ecx + + movl 8(%ebp),%edi + movl 12(%ebp),%esi + movl 16(%ebp),%ecx + + /* + * Default return code + */ + movl $0,%eax + +_MmSafeCopyFromUserUnsafeStart: + /* + * This is really a synthetic instruction since if we incur a + * pagefault then eax will be set to an appropiate STATUS code + */ + rep movsb + +_MmSafeCopyFromUserRestart: + + popl %ecx + popl %edi + popl %esi + + popl %ebp + ret + +/*****************************************************************************/ + + /* + * NTSTATUS MmSafeCopyToUser(PVOID Dest, PVOID Src, + * ULONG NumberOfBytes) + */ +_MmSafeCopyToUser: + pushl %ebp + movl %esp,%ebp + + pushl %esi + pushl %edi + pushl %ecx + + movl 8(%ebp),%edi + movl 12(%ebp),%esi + movl 16(%ebp),%ecx + + /* + * Default return code + */ + movl $0,%eax + +_MmSafeCopyToUserUnsafeStart: + /* + * This is really a synthetic instruction since if we incur a + * pagefault then eax will be set to an appropiate STATUS code + */ + rep movsb + +_MmSafeCopyToUserRestart: + + popl %ecx + popl %edi + popl %esi + + popl %ebp + ret + diff --git a/ntoskrnl/mm/i386/page.c b/ntoskrnl/mm/i386/page.c new file mode 100644 index 0000000..3e19b06 --- /dev/null +++ b/ntoskrnl/mm/i386/page.c @@ -0,0 +1,1124 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/i386/page.c + * PURPOSE: low level memory managment manipulation + * PROGRAMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 9/3/98: Created + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +#define PA_BIT_PRESENT (0) +#define PA_BIT_READWRITE (1) +#define PA_BIT_USER (2) +#define PA_BIT_WT (3) +#define PA_BIT_CD (4) +#define PA_BIT_ACCESSED (5) +#define PA_BIT_DIRTY (6) + +#define PA_PRESENT (1 << PA_BIT_PRESENT) +#define PA_READWRITE (1 << PA_BIT_READWRITE) +#define PA_USER (1 << PA_BIT_USER) +#define PA_DIRTY (1 << PA_BIT_DIRTY) +#define PA_WT (1 << PA_BIT_WT) +#define PA_CD (1 << PA_BIT_CD) +#define PA_ACCESSED (1 << PA_BIT_ACCESSED) +#define PA_DIRTY (1 << PA_BIT_DIRTY) + +#define PAGETABLE_MAP (0xf0000000) +#define PAGEDIRECTORY_MAP (0xf0000000 + (PAGETABLE_MAP / (1024))) + +ULONG MmGlobalKernelPageDirectory[1024] = {0, }; + +#define PTE_TO_PAGE(X) ((LARGE_INTEGER)(LONGLONG)(PAGE_MASK(X))) + +/* FUNCTIONS ***************************************************************/ + +PULONG +MmGetPageDirectory(VOID) +{ + unsigned int page_dir=0; + __asm__("movl %%cr3,%0\n\t" + : "=r" (page_dir)); + return((PULONG)page_dir); +} + +static ULONG +ProtectToPTE(ULONG flProtect) +{ + ULONG Attributes = 0; + + if (flProtect & PAGE_NOACCESS || flProtect & PAGE_GUARD) + { + Attributes = 0; + } + else if (flProtect & PAGE_READWRITE || flProtect & PAGE_EXECUTE_READWRITE) + { + Attributes = PA_PRESENT | PA_READWRITE; + } + else if (flProtect & PAGE_READONLY || flProtect & PAGE_EXECUTE || + flProtect & PAGE_EXECUTE_READ) + { + Attributes = PA_PRESENT; + } + else + { + DPRINT1("Unknown main protection type.\n"); + KeBugCheck(0); + } + if (!(flProtect & PAGE_SYSTEM)) + { + Attributes = Attributes | PA_USER; + } + if (flProtect & PAGE_NOCACHE) + { + Attributes = Attributes | PA_CD; + } + if (flProtect & PAGE_WRITETHROUGH) + { + Attributes = Attributes | PA_WT; + } + return(Attributes); +} + +#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024)) + +#define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \ + (((ULONG)v / (1024 * 1024))&(~0x3))) +#define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3))) + +#define ADDR_TO_PDE_OFFSET(v) (((ULONG)v / (4 * 1024 * 1024))) + +NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) +{ + DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process); + + MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase); + Process->Pcb.DirectoryTableBase.QuadPart = 0LL; + + DPRINT("Finished Mmi386ReleaseMmInfo()\n"); + return(STATUS_SUCCESS); +} + +NTSTATUS MmCopyMmInfo(PEPROCESS Src, PEPROCESS Dest) +{ + PHYSICAL_ADDRESS PhysPageDirectory; + PULONG PageDirectory; + PULONG CurrentPageDirectory; + PKPROCESS KProcess = &Dest->Pcb; + ULONG i; + + DPRINT("MmCopyMmInfo(Src %x, Dest %x)\n", Src, Dest); + + PageDirectory = ExAllocatePage(); + if (PageDirectory == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + PhysPageDirectory = MmGetPhysicalAddress(PageDirectory); + KProcess->DirectoryTableBase = PhysPageDirectory; + CurrentPageDirectory = (PULONG)PAGEDIRECTORY_MAP; + + memset(PageDirectory,0,PAGE_SIZE); + for (i=768; i<896; i++) + { + PageDirectory[i] = CurrentPageDirectory[i]; + } + for (i=961; i<1024; i++) + { + PageDirectory[i] = CurrentPageDirectory[i]; + } + DPRINT("Addr %x\n",PAGETABLE_MAP / (4*1024*1024)); + PageDirectory[PAGETABLE_MAP / (4*1024*1024)] = + (ULONG)PhysPageDirectory.QuadPart | 0x7; + + ExUnmapPage(PageDirectory); + + DPRINT("Finished MmCopyMmInfo()\n"); + return(STATUS_SUCCESS); +} + +VOID MmDeletePageTable(PEPROCESS Process, PVOID Address) +{ + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + *(ADDR_TO_PDE(Address)) = 0; + if (Address >= (PVOID)KERNEL_BASE) + { + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0; + } + FLUSH_TLB; + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } +} + +VOID MmFreePageTable(PEPROCESS Process, PVOID Address) +{ + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + PULONG PageTable; + ULONG i; + ULONG npage; + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address)); + for (i = 0; i < 1024; i++) + { + if (PageTable[i] != 0) + { + DbgPrint("Page table entry not clear at %x/%x (is %x)\n", + ((ULONG)Address / 4*1024*1024), i, PageTable[i]); + KeBugCheck(0); + } + } + npage = *(ADDR_TO_PDE(Address)); + *(ADDR_TO_PDE(Address)) = 0; + if (Address >= (PVOID)KERNEL_BASE) + { + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = 0; + } + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(npage)); + FLUSH_TLB; + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } +} + +NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte, BOOLEAN MayWait) +/* + * FUNCTION: Get a pointer to the page table entry for a virtual address + */ +{ + PULONG Pde; + ULONG Address = (ULONG)PAddress; + PHYSICAL_ADDRESS npage; + + DPRINT("MmGetPageEntry(Address %x)\n", Address); + + Pde = ADDR_TO_PDE(Address); + if ((*Pde) == 0) + { + if (Address >= KERNEL_BASE && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + else + { + NTSTATUS Status; + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, MayWait, &npage); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + (*Pde) = npage.QuadPart | 0x7; + if (Address >= KERNEL_BASE) + { + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] = + *Pde; + } + memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGE_SIZE); + FLUSH_TLB; + } + } + *Pte = ADDR_TO_PTE(Address); + return(STATUS_SUCCESS); +} + +ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address) +{ + ULONG Entry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + Entry = *MmGetPageEntry(Address); + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(Entry); +} + +ULONG MmGetPageEntry1(PVOID PAddress) +/* + * FUNCTION: Get a pointer to the page table entry for a virtual address + */ +{ + PULONG page_tlb; + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + + DPRINT("MmGetPageEntry(Address %x)\n", Address); + + page_dir = ADDR_TO_PDE(Address); + if ((*page_dir) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); + if ((*page_dir) == 0) + { + return(0); + } + page_tlb = ADDR_TO_PTE(Address); + DPRINT("page_tlb %x\n",page_tlb); + return(*page_tlb); +} + +ULONG MmGetPageEntryForProcess1(PEPROCESS Process, PVOID Address) +{ + ULONG Entry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + Entry = MmGetPageEntry1(Address); + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(Entry); +} + + +PHYSICAL_ADDRESS +MmGetPhysicalAddressForProcess(PEPROCESS Process, + PVOID Address) +{ + ULONG PageEntry; + + PageEntry = MmGetPageEntryForProcess(Process, Address); + + if (!(PageEntry & PA_PRESENT)) + { + return((LARGE_INTEGER)0LL); + } + return(PTE_TO_PAGE(PageEntry)); +} + +VOID +MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr) +/* + * FUNCTION: Delete a virtual mapping + */ +{ + ULONG Pte; + PULONG Pde; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + BOOLEAN WasValid; + + /* + * If we are setting a page in another process we need to be in its + * context. + */ + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + + /* + * Set the page directory entry, we may have to copy the entry from + * the global page directory. + */ + Pde = ADDR_TO_PDE(Address); + if ((*Pde) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + if ((*Pde) == 0) + { + KeBugCheck(0); + } + + /* + * Atomically set the entry to zero and get the old value. + */ + Pte = *ADDR_TO_PTE(Address); + *ADDR_TO_PTE(Address) = Pte & (~PA_PRESENT); + FLUSH_TLB; + WasValid = (PAGE_MASK(Pte) != 0); + if (!WasValid) + { + KeBugCheck(0); + } + + /* + * If necessary go back to the original context + */ + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + + /* + * Return some information to the caller + */ + if (WasDirty != NULL) + { + *WasDirty = Pte & PA_DIRTY; + } + if (PhysicalAddr != NULL) + { + PhysicalAddr->u.HighPart = 0; + PhysicalAddr->u.LowPart = PAGE_MASK(Pte); + } +} + +VOID +MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage, + BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr) +/* + * FUNCTION: Delete a virtual mapping + */ +{ + ULONG Pte; + PULONG Pde; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + BOOLEAN WasValid; + + /* + * If we are setting a page in another process we need to be in its + * context. + */ + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + + /* + * Set the page directory entry, we may have to copy the entry from + * the global page directory. + */ + Pde = ADDR_TO_PDE(Address); + if ((*Pde) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + if ((*Pde) == 0) + { + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + if (WasDirty != NULL) + { + *WasDirty = FALSE; + } + if (PhysicalAddr != NULL) + { + *PhysicalAddr = (LARGE_INTEGER)0LL; + } + return; + } + + /* + * Atomically set the entry to zero and get the old value. + */ + Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0); + FLUSH_TLB; + WasValid = (PAGE_MASK(Pte) != 0); + if (WasValid) + { + MmMarkPageUnmapped(PTE_TO_PAGE(Pte)); + } + if (FreePage && WasValid) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PTE_TO_PAGE(Pte)); + } + + /* + * Decrement the reference count for this page table. + */ + if (Process != NULL && WasValid && + Process->AddressSpace.PageTableRefCountTable != NULL && + ADDR_TO_PAGE_TABLE(Address) < 768) + { + PUSHORT Ptrc; + + Ptrc = Process->AddressSpace.PageTableRefCountTable; + + Ptrc[ADDR_TO_PAGE_TABLE(Address)]--; + if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0) + { + MmFreePageTable(Process, Address); + } + } + + /* + * If necessary go back to the original context + */ + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + + /* + * Return some information to the caller + */ + if (WasDirty != NULL) + { + if (Pte & PA_DIRTY) + { + *WasDirty = TRUE; + } + else + { + *WasDirty = FALSE; + } + } + if (PhysicalAddr != NULL) + { + *PhysicalAddr = PTE_TO_PAGE(Pte); + } +} + +VOID +MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, + SWAPENTRY* SwapEntry) +/* + * FUNCTION: Delete a virtual mapping + */ +{ + ULONG Pte; + PULONG Pde; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + BOOLEAN WasValid = FALSE; + + /* + * If we are setting a page in another process we need to be in its + * context. + */ + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + + /* + * Set the page directory entry, we may have to copy the entry from + * the global page directory. + */ + Pde = ADDR_TO_PDE(Address); + if ((*Pde) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + if ((*Pde) == 0) + { + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + *SwapEntry = 0; + return; + } + + /* + * Atomically set the entry to zero and get the old value. + */ + Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0); + FLUSH_TLB; + + /* + * Decrement the reference count for this page table. + */ + if (Process != NULL && WasValid && + Process->AddressSpace.PageTableRefCountTable != NULL && + ADDR_TO_PAGE_TABLE(Address) < 768) + { + PUSHORT Ptrc; + + Ptrc = Process->AddressSpace.PageTableRefCountTable; + + Ptrc[ADDR_TO_PAGE_TABLE(Address)]--; + if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0) + { + MmFreePageTable(Process, Address); + } + } + + /* + * If necessary go back to the original context + */ + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + + /* + * Return some information to the caller + */ + *SwapEntry = Pte >> 1; +} + +BOOLEAN +Mmi386MakeKernelPageTableGlobal(PVOID PAddress) +{ + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + + page_dir = ADDR_TO_PDE(Address); + if ((*page_dir) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + return(TRUE); + } + return(FALSE); +} + +BOOLEAN MmIsPageTablePresent(PVOID PAddress) +{ + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + + page_dir = ADDR_TO_PDE(Address); + if ((*page_dir) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + return((*page_dir) == 0); +} + +NTSTATUS MmCreatePageTable(PVOID PAddress) +{ + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + PHYSICAL_ADDRESS npage; + + DPRINT("MmGetPageEntry(Address %x)\n", Address); + + page_dir = ADDR_TO_PDE(Address); + DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); + if ((*page_dir) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + if ((*page_dir) == 0) + { + NTSTATUS Status; + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + (*page_dir) = npage.QuadPart | 0x7; + memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGE_SIZE); + FLUSH_TLB; + } + return(STATUS_SUCCESS); +} + +PULONG MmGetPageEntry(PVOID PAddress) +/* + * FUNCTION: Get a pointer to the page table entry for a virtual address + */ +{ + PULONG page_tlb; + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + PHYSICAL_ADDRESS npage; + + DPRINT("MmGetPageEntry(Address %x)\n", Address); + + page_dir = ADDR_TO_PDE(Address); + DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); + if ((*page_dir) == 0 && + MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0) + { + (*page_dir) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)]; + FLUSH_TLB; + } + if ((*page_dir) == 0) + { + NTSTATUS Status; + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &npage); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + (*page_dir) = npage.QuadPart | 0x7; + memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGE_SIZE); + FLUSH_TLB; + } + page_tlb = ADDR_TO_PTE(Address); + DPRINT("page_tlb %x\n",page_tlb); + return(page_tlb); +} + +BOOLEAN MmIsDirtyPage(PEPROCESS Process, PVOID Address) +{ + return((MmGetPageEntryForProcess(Process, Address)) & PA_DIRTY); +} + +BOOLEAN +MmIsAccessedAndResetAccessPage(PEPROCESS Process, PVOID Address) +{ + PULONG PageEntry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + BOOLEAN Accessed; + + if (Process != CurrentProcess) + { + KeAttachProcess(Process); + } + PageEntry = MmGetPageEntry(Address); + Accessed = (*PageEntry) & PA_ACCESSED; + if (Accessed) + { + (*PageEntry) = (*PageEntry) & (~PA_ACCESSED); + FLUSH_TLB; + } + if (Process != CurrentProcess) + { + KeDetachProcess(); + } + + return(Accessed); +} + +VOID MmSetCleanPage(PEPROCESS Process, PVOID Address) +{ + PULONG PageEntry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != CurrentProcess) + { + KeAttachProcess(Process); + } + PageEntry = MmGetPageEntry(Address); + (*PageEntry) = (*PageEntry) & (~PA_DIRTY); + FLUSH_TLB; + if (Process != CurrentProcess) + { + KeDetachProcess(); + } +} + +VOID MmSetDirtyPage(PEPROCESS Process, PVOID Address) +{ + PULONG PageEntry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != CurrentProcess) + { + KeAttachProcess(Process); + } + PageEntry = MmGetPageEntry(Address); + (*PageEntry) = (*PageEntry) | PA_DIRTY; + FLUSH_TLB; + if (Process != CurrentProcess) + { + KeDetachProcess(); + } +} + +VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address) +{ + PULONG PageEntry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != CurrentProcess) + { + KeAttachProcess(Process); + } + PageEntry = MmGetPageEntry(Address); + (*PageEntry) = (*PageEntry) | PA_PRESENT; + FLUSH_TLB; + if (Process != CurrentProcess) + { + KeDetachProcess(); + } +} + +BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address) +{ + return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT); +} + +BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address) +{ + ULONG Pte; + Pte = MmGetPageEntryForProcess1(Process, Address); + return((!(Pte & PA_PRESENT)) && Pte != 0); +} + +NTSTATUS +MmCreateVirtualMappingForKernel(PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress) +{ + PEPROCESS CurrentProcess; + ULONG Attributes; + PULONG Pte; + NTSTATUS Status; + PEPROCESS Process = NULL; + + if (Process != NULL) + { + CurrentProcess = PsGetCurrentProcess(); + } + else + { + CurrentProcess = NULL; + } + + if (Process == NULL && Address < (PVOID)KERNEL_BASE) + { + DPRINT1("No process\n"); + KeBugCheck(0); + } + if (Process != NULL && Address >= (PVOID)KERNEL_BASE) + { + DPRINT1("Setting kernel address with process context\n"); + KeBugCheck(0); + } + Attributes = ProtectToPTE(flProtect); + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + + Status = MmGetPageEntry2(Address, &Pte, FALSE); + if (!NT_SUCCESS(Status)) + { + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(Status); + } + if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT)) + { + KeBugCheck(0); + } + if (PAGE_MASK((*Pte)) != 0) + { + MmMarkPageUnmapped(PTE_TO_PAGE((*Pte))); + } + *Pte = PhysicalAddress.QuadPart | Attributes; + if (Process != NULL && + Process->AddressSpace.PageTableRefCountTable != NULL && + ADDR_TO_PAGE_TABLE(Address) < 768 && + Attributes & PA_PRESENT) + { + PUSHORT Ptrc; + + Ptrc = Process->AddressSpace.PageTableRefCountTable; + + Ptrc[ADDR_TO_PAGE_TABLE(Address)]++; + } + FLUSH_TLB; + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(STATUS_SUCCESS); +} + +NTSTATUS +MmCreatePageFileMapping(PEPROCESS Process, + PVOID Address, + SWAPENTRY SwapEntry) +{ + PEPROCESS CurrentProcess; + PULONG Pte; + NTSTATUS Status; + + if (Process != NULL) + { + CurrentProcess = PsGetCurrentProcess(); + } + else + { + CurrentProcess = NULL; + } + + if (Process == NULL && Address < (PVOID)KERNEL_BASE) + { + DPRINT1("No process\n"); + KeBugCheck(0); + } + if (Process != NULL && Address >= (PVOID)KERNEL_BASE) + { + DPRINT1("Setting kernel address with process context\n"); + KeBugCheck(0); + } + if (SwapEntry & (1 << 31)) + { + KeBugCheck(0); + } + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + + Status = MmGetPageEntry2(Address, &Pte, FALSE); + if (!NT_SUCCESS(Status)) + { + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(Status); + } + if (PAGE_MASK((*Pte)) != 0) + { + MmMarkPageUnmapped(PTE_TO_PAGE((*Pte))); + } + *Pte = SwapEntry << 1; + if (Process != NULL && + Process->AddressSpace.PageTableRefCountTable != NULL && + ADDR_TO_PAGE_TABLE(Address) < 768) + { + PUSHORT Ptrc; + + Ptrc = Process->AddressSpace.PageTableRefCountTable; + + Ptrc[ADDR_TO_PAGE_TABLE(Address)]++; + } + FLUSH_TLB; + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(STATUS_SUCCESS); +} + +NTSTATUS +MmCreateVirtualMappingUnsafe(PEPROCESS Process, + PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress, + BOOLEAN MayWait) +{ + PEPROCESS CurrentProcess; + ULONG Attributes; + PULONG Pte; + NTSTATUS Status; + + if (Process != NULL) + { + CurrentProcess = PsGetCurrentProcess(); + } + else + { + CurrentProcess = NULL; + } + + if (Process == NULL && Address < (PVOID)KERNEL_BASE) + { + DPRINT1("No process\n"); + KeBugCheck(0); + } + if (Process != NULL && Address >= (PVOID)KERNEL_BASE) + { + DPRINT1("Setting kernel address with process context\n"); + KeBugCheck(0); + } + MmMarkPageMapped(PhysicalAddress); + + Attributes = ProtectToPTE(flProtect); + if (!(Attributes & PA_PRESENT) && PhysicalAddress.QuadPart != 0) + { + DPRINT1("Setting physical address but not allowing access at address " + "0x%.8X with attributes %x/%x.\n", + Address, Attributes, flProtect); + KeBugCheck(0); + } + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + + Status = MmGetPageEntry2(Address, &Pte, MayWait); + if (!NT_SUCCESS(Status)) + { + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(Status); + } + if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT)) + { + KeBugCheck(0); + } + if (PAGE_MASK((*Pte)) != 0) + { + MmMarkPageUnmapped(PTE_TO_PAGE((*Pte))); + } + *Pte = PhysicalAddress.QuadPart | Attributes; + if (Process != NULL && + Process->AddressSpace.PageTableRefCountTable != NULL && + ADDR_TO_PAGE_TABLE(Address) < 768 && + Attributes & PA_PRESENT) + { + PUSHORT Ptrc; + + Ptrc = Process->AddressSpace.PageTableRefCountTable; + + Ptrc[ADDR_TO_PAGE_TABLE(Address)]++; + } + FLUSH_TLB; + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(STATUS_SUCCESS); +} + +NTSTATUS +MmCreateVirtualMapping(PEPROCESS Process, + PVOID Address, + ULONG flProtect, + PHYSICAL_ADDRESS PhysicalAddress, + BOOLEAN MayWait) +{ + if (!MmIsUsablePage(PhysicalAddress)) + { + DPRINT1("Page at address %x not usable\n", PhysicalAddress); + KeBugCheck(0); + } + + return(MmCreateVirtualMappingUnsafe(Process, + Address, + flProtect, + PhysicalAddress, + MayWait)); +} + +ULONG +MmGetPageProtect(PEPROCESS Process, PVOID Address) +{ + ULONG Entry; + ULONG Protect; + + Entry = MmGetPageEntryForProcess1(Process, Address); + + if (!(Entry & PA_PRESENT)) + { + Protect = PAGE_NOACCESS; + } + else if (Entry & PA_READWRITE) + { + Protect = PAGE_READWRITE; + } + else + { + Protect = PAGE_EXECUTE_READ; + } + return(Protect); +} + +VOID +MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect) +{ + ULONG Attributes = 0; + PULONG PageEntry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + DPRINT("MmSetPageProtect(Process %x Address %x flProtect %x)\n", + Process, Address, flProtect); + + Attributes = ProtectToPTE(flProtect); + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + PageEntry = MmGetPageEntry(Address); + (*PageEntry) = PAGE_MASK(*PageEntry) | Attributes; + FLUSH_TLB; + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } +} + +PHYSICAL_ADDRESS STDCALL +MmGetPhysicalAddress(PVOID vaddr) +/* + * FUNCTION: Returns the physical address corresponding to a virtual address + */ +{ + PHYSICAL_ADDRESS p; + ULONG Pte; + + DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr); + + Pte = *MmGetPageEntry(vaddr); + if (Pte & PA_PRESENT) + { + p.QuadPart = PAGE_MASK(Pte); + } + else + { + p.QuadPart = 0; + } + + return p; +} + + +/* EOF */ diff --git a/ntoskrnl/mm/i386/pfault.c b/ntoskrnl/mm/i386/pfault.c new file mode 100644 index 0000000..fe09feb --- /dev/null +++ b/ntoskrnl/mm/i386/pfault.c @@ -0,0 +1,95 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/i386/pfault.c + * PURPOSE: Paging file functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* EXTERNS *******************************************************************/ + +extern VOID MmSafeCopyFromUserUnsafeStart(VOID); +extern VOID MmSafeCopyFromUserRestart(VOID); +extern VOID MmSafeCopyToUserUnsafeStart(VOID); +extern VOID MmSafeCopyToUserRestart(VOID); + +extern ULONG MmGlobalKernelPageDirectory[1024]; + +BOOLEAN +Mmi386MakeKernelPageTableGlobal(PVOID Address); + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS MmPageFault(ULONG Cs, + PULONG Eip, + PULONG Eax, + ULONG Cr2, + ULONG ErrorCode) +{ + KPROCESSOR_MODE Mode; + NTSTATUS Status; + + DPRINT("MmPageFault(Eip %x, Cr2 %x, ErrorCode %x)\n", + Eip, Cr2, ErrorCode); + + if (ErrorCode & 0x4) + { + Mode = UserMode; + } + else + { + Mode = KernelMode; + } + + if (Mode == KernelMode && Cr2 >= KERNEL_BASE && + Mmi386MakeKernelPageTableGlobal((PVOID)Cr2)) + { + return(STATUS_SUCCESS); + } + + if (ErrorCode & 0x1) + { + Status = MmAccessFault(Mode, Cr2, FALSE); + } + else + { + Status = MmNotPresentFault(Mode, Cr2, FALSE); + } + + if (KeGetCurrentThread() != NULL && + KeGetCurrentThread()->Alerted[1] != 0 && + Cs != KERNEL_CS) + { + KiDeliverNormalApc(); + } + if (!NT_SUCCESS(Status) && (Mode == KernelMode) && + ((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) && + ((*Eip) <= (ULONG)MmSafeCopyFromUserRestart)) + { + (*Eip) = (ULONG)MmSafeCopyFromUserRestart; + (*Eax) = STATUS_ACCESS_VIOLATION; + return(STATUS_SUCCESS); + } + if (!NT_SUCCESS(Status) && (Mode == KernelMode) && + ((*Eip) >= (ULONG)MmSafeCopyToUserUnsafeStart) && + ((*Eip) <= (ULONG)MmSafeCopyToUserRestart)) + { + (*Eip) = (ULONG)MmSafeCopyToUserRestart; + (*Eax) = STATUS_ACCESS_VIOLATION; + return(STATUS_SUCCESS); + } + return(Status); +} diff --git a/ntoskrnl/mm/iospace.c b/ntoskrnl/mm/iospace.c new file mode 100644 index 0000000..a1b55a9 --- /dev/null +++ b/ntoskrnl/mm/iospace.c @@ -0,0 +1,173 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/iospace.c + * PURPOSE: Mapping I/O space + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/********************************************************************** + * NAME EXPORTED + * MmMapIoSpace@16 + * + * DESCRIPTION + * Maps a physical memory range into system space. + * + * ARGUMENTS + * PhysicalAddress + * First physical address to map; + * + * NumberOfBytes + * Number of bytes to map; + * + * CacheEnable + * TRUE if the range can be cached. + * + * RETURN VALUE + * The base virtual address which maps the region. + * + * NOTE + * Description moved here from include/ddk/mmfuncs.h. + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +PVOID STDCALL +MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG NumberOfBytes, + IN BOOLEAN CacheEnable) +{ + PVOID Result; + MEMORY_AREA* marea; + NTSTATUS Status; + ULONG i; + ULONG Attributes; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Result = NULL; + Status = MmCreateMemoryArea (NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_IO_MAPPING, + &Result, + NumberOfBytes, + 0, + &marea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + if (!NT_SUCCESS(STATUS_SUCCESS)) + { + return (NULL); + } + Attributes = PAGE_EXECUTE_READWRITE | PAGE_SYSTEM; + if (!CacheEnable) + { + Attributes |= (PAGE_NOCACHE | PAGE_WRITETHROUGH); + } + for (i = 0; (i < ((NumberOfBytes + PAGE_SIZE - 1) / PAGE_SIZE)); i++) + { + Status = + MmCreateVirtualMappingForKernel(Result + (i * PAGE_SIZE), + Attributes, + (PHYSICAL_ADDRESS) + (PhysicalAddress.QuadPart + + (i * PAGE_SIZE))); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + } + return ((PVOID)(Result + PhysicalAddress.QuadPart % PAGE_SIZE)); +} + + +/********************************************************************** + * NAME EXPORTED + * MmUnmapIoSpace@8 + * + * DESCRIPTION + * Unmaps a physical memory range from system space. + * + * ARGUMENTS + * BaseAddress + * The base virtual address which maps the region; + * + * NumberOfBytes + * Number of bytes to unmap. + * + * RETURN VALUE + * None. + * + * NOTE + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +VOID STDCALL +MmUnmapIoSpace (IN PVOID BaseAddress, + IN ULONG NumberOfBytes) +{ + (VOID)MmFreeMemoryArea(&PsGetCurrentProcess()->AddressSpace, + (PVOID)(((ULONG)BaseAddress / PAGE_SIZE) * PAGE_SIZE), + NumberOfBytes, + NULL, + NULL); +} + + +/********************************************************************** + * NAME EXPORTED + * MmMapVideoDisplay@16 + */ +PVOID STDCALL +MmMapVideoDisplay (IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG NumberOfBytes, + IN MEMORY_CACHING_TYPE CacheType) +{ + return MmMapIoSpace (PhysicalAddress, NumberOfBytes, CacheType); +} + + +VOID STDCALL +MmUnmapVideoDisplay (IN PVOID BaseAddress, + IN ULONG NumberOfBytes) +{ + MmUnmapIoSpace (BaseAddress, NumberOfBytes); +} + + +/* EOF */ diff --git a/ntoskrnl/mm/kmap.c b/ntoskrnl/mm/kmap.c new file mode 100644 index 0000000..6980931 --- /dev/null +++ b/ntoskrnl/mm/kmap.c @@ -0,0 +1,209 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/kmap.c + * PURPOSE: Implements the kernel memory pool + * PROGRAMMER: David Welch (welch@cwcom.net) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +#define ALLOC_MAP_SIZE (NONPAGED_POOL_SIZE / PAGE_SIZE) + +/* + * One bit for each page in the kmalloc region + * If set then the page is used by a kmalloc block + */ +static ULONG AllocMap[ALLOC_MAP_SIZE/32]={0,}; +static KSPIN_LOCK AllocMapLock; +static ULONG AllocMapHint = 1; + +static PVOID NonPagedPoolBase; + +/* FUNCTIONS ***************************************************************/ + +VOID +ExUnmapPage(PVOID Addr) +{ + KIRQL oldIrql; + ULONG i = (Addr - NonPagedPoolBase) / PAGE_SIZE; + + DPRINT("ExUnmapPage(Addr %x)\n",Addr); + DPRINT("i %x\n",i); + + MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL); + KeAcquireSpinLock(&AllocMapLock, &oldIrql); + AllocMap[i / 32] &= (~(1 << (i % 32))); + AllocMapHint = min(AllocMapHint, i); + KeReleaseSpinLock(&AllocMapLock, oldIrql); +} + +PVOID +ExAllocatePage(VOID) +{ + PHYSICAL_ADDRESS PhysPage; + NTSTATUS Status; + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PhysPage); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + + return(ExAllocatePageWithPhysPage(PhysPage)); +} + +NTSTATUS +MiZeroPage(PHYSICAL_ADDRESS PhysPage) +{ + PVOID TempAddress; + + TempAddress = ExAllocatePageWithPhysPage(PhysPage); + if (TempAddress == NULL) + { + return(STATUS_NO_MEMORY); + } + memset(TempAddress, 0, PAGE_SIZE); + ExUnmapPage(TempAddress); + return(STATUS_SUCCESS); +} + +NTSTATUS +MiCopyFromUserPage(PHYSICAL_ADDRESS DestPhysPage, PVOID SourceAddress) +{ + PVOID TempAddress; + + TempAddress = ExAllocatePageWithPhysPage(DestPhysPage); + if (TempAddress == NULL) + { + return(STATUS_NO_MEMORY); + } + memcpy(TempAddress, SourceAddress, PAGE_SIZE); + ExUnmapPage(TempAddress); + return(STATUS_SUCCESS); +} + +PVOID +ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage) +{ + KIRQL oldlvl; + ULONG addr; + ULONG i; + NTSTATUS Status; + + KeAcquireSpinLock(&AllocMapLock, &oldlvl); + for (i = AllocMapHint; i < ALLOC_MAP_SIZE; i++) + { + if (!(AllocMap[i / 32] & (1 << (i % 32)))) + { + DPRINT("i %x\n",i); + AllocMap[i / 32] |= (1 << (i % 32)); + AllocMapHint = i + 1; + addr = (ULONG)(NonPagedPoolBase + (i*PAGE_SIZE)); + Status = MmCreateVirtualMapping(NULL, + (PVOID)addr, + PAGE_READWRITE | PAGE_SYSTEM, + PhysPage, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + KeReleaseSpinLock(&AllocMapLock, oldlvl); + return((PVOID)addr); + } + } + KeReleaseSpinLock(&AllocMapLock, oldlvl); + return(NULL); +} + +VOID +MmInitKernelMap(PVOID BaseAddress) +{ + NonPagedPoolBase = BaseAddress; + KeInitializeSpinLock(&AllocMapLock); +} + +VOID +MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free) +{ + ULONG i; + ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE; + ULONG Offset; + KIRQL oldlvl; + + KeAcquireSpinLock(&AllocMapLock, &oldlvl); + AllocMapHint = min(AllocMapHint, Base); + for (i = 0; i < Count; i++) + { + Offset = Base + i; + AllocMap[Offset / 32] &= (~(1 << (Offset % 32))); + MmDeleteVirtualMapping(NULL, + Addr + (i * PAGE_SIZE), + Free, + NULL, + NULL); + } + KeReleaseSpinLock(&AllocMapLock, oldlvl); +} + +PVOID +MiAllocNonPagedPoolRegion(ULONG nr_pages) +/* + * FUNCTION: Allocates a region of pages within the nonpaged pool area + */ +{ + unsigned int start = 0; + unsigned int length = 0; + unsigned int i,j; + KIRQL oldlvl; + + KeAcquireSpinLock(&AllocMapLock, &oldlvl); + for (i=AllocMapHint; i +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_MAREA TAG('M', 'A', 'R', 'E') + +/* FUNCTIONS *****************************************************************/ + +VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead) +{ + PLIST_ENTRY current_entry; + MEMORY_AREA* current; + + DbgPrint("MmDumpMemoryAreas()\n"); + + current_entry = ListHead->Flink; + while (current_entry!=ListHead) + { + current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); + DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n", + current->BaseAddress,current->Length, + current->BaseAddress+current->Length,current->Attributes, + current->Entry.Flink); + current_entry = current_entry->Flink; + } + DbgPrint("Finished MmDumpMemoryAreas()\n"); +} + +MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace, + PVOID Address) +{ + PLIST_ENTRY current_entry; + MEMORY_AREA* current; + PLIST_ENTRY previous_entry; + + DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n", + AddressSpace, Address); + + previous_entry = &AddressSpace->MAreaListHead; + current_entry = AddressSpace->MAreaListHead.Flink; + while (current_entry != &AddressSpace->MAreaListHead) + { + current = CONTAINING_RECORD(current_entry, + MEMORY_AREA, + Entry); + assert(current_entry->Blink->Flink == current_entry); + assert(current_entry->Flink->Blink == current_entry); + assert(previous_entry->Flink == current_entry); + if (current->BaseAddress <= Address && + (current->BaseAddress + current->Length) > Address) + { + DPRINT("%s() = %x\n",__FUNCTION__,current); + return(current); + } + if (current->BaseAddress > Address) + { + DPRINT("%s() = NULL\n",__FUNCTION__); + return(NULL); + } + previous_entry = current_entry; + current_entry = current_entry->Flink; + } + DPRINT("%s() = NULL\n",__FUNCTION__); + return(NULL); +} + +MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, + PVOID Address, + ULONG Length) +{ + PLIST_ENTRY current_entry; + MEMORY_AREA* current; + ULONG Extent; + + DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n", + AddressSpace, Address, Length); + + current_entry = AddressSpace->MAreaListHead.Flink; + while (current_entry != &AddressSpace->MAreaListHead) + { + current = CONTAINING_RECORD(current_entry, + MEMORY_AREA, + Entry); + DPRINT("current->BaseAddress %x current->Length %x\n", + current->BaseAddress,current->Length); + if (current->BaseAddress >= Address && + current->BaseAddress < (Address+Length)) + { + DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n", + current); + return(current); + } + Extent = (ULONG)current->BaseAddress + current->Length; + if (Extent > (ULONG)Address && + Extent < (ULONG)(Address+Length)) + { + DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n", + current); + return(current); + } + if (current->BaseAddress <= Address && + Extent >= (ULONG)(Address+Length)) + { + DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n", + current); + return(current); + } + if (current->BaseAddress >= (Address+Length)) + { + DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0); + return(NULL); + } + current_entry = current_entry->Flink; + } + DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0); + return(NULL); +} + +static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* marea) +{ + PLIST_ENTRY ListHead; + PLIST_ENTRY current_entry; + PLIST_ENTRY inserted_entry = &marea->Entry; + MEMORY_AREA* current; + MEMORY_AREA* next; + + DPRINT("MmInsertMemoryArea(marea %x)\n", marea); + DPRINT("marea->BaseAddress %x\n", marea->BaseAddress); + DPRINT("marea->Length %x\n", marea->Length); + + ListHead = &AddressSpace->MAreaListHead; + + current_entry = ListHead->Flink; + if (IsListEmpty(ListHead)) + { + InsertHeadList(ListHead,&marea->Entry); + return; + } + current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); + if (current->BaseAddress > marea->BaseAddress) + { + InsertHeadList(ListHead,&marea->Entry); + return; + } + while (current_entry->Flink!=ListHead) + { + current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); + next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry); + if (current->BaseAddress < marea->BaseAddress && + current->Entry.Flink==ListHead) + { + current_entry->Flink = inserted_entry; + inserted_entry->Flink=ListHead; + inserted_entry->Blink=current_entry; + ListHead->Blink = inserted_entry; + return; + } + if (current->BaseAddress < marea->BaseAddress && + next->BaseAddress > marea->BaseAddress) + { + inserted_entry->Flink = current_entry->Flink; + inserted_entry->Blink = current_entry; + inserted_entry->Flink->Blink = inserted_entry; + current_entry->Flink=inserted_entry; + return; + } + current_entry = current_entry->Flink; + } + InsertTailList(ListHead,inserted_entry); +} + +PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length) +{ + PLIST_ENTRY ListHead; + PLIST_ENTRY current_entry; + MEMORY_AREA* current; + MEMORY_AREA* next; + ULONG Gap; + + DPRINT("MmFindGap(Length %x)\n",Length); + + ListHead = &AddressSpace->MAreaListHead; + + current_entry = ListHead->Flink; + while (current_entry->Flink!=ListHead) + { + current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); + next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry); + Gap = (next->BaseAddress ) -(current->BaseAddress + current->Length); + if (Gap >= Length) + { + return(current->BaseAddress + PAGE_ROUND_UP(current->Length)); + } + current_entry = current_entry->Flink; + } + + if (current_entry == ListHead) + { + return((PVOID)AddressSpace->LowestAddress); + } + + current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry); + return(current->BaseAddress + PAGE_ROUND_UP(current->Length)); +} + +NTSTATUS MmInitMemoryAreas(VOID) +/* + * FUNCTION: Initialize the memory area list + */ +{ + DPRINT("MmInitMemoryAreas()\n",0); + return(STATUS_SUCCESS); +} + +NTSTATUS +MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, + ULONG Length, + VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, + PVOID Address, PHYSICAL_ADDRESS PhysAddr, + SWAPENTRY SwapEntry, BOOLEAN Dirty), + PVOID FreePageContext) +{ + MEMORY_AREA* MemoryArea; + ULONG i; + + DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x," + "FreePageContext %d)\n",AddressSpace,BaseAddress,Length, + FreePageContext); + + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, + BaseAddress); + if (MemoryArea == NULL) + { + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); + } + for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGE_SIZE); i++) + { + PHYSICAL_ADDRESS PhysAddr = (PHYSICAL_ADDRESS)0LL; + BOOL Dirty; + SWAPENTRY SwapEntry = 0; + + if (MmIsPageSwapEntry(AddressSpace->Process, + MemoryArea->BaseAddress + (i * PAGE_SIZE))) + { + MmDeletePageFileMapping(AddressSpace->Process, + MemoryArea->BaseAddress + (i * PAGE_SIZE), + &SwapEntry); + } + else + { + MmDeleteVirtualMapping(AddressSpace->Process, + MemoryArea->BaseAddress + (i*PAGE_SIZE), + FALSE, &Dirty, &PhysAddr); + } + if (FreePage != NULL) + { + FreePage(FreePageContext, MemoryArea, + MemoryArea->BaseAddress + (i * PAGE_SIZE), PhysAddr, + SwapEntry, Dirty); + } + } + + RemoveEntryList(&MemoryArea->Entry); + ExFreePool(MemoryArea); + + DPRINT("MmFreeMemoryArea() succeeded\n"); + + return(STATUS_SUCCESS); +} + +PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA OriginalMemoryArea, + PVOID BaseAddress, + ULONG Length, + ULONG NewType, + ULONG NewAttributes) +{ + PMEMORY_AREA Result; + PMEMORY_AREA Split; + + Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA), + TAG_MAREA); + RtlZeroMemory(Result,sizeof(MEMORY_AREA)); + Result->Type = NewType; + Result->BaseAddress = BaseAddress; + Result->Length = Length; + Result->Attributes = NewAttributes; + Result->LockCount = 0; + Result->Process = Process; + + if (BaseAddress == OriginalMemoryArea->BaseAddress) + { + OriginalMemoryArea->BaseAddress = BaseAddress + Length; + OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length; + MmInsertMemoryArea(AddressSpace, Result); + return(Result); + } + if ((BaseAddress + Length) == + (OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length)) + { + OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length; + MmInsertMemoryArea(AddressSpace, Result); + + return(Result); + } + + Split = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA), + TAG_MAREA); + RtlCopyMemory(Split,OriginalMemoryArea,sizeof(MEMORY_AREA)); + Split->BaseAddress = BaseAddress + Length; + Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress) + + Length); + + OriginalMemoryArea->Length = BaseAddress - OriginalMemoryArea->BaseAddress; + + return(Split); +} + +NTSTATUS MmCreateMemoryArea(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + ULONG Type, + PVOID* BaseAddress, + ULONG Length, + ULONG Attributes, + MEMORY_AREA** Result, + BOOL FixedAddress) +/* + * FUNCTION: Create a memory area + * ARGUMENTS: + * AddressSpace = Address space to create the area in + * Type = Type of the address space + * BaseAddress = + * Length = Length to allocate + * Attributes = Protection attributes for the memory area + * Result = Receives a pointer to the memory area on exit + * RETURNS: Status + * NOTES: Lock the address space before calling this function + */ +{ + DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x," + "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n", + Type,BaseAddress,*BaseAddress,Length,Attributes,Result); + + if ((*BaseAddress)==0 && !FixedAddress) + { + *BaseAddress = MmFindGap(AddressSpace, + PAGE_ROUND_UP(Length) +(PAGE_SIZE*2)); + if ((*BaseAddress)==0) + { + DPRINT("No suitable gap\n"); + return(STATUS_NO_MEMORY); + } + (*BaseAddress)=(*BaseAddress)+PAGE_SIZE; + } + else + { + (*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress)); + if (MmOpenMemoryAreaByRegion(AddressSpace, + *BaseAddress, + Length)!=NULL) + { + DPRINT("Memory area already occupied\n"); + return(STATUS_CONFLICTING_ADDRESSES); + } + } + + *Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA), + TAG_MAREA); + RtlZeroMemory(*Result,sizeof(MEMORY_AREA)); + (*Result)->Type = Type; + (*Result)->BaseAddress = *BaseAddress; + (*Result)->Length = Length; + (*Result)->Attributes = Attributes; + (*Result)->LockCount = 0; + (*Result)->Process = Process; + (*Result)->PageOpCount = 0; + (*Result)->DeleteInProgress = FALSE; + + MmInsertMemoryArea(AddressSpace, *Result); + + DPRINT("MmCreateMemoryArea() succeeded\n"); + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/mm/mdl.c b/ntoskrnl/mm/mdl.c new file mode 100644 index 0000000..9ce47a3 --- /dev/null +++ b/ntoskrnl/mm/mdl.c @@ -0,0 +1,453 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/mdl.c + * PURPOSE: Manipulates MDLs + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 27/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_MDL TAG('M', 'M', 'D', 'L') + +#define MI_MDL_MAPPING_REGION_SIZE (256*1024*1024) + +static PVOID MiMdlMappingRegionBase = NULL; +static PULONG MiMdlMappingRegionAllocMap = NULL; +static ULONG MiMdlMappingRegionHighWaterMark = 0; +static KSPIN_LOCK MiMdlMappingRegionLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +MmInitializeMdlImplementation(VOID) +{ + MEMORY_AREA* Result; + NTSTATUS Status; + + MiMdlMappingRegionBase = NULL; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_MDL_MAPPING, + &MiMdlMappingRegionBase, + MI_MDL_MAPPING_REGION_SIZE, + 0, + &Result, + FALSE); + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + KeBugCheck(0); + } + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + MiMdlMappingRegionAllocMap = + ExAllocatePool(NonPagedPool, + MI_MDL_MAPPING_REGION_SIZE / (PAGE_SIZE * 32)); + MiMdlMappingRegionHighWaterMark = 0; + KeInitializeSpinLock(&MiMdlMappingRegionLock); +} + +PVOID +MmGetMdlPageAddress(PMDL Mdl, PVOID Offset) +{ + PULONG MdlPages; + + MdlPages = (PULONG)(Mdl + 1); + + return((PVOID)MdlPages[((ULONG)Offset) / PAGE_SIZE]); +} + +VOID STDCALL +MmUnlockPages(PMDL Mdl) +/* + * FUNCTION: Unlocks the physical pages described by a given MDL + * ARGUMENTS: + * MemoryDescriptorList = MDL describing the buffer to be unlocked + * NOTES: The memory described by the specified MDL must have been locked + * previously by a call to MmProbeAndLockPages. As the pages unlocked, the + * MDL is updated + */ +{ + ULONG i; + PULONG MdlPages; + + /* + * FIXME: I don't know whether this right, but it looks sensible + */ + if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) || + (Mdl->MdlFlags & MDL_IO_PAGE_READ)) + { + return; + } + + /* + * FIXME: Seems sensible + */ + if (!(Mdl->MdlFlags & MDL_PAGES_LOCKED)) + { + return; + } + + MdlPages = (PULONG)(Mdl + 1); + for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGE_SIZE); i++) + { + MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[i]); + MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]); + } + Mdl->MdlFlags = Mdl->MdlFlags & (~MDL_PAGES_LOCKED); +} + +PVOID STDCALL +MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode) +/* + * FUNCTION: Maps the physical pages described by a given MDL + * ARGUMENTS: + * Mdl = Points to an MDL updated by MmProbeAndLockPages + * AccessMode = Specifies the portion of the address space to map the + * pages. + * RETURNS: The base virtual address that maps the locked pages for the + * range described by the MDL + */ +{ + PVOID Base; + ULONG i; + PULONG MdlPages; + KIRQL oldIrql; + ULONG RegionSize; + + DPRINT("MmMapLockedPages(Mdl %x, AccessMode %x)\n", Mdl, AccessMode); + + if (Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) + { + return(Mdl->MappedSystemVa); + } + + if (AccessMode == UserMode) + { + DPRINT1("MDL mapping to user-mode not yet handled.\n"); + KeBugCheck(0); + } + + /* Calculate the number of pages required. */ + RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; + + /* Allocate that number of pages from the mdl mapping region. */ + KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql); + Base = MiMdlMappingRegionBase + MiMdlMappingRegionHighWaterMark * PAGE_SIZE; + for (i = 0; i < RegionSize; i++) + { + ULONG Offset = MiMdlMappingRegionHighWaterMark + i; + MiMdlMappingRegionAllocMap[Offset / 32] |= (1 << (Offset % 32)); + } + MiMdlMappingRegionHighWaterMark += RegionSize; + KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); + + /* Set the virtual mappings for the MDL pages. */ + MdlPages = (PULONG)(Mdl + 1); + for (i = 0; i < RegionSize; i++) + { + NTSTATUS Status; + Status = MmCreateVirtualMapping(NULL, + (PVOID)((ULONG)Base+(i*PAGE_SIZE)), + PAGE_READWRITE, + (LARGE_INTEGER)(LONGLONG)MdlPages[i], + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + } + + /* Mark the MDL has having being mapped. */ + Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; + Mdl->MappedSystemVa = Base + Mdl->ByteOffset; + return(Base + Mdl->ByteOffset); +} + +VOID STDCALL +MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) +/* + * FUNCTION: Releases a mapping set up by a preceding call to MmMapLockedPages + * ARGUMENTS: + * BaseAddress = Base virtual address to which the pages were mapped + * MemoryDescriptorList = MDL describing the mapped pages + */ +{ + KIRQL oldIrql; + ULONG i; + ULONG RegionSize; + ULONG Base; + + DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", Mdl, BaseAddress); + + /* + * In this case, the MDL has the same system address as the base address + * so there is no need to free it + */ + if (Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) + { + return; + } + + /* Calculate the number of pages we mapped. */ + RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE; + + /* Unmap all the pages. */ + for (i = 0; i < RegionSize; i++) + { + MmDeleteVirtualMapping(NULL, + BaseAddress + (i * PAGE_SIZE), + FALSE, + NULL, + NULL); + } + + KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql); + /* Deallocate all the pages used. */ + Base = (ULONG)(BaseAddress - MiMdlMappingRegionBase - Mdl->ByteOffset); + Base = Base / PAGE_SIZE; + for (i = 0; i < RegionSize; i++) + { + ULONG Offset = Base + i; + MiMdlMappingRegionAllocMap[Offset / 32] &= ~(1 << (Offset % 32)); + } + /* If all the pages below the high-water mark are free then move it down. */ + if ((Base + RegionSize) == MiMdlMappingRegionHighWaterMark) + { + MiMdlMappingRegionHighWaterMark = Base; + } + KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); + + /* Reset the MDL state. */ + Mdl->MdlFlags = Mdl->MdlFlags & ~MDL_MAPPED_TO_SYSTEM_VA; + Mdl->MappedSystemVa = NULL; +} + + +VOID +MmBuildMdlFromPages(PMDL Mdl, PULONG Pages) +{ + ULONG i; + PULONG MdlPages; + + Mdl->MdlFlags = Mdl->MdlFlags | + (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ); + + MdlPages = (PULONG)(Mdl + 1); + + for (i=0;i<(PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE);i++) + { + MdlPages[i] = Pages[i]; + } +} + +VOID STDCALL MmProbeAndLockPages (PMDL Mdl, + KPROCESSOR_MODE AccessMode, + LOCK_OPERATION Operation) +/* + * FUNCTION: Probes the specified pages, makes them resident and locks them + * ARGUMENTS: + * Mdl = MDL to probe + * AccessMode = Access at which to probe the buffer + * Operation = Operation to probe for + */ +{ + PULONG MdlPages; + ULONG i, j; + ULONG NrPages; + NTSTATUS Status; + KPROCESSOR_MODE Mode; + PEPROCESS CurrentProcess; + + DPRINT("MmProbeAndLockPages(Mdl %x)\n", Mdl); + + /* + * FIXME: Check behaviour against NT + */ + if (Mdl->MdlFlags & MDL_PAGES_LOCKED) + { + return; + } + + CurrentProcess = PsGetCurrentProcess(); + + if (Mdl->Process != CurrentProcess) + { + KeAttachProcess(Mdl->Process); + } + + if (Mdl->StartVa >= (PVOID)KERNEL_BASE) + { + Mode = KernelMode; + } + else + { + Mode = UserMode; + } + + /* + * Lock the pages + */ + + MmLockAddressSpace(&Mdl->Process->AddressSpace); + MdlPages = (ULONG *)(Mdl + 1); + NrPages = PAGE_ROUND_UP(Mdl->ByteOffset + Mdl->ByteCount) / PAGE_SIZE; + for (i = 0; i < NrPages; i++) + { + PVOID Address; + + Address = Mdl->StartVa + (i*PAGE_SIZE); + + if (!MmIsPagePresent(NULL, Address)) + { + Status = MmNotPresentFault(Mode, (ULONG)Address, TRUE); + if (!NT_SUCCESS(Status)) + { + for (j = 0; j < i; j++) + { + MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]); + MmDereferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[j]); + } + ExRaiseStatus(Status); + } + } + else + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + if ((Operation == IoWriteAccess || Operation == IoModifyAccess) && + (!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE))) + { + Status = MmAccessFault(Mode, (ULONG)Address, TRUE); + if (!NT_SUCCESS(Status)) + { + for (j = 0; j < i; j++) + { + MmUnlockPage((LARGE_INTEGER)(LONGLONG)MdlPages[j]); + MmDereferencePage( + (LARGE_INTEGER)(LONGLONG)MdlPages[j]); + } + ExRaiseStatus(Status); + } + } + MdlPages[i] = MmGetPhysicalAddressForProcess(NULL, Address).u.LowPart; + MmReferencePage((LARGE_INTEGER)(LONGLONG)MdlPages[i]); + } + MmUnlockAddressSpace(&Mdl->Process->AddressSpace); + if (Mdl->Process != CurrentProcess) + { + KeDetachProcess(); + } + Mdl->MdlFlags = Mdl->MdlFlags | MDL_PAGES_LOCKED; +} + + +ULONG STDCALL MmSizeOfMdl (PVOID Base, + ULONG Length) +/* + * FUNCTION: Returns the number of bytes to allocate for an MDL describing + * the given address range + * ARGUMENTS: + * Base = base virtual address + * Length = number of bytes to map + */ +{ + ULONG len; + + len = ADDRESS_AND_SIZE_TO_SPAN_PAGES(Base,Length); + + return(sizeof(MDL)+(len*sizeof(ULONG))); +} + + +VOID STDCALL +MmBuildMdlForNonPagedPool (PMDL Mdl) +/* + * FUNCTION: Fills in the corresponding physical page array of a given + * MDL for a buffer in nonpaged system space + * ARGUMENTS: + * Mdl = Points to an MDL that supplies a virtual address, + * byte offset and length + */ +{ + int va; + Mdl->MdlFlags = Mdl->MdlFlags | + (MDL_SOURCE_IS_NONPAGED_POOL | MDL_PAGES_LOCKED); + for (va=0; va < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); va++) + { + ((PULONG)(Mdl + 1))[va] = + (MmGetPhysicalAddress(Mdl->StartVa + (va * PAGE_SIZE))).u.LowPart; + } + Mdl->MappedSystemVa = Mdl->StartVa + Mdl->ByteOffset; +} + + +PMDL STDCALL +MmCreateMdl (PMDL MemoryDescriptorList, + PVOID Base, + ULONG Length) +/* + * FUNCTION: Allocates and initalizes an MDL + * ARGUMENTS: + * MemoryDescriptorList = Points to MDL to initalize. If this is + * NULL then one is allocated + * Base = Base virtual address of the buffer + * Length = Length in bytes of the buffer + * RETURNS: A pointer to initalized MDL + */ +{ + if (MemoryDescriptorList == NULL) + { + ULONG Size; + + Size = MmSizeOfMdl(Base,Length); + MemoryDescriptorList = + (PMDL)ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MDL); + if (MemoryDescriptorList == NULL) + { + return(NULL); + } + } + + MmInitializeMdl(MemoryDescriptorList,Base,Length); + + return(MemoryDescriptorList); +} + +VOID STDCALL +MmMapMemoryDumpMdl (PVOID Unknown0) +/* + * FIXME: Has something to do with crash dumps. Do we want to implement + * this? + */ +{ + UNIMPLEMENTED; +} + +/* EOF */ + + + + + + + + + diff --git a/ntoskrnl/mm/mm.c b/ntoskrnl/mm/mm.c new file mode 100644 index 0000000..8ace089 --- /dev/null +++ b/ntoskrnl/mm/mm.c @@ -0,0 +1,443 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/mm.c + * PURPOSE: kernel memory managment functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 9/4/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +PVOID EXPORTED MmUserProbeAddress = NULL; +PVOID EXPORTED MmHighestUserAddress = NULL; +MM_STATS MmStats; + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea) +{ + NTSTATUS Status; + + DPRINT("MmReleaseMemoryArea(Process %x, Marea %x)\n",Process,Marea); + + DPRINT("Releasing %x between %x %x (type %d)\n", + Marea, Marea->BaseAddress, Marea->BaseAddress + Marea->Length, + Marea->Type); + + switch (Marea->Type) + { + case MEMORY_AREA_SECTION_VIEW: + Status = MmUnmapViewOfSection(Process, Marea->BaseAddress); + assert(Status == STATUS_SUCCESS); + return(STATUS_SUCCESS); + + case MEMORY_AREA_VIRTUAL_MEMORY: + MmFreeVirtualMemory(Process, Marea); + break; + + case MEMORY_AREA_SHARED_DATA: + Status = MmFreeMemoryArea(&Process->AddressSpace, + Marea->BaseAddress, + 0, + NULL, + NULL); + break; + + default: + KeBugCheck(0); + } + + return(STATUS_SUCCESS); +} + +NTSTATUS MmReleaseMmInfo(PEPROCESS Process) +{ + PLIST_ENTRY CurrentEntry; + PMEMORY_AREA Current; + + DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process, + Process->ImageFileName); + + MmLockAddressSpace(&Process->AddressSpace); + + CurrentEntry = Process->AddressSpace.MAreaListHead.Flink; + while (CurrentEntry != &Process->AddressSpace.MAreaListHead) + { + Current = CONTAINING_RECORD(CurrentEntry, MEMORY_AREA, Entry); + CurrentEntry = CurrentEntry->Flink; + + MmReleaseMemoryArea(Process, Current); + } + + Mmi386ReleaseMmInfo(Process); + + MmUnlockAddressSpace(&Process->AddressSpace); + MmDestroyAddressSpace(&Process->AddressSpace); + + DPRINT("Finished MmReleaseMmInfo()\n"); + return(STATUS_SUCCESS); +} + +BOOLEAN STDCALL MmIsNonPagedSystemAddressValid(PVOID VirtualAddress) +{ + UNIMPLEMENTED; +} + +BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress) +/* + * FUNCTION: Checks whether the given address is valid for a read or write + * ARGUMENTS: + * VirtualAddress = address to check + * RETURNS: True if the access would be valid + * False if the access would cause a page fault + * NOTES: This function checks whether a byte access to the page would + * succeed. Is this realistic for RISC processors which don't + * allow byte granular access? + */ +{ + MEMORY_AREA* MemoryArea; + PMADDRESS_SPACE AddressSpace; + + AddressSpace = &PsGetCurrentProcess()->AddressSpace; + + MmLockAddressSpace(AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, + VirtualAddress); + + if (MemoryArea == NULL) + { + MmUnlockAddressSpace(AddressSpace); + return(FALSE); + } + MmUnlockAddressSpace(AddressSpace); + return(TRUE); +} + +NTSTATUS MmAccessFault(KPROCESSOR_MODE Mode, + ULONG Address, + BOOLEAN FromMdl) +{ + PMADDRESS_SPACE AddressSpace; + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + BOOLEAN Locked = FromMdl; + + DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); + + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql()); + return(STATUS_UNSUCCESSFUL); + } + if (PsGetCurrentProcess() == NULL) + { + DbgPrint("No current process\n"); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Find the memory area for the faulting address + */ + if (Address >= KERNEL_BASE) + { + /* + * Check permissions + */ + if (Mode != KernelMode) + { + DbgPrint("%s:%d\n",__FILE__,__LINE__); + return(STATUS_UNSUCCESSFUL); + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->AddressSpace; + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address); + if (MemoryArea == NULL) + { + DbgPrint("%s:%d\n",__FILE__,__LINE__); + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + return(STATUS_UNSUCCESSFUL); + } + + switch (MemoryArea->Type) + { + case MEMORY_AREA_SYSTEM: + Status = STATUS_UNSUCCESSFUL; + break; + + case MEMORY_AREA_PAGED_POOL: + Status = STATUS_SUCCESS; + break; + + case MEMORY_AREA_SECTION_VIEW: + Status = MmAccessFaultSectionView(AddressSpace, + MemoryArea, + (PVOID)Address, + Locked); + break; + + case MEMORY_AREA_VIRTUAL_MEMORY: + Status = STATUS_UNSUCCESSFUL; + break; + + case MEMORY_AREA_SHARED_DATA: + Status = STATUS_UNSUCCESSFUL; + break; + + default: + Status = STATUS_UNSUCCESSFUL; + break; + } + DPRINT("Completed page fault handling\n"); + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + return(Status); +} + +NTSTATUS MmCommitPagedPoolAddress(PVOID Address) +{ + NTSTATUS Status; + PHYSICAL_ADDRESS AllocatedPage; + Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage); + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage); + MmLockAddressSpace(MmGetKernelAddressSpace()); + } + Status = + MmCreateVirtualMapping(NULL, + (PVOID)PAGE_ROUND_DOWN(Address), + PAGE_READWRITE, + AllocatedPage, + FALSE); + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + Status = + MmCreateVirtualMapping(NULL, + (PVOID)PAGE_ROUND_DOWN(Address), + PAGE_READWRITE, + AllocatedPage, + FALSE); + MmLockAddressSpace(MmGetKernelAddressSpace()); + } + return(Status); +} + +NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode, + ULONG Address, + BOOLEAN FromMdl) +{ + PMADDRESS_SPACE AddressSpace; + MEMORY_AREA* MemoryArea; + NTSTATUS Status; + BOOLEAN Locked = FromMdl; + + DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address); + + if (KeGetCurrentIrql() >= DISPATCH_LEVEL) + { + DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql()); + return(STATUS_UNSUCCESSFUL); + } + if (PsGetCurrentProcess() == NULL) + { + DbgPrint("No current process\n"); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Find the memory area for the faulting address + */ + if (Address >= KERNEL_BASE) + { + /* + * Check permissions + */ + if (Mode != KernelMode) + { + DbgPrint("%s:%d\n",__FILE__,__LINE__); + return(STATUS_UNSUCCESSFUL); + } + AddressSpace = MmGetKernelAddressSpace(); + } + else + { + AddressSpace = &PsGetCurrentProcess()->AddressSpace; + } + + if (!FromMdl) + { + MmLockAddressSpace(AddressSpace); + } + + /* + * Call the memory area specific fault handler + */ + do + { + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, (PVOID)Address); + if (MemoryArea == NULL) + { + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + return (STATUS_UNSUCCESSFUL); + } + + switch (MemoryArea->Type) + { + case MEMORY_AREA_PAGED_POOL: + { + Status = MmCommitPagedPoolAddress((PVOID)Address); + break; + } + + case MEMORY_AREA_SYSTEM: + Status = STATUS_UNSUCCESSFUL; + break; + + case MEMORY_AREA_SECTION_VIEW: + Status = MmNotPresentFaultSectionView(AddressSpace, + MemoryArea, + (PVOID)Address, + Locked); + break; + + case MEMORY_AREA_VIRTUAL_MEMORY: + Status = MmNotPresentFaultVirtualMemory(AddressSpace, + MemoryArea, + (PVOID)Address, + Locked); + break; + + case MEMORY_AREA_SHARED_DATA: + Status = + MmCreateVirtualMapping(PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address), + PAGE_READONLY, + MmSharedDataPagePhysicalAddress, + FALSE); + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(&PsGetCurrentProcess()->AddressSpace); + Status = + MmCreateVirtualMapping(PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address), + PAGE_READONLY, + MmSharedDataPagePhysicalAddress, + TRUE); + MmLockAddressSpace(&PsGetCurrentProcess()->AddressSpace); + } + break; + + default: + Status = STATUS_UNSUCCESSFUL; + break; + } + } + while (Status == STATUS_MM_RESTART_OPERATION); + + DPRINT("Completed page fault handling\n"); + if (!FromMdl) + { + MmUnlockAddressSpace(AddressSpace); + } + return(Status); +} + +/* Miscellanea functions: they may fit somewhere else */ + +DWORD STDCALL +MmAdjustWorkingSetSize (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + return (0); +} + + +DWORD +STDCALL +MmDbgTranslatePhysicalAddress ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + UNIMPLEMENTED; + return (0); +} + + +NTSTATUS +STDCALL +MmGrowKernelStack ( + DWORD Unknown0 + ) +{ + UNIMPLEMENTED; + return (STATUS_NOT_IMPLEMENTED); +} + + +BOOLEAN +STDCALL +MmSetAddressRangeModified ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + UNIMPLEMENTED; + return (FALSE); +} + +/* EOF */ diff --git a/ntoskrnl/mm/mminit.c b/ntoskrnl/mm/mminit.c new file mode 100644 index 0000000..6a5948f --- /dev/null +++ b/ntoskrnl/mm/mminit.c @@ -0,0 +1,365 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/mminit.c + * PURPOSE: kernel memory managment initialization functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 9/4/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +/* + * Size of extended memory (kb) (fixed for now) + */ +#define EXTENDED_MEMORY_SIZE (3*1024*1024) + +/* + * Compiler defined symbols + */ +extern unsigned int _text_start__; +extern unsigned int _text_end__; + +static BOOLEAN IsThisAnNtAsSystem = FALSE; +static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem; + +extern unsigned int _bss_end__; + +static MEMORY_AREA* kernel_text_desc = NULL; +static MEMORY_AREA* kernel_data_desc = NULL; +static MEMORY_AREA* kernel_param_desc = NULL; +static MEMORY_AREA* kernel_pool_desc = NULL; +static MEMORY_AREA* kernel_shared_data_desc = NULL; +static MEMORY_AREA* MiPagedPoolDescriptor = NULL; + +PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress; + +/* FUNCTIONS ****************************************************************/ + +BOOLEAN STDCALL MmIsThisAnNtAsSystem(VOID) +{ + return(IsThisAnNtAsSystem); +} + +MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID) +{ + return(MmSystemSize); +} + +VOID MiShutdownMemoryManager(VOID) +{ +} + +VOID MmInitVirtualMemory(ULONG LastKernelAddress, + ULONG KernelLength) +/* + * FUNCTION: Intialize the memory areas list + * ARGUMENTS: + * bp = Pointer to the boot parameters + * kernel_len = Length of the kernel + */ +{ + PVOID BaseAddress; + ULONG Length; + ULONG ParamLength = KernelLength; + NTSTATUS Status; + //ULONG i; + + DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength); + + LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress); + + MmInitMemoryAreas(); + ExInitNonPagedPool(LastKernelAddress + PAGE_SIZE); + + /* + * Setup the system area descriptor list + */ + BaseAddress = (PVOID)KERNEL_BASE; + Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE; + ParamLength = ParamLength - Length; + + /* + * No need to lock the address space at this point since no + * other threads are running. + */ + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + Length, + 0, + &kernel_text_desc, + FALSE); + + Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) - + PAGE_ROUND_UP(((ULONG)&_text_end__)); + ParamLength = ParamLength - Length; + DPRINT("Length %x\n",Length); + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__)); + DPRINT("BaseAddress %x\n",BaseAddress); + + /* + * No need to lock the address space at this point since we are + * the only thread running. + */ + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + Length, + 0, + &kernel_data_desc, + FALSE); + + BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__)); +// Length = ParamLength; + Length = LastKernelAddress - (ULONG)BaseAddress; + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + Length, + 0, + &kernel_param_desc, + FALSE); + + BaseAddress = (PVOID)(LastKernelAddress + PAGE_SIZE); + Length = NONPAGED_POOL_SIZE; + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + Length, + 0, + &kernel_pool_desc, + FALSE); + + MmPagedPoolSize = MM_PAGED_POOL_SIZE; + BaseAddress = (PVOID)(LastKernelAddress + PAGE_SIZE + NONPAGED_POOL_SIZE + + PAGE_SIZE); + MmPagedPoolBase = BaseAddress; + Length = MM_PAGED_POOL_SIZE; + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_PAGED_POOL, + &BaseAddress, + Length, + 0, + &MiPagedPoolDescriptor, + FALSE); + MmInitializePagedPool(); + + /* + * Create the kernel mapping of the user/kernel shared memory. + */ + BaseAddress = (PVOID)KI_USER_SHARED_DATA; + Length = PAGE_SIZE; + MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_SYSTEM, + &BaseAddress, + Length, + 0, + &kernel_shared_data_desc, + FALSE); + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, + &MmSharedDataPagePhysicalAddress); + Status = MmCreateVirtualMapping(NULL, + (PVOID)KI_USER_SHARED_DATA, + PAGE_READWRITE, + MmSharedDataPagePhysicalAddress, + TRUE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + RtlZeroMemory(BaseAddress, Length); + + /* + * + */ + MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); +} + +VOID MmInit1(ULONG FirstKrnlPhysAddr, + ULONG LastKrnlPhysAddr, + ULONG LastKernelAddress, + PADDRESS_RANGE BIOSMemoryMap, + ULONG AddressRangeCount) +/* + * FUNCTION: Initalize memory managment + */ +{ + ULONG i; + ULONG kernel_len; +#ifndef MP + extern unsigned int unmap_me, unmap_me2, unmap_me3; +#endif + + DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n", + FirstKrnlPhysAddr, + LastKrnlPhysAddr, + LastKernelAddress); + + if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0)) + { + // If we have a bios memory map, recalulate the the memory size + ULONG last = 0; + for (i = 0; i < AddressRangeCount; i++) + { + if (BIOSMemoryMap[i].Type == 1 + && (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last) + { + last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE; + } + } + if ((last - 256) * 4 > KeLoaderBlock.MemHigher) + { + KeLoaderBlock.MemHigher = (last - 256) * 4; + } + } + + /* + * FIXME: Set this based on the system command line + */ + MmUserProbeAddress = (PVOID)0x7fff0000; + MmHighestUserAddress = (PVOID)0x7ffeffff; + + /* + * Initialize memory managment statistics + */ + MmStats.NrTotalPages = 0; + MmStats.NrSystemPages = 0; + MmStats.NrUserPages = 0; + MmStats.NrReservedPages = 0; + MmStats.NrUserPages = 0; + MmStats.NrFreePages = 0; + MmStats.NrLockedPages = 0; + MmStats.PagingRequestsInLastMinute = 0; + MmStats.PagingRequestsInLastFiveMinutes = 0; + MmStats.PagingRequestsInLastFifteenMinutes = 0; + + /* + * Initialize the kernel address space + */ + MmInitializeKernelAddressSpace(); + + /* + * Unmap low memory + */ +#ifndef MP + /* FIXME: This is broken in SMP mode */ + MmDeletePageTable(NULL, 0); +#endif + /* + * Free all pages not used for kernel memory + * (we assume the kernel occupies a continuous range of physical + * memory) + */ + DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr, + LastKrnlPhysAddr); + + /* + * Free physical memory not used by the kernel + */ + MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4; + if (!MmStats.NrTotalPages) + { + DbgPrint("Memory not detected, default to 8 MB\n"); + MmStats.NrTotalPages = 2048; + } + else + { + /* add 1MB for standard memory (not extended) */ + MmStats.NrTotalPages += 256; + } +#ifdef BIOS_MEM_FIX + MmStats.NrTotalPages += 16; +#endif + DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024); + + LastKernelAddress = (ULONG)MmInitializePageList( + (PVOID)FirstKrnlPhysAddr, + (PVOID)LastKrnlPhysAddr, + MmStats.NrTotalPages, + PAGE_ROUND_UP(LastKernelAddress), + BIOSMemoryMap, + AddressRangeCount); + kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr; + + /* + * Create a trap for null pointer references and protect text + * segment + */ + CHECKPOINT; + DPRINT("_text_start__ %x _text_end__ %x\n",(int)&_text_start__,(int)&_text_end__); + for (i=PAGE_ROUND_UP(((int)&_text_start__)); + i +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static HANDLE MpwThreadHandle; +static CLIENT_ID MpwThreadId; +static KEVENT MpwThreadEvent; +static volatile BOOLEAN MpwThreadShouldTerminate; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +MmWriteDirtyPages(ULONG Target, PULONG Actual) +{ + PHYSICAL_ADDRESS Page; + PHYSICAL_ADDRESS NextPage; + NTSTATUS Status; + + Page = MmGetLRUFirstUserPage(); + while (Page.QuadPart != 0LL && Target > 0) + { + NextPage = MmGetLRUNextUserPage(Page); + if (MmIsDirtyPageRmap(Page)) + { + Status = MmWritePagePhysicalAddress(Page); + if (NT_SUCCESS(Status)) + { + Target--; + } + } + Page = NextPage; + } + *Actual = Target; + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +MmMpwThreadMain(PVOID Ignored) +{ + NTSTATUS Status; + ULONG PagesWritten; + LARGE_INTEGER Timeout; + + Timeout.QuadPart = -50000000; + + for(;;) + { + Status = KeWaitForSingleObject(&MpwThreadEvent, + 0, + KernelMode, + FALSE, + &Timeout); + if (!NT_SUCCESS(Status)) + { + DbgPrint("MpwThread: Wait failed\n"); + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); + } + if (MpwThreadShouldTerminate) + { + DbgPrint("MpwThread: Terminating\n"); + return(STATUS_SUCCESS); + } + + PagesWritten = 0; + MmWriteDirtyPages(128, &PagesWritten); + CcRosFlushDirtyPages(128, &PagesWritten); + } +} + +NTSTATUS MmInitMpwThread(VOID) +{ + KPRIORITY Priority; + NTSTATUS Status; + + MpwThreadShouldTerminate = FALSE; + KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE); + + Status = PsCreateSystemThread(&MpwThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + &MpwThreadId, + MmMpwThreadMain, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Priority = 1; + NtSetInformationThread(MpwThreadHandle, + ThreadPriority, + &Priority, + sizeof(Priority)); + + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/mm/ncache.c b/ntoskrnl/mm/ncache.c new file mode 100644 index 0000000..2ff2129 --- /dev/null +++ b/ntoskrnl/mm/ncache.c @@ -0,0 +1,136 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/cont.c + * PURPOSE: Manages non-cached memory + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + + +/********************************************************************** + * NAME EXPORTED + * MmAllocateNonCachedMemory@4 + * + * DESCRIPTION + * Allocates a virtual address range of noncached and cache + * aligned memory. + * + * ARGUMENTS + * NumberOfBytes + * Size of region to allocate. + * + * RETURN VALUE + * The base address of the range on success; + * NULL on failure. + * + * NOTE + * Description taken from include/ddk/mmfuncs.h. + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +PVOID STDCALL +MmAllocateNonCachedMemory(IN ULONG NumberOfBytes) +{ + PVOID Result; + MEMORY_AREA* marea; + NTSTATUS Status; + ULONG i; + ULONG Attributes; + + MmLockAddressSpace(MmGetKernelAddressSpace()); + Result = NULL; + Status = MmCreateMemoryArea (NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_NO_CACHE, + &Result, + NumberOfBytes, + 0, + &marea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + + if (!NT_SUCCESS(Status)) + { + return (NULL); + } + Attributes = PAGE_READWRITE | PAGE_SYSTEM | PAGE_NOCACHE | + PAGE_WRITETHROUGH; + for (i = 0; i <= (NumberOfBytes / PAGE_SIZE); i++) + { + PHYSICAL_ADDRESS NPage; + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &NPage); + MmCreateVirtualMapping (NULL, + Result + (i * PAGE_SIZE), + Attributes, + NPage, + TRUE); + } + return ((PVOID)Result); +} + +VOID STATIC +MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, + BOOLEAN Dirty) +{ + assert(SwapEntry == 0); + if (PhysAddr.QuadPart != 0) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr); + } +} + +/********************************************************************** + * NAME EXPORTED + * MmFreeNonCachedMemory@8 + * + * DESCRIPTION + * Releases a range of noncached memory allocated with + * MmAllocateNonCachedMemory. + * + * ARGUMENTS + * BaseAddress + * Virtual address to be freed; + * + * NumberOfBytes + * Size of the region to be freed. + * + * RETURN VALUE + * None. + * + * NOTE + * Description taken from include/ddk/mmfuncs.h. + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +VOID STDCALL MmFreeNonCachedMemory (IN PVOID BaseAddress, + IN ULONG NumberOfBytes) +{ + MmFreeMemoryArea (MmGetKernelAddressSpace(), + BaseAddress, + NumberOfBytes, + MmFreeNonCachedPage, + NULL); +} + + +/* EOF */ diff --git a/ntoskrnl/mm/npool.c b/ntoskrnl/mm/npool.c new file mode 100644 index 0000000..391c1ae --- /dev/null +++ b/ntoskrnl/mm/npool.c @@ -0,0 +1,1055 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/npool.c + * PURPOSE: Implements the kernel memory pool + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 27/05/98: Created + * 10/06/98: Bug fixes by Iwan Fatahi (i_fatahi@hotmail.com) + * in take_block (if current bigger than required) + * in remove_from_used_list + * in ExFreePool + * 23/08/98: Fixes from Robert Bergkvist (fragdance@hotmail.com) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* Enable strict checking of the nonpaged pool on every allocation */ +//#define ENABLE_VALIDATE_POOL + +/* Enable tracking of statistics about the tagged blocks in the pool */ +#define TAG_STATISTICS_TRACKING + +/* + * Put each block in its own range of pages and position the block at the + * end of the range so any accesses beyond the end of block are to invalid + * memory locations. + */ +//#define WHOLE_PAGE_ALLOCATIONS + +#ifdef ENABLE_VALIDATE_POOL +#define VALIDATE_POOL validate_kernel_pool() +#else +#define VALIDATE_POOL +#endif + +#if 0 +#define POOL_TRACE(args...) do { DbgPrint(args); } while(0); +#else +#define POOL_TRACE(args...) +#endif + +/* TYPES *******************************************************************/ + +#define BLOCK_HDR_USED_MAGIC (0xdeadbeef) +#define BLOCK_HDR_FREE_MAGIC (0xceadbeef) + +/* + * fields present at the start of a block (this is for internal use only) + */ +typedef struct _BLOCK_HDR +{ + ULONG Magic; + ULONG Size; + LIST_ENTRY ListEntry; + ULONG Tag; + PVOID Caller; + struct _BLOCK_HDR* tag_next; + BOOLEAN Dumped; +} BLOCK_HDR; + +PVOID STDCALL +ExAllocateWholePageBlock(ULONG Size); +VOID STDCALL +ExFreeWholePageBlock(PVOID Addr); + +/* GLOBALS *****************************************************************/ + +/* + * Memory managment initalized symbol for the base of the pool + */ +static unsigned int kernel_pool_base = 0; + +/* + * Head of the list of free blocks + */ +static LIST_ENTRY FreeBlockListHead; + +/* + * Head of the list of in use block + */ +static LIST_ENTRY UsedBlockListHead; + +#ifndef WHOLE_PAGE_ALLOCATIONS +/* + * Count of free blocks + */ +static ULONG EiNrFreeBlocks = 0; + +/* + * Count of used blocks + */ +static ULONG EiNrUsedBlocks = 0; +#endif + +/* + * Lock that protects the non-paged pool data structures + */ +static KSPIN_LOCK MmNpoolLock; + +/* + * Total memory used for free nonpaged pool blocks + */ +ULONG EiFreeNonPagedPool = 0; + +/* + * Total memory used for nonpaged pool blocks + */ +ULONG EiUsedNonPagedPool = 0; + +/* + * Allocate a range of memory in the nonpaged pool + */ +PVOID +MiAllocNonPagedPoolRegion(unsigned int nr_pages); + +VOID +MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free); + +#ifdef TAG_STATISTICS_TRACKING +#define TAG_HASH_TABLE_SIZE (1024) +static BLOCK_HDR* tag_hash_table[TAG_HASH_TABLE_SIZE]; +#endif /* TAG_STATISTICS_TRACKING */ + +/* FUNCTIONS ***************************************************************/ + +#ifdef TAG_STATISTICS_TRACKING +VOID +MiRemoveFromTagHashTable(BLOCK_HDR* block) + /* + * Remove a block from the tag hash table + */ +{ + BLOCK_HDR* previous; + BLOCK_HDR* current; + ULONG hash; + + if (block->Tag == 0) + { + return; + } + + hash = block->Tag % TAG_HASH_TABLE_SIZE; + + previous = NULL; + current = tag_hash_table[hash]; + while (current != NULL) + { + if (current == block) + { + if (previous == NULL) + { + tag_hash_table[hash] = block->tag_next; + } + else + { + previous->tag_next = block->tag_next; + } + return; + } + previous = current; + current = current->tag_next; + } + DPRINT1("Tagged block wasn't on hash table list (Tag %x Caller %x)\n", + block->Tag, block->Caller); + KeBugCheck(0); +} + +VOID +MiAddToTagHashTable(BLOCK_HDR* block) + /* + * Add a block to the tag hash table + */ +{ + ULONG hash; + BLOCK_HDR* current; + BLOCK_HDR* previous; + + if (block->Tag == 0) + { + return; + } + + hash = block->Tag % TAG_HASH_TABLE_SIZE; + + previous = NULL; + current = tag_hash_table[hash]; + while (current != NULL) + { + if (current->Tag == block->Tag) + { + block->tag_next = current->tag_next; + current->tag_next = block; + return; + } + previous = current; + if ((PVOID)current->tag_next >= (PVOID)0xc1123160) + { + DbgPrint("previous %x\n", previous); + } + current = current->tag_next; + } + block->tag_next = NULL; + if (previous == NULL) + { + tag_hash_table[hash] = block; + } + else + { + previous->tag_next = block; + } +} +#endif /* TAG_STATISTICS_TRACKING */ + +VOID +ExInitNonPagedPool(ULONG BaseAddress) +{ + kernel_pool_base = BaseAddress; + KeInitializeSpinLock(&MmNpoolLock); + MmInitKernelMap((PVOID)BaseAddress); + memset(tag_hash_table, 0, sizeof(tag_hash_table)); + InitializeListHead(&FreeBlockListHead); + InitializeListHead(&UsedBlockListHead); +} + +#ifdef TAG_STATISTICS_TRACKING +VOID STATIC +MiDumpTagStats(ULONG CurrentTag, ULONG CurrentNrBlocks, ULONG CurrentSize) +{ + CHAR c1, c2, c3, c4; + + c1 = (CurrentTag >> 24) & 0xFF; + c2 = (CurrentTag >> 16) & 0xFF; + c3 = (CurrentTag >> 8) & 0xFF; + c4 = CurrentTag & 0xFF; + + if (isprint(c1) && isprint(c2) && isprint(c3) && isprint(c4)) + { + DbgPrint("Tag %x (%c%c%c%c) Blocks %d Total Size %d Average Size %d\n", + CurrentTag, c4, c3, c2, c1, CurrentNrBlocks, + CurrentSize, CurrentSize / CurrentNrBlocks); + } + else + { + DbgPrint("Tag %x Blocks %d Total Size %d Average Size %d\n", + CurrentTag, CurrentNrBlocks, CurrentSize, + CurrentSize / CurrentNrBlocks); + } +} +#endif /* TAG_STATISTICS_TRACKING */ + +VOID +MiDebugDumpNonPagedPoolStats(BOOLEAN NewOnly) +{ +#ifdef TAG_STATISTICS_TRACKING + ULONG i; + BLOCK_HDR* current; + ULONG CurrentTag; + ULONG CurrentNrBlocks; + ULONG CurrentSize; + ULONG TotalBlocks; + ULONG TotalSize; + + DbgPrint("******* Dumping non paging pool stats ******\n"); + TotalBlocks = 0; + TotalSize = 0; + for (i = 0; i < TAG_HASH_TABLE_SIZE; i++) + { + CurrentTag = 0; + CurrentNrBlocks = 0; + CurrentSize = 0; + current = tag_hash_table[i]; + while (current != NULL) + { + if (current->Tag != CurrentTag) + { + if (CurrentTag != 0 && CurrentNrBlocks != 0) + { + MiDumpTagStats(CurrentTag, CurrentNrBlocks, CurrentSize); + } + CurrentTag = current->Tag; + CurrentNrBlocks = 0; + CurrentSize = 0; + } + + if (!NewOnly || !current->Dumped) + { + CurrentNrBlocks++; + TotalBlocks++; + CurrentSize = CurrentSize + current->Size; + TotalSize = TotalSize + current->Size; + current->Dumped = TRUE; + } + current = current->tag_next; + } + if (CurrentTag != 0 && CurrentNrBlocks != 0) + { + MiDumpTagStats(CurrentTag, CurrentNrBlocks, CurrentSize); + } + } + if (TotalBlocks != 0) + { + DbgPrint("TotalBlocks %d TotalSize %d AverageSize %d\n", + TotalBlocks, TotalSize, TotalSize / TotalBlocks); + } + else + { + DbgPrint("TotalBlocks %d TotalSize %d\n", + TotalBlocks, TotalSize); + } + DbgPrint("***************** Dump Complete ***************\n"); +#endif /* TAG_STATISTICS_TRACKING */ +} + +VOID +MiDebugDumpNonPagedPool(BOOLEAN NewOnly) +{ + BLOCK_HDR* current; + PLIST_ENTRY current_entry; + KIRQL oldIrql; + + KeAcquireSpinLock(&MmNpoolLock, &oldIrql); + + DbgPrint("******* Dumping non paging pool contents ******\n"); + current_entry = UsedBlockListHead.Flink; + while (current_entry != &UsedBlockListHead) + { + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + if (!NewOnly || !current->Dumped) + { + CHAR c1, c2, c3, c4; + + c1 = (current->Tag >> 24) & 0xFF; + c2 = (current->Tag >> 16) & 0xFF; + c3 = (current->Tag >> 8) & 0xFF; + c4 = current->Tag & 0xFF; + + if (isprint(c1) && isprint(c2) && isprint(c3) && isprint(c4)) + { + DbgPrint("Size 0x%x Tag 0x%x (%c%c%c%c) Allocator 0x%x\n", + current->Size, current->Tag, c4, c3, c2, c1, + current->Caller); + } + else + { + DbgPrint("Size 0x%x Tag 0x%x Allocator 0x%x\n", + current->Size, current->Tag, current->Caller); + } + current->Dumped = TRUE; + } + current_entry = current_entry->Flink; + } + DbgPrint("***************** Dump Complete ***************\n"); + KeReleaseSpinLock(&MmNpoolLock, oldIrql); +} + +#ifndef WHOLE_PAGE_ALLOCATIONS + +#ifdef ENABLE_VALIDATE_POOL +static void validate_free_list(void) +/* + * FUNCTION: Validate the integrity of the list of free blocks + */ +{ + BLOCK_HDR* current; + PLIST_ENTRY current_entry; + unsigned int blocks_seen=0; + + current_entry = FreeBlockListHead.Flink; + while (current_entry != &FreeBlockListHead) + { + unsigned int base_addr; + + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + base_addr = (int)current; + + if (current->Magic != BLOCK_HDR_FREE_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption) at %x\n", + current); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + + if (base_addr < (kernel_pool_base) || + (base_addr+current->Size) > (kernel_pool_base)+NONPAGED_POOL_SIZE) + { + DbgPrint("Block %x found outside pool area\n",current); + DbgPrint("Size %d\n",current->Size); + DbgPrint("Limits are %x %x\n",kernel_pool_base, + kernel_pool_base+NONPAGED_POOL_SIZE); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + blocks_seen++; + if (blocks_seen > EiNrFreeBlocks) + { + DbgPrint("Too many blocks on free list\n"); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + if (current->ListEntry.Flink != &FreeBlockListHead && + current->ListEntry.Flink->Blink != ¤t->ListEntry) + { + DbgPrint("%s:%d:Break in list (current %x next %x " + "current->next->previous %x)\n", + __FILE__,__LINE__,current, current->ListEntry.Flink, + current->ListEntry.Flink->Blink); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + + current_entry = current_entry->Flink; + } +} + +static void validate_used_list(void) +/* + * FUNCTION: Validate the integrity of the list of used blocks + */ +{ + BLOCK_HDR* current; + PLIST_ENTRY current_entry; + unsigned int blocks_seen=0; + + current_entry = UsedBlockListHead.Flink; + while (current_entry != &UsedBlockListHead) + { + unsigned int base_addr; + + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + base_addr = (int)current; + + if (current->Magic != BLOCK_HDR_USED_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption) at %x\n", + current); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + if (base_addr < (kernel_pool_base) || + (base_addr+current->Size) > + (kernel_pool_base)+NONPAGED_POOL_SIZE) + { + DbgPrint("Block %x found outside pool area\n",current); + for(;;); + } + blocks_seen++; + if (blocks_seen > EiNrUsedBlocks) + { + DbgPrint("Too many blocks on used list\n"); + for(;;); + } + if (current->ListEntry.Flink != &UsedBlockListHead && + current->ListEntry.Flink->Blink != ¤t->ListEntry) + { + DbgPrint("Break in list (current %x next %x)\n", + current, current->ListEntry.Flink); + for(;;); + } + + current_entry = current_entry->Flink; + } +} + +static void check_duplicates(BLOCK_HDR* blk) +/* + * FUNCTION: Check a block has no duplicates + * ARGUMENTS: + * blk = block to check + * NOTE: Bug checks if duplicates are found + */ +{ + unsigned int base = (int)blk; + unsigned int last = ((int)blk) + +sizeof(BLOCK_HDR) + blk->Size; + BLOCK_HDR* current; + PLIST_ENTRY current_entry; + + current_entry = FreeBlockListHead.Flink; + while (current_entry != &FreeBlockListHead) + { + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + + if (current->Magic != BLOCK_HDR_FREE_MAGIC) + { + DbgPrint("Bad block magic (probable pool corruption) at %x\n", + current); + KeBugCheck(KBUG_POOL_FREE_LIST_CORRUPT); + } + + if ( (int)current > base && (int)current < last ) + { + DbgPrint("intersecting blocks on list\n"); + for(;;); + } + if ( (int)current < base && + ((int)current + current->Size + sizeof(BLOCK_HDR)) + > base ) + { + DbgPrint("intersecting blocks on list\n"); + for(;;); + } + + current_entry = current_entry->Flink; + } + + current_entry = UsedBlockListHead.Flink; + while (current_entry != &UsedBlockListHead) + { + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + + if ( (int)current > base && (int)current < last ) + { + DbgPrint("intersecting blocks on list\n"); + for(;;); + } + if ( (int)current < base && + ((int)current + current->Size + sizeof(BLOCK_HDR)) + > base ) + { + DbgPrint("intersecting blocks on list\n"); + for(;;); + } + + current_entry = current_entry->Flink; + } + +} + +static void validate_kernel_pool(void) +/* + * FUNCTION: Checks the integrity of the kernel memory heap + */ +{ + BLOCK_HDR* current; + PLIST_ENTRY current_entry; + + validate_free_list(); + validate_used_list(); + + current_entry = FreeBlockListHead.Flink; + while (current_entry != &FreeBlockListHead) + { + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + check_duplicates(current); + current_entry = current_entry->Flink; + } + current_entry = UsedBlockListHead.Flink; + while (current_entry != &UsedBlockListHead) + { + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + check_duplicates(current); + current_entry = current_entry->Flink; + } +} +#endif + +#if 0 +STATIC VOID +free_pages(BLOCK_HDR* blk) +{ + ULONG start; + ULONG end; + ULONG i; + + start = (ULONG)blk; + end = (ULONG)blk + sizeof(BLOCK_HDR) + blk->Size; + + /* + * If the block doesn't contain a whole page then there is nothing to do + */ + if (PAGE_ROUND_UP(start) >= PAGE_ROUND_DOWN(end)) + { + return; + } +} +#endif + +STATIC VOID +merge_free_block(BLOCK_HDR* blk) +{ + PLIST_ENTRY next_entry; + BLOCK_HDR* next; + PLIST_ENTRY previous_entry; + BLOCK_HDR* previous; + + next_entry = blk->ListEntry.Flink; + if (next_entry != &FreeBlockListHead) + { + next = CONTAINING_RECORD(next_entry, BLOCK_HDR, ListEntry); + if (((unsigned int)blk + sizeof(BLOCK_HDR) + blk->Size) == + (unsigned int)next) + { + RemoveEntryList(&next->ListEntry); + blk->Size = blk->Size + sizeof(BLOCK_HDR) + next->Size; + EiNrFreeBlocks--; + } + } + + previous_entry = blk->ListEntry.Blink; + if (previous_entry != &FreeBlockListHead) + { + previous = CONTAINING_RECORD(previous_entry, BLOCK_HDR, ListEntry); + if (((unsigned int)previous + sizeof(BLOCK_HDR) + previous->Size) == + (unsigned int)blk) + { + RemoveEntryList(&blk->ListEntry); + previous->Size = previous->Size + sizeof(BLOCK_HDR) + blk->Size; + EiNrFreeBlocks--; + } + } +} + +STATIC VOID +add_to_free_list(BLOCK_HDR* blk) +/* + * FUNCTION: add the block to the free list (internal) + */ +{ + PLIST_ENTRY current_entry; + BLOCK_HDR* current; + + current_entry = FreeBlockListHead.Flink; + while (current_entry != &FreeBlockListHead) + { + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + + if ((unsigned int)current > (unsigned int)blk) + { + blk->ListEntry.Flink = current_entry; + blk->ListEntry.Blink = current_entry->Blink; + current_entry->Blink->Flink = &blk->ListEntry; + current_entry->Blink = &blk->ListEntry; + EiNrFreeBlocks++; + return; + } + + current_entry = current_entry->Flink; + } + InsertTailList(&FreeBlockListHead, &blk->ListEntry); + EiNrFreeBlocks++; +} + +static void add_to_used_list(BLOCK_HDR* blk) +/* + * FUNCTION: add the block to the used list (internal) + */ +{ + InsertHeadList(&UsedBlockListHead, &blk->ListEntry); + EiNrUsedBlocks++; +} + + +static void remove_from_free_list(BLOCK_HDR* current) +{ + RemoveEntryList(¤t->ListEntry); + EiNrFreeBlocks--; +} + + +static void remove_from_used_list(BLOCK_HDR* current) +{ + RemoveEntryList(¤t->ListEntry); + EiNrUsedBlocks--; +} + + +inline static void* block_to_address(BLOCK_HDR* blk) +/* + * FUNCTION: Translate a block header address to the corresponding block + * address (internal) + */ +{ + return ( (void *) ((int)blk + sizeof(BLOCK_HDR)) ); +} + +inline static BLOCK_HDR* address_to_block(void* addr) +{ + return (BLOCK_HDR *) + ( ((int)addr) - sizeof(BLOCK_HDR) ); +} + +static BLOCK_HDR* grow_kernel_pool(unsigned int size, ULONG Tag, PVOID Caller) +/* + * FUNCTION: Grow the executive heap to accomodate a block of at least 'size' + * bytes + */ +{ + unsigned int total_size = size + sizeof(BLOCK_HDR); + unsigned int nr_pages = PAGE_ROUND_UP(total_size) / PAGE_SIZE; + unsigned int start; + BLOCK_HDR* used_blk=NULL; + BLOCK_HDR* free_blk=NULL; + int i; + NTSTATUS Status; + KIRQL oldIrql; + + start = (ULONG)MiAllocNonPagedPoolRegion(nr_pages); + + DPRINT("growing heap for block size %d, ",size); + DPRINT("start %x\n",start); + + for (i=0;i(2*sizeof(BLOCK_HDR))) + { + used_blk = (struct _BLOCK_HDR *)start; + DPRINT("Creating block at %x\n",start); + used_blk->Magic = BLOCK_HDR_USED_MAGIC; + used_blk->Size = size; + add_to_used_list(used_blk); + + free_blk = (BLOCK_HDR *)(start + sizeof(BLOCK_HDR) + size); + DPRINT("Creating block at %x\n",free_blk); + free_blk->Magic = BLOCK_HDR_FREE_MAGIC; + free_blk->Size = (nr_pages * PAGE_SIZE) -((sizeof(BLOCK_HDR)*2) + size); + add_to_free_list(free_blk); + + EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->Size; + EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->Size; + } + else + { + used_blk = (struct _BLOCK_HDR *)start; + used_blk->Magic = BLOCK_HDR_USED_MAGIC; + used_blk->Size = (nr_pages * PAGE_SIZE) - sizeof(BLOCK_HDR); + add_to_used_list(used_blk); + + EiUsedNonPagedPool = EiUsedNonPagedPool + used_blk->Size; + } + + used_blk->Tag = Tag; + used_blk->Caller = Caller; + used_blk->Dumped = FALSE; +#ifdef TAG_STATISTICS_TRACKING + MiAddToTagHashTable(used_blk); +#endif /* TAG_STATISTICS_TRACKING */ + + VALIDATE_POOL; + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + return(used_blk); +} + +static void* take_block(BLOCK_HDR* current, unsigned int size, + ULONG Tag, PVOID Caller) +/* + * FUNCTION: Allocate a used block of least 'size' from the specified + * free block + * RETURNS: The address of the created memory block + */ +{ + /* + * If the block is much bigger than required then split it and + * return a pointer to the allocated section. If the difference + * between the sizes is marginal it makes no sense to have the + * extra overhead + */ + if (current->Size > (1 + size + sizeof(BLOCK_HDR))) + { + BLOCK_HDR* free_blk; + + EiFreeNonPagedPool = EiFreeNonPagedPool - current->Size; + + /* + * Replace the bigger block with a smaller block in the + * same position in the list + */ + free_blk = (BLOCK_HDR *)(((int)current) + + sizeof(BLOCK_HDR) + size); + free_blk->Magic = BLOCK_HDR_FREE_MAGIC; + InsertHeadList(¤t->ListEntry, &free_blk->ListEntry); + free_blk->Size = current->Size - (sizeof(BLOCK_HDR) + size); + + current->Size=size; + RemoveEntryList(¤t->ListEntry); + InsertHeadList(&UsedBlockListHead, ¤t->ListEntry); + EiNrUsedBlocks++; + current->Magic = BLOCK_HDR_USED_MAGIC; + current->Tag = Tag; + current->Caller = Caller; + current->Dumped = FALSE; +#ifdef TAG_STATISTICS_TRACKING + MiAddToTagHashTable(current); +#endif /* TAG_STATISTICS_TRACKING */ + + EiUsedNonPagedPool = EiUsedNonPagedPool + current->Size; + EiFreeNonPagedPool = EiFreeNonPagedPool + free_blk->Size; + + VALIDATE_POOL; + return(block_to_address(current)); + } + + /* + * Otherwise allocate the whole block + */ + remove_from_free_list(current); + add_to_used_list(current); + + EiFreeNonPagedPool = EiFreeNonPagedPool - current->Size; + EiUsedNonPagedPool = EiUsedNonPagedPool + current->Size; + + current->Magic = BLOCK_HDR_USED_MAGIC; + current->Tag = Tag; + current->Caller = Caller; + current->Dumped = FALSE; +#ifdef TAG_STATISTICS_TRACKING + MiAddToTagHashTable(current); +#endif /* TAG_STATISTICS_TRACKING */ + + VALIDATE_POOL; + return(block_to_address(current)); +} + +#endif /* not WHOLE_PAGE_ALLOCATIONS */ + +VOID STDCALL ExFreeNonPagedPool (PVOID block) +/* + * FUNCTION: Releases previously allocated memory + * ARGUMENTS: + * block = block to free + */ +{ +#ifdef WHOLE_PAGE_ALLOCATIONS /* WHOLE_PAGE_ALLOCATIONS */ + KIRQL oldIrql; + + if (block == NULL) + { + return; + } + + DPRINT("freeing block %x\n",blk); + + POOL_TRACE("ExFreePool(block %x), size %d, caller %x\n",block,blk->size, + ((PULONG)&block)[-1]); + + KeAcquireSpinLock(&MmNpoolLock, &oldIrql); + + ExFreeWholePageBlock(block); + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + +#else /* not WHOLE_PAGE_ALLOCATIONS */ + + BLOCK_HDR* blk=address_to_block(block); + KIRQL oldIrql; + + if (block == NULL) + { + return; + } + + DPRINT("freeing block %x\n",blk); + + POOL_TRACE("ExFreePool(block %x), size %d, caller %x\n",block,blk->size, + ((PULONG)&block)[-1]); + + KeAcquireSpinLock(&MmNpoolLock, &oldIrql); + + VALIDATE_POOL; + + if (blk->Magic != BLOCK_HDR_USED_MAGIC) + { + if (blk->Magic == BLOCK_HDR_FREE_MAGIC) + { + DbgPrint("ExFreePool of already freed address %x\n", block); + } + else + { + DbgPrint("ExFreePool of non-allocated address %x (magic %x)\n", + block, blk->Magic); + } + KeBugCheck(0); + return; + } + + memset(block, 0xcc, blk->Size); + +#ifdef TAG_STATISTICS_TRACKING + MiRemoveFromTagHashTable(blk); +#endif /* TAG_STATISTICS_TRACKING */ + remove_from_used_list(blk); + blk->Magic = BLOCK_HDR_FREE_MAGIC; + add_to_free_list(blk); + merge_free_block(blk); + + EiUsedNonPagedPool = EiUsedNonPagedPool - blk->Size; + EiFreeNonPagedPool = EiFreeNonPagedPool + blk->Size; + VALIDATE_POOL; + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + +#endif /* WHOLE_PAGE_ALLOCATIONS */ +} + +PVOID STDCALL +ExAllocateNonPagedPoolWithTag(ULONG Type, ULONG Size, ULONG Tag, PVOID Caller) +{ +#ifdef WHOLE_PAGE_ALLOCATIONS + PVOID block; + KIRQL oldIrql; + + POOL_TRACE("ExAllocatePool(NumberOfBytes %d) caller %x ", + Size,Caller); + + KeAcquireSpinLock(&MmNpoolLock, &oldIrql); + + /* + * accomodate this useful idiom + */ + if (Size == 0) + { + POOL_TRACE("= NULL\n"); + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + return(NULL); + } + + block = ExAllocateWholePageBlock(Size); + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + return(block); + +#else /* not WHOLE_PAGE_ALLOCATIONS */ + BLOCK_HDR* current = NULL; + PLIST_ENTRY current_entry; + PVOID block; + BLOCK_HDR* best = NULL; + KIRQL oldIrql; + + POOL_TRACE("ExAllocatePool(NumberOfBytes %d) caller %x ", + Size,Caller); + + KeAcquireSpinLock(&MmNpoolLock, &oldIrql); + + VALIDATE_POOL; + + /* + * accomodate this useful idiom + */ + if (Size == 0) + { + POOL_TRACE("= NULL\n"); + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + return(NULL); + } + + /* + * Look for an already created block of sufficent size + */ + current_entry = FreeBlockListHead.Flink; + while (current_entry != &FreeBlockListHead) + { + DPRINT("current %x size %x tag_next %x\n",current,current->Size, + current->tag_next); + current = CONTAINING_RECORD(current_entry, BLOCK_HDR, ListEntry); + if (current->Size >= Size && + (best == NULL || current->Size < best->Size)) + { + best = current; + } + current_entry = current_entry->Flink; + } + if (best != NULL) + { + block=take_block(best, Size, Tag, Caller); + VALIDATE_POOL; + memset(block,0,Size); + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + return(block); + } + + + /* + * Otherwise create a new block + */ + KeReleaseSpinLock(&MmNpoolLock, oldIrql); + block=block_to_address(grow_kernel_pool(Size, Tag, Caller)); + memset(block, 0, Size); + return(block); +#endif /* WHOLE_PAGE_ALLOCATIONS */ +} + +#ifdef WHOLE_PAGE_ALLOCATIONS + +PVOID STDCALL +ExAllocateWholePageBlock(ULONG UserSize) +{ + PVOID Address; + PHYSICAL_ADDRESS Page; + ULONG i; + ULONG Size; + ULONG NrPages; + + Size = sizeof(ULONG) + UserSize; + NrPages = ROUND_UP(Size, PAGE_SIZE) / PAGE_SIZE; + + Address = MiAllocNonPagedPoolRegion(NrPages + 1); + + for (i = 0; i < NrPages; i++) + { + Page = MmAllocPage(MC_NPPOOL, 0); + if (Page.QuadPart == 0LL) + { + KeBugCheck(0); + } + MmCreateVirtualMapping(NULL, + Address + (i * PAGE_SIZE), + PAGE_READWRITE | PAGE_SYSTEM, + Page, + TRUE); + } + + *((PULONG)((ULONG)Address + (NrPages * PAGE_SIZE) - Size)) = NrPages; + return((PVOID)((ULONG)Address + (NrPages * PAGE_SIZE) - UserSize)); +} + +VOID STDCALL +ExFreeWholePageBlock(PVOID Addr) +{ + ULONG NrPages; + + if ((ULONG)Addr < kernel_pool_base || + (ULONG)Addr >= (kernel_pool_base + NONPAGED_POOL_SIZE)) + { + DbgPrint("Block %x found outside pool area\n", Addr); + KeBugCheck(0); + } + NrPages = *(PULONG)((ULONG)Addr - sizeof(ULONG)); + MiFreeNonPagedPoolRegion((PVOID)PAGE_ROUND_DOWN((ULONG)Addr), NrPages, TRUE); +} + +#endif /* WHOLE_PAGE_ALLOCATIONS */ + +/* EOF */ diff --git a/ntoskrnl/mm/pagefile.c b/ntoskrnl/mm/pagefile.c new file mode 100644 index 0000000..ade10f5 --- /dev/null +++ b/ntoskrnl/mm/pagefile.c @@ -0,0 +1,689 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pagefile.c + * PURPOSE: Paging file functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *********************************************************************/ + +typedef struct _PAGINGFILE +{ + LIST_ENTRY PagingFileListEntry; + PFILE_OBJECT FileObject; + LARGE_INTEGER MaximumSize; + LARGE_INTEGER CurrentSize; + ULONG FreePages; + ULONG UsedPages; + PULONG AllocMap; + KSPIN_LOCK AllocMapLock; + ULONG AllocMapSize; +} PAGINGFILE, *PPAGINGFILE; + +/* GLOBALS *******************************************************************/ + +#define MAX_PAGING_FILES (32) + +/* List of paging files, both used and free */ +static PPAGINGFILE PagingFileList[MAX_PAGING_FILES]; + +/* Lock for examining the list of paging files */ +static KSPIN_LOCK PagingFileListLock; + +/* Number of paging files */ +static ULONG MiPagingFileCount; + +/* Number of pages that are available for swapping */ +static ULONG MiFreeSwapPages; + +/* Number of pages that have been allocated for swapping */ +static ULONG MiUsedSwapPages; + +/* + * Number of pages that have been reserved for swapping but not yet allocated + */ +static ULONG MiReservedSwapPages; + +/* + * Ratio between reserved and available swap pages, e.g. setting this to five + * forces one swap page to be available for every five swap pages that are + * reserved. Setting this to zero turns off commit checking altogether. + */ +#define MM_PAGEFILE_COMMIT_RATIO (1) + +/* + * Number of pages that can be used for potentially swapable memory without + * pagefile space being reserved. The intention is that this allows smss + * to start up and create page files while ordinarily having a commit + * ratio of one. + */ +#define MM_PAGEFILE_COMMIT_GRACE (256) + +static PVOID MmCoreDumpPageFrame; +static PULONG MmCoreDumpBlockMap; +static ULONG MmCoreDumpSize; +static PULONG MmCoreDumpBlockMap = NULL; +static MM_DUMP_POINTERS MmCoreDumpDeviceFuncs; +ULONG MmCoreDumpType; + +/* + * Translate between a swap entry and a file and offset pair. + */ +#define FILE_FROM_ENTRY(i) ((i) >> 24) +#define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1) +#define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) | ((j) + 1)) + +static BOOLEAN MmSwapSpaceMessage = FALSE; + +/* FUNCTIONS *****************************************************************/ + +VOID +MmShowOutOfSpaceMessagePagingFile(VOID) +{ + if (!MmSwapSpaceMessage) + { + DPRINT1("MM: Out of swap space.\n"); + MmSwapSpaceMessage = TRUE; + } +} + +NTSTATUS MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl) +{ + ULONG i, offset; + LARGE_INTEGER file_offset; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + KEVENT Event; + + if (SwapEntry == 0) + { + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); + } + + i = FILE_FROM_ENTRY(SwapEntry); + offset = OFFSET_FROM_ENTRY(SwapEntry); + + if (i > MAX_PAGING_FILES) + { + DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry); + KeBugCheck(0); + } + if (PagingFileList[i]->FileObject == NULL || + PagingFileList[i]->FileObject->DeviceObject == NULL) + { + DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); + KeBugCheck(0); + } + + file_offset.QuadPart = offset * 4096; + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageWrite(PagingFileList[i]->FileObject, + Mdl, + &file_offset, + &Event, + &Iosb); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + return(Iosb.Status); + } + return(Status); +} + +NTSTATUS MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl) +{ + ULONG i, offset; + LARGE_INTEGER file_offset; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + KEVENT Event; + + if (SwapEntry == 0) + { + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); + } + + i = FILE_FROM_ENTRY(SwapEntry); + offset = OFFSET_FROM_ENTRY(SwapEntry); + + if (i > MAX_PAGING_FILES) + { + DPRINT1("Bad swap entry 0x%.8X\n", SwapEntry); + KeBugCheck(0); + } + if (PagingFileList[i]->FileObject == NULL || + PagingFileList[i]->FileObject->DeviceObject == NULL) + { + DPRINT1("Bad paging file 0x%.8X\n", SwapEntry); + KeBugCheck(0); + } + + file_offset.QuadPart = offset * 4096; + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageRead(PagingFileList[i]->FileObject, + Mdl, + &file_offset, + &Event, + &Iosb); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + return(Iosb.Status); + } + return(Status); +} + +VOID +MmInitPagingFile(VOID) +{ + ULONG i; + + KeInitializeSpinLock(&PagingFileListLock); + + MiFreeSwapPages = 0; + MiUsedSwapPages = 0; + MiReservedSwapPages = 0; + + for (i = 0; i < MAX_PAGING_FILES; i++) + { + PagingFileList[i] = NULL; + } + MiPagingFileCount = 0; + + /* + * Initialize the crash dump support. + */ + MmCoreDumpPageFrame = MmAllocateSection(PAGE_SIZE); + if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) + { + MmCoreDumpSize = MmStats.NrTotalPages * 4096 + 1024 * 1024; + } + else + { + MmCoreDumpSize = 1024 * 1024; + } +} + +BOOLEAN +MmReserveSwapPages(ULONG Nr) +{ + KIRQL oldIrql; + ULONG MiAvailSwapPages; + + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); + MiAvailSwapPages = + (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE; + MiReservedSwapPages = MiReservedSwapPages + Nr; + if (MM_PAGEFILE_COMMIT_RATIO != 0 && MiAvailSwapPages < MiReservedSwapPages) + { + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(FALSE); + } + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(TRUE); +} + +VOID +MmDereserveSwapPages(ULONG Nr) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); + MiReservedSwapPages = MiReservedSwapPages - Nr; + KeReleaseSpinLock(&PagingFileListLock, oldIrql); +} + +static ULONG +MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) +{ + KIRQL oldIrql; + ULONG i, j; + + KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); + + for (i = 0; i < PagingFile->AllocMapSize; i++) + { + for (j = 0; j < 32; j++) + { + if (!(PagingFile->AllocMap[i] & (1 << j))) + { + break; + } + } + if (j == 32) + { + continue; + } + PagingFile->AllocMap[i] |= (1 << j); + PagingFile->UsedPages++; + PagingFile->FreePages--; + KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); + return((i * 32) + j); + } + + KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); + return(0xFFFFFFFF); +} + +VOID +MmFreeSwapPage(SWAPENTRY Entry) +{ + ULONG i; + ULONG off; + KIRQL oldIrql; + + i = FILE_FROM_ENTRY(Entry); + off = OFFSET_FROM_ENTRY(Entry); + + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); + if (PagingFileList[i] == NULL) + { + KeBugCheck(0); + } + KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock); + + PagingFileList[i]->AllocMap[off / 32] &= (~(1 << (off % 32))); + + PagingFileList[i]->FreePages++; + PagingFileList[i]->UsedPages--; + + MiFreeSwapPages++; + MiUsedSwapPages--; + + KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock); + KeReleaseSpinLock(&PagingFileListLock, oldIrql); +} + +BOOLEAN +MmIsAvailableSwapPage(VOID) +{ + return(MiFreeSwapPages > 0); +} + +SWAPENTRY +MmAllocSwapPage(VOID) +{ + KIRQL oldIrql; + ULONG i; + ULONG off; + SWAPENTRY entry; + + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); + + if (MiFreeSwapPages == 0) + { + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(0); + } + + for (i = 0; i < MAX_PAGING_FILES; i++) + { + if (PagingFileList[i] != NULL && + PagingFileList[i]->FreePages >= 1) + { + off = MiAllocPageFromPagingFile(PagingFileList[i]); + if (off == 0xFFFFFFFF) + { + KeBugCheck(0); + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(STATUS_UNSUCCESSFUL); + } + MiUsedSwapPages++; + MiFreeSwapPages--; + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + + entry = ENTRY_FROM_FILE_OFFSET(i, off); + return(entry); + } + } + + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + KeBugCheck(0); + return(0); +} + +NTSTATUS STDCALL +MmDumpToPagingFile(ULONG BugCode, + ULONG BugCodeParameter1, + ULONG BugCodeParameter2, + ULONG BugCodeParameter3, + ULONG BugCodeParameter4, + PKTRAP_FRAME TrapFrame) +{ + PMM_CORE_DUMP_HEADER Headers; + PVOID Context; + NTSTATUS Status; + UCHAR MdlBase[sizeof(MDL) + sizeof(PVOID)]; + PMDL Mdl = (PMDL)MdlBase; + PETHREAD Thread = PsGetCurrentThread(); + ULONG StackSize; + PULONG MdlMap; + ULONG NextOffset = 0; + ULONG i; + + if (MmCoreDumpBlockMap == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + DbgPrint("MM: Dumping core"); + + /* Prepare the dump headers. */ + Headers = (PMM_CORE_DUMP_HEADER)MmCoreDumpPageFrame; + Headers->Magic = MM_CORE_DUMP_HEADER_MAGIC; + Headers->Version = MM_CORE_DUMP_HEADER_VERSION; + Headers->Type = MmCoreDumpType; + if (TrapFrame != NULL) + { + if (!(TrapFrame->Eflags & (1 << 17))) + { + memcpy(&Headers->TrapFrame, TrapFrame, + sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD))); + } + else + { + memcpy(&Headers->TrapFrame, TrapFrame, sizeof(KTRAP_FRAME)); + } + } + Headers->BugCheckCode = BugCode; + Headers->BugCheckParameters[0] = BugCodeParameter1; + Headers->BugCheckParameters[1] = BugCodeParameter2; + Headers->BugCheckParameters[2] = BugCodeParameter3; + Headers->BugCheckParameters[3] = BugCodeParameter4; + Headers->FaultingStackBase = (PVOID)Thread->Tcb.StackLimit; + Headers->FaultingStackSize = StackSize = + (ULONG)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit); + Headers->PhysicalMemorySize = MmStats.NrTotalPages * PAGE_SIZE; + + /* Initialize the dump device. */ + Context = MmCoreDumpDeviceFuncs.Context; + Status = MmCoreDumpDeviceFuncs.DeviceInit(Context); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to initialize core dump device.\n"); + return(Status); + } + + /* Initialize the MDL. */ + Mdl->Next = NULL; + Mdl->Size = sizeof(MDL) + sizeof(PVOID); + Mdl->MdlFlags = MDL_SOURCE_IS_NONPAGED_POOL; + Mdl->Process = NULL; + Mdl->MappedSystemVa = MmCoreDumpPageFrame; + Mdl->StartVa = NULL; + Mdl->ByteCount = PAGE_SIZE; + Mdl->ByteOffset = 0; + MdlMap = (PULONG)(Mdl + 1); + + /* Dump the header. */ + MdlMap[0] = MmGetPhysicalAddress(MmCoreDumpPageFrame).u.LowPart; + Status = MmCoreDumpDeviceFuncs.DeviceWrite(Context, + MmCoreDumpBlockMap[NextOffset], + Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write core dump header\n."); + } + NextOffset++; + DbgPrint("."); + + /* Write out the kernel mode stack of the faulting thread. */ + for (i = 0; i < (StackSize / PAGE_SIZE); i++) + { + Mdl->MappedSystemVa = (PVOID)(Thread->Tcb.StackLimit + (i * PAGE_SIZE)); + MdlMap[0] = MmGetPhysicalAddress(Mdl->MappedSystemVa).u.LowPart; + Status = + MmCoreDumpDeviceFuncs.DeviceWrite(Context, + MmCoreDumpBlockMap[NextOffset], + Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write page to core dump.\n"); + return(Status); + } + DbgPrint("."); + NextOffset++; + } + + /* Write out the contents of physical memory. */ + if (MmCoreDumpType == MM_CORE_DUMP_TYPE_FULL) + { + for (i = 0; i < MmStats.NrTotalPages; i++) + { + LARGE_INTEGER PhysicalAddress; + PhysicalAddress.QuadPart = i * PAGE_SIZE; + MdlMap[0] = i * PAGE_SIZE; + MmCreateVirtualMappingForKernel(MmCoreDumpPageFrame, + PAGE_READWRITE, + PhysicalAddress); + Status = + MmCoreDumpDeviceFuncs.DeviceWrite(Context, + MmCoreDumpBlockMap[NextOffset], + Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write page to core dump.\n"); + return(Status); + } + DbgPrint("."); + NextOffset++; + } + } + + DbgPrint("\n"); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtCreatePagingFile(IN PUNICODE_STRING FileName, + IN PLARGE_INTEGER InitialSize, + IN PLARGE_INTEGER MaximumSize, + IN ULONG Reserved) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE FileHandle; + IO_STATUS_BLOCK IoStatus; + PFILE_OBJECT FileObject; + PPAGINGFILE PagingFile; + KIRQL oldIrql; + ULONG AllocMapSize; + ULONG i; + + DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n", + FileName, InitialSize->QuadPart); + + if (MiPagingFileCount >= MAX_PAGING_FILES) + { + return(STATUS_TOO_MANY_PAGING_FILES); + } + + InitializeObjectAttributes(&ObjectAttributes, + FileName, + 0, + NULL, + NULL); + + Status = IoCreateFile(&FileHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatus, + NULL, + 0, + 0, + FILE_OPEN_IF, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0, + CreateFileTypeNone, + NULL, + SL_OPEN_PAGING_FILE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = NtSetInformationFile(FileHandle, + &IoStatus, + InitialSize, + sizeof(LARGE_INTEGER), + FileAllocationInformation); + if (!NT_SUCCESS(Status)) + { + ZwClose(FileHandle); + return(Status); + } + + Status = ObReferenceObjectByHandle(FileHandle, + FILE_ALL_ACCESS, + IoFileObjectType, + UserMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + NtClose(FileHandle); + return(Status); + } + + PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile)); + if (PagingFile == NULL) + { + ObDereferenceObject(FileObject); + NtClose(FileHandle); + return(STATUS_NO_MEMORY); + } + + PagingFile->FileObject = FileObject; + PagingFile->MaximumSize.QuadPart = MaximumSize->QuadPart; + PagingFile->CurrentSize.QuadPart = InitialSize->QuadPart; + PagingFile->FreePages = InitialSize->QuadPart / PAGE_SIZE; + PagingFile->UsedPages = 0; + KeInitializeSpinLock(&PagingFile->AllocMapLock); + + AllocMapSize = (PagingFile->FreePages / 32) + 1; + PagingFile->AllocMap = ExAllocatePool(NonPagedPool, + AllocMapSize * sizeof(ULONG)); + PagingFile->AllocMapSize = AllocMapSize; + + if (PagingFile->AllocMap == NULL) + { + ExFreePool(PagingFile); + ObDereferenceObject(FileObject); + NtClose(FileHandle); + return(STATUS_NO_MEMORY); + } + + KeAcquireSpinLock(&PagingFileListLock, &oldIrql); + for (i = 0; i < MAX_PAGING_FILES; i++) + { + if (PagingFileList[i] == NULL) + { + PagingFileList[i] = PagingFile; + break; + } + } + MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages; + MiPagingFileCount++; + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + + /* Check whether this pagefile can be a crash dump target. */ + if (PagingFile->CurrentSize.QuadPart >= MmCoreDumpSize && + MmCoreDumpBlockMap != NULL) + { + MmCoreDumpBlockMap = + ExAllocatePool(NonPagedPool, + (MmCoreDumpSize / PAGE_SIZE) * sizeof(ULONG)); + if (MmCoreDumpBlockMap == NULL) + { + DPRINT1("Failed to allocate block map.\n"); + NtClose(FileHandle); + return(STATUS_SUCCESS); + } + Status = ZwFsControlFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + FSCTL_GET_DUMP_BLOCK_MAP, + &MmCoreDumpSize, + sizeof(ULONG), + MmCoreDumpBlockMap, + (MmCoreDumpSize / PAGE_SIZE) * sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get dump block map (Status %X)\n", Status); + NtClose(FileHandle); + ExFreePool(MmCoreDumpBlockMap); + MmCoreDumpBlockMap = NULL; + return(STATUS_SUCCESS); + } + Status = ZwDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatus, + IOCTL_GET_DUMP_POINTERS, + NULL, + 0, + &MmCoreDumpDeviceFuncs, + sizeof(MmCoreDumpDeviceFuncs)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get dump block map (Status %X)\n", Status); + NtClose(FileHandle); + ExFreePool(MmCoreDumpBlockMap); + MmCoreDumpBlockMap = NULL; + return(STATUS_SUCCESS); + } + } + NtClose(FileHandle); + + MmSwapSpaceMessage = FALSE; + + return(STATUS_SUCCESS); +} + + +/* EOF */ + + + + + + + diff --git a/ntoskrnl/mm/pageop.c b/ntoskrnl/mm/pageop.c new file mode 100644 index 0000000..6c7a46f --- /dev/null +++ b/ntoskrnl/mm/pageop.c @@ -0,0 +1,241 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pageop.c + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 27/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define PAGEOP_HASH_TABLE_SIZE (32) + +KSPIN_LOCK MmPageOpHashTableLock; +PMM_PAGEOP MmPageOpHashTable[PAGEOP_HASH_TABLE_SIZE] = {NULL, } ; + +#define TAG_MM_PAGEOP TAG('M', 'P', 'O', 'P') + +/* FUNCTIONS *****************************************************************/ + +VOID +MmReleasePageOp(PMM_PAGEOP PageOp) + /* + * FUNCTION: Release a reference to a page operation descriptor + */ +{ + KIRQL oldIrql; + PMM_PAGEOP PrevPageOp; + + KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql); + PageOp->ReferenceCount--; + if (PageOp->ReferenceCount > 0) + { + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return; + } + InterlockedDecrement(&PageOp->MArea->PageOpCount); + PrevPageOp = MmPageOpHashTable[PageOp->Hash]; + if (PrevPageOp == PageOp) + { + MmPageOpHashTable[PageOp->Hash] = PageOp->Next; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + ExFreePool(PageOp); + return; + } + while (PrevPageOp->Next != NULL) + { + if (PrevPageOp->Next == PageOp) + { + PrevPageOp->Next = PageOp->Next; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + ExFreePool(PageOp); + return; + } + PrevPageOp = PrevPageOp->Next; + } + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + KeBugCheck(0); +} + +PMM_PAGEOP +MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, + PMM_SECTION_SEGMENT Segment, ULONG Offset) +{ + ULONG Hash; + KIRQL oldIrql; + PMM_PAGEOP PageOp; + + /* + * Calcuate the hash value for pageop structure + */ + if (MArea->Type == MEMORY_AREA_SECTION_VIEW) + { + Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE)); + } + else + { + Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE)); + } + Hash = Hash % PAGEOP_HASH_TABLE_SIZE; + + KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql); + + /* + * Check for an existing pageop structure + */ + PageOp = MmPageOpHashTable[Hash]; + while (PageOp != NULL) + { + if (MArea->Type == MEMORY_AREA_SECTION_VIEW) + { + if (PageOp->Segment == Segment && + PageOp->Offset == Offset) + { + break; + } + } + else + { + if (PageOp->Pid == Pid && + PageOp->Address == Address) + { + break; + } + } + PageOp = PageOp->Next; + } + + /* + * If we found an existing pageop then increment the reference count + * and return it. + */ + if (PageOp != NULL) + { + PageOp->ReferenceCount++; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(PageOp); + } + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(NULL); +} + +PMM_PAGEOP +MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, + PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType) + /* + * FUNCTION: Get a page operation descriptor corresponding to + * the memory area and either the segment, offset pair or the + * pid, address pair. + */ +{ + ULONG Hash; + KIRQL oldIrql; + PMM_PAGEOP PageOp; + + /* + * Calcuate the hash value for pageop structure + */ + if (MArea->Type == MEMORY_AREA_SECTION_VIEW) + { + Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE)); + } + else + { + Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE)); + } + Hash = Hash % PAGEOP_HASH_TABLE_SIZE; + + KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql); + + /* + * Check for an existing pageop structure + */ + PageOp = MmPageOpHashTable[Hash]; + while (PageOp != NULL) + { + if (MArea->Type == MEMORY_AREA_SECTION_VIEW) + { + if (PageOp->Segment == Segment && + PageOp->Offset == Offset) + { + break; + } + } + else + { + if (PageOp->Pid == Pid && + PageOp->Address == Address) + { + break; + } + } + PageOp = PageOp->Next; + } + + /* + * If we found an existing pageop then increment the reference count + * and return it. + */ + if (PageOp != NULL) + { + PageOp->ReferenceCount++; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(PageOp); + } + + /* + * Otherwise add a new pageop. + */ + PageOp = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_PAGEOP), + TAG_MM_PAGEOP); + if (PageOp == NULL) + { + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(NULL); + } + + if (MArea->Type != MEMORY_AREA_SECTION_VIEW) + { + PageOp->Pid = Pid; + PageOp->Address = Address; + } + else + { + PageOp->Segment = Segment; + PageOp->Offset = Offset; + } + PageOp->ReferenceCount = 1; + PageOp->Next = MmPageOpHashTable[Hash]; + PageOp->Hash = Hash; + PageOp->Thread = PsGetCurrentThread(); + PageOp->Abandoned = FALSE; + PageOp->Status = STATUS_PENDING; + PageOp->OpType = OpType; + PageOp->MArea = MArea; + KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE); + MmPageOpHashTable[Hash] = PageOp; + InterlockedIncrement(&MArea->PageOpCount); + + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(PageOp); +} + + + + + + + + diff --git a/ntoskrnl/mm/pager.c b/ntoskrnl/mm/pager.c new file mode 100644 index 0000000..ff1348e --- /dev/null +++ b/ntoskrnl/mm/pager.c @@ -0,0 +1,78 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pager.c + * PURPOSE: Moves infrequently used data out of memory + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 27/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static HANDLE PagerThreadHandle; +static CLIENT_ID PagerThreadId; +static KEVENT PagerThreadEvent; +static BOOLEAN PagerThreadShouldTerminate; + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS STDCALL +MmPagerThreadMain(PVOID Ignored) +{ + NTSTATUS Status; + + for(;;) + { + Status = KeWaitForSingleObject(&PagerThreadEvent, + 0, + KernelMode, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("PagerThread: Wait failed\n"); + KeBugCheck(0); + } + if (PagerThreadShouldTerminate) + { + DbgPrint("PagerThread: Terminating\n"); + return(STATUS_SUCCESS); + } + } +} + +NTSTATUS MmInitPagerThread(VOID) +{ + NTSTATUS Status; + + PagerThreadShouldTerminate = FALSE; + KeInitializeEvent(&PagerThreadEvent, + SynchronizationEvent, + FALSE); + + Status = PsCreateSystemThread(&PagerThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + &PagerThreadId, + MmPagerThreadMain, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/mm/pagfault.c b/ntoskrnl/mm/pagfault.c new file mode 100644 index 0000000..f20107e --- /dev/null +++ b/ntoskrnl/mm/pagfault.c @@ -0,0 +1,19 @@ +/* $Id$ */ +#include +#include + +BOOLEAN +STDCALL +MmIsRecursiveIoFault ( + VOID + ) +{ + PETHREAD Thread = PsGetCurrentThread (); + + return ( Thread->DisablePageFaultClustering + | Thread->ForwardClusterOnly + ); +} + + +/* EOF */ diff --git a/ntoskrnl/mm/paging.c b/ntoskrnl/mm/paging.c new file mode 100644 index 0000000..c6ff3a3 --- /dev/null +++ b/ntoskrnl/mm/paging.c @@ -0,0 +1,19 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/paging.c + * PURPOSE: Paging file functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + + +/* FUNCTIONS *****************************************************************/ + diff --git a/ntoskrnl/mm/pool.c b/ntoskrnl/mm/pool.c new file mode 100644 index 0000000..10c870f --- /dev/null +++ b/ntoskrnl/mm/pool.c @@ -0,0 +1,154 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pool.c + * PURPOSE: Implements the kernel memory pool + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *****************************************************************/ + +#define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24)) + +/* FUNCTIONS ***************************************************************/ + +PVOID STDCALL STATIC +EiAllocatePool(POOL_TYPE PoolType, + ULONG NumberOfBytes, + ULONG Tag, + PVOID Caller) +{ + PVOID Block; + + if (PoolType == NonPagedPoolCacheAligned || + PoolType == NonPagedPoolCacheAlignedMustS) + { + UNIMPLEMENTED; + } + + switch(PoolType) + { + case NonPagedPool: + case NonPagedPoolMustSucceed: + case NonPagedPoolCacheAligned: + case NonPagedPoolCacheAlignedMustS: + Block = + ExAllocateNonPagedPoolWithTag(PoolType, + NumberOfBytes, + Tag, + Caller); + break; + + case PagedPool: + case PagedPoolCacheAligned: + Block = ExAllocatePagedPoolWithTag(PoolType,NumberOfBytes,Tag); + break; + + default: + return(NULL); + }; + + if ((PoolType==NonPagedPoolMustSucceed || + PoolType==NonPagedPoolCacheAlignedMustS) && Block==NULL) + { + KeBugCheck(MUST_SUCCEED_POOL_EMPTY); + } + return(Block); +} + +PVOID STDCALL +ExAllocatePool (POOL_TYPE PoolType, ULONG NumberOfBytes) +/* + * FUNCTION: Allocates pool memory of a specified type and returns a pointer + * to the allocated block. This routine is used for general purpose allocation + * of memory + * ARGUMENTS: + * PoolType + * Specifies the type of memory to allocate which can be one + * of the following: + * + * NonPagedPool + * NonPagedPoolMustSucceed + * NonPagedPoolCacheAligned + * NonPagedPoolCacheAlignedMustS + * PagedPool + * PagedPoolCacheAligned + * + * NumberOfBytes + * Specifies the number of bytes to allocate + * RETURNS: The allocated block on success + * NULL on failure + */ +{ + PVOID Block; + Block = EiAllocatePool(PoolType, + NumberOfBytes, + TAG_NONE, + (PVOID)__builtin_return_address(0)); + return(Block); +} + + +PVOID STDCALL +ExAllocatePoolWithTag (ULONG PoolType, ULONG NumberOfBytes, ULONG Tag) +{ + PVOID Block; + Block = EiAllocatePool(PoolType, + NumberOfBytes, + Tag, + (PVOID)__builtin_return_address(0)); + return(Block); +} + + +PVOID STDCALL +ExAllocatePoolWithQuota (POOL_TYPE PoolType, ULONG NumberOfBytes) +{ + return(ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE)); +} + + +PVOID STDCALL +ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag) +{ +#if 0 + PVOID Block; + Block = EiAllocatePool(PoolType, + NumberOfBytes, + Tag, + (PVOID)__builtin_return_address(0)); + return(Block); +#endif + UNIMPLEMENTED; +} + +VOID STDCALL +ExFreePool(IN PVOID Block) +{ + if (Block >= MmPagedPoolBase && Block < (MmPagedPoolBase + MmPagedPoolSize)) + { + ExFreePagedPool(Block); + } + else + { + ExFreeNonPagedPool(Block); + } +} + +/* EOF */ + + + + diff --git a/ntoskrnl/mm/ppool.c b/ntoskrnl/mm/ppool.c new file mode 100644 index 0000000..e06829b --- /dev/null +++ b/ntoskrnl/mm/ppool.c @@ -0,0 +1,265 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/ppool.c + * PURPOSE: Implements the paged pool + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include + +/* GLOBALS *******************************************************************/ + +typedef struct _MM_PPOOL_FREE_BLOCK_HEADER +{ + ULONG Size; + struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree; +} MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER; + +typedef struct _MM_PPOOL_USED_BLOCK_HEADER +{ + ULONG Size; +} MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER; + +PVOID MmPagedPoolBase; +ULONG MmPagedPoolSize; +static FAST_MUTEX MmPagedPoolLock; +static PMM_PPOOL_FREE_BLOCK_HEADER MmPagedPoolFirstFreeBlock; + +/* FUNCTIONS *****************************************************************/ + +VOID MmInitializePagedPool(VOID) +{ + MmPagedPoolFirstFreeBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)MmPagedPoolBase; + /* + * We are still at a high IRQL level at this point so explicitly commit + * the first page of the paged pool before writing the first block header. + */ + MmCommitPagedPoolAddress((PVOID)MmPagedPoolFirstFreeBlock); + MmPagedPoolFirstFreeBlock->Size = MmPagedPoolSize; + MmPagedPoolFirstFreeBlock->NextFree = NULL; + + ExInitializeFastMutex(&MmPagedPoolLock); +} + +/********************************************************************** + * NAME INTERNAL + * ExAllocatePagedPoolWithTag@12 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +PVOID STDCALL +ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType, + IN ULONG NumberOfBytes, + IN ULONG Tag) +{ + PMM_PPOOL_FREE_BLOCK_HEADER BestBlock; + PMM_PPOOL_FREE_BLOCK_HEADER CurrentBlock; + ULONG BlockSize; + PMM_PPOOL_USED_BLOCK_HEADER NewBlock; + PMM_PPOOL_FREE_BLOCK_HEADER NextBlock; + PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock; + PMM_PPOOL_FREE_BLOCK_HEADER BestPreviousBlock; + PVOID BlockAddress; + + /* + * Don't bother allocating anything for a zero-byte block. + */ + if (NumberOfBytes == 0) + { + return(NULL); + } + + /* + * Calculate the total number of bytes we will need. + */ + BlockSize = NumberOfBytes + sizeof(MM_PPOOL_USED_BLOCK_HEADER); + if (BlockSize < sizeof(MM_PPOOL_FREE_BLOCK_HEADER)) + { + /* At least we need the size of the free block header. */ + BlockSize = sizeof(MM_PPOOL_FREE_BLOCK_HEADER); + } + + ExAcquireFastMutex(&MmPagedPoolLock); + + /* + * Find the best fitting block. + */ + PreviousBlock = NULL; + BestPreviousBlock = BestBlock = NULL; + CurrentBlock = MmPagedPoolFirstFreeBlock; + while (CurrentBlock != NULL) + { + if (CurrentBlock->Size >= BlockSize && + (BestBlock == NULL || + (BestBlock->Size - BlockSize) > (CurrentBlock->Size - BlockSize))) + { + BestPreviousBlock = PreviousBlock; + BestBlock = CurrentBlock; + } + + PreviousBlock = CurrentBlock; + CurrentBlock = CurrentBlock->NextFree; + } + + /* + * We didn't find anything suitable at all. + */ + if (BestBlock == NULL) + { + ExReleaseFastMutex(&MmPagedPoolLock); + return(NULL); + } + + /* + * Is there enough space to create a second block from the unused portion. + */ + if ((BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER)) + { + ULONG NewSize = BestBlock->Size - BlockSize; + + /* + * Create the new free block. + */ + NextBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)((PVOID)BestBlock + BlockSize); + NextBlock->Size = NewSize; + NextBlock->NextFree = BestBlock->NextFree; + + /* + * Replace the old free block with it. + */ + if (BestPreviousBlock == NULL) + { + MmPagedPoolFirstFreeBlock = NextBlock; + } + else + { + BestPreviousBlock->NextFree = NextBlock; + } + + /* + * Create the new used block header. + */ + NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock; + NewBlock->Size = BlockSize; + } + else + { + ULONG NewSize = BestBlock->Size; + + /* + * Remove the selected block from the list of free blocks. + */ + if (BestPreviousBlock == NULL) + { + MmPagedPoolFirstFreeBlock = BestBlock->NextFree; + } + else + { + BestPreviousBlock->NextFree = BestBlock->NextFree; + } + + /* + * Set up the header of the new block + */ + NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock; + NewBlock->Size = NewSize; + } + + ExReleaseFastMutex(&MmPagedPoolLock); + + BlockAddress = (PVOID)NewBlock + sizeof(MM_PPOOL_USED_BLOCK_HEADER); + + memset(BlockAddress, 0, NumberOfBytes); + + return(BlockAddress); +} + +VOID STDCALL +ExFreePagedPool(IN PVOID Block) +{ + PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock; + PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = + (PMM_PPOOL_USED_BLOCK_HEADER)(Block - sizeof(MM_PPOOL_USED_BLOCK_HEADER)); + ULONG UsedSize = UsedBlock->Size; + PMM_PPOOL_FREE_BLOCK_HEADER FreeBlock = + (PMM_PPOOL_FREE_BLOCK_HEADER)UsedBlock; + PMM_PPOOL_FREE_BLOCK_HEADER NextBlock; + PMM_PPOOL_FREE_BLOCK_HEADER NextNextBlock; + + ExAcquireFastMutex(&MmPagedPoolLock); + + /* + * Begin setting up the newly freed block's header. + */ + FreeBlock->Size = UsedSize; + + /* + * Find the blocks immediately before and after the newly freed block on the free list. + */ + PreviousBlock = NULL; + NextBlock = MmPagedPoolFirstFreeBlock; + while (NextBlock != NULL && NextBlock < FreeBlock) + { + PreviousBlock = NextBlock; + NextBlock = NextBlock->NextFree; + } + + /* + * Insert the freed block on the free list. + */ + if (PreviousBlock == NULL) + { + FreeBlock->NextFree = MmPagedPoolFirstFreeBlock; + MmPagedPoolFirstFreeBlock = FreeBlock; + } + else + { + PreviousBlock->NextFree = FreeBlock; + FreeBlock->NextFree = NextBlock; + } + + /* + * If the next block is immediately adjacent to the newly freed one then + * merge them. + */ + if (NextBlock != NULL && + ((PVOID)FreeBlock + FreeBlock->Size) == (PVOID)NextBlock) + { + FreeBlock->Size = FreeBlock->Size + NextBlock->Size; + FreeBlock->NextFree = NextBlock->NextFree; + NextNextBlock = NextBlock->NextFree; + } + else + { + NextNextBlock = NextBlock; + } + + /* + * If the previous block is adjacent to the newly freed one then + * merge them. + */ + if (PreviousBlock != NULL && + ((PVOID)PreviousBlock + PreviousBlock->Size) == (PVOID)FreeBlock) + { + PreviousBlock->Size = PreviousBlock->Size + FreeBlock->Size; + PreviousBlock->NextFree = NextNextBlock; + } + + ExReleaseFastMutex(&MmPagedPoolLock); +} + +/* EOF */ diff --git a/ntoskrnl/mm/region.c b/ntoskrnl/mm/region.c new file mode 100644 index 0000000..1070666 --- /dev/null +++ b/ntoskrnl/mm/region.c @@ -0,0 +1,303 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/region.c + * PROGRAMMER: David Welch + * PURPOSE: + */ + +/* INCLUDE *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_MM_REGION TAG('M', 'R', 'G', 'N') + +/* FUNCTIONS *****************************************************************/ + +VOID STATIC +InsertAfterEntry(PLIST_ENTRY Previous, + PLIST_ENTRY Entry) +/* + * FUNCTION: Insert a list entry after another entry in the list + */ +{ + Previous->Flink->Blink = Entry; + + Entry->Flink = Previous->Flink; + Entry->Blink = Previous; + + Previous->Flink = Entry; +} + +PMM_REGION STATIC +MmSplitRegion(PMM_REGION InitialRegion, PVOID InitialBaseAddress, + PVOID StartAddress, ULONG Length, ULONG NewType, + ULONG NewProtect, PMADDRESS_SPACE AddressSpace, + PMM_ALTER_REGION_FUNC AlterFunc) +{ + PMM_REGION NewRegion1; + PMM_REGION NewRegion2; + ULONG InternalLength; + + /* Allocate this in front otherwise the failure case is too difficult. */ + NewRegion2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION), + TAG_MM_REGION); + if (NewRegion2 == NULL) + { + return(NULL); + } + + /* Create the new region. */ + NewRegion1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION), + TAG_MM_REGION); + if (NewRegion1 == NULL) + { + ExFreePool(NewRegion2); + return(NULL); + } + NewRegion1->Type = NewType; + NewRegion1->Protect = NewProtect; + InternalLength = (InitialBaseAddress + InitialRegion->Length) - StartAddress; + InternalLength = min(InternalLength, Length); + NewRegion1->Length = InternalLength; + InsertAfterEntry(&InitialRegion->RegionListEntry, + &NewRegion1->RegionListEntry); + + /* + * Call our helper function to do the changes on the addresses contained + * in the initial region. + */ + AlterFunc(AddressSpace, StartAddress, InternalLength, InitialRegion->Type, + InitialRegion->Protect, NewType, NewProtect); + + /* + * If necessary create a new region for the portion of the initial region + * beyond the range of addresses to alter. + */ + if ((InitialBaseAddress + InitialRegion->Length) > (StartAddress + Length)) + { + NewRegion2->Type = InitialRegion->Type; + NewRegion2->Protect = InitialRegion->Protect; + NewRegion2->Length = (InitialBaseAddress + InitialRegion->Length) - + (StartAddress + Length); + InsertAfterEntry(&NewRegion1->RegionListEntry, + &NewRegion2->RegionListEntry); + } + else + { + ExFreePool(NewRegion2); + } + + /* Either remove or shrink the initial region. */ + if (InitialBaseAddress == StartAddress) + { + RemoveEntryList(&InitialRegion->RegionListEntry); + ExFreePool(InitialRegion); + } + else + { + InitialRegion->Length = StartAddress - InitialBaseAddress; + } + + return(NewRegion1); +} + +NTSTATUS +MmAlterRegion(PMADDRESS_SPACE AddressSpace, PVOID BaseAddress, + PLIST_ENTRY RegionListHead, PVOID StartAddress, ULONG Length, + ULONG NewType, ULONG NewProtect, PMM_ALTER_REGION_FUNC AlterFunc) +{ + PMM_REGION InitialRegion; + PVOID InitialBaseAddress; + PMM_REGION NewRegion; + PLIST_ENTRY CurrentEntry; + PMM_REGION CurrentRegion = NULL; + PVOID CurrentBaseAddress; + ULONG RemainingLength; + + /* + * Find the first region containing part of the range of addresses to + * be altered. + */ + InitialRegion = MmFindRegion(BaseAddress, RegionListHead, StartAddress, + &InitialBaseAddress); + if ((StartAddress + Length) > + (InitialBaseAddress + InitialRegion->Length)) + { + RemainingLength = (StartAddress + Length) - + (InitialBaseAddress + InitialRegion->Length); + } + else + { + RemainingLength = 0; + } + /* + * If necessary then split the region into the affected and unaffected parts. + */ + if (InitialRegion->Type != NewType || InitialRegion->Protect != NewProtect) + { + NewRegion = MmSplitRegion(InitialRegion, InitialBaseAddress, + StartAddress, Length, NewType, NewProtect, + AddressSpace, AlterFunc); + if (NewRegion == NULL) + { + return(STATUS_NO_MEMORY); + } + } + else + { + NewRegion = InitialRegion; + } + + /* + * Free any complete regions that are containing in the range of addresses + * and call the helper function to actually do the changes. + */ + CurrentEntry = NewRegion->RegionListEntry.Flink; + CurrentBaseAddress = StartAddress + NewRegion->Length; + while (RemainingLength > 0 && CurrentRegion->Length <= RemainingLength) + { + CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, + RegionListEntry); + CurrentEntry = CurrentEntry->Flink; + if (CurrentRegion->Type != NewType && + CurrentRegion->Protect != NewProtect) + { + AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length, + CurrentRegion->Type, CurrentRegion->Protect, + NewType, NewProtect); + } + CurrentBaseAddress += CurrentRegion->Length; + NewRegion->Length += CurrentRegion->Length; + RemainingLength -= CurrentRegion->Length; + RemoveEntryList(&CurrentRegion->RegionListEntry); + ExFreePool(CurrentRegion); + } + + /* + * Split any final region. + */ + if (RemainingLength > 0) + { + CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, + RegionListEntry); + if (CurrentRegion->Type != NewType && + CurrentRegion->Protect != NewProtect) + { + AlterFunc(AddressSpace, CurrentBaseAddress, CurrentRegion->Length, + CurrentRegion->Type, CurrentRegion->Protect, + NewType, NewProtect); + } + NewRegion->Length += RemainingLength; + CurrentRegion->Length -= RemainingLength; + } + + /* + * If the region after the new region has the same type then merge them. + */ + if (NewRegion->RegionListEntry.Flink != RegionListHead) + { + CurrentEntry = NewRegion->RegionListEntry.Flink; + CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, + RegionListEntry); + if (CurrentRegion->Type == NewRegion->Type && + CurrentRegion->Protect == NewRegion->Protect) + { + NewRegion->Length += CurrentRegion->Length; + RemoveEntryList(&CurrentRegion->RegionListEntry); + ExFreePool(CurrentRegion); + } + } + + /* + * If the region before the new region has the same type then merge them. + */ + if (NewRegion->RegionListEntry.Blink != RegionListHead) + { + CurrentEntry = NewRegion->RegionListEntry.Blink; + CurrentRegion = CONTAINING_RECORD(CurrentEntry, MM_REGION, + RegionListEntry); + if (CurrentRegion->Type == NewRegion->Type && + CurrentRegion->Protect == NewRegion->Protect) + { + NewRegion->Length += CurrentRegion->Length; + RemoveEntryList(&CurrentRegion->RegionListEntry); + ExFreePool(CurrentRegion); + } + } + + return(STATUS_SUCCESS); +} + +VOID +MmInitialiseRegion(PLIST_ENTRY RegionListHead, ULONG Length, ULONG Type, + ULONG Protect) +{ + PMM_REGION Region; + + Region = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_REGION), + TAG_MM_REGION); + Region->Type = Type; + Region->Protect = Protect; + Region->Length = Length; + InitializeListHead(RegionListHead); + InsertHeadList(RegionListHead, &Region->RegionListEntry); +} + +PMM_REGION +MmFindRegion(PVOID BaseAddress, PLIST_ENTRY RegionListHead, PVOID Address, + PVOID* RegionBaseAddress) +{ + PLIST_ENTRY current_entry; + PMM_REGION current; + PVOID StartAddress = BaseAddress; + + current_entry = RegionListHead->Flink; + while (current_entry != RegionListHead) + { + current = CONTAINING_RECORD(current_entry, MM_REGION, RegionListEntry); + + if (StartAddress <= Address && + (StartAddress + current->Length) > Address) + { + if (RegionBaseAddress != NULL) + { + *RegionBaseAddress = StartAddress; + } + return(current); + } + + current_entry = current_entry->Flink; + StartAddress += current->Length; + } + return(NULL); +} diff --git a/ntoskrnl/mm/rmap.c b/ntoskrnl/mm/rmap.c new file mode 100644 index 0000000..81df3e4 --- /dev/null +++ b/ntoskrnl/mm/rmap.c @@ -0,0 +1,443 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/rmap.c + * PURPOSE: kernel memory managment functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 27/12/01 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES ********************************************************************/ + +typedef struct _MM_RMAP_ENTRY +{ + struct _MM_RMAP_ENTRY* Next; + PEPROCESS Process; + PVOID Address; +} MM_RMAP_ENTRY, *PMM_RMAP_ENTRY; + +/* GLOBALS ******************************************************************/ + +static FAST_MUTEX RmapListLock; + +/* FUNCTIONS ****************************************************************/ + +VOID +MmInitializeRmapList(VOID) +{ + ExInitializeFastMutex(&RmapListLock); +} + +NTSTATUS +MmWritePagePhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress) +{ + PMM_RMAP_ENTRY entry; + PMEMORY_AREA MemoryArea; + ULONG Type; + PVOID Address; + PEPROCESS Process; + PMM_PAGEOP PageOp; + LARGE_INTEGER Offset; + NTSTATUS Status; + + /* + * Check that the address still has a valid rmap; then reference the + * process so it isn't freed while we are working. + */ + ExAcquireFastMutex(&RmapListLock); + entry = MmGetRmapListHeadPage(PhysicalAddress); + if (entry == NULL) + { + ExReleaseFastMutex(&RmapListLock); + return(STATUS_UNSUCCESSFUL); + } + Process = entry->Process; + Address = entry->Address; + if ((((ULONG)Address) & 0xFFF) != 0) + { + KeBugCheck(0); + } + Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode); + ExReleaseFastMutex(&RmapListLock); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* + * Lock the address space; then check that the address we are using + * still corresponds to a valid memory area (the page might have been + * freed or paged out after we read the rmap entry.) + */ + MmLockAddressSpace(&Process->AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, Address); + if (MemoryArea == NULL) + { + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + Type = MemoryArea->Type; + if (Type == MEMORY_AREA_SECTION_VIEW) + { + Offset.QuadPart = (ULONG)((Address - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset); + + /* + * Get or create a pageop + */ + PageOp = MmGetPageOp(MemoryArea, 0, 0, + MemoryArea->Data.SectionData.Segment, + Offset.u.LowPart, MM_PAGEOP_PAGEOUT); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed\n"); + KeBugCheck(0); + } + + + if (PageOp->Thread != PsGetCurrentThread()) + { + MmReleasePageOp(PageOp); + MmUnlockAddressSpace(&Process->AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Release locks now we have a page op. + */ + MmUnlockAddressSpace(&Process->AddressSpace); + + /* + * Do the actual page out work. + */ + Status = MmWritePageSectionView(&Process->AddressSpace, MemoryArea, + Address, PageOp); + } + else if (Type == MEMORY_AREA_VIRTUAL_MEMORY) + { + PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId, + Address, NULL, 0, MM_PAGEOP_PAGEOUT); + + + if (PageOp->Thread != PsGetCurrentThread()) + { + MmReleasePageOp(PageOp); + MmUnlockAddressSpace(&Process->AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Release locks now we have a page op. + */ + MmUnlockAddressSpace(&Process->AddressSpace); + + /* + * Do the actual page out work. + */ + Status = MmWritePageVirtualMemory(&Process->AddressSpace, MemoryArea, + Address, PageOp); + } + else + { + KeBugCheck(0); + } + ObDereferenceObject(Process); + return(Status); +} + +NTSTATUS +MmPageOutPhysicalAddress(PHYSICAL_ADDRESS PhysicalAddress) +{ + PMM_RMAP_ENTRY entry; + PMEMORY_AREA MemoryArea; + ULONG Type; + PVOID Address; + PEPROCESS Process; + PMM_PAGEOP PageOp; + LARGE_INTEGER Offset; + NTSTATUS Status; + + ExAcquireFastMutex(&RmapListLock); + entry = MmGetRmapListHeadPage(PhysicalAddress); + if (entry == NULL) + { + ExReleaseFastMutex(&RmapListLock); + return(STATUS_UNSUCCESSFUL); + } + Process = entry->Process; + Address = entry->Address; + if ((((ULONG)Address) & 0xFFF) != 0) + { + KeBugCheck(0); + } + + Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode); + ExReleaseFastMutex(&RmapListLock); + if (!NT_SUCCESS(Status)) + { + return Status; + } + MmLockAddressSpace(&Process->AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(&Process->AddressSpace, Address); + Type = MemoryArea->Type; + if (Type == MEMORY_AREA_SECTION_VIEW) + { + Offset.QuadPart = (ULONG)((Address - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset); + + /* + * Get or create a pageop + */ + PageOp = MmGetPageOp(MemoryArea, 0, 0, + MemoryArea->Data.SectionData.Segment, + Offset.u.LowPart, MM_PAGEOP_PAGEOUT); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed\n"); + KeBugCheck(0); + } + + if (PageOp->Thread != PsGetCurrentThread()) + { + MmReleasePageOp(PageOp); + MmUnlockAddressSpace(&Process->AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Release locks now we have a page op. + */ + MmUnlockAddressSpace(&Process->AddressSpace); + + /* + * Do the actual page out work. + */ + Status = MmPageOutSectionView(&Process->AddressSpace, MemoryArea, + Address, PageOp); + } + else if (Type == MEMORY_AREA_VIRTUAL_MEMORY) + { + PageOp = MmGetPageOp(MemoryArea, Process->UniqueProcessId, + Address, NULL, 0, MM_PAGEOP_PAGEOUT); + if (PageOp->Thread != PsGetCurrentThread()) + { + MmReleasePageOp(PageOp); + MmUnlockAddressSpace(&Process->AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Release locks now we have a page op. + */ + MmUnlockAddressSpace(&Process->AddressSpace); + + /* + * Do the actual page out work. + */ + Status = MmPageOutVirtualMemory(&Process->AddressSpace, MemoryArea, + Address, PageOp); + } + else + { + KeBugCheck(0); + } + ObDereferenceObject(Process); + return(Status); +} + +VOID +MmSetCleanAllRmaps(PHYSICAL_ADDRESS PhysicalAddress) +{ + PMM_RMAP_ENTRY current_entry; + + ExAcquireFastMutex(&RmapListLock); + current_entry = MmGetRmapListHeadPage(PhysicalAddress); + if (current_entry == NULL) + { + DPRINT1("MmIsDirtyRmap: No rmaps.\n"); + KeBugCheck(0); + } + while (current_entry != NULL) + { + MmSetCleanPage(current_entry->Process, current_entry->Address); + current_entry = current_entry->Next; + } + ExReleaseFastMutex(&RmapListLock); +} + +VOID +MmSetDirtyAllRmaps(PHYSICAL_ADDRESS PhysicalAddress) +{ + PMM_RMAP_ENTRY current_entry; + + ExAcquireFastMutex(&RmapListLock); + current_entry = MmGetRmapListHeadPage(PhysicalAddress); + if (current_entry == NULL) + { + DPRINT1("MmIsDirtyRmap: No rmaps.\n"); + KeBugCheck(0); + } + while (current_entry != NULL) + { + MmSetDirtyPage(current_entry->Process, current_entry->Address); + current_entry = current_entry->Next; + } + ExReleaseFastMutex(&RmapListLock); +} + +BOOL +MmIsDirtyPageRmap(PHYSICAL_ADDRESS PhysicalAddress) +{ + PMM_RMAP_ENTRY current_entry; + + ExAcquireFastMutex(&RmapListLock); + current_entry = MmGetRmapListHeadPage(PhysicalAddress); + if (current_entry == NULL) + { + ExReleaseFastMutex(&RmapListLock); + return(FALSE); + } + while (current_entry != NULL) + { + if (MmIsDirtyPage(current_entry->Process, current_entry->Address)) + { + ExReleaseFastMutex(&RmapListLock); + return(TRUE); + } + current_entry = current_entry->Next; + } + ExReleaseFastMutex(&RmapListLock); + return(FALSE); +} + +VOID +MmInsertRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process, + PVOID Address) +{ + PMM_RMAP_ENTRY current_entry; + PMM_RMAP_ENTRY new_entry; + + Address = (PVOID)PAGE_ROUND_DOWN(Address); + + new_entry = ExAllocatePool(NonPagedPool, sizeof(MM_RMAP_ENTRY)); + if (new_entry == NULL) + { + KeBugCheck(0); + } + new_entry->Address = Address; + new_entry->Process = Process; + + if (MmGetPhysicalAddressForProcess(Process, Address).QuadPart != + PhysicalAddress.QuadPart) + { + DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical " + "address 0x%.8X\n", Process->UniqueProcessId, Address, + MmGetPhysicalAddressForProcess(Process, Address), + PhysicalAddress) + KeBugCheck(0); + } + + ExAcquireFastMutex(&RmapListLock); + current_entry = MmGetRmapListHeadPage(PhysicalAddress); + new_entry->Next = current_entry; + MmSetRmapListHeadPage(PhysicalAddress, new_entry); + ExReleaseFastMutex(&RmapListLock); +} + +VOID +MmDeleteAllRmaps(PHYSICAL_ADDRESS PhysicalAddress, PVOID Context, + VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process, + PVOID Address)) +{ + PMM_RMAP_ENTRY current_entry; + PMM_RMAP_ENTRY previous_entry; + + ExAcquireFastMutex(&RmapListLock); + current_entry = MmGetRmapListHeadPage(PhysicalAddress); + if (current_entry == NULL) + { + DPRINT1("MmDeleteAllRmaps: No rmaps.\n"); + KeBugCheck(0); + } + while (current_entry != NULL) + { + previous_entry = current_entry; + current_entry = current_entry->Next; + if (DeleteMapping) + { + DeleteMapping(Context, previous_entry->Process, + previous_entry->Address); + } + ExFreePool(previous_entry); + } + MmSetRmapListHeadPage(PhysicalAddress, NULL); + ExReleaseFastMutex(&RmapListLock); +} + +VOID +MmDeleteRmap(PHYSICAL_ADDRESS PhysicalAddress, PEPROCESS Process, + PVOID Address) +{ + PMM_RMAP_ENTRY current_entry, previous_entry; + + ExAcquireFastMutex(&RmapListLock); + previous_entry = NULL; + current_entry = MmGetRmapListHeadPage(PhysicalAddress); + while (current_entry != NULL) + { + if (current_entry->Process == Process && + current_entry->Address == Address) + { + if (previous_entry == NULL) + { + MmSetRmapListHeadPage(PhysicalAddress, current_entry->Next); + ExReleaseFastMutex(&RmapListLock); + ExFreePool(current_entry); + } + else + { + previous_entry->Next = current_entry->Next; + ExReleaseFastMutex(&RmapListLock); + ExFreePool(current_entry); + } + return; + } + previous_entry = current_entry; + current_entry = current_entry->Next; + } + KeBugCheck(0); +} diff --git a/ntoskrnl/mm/section.c b/ntoskrnl/mm/section.c new file mode 100644 index 0000000..d4b5f53 --- /dev/null +++ b/ntoskrnl/mm/section.c @@ -0,0 +1,3547 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/section.c + * PURPOSE: Implements section objects + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *********************************************************************/ + +typedef struct +{ + PSECTION_OBJECT Section; + PMM_SECTION_SEGMENT Segment; + LARGE_INTEGER Offset; + BOOLEAN WasDirty; + BOOLEAN Private; +} MM_SECTION_PAGEOUT_CONTEXT; + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE EXPORTED MmSectionObjectType = NULL; + +static GENERIC_MAPPING MmpSectionMapping = { + STANDARD_RIGHTS_READ | SECTION_MAP_READ | SECTION_QUERY, + STANDARD_RIGHTS_WRITE | SECTION_MAP_WRITE, + STANDARD_RIGHTS_EXECUTE | SECTION_MAP_EXECUTE, + SECTION_ALL_ACCESS}; + +#define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S') +#define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T') + +#define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000) +#define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFE) >> 1) +#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001) +#define MAX_SHARE_COUNT 0x7FF +#define MAKE_SSE(P, C) ((P) | ((C) << 1)) +#define SWAPENTRY_FROM_SSE(E) ((E) >> 1) +#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1) + +/* FUNCTIONS *****************************************************************/ + +VOID +MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment) +{ + ULONG i; + + for (i = 0; i < NR_SECTION_PAGE_TABLES; i++) + { + if (Segment->PageDirectory.PageTables[i] != NULL) + { + ExFreePool(Segment->PageDirectory.PageTables[i]); + } + } +} + +VOID +MmFreeSectionSegments(PFILE_OBJECT FileObject) +{ + if (FileObject->SectionObjectPointers->ImageSectionObject != NULL) + { + PMM_IMAGE_SECTION_OBJECT ImageSectionObject; + + ULONG i; + + ImageSectionObject = + (PMM_IMAGE_SECTION_OBJECT)FileObject->SectionObjectPointers-> + ImageSectionObject; + + for (i = 0; i < ImageSectionObject->NrSegments; i++) + { + if (ImageSectionObject->Segments[i].ReferenceCount != 0) + { + DPRINT1("Image segment %d still referenced (was %d)\n", i, + ImageSectionObject->Segments[i].ReferenceCount); + KeBugCheck(0); + } + MmFreePageTablesSectionSegment(&ImageSectionObject->Segments[i]); + } + ExFreePool(ImageSectionObject); + FileObject->SectionObjectPointers->ImageSectionObject = NULL; + } + if (FileObject->SectionObjectPointers->DataSectionObject != NULL) + { + PMM_SECTION_SEGMENT Segment; + + Segment = (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers-> + DataSectionObject; + + if (Segment->ReferenceCount != 0) + { + DPRINT1("Data segment still referenced\n"); + KeBugCheck(0); + } + MmFreePageTablesSectionSegment(Segment); + ExFreePool(Segment); + FileObject->SectionObjectPointers->DataSectionObject = NULL; + } +} + +VOID +MmLockSection(PSECTION_OBJECT Section) +{ + KeWaitForSingleObject(&Section->Lock, + UserRequest, + KernelMode, + FALSE, + NULL); +} + +VOID +MmUnlockSection(PSECTION_OBJECT Section) +{ + KeReleaseMutex(&Section->Lock, FALSE); +} + +VOID +MmLockSectionSegment(PMM_SECTION_SEGMENT Segment) +{ + KeWaitForSingleObject(&Segment->Lock, + UserRequest, + KernelMode, + FALSE, + NULL); +} + +VOID +MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment) +{ + KeReleaseMutex(&Segment->Lock, FALSE); +} + +VOID +MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, + ULONG Offset, + ULONG Entry) +{ + PSECTION_PAGE_TABLE Table; + ULONG DirectoryOffset; + ULONG TableOffset; + + DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset); + Table = Segment->PageDirectory.PageTables[DirectoryOffset]; + if (Table == NULL) + { + Table = + Segment->PageDirectory.PageTables[DirectoryOffset] = + ExAllocatePoolWithTag(NonPagedPool, sizeof(SECTION_PAGE_TABLE), + TAG_SECTION_PAGE_TABLE); + memset(Table, 0, sizeof(SECTION_PAGE_TABLE)); + DPRINT("Table %x\n", Table); + } + TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset); + Table->Entry[TableOffset] = Entry; +} + + +ULONG +MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, + ULONG Offset) +{ + PSECTION_PAGE_TABLE Table; + ULONG Entry; + ULONG DirectoryOffset; + ULONG TableOffset; + + DPRINT("MmGetPageEntrySection(Offset %x)\n", Offset); + + DirectoryOffset = PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(Offset); + Table = Segment->PageDirectory.PageTables[DirectoryOffset]; + DPRINT("Table %x\n", Table); + if (Table == NULL) + { + return(0); + } + TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset); + Entry = Table->Entry[TableOffset]; + return(Entry); +} + +VOID +MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment, + ULONG Offset) +{ + ULONG Entry; + + Entry = MmGetPageEntrySectionSegment(Segment, Offset); + if (Entry == 0) + { + DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n"); + KeBugCheck(0); + } + if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT) + { + DPRINT1("Maximum share count reached\n"); + KeBugCheck(0); + } + if (IS_SWAP_FROM_SSE(Entry)) + { + KeBugCheck(0); + } + Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1); + MmSetPageEntrySectionSegment(Segment, Offset, Entry); +} + +BOOLEAN +MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section, + PMM_SECTION_SEGMENT Segment, + ULONG Offset, + BOOLEAN Dirty) +{ + ULONG Entry; + + Entry = MmGetPageEntrySectionSegment(Segment, Offset); + if (Entry == 0) + { + DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n"); + KeBugCheck(0); + } + if (SHARE_COUNT_FROM_SSE(Entry) == 0) + { + DPRINT1("Zero share count for unshare\n"); + KeBugCheck(0); + } + if (IS_SWAP_FROM_SSE(Entry)) + { + KeBugCheck(0); + } + Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1); + /* + * If we reducing the share count of this entry to zero then set the entry + * to zero and tell the cache the page is no longer mapped. + */ + if (SHARE_COUNT_FROM_SSE(Entry) == 0) + { + PFILE_OBJECT FileObject; + PREACTOS_COMMON_FCB_HEADER Fcb; + SWAPENTRY SavedSwapEntry; + PHYSICAL_ADDRESS Page; + + MmSetPageEntrySectionSegment(Segment, Offset, 0); + FileObject = Section->FileObject; + if (FileObject != NULL) + { + Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext; + + if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ && + (Offset % PAGE_SIZE) == 0) + { + NTSTATUS Status; + Status = CcRosUnmapCacheSegment(Fcb->Bcb, Offset, Dirty); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + } + + Page = (PHYSICAL_ADDRESS)(LONGLONG)PAGE_FROM_SSE(Entry); + SavedSwapEntry = MmGetSavedSwapEntryPage(Page); + if (SavedSwapEntry != 0) + { + MmFreeSwapPage(SavedSwapEntry); + MmSetSavedSwapEntryPage(Page, 0); + } + } + else + { + MmSetPageEntrySectionSegment(Segment, Offset, Entry); + } + return(SHARE_COUNT_FROM_SSE(Entry) > 1); +} + +NTSTATUS +MiReadPage(PMEMORY_AREA MemoryArea, + PLARGE_INTEGER Offset, + PHYSICAL_ADDRESS* Page) + /* + * FUNCTION: Read a page for a section backed memory area. + * PARAMETERS: + * MemoryArea - Memory area to read the page for. + * Offset - Offset of the page to read. + * Page - Variable that receives a page contains the read data. + */ +{ + IO_STATUS_BLOCK IoStatus; + PFILE_OBJECT FileObject; + PMDL Mdl; + NTSTATUS Status; + PREACTOS_COMMON_FCB_HEADER Fcb; + KEVENT Event; + + FileObject = MemoryArea->Data.SectionData.Section->FileObject; + Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext; + + /* + * If the file system is letting us go directly to the cache and the + * memory area was mapped at an offset in the file which is page aligned + * then get the related cache segment. + */ + if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ && + (Offset->QuadPart % PAGE_SIZE) == 0) + { + ULONG BaseOffset; + PVOID BaseAddress; + BOOLEAN UptoDate; + PCACHE_SEGMENT CacheSeg; + PHYSICAL_ADDRESS Addr; + + /* + * Get the related cache segment; we use a lower level interface than + * filesystems do because it is safe for us to use an offset with a + * alignment less than the file system block size. + */ + Status = CcRosGetCacheSegment(Fcb->Bcb, + (ULONG)Offset->QuadPart, + &BaseOffset, + &BaseAddress, + &UptoDate, + &CacheSeg); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (!UptoDate) + { + /* + * If the cache segment isn't up to date then call the file + * system to read in the data. + */ + Status = ReadCacheSegment(CacheSeg); + if (!NT_SUCCESS(Status)) + { + return Status; + } + } + /* + * Retrieve the page from the cache segment that we actually want. + */ + Addr = MmGetPhysicalAddress(BaseAddress + + Offset->QuadPart - BaseOffset); + (*Page) = Addr; + MmReferencePage((*Page)); + + CcRosReleaseCacheSegment(Fcb->Bcb, CacheSeg, TRUE, FALSE, TRUE); + return(STATUS_SUCCESS); + } + else + { + /* + * Allocate a page, this is rather complicated by the possibility + * we might have to move other things out of memory + */ + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, Page); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Create an mdl to hold the page we are going to read data into. + */ + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, &Page->u.LowPart); + /* + * Call the FSD to read the page + */ + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + Status = IoPageRead(FileObject, + Mdl, + Offset, + &Event, + &IoStatus); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); + return(IoStatus.Status); + } + return(Status); + } +} + +NTSTATUS +MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked) +{ + LARGE_INTEGER Offset; + LARGE_INTEGER Page; + NTSTATUS Status; + ULONG PAddress; + PSECTION_OBJECT Section; + PMM_SECTION_SEGMENT Segment; + ULONG Entry; + ULONG Entry1; + ULONG Attributes; + PMM_PAGEOP PageOp; + PMM_REGION Region; + + /* + * There is a window between taking the page fault and locking the + * address space when another thread could load the page so we check + * that. + */ + if (MmIsPagePresent(NULL, Address)) + { + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + return(STATUS_SUCCESS); + } + + PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address)); + Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset; + + /* + * Lock the segment + */ + Segment = MemoryArea->Data.SectionData.Segment; + Section = MemoryArea->Data.SectionData.Section; + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.SectionData.RegionListHead, + Address, NULL); + MmLockSection(Section); + MmLockSectionSegment(Segment); + + /* + * Check if this page needs to be mapped COW + */ + if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) && + (Region->Protect == PAGE_READWRITE || + Region->Protect == PAGE_EXECUTE_READWRITE)) + { + Attributes = PAGE_READONLY; + } + else + { + Attributes = Region->Protect; + } + + /* + * Get or create a page operation descriptor + */ + PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart, + MM_PAGEOP_PAGEIN); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed\n"); + KeBugCheck(0); + } + + /* + * Check if someone else is already handling this fault, if so wait + * for them + */ + if (PageOp->Thread != PsGetCurrentThread()) + { + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + Status = KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + /* + * Check for various strange conditions + */ + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op\n"); + KeBugCheck(0); + } + if (PageOp->Status == STATUS_PENDING) + { + DPRINT1("Woke for page op before completion\n"); + KeBugCheck(0); + } + /* + * If this wasn't a pagein then restart the operation + */ + if (PageOp->OpType != MM_PAGEOP_PAGEIN) + { + MmLockAddressSpace(AddressSpace); + MmReleasePageOp(PageOp); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_MM_RESTART_OPERATION); + } + /* + * If the thread handling this fault has failed then we don't retry + */ + if (!NT_SUCCESS(PageOp->Status)) + { + MmLockAddressSpace(AddressSpace); + DPRINT("Address 0x%.8X\n", Address); + return(PageOp->Status); + } + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + MmLockSectionSegment(Segment); + /* + * If the completed fault was for another address space then set the + * page in this one. + */ + if (!MmIsPagePresent(NULL, Address)) + { + Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart); + if (Entry == 0) + { + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmReleasePageOp(PageOp); + return(STATUS_MM_RESTART_OPERATION); + } + + Page = (LARGE_INTEGER)(LONGLONG)(PAGE_FROM_SSE(Entry)); + MmReferencePage(Page); + MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart); + + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Attributes, + Page, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + MmInsertRmap(Page, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + } + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmReleasePageOp(PageOp); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_SUCCESS); + } + + /* + * Must be private page we have swapped out. + */ + if (MmIsPageSwapEntry(NULL, (PVOID)PAddress)) + { + SWAPENTRY SwapEntry; + PMDL Mdl; + + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + + MmDeletePageFileMapping(NULL, (PVOID)PAddress, &SwapEntry); + + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&Page); + Status = MmReadFromSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Region->Protect, + Page, + FALSE); + while (Status == STATUS_NO_MEMORY) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Region->Protect, + Page, + TRUE); + MmLockAddressSpace(AddressSpace); + } + if (!NT_SUCCESS(Status)) + { + DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); + KeBugCheck(0); + return(Status); + } + + /* + * Store the swap entry for later use. + */ + MmSetSavedSwapEntryPage(Page, SwapEntry); + + /* + * Add the page to the process's working set + */ + MmInsertRmap(Page, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + + /* + * Finish the operation + */ + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_SUCCESS); + } + + /* + * Satisfying a page fault on a map of /Device/PhysicalMemory is easy + */ + if (Section->AllocationAttributes & SEC_PHYSICALMEMORY) + { + /* + * Just map the desired physical page + */ + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Region->Protect, + Offset, + FALSE); + /* + * Don't add an rmap entry since the page mapped could be for + * anything. + */ + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + + /* + * Cleanup and release locks + */ + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_SUCCESS); + } + + /* + * Map anonymous memory for BSS sections + */ + if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) + { + Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); + if (!NT_SUCCESS(Status)) + { + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + MmLockSectionSegment(Segment); + } + + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Region->Protect, + Page, + FALSE); + MmInsertRmap(Page, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + + /* + * Cleanup and release locks + */ + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_SUCCESS); + } + + /* + * Get the entry corresponding to the offset within the section + */ + Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart); + + if (Entry == 0) + { + /* + * If the entry is zero (and it can't change because we have + * locked the segment) then we need to load the page. + */ + + /* + * Release all our locks and read in the page from disk + */ + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + + if (Segment->Flags & MM_PAGEFILE_SEGMENT) + { + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + } + else + { + Status = MiReadPage(MemoryArea, &Offset, &Page); + } + if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE) + { + /* + * FIXME: What do we know in this case? + */ + DPRINT1("IoPageRead failed (Status %x)\n", Status); + + /* + * Cleanup and release locks + */ + PageOp->Status = Status; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + MmLockAddressSpace(AddressSpace); + return(Status); + } + + /* + * Relock the address space, section and segment + */ + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + MmLockSectionSegment(Segment); + + /* + * Check the entry. No one should change the status of a page + * that has a pending page-in. + */ + Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart); + if (Entry != Entry1) + { + DbgPrint("Someone changed ppte entry while we slept\n"); + KeBugCheck(0); + } + + /* + * Mark the offset within the section as having valid, in-memory + * data + */ + Entry = Page.u.LowPart; + MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry); + MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); + + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Attributes, + Page, + FALSE); + if (!NT_SUCCESS(Status)) + { + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Attributes, + Page, + TRUE); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + MmLockSectionSegment(Segment); + } + MmInsertRmap(Page, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + DPRINT("MmNotPresentFaultSectionView succeeded\n"); + return(STATUS_SUCCESS); + } + else if (IS_SWAP_FROM_SSE(Entry)) + { + SWAPENTRY SwapEntry; + PMDL Mdl; + + SwapEntry = SWAPENTRY_FROM_SSE(Entry); + + /* + * Release all our locks and read in the page from disk + */ + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&Page); + Status = MmReadFromSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + + /* + * Relock the address space, section and segment + */ + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + MmLockSectionSegment(Segment); + + /* + * Check the entry. No one should change the status of a page + * that has a pending page-in. + */ + Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart); + if (Entry != Entry1) + { + DbgPrint("Someone changed ppte entry while we slept\n"); + KeBugCheck(0); + } + + /* + * Mark the offset within the section as having valid, in-memory + * data + */ + Entry = Page.u.LowPart; + MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry); + MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); + + /* + * Save the swap entry. + */ + MmSetSavedSwapEntryPage(Page, SwapEntry); + + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Attributes, + Page, + FALSE); + MmInsertRmap(Page, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + DPRINT("MmNotPresentFaultSectionView succeeded\n"); + return(STATUS_SUCCESS); + } + else + { + /* + * If the section offset is already in-memory and valid then just + * take another reference to the page + */ + + Page = (LARGE_INTEGER)(LONGLONG)PAGE_FROM_SSE(Entry); + MmReferencePage(Page); + MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); + + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Attributes, + Page, + FALSE); + MmInsertRmap(Page, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + return(STATUS_SUCCESS); + } +} + +NTSTATUS +MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + BOOLEAN Locked) +{ + PMM_SECTION_SEGMENT Segment; + PSECTION_OBJECT Section; + PHYSICAL_ADDRESS OldPage; + PHYSICAL_ADDRESS NewPage; + PVOID NewAddress; + NTSTATUS Status; + ULONG PAddress; + LARGE_INTEGER Offset; + PMM_PAGEOP PageOp; + PMM_REGION Region; + + /* + * Check if the page has been paged out or has already been set readwrite + */ + if (!MmIsPagePresent(NULL, Address) || + MmGetPageProtect(NULL, Address) & PAGE_READWRITE) + { + return(STATUS_SUCCESS); + } + + /* + * Find the offset of the page + */ + PAddress = (ULONG)PAGE_ROUND_DOWN(((ULONG)Address)); + Offset.QuadPart = (PAddress - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset; + + /* + * Lock the segment + */ + Segment = MemoryArea->Data.SectionData.Segment; + Section = MemoryArea->Data.SectionData.Section; + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.SectionData.RegionListHead, + Address, NULL); + MmLockSection(Section); + MmLockSectionSegment(Segment); + + /* + * Sanity check. + */ + if (MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) == 0) + { + DPRINT1("COW fault for page with PESS 0. Address was 0x%.8X\n", + Address); + } + + /* + * Check if we are doing COW + */ + if (!((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) && + (Region->Protect == PAGE_READWRITE || + Region->Protect == PAGE_EXECUTE_READWRITE))) + { + MmUnlockSection(Section); + MmUnlockSectionSegment(Segment); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Get or create a pageop + */ + PageOp = MmGetPageOp(MemoryArea, 0, 0, Segment, Offset.u.LowPart, + MM_PAGEOP_ACCESSFAULT); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed\n"); + KeBugCheck(0); + } + + /* + * Wait for any other operations to complete + */ + if (PageOp->Thread != PsGetCurrentThread()) + { + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + Status = KeWaitForSingleObject(&PageOp->CompletionEvent, + 0, + KernelMode, + FALSE, + NULL); + /* + * Check for various strange conditions + */ + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op\n"); + KeBugCheck(0); + } + if (PageOp->Status == STATUS_PENDING) + { + DPRINT1("Woke for page op before completion\n"); + KeBugCheck(0); + } + /* + * Restart the operation + */ + MmLockAddressSpace(AddressSpace); + MmReleasePageOp(PageOp); + return(STATUS_MM_RESTART_OPERATION); + } + + /* + * Release locks now we have the pageop + */ + MmUnlockSectionSegment(Segment); + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + + /* + * Allocate a page + */ + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage); + + /* + * Copy the old page + */ + OldPage = MmGetPhysicalAddressForProcess(NULL, Address); + + NewAddress = ExAllocatePageWithPhysPage(NewPage); + memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGE_SIZE); + ExUnmapPage(NewAddress); + + /* + * Delete the old entry. + */ + MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE, NULL, NULL); + + /* + * Set the PTE to point to the new page + */ + MmLockAddressSpace(AddressSpace); + Status = MmCreateVirtualMapping(PsGetCurrentProcess(), + Address, + Region->Protect, + NewPage, + FALSE); + MmInsertRmap(NewPage, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + if (Locked) + { + MmLockPage(MmGetPhysicalAddressForProcess(NULL, Address)); + } + + /* + * Unshare the old page. + */ + MmUnsharePageEntrySectionSegment(Section, Segment, Offset.QuadPart, FALSE); + MmDeleteRmap(OldPage, PsGetCurrentProcess(), + (PVOID)PAGE_ROUND_DOWN(Address)); + MmReleasePageMemoryConsumer(MC_USER, OldPage); + + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); +} + +VOID +MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address) +{ + MM_SECTION_PAGEOUT_CONTEXT* PageOutContext; + BOOL WasDirty; + PHYSICAL_ADDRESS PhysicalAddress; + + PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context; + MmDeleteVirtualMapping(Process, + Address, + FALSE, + &WasDirty, + &PhysicalAddress); + if (WasDirty) + { + PageOutContext->WasDirty = TRUE; + } + if (!PageOutContext->Private) + { + MmUnsharePageEntrySectionSegment(PageOutContext->Section, + PageOutContext->Segment, + PageOutContext->Offset.u.LowPart, + PageOutContext->WasDirty); + } + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); +} + +NTSTATUS +MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, + MEMORY_AREA* MemoryArea, + PVOID Address, + PMM_PAGEOP PageOp) +{ + LARGE_INTEGER Offset; + PSECTION_OBJECT Section; + PMM_SECTION_SEGMENT Segment; + PHYSICAL_ADDRESS PhysicalAddress; + MM_SECTION_PAGEOUT_CONTEXT Context; + SWAPENTRY SwapEntry; + PMDL Mdl; + ULONG Entry; + BOOLEAN Private; + NTSTATUS Status; + PFILE_OBJECT FileObject; + PREACTOS_COMMON_FCB_HEADER Fcb; + BOOLEAN DirectMapped; + + Address = (PVOID)PAGE_ROUND_DOWN(Address); + + Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset; + + FileObject = MemoryArea->Data.SectionData.Section->FileObject; + DirectMapped = FALSE; + if (FileObject != NULL) + { + Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext; + + /* + * If the file system is letting us go directly to the cache and the + * memory area was mapped at an offset in the file which is page aligned + * then note this is a direct mapped page. + */ + if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ && + (Offset.QuadPart % PAGE_SIZE) == 0) + { + DirectMapped = TRUE; + } + } + + /* + * Get the segment and section. + */ + Segment = MemoryArea->Data.SectionData.Segment; + Section = MemoryArea->Data.SectionData.Section; + + /* + * This should never happen since mappings of physical memory are never + * placed in the rmap lists. + */ + if (Section->AllocationAttributes & SEC_PHYSICALMEMORY) + { + DPRINT1("Trying to page out from physical memory section address 0x%X " + "process %d\n", Address, AddressSpace->Process->UniqueProcessId); + KeBugCheck(0); + } + + /* + * Get the section segment entry and the physical address. + */ + Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart); + if (!MmIsPagePresent(AddressSpace->Process, Address)) + { + DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n", + AddressSpace->Process->UniqueProcessId, Address); + KeBugCheck(0); + } + PhysicalAddress = + MmGetPhysicalAddressForProcess(AddressSpace->Process, Address); + SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress); + + /* + * Prepare the context structure for the rmap delete call. + */ + Context.Section = Section; + Context.Segment = Segment; + Context.Offset = Offset; + Context.WasDirty = FALSE; + if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS || + IS_SWAP_FROM_SSE(Entry) || + (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart) + { + Context.Private = Private = TRUE; + } + else + { + Context.Private = Private = FALSE; + } + + /* + * Take an additional reference to the page. + */ + MmReferencePage(PhysicalAddress); + + /* + * Paging out data mapped read-only is easy. + */ + if (MemoryArea->Attributes & PAGE_READONLY || + MemoryArea->Attributes & PAGE_EXECUTE_READ) + { + /* + * Read-only data should never be in the swapfile. + */ + if (SwapEntry != 0) + { + DPRINT1("SwapEntry != 0 was 0x%.8X at address 0x%.8X, " + "paddress 0x%.8X\n", SwapEntry, Address, + PhysicalAddress); + KeBugCheck(0); + } + + /* + * Read-only data should never be COWed + */ + if (Private) + { + DPRINT1("Had private copy of read-only page.\n"); + KeBugCheck(0); + } + + /* + * Delete all mappings of this page. + */ + MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, + MmPageOutDeleteMapping); + if (Context.WasDirty) + { + KeBugCheck(0); + } + /* + * If this page wasn't direct mapped then we have a private copy so + * release back to the system; otherwise the cache manager will have + * handled freeing the cache segment which we mapped from. + */ + if (!DirectMapped) + { + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); + } + + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * Otherwise we have read-write data. + */ + MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context, MmPageOutDeleteMapping); + + /* + * If this wasn't a private page then we should have reduced the entry to + * zero by deleting all the rmaps. + */ + if (!Private && MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) != 0) + { + KeBugCheck(0); + } + + /* + * If the page wasn't dirty then we can just free it as for a readonly page. + * Since we unmapped all the mappings above we know it will not suddenly + * become dirty. + */ + if (!Context.WasDirty) + { + if (!DirectMapped || Private) + { + MmSetSavedSwapEntryPage(PhysicalAddress, 0); + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); + } + if (Private) + { + if (!(Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) && + SwapEntry == 0) + { + DPRINT1("Private page, non-dirty but not swapped out " + "process %d address 0x%.8X\n", + AddressSpace->Process->UniqueProcessId, + Address); + KeBugCheck(0); + } + else + { + Status = MmCreatePageFileMapping(AddressSpace->Process, + Address, + SwapEntry); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + } + + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * If this page was direct mapped from the cache then the cache manager + * will already have taken care of writing it back. + */ + if (DirectMapped && !Private) + { + assert(SwapEntry == 0); + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * If necessary, allocate an entry in the paging file for this page + */ + SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress); + if (SwapEntry == 0) + { + SwapEntry = MmAllocSwapPage(); + if (SwapEntry == 0) + { + MmShowOutOfSpaceMessagePagingFile(); + + /* + * For private pages restore the old mappings. + */ + if (Private) + { + Status = MmCreateVirtualMapping(MemoryArea->Process, + Address, + MemoryArea->Attributes, + PhysicalAddress, + FALSE); + MmSetDirtyPage(MemoryArea->Process, Address); + MmInsertRmap(PhysicalAddress, + MemoryArea->Process, + Address); + } + else + { + /* + * For non-private pages if the page wasn't direct mapped then + * set it back into the section segment entry so we don't loose + * our copy. Otherwise it will be handled by the cache manager. + */ + Status = MmCreateVirtualMapping(MemoryArea->Process, + Address, + MemoryArea->Attributes, + PhysicalAddress, + FALSE); + MmSetDirtyPage(MemoryArea->Process, Address); + MmInsertRmap(PhysicalAddress, + MemoryArea->Process, + Address); + MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, + PhysicalAddress.u.LowPart); + MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); + } + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + } + + /* + * Write the page to the pagefile + */ + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress); + Status = MmWriteToSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", + Status); + /* + * As above: undo our actions. + * FIXME: Also free the swap page. + */ + if (Private) + { + Status = MmCreateVirtualMapping(MemoryArea->Process, + Address, + MemoryArea->Attributes, + PhysicalAddress, + FALSE); + MmSetDirtyPage(MemoryArea->Process, Address); + MmInsertRmap(PhysicalAddress, + MemoryArea->Process, + Address); + } + else + { + Status = MmCreateVirtualMapping(MemoryArea->Process, + Address, + MemoryArea->Attributes, + PhysicalAddress, + FALSE); + MmSetDirtyPage(MemoryArea->Process, Address); + MmInsertRmap(PhysicalAddress, + MemoryArea->Process, + Address); + MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, + PhysicalAddress.u.LowPart); + MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); + } + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Otherwise we have succeeded. + */ + DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress); + MmSetSavedSwapEntryPage(PhysicalAddress, 0); + MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); + + if (Private) + { + Status = MmCreatePageFileMapping(MemoryArea->Process, + Address, + SwapEntry); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + else + { + Entry = MAKE_SWAP_SSE(SwapEntry); + MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry); + } + + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); +} + +NTSTATUS +MmWritePageSectionView(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + PMM_PAGEOP PageOp) +{ + LARGE_INTEGER Offset; + PSECTION_OBJECT Section; + PMM_SECTION_SEGMENT Segment; + PHYSICAL_ADDRESS PhysicalAddress; + SWAPENTRY SwapEntry; + PMDL Mdl; + ULONG Entry; + BOOLEAN Private; + NTSTATUS Status; + PFILE_OBJECT FileObject; + PREACTOS_COMMON_FCB_HEADER Fcb = NULL; + BOOLEAN DirectMapped; + + Address = (PVOID)PAGE_ROUND_DOWN(Address); + + Offset.QuadPart = (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset; + + FileObject = MemoryArea->Data.SectionData.Section->FileObject; + DirectMapped = FALSE; + if (FileObject != NULL) + { + Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext; + + /* + * If the file system is letting us go directly to the cache and the + * memory area was mapped at an offset in the file which is page aligned + * then note this is a direct mapped page. + */ + if (FileObject->Flags & FO_DIRECT_CACHE_PAGING_READ && + (Offset.QuadPart % PAGE_SIZE) == 0) + { + DirectMapped = TRUE; + } + } + + /* + * Get the segment and section. + */ + Segment = MemoryArea->Data.SectionData.Segment; + Section = MemoryArea->Data.SectionData.Section; + + /* + * This should never happen since mappings of physical memory are never + * placed in the rmap lists. + */ + if (Section->AllocationAttributes & SEC_PHYSICALMEMORY) + { + DPRINT1("Trying to write back page from physical memory mapped at %X " + "process %d\n", Address, AddressSpace->Process->UniqueProcessId); + KeBugCheck(0); + } + + /* + * Get the section segment entry and the physical address. + */ + Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart); + if (!MmIsPagePresent(AddressSpace->Process, Address)) + { + DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n", + AddressSpace->Process->UniqueProcessId, Address); + KeBugCheck(0); + } + PhysicalAddress = + MmGetPhysicalAddressForProcess(AddressSpace->Process, Address); + SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress); + + /* + * Check for a private (COWed) page. + */ + if (Segment->Characteristics & IMAGE_SECTION_CHAR_BSS || + IS_SWAP_FROM_SSE(Entry) || + (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart) + { + Private = TRUE; + } + else + { + Private = FALSE; + } + + /* + * Speculatively set all mappings of the page to clean. + */ + MmSetCleanAllRmaps(PhysicalAddress); + + /* + * If this page was direct mapped from the cache then the cache manager + * will take care of writing it back to disk. + */ + if (DirectMapped && !Private) + { + assert(SwapEntry == 0); + CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset.u.LowPart); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); + } + + /* + * If necessary, allocate an entry in the paging file for this page + */ + SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress); + if (SwapEntry == 0) + { + SwapEntry = MmAllocSwapPage(); + if (SwapEntry == 0) + { + MmSetDirtyAllRmaps(PhysicalAddress); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + } + + /* + * Write the page to the pagefile + */ + Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE); + MmBuildMdlFromPages(Mdl, (PULONG)&PhysicalAddress); + Status = MmWriteToSwapPage(SwapEntry, Mdl); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", + Status); + MmSetDirtyAllRmaps(PhysicalAddress); + PageOp->Status = STATUS_UNSUCCESSFUL; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Otherwise we have succeeded. + */ + DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress); + MmSetSavedSwapEntryPage(PhysicalAddress, SwapEntry); + PageOp->Status = STATUS_SUCCESS; + KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); + MmReleasePageOp(PageOp); + return(STATUS_SUCCESS); +} + +VOID STATIC +MmAlterViewAttributes(PMADDRESS_SPACE AddressSpace, + PVOID BaseAddress, + ULONG RegionSize, + ULONG OldType, + ULONG OldProtect, + ULONG NewType, + ULONG NewProtect) +{ + PMEMORY_AREA MemoryArea; + PMM_SECTION_SEGMENT Segment; + BOOL DoCOW = FALSE; + ULONG i; + + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, BaseAddress); + Segment = MemoryArea->Data.SectionData.Segment; + + if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) && + (NewProtect == PAGE_READWRITE || NewProtect == PAGE_EXECUTE_READWRITE)) + { + DoCOW = TRUE; + } + + if (OldProtect != NewProtect) + { + for (i = 0; i < (RegionSize / PAGE_SIZE); i++) + { + PVOID Address = BaseAddress + (i * PAGE_SIZE); + ULONG Protect = NewProtect; + + /* + * If we doing COW for this segment then check if the page is + * already private. + */ + if (DoCOW && MmIsPagePresent(AddressSpace->Process, Address)) + { + LARGE_INTEGER Offset; + ULONG Entry; + LARGE_INTEGER PhysicalAddress; + + Offset.QuadPart = + (ULONG)(Address - (ULONG)MemoryArea->BaseAddress) + + MemoryArea->Data.SectionData.ViewOffset; + Entry = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart); + PhysicalAddress = + MmGetPhysicalAddressForProcess(AddressSpace->Process, Address); + + Protect = PAGE_READONLY; + if ((Segment->Characteristics & IMAGE_SECTION_CHAR_BSS || + IS_SWAP_FROM_SSE(Entry) || + (LONGLONG)PAGE_FROM_SSE(Entry) != PhysicalAddress.QuadPart)) + { + Protect = NewProtect; + } + } + + if (MmIsPagePresent(AddressSpace->Process, Address)) + { + MmSetPageProtect(AddressSpace->Process, BaseAddress, + Protect); + } + } + } +} + +NTSTATUS +MmProtectSectionView(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID BaseAddress, + ULONG Length, + ULONG Protect, + PULONG OldProtect) +{ + PMM_REGION Region; + NTSTATUS Status; + + Length = + min(Length, MemoryArea->BaseAddress + MemoryArea->Length - BaseAddress); + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.SectionData.RegionListHead, + BaseAddress, NULL); + *OldProtect = Region->Protect; + Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress, + &MemoryArea->Data.SectionData.RegionListHead, + BaseAddress, Length, Region->Type, Protect, + MmAlterViewAttributes); + + return(Status); +} + +NTSTATUS STDCALL +MmQuerySectionView(PMEMORY_AREA MemoryArea, + PVOID Address, + PMEMORY_BASIC_INFORMATION Info, + PULONG ResultLength) +{ + PMM_REGION Region; + PVOID RegionBaseAddress; + + Region = MmFindRegion(MemoryArea->BaseAddress, + &MemoryArea->Data.SectionData.RegionListHead, + Address, &RegionBaseAddress); + Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address); + Info->AllocationBase = MemoryArea->BaseAddress; + Info->AllocationProtect = MemoryArea->Attributes; + Info->RegionSize = MemoryArea->Length; + Info->State = MEM_COMMIT; + Info->Protect = Region->Protect; + if (MemoryArea->Data.SectionData.Section->AllocationAttributes & SEC_IMAGE) + { + Info->Type = MEM_IMAGE; + } + else + { + Info->Type = MEM_MAPPED; + } + + return(STATUS_SUCCESS); +} + +VOID STDCALL +MmpDeleteSection(PVOID ObjectBody) +{ + PSECTION_OBJECT Section = (PSECTION_OBJECT)ObjectBody; + + DPRINT("MmpDeleteSection(ObjectBody %x)\n", ObjectBody); + if (Section->AllocationAttributes & SEC_IMAGE) + { + ULONG i; + + for (i = 0; i < Section->NrSegments; i++) + { + InterlockedDecrement(&Section->Segments[i].ReferenceCount); + } + } + else + { + InterlockedDecrement(&Section->Segments->ReferenceCount); + } + if (Section->FileObject != NULL) + { + CcRosDereferenceCache(Section->FileObject); + ObDereferenceObject(Section->FileObject); + Section->FileObject = NULL; + } +} + +VOID STDCALL +MmpCloseSection(PVOID ObjectBody, + ULONG HandleCount) +{ + DPRINT("MmpCloseSection(OB %x, HC %d) RC %d\n", + ObjectBody, HandleCount, ObGetObjectPointerCount(ObjectBody)); + +} + +NTSTATUS STDCALL +MmpCreateSection(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("MmpCreateSection(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath == NULL) + { + return(STATUS_SUCCESS); + } + + if (wcschr(RemainingPath+1, L'\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + +NTSTATUS +MmCreatePhysicalMemorySection(VOID) +{ + HANDLE PhysSectionH; + PSECTION_OBJECT PhysSection; + NTSTATUS Status; + OBJECT_ATTRIBUTES Obj; + UNICODE_STRING Name = UNICODE_STRING_INITIALIZER(L"\\Device\\PhysicalMemory"); + LARGE_INTEGER SectionSize; + + /* + * Create the section mapping physical memory + */ + SectionSize.QuadPart = 0xFFFFFFFF; + InitializeObjectAttributes(&Obj, + &Name, + 0, + NULL, + NULL); + Status = NtCreateSection(&PhysSectionH, + SECTION_ALL_ACCESS, + &Obj, + &SectionSize, + PAGE_EXECUTE_READWRITE, + 0, + NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to create PhysicalMemory section\n"); + KeBugCheck(0); + } + Status = ObReferenceObjectByHandle(PhysSectionH, + SECTION_ALL_ACCESS, + NULL, + KernelMode, + (PVOID*)&PhysSection, + NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to reference PhysicalMemory section\n"); + KeBugCheck(0); + } + PhysSection->AllocationAttributes |= SEC_PHYSICALMEMORY; + ObDereferenceObject((PVOID)PhysSection); + + return(STATUS_SUCCESS); +} + +NTSTATUS +MmInitSectionImplementation(VOID) +{ + MmSectionObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlInitUnicodeStringFromLiteral(&MmSectionObjectType->TypeName, L"Section"); + + MmSectionObjectType->Tag = TAG('S', 'E', 'C', 'T'); + MmSectionObjectType->TotalObjects = 0; + MmSectionObjectType->TotalHandles = 0; + MmSectionObjectType->MaxObjects = ULONG_MAX; + MmSectionObjectType->MaxHandles = ULONG_MAX; + MmSectionObjectType->PagedPoolCharge = 0; + MmSectionObjectType->NonpagedPoolCharge = sizeof(SECTION_OBJECT); + MmSectionObjectType->Mapping = &MmpSectionMapping; + MmSectionObjectType->Dump = NULL; + MmSectionObjectType->Open = NULL; + MmSectionObjectType->Close = MmpCloseSection; + MmSectionObjectType->Delete = MmpDeleteSection; + MmSectionObjectType->Parse = NULL; + MmSectionObjectType->Security = NULL; + MmSectionObjectType->QueryName = NULL; + MmSectionObjectType->OkayToClose = NULL; + MmSectionObjectType->Create = MmpCreateSection; + MmSectionObjectType->DuplicationNotify = NULL; + + return(STATUS_SUCCESS); +} + +NTSTATUS +MmCreatePageFileSection(PHANDLE SectionHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PLARGE_INTEGER UMaximumSize, + ULONG SectionPageProtection, + ULONG AllocationAttributes) + /* + * Create a section which is backed by the pagefile + */ +{ + LARGE_INTEGER MaximumSize; + PSECTION_OBJECT Section; + PMM_SECTION_SEGMENT Segment; + NTSTATUS Status; + + if (UMaximumSize == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + MaximumSize = *UMaximumSize; + + /* + * Check the protection + */ + if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) != + SectionPageProtection) + { + return(STATUS_INVALID_PAGE_PROTECTION); + } + + /* + * Create the section + */ + Status = ObCreateObject(SectionHandle, + DesiredAccess, + ObjectAttributes, + MmSectionObjectType, + (PVOID*)&Section); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Initialize it + */ + Section->SectionPageProtection = SectionPageProtection; + Section->AllocationAttributes = AllocationAttributes; + InitializeListHead(&Section->ViewListHead); + KeInitializeSpinLock(&Section->ViewListLock); + KeInitializeMutex(&Section->Lock, 0); + Section->FileObject = NULL; + Section->MaximumSize = MaximumSize; + Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT), + TAG_MM_SECTION_SEGMENT); + if (Segment == NULL) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + return(STATUS_NO_MEMORY); + } + Section->Segments = Segment; + Segment->ReferenceCount = 1; + KeInitializeMutex(&Segment->Lock, 0); + Segment->FileOffset = 0; + Segment->Protection = SectionPageProtection; + Segment->Attributes = AllocationAttributes; + Segment->Length = MaximumSize.u.LowPart; + Segment->Flags = MM_PAGEFILE_SEGMENT; + Segment->WriteCopy = FALSE; + return(STATUS_SUCCESS); +} + + +NTSTATUS +MmCreateDataFileSection(PHANDLE SectionHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PLARGE_INTEGER UMaximumSize, + ULONG SectionPageProtection, + ULONG AllocationAttributes, + HANDLE FileHandle) + /* + * Create a section backed by a data file + */ +{ + PSECTION_OBJECT Section; + NTSTATUS Status; + LARGE_INTEGER MaximumSize; + PFILE_OBJECT FileObject; + PMM_SECTION_SEGMENT Segment; + ULONG FileAccess; + + /* + * Check the protection + */ + if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) != + SectionPageProtection) + { + return(STATUS_INVALID_PAGE_PROTECTION); + } + + /* + * Create the section + */ + Status = ObCreateObject(SectionHandle, + DesiredAccess, + ObjectAttributes, + MmSectionObjectType, + (PVOID*)&Section); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Initialize it + */ + Section->SectionPageProtection = SectionPageProtection; + Section->AllocationAttributes = AllocationAttributes; + InitializeListHead(&Section->ViewListHead); + KeInitializeSpinLock(&Section->ViewListLock); + KeInitializeMutex(&Section->Lock, 0); + Section->NrSegments = 1; + Section->ImageBase = NULL; + Section->EntryPoint = NULL; + Section->StackReserve = 0; + Section->StackCommit = 0; + Section->Subsystem = 0; + Section->MinorSubsystemVersion = 0; + Section->MajorSubsystemVersion = 0; + Section->ImageCharacteristics = 0; + Section->Machine = 0; + Section->Executable = FALSE; + + /* + * Check file access required + */ + if (SectionPageProtection & PAGE_READWRITE || + SectionPageProtection & PAGE_EXECUTE_READWRITE) + { + FileAccess = FILE_READ_DATA | FILE_WRITE_DATA; + } + else + { + FileAccess = FILE_READ_DATA; + } + + /* + * Reference the file handle + */ + Status = ObReferenceObjectByHandle(FileHandle, + FileAccess, + IoFileObjectType, + UserMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + return(Status); + } + + /* + * We can't do memory mappings if the file system doesn't support the + * standard FCB + */ + if (!(FileObject->Flags & FO_FCB_IS_VALID)) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + return(STATUS_INVALID_FILE_FOR_SECTION); + } + + /* + * FIXME: Revise this once a locking order for file size changes is + * decided + */ + if (UMaximumSize != NULL) + { + MaximumSize = *UMaximumSize; + } + else + { + MaximumSize = + ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize; + } + + if (MaximumSize.QuadPart > + ((PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext)->FileSize.QuadPart) + { + IO_STATUS_BLOCK Iosb; + Status = NtSetInformationFile(FileHandle, + &Iosb, + &MaximumSize, + sizeof(LARGE_INTEGER), + FileAllocationInformation); + if (!NT_SUCCESS(Status)) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + return(STATUS_SECTION_NOT_EXTENDED); + } + } + + /* + * Lock the file + */ + Status = KeWaitForSingleObject((PVOID)&FileObject->Lock, + 0, + KernelMode, + FALSE, + NULL); + if (Status != STATUS_SUCCESS) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + return(Status); + } + + /* + * If this file hasn't been mapped as a data file before then allocate a + * section segment to describe the data file mapping + */ + if (FileObject->SectionObjectPointers->DataSectionObject == NULL) + { + Segment = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_SECTION_SEGMENT), + TAG_MM_SECTION_SEGMENT); + if (Segment == NULL) + { + KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + return(STATUS_NO_MEMORY); + } + Section->Segments = Segment; + Segment->ReferenceCount = 1; + KeInitializeMutex(&Segment->Lock, 0); + + /* + * Set the lock before assigning the segment to the file object + */ + Status = KeWaitForSingleObject((PVOID)&Segment->Lock, + 0, + KernelMode, + FALSE, + NULL); + if (Status != STATUS_SUCCESS) + { + KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); + ExFreePool(Segment); + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + return(Status); + } + FileObject->SectionObjectPointers->DataSectionObject = (PVOID)Segment; + + Segment->FileOffset = 0; + Segment->Protection = 0; + Segment->Attributes = 0; + Segment->Flags = MM_DATAFILE_SEGMENT; + Segment->Characteristics = 0; + Segment->WriteCopy = FALSE; + if (AllocationAttributes & SEC_RESERVE) + { + Segment->Length = 0; + } + else + { + Segment->Length = MaximumSize.u.LowPart; + } + Segment->VirtualAddress = NULL; + } + else + { + /* + * If the file is already mapped as a data file then we may need + * to extend it + */ + Segment = + (PMM_SECTION_SEGMENT)FileObject->SectionObjectPointers-> + DataSectionObject; + Section->Segments = Segment; + InterlockedIncrement((PLONG)&Segment->ReferenceCount); + Status = KeWaitForSingleObject((PVOID)&Segment->Lock, + 0, + KernelMode, + FALSE, + NULL); + if (Status != STATUS_SUCCESS) + { + InterlockedDecrement((PLONG)&Segment->ReferenceCount); + KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + return(Status); + } + if (MaximumSize.u.LowPart > Segment->Length && + !(AllocationAttributes & SEC_RESERVE)) + { + Segment->Length = MaximumSize.u.LowPart; + } + } + KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); + CcRosReferenceCache(FileObject); + Section->FileObject = FileObject; + Section->MaximumSize = MaximumSize; + KeReleaseMutex(&Segment->Lock, FALSE); + + ObDereferenceObject(Section); + return(STATUS_SUCCESS); +} + +static ULONG SectionCharacteristicsToProtect[16] = +{ + PAGE_NOACCESS, // 0 = NONE + PAGE_NOACCESS, // 1 = SHARED + PAGE_EXECUTE, // 2 = EXECUTABLE + PAGE_EXECUTE, // 3 = EXECUTABLE, SHARED + PAGE_READONLY, // 4 = READABLE + PAGE_READONLY, // 5 = READABLE, SHARED + PAGE_EXECUTE_READ, // 6 = READABLE, EXECUTABLE + PAGE_EXECUTE_READ, // 7 = READABLE, EXECUTABLE, SHARED + PAGE_READWRITE, // 8 = WRITABLE + PAGE_READWRITE, // 9 = WRITABLE, SHARED + PAGE_EXECUTE_READWRITE, // 10 = WRITABLE, EXECUTABLE + PAGE_EXECUTE_READWRITE, // 11 = WRITABLE, EXECUTABLE, SHARED + PAGE_READWRITE, // 12 = WRITABLE, READABLE + PAGE_READWRITE, // 13 = WRITABLE, READABLE, SHARED + PAGE_EXECUTE_READWRITE, // 14 = WRITABLE, READABLE, EXECUTABLE, + PAGE_EXECUTE_READWRITE, // 15 = WRITABLE, READABLE, EXECUTABLE, SHARED +}; + +NTSTATUS +MmCreateImageSection(PHANDLE SectionHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + PLARGE_INTEGER UMaximumSize, + ULONG SectionPageProtection, + ULONG AllocationAttributes, + HANDLE FileHandle) +{ + PSECTION_OBJECT Section; + NTSTATUS Status; + PFILE_OBJECT FileObject; + ULONG FileAccess; + IMAGE_DOS_HEADER DosHeader; + IO_STATUS_BLOCK Iosb; + LARGE_INTEGER Offset; + IMAGE_NT_HEADERS PEHeader; + PIMAGE_SECTION_HEADER ImageSections; + PMM_SECTION_SEGMENT SectionSegments; + ULONG NrSegments; + PMM_IMAGE_SECTION_OBJECT ImageSectionObject; + + /* + * Check the protection + */ + if ((SectionPageProtection & PAGE_FLAGS_VALID_FROM_USER_MODE) != + SectionPageProtection) + { + return(STATUS_INVALID_PAGE_PROTECTION); + } + + /* + * Specifying a maximum size is meaningless for an image section + */ + if (UMaximumSize != NULL) + { + return(STATUS_INVALID_PARAMETER_4); + } + + /* + * Read the dos header + */ + Offset.QuadPart = 0; + Status = ZwReadFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + &DosHeader, + sizeof(DosHeader), + &Offset, + 0); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (Iosb.Information != sizeof(DosHeader)) + { + return(STATUS_INVALID_IMAGE_FORMAT); + } + + /* + * Check the DOS signature + */ + if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) + { + return(STATUS_INVALID_IMAGE_FORMAT); + } + + /* + * Read the PE header + */ + Offset.QuadPart = DosHeader.e_lfanew; + Status = ZwReadFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + &PEHeader, + sizeof(PEHeader), + &Offset, + 0); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (Iosb.Information != sizeof(PEHeader)) + { + return(STATUS_INVALID_IMAGE_FORMAT); + } + + /* + * Check the signature + */ + if (PEHeader.Signature != IMAGE_NT_SIGNATURE) + { + return(STATUS_INVALID_IMAGE_FORMAT); + } + + /* + * Read in the section headers + */ + Offset.QuadPart = DosHeader.e_lfanew + sizeof(PEHeader); + ImageSections = + ExAllocatePool(NonPagedPool, + PEHeader.FileHeader.NumberOfSections * + sizeof(IMAGE_SECTION_HEADER)); + Status = ZwReadFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + ImageSections, + PEHeader.FileHeader.NumberOfSections * + sizeof(IMAGE_SECTION_HEADER), + &Offset, + 0); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ImageSections); + return(Status); + } + if (Iosb.Information != + (PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))) + { + ExFreePool(ImageSections); + return(STATUS_INVALID_IMAGE_FORMAT); + } + + /* + * Create the section + */ + Status = ObCreateObject(SectionHandle, + DesiredAccess, + ObjectAttributes, + MmSectionObjectType, + (PVOID*)&Section); + if (!NT_SUCCESS(Status)) + { + ExFreePool(ImageSections); + return(Status); + } + + /* + * Initialize it + */ + Section->SectionPageProtection = SectionPageProtection; + Section->AllocationAttributes = AllocationAttributes; + InitializeListHead(&Section->ViewListHead); + KeInitializeSpinLock(&Section->ViewListLock); + KeInitializeMutex(&Section->Lock, 0); + Section->NrSegments = PEHeader.FileHeader.NumberOfSections + 1; + Section->ImageBase = (PVOID)PEHeader.OptionalHeader.ImageBase; + Section->EntryPoint = (PVOID)PEHeader.OptionalHeader.AddressOfEntryPoint; + Section->StackReserve = PEHeader.OptionalHeader.SizeOfStackReserve; + Section->StackCommit = PEHeader.OptionalHeader.SizeOfStackCommit; + Section->Subsystem = PEHeader.OptionalHeader.Subsystem; + Section->MinorSubsystemVersion = + PEHeader.OptionalHeader.MinorSubsystemVersion; + Section->MajorSubsystemVersion = + PEHeader.OptionalHeader.MajorSubsystemVersion; + Section->ImageCharacteristics = PEHeader.FileHeader.Characteristics; + Section->Machine = PEHeader.FileHeader.Machine; + Section->Executable = (PEHeader.OptionalHeader.SizeOfCode != 0); + + /* + * Check file access required + */ + if (SectionPageProtection & PAGE_READWRITE || + SectionPageProtection & PAGE_EXECUTE_READWRITE) + { + FileAccess = FILE_READ_DATA | FILE_WRITE_DATA; + } + else + { + FileAccess = FILE_READ_DATA; + } + + /* + * Reference the file handle + */ + Status = ObReferenceObjectByHandle(FileHandle, + FileAccess, + IoFileObjectType, + UserMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ExFreePool(ImageSections); + return(Status); + } + + /* + * We can't do memory mappings if the file system doesn't support the + * standard FCB + */ + if (!(FileObject->Flags & FO_FCB_IS_VALID)) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + ExFreePool(ImageSections); + return(STATUS_INVALID_FILE_FOR_SECTION); + } + + /* + * Lock the file + */ + Status = KeWaitForSingleObject((PVOID)&FileObject->Lock, + 0, + KernelMode, + FALSE, + NULL); + if (Status != STATUS_SUCCESS) + { + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + ExFreePool(ImageSections); + return(Status); + } + + /* + * If this file hasn't been mapped as a image file before then allocate the + * section segments to describe the mapping + */ + NrSegments = PEHeader.FileHeader.NumberOfSections + 1; + if (FileObject->SectionObjectPointers->ImageSectionObject == NULL) + { + ULONG i; + ULONG Size; + ULONG Characteristics; + + Size = sizeof(MM_IMAGE_SECTION_OBJECT) + + (sizeof(MM_SECTION_SEGMENT) * NrSegments); + ImageSectionObject = + ExAllocatePoolWithTag(NonPagedPool, Size, TAG_MM_SECTION_SEGMENT); + if (ImageSectionObject == NULL) + { + KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); + ZwClose(*SectionHandle); + ObDereferenceObject(Section); + ObDereferenceObject(FileObject); + ExFreePool(ImageSections); + return(STATUS_NO_MEMORY); + } + ImageSectionObject->NrSegments = NrSegments; + SectionSegments = ImageSectionObject->Segments; + Section->Segments = SectionSegments; + + SectionSegments[0].FileOffset = 0; + SectionSegments[0].Characteristics = IMAGE_SECTION_CHAR_DATA; + SectionSegments[0].Protection = PAGE_READWRITE; + SectionSegments[0].RawLength = PAGE_SIZE; + SectionSegments[0].Length = PAGE_SIZE; + SectionSegments[0].Flags = 0; + SectionSegments[0].ReferenceCount = 1; + SectionSegments[0].VirtualAddress = 0; + SectionSegments[0].WriteCopy = TRUE; + KeInitializeMutex(&SectionSegments[0].Lock, 0); + + for (i = 1; i < NrSegments; i++) + { + SectionSegments[i].FileOffset = + ImageSections[i-1].PointerToRawData; + SectionSegments[i].Characteristics = + ImageSections[i-1].Characteristics; + + /* + * Set up the protection and write copy variables. + */ + Characteristics = ImageSections[i - 1].Characteristics; + if ((Characteristics & IMAGE_SECTION_CHAR_READABLE) || + (Characteristics & IMAGE_SECTION_CHAR_WRITABLE) || + (Characteristics & IMAGE_SECTION_CHAR_EXECUTABLE)) + { + SectionSegments[i].Protection = + SectionCharacteristicsToProtect[Characteristics >> 28]; + SectionSegments[i].WriteCopy = + !(Characteristics & IMAGE_SECTION_CHAR_SHARED); + } + else if (Characteristics & IMAGE_SECTION_CHAR_CODE) + { + SectionSegments[i].Protection = PAGE_EXECUTE_READ; + SectionSegments[i].WriteCopy = TRUE; + } + else if (Characteristics & IMAGE_SECTION_CHAR_DATA) + { + SectionSegments[i].Protection = PAGE_READWRITE; + SectionSegments[i].WriteCopy = TRUE; + } + else if (Characteristics & IMAGE_SECTION_CHAR_BSS) + { + SectionSegments[i].Protection = PAGE_READWRITE; + SectionSegments[i].WriteCopy = TRUE; + } + else + { + SectionSegments[i].Protection = PAGE_NOACCESS; + SectionSegments[i].WriteCopy = TRUE; + } + + /* + * Set up the attributes. + */ + if (Characteristics & IMAGE_SECTION_CHAR_CODE) + { + SectionSegments[i].Attributes = 0; + } + else if (Characteristics & IMAGE_SECTION_CHAR_DATA) + { + SectionSegments[i].Attributes = 0; + } + else if (Characteristics & IMAGE_SECTION_CHAR_BSS) + { + SectionSegments[i].Attributes = MM_SECTION_SEGMENT_BSS; + } + else + { + SectionSegments[i].Attributes = 0; + } + + SectionSegments[i].RawLength = ImageSections[i-1].SizeOfRawData; + SectionSegments[i].Length = + ImageSections[i-1].Misc.VirtualSize; + SectionSegments[i].Flags = 0; + SectionSegments[i].ReferenceCount = 1; + SectionSegments[i].VirtualAddress = + (PVOID)ImageSections[i-1].VirtualAddress; + KeInitializeMutex(&SectionSegments[i].Lock, 0); + } + + FileObject->SectionObjectPointers->ImageSectionObject = + (PVOID)ImageSectionObject; + } + else + { + ULONG i; + + ImageSectionObject = (PMM_IMAGE_SECTION_OBJECT) + FileObject->SectionObjectPointers->ImageSectionObject; + SectionSegments = ImageSectionObject->Segments; + Section->Segments = SectionSegments; + + /* + * Otherwise just reference all the section segments + */ + for (i = 0; i < NrSegments; i++) + { + InterlockedIncrement(&SectionSegments[i].ReferenceCount); + } + + } + ExFreePool(ImageSections); + KeSetEvent((PVOID)&FileObject->Lock, IO_NO_INCREMENT, FALSE); + CcRosReferenceCache(FileObject); + Section->FileObject = FileObject; + + ObDereferenceObject(Section); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtCreateSection (OUT PHANDLE SectionHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize OPTIONAL, + IN ULONG SectionPageProtection OPTIONAL, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL) +{ + if (AllocationAttributes & SEC_IMAGE) + { + return(MmCreateImageSection(SectionHandle, + DesiredAccess, + ObjectAttributes, + MaximumSize, + SectionPageProtection, + AllocationAttributes, + FileHandle)); + } + else if (FileHandle != NULL) + { + return(MmCreateDataFileSection(SectionHandle, + DesiredAccess, + ObjectAttributes, + MaximumSize, + SectionPageProtection, + AllocationAttributes, + FileHandle)); + } + else + { + return(MmCreatePageFileSection(SectionHandle, + DesiredAccess, + ObjectAttributes, + MaximumSize, + SectionPageProtection, + AllocationAttributes)); + } +} + + +/********************************************************************** + * NAME + * NtOpenSection + * + * DESCRIPTION + * + * ARGUMENTS + * SectionHandle + * + * DesiredAccess + * + * ObjectAttributes + * + * RETURN VALUE + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtOpenSection(PHANDLE SectionHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + NTSTATUS Status; + + *SectionHandle = 0; + + Status = ObOpenObjectByName(ObjectAttributes, + MmSectionObjectType, + NULL, + UserMode, + DesiredAccess, + NULL, + SectionHandle); + + return(Status); +} + +NTSTATUS STATIC +MmMapViewOfSegment(PEPROCESS Process, + PMADDRESS_SPACE AddressSpace, + PSECTION_OBJECT Section, + PMM_SECTION_SEGMENT Segment, + PVOID* BaseAddress, + ULONG ViewSize, + ULONG Protect, + ULONG ViewOffset) +{ + PMEMORY_AREA MArea; + NTSTATUS Status; + KIRQL oldIrql; + + Status = MmCreateMemoryArea(Process, + &Process->AddressSpace, + MEMORY_AREA_SECTION_VIEW, + BaseAddress, + ViewSize, + Protect, + &MArea, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Mapping between 0x%.8X and 0x%.8X failed.\n", + (*BaseAddress), (*BaseAddress) + ViewSize); + return(Status); + } + + KeAcquireSpinLock(&Section->ViewListLock, &oldIrql); + InsertTailList(&Section->ViewListHead, + &MArea->Data.SectionData.ViewListEntry); + KeReleaseSpinLock(&Section->ViewListLock, oldIrql); + + ObReferenceObjectByPointer((PVOID)Section, + SECTION_MAP_READ, + NULL, + ExGetPreviousMode()); + MArea->Data.SectionData.Segment = Segment; + MArea->Data.SectionData.Section = Section; + MArea->Data.SectionData.ViewOffset = ViewOffset; + MArea->Data.SectionData.WriteCopyView = FALSE; + MmInitialiseRegion(&MArea->Data.SectionData.RegionListHead, + ViewSize, 0, Protect); + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * NtMapViewOfSection + * + * DESCRIPTION + * Maps a view of a section into the virtual address space of a + * process. + * + * ARGUMENTS + * SectionHandle + * Handle of the section. + * + * ProcessHandle + * Handle of the process. + * + * BaseAddress + * Desired base address (or NULL) on entry; + * Actual base address of the view on exit. + * + * ZeroBits + * Number of high order address bits that must be zero. + * + * CommitSize + * Size in bytes of the initially committed section of + * the view. + * + * SectionOffset + * Offset in bytes from the beginning of the section + * to the beginning of the view. + * + * ViewSize + * Desired length of map (or zero to map all) on entry + * Actual length mapped on exit. + * + * InheritDisposition + * Specified how the view is to be shared with + * child processes. + * + * AllocateType + * Type of allocation for the pages. + * + * Protect + * Protection for the committed region of the view. + * + * RETURN VALUE + * Status. + */ +NTSTATUS STDCALL +NtMapViewOfSection(HANDLE SectionHandle, + HANDLE ProcessHandle, + PVOID* BaseAddress, + ULONG ZeroBits, + ULONG CommitSize, + PLARGE_INTEGER SectionOffset, + PULONG ViewSize, + SECTION_INHERIT InheritDisposition, + ULONG AllocationType, + ULONG Protect) +{ + PSECTION_OBJECT Section; + PEPROCESS Process; + NTSTATUS Status; + PMADDRESS_SPACE AddressSpace; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + AddressSpace = &Process->AddressSpace; + + Status = ObReferenceObjectByHandle(SectionHandle, + SECTION_MAP_READ, + MmSectionObjectType, + UserMode, + (PVOID*)&Section, + NULL); + if (!(NT_SUCCESS(Status))) + { + DPRINT("ObReference failed rc=%x\n",Status); + ObDereferenceObject(Process); + return(Status); + } + + Status = MmMapViewOfSection(Section, + Process, + BaseAddress, + ZeroBits, + CommitSize, + SectionOffset, + ViewSize, + InheritDisposition, + AllocationType, + Protect); + + ObDereferenceObject(Section); + ObDereferenceObject(Process); + + return(Status); +} + +VOID STATIC +MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, + BOOLEAN Dirty) +{ + PMEMORY_AREA MArea; + ULONG Entry; + PFILE_OBJECT FileObject; + PREACTOS_COMMON_FCB_HEADER Fcb; + ULONG Offset; + SWAPENTRY SavedSwapEntry; + PMM_PAGEOP PageOp; + + MArea = (PMEMORY_AREA)Context; + + Offset = ((ULONG)PAGE_ROUND_DOWN(Address) - (ULONG)MArea->BaseAddress) + + MArea->Data.SectionData.ViewOffset; + Entry = MmGetPageEntrySectionSegment(MArea->Data.SectionData.Segment, + Offset); + + PageOp = MmCheckForPageOp(MArea, 0, NULL, MArea->Data.SectionData.Segment, + Offset); + assert(PageOp == NULL); + + /* + * For a dirty, datafile, non-private page mark it as dirty in the + * cache manager. + */ + if (MArea->Data.SectionData.Segment->Flags & MM_DATAFILE_SEGMENT) + { + if (PhysAddr.QuadPart == PAGE_FROM_SSE(Entry) && Dirty) + { + FileObject = MemoryArea->Data.SectionData.Section->FileObject; + Fcb = (PREACTOS_COMMON_FCB_HEADER)FileObject->FsContext; + CcRosMarkDirtyCacheSegment(Fcb->Bcb, Offset); + assert(SwapEntry == 0); + } + } + + if (SwapEntry != 0) + { + MmFreeSwapPage(SwapEntry); + } + else if (PhysAddr.QuadPart != 0) + { + if (IS_SWAP_FROM_SSE(Entry) || + PhysAddr.QuadPart != (PAGE_FROM_SSE(Entry))) + { + /* + * Just dereference private pages + */ + SavedSwapEntry = MmGetSavedSwapEntryPage(PhysAddr); + if (SavedSwapEntry != 0) + { + MmFreeSwapPage(SavedSwapEntry); + MmSetSavedSwapEntryPage(PhysAddr, 0); + } + MmDeleteRmap(PhysAddr, MArea->Process, Address); + MmReleasePageMemoryConsumer(MC_USER, PhysAddr); + } + else + { + MmUnsharePageEntrySectionSegment(MArea->Data.SectionData.Section, + MArea->Data.SectionData.Segment, + Offset, + Dirty); + MmDeleteRmap(PhysAddr, MArea->Process, Address); + MmReleasePageMemoryConsumer(MC_USER, PhysAddr); + } + } +} + +NTSTATUS STDCALL +MmUnmapViewOfSection(PEPROCESS Process, + PVOID BaseAddress) +{ + NTSTATUS Status; + PMEMORY_AREA MemoryArea; + PMADDRESS_SPACE AddressSpace; + PSECTION_OBJECT Section; + PMM_SECTION_SEGMENT Segment; + KIRQL oldIrql; + PLIST_ENTRY CurrentEntry; + PMM_REGION CurrentRegion; + + AddressSpace = &Process->AddressSpace; + + DPRINT("Opening memory area Process %x BaseAddress %x\n", + Process, BaseAddress); + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, + BaseAddress); + if (MemoryArea == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + MemoryArea->DeleteInProgress = TRUE; + + MmLockSection(MemoryArea->Data.SectionData.Section); + MmLockSectionSegment(MemoryArea->Data.SectionData.Segment); + Section = MemoryArea->Data.SectionData.Section; + Segment = MemoryArea->Data.SectionData.Segment; + KeAcquireSpinLock(&Section->ViewListLock, &oldIrql); + RemoveEntryList(&MemoryArea->Data.SectionData.ViewListEntry); + KeReleaseSpinLock(&Section->ViewListLock, oldIrql); + + CurrentEntry = MemoryArea->Data.SectionData.RegionListHead.Flink; + while (CurrentEntry != &MemoryArea->Data.SectionData.RegionListHead) + { + CurrentRegion = + CONTAINING_RECORD(CurrentEntry, MM_REGION, RegionListEntry); + CurrentEntry = CurrentEntry->Flink; + ExFreePool(CurrentRegion); + } + + if (MemoryArea->Data.SectionData.Section->AllocationAttributes & + SEC_PHYSICALMEMORY) + { + Status = MmFreeMemoryArea(&Process->AddressSpace, + BaseAddress, + 0, + NULL, + NULL); + } + else + { + Status = MmFreeMemoryArea(&Process->AddressSpace, + BaseAddress, + 0, + MmFreeSectionPage, + MemoryArea); + } + MmUnlockSection(Section); + MmUnlockSectionSegment(Segment); + ObDereferenceObject(Section); + return(STATUS_SUCCESS); +} + +/********************************************************************** + * NAME EXPORTED + * NtUnmapViewOfSection + * + * DESCRIPTION + * + * ARGUMENTS + * ProcessHandle + * + * BaseAddress + * + * RETURN VALUE + * Status. + * + * REVISIONS + * + */ +NTSTATUS STDCALL +NtUnmapViewOfSection (HANDLE ProcessHandle, + PVOID BaseAddress) +{ + PEPROCESS Process; + NTSTATUS Status; + + DPRINT("NtUnmapViewOfSection(ProcessHandle %x, BaseAddress %x)\n", + ProcessHandle, BaseAddress); + + DPRINT("Referencing process\n"); + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObReferenceObjectByHandle failed (Status %x)\n", Status); + return(Status); + } + + MmLockAddressSpace(&Process->AddressSpace); + Status = MmUnmapViewOfSection(Process, BaseAddress); + MmUnlockAddressSpace(&Process->AddressSpace); + + ObDereferenceObject(Process); + + return Status; +} + + +NTSTATUS STDCALL +NtQuerySection (IN HANDLE SectionHandle, + IN CINT SectionInformationClass, + OUT PVOID SectionInformation, + IN ULONG Length, + OUT PULONG ResultLength) +/* + * FUNCTION: Queries the information of a section object. + * ARGUMENTS: + * SectionHandle = Handle to the section link object + * SectionInformationClass = Index to a certain information structure + * SectionInformation (OUT)= Caller supplies storage for resulting + * information + * Length = Size of the supplied storage + * ResultLength = Data written + * RETURNS: Status + * + */ +{ + PSECTION_OBJECT Section; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(SectionHandle, + SECTION_MAP_READ, + MmSectionObjectType, + UserMode, + (PVOID*)&Section, + NULL); + if (!(NT_SUCCESS(Status))) + { + return(Status); + } + + switch (SectionInformationClass) + { + case SectionBasicInformation: + { + PSECTION_BASIC_INFORMATION Sbi; + + if (Length != sizeof(SECTION_BASIC_INFORMATION)) + { + ObDereferenceObject(Section); + return(STATUS_INFO_LENGTH_MISMATCH); + } + + Sbi = (PSECTION_BASIC_INFORMATION)SectionInformation; + + Sbi->BaseAddress = 0; + Sbi->Attributes = 0; + Sbi->Size.QuadPart = 0; + + *ResultLength = sizeof(SECTION_BASIC_INFORMATION); + Status = STATUS_SUCCESS; + break; + } + + case SectionImageInformation: + { + PSECTION_IMAGE_INFORMATION Sii; + + if (Length != sizeof(SECTION_IMAGE_INFORMATION)) + { + ObDereferenceObject(Section); + return(STATUS_INFO_LENGTH_MISMATCH); + } + Sii = (PSECTION_IMAGE_INFORMATION)SectionInformation; + Sii->EntryPoint = Section->EntryPoint; + Sii->Unknown1 = 0; + Sii->StackReserve = Section->StackReserve; + Sii->StackCommit = Section->StackCommit; + Sii->Subsystem = Section->Subsystem; + Sii->MinorSubsystemVersion = Section->MinorSubsystemVersion; + Sii->MajorSubsystemVersion = Section->MajorSubsystemVersion; + Sii->Unknown2 = 0; + Sii->Characteristics = Section->ImageCharacteristics; + Sii->ImageNumber = Section->Machine; + Sii->Executable = Section->Executable; + Sii->Unknown3 = 0; + Sii->Unknown4[0] = 0; + Sii->Unknown4[1] = 0; + Sii->Unknown4[2] = 0; + + *ResultLength = sizeof(SECTION_IMAGE_INFORMATION); + Status = STATUS_SUCCESS; + break; + } + + default: + *ResultLength = 0; + Status = STATUS_INVALID_INFO_CLASS; + } + ObDereferenceObject(Section); + return(Status); +} + + +NTSTATUS STDCALL +NtExtendSection(IN HANDLE SectionHandle, + IN ULONG NewMaximumSize) +{ + UNIMPLEMENTED; +} + + +/********************************************************************** + * NAME INTERNAL + * MmAllocateSection@4 + * + * DESCRIPTION + * + * ARGUMENTS + * Length + * + * RETURN VALUE + * + * NOTE + * Code taken from ntoskrnl/mm/special.c. + * + * REVISIONS + * + */ +PVOID STDCALL +MmAllocateSection (IN ULONG Length) +{ + PVOID Result; + MEMORY_AREA* marea; + NTSTATUS Status; + ULONG i; + PMADDRESS_SPACE AddressSpace; + + DPRINT("MmAllocateSection(Length %x)\n",Length); + + AddressSpace = MmGetKernelAddressSpace(); + Result = NULL; + MmLockAddressSpace(AddressSpace); + Status = MmCreateMemoryArea (NULL, + AddressSpace, + MEMORY_AREA_SYSTEM, + &Result, + Length, + 0, + &marea, + FALSE); + if (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(AddressSpace); + return (NULL); + } + MmUnlockAddressSpace(AddressSpace); + DPRINT("Result %p\n",Result); + for (i = 0; (i <= (Length / PAGE_SIZE)); i++) + { + PHYSICAL_ADDRESS Page; + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to allocate page\n"); + KeBugCheck(0); + } + Status = MmCreateVirtualMapping (NULL, + (Result + (i * PAGE_SIZE)), + PAGE_READWRITE, + Page, + TRUE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Unable to create virtual mapping\n"); + KeBugCheck(0); + } + } + return ((PVOID)Result); +} + + +/********************************************************************** + * NAME EXPORTED + * MmMapViewOfSection + * + * DESCRIPTION + * Maps a view of a section into the virtual address space of a + * process. + * + * ARGUMENTS + * Section + * Pointer to the section object. + * + * ProcessHandle + * Pointer to the process. + * + * BaseAddress + * Desired base address (or NULL) on entry; + * Actual base address of the view on exit. + * + * ZeroBits + * Number of high order address bits that must be zero. + * + * CommitSize + * Size in bytes of the initially committed section of + * the view. + * + * SectionOffset + * Offset in bytes from the beginning of the section + * to the beginning of the view. + * + * ViewSize + * Desired length of map (or zero to map all) on entry + * Actual length mapped on exit. + * + * InheritDisposition + * Specified how the view is to be shared with + * child processes. + * + * AllocationType + * Type of allocation for the pages. + * + * Protect + * Protection for the committed region of the view. + * + * RETURN VALUE + * Status. + */ +NTSTATUS STDCALL +MmMapViewOfSection(IN PVOID SectionObject, + IN PEPROCESS Process, + IN OUT PVOID *BaseAddress, + IN ULONG ZeroBits, + IN ULONG CommitSize, + IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, + IN OUT PULONG ViewSize, + IN SECTION_INHERIT InheritDisposition, + IN ULONG AllocationType, + IN ULONG Protect) +{ + PSECTION_OBJECT Section; + PMADDRESS_SPACE AddressSpace; + ULONG ViewOffset; + NTSTATUS Status = STATUS_SUCCESS; + + Section = (PSECTION_OBJECT)SectionObject; + AddressSpace = &Process->AddressSpace; + + MmLockAddressSpace(AddressSpace); + MmLockSection(SectionObject); + + if (Section->AllocationAttributes & SEC_IMAGE) + { + ULONG i; + PVOID ImageBase; + ULONG ImageSize; + + ImageBase = *BaseAddress; + if (ImageBase == NULL) + { + ImageBase = Section->ImageBase; + } + + ImageSize = 0; + for (i = 0; i < Section->NrSegments; i++) + { + if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD)) + { + ULONG MaxExtent; + MaxExtent = (ULONG)(Section->Segments[i].VirtualAddress + + Section->Segments[i].Length); + ImageSize = max(ImageSize, MaxExtent); + } + } + + /* Check there is enough space to map the section at that point. */ + if (MmOpenMemoryAreaByRegion(AddressSpace, ImageBase, + ImageSize) != NULL) + { + /* Fail if the user requested a fixed base address. */ + if ((*BaseAddress) != NULL) + { + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + return(Status); + } + /* Otherwise find a gap to map the image. */ + ImageBase = MmFindGap(AddressSpace, ImageSize); + if (ImageBase == NULL) + { + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + return(Status); + } + } + + for (i = 0; i < Section->NrSegments; i++) + { + PVOID SBaseAddress; + + if (!(Section->Segments[i].Characteristics & IMAGE_SECTION_NOLOAD)) + { + SBaseAddress = (PVOID) + (ImageBase + (ULONG_PTR)Section->Segments[i].VirtualAddress); + + MmLockSectionSegment(&Section->Segments[i]); + Status = MmMapViewOfSegment(Process, + &Process->AddressSpace, + Section, + &Section->Segments[i], + &SBaseAddress, + Section->Segments[i].Length, + Section->Segments[i].Protection, + Section->Segments[i].FileOffset); + MmUnlockSectionSegment(&Section->Segments[i]); + if (!NT_SUCCESS(Status)) + { + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + return(Status); + } + } + } + *BaseAddress = ImageBase; + } + else + { + if (SectionOffset == NULL) + { + ViewOffset = 0; + } + else + { + ViewOffset = SectionOffset->u.LowPart; + } + + if ((ViewOffset % PAGE_SIZE) != 0) + { + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + return(STATUS_MAPPED_ALIGNMENT); + } + + if ((*ViewSize) == 0) + { + (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset; + } + else if (((*ViewSize)+ViewOffset) > Section->MaximumSize.u.LowPart) + { + (*ViewSize) = Section->MaximumSize.u.LowPart - ViewOffset; + } + + MmLockSectionSegment(Section->Segments); + Status = MmMapViewOfSegment(Process, + &Process->AddressSpace, + Section, + Section->Segments, + BaseAddress, + *ViewSize, + Protect, + ViewOffset); + MmUnlockSectionSegment(Section->Segments); + if (!NT_SUCCESS(Status)) + { + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + return(Status); + } + } + + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + + return(STATUS_SUCCESS); +} + +BOOLEAN STDCALL +MmCanFileBeTruncated (IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN PLARGE_INTEGER NewFileSize) +{ + UNIMPLEMENTED; + return (FALSE); +} + + +BOOLEAN STDCALL +MmDisableModifiedWriteOfSection (DWORD Unknown0) +{ + UNIMPLEMENTED; + return (FALSE); +} + +BOOLEAN STDCALL +MmFlushImageSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer, + IN MMFLUSH_TYPE FlushType) +{ + UNIMPLEMENTED; + return (FALSE); +} + +BOOLEAN STDCALL +MmForceSectionClosed (DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED; + return (FALSE); +} + + +NTSTATUS STDCALL +MmMapViewInSystemSpace (IN PVOID Section, + OUT PVOID * MappedBase, + IN PULONG ViewSize) +{ + UNIMPLEMENTED; + return (STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS STDCALL +MmUnmapViewInSystemSpace (DWORD Unknown0) +{ + UNIMPLEMENTED; + return (STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +MmSetBankedSection (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED; + return (STATUS_NOT_IMPLEMENTED); +} + + +/********************************************************************** + * NAME EXPORTED + * MmCreateSection@ + * + * DESCRIPTION + * Creates a section object. + * + * ARGUMENTS + * SectionObjiect (OUT) + * Caller supplied storage for the resulting pointer + * to a SECTION_BOJECT instance; + * + * DesiredAccess + * Specifies the desired access to the section can be a + * combination of: + * STANDARD_RIGHTS_REQUIRED | + * SECTION_QUERY | + * SECTION_MAP_WRITE | + * SECTION_MAP_READ | + * SECTION_MAP_EXECUTE + * + * ObjectAttributes [OPTIONAL] + * Initialized attributes for the object can be used + * to create a named section; + * + * MaximumSize + * Maximizes the size of the memory section. Must be + * non-NULL for a page-file backed section. + * If value specified for a mapped file and the file is + * not large enough, file will be extended. + * + * SectionPageProtection + * Can be a combination of: + * PAGE_READONLY | + * PAGE_READWRITE | + * PAGE_WRITEONLY | + * PAGE_WRITECOPY + * + * AllocationAttributes + * Can be a combination of: + * SEC_IMAGE | + * SEC_RESERVE + * + * FileHandle + * Handle to a file to create a section mapped to a file + * instead of a memory backed section; + * + * File + * Unknown. + * + * RETURN VALUE + * Status. + */ +NTSTATUS STDCALL +MmCreateSection (OUT PSECTION_OBJECT * SectionObject, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN PLARGE_INTEGER MaximumSize, + IN ULONG SectionPageProtection, + IN ULONG AllocationAttributes, + IN HANDLE FileHandle OPTIONAL, + IN PFILE_OBJECT File OPTIONAL) +{ + return (STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ + + + + + + diff --git a/ntoskrnl/mm/slab.c b/ntoskrnl/mm/slab.c new file mode 100644 index 0000000..e2479d4 --- /dev/null +++ b/ntoskrnl/mm/slab.c @@ -0,0 +1,322 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/slab.c + * PURPOSE: Slab allocator. + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 27/12/01 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* TYPES ********************************************************************/ + +typedef VOID (*SLAB_CACHE_CONSTRUCTOR)(VOID*, ULONG); +typedef VOID (*SLAB_CACHE_DESTRUCTOR)(VOID*, ULONG); + +struct _SLAB_CACHE_PAGE; + +typedef struct _SLAB_CACHE +{ + SLAB_CACHE_CONSTRUCTOR Constructor; + SLAB_CACHE_DESTRUCTOR Destructor; + ULONG BaseSize; + ULONG ObjectSize; + ULONG ObjectsPerPage; + LIST_ENTRY PageListHead; + struct _SLAB_CACHE_PAGE* FirstFreePage; + KSPIN_LOCK SlabLock; +} SLAB_CACHE, *PSLAB_CACHE; + +typedef struct _SLAB_CACHE_BUFCTL +{ + struct _SLAB_CACHE_BUFCTL* NextFree; +} SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL; + +typedef struct _SLAB_CACHE_PAGE +{ + LIST_ENTRY PageListEntry; + PSLAB_CACHE_BUFCTL FirstFreeBuffer; + ULONG ReferenceCount; +} SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE; + +/* GLOBALS ******************************************************************/ + +/* FUNCTIONS ****************************************************************/ + +PSLAB_CACHE +ExCreateSlabCache(PUNICODE_STRING Name, ULONG Size, ULONG Align, + SLAB_CACHE_CONSTRUCTOR Constructor, + SLAB_CACHE_DESTRUCTOR Destructor) +{ + PSLAB_CACHE Slab; + ULONG ObjectSize; + ULONG AlignSize; + + Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE)); + if (Slab == NULL) + { + return(NULL); + } + + Slab->Constructor = Constructor; + Slab->Destructor = Destructor; + Slab->BaseSize = Size; + ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL); + AlignSize = Align - (ObjectSize % Align); + Slab->ObjectSize = ObjectSize + AlignSize; + Slab->ObjectsPerPage = + (PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize; + InitializeListHead(&Slab->PageListHead); + KeInitializeSpinLock(&Slab->SlabLock); + + return(Slab); +} + +PSLAB_CACHE_PAGE +ExGrowSlabCache(PSLAB_CACHE Slab) +{ + PSLAB_CACHE_PAGE SlabPage; + PHYSICAL_ADDRESS PhysicalPage; + PVOID Page; + NTSTATUS Status; + ULONG i; + PSLAB_CACHE_BUFCTL BufCtl; + PVOID Object; + + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &PhysicalPage); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + + Page = ExAllocatePageWithPhysPage(PhysicalPage); + if (Page == NULL) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage); + return(NULL); + } + + SlabPage = (PSLAB_CACHE_PAGE)(Page + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)); + SlabPage->ReferenceCount = 0; + SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page; + for (i = 0; i < Slab->ObjectsPerPage; i++) + { + BufCtl = (PSLAB_CACHE_BUFCTL)(Page + (i * Slab->ObjectSize)); + Object = (PVOID)(BufCtl + 1); + if (Slab->Constructor != NULL) + { + Slab->Constructor(Object, Slab->BaseSize); + } + if (i == (Slab->ObjectsPerPage - 1)) + { + BufCtl->NextFree = + (PSLAB_CACHE_BUFCTL)(Page + ((i + 1) * Slab->ObjectSize)); + } + else + { + BufCtl->NextFree = NULL; + } + } + + return(SlabPage); +} + +PVOID +ExAllocateSlabCache(PSLAB_CACHE Slab, BOOLEAN MayWait) +{ + KIRQL oldIrql; + PSLAB_CACHE_PAGE Page; + PVOID Object; + BOOLEAN NewPage; + + KeAcquireSpinLock(&Slab->SlabLock, &oldIrql); + + /* + * Check if there is a page with free objects + * present, if so allocate from it, if + * not grow the slab. + */ + if (Slab->FirstFreePage == NULL) + { + KeReleaseSpinLock(&Slab->SlabLock, oldIrql); + Page = ExGrowSlabCache(Slab); + NewPage = TRUE; + KeAcquireSpinLock(&Slab->SlabLock, &oldIrql); + } + else + { + Page = Slab->FirstFreePage; + NewPage = FALSE; + } + + /* + * We shouldn't have got a page without free buffers. + */ + if (Page->FirstFreeBuffer == NULL) + { + DPRINT1("First free page had no free buffers.\n"); + KeBugCheck(0); + } + + /* + * Allocate the first free object from the page. + */ + Object = (PVOID)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL); + Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree; + Page->ReferenceCount++; + + /* + * If we just allocated all the objects from this page + * and it was the first free page then adjust the + * first free page pointer and move the page to the head + * of the list. + */ + if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage) + { + if (Page->PageListEntry.Flink == &Slab->PageListHead) + { + Slab->FirstFreePage = NULL; + } + else + { + PSLAB_CACHE_PAGE NextPage; + + NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink, + SLAB_CACHE_PAGE, + PageListEntry); + Slab->FirstFreePage = NextPage; + } + RemoveEntryList(&Page->PageListEntry); + InsertHeadList(&Slab->PageListHead, &Page->PageListEntry); + } + /* + * Otherwise if we created a new page then add it to the end of + * the page list. + */ + else if (NewPage) + { + InsertTailList(&Slab->PageListHead, &Page->PageListEntry); + if (Slab->FirstFreePage == NULL) + { + Slab->FirstFreePage = Page; + } + } + KeReleaseSpinLock(&Slab->SlabLock, oldIrql); + return(Object); +} + +VOID +ExFreeFromPageSlabCache(PSLAB_CACHE Slab, + PSLAB_CACHE_PAGE Page, + PVOID Object) +{ + PSLAB_CACHE_BUFCTL BufCtl; + + BufCtl = (PSLAB_CACHE_BUFCTL)(Object - sizeof(SLAB_CACHE_BUFCTL)); + BufCtl->NextFree = Page->FirstFreeBuffer; + Page->FirstFreeBuffer = BufCtl; + Page->ReferenceCount--; +} + +VOID +ExFreeSlabCache(PSLAB_CACHE Slab, PVOID Object) +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PSLAB_CACHE_PAGE current; + + KeAcquireSpinLock(&Slab->SlabLock, &oldIrql); + current_entry = Slab->PageListHead.Flink; + while (current_entry != &Slab->PageListHead) + { + PVOID Base; + + current = CONTAINING_RECORD(current_entry, + SLAB_CACHE_PAGE, + PageListEntry); + Base = (PVOID)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE; + if (Base >= Object && + (Base + PAGE_SIZE - sizeof(SLAB_CACHE_PAGE)) >= + (Object + Slab->ObjectSize)) + { + ExFreeFromPageSlabCache(Slab, current, Object); + /* + * If the page just become free then rearrange things. + */ + if (current->ReferenceCount == 0) + { + RemoveEntryList(¤t->PageListEntry); + InsertTailList(&Slab->PageListHead, ¤t->PageListEntry); + if (Slab->FirstFreePage == NULL) + { + Slab->FirstFreePage = current; + } + } + KeReleaseSpinLock(&Slab->SlabLock, oldIrql); + return; + } + } + DPRINT1("Tried to free object not in cache.\n"); + KeBugCheck(0); +} + +VOID +ExDestroySlabCache(PSLAB_CACHE Slab) +{ + PLIST_ENTRY current_entry; + PSLAB_CACHE_PAGE current; + ULONG i; + PVOID Object; + + current_entry = Slab->PageListHead.Flink; + while (current_entry != &Slab->PageListHead) + { + PVOID Base; + PHYSICAL_ADDRESS PhysicalPage; + + current = CONTAINING_RECORD(current_entry, + SLAB_CACHE_PAGE, + PageListEntry); + Base = (PVOID)current + sizeof(SLAB_CACHE_PAGE) - PAGE_SIZE; + if (Slab->Destructor != NULL) + { + for (i = 0; i < Slab->ObjectsPerPage; i++) + { + Object = Base + (i * Slab->ObjectSize) + + sizeof(SLAB_CACHE_BUFCTL); + Slab->Destructor(Object, Slab->BaseSize); + } + } + PhysicalPage = MmGetPhysicalAddressForProcess(NULL, Base); + ExUnmapPage(Base); + MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage); + } + ExFreePool(Slab); +} diff --git a/ntoskrnl/mm/virtual.c b/ntoskrnl/mm/virtual.c new file mode 100644 index 0000000..ad02cb9 --- /dev/null +++ b/ntoskrnl/mm/virtual.c @@ -0,0 +1,362 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/virtual.c + * PURPOSE: Implementing operations on virtual memory. + * PROGRAMMER: David Welch + */ + +/* INCLUDE *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtFlushVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToFlush, + OUT PULONG NumberOfBytesFlushed OPTIONAL) +/* + * FUNCTION: Flushes virtual memory to file + * ARGUMENTS: + * ProcessHandle = Points to the process that allocated the virtual + * memory + * BaseAddress = Points to the memory address + * NumberOfBytesToFlush = Limits the range to flush, + * NumberOfBytesFlushed = Actual number of bytes flushed + * RETURNS: Status + */ +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +NtLockVirtualMemory(HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToLock, + PULONG NumberOfBytesLocked) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +NtQueryVirtualMemory (IN HANDLE ProcessHandle, + IN PVOID Address, + IN CINT VirtualMemoryInformationClass, + OUT PVOID VirtualMemoryInformation, + IN ULONG Length, + OUT PULONG UnsafeResultLength) +{ + NTSTATUS Status; + PEPROCESS Process; + MEMORY_AREA* MemoryArea; + ULONG ResultLength = 0; + PMADDRESS_SPACE AddressSpace; + + DPRINT("NtQueryVirtualMemory(ProcessHandle %x, Address %x, " + "VirtualMemoryInformationClass %d, VirtualMemoryInformation %x, " + "Length %lu ResultLength %x)\n",ProcessHandle,Address, + VirtualMemoryInformationClass,VirtualMemoryInformation, + Length,ResultLength); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_QUERY_INFORMATION, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT("NtQueryVirtualMemory() = %x\n",Status); + return(Status); + } + + AddressSpace = &Process->AddressSpace; + MmLockAddressSpace(AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, + Address); + switch(VirtualMemoryInformationClass) + { + case MemoryBasicInformation: + { + PMEMORY_BASIC_INFORMATION Info = + (PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation; + + if (Length != sizeof(MEMORY_BASIC_INFORMATION)) + { + ObDereferenceObject(Process); + return(STATUS_INFO_LENGTH_MISMATCH); + } + + if (MemoryArea == NULL) + { + Info->State = MEM_FREE; + Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address); + Status = STATUS_SUCCESS; + ResultLength = sizeof(MEMORY_BASIC_INFORMATION); + } + else if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY) + { + Status = MmQueryAnonMem(MemoryArea, Address, Info, + &ResultLength); + } + else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) + { + Status = MmQuerySectionView(MemoryArea, Address, Info, + &ResultLength); + } + else + { + Status = STATUS_UNSUCCESSFUL; + ResultLength = 0; + } + break; + } + + default: + { + Status = STATUS_INVALID_INFO_CLASS; + ResultLength = 0; + break; + } + } + + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + if (UnsafeResultLength != NULL) + { + MmCopyToCaller(UnsafeResultLength, &ResultLength, sizeof(ULONG)); + } + return(Status); +} + +NTSTATUS STDCALL +NtProtectVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN ULONG NumberOfBytesToProtect, + IN ULONG NewAccessProtection, + OUT PULONG UnsafeOldAccessProtection) +{ + PMEMORY_AREA MemoryArea; + PEPROCESS Process; + NTSTATUS Status; + PMADDRESS_SPACE AddressSpace; + ULONG OldAccessProtection; + + NumberOfBytesToProtect = + PAGE_ROUND_UP(BaseAddress + NumberOfBytesToProtect) - + PAGE_ROUND_DOWN(BaseAddress); + BaseAddress = (PVOID)PAGE_ROUND_DOWN(BaseAddress); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_OPERATION, + PsProcessType, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + DPRINT("NtProtectVirtualMemory() = %x\n",Status); + return(Status); + } + + AddressSpace = &Process->AddressSpace; + + MmLockAddressSpace(AddressSpace); + MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace, + BaseAddress); + if (MemoryArea == NULL) + { + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + return(STATUS_UNSUCCESSFUL); + } + + if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY) + { + Status = MmProtectAnonMem(AddressSpace, MemoryArea, BaseAddress, + NumberOfBytesToProtect, NewAccessProtection, + &OldAccessProtection); + } + else if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) + { + Status = MmProtectSectionView(AddressSpace, MemoryArea, BaseAddress, + NumberOfBytesToProtect, + NewAccessProtection, + &OldAccessProtection); + } + + MmUnlockAddressSpace(AddressSpace); + ObDereferenceObject(Process); + + MmCopyToCaller(UnsafeOldAccessProtection, &OldAccessProtection, + sizeof(ULONG)); + + return(Status); +} + +NTSTATUS STDCALL +NtReadVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + OUT PVOID Buffer, + IN ULONG NumberOfBytesToRead, + OUT PULONG NumberOfBytesRead) +{ + NTSTATUS Status; + PMDL Mdl; + PVOID SystemAddress; + PEPROCESS Process; + + DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, " + "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress, + Buffer,NumberOfBytesToRead); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_WRITE, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + Mdl = MmCreateMdl(NULL, + Buffer, + NumberOfBytesToRead); + MmProbeAndLockPages(Mdl, + UserMode, + IoWriteAccess); + + KeAttachProcess(Process); + + SystemAddress = MmGetSystemAddressForMdl(Mdl); + memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead); + + KeDetachProcess(); + + if (Mdl->MappedSystemVa != NULL) + { + MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); + } + MmUnlockPages(Mdl); + ExFreePool(Mdl); + + ObDereferenceObject(Process); + + *NumberOfBytesRead = NumberOfBytesToRead; + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtUnlockVirtualMemory(HANDLE ProcessHandle, + PVOID BaseAddress, + ULONG NumberOfBytesToUnlock, + PULONG NumberOfBytesUnlocked OPTIONAL) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtWriteVirtualMemory(IN HANDLE ProcessHandle, + IN PVOID BaseAddress, + IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, + OUT PULONG NumberOfBytesWritten) +{ + NTSTATUS Status; + PMDL Mdl; + PVOID SystemAddress; + PEPROCESS Process; + + DPRINT("NtWriteVirtualMemory(ProcessHandle %x, BaseAddress %x, " + "Buffer %x, NumberOfBytesToWrite %d)\n",ProcessHandle,BaseAddress, + Buffer,NumberOfBytesToWrite); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_VM_WRITE, + NULL, + UserMode, + (PVOID*)(&Process), + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + Mdl = MmCreateMdl(NULL, + Buffer, + NumberOfBytesToWrite); + MmProbeAndLockPages(Mdl, + UserMode, + IoReadAccess); + + KeAttachProcess(Process); + + SystemAddress = MmGetSystemAddressForMdl(Mdl); + memcpy(BaseAddress, SystemAddress, NumberOfBytesToWrite); + + KeDetachProcess(); + + ObDereferenceObject(Process); + + if (Mdl->MappedSystemVa != NULL) + { + MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl); + } + MmUnlockPages(Mdl); + ExFreePool(Mdl); + + *NumberOfBytesWritten = NumberOfBytesToWrite; + + return(STATUS_SUCCESS); +} + +DWORD STDCALL +MmSecureVirtualMemory (DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + return 0; +} + + +VOID STDCALL +MmUnsecureVirtualMemory (DWORD Unknown0) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/mm/wset.c b/ntoskrnl/mm/wset.c new file mode 100644 index 0000000..dc42ca0 --- /dev/null +++ b/ntoskrnl/mm/wset.c @@ -0,0 +1,66 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/wset.c + * PURPOSE: Manages working sets + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages) +{ + PHYSICAL_ADDRESS CurrentPhysicalAddress; + PHYSICAL_ADDRESS NextPhysicalAddress; + NTSTATUS Status; + + (*NrFreedPages) = 0; + + CurrentPhysicalAddress = MmGetLRUFirstUserPage(); + while (CurrentPhysicalAddress.QuadPart != 0 && Target > 0) + { + NextPhysicalAddress = MmGetLRUNextUserPage(CurrentPhysicalAddress); + + Status = MmPageOutPhysicalAddress(CurrentPhysicalAddress); + if (NT_SUCCESS(Status)) + { + DPRINT("Succeeded\n"); + Target--; + (*NrFreedPages)++; + } + + CurrentPhysicalAddress = NextPhysicalAddress; + } + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/nls/.cvsignore b/ntoskrnl/nls/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/nls/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/nls/nls.c b/ntoskrnl/nls/nls.c new file mode 100644 index 0000000..27fec4e --- /dev/null +++ b/ntoskrnl/nls/nls.c @@ -0,0 +1,21 @@ +/* $Id$ + * + * reactos/ntoskrnl/nls/nls.c + */ +#include + +#if 0 +BYTE +NlsLeadByteInfo = 0; /* ? */ + +BOOLEAN /* USHORT? */ +NlsMbCodePageTag = 0; + +USHORT +NlsOemLeadByteInfo = 0; + +USHORT +NlsAnsiCodePage = 0; +#endif + +/* EOF */ diff --git a/ntoskrnl/nt/.cvsignore b/ntoskrnl/nt/.cvsignore new file mode 100644 index 0000000..5c508bb --- /dev/null +++ b/ntoskrnl/nt/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +zw.c diff --git a/ntoskrnl/nt/channel.c b/ntoskrnl/nt/channel.c new file mode 100644 index 0000000..cb67dc2 --- /dev/null +++ b/ntoskrnl/nt/channel.c @@ -0,0 +1,73 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/channel.c + * PURPOSE: Channels (??) + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* + * NOTES: + * + * An article on System Internals (http://www.sysinternals.com) reports + * that these functions are unimplemented on nt version 3-5. + * + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +NtCreateChannel(VOID) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtListenChannel(VOID) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +STDCALL +NtOpenChannel(VOID) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtReplyWaitSendChannel(VOID) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtSendWaitReplyChannel(VOID) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +STDCALL +NtSetContextChannel(VOID) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/nt/evtpair.c b/ntoskrnl/nt/evtpair.c new file mode 100644 index 0000000..d320bfb --- /dev/null +++ b/ntoskrnl/nt/evtpair.c @@ -0,0 +1,304 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/evtpair.c + * PURPOSE: Support for event pairs + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL; + +static GENERIC_MAPPING ExEventPairMapping = { + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, + EVENT_PAIR_ALL_ACCESS}; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtpCreateEventPair(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + +VOID NtInitializeEventPairImplementation(VOID) +{ + ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair"); + + ExEventPairObjectType->MaxObjects = ULONG_MAX; + ExEventPairObjectType->MaxHandles = ULONG_MAX; + ExEventPairObjectType->TotalObjects = 0; + ExEventPairObjectType->TotalHandles = 0; + ExEventPairObjectType->PagedPoolCharge = 0; + ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR); + ExEventPairObjectType->Mapping = &ExEventPairMapping; + ExEventPairObjectType->Dump = NULL; + ExEventPairObjectType->Open = NULL; + ExEventPairObjectType->Close = NULL; + ExEventPairObjectType->Delete = NULL; + ExEventPairObjectType->Parse = NULL; + ExEventPairObjectType->Security = NULL; + ExEventPairObjectType->QueryName = NULL; + ExEventPairObjectType->OkayToClose = NULL; + ExEventPairObjectType->Create = NtpCreateEventPair; + ExEventPairObjectType->DuplicationNotify = NULL; +} + + +NTSTATUS STDCALL +NtCreateEventPair(OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtCreateEventPair()\n"); + Status = ObCreateObject(EventPairHandle, + DesiredAccess, + ObjectAttributes, + ExEventPairObjectType, + (PVOID*)&EventPair); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeInitializeEvent(&EventPair->LowEvent, + SynchronizationEvent, + FALSE); + KeInitializeEvent(&EventPair->HighEvent, + SynchronizationEvent, + FALSE); + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtOpenEventPair(OUT PHANDLE EventPairHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + NTSTATUS Status; + + DPRINT("NtOpenEventPair()\n"); + + Status = ObOpenObjectByName(ObjectAttributes, + ExEventPairObjectType, + NULL, + UserMode, + DesiredAccess, + NULL, + EventPairHandle); + + return Status; +} + + +NTSTATUS STDCALL +NtSetHighEventPair(IN HANDLE EventPairHandle) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", + EventPairHandle); + + Status = ObReferenceObjectByHandle(EventPairHandle, + EVENT_PAIR_ALL_ACCESS, + ExEventPairObjectType, + UserMode, + (PVOID*)&EventPair, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + KeSetEvent(&EventPair->HighEvent, + EVENT_INCREMENT, + FALSE); + + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", + EventPairHandle); + + Status = ObReferenceObjectByHandle(EventPairHandle, + EVENT_PAIR_ALL_ACCESS, + ExEventPairObjectType, + UserMode, + (PVOID*)&EventPair, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + KeSetEvent(&EventPair->HighEvent, + EVENT_INCREMENT, + FALSE); + + KeWaitForSingleObject(&EventPair->LowEvent, + WrEventPair, + UserMode, + FALSE, + NULL); + + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetLowEventPair(IN HANDLE EventPairHandle) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtSetLowEventPair(EventPairHandle %x)\n", + EventPairHandle); + + Status = ObReferenceObjectByHandle(EventPairHandle, + EVENT_PAIR_ALL_ACCESS, + ExEventPairObjectType, + UserMode, + (PVOID*)&EventPair, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + KeSetEvent(&EventPair->LowEvent, + EVENT_INCREMENT, + FALSE); + + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n", + EventPairHandle); + + Status = ObReferenceObjectByHandle(EventPairHandle, + EVENT_PAIR_ALL_ACCESS, + ExEventPairObjectType, + UserMode, + (PVOID*)&EventPair, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + KeSetEvent(&EventPair->LowEvent, + EVENT_INCREMENT, + FALSE); + + KeWaitForSingleObject(&EventPair->HighEvent, + WrEventPair, + UserMode, + FALSE, + NULL); + + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtWaitLowEventPair(IN HANDLE EventPairHandle) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n", + EventPairHandle); + + Status = ObReferenceObjectByHandle(EventPairHandle, + EVENT_PAIR_ALL_ACCESS, + ExEventPairObjectType, + UserMode, + (PVOID*)&EventPair, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + KeWaitForSingleObject(&EventPair->LowEvent, + WrEventPair, + UserMode, + FALSE, + NULL); + + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtWaitHighEventPair(IN HANDLE EventPairHandle) +{ + PKEVENT_PAIR EventPair; + NTSTATUS Status; + + DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n", + EventPairHandle); + + Status = ObReferenceObjectByHandle(EventPairHandle, + EVENT_PAIR_ALL_ACCESS, + ExEventPairObjectType, + UserMode, + (PVOID*)&EventPair, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + KeWaitForSingleObject(&EventPair->HighEvent, + WrEventPair, + UserMode, + FALSE, + NULL); + + ObDereferenceObject(EventPair); + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/nt/misc.c b/ntoskrnl/nt/misc.c new file mode 100644 index 0000000..41d6af4 --- /dev/null +++ b/ntoskrnl/nt/misc.c @@ -0,0 +1,34 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/misc.c + * PURPOSE: Misc undocumented system calls + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +NtDisplayString(IN PUNICODE_STRING DisplayString) +{ + ANSI_STRING AnsiString; + + RtlUnicodeStringToAnsiString (&AnsiString, DisplayString, TRUE); + + HalDisplayString (AnsiString.Buffer); + + RtlFreeAnsiString (&AnsiString); + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/nt/mutant.c b/ntoskrnl/nt/mutant.c new file mode 100644 index 0000000..2f1f627 --- /dev/null +++ b/ntoskrnl/nt/mutant.c @@ -0,0 +1,221 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/mutant.c + * PURPOSE: Synchronization primitives + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +POBJECT_TYPE ExMutantObjectType = NULL; + +static GENERIC_MAPPING ExpMutantMapping = { + STANDARD_RIGHTS_READ | SYNCHRONIZE | MUTANT_QUERY_STATE, + STANDARD_RIGHTS_WRITE | SYNCHRONIZE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | MUTANT_QUERY_STATE, + MUTANT_ALL_ACCESS}; + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS STDCALL +NtpCreateMutant(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateMutant(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +NtpDeleteMutant(PVOID ObjectBody) +{ + DPRINT("NtpDeleteMutant(ObjectBody %x)\n", ObjectBody); + + KeReleaseMutant((PKMUTANT)ObjectBody, + MUTANT_INCREMENT, + TRUE, + FALSE); +} + + +VOID +NtInitializeMutantImplementation(VOID) +{ + ExMutantObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExMutantObjectType->TypeName, L"Mutant"); + + ExMutantObjectType->Tag = TAG('M', 'T', 'N', 'T'); + ExMutantObjectType->MaxObjects = ULONG_MAX; + ExMutantObjectType->MaxHandles = ULONG_MAX; + ExMutantObjectType->TotalObjects = 0; + ExMutantObjectType->TotalHandles = 0; + ExMutantObjectType->PagedPoolCharge = 0; + ExMutantObjectType->NonpagedPoolCharge = sizeof(KMUTANT); + ExMutantObjectType->Mapping = &ExpMutantMapping; + ExMutantObjectType->Dump = NULL; + ExMutantObjectType->Open = NULL; + ExMutantObjectType->Close = NULL; + ExMutantObjectType->Delete = NtpDeleteMutant; + ExMutantObjectType->Parse = NULL; + ExMutantObjectType->Security = NULL; + ExMutantObjectType->QueryName = NULL; + ExMutantObjectType->OkayToClose = NULL; + ExMutantObjectType->Create = NtpCreateMutant; + ExMutantObjectType->DuplicationNotify = NULL; +} + + +NTSTATUS STDCALL +NtCreateMutant(OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN BOOLEAN InitialOwner) +{ + PKMUTEX Mutant; + NTSTATUS Status; + + Status = ObCreateObject(MutantHandle, + DesiredAccess, + ObjectAttributes, + ExMutantObjectType, + (PVOID*)&Mutant); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeInitializeMutant(Mutant, + InitialOwner); + ObDereferenceObject(Mutant); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtOpenMutant(OUT PHANDLE MutantHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + return(ObOpenObjectByName(ObjectAttributes, + ExMutantObjectType, + NULL, + ExGetPreviousMode(), + DesiredAccess, + NULL, + MutantHandle)); +} + + +NTSTATUS STDCALL +NtQueryMutant(IN HANDLE MutantHandle, + IN CINT MutantInformationClass, + OUT PVOID MutantInformation, + IN ULONG Length, + OUT PULONG ResultLength) +{ + PMUTANT_BASIC_INFORMATION Info; + PKMUTANT Mutant; + NTSTATUS Status; + + Info = (PMUTANT_BASIC_INFORMATION)MutantInformation; + + if (MutantInformationClass > MutantBasicInformation) + return(STATUS_INVALID_INFO_CLASS); + + if (Length < sizeof(MUTANT_BASIC_INFORMATION)) + return(STATUS_INFO_LENGTH_MISMATCH); + + Status = ObReferenceObjectByHandle(MutantHandle, + MUTANT_QUERY_STATE, + ExMutantObjectType, + ExGetPreviousMode(), + (PVOID*)&Mutant, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Info->Count = KeReadStateMutant(Mutant); + Info->Owned = (Mutant->OwnerThread != NULL); + Info->Abandoned = Mutant->Abandoned; + + ObDereferenceObject(Mutant); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtReleaseMutant(IN HANDLE MutantHandle, + IN PULONG ReleaseCount OPTIONAL) +{ + PKMUTANT Mutant; + NTSTATUS Status; + ULONG Count; + + Status = ObReferenceObjectByHandle(MutantHandle, + MUTANT_ALL_ACCESS, + ExMutantObjectType, + ExGetPreviousMode(), + (PVOID*)&Mutant, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Count = KeReleaseMutant(Mutant, + MUTANT_INCREMENT, + 0, + FALSE); + ObDereferenceObject(Mutant); + + if (ReleaseCount != NULL) + { + *ReleaseCount = Count; + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/nt/nt.c b/ntoskrnl/nt/nt.c new file mode 100644 index 0000000..e70b9e8 --- /dev/null +++ b/ntoskrnl/nt/nt.c @@ -0,0 +1,32 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/nt.c + * PURPOSE: Initialization of system call interfaces + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID NtInit(VOID) +{ + NtInitializeEventImplementation(); + NtInitializeEventPairImplementation(); + NtInitializeMutantImplementation(); + NtInitializeSemaphoreImplementation(); + NtInitializeTimerImplementation(); + NiInitPort(); + NtInitializeProfileImplementation(); +} + +/* EOF */ diff --git a/ntoskrnl/nt/ntevent.c b/ntoskrnl/nt/ntevent.c new file mode 100644 index 0000000..496bc62 --- /dev/null +++ b/ntoskrnl/nt/ntevent.c @@ -0,0 +1,334 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/event.c + * PURPOSE: Named event support + * PROGRAMMER: Philip Susi and David Welch + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE EXPORTED ExEventObjectType = NULL; + +static GENERIC_MAPPING ExpEventMapping = { + STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE, + STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE, + EVENT_ALL_ACCESS}; + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtpCreateEvent(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID +NtInitializeEventImplementation(VOID) +{ + ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExEventObjectType->TypeName, L"Event"); + + ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T'); + ExEventObjectType->MaxObjects = ULONG_MAX; + ExEventObjectType->MaxHandles = ULONG_MAX; + ExEventObjectType->TotalObjects = 0; + ExEventObjectType->TotalHandles = 0; + ExEventObjectType->PagedPoolCharge = 0; + ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT); + ExEventObjectType->Mapping = &ExpEventMapping; + ExEventObjectType->Dump = NULL; + ExEventObjectType->Open = NULL; + ExEventObjectType->Close = NULL; + ExEventObjectType->Delete = NULL; + ExEventObjectType->Parse = NULL; + ExEventObjectType->Security = NULL; + ExEventObjectType->QueryName = NULL; + ExEventObjectType->OkayToClose = NULL; + ExEventObjectType->Create = NtpCreateEvent; + ExEventObjectType->DuplicationNotify = NULL; +} + + +NTSTATUS STDCALL +NtClearEvent(IN HANDLE EventHandle) +{ + PKEVENT Event; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeClearEvent(Event); + ObDereferenceObject(Event); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtCreateEvent(OUT PHANDLE UnsafeEventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES UnsafeObjectAttributes, + IN BOOLEAN ManualReset, + IN BOOLEAN InitialState) +{ + PKEVENT Event; + HANDLE EventHandle; + NTSTATUS Status; + OBJECT_ATTRIBUTES SafeObjectAttributes; + POBJECT_ATTRIBUTES ObjectAttributes; + + if (UnsafeObjectAttributes != NULL) + { + Status = MmCopyFromCaller(&SafeObjectAttributes, UnsafeObjectAttributes, + sizeof(OBJECT_ATTRIBUTES)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + ObjectAttributes = &SafeObjectAttributes; + } + else + { + ObjectAttributes = NULL; + } + + Status = ObCreateObject(&EventHandle, + DesiredAccess, + ObjectAttributes, + ExEventObjectType, + (PVOID*)&Event); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeInitializeEvent(Event, + ManualReset ? NotificationEvent : SynchronizationEvent, + InitialState); + ObDereferenceObject(Event); + + Status = MmCopyToCaller(UnsafeEventHandle, &EventHandle, sizeof(HANDLE)); + if (!NT_SUCCESS(Status)) + { + ZwClose(EventHandle); + return(Status); + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtOpenEvent(OUT PHANDLE UnsafeEventHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + NTSTATUS Status; + HANDLE EventHandle; + + DPRINT("ObjectName '%wZ'\n", ObjectAttributes->ObjectName); + + Status = ObOpenObjectByName(ObjectAttributes, + ExEventObjectType, + NULL, + UserMode, + DesiredAccess, + NULL, + &EventHandle); + + Status = MmCopyToCaller(UnsafeEventHandle, &EventHandle, sizeof(HANDLE)); + if (!NT_SUCCESS(Status)) + { + ZwClose(EventHandle); + return(Status); + } + + return(Status); +} + + +NTSTATUS STDCALL +NtPulseEvent(IN HANDLE EventHandle, + IN PULONG UnsafePulseCount OPTIONAL) +{ + PKEVENT Event; + NTSTATUS Status; + + DPRINT("NtPulseEvent(EventHandle %x UnsafePulseCount %x)\n", + EventHandle, UnsafePulseCount); + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + KePulseEvent(Event, EVENT_INCREMENT, FALSE); + + ObDereferenceObject(Event); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtQueryEvent(IN HANDLE EventHandle, + IN EVENT_INFORMATION_CLASS EventInformationClass, + OUT PVOID UnsafeEventInformation, + IN ULONG EventInformationLength, + OUT PULONG UnsafeReturnLength) +{ + EVENT_BASIC_INFORMATION Info; + PKEVENT Event; + NTSTATUS Status; + ULONG ReturnLength; + + if (EventInformationClass > EventBasicInformation) + return STATUS_INVALID_INFO_CLASS; + + if (EventInformationLength < sizeof(EVENT_BASIC_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_QUERY_STATE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + if (Event->Header.Type == InternalNotificationEvent) + Info.EventType = NotificationEvent; + else + Info.EventType = SynchronizationEvent; + Info.EventState = KeReadStateEvent(Event); + + Status = MmCopyToCaller(UnsafeEventInformation, &Event, + sizeof(EVENT_BASIC_INFORMATION)); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Event); + return(Status); + } + + ReturnLength = sizeof(EVENT_BASIC_INFORMATION); + Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength, sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Event); + return(Status); + } + + ObDereferenceObject(Event); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtResetEvent(IN HANDLE EventHandle, + OUT PULONG UnsafeNumberOfWaitingThreads OPTIONAL) +{ + PKEVENT Event; + NTSTATUS Status; + + DPRINT("NtResetEvent(EventHandle %x)\n", EventHandle); + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeResetEvent(Event); + ObDereferenceObject(Event); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetEvent(IN HANDLE EventHandle, + OUT PULONG UnsafeNumberOfThreadsReleased) +{ + PKEVENT Event; + NTSTATUS Status; + + DPRINT("NtSetEvent(EventHandle %x)\n", EventHandle); + + Status = ObReferenceObjectByHandle(EventHandle, + EVENT_MODIFY_STATE, + ExEventObjectType, + UserMode, + (PVOID*)&Event, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeSetEvent(Event,EVENT_INCREMENT,FALSE); + ObDereferenceObject(Event); + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/nt/ntsem.c b/ntoskrnl/nt/ntsem.c new file mode 100644 index 0000000..c7ca862 --- /dev/null +++ b/ntoskrnl/nt/ntsem.c @@ -0,0 +1,188 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/ntsem.c + * PURPOSE: Synchronization primitives + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +POBJECT_TYPE ExSemaphoreType; + +static GENERIC_MAPPING ExSemaphoreMapping = { + STANDARD_RIGHTS_READ | SEMAPHORE_QUERY_STATE, + STANDARD_RIGHTS_WRITE | SEMAPHORE_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | SEMAPHORE_QUERY_STATE, + SEMAPHORE_ALL_ACCESS}; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtpCreateSemaphore(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateSemaphore(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + +VOID NtInitializeSemaphoreImplementation(VOID) +{ + ExSemaphoreType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExSemaphoreType->TypeName, L"Semaphore"); + + ExSemaphoreType->Tag = TAG('S', 'E', 'M', 'T'); + ExSemaphoreType->MaxObjects = ULONG_MAX; + ExSemaphoreType->MaxHandles = ULONG_MAX; + ExSemaphoreType->TotalObjects = 0; + ExSemaphoreType->TotalHandles = 0; + ExSemaphoreType->PagedPoolCharge = 0; + ExSemaphoreType->NonpagedPoolCharge = sizeof(KSEMAPHORE); + ExSemaphoreType->Mapping = &ExSemaphoreMapping; + ExSemaphoreType->Dump = NULL; + ExSemaphoreType->Open = NULL; + ExSemaphoreType->Close = NULL; + ExSemaphoreType->Delete = NULL; + ExSemaphoreType->Parse = NULL; + ExSemaphoreType->Security = NULL; + ExSemaphoreType->QueryName = NULL; + ExSemaphoreType->OkayToClose = NULL; + ExSemaphoreType->Create = NtpCreateSemaphore; + ExSemaphoreType->DuplicationNotify = NULL; +} + +NTSTATUS STDCALL +NtCreateSemaphore(OUT PHANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN LONG InitialCount, + IN LONG MaximumCount) +{ + PKSEMAPHORE Semaphore; + NTSTATUS Status; + + Status = ObCreateObject(SemaphoreHandle, + DesiredAccess, + ObjectAttributes, + ExSemaphoreType, + (PVOID*)&Semaphore); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeInitializeSemaphore(Semaphore, + InitialCount, + MaximumCount); + ObDereferenceObject(Semaphore); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtOpenSemaphore(IN HANDLE SemaphoreHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + NTSTATUS Status; + + Status = ObOpenObjectByName(ObjectAttributes, + ExSemaphoreType, + NULL, + UserMode, + DesiredAccess, + NULL, + SemaphoreHandle); + + return Status; +} + + +NTSTATUS STDCALL +NtQuerySemaphore(IN HANDLE SemaphoreHandle, + IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, + OUT PVOID SemaphoreInformation, + IN ULONG SemaphoreInformationLength, + OUT PULONG ReturnLength) +{ + PSEMAPHORE_BASIC_INFORMATION Info; + PKSEMAPHORE Semaphore; + NTSTATUS Status; + + Info = (PSEMAPHORE_BASIC_INFORMATION)SemaphoreInformation; + + if (SemaphoreInformationClass > SemaphoreBasicInformation) + return STATUS_INVALID_INFO_CLASS; + + if (SemaphoreInformationLength < sizeof(SEMAPHORE_BASIC_INFORMATION)) + return STATUS_INFO_LENGTH_MISMATCH; + + Status = ObReferenceObjectByHandle(SemaphoreHandle, + SEMAPHORE_QUERY_STATE, + ExSemaphoreType, + UserMode, + (PVOID*)&Semaphore, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + Info->CurrentCount = KeReadStateSemaphore(Semaphore); + Info->MaximumCount = Semaphore->Limit; + + *ReturnLength = sizeof(SEMAPHORE_BASIC_INFORMATION); + + ObDereferenceObject(Semaphore); + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +NtReleaseSemaphore(IN HANDLE SemaphoreHandle, + IN LONG ReleaseCount, + OUT PLONG PreviousCount) +{ + PKSEMAPHORE Semaphore; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(SemaphoreHandle, + SEMAPHORE_MODIFY_STATE, + ExSemaphoreType, + UserMode, + (PVOID*)&Semaphore, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + KeReleaseSemaphore(Semaphore, + IO_NO_INCREMENT, + ReleaseCount, + FALSE); + ObDereferenceObject(Semaphore); + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/nt/nttimer.c b/ntoskrnl/nt/nttimer.c new file mode 100644 index 0000000..b2b3010 --- /dev/null +++ b/ntoskrnl/nt/nttimer.c @@ -0,0 +1,349 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/nttimer.c + * PURPOSE: User-mode timers + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + + +/* TYPES ********************************************************************/ + +typedef struct _NTTIMER +{ + KTIMER Timer; + KDPC Dpc; + KAPC Apc; + BOOLEAN Running; +} NTTIMER, *PNTTIMER; + + +/* GLOBALS ******************************************************************/ + +POBJECT_TYPE ExTimerType = NULL; + +static GENERIC_MAPPING ExpTimerMapping = { + STANDARD_RIGHTS_READ | TIMER_QUERY_STATE, + STANDARD_RIGHTS_WRITE | TIMER_MODIFY_STATE, + STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, + TIMER_ALL_ACCESS}; + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtpCreateTimer(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + DPRINT("NtpCreateTimer(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + return(STATUS_SUCCESS); +} + + +VOID +NtpTimerDpcRoutine(PKDPC Dpc, + PVOID DeferredContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PNTTIMER Timer; + + DPRINT("NtpTimerDpcRoutine()\n"); + + Timer = (PNTTIMER)DeferredContext; + + if ( Timer->Running ) + { + KeInsertQueueApc(&Timer->Apc, + SystemArgument1, + SystemArgument2, + KernelMode); + } +} + + +VOID +NtpTimerApcKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2) +{ + DPRINT("NtpTimerApcKernelRoutine()\n"); + +} + + +VOID NtInitializeTimerImplementation(VOID) +{ + ExTimerType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExTimerType->TypeName, L"Timer"); + + ExTimerType->Tag = TAG('T', 'I', 'M', 'T'); + ExTimerType->MaxObjects = ULONG_MAX; + ExTimerType->MaxHandles = ULONG_MAX; + ExTimerType->TotalObjects = 0; + ExTimerType->TotalHandles = 0; + ExTimerType->PagedPoolCharge = 0; + ExTimerType->NonpagedPoolCharge = sizeof(NTTIMER); + ExTimerType->Mapping = &ExpTimerMapping; + ExTimerType->Dump = NULL; + ExTimerType->Open = NULL; + ExTimerType->Close = NULL; + ExTimerType->Delete = NULL; + ExTimerType->Parse = NULL; + ExTimerType->Security = NULL; + ExTimerType->QueryName = NULL; + ExTimerType->OkayToClose = NULL; + ExTimerType->Create = NtpCreateTimer; + ExTimerType->DuplicationNotify = NULL; +} + + +NTSTATUS STDCALL +NtCancelTimer(IN HANDLE TimerHandle, + OUT PBOOLEAN CurrentState OPTIONAL) +{ + PNTTIMER Timer; + NTSTATUS Status; + BOOLEAN State; + KIRQL OldIrql; + + DPRINT("NtCancelTimer()\n"); + Status = ObReferenceObjectByHandle(TimerHandle, + TIMER_ALL_ACCESS, + ExTimerType, + UserMode, + (PVOID*)&Timer, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + OldIrql = KeRaiseIrqlToDpcLevel(); + + State = KeCancelTimer(&Timer->Timer); + KeRemoveQueueDpc(&Timer->Dpc); + KeRemoveQueueApc(&Timer->Apc); + Timer->Running = FALSE; + + KeLowerIrql(OldIrql); + ObDereferenceObject(Timer); + + if (CurrentState != NULL) + { + *CurrentState = State; + } + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +NtCreateTimer(OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN TIMER_TYPE TimerType) +{ + PNTTIMER Timer; + NTSTATUS Status; + + DPRINT("NtCreateTimer()\n"); + Status = ObCreateObject(TimerHandle, + DesiredAccess, + ObjectAttributes, + ExTimerType, + (PVOID*)&Timer); + if (!NT_SUCCESS(Status)) + return Status; + + KeInitializeTimerEx(&Timer->Timer, + TimerType); + + KeInitializeDpc (&Timer->Dpc, + (PKDEFERRED_ROUTINE)NtpTimerDpcRoutine, + (PVOID)Timer); + + Timer->Running = FALSE; + + ObDereferenceObject(Timer); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtOpenTimer(OUT PHANDLE TimerHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes) +{ + NTSTATUS Status; + + Status = ObOpenObjectByName(ObjectAttributes, + ExTimerType, + NULL, + UserMode, + DesiredAccess, + NULL, + TimerHandle); + return Status; +} + + +NTSTATUS STDCALL +NtQueryTimer(IN HANDLE TimerHandle, + IN CINT TimerInformationClass, + OUT PVOID UnsafeTimerInformation, + IN ULONG Length, + OUT PULONG UnsafeResultLength) +{ + PNTTIMER Timer; + TIMER_BASIC_INFORMATION TimerInformation; + ULONG ResultLength; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(TimerHandle, + TIMER_QUERY_STATE, + ExTimerType, + KeGetPreviousMode(), + (PVOID*)&Timer, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (TimerInformationClass != TimerBasicInformation) + { + ObDereferenceObject(Timer); + return(STATUS_INVALID_INFO_CLASS); + } + if (Length < sizeof(TIMER_BASIC_INFORMATION)) + { + ObDereferenceObject(Timer); + return(STATUS_INFO_LENGTH_MISMATCH); + } + + memcpy(&TimerInformation.TimeRemaining, &Timer->Timer.DueTime, + sizeof(LARGE_INTEGER)); + TimerInformation.SignalState = Timer->Timer.Header.SignalState; + ResultLength = sizeof(TIMER_BASIC_INFORMATION); + + Status = MmCopyToCaller(UnsafeTimerInformation, &TimerInformation, + sizeof(TIMER_BASIC_INFORMATION)); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Timer); + return(Status); + } + + if (UnsafeResultLength != NULL) + { + Status = MmCopyToCaller(UnsafeResultLength, &ResultLength, + sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Timer); + return(Status); + } + } + ObDereferenceObject(Timer); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetTimer(IN HANDLE TimerHandle, + IN PLARGE_INTEGER DueTime, + IN PTIMERAPCROUTINE TimerApcRoutine, + IN PVOID TimerContext, + IN BOOL WakeTimer, + IN ULONG Period OPTIONAL, + OUT PBOOLEAN PreviousState OPTIONAL) +{ + PNTTIMER Timer; + NTSTATUS Status; + BOOLEAN Result; + KIRQL OldIrql; + BOOLEAN State; + + DPRINT("NtSetTimer()\n"); + + Status = ObReferenceObjectByHandle(TimerHandle, + TIMER_ALL_ACCESS, + ExTimerType, + KeGetPreviousMode(), + (PVOID*)&Timer, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + State = KeReadStateTimer(&Timer->Timer); + + if (Timer->Running == TRUE) + { + /* cancel running timer */ + OldIrql = KeRaiseIrqlToDpcLevel(); + KeCancelTimer(&Timer->Timer); + KeRemoveQueueDpc(&Timer->Dpc); + KeRemoveQueueApc(&Timer->Apc); + Timer->Running = FALSE; + KeLowerIrql(OldIrql); + } + if( TimerApcRoutine ) + KeInitializeApc(&Timer->Apc, + KeGetCurrentThread(), + 0, + (PKKERNEL_ROUTINE)NtpTimerApcKernelRoutine, + (PKRUNDOWN_ROUTINE)NULL, + (PKNORMAL_ROUTINE)TimerApcRoutine, + KeGetPreviousMode(), + TimerContext); + + Result = KeSetTimerEx (&Timer->Timer, + *DueTime, + Period, + TimerApcRoutine ? &Timer->Dpc : 0 ); + if (Result == TRUE) + { + ObDereferenceObject(Timer); + DPRINT1( "KeSetTimer says the timer was already running, this shouldn't be\n" ); + return STATUS_UNSUCCESSFUL; + } + + Timer->Running = TRUE; + + ObDereferenceObject(Timer); + + if (PreviousState != NULL) + { + *PreviousState = State; + } + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/ntoskrnl/nt/plugplay.c b/ntoskrnl/nt/plugplay.c new file mode 100644 index 0000000..aae5a53 --- /dev/null +++ b/ntoskrnl/nt/plugplay.c @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/plugplay.c + * PURPOSE: Mysterious nt4 support for plug-and-play + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL NtGetPlugPlayEvent(VOID) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL NtPlugPlayControl(VOID) +{ + UNIMPLEMENTED; +} diff --git a/ntoskrnl/nt/profile.c b/ntoskrnl/nt/profile.c new file mode 100644 index 0000000..12ff554 --- /dev/null +++ b/ntoskrnl/nt/profile.c @@ -0,0 +1,576 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/profile.c + * PURPOSE: Support for profiling + * PROGRAMMER: Nobody + * UPDATE HISTORY: + * + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +/* TYPES ********************************************************************/ + +typedef struct _KPROCESS_PROFILE +/* + * List of the profile data structures associated with a process. + */ +{ + LIST_ENTRY ProfileListHead; + LIST_ENTRY ListEntry; + HANDLE Pid; +} KPROCESS_PROFILE, *PKPROCESS_PROFILE; + +typedef struct _KPROFILE +/* + * Describes a contiguous region of process memory that is being profiled. + */ +{ + CSHORT Type; + CSHORT Name; + + /* Entry in the list of profile data structures for this process. */ + LIST_ENTRY ListEntry; + + /* Base of the region being profiled. */ + PVOID Base; + + /* Size of the region being profiled. */ + ULONG Size; + + /* Shift of offsets from the region to buckets in the profiling buffer. */ + ULONG BucketShift; + + /* MDL which described the buffer that receives profiling data. */ + PMDL BufferMdl; + + /* System alias for the profiling buffer. */ + PULONG Buffer; + + /* Size of the buffer for profiling data. */ + ULONG BufferSize; + + /* + * Mask of processors for which profiling data should be collected. + * Currently unused. + */ + ULONG ProcessorMask; + + /* TRUE if profiling has been started for this region. */ + BOOLEAN Started; + + /* Pointer (and reference) to the process which is being profiled. */ + PEPROCESS Process; +} KPROFILE, *PKPROFILE; + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE EXPORTED ExProfileObjectType = NULL; + +static GENERIC_MAPPING ExpProfileMapping = { + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE, + STANDARD_RIGHTS_EXECUTE, + STANDARD_RIGHTS_ALL}; + +/* + * Size of the profile hash table. + */ +#define PROFILE_HASH_TABLE_SIZE (32) + +/* + * Table of lists of per-process profiling data structures hashed by PID. + */ +static LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE]; + +/* + * Head of the list of profile data structures for the kernel. + */ +static LIST_ENTRY SystemProfileList; + +/* + * Lock that protects the profiling data structures. + */ +static KSPIN_LOCK ProfileListLock; + +/* + * Timer interrupts happen before we have initialized the profiling + * data structures so just ignore them before that. + */ +static BOOLEAN ProfileInitDone = FALSE; + +/* FUNCTIONS *****************************************************************/ + +VOID STATIC +KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip) + /* + * Add a profile event to the profile objects for a particular process + * or the system + */ +{ + PKPROFILE current; + PLIST_ENTRY current_entry; + + current_entry = ListHead->Flink; + while (current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); + + if (current->Base > Eip) + { + return; + } + + if (current->Base <= Eip && (current->Base + current->Size) > Eip && + current->Started) + { + ULONG Bucket; + + Bucket = ((ULONG)(Eip - current->Base)) >> current->BucketShift; + + if ((Bucket*4) < current->BufferSize) + { + current->Buffer[Bucket]++; + } + } + + current_entry = current_entry->Flink; + } +} + +VOID +KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip) + /* + * Add a profile event + */ +{ + HANDLE Pid; + PKPROCESS_PROFILE current; + PLIST_ENTRY current_entry; + PLIST_ENTRY ListHead; + + if (!ProfileInitDone) + { + return; + } + + Pid = PsGetCurrentProcessId(); + ListHead = + ProcessProfileListHashTable[(ULONG)Pid % PROFILE_HASH_TABLE_SIZE].Flink; + + KeAcquireSpinLockAtDpcLevel(&ProfileListLock); + + current_entry = ListHead; + while (current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, ListEntry); + + if (current->Pid == Pid) + { + KiAddProfileEventToProcess(¤t->ProfileListHead, (PVOID)Eip); + break; + } + + current_entry = current_entry->Flink; + } + + KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip); + + KeReleaseSpinLockFromDpcLevel(&ProfileListLock); +} + +VOID +KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile) + /* + * Insert a profile object into the list for a process or the system + */ +{ + PKPROFILE current; + PLIST_ENTRY current_entry; + + current_entry = ListHead; + while (current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); + + if (current->Base > Profile->Base) + { + Profile->ListEntry.Flink = current_entry; + Profile->ListEntry.Blink = current_entry->Blink; + current_entry->Blink->Flink = &Profile->ListEntry; + current_entry->Blink = &Profile->ListEntry; + return; + } + + current_entry = current_entry->Flink; + } + InsertTailList(ListHead, &Profile->ListEntry); +} + +VOID +KiInsertProfile(PKPROFILE Profile) + /* + * Insert a profile into the relevant data structures + */ +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&ProfileListLock, &oldIrql); + + if (Profile->Process == NULL) + { + KiInsertProfileIntoProcess(&SystemProfileList, Profile); + } + else + { + ULONG Pid; + PKPROCESS_PROFILE current; + PLIST_ENTRY current_entry; + PLIST_ENTRY ListHead; + + Pid = Profile->Process->UniqueProcessId; + ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE]; + + current_entry = ListHead; + while(current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, + ListEntry); + + if (current->Pid == (HANDLE)Pid) + { + KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); + KeReleaseSpinLock(&ProfileListLock, oldIrql); + return; + } + + current_entry = current_entry->Flink; + } + + current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE)); + + current->Pid = (HANDLE)Pid; + InitializeListHead(¤t->ProfileListHead); + InsertTailList(ListHead, ¤t->ListEntry); + + KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); + } + + KeReleaseSpinLock(&ProfileListLock, oldIrql); +} + +VOID KiRemoveProfile(PKPROFILE Profile) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&ProfileListLock, &oldIrql); + + if (Profile->Process == NULL) + { + RemoveEntryList(&Profile->ListEntry); + } + else + { + ULONG Pid; + PLIST_ENTRY ListHead; + PKPROCESS_PROFILE current; + PLIST_ENTRY current_entry; + + RemoveEntryList(&Profile->ListEntry); + + Pid = Profile->Process->UniqueProcessId; + ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE]; + + current_entry = ListHead; + while(current_entry != ListHead) + { + current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, + ListEntry); + + if (current->Pid == (HANDLE)Pid) + { + if (IsListEmpty(¤t->ProfileListHead)) + { + RemoveEntryList(¤t->ListEntry); + ExFreePool(current); + } + KeReleaseSpinLock(&ProfileListLock, oldIrql); + return; + } + + current_entry = current_entry->Flink; + } + KeBugCheck(0); + } + + KeReleaseSpinLock(&ProfileListLock, oldIrql); +} + +VOID STDCALL +KiDeleteProfile(PVOID ObjectBody) +{ + PKPROFILE Profile; + + Profile = (PKPROFILE)ObjectBody; + + KiRemoveProfile(Profile); + if (Profile->Process != NULL) + { + ObDereferenceObject(Profile->Process); + Profile->Process = NULL; + } + + if (Profile->BufferMdl->MappedSystemVa != NULL) + { + MmUnmapLockedPages(Profile->BufferMdl->MappedSystemVa, + Profile->BufferMdl); + } + MmUnlockPages(Profile->BufferMdl); + ExFreePool(Profile->BufferMdl); + Profile->BufferMdl = NULL; +} + +VOID +NtInitializeProfileImplementation(VOID) +{ + ULONG i; + + InitializeListHead(&SystemProfileList); + + for (i = 0; i < PROFILE_HASH_TABLE_SIZE; i++) + { + InitializeListHead(&ProcessProfileListHashTable[i]); + } + + KeInitializeSpinLock(&ProfileListLock); + ProfileInitDone = TRUE; + + ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile"); + + ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F'); + ExProfileObjectType->MaxObjects = ULONG_MAX; + ExProfileObjectType->MaxHandles = ULONG_MAX; + ExProfileObjectType->TotalObjects = 0; + ExProfileObjectType->TotalHandles = 0; + ExProfileObjectType->PagedPoolCharge = 0; + ExProfileObjectType->NonpagedPoolCharge = sizeof(KPROFILE); + ExProfileObjectType->Mapping = &ExpProfileMapping; + ExProfileObjectType->Dump = NULL; + ExProfileObjectType->Open = NULL; + ExProfileObjectType->Close = NULL; + ExProfileObjectType->Delete = KiDeleteProfile; + ExProfileObjectType->Parse = NULL; + ExProfileObjectType->Security = NULL; + ExProfileObjectType->QueryName = NULL; + ExProfileObjectType->OkayToClose = NULL; + ExProfileObjectType->Create = NULL; +} + +NTSTATUS STDCALL +NtCreateProfile(OUT PHANDLE UnsafeProfileHandle, + IN HANDLE ProcessHandle, + IN PVOID ImageBase, + IN ULONG ImageSize, + IN ULONG Granularity, + OUT PULONG Buffer, + IN ULONG BufferSize, + IN KPROFILE_SOURCE Source, + IN ULONG ProcessorMask) +{ + HANDLE ProfileHandle; + NTSTATUS Status; + PKPROFILE Profile; + PEPROCESS Process; + + /* + * Reference the associated process + */ + if (ProcessHandle != NULL) + { + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_QUERY_INFORMATION, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + else + { + Process = NULL; + /* FIXME: Check privilege. */ + } + + /* + * Check the parameters + */ + if ((Process == NULL && ImageBase < (PVOID)KERNEL_BASE) || + (Process != NULL && ImageBase >= (PVOID)KERNEL_BASE)) + { + return(STATUS_INVALID_PARAMETER_3); + } + if (((ImageSize >> Granularity) * 4) >= BufferSize) + { + return(STATUS_BUFFER_TOO_SMALL); + } + if (Source != ProfileTime) + { + return(STATUS_INVALID_PARAMETER_9); + } + if (ProcessorMask != 0) + { + return(STATUS_INVALID_PARAMETER_10); + } + + /* + * Create the object + */ + Status = ObCreateObject(&ProfileHandle, + STANDARD_RIGHTS_ALL, + NULL, + ExProfileObjectType, + (PVOID*)&Profile); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Initialize it + */ + Profile->Base = ImageBase; + Profile->Size = ImageSize; + Profile->BucketShift = Granularity; + Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize); + MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess); + Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl); + Profile->BufferSize = BufferSize; + Profile->ProcessorMask = ProcessorMask; + Profile->Started = FALSE; + Profile->Process = Process; + + /* + * Insert the profile into the profile list data structures + */ + KiInsertProfile(Profile); + + /* + * Copy the created handle back to the caller + */ + Status = MmCopyToCaller(UnsafeProfileHandle, &ProfileHandle, sizeof(HANDLE)); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Profile); + ZwClose(ProfileHandle); + return(Status); + } + + ObDereferenceObject(Profile); + + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtQueryIntervalProfile(OUT PULONG UnsafeInterval, + OUT KPROFILE_SOURCE Source) +{ + NTSTATUS Status; + + if (Source == ProfileTime) + { + ULONG Interval; + + /* FIXME: What units does this use, for now nanoseconds */ + Interval = 100; + Status = MmCopyToCaller(UnsafeInterval, &Interval, sizeof(ULONG)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + return(STATUS_SUCCESS); + } + return(STATUS_INVALID_PARAMETER_2); +} + +NTSTATUS STDCALL +NtSetIntervalProfile(IN ULONG Interval, + IN KPROFILE_SOURCE Source) +{ + return(STATUS_NOT_IMPLEMENTED); +} + +NTSTATUS STDCALL +NtStartProfile(IN HANDLE ProfileHandle) +{ + NTSTATUS Status; + PKPROFILE Profile; + + Status = ObReferenceObjectByHandle(ProfileHandle, + STANDARD_RIGHTS_ALL, + ExProfileObjectType, + UserMode, + (PVOID*)&Profile, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Profile->Started = TRUE; + ObDereferenceObject(Profile); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtStopProfile(IN HANDLE ProfileHandle) +{ + NTSTATUS Status; + PKPROFILE Profile; + + Status = ObReferenceObjectByHandle(ProfileHandle, + STANDARD_RIGHTS_ALL, + ExProfileObjectType, + UserMode, + (PVOID*)&Profile, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Profile->Started = FALSE; + ObDereferenceObject(Profile); + return(STATUS_SUCCESS); +} + + diff --git a/ntoskrnl/nt/vdm.c b/ntoskrnl/nt/vdm.c new file mode 100644 index 0000000..59630a2 --- /dev/null +++ b/ntoskrnl/nt/vdm.c @@ -0,0 +1,52 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/vdm.c + * PURPOSE: Virtual DOS machine support + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* GLOBALS *******************************************************************/ + +static UCHAR OrigIVT[1024]; +static UCHAR OrigBDA[256]; +/* static UCHAR OrigEBDA[]; */ + +/* FUNCTIONS *****************************************************************/ + +VOID +NtEarlyInitVdm(VOID) +{ + /* + * Save various BIOS data tables. At this point the lower 4MB memory + * map is still active so we can just copy the data from low memory. + */ + memcpy(OrigIVT, (PVOID)0x0, 1024); + memcpy(OrigBDA, (PVOID)0x400, 256); +} + +NTSTATUS STDCALL NtVdmControl(ULONG ControlCode, + PVOID ControlData) +{ + switch (ControlCode) + { + case 0: + memcpy(ControlData, OrigIVT, 1024); + break; + + case 1: + memcpy(ControlData, OrigBDA, 256); + break; + } + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ntoskrnl.dbg.lnk b/ntoskrnl/ntoskrnl.dbg.lnk new file mode 100644 index 0000000..7937f44 --- /dev/null +++ b/ntoskrnl/ntoskrnl.dbg.lnk @@ -0,0 +1,86 @@ +OUTPUT_FORMAT(pei-i386) +ENTRY(_mainCRTStartup) +SECTIONS +{ + /DISCARD/ : + { + *(.init) + *(.text) + *(SORT(.text$*)) + *(.glue_7t) + *(.glue_7) + *(.fini) + /* ??? Why is .gcc_exc here? */ + *(.gcc_exc) + *(.gcc_except_table) + } + /* The Cygwin32 library uses a section to avoid copying certain data + on fork. This used to be named ".data". The linker used + to include this between __data_start__ and __data_end__, but that + breaks building the cygwin32 dll. Instead, we name the section + ".data_cygwin_nocopy" and explictly include it after __data_end__. */ + /DISCARD/ : + { + *(.data) + *(.data2) + *(SORT(.data$*)) + *(.data_cygwin_nocopy) + } + /DISCARD/ : + { + *(.rdata) + *(SORT(.rdata$*)) + *(.eh_frame) + } + /DISCARD/ : + { + *(.edata) + } + /DISCARD/ : + { + *(.debug$S) + *(.debug$T) + *(.debug$F) + *(.drectve) + } + /DISCARD/ : + { + /* This cannot currently be handled with grouped sections. + See pe.em:sort_sections. */ + SORT(*)(.idata$2) + SORT(*)(.idata$3) + /* These zeroes mark the end of the import list. */ +/* LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);*/ + SORT(*)(.idata$4) + SORT(*)(.idata$5) + SORT(*)(.idata$6) + SORT(*)(.idata$7) + } + /DISCARD/ : + { + *(SORT(.CRT$*)) + } + /DISCARD/ : + { + *(.rsrc) + *(SORT(.rsrc$*)) + } + /DISCARD/ : + { + *(.bss) + *(COMMON) + } + /DISCARD/ : + { + *(.reloc) + } + .stab BLOCK(__section_alignment__) (NOLOAD) : + { + [ .stab ] + } + .stabstr BLOCK(__section_alignment__) (NOLOAD) : + { + [ .stabstr ] + } +} + diff --git a/ntoskrnl/ntoskrnl.def b/ntoskrnl/ntoskrnl.def new file mode 100644 index 0000000..685061b --- /dev/null +++ b/ntoskrnl/ntoskrnl.def @@ -0,0 +1,1059 @@ +; $Id$ +; +; reactos/ntoskrnl/ntoskrnl.def +; +; ReactOS Operating System +; +EXPORTS +CcRosInitializeFileCache@12 +;CcRosRequestCacheSegment@20 +;CcRosReleaseCacheSegment@12 +CcRosReleaseFileCache@8 +CcCopyRead@24 +CcCopyWrite@20 +CcFlushCache@16 +CcGetFileObjectFromSectionPtrs@4 +CcMapData@24 +CcMdlReadComplete@8 +CcSetDirtyPinnedData@8 +CcSetFileSizes@8 +CcUnpinData@4 +CcZeroData@16 +DbgBreakPoint@0 +DbgBreakPointWithStatus@4 +;DbgLoadImageSymbols@12 +DbgPrint +DbgPrompt@12 +DpcQueueSize DATA +@ExAcquireFastMutexUnsafe@4 +ExAcquireResourceExclusive@8 +ExAcquireResourceExclusiveLite@8 +ExAcquireResourceSharedLite@8 +ExAcquireSharedStarveExclusive@8 +ExAcquireSharedWaitForExclusive@8 +ExAllocateFromPagedLookasideList@4 +ExAllocatePool@8 +ExAllocatePoolWithQuota@8 +ExAllocatePoolWithQuotaTag@12 +ExAllocatePoolWithTag@12 +ExConvertExclusiveToSharedLite@4 +ExCreateCallback@16 +ExDeleteNPagedLookasideList@4 +ExDeletePagedLookasideList@4 +ExDeleteResource@4 +ExDeleteResourceLite@4 +ExDesktopObjectType DATA +ExDisableResourceBoostLite@4 +ExEventObjectType DATA +ExExtendZone@12 +ExFreePool@4 +ExFreeToPagedLookasideList@8 +ExGetExclusiveWaiterCount@4 +ExGetPreviousMode@0 +ExGetSharedWaiterCount@4 +ExInitializeNPagedLookasideList@28 +ExInitializePagedLookasideList@28 +ExInitializeResource@4 +ExInitializeResourceLite@4 +ExInitializeZone@16 +ExInterlockedAddLargeInteger@16 +@ExInterlockedAddLargeStatistic@8 +ExInterlockedAddUlong@12 +@ExInterlockedCompareExchange64@16 +ExInterlockedDecrementLong@8 +ExInterlockedExchangeUlong@12 +ExInterlockedExtendZone@16 +ExInterlockedIncrementLong@8 +ExInterlockedInsertHeadList@12 +ExInterlockedInsertTailList@12 +ExInterlockedPopEntryList@8 +@ExInterlockedPopEntrySList@8 +ExInterlockedPushEntryList@12 +@ExInterlockedPushEntrySList@12 +ExInterlockedRemoveHeadList@8 +ExIsProcessorFeaturePresent@4 +ExIsResourceAcquiredExclusiveLite@4 +ExIsResourceAcquiredSharedLite@4 +ExLocalTimeToSystemTime@8 +ExNotifyCallback@12 +ExPostSystemEvent@12 +;ExQueryPoolBlockSize +ExQueueWorkItem@8 +ExRaiseAccessViolation@0 +ExRaiseDatatypeMisalignment@0 +;ExRaiseException +;ExRaiseHardError +ExRaiseStatus@4 +ExRegisterCallback@12 +ExReinitializeResourceLite@4 +@ExReleaseFastMutexUnsafe@4 +ExReleaseResourceForThread@8 +ExReleaseResourceForThreadLite@8 +@ExReleaseResourceLite@4 +ExSetResourceOwnerPointer@8 +;ExSystemExceptionFilter +ExSystemTimeToLocalTime@8 +ExTryToAcquireResourceExclusiveLite@4 +ExUnregisterCallback@4 +ExWindowStationObjectType DATA +ExInitializeBinaryTree@12 +ExDeleteBinaryTree@4 +ExInsertBinaryTree@12 +ExSearchBinaryTree@12 +ExRemoveBinaryTree@12 +ExTraverseBinaryTree@16 +ExInitializeSplayTree@16 +ExDeleteSplayTree@4 +ExInsertSplayTree@12 +ExSearchSplayTree@12 +ExRemoveSplayTree@12 +ExWeightOfSplayTree@8 +ExTraverseSplayTree@16 +ExInitializeHashTable@16 +ExDeleteHashTable@4 +ExInsertHashTable@16 +ExSearchHashTable@16 +ExRemoveHashTable@16 +@ExfInterlockedAddUlong@12 +@ExfInterlockedInsertHeadList@12 +@ExfInterlockedInsertTailList@12 +@ExfInterlockedPopEntryList@8 +@ExfInterlockedPushEntryList@12 +@ExfInterlockedRemoveHeadList@8 +@Exfi386InterlockedDecrementLong@4 +@Exfi386InterlockedExchangeUlong@8 +@Exfi386InterlockedIncrementLong@4 +Exi386InterlockedDecrementLong@4 +Exi386InterlockedExchangeUlong@8 +Exi386InterlockedIncrementLong@4 +FsRtlAddLargeMcbEntry@28 +FsRtlAddMcbEntry@16 +FsRtlAddToTunnelCache@32 +FsRtlAllocateFileLock@8 +FsRtlAllocatePool@8 +FsRtlAllocatePoolWithQuota@8 +FsRtlAllocatePoolWithQuotaTag@12 +FsRtlAllocatePoolWithTag@12 +FsRtlAllocateResource@0 +FsRtlAreNamesEqual@16 +FsRtlBalanceReads@4 +FsRtlCheckLockForReadAccess@8 +FsRtlCheckLockForWriteAccess@8 +FsRtlCheckOplock@20 +FsRtlCopyRead@32 +FsRtlCopyWrite@32 +FsRtlCurrentBatchOplock@4 +FsRtlDeleteKeyFromTunnelCache@12 +FsRtlDeleteTunnelCache@4 +FsRtlDeregisterUncProvider@4 +FsRtlDissectDbcs@16 +FsRtlDissectName@16 +FsRtlDoesDbcsContainWildCards@4 +FsRtlDoesNameContainWildCards@4 +FsRtlFastCheckLockForRead@24 +FsRtlFastCheckLockForWrite@24 +FsRtlFastUnlockAll@16 +FsRtlFastUnlockAllByKey@20 +FsRtlFastUnlockSingle@32 +FsRtlFindInTunnelCache@32 +FsRtlGetFileSize@8 +FsRtlGetNextFileLock@8 +FsRtlGetNextLargeMcbEntry@20 +FsRtlGetNextMcbEntry@20 +FsRtlInitializeFileLock@12 +FsRtlInitializeLargeMcb@8 +FsRtlInitializeMcb@8 +FsRtlInitializeOplock@4 +FsRtlInitializeTunnelCache@4 +FsRtlIsDbcsInExpression@8 +FsRtlIsFatDbcsLegal@20 +FsRtlIsHpfsDbcsLegal@20 +FsRtlIsNameInExpression@16 +FsRtlIsNtstatusExpected@4 +FsRtlIsTotalDeviceFailure@4 +FsRtlLegalAnsiCharacterArray DATA +FsRtlLookupLargeMcbEntry@32 +FsRtlLookupLastLargeMcbEntry@12 +FsRtlLookupLastMcbEntry@12 +FsRtlLookupMcbEntry@20 +FsRtlMdlRead@24 +FsRtlMdlReadComplete@8 +FsRtlMdlReadCompleteDev@12 +FsRtlMdlReadDev@28 +FsRtlMdlWriteComplete@12 +FsRtlMdlWriteCompleteDev@16 +FsRtlNormalizeNtstatus@8 +FsRtlNotifyChangeDirectory@28 +FsRtlNotifyCleanup@12 +FsRtlNotifyFullChangeDirectory@40 +FsRtlNotifyFullReportChange@36 +FsRtlNotifyInitializeSync@4 +FsRtlNotifyReportChange@20 +FsRtlNotifyUninitializeSync@4 +FsRtlNotifyVolumeEvent@8 +FsRtlNumberOfRunsInLargeMcb@4 +FsRtlNumberOfRunsInMcb@4 +FsRtlOplockFsctrl@12 +FsRtlOplockIsFastIoPossible@4 +FsRtlPostPagingFileStackOverflow@12 +FsRtlPostStackOverflow@12 +FsRtlPrepareMdlWrite@24 +FsRtlPrepareMdlWriteDev@28 +FsRtlPrivateLock@48 +FsRtlProcessFileLock@12 +FsRtlRegisterUncProvider@12 +FsRtlRemoveLargeMcbEntry@20 +FsRtlRemoveMcbEntry@12 +FsRtlSplitLargeMcb@20 +FsRtlSyncVolumes@12 +FsRtlTruncateLargeMcb@12 +FsRtlTruncateMcb@8 +FsRtlUninitializeFileLock@4 +FsRtlUninitializeLargeMcb@4 +FsRtlUninitializeMcb@4 +FsRtlUninitializeOplock@4 +HalDispatchTable DATA +HalPrivateDispatchTable DATA +@InterlockedCompareExchange@12 +@InterlockedDecrement@4 +@InterlockedExchange@8 +@InterlockedExchangeAdd@8 +@InterlockedIncrement@4 +IoAcquireCancelSpinLock@4 +IoAcquireRemoveLockEx@20 +IoAcquireVpbSpinLock@4 +IoAdapterObjectType DATA +IoAllocateAdapterChannel@20 +IoAllocateController@16 +IoAllocateErrorLogEntry@8 +IoAllocateIrp@8 +IoAllocateMdl@20 +IoAssignResources@24 +IoAttachDevice@12 +IoAttachDeviceByPointer@8 +IoAttachDeviceToDeviceStack@8 +IoBuildAsynchronousFsdRequest@24 +IoBuildDeviceIoControlRequest@36 +IoBuildPartialMdl@16 +IoBuildSynchronousFsdRequest@28 +IoCallDriver@8 +IoCancelIrp@4 +IoCheckDesiredAccess@8 +IoCheckEaBufferValidity@12 +IoCheckFunctionAccess@24 +IoCheckShareAccess@20 +IoCompleteRequest@8 +IoConnectInterrupt@44 +IoCreateController@4 +IoCreateDevice@28 +IoCreateFile@56 +IoCreateNotificationEvent@8 +IoCreateStreamFileObject@8 +IoCreateSymbolicLink@8 +IoCreateSynchronizationEvent@8 +IoCreateUnprotectedSymbolicLink@8 +IoDeleteController@4 +IoDeleteDevice@4 +IoDeleteSymbolicLink@4 +IoDetachDevice@4 +IoDeviceHandlerObjectSize DATA +IoDeviceHandlerObjectType DATA +IoDisconnectInterrupt@4 +IoDeviceObjectType DATA +IoDriverObjectType DATA +IoEnqueueIrp@4 +IoFastQueryNetworkAttributes@20 +IoFileObjectType DATA +IoFreeController@4 +IoFreeIrp@4 +IoFreeMdl@4 +IoGetAttachedDevice@4 +IoGetAttachedDeviceReference@4 +IoGetBaseFileSystemDeviceObject@4 +IoGetConfigurationInformation@0 +IoGetCurrentProcess@0 +IoGetDeviceObjectPointer@16 +IoGetDeviceToVerify@4 +IoGetFileObjectGenericMapping@0 +IoGetInitialStack@0 +IoGetRelatedDeviceObject@4 +IoGetRequestorProcess@4 +IoGetStackLimits@8 +IoGetTopLevelIrp@0 +IoInitializeIrp@12 +IoInvalidateDeviceState@4 +IoInitializeRemoveLockEx@20 +IoInitializeTimer@12 +IoIsOperationSynchronous@4 +IoMakeAssociatedIrp@8 +IoOpenDeviceInstanceKey@20 +IoPageRead@20 +IoQueryDeviceDescription@32 +IoQueryDeviceEnumInfo@8 +IoQueryFileInformation@20 +IoQueryVolumeInformation@20 +IoQueueThreadIrp@4 +IoRaiseHardError@12 +IoRaiseInformationalHardError@12 +IoReadOperationCount DATA +IoReadPartitionTable@16 +IoReadTransferCount DATA + +IoFreeWorkItem@4 +IoAllocateWorkItem@4 +IoQueueWorkItem@16 +IoRegisterDeviceInterface@16 +IoSetDeviceInterfaceState@8 +IoGetDeviceProperty@20 +IoOpenDeviceRegistryKey@16 +IoInvalidateDeviceRelations@8 + +IoRegisterDriverReinitialization@12 +IoRegisterFileSystem@4 +IoRegisterFsRegistrationChange@8 +IoRegisterShutdownNotification@4 +IoReleaseCancelSpinLock@4 +IoReleaseRemoveLockAndWaitEx@12 +IoReleaseRemoveLockEx@12 +IoReleaseVpbSpinLock@4 +IoRemoveShareAccess@8 +IoReportHalResourceUsage@16 +IoReportResourceUsage@36 +IoSetDeviceToVerify@8 +IoSetHardErrorOrVerifyDevice@8 +IoSetInformation@16 +IoSetPartitionInformation@16 +IoSetShareAccess@16 +IoSetThreadHardErrorMode@4 +IoSetTopLevelIrp@4 +IoStartNextPacket@8 +IoStartNextPacketByKey@12 +IoStartPacket@16 +IoStartTimer@4 +IoStatisticsLock DATA +IoStopTimer@4 +IoSynchronousPageWrite@20 +IoThreadToProcess@4 +IoUnregisterFileSystem@4 +IoUnregisterFsRegistrationChange@8 +IoUnregisterShutdownNotification@4 +IoUpdateShareAccess@8 +IoVerifyVolume@8 +IoWriteErrorLogEntry@4 +IoWriteOperationCount DATA +IoWritePartitionTable@20 +IoWriteTransferCount DATA +@IofCallDriver@8 +@IofCompleteRequest@8 +KdDebuggerEnabled DATA +KdDebuggerNotPresent DATA +KdPollBreakIn@0 +KdSystemDebugControl@4 +Ke386CallBios@8 +;Ke386IoSetAccessProcess +;Ke386QueryIoAccessMap +;Ke386SetIoAccessMap +KeAcquireSpinLockAtDpcLevel@4 +KeAddSystemServiceTable@20 +KeAttachProcess@4 +;KeBoostCurrentThread +KeBugCheck@4 +KeBugCheckEx@20 +KeCancelTimer@4 +KeClearEvent@4 +KeConnectInterrupt@4 +KeDcacheFlushCount DATA +KeDelayExecutionThread@12 +KeDeregisterBugCheckCallback@4 +KeDetachProcess@0 +KeDisconnectInterrupt@4 +KeEnterCriticalRegion@0 +KeEnterKernelDebugger@0 +;KeFindConfigurationEntry +;KeFindConfigurationNextEntry +;KeFlushEntireTb +KeGetCurrentThread@0 +KeGetPreviousMode@0 +;KeI386AbiosCall +;KeI386AllocateGdtSelectors +;KeI386Call16BitCStyleFunction +;KeI386Call16BitFunction +;KeI386FlatToGdtSelector +;KeI386GetLid +;KeI386MachineType DATA +;KeI386ReleaseGdtSelectors +;KeI386ReleaseLid +;KeI386SetGdtSelector +KeIcacheFlushCount DATA +KeInitializeApc@32 +KeInitializeDeviceQueue@4 +KeInitializeDpc@12 +KeInitializeEvent@12 +KeInitializeInterrupt@44 +KeInitializeMutant@8 +KeInitializeMutex@8 +KeInitializeQueue@8 +KeInitializeSemaphore@12 +KeInitializeSpinLock@4 +KeInitializeTimer@4 +KeInitializeTimerEx@8 +KeInsertByKeyDeviceQueue@12 +KeInsertDeviceQueue@8 +KeInsertHeadQueue@8 +KeInsertQueue@8 +KeInsertQueueApc@16 +KeInsertQueueDpc@12 +;KeIsExecutingDpc +KeLeaveCriticalRegion@0 +KeLoaderBlock DATA +KeNumberProcessors DATA +;KeProfileInterrupt +;KeProfileInterruptWithSource +KePulseEvent@12 +KeQuerySystemTime@4 +KeQueryTickCount@4 +KeQueryTimeIncrement@0 +;KeRaiseUserException +KeReadStateEvent@4 +KeReadStateMutant@4 +KeReadStateMutex@4 +KeReadStateQueue@4 +KeReadStateSemaphore@4 +KeReadStateTimer@4 +KeRegisterBugCheckCallback@20 +KeReleaseMutant@16 +KeReleaseMutex@8 +KeReleaseSemaphore@16 +KeReleaseSpinLockFromDpcLevel@4 +KeRemoveByKeyDeviceQueue@8 +KeRemoveDeviceQueue@4 +KeRemoveEntryDeviceQueue@8 +KeRemoveQueue@12 +KeRemoveQueueDpc@4 +KeResetEvent@4 +;KeRestoreFloatingPointState +KeRundownQueue@4 +;KeSaveFloatingPointState +KeServiceDescriptorTable DATA +;KeSetAffinityThread +KeSetBasePriorityThread@8 +;KeSetDmaIoCoherency +KeSetEvent@12 +;KeSetEventBoostPriority +;KeSetIdealProcessorThread +KeSetImportanceDpc@8 +;KeSetKernelStackSwapEnable +KeSetPriorityThread@8 +;KeSetProfileIrql +;@KeSetSwapContextNotifyRoutine +KeSetTargetProcessorDpc@8 +;@KeSetThreadSelectNotifyRoutine +;KeSetTimeIncrement +KeSetTimer@16 +KeSetTimerEx@20 +;@KeSetTimeUpdateNotifyRoutine +KeSynchronizeExecution@12 +;KeTerminateThread +KeTickCount DATA +;KeUpdateRunTime +;KeUserModeCallback +KeWaitForMultipleObjects@32 +KeWaitForMutexObject@20 +KeWaitForSingleObject@20 +;@KefAcquireSpinLockAtDpcLevel +;@KefReleaseSpinLockFromDpcLevel +;Kei386EoiHelper +;@KiAcquireSpinLock@4 +;KiBugCheckData DATA +;KiCoprocessorError@0 +KiDeliverApc@12 +KiDispatchInterrupt@0 +KiInterruptDispatch2@8 +;KiIpiServiceRoutine@8 +;@KiReleaseSpinLock@4 +;KiUnexpectedInterrupt +;Kii386SpinOnSpinLock +KiRawTicks DATA +LdrAccessResource@16 +;LdrEnumResources@20 +;LdrFindResourceDirectory_U@16 +LdrFindResource_U@16 +;LpcRequestPort@8 +LsaCallAuthenticationPackage@28 +LsaDeregisterLogonProcess@8 +LsaFreeReturnBuffer@4 +LsaLogonUser@56 +LsaLookupAuthenticationPackage@12 +LsaRegisterLogonProcess@12 +MmAdjustWorkingSetSize@12 +MmAllocateContiguousAlignedMemory@16 +MmAllocateContiguousMemory@12 +MmAllocateNonCachedMemory@4 +MmBuildMdlForNonPagedPool@4 +MmCanFileBeTruncated@8 +MmCopyFromCaller@12 +MmCopyToCaller@12 +MmCreateMdl@12 +MmCreateSection@32 +MmDbgTranslatePhysicalAddress@8 +MmDisableModifiedWriteOfSection@4 +MmFlushImageSection@8 +MmForceSectionClosed@8 +MmFreeContiguousMemory@4 +MmFreeNonCachedMemory@8 +MmGetPhysicalAddress@4 +MmGrowKernelStack@4 +MmHighestUserAddress DATA +MmIsAddressValid@4 +MmIsNonPagedSystemAddressValid@4 +MmIsRecursiveIoFault@0 +MmIsThisAnNtAsSystem@0 +MmLockPagableDataSection@4 +MmLockPagableImageSection@4=MmLockPagableDataSection@4 +MmLockPagableSectionByHandle@4 +MmMapIoSpace@16 +MmMapLockedPages@8 +MmMapMemoryDumpMdl@4 +MmMapVideoDisplay@16 +MmMapViewInSystemSpace@12 +MmMapViewOfSection@40 +MmPageEntireDriver@4 +MmProbeAndLockPages@12 +MmQuerySystemSize@0 +MmResetDriverPaging@4 +MmSectionObjectType DATA +MmSecureVirtualMemory@12 +MmSetAddressRangeModified@8 +MmSetBankedSection@24 +MmSizeOfMdl@8 +MmUnlockPagableImageSection@4 +MmUnlockPages@4 +MmUnmapIoSpace@8 +MmUnmapLockedPages@8 +MmUnmapVideoDisplay@8 +MmUnmapViewInSystemSpace@4 +MmUnmapViewOfSection@8 +MmUnsecureVirtualMemory@4 +MmUserProbeAddress DATA +NlsAnsiCodePage DATA +NlsLeadByteInfo DATA +NlsMbCodePageTag DATA +NlsMbOemCodePageTag DATA +NlsOemLeadByteInfo DATA +NtAddAtom@8 +NtAdjustPrivilegesToken@24 +NtAlertThread@4 +NtAllocateLocallyUniqueId@4 +NtAllocateUuids@12 +NtAllocateVirtualMemory@24 +NtBuildNumber DATA +NtClose@4 +NtConnectPort@32 +NtCreateEvent@20 +NtCreateTimer@16 +NtOpenEvent@12 +NtCreateFile@44 +NtCreateSection@28 +NtDeleteAtom@4 +NtDeleteFile@4 +NtDeviceIoControlFile@40 +NtDuplicateObject@28 +NtDuplicateToken@24 +NtFindAtom@8 +NtFreeVirtualMemory@16 +NtFsControlFile@40 +NtGlobalFlag DATA +NtLockFile@40 +NtMapViewOfSection@40 +NtNotifyChangeDirectoryFile@36 +NtOpenFile@24 +NtOpenProcess@16 +NtOpenProcessToken@12 +NtQueryDirectoryFile@44 +NtQueryEaFile@36 +NtQueryInformationAtom@20 +NtQueryInformationFile@20 +NtQueryInformationProcess@20 +NtQueryInformationToken@20 +;NtQueryOleDirectoryFile@ <--- ? +NtQuerySecurityObject@20 +NtQuerySystemTime@4 +NtQueryVolumeInformationFile@20 +NtReadFile@36 +NtRequestPort@20 +NtRequestWaitReplyPort@12 +NtSetEvent@8 +NtSetInformationFile@20 +NtSetInformationProcess@16 +NtSetInformationThread@16 +NtSetSecurityObject@12 +NtSetSystemTime@8 +NtUnlockFile@20 +NtVdmControl@8 +NtW32Call@20 +NtWaitForSingleObject@12 +NtWriteFile@36 +ObAssignSecurity@16 +;ObCheckCreateObjectAccess@28 +;ObCheckObjectAccess@20 +;ObCreateObject@36 +ObCreateObject@20 +;ObFindHandleForObject@20 +ObGetObjectPointerCount@4 +ObGetObjectSecurity@12 +;ObInsertObject@24 +ObMakeTemporaryObject@4 +ObOpenObjectByName@28 +ObOpenObjectByPointer@28 +;ObQueryNameString@16 +;ObQueryObjectAuditingByHandle@8 +@ObfDereferenceObject@4 +@ObfReferenceObject@4 +ObReferenceObjectByHandle@24 +ObReferenceObjectByName@32 +ObReferenceObjectByPointer@16 +ObReleaseObjectSecurity@8 +;ObSetSecurityDescriptorInfo@24 +;PfxFindPrefix +;PfxInitialize +;PfxInsertPrefix +;PfxRemovePrefix +PoCallDriver@8 +PoRegisterDeviceForIdleDetection@16 +PoRegisterSystemState@8 +PoRequestPowerIrp@24 +PoSetDeviceBusy@4 +PoSetPowerState@12 +PoSetSystemState@4 +PoStartNextPowerIrp@4 +PoUnregisterSystemState@4 +;ProbeForWrite@12 +PsAssignImpersonationToken@8 +;PsChargePoolQuota@12 +PsCreateSystemProcess@12 +PsCreateSystemThread@28 +PsCreateWin32Thread@4 +PsCreateWin32Process@4 +PsGetWin32Thread@0 +PsGetWin32Process@0 +PsEstablishWin32Callouts@24 +PsGetCurrentProcess@0 +PsGetCurrentProcessId@0 +PsGetCurrentThreadId@0 +PsGetCurrentThread@0 +PsGetProcessExitTime@0 +PsGetVersion@16 +PsImpersonateClient@20 +PsInitialSystemProcess DATA +PsIsThreadTerminating@4 +PsLookupProcessByProcessId@8 +PsLookupProcessThreadByCid@12 +PsLookupThreadByThreadId@8 +PsProcessType DATA +PsReferenceImpersonationToken@16 +PsReferencePrimaryToken@4 +;PsReturnPoolQuota@12 +PsRevertToSelf@0 +PsSetCreateProcessNotifyRoutine@8 +PsSetCreateThreadNotifyRoutine@4 +;PsSetLegoNotifyRoutine@4 +;PsSetProcessPriorityByClass@8 +PsTerminateSystemThread@4 +PsThreadType DATA +READ_REGISTER_UCHAR@4 +READ_REGISTER_ULONG@4 +READ_REGISTER_USHORT@4 +READ_REGISTER_BUFFER_UCHAR@12 +READ_REGISTER_BUFFER_ULONG@12 +READ_REGISTER_BUFFER_USHORT@12 +RtlAbsoluteToSelfRelativeSD@12 +RtlAddAccessAllowedAce@16 +RtlAddAce@20 +RtlAddAtomToAtomTable@12 +;RtlAllocateAndInitializeSid +;RtlAllocateHeap +RtlAnsiCharToUnicodeChar@4 +RtlAnsiStringToUnicodeSize@4 +RtlAnsiStringToUnicodeString@12 +RtlAppendAsciizToString@8 +RtlAppendStringToString@8 +RtlAppendUnicodeStringToString@8 +RtlAppendUnicodeToString@8 +RtlAreAllAccessesGranted@8 +RtlAreAnyAccessesGranted@8 +RtlAreBitsClear@12 +RtlAreBitsSet@12 +RtlAssert@16 +;RtlCaptureStackBackTrace +RtlCharToInteger@12 +RtlCheckRegistryKey@8 +RtlClearAllBits@4 +RtlClearBits@12 +RtlCompareMemory@12 +RtlCompareMemoryUlong@12 +RtlCompareString@12 +RtlCompareUnicodeString@12 +RtlCompressBuffer@32 +RtlCompressChunks@28 +RtlConvertLongToLargeInteger@4 +RtlConvertSidToUnicodeString@12 +RtlConvertUlongToLargeInteger@4 +RtlCopyLuid@8 +RtlCopySid@12 +RtlCopyString@8 +RtlCopyUnicodeString@8 +RtlCreateAcl@12 +RtlCreateAtomTable@8 +;RtlCreateHeap +RtlCreateRegistryKey@8 +RtlCreateSecurityDescriptor@8 +RtlCreateUnicodeString@8 +RtlCustomCPToUnicodeN@24 +RtlDecompressBuffer@24 +RtlDecompressChunks@28 +RtlDecompressFragment@32 +;RtlDelete +RtlDeleteAtomFromAtomTable@8 +;RtlDeleteElementGenericTable +;RtlDeleteNoSplay +RtlDeleteRegistryValue@12 +RtlDescribeChunk@20 +RtlDestroyAtomTable@4 +;RtlDestroyHeap +RtlDowncaseUnicodeString@12 +RtlEmptyAtomTable@8 +RtlEnlargedIntegerMultiply@8 +RtlEnlargedUnsignedDivide@16 +RtlEnlargedUnsignedMultiply@8 +;RtlEnumerateGenericTable +;RtlEnumerateGenericTableWithoutSplaying +RtlEqualLuid@8 +RtlEqualSid@8 +RtlEqualString@12 +RtlEqualUnicodeString@12 +RtlExtendedIntegerMultiply@12 +RtlExtendedLargeIntegerDivide@16 +RtlExtendedMagicDivide@20 +RtlFillMemory@12 +RtlFillMemoryUlong@12 +RtlFindClearBits@12 +RtlFindClearBitsAndSet@12 +RtlFindFirstRunClear@8 +RtlFindFirstRunSet@8 +RtlFindLongestRunClear@8 +RtlFindLongestRunSet@8 +RtlFindMessage@20 +RtlFindSetBits@12 +RtlFindSetBitsAndClear@12 +;RtlFindUnicodePrefix +RtlFormatCurrentUserKeyPath@4 +RtlFreeAnsiString@4 +;RtlFreeHeap +RtlFreeOemString@4 +RtlFreeUnicodeString@4 +RtlGenerate8dot3Name@16 +;RtlGetCallersAddress +RtlGetCompressionWorkSpaceSize@12 +RtlGetDaclSecurityDescriptor@16 +RtlGetDefaultCodePage@8 +;RtlGetElementGenericTable +RtlGetGroupSecurityDescriptor@12 +RtlGetOwnerSecurityDescriptor@12 +RtlImageNtHeader@4 +RtlInitAnsiString@8 +;RtlInitCodePageTable +RtlInitString@8 +RtlInitUnicodeString@8 +RtlInitializeBitMap@12 +;RtlInitializeGenericTable +RtlInitializeSid@12 +;RtlInitializeUnicodePrefix +;RtlInsertElementGenericTable +;RtlInsertUnicodePrefix +RtlIntegerToChar@16 +RtlIntegerToUnicodeString@12 +RtlIsNameLegalDOS8Dot3@12 +RtlLargeIntegerAdd@16 +RtlLargeIntegerArithmeticShift@12 +RtlLargeIntegerDivide@20 +RtlLargeIntegerNegate@8 +RtlLargeIntegerShiftLeft@12 +RtlLargeIntegerShiftRight@12 +RtlLargeIntegerSubtract@16 +RtlLengthRequiredSid@4 +RtlLengthSecurityDescriptor@4 +RtlLengthSid@4 +RtlLookupAtomInAtomTable@12 +;RtlLookupElementGenericTable +RtlMapGenericMask@8 +RtlMoveMemory@12 +RtlMultiByteToUnicodeN@20 +RtlMultiByteToUnicodeSize@12 +;RtlNextUnicodePrefix +RtlNtStatusToDosError@4 +RtlNtStatusToDosErrorNoTeb@4 +;RtlNumberGenericTableElements +RtlNumberOfClearBits@4 +RtlNumberOfSetBits@4 +RtlOemStringToCountedUnicodeString@12 +RtlOemStringToUnicodeSize@4 +RtlOemStringToUnicodeString@12 +RtlOemToUnicodeN@20 +RtlPinAtomInAtomTable@8 +RtlPrefixString@12 +RtlPrefixUnicodeString@12 +RtlQueryAtomInAtomTable@24 +RtlQueryRegistryValues@20 +RtlQueryTimeZoneInformation@4 +RtlRaiseException@4 +;RtlRandom +;RtlRemoveUnicodePrefix +RtlReserveChunk@20 +RtlSecondsSince1970ToTime@8 +RtlSecondsSince1980ToTime@8 +RtlSetAllBits@4 +RtlSetBits@12 +RtlSetDaclSecurityDescriptor@16 +RtlSetGroupSecurityDescriptor@12 +RtlSetOwnerSecurityDescriptor@12 +RtlSetSaclSecurityDescriptor@16 +RtlSetTimeZoneInformation@4 +;RtlSplay +RtlSubAuthorityCountSid@4 +RtlSubAuthoritySid@8 +RtlTimeFieldsToTime@8 +RtlTimeToSecondsSince1970@8 +RtlTimeToSecondsSince1980@8 +RtlTimeToTimeFields@8 +RtlUnicodeStringToAnsiSize@4 +RtlUnicodeStringToAnsiString@12 +RtlUnicodeStringToCountedOemString@12 +RtlUnicodeStringToInteger@12 +RtlUnicodeStringToOemSize@4 +RtlUnicodeStringToOemString@12 +RtlUnicodeToCustomCPN@24 +RtlUnicodeToMultiByteN@20 +RtlUnicodeToMultiByteSize@12 +RtlUnicodeToOemN@20 +RtlUnwind@16 +RtlUpcaseUnicodeChar@4 +RtlUpcaseUnicodeString@12 +RtlUpcaseUnicodeStringToAnsiString@12 +RtlUpcaseUnicodeStringToCountedOemString@12 +RtlUpcaseUnicodeStringToOemString@12 +RtlUpcaseUnicodeToCustomCPN@24 +RtlUpcaseUnicodeToMultiByteN@20 +RtlUpcaseUnicodeToOemN@20 +RtlUpperChar@4 +RtlUpperString@8 +RtlValidSecurityDescriptor@4 +RtlValidSid@4 +RtlWriteRegistryValue@24 +;RtlZeroHeap +RtlZeroMemory@8 +RtlxAnsiStringToUnicodeSize@4 +RtlxOemStringToUnicodeSize@4 +RtlxUnicodeStringToAnsiSize@4 +RtlxUnicodeStringToOemSize@4 +SeAccessCheck@40 +;SeAppendPrivileges@8 +SeAssignSecurity@28 +;SeAuditingFileEvents@8 +;SeAuditingFileOrGlobalEvents@18 +;SeCaptureSecurityDescriptor@20 +SeCaptureSubjectContext@4 +;SeCloseObjectAuditAlarm@12 +;SeCreateAccessState@16 +SeCreateClientSecurity@16 +SeDeassignSecurity@4 +;SeDeleteAccessState@4 +;SeDeleteObjectAuditAlarm@8 +SeExports DATA +;SeFreePrivileges@4 +SeImpersonateClient@8 +;SeLockSubjectContext@4 +;SeMarkLogonSessionForTerminationNotification@4 +;SeOpenObjectAuditAlarm@36 +;SeOpenObjectForDeleteAuditAlarm@36 +SePrivilegeCheck@12 +;SePrivilegeObjectAuditAlarm@24 +SePublicDefaultDacl DATA +;SeQueryAuthenticationIdToken@8 +;SeQuerySecurityDescriptorInfo@16 +;SeRegisterLogonSessionTerminatedRoutine@4 +;SeReleaseSecurityDescriptor@12 +SeReleaseSubjectContext@4 +;SeSetAccessStateGenericMapping@8 +;SeSetSecurityDescriptorInfo@24 +SeSinglePrivilegeCheck@12 +SeSystemDefaultDacl DATA +SeTokenImpersonationLevel@4 +SeTokenType@4 +;SeUnlockSubjectContext@4 +;SeUnregisterLogonSessionTerminatedRoutine@4 +;SeValidSecurityDescriptor@8 +WRITE_REGISTER_UCHAR@8 +WRITE_REGISTER_ULONG@8 +WRITE_REGISTER_USHORT@8 +WRITE_REGISTER_BUFFER_UCHAR@12 +WRITE_REGISTER_BUFFER_ULONG@12 +WRITE_REGISTER_BUFFER_USHORT@12 +ZwAccessCheckAndAuditAlarm@44 +ZwAlertThread@4 +ZwAllocateVirtualMemory@24 +ZwClearEvent@4 +ZwClose@4 +ZwCloseObjectAuditAlarm@12 +ZwConnectPort@32 +ZwCreateDirectoryObject@12 +ZwCreateEvent@20 +ZwCreateFile@44 +ZwCreateKey@28 +ZwCreateSection@28 +ZwCreateSymbolicLinkObject@16 +ZwDeleteFile@4 +ZwDeleteKey@4 +ZwDeleteValueKey@8 +ZwDeviceIoControlFile@40 +ZwDisplayString@4 +ZwDuplicateObject@28 +ZwDuplicateToken@24 +ZwEnumerateKey@24 +ZwEnumerateValueKey@24 +ZwFlushInstructionCache@12 +ZwFlushKey@4 +ZwFreeVirtualMemory@16 +ZwFsControlFile@40 +ZwLoadDriver@4 +ZwLoadKey@8 +ZwMakeTemporaryObject@4 +ZwMapViewOfSection@40 +ZwNotifyChangeKey@40 +ZwOpenDirectoryObject@12 +ZwOpenEvent@12 +ZwOpenFile@24 +ZwOpenKey@12 +ZwOpenProcess@16 +ZwOpenProcessToken@12 +ZwOpenSection@12 +ZwOpenSymbolicLinkObject@12 +ZwOpenThread@16 +ZwOpenThreadToken@16 +ZwPulseEvent@8 +ZwQueryDefaultLocale@8 +ZwQueryDirectoryFile@44 +ZwQueryInformationAtom@20 +ZwQueryInformationFile@20 +ZwQueryInformationProcess@20 +ZwQueryInformationToken@20 +ZwQueryKey@20 +ZwQueryObject@20 +ZwQuerySection@20 +ZwQuerySecurityObject@20 +ZwQuerySymbolicLinkObject@12 +ZwQuerySystemInformation@16 +ZwQuerySystemTime@4 +ZwQueryValueKey@24 +ZwQueryVolumeInformationFile@20 +ZwReadFile@36 +ZwReplaceKey@12 +ZwRequestWaitReplyPort@12 +ZwResetEvent@8 +ZwSaveKey@8 +ZwSetDefaultLocale@8 +ZwSetEvent@8 +ZwSetInformationFile@20 +ZwSetInformationObject@16 +ZwSetInformationProcess@16 +ZwSetInformationThread@16 +ZwSetSystemInformation@12 +ZwSetSystemTime@8 +ZwSetValueKey@24 +ZwTerminateProcess@8 +ZwUnloadDriver@4 +ZwUnloadKey@4 +ZwUnmapViewOfSection@8 +ZwWaitForMultipleObjects@20 +ZwWaitForSingleObject@12 +ZwWriteFile@36 +ZwYieldExecution@0 +_abnormal_termination +;_alldiv +;_allmul +;_allrem +;_allshl +;_allshr +;_aulldiv +;_aullrem +;_aullshr +_except_handler2 +_except_handler3 +_global_unwind2 +_itoa +_local_unwind2 +_purecall +_snprintf +_snwprintf +_stricmp +_strlwr +_strnicmp +_strnset +_strrev +_strset +_strupr +_vsnprintf +_wcsicmp +_wcslwr +_wcsnicmp +_wcsnset +_wcsrev +_wcsupr +atoi +atol +isdigit +islower +isprint +isspace +isupper +isxdigit +mbstowcs +mbtowc +memchr +memcpy +memmove +memset +qsort +rand +sprintf +srand +strcat +strchr +strcmp +strcpy +strlen +strncat +strncmp +strncpy +strrchr +strspn +strstr +swprintf +tolower +toupper +towlower +towupper +vsprintf +wcscat +wcschr +wcscmp +wcscpy +wcscspn +wcslen +wcsncat +wcsncmp +wcsncpy +wcsrchr +wcsspn +wcsstr +wcstombs +wctomb diff --git a/ntoskrnl/ntoskrnl.edf b/ntoskrnl/ntoskrnl.edf new file mode 100644 index 0000000..12bd828 --- /dev/null +++ b/ntoskrnl/ntoskrnl.edf @@ -0,0 +1,1057 @@ +; $Id$ +; +; reactos/ntoskrnl/ntoskrnl.def +; +; ReactOS Operating System +; +EXPORTS +CcRosInitializeFileCache=CcRosInitializeFileCache@12 +CcMdlReadComplete=CcMdlReadComplete@8 +;CcRosRequestCacheSegment=CcRosRequestCacheSegment@20 +;CcRosReleaseCacheSegment=CcRosReleaseCacheSegment@12 +CcRosReleaseFileCache=CcRosReleaseFileCache@8 +CcCopyRead=CcCopyRead@24 +CcCopyWrite=CcCopyWrite@20 +CcFlushCache=CcFlushCache@16 +CcGetFileObjectFromSectionPtrs=CcGetFileObjectFromSectionPtrs@4 +CcMapData=CcMapData@24 +CcSetDirtyPinnedData=CcSetDirtyPinnedData@8 +CcUnpinData=CcUnpinData@4 +CcSetFileSizes=CcSetFileSizes@8 +CcZeroData=CcZeroData@16 +DbgBreakPoint=DbgBreakPoint@0 +DbgBreakPointWithStatus=DbgBreakPointWithStatus@4 +;DbgLoadImageSymbols=DbgLoadImageSymbols@12 +DbgPrint +DbgPrompt=DbgPrompt@12 +DpcQueueSize DATA +ExAcquireFastMutexUnsafe=@ExAcquireFastMutexUnsafe@4 +ExAcquireResourceExclusive=ExAcquireResourceExclusive@8 +ExAcquireResourceExclusiveLite=ExAcquireResourceExclusiveLite@8 +ExAcquireResourceSharedLite=ExAcquireResourceSharedLite@8 +ExAcquireSharedStarveExclusive=ExAcquireSharedStarveExclusive@8 +ExAcquireSharedWaitForExclusive=ExAcquireSharedWaitForExclusive@8 +ExAllocateFromPagedLookasideList=ExAllocateFromPagedLookasideList@4 +ExAllocatePool=ExAllocatePool@8 +ExAllocatePoolWithQuota=ExAllocatePoolWithQuota@8 +ExAllocatePoolWithQuotaTag=ExAllocatePoolWithQuotaTag@12 +ExAllocatePoolWithTag=ExAllocatePoolWithTag@12 +ExConvertExclusiveToSharedLite=ExConvertExclusiveToSharedLite@4 +ExCreateCallback=ExCreateCallback@16 +ExDeleteNPagedLookasideList=ExDeleteNPagedLookasideList@4 +ExDeletePagedLookasideList=ExDeletePagedLookasideList@4 +ExDeleteResource=ExDeleteResource@4 +ExDeleteResourceLite=ExDeleteResourceLite@4 +ExDesktopObjectType DATA +ExDisableResourceBoostLite=ExDisableResourceBoostLite@4 +ExEventObjectType DATA +ExExtendZone=ExExtendZone@12 +ExFreePool=ExFreePool@4 +ExFreeToPagedLookasideList=ExFreeToPagedLookasideList@8 +ExGetExclusiveWaiterCount=ExGetExclusiveWaiterCount@4 +ExGetPreviousMode=ExGetPreviousMode@0 +ExGetSharedWaiterCount=ExGetSharedWaiterCount@4 +ExInitializeNPagedLookasideList=ExInitializeNPagedLookasideList@28 +ExInitializePagedLookasideList=ExInitializePagedLookasideList@28 +ExInitializeResource=ExInitializeResource@4 +ExInitializeResourceLite=ExInitializeResourceLite@4 +ExInitializeZone=ExInitializeZone@16 +ExInterlockedAddLargeInteger=ExInterlockedAddLargeInteger@16 +ExInterlockedAddLargeStatistic=@ExInterlockedAddLargeStatistic@8 +ExInterlockedAddUlong=ExInterlockedAddUlong@12 +ExInterlockedCompareExchange64=@ExInterlockedCompareExchange64@16 +ExInterlockedDecrementLong=ExInterlockedDecrementLong@8 +ExInterlockedExchangeUlong=ExInterlockedExchangeUlong@12 +ExInterlockedExtendZone=ExInterlockedExtendZone@16 +ExInterlockedIncrementLong=ExInterlockedIncrementLong@8 +ExInterlockedInsertHeadList=ExInterlockedInsertHeadList@12 +ExInterlockedInsertTailList=ExInterlockedInsertTailList@12 +ExInterlockedPopEntryList=ExInterlockedPopEntryList@8 +ExInterlockedPopEntrySList=@ExInterlockedPopEntrySList@8 +ExInterlockedPushEntryList=ExInterlockedPushEntryList@12 +ExInterlockedPushEntrySList=@ExInterlockedPushEntrySList@12 +ExInterlockedRemoveHeadList=ExInterlockedRemoveHeadList@8 +ExIsProcessorFeaturePresent=ExIsProcessorFeaturePresent@4 +ExIsResourceAcquiredExclusiveLite=ExIsResourceAcquiredExclusiveLite@4 +ExIsResourceAcquiredSharedLite=ExIsResourceAcquiredSharedLite@4 +ExLocalTimeToSystemTime=ExLocalTimeToSystemTime@8 +ExNotifyCallback=ExNotifyCallback@12 +ExPostSystemEvent=ExPostSystemEvent@12 +;ExQueryPoolBlockSize +ExQueueWorkItem=ExQueueWorkItem@8 +ExRaiseAccessViolation=ExRaiseAccessViolation@0 +ExRaiseDatatypeMisalignment=ExRaiseDatatypeMisalignment@0 +;ExRaiseException +;ExRaiseHardError +ExRaiseStatus=ExRaiseStatus@4 +ExRegisterCallback=ExRegisterCallback@12 +ExReinitializeResourceLite=ExReinitializeResourceLite@4 +ExReleaseFastMutexUnsafe=@ExReleaseFastMutexUnsafe@4 +ExReleaseResourceForThread=ExReleaseResourceForThread@8 +ExReleaseResourceForThreadLite=ExReleaseResourceForThreadLite@8 +ExReleaseResourceLite=@ExReleaseResourceLite@4 +ExSetResourceOwnerPointer=ExSetResourceOwnerPointer@8 +;ExSystemExceptionFilter +ExSystemTimeToLocalTime=ExSystemTimeToLocalTime@8 +ExTryToAcquireResourceExclusiveLite=ExTryToAcquireResourceExclusiveLite@4 +ExUnregisterCallback=ExUnregisterCallback@4 +ExWindowStationObjectType DATA +ExInitializeBinaryTree=ExInitializeBinaryTree@12 +ExDeleteBinaryTree=ExDeleteBinaryTree@4 +ExInsertBinaryTree=ExInsertBinaryTree@12 +ExSearchBinaryTree=ExSearchBinaryTree@12 +ExRemoveBinaryTree=ExRemoveBinaryTree@12 +ExTraverseBinaryTree=ExTraverseBinaryTree@16 +ExInitializeSplayTree=ExInitializeSplayTree@16 +ExDeleteSplayTree=ExDeleteSplayTree@4 +ExInsertSplayTree=ExInsertSplayTree@12 +ExSearchSplayTree=ExSearchSplayTree@12 +ExRemoveSplayTree=ExRemoveSplayTree@12 +ExWeightOfSplayTree=ExWeightOfSplayTree@8 +ExTraverseSplayTree=ExTraverseSplayTree@16 +ExInitializeHashTable=ExInitializeHashTable@16 +ExDeleteHashTable=ExDeleteHashTable@4 +ExInsertHashTable=ExInsertHashTable@16 +ExSearchHashTable=ExSearchHashTable@16 +ExRemoveHashTable=ExRemoveHashTable@16 +ExfInterlockedAddUlong=@ExfInterlockedAddUlong@12 +ExfInterlockedInsertHeadList=@ExfInterlockedInsertHeadList@12 +ExfInterlockedInsertTailList=@ExfInterlockedInsertTailList@12 +ExfInterlockedPopEntryList=@ExfInterlockedPopEntryList@8 +ExfInterlockedPushEntryList=@ExfInterlockedPushEntryList@12 +ExfInterlockedRemoveHeadList=@ExfInterlockedRemoveHeadList@8 +Exfi386InterlockedDecrementLong=@Exfi386InterlockedDecrementLong@4 +Exfi386InterlockedExchangeUlong=@Exfi386InterlockedExchangeUlong@8 +Exfi386InterlockedIncrementLong=@Exfi386InterlockedIncrementLong@4 +Exi386InterlockedDecrementLong=Exi386InterlockedDecrementLong@4 +Exi386InterlockedExchangeUlong=Exi386InterlockedExchangeUlong@8 +Exi386InterlockedIncrementLong=Exi386InterlockedIncrementLong@4 +FsRtlAddLargeMcbEntry=FsRtlAddLargeMcbEntry@28 +FsRtlAddMcbEntry=FsRtlAddMcbEntry@16 +FsRtlAddToTunnelCache=FsRtlAddToTunnelCache@32 +FsRtlAllocateFileLock=FsRtlAllocateFileLock@8 +FsRtlAllocatePool=FsRtlAllocatePool@8 +FsRtlAllocatePoolWithQuota=FsRtlAllocatePoolWithQuota@8 +FsRtlAllocatePoolWithQuotaTag=FsRtlAllocatePoolWithQuotaTag@12 +FsRtlAllocatePoolWithTag=FsRtlAllocatePoolWithTag@12 +FsRtlAllocateResource=FsRtlAllocateResource@0 +FsRtlAreNamesEqual=FsRtlAreNamesEqual@16 +FsRtlBalanceReads=FsRtlBalanceReads@4 +FsRtlCheckLockForReadAccess=FsRtlCheckLockForReadAccess@8 +FsRtlCheckLockForWriteAccess=FsRtlCheckLockForWriteAccess@8 +FsRtlCheckOplock=FsRtlCheckOplock@20 +FsRtlCopyRead=FsRtlCopyRead@32 +FsRtlCopyWrite=FsRtlCopyWrite@32 +FsRtlCurrentBatchOplock=FsRtlCurrentBatchOplock@4 +FsRtlDeleteKeyFromTunnelCache=FsRtlDeleteKeyFromTunnelCache@12 +FsRtlDeleteTunnelCache=FsRtlDeleteTunnelCache@4 +FsRtlDeregisterUncProvider=FsRtlDeregisterUncProvider@4 +FsRtlDissectDbcs=FsRtlDissectDbcs@16 +FsRtlDissectName=FsRtlDissectName@16 +FsRtlDoesDbcsContainWildCards=FsRtlDoesDbcsContainWildCards@4 +FsRtlDoesNameContainWildCards=FsRtlDoesNameContainWildCards@4 +FsRtlFastCheckLockForRead=FsRtlFastCheckLockForRead@24 +FsRtlFastCheckLockForWrite=FsRtlFastCheckLockForWrite@24 +FsRtlFastUnlockAll=FsRtlFastUnlockAll@16 +FsRtlFastUnlockAllByKey=FsRtlFastUnlockAllByKey@20 +FsRtlFastUnlockSingle=FsRtlFastUnlockSingle@32 +FsRtlFindInTunnelCache=FsRtlFindInTunnelCache@32 +FsRtlGetFileSize=FsRtlGetFileSize@8 +FsRtlGetNextFileLock=FsRtlGetNextFileLock@8 +FsRtlGetNextLargeMcbEntry=FsRtlGetNextLargeMcbEntry@20 +FsRtlGetNextMcbEntry=FsRtlGetNextMcbEntry@20 +FsRtlInitializeFileLock=FsRtlInitializeFileLock@12 +FsRtlInitializeLargeMcb=FsRtlInitializeLargeMcb@8 +FsRtlInitializeMcb=FsRtlInitializeMcb@8 +FsRtlInitializeOplock=FsRtlInitializeOplock@4 +FsRtlInitializeTunnelCache=FsRtlInitializeTunnelCache@4 +FsRtlIsDbcsInExpression=FsRtlIsDbcsInExpression@8 +FsRtlIsFatDbcsLegal=FsRtlIsFatDbcsLegal@20 +FsRtlIsHpfsDbcsLegal=FsRtlIsHpfsDbcsLegal@20 +FsRtlIsNameInExpression=FsRtlIsNameInExpression@16 +FsRtlIsNtstatusExpected=FsRtlIsNtstatusExpected@4 +FsRtlIsTotalDeviceFailure=FsRtlIsTotalDeviceFailure@4 +FsRtlLegalAnsiCharacterArray DATA +FsRtlLookupLargeMcbEntry=FsRtlLookupLargeMcbEntry@32 +FsRtlLookupLastLargeMcbEntry=FsRtlLookupLastLargeMcbEntry@12 +FsRtlLookupLastMcbEntry=FsRtlLookupLastMcbEntry@12 +FsRtlLookupMcbEntry=FsRtlLookupMcbEntry@20 +FsRtlMdlRead=FsRtlMdlRead@24 +FsRtlMdlReadComplete=FsRtlMdlReadComplete@8 +FsRtlMdlReadCompleteDev=FsRtlMdlReadCompleteDev@12 +FsRtlMdlReadDev=FsRtlMdlReadDev@28 +FsRtlMdlWriteComplete=FsRtlMdlWriteComplete@12 +FsRtlMdlWriteCompleteDev=FsRtlMdlWriteCompleteDev@16 +FsRtlNormalizeNtstatus=FsRtlNormalizeNtstatus@8 +FsRtlNotifyChangeDirectory=FsRtlNotifyChangeDirectory@28 +FsRtlNotifyCleanup=FsRtlNotifyCleanup@12 +FsRtlNotifyFullChangeDirectory=FsRtlNotifyFullChangeDirectory@40 +FsRtlNotifyFullReportChange=FsRtlNotifyFullReportChange@36 +FsRtlNotifyInitializeSync=FsRtlNotifyInitializeSync@4 +FsRtlNotifyReportChange=FsRtlNotifyReportChange@20 +FsRtlNotifyUninitializeSync=FsRtlNotifyUninitializeSync@4 +FsRtlNotifyVolumeEvent=FsRtlNotifyVolumeEvent@8 +FsRtlNumberOfRunsInLargeMcb=FsRtlNumberOfRunsInLargeMcb@4 +FsRtlNumberOfRunsInMcb=FsRtlNumberOfRunsInMcb@4 +FsRtlOplockFsctrl=FsRtlOplockFsctrl@12 +FsRtlOplockIsFastIoPossible=FsRtlOplockIsFastIoPossible@4 +FsRtlPostPagingFileStackOverflow=FsRtlPostPagingFileStackOverflow@12 +FsRtlPostStackOverflow=FsRtlPostStackOverflow@12 +FsRtlPrepareMdlWrite=FsRtlPrepareMdlWrite@24 +FsRtlPrepareMdlWriteDev=FsRtlPrepareMdlWriteDev@28 +FsRtlPrivateLock=FsRtlPrivateLock@48 +FsRtlProcessFileLock=FsRtlProcessFileLock@12 +FsRtlRegisterUncProvider=FsRtlRegisterUncProvider@12 +FsRtlRemoveLargeMcbEntry=FsRtlRemoveLargeMcbEntry@20 +FsRtlRemoveMcbEntry=FsRtlRemoveMcbEntry@12 +FsRtlSplitLargeMcb=FsRtlSplitLargeMcb@20 +FsRtlSyncVolumes=FsRtlSyncVolumes@12 +FsRtlTruncateLargeMcb=FsRtlTruncateLargeMcb@12 +FsRtlTruncateMcb=FsRtlTruncateMcb@8 +FsRtlUninitializeFileLock=FsRtlUninitializeFileLock@4 +FsRtlUninitializeLargeMcb=FsRtlUninitializeLargeMcb@4 +FsRtlUninitializeMcb=FsRtlUninitializeMcb@4 +FsRtlUninitializeOplock=FsRtlUninitializeOplock@4 +HalDispatchTable DATA +HalPrivateDispatchTable DATA +InterlockedCompareExchange=@InterlockedCompareExchange@12 +InterlockedDecrement=@InterlockedDecrement@4 +InterlockedExchange=@InterlockedExchange@8 +InterlockedExchangeAdd=@InterlockedExchangeAdd@8 +InterlockedIncrement=@InterlockedIncrement@4 +IoAcquireCancelSpinLock=IoAcquireCancelSpinLock@4 +IoAcquireVpbSpinLock=IoAcquireVpbSpinLock@4 +IoAdapterObjectType DATA +IoAllocateAdapterChannel=IoAllocateAdapterChannel@20 +IoAllocateIrp=IoAllocateIrp@8 +IoAllocateMdl=IoAllocateMdl@20 +IoAllocateController=IoAllocateController@16 +IoAllocateErrorLogEntry=IoAllocateErrorLogEntry@8 +IoAssignResources=IoAssignResources@24 +IoAttachDevice=IoAttachDevice@12 +IoAttachDeviceByPointer=IoAttachDeviceByPointer@8 +IoAttachDeviceToDeviceStack=IoAttachDeviceToDeviceStack@8 +IoBuildAsynchronousFsdRequest=IoBuildAsynchronousFsdRequest@24 +IoBuildDeviceIoControlRequest=IoBuildDeviceIoControlRequest@36 +IoBuildPartialMdl=IoBuildPartialMdl@16 +IoBuildSynchronousFsdRequest=IoBuildSynchronousFsdRequest@28 +IoCallDriver=IoCallDriver@8 +IoCancelIrp=IoCancelIrp@4 +IoCheckDesiredAccess=IoCheckDesiredAccess@8 +IoCheckEaBufferValidity=IoCheckEaBufferValidity@12 +IoCheckFunctionAccess=IoCheckFunctionAccess@24 +IoCheckShareAccess=IoCheckShareAccess@20 +IoCompleteRequest=IoCompleteRequest@8 +IoConnectInterrupt=IoConnectInterrupt@44 +IoCreateController=IoCreateController@4 +IoCreateDevice=IoCreateDevice@28 +IoCreateFile=IoCreateFile@56 +IoCreateNotificationEvent=IoCreateNotificationEvent@8 +IoCreateStreamFileObject=IoCreateStreamFileObject@8 +IoCreateSymbolicLink=IoCreateSymbolicLink@8 +IoCreateSynchronizationEvent=IoCreateSynchronizationEvent@8 +IoCreateUnprotectedSymbolicLink=IoCreateUnprotectedSymbolicLink@8 +IoDeleteController=IoDeleteController@4 +IoDeleteDevice=IoDeleteDevice@4 +IoDeleteSymbolicLink=IoDeleteSymbolicLink@4 +IoDetachDevice=IoDetachDevice@4 +IoDeviceHandlerObjectSize DATA +IoDeviceHandlerObjectType DATA +IoDeviceObjectType DATA +IoDisconnectInterrupt=IoDisconnectInterrupt@4 +IoDriverObjectType DATA +IoEnqueueIrp=IoEnqueueIrp@4 +IoFastQueryNetworkAttributes=IoFastQueryNetworkAttributes@20 +IoFileObjectType DATA +IoFreeController=IoFreeController@4 +IoFreeIrp=IoFreeIrp@4 +IoFreeMdl=IoFreeMdl@4 +IoGetAttachedDevice=IoGetAttachedDevice@4 +IoGetAttachedDeviceReference=IoGetAttachedDeviceReference@4 +IoGetBaseFileSystemDeviceObject=IoGetBaseFileSystemDeviceObject@4 +IoGetConfigurationInformation=IoGetConfigurationInformation@0 +IoGetCurrentProcess=IoGetCurrentProcess@0 +IoGetDeviceObjectPointer=IoGetDeviceObjectPointer@16 +IoGetDeviceToVerify=IoGetDeviceToVerify@4 +IoGetFileObjectGenericMapping=IoGetFileObjectGenericMapping@0 +IoGetInitialStack=IoGetInitialStack@0 +IoGetRelatedDeviceObject=IoGetRelatedDeviceObject@4 +IoGetRequestorProcess=IoGetRequestorProcess@4 +IoGetStackLimits=IoGetStackLimits@8 +IoGetTopLevelIrp=IoGetTopLevelIrp@0 +IoInitializeIrp=IoInitializeIrp@12 +IoInvalidateDeviceState=IoInvalidateDeviceState@4 +IoInitializeRemoveLockEx=IoInitializeRemoveLockEx@20 +IoInitializeTimer=IoInitializeTimer@12 +IoIsOperationSynchronous=IoIsOperationSynchronous@4 +IoMakeAssociatedIrp=IoMakeAssociatedIrp@8 +IoOpenDeviceInstanceKey=IoOpenDeviceInstanceKey@20 +IoPageRead=IoPageRead@20 +IoQueryDeviceDescription=IoQueryDeviceDescription@32 +IoQueryDeviceEnumInfo=IoQueryDeviceEnumInfo@8 +IoQueryFileInformation=IoQueryFileInformation@20 +IoQueryVolumeInformation=IoQueryVolumeInformation@20 +IoQueueThreadIrp=IoQueueThreadIrp@4 +IoRaiseHardError=IoRaiseHardError@12 +IoRaiseInformationalHardError=IoRaiseInformationalHardError@12 +IoReadOperationCount DATA +IoReadPartitionTable=IoReadPartitionTable@16 +IoReadTransferCount DATA + +IoFreeWorkItem=IoFreeWorkItem@4 +IoAllocateWorkItem=IoAllocateWorkItem@4 +IoQueueWorkItem=IoQueueWorkItem@16 +IoRegisterDeviceInterface=IoRegisterDeviceInterface@16 +IoSetDeviceInterfaceState=IoSetDeviceInterfaceState@8 +IoGetDeviceProperty=IoGetDeviceProperty@20 +IoOpenDeviceRegistryKey=IoOpenDeviceRegistryKey@16 +IoInvalidateDeviceRelations=IoInvalidateDeviceRelations@8 + +IoRegisterDriverReinitialization=IoRegisterDriverReinitialization@12 +IoRegisterFileSystem=IoRegisterFileSystem@4 +IoRegisterFsRegistrationChange=IoRegisterFsRegistrationChange@8 +IoRegisterShutdownNotification=IoRegisterShutdownNotification@4 +IoReleaseCancelSpinLock=IoReleaseCancelSpinLock@4 +IoReleaseRemoveLockAndWaitEx=IoReleaseRemoveLockAndWaitEx@12 +IoReleaseRemoveLockEx=IoReleaseRemoveLockEx@12 +IoReleaseVpbSpinLock=IoReleaseVpbSpinLock@4 +IoRemoveShareAccess=IoRemoveShareAccess@8 +IoReportHalResourceUsage=IoReportHalResourceUsage@16 +IoReportResourceUsage=IoReportResourceUsage@36 +IoSetDeviceToVerify=IoSetDeviceToVerify@8 +IoSetHardErrorOrVerifyDevice=IoSetHardErrorOrVerifyDevice@8 +IoSetInformation=IoSetInformation@16 +IoSetPartitionInformation=IoSetPartitionInformation@16 +IoSetShareAccess=IoSetShareAccess@16 +IoSetThreadHardErrorMode=IoSetThreadHardErrorMode@4 +IoSetTopLevelIrp=IoSetTopLevelIrp@4 +IoStartNextPacket=IoStartNextPacket@8 +IoStartNextPacketByKey=IoStartNextPacketByKey@12 +IoStartPacket=IoStartPacket@16 +IoStartTimer=IoStartTimer@4 +IoStatisticsLock DATA +IoStopTimer=IoStopTimer@4 +IoSynchronousPageWrite=IoSynchronousPageWrite@20 +IoThreadToProcess=IoThreadToProcess@4 +IoUnregisterFileSystem=IoUnregisterFileSystem@4 +IoUnregisterFsRegistrationChange=IoUnregisterFsRegistrationChange@8 +IoUnregisterShutdownNotification=IoUnregisterShutdownNotification@4 +IoUpdateShareAccess=IoUpdateShareAccess@8 +IoVerifyVolume=IoVerifyVolume@8 +IoWriteErrorLogEntry=IoWriteErrorLogEntry@4 +IoWriteOperationCount DATA +IoWritePartitionTable=IoWritePartitionTable@20 +IoWriteTransferCount DATA +IofCallDriver=@IofCallDriver@8 +IofCompleteRequest=@IofCompleteRequest@8 +KdDebuggerEnabled DATA +KdDebuggerNotPresent DATA +KdPollBreakIn=KdPollBreakIn@0 +KdSystemDebugControl=KdSystemDebugControl@4 +Ke386CallBios=Ke386CallBios@8 +;Ke386IoSetAccessProcess +;Ke386QueryIoAccessMap +;Ke386SetIoAccessMap +KeAcquireSpinLockAtDpcLevel=KeAcquireSpinLockAtDpcLevel@4 +KeAddSystemServiceTable=KeAddSystemServiceTable@20 +KeAttachProcess=KeAttachProcess@4 +;KeBoostCurrentThread +KeBugCheck=KeBugCheck@4 +KeBugCheckEx=KeBugCheckEx@20 +KeCancelTimer=KeCancelTimer@4 +KeClearEvent=KeClearEvent@4 +KeConnectInterrupt=KeConnectInterrupt@4 +KeDcacheFlushCount DATA +KeDelayExecutionThread=KeDelayExecutionThread@12 +KeDeregisterBugCheckCallback=KeDeregisterBugCheckCallback@4 +KeDetachProcess=KeDetachProcess@0 +KeDisconnectInterrupt=KeDisconnectInterrupt@4 +KeEnterCriticalRegion=KeEnterCriticalRegion@0 +KeEnterKernelDebugger=KeEnterKernelDebugger@0 +;KeFindConfigurationEntry +;KeFindConfigurationNextEntry +;KeFlushEntireTb +KeGetCurrentThread=KeGetCurrentThread@0 +KeGetPreviousMode=KeGetPreviousMode@0 +;KeI386AbiosCall +;KeI386AllocateGdtSelectors +;KeI386Call16BitCStyleFunction +;KeI386Call16BitFunction +;KeI386FlatToGdtSelector +;KeI386GetLid +;KeI386MachineType DATA +;KeI386ReleaseGdtSelectors +;KeI386ReleaseLid +;KeI386SetGdtSelector +KeIcacheFlushCount DATA +KeInitializeApc=KeInitializeApc@32 +KeInitializeDeviceQueue=KeInitializeDeviceQueue@4 +KeInitializeDpc=KeInitializeDpc@12 +KeInitializeEvent=KeInitializeEvent@12 +KeInitializeInterrupt=KeInitializeInterrupt@44 +KeInitializeMutant=KeInitializeMutant@8 +KeInitializeMutex=KeInitializeMutex@8 +KeInitializeQueue=KeInitializeQueue@8 +KeInitializeSemaphore=KeInitializeSemaphore@12 +KeInitializeSpinLock=KeInitializeSpinLock@4 +KeInitializeTimer=KeInitializeTimer@4 +KeInitializeTimerEx=KeInitializeTimerEx@8 +KeInsertByKeyDeviceQueue=KeInsertByKeyDeviceQueue@12 +KeInsertDeviceQueue=KeInsertDeviceQueue@8 +KeInsertHeadQueue=KeInsertHeadQueue@8 +KeInsertQueue=KeInsertQueue@8 +KeInsertQueueApc=KeInsertQueueApc@16 +KeInsertQueueDpc=KeInsertQueueDpc@12 +;KeIsExecutingDpc +KeLeaveCriticalRegion=KeLeaveCriticalRegion@0 +KeLoaderBlock DATA +KeNumberProcessors DATA +;KeProfileInterrupt +;KeProfileInterruptWithSource +KePulseEvent=KePulseEvent@12 +KeQuerySystemTime=KeQuerySystemTime@4 +KeQueryTickCount=KeQueryTickCount@4 +KeQueryTimeIncrement=KeQueryTimeIncrement@0 +;KeRaiseUserException +KeReadStateEvent=KeReadStateEvent@4 +KeReadStateMutant=KeReadStateMutant@4 +KeReadStateMutex=KeReadStateMutex@4 +KeReadStateQueue=KeReadStateQueue@4 +KeReadStateSemaphore=KeReadStateSemaphore@4 +KeReadStateTimer=KeReadStateTimer@4 +KeRegisterBugCheckCallback=KeRegisterBugCheckCallback@20 +KeReleaseMutant=KeReleaseMutant@16 +KeReleaseMutex=KeReleaseMutex@8 +KeReleaseSemaphore=KeReleaseSemaphore@16 +KeReleaseSpinLockFromDpcLevel=KeReleaseSpinLockFromDpcLevel@4 +KeRemoveByKeyDeviceQueue=KeRemoveByKeyDeviceQueue@8 +KeRemoveDeviceQueue=KeRemoveDeviceQueue@4 +KeRemoveEntryDeviceQueue=KeRemoveEntryDeviceQueue@8 +KeRemoveQueue=KeRemoveQueue@12 +KeRemoveQueueDpc=KeRemoveQueueDpc@4 +KeResetEvent=KeResetEvent@4 +;KeRestoreFloatingPointState +KeRundownQueue=KeRundownQueue@4 +;KeSaveFloatingPointState +KeServiceDescriptorTable DATA +;KeSetAffinityThread +KeSetBasePriorityThread=KeSetBasePriorityThread@8 +;KeSetDmaIoCoherency +KeSetEvent=KeSetEvent@12 +;KeSetEventBoostPriority +;KeSetIdealProcessorThread +KeSetImportanceDpc=KeSetImportanceDpc@8 +;KeSetKernelStackSwapEnable +KeSetPriorityThread=KeSetPriorityThread@8 +;KeSetProfileIrql +;KeSetSwapContextNotifyRoutine +KeSetTargetProcessorDpc=KeSetTargetProcessorDpc@8 +;KeSetThreadSelectNotifyRoutine +;KeSetTimeIncrement +KeSetTimer=KeSetTimer@16 +KeSetTimerEx=KeSetTimerEx@20 +;KeSetTimeUpdateNotifyRoutine +KeSynchronizeExecution=KeSynchronizeExecution@12 +;KeTerminateThread +KeTickCount DATA +;KeUpdateRunTime +;KeUserModeCallback +KeWaitForMultipleObjects=KeWaitForMultipleObjects@32 +KeWaitForMutexObject=KeWaitForMutexObject@20 +KeWaitForSingleObject=KeWaitForSingleObject@20 +;KefAcquireSpinLockAtDpcLevel +;KefReleaseSpinLockFromDpcLevel +;Kei386EoiHelper +;KiAcquireSpinLock@4 +;KiBugCheckData DATA +;KiCoprocessorError@0 +KiDeliverApc=KiDeliverApc@12 +KiDispatchInterrupt=KiDispatchInterrupt@0 +KiInterruptDispatch2=KiInterruptDispatch2@8 +;KiIpiServiceRoutine@8 +;KiReleaseSpinLock@4 +;KiUnexpectedInterrupt +;Kii386SpinOnSpinLock +KiRawTicks DATA +LdrAccessResource=LdrAccessResource@16 +;LdrEnumResources@20 +;LdrFindResourceDirectory_U@16 +LdrFindResource_U=LdrFindResource_U@16 +;LpcRequestPort@8 +LsaCallAuthenticationPackage=LsaCallAuthenticationPackage@28 +LsaDeregisterLogonProcess=LsaDeregisterLogonProcess@8 +LsaFreeReturnBuffer=LsaFreeReturnBuffer@4 +LsaLogonUser=LsaLogonUser@56 +LsaLookupAuthenticationPackage=LsaLookupAuthenticationPackage@12 +LsaRegisterLogonProcess=LsaRegisterLogonProcess@12 +MmAdjustWorkingSetSize=MmAdjustWorkingSetSize@12 +MmAllocateContiguousAlignedMemory=MmAllocateContiguousAlignedMemory@16 +MmAllocateContiguousMemory=MmAllocateContiguousMemory@12 +MmAllocateNonCachedMemory=MmAllocateNonCachedMemory@4 +MmBuildMdlForNonPagedPool=MmBuildMdlForNonPagedPool@4 +MmCanFileBeTruncated=MmCanFileBeTruncated@8 +MmCopyFromCaller=MmCopyFromCaller@12 +MmCopyToCaller=MmCopyToCaller@12 +MmCreateMdl=MmCreateMdl@12 +MmCreateSection=MmCreateSection@32 +MmDbgTranslatePhysicalAddress=MmDbgTranslatePhysicalAddress@8 +MmDisableModifiedWriteOfSection=MmDisableModifiedWriteOfSection@4 +MmFlushImageSection=MmFlushImageSection@8 +MmForceSectionClosed=MmForceSectionClosed@8 +MmFreeContiguousMemory=MmFreeContiguousMemory@4 +MmFreeNonCachedMemory=MmFreeNonCachedMemory@8 +MmGetPhysicalAddress=MmGetPhysicalAddress@4 +MmGrowKernelStack=MmGrowKernelStack@4 +MmHighestUserAddress DATA +MmIsAddressValid=MmIsAddressValid@4 +MmIsNonPagedSystemAddressValid=MmIsNonPagedSystemAddressValid@4 +MmIsRecursiveIoFault=MmIsRecursiveIoFault@0 +MmIsThisAnNtAsSystem=MmIsThisAnNtAsSystem@0 +MmLockPagableDataSection=MmLockPagableDataSection@4 +MmLockPagableImageSection=MmLockPagableDataSection@4 +MmLockPagableSectionByHandle=MmLockPagableSectionByHandle@4 +MmMapIoSpace=MmMapIoSpace@16 +MmMapLockedPages=MmMapLockedPages@8 +MmMapMemoryDumpMdl=MmMapMemoryDumpMdl@4 +MmMapVideoDisplay=MmMapVideoDisplay@16 +MmMapViewInSystemSpace=MmMapViewInSystemSpace@12 +MmMapViewOfSection=MmMapViewOfSection@40 +MmPageEntireDriver=MmPageEntireDriver@4 +MmProbeAndLockPages=MmProbeAndLockPages@12 +MmQuerySystemSize=MmQuerySystemSize@0 +MmResetDriverPaging=MmResetDriverPaging@4 +MmSectionObjectType DATA +MmSecureVirtualMemory=MmSecureVirtualMemory@12 +MmSetAddressRangeModified=MmSetAddressRangeModified@8 +MmSetBankedSection=MmSetBankedSection@24 +MmSizeOfMdl=MmSizeOfMdl@8 +MmUnlockPagableImageSection=MmUnlockPagableImageSection@4 +MmUnlockPages=MmUnlockPages@4 +MmUnmapIoSpace=MmUnmapIoSpace@8 +MmUnmapLockedPages=MmUnmapLockedPages@8 +MmUnmapVideoDisplay=MmUnmapVideoDisplay@8 +MmUnmapViewInSystemSpace=MmUnmapViewInSystemSpace@4 +MmUnmapViewOfSection=MmUnmapViewOfSection@8 +MmUnsecureVirtualMemory=MmUnsecureVirtualMemory@4 +MmUserProbeAddress DATA +NlsAnsiCodePage DATA +NlsLeadByteInfo DATA +NlsMbCodePageTag DATA +NlsMbOemCodePageTag DATA +NlsOemLeadByteInfo DATA +NtAddAtom=NtAddAtom@8 +NtAdjustPrivilegesToken=NtAdjustPrivilegesToken@24 +NtAlertThread=NtAlertThread@4 +NtAllocateLocallyUniqueId=NtAllocateLocallyUniqueId@4 +NtAllocateUuids=NtAllocateUuids@12 +NtAllocateVirtualMemory=NtAllocateVirtualMemory@24 +NtBuildNumber DATA +NtClose=NtClose@4 +NtConnectPort=NtConnectPort@32 +NtCreateEvent=NtCreateEvent@20 +NtCreateTimer=NtCreateTimer@16 +NtOpenEvent=NtOpenEvent@12 +NtCreateFile=NtCreateFile@44 +NtCreateSection=NtCreateSection@28 +NtDeleteAtom=NtDeleteAtom@4 +NtDeleteFile=NtDeleteFile@4 +NtDeviceIoControlFile=NtDeviceIoControlFile@40 +NtDuplicateObject=NtDuplicateObject@28 +NtDuplicateToken=NtDuplicateToken@24 +NtFindAtom=NtFindAtom@8 +NtFreeVirtualMemory=NtFreeVirtualMemory@16 +NtFsControlFile=NtFsControlFile@40 +NtGlobalFlag DATA +NtLockFile=NtLockFile@40 +NtMapViewOfSection=NtMapViewOfSection@40 +NtNotifyChangeDirectoryFile=NtNotifyChangeDirectoryFile@36 +NtOpenFile=NtOpenFile@24 +NtOpenProcess=NtOpenProcess@16 +NtOpenProcessToken=NtOpenProcessToken@12 +NtQueryDirectoryFile=NtQueryDirectoryFile@44 +NtQueryEaFile=NtQueryEaFile@36 +NtQueryInformationAtom=NtQueryInformationAtom@20 +NtQueryInformationFile=NtQueryInformationFile@20 +NtQueryInformationProcess=NtQueryInformationProcess@20 +NtQueryInformationToken=NtQueryInformationToken@20 +;NtQueryOleDirectoryFile@44 <--- ? +NtQuerySecurityObject=NtQuerySecurityObject@20 +NtQuerySystemTime=NtQuerySystemTime@4 +NtQueryVolumeInformationFile=NtQueryVolumeInformationFile@20 +NtReadFile=NtReadFile@36 +NtRequestPort=NtRequestPort@8 +NtRequestWaitReplyPort@12 +NtSetEvent=NtSetEvent@8 +NtSetInformationFile=NtSetInformationFile@20 +NtSetInformationProcess=NtSetInformationProcess@16 +NtSetInformationThread=NtSetInformationThread@16 +NtSetSecurityObject=NtSetSecurityObject@12 +NtSetSystemTime=NtSetSystemTime@8 +NtUnlockFile=NtUnlockFile@20 +NtVdmControl=NtVdmControl@8 +NtW32Call=NtW32Call@20 +NtWaitForSingleObject=NtWaitForSingleObject@12 +NtWriteFile=NtWriteFile@36 +ObAssignSecurity=ObAssignSecurity@16 +;ObCheckCreateObjectAccess=ObCheckCreateObjectAccess@28 +;ObCheckObjectAccess=ObCheckObjectAccess@20 +;ObCreateObject=ObCreateObject@36 +ObCreateObject=ObCreateObject@20 +;ObFindHandleForObject=ObFindHandleForObject@20 +ObGetObjectPointerCount=ObGetObjectPointerCount@4 +ObGetObjectSecurity=ObGetObjectSecurity@12 +;ObInsertObject=ObInsertObject@24 +ObMakeTemporaryObject=ObMakeTemporaryObject@4 +ObOpenObjectByName=ObOpenObjectByName@28 +ObOpenObjectByPointer=ObOpenObjectByPointer@28 +;ObQueryNameString=ObQueryNameString@16 +;ObQueryObjectAuditingByHandle=ObQueryObjectAuditingByHandle@8 +ObfDereferenceObject=@ObfDereferenceObject@4 +ObfReferenceObject=@ObfReferenceObject@4 +ObReferenceObjectByHandle=ObReferenceObjectByHandle@24 +ObReferenceObjectByName=ObReferenceObjectByName@32 +ObReferenceObjectByPointer=ObReferenceObjectByPointer@16 +ObReleaseObjectSecurity=ObReleaseObjectSecurity@8 +;ObSetSecurityDescriptorInfo=ObSetSecurityDescriptorInfo@24 +;PfxFindPrefix +;PfxInitialize +;PfxInsertPrefix +;PfxRemovePrefix +PoCallDriver=PoCallDriver@8 +PoRegisterDeviceForIdleDetection=PoRegisterDeviceForIdleDetection@16 +PoRegisterSystemState=PoRegisterSystemState@8 +PoRequestPowerIrp=PoRequestPowerIrp@24 +PoSetDeviceBusy=PoSetDeviceBusy@4 +PoSetPowerState=PoSetPowerState@12 +PoSetSystemState=PoSetSystemState@4 +PoStartNextPowerIrp=PoStartNextPowerIrp@4 +PoUnregisterSystemState=PoUnregisterSystemState@4 +;ProbeForWrite=ProbeForWrite@12 +PsAssignImpersonationToken=PsAssignImpersonationToken@8 +;PsChargePoolQuota=PsChargePoolQuota@12 +PsCreateSystemProcess=PsCreateSystemProcess@12 +PsCreateSystemThread=PsCreateSystemThread@28 +PsCreateWin32Thread=PsCreateWin32Thread@4 +PsCreateWin32Process=PsCreateWin32Process@4 +PsGetWin32Thread=PsGetWin32Thread@0 +PsGetWin32Process=PsGetWin32Process@0 +PsEstablishWin32Callouts=PsEstablishWin32Callouts@24 +PsGetCurrentProcess=PsGetCurrentProcess@0 +PsGetCurrentProcessId=PsGetCurrentProcessId@0 +PsGetCurrentThreadId=PsGetCurrentThreadId@0 +PsGetCurrentThread=PsGetCurrentThread@0 +PsGetProcessExitTime=PsGetProcessExitTime@0 +PsGetVersion=PsGetVersion@16 +PsImpersonateClient=PsImpersonateClient@20 +PsInitialSystemProcess DATA +PsIsThreadTerminating=PsIsThreadTerminating@4 +PsLookupProcessByProcessId=PsLookupProcessByProcessId@8 +PsLookupProcessThreadByCid=PsLookupProcessThreadByCid@12 +PsLookupThreadByThreadId=PsLookupThreadByThreadId@8 +PsProcessType DATA +PsReferenceImpersonationToken=PsReferenceImpersonationToken@16 +PsReferencePrimaryToken=PsReferencePrimaryToken@4 +;PsReturnPoolQuota +PsRevertToSelf=PsRevertToSelf@0 +PsSetCreateProcessNotifyRoutine=PsSetCreateProcessNotifyRoutine@8 +PsSetCreateThreadNotifyRoutine=PsSetCreateThreadNotifyRoutine@4 +;PsSetLegoNotifyRoutine +;PsSetProcessPriorityByClass +PsTerminateSystemThread=PsTerminateSystemThread@4 +PsThreadType DATA +READ_REGISTER_UCHAR=READ_REGISTER_UCHAR@4 +READ_REGISTER_ULONG=READ_REGISTER_ULONG@4 +READ_REGISTER_USHORT=READ_REGISTER_USHORT@4 +READ_REGISTER_BUFFER_UCHAR=READ_REGISTER_BUFFER_UCHAR@12 +READ_REGISTER_BUFFER_ULONG=READ_REGISTER_BUFFER_ULONG@12 +READ_REGISTER_BUFFER_USHORT=READ_REGISTER_BUFFER_USHORT@12 +RtlAbsoluteToSelfRelativeSD=RtlAbsoluteToSelfRelativeSD@12 +RtlAddAccessAllowedAce=RtlAddAccessAllowedAce@16 +RtlAddAce=RtlAddAce@20 +RtlAddAtomToAtomTable=RtlAddAtomToAtomTable@12 +;RtlAllocateAndInitializeSid +;RtlAllocateHeap +RtlAnsiCharToUnicodeChar=RtlAnsiCharToUnicodeChar@4 +RtlAnsiStringToUnicodeSize=RtlAnsiStringToUnicodeSize@4 +RtlAnsiStringToUnicodeString=RtlAnsiStringToUnicodeString@12 +RtlAppendAsciizToString=RtlAppendAsciizToString@8 +RtlAppendStringToString=RtlAppendStringToString@8 +RtlAppendUnicodeStringToString=RtlAppendUnicodeStringToString@8 +RtlAppendUnicodeToString=RtlAppendUnicodeToString@8 +RtlAreAllAccessesGranted=RtlAreAllAccessesGranted@8 +RtlAreAnyAccessesGranted=RtlAreAnyAccessesGranted@8 +RtlAreBitsClear=RtlAreBitsClear@12 +RtlAreBitsSet=RtlAreBitsSet@12 +RtlAssert=RtlAssert@16 +;RtlCaptureStackBackTrace +RtlCharToInteger=RtlCharToInteger@12 +RtlCheckRegistryKey=RtlCheckRegistryKey@8 +RtlClearAllBits=RtlClearAllBits@4 +RtlClearBits=RtlClearBits@12 +RtlCompareMemory=RtlCompareMemory@12 +RtlCompareMemoryUlong=RtlCompareMemoryUlong@12 +RtlCompareString=RtlCompareString@12 +RtlCompareUnicodeString=RtlCompareUnicodeString@12 +RtlCompressBuffer=RtlCompressBuffer@32 +RtlCompressChunks=RtlCompressChunks@28 +RtlConvertLongToLargeInteger=RtlConvertLongToLargeInteger@4 +RtlConvertSidToUnicodeString=RtlConvertSidToUnicodeString@12 +RtlConvertUlongToLargeInteger=RtlConvertUlongToLargeInteger@4 +RtlCopyLuid=RtlCopyLuid@8 +RtlCopySid=RtlCopySid@12 +RtlCopyString=RtlCopyString@8 +RtlCopyUnicodeString=RtlCopyUnicodeString@8 +RtlCreateAcl=RtlCreateAcl@12 +RtlCreateAtomTable=RtlCreateAtomTable@8 +;RtlCreateHeap +RtlCreateRegistryKey=RtlCreateRegistryKey@8 +RtlCreateSecurityDescriptor=RtlCreateSecurityDescriptor@8 +RtlCreateUnicodeString=RtlCreateUnicodeString@8 +RtlCustomCPToUnicodeN=RtlCustomCPToUnicodeN@24 +RtlDecompressBuffer=RtlDecompressBuffer@24 +RtlDecompressChunks=RtlDecompressChunks@28 +RtlDecompressFragment=RtlDecompressFragment@32 +;RtlDelete +RtlDeleteAtomFromAtomTable=RtlDeleteAtomFromAtomTable@8 +;RtlDeleteElementGenericTable +;RtlDeleteNoSplay +RtlDeleteRegistryValue=RtlDeleteRegistryValue@12 +RtlDescribeChunk=RtlDescribeChunk@20 +RtlDestroyAtomTable=RtlDestroyAtomTable@4 +;RtlDestroyHeap +RtlDowncaseUnicodeString=RtlDowncaseUnicodeString@12 +RtlEmptyAtomTable=RtlEmptyAtomTable@8 +RtlEnlargedIntegerMultiply=RtlEnlargedIntegerMultiply@8 +RtlEnlargedUnsignedDivide=RtlEnlargedUnsignedDivide@16 +RtlEnlargedUnsignedMultiply=RtlEnlargedUnsignedMultiply@8 +;RtlEnumerateGenericTable +;RtlEnumerateGenericTableWithoutSplaying +RtlEqualLuid=RtlEqualLuid@8 +RtlEqualSid=RtlEqualSid@8 +RtlEqualString=RtlEqualString@12 +RtlEqualUnicodeString=RtlEqualUnicodeString@12 +RtlExtendedIntegerMultiply=RtlExtendedIntegerMultiply@12 +RtlExtendedLargeIntegerDivide=RtlExtendedLargeIntegerDivide@16 +RtlExtendedMagicDivide=RtlExtendedMagicDivide@20 +RtlFillMemory=RtlFillMemory@12 +RtlFillMemoryUlong=RtlFillMemoryUlong@12 +RtlFindClearBits=RtlFindClearBits@12 +RtlFindClearBitsAndSet=RtlFindClearBitsAndSet@12 +RtlFindFirstRunClear=RtlFindFirstRunClear@8 +RtlFindFirstRunSet=RtlFindFirstRunSet@8 +RtlFindLongestRunClear=RtlFindLongestRunClear@8 +RtlFindLongestRunSet=RtlFindLongestRunSet@8 +RtlFindMessage=RtlFindMessage@20 +RtlFindSetBits=RtlFindSetBits@12 +RtlFindSetBitsAndClear=RtlFindSetBitsAndClear@12 +;RtlFindUnicodePrefix +RtlFormatCurrentUserKeyPath=RtlFormatCurrentUserKeyPath@4 +RtlFreeAnsiString=RtlFreeAnsiString@4 +;RtlFreeHeap +RtlFreeOemString=RtlFreeOemString@4 +RtlFreeUnicodeString=RtlFreeUnicodeString@4 +RtlGenerate8dot3Name=RtlGenerate8dot3Name@16 +;RtlGetCallersAddress +RtlGetCompressionWorkSpaceSize=RtlGetCompressionWorkSpaceSize@12 +RtlGetDaclSecurityDescriptor=RtlGetDaclSecurityDescriptor@16 +RtlGetDefaultCodePage=RtlGetDefaultCodePage@8 +;RtlGetElementGenericTable +RtlGetGroupSecurityDescriptor=RtlGetGroupSecurityDescriptor@12 +RtlGetOwnerSecurityDescriptor=RtlGetOwnerSecurityDescriptor@12 +RtlImageNtHeader=RtlImageNtHeader@4 +RtlInitAnsiString=RtlInitAnsiString@8 +;RtlInitCodePageTable +RtlInitString=RtlInitString@8 +RtlInitUnicodeString=RtlInitUnicodeString@8 +RtlInitializeBitMap=RtlInitializeBitMap@12 +;RtlInitializeGenericTable +RtlInitializeSid=RtlInitializeSid@12 +;RtlInitializeUnicodePrefix +;RtlInsertElementGenericTable +;RtlInsertUnicodePrefix +RtlIntegerToChar=RtlIntegerToChar@16 +RtlIntegerToUnicodeString=RtlIntegerToUnicodeString@12 +RtlIsNameLegalDOS8Dot3=RtlIsNameLegalDOS8Dot3@12 +RtlLargeIntegerAdd=RtlLargeIntegerAdd@16 +RtlLargeIntegerArithmeticShift=RtlLargeIntegerArithmeticShift@12 +RtlLargeIntegerDivide=RtlLargeIntegerDivide@20 +RtlLargeIntegerNegate=RtlLargeIntegerNegate@8 +RtlLargeIntegerShiftLeft=RtlLargeIntegerShiftLeft@12 +RtlLargeIntegerShiftRight=RtlLargeIntegerShiftRight@12 +RtlLargeIntegerSubtract=RtlLargeIntegerSubtract@16 +RtlLengthRequiredSid=RtlLengthRequiredSid@4 +RtlLengthSecurityDescriptor=RtlLengthSecurityDescriptor@4 +RtlLengthSid=RtlLengthSid@4 +RtlLookupAtomInAtomTable=RtlLookupAtomInAtomTable@12 +;RtlLookupElementGenericTable +RtlMapGenericMask=RtlMapGenericMask@8 +RtlMoveMemory=RtlMoveMemory@12 +RtlMultiByteToUnicodeN=RtlMultiByteToUnicodeN@20 +RtlMultiByteToUnicodeSize=RtlMultiByteToUnicodeSize@12 +;RtlNextUnicodePrefix +RtlNtStatusToDosError=RtlNtStatusToDosError@4 +RtlNtStatusToDosErrorNoTeb=RtlNtStatusToDosErrorNoTeb@4 +;RtlNumberGenericTableElements +RtlNumberOfClearBits=RtlNumberOfClearBits@4 +RtlNumberOfSetBits=RtlNumberOfSetBits@4 +RtlOemStringToCountedUnicodeString=RtlOemStringToCountedUnicodeString@12 +RtlOemStringToUnicodeSize=RtlOemStringToUnicodeSize@4 +RtlOemStringToUnicodeString=RtlOemStringToUnicodeString@12 +RtlPinAtomInAtomTable=RtlPinAtomInAtomTable@8 +RtlPrefixString=RtlPrefixString@12 +RtlPrefixUnicodeString=RtlPrefixUnicodeString@12 +RtlQueryAtomInAtomTable=RtlQueryAtomInAtomTable@24 +RtlQueryRegistryValues=RtlQueryRegistryValues@20 +RtlQueryTimeZoneInformation=RtlQueryTimeZoneInformation@4 +RtlRaiseException=RtlRaiseException@4 +;RtlRandom +;RtlRemoveUnicodePrefix +RtlReserveChunk=RtlReserveChunk@20 +RtlSecondsSince1970ToTime=RtlSecondsSince1970ToTime@8 +RtlSecondsSince1980ToTime=RtlSecondsSince1980ToTime@8 +RtlSetAllBits=RtlSetAllBits@4 +RtlSetBits=RtlSetBits@12 +RtlSetDaclSecurityDescriptor=RtlSetDaclSecurityDescriptor@16 +RtlSetGroupSecurityDescriptor=RtlSetGroupSecurityDescriptor@12 +RtlSetOwnerSecurityDescriptor=RtlSetOwnerSecurityDescriptor@12 +RtlSetSaclSecurityDescriptor=RtlSetSaclSecurityDescriptor@16 +RtlSetTimeZoneInformation=RtlSetTimeZoneInformation@4 +;RtlSplay +RtlSubAuthorityCountSid=RtlSubAuthorityCountSid@4 +RtlSubAuthoritySid=RtlSubAuthoritySid@8 +RtlTimeFieldsToTime=RtlTimeFieldsToTime@8 +RtlTimeToSecondsSince1970=RtlTimeToSecondsSince1970@8 +RtlTimeToSecondsSince1980=RtlTimeToSecondsSince1980@8 +RtlTimeToTimeFields=RtlTimeToTimeFields@8 +RtlUnicodeStringToAnsiSize=RtlUnicodeStringToAnsiSize@4 +RtlUnicodeStringToAnsiString=RtlUnicodeStringToAnsiString@12 +RtlUnicodeStringToCountedOemString=RtlUnicodeStringToCountedOemString@12 +RtlUnicodeStringToInteger=RtlUnicodeStringToInteger@12 +RtlUnicodeStringToOemSize=RtlUnicodeStringToOemSize@4 +RtlUnicodeStringToOemString=RtlUnicodeStringToOemString@12 +RtlUnicodeToCustomCPN=RtlUnicodeToCustomCPN@24 +RtlUnicodeToMultiByteN=RtlUnicodeToMultiByteN@20 +RtlUnicodeToMultiByteSize=RtlUnicodeToMultiByteSize@12 +RtlUnicodeToOemN=RtlUnicodeToOemN@20 +RtlUnwind=RtlUnwind@16 +RtlUpcaseUnicodeChar=RtlUpcaseUnicodeChar@4 +RtlUpcaseUnicodeString=RtlUpcaseUnicodeString@12 +RtlUpcaseUnicodeStringToAnsiString=RtlUpcaseUnicodeStringToAnsiString@12 +RtlUpcaseUnicodeStringToCountedOemString=RtlUpcaseUnicodeStringToCountedOemString@12 +RtlUpcaseUnicodeStringToOemString=RtlUpcaseUnicodeStringToOemString@12 +RtlUpcaseUnicodeToCustomCPN=RtlUpcaseUnicodeToCustomCPN@24 +RtlUpcaseUnicodeToMultiByteN=RtlUpcaseUnicodeToMultiByteN@20 +RtlUpcaseUnicodeToOemN=RtlUpcaseUnicodeToOemN@20 +RtlUpperChar=RtlUpperChar@4 +RtlUpperString=RtlUpperString@8 +RtlValidSecurityDescriptor=RtlValidSecurityDescriptor@4 +RtlValidSid=RtlValidSid@4 +RtlWriteRegistryValue=RtlWriteRegistryValue@24 +;RtlZeroHeap +RtlZeroMemory=RtlZeroMemory@8 +RtlxAnsiStringToUnicodeSize=RtlxAnsiStringToUnicodeSize@4 +RtlxOemStringToUnicodeSize=RtlxOemStringToUnicodeSize@4 +RtlxUnicodeStringToAnsiSize=RtlxUnicodeStringToAnsiSize@4 +RtlxUnicodeStringToOemSize=RtlxUnicodeStringToOemSize@4 +SeAccessCheck=SeAccessCheck@40 +;SeAppendPrivileges=SeAppendPrivileges@8 +SeAssignSecurity=SeAssignSecurity@28 +;SeAuditingFileEvents=SeAuditingFileEvents@8 +;SeAuditingFileOrGlobalEvents=SeAuditingFileOrGlobalEvents@18 +;SeCaptureSecurityDescriptor=SeCaptureSecurityDescriptor@20 +SeCaptureSubjectContext=SeCaptureSubjectContext@4 +;SeCloseObjectAuditAlarm=SeCloseObjectAuditAlarm@12 +;SeCreateAccessState=SeCreateAccessState@16 +SeCreateClientSecurity=SeCreateClientSecurity@16 +SeDeassignSecurity=SeDeassignSecurity@4 +;SeDeleteAccessState=SeDeleteAccessState@4 +;SeDeleteObjectAuditAlarm=SeDeleteObjectAuditAlarm@8 +SeExports DATA +;SeFreePrivileges=SeFreePrivileges@4 +SeImpersonateClient=SeImpersonateClient@8 +;SeLockSubjectContext=SeLockSubjectContext@4 +;SeMarkLogonSessionForTerminationNotification=SeMarkLogonSessionForTerminationNotification@4 +;SeOpenObjectAuditAlarm=SeOpenObjectAuditAlarm@36 +;SeOpenObjectForDeleteAuditAlarm=SeOpenObjectForDeleteAuditAlarm@36 +SePrivilegeCheck=SePrivilegeCheck@12 +;SePrivilegeObjectAuditAlarm=SePrivilegeObjectAuditAlarm@24 +SePublicDefaultDacl DATA +;SeQueryAuthenticationIdToken=SeQueryAuthenticationIdToken@8 +;SeQuerySecurityDescriptorInfo=SeQuerySecurityDescriptorInfo@16 +;SeRegisterLogonSessionTerminatedRoutine=SeRegisterLogonSessionTerminatedRoutine@4 +;SeReleaseSecurityDescriptor=SeReleaseSecurityDescriptor@12 +SeReleaseSubjectContext=SeReleaseSubjectContext@4 +;SeSetAccessStateGenericMapping=SeSetAccessStateGenericMapping@8 +;SeSetSecurityDescriptorInfo=SeSetSecurityDescriptorInfo@24 +SeSinglePrivilegeCheck=SeSinglePrivilegeCheck@12 +SeSystemDefaultDacl DATA +SeTokenImpersonationLevel=SeTokenImpersonationLevel@4 +SeTokenType=SeTokenType@4 +;SeUnlockSubjectContext=SeUnlockSubjectContext@4 +;SeUnregisterLogonSessionTerminatedRoutine=SeUnregisterLogonSessionTerminatedRoutine@4 +;SeValidSecurityDescriptor=SeValidSecurityDescriptor@8 +WRITE_REGISTER_UCHAR=WRITE_REGISTER_UCHAR@8 +WRITE_REGISTER_ULONG=WRITE_REGISTER_ULONG@8 +WRITE_REGISTER_USHORT=WRITE_REGISTER_USHORT@8 +WRITE_REGISTER_BUFFER_UCHAR=WRITE_REGISTER_BUFFER_UCHAR@12 +WRITE_REGISTER_BUFFER_ULONG=WRITE_REGISTER_BUFFER_ULONG@12 +WRITE_REGISTER_BUFFER_USHORT=WRITE_REGISTER_BUFFER_USHORT@12 +ZwAccessCheckAndAuditAlarm=ZwAccessCheckAndAuditAlarm@44 +ZwAlertThread=ZwAlertThread@4 +ZwAllocateVirtualMemory=ZwAllocateVirtualMemory@24 +ZwClearEvent=ZwClearEvent@4 +ZwClose=ZwClose@4 +ZwCloseObjectAuditAlarm=ZwCloseObjectAuditAlarm@12 +ZwConnectPort=ZwConnectPort@32 +ZwCreateDirectoryObject=ZwCreateDirectoryObject@12 +ZwCreateEvent=ZwCreateEvent@20 +ZwCreateFile=ZwCreateFile@44 +ZwCreateKey=ZwCreateKey@28 +ZwCreateSection=ZwCreateSection@28 +ZwCreateSymbolicLinkObject=ZwCreateSymbolicLinkObject@16 +ZwDeleteFile=ZwDeleteFile@4 +ZwDeleteKey=ZwDeleteKey@4 +ZwDeleteValueKey=ZwDeleteValueKey@8 +ZwDeviceIoControlFile=ZwDeviceIoControlFile@40 +ZwDisplayString=ZwDisplayString@4 +ZwDuplicateObject=ZwDuplicateObject@28 +ZwDuplicateToken=ZwDuplicateToken@24 +ZwEnumerateKey=ZwEnumerateKey@24 +ZwEnumerateValueKey=ZwEnumerateValueKey@24 +ZwFlushInstructionCache=ZwFlushInstructionCache@12 +ZwFlushKey=ZwFlushKey@4 +ZwFreeVirtualMemory=ZwFreeVirtualMemory@16 +ZwFsControlFile=ZwFsControlFile@40 +ZwLoadDriver=ZwLoadDriver@4 +ZwLoadKey=ZwLoadKey@8 +ZwMakeTemporaryObject=ZwMakeTemporaryObject@4 +ZwMapViewOfSection=ZwMapViewOfSection@40 +ZwNotifyChangeKey=ZwNotifyChangeKey@40 +ZwOpenDirectoryObject=ZwOpenDirectoryObject@12 +ZwOpenEvent=ZwOpenEvent@12 +ZwOpenFile=ZwOpenFile@24 +ZwOpenKey=ZwOpenKey@12 +ZwOpenProcess=ZwOpenProcess@16 +ZwOpenProcessToken=ZwOpenProcessToken@12 +ZwOpenSection=ZwOpenSection@12 +ZwOpenSymbolicLinkObject=ZwOpenSymbolicLinkObject@12 +ZwOpenThread=ZwOpenThread@16 +ZwOpenThreadToken=ZwOpenThreadToken@16 +ZwPulseEvent=ZwPulseEvent@8 +ZwQueryDefaultLocale=ZwQueryDefaultLocale@8 +ZwQueryDirectoryFile=ZwQueryDirectoryFile@44 +ZwQueryInformationAtom=ZwQueryInformationAtom@20 +ZwQueryInformationFile=ZwQueryInformationFile@20 +ZwQueryInformationProcess=ZwQueryInformationProcess@20 +ZwQueryInformationToken=ZwQueryInformationToken@20 +ZwQueryKey=ZwQueryKey@20 +ZwQueryObject=ZwQueryObject@20 +ZwQuerySection=ZwQuerySection@20 +ZwQuerySecurityObject=ZwQuerySecurityObject@20 +ZwQuerySymbolicLinkObject=ZwQuerySymbolicLinkObject@12 +ZwQuerySystemInformation=ZwQuerySystemInformation@16 +ZwQuerySystemTime=ZwQuerySystemTime@4 +ZwQueryValueKey=ZwQueryValueKey@24 +ZwQueryVolumeInformationFile=ZwQueryVolumeInformationFile@20 +ZwReadFile=ZwReadFile@36 +ZwReplaceKey=ZwReplaceKey@12 +ZwRequestWaitReplyPort=ZwRequestWaitReplyPort@12 +ZwResetEvent=ZwResetEvent@8 +ZwSaveKey=ZwSaveKey@8 +ZwSetDefaultLocale=ZwSetDefaultLocale@8 +ZwSetEvent=ZwSetEvent@8 +ZwSetInformationFile=ZwSetInformationFile@20 +ZwSetInformationObject=ZwSetInformationObject@16 +ZwSetInformationProcess=ZwSetInformationProcess@16 +ZwSetInformationThread=ZwSetInformationThread@16 +ZwSetSystemInformation=ZwSetSystemInformation@12 +ZwSetSystemTime=ZwSetSystemTime@8 +ZwSetValueKey=ZwSetValueKey@24 +ZwTerminateProcess=ZwTerminateProcess@8 +ZwUnloadDriver=ZwUnloadDriver@4 +ZwUnloadKey=ZwUnloadKey@4 +ZwUnmapViewOfSection=ZwUnmapViewOfSection@8 +ZwWaitForMultipleObjects=ZwWaitForMultipleObjects@20 +ZwWaitForSingleObject=ZwWaitForSingleObject@12 +ZwWriteFile=ZwWriteFile@36 +ZwYieldExecution=ZwYieldExecution@0 +_abnormal_termination +;_alldiv +;_allmul +;_allrem +;_allshl +;_allshr +;_aulldiv +;_aullrem +;_aullshr +_except_handler2 +_except_handler3 +_global_unwind2 +_itoa +_local_unwind2 +_purecall +_snprintf +_snwprintf +_stricmp +_strlwr +_strnicmp +_strnset +_strrev +_strset +_strupr +_vsnprintf +_wcsicmp +_wcslwr +_wcsnicmp +_wcsnset +_wcsrev +_wcsupr +atoi +atol +isdigit +islower +isprint +isspace +isupper +isxdigit +mbstowcs +mbtowc +memchr +memcpy +memmove +memset +qsort +rand +sprintf +srand +strcat +strchr +strcmp +strcpy +strlen +strncat +strncmp +strncpy +strrchr +strspn +strstr +swprintf +tolower +toupper +towlower +towupper +vsprintf +wcscat +wcschr +wcscmp +wcscpy +wcscspn +wcslen +wcsncat +wcsncmp +wcsncpy +wcsrchr +wcsspn +wcsstr +wcstombs +wctomb diff --git a/ntoskrnl/ntoskrnl.full.def b/ntoskrnl/ntoskrnl.full.def new file mode 100644 index 0000000..a1fddc0 --- /dev/null +++ b/ntoskrnl/ntoskrnl.full.def @@ -0,0 +1,1070 @@ +EXPORTS +ExAcquireFastMutexUnsafe +ExInterlockedAddLargeStatistic +ExInterlockedCompareExchange64 +ExInterlockedPopEntrySList +ExInterlockedPushEntrySList +ExReleaseFastMutexUnsafe +ExReleaseResourceLite +ExfInterlockedAddUlong +ExfInterlockedInsertHeadList +ExfInterlockedInsertTailList +ExfInterlockedPopEntryList +ExfInterlockedPushEntryList +ExfInterlockedRemoveHeadList +Exfi386InterlockedDecrementLong +Exfi386InterlockedExchangeUlong +Exfi386InterlockedIncrementLong +InterlockedCompareExchange +InterlockedDecrement +InterlockedExchange +InterlockedExchangeAdd +InterlockedIncrement +IofCallDriver +IofCompleteRequest +KeSetSwapContextNotifyRoutine +KeSetThreadSelectNotifyRoutine +KeSetTimeUpdateNotifyRoutine +KefAcquireSpinLockAtDpcLevel +KefReleaseSpinLockFromDpcLevel +KiAcquireSpinLock +KiReleaseSpinLock +ObfDereferenceObject +ObfReferenceObject +Kei386EoiHelper +Kii386SpinOnSpinLock +CcCanIWrite +CcCopyRead +CcCopyWrite +CcDeferWrite +CcFastCopyRead +CcFastCopyWrite +CcFastMdlReadWait +CcFastReadNotPossible +CcFastReadWait +CcFlushCache +CcGetDirtyPages +CcGetFileObjectFromBcb +CcGetFileObjectFromSectionPtrs +CcGetLsnForFileObject +CcInitializeCacheMap +CcIsThereDirtyData +CcMapData +CcMdlRead +CcMdlReadComplete +CcMdlWriteComplete +CcPinMappedData +CcPinRead +CcPrepareMdlWrite +CcPreparePinWrite +CcPurgeCacheSection +CcRepinBcb +CcScheduleReadAhead +CcSetAdditionalCacheAttributes +CcSetBcbOwnerPointer +CcSetDirtyPageThreshold +CcSetDirtyPinnedData +CcSetFileSizes +CcSetLogHandleForFile +CcSetReadAheadGranularity +CcUninitializeCacheMap +CcUnpinData +CcUnpinDataForThread +CcUnpinRepinnedBcb +CcZeroData +DbgBreakPoint +DbgBreakPointWithStatus +DbgLoadImageSymbols +DbgPrint +DbgPrompt +ExAcquireResourceExclusive +ExAcquireResourceExclusiveLite +ExAcquireResourceSharedLite +ExAcquireSharedStarveExclusive +ExAcquireSharedWaitForExclusive +ExAllocateFromPagedLookasideList +ExAllocatePool +ExAllocatePoolWithQuota +ExAllocatePoolWithQuotaTag +ExAllocatePoolWithTag +ExConvertExclusiveToSharedLite +ExCreateCallback +ExDeleteNPagedLookasideList +ExDeletePagedLookasideList +ExDeleteResource +ExDeleteResourceLite +ExDesktopObjectType +ExDisableResourceBoostLite +ExEnumHandleTable +ExEventObjectType +ExExtendZone +ExFreePool +ExFreeToPagedLookasideList +ExGetExclusiveWaiterCount +ExGetPreviousMode +ExGetSharedWaiterCount +ExInitializeNPagedLookasideList +ExInitializePagedLookasideList +ExInitializeResource +ExInitializeResourceLite +ExInitializeZone +ExInterlockedAddLargeInteger +ExInterlockedAddUlong +ExInterlockedDecrementLong +ExInterlockedExchangeUlong +ExInterlockedExtendZone +ExInterlockedIncrementLong +ExInterlockedInsertHeadList +ExInterlockedInsertTailList +ExInterlockedPopEntryList +ExInterlockedPushEntryList +ExInterlockedRemoveHeadList +ExIsProcessorFeaturePresent +ExIsResourceAcquiredExclusiveLite +ExIsResourceAcquiredSharedLite +ExLocalTimeToSystemTime +ExNotifyCallback +ExPostSystemEvent +ExQueryPoolBlockSize +ExQueueWorkItem +ExRaiseAccessViolation +ExRaiseDatatypeMisalignment +ExRaiseException +ExRaiseHardError +ExRaiseStatus +ExRegisterCallback +ExReinitializeResourceLite +ExReleaseResourceForThread +ExReleaseResourceForThreadLite +ExSetResourceOwnerPointer +ExSystemExceptionFilter +ExSystemTimeToLocalTime +ExUnregisterCallback +ExWindowStationObjectType +Exi386InterlockedDecrementLong +Exi386InterlockedExchangeUlong +Exi386InterlockedIncrementLong +FsRtlAddLargeMcbEntry +FsRtlAddMcbEntry +FsRtlAddToTunnelCache +FsRtlAllocatePool +FsRtlAllocatePoolWithQuota +FsRtlAllocatePoolWithQuotaTag +FsRtlAllocatePoolWithTag +FsRtlAllocateResource +FsRtlAreNamesEqual +FsRtlBalanceReads +FsRtlCheckLockForReadAccess +FsRtlCheckLockForWriteAccess +FsRtlCheckOplock +FsRtlCopyRead +FsRtlCopyWrite +FsRtlCurrentBatchOplock +FsRtlDeleteKeyFromTunnelCache +FsRtlDeleteTunnelCache +FsRtlDeregisterUncProvider +FsRtlDissectDbcs +FsRtlDissectName +FsRtlDoesDbcsContainWildCards +FsRtlDoesNameContainWildCards +FsRtlFastCheckLockForRead +FsRtlFastCheckLockForWrite +FsRtlFastUnlockAll +FsRtlFastUnlockAllByKey +FsRtlFastUnlockSingle +FsRtlFindInTunnelCache +FsRtlGetFileSize +FsRtlGetNextFileLock +FsRtlGetNextLargeMcbEntry +FsRtlGetNextMcbEntry +FsRtlInitializeFileLock +FsRtlInitializeLargeMcb +FsRtlInitializeMcb +FsRtlInitializeOplock +FsRtlInitializeTunnelCache +FsRtlIsDbcsInExpression +FsRtlIsFatDbcsLegal +FsRtlIsHpfsDbcsLegal +FsRtlIsNameInExpression +FsRtlIsNtstatusExpected +FsRtlIsTotalDeviceFailure +FsRtlLegalAnsiCharacterArray +FsRtlLookupLargeMcbEntry +FsRtlLookupLastLargeMcbEntry +FsRtlLookupLastMcbEntry +FsRtlLookupMcbEntry +FsRtlMdlRead +FsRtlMdlReadComplete +FsRtlMdlReadCompleteDev +FsRtlMdlReadDev +FsRtlMdlWriteComplete +FsRtlMdlWriteCompleteDev +FsRtlNormalizeNtstatus +FsRtlNotifyChangeDirectory +FsRtlNotifyCleanup +FsRtlNotifyFullChangeDirectory +FsRtlNotifyFullReportChange +FsRtlNotifyInitializeSync +FsRtlNotifyReportChange +FsRtlNotifyUninitializeSync +FsRtlNumberOfRunsInLargeMcb +FsRtlNumberOfRunsInMcb +FsRtlOplockFsctrl +FsRtlOplockIsFastIoPossible +FsRtlPostPagingFileStackOverflow +FsRtlPostStackOverflow +FsRtlPrepareMdlWrite +FsRtlPrepareMdlWriteDev +FsRtlPrivateLock +FsRtlProcessFileLock +FsRtlRegisterUncProvider +FsRtlRemoveLargeMcbEntry +FsRtlRemoveMcbEntry +FsRtlSplitLargeMcb +FsRtlSyncVolumes +FsRtlTruncateLargeMcb +FsRtlTruncateMcb +FsRtlUninitializeFileLock +FsRtlUninitializeLargeMcb +FsRtlUninitializeMcb +FsRtlUninitializeOplock +HalDispatchTable +HalPrivateDispatchTable +IoAcquireCancelSpinLock +IoAcquireVpbSpinLock +IoAdapterObjectType +IoAllocateAdapterChannel +IoAllocateController +IoAllocateErrorLogEntry +IoAllocateIrp +IoAllocateMdl +IoAssignResources +IoAttachDevice +IoAttachDeviceByPointer +IoAttachDeviceToDeviceStack +IoBuildAsynchronousFsdRequest +IoBuildDeviceIoControlRequest +IoBuildPartialMdl +IoBuildSynchronousFsdRequest +IoCallDriver +IoCancelIrp +IoCheckDesiredAccess +IoCheckEaBufferValidity +IoCheckFunctionAccess +IoCheckShareAccess +IoCompleteRequest +IoConnectInterrupt +IoCreateController +IoCreateDevice +IoCreateFile +IoCreateNotificationEvent +IoCreateStreamFileObject +IoCreateSymbolicLink +IoCreateSynchronizationEvent +IoCreateUnprotectedSymbolicLink +IoDeleteController +IoDeleteDevice +IoDeleteSymbolicLink +IoDetachDevice +IoDeviceHandlerObjectSize +IoDeviceHandlerObjectType +IoDeviceObjectType +IoDisconnectInterrupt +IoDriverObjectType +IoEnqueueIrp +IoFastQueryNetworkAttributes +IoFileObjectType +IoFreeController +IoFreeIrp +IoFreeMdl +IoGetAttachedDevice +IoGetBaseFileSystemDeviceObject +IoGetConfigurationInformation +IoGetCurrentProcess +IoGetDeviceObjectPointer +IoGetDeviceToVerify +IoGetFileObjectGenericMapping +IoGetInitialStack +IoGetRelatedDeviceObject +IoGetRequestorProcess +IoGetStackLimits +IoGetTopLevelIrp +IoInitializeIrp +IoInitializeTimer +IoIsOperationSynchronous +IoIsSystemThread +IoMakeAssociatedIrp +IoOpenDeviceInstanceKey +IoPageRead +IoQueryDeviceDescription +IoQueryDeviceEnumInfo +IoQueryFileInformation +IoQueryVolumeInformation +IoQueueThreadIrp +IoRaiseHardError +IoRaiseInformationalHardError +IoReadOperationCount +IoReadTransferCount +IoRegisterDriverReinitialization +IoRegisterFileSystem +IoRegisterFsRegistrationChange +IoRegisterShutdownNotification +IoReleaseCancelSpinLock +IoReleaseVpbSpinLock +IoRemoveShareAccess +IoReportHalResourceUsage +IoReportResourceUsage +IoSetDeviceToVerify +IoSetHardErrorOrVerifyDevice +IoSetInformation +IoSetShareAccess +IoSetThreadHardErrorMode +IoSetTopLevelIrp +IoStartNextPacket +IoStartNextPacketByKey +IoStartPacket +IoStartTimer +IoStatisticsLock +IoStopTimer +IoSynchronousPageWrite +IoThreadToProcess +IoUnregisterFileSystem +IoUnregisterFsRegistrationChange +IoUnregisterShutdownNotification +IoUpdateShareAccess +IoVerifyVolume +IoWriteErrorLogEntry +IoWriteOperationCount +IoWriteTransferCount +KdDebuggerEnabled +KdDebuggerNotPresent +KdPollBreakIn +Ke386CallBios +Ke386IoSetAccessProcess +Ke386QueryIoAccessMap +Ke386SetIoAccessMap +KeAcquireSpinLockAtDpcLevel +KeAddSystemServiceTable +KeAttachProcess +KeBoostCurrentThread +KeBugCheck +KeBugCheckEx +KeCancelTimer +KeClearEvent +KeConnectInterrupt +KeDcacheFlushCount +KeDelayExecutionThread +KeDeregisterBugCheckCallback +KeDetachProcess +KeDisconnectInterrupt +KeEnterCriticalRegion +KeEnterKernelDebugger +KeFindConfigurationEntry +KeFindConfigurationNextEntry +KeFlushEntireTb +KeGetCurrentThread +KeGetPreviousMode +KeI386AbiosCall +KeI386AllocateGdtSelectors +KeI386Call16BitCStyleFunction +KeI386Call16BitFunction +KeI386FlatToGdtSelector +KeI386GetLid +KeI386MachineType +KeI386ReleaseGdtSelectors +KeI386ReleaseLid +KeI386SetGdtSelector +KeIcacheFlushCount +KeInitializeApc +KeInitializeDeviceQueue +KeInitializeDpc +KeInitializeEvent +KeInitializeInterrupt +KeInitializeMutant +KeInitializeMutex +KeInitializeQueue +KeInitializeSemaphore +KeInitializeSpinLock +KeInitializeTimer +KeInitializeTimerEx +KeInsertByKeyDeviceQueue +KeInsertDeviceQueue +KeInsertHeadQueue +KeInsertQueue +KeInsertQueueApc +KeInsertQueueDpc +KeIsExecutingDpc +KeLeaveCriticalRegion +KeLoaderBlock +KeNumberProcessors +KeProfileInterrupt +KeProfileInterruptWithSource +KePulseEvent +KeQuerySystemTime +KeQueryTickCount +KeQueryTimeIncrement +KeRaiseUserException +KeReadStateEvent +KeReadStateMutant +KeReadStateMutex +KeReadStateQueue +KeReadStateSemaphore +KeReadStateTimer +KeRegisterBugCheckCallback +KeReleaseMutant +KeReleaseMutex +KeReleaseSemaphore +KeReleaseSpinLockFromDpcLevel +KeRemoveByKeyDeviceQueue +KeRemoveDeviceQueue +KeRemoveEntryDeviceQueue +KeRemoveQueue +KeRemoveQueueDpc +KeResetEvent +KeRestoreFloatingPointState +KeRundownQueue +KeSaveFloatingPointState +KeServiceDescriptorTable +KeSetAffinityThread +KeSetBasePriorityThread +KeSetDmaIoCoherency +KeSetEvent +KeSetEventBoostPriority +KeSetIdealProcessorThread +KeSetImportanceDpc +KeSetKernelStackSwapEnable +KeSetPriorityThread +KeSetProfileIrql +KeSetTargetProcessorDpc +KeSetTimeIncrement +KeSetTimer +KeSetTimerEx +KeSynchronizeExecution +KeTerminateThread +KeTickCount +KeUpdateRunTime +KeUpdateSystemTime +KeUserModeCallback +KeWaitForMultipleObjects +KeWaitForMutexObject +KeWaitForSingleObject +KiBugCheckData +KiCoprocessorError +KiDeliverApc +KiDispatchInterrupt +KiIpiServiceRoutine +KiUnexpectedInterrupt +LdrAccessResource +LdrEnumResources +LdrFindResourceDirectory_U +LdrFindResource_U +LpcRequestPort +LsaCallAuthenticationPackage +LsaDeregisterLogonProcess +LsaFreeReturnBuffer +LsaLogonUser +LsaLookupAuthenticationPackage +LsaRegisterLogonProcess +MmAdjustWorkingSetSize +MmAllocateContiguousMemory +MmAllocateNonCachedMemory +MmBuildMdlForNonPagedPool +MmCanFileBeTruncated +MmCreateMdl +MmCreateSection +MmDbgTranslatePhysicalAddress +MmDisableModifiedWriteOfSection +MmFlushImageSection +MmForceSectionClosed +MmFreeContiguousMemory +MmFreeNonCachedMemory +MmGetPhysicalAddress +MmGrowKernelStack +MmIsAddressValid +MmIsNonPagedSystemAddressValid +MmIsRecursiveIoFault +MmIsThisAnNtAsSystem +MmLockPagableDataSection +MmLockPagableImageSection +MmLockPagableSectionByHandle +MmMapIoSpace +MmMapLockedPages +MmMapMemoryDumpMdl +MmMapVideoDisplay +MmMapViewInSystemSpace +MmMapViewOfSection +MmPageEntireDriver +MmProbeAndLockPages +MmQuerySystemSize +MmResetDriverPaging +MmSectionObjectType +MmSecureVirtualMemory +MmSetAddressRangeModified +MmSetBankedSection +MmSizeOfMdl +MmUnlockPagableImageSection +MmUnlockPages +MmUnmapIoSpace +MmUnmapLockedPages +MmUnmapVideoDisplay +MmUnmapViewInSystemSpace +MmUnmapViewOfSection +MmUnsecureVirtualMemory +NlsAnsiCodePage +NlsLeadByteInfo +NlsMbCodePageTag +NlsMbOemCodePageTag +NlsOemLeadByteInfo +NtAddAtom +NtAdjustPrivilegesToken +NtAllocateLocallyUniqueId +NtAllocateUuids +NtAllocateVirtualMemory +NtBuildNumber +NtClose +NtConnectPort +NtCreateEvent +NtCreateFile +NtCreateSection +NtDeleteAtom +NtDeleteFile +NtDeviceIoControlFile +NtDuplicateObject +NtDuplicateToken +NtFindAtom +NtFreeVirtualMemory +NtFsControlFile +NtGlobalFlag +NtLockFile +NtMapViewOfSection +NtNotifyChangeDirectoryFile +NtOpenFile +NtOpenProcess +NtOpenProcessToken +NtQueryDirectoryFile +NtQueryEaFile +NtQueryInformationAtom +NtQueryInformationFile +NtQueryInformationProcess +NtQueryInformationToken +NtQueryOleDirectoryFile +NtQuerySecurityObject +NtQueryVolumeInformationFile +NtReadFile +NtRequestPort +NtRequestWaitReplyPort +NtSetEvent +NtSetInformationFile +NtSetInformationProcess +NtSetInformationThread +NtSetSecurityObject +NtUnlockFile +NtVdmControl +NtWaitForSingleObject +NtWriteFile +ObAssignSecurity +ObCheckCreateObjectAccess +ObCheckObjectAccess +ObCreateObject +ObDereferenceObject +ObFindHandleForObject +ObGetObjectPointerCount +ObGetObjectSecurity +ObInsertObject +ObMakeTemporaryObject +ObOpenObjectByName +ObOpenObjectByPointer +ObQueryNameString +ObQueryObjectAuditingByHandle +ObReferenceObjectByHandle +ObReferenceObjectByName +ObReferenceObjectByPointer +ObReleaseObjectSecurity +ObSetSecurityDescriptorInfo +PfxFindPrefix +PfxInitialize +PfxInsertPrefix +PfxRemovePrefix +PoQueryPowerSequence +PoRequestPowerChange +PoSetDeviceIdleDetection +ProbeForWrite +PsAssignImpersonationToken +PsChargePoolQuota +PsCreateSystemProcess +PsCreateSystemThread +PsCreateWin32Process +PsEstablishWin32Callouts +PsGetCurrentProcessId +PsGetCurrentThreadId +PsGetProcessExitTime +PsGetVersion +PsImpersonateClient +PsInitialSystemProcess +PsIsThreadTerminating +PsLookupProcessByProcessId +PsLookupProcessThreadByCid +PsLookupThreadByThreadId +PsProcessType +PsReferenceImpersonationToken +PsReferencePrimaryToken +PsReturnPoolQuota +PsRevertToSelf +PsSetCreateProcessNotifyRoutine +PsSetCreateThreadNotifyRoutine +PsSetLegoNotifyRoutine +PsSetProcessPriorityByClass +PsTerminateSystemThread +PsThreadType +READ_REGISTER_BUFFER_UCHAR +READ_REGISTER_BUFFER_ULONG +READ_REGISTER_BUFFER_USHORT +READ_REGISTER_UCHAR +READ_REGISTER_ULONG +READ_REGISTER_USHORT +RtlAbsoluteToSelfRelativeSD +RtlAddAccessAllowedAce +RtlAddAce +RtlAddAtomToAtomTable +RtlAllocateAndInitializeSid +RtlAllocateHeap +RtlAnsiCharToUnicodeChar +RtlAnsiStringToUnicodeSize +RtlAnsiStringToUnicodeString +RtlAppendAsciizToString +RtlAppendStringToString +RtlAppendUnicodeStringToString +RtlAppendUnicodeToString +RtlAreAllAccessesGranted +RtlAreAnyAccessesGranted +RtlAreBitsClear +RtlAreBitsSet +RtlAssert +RtlCaptureStackBackTrace +RtlCharToInteger +RtlCheckRegistryKey +RtlClearAllBits +RtlClearBits +RtlCompareMemory +RtlCompareMemoryUlong +RtlCompareString +RtlCompareUnicodeString +RtlCompressBuffer +RtlCompressChunks +RtlConvertLongToLargeInteger +RtlConvertSidToUnicodeString +RtlConvertUlongToLargeInteger +RtlCopyLuid +RtlCopySid +RtlCopyString +RtlCopyUnicodeString +RtlCreateAcl +RtlCreateAtomTable +RtlCreateHeap +RtlCreateRegistryKey +RtlCreateSecurityDescriptor +RtlCreateUnicodeString +RtlCustomCPToUnicodeN +RtlDecompressBuffer +RtlDecompressChunks +RtlDecompressFragment +RtlDelete +RtlDeleteAtomFromAtomTable +RtlDeleteElementGenericTable +RtlDeleteNoSplay +RtlDeleteRegistryValue +RtlDescribeChunk +RtlDestroyAtomTable +RtlDestroyHeap +RtlDowncaseUnicodeString +RtlEmptyAtomTable +RtlEnlargedIntegerMultiply +RtlEnlargedUnsignedDivide +RtlEnlargedUnsignedMultiply +RtlEnumerateGenericTable +RtlEnumerateGenericTableWithoutSplaying +RtlEqualLuid +RtlEqualSid +RtlEqualString +RtlEqualUnicodeString +RtlExtendedIntegerMultiply +RtlExtendedLargeIntegerDivide +RtlExtendedMagicDivide +RtlFillMemory +RtlFillMemoryUlong +RtlFindClearBits +RtlFindClearBitsAndSet +RtlFindFirstRunClear +RtlFindFirstRunSet +RtlFindLongestRunClear +RtlFindLongestRunSet +RtlFindMessage +RtlFindSetBits +RtlFindSetBitsAndClear +RtlFindUnicodePrefix +RtlFormatCurrentUserKeyPath +RtlFreeAnsiString +RtlFreeHeap +RtlFreeOemString +RtlFreeUnicodeString +RtlGenerate8dot3Name +RtlGetCallersAddress +RtlGetCompressionWorkSpaceSize +RtlGetDaclSecurityDescriptor +RtlGetDefaultCodePage +RtlGetElementGenericTable +RtlGetGroupSecurityDescriptor +RtlGetOwnerSecurityDescriptor +RtlImageNtHeader +RtlInitAnsiString +RtlInitCodePageTable +RtlInitString +RtlInitUnicodeString +RtlInitializeBitMap +RtlInitializeGenericTable +RtlInitializeSid +RtlInitializeUnicodePrefix +RtlInsertElementGenericTable +RtlInsertUnicodePrefix +RtlIntegerToChar +RtlIntegerToUnicodeString +RtlIsNameLegalDOS8Dot3 +RtlLargeIntegerAdd +RtlLargeIntegerArithmeticShift +RtlLargeIntegerDivide +RtlLargeIntegerNegate +RtlLargeIntegerShiftLeft +RtlLargeIntegerShiftRight +RtlLargeIntegerSubtract +RtlLengthRequiredSid +RtlLengthSecurityDescriptor +RtlLengthSid +RtlLookupAtomInAtomTable +RtlLookupElementGenericTable +RtlMapGenericMask +RtlMoveMemory +RtlMultiByteToUnicodeN +RtlMultiByteToUnicodeSize +RtlNextUnicodePrefix +RtlNtStatusToDosError +RtlNtStatusToDosErrorNoTeb +RtlNumberGenericTableElements +RtlNumberOfClearBits +RtlNumberOfSetBits +RtlOemStringToCountedUnicodeString +RtlOemStringToUnicodeSize +RtlOemStringToUnicodeString +RtlOemToUnicodeN +RtlPinAtomInAtomTable +RtlPrefixString +RtlPrefixUnicodeString +RtlQueryAtomInAtomTable +RtlQueryRegistryValues +RtlQueryTimeZoneInformation +RtlRaiseException +RtlRandom +RtlRemoveUnicodePrefix +RtlReserveChunk +RtlSecondsSince1970ToTime +RtlSecondsSince1980ToTime +RtlSetAllBits +RtlSetBits +RtlSetDaclSecurityDescriptor +RtlSetGroupSecurityDescriptor +RtlSetOwnerSecurityDescriptor +RtlSetSaclSecurityDescriptor +RtlSetTimeZoneInformation +RtlSplay +RtlSubAuthorityCountSid +RtlSubAuthoritySid +RtlTimeFieldsToTime +RtlTimeToSecondsSince1970 +RtlTimeToSecondsSince1980 +RtlTimeToTimeFields +RtlUnicodeStringToAnsiSize +RtlUnicodeStringToAnsiString +RtlUnicodeStringToCountedOemString +RtlUnicodeStringToInteger +RtlUnicodeStringToOemSize +RtlUnicodeStringToOemString +RtlUnicodeToCustomCPN +RtlUnicodeToMultiByteN +RtlUnicodeToMultiByteSize +RtlUnicodeToOemN +RtlUnwind +RtlUpcaseUnicodeChar +RtlUpcaseUnicodeString +RtlUpcaseUnicodeStringToAnsiString +RtlUpcaseUnicodeStringToCountedOemString +RtlUpcaseUnicodeStringToOemString +RtlUpcaseUnicodeToCustomCPN +RtlUpcaseUnicodeToMultiByteN +RtlUpcaseUnicodeToOemN +RtlUpperChar +RtlUpperString +RtlValidSecurityDescriptor +RtlValidSid +RtlWriteRegistryValue +RtlZeroHeap +RtlZeroMemory +RtlxAnsiStringToUnicodeSize +RtlxOemStringToUnicodeSize +RtlxUnicodeStringToAnsiSize +RtlxUnicodeStringToOemSize +SeAccessCheck +SeAppendPrivileges +SeAssignSecurity +SeAuditingFileEvents +SeAuditingFileOrGlobalEvents +SeCaptureSecurityDescriptor +SeCaptureSubjectContext +SeCloseObjectAuditAlarm +SeCreateAccessState +SeCreateClientSecurity +SeDeassignSecurity +SeDeleteAccessState +SeDeleteObjectAuditAlarm +SeExports +SeFreePrivileges +SeImpersonateClient +SeLockSubjectContext +sionForTerminationNotification +SeOpenObjectAuditAlarm +SeOpenObjectForDeleteAuditAlarm +SePrivilegeCheck +SePrivilegeObjectAuditAlarm +SePublicDefaultDacl +SeQueryAuthenticationIdToken +SeQuerySecurityDescriptorInfo +SeRegisterLogonSessionTerminatedRoutine +SeReleaseSecurityDescriptor +SeReleaseSubjectContext +SeSetAccessStateGenericMapping +SeSetSecurityDescriptorInfo +SeSinglePrivilegeCheck +SeSystemDefaultDacl +SeTokenImpersonationLevel +SeTokenType +SeUnlockSubjectContext +SeUnregisterLogonSessionTerminatedRoutine +SeValidSecurityDescriptor +WRITE_REGISTER_BUFFER_UCHAR +WRITE_REGISTER_BUFFER_ULONG +WRITE_REGISTER_BUFFER_USHORT +WRITE_REGISTER_UCHAR +WRITE_REGISTER_ULONG +WRITE_REGISTER_USHORT +ZwAccessCheckAndAuditAlarm +ZwAlertThread +ZwAllocateVirtualMemory +ZwClearEvent +ZwClose +ZwCloseObjectAuditAlarm +ZwConnectPort +ZwCreateDirectoryObject +ZwCreateEvent +ZwCreateFile +ZwCreateKey +ZwCreateSection +ZwCreateSymbolicLinkObject +ZwDeleteFile +ZwDeleteKey +ZwDeleteValueKey +ZwDeviceIoControlFile +ZwDisplayString +ZwDuplicateObject +ZwDuplicateToken +ZwEnumerateKey +ZwEnumerateValueKey +ZwFlushInstructionCache +ZwFlushKey +ZwFreeVirtualMemory +ZwFsControlFile +ZwLoadDriver +ZwLoadKey +ZwMakeTemporaryObject +ZwMapViewOfSection +ZwNotifyChangeKey +ZwOpenDirectoryObject +ZwOpenEvent +ZwOpenFile +ZwOpenKey +ZwOpenProcess +ZwOpenProcessToken +ZwOpenSection +ZwOpenSymbolicLinkObject +ZwOpenThread +ZwOpenThreadToken +ZwPulseEvent +ZwQueryDefaultLocale +ZwQueryDirectoryFile +ZwQueryInformationFile +ZwQueryInformationProcess +ZwQueryInformationToken +ZwQueryKey +ZwQueryObject +ZwQuerySection +ZwQuerySecurityObject +ZwQuerySymbolicLinkObject +ZwQuerySystemInformation +ZwQueryValueKey +ZwQueryVolumeInformationFile +ZwReadFile +ZwReplaceKey +ZwRequestWaitReplyPort +ZwResetEvent +ZwSaveKey +ZwSetDefaultLocale +ZwSetEvent +ZwSetInformationFile +ZwSetInformationObject +ZwSetInformationProcess +ZwSetInformationThread +ZwSetSystemInformation +ZwSetSystemTime +ZwSetValueKey +ZwTerminateProcess +ZwUnloadDriver +ZwUnloadKey +ZwUnmapViewOfSection +ZwWaitForMultipleObjects +ZwWaitForSingleObject +ZwWriteFile +ZwYieldExecution +_abnormal_termination +_alldiv +_allmul +_allrem +_allshl +_allshr +_aulldiv +_aullrem +_aullshr +_except_handler2 +_global_unwind2 +_itoa +_local_unwind2 +_purecall +_snprintf +_snwprintf +_stricmp +_strlwr +_strnicmp +_strnset +_strrev +_strset +_strupr +_vsnprintf +_wcsicmp +_wcslwr +_wcsnicmp +_wcsnset +_wcsrev +_wcsupr +atoi +atol +isdigit +islower +isprint +isspace +isupper +isxdigit +mbstowcs +mbtowc +memchr +memcpy +memmove +memset +qsort +rand +sprintf +srand +strcat +strchr +strcmp +strcpy +strlen +strncat +strncmp +strncpy +strrchr +strspn +strstr +swprintf +tolower +toupper +towlower +towupper +vsprintf +wcscat +wcschr +wcscmp +wcscpy +wcscspn +wcslen +wcsncat +wcsncmp +wcsncpy +wcsrchr +wcsspn +wcsstr +wcstombs +wctomb +KdPortSave +KeRaiseIrqlToDpcLevel +ExReleaseFastMutex +ExAcquireFastMutex +ExTryToAcquireFastMutex +HalRequestSoftwareInterrupt +HalReturnToFirmware +HalDisplayString +HalQueryRealTimeClock +HalSetRealTimeClock +HalSetTimeIncrement +KeGetCurrentIrql +KeQueryPerformanceCounter +HalGetEnvironmentVariable +HalSetEnvironmentVariable +KfRaiseIrql +HalInitSystem +HalReportResourceUsage +HalAllProcessorsStarted +HalAllocateAdapterChannel +HalGetInterruptVector +HalTranslateBusAddress +HalAdjustResourceList +IoAssignDriveLetters +IoReadPartitionTable +HalAllocateCommonBuffer +KdPortInitialize +KdPortGetByte +KdPortPutByte +KdPortPollByte +KfLowerIrql +KdPortRestore +READ_PORT_ULONG +READ_PORT_USHORT +READ_PORT_UCHAR +WRITE_PORT_ULONG +WRITE_PORT_USHORT +WRITE_PORT_UCHAR +HalInitializeProcessor +HalProcessorIdle +HalClearSoftwareInterrupt +KeRaiseIrqlToSynchLevel +HalHandleNMI +HalBeginSystemInterrupt +HalEndSystemInterrupt +HalEnableSystemInterrupt +HalDisableSystemInterrupt +HalSystemVectorDispatchEntry +KeRaiseIrql +KeLowerIrql +HalSetProfileInterval +HalStartProfileInterrupt +HalStopProfileInterrupt +HalQueryDisplayParameters +KfReleaseSpinLock +KfAcquireSpinLock +KeFlushWriteBuffer +KeStallExecutionProcessor diff --git a/ntoskrnl/ntoskrnl.lnk b/ntoskrnl/ntoskrnl.lnk new file mode 100644 index 0000000..14299b3 --- /dev/null +++ b/ntoskrnl/ntoskrnl.lnk @@ -0,0 +1,99 @@ +OUTPUT_FORMAT(pei-i386) +ENTRY(_mainCRTStartup) +SECTIONS +{ + .text __image_base__ + __section_alignment__ : + { + __text_start__ = .; + *(.init) + *(.text) + *(SORT(.text$*)) + *(.glue_7t) + *(.glue_7) + ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; + LONG (-1); *(.ctors); *(.ctor); LONG (0); + ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; + LONG (-1); *(.dtors); *(.dtor); LONG (0); + *(.fini) + /* ??? Why is .gcc_exc here? */ + *(.gcc_exc) + __text_end__ = .; + *(.gcc_except_table) + } + /* The Cygwin32 library uses a section to avoid copying certain data + on fork. This used to be named ".data". The linker used + to include this between __data_start__ and __data_end__, but that + breaks building the cygwin32 dll. Instead, we name the section + ".data_cygwin_nocopy" and explictly include it after __data_end__. */ + .data BLOCK(__section_alignment__) : + { + __data_start__ = . ; + *(.data) + *(.data2) + *(SORT(.data$*)) + __data_end__ = . ; + *(.data_cygwin_nocopy) + } + .rdata BLOCK(__section_alignment__) : + { + *(.rdata) + *(SORT(.rdata$*)) + *(.eh_frame) + } + .edata BLOCK(__section_alignment__) : + { + *(.edata) + } + /DISCARD/ : + { + *(.debug$S) + *(.debug$T) + *(.debug$F) + *(.drectve) + } + + .idata BLOCK(__section_alignment__) : + { + /* This cannot currently be handled with grouped sections. + See pe.em:sort_sections. */ + SORT(*)(.idata$2) + SORT(*)(.idata$3) + /* These zeroes mark the end of the import list. */ + LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); + SORT(*)(.idata$4) + SORT(*)(.idata$5) + SORT(*)(.idata$6) + SORT(*)(.idata$7) + } + .CRT BLOCK(__section_alignment__) : + { + *(SORT(.CRT$*)) + } + .rsrc BLOCK(__section_alignment__) : + { + *(.rsrc) + *(SORT(.rsrc$*)) + } + .bss BLOCK(__section_alignment__) : + { + __bss_start__ = . ; + *(.bss) + *(COMMON) + __bss_end__ = . ; + } + .reloc BLOCK(__section_alignment__) : + { + *(.reloc) + /* These zeroes mark the end of the reloc section. */ + LONG (0); LONG (0); LONG (0); LONG (0); LONG (0); + } + .stab BLOCK(__section_alignment__) (NOLOAD) : + { + [ .stab ] + } + .stabstr BLOCK(__section_alignment__) (NOLOAD) : + { + [ .stabstr ] + } +} + diff --git a/ntoskrnl/ntoskrnl.mc b/ntoskrnl/ntoskrnl.mc new file mode 100644 index 0000000..4cf04a1 --- /dev/null +++ b/ntoskrnl/ntoskrnl.mc @@ -0,0 +1,1029 @@ +; +; ntoskrnl.exe bug codes +; + +MessageIdTypedef=ULONG + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + +FacilityNames=(System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + ) + +LanguageNames=(English=0x409:MSG00409) + +; +; message definitions +; + +MessageId=0x0 +Severity=Success +Facility=System +SymbolicName=UNDEFINED_BUG_CODE +Language=English +The bug code is undefined. Please use an existing code instead. +. + +MessageId=0x01 +Severity=Success +Facility=System +SymbolicName=APC_INDEX_MISMATCH +Language=English +APC_INDEX_MISMATCH +. + +MessageId=0x02 +Severity=Success +Facility=System +SymbolicName=DEVICE_QUEUE_NOT_BUSY +Language=English +DEVICE_QUEUE_NOT_BUSY +. + +MessageId=0x3 +Severity=Success +Facility=System +SymbolicName=INVALID_AFFINITY_SET +Language=English +INVALID_AFFINITY_SET +. + +MessageId=0x04 +Severity=Success +Facility=System +SymbolicName=INVALID_DATA_ACCESS_TRAP +Language=English +INVALID_DATA_ACCESS_TRAP +. + +MessageId=0x05 +Severity=Success +Facility=System +SymbolicName=INVALID_PROCESS_ATTACH_ATTEMPT +Language=English +INVALID_PROCESS_ATTACH_ATTEMPT +. + +MessageId=0x06 +Severity=Success +Facility=System +SymbolicName=INVALID_PROCESS_DETACH_ATTEMPT +Language=English +INVALID_PROCESS_DETACH_ATTEMPT +. + +MessageId=0x7 +Severity=Success +Facility=System +SymbolicName=INVALID_SOFTWARE_INTERRUPT +Language=English +INVALID_SOFTWARE_INTERRUPT +. + +MessageId=0x08 +Severity=Success +Facility=System +SymbolicName=IRQL_NOT_DISPATCH_LEVEL +Language=English +IRQL_NOT_DISPATCH_LEVEL +. + +MessageId=0x09 +Severity=Success +Facility=System +SymbolicName=IRQL_NOT_GREATER_OR_EQUAL +Language=English +IRQL_NOT_GREATER_OR_EQUAL +. + +MessageId=0x0A +Severity=Success +Facility=System +SymbolicName=IRQL_NOT_LESS_OR_EQUAL +Language=English +IRQL_NOT_LESS_OR_EQUAL +. + +MessageId=0x0B +Severity=Success +Facility=System +SymbolicName=NO_EXCEPTION_HANDLING_SUPPORT +Language=English +NO_EXCEPTION_HANDLING_SUPPORT +. + +MessageId=0x0C +Severity=Success +Facility=System +SymbolicName=MAXIMUM_WAIT_OBJECTS_EXCEEDED +Language=English +MAXIMUM_WAIT_OBJECTS_EXCEEDED +. + +MessageId=0x0D +Severity=Success +Facility=System +SymbolicName=MUTEX_LEVEL_NUMBER_VIOLATION +Language=English +MUTEX_LEVEL_NUMBER_VIOLATION +. + +MessageId=0x0E +Severity=Success +Facility=System +SymbolicName=NO_USER_MODE_CONTEXT +Language=English +NO_USER_MODE_CONTEXT +. + +MessageId=0x0F +Severity=Success +Facility=System +SymbolicName=SPIN_LOCK_ALREADY_OWNED +Language=English +SPIN_LOCK_ALREADY_OWNED +. + +MessageId=0x10 +Severity=Success +Facility=System +SymbolicName=SPIN_LOCK_NOT_OWNED +Language=English +SPIN_LOCK_NOT_OWNED +. + +MessageId=0x11 +Severity=Success +Facility=System +SymbolicName=THREAD_NOT_MUTEX_OWNER +Language=English +THREAD_NOT_MUTEX_OWNER +. + +MessageId=0x12 +Severity=Success +Facility=System +SymbolicName=TRAP_CAUSE_UNKNOWN +Language=English +TRAP_CAUSE_UNKNOWN +. + +MessageId=0x13 +Severity=Success +Facility=System +SymbolicName=EMPTY_THREAD_REAPER_LIST +Language=English +EMPTY_THREAD_REAPER_LIST +. + +MessageId=0x14 +Severity=Success +Facility=System +SymbolicName=CREATE_DELETE_LOCK_NOT_LOCKED +Language=English +The thread reaper was handed a thread to reap, but the thread's process' +. + +MessageId=0x15 +Severity=Success +Facility=System +SymbolicName=LAST_CHANCE_CALLED_FROM_KMODE +Language=English +LAST_CHANCE_CALLED_FROM_KMODE +. + +MessageId=0x16 +Severity=Success +Facility=System +SymbolicName=CID_HANDLE_CREATION +Language=English +CID_HANDLE_CREATION +. + +MessageId=0x17 +Severity=Success +Facility=System +SymbolicName=CID_HANDLE_DELETION +Language=English +CID_HANDLE_DELETION +. + +MessageId=0x18 +Severity=Success +Facility=System +SymbolicName=REFERENCE_BY_POINTER +Language=English +REFERENCE_BY_POINTER +. + +MessageId=0x19 +Severity=Success +Facility=System +SymbolicName=BAD_POOL_HEADER +Language=English +BAD_POOL_HEADER +. + +MessageId=0x1A +Severity=Success +Facility=System +SymbolicName=MEMORY_MANAGEMENT +Language=English +MEMORY_MANAGEMENT +. + +MessageId=0x1B +Severity=Success +Facility=System +SymbolicName=PFN_SHARE_COUNT +Language=English +PFN_SHARE_COUNT +. + +MessageId=0x1C +Severity=Success +Facility=System +SymbolicName=PFN_REFERENCE_COUNT +Language=English +PFN_REFERENCE_COUNT +. + +MessageId=0x1D +Severity=Success +Facility=System +SymbolicName=NO_SPINLOCK_AVAILABLE +Language=English +NO_SPINLOCK_AVAILABLE +. + +MessageId=0x1E +Severity=Success +Facility=System +SymbolicName=KMODE_EXCEPTION_NOT_HANDLED +Language=English +KMODE_EXCEPTION_NOT_HANDLED +. + +MessageId=0x1F +Severity=Success +Facility=System +SymbolicName=SHARED_RESOURCE_CONV_ERROR +Language=English +SHARED_RESOURCE_CONV_ERROR +. + +MessageId=0x20 +Severity=Success +Facility=System +SymbolicName=KERNEL_APC_PENDING_DURING_EXIT +Language=English +KERNEL_APC_PENDING_DURING_EXIT +. + +MessageId=0x21 +Severity=Success +Facility=System +SymbolicName=QUOTA_UNDERFLOW +Language=English +QUOTA_UNDERFLOW +. + +MessageId=0x22 +Severity=Success +Facility=System +SymbolicName=FILE_SYSTEM +Language=English +FILE_SYSTEM +. + +MessageId=0x23 +Severity=Success +Facility=System +SymbolicName=FAT_FILE_SYSTEM +Language=English +FAT_FILE_SYSTEM +. + +MessageId=0x24 +Severity=Success +Facility=System +SymbolicName=NTFS_FILE_SYSTEM +Language=English +NTFS_FILE_SYSTEM +. + +MessageId=0x25 +Severity=Success +Facility=System +SymbolicName=NPFS_FILE_SYSTEM +Language=English +NPFS_FILE_SYSTEM +. + +MessageId=0x26 +Severity=Success +Facility=System +SymbolicName=CDFS_FILE_SYSTEM +Language=English +CDFS_FILE_SYSTEM +. + +MessageId=0x27 +Severity=Success +Facility=System +SymbolicName=RDR_FILE_SYSTEM +Language=English +RDR_FILE_SYSTEM +. + +MessageId=0x28 +Severity=Success +Facility=System +SymbolicName=CORRUPT_ACCESS_TOKEN +Language=English +CORRUPT_ACCESS_TOKEN +. + +MessageId=0x29 +Severity=Success +Facility=System +SymbolicName=SECURITY_SYSTEM +Language=English +SECURITY_SYSTEM +. + +MessageId=0x2A +Severity=Success +Facility=System +SymbolicName=INCONSISTENT_IRP +Language=English +INCONSISTENT_IRP +. + +MessageId=0x2B +Severity=Success +Facility=System +SymbolicName=PANIC_STACK_SWITCH +Language=English +PANIC_STACK_SWITCH +. + +MessageId=0x2C +Severity=Success +Facility=System +SymbolicName=PORT_DRIVER_INTERNAL +Language=English +PORT_DRIVER_INTERNAL +. + +MessageId=0x2D +Severity=Success +Facility=System +SymbolicName=SCSI_DISK_DRIVER_INTERNAL +Language=English +SCSI_DISK_DRIVER_INTERNAL +. + +MessageId=0x2E +Severity=Success +Facility=System +SymbolicName=DATA_BUS_ERROR +Language=English +DATA_BUS_ERROR +. + +MessageId=0x2F +Severity=Success +Facility=System +SymbolicName=INSTRUCTION_BUS_ERROR +Language=English +INSTRUCTION_BUS_ERROR +. + +MessageId=0x30 +Severity=Success +Facility=System +SymbolicName=SET_OF_INVALID_CONTEXT +Language=English +SET_OF_INVALID_CONTEXT +. + +MessageId=0x31 +Severity=Success +Facility=System +SymbolicName=PHASE0_INITIALIZATION_FAILED +Language=English +PHASE0_INITIALIZATION_FAILED +. + +MessageId=0x32 +Severity=Success +Facility=System +SymbolicName=PHASE1_INITIALIZATION_FAILED +Language=English +PHASE1_INITIALIZATION_FAILED +. + +MessageId=0x33 +Severity=Success +Facility=System +SymbolicName=UNEXPECTED_INITIALIZATION_CALL +Language=English +UNEXPECTED_INITIALIZATION_CALL +. + +MessageId=0x34 +Severity=Success +Facility=System +SymbolicName=CACHE_MANAGER +Language=English +CACHE_MANAGER +. + +MessageId=0x35 +Severity=Success +Facility=System +SymbolicName=NO_MORE_IRP_STACK_LOCATIONS +Language=English +NO_MORE_IRP_STACK_LOCATIONS +. + +MessageId=0x36 +Severity=Success +Facility=System +SymbolicName=DEVICE_REFERENCE_COUNT_NOT_ZERO +Language=English +DEVICE_REFERENCE_COUNT_NOT_ZERO +. + +MessageId=0x37 +Severity=Success +Facility=System +SymbolicName=FLOPPY_INTERNAL_ERROR +Language=English +FLOPPY_INTERNAL_ERROR +. + +MessageId=0x38 +Severity=Success +Facility=System +SymbolicName=SERIAL_DRIVER_INTERNAL +Language=English +SERIAL_DRIVER_INTERNAL +. + +MessageId=0x39 +Severity=Success +Facility=System +SymbolicName=SYSTEM_EXIT_OWNED_MUTEX +Language=English +SYSTEM_EXIT_OWNED_MUTEX +. + + + + +MessageId=0x3E +Severity=Success +Facility=System +SymbolicName=MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED +Language=English +MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED +. + +MessageId=0x3F +Severity=Success +Facility=System +SymbolicName=NO_MORE_SYSTEM_PTES +Language=English +NO_MORE_SYSTEM_PTES +. + +MessageId=0x40 +Severity=Success +Facility=System +SymbolicName=TARGET_MDL_TOO_SMALL +Language=English +TARGET_MDL_TOO_SMALL +. + +MessageId=0x41 +Severity=Success +Facility=System +SymbolicName=MUST_SUCCEED_POOL_EMPTY +Language=English +MUST_SUCCEED_POOL_EMPTY +. + +MessageId=0x42 +Severity=Success +Facility=System +SymbolicName=ATDISK_DRIVER_INTERNAL +Language=English +ATDISK_DRIVER_INTERNAL +. + + + +MessageId=0x44 +Severity=Success +Facility=System +SymbolicName=MULTIPLE_IRP_COMPLETE_REQUESTS +Language=English +MULTIPLE_IRP_COMPLETE_REQUESTS +. + +MessageId=0x45 +Severity=Success +Facility=System +SymbolicName=INSUFFICIENT_SYSTEM_MAP_REGS +Language=English +INSUFFICIENT_SYSTEM_MAP_REGS +. + + + +MessageId=0x48 +Severity=Success +Facility=System +SymbolicName=CANCEL_STATE_IN_COMPLETED_IRP +Language=English +CANCEL_STATE_IN_COMPLETED_IRP +. + +MessageId=0x49 +Severity=Success +Facility=System +SymbolicName=PAGE_FAULT_WITH_INTERRUPTS_OFF +Language=English +PAGE_FAULT_WITH_INTERRUPTS_OFF +. + +MessageId=0x4A +Severity=Success +Facility=System +SymbolicName=IRQL_GT_ZERO_AT_SYSTEM_SERVICE +Language=English +IRQL_GT_ZERO_AT_SYSTEM_SERVICE +. + +MessageId=0x4B +Severity=Success +Facility=System +SymbolicName=STREAMS_INTERNAL_ERROR +Language=English +STREAMS_INTERNAL_ERROR +. + + + +MessageId=0x4D +Severity=Success +Facility=System +SymbolicName=NO_PAGES_AVAILABLE +Language=English +NO_PAGES_AVAILABLE +. + +MessageId=0x4E +Severity=Success +Facility=System +SymbolicName=PFN_LIST_CORRUPT +Language=English +PFN_LIST_CORRUPT +. + +MessageId=0x4F +Severity=Success +Facility=System +SymbolicName=NDIS_INTERNAL_ERROR +Language=English +NDIS_INTERNAL_ERROR +. + +MessageId=0x50 +Severity=Success +Facility=System +SymbolicName=PAGE_FAULT_IN_NONPAGED_AREA +Language=English +PAGE_FAULT_IN_NONPAGED_AREA +. + +MessageId=0x51 +Severity=Success +Facility=System +SymbolicName=REGISTRY_ERROR +Language=English +REGISTRY_ERROR +. + +MessageId=0x52 +Severity=Success +Facility=System +SymbolicName=MAILSLOT_FILE_SYSTEM +Language=English +MAILSLOT_FILE_SYSTEM +. + + + +MessageId=0x54 +Severity=Success +Facility=System +SymbolicName=LM_SERVER_INTERNAL_ERROR +Language=English +LM_SERVER_INTERNAL_ERROR +. + +MessageId=0x55 +Severity=Success +Facility=System +SymbolicName=DATA_COHERENCY_EXCEPTION +Language=English +DATA_COHERENCY_EXCEPTION +. + +MessageId=0x56 +Severity=Success +Facility=System +SymbolicName=INSTRUCTION_COHERENCY_EXCEPTION +Language=English +INSTRUCTION_COHERENCY_EXCEPTION +. + +MessageId=0x57 +Severity=Success +Facility=System +SymbolicName=XNS_INTERNAL_ERROR +Language=English +XNS_INTERNAL_ERROR +. + +MessageId=0x58 +Severity=Success +Facility=System +SymbolicName=FTDISK_INTERNAL_ERROR +Language=English +FTDISK_INTERNAL_ERROR +. + +MessageId=0x59 +Severity=Success +Facility=System +SymbolicName=PINBALL_FILE_SYSTEM +Language=English +PINBALL_FILE_SYSTEM +. + + + +MessageId=0x5C +Severity=Success +Facility=System +SymbolicName=HAL_INITIALIZATION_FAILED +Language=English +HAL_INITIALIZATION_FAILED +. + +MessageId=0x5D +Severity=Success +Facility=System +SymbolicName=HEAP_INITIALIZATION_FAILED +Language=English +HEAP_INITIALIZATION_FAILED +. + +MessageId=0x5E +Severity=Success +Facility=System +SymbolicName=OBJECT_INITIALIZATION_FAILED +Language=English +OBJECT_INITIALIZATION_FAILED +. + +MessageId=0x5F +Severity=Success +Facility=System +SymbolicName=SECURITY_INITIALIZATION_FAILED +Language=English +SECURITY_INITIALIZATION_FAILED +. + +MessageId=0x60 +Severity=Success +Facility=System +SymbolicName=PROCESS_INITIALIZATION_FAILED +Language=English +PROCESS_INITIALIZATION_FAILED +. + +MessageId=0x61 +Severity=Success +Facility=System +SymbolicName=HAL1_INITIALIZATION_FAILED +Language=English +HAL1_INITIALIZATION_FAILED +. + +MessageId=0x62 +Severity=Success +Facility=System +SymbolicName=OBJECT1_INITIALIZATION_FAILED +Language=English +OBJECT1_INITIALIZATION_FAILED +. + +MessageId=0x63 +Severity=Success +Facility=System +SymbolicName=SECURITY1_INITIALIZATION_FAILED +Language=English +SECURITY1_INITIALIZATION_FAILED +. + +MessageId=0x64 +Severity=Success +Facility=System +SymbolicName=SYMBOLIC_INITIALIZATION_FAILED +Language=English +SYMBOLIC_INITIALIZATION_FAILED +. + +MessageId=0x65 +Severity=Success +Facility=System +SymbolicName=MEMORY1_INITIALIZATION_FAILED +Language=English +MEMORY1_INITIALIZATION_FAILED +. + +MessageId=0x66 +Severity=Success +Facility=System +SymbolicName=CACHE_INITIALIZATION_FAILED +Language=English +CACHE_INITIALIZATION_FAILED +. + +MessageId=0x67 +Severity=Success +Facility=System +SymbolicName=CONFIG_INITIALIZATION_FAILED +Language=English +CONFIG_INITIALIZATION_FAILED +. + +MessageId=0x68 +Severity=Success +Facility=System +SymbolicName=FILE_INITIALIZATION_FAILED +Language=English +FILE_INITIALIZATION_FAILED +. + +MessageId=0x69 +Severity=Success +Facility=System +SymbolicName=IO1_INITIALIZATION_FAILED +Language=English +IO1_INITIALIZATION_FAILED +. + +MessageId=0x6A +Severity=Success +Facility=System +SymbolicName=LPC_INITIALIZATION_FAILED +Language=English +LPC_INITIALIZATION_FAILED +. + +MessageId=0x6B +Severity=Success +Facility=System +SymbolicName=PROCESS1_INITIALIZATION_FAILED +Language=English +PROCESS1_INITIALIZATION_FAILED +. + +MessageId=0x6C +Severity=Success +Facility=System +SymbolicName=REFMON_INITIALIZATION_FAILED +Language=English +REFMON_INITIALIZATION_FAILED +. + +MessageId=0x6D +Severity=Success +Facility=System +SymbolicName=SESSION1_INITIALIZATION_FAILED +Language=English +SESSION1_INITIALIZATION_FAILED +. + +MessageId=0x6E +Severity=Success +Facility=System +SymbolicName=SESSION2_INITIALIZATION_FAILED +Language=English +SESSION2_INITIALIZATION_FAILED +. + +MessageId=0x6F +Severity=Success +Facility=System +SymbolicName=SESSION3_INITIALIZATION_FAILED +Language=English +SESSION3_INITIALIZATION_FAILED +. + +MessageId=0x70 +Severity=Success +Facility=System +SymbolicName=SESSION4_INITIALIZATION_FAILED +Language=English +SESSION4_INITIALIZATION_FAILED +. + +MessageId=0x71 +Severity=Success +Facility=System +SymbolicName=SESSION5_INITIALIZATION_FAILED +Language=English +SESSION5_INITIALIZATION_FAILED +. + +MessageId=0x72 +Severity=Success +Facility=System +SymbolicName=ASSIGN_DRIVE_LETTERS_FAILED +Language=English +ASSIGN_DRIVE_LETTERS_FAILED +. + +MessageId=0x73 +Severity=Success +Facility=System +SymbolicName=CONFIG_LIST_FAILED +Language=English +CONFIG_LIST_FAILED +. + +MessageId=0x74 +Severity=Success +Facility=System +SymbolicName=BAD_SYSTEM_CONFIG_INFO +Language=English +BAD_SYSTEM_CONFIG_INFO +. + +MessageId=0x75 +Severity=Success +Facility=System +SymbolicName=CANNOT_WRITE_CONFIGURATION +Language=English +CANNOT_WRITE_CONFIGURATION +. + +MessageId=0x76 +Severity=Success +Facility=System +SymbolicName=PROCESS_HAS_LOCKED_PAGES +Language=English +PROCESS_HAS_LOCKED_PAGES +. + +MessageId=0x77 +Severity=Success +Facility=System +SymbolicName=KERNEL_STACK_INPAGE_ERROR +Language=English +KERNEL_STACK_INPAGE_ERROR +. + +MessageId=0x78 +Severity=Success +Facility=System +SymbolicName=PHASE0_EXCEPTION +Language=English +PHASE0_EXCEPTION +. + +MessageId=0x79 +Severity=Success +Facility=System +SymbolicName=MISMATCHED_HAL +Language=English +Mismatched Kernel and HAL image +. + +MessageId=0x7A +Severity=Success +Facility=System +SymbolicName=KERNEL_DATA_INPAGE_ERROR +Language=English +KERNEL_DATA_INPAGE_ERROR +. + +MessageId=0x7B +Severity=Success +Facility=System +SymbolicName=INACCESSIBLE_BOOT_DEVICE +Language=English +INACCESSIBLE_BOOT_DEVICE +. + + + +MessageId=0x7D +Severity=Success +Facility=System +SymbolicName=INSTALL_MORE_MEMORY +Language=English +INSTALL_MORE_MEMORY +. + +MessageId=0x7E +Severity=Success +Facility=System +SymbolicName=UNEXPECTED_KERNEL_MODE_TRAP +Language=English +UNEXPECTED_KERNEL_MODE_TRAP +. + +MessageId=0x7F +Severity=Success +Facility=System +SymbolicName=NMI_HARDWARE_FAILURE +Language=English +Hardware malfunction +. + +MessageId=0x80 +Severity=Success +Facility=System +SymbolicName=SPIN_LOCK_INIT_FAILURE +Language=English +SPIN_LOCK_INIT_FAILURE +. + + + + +MessageId=0x9A +Severity=Informational +Facility=System +SymbolicName=REACTOS_BANNER +Language=English +ReactOS Version %s (Build %s) +. + +MessageId=0x9B +Severity=Informational +Facility=System +SymbolicName=REACTOS_SERVICE_PACK +Language=English +Service Pack +. + +MessageId=0x9C +Severity=Informational +Facility=System +SymbolicName=REACTOS_INFO_STRING_UNI_PROCESSOR +Language=English +%u System Processor [%u MB Memory] %Z +. + +MessageId=0x9D +Severity=Informational +Facility=System +SymbolicName=REACTOS_MP_KERNEL +Language=English +MulitProcessor Kernel +. + +MessageId=0x9E +Severity=Informational +Facility=System +SymbolicName=REACTOS_INFO_STRING_MULTI_PROCESSOR +Language=English +%u System Processors [%u MB Memory] %Z +. + +MessageId=0x9F +Severity=Informational +Facility=System +SymbolicName=REACTOS_COPYRIGHT_NOTICE +Language=English +\n\nReactOS is free software, covered by the GNU General Public License, + and you\n are welcome to change it and/or distribute copies of it under + certain\n conditions. There is absolutely no warranty for ReactOS.\n +. + +; EOF \ No newline at end of file diff --git a/ntoskrnl/ntoskrnl.rc b/ntoskrnl/ntoskrnl.rc new file mode 100644 index 0000000..2d6864d --- /dev/null +++ b/ntoskrnl/ntoskrnl.rc @@ -0,0 +1,39 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Kernel & System\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ntoskrnl\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ntoskrnl.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#include "bugcodes.rc" diff --git a/ntoskrnl/ntoskrnl.txt b/ntoskrnl/ntoskrnl.txt new file mode 100644 index 0000000..1e23991 --- /dev/null +++ b/ntoskrnl/ntoskrnl.txt @@ -0,0 +1,1084 @@ +Name: Ntoskrnl.exe + +Description: Windows NT Executive + + +Ordinal Exported +Value: Name: +1 ExAcquireFastMutexUnsafe +2 ExInterlockedAddLargeStatistic +3 ExInterlockedCompareExchange64 +4 ExInterlockedPopEntrySList +5 ExInterlockedPushEntrySList +6 ExReleaseFastMutexUnsafe +7 ExReleaseResourceLite +8 ExfInterlockedAddUlong +9 ExfInterlockedInsertHeadList +10 ExfInterlockedInsertTailList +11 ExfInterlockedPopEntryList +12 ExfInterlockedPushEntryList +13 ExfInterlockedRemoveHeadList +14 Exfi386InterlockedDecrementLong +15 Exfi386InterlockedExchangeUlong +16 Exfi386InterlockedIncrementLong +17 InterlockedCompareExchange +18 InterlockedDecrement +19 InterlockedExchange +20 InterlockedExchangeAdd +21 InterlockedIncrement +22 IofCallDriver +23 IofCompleteRequest +24 KeSetSwapContextNotifyRoutine +25 KeSetThreadSelectNotifyRoutine +26 KeSetTimeUpdateNotifyRoutine +27 KefAcquireSpinLockAtDpcLevel +28 KefReleaseSpinLockFromDpcLevel +29 KiAcquireSpinLock +30 KiReleaseSpinLock +31 ObfDereferenceObject +32 ObfReferenceObject +33 Kei386EoiHelper +34 Kii386SpinOnSpinLock +35 CcCanIWrite +36 CcCopyRead +37 CcCopyWrite +38 CcDeferWrite +39 CcFastCopyRead +40 CcFastCopyWrite +41 CcFastMdlReadWait +42 CcFastReadNotPossible +43 CcFastReadWait +44 CcFlushCache +45 CcGetDirtyPages +46 CcGetFileObjectFromBcb +47 CcGetFileObjectFromSectionPtrs +48 CcGetLsnForFileObject +49 CcInitializeCacheMap +50 CcIsThereDirtyData +51 CcMapData +52 CcMdlRead +53 CcMdlReadComplete +54 CcMdlWriteComplete +55 CcPinMappedData +56 CcPinRead +57 CcPrepareMdlWrite +58 CcPreparePinWrite +59 CcPurgeCacheSection +60 CcRepinBcb +61 CcScheduleReadAhead +62 CcSetAdditionalCacheAttributes +63 CcSetBcbOwnerPointer +64 CcSetDirtyPageThreshold +65 CcSetDirtyPinnedData +66 CcSetFileSizes +67 CcSetLogHandleForFile +68 CcSetReadAheadGranularity +69 CcUninitializeCacheMap +70 CcUnpinData +71 CcUnpinDataForThread +72 CcUnpinRepinnedBcb +73 CcZeroData +74 DbgBreakPoint +75 DbgBreakPointWithStatus +76 DbgLoadImageSymbols +77 DbgPrint +78 DbgPrompt +79 ExAcquireResourceExclusive +80 ExAcquireResourceExclusiveLite +81 ExAcquireResourceSharedLite +82 ExAcquireSharedStarveExclusive +83 ExAcquireSharedWaitForExclusive +84 ExAllocateFromPagedLookasideList +85 ExAllocatePool +86 ExAllocatePoolWithQuota +87 ExAllocatePoolWithQuotaTag +88 ExAllocatePoolWithTag +89 ExConvertExclusiveToSharedLite +90 ExCreateCallback +91 ExDeleteNPagedLookasideList +92 ExDeletePagedLookasideList +93 ExDeleteResource +94 ExDeleteResourceLite +95 ExDesktopObjectType +96 ExDisableResourceBoostLite +97 ExEnumHandleTable +98 ExEventObjectType +99 ExExtendZone +100 ExFreePool +101 ExFreeToPagedLookasideList +102 ExGetExclusiveWaiterCount +103 ExGetPreviousMode +104 ExGetSharedWaiterCount +105 ExInitializeNPagedLookasideList +106 ExInitializePagedLookasideList +107 ExInitializeResource +108 ExInitializeResourceLite +109 ExInitializeZone +110 ExInterlockedAddLargeInteger +111 ExInterlockedAddUlong +112 ExInterlockedDecrementLong +113 ExInterlockedExchangeUlong +114 ExInterlockedExtendZone +115 ExInterlockedIncrementLong +116 ExInterlockedInsertHeadList +117 ExInterlockedInsertTailList +118 ExInterlockedPopEntryList +119 ExInterlockedPushEntryList +120 ExInterlockedRemoveHeadList +121 ExIsProcessorFeaturePresent +122 ExIsResourceAcquiredExclusiveLite +123 ExIsResourceAcquiredSharedLite +124 ExLocalTimeToSystemTime +125 ExNotifyCallback +126 ExPostSystemEvent +127 ExQueryPoolBlockSize +128 ExQueueWorkItem +129 ExRaiseAccessViolation +130 ExRaiseDatatypeMisalignment +131 ExRaiseException +132 ExRaiseHardError +133 ExRaiseStatus +134 ExRegisterCallback +135 ExReinitializeResourceLite +136 ExReleaseResourceForThread +137 ExReleaseResourceForThreadLite +138 ExSetResourceOwnerPointer +139 ExSystemExceptionFilter +140 ExSystemTimeToLocalTime +141 ExUnregisterCallback +142 ExWindowStationObjectType +143 Exi386InterlockedDecrementLong +144 Exi386InterlockedExchangeUlong +145 Exi386InterlockedIncrementLong +146 FsRtlAddLargeMcbEntry +147 FsRtlAddMcbEntry +148 FsRtlAddToTunnelCache +149 FsRtlAllocatePool +150 FsRtlAllocatePoolWithQuota +151 FsRtlAllocatePoolWithQuotaTag +152 FsRtlAllocatePoolWithTag +153 FsRtlAllocateResource +154 FsRtlAreNamesEqual +155 FsRtlBalanceReads +156 FsRtlCheckLockForReadAccess +157 FsRtlCheckLockForWriteAccess +158 FsRtlCheckOplock +159 FsRtlCopyRead +160 FsRtlCopyWrite +161 FsRtlCurrentBatchOplock +162 FsRtlDeleteKeyFromTunnelCache +163 FsRtlDeleteTunnelCache +164 FsRtlDeregisterUncProvider +165 FsRtlDissectDbcs +166 FsRtlDissectName +167 FsRtlDoesDbcsContainWildCards +168 FsRtlDoesNameContainWildCards +169 FsRtlFastCheckLockForRead +170 FsRtlFastCheckLockForWrite +171 FsRtlFastUnlockAll +172 FsRtlFastUnlockAllByKey +173 FsRtlFastUnlockSingle +174 FsRtlFindInTunnelCache +175 FsRtlGetFileSize +176 FsRtlGetNextFileLock +177 FsRtlGetNextLargeMcbEntry +178 FsRtlGetNextMcbEntry +179 FsRtlInitializeFileLock +180 FsRtlInitializeLargeMcb +181 FsRtlInitializeMcb +182 FsRtlInitializeOplock +183 FsRtlInitializeTunnelCache +184 FsRtlIsDbcsInExpression +185 FsRtlIsFatDbcsLegal +186 FsRtlIsHpfsDbcsLegal +187 FsRtlIsNameInExpression +188 FsRtlIsNtstatusExpected +189 FsRtlIsTotalDeviceFailure +190 FsRtlLegalAnsiCharacterArray +191 FsRtlLookupLargeMcbEntry +192 FsRtlLookupLastLargeMcbEntry +193 FsRtlLookupLastMcbEntry +194 FsRtlLookupMcbEntry +195 FsRtlMdlRead +196 FsRtlMdlReadComplete +197 FsRtlMdlReadCompleteDev +198 FsRtlMdlReadDev +199 FsRtlMdlWriteComplete +200 FsRtlMdlWriteCompleteDev +201 FsRtlNormalizeNtstatus +202 FsRtlNotifyChangeDirectory +203 FsRtlNotifyCleanup +204 FsRtlNotifyFullChangeDirectory +205 FsRtlNotifyFullReportChange +206 FsRtlNotifyInitializeSync +207 FsRtlNotifyReportChange +208 FsRtlNotifyUninitializeSync +209 FsRtlNumberOfRunsInLargeMcb +210 FsRtlNumberOfRunsInMcb +211 FsRtlOplockFsctrl +212 FsRtlOplockIsFastIoPossible +213 FsRtlPostPagingFileStackOverflow +214 FsRtlPostStackOverflow +215 FsRtlPrepareMdlWrite +216 FsRtlPrepareMdlWriteDev +217 FsRtlPrivateLock +218 FsRtlProcessFileLock +219 FsRtlRegisterUncProvider +220 FsRtlRemoveLargeMcbEntry +221 FsRtlRemoveMcbEntry +222 FsRtlSplitLargeMcb +223 FsRtlSyncVolumes +224 FsRtlTruncateLargeMcb +225 FsRtlTruncateMcb +226 FsRtlUninitializeFileLock +227 FsRtlUninitializeLargeMcb +228 FsRtlUninitializeMcb +229 FsRtlUninitializeOplock +230 HalDispatchTable +231 HalPrivateDispatchTable +232 IoAcquireCancelSpinLock +233 IoAcquireVpbSpinLock +234 IoAdapterObjectType +235 IoAllocateAdapterChannel +236 IoAllocateController +237 IoAllocateErrorLogEntry +238 IoAllocateIrp +239 IoAllocateMdl +240 IoAssignResources +241 IoAttachDevice +242 IoAttachDeviceByPointer +243 IoAttachDeviceToDeviceStack +244 IoBuildAsynchronousFsdRequest +245 IoBuildDeviceIoControlRequest +246 IoBuildPartialMdl +247 IoBuildSynchronousFsdRequest +248 IoCallDriver +249 IoCancelIrp +250 IoCheckDesiredAccess +251 IoCheckEaBufferValidity +252 IoCheckFunctionAccess +253 IoCheckShareAccess +254 IoCompleteRequest +255 IoConnectInterrupt +256 IoCreateController +257 IoCreateDevice +258 IoCreateFile +259 IoCreateNotificationEvent +260 IoCreateStreamFileObject +261 IoCreateSymbolicLink +262 IoCreateSynchronizationEvent +263 IoCreateUnprotectedSymbolicLink +264 IoDeleteController +265 IoDeleteDevice +266 IoDeleteSymbolicLink +267 IoDetachDevice +268 IoDeviceHandlerObjectSize +269 IoDeviceHandlerObjectType +270 IoDeviceObjectType +271 IoDisconnectInterrupt +272 IoDriverObjectType +273 IoEnqueueIrp +274 IoFastQueryNetworkAttributes +275 IoFileObjectType +276 IoFreeController +277 IoFreeIrp +278 IoFreeMdl +279 IoGetAttachedDevice +280 IoGetBaseFileSystemDeviceObject +281 IoGetConfigurationInformation +282 IoGetCurrentProcess +283 IoGetDeviceObjectPointer +284 IoGetDeviceToVerify +285 IoGetFileObjectGenericMapping +286 IoGetInitialStack +287 IoGetRelatedDeviceObject +288 IoGetRequestorProcess +289 IoGetStackLimits +290 IoGetTopLevelIrp +291 IoInitializeIrp +292 IoInitializeTimer +293 IoIsOperationSynchronous +294 IoIsSystemThread +295 IoMakeAssociatedIrp +296 IoOpenDeviceInstanceKey +297 IoPageRead +298 IoQueryDeviceDescription +299 IoQueryDeviceEnumInfo +300 IoQueryFileInformation +301 IoQueryVolumeInformation +302 IoQueueThreadIrp +303 IoRaiseHardError +304 IoRaiseInformationalHardError +305 IoReadOperationCount +306 IoReadTransferCount +307 IoRegisterDriverReinitialization +308 IoRegisterFileSystem +309 IoRegisterFsRegistrationChange +310 IoRegisterShutdownNotification +311 IoReleaseCancelSpinLock +312 IoReleaseVpbSpinLock +313 IoRemoveShareAccess +314 IoReportHalResourceUsage +315 IoReportResourceUsage +316 IoSetDeviceToVerify +317 IoSetHardErrorOrVerifyDevice +318 IoSetInformation +319 IoSetShareAccess +320 IoSetThreadHardErrorMode +321 IoSetTopLevelIrp +322 IoStartNextPacket +323 IoStartNextPacketByKey +324 IoStartPacket +325 IoStartTimer +326 IoStatisticsLock +327 IoStopTimer +328 IoSynchronousPageWrite +329 IoThreadToProcess +330 IoUnregisterFileSystem +331 IoUnregisterFsRegistrationChange +332 IoUnregisterShutdownNotification +333 IoUpdateShareAccess +334 IoVerifyVolume +335 IoWriteErrorLogEntry +336 IoWriteOperationCount +337 IoWriteTransferCount +338 KdDebuggerEnabled +339 KdDebuggerNotPresent +340 KdPollBreakIn +341 Ke386CallBios +342 Ke386IoSetAccessProcess +343 Ke386QueryIoAccessMap +344 Ke386SetIoAccessMap +345 KeAcquireSpinLockAtDpcLevel +346 KeAddSystemServiceTable +347 KeAttachProcess +348 KeBoostCurrentThread +349 KeBugCheck +350 KeBugCheckEx +351 KeCancelTimer +352 KeClearEvent +353 KeConnectInterrupt +354 KeDcacheFlushCount +355 KeDelayExecutionThread +356 KeDeregisterBugCheckCallback +357 KeDetachProcess +358 KeDisconnectInterrupt +359 KeEnterCriticalRegion +360 KeEnterKernelDebugger +361 KeFindConfigurationEntry +362 KeFindConfigurationNextEntry +363 KeFlushEntireTb +364 KeGetCurrentThread +365 KeGetPreviousMode +366 KeI386AbiosCall +367 KeI386AllocateGdtSelectors +368 KeI386Call16BitCStyleFunction +369 KeI386Call16BitFunction +370 KeI386FlatToGdtSelector +371 KeI386GetLid +372 KeI386MachineType +373 KeI386ReleaseGdtSelectors +374 KeI386ReleaseLid +375 KeI386SetGdtSelector +376 KeIcacheFlushCount +377 KeInitializeApc +378 KeInitializeDeviceQueue +379 KeInitializeDpc +380 KeInitializeEvent +381 KeInitializeInterrupt +382 KeInitializeMutant +383 KeInitializeMutex +384 KeInitializeQueue +385 KeInitializeSemaphore +386 KeInitializeSpinLock +387 KeInitializeTimer +388 KeInitializeTimerEx +389 KeInsertByKeyDeviceQueue +390 KeInsertDeviceQueue +391 KeInsertHeadQueue +392 KeInsertQueue +393 KeInsertQueueApc +394 KeInsertQueueDpc +395 KeIsExecutingDpc +396 KeLeaveCriticalRegion +397 KeLoaderBlock +398 KeNumberProcessors +399 KeProfileInterrupt +400 KeProfileInterruptWithSource +401 KePulseEvent +402 KeQuerySystemTime +403 KeQueryTickCount +404 KeQueryTimeIncrement +405 KeRaiseUserException +406 KeReadStateEvent +407 KeReadStateMutant +408 KeReadStateMutex +409 KeReadStateQueue +410 KeReadStateSemaphore +411 KeReadStateTimer +412 KeRegisterBugCheckCallback +413 KeReleaseMutant +414 KeReleaseMutex +415 KeReleaseSemaphore +416 KeReleaseSpinLockFromDpcLevel +417 KeRemoveByKeyDeviceQueue +418 KeRemoveDeviceQueue +419 KeRemoveEntryDeviceQueue +420 KeRemoveQueue +421 KeRemoveQueueDpc +422 KeResetEvent +423 KeRestoreFloatingPointState +424 KeRundownQueue +425 KeSaveFloatingPointState +426 KeServiceDescriptorTable +427 KeSetAffinityThread +428 KeSetBasePriorityThread +429 KeSetDmaIoCoherency +430 KeSetEvent +431 KeSetEventBoostPriority +432 KeSetIdealProcessorThread +433 KeSetImportanceDpc +434 KeSetKernelStackSwapEnable +435 KeSetPriorityThread +436 KeSetProfileIrql +437 KeSetTargetProcessorDpc +438 KeSetTimeIncrement +439 KeSetTimer +440 KeSetTimerEx +441 KeSynchronizeExecution +442 KeTerminateThread +443 KeTickCount +444 KeUpdateRunTime +445 KeUpdateSystemTime +446 KeUserModeCallback +447 KeWaitForMultipleObjects +448 KeWaitForMutexObject +449 KeWaitForSingleObject +450 KiBugCheckData +451 KiCoprocessorError +452 KiDeliverApc +453 KiDispatchInterrupt +454 KiIpiServiceRoutine +455 KiUnexpectedInterrupt +456 LdrAccessResource +457 LdrEnumResources +458 LdrFindResourceDirectory_U +459 LdrFindResource_U +460 LpcRequestPort +461 LsaCallAuthenticationPackage +462 LsaDeregisterLogonProcess +463 LsaFreeReturnBuffer +464 LsaLogonUser +465 LsaLookupAuthenticationPackage +466 LsaRegisterLogonProcess +467 MmAdjustWorkingSetSize +468 MmAllocateContiguousMemory +469 MmAllocateNonCachedMemory +470 MmBuildMdlForNonPagedPool +471 MmCanFileBeTruncated +472 MmCreateMdl +473 MmCreateSection +474 MmDbgTranslatePhysicalAddress +475 MmDisableModifiedWriteOfSection +476 MmFlushImageSection +477 MmForceSectionClosed +478 MmFreeContiguousMemory +479 MmFreeNonCachedMemory +480 MmGetPhysicalAddress +481 MmGrowKernelStack +482 MmIsAddressValid +483 MmIsNonPagedSystemAddressValid +484 MmIsRecursiveIoFault +485 MmIsThisAnNtAsSystem +486 MmLockPagableDataSection +487 MmLockPagableImageSection +488 MmLockPagableSectionByHandle +489 MmMapIoSpace +490 MmMapLockedPages +491 MmMapMemoryDumpMdl +492 MmMapVideoDisplay +493 MmMapViewInSystemSpace +494 MmMapViewOfSection +495 MmPageEntireDriver +496 MmProbeAndLockPages +497 MmQuerySystemSize +498 MmResetDriverPaging +499 MmSectionObjectType +500 MmSecureVirtualMemory +501 MmSetAddressRangeModified +502 MmSetBankedSection +503 MmSizeOfMdl +504 MmUnlockPagableImageSection +505 MmUnlockPages +506 MmUnmapIoSpace +507 MmUnmapLockedPages +508 MmUnmapVideoDisplay +509 MmUnmapViewInSystemSpace +510 MmUnmapViewOfSection +511 MmUnsecureVirtualMemory +512 NlsAnsiCodePage +513 NlsLeadByteInfo +514 NlsMbCodePageTag +515 NlsMbOemCodePageTag +516 NlsOemLeadByteInfo +517 NtAddAtom +518 NtAdjustPrivilegesToken +519 NtAllocateLocallyUniqueId +520 NtAllocateUuids +521 NtAllocateVirtualMemory +522 NtBuildNumber +523 NtClose +524 NtConnectPort +525 NtCreateEvent +526 NtCreateFile +527 NtCreateSection +528 NtDeleteAtom +529 NtDeleteFile +530 NtDeviceIoControlFile +531 NtDuplicateObject +532 NtDuplicateToken +533 NtFindAtom +534 NtFreeVirtualMemory +535 NtFsControlFile +536 NtGlobalFlag +537 NtLockFile +538 NtMapViewOfSection +539 NtNotifyChangeDirectoryFile +540 NtOpenFile +541 NtOpenProcess +542 NtOpenProcessToken +543 NtQueryDirectoryFile +544 NtQueryEaFile +545 NtQueryInformationAtom +546 NtQueryInformationFile +547 NtQueryInformationProcess +548 NtQueryInformationToken +549 NtQueryOleDirectoryFile +550 NtQuerySecurityObject +551 NtQueryVolumeInformationFile +552 NtReadFile +553 NtRequestPort +554 NtRequestWaitReplyPort +555 NtSetEvent +556 NtSetInformationFile +557 NtSetInformationProcess +558 NtSetInformationThread +559 NtSetSecurityObject +560 NtUnlockFile +561 NtVdmControl +562 NtWaitForSingleObject +563 NtWriteFile +564 ObAssignSecurity +565 ObCheckCreateObjectAccess +566 ObCheckObjectAccess +567 ObCreateObject +568 ObDereferenceObject +569 ObFindHandleForObject +570 ObGetObjectPointerCount +571 ObGetObjectSecurity +572 ObInsertObject +573 ObMakeTemporaryObject +574 ObOpenObjectByName +575 ObOpenObjectByPointer +576 ObQueryNameString +577 ObQueryObjectAuditingByHandle +578 ObReferenceObjectByHandle +579 ObReferenceObjectByName +580 ObReferenceObjectByPointer +581 ObReleaseObjectSecurity +582 ObSetSecurityDescriptorInfo +583 PfxFindPrefix +584 PfxInitialize +585 PfxInsertPrefix +586 PfxRemovePrefix +587 PoQueryPowerSequence +588 PoRequestPowerChange +589 PoSetDeviceIdleDetection +590 ProbeForWrite +591 PsAssignImpersonationToken +592 PsChargePoolQuota +593 PsCreateSystemProcess +594 PsCreateSystemThread +595 PsCreateWin32Process +596 PsEstablishWin32Callouts +597 PsGetCurrentProcessId +598 PsGetCurrentThreadId +599 PsGetProcessExitTime +600 PsGetVersion +601 PsImpersonateClient +602 PsInitialSystemProcess +603 PsIsThreadTerminating +604 PsLookupProcessByProcessId +605 PsLookupProcessThreadByCid +606 PsLookupThreadByThreadId +607 PsProcessType +608 PsReferenceImpersonationToken +609 PsReferencePrimaryToken +610 PsReturnPoolQuota +611 PsRevertToSelf +612 PsSetCreateProcessNotifyRoutine +613 PsSetCreateThreadNotifyRoutine +614 PsSetLegoNotifyRoutine +615 PsSetProcessPriorityByClass +616 PsTerminateSystemThread +617 PsThreadType +618 READ_REGISTER_BUFFER_UCHAR +619 READ_REGISTER_BUFFER_ULONG +620 READ_REGISTER_BUFFER_USHORT +621 READ_REGISTER_UCHAR +622 READ_REGISTER_ULONG +623 READ_REGISTER_USHORT +624 RtlAbsoluteToSelfRelativeSD +625 RtlAddAccessAllowedAce +626 RtlAddAce +627 RtlAddAtomToAtomTable +628 RtlAllocateAndInitializeSid +629 RtlAllocateHeap +630 RtlAnsiCharToUnicodeChar +631 RtlAnsiStringToUnicodeSize +632 RtlAnsiStringToUnicodeString +633 RtlAppendAsciizToString +634 RtlAppendStringToString +635 RtlAppendUnicodeStringToString +636 RtlAppendUnicodeToString +637 RtlAreAllAccessesGranted +638 RtlAreAnyAccessesGranted +639 RtlAreBitsClear +640 RtlAreBitsSet +641 RtlAssert +642 RtlCaptureStackBackTrace +643 RtlCharToInteger +644 RtlCheckRegistryKey +645 RtlClearAllBits +646 RtlClearBits +647 RtlCompareMemory +648 RtlCompareMemoryUlong +649 RtlCompareString +650 RtlCompareUnicodeString +651 RtlCompressBuffer +652 RtlCompressChunks +653 RtlConvertLongToLargeInteger +654 RtlConvertSidToUnicodeString +655 RtlConvertUlongToLargeInteger +656 RtlCopyLuid +657 RtlCopySid +658 RtlCopyString +659 RtlCopyUnicodeString +660 RtlCreateAcl +661 RtlCreateAtomTable +662 RtlCreateHeap +663 RtlCreateRegistryKey +664 RtlCreateSecurityDescriptor +665 RtlCreateUnicodeString +666 RtlCustomCPToUnicodeN +667 RtlDecompressBuffer +668 RtlDecompressChunks +669 RtlDecompressFragment +670 RtlDelete +671 RtlDeleteAtomFromAtomTable +672 RtlDeleteElementGenericTable +673 RtlDeleteNoSplay +674 RtlDeleteRegistryValue +675 RtlDescribeChunk +676 RtlDestroyAtomTable +677 RtlDestroyHeap +678 RtlDowncaseUnicodeString +679 RtlEmptyAtomTable +680 RtlEnlargedIntegerMultiply +681 RtlEnlargedUnsignedDivide +682 RtlEnlargedUnsignedMultiply +683 RtlEnumerateGenericTable +684 RtlEnumerateGenericTableWithoutSplaying +685 RtlEqualLuid +686 RtlEqualSid +687 RtlEqualString +688 RtlEqualUnicodeString +689 RtlExtendedIntegerMultiply +690 RtlExtendedLargeIntegerDivide +691 RtlExtendedMagicDivide +692 RtlFillMemory +693 RtlFillMemoryUlong +694 RtlFindClearBits +695 RtlFindClearBitsAndSet +696 RtlFindFirstRunClear +697 RtlFindFirstRunSet +698 RtlFindLongestRunClear +699 RtlFindLongestRunSet +700 RtlFindMessage +701 RtlFindSetBits +702 RtlFindSetBitsAndClear +703 RtlFindUnicodePrefix +704 RtlFormatCurrentUserKeyPath +705 RtlFreeAnsiString +706 RtlFreeHeap +707 RtlFreeOemString +708 RtlFreeUnicodeString +709 RtlGenerate8dot3Name +710 RtlGetCallersAddress +711 RtlGetCompressionWorkSpaceSize +712 RtlGetDaclSecurityDescriptor +713 RtlGetDefaultCodePage +714 RtlGetElementGenericTable +715 RtlGetGroupSecurityDescriptor +716 RtlGetOwnerSecurityDescriptor +717 RtlImageNtHeader +718 RtlInitAnsiString +719 RtlInitCodePageTable +720 RtlInitString +721 RtlInitUnicodeString +722 RtlInitializeBitMap +723 RtlInitializeGenericTable +724 RtlInitializeSid +725 RtlInitializeUnicodePrefix +726 RtlInsertElementGenericTable +727 RtlInsertUnicodePrefix +728 RtlIntegerToChar +729 RtlIntegerToUnicodeString +730 RtlIsNameLegalDOS8Dot3 +731 RtlLargeIntegerAdd +732 RtlLargeIntegerArithmeticShift +733 RtlLargeIntegerDivide +734 RtlLargeIntegerNegate +735 RtlLargeIntegerShiftLeft +736 RtlLargeIntegerShiftRight +737 RtlLargeIntegerSubtract +738 RtlLengthRequiredSid +739 RtlLengthSecurityDescriptor +740 RtlLengthSid +741 RtlLookupAtomInAtomTable +742 RtlLookupElementGenericTable +743 RtlMapGenericMask +744 RtlMoveMemory +745 RtlMultiByteToUnicodeN +746 RtlMultiByteToUnicodeSize +747 RtlNextUnicodePrefix +748 RtlNtStatusToDosError +749 RtlNtStatusToDosErrorNoTeb +750 RtlNumberGenericTableElements +751 RtlNumberOfClearBits +752 RtlNumberOfSetBits +753 RtlOemStringToCountedUnicodeString +754 RtlOemStringToUnicodeSize +755 RtlOemStringToUnicodeString +756 RtlOemToUnicodeN +757 RtlPinAtomInAtomTable +758 RtlPrefixString +759 RtlPrefixUnicodeString +760 RtlQueryAtomInAtomTable +761 RtlQueryRegistryValues +762 RtlQueryTimeZoneInformation +763 RtlRaiseException +764 RtlRandom +765 RtlRemoveUnicodePrefix +766 RtlReserveChunk +767 RtlSecondsSince1970ToTime +768 RtlSecondsSince1980ToTime +769 RtlSetAllBits +770 RtlSetBits +771 RtlSetDaclSecurityDescriptor +772 RtlSetGroupSecurityDescriptor +773 RtlSetOwnerSecurityDescriptor +774 RtlSetSaclSecurityDescriptor +775 RtlSetTimeZoneInformation +776 RtlSplay +777 RtlSubAuthorityCountSid +778 RtlSubAuthoritySid +779 RtlTimeFieldsToTime +780 RtlTimeToSecondsSince1970 +781 RtlTimeToSecondsSince1980 +782 RtlTimeToTimeFields +783 RtlUnicodeStringToAnsiSize +784 RtlUnicodeStringToAnsiString +785 RtlUnicodeStringToCountedOemString +786 RtlUnicodeStringToInteger +787 RtlUnicodeStringToOemSize +788 RtlUnicodeStringToOemString +789 RtlUnicodeToCustomCPN +790 RtlUnicodeToMultiByteN +791 RtlUnicodeToMultiByteSize +792 RtlUnicodeToOemN +793 RtlUnwind +794 RtlUpcaseUnicodeChar +795 RtlUpcaseUnicodeString +796 RtlUpcaseUnicodeStringToAnsiString +797 RtlUpcaseUnicodeStringToCountedOemString +798 RtlUpcaseUnicodeStringToOemString +799 RtlUpcaseUnicodeToCustomCPN +800 RtlUpcaseUnicodeToMultiByteN +801 RtlUpcaseUnicodeToOemN +802 RtlUpperChar +803 RtlUpperString +804 RtlValidSecurityDescriptor +805 RtlValidSid +806 RtlWriteRegistryValue +807 RtlZeroHeap +808 RtlZeroMemory +809 RtlxAnsiStringToUnicodeSize +810 RtlxOemStringToUnicodeSize +811 RtlxUnicodeStringToAnsiSize +812 RtlxUnicodeStringToOemSize +813 SeAccessCheck +814 SeAppendPrivileges +815 SeAssignSecurity +816 SeAuditingFileEvents +817 SeAuditingFileOrGlobalEvents +818 SeCaptureSecurityDescriptor +819 SeCaptureSubjectContext +820 SeCloseObjectAuditAlarm +821 SeCreateAccessState +822 SeCreateClientSecurity +823 SeDeassignSecurity +824 SeDeleteAccessState +825 SeDeleteObjectAuditAlarm +826 SeExports +827 SeFreePrivileges +828 SeImpersonateClient +829 SeLockSubjectContext +830 sionForTerminationNotification +831 SeOpenObjectAuditAlarm +832 SeOpenObjectForDeleteAuditAlarm +833 SePrivilegeCheck +834 SePrivilegeObjectAuditAlarm +835 SePublicDefaultDacl +836 SeQueryAuthenticationIdToken +837 SeQuerySecurityDescriptorInfo +838 SeRegisterLogonSessionTerminatedRoutine +839 SeReleaseSecurityDescriptor +840 SeReleaseSubjectContext +841 SeSetAccessStateGenericMapping +842 SeSetSecurityDescriptorInfo +843 SeSinglePrivilegeCheck +844 SeSystemDefaultDacl +845 SeTokenImpersonationLevel +846 SeTokenType +847 SeUnlockSubjectContext +848 SeUnregisterLogonSessionTerminatedRoutine +849 SeValidSecurityDescriptor +850 WRITE_REGISTER_BUFFER_UCHAR +851 WRITE_REGISTER_BUFFER_ULONG +852 WRITE_REGISTER_BUFFER_USHORT +853 WRITE_REGISTER_UCHAR +854 WRITE_REGISTER_ULONG +855 WRITE_REGISTER_USHORT +856 ZwAccessCheckAndAuditAlarm +857 ZwAlertThread +858 ZwAllocateVirtualMemory +859 ZwClearEvent +860 ZwClose +861 ZwCloseObjectAuditAlarm +862 ZwConnectPort +863 ZwCreateDirectoryObject +864 ZwCreateEvent +865 ZwCreateFile +866 ZwCreateKey +867 ZwCreateSection +868 ZwCreateSymbolicLinkObject +869 ZwDeleteFile +870 ZwDeleteKey +871 ZwDeleteValueKey +872 ZwDeviceIoControlFile +873 ZwDisplayString +874 ZwDuplicateObject +875 ZwDuplicateToken +876 ZwEnumerateKey +877 ZwEnumerateValueKey +878 ZwFlushInstructionCache +879 ZwFlushKey +880 ZwFreeVirtualMemory +881 ZwFsControlFile +882 ZwLoadDriver +883 ZwLoadKey +884 ZwMakeTemporaryObject +885 ZwMapViewOfSection +886 ZwNotifyChangeKey +887 ZwOpenDirectoryObject +888 ZwOpenEvent +889 ZwOpenFile +890 ZwOpenKey +891 ZwOpenProcess +892 ZwOpenProcessToken +893 ZwOpenSection +894 ZwOpenSymbolicLinkObject +895 ZwOpenThread +896 ZwOpenThreadToken +897 ZwPulseEvent +898 ZwQueryDefaultLocale +899 ZwQueryDirectoryFile +900 ZwQueryInformationFile +901 ZwQueryInformationProcess +902 ZwQueryInformationToken +903 ZwQueryKey +904 ZwQueryObject +905 ZwQuerySection +906 ZwQuerySecurityObject +907 ZwQuerySymbolicLinkObject +908 ZwQuerySystemInformation +909 ZwQueryValueKey +910 ZwQueryVolumeInformationFile +911 ZwReadFile +912 ZwReplaceKey +913 ZwRequestWaitReplyPort +914 ZwResetEvent +915 ZwSaveKey +916 ZwSetDefaultLocale +917 ZwSetEvent +918 ZwSetInformationFile +919 ZwSetInformationObject +920 ZwSetInformationProcess +921 ZwSetInformationThread +922 ZwSetSystemInformation +923 ZwSetSystemTime +924 ZwSetValueKey +925 ZwTerminateProcess +926 ZwUnloadDriver +927 ZwUnloadKey +928 ZwUnmapViewOfSection +929 ZwWaitForMultipleObjects +930 ZwWaitForSingleObject +931 ZwWriteFile +932 ZwYieldExecution +933 _abnormal_termination +934 _alldiv +935 _allmul +936 _allrem +937 _allshl +938 _allshr +939 _aulldiv +940 _aullrem +941 _aullshr +942 _except_handler2 +943 _global_unwind2 +944 _itoa +945 _local_unwind2 +946 _purecall +947 _snprintf +948 _snwprintf +949 _stricmp +950 _strlwr +951 _strnicmp +952 _strnset +953 _strrev +954 _strset +955 _strupr +956 _vsnprintf +957 _wcsicmp +958 _wcslwr +959 _wcsnicmp +960 _wcsnset +961 _wcsrev +962 _wcsupr +963 atoi +964 atol +965 isdigit +966 islower +967 isprint +968 isspace +969 isupper +970 isxdigit +971 mbstowcs +972 mbtowc +973 memchr +974 memcpy +975 memmove +976 memset +977 qsort +978 rand +979 sprintf +980 srand +981 strcat +982 strchr +983 strcmp +984 strcpy +985 strlen +986 strncat +987 strncmp +988 strncpy +989 strrchr +990 strspn +991 strstr +992 swprintf +993 tolower +994 toupper +995 towlower +996 towupper +997 vsprintf +998 wcscat +999 wcschr +1000 wcscmp +1001 wcscpy +1002 wcscspn +1003 wcslen +1004 wcsncat +1005 wcsncmp +1006 wcsncpy +1007 wcsrchr +1008 wcsspn +1009 wcsstr +1010 wcstombs +1011 wctomb + + +Import Name: hal.dll + +Hint Exported +Value: Name: +003E KdPortSave +0046 KeRaiseIrqlToDpcLevel +0001 ExReleaseFastMutex +0000 ExAcquireFastMutex +0002 ExTryToAcquireFastMutex +0022 HalRequestSoftwareInterrupt +0023 HalReturnToFirmware +000E HalDisplayString +001E HalQueryRealTimeClock +0029 HalSetRealTimeClock +002A HalSetTimeIncrement +0042 KeGetCurrentIrql +0044 KeQueryPerformanceCounter +0016 HalGetEnvironmentVariable +0027 HalSetEnvironmentVariable +004C KfRaiseIrql +0019 HalInitSystem +0020 HalReportResourceUsage +0005 HalAllProcessorsStarted +0006 HalAllocateAdapterChannel +0017 HalGetInterruptVector +002F HalTranslateBusAddress +0004 HalAdjustResourceList +0030 IoAssignDriveLetters +0035 IoReadPartitionTable +0007 HalAllocateCommonBuffer +003A KdPortInitialize +0039 KdPortGetByte +003C KdPortPutByte +003B KdPortPollByte +004B KfLowerIrql +003D KdPortRestore +0052 READ_PORT_ULONG +0053 READ_PORT_USHORT +0051 READ_PORT_UCHAR +0058 WRITE_PORT_ULONG +0059 WRITE_PORT_USHORT +0057 WRITE_PORT_UCHAR +001A HalInitializeProcessor +001C HalProcessorIdle +000C HalClearSoftwareInterrupt +0047 KeRaiseIrqlToSynchLevel +0018 HalHandleNMI +000A HalBeginSystemInterrupt +0010 HalEndSystemInterrupt +000F HalEnableSystemInterrupt +000D HalDisableSystemInterrupt +002E HalSystemVectorDispatchEntry +0045 KeRaiseIrql +0043 KeLowerIrql +0028 HalSetProfileInterval +002C HalStartProfileInterrupt +002D HalStopProfileInterrupt +001D HalQueryDisplayParameters +004D KfReleaseSpinLock +004A KfAcquireSpinLock +0041 KeFlushWriteBuffer +0049 KeStallExecutionProcessor + +These exported and imported functions might only correspond to Windows NT 4.0 diff --git a/ntoskrnl/ob/.cvsignore b/ntoskrnl/ob/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/ob/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/ob/dirobj.c b/ntoskrnl/ob/dirobj.c new file mode 100644 index 0000000..15f3ca8 --- /dev/null +++ b/ntoskrnl/ob/dirobj.c @@ -0,0 +1,348 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/dirobj.c + * PURPOSE: Interface functions to directory object + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 22/05/98: Created + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS **************************************************************/ + + +/********************************************************************** + * NAME EXPORTED + * NtOpenDirectoryObject + * + * DESCRIPTION + * Opens a namespace directory object. + * + * ARGUMENTS + * DirectoryHandle (OUT) + * Variable which receives the directory handle. + * + * DesiredAccess + * Desired access to the directory. + * + * ObjectAttributes + * Structure describing the directory. + * + * RETURN VALUE + * Status. + * + * NOTES + * Undocumented. + */ +NTSTATUS STDCALL NtOpenDirectoryObject(PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + PVOID Object; + NTSTATUS Status; + + *DirectoryHandle = 0; + + Status = ObReferenceObjectByName(ObjectAttributes->ObjectName, + ObjectAttributes->Attributes, + NULL, + DesiredAccess, + ObDirectoryType, + UserMode, + NULL, + &Object); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + DirectoryHandle); + return STATUS_SUCCESS; +} + + +/********************************************************************** + * NAME EXPORTED + * NtQueryDirectoryObject + * + * DESCRIPTION + * Reads information from a directory in the system namespace. + * + * ARGUMENTS + * DirObjHandle + * Handle, obtained with NtOpenDirectoryObject(), which + * must grant DIRECTORY_QUERY access to the directory + * object. + * + * DirObjInformation (OUT) + * Buffer to hold the data read. + * + * BufferLength + * Size of the buffer in bytes. + * + * ReturnSingleEntry + * When TRUE, only 1 entry is written in DirObjInformation; + * otherwise as many as will fit in the buffer. + * + * RestartScan + * If TRUE start reading at index 0. + * If FALSE start reading at the index specified + * by object index *ObjectIndex. + * + * ObjectIndex + * Zero based index into the directory, interpretation + * depends on RestartScan. + * + * DataWritten (OUT) + * Caller supplied storage for the number of bytes + * written (or NULL). + * + * RETURN VALUE + * Status. + * + * REVISIONS + * 2001-05-01 (ea) + * Changed 4th, and 5th parameter names after + * G.Nebbett "WNT/W2k Native API Reference". + * Mostly rewritten. + */ +NTSTATUS STDCALL NtQueryDirectoryObject (IN HANDLE DirObjHandle, + OUT POBJDIR_INFORMATION + DirObjInformation, + IN ULONG BufferLength, + IN BOOLEAN ReturnSingleEntry, + IN BOOLEAN RestartScan, + IN OUT PULONG ObjectIndex, + OUT PULONG DataWritten OPTIONAL) +{ + PDIRECTORY_OBJECT dir = NULL; + PLIST_ENTRY current_entry = NULL; + POBJECT_HEADER current = NULL; + ULONG i = 0; + NTSTATUS Status = STATUS_SUCCESS; + DWORD DirectoryCount = 0; + DWORD DirectorySize = 0; + ULONG SpaceLeft = BufferLength; + ULONG SpaceRequired = 0; + ULONG NameLength = 0; + ULONG TypeNameLength = 0; + POBJDIR_INFORMATION current_odi = DirObjInformation; + PBYTE FirstFree = (PBYTE) DirObjInformation; + + + DPRINT("NtQueryDirectoryObject(DirObjHandle %x)\n", DirObjHandle); + + /* FIXME: if previous mode == user, use ProbeForWrite + * on user params. */ + + /* Reference the DIRECTORY_OBJECT */ + Status = ObReferenceObjectByHandle(DirObjHandle, + DIRECTORY_QUERY, + ObDirectoryType, + UserMode, + (PVOID*)&dir, + NULL); + if (!NT_SUCCESS(Status)) + { + return (Status); + } + /* Check ObjectIndex is not NULL */ + if (NULL == ObjectIndex) + { + return (STATUS_INVALID_PARAMETER); + } + /* + * Compute the number of directory entries + * and the size of the array (in bytes). + * One more entry marks the end of the array. + */ + if (FALSE == ReturnSingleEntry) + { + for ( current_entry = dir->head.Flink; + (current_entry != & dir->head); + current_entry = current_entry->Flink + ) + { + ++ DirectoryCount; + } + } + else + { + DirectoryCount = 1; + } + // count is DirectoryCount + one null entry + DirectorySize = (DirectoryCount + 1) * sizeof (OBJDIR_INFORMATION); + if (DirectorySize > SpaceLeft) + { + return (STATUS_BUFFER_TOO_SMALL); + } + /* + * Optionally, skip over some entries at the start of the directory + * (use *ObjectIndex value) + */ + current_entry = dir->head.Flink; + if (FALSE == RestartScan) + { + /* RestartScan == FALSE */ + register ULONG EntriesToSkip = *ObjectIndex; + + CHECKPOINT; + + for ( ; + ((EntriesToSkip --) && (current_entry != & dir->head)); + current_entry = current_entry->Flink + ); + if ((EntriesToSkip) && (current_entry == & dir->head)) + { + return (STATUS_NO_MORE_ENTRIES); + } + } + /* + * Initialize the array of OBJDIR_INFORMATION. + */ + RtlZeroMemory (FirstFree, DirectorySize); + /* + * Move FirstFree to point to the Unicode strings area + */ + FirstFree += DirectorySize; + /* + * Compute how much space is left after allocating the + * array in the user buffer. + */ + SpaceLeft -= DirectorySize; + /* Scan the directory */ + do + { + /* + * Check if we reached the end of the directory. + */ + if (current_entry == & dir->head) + { + /* Any data? */ + if (i) break; /* DONE */ + /* FIXME: better error handling here! */ + return (STATUS_NO_MORE_ENTRIES); + } + /* + * Compute the current OBJECT_HEADER memory + * object's address. + */ + current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry); + /* + * Compute the space required in the user buffer to copy + * the data from the current object: + * + * Name (WCHAR) 0 TypeName (WCHAR) 0 + */ + NameLength = (wcslen (current->Name.Buffer) * sizeof (WCHAR)); + TypeNameLength = (wcslen (current->ObjectType->TypeName.Buffer) * sizeof (WCHAR)); + SpaceRequired = (NameLength + 1) * sizeof (WCHAR) + + (TypeNameLength + 1) * sizeof (WCHAR); + /* + * Check for free space in the user buffer. + */ + if (SpaceRequired > SpaceLeft) + { + return (STATUS_BUFFER_TOO_SMALL); + } + /* + * Copy the current directory entry's data into the buffer + * and update the OBJDIR_INFORMATION entry in the array. + */ + /* --- Object's name --- */ + current_odi->ObjectName.Length = NameLength; + current_odi->ObjectName.MaximumLength = (NameLength + sizeof (WCHAR)); + current_odi->ObjectName.Buffer = (PWCHAR) FirstFree; + wcscpy ((PWCHAR) FirstFree, current->Name.Buffer); + FirstFree += (current_odi->ObjectName.MaximumLength); + /* --- Object type's name --- */ + current_odi->ObjectTypeName.Length = TypeNameLength; + current_odi->ObjectTypeName.MaximumLength = (TypeNameLength + sizeof (WCHAR)); + current_odi->ObjectTypeName.Buffer = (PWCHAR) FirstFree; + wcscpy ((PWCHAR) FirstFree, current->ObjectType->TypeName.Buffer); + FirstFree += (current_odi->ObjectTypeName.MaximumLength); + /* Next entry in the array */ + ++ current_odi; + /* Decrease the space left count */ + SpaceLeft -= SpaceRequired; + /* Increase the object index number */ + ++ i; + /* Next object in the directory */ + current_entry = current_entry->Flink; + + } while (FALSE == ReturnSingleEntry); + /* + * Store current index in ObjectIndex + */ + *ObjectIndex += DirectoryCount; + /* + * Report to the caller how much bytes + * we wrote in the user buffer. + */ + if (NULL != DataWritten) + { + *DataWritten = (BufferLength - SpaceLeft); + } + return (STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME (EXPORTED as Zw) + * NtCreateDirectoryObject + * + * DESCRIPTION + * Creates or opens a directory object (a container for other + * objects). + * + * ARGUMENTS + * DirectoryHandle (OUT) + * Caller supplied storage for the handle of the + * directory. + * + * DesiredAccess + * Access desired to the directory. + * + * ObjectAttributes + * Object attributes initialized with + * InitializeObjectAttributes. + * + * RETURN VALUE + * Status. + */ +NTSTATUS STDCALL +NtCreateDirectoryObject(PHANDLE DirectoryHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + PDIRECTORY_OBJECT dir; + + DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, " + "DesiredAccess %x, ObjectAttributes %x, " + "ObjectAttributes->ObjectName %S)\n", + DirectoryHandle, DesiredAccess, ObjectAttributes, + ObjectAttributes->ObjectName); + + return(ObCreateObject(DirectoryHandle, + DesiredAccess, + ObjectAttributes, + ObDirectoryType, + (PVOID*)&dir)); +} + +/* EOF */ diff --git a/ntoskrnl/ob/handle.c b/ntoskrnl/ob/handle.c new file mode 100644 index 0000000..8d3b679 --- /dev/null +++ b/ntoskrnl/ob/handle.c @@ -0,0 +1,749 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/handle.c + * PURPOSE: Managing handles + * PROGRAMMER: David Welch (welch@cwcom.net) + * REVISION HISTORY: + * 17/06/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +/* + * PURPOSE: Defines a handle + */ +typedef struct +{ + PVOID ObjectBody; + ACCESS_MASK GrantedAccess; + BOOLEAN Inherit; +} HANDLE_REP, *PHANDLE_REP; + +#define HANDLE_BLOCK_ENTRIES ((PAGE_SIZE-sizeof(LIST_ENTRY))/sizeof(HANDLE_REP)) + + +/* + * PURPOSE: Defines a page's worth of handles + */ +typedef struct +{ + LIST_ENTRY entry; + HANDLE_REP handles[HANDLE_BLOCK_ENTRIES]; +} HANDLE_BLOCK, *PHANDLE_BLOCK; + + +/* GLOBALS *******************************************************************/ + +#define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L') + +/* FUNCTIONS ***************************************************************/ + + +static PHANDLE_REP ObpGetObjectByHandle(PHANDLE_TABLE HandleTable, HANDLE h) +/* + * FUNCTION: Get the data structure for a handle + * ARGUMENTS: + * Process = Process to get the handle for + * h = Handle + * ARGUMENTS: A pointer to the information about the handle on success, + * NULL on failure + */ +{ + PLIST_ENTRY current; + unsigned int handle = (((unsigned int)h) >> 2) - 1; + unsigned int count=handle/HANDLE_BLOCK_ENTRIES; + HANDLE_BLOCK* blk = NULL; + unsigned int i; + + DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable,h); + + current = HandleTable->ListHead.Flink; + DPRINT("current %x\n",current); + + for (i=0;iFlink; + if (current == (&(HandleTable->ListHead))) + { + return(NULL); + } + } + + blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry); + DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES])); + return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES])); +} + +NTSTATUS +ObDuplicateObject(PEPROCESS SourceProcess, + PEPROCESS TargetProcess, + HANDLE SourceHandle, + PHANDLE TargetHandle, + ACCESS_MASK DesiredAccess, + BOOLEAN InheritHandle, + ULONG Options) +{ + KIRQL oldIrql; + PHANDLE_REP SourceHandleRep; + PVOID ObjectBody; + + KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql); + SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable, + SourceHandle); + if (SourceHandleRep == NULL) + { + KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); + return(STATUS_INVALID_HANDLE); + } + ObjectBody = SourceHandleRep->ObjectBody; + ObReferenceObjectByPointer(ObjectBody, + 0, + NULL, + UserMode); + + if (Options & DUPLICATE_SAME_ACCESS) + { + DesiredAccess = SourceHandleRep->GrantedAccess; + } + + KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); + ObCreateHandle(TargetProcess, + ObjectBody, + DesiredAccess, + InheritHandle, + TargetHandle); + + if (Options & DUPLICATE_CLOSE_SOURCE) + { + ZwClose(SourceHandle); + } + + ObDereferenceObject(ObjectBody); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtDuplicateObject (IN HANDLE SourceProcessHandle, + IN HANDLE SourceHandle, + IN HANDLE TargetProcessHandle, + OUT PHANDLE UnsafeTargetHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN InheritHandle, + ULONG Options) +/* + * FUNCTION: Copies a handle from one process space to another + * ARGUMENTS: + * SourceProcessHandle = The source process owning the handle. The + * source process should have opened + * the SourceHandle with PROCESS_DUP_HANDLE + * access. + * SourceHandle = The handle to the object. + * TargetProcessHandle = The destination process owning the handle + * TargetHandle (OUT) = Caller should supply storage for the + * duplicated handle. + * DesiredAccess = The desired access to the handle. + * InheritHandle = Indicates wheter the new handle will be inheritable + * or not. + * Options = Specifies special actions upon duplicating the handle. + * Can be one of the values DUPLICATE_CLOSE_SOURCE | + * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies + * that the source handle should be closed after duplicating. + * DUPLICATE_SAME_ACCESS specifies to ignore the + * DesiredAccess paramter and just grant the same access to + * the new handle. + * RETURNS: Status + * REMARKS: This function maps to the win32 DuplicateHandle. + */ +{ + PEPROCESS SourceProcess; + PEPROCESS TargetProcess; + PHANDLE_REP SourceHandleRep; + KIRQL oldIrql; + PVOID ObjectBody; + HANDLE TargetHandle; + NTSTATUS Status; + + ASSERT_IRQL(PASSIVE_LEVEL); + + Status = ObReferenceObjectByHandle(SourceProcessHandle, + PROCESS_DUP_HANDLE, + NULL, + UserMode, + (PVOID*)&SourceProcess, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Status = ObReferenceObjectByHandle(TargetProcessHandle, + PROCESS_DUP_HANDLE, + NULL, + UserMode, + (PVOID*)&TargetProcess, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(SourceProcess); + return(Status); + } + KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql); + SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable, + SourceHandle); + if (SourceHandleRep == NULL) + { + KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); + ObDereferenceObject(SourceProcess); + ObDereferenceObject(TargetProcess); + return(STATUS_INVALID_HANDLE); + } + ObjectBody = SourceHandleRep->ObjectBody; + ObReferenceObjectByPointer(ObjectBody, + 0, + NULL, + UserMode); + + if (Options & DUPLICATE_SAME_ACCESS) + { + DesiredAccess = SourceHandleRep->GrantedAccess; + } + + KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql); + if (!SourceHandleRep->Inherit) + { + ObDereferenceObject(TargetProcess); + ObDereferenceObject(SourceProcess); + ObDereferenceObject(ObjectBody); + return STATUS_INVALID_HANDLE; + } + ObCreateHandle(TargetProcess, + ObjectBody, + DesiredAccess, + InheritHandle, + &TargetHandle); + + if (Options & DUPLICATE_CLOSE_SOURCE) + { + ZwClose(SourceHandle); + } + + ObDereferenceObject(TargetProcess); + ObDereferenceObject(SourceProcess); + ObDereferenceObject(ObjectBody); + + Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + return(STATUS_SUCCESS); +} + +VOID ObCloseAllHandles(PEPROCESS Process) +{ + KIRQL oldIrql; + PHANDLE_TABLE HandleTable; + PLIST_ENTRY current_entry; + PHANDLE_BLOCK current; + ULONG i; + PVOID ObjectBody; + + DPRINT("ObCloseAllHandles(Process %x)\n", Process); + + HandleTable = &Process->HandleTable; + + KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql); + + current_entry = HandleTable->ListHead.Flink; + + while (current_entry != &HandleTable->ListHead) + { + current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry); + + for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) + { + ObjectBody = current->handles[i].ObjectBody; + + if (ObjectBody != NULL) + { + POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody); + + if (Header->ObjectType == PsProcessType || + Header->ObjectType == PsThreadType) + { + DPRINT("Deleting handle to %x\n", ObjectBody); + } + + ObReferenceObjectByPointer(ObjectBody, + 0, + NULL, + UserMode); + InterlockedDecrement(&Header->HandleCount); + current->handles[i].ObjectBody = NULL; + + KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); + KeDetachProcess(); + + if ((Header->ObjectType != NULL) && + (Header->ObjectType->Close != NULL)) + { + Header->ObjectType->Close(ObjectBody, + Header->HandleCount); + } + + ObDereferenceObject(ObjectBody); + KeAttachProcess(Process); + KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql); + current_entry = &HandleTable->ListHead; + break; + } + } + + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); + DPRINT("ObCloseAllHandles() finished\n"); + DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType); +} + +VOID ObDeleteHandleTable(PEPROCESS Process) +/* + * FUNCTION: Deletes the handle table associated with a process + */ +{ + PLIST_ENTRY current = NULL; + PHANDLE_TABLE HandleTable = NULL; + + ObCloseAllHandles(Process); + + HandleTable = &Process->HandleTable; + current = RemoveHeadList(&HandleTable->ListHead); + + while (current != &HandleTable->ListHead) + { + HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current, + HANDLE_BLOCK, + entry); + DPRINT("Freeing %x\n", HandleBlock); + ExFreePool(HandleBlock); + + current = RemoveHeadList(&HandleTable->ListHead); + } +} + + +VOID ObCreateHandleTable(PEPROCESS Parent, + BOOLEAN Inherit, + PEPROCESS Process) +/* + * FUNCTION: Creates a handle table for a process + * ARGUMENTS: + * Parent = Parent process (or NULL if this is the first process) + * Inherit = True if the process should inherit its parent's handles + * Process = Process whose handle table is to be created + */ +{ + PHANDLE_TABLE ParentHandleTable, HandleTable; + KIRQL oldIrql; + PLIST_ENTRY parent_current; + ULONG i; + PHANDLE_BLOCK current_block, new_block; + + DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n", + Parent,Inherit,Process); + + InitializeListHead(&(Process->HandleTable.ListHead)); + KeInitializeSpinLock(&(Process->HandleTable.ListLock)); + + if (Parent != NULL) + { + ParentHandleTable = &Parent->HandleTable; + HandleTable = &Process->HandleTable; + + KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql); + KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock); + + parent_current = ParentHandleTable->ListHead.Flink; + + while (parent_current != &ParentHandleTable->ListHead) + { + current_block = CONTAINING_RECORD(parent_current, + HANDLE_BLOCK, + entry); + new_block = ExAllocatePoolWithTag(NonPagedPool, + sizeof(HANDLE_BLOCK), + TAG_HANDLE_TABLE); + if (new_block == NULL) + { + break; + } + RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK)); + + for (i=0; ihandles[i].ObjectBody) + { + if (current_block->handles[i].Inherit && Inherit) + { + new_block->handles[i].ObjectBody = + current_block->handles[i].ObjectBody; + new_block->handles[i].GrantedAccess = + current_block->handles[i].GrantedAccess; + new_block->handles[i].Inherit = TRUE; + InterlockedIncrement(&(BODY_TO_HEADER(current_block->handles[i].ObjectBody)->HandleCount)); + } + } + } + InsertTailList(&Process->HandleTable.ListHead, &new_block->entry); + parent_current = parent_current->Flink; + } + KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock); + KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql); + } +} + + +PVOID ObDeleteHandle(PEPROCESS Process, HANDLE Handle) +{ + PHANDLE_REP Rep; + PVOID ObjectBody; + KIRQL oldIrql; + PHANDLE_TABLE HandleTable; + POBJECT_HEADER Header; + + DPRINT("ObDeleteHandle(Handle %x)\n",Handle); + + HandleTable = &Process->HandleTable; + + KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql); + + Rep = ObpGetObjectByHandle(HandleTable, Handle); + if (Rep == NULL) + { + KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); + return(NULL); + } + + ObjectBody = Rep->ObjectBody; + DPRINT("ObjectBody %x\n", ObjectBody); + if (ObjectBody != NULL) + { + Header = BODY_TO_HEADER(ObjectBody); + InterlockedDecrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount)); + ObReferenceObjectByPointer(ObjectBody, + 0, + NULL, + UserMode); + Rep->ObjectBody = NULL; + + KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); + + if ((Header->ObjectType != NULL) && + (Header->ObjectType->Close != NULL)) + { + Header->ObjectType->Close(ObjectBody, Header->HandleCount); + } + } + else + { + KeReleaseSpinLock(&HandleTable->ListLock, oldIrql); + } + + DPRINT("Finished ObDeleteHandle()\n"); + return(ObjectBody); +} + + +NTSTATUS ObCreateHandle(PEPROCESS Process, + PVOID ObjectBody, + ACCESS_MASK GrantedAccess, + BOOLEAN Inherit, + PHANDLE HandleReturn) +/* + * FUNCTION: Add a handle referencing an object + * ARGUMENTS: + * obj = Object body that the handle should refer to + * RETURNS: The created handle + * NOTE: The handle is valid only in the context of the current process + */ +{ + LIST_ENTRY* current; + unsigned int handle=1; + unsigned int i; + HANDLE_BLOCK* new_blk = NULL; + PHANDLE_TABLE HandleTable; + KIRQL oldlvl; + + DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody); + + assert(Process); + + if (ObjectBody != NULL) + { + InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount)); + } + HandleTable = &Process->HandleTable; + KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl); + current = HandleTable->ListHead.Flink; + /* + * Scan through the currently allocated handle blocks looking for a free + * slot + */ + while (current != (&HandleTable->ListHead)) + { + HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry); + + DPRINT("Current %x\n",current); + + for (i=0;ihandles[i]); + if (blk->handles[i].ObjectBody==NULL) + { + blk->handles[i].ObjectBody = ObjectBody; + blk->handles[i].GrantedAccess = GrantedAccess; + blk->handles[i].Inherit = Inherit; + KeReleaseSpinLock(&HandleTable->ListLock, oldlvl); + *HandleReturn = (HANDLE)((handle + i) << 2); + return(STATUS_SUCCESS); + } + } + + handle = handle + HANDLE_BLOCK_ENTRIES; + current = current->Flink; + } + + /* + * Add a new handle block to the end of the list + */ + new_blk = + (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK), + TAG_HANDLE_TABLE); + if (!new_blk) + { + *HandleReturn = (PHANDLE)NULL; + return(STATUS_INSUFFICIENT_RESOURCES); + } + RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK)); + InsertTailList(&(Process->HandleTable.ListHead), + &new_blk->entry); + new_blk->handles[0].ObjectBody = ObjectBody; + new_blk->handles[0].GrantedAccess = GrantedAccess; + new_blk->handles[0].Inherit = Inherit; + KeReleaseSpinLock(&HandleTable->ListLock, oldlvl); + *HandleReturn = (HANDLE)(handle << 2); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID* Object, + POBJECT_HANDLE_INFORMATION HandleInformationPtr) +/* + * FUNCTION: Increments the reference count for an object and returns a + * pointer to its body + * ARGUMENTS: + * Handle = Handle for the object + * DesiredAccess = Desired access to the object + * ObjectType + * AccessMode + * Object (OUT) = Points to the object body on return + * HandleInformation (OUT) = Contains information about the handle + * on return + * RETURNS: Status + */ +{ + PHANDLE_REP HandleRep; + POBJECT_HEADER ObjectHeader; + KIRQL oldIrql; + PVOID ObjectBody; + ACCESS_MASK GrantedAccess; + + ASSERT_IRQL(PASSIVE_LEVEL); + + DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, " + "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess, + ObjectType,AccessMode,Object); + + + /* + * Handle special handle names + */ + if (Handle == NtCurrentProcess() && + (ObjectType == PsProcessType || ObjectType == NULL)) + { + DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]); + + ObReferenceObjectByPointer(PsGetCurrentProcess(), + PROCESS_ALL_ACCESS, + PsProcessType, + UserMode); + *Object = PsGetCurrentProcess(); + DPRINT("Referencing current process %x\n", PsGetCurrentProcess()); + return(STATUS_SUCCESS); + } + else if (Handle == NtCurrentProcess()) + { + CHECKPOINT; + return(STATUS_OBJECT_TYPE_MISMATCH); + } + if (Handle == NtCurrentThread() && + (ObjectType == PsThreadType || ObjectType == NULL)) + { + ObReferenceObjectByPointer(PsGetCurrentThread(), + THREAD_ALL_ACCESS, + PsThreadType, + UserMode); + *Object = PsGetCurrentThread(); + CHECKPOINT; + return(STATUS_SUCCESS); + } + else if (Handle == NtCurrentThread()) + { + CHECKPOINT; + return(STATUS_OBJECT_TYPE_MISMATCH); + } + + KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock, + &oldIrql); + HandleRep = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable, + Handle); + if (HandleRep == NULL || HandleRep->ObjectBody == NULL) + { + KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock, + oldIrql); + return(STATUS_INVALID_HANDLE); + } + ObjectBody = HandleRep->ObjectBody; + DPRINT("ObjectBody %p\n",ObjectBody); + ObjectHeader = BODY_TO_HEADER(ObjectBody); + DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount); + ObReferenceObjectByPointer(ObjectBody, + 0, + NULL, + UserMode); + GrantedAccess = HandleRep->GrantedAccess; + KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock, + oldIrql); + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount); + + if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType) + { + CHECKPOINT; + return(STATUS_OBJECT_TYPE_MISMATCH); + } + + if (ObjectHeader->ObjectType == PsProcessType) + { + DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]); + } + + if (AccessMode == UserMode) + { + RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping); + + if (!(GrantedAccess & DesiredAccess) && + !((~GrantedAccess) & DesiredAccess)) + { + CHECKPOINT; + return(STATUS_ACCESS_DENIED); + } + } + + *Object = ObjectBody; + + CHECKPOINT; + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * NtClose + * + * DESCRIPTION + * Closes a handle reference to an object. + * + * ARGUMENTS + * Handle + * Handle to close. + * + * RETURN VALUE + * Status. + */ +NTSTATUS STDCALL NtClose(HANDLE Handle) +{ + PVOID ObjectBody; + POBJECT_HEADER Header; + + assert_irql(PASSIVE_LEVEL); + + DPRINT("NtClose(Handle %x)\n",Handle); + + ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle); + if (ObjectBody == NULL) + { + return(STATUS_INVALID_HANDLE); + } + + Header = BODY_TO_HEADER(ObjectBody); + + DPRINT("Dereferencing %x\n", ObjectBody); + ObDereferenceObject(ObjectBody); + + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +ObInsertObject(PVOID Object, + PACCESS_STATE PassedAccessState, + ACCESS_MASK DesiredAccess, + ULONG AdditionalReferences, + PVOID* ReferencedObject, + PHANDLE Handle) +{ + return(ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + Handle)); +} + +/* EOF */ diff --git a/ntoskrnl/ob/namespc.c b/ntoskrnl/ob/namespc.c new file mode 100644 index 0000000..de66216 --- /dev/null +++ b/ntoskrnl/ob/namespc.c @@ -0,0 +1,445 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/namespc.c + * PURPOSE: Manages the system namespace + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 22/05/98: Created + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ****************************************************************/ + +POBJECT_TYPE ObDirectoryType = NULL; +POBJECT_TYPE ObTypeObjectType = NULL; + +PDIRECTORY_OBJECT NameSpaceRoot = NULL; + +static GENERIC_MAPPING ObpDirectoryMapping = { + STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE, + STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY, + STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE, + DIRECTORY_ALL_ACCESS}; + +static GENERIC_MAPPING ObpTypeMapping = { + STANDARD_RIGHTS_READ, + STANDARD_RIGHTS_WRITE, + STANDARD_RIGHTS_EXECUTE, + 0x000F0001}; + +/* FUNCTIONS **************************************************************/ + +NTSTATUS STDCALL +ObReferenceObjectByName(PUNICODE_STRING ObjectPath, + ULONG Attributes, + PACCESS_STATE PassedAccessState, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID ParseContext, + PVOID* ObjectPtr) +{ + PVOID Object = NULL; + UNICODE_STRING RemainingPath; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, + ObjectPath, + Attributes, + NULL, + NULL); + Status = ObFindObject(&ObjectAttributes, + &Object, + &RemainingPath, + ObjectType); + if (!NT_SUCCESS(Status)) + { + return(Status); + } +CHECKPOINT; +DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object); + + if (RemainingPath.Buffer != NULL || Object == NULL) + { +CHECKPOINT; +DPRINT("Object %p\n", Object); + *ObjectPtr = NULL; + RtlFreeUnicodeString (&RemainingPath); + return(STATUS_UNSUCCESSFUL); + } + *ObjectPtr = Object; + RtlFreeUnicodeString (&RemainingPath); + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * ObOpenObjectByName + * + * DESCRIPTION + * Obtain a handle to an existing object. + * + * ARGUMENTS + * ObjectAttributes + * ... + * ObjectType + * ... + * ParseContext + * ... + * AccessMode + * ... + * DesiredAccess + * ... + * PassedAccessState + * ... + * Handle + * Handle to close. + * + * RETURN VALUE + * Status. + */ +NTSTATUS STDCALL +ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, + IN POBJECT_TYPE ObjectType, + IN OUT PVOID ParseContext, + IN KPROCESSOR_MODE AccessMode, + IN ACCESS_MASK DesiredAccess, + IN PACCESS_STATE PassedAccessState, + OUT PHANDLE Handle) +{ + UNICODE_STRING RemainingPath; + PVOID Object = NULL; + NTSTATUS Status; + + DPRINT("ObOpenObjectByName()\n"); + + Status = ObFindObject(ObjectAttributes, + &Object, + &RemainingPath, + ObjectType); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + if (RemainingPath.Buffer != NULL || + Object == NULL) + { + RtlFreeUnicodeString(&RemainingPath); + return STATUS_UNSUCCESSFUL; + } + + Status = ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + FALSE, + Handle); + + ObDereferenceObject(Object); + RtlFreeUnicodeString(&RemainingPath); + + return Status; +} + + +VOID +ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, + POBJECT_HEADER Header, + PWSTR Name) +/* + * FUNCTION: Add an entry to a namespace directory + * ARGUMENTS: + * Parent = directory to add in + * Header = Header of the object to add the entry for + * Name = Name to give the entry + */ +{ + KIRQL oldlvl; + + RtlCreateUnicodeString(&Header->Name, Name); + Header->Parent = Parent; + + KeAcquireSpinLock(&Parent->Lock, &oldlvl); + InsertTailList(&Parent->head, &Header->Entry); + KeReleaseSpinLock(&Parent->Lock, oldlvl); +} + +VOID +ObpRemoveEntryDirectory(POBJECT_HEADER Header) +/* + * FUNCTION: Remove an entry from a namespace directory + * ARGUMENTS: + * Header = Header of the object to remove + */ +{ + KIRQL oldlvl; + + DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header); + + KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl); + RemoveEntryList(&(Header->Entry)); + KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl); +} + +PVOID +ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject, + PWSTR Name, + ULONG Attributes) +{ + PLIST_ENTRY current = DirectoryObject->head.Flink; + POBJECT_HEADER current_obj; + + DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name); + + if (Name[0]==0) + { + return(DirectoryObject); + } + if (Name[0]=='.' && Name[1]==0) + { + return(DirectoryObject); + } + if (Name[0]=='.' && Name[1]=='.' && Name[2]==0) + { + return(BODY_TO_HEADER(DirectoryObject)->Parent); + } + while (current!=(&(DirectoryObject->head))) + { + current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry); + DPRINT("Scanning %S %S\n",current_obj->Name.Buffer, Name); + if (Attributes & OBJ_CASE_INSENSITIVE) + { + if (_wcsicmp(current_obj->Name.Buffer, Name)==0) + { + DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj)); + return(HEADER_TO_BODY(current_obj)); + } + } + else + { + if ( wcscmp(current_obj->Name.Buffer, Name)==0) + { + DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj)); + return(HEADER_TO_BODY(current_obj)); + } + } + current = current->Flink; + } + DPRINT("%s() = NULL\n",__FUNCTION__); + return(NULL); +} + +NTSTATUS STDCALL +ObpParseDirectory(PVOID Object, + PVOID * NextObject, + PUNICODE_STRING FullPath, + PWSTR * Path, + ULONG Attributes) +{ + PWSTR end; + PVOID FoundObject; + + DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n", + Object,Path,*Path); + + *NextObject = NULL; + + if ((*Path) == NULL) + { + return STATUS_UNSUCCESSFUL; + } + + end = wcschr((*Path)+1, '\\'); + if (end != NULL) + { + *end = 0; + } + + FoundObject = ObpFindEntryDirectory(Object, (*Path)+1, Attributes); + + if (FoundObject == NULL) + { + if (end != NULL) + { + *end = '\\'; + } + return STATUS_UNSUCCESSFUL; + } + + ObReferenceObjectByPointer(FoundObject, + STANDARD_RIGHTS_REQUIRED, + NULL, + UserMode); + + if (end != NULL) + { + *end = '\\'; + *Path = end; + } + else + { + *Path = NULL; + } + + *NextObject = FoundObject; + + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL +ObpCreateDirectory(PVOID ObjectBody, + PVOID Parent, + PWSTR RemainingPath, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody; + + DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n", + ObjectBody, Parent, RemainingPath); + + if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL) + { + return(STATUS_UNSUCCESSFUL); + } + + InitializeListHead(&DirectoryObject->head); + KeInitializeSpinLock(&DirectoryObject->Lock); + + return(STATUS_SUCCESS); +} + + +VOID +ObInit(VOID) +/* + * FUNCTION: Initialize the object manager namespace + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING Name; + + /* create 'directory' object type */ + ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T'); + ObDirectoryType->TotalObjects = 0; + ObDirectoryType->TotalHandles = 0; + ObDirectoryType->MaxObjects = ULONG_MAX; + ObDirectoryType->MaxHandles = ULONG_MAX; + ObDirectoryType->PagedPoolCharge = 0; + ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT); + ObDirectoryType->Mapping = &ObpDirectoryMapping; + ObDirectoryType->Dump = NULL; + ObDirectoryType->Open = NULL; + ObDirectoryType->Close = NULL; + ObDirectoryType->Delete = NULL; + ObDirectoryType->Parse = ObpParseDirectory; + ObDirectoryType->Security = NULL; + ObDirectoryType->QueryName = NULL; + ObDirectoryType->OkayToClose = NULL; + ObDirectoryType->Create = ObpCreateDirectory; + ObDirectoryType->DuplicationNotify = NULL; + + RtlInitUnicodeStringFromLiteral(&ObDirectoryType->TypeName, + L"Directory"); + + /* create 'type' object type*/ + ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T'); + ObTypeObjectType->TotalObjects = 0; + ObTypeObjectType->TotalHandles = 0; + ObTypeObjectType->MaxObjects = ULONG_MAX; + ObTypeObjectType->MaxHandles = ULONG_MAX; + ObTypeObjectType->PagedPoolCharge = 0; + ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT); + ObTypeObjectType->Mapping = &ObpTypeMapping; + ObTypeObjectType->Dump = NULL; + ObTypeObjectType->Open = NULL; + ObTypeObjectType->Close = NULL; + ObTypeObjectType->Delete = NULL; + ObTypeObjectType->Parse = NULL; + ObTypeObjectType->Security = NULL; + ObTypeObjectType->QueryName = NULL; + ObTypeObjectType->OkayToClose = NULL; + ObTypeObjectType->Create = NULL; + ObTypeObjectType->DuplicationNotify = NULL; + + RtlInitUnicodeStringFromLiteral(&ObTypeObjectType->TypeName, + L"ObjectType"); + + /* create root directory */ + ObCreateObject(NULL, + STANDARD_RIGHTS_REQUIRED, + NULL, + ObDirectoryType, + (PVOID*)&NameSpaceRoot); + + /* create '\ObjectTypes' directory */ + RtlInitUnicodeStringFromLiteral(&Name, + L"\\ObjectTypes"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_PERMANENT, + NULL, + NULL); + ObCreateObject(NULL, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + ObDirectoryType, + NULL); + + ObpCreateTypeObject(ObDirectoryType); + ObpCreateTypeObject(ObTypeObjectType); +} + + +NTSTATUS +ObpCreateTypeObject(POBJECT_TYPE ObjectType) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + WCHAR NameString[120]; + PTYPE_OBJECT TypeObject = NULL; + UNICODE_STRING Name; + NTSTATUS Status; + + DPRINT("ObjectType: %wZ\n", &ObjectType->TypeName); + wcscpy(NameString, L"\\ObjectTypes\\"); + wcscat(NameString, ObjectType->TypeName.Buffer); + RtlInitUnicodeString(&Name, + NameString); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_PERMANENT, + NULL, + NULL); + Status = ObCreateObject(NULL, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + ObTypeObjectType, + (PVOID*)&TypeObject); + if (NT_SUCCESS(Status)) + { + TypeObject->ObjectType = ObjectType; + } + + return(STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/ntoskrnl/ob/ntobj.c b/ntoskrnl/ob/ntobj.c new file mode 100644 index 0000000..dc71229 --- /dev/null +++ b/ntoskrnl/ob/ntobj.c @@ -0,0 +1,220 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/ntobj.c + * PURPOSE: User mode interface to object manager + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 10/06/98: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ************************************************************/ + +NTSTATUS +STDCALL +NtSetInformationObject ( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + IN PVOID ObjectInformation, + IN ULONG Length + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +internalNameBuilder +( +POBJECT_HEADER ObjectHeader, +PUNICODE_STRING string) +/* So, what's the purpose of this function? + It will take any OBJECT_HEADER and traverse the Parent structure up to the root + and form the name, i.e. this will only work on objects where the Parent/Name fields + have any meaning (not files) */ +{ + NTSTATUS status; + if (ObjectHeader->Parent) + { + status = internalNameBuilder(BODY_TO_HEADER(ObjectHeader->Parent),string); + if (status != STATUS_SUCCESS) + { + return status; + } + } + if (ObjectHeader->Name.Buffer) + { + status = RtlAppendUnicodeToString(string, L"\\"); + if (status != STATUS_SUCCESS) return status; + return RtlAppendUnicodeStringToString(string, &ObjectHeader->Name); + } + return STATUS_SUCCESS; +} + +NTSTATUS +STDCALL +NtQueryObject ( + IN HANDLE ObjectHandle, + IN CINT ObjectInformationClass, + OUT PVOID ObjectInformation, + IN ULONG Length, + OUT PULONG ResultLength + ) +/*Very, very, very new implementation. Test it! + + Probably we should add meaning to QueryName in POBJECT_TYPE, no matter if we know + the correct parameters or not. For FILE_OBJECTs, it would probably look like the code + for ObjectNameInformation below. You give it a POBJECT and a PUNICODE_STRING, and it + returns the full path in the PUNICODE_STRING + + If we don't do it this way, we should anyway add switches and separate functions to handle + the different object types*/ +{ + POBJECT_NAME_INFORMATION nameinfo; + POBJECT_TYPE_INFORMATION typeinfo; + PFILE_NAME_INFORMATION filenameinfo; + PVOID Object; + NTSTATUS Status; + POBJECT_HEADER ObjectHeader; + PFILE_OBJECT fileob; + + Status = ObReferenceObjectByHandle(ObjectHandle, + 0, + NULL, + KernelMode, + &Object, + NULL); + if (Status != STATUS_SUCCESS) + { + return Status; + } + + ObjectHeader = BODY_TO_HEADER(Object); + + switch (ObjectInformationClass) + { + case ObjectNameInformation: + if (Length!=sizeof(OBJECT_NAME_INFORMATION)) return STATUS_INVALID_BUFFER_SIZE; + nameinfo = (POBJECT_NAME_INFORMATION)ObjectInformation; + (*ResultLength)=Length; + + if (ObjectHeader->Type==InternalFileType) // FIXME: Temporary QueryName implementation, or at least separate functions + { + fileob = (PFILE_OBJECT) Object; + Status = internalNameBuilder(BODY_TO_HEADER(fileob->DeviceObject->Vpb->RealDevice), &nameinfo->Name); + + if (Status != STATUS_SUCCESS) + { + ObDereferenceObject(Object); + return Status; + } + filenameinfo = ExAllocatePool(NonPagedPool,MAX_PATH*sizeof(WCHAR)+sizeof(ULONG)); + IoQueryFileInformation(fileob,FileNameInformation,MAX_PATH*sizeof(WCHAR)+sizeof(ULONG), filenameinfo,NULL); + + Status = RtlAppendUnicodeToString(&(nameinfo->Name), filenameinfo->FileName); + + ExFreePool( filenameinfo); + ObDereferenceObject(Object); + return Status; + } + else + if (ObjectHeader->Name.Buffer) // If it's got a name there, we can probably just make the full path through Name and Parent + { + Status = internalNameBuilder(ObjectHeader, &nameinfo->Name); + ObDereferenceObject(Object); + return Status; + } + ObDereferenceObject(Object); + return STATUS_NOT_IMPLEMENTED; + case ObjectTypeInformation: + typeinfo = (POBJECT_TYPE_INFORMATION)ObjectInformation; + if (Length!=sizeof(OBJECT_TYPE_INFORMATION)) return STATUS_INVALID_BUFFER_SIZE; + + // FIXME: Is this supposed to only be the header's Name field? + // Can somebody check/verify this? + RtlCopyUnicodeString(&typeinfo->Name,&ObjectHeader->Name); + + if (Status != STATUS_SUCCESS) + { + ObDereferenceObject(Object); + return Status; + } + + RtlCopyUnicodeString(&typeinfo->Type,&ObjectHeader->ObjectType->TypeName); + //This should be info from the object header, not the object type, right? + typeinfo->TotalHandles = ObjectHeader-> HandleCount; + typeinfo->ReferenceCount = ObjectHeader -> RefCount; + + ObDereferenceObject(Object); + return Status; + default: + ObDereferenceObject(Object); + return STATUS_NOT_IMPLEMENTED; + } +} + +VOID STDCALL +ObMakeTemporaryObject (PVOID ObjectBody) +{ + POBJECT_HEADER ObjectHeader; + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader->Permanent = FALSE; +} + + +/********************************************************************** + * NAME EXPORTED + * NtMakeTemporaryObject + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * + * REVISIONS + */ +NTSTATUS +STDCALL +NtMakeTemporaryObject ( + HANDLE Handle + ) +{ + PVOID Object; + NTSTATUS Status; + POBJECT_HEADER ObjectHeader; + + Status = ObReferenceObjectByHandle( + Handle, + 0, + NULL, + KernelMode, + & Object, + NULL + ); + if (Status != STATUS_SUCCESS) + { + return Status; + } + + ObjectHeader = BODY_TO_HEADER(Object); + ObjectHeader->Permanent = FALSE; + + ObDereferenceObject(Object); + + return STATUS_SUCCESS; +} + + +/* EOF */ diff --git a/ntoskrnl/ob/object.c b/ntoskrnl/ob/object.c new file mode 100644 index 0000000..7ac9996 --- /dev/null +++ b/ntoskrnl/ob/object.c @@ -0,0 +1,598 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ob/object.c + * PURPOSE: Implements generic object managment functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 10/06/98: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ************************************************************/ + +PVOID HEADER_TO_BODY(POBJECT_HEADER obj) +{ + return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)); +} + +POBJECT_HEADER BODY_TO_HEADER(PVOID body) +{ + PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body; + return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); +} + + +/********************************************************************** + * NAME PRIVATE + * ObInitializeObject + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +VOID ObInitializeObject(POBJECT_HEADER ObjectHeader, + PHANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE Type, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + ObjectHeader->HandleCount = 0; + ObjectHeader->RefCount = 1; + ObjectHeader->ObjectType = Type; + if (ObjectAttributes != NULL && + ObjectAttributes->Attributes & OBJ_PERMANENT) + { + ObjectHeader->Permanent = TRUE; + } + else + { + ObjectHeader->Permanent = FALSE; + } + RtlInitUnicodeString(&(ObjectHeader->Name),NULL); + if (Handle != NULL) + { + ObCreateHandle(PsGetCurrentProcess(), + HEADER_TO_BODY(ObjectHeader), + DesiredAccess, + ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE, + Handle); + } +} + + +/********************************************************************** + * NAME PRIVATE + * ObFindObject@16 + * + * DESCRIPTION + * + * ARGUMENTS + * ObjectAttributes + * + * ReturnedObject + * + * RemainigPath + * Pointer to a unicode string that will contain the + * remaining path if the function returns successfully. + * The caller must free the buffer after use by calling + * RtlFreeUnicodeString (). + * + * ObjectType + * Optional pointer to an object type. This is used to + * descide if a symbolic link object will be parsed or not. + * + * RETURN VALUE + */ +NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, + PVOID* ReturnedObject, + PUNICODE_STRING RemainingPath, + POBJECT_TYPE ObjectType) +{ + PVOID NextObject; + PVOID CurrentObject; + PVOID RootObject; + POBJECT_HEADER CurrentHeader; + NTSTATUS Status; + PWSTR Path; + PWSTR current; + UNICODE_STRING PathString; + + DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, " + "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath); + DPRINT("ObjectAttributes->ObjectName %wZ\n", + ObjectAttributes->ObjectName); + + RtlInitUnicodeString (RemainingPath, NULL); + + if (ObjectAttributes->RootDirectory == NULL) + { + ObReferenceObjectByPointer(NameSpaceRoot, + DIRECTORY_TRAVERSE, + NULL, + UserMode); + CurrentObject = NameSpaceRoot; + } + else + { + Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory, + DIRECTORY_TRAVERSE, + NULL, + UserMode, + &CurrentObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + } + + Path = ObjectAttributes->ObjectName->Buffer; + + if (Path[0] == 0) + { + *ReturnedObject = CurrentObject; + return(STATUS_SUCCESS); + } + + if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\')) + { + ObDereferenceObject(CurrentObject); + return(STATUS_UNSUCCESSFUL); + } + + if (Path) + { + RtlCreateUnicodeString (&PathString, Path); + current = PathString.Buffer; + } + else + { + RtlInitUnicodeString (&PathString, NULL); + current = NULL; + } + + RootObject = CurrentObject; + + while (TRUE) + { + DPRINT("current %S\n",current); + CurrentHeader = BODY_TO_HEADER(CurrentObject); + + DPRINT("Current ObjectType %wZ\n", + &CurrentHeader->ObjectType->TypeName); + + if (CurrentHeader->ObjectType->Parse == NULL) + { + DPRINT("Current object can't parse\n"); + break; + } + Status = CurrentHeader->ObjectType->Parse(CurrentObject, + &NextObject, + &PathString, + ¤t, + ObjectAttributes->Attributes); + if (Status == STATUS_REPARSE) + { + /* reparse the object path */ + NextObject = RootObject; + current = PathString.Buffer; + + ObReferenceObjectByPointer(NextObject, + DIRECTORY_TRAVERSE, + NULL, + UserMode); + } + + if (NextObject == NULL) + { + break; + } + ObDereferenceObject(CurrentObject); + CurrentObject = NextObject; + } + + if (current) + RtlCreateUnicodeString (RemainingPath, current); + RtlFreeUnicodeString (&PathString); + *ReturnedObject = CurrentObject; + + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * ObCreateObject@36 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + */ +NTSTATUS STDCALL +ObCreateObject(OUT PHANDLE Handle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN POBJECT_TYPE Type, + OUT PVOID *Object) +{ + PVOID Parent = NULL; + UNICODE_STRING RemainingPath; + POBJECT_HEADER Header; + POBJECT_HEADER ParentHeader = NULL; + NTSTATUS Status; + BOOLEAN ObjectAttached = FALSE; + + assert_irql(APC_LEVEL); + + DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n", + Handle, ObjectAttributes, Type); + + if (ObjectAttributes != NULL && + ObjectAttributes->ObjectName != NULL && + ObjectAttributes->ObjectName->Buffer != NULL) + { + Status = ObFindObject(ObjectAttributes, + &Parent, + &RemainingPath, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("ObFindObject() failed! (Status 0x%x)\n", Status); + return(Status); + } + } + else + { + RtlInitUnicodeString(&RemainingPath, NULL); + } + + RtlMapGenericMask(&DesiredAccess, + Type->Mapping); + + Header = (POBJECT_HEADER)ExAllocatePoolWithTag(NonPagedPool, + OBJECT_ALLOC_SIZE(Type), + Type->Tag); + ObInitializeObject(Header, + NULL, + DesiredAccess, + Type, + ObjectAttributes); + + if (Parent != NULL) + { + ParentHeader = BODY_TO_HEADER(Parent); + } + + if (ParentHeader != NULL && + ParentHeader->ObjectType == ObDirectoryType && + RemainingPath.Buffer != NULL) + { + ObpAddEntryDirectory(Parent, + Header, + RemainingPath.Buffer+1); + ObjectAttached = TRUE; + } + + if ((Header->ObjectType != NULL) && + (Header->ObjectType->Create != NULL)) + { + DPRINT("Calling %x\n", Header->ObjectType->Create); + Status = Header->ObjectType->Create(HEADER_TO_BODY(Header), + Parent, + RemainingPath.Buffer, + ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + if (ObjectAttached == TRUE) + { + ObpRemoveEntryDirectory(Header); + } + if (Parent) + { + ObDereferenceObject(Parent); + } + RtlFreeUnicodeString(&Header->Name); + RtlFreeUnicodeString(&RemainingPath); + ExFreePool(Header); + return(Status); + } + } + RtlFreeUnicodeString( &RemainingPath ); + + if (Object != NULL) + { + *Object = HEADER_TO_BODY(Header); + } + + if (Handle != NULL) + { + ObCreateHandle(PsGetCurrentProcess(), + *Object, + DesiredAccess, + ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT) ? TRUE : FALSE, + Handle); + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +ObReferenceObjectByPointer(IN PVOID Object, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode) +/* + * FUNCTION: Increments the pointer reference count for a given object + * ARGUMENTS: + * ObjectBody = Object's body + * DesiredAccess = Desired access to the object + * ObjectType = Points to the object type structure + * AccessMode = Type of access check to perform + * RETURNS: Status + */ +{ + POBJECT_HEADER Header; + +// DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n", +// Object,ObjectType); + + Header = BODY_TO_HEADER(Object); + + if (ObjectType != NULL && Header->ObjectType != ObjectType) + { + DPRINT("Failed %x (type was %x %S) should be %x %S\n", + Header, + Header->ObjectType, + Header->ObjectType->TypeName.Buffer, + ObjectType, + ObjectType->TypeName.Buffer); + return(STATUS_UNSUCCESSFUL); + } + if (Header->ObjectType == PsProcessType) + { + DPRINT("Ref p 0x%x refcount %d type %x ", + Object, Header->RefCount, PsProcessType); + DPRINT("eip %x\n", ((PULONG)&Object)[-1]); + } + if (Header->ObjectType == PsThreadType) + { + DPRINT("Deref t 0x%x with refcount %d type %x ", + Object, Header->RefCount, PsThreadType); + DPRINT("eip %x\n", ((PULONG)&Object)[-1]); + } + + if (Header->CloseInProcess) + { + return(STATUS_UNSUCCESSFUL); + } + + InterlockedIncrement(&Header->RefCount); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +ObOpenObjectByPointer(IN POBJECT Object, + IN ULONG HandleAttributes, + IN PACCESS_STATE PassedAccessState, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_TYPE ObjectType, + IN KPROCESSOR_MODE AccessMode, + OUT PHANDLE Handle) +{ + NTSTATUS Status; + + DPRINT("ObOpenObjectByPointer()\n"); + + Status = ObReferenceObjectByPointer(Object, + 0, + ObjectType, + AccessMode); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = ObCreateHandle(PsGetCurrentProcess(), + Object, + DesiredAccess, + HandleAttributes & OBJ_INHERIT, + Handle); + + ObDereferenceObject(Object); + + return STATUS_SUCCESS; +} + + +static NTSTATUS +ObpPerformRetentionChecks(POBJECT_HEADER Header) +{ +// DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n", +// Header,Header->RefCount,Header->HandleCount); + + if (Header->RefCount < 0) + { + CPRINT("Object %x/%x has invalid reference count (%d)\n", + Header, HEADER_TO_BODY(Header), Header->RefCount); + KeBugCheck(0); + } + if (Header->HandleCount < 0) + { + CPRINT("Object %x/%x has invalid handle count (%d)\n", + Header, HEADER_TO_BODY(Header), Header->HandleCount); + KeBugCheck(0); + } + + if (Header->RefCount == 0 && + Header->HandleCount == 0 && + Header->Permanent == FALSE) + { + if (Header->CloseInProcess) + { + KeBugCheck(0); + return STATUS_UNSUCCESSFUL; + } + Header->CloseInProcess = TRUE; + if (Header->ObjectType != NULL && + Header->ObjectType->Delete != NULL) + { + Header->ObjectType->Delete(HEADER_TO_BODY(Header)); + } + if (Header->Name.Buffer != NULL) + { + ObpRemoveEntryDirectory(Header); + RtlFreeUnicodeString(&Header->Name); + } + DPRINT("ObPerformRetentionChecks() = Freeing object\n"); + ExFreePool(Header); + } + return(STATUS_SUCCESS); +} + + +/********************************************************************** + * NAME EXPORTED + * ObfReferenceObject@4 + * + * DESCRIPTION + * Increments a given object's reference count and performs + * retention checks. + * + * ARGUMENTS + * ObjectBody = Body of the object. + * + * RETURN VALUE + * None. + */ +VOID FASTCALL +ObfReferenceObject(IN PVOID Object) +{ + POBJECT_HEADER Header; + + assert(Object); + + Header = BODY_TO_HEADER(Object); + + if (Header->CloseInProcess) + { + KeBugCheck(0); + } + InterlockedIncrement(&Header->RefCount); + + ObpPerformRetentionChecks(Header); +} + + +/********************************************************************** + * NAME EXPORTED + * ObfDereferenceObject@4 + * + * DESCRIPTION + * Decrements a given object's reference count and performs + * retention checks. + * + * ARGUMENTS + * ObjectBody = Body of the object. + * + * RETURN VALUE + * None. + */ +VOID FASTCALL +ObfDereferenceObject(IN PVOID Object) +{ + POBJECT_HEADER Header; + extern POBJECT_TYPE PsProcessType; + + assert(Object); + + Header = BODY_TO_HEADER(Object); + + if (Header->ObjectType == PsProcessType) + { + DPRINT("Deref p 0x%x with refcount %d type %x ", + Object, Header->RefCount, PsProcessType); + DPRINT("eip %x\n", ((PULONG)&Object)[-1]); + } + if (Header->ObjectType == PsThreadType) + { + DPRINT("Deref t 0x%x with refcount %d type %x ", + Object, Header->RefCount, PsThreadType); + DPRINT("eip %x\n", ((PULONG)&Object)[-1]); + } + + InterlockedDecrement(&Header->RefCount); + + ObpPerformRetentionChecks(Header); +} + + +/********************************************************************** + * NAME EXPORTED + * ObGetObjectPointerCount@4 + * + * DESCRIPTION + * Retrieves the pointer(reference) count of the given object. + * + * ARGUMENTS + * ObjectBody = Body of the object. + * + * RETURN VALUE + * Reference count. + */ +ULONG STDCALL +ObGetObjectPointerCount(PVOID Object) +{ + POBJECT_HEADER Header; + + assert(Object); + Header = BODY_TO_HEADER(Object); + + return(Header->RefCount); +} + + +/********************************************************************** + * NAME INTERNAL + * ObGetObjectHandleCount@4 + * + * DESCRIPTION + * Retrieves the handle count of the given object. + * + * ARGUMENTS + * ObjectBody = Body of the object. + * + * RETURN VALUE + * Reference count. + */ +ULONG +ObGetObjectHandleCount(PVOID Object) +{ + POBJECT_HEADER Header; + + assert(Object); + Header = BODY_TO_HEADER(Object); + + return(Header->HandleCount); +} + +/* EOF */ diff --git a/ntoskrnl/ob/security.c b/ntoskrnl/ob/security.c new file mode 100644 index 0000000..cef5182 --- /dev/null +++ b/ntoskrnl/ob/security.c @@ -0,0 +1,97 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: ntoskrnl/ob/security.c + * PROGRAMER: ? + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +ObAssignSecurity(IN PACCESS_STATE AccessState, + IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PVOID Object, + IN POBJECT_TYPE Type) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +ObGetObjectSecurity(IN PVOID Object, + OUT PSECURITY_DESCRIPTOR *SecurityDescriptor, + OUT PBOOLEAN MemoryAllocated) +{ + UNIMPLEMENTED; +} + + +VOID STDCALL +ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN BOOLEAN MemoryAllocated) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtQuerySecurityObject(IN HANDLE ObjectHandle, + IN CINT SecurityObjectInformationClass, + OUT PVOID SecurityObjectInformation, + IN ULONG Length, + OUT PULONG ReturnLength) +{ + NTSTATUS Status; + PVOID Object; + OBJECT_HANDLE_INFORMATION HandleInfo; + POBJECT_HEADER Header; + + Status = ObReferenceObjectByHandle(ObjectHandle, + 0, + NULL, + KeGetPreviousMode(), + &Object, + &HandleInfo); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Header = BODY_TO_HEADER(Object); + if (Header->ObjectType != NULL && + Header->ObjectType->Security != NULL) + { + Status = Header->ObjectType->Security(Object, + SecurityObjectInformationClass, + SecurityObjectInformation, + &Length); + *ReturnLength = Length; + } + else + { + Status = STATUS_NOT_IMPLEMENTED; + } + ObDereferenceObject(Object); + return(Status); +} + + +NTSTATUS STDCALL +NtSetSecurityObject(IN HANDLE Handle, + IN SECURITY_INFORMATION SecurityInformation, + IN PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/objects/.cvsignore b/ntoskrnl/objects/.cvsignore new file mode 100644 index 0000000..6dd71d1 --- /dev/null +++ b/ntoskrnl/objects/.cvsignore @@ -0,0 +1,2 @@ +*.o +*.coff diff --git a/ntoskrnl/po/.cvsignore b/ntoskrnl/po/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/po/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/po/power.c b/ntoskrnl/po/power.c new file mode 100644 index 0000000..2996c91 --- /dev/null +++ b/ntoskrnl/po/power.c @@ -0,0 +1,200 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/po/power.c + * PURPOSE: Power Manager + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 20/08/1999 EA Created + * 16/04/2001 CSH Stubs added + */ +#include +#include +#include +#include + +#define NDEBUG +#include + + +PDEVICE_NODE PopSystemPowerDeviceNode = NULL; + + +NTSTATUS +STDCALL +PoCallDriver( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp) +{ + NTSTATUS Status; + + Status = IoCallDriver(DeviceObject, Irp); + + return Status; +} + +PULONG +STDCALL +PoRegisterDeviceForIdleDetection( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG ConservationIdleTime, + IN ULONG PerformanceIdleTime, + IN DEVICE_POWER_STATE State) +{ + return NULL; +} + +PVOID +STDCALL +PoRegisterSystemState( + IN PVOID StateHandle, + IN EXECUTION_STATE Flags) +{ + return NULL; +} + +NTSTATUS +STDCALL +PoRequestPowerIrp( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PREQUEST_POWER_COMPLETE CompletionFunction, + IN PVOID Context, + OUT PIRP *Irp OPTIONAL) +{ + return STATUS_NOT_IMPLEMENTED; +} + +VOID +STDCALL +PoSetDeviceBusy( + PULONG IdlePointer) +{ +} + +POWER_STATE +STDCALL +PoSetPowerState( + IN PDEVICE_OBJECT DeviceObject, + IN POWER_STATE_TYPE Type, + IN POWER_STATE State) +{ + POWER_STATE ps; + + ps.SystemState = PowerSystemWorking; // Fully on + ps.DeviceState = PowerDeviceD0; // Fully on + + return ps; +} + +VOID +STDCALL +PoSetSystemState( + IN EXECUTION_STATE Flags) +{ +} + +VOID +STDCALL +PoStartNextPowerIrp( + IN PIRP Irp) +{ +} + +VOID +STDCALL +PoUnregisterSystemState( + IN PVOID StateHandle) +{ +} + +NTSTATUS +PopSetSystemPowerState( + SYSTEM_POWER_STATE PowerState) +{ + +#ifdef ACPI + + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION IrpSp; + PDEVICE_OBJECT Fdo; + NTSTATUS Status; + KEVENT Event; + PIRP Irp; + + Status = IopGetSystemPowerDeviceObject(&DeviceObject); + if (!NT_SUCCESS(Status)) { + CPRINT("No system power driver available\n"); + return STATUS_UNSUCCESSFUL; + } + + Fdo = IoGetAttachedDeviceReference(DeviceObject); + + if (Fdo == DeviceObject) + { + DPRINT("An FDO was not attached\n"); + return STATUS_UNSUCCESSFUL; + } + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER, + Fdo, + NULL, + 0, + NULL, + &Event, + &IoStatusBlock); + + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->MinorFunction = IRP_MN_SET_POWER; + IrpSp->Parameters.Power.Type = SystemPowerState; + IrpSp->Parameters.Power.State.SystemState = PowerState; + + Status = PoCallDriver(Fdo, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + ObDereferenceObject(Fdo); + + return Status; + +#endif /* ACPI */ + + return STATUS_NOT_IMPLEMENTED; +} + +VOID +PoInit(VOID) +{ +} + +/* EOF */ diff --git a/ntoskrnl/ps/.cvsignore b/ntoskrnl/ps/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/ps/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/ps/create.c b/ntoskrnl/ps/create.c new file mode 100644 index 0000000..72fa987 --- /dev/null +++ b/ntoskrnl/ps/create.c @@ -0,0 +1,689 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/thread.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Created + * 12/10/99: Phillip Susi: Thread priorities, and APC work + */ + +/* + * NOTE: + * + * All of the routines that manipulate the thread queue synchronize on + * a single spinlock + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBAL *******************************************************************/ + +static ULONG PiNextThreadUniqueId = 0; + +extern KSPIN_LOCK PiThreadListLock; +extern ULONG PiNrThreads; + +extern LIST_ENTRY PiThreadListHead; + +#define MAX_THREAD_NOTIFY_ROUTINE_COUNT 8 + +static ULONG PiThreadNotifyRoutineCount = 0; +static PCREATE_THREAD_NOTIFY_ROUTINE +PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT]; + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +PsAssignImpersonationToken(PETHREAD Thread, + HANDLE TokenHandle) +{ + PACCESS_TOKEN Token; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + NTSTATUS Status; + + if (TokenHandle != NULL) + { + Status = ObReferenceObjectByHandle(TokenHandle, + 0, + SepTokenObjectType, + UserMode, + (PVOID*)&Token, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + ImpersonationLevel = Token->ImpersonationLevel; + } + else + { + Token = NULL; + ImpersonationLevel = 0; + } + + PsImpersonateClient(Thread, + Token, + 0, + 0, + ImpersonationLevel); + if (Token != NULL) + { + ObDereferenceObject(Token); + } + return(STATUS_SUCCESS); +} + +VOID STDCALL +PsRevertToSelf(VOID) +{ + PETHREAD Thread; + + Thread = PsGetCurrentThread(); + + if (Thread->ActiveImpersonationInfo != 0) + { + ObDereferenceObject(Thread->ImpersonationInfo->Token); + Thread->ActiveImpersonationInfo = 0; + } +} + +VOID STDCALL +PsImpersonateClient(PETHREAD Thread, + PACCESS_TOKEN Token, + UCHAR b, + UCHAR c, + SECURITY_IMPERSONATION_LEVEL Level) +{ + if (Token == 0) + { + if (Thread->ActiveImpersonationInfo != 0) + { + Thread->ActiveImpersonationInfo = 0; + if (Thread->ImpersonationInfo->Token != NULL) + { + ObDereferenceObject(Thread->ImpersonationInfo->Token); + } + } + return; + } + if (Thread->ActiveImpersonationInfo == 0 || + Thread->ImpersonationInfo == NULL) + { + Thread->ImpersonationInfo = ExAllocatePool(NonPagedPool, + sizeof(PS_IMPERSONATION_INFO)); + } + Thread->ImpersonationInfo->Level = Level; + Thread->ImpersonationInfo->Unknown2 = c; + Thread->ImpersonationInfo->Unknown1 = b; + Thread->ImpersonationInfo->Token = Token; + ObReferenceObjectByPointer(Token, + 0, + SepTokenObjectType, + KernelMode); + Thread->ActiveImpersonationInfo = 1; +} + +PACCESS_TOKEN +PsReferenceEffectiveToken(PETHREAD Thread, + PTOKEN_TYPE TokenType, + PUCHAR b, + PSECURITY_IMPERSONATION_LEVEL Level) +{ + PEPROCESS Process; + PACCESS_TOKEN Token; + + if (Thread->ActiveImpersonationInfo == 0) + { + Process = Thread->ThreadsProcess; + *TokenType = TokenPrimary; + *b = 0; + Token = Process->Token; + } + else + { + Token = Thread->ImpersonationInfo->Token; + *TokenType = TokenImpersonation; + *b = Thread->ImpersonationInfo->Unknown2; + *Level = Thread->ImpersonationInfo->Level; + } + return(Token); +} + +NTSTATUS STDCALL +NtImpersonateThread(IN HANDLE ThreadHandle, + IN HANDLE ThreadToImpersonateHandle, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService) +{ + PETHREAD Thread; + PETHREAD ThreadToImpersonate; + NTSTATUS Status; + SECURITY_CLIENT_CONTEXT ClientContext; + + Status = ObReferenceObjectByHandle(ThreadHandle, + 0, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle, + 0, + PsThreadType, + UserMode, + (PVOID*)&ThreadToImpersonate, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Thread); + return(Status); + } + + Status = SeCreateClientSecurity(ThreadToImpersonate, + SecurityQualityOfService, + 0, + &ClientContext); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Thread); + ObDereferenceObject(ThreadToImpersonate); + return(Status); + } + + SeImpersonateClient(&ClientContext, Thread); + if (ClientContext.Token != NULL) + { + ObDereferenceObject(ClientContext.Token); + } + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtOpenThreadToken(IN HANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN BOOLEAN OpenAsSelf, + OUT PHANDLE TokenHandle) +{ +#if 0 + PETHREAD Thread; + NTSTATUS Status; + PACCESS_TOKEN Token; + + Status = ObReferenceObjectByHandle(ThreadHandle, + 0, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Token = PsReferencePrimaryToken(Thread->ThreadsProcess); + SepCreateImpersonationTokenDacl(Token); +#endif + return(STATUS_UNSUCCESSFUL); +} + +PACCESS_TOKEN STDCALL +PsReferenceImpersonationToken(PETHREAD Thread, + PULONG Unknown1, + PULONG Unknown2, + SECURITY_IMPERSONATION_LEVEL* Level) +{ + if (Thread->ActiveImpersonationInfo == 0) + { + return(NULL); + } + + *Level = Thread->ImpersonationInfo->Level; + *Unknown1 = Thread->ImpersonationInfo->Unknown1; + *Unknown2 = Thread->ImpersonationInfo->Unknown2; + ObReferenceObjectByPointer(Thread->ImpersonationInfo->Token, + TOKEN_ALL_ACCESS, + SepTokenObjectType, + KernelMode); + return(Thread->ImpersonationInfo->Token); +} + +VOID +PiBeforeBeginThread(CONTEXT c) +{ + DPRINT("PiBeforeBeginThread(Eip %x)\n", c.Eip); + KeLowerIrql(PASSIVE_LEVEL); +} + +VOID STDCALL +PiDeleteThread(PVOID ObjectBody) +{ + KIRQL oldIrql; + PETHREAD Thread; + ULONG i; + Thread = (PETHREAD)ObjectBody; + + DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody); + + ObDereferenceObject(Thread->ThreadsProcess); + Thread->ThreadsProcess = NULL; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + for (i = 0; i < PiThreadNotifyRoutineCount; i++) + { + PiThreadNotifyRoutine[i](Thread->Cid.UniqueProcess, + Thread->Cid.UniqueThread, + FALSE); + } + PiNrThreads--; + RemoveEntryList(&Thread->Tcb.ThreadListEntry); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + KeReleaseThread(Thread); + DPRINT("PiDeleteThread() finished\n"); +} + +NTSTATUS +PsInitializeThread(HANDLE ProcessHandle, + PETHREAD* ThreadPtr, + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ThreadAttributes, + BOOLEAN First) +{ + PETHREAD Thread; + NTSTATUS Status; + KIRQL oldIrql; + PEPROCESS Process; + ULONG i; + + /* + * Reference process + */ + if (ProcessHandle != NULL) + { + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (Status != STATUS_SUCCESS) + { + DPRINT("Failed at %s:%d\n",__FILE__,__LINE__); + return(Status); + } + DPRINT( "Creating thread in process %x\n", Process ); + } + else + { + Process = PsInitialSystemProcess; + ObReferenceObjectByPointer(Process, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode); + } + + /* + * Create and initialize thread + */ + Status = ObCreateObject(ThreadHandle, + DesiredAccess, + ThreadAttributes, + PsThreadType, + (PVOID*)&Thread); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("Thread = %x\n",Thread); + + PiNrThreads++; + + KeInitializeThread(&Process->Pcb, &Thread->Tcb, First); + Thread->ThreadsProcess = Process; + /* + * FIXME: What lock protects this? + */ + InsertTailList(&Thread->ThreadsProcess->ThreadListHead, + &Thread->Tcb.ProcessThreadListEntry); + InitializeListHead(&Thread->TerminationPortList); + KeInitializeSpinLock(&Thread->ActiveTimerListLock); + InitializeListHead(&Thread->IrpList); + Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement( + &PiNextThreadUniqueId); + Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; + Thread->DeadThread = 0; + Thread->Win32Thread = 0; + DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread); + + *ThreadPtr = Thread; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + + Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority; + Thread->Tcb.Priority = Thread->Tcb.BasePriority; + + for (i = 0; i < PiThreadNotifyRoutineCount; i++) + { + PiThreadNotifyRoutine[i](Thread->Cid.UniqueProcess, + Thread->Cid.UniqueThread, + TRUE); + } + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +PsCreateTeb(HANDLE ProcessHandle, + PTEB *TebPtr, + PETHREAD Thread, + PINITIAL_TEB InitialTeb) +{ + MEMORY_BASIC_INFORMATION Info; + NTSTATUS Status; + ULONG ByteCount; + ULONG RegionSize; + ULONG TebSize; + PVOID TebBase; + TEB Teb; + ULONG ResultLength; + + TebBase = (PVOID)0x7FFDE000; + TebSize = PAGE_SIZE; + + while (TRUE) + { + Status = NtQueryVirtualMemory(ProcessHandle, + TebBase, + MemoryBasicInformation, + &Info, + sizeof(Info), + &ResultLength); + if (!NT_SUCCESS(Status)) + { + CPRINT("NtQueryVirtualMemory (Status %x)\n", Status); + KeBugCheck(0); + } + /* FIXME: Race between this and the above check */ + if (Info.State == MEM_FREE) + { + /* The TEB must reside in user space */ + Status = NtAllocateVirtualMemory(ProcessHandle, + &TebBase, + 0, + &TebSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (NT_SUCCESS(Status)) + { + break; + } + } + + TebBase = TebBase - TebSize; + } + + DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); + + /* set all pointers to and from the TEB */ + Teb.Tib.Self = TebBase; + if (Thread->ThreadsProcess) + { + Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */ + } + DPRINT("Teb.Peb %x\n", Teb.Peb); + + /* store stack information from InitialTeb */ + if (InitialTeb != NULL) + { + Teb.Tib.StackBase = InitialTeb->StackBase; + Teb.Tib.StackLimit = InitialTeb->StackLimit; + Teb.DeallocationStack = InitialTeb->StackAllocate; + } + + /* more initialization */ + Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; + Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; + Teb.CurrentLocale = PsDefaultThreadLocaleId; + + /* Terminate the exception handler list */ + Teb.Tib.ExceptionList = (PVOID)-1; + + DPRINT("sizeof(TEB) %x\n", sizeof(TEB)); + + /* write TEB data into teb page */ + Status = NtWriteVirtualMemory(ProcessHandle, + TebBase, + &Teb, + sizeof(TEB), + &ByteCount); + + if (!NT_SUCCESS(Status)) + { + /* free TEB */ + DPRINT1 ("Writing TEB failed!\n"); + + RegionSize = 0; + NtFreeVirtualMemory(ProcessHandle, + TebBase, + &RegionSize, + MEM_RELEASE); + + return Status; + } + + if (TebPtr != NULL) + { + *TebPtr = (PTEB)TebBase; + } + + DPRINT("TEB allocated at %p\n", TebBase); + + return Status; +} + +VOID STDCALL +LdrInitApcRundownRoutine(PKAPC Apc) +{ + ExFreePool(Apc); +} + +VOID STDCALL +LdrInitApcKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) +{ + ExFreePool(Apc); +} + +NTSTATUS STDCALL +NtCreateThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID Client, + PCONTEXT ThreadContext, + PINITIAL_TEB InitialTeb, + BOOLEAN CreateSuspended) +{ + PETHREAD Thread; + PTEB TebBase; + NTSTATUS Status; + PKAPC LdrInitApc; + + DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n", + ThreadHandle,ThreadContext); + + Status = PsInitializeThread(ProcessHandle, + &Thread, + ThreadHandle, + DesiredAccess, + ObjectAttributes, + FALSE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = PsCreateTeb(ProcessHandle, + &TebBase, + Thread, + InitialTeb); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Thread->Tcb.Teb = TebBase; + + Thread->StartAddress = NULL; + + if (Client != NULL) + { + *Client = Thread->Cid; + } + + /* + * Maybe send a message to the process's debugger + */ + DbgkCreateThread((PVOID)ThreadContext->Eip); + + /* + * First, force the thread to be non-alertable for user-mode alerts. + */ + Thread->Tcb.Alertable = FALSE; + + /* + * If the thread is to be created suspended then queue an APC to + * do the suspend before we run any userspace code. + */ + if (CreateSuspended) + { + PsSuspendThread(Thread, NULL); + } + + /* + * Queue an APC to the thread that will execute the ntdll startup + * routine. + */ + LdrInitApc = ExAllocatePool(NonPagedPool, sizeof(KAPC)); + KeInitializeApc(LdrInitApc, &Thread->Tcb, 0, LdrInitApcKernelRoutine, + LdrInitApcRundownRoutine, LdrpGetSystemDllEntryPoint(), + UserMode, NULL); + KeInsertQueueApc(LdrInitApc, NULL, NULL, UserMode); + + /* + * Start the thread running and force it to execute the APC(s) we just + * queued before it runs anything else in user-mode. + */ + Thread->Tcb.Alertable = TRUE; + Thread->Tcb.Alerted[0] = 1; + PsUnblockThread(Thread, NULL); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +PsCreateSystemThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext) +/* + * FUNCTION: Creates a thread which executes in kernel mode + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the returned thread + * handle + * DesiredAccess = Requested access to the thread + * ObjectAttributes = Object attributes (optional) + * ProcessHandle = Handle of process thread will run in + * NULL to use system process + * ClientId (OUT) = Caller supplied storage for the returned client id + * of the thread (optional) + * StartRoutine = Entry point for the thread + * StartContext = Argument supplied to the thread when it begins + * execution + * RETURNS: Success or failure status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + + DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", + ThreadHandle,ProcessHandle); + + Status = PsInitializeThread(ProcessHandle, + &Thread, + ThreadHandle, + DesiredAccess, + ObjectAttributes, + FALSE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Thread->StartAddress = StartRoutine; + Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (ClientId != NULL) + { + *ClientId=Thread->Cid; + } + + PsUnblockThread(Thread, NULL); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine) +{ + if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT) + return(STATUS_INSUFFICIENT_RESOURCES); + + PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine; + PiThreadNotifyRoutineCount++; + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ps/debug.c b/ntoskrnl/ps/debug.c new file mode 100644 index 0000000..7c843f3 --- /dev/null +++ b/ntoskrnl/ps/debug.c @@ -0,0 +1,275 @@ +/* + * ReactOS kernel + * Copyright (C) 2000, 1999, 1998 David Welch , + * Philip Susi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/debug.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Created + * 12/10/99: Phillip Susi: Thread priorities, and APC work + */ + +/* + * NOTE: + * + * All of the routines that manipulate the thread queue synchronize on + * a single spinlock + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +VOID +KeContextToTrapFrame(PCONTEXT Context, + PKTRAP_FRAME TrapFrame) +{ + if (Context->ContextFlags & CONTEXT_CONTROL) + { + TrapFrame->Esp = Context->Esp; + TrapFrame->Ss = Context->SegSs; + TrapFrame->Cs = Context->SegCs; + TrapFrame->Eip = Context->Eip; + TrapFrame->Eflags = Context->EFlags; + TrapFrame->Ebp = Context->Ebp; + } + if (Context->ContextFlags & CONTEXT_INTEGER) + { + TrapFrame->Eax = Context->Eax; + TrapFrame->Ebx = Context->Ebx; + TrapFrame->Ecx = Context->Ecx; + /* + * Edx is used in the TrapFrame to hold the old trap frame pointer + * so we don't want to overwrite it here + */ +/* TrapFrame->Edx = Context->Edx; */ + TrapFrame->Esi = Context->Esi; + TrapFrame->Edx = Context->Edi; + } + if (Context->ContextFlags & CONTEXT_SEGMENTS) + { + TrapFrame->Ds = Context->SegDs; + TrapFrame->Es = Context->SegEs; + TrapFrame->Fs = Context->SegFs; + TrapFrame->Gs = Context->SegGs; + } + if (Context->ContextFlags & CONTEXT_FLOATING_POINT) + { + /* + * Not handled + */ + } + if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) + { + /* + * Not handled + */ + } +} + +VOID +KeTrapFrameToContext(PKTRAP_FRAME TrapFrame, + PCONTEXT Context) +{ + if (Context->ContextFlags & CONTEXT_CONTROL) + { + Context->SegSs = TrapFrame->Ss; + Context->Esp = TrapFrame->Esp; + Context->SegCs = TrapFrame->Cs; + Context->Eip = TrapFrame->Eip; + Context->EFlags = TrapFrame->Eflags; + Context->Ebp = TrapFrame->Ebp; + } + if (Context->ContextFlags & CONTEXT_INTEGER) + { + Context->Eax = TrapFrame->Eax; + Context->Ebx = TrapFrame->Ebx; + Context->Ecx = TrapFrame->Ecx; + /* + * NOTE: In the trap frame which is built on entry to a system + * call TrapFrame->Edx will actually hold the address of the + * previous TrapFrame. I don't believe leaking this information + * has security implications. Also EDX holds the address of the + * arguments to the system call in progress so it isn't of much + * interest to the debugger. + */ + Context->Edx = TrapFrame->Edx; + Context->Esi = TrapFrame->Esi; + Context->Edi = TrapFrame->Edi; + } + if (Context->ContextFlags & CONTEXT_SEGMENTS) + { + Context->SegDs = TrapFrame->Ds; + Context->SegEs = TrapFrame->Es; + Context->SegFs = TrapFrame->Fs; + Context->SegGs = TrapFrame->Gs; + } + if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) + { + /* + * FIXME: Implement this case + */ + } + if (Context->ContextFlags & CONTEXT_FLOATING_POINT) + { + /* + * FIXME: Implement this case + */ + } +#if 0 + if (Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) + { + /* + * FIXME: Investigate this + */ + } +#endif +} + +VOID STDCALL +KeGetContextRundownRoutine(PKAPC Apc) +{ + PKEVENT Event; + PNTSTATUS Status; + + Event = (PKEVENT)Apc->SystemArgument1; + Status = (PNTSTATUS)Apc->SystemArgument2; + (*Status) = STATUS_THREAD_IS_TERMINATING; + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); +} + +VOID STDCALL +KeGetContextKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) +/* + * FUNCTION: This routine is called by an APC sent by NtGetContextThread to + * copy the context of a thread into a buffer. + */ +{ + PKEVENT Event; + PCONTEXT Context; + PNTSTATUS Status; + + Context = (PCONTEXT)(*NormalContext); + Event = (PKEVENT)(*SystemArgument1); + Status = (PNTSTATUS)(*SystemArgument2); + + KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context); + + *Status = STATUS_SUCCESS; + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); +} + +NTSTATUS STDCALL +NtGetContextThread(IN HANDLE ThreadHandle, + OUT PCONTEXT Context) +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_GET_CONTEXT, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (Thread == PsGetCurrentThread()) + { + /* + * I don't know if trying to get your own context makes much + * sense but we can handle it more efficently. + */ + + KeTrapFrameToContext(Thread->Tcb.TrapFrame, Context); + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); + } + else + { + KAPC Apc; + KEVENT Event; + NTSTATUS AStatus; + CONTEXT KContext; + + KContext.ContextFlags = Context->ContextFlags; + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + AStatus = STATUS_SUCCESS; + + KeInitializeApc(&Apc, + &Thread->Tcb, + 0, + KeGetContextKernelRoutine, + KeGetContextRundownRoutine, + NULL, + KernelMode, + (PVOID)&KContext); + KeInsertQueueApc(&Apc, + (PVOID)&Event, + (PVOID)&AStatus, + 0); + Status = KeWaitForSingleObject(&Event, + 0, + UserMode, + FALSE, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (!NT_SUCCESS(AStatus)) + { + return(AStatus); + } + memcpy(Context, &KContext, sizeof(CONTEXT)); + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); + } +} + +NTSTATUS STDCALL +NtSetContextThread(IN HANDLE ThreadHandle, + IN PCONTEXT Context) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/ntoskrnl/ps/idle.c b/ntoskrnl/ps/idle.c new file mode 100644 index 0000000..f19ac14 --- /dev/null +++ b/ntoskrnl/ps/idle.c @@ -0,0 +1,69 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/idle.c + * PURPOSE: Using idle time + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +HANDLE PsIdleThreadHandle = NULL; +extern ULONG DpcQueueSize; +PETHREAD PiIdleThread; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +PsIdleThreadMain(PVOID Context) +{ + KIRQL oldlvl; + + for(;;) + { + if (DpcQueueSize > 0) + { + KeRaiseIrql(DISPATCH_LEVEL,&oldlvl); + KiDispatchInterrupt(); + KeLowerIrql(oldlvl); + } + NtYieldExecution(); + __asm__( "hlt" ); + } +} + +VOID PsInitIdleThread(VOID) +{ + KPRIORITY Priority; + ULONG Affinity; + + PsCreateSystemThread(&PsIdleThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + PsIdleThreadMain, + NULL); + + Priority = LOW_PRIORITY; + NtSetInformationThread(PsIdleThreadHandle, + ThreadPriority, + &Priority, + sizeof(Priority)); + Affinity = 1 << 0; + NtSetInformationThread(PsIdleThreadHandle, + ThreadAffinityMask, + &Affinity, + sizeof(Affinity)); +} diff --git a/ntoskrnl/ps/kill.c b/ntoskrnl/ps/kill.c new file mode 100644 index 0000000..7d9fa12 --- /dev/null +++ b/ntoskrnl/ps/kill.c @@ -0,0 +1,372 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/kill.c + * PURPOSE: Terminating a thread + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +extern ULONG PiNrThreads; +extern ULONG PiNrRunnableThreads; +extern KSPIN_LOCK PiThreadListLock; +extern LIST_ENTRY PiThreadListHead; +extern KSPIN_LOCK PiApcLock; + +VOID PsTerminateCurrentThread(NTSTATUS ExitStatus); + +#define TAG_TERMINATE_APC TAG('T', 'A', 'P', 'C') + +/* FUNCTIONS *****************************************************************/ + +VOID +PiTerminateProcessThreads(PEPROCESS Process, + NTSTATUS ExitStatus) +{ + KIRQL oldlvl; + PLIST_ENTRY current_entry; + PETHREAD current; + + DPRINT("PiTerminateProcessThreads(Process %x, ExitStatus %x)\n", + Process, ExitStatus); + + KeAcquireSpinLock(&PiThreadListLock, &oldlvl); + + current_entry = Process->ThreadListHead.Flink; + while (current_entry != &Process->ThreadListHead) + { + current = CONTAINING_RECORD(current_entry, ETHREAD, + Tcb.ProcessThreadListEntry); + if (current != PsGetCurrentThread() && + current->DeadThread == 0) + { + DPRINT("Terminating %x, current thread: %x, " + "thread's process: %x\n", current, PsGetCurrentThread(), + current->ThreadsProcess); + KeReleaseSpinLock(&PiThreadListLock, oldlvl); + PsTerminateOtherThread(current, ExitStatus); + KeAcquireSpinLock(&PiThreadListLock, &oldlvl); + current_entry = Process->ThreadListHead.Flink; + } + else + { + current_entry = current_entry->Flink; + } + } + KeReleaseSpinLock(&PiThreadListLock, oldlvl); + DPRINT("Finished PiTerminateProcessThreads()\n"); +} + +VOID +PsReapThreads(VOID) +{ + PLIST_ENTRY current_entry; + PETHREAD current; + KIRQL oldIrql; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + current_entry = PiThreadListHead.Flink; + + while (current_entry != &PiThreadListHead) + { + current = CONTAINING_RECORD(current_entry, ETHREAD, + Tcb.ThreadListEntry); + + current_entry = current_entry->Flink; + + if (current->Tcb.State == THREAD_STATE_TERMINATED_1) + { + PEPROCESS Process = current->ThreadsProcess; + NTSTATUS Status = current->ExitStatus; + + PiNrThreadsAwaitingReaping--; + current->Tcb.State = THREAD_STATE_TERMINATED_2; + RemoveEntryList(¤t->Tcb.ProcessThreadListEntry); + if (IsListEmpty(&Process->ThreadListHead)) + { + KeReleaseSpinLock( &PiThreadListLock, oldIrql ); + PiTerminateProcess(Process, Status); + KeAcquireSpinLock( &PiThreadListLock, &oldIrql ); + } + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + ObDereferenceObject(current); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + current_entry = PiThreadListHead.Flink; + } + } + KeReleaseSpinLock(&PiThreadListLock, oldIrql); +} + +VOID +PsTerminateCurrentThread(NTSTATUS ExitStatus) +/* + * FUNCTION: Terminates the current thread + */ +{ + KIRQL oldIrql; + PETHREAD CurrentThread; + PKTHREAD Thread; + PLIST_ENTRY current_entry; + PKMUTANT Mutant; + + CurrentThread = PsGetCurrentThread(); + + DPRINT("terminating %x\n",CurrentThread); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + CurrentThread->ExitStatus = ExitStatus; + Thread = KeGetCurrentThread(); + KeCancelTimer(&Thread->Timer); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + + /* abandon all owned mutants */ + current_entry = Thread->MutantListHead.Flink; + while (current_entry != &Thread->MutantListHead) + { + Mutant = CONTAINING_RECORD(current_entry, KMUTANT, + MutantListEntry); + KeReleaseMutant(Mutant, + MUTANT_INCREMENT, + TRUE, + FALSE); + current_entry = Thread->MutantListHead.Flink; + } + + KeAcquireDispatcherDatabaseLock(FALSE); + CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE; + KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader); + KeReleaseDispatcherDatabaseLock(FALSE); + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1); + KeBugCheck(0); +} + +VOID STDCALL +PiTerminateThreadRundownRoutine(PKAPC Apc) +{ + ExFreePool(Apc); +} + +VOID STDCALL +PiTerminateThreadKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2) +{ + ExFreePool(Apc); +} + +VOID STDCALL +PiTerminateThreadNormalRoutine(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus); +} + +VOID +PsTerminateOtherThread(PETHREAD Thread, + NTSTATUS ExitStatus) +/* + * FUNCTION: Terminate a thread when calling from another thread's context + * NOTES: This function must be called with PiThreadListLock held + */ +{ + PKAPC Apc; + + DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n", + Thread, ExitStatus); + + Thread->DeadThread = 1; + Thread->ExitStatus = ExitStatus; + Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC); + KeInitializeApc(Apc, + &Thread->Tcb, + 0, + PiTerminateThreadKernelRoutine, + PiTerminateThreadRundownRoutine, + PiTerminateThreadNormalRoutine, + KernelMode, + NULL); + KeInsertQueueApc(Apc, + NULL, + NULL, + KernelMode); +} + +NTSTATUS STDCALL +PiTerminateProcess(PEPROCESS Process, + NTSTATUS ExitStatus) +{ + DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) PC %d HC %d\n", + Process, ExitStatus, ObGetObjectPointerCount(Process), + ObGetObjectHandleCount(Process)); + + ObReferenceObject(Process); + if (InterlockedExchange((PLONG)&Process->Pcb.State, + PROCESS_STATE_TERMINATED) == + PROCESS_STATE_TERMINATED) + { + ObDereferenceObject(Process); + return(STATUS_SUCCESS); + } + KeAttachProcess( Process ); + ObCloseAllHandles(Process); + KeDetachProcess(); + KeAcquireDispatcherDatabaseLock(FALSE); + Process->Pcb.DispatcherHeader.SignalState = TRUE; + KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader); + KeReleaseDispatcherDatabaseLock(FALSE); + ObDereferenceObject(Process); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtTerminateProcess(IN HANDLE ProcessHandle, + IN NTSTATUS ExitStatus) +{ + NTSTATUS Status; + PEPROCESS Process; + + DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n", + ProcessHandle, ExitStatus); + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_TERMINATE, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Process->ExitStatus = ExitStatus; + PiTerminateProcessThreads(Process, ExitStatus); + if (PsGetCurrentThread()->ThreadsProcess == Process) + { + ObDereferenceObject(Process); + PsTerminateCurrentThread(ExitStatus); + } + ObDereferenceObject(Process); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtTerminateThread(IN HANDLE ThreadHandle, + IN NTSTATUS ExitStatus) +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_TERMINATE, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + ObDereferenceObject(Thread); + + if (Thread == PsGetCurrentThread()) + { + PsTerminateCurrentThread(ExitStatus); + } + else + { + PsTerminateOtherThread(Thread, ExitStatus); + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +PsTerminateSystemThread(NTSTATUS ExitStatus) +/* + * FUNCTION: Terminates the current thread + * ARGUMENTS: + * ExitStatus = Status to pass to the creater + * RETURNS: Doesn't + */ +{ + PsTerminateCurrentThread(ExitStatus); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtCallTerminatePorts(PETHREAD Thread) +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PEPORT_TERMINATION_REQUEST current; + + KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql); + while ((current_entry = RemoveHeadList(&Thread->TerminationPortList)) != + &Thread->TerminationPortList); + { + current = CONTAINING_RECORD(current_entry, + EPORT_TERMINATION_REQUEST, + ThreadListEntry); + KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql); + LpcSendTerminationPort(current->Port, + Thread->CreateTime); + KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql); + } + KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle) +{ + NTSTATUS Status; + PEPORT_TERMINATION_REQUEST Request; + PEPORT TerminationPort; + KIRQL oldIrql; + PETHREAD Thread; + + Status = ObReferenceObjectByHandle(TerminationPortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&TerminationPort, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Request = ExAllocatePool(NonPagedPool, sizeof(EPORT_TERMINATION_REQUEST)); + Request->Port = TerminationPort; + Thread = PsGetCurrentThread(); + KeAcquireSpinLock(&Thread->ActiveTimerListLock, &oldIrql); + InsertTailList(&Thread->TerminationPortList, &Request->ThreadListEntry); + KeReleaseSpinLock(&Thread->ActiveTimerListLock, oldIrql); + + return(STATUS_SUCCESS); +} diff --git a/ntoskrnl/ps/locale.c b/ntoskrnl/ps/locale.c new file mode 100644 index 0000000..b78764d --- /dev/null +++ b/ntoskrnl/ps/locale.c @@ -0,0 +1,272 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/locale.c + * PURPOSE: Locale support + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +/* + * Default setting: LANG_NEUTRAL, SUBLANG_NEUTRAL, SORT_DEFAULT + */ +LCID PsDefaultThreadLocaleId = 0; +LCID PsDefaultSystemLocaleId = 0; + + +#define VALUE_BUFFER_SIZE 256 + +/* FUNCTIONS *****************************************************************/ + +VOID +PiInitDefaultLocale(VOID) +/* + * FUNCTION: + * Initializes the default locale. + * Reads default locale from registry, if available + * ARGUMENTS: + * None. + * Returns: + * None. + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + ULONG ValueLength; + UCHAR ValueBuffer[VALUE_BUFFER_SIZE]; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + UNICODE_STRING ValueString; + ULONG LocaleValue; + NTSTATUS Status; + + ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; + + /* read system locale */ + RtlInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language"); + RtlInitUnicodeStringFromLiteral(&ValueName, + L"Default"); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, + KEY_QUERY_VALUE, + &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + Status = NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueBuffer, + VALUE_BUFFER_SIZE, + &ValueLength); + if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ)) + { + ValueString.Length = ValueInfo->DataLength; + ValueString.MaximumLength = ValueInfo->DataLength; + ValueString.Buffer = (PWSTR)ValueInfo->Data; + + Status = RtlUnicodeStringToInteger(&ValueString, + 10, + &LocaleValue); + if (NT_SUCCESS(Status)) + { + DPRINT("System locale: %08lu\n", LocaleValue); + PsDefaultSystemLocaleId = (LCID)LocaleValue; + } + } + NtClose(KeyHandle); + } + + /* read default thread locale */ + RtlInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\User\\.Default\\Control Panel\\International"); + RtlInitUnicodeStringFromLiteral(&ValueName, + L"Locale"); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, + KEY_QUERY_VALUE, + &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + Status = NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueBuffer, + VALUE_BUFFER_SIZE, + &ValueLength); + if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ)) + { + ValueString.Length = ValueInfo->DataLength; + ValueString.MaximumLength = ValueInfo->DataLength; + ValueString.Buffer = (PWSTR)ValueInfo->Data; + + Status = RtlUnicodeStringToInteger(&ValueString, + 10, + &LocaleValue); + if (NT_SUCCESS(Status)) + { + DPRINT("Thread locale: %08lu\n", LocaleValue); + PsDefaultThreadLocaleId = (LCID)LocaleValue; + } + } + NtClose(KeyHandle); + } +} + + +NTSTATUS STDCALL +NtQueryDefaultLocale(IN BOOLEAN ThreadOrSystem, + OUT PLCID DefaultLocaleId) +/* + * FUNCTION: + * Returns the default locale. + * ARGUMENTS: + * ThreadOrSystem = If TRUE then the locale for this thread is returned, + * otherwise the locale for the system is returned. + * DefaultLocaleId = Points to a variable that receives the locale id. + * Returns: + * Status. + */ +{ + if (DefaultLocaleId == NULL) + return STATUS_UNSUCCESSFUL; + + if (ThreadOrSystem == TRUE) + { + /* set thread locale */ + *DefaultLocaleId = PsDefaultThreadLocaleId; + } + else + { + /* set system locale */ + *DefaultLocaleId = PsDefaultSystemLocaleId; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSetDefaultLocale(IN BOOLEAN ThreadOrSystem, + IN LCID DefaultLocaleId) +/* + * FUNCTION: + * Sets the default locale. + * ARGUMENTS: + * ThreadOrSystem = If TRUE then the locale for this thread is set, + * otherwise the locale for the system is set. + * DefaultLocaleId = The locale id to be set. + * Returns: + * Status. + */ +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + ULONG ValueLength; + WCHAR ValueBuffer[20]; + HANDLE UserKey = NULL; + NTSTATUS Status; + + if (ThreadOrSystem == TRUE) + { + /* thread locale */ + Status = RtlOpenCurrentUser(KEY_WRITE, + &UserKey); + if (!NT_SUCCESS(Status)) + return(Status); + RtlInitUnicodeStringFromLiteral(&KeyName, + L"Control Panel\\International"); + RtlInitUnicodeStringFromLiteral(&ValueName, + L"Locale"); + } + else + { + /* system locale */ + RtlInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language"); + RtlInitUnicodeStringFromLiteral(&ValueName, + L"Default"); + } + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + UserKey, + NULL); + Status = NtOpenKey(&KeyHandle, + KEY_SET_VALUE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + if (UserKey != NULL) + { + NtClose(UserKey); + } + return(Status); + } + + ValueLength = swprintf(ValueBuffer, + L"%08lu", + (ULONG)DefaultLocaleId); + ValueLength = (ValueLength + 1) * sizeof(WCHAR); + + Status = NtSetValueKey(KeyHandle, + &ValueName, + 0, + REG_SZ, + ValueBuffer, + ValueLength); + + NtClose(KeyHandle); + if (UserKey != NULL) + { + NtClose(UserKey); + } + + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (ThreadOrSystem == TRUE) + { + /* set thread locale */ + DPRINT("Thread locale: %08lu\n", DefaultLocaleId); + PsDefaultThreadLocaleId = DefaultLocaleId; + } + else + { + /* set system locale */ + DPRINT("System locale: %08lu\n", DefaultLocaleId); + PsDefaultSystemLocaleId = DefaultLocaleId; + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ps/process.c b/ntoskrnl/ps/process.c new file mode 100644 index 0000000..c0b094c --- /dev/null +++ b/ntoskrnl/ps/process.c @@ -0,0 +1,1248 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/process.c + * PURPOSE: Process managment + * PROGRAMMER: David Welch (welch@cwcom.net) + * REVISION HISTORY: + * 21/07/98: Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +PEPROCESS EXPORTED PsInitialSystemProcess = NULL; +HANDLE SystemProcessHandle = NULL; + +POBJECT_TYPE EXPORTED PsProcessType = NULL; + +LIST_ENTRY PsProcessListHead; +static KSPIN_LOCK PsProcessListLock; +static ULONG PiNextProcessUniqueId = 0; + +static GENERIC_MAPPING PiProcessMapping = {PROCESS_READ, + PROCESS_WRITE, + PROCESS_EXECUTE, + PROCESS_ALL_ACCESS}; + +#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8 + +static ULONG PiProcessNotifyRoutineCount = 0; +static PCREATE_PROCESS_NOTIFY_ROUTINE +PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT]; + +/* FUNCTIONS *****************************************************************/ + + +PEPROCESS +PsGetNextProcess(PEPROCESS OldProcess) +{ + KIRQL oldIrql; + PEPROCESS NextProcess; + NTSTATUS Status; + + if (OldProcess == NULL) + { + return(PsInitialSystemProcess); + } + + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead) + { + NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink, + EPROCESS, + ProcessListEntry); + } + else + { + NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink, + EPROCESS, + ProcessListEntry); + } + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + Status = ObReferenceObjectByPointer(NextProcess, + PROCESS_ALL_ACCESS, + PsProcessType, + KernelMode); + if (!NT_SUCCESS(Status)) + { + CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n"); + KeBugCheck(0); + } + ObDereferenceObject(OldProcess); + + return(NextProcess); +} + + +NTSTATUS STDCALL +_NtOpenProcessToken(IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle) +{ + PACCESS_TOKEN Token; + NTSTATUS Status; + + Status = PsOpenTokenOfProcess(ProcessHandle, + &Token); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Status = ObCreateHandle(PsGetCurrentProcess(), + Token, + DesiredAccess, + FALSE, + TokenHandle); + ObDereferenceObject(Token); + return(Status); +} + + +NTSTATUS STDCALL +NtOpenProcessToken(IN HANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE TokenHandle) +{ + return _NtOpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle); +} + + +PACCESS_TOKEN STDCALL +PsReferencePrimaryToken(PEPROCESS Process) +{ + ObReferenceObjectByPointer(Process->Token, + TOKEN_ALL_ACCESS, + SepTokenObjectType, + UserMode); + return(Process->Token); +} + + +NTSTATUS +PsOpenTokenOfProcess(HANDLE ProcessHandle, + PACCESS_TOKEN* Token) +{ + PEPROCESS Process; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_QUERY_INFORMATION, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + *Token = PsReferencePrimaryToken(Process); + ObDereferenceObject(Process); + return(STATUS_SUCCESS); +} + + +VOID +PiKillMostProcesses(VOID) +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PEPROCESS current; + + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + + current_entry = PsProcessListHead.Flink; + while (current_entry != &PsProcessListHead) + { + current = CONTAINING_RECORD(current_entry, EPROCESS, + ProcessListEntry); + current_entry = current_entry->Flink; + + if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId && + current->UniqueProcessId != (ULONG)PsGetCurrentProcessId()) + { + PiTerminateProcessThreads(current, STATUS_SUCCESS); + } + } + + KeReleaseSpinLock(&PsProcessListLock, oldIrql); +} + + +VOID +PsInitProcessManagment(VOID) +{ + PKPROCESS KProcess; + KIRQL oldIrql; + NTSTATUS Status; + + /* + * Register the process object type + */ + + PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + PsProcessType->Tag = TAG('P', 'R', 'O', 'C'); + PsProcessType->TotalObjects = 0; + PsProcessType->TotalHandles = 0; + PsProcessType->MaxObjects = ULONG_MAX; + PsProcessType->MaxHandles = ULONG_MAX; + PsProcessType->PagedPoolCharge = 0; + PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS); + PsProcessType->Mapping = &PiProcessMapping; + PsProcessType->Dump = NULL; + PsProcessType->Open = NULL; + PsProcessType->Close = NULL; + PsProcessType->Delete = PiDeleteProcess; + PsProcessType->Parse = NULL; + PsProcessType->Security = NULL; + PsProcessType->QueryName = NULL; + PsProcessType->OkayToClose = NULL; + PsProcessType->Create = NULL; + PsProcessType->DuplicationNotify = NULL; + + RtlInitUnicodeStringFromLiteral(&PsProcessType->TypeName, L"Process"); + + InitializeListHead(&PsProcessListHead); + KeInitializeSpinLock(&PsProcessListLock); + + /* + * Initialize the system process + */ + Status = ObCreateObject(NULL, + PROCESS_ALL_ACCESS, + NULL, + PsProcessType, + (PVOID*)&PsInitialSystemProcess); + if (!NT_SUCCESS(Status)) + { + return; + } + + /* System threads may run on any processor. */ + PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF; + PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL; + KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader, + InternalProcessType, + sizeof(EPROCESS), + FALSE); + KProcess = &PsInitialSystemProcess->Pcb; + + MmInitializeAddressSpace(PsInitialSystemProcess, + &PsInitialSystemProcess->AddressSpace); + ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess); + KProcess->DirectoryTableBase = + (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory(); + PsInitialSystemProcess->UniqueProcessId = + InterlockedIncrement(&PiNextProcessUniqueId); + PsInitialSystemProcess->Win32WindowStation = (HANDLE)0; + PsInitialSystemProcess->Win32Desktop = (HANDLE)0; + + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + InsertHeadList(&PsProcessListHead, + &PsInitialSystemProcess->ProcessListEntry); + InitializeListHead(&PsInitialSystemProcess->ThreadListHead); + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + + strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM"); + + SepCreateSystemProcessToken(PsInitialSystemProcess); + + ObCreateHandle(PsInitialSystemProcess, + PsInitialSystemProcess, + PROCESS_ALL_ACCESS, + FALSE, + &SystemProcessHandle); +} + +VOID STDCALL +PiDeleteProcess(PVOID ObjectBody) +{ + KIRQL oldIrql; + PEPROCESS Process; + ULONG i; + + DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody); + + Process = (PEPROCESS)ObjectBody; + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + for (i = 0; i < PiProcessNotifyRoutineCount; i++) + { + PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId, + (HANDLE)Process->UniqueProcessId, + FALSE); + } + RemoveEntryList(&Process->ProcessListEntry); + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + + /* KDB hook */ + KDB_DELETEPROCESS_HOOK(Process->Peb); + + ObDereferenceObject(Process->Token); + + (VOID)MmReleaseMmInfo(Process); + ObDeleteHandleTable(Process); +} + + +static NTSTATUS +PsCreatePeb(HANDLE ProcessHandle, + PVOID ImageBase, + PVOID* RPeb) +{ + NTSTATUS Status; + PVOID PebBase; + ULONG PebSize; + PEB Peb; + ULONG BytesWritten; + + memset(&Peb, 0, sizeof(Peb)); + Peb.ImageBaseAddress = ImageBase; + + PebBase = (PVOID)PEB_BASE; + PebSize = 0x1000; + Status = NtAllocateVirtualMemory(ProcessHandle, + &PebBase, + 0, + &PebSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + NtWriteVirtualMemory(ProcessHandle, + (PVOID)PEB_BASE, + &Peb, + sizeof(Peb), + &BytesWritten); + + DPRINT("PsCreatePeb: Peb created at %x\n", PebBase); + + *RPeb = PebBase; + + return(STATUS_SUCCESS); +} + + +PKPROCESS +KeGetCurrentProcess(VOID) +/* + * FUNCTION: Returns a pointer to the current process + */ +{ + return(&(PsGetCurrentProcess()->Pcb)); +} + +HANDLE STDCALL +PsGetCurrentProcessId(VOID) +{ + return((HANDLE)PsGetCurrentProcess()->UniqueProcessId); +} + +/* + * FUNCTION: Returns a pointer to the current process + */ +PEPROCESS STDCALL +PsGetCurrentProcess(VOID) +{ + if (PsGetCurrentThread() == NULL || + PsGetCurrentThread()->ThreadsProcess == NULL) + { + return(PsInitialSystemProcess); + } + else + { + return(PsGetCurrentThread()->ThreadsProcess); + } +} + +PEPROCESS STDCALL +IoGetCurrentProcess(VOID) +{ + return(PsGetCurrentProcess()); +} + +NTSTATUS STDCALL +PsCreateSystemProcess(PHANDLE ProcessHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) +{ + return NtCreateProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + SystemProcessHandle, + FALSE, + NULL, + NULL, + NULL); +} + +NTSTATUS STDCALL +NtCreateProcess(OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcessHandle, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPortHandle OPTIONAL, + IN HANDLE ExceptionPortHandle OPTIONAL) +/* + * FUNCTION: Creates a process. + * ARGUMENTS: + * ProcessHandle (OUT) = Caller supplied storage for the resulting + * handle + * DesiredAccess = Specifies the allowed or desired access to the + * process can be a combination of + * STANDARD_RIGHTS_REQUIRED| .. + * ObjectAttribute = Initialized attributes for the object, contains + * the rootdirectory and the filename + * ParentProcess = Handle to the parent process. + * InheritObjectTable = Specifies to inherit the objects of the parent + * process if true. + * SectionHandle = Handle to a section object to back the image file + * DebugPort = Handle to a DebugPort if NULL the system default debug + * port will be used. + * ExceptionPort = Handle to a exception port. + * REMARKS: + * This function maps to the win32 CreateProcess. + * RETURNS: Status + */ +{ + PEPROCESS Process; + PEPROCESS ParentProcess; + PKPROCESS KProcess; + NTSTATUS Status; + KIRQL oldIrql; + PVOID LdrStartupAddr; + PVOID ImageBase; + PVOID Peb; + PEPORT DebugPort; + PEPORT ExceptionPort; + PVOID BaseAddress; + PMEMORY_AREA MemoryArea; + ULONG i; + + DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes); + + Status = ObReferenceObjectByHandle(ParentProcessHandle, + PROCESS_CREATE_PROCESS, + PsProcessType, + ExGetPreviousMode(), + (PVOID*)&ParentProcess, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("NtCreateProcess() = %x\n",Status); + return(Status); + } + + Status = ObCreateObject(ProcessHandle, + DesiredAccess, + ObjectAttributes, + PsProcessType, + (PVOID*)&Process); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(ParentProcess); + DPRINT("ObCreateObject() = %x\n",Status); + return(Status); + } + + KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader, + InternalProcessType, + sizeof(EPROCESS), + FALSE); + KProcess = &Process->Pcb; + /* Inherit parent process's affinity. */ + KProcess->Affinity = ParentProcess->Pcb.Affinity; + KProcess->BasePriority = PROCESS_PRIO_NORMAL; + MmInitializeAddressSpace(Process, + &Process->AddressSpace); + Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId); + Process->InheritedFromUniqueProcessId = + (HANDLE)ParentProcess->UniqueProcessId; + ObCreateHandleTable(ParentProcess, + InheritObjectTable, + Process); + MmCopyMmInfo(ParentProcess, Process); + if (ParentProcess->Win32WindowStation != (HANDLE)0) + { + /* Always duplicate the process window station. */ + Process->Win32WindowStation = 0; + Status = ObDuplicateObject(ParentProcess, + Process, + ParentProcess->Win32WindowStation, + &Process->Win32WindowStation, + 0, + FALSE, + DUPLICATE_SAME_ACCESS); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + else + { + Process->Win32WindowStation = (HANDLE)0; + } + if (ParentProcess->Win32Desktop != (HANDLE)0) + { + /* Always duplicate the process window station. */ + Process->Win32Desktop = 0; + Status = ObDuplicateObject(ParentProcess, + Process, + ParentProcess->Win32Desktop, + &Process->Win32Desktop, + 0, + FALSE, + DUPLICATE_SAME_ACCESS); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + else + { + Process->Win32Desktop = (HANDLE)0; + } + + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + for (i = 0; i < PiProcessNotifyRoutineCount; i++) + { + PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId, + (HANDLE)Process->UniqueProcessId, + TRUE); + } + InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry); + InitializeListHead(&Process->ThreadListHead); + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + + Process->Pcb.State = PROCESS_STATE_ACTIVE; + + /* + * Add the debug port + */ + if (DebugPortHandle != NULL) + { + Status = ObReferenceObjectByHandle(DebugPortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&DebugPort, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + ZwClose(*ProcessHandle); + *ProcessHandle = NULL; + return(Status); + } + Process->DebugPort = DebugPort; + } + + /* + * Add the exception port + */ + if (ExceptionPortHandle != NULL) + { + Status = ObReferenceObjectByHandle(ExceptionPortHandle, + PORT_ALL_ACCESS, + ExPortType, + UserMode, + (PVOID*)&ExceptionPort, + NULL); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + ZwClose(*ProcessHandle); + *ProcessHandle = NULL; + return(Status); + } + Process->ExceptionPort = ExceptionPort; + } + + /* + * Now we have created the process proper + */ + + /* + * Create the shared data page + */ + MmLockAddressSpace(&Process->AddressSpace); + BaseAddress = (PVOID)USER_SHARED_DATA; + Status = MmCreateMemoryArea(Process, + &Process->AddressSpace, + MEMORY_AREA_SHARED_DATA, + &BaseAddress, + PAGE_SIZE, + PAGE_READONLY, + &MemoryArea, + FALSE); + MmUnlockAddressSpace(&Process->AddressSpace); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create shared data page\n"); + KeBugCheck(0); + } + + /* + * Map ntdll + */ + Status = LdrpMapSystemDll(*ProcessHandle, + &LdrStartupAddr); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status); + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + return(Status); + } + + /* + * Map the process image + */ + if (SectionHandle != NULL) + { + DPRINT("Mapping process image\n"); + Status = LdrpMapImage(*ProcessHandle, + SectionHandle, + &ImageBase); + if (!NT_SUCCESS(Status)) + { + DbgPrint("LdrpMapImage failed (Status %x)\n", Status); + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + return(Status); + } + } + else + { + ImageBase = NULL; + } + + /* + * Duplicate the token + */ + Status = SepInitializeNewProcess(Process, ParentProcess); + if (!NT_SUCCESS(Status)) + { + DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status); + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + return(Status); + } + + /* + * + */ + DPRINT("Creating PEB\n"); + Status = PsCreatePeb(*ProcessHandle, + ImageBase, + &Peb); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status); + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + ZwClose(*ProcessHandle); + *ProcessHandle = NULL; + return(Status); + } + Process->Peb = Peb; + + /* + * Maybe send a message to the creator process's debugger + */ +#if 0 + if (ParentProcess->DebugPort != NULL) + { + LPC_DBG_MESSAGE Message; + HANDLE FileHandle; + + ObCreateHandle(NULL, // Debugger Process + NULL, // SectionHandle + FILE_ALL_ACCESS, + FALSE, + &FileHandle); + + Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE); + Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) - + sizeof(LPC_MESSAGE_HEADER); + Message.Type = DBG_EVENT_CREATE_PROCESS; + Message.Data.CreateProcess.FileHandle = FileHandle; + Message.Data.CreateProcess.Base = ImageBase; + Message.Data.CreateProcess.EntryPoint = NULL; // + + Status = LpcSendDebugMessagePort(ParentProcess->DebugPort, + &Message); + } +#endif + + ObDereferenceObject(Process); + ObDereferenceObject(ParentProcess); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtOpenProcess(OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) +{ + DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, " + "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n", + ProcessHandle, DesiredAccess, ObjectAttributes, ClientId, + ClientId->UniqueProcess, ClientId->UniqueThread); + + + /* + * Not sure of the exact semantics + */ + if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL && + ObjectAttributes->ObjectName->Buffer != NULL) + { + NTSTATUS Status; + PEPROCESS Process; + + Status = ObReferenceObjectByName(ObjectAttributes->ObjectName, + ObjectAttributes->Attributes, + NULL, + DesiredAccess, + PsProcessType, + UserMode, + NULL, + (PVOID*)&Process); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + Status = ObCreateHandle(PsGetCurrentProcess(), + Process, + DesiredAccess, + FALSE, + ProcessHandle); + ObDereferenceObject(Process); + + return(Status); + } + else + { + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PEPROCESS current; + NTSTATUS Status; + + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + current_entry = PsProcessListHead.Flink; + while (current_entry != &PsProcessListHead) + { + current = CONTAINING_RECORD(current_entry, EPROCESS, + ProcessListEntry); + if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess) + { + ObReferenceObjectByPointer(current, + DesiredAccess, + PsProcessType, + UserMode); + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + Status = ObCreateHandle(PsGetCurrentProcess(), + current, + DesiredAccess, + FALSE, + ProcessHandle); + ObDereferenceObject(current); + DPRINT("*ProcessHandle %x\n", ProcessHandle); + DPRINT("NtOpenProcess() = %x\n", Status); + return(Status); + } + current_entry = current_entry->Flink; + } + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n"); + return(STATUS_UNSUCCESSFUL); + } + return(STATUS_UNSUCCESSFUL); +} + + +NTSTATUS STDCALL +NtQueryInformationProcess(IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength) +{ + PEPROCESS Process; + NTSTATUS Status; + PPROCESS_BASIC_INFORMATION ProcessBasicInformationP; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_SET_INFORMATION, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + switch (ProcessInformationClass) + { + case ProcessBasicInformation: + ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION) + ProcessInformation; + ProcessBasicInformationP->ExitStatus = Process->ExitStatus; + ProcessBasicInformationP->PebBaseAddress = Process->Peb; + ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity; + ProcessBasicInformationP->UniqueProcessId = + Process->UniqueProcessId; + ProcessBasicInformationP->InheritedFromUniqueProcessId = + (ULONG)Process->InheritedFromUniqueProcessId; + Status = STATUS_SUCCESS; + break; + + case ProcessQuotaLimits: + case ProcessIoCounters: + case ProcessVmCounters: + case ProcessTimes: + case ProcessDebugPort: + case ProcessLdtInformation: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessDefaultHardErrorMode: + *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing; + break; + + case ProcessWorkingSetWatch: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessWx86Information: + case ProcessHandleCount: + case ProcessPriorityBoost: + case ProcessDeviceMap: + case ProcessSessionInformation: + case ProcessWow64Information: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessBasePriority: + case ProcessRaisePriority: + case ProcessExceptionPort: + case ProcessAccessToken: + case ProcessLdtSize: + case ProcessIoPortHandlers: + case ProcessUserModeIOPL: + case ProcessEnableAlignmentFaultFixup: + case ProcessPriorityClass: + case ProcessAffinityMask: + case ProcessForegroundInformation: + default: + Status = STATUS_INVALID_INFO_CLASS; + } + ObDereferenceObject(Process); + return(Status); +} + +NTSTATUS +PspAssignPrimaryToken(PEPROCESS Process, + HANDLE TokenHandle) +{ + PACCESS_TOKEN Token; + PACCESS_TOKEN OldToken; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(TokenHandle, + 0, + SepTokenObjectType, + UserMode, + (PVOID*)&Token, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + Status = SeExchangePrimaryToken(Process, Token, &OldToken); + if (NT_SUCCESS(Status)) + { + ObDereferenceObject(OldToken); + } + ObDereferenceObject(Token); + return(Status); +} + +NTSTATUS STDCALL +NtSetInformationProcess(IN HANDLE ProcessHandle, + IN CINT ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength) +{ + PEPROCESS Process; + NTSTATUS Status; + PHANDLE ProcessAccessTokenP; + + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_SET_INFORMATION, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + switch (ProcessInformationClass) + { + case ProcessQuotaLimits: + case ProcessBasePriority: + case ProcessRaisePriority: + case ProcessDebugPort: + case ProcessExceptionPort: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessAccessToken: + ProcessAccessTokenP = (PHANDLE)ProcessInformation; + Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP); + break; + + case ProcessImageFileName: + memcpy(Process->ImageFileName, ProcessInformation, 8); + Status = STATUS_SUCCESS; + break; + + case ProcessLdtInformation: + case ProcessLdtSize: + case ProcessDefaultHardErrorMode: + case ProcessIoPortHandlers: + case ProcessWorkingSetWatch: + case ProcessUserModeIOPL: + case ProcessEnableAlignmentFaultFixup: + case ProcessPriorityClass: + case ProcessAffinityMask: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ProcessBasicInformation: + case ProcessIoCounters: + case ProcessVmCounters: + case ProcessTimes: + case ProcessPooledUsageAndLimits: + case ProcessWx86Information: + case ProcessHandleCount: + case ProcessWow64Information: + default: + Status = STATUS_INVALID_INFO_CLASS; + + case ProcessDesktop: + Process->Win32Desktop = *(PHANDLE)ProcessInformation; + Status = STATUS_SUCCESS; + break; + } + ObDereferenceObject(Process); + return(Status); +} + + +/********************************************************************** + * NAME INTERNAL + * PiQuerySystemProcessInformation + * + * DESCRIPTION + * Compute the size of a process+thread snapshot as + * expected by NtQuerySystemInformation. + * + * RETURN VALUE + * 0 on error; otherwise the size, in bytes of the buffer + * required to write a full snapshot. + * + * NOTE + * We assume (sizeof (PVOID) == sizeof (ULONG)) holds. + */ +NTSTATUS +PiQuerySystemProcessInformation(PVOID Buffer, + ULONG Size, + PULONG ReqSize) +{ + return STATUS_NOT_IMPLEMENTED; + +#if 0 + KIRQL OldIrql; + PLIST_ENTRY CurrentEntryP; + PEPROCESS CurrentP; + PLIST_ENTRY CurrentEntryT; + PETHREAD CurrentT; + + ULONG RequiredSize = 0L; + BOOLEAN SizeOnly = FALSE; + + ULONG SpiSize = 0L; + + PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer; + PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL; + PSYSTEM_THREAD_INFO pInfoT = NULL; + + + /* Lock the process list. */ + KeAcquireSpinLock(&PsProcessListLock, + &OldIrql); + + /* + * Scan the process list. Since the + * list is circular, the guard is false + * after the last process. + */ + for ( CurrentEntryP = PsProcessListHead.Flink; + (CurrentEntryP != & PsProcessListHead); + CurrentEntryP = CurrentEntryP->Flink + ) + { + /* + * Compute how much space is + * occupied in the snapshot + * by adding this process info. + * (at least one thread). + */ + SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION); + RequiredSize += SpiSizeCurrent; + /* + * Do not write process data in the + * buffer if it is too small. + */ + if (TRUE == SizeOnly) continue; + /* + * Check if the buffer can contain + * the full snapshot. + */ + if (Size < RequiredSize) + { + SizeOnly = TRUE; + continue; + } + /* + * Get a reference to the + * process descriptor we are + * handling. + */ + CurrentP = CONTAINING_RECORD( + CurrentEntryP, + EPROCESS, + ProcessListEntry + ); + /* + * Write process data in the buffer. + */ + RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION)); + /* PROCESS */ + pInfoP->ThreadCount = 0L; + pInfoP->ProcessId = CurrentP->UniqueProcessId; + RtlInitUnicodeString ( + & pInfoP->Name, + CurrentP->ImageFileName + ); + /* THREAD */ + for ( pInfoT = & CurrentP->ThreadSysInfo [0], + CurrentEntryT = CurrentP->ThreadListHead.Flink; + + (CurrentEntryT != & CurrentP->ThreadListHead); + + pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount], + CurrentEntryT = CurrentEntryT->Flink + ) + { + /* + * Recalculate the size of the + * information block. + */ + if (0 < pInfoP->ThreadCount) + { + RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION); + } + /* + * Do not write thread data in the + * buffer if it is too small. + */ + if (TRUE == SizeOnly) continue; + /* + * Check if the buffer can contain + * the full snapshot. + */ + if (Size < RequiredSize) + { + SizeOnly = TRUE; + continue; + } + /* + * Get a reference to the + * thread descriptor we are + * handling. + */ + CurrentT = CONTAINING_RECORD( + CurrentEntryT, + KTHREAD, + Tcb.ThreadListEntry + ); + /* + * Write thread data. + */ + RtlZeroMemory ( + pInfoT, + sizeof (SYSTEM_THREAD_INFORMATION) + ); + pInfoT->KernelTime = CurrentT-> ; /* TIME */ + pInfoT->UserTime = CurrentT-> ; /* TIME */ + pInfoT->CreateTime = CurrentT-> ; /* TIME */ + pInfoT->TickCount = CurrentT-> ; /* ULONG */ + pInfoT->StartEIP = CurrentT-> ; /* ULONG */ + pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */ + pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */ + pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */ + pInfoT->BasePriority = CurrentT-> ; /* ULONG */ + pInfoT->nSwitches = CurrentT-> ; /* ULONG */ + pInfoT->State = CurrentT-> ; /* DWORD */ + pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */ + /* + * Count the number of threads + * this process has. + */ + ++ pInfoP->ThreadCount; + } + /* + * Save the size of information + * stored in the buffer for the + * current process. + */ + pInfoP->RelativeOffset = SpiSize; + /* + * Save a reference to the last + * valid information block. + */ + pInfoPLast = pInfoP; + /* + * Compute the offset of the + * SYSTEM_PROCESS_INFORMATION + * descriptor in the snapshot + * buffer for the next process. + */ + (ULONG) pInfoP += SpiSize; + } + /* + * Unlock the process list. + */ + KeReleaseSpinLock ( + & PsProcessListLock, + OldIrql + ); + /* + * Return the proper error status code, + * if the buffer was too small. + */ + if (TRUE == SizeOnly) + { + if (NULL != RequiredSize) + { + *pRequiredSize = RequiredSize; + } + return STATUS_INFO_LENGTH_MISMATCH; + } + /* + * Mark the end of the snapshot. + */ + pInfoP->RelativeOffset = 0L; + /* OK */ + return STATUS_SUCCESS; +#endif +} + +LARGE_INTEGER STDCALL +PsGetProcessExitTime(VOID) +{ + LARGE_INTEGER Li; + Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart; + return Li; +} + +BOOLEAN STDCALL +PsIsThreadTerminating(IN PETHREAD Thread) +{ + return(Thread->DeadThread); +} + + +NTSTATUS STDCALL +PsLookupProcessByProcessId(IN PVOID ProcessId, + OUT PEPROCESS *Process) +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PEPROCESS current; + + KeAcquireSpinLock(&PsProcessListLock, &oldIrql); + + current_entry = PsProcessListHead.Flink; + while (current_entry != &PsProcessListHead) + { + current = CONTAINING_RECORD(current_entry, + EPROCESS, + ProcessListEntry); + if (current->UniqueProcessId == (ULONG)ProcessId) + { + *Process = current; + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + return(STATUS_SUCCESS); + } + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&PsProcessListLock, oldIrql); + + return(STATUS_INVALID_PARAMETER); +} + + +NTSTATUS STDCALL +PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, + IN BOOLEAN Remove) +{ + if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT) + return(STATUS_INSUFFICIENT_RESOURCES); + + PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine; + PiProcessNotifyRoutineCount++; + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/ps/psmgr.c b/ntoskrnl/ps/psmgr.c new file mode 100644 index 0000000..31df57b --- /dev/null +++ b/ntoskrnl/ps/psmgr.c @@ -0,0 +1,102 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/psmgr.c + * PURPOSE: Process management + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES **************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +VOID PiShutdownProcessManager(VOID) +{ + DPRINT("PiShutdownMemoryManager()\n"); + + PiKillMostProcesses(); +} + +VOID PiInitProcessManager(VOID) +{ + PsInitProcessManagment(); + PsInitThreadManagment(); + PsInitIdleThread(); + PiInitApcManagement(); + PsInitialiseSuspendImplementation(); +} + + +/********************************************************************** + * NAME EXPORTED + * PsGetVersion + * + * DESCRIPTION + * Retrieves the current OS version. + * + * ARGUMENTS + * MajorVersion Pointer to a variable that will be set to the + * major version of the OS. Can be NULL. + * + * MinorVersion Pointer to a variable that will be set to the + * minor version of the OS. Can be NULL. + * + * BuildNumber Pointer to a variable that will be set to the + * build number of the OS. Can be NULL. + * + * CSDVersion Pointer to a variable that will be set to the + * CSD string of the OS. Can be NULL. + * + * RETURN VALUE + * TRUE OS is a checked build. + * FALSE OS is a free build. + * + * NOTES + * The DDK docs say something about a 'CmCSDVersionString'. + * How do we determine in the build is checked or free?? + */ + +BOOLEAN +STDCALL +PsGetVersion ( + PULONG MajorVersion OPTIONAL, + PULONG MinorVersion OPTIONAL, + PULONG BuildNumber OPTIONAL, + PUNICODE_STRING CSDVersion OPTIONAL + ) +{ + if (MajorVersion) + *MajorVersion = KERNEL_VERSION_MAJOR; + + if (MinorVersion) + *MinorVersion = KERNEL_VERSION_MINOR; + + if (BuildNumber) + *BuildNumber = NtBuildNumber; + + if (CSDVersion) + { + CSDVersion->Length = 0; + CSDVersion->MaximumLength = 0; + CSDVersion->Buffer = NULL; +#if 0 + CSDVersion->Length = CmCSDVersionString.Length; + CSDVersion->MaximumLength = CmCSDVersionString.Maximum; + CSDVersion->Buffer = CmCSDVersionString.Buffer; +#endif + } + + /* FIXME: How do we determine if build is checked or free? */ + return FALSE; +} + +/* EOF */ diff --git a/ntoskrnl/ps/suspend.c b/ntoskrnl/ps/suspend.c new file mode 100644 index 0000000..1b97343 --- /dev/null +++ b/ntoskrnl/ps/suspend.c @@ -0,0 +1,217 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/suspend.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* NOTES ********************************************************************** + * + */ + +/* GLOBALS *******************************************************************/ + +static FAST_MUTEX SuspendMutex; + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +PiSuspendThreadRundownRoutine(PKAPC Apc) +{ +} + + +VOID STDCALL +PiSuspendThreadKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2) +{ +} + + +VOID STDCALL +PiSuspendThreadNormalRoutine(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PETHREAD CurrentThread = PsGetCurrentThread(); + while (CurrentThread->Tcb.SuspendCount > 0) + { + KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore, + 0, + UserMode, + TRUE, + NULL); + } +} + + +NTSTATUS +PsResumeThread(PETHREAD Thread, PULONG SuspendCount) +{ + ExAcquireFastMutex(&SuspendMutex); + if (SuspendCount != NULL) + { + *SuspendCount = Thread->Tcb.SuspendCount; + } + if (Thread->Tcb.SuspendCount > 0) + { + Thread->Tcb.SuspendCount--; + if (Thread->Tcb.SuspendCount == 0) + { + KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, + 1, FALSE); + } + } + ExReleaseFastMutex(&SuspendMutex); + return(STATUS_SUCCESS); +} + + +NTSTATUS +PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount) +{ + ULONG OldValue; + + ExAcquireFastMutex(&SuspendMutex); + OldValue = Thread->Tcb.SuspendCount; + Thread->Tcb.SuspendCount++; + if (!Thread->Tcb.SuspendApc.Inserted) + { + KeInsertQueueApc(&Thread->Tcb.SuspendApc, + NULL, + NULL, + 0); + } + ExReleaseFastMutex(&SuspendMutex); + if (PreviousSuspendCount != NULL) + { + *PreviousSuspendCount = OldValue; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtResumeThread(IN HANDLE ThreadHandle, + IN PULONG SuspendCount) +/* + * FUNCTION: Decrements a thread's resume count + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * ResumeCount = The resulting resume count. + * RETURNS: Status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + ULONG Count; + + DPRINT("NtResumeThead(ThreadHandle %lx SuspendCount %p)\n", + ThreadHandle, SuspendCount); + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = PsResumeThread(Thread, &Count); + if (SuspendCount != NULL) + { + *SuspendCount = Count; + } + + ObDereferenceObject((PVOID)Thread); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtSuspendThread(IN HANDLE ThreadHandle, + IN PULONG PreviousSuspendCount) +/* + * FUNCTION: Increments a thread's suspend count + * ARGUMENTS: + * ThreadHandle = Handle to the thread that should be resumed + * PreviousSuspendCount = The resulting/previous suspend count. + * REMARK: + * A thread will be suspended if its suspend count is greater than 0. + * This procedure maps to the win32 SuspendThread function. ( + * documentation about the the suspend count can be found here aswell ) + * The suspend count is not increased if it is greater than + * MAXIMUM_SUSPEND_COUNT. + * RETURNS: Status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + ULONG Count; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = PsSuspendThread(Thread, &Count); + if (PreviousSuspendCount != NULL) + { + *PreviousSuspendCount = Count; + } + + ObDereferenceObject((PVOID)Thread); + + return(STATUS_SUCCESS); +} + +VOID +PsInitialiseSuspendImplementation(VOID) +{ + ExInitializeFastMutex(&SuspendMutex); +} + +/* EOF */ diff --git a/ntoskrnl/ps/thread.c b/ntoskrnl/ps/thread.c new file mode 100644 index 0000000..c4da6f3 --- /dev/null +++ b/ntoskrnl/ps/thread.c @@ -0,0 +1,650 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/thread.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Created + * 12/10/99: Phillip Susi: Thread priorities, and APC work + */ + +/* + * NOTE: + * + * All of the routines that manipulate the thread queue synchronize on + * a single spinlock + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +/* GLOBALS ******************************************************************/ + +POBJECT_TYPE EXPORTED PsThreadType = NULL; + +KSPIN_LOCK PiThreadListLock; + +/* + * PURPOSE: List of threads associated with each priority level + */ +LIST_ENTRY PiThreadListHead; +static LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY]; +static BOOLEAN DoneInitYet = FALSE; +static PETHREAD IdleThreads[MAXIMUM_PROCESSORS]; +ULONG PiNrThreads = 0; +ULONG PiNrReadyThreads = 0; +static HANDLE PiReaperThreadHandle; +static KEVENT PiReaperThreadEvent; +static BOOL PiReaperThreadShouldTerminate = FALSE; +ULONG PiNrThreadsAwaitingReaping = 0; + +static GENERIC_MAPPING PiThreadMapping = {THREAD_READ, + THREAD_WRITE, + THREAD_EXECUTE, + THREAD_ALL_ACCESS}; + +/* FUNCTIONS ***************************************************************/ + +PKTHREAD STDCALL KeGetCurrentThread(VOID) +{ + return(KeGetCurrentKPCR()->CurrentThread); +} + +PETHREAD STDCALL PsGetCurrentThread(VOID) +{ + PKTHREAD CurrentThread = KeGetCurrentKPCR()->CurrentThread; + return(CONTAINING_RECORD(CurrentThread, ETHREAD, Tcb)); +} + +HANDLE STDCALL PsGetCurrentThreadId(VOID) +{ + return(PsGetCurrentThread()->Cid.UniqueThread); +} + +VOID +PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread) +{ + if (Priority >= MAXIMUM_PRIORITY || Priority < 0) + { + DPRINT1("Invalid thread priority\n"); + KeBugCheck(0); + } + InsertTailList(&PriorityListHead[Priority], &Thread->Tcb.QueueListEntry); + PiNrReadyThreads++; +} + +VOID PsDumpThreads(BOOLEAN IncludeSystem) +{ + PLIST_ENTRY current_entry; + PETHREAD current; + ULONG t; + ULONG i; + + current_entry = PiThreadListHead.Flink; + t = 0; + + while (current_entry != &PiThreadListHead) + { + PULONG Ebp; + PULONG Esp; + + current = CONTAINING_RECORD(current_entry, ETHREAD, + Tcb.ThreadListEntry); + t++; + if (t > PiNrThreads) + { + DbgPrint("Too many threads on list\n"); + return; + } + if (IncludeSystem || current->ThreadsProcess->UniqueProcessId >= 6) + { + DbgPrint("current->Tcb.State %d PID.TID %d.%d Name %.8s Stack: \n", + current->Tcb.State, + current->ThreadsProcess->UniqueProcessId, + current->Cid.UniqueThread, + current->ThreadsProcess->ImageFileName); + if (current->Tcb.State == THREAD_STATE_READY || + current->Tcb.State == THREAD_STATE_SUSPENDED || + current->Tcb.State == THREAD_STATE_BLOCKED) + { + Esp = (PULONG)current->Tcb.KernelStack; + Ebp = (PULONG)Esp[3]; + DbgPrint("Ebp 0x%.8X\n", Ebp); + i = 0; + while (Ebp != 0 && Ebp >= (PULONG)current->Tcb.StackLimit) + { + DbgPrint("%.8X %.8X%s", Ebp[0], Ebp[1], + (i % 8) == 7 ? "\n" : " "); + Ebp = (PULONG)Ebp[0]; + i++; + } + if ((i % 8) != 7) + { + DbgPrint("\n"); + } + } + } + current_entry = current_entry->Flink; + } +} + +static PETHREAD PsScanThreadList (KPRIORITY Priority, ULONG Affinity) +{ + PLIST_ENTRY current_entry; + PETHREAD current; + + current_entry = PriorityListHead[Priority].Flink; + while (current_entry != &PriorityListHead[Priority]) + { + current = CONTAINING_RECORD(current_entry, ETHREAD, + Tcb.QueueListEntry); + assert(current->Tcb.State == THREAD_STATE_READY); + DPRINT("current->Tcb.UserAffinity %x Affinity %x PID %d %d\n", + current->Tcb.UserAffinity, Affinity, current->Cid.UniqueThread, + Priority); + if (current->Tcb.UserAffinity & Affinity) + { + RemoveEntryList(¤t->Tcb.QueueListEntry); + return(current); + } + current_entry = current_entry->Flink; + } + return(NULL); +} + +VOID STDCALL +PiWakeupReaperThread(VOID) +{ + KeSetEvent(&PiReaperThreadEvent, 0, FALSE); +} + +NTSTATUS STDCALL +PiReaperThreadMain(PVOID Ignored) +{ + while (1) + { + KeWaitForSingleObject(&PiReaperThreadEvent, + Executive, + KernelMode, + FALSE, + NULL); + if (PiReaperThreadShouldTerminate) + { + PsTerminateSystemThread(0); + } + PsReapThreads(); + } +} + +VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) +{ + KPRIORITY CurrentPriority; + PETHREAD Candidate; + ULONG Affinity; + PKTHREAD KCurrentThread = KeGetCurrentKPCR()->CurrentThread; + PETHREAD CurrentThread = CONTAINING_RECORD(KCurrentThread, ETHREAD, Tcb); + + DPRINT("PsDispatchThread() %d/%d\n", KeGetCurrentProcessorNumber(), + CurrentThread->Cid.UniqueThread); + + CurrentThread->Tcb.State = NewThreadStatus; + if (CurrentThread->Tcb.State == THREAD_STATE_READY) + { + PiNrReadyThreads++; + PsInsertIntoThreadList(CurrentThread->Tcb.Priority, + CurrentThread); + } + if (CurrentThread->Tcb.State == THREAD_STATE_TERMINATED_1) + { + PiNrThreadsAwaitingReaping++; + } + + Affinity = 1 << KeGetCurrentProcessorNumber(); + for (CurrentPriority = HIGH_PRIORITY; + CurrentPriority >= LOW_PRIORITY; + CurrentPriority--) + { + Candidate = PsScanThreadList(CurrentPriority, Affinity); + if (Candidate == CurrentThread) + { + KeReleaseSpinLockFromDpcLevel(&PiThreadListLock); + return; + } + if (Candidate != NULL) + { + PETHREAD OldThread; + + DPRINT("Scheduling %x(%d)\n",Candidate, CurrentPriority); + + Candidate->Tcb.State = THREAD_STATE_RUNNING; + + OldThread = CurrentThread; + CurrentThread = Candidate; + + KeReleaseSpinLockFromDpcLevel(&PiThreadListLock); + if (PiNrThreadsAwaitingReaping > 0) + { + PiWakeupReaperThread(); + } + KiArchContextSwitch(&CurrentThread->Tcb, &OldThread->Tcb); + return; + } + } + CPRINT("CRITICAL: No threads are ready\n"); + KeBugCheck(0); +} + +VOID STDCALL +PsDispatchThread(ULONG NewThreadStatus) +{ + KIRQL oldIrql; + + if (!DoneInitYet) + { + return; + } + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + /* + * Save wait IRQL + */ + KeGetCurrentKPCR()->CurrentThread->WaitIrql = oldIrql; + PsDispatchThreadNoLock(NewThreadStatus); + KeLowerIrql(oldIrql); +} + +VOID +PsUnblockThread(PETHREAD Thread, PNTSTATUS WaitStatus) +{ + KIRQL oldIrql; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + if (WaitStatus != NULL) + { + Thread->Tcb.WaitStatus = *WaitStatus; + } + Thread->Tcb.State = THREAD_STATE_READY; + PsInsertIntoThreadList(Thread->Tcb.Priority, Thread); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); +} + +VOID +PsBlockThread(PNTSTATUS Status, UCHAR Alertable, ULONG WaitMode, + BOOLEAN DispatcherLock, KIRQL WaitIrql) +{ + KIRQL oldIrql; + PKTHREAD KThread = KeGetCurrentKPCR()->CurrentThread; + PETHREAD Thread = CONTAINING_RECORD (KThread, ETHREAD, Tcb); + PKWAIT_BLOCK WaitBlock; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + if (KThread->ApcState.KernelApcPending) + { + if (!DispatcherLock) + { + KeAcquireDispatcherDatabaseLock(FALSE); + } + WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList; + while (WaitBlock) + { + RemoveEntryList (&WaitBlock->WaitListEntry); + WaitBlock = WaitBlock->NextWaitBlock; + } + Thread->Tcb.WaitBlockList = NULL; + KeReleaseDispatcherDatabaseLockAtDpcLevel(FALSE); + PsDispatchThreadNoLock (THREAD_STATE_READY); + if (Status != NULL) + { + *Status = STATUS_KERNEL_APC; + } + } + else + { + if (DispatcherLock) + { + KeReleaseDispatcherDatabaseLockAtDpcLevel(FALSE); + } + Thread->Tcb.Alertable = Alertable; + Thread->Tcb.WaitMode = WaitMode; + Thread->Tcb.WaitIrql = WaitIrql; + PsDispatchThreadNoLock(THREAD_STATE_BLOCKED); + if (Status != NULL) + { + *Status = Thread->Tcb.WaitStatus; + } + } + KeLowerIrql(WaitIrql); +} + +VOID +PsFreezeAllThreads(PEPROCESS Process) + /* + * Used by the debugging code to freeze all the process's threads + * while the debugger is examining their state. + */ +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PETHREAD current; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + current_entry = Process->ThreadListHead.Flink; + while (current_entry != &Process->ThreadListHead) + { + current = CONTAINING_RECORD(current_entry, ETHREAD, + Tcb.ProcessThreadListEntry); + + /* + * We have to be careful here, we can't just set the freeze the + * thread inside kernel mode since it may be holding a lock. + */ + + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&PiThreadListLock, oldIrql); +} + +VOID +PsApplicationProcessorInit(VOID) +{ + KeGetCurrentKPCR()->CurrentThread = + (PVOID)IdleThreads[KeGetCurrentProcessorNumber()]; +} + +VOID +PsPrepareForApplicationProcessorInit(ULONG Id) +{ + PETHREAD IdleThread; + HANDLE IdleThreadHandle; + + PsInitializeThread(NULL, + &IdleThread, + &IdleThreadHandle, + THREAD_ALL_ACCESS, + NULL, + TRUE); + IdleThread->Tcb.State = THREAD_STATE_RUNNING; + IdleThread->Tcb.FreezeCount = 0; + IdleThread->Tcb.UserAffinity = 1 << Id; + IdleThread->Tcb.Priority = LOW_PRIORITY; + IdleThreads[Id] = IdleThread; + + NtClose(IdleThreadHandle); + DPRINT("IdleThread for Processor %d has PID %d\n", + Id, IdleThread->Cid.UniqueThread); +} + +VOID +PsInitThreadManagment(VOID) +/* + * FUNCTION: Initialize thread managment + */ +{ + PETHREAD FirstThread; + ULONG i; + HANDLE FirstThreadHandle; + NTSTATUS Status; + + KeInitializeSpinLock(&PiThreadListLock); + for (i=0; i < MAXIMUM_PRIORITY; i++) + { + InitializeListHead(&PriorityListHead[i]); + } + + InitializeListHead(&PiThreadListHead); + + PsThreadType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + + RtlInitUnicodeStringFromLiteral(&PsThreadType->TypeName, L"Thread"); + + PsThreadType->Tag = TAG('T', 'H', 'R', 'T'); + PsThreadType->TotalObjects = 0; + PsThreadType->TotalHandles = 0; + PsThreadType->MaxObjects = 0; + PsThreadType->MaxHandles = 0; + PsThreadType->PagedPoolCharge = 0; + PsThreadType->NonpagedPoolCharge = sizeof(ETHREAD); + PsThreadType->Mapping = &PiThreadMapping; + PsThreadType->Dump = NULL; + PsThreadType->Open = NULL; + PsThreadType->Close = NULL; + PsThreadType->Delete = PiDeleteThread; + PsThreadType->Parse = NULL; + PsThreadType->Security = NULL; + PsThreadType->QueryName = NULL; + PsThreadType->OkayToClose = NULL; + PsThreadType->Create = NULL; + PsThreadType->DuplicationNotify = NULL; + + PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle, + THREAD_ALL_ACCESS,NULL, TRUE); + FirstThread->Tcb.State = THREAD_STATE_RUNNING; + FirstThread->Tcb.FreezeCount = 0; + KeGetCurrentKPCR()->CurrentThread = (PVOID)FirstThread; + NtClose(FirstThreadHandle); + + DPRINT("FirstThread %x\n",FirstThread); + + DoneInitYet = TRUE; + + /* + * Create the reaper thread + */ + KeInitializeEvent(&PiReaperThreadEvent, SynchronizationEvent, FALSE); + Status = PsCreateSystemThread(&PiReaperThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + NULL, + PiReaperThreadMain, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("PS: Failed to create reaper thread.\n"); + KeBugCheck(0); + } +} + +LONG STDCALL +KeSetBasePriorityThread (PKTHREAD Thread, + LONG Increment) +/* + * Sets thread's base priority relative to the process' base priority + * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h + */ +{ + Thread->BasePriority = + ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment; + if (Thread->BasePriority < LOW_PRIORITY) + Thread->BasePriority = LOW_PRIORITY; + else if (Thread->BasePriority >= MAXIMUM_PRIORITY) + Thread->BasePriority = HIGH_PRIORITY; + Thread->Priority = Thread->BasePriority; + return 1; +} + + +KPRIORITY STDCALL +KeSetPriorityThread (PKTHREAD Thread, KPRIORITY Priority) +{ + KPRIORITY OldPriority; + KIRQL oldIrql; + + if (Priority < 0 || Priority >= MAXIMUM_PRIORITY) + { + KeBugCheck(0); + } + + OldPriority = Thread->Priority; + Thread->Priority = (CHAR)Priority; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + if (Thread->State == THREAD_STATE_READY) + { + RemoveEntryList(&Thread->QueueListEntry); + PsInsertIntoThreadList(Thread->BasePriority, + CONTAINING_RECORD(Thread,ETHREAD,Tcb)); + } + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + return(OldPriority); +} + + +NTSTATUS STDCALL +NtAlertResumeThread(IN HANDLE ThreadHandle, + OUT PULONG SuspendCount) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle) +{ + PETHREAD Thread; + NTSTATUS Status; + NTSTATUS ThreadStatus; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SUSPEND_RESUME, + PsThreadType, + UserMode, + (PVOID*)&Thread, + NULL); + if (Status != STATUS_SUCCESS) + { + return(Status); + } + + ThreadStatus = STATUS_ALERTED; + (VOID)PsUnblockThread(Thread, &ThreadStatus); + + ObDereferenceObject(Thread); + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtOpenThread(OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +NtContinue(IN PCONTEXT Context, + IN BOOLEAN TestAlert) +{ + PKTRAP_FRAME TrapFrame; + + /* + * Copy the supplied context over the register information that was saved + * on entry to kernel mode, it will then be restored on exit + * FIXME: Validate the context + */ + TrapFrame = KeGetCurrentThread()->TrapFrame; + if (TrapFrame == NULL) + { + CPRINT("NtContinue called but TrapFrame was NULL\n"); + KeBugCheck(0); + } + KeContextToTrapFrame(Context, TrapFrame); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +NtYieldExecution(VOID) +{ + PsDispatchThread(THREAD_STATE_READY); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, + OUT PEPROCESS *Process OPTIONAL, + OUT PETHREAD *Thread) +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PETHREAD current; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + current_entry = PiThreadListHead.Flink; + while (current_entry != &PiThreadListHead) + { + current = CONTAINING_RECORD(current_entry, + ETHREAD, + Tcb.ThreadListEntry); + if (current->Cid.UniqueThread == Cid->UniqueThread && + current->Cid.UniqueProcess == Cid->UniqueProcess) + { + if (Process != NULL) + *Process = current->ThreadsProcess; + *Thread = current; + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + return(STATUS_SUCCESS); + } + + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + + return(STATUS_INVALID_PARAMETER); +} + + +NTSTATUS STDCALL +PsLookupThreadByThreadId(IN PVOID ThreadId, + OUT PETHREAD *Thread) +{ + KIRQL oldIrql; + PLIST_ENTRY current_entry; + PETHREAD current; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + current_entry = PiThreadListHead.Flink; + while (current_entry != &PiThreadListHead) + { + current = CONTAINING_RECORD(current_entry, + ETHREAD, + Tcb.ThreadListEntry); + if (current->Cid.UniqueThread == (HANDLE)ThreadId) + { + *Thread = current; + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + return(STATUS_SUCCESS); + } + + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + + return(STATUS_INVALID_PARAMETER); +} + +/* EOF */ diff --git a/ntoskrnl/ps/tinfo.c b/ntoskrnl/ps/tinfo.c new file mode 100644 index 0000000..63463e2 --- /dev/null +++ b/ntoskrnl/ps/tinfo.c @@ -0,0 +1,336 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/tinfo.c + * PURPOSE: Getting/setting thread information + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +NtSetInformationThread(HANDLE ThreadHandle, + THREADINFOCLASS ThreadInformationClass, + PVOID ThreadInformation, + ULONG ThreadInformationLength) +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_SET_INFORMATION, + PsThreadType, + ExGetPreviousMode(), + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + switch (ThreadInformationClass) + { + case ThreadBasicInformation: + /* Can only be queried */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadTimes: + /* Can only be queried */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadPriority: + { + KPRIORITY Priority; + + if (ThreadInformationLength != sizeof(KPRIORITY)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + Priority = *(KPRIORITY*)ThreadInformation; + if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + KeSetPriorityThread(&Thread->Tcb, Priority); + Status = STATUS_SUCCESS; + break; + } + + case ThreadBasePriority: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadAffinityMask: + Thread->Tcb.UserAffinity = *((PULONG)ThreadInformation); + break; + + case ThreadImpersonationToken: + { + HANDLE TokenHandle; + + if (ThreadInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + TokenHandle = *((PHANDLE)ThreadInformation); + Status = PsAssignImpersonationToken(Thread, TokenHandle); + break; + } + + case ThreadDescriptorTableEntry: + /* Can only be queried */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadEventPair: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadQuerySetWin32StartAddress: + if (ThreadInformationLength != sizeof(ULONG)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + Thread->u2.Win32StartAddress = (PVOID)*((PULONG)ThreadInformation); + Status = STATUS_SUCCESS; + break; + + case ThreadZeroTlsCell: + { + Status = STATUS_NOT_IMPLEMENTED; + break; + } + + case ThreadPerformanceCount: + /* Can only be queried */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadAmILastThread: + /* Can only be queried */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadIdealProcessor: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadPriorityBoost: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadSetTlsArrayAddress: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadIsIoPending: + /* Can only be queried */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadHideFromDebugger: + Status = STATUS_NOT_IMPLEMENTED; + break; + + default: + Status = STATUS_UNSUCCESSFUL; + } + ObDereferenceObject(Thread); + return Status; +} + + +NTSTATUS STDCALL +NtQueryInformationThread (IN HANDLE ThreadHandle, + IN THREADINFOCLASS ThreadInformationClass, + OUT PVOID ThreadInformation, + IN ULONG ThreadInformationLength, + OUT PULONG ReturnLength) +{ + PETHREAD Thread; + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(ThreadHandle, + THREAD_QUERY_INFORMATION, + PsThreadType, + ExGetPreviousMode(), + (PVOID*)&Thread, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + switch (ThreadInformationClass) + { + case ThreadBasicInformation: + { + PTHREAD_BASIC_INFORMATION TBI; + + TBI = (PTHREAD_BASIC_INFORMATION)ThreadInformation; + + if (ThreadInformationLength != sizeof(THREAD_BASIC_INFORMATION)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + TBI->ExitStatus = Thread->ExitStatus; + TBI->TebBaseAddress = Thread->Tcb.Teb; + TBI->ClientId = Thread->Cid; + TBI->AffinityMask = Thread->Tcb.Affinity; + TBI->Priority = Thread->Tcb.Priority; + TBI->BasePriority = Thread->Tcb.BasePriority; + Status = STATUS_SUCCESS; + break; + } + + case ThreadTimes: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadPriority: + /* Can be set only */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadBasePriority: + /* Can be set only */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadAffinityMask: + /* Can be set only */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadImpersonationToken: + /* Can be set only */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadDescriptorTableEntry: + /* Nebbett says nothing about this */ + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadEnableAlignmentFaultFixup: + /* Can be set only */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadEventPair: + /* Can be set only */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadQuerySetWin32StartAddress: + if (ThreadInformationLength != sizeof(PVOID)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + *((PVOID*)ThreadInformation) = Thread->u2.Win32StartAddress; + Status = STATUS_SUCCESS; + break; + + case ThreadZeroTlsCell: + /* Can only be set */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadPerformanceCount: + /* Nebbett says this class is always zero */ + if (ThreadInformationLength != sizeof(LARGE_INTEGER)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + ((PLARGE_INTEGER)ThreadInformation)->QuadPart = 0; + Status = STATUS_SUCCESS; + break; + + case ThreadAmILastThread: + { + if (ThreadInformationLength != sizeof(BOOLEAN)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink == + &Thread->ThreadsProcess->ThreadListHead) + { + *((PBOOLEAN)ThreadInformation) = TRUE; + } + else + { + *((PBOOLEAN)ThreadInformation) = FALSE; + } + Status = STATUS_SUCCESS; + break; + } + + case ThreadIdealProcessor: + /* Can only be set */ + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + + case ThreadPriorityBoost: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadSetTlsArrayAddress: + /* Can only be set */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + case ThreadIsIoPending: + Status = STATUS_NOT_IMPLEMENTED; + break; + + case ThreadHideFromDebugger: + /* Can only be set */ + Status = STATUS_INVALID_INFO_CLASS; + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + ObDereferenceObject(Thread); + return(Status); +} + +VOID KeSetPreviousMode(ULONG Mode) +{ + PsGetCurrentThread()->Tcb.PreviousMode = Mode; +} + +ULONG STDCALL +KeGetPreviousMode (VOID) +{ + return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode; +} + +ULONG STDCALL +ExGetPreviousMode (VOID) +{ + return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode; +} + +/* EOF */ diff --git a/ntoskrnl/ps/w32call.c b/ntoskrnl/ps/w32call.c new file mode 100644 index 0000000..c3530c2 --- /dev/null +++ b/ntoskrnl/ps/w32call.c @@ -0,0 +1,251 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/thread.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Created + * 12/10/99: Phillip Susi: Thread priorities, and APC work + */ + +/* + * NOTE: + * + * All of the routines that manipulate the thread queue synchronize on + * a single spinlock + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* TYPES *******************************************************************/ + +typedef struct _NTW32CALL_SAVED_STATE +{ + ULONG SavedStackLimit; + PVOID SavedStackBase; + PVOID SavedInitialStack; + PVOID CallerResult; + PULONG CallerResultLength; + PNTSTATUS CallbackStatus; + PKTRAP_FRAME SavedTrapFrame; + PVOID SavedCallbackStack; +} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE; + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS STDCALL +NtCallbackReturn (PVOID Result, + ULONG ResultLength, + NTSTATUS Status) +{ + PULONG OldStack; + PETHREAD Thread; + PNTSTATUS CallbackStatus; + PULONG CallerResultLength; + PVOID* CallerResult; + PVOID InitialStack; + PVOID StackBase; + ULONG StackLimit; + KIRQL oldIrql; + PNTW32CALL_SAVED_STATE State; + PKTRAP_FRAME SavedTrapFrame; + PVOID SavedCallbackStack; + + Thread = PsGetCurrentThread(); + if (Thread->Tcb.CallbackStack == NULL) + { + return(STATUS_NO_CALLBACK_ACTIVE); + } + + OldStack = (PULONG)Thread->Tcb.CallbackStack; + + /* + * Get the values that NtW32Call left on the inactive stack for us. + */ + State = (PNTW32CALL_SAVED_STATE)OldStack[0]; + CallbackStatus = State->CallbackStatus; + CallerResultLength = State->CallerResultLength; + CallerResult = State->CallerResult; + InitialStack = State->SavedInitialStack; + StackBase = State->SavedStackBase; + StackLimit = State->SavedStackLimit; + SavedTrapFrame = State->SavedTrapFrame; + SavedCallbackStack = State->SavedCallbackStack; + + /* + * Copy the callback status and the callback result to NtW32Call + */ + *CallbackStatus = Status; + if (CallerResult != NULL && CallerResultLength != NULL) + { + if (Result == NULL) + { + *CallerResultLength = 0; + } + else + { + *CallerResultLength = min(ResultLength, *CallerResultLength); + memcpy(*CallerResult, Result, *CallerResultLength); + } + } + + /* + * Restore the old stack. + */ + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + Thread->Tcb.InitialStack = InitialStack; + Thread->Tcb.StackBase = StackBase; + Thread->Tcb.StackLimit = StackLimit; + Thread->Tcb.TrapFrame = SavedTrapFrame; + Thread->Tcb.CallbackStack = SavedCallbackStack; + KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack; + KeStackSwitchAndRet((PVOID)(OldStack + 1)); + + /* Should never return. */ + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); +} + +VOID STATIC +PsFreeCallbackStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, + PHYSICAL_ADDRESS PhysAddr, SWAPENTRY SwapEntry, + BOOLEAN Dirty) +{ + assert(SwapEntry == 0); + if (PhysAddr.QuadPart != 0) + { + MmReleasePageMemoryConsumer(MC_NPPOOL, PhysAddr); + } +} + +VOID STATIC +PsFreeCallbackStack(PVOID StackLimit) +{ + MmLockAddressSpace(MmGetKernelAddressSpace()); + MmFreeMemoryArea(MmGetKernelAddressSpace(), + StackLimit, + MM_STACK_SIZE, + PsFreeCallbackStackPage, + NULL); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); +} + +PVOID STATIC +PsAllocateCallbackStack(ULONG StackSize) +{ + PVOID KernelStack = NULL; + NTSTATUS Status; + PMEMORY_AREA StackArea; + ULONG i; + + StackSize = PAGE_ROUND_UP(StackSize); + MmLockAddressSpace(MmGetKernelAddressSpace()); + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_KERNEL_STACK, + &KernelStack, + StackSize, + 0, + &StackArea, + FALSE); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to create thread stack\n"); + return(NULL); + } + for (i = 0; i < (StackSize / PAGE_SIZE); i++) + { + PHYSICAL_ADDRESS Page; + Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + Status = MmCreateVirtualMapping(NULL, + KernelStack + (i * PAGE_SIZE), + PAGE_EXECUTE_READWRITE, + Page, + TRUE); + } + return(KernelStack); +} + +NTSTATUS STDCALL +NtW32Call (IN ULONG RoutineIndex, + IN PVOID Argument, + IN ULONG ArgumentLength, + OUT PVOID* Result OPTIONAL, + OUT PULONG ResultLength OPTIONAL) +{ + PETHREAD Thread; + PVOID NewStack; + ULONG StackSize; + PKTRAP_FRAME NewFrame; + PULONG UserEsp; + KIRQL oldIrql; + NTSTATUS CallbackStatus; + NTW32CALL_SAVED_STATE SavedState; + + DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n", + RoutineIndex, Argument, ArgumentLength); + + Thread = PsGetCurrentThread(); + + /* Set up the new kernel and user environment. */ + StackSize = (ULONG)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit); + NewStack = PsAllocateCallbackStack(StackSize); + /* FIXME: Need to check whether we were interrupted from v86 mode. */ + memcpy(NewStack + StackSize - sizeof(KTRAP_FRAME), Thread->Tcb.TrapFrame, + sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD))); + NewFrame = (PKTRAP_FRAME)(NewStack + StackSize - sizeof(KTRAP_FRAME)); + NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG))); + NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher(); + UserEsp = (PULONG)NewFrame->Esp; + UserEsp[0] = 0; /* Return address. */ + UserEsp[1] = RoutineIndex; + UserEsp[2] = (ULONG)&UserEsp[4]; + UserEsp[3] = ArgumentLength; + memcpy((PVOID)&UserEsp[4], Argument, ArgumentLength); + + /* Switch to the new environment and return to user-mode. */ + KeRaiseIrql(HIGH_LEVEL, &oldIrql); + SavedState.SavedStackLimit = Thread->Tcb.StackLimit; + SavedState.SavedStackBase = Thread->Tcb.StackBase; + SavedState.SavedInitialStack = Thread->Tcb.InitialStack; + SavedState.CallerResult = Result; + SavedState.CallerResultLength = ResultLength; + SavedState.CallbackStatus = &CallbackStatus; + SavedState.SavedTrapFrame = Thread->Tcb.TrapFrame; + SavedState.SavedCallbackStack = Thread->Tcb.CallbackStack; + Thread->Tcb.InitialStack = Thread->Tcb.StackBase = NewStack + StackSize; + Thread->Tcb.StackLimit = (ULONG)NewStack; + Thread->Tcb.KernelStack = NewStack + StackSize - sizeof(KTRAP_FRAME); + KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack; + KePushAndStackSwitchAndSysRet((ULONG)&SavedState, Thread->Tcb.KernelStack); + + /* + * The callback return will have already restored most of the state we + * modified. + */ + KeLowerIrql(PASSIVE_LEVEL); + PsFreeCallbackStack(NewStack); + return(CallbackStatus); +} + +/* EOF */ diff --git a/ntoskrnl/ps/win32.c b/ntoskrnl/ps/win32.c new file mode 100644 index 0000000..ebceb5f --- /dev/null +++ b/ntoskrnl/ps/win32.c @@ -0,0 +1,104 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/win32.c + * PURPOSE: win32k support + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * REVISION HISTORY: + * 04/01/2002: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include + +/* TYPES *******************************************************************/ + +/* GLOBALS ******************************************************************/ + +static ULONG PspWin32ProcessSize = 0; +static ULONG PspWin32ThreadSize = 0; + +/* FUNCTIONS ***************************************************************/ + +PW32THREAD STDCALL +PsGetWin32Thread(VOID) +{ + return(PsGetCurrentThread()->Win32Thread); +} + +NTSTATUS STDCALL +PsCreateWin32Thread(PETHREAD Thread) +{ + if (Thread->Win32Thread != NULL) + return(STATUS_SUCCESS); + + Thread->Win32Thread = ExAllocatePool(NonPagedPool, + PspWin32ThreadSize); + if (Thread->Win32Thread == NULL) + return(STATUS_NO_MEMORY); + + RtlZeroMemory(Thread->Win32Thread, + PspWin32ThreadSize); + + return(STATUS_SUCCESS); +} + +PW32PROCESS STDCALL +PsGetWin32Process(VOID) +{ + return(PsGetCurrentProcess()->Win32Process); +} + +NTSTATUS STDCALL +PsCreateWin32Process(PEPROCESS Process) +{ + if (Process->Win32Process != NULL) + return(STATUS_SUCCESS); + + Process->Win32Process = ExAllocatePool(NonPagedPool, + PspWin32ProcessSize); + if (Process->Win32Process == NULL) + return(STATUS_NO_MEMORY); + + RtlZeroMemory(Process->Win32Process, + PspWin32ProcessSize); + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +PsEstablishWin32Callouts(PVOID Param1, + PVOID Param2, + PVOID Param3, + PVOID Param4, + ULONG W32ThreadSize, + ULONG W32ProcessSize) +{ + PspWin32ProcessSize = W32ProcessSize; + PspWin32ThreadSize = W32ThreadSize; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/.cvsignore b/ntoskrnl/rtl/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/rtl/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/rtl/atom.c b/ntoskrnl/rtl/atom.c new file mode 100644 index 0000000..e822da1 --- /dev/null +++ b/ntoskrnl/rtl/atom.c @@ -0,0 +1,917 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/nt/atom.c + * PURPOSE: Atom managment + * PROGRAMMER: Nobody + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + + +typedef struct _RTL_ATOM_ENTRY +{ + LIST_ENTRY List; + UNICODE_STRING Name; + ULONG RefCount; + BOOLEAN Locked; + ULONG Index; +} RTL_ATOM_ENTRY, *PRTL_ATOM_ENTRY; + + +/* PROTOTYPES ****************************************************************/ + +static PRTL_ATOM_TABLE RtlpGetGlobalAtomTable(VOID); + +static ULONG RtlpHashAtomName(ULONG TableSize, PWSTR AtomName); +static BOOLEAN RtlpCheckIntegerAtom(PWSTR AtomName, PUSHORT AtomValue); + +static NTSTATUS RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable); +static VOID RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable); +static BOOLEAN RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable); +static VOID RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable); + +static BOOLEAN RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable); +static VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable); + +static NTSTATUS RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable, + RTL_ATOM Atom, + PATOM_BASIC_INFORMATION AtomInformation, + ULONG AtomInformationLength, + PULONG ReturnLength); + +static NTSTATUS RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable, + RTL_ATOM Atom, + PATOM_TABLE_INFORMATION AtomInformation, + ULONG AtomInformationLength, + PULONG ReturnLength); + + +/* GLOBALS *******************************************************************/ + +static PRTL_ATOM_TABLE GlobalAtomTable = NULL; + +/* FUNCTIONS *****************************************************************/ + + +NTSTATUS STDCALL +NtAddAtom(IN PWSTR AtomName, + OUT PRTL_ATOM Atom) +{ + PRTL_ATOM_TABLE AtomTable; + + AtomTable = RtlpGetGlobalAtomTable(); + if (AtomTable == NULL) + return STATUS_ACCESS_DENIED; + + return (RtlAddAtomToAtomTable(AtomTable, + AtomName, + Atom)); +} + + +NTSTATUS STDCALL +NtDeleteAtom(IN RTL_ATOM Atom) +{ + PRTL_ATOM_TABLE AtomTable; + + AtomTable = RtlpGetGlobalAtomTable(); + if (AtomTable == NULL) + return STATUS_ACCESS_DENIED; + + return (RtlDeleteAtomFromAtomTable(AtomTable, + Atom)); +} + + +NTSTATUS STDCALL +NtFindAtom(IN PWSTR AtomName, + OUT PRTL_ATOM Atom) +{ + PRTL_ATOM_TABLE AtomTable; + + AtomTable = RtlpGetGlobalAtomTable(); + if (AtomTable == NULL) + return STATUS_ACCESS_DENIED; + + return (RtlLookupAtomInAtomTable(AtomTable, + AtomName, + Atom)); +} + + +NTSTATUS STDCALL +NtQueryInformationAtom(RTL_ATOM Atom, + ATOM_INFORMATION_CLASS AtomInformationClass, + PVOID AtomInformation, + ULONG AtomInformationLength, + PULONG ReturnLength) +{ + PRTL_ATOM_TABLE AtomTable; + NTSTATUS Status; + + AtomTable = RtlpGetGlobalAtomTable(); + if (AtomTable == NULL) + return STATUS_ACCESS_DENIED; + + switch (AtomInformationClass) + { + case AtomBasicInformation: + Status = RtlpQueryAtomInformation(AtomTable, + Atom, + AtomInformation, + AtomInformationLength, + ReturnLength); + break; + + case AtomTableInformation: + Status = RtlpQueryAtomTableInformation(AtomTable, + Atom, + AtomInformation, + AtomInformationLength, + ReturnLength); + break; + + default: + Status = STATUS_INVALID_INFO_CLASS; + } + + return Status; +} + + +NTSTATUS STDCALL +RtlCreateAtomTable(ULONG TableSize, + PRTL_ATOM_TABLE *AtomTable) +{ + PRTL_ATOM_TABLE Table; + ULONG i; + NTSTATUS Status; + + DPRINT("RtlCreateAtomTable(TableSize %lu AtomTable %p)\n", + TableSize, AtomTable); + + if (*AtomTable != NULL) + { + return STATUS_SUCCESS; + } + + /* allocate atom table */ + Table = ExAllocatePool(NonPagedPool, + TableSize * sizeof(RTL_ATOM_ENTRY) + + sizeof(RTL_ATOM_TABLE)); + if (Table == NULL) + return STATUS_NO_MEMORY; + + /* initialize atom table */ + Table->TableSize = TableSize; + Table->NumberOfAtoms = 0; + + for (i = 0; i < TableSize; i++) + { + InitializeListHead(&Table->Slot[i]); + } + + Status = RtlpInitAtomTableLock(Table); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Table); + return Status; + } + + if (RtlpCreateAtomHandleTable(Table) == FALSE) + { + RtlpDestroyAtomTableLock(Table); + ExFreePool(Table); + return STATUS_NO_MEMORY; + } + + *AtomTable = Table; + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable) +{ + PLIST_ENTRY Current; + PRTL_ATOM_ENTRY AtomEntry; + ULONG i; + + if (RtlpLockAtomTable(AtomTable) == FALSE) + { + return (STATUS_INVALID_PARAMETER); + } + + /* delete all atoms */ + for (i = 0; i < AtomTable->TableSize; i++) + { + + Current = AtomTable->Slot[i].Flink; + while (Current != &AtomTable->Slot[i]) + { + AtomEntry = (PRTL_ATOM_ENTRY)Current; + RtlFreeUnicodeString(&AtomEntry->Name); + RemoveEntryList(&AtomEntry->List); + ExFreePool(AtomEntry); + Current = AtomTable->Slot[i].Flink; + } + + } + + RtlpDestroyAtomHandleTable(AtomTable); + + RtlpUnlockAtomTable(AtomTable); + + RtlpDestroyAtomTableLock(AtomTable); + + ExFreePool(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlEmptyAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN BOOLEAN DeletePinned) +{ + PLIST_ENTRY Current, Next; + PRTL_ATOM_ENTRY AtomEntry; + ULONG i; + + DPRINT("RtlEmptyAtomTable (AtomTable %p DeletePinned %x)\n", + AtomTable, DeletePinned); + + if (RtlpLockAtomTable(AtomTable) == FALSE) + { + return (STATUS_INVALID_PARAMETER); + } + + /* delete all atoms */ + for (i = 0; i < AtomTable->TableSize; i++) + { + Current = AtomTable->Slot[i].Flink; + while (Current != &AtomTable->Slot[i]) + { + Next = Current->Flink; + AtomEntry = (PRTL_ATOM_ENTRY)Current; + + if ((AtomEntry->Locked == FALSE) || + ((AtomEntry->Locked == TRUE) && (DeletePinned == TRUE))) + { + RtlFreeUnicodeString(&AtomEntry->Name); + + RtlpFreeHandle(AtomTable->HandleTable, + AtomEntry->Index); + + RemoveEntryList(&AtomEntry->List); + ExFreePool(AtomEntry); + } + Current = Next; + } + + } + + AtomTable->NumberOfAtoms = 0; + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlAddAtomToAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN PWSTR AtomName, + OUT PRTL_ATOM Atom) +{ + ULONG Hash; + PLIST_ENTRY Current; + PRTL_ATOM_ENTRY Entry; + USHORT AtomValue; + NTSTATUS Status; + ULONG AtomIndex; + + DPRINT("RtlAddAtomToAtomTable (AtomTable %p AtomName %S Atom %p)\n", + AtomTable, AtomName, Atom); + + if (RtlpCheckIntegerAtom (AtomName, &AtomValue)) + { + /* integer atom */ + if (AtomValue >= 0xC000) + { + AtomValue = 0; + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = STATUS_SUCCESS; + } + + if (Atom) + *Atom = (RTL_ATOM)AtomValue; + + return Status; + } + + RtlpLockAtomTable(AtomTable); + + /* string atom */ + Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName); + + /* search for existing atom */ + Current = AtomTable->Slot[Hash].Flink; + while (Current != &AtomTable->Slot[Hash]) + { + Entry = (PRTL_ATOM_ENTRY)Current; + + DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName); + if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0) + { + Entry->RefCount++; + if (Atom) + *Atom = (RTL_ATOM)(Entry->Index + 0xC000); + RtlpUnlockAtomTable(AtomTable); + return STATUS_SUCCESS; + } + Current = Current->Flink; + } + + /* insert new atom */ + Entry = ExAllocatePool(NonPagedPool, + sizeof(RTL_ATOM_ENTRY)); + if (Entry == NULL) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_NO_MEMORY; + } + + InsertTailList(&AtomTable->Slot[Hash], &Entry->List) + RtlCreateUnicodeString (&Entry->Name, + AtomName); + Entry->RefCount = 1; + Entry->Locked = FALSE; + + /* FIXME: use general function instead !! */ + RtlpAllocateHandle(AtomTable->HandleTable, + (PVOID)Entry, + &AtomIndex); + + DPRINT("AtomIndex %x\n", AtomIndex); + + Entry->Index = AtomIndex; + AtomTable->NumberOfAtoms++; + + if (Atom) + *Atom = (RTL_ATOM)(AtomIndex + 0xC000); + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom) +{ + PRTL_ATOM_ENTRY AtomEntry; + + DPRINT("RtlDeleteAtomFromAtomTable (AtomTable %p Atom %x)\n", + AtomTable, Atom); + + if (Atom < 0xC000) + { + return STATUS_SUCCESS; + } + + RtlpLockAtomTable(AtomTable); + + /* FIXME: use general function instead !! */ + AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable, + (ULONG)Atom - 0xC000); + if (AtomEntry == NULL) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_INVALID_HANDLE; + } + + DPRINT("AtomEntry %x\n", AtomEntry); + DPRINT("Atom name: %wZ\n", &AtomEntry->Name); + + AtomEntry->RefCount--; + + if (AtomEntry->RefCount == 0) + { + if (AtomEntry->Locked == TRUE) + { + DPRINT("Atom %wZ is locked!\n", &AtomEntry->Name); + + RtlpUnlockAtomTable(AtomTable); + return STATUS_WAS_LOCKED; + } + + DPRINT("Removing atom: %wZ\n", &AtomEntry->Name); + + RtlFreeUnicodeString(&AtomEntry->Name); + RemoveEntryList(&AtomEntry->List); + ExFreePool(AtomEntry); + RtlpFreeHandle(AtomTable->HandleTable, + (ULONG)Atom - 0xC000); + AtomTable->NumberOfAtoms++; + } + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlLookupAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN PWSTR AtomName, + OUT PRTL_ATOM Atom) +{ + ULONG Hash; + PLIST_ENTRY Current; + PRTL_ATOM_ENTRY Entry; + USHORT AtomValue; + NTSTATUS Status; + + DPRINT("RtlLookupAtomInAtomTable (AtomTable %p AtomName %S Atom %p)\n", + AtomTable, AtomName, Atom); + + if (RtlpCheckIntegerAtom (AtomName, &AtomValue)) + { + /* integer atom */ + if (AtomValue >= 0xC000) + { + AtomValue = 0; + Status = STATUS_INVALID_PARAMETER; + } + else + { + Status = STATUS_SUCCESS; + } + + if (Atom) + *Atom = (RTL_ATOM)AtomValue; + + return Status; + } + + RtlpLockAtomTable(AtomTable); + + /* string atom */ + Hash = RtlpHashAtomName(AtomTable->TableSize, AtomName); + + /* search for existing atom */ + Current = AtomTable->Slot[Hash].Flink; + while (Current != &AtomTable->Slot[Hash]) + { + Entry = (PRTL_ATOM_ENTRY)Current; + + DPRINT("Comparing %S and %S\n", Entry->Name.Buffer, AtomName); + if (_wcsicmp(Entry->Name.Buffer, AtomName) == 0) + { + if (Atom) + *Atom = (RTL_ATOM)(Entry->Index + 0xC000); + RtlpUnlockAtomTable(AtomTable); + return STATUS_SUCCESS; + } + + Current = Current->Flink; + } + + return STATUS_OBJECT_NAME_NOT_FOUND; +} + + +NTSTATUS STDCALL +RtlPinAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom) +{ + PRTL_ATOM_ENTRY AtomEntry; + + DPRINT("RtlPinAtomInAtomTable (AtomTable %p Atom %x)\n", + AtomTable, Atom); + + if (Atom < 0xC000) + { + return STATUS_SUCCESS; + } + + RtlpLockAtomTable(AtomTable); + + /* FIXME: use general function instead !! */ + AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable, + (ULONG)Atom - 0xC000); + if (AtomEntry == NULL) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_INVALID_HANDLE; + } + + DPRINT("AtomEntry %x\n", AtomEntry); + DPRINT("Atom name: %wZ\n", &AtomEntry->Name); + + AtomEntry->Locked = TRUE; + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlQueryAtomInAtomTable(IN PRTL_ATOM_TABLE AtomTable, + IN RTL_ATOM Atom, + IN OUT PULONG RefCount, + IN OUT PULONG PinCount, + IN OUT PWSTR AtomName, + IN OUT PULONG NameLength) +{ + ULONG Length; + PRTL_ATOM_ENTRY AtomEntry; + + if (Atom < 0xC000) + { + if (RefCount != NULL) + { + *RefCount = 1; + } + + if (PinCount != NULL) + { + *PinCount = 1; + } + + if ((AtomName != NULL) && (NameLength != NULL) && (NameLength > 0)) + { + Length = swprintf(AtomName, L"#%lu", (ULONG)Atom); + *NameLength = Length * sizeof(WCHAR); + } + + return STATUS_SUCCESS; + } + + RtlpLockAtomTable(AtomTable); + + /* FIXME: use general function instead !! */ + AtomEntry = (PRTL_ATOM_ENTRY)RtlpMapHandleToPointer(AtomTable->HandleTable, + (ULONG)Atom - 0xC000); + if (AtomEntry == NULL) + { + RtlpUnlockAtomTable(AtomTable); + return STATUS_INVALID_HANDLE; + } + + DPRINT("AtomEntry %x\n", AtomEntry); + DPRINT("Atom name: %wZ\n", &AtomEntry->Name); + + if (RefCount != NULL) + { + *RefCount = AtomEntry->RefCount; + } + + if (PinCount != NULL) + { + *PinCount = (ULONG)AtomEntry->Locked; + } + + if ((AtomName != NULL) && (NameLength != NULL)) + { + if (*NameLength < AtomEntry->Name.Length) + { + *NameLength = AtomEntry->Name.Length; + RtlpUnlockAtomTable(AtomTable); + return STATUS_BUFFER_TOO_SMALL; + } + + Length = swprintf(AtomName, L"%s", AtomEntry->Name.Buffer); + *NameLength = Length * sizeof(WCHAR); + } + + RtlpUnlockAtomTable(AtomTable); + + return STATUS_SUCCESS; +} + + +/* INTERNAL FUNCTIONS ********************************************************/ + +static PRTL_ATOM_TABLE +RtlpGetGlobalAtomTable(VOID) +{ + NTSTATUS Status; + + if (GlobalAtomTable != NULL) + return GlobalAtomTable; + + Status = RtlCreateAtomTable(37, &GlobalAtomTable); + if (!NT_SUCCESS(Status)) + return NULL; + + return GlobalAtomTable; +} + + +static ULONG +RtlpHashAtomName(ULONG TableSize, + PWSTR AtomName) +{ + ULONG q = 0; + PWCHAR p; + + DPRINT("RtlpHashAtomName(TableSize %ld AtomName '%S')\n", + TableSize, AtomName); + + /* convert the string to an internal representation */ + p = AtomName; + while (*p != 0) + { + q += (ULONG)towupper(*p); + p++; + } + + DPRINT("q %lu Hash %lu\n", q, q % TableSize); + + return (q % TableSize); +} + + +static BOOLEAN +RtlpCheckIntegerAtom(PWSTR AtomName, + PUSHORT AtomValue) +{ + UNICODE_STRING AtomString; + ULONG LongValue; + USHORT LoValue; + PWCHAR p; + + DPRINT("RtlpCheckIntegerAtom(AtomName '%S' AtomValue %p)\n", + AtomName, AtomValue); + + if (!((ULONG)AtomName & 0xFFFF0000)) + { + LoValue = (USHORT)((ULONG)AtomName & 0xFFFF); + + if (LoValue >= 0xC000) + return FALSE; + + if (LoValue == 0) + LoValue = 0xC000; + + if (AtomValue != NULL) + *AtomValue = LoValue; + + return TRUE; + } + + if (*AtomName != L'#') + return FALSE; + + p = AtomName; + p++; + while (*p) + { + if ((*p < L'0') || (*p > L'9')) + return FALSE; + p++; + } + + p = AtomName; + p++; + RtlInitUnicodeString(&AtomString, + p); + + DPRINT1("AtomString: %wZ\n", &AtomString); + + RtlUnicodeStringToInteger(&AtomString,10, &LongValue); + + DPRINT1("LongValue: %lu\n", LongValue); + + *AtomValue = (USHORT)(LongValue & 0x0000FFFF); + + return TRUE; +} + + +/* lock functions */ + +static NTSTATUS +RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable) +{ + AtomTable->Lock = ExAllocatePool(NonPagedPool, + sizeof(FAST_MUTEX)); + if (AtomTable->Lock == NULL) + return STATUS_NO_MEMORY; + + ExInitializeFastMutex((PFAST_MUTEX)AtomTable->Lock); + + return STATUS_SUCCESS; +} + + +static VOID +RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable) +{ + if (AtomTable->Lock) + ExFreePool(AtomTable->Lock); +} + + +static BOOLEAN +RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable) +{ +// ExAcquireFastMutex((PFAST_MUTEX)AtomTable->Lock); + return TRUE; +} + +static VOID +RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable) +{ +// ExReleaseFastMutex((PFAST_MUTEX)AtomTable->Lock); +} + +#if 0 +static NTSTATUS +RtlpInitAtomTableLock(PRTL_ATOM_TABLE AtomTable) +{ + AtomTable->Lock = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CRITICAL_SECTION)); + if (AtomTable->Lock == NULL) + return STATUS_NO_MEMORY; + + RtlInitializeCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); + + return STATUS_SUCCESS; +} + + +static VOID +RtlpDestroyAtomTableLock(PRTL_ATOM_TABLE AtomTable) +{ + if (AtomTable->Lock) + { + RtlDeleteCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); + RtlFreeHeap(RtlGetProcessHeap(), + 0, + AtomTable->Lock); + AtomTable->Lock = NULL; + } +} + + +static BOOLEAN +RtlpLockAtomTable(PRTL_ATOM_TABLE AtomTable) +{ + RtlEnterCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); + return TRUE; +} + + +static VOID +RtlpUnlockAtomTable(PRTL_ATOM_TABLE AtomTable) +{ + RtlLeaveCriticalSection((PCRITICAL_SECTION)AtomTable->Lock); +} +#endif + +/* handle functions */ + +static BOOLEAN +RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable) +{ + AtomTable->HandleTable = ExAllocatePool(NonPagedPool, + sizeof(RTL_HANDLE_TABLE)); + if (AtomTable->HandleTable == NULL) + return FALSE; + + RtlpInitializeHandleTable(0xCFFF, + (PRTL_HANDLE_TABLE)AtomTable->HandleTable); + + return TRUE; +} + + +static VOID +RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable) +{ + if (AtomTable->HandleTable) + { + RtlpDestroyHandleTable((PRTL_HANDLE_TABLE)AtomTable->HandleTable); + ExFreePool(AtomTable->HandleTable); + AtomTable->HandleTable = NULL; + } +} + + +static NTSTATUS +RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable, + RTL_ATOM Atom, + PATOM_BASIC_INFORMATION AtomInformation, + ULONG AtomInformationLength, + PULONG ReturnLength) +{ + NTSTATUS Status; + ULONG UsageCount; + ULONG Flags; + ULONG NameLength; + + NameLength = AtomInformationLength - sizeof(ATOM_BASIC_INFORMATION) + sizeof(WCHAR); + Status = RtlQueryAtomInAtomTable(AtomTable, + Atom, + &UsageCount, + &Flags, + AtomInformation->Name, + &NameLength); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + DPRINT1("NameLength: %lu\n", NameLength); + + if (ReturnLength != NULL) + { + *ReturnLength = NameLength + sizeof(ATOM_BASIC_INFORMATION); + } + + if (NameLength + sizeof(ATOM_BASIC_INFORMATION) > AtomInformationLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + AtomInformation->UsageCount = (USHORT)UsageCount; + AtomInformation->Flags = (USHORT)Flags; + AtomInformation->NameLength = (USHORT)NameLength; + + return STATUS_SUCCESS; +} + + +static NTSTATUS +RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable, + RTL_ATOM Atom, + PATOM_TABLE_INFORMATION AtomInformation, + ULONG AtomInformationLength, + PULONG ReturnLength) +{ + PLIST_ENTRY Current, Next; + PRTL_ATOM_ENTRY AtomEntry; + ULONG Length; + ULONG i, j; + + Length = sizeof(ATOM_TABLE_INFORMATION); + if (AtomTable->NumberOfAtoms > 1) + { + Length += ((AtomTable->NumberOfAtoms - 1)* sizeof(RTL_ATOM)); + } + + DPRINT1("RequiredLength: %lu\n", Length); + + if (ReturnLength != NULL) + { + *ReturnLength = Length; + } + + if (Length > AtomInformationLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + AtomInformation->NumberOfAtoms = AtomTable->NumberOfAtoms; + + j = 0; + for (i = 0; i < AtomTable->TableSize; i++) + { + Current = AtomTable->Slot[i].Flink; + while (Current != &AtomTable->Slot[i]) + { + Next = Current->Flink; + AtomEntry = (PRTL_ATOM_ENTRY)Current; + + AtomInformation->Atoms[j] = AtomEntry->Index + 0xC000; + j++; + + Current = Next; + } + } + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/bitmap.c b/ntoskrnl/rtl/bitmap.c new file mode 100644 index 0000000..6823b48 --- /dev/null +++ b/ntoskrnl/rtl/bitmap.c @@ -0,0 +1,649 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/bitmap.c + * PURPOSE: Bitmap functions + * UPDATE HISTORY: + * 20/08/99 Created by Eric Kohl + */ + +#include + + +#define ALIGN(x,align) (((x)+(align)-1) / (align)) + + +VOID +STDCALL +RtlInitializeBitMap ( + PRTL_BITMAP BitMapHeader, + PULONG BitMapBuffer, + ULONG SizeOfBitMap + ) +{ + BitMapHeader->SizeOfBitMap = SizeOfBitMap; + BitMapHeader->Buffer = BitMapBuffer; +} + + +BOOLEAN +STDCALL +RtlAreBitsClear ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Shift; + ULONG Count; + PCHAR Ptr; + + if (StartingIndex >= Size || + !Length || + (StartingIndex + Length > Size)) + return FALSE; + + Ptr = (PCHAR)BitMapHeader->Buffer + (StartingIndex / 8); + while (Length) + { + /* get bit shift in current byte */ + Shift = StartingIndex & 7; + + /* get number of bits to check in current byte */ + Count = (Length > 8 - Shift) ? 8 - Shift : Length; + + /* check byte */ + if (*Ptr++ & (~(0xFF << Count) << Shift)) + return FALSE; + + Length -= Count; + StartingIndex += Count; + } + + return TRUE; +} + + +BOOLEAN +STDCALL +RtlAreBitsSet ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG Length + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Shift; + ULONG Count; + PCHAR Ptr; + + if (StartingIndex >= Size || + !Length || + (StartingIndex + Length > Size)) + return FALSE; + + Ptr = (PCHAR)BitMapHeader->Buffer + (StartingIndex / 8); + while (Length) + { + /* get bit shift in current byte */ + Shift = StartingIndex & 7; + + /* get number of bits to check in current byte */ + Count = (Length > 8 - Shift) ? 8 - Shift : Length; + + /* check byte */ + if (~*Ptr++ & (~(0xFF << Count) << Shift)) + return FALSE; + + Length -= Count; + StartingIndex += Count; + } + + return TRUE; +} + + +VOID +STDCALL +RtlClearAllBits ( + IN OUT PRTL_BITMAP BitMapHeader + ) +{ + memset (BitMapHeader->Buffer, + 0x00, + ALIGN(BitMapHeader->SizeOfBitMap, 8)); +} + + +VOID +STDCALL +RtlClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToClear + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Count; + ULONG Shift; + PCHAR Ptr; + + if (StartingIndex >= Size || NumberToClear == 0) + return; + + if (StartingIndex + NumberToClear > Size) + NumberToClear = Size - StartingIndex; + + Ptr = (PCHAR)(BitMapHeader->Buffer + (StartingIndex / 8)); + while (NumberToClear) + { + /* bit shift in current byte */ + Shift = StartingIndex & 7; + + /* number of bits to change in current byte */ + Count = (NumberToClear > 8 - Shift ) ? 8 - Shift : NumberToClear; + + /* adjust byte */ + *Ptr++ &= ~(~(0xFF << Count) << Shift); + NumberToClear -= Count; + StartingIndex += Count; + } +} + + +ULONG +STDCALL +RtlFindClearBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (NumberToFind > Size || NumberToFind == 0) + return -1; + + if (HintIndex >= Size) + HintIndex = 0; + + Index = HintIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + while (HintIndex < Size) + { + /* count clear bits */ + for (Count = 0; Index < Size && ~*Ptr & Mask; Index++) + { + if (++Count >= NumberToFind) + return HintIndex; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip set bits */ + for (; Index < Size && *Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + HintIndex = Index; + } + + return -1; +} + + +ULONG +STDCALL +RtlFindClearBitsAndSet ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Index; + + Index = RtlFindClearBits (BitMapHeader, + NumberToFind, + HintIndex); + if (Index != (ULONG)-1) + RtlSetBits (BitMapHeader, + Index, + NumberToFind); + + return Index; +} + + +ULONG +STDCALL +RtlFindFirstRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (*StartingIndex > Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + + Index = *StartingIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + /* skip set bits */ + for (; Index < Size && *Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* return index of first clear bit */ + if (Index >= Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + else + *StartingIndex = Index; + + /* count clear bits */ + for (Count = 0; Index < Size && ~*Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +ULONG +STDCALL +RtlFindFirstRunSet ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (*StartingIndex > Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + + Index = *StartingIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + /* skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* return index of first set bit */ + if (Index >= Size) + { + *StartingIndex = (ULONG)-1; + return 0; + } + else + *StartingIndex = Index; + + /* count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +ULONG +STDCALL +RtlFindLongestRunClear ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Index = 0; + ULONG Count; + ULONG Max = 0; + ULONG Start; + ULONG Maxstart = 0; + CHAR Mask = 1; + + while (Index < Size) + { + Start = Index; + + /* count clear bits */ + for (Count = 0; Index < Size && ~*Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip set bits */ + for (; Index < Size && *Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + if (Count > Max) + { + Max = Count; + Maxstart = Start; + } + } + + if (StartingIndex) + *StartingIndex = Maxstart; + + return Max; +} + + +ULONG +STDCALL +RtlFindLongestRunSet ( + PRTL_BITMAP BitMapHeader, + PULONG StartingIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Index = 0; + ULONG Count; + ULONG Max = 0; + ULONG Start; + ULONG Maxstart = 0; + CHAR Mask = 1; + + while (Index < Size) + { + Start = Index; + + /* count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + Count++; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + if (Count > Max) + { + Max = Count; + Maxstart = Start; + } + } + + if (StartingIndex) + *StartingIndex = Maxstart; + + return Max; +} + + +ULONG +STDCALL +RtlFindSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + PCHAR Ptr; + CHAR Mask; + + if (NumberToFind > Size || NumberToFind == 0) + return (ULONG)-1; + + if (HintIndex >= Size) + HintIndex = 0; + + Index = HintIndex; + Ptr = (PCHAR)BitMapHeader->Buffer + (Index / 8); + Mask = 1 << (Index & 7); + + while (HintIndex < Size) + { + /* count set bits */ + for (Count = 0; Index < Size && *Ptr & Mask; Index++) + { + if (++Count >= NumberToFind) + return HintIndex; + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + /* skip clear bits */ + for (; Index < Size && ~*Ptr & Mask; Index++) + { + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + HintIndex = Index; + } + + return (ULONG)-1; +} + + +ULONG +STDCALL +RtlFindSetBitsAndClear ( + PRTL_BITMAP BitMapHeader, + ULONG NumberToFind, + ULONG HintIndex + ) +{ + ULONG Index; + + Index = RtlFindSetBits (BitMapHeader, + NumberToFind, + HintIndex); + if (Index != (ULONG)-1) + RtlClearBits (BitMapHeader, + Index, + NumberToFind); + + return Index; +} + + +ULONG +STDCALL +RtlNumberOfClearBits ( + PRTL_BITMAP BitMapHeader + ) +{ + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + CHAR Mask; + + for (Mask = 1, Index = 0, Count = 0; Index < Size; Index++) + { + if (~*Ptr & Mask) + Count++; + + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +ULONG +STDCALL +RtlNumberOfSetBits ( + PRTL_BITMAP BitMapHeader + ) +{ + PCHAR Ptr = (PCHAR)BitMapHeader->Buffer; + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Index; + ULONG Count; + CHAR Mask; + + for (Mask = 1, Index = 0, Count = 0; Index < Size; Index++) + { + if (*Ptr & Mask) + Count++; + + Mask <<= 1; + if (Mask == 0) + { + Mask = 1; + Ptr++; + } + } + + return Count; +} + + +VOID +STDCALL +RtlSetAllBits ( + IN OUT PRTL_BITMAP BitMapHeader + ) +{ + memset (BitMapHeader->Buffer, + 0xFF, + ALIGN(BitMapHeader->SizeOfBitMap, 8)); +} + + +VOID +STDCALL +RtlSetBits ( + PRTL_BITMAP BitMapHeader, + ULONG StartingIndex, + ULONG NumberToSet + ) +{ + ULONG Size = BitMapHeader->SizeOfBitMap; + ULONG Count; + ULONG Shift; + PCHAR Ptr; + + if (StartingIndex >= Size || NumberToSet == 0) + return; + + if (StartingIndex + NumberToSet > Size) + NumberToSet = Size - StartingIndex; + + Ptr = (PCHAR)BitMapHeader->Buffer + (StartingIndex / 8); + while (NumberToSet) + { + /* bit shift in current byte */ + Shift = StartingIndex & 7; + + /* number of bits to change in current byte */ + Count = (NumberToSet > 8 - Shift) ? 8 - Shift : NumberToSet; + + /* adjust byte */ + *Ptr++ |= ~(0xFF << Count) << Shift; + NumberToSet -= Count; + StartingIndex += Count; + } +} + +/* EOF */ diff --git a/ntoskrnl/rtl/capture.c b/ntoskrnl/rtl/capture.c new file mode 100644 index 0000000..23e1160 --- /dev/null +++ b/ntoskrnl/rtl/capture.c @@ -0,0 +1,120 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/capture.c + * PURPOSE: Helper routines for system calls. + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 02/09/01: Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +RtlCaptureUnicodeString(PUNICODE_STRING Dest, + PUNICODE_STRING UnsafeSrc) +{ + PUNICODE_STRING Src; + NTSTATUS Status; + + /* + * Copy the source string structure to kernel space. + */ + Status = MmCopyFromCaller(&Src, UnsafeSrc, sizeof(UNICODE_STRING)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Initialize the destination string. + */ + Dest->Length = Src->Length; + Dest->MaximumLength = Src->MaximumLength; + Dest->Buffer = ExAllocatePool(NonPagedPool, Dest->MaximumLength); + if (Dest->Buffer == NULL) + { + return(STATUS_NO_MEMORY); + } + + /* + * Copy the source string to kernel space. + */ + Status = MmCopyFromCaller(Dest->Buffer, Src->Buffer, Dest->Length); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Dest->Buffer); + return(Status); + } + + return(STATUS_SUCCESS); +} + +NTSTATUS +RtlCaptureAnsiString(PANSI_STRING Dest, + PANSI_STRING UnsafeSrc) +{ + PANSI_STRING Src; + NTSTATUS Status; + + /* + * Copy the source string structure to kernel space. + */ + Status = MmCopyFromCaller(&Src, UnsafeSrc, sizeof(ANSI_STRING)); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* + * Initialize the destination string. + */ + Dest->Length = Src->Length; + Dest->MaximumLength = Src->MaximumLength; + Dest->Buffer = ExAllocatePool(NonPagedPool, Dest->MaximumLength); + if (Dest->Buffer == NULL) + { + return(Status); + } + + /* + * Copy the source string to kernel space. + */ + Status = MmCopyFromCaller(Dest->Buffer, Src->Buffer, Dest->Length); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Dest->Buffer); + return(Status); + } + + return(STATUS_SUCCESS); +} + +/* EOF */ + diff --git a/ntoskrnl/rtl/compress.c b/ntoskrnl/rtl/compress.c new file mode 100644 index 0000000..c4e37de --- /dev/null +++ b/ntoskrnl/rtl/compress.c @@ -0,0 +1,205 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Compression and decompression functions + * FILE: ntoskrnl/rtl/compress.c + * PROGRAMER: Eric Kohl (ekohl@zr-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include + + +/* MACROS *******************************************************************/ + +#define COMPRESSION_FORMAT_MASK 0x00FF +#define COMPRESSION_ENGINE_MASK 0xFF00 + + +/* FUNCTIONS ****************************************************************/ + + +static NTSTATUS +RtlpCompressBufferLZNT1(USHORT Engine, + PUCHAR UncompressedBuffer, + ULONG UncompressedBufferSize, + PUCHAR CompressedBuffer, + ULONG CompressedBufferSize, + ULONG UncompressedChunkSize, + PULONG FinalCompressedSize, + PVOID WorkSpace) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +static NTSTATUS +RtlpWorkSpaceSizeLZNT1(USHORT Engine, + PULONG BufferAndWorkSpaceSize, + PULONG FragmentWorkSpaceSize) +{ + if (Engine == COMPRESSION_ENGINE_STANDARD) + { + *BufferAndWorkSpaceSize = 0x8010; + *FragmentWorkSpaceSize = 0x1000; + return(STATUS_SUCCESS); + } + else if (Engine == COMPRESSION_ENGINE_MAXIMUM) + { + *BufferAndWorkSpaceSize = 0x10; + *FragmentWorkSpaceSize = 0x1000; + return(STATUS_SUCCESS); + } + + return(STATUS_NOT_SUPPORTED); +} + + + + +NTSTATUS STDCALL +RtlCompressBuffer(IN USHORT CompressionFormatAndEngine, + IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG UncompressedChunkSize, + OUT PULONG FinalCompressedSize, + IN PVOID WorkSpace) +{ + USHORT Format = CompressionFormatAndEngine & COMPRESSION_FORMAT_MASK; + USHORT Engine = CompressionFormatAndEngine & COMPRESSION_ENGINE_MASK; + + if ((Format == COMPRESSION_FORMAT_NONE) || + (Format == COMPRESSION_FORMAT_DEFAULT)) + return(STATUS_INVALID_PARAMETER); + + if (Format == COMPRESSION_FORMAT_LZNT1) + return(RtlpCompressBufferLZNT1(Engine, + UncompressedBuffer, + UncompressedBufferSize, + CompressedBuffer, + CompressedBufferSize, + UncompressedChunkSize, + FinalCompressedSize, + WorkSpace)); + + return(STATUS_UNSUPPORTED_COMPRESSION); +} + + +NTSTATUS STDCALL +RtlCompressChunks(IN PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + OUT PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo, + IN ULONG CompressedDataInfoLength, + IN PVOID WorkSpace) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +RtlDecompressBuffer(IN USHORT CompressionFormat, + OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + OUT PULONG FinalUncompressedSize) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +RtlDecompressChunks(OUT PUCHAR UncompressedBuffer, + IN ULONG UncompressedBufferSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN PUCHAR CompressedTail, + IN ULONG CompressedTailSize, + IN PCOMPRESSED_DATA_INFO CompressedDataInfo) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +RtlDecompressFragment(IN USHORT CompressionFormat, + OUT PUCHAR UncompressedFragment, + IN ULONG UncompressedFragmentSize, + IN PUCHAR CompressedBuffer, + IN ULONG CompressedBufferSize, + IN ULONG FragmentOffset, + OUT PULONG FinalUncompressedSize, + IN PVOID WorkSpace) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +RtlDescribeChunk(IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + OUT PULONG ChunkSize) +{ + return(STATUS_NOT_IMPLEMENTED); +} + + +NTSTATUS STDCALL +RtlGetCompressionWorkSpaceSize(IN USHORT CompressionFormatAndEngine, + OUT PULONG CompressBufferAndWorkSpaceSize, + OUT PULONG CompressFragmentWorkSpaceSize) +{ + USHORT Format = CompressionFormatAndEngine & COMPRESSION_FORMAT_MASK; + USHORT Engine = CompressionFormatAndEngine & COMPRESSION_ENGINE_MASK; + + if ((Format == COMPRESSION_FORMAT_NONE) || + (Format == COMPRESSION_FORMAT_DEFAULT)) + return(STATUS_INVALID_PARAMETER); + + if (Format == COMPRESSION_FORMAT_LZNT1) + return(RtlpWorkSpaceSizeLZNT1(Engine, + CompressBufferAndWorkSpaceSize, + CompressFragmentWorkSpaceSize)); + + return(STATUS_UNSUPPORTED_COMPRESSION); +} + + +NTSTATUS STDCALL +RtlReserveChunk(IN USHORT CompressionFormat, + IN OUT PUCHAR *CompressedBuffer, + IN PUCHAR EndOfCompressedBufferPlus1, + OUT PUCHAR *ChunkBuffer, + IN ULONG ChunkSize) +{ + return(STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/ctype.c b/ntoskrnl/rtl/ctype.c new file mode 100644 index 0000000..a8ccc9b --- /dev/null +++ b/ntoskrnl/rtl/ctype.c @@ -0,0 +1,443 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/ctype.c + * PURPOSE: Character type and conversion functions + * PROGRAMMERS: ??? + * Eric Kohl + * HISTORY: ???: Created + * 10/01/2000: Added missing functions and changed + * all functions to use ctype table + */ +#undef __MSVCRT__ +#include + +#undef _pctype + +#define upalpha ('A' - 'a') + + +unsigned short _ctype[] = { + 0, /* , 0xFFFF */ + _CONTROL, /* CTRL+@, 0x00 */ + _CONTROL, /* CTRL+A, 0x01 */ + _CONTROL, /* CTRL+B, 0x02 */ + _CONTROL, /* CTRL+C, 0x03 */ + _CONTROL, /* CTRL+D, 0x04 */ + _CONTROL, /* CTRL+E, 0x05 */ + _CONTROL, /* CTRL+F, 0x06 */ + _CONTROL, /* CTRL+G, 0x07 */ + _CONTROL, /* CTRL+H, 0x08 */ + _CONTROL | _SPACE, /* CTRL+I, 0x09 */ + _CONTROL | _SPACE, /* CTRL+J, 0x0a */ + _CONTROL | _SPACE, /* CTRL+K, 0x0b */ + _CONTROL | _SPACE, /* CTRL+L, 0x0c */ + _CONTROL | _SPACE, /* CTRL+M, 0x0d */ + _CONTROL, /* CTRL+N, 0x0e */ + _CONTROL, /* CTRL+O, 0x0f */ + _CONTROL, /* CTRL+P, 0x10 */ + _CONTROL, /* CTRL+Q, 0x11 */ + _CONTROL, /* CTRL+R, 0x12 */ + _CONTROL, /* CTRL+S, 0x13 */ + _CONTROL, /* CTRL+T, 0x14 */ + _CONTROL, /* CTRL+U, 0x15 */ + _CONTROL, /* CTRL+V, 0x16 */ + _CONTROL, /* CTRL+W, 0x17 */ + _CONTROL, /* CTRL+X, 0x18 */ + _CONTROL, /* CTRL+Y, 0x19 */ + _CONTROL, /* CTRL+Z, 0x1a */ + _CONTROL, /* CTRL+[, 0x1b */ + _CONTROL, /* CTRL+\, 0x1c */ + _CONTROL, /* CTRL+], 0x1d */ + _CONTROL, /* CTRL+^, 0x1e */ + _CONTROL, /* CTRL+_, 0x1f */ + _SPACE | _BLANK, /* ` ', 0x20 */ + _PUNCT, /* `!', 0x21 */ + _PUNCT, /* 0x22 */ + _PUNCT, /* `#', 0x23 */ + _PUNCT, /* `$', 0x24 */ + _PUNCT, /* `%', 0x25 */ + _PUNCT, /* `&', 0x26 */ + _PUNCT, /* 0x27 */ + _PUNCT, /* `(', 0x28 */ + _PUNCT, /* `)', 0x29 */ + _PUNCT, /* `*', 0x2a */ + _PUNCT, /* `+', 0x2b */ + _PUNCT, /* `,', 0x2c */ + _PUNCT, /* `-', 0x2d */ + _PUNCT, /* `.', 0x2e */ + _PUNCT, /* `/', 0x2f */ + _DIGIT | _HEX, /* `0', 0x30 */ + _DIGIT | _HEX, /* `1', 0x31 */ + _DIGIT | _HEX, /* `2', 0x32 */ + _DIGIT | _HEX, /* `3', 0x33 */ + _DIGIT | _HEX, /* `4', 0x34 */ + _DIGIT | _HEX, /* `5', 0x35 */ + _DIGIT | _HEX, /* `6', 0x36 */ + _DIGIT | _HEX, /* `7', 0x37 */ + _DIGIT | _HEX, /* `8', 0x38 */ + _DIGIT | _HEX, /* `9', 0x39 */ + _PUNCT, /* `:', 0x3a */ + _PUNCT, /* `;', 0x3b */ + _PUNCT, /* `<', 0x3c */ + _PUNCT, /* `=', 0x3d */ + _PUNCT, /* `>', 0x3e */ + _PUNCT, /* `?', 0x3f */ + _PUNCT, /* `@', 0x40 */ + _UPPER | _HEX, /* `A', 0x41 */ + _UPPER | _HEX, /* `B', 0x42 */ + _UPPER | _HEX, /* `C', 0x43 */ + _UPPER | _HEX, /* `D', 0x44 */ + _UPPER | _HEX, /* `E', 0x45 */ + _UPPER | _HEX, /* `F', 0x46 */ + _UPPER, /* `G', 0x47 */ + _UPPER, /* `H', 0x48 */ + _UPPER, /* `I', 0x49 */ + _UPPER, /* `J', 0x4a */ + _UPPER, /* `K', 0x4b */ + _UPPER, /* `L', 0x4c */ + _UPPER, /* `M', 0x4d */ + _UPPER, /* `N', 0x4e */ + _UPPER, /* `O', 0x4f */ + _UPPER, /* `P', 0x50 */ + _UPPER, /* `Q', 0x51 */ + _UPPER, /* `R', 0x52 */ + _UPPER, /* `S', 0x53 */ + _UPPER, /* `T', 0x54 */ + _UPPER, /* `U', 0x55 */ + _UPPER, /* `V', 0x56 */ + _UPPER, /* `W', 0x57 */ + _UPPER, /* `X', 0x58 */ + _UPPER, /* `Y', 0x59 */ + _UPPER, /* `Z', 0x5a */ + _PUNCT, /* `[', 0x5b */ + _PUNCT, /* 0x5c */ + _PUNCT, /* `]', 0x5d */ + _PUNCT, /* `^', 0x5e */ + _PUNCT, /* `_', 0x5f */ + _PUNCT, /* 0x60 */ + _LOWER | _HEX, /* `a', 0x61 */ + _LOWER | _HEX, /* `b', 0x62 */ + _LOWER | _HEX, /* `c', 0x63 */ + _LOWER | _HEX, /* `d', 0x64 */ + _LOWER | _HEX, /* `e', 0x65 */ + _LOWER | _HEX, /* `f', 0x66 */ + _LOWER, /* `g', 0x67 */ + _LOWER, /* `h', 0x68 */ + _LOWER, /* `i', 0x69 */ + _LOWER, /* `j', 0x6a */ + _LOWER, /* `k', 0x6b */ + _LOWER, /* `l', 0x6c */ + _LOWER, /* `m', 0x6d */ + _LOWER, /* `n', 0x6e */ + _LOWER, /* `o', 0x6f */ + _LOWER, /* `p', 0x70 */ + _LOWER, /* `q', 0x71 */ + _LOWER, /* `r', 0x72 */ + _LOWER, /* `s', 0x73 */ + _LOWER, /* `t', 0x74 */ + _LOWER, /* `u', 0x75 */ + _LOWER, /* `v', 0x76 */ + _LOWER, /* `w', 0x77 */ + _LOWER, /* `x', 0x78 */ + _LOWER, /* `y', 0x79 */ + _LOWER, /* `z', 0x7a */ + _PUNCT, /* `{', 0x7b */ + _PUNCT, /* `|', 0x7c */ + _PUNCT, /* `}', 0x7d */ + _PUNCT, /* `~', 0x7e */ + _CONTROL, /* 0x7f */ + 0, /* 0x80 */ + 0, /* 0x81 */ + 0, /* 0x82 */ + 0, /* 0x83 */ + 0, /* 0x84 */ + 0, /* 0x85 */ + 0, /* 0x86 */ + 0, /* 0x87 */ + 0, /* 0x88 */ + 0, /* 0x89 */ + 0, /* 0x8a */ + 0, /* 0x8b */ + 0, /* 0x8c */ + 0, /* 0x8d */ + 0, /* 0x8e */ + 0, /* 0x8f */ + 0, /* 0x90 */ + 0, /* 0x91 */ + 0, /* 0x92 */ + 0, /* 0x93 */ + 0, /* 0x94 */ + 0, /* 0x95 */ + 0, /* 0x96 */ + 0, /* 0x97 */ + 0, /* 0x98 */ + 0, /* 0x99 */ + 0, /* 0x9a */ + 0, /* 0x9b */ + 0, /* 0x9c */ + 0, /* 0x9d */ + 0, /* 0x9e */ + 0, /* 0x9f */ + 0, /* 0xa0 */ + 0, /* 0xa1 */ + 0, /* 0xa2 */ + 0, /* 0xa3 */ + 0, /* 0xa4 */ + 0, /* 0xa5 */ + 0, /* 0xa6 */ + 0, /* 0xa7 */ + 0, /* 0xa8 */ + 0, /* 0xa9 */ + 0, /* 0xaa */ + 0, /* 0xab */ + 0, /* 0xac */ + 0, /* 0xad */ + 0, /* 0xae */ + 0, /* 0xaf */ + 0, /* 0xb0 */ + 0, /* 0xb1 */ + 0, /* 0xb2 */ + 0, /* 0xb3 */ + 0, /* 0xb4 */ + 0, /* 0xb5 */ + 0, /* 0xb6 */ + 0, /* 0xb7 */ + 0, /* 0xb8 */ + 0, /* 0xb9 */ + 0, /* 0xba */ + 0, /* 0xbb */ + 0, /* 0xbc */ + 0, /* 0xbd */ + 0, /* 0xbe */ + 0, /* 0xbf */ + 0, /* 0xc0 */ + 0, /* 0xc1 */ + 0, /* 0xc2 */ + 0, /* 0xc3 */ + 0, /* 0xc4 */ + 0, /* 0xc5 */ + 0, /* 0xc6 */ + 0, /* 0xc7 */ + 0, /* 0xc8 */ + 0, /* 0xc9 */ + 0, /* 0xca */ + 0, /* 0xcb */ + 0, /* 0xcc */ + 0, /* 0xcd */ + 0, /* 0xce */ + 0, /* 0xcf */ + 0, /* 0xd0 */ + 0, /* 0xd1 */ + 0, /* 0xd2 */ + 0, /* 0xd3 */ + 0, /* 0xd4 */ + 0, /* 0xd5 */ + 0, /* 0xd6 */ + 0, /* 0xd7 */ + 0, /* 0xd8 */ + 0, /* 0xd9 */ + 0, /* 0xda */ + 0, /* 0xdb */ + 0, /* 0xdc */ + 0, /* 0xdd */ + 0, /* 0xde */ + 0, /* 0xdf */ + 0, /* 0xe0 */ + 0, /* 0xe1 */ + 0, /* 0xe2 */ + 0, /* 0xe3 */ + 0, /* 0xe4 */ + 0, /* 0xe5 */ + 0, /* 0xe6 */ + 0, /* 0xe7 */ + 0, /* 0xe8 */ + 0, /* 0xe9 */ + 0, /* 0xea */ + 0, /* 0xeb */ + 0, /* 0xec */ + 0, /* 0xed */ + 0, /* 0xee */ + 0, /* 0xef */ + 0, /* 0xf0 */ + 0, /* 0xf1 */ + 0, /* 0xf2 */ + 0, /* 0xf3 */ + 0, /* 0xf4 */ + 0, /* 0xf5 */ + 0, /* 0xf6 */ + 0, /* 0xf7 */ + 0, /* 0xf8 */ + 0, /* 0xf9 */ + 0, /* 0xfa */ + 0, /* 0xfb */ + 0, /* 0xfc */ + 0, /* 0xfd */ + 0, /* 0xfe */ + 0 /* 0xff */ +}; + +unsigned short *_pctype = _ctype + 1; +unsigned short *_pwctype = _ctype + 1; + +int _isctype (int c, int ctypeFlags) +{ + return (_pctype[(unsigned char)(c & 0xFF)] & ctypeFlags); +} + +int iswctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + + +int isalpha(int c) +{ + return(_isctype(c, _ALPHA)); +} + +/* +int isalnum(int c) +{ + return(_isctype(c, _ALPHA | _DIGIT)); +} + +int __isascii(int c) +{ + return ((unsigned char)c <= 0x7f); +} + +int iscntrl(int c) +{ + return(_isctype(c, _CONTROL)); +} + +int __iscsym(int c) +{ + return(isalnum(c)||(c == '_')); +} + +int __iscsymf(int c) +{ + return(isalpha(c)||(c == '_')); +} +*/ + +int isdigit(int c) +{ + return(_isctype(c, _DIGIT)); +} + +/* +int isgraph(int c) +{ + return (_isctype (c, _PUNCT | _ALPHA | _DIGIT)); +} +*/ + +int islower(int c) +{ + return (_isctype (c, _LOWER)); +} + +int isprint(int c) +{ + return (_isctype (c, _BLANK | _PUNCT | _ALPHA | _DIGIT)); +} + +/* +int ispunct(int c) +{ + return (_isctype (c, _PUNCT)); +} +*/ + +int isspace(int c) +{ + return (_isctype (c, _SPACE)); +} + +int isupper(int c) +{ + return (_isctype (c, _UPPER)); +} + +int isxdigit(int c) +{ + return (_isctype (c, _HEX)); +} + +/* +int iswalpha(wint_t c) +{ + return (iswctype (c, _ALPHA)); +} +*/ + +int iswdigit(wint_t c) +{ + return (iswctype (c, _DIGIT)); +} + +int iswlower(wint_t c) +{ + return (iswctype (c, _LOWER)); +} + +int iswxdigit(wint_t c) +{ + return (iswctype (c, _HEX)); +} + + +/* +int __toascii(int c) +{ + return((unsigned)(c) & 0x7f); +} + +int _tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int _toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} +*/ + +int tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +wchar_t towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +wchar_t towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/dos8dot3.c b/ntoskrnl/rtl/dos8dot3.c new file mode 100644 index 0000000..ffe8261 --- /dev/null +++ b/ntoskrnl/rtl/dos8dot3.c @@ -0,0 +1,253 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/dos8dot3.c + * PURPOSE: Short name (8.3 name) functions + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* CONSTANTS *****************************************************************/ + +const PWCHAR RtlpShortIllegals = L" ;+=[]',\"*\\<>/?:|"; + + +/* FUNCTIONS *****************************************************************/ + +static BOOLEAN +RtlpIsShortIllegal(WCHAR Char) +{ + int i; + + for (i = 0; RtlpShortIllegals[i]; i++) + { + if (Char == RtlpShortIllegals[i]) + return(TRUE); + } + + return(FALSE); +} + + +VOID STDCALL +RtlGenerate8dot3Name(IN PUNICODE_STRING Name, + IN BOOLEAN AllowExtendedCharacters, + IN OUT PGENERATE_NAME_CONTEXT Context, + OUT PUNICODE_STRING Name8dot3) +{ + WCHAR NameBuffer[8]; + WCHAR ExtBuffer[4]; + USHORT StrLength; + USHORT NameLength; + USHORT ExtLength; + USHORT CopyLength; + USHORT DotPos; + USHORT i, j; + USHORT CurrentIndex; + + memset(NameBuffer, 0, sizeof(NameBuffer)); + memset(ExtBuffer, 0, sizeof(ExtBuffer)); + + StrLength = Name->Length / sizeof(WCHAR); + DPRINT("StrLength: %hu\n", StrLength); + + /* Find last dot in Name */ + DotPos = 0; + for (i = 0; i < StrLength; i++) + { + if (Name->Buffer[i] == L'.') + { + DotPos = i; + } + } + + if (DotPos == 0) + { + DotPos = i; + } + DPRINT("DotPos: %hu\n", DotPos); + + /* Copy name (6 valid characters max) */ + for (i = 0, NameLength = 0; NameLength < 6 && i < DotPos; i++) + { + if ((!RtlpIsShortIllegal(Name->Buffer[i])) && + (Name->Buffer[i] != L'.')) + { + NameBuffer[NameLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]); + } + } + DPRINT("NameBuffer: '%.08S'\n", NameBuffer); + DPRINT("NameLength: %hu\n", NameLength); + + /* Copy extension (4 valid characters max) */ + if (DotPos < StrLength) + { + for (i = DotPos, ExtLength = 0; ExtLength < 4 && i < StrLength; i++) + { + if (!RtlpIsShortIllegal(Name->Buffer[i])) + { + ExtBuffer[ExtLength++] = RtlUpcaseUnicodeChar(Name->Buffer[i]); + } + } + } + else + { + ExtLength = 0; + } + DPRINT("ExtBuffer: '%.04S'\n", ExtBuffer); + DPRINT("ExtLength: %hu\n", ExtLength); + + /* Determine next index */ + CurrentIndex = Context->LastIndexValue; + CopyLength = min(NameLength, (CurrentIndex < 10) ? 6 : 5); + DPRINT("CopyLength: %hu\n", CopyLength); + + if ((Context->NameLength == CopyLength) && + (wcsncmp(Context->NameBuffer, NameBuffer, CopyLength) == 0) && + (Context->ExtensionLength == ExtLength) && + (wcsncmp(Context->ExtensionBuffer, ExtBuffer, ExtLength) == 0)) + CurrentIndex++; + else + CurrentIndex = 1; + DPRINT("CurrentIndex: %hu\n", CurrentIndex); + + /* Build the short name */ + for (i = 0; i < CopyLength; i++) + { + Name8dot3->Buffer[i] = NameBuffer[i]; + } + + Name8dot3->Buffer[i++] = L'~'; + if (CurrentIndex >= 10) + Name8dot3->Buffer[i++] = (CurrentIndex / 10) + L'0'; + Name8dot3->Buffer[i++] = (CurrentIndex % 10) + L'0'; + + for (j = 0; j < ExtLength; i++, j++) + { + Name8dot3->Buffer[i] = ExtBuffer[j]; + } + + Name8dot3->Length = i * sizeof(WCHAR); + + DPRINT("Name8dot3: '%wZ'\n", Name8dot3); + + /* Update context */ + Context->NameLength = CopyLength; + for (i = 0; i < CopyLength; i++) + { + Context->NameBuffer[i] = NameBuffer[i]; + } + + Context->ExtensionLength = ExtLength; + for (i = 0; i < ExtLength; i++) + { + Context->ExtensionBuffer[i] = ExtBuffer[i]; + } + + Context->LastIndexValue = CurrentIndex; +} + + +BOOLEAN STDCALL +RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName, + IN PANSI_STRING AnsiName, + OUT PBOOLEAN SpacesFound) +{ + PANSI_STRING name = AnsiName; + ANSI_STRING DummyString; + CHAR Buffer[12]; + char *str; + ULONG Length; + ULONG i; + NTSTATUS Status; + BOOLEAN HasSpace = FALSE; + BOOLEAN HasDot = FALSE; + + if (UnicodeName->Length > 24) + { + return(FALSE); /* name too long */ + } + + if (!name) + { + name = &DummyString; + name->Length = 0; + name->MaximumLength = 12; + name->Buffer = Buffer; + } + + Status = RtlUpcaseUnicodeStringToCountedOemString(name, + UnicodeName, + FALSE); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + Length = name->Length; + str = name->Buffer; + + if (!(Length == 1 && *str == '.') && + !(Length == 2 && *str == '.' && *(str + 1) == '.')) + { + for (i = 0; i < Length; i++, str++) + { + switch (*str) + { + case ' ': + HasSpace = TRUE; + break; + + case '.': + if ((HasDot) || /* two or more dots */ + (i == 0) || /* dot is first char */ + (i + 1 == Length) || /* dot is last char */ + (Length - i > 4) || /* more than 3 chars of extension */ + (HasDot == FALSE && i > 8)) /* name is longer than 8 chars */ + return(FALSE); + HasDot = TRUE; + break; + } + } + } + + /* Name is longer than 8 chars and does not have an extension */ + if (Length > 8 && HasDot == FALSE) + { + return(FALSE); + } + + if (SpacesFound) + *SpacesFound = HasSpace; + + return(TRUE); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/error.c b/ntoskrnl/rtl/error.c new file mode 100644 index 0000000..7e02546 --- /dev/null +++ b/ntoskrnl/rtl/error.c @@ -0,0 +1,963 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Rtl error functions + * FILE: lib/ntdll/rtl/error.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 22/07/99: Added RtlNtStatusToDosError. + * 1999-11-30: Added RtlNtStatusToPsxErrno. + * 1999-12-18: STDCALL RtlNtStatusToDosError + */ + +/* + * Partially taken from WINE, original copyright: + * + * Copyright 2000 Alexandre Julliard + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) +#define LOWORD(l) ((WORD)(l)) + +/* TYPES *******************************************************************/ + +typedef struct _ERROR_TABLE +{ + ULONG Start; + ULONG End; + const WORD *Table; +} ERROR_TABLE, *PERROR_TABLE; + + +/* FUNCTIONS ***************************************************************/ + +static const WORD table_00000103[11] = +{ + ERROR_IO_PENDING, /* 00000103 (STATUS_PENDING) */ + ERROR_MR_MID_NOT_FOUND, /* 00000104 (STATUS_REPARSE) */ + ERROR_MORE_DATA, /* 00000105 (STATUS_MORE_ENTRIES) */ + ERROR_NOT_ALL_ASSIGNED, /* 00000106 (STATUS_NOT_ALL_ASSIGNED) */ + ERROR_SOME_NOT_MAPPED, /* 00000107 (STATUS_SOME_NOT_MAPPED) */ + ERROR_MR_MID_NOT_FOUND, /* 00000108 (STATUS_OPLOCK_BREAK_IN_PROCESS) */ + ERROR_MR_MID_NOT_FOUND, /* 00000109 (STATUS_VOLUME_MOUNTED) */ + ERROR_MR_MID_NOT_FOUND, /* 0000010a (STATUS_RXACT_COMMITTED) */ + ERROR_MR_MID_NOT_FOUND, /* 0000010b (STATUS_NOTIFY_CLEANUP) */ + ERROR_NOTIFY_ENUM_DIR, /* 0000010c (STATUS_NOTIFY_ENUM_DIR) */ + ERROR_NO_QUOTAS_FOR_ACCOUNT /* 0000010d (STATUS_NO_QUOTAS_FOR_ACCOUNT) */ +// /* 0000010e (STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED) */ +}; + +static const WORD table_40000002[12] = +{ + ERROR_INVALID_PARAMETER, /* 40000002 */ + ERROR_MR_MID_NOT_FOUND, /* 40000003 */ + ERROR_MR_MID_NOT_FOUND, /* 40000004 */ + ERROR_MR_MID_NOT_FOUND, /* 40000005 */ + ERROR_LOCAL_USER_SESSION_KEY, /* 40000006 (STATUS_LOCAL_USER_SESSION_KEY) */ + ERROR_MR_MID_NOT_FOUND, /* 40000007 */ + ERROR_MORE_WRITES, /* 40000008 (STATUS_SERIAL_MORE_WRITES) */ + ERROR_REGISTRY_RECOVERED, /* 40000009 (STATUS_REGISTRY_RECOVERED) */ + ERROR_MR_MID_NOT_FOUND, /* 4000000a */ + ERROR_MR_MID_NOT_FOUND, /* 4000000b */ + ERROR_COUNTER_TIMEOUT, /* 4000000c (STATUS_SERIAL_COUNTER_TIMEOUT) */ + ERROR_NULL_LM_PASSWORD /* 4000000d (STATUS_NULL_LM_PASSWORD) */ +}; + +static const WORD table_40020056[1] = +{ + RPC_S_UUID_LOCAL_ONLY /* 40020056 */ +}; + +static const WORD table_400200af[1] = +{ + RPC_S_SEND_INCOMPLETE /* 400200af */ +}; + +static const WORD table_80000001[38] = +{ + 0, /* 80000001 (STATUS_GUARD_PAGE_VIOLATION) */ + ERROR_NOACCESS, /* 80000002 (STATUS_DATATYPE_MISALIGNMENT) */ + 0, /* 80000003 (STATUS_BREAKPOINT) */ + 0, /* 80000004 (STATUS_SINGLE_STEP) */ + ERROR_MORE_DATA, /* 80000005 (STATUS_BUFFER_OVERFLOW) */ + ERROR_NO_MORE_FILES, /* 80000006 (STATUS_NO_MORE_FILES) */ + ERROR_MR_MID_NOT_FOUND, /* 80000007 (STATUS_WAKE_SYSTEM_DEBUGGER) */ + ERROR_MR_MID_NOT_FOUND, /* 80000008 */ + ERROR_MR_MID_NOT_FOUND, /* 80000009 */ + ERROR_MR_MID_NOT_FOUND, /* 8000000a (STATUS_HANDLES_CLOSED) */ + ERROR_NO_INHERITANCE, /* 8000000b (STATUS_NO_INHERITANCE) */ + ERROR_MR_MID_NOT_FOUND, /* 8000000c (STATUS_GUID_SUBSTITUTION_MADE) */ + ERROR_PARTIAL_COPY, /* 8000000d (STATUS_PARTIAL_COPY) */ + ERROR_OUT_OF_PAPER, /* 8000000e (STATUS_DEVICE_PAPER_EMPTY) */ + ERROR_NOT_READY, /* 8000000f (STATUS_DEVICE_POWERED_OFF) */ + ERROR_NOT_READY, /* 80000010 (STATUS_DEVICE_OFF_LINE) */ + ERROR_BUSY, /* 80000011 (STATUS_DEVICE_BUSY) */ + ERROR_NO_MORE_ITEMS, /* 80000012 (STATUS_NO_MORE_EAS) */ + ERROR_INVALID_EA_NAME, /* 80000013 (STATUS_INVALID_EA_NAME) */ + ERROR_EA_LIST_INCONSISTENT, /* 80000014 (STATUS_EA_LIST_INCONSISTENT) */ + ERROR_EA_LIST_INCONSISTENT, /* 80000015 (STATUS_INVALID_EA_FLAG) */ + ERROR_MEDIA_CHANGED, /* 80000016 (STATUS_VERIFY_REQUIRED) */ + ERROR_MR_MID_NOT_FOUND, /* 80000017 (STATUS_EXTRANEOUS_INFORMATION) */ + ERROR_MR_MID_NOT_FOUND, /* 80000018 (STATUS_RXACT_COMMIT_NECESSARY) */ + ERROR_MR_MID_NOT_FOUND, /* 80000019 */ + ERROR_NO_MORE_ITEMS, /* 8000001a (STATUS_NO_MORE_ENTRIES) */ + ERROR_FILEMARK_DETECTED, /* 8000001b (STATUS_FILEMARK_DETECTED) */ + ERROR_MEDIA_CHANGED, /* 8000001c (STATUS_MEDIA_CHANGED) */ + ERROR_BUS_RESET, /* 8000001d (STATUS_BUS_RESET) */ + ERROR_END_OF_MEDIA, /* 8000001e (STATUS_END_OF_MEDIA) */ + ERROR_BEGINNING_OF_MEDIA, /* 8000001f (STATUS_BEGINNING_OF_MEDIA) */ + ERROR_MR_MID_NOT_FOUND, /* 80000020 (STATUS_MEDIA_CHECK) */ + ERROR_SETMARK_DETECTED, /* 80000021 (STATUS_SETMARK_DETECTED) */ + ERROR_NO_DATA_DETECTED, /* 80000022 (STATUS_NO_DATA_DETECTED) */ + ERROR_MR_MID_NOT_FOUND, /* 80000023 (STATUS_REDIRECTOR_HAS_OPEN_HANDLES) */ + ERROR_MR_MID_NOT_FOUND, /* 80000024 (STATUS_SERVER_HAS_OPEN_HANDLES) */ + ERROR_ACTIVE_CONNECTIONS, /* 80000025 (STATUS_ALREADY_DISCONNECTED) */ + ERROR_MR_MID_NOT_FOUND /* 80000026 (STATUS_LONGJUMP) */ +}; + +static const WORD table_80090300[23] = +{ + ERROR_NO_SYSTEM_RESOURCES, /* 80090300 */ + ERROR_INVALID_HANDLE, /* 80090301 */ + ERROR_INVALID_FUNCTION, /* 80090302 */ + ERROR_BAD_NETPATH, /* 80090303 */ + ERROR_INTERNAL_ERROR, /* 80090304 */ + ERROR_NO_SUCH_PACKAGE, /* 80090305 */ + ERROR_NOT_OWNER, /* 80090306 */ + ERROR_NO_SUCH_PACKAGE, /* 80090307 */ + ERROR_INVALID_PARAMETER, /* 80090308 */ + ERROR_INVALID_PARAMETER, /* 80090309 */ + ERROR_NOT_SUPPORTED, /* 8009030a */ + ERROR_CANNOT_IMPERSONATE, /* 8009030b */ + ERROR_LOGON_FAILURE, /* 8009030c */ + ERROR_INVALID_PARAMETER, /* 8009030d */ + ERROR_NO_SUCH_LOGON_SESSION, /* 8009030e */ + ERROR_ACCESS_DENIED, /* 8009030f */ + ERROR_ACCESS_DENIED, /* 80090310 */ + ERROR_NO_LOGON_SERVERS, /* 80090311 */ + ERROR_MR_MID_NOT_FOUND, /* 80090312 */ + ERROR_MR_MID_NOT_FOUND, /* 80090313 */ + ERROR_MR_MID_NOT_FOUND, /* 80090314 */ + ERROR_MR_MID_NOT_FOUND, /* 80090315 */ + ERROR_NO_SUCH_PACKAGE /* 80090316 */ +}; + +static const WORD table_c0000001[411] = +{ + ERROR_GEN_FAILURE, /* c0000001 (STATUS_UNSUCCESSFUL) */ + ERROR_INVALID_FUNCTION, /* c0000002 (STATUS_NOT_IMPLEMENTED) */ + ERROR_INVALID_PARAMETER, /* c0000003 (STATUS_INVALID_INFO_CLASS) */ + ERROR_BAD_LENGTH, /* c0000004 (STATUS_INFO_LENGTH_MISMATCH) */ + ERROR_NOACCESS, /* c0000005 (STATUS_ACCESS_VIOLATION) */ + ERROR_SWAPERROR, /* c0000006 (STATUS_IN_PAGE_ERROR) */ + ERROR_PAGEFILE_QUOTA, /* c0000007 (STATUS_PAGEFILE_QUOTA) */ + ERROR_INVALID_HANDLE, /* c0000008 (STATUS_INVALID_HANDLE) */ + ERROR_STACK_OVERFLOW, /* c0000009 (STATUS_BAD_INITIAL_STACK) */ + ERROR_BAD_EXE_FORMAT, /* c000000a (STATUS_BAD_INITIAL_PC) */ + ERROR_INVALID_PARAMETER, /* c000000b (STATUS_INVALID_CID) */ + ERROR_MR_MID_NOT_FOUND, /* c000000c (STATUS_TIMER_NOT_CANCELED) */ + ERROR_INVALID_PARAMETER, /* c000000d (STATUS_INVALID_PARAMETER) */ + ERROR_FILE_NOT_FOUND, /* c000000e (STATUS_NO_SUCH_DEVICE) */ + ERROR_FILE_NOT_FOUND, /* c000000f (STATUS_NO_SUCH_FILE) */ + ERROR_INVALID_FUNCTION, /* c0000010 (STATUS_INVALID_DEVICE_REQUEST) */ + ERROR_HANDLE_EOF, /* c0000011 (STATUS_END_OF_FILE) */ + ERROR_WRONG_DISK, /* c0000012 (STATUS_WRONG_VOLUME) */ + ERROR_NOT_READY, /* c0000013 (STATUS_NO_MEDIA_IN_DEVICE) */ + ERROR_UNRECOGNIZED_MEDIA, /* c0000014 (STATUS_UNRECOGNIZED_MEDIA) */ + ERROR_SECTOR_NOT_FOUND, /* c0000015 (STATUS_NONEXISTENT_SECTOR) */ + ERROR_MORE_DATA, /* c0000016 (STATUS_MORE_PROCESSING_REQUIRED) */ + ERROR_NOT_ENOUGH_MEMORY, /* c0000017 (STATUS_NO_MEMORY) */ + ERROR_INVALID_ADDRESS, /* c0000018 (STATUS_CONFLICTING_ADDRESSES) */ + ERROR_INVALID_ADDRESS, /* c0000019 (STATUS_NOT_MAPPED_VIEW) */ + ERROR_INVALID_PARAMETER, /* c000001a (STATUS_UNABLE_TO_FREE_VM) */ + ERROR_INVALID_PARAMETER, /* c000001b (STATUS_UNABLE_TO_DELETE_SECTION) */ + ERROR_INVALID_FUNCTION, /* c000001c (STATUS_INVALID_SYSTEM_SERVICE) */ + 0, /* c000001d (STATUS_ILLEGAL_INSTRUCTION) */ + ERROR_ACCESS_DENIED, /* c000001e (STATUS_INVALID_LOCK_SEQUENCE) */ + ERROR_ACCESS_DENIED, /* c000001f (STATUS_INVALID_VIEW_SIZE) */ + ERROR_BAD_EXE_FORMAT, /* c0000020 (STATUS_INVALID_FILE_FOR_SECTION) */ + ERROR_ACCESS_DENIED, /* c0000021 (STATUS_ALREADY_COMMITTED) */ + ERROR_ACCESS_DENIED, /* c0000022 (STATUS_ACCESS_DENIED) */ + ERROR_INSUFFICIENT_BUFFER, /* c0000023 (STATUS_BUFFER_TOO_SMALL) */ + ERROR_INVALID_HANDLE, /* c0000024 (STATUS_OBJECT_TYPE_MISMATCH) */ + 0, /* c0000025 (STATUS_NONCONTINUABLE_EXCEPTION) */ + 0, /* c0000026 (STATUS_INVALID_DISPOSITION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000027 (STATUS_UNWIND) */ + ERROR_MR_MID_NOT_FOUND, /* c0000028 (STATUS_BAD_STACK) */ + ERROR_MR_MID_NOT_FOUND, /* c0000029 (STATUS_INVALID_UNWIND_TARGET) */ + ERROR_NOT_LOCKED, /* c000002a (STATUS_NOT_LOCKED) */ + 0, /* c000002b (STATUS_PARITY_ERROR) */ + ERROR_INVALID_ADDRESS, /* c000002c (STATUS_UNABLE_TO_DECOMMIT_VM) */ + ERROR_INVALID_ADDRESS, /* c000002d (STATUS_NOT_COMMITTED) */ + ERROR_MR_MID_NOT_FOUND, /* c000002e (STATUS_INVALID_PORT_ATTRIBUTES) */ + ERROR_MR_MID_NOT_FOUND, /* c000002f (STATUS_PORT_MESSAGE_TOO_LONG) */ + ERROR_INVALID_PARAMETER, /* c0000030 (STATUS_INVALID_PARAMETER_MIX) */ + ERROR_MR_MID_NOT_FOUND, /* c0000031 (STATUS_INVALID_QUOTA_LOWER) */ + ERROR_DISK_CORRUPT, /* c0000032 (STATUS_DISK_CORRUPT_ERROR) */ + ERROR_INVALID_NAME, /* c0000033 (STATUS_OBJECT_NAME_INVALID) */ + ERROR_FILE_NOT_FOUND, /* c0000034 (STATUS_OBJECT_NAME_NOT_FOUND) */ + ERROR_ALREADY_EXISTS, /* c0000035 (STATUS_OBJECT_NAME_COLLISION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000036 */ + ERROR_INVALID_HANDLE, /* c0000037 (STATUS_PORT_DISCONNECTED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000038 (STATUS_DEVICE_ALREADY_ATTACHED) */ + ERROR_BAD_PATHNAME, /* c0000039 (STATUS_OBJECT_PATH_INVALID) */ + ERROR_PATH_NOT_FOUND, /* c000003a (STATUS_OBJECT_PATH_NOT_FOUND) */ + ERROR_BAD_PATHNAME, /* c000003b (STATUS_PATH_SYNTAX_BAD) */ + ERROR_IO_DEVICE, /* c000003c (STATUS_DATA_OVERRUN) */ + ERROR_IO_DEVICE, /* c000003d (STATUS_DATA_LATE_ERROR) */ + ERROR_CRC, /* c000003e (STATUS_DATA_ERROR) */ + ERROR_CRC, /* c000003f (STATUS_CRC_ERROR) */ + ERROR_NOT_ENOUGH_MEMORY, /* c0000040 (STATUS_SECTION_TOO_BIG) */ + ERROR_ACCESS_DENIED, /* c0000041 (STATUS_PORT_CONNECTION_REFUSED) */ + ERROR_INVALID_HANDLE, /* c0000042 (STATUS_INVALID_PORT_HANDLE) */ + ERROR_SHARING_VIOLATION, /* c0000043 (STATUS_SHARING_VIOLATION) */ + ERROR_NOT_ENOUGH_QUOTA, /* c0000044 (STATUS_QUOTA_EXCEEDED) */ + ERROR_INVALID_PARAMETER, /* c0000045 (STATUS_INVALID_PAGE_PROTECTION) */ + ERROR_NOT_OWNER, /* c0000046 (STATUS_MUTANT_NOT_OWNED) */ + ERROR_TOO_MANY_POSTS, /* c0000047 (STATUS_SEMAPHORE_LIMIT_EXCEEDED) */ + ERROR_INVALID_PARAMETER, /* c0000048 (STATUS_PORT_ALREADY_SET) */ + ERROR_INVALID_PARAMETER, /* c0000049 (STATUS_SECTION_NOT_IMAGE) */ + ERROR_SIGNAL_REFUSED, /* c000004a (STATUS_SUSPEND_COUNT_EXCEEDED) */ + ERROR_ACCESS_DENIED, /* c000004b (STATUS_THREAD_IS_TERMINATING) */ + ERROR_INVALID_PARAMETER, /* c000004c (STATUS_BAD_WORKING_SET_LIMIT) */ + ERROR_INVALID_PARAMETER, /* c000004d (STATUS_INCOMPATIBLE_FILE_MAP) */ + ERROR_INVALID_PARAMETER, /* c000004e (STATUS_SECTION_PROTECTION) */ + ERROR_MR_MID_NOT_FOUND, /* c000004f (STATUS_EAS_NOT_SUPPORTED) */ + ERROR_EA_LIST_INCONSISTENT, /* c0000050 (STATUS_EA_TOO_LARGE) */ + ERROR_FILE_CORRUPT, /* c0000051 (STATUS_NONEXISTENT_EA_ENTRY) */ + ERROR_FILE_CORRUPT, /* c0000052 (STATUS_NO_EAS_ON_FILE) */ + ERROR_FILE_CORRUPT, /* c0000053 (STATUS_EA_CORRUPT_ERROR) */ + ERROR_LOCK_VIOLATION, /* c0000054 (STATUS_LOCK_NOT_GRANTED) */ + ERROR_LOCK_VIOLATION, /* c0000055 (STATUS_FILE_LOCK_CONFLICT) */ + ERROR_ACCESS_DENIED, /* c0000056 (STATUS_DELETE_PENDING) */ + ERROR_NOT_SUPPORTED, /* c0000057 (STATUS_CTL_FILE_NOT_SUPPORTED) */ + ERROR_UNKNOWN_REVISION, /* c0000058 (STATUS_UNKNOWN_REVISION) */ + ERROR_REVISION_MISMATCH, /* c0000059 (STATUS_REVISION_MISMATCH) */ + ERROR_INVALID_OWNER, /* c000005a (STATUS_INVALID_OWNER) */ + ERROR_INVALID_PRIMARY_GROUP, /* c000005b (STATUS_INVALID_PRIMARY_GROUP) */ + ERROR_NO_IMPERSONATION_TOKEN, /* c000005c (STATUS_NO_IMPERSONATION_TOKEN) */ + ERROR_CANT_DISABLE_MANDATORY, /* c000005d (STATUS_CANT_DISABLE_MANDATORY) */ + ERROR_NO_LOGON_SERVERS, /* c000005e (STATUS_NO_LOGON_SERVERS) */ + ERROR_NO_SUCH_LOGON_SESSION, /* c000005f (STATUS_NO_SUCH_LOGON_SESSION) */ + ERROR_NO_SUCH_PRIVILEGE, /* c0000060 (STATUS_NO_SUCH_PRIVILEGE) */ + ERROR_PRIVILEGE_NOT_HELD, /* c0000061 (STATUS_PRIVILEGE_NOT_HELD) */ + ERROR_INVALID_ACCOUNT_NAME, /* c0000062 (STATUS_INVALID_ACCOUNT_NAME) */ + ERROR_USER_EXISTS, /* c0000063 (STATUS_USER_EXISTS) */ + ERROR_NO_SUCH_USER, /* c0000064 (STATUS_NO_SUCH_USER) */ + ERROR_GROUP_EXISTS, /* c0000065 (STATUS_GROUP_EXISTS) */ + ERROR_NO_SUCH_GROUP, /* c0000066 (STATUS_NO_SUCH_GROUP) */ + ERROR_MEMBER_IN_GROUP, /* c0000067 (STATUS_MEMBER_IN_GROUP) */ + ERROR_MEMBER_NOT_IN_GROUP, /* c0000068 (STATUS_MEMBER_NOT_IN_GROUP) */ + ERROR_LAST_ADMIN, /* c0000069 (STATUS_LAST_ADMIN) */ + ERROR_INVALID_PASSWORD, /* c000006a (STATUS_WRONG_PASSWORD) */ + ERROR_ILL_FORMED_PASSWORD, /* c000006b (STATUS_ILL_FORMED_PASSWORD) */ + ERROR_PASSWORD_RESTRICTION, /* c000006c (STATUS_PASSWORD_RESTRICTION) */ + ERROR_LOGON_FAILURE, /* c000006d (STATUS_LOGON_FAILURE) */ + ERROR_ACCOUNT_RESTRICTION, /* c000006e (STATUS_ACCOUNT_RESTRICTION) */ + ERROR_INVALID_LOGON_HOURS, /* c000006f (STATUS_INVALID_LOGON_HOURS) */ + ERROR_INVALID_WORKSTATION, /* c0000070 (STATUS_INVALID_WORKSTATION) */ + ERROR_PASSWORD_EXPIRED, /* c0000071 (STATUS_PASSWORD_EXPIRED) */ + ERROR_ACCOUNT_DISABLED, /* c0000072 (STATUS_ACCOUNT_DISABLED) */ + ERROR_NONE_MAPPED, /* c0000073 (STATUS_NONE_MAPPED) */ + ERROR_TOO_MANY_LUIDS_REQUESTED, /* c0000074 (STATUS_TOO_MANY_LUIDS_REQUESTED) */ + ERROR_LUIDS_EXHAUSTED, /* c0000075 (STATUS_LUIDS_EXHAUSTED) */ + ERROR_INVALID_SUB_AUTHORITY, /* c0000076 (STATUS_INVALID_SUB_AUTHORITY) */ + ERROR_INVALID_ACL, /* c0000077 (STATUS_INVALID_ACL) */ + ERROR_INVALID_SID, /* c0000078 (STATUS_INVALID_SID) */ + ERROR_INVALID_SECURITY_DESCR, /* c0000079 (STATUS_INVALID_SECURITY_DESCR) */ + ERROR_PROC_NOT_FOUND, /* c000007a (STATUS_PROCEDURE_NOT_FOUND) */ + ERROR_BAD_EXE_FORMAT, /* c000007b (STATUS_INVALID_IMAGE_FORMAT) */ + ERROR_NO_TOKEN, /* c000007c (STATUS_NO_TOKEN) */ + ERROR_BAD_INHERITANCE_ACL, /* c000007d (STATUS_BAD_INHERITANCE_ACL) */ + ERROR_NOT_LOCKED, /* c000007e (STATUS_RANGE_NOT_LOCKED) */ + ERROR_DISK_FULL, /* c000007f (STATUS_DISK_FULL) */ + ERROR_SERVER_DISABLED, /* c0000080 (STATUS_SERVER_DISABLED) */ + ERROR_SERVER_NOT_DISABLED, /* c0000081 (STATUS_SERVER_NOT_DISABLED) */ + ERROR_TOO_MANY_NAMES, /* c0000082 (STATUS_TOO_MANY_GUIDS_REQUESTED) */ + ERROR_NO_MORE_ITEMS, /* c0000083 (STATUS_GUIDS_EXHAUSTED) */ + ERROR_INVALID_ID_AUTHORITY, /* c0000084 (STATUS_INVALID_ID_AUTHORITY) */ + ERROR_NO_MORE_ITEMS, /* c0000085 (STATUS_AGENTS_EXHAUSTED) */ + ERROR_LABEL_TOO_LONG, /* c0000086 (STATUS_INVALID_VOLUME_LABEL) */ + ERROR_OUTOFMEMORY, /* c0000087 (STATUS_SECTION_NOT_EXTENDED) */ + ERROR_INVALID_ADDRESS, /* c0000088 (STATUS_NOT_MAPPED_DATA) */ + ERROR_RESOURCE_DATA_NOT_FOUND, /* c0000089 (STATUS_RESOURCE_DATA_NOT_FOUND) */ + ERROR_RESOURCE_TYPE_NOT_FOUND, /* c000008a (STATUS_RESOURCE_TYPE_NOT_FOUND) */ + ERROR_RESOURCE_NAME_NOT_FOUND, /* c000008b (STATUS_RESOURCE_NAME_NOT_FOUND) */ + 0, /* c000008c (STATUS_ARRAY_BOUNDS_EXCEEDED) */ + 0, /* c000008d (STATUS_FLOAT_DENORMAL_OPERAND) */ + 0, /* c000008e (STATUS_FLOAT_DIVIDE_BY_ZERO) */ + 0, /* c000008f (STATUS_FLOAT_INEXACT_RESULT) */ + 0, /* c0000090 (STATUS_FLOAT_INVALID_OPERATION) */ + 0, /* c0000091 (STATUS_FLOAT_OVERFLOW) */ + 0, /* c0000092 (STATUS_FLOAT_STACK_CHECK) */ + 0, /* c0000093 (STATUS_FLOAT_UNDERFLOW) */ + 0, /* c0000094 (STATUS_INTEGER_DIVIDE_BY_ZERO) */ + ERROR_ARITHMETIC_OVERFLOW, /* c0000095 (STATUS_INTEGER_OVERFLOW) */ + 0, /* c0000096 (STATUS_PRIVILEGED_INSTRUCTION) */ + ERROR_NOT_ENOUGH_MEMORY, /* c0000097 (STATUS_TOO_MANY_PAGING_FILES) */ + ERROR_FILE_INVALID, /* c0000098 (STATUS_FILE_INVALID) */ + ERROR_ALLOTTED_SPACE_EXCEEDED, /* c0000099 (STATUS_ALLOTTED_SPACE_EXCEEDED) */ + ERROR_NO_SYSTEM_RESOURCES, /* c000009a (STATUS_INSUFFICIENT_RESOURCES) */ + ERROR_PATH_NOT_FOUND, /* c000009b (STATUS_DFS_EXIT_PATH_FOUND) */ + ERROR_CRC, /* c000009c (STATUS_DEVICE_DATA_ERROR) */ + ERROR_NOT_READY, /* c000009d (STATUS_DEVICE_NOT_CONNECTED) */ + ERROR_NOT_READY, /* c000009e (STATUS_DEVICE_POWER_FAILURE) */ + ERROR_INVALID_ADDRESS, /* c000009f (STATUS_FREE_VM_NOT_AT_BASE) */ + ERROR_INVALID_ADDRESS, /* c00000a0 (STATUS_MEMORY_NOT_ALLOCATED) */ + ERROR_WORKING_SET_QUOTA, /* c00000a1 (STATUS_WORKING_SET_QUOTA) */ + ERROR_WRITE_PROTECT, /* c00000a2 (STATUS_MEDIA_WRITE_PROTECTED) */ + ERROR_NOT_READY, /* c00000a3 (STATUS_DEVICE_NOT_READY) */ + ERROR_INVALID_GROUP_ATTRIBUTES, /* c00000a4 (STATUS_INVALID_GROUP_ATTRIBUTES) */ + ERROR_BAD_IMPERSONATION_LEVEL, /* c00000a5 (STATUS_BAD_IMPERSONATION_LEVEL) */ + ERROR_CANT_OPEN_ANONYMOUS, /* c00000a6 (STATUS_CANT_OPEN_ANONYMOUS) */ + ERROR_BAD_VALIDATION_CLASS, /* c00000a7 (STATUS_BAD_VALIDATION_CLASS) */ + ERROR_BAD_TOKEN_TYPE, /* c00000a8 (STATUS_BAD_TOKEN_TYPE)*/ + ERROR_MR_MID_NOT_FOUND, /* c00000a9 (STATUS_BAD_MASTER_BOOT_RECORD) */ + ERROR_MR_MID_NOT_FOUND, /* c00000aa (STATUS_INSTRUCTION_MISALIGNMENT) */ + ERROR_PIPE_BUSY, /* c00000ab (STATUS_INSTANCE_NOT_AVAILABLE) */ + ERROR_PIPE_BUSY, /* c00000ac (STATUS_PIPE_NOT_AVAILABLE) */ + ERROR_BAD_PIPE, /* c00000ad (STATUS_INVALID_PIPE_STATE) */ + ERROR_PIPE_BUSY, /* c00000ae (STATUS_PIPE_BUSY) */ + ERROR_INVALID_FUNCTION, /* c00000af (STATUS_ILLEGAL_FUNCTION) */ + ERROR_PIPE_NOT_CONNECTED, /* c00000b0 (STATUS_PIPE_DISCONNECTED) */ + ERROR_NO_DATA, /* c00000b1 (STATUS_PIPE_CLOSING) */ + ERROR_PIPE_CONNECTED, /* c00000b2 (STATUS_PIPE_CONNECTED) */ + ERROR_PIPE_LISTENING, /* c00000b3 (STATUS_PIPE_LISTENING) */ + ERROR_BAD_PIPE, /* c00000b4 (STATUS_INVALID_READ_MODE) */ + ERROR_SEM_TIMEOUT, /* c00000b5 (STATUS_IO_TIMEOUT) */ + ERROR_HANDLE_EOF, /* c00000b6 (STATUS_FILE_FORCED_CLOSED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000b7 (STATUS_PROFILING_NOT_STARTED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000b8 (STATUS_PROFILING_NOT_STOPPED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000b9 (STATUS_COULD_NOT_INTERPRET) */ + ERROR_ACCESS_DENIED, /* c00000ba (STATUS_FILE_IS_A_DIRECTORY) */ + ERROR_NOT_SUPPORTED, /* c00000bb (STATUS_NOT_SUPPORTED) */ + ERROR_REM_NOT_LIST, /* c00000bc (STATUS_REMOTE_NOT_LISTENING) */ + ERROR_DUP_NAME, /* c00000bd (STATUS_DUPLICATE_NAME) */ + ERROR_BAD_NETPATH, /* c00000be (STATUS_BAD_NETWORK_PATH) */ + ERROR_NETWORK_BUSY, /* c00000bf (STATUS_NETWORK_BUSY) */ + ERROR_DEV_NOT_EXIST, /* c00000c0 (STATUS_DEVICE_DOES_NOT_EXIST) */ + ERROR_TOO_MANY_CMDS, /* c00000c1 (STATUS_TOO_MANY_COMMANDS) */ + ERROR_ADAP_HDW_ERR, /* c00000c2 (STATUS_ADAPTER_HARDWARE_ERROR) */ + ERROR_BAD_NET_RESP, /* c00000c3 (STATUS_INVALID_NETWORK_RESPONSE) */ + ERROR_UNEXP_NET_ERR, /* c00000c4 (STATUS_UNEXPECTED_NETWORK_ERROR) */ + ERROR_BAD_REM_ADAP, /* c00000c5 (STATUS_BAD_REMOTE_ADAPTER) */ + ERROR_PRINTQ_FULL, /* c00000c6 (STATUS_PRINT_QUEUE_FULL) */ + ERROR_NO_SPOOL_SPACE, /* c00000c7 (STATUS_NO_SPOOL_SPACE) */ + ERROR_PRINT_CANCELLED, /* c00000c8 (STATUS_PRINT_CANCELLED) */ + ERROR_NETNAME_DELETED, /* c00000c9 (STATUS_NETWORK_NAME_DELETED) */ + ERROR_NETWORK_ACCESS_DENIED, /* c00000ca (STATUS_NETWORK_ACCESS_DENIED) */ + ERROR_BAD_DEV_TYPE, /* c00000cb (STATUS_BAD_DEVICE_TYPE) */ + ERROR_BAD_NET_NAME, /* c00000cc (STATUS_BAD_NETWORK_NAME) */ + ERROR_TOO_MANY_NAMES, /* c00000cd (STATUS_TOO_MANY_NAMES) */ + ERROR_TOO_MANY_SESS, /* c00000ce (STATUS_TOO_MANY_SESSIONS) */ + ERROR_SHARING_PAUSED, /* c00000cf (STATUS_SHARING_PAUSED) */ + ERROR_REQ_NOT_ACCEP, /* c00000d0 (STATUS_REQUEST_NOT_ACCEPTED) */ + ERROR_REDIR_PAUSED, /* c00000d1 (STATUS_REDIRECTOR_PAUSED) */ + ERROR_NET_WRITE_FAULT, /* c00000d2 (STATUS_NET_WRITE_FAULT) */ + ERROR_MR_MID_NOT_FOUND, /* c00000d3 (STATUS_PROFILING_AT_LIMIT) */ + ERROR_NOT_SAME_DEVICE, /* c00000d4 (STATUS_NOT_SAME_DEVICE) */ + ERROR_MR_MID_NOT_FOUND, /* c00000d5 (STATUS_FILE_RENAMED) */ + ERROR_VC_DISCONNECTED, /* c00000d6 (STATUS_VIRTUAL_CIRCUIT_CLOSED) */ + ERROR_NO_SECURITY_ON_OBJECT, /* c00000d7 (STATUS_NO_SECURITY_ON_OBJECT) */ + ERROR_MR_MID_NOT_FOUND, /* c00000d8 (STATUS_CANT_WAIT) */ + ERROR_NO_DATA, /* c00000d9 (STATUS_PIPE_EMPTY) */ + ERROR_CANT_ACCESS_DOMAIN_INFO, /* c00000da (STATUS_CANT_ACCESS_DOMAIN_INFO) */ + ERROR_MR_MID_NOT_FOUND, /* c00000db (STATUS_CANT_TERMINATE_SELF) */ + ERROR_INVALID_SERVER_STATE, /* c00000dc (STATUS_INVALID_SERVER_STATE) */ + ERROR_INVALID_DOMAIN_STATE, /* c00000dd (STATUS_INVALID_DOMAIN_STATE) */ + ERROR_INVALID_DOMAIN_ROLE, /* c00000de (STATUS_INVALID_DOMAIN_ROLE) */ + ERROR_NO_SUCH_DOMAIN, /* c00000df (STATUS_NO_SUCH_DOMAIN) */ + ERROR_DOMAIN_EXISTS, /* c00000e0 (STATUS_DOMAIN_EXISTS) */ + ERROR_DOMAIN_LIMIT_EXCEEDED, /* c00000e1 (STATUS_DOMAIN_LIMIT_EXCEEDED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000e2 (STATUS_OPLOCK_NOT_GRANTED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000e3 (STATUS_INVALID_OPLOCK_PROTOCOL) */ + ERROR_INTERNAL_DB_CORRUPTION, /* c00000e4 (STATUS_INTERNAL_DB_CORRUPTION) */ + ERROR_INTERNAL_ERROR, /* c00000e5 (STATUS_INTERNAL_ERROR) */ + ERROR_GENERIC_NOT_MAPPED, /* c00000e6 (STATUS_GENERIC_NOT_MAPPED) */ + ERROR_BAD_DESCRIPTOR_FORMAT, /* c00000e7 (STATUS_BAD_DESCRIPTOR_FORMAT) */ + ERROR_INVALID_USER_BUFFER, /* c00000e8 (STATUS_INVALID_USER_BUFFER) */ + ERROR_MR_MID_NOT_FOUND, /* c00000e9 (STATUS_UNEXPECTED_IO_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c00000ea (STATUS_UNEXPECTED_MM_CREATE_ERR) */ + ERROR_MR_MID_NOT_FOUND, /* c00000eb (STATUS_UNEXPECTED_MM_MAP_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c00000ec (STATUS_UNEXPECTED_MM_EXTEND_ERR) */ + ERROR_NOT_LOGON_PROCESS, /* c00000ed (STATUS_NOT_LOGON_PROCESS) */ + ERROR_LOGON_SESSION_EXISTS, /* c00000ee (STATUS_LOGON_SESSION_EXISTS) */ + ERROR_INVALID_PARAMETER, /* c00000ef (STATUS_INVALID_PARAMETER_1) */ + ERROR_INVALID_PARAMETER, /* c00000f0 (STATUS_INVALID_PARAMETER_2) */ + ERROR_INVALID_PARAMETER, /* c00000f1 (STATUS_INVALID_PARAMETER_3) */ + ERROR_INVALID_PARAMETER, /* c00000f2 (STATUS_INVALID_PARAMETER_4) */ + ERROR_INVALID_PARAMETER, /* c00000f3 (STATUS_INVALID_PARAMETER_5) */ + ERROR_INVALID_PARAMETER, /* c00000f4 (STATUS_INVALID_PARAMETER_6) */ + ERROR_INVALID_PARAMETER, /* c00000f5 (STATUS_INVALID_PARAMETER_7) */ + ERROR_INVALID_PARAMETER, /* c00000f6 (STATUS_INVALID_PARAMETER_8) */ + ERROR_INVALID_PARAMETER, /* c00000f7 (STATUS_INVALID_PARAMETER_9) */ + ERROR_INVALID_PARAMETER, /* c00000f8 (STATUS_INVALID_PARAMETER_10) */ + ERROR_INVALID_PARAMETER, /* c00000f9 (STATUS_INVALID_PARAMETER_11) */ + ERROR_INVALID_PARAMETER, /* c00000fa (STATUS_INVALID_PARAMETER_12) */ + ERROR_PATH_NOT_FOUND, /* c00000fb (STATUS_REDIRECTOR_NOT_STARTED) */ + ERROR_MR_MID_NOT_FOUND, /* c00000fc (STATUS_REDIRECTOR_STARTED) */ + ERROR_STACK_OVERFLOW, /* c00000fd (STATUS_STACK_OVERFLOW) */ + ERROR_NO_SUCH_PACKAGE, /* c00000fe (STATUS_NO_SUCH_PACKAGE) */ + ERROR_MR_MID_NOT_FOUND, /* c00000ff (STATUS_BAD_FUNCTION_TABLE) */ + ERROR_ENVVAR_NOT_FOUND, /* c0000100 (STATUS_VARIABLE_NOT_FOUND) */ + ERROR_DIR_NOT_EMPTY, /* c0000101 (STATUS_DIRECTORY_NOT_EMPTY) */ + ERROR_FILE_CORRUPT, /* c0000102 (STATUS_FILE_CORRUPT_ERROR) */ + ERROR_DIRECTORY, /* c0000103 (STATUS_NOT_A_DIRECTORY) */ + ERROR_BAD_LOGON_SESSION_STATE, /* c0000104 (STATUS_BAD_LOGON_SESSION_STATE) */ + ERROR_LOGON_SESSION_COLLISION, /* c0000105 (STATUS_LOGON_SESSION_COLLISION) */ + ERROR_FILENAME_EXCED_RANGE, /* c0000106 (STATUS_NAME_TOO_LONG) */ + ERROR_MR_MID_NOT_FOUND, /* c0000107 (STATUS_FILES_OPEN) */ + ERROR_DEVICE_IN_USE, /* c0000108 (STATUS_CONNECTION_IN_USE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000109 (STATUS_MESSAGE_NOT_FOUND) */ + ERROR_ACCESS_DENIED, /* c000010a (STATUS_PROCESS_IS_TERMINATING) */ + ERROR_INVALID_LOGON_TYPE, /* c000010b (STATUS_INVALID_LOGON_TYPE) */ + ERROR_MR_MID_NOT_FOUND, /* c000010c (STATUS_NO_GUID_TRANSLATION) */ + ERROR_CANNOT_IMPERSONATE, /* c000010d (STATUS_CANNOT_IMPERSONATE) */ + ERROR_SERVICE_ALREADY_RUNNING, /* c000010e (STATUS_IMAGE_ALREADY_LOADED) */ + ERROR_MR_MID_NOT_FOUND, /* c000010f (STATUS_ABIOS_NOT_PRESENT) */ + ERROR_MR_MID_NOT_FOUND, /* c0000110 (STATUS_ABIOS_LID_NOT_EXIST) */ + ERROR_MR_MID_NOT_FOUND, /* c0000111 (STATUS_ABIOS_LID_ALREADY_OWNED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000112 (STATUS_ABIOS_NOT_LID_OWNER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000113 (STATUS_ABIOS_INVALID_COMMAND) */ + ERROR_MR_MID_NOT_FOUND, /* c0000114 (STATUS_ABIOS_INVALID_LID) */ + ERROR_MR_MID_NOT_FOUND, /* c0000115 (STATUS_ABIOS_SELECTOR_NOT_AVAILABLE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000116 (STATUS_ABIOS_INVALID_SELECTOR) */ + ERROR_MR_MID_NOT_FOUND, /* c0000117 (STATUS_NO_LDT) */ + ERROR_MR_MID_NOT_FOUND, /* c0000118 (STATUS_INVALID_LDT_SIZE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000119 (STATUS_INVALID_LDT_OFFSET) */ + ERROR_MR_MID_NOT_FOUND, /* c000011a (STATUS_INVALID_LDT_DESCRIPTOR) */ + ERROR_BAD_EXE_FORMAT, /* c000011b (STATUS_INVALID_IMAGE_NE_FORMAT) */ + ERROR_RXACT_INVALID_STATE, /* c000011c (STATUS_RXACT_INVALID_STATE) */ + ERROR_RXACT_COMMIT_FAILURE, /* c000011d (STATUS_RXACT_COMMIT_FAILURE) */ + ERROR_FILE_INVALID, /* c000011e (STATUS_MAPPED_FILE_SIZE_ZERO) */ + ERROR_TOO_MANY_OPEN_FILES, /* c000011f (STATUS_TOO_MANY_OPENED_FILES) */ + ERROR_OPERATION_ABORTED, /* c0000120 (STATUS_CANCELLED) */ + ERROR_ACCESS_DENIED, /* c0000121 (STATUS_CANNOT_DELETE) */ + ERROR_INVALID_COMPUTERNAME, /* c0000122 (STATUS_INVALID_COMPUTER_NAME) */ + ERROR_ACCESS_DENIED, /* c0000123 (STATUS_FILE_DELETED) */ + ERROR_SPECIAL_ACCOUNT, /* c0000124 (STATUS_SPECIAL_ACCOUNT) */ + ERROR_SPECIAL_GROUP, /* c0000125 (STATUS_SPECIAL_GROUP) */ + ERROR_SPECIAL_USER, /* c0000126 (STATUS_SPECIAL_USER) */ + ERROR_MEMBERS_PRIMARY_GROUP, /* c0000127 (STATUS_MEMBERS_PRIMARY_GROUP) */ + ERROR_INVALID_HANDLE, /* c0000128 (STATUS_FILE_CLOSED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000129 (STATUS_TOO_MANY_THREADS) */ + ERROR_MR_MID_NOT_FOUND, /* c000012a (STATUS_THREAD_NOT_IN_PROCESS) */ + ERROR_TOKEN_ALREADY_IN_USE, /* c000012b (STATUS_TOKEN_ALREADY_IN_USE) */ + ERROR_MR_MID_NOT_FOUND, /* c000012c (STATUS_PAGEFILE_QUOTA_EXCEEDED) */ + ERROR_COMMITMENT_LIMIT, /* c000012d (STATUS_COMMITMENT_LIMIT) */ + ERROR_BAD_EXE_FORMAT, /* c000012e (STATUS_INVALID_IMAGE_LE_FORMAT) */ + ERROR_BAD_EXE_FORMAT, /* c000012f (STATUS_INVALID_IMAGE_NOT_MZ) */ + ERROR_BAD_EXE_FORMAT, /* c0000130 (STATUS_INVALID_IMAGE_PROTECT) */ + ERROR_BAD_EXE_FORMAT, /* c0000131 (STATUS_INVALID_IMAGE_WIN_16) */ + ERROR_MR_MID_NOT_FOUND, /* c0000132 (STATUS_LOGON_SERVER_CONFLICT) */ + ERROR_MR_MID_NOT_FOUND, /* c0000133 (STATUS_TIME_DIFFERENCE_AT_DC) */ + ERROR_MR_MID_NOT_FOUND, /* c0000134 (STATUS_SYNCHRONIZATION_REQUIRED) */ + ERROR_MOD_NOT_FOUND, /* c0000135 (STATUS_DLL_NOT_FOUND) */ + ERROR_MR_MID_NOT_FOUND, /* c0000136 (STATUS_OPEN_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000137 (STATUS_IO_PRIVILEGE_FAILED) */ + ERROR_INVALID_ORDINAL, /* c0000138 (STATUS_ORDINAL_NOT_FOUND) */ + ERROR_PROC_NOT_FOUND, /* c0000139 (STATUS_ENTRYPOINT_NOT_FOUND) */ + ERROR_MR_MID_NOT_FOUND, /* c000013a (STATUS_CONTROL_C_EXIT) */ + ERROR_NETNAME_DELETED, /* c000013b (STATUS_LOCAL_DISCONNECT) */ + ERROR_NETNAME_DELETED, /* c000013c (STATUS_REMOTE_DISCONNECT) */ + ERROR_REM_NOT_LIST, /* c000013d (STATUS_REMOTE_RESOURCES) */ + ERROR_UNEXP_NET_ERR, /* c000013e (STATUS_LINK_FAILED) */ + ERROR_UNEXP_NET_ERR, /* c000013f (STATUS_LINK_TIMEOUT) */ + ERROR_UNEXP_NET_ERR, /* c0000140 (STATUS_INVALID_CONNECTION) */ + ERROR_UNEXP_NET_ERR, /* c0000141 (STATUS_INVALID_ADDRESS) */ + ERROR_DLL_INIT_FAILED, /* c0000142 (STATUS_DLL_INIT_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000143 (STATUS_MISSING_SYSTEMFILE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000144 (STATUS_UNHANDLED_EXCEPTION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000145 (STATUS_APP_INIT_FAILURE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000146 (STATUS_PAGEFILE_CREATE_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c0000147 (STATUS_NO_PAGEFILE) */ + ERROR_INVALID_LEVEL, /* c0000148 (STATUS_INVALID_LEVEL) */ + ERROR_INVALID_PASSWORD, /* c0000149 (STATUS_WRONG_PASSWORD_CORE) */ + ERROR_MR_MID_NOT_FOUND, /* c000014a (STATUS_ILLEGAL_FLOAT_CONTEXT) */ + ERROR_BROKEN_PIPE, /* c000014b (STATUS_PIPE_BROKEN) */ + ERROR_BADDB, /* c000014c (STATUS_REGISTRY_CORRUPT) */ + ERROR_REGISTRY_IO_FAILED, /* c000014d (STATUS_REGISTRY_IO_FAILED) */ + ERROR_MR_MID_NOT_FOUND, /* c000014e (STATUS_NO_EVENT_PAIR) */ + ERROR_UNRECOGNIZED_VOLUME, /* c000014f (STATUS_UNRECOGNIZED_VOLUME) */ + ERROR_SERIAL_NO_DEVICE, /* c0000150 (STATUS_SERIAL_NO_DEVICE_INITED) */ + ERROR_NO_SUCH_ALIAS, /* c0000151 (STATUS_NO_SUCH_ALIAS) */ + ERROR_MEMBER_NOT_IN_ALIAS, /* c0000152 (STATUS_MEMBER_NOT_IN_ALIAS) */ + ERROR_MEMBER_IN_ALIAS, /* c0000153 (STATUS_MEMBER_IN_ALIAS) */ + ERROR_ALIAS_EXISTS, /* c0000154 (STATUS_ALIAS_EXISTS) */ + ERROR_LOGON_NOT_GRANTED, /* c0000155 (STATUS_LOGON_NOT_GRANTED) */ + ERROR_TOO_MANY_SECRETS, /* c0000156 (STATUS_TOO_MANY_SECRETS) */ + ERROR_SECRET_TOO_LONG, /* c0000157 (STATUS_SECRET_TOO_LONG) */ + ERROR_INTERNAL_DB_ERROR, /* c0000158 (STATUS_INTERNAL_DB_ERROR) */ + ERROR_FULLSCREEN_MODE, /* c0000159 (STATUS_FULLSCREEN_MODE) */ + ERROR_TOO_MANY_CONTEXT_IDS, /* c000015a (STATUS_TOO_MANY_CONTEXT_IDS) */ + ERROR_LOGON_TYPE_NOT_GRANTED, /* c000015b (STATUS_LOGON_TYPE_NOT_GRANTED) */ + ERROR_NOT_REGISTRY_FILE, /* c000015c (STATUS_NOT_REGISTRY_FILE) */ + ERROR_NT_CROSS_ENCRYPTION_REQUIRED, /* c000015d (STATUS_NT_CROSS_ENCRYPTION_REQUIRED) */ + ERROR_MR_MID_NOT_FOUND, /* c000015e (STATUS_DOMAIN_CTRLR_CONFIG_ERROR) */ + ERROR_IO_DEVICE, /* c000015f (STATUS_FT_MISSING_MEMBER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000160 (STATUS_ILL_FORMED_SERVICE_ENTRY) */ + ERROR_MR_MID_NOT_FOUND, /* c0000161 (STATUS_ILLEGAL_CHARACTER) */ + ERROR_NO_UNICODE_TRANSLATION, /* c0000162 (STATUS_UNMAPPABLE_CHARACTER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000163 (STATUS_UNDEFINED_CHARACTER) */ + ERROR_MR_MID_NOT_FOUND, /* c0000164 (STATUS_FLOPPY_VOLUME) */ + ERROR_FLOPPY_ID_MARK_NOT_FOUND, /* c0000165 (STATUS_FLOPPY_ID_MARK_NOT_FOUND) */ + ERROR_FLOPPY_WRONG_CYLINDER, /* c0000166 (STATUS_FLOPPY_WRONG_CYLINDER) */ + ERROR_FLOPPY_UNKNOWN_ERROR, /* c0000167 (STATUS_FLOPPY_UNKNOWN_ERROR) */ + ERROR_FLOPPY_BAD_REGISTERS, /* c0000168 (STATUS_FLOPPY_BAD_REGISTERS) */ + ERROR_DISK_RECALIBRATE_FAILED, /* c0000169 (STATUS_DISK_RECALIBRATE_FAILED) */ + ERROR_DISK_OPERATION_FAILED, /* c000016a (STATUS_DISK_OPERATION_FAILED) */ + ERROR_DISK_RESET_FAILED, /* c000016b (STATUS_DISK_RESET_FAILED) */ + ERROR_IRQ_BUSY, /* c000016c (STATUS_SHARED_IRQ_BUSY) */ + ERROR_IO_DEVICE, /* c000016d (STATUS_FT_ORPHANING) */ + ERROR_MR_MID_NOT_FOUND, /* c000016e (STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT) */ + ERROR_MR_MID_NOT_FOUND, /* c000016f */ + ERROR_MR_MID_NOT_FOUND, /* c0000170 */ + ERROR_MR_MID_NOT_FOUND, /* c0000171 */ + ERROR_PARTITION_FAILURE, /* c0000172 (STATUS_PARTITION_FAILURE) */ + ERROR_INVALID_BLOCK_LENGTH, /* c0000173 (STATUS_INVALID_BLOCK_LENGTH) */ + ERROR_DEVICE_NOT_PARTITIONED, /* c0000174 (STATUS_DEVICE_NOT_PARTITIONED) */ + ERROR_UNABLE_TO_LOCK_MEDIA, /* c0000175 (STATUS_UNABLE_TO_LOCK_MEDIA) */ + ERROR_UNABLE_TO_UNLOAD_MEDIA, /* c0000176 (STATUS_UNABLE_TO_UNLOAD_MEDIA) */ + ERROR_EOM_OVERFLOW, /* c0000177 (STATUS_EOM_OVERFLOW) */ + ERROR_NO_MEDIA_IN_DRIVE, /* c0000178 (STATUS_NO_MEDIA) */ + ERROR_MR_MID_NOT_FOUND, /* c0000179 */ + ERROR_NO_SUCH_MEMBER, /* c000017a (STATUS_NO_SUCH_MEMBER) */ + ERROR_INVALID_MEMBER, /* c000017b (STATUS_INVALID_MEMBER) */ + ERROR_KEY_DELETED, /* c000017c (STATUS_KEY_DELETED) */ + ERROR_NO_LOG_SPACE, /* c000017d (STATUS_NO_LOG_SPACE) */ + ERROR_TOO_MANY_SIDS, /* c000017e (STATUS_TOO_MANY_SIDS) */ + ERROR_LM_CROSS_ENCRYPTION_REQUIRED, /* c000017f (STATUS_LM_CROSS_ENCRYPTION_REQUIRED) */ + ERROR_KEY_HAS_CHILDREN, /* c0000180 (STATUS_KEY_HAS_CHILDREN) */ + ERROR_CHILD_MUST_BE_VOLATILE, /* c0000181 (STATUS_CHILD_MUST_BE_VOLATILE) */ + ERROR_INVALID_PARAMETER, /* c0000182 (STATUS_DEVICE_CONFIGURATION_ERROR) */ + ERROR_IO_DEVICE, /* c0000183 (STATUS_DRIVER_INTERNAL_ERROR) */ + ERROR_BAD_COMMAND, /* c0000184 (STATUS_INVALID_DEVICE_STATE) */ + ERROR_IO_DEVICE, /* c0000185 (STATUS_IO_DEVICE_ERROR) */ + ERROR_IO_DEVICE, /* c0000186 (STATUS_DEVICE_PROTOCOL_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c0000187 (STATUS_BACKUP_CONTROLLER) */ + ERROR_LOG_FILE_FULL, /* c0000188 (STATUS_LOG_FILE_FULL) */ + ERROR_WRITE_PROTECT, /* c0000189 (STATUS_TOO_LATE) */ + ERROR_NO_TRUST_LSA_SECRET, /* c000018a (STATUS_NO_TRUST_LSA_SECRET) */ + ERROR_NO_TRUST_SAM_ACCOUNT, /* c000018b (STATUS_NO_TRUST_SAM_ACCOUNT) */ + ERROR_TRUSTED_DOMAIN_FAILURE, /* c000018c (STATUS_TRUSTED_DOMAIN_FAILURE) */ + ERROR_TRUSTED_RELATIONSHIP_FAILURE, /* c000018d (STATUS_TRUSTED_RELATIONSHIP_FAILURE) */ + ERROR_EVENTLOG_FILE_CORRUPT, /* c000018e (STATUS_EVENTLOG_FILE_CORRUPT) */ + ERROR_EVENTLOG_CANT_START, /* c000018f (STATUS_EVENTLOG_CANT_START) */ + ERROR_TRUST_FAILURE, /* c0000190 (STATUS_TRUST_FAILURE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000191 (STATUS_MUTANT_LIMIT_EXCEEDED) */ + ERROR_NETLOGON_NOT_STARTED, /* c0000192 (STATUS_NETLOGON_NOT_STARTED) */ + ERROR_ACCOUNT_EXPIRED, /* c0000193 (STATUS_ACCOUNT_EXPIRED) */ + ERROR_POSSIBLE_DEADLOCK, /* c0000194 (STATUS_POSSIBLE_DEADLOCK) */ + ERROR_SESSION_CREDENTIAL_CONFLICT, /* c0000195 (STATUS_NETWORK_CREDENTIAL_CONFLICT) */ + ERROR_REMOTE_SESSION_LIMIT_EXCEEDED, /* c0000196 (STATUS_REMOTE_SESSION_LIMIT) */ + ERROR_EVENTLOG_FILE_CHANGED, /* c0000197 (STATUS_EVENTLOG_FILE_CHANGED) */ + ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,/* c0000198 (STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT) */ + ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT,/* c0000199 (STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT) */ + ERROR_NOLOGON_SERVER_TRUST_ACCOUNT, /* c000019a (STATUS_NOLOGON_SERVER_TRUST_ACCOUNT) */ + ERROR_DOMAIN_TRUST_INCONSISTENT /* c000019b (STATUS_DOMAIN_TRUST_INCONSISTENT) */ +}; + +static const WORD table_c0000202[109] = +{ + ERROR_NO_USER_SESSION_KEY, /* c0000202 (STATUS_NO_USER_SESSION_KEY) */ + ERROR_UNEXP_NET_ERR, /* c0000203 (STATUS_USER_SESSION_DELETED) */ + ERROR_RESOURCE_LANG_NOT_FOUND, /* c0000204 (STATUS_RESOURCE_LANG_NOT_FOUND) */ + ERROR_NOT_ENOUGH_SERVER_MEMORY, /* c0000205 (STATUS_INSUFF_SERVER_RESOURCES) */ + ERROR_INVALID_USER_BUFFER, /* c0000206 (STATUS_INVALID_BUFFER_SIZE) */ + ERROR_INVALID_NETNAME, /* c0000207 (STATUS_INVALID_ADDRESS_COMPONENT) */ + ERROR_INVALID_NETNAME, /* c0000208 (STATUS_INVALID_ADDRESS_WILDCARD) */ + ERROR_TOO_MANY_NAMES, /* c0000209 (STATUS_TOO_MANY_ADDRESSES) */ + ERROR_DUP_NAME, /* c000020a (STATUS_ADDRESS_ALREADY_EXISTS) */ + ERROR_NETNAME_DELETED, /* c000020b (STATUS_ADDRESS_CLOSED) */ + ERROR_NETNAME_DELETED, /* c000020c (STATUS_CONNECTION_DISCONNECTED) */ + ERROR_NETNAME_DELETED, /* c000020d (STATUS_CONNECTION_RESET) */ + ERROR_TOO_MANY_NAMES, /* c000020e (STATUS_TOO_MANY_NODES) */ + ERROR_UNEXP_NET_ERR, /* c000020f (STATUS_TRANSACTION_ABORTED) */ + ERROR_UNEXP_NET_ERR, /* c0000210 (STATUS_TRANSACTION_TIMED_OUT) */ + ERROR_UNEXP_NET_ERR, /* c0000211 (STATUS_TRANSACTION_NO_RELEASE) */ + ERROR_UNEXP_NET_ERR, /* c0000212 (STATUS_TRANSACTION_NO_MATCH) */ + ERROR_UNEXP_NET_ERR, /* c0000213 (STATUS_TRANSACTION_RESPONDED) */ + ERROR_UNEXP_NET_ERR, /* c0000214 (STATUS_TRANSACTION_INVALID_ID) */ + ERROR_UNEXP_NET_ERR, /* c0000215 (STATUS_TRANSACTION_INVALID_TYPE) */ + ERROR_NOT_SUPPORTED, /* c0000216 (STATUS_NOT_SERVER_SESSION) */ + ERROR_NOT_SUPPORTED, /* c0000217 (STATUS_NOT_CLIENT_SESSION) */ + ERROR_MR_MID_NOT_FOUND, /* c0000218 (STATUS_CANNOT_LOAD_REGISTRY_FILE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000219 */ + ERROR_MR_MID_NOT_FOUND, /* c000021a */ + ERROR_MR_MID_NOT_FOUND, /* c000021b */ + ERROR_NO_BROWSER_SERVERS_FOUND, /* c000021c (STATUS_NO_BROWSER_SERVERS_FOUND) */ + ERROR_MR_MID_NOT_FOUND, /* c000021d */ + ERROR_MR_MID_NOT_FOUND, /* c000021e */ + ERROR_MR_MID_NOT_FOUND, /* c000021f */ + ERROR_MAPPED_ALIGNMENT, /* c0000220 (STATUS_MAPPED_ALIGNMENT) */ + ERROR_BAD_EXE_FORMAT, /* c0000221 (STATUS_IMAGE_CHECKSUM_MISMATCH) */ + ERROR_MR_MID_NOT_FOUND, /* c0000222 */ + ERROR_MR_MID_NOT_FOUND, /* c0000223 */ + ERROR_PASSWORD_MUST_CHANGE, /* c0000224 (STATUS_PASSWORD_MUST_CHANGE) */ + ERROR_MR_MID_NOT_FOUND, /* c0000225 */ + ERROR_MR_MID_NOT_FOUND, /* c0000226 */ + ERROR_MR_MID_NOT_FOUND, /* c0000227 */ + ERROR_MR_MID_NOT_FOUND, /* c0000228 */ + ERROR_MR_MID_NOT_FOUND, /* c0000229 */ + 0, /* c000022a */ + 0, /* c000022b */ + ERROR_MR_MID_NOT_FOUND, /* c000022c */ + ERROR_MR_MID_NOT_FOUND, /* c000022d */ + ERROR_MR_MID_NOT_FOUND, /* c000022e */ + ERROR_MR_MID_NOT_FOUND, /* c000022f */ + ERROR_MR_MID_NOT_FOUND, /* c0000230 */ + ERROR_MR_MID_NOT_FOUND, /* c0000231 */ + ERROR_MR_MID_NOT_FOUND, /* c0000232 */ + ERROR_DOMAIN_CONTROLLER_NOT_FOUND, /* c0000233 */ + ERROR_ACCOUNT_LOCKED_OUT, /* c0000234 */ + ERROR_INVALID_HANDLE, /* c0000235 */ + ERROR_CONNECTION_REFUSED, /* c0000236 */ + ERROR_GRACEFUL_DISCONNECT, /* c0000237 */ + ERROR_ADDRESS_ALREADY_ASSOCIATED, /* c0000238 */ + ERROR_ADDRESS_NOT_ASSOCIATED, /* c0000239 */ + ERROR_CONNECTION_INVALID, /* c000023a */ + ERROR_CONNECTION_ACTIVE, /* c000023b */ + ERROR_NETWORK_UNREACHABLE, /* c000023c */ + ERROR_HOST_UNREACHABLE, /* c000023d */ + ERROR_PROTOCOL_UNREACHABLE, /* c000023e */ + ERROR_PORT_UNREACHABLE, /* c000023f */ + ERROR_REQUEST_ABORTED, /* c0000240 */ + ERROR_CONNECTION_ABORTED, /* c0000241 */ + ERROR_MR_MID_NOT_FOUND, /* c0000242 */ + ERROR_USER_MAPPED_FILE, /* c0000243 */ + ERROR_MR_MID_NOT_FOUND, /* c0000244 */ + ERROR_MR_MID_NOT_FOUND, /* c0000245 */ + ERROR_CONNECTION_COUNT_LIMIT, /* c0000246 */ + ERROR_LOGIN_TIME_RESTRICTION, /* c0000247 */ + ERROR_LOGIN_WKSTA_RESTRICTION, /* c0000248 */ + ERROR_BAD_EXE_FORMAT, /* c0000249 */ + ERROR_MR_MID_NOT_FOUND, /* c000024a */ + ERROR_MR_MID_NOT_FOUND, /* c000024b */ + ERROR_MR_MID_NOT_FOUND, /* c000024c */ + ERROR_MR_MID_NOT_FOUND, /* c000024d */ + ERROR_MR_MID_NOT_FOUND, /* c000024e */ + ERROR_MR_MID_NOT_FOUND, /* c000024f */ + ERROR_MR_MID_NOT_FOUND, /* c0000250 */ + ERROR_MR_MID_NOT_FOUND, /* c0000251 */ + ERROR_MR_MID_NOT_FOUND, /* c0000252 */ + ERROR_INTERNAL_ERROR, /* c0000253 */ + ERROR_MR_MID_NOT_FOUND, /* c0000254 */ + ERROR_MR_MID_NOT_FOUND, /* c0000255 */ + ERROR_MR_MID_NOT_FOUND, /* c0000256 */ + ERROR_HOST_UNREACHABLE, /* c0000257 */ + ERROR_MR_MID_NOT_FOUND, /* c0000258 */ + ERROR_LICENSE_QUOTA_EXCEEDED, /* c0000259 */ + ERROR_MR_MID_NOT_FOUND, /* c000025a */ + ERROR_MR_MID_NOT_FOUND, /* c000025b */ + ERROR_MR_MID_NOT_FOUND, /* c000025c */ + ERROR_MR_MID_NOT_FOUND, /* c000025d */ + ERROR_SERVICE_DISABLED, /* c000025e */ + ERROR_MR_MID_NOT_FOUND, /* c000025f */ + ERROR_MR_MID_NOT_FOUND, /* c0000260 */ + ERROR_MR_MID_NOT_FOUND, /* c0000261 */ + ERROR_INVALID_ORDINAL, /* c0000262 */ + ERROR_PROC_NOT_FOUND, /* c0000263 */ + ERROR_NOT_OWNER, /* c0000264 */ + ERROR_TOO_MANY_LINKS, /* c0000265 */ + ERROR_MR_MID_NOT_FOUND, /* c0000266 */ + ERROR_MR_MID_NOT_FOUND, /* c0000267 */ + ERROR_MR_MID_NOT_FOUND, /* c0000268 */ + ERROR_MR_MID_NOT_FOUND, /* c0000269 */ + ERROR_MR_MID_NOT_FOUND, /* c000026a */ + ERROR_MR_MID_NOT_FOUND, /* c000026b */ + ERROR_MR_MID_NOT_FOUND, /* c000026c */ + ERROR_MR_MID_NOT_FOUND, /* c000026d */ + ERROR_NOT_READY /* c000026e (STATUS_VOLUME_DISMOUNTED) */ +}; + +static const WORD table_c0020001[88] = +{ + RPC_S_INVALID_STRING_BINDING, /* c0020001 (RPC_NT_INVALID_STRING_BINDING) */ + RPC_S_WRONG_KIND_OF_BINDING, /* c0020002 (RPC_NT_WRONG_KIND_OF_BINDING) */ + ERROR_INVALID_HANDLE, /* c0020003 (RPC_NT_INVALID_BINDING) */ + RPC_S_PROTSEQ_NOT_SUPPORTED, /* c0020004 (RPC_NT_PROTSEQ_NOT_SUPPORTED) */ + RPC_S_INVALID_RPC_PROTSEQ, /* c0020005 (RPC_NT_INVALID_RPC_PROTSEQ) */ + RPC_S_INVALID_STRING_UUID, /* c0020006 (RPC_NT_INVALID_STRING_UUID) */ + RPC_S_INVALID_ENDPOINT_FORMAT, /* c0020007 (RPC_NT_INVALID_ENDPOINT_FORMAT) */ + RPC_S_INVALID_NET_ADDR, /* c0020008 (RPC_NT_INVALID_NET_ADDR) */ + RPC_S_NO_ENDPOINT_FOUND, /* c0020009 (RPC_NT_NO_ENDPOINT_FOUND) */ + RPC_S_INVALID_TIMEOUT, /* c002000a (RPC_NT_INVALID_TIMEOUT) */ + RPC_S_OBJECT_NOT_FOUND, /* c002000b (RPC_NT_OBJECT_NOT_FOUND) */ + RPC_S_ALREADY_REGISTERED, /* c002000c (RPC_NT_ALREADY_REGISTERED) */ + RPC_S_TYPE_ALREADY_REGISTERED, /* c002000d (RPC_NT_TYPE_ALREADY_REGISTERED) */ + RPC_S_ALREADY_LISTENING, /* c002000e (RPC_NT_ALREADY_LISTENING) */ + RPC_S_NO_PROTSEQS_REGISTERED, /* c002000f (RPC_NT_NO_PROTSEQS_REGISTERED) */ + RPC_S_NOT_LISTENING, /* c0020010 (RPC_NT_NOT_LISTENING) */ + RPC_S_UNKNOWN_MGR_TYPE, /* c0020011 (RPC_NT_UNKNOWN_MGR_TYPE) */ + RPC_S_UNKNOWN_IF, /* c0020012 (RPC_NT_UNKNOWN_IF) */ + RPC_S_NO_BINDINGS, /* c0020013 (RPC_NT_NO_BINDINGS) */ + RPC_S_NO_PROTSEQS, /* c0020014 (RPC_NT_NO_PROTSEQS) */ + RPC_S_CANT_CREATE_ENDPOINT, /* c0020015 (RPC_NT_CANT_CREATE_ENDPOINT) */ + RPC_S_OUT_OF_RESOURCES, /* c0020016 (RPC_NT_OUT_OF_RESOURCES) */ + RPC_S_SERVER_UNAVAILABLE, /* c0020017 (RPC_NT_SERVER_UNAVAILABLE) */ + RPC_S_SERVER_TOO_BUSY, /* c0020018 (RPC_NT_SERVER_TOO_BUSY) */ + RPC_S_INVALID_NETWORK_OPTIONS, /* c0020019 (RPC_NT_INVALID_NETWORK_OPTIONS) */ + RPC_S_NO_CALL_ACTIVE, /* c002001a (RPC_NT_NO_CALL_ACTIVE) */ + RPC_S_CALL_FAILED, /* c002001b (RPC_NT_CALL_FAILED) */ + RPC_S_CALL_FAILED_DNE, /* c002001c (RPC_NT_CALL_FAILED_DNE) */ + RPC_S_PROTOCOL_ERROR, /* c002001d (RPC_NT_PROTOCOL_ERROR) */ + ERROR_MR_MID_NOT_FOUND, /* c002001e */ + RPC_S_UNSUPPORTED_TRANS_SYN, /* c002001f (RPC_NT_UNSUPPORTED_TRANS_SYN) */ + ERROR_MR_MID_NOT_FOUND, /* c0020020 */ + RPC_S_UNSUPPORTED_TYPE, /* c0020021 (RPC_NT_UNSUPPORTED_TYPE) */ + RPC_S_INVALID_TAG, /* c0020022 (RPC_NT_INVALID_TAG) */ + RPC_S_INVALID_BOUND, /* c0020023 (RPC_NT_INVALID_BOUND) */ + RPC_S_NO_ENTRY_NAME, /* c0020024 (RPC_NT_NO_ENTRY_NAME) */ + RPC_S_INVALID_NAME_SYNTAX, /* c0020025 (RPC_NT_INVALID_NAME_SYNTAX) */ + RPC_S_UNSUPPORTED_NAME_SYNTAX, /* c0020026 (RPC_NT_UNSUPPORTED_NAME_SYNTAX) */ + ERROR_MR_MID_NOT_FOUND, /* c0020027 */ + RPC_S_UUID_NO_ADDRESS, /* c0020028 (RPC_NT_UUID_NO_ADDRESS) */ + RPC_S_DUPLICATE_ENDPOINT, /* c0020029 (RPC_NT_DUPLICATE_ENDPOINT) */ + RPC_S_UNKNOWN_AUTHN_TYPE, /* c002002a (RPC_NT_UNKNOWN_AUTHN_TYPE) */ + RPC_S_MAX_CALLS_TOO_SMALL, /* c002002b (RPC_NT_MAX_CALLS_TOO_SMALL) */ + RPC_S_STRING_TOO_LONG, /* c002002c (RPC_NT_STRING_TOO_LONG) */ + RPC_S_PROTSEQ_NOT_FOUND, /* c002002d (RPC_NT_PROTSEQ_NOT_FOUND) */ + RPC_S_PROCNUM_OUT_OF_RANGE, /* c002002e (RPC_NT_PROCNUM_OUT_OF_RANGE) */ + RPC_S_BINDING_HAS_NO_AUTH, /* c002002f (RPC_NT_BINDING_HAS_NO_AUTH) */ + RPC_S_UNKNOWN_AUTHN_SERVICE, /* c0020030 (RPC_NT_UNKNOWN_AUTHN_SERVICE) */ + RPC_S_UNKNOWN_AUTHN_LEVEL, /* c0020031 (RPC_NT_UNKNOWN_AUTHN_LEVEL) */ + RPC_S_INVALID_AUTH_IDENTITY, /* c0020032 (RPC_NT_INVALID_AUTH_IDENTITY) */ + RPC_S_UNKNOWN_AUTHZ_SERVICE, /* c0020033 (RPC_NT_UNKNOWN_AUTHZ_SERVICE) */ + EPT_S_INVALID_ENTRY, /* c0020034 (EPT_NT_INVALID_ENTRY) */ + EPT_S_CANT_PERFORM_OP, /* c0020035 (EPT_NT_CANT_PERFORM_OP) */ + EPT_S_NOT_REGISTERED, /* c0020036 (EPT_NT_NOT_REGISTERED) */ + RPC_S_NOTHING_TO_EXPORT, /* c0020037 (RPC_NT_NOTHING_TO_EXPORT) */ + RPC_S_INCOMPLETE_NAME, /* c0020038 (RPC_NT_INCOMPLETE_NAME) */ + RPC_S_INVALID_VERS_OPTION, /* c0020039 (RPC_NT_INVALID_VERS_OPTION) */ + RPC_S_NO_MORE_MEMBERS, /* c002003a (RPC_NT_NO_MORE_MEMBERS) */ + RPC_S_NOT_ALL_OBJS_UNEXPORTED, /* c002003b (RPC_NT_NOT_ALL_OBJS_UNEXPORTED) */ + RPC_S_INTERFACE_NOT_FOUND, /* c002003c (RPC_NT_INTERFACE_NOT_FOUND) */ + RPC_S_ENTRY_ALREADY_EXISTS, /* c002003d (RPC_NT_ENTRY_ALREADY_EXISTS) */ + RPC_S_ENTRY_NOT_FOUND, /* c002003e (RPC_NT_ENTRY_NOT_FOUND) */ + RPC_S_NAME_SERVICE_UNAVAILABLE, /* c002003f (RPC_NT_NAME_SERVICE_UNAVAILABLE) */ + RPC_S_INVALID_NAF_ID, /* c0020040 (RPC_NT_INVALID_NAF_ID) */ + RPC_S_CANNOT_SUPPORT, /* c0020041 (RPC_NT_CANNOT_SUPPORT) */ + RPC_S_NO_CONTEXT_AVAILABLE, /* c0020042 (RPC_NT_NO_CONTEXT_AVAILABLE) */ + RPC_S_INTERNAL_ERROR, /* c0020043 (RPC_NT_INTERNAL_ERROR) */ + RPC_S_ZERO_DIVIDE, /* c0020044 (RPC_NT_ZERO_DIVIDE) */ + RPC_S_ADDRESS_ERROR, /* c0020045 (RPC_NT_ADDRESS_ERROR) */ + RPC_S_FP_DIV_ZERO, /* c0020046 (RPC_NT_FP_DIV_ZERO) */ + RPC_S_FP_UNDERFLOW, /* c0020047 (RPC_NT_FP_UNDERFLOW) */ + RPC_S_FP_OVERFLOW, /* c0020048 (RPC_NT_FP_OVERFLOW) */ + RPC_S_CALL_IN_PROGRESS, /* c0020049 (RPC_NT_CALL_IN_PROGRESS) */ + RPC_S_NO_MORE_BINDINGS, /* c002004a (RPC_NT_NO_MORE_BINDINGS) */ + RPC_S_GROUP_MEMBER_NOT_FOUND, /* c002004b (RPC_NT_GROUP_MEMBER_NOT_FOUND) */ + EPT_S_CANT_CREATE, /* c002004c (EPT_NT_CANT_CREATE) */ + RPC_S_INVALID_OBJECT, /* c002004d (RPC_NT_INVALID_OBJECT) */ + ERROR_MR_MID_NOT_FOUND, /* c002004e */ + RPC_S_NO_INTERFACES, /* c002004f */ + RPC_S_CALL_CANCELLED, /* c0020050 */ + RPC_S_BINDING_INCOMPLETE, /* c0020051 */ + RPC_S_COMM_FAILURE, /* c0020052 */ + RPC_S_UNSUPPORTED_AUTHN_LEVEL, /* c0020053 */ + RPC_S_NO_PRINC_NAME, /* c0020054 */ + RPC_S_NOT_RPC_ERROR, /* c0020055 */ + ERROR_MR_MID_NOT_FOUND, /* c0020056 */ + RPC_S_SEC_PKG_ERROR, /* c0020057 */ + RPC_S_NOT_CANCELLED /* c0020058 */ +}; + +static const WORD table_c0030001[12] = +{ + RPC_X_NO_MORE_ENTRIES, /* c0030001 (RPC_NT_NO_MORE_ENTRIES) */ + RPC_X_SS_CHAR_TRANS_OPEN_FAIL, /* c0030002 (RPC_NT_SS_CHAR_TRANS_OPEN_FAIL) */ + RPC_X_SS_CHAR_TRANS_SHORT_FILE, /* c0030003 (RPC_NT_SS_CHAR_TRANS_SHORT_FILE) */ + ERROR_INVALID_HANDLE, /* c0030004 (RPC_NT_SS_IN_NULL_CONTEXT) */ + ERROR_INVALID_HANDLE, /* c0030005 */ + RPC_X_SS_CONTEXT_DAMAGED, /* c0030006 (RPC_NT_SS_CONTEXT_DAMAGED) */ + RPC_X_SS_HANDLES_MISMATCH, /* c0030007 (RPC_NT_SS_HANDLES_MISMATCH) */ + RPC_X_SS_CANNOT_GET_CALL_HANDLE, /* c0030008 (RPC_NT_SS_CANNOT_GET_CALL_HANDLE) */ + RPC_X_NULL_REF_POINTER, /* c0030009 (RPC_NT_NULL_REF_POINTER) */ + RPC_X_ENUM_VALUE_OUT_OF_RANGE, /* c003000a (RPC_NT_ENUM_VALUE_OUT_OF_RANGE) */ + RPC_X_BYTE_COUNT_TOO_SMALL, /* c003000b (RPC_NT_BYTE_COUNT_TOO_SMALL) */ + RPC_X_BAD_STUB_DATA /* c003000c (RPC_NT_BAD_STUB_DATA) */ +}; + +static const WORD table_c0030059[6] = +{ + RPC_X_INVALID_ES_ACTION, /* c0030059 */ + RPC_X_WRONG_ES_VERSION, /* c003005a */ + RPC_X_WRONG_STUB_VERSION, /* c003005b */ + RPC_X_INVALID_PIPE_OBJECT, /* c003005c */ + RPC_X_WRONG_PIPE_ORDER, /* c003005d */ + RPC_X_WRONG_PIPE_VERSION /* c003005e */ +}; + +static const ERROR_TABLE ErrorTable[] = +{ + { 0x00000103, 0x0000010e, table_00000103 }, + { 0x40000002, 0x4000000e, table_40000002 }, + { 0x40020056, 0x40020057, table_40020056 }, + { 0x400200af, 0x400200b0, table_400200af }, + { 0x80000001, 0x80000027, table_80000001 }, + { 0x80090300, 0x80090317, table_80090300 }, + { 0xc0000001, 0xc000019c, table_c0000001 }, + { 0xc0000202, 0xc000026f, table_c0000202 }, + { 0xc0020001, 0xc0020059, table_c0020001 }, + { 0xc0030001, 0xc003000d, table_c0030001 }, + { 0xc0030059, 0xc003005f, table_c0030059 }, + { 0, 0, 0 } /* last entry */ +}; + + +#if 0 +/* currently not assigned values */ + ERROR_ARENA_TRASHED +STATUS_HANDLE_NOT_WAITABLE ERROR_INVALID_HANDLE; +STATUS_LOCK_NOT_GRANTED ERROR_LOCK_VIOLATION; + +RPC_NT_SS_CONTEXT_MISMATCH ERROR_INVALID_HANDLE +#endif + + +/* FUNCTIONS ***************************************************************/ + +VOID STDCALL +RtlAssert(PVOID FailedAssertion, + PVOID FileName, + ULONG LineNumber, + PCHAR Message) +{ + DbgPrint("Assertion \'%s\' failed at %s line %d: %s\n", + (PCHAR)FailedAssertion, + (PCHAR)FileName, + LineNumber, + Message); +} + + +/********************************************************************** + * NAME EXPORTED + * RtlNtStatusToDosErrorNoTeb + * + * DESCRIPTION + * Convert an Executive status ID into a DOS error number + * (winerror.h). + * + * ARGUMENTS + * Status The Executive status ID to convert. + * + * RETURN VALUE + * dos error as in winerror.h + * + * REMARK + * RtlNtStatusToDosErrorNoTeb() does the real work. + */ +DWORD STDCALL +RtlNtStatusToDosErrorNoTeb(IN NTSTATUS Status) +{ + PERROR_TABLE Table = (PERROR_TABLE)ErrorTable; + + if (!Status || (Status & 0x20000000)) + return Status; + + /* 0xd... is equivalent to 0xc... */ + if ((Status & 0xf0000000) == 0xd0000000) + Status &= ~0x10000000; + + while (Table->Start) + { + if (Status < Table->Start) + break; + + if (Status < Table->End) + { + DWORD ret = Table->Table[Status - Table->Start]; + if (!ret) + ret = Status; /* 0 means 1:1 mapping */ + else if (ret == ERROR_MR_MID_NOT_FOUND) + DbgPrint("RTL: RtlNtStatusToDosErrorNoTeb(0x%lx): no valid W32 error mapping\n", Status); + return ret; + } + Table++; + } + + /* now some special cases */ + if (HIWORD(Status) == 0xc001) + return LOWORD(Status); + if (HIWORD(Status) == 0x8007) + return LOWORD(Status); + + DbgPrint("RTL: RtlNtStatusToDosErrorNoTeb(0x%lx): no valid W32 error mapping\n", Status); + + return ERROR_MR_MID_NOT_FOUND; +} + + +/********************************************************************** + * NAME EXPORTED + * RtlNtStatusToDosError + * + * DESCRIPTION + * Convert an Executive status ID into a DOS error number + * (winerror.h). + * + * ARGUMENTS + * Status The Executive status ID to convert. + * + * RETURN VALUE + * dos error as in winerror.h + * + * REMARK + * RtlNtStatusToDosErrorNoTeb() does the real work. + */ +DWORD STDCALL +RtlNtStatusToDosError(IN NTSTATUS Status) +{ + PTEB Teb = NtCurrentTeb (); + + if (NULL != Teb) + { + Teb->LastStatusValue = Status; + } + return RtlNtStatusToDosErrorNoTeb(Status); +} + + +/********************************************************************** + * NAME EXPORTED + * RtlNtStatusToPsxErrno + * + * DESCRIPTION + * Convert an Executive status ID into a POSIX error number + * (errno.h). + * + * NOTE + * Not present in the legacy WNT (a ReactOS extension to support + * the POSIX+ subsystem). + * + * ARGUMENTS + * Status The Executive status ID to convert. + * + * RETURN VALUE + * errno as in errno.h + * + * REVISIONS + * 1999-11-30 ea + */ +INT STDCALL +RtlNtStatusToPsxErrno(IN NTSTATUS Status) +{ +#if 0 + switch (Status) + { + } +#endif + return -1; /* generic POSIX error */ +} + +/* EOF */ diff --git a/ntoskrnl/rtl/handle.c b/ntoskrnl/rtl/handle.c new file mode 100644 index 0000000..e5bb6af --- /dev/null +++ b/ntoskrnl/rtl/handle.c @@ -0,0 +1,186 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Handle table + * FILE: lib/ntdll/rtl/handle.c + * PROGRAMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +#define TAG_HDTB TAG('H', 'D', 'T', 'B') + + +static BOOLEAN +RtlpIsValidHandle(PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE Handle); +static BOOLEAN +RtlpIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE *Handle, ULONG Index); + + +/* FUNCTIONS *****************************************************************/ + +VOID +RtlpInitializeHandleTable(ULONG TableSize, + PRTL_HANDLE_TABLE HandleTable) +{ + /* initialize handle table */ + memset(HandleTable, + 0, + sizeof(RTL_HANDLE_TABLE)); + HandleTable->TableSize = TableSize; +} + + +VOID +RtlpDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable) +{ + ExFreePool((PVOID)HandleTable->Handles); +} + + +BOOLEAN +RtlpAllocateHandle(PRTL_HANDLE_TABLE HandleTable, + PVOID Object, + PULONG Index) +{ + RTL_HANDLE **pp_new,**pph,*ph; + PRTL_HANDLE retval; + PVOID ArrayPointer; + ULONG ArraySize; + + if (Index == NULL) + return FALSE; + + pp_new = &HandleTable->FirstFree; + + if (HandleTable->FirstFree == NULL) + { + /* no free handle available */ + if (HandleTable->LastUsed == NULL) + { + /* allocate handle array */ + ArraySize = sizeof(RTL_HANDLE) * HandleTable->TableSize; + ArrayPointer = ExAllocatePoolWithTag(NonPagedPool, + ArraySize, + TAG_HDTB); + if (ArrayPointer == NULL) + return FALSE; + + /* update handle array pointers */ + HandleTable->Handles = (PRTL_HANDLE)ArrayPointer; + HandleTable->Limit = (PRTL_HANDLE)(ArrayPointer + ArraySize); + HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer; + } + + /* build free list in handle array */ + ph = HandleTable->LastUsed; + pph = pp_new; + while (ph < HandleTable->Limit) + { + *pph = ph; + pph = &ph->Next; + ph = (PRTL_HANDLE)((ULONG)ph + sizeof(RTL_HANDLE)); + } + *pph = 0; + } + + /* remove handle from free list */ + retval = *pp_new; + *pp_new = retval->Next; + retval->Next = NULL; + retval->Object = Object; + + *Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / sizeof(RTL_HANDLE); + + return TRUE; +} + + +BOOLEAN +RtlpFreeHandle(PRTL_HANDLE_TABLE HandleTable, + ULONG Index) +{ + PRTL_HANDLE Handle; + + /* check if handle is valid */ + if (RtlpIsValidIndexHandle(HandleTable, + &Handle, + Index)) + return FALSE; + + /* clear handle */ + memset(Handle, 0, sizeof(RTL_HANDLE)); + + /* add handle to free list */ + Handle->Next = HandleTable->FirstFree; + HandleTable->FirstFree = Handle; + + return TRUE; +} + + +static BOOLEAN +RtlpIsValidHandle(PRTL_HANDLE_TABLE HandleTable, + PRTL_HANDLE Handle) +{ + if ((HandleTable != NULL) + && (Handle != NULL) + && (Handle >= HandleTable->Handles) + && (Handle < HandleTable->Limit)) + return TRUE; + return FALSE; +} + + +static BOOLEAN +RtlpIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable, + PRTL_HANDLE *Handle, + ULONG Index) +{ + PRTL_HANDLE InternalHandle; + + DPRINT("RtlpIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index); + + if (HandleTable == NULL) + return FALSE; + + DPRINT("Handles %p\n", HandleTable->Handles); + + InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + sizeof(RTL_HANDLE) * Index); + if (RtlpIsValidHandle(HandleTable, InternalHandle) == FALSE) + return FALSE; + + DPRINT("InternalHandle %p\n", InternalHandle); + + if (Handle != NULL) + *Handle = InternalHandle; + + return TRUE; +} + +PVOID +RtlpMapHandleToPointer(PRTL_HANDLE_TABLE HandleTable, + ULONG Index) +{ + PRTL_HANDLE Handle; + + if (!RtlpIsValidIndexHandle(HandleTable, + &Handle, + Index)) + { + return NULL; + } + + return Handle->Object; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/i386/.cvsignore b/ntoskrnl/rtl/i386/.cvsignore new file mode 100644 index 0000000..31dc307 --- /dev/null +++ b/ntoskrnl/rtl/i386/.cvsignore @@ -0,0 +1,2 @@ +*.d +*.o diff --git a/ntoskrnl/rtl/i386/except.s b/ntoskrnl/rtl/i386/except.s new file mode 100755 index 0000000..299265c --- /dev/null +++ b/ntoskrnl/rtl/i386/except.s @@ -0,0 +1,291 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Kernel-mode exception support for IA-32 + * FILE: ntoskrnl/rtl/i386/except.s + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: This file is shared with lib/ntdll/rtl/i386/except.s. + * Please keep them in sync. + */ + +#define EXCEPTION_UNWINDING 0x02 + +#define EREC_FLAGS 0x04 + +#define ExceptionContinueExecution 0 +#define ExceptionContinueSearch 1 +#define ExceptionNestedException 2 +#define ExceptionCollidedUnwind 3 + +.globl _RtlpExecuteHandlerForException +.globl _RtlpExecuteHandlerForUnwind + +#define CONTEXT_FLAGS 0x00 +#define CONTEXT_SEGGS 0x8C +#define CONTEXT_SEGFS 0x90 +#define CONTEXT_SEGES 0x94 +#define CONTEXT_SEGDS 0x98 +#define CONTEXT_EDI 0x9C +#define CONTEXT_ESI 0xA0 +#define CONTEXT_EBX 0xA4 +#define CONTEXT_EDX 0xA8 +#define CONTEXT_ECX 0xAC +#define CONTEXT_EAX 0xB0 +#define CONTEXT_EBP 0xB4 +#define CONTEXT_EIP 0xB8 +#define CONTEXT_SEGCS 0xBC +#define CONTEXT_EFLAGS 0xC0 +#define CONTEXT_ESP 0xC4 +#define CONTEXT_SEGSS 0xC8 + + +#define RCC_CONTEXT 0x08 + +// EAX = value to print +_do_debug: + pushal + pushl %eax + call _AsmDebug@4 + popal + ret + +#ifndef __NTOSKRNL__ + +// +// VOID +// RtlpCaptureContext(PCONTEXT pContext); +// +// Parameters: +// [ESP+08h] - PCONTEXT_X86 pContext +// Registers: +// None +// Returns: +// Nothing +// Notes: +// Grabs the current CPU context. +.globl _RtlpCaptureContext +_RtlpCaptureContext: + pushl %ebp + movl %esp, %ebp + movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure + + cld + pushf + pop %eax + movl %eax, CONTEXT_EFLAGS(%edx) + xorl %eax, %eax + movl %eax, CONTEXT_EAX(%edx) + movl %eax, CONTEXT_EBX(%edx) + movl %eax, CONTEXT_ECX(%edx) + movl %eax, CONTEXT_EDX(%edx) + movl %eax, CONTEXT_ESI(%edx) + movl %eax, CONTEXT_EDI(%edx) + movl %cs, %eax + movl %eax, CONTEXT_SEGCS(%edx) + movl %ds, %eax + movl %eax, CONTEXT_SEGDS(%edx) + movl %es, %eax + movl %eax, CONTEXT_SEGES(%edx) + movl %fs, %eax + movl %eax, CONTEXT_SEGFS(%edx) + movl %gs, %eax + movl %eax, CONTEXT_SEGGS(%edx) + movl %ss, %eax + movl %eax, CONTEXT_SEGSS(%edx) + + // + // STACK LAYOUT: - (ESP to put in context structure) + // - RETURN ADDRESS OF CALLER OF CALLER + // - EBP OF CALLER OF CALLER + // ... + // - RETURN ADDRESS OF CALLER + // - EBP OF CALLER + // ... + // + + // Get return address of the caller of the caller of this function + movl %ebp, %ebx + //movl 4(%ebx), %eax // EAX = return address of caller + movl (%ebx), %ebx // EBX = EBP of caller + + movl 4(%ebx), %eax // EAX = return address of caller of caller + movl (%ebx), %ebx // EBX = EBP of caller of caller + + movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller + movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller + addl $8, %ebx + movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8 + + movl %ebp, %esp + popl %ebp + ret + +#endif /* !__NTOSKRNL__ */ + +#define REH_ERECORD 0x08 +#define REH_RFRAME 0x0C +#define REH_CONTEXT 0x10 +#define REH_DCONTEXT 0x14 +#define REH_EROUTINE 0x18 + +// Parameters: +// None +// Registers: +// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord +// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame +// [EBP+10h] - PVOID Context +// [EBP+14h] - PVOID DispatcherContext +// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine +// EDX - Address of protecting exception handler +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// Setup the protecting exception handler and call the exception +// handler in the right context. +_RtlpExecuteHandler: + pushl %ebp + movl %esp, %ebp + pushl REH_RFRAME(%ebp) + + pushl %edx + pushl %fs:0x0 + movl %esp, %fs:0x0 + + // Prepare to call the exception handler + pushl REH_DCONTEXT(%ebp) + pushl REH_CONTEXT(%ebp) + pushl REH_RFRAME(%ebp) + pushl REH_ERECORD(%ebp) + + // Now call the exception handler + movl REH_EROUTINE(%ebp), %eax + call *%eax + + cmpl $-1, %fs:0x0 + jne .reh_stack_looks_ok + + // This should not happen + pushl 0 + pushl 0 + pushl 0 + pushl 0 + call _RtlAssert@16 + +.reh_loop: + jmp .reh_loop + +.reh_stack_looks_ok: + movl %fs:0x0, %esp + + // Return to the 'front-end' for this function + popl %fs:0x0 + movl %ebp, %esp + popl %ebp + ret + + +#define REP_ERECORD 0x04 +#define REP_RFRAME 0x08 +#define REP_CONTEXT 0x0C +#define REP_DCONTEXT 0x10 + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// This exception handler protects the exception handling +// mechanism by detecting nested exceptions. +_RtlpExceptionProtector: + movl $ExceptionContinueSearch, %eax + movl REP_ERECORD(%esp), %ecx + testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) + jnz .rep_end + + // Unwinding is not taking place, so return ExceptionNestedException + + // Set DispatcherContext field to the exception registration for the + // exception handler that executed when a nested exception occurred + movl REP_DCONTEXT(%esp), %ecx + movl REP_RFRAME(%esp), %eax + movl %eax, (%ecx) + movl $ExceptionNestedException, %eax + +.rep_end: + ret + + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// Front-end +_RtlpExecuteHandlerForException: + movl $_RtlpExceptionProtector, %edx + jmp _RtlpExecuteHandler + + +#define RUP_ERECORD 0x04 +#define RUP_RFRAME 0x08 +#define RUP_CONTEXT 0x0C +#define RUP_DCONTEXT 0x10 + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +// Notes: +// This exception handler protects the exception handling +// mechanism by detecting collided unwinds. +_RtlpUnwindProtector: + movl $ExceptionContinueSearch, %eax + movl %ecx, RUP_ERECORD(%esp) + testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx) + jz .rup_end + + // Unwinding is taking place, so return ExceptionCollidedUnwind + + movl RUP_RFRAME(%esp), %ecx + movl RUP_DCONTEXT(%esp), %edx + + // Set DispatcherContext field to the exception registration for the + // exception handler that executed when a collision occurred + movl RUP_RFRAME(%ecx), %eax + movl %eax, (%edx) + movl $ExceptionCollidedUnwind, %eax + +.rup_end: + ret + + +// Parameters: +// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord +// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+0Ch] - PCONTEXT Context +// [ESP+10h] - PVOID DispatcherContext +// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler +// Registers: +// None +// Returns: +// EXCEPTION_DISPOSITION +_RtlpExecuteHandlerForUnwind: + movl $_RtlpUnwindProtector, %edx + jmp _RtlpExecuteHandler diff --git a/ntoskrnl/rtl/i386/exception.c b/ntoskrnl/rtl/i386/exception.c new file mode 100755 index 0000000..db47357 --- /dev/null +++ b/ntoskrnl/rtl/i386/exception.c @@ -0,0 +1,475 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Kernel-mode exception support for IA-32 + * FILE: ntoskrnl/rtl/i386/exception.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +#if 1 +VOID STDCALL +MsvcrtDebug(ULONG Value) +{ + DbgPrint("KernelDebug 0x%.08x\n", Value); +} +#endif + +int +_abnormal_termination(void) +{ + DbgPrint("Abnormal Termination\n"); + return 0; +} + +struct _CONTEXT; + +EXCEPTION_DISPOSITION +_except_handler2( + struct _EXCEPTION_RECORD *ExceptionRecord, + void *RegistrationFrame, + struct _CONTEXT *ContextRecord, + void *DispatcherContext) +{ + DbgPrint("_except_handler2()\n"); + return (EXCEPTION_DISPOSITION)0; +} + +void __cdecl +_global_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame) +{ + RtlUnwind(RegistrationFrame, &&__ret_label, NULL, 0); +__ret_label: + // return is important + return; +} + + +/* Implemented in except.s */ + +VOID +RtlpCaptureContext(PCONTEXT pContext); + +/* Macros that will help streamline the SEH implementations for + kernel mode and user mode */ + +#define SehpGetStackLimits(StackBase, StackLimit) \ +{ \ + (*(StackBase)) = KeGetCurrentKPCR()->StackBase; \ + (*(StackLimit)) = KeGetCurrentKPCR()->StackLimit; \ +} + +#define SehpGetExceptionList() \ + (PEXCEPTION_REGISTRATION)(KeGetCurrentThread()->TrapFrame ->ExceptionList) + +#define SehpSetExceptionList(NewExceptionList) \ + KeGetCurrentThread()->TrapFrame->ExceptionList = (PVOID)(NewExceptionList) + +#define SehpCaptureContext(Context) \ +{ \ + KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, (Context)); \ +} + +/*** Code below this line is shared with lib/ntdll/arch/ia32/exception.c - please keep in sync ***/ + +VOID STDCALL +AsmDebug(ULONG Value) +{ + DbgPrint("Value 0x%.08x\n", Value); +} + + +/* Declare a few prototypes for the functions in except.s */ + +EXCEPTION_DISPOSITION +RtlpExecuteHandlerForException( + PEXCEPTION_RECORD ExceptionRecord, + PEXCEPTION_REGISTRATION RegistrationFrame, + PCONTEXT Context, + PVOID DispatcherContext, + PEXCEPTION_HANDLER ExceptionHandler); + +EXCEPTION_DISPOSITION +RtlpExecuteHandlerForUnwind( + PEXCEPTION_RECORD ExceptionRecord, + PEXCEPTION_REGISTRATION RegistrationFrame, + PCONTEXT Context, + PVOID DispatcherContext, + PEXCEPTION_HANDLER ExceptionHandler); + + +#ifndef NDEBUG + +VOID RtlpDumpExceptionRegistrations(VOID) +{ + PEXCEPTION_REGISTRATION Current; + + DbgPrint("Dumping exception registrations:\n"); + + Current = SehpGetExceptionList(); + + if ((ULONG_PTR)Current != -1) + { + while ((ULONG_PTR)Current != -1) + { + DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler); + Current = Current->prev; + } + DbgPrint(" End-Of-List\n"); + } else { + DbgPrint(" No exception registrations exists.\n"); + } +} + +#endif /* NDEBUG */ + +ULONG +RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) +{ + PEXCEPTION_REGISTRATION RegistrationFrame; + DWORD DispatcherContext; + DWORD ReturnValue; + + DPRINT("RtlpDispatchException()\n"); + +#ifndef NDEBUG + RtlpDumpExceptionRegistrations(); +#endif /* NDEBUG */ + + RegistrationFrame = SehpGetExceptionList(); + + DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame); + + while ((ULONG_PTR)RegistrationFrame != -1) + { + EXCEPTION_RECORD ExceptionRecord2; + DWORD Temp = 0; + //PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8; + + // Make sure the registration frame is located within the stack + + DPRINT("Error checking\n"); +#if 0 + if (Teb->Tib.StackBase > RegistrationFrameEnd) + { + DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n", + Teb->Tib.StackBase, RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } + // FIXME: Stack top, correct? + if (Teb->Tib.StackLimit < RegistrationFrameEnd) + { + DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n", + Teb->Tib.StackLimit, RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } + + // Make sure stack is DWORD aligned + if ((ULONG_PTR)RegistrationFrame & 3) + { + DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n", + RegistrationFrameEnd); + ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID; + return ExceptionContinueExecution; + } +#endif + +#if 0 + /* FIXME: */ + if (someFlag) + RtlpLogLastExceptionDisposition( hLog, retValue ); +#endif + + DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler); + DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord); + DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame); + DPRINT("Context 0x%X\n", Context); + DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext); + + ReturnValue = RtlpExecuteHandlerForException( + ExceptionRecord, + RegistrationFrame, + Context, + &DispatcherContext, + RegistrationFrame->handler); + +#ifndef NDEBUG + + DPRINT("Exception handler said 0x%X\n", ReturnValue); + DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame); + { + PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08); + DPRINT("StandardESP == 0x%.08x\n", sp[0]); + DPRINT("Exception Pointers == 0x%.08x\n", sp[1]); + DPRINT("PrevFrame == 0x%.08x\n", sp[2]); + DPRINT("Handler == 0x%.08x\n", sp[3]); + DPRINT("ScopeTable == 0x%.08x\n", sp[4]); + DPRINT("TryLevel == 0x%.08x\n", sp[5]); + DPRINT("EBP == 0x%.08x\n", sp[6]); + } + +#endif + + if (RegistrationFrame == NULL) + { + ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag + } + + if (ReturnValue == ExceptionContinueExecution) + { + DPRINT("ReturnValue == ExceptionContinueExecution\n"); + if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) + { + DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n"); + + ExceptionRecord2.ExceptionRecord = ExceptionRecord; + ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; + ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ExceptionRecord2.NumberParameters = 0; + RtlRaiseException(&ExceptionRecord2); + } + else + { + /* Copy the (possibly changed) context back to the trap frame and return */ + NtContinue(Context, FALSE); + return ExceptionContinueExecution; + } + } + else if (ReturnValue == ExceptionContinueSearch) + { + DPRINT("ReturnValue == ExceptionContinueSearch\n"); + + /* Nothing to do here */ + } + else if (ReturnValue == ExceptionNestedException) + { + DPRINT("ReturnValue == ExceptionNestedException\n"); + + ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND; + if (DispatcherContext > Temp) + { + Temp = DispatcherContext; + } + } + else /* if (ReturnValue == ExceptionCollidedUnwind) */ + { + DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n"); + + ExceptionRecord2.ExceptionRecord = ExceptionRecord; + ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION; + ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + ExceptionRecord2.NumberParameters = 0; + RtlRaiseException(&ExceptionRecord2); + } + + RegistrationFrame = RegistrationFrame->prev; // Go to previous frame + } + + /* No exception handler will handle this exception */ + + DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n"); + + return ExceptionContinueExecution; +} + +VOID STDCALL +RtlRaiseStatus(NTSTATUS Status) +{ + EXCEPTION_RECORD ExceptionRecord; + + DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status); + + ExceptionRecord.ExceptionCode = Status; + ExceptionRecord.ExceptionRecord = NULL; + ExceptionRecord.NumberParameters = 0; + ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + RtlRaiseException (& ExceptionRecord); +} + +VOID STDCALL +RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame, + PVOID ReturnAddress, + PEXCEPTION_RECORD ExceptionRecord, + DWORD EaxValue) +{ + PEXCEPTION_REGISTRATION ERHead; + PEXCEPTION_RECORD pExceptRec; + EXCEPTION_RECORD TempER; + CONTEXT Context; + + DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame); + +#ifndef NDEBUG + RtlpDumpExceptionRegistrations(); +#endif /* NDEBUG */ + + ERHead = SehpGetExceptionList(); + + DPRINT("ERHead is 0x%X\n", ERHead); + + if (ExceptionRecord == NULL) // The normal case + { + DPRINT("ExceptionRecord == NULL (normal)\n"); + + pExceptRec = &TempER; + pExceptRec->ExceptionFlags = 0; + pExceptRec->ExceptionCode = STATUS_UNWIND; + pExceptRec->ExceptionRecord = NULL; + pExceptRec->ExceptionAddress = ReturnAddress; + pExceptRec->ExceptionInformation[0] = 0; + } + + if (RegistrationFrame) + pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING; + else + pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND); + +#ifndef NDEBUG + DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags); + if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING) + { + DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING); + } + if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND) + { + DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND); + } +#endif /* NDEBUG */ + + Context.ContextFlags = + (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS); + + SehpCaptureContext(&Context); + + DPRINT("Context.Eip = 0x%.08x\n", Context.Eip); + DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp); + DPRINT("Context.Esp = 0x%.08x\n", Context.Esp); + + Context.Esp += 0x10; + Context.Eax = EaxValue; + + // Begin traversing the list of EXCEPTION_REGISTRATION + while ((ULONG_PTR)ERHead != -1) + { + EXCEPTION_RECORD er2; + + DPRINT("ERHead 0x%X\n", ERHead); + + if (ERHead == RegistrationFrame) + { + DPRINT("Continueing execution\n"); + NtContinue(&Context, FALSE); + return; + } + else + { + // If there's an exception frame, but it's lower on the stack + // than the head of the exception list, something's wrong! + if (RegistrationFrame && (RegistrationFrame <= ERHead)) + { + DPRINT("The exception frame is bad\n"); + + // Generate an exception to bail out + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + } + +#if 0 + Stack = ERHead + sizeof(EXCEPTION_REGISTRATION); + if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead + && (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple + && (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane) + { +#else + if (1) { +#endif + PEXCEPTION_REGISTRATION NewERHead; + PEXCEPTION_REGISTRATION pCurrExceptReg; + EXCEPTION_DISPOSITION ReturnValue; + + DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler); + + ReturnValue = RtlpExecuteHandlerForUnwind( + pExceptRec, + ERHead, + &Context, + &NewERHead, + ERHead->handler); + + DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue); + + if (ReturnValue != ExceptionContinueSearch) + { + if (ReturnValue != ExceptionCollidedUnwind) + { + DPRINT("Bad return value\n"); + + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_INVALID_DISPOSITION; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + else + { + ERHead = NewERHead; + } + } + + pCurrExceptReg = ERHead; + ERHead = ERHead->prev; + + DPRINT("New ERHead is 0x%X\n", ERHead); + + DPRINT("Setting exception registration at 0x%X as current\n", + RegistrationFrame->prev); + + // Unlink the exception handler + SehpSetExceptionList(RegistrationFrame->prev); + } + else // The stack looks goofy! Raise an exception to bail out + { + DPRINT("Bad stack\n"); + + er2.ExceptionRecord = pExceptRec; + er2.NumberParameters = 0; + er2.ExceptionCode = STATUS_BAD_STACK; + er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE; + + RtlRaiseException(&er2); + } + } + + // If we get here, we reached the end of the EXCEPTION_REGISTRATION list. + // This shouldn't happen normally. + + DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n", + RegistrationFrame); + + if ((ULONG_PTR)RegistrationFrame == -1) + NtContinue(&Context, FALSE); + else + NtRaiseException(pExceptRec, &Context, 0); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/i386/memcpy.c b/ntoskrnl/rtl/i386/memcpy.c new file mode 100644 index 0000000..de051c2 --- /dev/null +++ b/ntoskrnl/rtl/i386/memcpy.c @@ -0,0 +1,34 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/i386/memcpy.c + * PROGRAMMER: Hartmut Birr + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +#undef memcpy +void *memcpy (void *to, const void *from, size_t count) +{ + __asm__( \ + "or %%ecx,%%ecx\n\t"\ + "jz .L1\n\t" \ + "cld\n\t" \ + "rep\n\t" \ + "movsb\n\t" \ + ".L1:\n\t" + : + : "D" (to), "S" (from), "c" (count)); + return to; +} + diff --git a/ntoskrnl/rtl/i386/memset.c b/ntoskrnl/rtl/i386/memset.c new file mode 100644 index 0000000..5474cca --- /dev/null +++ b/ntoskrnl/rtl/i386/memset.c @@ -0,0 +1,31 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/i386/memcpy.c + * PROGRAMMER: Hartmut Birr + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +void * memset(void *src, int val, size_t count) +{ + __asm__( \ + "or %%ecx,%%ecx\n\t"\ + "jz .L1\n\t" \ + "cld\t\n" \ + "rep\t\n" \ + "stosb\t\n" \ + ".L1:\n\t" + : + : "D" (src), "c" (count), "a" (val)); + return src; +} diff --git a/ntoskrnl/rtl/i386/seh.s b/ntoskrnl/rtl/i386/seh.s new file mode 100755 index 0000000..03ccd6b --- /dev/null +++ b/ntoskrnl/rtl/i386/seh.s @@ -0,0 +1,366 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Runtime library exception support for IA-32 + * FILE: ntoskrnl/rtl/i386/seh.s + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: This file is shared with lib/msvcrt/except/seh.s. + * Please keep them in sync. + */ + +#define ExceptionContinueExecution 0 +#define ExceptionContinueSearch 1 +#define ExceptionNestedException 2 +#define ExceptionCollidedUnwind 3 + +#define EXCEPTION_NONCONTINUABLE 0x01 +#define EXCEPTION_UNWINDING 0x02 +#define EXCEPTION_EXIT_UNWIND 0x04 +#define EXCEPTION_STACK_INVALID 0x08 +#define EXCEPTION_NESTED_CALL 0x10 +#define EXCEPTION_TARGET_UNWIND 0x20 +#define EXCEPTION_COLLIDED_UNWIND 0x40 + +#define EXCEPTION_UNWIND_MODE \ +( EXCEPTION_UNWINDING \ + | EXCEPTION_EXIT_UNWIND \ + | EXCEPTION_TARGET_UNWIND \ + | EXCEPTION_COLLIDED_UNWIND) + +#define EREC_CODE 0x00 +#define EREC_FLAGS 0x04 +#define EREC_RECORD 0x08 +#define EREC_ADDRESS 0x0C +#define EREC_NUMPARAMS 0x10 +#define EREC_INFO 0x14 + +#define TRYLEVEL_NONE -1 +#define TRYLEVEL_INVALID -2 + +#define ER_STANDARDESP -0x08 +#define ER_EPOINTERS -0x04 +#define ER_PREVFRAME 0x00 +#define ER_HANDLER 0x04 +#define ER_SCOPETABLE 0x08 +#define ER_TRYLEVEL 0x0C +#define ER_EBP 0x10 + +#define ST_TRYLEVEL 0x00 +#define ST_FILTER 0x04 +#define ST_HANDLER 0x08 + +#define CONTEXT_EDI 0x9C +#define CONTEXT_EBX 0xA4 +#define CONTEXT_EIP 0xB8 + +.globl __local_unwind2 +.globl __except_handler3 + +// EAX = value to print +_do_debug: + pushal + pushl %eax + call _MsvcrtDebug@4 + popal + ret + +#define LU2_TRYLEVEL 0x08 +#define LU2_REGFRAME 0x04 + +// +// void +// _local_unwind2(PEXCEPTION_REGISTRATION RegistrationFrame, +// LONG TryLevel) +// +// Parameters: +// [EDX+08h] - PEXCEPTION_REGISTRATION RegistrationFrame +// [EDX+04h] - LONG TryLevel +// Registers: +// EBP - EBP of call frame we are unwinding +// Returns: +// Nothing +// Notes: +// Run all termination handlers for a call frame from the current +// try-level up to (but not including) the given stop try-level. +__local_unwind2: + // Setup our call frame so we can access parameters using EDX + //pushl %ebp + movl %esp, %edx + + // FIXME: Setup an EXCEPTION_REGISTRATION entry to protect the + // unwinding in case something goes wrong + +.lu2_next_scope: + + // Keep a pointer to the exception registration in EBX + movl LU2_REGFRAME(%edx), %ebx + + // If we have reached the end of the chain or we're asked to stop here + // by the caller then exit + movl ER_TRYLEVEL(%ebx), %eax + + cmpl $-1, %eax + je .lu2_done + + cmpl LU2_TRYLEVEL(%edx), %eax + je .lu2_done + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + + // Compute the offset of the entry in the scopetable that describes + // the scope that is to be unwound. Put the offset in EDI. + movl ST_TRYLEVEL(%esi), %edi + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + + // If this is not a termination handler then skip it + cmpl $0, ST_FILTER(%edi) + jne .lu2_next_scope + + // Save the previous try-level in the exception registration structure + movl ST_TRYLEVEL(%edi), %eax + movl %eax, ER_TRYLEVEL(%ebx) + + // Fetch the address of the termination handler + movl ST_HANDLER(%edi), %eax + + // Termination handlers may trash all registers so save the + // important ones and then call the handler + pushl %edx + call *%eax + + // Get our base pointer back + popl %edx + + jmp .lu2_next_scope + +.lu2_done: + + // FIXME: Tear down the EXCEPTION_REGISTRATION entry setup to protect + // the unwinding + + //movl %esi, %esp + //popl %ebp + ret + +#define EH3_DISPCONTEXT 0x14 +#define EH3_CONTEXT 0x10 +#define EH3_REGFRAME 0x0C +#define EH3_ERECORD 0x08 + +// Parameters: +// [ESP+14h] - PVOID DispatcherContext +// [ESP+10h] - PCONTEXT Context +// [ESP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame +// [ESP+08h] - PEXCEPTION_RECORD ExceptionRecord +// Registers: +// Unknown +// Returns: +// EXCEPTION_DISPOSITION - How this handler handled the exception +// Notes: +// Try to find an exception handler that will handle the exception. +// Traverse the entries in the scopetable that is associated with the +// exception registration passed as a parameter to this function. +// If an exception handler that will handle the exception is found, it +// is called and this function never returns +__except_handler3: + // Setup our call frame so we can access parameters using EBP + pushl %ebp // Standard ESP in frame (considered part of EXCEPTION_REGISTRATION) + movl %esp, %ebp + + // Don't trust the direction flag to be cleared + cld + + // Either we're called to handle an exception or we're called to unwind + movl EH3_ERECORD(%ebp), %eax + testl $EXCEPTION_UNWIND_MODE, EREC_FLAGS(%eax) + jnz .eh3_unwind + + // Keep a pointer to the exception registration in EBX + movl EH3_REGFRAME(%ebp), %ebx + + // Build an EXCEPTION_POINTERS structure on the stack and store it's + // address in the EXCEPTION_REGISTRATION structure + movl EH3_CONTEXT(%esp), %eax + pushl %ebx // Registration frame + pushl %eax // Context + movl %esp, ER_EPOINTERS(%ebx) // Pointer to EXCEPTION_REGISTRATION on the stack + + // Keep current try-level in EDI + movl ER_TRYLEVEL(%ebx), %edi + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + +.eh3_next_scope: + + // If we have reached the end of the chain then exit + cmpl $-1, %edi + je .eh3_search + + // Compute the offset of the entry in the scopetable and store + // the absolute address in EAX + lea (%edi, %edi, 2), %eax + shll $2, %eax + addl %esi, %eax + + // Fetch the address of the filter routine + movl ST_FILTER(%eax), %eax + + // If this is a termination handler then skip it + cmpl $0, %eax + je .eh3_continue + + // Filter routines may trash all registers so save the important + // ones before restoring the call frame ebp and calling the handler + pushl %ebp + pushl %edi // Stop try-level + lea ER_EBP(%ebx), %ebp + call *%eax + popl %edi // Stop try-level + popl %ebp + + // Reload EBX with registration frame address + movl EH3_REGFRAME(%ebp), %ebx + + // Be more flexible here by checking if the return value is less than + // zero, equal to zero, or larger than zero instead of the defined + // values: + // -1 (EXCEPTION_CONTINUE_EXECUTION) + // 0 (EXCEPTION_CONTINUE_SEARCH) + // +1 (EXCEPTION_EXECUTE_HANDLER) + orl %eax, %eax + jz .eh3_continue + js .eh3_dismiss + + // Filter returned: EXCEPTION_EXECUTE_HANDLER + + // Ask the OS to perform global unwinding. + pushl %edi // Save stop try-level + pushl %ebx // Save registration frame address + pushl %ebx // Registration frame address + call __global_unwind2 + popl %eax // Remove parameter to __global_unwind2 + popl %ebx // Restore registration frame address + popl %edi // Restore stop try-level + + // Change the context structure so _except_finish is called in the + // correct context since we return ExceptionContinueExecution. + movl EH3_CONTEXT(%ebp), %eax + + movl %edi, CONTEXT_EDI(%eax) // Stop try-level + movl %ebx, CONTEXT_EBX(%eax) // Registration frame address + movl $_except_finish, CONTEXT_EIP(%eax) + + movl $ExceptionContinueExecution, %eax + jmp .eh3_return + + // Filter returned: EXCEPTION_CONTINUE_SEARCH +.eh3_continue: + + // Reload ESI because the filter routine may have trashed it + movl ER_SCOPETABLE(%ebx), %esi + + // Go one try-level closer to the top + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + movl ST_TRYLEVEL(%edi), %edi + + jmp .eh3_next_scope + + // Filter returned: EXCEPTION_CONTINUE_EXECUTION + // Continue execution like nothing happened +.eh3_dismiss: + movl $ExceptionContinueExecution, %eax + jmp .eh3_return + + // Tell the OS to search for another handler that will handle the exception +.eh3_search: + + movl $ExceptionContinueSearch, %eax + jmp .eh3_return + + // Perform local unwinding +.eh3_unwind: + + movl $ExceptionContinueSearch, %eax + testl $EXCEPTION_TARGET_UNWIND, EREC_FLAGS(%eax) + jnz .eh3_return + + // Save some important registers + pushl %ebp + + lea ER_EBP(%ebx), %ebp + pushl $-1 + pushl %ebx + call __local_unwind2 + addl $8, %esp + + // Restore some important registers + popl %ebp + + movl $ExceptionContinueSearch, %eax + + // Get me out of here +.eh3_return: + + movl %ebp, %esp + popl %ebp + ret + +// Parameters: +// None +// Registers: +// EBX - Pointer to exception registration structure +// EDI - Stop try-level +// Returns: +// - +// Notes: +// - +_except_finish: + + // Setup EBP for the exception handler. By doing this the exception + // handler can access local variables as normal + lea ER_EBP(%ebx), %ebp + + // Save some important registers + pushl %ebp + pushl %ebx + pushl %edi + + // Stop try-level + pushl %edi + + // Pointer to exception registration structure + pushl %ebx + call __local_unwind2 + addl $8, %esp + + // Restore some important registers + popl %edi + popl %ebx + popl %ebp + + // Keep a pointer to the scopetable in ESI + movl ER_SCOPETABLE(%ebx), %esi + + // Compute the offset of the entry in the scopetable and store + // the absolute address in EDI + lea (%edi, %edi, 2), %edi + shll $2, %edi + addl %esi, %edi + + // Set the current try-level to the previous try-level and call + // the exception handler + movl ST_TRYLEVEL(%edi), %eax + movl %eax, ER_TRYLEVEL(%ebx) + movl ST_HANDLER(%edi), %eax + + call *%eax + + // We should never get here + ret diff --git a/ntoskrnl/rtl/largeint.c b/ntoskrnl/rtl/largeint.c new file mode 100644 index 0000000..d45df86 --- /dev/null +++ b/ntoskrnl/rtl/largeint.c @@ -0,0 +1,250 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: kernel/rtl/largeint.c + * PURPOSE: Large integer operations + * UPDATE HISTORY: + * Created 22/05/98 + * 08/30/98 RJJ Implemented several functions + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +LARGE_INTEGER +STDCALL +RtlConvertLongToLargeInteger ( + LONG SignedInteger + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = SignedInteger; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlConvertUlongToLargeInteger ( + ULONG UnsignedInteger + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = UnsignedInteger; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlEnlargedIntegerMultiply ( + LONG Multiplicand, + LONG Multiplier + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = (LONGLONG) Multiplicand * Multiplier; + + return RC; +} + +ULONG +STDCALL +RtlEnlargedUnsignedDivide ( + ULARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ) +{ + if (Remainder) + *Remainder = Dividend.QuadPart % Divisor; + + return (ULONG)(Dividend.QuadPart / Divisor); +} + +LARGE_INTEGER +STDCALL +RtlEnlargedUnsignedMultiply ( + ULONG Multiplicand, + ULONG Multiplier + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlExtendedIntegerMultiply ( + LARGE_INTEGER Multiplicand, + LONG Multiplier + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = Multiplicand.QuadPart * Multiplier; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlExtendedLargeIntegerDivide ( + LARGE_INTEGER Dividend, + ULONG Divisor, + PULONG Remainder + ) +{ + LARGE_INTEGER RC; + + if (Remainder) + *Remainder = Dividend.QuadPart % Divisor; + + RC.QuadPart = Dividend.QuadPart / Divisor; + + return RC; +} + +LARGE_INTEGER STDCALL +RtlExtendedMagicDivide (LARGE_INTEGER Dividend, + LARGE_INTEGER MagicDivisor, + CCHAR ShiftCount) +{ + LARGE_INTEGER Result; + + Result.QuadPart = (Dividend.QuadPart * MagicDivisor.QuadPart) >> ShiftCount; + return(Result); +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerAdd ( + LARGE_INTEGER Addend1, + LARGE_INTEGER Addend2 + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerArithmeticShift ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ) +{ + LARGE_INTEGER RC; + CHAR Shift; + + Shift = ShiftCount % 64; + + if (Shift < 32) + { + RC.QuadPart = LargeInteger.QuadPart >> Shift; + } + else + { + /* copy the sign bit */ + RC.u.HighPart |= (LargeInteger.u.HighPart & 0x80000000); + RC.u.LowPart = LargeInteger.u.HighPart >> Shift; + } + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerDivide ( + LARGE_INTEGER Dividend, + LARGE_INTEGER Divisor, + PLARGE_INTEGER Remainder + ) +{ + LARGE_INTEGER RC; + + if (Remainder) + Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart; + + RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerNegate ( + LARGE_INTEGER Subtrahend + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = - Subtrahend.QuadPart; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerShiftLeft ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ) +{ + LARGE_INTEGER RC; + CHAR Shift; + + Shift = ShiftCount % 64; + RC.QuadPart = LargeInteger.QuadPart << Shift; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerShiftRight ( + LARGE_INTEGER LargeInteger, + CCHAR ShiftCount + ) +{ + LARGE_INTEGER RC; + CHAR Shift; + + Shift = ShiftCount % 64; + RC.QuadPart = LargeInteger.QuadPart >> ShiftCount; + + return RC; +} + +LARGE_INTEGER +STDCALL +RtlLargeIntegerSubtract ( + LARGE_INTEGER Minuend, + LARGE_INTEGER Subtrahend + ) +{ + LARGE_INTEGER RC; + + RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart; + + return RC; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/mem.c b/ntoskrnl/rtl/mem.c new file mode 100644 index 0000000..dfdbdd7 --- /dev/null +++ b/ntoskrnl/rtl/mem.c @@ -0,0 +1,206 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: kernel/rtl/mem.c + * PURPOSE: Memory functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +MmCopyToCaller(PVOID Dest, PVOID Src, ULONG NumberOfBytes) +{ + NTSTATUS Status; + + if (ExGetPreviousMode() == UserMode) + { + if ((ULONG)Dest >= KERNEL_BASE) + { + return(STATUS_ACCESS_VIOLATION); + } + Status = MmSafeCopyToUser(Dest, Src, NumberOfBytes); + return(Status); + } + else + { + memcpy(Dest, Src, NumberOfBytes); + return(STATUS_SUCCESS); + } +} + +NTSTATUS STDCALL +MmCopyFromCaller(PVOID Dest, PVOID Src, ULONG NumberOfBytes) +{ + NTSTATUS Status; + + if (ExGetPreviousMode() == UserMode) + { + if ((ULONG)Src >= KERNEL_BASE) + { + return(STATUS_ACCESS_VIOLATION); + } + Status = MmSafeCopyFromUser(Dest, Src, NumberOfBytes); + return(Status); + } + else + { + memcpy(Dest, Src, NumberOfBytes); + return(STATUS_SUCCESS); + } +} + + +ULONG +STDCALL +RtlCompareMemory ( + PVOID Source1, + PVOID Source2, + ULONG Length + ) +/* + * FUNCTION: Compares blocks of memory and returns the number of equal bytes + * ARGUMENTS: + * Source1 = Block to compare + * Source2 = Block to compare + * Length = Number of bytes to compare + * RETURNS: Number of equal bytes + */ +{ + int i,total; + + for (i=0,total=0;i 0) + { + *Dest = Fill; + Dest++; + Count--; + } +} + + +VOID +STDCALL +RtlMoveMemory ( + PVOID Destination, + CONST VOID * Source, + ULONG Length + ) +{ + memmove ( + Destination, + Source, + Length + ); +} + + +VOID +STDCALL +RtlZeroMemory ( + PVOID Destination, + ULONG Length + ) +{ + RtlFillMemory ( + Destination, + Length, + 0 + ); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/memchr.c b/ntoskrnl/rtl/memchr.c new file mode 100644 index 0000000..dd8e58c --- /dev/null +++ b/ntoskrnl/rtl/memchr.c @@ -0,0 +1,42 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/rtl/memchr.c + * PURPOSE: Implements memchr function + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + + +#include + +void *memchr(const void *s, int c, size_t n) +{ + while (n > 0) + { + if ((*((const unsigned char *)s)) == (unsigned char)c) + { + return((void *)s); + } + s++; + n--; + } + return(NULL); +} diff --git a/ntoskrnl/rtl/memcmp.c b/ntoskrnl/rtl/memcmp.c new file mode 100644 index 0000000..ed1b796 --- /dev/null +++ b/ntoskrnl/rtl/memcmp.c @@ -0,0 +1,47 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * FILE: ntoskrnl/rtl/memcmp.c + * PURPOSE: Implements memcmp function + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 01/10/00 + */ + +#include + +int memcmp(const void* _s1, const void* _s2, size_t n) +{ + unsigned int i; + const char* s1; + const char* s2; + + s1 = (const char *)_s1; + s2 = (const char *)_s2; + for (i = 0; i < n; i++) + { + if ((*s1) != (*s2)) + { + return((*s1) - (*s2)); + } + s1++; + s2++; + } + return(0); +} diff --git a/ntoskrnl/rtl/memcpy.c b/ntoskrnl/rtl/memcpy.c new file mode 100644 index 0000000..7373985 --- /dev/null +++ b/ntoskrnl/rtl/memcpy.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/memcpy.c + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +#undef memcpy +void *memcpy (void *to, const void *from, size_t count) +{ + const char *f = (char*)from; + char *t = (char *)to; + int i = count; + + while (i-- > 0) + *t++ = *f++; + + return to; +} + diff --git a/ntoskrnl/rtl/memmove.c b/ntoskrnl/rtl/memmove.c new file mode 100644 index 0000000..f15f6bb --- /dev/null +++ b/ntoskrnl/rtl/memmove.c @@ -0,0 +1,35 @@ +#include + +void * memmove(void *dest,const void *src,size_t count) +{ + char *char_dest = (char *)dest; + char *char_src = (char *)src; + + if ((char_dest <= char_src) || (char_dest >= (char_src+count))) + { + /* non-overlapping buffers */ + while(count > 0) + { + *char_dest = *char_src; + char_dest++; + char_src++; + count--; + } + } + else + { + /* overlaping buffers */ + char_dest = (char *)dest + count - 1; + char_src = (char *)src + count - 1; + + while(count > 0) + { + *char_dest = *char_src; + char_dest--; + char_src--; + count--; + } + } + + return dest; +} diff --git a/ntoskrnl/rtl/memset.c b/ntoskrnl/rtl/memset.c new file mode 100644 index 0000000..49d1e73 --- /dev/null +++ b/ntoskrnl/rtl/memset.c @@ -0,0 +1,14 @@ + +#include + +void * memset(void *src, int val, size_t count) +{ + char *char_src = (char *)src; + + while(count>0) { + *char_src = val; + char_src++; + count--; + } + return src; +} diff --git a/ntoskrnl/rtl/message.c b/ntoskrnl/rtl/message.c new file mode 100644 index 0000000..3184c17 --- /dev/null +++ b/ntoskrnl/rtl/message.c @@ -0,0 +1,123 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Message table functions + * FILE: ntoskrnl/rtl/message.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 29/05/2001: Created + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +RtlFindMessage(PVOID BaseAddress, + ULONG Type, + ULONG Language, + ULONG MessageId, + PRTL_MESSAGE_RESOURCE_ENTRY *MessageResourceEntry) +{ + LDR_RESOURCE_INFO ResourceInfo; + PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry; + PRTL_MESSAGE_RESOURCE_DATA MessageTable; + NTSTATUS Status; + ULONG EntryOffset, IdOffset = 0; + PRTL_MESSAGE_RESOURCE_ENTRY MessageEntry; + + ULONG i; + + DPRINT("RtlFindMessage()\n"); + + ResourceInfo.Type = Type; + ResourceInfo.Name = 1; + ResourceInfo.Language = Language; + + Status = LdrFindResource_U(BaseAddress, + &ResourceInfo, + RESOURCE_DATA_LEVEL, + &ResourceDataEntry); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("ResourceDataEntry: %p\n", ResourceDataEntry); + + Status = LdrAccessResource(BaseAddress, + ResourceDataEntry, + (PVOID*)&MessageTable, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + DPRINT("MessageTable: %p\n", MessageTable); + + DPRINT("NumberOfBlocks %lu\n", MessageTable->NumberOfBlocks); + for (i = 0; i < MessageTable->NumberOfBlocks; i++) + { + DPRINT("LoId 0x%08lx HiId 0x%08lx Offset 0x%08lx\n", + MessageTable->Blocks[i].LowId, + MessageTable->Blocks[i].HighId, + MessageTable->Blocks[i].OffsetToEntries); + } + + for (i = 0; i < MessageTable->NumberOfBlocks; i++) + { + if ((MessageId >= MessageTable->Blocks[i].LowId) && + (MessageId <= MessageTable->Blocks[i].HighId)) + { + EntryOffset = MessageTable->Blocks[i].OffsetToEntries; + IdOffset = MessageId - MessageTable->Blocks[i].LowId; + break; + } + + if (MessageId < MessageTable->Blocks[i].LowId) + { + return STATUS_MESSAGE_NOT_FOUND; + } + } + + MessageEntry = (PRTL_MESSAGE_RESOURCE_ENTRY)((PUCHAR)MessageTable + MessageTable->Blocks[i].OffsetToEntries); + + DPRINT("EntryOffset 0x%08lx\n", EntryOffset); + DPRINT("IdOffset 0x%08lx\n", IdOffset); + + DPRINT("MessageEntry: %p\n", MessageEntry); + for (i = 0; i < IdOffset; i++) + { + DPRINT("MessageEntry %d: %p\n", i, MessageEntry); + MessageEntry = (PRTL_MESSAGE_RESOURCE_ENTRY)((PUCHAR)MessageEntry + (ULONG)MessageEntry->Length); + } + DPRINT("MessageEntry: %p\n", MessageEntry); + DPRINT("Flags: %hx\n", MessageEntry->Flags); + DPRINT("Length: %hu\n", MessageEntry->Length); + + if (MessageEntry->Flags == 0) + { + DPRINT("AnsiText: %s\n", MessageEntry->Text); + } + else + { + DPRINT("UnicodeText: %S\n", (PWSTR)MessageEntry->Text); + } + + if (MessageResourceEntry != NULL); + { + *MessageResourceEntry = MessageEntry; + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/nls.c b/ntoskrnl/rtl/nls.c new file mode 100644 index 0000000..e78be44 --- /dev/null +++ b/ntoskrnl/rtl/nls.c @@ -0,0 +1,617 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/nls.c + * PURPOSE: National Language Support (NLS) functions + * UPDATE HISTORY: + * 20/08/99 Created by Emanuele Aliberti + * 10/11/99 Added translation functions. + * + * NOTE: + * Multi-byte code pages are not supported yet. Even single-byte code + * pages are not supported properly. Only stupid CHAR->WCHAR and + * WCHAR->CHAR (Attention: data loss!!!) translation is done. + * + * TODO: + * 1) Implement code to initialize the translation tables. + * 2) Use fixed translation table for translation. + * 3) Add loading of translation tables (NLS files). + * 4) Add multi-byte translation code. + */ + +#include +//#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +BOOLEAN NlsMbCodePageTag = FALSE; +BOOLEAN NlsMbOemCodePageTag = FALSE; + +BYTE NlsLeadByteInfo = 0; /* ? */ + +USHORT NlsOemLeadByteInfo = 0; + +USHORT NlsAnsiCodePage = 0; +USHORT NlsOemCodePage = 0; /* not exported */ + +PWCHAR AnsiToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */ +PWCHAR OemToUnicodeTable = NULL; /* size: 256*sizeof(WCHAR) */ + +PCHAR UnicodeToAnsiTable = NULL; /* size: 65536*sizeof(CHAR) */ +PCHAR UnicodeToOemTable =NULL; /* size: 65536*sizeof(CHAR) */ + +PWCHAR UnicodeUpcaseTable = NULL; /* size: 65536*sizeof(WCHAR) */ +PWCHAR UnicodeLowercaseTable = NULL; /* size: 65536*sizeof(WCHAR) */ + + +/* FUNCTIONS *****************************************************************/ + +VOID +RtlpInitNlsTables(VOID) +{ + INT i; + PCHAR pc; + PWCHAR pwc; + + /* allocate and initialize ansi->unicode table */ + AnsiToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR)); + if (AnsiToUnicodeTable == NULL) + { + DbgPrint("Allocation of 'AnsiToUnicodeTable' failed\n"); + KeBugCheck(0); + } + + pwc = AnsiToUnicodeTable; + for (i = 0; i < 256; i++, pwc++) + *pwc = (WCHAR)i; + + /* allocate and initialize oem->unicode table */ + OemToUnicodeTable = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR)); + if (OemToUnicodeTable == NULL) + { + DbgPrint("Allocation of 'OemToUnicodeTable' failed\n"); + KeBugCheck(0); + } + + pwc = OemToUnicodeTable; + for (i = 0; i < 256; i++, pwc++) + *pwc = (WCHAR)i; + + /* allocate and initialize unicode->ansi table */ + UnicodeToAnsiTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR)); + if (UnicodeToAnsiTable == NULL) + { + DbgPrint("Allocation of 'UnicodeToAnsiTable' failed\n"); + KeBugCheck(0); + } + + pc = UnicodeToAnsiTable; + for (i = 0; i < 256; i++, pc++) + *pc = (CHAR)i; + for (; i < 65536; i++, pc++) + *pc = 0; + + /* allocate and initialize unicode->oem table */ + UnicodeToOemTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(CHAR)); + if (UnicodeToOemTable == NULL) + { + DbgPrint("Allocation of 'UnicodeToOemTable' failed\n"); + KeBugCheck(0); + } + + pc = UnicodeToOemTable; + for (i = 0; i < 256; i++, pc++) + *pc = (CHAR)i; + for (; i < 65536; i++, pc++) + *pc = 0; + + /* allocate and initialize unicode upcase table */ + UnicodeUpcaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR)); + if (UnicodeUpcaseTable == NULL) + { + DbgPrint("Allocation of 'UnicodeUpcaseTable' failed\n"); + KeBugCheck(0); + } + + pwc = UnicodeUpcaseTable; + for (i = 0; i < 65536; i++, pwc++) + *pwc = (WCHAR)i; + for (i = 'a'; i < ('z'+ 1); i++) + UnicodeUpcaseTable[i] = (WCHAR)i + (L'A' - L'a'); + + + /* allocate and initialize unicode lowercase table */ + UnicodeLowercaseTable = ExAllocatePool(NonPagedPool, 65536 * sizeof(WCHAR)); + if (UnicodeLowercaseTable == NULL) + { + DbgPrint("Allocation of 'UnicodeLowercaseTable' failed\n"); + KeBugCheck(0); + } + + pwc = UnicodeLowercaseTable; + for (i = 0; i < 65536; i++, pwc++) + *pwc = (WCHAR)i; + for (i = 'A'; i < ('Z'+ 1); i++) + UnicodeLowercaseTable[i] = (WCHAR)i - (L'A' - L'a'); + + /* FIXME: initialize codepage info */ + +} + + +NTSTATUS +RtlpInitNlsSections(ULONG Mod1Start, + ULONG Mod1End, + ULONG Mod2Start, + ULONG Mod2End, + ULONG Mod3Start, + ULONG Mod3End) +{ + UNICODE_STRING UnicodeString; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE DirectoryHandle; + HANDLE SectionHandle; + NTSTATUS Status; + LARGE_INTEGER SectionSize; + + DPRINT("Ansi section start: 0x%08lX\n", Mod1Start); + DPRINT("Ansi section end: 0x%08lX\n", Mod1End); + DPRINT("Oem section start: 0x%08lX\n", Mod2Start); + DPRINT("Oem section end: 0x%08lX\n", Mod2End); + DPRINT("Upcase section start: 0x%08lX\n", Mod3Start); + DPRINT("Upcase section end: 0x%08lX\n", Mod3End); + + /* Create the '\NLS' directory */ + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"\\NLS"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + OBJ_PERMANENT, + NULL, + NULL); + Status = NtCreateDirectoryObject(&DirectoryHandle, + 0, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Create the 'NlsSectionUnicode' section */ + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"NlsSectionUnicode"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + OBJ_PERMANENT, + DirectoryHandle, + NULL); + SectionSize.QuadPart = (Mod1End - Mod1Start) + + (Mod2End - Mod2Start) + (Mod3End - Mod3Start); + DPRINT("NlsSectionUnicode size: 0x%I64X\n", SectionSize.QuadPart); + + Status = NtCreateSection(&SectionHandle, + SECTION_ALL_ACCESS, + &ObjectAttributes, + &SectionSize, + PAGE_READWRITE, + 0, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + + /* create and initialize code page table */ + + /* map the nls table into the 'NlsSectionUnicode' section */ + + + NtClose(SectionHandle); + NtClose(DirectoryHandle); + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCustomCPToUnicodeN(PRTL_NLS_DATA NlsData, + PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR CustomString, + ULONG CustomSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsData->DbcsFlag == FALSE) + { + /* single-byte code page */ + if (CustomSize > (UnicodeSize / sizeof(WCHAR))) + Size = UnicodeSize / sizeof(WCHAR); + else + Size = CustomSize; + + if (ResultSize != NULL) + *ResultSize = Size * sizeof(WCHAR); + + for (i = 0; i < Size; i++) + { + *UnicodeString = NlsData->MultiByteToUnicode[(unsigned int)*CustomString]; + UnicodeString++; + CustomString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +RtlGetDefaultCodePage(PUSHORT AnsiCodePage, + PUSHORT OemCodePage) +{ + *AnsiCodePage = NlsAnsiCodePage; + *OemCodePage = NlsOemCodePage; +} + + +NTSTATUS STDCALL +RtlMultiByteToUnicodeN(PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR MbString, + ULONG MbSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + if (MbSize > (UnicodeSize / sizeof(WCHAR))) + Size = UnicodeSize / sizeof(WCHAR); + else + Size = MbSize; + + if (ResultSize != NULL) + *ResultSize = Size * sizeof(WCHAR); + + for (i = 0; i < Size; i++) + { + *UnicodeString = AnsiToUnicodeTable[(unsigned int)*MbString]; + UnicodeString++; + MbString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlMultiByteToUnicodeSize(PULONG UnicodeSize, + PCHAR MbString, + ULONG MbSize) +{ + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + *UnicodeSize = MbSize * sizeof (WCHAR); + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlOemToUnicodeN(PWCHAR UnicodeString, + ULONG UnicodeSize, + PULONG ResultSize, + PCHAR OemString, + ULONG OemSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbOemCodePageTag == FALSE) + { + /* single-byte code page */ + if (OemSize > (UnicodeSize / sizeof(WCHAR))) + Size = UnicodeSize / sizeof(WCHAR); + else + Size = OemSize; + + if (ResultSize != NULL) + *ResultSize = Size * sizeof(WCHAR); + + for (i = 0; i < Size; i++) + { + *UnicodeString = OemToUnicodeTable[(unsigned int)*OemString]; + UnicodeString++; + OemString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUnicodeToCustomCPN(PRTL_NLS_DATA NlsData, + PCHAR CustomString, + ULONG CustomSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsData->DbcsFlag == 0) + { + /* single-byte code page */ + if (UnicodeSize > (CustomSize * sizeof(WCHAR))) + Size = CustomSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)*UnicodeString]; + CustomString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS +STDCALL +RtlUnicodeToMultiByteN(PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (MbSize * sizeof(WCHAR))) + Size = MbSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *MbString = UnicodeToAnsiTable[(unsigned int)*UnicodeString]; + MbString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUnicodeToMultiByteSize(PULONG MbSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + *MbSize = UnicodeSize / sizeof (WCHAR); + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUnicodeToOemN(PCHAR OemString, + ULONG OemSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + ULONG Size = 0; + ULONG i; + + if (NlsMbOemCodePageTag == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (OemSize * sizeof(WCHAR))) + Size = OemSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + *OemString = UnicodeToOemTable[(unsigned int)*UnicodeString]; + OemString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeToCustomCPN(PRTL_NLS_DATA NlsData, + PCHAR CustomString, + ULONG CustomSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + ULONG Size = 0; + ULONG i; + WCHAR wc; + + if (NlsData->DbcsFlag == 0) + { + /* single-byte code page */ + if (UnicodeSize > (CustomSize * sizeof(WCHAR))) + Size = CustomSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString]; + *CustomString = NlsData->UnicodeToMultiByte[(unsigned int)wc]; + CustomString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeToMultiByteN(PCHAR MbString, + ULONG MbSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + ULONG Size = 0; + ULONG i; + WCHAR wc; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (MbSize * sizeof(WCHAR))) + Size = MbSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString]; + *MbString = UnicodeToAnsiTable[(unsigned int)wc]; + MbString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeToOemN(PCHAR OemString, + ULONG OemSize, + PULONG ResultSize, + PWCHAR UnicodeString, + ULONG UnicodeSize) +{ + ULONG Size = 0; + ULONG i; + UCHAR wc; + + if (NlsMbOemCodePageTag == FALSE) + { + /* single-byte code page */ + if (UnicodeSize > (OemSize * sizeof(WCHAR))) + Size = OemSize; + else + Size = UnicodeSize / sizeof(WCHAR); + + if (ResultSize != NULL) + *ResultSize = Size; + + for (i = 0; i < Size; i++) + { + wc = UnicodeUpcaseTable[(unsigned int)*UnicodeString]; + *OemString = UnicodeToOemTable[(unsigned int)wc]; + OemString++; + UnicodeString++; + } + } + else + { + /* multi-byte code page */ + /* FIXME */ + } + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/purecall.c b/ntoskrnl/rtl/purecall.c new file mode 100644 index 0000000..aa20290 --- /dev/null +++ b/ntoskrnl/rtl/purecall.c @@ -0,0 +1,23 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Message table functions + * FILE: ntoskrnl/rtl/message.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 29/05/2001: Created + */ + +/* INCLUDES *****************************************************************/ + +#include + +/* FUNCTIONS ****************************************************************/ + +void _purecall(void) +{ + ExRaiseStatus(STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/qsort.c b/ntoskrnl/rtl/qsort.c new file mode 100644 index 0000000..0ea2726 --- /dev/null +++ b/ntoskrnl/rtl/qsort.c @@ -0,0 +1,266 @@ +/* $Id$ + * + * FILE: ntoskrnl/rtl/qsort.c + * NOTE: Adapted from CygWin newlib 2000-03-12. + */ +/* +FUNCTION +<>---sort an array + +INDEX + qsort + +ANSI_SYNOPSIS + #include + void qsort(void *<[base]>, size_t <[nmemb]>, size_t <[size]>, + int (*<[compar]>)(const void *, const void *) ); + +TRAD_SYNOPSIS + #include + qsort(<[base]>, <[nmemb]>, <[size]>, <[compar]> ) + char *<[base]>; + size_t <[nmemb]>; + size_t <[size]>; + int (*<[compar]>)(); + +DESCRIPTION +<> sorts an array (beginning at <[base]>) of <[nmemb]> objects. +<[size]> describes the size of each element of the array. + +You must supply a pointer to a comparison function, using the argument +shown as <[compar]>. (This permits sorting objects of unknown +properties.) Define the comparison function to accept two arguments, +each a pointer to an element of the array starting at <[base]>. The +result of <<(*<[compar]>)>> must be negative if the first argument is +less than the second, zero if the two arguments match, and positive if +the first argument is greater than the second (where ``less than'' and +``greater than'' refer to whatever arbitrary ordering is appropriate). + +The array is sorted in place; that is, when <> returns, the +array elements beginning at <[base]> have been reordered. + +RETURNS +<> does not return a result. + +PORTABILITY +<> is required by ANSI (without specifying the sorting algorithm). +*/ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __GNUC__ +#define inline +#endif + +/* FIXME: these types should be from the default includes */ + +typedef int (* _pfunccmp_t) (char *, char *); +typedef int size_t; + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *) (parmi); \ + register TYPE *pj = (TYPE *) (parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc ( + char * a, + char * b, + int n, + int swaptype + ) +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +static inline char * +med3 ( + char * a, + char * b, + char * c, + _pfunccmp_t cmp + ) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} + + +/* EXPORTED */ +void +qsort ( + void * a, + size_t n, + size_t es, + _pfunccmp_t cmp + ) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + pm = (char *) a + (n / 2) * es; + if (n > 7) + { + pl = (char *) a; + pn = (char *) a + (n - 1) * es; + if (n > 40) + { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *) a + es; + + pc = pd = (char *) a + (n - 1) * es; + for (;;) + { + while (pb <= pc && (r = cmp(pb, a)) <= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + { + break; + } + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) /* Switch to insertion sort */ + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + + pn = (char *) a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) + { + qsort(a, r / es, es, cmp); + } + if ((r = pd - pc) > es) + { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} + + +/* EOF */ diff --git a/ntoskrnl/rtl/regio.c b/ntoskrnl/rtl/regio.c new file mode 100644 index 0000000..4c00429 --- /dev/null +++ b/ntoskrnl/rtl/regio.c @@ -0,0 +1,158 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/regio.c + * PURPOSE: Register io functions + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * REVISION HISTORY: + * 29/12/1999 Created + */ + +#include + + +/* FUNCTIONS ***************************************************************/ + +UCHAR +STDCALL +READ_REGISTER_UCHAR ( + PUCHAR Register + ) +{ + return *Register; +} + +USHORT +STDCALL +READ_REGISTER_USHORT ( + PUSHORT Register + ) +{ + return *Register; +} + +ULONG +STDCALL +READ_REGISTER_ULONG ( + PULONG Register + ) +{ + return *Register; +} + +VOID +STDCALL +READ_REGISTER_BUFFER_UCHAR ( + PUCHAR Register, + PUCHAR Buffer, + ULONG Count + ) +{ + while (Count--) + { + *Buffer++ = *Register++; + } +} + +VOID +STDCALL +READ_REGISTER_BUFFER_USHORT ( + PUSHORT Register, + PUSHORT Buffer, + ULONG Count + ) +{ + while (Count--) + { + *Buffer++ = *Register++; + } +} + +VOID +STDCALL +READ_REGISTER_BUFFER_ULONG ( + PULONG Register, + PULONG Buffer, + ULONG Count + ) +{ + while (Count--) + { + *Buffer++ = *Register++; + } +} + +VOID +STDCALL +WRITE_REGISTER_UCHAR ( + PUCHAR Register, + UCHAR Value + ) +{ + *Register = Value; +} + +VOID +STDCALL +WRITE_REGISTER_USHORT ( + PUSHORT Register, + USHORT Value + ) +{ + *Register = Value; +} + +VOID +STDCALL +WRITE_REGISTER_ULONG ( + PULONG Register, + ULONG Value + ) +{ + *Register = Value; +} + +VOID +STDCALL +WRITE_REGISTER_BUFFER_UCHAR ( + PUCHAR Register, + PUCHAR Buffer, + ULONG Count + ) +{ + while (Count--) + { + *Buffer++ = *Register++; + } +} + +VOID +STDCALL +WRITE_REGISTER_BUFFER_USHORT ( + PUSHORT Register, + PUSHORT Buffer, + ULONG Count + ) +{ + while (Count--) + { + *Buffer++ = *Register++; + } +} + +VOID +STDCALL +WRITE_REGISTER_BUFFER_ULONG ( + PULONG Register, + PULONG Buffer, + ULONG Count +) +{ + while (Count--) + { + *Buffer++ = *Register++; + } +} + +/* EOF */ diff --git a/ntoskrnl/rtl/sprintf.c b/ntoskrnl/rtl/sprintf.c new file mode 100644 index 0000000..259a897 --- /dev/null +++ b/ntoskrnl/rtl/sprintf.c @@ -0,0 +1,553 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/sprintf.c + * PURPOSE: Single byte sprintf functions + * PROGRAMMERS: David Welch + * Eric Kohl + * + */ + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +#include +#include +#include +#include +#include +#include + +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ +__res; }) + + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + + +static char * +number(char *buf, char *end, long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits; + const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = '0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = '0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = '0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +static char* +string(char* buf, char* end, const char* s, int len, int field_width, int precision, int flags) +{ + int i; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (s[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = *s++; + ++buf; + } + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +static char* +stringw(char* buf, char* end, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (sw[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = (unsigned char)(*sw++); + ++buf; + } + while (len < field_width--) + { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +int _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int base; + char *str, *end; + const char *s; + const wchar_t *sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */ + + str = buf; + end = buf + cnt - 1; + if (end < buf - 1) { + end = ((void *) -1); + cnt = end - buf + 1; + } + + for ( ; *fmt ; ++fmt) { + if (*fmt != '%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + { + if (str <= end) + *str = ' '; + ++str; + } + if (qualifier == 'l' || qualifier == 'w') + { + if (str <= end) + *str = (unsigned char)(wchar_t) va_arg(args, int); + ++str; + } + else + { + if (str <= end) + *str = (unsigned char) va_arg(args, int); + ++str; + } + while (--field_width > 0) + { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 'C': /* finished */ + if (!(flags & LEFT)) + while (--field_width > 0) + { + if (str <= end) + *str = ' '; + ++str; + } + if (qualifier == 'h') + { + if (str <= end) + *str = (unsigned char) va_arg(args, int); + ++str; + } + else + { + if (str <= end) + *str = (unsigned char)(wchar_t) va_arg(args, int); + ++str; + } + while (--field_width > 0) + { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 's': /* finished */ + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } + continue; + + case 'Z': + if (qualifier == 'w') { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + len = pus->Length / sizeof(WCHAR); + } + str = stringw(str, end, sw, len, field_width, precision, flags); + } else { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + s = NULL; + len = -1; + } else { + s = pus->Buffer; + len = pus->Length; + } + str = string(str, end, s, len, field_width, precision, flags); + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2 * sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), + 16, field_width, precision, flags); + continue; + + case 'n': + /* FIXME: What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + { + if (str <= end) + *str = '%'; + ++str; + } + if (*fmt) + { + if (str <= end) + *str = *fmt; + ++str; + } + else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + str = number(str, end, num, base, field_width, precision, flags); + } + + if (str <= end) + *str = '\0'; + else if (cnt > 0) + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + + return str-buf; +} + + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnprintf(buf,INT_MAX,fmt,args); + va_end(args); + return i; +} + + +int _snprintf(char * buf, size_t cnt, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnprintf(buf,cnt,fmt,args); + va_end(args); + return i; +} + + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return _vsnprintf(buf,INT_MAX,fmt,args); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/stdlib.c b/ntoskrnl/rtl/stdlib.c new file mode 100644 index 0000000..97f3644 --- /dev/null +++ b/ntoskrnl/rtl/stdlib.c @@ -0,0 +1,259 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/stdlib.c + * PURPOSE: Standard library functions + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * 1999/07/29 ekohl Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +/* GLOBALS ****************************************************************/ + +static unsigned long long next = 0; + +/* FUNCTIONS ****************************************************************/ + +int atoi(const char *str) +{ + return (int)atol (str); +} + + +/* + * NOTE: no error + */ + +long atol(const char *str) +{ + const char *s = str; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)10; + cutoff /= (unsigned long)10; + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else + break; + if (c >= 10) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= 10; + acc += c; + } + } + if (any < 0) + { + acc = neg ? LONG_MIN : LONG_MAX; + } + else if (neg) + acc = -acc; + + return acc; +} + + +/* + * NOTE: no radix range check (valid range: 2 - 36) + */ + +char *_itoa (int value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp = NULL; + + if (string == NULL) + return NULL; + + sign = (radix == 10 && value < 0); + if (sign) + v = -value; + else + v = (unsigned)value; + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + if (sign) + *sp++ = '-'; + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} + + +int rand(void) +{ + next = next * 0x5deece66dLL + 11; + return (int)((next >> 16) & RAND_MAX); +} + + +void srand(unsigned seed) +{ + next = seed; +} + + +int mbtowc (wchar_t *wchar, const char *mbchar, size_t count) +{ + NTSTATUS Status; + ULONG Size; + + if (wchar == NULL) + return 0; + + Status = RtlMultiByteToUnicodeN (wchar, + sizeof(WCHAR), + &Size, + (char *)mbchar, + count); + if (!NT_SUCCESS(Status)) + return -1; + + return (int)Size; +} + + +size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count) +{ + NTSTATUS Status; + ULONG Size; + ULONG Length; + + Length = strlen (mbstr); + + if (wcstr == NULL) + { + RtlMultiByteToUnicodeSize (&Size, + (char *)mbstr, + Length); + + return (size_t)Size; + } + + Status = RtlMultiByteToUnicodeN (wcstr, + count, + &Size, + (char *)mbstr, + Length); + if (!NT_SUCCESS(Status)) + return -1; + + return (size_t)Size; +} + + +int wctomb (char *mbchar, wchar_t wchar) +{ + NTSTATUS Status; + ULONG Size; + + if (mbchar == NULL) + return 0; + + Status = RtlUnicodeToMultiByteN (mbchar, + 1, + &Size, + &wchar, + sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + return -1; + + return (int)Size; +} + + +size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count) +{ + NTSTATUS Status; + ULONG Size; + ULONG Length; + + Length = wcslen (wcstr); + + if (mbstr == NULL) + { + RtlUnicodeToMultiByteSize (&Size, + (wchar_t *)wcstr, + Length * sizeof(WCHAR)); + + return (size_t)Size; + } + + Status = RtlUnicodeToMultiByteN (mbstr, + count, + &Size, + (wchar_t *)wcstr, + Length * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + return -1; + + return (size_t)Size; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/string.c b/ntoskrnl/rtl/string.c new file mode 100644 index 0000000..99fd4ee --- /dev/null +++ b/ntoskrnl/rtl/string.c @@ -0,0 +1,308 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/string.c + * PURPOSE: Ascii string functions + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * 1999/07/29 ekohl Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +int _stricmp(const char *s1, const char *s2) +{ + while (toupper(*s1) == toupper(*s2)) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)(s2)); +} + + +char * _strlwr(char *x) +{ + char *y=x; + + while (*y) + { + *y=tolower(*y); + y++; + } + return x; +} + + +int _strnicmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + return 0; + do + { + if (toupper(*s1) != toupper(*s2++)) + return toupper(*(unsigned const char *)s1) - toupper(*(unsigned const char *)--s2); + if (*s1++ == 0) + break; + } + while (--n != 0); + return 0; +} + +char* _strnset(char* szToFill, int szFill, size_t sizeMaxFill) +{ + char *t = szToFill; + int i = 0; + while (*szToFill != 0 && i < sizeMaxFill) + { + *szToFill = szFill; + szToFill++; + i++; + + } + return t; +} + + +char * _strrev(char *s) +{ + char *e; + char a; + + e = s; + while (*e) + e++; + + while (s + +#include + + +/* FUNCTIONS *****************************************************************/ + +char* strtok(char *s, const char *delim) +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ + cont: + c = *s++; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +PWSTR RtlStrtok(PUNICODE_STRING _string, PWSTR _sep, + PWSTR* temp) +/* + * FUNCTION: Splits a string into tokens + * ARGUMENTS: + * string = string to operate on + * if NULL then continue with previous string + * sep = Token deliminators + * temp = Tempory storage provided by the caller + * ARGUMENTS: Returns the beginning of the next token + */ +{ + PWSTR string; + PWSTR sep; + PWSTR start; + + if (_string!=NULL) + { + string = _string->Buffer; + } + else + { + string = *temp; + } + + start = string; + + while ((*string)!=0) + { + sep = _sep; + while ((*sep)!=0) + { + if ((*string)==(*sep)) + { + *string=0; + *temp=string+1; + return(start); + } + sep++; + } + string++; + } + *temp=NULL; + return(start); +} diff --git a/ntoskrnl/rtl/swprintf.c b/ntoskrnl/rtl/swprintf.c new file mode 100644 index 0000000..add79d7 --- /dev/null +++ b/ntoskrnl/rtl/swprintf.c @@ -0,0 +1,541 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/swprintf.c + * PURPOSE: unicode sprintf functions + * PROGRAMMERS: David Welch + * Eric Kohl + * + * TODO: + * - Verify the implementation of '%Z'. + */ + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ +__res; }) + + +static int skip_atoi(const wchar_t **s) +{ + int i=0; + + while (iswdigit(**s)) + i = i*10 + *((*s)++) - L'0'; + return i; +} + + +static wchar_t * +number(wchar_t * buf, wchar_t * end, long long num, int base, int size, int precision, int type) +{ + wchar_t c,sign, tmp[66]; + const wchar_t *digits; + const wchar_t small_digits[] = L"0123456789abcdefghijklmnopqrstuvwxyz"; + const wchar_t large_digits[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++] = L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = L' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = L'0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = L'0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = L'0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = L' '; + ++buf; + } + return buf; +} + +static wchar_t* +string(wchar_t* buf, wchar_t* end, const char* s, int len, int field_width, int precision, int flags) +{ + int i; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (s[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + ++buf; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = *s++; + ++buf; + } + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + ++buf; + } + return buf; +} + +static wchar_t* +stringw(wchar_t* buf, wchar_t* end, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while (sw[len] && (unsigned int)len < (unsigned int)precision) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + buf++; + } + for (i = 0; i < len; ++i) + { + if (buf <= end) + *buf = *sw++; + buf++; + } + while (len < field_width--) + { + if (buf <= end) + *buf = L' '; + buf++; + } + return buf; +} + +int _vsnwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, va_list args) +{ + int len; + unsigned long long num; + int base; + wchar_t * str, * end; + const char *s; + const wchar_t *sw; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */ + + str = buf; + end = buf + cnt - 1; + if (end < buf - 1) { + end = ((void *) -1); + cnt = end - buf + 1; + } + + for ( ; *fmt ; ++fmt) { + if (*fmt != L'%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case L'-': flags |= LEFT; goto repeat; + case L'+': flags |= PLUS; goto repeat; + case L' ': flags |= SPACE; goto repeat; + case L'#': flags |= SPECIAL; goto repeat; + case L'0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (iswdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == L'.') { + ++fmt; + if (iswdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case L'c': + if (!(flags & LEFT)) + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + if (qualifier == 'h') { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } else { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + continue; + + case L'C': + if (!(flags & LEFT)) + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + if (qualifier == 'l' || qualifier == 'w') { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } else { + if (str <= end) + *str = (wchar_t) va_arg(args, int); + ++str; + } + while (--field_width > 0) { + if (str <= end) + *str = L' '; + ++str; + } + continue; + + case L's': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } + continue; + + case L'S': + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + str = stringw(str, end, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + str = string(str, end, s, -1, field_width, precision, flags); + } + continue; + + case L'Z': + if (qualifier == 'h') { + /* print counted ascii string */ + PANSI_STRING pus = va_arg(args, PANSI_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + s = NULL; + len = -1; + } else { + s = pus->Buffer; + len = pus->Length; + } + str = string(str, end, s, len, field_width, precision, flags); + } else { + /* print counted unicode string */ + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + len = pus->Length / sizeof(WCHAR); + } + str = stringw(str, end, sw, len, field_width, precision, flags); + } + continue; + + case L'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + case L'n': + /* FIXME: What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + /* integer number formats - set up the flags and "break" */ + case L'o': + base = 8; + break; + + case L'b': + base = 2; + break; + + case L'X': + flags |= LARGE; + case L'x': + base = 16; + break; + + case L'd': + case L'i': + flags |= SIGN; + case L'u': + break; + + default: + if (*fmt != L'%') { + if (str <= end) + *str = L'%'; + ++str; + } + if (*fmt) { + if (str <= end) + *str = *fmt; + ++str; + } else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, unsigned long long); + else if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + str = number(str, end, num, base, field_width, precision, flags); + } + if (str <= end) + *str = L'\0'; + else if (cnt > 0) + /* don't write out a null byte if the buf size is zero */ + *end = L'\0'; + return str-buf; +} + + +int swprintf(wchar_t *buf, const wchar_t *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnwprintf(buf,INT_MAX,fmt,args); + va_end(args); + return i; +} + + +int _snwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=_vsnwprintf(buf,cnt,fmt,args); + va_end(args); + return i; +} + + +int vswprintf(wchar_t *buf, const wchar_t *fmt, va_list args) +{ + return _vsnwprintf(buf,INT_MAX,fmt,args); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/time.c b/ntoskrnl/rtl/time.c new file mode 100644 index 0000000..333c442 --- /dev/null +++ b/ntoskrnl/rtl/time.c @@ -0,0 +1,267 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: kernel/rtl/time.c + * PURPOSE: Conversion between Time and TimeFields + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + * UPDATE HISTORY: + * Created 22/05/98 + * 08/03/98 RJJ Implemented these functions + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +#define TICKSPERMIN 600000000 +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 +#define SECSPERHOUR 3600 +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define EPOCHWEEKDAY 1 +#define DAYSPERWEEK 7 +#define EPOCHYEAR 1601 +#define DAYSPERNORMALYEAR 365 +#define DAYSPERLEAPYEAR 366 +#define MONSPERYEAR 12 + +#define TICKSTO1970 0x019db1ded53e8000 +#define TICKSTO1980 0x01a8e79fe1d58000 + + +static const int YearLengths[2] = {DAYSPERNORMALYEAR, DAYSPERLEAPYEAR}; +static const int MonthLengths[2][MONSPERYEAR] = +{ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static __inline int IsLeapYear(int Year) +{ + return Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) ? 1 : 0; +} + +static __inline void NormalizeTimeFields(CSHORT *FieldToNormalize, + CSHORT *CarryField, + int Modulus) +{ + *FieldToNormalize = (CSHORT) (*FieldToNormalize - Modulus); + *CarryField = (CSHORT) (*CarryField + 1); +} + +/* FUNCTIONS *****************************************************************/ + +VOID +STDCALL +RtlTimeToTimeFields ( + PLARGE_INTEGER liTime, + PTIME_FIELDS TimeFields + ) +{ + const int *Months; + int LeapSecondCorrections, SecondsInDay, CurYear; + int LeapYear, CurMonth, GMTOffset; + long int Days; + long long int Time = (long long int)liTime->QuadPart; + + /* Extract millisecond from time and convert time into seconds */ + TimeFields->Milliseconds = (CSHORT) ((Time % TICKSPERSEC) / TICKSPERMSEC); + Time = Time / TICKSPERSEC; + + /* FIXME: Compute the number of leap second corrections here */ + LeapSecondCorrections = 0; + + /* FIXME: get the GMT offset here */ + GMTOffset = 0; + + /* Split the time into days and seconds within the day */ + Days = Time / SECSPERDAY; + SecondsInDay = Time % SECSPERDAY; + + /* Adjust the values for GMT and leap seconds */ + SecondsInDay += (GMTOffset - LeapSecondCorrections); + while (SecondsInDay < 0) + { + SecondsInDay += SECSPERDAY; + Days--; + } + while (SecondsInDay >= SECSPERDAY) + { + SecondsInDay -= SECSPERDAY; + Days++; + } + + /* compute time of day */ + TimeFields->Hour = (CSHORT) (SecondsInDay / SECSPERHOUR); + SecondsInDay = SecondsInDay % SECSPERHOUR; + TimeFields->Minute = (CSHORT) (SecondsInDay / SECSPERMIN); + TimeFields->Second = (CSHORT) (SecondsInDay % SECSPERMIN); + + /* FIXME: handle the possibility that we are on a leap second (i.e. Second = 60) */ + + /* compute day of week */ + TimeFields->Weekday = (CSHORT) ((EPOCHWEEKDAY + Days) % DAYSPERWEEK); + + /* compute year */ + CurYear = EPOCHYEAR; + /* FIXME: handle calendar modifications */ + CurYear += Days / DAYSPERLEAPYEAR; + Days -= (CurYear - EPOCHYEAR) * DAYSPERLEAPYEAR; + CurYear--; /* The next calculation needs CurYear - 1 */ + Days += CurYear - CurYear / 4 + CurYear / 100 - CurYear / 400; + CurYear++; + Days -= EPOCHYEAR - 1 - (EPOCHYEAR -1) / 4 + (EPOCHYEAR -1) / 100 - (EPOCHYEAR - 1) / 400; + while (1) + { + LeapYear = IsLeapYear(CurYear); + if (Days < (long) YearLengths[LeapYear]) + { + break; + } + CurYear++; + Days = Days - (long) YearLengths[LeapYear]; + } + TimeFields->Year = (CSHORT) CurYear; + + /* Compute month of year */ + LeapYear = IsLeapYear(CurYear); + Months = MonthLengths[LeapYear]; + for (CurMonth = 0; Days >= (long) Months[CurMonth]; CurMonth++) + Days = Days - (long) Months[CurMonth]; + TimeFields->Month = (CSHORT) (CurMonth + 1); + TimeFields->Day = (CSHORT) (Days + 1); +} + +BOOLEAN +STDCALL +RtlTimeFieldsToTime ( + PTIME_FIELDS tfTimeFields, + PLARGE_INTEGER Time + ) +{ + int CurMonth; + long long int rcTime; + TIME_FIELDS TimeFields = *tfTimeFields; + const int *Months; + + rcTime = 0; + + /* Normalize the month value, because we don't know the length for month -1, 0, 13, 14, ... */ + if (TimeFields.Month < 1 || TimeFields.Month > 12) + { + TimeFields.Year += (TimeFields.Month - 1) / MONSPERYEAR; + TimeFields.Month = ((TimeFields.Month - 1) % MONSPERYEAR) + 1; + if (TimeFields.Month < 1) + { + TimeFields.Year--; + TimeFields.Month += MONSPERYEAR; + } + } + /* FIXME: handle calendar corrections here */ + + rcTime += (TimeFields.Year - EPOCHYEAR) * DAYSPERNORMALYEAR; + /* Adjust leap years */ + rcTime += (TimeFields.Year - 1)/ 4 - (TimeFields.Year - 1) / 100 + (TimeFields.Year - 1) / 400; + rcTime -= EPOCHYEAR / 4 - EPOCHYEAR / 100 + EPOCHYEAR / 400; + + /* FIXME: handle calendar corrections here */ + Months = MonthLengths[IsLeapYear(TimeFields.Year)]; + for (CurMonth = 1; CurMonth < TimeFields.Month; CurMonth++) + { + rcTime += Months[CurMonth - 1]; + } + rcTime += TimeFields.Day - 1; + rcTime *= SECSPERDAY; + rcTime += TimeFields.Hour * SECSPERHOUR + TimeFields.Minute * SECSPERMIN + + TimeFields.Second; + rcTime *= TICKSPERSEC; + rcTime += TimeFields.Milliseconds * TICKSPERMSEC; + + /* FIXME: handle UTC bias here */ +// rcTime += UTCBias * TICKSPERMIN; + + *Time = *(LARGE_INTEGER *)&rcTime; + + return TRUE; +} + + +VOID +STDCALL +RtlSecondsSince1970ToTime ( + ULONG SecondsSince1970, + PLARGE_INTEGER Time + ) +{ + LONGLONG llTime; + + llTime = (SecondsSince1970 * TICKSPERSEC) + TICKSTO1970; + + *Time = *(LARGE_INTEGER *)&llTime; +} + + +VOID +STDCALL +RtlSecondsSince1980ToTime ( + ULONG SecondsSince1980, + PLARGE_INTEGER Time + ) +{ + LONGLONG llTime; + + llTime = (SecondsSince1980 * TICKSPERSEC) + TICKSTO1980; + + *Time = *(LARGE_INTEGER *)&llTime; +} + + +BOOLEAN +STDCALL +RtlTimeToSecondsSince1970 ( + PLARGE_INTEGER Time, + PULONG SecondsSince1970 + ) +{ + LARGE_INTEGER liTime; + + liTime.QuadPart = Time->QuadPart - TICKSTO1970; + liTime.QuadPart = liTime.QuadPart / TICKSPERSEC; + + if (liTime.u.HighPart != 0) + return FALSE; + + *SecondsSince1970 = liTime.u.LowPart; + + return TRUE; +} + + +BOOLEAN +STDCALL +RtlTimeToSecondsSince1980 ( + PLARGE_INTEGER Time, + PULONG SecondsSince1980 + ) +{ + LARGE_INTEGER liTime; + + liTime.QuadPart = Time->QuadPart - TICKSTO1980; + liTime.QuadPart = liTime.QuadPart / TICKSPERSEC; + + if (liTime.u.HighPart != 0) + return FALSE; + + *SecondsSince1980 = liTime.u.LowPart; + + return TRUE; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/timezone.c b/ntoskrnl/rtl/timezone.c new file mode 100644 index 0000000..6f88e94 --- /dev/null +++ b/ntoskrnl/rtl/timezone.c @@ -0,0 +1,200 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Timezone functions + * FILE: ntoskrnl/rtl/timezone.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 29/05/2001: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL +RtlQueryTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) +{ + HANDLE KeyHandle; + RTL_QUERY_REGISTRY_TABLE QueryTable[8]; + UNICODE_STRING StandardName; + UNICODE_STRING DaylightName; + NTSTATUS Status; + + DPRINT("RtlQueryTimeZoneInformation()\n"); + + Status = RtlpGetRegistryHandle(RTL_REGISTRY_CONTROL, + L"TimeZoneInformation", + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle failed (Status %x)\n", Status); + return Status; + } + + RtlZeroMemory(QueryTable, + sizeof(QueryTable)); + + StandardName.Length = 0; + StandardName.MaximumLength = 32 * sizeof(WCHAR); + StandardName.Buffer = TimeZoneInformation->StandardName; + + DaylightName.Length = 0; + DaylightName.MaximumLength = 32 * sizeof(WCHAR); + DaylightName.Buffer = TimeZoneInformation->DaylightName; + + QueryTable[0].Name = L"Bias"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[0].EntryContext = &TimeZoneInformation->Bias; + + QueryTable[1].Name = L"Standard Name"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[1].EntryContext = &StandardName; + + QueryTable[2].Name = L"Standard Bias"; + QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[2].EntryContext = &TimeZoneInformation->StandardBias; + + QueryTable[3].Name = L"Standard Start"; + QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[3].EntryContext = &TimeZoneInformation->StandardDate; + + QueryTable[4].Name = L"Daylight Name"; + QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[4].EntryContext = &DaylightName; + + QueryTable[5].Name = L"Daylight Bias"; + QueryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[5].EntryContext = &TimeZoneInformation->DaylightBias; + + QueryTable[6].Name = L"Daylight Start"; + QueryTable[6].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[6].EntryContext = &TimeZoneInformation->DaylightDate; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + QueryTable, + NULL, + NULL); + NtClose(KeyHandle); + + return Status; +} + + +NTSTATUS STDCALL +RtlSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation) +{ + HANDLE KeyHandle; + ULONG Length; + NTSTATUS Status; + + DPRINT("RtlSetTimeZoneInformation()\n"); + + Status = RtlpGetRegistryHandle(RTL_REGISTRY_CONTROL, + L"TimeZoneInformation", + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlpGetRegistryHandle failed (Status %x)\n", Status); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Bias", + REG_DWORD, + &TimeZoneInformation->Bias, + sizeof(LONG)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Length = (wcslen(TimeZoneInformation->StandardName) + 1) * sizeof(WCHAR); + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Standard Name", + REG_SZ, + TimeZoneInformation->StandardName, + Length); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Standard Bias", + REG_DWORD, + &TimeZoneInformation->StandardBias, + sizeof(LONG)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Standard Start", + REG_BINARY, + &TimeZoneInformation->StandardDate, + sizeof(SYSTEMTIME)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Length = (wcslen(TimeZoneInformation->DaylightName) + 1) * sizeof(WCHAR); + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Daylight Name", + REG_SZ, + TimeZoneInformation->DaylightName, + Length); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Daylight Bias", + REG_DWORD, + &TimeZoneInformation->DaylightBias, + sizeof(LONG)); + if (!NT_SUCCESS(Status)) + { + NtClose(KeyHandle); + return Status; + } + + Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + (PWSTR)KeyHandle, + L"Daylight Start", + REG_BINARY, + &TimeZoneInformation->DaylightDate, + sizeof(SYSTEMTIME)); + + NtClose(KeyHandle); + + return Status; +} + +/* EOF */ diff --git a/ntoskrnl/rtl/unicode.c b/ntoskrnl/rtl/unicode.c new file mode 100644 index 0000000..705e7cc --- /dev/null +++ b/ntoskrnl/rtl/unicode.c @@ -0,0 +1,1569 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/unicode.c + * PURPOSE: String functions + * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) + * UPDATE HISTORY: + * Created 10/08/98 + */ + +#include +//#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_USTR TAG('U', 'S', 'T', 'R') +#define TAG_ASTR TAG('A', 'S', 'T', 'R') +#define TAG_OSTR TAG('O', 'S', 'T', 'R') + +/* FUNCTIONS *****************************************************************/ + +WCHAR STDCALL +RtlAnsiCharToUnicodeChar(IN CHAR AnsiChar) +{ + ULONG Size; + WCHAR UnicodeChar; + + Size = 1; +#if 0 + Size = (NlsLeadByteInfo[AnsiChar] == 0) ? 1 : 2; +#endif + + RtlMultiByteToUnicodeN(&UnicodeChar, + sizeof(WCHAR), + NULL, + &AnsiChar, + Size); + + return(UnicodeChar); +} + + +ULONG STDCALL +RtlAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString) +{ + ULONG Size; + + RtlMultiByteToUnicodeSize(&Size, + AnsiString->Buffer, + AnsiString->Length); + + return(Size); +} + + +NTSTATUS STDCALL +RtlAnsiStringToUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PANSI_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE) + Length = RtlAnsiStringToUnicodeSize (SourceString); + else + Length = SourceString->Length * sizeof(WCHAR); + + if (Length > 65535) + return STATUS_INVALID_PARAMETER_2; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(WCHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag (NonPagedPool, + DestinationString->MaximumLength, + TAG_USTR); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length + sizeof(WCHAR) > DestinationString->MaximumLength) + { + DPRINT("STATUS_BUFFER_TOO_SMALL\n"); + return STATUS_BUFFER_TOO_SMALL; + } + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlMultiByteToUnicodeN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool (DestinationString->Buffer); + return Status; + } + + DestinationString->Buffer[Length / sizeof(WCHAR)] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlAppendAsciizToString(IN OUT PSTRING Destination, + IN PCSZ Source) +{ + ULONG Length; + PCHAR Ptr; + + if (Source == NULL) + return STATUS_SUCCESS; + + Length = strlen (Source); + if (Destination->Length + Length >= Destination->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + + Ptr = Destination->Buffer + Destination->Length; + memmove (Ptr, + Source, + Length); + Ptr += Length; + *Ptr = 0; + + Destination->Length += Length; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlAppendStringToString(IN OUT PSTRING Destination, + IN PSTRING Source) +{ + PCHAR Ptr; + + if (Source->Length == 0) + return(STATUS_SUCCESS); + + if (Destination->Length + Source->Length >= Destination->MaximumLength) + return(STATUS_BUFFER_TOO_SMALL); + + Ptr = Destination->Buffer + Destination->Length; + memmove(Ptr, + Source->Buffer, + Source->Length); + Ptr += Source->Length; + *Ptr = 0; + + Destination->Length += Source->Length; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlAppendUnicodeStringToString(IN OUT PUNICODE_STRING Destination, + IN PUNICODE_STRING Source) +{ + PWCHAR Src, Dest; + ULONG i; + + if ((Source->Length + Destination->Length) >= Destination->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + + Src = Source->Buffer; + Dest = Destination->Buffer + (Destination->Length / sizeof (WCHAR)); + for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + Destination->Length += Source->Length; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlAppendUnicodeToString(IN OUT PUNICODE_STRING Destination, + IN PWSTR Source) +{ + PWCHAR Src; + PWCHAR Dest; + ULONG i; + ULONG slen; + + slen = wcslen(Source) * sizeof(WCHAR); + + if (Destination->Length + slen >= Destination->MaximumLength) + return(STATUS_BUFFER_TOO_SMALL); + + Src = Source; + Dest = Destination->Buffer + (Destination->Length / sizeof(WCHAR)); + + for (i = 0; i < (slen / sizeof(WCHAR)); i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + Destination->Length += slen; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCharToInteger(IN PCSZ String, + IN ULONG Base, + IN OUT PULONG Value) +{ + ULONG Val; + + *Value = 0; + + if (Base == 0) + { + Base = 10; + if (*String == '0') + { + Base = 8; + String++; + if ((*String == 'x') && isxdigit (String[1])) + { + String++; + Base = 16; + } + } + } + + if (!isxdigit (*String)) + return(STATUS_INVALID_PARAMETER); + + while (isxdigit (*String) && + (Val = isdigit (*String) ? * String - '0' : (islower (*String) + ? toupper (*String) : *String) - 'A' + 10) < Base) + { + *Value = *Value * Base + Val; + String++; + } + + return(STATUS_SUCCESS); +} + + +LONG STDCALL +RtlCompareString(IN PSTRING String1, + IN PSTRING String2, + IN BOOLEAN CaseInsensitive) +{ + ULONG len1, len2; + PCHAR s1, s2; + CHAR c1, c2; + + if (String1 && String2) + { + len1 = String1->Length; + len2 = String2->Length; + s1 = String1->Buffer; + s2 = String2->Buffer; + + if (s1 && s2) + { + if (CaseInsensitive) + { + while (1) + { + c1 = len1-- ? RtlUpperChar (*s1++) : 0; + c2 = len2-- ? RtlUpperChar (*s2++) : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + else + { + while (1) + { + c1 = len1-- ? *s1++ : 0; + c2 = len2-- ? *s2++ : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + } + } + + return 0; +} + + +LONG STDCALL +RtlCompareUnicodeString(IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2, + IN BOOLEAN CaseInsensitive) +{ + ULONG len1, len2; + PWCHAR s1, s2; + WCHAR c1, c2; + + if (String1 && String2) + { + len1 = String1->Length / sizeof(WCHAR); + len2 = String2->Length / sizeof(WCHAR); + s1 = String1->Buffer; + s2 = String2->Buffer; + + if (s1 && s2) + { + if (CaseInsensitive) + { + while (1) + { + c1 = len1-- ? RtlUpcaseUnicodeChar (*s1++) : 0; + c2 = len2-- ? RtlUpcaseUnicodeChar (*s2++) : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + else + { + while (1) + { + c1 = len1-- ? *s1++ : 0; + c2 = len2-- ? *s2++ : 0; + if (!c1 || !c2 || c1 != c2) + return c1 - c2; + } + } + } + } + + return 0; +} + + +VOID STDCALL +RtlCopyString(IN OUT PSTRING DestinationString, + IN PSTRING SourceString) +{ + ULONG copylen, i; + PCHAR Src, Dest; + + if(SourceString == NULL) + { + DestinationString->Length = 0; + return; + } + + copylen = min (DestinationString->MaximumLength - sizeof(CHAR), + SourceString->Length); + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + + for (i = 0; i < copylen; i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + DestinationString->Length = copylen; +} + + +VOID STDCALL +RtlCopyUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString) +{ + ULONG copylen, i; + PWCHAR Src, Dest; + + if(SourceString==NULL) + { + DestinationString->Length=0; + return; + } + + copylen = min(DestinationString->MaximumLength - sizeof(WCHAR), + SourceString->Length); + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + + for (i = 0; i < (copylen / sizeof (WCHAR)); i++) + { + *Dest = *Src; + Dest++; + Src++; + } + *Dest = 0; + + DestinationString->Length = copylen; +} + + +BOOLEAN STDCALL +RtlCreateUnicodeString(IN OUT PUNICODE_STRING Destination, + IN PWSTR Source) +{ + ULONG Length; + + Length = (wcslen (Source) + 1) * sizeof(WCHAR); + + Destination->Buffer = ExAllocatePoolWithTag (NonPagedPool, + Length, + TAG_USTR); + if (Destination->Buffer == NULL) + return FALSE; + + memmove (Destination->Buffer, + Source, + Length); + + Destination->MaximumLength = Length; + Destination->Length = Length - sizeof (WCHAR); + + return TRUE; +} + + +BOOLEAN STDCALL +RtlCreateUnicodeStringFromAsciiz(IN OUT PUNICODE_STRING Destination, + IN PCSZ Source) +{ + ANSI_STRING AnsiString; + NTSTATUS Status; + + RtlInitAnsiString(&AnsiString, + Source); + + Status = RtlAnsiStringToUnicodeString(Destination, + &AnsiString, + TRUE); + + return(NT_SUCCESS(Status)); +} + + +NTSTATUS STDCALL +RtlDowncaseUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + ULONG i; + PWCHAR Src, Dest; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag (NonPagedPool, + SourceString->Length + sizeof(WCHAR), + TAG_USTR); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (SourceString->Length >= DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = SourceString->Length; + + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + for (i=0; i < SourceString->Length / sizeof(WCHAR); i++) + { + if (*Src < L'A') + { + *Dest = *Src; + } + else if (*Src <= L'Z') + { + *Dest = (*Src + (L'a' - L'A')); + } + else + { + /* FIXME: characters above 'Z' */ + *Dest = *Src; + } + + Dest++; + Src++; + } + *Dest = 0; + + return STATUS_SUCCESS; +} + + +BOOLEAN STDCALL +RtlEqualString(IN PSTRING String1, + IN PSTRING String2, + IN BOOLEAN CaseInsensitive) +{ + unsigned long s1l=String1->Length; + unsigned long s2l=String2->Length; + unsigned long i; + char c1, c2; + + if (s1l != s2l) + return FALSE; + + for (i = 0; i < s1l; i++) + { + c1 = *String1->Buffer; + c2 = *String2->Buffer; + + if (CaseInsensitive == TRUE) + { + c1 = RtlUpperChar (c1); + c2 = RtlUpperChar (c2); + } + + if (c1 != c2) + { + String1->Buffer -= i; + String2->Buffer -= i; + return FALSE; + } + + String1->Buffer++; + String2->Buffer++; + } + + String1->Buffer -= i; + String2->Buffer -= i; + + return TRUE; +} + + +BOOLEAN STDCALL +RtlEqualUnicodeString(IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2, + IN BOOLEAN CaseInsensitive) +{ + unsigned long s1l = String1->Length / sizeof(WCHAR); + unsigned long s2l = String2->Length / sizeof(WCHAR); + unsigned long i; + WCHAR wc1, wc2; + PWCHAR pw1, pw2; + + if (s1l != s2l) + return FALSE; + + pw1 = String1->Buffer; + pw2 = String2->Buffer; + + for (i = 0; i < s1l; i++) + { + if(CaseInsensitive == TRUE) + { + wc1 = RtlUpcaseUnicodeChar (*pw1); + wc2 = RtlUpcaseUnicodeChar (*pw2); + } + else + { + wc1 = *pw1; + wc2 = *pw2; + } + + if (wc1 != wc2) + return FALSE; + + pw1++; + pw2++; + } + + return TRUE; +} + + +VOID STDCALL +RtlFreeAnsiString(IN PANSI_STRING AnsiString) +{ + if (AnsiString->Buffer == NULL) + return; + + ExFreePool (AnsiString->Buffer); + + AnsiString->Buffer = NULL; + AnsiString->Length = 0; + AnsiString->MaximumLength = 0; +} + + +VOID STDCALL +RtlFreeOemString(IN POEM_STRING OemString) +{ + if (OemString->Buffer == NULL) + return; + + ExFreePool (OemString->Buffer); + + OemString->Buffer = NULL; + OemString->Length = 0; + OemString->MaximumLength = 0; +} + + +VOID STDCALL +RtlFreeUnicodeString(IN PUNICODE_STRING UnicodeString) +{ + if (UnicodeString->Buffer == NULL) + return; + + ExFreePool (UnicodeString->Buffer); + + UnicodeString->Buffer = NULL; + UnicodeString->Length = 0; + UnicodeString->MaximumLength = 0; +} + + +VOID STDCALL +RtlInitAnsiString(IN OUT PANSI_STRING DestinationString, + IN PCSZ SourceString) +{ + ULONG DestSize; + + if (SourceString == NULL) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + DestSize = strlen ((const char *)SourceString); + DestinationString->Length = DestSize; + DestinationString->MaximumLength = DestSize + sizeof(CHAR); + } + DestinationString->Buffer = (PCHAR)SourceString; +} + + +VOID STDCALL +RtlInitString(IN OUT PSTRING DestinationString, + IN PCSZ SourceString) +{ + ULONG DestSize; + + if (SourceString == NULL) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + DestSize = strlen((const char *)SourceString); + DestinationString->Length = DestSize; + DestinationString->MaximumLength = DestSize + sizeof(CHAR); + } + DestinationString->Buffer = (PCHAR)SourceString; +} + + +VOID STDCALL +RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PCWSTR SourceString) +{ + ULONG DestSize; + + DPRINT("RtlInitUnicodeString(DestinationString %x, SourceString %x)\n", + DestinationString, + SourceString); + + if (SourceString == NULL) + { + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + } + else + { + DestSize = wcslen((PWSTR)SourceString) * sizeof(WCHAR); + DestinationString->Length = DestSize; + DestinationString->MaximumLength = DestSize + sizeof(WCHAR); + } + DestinationString->Buffer = (PWSTR)SourceString; +} + + +NTSTATUS STDCALL +RtlIntegerToChar(IN ULONG Value, + IN ULONG Base, + IN ULONG Length, + IN OUT PCHAR String) +{ + ULONG Radix; + CHAR temp[33]; + ULONG v = 0; + ULONG i; + PCHAR tp; + PCHAR sp; + + Radix = Base; + if (Radix == 0) + Radix = 10; + + if ((Radix != 2) && (Radix != 8) && + (Radix != 10) && (Radix != 16)) + return STATUS_INVALID_PARAMETER; + + tp = temp; + while (v || tp == temp) + { + i = v % Radix; + v = v / Radix; + if (i < 10) + *tp = i + '0'; + else + *tp = i + 'a' - 10; + tp++; + } + + if (tp - temp >= Length) + return STATUS_BUFFER_TOO_SMALL; + + sp = String; + while (tp > temp) + *sp++ = *--tp; + *sp = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlIntegerToUnicodeString(IN ULONG Value, + IN ULONG Base, /* optional */ + IN OUT PUNICODE_STRING String) +{ + ANSI_STRING AnsiString; + CHAR Buffer[33]; + NTSTATUS Status; + + Status = RtlIntegerToChar (Value, + Base, + 33, + Buffer); + if (!NT_SUCCESS(Status)) + return Status; + + AnsiString.Buffer = Buffer; + AnsiString.Length = strlen (Buffer); + AnsiString.MaximumLength = 33; + + Status = RtlAnsiStringToUnicodeString (String, + &AnsiString, + FALSE); + + return Status; +} + + +NTSTATUS STDCALL +RtlOemStringToCountedUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN POEM_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE) + Length = RtlAnsiStringToUnicodeSize (SourceString); + else + Length = SourceString->Length * sizeof(WCHAR); + + if (Length > 65535) + return STATUS_INVALID_PARAMETER_2; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(WCHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag (NonPagedPool, + DestinationString->MaximumLength, + TAG_USTR); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length > DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlOemToUnicodeN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool (DestinationString->Buffer); + + return Status; + } + + DestinationString->Buffer[Length / sizeof(WCHAR)] = 0; + + return STATUS_SUCCESS; +} + + +ULONG STDCALL +RtlOemStringToUnicodeSize(IN POEM_STRING OemString) +{ + ULONG Size; + + RtlMultiByteToUnicodeSize(&Size, + OemString->Buffer, + OemString->Length); + + return(Size); +} + + +NTSTATUS STDCALL +RtlOemStringToUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN POEM_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE) + Length = RtlAnsiStringToUnicodeSize (SourceString); + else + Length = SourceString->Length * sizeof(WCHAR); + + if (Length > 65535) + return STATUS_INVALID_PARAMETER_2; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(WCHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag (NonPagedPool, + DestinationString->MaximumLength, + TAG_USTR); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length + sizeof(WCHAR) > DestinationString->MaximumLength) + { + DPRINT("STATUS_BUFFER_TOO_SMALL\n"); + return STATUS_BUFFER_TOO_SMALL; + } + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlOemToUnicodeN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool (DestinationString->Buffer); + return Status; + } + + DestinationString->Buffer[Length / sizeof(WCHAR)] = 0; + + return STATUS_SUCCESS; +} + + +BOOLEAN STDCALL +RtlPrefixString(IN PANSI_STRING String1, + IN PANSI_STRING String2, + IN BOOLEAN CaseInsensitive) +{ + PCHAR pc1; + PCHAR pc2; + ULONG Length; + + if (String2->Length < String1->Length) + return FALSE; + + Length = String1->Length; + pc1 = String1->Buffer; + pc2 = String2->Buffer; + + if (pc1 && pc2) + { + if (CaseInsensitive) + { + while (Length--) + { + if (RtlUpperChar (*pc1++) != RtlUpperChar (*pc2++)) + return FALSE; + } + } + else + { + while (Length--) + { + if (*pc1++ != *pc2++) + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + + +BOOLEAN STDCALL +RtlPrefixUnicodeString(IN PUNICODE_STRING String1, + IN PUNICODE_STRING String2, + IN BOOLEAN CaseInsensitive) +{ + PWCHAR pc1; + PWCHAR pc2; + ULONG Length; + + if (String2->Length < String1->Length) + return FALSE; + + Length = String1->Length / 2; + pc1 = String1->Buffer; + pc2 = String2->Buffer; + + if (pc1 && pc2) + { + if (CaseInsensitive) + { + while (Length--) + { + if (RtlUpcaseUnicodeChar (*pc1++) + != RtlUpcaseUnicodeChar (*pc2++)) + return FALSE; + } + } + else + { + while (Length--) + { + if( *pc1++ != *pc2++ ) + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + + +ULONG STDCALL +RtlUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString) +{ + ULONG Size; + + RtlUnicodeToMultiByteSize(&Size, + UnicodeString->Buffer, + UnicodeString->Length); + + return(Size+1); +} + + +NTSTATUS STDCALL +RtlUnicodeStringToAnsiString(IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE){ + Length = RtlUnicodeStringToAnsiSize (SourceString); Length--; + } + else + Length = SourceString->Length / sizeof(WCHAR); + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(CHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag (NonPagedPool, + DestinationString->MaximumLength, + TAG_ASTR); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length >= DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = Length; + + RtlZeroMemory (DestinationString->Buffer, + DestinationString->Length); + + Status = RtlUnicodeToMultiByteN (DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool (DestinationString->Buffer); + return Status; + } + + DestinationString->Buffer[Length] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlUnicodeStringToCountedOemString(IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbOemCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return STATUS_INVALID_PARAMETER_2; + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString) + { + DestinationString->Buffer = ExAllocatePoolWithTag (NonPagedPool, + Length, + TAG_ASTR); + + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + + RtlZeroMemory (DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (DestinationString->MaximumLength == 0) + return STATUS_BUFFER_OVERFLOW; + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUnicodeToOemN (DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool (DestinationString->Buffer); + + return Status; + } + + DestinationString->Buffer[Size] = 0; + + return STATUS_SUCCESS; +} + + +NTSTATUS STDCALL +RtlUnicodeStringToInteger(IN PUNICODE_STRING String, + IN ULONG Base, + OUT PULONG Value) +{ + PWCHAR Str; + ULONG lenmin = 0; + ULONG i; + ULONG Val; + BOOLEAN addneg = FALSE; + + *Value = 0; + Str = String->Buffer; + + for (i = 0; i < String->Length / sizeof(WCHAR); i++) + { + if (*Str == L'b') + { + Base = 2; + lenmin++; + } + else if (*Str == L'o') + { + Base = 8; + lenmin++; + } + else if (*Str == L'd') + { + Base = 10; + lenmin++; + } + else if (*Str == L'x') + { + Base = 16; + lenmin++; + } + else if (*Str == L'+') + { + lenmin++; + } + else if (*Str == L'-') + { + addneg = TRUE; + lenmin++; + } + else if ((*Str > L'1') && (Base == 2)) + { + return STATUS_INVALID_PARAMETER; + } + else if (((*Str > L'7') || (*Str < L'0')) && (Base == 8)) + { + return STATUS_INVALID_PARAMETER; + } + else if (((*Str > L'9') || (*Str < L'0')) && (Base == 10)) + { + return STATUS_INVALID_PARAMETER; + } + else if ((((*Str > L'9') || (*Str < L'0')) || + ((towupper (*Str) > L'F') || + (towupper (*Str) < L'A'))) && (Base == 16)) + { + return STATUS_INVALID_PARAMETER; + } + else + Str++; + } + + Str = String->Buffer + lenmin; + + if (Base == 0) + Base = 10; + + while (iswxdigit (*Str) && + (Val = iswdigit (*Str) ? *Str - L'0' : (iswlower (*Str) + ? toupper (*Str) : *Str) - L'A' + 10) < Base) + { + *Value = *Value * Base + Val; + Str++; + } + + if (addneg == TRUE) + *Value *= -1; + + return STATUS_SUCCESS; +} + + +ULONG STDCALL +RtlUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString) +{ + ULONG Size; + + RtlUnicodeToMultiByteSize(&Size, + UnicodeString->Buffer, + UnicodeString->Length); + return(Size+1); +} + + +NTSTATUS STDCALL +RtlUnicodeStringToOemString(IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbOemCodePageTag == TRUE){ + Length = RtlUnicodeStringToAnsiSize (SourceString); Length--; + } + else + Length = SourceString->Length / sizeof(WCHAR); + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(CHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag (NonPagedPool, + DestinationString->MaximumLength, + TAG_OSTR); + if (DestinationString->Buffer == NULL) + return STATUS_NO_MEMORY; + } + else + { + if (Length >= DestinationString->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + DestinationString->Length = Length; + + RtlZeroMemory(DestinationString->Buffer, + DestinationString->Length); + + Status = RtlUnicodeToOemN(DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool(DestinationString->Buffer); + return Status; + } + + DestinationString->Buffer[Length] = 0; + + return STATUS_SUCCESS; +} + + +WCHAR STDCALL +RtlUpcaseUnicodeChar(IN WCHAR Source) +{ + if (Source < L'a') + return(Source); + + if (Source <= L'z') + return(Source - (L'a' - L'A')); + + /* FIXME: characters above 'z' */ + + return(Source); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeString(IN OUT PUNICODE_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + ULONG i; + PWCHAR Src, Dest; + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag(NonPagedPool, + SourceString->Length + sizeof(WCHAR), + TAG_USTR); + if (DestinationString->Buffer == NULL) + return(STATUS_NO_MEMORY); + } + else + { + if (SourceString->Length >= DestinationString->MaximumLength) + return(STATUS_BUFFER_TOO_SMALL); + } + DestinationString->Length = SourceString->Length; + + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + for (i=0; i < SourceString->Length / sizeof(WCHAR); i++) + { + *Dest = RtlUpcaseUnicodeChar(*Src); + Dest++; + Src++; + } + *Dest = 0; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeStringToAnsiString(IN OUT PANSI_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbCodePageTag == TRUE){ + Length = RtlUnicodeStringToAnsiSize(SourceString); Length--; + } + else + Length = SourceString->Length / sizeof(WCHAR); + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(CHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag(NonPagedPool, + DestinationString->MaximumLength, + TAG_ASTR); + if (DestinationString->Buffer == NULL) + return(STATUS_NO_MEMORY); + } + else + { + if (Length >= DestinationString->MaximumLength) + return(STATUS_BUFFER_TOO_SMALL); + } + DestinationString->Length = Length; + + RtlZeroMemory(DestinationString->Buffer, + DestinationString->Length); + + Status = RtlUpcaseUnicodeToMultiByteN(DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool(DestinationString->Buffer); + return(Status); + } + + DestinationString->Buffer[Length] = 0; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeStringToCountedOemString(IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + ULONG Size; + + if (NlsMbCodePageTag == TRUE) + Length = RtlUnicodeStringToAnsiSize (SourceString)/* + 1*/; + else + Length = SourceString->Length / sizeof(WCHAR) + 1; + + if (Length > 0x0000FFFF) + return(STATUS_INVALID_PARAMETER_2); + + DestinationString->Length = (WORD)(Length - 1); + + if (AllocateDestinationString == TRUE) + { + DestinationString->Buffer = + ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_OSTR); + if (DestinationString->Buffer == NULL) + return(STATUS_NO_MEMORY); + + RtlZeroMemory(DestinationString->Buffer, + Length); + DestinationString->MaximumLength = (WORD)Length; + } + else + { + if (Length > DestinationString->MaximumLength) + { + if (DestinationString->MaximumLength == 0) + return(STATUS_BUFFER_OVERFLOW); + DestinationString->Length = + DestinationString->MaximumLength - 1; + } + } + + Status = RtlUpcaseUnicodeToOemN(DestinationString->Buffer, + DestinationString->Length, + &Size, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool(DestinationString->Buffer); + return(Status); + } + + DestinationString->Buffer[Size] = 0; + + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlUpcaseUnicodeStringToOemString(IN OUT POEM_STRING DestinationString, + IN PUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString) +{ + NTSTATUS Status; + ULONG Length; + + if (NlsMbOemCodePageTag == TRUE) { + Length = RtlUnicodeStringToOemSize(SourceString); Length--; + } + else + Length = SourceString->Length / sizeof(WCHAR); + + if (AllocateDestinationString == TRUE) + { + DestinationString->MaximumLength = Length + sizeof(CHAR); + DestinationString->Buffer = + ExAllocatePoolWithTag(NonPagedPool, + DestinationString->MaximumLength, + TAG_OSTR); + if (DestinationString->Buffer == NULL) + return(STATUS_NO_MEMORY); + } + else + { + if (Length >= DestinationString->MaximumLength) + return(STATUS_BUFFER_TOO_SMALL); + } + DestinationString->Length = Length; + + RtlZeroMemory(DestinationString->Buffer, + DestinationString->Length); + + Status = RtlUpcaseUnicodeToOemN(DestinationString->Buffer, + DestinationString->Length, + NULL, + SourceString->Buffer, + SourceString->Length); + if (!NT_SUCCESS(Status)) + { + if (AllocateDestinationString) + ExFreePool(DestinationString->Buffer); + return(Status); + } + + DestinationString->Buffer[Length] = 0; + + return(STATUS_SUCCESS); +} + + +CHAR STDCALL +RtlUpperChar(IN CHAR Source) +{ + WCHAR Unicode; + CHAR Destination; + + if (NlsMbCodePageTag == FALSE) + { + /* single-byte code page */ + /* ansi->unicode */ + Unicode = (WCHAR)Source; +#if 0 + Unicode = NlsAnsiToUnicodeData[Source]; +#endif + + /* upcase conversion */ + Unicode = RtlUpcaseUnicodeChar (Unicode); + + /* unicode -> ansi */ + Destination = (CHAR)Unicode; +#if 0 + Destination = NlsUnicodeToAnsiData[Unicode]; +#endif + } + else + { + /* single-byte code page */ + /* FIXME: implement the multi-byte stuff!! */ + Destination = Source; + } + + return(Destination); +} + + +VOID STDCALL +RtlUpperString(PSTRING DestinationString, + PSTRING SourceString) +{ + ULONG Length; + ULONG i; + PCHAR Src; + PCHAR Dest; + + Length = min(SourceString->Length, + DestinationString->MaximumLength - 1); + + Src = SourceString->Buffer; + Dest = DestinationString->Buffer; + for (i = 0; i < Length; i++) + { + *Dest = RtlUpperChar(*Src); + Src++; + Dest++; + } + *Dest = 0; + + DestinationString->Length = SourceString->Length; +} + + +ULONG STDCALL +RtlxAnsiStringToUnicodeSize(IN PANSI_STRING AnsiString) +{ + return(RtlAnsiStringToUnicodeSize(AnsiString)); +} + + +ULONG STDCALL +RtlxOemStringToUnicodeSize(IN POEM_STRING OemString) +{ + return(RtlOemStringToUnicodeSize((PANSI_STRING)OemString)); +} + + +ULONG STDCALL +RtlxUnicodeStringToAnsiSize(IN PUNICODE_STRING UnicodeString) +{ + return(RtlUnicodeStringToAnsiSize(UnicodeString)); +} + + +ULONG STDCALL +RtlxUnicodeStringToOemSize(IN PUNICODE_STRING UnicodeString) +{ + return(RtlUnicodeStringToOemSize(UnicodeString)); +} + +/* EOF */ diff --git a/ntoskrnl/rtl/wstring.c b/ntoskrnl/rtl/wstring.c new file mode 100644 index 0000000..ee59a51 --- /dev/null +++ b/ntoskrnl/rtl/wstring.c @@ -0,0 +1,308 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/wstring.c + * PURPOSE: Wide string functions + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + * 1998/12/04 RJJ Cleaned up and added i386 def checks. + * 1999/07/29 ekohl Added missing functions. + */ + +/* INCLUDES *****************************************************************/ + +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +int _wcsicmp (const wchar_t* cs, const wchar_t* ct) +{ + while (*cs != '\0' && *ct != '\0' && towupper(*cs) == towupper(*ct)) + { + cs++; + ct++; + } + return *cs - *ct; +} + +wchar_t *_wcslwr (wchar_t *x) +{ + wchar_t *y=x; + + while (*y) + { + *y=towlower(*y); + y++; + } + return x; +} + + +int _wcsnicmp (const wchar_t * cs,const wchar_t * ct,size_t count) +{ + if (count == 0) + return 0; + do { + if (towupper(*cs) != towupper(*ct++)) + return towupper(*cs) - towupper(*--ct); + if (*cs++ == 0) + break; + } while (--count != 0); + return 0; +} + + +wchar_t *_wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill) +{ + wchar_t *t = wsToFill; + int i = 0; + while( *wsToFill != 0 && i < sizeMaxFill) + { + *wsToFill = wcFill; + wsToFill++; + i++; + } + return t; +} + + +wchar_t *_wcsrev(wchar_t *s) +{ + wchar_t *e; + wchar_t a; + e=s; + while (*e) + e++; + while (s 0; len--) + { + if (str[len-1]==ch) + { + return (wchar_t *) &str[len - 1]; + } + } + + return NULL; +} + + +size_t wcsspn(const wchar_t *str,const wchar_t *accept) +{ + wchar_t *s; + wchar_t *t; + s=(wchar_t *)str; + do + { + t=(wchar_t *)accept; + while (*t) + { + if (*t==*s) + break; + t++; + } + if (!*t) + break; + s++; + } while (*s); + return s-str; /* nr of wchars */ +} + + +wchar_t *wcsstr(const wchar_t *s,const wchar_t *b) +{ + wchar_t *x; + wchar_t *y; + wchar_t *c; + x=(wchar_t *)s; + while (*x) + { + if (*x==*b) + { + y=x; + c=(wchar_t *)b; + while (*y && *c && *y==*c) + { + c++; + y++; + } + if (!*c) + return x; + } + x++; + } + return NULL; +} diff --git a/ntoskrnl/se/.cvsignore b/ntoskrnl/se/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/ntoskrnl/se/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/ntoskrnl/se/access.c b/ntoskrnl/se/access.c new file mode 100644 index 0000000..640d40b --- /dev/null +++ b/ntoskrnl/se/access.c @@ -0,0 +1,63 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Access rights handling functions + * FILE: ntoskrnl/se/access.c + * PROGRAMER: Eric Kohl + * REVISION HISTORY: + * 07/04/2000: Created + */ + +/* INCLUDES *****************************************************************/ + +#include + + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN +STDCALL +RtlAreAllAccessesGranted ( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ) +{ + return ((GrantedAccess & DesiredAccess) == DesiredAccess); +} + + +BOOLEAN +STDCALL +RtlAreAnyAccessesGranted ( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess + ) +{ + return ((GrantedAccess & DesiredAccess) != 0); +} + + +VOID +STDCALL +RtlMapGenericMask ( + PACCESS_MASK AccessMask, + PGENERIC_MAPPING GenericMapping + ) +{ + if (*AccessMask & GENERIC_READ) + *AccessMask |= GenericMapping->GenericRead; + + if (*AccessMask & GENERIC_WRITE) + *AccessMask |= GenericMapping->GenericWrite; + + if (*AccessMask & GENERIC_EXECUTE) + *AccessMask |= GenericMapping->GenericExecute; + + if (*AccessMask & GENERIC_ALL) + *AccessMask |= GenericMapping->GenericAll; + + *AccessMask &= 0x0FFFFFFF; +} + +/* EOF */ diff --git a/ntoskrnl/se/acl.c b/ntoskrnl/se/acl.c new file mode 100644 index 0000000..bd24958 --- /dev/null +++ b/ntoskrnl/se/acl.c @@ -0,0 +1,325 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: kernel/se/acl.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +#define TAG_ACL TAG('A', 'C', 'L', 'T') + + +/* GLOBALS ******************************************************************/ + +PACL EXPORTED SePublicDefaultDacl = NULL; +PACL EXPORTED SeSystemDefaultDacl = NULL; + +PACL SePublicDefaultUnrestrictedDacl = NULL; +PACL SePublicOpenDacl = NULL; +PACL SePublicOpenUnrestrictedDacl = NULL; +PACL SeUnrestrictedDacl = NULL; + + +/* FUNCTIONS ****************************************************************/ + +BOOLEAN +SepInitDACLs(VOID) +{ + ULONG AclLength2; + ULONG AclLength3; + ULONG AclLength4; + + AclLength2 = sizeof(ACL) + + 2 * (RtlLengthRequiredSid(1) + sizeof(ACE)); + AclLength3 = sizeof(ACL) + + 3 * (RtlLengthRequiredSid(1) + sizeof(ACE)); + AclLength4 = sizeof(ACL) + + 4 * (RtlLengthRequiredSid(1) + sizeof(ACE)); + + /* create PublicDefaultDacl */ + SePublicDefaultDacl = ExAllocatePoolWithTag(NonPagedPool, + AclLength2, + TAG_ACL); + if (SePublicDefaultDacl == NULL) + return(FALSE); + + RtlCreateAcl(SePublicDefaultDacl, + AclLength2, + 2); + + RtlAddAccessAllowedAce(SePublicDefaultDacl, + 2, + GENERIC_EXECUTE, + SeWorldSid); + + RtlAddAccessAllowedAce(SePublicDefaultDacl, + 2, + GENERIC_ALL, + SeLocalSystemSid); + + + /* create PublicDefaultUnrestrictedDacl */ + SePublicDefaultUnrestrictedDacl = ExAllocatePoolWithTag(NonPagedPool, + AclLength4, + TAG_ACL); + if (SePublicDefaultUnrestrictedDacl == NULL) + return(FALSE); + + RtlCreateAcl(SePublicDefaultUnrestrictedDacl, + AclLength4, + 2); + + RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, + 4, + GENERIC_EXECUTE, + SeWorldSid); + + RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, + 4, + GENERIC_ALL, + SeLocalSystemSid); + + RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, + 4, + GENERIC_ALL, + SeAliasAdminsSid); + + RtlAddAccessAllowedAce(SePublicDefaultUnrestrictedDacl, + 4, + GENERIC_READ | GENERIC_EXECUTE | STANDARD_RIGHTS_READ, + SeRestrictedCodeSid); + + /* create PublicOpenDacl */ + SePublicOpenDacl = ExAllocatePoolWithTag(NonPagedPool, + AclLength3, + TAG_ACL); + if (SePublicOpenDacl == NULL) + return(FALSE); + + RtlCreateAcl(SePublicOpenDacl, + AclLength3, + 3); + + RtlAddAccessAllowedAce(SePublicOpenDacl, + 2, + GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, + SeWorldSid); + + RtlAddAccessAllowedAce(SePublicOpenDacl, + 2, + GENERIC_ALL, + SeLocalSystemSid); + + RtlAddAccessAllowedAce(SePublicOpenDacl, + 2, + GENERIC_ALL, + SeAliasAdminsSid); + + + return(TRUE); +} + + +BOOLEAN STDCALL +RtlFirstFreeAce(PACL Acl, + PACE* Ace) +{ + PACE Current; + PVOID AclEnd; + ULONG i; + + Current = (PACE)(Acl + 1); + *Ace = NULL; + i = 0; + if (Acl->AceCount == 0) + { + *Ace = Current; + return(TRUE); + } + AclEnd = Acl->AclSize + Acl; + do + { + if ((PVOID)Current >= AclEnd) + { + return(FALSE); + } + if (Current->Header.AceType == 4) + { + if (Acl->AclRevision < 3) + { + return(FALSE); + } + } + Current = (PACE)((PVOID)Current + (ULONG)Current->Header.AceSize); + i++; + } while (i < Acl->AceCount); + if ((PVOID)Current >= AclEnd) + { + return(FALSE); + } + *Ace = Current; + return(TRUE); +} + + +NTSTATUS +RtlpAddKnownAce(PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid, + ULONG Type) +{ + PACE Ace; + + if (!RtlValidSid(Sid)) + { + return(STATUS_INVALID_SID); + } + if (Acl->AclRevision > 3 || + Revision > 3) + { + return(STATUS_UNKNOWN_REVISION); + } + if (Revision < Acl->AclRevision) + { + Revision = Acl->AclRevision; + } + if (!RtlFirstFreeAce(Acl, &Ace)) + { + return(STATUS_BUFFER_TOO_SMALL); + } + if (Ace == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + if (((PVOID)Ace + RtlLengthSid(Sid) + sizeof(ACE)) >= + ((PVOID)Acl + Acl->AclSize)) + { + return(STATUS_BUFFER_TOO_SMALL); + } + Ace->Header.AceFlags = 0; + Ace->Header.AceType = Type; + Ace->Header.AceSize = RtlLengthSid(Sid) + sizeof(ACE); + Ace->AccessMask = AccessMask; + RtlCopySid(RtlLengthSid(Sid), (PSID)(Ace + 1), Sid); + Acl->AceCount++; + Acl->AclRevision = Revision; + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlAddAccessAllowedAce(PACL Acl, + ULONG Revision, + ACCESS_MASK AccessMask, + PSID Sid) +{ + return(RtlpAddKnownAce(Acl, Revision, AccessMask, Sid, 0)); +} + + +NTSTATUS STDCALL +RtlAddAce(PACL Acl, + ULONG AclRevision, + ULONG StartingIndex, + PACE AceList, + ULONG AceListLength) +{ + PACE Ace; + ULONG i; + PACE Current; + ULONG j; + + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3) + { + return(STATUS_UNSUCCESSFUL); + } + if (!RtlFirstFreeAce(Acl,&Ace)) + { + return(STATUS_UNSUCCESSFUL); + } + if (Acl->AclRevision <= AclRevision) + { + AclRevision = Acl->AclRevision; + } + if (((PVOID)AceList + AceListLength) <= (PVOID)AceList) + { + return(STATUS_UNSUCCESSFUL); + } + i = 0; + Current = (PACE)(Acl + 1); + while ((PVOID)Current < ((PVOID)AceList + AceListLength)) + { + if (AceList->Header.AceType == 4 && + AclRevision < 3) + { + return(STATUS_UNSUCCESSFUL); + } + Current = (PACE)((PVOID)Current + Current->Header.AceSize); + } + if (Ace == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + if (((PVOID)Ace + AceListLength) >= ((PVOID)Acl + Acl->AclSize)) + { + return(STATUS_UNSUCCESSFUL); + } + if (StartingIndex != 0) + { + if (Acl->AceCount > 0) + { + Current = (PACE)(Acl + 1); + for (j = 0; j < StartingIndex; j++) + { + Current = (PACE)((PVOID)Current + Current->Header.AceSize); + } + } + } + /* RtlpAddData(AceList, AceListLength, Current, (PVOID)Ace - Current)); */ + memcpy(Current, AceList, AceListLength); + Acl->AceCount = Acl->AceCount + i; + Acl->AclRevision = AclRevision; + return(TRUE); +} + + +NTSTATUS STDCALL +RtlCreateAcl(PACL Acl, + ULONG AclSize, + ULONG AclRevision) +{ + if (AclSize < 8) + { + return(STATUS_BUFFER_TOO_SMALL); + } + if (AclRevision != 2 && + AclRevision != 3) + { + return(STATUS_UNKNOWN_REVISION); + } + if (AclSize > 0xffff) + { + return(STATUS_UNSUCCESSFUL); + } + AclSize = AclSize & ~(0x3); + Acl->AclSize = AclSize; + Acl->AclRevision = AclRevision; + Acl->AceCount = 0; + Acl->Sbz1 = 0; + Acl->Sbz2 = 0; + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/ntoskrnl/se/lsa.c b/ntoskrnl/se/lsa.c new file mode 100644 index 0000000..5b013ea --- /dev/null +++ b/ntoskrnl/se/lsa.c @@ -0,0 +1,83 @@ +/* $Id$ + */ +#include + +/* LsaCallAuthenticationPackage@28 */ +NTSTATUS STDCALL LsaCallAuthenticationPackage ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6 + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* LsaDeregisterLogonProcess@8 */ +NTSTATUS STDCALL LsaDeregisterLogonProcess ( + DWORD Unknown0, + DWORD Unknown1 + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* LsaFreeReturnBuffer@4 */ +NTSTATUS STDCALL LsaFreeReturnBuffer (PVOID Buffer) +{ + ULONG Size = 0; /* required by MEM_RELEASE */ + + return ZwFreeVirtualMemory ( + NtCurrentProcess(), + & Buffer, + & Size, + MEM_RELEASE + ); +} + +/* LsaLogonUser@56 */ +NTSTATUS STDCALL LsaLogonUser ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10, + DWORD Unknown11, + DWORD Unknown12, + DWORD Unknown13 + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* LsaLookupAuthenticationPackage@12 */ +NTSTATUS STDCALL LsaLookupAuthenticationPackage ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +/* LsaRegisterLogonProcess@12 */ +NTSTATUS STDCALL LsaRegisterLogonProcess ( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +/* EOF */ diff --git a/ntoskrnl/se/luid.c b/ntoskrnl/se/luid.c new file mode 100644 index 0000000..82b06f8 --- /dev/null +++ b/ntoskrnl/se/luid.c @@ -0,0 +1,69 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: ntoskrnl/se/luid.c + * PROGRAMER: ? + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* GLOBALS *******************************************************************/ + +static KSPIN_LOCK LuidLock; +static LARGE_INTEGER LuidIncrement; +static LUID Luid; + +/* FUNCTIONS *****************************************************************/ + +VOID +SepInitLuid(VOID) +{ + KeInitializeSpinLock(&LuidLock); + Luid.QuadPart = 999; /* SYSTEM_LUID */ + LuidIncrement.QuadPart = 1; +} + + +NTSTATUS STDCALL +NtAllocateLocallyUniqueId(OUT LUID* LocallyUniqueId) +{ + KIRQL oldIrql; + LUID ReturnedLuid; + + KeAcquireSpinLock(&LuidLock, + &oldIrql); + ReturnedLuid = Luid; + Luid = RtlLargeIntegerAdd(Luid, + LuidIncrement); + KeReleaseSpinLock(&LuidLock, + oldIrql); + *LocallyUniqueId = ReturnedLuid; + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +RtlCopyLuid(IN PLUID LuidDest, + IN PLUID LuidSrc) +{ + LuidDest->QuadPart = LuidSrc->QuadPart; +} + + +BOOLEAN STDCALL +RtlEqualLuid(IN PLUID Luid1, + IN PLUID Luid2) +{ + return((Luid1->QuadPart == Luid2->QuadPart) ? TRUE : FALSE); +} + +/* EOF */ diff --git a/ntoskrnl/se/priv.c b/ntoskrnl/se/priv.c new file mode 100644 index 0000000..df54d6f --- /dev/null +++ b/ntoskrnl/se/priv.c @@ -0,0 +1,306 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: kernel/se/priv.c + * PROGRAMER: ? + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + + +/* GLOBALS *******************************************************************/ + +LUID SeCreateTokenPrivilege; +LUID SeAssignPrimaryTokenPrivilege; +LUID SeLockMemoryPrivilege; +LUID SeIncreaseQuotaPrivilege; +LUID SeUnsolicitedInputPrivilege; +LUID SeTcbPrivilege; +LUID SeSecurityPrivilege; +LUID SeTakeOwnershipPrivilege; +LUID SeLoadDriverPrivilege; +LUID SeCreatePagefilePrivilege; +LUID SeIncreaseBasePriorityPrivilege; +LUID SeSystemProfilePrivilege; +LUID SeSystemtimePrivilege; +LUID SeProfileSingleProcessPrivilege; +LUID SeCreatePermanentPrivilege; +LUID SeBackupPrivilege; +LUID SeRestorePrivilege; +LUID SeShutdownPrivilege; +LUID SeDebugPrivilege; +LUID SeAuditPrivilege; +LUID SeSystemEnvironmentPrivilege; +LUID SeChangeNotifyPrivilege; +LUID SeRemoteShutdownPrivilege; + + +/* FUNCTIONS ***************************************************************/ + +VOID +SepInitPrivileges(VOID) +{ + SeCreateTokenPrivilege.QuadPart = SE_CREATE_TOKEN_PRIVILEGE; + SeAssignPrimaryTokenPrivilege.QuadPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE; + SeLockMemoryPrivilege.QuadPart = SE_LOCK_MEMORY_PRIVILEGE; + SeIncreaseQuotaPrivilege.QuadPart = SE_INCREASE_QUOTA_PRIVILEGE; + SeUnsolicitedInputPrivilege.QuadPart = SE_UNSOLICITED_INPUT_PRIVILEGE; + SeTcbPrivilege.QuadPart = SE_TCB_PRIVILEGE; + SeSecurityPrivilege.QuadPart = SE_SECURITY_PRIVILEGE; + SeTakeOwnershipPrivilege.QuadPart = SE_TAKE_OWNERSHIP_PRIVILEGE; + SeLoadDriverPrivilege.QuadPart = SE_LOAD_DRIVER_PRIVILEGE; + SeSystemProfilePrivilege.QuadPart = SE_SYSTEM_PROFILE_PRIVILEGE; + SeSystemtimePrivilege.QuadPart = SE_SYSTEMTIME_PRIVILEGE; + SeProfileSingleProcessPrivilege.QuadPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE; + SeIncreaseBasePriorityPrivilege.QuadPart = SE_INC_BASE_PRIORITY_PRIVILEGE; + SeCreatePagefilePrivilege.QuadPart = SE_CREATE_PAGEFILE_PRIVILEGE; + SeCreatePermanentPrivilege.QuadPart = SE_CREATE_PERMANENT_PRIVILEGE; + SeBackupPrivilege.QuadPart = SE_BACKUP_PRIVILEGE; + SeRestorePrivilege.QuadPart = SE_RESTORE_PRIVILEGE; + SeShutdownPrivilege.QuadPart = SE_SHUTDOWN_PRIVILEGE; + SeDebugPrivilege.QuadPart = SE_DEBUG_PRIVILEGE; + SeAuditPrivilege.QuadPart = SE_AUDIT_PRIVILEGE; + SeSystemEnvironmentPrivilege.QuadPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE; + SeChangeNotifyPrivilege.QuadPart = SE_CHANGE_NOTIFY_PRIVILEGE; + SeRemoteShutdownPrivilege.QuadPart = SE_REMOTE_SHUTDOWN_PRIVILEGE; +} + + +BOOLEAN SepPrivilegeCheck(PACCESS_TOKEN Token, + PLUID_AND_ATTRIBUTES Privileges, + ULONG PrivilegeCount, + ULONG PrivilegeControl, + KPROCESSOR_MODE PreviousMode) +{ + ULONG i; + PLUID_AND_ATTRIBUTES Current; + ULONG j; + ULONG k; + + if (PreviousMode == KernelMode) + { + return(TRUE); + } + + j = 0; + if (PrivilegeCount != 0) + { + k = PrivilegeCount; + do + { + i = Token->PrivilegeCount; + Current = Token->Privileges; + for (i = 0; i < Token->PrivilegeCount; i++) + { + if (!(Current[i].Attributes & SE_PRIVILEGE_ENABLED) && + Privileges[i].Luid.u.LowPart == + Current[i].Luid.u.LowPart && + Privileges[i].Luid.u.HighPart == + Current[i].Luid.u.HighPart) + { + Privileges[i].Attributes = + Privileges[i].Attributes | + SE_PRIVILEGE_USED_FOR_ACCESS; + j++; + break; + } + } + k--; + } while (k > 0); + } + + if ((PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) && + PrivilegeCount == j) + { + return(TRUE); + } + + if (j > 0 && + !(PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY)) + { + return(TRUE); + } + + return(FALSE); +} + + +NTSTATUS SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src, + ULONG PrivilegeCount, + KPROCESSOR_MODE PreviousMode, + PLUID_AND_ATTRIBUTES AllocatedMem, + ULONG AllocatedLength, + POOL_TYPE PoolType, + ULONG d, + PLUID_AND_ATTRIBUTES* Dest, + PULONG Length) +{ + PLUID_AND_ATTRIBUTES* NewMem; + ULONG SrcLength; + + if (PrivilegeCount == 0) + { + *Dest = 0; + *Length = 0; + return(STATUS_SUCCESS); + } + if (PreviousMode == 0 && d == 0) + { + *Dest = Src; + return(STATUS_SUCCESS); + } + SrcLength = ((PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES)) + 3) & 0xfc; + *Length = SrcLength; + if (AllocatedMem == NULL) + { + NewMem = ExAllocatePool(PoolType, SrcLength); + *Dest = (PLUID_AND_ATTRIBUTES)NewMem; + if (NewMem == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + } + else + { + if (SrcLength > AllocatedLength) + { + return(STATUS_UNSUCCESSFUL); + } + *Dest = AllocatedMem; + } + memmove(*Dest, Src, SrcLength); + return(STATUS_SUCCESS); +} + +VOID +SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege, + KPROCESSOR_MODE PreviousMode, + ULONG a) +{ + ExFreePool(Privilege); +} + +NTSTATUS STDCALL +NtPrivilegeCheck(IN HANDLE ClientToken, + IN PPRIVILEGE_SET RequiredPrivileges, + IN PBOOLEAN Result) +{ + NTSTATUS Status; + PACCESS_TOKEN Token; + ULONG PrivilegeCount; + BOOLEAN TResult; + ULONG PrivilegeControl; + PLUID_AND_ATTRIBUTES Privilege; + ULONG Length; + + Status = ObReferenceObjectByHandle(ClientToken, + 0, + SepTokenObjectType, + UserMode, + (PVOID*)&Token, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + if (Token->TokenType == TokenImpersonation && + Token->ImpersonationLevel < SecurityAnonymous) + { + ObDereferenceObject(Token); + return(STATUS_UNSUCCESSFUL); + } + PrivilegeCount = RequiredPrivileges->PrivilegeCount; + PrivilegeControl = RequiredPrivileges->Control; + Privilege = 0; + Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege, + PrivilegeCount, + 1, + 0, + 0, + 1, + 1, + &Privilege, + &Length); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Token); + return(STATUS_UNSUCCESSFUL); + } + TResult = SepPrivilegeCheck(Token, + Privilege, + PrivilegeCount, + PrivilegeControl, + UserMode); + memmove(RequiredPrivileges->Privilege, Privilege, Length); + *Result = TResult; + SeReleaseLuidAndAttributesArray(Privilege, UserMode, 1); + return(STATUS_SUCCESS); +} + +BOOLEAN STDCALL +SePrivilegeCheck(PPRIVILEGE_SET Privileges, + PSECURITY_SUBJECT_CONTEXT SubjectContext, + KPROCESSOR_MODE PreviousMode) +{ + PACCESS_TOKEN Token = NULL; + + if (SubjectContext->ClientToken == NULL) + { + Token = SubjectContext->PrimaryToken; + } + else + { + Token = SubjectContext->ClientToken; + if (SubjectContext->ImpersonationLevel < 2) + { + return(FALSE); + } + } + + return(SepPrivilegeCheck(Token, + Privileges->Privilege, + Privileges->PrivilegeCount, + Privileges->Control, + PreviousMode)); +} + +BOOLEAN STDCALL +SeSinglePrivilegeCheck(IN LUID PrivilegeValue, + IN KPROCESSOR_MODE PreviousMode) +{ + SECURITY_SUBJECT_CONTEXT SubjectContext; + BOOLEAN r; + PRIVILEGE_SET Priv; + + SeCaptureSubjectContext(&SubjectContext); + + Priv.PrivilegeCount = 1; + Priv.Control = 1; + Priv.Privilege[0].Luid = PrivilegeValue; + Priv.Privilege[0].Attributes = 0; + + r = SePrivilegeCheck(&Priv, + &SubjectContext, + PreviousMode); + + if (PreviousMode != KernelMode) + { +#if 0 + SePrivilegeServiceAuditAlarm(0, + &SubjectContext, + &PrivilegeValue); +#endif + } + SeReleaseSubjectContext(&SubjectContext); + return(r); +} + diff --git a/ntoskrnl/se/sd.c b/ntoskrnl/se/sd.c new file mode 100644 index 0000000..463fba2 --- /dev/null +++ b/ntoskrnl/se/sd.c @@ -0,0 +1,394 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: kernel/se/sd.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + + +/* FUNCTIONS ***************************************************************/ + +BOOLEAN +SepInitSDs(VOID) +{ + return(TRUE); +} + + +NTSTATUS STDCALL +RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + ULONG Revision) +{ + if (Revision != 1) + return(STATUS_UNSUCCESSFUL); + + SecurityDescriptor->Revision = 1; + SecurityDescriptor->Sbz1 = 0; + SecurityDescriptor->Control = 0; + SecurityDescriptor->Owner = NULL; + SecurityDescriptor->Group = NULL; + SecurityDescriptor->Sacl = NULL; + SecurityDescriptor->Dacl = NULL; + + return(STATUS_SUCCESS); +} + +ULONG STDCALL +RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + PSID Owner; + PSID Group; + ULONG Length; + PACL Dacl; + PACL Sacl; + + Length = sizeof(SECURITY_DESCRIPTOR); + + if (SecurityDescriptor->Owner != NULL) + { + Owner = SecurityDescriptor->Owner; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Owner = (PSID)((ULONG)Owner + + (ULONG)SecurityDescriptor); + } + Length = Length + ((sizeof(SID) + (Owner->SubAuthorityCount - 1) * + sizeof(ULONG) + 3) & 0xfc); + } + if (SecurityDescriptor->Group != NULL) + { + Group = SecurityDescriptor->Group; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Group = (PSID)((ULONG)Group + (ULONG)SecurityDescriptor); + } + Length = Length + ((sizeof(SID) + (Group->SubAuthorityCount - 1) * + sizeof(ULONG) + 3) & 0xfc); + } + if (SecurityDescriptor->Control & SE_DACL_PRESENT && + SecurityDescriptor->Dacl != NULL) + { + Dacl = SecurityDescriptor->Dacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Dacl = (PACL)((ULONG)Dacl + (PVOID)SecurityDescriptor); + } + Length = Length + ((Dacl->AclSize + 3) & 0xfc); + } + if (SecurityDescriptor->Control & SE_SACL_PRESENT && + SecurityDescriptor->Sacl != NULL) + { + Sacl = SecurityDescriptor->Sacl; + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + Sacl = (PACL)((ULONG)Sacl + (PVOID)SecurityDescriptor); + } + Length = Length + ((Sacl->AclSize + 3) & 0xfc); + } + return(Length); +} + + +NTSTATUS STDCALL +RtlGetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PBOOLEAN DaclPresent, + PACL* Dacl, + PBOOLEAN DaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (!(SecurityDescriptor->Control & SE_DACL_PRESENT)) + { + *DaclPresent = 0; + return(STATUS_SUCCESS); + } + *DaclPresent = 1; + if (SecurityDescriptor->Dacl == NULL) + { + *Dacl = NULL; + } + else + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Dacl = (PACL)((ULONG)SecurityDescriptor->Dacl + + (PVOID)SecurityDescriptor); + } + else + { + *Dacl = SecurityDescriptor->Dacl; + } + } + if (SecurityDescriptor->Control & SE_DACL_DEFAULTED) + { + *DaclDefaulted = 1; + } + else + { + *DaclDefaulted = 0; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN DaclPresent, + PACL Dacl, + BOOLEAN DaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + if (!DaclPresent) + { + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_PRESENT); + return(STATUS_SUCCESS); + } + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_PRESENT; + SecurityDescriptor->Dacl = Dacl; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_DACL_DEFAULTED); + if (DaclDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_DACL_DEFAULTED; + } + return(STATUS_SUCCESS); +} + + +BOOLEAN STDCALL +RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID Owner, + BOOLEAN OwnerDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + SecurityDescriptor->Owner = Owner; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_OWNER_DEFAULTED); + if (OwnerDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_OWNER_DEFAULTED; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlGetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID* Owner, + PBOOLEAN OwnerDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Owner != NULL) + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Owner = (PSID)((ULONG)SecurityDescriptor->Owner + + (PVOID)SecurityDescriptor); + } + else + { + *Owner = SecurityDescriptor->Owner; + } + } + else + { + *Owner = NULL; + } + if (SecurityDescriptor->Control & SE_OWNER_DEFAULTED) + { + *OwnerDefaulted = 1; + } + else + { + *OwnerDefaulted = 0; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlSetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID Group, + BOOLEAN GroupDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + SecurityDescriptor->Group = Group; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_GROUP_DEFAULTED); + if (GroupDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_GROUP_DEFAULTED; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlGetGroupSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PSID* Group, + PBOOLEAN GroupDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Group != NULL) + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Group = (PSID)((ULONG)SecurityDescriptor->Group + + (PVOID)SecurityDescriptor); + } + else + { + *Group = SecurityDescriptor->Group; + } + } + else + { + *Group = NULL; + } + if (SecurityDescriptor->Control & SE_GROUP_DEFAULTED) + { + *GroupDefaulted = 1; + } + else + { + *GroupDefaulted = 0; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlGetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + PBOOLEAN SaclPresent, + PACL *Sacl, + PBOOLEAN SaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (!(SecurityDescriptor->Control & SE_SACL_PRESENT)) + { + *SaclPresent = 0; + return(STATUS_SUCCESS); + } + *SaclPresent = 1; + if (SecurityDescriptor->Sacl == NULL) + { + *Sacl = NULL; + } + else + { + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + *Sacl = (PACL)((ULONG)SecurityDescriptor->Sacl + + (PVOID)SecurityDescriptor); + } + else + { + *Sacl = SecurityDescriptor->Sacl; + } + } + if (SecurityDescriptor->Control & SE_SACL_DEFAULTED) + { + *SaclDefaulted = 1; + } + else + { + *SaclDefaulted = 0; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOLEAN SaclPresent, + PACL Sacl, + BOOLEAN SaclDefaulted) +{ + if (SecurityDescriptor->Revision != 1) + { + return(STATUS_UNSUCCESSFUL); + } + if (SecurityDescriptor->Control & SE_SELF_RELATIVE) + { + return(STATUS_UNSUCCESSFUL); + } + if (!SaclPresent) + { + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_PRESENT); + return(STATUS_SUCCESS); + } + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_PRESENT; + SecurityDescriptor->Sacl = Sacl; + SecurityDescriptor->Control = SecurityDescriptor->Control & ~(SE_SACL_DEFAULTED); + if (SaclDefaulted) + { + SecurityDescriptor->Control = SecurityDescriptor->Control | SE_SACL_DEFAULTED; + } + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlAbsoluteToSelfRelativeSD(PSECURITY_DESCRIPTOR AbsSD, + PSECURITY_DESCRIPTOR RelSD, + PULONG BufferLength) +{ + if (AbsSD->Control & SE_SELF_RELATIVE) + return(STATUS_BAD_DESCRIPTOR_FORMAT); + +// return(RtlPMakeSelfRelativeSD (AbsSD, RelSD, BufferLength)); + + UNIMPLEMENTED; + return(STATUS_NOT_IMPLEMENTED); +} + + + +/* EOF */ diff --git a/ntoskrnl/se/semgr.c b/ntoskrnl/se/semgr.c new file mode 100644 index 0000000..6102752 --- /dev/null +++ b/ntoskrnl/se/semgr.c @@ -0,0 +1,501 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: kernel/se/semgr.c + * PROGRAMER: ? + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include + +#define TAG_SXPT TAG('S', 'X', 'P', 'T') + + +/* GLOBALS ******************************************************************/ + +PSE_EXPORTS EXPORTED SeExports = NULL; + + +/* PROTOTYPES ***************************************************************/ + +static BOOLEAN SepInitExports(VOID); + +/* FUNCTIONS ****************************************************************/ + + +BOOLEAN +SeInit1(VOID) +{ + SepInitLuid(); + + if (!SepInitSecurityIDs()) + return(FALSE); + + if (!SepInitDACLs()) + return(FALSE); + + if (!SepInitSDs()) + return(FALSE); + + SepInitPrivileges(); + + if (!SepInitExports()) + return(FALSE); + + return(TRUE); +} + + +BOOLEAN +SeInit2(VOID) +{ + SepInitializeTokenImplementation(); + + return(TRUE); +} + + +static BOOLEAN +SepInitExports(VOID) +{ + SeExports = ExAllocatePoolWithTag(NonPagedPool, + sizeof(SE_EXPORTS), + TAG_SXPT); + if (SeExports == NULL) + return(FALSE); + + SeExports->SeCreateTokenPrivilege = SeCreateTokenPrivilege; + SeExports->SeAssignPrimaryTokenPrivilege = SeAssignPrimaryTokenPrivilege; + SeExports->SeLockMemoryPrivilege = SeLockMemoryPrivilege; + SeExports->SeIncreaseQuotaPrivilege = SeIncreaseQuotaPrivilege; + SeExports->SeUnsolicitedInputPrivilege = SeUnsolicitedInputPrivilege; + SeExports->SeTcbPrivilege = SeTcbPrivilege; + SeExports->SeSecurityPrivilege = SeSecurityPrivilege; + SeExports->SeTakeOwnershipPrivilege = SeTakeOwnershipPrivilege; + SeExports->SeLoadDriverPrivilege = SeLoadDriverPrivilege; + SeExports->SeCreatePagefilePrivilege = SeCreatePagefilePrivilege; + SeExports->SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege; + SeExports->SeSystemProfilePrivilege = SeSystemProfilePrivilege; + SeExports->SeSystemtimePrivilege = SeSystemtimePrivilege; + SeExports->SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege; + SeExports->SeCreatePermanentPrivilege = SeCreatePermanentPrivilege; + SeExports->SeBackupPrivilege = SeBackupPrivilege; + SeExports->SeRestorePrivilege = SeRestorePrivilege; + SeExports->SeShutdownPrivilege = SeShutdownPrivilege; + SeExports->SeDebugPrivilege = SeDebugPrivilege; + SeExports->SeAuditPrivilege = SeAuditPrivilege; + SeExports->SeSystemEnvironmentPrivilege = SeSystemEnvironmentPrivilege; + SeExports->SeChangeNotifyPrivilege = SeChangeNotifyPrivilege; + SeExports->SeRemoteShutdownPrivilege = SeRemoteShutdownPrivilege; + + SeExports->SeNullSid = SeNullSid; + SeExports->SeWorldSid = SeWorldSid; + SeExports->SeLocalSid = SeLocalSid; + SeExports->SeCreatorOwnerSid = SeCreatorOwnerSid; + SeExports->SeCreatorGroupSid = SeCreatorGroupSid; + SeExports->SeNtAuthoritySid = SeNtAuthoritySid; + SeExports->SeDialupSid = SeDialupSid; + SeExports->SeNetworkSid = SeNetworkSid; + SeExports->SeBatchSid = SeBatchSid; + SeExports->SeInteractiveSid = SeInteractiveSid; + SeExports->SeLocalSystemSid = SeLocalSystemSid; + SeExports->SeAliasAdminsSid = SeAliasAdminsSid; + SeExports->SeAliasUsersSid = SeAliasUsersSid; + SeExports->SeAliasGuestsSid = SeAliasGuestsSid; + SeExports->SeAliasPowerUsersSid = SeAliasPowerUsersSid; + SeExports->SeAliasAccountOpsSid = SeAliasAccountOpsSid; + SeExports->SeAliasSystemOpsSid = SeAliasSystemOpsSid; + SeExports->SeAliasPrintOpsSid = SeAliasPrintOpsSid; + SeExports->SeAliasBackupOpsSid = SeAliasBackupOpsSid; + + return(TRUE); +} + + +VOID SepReferenceLogonSession(PLUID AuthenticationId) +{ + UNIMPLEMENTED; +} + +VOID SepDeReferenceLogonSession(PLUID AuthenticationId) +{ + UNIMPLEMENTED; +} + +NTSTATUS STDCALL +NtPrivilegedServiceAuditAlarm(IN PUNICODE_STRING SubsystemName, + IN PUNICODE_STRING ServiceName, + IN HANDLE ClientToken, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtPrivilegeObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN HANDLE ClientToken, + IN ULONG DesiredAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN AccessGranted) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtOpenObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ClientToken, + IN ULONG DesiredAccess, + IN ULONG GrantedAccess, + IN PPRIVILEGE_SET Privileges, + IN BOOLEAN ObjectCreation, + IN BOOLEAN AccessGranted, + OUT PBOOLEAN GenerateOnClose) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtAccessCheckAndAuditAlarm(IN PUNICODE_STRING SubsystemName, + IN PHANDLE ObjectHandle, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + IN BOOLEAN ObjectCreation, + OUT PULONG GrantedAccess, + OUT PBOOLEAN AccessStatus, + OUT PBOOLEAN GenerateOnClose + ) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtAllocateUuids(PULARGE_INTEGER Time, + PULONG Range, + PULONG Sequence) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtCloseObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN HANDLE ClientToken, + IN ACCESS_MASK DesiredAccess, + IN PGENERIC_MAPPING GenericMapping, + OUT PPRIVILEGE_SET PrivilegeSet, + OUT PULONG ReturnLength, + OUT PULONG GrantedAccess, + OUT PBOOLEAN AccessStatus) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtDeleteObjectAuditAlarm(IN PUNICODE_STRING SubsystemName, + IN PVOID HandleId, + IN BOOLEAN GenerateOnClose) +{ + UNIMPLEMENTED; +} + + + +VOID STDCALL SeReleaseSubjectContext (PSECURITY_SUBJECT_CONTEXT SubjectContext) +{ + ObDereferenceObject(SubjectContext->PrimaryToken); + if (SubjectContext->ClientToken != NULL) + { + ObDereferenceObject(SubjectContext->ClientToken); + } +} + +VOID STDCALL SeCaptureSubjectContext (PSECURITY_SUBJECT_CONTEXT SubjectContext) +{ + PEPROCESS Process; + ULONG a; + ULONG b; + + Process = PsGetCurrentThread()->ThreadsProcess; + + SubjectContext->ProcessAuditId = Process; + SubjectContext->ClientToken = + PsReferenceImpersonationToken(PsGetCurrentThread(), + &a, + &b, + &SubjectContext->ImpersonationLevel); + SubjectContext->PrimaryToken = PsReferencePrimaryToken(Process); +} + + +NTSTATUS STDCALL +SeDeassignSecurity(PSECURITY_DESCRIPTOR* SecurityDescriptor) +{ + if ((*SecurityDescriptor) != NULL) + { + ExFreePool(*SecurityDescriptor); + (*SecurityDescriptor) = NULL; + } + return(STATUS_SUCCESS); +} + + +#if 0 +VOID SepGetDefaultsSubjectContext(PSECURITY_SUBJECT_CONTEXT SubjectContext, + PSID* Owner, + PSID* PrimaryGroup, + PSID* ProcessOwner, + PSID* ProcessPrimaryGroup, + PACL* DefaultDacl) +{ + PACCESS_TOKEN Token; + + if (SubjectContext->ClientToken != NULL) + { + Token = SubjectContext->ClientToken; + } + else + { + Token = SubjectContext->PrimaryToken; + } + *Owner = Token->UserAndGroups[Token->DefaultOwnerIndex].Sid; + *PrimaryGroup = Token->PrimaryGroup; + *DefaultDacl = Token->DefaultDacl; + *ProcessOwner = SubjectContext->PrimaryToken-> + UserAndGroups[Token->DefaultOwnerIndex].Sid; + *ProcessPrimaryGroup = SubjectContext->PrimaryToken->PrimaryGroup; +} + +NTSTATUS SepInheritAcl(PACL Acl, + BOOLEAN IsDirectoryObject, + PSID Owner, + PSID PrimaryGroup, + PACL DefaultAcl, + PSID ProcessOwner, + PSID ProcessGroup, + PGENERIC_MAPPING GenericMapping) +{ + if (Acl == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + if (Acl->AclRevision != 2 && + Acl->AclRevision != 3 ) + { + return(STATUS_UNSUCCESSFUL); + } + +} +#endif + +NTSTATUS STDCALL +SeAssignSecurity(PSECURITY_DESCRIPTOR ParentDescriptor, + PSECURITY_DESCRIPTOR ExplicitDescriptor, + PSECURITY_DESCRIPTOR* NewDescriptor, + BOOLEAN IsDirectoryObject, + PSECURITY_SUBJECT_CONTEXT SubjectContext, + PGENERIC_MAPPING GenericMapping, + POOL_TYPE PoolType) +{ +#if 0 + PSECURITY_DESCRIPTOR Descriptor; + PSID Owner; + PSID PrimaryGroup; + PACL DefaultDacl; + PSID ProcessOwner; + PSID ProcessPrimaryGroup; + PACL Sacl; + + if (ExplicitDescriptor == NULL) + { + RtlCreateSecurityDescriptor(&Descriptor, 1); + } + else + { + Descriptor = ExplicitDescriptor; + } + SeLockSubjectContext(SubjectContext); + SepGetDefaultsSubjectContext(SubjectContext, + &Owner, + &PrimaryGroup, + &DefaultDacl, + &ProcessOwner, + &ProcessPrimaryGroup); + if (Descriptor->Control & SE_SACL_PRESENT || + Descriptor->Control & SE_SACL_DEFAULTED) + { + if (ParentDescriptor == NULL) + { + } + if (Descriptor->Control & SE_SACL_PRESENT || + Descriptor->Sacl == NULL ||) + { + Sacl = NULL; + } + else + { + Sacl = Descriptor->Sacl; + if (Descriptor->Control & SE_SELF_RELATIVE) + { + Sacl = (PACL)(((PVOID)Sacl) + (PVOID)Descriptor); + } + } + SepInheritAcl(Sacl, + IsDirectoryObject, + Owner, + PrimaryGroup, + DefaultDacl, + ProcessOwner, + GenericMapping); + } +#else + UNIMPLEMENTED; +#endif +} + +BOOLEAN SepSidInToken(PACCESS_TOKEN Token, + PSID Sid) +{ + ULONG i; + + if (Token->UserAndGroupCount == 0) + { + return(FALSE); + } + + for (i=0; iUserAndGroupCount; i++) + { + if (RtlEqualSid(Sid, Token->UserAndGroups[i].Sid)) + { + if (i == 0 || + (!(Token->UserAndGroups[i].Attributes & SE_GROUP_ENABLED))) + { + return(TRUE); + } + return(FALSE); + } + } + return(FALSE); +} + + +BOOLEAN STDCALL +SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, + IN BOOLEAN SubjectContextLocked, + IN ACCESS_MASK DesiredAccess, + IN ACCESS_MASK PreviouslyGrantedAccess, + OUT PPRIVILEGE_SET* Privileges, + IN PGENERIC_MAPPING GenericMapping, + IN KPROCESSOR_MODE AccessMode, + OUT PACCESS_MODE GrantedAccess, + OUT PNTSTATUS AccessStatus) +/* + * FUNCTION: Determines whether the requested access rights can be granted + * to an object protected by a security descriptor and an object owner + * ARGUMENTS: + * SecurityDescriptor = Security descriptor protecting the object + * SubjectSecurityContext = Subject's captured security context + * SubjectContextLocked = Indicates the user's subject context is locked + * DesiredAccess = Access rights the caller is trying to acquire + * PreviouslyGrantedAccess = Specified the access rights already granted + * Privileges = ? + * GenericMapping = Generic mapping associated with the object + * AccessMode = Access mode used for the check + * GrantedAccess (OUT) = On return specifies the access granted + * AccessStatus (OUT) = Status indicating why access was denied + * RETURNS: If access was granted, returns TRUE + */ +{ + ULONG i; + PACL Dacl; + BOOLEAN Present; + BOOLEAN Defaulted; + NTSTATUS Status; + PACE CurrentAce; + PSID Sid; + ACCESS_MASK CurrentAccess; + + CurrentAccess = PreviouslyGrantedAccess; + + /* + * Ignore the SACL for now + */ + + /* + * Check the DACL + */ + Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, + &Present, + &Dacl, + &Defaulted); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + CurrentAce = (PACE)(Dacl + 1); + for (i = 0; i < Dacl->AceCount; i++) + { + Sid = (PSID)(CurrentAce + 1); + if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) + { + if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid)) + { + *AccessStatus = STATUS_ACCESS_DENIED; + *GrantedAccess = 0; + return(STATUS_SUCCESS); + } + } + if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) + { + if (SepSidInToken(SubjectSecurityContext->ClientToken, Sid)) + { + CurrentAccess = CurrentAccess | + CurrentAce->AccessMask; + } + } + } + if (!(CurrentAccess & DesiredAccess) && + !((~CurrentAccess) & DesiredAccess)) + { + *AccessStatus = STATUS_ACCESS_DENIED; + } + else + { + *AccessStatus = STATUS_SUCCESS; + } + *GrantedAccess = CurrentAccess; + + return(STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/ntoskrnl/se/sid.c b/ntoskrnl/se/sid.c new file mode 100644 index 0000000..c9a6100 --- /dev/null +++ b/ntoskrnl/se/sid.c @@ -0,0 +1,669 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: ntoskrnl/se/sid.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include + +#define TAG_SID TAG('S', 'I', 'D', 'T') + + +/* GLOBALS ******************************************************************/ + +SID_IDENTIFIER_AUTHORITY SeNullSidAuthority = {SECURITY_NULL_SID_AUTHORITY}; +SID_IDENTIFIER_AUTHORITY SeWorldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY}; +SID_IDENTIFIER_AUTHORITY SeLocalSidAuthority = {SECURITY_LOCAL_SID_AUTHORITY}; +SID_IDENTIFIER_AUTHORITY SeCreatorSidAuthority = {SECURITY_CREATOR_SID_AUTHORITY}; +SID_IDENTIFIER_AUTHORITY SeNtSidAuthority = {SECURITY_NT_AUTHORITY}; + +PSID SeNullSid = NULL; +PSID SeWorldSid = NULL; +PSID SeLocalSid = NULL; +PSID SeCreatorOwnerSid = NULL; +PSID SeCreatorGroupSid = NULL; +PSID SeCreatorOwnerServerSid = NULL; +PSID SeCreatorGroupServerSid = NULL; +PSID SeNtAuthoritySid = NULL; +PSID SeDialupSid = NULL; +PSID SeNetworkSid = NULL; +PSID SeBatchSid = NULL; +PSID SeInteractiveSid = NULL; +PSID SeServiceSid = NULL; +PSID SeAnonymousLogonSid = NULL; +PSID SePrincipalSelfSid = NULL; +PSID SeLocalSystemSid = NULL; +PSID SeAuthenticatedUserSid = NULL; +PSID SeRestrictedCodeSid = NULL; +PSID SeAliasAdminsSid = NULL; +PSID SeAliasUsersSid = NULL; +PSID SeAliasGuestsSid = NULL; +PSID SeAliasPowerUsersSid = NULL; +PSID SeAliasAccountOpsSid = NULL; +PSID SeAliasSystemOpsSid = NULL; +PSID SeAliasPrintOpsSid = NULL; +PSID SeAliasBackupOpsSid = NULL; + + +/* FUNCTIONS ****************************************************************/ + + +BOOLEAN +SepInitSecurityIDs(VOID) +{ + ULONG SidLength0; + ULONG SidLength1; + ULONG SidLength2; + PULONG SubAuthority; + + SidLength0 = RtlLengthRequiredSid(0); + SidLength1 = RtlLengthRequiredSid(1); + SidLength2 = RtlLengthRequiredSid(2); + + /* create NullSid */ + SeNullSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeNullSid == NULL) + return(FALSE); + + RtlInitializeSid(SeNullSid, + &SeNullSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeNullSid, + 0); + *SubAuthority = SECURITY_NULL_RID; + + /* create WorldSid */ + SeWorldSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeWorldSid == NULL) + return(FALSE); + + RtlInitializeSid(SeWorldSid, + &SeWorldSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeWorldSid, + 0); + *SubAuthority = SECURITY_WORLD_RID; + + /* create LocalSid */ + SeLocalSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeLocalSid == NULL) + return(FALSE); + + RtlInitializeSid(SeLocalSid, + &SeLocalSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeLocalSid, + 0); + *SubAuthority = SECURITY_LOCAL_RID; + + /* create CreatorOwnerSid */ + SeCreatorOwnerSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeCreatorOwnerSid == NULL) + return(FALSE); + + RtlInitializeSid(SeCreatorOwnerSid, + &SeCreatorSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeCreatorOwnerSid, + 0); + *SubAuthority = SECURITY_CREATOR_OWNER_RID; + + /* create CreatorGroupSid */ + SeCreatorGroupSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeCreatorGroupSid == NULL) + return(FALSE); + + RtlInitializeSid(SeCreatorGroupSid, + &SeCreatorSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeCreatorGroupSid, + 0); + *SubAuthority = SECURITY_CREATOR_GROUP_RID; + + /* create CreatorOwnerServerSid */ + SeCreatorOwnerServerSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeCreatorOwnerServerSid == NULL) + return(FALSE); + + RtlInitializeSid(SeCreatorOwnerServerSid, + &SeCreatorSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeCreatorOwnerServerSid, + 0); + *SubAuthority = SECURITY_CREATOR_OWNER_SERVER_RID; + + /* create CreatorGroupServerSid */ + SeCreatorGroupServerSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeCreatorGroupServerSid == NULL) + return(FALSE); + + RtlInitializeSid(SeCreatorGroupServerSid, + &SeCreatorSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeCreatorGroupServerSid, + 0); + *SubAuthority = SECURITY_CREATOR_GROUP_SERVER_RID; + + + /* create NtAuthoritySid */ + SeNtAuthoritySid = ExAllocatePoolWithTag(NonPagedPool, + SidLength0, + TAG_SID); + if (SeNtAuthoritySid == NULL) + return(FALSE); + + RtlInitializeSid(SeNtAuthoritySid, + &SeNtSidAuthority, + 0); + + /* create DialupSid */ + SeDialupSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeDialupSid == NULL) + return(FALSE); + + RtlInitializeSid(SeDialupSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeDialupSid, + 0); + *SubAuthority = SECURITY_DIALUP_RID; + + /* create NetworkSid */ + SeNetworkSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeNetworkSid == NULL) + return(FALSE); + + RtlInitializeSid(SeNetworkSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeNetworkSid, + 0); + *SubAuthority = SECURITY_NETWORK_RID; + + /* create BatchSid */ + SeBatchSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeBatchSid == NULL) + return(FALSE); + + RtlInitializeSid(SeBatchSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeBatchSid, + 0); + *SubAuthority = SECURITY_BATCH_RID; + + /* create InteractiveSid */ + SeInteractiveSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeInteractiveSid == NULL) + return(FALSE); + + RtlInitializeSid(SeInteractiveSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeInteractiveSid, + 0); + *SubAuthority = SECURITY_INTERACTIVE_RID; + + /* create ServiceSid */ + SeServiceSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeServiceSid == NULL) + return(FALSE); + + RtlInitializeSid(SeServiceSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeServiceSid, + 0); + *SubAuthority = SECURITY_SERVICE_RID; + + /* create AnonymousLogonSid */ + SeAnonymousLogonSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeAnonymousLogonSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAnonymousLogonSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeAnonymousLogonSid, + 0); + *SubAuthority = SECURITY_ANONYMOUS_LOGON_RID; + + /* create PrincipalSelfSid */ + SePrincipalSelfSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SePrincipalSelfSid == NULL) + return(FALSE); + + RtlInitializeSid(SePrincipalSelfSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SePrincipalSelfSid, + 0); + *SubAuthority = SECURITY_PRINCIPAL_SELF_RID; + + /* create LocalSystemSid */ + SeLocalSystemSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeLocalSystemSid == NULL) + return(FALSE); + + RtlInitializeSid(SeLocalSystemSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeLocalSystemSid, + 0); + *SubAuthority = SECURITY_LOCAL_SYSTEM_RID; + + /* create AuthenticatedUserSid */ + SeAuthenticatedUserSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeAuthenticatedUserSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAuthenticatedUserSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeAuthenticatedUserSid, + 0); + *SubAuthority = SECURITY_AUTHENTICATED_USER_RID; + + /* create RestrictedCodeSid */ + SeRestrictedCodeSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength1, + TAG_SID); + if (SeRestrictedCodeSid == NULL) + return(FALSE); + + RtlInitializeSid(SeRestrictedCodeSid, + &SeNtSidAuthority, + 1); + SubAuthority = RtlSubAuthoritySid(SeRestrictedCodeSid, + 0); + *SubAuthority = SECURITY_RESTRICTED_CODE_RID; + + /* create AliasAdminsSid */ + SeAliasAdminsSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasAdminsSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasAdminsSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasAdminsSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasAdminsSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_ADMINS; + + /* create AliasUsersSid */ + SeAliasUsersSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasUsersSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasUsersSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasUsersSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasUsersSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_USERS; + + /* create AliasGuestsSid */ + SeAliasGuestsSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasGuestsSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasGuestsSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasGuestsSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasGuestsSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_GUESTS; + + /* create AliasPowerUsersSid */ + SeAliasPowerUsersSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasPowerUsersSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasPowerUsersSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasPowerUsersSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasPowerUsersSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_POWER_USERS; + + /* create AliasAccountOpsSid */ + SeAliasAccountOpsSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasAccountOpsSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasAccountOpsSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasAccountOpsSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasAccountOpsSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_ACCOUNT_OPS; + + /* create AliasSystemOpsSid */ + SeAliasSystemOpsSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasSystemOpsSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasSystemOpsSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasSystemOpsSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasSystemOpsSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_SYSTEM_OPS; + + /* create AliasPrintOpsSid */ + SeAliasPrintOpsSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasPrintOpsSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasPrintOpsSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasPrintOpsSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasPrintOpsSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_PRINT_OPS; + + /* create AliasBackupOpsSid */ + SeAliasBackupOpsSid = ExAllocatePoolWithTag(NonPagedPool, + SidLength2, + TAG_SID); + if (SeAliasBackupOpsSid == NULL) + return(FALSE); + + RtlInitializeSid(SeAliasBackupOpsSid, + &SeNtSidAuthority, + 2); + SubAuthority = RtlSubAuthoritySid(SeAliasBackupOpsSid, + 0); + *SubAuthority = SECURITY_BUILTIN_DOMAIN_RID; + + SubAuthority = RtlSubAuthoritySid(SeAliasBackupOpsSid, + 1); + *SubAuthority = DOMAIN_ALIAS_RID_BACKUP_OPS; + + return(TRUE); +} + + +BOOLEAN STDCALL +RtlValidSid(PSID Sid) +{ + if ((Sid->Revision & 0xf) != 1) + { + return(FALSE); + } + if (Sid->SubAuthorityCount > 15) + { + return(FALSE); + } + return(TRUE); +} + + +ULONG STDCALL +RtlLengthRequiredSid(UCHAR SubAuthorityCount) +{ + return(sizeof(SID) + (SubAuthorityCount - 1) * sizeof(ULONG)); +} + + +NTSTATUS STDCALL +RtlInitializeSid(PSID Sid, + PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, + UCHAR SubAuthorityCount) +{ + Sid->Revision = 1; + Sid->SubAuthorityCount = SubAuthorityCount; + RtlCopyMemory(&Sid->IdentifierAuthority, + IdentifierAuthority, + sizeof(SID_IDENTIFIER_AUTHORITY)); + return(STATUS_SUCCESS); +} + + +PULONG STDCALL +RtlSubAuthoritySid(PSID Sid, + ULONG SubAuthority) +{ + return(&Sid->SubAuthority[SubAuthority]); +} + + +PUCHAR STDCALL +RtlSubAuthorityCountSid(PSID Sid) +{ + return(&Sid->SubAuthorityCount); +} + + +BOOLEAN STDCALL +RtlEqualSid(PSID Sid1, + PSID Sid2) +{ + if (Sid1->Revision != Sid2->Revision) + { + return(FALSE); + } + if ((*RtlSubAuthorityCountSid(Sid1)) != + (*RtlSubAuthorityCountSid(Sid2))) + { + return(FALSE); + } + if (memcmp(Sid1, Sid2, RtlLengthSid(Sid1)) != 0) + { + return(FALSE); + } + return(TRUE); +} + + +ULONG STDCALL +RtlLengthSid(PSID Sid) +{ + return(sizeof(SID) + (Sid->SubAuthorityCount-1)*4); +} + + +NTSTATUS STDCALL +RtlCopySid(ULONG BufferLength, + PSID Dest, + PSID Src) +{ + if (BufferLength < RtlLengthSid(Src)) + { + return(STATUS_UNSUCCESSFUL); + } + memmove(Dest, Src, RtlLengthSid(Src)); + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlCopySidAndAttributesArray(ULONG Count, + PSID_AND_ATTRIBUTES Src, + ULONG SidAreaSize, + PSID_AND_ATTRIBUTES Dest, + PVOID SidArea, + PVOID* RemainingSidArea, + PULONG RemainingSidAreaSize) +{ + ULONG Length; + ULONG i; + + Length = SidAreaSize; + + for (i=0; i Length) + { + return(STATUS_BUFFER_TOO_SMALL); + } + Length = Length - RtlLengthSid(Src[i].Sid); + Dest[i].Sid = SidArea; + Dest[i].Attributes = Src[i].Attributes; + RtlCopySid(RtlLengthSid(Src[i].Sid), SidArea, Src[i].Sid); + SidArea = SidArea + RtlLengthSid(Src[i].Sid); + } + *RemainingSidArea = SidArea; + *RemainingSidAreaSize = Length; + return(STATUS_SUCCESS); +} + + +NTSTATUS STDCALL +RtlConvertSidToUnicodeString(PUNICODE_STRING String, + PSID Sid, + BOOLEAN AllocateString) +{ + WCHAR Buffer[256]; + PWSTR Ptr; + ULONG Length; + ULONG i; + + if (!RtlValidSid(Sid)) + return STATUS_INVALID_SID; + + Ptr = Buffer; + Ptr += swprintf (Ptr, + L"S-%u-", + Sid->Revision); + + if(!Sid->IdentifierAuthority.Value[0] && + !Sid->IdentifierAuthority.Value[1]) + { + Ptr += swprintf(Ptr, + L"%u", + (ULONG)Sid->IdentifierAuthority.Value[2] << 24 | + (ULONG)Sid->IdentifierAuthority.Value[3] << 16 | + (ULONG)Sid->IdentifierAuthority.Value[4] << 8 | + (ULONG)Sid->IdentifierAuthority.Value[5]); + } + else + { + Ptr += swprintf(Ptr, + L"0x%02hx%02hx%02hx%02hx%02hx%02hx", + Sid->IdentifierAuthority.Value[0], + Sid->IdentifierAuthority.Value[1], + Sid->IdentifierAuthority.Value[2], + Sid->IdentifierAuthority.Value[3], + Sid->IdentifierAuthority.Value[4], + Sid->IdentifierAuthority.Value[5]); + } + + for (i = 0; i < Sid->SubAuthorityCount; i++) + { + Ptr += swprintf(Ptr, + L"-%u", + Sid->SubAuthority[i]); + } + + Length = (Ptr - Buffer) * sizeof(WCHAR); + + if (AllocateString) + { + String->Buffer = ExAllocatePool(NonPagedPool, + Length + sizeof(WCHAR)); + if (String->Buffer == NULL) + return STATUS_NO_MEMORY; + + String->MaximumLength = Length + sizeof(WCHAR); + } + else + { + if (Length > String->MaximumLength) + return STATUS_BUFFER_TOO_SMALL; + } + String->Length = Length; + memmove(String->Buffer, + Buffer, + Length); + if (Length < String->MaximumLength) + String->Buffer[Length] = 0; + + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c new file mode 100644 index 0000000..1bb70c5 --- /dev/null +++ b/ntoskrnl/se/token.c @@ -0,0 +1,1286 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Security manager + * FILE: kernel/se/token.c + * PROGRAMER: David Welch + * REVISION HISTORY: + * 26/07/98: Added stubs for security functions + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +POBJECT_TYPE SepTokenObjectType = NULL; + +static GENERIC_MAPPING SepTokenMapping = {TOKEN_READ, + TOKEN_WRITE, + TOKEN_EXECUTE, + TOKEN_ALL_ACCESS}; + +#define SYSTEM_LUID 0x3E7; + +/* FUNCTIONS *****************************************************************/ + +VOID SepFreeProxyData(PVOID ProxyData) +{ + UNIMPLEMENTED; +} + +NTSTATUS SepCopyProxyData(PVOID* Dest, PVOID Src) +{ + UNIMPLEMENTED; +} + +NTSTATUS SeExchangePrimaryToken(PEPROCESS Process, + PACCESS_TOKEN NewToken, + PACCESS_TOKEN* OldTokenP) +{ + PACCESS_TOKEN OldToken; + + if (NewToken->TokenType != TokenPrimary) + { + return(STATUS_UNSUCCESSFUL); + } + if (NewToken->TokenInUse != 0) + { + return(STATUS_UNSUCCESSFUL); + } + OldToken = Process->Token; + Process->Token = NewToken; + NewToken->TokenInUse = 1; + ObReferenceObjectByPointer(NewToken, + TOKEN_ALL_ACCESS, + SepTokenObjectType, + KernelMode); + OldToken->TokenInUse = 0; + *OldTokenP = OldToken; + return(STATUS_SUCCESS); +} + +static ULONG +RtlLengthSidAndAttributes(ULONG Count, + PSID_AND_ATTRIBUTES Src) +{ + ULONG i; + ULONG uLength; + + uLength = Count * sizeof(SID_AND_ATTRIBUTES); + for (i = 0; i < Count; i++) + uLength += RtlLengthSid(Src[i].Sid); + + return(uLength); +} + + +NTSTATUS +SepFindPrimaryGroupAndDefaultOwner(PACCESS_TOKEN Token, + PSID PrimaryGroup, + PSID DefaultOwner) +{ + ULONG i; + + Token->PrimaryGroup = 0; + + if (DefaultOwner) + { + Token->DefaultOwnerIndex = Token->UserAndGroupCount; + } + + /* Validate and set the primary group and user pointers */ + for (i = 0; i < Token->UserAndGroupCount; i++) + { + if (DefaultOwner && + RtlEqualSid(Token->UserAndGroups[i].Sid, DefaultOwner)) + { + Token->DefaultOwnerIndex = i; + } + + if (RtlEqualSid(Token->UserAndGroups[i].Sid, PrimaryGroup)) + { + Token->PrimaryGroup = Token->UserAndGroups[i].Sid; + } + } + + if (Token->DefaultOwnerIndex == Token->UserAndGroupCount) + { + return(STATUS_INVALID_OWNER); + } + + if (Token->PrimaryGroup == 0) + { + return(STATUS_INVALID_PRIMARY_GROUP); + } + + return(STATUS_SUCCESS); +} + + +NTSTATUS +SepDuplicateToken(PACCESS_TOKEN Token, + POBJECT_ATTRIBUTES ObjectAttributes, + TOKEN_TYPE TokenType, + SECURITY_IMPERSONATION_LEVEL Level, + SECURITY_IMPERSONATION_LEVEL ExistingLevel, + KPROCESSOR_MODE PreviousMode, + PACCESS_TOKEN* NewAccessToken) +{ + NTSTATUS Status; + ULONG uLength; + ULONG i; + + PVOID EndMem; + + PACCESS_TOKEN AccessToken; + + Status = ObCreateObject(0, + TOKEN_ALL_ACCESS, + ObjectAttributes, + SepTokenObjectType, + (PVOID*)&AccessToken); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ObCreateObject() failed (Status %lx)\n"); + return(Status); + } + + Status = ZwAllocateLocallyUniqueId(&AccessToken->TokenId); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(AccessToken); + return(Status); + } + + Status = ZwAllocateLocallyUniqueId(&AccessToken->ModifiedId); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(AccessToken); + return(Status); + } + + AccessToken->TokenInUse = 0; + AccessToken->TokenType = TokenType; + AccessToken->ImpersonationLevel = Level; + AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID; + + AccessToken->TokenSource.SourceIdentifier.QuadPart = Token->TokenSource.SourceIdentifier.QuadPart; + memcpy(AccessToken->TokenSource.SourceName, Token->TokenSource.SourceName, sizeof(Token->TokenSource.SourceName)); + AccessToken->ExpirationTime.QuadPart = Token->ExpirationTime.QuadPart; + AccessToken->UserAndGroupCount = Token->UserAndGroupCount; + AccessToken->DefaultOwnerIndex = Token->DefaultOwnerIndex; + + uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount; + for (i = 0; i < Token->UserAndGroupCount; i++) + uLength += RtlLengthSid(Token->UserAndGroups[i].Sid); + + AccessToken->UserAndGroups = + (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool, + uLength, + TAG('T', 'O', 'K', 'u')); + + EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount]; + + Status = RtlCopySidAndAttributesArray(AccessToken->UserAndGroupCount, + Token->UserAndGroups, + uLength, + AccessToken->UserAndGroups, + EndMem, + &EndMem, + &uLength); + if (NT_SUCCESS(Status)) + { + Status = SepFindPrimaryGroupAndDefaultOwner( + AccessToken, + Token->PrimaryGroup, + 0); + } + + if (NT_SUCCESS(Status)) + { + AccessToken->PrivilegeCount = Token->PrivilegeCount; + + uLength = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); + AccessToken->Privileges = + (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool, + uLength, + TAG('T', 'O', 'K', 'p')); + + for (i = 0; i < AccessToken->PrivilegeCount; i++) + { + RtlCopyLuid(&AccessToken->Privileges[i].Luid, + &Token->Privileges[i].Luid); + AccessToken->Privileges[i].Attributes = + Token->Privileges[i].Attributes; + } + + if ( Token->DefaultDacl ) + { + AccessToken->DefaultDacl = + (PACL) ExAllocatePoolWithTag(NonPagedPool, + Token->DefaultDacl->AclSize, + TAG('T', 'O', 'K', 'd')); + memcpy(AccessToken->DefaultDacl, + Token->DefaultDacl, + Token->DefaultDacl->AclSize); + } + else + { + AccessToken->DefaultDacl = 0; + } + } + + if ( NT_SUCCESS(Status) ) + { + *NewAccessToken = AccessToken; + return(STATUS_SUCCESS); + } + + ObDereferenceObject(AccessToken); + return(Status); +} + + +NTSTATUS +SepInitializeNewProcess(struct _EPROCESS* NewProcess, + struct _EPROCESS* ParentProcess) +{ + NTSTATUS Status; + PACCESS_TOKEN pNewToken; + PACCESS_TOKEN pParentToken; + + OBJECT_ATTRIBUTES ObjectAttributes; + + pParentToken = (PACCESS_TOKEN) ParentProcess->Token; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + + Status = SepDuplicateToken(pParentToken, + &ObjectAttributes, + TokenPrimary, + pParentToken->ImpersonationLevel, + pParentToken->ImpersonationLevel, + KernelMode, + &pNewToken); + if ( ! NT_SUCCESS(Status) ) + return Status; + + NewProcess->Token = pNewToken; + return(STATUS_SUCCESS); +} + + +NTSTATUS SeCopyClientToken(PACCESS_TOKEN Token, + SECURITY_IMPERSONATION_LEVEL Level, + KPROCESSOR_MODE PreviousMode, + PACCESS_TOKEN* NewToken) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + Status = SepDuplicateToken(Token, + &ObjectAttributes, + 0, + SecurityIdentification, + Level, + PreviousMode, + NewToken); + return(Status); +} + + +NTSTATUS STDCALL +SeCreateClientSecurity(IN struct _ETHREAD *Thread, + IN PSECURITY_QUALITY_OF_SERVICE Qos, + IN BOOLEAN RemoteClient, + OUT PSECURITY_CLIENT_CONTEXT ClientContext) +{ + TOKEN_TYPE TokenType; + UCHAR b; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + PACCESS_TOKEN Token; + ULONG g; + PACCESS_TOKEN NewToken; + + Token = PsReferenceEffectiveToken(Thread, + &TokenType, + &b, + &ImpersonationLevel); + if (TokenType != 2) + { + ClientContext->DirectAccessEffectiveOnly = Qos->EffectiveOnly; + } + else + { + if (Qos->ImpersonationLevel > ImpersonationLevel) + { + if (Token != NULL) + { + ObDereferenceObject(Token); + } + return(STATUS_UNSUCCESSFUL); + } + if (ImpersonationLevel == 0 || + ImpersonationLevel == 1 || + (RemoteClient != FALSE && ImpersonationLevel != 3)) + { + if (Token != NULL) + { + ObDereferenceObject(Token); + } + return(STATUS_UNSUCCESSFUL); + } + if (b != 0 || + Qos->EffectiveOnly != 0) + { + ClientContext->DirectAccessEffectiveOnly = TRUE; + } + else + { + ClientContext->DirectAccessEffectiveOnly = FALSE; + } + } + + if (Qos->ContextTrackingMode == 0) + { + ClientContext->DirectlyAccessClientToken = FALSE; + g = SeCopyClientToken(Token, ImpersonationLevel, 0, &NewToken); + if (g >= 0) + { +// ObDeleteCapturedInsertInfo(NewToken); + } + if (TokenType == TokenPrimary || Token != NULL) + { + ObDereferenceObject(Token); + } + if (g < 0) + { + return(g); + } + } + else + { + ClientContext->DirectlyAccessClientToken = TRUE; + if (RemoteClient != FALSE) + { +// SeGetTokenControlInformation(Token, &ClientContext->Unknown11); + } + NewToken = Token; + } + ClientContext->SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + ClientContext->SecurityQos.ImpersonationLevel = Qos->ImpersonationLevel; + ClientContext->SecurityQos.ContextTrackingMode = Qos->ContextTrackingMode; + ClientContext->SecurityQos.EffectiveOnly = Qos->EffectiveOnly; + ClientContext->ServerIsRemote = RemoteClient; + ClientContext->Token = NewToken; + + return(STATUS_SUCCESS); +} + + +VOID STDCALL +SeImpersonateClient(IN PSECURITY_CLIENT_CONTEXT ClientContext, + IN PETHREAD ServerThread OPTIONAL) +{ + UCHAR b; + + if (ClientContext->DirectlyAccessClientToken == FALSE) + { + b = ClientContext->SecurityQos.EffectiveOnly; + } + else + { + b = ClientContext->DirectAccessEffectiveOnly; + } + if (ServerThread == NULL) + { + ServerThread = PsGetCurrentThread(); + } + PsImpersonateClient(ServerThread, + ClientContext->Token, + 1, + (ULONG)b, + ClientContext->SecurityQos.ImpersonationLevel); +} + + +VOID STDCALL +SepDeleteToken(PVOID ObjectBody) +{ + PACCESS_TOKEN AccessToken = (PACCESS_TOKEN)ObjectBody; + + if (AccessToken->UserAndGroups) + ExFreePool(AccessToken->UserAndGroups); + + if (AccessToken->Privileges) + ExFreePool(AccessToken->Privileges); + + if (AccessToken->DefaultDacl) + ExFreePool(AccessToken->DefaultDacl); +} + + +VOID +SepInitializeTokenImplementation(VOID) +{ + SepTokenObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); + + SepTokenObjectType->Tag = TAG('T', 'O', 'K', 'T'); + SepTokenObjectType->MaxObjects = ULONG_MAX; + SepTokenObjectType->MaxHandles = ULONG_MAX; + SepTokenObjectType->TotalObjects = 0; + SepTokenObjectType->TotalHandles = 0; + SepTokenObjectType->PagedPoolCharge = 0; + SepTokenObjectType->NonpagedPoolCharge = sizeof(ACCESS_TOKEN); + SepTokenObjectType->Mapping = &SepTokenMapping; + SepTokenObjectType->Dump = NULL; + SepTokenObjectType->Open = NULL; + SepTokenObjectType->Close = NULL; + SepTokenObjectType->Delete = SepDeleteToken; + SepTokenObjectType->Parse = NULL; + SepTokenObjectType->Security = NULL; + SepTokenObjectType->QueryName = NULL; + SepTokenObjectType->OkayToClose = NULL; + SepTokenObjectType->Create = NULL; + SepTokenObjectType->DuplicationNotify = NULL; + + RtlCreateUnicodeString(&SepTokenObjectType->TypeName, + L"Token"); +} + + +NTSTATUS STDCALL +NtQueryInformationToken(IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength) +{ + NTSTATUS Status; + PACCESS_TOKEN Token; + PVOID UnusedInfo; + PVOID EndMem; + PTOKEN_GROUPS PtrTokenGroups; + PTOKEN_DEFAULT_DACL PtrDefaultDacl; + PTOKEN_STATISTICS PtrTokenStatistics; + ULONG uLength; + + Status = ObReferenceObjectByHandle(TokenHandle, + (TokenInformationClass == TokenSource) ? TOKEN_QUERY_SOURCE : TOKEN_QUERY, + SepTokenObjectType, + UserMode, + (PVOID*)&Token, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + switch (TokenInformationClass) + { + case TokenUser: + DPRINT("NtQueryInformationToken(TokenUser)\n"); + uLength = RtlLengthSidAndAttributes(1, Token->UserAndGroups); + if (TokenInformationLength < uLength) + { + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + Status = RtlCopySidAndAttributesArray(1, + Token->UserAndGroups, + TokenInformationLength, + TokenInformation, + TokenInformation + 8, + &UnusedInfo, + &uLength); + if (NT_SUCCESS(Status)) + { + uLength = TokenInformationLength - uLength; + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + } + } + break; + + case TokenGroups: + DPRINT("NtQueryInformationToken(TokenGroups)\n"); + uLength = RtlLengthSidAndAttributes(Token->UserAndGroupCount - 1, &Token->UserAndGroups[1]) + sizeof(DWORD); + if (TokenInformationLength < uLength) + { + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + EndMem = TokenInformation + Token->UserAndGroupCount * sizeof(SID_AND_ATTRIBUTES); + PtrTokenGroups = (PTOKEN_GROUPS)TokenInformation; + PtrTokenGroups->GroupCount = Token->UserAndGroupCount - 1; + Status = RtlCopySidAndAttributesArray(Token->UserAndGroupCount - 1, + &Token->UserAndGroups[1], + TokenInformationLength, + PtrTokenGroups->Groups, + EndMem, + &UnusedInfo, + &uLength); + if (NT_SUCCESS(Status)) + { + uLength = TokenInformationLength - uLength; + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + } + } + break; + + case TokenPrivileges: + DPRINT("NtQueryInformationToken(TokenPrivileges)\n"); + uLength = sizeof(DWORD) + Token->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); + if (TokenInformationLength < uLength) + { + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + ULONG i; + TOKEN_PRIVILEGES* pPriv = (TOKEN_PRIVILEGES*)TokenInformation; + + pPriv->PrivilegeCount = Token->PrivilegeCount; + for (i = 0; i < Token->PrivilegeCount; i++) + { + RtlCopyLuid(&pPriv->Privileges[i].Luid, &Token->Privileges[i].Luid); + pPriv->Privileges[i].Attributes = Token->Privileges[i].Attributes; + } + Status = STATUS_SUCCESS; + } + break; + + case TokenOwner: + DPRINT("NtQueryInformationToken(TokenOwner)\n"); + uLength = RtlLengthSid(Token->UserAndGroups[Token->DefaultOwnerIndex].Sid) + sizeof(TOKEN_OWNER); + if (TokenInformationLength < uLength) + { + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + ((PTOKEN_OWNER)TokenInformation)->Owner = + (PSID)(((PTOKEN_OWNER)TokenInformation) + 1); + RtlCopySid(TokenInformationLength - sizeof(TOKEN_OWNER), + ((PTOKEN_OWNER)TokenInformation)->Owner, + Token->UserAndGroups[Token->DefaultOwnerIndex].Sid); + Status = STATUS_SUCCESS; + } + break; + + case TokenPrimaryGroup: + DPRINT("NtQueryInformationToken(TokenPrimaryGroup)," + "Token->PrimaryGroup = 0x%08x\n", Token->PrimaryGroup); + uLength = RtlLengthSid(Token->PrimaryGroup) + sizeof(TOKEN_PRIMARY_GROUP); + if (TokenInformationLength < uLength) + { + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup = + (PSID)(((PTOKEN_PRIMARY_GROUP)TokenInformation) + 1); + RtlCopySid(TokenInformationLength - sizeof(TOKEN_PRIMARY_GROUP), + ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup, + Token->PrimaryGroup); + Status = STATUS_SUCCESS; + } + break; + + case TokenDefaultDacl: + DPRINT("NtQueryInformationToken(TokenDefaultDacl)\n"); + PtrDefaultDacl = (PTOKEN_DEFAULT_DACL) TokenInformation; + uLength = (Token->DefaultDacl ? Token->DefaultDacl->AclSize : 0) + sizeof(TOKEN_DEFAULT_DACL); + if (TokenInformationLength < uLength) + { + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else if (!Token->DefaultDacl) + { + PtrDefaultDacl->DefaultDacl = 0; + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + } + else + { + PtrDefaultDacl->DefaultDacl = (PACL) (PtrDefaultDacl + 1); + memmove(PtrDefaultDacl->DefaultDacl, + Token->DefaultDacl, + Token->DefaultDacl->AclSize); + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + } + break; + + case TokenSource: + DPRINT("NtQueryInformationToken(TokenSource)\n"); + if (TokenInformationLength < sizeof(TOKEN_SOURCE)) + { + uLength = sizeof(TOKEN_SOURCE); + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + Status = MmCopyToCaller(TokenInformation, &Token->TokenSource, sizeof(TOKEN_SOURCE)); + } + break; + + case TokenType: + DPRINT("NtQueryInformationToken(TokenType)\n"); + if (TokenInformationLength < sizeof(TOKEN_TYPE)) + { + uLength = sizeof(TOKEN_TYPE); + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + Status = MmCopyToCaller(TokenInformation, &Token->TokenType, sizeof(TOKEN_TYPE)); + } + break; + + case TokenImpersonationLevel: + DPRINT("NtQueryInformationToken(TokenImpersonationLevel)\n"); + if (TokenInformationLength < sizeof(SECURITY_IMPERSONATION_LEVEL)) + { + uLength = sizeof(SECURITY_IMPERSONATION_LEVEL); + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + Status = MmCopyToCaller(TokenInformation, &Token->ImpersonationLevel, sizeof(SECURITY_IMPERSONATION_LEVEL)); + } + break; + + case TokenStatistics: + DPRINT("NtQueryInformationToken(TokenStatistics)\n"); + if (TokenInformationLength < sizeof(TOKEN_STATISTICS)) + { + uLength = sizeof(TOKEN_STATISTICS); + Status = MmCopyToCaller(ReturnLength, &uLength, sizeof(ULONG)); + if (NT_SUCCESS(Status)) + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + PtrTokenStatistics = (PTOKEN_STATISTICS)TokenInformation; + PtrTokenStatistics->TokenId = Token->TokenId; + PtrTokenStatistics->AuthenticationId = Token->AuthenticationId; + PtrTokenStatistics->ExpirationTime = Token->ExpirationTime; + PtrTokenStatistics->TokenType = Token->TokenType; + PtrTokenStatistics->ImpersonationLevel = Token->ImpersonationLevel; + PtrTokenStatistics->DynamicCharged = Token->DynamicCharged; + PtrTokenStatistics->DynamicAvailable = Token->DynamicAvailable; + PtrTokenStatistics->GroupCount = Token->UserAndGroupCount - 1; + PtrTokenStatistics->PrivilegeCount = Token->PrivilegeCount; + PtrTokenStatistics->ModifiedId = Token->ModifiedId; + + Status = STATUS_SUCCESS; + } + break; + } + + ObDereferenceObject(Token); + + return(Status); +} + + +NTSTATUS STDCALL +NtSetInformationToken(IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtDuplicateToken(IN HANDLE ExistingTokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + IN TOKEN_TYPE TokenType, + OUT PHANDLE NewTokenHandle) +{ +#if 0 + PACCESS_TOKEN Token; + PACCESS_TOKEN NewToken; + NTSTATUS Status; + ULONG ExistingImpersonationLevel; + + Status = ObReferenceObjectByHandle(ExistingTokenHandle, + TOKEN_DUPLICATE, + SepTokenObjectType, + UserMode, + (PVOID*)&Token, + NULL); + + ExistingImpersonationLevel = Token->ImpersonationLevel; + SepDuplicateToken(Token, + ObjectAttributes, + ImpersonationLevel, + TokenType, + ExistingImpersonationLevel, + KeGetPreviousMode(), + &NewToken); +#else + UNIMPLEMENTED; +#endif +} + +VOID SepAdjustGroups(PACCESS_TOKEN Token, + ULONG a, + BOOLEAN ResetToDefault, + PSID_AND_ATTRIBUTES Groups, + ULONG b, + KPROCESSOR_MODE PreviousMode, + ULONG c, + PULONG d, + PULONG e, + PULONG f) +{ + UNIMPLEMENTED; +} + + +NTSTATUS STDCALL +NtAdjustGroupsToken(IN HANDLE TokenHandle, + IN BOOLEAN ResetToDefault, + IN PTOKEN_GROUPS NewState, + IN ULONG BufferLength, + OUT PTOKEN_GROUPS PreviousState OPTIONAL, + OUT PULONG ReturnLength) +{ +#if 0 + NTSTATUS Status; + PACCESS_TOKEN Token; + ULONG a; + ULONG b; + ULONG c; + + Status = ObReferenceObjectByHandle(TokenHandle, + ?, + SepTokenObjectType, + UserMode, + (PVOID*)&Token, + NULL); + + + SepAdjustGroups(Token, + 0, + ResetToDefault, + NewState->Groups, + ?, + PreviousState, + 0, + &a, + &b, + &c); +#else + UNIMPLEMENTED; +#endif +} + + +#if 0 +NTSTATUS SepAdjustPrivileges(PACCESS_TOKEN Token, // 0x8 + ULONG a, // 0xC + KPROCESSOR_MODE PreviousMode, // 0x10 + ULONG PrivilegeCount, // 0x14 + PLUID_AND_ATTRIBUTES Privileges, // 0x18 + PTOKEN_PRIVILEGES* PreviousState, // 0x1C + PULONG b, // 0x20 + PULONG c, // 0x24 + PULONG d) // 0x28 +{ + ULONG i; + + *c = 0; + if (Token->PrivilegeCount > 0) + { + for (i=0; iPrivilegeCount; i++) + { + if (PreviousMode != 0) + { + if (!(Token->Privileges[i]->Attributes & + SE_PRIVILEGE_ENABLED)) + { + if (a != 0) + { + if (PreviousState != NULL) + { + memcpy(&PreviousState[i], + &Token->Privileges[i], + sizeof(LUID_AND_ATTRIBUTES)); + } + Token->Privileges[i].Attributes = + Token->Privileges[i].Attributes & + (~SE_PRIVILEGE_ENABLED); + } + } + } + } + } + if (PreviousMode != 0) + { + Token->TokenFlags = Token->TokenFlags & (~1); + } + else + { + if (PrivilegeCount <= ?) + { + + } + } + if ( +} +#endif + + +NTSTATUS STDCALL +NtAdjustPrivilegesToken(IN HANDLE TokenHandle, + IN BOOLEAN DisableAllPrivileges, + IN PTOKEN_PRIVILEGES NewState, + IN ULONG BufferLength, + OUT PTOKEN_PRIVILEGES PreviousState, + OUT PULONG ReturnLength) +{ +#if 0 + ULONG PrivilegeCount; + ULONG Length; + PSID_AND_ATTRIBUTES Privileges; + ULONG a; + ULONG b; + ULONG c; + + PrivilegeCount = NewState->PrivilegeCount; + + SeCaptureLuidAndAttributesArray(NewState->Privileges, + &PrivilegeCount, + KeGetPreviousMode(), + NULL, + 0, + NonPagedPool, + 1, + &Privileges. + &Length); + SepAdjustPrivileges(Token, + 0, + KeGetPreviousMode(), + PrivilegeCount, + Privileges, + PreviousState, + &a, + &b, + &c); +#else + UNIMPLEMENTED; +#endif +} + + +NTSTATUS +SepCreateSystemProcessToken(struct _EPROCESS* Process) +{ + NTSTATUS Status; + ULONG uSize; + ULONG i; + + ULONG uLocalSystemLength = RtlLengthSid(SeLocalSystemSid); + ULONG uWorldLength = RtlLengthSid(SeWorldSid); + ULONG uAuthUserLength = RtlLengthSid(SeAuthenticatedUserSid); + ULONG uAdminsLength = RtlLengthSid(SeAliasAdminsSid); + + PACCESS_TOKEN AccessToken; + + PVOID SidArea; + + /* + * Initialize the token + */ + Status = ObCreateObject(NULL, + TOKEN_ALL_ACCESS, + NULL, + SepTokenObjectType, + (PVOID*)&AccessToken); + + Status = NtAllocateLocallyUniqueId(&AccessToken->TokenId); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(AccessToken); + return(Status); + } + + Status = NtAllocateLocallyUniqueId(&AccessToken->ModifiedId); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(AccessToken); + return(Status); + } + + AccessToken->AuthenticationId.QuadPart = SYSTEM_LUID; + + AccessToken->TokenType = TokenPrimary; + AccessToken->ImpersonationLevel = SecurityDelegation; + AccessToken->TokenSource.SourceIdentifier.QuadPart = 0; + memcpy(AccessToken->TokenSource.SourceName, "SeMgr\0\0\0", 8); + AccessToken->ExpirationTime.QuadPart = -1; + AccessToken->UserAndGroupCount = 4; + + uSize = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount; + uSize += uLocalSystemLength; + uSize += uWorldLength; + uSize += uAuthUserLength; + uSize += uAdminsLength; + + AccessToken->UserAndGroups = + (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool, + uSize, + TAG('T', 'O', 'K', 'u')); + SidArea = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount]; + + i = 0; + AccessToken->UserAndGroups[i].Sid = (PSID) SidArea; + AccessToken->UserAndGroups[i++].Attributes = 0; + RtlCopySid(uLocalSystemLength, SidArea, SeLocalSystemSid); + SidArea += uLocalSystemLength; + + AccessToken->DefaultOwnerIndex = i; + AccessToken->UserAndGroups[i].Sid = (PSID) SidArea; + AccessToken->PrimaryGroup = (PSID) SidArea; + AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT; + Status = RtlCopySid(uAdminsLength, SidArea, SeAliasAdminsSid); + SidArea += uAdminsLength; + + AccessToken->UserAndGroups[i].Sid = (PSID) SidArea; + AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY; + RtlCopySid(uWorldLength, SidArea, SeWorldSid); + SidArea += uWorldLength; + + AccessToken->UserAndGroups[i].Sid = (PSID) SidArea; + AccessToken->UserAndGroups[i++].Attributes = SE_GROUP_ENABLED|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_MANDATORY; + RtlCopySid(uAuthUserLength, SidArea, SeAuthenticatedUserSid); + SidArea += uAuthUserLength; + + AccessToken->PrivilegeCount = 20; + + uSize = AccessToken->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); + AccessToken->Privileges = + (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool, + uSize, + TAG('T', 'O', 'K', 'p')); + + i = 0; + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeTcbPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeCreateTokenPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeTakeOwnershipPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeCreatePagefilePrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeLockMemoryPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeAssignPrimaryTokenPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeIncreaseQuotaPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeIncreaseBasePriorityPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeCreatePermanentPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeDebugPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeAuditPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeSecurityPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeSystemEnvironmentPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeChangeNotifyPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeBackupPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeRestorePrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeShutdownPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeLoadDriverPrivilege; + + AccessToken->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED; + AccessToken->Privileges[i++].Luid = SeProfileSingleProcessPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeSystemtimePrivilege; +#if 0 + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeUndockPrivilege; + + AccessToken->Privileges[i].Attributes = 0; + AccessToken->Privileges[i++].Luid = SeManageVolumePrivilege; +#endif + + assert( i == 20 ); + + uSize = sizeof(ACL); + uSize += sizeof(ACE) + uLocalSystemLength; + uSize += sizeof(ACE) + uAdminsLength; + uSize = (uSize & (~3)) + 8; + AccessToken->DefaultDacl = + (PACL) ExAllocatePoolWithTag(NonPagedPool, + uSize, + TAG('T', 'O', 'K', 'd')); + Status = RtlCreateAcl(AccessToken->DefaultDacl, uSize, ACL_REVISION); + if ( NT_SUCCESS(Status) ) + { + Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_ALL, SeLocalSystemSid); + } + + if ( NT_SUCCESS(Status) ) + { + Status = RtlAddAccessAllowedAce(AccessToken->DefaultDacl, ACL_REVISION, GENERIC_READ|GENERIC_EXECUTE|READ_CONTROL, SeAliasAdminsSid); + } + + if ( ! NT_SUCCESS(Status) ) + { + ObDereferenceObject(AccessToken); + return Status; + } + + Process->Token = AccessToken; + return(STATUS_SUCCESS); +} + +NTSTATUS STDCALL +NtCreateToken(OUT PHANDLE UnsafeTokenHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES UnsafeObjectAttributes, + IN TOKEN_TYPE TokenType, + IN PLUID AuthenticationId, + IN PLARGE_INTEGER ExpirationTime, + IN PTOKEN_USER TokenUser, + IN PTOKEN_GROUPS TokenGroups, + IN PTOKEN_PRIVILEGES TokenPrivileges, + IN PTOKEN_OWNER TokenOwner, + IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup, + IN PTOKEN_DEFAULT_DACL TokenDefaultDacl, + IN PTOKEN_SOURCE TokenSource) +{ + HANDLE TokenHandle; + PACCESS_TOKEN AccessToken; + NTSTATUS Status; + OBJECT_ATTRIBUTES SafeObjectAttributes; + POBJECT_ATTRIBUTES ObjectAttributes; + LUID TokenId; + LUID ModifiedId; + PVOID EndMem; + ULONG uLength; + ULONG i; + + Status = MmCopyFromCaller(&SafeObjectAttributes, + UnsafeObjectAttributes, + sizeof(OBJECT_ATTRIBUTES)); + if (!NT_SUCCESS(Status)) + return(Status); + + ObjectAttributes = &SafeObjectAttributes; + + Status = ZwAllocateLocallyUniqueId(&TokenId); + if (!NT_SUCCESS(Status)) + return(Status); + + Status = ZwAllocateLocallyUniqueId(&ModifiedId); + if (!NT_SUCCESS(Status)) + return(Status); + + Status = ObCreateObject(&TokenHandle, + DesiredAccess, + ObjectAttributes, + SepTokenObjectType, + (PVOID*)&AccessToken); + if (!NT_SUCCESS(Status)) + { + DPRINT1("ObCreateObject() failed (Status %lx)\n"); + return(Status); + } + + RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier, + &TokenSource->SourceIdentifier); + memcpy(AccessToken->TokenSource.SourceName, + TokenSource->SourceName, + sizeof(TokenSource->SourceName)); + + RtlCopyLuid(&AccessToken->TokenId, &TokenId); + RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId); + AccessToken->ExpirationTime = *ExpirationTime; + RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId); + + AccessToken->UserAndGroupCount = TokenGroups->GroupCount + 1; + AccessToken->PrivilegeCount = TokenPrivileges->PrivilegeCount; + AccessToken->UserAndGroups = 0; + AccessToken->Privileges = 0; + + AccessToken->TokenType = TokenType; + AccessToken->ImpersonationLevel = ObjectAttributes->SecurityQualityOfService->ImpersonationLevel; + + /* + * Normally we would just point these members into the variable information + * area; however, our ObCreateObject() call can't allocate a variable information + * area, so we allocate them seperately and provide a destroy function. + */ + + uLength = sizeof(SID_AND_ATTRIBUTES) * AccessToken->UserAndGroupCount; + uLength += RtlLengthSid(TokenUser->User.Sid); + for (i = 0; i < TokenGroups->GroupCount; i++) + uLength += RtlLengthSid(TokenGroups->Groups[i].Sid); + + AccessToken->UserAndGroups = + (PSID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool, + uLength, + TAG('T', 'O', 'K', 'u')); + + EndMem = &AccessToken->UserAndGroups[AccessToken->UserAndGroupCount]; + + Status = RtlCopySidAndAttributesArray(1, + &TokenUser->User, + uLength, + AccessToken->UserAndGroups, + EndMem, + &EndMem, + &uLength); + if (NT_SUCCESS(Status)) + { + Status = RtlCopySidAndAttributesArray(TokenGroups->GroupCount, + TokenGroups->Groups, + uLength, + &AccessToken->UserAndGroups[1], + EndMem, + &EndMem, + &uLength); + } + + if (NT_SUCCESS(Status)) + { + Status = SepFindPrimaryGroupAndDefaultOwner( + AccessToken, + TokenPrimaryGroup->PrimaryGroup, + TokenOwner->Owner); + } + + if (NT_SUCCESS(Status)) + { + uLength = TokenPrivileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); + AccessToken->Privileges = + (PLUID_AND_ATTRIBUTES)ExAllocatePoolWithTag(NonPagedPool, + uLength, + TAG('T', 'O', 'K', 'p')); + + for (i = 0; i < TokenPrivileges->PrivilegeCount; i++) + { + Status = MmCopyFromCaller(&AccessToken->Privileges[i], + &TokenPrivileges->Privileges[i], + sizeof(LUID_AND_ATTRIBUTES)); + if (!NT_SUCCESS(Status)) + break; + } + } + + if (NT_SUCCESS(Status)) + { + AccessToken->DefaultDacl = + (PACL) ExAllocatePoolWithTag(NonPagedPool, + TokenDefaultDacl->DefaultDacl->AclSize, + TAG('T', 'O', 'K', 'd')); + memcpy(AccessToken->DefaultDacl, + TokenDefaultDacl->DefaultDacl, + TokenDefaultDacl->DefaultDacl->AclSize); + } + + ObDereferenceObject(AccessToken); + + if (NT_SUCCESS(Status)) + { + Status = MmCopyToCaller(UnsafeTokenHandle, + &TokenHandle, + sizeof(HANDLE)); + } + + if (!NT_SUCCESS(Status)) + { + ZwClose(TokenHandle); + return(Status); + } + + return(STATUS_SUCCESS); +} + + +SECURITY_IMPERSONATION_LEVEL STDCALL +SeTokenImpersonationLevel(IN PACCESS_TOKEN Token) +{ + return(Token->ImpersonationLevel); +} + + +TOKEN_TYPE STDCALL +SeTokenType(IN PACCESS_TOKEN Token) +{ + return(Token->TokenType); +} + +/* EOF */ diff --git a/rosbin.txt b/rosbin.txt new file mode 100644 index 0000000..a847dc1 --- /dev/null +++ b/rosbin.txt @@ -0,0 +1,67 @@ +; ReactOS Cabinet Manager Directive File - ReactOS Binary Distribution + +;.Set DiskLabel1="ReactOS Setup Disk" ; Label of 1st disk +;.Set DiskLabel2="ReactOS Drivers" ; Label of 2nd disk +;.Set DiskLabel3="ReactOS Subsystems" ; Label of 3rd disk +;.Set DiskLabel4="ReactOS Applications" ; Label of 4th disk +.Set DiskLabelTemplate="ReactOS Disk *" ; Label of all disks +.Set CabinetNameTemplate="ROS*.CAB" ; ROS1.CAB, ROS2.CAB, etc. +.Set MaxDiskSize=500000 ; 500000 bytes disks +;.Set MaxDiskSize=720K ; 720KB disks +;.Set MaxDiskSize=1.44M ; 1.44MB disks +;.Set MaxDiskSize=2.88M ; 2.88MB disks + + +;.Set Cabinet=on +;.Set Compress=on + +; Contents of disk 1 +boot.bat +loaders\dos\loadros.com +ntoskrnl\ntoskrnl.exe system32 +lib\ntdll\ntdll.dll system32 +apps\system\services\services.exe system32 +apps\system\winlogon\winlogon.exe system32 + +; Contents of disk 2 +;.New Disk +;services\dd\beep\beep.sys system32\drivers +services\dd\blue\blue.sys system32\drivers +services\dd\floppy\floppy.sys system32\drivers +services\dd\ide\ide.sys system32\drivers +services\dd\null\null.sys system32\drivers +services\dd\parallel\parallel.sys system32\drivers +services\dd\serial\serial.sys system32\drivers +services\dd\vga\display\vgaddi.dll system32\drivers +services\dd\vga\miniport\vgamp.sys system32\drivers +services\dd\vidport\vidport.sys system32\drivers +services\fs\vfat\vfatfs.sys system32\drivers +services\input\keyboard\keyboard.sys system32\drivers +services\net\afd\afd.sys system32 +services\net\ndis\ndis.sys system32 +services\net\tcpip\tcpip.sys system32 +;services\net\tdi\tdi.sys system32 +services\net\wshtcpip\wshtcpip.dll system32 +services\net\dd\ne2000\ne2000.sys system32\drivers + +; Contents of disk 3 +;.New Disk +lib\advapi32\advapi32.dll system32 +lib\crtdll\crtdll.dll system32 +lib\fmifs\fmifs.dll system32 +lib\gdi32\gdi32.dll system32 +lib\kernel32\kernel32.dll system32 +lib\msafd\msafd.dll system32 +;lib\msvcrt\msvcrt.dll system32 +lib\secur32\secur32.dll system32 +;lib\user32\user32.dll system32 +lib\ws2_32\ws2_32.dll system32 +subsys\csrss\csrss.exe system32 +subsys\smss\smss.exe system32 +subsys\win32k\win32k.sys system32 + +; Contents of disk 4 +;.New Disk +apps\system\shell\shell.exe system32 + +; EOF diff --git a/rules.mak b/rules.mak new file mode 100644 index 0000000..355c468 --- /dev/null +++ b/rules.mak @@ -0,0 +1,116 @@ +# +# Important +# +.EXPORT_ALL_VARIABLES: + +# Windows is default host environment +ifeq ($(HOST),) +HOST = mingw32-windows +endif + +# uncomment if you use bochs and it displays only 30 rows +# BOCHS_30ROWS = yes + +ifeq ($(HOST),mingw32-linux) +TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) +endif + +# +# Choose various options +# +ifeq ($(HOST),mingw32-linux) +NASM_FORMAT = win32 +PREFIX = mingw32- +EXE_POSTFIX := +EXE_PREFIX := ./ +DLLTOOL = $(PREFIX)dlltool --as=$(PREFIX)as +NASM_CMD = nasm +DOSCLI = +FLOPPY_DIR = /mnt/floppy +SEP := / +PIPE := +endif + +ifeq ($(HOST),mingw32-windows) +NASM_FORMAT = win32 +PREFIX = +EXE_PREFIX := +EXE_POSTFIX := .exe +DLLTOOL = $(PREFIX)dlltool --as=$(PREFIX)as +NASM_CMD = nasmw +DOSCLI = yes +FLOPPY_DIR = A: +SEP := \$(EMPTY_VAR) +PIPE := -pipe +endif + + +# Set INSTALL_DIR to default value if not already set +# ifeq ($(INSTALL_DIR),) +INSTALL_DIR = $(PATH_TO_TOP)/reactos +# endif + +# Set DIST_DIR to default value if not already set +# ifeq ($(DIST_DIR),) +DIST_DIR = $(PATH_TO_TOP)/dist +# endif + + +CC = $(PREFIX)gcc +CXX = $(PREFIX)g++ +HOST_CC = gcc +HOST_NM = nm +LD = $(PREFIX)ld +NM = $(PREFIX)nm +OBJCOPY = $(PREFIX)objcopy +STRIP = $(PREFIX)strip +AS = $(PREFIX)gcc -c -x assembler-with-cpp +CPP = $(PREFIX)cpp +AR = $(PREFIX)ar +RC = $(PREFIX)windres +WRC = $(WINE_TOP)/tools/wrc/wrc +RCINC = --include-dir $(PATH_TO_TOP)/include +OBJCOPY = $(PREFIX)objcopy +TOOLS_PATH = $(PATH_TO_TOP)/tools +CP = $(TOOLS_PATH)/rcopy +RM = $(TOOLS_PATH)/rdel +RMDIR = $(TOOLS_PATH)/rrmdir +RMKDIR = $(TOOLS_PATH)/rmkdir +RSYM = $(TOOLS_PATH)/rsym +MC = $(TOOLS_PATH)/wmc/wmc + + +# Maybe we can delete these soon + +ifeq ($(HOST),mingw32-linux) +CFLAGS := $(CFLAGS) -I$(PATH_TO_TOP)/include -pipe -march=i386 +endif + +ifeq ($(HOST),mingw32-windows) +CFLAGS := $(CFLAGS) -I$(PATH_TO_TOP)/include -pipe -march=i386 +endif + +CXXFLAGS = $(CFLAGS) +NFLAGS = -i$(PATH_TO_TOP)/include/ -f$(NASM_FORMAT) -d$(NASM_FORMAT) +ASFLAGS := $(ASFLAGS) -I$(PATH_TO_TOP)/include -D__ASM__ + + +# Developer Kits +DK_PATH=$(PATH_TO_TOP)/dk +# Native and kernel mode +DDK_PATH=$(DK_PATH)/nkm +DDK_PATH_LIB=$(DDK_PATH)/lib +DDK_PATH_INC=$(PATH_TO_TOP)/include +# Win32 +SDK_PATH=$(DK_PATH)/w32 +SDK_PATH_LIB=$(SDK_PATH)/lib +SDK_PATH_INC=$(PATH_TO_TOP)/include +# POSIX+ +XDK_PATH=$(DK_PATH)/psx +XDK_PATH_LIB=$(XDK_PATH)/lib +XDK_PATH_INC=$(XDK_PATH)/include + +# Wine Integration +WINE_PATH=$(PATH_TO_TOP)/../wine +WINE_PATH_LIB=$(WINE_PATH)/lib +WINE_PATH_INC=$(WINE_PATH)/include diff --git a/services/eventlog/.cvsignore b/services/eventlog/.cvsignore new file mode 100644 index 0000000..b349ee7 --- /dev/null +++ b/services/eventlog/.cvsignore @@ -0,0 +1,4 @@ +eventlog.coff +*.d +*.o +*.sym diff --git a/services/eventlog/eventlog.c b/services/eventlog/eventlog.c new file mode 100644 index 0000000..ebccb43 --- /dev/null +++ b/services/eventlog/eventlog.c @@ -0,0 +1,113 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/eventlog/eventlog.c + * PURPOSE: Event logging service + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#define UNICODE + +#define NTOS_MODE_USER +#include +#include + +#include "eventlog.h" + +#define DBG +#define NDEBUG +#include + + + +/* GLOBALS ******************************************************************/ + + + +/* FUNCTIONS *****************************************************************/ + +void +PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + OutputDebugStringA(buffer); +} + + +VOID CALLBACK +ServiceMain(DWORD argc, LPTSTR *argv) +{ + + PrintString("ServiceMain() called\n"); + + + PrintString("ServiceMain() done\n"); + +} + + +int +main(int argc, char *argv[]) +{ + SERVICE_TABLE_ENTRY ServiceTable[2] = {{L"EventLog", ServiceMain}, + {NULL, NULL}}; + + HANDLE hEvent; +// NTSTATUS Status; + + PrintString("EventLog started\n"); + + + + + + StartServiceCtrlDispatcher(ServiceTable); + PrintString("StartServiceCtrlDispatcher() done\n"); + +#if 0 + if (StartPortThread() == FALSE) + { + PrintString("StartPortThread() failed\n"); + } +#endif + + + + PrintString("EventLog waiting\n"); + hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + WaitForSingleObject(hEvent, INFINITE); + + PrintString("EventLog done\n"); + + ExitThread(0); + return(0); +} + +/* EOF */ diff --git a/services/eventlog/eventlog.h b/services/eventlog/eventlog.h new file mode 100644 index 0000000..4cf1559 --- /dev/null +++ b/services/eventlog/eventlog.h @@ -0,0 +1,12 @@ + +#ifndef __EVENTLOG_H__ +#define __EVENTLOG_H__ + + +BOOL +StartPortThread(VOID); + + +#endif /* __EVENTLOG_H__ */ + +/* EOF */ diff --git a/services/eventlog/eventlog.rc b/services/eventlog/eventlog.rc new file mode 100644 index 0000000..fff9e1d --- /dev/null +++ b/services/eventlog/eventlog.rc @@ -0,0 +1,38 @@ +#include "../../include/defines.h" +#include "../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Event logging service\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "EventLog\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "EventLog.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/services/eventlog/logport.c b/services/eventlog/logport.c new file mode 100644 index 0000000..7d568e3 --- /dev/null +++ b/services/eventlog/logport.c @@ -0,0 +1,187 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/eventlog/logport.c + * PURPOSE: Event logger service + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#define UNICODE + +#define NTOS_MODE_USER +#include +#include +#include + +#include "eventlog.h" + +#define NDEBUG +#include + + +/* GLOBALS ******************************************************************/ + +HANDLE PortThreadHandle = NULL; +HANDLE ConnectPortHandle = NULL; +HANDLE MessagePortHandle = NULL; + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +InitLogPort(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING PortName; + LPC_MESSAGE Message; + NTSTATUS Status; + + ConnectPortHandle = NULL; + MessagePortHandle = NULL; + + RtlInitUnicodeStringFromLiteral(&PortName, + L"\\ErrorLogPort"); + InitializeObjectAttributes(&ObjectAttributes, + &PortName, + 0, + NULL, + NULL); + + Status = NtCreatePort(&ConnectPortHandle, + &ObjectAttributes, + 0, + 0x100, + 0x2000); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + Message.DataSize = sizeof(LPC_MESSAGE); + Message.MessageSize = 0; + + Status = NtListenPort(ConnectPortHandle, + &Message); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + Status = NtAcceptConnectPort(&MessagePortHandle, + 0, + &Message, + 1, + 0, + 0); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + Status = NtCompleteConnectPort(MessagePortHandle); + if (!NT_SUCCESS(Status)) + goto ByeBye; + +ByeBye: + if (ConnectPortHandle != NULL) + NtClose(ConnectPortHandle); + + if (MessagePortHandle != NULL) + NtClose(MessagePortHandle); + + return(Status); +} + + +static NTSTATUS +ProcessPortMessage(VOID) +{ + PLPC_MAX_MESSAGE Request; + LPC_MESSAGE Reply; + BOOL ReplyReady = FALSE; + NTSTATUS Status; + + Request = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(LPC_MAX_MESSAGE)); + if (Request == NULL) + return(STATUS_NO_MEMORY); + + while (TRUE) + { + Status = NtReplyWaitReceivePort(MessagePortHandle, + 0, + (ReplyReady)? &Reply : NULL, + (PLPC_MESSAGE)Request); + if (!NT_SUCCESS(Status)) + { + HeapFree(GetProcessHeap(), + 0, + Request); + return(Status); + } + + ReplyReady = FALSE; + if (Request->Header.MessageType == LPC_REQUEST) + { + DPRINT1("Received request\n"); + + ReplyReady = FALSE; + } + else if (Request->Header.MessageType == LPC_DATAGRAM) + { + DPRINT1("Received datagram\n"); + } + } +} + + +static NTSTATUS STDCALL +PortThreadRoutine(PVOID Param) +{ + NTSTATUS Status = STATUS_SUCCESS; + + Status = InitLogPort(); + if (!NT_SUCCESS(Status)) + return(Status); + + while (!NT_SUCCESS(Status)) + { + Status = ProcessPortMessage(); + } + + return(Status); +} + + +BOOL +StartPortThread(VOID) +{ + DWORD ThreadId; + + PortThreadHandle = CreateThread(NULL, + 0x1000, + PortThreadRoutine, + NULL, + 0, + &ThreadId); + + return((PortThreadHandle != NULL)); +} + +/* EOF */ diff --git a/services/eventlog/makefile b/services/eventlog/makefile new file mode 100644 index 0000000..a75e95b --- /dev/null +++ b/services/eventlog/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = eventlog + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o logport.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/services/rpcss/.cvsignore b/services/rpcss/.cvsignore new file mode 100644 index 0000000..ff4292b --- /dev/null +++ b/services/rpcss/.cvsignore @@ -0,0 +1,4 @@ +rpcss.coff +*.d +*.o +*.sym diff --git a/services/rpcss/endpoint.c b/services/rpcss/endpoint.c new file mode 100644 index 0000000..39c806c --- /dev/null +++ b/services/rpcss/endpoint.c @@ -0,0 +1,47 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/rpcss/endpoint.c + * PURPOSE: RPC server + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include +//#include + +/* FUNCTIONS ****************************************************************/ + +VOID +StartEndpointMapper(VOID) +{ +#if 0 + RpcServerRegisterProtseqW("ncacn_np", 1, "\pipe\epmapper"); + + RpcServerRegisterProtseqW("ncalrpc", 1, "epmapper"); + + RpcServerRegisterIf(epmapper_InterfaceHandle, 0, 0); +#endif +} + +/* EOF */ diff --git a/services/rpcss/makefile b/services/rpcss/makefile new file mode 100644 index 0000000..b42dc40 --- /dev/null +++ b/services/rpcss/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = rpcss + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = kernel32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o endpoint.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/services/rpcss/rpcss.c b/services/rpcss/rpcss.c new file mode 100644 index 0000000..f675c32 --- /dev/null +++ b/services/rpcss/rpcss.c @@ -0,0 +1,110 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/rpcss/rpcss.c + * PURPOSE: RPC server + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#define UNICODE + +#define NTOS_MODE_USER +#include +#include + +//#include "services.h" + +#define NDEBUG +#include + + + +/* GLOBALS ******************************************************************/ + + + +/* FUNCTIONS *****************************************************************/ + +void +PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + OutputDebugStringA(buffer); +} + + + +VOID CALLBACK +ServiceMain(DWORD argc, LPTSTR *argv) +{ + + PrintString("ServiceMain() called\n"); + + + StartEndpointMapper(); + + + PrintString("ServiceMain() done\n"); + +} + + +int main(int argc, char *argv[]) +{ +#if 0 + SERVICE_TABLE_ENTRY ServiceTable[] = {{"RpcSs", ServiceMain},{NULL, NULL}}; +#endif + + HANDLE hEvent; + NTSTATUS Status; + + PrintString("RpcSs service\n"); + + + + +#if 0 + StartServiceCtrlDispatcher(ServiceTable); +#endif + + + ServiceMain(0, NULL); + + + hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + WaitForSingleObject(hEvent, INFINITE); + + PrintString("EventLog: done\n"); + + ExitThread(0); + return(0); +} + +/* EOF */ diff --git a/services/rpcss/rpcss.h b/services/rpcss/rpcss.h new file mode 100644 index 0000000..4bf62c6 --- /dev/null +++ b/services/rpcss/rpcss.h @@ -0,0 +1,9 @@ +#ifndef __RPCSS_H__ +#define __RPCSS_H__ + +VOID +StartEndpointMapper(VOID); + +#endif /* __RPCSS_H__ */ + +/* EOF */ \ No newline at end of file diff --git a/services/rpcss/rpcss.rc b/services/rpcss/rpcss.rc new file mode 100644 index 0000000..5cd1dba --- /dev/null +++ b/services/rpcss/rpcss.rc @@ -0,0 +1,38 @@ +#include "../../include/defines.h" +#include "../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "RPC subsystem\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "RpcSs\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "RpcSs.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/csrss/.cvsignore b/subsys/csrss/.cvsignore new file mode 100644 index 0000000..47fb562 --- /dev/null +++ b/subsys/csrss/.cvsignore @@ -0,0 +1,7 @@ +csrss.coff +csrss.exe +csrss.nostrip.exe +*.d +*.o +*.sym +win32k.c diff --git a/subsys/csrss/api.h b/subsys/csrss/api.h new file mode 100644 index 0000000..e70bc96 --- /dev/null +++ b/subsys/csrss/api.h @@ -0,0 +1,163 @@ +#ifndef _CSRSS_API_H +#define _CSRSS_API_H + +#include + +#include + +/* Object type magic numbers */ + +#define CSRSS_CONSOLE_MAGIC 1 +#define CSRSS_SCREEN_BUFFER_MAGIC 2 + +typedef struct Object_tt +{ + LONG Type; + LONG ReferenceCount; +} Object_t; + +typedef struct ConsoleInput_t +{ + LIST_ENTRY ListEntry; + INPUT_RECORD InputEvent; + BOOLEAN Echoed; // already been echoed or not +} ConsoleInput; + + +/************************************************************************ + * Screen buffer structure represents the win32 screen buffer object. * + * Internally, the portion of the buffer being shown CAN loop past the * + * bottom of the virtual buffer and wrap around to the top. Win32 does * + * not do this. I decided to do this because it eliminates the need to * + * do a massive memcpy() to scroll the contents of the buffer up to * + * scroll the screen on output, instead I just shift down the position * + * to be displayed, and let it wrap around to the top again. * + * The VirtualX member keeps track of the top X coord that win32 * + * clients THINK is currently being displayed, because they think that * + * when the display reaches the bottom of the buffer and another line * + * being printed causes another line to scroll down, that the buffer IS * + * memcpy()'s up, and the bottom of the buffer is still displayed, but * + * internally, I just wrap back to the top of the buffer. * + ***********************************************************************/ + +typedef struct CSRSS_SCREEN_BUFFER_t +{ + Object_t Header; /* Object header */ + BYTE *Buffer; /* pointer to screen buffer */ + USHORT MaxX, MaxY; /* size of the entire scrollback buffer */ + USHORT ShowX, ShowY; /* beginning offset for the actual display area */ + ULONG CurrentX; /* Current X cursor position */ + ULONG CurrentY; /* Current Y cursor position */ + BYTE DefaultAttrib; /* default char attribute */ + USHORT VirtualX; /* top row of buffer being displayed, reported to callers */ + CONSOLE_CURSOR_INFO CursorInfo; + USHORT Mode; +} CSRSS_SCREEN_BUFFER, *PCSRSS_SCREEN_BUFFER; + +typedef struct CSRSS_CONSOLE_t +{ + Object_t Header; /* Object header */ + struct CSRSS_CONSOLE_t *Prev, *Next; /* Next and Prev consoles in console wheel */ + HANDLE ActiveEvent; + LIST_ENTRY InputEvents; /* List head for input event queue */ + WORD WaitingChars; + WORD WaitingLines; /* number of chars and lines in input queue */ + PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */ + WORD Mode; /* Console mode flags */ + WORD EchoCount; /* count of chars to echo, in line buffered mode */ + UNICODE_STRING Title; /* Title of console */ + struct { /* active code pages */ + UINT Input; + UINT Output; + } CodePageId; + BOOL EarlyReturn; /* wake client and return data, even if we are in line buffered mode, and we don't have a complete line */ +} CSRSS_CONSOLE, *PCSRSS_CONSOLE; + +typedef struct +{ + PCSRSS_CONSOLE Console; + ULONG HandleTableSize; + Object_t ** HandleTable; + ULONG ProcessId; + ULONG ShutdownLevel; + ULONG ShutdownFlags; + HANDLE ConsoleEvent; + PVOID CsrSectionViewBase; + ULONG CsrSectionViewSize; +} CSRSS_PROCESS_DATA, *PCSRSS_PROCESS_DATA; + +#define CSR_API(n) NTSTATUS n (\ +PCSRSS_PROCESS_DATA ProcessData,\ +PCSRSS_API_REQUEST Request,\ +PCSRSS_API_REPLY Reply) + +/* api/process.c */ +CSR_API(CsrConnectProcess); +CSR_API(CsrCreateProcess); +CSR_API(CsrTerminateProcess); + +/* api/conio.c */ +CSR_API(CsrWriteConsole); +CSR_API(CsrAllocConsole); +CSR_API(CsrFreeConsole); +CSR_API(CsrReadConsole); +CSR_API(CsrConnectProcess); +CSR_API(CsrGetScreenBufferInfo); +CSR_API(CsrSetCursor); +CSR_API(CsrFillOutputChar); +CSR_API(CsrReadInputEvent); +CSR_API(CsrWriteConsoleOutputChar); +CSR_API(CsrWriteConsoleOutputAttrib); +CSR_API(CsrFillOutputAttrib); +CSR_API(CsrGetCursorInfo); +CSR_API(CsrSetCursorInfo); +CSR_API(CsrSetTextAttrib); +CSR_API(CsrSetConsoleMode); +CSR_API(CsrGetConsoleMode); +CSR_API(CsrCreateScreenBuffer); +CSR_API(CsrSetScreenBuffer); +CSR_API(CsrSetTitle); +CSR_API(CsrGetTitle); +CSR_API(CsrWriteConsoleOutput); +CSR_API(CsrFlushInputBuffer); +CSR_API(CsrScrollConsoleScreenBuffer); +CSR_API(CsrReadConsoleOutputChar); +CSR_API(CsrReadConsoleOutputAttrib); +CSR_API(CsrGetNumberOfConsoleInputEvents); +CSR_API(CsrRegisterServicesProcess); +CSR_API(CsrExitReactos); +CSR_API(CsrGetShutdownParameters); +CSR_API(CsrSetShutdownParameters); +CSR_API(CsrPeekConsoleInput); + +/* print.c */ +VOID STDCALL DisplayString(LPCWSTR lpwString); +VOID STDCALL PrintString (char* fmt, ...); + +/* api/wapi.c */ +VOID Thread_Api(PVOID PortHandle); +VOID Console_Api( DWORD Ignored ); + +extern HANDLE CsrssApiHeap; + +/* api/conio.c */ +NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console); +VOID STDCALL CsrDeleteConsole( PCSRSS_CONSOLE Console ); +VOID STDCALL CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer ); +NTSTATUS STDCALL CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console ); +VOID STDCALL CsrInitConsoleSupport(VOID); + +/* api/process.c */ +VOID STDCALL CsrInitProcessData(VOID); +PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId); +NTSTATUS STDCALL CsrFreeProcessData( ULONG Pid ); + +/* api/handle.c */ +NTSTATUS STDCALL CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object ); +NTSTATUS STDCALL CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object ); +BOOL STDCALL CsrServerInitialization (ULONG ArgumentCount, PWSTR *ArgumentArray); +NTSTATUS STDCALL CsrReleaseObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object ); +VOID STDCALL CsrDrawConsole( PCSRSS_SCREEN_BUFFER Console ); +NTSTATUS STDCALL CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWORD Length, BOOL Attrib ); + +#endif /* ndef _CSRSS_API_H */ diff --git a/subsys/csrss/api/.cvsignore b/subsys/csrss/api/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/csrss/api/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/csrss/api/conio.c b/subsys/csrss/api/conio.c new file mode 100644 index 0000000..adeb5bd --- /dev/null +++ b/subsys/csrss/api/conio.c @@ -0,0 +1,2150 @@ +/* $Id$ + * + * reactos/subsys/csrss/api/conio.c + * + * Console I/O functions + * + * ReactOS Operating System + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include +#include "api.h" +#include +#include + +#define NDEBUG +#include + +#define LOCK RtlEnterCriticalSection(&ActiveConsoleLock) +#define UNLOCK RtlLeaveCriticalSection(&ActiveConsoleLock) + +/* FIXME: Is there a way to create real aliasses with gcc? [CSH] */ +#define ALIAS(Name, Target) typeof(Target) Name = Target + + +/* GLOBALS *******************************************************************/ + +static HANDLE ConsoleDeviceHandle; +static HANDLE KeyboardDeviceHandle; +static PCSRSS_CONSOLE ActiveConsole; +CRITICAL_SECTION ActiveConsoleLock; +static COORD PhysicalConsoleSize; + +/* FUNCTIONS *****************************************************************/ + +CSR_API(CsrAllocConsole) +{ + PCSRSS_CONSOLE Console; + HANDLE Process; + NTSTATUS Status; + CLIENT_ID ClientId; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + if( ProcessData->Console ) + { + Reply->Status = STATUS_INVALID_PARAMETER; + return STATUS_INVALID_PARAMETER; + } + Reply->Status = STATUS_SUCCESS; + Console = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_CONSOLE ) ); + if( Console == 0 ) + { + Reply->Status = STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; + } + Reply->Status = CsrInitConsole( Console ); + if( !NT_SUCCESS( Reply->Status ) ) + { + RtlFreeHeap( CsrssApiHeap, 0, Console ); + return Reply->Status; + } + ProcessData->Console = Console; + /* add a reference count because the process is tied to the console */ + Console->Header.ReferenceCount++; + Status = CsrInsertObject( ProcessData, &Reply->Data.AllocConsoleReply.InputHandle, &Console->Header ); + if( !NT_SUCCESS( Status ) ) + { + CsrDeleteConsole( Console ); + ProcessData->Console = 0; + return Reply->Status = Status; + } + Status = CsrInsertObject( ProcessData, &Reply->Data.AllocConsoleReply.OutputHandle, &Console->ActiveBuffer->Header ); + if( !NT_SUCCESS( Status ) ) + { + Console->Header.ReferenceCount--; + CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.InputHandle ); + ProcessData->Console = 0; + return Reply->Status = Status; + } + ClientId.UniqueProcess = (HANDLE)ProcessData->ProcessId; + Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" ); + Console->Header.ReferenceCount--; + ProcessData->Console = 0; + CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.OutputHandle ); + CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.InputHandle ); + Reply->Status = Status; + return Status; + } + Status = NtDuplicateObject( NtCurrentProcess(), ProcessData->Console->ActiveEvent, Process, &ProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status ); + NtClose( Process ); + Console->Header.ReferenceCount--; + CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.OutputHandle ); + CsrReleaseObject( ProcessData, Reply->Data.AllocConsoleReply.InputHandle ); + ProcessData->Console = 0; + Reply->Status = Status; + return Status; + } + NtClose( Process ); + return STATUS_SUCCESS; +} + +CSR_API(CsrFreeConsole) +{ + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + Reply->Status = STATUS_NOT_IMPLEMENTED; + + return(STATUS_NOT_IMPLEMENTED); +} + +CSR_API(CsrReadConsole) +{ + PLIST_ENTRY CurrentEntry; + ConsoleInput *Input; + PCHAR Buffer; + int i = 0; + ULONG nNumberOfCharsToRead; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + + /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */ + nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : Request->Data.ReadConsoleRequest.NrCharactersToRead; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = Reply->Header.MessageSize - + sizeof(LPC_MESSAGE_HEADER); + Buffer = Reply->Data.ReadConsoleReply.Buffer; + Reply->Data.ReadConsoleReply.EventHandle = ProcessData->ConsoleEvent; + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle, (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) ) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + if( Console->Header.Type != CSRSS_CONSOLE_MAGIC ) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return STATUS_INVALID_HANDLE; + } + for (; iInputEvents.Flink != &Console->InputEvents; i++ ) + { + // remove input event from queue + CurrentEntry = RemoveHeadList(&Console->InputEvents); + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + + // only pay attention to valid ascii chars, on key down + if( Input->InputEvent.EventType == KEY_EVENT && + Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE && + Input->InputEvent.Event.KeyEvent.uChar.AsciiChar ) + { + // backspace handling + if( Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' ) + { + // echo if it has not already been done, and either we or the client has chars to be deleted + if( !Input->Echoed && ( i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted ) ) + CsrpWriteConsole( Console->ActiveBuffer, &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); + if( i ) + i-=2; // if we already have something to return, just back it up by 2 + else + { // otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer + Reply->Data.ReadConsoleReply.NrCharactersRead = 0; + Reply->Status = STATUS_NOTIFY_CLEANUP; + Console->WaitingChars--; + RtlFreeHeap( CsrssApiHeap, 0, Input ); + UNLOCK; + return STATUS_NOTIFY_CLEANUP; + } + Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--; + Input->Echoed = TRUE; // mark as echoed so we don't echo it below + } + // do not copy backspace to buffer + else Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; + // echo to screen if enabled and we did not already echo the char + if( Console->Mode & ENABLE_ECHO_INPUT && + !Input->Echoed && + Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' ) + CsrpWriteConsole( Console->ActiveBuffer, &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); + } + else i--; + Console->WaitingChars--; + RtlFreeHeap( CsrssApiHeap, 0, Input ); + } + Reply->Data.ReadConsoleReply.NrCharactersRead = i; + if( !i ) + Reply->Status = STATUS_PENDING; // we didn't read anything + else if( Console->Mode & ENABLE_LINE_INPUT ) + if( !Console->WaitingLines || Buffer[i-1] != '\n' ) + { + Reply->Status = STATUS_PENDING; // line buffered, didn't get a complete line + } + else { + Console->WaitingLines--; + Reply->Status = STATUS_SUCCESS; // line buffered, did get a complete line + } + else Reply->Status = STATUS_SUCCESS; // not line buffered, did read something + if( Reply->Status == STATUS_PENDING ) + { + Console->EchoCount = nNumberOfCharsToRead - i; + } + else { + Console->EchoCount = 0; // if the client is no longer waiting on input, do not echo + } + Reply->Header.MessageSize += i; + UNLOCK; + return Reply->Status; +} + +#define GET_CELL_BUFFER(b,o)\ +(b)->Buffer[(o)++]; + +#define SET_CELL_BUFFER(b,o,c,a)\ +(b)->Buffer[(o)++]=(c);\ +(b)->Buffer[(o)++]=(a); + +static VOID FASTCALL +ClearLineBuffer ( + PCSRSS_SCREEN_BUFFER Buff, + DWORD StartX + ) +{ + DWORD Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + StartX); + + for ( ; StartX < Buff->MaxX; StartX ++ ) + { + /* Fill the cell: Offset is incremented by the macro */ + SET_CELL_BUFFER(Buff,Offset,' ',Buff->DefaultAttrib) + } +} + +NTSTATUS STDCALL CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWORD Length, BOOL Attrib ) +{ + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + int i; + DWORD Offset; + + for( i = 0; i < Length; i++ ) + { + switch( Buffer[ i ] ) + { + /* --- LF --- */ + case '\n': + Buff->CurrentX = 0; + /* slide the viewable screen */ + if( ((PhysicalConsoleSize.Y + Buff->ShowY) % Buff->MaxY) == (Buff->CurrentY + 1) % Buff->MaxY) + if( ++Buff->ShowY == (Buff->MaxY - 1) ) + Buff->ShowY = 0; + if( ++Buff->CurrentY == Buff->MaxY ) + { + Buff->CurrentY = 0; + } + ClearLineBuffer (Buff, 0); + break; + /* --- BS --- */ + case '\b': + if( Buff->CurrentX == 0 ) + { + /* slide viewable screen up */ + if( Buff->ShowY == Buff->CurrentY ) + { + if( Buff->ShowY == 0 ) + Buff->ShowY = Buff->MaxY; + else + Buff->ShowY--; + } + /* slide virtual position up */ + Buff->CurrentX = Buff->MaxX; + if( Buff->CurrentY == 0 ) + Buff->CurrentY = Buff->MaxY; + else + Buff->CurrentY--; + } + else + Buff->CurrentX--; + Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX); + SET_CELL_BUFFER(Buff,Offset,' ',Buff->DefaultAttrib); + break; + /* --- CR --- */ + case '\r': + Buff->CurrentX = 0; + break; + /* --- TAB --- */ + case '\t': + CsrpWriteConsole(Buff, " ", (8 - (Buff->CurrentX % 8)), FALSE); + break; + /* --- */ + default: + Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX); + Buff->Buffer[Offset ++] = Buffer[ i ]; + if( Attrib ) + Buff->Buffer[Offset] = Buff->DefaultAttrib; + Buff->CurrentX++; + if( Buff->CurrentX == Buff->MaxX ) + { + /* if end of line, go to next */ + Buff->CurrentX = 0; + if( ++Buff->CurrentY == Buff->MaxY ) + { + /* if end of buffer, wrap back to beginning */ + Buff->CurrentY = 0; + } + /* clear new line */ + ClearLineBuffer (Buff, 0); + /* slide the viewable screen */ + if( (Buff->CurrentY - Buff->ShowY) == PhysicalConsoleSize.Y ) + if( ++Buff->ShowY == Buff->MaxY ) + Buff->ShowY = 0; + } + } + } + if( Buff == ActiveConsole->ActiveBuffer ) + { /* only write to screen if Console is Active, and not scrolled up */ + if( Attrib ) + { + Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, Buffer, Length, NULL, 0); + if (!NT_SUCCESS(Status)) + DbgPrint("CSR: Write failed\n"); + } + } + return(STATUS_SUCCESS); +} + +#define CsrpInitRect(_Rect, _Top, _Left, _Bottom, _Right) \ +{ \ + ((_Rect).Top) = _Top; \ + ((_Rect).Left) = _Left; \ + ((_Rect).Bottom) = _Bottom; \ + ((_Rect).Right) = _Right; \ +} + +#define CsrpRectHeight(Rect) \ + ((Rect.Bottom) - (Rect.Top) + 1) + +#define CsrpRectWidth(Rect) \ + ((Rect.Right) - (Rect.Left) + 1) + +#define CsrpIsRectEmpty(Rect) \ + ((Rect.Left >= Rect.Right) || (Rect.Top >= Rect.Bottom)) + + +inline BOOLEAN CsrpIsEqualRect( + SMALL_RECT Rect1, + SMALL_RECT Rect2) +{ + return ((Rect1.Left == Rect2.Left) && (Rect1.Right == Rect2.Right) && + (Rect1.Top == Rect2.Top) && (Rect1.Bottom == Rect2.Bottom)); +} + +inline BOOLEAN CsrpGetIntersection( + PSMALL_RECT Intersection, + SMALL_RECT Rect1, + SMALL_RECT Rect2) +{ + if (CsrpIsRectEmpty(Rect1) || + (CsrpIsRectEmpty(Rect2)) || + (Rect1.Top >= Rect2.Bottom) || + (Rect1.Left >= Rect2.Right) || + (Rect1.Bottom <= Rect2.Top) || + (Rect1.Right <= Rect2.Left)) + { + /* The rectangles do not intersect */ + CsrpInitRect(*Intersection, 0, 0, 0, 0) + return FALSE; + } + + CsrpInitRect( + *Intersection, + RtlMax(Rect1.Top, Rect2.Top), + RtlMax(Rect1.Left, Rect2.Left), + RtlMin(Rect1.Bottom, Rect2.Bottom), + RtlMin(Rect1.Right, Rect2.Right)); + return TRUE; +} + +inline BOOLEAN CsrpGetUnion( + PSMALL_RECT Union, + SMALL_RECT Rect1, + SMALL_RECT Rect2) +{ + if (CsrpIsRectEmpty(Rect1)) + { + if (CsrpIsRectEmpty(Rect2)) + { + CsrpInitRect(*Union, 0, 0, 0, 0); + return FALSE; + } + else + *Union = Rect2; + } + else + { + if (CsrpIsRectEmpty(Rect2)) + { + *Union = Rect1; + } + else + { + CsrpInitRect( + *Union, + RtlMin(Rect1.Top, Rect2.Top), + RtlMin(Rect1.Left, Rect2.Left), + RtlMax(Rect1.Bottom, Rect2.Bottom), + RtlMax(Rect1.Right, Rect2.Right)); + } + } + return TRUE; +} + +inline BOOLEAN CsrpSubtractRect( + PSMALL_RECT Subtraction, + SMALL_RECT Rect1, + SMALL_RECT Rect2) +{ + SMALL_RECT tmp; + + if (CsrpIsRectEmpty(Rect1)) + { + CsrpInitRect(*Subtraction, 0, 0, 0, 0); + return FALSE; + } + *Subtraction = Rect1; + if (CsrpGetIntersection(&tmp, Rect1, Rect2)) + { + if (CsrpIsEqualRect(tmp, *Subtraction)) + { + CsrpInitRect(*Subtraction, 0, 0, 0, 0); + return FALSE; + } + if ((tmp.Top == Subtraction->Top) && (tmp.Bottom == Subtraction->Bottom)) + { + if (tmp.Left == Subtraction->Left) + Subtraction->Left = tmp.Right; + else if (tmp.Right == Subtraction->Right) + Subtraction->Right = tmp.Left; + } + else if ((tmp.Left == Subtraction->Left) && (tmp.Right == Subtraction->Right)) + { + if (tmp.Top == Subtraction->Top) + Subtraction->Top = tmp.Bottom; + else if (tmp.Bottom == Subtraction->Bottom) + Subtraction->Bottom = tmp.Top; + } + } + return TRUE; +} + +/* + * Screen buffer must be locked when this function is called + */ +static VOID CsrpCopyRegion( + PCSRSS_SCREEN_BUFFER ScreenBuffer, + SMALL_RECT SrcRegion, + SMALL_RECT DstRegion) +{ + SHORT SrcY, DstY; + DWORD SrcOffset; + DWORD DstOffset; + DWORD BytesPerLine; + + DstY = DstRegion.Top; + BytesPerLine = CsrpRectWidth(DstRegion) * 2; + for (SrcY = SrcRegion.Top; SrcY <= SrcRegion.Bottom; SrcY++) + { + SrcOffset = (SrcY * ScreenBuffer->MaxX * 2) + (SrcRegion.Left * 2); + DstOffset = (DstY * ScreenBuffer->MaxX * 2) + (DstRegion.Left * 2); + RtlCopyMemory( + &ScreenBuffer->Buffer[DstOffset], + &ScreenBuffer->Buffer[SrcOffset], + BytesPerLine); + DstY++; + } +} + +/* + * Screen buffer must be locked when this function is called + */ +static VOID CsrpFillRegion( + PCSRSS_SCREEN_BUFFER ScreenBuffer, + SMALL_RECT Region, + CHAR_INFO CharInfo) +{ + SHORT X, Y; + DWORD Offset; + + for (Y = Region.Top; Y <= Region.Bottom; Y++) + { + Offset = (Y * ScreenBuffer->MaxX + Region.Left) * 2; + for (X = Region.Left; X <= Region.Right; X++) + { + SET_CELL_BUFFER(ScreenBuffer, Offset, CharInfo.Char.AsciiChar, CharInfo.Attributes); + } + } +} + +/* + * Screen buffer must be locked when this function is called + */ +inline NTSTATUS CsrpSetConsoleDeviceCursor(PCSRSS_SCREEN_BUFFER ScreenBuffer, SHORT X, SHORT Y) +{ + CONSOLE_SCREEN_BUFFER_INFO ScrInfo; + IO_STATUS_BLOCK Iosb; + + ScrInfo.dwCursorPosition.X = X; + ScrInfo.dwCursorPosition.Y = Y; + ScrInfo.wAttributes = ScreenBuffer->DefaultAttrib; + + return NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 ); +} + +/* + * Region - Region of virtual screen buffer to draw onto the physical console + * Screen buffer must be locked when this function is called + */ +static VOID CsrpDrawRegion( + PCSRSS_SCREEN_BUFFER ScreenBuffer, + SMALL_RECT Region) +{ + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + CONSOLE_SCREEN_BUFFER_INFO ScrInfo; + CONSOLE_MODE Mode; + int i, y; + DWORD BytesPerLine; + DWORD SrcOffset; + DWORD SrcDelta; + + Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */ + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set console mode\n" ); + return; + } + + /* blast out buffer */ + BytesPerLine = CsrpRectWidth(Region) * 2; + SrcOffset = (Region.Top * ScreenBuffer->MaxX + Region.Left) * 2; + SrcDelta = ScreenBuffer->MaxX * 2; + for( i = Region.Top - ScreenBuffer->ShowY, y = ScreenBuffer->ShowY; + i <= Region.Bottom - ScreenBuffer->ShowY; i++ ) + { + /* Position the cursor correctly */ + Status = CsrpSetConsoleDeviceCursor(ScreenBuffer, Region.Left - ScreenBuffer->ShowX, i); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set console info\n" ); + return; + } + + Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + &ScreenBuffer->Buffer[ SrcOffset ], + BytesPerLine, 0, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Write to console failed\n" ); + return; + } + + /* wrap back around the end of the buffer */ + if( ++y == ScreenBuffer->MaxY ) + y = 0; + + SrcOffset += SrcDelta; + } + Mode.dwMode = ENABLE_PROCESSED_OUTPUT; + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set console mode\n" ); + return; + } + Status = CsrpSetConsoleDeviceCursor( + ScreenBuffer, + ScreenBuffer->CurrentX - ScreenBuffer->ShowX, + ((ScreenBuffer->CurrentY + ScreenBuffer->MaxY) - ScreenBuffer->ShowY) % ScreenBuffer->MaxY); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set console info\n" ); + return; + } + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + IOCTL_CONSOLE_SET_CURSOR_INFO, &ScreenBuffer->CursorInfo, + sizeof( ScreenBuffer->CursorInfo ), 0, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set cursor info\n" ); + return; + } +} + + +CSR_API(CsrWriteConsole) +{ + BYTE *Buffer = Request->Data.WriteConsoleRequest.Buffer; + PCSRSS_SCREEN_BUFFER Buff; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + LOCK; + if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, + (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC ) + { + UNLOCK; + return Reply->Status = STATUS_INVALID_HANDLE; + } + CsrpWriteConsole( Buff, Buffer, Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE ); + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + + +NTSTATUS STDCALL CsrInitConsoleScreenBuffer( PCSRSS_SCREEN_BUFFER Console ) +{ + Console->Header.Type = CSRSS_SCREEN_BUFFER_MAGIC; + Console->Header.ReferenceCount = 0; + Console->MaxX = PhysicalConsoleSize.X; + Console->MaxY = PhysicalConsoleSize.Y * 2; + Console->ShowX = 0; + Console->ShowY = 0; + Console->CurrentX = 0; + Console->CurrentY = 0; + Console->Buffer = RtlAllocateHeap( CsrssApiHeap, 0, Console->MaxX * Console->MaxY * 2 ); + if( Console->Buffer == 0 ) + return STATUS_INSUFFICIENT_RESOURCES; + Console->DefaultAttrib = 0x17; + /* initialize buffer to be empty with default attributes */ + for( ; Console->CurrentY < Console->MaxY; Console->CurrentY++ ) + { + ClearLineBuffer (Console, 0); + } + Console->CursorInfo.bVisible = TRUE; + Console->CursorInfo.dwSize = 5; + Console->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; + Console->CurrentX = 0; + Console->CurrentY = 0; + return STATUS_SUCCESS; +} + +VOID STDCALL CsrDeleteScreenBuffer( PCSRSS_SCREEN_BUFFER Buffer ) +{ + RtlFreeHeap( CsrssApiHeap, 0, Buffer->Buffer ); + RtlFreeHeap( CsrssApiHeap, 0, Buffer ); +} + +NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + + Console->Title.MaximumLength = Console->Title.Length = 0; + Console->Title.Buffer = 0; + + RtlCreateUnicodeString( &Console->Title, L"Command Prompt" ); + + Console->Header.ReferenceCount = 0; + Console->WaitingChars = 0; + Console->WaitingLines = 0; + Console->EchoCount = 0; + Console->Header.Type = CSRSS_CONSOLE_MAGIC; + Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT; + Console->EarlyReturn = FALSE; + InitializeListHead(&Console->InputEvents); + + InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL); + + Status = NtCreateEvent( &Console->ActiveEvent, STANDARD_RIGHTS_ALL, &ObjectAttributes, FALSE, FALSE ); + if( !NT_SUCCESS( Status ) ) + { + return Status; + } + Console->ActiveBuffer = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_SCREEN_BUFFER ) ); + if( !Console->ActiveBuffer ) + { + NtClose( Console->ActiveEvent ); + return STATUS_INSUFFICIENT_RESOURCES; + } + Status = CsrInitConsoleScreenBuffer( Console->ActiveBuffer ); + if( !NT_SUCCESS( Status ) ) + { + NtClose( Console->ActiveEvent ); + RtlFreeHeap( CsrssApiHeap, 0, Console->ActiveBuffer ); + return Status; + } + /* add a reference count because the buffer is tied to the console */ + Console->ActiveBuffer->Header.ReferenceCount++; + /* make console active, and insert into console list */ + LOCK; + if( ActiveConsole ) + { + Console->Prev = ActiveConsole; + Console->Next = ActiveConsole->Next; + ActiveConsole->Next->Prev = Console; + ActiveConsole->Next = Console; + } + else { + Console->Prev = Console; + Console->Next = Console; + } + ActiveConsole = Console; + /* copy buffer contents to screen */ + CsrDrawConsole( Console->ActiveBuffer ); + UNLOCK; + return STATUS_SUCCESS; +} + +/*************************************************************** + * CsrDrawConsole blasts the console buffer onto the screen * + * must be called while holding the active console lock * + **************************************************************/ +VOID STDCALL CsrDrawConsole( PCSRSS_SCREEN_BUFFER Buff ) +{ + SMALL_RECT Region; + + CsrpInitRect( + Region, + Buff->ShowY, + Buff->ShowX, + Buff->ShowY + PhysicalConsoleSize.Y - 1, + Buff->ShowX + PhysicalConsoleSize.X - 1); + + CsrpDrawRegion(Buff, Region); +} + + +VOID STDCALL CsrDeleteConsole( PCSRSS_CONSOLE Console ) +{ + ConsoleInput *Event; + DPRINT( "CsrDeleteConsole\n" ); + LOCK; + /* Drain input event queue */ + while( Console->InputEvents.Flink != &Console->InputEvents ) + { + Event = (ConsoleInput *)Console->InputEvents.Flink; + Console->InputEvents.Flink = Console->InputEvents.Flink->Flink; + Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents; + RtlFreeHeap( CsrssApiHeap, 0, Event ); + } + /* Switch to next console */ + if( ActiveConsole == Console ) + { + if( Console->Next != Console ) + { + ActiveConsole = Console->Next; + Console->Prev->Next = Console->Next; + Console->Next->Prev = Console->Prev; + } + else ActiveConsole = 0; + } + if( ActiveConsole ) + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + UNLOCK; + if( !--Console->ActiveBuffer->Header.ReferenceCount ) + CsrDeleteScreenBuffer( Console->ActiveBuffer ); + NtClose( Console->ActiveEvent ); + RtlFreeUnicodeString( &Console->Title ); + RtlFreeHeap( CsrssApiHeap, 0, Console ); +} + +VOID STDCALL CsrInitConsoleSupport(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DeviceName; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + CONSOLE_SCREEN_BUFFER_INFO ScrInfo; + + DPRINT("CSR: CsrInitConsoleSupport()\n"); + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\BlueScreen"); + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + Status = NtOpenFile(&ConsoleDeviceHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CSR: Failed to open console. Expect problems.\n"); + } + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\Keyboard"); + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + Status = NtOpenFile(&KeyboardDeviceHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CSR: Failed to open keyboard. Expect problems.\n"); + } + + ActiveConsole = 0; + RtlInitializeCriticalSection( &ActiveConsoleLock ); + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, &ScrInfo, sizeof( ScrInfo ) ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to get console info, expect trouble\n" ); + return; + } + PhysicalConsoleSize = ScrInfo.dwSize; +} + +VOID Console_Api( DWORD RefreshEvent ) +{ + /* keep reading events from the keyboard and stuffing them into the current + console's input queue */ + ConsoleInput *KeyEventRecord; + ConsoleInput *TempInput; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + HANDLE Events[2]; // 0 = keyboard, 1 = refresh + int c; + int updown; + PCSRSS_CONSOLE SwapConsole = 0; // console we are thinking about swapping with + + Events[0] = 0; + Status = NtCreateEvent( &Events[0], STANDARD_RIGHTS_ALL, NULL, FALSE, FALSE ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: NtCreateEvent failed: %x\n", Status ); + NtTerminateProcess( NtCurrentProcess(), Status ); + } + Events[1] = (HANDLE)RefreshEvent; + while( 1 ) + { + KeyEventRecord = RtlAllocateHeap(CsrssApiHeap, + 0, + sizeof(ConsoleInput)); + if ( KeyEventRecord == 0 ) + { + DbgPrint( "CSR: Memory allocation failure!" ); + continue; + } + KeyEventRecord->InputEvent.EventType = KEY_EVENT; + Status = NtReadFile( KeyboardDeviceHandle, Events[0], NULL, NULL, &Iosb, + &KeyEventRecord->InputEvent.Event.KeyEvent, sizeof( KEY_EVENT_RECORD ), NULL, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: ReadFile on keyboard device failed\n" ); + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; + } + if( Status == STATUS_PENDING ) + { + while( 1 ) + { + Status = NtWaitForMultipleObjects( 2, Events, WaitAny, FALSE, NULL ); + if( Status == STATUS_WAIT_0 + 1 ) + { + LOCK; + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + UNLOCK; + continue; + } + else if( Status != STATUS_WAIT_0 ) + { + DbgPrint( "CSR: NtWaitForMultipleObjects failed: %x, exiting\n", Status ); + NtTerminateProcess( NtCurrentProcess(), Status ); + } + else break; + } + } + if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & + ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED )&& + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_TAB ) + if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) + { + ANSI_STRING Title; + void * Buffer; + COORD *pos; + unsigned int src, dst; + + /* alt-tab, swap consoles */ + // move SwapConsole to next console, and print its title + LOCK; + if( !SwapConsole ) + SwapConsole = ActiveConsole; + + if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED ) + SwapConsole = SwapConsole->Prev; + else SwapConsole = SwapConsole->Next; + Title.MaximumLength = RtlUnicodeStringToAnsiSize( &SwapConsole->Title ); + Title.Length = 0; + Buffer = RtlAllocateHeap( CsrssApiHeap, + 0, + sizeof( COORD ) + Title.MaximumLength ); + pos = (COORD *)Buffer; + Title.Buffer = Buffer + sizeof( COORD ); + + /* this does not seem to work + RtlUnicodeStringToAnsiString( &Title, &SwapConsole->Title, FALSE ); */ + // temp hack + for( src = 0, dst = 0; src < SwapConsole->Title.Length; src++, dst++ ) + Title.Buffer[dst] = (char)SwapConsole->Title.Buffer[dst]; + + pos->Y = PhysicalConsoleSize.Y / 2; + pos->X = ( PhysicalConsoleSize.X - Title.MaximumLength ) / 2; + // redraw the console to clear off old title + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, + 0, + 0, + Buffer, + sizeof (COORD) + Title.MaximumLength ); + if( !NT_SUCCESS( Status ) ) + { + DPRINT1( "Error writing to console\n" ); + } + RtlFreeHeap( CsrssApiHeap, 0, Buffer ); + + UNLOCK; + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; + } + else { + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; + } + else if( SwapConsole && + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_MENU && + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE ) + { + // alt key released, swap consoles + PCSRSS_CONSOLE tmp; + + LOCK; + if( SwapConsole != ActiveConsole ) + { + // first remove swapconsole from the list + SwapConsole->Prev->Next = SwapConsole->Next; + SwapConsole->Next->Prev = SwapConsole->Prev; + // now insert before activeconsole + SwapConsole->Next = ActiveConsole; + SwapConsole->Prev = ActiveConsole->Prev; + ActiveConsole->Prev->Next = SwapConsole; + ActiveConsole->Prev = SwapConsole; + } + ActiveConsole = SwapConsole; + SwapConsole = 0; + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + + UNLOCK; + } + if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & + ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && + ( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) ) + { + if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) + { + /* scroll up or down */ + LOCK; + if( ActiveConsole == 0 ) + { + DbgPrint( "CSR: No Active Console!\n" ); + UNLOCK; + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; + } + if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ) + { + /* only scroll up if there is room to scroll up into */ + if( ActiveConsole->ActiveBuffer->ShowY != ((ActiveConsole->ActiveBuffer->CurrentY + 1) % + ActiveConsole->ActiveBuffer->MaxY) ) + ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + + ActiveConsole->ActiveBuffer->MaxY - 1) % ActiveConsole->ActiveBuffer->MaxY; + } + else if( ActiveConsole->ActiveBuffer->ShowY != ActiveConsole->ActiveBuffer->CurrentY ) + /* only scroll down if there is room to scroll down into */ + if( ActiveConsole->ActiveBuffer->ShowY % ActiveConsole->ActiveBuffer->MaxY != + ActiveConsole->ActiveBuffer->CurrentY ) + + if( ((ActiveConsole->ActiveBuffer->CurrentY + 1) % ActiveConsole->ActiveBuffer->MaxY) != + (ActiveConsole->ActiveBuffer->ShowY + PhysicalConsoleSize.Y) % ActiveConsole->ActiveBuffer->MaxY ) + ActiveConsole->ActiveBuffer->ShowY = (ActiveConsole->ActiveBuffer->ShowY + 1) % + ActiveConsole->ActiveBuffer->MaxY; + CsrDrawConsole( ActiveConsole->ActiveBuffer ); + UNLOCK; + } + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; + } + LOCK; + if( ActiveConsole == 0 ) + { + DbgPrint( "CSR: No Active Console!\n" ); + UNLOCK; + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + continue; + } + // process special keys if enabled + if( ActiveConsole->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) ) + switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar ) + { + case '\r': + // add a \n to the queue as well + // first add the \r + updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown; + KeyEventRecord->Echoed = FALSE; + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r'; + InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry); + ActiveConsole->WaitingChars++; + KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) ); + if( !KeyEventRecord ) + { + DbgPrint( "CSR: Failed to allocate KeyEventRecord\n" ); + UNLOCK; + continue; + } + KeyEventRecord->InputEvent.EventType = KEY_EVENT; + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown; + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0; + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0; + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n'; + } + // add event to the queue + InsertTailList(&ActiveConsole->InputEvents, &KeyEventRecord->ListEntry); + // if line input mode is enabled, only wake the client on enter key down + if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT ) || + ActiveConsole->EarlyReturn || + ( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' && + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) ) + { + NtSetEvent( ActiveConsole->ActiveEvent, 0 ); + if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' ) + ActiveConsole->WaitingLines++; + } + KeyEventRecord->Echoed = FALSE; + if( ActiveConsole->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) && + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' && + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown ) + { + // walk the input queue looking for a char to backspace + for( TempInput = (ConsoleInput *)ActiveConsole->InputEvents.Blink; + TempInput != (ConsoleInput *)&ActiveConsole->InputEvents && + (TempInput->InputEvent.EventType != KEY_EVENT || + TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE || + TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' ); + TempInput = (ConsoleInput *)TempInput->ListEntry.Blink ); + // if we found one, delete it, otherwise, wake the client + if( TempInput != (ConsoleInput *)&ActiveConsole->InputEvents ) + { + // delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue + RemoveEntryList(&TempInput->ListEntry); + if( TempInput->Echoed ) + CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); + RtlFreeHeap( CsrssApiHeap, 0, TempInput ); + RemoveEntryList(&KeyEventRecord->ListEntry); + RtlFreeHeap( CsrssApiHeap, 0, KeyEventRecord ); + ActiveConsole->WaitingChars -= 2; + } + else NtSetEvent( ActiveConsole->ActiveEvent, 0 ); + } + else { + // echo chars if we are supposed to and client is waiting for some + if( ( ActiveConsole->Mode & ENABLE_ECHO_INPUT ) && ActiveConsole->EchoCount && + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar && + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE && + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' ) + { + // mark the char as already echoed + CsrpWriteConsole( ActiveConsole->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); + ActiveConsole->EchoCount--; + KeyEventRecord->Echoed = TRUE; + } + } + ActiveConsole->WaitingChars++; + if( !(ActiveConsole->Mode & ENABLE_LINE_INPUT) ) + NtSetEvent( ActiveConsole->ActiveEvent, 0 ); + UNLOCK; + } +} + +CSR_API(CsrGetScreenBufferInfo) +{ + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER Buff; + PCONSOLE_SCREEN_BUFFER_INFO pInfo; + IO_STATUS_BLOCK Iosb; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + LOCK; + if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, + (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC ) + { + UNLOCK; + return Reply->Status = STATUS_INVALID_HANDLE; + } + pInfo = &Reply->Data.ScreenBufferInfoReply.Info; + if( Buff == ActiveConsole->ActiveBuffer ) + { + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, pInfo, sizeof( *pInfo ) ); + if( !NT_SUCCESS( Status ) ) + DbgPrint( "CSR: Failed to get console info, expect trouble\n" ); + Reply->Status = Status; + } + else { + pInfo->dwSize.X = PhysicalConsoleSize.X; + pInfo->dwSize.Y = PhysicalConsoleSize.Y; + pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX; + pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY; + pInfo->wAttributes = Buff->DefaultAttrib; + pInfo->srWindow.Left = 0; + pInfo->srWindow.Right = PhysicalConsoleSize.X - 1; + pInfo->srWindow.Top = 0; + pInfo->srWindow.Bottom = PhysicalConsoleSize.Y - 1; + Reply->Status = STATUS_SUCCESS; + } + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrSetCursor) +{ + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER Buff; + CONSOLE_SCREEN_BUFFER_INFO Info; + IO_STATUS_BLOCK Iosb; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + LOCK; + if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, + (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC ) + { + UNLOCK; + return Reply->Status = STATUS_INVALID_HANDLE; + } + Info.dwCursorPosition = Request->Data.SetCursorRequest.Position; + Info.wAttributes = Buff->DefaultAttrib; + if( Buff == ActiveConsole->ActiveBuffer ) + { + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, + IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &Info, sizeof( Info ), 0, 0 ); + if( !NT_SUCCESS( Status ) ) + DbgPrint( "CSR: Failed to set console info, expect trouble\n" ); + } + + Buff->CurrentX = Info.dwCursorPosition.X + Buff->ShowX; + Buff->CurrentY = (Info.dwCursorPosition.Y + Buff->ShowY) % Buff->MaxY; + UNLOCK; + return Reply->Status = Status; +} + +CSR_API(CsrWriteConsoleOutputChar) +{ + BYTE *Buffer = Request->Data.WriteConsoleOutputCharRequest.String; + PCSRSS_SCREEN_BUFFER Buff; + DWORD X, Y; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + LOCK; + if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC ) + { + UNLOCK; + return Reply->Status = STATUS_INVALID_HANDLE; + } + X = Buff->CurrentX; + Y = Buff->CurrentY; + Buff->CurrentX = Request->Data.WriteConsoleOutputCharRequest.Coord.X; + Buff->CurrentY = Request->Data.WriteConsoleOutputCharRequest.Coord.Y; + Buffer[Request->Data.WriteConsoleOutputCharRequest.Length] = 0; + CsrpWriteConsole( Buff, Buffer, Request->Data.WriteConsoleOutputCharRequest.Length, FALSE ); + if( ActiveConsole->ActiveBuffer == Buff ) + { + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, + 0, + 0, + &Request->Data.WriteConsoleOutputCharRequest.Coord, + sizeof (COORD) + Request->Data.WriteConsoleOutputCharRequest.Length ); + if( !NT_SUCCESS( Status ) ) + DPRINT1( "Failed to write output chars: %x\n", Status ); + } + Reply->Data.WriteConsoleOutputCharReply.EndCoord.X = Buff->CurrentX - Buff->ShowX; + Reply->Data.WriteConsoleOutputCharReply.EndCoord.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY; + Buff->CurrentY = Y; + Buff->CurrentX = X; + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + +CSR_API(CsrFillOutputChar) +{ + PCSRSS_SCREEN_BUFFER Buff; + DWORD X, Y, i; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + LOCK; + if( !NT_SUCCESS( CsrGetObject( ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC ) + { + UNLOCK; + return Reply->Status = STATUS_INVALID_HANDLE; + } + X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX; + Y = Request->Data.FillOutputRequest.Position.Y + Buff->ShowY; + for( i = 0; i < 20000; i++ ); + for( i = 0; i < Request->Data.FillOutputRequest.Length; i++ ) + { + Buff->Buffer[ (Y * 2 * Buff->MaxX) + (X * 2) ] = Request->Data.FillOutputRequest.Char; + if( ++X == Buff->MaxX ) + { + if( ++Y == Buff->MaxY ) + Y = 0; + X = 0; + } + } + if( Buff == ActiveConsole->ActiveBuffer ) + CsrDrawConsole( Buff ); + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrReadInputEvent) +{ + PLIST_ENTRY CurrentEntry; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + ConsoleInput *Input; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + Reply->Data.ReadInputReply.Event = ProcessData->ConsoleEvent; + + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CSRSS_CONSOLE_MAGIC ? 0 : STATUS_INVALID_HANDLE)) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + + // only get input if there is any + if( Console->InputEvents.Flink != &Console->InputEvents ) + { + CurrentEntry = RemoveHeadList(&Console->InputEvents); + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + Reply->Data.ReadInputReply.Input = Input->InputEvent; + + if( Input->InputEvent.EventType == KEY_EVENT ) + { + if( Console->Mode & ENABLE_LINE_INPUT && + Input->InputEvent.Event.KeyEvent.bKeyDown == FALSE && + Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' ) + Console->WaitingLines--; + Console->WaitingChars--; + } + RtlFreeHeap( CsrssApiHeap, 0, Input ); + Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents) ? TRUE : FALSE; + Status = STATUS_SUCCESS; + Console->EarlyReturn = FALSE; // clear early return + } + else { + Status = STATUS_PENDING; + Console->EarlyReturn = TRUE; // mark for early return + } + UNLOCK; + return Reply->Status = Status; +} + +CSR_API(CsrWriteConsoleOutputAttrib) +{ + int c; + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + int X, Y; + IO_STATUS_BLOCK Iosb; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + X = Buff->CurrentX; + Y = Buff->CurrentY; + Buff->CurrentX = Request->Data.WriteConsoleOutputAttribRequest.Coord.X + Buff->ShowX; + Buff->CurrentY = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY; + for( c = 0; c < Request->Data.WriteConsoleOutputAttribRequest.Length; c++ ) + { + Buff->Buffer[(Buff->CurrentY * Buff->MaxX * 2) + (Buff->CurrentX * 2) + 1] = Request->Data.WriteConsoleOutputAttribRequest.String[c]; + if( ++Buff->CurrentX == Buff->MaxX ) + { + Buff->CurrentX = 0; + if( ++Buff->CurrentY == Buff->MaxY ) + Buff->CurrentY = 0; + } + } + if( Buff == ActiveConsole->ActiveBuffer ) + { + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE, + 0, + 0, + &Request->Data.WriteConsoleOutputAttribRequest.Coord, + Request->Data.WriteConsoleOutputAttribRequest.Length + + sizeof (COORD) ); + if( !NT_SUCCESS( Status ) ) + DPRINT1( "Failed to write output attributes to console\n" ); + } + Reply->Data.WriteConsoleOutputAttribReply.EndCoord.X = Buff->CurrentX - Buff->ShowX; + Reply->Data.WriteConsoleOutputAttribReply.EndCoord.Y = ( Buff->CurrentY + Buff->MaxY - Buff->ShowY ) % Buff->MaxY; + Buff->CurrentX = X; + Buff->CurrentY = Y; + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + +CSR_API(CsrFillOutputAttrib) +{ + int c; + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + int X, Y; + IO_STATUS_BLOCK Iosb; + OUTPUT_ATTRIBUTE Attr; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + X = Buff->CurrentX; + Y = Buff->CurrentY; + Buff->CurrentX = Request->Data.FillOutputAttribRequest.Coord.X + Buff->ShowX; + Buff->CurrentY = Request->Data.FillOutputAttribRequest.Coord.Y + Buff->ShowY; + for( c = 0; c < Request->Data.FillOutputAttribRequest.Length; c++ ) + { + Buff->Buffer[(Buff->CurrentY * Buff->MaxX * 2) + (Buff->CurrentX * 2) + 1] = Request->Data.FillOutputAttribRequest.Attribute; + if( ++Buff->CurrentX == Buff->MaxX ) + { + Buff->CurrentX = 0; + if( ++Buff->CurrentY == Buff->MaxY ) + Buff->CurrentY = 0; + } + } + if( Buff == ActiveConsole->ActiveBuffer ) + { + Attr.wAttribute = Request->Data.FillOutputAttribRequest.Attribute; + Attr.nLength = Request->Data.FillOutputAttribRequest.Length; + Attr.dwCoord = Request->Data.FillOutputAttribRequest.Coord; + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE, + &Attr, + sizeof (Attr), + 0, + 0 ); + if( !NT_SUCCESS( Status ) ) + DPRINT1( "Failed to fill output attribute\n" ); + } + Buff->CurrentX = X; + Buff->CurrentY = Y; + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + + +CSR_API(CsrGetCursorInfo) +{ + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + Reply->Data.GetCursorInfoReply.Info = Buff->CursorInfo; + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + +CSR_API(CsrSetCursorInfo) +{ + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, + Request->Data.SetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff ); + + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + Buff->CursorInfo = Request->Data.SetCursorInfoRequest.Info; + if( Buff == ActiveConsole->ActiveBuffer ) + { + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_CURSOR_INFO, &Buff->CursorInfo, sizeof( Buff->CursorInfo ), 0, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set cursor info\n" ); + return Reply->Status = Status; + } + } + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + +CSR_API(CsrSetTextAttrib) +{ + NTSTATUS Status; + CONSOLE_SCREEN_BUFFER_INFO ScrInfo; + IO_STATUS_BLOCK Iosb; + PCSRSS_SCREEN_BUFFER Buff; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.SetAttribRequest.ConsoleHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib; + if( Buff == ActiveConsole->ActiveBuffer ) + { + ScrInfo.wAttributes = Buff->DefaultAttrib; + ScrInfo.dwCursorPosition.X = Buff->CurrentX - Buff->ShowX; + ScrInfo.dwCursorPosition.Y = ((Buff->CurrentY + Buff->MaxY) - Buff->ShowY) % Buff->MaxY; + Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: Failed to set console info\n" ); + UNLOCK; + return Reply->Status = Status; + } + } + UNLOCK; + return Reply->Status = STATUS_SUCCESS; +} + +CSR_API(CsrSetConsoleMode) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, + Request->Data.SetConsoleModeRequest.ConsoleHandle, + (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) ) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + + Buff = (PCSRSS_SCREEN_BUFFER)Console; + if( Console->Header.Type == CSRSS_CONSOLE_MAGIC ) + Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID; + else if( Console->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ) + Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID; + else { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return Status; + } + UNLOCK; + Reply->Status = STATUS_SUCCESS; + return Reply->Status; +} + +CSR_API(CsrGetConsoleMode) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */ + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, + Request->Data.GetConsoleModeRequest.ConsoleHandle, + (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) ) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + Reply->Status = STATUS_SUCCESS; + Buff = (PCSRSS_SCREEN_BUFFER)Console; + if( Console->Header.Type == CSRSS_CONSOLE_MAGIC ) + Reply->Data.GetConsoleModeReply.ConsoleMode = Console->Mode; + else if( Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ) + Reply->Data.GetConsoleModeReply.ConsoleMode = Buff->Mode; + else Status = STATUS_INVALID_HANDLE; + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrCreateScreenBuffer) +{ + PCSRSS_SCREEN_BUFFER Buff = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( CSRSS_SCREEN_BUFFER ) ); + NTSTATUS Status; + + Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + if( !Buff ) + Reply->Status = STATUS_INSUFFICIENT_RESOURCES; + LOCK; + Status = CsrInitConsoleScreenBuffer( Buff ); + if( !NT_SUCCESS( Status ) ) + Reply->Status = Status; + else { + Status = CsrInsertObject( ProcessData, &Reply->Data.CreateScreenBufferReply.OutputHandle, &Buff->Header ); + if( !NT_SUCCESS( Status ) ) + Reply->Status = Status; + else Reply->Status = STATUS_SUCCESS; + } + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrSetScreenBuffer) +{ + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER Buff; + + Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.SetActiveScreenBufferRequest.OutputHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) ) + Reply->Status = Status; + else { + // drop reference to old buffer, maybe delete + if( !InterlockedDecrement( &ProcessData->Console->ActiveBuffer->Header.ReferenceCount ) ) + CsrDeleteScreenBuffer( ProcessData->Console->ActiveBuffer ); + // tie console to new buffer + ProcessData->Console->ActiveBuffer = Buff; + // inc ref count on new buffer + InterlockedIncrement( &Buff->Header.ReferenceCount ); + // if the console is active, redraw it + if( ActiveConsole == ProcessData->Console ) + CsrDrawConsole( Buff ); + Reply->Status = STATUS_SUCCESS; + } + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrSetTitle) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + + Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.SetTitleRequest.Console, (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) ) + Reply->Status = Status; + else { + // copy title to console + RtlFreeUnicodeString( &Console->Title ); + RtlCreateUnicodeString( &Console->Title, Request->Data.SetTitleRequest.Title ); + Reply->Status = STATUS_SUCCESS; + } + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrGetTitle) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + + Reply->Header.MessageSize = sizeof (CSRSS_API_REPLY); + Reply->Header.DataSize = + sizeof (CSRSS_API_REPLY) + - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject ( + ProcessData, + Request->Data.GetTitleRequest.ConsoleHandle, + (Object_t **) & Console + ); + if ( !NT_SUCCESS( Status ) ) + { + Reply->Status = Status; + } + else + { + HANDLE ConsoleHandle = Request->Data.GetTitleRequest.ConsoleHandle; + + /* Copy title of the console to the user title buffer */ + RtlZeroMemory ( + & Reply->Data.GetTitleReply, + sizeof (CSRSS_GET_TITLE_REPLY) + ); + Reply->Data.GetTitleReply.ConsoleHandle = ConsoleHandle; + Reply->Data.GetTitleReply.Length = Console->Title.Length; + wcscpy (Reply->Data.GetTitleReply.Title, Console->Title.Buffer); + Reply->Status = STATUS_SUCCESS; + } + UNLOCK; + return Reply->Status; +} + +CSR_API(CsrWriteConsoleOutput) +{ + SHORT i, X, Y, SizeX, SizeY; + PCSRSS_SCREEN_BUFFER Buff; + SMALL_RECT ScreenBuffer; + CHAR_INFO* CurCharInfo; + SMALL_RECT WriteRegion; + CHAR_INFO* CharInfo; + COORD BufferCoord; + COORD BufferSize; + NTSTATUS Status; + DWORD Offset; + DWORD PSize; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputRequest.ConsoleHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + + BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize; + PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO); + BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord; + CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo; + if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase) || + (((PVOID)CharInfo + PSize) > + (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + UNLOCK; + Reply->Status = STATUS_ACCESS_VIOLATION; + return(Reply->Status); + } + WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion; + + SizeY = RtlMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(WriteRegion)); + SizeX = RtlMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(WriteRegion)); + WriteRegion.Bottom = WriteRegion.Top + SizeY; + WriteRegion.Right = WriteRegion.Left + SizeX; + + /* Make sure WriteRegion is inside the screen buffer */ + CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); + if (!CsrpGetIntersection(&WriteRegion, ScreenBuffer, WriteRegion)) + { + UNLOCK; + /* It is okay to have a WriteRegion completely outside the screen buffer. + No data is written then. */ + return (Reply->Status = STATUS_SUCCESS); + } + + for ( i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++ ) + { + CurCharInfo = CharInfo + (i * BufferSize.Y); + Offset = (Y * Buff->MaxX + WriteRegion.Left) * 2; + for ( X = WriteRegion.Left; X <= WriteRegion.Right; X++ ) + { + SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes); + CurCharInfo++; + } + } + + if( Buff == ActiveConsole->ActiveBuffer ) + { + CsrpDrawRegion( ActiveConsole->ActiveBuffer, WriteRegion ); + } + + UNLOCK; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Right = WriteRegion.Left + SizeX - 1; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1; + return (Reply->Status = STATUS_SUCCESS); +} + +CSR_API(CsrFlushInputBuffer) +{ + PLIST_ENTRY CurrentEntry; + PLIST_ENTRY NextEntry; + PCSRSS_CONSOLE Console; + ConsoleInput* Input; + NTSTATUS Status; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, Request->Data.FlushInputBufferRequest.ConsoleInput, (Object_t **)&Console ); + if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CSRSS_CONSOLE_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + + /* Discard all entries in the input event queue */ + CurrentEntry = Console->InputEvents.Flink; + while (IsListEmpty(&Console->InputEvents)) + { + NextEntry = CurrentEntry->Flink; + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + /* Destroy the event */ + Console->WaitingChars--; + RtlFreeHeap( CsrssApiHeap, 0, Input ); + CurrentEntry = NextEntry; + } + UNLOCK; + + return (Reply->Status = STATUS_SUCCESS); +} + +CSR_API(CsrScrollConsoleScreenBuffer) +{ + SHORT i, X, Y, SizeX, SizeY; + PCSRSS_SCREEN_BUFFER Buff; + SMALL_RECT ScreenBuffer; + SMALL_RECT SrcRegion; + SMALL_RECT DstRegion; + SMALL_RECT FillRegion; + IO_STATUS_BLOCK Iosb; + CHAR_INFO* CharInfo; + NTSTATUS Status; + DWORD SrcOffset; + DWORD DstOffset; + BOOLEAN DoFill; + + ALIAS(ConsoleHandle,Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle); + ALIAS(ScrollRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle); + ALIAS(UseClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle); + ALIAS(ClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle); + ALIAS(DestinationOrigin,Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin); + ALIAS(Fill,Request->Data.ScrollConsoleScreenBufferRequest.Fill); + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + LOCK; + Status = CsrGetObject( ProcessData, ConsoleHandle, (Object_t **)&Buff ); + if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CSRSS_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE )) + { + Reply->Status = Status; + UNLOCK; + return Status; + } + + /* Make sure source rectangle is inside the screen buffer */ + CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); + if (!CsrpGetIntersection(&SrcRegion, ScreenBuffer, ScrollRectangle)) + { + UNLOCK; + return (Reply->Status = STATUS_INVALID_PARAMETER); + } + + if (UseClipRectangle) + { + if (!CsrpGetIntersection(&SrcRegion, SrcRegion, ClipRectangle)) + { + UNLOCK; + return (Reply->Status = STATUS_SUCCESS); + } + } + + + CsrpInitRect( + DstRegion, + DestinationOrigin.Y, + DestinationOrigin.X, + DestinationOrigin.Y + CsrpRectHeight(ScrollRectangle) - 1, + DestinationOrigin.X + CsrpRectWidth(ScrollRectangle) - 1) + + /* Make sure destination rectangle is inside the screen buffer */ + if (!CsrpGetIntersection(&DstRegion, DstRegion, ScreenBuffer)) + { + UNLOCK; + return (Reply->Status = STATUS_INVALID_PARAMETER); + } + + CsrpCopyRegion(Buff, SrcRegion, DstRegion); + + + /* Get the region that should be filled with the specified character and attributes */ + + DoFill = FALSE; + + CsrpGetUnion(&FillRegion, SrcRegion, DstRegion); + + if (CsrpSubtractRect(&FillRegion, FillRegion, DstRegion)) + { + /* FIXME: The subtracted rectangle is off by one line */ + FillRegion.Top += 1; + + CsrpFillRegion(Buff, FillRegion, Fill); + DoFill = TRUE; + } + + if (Buff == ActiveConsole->ActiveBuffer) + { + /* Draw destination region */ + CsrpDrawRegion(ActiveConsole->ActiveBuffer, DstRegion); + + if (DoFill) + { + /* Draw filled region */ + CsrpDrawRegion(ActiveConsole->ActiveBuffer, FillRegion); + } + } + + UNLOCK; + return(Reply->Status = STATUS_SUCCESS); +} + + +CSR_API(CsrReadConsoleOutputChar) +{ + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER ScreenBuffer; + DWORD Xpos, Ypos; + BYTE* ReadBuffer; + DWORD i; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE_HEADER); + ReadBuffer = Reply->Data.ReadConsoleOutputCharReply.String; + + LOCK; + + Status = CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, (Object_t**)&ScreenBuffer); + if (!NT_SUCCESS(Status)) + { + Reply->Status = Status; + UNLOCK; + return(Reply->Status); + } + + if (ScreenBuffer->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return(Reply->Status); + } + + Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X + ScreenBuffer->ShowX; + Ypos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + ScreenBuffer->ShowY; + + for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i) + { + *ReadBuffer = ScreenBuffer->Buffer[(Xpos * 2) + (Ypos * 2 * ScreenBuffer->MaxX)]; + + ReadBuffer++; + Xpos++; + + if (Xpos == ScreenBuffer->MaxX) + { + Xpos = 0; + Ypos++; + + if (Ypos == ScreenBuffer->MaxY) + Ypos = 0; + } + } + + *ReadBuffer = 0; + + Reply->Status = STATUS_SUCCESS; + Reply->Data.ReadConsoleOutputCharReply.EndCoord.X = Xpos - ScreenBuffer->ShowX; + Reply->Data.ReadConsoleOutputCharReply.EndCoord.Y = Ypos - ScreenBuffer->ShowY; + Reply->Header.MessageSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; + Reply->Header.DataSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; + + UNLOCK; + + return(Reply->Status); +} + + +CSR_API(CsrReadConsoleOutputAttrib) +{ + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER ScreenBuffer; + DWORD Xpos, Ypos; + CHAR* ReadBuffer; + DWORD i; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE_HEADER); + ReadBuffer = Reply->Data.ReadConsoleOutputAttribReply.String; + + LOCK; + + Status = CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, (Object_t**)&ScreenBuffer); + if (!NT_SUCCESS(Status)) + { + Reply->Status = Status; + UNLOCK; + return(Reply->Status); + } + + if (ScreenBuffer->Header.Type != CSRSS_SCREEN_BUFFER_MAGIC) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return(Reply->Status); + } + + Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X + ScreenBuffer->ShowX; + Ypos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + ScreenBuffer->ShowY; + + for (i = 0; i < Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; ++i) + { + *ReadBuffer = ScreenBuffer->Buffer[(Xpos * 2) + (Ypos * 2 * ScreenBuffer->MaxX) + 1]; + + ReadBuffer++; + Xpos++; + + if (Xpos == ScreenBuffer->MaxX) + { + Xpos = 0; + Ypos++; + + if (Ypos == ScreenBuffer->MaxY) + Ypos = 0; + } + } + + *ReadBuffer = 0; + + Reply->Status = STATUS_SUCCESS; + Reply->Data.ReadConsoleOutputAttribReply.EndCoord.X = Xpos - ScreenBuffer->ShowX; + Reply->Data.ReadConsoleOutputAttribReply.EndCoord.Y = Ypos - ScreenBuffer->ShowY; + Reply->Header.MessageSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; + Reply->Header.DataSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; + + UNLOCK; + + return(Reply->Status); +} + + +CSR_API(CsrGetNumberOfConsoleInputEvents) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PLIST_ENTRY CurrentItem; + DWORD NumEvents; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE_HEADER); + + LOCK; + + Status = CsrGetObject(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, (Object_t**)&Console); + if (!NT_SUCCESS(Status)) + { + Reply->Status = Status; + UNLOCK; + return(Reply->Status); + } + + if (Console->Header.Type != CSRSS_CONSOLE_MAGIC) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return(Reply->Status); + } + + CurrentItem = &Console->InputEvents; + NumEvents = 0; + + // If there are any events ... + if(CurrentItem->Flink != CurrentItem) + { + do + { + CurrentItem = CurrentItem->Flink; + ++NumEvents; + }while(CurrentItem != &Console->InputEvents); + } + + UNLOCK; + + Reply->Status = STATUS_SUCCESS; + Reply->Data.GetNumInputEventsReply.NumInputEvents = NumEvents; + + return Reply->Status; +} + + +CSR_API(CsrPeekConsoleInput) +{ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + DWORD Size; + DWORD Length; + PLIST_ENTRY CurrentItem; + PLIST_ENTRY NextItem; + PINPUT_RECORD InputRecord; + ConsoleInput* Item; + UINT NumItems; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE_HEADER); + + LOCK; + + Status = CsrGetObject(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, (Object_t**)&Console); + if(!NT_SUCCESS(Status)) + { + Reply->Status = Status; + UNLOCK; + return Reply->Status; + } + + if(Console->Header.Type != CSRSS_CONSOLE_MAGIC) + { + Reply->Status = STATUS_INVALID_HANDLE; + UNLOCK; + return Reply->Status; + } + + InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord; + Length = Request->Data.PeekConsoleInputRequest.Length; + Size = Length * sizeof(INPUT_RECORD); + + if(((PVOID)InputRecord < ProcessData->CsrSectionViewBase) + || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + UNLOCK; + Reply->Status = STATUS_ACCESS_VIOLATION; + return Reply->Status ; + } + + NumItems = 0; + + if(!IsListEmpty(&Console->InputEvents)) + { + CurrentItem = &Console->InputEvents; + + while(NumItems < Length) + { + ++NumItems; + Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry); + *InputRecord++ = Item->InputEvent; + + if(CurrentItem->Flink == &Console->InputEvents) + break; + else + CurrentItem = CurrentItem->Flink; + } + } + + UNLOCK; + + Reply->Status = STATUS_SUCCESS; + Reply->Data.PeekConsoleInputReply.Length = NumItems; + return Reply->Status; +} + +/* EOF */ diff --git a/subsys/csrss/api/handle.c b/subsys/csrss/api/handle.c new file mode 100644 index 0000000..9a9381f --- /dev/null +++ b/subsys/csrss/api/handle.c @@ -0,0 +1,93 @@ +/* $Id$ + * + * reactos/subsys/csrss/api/handle.c + * + * Console I/O functions + * + * ReactOS Operating System + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include +#include "api.h" +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object ) +{ + ULONG h = (((ULONG)Handle) >> 2) - 1; + // DbgPrint( "CsrGetObject, Object: %x, %x, %x\n", Object, Handle, ProcessData->HandleTableSize ); + if( h >= ProcessData->HandleTableSize ) + { + DbgPrint( "CsrGetObject returning invalid handle\n" ); + return STATUS_INVALID_HANDLE; + } + *Object = ProcessData->HandleTable[h]; + // DbgPrint( "CsrGetObject returning\n" ); + return *Object ? STATUS_SUCCESS : STATUS_INVALID_HANDLE; +} + + +NTSTATUS STDCALL CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData, + HANDLE Handle) +{ + Object_t *Object; + ULONG h = (((ULONG)Handle) >> 2) - 1; + if( h >= ProcessData->HandleTableSize || ProcessData->HandleTable[h] == 0 ) + return STATUS_INVALID_HANDLE; + /* dec ref count */ + Object = ProcessData->HandleTable[h]; + if( InterlockedDecrement( &Object->ReferenceCount ) == 0 ) + switch( Object->Type ) + { + case CSRSS_CONSOLE_MAGIC: CsrDeleteConsole( (PCSRSS_CONSOLE) Object ); + break; + case CSRSS_SCREEN_BUFFER_MAGIC: CsrDeleteScreenBuffer( (PCSRSS_SCREEN_BUFFER) Object ); + break; + default: DbgPrint( "CSR: Error: releaseing unknown object type" ); + } + ProcessData->HandleTable[h] = 0; + return STATUS_SUCCESS; +} + +NTSTATUS STDCALL CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object ) +{ + ULONG i; + PVOID* NewBlock; + + for (i = 0; i < ProcessData->HandleTableSize; i++) + { + if (ProcessData->HandleTable[i] == NULL) + { + ProcessData->HandleTable[i] = Object; + *Handle = (HANDLE)(((i + 1) << 2) | 0x3); + InterlockedIncrement( &Object->ReferenceCount ); + return(STATUS_SUCCESS); + } + } + NewBlock = RtlAllocateHeap(CsrssApiHeap, + HEAP_ZERO_MEMORY, + (ProcessData->HandleTableSize + 64) * + sizeof(HANDLE)); + if (NewBlock == NULL) + { + return(STATUS_UNSUCCESSFUL); + } + RtlCopyMemory(NewBlock, + ProcessData->HandleTable, + ProcessData->HandleTableSize * sizeof(HANDLE)); + RtlFreeHeap( CsrssApiHeap, 0, ProcessData->HandleTable ); + ProcessData->HandleTable = (Object_t **)NewBlock; + ProcessData->HandleTable[i] = Object; + *Handle = (HANDLE)(((i + 1) << 2) | 0x3); + InterlockedIncrement( &Object->ReferenceCount ); + ProcessData->HandleTableSize = ProcessData->HandleTableSize + 64; + return(STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/subsys/csrss/api/process.c b/subsys/csrss/api/process.c new file mode 100644 index 0000000..0165d1a --- /dev/null +++ b/subsys/csrss/api/process.c @@ -0,0 +1,261 @@ +/* $Id$ + * + * reactos/subsys/csrss/api/process.c + * + * "\windows\ApiPort" port process management functions + * + * ReactOS Operating System + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include +#include +#include "api.h" + +BOOL STDCALL W32kCleanupForProcess( INT Process ); + +#define LOCK RtlEnterCriticalSection(&ProcessDataLock) +#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock) + +/* GLOBALS *******************************************************************/ + +static ULONG NrProcess; +static PCSRSS_PROCESS_DATA ProcessData[256]; +extern CRITICAL_SECTION ActiveConsoleLock; +CRITICAL_SECTION ProcessDataLock; + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL CsrInitProcessData(VOID) +{ +/* ULONG i; + + for (i=0; i<256; i++) + { + ProcessData[i] = NULL; + } +*/ + RtlZeroMemory (ProcessData, sizeof ProcessData); + NrProcess = sizeof ProcessData / sizeof ProcessData[0]; + RtlInitializeCriticalSection( &ProcessDataLock ); +} + +PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(ULONG ProcessId) +{ + ULONG i; + + LOCK; + for (i=0; iProcessId == ProcessId) + { + UNLOCK; + return(ProcessData[i]); + } + } + for (i=0; iProcessId = ProcessId; + UNLOCK; + return(ProcessData[i]); + } + } +// DbgPrint("CSR: CsrGetProcessData() failed\n"); + UNLOCK; + return(NULL); +} + +NTSTATUS STDCALL CsrFreeProcessData(ULONG Pid) +{ + int i; + LOCK; + for( i = 0; i < NrProcess; i++ ) + { + if( ProcessData[i] && ProcessData[i]->ProcessId == Pid ) + { + //DbgPrint("CsrFreeProcessData pid: %d\n", Pid); + W32kCleanupForProcess( Pid ); //should check if win32k process + if( ProcessData[i]->HandleTable ) + { + int c; + for( c = 0; c < ProcessData[i]->HandleTableSize; c++ ) + if( ProcessData[i]->HandleTable[c] ) + CsrReleaseObject( ProcessData[i], (HANDLE)((c + 1) << 2) ); + RtlFreeHeap( CsrssApiHeap, 0, ProcessData[i]->HandleTable ); + } + if( ProcessData[i]->Console ) + { + if( InterlockedDecrement( &(ProcessData[i]->Console->Header.ReferenceCount) ) == 0 ) + CsrDeleteConsole( ProcessData[i]->Console ); + } + RtlFreeHeap( CsrssApiHeap, 0, ProcessData[i] ); + ProcessData[i] = 0; + UNLOCK; + return STATUS_SUCCESS; + } + } + UNLOCK; + return STATUS_INVALID_PARAMETER; +} + + +/********************************************************************** + * CSRSS API + *********************************************************************/ + +CSR_API(CsrCreateProcess) +{ + PCSRSS_PROCESS_DATA NewProcessData; + NTSTATUS Status; + HANDLE Process; + + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + + NewProcessData = CsrGetProcessData(Request->Data.CreateProcessRequest.NewProcessId); + if (NewProcessData == NULL) + { + Reply->Status = STATUS_NO_MEMORY; + return(STATUS_NO_MEMORY); + } + + /* Set default shutdown parameters */ + NewProcessData->ShutdownLevel = 0x280; + NewProcessData->ShutdownFlags = 0; + + if (Request->Data.CreateProcessRequest.Flags & DETACHED_PROCESS) + { + NewProcessData->Console = NULL; + } + else if (Request->Data.CreateProcessRequest.Flags & CREATE_NEW_CONSOLE) + { + PCSRSS_CONSOLE Console; + + Console = RtlAllocateHeap(CsrssApiHeap, + HEAP_ZERO_MEMORY, + sizeof(CSRSS_CONSOLE)); + Status = CsrInitConsole(Console); + if( !NT_SUCCESS( Status ) ) + { + CsrFreeProcessData( NewProcessData->ProcessId ); + Reply->Status = Status; + return Status; + } + NewProcessData->Console = Console; + Console->Header.ReferenceCount++; + } + else + { + NewProcessData->Console = ProcessData->Console; + InterlockedIncrement( &(ProcessData->Console->Header.ReferenceCount) ); + } + + if( NewProcessData->Console ) + { + CLIENT_ID ClientId; + CsrInsertObject(NewProcessData, + &Reply->Data.CreateProcessReply.InputHandle, + (Object_t *)NewProcessData->Console); + RtlEnterCriticalSection( &ActiveConsoleLock ); + CsrInsertObject( NewProcessData, + &Reply->Data.CreateProcessReply.OutputHandle, + &(NewProcessData->Console->ActiveBuffer->Header) ); + + RtlLeaveCriticalSection( &ActiveConsoleLock ); + ClientId.UniqueProcess = (HANDLE)NewProcessData->ProcessId; + Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" ); + InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) ); + CsrFreeProcessData( NewProcessData->ProcessId ); + Reply->Status = Status; + return Status; + } + Status = NtDuplicateObject( NtCurrentProcess(), NewProcessData->Console->ActiveEvent, Process, &NewProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0 ); + if( !NT_SUCCESS( Status ) ) + { + DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status ); + NtClose( Process ); + InterlockedDecrement( &(NewProcessData->Console->Header.ReferenceCount) ); + CsrFreeProcessData( NewProcessData->ProcessId ); + Reply->Status = Status; + return Status; + } + NtClose( Process ); + } + else Reply->Data.CreateProcessReply.OutputHandle = Reply->Data.CreateProcessReply.InputHandle = INVALID_HANDLE_VALUE; + + return(STATUS_SUCCESS); +} + +CSR_API(CsrTerminateProcess) +{ + NTSTATUS Status; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY) + - sizeof(LPC_MESSAGE_HEADER); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY); + + Status = CsrFreeProcessData(ProcessData->ProcessId); + + Reply->Status = Status; + return Status; +} + +CSR_API(CsrConnectProcess) +{ + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + Reply->Status = STATUS_SUCCESS; + + return(STATUS_SUCCESS); +} + +CSR_API(CsrGetShutdownParameters) +{ + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + Reply->Data.GetShutdownParametersReply.Level = ProcessData->ShutdownLevel; + Reply->Data.GetShutdownParametersReply.Flags = ProcessData->ShutdownFlags; + + Reply->Status = STATUS_SUCCESS; + + return(STATUS_SUCCESS); +} + +CSR_API(CsrSetShutdownParameters) +{ + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level; + ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags; + + Reply->Status = STATUS_SUCCESS; + + return(STATUS_SUCCESS); +} + + +/* EOF */ diff --git a/subsys/csrss/api/user.c b/subsys/csrss/api/user.c new file mode 100644 index 0000000..cf3dcb6 --- /dev/null +++ b/subsys/csrss/api/user.c @@ -0,0 +1,69 @@ +/* $Id$ + * + * reactos/subsys/csrss/api/user.c + * + * User functions + * + * ReactOS Operating System + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include +#include "api.h" +#include + +#define NDEBUG +#include + + +/* GLOBALS *******************************************************************/ + +static BOOLEAN ServicesProcessIdValid = FALSE; +static ULONG ServicesProcessId; + + +/* FUNCTIONS *****************************************************************/ + +CSR_API(CsrRegisterServicesProcess) +{ + NTSTATUS Status; + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + if (ServicesProcessIdValid == TRUE) + { + /* Only accept a single call */ + Status = STATUS_INVALID_PARAMETER; + } + else + { + ServicesProcessId = (ULONG)Request->Data.RegisterServicesProcessRequest.ProcessId; + ServicesProcessIdValid = TRUE; + Status = STATUS_SUCCESS; + } + + Reply->Status = Status; + + return(Status); +} + + +CSR_API(CsrExitReactos) +{ + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - + sizeof(LPC_MESSAGE_HEADER); + + + + Reply->Status = STATUS_NOT_IMPLEMENTED; + + return(STATUS_NOT_IMPLEMENTED); +} + +/* EOF */ diff --git a/subsys/csrss/api/wapi.c b/subsys/csrss/api/wapi.c new file mode 100644 index 0000000..745b192 --- /dev/null +++ b/subsys/csrss/api/wapi.c @@ -0,0 +1,182 @@ +/* $Id$ + * + * reactos/subsys/csrss/api/wapi.c + * + * Initialize the CSRSS subsystem server process. + * + * ReactOS Operating System + * + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include + +#include "api.h" + +/* GLOBALS *******************************************************************/ + +HANDLE CsrssApiHeap; + +/* FUNCTIONS *****************************************************************/ + +typedef NTSTATUS (*CsrFunc)( PCSRSS_PROCESS_DATA, PCSRSS_API_REQUEST, PCSRSS_API_REPLY ); + +static const CsrFunc CsrFuncs[] = { + CsrCreateProcess, + CsrTerminateProcess, + CsrWriteConsole, + CsrReadConsole, + CsrAllocConsole, + CsrFreeConsole, + CsrConnectProcess, + CsrGetScreenBufferInfo, + CsrSetCursor, + CsrFillOutputChar, + CsrReadInputEvent, + CsrWriteConsoleOutputChar, + CsrWriteConsoleOutputAttrib, + CsrFillOutputAttrib, + CsrGetCursorInfo, + CsrSetCursorInfo, + CsrSetTextAttrib, + CsrGetConsoleMode, + CsrSetConsoleMode, + CsrCreateScreenBuffer, + CsrSetScreenBuffer, + CsrSetTitle, + CsrGetTitle, + CsrWriteConsoleOutput, + CsrFlushInputBuffer, + CsrScrollConsoleScreenBuffer, + CsrReadConsoleOutputChar, + CsrReadConsoleOutputAttrib, + CsrGetNumberOfConsoleInputEvents, + CsrRegisterServicesProcess, + CsrExitReactos, + CsrGetShutdownParameters, + CsrSetShutdownParameters, + CsrPeekConsoleInput, + 0 }; + +static void Thread_Api2(HANDLE ServerPort) +{ + NTSTATUS Status; + LPC_MAX_MESSAGE LpcReply; + LPC_MAX_MESSAGE LpcRequest; + PCSRSS_API_REQUEST Request; + PCSRSS_PROCESS_DATA ProcessData; + PCSRSS_API_REPLY Reply; + + Reply = NULL; + + for (;;) + { + Status = NtReplyWaitReceivePort(ServerPort, + 0, + &Reply->Header, + &LpcRequest.Header); + if ( !NT_SUCCESS( Status ) ) + { + DisplayString(L"CSR: NtReplyWaitReceivePort failed\n"); + } + + if ( LpcRequest.Header.MessageType == LPC_PORT_CLOSED ) + + { + CsrFreeProcessData( (ULONG)LpcRequest.Header.Cid.UniqueProcess ); + NtClose(ServerPort); + NtTerminateThread(NtCurrentThread(), STATUS_SUCCESS); + continue; + } + + Request = (PCSRSS_API_REQUEST)&LpcRequest; + Reply = (PCSRSS_API_REPLY)&LpcReply; + + ProcessData = CsrGetProcessData( + (ULONG)LpcRequest.Header.Cid.UniqueProcess); + +// DisplayString(L"CSR: Received request\n"); + if( Request->Type >= (sizeof( CsrFuncs ) / sizeof( CsrFunc )) - 1 ) + Reply->Status = STATUS_INVALID_SYSTEM_SERVICE; + else CsrFuncs[ Request->Type ]( ProcessData, Request, Reply ); + } +} + +/********************************************************************** + * NAME + * Thread_Api + * + * DESCRIPTION + * Handle connection requests from clients to the port + * "\Windows\ApiPort". + */ +void Thread_Api(PVOID PortHandle) +{ + NTSTATUS Status; + LPC_MAX_MESSAGE Request; + HANDLE ServerPort; + HANDLE ServerThread; + PCSRSS_PROCESS_DATA ProcessData; + + CsrInitProcessData(); + + for (;;) + { + LPC_SECTION_READ LpcRead; + + Status = NtListenPort(PortHandle, &Request.Header); + if (!NT_SUCCESS(Status)) + { + DisplayString(L"CSR: NtListenPort() failed\n"); + NtTerminateThread(NtCurrentThread(), Status); + } + + Status = NtAcceptConnectPort(&ServerPort, + PortHandle, + NULL, + 1, + 0, + &LpcRead); + if (!NT_SUCCESS(Status)) + { + DisplayString(L"CSR: NtAcceptConnectPort() failed\n"); + NtTerminateThread(NtCurrentThread(), Status); + } + + ProcessData = CsrGetProcessData((ULONG)Request.Header.Cid.UniqueProcess); + ProcessData->CsrSectionViewBase = LpcRead.ViewBase; + ProcessData->CsrSectionViewSize = LpcRead.ViewSize; + + Status = NtCompleteConnectPort(ServerPort); + if (!NT_SUCCESS(Status)) + { + DisplayString(L"CSR: NtCompleteConnectPort() failed\n"); + NtTerminateThread(NtCurrentThread(), Status); + } + + Status = RtlCreateUserThread(NtCurrentProcess(), + NULL, + FALSE, + 0, + NULL, + NULL, + (PTHREAD_START_ROUTINE)Thread_Api2, + ServerPort, + &ServerThread, + NULL); + if (!NT_SUCCESS(Status)) + { + DisplayString(L"CSR: Unable to create server thread\n"); + NtClose(ServerPort); + NtTerminateThread(NtCurrentThread(), Status); + } + NtClose(ServerThread); + } +} + +/* EOF */ diff --git a/subsys/csrss/csrss.c b/subsys/csrss/csrss.c new file mode 100644 index 0000000..b630d2c --- /dev/null +++ b/subsys/csrss/csrss.c @@ -0,0 +1,137 @@ +/* $Id$ + * + * csrss.c - Client/Server Runtime subsystem + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * 19990417 (Emanuele Aliberti) + * Do nothing native application skeleton + * 19990528 (Emanuele Aliberti) + * Compiled successfully with egcs 1.1.2 + * 19990605 (Emanuele Aliberti) + * First standalone run under ReactOS (it + * actually does nothing but running). + */ +#include +#include +#include + +#include "api.h" + +/* Native process' entry point */ + +VOID STDCALL NtProcessStartup(PPEB Peb) +{ + PRTL_USER_PROCESS_PARAMETERS ProcParams; + PWSTR ArgBuffer; + PWSTR *argv; + ULONG argc = 0; + int i = 0; + int afterlastspace = 0; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE CsrssInitEvent; + UNICODE_STRING UnicodeString; + NTSTATUS Status; + + ProcParams = RtlNormalizeProcessParams (Peb->ProcessParameters); + + argv = (PWSTR *)RtlAllocateHeap (Peb->ProcessHeap, + 0, 512 * sizeof(PWSTR)); + ArgBuffer = (PWSTR)RtlAllocateHeap (Peb->ProcessHeap, + 0, + ProcParams->CommandLine.Length + sizeof(WCHAR)); + memcpy (ArgBuffer, + ProcParams->CommandLine.Buffer, + ProcParams->CommandLine.Length + sizeof(WCHAR)); + + while (ArgBuffer[i]) + { + if (ArgBuffer[i] == L' ') + { + argc++; + ArgBuffer[i] = L'\0'; + argv[argc-1] = &(ArgBuffer[afterlastspace]); + i++; + while (ArgBuffer[i] == L' ') + i++; + afterlastspace = i; + } + else + { + i++; + } + } + + if (ArgBuffer[afterlastspace] != L'\0') + { + argc++; + ArgBuffer[i] = L'\0'; + argv[argc-1] = &(ArgBuffer[afterlastspace]); + } + + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"\\CsrssInitDone"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + EVENT_ALL_ACCESS, + 0, + NULL); + Status = NtOpenEvent(&CsrssInitEvent, + EVENT_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DbgPrint("CSR: Failed to open csrss notification event\n"); + } + if (CsrServerInitialization (argc, argv) == TRUE) + { + + NtSetEvent(CsrssInitEvent, + NULL); + + RtlFreeHeap (Peb->ProcessHeap, + 0, argv); + RtlFreeHeap (Peb->ProcessHeap, + 0, + ArgBuffer); + + /* terminate the current thread only */ + NtTerminateThread( NtCurrentThread(), 0 ); + } + else + { + DisplayString( L"CSR: Subsystem initialization failed.\n" ); + + RtlFreeHeap (Peb->ProcessHeap, + 0, argv); + RtlFreeHeap (Peb->ProcessHeap, + 0, + ArgBuffer); + + /* + * Tell SM we failed. + */ + NtTerminateProcess( NtCurrentProcess(), 0 ); + } +} + +/* EOF */ diff --git a/subsys/csrss/csrss.rc b/subsys/csrss/csrss.rc new file mode 100644 index 0000000..c2ecd4d --- /dev/null +++ b/subsys/csrss/csrss.rc @@ -0,0 +1,38 @@ +#include "../../include/defines.h" +#include "../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Client/Server Runtime Process\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "CSRSs and CSRSrv\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "CSRSs.exe and CSRSrv.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/csrss/init.c b/subsys/csrss/init.c new file mode 100644 index 0000000..8ed7fbd --- /dev/null +++ b/subsys/csrss/init.c @@ -0,0 +1,212 @@ +/* $Id$ + * + * reactos/subsys/csrss/init.c + * + * Initialize the CSRSS subsystem server process. + * + * ReactOS Operating System + * + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +#include "api.h" + +/* GLOBALS ******************************************************************/ + +/* + * Server's named ports. + */ +static HANDLE ApiPortHandle; + + +HANDLE CsrInitEvent = INVALID_HANDLE_VALUE; +HANDLE CsrHeap = INVALID_HANDLE_VALUE; + +HANDLE CsrObjectDirectory = INVALID_HANDLE_VALUE; +HANDLE CsrApiPort = INVALID_HANDLE_VALUE; +HANDLE CsrSbApiPort = INVALID_HANDLE_VALUE; + +UNICODE_STRING CsrDirectoryName; + +extern HANDLE CsrssApiHeap; + +ULONG +InitializeVideoAddressSpace(VOID); + +static NTSTATUS +CsrParseCommandLine ( + ULONG ArgumentCount, + PWSTR *ArgumentArray + ) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES Attributes; + ANSI_STRING AnsiString; + + ULONG i; + + /* DbgPrint ("Arguments: %ld\n", ArgumentCount); + for (i = 0; i < ArgumentCount; i++) + { + DbgPrint ("Argument %ld: %S\n", i, ArgumentArray[i]); + }*/ + + + /* create object directory ('\Windows') */ + RtlCreateUnicodeString (&CsrDirectoryName, + L"\\Windows"); + + InitializeObjectAttributes (&Attributes, + &CsrDirectoryName, + 0, + NULL, + NULL); + + Status = NtCreateDirectoryObject(&CsrObjectDirectory, + 0xF000F, + &Attributes); + + return Status; +} + + +static VOID +CsrInitVideo(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DeviceName; + IO_STATUS_BLOCK Iosb; + HANDLE VideoHandle; + NTSTATUS Status; + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\DISPLAY1"); + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + Status = NtOpenFile(&VideoHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + 0, + 0); + if (NT_SUCCESS(Status)) + { + NtClose(VideoHandle); + } +} + + +/********************************************************************** + * NAME + * CsrServerInitialization + * + * DESCRIPTION + * Create a directory object (\windows) and two named LPC ports: + * + * 1. \windows\ApiPort + * 2. \windows\SbApiPort + * + * RETURN VALUE + * TRUE: Initialization OK; otherwise FALSE. + */ +BOOL +STDCALL +CsrServerInitialization ( + ULONG ArgumentCount, + PWSTR *ArgumentArray + ) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObAttributes; + UNICODE_STRING PortName; + OBJECT_ATTRIBUTES RefreshEventAttr; + UNICODE_STRING RefreshEventName; + HANDLE RefreshEventHandle; + + Status = CsrParseCommandLine (ArgumentCount, ArgumentArray); + if (!NT_SUCCESS(Status)) + { + PrintString("CSR: Unable to parse the command line (Status: %x)\n", Status); + return(FALSE); + } + + CsrInitVideo(); + + /* NEW NAMED PORT: \ApiPort */ + RtlInitUnicodeStringFromLiteral(&PortName, L"\\Windows\\ApiPort"); + InitializeObjectAttributes(&ObAttributes, + &PortName, + 0, + NULL, + NULL); + + Status = NtCreatePort(&ApiPortHandle, + &ObAttributes, + 260, + 328, + 0); + if (!NT_SUCCESS(Status)) + { + PrintString("CSR: Unable to create \\ApiPort (Status %x)\n", Status); + return(FALSE); + } + CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE, + NULL, + 65536, + 65536, + NULL, + NULL); + if (CsrssApiHeap == NULL) + { + PrintString("CSR: Failed to create private heap, aborting\n"); + return FALSE; + } + + CsrInitConsoleSupport(); + Status = RtlCreateUserThread(NtCurrentProcess(), + NULL, + FALSE, + 0, + NULL, + NULL, + (PTHREAD_START_ROUTINE)Thread_Api, + ApiPortHandle, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + PrintString("CSR: Unable to create server thread\n"); + NtClose(ApiPortHandle); + return FALSE; + } + RtlInitUnicodeStringFromLiteral( &RefreshEventName, L"\\TextConsoleRefreshEvent" ); + InitializeObjectAttributes( &RefreshEventAttr, &RefreshEventName, 0, NULL, NULL ); + Status = NtCreateEvent( &RefreshEventHandle, STANDARD_RIGHTS_ALL, &RefreshEventAttr, FALSE, FALSE ); + if( !NT_SUCCESS( Status ) ) + { + PrintString( "CSR: Unable to create refresh event!\n" ); + return FALSE; + } + Status = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE, 0, NULL, NULL, (PTHREAD_START_ROUTINE)Console_Api, (PVOID) RefreshEventHandle, NULL, NULL ); + if( !NT_SUCCESS( Status ) ) + { + PrintString( "CSR: Unable to create console thread\n" ); + return FALSE; + } + + InitializeVideoAddressSpace(); + + W32kInitialize(); + + return TRUE; +} + +/* EOF */ diff --git a/subsys/csrss/lpcstub.c b/subsys/csrss/lpcstub.c new file mode 100644 index 0000000..1eaff74 --- /dev/null +++ b/subsys/csrss/lpcstub.c @@ -0,0 +1,42 @@ +/* $Id$ + * + * lpcstub.c + * + * ReactOS Operating System + * + * + */ +#include +#include "api.h" + + +/* CUI & GUI Win32(tm) API port */ + +LPC_RETURN_CODE +PortDispatcher_Api( + PLPC_REQUEST_REPLY pLpcRequestReply + ) +{ + switch (pLpcRequestReply->Function) + { + case CSRSS_API_PROCESS_CREATE: + return CSRSS_CreateProcess(pLpcRequestReply); + case CSRSS_API_PROCESS_TERMINATE: + return CSRSS_TerminateProcess(pLpcRequestReply); + } + return LPC_ERROR_INVALID_FUNCTION; +} + + +/* The \SbApi dispatcher: what is this port for? */ + +LPC_RETURN_CODE +PortDispatcher_SbApi( + PLPC_REQUEST_REPLY pLpcRequestReply + ) +{ + return LPC_ERROR_INVALID_FUNCTION; +} + + +/* EOF */ diff --git a/subsys/csrss/makefile b/subsys/csrss/makefile new file mode 100644 index 0000000..4cb75b3 --- /dev/null +++ b/subsys/csrss/makefile @@ -0,0 +1,37 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = native + +TARGET_NAME = csrss + +TARGET_INSTALLDIR = system32 + +TARGET_CFLAGS = -D__NTAPP__ + +OBJECTS_API = \ + api/process.o \ + api/wapi.o \ + api/conio.o \ + api/handle.o \ + api/user.o + +OBJECTS_MISC = \ + $(TARGET_NAME).o \ + init.o \ + print.o \ + video.o \ + win32k.o + +TARGET_OBJECTS = \ + $(OBJECTS_API) \ + $(OBJECTS_MISC) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/csrss/print.c b/subsys/csrss/print.c new file mode 100644 index 0000000..21cb712 --- /dev/null +++ b/subsys/csrss/print.c @@ -0,0 +1,63 @@ +/* $Id$ + * + * smss.c - Session Manager + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * 19990529 (Emanuele Aliberti) + * Compiled successfully with egcs 1.1.2 + */ + +#include + +#include + + +VOID STDCALL DisplayString(LPCWSTR lpwString) +{ + UNICODE_STRING us; + + RtlInitUnicodeString (&us, lpwString); + NtDisplayString (&us); +} + +VOID STDCALL PrintString (char* fmt, ...) +{ + char buffer[512]; + va_list ap; + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + ULONG i; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + RtlInitAnsiString (&AnsiString, buffer); + RtlAnsiStringToUnicodeString (&UnicodeString, + &AnsiString, + TRUE); + NtDisplayString(&UnicodeString); + RtlFreeUnicodeString (&UnicodeString); +} + +/* EOF */ diff --git a/subsys/csrss/video.c b/subsys/csrss/video.c new file mode 100644 index 0000000..dc95034 --- /dev/null +++ b/subsys/csrss/video.c @@ -0,0 +1,126 @@ +/* $Id$ + * + * ReactOS Project + */ +#include + +ULONG +InitializeVideoAddressSpace(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING PhysMemName; + NTSTATUS Status; + HANDLE PhysMemHandle; + PVOID BaseAddress; + LARGE_INTEGER Offset; + ULONG ViewSize; + PUCHAR TextMap; + CHAR IVT[1024]; + CHAR BDA[256]; + + /* + * Open the physical memory section + */ + RtlInitUnicodeStringFromLiteral(&PhysMemName, L"\\Device\\PhysicalMemory"); + InitializeObjectAttributes(&ObjectAttributes, + &PhysMemName, + 0, + NULL, + NULL); + Status = NtOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Couldn't open \\Device\\PhysicalMemory\n"); + return(0); + } + + /* + * Map the BIOS and device registers into the address space + */ + Offset.QuadPart = 0xa0000; + ViewSize = 0x100000 - 0xa0000; + BaseAddress = (PVOID)0xa0000; + Status = NtMapViewOfSection(PhysMemHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + 8192, + &Offset, + &ViewSize, + ViewUnmap, + 0, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Couldn't map physical memory (%x)\n", Status); + NtClose(PhysMemHandle); + return(0); + } + NtClose(PhysMemHandle); + if (BaseAddress != (PVOID)0xa0000) + { + DbgPrint("Couldn't map physical memory at the right address " + "(was %x)\n", BaseAddress); + return(0); + } + + /* + * Map some memory to use for the non-BIOS parts of the v86 mode address + * space + */ + BaseAddress = (PVOID)0x1; + ViewSize = 0xa0000 - 0x1000; + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &ViewSize, + MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to allocate virtual memory (Status %x)\n", Status); + return(0); + } + if (BaseAddress != (PVOID)0x0) + { + DbgPrint("Failed to allocate virtual memory at right address " + "(was %x)\n", BaseAddress); + return(0); + } + + /* + * Get the real mode IVT from the kernel + */ + Status = NtVdmControl(0, IVT); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NtVdmControl failed (status %x)\n", Status); + return(0); + } + + /* + * Copy the real mode IVT into the right place + */ + memcpy((PVOID)0x0, IVT, 1024); + + /* + * Get the BDA from the kernel + */ + Status = NtVdmControl(1, BDA); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NtVdmControl failed (status %x)\n", Status); + return(0); + } + + /* + * Copy the BDA into the right place + */ + memcpy((PVOID)0x400, BDA, 256); + + return(1); +} + + +/* EOF */ diff --git a/subsys/ntvdm/.cvsignore b/subsys/ntvdm/.cvsignore new file mode 100644 index 0000000..5b2574d --- /dev/null +++ b/subsys/ntvdm/.cvsignore @@ -0,0 +1,6 @@ +ntvdm.coff +ntvdm.exe +ntvdm.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/ntvdm/makefile b/subsys/ntvdm/makefile new file mode 100644 index 0000000..f57351f --- /dev/null +++ b/subsys/ntvdm/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = ntvdm + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ntdll.a kernel32.a user32.a gdi32.a advapi32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/ntvdm/ntvdm.c b/subsys/ntvdm/ntvdm.c new file mode 100644 index 0000000..188d562 --- /dev/null +++ b/subsys/ntvdm/ntvdm.c @@ -0,0 +1,144 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: subsys/ntvdm/ntvdm.c + * PURPOSE: Virtual DOS Machine + * PROGRAMMER: Robert Dickenson (robd@mok.lvcm.com) + * UPDATE HISTORY: + * Created 23/10/2002 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + +void PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + OutputDebugString(buffer); +} + +/* +GetVersion +GetVolumeInformationW +GetWindowsDirectoryA +GlobalMemoryStatus +HeapAlloc +HeapCreate +HeapDestroy +HeapFree +HeapReAlloc + +GetNextVDMCommand +ExitVDM +RegisterConsoleVDM +SetVDMCurrentDirectories +VDMConsoleOperation +WriteConsoleInputVDMW + +NtSetLdtEntries +NtTerminateProcess + +NtMapViewOfSection +NtUnmapViewOfSection + +NtVdmControl + */ + +BOOLEAN +StartVirtualMachine(VOID) +{ + BOOLEAN Result; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + CHAR CommandLine[MAX_PATH]; + CHAR CurrentDirectory[MAX_PATH]; + + GetSystemDirectory(CommandLine, MAX_PATH); + strcat(CommandLine, "\\hello.exe"); + GetWindowsDirectory(CurrentDirectory, MAX_PATH); + + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.lpReserved = NULL; + StartupInfo.lpDesktop = NULL; + StartupInfo.lpTitle = NULL; + StartupInfo.dwFlags = 0; + StartupInfo.cbReserved2 = 0; + StartupInfo.lpReserved2 = 0; + + Result = CreateProcess(CommandLine, + NULL, + NULL, + NULL, + FALSE, + DETACHED_PROCESS, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + if (!Result) { + PrintString("WL: Failed to execute target process\n"); + return FALSE; + } + WaitForSingleObject(ProcessInformation.hProcess, INFINITE); + CloseHandle(ProcessInformation.hProcess); + CloseHandle(ProcessInformation.hThread); + return TRUE; +} + +int STDCALL +WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) +{ + DWORD Result; + BOOL Success; + ULONG i; + NTSTATUS Status; + + CHAR WelcomeMsg[] = "ReactOS Virtual DOS Machine support.\nType q to quit."; + CHAR InputBuffer[255]; + + AllocConsole(); + SetConsoleTitle("ntvdm"); + StartVirtualMachine(); + + for (;;) { + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), + WelcomeMsg, strlen(WelcomeMsg), // wcslen(WelcomeMsg), + &Result, NULL); + i = 0; + do { + ReadConsole(GetStdHandle(STD_INPUT_HANDLE), + &InputBuffer[i], 1, + &Result, NULL); + if (++i >= (sizeof(InputBuffer) - 1)) { + break; + } + } while (InputBuffer[i - 1] != '\n'); + InputBuffer[i - 1] = '\0'; + + if (InputBuffer[0] == 'q' || InputBuffer[0] == 'Q') { + break; + } + } + + ExitProcess(0); + return 0; +} diff --git a/subsys/ntvdm/ntvdm.rc b/subsys/ntvdm/ntvdm.rc new file mode 100644 index 0000000..f8fc057 --- /dev/null +++ b/subsys/ntvdm/ntvdm.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Virtual DOS Machine\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "ntvdm\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "ntvdm.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/smss/.cvsignore b/subsys/smss/.cvsignore new file mode 100644 index 0000000..5f7d29f --- /dev/null +++ b/subsys/smss/.cvsignore @@ -0,0 +1,6 @@ +smss.coff +smss.exe +smss.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/smss/init.c b/subsys/smss/init.c new file mode 100644 index 0000000..a3cce66 --- /dev/null +++ b/subsys/smss/init.c @@ -0,0 +1,837 @@ +/* $Id$ + * + * init.c - Session Manager initialization + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * 19990530 (Emanuele Aliberti) + * Compiled successfully with egcs 1.1.2 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#include "smss.h" + +#define NDEBUG + + +/* GLOBALS ******************************************************************/ + +HANDLE DbgSsApiPort = INVALID_HANDLE_VALUE; +HANDLE DbgUiApiPort = INVALID_HANDLE_VALUE; + +PWSTR SmSystemEnvironment = NULL; + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS STDCALL +SmObjectDirectoryQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeString; + HANDLE WindowsDirectory; + NTSTATUS Status = STATUS_SUCCESS; + +#ifndef NDEBUG + PrintString("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + PrintString("ValueData '%S'\n", (PWSTR)ValueData); +#endif + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + RtlInitUnicodeString(&UnicodeString, + (PWSTR)ValueData); + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + 0, + NULL, + NULL); + + Status = ZwCreateDirectoryObject(&WindowsDirectory, + 0, + &ObjectAttributes); + + return(Status); +} + + +static NTSTATUS +SmCreateObjectDirectories(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"ObjectDirectories"; + QueryTable[0].QueryRoutine = SmObjectDirectoryQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager", + QueryTable, + NULL, + NULL); + + return(Status); +} + + +static NTSTATUS STDCALL +SmDosDevicesQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DeviceName; + UNICODE_STRING LinkName; + HANDLE LinkHandle; + WCHAR LinkBuffer[80]; + NTSTATUS Status; + +#ifndef NDEBUG + PrintString("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + PrintString("ValueData '%S'\n", (PWSTR)ValueData); +#endif + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + swprintf(LinkBuffer, + L"\\??\\%s", + ValueName); + RtlInitUnicodeString(&LinkName, + LinkBuffer); + RtlInitUnicodeString(&DeviceName, + (PWSTR)ValueData); + +#ifndef NDEBUG + PrintString("SM: Linking %wZ --> %wZ\n", + &LinkName, + &DeviceName); +#endif + + /* create symbolic link */ + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_PERMANENT, + NULL, + NULL); + Status = NtCreateSymbolicLinkObject(&LinkHandle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes, + &DeviceName); + if (!NT_SUCCESS(Status)) + { + PrintString("SmDosDevicesQueryRoutine: NtCreateSymbolicLink( %wZ --> %wZ ) failed!\n", + &LinkName, + &DeviceName); + } + NtClose(LinkHandle); + + return(Status); +} + + +static NTSTATUS +SmInitDosDevices(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].QueryRoutine = SmDosDevicesQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\DOS Devices", + QueryTable, + NULL, + NULL); + return(Status); +} + + +static NTSTATUS STDCALL +SmRunBootAppsQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + RTL_PROCESS_INFO ProcessInfo; + UNICODE_STRING ImagePathString; + UNICODE_STRING CommandLineString; + WCHAR Description[256]; + WCHAR ImageName[256]; + WCHAR ImagePath[256]; + WCHAR CommandLine[256]; + PWSTR p1, p2; + ULONG len; + NTSTATUS Status; + +#ifndef NDEBUG + PrintString("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + PrintString("ValueData '%S'\n", (PWSTR)ValueData); +#endif + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + /* Extract the description */ + p1 = wcschr((PWSTR)ValueData, L' '); + len = p1 - (PWSTR)ValueData; + memcpy(Description,ValueData, len * sizeof(WCHAR)); + Description[len] = 0; + + /* Extract the image name */ + p1++; + p2 = wcschr(p1, L' '); + if (p2 != NULL) + len = p2 - p1; + else + len = wcslen(p1); + memcpy(ImageName, p1, len * sizeof(WCHAR)); + ImageName[len] = 0; + + /* Extract the command line */ + if (p2 == NULL) + { + CommandLine[0] = 0; + } + else + { + p2++; + wcscpy(CommandLine, p2); + } + + PrintString("Running %S...\n", Description); +#ifndef NDEBUG + PrintString("ImageName: '%S'\n", ImageName); + PrintString("CommandLine: '%S'\n", CommandLine); +#endif + + /* initialize executable path */ + wcscpy(ImagePath, L"\\SystemRoot\\system32\\"); + wcscat(ImagePath, ImageName); + wcscat(ImagePath, L".exe"); + + RtlInitUnicodeString(&ImagePathString, + ImagePath); + + RtlInitUnicodeString(&CommandLineString, + CommandLine); + + RtlCreateProcessParameters(&ProcessParameters, + &ImagePathString, + NULL, + NULL, + &CommandLineString, + NULL, + NULL, + NULL, + NULL, + NULL); + + Status = RtlCreateUserProcess(&ImagePathString, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + if (!NT_SUCCESS(Status)) + { + PrintString("Running %s failed (Status %lx)\n", Description, Status); + return(STATUS_SUCCESS); + } + + RtlDestroyProcessParameters(ProcessParameters); + + /* Wait for process termination */ + NtWaitForSingleObject(ProcessInfo.ProcessHandle, + FALSE, + NULL); + + NtClose(ProcessInfo.ThreadHandle); + NtClose(ProcessInfo.ProcessHandle); + + return(STATUS_SUCCESS); +} + + +/* + * Run native applications listed in the registry. + * + * Key: + * \Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager + * + * Value (format: " ": + * BootExecute = "autocheck autochk *" + */ +static NTSTATUS +SmRunBootApps(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"BootExecute"; + QueryTable[0].QueryRoutine = SmRunBootAppsQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + PrintString("SmRunBootApps: RtlQueryRegistryValues() failed! (Status %lx)\n", Status); + } + + return(Status); +} + + +static NTSTATUS +SmProcessFileRenameList(VOID) +{ +#ifndef NDEBUG + PrintString("SmProcessFileRenameList() called\n"); +#endif + + /* FIXME: implement it! */ + +#ifndef NDEBUG + PrintString("SmProcessFileRenameList() done\n"); +#endif + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +SmPreloadDlls(VOID) +{ +#ifndef NDEBUG + PrintString("SmPreloadDlls() called\n"); +#endif + + /* FIXME: implement it! */ + +#ifndef NDEBUG + PrintString("SmPreloadDlls() done\n"); +#endif + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +SmPagingFilesQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + UNICODE_STRING FileName; + LARGE_INTEGER InitialSize; + LARGE_INTEGER MaximumSize; + NTSTATUS Status; + LPWSTR p; + +#ifndef NDEBUG + PrintString("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + PrintString("ValueData '%S'\n", (PWSTR)ValueData); +#endif + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + /* + * Format: "[ [ ]]" + */ + if ((p = wcschr(ValueData, ' ')) != NULL) + { + *p = L'\0'; + InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096; + if (*p == ' ') + { + MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096; + } + else + MaximumSize = InitialSize; + } + else + { + InitialSize.QuadPart = 50 * 4096; + MaximumSize.QuadPart = 80 * 4096; + } + + if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData, + &FileName, + NULL, + NULL)) + { + return (STATUS_SUCCESS); + } + + DbgPrint("SMSS: Created paging file %wZ with size %dKB\n", + &FileName, InitialSize.QuadPart / 1024); + Status = NtCreatePagingFile(&FileName, + &InitialSize, + &MaximumSize, + 0); + + RtlFreeUnicodeString(&FileName); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +SmCreatePagingFiles(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"PagingFiles"; + QueryTable[0].QueryRoutine = SmPagingFilesQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\Memory Management", + QueryTable, + NULL, + NULL); + + return(Status); +} + + +static NTSTATUS STDCALL +SmEnvironmentQueryRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + UNICODE_STRING EnvVariable; + UNICODE_STRING EnvValue; + +#ifndef NDEBUG + PrintString("ValueName '%S' Type %lu Length %lu\n", ValueName, ValueType, ValueLength); + PrintString("ValueData '%S'\n", (PWSTR)ValueData); +#endif + + if (ValueType != REG_SZ) + { + return(STATUS_SUCCESS); + } + + RtlInitUnicodeString(&EnvVariable, + ValueName); + RtlInitUnicodeString(&EnvValue, + (PWSTR)ValueData); + RtlSetEnvironmentVariable(Context, + &EnvVariable, + &EnvValue); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +SmSetEnvironmentVariables(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + UNICODE_STRING EnvVariable; + UNICODE_STRING EnvValue; + WCHAR ValueBuffer[MAX_PATH]; + NTSTATUS Status; + + /* + * The following environment variables must be set prior to reading + * other variables from the registry. + * + * Variables (example): + * SystemRoot = "C:\reactos" + * SystemDrive = "C:" + */ + + /* Copy system root into value buffer */ + wcscpy(ValueBuffer, + SharedUserData->NtSystemRoot); + + /* Cet SystemRoot = "C:\reactos" */ + RtlInitUnicodeStringFromLiteral(&EnvVariable, + L"SystemRoot"); + RtlInitUnicodeString(&EnvValue, + ValueBuffer); + RtlSetEnvironmentVariable(&SmSystemEnvironment, + &EnvVariable, + &EnvValue); + + /* Cut off trailing path */ + ValueBuffer[2] = 0; + + /* Set SystemDrive = "C:" */ + RtlInitUnicodeStringFromLiteral(&EnvVariable, + L"SystemDrive"); + RtlInitUnicodeString(&EnvValue, + ValueBuffer); + RtlSetEnvironmentVariable(&SmSystemEnvironment, + &EnvVariable, + &EnvValue); + + /* Read system environment from the registry. */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].QueryRoutine = SmEnvironmentQueryRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"\\Session Manager\\Environment", + QueryTable, + &SmSystemEnvironment, + SmSystemEnvironment); + + return(Status); +} + + +static NTSTATUS +SmLoadSubsystems(VOID) +{ + SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo; + NTSTATUS Status; + + /* Load kernel mode subsystem (aka win32k.sys) */ + RtlInitUnicodeStringFromLiteral(&ImageInfo.ModuleName, + L"\\SystemRoot\\system32\\drivers\\win32k.sys"); + + Status = NtSetSystemInformation(SystemLoadAndCallImage, + &ImageInfo, + sizeof(SYSTEM_LOAD_AND_CALL_IMAGE)); + + PrintString("SMSS: Loaded win32k.sys (Status %lx)\n", Status); +#if 0 + if (!NT_SUCCESS(Status)) + { + return(Status); + } +#endif + + /* FIXME: load more subsystems (csrss!) */ + + return(Status); +} + + +NTSTATUS +InitSessionManager(HANDLE Children[]) +{ + NTSTATUS Status; + UNICODE_STRING UnicodeString; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING CmdLineW; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + RTL_PROCESS_INFO ProcessInfo; + HANDLE CsrssInitEvent; + WCHAR UnicodeBuffer[MAX_PATH]; + + /* Create object directories */ + Status = SmCreateObjectDirectories(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to create object directories (Status %lx)\n", Status); + return(Status); + } + + /* Create the SmApiPort object (LPC) */ + Status = SmCreateApiPort(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to create SmApiPort (Status %lx)\n", Status); + return(Status); + } + + /* Create the system environment */ + Status = RtlCreateEnvironment(FALSE, + &SmSystemEnvironment); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to create the system environment (Status %lx)\n", Status); + return(Status); + } + + /* Define symbolic links to kernel devices (MS-DOS names) */ + Status = SmInitDosDevices(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to create dos device links (Status %lx)\n", Status); + return(Status); + } + + /* Run all programs in the boot execution list */ + Status = SmRunBootApps(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to run boot applications (Status %lx)\n", Status); + return(Status); + } + + /* Process the file rename list */ + Status = SmProcessFileRenameList(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to process the file rename list (Status %lx)\n", Status); + return(Status); + } + + /* Load the well known DLLs */ + Status = SmPreloadDlls(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to preload system DLLs (Status %lx)\n", Status); + return(Status); + } + + /* Create paging files */ + Status = SmCreatePagingFiles(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to create paging files (Status %lx)\n", Status); + return(Status); + } + + /* Load remaining registry hives */ + NtInitializeRegistry(FALSE); + + /* Set environment variables from registry */ + Status = SmSetEnvironmentVariables(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to set system environment variables (Status %lx)\n", Status); + return(Status); + } + + /* Load the subsystems */ + Status = SmLoadSubsystems(); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Failed to load subsystems (Status %lx)\n", Status); + return(Status); + } + + /* Run csrss.exe */ + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"\\CsrssInitDone"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + EVENT_ALL_ACCESS, + 0, + NULL); + Status = NtCreateEvent(&CsrssInitEvent, + EVENT_ALL_ACCESS, + &ObjectAttributes, + TRUE, + FALSE); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to create csrss notification event\n"); + } + + /* + * Start the Win32 subsystem (csrss.exe) + */ + + /* initialize executable path */ + wcscpy(UnicodeBuffer, L"\\??\\"); + wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot); + wcscat(UnicodeBuffer, L"\\system32\\csrss.exe"); + RtlInitUnicodeString(&UnicodeString, + UnicodeBuffer); + + RtlCreateProcessParameters(&ProcessParameters, + &UnicodeString, + NULL, + NULL, + NULL, + SmSystemEnvironment, + NULL, + NULL, + NULL, + NULL); + + Status = RtlCreateUserProcess(&UnicodeString, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + + RtlDestroyProcessParameters (ProcessParameters); + + if (!NT_SUCCESS(Status)) + { + DisplayString(L"SM: Loading csrss.exe failed!\n"); + return(Status); + } + + NtWaitForSingleObject(CsrssInitEvent, + FALSE, + NULL); + + Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle; + + /* + * Start the logon process (winlogon.exe) + */ + + /* initialize executable path */ + wcscpy(UnicodeBuffer, L"\\??\\"); + wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot); + wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe"); + RtlInitUnicodeString(&UnicodeString, + UnicodeBuffer); + + RtlCreateProcessParameters(&ProcessParameters, + &UnicodeString, + NULL, + NULL, + NULL, + SmSystemEnvironment, + NULL, + NULL, + NULL, + NULL); + + Status = RtlCreateUserProcess(&UnicodeString, + OBJ_CASE_INSENSITIVE, + ProcessParameters, + NULL, + NULL, + NULL, + FALSE, + NULL, + NULL, + &ProcessInfo); + + RtlDestroyProcessParameters(ProcessParameters); + + if (!NT_SUCCESS(Status)) + { + DisplayString(L"SM: Loading winlogon.exe failed!\n"); + NtTerminateProcess(Children[CHILD_CSRSS], + 0); + return(Status); + } + Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle; + + /* Create the \DbgSsApiPort object (LPC) */ + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"\\DbgSsApiPort"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + PORT_ALL_ACCESS, + NULL, + NULL); + + Status = NtCreatePort(&DbgSsApiPort, + &ObjectAttributes, + 0, + 0, + 0); + + if (!NT_SUCCESS(Status)) + { + return(Status); + } +#ifndef NDEBUG + DisplayString(L"SM: DbgSsApiPort created...\n"); +#endif + + /* Create the \DbgUiApiPort object (LPC) */ + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"\\DbgUiApiPort"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + PORT_ALL_ACCESS, + NULL, + NULL); + + Status = NtCreatePort(&DbgUiApiPort, + &ObjectAttributes, + 0, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + return(Status); + } +#ifndef NDEBUG + DisplayString (L"SM: DbgUiApiPort created...\n"); +#endif + + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/subsys/smss/makefile b/subsys/smss/makefile new file mode 100644 index 0000000..cfc96d0 --- /dev/null +++ b/subsys/smss/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = native + +TARGET_NAME = smss + +TARGET_INSTALLDIR = system32 + +TARGET_CFLAGS = -D__NTAPP__ + +TARGET_OBJECTS = $(TARGET_NAME).o init.o smapi.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/smss/smapi.c b/subsys/smss/smapi.c new file mode 100644 index 0000000..6945f82 --- /dev/null +++ b/subsys/smss/smapi.c @@ -0,0 +1,125 @@ +/* $Id$ + * + * Reactos Session Manager + * + * + */ + +#include +#include +#include + +#include "smss.h" + +#define NDEBUG + +/* GLOBAL VARIABLES *********************************************************/ + +static HANDLE SmApiPort = INVALID_HANDLE_VALUE; + +/* FUNCTIONS ****************************************************************/ + + +VOID STDCALL +SmApiThread(HANDLE Port) +{ + NTSTATUS Status; + ULONG Unknown; + PLPC_MESSAGE Reply = NULL; + LPC_MESSAGE Message; + +#ifndef NDEBUG + DisplayString(L"SmApiThread: running\n"); +#endif + + while (TRUE) + { +#ifndef NDEBUG + DisplayString(L"SmApiThread: waiting for message\n"); +#endif + + Status = NtReplyWaitReceivePort(Port, + &Unknown, + Reply, + &Message); + if (NT_SUCCESS(Status)) + { +#ifndef NDEBUG + DisplayString(L"SmApiThread: message received\n"); +#endif + + if (Message.MessageType == LPC_CONNECTION_REQUEST) + { +// SmHandleConnectionRequest (Port, &Message); + Reply = NULL; + } + else if (Message.MessageType == LPC_DEBUG_EVENT) + { +// DbgSsHandleKmApiMsg (&Message, 0); + Reply = NULL; + } + else if (Message.MessageType == LPC_PORT_CLOSED) + { + Reply = NULL; + } + else + { +// Reply = &Message; + } + } + } +} + + +NTSTATUS +SmCreateApiPort(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING UnicodeString; + NTSTATUS Status; + + RtlInitUnicodeStringFromLiteral(&UnicodeString, + L"\\SmApiPort"); + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + PORT_ALL_ACCESS, + NULL, + NULL); + + Status = NtCreatePort(&SmApiPort, + &ObjectAttributes, + 0, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* Create two threads for "\SmApiPort" */ + RtlCreateUserThread(NtCurrentProcess(), + NULL, + FALSE, + 0, + NULL, + NULL, + (PTHREAD_START_ROUTINE)SmApiThread, + (PVOID)SmApiPort, + NULL, + NULL); + + RtlCreateUserThread(NtCurrentProcess(), + NULL, + FALSE, + 0, + NULL, + NULL, + (PTHREAD_START_ROUTINE)SmApiThread, + (PVOID)SmApiPort, + NULL, + NULL); + + return(Status); +} + +/* EOF */ diff --git a/subsys/smss/smss.c b/subsys/smss/smss.c new file mode 100644 index 0000000..76821d7 --- /dev/null +++ b/subsys/smss/smss.c @@ -0,0 +1,102 @@ +/* $Id$ + * + * smss.c - Session Manager + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * 19990529 (Emanuele Aliberti) + * Compiled successfully with egcs 1.1.2 + */ +#include + +#include "smss.h" + + +void +DisplayString(LPCWSTR lpwString) +{ + UNICODE_STRING us; + + RtlInitUnicodeString(&us, lpwString); + NtDisplayString(&us); +} + + +void +PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + RtlInitAnsiString(&AnsiString, buffer); + RtlAnsiStringToUnicodeString(&UnicodeString, + &AnsiString, + TRUE); + NtDisplayString(&UnicodeString); + RtlFreeUnicodeString(&UnicodeString); +} + + +/* Native image's entry point */ + +VOID STDCALL +NtProcessStartup(PPEB Peb) +{ + HANDLE Children[2]; /* csrss, winlogon */ + NTSTATUS Status; + + Status = InitSessionManager(Children); + if (!NT_SUCCESS(Status)) + { + PrintString("SM: Initialization failed!\n"); + goto ByeBye; + } + + Status = NtWaitForMultipleObjects(((LONG) sizeof(Children) / sizeof(HANDLE)), + Children, + WaitAny, + TRUE, /* alertable */ + NULL); /* NULL for infinite */ + if (!NT_SUCCESS(Status)) + { + PrintString("SM: NtWaitForMultipleObjects failed!\n"); + } + else + { + PrintString("SM: Process terminated!\n"); + } + +ByeBye: + /* Raise a hard error (crash the system/BSOD) */ + NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, + 0,0,0,0,0); + +// NtTerminateProcess(NtCurrentProcess(), 0); +} + +/* EOF */ diff --git a/subsys/smss/smss.h b/subsys/smss/smss.h new file mode 100644 index 0000000..295f1a3 --- /dev/null +++ b/subsys/smss/smss.h @@ -0,0 +1,40 @@ + +#ifndef _SMSS_H_INCLUDED_ +#define _SMSS_H_INCLUDED_ + + +#define CHILD_CSRSS 0 +#define CHILD_WINLOGON 1 + + +/* GLOBAL VARIABLES ****/ + +//extern HANDLE SmApiPort; + + +/* FUNCTIONS ***********/ + +/* init.c */ +NTSTATUS +InitSessionManager(HANDLE Children[]); + + +/* smss.c */ +void DisplayString (LPCWSTR lpwString); +void PrintString (char* fmt,...); + + +/* smapi.c */ + +NTSTATUS +SmCreateApiPort(VOID); + +VOID STDCALL +SmApiThread(HANDLE Port); + + + +#endif /* _SMSS_H_INCLUDED_ */ + +/* EOF */ + diff --git a/subsys/smss/smss.rc b/subsys/smss/smss.rc new file mode 100644 index 0000000..c8e6cd1 --- /dev/null +++ b/subsys/smss/smss.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Session Manager\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "smss\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "smss.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/autochk/.cvsignore b/subsys/system/autochk/.cvsignore new file mode 100644 index 0000000..1fc4978 --- /dev/null +++ b/subsys/system/autochk/.cvsignore @@ -0,0 +1,6 @@ +autochk.coff +autochk.exe +autochk.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/system/autochk/autochk.c b/subsys/system/autochk/autochk.c new file mode 100644 index 0000000..da21bf5 --- /dev/null +++ b/subsys/system/autochk/autochk.c @@ -0,0 +1,89 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: apps/system/autochk/autochk.c + * PURPOSE: Filesystem checker + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS ****************************************************************/ + +void +DisplayString(LPCWSTR lpwString) +{ + UNICODE_STRING us; + + RtlInitUnicodeString(&us, lpwString); + NtDisplayString(&us); +} + + +void +PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + RtlInitAnsiString(&AnsiString, buffer); + RtlAnsiStringToUnicodeString(&UnicodeString, + &AnsiString, + TRUE); + NtDisplayString(&UnicodeString); + RtlFreeUnicodeString(&UnicodeString); +} + + +/* Native image's entry point */ + +VOID STDCALL +NtProcessStartup(PPEB Peb) +{ + ULONG i; + + PrintString("Autochk 0.0.1\n"); + + for (i = 0; i < 26; i++) + { + if ((SharedUserData->DosDeviceMap & (1 << i)) && + (SharedUserData->DosDeviceDriveType[i] == DOSDEVICE_DRIVE_FIXED)) + { + PrintString(" Checking drive %c:", 'A'+i); + PrintString(" OK\n"); + } + } + PrintString("\n"); + + NtTerminateProcess(NtCurrentProcess(), 0); +} + +/* EOF */ diff --git a/subsys/system/autochk/autochk.rc b/subsys/system/autochk/autochk.rc new file mode 100644 index 0000000..270e392 --- /dev/null +++ b/subsys/system/autochk/autochk.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "File system checker\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "autochk\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "autochk.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/autochk/makefile b/subsys/system/autochk/makefile new file mode 100644 index 0000000..115f004 --- /dev/null +++ b/subsys/system/autochk/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = native + +TARGET_NAME = autochk + +TARGET_INSTALLDIR = system32 + +TARGET_CFLAGS = -D__NTAPP__ + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/system/gstart/.cvsignore b/subsys/system/gstart/.cvsignore new file mode 100644 index 0000000..41a2c60 --- /dev/null +++ b/subsys/system/gstart/.cvsignore @@ -0,0 +1,6 @@ +gstart.coff +gstart.exe +gstart.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/system/gstart/Makefile b/subsys/system/gstart/Makefile new file mode 100644 index 0000000..e4d780f --- /dev/null +++ b/subsys/system/gstart/Makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = gstart + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = user32.a gdi32.a ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/system/gstart/gstart.c b/subsys/system/gstart/gstart.c new file mode 100644 index 0000000..6af8c5f --- /dev/null +++ b/subsys/system/gstart/gstart.c @@ -0,0 +1,89 @@ +/* $Id$ + * + * PROJECT : ReactOS Operating System + * DESCRIPTION: ReactOS GUI Startup + * LICENSE : See top level directory + * + */ +#define NTOS_MODE_USER +#include +#include +#include +#include +#include +#include +#include + +int ExecuteProcess(char* name, char* cmdline) +{ + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + BOOL ret; + CHAR fullname[260]; + PCHAR p; + + /* append '.exe' if needed */ + strcpy (fullname, name); + p = strrchr (fullname, '.'); + if ((p == NULL) || (_stricmp (p, ".exe") != 0)) + { + strcat (fullname, ".exe"); + } + + memset(&StartupInfo, 0, sizeof(StartupInfo)); + StartupInfo.cb = sizeof (STARTUPINFO); + StartupInfo.lpTitle = name; + if( cmdline && *cmdline ) + *(cmdline-1) = ' '; + ret = CreateProcessA(fullname, + name, + NULL, + NULL, + FALSE, + 0, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + if (ret) + { + WaitForSingleObject(ProcessInformation.hProcess, INFINITE); + CloseHandle(ProcessInformation.hProcess); + CloseHandle(ProcessInformation.hThread); + } + return(ret); +} + +int main(int argc, char* argv[]) +{ + HDC Desktop; + HBRUSH Pen; + + GdiDllInitialize (NULL, DLL_PROCESS_ATTACH, NULL); + + /* Set up a DC called Desktop that accesses DISPLAY */ + Desktop = CreateDCA("DISPLAY", NULL, NULL, NULL); + if (Desktop == NULL) + { + return 1; + } + + Pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 255)); + SelectObject(Desktop, Pen); + Rectangle(Desktop, 0, 0, 640, 480); + + if (argc > 1) + { + ExecuteProcess(argv[1], ""); + } + else + { + Sleep(50); + } + + DeleteDC(Desktop); + + return(0); +} + +/* EOF */ diff --git a/subsys/system/gstart/gstart.rc b/subsys/system/gstart/gstart.rc new file mode 100644 index 0000000..0982e26 --- /dev/null +++ b/subsys/system/gstart/gstart.rc @@ -0,0 +1,38 @@ +#include "../../../include/defines.h" +#include "../../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Simple Shell\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "shell\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "shell.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/lsass/init.c b/subsys/system/lsass/init.c new file mode 100644 index 0000000..86f739c --- /dev/null +++ b/subsys/system/lsass/init.c @@ -0,0 +1,43 @@ +/* $Id$ + * + * init.c - Local Security Manager Initialization + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * 19990704 (Emanuele Aliberti) + * Compiled successfully with egcs 1.1.2 + */ +#include + +BOOL +InitLsa( + HANDLE Children[] + ) +{ + /* FIXME: create the \SeLsaCommandPort LPC port */ + /* FIXME: create the \LsaAuthenticationPort LPC port */ + return TRUE; +} + + +/* EOF */ + diff --git a/subsys/system/lsass/lsasrv.def b/subsys/system/lsass/lsasrv.def new file mode 100644 index 0000000..be8ee01 --- /dev/null +++ b/subsys/system/lsass/lsasrv.def @@ -0,0 +1,68 @@ +; $Id$ +LIBRARY lsasrv +EXPORTS +LsaIAuditNotifyPackageLoad +LsaIAuditSamEvent +LsaIEnumerateSecrets +LsaIFree_LSAI_PRIVATE_DATA +LsaIFree_LSAI_SECRET_ENUM_BUFFER +LsaIFree_LSAPR_ACCOUNT_ENUM_BUFFER +LsaIFree_LSAPR_CR_CIPHER_VALUE +LsaIFree_LSAPR_POLICY_INFORMATION +LsaIFree_LSAPR_PRIVILEGE_ENUM_BUFFER +LsaIFree_LSAPR_PRIVILEGE_SET +LsaIFree_LSAPR_REFERENCED_DOMAIN_LIST +LsaIFree_LSAPR_SR_SECURITY_DESCRIPTOR +LsaIFree_LSAPR_TRANSLATED_NAMES +LsaIFree_LSAPR_TRANSLATED_SIDS +LsaIFree_LSAPR_TRUSTED_DOMAIN_INFO +LsaIFree_LSAPR_TRUSTED_ENUM_BUFFER +LsaIFree_LSAPR_TRUST_INFORMATION +LsaIFree_LSAPR_UNICODE_STRING +LsaIGetPrivateData +LsaIGetSerialNumberPolicy +LsaIGetSerialNumberPolicy2 +LsaIHealthCheck +LsaIInitializeWellKnownSids +LsaIOpenPolicyTrusted +LsaIQueryInformationPolicyTrusted +LsaISetPrivateData +LsaISetSerialNumberPolicy +LsaISetTimesSecret +LsaISetupWasRun +LsapAuOpenSam +LsapInitLsa +LsarAddPrivilegesToAccount +LsarClose +LsarCreateAccount +LsarCreateSecret +LsarCreateTrustedDomain +LsarDelete +LsarEnumerateAccounts +LsarEnumeratePrivileges +LsarEnumeratePrivilegesAccount +LsarEnumerateTrustedDomains +LsarGetQuotasForAccount +LsarGetSystemAccessAccount +LsarLookupNames +LsarLookupPrivilegeDisplayName +LsarLookupPrivilegeName +LsarLookupPrivilegeValue +LsarLookupSids +LsarOpenAccount +LsarOpenPolicy +LsarOpenSecret +LsarOpenTrustedDomain +LsarQueryInfoTrustedDomain +LsarQueryInformationPolicy +LsarQuerySecret +LsarQuerySecurityObject +LsarRemovePrivilegesFromAccount +LsarSetInformationPolicy +LsarSetInformationTrustedDomain +LsarSetQuotasForAccount +LsarSetSecret +LsarSetSecurityObject +LsarSetSystemAccessAccount +ServiceInit + diff --git a/subsys/system/lsass/lsass.c b/subsys/system/lsass/lsass.c new file mode 100644 index 0000000..f3cc2fc --- /dev/null +++ b/subsys/system/lsass/lsass.c @@ -0,0 +1,72 @@ +/* $Id$ + * + * reactos/services/lsass/lsass.c + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + * -------------------------------------------------------------------- + * + * 19990704 (Emanuele Aliberti) + * Compiled successfully with egcs 1.1.2 + */ +#include +#include + +BOOL InitLsa(VOID); /* ./init.c */ + + +void +DisplayString( LPCWSTR lpwString ) +{ + UNICODE_STRING us; + + us.Buffer = (LPWSTR) lpwString; + us.Length = wcslen(lpwString) * sizeof (WCHAR); + us.MaximumLength = us.Length + sizeof (WCHAR); + NtDisplayString( & us ); +} + + +/* Native image's entry point */ + +void +NtProcessStartup( PSTARTUP_ARGUMENT StartupArgument ) +{ + DisplayString( L"Local Security Authority Subsystem:\n" ); + DisplayString( L"\tInitializing...\n" ); + + if (TRUE == InitLsa()) + { + DisplayString( L"\tInitialization OK\n" ); + /* FIXME: do nothing loop */ + while (TRUE) + { + NtYieldExecution(); + } + } + else + { + DisplayString( L"\tInitialization failed!\n" ); + } + NtTerminateProcess( NtCurrentProcess(), 0 ); +} + + +/* EOF */ diff --git a/subsys/system/lsass/lsass.rc b/subsys/system/lsass/lsass.rc new file mode 100644 index 0000000..b66067a --- /dev/null +++ b/subsys/system/lsass/lsass.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Local Security Authority\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "lsass\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "lsass.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/lsass/makefile b/subsys/system/lsass/makefile new file mode 100644 index 0000000..0d200a6 --- /dev/null +++ b/subsys/system/lsass/makefile @@ -0,0 +1,19 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = native + +TARGET_NAME = lsass + +TARGET_INSTALLDIR = system32 + +TARGET_OBJECTS = $(TARGET_NAME).o init.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/system/services/.cvsignore b/subsys/system/services/.cvsignore new file mode 100644 index 0000000..4eb78a7 --- /dev/null +++ b/subsys/system/services/.cvsignore @@ -0,0 +1,6 @@ +services.coff +services.exe +services.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/system/services/database.c b/subsys/system/services/database.c new file mode 100644 index 0000000..2e9dce1 --- /dev/null +++ b/subsys/system/services/database.c @@ -0,0 +1,723 @@ +/* $Id$ + * + * service control manager + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + */ + +/* INCLUDES *****************************************************************/ + +#define NTOS_MODE_USER +#include + +#include +#include + +#include "services.h" + +#define NDEBUG +#include + + +/* TYPES *********************************************************************/ + +typedef struct _SERVICE_GROUP +{ + LIST_ENTRY GroupListEntry; + UNICODE_STRING GroupName; + + BOOLEAN ServicesRunning; + +} SERVICE_GROUP, *PSERVICE_GROUP; + + +typedef struct _SERVICE +{ + LIST_ENTRY ServiceListEntry; + UNICODE_STRING ServiceName; + UNICODE_STRING RegistryPath; + UNICODE_STRING ServiceGroup; + + ULONG Start; + ULONG Type; + ULONG ErrorControl; + ULONG Tag; + + BOOLEAN ServiceRunning; + BOOLEAN ServiceVisited; + + HANDLE ControlPipeHandle; + ULONG ProcessId; + ULONG ThreadId; +} SERVICE, *PSERVICE; + + +/* GLOBALS *******************************************************************/ + +LIST_ENTRY GroupListHead; +LIST_ENTRY ServiceListHead; + + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS STDCALL +CreateGroupListRoutine(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + PSERVICE_GROUP Group; + + if (ValueType == REG_SZ) + { + DPRINT("Data: '%S'\n", (PWCHAR)ValueData); + + Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(SERVICE_GROUP)); + if (Group == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + if (!RtlCreateUnicodeString(&Group->GroupName, + (PWSTR)ValueData)) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + + InsertTailList(&GroupListHead, + &Group->GroupListEntry); + } + + return(STATUS_SUCCESS); +} + + +static NTSTATUS STDCALL +CreateServiceListEntry(PUNICODE_STRING ServiceName) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[6]; + PSERVICE Service = NULL; + NTSTATUS Status; + + DPRINT("Service: '%wZ'\n", ServiceName); + + /* Allocate service entry */ + Service = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(SERVICE)); + if (Service == NULL) + { + return(STATUS_INSUFFICIENT_RESOURCES); + } + + /* Copy service name */ + Service->ServiceName.Length = ServiceName->Length; + Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR); + Service->ServiceName.Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + Service->ServiceName.MaximumLength); + if (Service->ServiceName.Buffer == NULL) + { + HeapFree(GetProcessHeap(), 0, Service); + return(STATUS_INSUFFICIENT_RESOURCES); + } + RtlCopyMemory(Service->ServiceName.Buffer, + ServiceName->Buffer, + ServiceName->Length); + Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0; + + /* Build registry path */ + Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR); + Service->RegistryPath.Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + MAX_PATH * sizeof(WCHAR)); + if (Service->ServiceName.Buffer == NULL) + { + HeapFree(GetProcessHeap(), 0, Service->ServiceName.Buffer); + HeapFree(GetProcessHeap(), 0, Service); + return(STATUS_INSUFFICIENT_RESOURCES); + } + wcscpy(Service->RegistryPath.Buffer, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + wcscat(Service->RegistryPath.Buffer, + Service->ServiceName.Buffer); + Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR); + + /* Get service data */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"Start"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &Service->Start; + + QueryTable[1].Name = L"Type"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[1].EntryContext = &Service->Type; + + QueryTable[2].Name = L"ErrorControl"; + QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[2].EntryContext = &Service->ErrorControl; + + QueryTable[3].Name = L"Group"; + QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[3].EntryContext = &Service->ServiceGroup; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + ServiceName->Buffer, + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + PrintString("RtlQueryRegistryValues() failed (Status %lx)\n", Status); + RtlFreeUnicodeString(&Service->RegistryPath); + RtlFreeUnicodeString(&Service->ServiceName); + HeapFree(GetProcessHeap(), 0, Service); + return(Status); + } + + DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName); + DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); + DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); + DPRINT("Start %lx Type %lx ErrorControl %lx\n", + Service->Start, Service->Type, Service->ErrorControl); + + /* Append service entry */ + InsertTailList(&ServiceListHead, + &Service->ServiceListEntry); + + return(STATUS_SUCCESS); +} + + +NTSTATUS +ScmCreateServiceDataBase(VOID) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING ServicesKeyName; + UNICODE_STRING SubKeyName; + HKEY ServicesKey; + ULONG Index; + NTSTATUS Status; + + PKEY_BASIC_INFORMATION KeyInfo = NULL; + ULONG KeyInfoLength = 0; + ULONG ReturnedLength; + + DPRINT("ScmCreateServiceDataBase() called\n"); + + /* Initialize basic variables */ + InitializeListHead(&GroupListHead); + InitializeListHead(&ServiceListHead); + + /* Build group order list */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"List"; + QueryTable[0].QueryRoutine = CreateGroupListRoutine; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"ServiceGroupOrder", + QueryTable, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + return(Status); + + RtlInitUnicodeStringFromLiteral(&ServicesKeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"); + + InitializeObjectAttributes(&ObjectAttributes, + &ServicesKeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = RtlpNtOpenKey(&ServicesKey, + 0x10001, + &ObjectAttributes, + 0); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Allocate key info buffer */ + KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR); + KeyInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, KeyInfoLength); + if (KeyInfo == NULL) + { + NtClose(ServicesKey); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Index = 0; + while (TRUE) + { + Status = NtEnumerateKey(ServicesKey, + Index, + KeyBasicInformation, + KeyInfo, + KeyInfoLength, + &ReturnedLength); + if (NT_SUCCESS(Status)) + { + if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR)) + { + + SubKeyName.Length = KeyInfo->NameLength; + SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR); + SubKeyName.Buffer = KeyInfo->Name; + SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0; + + DPRINT("KeyName: '%wZ'\n", &SubKeyName); + Status = CreateServiceListEntry(&SubKeyName); + } + } + + if (!NT_SUCCESS(Status)) + break; + + Index++; + } + + HeapFree(GetProcessHeap(), 0, KeyInfo); + NtClose(ServicesKey); + + DPRINT("ScmCreateServiceDataBase() done\n"); + + return(STATUS_SUCCESS); +} + + +static NTSTATUS +ScmCheckDriver(PSERVICE Service) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DirName; + HANDLE DirHandle; + NTSTATUS Status; + POBJDIR_INFORMATION DirInfo; + ULONG BufferLength; + ULONG DataLength; + ULONG Index; + PLIST_ENTRY GroupEntry; + PSERVICE_GROUP CurrentGroup; + + DPRINT("ScmCheckDriver(%wZ) called\n", &Service->ServiceName); + + if (Service->Type == SERVICE_KERNEL_DRIVER) + { + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\Driver"); + } + else + { + RtlInitUnicodeStringFromLiteral(&DirName, + L"\\FileSystem"); + } + + InitializeObjectAttributes(&ObjectAttributes, + &DirName, + 0, + NULL, + NULL); + + Status = NtOpenDirectoryObject(&DirHandle, + DIRECTORY_QUERY | DIRECTORY_TRAVERSE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + BufferLength = sizeof(OBJDIR_INFORMATION) + + 2 * MAX_PATH * sizeof(WCHAR); + DirInfo = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + BufferLength); + + Index = 0; + while (TRUE) + { + Status = NtQueryDirectoryObject(DirHandle, + DirInfo, + BufferLength, + TRUE, + FALSE, + &Index, + &DataLength); + if (Status == STATUS_NO_MORE_ENTRIES) + { + /* FIXME: Add current service to 'failed service' list */ + DPRINT("Service '%wZ' failed\n", &Service->ServiceName); + break; + } + + if (!NT_SUCCESS(Status)) + break; + + DPRINT("Comparing: '%wZ' '%wZ'\n", &Service->ServiceName, &DirInfo->ObjectName); + + if (RtlEqualUnicodeString(&Service->ServiceName, &DirInfo->ObjectName, TRUE)) + { + DPRINT("Found: '%wZ' '%wZ'\n", &Service->ServiceName, &DirInfo->ObjectName); + + /* Mark service as 'running' */ + Service->ServiceRunning = TRUE; + + /* Find the driver's group and mark it as 'running' */ + if (Service->ServiceGroup.Buffer != NULL) + { + GroupEntry = GroupListHead.Flink; + while (GroupEntry != &GroupListHead) + { + CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); + + DPRINT("Checking group '%wZ'\n", &CurrentGroup->GroupName); + if (RtlEqualUnicodeString(&Service->ServiceGroup, &CurrentGroup->GroupName, TRUE)) + { + CurrentGroup->ServicesRunning = TRUE; + } + + GroupEntry = GroupEntry->Flink; + } + } + break; + } + } + + HeapFree(GetProcessHeap(), + 0, + DirInfo); + NtClose(DirHandle); + + return(STATUS_SUCCESS); +} + + +VOID +ScmGetBootAndSystemDriverState(VOID) +{ + PLIST_ENTRY ServiceEntry; + PSERVICE CurrentService; + NTSTATUS Status; + + DPRINT("ScmGetBootAndSystemDriverState() called\n"); + + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + if (CurrentService->Start == SERVICE_BOOT_START || + CurrentService->Start == SERVICE_SYSTEM_START) + { + /* Check driver */ + DPRINT(" Checking service: %wZ\n", &CurrentService->ServiceName); + + ScmCheckDriver(CurrentService); + } + ServiceEntry = ServiceEntry->Flink; + } + + DPRINT("ScmGetBootAndSystemDriverState() done\n"); +} + + +static NTSTATUS +ScmStartService(PSERVICE Service, + PSERVICE_GROUP Group) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[3]; + PROCESS_INFORMATION ProcessInformation; + STARTUPINFOW StartupInfo; + UNICODE_STRING ImagePath; + NTSTATUS Status; + ULONG Type; + BOOL Result; + + DPRINT("ScmStartService() called\n"); + + Service->ControlPipeHandle = INVALID_HANDLE_VALUE; + + if (Service->Type == SERVICE_KERNEL_DRIVER || + Service->Type == SERVICE_FILE_SYSTEM_DRIVER || + Service->Type == SERVICE_RECOGNIZER_DRIVER) + { + /* Load driver */ + DPRINT(" Path: %wZ\n", &Service->RegistryPath); + Status = NtLoadDriver(&Service->RegistryPath); + } + else + { + RtlInitUnicodeString(&ImagePath, NULL); + + /* Get service data */ + RtlZeroMemory(&QueryTable, + sizeof(QueryTable)); + + QueryTable[0].Name = L"Type"; + QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[0].EntryContext = &Type; + + QueryTable[1].Name = L"ImagePath"; + QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; + QueryTable[1].EntryContext = &ImagePath; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + Service->ServiceName.Buffer, + QueryTable, + NULL, + NULL); + if (NT_SUCCESS(Status)) + { + DPRINT("ImagePath: '%S'\n", ImagePath.Buffer); + DPRINT("Type: %lx\n", Type); + + /* FIXME: create '\\.\pipe\net\NtControlPipe' instance */ + Service->ControlPipeHandle = CreateNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe", + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 100, + 8000, + 4, + 30000, + NULL); + DPRINT1("CreateNamedPipeW() done\n"); + if (Service->ControlPipeHandle == INVALID_HANDLE_VALUE) + { + DPRINT1("Failed to create control pipe!\n"); + Status = STATUS_UNSUCCESSFUL; + goto Done; + } + + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.lpReserved = NULL; + StartupInfo.lpDesktop = NULL; + StartupInfo.lpTitle = NULL; + StartupInfo.dwFlags = 0; + StartupInfo.cbReserved2 = 0; + StartupInfo.lpReserved2 = 0; + + Result = CreateProcessW(ImagePath.Buffer, + NULL, + NULL, + NULL, + FALSE, + DETACHED_PROCESS | CREATE_SUSPENDED, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + RtlFreeUnicodeString(&ImagePath); + + if (!Result) + { + /* Close control pipe */ + CloseHandle(Service->ControlPipeHandle); + Service->ControlPipeHandle = INVALID_HANDLE_VALUE; + + DPRINT("Starting '%S' failed!\n", Service->ServiceName.Buffer); + Status = STATUS_UNSUCCESSFUL; + } + else + { + DPRINT1("Process Id: %lu Handle %lx\n", + ProcessInformation.dwProcessId, + ProcessInformation.hProcess); + DPRINT1("Tread Id: %lu Handle %lx\n", + ProcessInformation.dwThreadId, + ProcessInformation.hThread); + + /* Get process and thread ids */ + Service->ProcessId = ProcessInformation.dwProcessId; + Service->ThreadId = ProcessInformation.dwThreadId; + + /* Resume Thread */ + ResumeThread(ProcessInformation.hThread); + + /* FIXME: connect control pipe */ + if (ConnectNamedPipe(Service->ControlPipeHandle, NULL)) + { + DPRINT1("Control pipe connected!\n"); + Status = STATUS_SUCCESS; + } + else + { + DPRINT1("Connecting control pipe failed!\n"); + + /* Close control pipe */ + CloseHandle(Service->ControlPipeHandle); + Service->ControlPipeHandle = INVALID_HANDLE_VALUE; + Service->ProcessId = 0; + Service->ThreadId = 0; + Status = STATUS_UNSUCCESSFUL; + } + + /* Close process and thread handle */ + CloseHandle(ProcessInformation.hThread); + CloseHandle(ProcessInformation.hProcess); + } + } + } + +Done: + if (NT_SUCCESS(Status)) + { + if (Group != NULL) + { + Group->ServicesRunning = TRUE; + } + Service->ServiceRunning = TRUE; + } +#if 0 + else + { + if (CurrentService->ErrorControl == 1) + { + /* Log error */ + + } + else if (CurrentService->ErrorControl == 2) + { + if (IsLastKnownGood == FALSE) + { + /* Boot last known good configuration */ + + } + } + else if (CurrentService->ErrorControl == 3) + { + if (IsLastKnownGood == FALSE) + { + /* Boot last known good configuration */ + + } + else + { + /* BSOD! */ + + } + } + } +#endif + + return(STATUS_SUCCESS); +} + + +VOID +ScmAutoStartServices(VOID) +{ + PLIST_ENTRY GroupEntry; + PLIST_ENTRY ServiceEntry; + PSERVICE_GROUP CurrentGroup; + PSERVICE CurrentService; + NTSTATUS Status; + + /* Clear 'ServiceVisited' flag */ + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + CurrentService->ServiceVisited = FALSE; + ServiceEntry = ServiceEntry->Flink; + } + + /* Start all services which are members of an existing group */ + GroupEntry = GroupListHead.Flink; + while (GroupEntry != &GroupListHead) + { + CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); + + DPRINT("Group '%wZ'\n", &CurrentGroup->GroupName); + + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + if ((RtlEqualUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE)) && + (CurrentService->Start == SERVICE_AUTO_START) && + (CurrentService->ServiceVisited == FALSE)) + { + CurrentService->ServiceVisited = TRUE; + ScmStartService(CurrentService, + CurrentGroup); + } + + ServiceEntry = ServiceEntry->Flink; + } + + GroupEntry = GroupEntry->Flink; + } + + /* Start all services which are members of any non-existing group */ + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + if ((CurrentGroup->GroupName.Length > 0) && + (CurrentService->Start == SERVICE_AUTO_START) && + (CurrentService->ServiceVisited == FALSE)) + { + CurrentService->ServiceVisited = TRUE; + ScmStartService(CurrentService, + NULL); + } + + ServiceEntry = ServiceEntry->Flink; + } + + /* Start all services which are not a member of any group */ + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + if ((CurrentGroup->GroupName.Length == 0) && + (CurrentService->Start == SERVICE_AUTO_START) && + (CurrentService->ServiceVisited == FALSE)) + { + CurrentService->ServiceVisited = TRUE; + ScmStartService(CurrentService, + NULL); + } + + ServiceEntry = ServiceEntry->Flink; + } + + /* Clear 'ServiceVisited' flag again */ + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + CurrentService->ServiceVisited = FALSE; + ServiceEntry = ServiceEntry->Flink; + } +} + +/* EOF */ diff --git a/subsys/system/services/makefile b/subsys/system/services/makefile new file mode 100644 index 0000000..e803edb --- /dev/null +++ b/subsys/system/services/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = services + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ntdll.a kernel32.a user32.a + +TARGET_OBJECTS = $(TARGET_NAME).o database.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/system/services/services.c b/subsys/system/services/services.c new file mode 100644 index 0000000..e15ce08 --- /dev/null +++ b/subsys/system/services/services.c @@ -0,0 +1,303 @@ +/* $Id$ + * + * service control manager + * + * ReactOS Operating System + * + * -------------------------------------------------------------------- + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.LIB. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + */ + +/* NOTE: + * - Services.exe is NOT a native application, it is a GUI app. + */ + +/* INCLUDES *****************************************************************/ + +#define NTOS_MODE_USER +#include +#include + +#include "services.h" + +#define DBG +//#define NDEBUG +#include + + + +/* GLOBALS ******************************************************************/ + +#define PIPE_BUFSIZE 1024 +#define PIPE_TIMEOUT 1000 + + +/* FUNCTIONS *****************************************************************/ + +void +PrintString(char* fmt,...) +{ +#ifdef DBG + char buffer[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + OutputDebugStringA(buffer); +#endif +} + + +BOOL +ScmCreateStartEvent(PHANDLE StartEvent) +{ + HANDLE hEvent; + + hEvent = CreateEvent(NULL, + TRUE, + FALSE, + _T("SvcctrlStartEvent_A3725DX")); + if (hEvent == NULL) + { + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + hEvent = OpenEvent(EVENT_ALL_ACCESS, + FALSE, + _T("SvcctrlStartEvent_A3725DX")); + if (hEvent == NULL) + { + return(FALSE); + } + } + else + { + return(FALSE); + } + } + + *StartEvent = hEvent; + + return(TRUE); +} + + +BOOL +ScmNamedPipeHandleRequest( + PVOID Request, + DWORD RequestSize, + PVOID Reply, + LPDWORD ReplySize) +{ + DbgPrint("SCM READ: %s\n", Request); + + *ReplySize = 0; + + return FALSE; +} + + +DWORD +WINAPI +ScmNamedPipeThread( + LPVOID Context) +{ + CHAR chRequest[PIPE_BUFSIZE]; + CHAR chReply[PIPE_BUFSIZE]; + DWORD cbReplyBytes; + DWORD cbBytesRead; + DWORD cbWritten; + BOOL fSuccess; + HANDLE hPipe; + + DPRINT("Accepting SCM commands through named pipe\n"); + + hPipe = (HANDLE)Context; + + for (;;) + { + fSuccess = ReadFile( + hPipe, + &chRequest, + PIPE_BUFSIZE, + &cbBytesRead, + NULL); + if (!fSuccess || cbBytesRead == 0) + { + break; + } + + if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes)) + { + fSuccess = WriteFile( + hPipe, + &chReply, + cbReplyBytes, + &cbWritten, + NULL); + if (!fSuccess || cbReplyBytes != cbWritten) + { + break; + } + } + } + + FlushFileBuffers(hPipe); + DisconnectNamedPipe(hPipe); + CloseHandle(hPipe); + + return ERROR_SUCCESS; +} + + +BOOL ScmCreateNamedPipe(VOID) +{ + DWORD dwThreadId; + BOOL fConnected; + HANDLE hThread; + HANDLE hPipe; + + hPipe = CreateNamedPipe("\\\\.\\pipe\\Ntsvcs", + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + PIPE_BUFSIZE, + PIPE_BUFSIZE, + PIPE_TIMEOUT, + NULL); + if (hPipe == INVALID_HANDLE_VALUE) + { + DPRINT("CreateNamedPipe() failed (%d)\n", GetLastError()); + return(FALSE); + } + + fConnected = ConnectNamedPipe(hPipe, + NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); + if (fConnected) + { + DPRINT("Pipe connected\n"); + + hThread = CreateThread(NULL, + 0, + ScmNamedPipeThread, + (LPVOID)hPipe, + 0, + &dwThreadId); + if (!hThread) + { + DPRINT("Could not create thread (%d)\n", GetLastError()); + + DisconnectNamedPipe(hPipe); + CloseHandle(hPipe); + return(FALSE); + } + } + else + { + DPRINT("Pipe not connected\n"); + + CloseHandle(hPipe); + return FALSE; + } + + return TRUE; +} + + +int STDCALL +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nShowCmd) +{ + HANDLE hScmStartEvent; + HANDLE hEvent; + NTSTATUS Status; + + PrintString("Service Control Manager\n"); + + /* Create start event */ + if (!ScmCreateStartEvent(&hScmStartEvent)) + { + PrintString("SERVICES: Failed to create start event\n"); + ExitThread(0); + } + + + /* FIXME: more initialization */ + + + /* Create the service database */ + Status = ScmCreateServiceDataBase(); + if (!NT_SUCCESS(Status)) + { + PrintString("ScmCreateServiceDataBase() failed (Status %lx)\n", Status); + ExitThread(0); + } + + /* Update service database */ + ScmGetBootAndSystemDriverState(); + +#if 0 + /* Create named pipe */ + if (!ScmCreateNamedPipe()) + { + PrintString("SERVICES: Failed to create named pipe\n"); + ExitThread(0); + } +#endif + /* FIXME: create listener thread for pipe */ + + + /* Register service process with CSRSS */ + RegisterServicesProcess(GetCurrentProcessId()); + + PrintString("SERVICES: Initialized.\n"); + + /* Signal start event */ + SetEvent(hScmStartEvent); + + /* FIXME: register event handler (used for system shutdown) */ +// SetConsoleCtrlHandler(...); + + + /* Start auto-start services */ + ScmAutoStartServices(); + + /* FIXME: more to do ? */ + + + PrintString("SERVICES: Running.\n"); + + hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + WaitForSingleObject(hEvent, INFINITE); +#if 0 + for (;;) + { + NtYieldExecution(); + } +#endif + + PrintString("SERVICES: Finished.\n"); + + ExitThread(0); + return(0); +} + +/* EOF */ diff --git a/subsys/system/services/services.h b/subsys/system/services/services.h new file mode 100644 index 0000000..443ac04 --- /dev/null +++ b/subsys/system/services/services.h @@ -0,0 +1,19 @@ +/* + * services.h + */ + + +/* services.c */ + +void PrintString(char* fmt,...); + + +/* database.c */ + +NTSTATUS ScmCreateServiceDataBase(VOID); +VOID ScmGetBootAndSystemDriverState(VOID); +VOID ScmAutoStartServices(VOID); + + +/* EOF */ + diff --git a/subsys/system/services/services.rc b/subsys/system/services/services.rc new file mode 100644 index 0000000..6870571 --- /dev/null +++ b/subsys/system/services/services.rc @@ -0,0 +1,38 @@ +#include "../../../include/defines.h" +#include "../../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Service Control Manager\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "Services\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "Services.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/shell/.cvsignore b/subsys/system/shell/.cvsignore new file mode 100644 index 0000000..40e130e --- /dev/null +++ b/subsys/system/shell/.cvsignore @@ -0,0 +1,6 @@ +shell.coff +shell.exe +shell.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/system/shell/makefile b/subsys/system/shell/makefile new file mode 100644 index 0000000..5723fc4 --- /dev/null +++ b/subsys/system/shell/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = shell + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ntdll.a kernel32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/system/shell/shell.c b/subsys/system/shell/shell.c new file mode 100644 index 0000000..26dd9e1 --- /dev/null +++ b/subsys/system/shell/shell.c @@ -0,0 +1,504 @@ +/* $Id$ + * + * PROJECT : ReactOS Operating System + * DESCRIPTION: ReactOS' Native Shell + * LICENSE : See top level directory + * + */ +#define NTOS_MODE_USER +#include +#include +#include +#include +#include +#include +#include + + +HANDLE InputHandle, OutputHandle; +BOOL bCanExit = TRUE, bCanLinespace = TRUE; + + +void debug_printf(char* fmt, ...) +{ + va_list args; + char buffer[512]; + DWORD nbChar; + + va_start(args,fmt); + _vsnprintf(buffer,512,fmt,args); + va_end(args); + WriteConsoleA(OutputHandle, buffer, strlen(buffer), &nbChar, NULL); +} + +void ExecuteCls(void) +{ + DWORD dwWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + COORD coPos; + + GetConsoleScreenBufferInfo (OutputHandle, &csbi); + + coPos.X = 0; + coPos.Y = 0; + FillConsoleOutputAttribute (OutputHandle, csbi.wAttributes, (csbi.dwSize.X)*(csbi.dwSize.Y), coPos, &dwWritten); + FillConsoleOutputCharacter (OutputHandle, _T(' '), (csbi.dwSize.X)*(csbi.dwSize.Y), coPos, &dwWritten); + SetConsoleCursorPosition (OutputHandle, coPos); +} + +void ExecuteVer(void) +{ + debug_printf( + "Reactos Simple Shell\n(compiled on %s, at %s)\n", + __DATE__, + __TIME__ + ); +} + +void ExecuteCd(char* cmdline) +{ + if (!SetCurrentDirectoryA(cmdline)) + { + debug_printf("Invalid directory\n"); + } +} + +void ExecuteMd (char *cmdline) +{ + if (!CreateDirectoryA (cmdline, NULL)) + { + debug_printf("Create Directory failed!\n"); + } +} + +void ExecuteDir(char* cmdline) +{ + HANDLE shandle; + WIN32_FIND_DATA FindData; + int nFile=0, nRep=0; + FILETIME fTime; + SYSTEMTIME sTime; + + shandle = FindFirstFile("*",&FindData); + + if (shandle==INVALID_HANDLE_VALUE) + { + debug_printf("File not found\n"); + return; + } + do + { + debug_printf("%-15.15s",FindData.cAlternateFileName); + if(FindData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY) + debug_printf("

"),nRep++; + else + debug_printf(" %10d ",FindData.nFileSizeLow),nFile++; + + FileTimeToLocalFileTime(&FindData.ftLastWriteTime ,&fTime); + FileTimeToSystemTime(&fTime, &sTime); + debug_printf("%02d/%02d/%04d %02d:%02d:%02d " + ,sTime.wMonth,sTime.wDay,sTime.wYear + ,sTime.wHour,sTime.wMinute,sTime.wSecond); + + debug_printf("%s\n",FindData.cFileName); + } while(FindNextFile(shandle,&FindData)); + debug_printf("\n %d files\n %d directories\n",nFile,nRep); + FindClose(shandle); +} + + +void ExecuteReboot(char* cmdline) +{ + NtShutdownSystem (ShutdownReboot); +} + + +void ExecuteShutdown(char* cmdline) +{ + NtShutdownSystem (ShutdownNoReboot); +} + + +void ExecuteType(char* cmdline) +{ + HANDLE FileHandle; + char c; + DWORD Result; + BOOL Success; + + FileHandle = CreateFile(cmdline, + FILE_GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (FileHandle == NULL) + { + debug_printf("Unknown file\n"); + return; + } + do + { + Success = ReadFile(FileHandle, + &c, + 1, + &Result, + NULL); + if (Success) + { + debug_printf("%c",c); + c = 0; + } + } while (Success && Result > 0); + CloseHandle(FileHandle); +} + +int ExecuteProcess(char* name, char* cmdline, BOOL detached) +{ + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + BOOL ret; + CHAR fullname[260]; + PCHAR p; + + /* append '.exe' if needed */ + strcpy (fullname, name); + p = strrchr (fullname, '.'); + if ((p == NULL) || + (_stricmp (p, ".exe") != 0)) + { + strcat (fullname, ".exe"); + } + + memset(&StartupInfo, 0, sizeof(StartupInfo)); + StartupInfo.cb = sizeof (STARTUPINFO); + StartupInfo.lpTitle = name; + if( cmdline && *cmdline ) + *(cmdline-1) = ' '; // fix command line so it is the FULL command, including exe name + ret = CreateProcessA(fullname, + name, + NULL, + NULL, + FALSE, + ((TRUE == detached) + ? CREATE_NEW_CONSOLE + : 0 + ), + NULL, + NULL, + & StartupInfo, + & ProcessInformation + ); + if (TRUE == detached) + { + if (ret) + { + debug_printf("\"%s\" detached:\n" + "\thProcess = %08X\n" + "\thThread = %08X\n" + "\tPID = %d\n" + "\tTID = %d\n\n", + fullname, + ProcessInformation.hProcess, + ProcessInformation.hThread, + ProcessInformation.dwProcessId, + ProcessInformation.dwThreadId); + CloseHandle(ProcessInformation.hProcess); + CloseHandle(ProcessInformation.hThread); + } + else + { + debug_printf("Could not detach %s\n", name); + } + } + else + { + if (ret) + { +// debug_printf("ProcessInformation.hThread %x\n", +// ProcessInformation.hThread); + WaitForSingleObject(ProcessInformation.hProcess, INFINITE); + CloseHandle(ProcessInformation.hProcess); +// debug_printf("Thandle %x\n", ProcessInformation.hThread); + CloseHandle(ProcessInformation.hThread); + } + } + return(ret); +} + +void ExecuteStart(char* CommandLine) +{ + char *ImageName = CommandLine; + + for ( ; + ( (*CommandLine) + && (*CommandLine != ' ') + && (*CommandLine != '\t') + ); + CommandLine++ + ); + *CommandLine++ = '\0'; + while ( (*CommandLine) + && ( (*CommandLine == ' ') + || (*CommandLine == '\t') + ) + ); + ExecuteProcess( + ImageName, + CommandLine, + TRUE + ); + return; +} + +void +ExecuteKill(char * lpPid) +{ + HANDLE hProcess; + DWORD dwProcessId; + + dwProcessId = (DWORD) atol(lpPid); + debug_printf("Killing PID %d...\n",dwProcessId); + hProcess = OpenProcess( + PROCESS_TERMINATE, + FALSE, + dwProcessId + ); + if (NULL == hProcess) + { + debug_printf( + "Could not open the process with PID = %d\n", + dwProcessId + ); + return; + } + if (FALSE == TerminateProcess( + hProcess, + 0 + ) + ) { + debug_printf( + "Could not terminate the process with PID = %d\n", + dwProcessId + ); + } + CloseHandle(hProcess); + return; +} + +void ExecuteHelp (void * dummy) +{ + debug_printf ( + "A:\t\t\tCurrent drive is A:\n" + "C:\t\t\tCurrent drive is C:\n" + "cd [directory]\t\tChange current directory\n" + "dir [directory]\t\tList directory\n" + "exit\t\t\tTerminate the shell\n" + "help\t\t\tPrint this help message\n" + "kill [pid]\t\tKill process which PID is pid\n" + "md [directory]\t\tCreate a new directory\n" + "reboot\t\t\tRestart the system\n" + "start [program.exe]\tDetach program.exe\n" + "type [file]\t\tPrint the file on console\n" + "validate\t\tValidate the process' heap\n" + "ver\t\t\tPrint version information\n" + "[program.exe]\t\tStart synchronously program.exe\n" + ); +} + +void ExecuteCommand(char* line) +{ + char* cmd; + char* tail; + + if (isalpha(line[0]) && line[1] == ':' && line[2] == 0) + { + char szPath[MAX_PATH]; + char szVar[5]; + + /* save curent directory in environment variable */ + GetCurrentDirectory (MAX_PATH, szPath); + + strcpy (szVar, "=A:"); + szVar[1] = toupper (szPath[0]); + SetEnvironmentVariable (szVar, szPath); + + /* check for current directory of new drive */ + strcpy (szVar, "=A:"); + szVar[1] = toupper (line[0]); + if (GetEnvironmentVariable (szVar, szPath, MAX_PATH) == 0) + { + /* no environment variable found */ + strcpy (szPath, "A:\\"); + szPath[0] = toupper (line[0]); + } + + /* set new current directory */ + SetCurrentDirectory (szPath); + GetCurrentDirectory (MAX_PATH, szPath); + if (szPath[0] != (char)toupper (line[0])) + debug_printf("Invalid drive\n"); + + return; + } + + tail = line; + while ((*tail)!=' ' && (*tail)!=0) + { + tail++; + } + if ((*tail)==' ') + { + *tail = 0; + tail++; + } + cmd = line; + + + if (cmd==NULL || *cmd == '\0' ) + { + return; + } + if (strcmp(cmd,"cd")==0) + { + ExecuteCd(tail); + return; + } + if (strcmp(cmd,"dir")==0) + { + ExecuteDir(tail); + return; + } + if (strcmp(cmd,"kill")==0) + { + ExecuteKill(tail); + return; + } + if (strcmp(cmd,"md")==0) + { + ExecuteMd(tail); + return; + } + if (strcmp(cmd,"reboot")==0) + { + ExecuteReboot(tail); + return; + } + if (strcmp(cmd,"shutdown")==0) + { + ExecuteShutdown(tail); + return; + } + if (strcmp(cmd,"type")==0) + { + ExecuteType(tail); + return; + } + if (strcmp(cmd,"ver")==0) + { + ExecuteVer(); + return; + } + if (strcmp(cmd,"validate")==0) + { + debug_printf("Validating heap..."); + if (HeapValidate(GetProcessHeap(),0,NULL)) + { + debug_printf("succeeded\n"); + } + else + { + debug_printf("failed\n"); + } + return; + } + if (strcmp(cmd,"start") == 0) + { + ExecuteStart(tail); + return; + } + if ((strcmp(cmd,"help") * strcmp(cmd,"?")) == 0) + { + ExecuteHelp(tail); + return; + } + if (strcmp(cmd,"exit")==0) + { + if (bCanExit == TRUE) + { + ExitProcess(0); + } + return; + } + if (strcmp(cmd,"cls") == 0) + { + ExecuteCls(); + bCanLinespace = FALSE; + return; + } + if (ExecuteProcess(cmd,tail,FALSE)) + { + return; + } + debug_printf("Unknown command '%s'\n", cmd); +} + +void ReadLine(char* line) +{ + DWORD Result; + UCHAR CurrentDir[255]; + + GetCurrentDirectoryA(255,CurrentDir); + debug_printf("%s>", CurrentDir); + if ( !ReadConsoleA(InputHandle, line, 252, &Result, NULL) ) + { + debug_printf("Failed to read from console\n"); + for(;;); + } + // If the \n is in there, so is the \r so null it, otherwise, null the last char + if( line[Result-1] == '\n' ) + line[Result-2] = 0; + else { + line[Result] = 0; + } +} + +void ParseCommandLine (void) +{ + char *pszCommandLine; + + pszCommandLine = GetCommandLineA (); + _strupr (pszCommandLine); + if (strstr (pszCommandLine, "/P") != NULL) + { + debug_printf("Permanent shell\n"); + bCanExit = FALSE; + } +} + +int main(void) +{ + static char line[256]; + + AllocConsole(); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + ParseCommandLine (); + + for(;;) + { + ReadLine(line); + ExecuteCommand(line); + if(bCanLinespace) + { + printf("\n"); + } else + bCanLinespace = TRUE; + } + + return 0; +} + +/* EOF */ diff --git a/subsys/system/shell/shell.rc b/subsys/system/shell/shell.rc new file mode 100644 index 0000000..0982e26 --- /dev/null +++ b/subsys/system/shell/shell.rc @@ -0,0 +1,38 @@ +#include "../../../include/defines.h" +#include "../../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Simple Shell\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "shell\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "shell.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/usetup/.cvsignore b/subsys/system/usetup/.cvsignore new file mode 100644 index 0000000..9c63d05 --- /dev/null +++ b/subsys/system/usetup/.cvsignore @@ -0,0 +1,5 @@ +*.coff +*.d +*.exe +*.o +*.sym diff --git a/subsys/system/usetup/console.c b/subsys/system/usetup/console.c new file mode 100644 index 0000000..e9fbc2b --- /dev/null +++ b/subsys/system/usetup/console.c @@ -0,0 +1,1025 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/console.c + * PURPOSE: Console support functions + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#include "usetup.h" +#include "console.h" + + +/* GLOBALS ******************************************************************/ + +static HANDLE StdInput = INVALID_HANDLE_VALUE; +static HANDLE StdOutput = INVALID_HANDLE_VALUE; +static HANDLE InputEvent = INVALID_HANDLE_VALUE; + +static SHORT xScreen = 0; +static SHORT yScreen = 0; + + +NTSTATUS +GetConsoleScreenBufferInfo(PCONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo); + + +/* FUNCTIONS *****************************************************************/ + + + +NTSTATUS +AllocConsole(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + NTSTATUS Status; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + /* Open the screen */ + RtlInitUnicodeString(&Name, + L"\\??\\BlueScreen"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + Status = NtCreateFile(&StdOutput, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + 0, + FILE_OPEN, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Create input event */ + Status = NtCreateEvent(&InputEvent, + STANDARD_RIGHTS_ALL, + NULL, + FALSE, + FALSE); + if (!NT_SUCCESS(Status)) + return(Status); + + /* Open the keyboard */ + RtlInitUnicodeString(&Name, + L"\\??\\Keyboard"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + Status = NtCreateFile(&StdInput, + FILE_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + 0, + FILE_OPEN, + 0, + NULL, + 0); + + GetConsoleScreenBufferInfo(&csbi); + + xScreen = csbi.dwSize.X; + yScreen = csbi.dwSize.Y; + + return(Status); +} + + +VOID +FreeConsole(VOID) +{ + if (StdInput != INVALID_HANDLE_VALUE) + NtClose(StdInput); + + if (StdOutput != INVALID_HANDLE_VALUE) + NtClose(StdOutput); + + if (InputEvent != INVALID_HANDLE_VALUE) + NtClose(InputEvent); +} + + + + +NTSTATUS +WriteConsole(PCHAR Buffer, + ULONG NumberOfCharsToWrite, + PULONG NumberOfCharsWritten) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status = STATUS_SUCCESS; + ULONG i; + + Status = NtWriteFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + Buffer, + NumberOfCharsToWrite, + NULL, + NULL); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + if (NumberOfCharsWritten != NULL) + { + *NumberOfCharsWritten = IoStatusBlock.Information; + } + + return(Status); +} + + +#if 0 +/*-------------------------------------------------------------- + * ReadConsoleA + */ +WINBOOL +STDCALL +ReadConsoleA(HANDLE hConsoleInput, + LPVOID lpBuffer, + DWORD nNumberOfCharsToRead, + LPDWORD lpNumberOfCharsRead, + LPVOID lpReserved) +{ + KEY_EVENT_RECORD KeyEventRecord; + BOOL stat = TRUE; + PCHAR Buffer = (PCHAR)lpBuffer; + DWORD Result; + int i; + + for (i=0; (stat && iEventType = KEY_EVENT; + Status = NtReadFile(StdInput, + InputEvent, + NULL, + NULL, + &Iosb, + &Buffer->Event.KeyEvent, //&KeyEventRecord->InputEvent.Event.KeyEvent, + sizeof(KEY_EVENT_RECORD), + NULL, + 0); + + if( Status == STATUS_PENDING ) + { + NtWaitForSingleObject(InputEvent, + FALSE, + NULL); + Status = Iosb.Status; + } + + return(Status); +} + + +NTSTATUS +ReadConsoleOutputCharacters(LPSTR lpCharacter, + ULONG nLength, + COORD dwReadCoord, + PULONG lpNumberOfCharsRead) +{ + IO_STATUS_BLOCK IoStatusBlock; + ULONG dwBytesReturned; + OUTPUT_CHARACTER Buffer; + NTSTATUS Status; + + Buffer.dwCoord = dwReadCoord; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_READ_OUTPUT_CHARACTER, + &Buffer, + sizeof(OUTPUT_CHARACTER), + (PVOID)lpCharacter, + nLength); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + if (NT_SUCCESS(Status) && lpNumberOfCharsRead != NULL) + { + *lpNumberOfCharsRead = Buffer.dwTransfered; + } + + return(Status); +} + + +NTSTATUS +ReadConsoleOutputAttributes(PUSHORT lpAttribute, + ULONG nLength, + COORD dwReadCoord, + PULONG lpNumberOfAttrsRead) +{ + IO_STATUS_BLOCK IoStatusBlock; + ULONG dwBytesReturned; + OUTPUT_ATTRIBUTE Buffer; + NTSTATUS Status; + + Buffer.dwCoord = dwReadCoord; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE, + &Buffer, + sizeof(OUTPUT_ATTRIBUTE), + (PVOID)lpAttribute, + nLength); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + if (NT_SUCCESS(Status) && lpNumberOfAttrsRead != NULL) + { + *lpNumberOfAttrsRead = Buffer.dwTransfered; + } + + return(Status); +} + + +NTSTATUS +WriteConsoleOutputCharacters(LPCSTR lpCharacter, + ULONG nLength, + COORD dwWriteCoord) +{ + IO_STATUS_BLOCK IoStatusBlock; + PCHAR Buffer; + COORD *pCoord; + PCHAR pText; + NTSTATUS Status; + + Buffer = RtlAllocateHeap(ProcessHeap, + 0, + nLength + sizeof(COORD)); + pCoord = (COORD *)Buffer; + pText = (PCHAR)(pCoord + 1); + + *pCoord = dwWriteCoord; + memcpy(pText, lpCharacter, nLength); + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, + NULL, + 0, + Buffer, + nLength + sizeof(COORD)); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + RtlFreeHeap(ProcessHeap, + 0, + Buffer); + + return(Status); +} + + +NTSTATUS +WriteConsoleOutputAttributes(CONST USHORT *lpAttribute, + ULONG nLength, + COORD dwWriteCoord, + PULONG lpNumberOfAttrsWritten) +{ + IO_STATUS_BLOCK IoStatusBlock; + PUSHORT Buffer; + COORD *pCoord; + PUSHORT pAttrib; + NTSTATUS Status; + + Buffer = RtlAllocateHeap(ProcessHeap, + 0, + nLength * sizeof(USHORT) + sizeof(COORD)); + pCoord = (COORD *)Buffer; + pAttrib = (PUSHORT)(pCoord + 1); + + *pCoord = dwWriteCoord; + memcpy(pAttrib, lpAttribute, nLength * sizeof(USHORT)); + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE, + NULL, + 0, + Buffer, + nLength * sizeof(USHORT) + sizeof(COORD)); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + RtlFreeHeap(ProcessHeap, + 0, + Buffer); + + return(Status); +} + + +NTSTATUS +FillConsoleOutputAttribute(USHORT wAttribute, + ULONG nLength, + COORD dwWriteCoord, + PULONG lpNumberOfAttrsWritten) +{ + IO_STATUS_BLOCK IoStatusBlock; + OUTPUT_ATTRIBUTE Buffer; + ULONG dwBytesReturned; + NTSTATUS Status; + + Buffer.wAttribute = wAttribute; + Buffer.nLength = nLength; + Buffer.dwCoord = dwWriteCoord; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE, + &Buffer, + sizeof(OUTPUT_ATTRIBUTE), + &Buffer, + sizeof(OUTPUT_ATTRIBUTE)); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + if (NT_SUCCESS(Status)) + { + *lpNumberOfAttrsWritten = Buffer.dwTransfered; + } + + return(Status); +} + + +NTSTATUS +FillConsoleOutputCharacter(CHAR Character, + ULONG Length, + COORD WriteCoord, + PULONG NumberOfCharsWritten) +{ + IO_STATUS_BLOCK IoStatusBlock; + OUTPUT_CHARACTER Buffer; + ULONG dwBytesReturned; + NTSTATUS Status; + + Buffer.cCharacter = Character; + Buffer.nLength = Length; + Buffer.dwCoord = WriteCoord; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER, + &Buffer, + sizeof(OUTPUT_CHARACTER), + &Buffer, + sizeof(OUTPUT_CHARACTER)); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + if (NT_SUCCESS(Status)) + { + *NumberOfCharsWritten = Buffer.dwTransfered; + } + + return(Status); +} + + +#if 0 +/*-------------------------------------------------------------- + * GetConsoleMode + */ +WINBASEAPI +BOOL +WINAPI +GetConsoleMode( + HANDLE hConsoleHandle, + LPDWORD lpMode + ) +{ + CONSOLE_MODE Buffer; + DWORD dwBytesReturned; + + if (DeviceIoControl (hConsoleHandle, + IOCTL_CONSOLE_GET_MODE, + NULL, + 0, + &Buffer, + sizeof(CONSOLE_MODE), + &dwBytesReturned, + NULL)) + { + *lpMode = Buffer.dwMode; + SetLastError (ERROR_SUCCESS); + return TRUE; + } + + SetLastError(0); /* FIXME: What error code? */ + return FALSE; +} + + +/*-------------------------------------------------------------- + * GetConsoleCursorInfo + */ +WINBASEAPI +BOOL +WINAPI +GetConsoleCursorInfo( + HANDLE hConsoleOutput, + PCONSOLE_CURSOR_INFO lpConsoleCursorInfo + ) +{ + DWORD dwBytesReturned; + + if (DeviceIoControl (hConsoleOutput, + IOCTL_CONSOLE_GET_CURSOR_INFO, + NULL, + 0, + lpConsoleCursorInfo, + sizeof(CONSOLE_CURSOR_INFO), + &dwBytesReturned, + NULL)) + return TRUE; + + return FALSE; +} + + +NTSTATUS +SetConsoleMode(HANDLE hConsoleHandle, + ULONG dwMode) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + CONSOLE_MODE Buffer; + + Buffer.dwMode = dwMode; + + Status = NtDeviceIoControlFile(hConsoleHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_SET_MODE, + &Buffer, + sizeof(CONSOLE_MODE), + NULL, + 0); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(hConsoleHandle, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + return(Status); +} +#endif + + +NTSTATUS +GetConsoleScreenBufferInfo(PCONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, + NULL, + 0, + ConsoleScreenBufferInfo, + sizeof(CONSOLE_SCREEN_BUFFER_INFO)); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + return(Status); +} + + +NTSTATUS +SetConsoleCursorInfo(PCONSOLE_CURSOR_INFO lpConsoleCursorInfo) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_SET_CURSOR_INFO, + (PCONSOLE_CURSOR_INFO)lpConsoleCursorInfo, + sizeof(CONSOLE_CURSOR_INFO), + NULL, + 0); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + return(Status); +} + + +NTSTATUS +SetConsoleCursorPosition(COORD dwCursorPosition) +{ + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + Status = GetConsoleScreenBufferInfo(&ConsoleScreenBufferInfo); + if (!NT_SUCCESS(Status)) + return(Status); + + ConsoleScreenBufferInfo.dwCursorPosition.X = dwCursorPosition.X; + ConsoleScreenBufferInfo.dwCursorPosition.Y = dwCursorPosition.Y; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, + &ConsoleScreenBufferInfo, + sizeof(CONSOLE_SCREEN_BUFFER_INFO), + NULL, + 0); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + return(Status); +} + + +NTSTATUS +SetConsoleTextAttribute(WORD wAttributes) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + Status = NtDeviceIoControlFile(StdOutput, + NULL, + NULL, + NULL, + &IoStatusBlock, + IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE, + &wAttributes, + sizeof(WORD), + NULL, + 0); + if (Status == STATUS_PENDING) + { + NtWaitForSingleObject(StdOutput, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + return(Status); +} + + + + +VOID +ConInKey(PINPUT_RECORD Buffer) +{ + ULONG KeysRead; + + while (TRUE) + { + ReadConsoleInput(Buffer); + + if ((Buffer->EventType == KEY_EVENT) && + (Buffer->Event.KeyEvent.bKeyDown == TRUE)) + break; + } +} + + +VOID +ConOutChar(CHAR c) +{ + ULONG Written; + + WriteConsole(&c, + 1, + &Written); +} + + +VOID +ConOutPuts(LPSTR szText) +{ + ULONG Written; + + WriteConsole(szText, + strlen(szText), + &Written); + WriteConsole("\n", + 1, + &Written); +} + + +VOID +ConOutPrintf(LPSTR szFormat, ...) +{ + CHAR szOut[256]; + DWORD dwWritten; + va_list arg_ptr; + + va_start(arg_ptr, szFormat); + vsprintf(szOut, szFormat, arg_ptr); + va_end(arg_ptr); + + WriteConsole(szOut, + strlen(szOut), + &dwWritten); +} + + + + + +SHORT +GetCursorX(VOID) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(&csbi); + + return(csbi.dwCursorPosition.X); +} + + +SHORT +GetCursorY(VOID) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(&csbi); + + return(csbi.dwCursorPosition.Y); +} + + +VOID +GetScreenSize(SHORT *maxx, + SHORT *maxy) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(&csbi); + + if (maxx) + *maxx = csbi.dwSize.X; + + if (maxy) + *maxy = csbi.dwSize.Y; +} + + +VOID +SetCursorType(BOOL bInsert, + BOOL bVisible) +{ + CONSOLE_CURSOR_INFO cci; + + cci.dwSize = bInsert ? 10 : 99; + cci.bVisible = bVisible; + + SetConsoleCursorInfo(&cci); +} + + +VOID +SetCursorXY(SHORT x, + SHORT y) +{ + COORD coPos; + + coPos.X = x; + coPos.Y = y; + SetConsoleCursorPosition(coPos); +} + + +VOID +ClearScreen(VOID) +{ + COORD coPos; + ULONG Written; + + coPos.X = 0; + coPos.Y = 0; + + FillConsoleOutputAttribute(0x17, + xScreen * yScreen, + coPos, + &Written); + + FillConsoleOutputCharacter(' ', + xScreen * yScreen, + coPos, + &Written); +} + + +VOID +SetStatusText(PCHAR Text) +{ + COORD coPos; + ULONG Written; + + coPos.X = 0; + coPos.Y = yScreen - 1; + + FillConsoleOutputAttribute(0x70, + xScreen, + coPos, + &Written); + + FillConsoleOutputCharacter(' ', + xScreen, + coPos, + &Written); + + WriteConsoleOutputCharacters(Text, + strlen(Text), + coPos); +} + + +VOID +SetTextXY(SHORT x, SHORT y, PCHAR Text) +{ + COORD coPos; + + coPos.X = x; + coPos.Y = y; + + WriteConsoleOutputCharacters(Text, + strlen(Text), + coPos); +} + + +VOID +SetInputTextXY(SHORT x, SHORT y, SHORT len, PCHAR Text) +{ + COORD coPos; + ULONG Length; + ULONG Written; + + coPos.X = x; + coPos.Y = y; + + Length = strlen(Text); + + FillConsoleOutputAttribute(0x70, + len, + coPos, + &Written); + + WriteConsoleOutputCharacters(Text, + Length, + coPos); + + coPos.X += Length; + FillConsoleOutputCharacter('_', + 1, + coPos, + &Written); + + if (len > Length + 1) + { + coPos.X++; + FillConsoleOutputCharacter(' ', + len - Length - 1, + coPos, + &Written); + } +} + + +VOID +SetUnderlinedTextXY(SHORT x, SHORT y, PCHAR Text) +{ + COORD coPos; + ULONG Length; + ULONG Written; + + coPos.X = x; + coPos.Y = y; + + Length = strlen(Text); + + WriteConsoleOutputCharacters(Text, + Length, + coPos); + + coPos.Y++; + FillConsoleOutputCharacter(0xCD, + Length, + coPos, + &Written); +} + + +VOID +SetInvertedTextXY(SHORT x, SHORT y, PCHAR Text) +{ + COORD coPos; + ULONG Length; + ULONG Written; + + coPos.X = x; + coPos.Y = y; + + Length = strlen(Text); + + FillConsoleOutputAttribute(0x71, + Length, + coPos, + &Written); + + WriteConsoleOutputCharacters(Text, + Length, + coPos); +} + + +VOID +SetHighlightedTextXY(SHORT x, SHORT y, PCHAR Text) +{ + COORD coPos; + ULONG Length; + ULONG Written; + + coPos.X = x; + coPos.Y = y; + + Length = strlen(Text); + + FillConsoleOutputAttribute(0x1F, + Length, + coPos, + &Written); + + WriteConsoleOutputCharacters(Text, + Length, + coPos); +} + + +VOID +PrintTextXY(SHORT x, SHORT y, char* fmt,...) +{ + char buffer[512]; + va_list ap; + COORD coPos; + +CHECKPOINT1; + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); +CHECKPOINT1; +DPRINT1("%s\n", buffer); +CHECKPOINT1; + + coPos.X = x; + coPos.Y = y; + + WriteConsoleOutputCharacters(buffer, + strlen(buffer), + coPos); +} + +/* EOF */ diff --git a/subsys/system/usetup/console.h b/subsys/system/usetup/console.h new file mode 100644 index 0000000..cecff91 --- /dev/null +++ b/subsys/system/usetup/console.h @@ -0,0 +1,127 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/console.h + * PURPOSE: Console support functions + * PROGRAMMER: Eric Kohl + */ + +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ + +#include + + +NTSTATUS +AllocConsole(VOID); + +VOID +FreeConsole(VOID); + + +NTSTATUS +ReadConsoleOutputCharacters(LPSTR lpCharacter, + ULONG nLength, + COORD dwReadCoord, + PULONG lpNumberOfCharsRead); + +NTSTATUS +ReadConsoleOutputAttributes(PUSHORT lpAttribute, + ULONG nLength, + COORD dwReadCoord, + PULONG lpNumberOfAttrsRead); + +NTSTATUS +WriteConsoleOutputCharacters(LPCSTR lpCharacter, + ULONG nLength, + COORD dwWriteCoord); + +NTSTATUS +WriteConsoleOutputAttributes(CONST USHORT *lpAttribute, + ULONG nLength, + COORD dwWriteCoord, + PULONG lpNumberOfAttrsWritten); + +#if 0 +NTSTATUS +SetConsoleMode(HANDLE hConsoleHandle, + ULONG dwMode); +#endif + +VOID +ConInKey(PINPUT_RECORD Buffer); + +VOID +ConOutChar(CHAR c); + +VOID +ConOutPuts(LPSTR szText); + +VOID +ConOutPrintf(LPSTR szFormat, ...); + +SHORT +GetCursorX(VOID); + +SHORT +GetCursorY(VOID); + +VOID +GetScreenSize(SHORT *maxx, + SHORT *maxy); + + +VOID +SetCursorType(BOOL bInsert, + BOOL bVisible); + +VOID +SetCursorXY(SHORT x, + SHORT y); + + +VOID +ClearScreen(VOID); + +VOID +SetStatusText(PCHAR Text); + +VOID +SetTextXY(SHORT x, SHORT y, PCHAR Text); + +VOID +SetInputTextXY(SHORT x, SHORT y, SHORT len, PCHAR Text); + +VOID +SetUnderlinedTextXY(SHORT x, SHORT y, PCHAR Text); + +VOID +SetInvertedTextXY(SHORT x, SHORT y, PCHAR Text); + +VOID +SetHighlightedTextXY(SHORT x, SHORT y, PCHAR Text); + +VOID +PrintTextXY(SHORT x, SHORT y, char* fmt,...); + +#endif /* __CONSOLE_H__*/ + +/* EOF */ diff --git a/subsys/system/usetup/drivesup.c b/subsys/system/usetup/drivesup.c new file mode 100644 index 0000000..c87f74e --- /dev/null +++ b/subsys/system/usetup/drivesup.c @@ -0,0 +1,163 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/drivesup.c + * PURPOSE: Drive support functions + * PROGRAMMER: Eric Kohl + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#include "usetup.h" +#include "drivesup.h" + + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +GetSourcePaths(PUNICODE_STRING SourcePath, + PUNICODE_STRING SourceRootPath) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING LinkName; + UNICODE_STRING SourceName; + WCHAR SourceBuffer[MAX_PATH]; + HANDLE Handle; + NTSTATUS Status; + ULONG Length; + PWCHAR Ptr; + + RtlInitUnicodeString(&LinkName, + L"\\SystemRoot"); + + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_OPENLINK, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return(Status); + + SourceName.Length = 0; + SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR); + SourceName.Buffer = SourceBuffer; + + Status = NtQuerySymbolicLinkObject(Handle, + &SourceName, + &Length); + NtClose(Handle); + + if (NT_SUCCESS(Status)) + { + RtlCreateUnicodeString(SourcePath, + SourceName.Buffer); + + /* strip trailing directory */ + Ptr = wcsrchr(SourceName.Buffer, L'\\'); +// if ((Ptr != NULL) && +// (wcsicmp(Ptr, L"\\reactos") == 0)) + if (Ptr != NULL) + *Ptr = 0; + + RtlCreateUnicodeString(SourceRootPath, + SourceName.Buffer); + } + + NtClose(Handle); + + return(STATUS_SUCCESS); +} + + +#if 0 +CHAR +GetDriveLetter(IN ULONG DriveNumber, + IN ULONG PartitionNumber) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING LinkName; + WCHAR LinkBuffer[8]; + WCHAR Letter; + HANDLE LinkHandle; + UNICODE_STRING TargetName; + WCHAR TargetBuffer[MAX_PATH]; +// WCHAR DeviceBuffer[MAX_PATH]; + ULONG Length; + + wcscpy(LinkBuffer, + L"\\??\\A:"); + + RtlInitUnicodeString(&LinkName, + LinkBuffer); + + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_OPENLINK, + NULL, + NULL); + + TargetName.Length = 0; + TargetName.MaximumLength = MAX_PATH * sizeof(WCHAR); + TargetName.Buffer = TargetBuffer; + + for (Letter = L'C'; Letter <= L'Z'; Letter++) + { + LinkBuffer[4] = Letter; + TargetName.Length = 0; + + Status = NtOpenSymbolicLinkObject(&LinkHandle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + Status = NtQuerySymbolicLinkObject(LinkHandle, + &TargetName, + &Length); + if (NT_SUCCESS(Status)) + { + + + + } + NtClose(LinkHandle); + } + } + + return((CHAR)0); +} +#endif + +#if 0 +STATUS +GetFileSystem() +{ + +} +#endif + +/* EOF */ diff --git a/subsys/system/usetup/drivesup.h b/subsys/system/usetup/drivesup.h new file mode 100644 index 0000000..f2ef4de --- /dev/null +++ b/subsys/system/usetup/drivesup.h @@ -0,0 +1,37 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/drivesup.h + * PURPOSE: Drive support functions + * PROGRAMMER: Eric Kohl + */ + +#ifndef __DRIVESUP_H__ +#define __DRIVESUP_H__ + +NTSTATUS +GetSourcePaths(PUNICODE_STRING SourcePath, + PUNICODE_STRING SourceRootPath); + + +#endif /* __DRIVESUP_H__ */ + +/* EOF */ \ No newline at end of file diff --git a/subsys/system/usetup/makefile b/subsys/system/usetup/makefile new file mode 100644 index 0000000..06f4540 --- /dev/null +++ b/subsys/system/usetup/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = native + +TARGET_NAME = usetup + +TARGET_INSTALLDIR = system32 + +TARGET_CFLAGS = -D__NTAPP__ + +TARGET_OBJECTS = $(TARGET_NAME).o console.o drivesup.o partlist.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF \ No newline at end of file diff --git a/subsys/system/usetup/partlist.c b/subsys/system/usetup/partlist.c new file mode 100644 index 0000000..d00867f --- /dev/null +++ b/subsys/system/usetup/partlist.c @@ -0,0 +1,693 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/partlist.c + * PURPOSE: Partition list functions + * PROGRAMMER: Eric Kohl + */ + +#include +#include + +#include + +#include + +#include "usetup.h" +#include "console.h" +#include "partlist.h" + + +/* FUNCTIONS ****************************************************************/ + +PPARTLIST +CreatePartitionList(SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom) +{ + PPARTLIST List; + OBJECT_ATTRIBUTES ObjectAttributes; + SYSTEM_DEVICE_INFORMATION Sdi; + DISK_GEOMETRY DiskGeometry; + ULONG ReturnSize; + NTSTATUS Status; + ULONG DiskCount; + IO_STATUS_BLOCK Iosb; + WCHAR Buffer[MAX_PATH]; + UNICODE_STRING Name; + HANDLE FileHandle; + DRIVE_LAYOUT_INFORMATION *LayoutBuffer; + SCSI_ADDRESS ScsiAddress; + ULONG i; + + List = (PPARTLIST)RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTLIST)); + if (List == NULL) + return(NULL); + + List->Left = Left; + List->Top = Top; + List->Right = Right; + List->Bottom = Bottom; + + List->Line = 0; + + List->TopDisk = (ULONG)-1; + List->TopPartition = (ULONG)-1; + + List->CurrentDisk = (ULONG)-1; + List->CurrentPartition = (ULONG)-1; + + List->DiskCount = 0; + List->DiskArray = NULL; + + + Status = NtQuerySystemInformation(SystemDeviceInformation, + &Sdi, + sizeof(SYSTEM_DEVICE_INFORMATION), + &ReturnSize); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(ProcessHeap, 0, List); + return(NULL); + } + + List->DiskArray = (PDISKENTRY)RtlAllocateHeap(ProcessHeap, + 0, + Sdi.NumberOfDisks * sizeof(DISKENTRY)); + List->DiskCount = Sdi.NumberOfDisks; + + for (DiskCount = 0; DiskCount < Sdi.NumberOfDisks; DiskCount++) + { + swprintf(Buffer, + L"\\Device\\Harddisk%d\\Partition0", + DiskCount); + RtlInitUnicodeString(&Name, + Buffer); + + InitializeObjectAttributes(&ObjectAttributes, + &Name, + 0, + NULL, + NULL); + + Status = NtOpenFile(&FileHandle, + 0x10001, + &ObjectAttributes, + &Iosb, + 1, + FILE_SYNCHRONOUS_IO_NONALERT); + if (NT_SUCCESS(Status)) + { + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &DiskGeometry, + sizeof(DISK_GEOMETRY)); + if (NT_SUCCESS(Status)) + { + if (DiskGeometry.MediaType == FixedMedia) + { + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_SCSI_GET_ADDRESS, + NULL, + 0, + &ScsiAddress, + sizeof(SCSI_ADDRESS)); + + + List->DiskArray[DiskCount].DiskSize = + DiskGeometry.Cylinders.QuadPart * + (ULONGLONG)DiskGeometry.TracksPerCylinder * + (ULONGLONG)DiskGeometry.SectorsPerTrack * + (ULONGLONG)DiskGeometry.BytesPerSector; + List->DiskArray[DiskCount].DiskNumber = DiskCount; + List->DiskArray[DiskCount].Port = ScsiAddress.PortNumber; + List->DiskArray[DiskCount].Bus = ScsiAddress.PathId; + List->DiskArray[DiskCount].Id = ScsiAddress.TargetId; + + List->DiskArray[DiskCount].FixedDisk = TRUE; + + + LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap(ProcessHeap, 0, 8192); + + Status = NtDeviceIoControlFile(FileHandle, + NULL, + NULL, + NULL, + &Iosb, + IOCTL_DISK_GET_DRIVE_LAYOUT, + NULL, + 0, + LayoutBuffer, + 8192); + if (NT_SUCCESS(Status)) + { + + List->DiskArray[DiskCount].PartArray = (PPARTENTRY)RtlAllocateHeap(ProcessHeap, + 0, + LayoutBuffer->PartitionCount * sizeof(PARTENTRY)); + List->DiskArray[DiskCount].PartCount = LayoutBuffer->PartitionCount; + + for (i = 0; i < LayoutBuffer->PartitionCount; i++) + { + if ((LayoutBuffer->PartitionEntry[i].PartitionType != PARTITION_ENTRY_UNUSED) && + !IsContainerPartition(LayoutBuffer->PartitionEntry[i].PartitionType)) + { + List->DiskArray[DiskCount].PartArray[i].PartSize = LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart; + List->DiskArray[DiskCount].PartArray[i].PartNumber = LayoutBuffer->PartitionEntry[i].PartitionNumber, + List->DiskArray[DiskCount].PartArray[i].PartType = LayoutBuffer->PartitionEntry[i].PartitionType; + List->DiskArray[DiskCount].PartArray[i].Used = TRUE; + } + else + { + List->DiskArray[DiskCount].PartArray[i].Used = FALSE; + } + } + } + + RtlFreeHeap(ProcessHeap, 0, LayoutBuffer); + } + else + { + /* mark removable disk entry */ + List->DiskArray[DiskCount].FixedDisk = FALSE; + List->DiskArray[DiskCount].PartCount = 0; + List->DiskArray[DiskCount].PartArray = NULL; + } + } + + NtClose(FileHandle); + } + } + + List->TopDisk = 0; + List->TopPartition = 0; + + /* FIXME: search for first usable disk and partition */ + List->CurrentDisk = 0; + List->CurrentPartition = 0; + + DrawPartitionList(List); + + return(List); +} + + +VOID +DestroyPartitionList(PPARTLIST List) +{ + ULONG i; +#if 0 + COORD coPos; + USHORT Width; + + /* clear occupied screen area */ + coPos.X = List->Left; + Width = List->Right - List->Left + 1; + for (coPos.Y = List->Top; coPos.Y <= List->Bottom; coPos.Y++) + { + FillConsoleOutputAttribute(0x17, + Width, + coPos, + &i); + + FillConsoleOutputCharacter(' ', + Width, + coPos, + &i); + } +#endif + + /* free disk and partition info */ + if (List->DiskArray != NULL) + { + /* free partition arrays */ + for (i = 0; i < List->DiskCount; i++) + { + if (List->DiskArray[i].PartArray != NULL) + { + RtlFreeHeap(ProcessHeap, 0, List->DiskArray[i].PartArray); + List->DiskArray[i].PartCount = 0; + List->DiskArray[i].PartArray = NULL; + } + } + + /* free disk array */ + RtlFreeHeap(ProcessHeap, 0, List->DiskArray); + List->DiskCount = 0; + List->DiskArray = NULL; + } + + /* free list head */ + RtlFreeHeap(ProcessHeap, 0, List); +} + + +static VOID +PrintEmptyLine(PPARTLIST List) +{ + COORD coPos; + ULONG Written; + USHORT Width; + USHORT Height; + + Width = List->Right - List->Left - 1; + Height = List->Bottom - List->Top - 1; + + if (List->Line < 0 || List->Line > Height) + return; + + coPos.X = List->Left + 1; + coPos.Y = List->Top + 1 + List->Line; + + FillConsoleOutputAttribute(0x17, + Width, + coPos, + &Written); + + FillConsoleOutputCharacter(' ', + Width, + coPos, + &Written); + + List->Line++; +} + + +static VOID +PrintPartitionData(PPARTLIST List, + SHORT DiskIndex, + SHORT PartIndex) +{ + PPARTENTRY PartEntry; + CHAR LineBuffer[128]; + COORD coPos; + ULONG Written; + USHORT Width; + USHORT Height; + + ULONGLONG PartSize; + PCHAR Unit; + PCHAR PartType; + UCHAR Attribute; + + + Width = List->Right - List->Left - 1; + Height = List->Bottom - List->Top - 1; + + if (List->Line < 0 || List->Line > Height) + return; + + coPos.X = List->Left + 1; + coPos.Y = List->Top + 1 + List->Line; + + PartEntry = &List->DiskArray[DiskIndex].PartArray[PartIndex]; + + if ((PartEntry->PartType == PARTITION_FAT_12) || + (PartEntry->PartType == PARTITION_FAT_16) || + (PartEntry->PartType == PARTITION_HUGE) || + (PartEntry->PartType == PARTITION_XINT13)) + { + PartType = "FAT"; + } + else if ((PartEntry->PartType == PARTITION_FAT32) || + (PartEntry->PartType == PARTITION_FAT32_XINT13)) + { + PartType = "FAT32"; + } + else if (PartEntry->PartType == PARTITION_IFS) + { + PartType = "NTFS"; /* FIXME: Not quite correct! */ + } + else + { + PartType = "Unknown"; + } + + if (PartEntry->PartSize >= 0x280000000ULL) /* 10 GB */ + { + PartSize = (PartEntry->PartSize + (1 << 29)) >> 30; + Unit = "GB"; + } + else if (PartEntry->PartSize >= 0xA00000ULL) /* 10 MB */ + { + PartSize = (PartEntry->PartSize + (1 << 19)) >> 20; + Unit = "MB"; + } + else + { + PartSize = (PartEntry->PartSize + (1 << 9)) >> 10; + Unit = "kB"; + } + + sprintf(LineBuffer, + "%d: nr: %d type: %x (%s) %I64u %s", + PartIndex, + PartEntry->PartNumber, + PartEntry->PartType, + PartType, + PartSize, + Unit); + + + Attribute = (List->CurrentDisk == DiskIndex && + List->CurrentPartition == PartIndex) ? 0x71 : 0x17; + + FillConsoleOutputCharacter(' ', + Width, + coPos, + &Written); + + coPos.X += 4; + Width -= 8; + FillConsoleOutputAttribute(Attribute, + Width, + coPos, + &Written); + + coPos.X++; + Width -= 2; + WriteConsoleOutputCharacters(LineBuffer, + min(strlen(LineBuffer), Width), + coPos); + + List->Line++; +} + + +static VOID +PrintDiskData(PPARTLIST List, + SHORT DiskIndex) +{ + PDISKENTRY DiskEntry; + CHAR LineBuffer[128]; + COORD coPos; + ULONG Written; + USHORT Width; + USHORT Height; + ULONGLONG DiskSize; + PCHAR Unit; + SHORT PartIndex; + BOOL PartPrinted; + + DiskEntry = &List->DiskArray[DiskIndex]; + + Width = List->Right - List->Left - 1; + Height = List->Bottom - List->Top - 1; + + if (List->Line < 0 || List->Line > Height) + return; + + coPos.X = List->Left + 1; + coPos.Y = List->Top + 1 + List->Line; + + if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */ + { + DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30; + Unit = "GB"; + } + else if (DiskEntry->DiskSize >= 0xA00000ULL) /* 10 MB */ + { + DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20; + Unit = "MB"; + } + else + { + DiskSize = (DiskEntry->DiskSize + (1 << 9)) >> 10; + Unit = "kB"; + } + + sprintf(LineBuffer, + "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)", + DiskSize, + Unit, + DiskEntry->DiskNumber, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id); + + FillConsoleOutputAttribute(0x17, + Width, + coPos, + &Written); + + FillConsoleOutputCharacter(' ', + Width, + coPos, + &Written); + + coPos.X++; + WriteConsoleOutputCharacters(LineBuffer, + min(strlen(LineBuffer), Width - 2), + coPos); + + List->Line++; + + /* Print separator line */ + PrintEmptyLine(List); + + + PartPrinted = FALSE; + + /* Print partition lines*/ + for (PartIndex = 0; PartIndex < List->DiskArray[DiskIndex].PartCount; PartIndex++) + { + if (List->DiskArray[DiskIndex].PartArray[PartIndex].Used == TRUE) + { + PrintPartitionData(List, + DiskIndex, + PartIndex); + PartPrinted = TRUE; + } + } + + /* Print separator line */ + if (PartPrinted == TRUE) + { + PrintEmptyLine(List); + } +} + + +VOID +DrawPartitionList(PPARTLIST List) +{ + CHAR LineBuffer[128]; + COORD coPos; + ULONG Written; + SHORT i; + SHORT DiskIndex; + + /* draw upper left corner */ + coPos.X = List->Left; + coPos.Y = List->Top; + FillConsoleOutputCharacter(0xDA, // '+', + 1, + coPos, + &Written); + + /* draw upper edge */ + coPos.X = List->Left + 1; + coPos.Y = List->Top; + FillConsoleOutputCharacter(0xC4, // '-', + List->Right - List->Left - 1, + coPos, + &Written); + + /* draw upper right corner */ + coPos.X = List->Right; + coPos.Y = List->Top; + FillConsoleOutputCharacter(0xBF, // '+', + 1, + coPos, + &Written); + + /* draw left and right edge */ + for (i = List->Top + 1; i < List->Bottom; i++) + { + coPos.X = List->Left; + coPos.Y = i; + FillConsoleOutputCharacter(0xB3, // '|', + 1, + coPos, + &Written); + + coPos.X = List->Right; + FillConsoleOutputCharacter(0xB3, //'|', + 1, + coPos, + &Written); + } + + /* draw lower left corner */ + coPos.X = List->Left; + coPos.Y = List->Bottom; + FillConsoleOutputCharacter(0xC0, // '+', + 1, + coPos, + &Written); + + /* draw lower edge */ + coPos.X = List->Left + 1; + coPos.Y = List->Bottom; + FillConsoleOutputCharacter(0xC4, // '-', + List->Right - List->Left - 1, + coPos, + &Written); + + /* draw upper right corner */ + coPos.X = List->Right; + coPos.Y = List->Bottom; + FillConsoleOutputCharacter(0xD9, // '+', + 1, + coPos, + &Written); + + /* print list entries */ + List->Line = 0; + for (DiskIndex = 0; DiskIndex < List->DiskCount; DiskIndex++) + { + if (List->DiskArray[DiskIndex].FixedDisk == TRUE) + { + /* Print disk entry */ + PrintDiskData(List, + DiskIndex); + } + } +} + + +VOID +ScrollDownPartitionList(PPARTLIST List) +{ + ULONG i; + ULONG j; + + /* check for available disks */ + if (List->DiskCount == 0) + return; + + /* check for next usable entry on current disk */ + for (i = List->CurrentPartition + 1; i < List->DiskArray[List->CurrentDisk].PartCount; i++) + { + if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE) + { + List->CurrentPartition = i; + DrawPartitionList(List); + return; + } + } + + /* check for first usable entry on next disk */ + for (j = List->CurrentDisk + 1; j < List->DiskCount; j++) + { + for (i = 0; i < List->DiskArray[j].PartCount; i++) + { + if (List->DiskArray[j].PartArray[i].Used == TRUE) + { + List->CurrentDisk = j; + List->CurrentPartition = i; + DrawPartitionList(List); + return; + } + } + } +} + + +VOID +ScrollUpPartitionList(PPARTLIST List) +{ + ULONG i; + ULONG j; + + /* check for available disks */ + if (List->DiskCount == 0) + return; + + /* check for previous usable entry on current disk */ + for (i = List->CurrentPartition - 1; i != (ULONG)-1; i--) + { + if (List->DiskArray[List->CurrentDisk].PartArray[i].Used == TRUE) + { + List->CurrentPartition = i; + DrawPartitionList(List); + return; + } + } + + /* check for last usable entry on previous disk */ + for (j = List->CurrentDisk - 1; j != (ULONG)-1; j--) + { + for (i = List->DiskArray[j].PartCount - 1; i != (ULONG)-1; i--) + { + if (List->DiskArray[j].PartArray[i].Used == TRUE) + { + List->CurrentDisk = j; + List->CurrentPartition = i; + DrawPartitionList(List); + return; + } + } + } +} + + +BOOL +GetPartitionData(PPARTLIST List, + PPARTDATA Data) +{ + if (List->CurrentDisk >= List->DiskCount) + return(FALSE); + + if (List->DiskArray[List->CurrentDisk].FixedDisk == FALSE) + return(FALSE); + + if (List->CurrentPartition >= List->DiskArray[List->CurrentDisk].PartCount) + return(FALSE); + + if (List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].Used == FALSE) + return(FALSE); + + Data->DiskSize = List->DiskArray[List->CurrentDisk].DiskSize; + Data->DiskNumber = List->DiskArray[List->CurrentDisk].DiskNumber; + Data->Port = List->DiskArray[List->CurrentDisk].Port; + Data->Bus = List->DiskArray[List->CurrentDisk].Bus; + Data->Id = List->DiskArray[List->CurrentDisk].Id; + + Data->PartSize = List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].PartSize; + Data->PartNumber = List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].PartNumber; + Data->PartType = List->DiskArray[List->CurrentDisk].PartArray[List->CurrentPartition].PartType; + + return(TRUE); +} + +/* EOF */ diff --git a/subsys/system/usetup/partlist.h b/subsys/system/usetup/partlist.h new file mode 100644 index 0000000..28bf5c1 --- /dev/null +++ b/subsys/system/usetup/partlist.h @@ -0,0 +1,113 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/partlist.h + * PURPOSE: Partition list functions + * PROGRAMMER: Eric Kohl + */ + +#ifndef __PARTLIST_H__ +#define __PARTLIST_H__ + +typedef struct _PARTDATA +{ + ULONGLONG DiskSize; + ULONG DiskNumber; + USHORT Port; + USHORT Bus; + USHORT Id; + ULONGLONG PartSize; + ULONG PartNumber; + ULONG PartType; +} PARTDATA, *PPARTDATA; + + +typedef struct _PARTENTRY +{ + ULONGLONG PartSize; + ULONG PartNumber; + ULONG PartType; + CHAR DriveLetter; + BOOL Used; +} PARTENTRY, *PPARTENTRY; + +typedef struct _DISKENTRY +{ + ULONGLONG DiskSize; + ULONG DiskNumber; + USHORT Port; + USHORT Bus; + USHORT Id; + BOOL FixedDisk; + + ULONG PartCount; + PPARTENTRY PartArray; + +} DISKENTRY, *PDISKENTRY; + + +typedef struct _PARTLIST +{ + SHORT Left; + SHORT Top; + SHORT Right; + SHORT Bottom; + + SHORT Line; + + ULONG TopDisk; + ULONG TopPartition; + + ULONG CurrentDisk; + ULONG CurrentPartition; + + ULONG DiskCount; + PDISKENTRY DiskArray; + +} PARTLIST, *PPARTLIST; + + + + +PPARTLIST +CreatePartitionList(SHORT Left, + SHORT Top, + SHORT Right, + SHORT Bottom); + +VOID +DestroyPartitionList(PPARTLIST List); + +VOID +DrawPartitionList(PPARTLIST List); + +VOID +ScrollDownPartitionList(PPARTLIST List); + +VOID +ScrollUpPartitionList(PPARTLIST List); + +BOOL +GetPartitionData(PPARTLIST List, PPARTDATA Data); + +#endif /* __PARTLIST_H__ */ + +/* EOF */ \ No newline at end of file diff --git a/subsys/system/usetup/usetup.c b/subsys/system/usetup/usetup.c new file mode 100644 index 0000000..1704d6e --- /dev/null +++ b/subsys/system/usetup/usetup.c @@ -0,0 +1,1146 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/usetup.c + * PURPOSE: Text-mode setup + * PROGRAMMER: Eric Kohl + */ + +#include +#include + +#include "usetup.h" +#include "console.h" +#include "partlist.h" + + + +#define START_PAGE 0 +#define INTRO_PAGE 1 +#define INSTALL_INTRO_PAGE 2 + +#define SELECT_PARTITION_PAGE 4 +#define SELECT_FILE_SYSTEM_PAGE 5 +#define CHECK_FILE_SYSTEM_PAGE 6 +#define PREPARE_COPY_PAGE 7 +#define INSTALL_DIRECTORY_PAGE 8 +#define FILE_COPY_PAGE 9 +#define INIT_SYSTEM_PAGE 10 + +#define REPAIR_INTRO_PAGE 20 + +#define SUCCESS_PAGE 100 +#define QUIT_PAGE 101 +#define REBOOT_PAGE 102 + + +/* GLOBALS ******************************************************************/ + +HANDLE ProcessHeap; + +BOOL PartDataValid = FALSE; +PARTDATA PartData; + +CHAR InstallDir[51]; + +UNICODE_STRING SourcePath; +UNICODE_STRING SourceRootPath; + + +/* FUNCTIONS ****************************************************************/ + +static VOID +PrintString(char* fmt,...) +{ + char buffer[512]; + va_list ap; + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + RtlInitAnsiString(&AnsiString, buffer); + RtlAnsiStringToUnicodeString(&UnicodeString, + &AnsiString, + TRUE); + NtDisplayString(&UnicodeString); + RtlFreeUnicodeString(&UnicodeString); +} + + +/* + * Confirm quit setup + * RETURNS + * TRUE: Quit setup. + * FALSE: Don't quit setup. + */ +static BOOL +ConfirmQuit(PINPUT_RECORD Ir) +{ + SHORT xScreen; + SHORT yScreen; + SHORT yTop; + SHORT xLeft; + BOOL Result = FALSE; + PUSHORT pAttributes = NULL; + PUCHAR pCharacters = NULL; + COORD Pos; + + GetScreenSize(&xScreen, &yScreen); + yTop = (yScreen - 10) / 2; + xLeft = (xScreen - 52) / 2; + + /* Save screen */ +#if 0 + Pos.X = 0; + Pos.Y = 0; + pAttributes = (PUSHORT)RtlAllocateHeap(ProcessHeap, + 0, + xScreen * yScreen * sizeof(USHORT)); +CHECKPOINT1; +DPRINT1("pAttributes %p\n", pAttributes); + ReadConsoleOutputAttributes(pAttributes, + xScreen * yScreen, + Pos, + NULL); +CHECKPOINT1; + pCharacters = (PUCHAR)RtlAllocateHeap(ProcessHeap, + 0, + xScreen * yScreen * sizeof(UCHAR)); +CHECKPOINT1; + ReadConsoleOutputCharacters(pCharacters, + xScreen * yScreen, + Pos, + NULL); +CHECKPOINT1; +#endif + + /* Draw popup window */ + SetTextXY(xLeft, yTop, + "+----------------------------------------------------+"); + SetTextXY(xLeft, yTop + 1, + "| ReactOS 0.0.20 is not completely installed on your |"); + SetTextXY(xLeft, yTop + 2, + "| computer. If you quit Setup now, you will need to |"); + SetTextXY(xLeft, yTop + 3, + "| run Setup again to install ReactOS. |"); + SetTextXY(xLeft, yTop + 4, + "| |"); + SetTextXY(xLeft, yTop + 5, + "| * Press ENTER to continue Setup. |"); + SetTextXY(xLeft, yTop + 6, + "| * Press F3 to quit Setup. |"); + SetTextXY(xLeft, yTop + 7, + "+----------------------------------------------------+"); + SetTextXY(xLeft, yTop + 8, + "| F3= Quit ENTER = Continue |"); + SetTextXY(xLeft, yTop + 9, + "+----------------------------------------------------+"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + Result = TRUE; + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + Result = FALSE; + break; + } + } + + /* Restore screen */ +#if 0 +CHECKPOINT1; + WriteConsoleOutputAttributes(pAttributes, + xScreen * yScreen, + Pos, + NULL); +CHECKPOINT1; + + WriteConsoleOutputCharacters(pCharacters, + xScreen * yScreen, + Pos); +CHECKPOINT1; + + RtlFreeHeap(ProcessHeap, + 0, + pAttributes); + RtlFreeHeap(ProcessHeap, + 0, + pCharacters); +#endif + + return(Result); +} + + + + +/* + * First setup page + * RETURNS + * TRUE: setup/repair completed successfully + * FALSE: setup/repair terminated by user + */ +static ULONG +StartPage(PINPUT_RECORD Ir) +{ + NTSTATUS Status; + + SetStatusText(" Please wait..."); + + Status = GetSourcePaths(&SourcePath, + &SourceRootPath); + if (!NT_SUCCESS(Status)) + { + PrintTextXY(6, 15, "GetSourcePath() failed (Status 0x%08lx)", Status); + } + else + { + PrintTextXY(6, 15, "SourcePath: '%wZ'", &SourcePath); + PrintTextXY(6, 16, "SourceRootPath: '%wZ'", &SourceRootPath); + } + + /* + * FIXME: Open and load txtsetup.sif here. A pointer (or handle) to the + * ini data should be stored in a global variable. + * The full path to txtsetup.sif is created by appending '\txtsetup.sif' + * to the unicode string SourceRootPath. + */ + + SetStatusText(" ENTER = Continue"); + + while(TRUE) + { + ConInKey(Ir); + + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return(INTRO_PAGE); + } + } + + return(START_PAGE); +} + + + +static ULONG +RepairIntroPage(PINPUT_RECORD Ir) +{ + SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet"); + SetTextXY(6, 9, "support all the functions of a fully usable setup application."); + + SetTextXY(6, 12, "The repair functions are not implemented yet."); + + SetTextXY(8, 15, "\xf9 Press ESC to return to the main page."); + + SetTextXY(8, 17, "\xf9 Press ENTER to reboot your computer."); + + SetStatusText(" ESC = Main page ENTER = Reboot"); + + while(TRUE) + { + ConInKey(Ir); + + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return(REBOOT_PAGE); + } + else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ + { + return(INTRO_PAGE); + } + } + + return(REPAIR_INTRO_PAGE); +} + + +/* + * First setup page + * RETURNS + * TRUE: setup/repair completed successfully + * FALSE: setup/repair terminated by user + */ +static ULONG +IntroPage(PINPUT_RECORD Ir) +{ + SetHighlightedTextXY(6, 8, "Welcome to ReactOS Setup"); + + SetTextXY(6, 11, "This part of the setup copies the ReactOS Operating System to your"); + SetTextXY(6, 12, "computer and prepares the second part of the setup."); + + SetTextXY(8, 15, "\xf9 Press ENTER to install ReactOS."); + + SetTextXY(8, 17, "\xf9 Press R to repair ReactOS."); + + SetTextXY(8, 19, "\xf9 Press F3 to quit without installing ReactOS."); + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return(INSTALL_INTRO_PAGE); + } + else if (toupper(Ir->Event.KeyEvent.uChar.AsciiChar) == 'R') /* R */ + { + return(REPAIR_INTRO_PAGE); + } + } + + return(INTRO_PAGE); +} + + +static ULONG +InstallIntroPage(PINPUT_RECORD Ir) +{ + SetTextXY(6, 8, "ReactOS Setup is in an early development phase. It does not yet"); + SetTextXY(6, 9, "support all the functions of a fully usable setup application."); + + SetTextXY(6, 12, "The following functions are missing:"); + SetTextXY(8, 13, "- Creating and deleting harddisk partitions."); + SetTextXY(8, 14, "- Formatting partitions."); + SetTextXY(8, 15, "- Support for non-FAT file systems."); + SetTextXY(8, 16, "- Checking file systems."); + SetTextXY(8, 17, "- Installing the bootloader."); + + + + SetTextXY(8, 21, "\xf9 Press ENTER to install ReactOS."); + + SetTextXY(8, 23, "\xf9 Press F3 to quit without installing ReactOS."); + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + return(SELECT_PARTITION_PAGE); + } + } + + return(INSTALL_INTRO_PAGE); +} + + +static ULONG +SelectPartitionPage(PINPUT_RECORD Ir) +{ + PPARTLIST PartList; + SHORT xScreen; + SHORT yScreen; + + SetTextXY(6, 8, "The list below shows existing partitions and unused disk"); + SetTextXY(6, 9, "space for new partitions."); + + SetTextXY(8, 11, "\xf9 Press UP or DOWN to select a list entry."); + SetTextXY(8, 13, "\xf9 Press ENTER to install ReactOS onto the selected partition."); + SetTextXY(8, 15, "\xf9 Press C to create a new partition."); + SetTextXY(8, 17, "\xf9 Press D to delete an existing partition."); + + SetStatusText(" Please wait..."); + + GetScreenSize(&xScreen, &yScreen); + + PartList = CreatePartitionList(2, 19, xScreen - 3, yScreen - 3); + if (PartList == NULL) + { + /* FIXME: show an error dialog */ + return(QUIT_PAGE); + } + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) + { + if (ConfirmQuit(Ir) == TRUE) + { + DestroyPartitionList(PartList); + return(QUIT_PAGE); + } + break; + } + else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_DOWN)) + { + ScrollDownPartitionList(PartList); + } + else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_UP)) + { + ScrollUpPartitionList(PartList); + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + PartDataValid = GetPartitionData(PartList, &PartData); + DestroyPartitionList(PartList); + return(SELECT_FILE_SYSTEM_PAGE); + } + + /* FIXME: Update status text */ + + } + + DestroyPartitionList(PartList); + + return(SELECT_PARTITION_PAGE); +} + + +static ULONG +SelectFileSystemPage(PINPUT_RECORD Ir) +{ + ULONGLONG DiskSize; + ULONGLONG PartSize; + PCHAR DiskUnit; + PCHAR PartUnit; + PCHAR PartType; + + if (PartDataValid == FALSE) + { + /* FIXME: show an error dialog */ + return(QUIT_PAGE); + } + + /* adjust disk size */ + if (PartData.DiskSize >= 0x280000000ULL) /* 10 GB */ + { + DiskSize = (PartData.DiskSize + (1 << 29)) >> 30; + DiskUnit = "GB"; + } + else + { + DiskSize = (PartData.DiskSize + (1 << 19)) >> 20; + DiskUnit = "MB"; + } + + /* adjust partition size */ + if (PartData.PartSize >= 0x280000000ULL) /* 10 GB */ + { + PartSize = (PartData.PartSize + (1 << 29)) >> 30; + PartUnit = "GB"; + } + else + { + PartSize = (PartData.PartSize + (1 << 19)) >> 20; + PartUnit = "MB"; + } + + /* adjust partition type */ + if ((PartData.PartType == PARTITION_FAT_12) || + (PartData.PartType == PARTITION_FAT_16) || + (PartData.PartType == PARTITION_HUGE) || + (PartData.PartType == PARTITION_XINT13)) + { + PartType = "FAT"; + } + else if ((PartData.PartType == PARTITION_FAT32) || + (PartData.PartType == PARTITION_FAT32_XINT13)) + { + PartType = "FAT32"; + } + else if (PartData.PartType == PARTITION_IFS) + { + PartType = "NTFS"; /* FIXME: Not quite correct! */ + } + else + { + PartType = "Unknown"; + } + + SetTextXY(6, 8, "ReactOS will be installed"); + + PrintTextXY(8, 9, "on Harddisk %lu (%I64u %s), Port=%hu, Bus=%hu, Id=%hu.", + PartData.DiskNumber, + DiskSize, + DiskUnit, + PartData.Port, + PartData.Bus, + PartData.Id); + + PrintTextXY(8, 10, "on Partition %lu (%I64u %s) %s", + PartData.PartNumber, + PartSize, + PartUnit, + PartType); + + SetTextXY(6, 13, "Select a file system for the partition from the list below."); + + SetTextXY(8, 15, "\xf9 Press UP or DOWN to select a file system."); + SetTextXY(8, 17, "\xf9 Press ENTER to format the partition."); + SetTextXY(8, 19, "\xf9 Press ESC to select another partition."); + + /* FIXME: use a real list later */ + SetInvertedTextXY(6, 22, " Keep current file system (no changes) "); + + + SetStatusText(" ENTER = Continue ESC = Cancel F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)) /* ESC */ + { + return(SELECT_PARTITION_PAGE); + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return(CHECK_FILE_SYSTEM_PAGE); + } + } + + return(SELECT_FILE_SYSTEM_PAGE); +} + + +static ULONG +CheckFileSystemPage(PINPUT_RECORD Ir) +{ + SetTextXY(6, 8, "Check file system"); + + SetTextXY(6, 10, "At present, ReactOS can not check file systems."); + + SetStatusText(" Please wait ..."); + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return(INSTALL_DIRECTORY_PAGE); + } + } + + return(CHECK_FILE_SYSTEM_PAGE); +} + + +static ULONG +InstallDirectoryPage(PINPUT_RECORD Ir) +{ + ULONG Length; + + SetTextXY(6, 8, "Setup installs ReactOS files onto the selected partition. Choose a"); + SetTextXY(6, 9, "directory where you want ReactOS to be installed:"); + + strcpy(InstallDir, "\\reactos"); + Length = strlen(InstallDir); + + SetInputTextXY(8, 11, 51, InstallDir); + + SetTextXY(6, 14, "To change the suggested directory, press BACKSPACE to delete"); + SetTextXY(6, 15, "characters and then type the directory where you want ReactOS to"); + SetTextXY(6, 16, "be installed."); + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) /* ENTER */ + { + return(PREPARE_COPY_PAGE); + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x08) /* BACKSPACE */ + { + if (Length > 0) + { + Length--; + InstallDir[Length] = 0; + SetInputTextXY(8, 11, 51, InstallDir); + } + } + else if (isprint(Ir->Event.KeyEvent.uChar.AsciiChar)) + { + if (Length < 50) + { + InstallDir[Length] = Ir->Event.KeyEvent.uChar.AsciiChar; + Length++; + InstallDir[Length] = 0; + SetInputTextXY(8, 11, 51, InstallDir); + } + } + } + + return(INSTALL_DIRECTORY_PAGE); +} + + +static ULONG +PrepareCopyPage(PINPUT_RECORD Ir) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + CHAR PathBuffer[MAX_PATH]; + UNICODE_STRING PathName; + HANDLE DirectoryHandle; + NTSTATUS Status; + PCHAR End; + ULONG Length; + ULONG i; + + PCHAR Dirs[]= { + "System32", + "System32\\Config", + "System32\\Drivers", + "Inf", + "Help", + "Fonts", + NULL}; + + SetTextXY(6, 8, "Setup prepares your computer for copying the ReactOS files. "); + + + SetTextXY(8, 12, "Build file copy list"); + + SetTextXY(8, 14, "Create directories"); + + SetStatusText(" Please wait..."); + + + /* build the file copy list */ + + SetInvertedTextXY(8, 12, "Build file copy list"); + + /* FIXME: build that list */ + + SetTextXY(8, 12, "Build file copy list"); + SetHighlightedTextXY(50, 12, "Done"); + + + /* create directories */ + SetInvertedTextXY(8, 14, "Create directories"); + + + /* + * FIXME: Enumerate the ini section 'Directories' and create all "relative" directories + */ + + + /* create the systemroot directory */ + sprintf(PathBuffer, + "\\Device\\Harddisk%lu\\Partition%lu", + PartData.DiskNumber, + PartData.PartNumber); + if (InstallDir[0] != '\\') + strcat(PathBuffer, "\\"); + strcat(PathBuffer, InstallDir); + + /* remove trailing backslash */ + Length = strlen(PathBuffer); + if ((Length > 0) && (PathBuffer[Length - 1] == '\\')) + PathBuffer[Length - 1] = 0; + + RtlCreateUnicodeStringFromAsciiz(&PathName, + PathBuffer); + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &PathName; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + Status = NtCreateFile(&DirectoryHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_DIRECTORY, + 0, + FILE_CREATE, + FILE_DIRECTORY_FILE, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status); + + } + else + { + PrintTextXY(6, 25, "Created directory."); + NtClose (DirectoryHandle); + } + + + RtlFreeUnicodeString(&PathName); + + + /* create the subdirectories */ + + /* append backslash and init end pointer */ + strcat(PathBuffer, "\\"); + Length = strlen(PathBuffer); + End = &PathBuffer[Length]; + + for (i = 0; Dirs[i] != NULL; i++) + { + strcpy(End, Dirs[i]); + + + RtlCreateUnicodeStringFromAsciiz(&PathName, + PathBuffer); + + + ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); + ObjectAttributes.RootDirectory = NULL; + ObjectAttributes.ObjectName = &PathName; + ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE | OBJ_INHERIT; + ObjectAttributes.SecurityDescriptor = NULL; + ObjectAttributes.SecurityQualityOfService = NULL; + + Status = NtCreateFile(&DirectoryHandle, + DIRECTORY_ALL_ACCESS, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_DIRECTORY, + 0, + FILE_CREATE, + FILE_DIRECTORY_FILE, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + PrintTextXY(6, 25, "Creating directory failed: Status = 0x%08lx", Status); + } + else + { + PrintTextXY(6, 25, "Created directory."); + NtClose (DirectoryHandle); + } + + RtlFreeUnicodeString(&PathName); + } + + + SetTextXY(8, 14, "Create directories"); + SetHighlightedTextXY(50, 14, "Done"); + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + return(FILE_COPY_PAGE); + } + } + + return(PREPARE_COPY_PAGE); +} + + +static ULONG +FileCopyPage(PINPUT_RECORD Ir) +{ + + SetTextXY(6, 8, "Copying files"); + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) /* F3 */ + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + return(INIT_SYSTEM_PAGE); + } + } + + return(FILE_COPY_PAGE); +} + + +#if 0 +static NTSTATUS +UpdateSystemRootLink(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING LinkName; + UNICODE_STRING TargetName; + CHAR TargetBuffer[MAX_PATH]; + HANDLE Handle; + NTSTATUS Status; + + RtlInitUnicodeString(&LinkName, + L"\\SystemRoot"); + + InitializeObjectAttributes(&ObjectAttributes, + &LinkName, + OBJ_OPENLINK, + NULL, + NULL); + + Status = NtOpenSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return(Status); + + Status = NtMakeTemporaryObject(Handle); + NtClose(Handle); + if (!NT_SUCCESS(Status)) + return(Status); + + sprintf(TargetBuffer, + "\\Device\\Harddisk%lu\\Partition%lu", + PartData.DiskNumber, + PartData.PartNumber); + if (InstallDir[0] != '\\') + strcat(TargetBuffer, "\\"); + strcat(TargetBuffer, InstallDir); + + RtlCreateUnicodeStringFromAsciiz(&TargetName, + TargetBuffer); + + Status = NtCreateSymbolicLinkObject(&Handle, + SYMBOLIC_LINK_ALL_ACCESS, + &ObjectAttributes, + &TargetName); + + RtlFreeUnicodeString(&TargetName); + + if (!NT_SUCCESS(Status)) + return(Status); + + NtClose(Handle); + + return(STATUS_SUCCESS); +} +#endif + + +static ULONG +InitSystemPage(PINPUT_RECORD Ir) +{ +#if 0 + NTSTATUS Status; +#endif + + SetTextXY(6, 8, "Initializing system settings"); + + + SetTextXY(6, 12, "Create registry hives"); + + SetTextXY(6, 14, "Update registry hives"); + + SetTextXY(6, 16, "Install/update boot manager"); + + SetStatusText(" Please wait..."); + +#if 0 + /* + * Initialize registry + */ + + /* Update 'SystemRoot' link */ + Status = UpdateSystemRootLink(); + if (!NT_SUCCESS(Status)) + { + + PrintTextXY(6, 25, "UpdateSystemRootLink() failed (Status = 0x%08lx)", Status); + } + + + Status = NtInitializeRegistry(TRUE); + if (!NT_SUCCESS(Status)) + { + + PrintTextXY(6, 26, "NtInitializeRegistry() failed (Status = 0x%08lx)", Status); + } +#endif + + /* + * Update registry + */ + + /* FIXME: Create key '\Registry\Machine\System\Setup' */ + + /* FIXME: Create value 'SystemSetupInProgress' */ + + + + SetStatusText(" ENTER = Continue F3 = Quit"); + + while(TRUE) + { + ConInKey(Ir); + + if ((Ir->Event.KeyEvent.uChar.AsciiChar == 0x00) && + (Ir->Event.KeyEvent.wVirtualKeyCode == VK_F3)) + { + if (ConfirmQuit(Ir) == TRUE) + return(QUIT_PAGE); + break; + } + else if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + return(SUCCESS_PAGE); + } + } + + return(INIT_SYSTEM_PAGE); +} + + +static ULONG +QuitPage(PINPUT_RECORD Ir) +{ + SetTextXY(10, 6, "ReactOS is not completely installed"); + + SetTextXY(10, 8, "Remove floppy disk from Drive A: and"); + SetTextXY(10, 9, "all CD-ROMs from CD-Drive."); + + SetTextXY(10, 11, "Press ENTER to reboot your computer."); + + SetStatusText(" ENTER = Reboot computer"); + + while(TRUE) + { + ConInKey(Ir); + + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + return(REBOOT_PAGE); + } + } +} + + +static ULONG +SuccessPage(PINPUT_RECORD Ir) +{ + SetTextXY(10, 6, "The basic components of ReactOS have been installed successfully."); + + SetTextXY(10, 8, "Remove floppy disk from Drive A: and"); + SetTextXY(10, 9, "all CD-ROMs from CD-Drive."); + + SetTextXY(10, 11, "Press ENTER to reboot your computer."); + + SetStatusText(" ENTER = Reboot computer"); + + while(TRUE) + { + ConInKey(Ir); + + if (Ir->Event.KeyEvent.uChar.AsciiChar == 0x0D) + { + return(REBOOT_PAGE); + } + } +} + + +VOID STDCALL +NtProcessStartup(PPEB Peb) +{ + NTSTATUS Status; + INPUT_RECORD Ir; + ULONG Page; + + RtlNormalizeProcessParams(Peb->ProcessParameters); + + ProcessHeap = Peb->ProcessHeap; + + Status = AllocConsole(); + if (!NT_SUCCESS(Status)) + { + PrintString("AllocConsole() failed (Status = 0x%08lx)\n", Status); + + /* Raise a hard error (crash the system/BSOD) */ + NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, + 0,0,0,0,0); + } + + Page = START_PAGE; + while (Page != REBOOT_PAGE) + { + ClearScreen(); + + SetUnderlinedTextXY(4, 3, " ReactOS 0.0.20 Setup "); + + switch (Page) + { + /* Start page */ + case START_PAGE: + Page = StartPage(&Ir); + break; + + /* Intro page */ + case INTRO_PAGE: + Page = IntroPage(&Ir); + break; + + /* Install pages */ + case INSTALL_INTRO_PAGE: + Page = InstallIntroPage(&Ir); + break; + +#if 0 + case OEM_DRIVER_PAGE: + Page = OemDriverPage(&Ir); + break; +#endif + +#if 0 + case DEVICE_SETTINGS_PAGE: +#endif + + case SELECT_PARTITION_PAGE: + Page = SelectPartitionPage(&Ir); + break; + + case SELECT_FILE_SYSTEM_PAGE: + Page = SelectFileSystemPage(&Ir); + break; + + case CHECK_FILE_SYSTEM_PAGE: + Page = CheckFileSystemPage(&Ir); + break; + + case INSTALL_DIRECTORY_PAGE: + Page = InstallDirectoryPage(&Ir); + break; + + case PREPARE_COPY_PAGE: + Page = PrepareCopyPage(&Ir); + break; + + case FILE_COPY_PAGE: + Page = FileCopyPage(&Ir); + break; + + case INIT_SYSTEM_PAGE: + Page = InitSystemPage(&Ir); + break; + + + /* Repair pages */ + case REPAIR_INTRO_PAGE: + Page = RepairIntroPage(&Ir); + break; + + + case SUCCESS_PAGE: + Page = SuccessPage(&Ir); + break; + + case QUIT_PAGE: + Page = QuitPage(&Ir); + break; + } + } + + /* Reboot */ + FreeConsole(); + NtShutdownSystem(ShutdownReboot); +} + +/* EOF */ diff --git a/subsys/system/usetup/usetup.h b/subsys/system/usetup/usetup.h new file mode 100644 index 0000000..b4fc855 --- /dev/null +++ b/subsys/system/usetup/usetup.h @@ -0,0 +1,43 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS text-mode setup + * FILE: subsys/system/usetup/usetup.h + * PURPOSE: Text-mode setup + * PROGRAMMER: Eric Kohl + */ + +#ifndef __USETUP_H__ +#define __USETUP_H__ + + +#define DPRINT1(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0); +#define CHECKPOINT1 do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0); + +#define DPRINT(args...) +#define CHECKPOINT + + +extern HANDLE ProcessHeap; + + +#endif /* __USETUP_H__*/ + +/* EOF */ diff --git a/subsys/system/usetup/usetup.rc b/subsys/system/usetup/usetup.rc new file mode 100644 index 0000000..0ff6817 --- /dev/null +++ b/subsys/system/usetup/usetup.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Setup\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "usetup\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "usetup.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/system/winlogon/.cvsignore b/subsys/system/winlogon/.cvsignore new file mode 100644 index 0000000..1ad6ca8 --- /dev/null +++ b/subsys/system/winlogon/.cvsignore @@ -0,0 +1,6 @@ +winlogon.coff +winlogon.exe +winlogon.nostrip.exe +*.d +*.o +*.sym diff --git a/subsys/system/winlogon/makefile b/subsys/system/winlogon/makefile new file mode 100644 index 0000000..031b6c4 --- /dev/null +++ b/subsys/system/winlogon/makefile @@ -0,0 +1,21 @@ +# $Id$ + +PATH_TO_TOP = ../../.. + +TARGET_TYPE = program + +TARGET_APPTYPE = console + +TARGET_NAME = winlogon + +TARGET_INSTALLDIR = system32 + +TARGET_SDKLIBS = ntdll.a kernel32.a user32.a + +TARGET_OBJECTS = $(TARGET_NAME).o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# EOF diff --git a/subsys/system/winlogon/winlogon.c b/subsys/system/winlogon/winlogon.c new file mode 100644 index 0000000..ebeb403 --- /dev/null +++ b/subsys/system/winlogon/winlogon.c @@ -0,0 +1,364 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: services/winlogon/winlogon.c + * PURPOSE: Logon + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +HWINSTA InteractiveWindowStation; /* WinSta0 */ +HDESK ApplicationDesktop; /* WinSta0\Default */ +HDESK WinlogonDesktop; /* WinSta0\Winlogon */ +HDESK ScreenSaverDesktop; /* WinSta0\Screen-Saver */ + +/* FUNCTIONS *****************************************************************/ + +void PrintString (char* fmt,...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + OutputDebugString(buffer); +} + + +BOOLEAN StartServices(VOID) +{ + HANDLE ServicesInitEvent; + BOOLEAN Result; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + CHAR CommandLine[MAX_PATH]; + DWORD Count; + + /* Start the service control manager (services.exe) */ + GetSystemDirectory(CommandLine, MAX_PATH); + strcat(CommandLine, "\\services.exe"); + + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.lpReserved = NULL; + StartupInfo.lpDesktop = NULL; + StartupInfo.lpTitle = NULL; + StartupInfo.dwFlags = 0; + StartupInfo.cbReserved2 = 0; + StartupInfo.lpReserved2 = 0; + + Result = CreateProcess(CommandLine, + NULL, + NULL, + NULL, + FALSE, + DETACHED_PROCESS, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + if (!Result) + { + PrintString("WL: Failed to execute services\n"); + return FALSE; + } + + /* wait for event creation (by SCM) for max. 20 seconds */ + for (Count = 0; Count < 20; Count++) + { + Sleep(1000); + + ServicesInitEvent = OpenEvent(EVENT_ALL_ACCESS, //SYNCHRONIZE, + FALSE, + "SvcctrlStartEvent_A3725DX"); + if (ServicesInitEvent != NULL) + { + break; + } + } + + /* wait for event signalization */ + WaitForSingleObject(ServicesInitEvent, INFINITE); + CloseHandle(ServicesInitEvent); + + return TRUE; +} + +BOOLEAN StartLsass(VOID) +{ + HANDLE LsassInitEvent; + BOOLEAN Result; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + CHAR CommandLine[MAX_PATH]; + + LsassInitEvent = CreateEvent(NULL, + TRUE, + FALSE, + "\\LsassInitDone"); + + if (LsassInitEvent == NULL) + { + DbgPrint("Failed to create lsass notification event\n"); + return(FALSE); + } + + /* Start the local security authority subsystem (lsass.exe) */ + + GetSystemDirectory(CommandLine, MAX_PATH); + strcat(CommandLine, "\\lsass.exe"); + + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.lpReserved = NULL; + StartupInfo.lpDesktop = NULL; + StartupInfo.lpTitle = NULL; + StartupInfo.dwFlags = 0; + StartupInfo.cbReserved2 = 0; + StartupInfo.lpReserved2 = 0; + + Result = CreateProcess(CommandLine, + NULL, + NULL, + NULL, + FALSE, + DETACHED_PROCESS, + NULL, + NULL, + &StartupInfo, + &ProcessInformation); + if (!Result) + { + DbgPrint("WL: Failed to execute lsass\n"); + return(FALSE); + } + + DPRINT("WL: Waiting for lsass\n"); + WaitForSingleObject(LsassInitEvent, INFINITE); + CloseHandle(LsassInitEvent); + + return(TRUE); +} + +VOID DoLoginUser(PCHAR Name, PCHAR Password) +{ + PROCESS_INFORMATION ProcessInformation; + STARTUPINFO StartupInfo; + BOOLEAN Result; + CHAR CommandLine[MAX_PATH]; + CHAR CurrentDirectory[MAX_PATH]; + + GetSystemDirectory(CommandLine, MAX_PATH); + strcat(CommandLine, "\\shell.exe"); + + GetWindowsDirectory(CurrentDirectory, MAX_PATH); + + StartupInfo.cb = sizeof(StartupInfo); + StartupInfo.lpReserved = NULL; + StartupInfo.lpDesktop = NULL; + StartupInfo.lpTitle = NULL; + StartupInfo.dwFlags = 0; + StartupInfo.cbReserved2 = 0; + StartupInfo.lpReserved2 = 0; + + Result = CreateProcess(CommandLine, + NULL, + NULL, + NULL, + FALSE, + DETACHED_PROCESS, + NULL, + CurrentDirectory, + &StartupInfo, + &ProcessInformation); + if (!Result) + { + DbgPrint("WL: Failed to execute user shell\n"); + return; + } + WaitForSingleObject(ProcessInformation.hProcess, INFINITE); + CloseHandle( ProcessInformation.hProcess ); + CloseHandle( ProcessInformation.hThread ); +} + +int STDCALL +WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nShowCmd) +{ +#if 0 + LSA_STRING ProcessName; + NTSTATUS Status; + HANDLE LsaHandle; + LSA_OPERATIONAL_MODE Mode; +#endif + CHAR LoginPrompt[] = "login:"; + CHAR PasswordPrompt[] = "password:"; + DWORD Result; + CHAR LoginName[255]; + CHAR Password[255]; + BOOL Success; + ULONG i; + NTSTATUS Status; + + /* + * FIXME: Create a security descriptor with + * one ACE containing the Winlogon SID + */ + + /* + * Create the interactive window station + */ + InteractiveWindowStation = + CreateWindowStationW(L"WinSta0", 0, GENERIC_ALL, NULL); + if (InteractiveWindowStation == NULL) + { + DbgPrint("Failed to create window station (0x%X)\n", GetLastError()); + NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, 0, 0, 0); + ExitProcess(1); + } + + /* + * Set the process window station + */ + SetProcessWindowStation(InteractiveWindowStation); + + /* + * Create the application desktop + */ + ApplicationDesktop = + CreateDesktopW(L"Default", + NULL, + NULL, + 0, /* FIXME: Set some flags */ + GENERIC_ALL, + NULL); + + /* + * Create the winlogon desktop + */ + WinlogonDesktop = CreateDesktopW(L"Winlogon", + NULL, + NULL, + 0, /* FIXME: Set some flags */ + GENERIC_ALL, + NULL); + + /* + * Create the screen saver desktop + */ + ScreenSaverDesktop = CreateDesktopW(L"Screen-Saver", + NULL, + NULL, + 0, /* FIXME: Set some flags */ + GENERIC_ALL, + NULL); + + /* + * Switch to winlogon desktop + */ + /* FIXME: Do start up in the application desktop for now. */ + Status = NtSetInformationProcess(NtCurrentProcess(), + ProcessDesktop, + &ApplicationDesktop, + sizeof(ApplicationDesktop)); + if (!NT_SUCCESS(Status)) + { + DbgPrint("WL: Cannot set default desktop for winlogon.\n"); + } + SetThreadDesktop(ApplicationDesktop); + Success = SwitchDesktop(ApplicationDesktop); + if (!Success) + { + DbgPrint("Cannot switch to Winlogon desktop (0x%X)\n", GetLastError()); + } + + AllocConsole(); + SetConsoleTitle( "Winlogon" ); + /* start system processes (services.exe & lsass.exe) */ + StartServices(); +#if 0 + StartLsass(); +#endif + + /* FIXME: What name does the real WinLogon use? */ +#if 0 + RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"WinLogon"); + Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); + if (!NT_SUCCESS(Status)) + { + DbgPrint("WL: Failed to connect to lsass\n"); + return(1); + } +#endif + + /* FIXME: Create a window class and associate a Winlogon + * window procedure with it. + * Register SAS with the window. + * Register for logoff notification + */ + + /* Main loop */ + for (;;) + { +#if 0 + /* Display login prompt */ + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), + LoginPrompt, + strlen(LoginPrompt), // wcslen(LoginPrompt), + &Result, + NULL); + i = 0; + do + { + ReadConsole(GetStdHandle(STD_INPUT_HANDLE), + &LoginName[i], + 1, + &Result, + NULL); + i++; + } while (LoginName[i - 1] != '\n'); + LoginName[i - 1] = 0; + + /* Display password prompt */ + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), + PasswordPrompt, + strlen(PasswordPrompt), // wcslen(PasswordPrompt), + &Result, + NULL); + i = 0; + do + { + ReadConsole(GetStdHandle(STD_INPUT_HANDLE), + &Password[i], + 1, + &Result, + NULL); + i++; + } while (Password[i - 1] != '\n'); + Password[i - 1] =0; +#endif + DoLoginUser(LoginName, Password); + } + + ExitProcess(0); + + return 0; +} diff --git a/subsys/system/winlogon/winlogon.rc b/subsys/system/winlogon/winlogon.rc new file mode 100644 index 0000000..46b4f77 --- /dev/null +++ b/subsys/system/winlogon/winlogon.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "ReactOS Logon Application\0" + VALUE "FileVersion", RES_STR_FILE_VERSION + VALUE "InternalName", "winlogon\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "winlogon.exe\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/subsys/win32k/.cvsignore b/subsys/win32k/.cvsignore new file mode 100644 index 0000000..1057c1a --- /dev/null +++ b/subsys/win32k/.cvsignore @@ -0,0 +1,8 @@ +base.tmp +junk.tmp +temp.exp +win32k.coff +win32k.sys +*.d +*.o +*.sym diff --git a/subsys/win32k/dib/.cvsignore b/subsys/win32k/dib/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/dib/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/dib/dib.h b/subsys/win32k/dib/dib.h new file mode 100644 index 0000000..4d00fed --- /dev/null +++ b/subsys/win32k/dib/dib.h @@ -0,0 +1,35 @@ +static unsigned char notmask[2] = { 0x0f, 0xf0 }; +static unsigned char altnotmask[2] = { 0xf0, 0x0f }; +static unsigned char mask1Bpp[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + +typedef VOID (*PFN_DIB_PutPixel)(PSURFOBJ, LONG, LONG, ULONG); +typedef ULONG (*PFN_DIB_GetPixel)(PSURFOBJ, LONG, LONG); +typedef VOID (*PFN_DIB_HLine) (PSURFOBJ, LONG, LONG, LONG, ULONG); +typedef VOID (*PFN_DIB_VLine) (PSURFOBJ, LONG, LONG, LONG, ULONG); + +PFN_DIB_PutPixel DIB_1BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c); +PFN_DIB_GetPixel DIB_1BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y); +PFN_DIB_HLine DIB_1BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c); +PFN_DIB_VLine DIB_1BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c); +BOOLEAN DIB_To_1BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation); + +PFN_DIB_PutPixel DIB_4BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c); +PFN_DIB_GetPixel DIB_4BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y); +PFN_DIB_HLine DIB_4BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c); +PFN_DIB_VLine DIB_4BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c); +BOOLEAN DIB_To_4BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation); + +PFN_DIB_PutPixel DIB_24BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c); +PFN_DIB_GetPixel DIB_24BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y); +PFN_DIB_HLine DIB_24BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c); +PFN_DIB_VLine DIB_24BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c); +BOOLEAN DIB_To_24BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation); diff --git a/subsys/win32k/dib/dib1bpp.c b/subsys/win32k/dib/dib1bpp.c new file mode 100644 index 0000000..a3af45a --- /dev/null +++ b/subsys/win32k/dib/dib1bpp.c @@ -0,0 +1,122 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include "../eng/objects.h" +#include "dib.h" + +PFN_DIB_PutPixel DIB_1BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c) +{ + unsigned char *vp; + unsigned char mask; + PBYTE addr = SurfObj->pvBits; + + addr += y * SurfObj->lDelta + (x >> 3); + + if(c == 0) + { + *addr = (*addr ^ mask1Bpp[mod(x, 8)]); + } + else + { + *addr = (*addr | mask1Bpp[mod(x, 8)]); + } +} + +PFN_DIB_GetPixel DIB_1BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y) +{ + PBYTE addr = SurfObj->pvBits + y * SurfObj->lDelta + (x >> 3); + + if(*addr & mask1Bpp[mod(x, 8)]) return (PFN_DIB_GetPixel)(1); + return (PFN_DIB_GetPixel)(0); +} + +PFN_DIB_HLine DIB_1BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c) +{ + while(x1 <= x2) { + DIB_1BPP_PutPixel(SurfObj, x1, y, c); + x1++; + } +} + +PFN_DIB_VLine DIB_1BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c) +{ + while(y1 <= y2) { + DIB_1BPP_PutPixel(SurfObj, x, y1, c); + y1++; + } +} + +BOOLEAN DIB_To_1BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation) +{ + LONG i, j, sx, sy = SourcePoint->y; + + switch(SourceGDI->BitsPerPixel) + { + case 1: + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + for (i=DestRect->left; iright; i++) + { + if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0) + { + DIB_1BPP_PutPixel(DestSurf, i, j, 0); + } else { + DIB_1BPP_PutPixel(DestSurf, i, j, 1); + } + sx++; + } + sy++; + } + break; + + case 4: + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + for (i=DestRect->left; iright; i++) + { + if(XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy)) == 0) + { + DIB_1BPP_PutPixel(DestSurf, i, j, 0); + } else { + DIB_1BPP_PutPixel(DestSurf, i, j, 1); + } + sx++; + } + sy++; + } + break; + + case 24: + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + for (i=DestRect->left; iright; i++) + { + if(XLATEOBJ_iXlate(ColorTranslation, DIB_24BPP_GetPixel(SourceSurf, sx, sy)) == 0) + { + DIB_1BPP_PutPixel(DestSurf, i, j, 0); + } else { + DIB_1BPP_PutPixel(DestSurf, i, j, 1); + } + sx++; + } + sy++; + } + break; + + default: + DbgPrint("DIB_1BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + return FALSE; + } + + return TRUE; +} diff --git a/subsys/win32k/dib/dib24bpp.c b/subsys/win32k/dib/dib24bpp.c new file mode 100644 index 0000000..1e27752 --- /dev/null +++ b/subsys/win32k/dib/dib24bpp.c @@ -0,0 +1,155 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include "../eng/objects.h" +#include "dib.h" + +PFN_DIB_PutPixel DIB_24BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c) +{ + PBYTE byteaddr = SurfObj->pvBits + y * SurfObj->lDelta; + PRGBTRIPLE addr = (PRGBTRIPLE)byteaddr + x; + + *(PULONG)(addr) = c; +} + +PFN_DIB_GetPixel DIB_24BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y) +{ + PBYTE byteaddr = SurfObj->pvBits + y * SurfObj->lDelta; + PRGBTRIPLE addr = (PRGBTRIPLE)byteaddr + x; + + return (PFN_DIB_GetPixel)(*(PULONG)(addr)); +} + +PFN_DIB_HLine DIB_24BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c) +{ + PBYTE byteaddr = SurfObj->pvBits + y * SurfObj->lDelta; + PRGBTRIPLE addr = (PRGBTRIPLE)byteaddr + x1; + LONG cx = x1; + + while(cx <= x2) { + *(PULONG)(addr) = c; + ++addr; + ++cx; + } +} + +PFN_DIB_VLine DIB_24BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c) +{ + PBYTE byteaddr = SurfObj->pvBits + y1 * SurfObj->lDelta; + PRGBTRIPLE addr = (PRGBTRIPLE)byteaddr + x; + LONG lDelta = SurfObj->lDelta; + + byteaddr = (PBYTE)addr; + while(y1++ <= y2) { + *(PULONG)(addr) = c; + + byteaddr += lDelta; + addr = (PRGBTRIPLE)byteaddr; + } +} + +VOID DIB_24BPP_BltTo_24BPP(PSURFOBJ dstpsd, LONG dstx, LONG dsty, LONG w, LONG h, + PSURFOBJ srcpsd, LONG srcx, LONG srcy) +{ + PRGBTRIPLE dst; + PRGBTRIPLE src; + PBYTE bytedst; + PBYTE bytesrc; + int i; + int dlDelta = dstpsd->lDelta; + int slDelta = srcpsd->lDelta; + + bytedst = (char *)dstpsd->pvBits + dsty * dlDelta; + bytesrc = (char *)srcpsd->pvBits + srcy * slDelta; + dst = (PRGBTRIPLE)bytedst + dstx; + src = (PRGBTRIPLE)bytesrc + srcx; + + while(--h >= 0) { + PRGBTRIPLE d = dst; + PRGBTRIPLE s = src; + LONG dx = dstx; + LONG sx = srcx; + for(i=0; ipvBits + (DestRect->top * DestSurf->lDelta) + DestRect->left * 3; + + switch(SourceGDI->BitsPerPixel) + { + case 1: + sx = SourcePoint->x; + sy = SourcePoint->y; + + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + for (i=DestRect->left; iright; i++) + { + if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0) + { + DIB_24BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 0)); + } else { + DIB_24BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 1)); + } + sx++; + } + sy++; + } + break; + + case 4: + SourceBits_4BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x; + + for (j=DestRect->top; jbottom; j++) + { + SourceLine_4BPP = SourceBits_4BPP; + DestLine = DestBits; + sx = SourcePoint->x; + f1 = sx & 1; + + for (i=DestRect->left; iright; i++) + { + xColor = XLATEOBJ_iXlate(ColorTranslation, + (*SourceLine_4BPP & altnotmask[sx&1]) >> (4 * (1-(sx & 1)))); + *DestLine++ = xColor & 0xff; + *(PWORD)DestLine = xColor >> 8; + DestLine += 2; + if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; } + sx++; + } + + SourceBits_4BPP += SourceSurf->lDelta; + DestBits += DestSurf->lDelta; + } + break; + + default: + DbgPrint("DIB_24BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + return FALSE; + } + + return TRUE; +} diff --git a/subsys/win32k/dib/dib4bpp.c b/subsys/win32k/dib/dib4bpp.c new file mode 100644 index 0000000..856ea0d --- /dev/null +++ b/subsys/win32k/dib/dib4bpp.c @@ -0,0 +1,164 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include "../eng/objects.h" +#include "dib.h" + +PFN_DIB_PutPixel DIB_4BPP_PutPixel(PSURFOBJ SurfObj, LONG x, LONG y, ULONG c) +{ + unsigned char *vp; + unsigned char mask; + PBYTE addr = SurfObj->pvBits; + + addr += (x>>1) + y * SurfObj->lDelta; + *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2)); +} + +PFN_DIB_GetPixel DIB_4BPP_GetPixel(PSURFOBJ SurfObj, LONG x, LONG y) +{ + PBYTE addr = SurfObj->pvBits; + + return (PFN_DIB_GetPixel)((addr[(x>>1) + y * SurfObj->lDelta] >> ((1-(x&1))<<2) ) & 0x0f); +} + +PFN_DIB_HLine DIB_4BPP_HLine(PSURFOBJ SurfObj, LONG x1, LONG x2, LONG y, ULONG c) +{ + PBYTE addr = SurfObj->pvBits + (x1>>1) + y * SurfObj->lDelta; + LONG cx = x1; + + while(cx <= x2) { + *addr = (*addr & notmask[x1&1]) | (c << ((1-(x1&1))<<2)); + if((++x1 & 1) == 0) + ++addr; + ++cx; + } +} + +PFN_DIB_VLine DIB_4BPP_VLine(PSURFOBJ SurfObj, LONG x, LONG y1, LONG y2, ULONG c) +{ + PBYTE addr = SurfObj->pvBits; + int lDelta = SurfObj->lDelta; + + addr += (x>>1) + y1 * lDelta; + while(y1++ <= y2) { + *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2)); + addr += lDelta; + } +} + +BOOLEAN DIB_To_4BPP_Bitblt( SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation) +{ + LONG i, j, sx, sy, f1, f2, xColor; + PBYTE SourceBits_24BPP, SourceLine_24BPP; + PBYTE DestBits, DestLine, SourceBits_4BPP, SourceBits_8BPP, SourceLine_4BPP, SourceLine_8BPP; + PWORD SourceBits_16BPP, SourceLine_16BPP; + PDWORD SourceBits_32BPP, SourceLine_32BPP; + + DestBits = DestSurf->pvBits + (DestRect->left>>1) + DestRect->top * DestSurf->lDelta; + + switch(SourceGDI->BitsPerPixel) + { + case 1: + sx = SourcePoint->x; + sy = SourcePoint->y; + + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + for (i=DestRect->left; iright; i++) + { + if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0) + { + DIB_4BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 0)); + } else { + DIB_4BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, 1)); + } + sx++; + } + sy++; + } + break; + + case 4: + sy = SourcePoint->y; + + for (j=DestRect->top; jbottom; j++) + { + sx = SourcePoint->x; + + for (i=DestRect->left; iright; i++) + { + DIB_4BPP_PutPixel(DestSurf, i, j, XLATEOBJ_iXlate(ColorTranslation, DIB_4BPP_GetPixel(SourceSurf, sx, sy))); + sx++; + } + sy++; + } + break; + + case 8: + SourceBits_8BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x; + + for (j=DestRect->top; jbottom; j++) + { + SourceLine_8BPP = SourceBits_8BPP; + DestLine = DestBits; + sx = SourcePoint->x; + f1 = sx & 1; + f2 = DestRect->left & 1; + + for (i=DestRect->left; iright; i++) + { + *DestLine = (*DestLine & notmask[i&1]) | + ((XLATEOBJ_iXlate(ColorTranslation, *SourceLine_8BPP)) << ((4 * (1-(sx & 1))))); + if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; } + SourceLine_8BPP++; + sx++; + } + + SourceBits_8BPP += SourceSurf->lDelta; + DestBits += DestSurf->lDelta; + } + break; + + case 24: + SourceBits_24BPP = SourceSurf->pvBits + (SourcePoint->y * SourceSurf->lDelta) + SourcePoint->x * 3; + + for (j=DestRect->top; jbottom; j++) + { + SourceLine_24BPP = SourceBits_24BPP; + DestLine = DestBits; + sx = SourcePoint->x; + f1 = sx & 1; + f2 = DestRect->left & 1; + + for (i=DestRect->left; iright; i++) + { + xColor = (*(SourceLine_24BPP + 2) << 0x10) + + (*(SourceLine_24BPP + 1) << 0x08) + + (*(SourceLine_24BPP)); + *DestLine = (*DestLine & notmask[i&1]) | + ((XLATEOBJ_iXlate(ColorTranslation, xColor)) << ((4 * (1-(sx & 1))))); + if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; } + SourceLine_24BPP+=3; + sx++; + } + + SourceBits_24BPP += SourceSurf->lDelta; + DestBits += DestSurf->lDelta; + } + break; + + default: + DbgPrint("DIB_4BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + return FALSE; + } + + return TRUE; +} diff --git a/subsys/win32k/eng/.cvsignore b/subsys/win32k/eng/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/eng/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/eng/bitblt.c b/subsys/win32k/eng/bitblt.c new file mode 100644 index 0000000..c582ebf --- /dev/null +++ b/subsys/win32k/eng/bitblt.c @@ -0,0 +1,225 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI BitBlt Functions + * FILE: subsys/win32k/eng/bitblt.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 2/10/1999: Created + */ + +#include +#include +#include +#include "brush.h" +#include "clip.h" +#include "objects.h" +#include +#include +#include +#include +#include + +BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2) +{ + static const RECTL rclEmpty = { 0, 0, 0, 0 }; + + prcDst->left = max(prcSrc1->left, prcSrc2->left); + prcDst->right = min(prcSrc1->right, prcSrc2->right); + + if (prcDst->left < prcDst->right) + { + prcDst->top = max(prcSrc1->top, prcSrc2->top); + prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); + + if (prcDst->top < prcDst->bottom) return(TRUE); + } + + *prcDst = rclEmpty; + + return(FALSE); +} + +INT abs(INT nm); + +BOOL STDCALL +EngBitBlt(SURFOBJ *Dest, + SURFOBJ *Source, + SURFOBJ *Mask, + CLIPOBJ *ClipRegion, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint, + POINTL *MaskRect, + BRUSHOBJ *Brush, + POINTL *BrushOrigin, + ROP4 rop4) +{ + BOOLEAN ret; + BYTE clippingType; + RECTL rclTmp; + POINTL ptlTmp; + RECT_ENUM RectEnum; + BOOL EnumMore; + PSURFGDI DestGDI, SourceGDI; + HSURF hTemp; + PSURFOBJ TempSurf = NULL; + BOOLEAN canCopyBits; + POINTL TempPoint; + RECTL TempRect; + SIZEL TempSize; + + if(Source != NULL) SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source); + if(Dest != NULL) DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest); + + if (Source != NULL) + { + MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y, + (SourcePoint->x + abs(DestRect->right - DestRect->left)), + (SourcePoint->y + abs(DestRect->bottom - DestRect->top))); + } + MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); + + // If we don't have to do anything special, we can punt to DrvCopyBits + // if it exists + if( (Mask == NULL) && (MaskRect == NULL) && (Brush == NULL) && + (BrushOrigin == NULL) && (rop4 == 0) ) + { + canCopyBits = TRUE; + } else + canCopyBits = FALSE; + + // Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap, IF: + // * The destination bitmap is not managed by the GDI OR + if(Dest->iType != STYPE_BITMAP) + { + // Destination surface is device managed + if (DestGDI->BitBlt!=NULL) + { + if (Source!=NULL) + { + // Get the source into a format compatible surface + TempPoint.x = 0; + TempPoint.y = 0; + TempRect.top = 0; + TempRect.left = 0; + TempRect.bottom = DestRect->bottom - DestRect->top; + TempRect.right = DestRect->right - DestRect->left; + TempSize.cx = TempRect.right; + TempSize.cy = TempRect.bottom; + + hTemp = EngCreateBitmap(TempSize, + DIB_GetDIBWidthBytes(DestRect->right - DestRect->left, BitsPerFormat(Dest->iBitmapFormat)), + Dest->iBitmapFormat, 0, NULL); + TempSurf = (PSURFOBJ)AccessUserObject((ULONG)hTemp); + + // FIXME: Skip creating a TempSurf if we have the same BPP and palette + EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, SourcePoint, NULL, NULL, NULL, 0); + } + + ret = DestGDI->BitBlt(Dest, TempSurf, Mask, ClipRegion, + NULL, DestRect, &TempPoint, + MaskRect, Brush, BrushOrigin, rop4); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return ret; + } + } + + /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to + * paint a brush pattern on the destination. */ + if(!Source) + { + DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n"); + return FALSE; + } + + // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device + if(Source->iType != STYPE_BITMAP && SourceGDI->CopyBits == NULL) + { + if (SourceGDI->BitBlt!=NULL) + { + // Request the device driver to return the bitmap in a format compatible with the device + ret = SourceGDI->BitBlt(Dest, Source, Mask, ClipRegion, + NULL, DestRect, SourcePoint, + MaskRect, Brush, BrushOrigin, rop4); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return ret; + + // Convert the surface from the driver into the required destination surface + } + } + + // Determine clipping type + if (ClipRegion == (CLIPOBJ *) NULL) + { + clippingType = DC_TRIVIAL; + } else { + clippingType = ClipRegion->iDComplexity; + } + + // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE] + switch(clippingType) + { + case DC_TRIVIAL: + CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, Source->lDelta, ColorTranslation); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(TRUE); + + case DC_RECT: + + // Clip the blt to the clip rectangle + EngIntersectRect(&rclTmp, DestRect, &ClipRegion->rclBounds); + + ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left; + ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top; + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(TRUE); + + case DC_COMPLEX: + + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT); + + do { + EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + + if (RectEnum.c > 0) + { + RECTL* prclEnd = &RectEnum.arcl[RectEnum.c]; + RECTL* prcl = &RectEnum.arcl[0]; + + do { + EngIntersectRect(prcl, prcl, DestRect); + + ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left; + ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top; + + prcl++; + + } while (prcl < prclEnd); + } + + } while(EnumMore); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(TRUE); + } + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(FALSE); +} diff --git a/subsys/win32k/eng/brush.c b/subsys/win32k/eng/brush.c new file mode 100644 index 0000000..b07abf1 --- /dev/null +++ b/subsys/win32k/eng/brush.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Driver Brush Functions + * FILE: subsys/win32k/eng/brush.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 3/7/1999: Created + */ + +#include + +PVOID STDCALL +BRUSHOBJ_pvAllocRbrush(IN PBRUSHOBJ BrushObj, + IN ULONG ObjSize) +{ + BrushObj->pvRbrush=EngAllocMem(0, ObjSize, 0); + return(BrushObj->pvRbrush); +} + +PVOID STDCALL +BRUSHOBJ_pvGetRbrush(IN PBRUSHOBJ BrushObj) +{ + return(BrushObj->pvRbrush); +} diff --git a/subsys/win32k/eng/brush.h b/subsys/win32k/eng/brush.h new file mode 100644 index 0000000..d6b73ab --- /dev/null +++ b/subsys/win32k/eng/brush.h @@ -0,0 +1,58 @@ +typedef struct _BRUSHINST +{ + // We need to removed ajC0-3 when color pattern code is complete!!! + // + BYTE ajC0[8]; // Color bits for plane 0 + BYTE ajC1[8]; // Color bits for plane 1 + BYTE ajC2[8]; // Color bits for plane 2 + BYTE ajC3[8]; // Color bits for plane 3 + + BYTE ajPattern[32]; // Color bits for the mask + USHORT usStyle; // Brush style + BYTE fjAccel; // Accelerator flags + BYTE jFgColor; // Current foreground color + BYTE jBkColor; // Current background color + BYTE RealWidth;// + BYTE YShiftValue; // + BYTE jOldBrushRealized; // + DWORD Width; // Width of brush + DWORD Height; + BYTE *pPattern; //Pointer to realized mono pattern +} BRUSHINST; + +#define BRI_SOLID 0 +#define BRI_HOLLOW 1 +#define BRI_HATCHED 2 +#define BRI_PATTERN 3 +#define BRI_MONO_PATTERN 4 +#define BRI_COLOR_PATTERN 5 + +// Definitions for the pcol_C3 byte of the physical color +// +// Some of these definitions have limitations as to when they +// are valid. They are as follows: +// +// C0_BIT color device, phys color, solid brushes if SOLID_COLOR +// C1_BIT color device, phys color, solid brushes if SOLID_COLOR +// C2_BIT color device, phys color, solid brushes if SOLID_COLOR +// C3_BIT color device, phys color, solid brushes if SOLID_COLOR +// MONO_BIT mono device, phys color +// ONES_OR_ZEROS color device, phys color, solid brushes if SOLID_COLOR +// GREY_SCALE color device, dithered solid and hatched brushes +// SOLID_BRUSH color device, solid brush qualifier +// +// There may be brushes where the accelerators could have been set, +// but wasn't. That's life. + +#define C0_BIT 0x01 // C0 color +#define C1_BIT 0x02 // C1 color +#define C2_BIT 0x04 // C2 color +#define C3_BIT 0x08 // C3 color +#define COLOR_BITS 0x0f // All the color bits +#define MONO_BIT 0x10 // Monochrome bit +#define ONES_OR_ZEROS 0x20 // Color is really all 1's or all 0's +#define GREY_SCALE 0x40 // Indicates a real grey scale brush +#define SOLID_BRUSH 0x80 // Indicates a solid color brush + +#define PTRI_INVERT 0x0001 +#define PTRI_ANIMATE 0x0002 diff --git a/subsys/win32k/eng/clip.c b/subsys/win32k/eng/clip.c new file mode 100644 index 0000000..244b3bd --- /dev/null +++ b/subsys/win32k/eng/clip.c @@ -0,0 +1,135 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Clipping Functions + * FILE: subsys/win32k/eng/clip.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 21/8/1999: Created + */ + +#include +#include +#include "objects.h" +#include "clip.h" +#include + +#include + +VOID IntEngDeleteClipRegion(CLIPOBJ *ClipObj) +{ + HCLIP HClip = AccessHandleFromUserObject(ClipObj); + FreeGDIHandle(HClip); +} + +CLIPOBJ * IntEngCreateClipRegion( ULONG count, PRECTL pRect, RECTL rcBounds ) +{ + HCLIP hClip; + CLIPGDI* clipInt; + CLIPOBJ* clipUser; + DPRINT("IntEngCreateClipRegion count: %d\n", count); + if( count > 1 ){ + hClip = (HCLIP)CreateGDIHandle( sizeof( CLIPGDI ) + count*sizeof(RECTL), + sizeof( CLIPOBJ ) ); + + if( hClip ){ + clipInt = (CLIPGDI*)AccessInternalObject( hClip ); + RtlCopyMemory( clipInt->EnumRects.arcl, pRect, count*sizeof(RECTL)); + clipInt->EnumRects.c=count; + + clipUser = (CLIPOBJ*)AccessUserObject( hClip ); + ASSERT( clipUser ); + + clipUser->iDComplexity = DC_COMPLEX; + clipUser->iFComplexity = (count <= 4)? FC_RECT4: FC_COMPLEX; + clipUser->iMode = TC_RECTANGLES; + RtlCopyMemory( &(clipUser->rclBounds), &rcBounds, sizeof( RECTL ) ); + + return clipUser; + } + return NULL; + } + else{ + hClip = (HCLIP)CreateGDIHandle( sizeof( CLIPGDI ), + sizeof( CLIPOBJ ) ); + if( hClip ){ + clipInt = (CLIPGDI*)AccessInternalObject( hClip ); + RtlCopyMemory( clipInt->EnumRects.arcl, &rcBounds, sizeof( RECTL )); + clipInt->EnumRects.c = 1; + + clipUser = (CLIPOBJ*)AccessUserObject( hClip ); + ASSERT( clipUser ); + + clipUser->iDComplexity = ((rcBounds.top==rcBounds.bottom)&&(rcBounds.left==rcBounds.right))? + DC_TRIVIAL:DC_RECT; + clipUser->iFComplexity = FC_RECT; + clipUser->iMode = TC_RECTANGLES; + DPRINT("IntEngCreateClipRegion: iDComplexity: %d\n", clipUser->iDComplexity); + RtlCopyMemory( &(clipUser->rclBounds), &rcBounds, sizeof( RECTL ) ); + return clipUser; + } + } + return NULL; +} + +CLIPOBJ * STDCALL +EngCreateClip(VOID) +{ + return EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPOBJ), 0); +} + +VOID STDCALL +EngDeleteClip(CLIPOBJ *ClipRegion) +{ + EngFreeMem(ClipRegion); +} + +ULONG STDCALL +CLIPOBJ_cEnumStart(IN PCLIPOBJ ClipObj, + IN BOOL ShouldDoAll, + IN ULONG ClipType, + IN ULONG BuildOrder, + IN ULONG MaxRects) +{ + CLIPGDI *ClipGDI = (CLIPGDI*)AccessInternalObjectFromUserObject(ClipObj); + + ClipGDI->EnumPos = 0; + ClipGDI->EnumMax = (MaxRects>0)? MaxRects : ClipGDI->EnumRects.c; + + if( !((BuildOrder == CD_ANY) || (BuildOrder == CD_LEFTDOWN ))){ + UNIMPLEMENTED; + } + ClipGDI->EnumOrder = BuildOrder; + + // Return the number of rectangles enumerated + if( (MaxRects > 0) && (ClipGDI->EnumRects.c>MaxRects) ) + { + return 0xFFFFFFFF; + } + + return ClipGDI->EnumRects.c; +} + +BOOL STDCALL +CLIPOBJ_bEnum(IN PCLIPOBJ ClipObj, + IN ULONG ObjSize, + OUT ULONG *EnumRects) +{ + CLIPGDI *ClipGDI = (CLIPGDI*)AccessInternalObjectFromUserObject(ClipObj); + ULONG nCopy; + PENUMRECTS pERects = (PENUMRECTS)EnumRects; + + //calculate how many rectangles we should copy + nCopy = MIN( ClipGDI->EnumMax-ClipGDI->EnumPos, + MIN( ClipGDI->EnumRects.c, (ObjSize-sizeof(ULONG))/sizeof(RECTL))); + + RtlCopyMemory( &(pERects->arcl), &(ClipGDI->EnumRects.arcl), nCopy*sizeof(RECTL) ); + pERects->c = nCopy; + + ClipGDI->EnumPos+=nCopy; + + if(ClipGDI->EnumPos > ClipGDI->EnumRects.c) + return FALSE; + else + return TRUE; +} diff --git a/subsys/win32k/eng/clip.h b/subsys/win32k/eng/clip.h new file mode 100644 index 0000000..f637eb0 --- /dev/null +++ b/subsys/win32k/eng/clip.h @@ -0,0 +1,17 @@ +#ifndef __WIN32K_CLIP_H +#define __WIN32K_CLIP_H + +typedef ULONG HCLIP; +CLIPOBJ * IntEngCreateClipRegion( ULONG count, PRECTL pRect, RECTL rcBounds ); +VOID IntEngDeleteClipRegion(CLIPOBJ *ClipObj); + + +#define ENUM_RECT_LIMIT 50 + +typedef struct _RECT_ENUM +{ + ULONG c; + RECTL arcl[ENUM_RECT_LIMIT]; +} RECT_ENUM; + +#endif diff --git a/subsys/win32k/eng/copybits.c b/subsys/win32k/eng/copybits.c new file mode 100644 index 0000000..d3f4528 --- /dev/null +++ b/subsys/win32k/eng/copybits.c @@ -0,0 +1,209 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI EngCopyBits Function + * FILE: subsys/win32k/eng/copybits.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 8/18/1999: Created + */ + +#include +#include "objects.h" +#include "clip.h" +#include "../dib/dib.h" +#include +#include +#include + +BOOLEAN CopyBitsCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + LONG Delta, XLATEOBJ *ColorTranslation) +{ + LONG DestWidth, DestHeight, CurrentDestLine, CurrentSourceLine, CurrentDestCol, CurrentSourceCol, i, TranslationPixel; + + PFN_DIB_GetPixel Source_DIB_GetPixel; + PFN_DIB_PutPixel Dest_DIB_PutPixel; + + DestWidth = DestRect->right - DestRect->left; + DestHeight = DestRect->bottom - DestRect->top; + CurrentSourceCol = SourcePoint->x; + CurrentSourceLine = SourcePoint->y; + + // Assign GetPixel DIB function according to bytes per pixel + switch(DestGDI->BitsPerPixel) + { + case 1: + return DIB_To_1BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI, + DestRect, SourcePoint, Delta, ColorTranslation); + break; + + case 4: + return DIB_To_4BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI, + DestRect, SourcePoint, Delta, ColorTranslation); + break; + + case 24: + return DIB_To_24BPP_Bitblt(DestSurf, SourceSurf, DestGDI, SourceGDI, + DestRect, SourcePoint, Delta, ColorTranslation); + break; + + default: + return FALSE; + } + + return TRUE; +} + +BOOL STDCALL +EngCopyBits(SURFOBJ *Dest, + SURFOBJ *Source, + CLIPOBJ *Clip, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint) +{ + BOOLEAN ret; + SURFGDI *DestGDI, *SourceGDI; + BYTE clippingType; + RECTL rclTmp; + POINTL ptlTmp; + RECT_ENUM RectEnum; + BOOL EnumMore; + + MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y, + (SourcePoint->x + abs(DestRect->right - DestRect->left)), + (SourcePoint->y + abs(DestRect->bottom - DestRect->top))); + MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); + + // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead, + // mark the copy block function to be DrvCopyBits instead of the + // GDI's copy bit function so as to remove clipping from the + // driver's responsibility + + // If one of the surfaces isn't managed by the GDI + if((Dest->iType!=STYPE_BITMAP) || (Source->iType!=STYPE_BITMAP)) + { + // Destination surface is device managed + if(Dest->iType!=STYPE_BITMAP) + { + DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest); + + if (DestGDI->CopyBits!=NULL) + { + ret = DestGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return ret; + } + } + + // Source surface is device managed + if(Source->iType!=STYPE_BITMAP) + { + SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source); + + if (SourceGDI->CopyBits!=NULL) + { + ret = SourceGDI->CopyBits(Dest, Source, Clip, ColorTranslation, DestRect, SourcePoint); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return ret; + } + } + + // If CopyBits wasn't hooked, BitBlt must be + ret = EngBitBlt(Dest, Source, + NULL, Clip, ColorTranslation, DestRect, SourcePoint, + NULL, NULL, NULL, 0); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return ret; + } + + // Determine clipping type + if (Clip == (CLIPOBJ *) NULL) + { + clippingType = DC_TRIVIAL; + } else { + clippingType = Clip->iDComplexity; + } + + // We only handle XO_TABLE translations at the momement + if ((ColorTranslation == NULL) || (ColorTranslation->flXlate & XO_TRIVIAL) || + (ColorTranslation->flXlate & XO_TABLE)) + { + SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source); + DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest); + + switch(clippingType) + { + case DC_TRIVIAL: + CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, Source->lDelta, ColorTranslation); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(TRUE); + + case DC_RECT: + // Clip the blt to the clip rectangle + EngIntersectRect(&rclTmp, DestRect, &Clip->rclBounds); + + ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left; + ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top; + + CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, &rclTmp, &ptlTmp, Source->lDelta, ColorTranslation); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(TRUE); + + case DC_COMPLEX: + + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT); + + do { + EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + + if (RectEnum.c > 0) + { + RECTL* prclEnd = &RectEnum.arcl[RectEnum.c]; + RECTL* prcl = &RectEnum.arcl[0]; + + do { + EngIntersectRect(prcl, prcl, DestRect); + + ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left; + ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top; + + if(!CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, + prcl, &ptlTmp, Source->lDelta, ColorTranslation)) return FALSE; + + prcl++; + + } while (prcl < prclEnd); + } + + } while(EnumMore); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return(TRUE); + } + } + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return FALSE; +} diff --git a/subsys/win32k/eng/debug.c b/subsys/win32k/eng/debug.c new file mode 100644 index 0000000..ecb0e83 --- /dev/null +++ b/subsys/win32k/eng/debug.c @@ -0,0 +1,21 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Driver Brush Functions + * FILE: subsys/win32k/eng/debug.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 11/7/1999: Created + */ + +#include + +VOID STDCALL +EngDebugPrint(PCHAR StandardPrefix, + PCHAR DebugMessage, + va_list ap) +{ + DbgPrint(StandardPrefix); + DbgPrint(DebugMessage, ap); + DbgPrint("\n"); +} diff --git a/subsys/win32k/eng/device.c b/subsys/win32k/eng/device.c new file mode 100644 index 0000000..39a5358 --- /dev/null +++ b/subsys/win32k/eng/device.c @@ -0,0 +1,61 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Driver Device Functions + * FILE: subsys/win32k/eng/device.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 3/7/1999: Created + */ + +#include + +#define NDEBUG +#include + +DWORD STDCALL +EngDeviceIoControl(HANDLE hDevice, + DWORD dwIoControlCode, + LPVOID lpInBuffer, + DWORD nInBufferSize, + LPVOID lpOutBuffer, + DWORD nOutBufferSize, + DWORD *lpBytesReturned) +{ + PIRP Irp; + NTSTATUS Status; + KEVENT Event; + IO_STATUS_BLOCK Iosb; + PFILE_OBJECT FileObject; + + DPRINT("EngDeviceIoControl() called\n"); + + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + + Status = ObReferenceObjectByHandle(hDevice, + FILE_READ_DATA | FILE_WRITE_DATA, + IoFileObjectType, + KernelMode, + (PVOID *)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Irp = IoBuildDeviceIoControlRequest(dwIoControlCode, + FileObject->DeviceObject, + lpInBuffer, + nInBufferSize, + lpOutBuffer, + nOutBufferSize, FALSE, &Event, &Iosb); + + Status = IoCallDriver(FileObject->DeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + (void) KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, 0); + } + + return (Status); +} diff --git a/subsys/win32k/eng/handle.c b/subsys/win32k/eng/handle.c new file mode 100644 index 0000000..dd0700b --- /dev/null +++ b/subsys/win32k/eng/handle.c @@ -0,0 +1,114 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Manage GDI Handles + * FILE: subsys/win32k/eng/handle.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 29/8/1999: Created + */ + +#include +#include "handle.h" + +#define NDEBUG +#include + + +ULONG CreateGDIHandle(ULONG InternalSize, ULONG UserSize) +{ + ULONG size; + PENGOBJ pObj; + int i; + + //size = sizeof( ENGOBJ ) + InternalSize + UserSize; + size = InternalSize; //internal size includes header and user portions + pObj = EngAllocMem( FL_ZERO_MEMORY, size, 0 ); + + if( !pObj ) + return 0; + + pObj->InternalSize = InternalSize; + pObj->UserSize = UserSize; + + for( i=1; i < MAX_GDI_HANDLES; i++ ){ + if( GDIHandles[ i ].pEngObj == NULL ){ + pObj->hObj = i; + GDIHandles[ i ].pEngObj = pObj; + DPRINT("CreateGDIHandle: obj: %x, handle: %d, usersize: %d\n", pObj, i, UserSize ); + return i; + } + } + DPRINT("CreateGDIHandle: Out of available handles!!!\n"); + EngFreeMem( pObj ); + return 0; +} + +VOID FreeGDIHandle(ULONG Handle) +{ + if( Handle == 0 || Handle >= MAX_GDI_HANDLES ){ + DPRINT("FreeGDIHandle: invalid handle!!!!\n"); + return; + } + DPRINT("FreeGDIHandle: handle: %d\n", Handle); + EngFreeMem( GDIHandles[Handle].pEngObj ); + GDIHandles[Handle].pEngObj = NULL; +} + +PVOID AccessInternalObject(ULONG Handle) +{ + PENGOBJ pEngObj; + + if( Handle == 0 || Handle >= MAX_GDI_HANDLES ){ + DPRINT("AccessInternalObject: invalid handle: %d!!!!\n", Handle); + return NULL; + } + + pEngObj = GDIHandles[Handle].pEngObj; + return (PVOID)pEngObj; +} + +PVOID AccessUserObject(ULONG Handle) +{ + PENGOBJ pEngObj; + + if( Handle == 0 || Handle >= MAX_GDI_HANDLES ){ + DPRINT("AccessUserObject: invalid handle: %d!!!!\n", Handle); + return NULL; + } + + pEngObj = GDIHandles[Handle].pEngObj; + return (PVOID)( (PCHAR)pEngObj + sizeof( ENGOBJ ) ); +} + +ULONG AccessHandleFromUserObject(PVOID UserObject) +{ + PENGOBJ pEngObj; + ULONG Handle; + + if( !UserObject ) + return INVALID_HANDLE; + + pEngObj = (PENGOBJ)((PCHAR) UserObject - sizeof( ENGOBJ )); + Handle = pEngObj->hObj; + + if( Handle == 0 || Handle >= MAX_GDI_HANDLES ){ + DPRINT("AccessHandleFromUserObject: inv handle: %d, obj: %x!!!!\n", Handle, pEngObj); + return INVALID_HANDLE; + } + return Handle; +} + +PVOID AccessInternalObjectFromUserObject(PVOID UserObject) +{ + + return AccessInternalObject( AccessHandleFromUserObject( UserObject ) ); +} + +VOID InitEngHandleTable( void ) +{ + ULONG i; + for( i=1; i < MAX_GDI_HANDLES; i++ ){ + GDIHandles[ i ].pEngObj == NULL; + } +} diff --git a/subsys/win32k/eng/handle.h b/subsys/win32k/eng/handle.h new file mode 100644 index 0000000..44a9cff --- /dev/null +++ b/subsys/win32k/eng/handle.h @@ -0,0 +1,27 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Manage GDI Handle definitions + * FILE: subsys/win32k/eng/handle.h + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 29/8/1999: Created + */ +#ifndef __ENG_HANDLE_H +#define __ENG_HANDLE_H + +#include "objects.h" +#include + +typedef struct _GDI_HANDLE { + PENGOBJ pEngObj; +} GDI_HANDLE, *PGDI_HANDLE; + +#define INVALID_HANDLE 0 +#define MAX_GDI_HANDLES 4096 + +GDI_HANDLE GDIHandles[MAX_GDI_HANDLES]; + +#define ValidEngHandle( x ) (!( (x) == INVALID_HANDLE )) + +#endif diff --git a/subsys/win32k/eng/lineto.c b/subsys/win32k/eng/lineto.c new file mode 100644 index 0000000..ce09b70 --- /dev/null +++ b/subsys/win32k/eng/lineto.c @@ -0,0 +1,141 @@ +#include +#include "objects.h" +#include "../dib/dib.h" + +#include +#include +#include + +BOOL STDCALL +EngLineTo(SURFOBJ *Surface, + CLIPOBJ *Clip, + BRUSHOBJ *Brush, + LONG x1, + LONG y1, + LONG x2, + LONG y2, + RECTL *RectBounds, + MIX mix) +{ + BOOLEAN ret; + SURFGDI *SurfGDI; + LONG x, y, d, deltax, deltay, i, length, xchange, ychange, error, hx, vy; + + // These functions are assigned if we're working with a DIB + // The assigned functions depend on the bitsPerPixel of the DIB + PFN_DIB_PutPixel DIB_PutPixel; + PFN_DIB_HLine DIB_HLine; + PFN_DIB_VLine DIB_VLine; + + SurfGDI = (SURFGDI*)AccessInternalObjectFromUserObject(Surface); + + MouseSafetyOnDrawStart(Surface, SurfGDI, x1, y1, x2, y2); + + if(Surface->iType!=STYPE_BITMAP) + { + // Call the driver's DrvLineTo + ret = SurfGDI->LineTo(Surface, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); + MouseSafetyOnDrawEnd(Surface, SurfGDI); + return ret; + } + + // Assign DIB functions according to bytes per pixel + switch(BitsPerFormat(Surface->iBitmapFormat)) + { + case 1: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_1BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_1BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_1BPP_VLine; + break; + + case 4: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_4BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_4BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_4BPP_VLine; + break; + + case 24: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_24BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_24BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_24BPP_VLine; + break; + + default: + DbgPrint("EngLineTo: unsupported DIB format %u (bitsPerPixel:%u)\n", Surface->iBitmapFormat, + BitsPerFormat(Surface->iBitmapFormat)); + + MouseSafetyOnDrawEnd(Surface, SurfGDI); + return FALSE; + } + + // FIXME: Implement clipping + x=x1; + y=y1; + deltax=x2-x1; + deltay=y2-y1; + + if(deltax<0) + { + xchange=-1; + deltax=-deltax; + hx = x2; + } else + { + xchange=1; + hx = x1; + } + + if(deltay<0) + { + ychange=-1; + deltay=-deltay; + vy = y2; + } else + { + ychange=1; + vy = y1; + } + + if(y1==y2) { DIB_HLine(Surface, hx, hx + deltax, y1, Brush->iSolidColor); MouseSafetyOnDrawEnd(Surface, SurfGDI); return TRUE; } + if(x1==x2) { DIB_VLine(Surface, x1, vy, vy + deltay, Brush->iSolidColor); MouseSafetyOnDrawEnd(Surface, SurfGDI); return TRUE; } + + error=0; + i=0; + + if(deltaxiSolidColor); + y=y+ychange; + error=error+deltax; + + if(error>deltay) + { + x=x+xchange; + error=error-deltay; + } + i=i+1; + } + } else + { + length=deltax+1; + while(iiSolidColor); + x=x+xchange; + error=error+deltay; + if(error>deltax) + { + y=y+ychange; + error=error-deltax; + } + i=i+1; + } + } + + MouseSafetyOnDrawEnd(Surface, SurfGDI); + + return TRUE; +} diff --git a/subsys/win32k/eng/mem.c b/subsys/win32k/eng/mem.c new file mode 100644 index 0000000..ba88a64 --- /dev/null +++ b/subsys/win32k/eng/mem.c @@ -0,0 +1,53 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Driver Memory Management Functions + * FILE: subsys/win32k/eng/mem.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 3/7/1999: Created + */ + +#include +#include + +PVOID STDCALL +EngAllocMem(ULONG Flags, + ULONG MemSize, + ULONG Tag) +{ + PVOID newMem; + + newMem = ExAllocatePoolWithTag(NonPagedPool, MemSize, Tag); // FIXME: Use PagedPool when it is implemented + + if(Flags == FL_ZERO_MEMORY) + { + RtlZeroMemory(newMem, MemSize); + } + + return newMem; +} + +VOID STDCALL +EngFreeMem(PVOID Mem) +{ + ExFreePool(Mem); +} + +PVOID STDCALL +EngAllocUserMem(ULONG cj, ULONG tag) +{ + PVOID newMem = NULL; + NTSTATUS status; + + status = ZwAllocateVirtualMemory(NtCurrentProcess(), &newMem, 0, &cj, MEM_COMMIT, PAGE_READWRITE); + + if(status != STATUS_SUCCESS) return NULL; + return newMem; +} + +VOID STDCALL +EngFreeUserMem(PVOID pv) +{ + ZwFreeVirtualMemory (NtCurrentProcess(), &pv, 0, MEM_DECOMMIT); +} diff --git a/subsys/win32k/eng/mouse.c b/subsys/win32k/eng/mouse.c new file mode 100644 index 0000000..baecf52 --- /dev/null +++ b/subsys/win32k/eng/mouse.c @@ -0,0 +1,303 @@ +/* + * ReactOS kernel + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id$ + * + * PROJECT: ReactOS kernel + * PURPOSE: Mouse + * FILE: subsys/win32k/eng/mouse.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include "../../drivers/input/include/mouse.h" +#include "objects.h" +#include "include/msgqueue.h" + +/* GLOBALS *******************************************************************/ + +static BOOLEAN SafetySwitch = FALSE; +static BOOLEAN SafetySwitch2 = FALSE; +static BOOLEAN MouseEnabled = FALSE; +static LONG mouse_x, mouse_y; +static UINT mouse_width = 0, mouse_height = 0; + +static UCHAR DefaultCursor[256] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, + 0x43, 0x00, 0x00, 0x00, + 0x66, 0x00, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, + 0x7F, 0xC0, 0x00, 0x00, + 0x7F, 0x80, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3F, 0xFF, 0xFF, + 0xFE, 0x1F, 0xFF, 0xFF, + 0xFE, 0x1F, 0xFF, 0xFF, + 0xFC, 0x3F, 0xFF, 0xFF, + 0x7C, 0x3F, 0xFF, 0xFF, + 0x38, 0x7F, 0xFF, 0xFF, + 0x18, 0x7F, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x1F, 0xFF, 0xFF, + 0x00, 0x3F, 0xFF, 0xFF, + 0x00, 0x7F, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, + 0x01, 0xFF, 0xFF, 0xFF, + 0x03, 0xFF, 0xFF, 0xFF, + 0x07, 0xFF, 0xFF, 0xFF, + 0x0F, 0xFF, 0xFF, 0xFF, + 0x1F, 0xFF, 0xFF, 0xFF, + 0x3F, 0xFF, 0xFF, 0xFF}; + +/* FUNCTIONS *****************************************************************/ + +INT +MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, + LONG HazardY1, LONG HazardX2, LONG HazardY2) +/* + * FUNCTION: Notify the mouse driver that drawing is about to begin in + * a rectangle on a particular surface. + */ +{ + RECTL MouseRect; + LONG tmp; + + if (SurfObj == NULL) + { + return(FALSE); + } + + if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE) + { + return(FALSE); + } + + if (HazardX1 > HazardX2) + { + tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp; + } + if (HazardY1 > HazardY2) + { + tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp; + } + + if ((mouse_x + mouse_width >= HazardX1) && (mouse_x <= HazardX2) && + (mouse_y + mouse_height >= HazardY1) && (mouse_y <= HazardY2)) + { + SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect); + SafetySwitch = TRUE; + } + + /* Mouse is not allowed to move if GDI is busy drawing */ + SafetySwitch2 = TRUE; + + return(TRUE); +} + +INT +MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI) +/* + * FUNCTION: Notify the mouse driver that drawing has finished on a surface. + */ +{ + RECTL MouseRect; + + if (SurfObj == NULL) + { + return(FALSE); + } + + if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE) + { + return(FALSE); + } + + if (SafetySwitch) + { + SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); + SafetySwitch = FALSE; + } + + SafetySwitch2 = FALSE; + + return(TRUE); +} + +VOID +MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) +/* + * FUNCTION: Call by the mouse driver when input events occur. + */ +{ + ULONG i; + LONG mouse_cx = 0, mouse_cy = 0; + HDC hDC = W32kGetScreenDC(); + PDC dc; + PSURFOBJ SurfObj; + PSURFGDI SurfGDI; + RECTL MouseRect; + MSG Msg; + ULONG j; + LARGE_INTEGER LargeTickCount; + ULONG TickCount; + static ULONG ButtonsDown = 0; + const UINT MouseButtonDownMessage[3] = + {WM_RBUTTONDOWN, WM_MBUTTONDOWN, WM_LBUTTONDOWN}; + const UINT MouseButtonUpMessage[3] = + {WM_RBUTTONUP, WM_MBUTTONUP, WM_LBUTTONUP}; + const ULONG MouseButtonFlag[3] = {MK_RBUTTON, MK_MBUTTON, MK_LBUTTON}; + + KeQueryTickCount(&LargeTickCount); + TickCount = LargeTickCount.u.LowPart; + + if (hDC == 0) + { + return; + } + + dc = DC_HandleToPtr(hDC); + SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface); + SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface); + + /* Compile the total mouse movement change and dispatch button events. */ + for (i = 0; i < InputCount; i++) + { + mouse_cx += Data[i].LastX; + mouse_cy += Data[i].LastY; + + Msg.wParam = ButtonsDown; + Msg.lParam = MAKELPARAM(mouse_x + mouse_cx, mouse_y + mouse_cy); + Msg.message = WM_MOUSEMOVE; + Msg.time = TickCount; + Msg.pt.x = mouse_x + mouse_cx; + Msg.pt.y = mouse_y + mouse_cy; + MsqInsertSystemMessage(&Msg); + + for (j = 0; j < 3; j++) + { + ULONG Flag = MouseButtonFlag[j]; + if (Data[i].ButtonData & (1 << j) && !(ButtonsDown & Flag)) + { + ButtonsDown |= Flag; + + Msg.wParam = ButtonsDown; + Msg.message = MouseButtonDownMessage[j]; + MsqInsertSystemMessage(&Msg); + } + if (!(Data[i].ButtonData & (1 << j)) && (ButtonsDown & Flag)) + { + ButtonsDown &= ~Flag; + + Msg.wParam = ButtonsDown; + Msg.message = MouseButtonUpMessage[j]; + MsqInsertSystemMessage(&Msg); + } + } + } + + /* If the mouse moved then move the pointer. */ + if (mouse_cx != 0 || mouse_cy != 0) + { + mouse_x += mouse_cx; + mouse_y += mouse_cy; + + mouse_x = max(mouse_x, 0); + mouse_y = max(mouse_y, 0); + mouse_x = min(mouse_x, 620); + mouse_y = min(mouse_y, 460); + + if (SafetySwitch == FALSE && SafetySwitch2 == FALSE) + { + SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); + } + } +} + +VOID +EnableMouse(HDC hDisplayDC) +{ + PDC dc = DC_HandleToPtr(hDisplayDC); + PSURFOBJ SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface); + PSURFGDI SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface); + HBITMAP hMouseSurf; + PSURFOBJ MouseSurf; + SIZEL MouseSize; + RECTL MouseRect; + + /* Create the default mouse cursor. */ + mouse_width = 32; + mouse_height = 32; + MouseSize.cx = 32; + MouseSize.cy = 64; + hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, 0, DefaultCursor); + MouseSurf = (PSURFOBJ)AccessUserObject(hMouseSurf); + + /* Tell the display driver to set the pointer shape. */ + SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL, 0, 0, 320, 240, + &MouseRect, 0); + + mouse_x = 320; + mouse_y = 240; + MouseEnabled = TRUE; +} + diff --git a/subsys/win32k/eng/objects.h b/subsys/win32k/eng/objects.h new file mode 100644 index 0000000..23bb15c --- /dev/null +++ b/subsys/win32k/eng/objects.h @@ -0,0 +1,194 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Internal Objects + * FILE: subsys/win32k/eng/objects.h + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 21/8/1999: Created + */ +#ifndef __ENG_OBJECTS_H +#define __ENG_OBJECTS_H + +#include + +/* Structure of internal gdi objects that win32k manages for ddi engine: + |---------------------------------| + | EngObj | + |---------------------------------| + | Public part | + | accessed from engine | + |---------------------------------| + | Private part | + | managed by gdi | + |_________________________________| + +---------------------------------------------------------------------------*/ + +typedef struct _ENGOBJ { + ULONG hObj; + ULONG InternalSize; + ULONG UserSize; +}ENGOBJ, *PENGOBJ; + + + +typedef struct _BRUSHGDI { + ENGOBJ Header; + BRUSHOBJ BrushObj; +} BRUSHGDI; + +typedef struct _CLIPGDI { + ENGOBJ Header; + CLIPOBJ ClipObj; + /* ei what were these for? + ULONG NumRegionRects; + ULONG NumIntersectRects; + RECTL *RegionRects; + RECTL *IntersectRects; + */ + ULONG EnumPos; + ULONG EnumOrder; + ULONG EnumMax; + ENUMRECTS EnumRects; +} CLIPGDI, *PCLIPGDI; + +/*ei What is this for? */ +typedef struct _DRVFUNCTIONSGDI { + HDEV hdev; + DRVFN Functions[INDEX_LAST]; +} DRVFUNCTIONSGDI; + +typedef struct _FLOATGDI { + +} FLOATGDI; + +typedef struct _FONTGDI { + ENGOBJ Header; + FONTOBJ FontObj; + + LPCWSTR Filename; + FT_Face face; + TEXTMETRIC TextMetric; +} FONTGDI, *PFONTGDI; + +typedef struct _PALGDI { + ENGOBJ Header; + PALOBJ PalObj; + + ULONG Mode; // PAL_INDEXED, PAL_BITFIELDS, PAL_RGB, PAL_BGR + ULONG NumColors; + ULONG *IndexedColors; + ULONG RedMask; + ULONG GreenMask; + ULONG BlueMask; +} PALGDI, *PPALGDI; + +typedef struct _PATHGDI { + ENGOBJ Header; + PATHOBJ PathObj; +} PATHGDI; + +/*ei Fixme! Fix STROBJ */ +typedef struct _STRGDI { + ENGOBJ Header; + //STROBJ StrObj; +} STRGDI; + +typedef BOOL STDCALL (*PFN_BitBlt)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PCLIPOBJ, + PXLATEOBJ, PRECTL, PPOINTL, PPOINTL, + PBRUSHOBJ, PPOINTL, ROP4); + +typedef BOOL STDCALL (*PFN_TransparentBlt)(PSURFOBJ, PSURFOBJ, PCLIPOBJ, PXLATEOBJ, PRECTL, PRECTL, ULONG, ULONG); + +typedef BOOL STDCALL (*PFN_StretchBlt)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PCLIPOBJ, + PXLATEOBJ, PCOLORADJUSTMENT, PPOINTL, + PRECTL, PRECTL, PPOINT, ULONG); + +typedef BOOL STDCALL (*PFN_TextOut)(PSURFOBJ, PSTROBJ, PFONTOBJ, PCLIPOBJ, + PRECTL, PRECTL, PBRUSHOBJ, PBRUSHOBJ, + PPOINTL, MIX); + +typedef BOOL STDCALL (*PFN_Paint)(PSURFOBJ, PCLIPOBJ, PBRUSHOBJ, PPOINTL, MIX); + +typedef BOOL STDCALL (*PFN_StrokePath)(PSURFOBJ, PPATHOBJ, PCLIPOBJ, PXFORMOBJ, + PBRUSHOBJ, PPOINTL, PLINEATTRS, MIX); + +typedef BOOL STDCALL (*PFN_FillPath)(PSURFOBJ, PPATHOBJ, PCLIPOBJ, PBRUSHOBJ, + PPOINTL, MIX, ULONG); + +typedef BOOL STDCALL (*PFN_StrokeAndFillPath)(PSURFOBJ, PPATHOBJ, PCLIPOBJ, + PXFORMOBJ, PBRUSHOBJ, PLINEATTRS, PBRUSHOBJ, + PPOINTL, MIX, ULONG); + +typedef BOOL STDCALL (*PFN_LineTo)(PSURFOBJ, PCLIPOBJ, PBRUSHOBJ, + LONG, LONG, LONG, LONG, PRECTL, MIX); + +typedef BOOL STDCALL (*PFN_CopyBits)(PSURFOBJ, PSURFOBJ, PCLIPOBJ, + PXLATEOBJ, PRECTL, PPOINTL); + +typedef VOID STDCALL (*PFN_Synchronize)(DHPDEV, PRECTL); + +typedef VOID STDCALL (*PFN_MovePointer)(PSURFOBJ, LONG, LONG, PRECTL); + +typedef VOID STDCALL (*PFN_SetPointerShape)(PSURFOBJ, PSURFOBJ, PSURFOBJ, PXLATEOBJ, + LONG, LONG, LONG, LONG, PRECTL, ULONG); + +typedef HBITMAP STDCALL (*PFN_CreateDeviceBitmap)(DHPDEV, SIZEL, ULONG); + +typedef BOOL STDCALL (*PFN_SetPalette)(DHPDEV, PALOBJ*, ULONG, ULONG, ULONG); + +typedef struct _SURFGDI { + ENGOBJ Header; + SURFOBJ SurfObj; + + INT BitsPerPixel; + + PFN_BitBlt BitBlt; + PFN_TransparentBlt TransparentBlt; + PFN_StretchBlt StretchBlt; + PFN_TextOut TextOut; + PFN_Paint Paint; + PFN_StrokePath StrokePath; + PFN_FillPath FillPath; + PFN_StrokeAndFillPath StrokeAndFillPath; + PFN_LineTo LineTo; + PFN_CopyBits CopyBits; + PFN_Synchronize Synchronize; + BOOL SynchronizeAccess; + PFN_CreateDeviceBitmap CreateDeviceBitmap; + PFN_SetPalette SetPalette; + PFN_MovePointer MovePointer; + PFN_SetPointerShape SetPointerShape; +} SURFGDI, *PSURFGDI; + +typedef struct _XFORMGDI { + ENGOBJ Header; + /* XFORMOBJ has no public members */ +} XFORMGDI; + +typedef struct _XLATEGDI { + ENGOBJ Header; + XLATEOBJ XlateObj; + HPALETTE DestPal; + HPALETTE SourcePal; + + ULONG *translationTable; +} XLATEGDI; + +// List of GDI objects +// FIXME: Make more dynamic + +#define MAX_GDI_BRUSHES 255 +#define MAX_GDI_CLIPS 255 +#define MAX_GDI_DRVFUNCTIONS 16 +#define MAX_GDI_FLOATS 255 +#define MAX_GDI_FONTS 255 +#define MAX_GDI_PALS 255 +#define MAX_GDI_PATHS 255 +#define MAX_GDI_STRS 255 +#define MAX_GDI_SURFS 255 +#define MAX_GDI_XFORMS 255 +#define MAX_GDI_XLATES 255 + +#endif //__ENG_OBJECTS_H diff --git a/subsys/win32k/eng/paint.c b/subsys/win32k/eng/paint.c new file mode 100644 index 0000000..a500969 --- /dev/null +++ b/subsys/win32k/eng/paint.c @@ -0,0 +1,162 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Driver Paint Functions + * FILE: subsys/win32k/eng/paint.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 3/7/1999: Created + */ + +#include +#include +#include +#include + +#include "objects.h" +#include +#include "../dib/dib.h" + +#include "brush.h" +#include "clip.h" + +//#define NDEBUG +#include + +BOOL FillSolid(SURFOBJ *Surface, PRECTL pRect, ULONG iColor) +{ + // These functions are assigned if we're working with a DIB + // The assigned functions depend on the bitsPerPixel of the DIB + PFN_DIB_PutPixel DIB_PutPixel; + PFN_DIB_HLine DIB_HLine; + PFN_DIB_VLine DIB_VLine; + LONG y; + ULONG x, LineWidth, leftOfBitmap; + SURFGDI *SurfaceGDI; + + SurfaceGDI = (SURFGDI*)AccessInternalObjectFromUserObject(Surface); + MouseSafetyOnDrawStart(Surface, SurfaceGDI, pRect->left, pRect->top, pRect->right, pRect->bottom); +/* + if(Surface->iType!=STYPE_BITMAP) + { + // Call the driver's DrvLineTo + ret = SurfGDI->LineTo(Surface, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); + MouseSafetyOnDrawEnd(Surface, SurfGDI); + return ret; + } +*/ + // Assign DIB functions according to bytes per pixel + DPRINT("BPF: %d\n", BitsPerFormat(Surface->iBitmapFormat)); + switch(BitsPerFormat(Surface->iBitmapFormat)) + { + case 4: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_4BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_4BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_4BPP_VLine; + break; + + case 24: + DIB_PutPixel = (PFN_DIB_PutPixel)DIB_24BPP_PutPixel; + DIB_HLine = (PFN_DIB_HLine)DIB_24BPP_HLine; + DIB_VLine = (PFN_DIB_VLine)DIB_24BPP_VLine; + break; + + default: + DbgPrint("EngLineTo: unsupported DIB format %u (bitsPerPixel:%u)\n", Surface->iBitmapFormat, + BitsPerFormat(Surface->iBitmapFormat)); + + MouseSafetyOnDrawEnd(Surface, SurfaceGDI); + return FALSE; + } + + LineWidth = pRect->right - pRect->left; + DPRINT(" LineWidth: %d, top: %d, bottom: %d\n", LineWidth, pRect->top, pRect->bottom); + for (y = pRect->top; y < pRect->bottom; y++) + { + //EngLineTo(Surface, SurfaceGDI, Dimensions->left, y, LineWidth, iColor); + DIB_HLine(Surface, pRect->left, pRect->right, y, iColor); + } + MouseSafetyOnDrawEnd(Surface, SurfaceGDI); + + return TRUE; +} + +BOOL EngPaintRgn(SURFOBJ *Surface, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix, + BRUSHINST *BrushInst, POINTL *BrushPoint) +{ + RECT_ENUM RectEnum; + BOOL EnumMore; + + DPRINT("ClipRegion->iMode:%d, ClipRegion->iDComplexity: %d\n Color: %d", ClipRegion->iMode, ClipRegion->iDComplexity, iColor); + switch(ClipRegion->iMode) { + + case TC_RECTANGLES: + + /* Rectangular clipping can be handled without enumeration. + Note that trivial clipping is not possible, since the clipping + region defines the area to fill */ + + if (ClipRegion->iDComplexity == DC_RECT) + { + FillSolid(Surface, &(ClipRegion->rclBounds), iColor); + } else { + + /* Enumerate all the rectangles and draw them */ + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT); + + do { + EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum); + FillSolid(Surface, &RectEnum.arcl[0], iColor); + } while (EnumMore); + } + + return(TRUE); + + default: + return(FALSE); + } +} + +BOOL STDCALL +EngPaint(IN SURFOBJ *Surface, + IN CLIPOBJ *ClipRegion, + IN BRUSHOBJ *Brush, + IN POINTL *BrushOrigin, + IN MIX Mix) +{ + BOOLEAN ret; + + // FIXME: We only support a brush's solid color attribute + ret = EngPaintRgn(Surface, ClipRegion, Brush->iSolidColor, Mix, NULL, BrushOrigin); + + return ret; +} + +BOOL STDCALL +IntEngPaint(IN SURFOBJ *Surface, + IN CLIPOBJ *ClipRegion, + IN BRUSHOBJ *Brush, + IN POINTL *BrushOrigin, + IN MIX Mix) +{ + SURFGDI *SurfGDI; + BOOL ret; + + // Is the surface's Paint function hooked? + SurfGDI = (SURFGDI*)AccessInternalObjectFromUserObject(Surface); + + DPRINT("SurfGDI type: %d, sgdi paint: %x\n", Surface->iType, SurfGDI->Paint); + if((Surface->iType!=STYPE_BITMAP) && (SurfGDI->Paint!=NULL)) + { + // Call the driver's DrvPaint + MouseSafetyOnDrawStart(Surface, SurfGDI, ClipRegion->rclBounds.left, + ClipRegion->rclBounds.top, ClipRegion->rclBounds.right, + ClipRegion->rclBounds.bottom); + + ret = SurfGDI->Paint(Surface, ClipRegion, Brush, BrushOrigin, Mix); + MouseSafetyOnDrawEnd(Surface, SurfGDI); + return ret; + } + return EngPaint( Surface, ClipRegion, Brush, BrushOrigin, Mix ); + +} diff --git a/subsys/win32k/eng/palette.c b/subsys/win32k/eng/palette.c new file mode 100644 index 0000000..327cbe3 --- /dev/null +++ b/subsys/win32k/eng/palette.c @@ -0,0 +1,82 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Palette Functions + * FILE: subsys/win32k/eng/palette.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 11/7/1999: Created + */ + +#include +#include +#include "handle.h" + +//#define NDEBUG +#include + +HPALETTE STDCALL +EngCreatePalette(ULONG Mode, + ULONG NumColors, + PULONG *Colors, // FIXME: This was implemented with ULONG *Colors!! + ULONG Red, + ULONG Green, + ULONG Blue) +{ + HPALETTE NewPalette; + PALGDI *PalGDI; + + NewPalette = (HPALETTE)CreateGDIHandle(sizeof(PALGDI), sizeof(PALOBJ)); + if( !ValidEngHandle( NewPalette ) ) + return 0; + + PalGDI = (PALGDI*) AccessInternalObject( NewPalette ); + ASSERT( PalGDI ); + + PalGDI->Mode = Mode; + + if(Colors != NULL) + { + PalGDI->IndexedColors = ExAllocatePool(NonPagedPool, sizeof(PALETTEENTRY) * NumColors); + RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors); + } + + if(Mode==PAL_INDEXED) + { + PalGDI->NumColors = NumColors; + } else + if(Mode==PAL_BITFIELDS) + { + PalGDI->RedMask = Red; + PalGDI->GreenMask = Green; + PalGDI->BlueMask = Blue; + } + + return NewPalette; +} + +BOOL STDCALL +EngDeletePalette(IN HPALETTE Palette) +{ + FreeGDIHandle((ULONG)Palette); + return TRUE; +} + +ULONG STDCALL +PALOBJ_cGetColors(PALOBJ *PalObj, + ULONG Start, + ULONG Colors, + ULONG *PaletteEntry) +{ + ULONG i, entry; + PALGDI *PalGDI; + + PalGDI = (PALGDI*)AccessInternalObjectFromUserObject(PalObj); + + for(i=Start; iIndexedColors[i]; + } + + return Colors; +} diff --git a/subsys/win32k/eng/surface.c b/subsys/win32k/eng/surface.c new file mode 100644 index 0000000..3ec0967 --- /dev/null +++ b/subsys/win32k/eng/surface.c @@ -0,0 +1,245 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Driver Surace Functions + * FILE: subsys/win32k/eng/surface.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 3/7/1999: Created + * 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED) + * TESTING TO BE DONE: + * - Create a GDI bitmap with all formats, perform all drawing operations on them, render to VGA surface + * refer to \test\microwin\src\engine\devdraw.c for info on correct pixel plotting for various formats + */ + +#include +#include +#include +#include +#include +#include "handle.h" + +//#define NDEBUG +#include + +INT BitsPerFormat(ULONG Format) +{ + switch(Format) + { + case BMF_1BPP: return 1; + case BMF_4BPP: + case BMF_4RLE: return 4; + case BMF_8BPP: + case BMF_8RLE: return 8; + case BMF_16BPP: return 16; + case BMF_24BPP: return 24; + case BMF_32BPP: return 32; + default: return 0; + } +} + +ULONG BitmapFormat(WORD Bits, DWORD Compression) +{ + switch(Compression) + { + case BI_RGB: + switch(Bits) + { + case 1: return BMF_1BPP; + case 4: return BMF_4BPP; + case 8: return BMF_8BPP; + case 16: return BMF_16BPP; + case 24: return BMF_24BPP; + case 32: return BMF_32BPP; + } + + case BI_RLE4: return BMF_4RLE; + case BI_RLE8: return BMF_8RLE; + + default: return 0; + } +} + +VOID InitializeHooks(SURFGDI *SurfGDI) +{ + SurfGDI->BitBlt = NULL; + SurfGDI->CopyBits = NULL; + SurfGDI->CreateDeviceBitmap = NULL; + SurfGDI->SetPalette = NULL; + SurfGDI->TransparentBlt = NULL; +} + +HBITMAP STDCALL +EngCreateDeviceBitmap(IN DHSURF dhsurf, + IN SIZEL Size, + IN ULONG Format) +{ + HBITMAP NewBitmap; + SURFOBJ *SurfObj; + + NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL); + SurfObj = (PVOID)AccessUserObject((ULONG)NewBitmap); + SurfObj->dhpdev = dhsurf; + + return NewBitmap; +} + +HBITMAP STDCALL +EngCreateBitmap(IN SIZEL Size, + IN LONG Width, + IN ULONG Format, + IN ULONG Flags, + IN PVOID Bits) +{ + HBITMAP NewBitmap; + SURFOBJ *SurfObj; + SURFGDI *SurfGDI; + + + NewBitmap = (PVOID)CreateGDIHandle(sizeof(SURFGDI), sizeof(SURFOBJ)); + if( !ValidEngHandle( NewBitmap ) ) + return 0; + + SurfObj = (SURFOBJ*) AccessUserObject( NewBitmap ); + SurfGDI = (SURFGDI*) AccessInternalObject( NewBitmap ); + ASSERT( SurfObj ); + ASSERT( SurfGDI ); + + InitializeHooks(SurfGDI); + + SurfGDI->BitsPerPixel = BitsPerFormat(Format); + SurfObj->lDelta = Width; + SurfObj->cjBits = SurfObj->lDelta * Size.cy; + + if(Bits!=NULL) + { + SurfObj->pvBits = Bits; + } else + { + if(Flags & BMF_USERMEM) + { + SurfObj->pvBits = EngAllocUserMem(SurfObj->cjBits, 0); + } else { + if(Flags & BMF_NOZEROINIT) + { + SurfObj->pvBits = EngAllocMem(0, SurfObj->cjBits, 0); + } else { + SurfObj->pvBits = EngAllocMem(FL_ZERO_MEMORY, SurfObj->cjBits, 0); + } + } + } + + SurfObj->dhsurf = 0; // device managed surface + SurfObj->hsurf = 0; + SurfObj->sizlBitmap = Size; + SurfObj->iBitmapFormat = Format; + SurfObj->iType = STYPE_BITMAP; + + // Use flags to determine bitmap type -- TOP_DOWN or whatever + + return NewBitmap; +} + +HSURF STDCALL +EngCreateDeviceSurface(IN DHSURF dhsurf, + IN SIZEL Size, + IN ULONG Format) +{ + HSURF NewSurface; + SURFOBJ *SurfObj; + SURFGDI *SurfGDI; + + NewSurface = (HSURF)CreateGDIHandle(sizeof( SURFGDI ), sizeof( SURFOBJ )); + if( !ValidEngHandle( NewSurface ) ) + return 0; + + SurfObj = (SURFOBJ*) AccessUserObject( NewSurface ); + SurfGDI = (SURFGDI*) AccessInternalObject( NewSurface ); + ASSERT( SurfObj ); + ASSERT( SurfGDI ); + + InitializeHooks(SurfGDI); + + SurfGDI->BitsPerPixel = BitsPerFormat(Format); + SurfObj->dhsurf = dhsurf; + SurfObj->hsurf = dhsurf; // FIXME: Is this correct?? + SurfObj->sizlBitmap = Size; + SurfObj->iBitmapFormat = Format; + SurfObj->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)); + SurfObj->iType = STYPE_DEVICE; + + return NewSurface; +} + +PFN DriverFunction(DRVENABLEDATA *DED, ULONG DriverFunc) +{ + ULONG i; + + for(i=0; ic; i++) + { + if(DED->pdrvfn[i].iFunc == DriverFunc) + return DED->pdrvfn[i].pfn; + } + return NULL; +} + +BOOL STDCALL +EngAssociateSurface(IN HSURF Surface, + IN HDEV Dev, + IN ULONG Hooks) +{ + SURFOBJ *SurfObj; + SURFGDI *SurfGDI; + GDIDEVICE* Device; + + Device = (GDIDEVICE*)Dev; + + SurfGDI = (PVOID)AccessInternalObject((ULONG)Surface); + SurfObj = (PVOID)AccessUserObject((ULONG)Surface); + + // Associate the hdev + SurfObj->hdev = Dev; + + // Hook up specified functions + if(Hooks & HOOK_BITBLT) SurfGDI->BitBlt = Device->DriverFunctions.BitBlt; + if(Hooks & HOOK_TRANSPARENTBLT) SurfGDI->TransparentBlt = Device->DriverFunctions.TransparentBlt; + if(Hooks & HOOK_STRETCHBLT) SurfGDI->StretchBlt = (PFN_StretchBlt)Device->DriverFunctions.StretchBlt; + if(Hooks & HOOK_TEXTOUT) SurfGDI->TextOut = Device->DriverFunctions.TextOut; + if(Hooks & HOOK_PAINT) SurfGDI->Paint = Device->DriverFunctions.Paint; + if(Hooks & HOOK_STROKEPATH) SurfGDI->StrokePath = Device->DriverFunctions.StrokePath; + if(Hooks & HOOK_FILLPATH) SurfGDI->FillPath = Device->DriverFunctions.FillPath; + if(Hooks & HOOK_STROKEANDFILLPATH) SurfGDI->StrokeAndFillPath = Device->DriverFunctions.StrokeAndFillPath; + if(Hooks & HOOK_LINETO) SurfGDI->LineTo = Device->DriverFunctions.LineTo; + if(Hooks & HOOK_COPYBITS) SurfGDI->CopyBits = Device->DriverFunctions.CopyBits; + if(Hooks & HOOK_SYNCHRONIZE) SurfGDI->Synchronize = Device->DriverFunctions.Synchronize; + if(Hooks & HOOK_SYNCHRONIZEACCESS) SurfGDI->SynchronizeAccess = TRUE; + + SurfGDI->CreateDeviceBitmap = Device->DriverFunctions.CreateDeviceBitmap; + SurfGDI->SetPalette = Device->DriverFunctions.SetPalette; + SurfGDI->MovePointer = Device->DriverFunctions.MovePointer; + SurfGDI->SetPointerShape = (PFN_SetPointerShape)Device->DriverFunctions.SetPointerShape; + + return TRUE; +} + +BOOL STDCALL +EngDeleteSurface(IN HSURF Surface) +{ + FreeGDIHandle((ULONG)Surface); + return TRUE; +} + +BOOL STDCALL +EngEraseSurface(SURFOBJ *Surface, + RECTL *Rect, + ULONG iColor) +{ + return FillSolid(Surface, Rect, iColor); +} + +SURFOBJ * STDCALL +EngLockSurface(IN HSURF Surface) +{ + // FIXME: Call GDI_LockObject (see subsys/win32k/objects/gdi.c) + return (SURFOBJ*)AccessUserObject((ULONG)Surface); +} diff --git a/subsys/win32k/eng/transblt.c b/subsys/win32k/eng/transblt.c new file mode 100644 index 0000000..9af39f6 --- /dev/null +++ b/subsys/win32k/eng/transblt.c @@ -0,0 +1,94 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI TransparentBlt Function + * FILE: subsys/win32k/eng/transblt.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 4/6/2001: Created + */ + +#include +#include +#include +#include +#include +#include + +#include "brush.h" +#include "clip.h" +#include "objects.h" + +#include + +BOOL STDCALL +EngTransparentBlt(PSURFOBJ Dest, + PSURFOBJ Source, + PCLIPOBJ Clip, + PXLATEOBJ ColorTranslation, + PRECTL DestRect, + PRECTL SourceRect, + ULONG TransparentColor, + ULONG Reserved) +{ + PSURFGDI DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest), + SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source); + HSURF hTemp; + PSURFOBJ TempSurf; + POINTL TempPoint, SourcePoint; + RECTL TempRect; + SIZEL TempSize; + BOOLEAN ret; + LONG dx, dy, sx, sy; + + dx = abs(DestRect->right - DestRect->left); + dy = abs(DestRect->bottom - DestRect->top); + + sx = abs(SourceRect->right - SourceRect->left); + sy = abs(SourceRect->bottom - SourceRect->top); + + if(sxleft, SourceRect->top, SourceRect->right, SourceRect->bottom); + MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); + + if(DestGDI->TransparentBlt != NULL) + { + // The destination is device managed, therefore get the source into a format compatible surface + TempPoint.x = 0; + TempPoint.y = 0; + TempRect.top = 0; + TempRect.left = 0; + TempRect.bottom = dy; + TempRect.right = dx; + TempSize.cx = TempRect.right; + TempSize.cy = TempRect.bottom; + + hTemp = EngCreateBitmap(TempSize, + DIB_GetDIBWidthBytes(dx, BitsPerFormat(Dest->iBitmapFormat)), + Dest->iBitmapFormat, 0, NULL); + TempSurf = (PSURFOBJ)AccessUserObject((ULONG)hTemp); + + SourcePoint.x = SourceRect->left; + SourcePoint.y = SourceRect->top; + + // FIXME: Skip creating a TempSurf if we have the same BPP and palette + EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, &SourcePoint, NULL, NULL, NULL, 0); + + ret = DestGDI->TransparentBlt(Dest, TempSurf, Clip, NULL, DestRect, SourceRect, + TransparentColor, Reserved); + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return ret; + } + + // Simulate a transparent blt + + MouseSafetyOnDrawEnd(Source, SourceGDI); + MouseSafetyOnDrawEnd(Dest, DestGDI); + + return TRUE; +} diff --git a/subsys/win32k/eng/xlate.c b/subsys/win32k/eng/xlate.c new file mode 100644 index 0000000..3022c56 --- /dev/null +++ b/subsys/win32k/eng/xlate.c @@ -0,0 +1,287 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GDI Color Translation Functions + * FILE: subsys/win32k/eng/xlate.c + * PROGRAMER: Jason Filby + * REVISION HISTORY: + * 8/20/1999: Created + */ + +// TODO: Cache XLATEOBJs that are created by EngCreateXlate by checking if the given palettes match a cached list + +#include +#include +#include + +#include +#include "handle.h" + +//#define NDEBUG +#include + +ULONG CCMLastSourceColor = 0, CCMLastColorMatch = 0; + +ULONG RGBtoULONG(BYTE Red, BYTE Green, BYTE Blue) +{ + return ((Red & 0xff) << 16) | ((Green & 0xff) << 8) | (Blue & 0xff); +} + +ULONG BGRtoULONG(BYTE Blue, BYTE Green, BYTE Red) +{ + return ((Blue & 0xff) << 16) | ((Green & 0xff) << 8) | (Red & 0xff); +} + +INT abs(INT nm) +{ + if(nm<0) + { + return nm * -1; + } else + { + return nm; + } +} + +// FIXME: If the caller knows that the destinations are indexed and not RGB +// then we should cache more than one value. Same with the source. + +// Takes indexed palette and a +ULONG ClosestColorMatch(ULONG SourceColor, ULONG *DestColors, + ULONG NumColors) +{ + PVIDEO_CLUTDATA cSourceColor; + PVIDEO_CLUTDATA cDestColors; + LONG idx = 0, i, rt; + ULONG cxRed, cxGreen, cxBlue, BestMatch = 16777215; + + // Simple cache -- only one value because we don't want to waste time + // if the colors aren't very sequential + + if(SourceColor == CCMLastSourceColor) + { + return CCMLastColorMatch; + } + + cSourceColor = (PVIDEO_CLUTDATA)&SourceColor; + for (i=0; iRed - cDestColors->Red) ^ 2; + cxGreen = abs(cSourceColor->Green - cDestColors->Green) ^ 2; + cxBlue = abs(cSourceColor->Blue - cDestColors->Blue) ^ 2; + + rt = /* sqrt */ (cxRed + cxGreen + cxBlue); + + if(rt<=BestMatch) + { + idx = i; + BestMatch = rt; + } + } + + CCMLastSourceColor = SourceColor; + CCMLastColorMatch = idx; + + return idx; +} + +VOID IndexedToIndexedTranslationTable(ULONG *TranslationTable, + PALGDI *PalDest, PALGDI *PalSource) +{ + ULONG i; + + for(i=0; iNumColors; i++) + { + TranslationTable[i] = ClosestColorMatch(PalSource->IndexedColors[i], PalDest->IndexedColors, PalDest->NumColors); + } +} + +XLATEOBJ *EngCreateXlate(USHORT DestPalType, USHORT SourcePalType, + HPALETTE PaletteDest, HPALETTE PaletteSource) +{ + // FIXME: Add support for BGR conversions + + HPALETTE NewXlate; + XLATEOBJ *XlateObj; + XLATEGDI *XlateGDI; + PALGDI *SourcePalGDI, *DestPalGDI; + ULONG IndexedColors; + + NewXlate = (HPALETTE)CreateGDIHandle(sizeof( XLATEGDI ), sizeof( XLATEOBJ )); + if( !ValidEngHandle( NewXlate ) ) + return NULL; + + XlateObj = (XLATEOBJ*) AccessUserObject( NewXlate ); + XlateGDI = (XLATEGDI*) AccessInternalObject( NewXlate ); + ASSERT( XlateObj ); + ASSERT( XlateGDI ); + + if(SourcePalType == PAL_INDEXED) + SourcePalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteSource); + if(DestPalType == PAL_INDEXED) + DestPalGDI = (PALGDI*)AccessInternalObject((ULONG)PaletteDest); + + XlateObj->iSrcType = SourcePalType; + XlateObj->iDstType = DestPalType; + + // Store handles of palettes in internal Xlate GDI object (or NULLs) + XlateGDI->DestPal = PaletteDest; + XlateGDI->SourcePal = PaletteSource; + + XlateObj->flXlate = 0; + + // If source and destination palettes are the same or if they're RGB/BGR + if( (PaletteDest == PaletteSource) || + ((DestPalType == PAL_RGB) && (SourcePalType == PAL_RGB)) || + ((DestPalType == PAL_BGR) && (SourcePalType == PAL_BGR)) ) + { + XlateObj->flXlate |= XO_TRIVIAL; + return XlateObj; + } + + // Prepare the translation table + if( (SourcePalType == PAL_INDEXED) || (SourcePalType == PAL_RGB) ) + { + XlateObj->flXlate |= XO_TABLE; + if ((SourcePalType == PAL_INDEXED) && (DestPalType == PAL_INDEXED)) + { + if(SourcePalGDI->NumColors > DestPalGDI->NumColors) + { + IndexedColors = SourcePalGDI->NumColors; + } else + IndexedColors = DestPalGDI->NumColors; + } + else if (SourcePalType == PAL_INDEXED) { IndexedColors = SourcePalGDI->NumColors; } + else if (DestPalType == PAL_INDEXED) { IndexedColors = DestPalGDI->NumColors; } + + XlateGDI->translationTable = EngAllocMem(FL_ZERO_MEMORY, sizeof(ULONG)*IndexedColors, 0); + } + + // Source palette is indexed + if(XlateObj->iSrcType == PAL_INDEXED) + { + if(XlateObj->iDstType == PAL_INDEXED) + { + // Converting from indexed to indexed + IndexedToIndexedTranslationTable(XlateGDI->translationTable, DestPalGDI, SourcePalGDI); + } else + if(XlateObj->iDstType == PAL_RGB) + { + // FIXME: Is this necessary? I think the driver has to call this + // function anyways if pulXlate is NULL and Source is PAL_INDEXED + + // Converting from indexed to RGB + + XLATEOBJ_cGetPalette(XlateObj, XO_SRCPALETTE, + SourcePalGDI->NumColors, + XlateGDI->translationTable); + } + + XlateObj->pulXlate = XlateGDI->translationTable; + } + + // Source palette is RGB + if(XlateObj->iSrcType == PAL_RGB) + { + if(XlateObj->iDstType == PAL_INDEXED) + { + // FIXME: Is this necessary? I think the driver has to call this + // function anyways if pulXlate is NULL and Dest is PAL_INDEXED + + // Converting from RGB to indexed + XLATEOBJ_cGetPalette(XlateObj, XO_DESTPALETTE, DestPalGDI->NumColors, XlateGDI->translationTable); + } + } + + // FIXME: Add support for XO_TO_MONO + return XlateObj; +} + +VOID EngDeleteXlate(XLATEOBJ *XlateObj) +{ + HPALETTE HXlate = (HPALETTE)AccessHandleFromUserObject(XlateObj); + XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObject((ULONG)HXlate); + + if(XlateGDI->translationTable!=NULL) + { + EngFreeMem(XlateGDI->translationTable); + } + + FreeGDIHandle((ULONG)HXlate); +} + +ULONG * STDCALL +XLATEOBJ_piVector(XLATEOBJ *XlateObj) +{ + XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj); + + if(XlateObj->iSrcType == PAL_INDEXED) + { + return XlateGDI->translationTable; + } + + return NULL; +} + +ULONG STDCALL +XLATEOBJ_iXlate(XLATEOBJ *XlateObj, + ULONG Color) +{ + PALGDI *PalGDI; + XLATEGDI *XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj); + + // Return the original color if there's no color translation object + if(!XlateObj) return Color; + + if(XlateObj->flXlate & XO_TRIVIAL) + { + return Color; + } else + if(XlateObj->iSrcType == PAL_RGB) + { + // FIXME: should we cache colors used often? + // FIXME: won't work if destination isn't indexed + + // Extract the destination palette + PalGDI = (PALGDI*)AccessInternalObject((ULONG)XlateGDI->DestPal); + + // Return closest match for the given RGB color + return ClosestColorMatch(Color, PalGDI->IndexedColors, PalGDI->NumColors); + } else + if(XlateObj->iSrcType == PAL_INDEXED) + { + return XlateGDI->translationTable[Color]; + } + + return 0; +} + +ULONG STDCALL +XLATEOBJ_cGetPalette(XLATEOBJ *XlateObj, + ULONG PalOutType, + ULONG cPal, + ULONG *OutPal) +{ + ULONG i; + HPALETTE HPal; + XLATEGDI *XlateGDI; + PALGDI *PalGDI; + + XlateGDI = (XLATEGDI*)AccessInternalObjectFromUserObject(XlateObj); + + if(PalOutType == XO_SRCPALETTE) + { + HPal = XlateGDI->SourcePal; + } else + if(PalOutType == XO_DESTPALETTE) + { + HPal = XlateGDI->DestPal; + } + + PalGDI = (PALGDI*)AccessInternalObject((ULONG)HPal); + RtlCopyMemory(OutPal, PalGDI->IndexedColors, sizeof(ULONG)*cPal); + + return i; +} diff --git a/subsys/win32k/freetype/.cvsignore b/subsys/win32k/freetype/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/CHANGES b/subsys/win32k/freetype/CHANGES new file mode 100644 index 0000000..d9d5816 --- /dev/null +++ b/subsys/win32k/freetype/CHANGES @@ -0,0 +1,904 @@ +LATEST CHANGES + + - deactivated the trueType bytecode interpreter by default + + - deactivated the "src/type1" font driver. Now "src/type1z" is + used by default.. + + - updates to the build system. We now compile the library correctly + under Unix system through "configure" which is automatically called + on the first "make" invocation. + + - added the auto-hinting module !!. Fixing some bugs here and there.. + + - found some bugs in the composite loader (seac) of the Type1-based + font drivers.. + + - renamed the directory "freetype2/config" to "freetype2/builds" and + updated all relevant files.. + + - found a memory leak in the "type1" driver + + - incorporated Tom's patches to support flex operators correctly + in OpenType/CFF fonts.. Now all I need is to support pure CFF + and CEF fonts to be done with this driver.. :-) + + - added the Windows FNT/FON driver in "src/winfonts". For now, + it always "simulates" a Unicode charmap, so it shouldn't be + considered completed right now.. + + It's there to be more a proof of concept than anything else + anyway. The driver is a single C source file, that compiles + to 3 Kb of code.. + + I'm still working on the PCF/BDF drivers.. but I'm too lazy + to finish them now.. + + + - CHANGES TO THE HIGH-LEVEL API + + o FT_Get_Kerning has a new parameter that allows you to select + the coordinates of the kerning vector ( font units, scaled, + scaled + grid-fitted ). + + o the outline functions are now in and not + part of anymore + + o now contains declarations for + FT_New_Library, FT_Done_Library, FT_Add_Default_Modules + + o the so-called convenience functions have moved from "ftoutln.c" + to "ftglyph.c", and are thus available with this optional component + of the library. They are declared in now.. + + o anti-aliased rendering is now the default for FT_Render_Glyph + (i.e. corresponds to render_mode == 0 == ft_render_mode_normal). + To generate a monochrome bitmap, use ft_render_mode_mono, or the + FT_LOAD_MONOCHROME flag in FT_Load_Glyph/FT_Load_Char. + + FT_LOAD_ANTI_ALIAS is still defined, but values to 0. + + o now include , + solving a few headaches :-) + + o the type FT_GlyphSlotRec has now a "library" field. + + + + - CHANGES TO THE "ftglyph.h" API + + This API has been severely modified in order to make it simpler, + clearer, and more efficient. It certainly now looks like a real + "glyph factory" object, and allows client applications to manage + (i.e. transform, bbox and render) glyph images without ever knowing + their original format. + + - added support for CID-keyed fonts to the CFF driver. + maybe support for pure CFF + CEF fonts should come in ?? + + + - cleaned up source code in order to avoid two functions with the + same name. Also changed the names of the files in "type1z" from + "t1XXXX" to "z1XXXX" in order to avoid any conflicts. + + "make multi" now works well :-) + + Also removed the use of "cidafm" for now, even if the source files + are still there. This functionality will certainly go into a specific + module.. + + + + - ADDED SUPPORT FOR THE AUTO-HINTER + + It works :-) I have a demo program which simply is a copy of "ftview" + that does a FT_Add_Module( library, &autohinter_module_class ) after + library initialisation, and Type 1 & OpenType/CFF fonts are now hinted. + + CID fonts are not hinted, as they include no charmap and the auto-hinter + doesn't include "generic" global metrics computations yet.. + + Now, I need to release this thing to the FreeType 2 source.. + + + + + + - CHANGES TO THE RENDERER MODULES + + the monochrome and smooth renderers are now in two distinct directories, + namely "src/raster1" and "src/smooth". Note that the old "src/renderer" + is now gone.. + + I ditched the 5-gray-levels renderers. Basically, it involved a simple + #define toggle in 'src/raster1/ftraster.c' + + FT_Render_Glyph, FT_Outline_Render & FT_Outline_Get_Bitmap now select + the best renderer available, depending on render mode. If the current + renderer for a given glyph image format isn't capable of supporting + the render mode, another one will be found in the library's list. + + This means that client applications do not need to switch or set the + renderers themselves (as in the latest change), they'll get what they + want automatically... At last.. + + Changed the demo programs accordingly.. + + + + - MAJOR INTERNAL REDESIGN: + + A lot of internal modifications have been performed lately on the + source in order to provide the following enhancements: + + - more generic module support: + + The FT_Module type is now defined to represent a handle to a given + module. The file contains the FT_Module_Class + definition, as well as the module-loading public API + + The FT_Driver type is still defined, and still represents a pointer + to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module, + FT_Get_Driver by FT_Get_Module, etc.. + + + - support for generic glyph image types: + + The FT_Renderer type is a pointer to a module used to perform various + operations on glyph image. + + Each renderer is capable of handling images in a single format + (e.g. ft_glyph_format_outline). Its functions are used to: + + - transform an glyph image + - render a glyph image into a bitmap + - return the control box (dimensions) of a given glyph image + + + The scan converters "ftraster.c" and "ftgrays.c" have been moved + to the new directory "src/renderer", and are used to provide two + default renderer modules. + + One corresponds to the "standard" scan-converter, the other to the + "smooth" one. + + The current renderer can be set through the new function + FT_Set_Renderer. + + The old raster-related function FT_Set_Raster, FT_Get_Raster and + FT_Set_Raster_Mode have now disappeared, in favor of the new: + + FT_Get_Renderer + FT_Set_Renderer + + see the file for more details.. + + These changes were necessary to properly support different scalable + formats in the future, like bi-color glyphs, etc.. + + + - glyph loader object: + + A new internal object, called a 'glyph loader' has been introduced + in the base layer. It is used by all scalable format font drivers + to load glyphs and composites. + + This object has been created to reduce the code size of each driver, + as each one of them basically re-implemented its functionality. + + See and the FT_GlyphLoader type for + more information.. + + + + - FT_GlyphSlot had new fields: + + In order to support extended features (see below), the FT_GlyphSlot + structure has a few new fields: + + linearHoriAdvance: this field gives the linearly scaled (i.e. + scaled but unhinted) advance width for the glyph, + expressed as a 16.16 fixed pixel value. This + is useful to perform WYSIWYG text. + + linearVertAdvance: this field gives the linearly scaled advance + height for the glyph (relevant in vertical glyph + layouts only). This is useful to perform + WYSIWYG text. + + Note that the two above field replace the removed "metrics2" field + in the glyph slot. + + advance: this field is a vector that gives the transformed + advance for the glyph. By default, it corresponds + to the advance width, unless FT_LOAD_VERTICAL_LAYOUT + was specified when calling FT_Load_Glyph or FT_Load_Char + + bitmap_left: this field gives the distance in integer pixels from + the current pen position to the left-most pixel of + a glyph image WHEN IT IS A BITMAP. It is only valid + when the "format" field is set to + "ft_glyph_format_bitmap", for example, after calling + the new function FT_Render_Glyph. + + bitmap_top: this field gives the distance in integer pixels from + the current pen position (located on the baseline) to + the top-most pixel of the glyph image WHEN IT IS A + BITMAP. Positive values correspond to upwards Y. + + loader: this is a new private field for the glyph slot. Client + applications should not touch it.. + + + - support for transforms and direct rendering in FT_Load_Glyph: + + Most of the functionality found in has been + moved to the core library. Hence, the following: + + - a transform can be specified for a face through FT_Set_Transform. + this transform is applied by FT_Load_Glyph to scalable glyph images + (i.e. NOT TO BITMAPS) before the function returns, unless the + bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags.. + + + - once a glyph image has been loaded, it can be directly converted to + a bitmap by using the new FT_Render_Glyph function. Note that this + function takes the glyph image from the glyph slot, and converts + it to a bitmap whose properties are returned in "face.glyph.bitmap", + "face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original + native image might be lost after the conversion. + + + - when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph + and FT_Load_Char functions will call FT_Render_Glyph automatically + when needed. + + + + + - reformated all modules source code in order to get rid of the basic + data types redifinitions (i.e. "TT_Int" instead of "FT_Int", "T1_Fixed" + instead of "FT_Fixed"). Hence the format-specific prefixes like "TT_", + "T1_", "T2_" and "CID_" are only used for relevant structures.. + +============================================================================ +OLD CHANGES FOR BETA 7 + + - bug-fixed the OpenType/CFF parser. It now loads and displays my two + fonts nicely, but I'm pretty certain that more testing is needed :-) + + - fixed the crummy Type 1 hinter, it now handles accented characters + correctly (well, the accent is not always well placed, but that's + another problem..) + + - added the CID-keyed Type 1 driver in "src/cid". Works pretty well for + only 13 Kb of code ;-) Doesn't read AFM files though, nor the really + useful CMAP files.. + + - fixed two bugs in the smooth renderer (src/base/ftgrays.c). Thanks to + Boris Letocha for spotting them and providing a fix.. + + - fixed potential "divide by zero" bugs in ftcalc.c.. my god.. + + - added source code for the OpenType/CFF driver (still incomplete though..) + + - modified the SFNT driver slightly to perform more robust header + checks in TT_Load_SFNT_Header. This prevents certain font files + (e.g. some Type 1 Multiple Masters) from being incorrectly "recognized" + as TrueType font files.. + + - moved a lot of stuff from the TrueType driver to the SFNT module, + this allows greater code re-use between font drivers (e.g. TrueType, + OpenType, Compact-TrueType, etc..) + + - added a tiny segment cache to the SFNT Charmap 4 decoder, in order + to minimally speed it up.. + + - added support for Multiple Master fonts in "type1z". There is also + a new file named which defines functions to + manage them from client applications. + + The new file "src/base/ftmm.c" is also optional to the engine.. + + - various formatting changes (e.g. EXPORT_DEF -> FT_EXPORT_DEF) + + small bug fixes in FT_Load_Glyph, the "type1" driver, etc.. + + - a minor fix to the Type 1 driver to let them apply the font matrix + correctly (used for many oblique fonts..) + + - some fixes for 64-bit systems (mainly changing some FT_TRACE calls + to use %p instead of %lx).. Thanks to Karl Robillard + + - fixed some bugs in the sbit loader (src/base/sfnt/ttsbit.c) + added + a new flag, FT_LOAD_CROP_BITMAP to query that bitmaps be cropped when + loaded from a file (maybe I should move the bitmap cropper to the + base layer ??). + + - changed the default number of gray levels of the smooth renderer to + 256 (instead of the previous 128). Of course, the human eye can't + see any difference ;-) + + - removed TT_MAX_SUBGLYPHS, there is no static limit on the number of + subglyphs in a TrueType font now.. + +============================================================================= +OLD CHANGES 16 May 2000 + + - tagged "BETA-6" in the CVS tree. This one is a serious release candidate + even though it doesn't incorporate the auto-hinter yet.. + + - various obsolete files were removed, and copyright header updated + + - finally updated the standard raster to fix the monochrome rendering bug + + re-enable support for 5-gray levels anti-aliasing (suck, suck..) + + - created new header files, and modified sources accordingly: + + - simple FreeType types, without the API + - definition of memory-management macros + + - added the "DSIG" (OpenType Digital Signature) tag to + + - light update/cleaning of the build system + changes to the sources in + order to get rid of _all_ compiler warnings with three compilers, i.e: + + gcc with "-ansi -pedantic -Wall -W", Visual C++ with "/W3 /WX" + and LCC + + IMPORTANT NOTE FOR WIN32-LCC USERS: + | + | It seems the C pre-processor that comes with LCC is broken, it + | doesn't recognize the ANSI standard directives # and ## correctly + | when one of the argument is a macro. Also, something like: + | + | #define F(x) print##x + | + | F(("hello")) + | + | will get incorrectly translated to: + | + | print "hello") + | + | by its pre-processor. For this reason, you simply cannot build + | FreeType 2 in debug mode with this compiler.. + + + - yet another massive grunt work. I've changed the definition of the + EXPORT_DEF, EXPORT_FUNC, BASE_DEF & BASE_FUNC macros. These now take + an argument, which is the function's return value type. + + This is necessary to compile FreeType as a DLL on Windows and OS/2. + Depending on the compiler used, a compiler-specific keyword like __export + or __system must be placed before (VisualC++) or after (BorlandC++) + the type.. + + Of course, this needed a lot of changes throughout the source code + to make it compile again... All cleaned up now, apparently.. + + Note also that there is a new EXPORT_VAR macro defined to allow the + _declaration_ of an exportable public (constant) variable. This is the + case of the raster interfaces (see ftraster.h and ftgrays.h), as well + as each module's interface (see sfdriver.h, psdriver.h, etc..) + + - new feature: it is now possible to pass extra parameters to font + drivers when creating a new face object. For now, this + capability is unused. It could however prove to be useful + in a near future.. + + the FT_Open_Args structure was changes, as well as the internal + driver interface (the specific "init_face" module function has now + a different signature). + + - updated the tutorial (not finished though). + - updated the top-level BUILD document + + - fixed a potential memory leak that could occur when loading embedded + bitmaps. + + - added the declaration of FT_New_Memory_Face in , as + it was missing from the public header (the implementation was already + in "ftobjs.c"). + + - the file has been seriously updated in order to + allow the automatic generation of error message tables. See the comments + within it for more information. + + - major directory hierarchy re-organisation. This was done for two things: + + * first, to ease the "manual" compilation of the library by requiring + at lot less include paths :-) + + * second, to allow external programs to effectively access internal + data fields. For example, this can be extremely useful if someone + wants to write a font producer or a font manager on top of FreeType. + + Basically, you should now use the 'freetype/' prefix for header inclusion, + as in: + + #include + #include + + Some new include sub-directories are available: + + a. the "freetype/config" directory, contains two files used to + configure the build of the library. Client applications should + not need to look at these normally, but they can if they want. + + #include + #include + + b. the "freetype/internal" directory, contains header files that + describes library internals. These are the header files that were + previously found in the "src/base" and "src/shared" directories. + + + As usual, the build system and the demos have been updated to reflect + the change.. + + Here's a layout of the new directory hierarchy: + + TOP + include/ + freetype/ + freetype.h + ... + config/ + ftoption.h + ftconfig.h + ftmodule.h + + internal/ + ftobjs.h + ftstream.h + ftcalc.h + ... + + src/ + base/ + ... + + sfnt/ + psnames/ + truetype/ + type1/ + type1z/ + + + Compiling a module is now much easier, for example, the following should + work when in the TOP directory on an ANSI build: + + gcc -c -I./include -I./src/base src/base/ftbase.c + gcc -c -I./include -I./src/sfnt src/sfnt/sfnt.c + etc.. + + (of course, using -Iconfig/ if you provide system-specific + configuration files). + + + - updated the structure of FT_Outline_Funcs in order to allow + direct coordinate scaling within the outline decomposition routine + (this is important for virtual "on" points with TrueType outlines) + + updates to the rasters to support this.. + + - updated the OS/2 table loading code in "src/sfnt/ttload.c" in order + to support version 2 of the table (see OpenType 1.2 spec) + + - created "include/tttables.h" and "include/t1tables.h" to allow + client applications to access some of the SFNT and T1 tables of a + face with a procedural interface (see FT_Get_Sfnt_Table()) + + updates to internal source files to reflect the change.. + + - some cleanups in the source code to get rid of warnings when compiling + with the "-Wall -W -ansi -pedantic" options in gcc. + + - debugged and moved the smooth renderer to "src/base/ftgrays.c" and + its header to "include/ftgrays.h" + + - updated TT_MAX_SUBGLYPHS to 96 as some CJK fonts have composites with + up to 80 sub-glyphs !! Thanks to Werner + +================================================================================ +OLD CHANGES - 14-apr-2000 + + - fixed a bug in the TrueType glyph loader that prevented the correct + loading of some CJK glyphs in mingli.ttf + + - improved the standard Type 1 hinter in "src/type1" + + - fixed two bugs in the experimental Type 1 driver in "src/type1z" + to handle the new XFree86 4.0 fonts (and a few other ones..) + + - the smooth renderer is now complete and supports sub-banding + to render large glyphs at high speed. However, it is still located + in "demos/src/ftgrays.c" and should move to the library itself + in the next beta.. NOTE: The smooth renderer doesn't compile in + stand-alone mode anymore, but this should be fixed RSN.. + + - introduced convenience functions to more easily deal with glyph + images, see "include/ftglyph.h" for more details, as well as the + new demo program named "demos/src/ftstring.c" that demonstrates + its use + + - implemented FT_LOAD_NO_RECURSE in both the TrueType and Type 1 + drivers (this is required by the auto-hinter to improve its results). + + - changed the raster interface, in order to allow client applications + to provide their own span-drawing callbacks. However, only the + smooth renderer supports this. See "FT_Raster_Params" in the + file "include/ftimage.h" + + - fixed a small bug in FT_MulFix that caused incorrect transform + computation !! + + - Note: The tutorial is out-of-date, grumpf.. :-( + +================================================================================ +OLD CHANGES - 12-mar-2000 + + - changed the layout of configuration files : now, all ANSI configuration + files are located in "freetype2/config". System-specific over-rides + can be placed in "freetype2/config/". + + - moved all configuration macros to "config/ftoption.h" + + - improvements in the Type 1 driver with AFM support + + - changed the fields in the FT_Outline structure : the old "flags" + array is re-named "tags", while all ancient flags are encoded into + a single unsigned int named "flags". + + - introduced new flags in FT_Outline.flags (see ft_outline_.... enums in + "ftimage.h"). + + - changed outline functions to "FT_Outline_" syntax + + - added a smooth anti-alias renderer to the demonstration programs + - added Mac graphics driver (thanks Just) + + - FT_Open_Face changed in order to received a pointer to a FT_Open_Args + descriptor.. + + - various cleanups, a few more API functions implemented (see FT_Attach_File) + + - updated some docs + +================================================================================ +OLD CHANGES - 22-feb-2000 + + - introduced the "psnames" module. It is used to: + + o convert a Postscript glyph name into the equivalent Unicode + character code (used by the Type 1 driver(s) to synthetize + on the fly a Unicode charmap). + + o provide an interface to retrieve the Postscript names of + the Macintosh, Adobe Standard & Adobe Expert character codes. + (the Macintosh names are used by the SFNT-module postscript + names support routines, while the other two tables are used + by the Type 1 driver(s)). + + - introduced the "type1z" alternate Type 1 driver. This is a (still + experimental) driver for the Type 1 format that will ultimately + replace the one in "src/type1". It uses pattern matching to load + data from the font, instead of a finite state analyzer. It works + much better than the "old" driver with "broken" fonts. It is also + much smaller (under 15 Kb). + + - the Type 1 drivers (both in "src/type1" and "src/type1z") are + nearly complete. They both provide automatic Unicode charmap + synthesis through the "psnames" module. No re-encoding vector + is needed. (note that they still leak memory due to some code + missing, and I'm getting lazy). + + Trivial AFM support has been added to read kerning information + but wasn't exactly tested as it should ;-) + + - The TrueType glyph loader has been seriously rewritten (see the + file "src/truetype/ttgload.c". It is now much, much simpler as + well as easier to read, maintain and understand :-) Preliminary + versions introduced a memory leak that has been reported by Jack + Davis, and is now fixed.. + + - introduced the new "ft_glyph_format_plotter", used to represent + stroked outlines like Windows "Vector" fonts, and certain Type 1 + fonts like "Hershey". The corresponding raster will be written + soon. + + - FT_New_Memory_Face is gone. Likewise, FT_Open_Face has a new + interface that uses a structure to describe the input stream, + the driver (if required), etc.. + +TODO + - Write FT_Get_Glyph_Bitmap and FT_Load_Glyph_Bitmap + + - Add a function like FT_Load_Character( face, char_code, load_flags ) + that would really embbed a call to FT_Get_Char_Index then FT_Load_Glyph + to ease developer's work. + + - Update the tutorial !! + - consider adding support for Multiple Master fonts in the Type 1 + drivers. + + - Test the AFM routines of the Type 1 drivers to check that kerning + information is returned correctly. + + - write a decent auto-gridding component !! We need this to release + FreeType 2.0 gold ! + + +----- less urgent needs : ---------- + - add a CFF/Type2 driver + - add a BDF driver + - add a FNT/PCF/HBF driver + - add a Speedo driver from the X11 sources + + +============================================================================== +OLDER CHANGES - 27-jan-2000 + + - updated the "sfnt" module interface to allow several SFNT-based + drivers to co-exist peacefully + + - updated the "T1_Face" type to better separate Postscript font content + from the rest of the FT_Face structure. Might be used later by the + CFF/Type2 driver.. + + - added an experimental replacement Type 1 driver featuring advanced + (and speedy) pattern matching to retrieve the data from postscript + fonts. + + - very minor changes in the implementation of FT_Set_Char_Size and + FT_Set_Pixel_Sizes (they now implement default to ligthen the + font driver's code). + + +============================================================================= +OLD MESSAGE + +This file summarizes the changes that occured since the last "beta" of FreeType 2. +Because the list is important, it has been divided into separate sections: + +Table Of Contents: + + I High-Level Interface (easier !) + II Directory Structure + III Glyph Image Formats + IV Build System + V Portability + VI Font Drivers + +----------------------------------------------------------------------------------------- +High-Level Interface : + + The high-level API has been considerably simplified. Here is how : + + - resource objects have disappeared. this means that face objects can + now be created with a single function call (see FT_New_Face and + FT_Open_Face) + + - when calling either FT_New_Face & FT_Open_Face, a size object and a + glyph slot object are automatically created for the face, and can be + accessed through "face->glyph" and "face->size" if one really needs to. + In most cases, there's no need to call FT_New_Size or FT_New_Glyph. + + - similarly, FT_Load_Glyph now only takes a "face" argument (instead of + a glyph slot and a size). Also, it's "result" parameter is gone, as + the glyph image type is returned in the field "face->glyph.format" + + - the list of available charmaps is directly accessible through + "face->charmaps", counting "face->num_charmaps" elements. Each + charmap has an 'encoding' field which specifies which known encoding + it deals with. Valid values are, for example : + + ft_encoding_unicode (for ASCII, Latin-1 and Unicode) + ft_encoding_apple_roman + ft_encoding_sjis + ft_encoding_adobe_standard + ft_encoding_adobe_expert + + other values may be added in the future. Each charmap still holds its + "platform_id" and "encoding_id" values in case the encoding is too + exotic for the current library + + +----------------------------------------------------------------------------------------- +Directory Structure: + + Should seem obvious to most of you: + + freetype/ + config/ -- configuration sub-makefiles + ansi/ + unix/ -- platform-specific configuration files + win32/ + os2/ + msdos/ + + include/ -- public header files, those to be included directly + by client apps + + src/ -- sources of the library + base/ -- the base layer + sfnt/ -- the sfnt "driver" (see the drivers section below) + truetype/ -- the truetype driver + type1/ -- the type1 driver + shared/ -- some header files shared between drivers + + demos/ -- demos/tools + + docs/ -- documentation (a bit empty for now) + +----------------------------------------------------------------------------------------- +Glyph Image Formats : + + Drivers are now able to register new glyph image formats within the library. + For now, the base layer supports of course bitmaps and vector outlines, but + one could imagine something different like colored bitmaps, bi-color + vectors or wathever else (Metafonts anyone ??). + + See the file `include/ftimage.h'. Note also that the type FT_Raster_Map is + gone, and is now replaced by FT_Bitmap, which should encompass all known + bitmap types. + + Each new image format must provide at least one "raster", i.e. a module + capable of transforming the glyph image into a bitmap. It's also possible + to change the default raster used for a given glyph image format. + + The default outline scan-converter now uses 128 levels of grays by default, + which tends to smooth many things. Note that the demo programs have been + updated significantly in order to display these.. + + +----------------------------------------------------------------------------------------- +Build system : + + You still need GNU Make to build the library. The build system has been + very seriously re-vamped in order to provide things like : + + - automatic host platform detection (reverting to 'config/ansi' + if it is not detected, with pseudo-standard compilation flags) + + - the ability to compile from the Makefiles with very different and + exotic compilers. Note that linking the library can be difficult for + some platforms. + + For example, the file `config/win32/lcclib.bat' is invoked by the + build system to create the ".lib" file with LCC-Win32 because its + librarian has too many flaws to be invoked directly from the Makefile. + + Here's how it works : + + - the first time you type `make', the build system runs a series of + sub-makefiles in order to detect your host platform. It then dumps + what it found, and creates a file called `config.mk' in the current + directory. This is a sub-Makefile used to define many important Make + variables used to build the library. + + - the second time, the build system detects the `config.mk' then use it + to build the library. All object files go into 'obj' by default, as + well as the library file, but this can easily be changed. + + Note that you can run "make setup" to force another host platform detection + even if a `config.mk' is present in the current directory. Another solution + is simply to delete the file, then re-run make. + + Finally, the default compiler for all platforms is gcc (for now, this will + hopefully changed in the future). You can however specify a different + compiler by specifying it after the 'setup' target as in : + + gnumake setup lcc on Win32 to use the LCC compiler + gnumake setup visualc on Win32 to use Visual C++ + + See the file `config//detect.mk' for a list of supported compilers + for your platforms. + + It should be relatively easy to write new detection rules files and + config.mk.. + + Finally, to build the demo programs, go to `demos' and launch GNU Make, + it will use the `config.mk' in the top directory to build the test + programs.. + +----------------------------------------------------------------------------------------- +Portability : + + In the previous beta, a single FT_System object was used to encompass + all low-level operations like thread synchronisation, memory management + and i/o access. This has been greatly simplified : + + - thread synchronisation has been dropped, for the simple reason that + the library is already re-entrant, and that if you really need two + threads accessing the same FT_Library, you should really synchronize + access to it yourself with a simple mutex. + + - memory management is performed through a very simple object called + "FT_Memory", which really is a table containing a table of pointers + to functions like malloc, realloc and free as well as some user data + (closure). + + - resources have disappeared (they created more problems than they + solved), and i/o management have been simplified greatly as a + result. Streams are defined through FT_Stream objects, which can + be either memory-based or disk-based. + + Note that each face has its own stream, which is closed only when + the face object is destroyed. Hence, a function like TT_Flush_Face + in 1.x cannot be directly supported. However, if you really need + something like this, you can easily tailor your own streams to achieve + the same feature at a lower level (and use FT_Open_Face instead of + FT_New_Face to create the face). + + See the file "include/ftsystem.h" for more details, as well as the + implementations found in "config/unix" and "config/ansi". + + +----------------------------------------------------------------------------------------- +Font Drivers : + + + The Font Driver interface has been modified in order to support + extensions & versioning. + + + The list of the font drivers that are statically linked to the + library at compile time is managed through a new configuration file + called `config//ftmodule.h'. + + This file is autogenerated when invoking `make modules'. This target + will parse all sub-directories of 'src', looking for a "module.mk" + rules file, used to describe the driver to the build system. + + Hence, one should call `make modules' each time a font driver is added + or removed from the `src' directory. + + + Finally, this version provides a "pseudo-driver" in `src/sfnt'. This + driver doesn't support font files directly, but provides services used + by all TrueType-like font drivers. Hence, its code is shared between + the TrueType & OpenType font formats, and possibly more formats to + come if we're lucky.. + +----------------------------------------------------------------------------------------- +Extensions support : + + The extensions support is inspired by the one found in 1.x. + + Now, each font driver has its own "extension registry", which lists + which extensions are available for the font faces managed by the driver. + + Extension ids are now strings, rather than 4-byte tags, as this is + usually more readable.. + + Each extension has: + - some data, associated to each face object + - an interface (table of function pointers) + + An extension that is format-specific should simply register itself + to the correct font driver. Here is some example code: + + // Registering an extensions + // + FT_Error FT_Init_XXXX_Extension( FT_Library library ) + { + FT_DriverInterface* tt_driver; + + driver = FT_Get_Driver( library, "truetype" ); + if (!driver) return FT_Err_Unimplemented_Feature; + + return FT_Register_Extension( driver, &extension_class ); + } + + + // Implementing the extensions + // + FT_Error FT_Proceed_Extension_XXX( FT_Face face ) + { + FT_XXX_Extension ext; + FT_XXX_Extension_Interface ext_interface; + + ext = FT_Get_Extension( face, "extensionid", &ext_interface ); + if (!ext) return error; + + return ext_interface->do_it(ext); + } + diff --git a/subsys/win32k/freetype/builds/.cvsignore b/subsys/win32k/freetype/builds/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/builds/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/builds/ansi/ansi.mk b/subsys/win32k/freetype/builds/ansi/ansi.mk new file mode 100644 index 0000000..d326f83 --- /dev/null +++ b/subsys/win32k/freetype/builds/ansi/ansi.mk @@ -0,0 +1,134 @@ +# +# FreeType 2 configuration rules for a `normal' ANSI compiler +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := rm -f +SEP := / +HOSTSEP := $(SEP) +BUILD := $(TOP)/builds/ansi +PLATFORM := ansi + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f $TOP/Makefile setup [options] +# make -f $TOP/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_std + distclean_freetype: distclean_freetype_std + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $@ + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/detect.mk b/subsys/win32k/freetype/builds/detect.mk new file mode 100644 index 0000000..d34904a --- /dev/null +++ b/subsys/win32k/freetype/builds/detect.mk @@ -0,0 +1,130 @@ +# +# FreeType 2 host platform detection rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# This sub-Makefile is in charge of detecting the current platform. It sets +# the following variables: +# +# BUILD The configuration and system-specific directory. Usually +# `freetype/builds/$(PLATFORM)' but can be different for +# custom builds of the library. +# +# The following variables must be defined in system specific `detect.mk' +# files: +# +# PLATFORM The detected platform. This will default to `ansi' if +# auto-detection fails. +# CONFIG_FILE The configuration sub-makefile to use. This usually depends +# on the compiler defined in the `CC' environment variable. +# DELETE The shell command used to remove a given file. +# COPY The shell command used to copy one file. +# SEP The platform-specific directory separator. +# CC The compiler to use. +# +# You need to set the following variable(s) before calling it: +# +# TOP The top-most directory in the FreeType library source +# hierarchy. If not defined, it will default to `.'. + +# If TOP is not defined, default it to `.' +# +ifndef TOP + TOP := . +endif + +# Set auto-detection default to `ansi' resp. UNIX-like operating systems. +# Note that we delay the evaluation of $(BUILD_CONFIG_), $(BUILD), and +# $(CONFIG_RULES). +# +PLATFORM := ansi +DELETE := $(RM) +COPY := cp +SEP := / + +BUILD_CONFIG_ = $(TOP)$(SEP)builds$(SEP) +BUILD = $(BUILD_CONFIG_)$(PLATFORM) +CONFIG_RULES = $(BUILD)$(SEP)$(CONFIG_FILE) + +# We define the BACKSLASH variable to hold a single back-slash character. +# This is needed because a line like +# +# SEP := \ +# +# does not work with GNU Make (the backslash is interpreted as a line +# continuation). While a line like +# +# SEP := \\ +# +# really defines $(SEP) as `\' on Unix, and `\\' on Dos and Windows! +# +BACKSLASH := $(strip \ ) + +# Now, include all detection rule files found in the `builds/' +# directories. Note that the calling order of the various `detect.mk' files +# isn't predictable. +# +include $(wildcard $(BUILD_CONFIG_)*/detect.mk) + +# In case no detection rule file was successful, use the default. +# +ifndef CONFIG_FILE + CONFIG_FILE := ansi.mk + setup: std_setup +endif + +# The following targets are equivalent, with the exception that they use +# a slightly different syntax for the `echo' command. +# +# std_setup: defined for most (i.e. Unix-like) platforms +# dos_setup: defined for Dos-ish platforms like Dos, Windows & OS/2 +# +.PHONY: std_setup dos_setup + +std_setup: + @echo "" + @echo "FreeType build system -- automatic system detection" + @echo "" + @echo "The following settings are used:" + @echo "" + @echo " platform $(PLATFORM)" + @echo " compiler $(CC)" + @echo " configuration directory $(BUILD)" + @echo " configuration rules $(CONFIG_RULES)" + @echo "" + @echo "If this does not correspond to your system or settings please remove the file" + @echo "\`$(CONFIG_MK)' from this directory then read the INSTALL file for help." + @echo "" + @echo "Otherwise, simply type \`make' again to build the library." + @echo "" + @$(COPY) $(CONFIG_RULES) $(CONFIG_MK) + +dos_setup: + @echo ÿ + @echo FreeType build system -- automatic system detection + @echo ÿ + @echo The following settings are used: + @echo ÿ + @echo ÿÿplatformÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(PLATFORM) + @echo ÿÿcompilerÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$(CC) + @echo ÿÿconfiguration directoryÿÿÿÿÿÿ$(BUILD) + @echo ÿÿconfiguration rulesÿÿÿÿÿÿÿÿÿÿ$(CONFIG_RULES) + @echo ÿ + @echo If this does not correspond to your system or settings please remove the file + @echo '$(CONFIG_MK)' from this directory then read the INSTALL file for help. + @echo ÿ + @echo Otherwise, simply type 'make' again to build the library. + @echo ÿ + @$(COPY) $(subst /,\,$(CONFIG_RULES) $(CONFIG_MK)) > nul + +# EOF diff --git a/subsys/win32k/freetype/builds/dos/detect.mk b/subsys/win32k/freetype/builds/dos/detect.mk new file mode 100644 index 0000000..f8c1706 --- /dev/null +++ b/subsys/win32k/freetype/builds/dos/detect.mk @@ -0,0 +1,87 @@ +# +# FreeType 2 configuration file to detect a DOS host platform. +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# We test for the COMSPEC environment variable, then run the `ver' +# command-line program to see if its output contains the word `Dos'. +# +# If this is true, we are running a Dos-ish platform (or an emulation). +# +ifeq ($(PLATFORM),ansi) + + ifdef COMSPEC + + is_dos := $(findstring Dos,$(shell ver)) + + # We try to recognize a Dos session under OS/2. The `ver' command + # returns `Operating System/2 ...' there, so `is_dos' should be empty. + # + # To recognize a Dos session under OS/2, we check COMSPEC for the + # substring `MDOS\COMMAND' + # + ifeq ($(is_dos),) + is_dos := $(findstring MDOS\COMMAND,$(COMSPEC)) + endif + + ifneq ($(is_dos),) + + PLATFORM := dos + DELETE := del + COPY := copy + + # Use DJGPP (i.e. gcc) by default. + # + CONFIG_FILE := dos-gcc.mk + SEP := / + ifndef CC + CC := gcc + endif + + # additionally, we provide hooks for various other compilers + # + ifneq ($(findstring turboc,$(MAKECMDGOALS)),) # Turbo C + CONFIG_FILE := dos-tcc.mk + SEP := $(BACKSLASH) + CC := tcc + .PHONY: turboc + endif + + ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ + CONFIG_FILE := dos-wat.mk + SEP := $(BACKSLASH) + CC := wcc386 + .PHONY: watcom + endif + + ifneq ($(findstring borlandc16,$(MAKECMDGOALS)),) # Borland C/C++ 16-bit + CONFIG_FILE := dos-bcc.mk + SEP := $(BACKSLASH) + CC := bcc + .PHONY: borlandc16 + endif + + ifneq ($(findstring borlandc,$(MAKECMDGOALS)),) # Borland C/C++ 32-bit + CONFIG_FILE := dos-bcc.mk + SEP := $(BACKSLASH) + CC := bcc32 + .PHONY: borlandc + endif + + setup: dos_setup + + endif # test Dos + endif # test COMSPEC +endif # test PLATFORM + +# EOF diff --git a/subsys/win32k/freetype/builds/dos/dos-gcc.mk b/subsys/win32k/freetype/builds/dos/dos-gcc.mk new file mode 100644 index 0000000..b9f55a2 --- /dev/null +++ b/subsys/win32k/freetype/builds/dos/dos-gcc.mk @@ -0,0 +1,134 @@ +# +# FreeType 2 configuration rules for the DJGPP compiler +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := rm -f +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/dos +PLATFORM := dos + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O6 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like: + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $@ + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/freetype.mk b/subsys/win32k/freetype/builds/freetype.mk new file mode 100644 index 0000000..172678f --- /dev/null +++ b/subsys/win32k/freetype/builds/freetype.mk @@ -0,0 +1,279 @@ +# +# FreeType 2 library sub-Makefile +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# DO NOT INVOKE THIS MAKEFILE DIRECTLY! IT IS MEANT TO BE INCLUDED BY +# OTHER MAKEFILES. + + +# The following variables (set by other Makefile components, in the +# environment, or on the command line) are used: +# +# BUILD The architecture dependent directory, +# e.g. `$(TOP)/builds/unix'. +# +# OBJ_DIR The directory in which object files are created. +# +# LIB_DIR The directory in which the library is created. +# +# INCLUDES A list of directories to be included additionally. +# Usually empty. +# +# CFLAGS Compilation flags. This overrides the default settings +# in the platform-specific configuration files. +# +# FTSYS_SRC If set, its value is used as the name of a replacement +# file for `src/base/ftsystem.c'. +# +# FTDEBUG_SRC If set, its value is used as the name of a replacement +# file for `src/base/ftdebug.c'. [For a normal build, this +# file does nothing.] +# +# FT_MODULE_LIST The file which contains the list of modules for the +# current build. Usually, this is automatically created by +# `modules.mk'. +# +# BASE_OBJ_S +# BASE_OBJ_M A list of base objects (for single object and multiple +# object builds, respectively). Set up in +# `src/base/rules.mk'. +# +# BASE_EXT_OBJ A list of base extension objects. Set up in +# `src/base/rules.mk'. +# +# DRV_OBJ_S +# DRV_OBJ_M A list of driver objects (for single object and multiple +# object builds, respectively). Set up cumulatively in +# `src//rules.mk'. +# +# CLEAN +# DISTCLEAN The sub-makefiles can append additional stuff to these two +# variables which is to be removed for the `clean' resp. +# `distclean' target. +# +# TOP, SEP, +# LIBRARY, CC, +# A, I, O, T Check `config.mk' for details. + + +# The targets `objects' and `library' are defined at the end of this +# Makefile after all other rules have been included. +# +.PHONY: single objects library + +# default target -- build single objects and library +# +single: objects library + +# `multi' target -- build multiple objects and library +# +multi: objects library + + +# The FreeType source directory, usually `./src'. +# +SRC := $(TOP)$(SEP)src + + +# The directory where the base layer components are placed, usually +# `./src/base'. +# +BASE_DIR := $(SRC)$(SEP)base + + +# A few short-cuts in order to avoid typing $(SEP) all the time for the +# directory separator. +# +# For example: $(SRC_) equals to `./src/' where `.' is $(TOP). +# +# +SRC_ := $(SRC)$(SEP) +BASE_ := $(BASE_DIR)$(SEP) +OBJ_ := $(OBJ_DIR)$(SEP) +LIB_ := $(LIB_DIR)$(SEP) +PUBLIC_ := $(TOP)$(SEP)include$(SEP)freetype$(SEP) +INTERNAL_ := $(PUBLIC_)internal$(SEP) +CONFIG_ := $(PUBLIC_)config$(SEP) + + +# The final name of the library file. +# +FT_LIBRARY := $(LIB_)$(LIBRARY).$A + + +# include paths +# +# IMPORTANT NOTE: The architecture-dependent directory must ALWAYS be placed +# in front of the include list. Porters are then able to +# put their own version of some of the FreeType components +# in the `freetype/builds/' directory, as these +# files will override the default sources. +# +INCLUDES := $(BUILD) $(TOP)$(SEP)include $(SRC) + +INCLUDE_FLAGS = $(INCLUDES:%=$I%) + + +# C flags used for the compilation of an object file. This must include at +# least the paths for the `base' and `builds/' directories; +# debug/optimization/warning flags + ansi compliance if needed. +# +FT_CFLAGS = $(CFLAGS) $(INCLUDE_FLAGS) +FT_CC = $(CC) $(FT_CFLAGS) +FT_COMPILE = $(CC) $(ANSIFLAGS) $(FT_CFLAGS) + + +# Include the `modules' rules file. +# +include $(TOP)/builds/modules.mk + + +# Initialize the list of objects. +# +OBJECTS_LIST := + + +# Define $(PUBLIC_H) as the list of all public header files located in +# `$(TOP)/include/freetype'. $(BASE_H) and $(CONFIG_H) are defined +# similarly. +# +# This is used to simplify the dependency rules -- if one of these files +# changes, the whole library is recompiled. +# +PUBLIC_H := $(wildcard $(PUBLIC_)*.h) +BASE_H := $(wildcard $(INTERNAL_)*.h) +CONFIG_H := $(wildcard $(CONFIG_)*.h) + +FREETYPE_H := $(PUBLIC_H) $(BASE_H) $(CONFIG_H) + + +# ftsystem component +# +ifndef FTSYS_SRC + FTSYS_SRC = $(BASE_)ftsystem.c +endif + +FTSYS_OBJ = $(OBJ_)ftsystem.$O + +OBJECTS_LIST += $(FTSYS_OBJ) + +$(FTSYS_OBJ): $(FTSYS_SRC) $(FREETYPE_H) + $(FT_COMPILE) $T$@ $< + + +# ftdebug component +# +ifndef FTDEBUG_SRC + FTDEBUG_SRC = $(BASE_)ftdebug.c +endif + +FTDEBUG_OBJ = $(OBJ_)ftdebug.$O + +OBJECTS_LIST += $(FTDEBUG_OBJ) + +$(FTDEBUG_OBJ): $(FTDEBUG_SRC) $(FREETYPE_H) + $(FT_COMPILE) $T$@ $< + + +# Include all rule files from FreeType components. +# +include $(wildcard $(SRC)/*/rules.mk) + + +# ftinit component +# +# The C source `ftinit.c' contains the FreeType initialization routines. +# It is able to automatically register one or more drivers when the API +# function FT_Init_FreeType() is called. +# +# The set of initial drivers is determined by the driver Makefiles +# includes above. Each driver Makefile updates the FTINIT_xxx lists +# which contain additional include paths and macros used to compile the +# single `ftinit.c' source. +# +FTINIT_SRC := $(BASE_)ftinit.c +FTINIT_OBJ := $(OBJ_)ftinit.$O + +OBJECTS_LIST += $(FTINIT_OBJ) + +$(FTINIT_OBJ): $(FTINIT_SRC) $(FREETYPE_H) $(FT_MODULE_LIST) + $(FT_COMPILE) $T$@ $< + + +# All FreeType library objects +# +# By default, we include the base layer extensions. These could be +# omitted on builds which do not want them. +# +OBJ_M = $(BASE_OBJ_M) $(BASE_EXT_OBJ) $(DRV_OBJS_M) +OBJ_S = $(BASE_OBJ_S) $(BASE_EXT_OBJ) $(DRV_OBJS_S) + + +# The target `multi' on the Make command line indicates that we want to +# compile each source file independently. +# +# Otherwise, each module/driver is compiled in a single object file through +# source file inclusion (see `src/base/ftbase.c' or +# `src/truetype/truetype.c' for examples). +# +BASE_OBJECTS := $(OBJECTS_LIST) + +ifneq ($(findstring multi,$(MAKECMDGOALS)),) + OBJECTS_LIST += $(OBJ_M) +else + OBJECTS_LIST += $(OBJ_S) +endif + +objects: $(OBJECTS_LIST) + +library: $(FT_LIBRARY) + +.c.$O: + $(FT_COMPILE) $T$@ $< + + +# Standard cleaning and distclean rules. These are not accepted +# on all systems though. +# +clean_freetype_std: + -$(DELETE) $(BASE_OBJECTS) $(OBJ_M) $(OBJ_S) $(CLEAN) + +distclean_freetype_std: clean_freetype_std + -$(DELETE) $(FT_LIBRARY) + -$(DELETE) *.orig *~ core *.core $(DISTCLEAN) + +# The Dos command shell does not support very long list of arguments, so +# we are stuck with wildcards. +# +clean_freetype_dos: + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(OBJ_))*.$O $(CLEAN) 2> nul + +distclean_freetype_dos: clean_freetype_dos + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) $(DISTCLEAN) 2> nul + +# Remove configuration file (used for distclean). +# +remove_config_mk: + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(CONFIG_MK)) + + +# The `config.mk' file must define `clean_freetype' and +# `distclean_freetype'. Implementations may use to relay these to either +# the `std' or `dos' versions from above, or simply provide their own +# implementation. +# +clean: clean_freetype +distclean: distclean_freetype remove_config_mk + +# EOF diff --git a/subsys/win32k/freetype/builds/mac/ftlib.prj b/subsys/win32k/freetype/builds/mac/ftlib.prj new file mode 100644 index 0000000000000000000000000000000000000000..d624c2502ff104ae5014f36690ca32123c42def5 GIT binary patch literal 603 zcmd_mI}QO+6vpv$$9TWrG$^SQ647f^LZu@zrXZ3VH*A1bY(irb5~U4@MX2?@F`req z#r^+gZgq~M^;$#%BC08}S0aa&h<(SujZ{e8~>w@uH`AiYCF^a%~q7c@d&(J1{yWAq!1`&Qn2g07)Sx{IdhA)2PAXolXP mS^9|P=rfw9Z)kyjphfzHmV8^@d}X?hR_Gq;?FGjg + +DISCLAIMER: this subdirectory is *not* being maintained by the +FreeType team, but by Just van Rossum. It's being released under +the same terms as FreeType (see LICENSE.TXT). diff --git a/subsys/win32k/freetype/builds/modules.mk b/subsys/win32k/freetype/builds/modules.mk new file mode 100644 index 0000000..110ee81 --- /dev/null +++ b/subsys/win32k/freetype/builds/modules.mk @@ -0,0 +1,75 @@ +# +# FreeType 2 modules sub-Makefile +# + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# DO NOT INVOKE THIS MAKEFILE DIRECTLY! IT IS MEANT TO BE INCLUDED BY +# OTHER MAKEFILES. + + +# This file is in charge of handling the generation of the modules list +# file. + +.PHONY: make_module_list clean_module_list remake_module_list + +# MODULE_LIST, as its name suggests, indicates where the modules list +# resides. For now, it is in `include/freetype/config/ftmodule.h'. +# +ifndef FT_MODULE_LIST + FT_MODULE_LIST := $(TOP)$(SEP)include$(SEP)freetype$(SEP)config$(SEP)ftmodule.h +endif + +# To build the modules list, we invoke the `make_module_list' target. +# +# This rule is commented out by default since FreeType comes already with +# a ftmodule.h file. +# +#$(FT_MODULE_LIST): make_module_list + +# Before the modules list file can be generated, we must remove the file in +# order to `clean' the list. +# +clean_module_list: + @-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_MODULE_LIST)) + @-echo Regenerating the modules list in $(FT_MODULE_LIST)... + +make_module_list: clean_module_list + @echo done. + + +# Trailing spaces are protected with a `#' sign to avoid accidental +# removing. +# +ifneq ($(findstring $(PLATFORM),dos win32 win16 os2),) + OPEN_MODULE := @echo # + CLOSE_MODULE := >> $(subst $(SEP),$(HOSTSEP),$(FT_MODULE_LIST)) +else + OPEN_MODULE := @echo " + CLOSE_MODULE := " >> $(FT_MODULE_LIST) +endif + +# $(OPEN_DRIVER) & $(CLOSE_DRIVER) are used to specify a given font driver +# in the `module.mk' rules file. +# +OPEN_DRIVER := $(OPEN_MODULE)FT_USE_MODULE( +CLOSE_DRIVER := )$(CLOSE_MODULE) + +ECHO_DRIVER := @echo "* module: # +ECHO_DRIVER_DESC := ( +ECHO_DRIVER_DONE := )" + +# Each `module.mk' in the `src' sub-dirs is used to add one rule to the +# target `make_module_list'. +# +include $(wildcard $(TOP)/src/*/module.mk) + +# EOF diff --git a/subsys/win32k/freetype/builds/os2/detect.mk b/subsys/win32k/freetype/builds/os2/detect.mk new file mode 100644 index 0000000..ed0f124 --- /dev/null +++ b/subsys/win32k/freetype/builds/os2/detect.mk @@ -0,0 +1,62 @@ +# +# FreeType 2 configuration file to detect an OS/2 host platform. +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifeq ($(PLATFORM),ansi) + + ifdef OS2_SHELL + + PLATFORM := os2 + COPY := copy + DELETE := del + + CONFIG_FILE := os2-gcc.mk # gcc-emx by default + SEP := / + + # additionally, we provide hooks for various other compilers + # + ifneq ($(findstring visualage,$(MAKECMDGOALS)),) # Visual Age C++ + CONFIG_FILE := os2-icc.mk + SEP := $(BACKSLASH) + CC := icc + .PHONY: visualage + endif + + ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ + CONFIG_FILE := os2-wat.mk + SEP := $(BACKSLASH) + CC := wcc386 + .PHONY: watcom + endif + + ifneq ($(findstring borlandc,$(MAKECMDGOALS)),) # Borland C++ 32-bit + CONFIG_FILE := os2-bcc.mk + SEP := $(BACKSLASH) + CC := bcc32 + .PHONY: borlandc + endif + + ifneq ($(findstring devel,$(MAKECMDGOALS)),) # development target + CONFIG_FILE := os2-dev.mk + CC := gcc + SEP := / + devel: setup + endif + + setup: dos_setup + + endif # test OS2_SHELL +endif # test PLATFORM + +#EOF diff --git a/subsys/win32k/freetype/builds/os2/os2-dev.mk b/subsys/win32k/freetype/builds/os2/os2-dev.mk new file mode 100644 index 0000000..93939d2 --- /dev/null +++ b/subsys/win32k/freetype/builds/os2/os2-dev.mk @@ -0,0 +1,137 @@ +# +# FreeType 2 configuration rules for OS/2 + gcc +# +# Development version without optimizations. +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/os2 +PLATFORM := os2 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O0 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/os2/os2-gcc.mk b/subsys/win32k/freetype/builds/os2/os2-gcc.mk new file mode 100644 index 0000000..14992e6 --- /dev/null +++ b/subsys/win32k/freetype/builds/os2/os2-gcc.mk @@ -0,0 +1,135 @@ +# +# FreeType 2 configuration rules for OS/2 + gcc +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/os2 +PLATFORM := os2 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O6 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/unix/aclocal.m4 b/subsys/win32k/freetype/builds/unix/aclocal.m4 new file mode 100644 index 0000000..47abe43 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/aclocal.m4 @@ -0,0 +1,430 @@ +## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*- +## Copyright (C) 1996-1999 Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 40 AC_PROG_LIBTOOL +AC_DEFUN(AC_PROG_LIBTOOL, +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl + +# Save cache, so that ltconfig can load it +AC_CACHE_SAVE + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ +LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ +DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \ +|| AC_MSG_ERROR([libtool configure failed]) + +# Reload cache, that may have been modified by ltconfig +AC_CACHE_LOAD + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log +]) + +AC_DEFUN(AC_LIBTOOL_SETUP, +[AC_PREREQ(2.13)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_NM])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +dnl + +case "$target" in +NONE) lt_target="$host" ;; +*) lt_target="$target" ;; +esac + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" +ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN], +[libtool_flags="$libtool_flags --enable-dlopen"]) +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[libtool_flags="$libtool_flags --enable-win32-dll"]) +AC_ARG_ENABLE(libtool-lock, + [ --disable-libtool-lock avoid locking (might break parallel builds)]) +test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock" +test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$lt_target" in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +]) +esac +]) + +# AC_LIBTOOL_DLOPEN - enable checks for dlopen support +AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])]) + +# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's +AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])]) + +# AC_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AC_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_SHARED, [dnl +define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl +]) + +# AC_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no)]) + +# AC_ENABLE_STATIC - implement the --enable-static flag +# Usage: AC_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_STATIC, [dnl +define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AC_ENABLE_STATIC_DEFAULT)dnl +]) + +# AC_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no)]) + + +# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag +# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl +define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(fast-install, +changequote(<<, >>)dnl +<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT], +changequote([, ])dnl +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl +]) + +# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install +AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no)]) + +# AC_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN(AC_PROG_LD, +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. +changequote(,)dnl + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' +changequote([,])dnl + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +]) + +AC_DEFUN(AC_PROG_LD_GNU, +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +]) + +# AC_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN(AC_PROG_NM, +[AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(ac_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi]) +NM="$ac_cv_path_NM" +AC_MSG_RESULT([$NM]) +]) + +# AC_CHECK_LIBM - check for math library +AC_DEFUN(AC_CHECK_LIBM, +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case "$lt_target" in +*-*-beos* | *-*-cygwin*) + # These system don't have libm + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, main, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, main, LIBM="-lm") + ;; +esac +]) + +# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl convenience library, adds --enable-ltdl-convenience to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case "$enable_ltdl_convenience" in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la + INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) +]) + +# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for +# the libltdl installable library, and adds --enable-ltdl-install to +# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor +# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed +# to be `${top_builddir}/libltdl'. Make sure you start DIR with +# '${top_builddir}/' (note the single quotes!) if your package is not +# flat, and, if you're not using automake, define top_builddir as +# appropriate in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, main, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la + INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + INCLTDL= + fi +]) + +dnl old names +AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl +AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl +AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl +AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl +AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl +AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl +AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl + +dnl This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL])dnl diff --git a/subsys/win32k/freetype/builds/unix/config.guess b/subsys/win32k/freetype/builds/unix/config.guess new file mode 100644 index 0000000..4994964 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/config.guess @@ -0,0 +1,1273 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-06-13' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# Please send patches to . +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of this system. + +Operation modes: + -h, --help print this help, then exit + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # Netbsd (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-cbm ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format. + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + *:Linux:*:*) + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + *ia64) + echo "${UNAME_MACHINE}-unknown-linux" + exit 0 + ;; + i?86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 + ;; + elf_i?86) + echo "${UNAME_MACHINE}-pc-linux" + exit 0 + ;; + i?86coff) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 + ;; + sparclinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + armlinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32arm*) + echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" + exit 0 + ;; + armelf_linux*) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + m68klinux) + echo "${UNAME_MACHINE}-unknown-linux-gnuaout" + exit 0 + ;; + elf32ppc | elf32ppclinux) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unkown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} + exit 0 + ;; + shelf_linux) + echo "${UNAME_MACHINE}-unknown-linux-gnu" + exit 0 + ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c < /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + elif test "${UNAME_MACHINE}" = "s390"; then + echo s390-ibm-linux && exit 0 + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i?86:*:5:7*) + # Fixed at (any) Pentium or better + UNAME_MACHINE=i586 + if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then + echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-W:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess version = $version + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/subsys/win32k/freetype/builds/unix/config.sub b/subsys/win32k/freetype/builds/unix/config.sub new file mode 100644 index 0000000..6e5f1a8 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/config.sub @@ -0,0 +1,1319 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 +# Free Software Foundation, Inc. + +version='2000-06-20' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -V, --version print version number, then exit" + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case "$1" in + --version | --vers* | -V ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + exec >&2 + echo "$me: invalid option $1" + echo "$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 \ + | x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | hppa64 \ + | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ + | alphaev6[78] \ + | we32k | ns16k | clipper | i370 | sh | sh[34] \ + | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el | mcore \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v | fr30 | avr) + basic_machine=$basic_machine-unknown + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[234567]86) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + # FIXME: clean up the formatting here. + vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ + | hppa2.0n-* | hppa64-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ + | alphaev6[78]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ + | mipstx39-* | mipstx39el-* | mcore-* \ + | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \ + | bs2000-* | tic54x-* | c54x-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + i386-go32 | go32) + basic_machine=i386-unknown + os=-go32 + ;; + i386-mingw32 | mingw32) + basic_machine=i386-unknown + os=-mingw32 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4) + base_machine=sh-unknown + ;; + sparc | sparcv9) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i[34567]86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -*MiNT) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f301-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "version='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/subsys/win32k/freetype/builds/unix/configure b/subsys/win32k/freetype/builds/unix/configure new file mode 100644 index 0000000..78e572b --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/configure @@ -0,0 +1,2514 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared[=PKGS] build shared libraries [default=yes]" +ac_help="$ac_help + --enable-static[=PKGS] build static libraries [default=yes]" +ac_help="$ac_help + --enable-fast-install[=PKGS] optimize for fast installation [default=yes]" +ac_help="$ac_help + --with-gnu-ld assume the C compiler uses GNU ld [default=no]" +ac_help="$ac_help + --disable-libtool-lock avoid locking (might break parallel builds)" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=ftconfig.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + + +version_info='6:0:0' + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:588: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:609: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:627: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:653: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:683: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:734: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:766: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 777 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:808: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:813: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:841: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:873: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:894: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:911: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:928: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + +if test "x$CC" = xgcc; then + XX_CFLAGS="-Wall" + XX_ANSIFLAGS="-pedantic -ansi" +else + case "$host" in + *-dec-osf*) + XX_CFLAGS="-std1 -O2 -g3" + XX_ANSIFLAGS= + ;; + *) + XX_CFLAGS= + XX_ANSIFLAGS= + ;; + esac +fi + + + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:974: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RMF'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RMF"; then + ac_cv_prog_RMF="$RMF" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RMF="rm -f" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +RMF="$ac_cv_prog_RMF" +if test -n "$RMF"; then + echo "$ac_t""$RMF" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "rmdir", so it can be a program name with args. +set dummy rmdir; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1003: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RMDIR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RMDIR"; then + ac_cv_prog_RMDIR="$RMDIR" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RMDIR="rmdir" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +RMDIR="$ac_cv_prog_RMDIR" +if test -n "$RMDIR"; then + echo "$ac_t""$RMDIR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1041: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1095: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1108: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1175: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in fcntl.h unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1202: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1212: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1240: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1294: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking size of int""... $ac_c" 1>&6 +echo "configure:1315: checking size of int" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(int)); + exit(0); +} +EOF +if { (eval echo configure:1334: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_int=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_int=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_int" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1354: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(long)); + exit(0); +} +EOF +if { (eval echo configure:1373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_long=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_long=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1398: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1408: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1437: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1490: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1638: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + +if test "$ac_cv_func_mmap_fixed_mapped" != yes; then + FTSYS_SRC='$(BASE_)ftsystem.c' +else + FTSYS_SRC='$(BUILD)/ftsystem.c' +fi + + +for ac_func in memcpy memmove +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1670: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_shared=yes +fi + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_static=yes +fi + +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_fast_install=yes ;; +no) enable_fast_install=no ;; +*) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_fast_install=yes +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1795: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 +echo "configure:1834: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 +echo "configure:1858: checking for GNU ld" >&5 +else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 +echo "configure:1861: checking for non-GNU ld" >&5 +fi +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } +echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 +echo "configure:1896: checking if the linker ($LD) is GNU ld" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 + + +echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 +echo "configure:1912: checking for BSD-compatible nm" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$NM"; then + # Let the user override the test. + ac_cv_path_NM="$NM" +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + break + else + ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm +fi +fi + +NM="$ac_cv_path_NM" +echo "$ac_t""$NM" 1>&6 + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1948: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +case "$target" in +NONE) lt_target="$host" ;; +*) lt_target="$target" ;; +esac + +# Check for any special flags to pass to ltconfig. +libtool_flags="--cache-file=$cache_file" +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + : +fi + +test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock" +test x"$silent" = xyes && libtool_flags="$libtool_flags --silent" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$lt_target" in +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 1997 "configure"' > conftest.$ac_ext + if { (eval echo configure:1998: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 +echo "configure:2019: checking whether the C compiler needs -belf" >&5 +if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + lt_cv_cc_needs_belf=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + lt_cv_cc_needs_belf=no +fi +rm -f conftest* +fi + +echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + + +esac + + +# Save cache, so that ltconfig can load it +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \ +LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \ +DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + +# Reload cache, that may have been modified by ltconfig +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Redirect the config.log output again, so that the ltconfig log is not +# clobbered by the next message. +exec 5>>./config.log + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "unix.mk:unix.in ftconfig.h:ftconfig.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@version_info@%$version_info%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@XX_CFLAGS@%$XX_CFLAGS%g +s%@XX_ANSIFLAGS@%$XX_ANSIFLAGS%g +s%@RMF@%$RMF%g +s%@RMDIR@%$RMDIR%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@FTSYS_SRC@%$FTSYS_SRC%g +s%@RANLIB@%$RANLIB%g +s%@LN_S@%$LN_S%g +s%@LIBTOOL@%$LIBTOOL%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + + diff --git a/subsys/win32k/freetype/builds/unix/configure.in b/subsys/win32k/freetype/builds/unix/configure.in new file mode 100644 index 0000000..cfaf1b7 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/configure.in @@ -0,0 +1,74 @@ +dnl This file is part of the FreeType project. +dnl +dnl Process this file with autoconf to produce a configure script. +dnl + +AC_INIT(ftconfig.in) + +dnl Configuration file -- stay in 8.3 limit +AC_CONFIG_HEADER(ftconfig.h:ftconfig.in) + +version_info='6:0:0' +AC_SUBST(version_info) + +dnl checks for system type +AC_CANONICAL_SYSTEM + +dnl checks for programs +AC_PROG_CC +AC_PROG_CPP + +dnl get Compiler flags right. +if test "x$CC" = xgcc; then + XX_CFLAGS="-Wall" + XX_ANSIFLAGS="-pedantic -ansi" +else + case "$host" in + *-dec-osf*) + XX_CFLAGS="-std1 -O2 -g3" + XX_ANSIFLAGS= + ;; + *) + XX_CFLAGS= + XX_ANSIFLAGS= + ;; + esac +fi +AC_SUBST(XX_CFLAGS) +AC_SUBST(XX_ANSIFLAGS) + +AC_CHECK_PROG(RMF, rm, rm -f) +AC_CHECK_PROG(RMDIR, rmdir, rmdir) +AC_PROG_INSTALL + +dnl checks for header files +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h unistd.h) + +dnl checks for typedefs, structures, and compiler characteristics +AC_C_CONST +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) + +dnl Checks for library functions. + +dnl Here we check whether we can use our mmap file component. +AC_FUNC_MMAP +if test "$ac_cv_func_mmap_fixed_mapped" != yes; then + FTSYS_SRC='$(BASE_)ftsystem.c' +else + FTSYS_SRC='$(BUILD)/ftsystem.c' +fi +AC_SUBST(FTSYS_SRC) + +AC_CHECK_FUNCS(memcpy memmove) + +AM_PROG_LIBTOOL + +dnl create the Unix-specific sub-Makefile `builds/unix/unix.mk' that will be +dnl used by the build system +dnl +AC_OUTPUT(unix.mk:unix.in) + + +dnl end of configure.in diff --git a/subsys/win32k/freetype/builds/unix/detect.mk b/subsys/win32k/freetype/builds/unix/detect.mk new file mode 100644 index 0000000..dec1baa --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/detect.mk @@ -0,0 +1,59 @@ +# +# FreeType 2 configuration file to detect a UNIX host platform. +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifeq ($(PLATFORM),ansi) + + has_init := $(strip $(wildcard /sbin/init)) + ifneq ($(has_init),) + + PLATFORM := unix + COPY := cp + DELETE := rm -f + + # If a Unix platform is detected, the configure script is called and + # `unix.mk' is created. + # + # Arguments to `configure' should be in the CFG variable. Example: + # + # make CFG="--prefix=/usr --disable-static" + # + # If you need to set CFLAGS or LDFLAGS, do it here also. + # + # Feel free to add support for other platform specific compilers in this + # directory (e.g. solaris.mk + changes here to detect the platform). + # + CONFIG_FILE := unix.mk + setup: unix.mk + unix: setup + + # If `devel' is the requested target, use `-g -O0' as the default value + # for CFLAGS if CFLAGS isn't set. + # + ifneq ($(findstring devel,$(MAKECMDGOALS)),) + ifndef CFLAGS + USE_CFLAGS := CFLAGS="-g -O0" + endif + devel: setup + endif + + setup: std_setup + + unix.mk: builds/unix/unix.in + cd builds/unix; $(USE_CFLAGS) ./configure $(CFG) + + endif # test Unix +endif # test PLATFORM + +# EOF diff --git a/subsys/win32k/freetype/builds/unix/ftconfig.in b/subsys/win32k/freetype/builds/unix/ftconfig.in new file mode 100644 index 0000000..a24b679 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/ftconfig.in @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* ftconfig.in */ +/* */ +/* UNIX-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This header file contains a number of macro definitions that are used */ + /* by the rest of the engine. Most of the macros here are automatically */ + /* determined at compile time, and you should not need to change it to */ + /* port FreeType, except to compile the library with a non-ANSI */ + /* compiler. */ + /* */ + /* Note however that if some specific modifications are needed, we */ + /* advise you to place a modified copy in your build directory. */ + /* */ + /* The build directory is usually `freetype/builds/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /*************************************************************************/ + + +#ifndef FTCONFIG_H +#define FTCONFIG_H + + + /* Include the header file containing all developer build options */ +#include + + + /*************************************************************************/ + /* */ + /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled to suit a specific system. The current */ + /* ones are defaults used to compile FreeType in an ANSI C environment */ + /* (16bit compilers are also supported). Copy this file to your own */ + /* `freetype/builds/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + +#define HAVE_UNISTD_H 0 +#define HAVE_FCNTL_H 0 + +#define SIZEOF_INT 2 +#define SIZEOF_LONG 2 + + +#define FT_SIZEOF_INT SIZEOF_INT +#define FT_SIZEOF_LONG SIZEOF_LONG + + + /* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + /* UNUSED is a macro used to indicate that a given parameter is not used */ + /* -- this is only used to get rid of unpleasant compiler warnings */ +#ifndef FT_UNUSED +#define FT_UNUSED( arg ) ( (arg) = (arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you are doing. No */ + /* porter should need to mess with them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* IntN types */ + /* */ + /* Used to guarantee the size of some specific integers. */ + /* */ + typedef signed short FT_Int16; + typedef unsigned short FT_UInt16; + +#if FT_SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_UInt32; + +#elif FT_SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_UInt32; + +#else +#error "no 32bit type found -- please check your configuration files" +#endif + +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro in */ + /* `ftoption.h'. */ + /* */ + /* Note that this will produce many -ansi warnings during library */ + /* compilation, and that in many cases, the generated code will be */ + /* neither smaller nor faster! */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define FT_LONG64 +#define FT_INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif /* FT_SIZEOF_LONG == 8 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT +#define LOCAL_DEF static +#define LOCAL_FUNC static +#else +#define LOCAL_DEF extern +#define LOCAL_FUNC /* nothing */ +#endif + +#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT +#define BASE_DEF( x ) static x +#define BASE_FUNC( x ) static x +#else +#define BASE_DEF( x ) extern x +#define BASE_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_DEF +#define FT_EXPORT_DEF( x ) extern x +#endif + +#ifndef FT_EXPORT_FUNC +#define FT_EXPORT_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/builds/unix/ftsystem.c b/subsys/win32k/freetype/builds/unix/ftsystem.c new file mode 100644 index 0000000..9ecd95c --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/ftsystem.c @@ -0,0 +1,306 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* Unix-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include + +#include +#include +#include + + + /* memory-mapping includes and definitions */ +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#ifndef MAP_FILE +#define MAP_FILE 0x00 +#endif + + /*************************************************************************/ + /* */ + /* The prototype for munmap() is not provided on SunOS. This needs to */ + /* have a check added later to see if the GNU C library is being used. */ + /* If so, then this prototype is not needed. */ + /* */ +#if defined( __sun__ ) && !defined( SVR4 ) && !defined( __SVR4 ) + extern int munmap( caddr_t addr, + int len ); +#endif + +#include + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_alloc */ + /* */ + /* */ + /* The memory allocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* size :: The requested size in bytes. */ + /* */ + /* */ + /* block :: The address of newly allocated block. */ + /* */ + static + void* ft_alloc( FT_Memory memory, + long size ) + { + FT_UNUSED( memory ); + + return malloc( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_realloc */ + /* */ + /* */ + /* The memory reallocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* cur_size :: The current size of the allocated memory block. */ + /* */ + /* new_size :: The newly requested size in bytes. */ + /* */ + /* block :: The current address of the block in memory. */ + /* */ + /* */ + /* The address of the reallocated memory block. */ + /* */ + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + FT_UNUSED( memory ); + FT_UNUSED( cur_size ); + + return realloc( block, new_size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_free */ + /* */ + /* */ + /* The memory release function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + static + void ft_free( FT_Memory memory, + void* block ) + { + FT_UNUSED( memory ); + + free( block ); + } + + + /*************************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + /* We use the macro STREAM_FILE for convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object */ +#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream */ + /* */ + /* */ + /* The function to close a stream. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + static + void ft_close_stream( FT_Stream stream ) + { + munmap ( stream->descriptor.pointer, stream->size ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Stream */ + /* */ + /* */ + /* Creates a new stream object. */ + /* */ + /* */ + /* filepathname :: The name of the stream (usually a file) to be */ + /* opened. */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { + int file; + struct stat stat_buf; + + + if ( !stream ) + return FT_Err_Invalid_Stream_Handle; + + /* open the file */ + file = open( filepathname, O_RDONLY ); + if ( file < 0 ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not open `%s'\n", filepathname )); + return FT_Err_Cannot_Open_Resource; + } + + if ( fstat( file, &stat_buf ) < 0 ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not `fstat' file `%s'\n", filepathname )); + goto Fail_Map; + } + + stream->size = stat_buf.st_size; + stream->pos = 0; + stream->base = mmap( NULL, + stream->size, + PROT_READ, + MAP_FILE | MAP_PRIVATE, + file, + 0 ); + + if ( (long)stream->base == -1 ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); + goto Fail_Map; + } + + close( file ); + + stream->descriptor.pointer = stream->base; + stream->pathname.pointer = (char*)filepathname; + + stream->close = ft_close_stream; + stream->read = 0; + + FT_TRACE1(( "FT_New_Stream:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); + + return FT_Err_Ok; + + Fail_Map: + close( file ); + + stream->base = NULL; + stream->size = 0; + stream->pos = 0; + + return FT_Err_Cannot_Open_Stream; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory */ + /* */ + /* */ + /* Creates a new memory object. */ + /* */ + /* */ + /* A pointer to the new memory object. 0 in case of error. */ + /* */ + FT_EXPORT_FUNC( FT_Memory ) FT_New_Memory( void ) + { + FT_Memory memory; + + + memory = (FT_Memory)malloc( sizeof ( *memory ) ); + if ( memory ) + { + memory->user = 0; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; + } + + return memory; + } + + +/* END */ diff --git a/subsys/win32k/freetype/builds/unix/install-sh b/subsys/win32k/freetype/builds/unix/install-sh new file mode 100644 index 0000000..ebc6691 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/install-sh @@ -0,0 +1,250 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/subsys/win32k/freetype/builds/unix/ltconfig b/subsys/win32k/freetype/builds/unix/ltconfig new file mode 100644 index 0000000..a01334f --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/ltconfig @@ -0,0 +1,3078 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A lot of this script is taken from autoconf-2.10. + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} +echo=echo +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec "$SHELL" "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null`} + case X$UNAME in + *-DOS) PATH_SEPARATOR=';' ;; + *) PATH_SEPARATOR=':' ;; + esac +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || + test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH /usr/ucb; do + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running ltconfig again with it. + ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf "%s\n"' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # Cool, printf works + : + elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.3.4 +TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)" +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +default_ofile=libtool +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +enable_static=yes +enable_fast_install=yes +enable_dlopen=unknown +enable_win32_dll=no +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +ofile="$default_ofile" +verify_host=yes +with_gcc=no +with_gnu_ld=no +need_locks=yes +ac_ext=c +objext=o +libext=a +exeext= +cache_file= + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LDFLAGS="$LDFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_LIBS="$LIBS" +old_NM="$NM" +old_RANLIB="$RANLIB" +old_DLLTOOL="$DLLTOOL" +old_OBJDUMP="$OBJDUMP" +old_AS="$AS" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test ! -f "$ltmain"; then + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi +if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi + +if test -n "$cache_file" && test -r "$cache_file"; then + echo "loading cache $cache_file within ltconfig" + . $cache_file +fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to LTMAIN. + srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$SHELL $ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$SHELL $ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# Set a sane default for `OBJDUMP'. +test -z "$OBJDUMP" && OBJDUMP=objdump + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +fi + +# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$AS" && AS=as + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc || test -f $dir/cc$ac_exeext; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:581: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for object suffix... $ac_c" 1>&6 +$rm conftest* +echo 'int i = 1;' > conftest.c +echo "$progname:603: checking for object suffix" >& 5 +if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* +echo "$ac_t$objext" 1>&6 + +echo $ac_n "checking for executable suffix... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_exeext="no" + $rm conftest* + echo 'main () { return 0; }' > conftest.c + echo "$progname:629: checking for executable suffix" >& 5 + if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c | *.err | *.$objext ) ;; + *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; + esac + done + else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* +fi +if test "X$ac_cv_exeext" = Xno; then + exeext="" +else + exeext="$ac_cv_exeext" +fi +echo "$ac_t$ac_cv_exeext" 1>&6 + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + + case "$host_os" in + beos* | irix5* | irix6* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + aix*) + # Below there is a dirty hack to force normal static linking with -ldl + # The problem is because libdl dynamically linked with both libc and + # libC (AIX C++ library), which obviously doesn't included in libraries + # list by gcc. This cause undefined symbols with -static flags. + # This hack allows C programs to be linked with "-static -ldl", but + # we not sure about C++ programs. + link_static_flag="$link_static_flag ${wl}-lC" + ;; + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + sysv4*MP*) + if test -d /usr/nec; then + pic_flag=-Kconform_pic + fi + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10* | hpux11*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4* | osf5*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + sysv4*MP*) + if test -d /usr/nec ;then + pic_flag='-Kconform_pic' + link_static_flag='-Bstatic' + fi + ;; + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + case "$host_os" in + hpux9* | hpux10* | hpux11*) + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + ;; + *) + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + ;; + esac + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check to see if options -o and -c are simultaneously supported by compiler +echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 +$rm -r conftest 2>/dev/null +mkdir conftest +cd conftest +$rm conftest* +echo "int some_variable = 0;" > conftest.c +mkdir out +# According to Tom Tromey, Ian Lance Taylor reported there are C compilers +# that will create temporary files in the current directory regardless of +# the output directory. Thus, making CWD read-only will cause this test +# to fail, enabling locking or at least warning the user not to do parallel +# builds. +chmod -w . +save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -o out/conftest2.o" +echo "$progname:829: checking if $compiler supports -c -o file.o" >&5 +if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + echo "$ac_t"no 1>&6 + compiler_c_o=no + else + echo "$ac_t"yes 1>&6 + compiler_c_o=yes + fi +else + # Append any errors to the config.log. + cat out/conftest.err 1>&5 + compiler_c_o=no + echo "$ac_t"no 1>&6 +fi +CFLAGS="$save_CFLAGS" +chmod u+w . +$rm conftest* out/* +rmdir out +cd .. +rmdir conftest +$rm -r conftest 2>/dev/null + +if test x"$compiler_c_o" = x"yes"; then + # Check to see if we can write to a .lo + echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -c -o conftest.lo" + echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5 +if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_o_lo=no + else + echo "$ac_t"yes 1>&6 + compiler_o_lo=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_o_lo=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + compiler_o_lo=no +fi + +# Check to see if we can do hard links to lock some files if needed +hard_links="nottested" +if test "$compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$ac_t$hard_links" 1>&6 + $rm conftest* + if test "$hard_links" = no; then + echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 + need_locks=warn + fi +else + need_locks=no +fi + +if test "$with_gcc" = yes; then + # Check to see if options -fno-rtti -fno-exceptions are supported by compiler + echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" + echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_rtti_exceptions=no + else + echo "$ac_t"yes 1>&6 + compiler_rtti_exceptions=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_rtti_exceptions=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* + + if test "$compiler_rtti_exceptions" = "yes"; then + no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' + else + no_builtin_flag=' -fno-builtin' + fi + +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftest.dat + if ln -s X conftest.dat 2>/dev/null; then + $rm conftest.dat + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:991: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:1015: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:1018: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +need_lib_prefix=unknown +need_version=unknown +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +archive_cmds= +archive_expsym_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +whole_archive_flag_spec= +thread_safe_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= +always_export_symbols=no +export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' +# include_expsyms should be a list of space-separated symbols to be *always* +# included in the symbol list +include_expsyms= +# exclude_expsyms can be an egrep regular expression of symbols to exclude +# it will be wrapped by ` (' and `)$', so one must not match beginning or +# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', +# as well as any symbol that contains `d'. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" +# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out +# platforms (ab)use it in PIC code, but their linkers get confused if +# the symbol is explicitly referenced. Since portable code cannot +# rely on this symbol name, it's probably fine to never include it in +# preloaded symbol tables. + +case "$host_os" in +cygwin* | mingw*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$with_gcc" != yes; then + with_gnu_ld=no + fi + ;; + +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case "$host_os" in + aix3* | aix4*) + # On AIX, the GNU linker is very broken + ld_shlibs=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=yes + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ + $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols' + + archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ + _lt_hint=1; + for symbol in `cat $export_symbols`; do + echo " \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def; + _lt_hint=`expr 1 + \$_lt_hint`; + done~ + test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ + $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' + + old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' + # can we support soname and/or expsyms with a.out? -oliva + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw*) + # dlltool doesn't understand --whole-archive et. al. + whole_archive_flag_spec= + ;; + *) + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + ;; + esac + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' + hardcode_libdir_separator=':' + if test "$with_gcc" = yes; then + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + shared_flag='-shared' + else + shared_flag='${wl}-bM:SRE' + hardcode_direct=yes + fi + allow_undefined_flag=' ${wl}-berok' + archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' + archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' + case "$host_os" in aix4.[01]|aix4.[01].*) + # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on + always_export_symbols=yes ;; + esac + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + cygwin* | mingw*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs' + fix_srcfile_path='`cygpath -w $srcfile`' + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9* | hpux10* | hpux11*) + case "$host_os" in + hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; + *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; + esac + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_minus_L=yes # Not in the search PATH, but as the default + # location of the library. + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF + fi + hardcode_libdir_flag_spec='${wl}-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3*) + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # As osf3* with the addition of the -msym flag + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case "$host_os" in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv5*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' + hardcode_libdir_flag_spec= + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=no + hardcode_shlibpath_var=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + unixware7*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 +test "$ld_shlibs" = no && can_build_shared=no + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + break + else + NM=${NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + symcode='[BCDEGRST]' + ;; +solaris*) + symcode='[BDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + $rm conftest* + cat > conftest.c <&5 + if { (eval echo $progname:1636: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:1639: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' + + cat <> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$objext conftstm.$objext + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="conftstm.$objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + global_symbol_pipe= + fi +done +if test "$pipe_works" = yes; then + echo "${ac_t}ok" 1>&6 +else + echo "${ac_t}failed" 1>&6 +fi + +if test -z "$global_symbol_pipe"; then + global_symbol_to_cdecl= +fi + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$hardcode_shlibpath_var" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$ac_t$hardcode_action" 1>&6 + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linkers may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" 1>&6 +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +file_magic_cmd= +file_magic_test_file= +deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [regex]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + ;; + +aix4*) + version_type=linux + # AIX has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + # We preserve .a as extension for shared libraries though AIX4.2 + # and later linker supports .so + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' + shlibpath_var=LIBPATH + deplibs_check_method=pass_all + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + deplibs_check_method=pass_all + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + export_dynamic_flag_spec=-rdynamic + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw*) + version_type=windows + need_version=no + need_lib_prefix=no + if test "$with_gcc" = yes; then + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' + else + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' + fi + dynamic_linker='Win32 ld.exe' + deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + file_magic_cmd='${OBJDUMP} -f' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case "$version_type" in + freebsd-elf*) + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + deplibs_check_method=unknown + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case "$host_os" in + freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + need_lib_prefix=no + need_version=no + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=irix + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' + case "$host_os" in + irix5*) + libsuff= shlibsuff= + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case "$LD" in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib${libsuff}/libc.so*` + deplibs_check_method='pass_all' + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd*) + version_type=sunos + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + ;; + +openbsd*) + version_type=sunos + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + need_version=no + fi + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_version=no + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + shlibpath_var=LD_LIBRARY_PATH + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method='file_magic COFF format alpha shared library' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + deplibs_check_method='pass_all' + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" + file_magic_cmd=/usr/bin/file + file_magic_test_file=/lib/libc.so + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case "$host_vendor" in + ncr) + deplibs_check_method='pass_all' + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + esac + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" 1>&6 +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in +# configure.in, otherwise build static only libraries. +case "$host_os" in +cygwin* | mingw* | os2*) + if test x$can_build_shared = xyes; then + test x$enable_win32_dll = xno && can_build_shared=no + echo "checking if package supports dlls... $can_build_shared" 1>&6 + fi +;; +esac + +if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then + case "$deplibs_check_method" in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac +fi + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + test "$enable_shared" = yes && enable_static=no + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else +if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then + lt_cv_dlopen=no lt_cv_dlopen_libs= +echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 +echo "$progname:2212: checking for dlopen in -ldl" >&5 +ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dlopen""... $ac_c" 1>&6 +echo "$progname:2252: checking for dlopen" >&5 +if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +dlopen(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2282: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_dlopen=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_dlopen=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 +echo "$progname:2299: checking for dld_link in -ldld" >&5 +ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load""... $ac_c" 1>&6 +echo "$progname:2339: checking for shl_load" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +shl_load(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shl_load=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shl_load=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 +echo "$progname:2387: checking for shl_load in -ldld" >&5 +ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +fi + + +fi + + +fi + + +fi + + +fi + +fi + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + fi + + case "$lt_cv_dlopen" in + dlopen) +for ac_hdr in dlfcn.h; do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "$progname:2452: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int fnord = 0; +EOF +ac_try="$ac_compile >/dev/null 2>conftest.out" +{ (eval echo $progname:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +done + + if test "x$ac_cv_header_dlfcn_h" = xyes; then + CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + fi + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2490: checking whether a program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self=cross + else + cat > conftest.c < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self" 1>&6 + + if test "$lt_cv_dlopen_self" = yes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2563: checking whether a statically linked program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self_static=cross + else + cat > conftest.c < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self_static=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self_static=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 +fi + ;; + esac + + case "$lt_cv_dlopen_self" in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case "$lt_cv_dlopen_self_static" in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" +if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ltecho="$CONFIG_SHELL \$0 --fallback-echo" +fi +LTSHELL="$SHELL" + +LTCONFIG_VERSION="$VERSION" + +# Only quote variables if we're using ltmain.sh. +case "$ltmain" in +*.sh) + # Now quote all the things that may contain metacharacters. + for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ + AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ + reload_flag reload_cmds wl \ + pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ + thread_safe_flag_spec whole_archive_flag_spec libname_spec \ + library_names_spec soname_spec \ + RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ + file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ + hardcode_libdir_flag_spec hardcode_libdir_separator \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case "$ltecho" in + *'\$0 --fallback-echo"') + ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + + trap "$rm \"$ofile\"; exit 1" 1 2 15 + echo "creating $ofile" + $rm "$ofile" + cat < "$ofile" +#! $SHELL + +# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +### BEGIN LIBTOOL CONFIG +EOF + cfgfile="$ofile" + ;; + +*) + # Double-quote the variables that need it (for aesthetics). + for var in old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do + eval "$var=\\\"\$var\\\"" + done + + # Just create a config file. + cfgfile="$ofile.cfg" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + echo "creating $cfgfile" + $rm "$cfgfile" + cat < "$cfgfile" +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +EOF + ;; +esac + +cat <> "$cfgfile" +# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ +# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ +# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ +# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# The version of $progname that generated this script. +LTCONFIG_VERSION=$LTCONFIG_VERSION + +# Shell to use when invoking shell scripts. +SHELL=$LTSHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$ltecho + +# The archiver. +AR=$AR + +# The default C compiler. +CC=$CC + +# The linker used to build libraries. +LD=$LD + +# Whether we need hard or soft links. +LN_S=$LN_S + +# A BSD-compatible nm program. +NM=$NM + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$reload_flag +reload_cmds=$reload_cmds + +# How to pass a linker flag through the compiler. +wl=$wl + +# Object file suffix (normally "o"). +objext="$objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$pic_flag + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$compiler_c_o + +# Can we write directly to a .lo ? +compiler_o_lo=$compiler_o_lo + +# Must we lock files when doing compilation ? +need_locks=$need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$link_static_flag + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$RANLIB +old_archive_cmds=$old_archive_cmds +old_postinstall_cmds=$old_postinstall_cmds +old_postuninstall_cmds=$old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$old_archive_from_new_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$archive_cmds +archive_expsym_cmds=$archive_expsym_cmds +postinstall_cmds=$postinstall_cmds +postuninstall_cmds=$postuninstall_cmds + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$global_symbol_to_cdecl + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$hardcode_libdir_separator + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$include_expsyms + +EOF + +case "$ltmain" in +*.sh) + echo '### END LIBTOOL CONFIG' >> "$ofile" + echo >> "$ofile" + case "$host_os" in + aix3*) + cat <<\EOF >> "$ofile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # Append the ltmain.sh script. + sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + + chmod +x "$ofile" + ;; + +*) + # Compile the libtool program. + echo "FIXME: would compile $ltmain" + ;; +esac + +test -n "$cache_file" || exit 0 + +# AC_CACHE_SAVE +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/subsys/win32k/freetype/builds/unix/ltmain.sh b/subsys/win32k/freetype/builds/unix/ltmain.sh new file mode 100644 index 0000000..ab65054 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/ltmain.sh @@ -0,0 +1,4012 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + exit 0 + ;; + + --config) + sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0 + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + user_target=no + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + if test "$user_target" != "no"; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit 1 + fi + user_target=next + ;; + + -static) + build_old_libs=yes + continue + ;; + esac + + case "$user_target" in + next) + # The next one is the -o target name + user_target=yes + continue + ;; + yes) + # We got the output file + user_target=set + libobj="$arg" + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + case "$user_target" in + set) + ;; + no) + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + *) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit 1 + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSfmso]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $libobj" + else + removelist="$libobj" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit 1" 1 2 15 + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit 1" 1 2 15 + else + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until ln "$0" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + if test "$build_old_libs" = yes; then + lo_libobj="$libobj" + dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$libobj"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + + if test -d "$dir"; then + $show "$rm $libobj" + $run $rm $libobj + else + $show "$mkdir $dir" + $run $mkdir $dir + status=$? + if test $status -ne 0 && test ! -d $dir; then + exit $status + fi + fi + fi + if test "$compiler_o_lo" = yes; then + output_obj="$libobj" + command="$command -o $output_obj" + elif test "$compiler_c_o" = yes; then + output_obj="$obj" + command="$command -o $output_obj" + fi + + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed, then go on to compile the next one + if test x"$output_obj" != x"$libobj"; then + $show "$mv $output_obj $libobj" + if $run $mv $output_obj $libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag" && test "$build_old_libs" = yes; then + # Rename the .lo from within objdir to obj + if test -f $obj; then + $show $rm $obj + $run $rm $obj + fi + + $show "$mv $libobj $obj" + if $run $mv $libobj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` + libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + # Now arrange that obj and lo_libobj become the same file + $show "(cd $xdir && $LN_S $baseobj $libobj)" + if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then + exit 0 + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + command="$base_compile $srcfile" + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + output_obj="$obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed + if test x"$output_obj" != x"$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + else + # Move the .lo from within objdir + $show "$mv $libobj $lo_libobj" + if $run $mv $libobj $lo_libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + fi + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $rm "$lockfile" + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invokation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + + # This is a source program that is used to create dlls on Windows + # Don't remove nor modify the starting and closing comments +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ + # This is a source program that is used to create import libraries + # on Windows for dlls which lack them. Don't remove nor modify the + # starting and closing comments +# /* impgen.c starts here */ +# /* Copyright (C) 1999 Free Software Foundation, Inc. +# +# This file is part of GNU libtool. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# */ +# +# #include /* for printf() */ +# #include /* for open(), lseek(), read() */ +# #include /* for O_RDONLY, O_BINARY */ +# #include /* for strdup() */ +# +# static unsigned int +# pe_get16 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[2]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 2); +# return b[0] + (b[1]<<8); +# } +# +# static unsigned int +# pe_get32 (fd, offset) +# int fd; +# int offset; +# { +# unsigned char b[4]; +# lseek (fd, offset, SEEK_SET); +# read (fd, b, 4); +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# static unsigned int +# pe_as32 (ptr) +# void *ptr; +# { +# unsigned char *b = ptr; +# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); +# } +# +# int +# main (argc, argv) +# int argc; +# char *argv[]; +# { +# int dll; +# unsigned long pe_header_offset, opthdr_ofs, num_entries, i; +# unsigned long export_rva, export_size, nsections, secptr, expptr; +# unsigned long name_rvas, nexp; +# unsigned char *expdata, *erva; +# char *filename, *dll_name; +# +# filename = argv[1]; +# +# dll = open(filename, O_RDONLY|O_BINARY); +# if (!dll) +# return 1; +# +# dll_name = filename; +# +# for (i=0; filename[i]; i++) +# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') +# dll_name = filename + i +1; +# +# pe_header_offset = pe_get32 (dll, 0x3c); +# opthdr_ofs = pe_header_offset + 4 + 20; +# num_entries = pe_get32 (dll, opthdr_ofs + 92); +# +# if (num_entries < 1) /* no exports */ +# return 1; +# +# export_rva = pe_get32 (dll, opthdr_ofs + 96); +# export_size = pe_get32 (dll, opthdr_ofs + 100); +# nsections = pe_get16 (dll, pe_header_offset + 4 +2); +# secptr = (pe_header_offset + 4 + 20 + +# pe_get16 (dll, pe_header_offset + 4 + 16)); +# +# expptr = 0; +# for (i = 0; i < nsections; i++) +# { +# char sname[8]; +# unsigned long secptr1 = secptr + 40 * i; +# unsigned long vaddr = pe_get32 (dll, secptr1 + 12); +# unsigned long vsize = pe_get32 (dll, secptr1 + 16); +# unsigned long fptr = pe_get32 (dll, secptr1 + 20); +# lseek(dll, secptr1, SEEK_SET); +# read(dll, sname, 8); +# if (vaddr <= export_rva && vaddr+vsize > export_rva) +# { +# expptr = fptr + (export_rva - vaddr); +# if (export_rva + export_size > vaddr + vsize) +# export_size = vsize - (export_rva - vaddr); +# break; +# } +# } +# +# expdata = (unsigned char*)malloc(export_size); +# lseek (dll, expptr, SEEK_SET); +# read (dll, expdata, export_size); +# erva = expdata - export_rva; +# +# nexp = pe_as32 (expdata+24); +# name_rvas = pe_as32 (expdata+32); +# +# printf ("EXPORTS\n"); +# for (i = 0; i&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test $# -gt 0; do + arg="$1" + shift + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit 1 + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case "$arg" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: not more than one -exported-symbols argument allowed" + exit 1 + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + absdir="$dir" + fi + dir="$absdir" + ;; + esac + case " $deplibs " in + *" $arg "*) ;; + *) deplibs="$deplibs $arg";; + esac + case " $lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir";; + esac + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + dllsearchdir=`cd "$dir" && pwd || echo "$dir"` + case ":$dllsearchpath:" in + ::) dllsearchpath="$dllsearchdir";; + *":$dllsearchdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dllsearchdir";; + esac + ;; + esac + ;; + + -l*) + if test "$arg" = "-lc"; then + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + # These systems don't actually have c library (as such) + continue + ;; + esac + elif test "$arg" = "-lm"; then + case "$host" in + *-*-cygwin* | *-*-beos*) + # These systems don't actually have math library (as such) + continue + ;; + esac + fi + deplibs="$deplibs $arg" + ;; + + -module) + module=yes + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.obj | *.a | *.lib) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` + prev= + fi + libobjs="$libobjs $arg" + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If the library was installed with an old release of libtool, + # it will not redefine variable installed. + installed=yes + + # Read the .la file + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + + if test "X$installed" = Xyes; then + dir="$libdir" + else + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + fi + + if test -n "$dependency_libs"; then + # Extract -R and -L from dependency_libs + temp_deplibs= + for deplib in $dependency_libs; do + case "$deplib" in + -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + case " $rpath $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + -L*) case "$compile_command $temp_deplibs " in + *" $deplib "*) ;; + *) temp_deplibs="$temp_deplibs $deplib";; + esac + temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'` + case " $lib_search_path " in + *" $temp_dir "*) ;; + *) lib_search_path="$lib_search_path $temp_dir";; + esac + ;; + *) temp_deplibs="$temp_deplibs $deplib";; + esac + done + dependency_libs="$temp_deplibs" + fi + + if test -z "$libdir"; then + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$deplibs$dependency_libs" + compile_command="$compile_command $dir/$old_library$dependency_libs" + finalize_command="$finalize_command $dir/$old_library$dependency_libs" + continue + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking statically, + # we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # We need an absolute path. + case "$dir" in + [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + absdir="$dir" + fi + ;; + esac + + # This is the magic to use -rpath. + # Skip directories that are in the system default run-time + # search path, unless they have been requested with -R. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + + lib_linked=yes + case "$hardcode_action" in + immediate | unsupported) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + deplibs="$deplibs $dir/$linklib" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2*) + dllsearchdir=`cd "$dir" && pwd || echo "$dir"` + if test -n "$dllsearchpath"; then + dllsearchpath="$dllsearchpath:$dllsearchdir" + else + dllsearchpath="$dllsearchdir" + fi + ;; + esac + elif test "$hardcode_minus_L" = no; then + case "$host" in + *-*-sunos*) + compile_shlibpath="$compile_shlibpath$dir:" + ;; + esac + case "$compile_command " in + *" -L$dir "*) ;; + *) compile_command="$compile_command -L$dir";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + case ":$compile_shlibpath:" in + *":$dir:"*) ;; + *) compile_shlibpath="$compile_shlibpath$dir:";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -l$name" + else + lib_linked=no + fi + ;; + + relink) + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $absdir/$linklib" + deplibs="$deplibs $absdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + case "$compile_command " in + *" -L$absdir "*) ;; + *) compile_command="$compile_command -L$absdir";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -L$absdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case ":$compile_shlibpath:" in + *":$absdir:"*) ;; + *) compile_shlibpath="$compile_shlibpath$absdir:";; + esac + compile_command="$compile_command -l$name" + deplibs="$deplibs -l$name" + else + lib_linked=no + fi + ;; + + *) + lib_linked=no + ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit 1 + fi + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + case "$finalize_command " in + *" -L$libdir "*) ;; + *) finalize_command="$finalize_command -L$libdir";; + esac + finalize_command="$finalize_command -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case ":$finalize_shlibpath:" in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:";; + esac + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + case "$finalize_command " in + *" -L$dir "*) ;; + *) finalize_command="$finalize_command -L$libdir";; + esac + finalize_command="$finalize_command -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + case "$compile_command " in + *" -L$dir "*) ;; + *) compile_command="$compile_command -L$dir";; + esac + compile_command="$compile_command -l$name" + case "$finalize_command " in + *" -L$dir "*) ;; + *) finalize_command="$finalize_command -L$dir";; + esac + finalize_command="$finalize_command -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *.a | *.lib) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into archives" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$outputname" in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + libext=al + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + dependency_libs="$deplibs" + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + current="$2" + revision="$3" + age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case "$version_type" in + none) ;; + + irix) + major=`expr $current - $age + 1` + versuffix="$major.$revision" + verstring="sgi$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test $loop != 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="sgi$major.$iface:$verstring" + done + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + windows) + # Like Linux, but with '-' rather than '.', since we only + # want one extension on Windows 95. + major=`expr $current - $age` + versuffix="-$major-$age-$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + verstring="0.0" + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + dependency_libs="$deplibs" + case "$host" in + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *) + # Add libc to deplibs on all other systems. + deplibs="$deplibs -lc" + ;; + esac + fi + + # Create the output directory, or remove our outputs if we need to. + if test -d $output_objdir; then + $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" + $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* + else + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + if test "$build_libtool_libs" = yes; then + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case "$deplibs_check_method" in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behaviour. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | sed 's/.* -> //'` + case "$potliblink" in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | sed 10q \ + | egrep "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | + grep . >/dev/null; then + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + echo "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Ensure that we have .o objects for linkers which dislike .lo + # (e.g. aix) in case we are running --disable-static + for obj in $libobjs; do + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + if test ! -f $xdir/$oldobj; then + $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" + $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? + fi + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + eval cmds=\"$export_symbols_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linkopts="$linkopts $flag" + fi + + # Do each of the archive commands. + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval cmds=\"$archive_expsym_cmds\" + else + eval cmds=\"$archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + *.lo | *.o | *.obj) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show $rm $libobj + $run $rm $libobj + xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$libobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + $show "(cd $xdir && $LN_S $oldobj $baseobj)" + $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + ;; + + # Anything else should be a program. + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$compile_rpath " in + *" $libdir "*) ;; + *) compile_rpath="$compile_rpath $libdir" ;; + esac + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + + # Create the binary in the object directory, then wrap it. + if test ! -d $output_objdir; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test $status -ne 0 && test ! -d $output_objdir; then + exit $status + fi + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case "$dlsyms" in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`echo "$arg" | sed -e 's%^.*/%%'` + $run eval 'echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{\ +" + + sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \ + -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \ + < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr_t) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case "$host" in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $0 --fallback-echo"; then + case "$0" in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; + *) qecho="$SHELL `pwd`/$0 --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`echo $output|sed 's,.exe$,,'` ;; + esac + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + link_against_libtool_libs='$link_against_libtool_libs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + echo >> $output "\ + program=lt-'$outputname' + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if (cd \"\$thisdir\" && eval \$relink_command); then : + else + $rm \"\$progdir/\$file\" + exit 1 + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + *-*-cygwin* | *-*-mingw | *-*-os2*) + # win32 systems need to use the prog path for dll + # lookup to work + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + *) + $echo >> $output "\ + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test $status -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case "$xlib" in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test $status -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + # Ensure that we have .o objects in place in case we decided + # not to build a shared library, and have fallen back to building + # static libs even though --disable-static was passed! + for oldobj in $oldobjs; do + if test ! -f $oldobj; then + xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$oldobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` + obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + $show "(cd $xdir && ${LN_S} $obj $baseobj)" + $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? + fi + done + + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + if test -n "$xrpath"; then + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + done + dependency_libs="$temp_xrpath $dependency_libs" + fi + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + fi + $rm $output + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $? + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a | *.lib) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + + if test $# -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.o | *.obj) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + link_against_libtool_libs= + relink_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir="$tmpdir/libtool-$$" + if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : + else + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit 0 + + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "----------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved enviroment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/subsys/win32k/freetype/builds/unix/mkinstalldirs b/subsys/win32k/freetype/builds/unix/mkinstalldirs new file mode 100644 index 0000000..d0fd194 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/subsys/win32k/freetype/builds/unix/unix.in b/subsys/win32k/freetype/builds/unix/unix.in new file mode 100644 index 0000000..9aeea24 --- /dev/null +++ b/subsys/win32k/freetype/builds/unix/unix.in @@ -0,0 +1,216 @@ +# +# FreeType 2 configuration rules templates for Unix + configure +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := @RMF@ +DELDIR := @RMDIR@ +SEP := / +HOSTSEP := $(SEP) +BUILD := $(TOP)/builds/unix +PLATFORM := unix +CC := @CC@ + +INSTALL := @INSTALL@ +INSTALL_DATA := @INSTALL_DATA@ +MKINSTALLDIRS := $(BUILD)/mkinstalldirs + +LIBTOOL := $(BUILD)/libtool + + +# don't use `:=' here since the path stuff will be included after this file +# +FTSYS_SRC = @FTSYS_SRC@ + +DISTCLEAN += $(BUILD)/config.cache \ + $(BUILD)/config.log \ + $(BUILD)/config.status \ + $(BUILD)/unix.mk \ + $(BUILD)/ftconfig.h \ + $(LIBTOOL) + + +# Standard installation variables. +# +prefix := @prefix@ +exec_prefix := @exec_prefix@ +libdir := @libdir@ +bindir := @bindir@ +includedir := @includedir@ + +version_info := @version_info@ + + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f $TOP/Makefile setup [options] +# make -f $TOP/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := lo +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := la +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +CFLAGS := -c @XX_CFLAGS@ @CFLAGS@ + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := @XX_ANSIFLAGS@ + +# C compiler to use -- we use libtool! +# +# +CCraw := $(CC) +CC := $(LIBTOOL) --mode=compile $(CCraw) + +# Linker flags. +# +LDFLAGS := @LDFLAGS@ + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + + # The cleanup targets. + # + clean_freetype: clean_freetype_unix + distclean_freetype: distclean_freetype_unix + + + # Unix installation and deinstallation targets. + install: $(FT_LIBRARY) + $(MKINSTALLDIRS) $(libdir) \ + $(includedir)/freetype/config \ + $(includedir)/freetype/internal + $(LIBTOOL) --mode=install $(INSTALL) $(FT_LIBRARY) $(libdir) + -for P in $(PUBLIC_H) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype ; \ + done + -for P in $(BASE_H) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype/internal ; \ + done + -for P in $(CONFIG_H) ; do \ + $(INSTALL_DATA) $$P $(includedir)/freetype/config ; \ + done + + uninstall: + -$(LIBTOOL) --mode=uninstall $(RM) $(libdir)/$(LIBRARY).$A + -$(DELETE) $(includedir)/freetype/config/* + -$(DELDIR) $(includedir)/freetype/config + -$(DELETE) $(includedir)/freetype/internal/* + -$(DELDIR) $(includedir)/freetype/internal + -$(DELETE) $(includedir)/freetype/* + -$(DELDIR) $(includedir)/freetype + + + # Unix cleaning and distclean rules. + # + clean_freetype_unix: + -$(DELETE) $(BASE_OBJECTS) $(OBJ_M) $(OBJ_S) + -$(DELETE) $(subst $O,$(SO),$(BASE_OBJECTS) $(OBJ_M) $(OBJ_S)) \ + $(CLEAN) + + distclean_freetype_unix: clean_freetype_unix + -$(DELETE) $(FT_LIBRARY) + -$(DELETE) $(OBJ_DIR)/.libs/* + -$(DELDIR) $(OBJ_DIR)/.libs + -$(DELETE) *.orig *~ core *.core $(DISTCLEAN) + + + # Librarian to use to build the library + # + FT_LIBRARIAN := $(LIBTOOL) --mode=link $(CCraw) + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + $(FT_LIBRARIAN) -o $@ $(OBJECTS_LIST) \ + -rpath $(libdir) -version-info $(version_info) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/win32/detect.mk b/subsys/win32k/freetype/builds/win32/detect.mk new file mode 100644 index 0000000..c2bf8cc --- /dev/null +++ b/subsys/win32k/freetype/builds/win32/detect.mk @@ -0,0 +1,90 @@ +# +# FreeType 2 configuration file to detect a Win32 host platform. +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifeq ($(PLATFORM),ansi) + + # Detecting Windows NT is easy, as the OS variable must be defined and + # contains `Windows_NT'. Untested with Windows 2K, but I guess it should + # work... + # + ifeq ($(OS),Windows_NT) + is_windows := 1 + + # We test for the COMSPEC environment variable, then run the `ver' + # command-line program to see if its output contains the word `Windows'. + # + # If this is true, we are running a win32 platform (or an emulation). + # + else + ifdef COMSPEC + is_windows := $(findstring Windows,$(strip $(shell ver))) + endif + endif # test NT + + ifdef is_windows + + PLATFORM := win32 + DELETE := del + COPY := copy + + CONFIG_FILE := w32-gcc.mk # gcc Makefile by default + SEP := / + ifeq ($(firstword $(CC)),cc) + CC := gcc + endif + + # additionally, we provide hooks for various other compilers + # + ifneq ($(findstring visualc,$(MAKECMDGOALS)),) # Visual C/C++ + CONFIG_FILE := w32-vcc.mk + SEP := $(BACKSLASH) + CC := cl + visualc: setup + endif + + ifneq ($(findstring watcom,$(MAKECMDGOALS)),) # Watcom C/C++ + CONFIG_FILE := w32-wat.mk + SEP := $(BACKSLASH) + CC := wcc386 + watcom: setup + endif + + ifneq ($(findstring visualage,$(MAKECMDGOALS)),) # Visual Age C++ + CONFIG_FILE := w32-icc.mk + SEP := $(BACKSLASH) + CC := icc + visualage: setup + endif + + ifneq ($(findstring lcc,$(MAKECMDGOALS)),) # LCC-Win32 + CONFIG_FILE := w32-lcc.mk + SEP := $(BACKSLASH) + CC := lcc + lcc: setup + endif + + ifneq ($(findstring devel,$(MAKECMDGOALS)),) # development target + CONFIG_FILE := w32-dev.mk + CC := gcc + SEP := / + devel: setup + endif + + setup: dos_setup + + endif # test is_windows +endif # test PLATFORM + +# EOF diff --git a/subsys/win32k/freetype/builds/win32/w32-dev.mk b/subsys/win32k/freetype/builds/win32/w32-dev.mk new file mode 100644 index 0000000..8eea55a --- /dev/null +++ b/subsys/win32k/freetype/builds/win32/w32-dev.mk @@ -0,0 +1,140 @@ +# +# FreeType 2 Configuration rules for Win32 + GCC +# +# Development version without optimizations. +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. +# +# NOTE: This version requires that GNU Make is invoked from the Windows +# Shell (_not_ Cygwin BASH)! +# + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O0 -Wall -W +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/win32/w32-gcc.mk b/subsys/win32k/freetype/builds/win32/w32-gcc.mk new file mode 100644 index 0000000..3501a79 --- /dev/null +++ b/subsys/win32k/freetype/builds/win32/w32-gcc.mk @@ -0,0 +1,138 @@ +# +# FreeType 2 Configuration rules for Win32 + GCC +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. +# +# NOTE: This version requires that GNU Make is invoked from the Windows +# Shell (_not_ Cygwin BASH)! +# + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := gcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := o +SO := o + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := a +SA := a + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := libfreetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -l + + +# Target flag. +# +T := -o # Don't remove this comment line! We need the space after `-o'. + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g -O6 -Wall +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := -ansi -pedantic + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # Librarian to use to build the static library + # + FT_LIBRARIAN := $(AR) -r + + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + -$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_LIBRARY)) 2> nul + $(FT_LIBRARIAN) $@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/win32/w32-icc.mk b/subsys/win32k/freetype/builds/win32/w32-icc.mk new file mode 100644 index 0000000..504579e --- /dev/null +++ b/subsys/win32k/freetype/builds/win32/w32-icc.mk @@ -0,0 +1,122 @@ +# +# FreeType 2 Configuration rules for Win32 + IBM Visual Age C++ +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. +# + +DELETE := del +SEP := $(strip \ ) +HOSTSEP := $(strip \ ) +BUILD := $(TOP)$(SEP)config$(SEP)win32 +PLATFORM := win32 +CC := icc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := obj +SO := obj + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := lib +SA := lib + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := freetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := /I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := /D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := /Fl + + +# Target flag. +# +T := /Fo + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +ifndef CFLAGS + CFLAGS := /Q- /Gd+ /O2 /G5 /W3 /C +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSI_FLAGS := /Sa + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + lib /nologo /out:$@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/win32/w32-lcc.mk b/subsys/win32k/freetype/builds/win32/w32-lcc.mk new file mode 100644 index 0000000..476de14 --- /dev/null +++ b/subsys/win32k/freetype/builds/win32/w32-lcc.mk @@ -0,0 +1,130 @@ +# +# FreeType 2 Configuration rules for Win32 + LCC +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := lcc + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := obj +SO := obj + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := lib +SA := lib + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := freetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := -I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := -D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := -Fl + + +# Target flag. +# +T := -Fo + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := -c -g2 -O +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + lcclib /out:$(subst $(SEP),\\,$@) \ + $(subst $(SEP),\\,$(OBJECTS_LIST)) + +endif + +# EOF diff --git a/subsys/win32k/freetype/builds/win32/w32-vcc.mk b/subsys/win32k/freetype/builds/win32/w32-vcc.mk new file mode 100644 index 0000000..955f44a --- /dev/null +++ b/subsys/win32k/freetype/builds/win32/w32-vcc.mk @@ -0,0 +1,129 @@ +# +# FreeType 2 Configuration rules for Win32 + Visual C/C++ +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +ifndef TOP + TOP := . +endif + +DELETE := del +SEP := / +HOSTSEP := $(strip \ ) +BUILD := $(TOP)/builds/win32 +PLATFORM := win32 +CC := cl + +# The directory where all object files are placed. +# +# Note that this is not $(TOP)/obj! +# This lets you build the library in your own directory with something like +# +# set TOP=.../path/to/freetype2/top/dir... +# mkdir obj +# make -f %TOP%/Makefile setup [options] +# make -f %TOP%/Makefile +# +OBJ_DIR := obj + + +# The directory where all library files are placed. +# +# By default, this is the same as $(OBJ_DIR), however, this can be changed +# to suit particular needs. +# +LIB_DIR := $(OBJ_DIR) + + +# The object file extension (for standard and static libraries). This can be +# .o, .tco, .obj, etc., depending on the platform. +# +O := obj +SO := obj + +# The library file extension (for standard and static libraries). This can +# be .a, .lib, etc., depending on the platform. +# +A := lib +SA := lib + + +# The name of the final library file. Note that the DOS-specific Makefile +# uses a shorter (8.3) name. +# +LIBRARY := freetype + + +# Path inclusion flag. Some compilers use a different flag than `-I' to +# specify an additional include path. Examples are `/i=' or `-J'. +# +I := /I + + +# C flag used to define a macro before the compilation of a given source +# object. Usually is `-D' like in `-DDEBUG'. +# +D := /D + + +# The link flag used to specify a given library file on link. Note that +# this is only used to compile the demo programs, not the library itself. +# +L := /Fl + + +# Target flag. +# +T := /Fo + + +# C flags +# +# These should concern: debug output, optimization & warnings. +# +# Use the ANSIFLAGS variable to define the compiler flags used to enfore +# ANSI compliance. +# +ifndef CFLAGS + CFLAGS := /nologo /c /Ox /G5 /W3 /WX +endif + +# ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant. +# +ANSIFLAGS := /Za + + +ifdef BUILD_FREETYPE + + # Now include the main sub-makefile. It contains all the rules used to + # build the library with the previous variables defined. + # + include $(TOP)/builds/freetype.mk + + # The cleanup targets. + # + clean_freetype: clean_freetype_dos + distclean_freetype: distclean_freetype_dos + + # This final rule is used to link all object files into a single library. + # It is part of the system-specific sub-Makefile because not all + # librarians accept a simple syntax like + # + # librarian library_file {list of object files} + # + $(FT_LIBRARY): $(OBJECTS_LIST) + lib /nologo /out:$@ $(OBJECTS_LIST) + +endif + +# EOF diff --git a/subsys/win32k/freetype/ctype.c b/subsys/win32k/freetype/ctype.c new file mode 100644 index 0000000..42689b4 --- /dev/null +++ b/subsys/win32k/freetype/ctype.c @@ -0,0 +1,706 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/rtl/ctype.c + * PURPOSE: Character type and conversion functions + * PROGRAMMERS: ??? + * Eric Kohl + * HISTORY: ???: Created + * 10/01/2000: Added missing functions and changed + * all functions to use ctype table + */ + +#undef __MSVCRT__ +#include +#include + +#undef _pctype + +#define upalpha ('A' - 'a') + + +unsigned short _ctype[] = { + 0, /* , 0xFFFF */ + _CONTROL, /* CTRL+@, 0x00 */ + _CONTROL, /* CTRL+A, 0x01 */ + _CONTROL, /* CTRL+B, 0x02 */ + _CONTROL, /* CTRL+C, 0x03 */ + _CONTROL, /* CTRL+D, 0x04 */ + _CONTROL, /* CTRL+E, 0x05 */ + _CONTROL, /* CTRL+F, 0x06 */ + _CONTROL, /* CTRL+G, 0x07 */ + _CONTROL, /* CTRL+H, 0x08 */ + _CONTROL | _SPACE, /* CTRL+I, 0x09 */ + _CONTROL | _SPACE, /* CTRL+J, 0x0a */ + _CONTROL | _SPACE, /* CTRL+K, 0x0b */ + _CONTROL | _SPACE, /* CTRL+L, 0x0c */ + _CONTROL | _SPACE, /* CTRL+M, 0x0d */ + _CONTROL, /* CTRL+N, 0x0e */ + _CONTROL, /* CTRL+O, 0x0f */ + _CONTROL, /* CTRL+P, 0x10 */ + _CONTROL, /* CTRL+Q, 0x11 */ + _CONTROL, /* CTRL+R, 0x12 */ + _CONTROL, /* CTRL+S, 0x13 */ + _CONTROL, /* CTRL+T, 0x14 */ + _CONTROL, /* CTRL+U, 0x15 */ + _CONTROL, /* CTRL+V, 0x16 */ + _CONTROL, /* CTRL+W, 0x17 */ + _CONTROL, /* CTRL+X, 0x18 */ + _CONTROL, /* CTRL+Y, 0x19 */ + _CONTROL, /* CTRL+Z, 0x1a */ + _CONTROL, /* CTRL+[, 0x1b */ + _CONTROL, /* CTRL+\, 0x1c */ + _CONTROL, /* CTRL+], 0x1d */ + _CONTROL, /* CTRL+^, 0x1e */ + _CONTROL, /* CTRL+_, 0x1f */ + _SPACE | _BLANK, /* ` ', 0x20 */ + _PUNCT, /* `!', 0x21 */ + _PUNCT, /* 0x22 */ + _PUNCT, /* `#', 0x23 */ + _PUNCT, /* `$', 0x24 */ + _PUNCT, /* `%', 0x25 */ + _PUNCT, /* `&', 0x26 */ + _PUNCT, /* 0x27 */ + _PUNCT, /* `(', 0x28 */ + _PUNCT, /* `)', 0x29 */ + _PUNCT, /* `*', 0x2a */ + _PUNCT, /* `+', 0x2b */ + _PUNCT, /* `,', 0x2c */ + _PUNCT, /* `-', 0x2d */ + _PUNCT, /* `.', 0x2e */ + _PUNCT, /* `/', 0x2f */ + _DIGIT | _HEX, /* `0', 0x30 */ + _DIGIT | _HEX, /* `1', 0x31 */ + _DIGIT | _HEX, /* `2', 0x32 */ + _DIGIT | _HEX, /* `3', 0x33 */ + _DIGIT | _HEX, /* `4', 0x34 */ + _DIGIT | _HEX, /* `5', 0x35 */ + _DIGIT | _HEX, /* `6', 0x36 */ + _DIGIT | _HEX, /* `7', 0x37 */ + _DIGIT | _HEX, /* `8', 0x38 */ + _DIGIT | _HEX, /* `9', 0x39 */ + _PUNCT, /* `:', 0x3a */ + _PUNCT, /* `;', 0x3b */ + _PUNCT, /* `<', 0x3c */ + _PUNCT, /* `=', 0x3d */ + _PUNCT, /* `>', 0x3e */ + _PUNCT, /* `?', 0x3f */ + _PUNCT, /* `@', 0x40 */ + _UPPER | _HEX, /* `A', 0x41 */ + _UPPER | _HEX, /* `B', 0x42 */ + _UPPER | _HEX, /* `C', 0x43 */ + _UPPER | _HEX, /* `D', 0x44 */ + _UPPER | _HEX, /* `E', 0x45 */ + _UPPER | _HEX, /* `F', 0x46 */ + _UPPER, /* `G', 0x47 */ + _UPPER, /* `H', 0x48 */ + _UPPER, /* `I', 0x49 */ + _UPPER, /* `J', 0x4a */ + _UPPER, /* `K', 0x4b */ + _UPPER, /* `L', 0x4c */ + _UPPER, /* `M', 0x4d */ + _UPPER, /* `N', 0x4e */ + _UPPER, /* `O', 0x4f */ + _UPPER, /* `P', 0x50 */ + _UPPER, /* `Q', 0x51 */ + _UPPER, /* `R', 0x52 */ + _UPPER, /* `S', 0x53 */ + _UPPER, /* `T', 0x54 */ + _UPPER, /* `U', 0x55 */ + _UPPER, /* `V', 0x56 */ + _UPPER, /* `W', 0x57 */ + _UPPER, /* `X', 0x58 */ + _UPPER, /* `Y', 0x59 */ + _UPPER, /* `Z', 0x5a */ + _PUNCT, /* `[', 0x5b */ + _PUNCT, /* 0x5c */ + _PUNCT, /* `]', 0x5d */ + _PUNCT, /* `^', 0x5e */ + _PUNCT, /* `_', 0x5f */ + _PUNCT, /* 0x60 */ + _LOWER | _HEX, /* `a', 0x61 */ + _LOWER | _HEX, /* `b', 0x62 */ + _LOWER | _HEX, /* `c', 0x63 */ + _LOWER | _HEX, /* `d', 0x64 */ + _LOWER | _HEX, /* `e', 0x65 */ + _LOWER | _HEX, /* `f', 0x66 */ + _LOWER, /* `g', 0x67 */ + _LOWER, /* `h', 0x68 */ + _LOWER, /* `i', 0x69 */ + _LOWER, /* `j', 0x6a */ + _LOWER, /* `k', 0x6b */ + _LOWER, /* `l', 0x6c */ + _LOWER, /* `m', 0x6d */ + _LOWER, /* `n', 0x6e */ + _LOWER, /* `o', 0x6f */ + _LOWER, /* `p', 0x70 */ + _LOWER, /* `q', 0x71 */ + _LOWER, /* `r', 0x72 */ + _LOWER, /* `s', 0x73 */ + _LOWER, /* `t', 0x74 */ + _LOWER, /* `u', 0x75 */ + _LOWER, /* `v', 0x76 */ + _LOWER, /* `w', 0x77 */ + _LOWER, /* `x', 0x78 */ + _LOWER, /* `y', 0x79 */ + _LOWER, /* `z', 0x7a */ + _PUNCT, /* `{', 0x7b */ + _PUNCT, /* `|', 0x7c */ + _PUNCT, /* `}', 0x7d */ + _PUNCT, /* `~', 0x7e */ + _CONTROL, /* 0x7f */ + 0, /* 0x80 */ + 0, /* 0x81 */ + 0, /* 0x82 */ + 0, /* 0x83 */ + 0, /* 0x84 */ + 0, /* 0x85 */ + 0, /* 0x86 */ + 0, /* 0x87 */ + 0, /* 0x88 */ + 0, /* 0x89 */ + 0, /* 0x8a */ + 0, /* 0x8b */ + 0, /* 0x8c */ + 0, /* 0x8d */ + 0, /* 0x8e */ + 0, /* 0x8f */ + 0, /* 0x90 */ + 0, /* 0x91 */ + 0, /* 0x92 */ + 0, /* 0x93 */ + 0, /* 0x94 */ + 0, /* 0x95 */ + 0, /* 0x96 */ + 0, /* 0x97 */ + 0, /* 0x98 */ + 0, /* 0x99 */ + 0, /* 0x9a */ + 0, /* 0x9b */ + 0, /* 0x9c */ + 0, /* 0x9d */ + 0, /* 0x9e */ + 0, /* 0x9f */ + 0, /* 0xa0 */ + 0, /* 0xa1 */ + 0, /* 0xa2 */ + 0, /* 0xa3 */ + 0, /* 0xa4 */ + 0, /* 0xa5 */ + 0, /* 0xa6 */ + 0, /* 0xa7 */ + 0, /* 0xa8 */ + 0, /* 0xa9 */ + 0, /* 0xaa */ + 0, /* 0xab */ + 0, /* 0xac */ + 0, /* 0xad */ + 0, /* 0xae */ + 0, /* 0xaf */ + 0, /* 0xb0 */ + 0, /* 0xb1 */ + 0, /* 0xb2 */ + 0, /* 0xb3 */ + 0, /* 0xb4 */ + 0, /* 0xb5 */ + 0, /* 0xb6 */ + 0, /* 0xb7 */ + 0, /* 0xb8 */ + 0, /* 0xb9 */ + 0, /* 0xba */ + 0, /* 0xbb */ + 0, /* 0xbc */ + 0, /* 0xbd */ + 0, /* 0xbe */ + 0, /* 0xbf */ + 0, /* 0xc0 */ + 0, /* 0xc1 */ + 0, /* 0xc2 */ + 0, /* 0xc3 */ + 0, /* 0xc4 */ + 0, /* 0xc5 */ + 0, /* 0xc6 */ + 0, /* 0xc7 */ + 0, /* 0xc8 */ + 0, /* 0xc9 */ + 0, /* 0xca */ + 0, /* 0xcb */ + 0, /* 0xcc */ + 0, /* 0xcd */ + 0, /* 0xce */ + 0, /* 0xcf */ + 0, /* 0xd0 */ + 0, /* 0xd1 */ + 0, /* 0xd2 */ + 0, /* 0xd3 */ + 0, /* 0xd4 */ + 0, /* 0xd5 */ + 0, /* 0xd6 */ + 0, /* 0xd7 */ + 0, /* 0xd8 */ + 0, /* 0xd9 */ + 0, /* 0xda */ + 0, /* 0xdb */ + 0, /* 0xdc */ + 0, /* 0xdd */ + 0, /* 0xde */ + 0, /* 0xdf */ + 0, /* 0xe0 */ + 0, /* 0xe1 */ + 0, /* 0xe2 */ + 0, /* 0xe3 */ + 0, /* 0xe4 */ + 0, /* 0xe5 */ + 0, /* 0xe6 */ + 0, /* 0xe7 */ + 0, /* 0xe8 */ + 0, /* 0xe9 */ + 0, /* 0xea */ + 0, /* 0xeb */ + 0, /* 0xec */ + 0, /* 0xed */ + 0, /* 0xee */ + 0, /* 0xef */ + 0, /* 0xf0 */ + 0, /* 0xf1 */ + 0, /* 0xf2 */ + 0, /* 0xf3 */ + 0, /* 0xf4 */ + 0, /* 0xf5 */ + 0, /* 0xf6 */ + 0, /* 0xf7 */ + 0, /* 0xf8 */ + 0, /* 0xf9 */ + 0, /* 0xfa */ + 0, /* 0xfb */ + 0, /* 0xfc */ + 0, /* 0xfd */ + 0, /* 0xfe */ + 0 /* 0xff */ +}; + +unsigned short *_pctype = _ctype + 1; +unsigned short *_pwctype = _ctype + 1; + +int _isctype (int c, int ctypeFlags) +{ + return (_pctype[(unsigned char)(c & 0xFF)] & ctypeFlags); +} + +int iswctype(wint_t wc, wctype_t wctypeFlags) +{ + return (_pwctype[(unsigned char)(wc & 0xFF)] & wctypeFlags); +} + +int isalpha(int c) +{ + return(_isctype(c, _ALPHA)); +} + +int isalnum(int c) +{ + return(_isctype(c, _ALPHA | _DIGIT)); +} + +int __isascii(int c) +{ + return ((unsigned char)c <= 0x7f); +} + +int iscntrl(int c) +{ + return(_isctype(c, _CONTROL)); +} + +int __iscsym(int c) +{ + return(isalnum(c)||(c == '_')); +} + +int __iscsymf(int c) +{ + return(isalpha(c)||(c == '_')); +} + + +int isdigit(int c) +{ + return(_isctype(c, _DIGIT)); +} + +/* +int isgraph(int c) +{ + return (_isctype (c, _PUNCT | _ALPHA | _DIGIT)); +} +*/ + +int islower(int c) +{ + return (_isctype (c, _LOWER)); +} + +int isprint(int c) +{ + return (_isctype (c, _BLANK | _PUNCT | _ALPHA | _DIGIT)); +} + +/* +int ispunct(int c) +{ + return (_isctype (c, _PUNCT)); +} +*/ + +int isspace(int c) +{ + return (_isctype (c, _SPACE)); +} + +int isupper(int c) +{ + return (_isctype (c, _UPPER)); +} + +int isxdigit(int c) +{ + return (_isctype (c, _HEX)); +} + +/* +int iswalpha(wint_t c) +{ + return (iswctype (c, _ALPHA)); +} +*/ + +int iswdigit(wint_t c) +{ + return (iswctype (c, _DIGIT)); +} + +int iswlower(wint_t c) +{ + return (iswctype (c, _LOWER)); +} + +int iswxdigit(wint_t c) +{ + return (iswctype (c, _HEX)); +} + + +/* +int __toascii(int c) +{ + return((unsigned)(c) & 0x7f); +} + +int _tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int _toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} +*/ + +int tolower(int c) +{ + if (_isctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +int toupper(int c) +{ + if (_isctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +wchar_t towlower(wchar_t c) +{ + if (iswctype (c, _UPPER)) + return (c - upalpha); + return(c); +} + +wchar_t towupper(wchar_t c) +{ + if (iswctype (c, _LOWER)) + return (c + upalpha); + return(c); +} + +/* EOF */ + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2) + { + if (*s1 == 0) + return 0; + s1++; + s2++; + } + + return *(unsigned const char *)s1 - *(unsigned const char *)(s2); +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + return 0; + do + { + if (*s1 != *s2++) + return *(unsigned const char *)s1 - *(unsigned const char *)--s2; + if (*s1++ == 0) + break; + } + while (--n != 0); + + return 0; +} + +char *strncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) + { + char *d = dst; + const char *s = src; + + do + { + if ((*d++ = *s++) == 0) + { + while (--n != 0) + *d++ = 0; + break; + } + } + while (--n != 0); + } + + return dst; +} + +void * memmove(void *dest,const void *src,size_t count) +{ + char *char_dest = (char *)dest; + char *char_src = (char *)src; + + if ((char_dest <= char_src) || (char_dest >= (char_src+count))) + { + /* non-overlapping buffers */ + while(count > 0) + { + *char_dest = *char_src; + char_dest++; + char_src++; + count--; + } + } + else + { + /* overlaping buffers */ + char_dest = (char *)dest + count - 1; + char_src = (char *)src + count - 1; + + while(count > 0) + { + *char_dest = *char_src; + char_dest--; + char_src--; + count--; + } + } + + return dest; +} + +/* FIXME: these types should be from the default includes */ + +typedef int (* _pfunccmp_t) (char *, char *); + +#define min(a,b) ((a)<(b)?(a):(b)) + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *) (parmi); \ + register TYPE *pj = (TYPE *) (parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc ( + char * a, + char * b, + int n, + int swaptype + ) +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +static inline char * +med3 ( + char * a, + char * b, + char * c, + _pfunccmp_t cmp + ) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} + + +/* EXPORTED */ +void +qsort ( + void * a, + size_t n, + size_t es, + _pfunccmp_t cmp + ) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + pm = (char *) a + (n / 2) * es; + if (n > 7) + { + pl = (char *) a; + pn = (char *) a + (n - 1) * es; + if (n > 40) + { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *) a + es; + + pc = pd = (char *) a + (n - 1) * es; + for (;;) + { + while (pb <= pc && (r = cmp(pb, a)) <= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + { + break; + } + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) /* Switch to insertion sort */ + { + for ( pm = (char *) a + es; + pm < (char *) a + n * es; + pm += es + ) + { + for ( pl = pm; + pl > (char *) a && cmp(pl - es, pl) > 0; + pl -= es + ) + { + swap(pl, pl - es); + } + } + return; + } + + pn = (char *) a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) + { + qsort(a, r / es, es, cmp); + } + if ((r = pd - pc) > es) + { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} diff --git a/subsys/win32k/freetype/docs/build b/subsys/win32k/freetype/docs/build new file mode 100644 index 0000000..93c7463 --- /dev/null +++ b/subsys/win32k/freetype/docs/build @@ -0,0 +1,264 @@ +FreeType 2 compilation how-to + + +Introduction: + +Welcome to this new beta of the FreeType 2 library. You'll find in this +document instructions on how to compile the library on your favorite +platform. + + *** UNIX USERS : Even though the FT2 build system doesn't + ************** : use the Autoconf/Automake tools, these will + ************** : be introduced in the Unix-specific parts of + ************** : the build in our final release.. + + +I. QUICK COMMAND-LINE GUIDE: +---------------------------- + + Install GNU Make, then try the following on Unix or any system with gcc: + + make // this will setup the build + make // this will build the library + + On Win32+Visual C++: + + make setup visualc // setup the build for VisualC++ on Win32 + make // build the library + + Then, go to the "demos" directory and type + + make + + To compile the demo programs.. + + If this doesn't work, read the following.. + + + +II. COMMAND-LINE COMPILATION: +----------------------------- + + Note that if you do not want to compile FreeType 2 from a command line + shell, please skip to section III below (DETAILED COMPILATION) + + FreeType 2 includes a powerful and flexible build system that allows you + to easily compile it on a great variety of platforms from the command + line. To do so, just follow these simple instructions: + + a/ Install GNU Make: + + Because GNU Make is the only Make tool supported to compile FreeType 2, + you should install it on your machine. + + Because the FT2 build system relies on many important features of GNU + Make, trying to build the library with any other Make tool will *fail*. + + + b/ Invoke "make": + + Go to the root FT2 directory, then simply invoke GNU Make from the + command line, this will launch the FreeType 2 Host Platform detection + routines. A summary will be displayed, for example, on Win32: + + ======================================================================== + FreeType build system -- automatic system detection + + The following settings are used: + + platform win32 + compiler gcc + configuration directory ./builds/win32 + configuration rules ./builds/win32/w32-gcc.mk + + If this does not correspond to your system or settings please remove + the file 'config.mk' from this directory then read the INSTALL file + for help. + + Otherwise, simply type 'make' again to build the library. + ========================================================================= + + If the detected settings correspond to your platform and compiler, + skip to step e/. Note that if your platform is completely alien to + the build system, the detected platform will be "ansi". + + + c/ Configure the build system for a different compiler: + + If the build system correctly detected your platform, but you want to + use a different compiler than the one specified in the summary (for + most platforms, gcc is the defaut compiler), simply invoke GNU Make + like : + + make setup + + For example: + + to use Visual C++ on Win32, type: "make setup visualc" + to use LCC-Win32 on Win32, type: "make setup lcc" + + The name to use is platform-dependent. The list of available + compilers for your system is available in the file + "builds//detect.mk" (note that we hope to make the list + displayed at user demand in the final release).. + + If you're satisfying by the new configuration summary, skip to step e/ + + + d/ Configure the build system for an unknown platform/compiler: + + What the auto-detection/setup phase of the build system does is simply + copy a file to the current directory under the name "config.mk". + + For example, on OS/2+gcc, it would simply copy "builds/os2/os2-gcc.mk" + to "./config.mk" + + If for some reason your platform isn't correctly detected, simply copy + manually the configuration sub-makefile to "./config.mk" and go to + step e/. + + Note that this file is a sub-Makefile used to specify Make variables + used to invoke the compiler and linker during the build, you can easily + create your own version from one of the existing configuration files, + then copy it to the current directory under the name "./config.mk". + + + e/ Build the library: + + The auto-detection/setup phase should have copied a file in the current + directory, called "./config.mk". This file contains definitions of various + Make variables used to invoke the compiler and linker during the build. + + To launch the build, simply invoke GNU Make again: the top Makefile will + detect the configuration file and run the build with it.. + + + f/ Build the demonstration programs: + + Once the library is compiled, go to "demos", then invoke GNU Make. + + Note that the demonstration programs include a tiny graphics sub-system + that includes "drivers" to display Windows on Win32, X11 and OS/2. The + build system should automatically detect which driver to use based on + the current platform. + + UNIX USERS TAKE NOTE: XXXXXX + + When building the demos, the build system tries to detect your X11 path + by looking for the patterns "X11R5/bin", "X11R6/bin" or "X11/bin" in + your current path. If no X11 path is found, the demo programs will not + be able to display graphics and will fail. Change your current path + if you encounter this problem. + + Note that the release version will use Autoconf to detect everything + on Unix, so this will not be necessary !! + + +II. DETAILED COMPILATION PROCEDURE: +----------------------------------- + + If you don't want to compile FreeType 2 from the command-line (for example + from a graphical IDE on a Mac or Windows), you'll need to understand how the + FreeType files are organized. + + FreeType 2 has a very module design, and it is made of several components. + Each component must be compiled as a stand-alone object file, even when it + is really made of several C source files. For example, the "base layer" + component is made of the following C files: + + src/ + base/ + ftcalc.c - computations + ftobjs.c - object management + ftstream.c - stream input + ftlist.c - simple list management + ftoutln.c - simple outline processing + ftextend.c - extensions support + + However, you can create a single object file by compiling the file + "src/base/ftbase.c", whose content is basically: + + #include + #include + #include + #include + #include + #include + + Similarly, each component has a single "englobing" C file to compile it + as a stand-alone object, i.e. : + + src/base/ftbase.c - the base layer, high-level interface + src/sfnt/sfnt.c - the "sfnt" module + src/psnames/psnames.c - the Postscript Names module + src/truetype/truetype.c - the TrueType font driver + src/type1/type1.c - the Type 1 font driver + + + To compile one component, do the following: + + - add the top-level "include" directory to your compilation include path + + - add the "src" directory to your compilation include path. + + - compile the component "source" file (see list below), you don't need + to be in the component's directory.. + + For example, the following line can be used to compile the truetype driver + on Unix: + + cd freetype2/ + cc -c -Iinclude -Isrc src/truetype/truetype.c + + Alternatively: + + cd freetype2/src/truetype + cc -c -I../../include -I.. truetype.c + + The complete list of files to compile for a feature-complete build of + FreeType 2 is: + + src/base/ftsystem.c - system-specific memory and i/o support + src/base/ftinit.c - initialisation layer + src/base/ftdebug.c - debugging component (empty in release build) + src/base/ftbase.c - the "base layer" component + src/base/ftglyph.c - optional convenience functions + src/raster1/raster1.c - the monochrome bitmap renderer + src/smooth/smooth.c - the anti-aliased bitmap renderer + src/sfnt/sfnt.c - the "sfnt" module + src/psnames/psnames.c - the "psnames" module + src/truetype/truetype.c - the TrueType font driver + src/type1/type1.c - the Type 1 font driver (incl. Multiple Masters) + src/cid/type1cid.c - the Type 1 CID-keyed font driver + src/cff/cff.c - the OpenType/CFF/CEF font driver + src/winfonts/winfnt.c - the Windows FNT/FON font driver + + All font drivers are optional. the "sfnt" and "psnames" modules are + mandatory for certain drivers. + + +III. Support for flat-directory compilation: +---------------------------------------- + + It is now possible to put all FreeType 2 source files into a single + directory, with the exception of the "include" hierarchy. + + Note that you'll still need to only compile the 'wrapper' sources described + above. Define the "FT_FLAT_COMPILE" macro when compiling. Here's an + example: + + 1/ Copy all files in current directory: + + cp freetype2/src/base/*.[hc] . + cp freetype2/src/raster1/*.[hc] . + cp freetype2/src/smooth/*.[hc] . + etc... + + 2/ Compile sources: + + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftsystem.c + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftinit.c + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftdebug.c + cc -c -DFT_FLAT_COMPILE -Ifreetype/include ftbase.c + etc... + diff --git a/subsys/win32k/freetype/docs/design/build-system.html b/subsys/win32k/freetype/docs/design/build-system.html new file mode 100644 index 0000000..b548b45 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/build-system.html @@ -0,0 +1,910 @@ + + + + + + + FreeType 2 Internals - I/O Frames + + + + + + +
+

FreeType 2.0 Build System

+ +
+

+© 2000 David Turner (david@freetype.org)
+© 2000 The FreeType Development Team +(devel@freetype.org) +

+ +
+ +


+ +

Table of Content

+ +
+

Introduction

+

I. Features & Background

+ +

II. Overview of the build process

+ +

III. Build setup details

+

IV. Library compilation details

+ + +
+ +
+

Introduction:

+ +

This document describes the new build system that was introduced + with FreeType 2.

+ +


+
+

I. Features and Background:

+ +

The FreeType 2 build system is a set of Makefiles and sub-Makefiles that + are used to build the library on a very large variety of systems easily. + One of its main features are the following:

+ +
+

1. Convenience, not Requirement

+
    +

    Even though the build system is rather sophisticated, it simply is a + convenience that was written simply to allow the compilation of the + FreeType 2 library on as many platforms as possible, as easily as + possible. However, it is not a requirement and the library can be + compiled manually or in a graphical IDE without using it, with minimal + efforts

    + +

    (for more information on this topic, see the BUILD + document that comes with your release of FreeType, in its Detailed + Compilation Guide section).

    +
+ +
+

2. Compiler and platform independence

+
    +

    The FreeType 2 build system can be used with any compiler, on any platform. + It is independent of object file suffix, executable file suffix, directory + separator convention (i.e. "/" or "\"), and compiler flags for path + inclusion, macro definition, output naming, ansi compliance, etc..

    + +

    Supporting a new compiler is trivial and only requires writing a minimal + configuration sub-makefile that contains several Makefile variables + definitions that are later used by the rest of the build system. This is + described in details later in the document.

    +
+ +
+

3. Uses GNU Make

+
    +

    The build system works exclusively with GNU Make. Reason + is that it is the only make utility that has all the features required to + implement the build system as described below. Moreover, it is already + ported to hundreds of various distinct platforms and is widely and + freely available.

    + +

    It also uses the native command line shell. You thus + don't need a Unix-like shell on your platform. + For example, FreeType 2 already compiles on Unix, Dos, Windows + and OS/2 right "out of the box" (assuming you have GNU Make + installed).

    + +

    Finally, note that the build system is specifically designed + for gnu make and will fail with any other make tool. We have + no plans to support a different tools, as you'll rapidly + understand by reading this document or looking at the sub-makefiles + themselves.

    +
+ +
+

4. Automatic host platform detection

+
    +

    When you launch the build system for the first time, by simply invoking + GNU make in the top-level directory, it automatically tries to detect + your current platform in order to choose the best configuration + sub-makefile available. It then displays what it found. If everything + is ok, you can then launch compilation of the library, by invoking make + a second time.

    + +

    The following platforms are currently automatically detected:

    +
      +
    • Dos (plain-dos, windows in Dos mode, or Dos session under OS/2) +
    • Windows 95, 98 + Windows NT (a.k.a win32) +
    • OS/2 +
    • Unix (uses Autoconf/Automake) +
    + +

    Note that adding support for a new platform requires writing a minimal + number of very small files, and simply putting them in a new sub-directory + of freetype2/config.

    +
+ +
+

5. User-selectable builds

+
    +

    The platform auto-detection rules try to setup the build for a default + compiler (gcc for most platforms), with default build options + for the library (which normally is + "all features enable, no debugging"), as well as the default + list of modules (which is "all modules in freetype2/src")

    + +

    There are cases where it is important to specify a different compiler, + different build options or simply a different module list. The FreeType 2 + build system is designed in such a way that all of this is easily possible + from the command line, without having to touch a single file. + The latter is crucial when dealing with projects that need specific + builds of the library without modifying a single file from the FreeType + distribution.

    + +

    The exact mechanism and implementation to do this is described later in + this document. It allows, for example, to compile FreeType with any of + the following compilers on Win32: gcc, Visual C++, Win32-LCC.

    +
+ +
+

6. Robustness

+
+ + +

7. Simple Module Management

+
    +

    FreeType 2 has a very modular design, and is made of a core + base layer that provides its high-level API as well as + generic services used by one or more modules. + + Most modules are used to support a specific font format (like TrueType + or Type 1), and they are called font drivers. However, some of + them do not support font files directly, but rather provide helper + services to the font drivers.

    + +

    FreeType 2 is designed so that adding modules at run-time is possible + and easy. Similarly, we expect many more modules to come in the near + future and wanted a build system that makes such additions to the + source package itself dead easy. + + Indeed, all source code (base + modules) is located in the + freetype2/src directory hierarchy. And the build system is + capable of re-generating automatically the list of known modules + from the contents of this directory. Hence, adding a new font driver + to the FreeType sources simply requires to:

    + +
      +
    • Add a new sub-directory to freetype2/src +

    • Re-launch the build system

      +
    + +

    There is thus no need to edit a source file

    +
+ +


+ +

II. Overview of the build process(es):

+ +

Before describing in details how the build system works, it is essential + to give a few examples of how it's used. This section presents + what's the build process is to the typical developer:

+ +

Compiling the library is normally done in two steps: the first one + configures the build according to the current platform and possible + additional parameters, while the second simply compiles the library with + the information gathered in the configuration step.

+ +
+

1. Build Setup

+ +
+

a. Default build setup

+
    +

    To configure the build, simply invoke gnu make from the top-level FreeType + directory. This will launch a series of rules that will detect your current + host platform, and choose a configuration file for you. It will then display + what it found. For example, here's the output of typing the command "make" + on a win32 platform (assuming this calls GNU make):

    + +
    
    +    C:\FreeType> make
    +
    +    FreeType build system -- automatic system detection
    +
    +    The following settings are used:
    +
    +      platform                     win32
    +      compiler                     gcc
    +      configuration directory      ./config/win32
    +      configuration rules          ./config/win32/w32-gcc.mk
    +
    +    If this does not correspond to your system or settings please remove the file
    +    'config.mk' from this directory then read the INSTALL file for help.
    +
    +    Otherwise, simply type 'make' again to build the library.
    +
    +    C:\FreeType>
    +
    + +

    Note that this step copies the selected configuration file (here + ./config/win32/w32-gcc.mk) to the current directory, under + the name config.mk. This file contains data that is used + to drive the library compilation of the second step. It correspond to + the platform and compiler selected by the auto-detection phase.

    + +

    Note that you can re-generate the config.mk file anytime + by invoking make setup whenever you need it, even when the file is + already present in the current directory.

    + +

    Finally, if your platform is not correctly detected, the build system will + display and use configuration information for the virtual "ansi" platform. +

    +
+
+

b. Selecting another build configuration

+
    +

    You may not be really satisfied by the configuration file selected by the + auto-detection routines. Typically, you might be using a compiler that is + not the default one for your platform. It is however possible to re-launch + the build setup phase with an additional argument, used to specify a + different compiler/config file. For example, you can type the following + commands on Win32 systems:

    + +

    +

    make setup

    +
    +

    re-run the platform detection phase, and select the default compiler for it. + On Win32, this is gcc.

    +
    +

    make setup visualc

    +
    +

    re-run the platform detection phase, and select a config file that + corresponds to the Visual C++ compiler

    +
    +

    make setup lcc

    +
    +

    re-run the platform detection phase, and select a config file that + corresponds to the Win32-LCC compiler

    +
    +

    + +

    Note that a specific configuration is selected with a command that + looks like : make setup compiler, + where the compiler keywords depends on the platform. + Moreover, each one of them corresponds to a specific configuration + sub-makefile that is copied as config.mk in the current + directory.

    +
+ + +
+

2. Library compilation

+ +

Once you're satisfied with the version of config.mk that + has been copied to your current directory, you can simply re-invoke + gnu make with no arguments. The top-level Makefile will + automatically detect the config sub-makefile in the current directory, + and use it to drive the library compilation. The latter can be seen + as a series of different steps decribed here:

+ +
    +
  • Compiling the ftsystem component

      + It encapsulates all low-level operations (memory management + + i/o access) for the library. Its default version, located in + ./src/base/ftsystem.c uses the ANSI C library but + system-specific implementations are also available to + improve performance (e.g. memory-mapped files on Unix). +

    + +
  • Compiling the base layer and optional components

      + They provide the library's high-level API as well as various useful + routines for client applications. Many features of the base layer can + be activated or not depending on a configuration file named + ftoption.h +

    + +
  • Compiling the modules

      + Each module is used to support a specific font format (it is then + called a font driver), or to provide helper services to + the drivers (e.g. the auto-hinter). They are all located in + sub-directories of ./src, like ./src/truetype, + ./src/type1. +

    + +
  • Compiling the ftinit component

      + This one is in charge of implementing FT_Init_FreeType, + the library initialisation routine. It also selects what modules + are activated when a new library instance is created. +

    +
+


+ +

II. Details of the build setup.

+ +

When the top-level Makefile is invoked, it looks for a + file named config.mk in the current directory. + If this file is found, it is used directly to build the library + (skip to Section III for details then).

+ +

Otherwise, the file ./config/detect.mk is included + by the top-level Makefile and parsed. Its purpose is to drive the + platform-detection phase, by:

+ +
    +
  • Defining the PLATFORM variable, which indicates + what the currently detected platform is. It is initially + set to the default value "ansi". +

    + +
  • Searching for a detect.mk file in all + subdirectories of ./config. + Each such file is included and parsed. Each of these files must + try to detect if the host platform is a system it knows + about. If so, it changes the value of the PLATFORM variable + accordingly.

    + +
  • Copying the selected configuration submakefile to the current directory + under the name config.mk.

    +
+

This is illustrated by the following graphics :

+

+ +

+ +

Each system-specific detect.mk works as follows:

+
    +
  • It checks that the value of PLATFORM is currently set + to ansi, which indicates that no platform was detected + for now. If this isn't true, it doesn't do anything

    + +
  • Otherwise, it runs a series of test to see wether it is on a + system it knows about. Here are a few examples of tests:

    + +

    + Unix + +

    checks for a file named /sbin/init, and runs, when it found + it, a 'configure' script to generate the relevant config sub-makefile

    +
    + Dos + +

    checks for the COMSPEC environment variable, then tries to + run the "ver" command on the current shell to check that there + is a "Dos" substring in its output; if not, it tries to find the + substring "MDOS\COMMAND" in COMSPEC, which indicates + a Dos session under OS/2.

    +
    + Win32 + +

    if the environment variable OS is defined and has the value + Windows_NT, or if COMSPEC is defined and the + "ver" returns a string that contains Windows in it, + we're on a Win32 system.

    +
    +

    + +
  • It sets the value of PLATFORM to a new value corresponding + to its platform.

    + +
  • It then tries to select a configuration + sub-makefile, depending on the current platform and any optional + make target (like "visualc" or "devel", etc..). Note that it can + even generate the file, as on Unix through Autoconf/Automake.

    + +
  • It copies the selected configuration sub-makefile to the current + directory, under the name config.mk +

+ +

If one wants to support a new platform in the build system, it simply needs + to provide:

+ +
    +
  • A new subdirectory, in ./config, with a file named + detect.mk in it, containing relevant checks for the system. + +
  • One or more configuration sub-makefiles that will get copied to + config.mk at build setup time. You can use the one in + ./config/ansi/config.mk as a template. +
+ +

Similary, supporting a new compiler on an existing system simply means:

+
    +
  • Writing a new config sub-makefile that contains definitions used to + specify the compiler and flags for the build. + +
  • Change your ./config/system/detect.mk to recognize + a new optional build target that will copy your new config sub-makefile + instead of the default one. +
+ + +


+

III. Details of the library compilation.

+ +

When the top-level Makefile is invoked, it looks for a file named + config.mk in the current directory. If one is found, it + defines the BUILD_FREETYPE variable, then includes and parses it. + The structure of this file is the following: +

+ +
    +
  • First, it defines a series of Make variables that describe + the host environment, like the compiler, compilation flags, + object file suffix, the directory where all object files are + placed, etc..

    + +
  • If BUILD_FREETYPE is defined, it includes the file + ./config/freetype.mk, which is in charge of + defining all the rules used to build the library object files. + (The test is useful to use the config.mk file to + compile other projects that rely on FreeType 2, like its + demonstration programs).

    + +
  • Finally, it defines the rule(s) used to link FreeType 2 object files + into a library file (e.g. libfreetype.a, freetype.lib, + freetype.dll, ...). Unfortunately, the command line interface of link tools is + a lot less standardized than those of compilers, which + explains why this rule must be defined in the system-specific + config.mk.

    +
+ +

The following is an explanation of what ./config/freetype.mk + does to build the library objects: +

+ +

a. Include paths

+
    +

    To avoid namespace pollution, the freetype directory prefix + is used to include all public header files of the library. This means + that a client application will typically use lines like:

    + +
    
    +    #include <freetype/freetype.h>
    +    #include <freetype/ftglyph.h>
    +
    + +

    to include one the FreeType 2 public header files. freetype.mk + uses a variable named INCLUDES to hold the inclusion + paths list, and thus starts by adding ./include to it. However, + nothing prevents + +

    freetype.mk uses a variable named INCLUDES + to hold directory inclusion-path to be used when compiling the library. + It always add ./include to this variable, which means + +

+ +

b. Configuration header files:

+
    +

    Three header files used to configure the compilation of the + FreeType 2 library. Their default versions are all located in the + directory ./include/freetype/config/, even though + project specific versions can be provided on a given build, as + described later:

    + +
      +

      #include <freetype/config/ftoption.h>

        + This file contains a set of configuration macro definitions that + can be toggled to activate or deactivate certain features of the + library. By changing one of these definitions, it is possible to + compile only the features that are needed for a specific + project. Note that by default, all options are enabled. +

        + You might need to provide an alternative version of ftoption.h + for one of your own projects. +

      + +

      #include <freetype/config/ftconfig.h>

        + This file includes ftoption.h but also contains some automatic + macro definitions used to indicate some important system-specific + features (e.g: word size in bytes, DLL export prefix macros, etc..). +

        + You shouldn't normally need to change or provide an alternative + version of this file. +

      + + +

      #include <freetype/config/ftmodule.h>

        + This file is very special, as it is normally machine-generated, and + used by the ftinit component that is described below. To + understand it, one must reminds that FreeType 2 has an extremely + modular design and that it's possible to change, at run-time, + the modules it's using. The ftmodule.h file simply contains + the list of modules that are registered with each new instance of + the library. +

        + Note that the file can be re-generated automatically by invoking + make setup from the top-level directory. The re-generated + list contains all the modules that were found in subdirectories of + ./src. +

      +
    + +

    Note that we strongly advise you to avoid modifying the config files + within the FreeType 2 source directory hierarchy. Rather, it's possible + to specify alternative versions through the help of a build-specific + include path that is include before ./include in the inclusion + path.

    + +

    For example, imagine that your platform, named foo, needs a + specific version of ftoption.h +

+ +

a. Compiling the ftsystem component:

+
    +

    FreeType 2 encapsulates all low-level operations (i.e. memory management + and i/o access) within a single component called ftsystem. + Its default implementation uses the ANSI C Library and is located + in ./src/base/ftsystem.c.

    + +

    However, some alternate, system-specific, implementations of + ftsystem are provided with the library in order to support more + efficient and advanced features. As an example, the file + ./config/unix/ftsystem.c is an implementation that + uses memory-mapped files rather than the slow ANSI fopen, + fread and fseek, boosting performance significantly.

    + +

    The build system is thus capable of managing alternate implementations + of ftsystem

    +
+ +

b. Compiling the base layer and optional components:

+
    +

    The high-level API of the library is provided by a component called the + base layer, whose source is located in ./src/base. This + directory also contains one or more components that are optional, i.e. + that are not required by the library but provide valuable routines to + client applications.

    + +

    The features of the base library and other components are selected through + a single configuration file named + ./include/freetype/config/ftoption.h. It contains a list + of commented configuration macro definitions, that can be toggled to + activate or de-activate a certain feature or component at build time.

    + +

    For example, the code in ./src/base/ftdebug.c will be compiled + only if one of these two macros are defined in ftoption.h: + FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE

    +
+ +

c. Compiling the modules:

+
    +

    Once the base layer is completed, the build system starts to compile each + additional module independently. These are simply defined as all source + code located in a sub-directory of ./src that contains a file + named rules., for example: + src/sfnt, src/truetype, src/type1, ...

    + +

    The rules. file simply contains directives used by the + build system to compile the corresponding module into a single object + file.

    +
+ +

d. Compiling the ftinit component:

+
    +

    The file ./src/base/ftinit.c is special because it is used + to implement the library initialisation function FT_Init_FreeType. +

    +
+ +

Typically, you will end up with all object files, as well as the + corresponding library file, residing in the freetype2/obj + directory.

+ + +

1. Purpose of the configuration sub-makefile

+ +

2. Managing module dependencies

+ +

3.

+ +


+ +

IV. Managing the modules list

+ +


+ The build system features some important points, which are all detailed + in the following sections:

+

    +
  • Automatic host platform detection
    + The first time the top Makefile is invoked, it will + run a series of rules to detect your platform. It will then + create a system-specific configuration sub-Makefile in the + current directory, called config.mk. You can now + invoke the top Makefile a second time to compile the + library directly. +

    + The configuration sub-makefile can be regenerated any time + by invoking "make setup", which will re-run the + detection rules even if a config.mk is already present. +

    + + +

  • User-selectable builds
    +

    + + + +

  • Automatic detection of font drivers
    + FreeType is made of a "base" layer that invokes several + separately-compiled modules. Each module is a given + font driver, in charge of supporting a given font format. +

    + The list of font drivers is located in the file + "freetype2/config/system/ftmodule.h", however + it can be regenerated on-demand. Adding a new module to the + FreeType source tree is thus as easy as:

    +

      +
    • create a new directory in "freetype2/src" and + put the new driver's source code and sub-makefiles there. +

      + +

    • invoke the top Makefile with target + "modules" (as in "make modules"), + as this will automatically regenerate the list of + available drivers by detecting the new directory and + its content. +
    +

    +

+ + +


+ +

II. Host Platform Detection

+
    + When the top-level Makefile is invoked, it looks for a + file named config.mk in the current directory. If this + file is found, it is used to build the library + (see Section III). +

    + Otherwise, the file freetype2/config/detect.mk is included + and parsed. Its purpose is to:

    +

      +
    • Define the PLATFORM variable, which indicates + what is the currently detected platform. It is initially + set to the default value "ansi". +

      + +

    • It searches for a detect.mk file in all + subdirectories of freetype2/config. Each such + file is included and parsed. Each of these files must + try to detect if the host platform is a system it knows + about. If so, it changes the value of the PLATFORM + accordingly. +
    +

    + This is illustrated by the following graphics :

    +

    + +
    +

    + Note that each system-specific detect.mk is in charge + of copying a valid configuration makefile to the current directory + (i.e. the one where make was invoked), depending on the + current targets. For example, the Win32 detect.mk will + be able to detect a "visualc" or "lcc" target, + as described in section I. Similarly, the OS/2 detect.mk + can detect targets like "borlandc", "watcom" + or "visualage", etc.. +

+ +


+ +

III. Building the library

+
    + When the top-level Makefile is invoked and that it finds + a config.mk file in the current directory, it defines + the variable BUILD_FREETYPE, then includes and parses the + configuration sub-makefile. +

    + The latter defines a number of important variables that describe + the compilation process to the build system. Among other things:

    +

      +
    • the extension to be used for object files and library files + (i.e. .o and .a on Unix, .obj + and .lib on Dos-Windows-OS/2, etc..). +

      + +

    • the directory where all object files will be stored + (usually freetype2/obj), as well as the one + containing the library file (usually the same as for + objects). +

      + +

    • the command line compiler, and its compilation flags for + indicating a new include path (usually "-I"), + a new macro declaration (usually "-D") or + the target object file (usually "-o ") +
    +

    + Once these variable are defined, config.mk test for the + definition of the BUILD_FREETYPE variable. If it exists, + the makefile then includes "freetype2/config/freetype.mk" + which contains the rules required to compile the library. +

    + Note that freetype.mk also scans the subdirectories of + "freetype2/src" for a file called "rules.mk". + Each rules.mk contains, as it names suggests, the rules + required to compile a given font driver or module. +

    + Once all this parsing is done, the library can be compiled. Usually, + each font driver is compiled as a standalone object file (e.g. + sfnt.o, truetype.o and type1.o). +

    + This process can be illustrated by the following graphics:

    +

    + +
    +

    +

+ +


+ +

IIV. Managing the list of modules

+
    + The makefile freetype.mk only determines how to compile + each one of the modules that are located in the sub-directories of + freetype2/src. +

    + However, when the function FT_Init_FreeType is invoked at + the start of an application, it must create a new FT_Library + object, and registers all known font drivers to it by + repeatly calling FT_Add_Driver. +

    + The list of known drivers is located in the file + "freetype2/config/system/ftmodule.h", and is used + exclusively by the internal function FT_Default_Drivers. The + list in ftmodule.h must be re-generated each time you add + or remove a module from freetype2/src. +

    + This is normally performed by invoking the top-level Makefile + with the modules target, as in:

    +

      + make modules +
    +

    + This will trigger a special rule that will re-generate + ftmodule.h. To do so, the Makefile will parse all module + directories for a file called "module.mk". Each + module.mk is a tiny sub-Makefile used to add a single + module to the driver list. +

    + This is illustrated by the following graphics:

    +

    + +
    +

    + Note that the new list of modules is displayed in a very human-friendly + way after a "make modules". Here's an example with the current + source tree (on 11 Jan 2000):

    +

      +Regenerating the font drivers list in ./config/unix/ftmodule.h
      +* driver:  sfnt      ( pseudo-driver for TrueType & OpenType formats )
      +* driver:  truetype  ( Windows/Mac font files with extension *.ttf or *.ttc )
      +* driver:  type1     ( Postscript font files with extension *.pfa or *.pfb )
      +-- done --
      +    
    + +
+ +


+ +

V. Building the demonstration programs

+
    + Several demonstration programs are located in the + "freetype2/demos" directory hierarchy. This directory also + includes a tiny graphics sub-system that is able to blit glyphs to + a great variety of surfaces, as well as display these in various + graphics libraries or windowed environments. +

    + This section describes how the demonstration programs are compiled, + using the configuration freetype2/config.mk and their own + freetype2/demos/Makefile. +

    + To compile the demonstration programs, after the library, + simply go to freetype2/demos then invoke GNU make with no + arguments. +

    + The top-level Makefile will detect the config.mk in the + upper directory and include it. Because it doesn't define + the BUILD_FREETYPE variable, this will not force the + inclusion of freetype2/config/freetype.mk as described in + the previous section. +

    + the Makefile will then include the makefile called + "freetype2/demos/graph/rules.mk". The graphics rules.mk + defines the rules required to compile the graphics sub-system. +

    + Because the graphics syb-system is also designed modularly, it is able + to use any number of "modules" to display surfaces on the screen. + The graphics modules are located in the subdirectories of + freetype2/demos/config. Each such directory contains a file + named rules.mk which is in charge of:

    +

      +
    • detecting wether the corresponding graphics library is + available at the time of compilation. +

      +

    • if it is, alter the compilation rules to include the graphics + module in the build of the graph library. +
    +

    + When the graph library is built in demos/obj, the + demonstration programs executables are generated by the top-level + Makefile. +

    + This is illustrated by the following graphics:

    +

    + +
    +
+ +


+
+ + + diff --git a/subsys/win32k/freetype/docs/design/demo-programs.png b/subsys/win32k/freetype/docs/design/demo-programs.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/demo-programs.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/drivers-list.png b/subsys/win32k/freetype/docs/design/drivers-list.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/drivers-list.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/index.html b/subsys/win32k/freetype/docs/design/index.html new file mode 100644 index 0000000..50f7f29 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/index.html @@ -0,0 +1,791 @@ + + + + + + + FreeType 2 Internals + + + + + +
+

+FreeType 2.0 Internals

+ +
+

+Version 1.2

+ +
+

+© 1999-2000 David Turner (david@freetype.org)
+© 1999-2000 The FreeType Development Team (devel@freetype.org)

+ +


+


+
  +

Introduction:

+ +

This document describes in great deatils the internals of FreeType 2. + It is a must read for porters and developers alike. Its purpose is to + + present the +

This document describes in great details the internals of the +FreeType 2.0 library. It is a must read for porters and developers alike. +Its purpose is to present the engine's objects, their roles and interactions. +It is assumed that the FreeType Glyph Conventions document +has been read. +

We advise porters to also read the FreeType Porting Guide +after this document. Would-be hackers and maintainers are of course encouraged +to read the FreeType Coding Conventions document too. The +development of a new driver is described in more details in the FreeType +Driver HowTo document.

+ +


+


+

+I. Overview :

+ +
+

+1. Features (and what's new) :

+ +
FreeType 2.0 has a number of important new features that were +not found in the 1.x releases : +
  +
font-format independent API +
FreeType 2.0 is able to support any kind of font format, be it fixed +or scalable, through the use of pluggable "font drivers". These drivers +can be added or replaced at run time, while applications use a new font +format-independent API. +

advanced stream caching +
2.0 is able to control the number of concurrently opened streams when +using fonts. It is thus possible to open dozens or hundreds of font faces +without running out of system resources. +

real reentrancy support +
It is now possible to use FreeType as a shared library with no static +data in a multi-threaded environment. The synchronization model has also +been simplified in order to make font driver writing easier. Of course, +you can build FreeType with no thread support to get a smaller library. +

support for cubic beziers and 17-levels anti-aliasing +
The FreeType scan-line converter (a.k.a. raster) now supports cubic +bezier arcs seamlessly. It also provides a new anti-aliasing mode which +uses a palette of 17 levels of grays. +
 

+It also features the following : +
performance improvements : +
The FreeType raster has been optimized, and the generation of anti-aliased +pixmaps is now 60% faster than in the 1.x release. Moreover, the TrueType +bytecode interpreter has been profiled and greatly optimised. +

easier portability +
Porting and configuring FreeType is now much easier. A single file +must be provided for system-specific operations (like memory, i/o, thread +management), and a single configuration header is used to select the build +you need. +
 

+
+ +

+2. Architecture :

+ +
The engine is now split in several parts, which are : +

+a. The base layer :

+ +
This part contains all the font-format independent features +of the engine which are : +
    +
  • +computations/scaling
  • + +
  • +list processing
  • + +
  • +outline processing
  • + +
  • +scan-line converter
  • + +
  • +stream manager
  • + +
  • +base object classes
  • + +
  • +debugging & traces
  • + +
  • +high-level API functions
  • + +
  • +low-level system object (memory, i/o, threads)
  • +
+
+ +

+b. The font drivers :

+ +
Each font format is managed with the use of a single font driver +object. The base layer is able to manage several drivers, and these can +be easily added, removed or upgraded at runtime. Each driver has the following +features and functions : +
    +
  • +auto-check font format when opening a font resource (i.e. file)
  • + +
  • +access, load and/or extract all tables and data from the font file
  • + +
  • +grid-fit/hint the glyph outlines (in the case of scalable formats like +TrueType or Type1)
  • + +
  • +provide extensions to access font format-specific data and tables from +the font file
  • +
+Note that FreeType 2.0 is a font service. Its purpose is to provide a unified +API for all kinds of fonts and extract individual glyph images and metrics. +However, it does not render text itself, as this operation is left to the +developer, or to higher-level libraries built on top of FreeType. Here +are a few features that are thus not implemented : +
1) Text string rendering +
2) Glyph bitmap/outline caching for improved performance +
3) Synthetic fonts (i.e. italicising, emboldening, underlining) +
4) Contextual glyph substitution and other advanced layout processes
+Note that features 1 through 3 should be provided by the SemTex library, +which may soon become part of the standard FreeType distribution.
+
+
+ +


+


+

+II. Design :

+ +
+

+1. Objects :

+ +
They are several kinds of objects in FreeType, which can be +described as follows : +
Base objects +
These objects do not relate directly to font data, but to the way it +is organised and managed. It is the basic core and provides functions that +are heavily used by each font driver. Examples are the resource objects, +used to describe font files, the system object used to manage low-level +system operations, or the raster object, used to convert vector outlines +into bitmaps or anti-aliased pixmaps. Most of the base objects are not +directly visible for client applications of FreeType. +

Font objects +
The font objects directly model the data as it is found in font files. +The root classes implemented in the base layer like FT_Face, FT_Size, +FT_GlyphSlot, +must be derived in each font driver.

+Objects are defined in the files "base/freetype.h" and "base/ftobjs.h". +The former contains all the public object definitions usable by client +applications. The latter contains private definitions used by the rest +of the base layer and each font driver.
+ +

+2. List management

+ +
The "base/ftlist.c" component a very simple doubly-linked +list facility which is used by the rest of the engine to create and process +lists, including iteration and finalisation. The definition of the list +node and functions are placed in the "base/freetype.h" to let +client applications access listed objects as they like. +

The base list type is FT_List, which links nodes of type FT_ListNode +together. +
 

+ +

+3. Limited encapsulation

+ +
Unlike what happened in the 1.x releases, the FT_Face, +FT_Size, +FT_GlyphSlot and FT_CharMap types are no longer blind +pointers to opaque types. Rather, the corresponding structures are now +public (and defined in "base/freetype.h", see FT_FaceRec, +FT_SizeRec, +etc..) in order to let client applications read directly the various object +attributes they're interested in. +

This breaks encapsulation of implementation, famed by OOP, but was chosen +because: +
  +

    +
  • +it simplifies a lot the work of client applications and libraries which +don't need to perform a function call everytime they want to read one important +object attribute (nor does it force them to cache these attributes in their +own structures).
  • +
+ +
    +
  • +It reduces greatly the API, as many FT_Get_XXX functions are avoided.
  • +
+ +
    +
  • +Higher-level libraries are able to  access data directly. When it +is used frequently, they don't need to cache it in their own structures.
  • +
+ +
    +
  • +It is possible to tightly link FreeType objects with higher-level ones, +in a clearer and more efficient way. This is very important when one wants +to write a C++ wrapper or a text rendering library on top of FreeType (actually, +both projects were performed in an earlier version of FreeType 2.0 which +featured classic encapsulation through get/set methods. The resulting code +was ugly and slow. Moving to a limited encapsulation approach simplified +so many things that the compiled code size was reduced by a factor of two +!).
  • +
+ +
    +
  • +Finally, the API and font object structures were designed after the creation +of two scalable font drivers and one bitmap font driver. They are now very +stable and the public (visible) attributes are not going to change.
  • +
+
+
+ +


+


+

+III. Base objects :

+ +
This section describes the FreeType base object classes : +
  +

+1. System objects :

+ +
The system class is in charge of managing all low-level and +system-specific operations. This means simply memory management, i/o access +and thread synchronisation. It is implemented by the "ftsys.c" +component, whose source must be located in the configuration directory +when building FreeType. (e.g. "lib/arch/ansi/ftsys.c" for an ANSI +build, "lib/arch/unix/ftsys.c" for a Unix one, etc..). +

Porting FreeType 2.0 really means providing a new implementation of +ftsys +(along with a few configuration file changes). Note however that its interface +is common to all ports, and located in "base/ftsys.h".

+ +

+2. Resources and Streams:

+ +
The concepts of files as storages, and files as streams has +been separated for FreeType 2.0. The "resource" concept was +introduced while the "stream" one has been redefined. Here +is how they work together : +
    +
  • +a "resource" is an object which models a file, seen as a storage. +There are several classes of resources, which differ usually in two ways +: the way their data is accessed by applications, and the way they're named +within the system.
  • +
+ +
    For example, when parsing files with the ANSI C library, data has to +be read (through fseek/fread) into intermediate buffers before it can be +decoded. This scheme is highly portable, but rather inefficient; when using +it, we'll describe the file as a disk-based resource. +

    As most modern operating systems now provide memory-mapped files, which +allow direct access while improving performance and reducing memory usage. +Because data can be read directly in memory, we'll speak of a memory-based +resource in this case. For embedded systems (like printers, PDAs, etc..), +ROM-fonts fit into this category as well. +

    Regarding naming, most systems use a string to name files in their storage +hierarchy. Though a typical pathname is an ASCII string ('c:\windows\fonts\times.ttf' +on Windows, '/home/fonts/times.ttf' on Unix), some OSes use different +schemes, varying from Unicode character strings to file i-node numbers. +These details are platform-specific and must be hidden to the rest of the +library in resource objects. +

    A resource encapsulates the lowest details regarding a file, though +it should have NO STATE. Note that the nature or type of a resource (i.e. +disk or memory based) is important to the "stream" component only. The +rest of the library and font drivers work transparently from their implementation. +

    Note also that it is perfectly possible to mix resources of distinct +natures in a single build

+ +
    +
  • +a "stream" is an object which is used to extract bytes from a resource. +Only resource objects can create streams, through its Open_Stream() +method. A stream has state, which typically consist of a file "cursor", +some intermediate buffers, a "current frame" and, of course, methods used +to extract the data from streams, resolving endianess and alignement issues.
  • +
+Data can be extracted from streams through direct reads, or through the +use of frames. A frame models a run of contiguous bytes starting +from the current stream position, and of liberal size. +

Methods exist to extract successive integers of any sizes, while resolving +endianess and alignement issues. Rather than a long rethorical explanation, +here's how frames are typically used : +

{ +
  … +
  FT_Error  error; +

  error = FT_Access_Frame( stream, 14 ); +
  if (error) goto Fail; +

  val1 = FT_Get_Short(stream); +
  val2 = FT_Get_Long(stream); +
  val3 = FT_Get_Long(stream); +
  val4 = FT_Get_Long(stream); +

  FT_Forget_Frame(stream); +
  … +
}

+This code does the following : +
+
    +
  1. + first, it "loads" the next 14 bytes from the current cursor position +into the stream's frame, using the FT_Access_Frame API. An error +is returned if, for example, less than 14 bytes are left in the stream +when the call occurs..
  2. +
+ +
    +
  1. + it extract four integers (one 16-bit short, three 32-bit longs) from +the frame using FT_Get_Short and FT_Get_Long. These function +increment the frame's cursor finally, it "releases" the stream's frame.
  2. +
+ +
    +
  1. + Each stream has its own frame which can be accessed independently, +however, nested frame accesses are not allowed. Note also that the bytes +are effectively read from the stream on the call to FT_Access_Frame. +Any subsequent read will occur after these 14 bytes, even if less are extracted +through FT_Get_xxxx functions.
  2. +
+
+The implementation of the resource class is located in the system component +(i.e. "arch/<system>/ftsys.c") and can thus be tailored +for a specific port of the engine. +

A resource can be created through the FT_New_Resource API; +however this function only accepts an 8-bit pathname to name the target +font file, which may be inappropriate for systems using a different naming +scheme (e.g. UTF-16 pathname, i-node number, etc..). It's up to the porter +then to provide its own resource creation function (like. FT_New_UTF16_Resource, +for example) in its version of "ftsys.c". +

Note that FT_New_Resource will fail and return an error code +if the font file cannot be found, or when its font format isn't recognized +by one of the drivers installed in the library. The list or resources created +for a given library instance is thus the list of "installed font files". +
 

+ +

+3. Stream Manager :

+ +
As said before, resources do not bear states, while streams +do. Stream creation is also a very lengthy process, depending on the target +operating system (e.g. "fopen" is usually very slow). +

Because a typical font driver will want to use a new stream on each +access to individual glyphs, being able to cache the most recently used +streams is a requirement in order to avoid considerable performance penalties. +

Stream caching is thus implemented in the "ftstream" component. +It maintains a simple LRU list of the least recently used streams. Each +stream in the cache is still opened and available for immediate processing. +When a resource is destroyed, the stream cache is parsed to remove all +related cached streams. +

Stream caching can also be disabled with a configuration macro when +using only ROM based resources (where stream opening is really quick). +It is implemented through a Stream Manager object (see ftstream.c). +
 

+ +

+4. Raster :

+ +
The raster is the component is charge of generating bitmaps +and anti-aliased pixmaps from vectorial outline definitions. It is also +sometimes called the scan-line converter. It has been completely rewritten +for FreeType 2.0 in order to support third-order bezier arcs, 17-levels +anti-aliasing (through 4x4 sub-sampling), improved performance, as well +as stand-alone compilation (in order to include it in other graphics package +without requiring the rest of the FreeType engine). +

Because it was designed for easy re-use and embedded systems, the raster +is a rtaher 'unusual' piece of code, because it doesn't perform a single +memory allocation, nor contain any static or global variable. Rather, it +is up to client applications to allocate a raster object in their own heap +or memory space. +

Each raster object also needs a rather large block of memory called +its render pool. The pool is used during rendering (and only during it) +in order to perform the scan-line conversion. Because it accesses and manages +data directly within the pool, the raster yelds impressive performance +as well as bounded memory consumption. It can also automatically decompose +large requests into smaller individual sub-tasks. +

Finally, it never creates bitmaps or pixmaps, but simply renders into +them (providing clipping too). These must be described to the raster with +the help of a FT_Raster_Map structure (a very simple bitmap/pixmap +descriptor). +

Note that when rendering anti-aliased pixmaps, the raster doesn't use +an intermediate bitmap buffer, as filtering is part of the scan-line conversion +process. +
 

+ +

+5. Library objects :

+ +
A library object models a single instance of the FreeType engine. +This is useful when FreeType is compiled as a shared object (DLL), as it +can then be used by several applications, each with its own resources and +objects. +

The FT_Library type is an opaque handle to a library object. +Such an object is created through a call  to FT_Init_FreeType. +Once you don't need it anymore, one can destroy a library object through +FT_Done_FreeType. +

Note that in reentrant builds, several threads can access a single library +object concurrently. Such a build can be chosen by switching one configuration +macro in the file 'arch/<system>/ftconfig.h'

+ +

+6. Driver objects :

+ +
A driver object models an instance of a given font driver, +i.e. an element of FreeType code in charge of handling a given font format, +like TrueType, Type1, FNT, PCF, etc.. +

Each library object contains a given set of driver objects when it is +created through FT_Init_FreeType, this set being determined at compile +time (see the file 'base/ftapi.c'). However, removing or adding drivers +is possible at run-time, in order to make upgrades easy.

+ +

+7. Diagram

+ +
This diagram show the object relationships for the sole base +layer. The library object is the root of the object graph : +
+

+ +

It can be read as follows : +
  +

    +
  • +Each library object has one system, one raster and one stream manager objects. +These objects can only belong to one given library.
  • +
+ +
    +
  • +Each library contains one list of 0 or more resources, as well as one list +of 0 or more driver objects.
  • +
+ +
    +
  • +Each stream manager holds a bounded list ("0..n" where 'n' is the stream +cache's size) of stream objects. Each stream is related to one given resource +object. Each resource may be related to zero or one stream.
  • +
+ +
    +
  • +Each resource is related to one driver object. A driver is related to 0 +or more resources.
  • +
+
+
+ +


+


+

+IV. Font objects :

+ +
Font objects are used to directly map the information found +in font files into several categories : +
  +

+1. Face objects :

+ +
Face objects are used to model individual font faces. They +encapsulate data which isn't related to a specific character size, or a +specific glyph or glyph set. Usually, this means : +
    +
  • +the font face's family and style names (e.g. "Palatino" + "Regular")
  • + +
  • +some flags indicating which kind of font this is (scalable or fixed ? fixed-width +or proportional ? horizontal or vertical ? etc…)
  • + +
  • +the number of glyphs, charmaps and eventually fixed character sizes (for +bitmap formats) found in the font face.
  • + +
  • +for scalable formats, some important metrics like the ascender, descender, +global font bounding box, maximum advance width, etc.. expressed in notional +font/grid units (as well as the number of units on the EM grid).
  • +
+A face is created from a resource object, with the FT_New_Face +API. Each driver contains a list of opened face objects for the resources +it manages. When a driver is removed or destroyed, all its child faces +are discarded automatically with it.
+ +

+2. Size objects :

+ +
Size objects are used to model a given character dimension +for a given device resolution (which really means a given character pixel +dimensions). +

Each size object is created from a parent face object. The object can +be reset to new dimensions at any time. Each face object holds a list of +all its child sizes, these are destroyed automatically when the face object +is discarded. +

The metrics contains metrics, expressed in pixels, for the ascender, +descender, maximum advance width, etc.. +
 

+ +

+3. Glyph Slot objects :

+ +
A glyph slot is a container where one can load individual glyphs, +be they in vector of bitmap format. Each slot also contains metrics for +the glyph it contains. +

Each face object contains one or more glyph slot object : the first +glyph slot is created automatically with its parent face, and it is possible +to add new glyph slots (this is rarely used outside of debugging purposes). +
 

+ +

+4. CharMap objects :

+ +
A charmap object is a sort of dictionary whose task is to translate +character codes in a given character encoding (like ShiftJIS, Unicode, +ANSI, etc..) into glyph indexes in a given font face. +

A face object contains one or more charmap objects. All charmap objects +are created when the parent face is created, though they're not directly +visible to client applications (rather, they can be enumerated through +FT_Get_First_CharMap and FT_Get_Next_CharMap, or more simply picked adequately +with FT_Find_CharMap for a set of given encodings). +
 

+ +

+5. Diagram

+ +
The following diagram illustrates the relationships between +font objects : +
+

+ +

Which can be read as : +
  +

    +
  • +each resource may have zero or more child face objects "opened" for it. +The number of faces is bounded by the number of font faces within the font +resource.
  • +
+ +
    +
  • +each driver holds a list of all the faces opened for the resources it manages. +When the driver is removed, its child faces are discarded automatically.
  • +
+ +
    +
  • +each face object has one single parent resource, and one single driver.
  • +
+ +
    +
  • +each face has one or more charmaps, and one or more glyph slots
  • +
+ +
    +
  • +each face holds a list of zero or more child size objects
  • +
+ +
    +
  • +each charmap, glyph slot and size is related to one given parent face. +These objects are destroyed automatically when the parent face is discarded.
  • +
+
+
+ +


+


+

+V. Driver Interface :

+ +
A font driver is added to a given library object through the +FT_Add_Driver +API. This function receives a structure known as a FT_DriverInterface, +which describes the driver's basic properties. +

The FT_DriverInterface contains a set of function pointers +used for the base FreeType functionalities. However, each driver can also +provide a font-format-specific extended interface to allow client applications +to use more advanced features. +
  +

+1. Common Interface

+ +
The structure of FT_DriverInterface is rather simple, +and defined in "base/ftdriver.h". It must be well known by any +developer who wants to write a new driver for the engine. We advise reading +the FreeType Driver HowTo as well as the source code of existing +drivers. Source comments.
+ +

+2. Driver-specific extensions

+ +
The field of the FT_DriverInterface structure is a +typeless pointer to a format-specific interface. This extended interface +is usually a structure containing function pointers as well as other kind +of information related to the driver. +

It is assumed that client applications that wish to use the driver-specific +extensions are able to #include the relevant header files to understand +the format-specific interface structure.

+
+ +
+

+VI. Configuration:

+ +
This section relates to the configuration of the FreeType library. +By configuration, we mean selection of build options as well as the choice +of font drivers to be used for each new library object. +
  +

+1. Configuration files :

+ +
A single file is used to configure the FreeType base engine. +As it is considered system-specific, it is located in the architecture +directories of the library, under the name "arch/<system>/ftconfig.h". +Note that the same directory should also contain a platform-specific implementation +of "ftsys.c". +

The configuration files is a simple C header which is included by the +engine's sources during compilation. It is not included in "freetype.h", +and hence doesn't need to be copied when installing the FreeType headers +on your system. +

It is made of a series of #define or #undef statements, which are used +to select or turn off a specific option. Each option is documented with +heavy comments, and some of them are explained below.

+ +

+2. Building and Makefiles :

+ +
FreeType 2.0 is more complex than its 1.x release. In order +to facilitate maintenance, as well as ease considerably the writing of +new font drivers, only GNU Make is supported with FreeType 2.0. +However, it is possible to use any compiler, as well as any object or library +prefix (.o, .obj, .a, .lib etc..) with them. +

To build FreeType 2.0, one has to be in the library directory, then +invoke its platform-specific makefile. For a Unix system, this would be +: +

+
% cd freetype2/lib +
% make -f arch/unix/Makefile +

where 'make' is really GNU Make !

+
+The system-specific Makefile located in 'arch/<system>' +is a tiny file used to define several variables. It then includes the file +freetype2/lib/Makefile.lib, +which contains all the gory details about library compilation. The system-specific +Makefile can be very easily modified to accomodate a new compiler/platform +(see the comments within one of these files). +

Each font driver is located in a directory like "freetype2/lib/drivers/<formatdir>". +For example, the TrueType driver is located in "drivers/truetype". +Each driver directory must contain a Makefile which will be included +by Makefile.lib. The former is used to define and build driver +object files. +
  +


+

+

+
+ +

+3. Make options :

+ +
The base layer, as well as each font driver, are made up of +several C sources. Traditionally, one compiles each source (i.e. '.c' +file) into an object ('.o' or '.obj') file, and all of +them are grouped into a library file (i.e. '.a' or '.lib'). +

By default, FreeType takes a slightly different approach when it comes +to compiling each part of the engine. Usually, a single tiny source is +compiled, which includes all other component sources. This results in a +single object files, with the benefits or reduced code size, usually better +compilation as well as a drastic reduction of the number of symbols exported +by the library. Of course, it is made possible through the use of specific +declaration macros in the FreeType source (see the definition of LOCAL_DEF +and LOCAL_FUNC in ftconfig.h for details). +

For a concrete example, see the source code in "base/ftbase.c" +which generates the whole base layer in a single object file. The same +build process is applied to font drivers, in order to generate one single +object file per given font format (e.g. truetype.o, type1.o, +etc..). +

Compiling the library and drivers in "normal" mode is possible, through +the use of the 'multi' target (which really means « multiple +objects »). For example, calling : +

% make -f arch/ansi/Makefile multi
+Will build the FreeType library by compiling each source file to an individual +object, then linking them together. You'll notice that the library is significantly +bigger in this case. Creating a shared dll from a 'multi' build is certainly +a very poor idea, as this will export a huge quantity of symbols that aren't +useful to any client application.
+ +

+4. Adding a driver at compile time

+ +
A driver can be included very easily in the build process by +including its Makefile in Makefile.lib. For example, +the TrueType driver is simply included with the following lines (see Makefile.lib): +
# TrueType driver rules +
# +
include $(DRIVERS_DIR)/truetype/Makefile
+ +


Where DRIVERS_DIR really is "freetype2/lib/drivers", +though this can be redefined. You can, of course specify a different path +if you want to place your driver sources in another location. +

Note that this only adds the driver's object files to the generated +library file. A few more steps are needed to make your FT_Library +objects use the driver. They consist in modifying the file "base/ftinit.c", +whose sole purpose is to define the set of driver objects that are to be +created with each new library object. +
 

+ +

+5. Adding a driver at run time

+ +
New driver objects can be added at run-time through the FT_Add_Driver +API. This function takes a handle to an existing library object, as well +as a pointer to a given driver interface. This interface is used to create +a new driver object and register it within the library. +

Similarly, a single driver can be removed from a library anytime through +FT_Remove_Driver. +This will automatically discard the resources and face objects managed +by the driver.

+ +

+6. Custom library objects :

+ +
Finally, it is possible to build custom library objects. You +need to pass a handle to a valid FT_System object to the FT_Build_Library +API. The function will return a handle to the new fresh library object. +Note that the library has no registered drivers after the call, developers +have to add them by hand with FT_Add_Driver. +

It is thus possible to create two distinct library objects with distinct +FT_System +implementations in the same session, which can be useful for debugging +purpose.

+ +
 
+ + + diff --git a/subsys/win32k/freetype/docs/design/io-frames.html b/subsys/win32k/freetype/docs/design/io-frames.html new file mode 100644 index 0000000..a5c6de7 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/io-frames.html @@ -0,0 +1,343 @@ + + + + + + FreeType 2 Internals - I/O Frames + + + + +

+ FreeType 2.0 I/O Frames +

+ +

+ © 2000 David Turner + (david@freetype.org)
+ © 2000 The FreeType Development Team + (www.freetype.org) +

+ +
+ + +
+ +
+ +

+ Introduction +

+ +

This document explains the concept of I/O frames as used in the + FreeType 2 source code. It also enumerates the various functions and + macros that can be used to read them.

+ +

It is targeted to FreeType hackers, or more simply to developers who + would like a better understanding of the library's source code.

+ +
+ +

+ I. What frames are +

+ +

Simply speaking, a frame is an array of bytes in a font file that is + `preloaded' into memory in order to be rapidly parsed. Frames are useful + to ensure that every `load' is checked against end-of-file overruns, and + provides nice functions to extract data in a variety of distinct + formats.

+ +

But an example is certainly more meaningful than anything else. The + following code

+ + +
+    error = read_short( stream, &str.value1 );
+    if ( error ) goto ...
+
+    error = read_ulong( stream, &str.value2 );
+    if ( error ) goto ...
+
+    error = read_ulong( stream, &str.value3 );
+    if ( error ) goto ...
+
+ +

can easily be replaced with

+ + +
+    error = FT_Access_Frame( stream, 2 + 4 + 4 );
+    if ( error ) goto ...
+
+    str.value1 = FT_Get_Short( stream );
+    str.value2 = FT_Get_ULong( stream );
+    str.value3 = FT_Get_ULong( stream );
+
+    FT_Forget_Frame( stream );
+
+ +

Here, the call to FT_Access_Frame() will

+ +
    +
  • +

    Ensure that there are at least 2+4+4=10 bytes left in the + stream.

    +
  • +
  • +

    `Preload' (for disk-based streams) 10 bytes from the current + stream position.

    +
  • +
  • +

    Set the frame `cursor' to the first byte in the frame.

    +
  • +
+ +

Each FT_Get_Short() or FT_Get_ULong() call + will read a big-endian integer from the stream (2 bytes for + FT_Get_Short(), 4 bytes for FT_Get_ULong) + and advance the frame cursor accordingly.

+ +

FT_Forget_Frame() `releases' the frame from memory.

+ +

There are several advantages to using frames:

+ +
    +
  • +

    Single-check when loading tables.

    +
  • +
  • +

    Making code clearer by providing simple parsing functions + while keeping code safe from file over-runs and invalid + offsets.

    +
  • +
+ +
+ +

+ II. Accessing and reading a frame with macros +

+ +

By convention in the FreeType source code, macros are able to use two + implicit variables named error and stream. This is + useful because these two variables are extremely often used in the + library, and doing this only reduces our typing requirements and make the + source code much clearer.

+ +

Note that error must be a local variable of type + FT_Error, while stream must be a local variable or + argument of type FT_Stream.

+ +

The macro used to access a frame is ACCESS_Frame(_size_), it will + translate to

+ + +
+    ( error = FT_Access_Frame( stream, _size_ ) )
+        != FT_Err_Ok
+
+ +

Similarly, the macro FORGET_Frame() translates to

+ + +
+    FT_Forget_Frame( stream )
+
+ +

Extracting integers can be performed with the GET_xxx() + macros, like

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Macro name + + Translation + + Description +
+ GET_Byte() + + FT_Get_Byte(stream) + +

Reads an 8-bit unsigned byte.

+
+ GET_Char() + + (FT_Char)
+ FT_Get_Byte(stream)
+
+

Reads an 8-bit signed byte.

+
+ GET_Short() + + FT_Get_Short(stream) + + Reads a 16-bit signed big-endian integer. +
+ GET_UShort() + + (FT_UShort)
+ FT_Get_Short(stream)
+
+ Reads a 16-bit unsigned big-endian integer. +
+ GET_Offset() + + FT_Get_Offset(stream) + + Reads a 24-bit signed big-endian integer. +
+ GET_UOffset() + + (FT_UOffset)
+ FT_Get_Offset(stream)
+
+ Reads a 24-bit unsigned big-endian integer. +
+ GET_Long() + + FT_Get_Long(stream) + + Reads a 32-bit signed big-endian integer. +
+ GET_ULong() + + (FT_ULong)
+ FT_Get_Long(stream)
+
+ Reads a 32-bit unsigned big-endian integer. +
+ +

(Note that an Offset is an integer stored with 3 bytes on + the file.)

+ +

All this means that the following code

+ + +
+    error = FT_Access_Frame( stream, 2 + 4 + 4 );
+    if ( error ) goto ...
+
+    str.value1 = FT_Get_Short( stream );
+    str.value2 = FT_Get_ULong( stream );
+    str.value3 = FT_Get_ULong( stream );
+
+    FT_Forget_Frame( stream );
+
+ +

can be simplified with macros:

+ + +
+    if ( ACCESS_Frame( 2 +4 + 4 ) ) goto ...
+
+    str.value1 = GET_Short();
+    str.value2 = GET_ULong();
+    str.value3 = GET_ULong();
+
+    FORGET_Frame();
+
+ +

Which is clearer. Notice that error and stream + must be defined locally though for this code to work!

+ +
+ +

+ III. Alternatives +

+ +

It is sometimes useful to read small integers from a font file without + using a frame. Some functions have been introduced in FreeType 2 to + do just that, and they are of the form FT_Read_xxxx.

+ +

For example, FT_Read_Short(stream, + &error) reads and returns a 2-byte big-endian integer from a + stream, and places an error code in the error + variable.

+ +

Thus, reading a single big-endian integer is shorter than using a frame + for it.

+ +

Note that there are also macros READ_xxx() which translate to

+ + +
+    FT_Read_xxx( stream, &error ), error != FT_Err_Ok
+
+ +

and can be used as in

+ + +
+    if ( READ_UShort( variable1 ) ||
+         READ_ULong ( variable2 ) )
+      goto Fail;
+
+ +

if error and stream are already defined + locally.

+ +
+
+ + + diff --git a/subsys/win32k/freetype/docs/design/library-compilation.png b/subsys/win32k/freetype/docs/design/library-compilation.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/library-compilation.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/logo1.png b/subsys/win32k/freetype/docs/design/logo1.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/logo1.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/objects_diagram.png b/subsys/win32k/freetype/docs/design/objects_diagram.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/objects_diagram.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/objects_diagram2.png b/subsys/win32k/freetype/docs/design/objects_diagram2.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/objects_diagram2.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/platform-detection.png b/subsys/win32k/freetype/docs/design/platform-detection.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/design/platform-detection.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/design/system-interface.html b/subsys/win32k/freetype/docs/design/system-interface.html new file mode 100644 index 0000000..c505bbe --- /dev/null +++ b/subsys/win32k/freetype/docs/design/system-interface.html @@ -0,0 +1,258 @@ + + + + + + + FreeType 2 Internals + + + + + +
+

+FreeType 2.0 System Interface

+ +
+

+© 2000 David Turner (david@freetype.org)
+© 2000 The FreeType Development Team (devel@freetype.org)

+ +


+


+
  +

Introduction:

+
    + This document explains how the FreeType 2 library performs the low-level and + system-specific operations of memory management and i/o access. It is targetted + to FreeType hackers, porters and "advanced" developers who want special + features like providing their own memory manager or streams. +

    + Note that the only system-specific part of the library is a file + named "ftsystem.c", normally located in the directory + "freetype2/config/<system>" where <system> designates + your platform (e.g. "config/ansi/ftsystem.c" or + "config/unix/ftsystem.c"). +

    +

+ +

+


+

+ +

I. Memory Management

+
    + Memory allocation and releases are performed through a FT_Memory object in + FreeType. A FT_Memory is nothing more than a table of functions plus + an arbitrary user data field. It is defined in the file + "freetype2/include/ftsystem.h" and has the following structure: +

    +

      + typedef struct
      + { +
        + +
        void* user // a user-defined pointer. This is zero by default +
        void* (*alloc)( FT_System, int) // a function used to allocate a new block +
        void* (*realloc)( FT_System, int, int, void* ) // a function used to reallocate a given block +
        void (*free)( FT_System, void*) // a function used to release a given block +
        +
      + } FT_MemoryRec, *FT_Memory;
      +
    +

    + You'll notice that:

    +

      +
    • The FT_Memory type is really a pointer to a FT_MemoryRec. + This is a normal convention for the FreeType code. +
    • The realloc takes two integer arguments. The first one is the + current block size, the second one its new size. +
    +

    + + All current implementations of "ftsystem.c" provide a very simple + implementation of the FT_Memory interface by calling directly the + standard C alloc, realloc and free. +

    + The FreeType source code never invokes directly the function pointers. Rather, + it calls FT_Alloc, FT_Realloc and FT_Free functions + which are defined in "freetype2/src/base/ftobjs.c". These will not be + discussed here. +

    + If you want to use your own memory allocator rather than the one provided + by your build of FreeType, follow these simple steps:

    +

      +
    1. Create your own FT_Memory object, with pointers that map to + your own memory management routines (beware function signatures though). +

      +

    2. Call FT_Build_Library(memory,&library). This will create a new + FT_Library object that uses your own FT_Memory exclusively. + Note however that this library has no font drivers loaded in !! +

      +

    3. Load the default font drivers into the new library, either by + calling FT_Default_Drivers(library), or by adding them manually + through repeated calls to FT_Add_Driver(library,&driver_interface) +

      +

    + This will replace the FT_Init_FreeType(&library) call that an application + must do to initialise one library instance. +

    + Notice that you don't need to recompile FreeType 2 to use your own memory + manager !!. +

    +

+ +

+


+

+ +

II. Streams

+
    +

    1. Basic Stream Structure

    +

    + A stream models the array of bytes found in a font file. FreeType 2 separates + streams into two families :

    +

      +
    • memory-based streams:
      + when the stream's content is entirely found in memory. This is the + case for ROM font files, or memory-mapped files. +

      +

    • disk-based streams:
      + when the stream isn't directly accessible in memory. This is the + case for local or remote files. +

      +

    +

    + Note that a stream's nature only determines how FreeType accesses its content, not + the way it is effectively stored. For example, in the case of a compressed font file, + one implementation may choose to uncompress the font in memory, then provide a memory + based stream to access it. Another one might chose a disk based stream to perform + on-the-fly decompression of the font data. Similarly, the font file can be stored + on a local disk, or obtained from a network. This will be completely transparent to + FreeType. +

    + The stream structure is: +

    +

      + typedef struct
      + {
      +
        +
        char* base for memory-based streams, the address + of its first byte. + +
        ulong size the stream's size in bytes. + +
        ulong pos the current stream position in the file + +
        descriptor a union field used to hold either an + integer file descriptor or pointer. + This field is not used by FreeType + itself, but is left to implementations + of "ftsystem" +
        pathname a union field that can hold either an + integer or pointer. It is not used by + FreeType itself, but is left to + implementations. These can put the + file pathname's during debugging for + example. + +
        read a pointer to a function used to seek the + stream and/or read a run of bytes from it. + +
        close a pointer to a function called when the + stream is closed. + +
        memory a FT_Memory object, which is used + to allocate frames for disk-based streams. + This field is set and used by FreeType. + +
        cursor a pointer in memory used when accessing + frames. This is set and used by FreeType. + +
        limit a pointer in memory used when accessing + frames. This is set and used by FreeType. +
      + } FT_StreamRec, *FT_Stream +
    +

    + + The following important things must be noticed here:

    +

      +
    • The FT_Stream type is really a pointer to a FT_StreamRec. + This is a normal convention for the FreeType source. +

      + +

    • When the read field is non NULL, the stream is considered to be + disk-based. Otherwise, the stream is memory-based, and the base + field must be set by "ftsystem.c" when the stream is + created. +

      + +

    • The base field must be set to 0 when a disk-based stream is created. + However, this field will later be set and used by the FreeType library when + accessing frames of bytes within the font file (of course, this doesn't + happen with memory-based streams). +
    + +

    2. Stream lifecyles

    +

    + Each FT_Face needs its own stream to access font data. The most common + way to create a new FT_Stream object is to call the function + FT_New_Face. This function takes a file pathname argument that + is used to create a new stream object. +

    + This is possible because each implementation of "ftsystem.c" provides + a function called FT_New_Stream which takes a file pathname and a + FT_Stream pointer as an argument. The function simply opens the file + and initialises the stream structure accordingly. It is called by FT_New_Face + to create the face's stream object. +

    + A stream is only closed when the face is destroyed through FT_Done_Face. + Its close field function will then be called. Note that the function should + never destroy the FT_Stream. +

    + + +

    3. Using your own streams

    +

    + There are cases where it is interesting to provide your own stream to create + a new face object, rather than rely on the default implementation. For example, + a filepathname, which is a C string, might not be useful on a system where files + are named with a UTF-16 string or via an i-node number of memory address (for ROM files). +

    + For this purpose, the FT_Open_Face is defined. It simply takes a + FT_Stream pointer as its second argument, instead of a file pathname (the + stream must be allocated and initialised by you, so be careful). +

    + Actually, the only thing that FT_New_Face does is create a new stream + through FT_New_Stream, then call FT_Open_Face to create the + face with it. +

    + Note also that you can use the function FT_New_Memory_Face to create + a new font face for a memory-based font file, whose address and size can be passed + as arguments. The function automatically creates the corresponding memory-based + stream and use it to create the face. +

    + +

+ + +

+


+

+ +

III. Thread synchronisation

+
    + The FreeType library uses no static data. It can be used concurrently by two + thread as long as each one uses its own FT_Library instance. Otherwise, + one can very simply synchronize access to a single library instance by using a + mutex to protect each call to one of FreeType's API functions. +

    +

+ + diff --git a/subsys/win32k/freetype/docs/docmaker.py b/subsys/win32k/freetype/docs/docmaker.py new file mode 100644 index 0000000..5a6ea0e --- /dev/null +++ b/subsys/win32k/freetype/docs/docmaker.py @@ -0,0 +1,516 @@ +#!/usr/bin/env python +# +# DocMaker is a very simple program used to generate HTML documentation +# from the source files of the FreeType packages. +# + +import fileinput, sys, string + +# This function is used to parse a source file, and extract comment blocks +# from it. The following comment block formats are recognized : +# +# /************************** +# * +# * FORMAT1 +# * +# * +# * +# * +# *************************/ +# +# /**************************/ +# /* */ +# /* FORMAT2 */ +# /* */ +# /* */ +# /* */ +# /* */ +# +# /**************************/ +# /* */ +# /* FORMAT3 */ +# /* */ +# /* */ +# /* */ +# /* */ +# /**************************/ +# +# Each block is modeled as a simple list of text strings +# The function returns a list of blocks, i.e. a list of strings lists +# + +def make_block_list(): + """parse a file and extract comments blocks from it""" + + list = [] + block = [] + format = 0 + + for line in fileinput.input(): + + line = string.strip(line) + l = len(line) + + if format == 0: + if l > 3 and line[0:3] == '/**': + i = 3 + while (i < l) and (line[i] == '*'): + i = i+1 + + if i == l: + # this is '/**' followed by any number of '*', the + # beginning of a Format 1 block + # + block = []; + format = 1; + + elif (i == l-1) and (line[i] == '/'): + # this is '/**' followed by any number of '*', followed + # by a '/', i.e. the beginning of a Format 2 or 3 block + # + block = []; + format = 2; + + ############################################################## + # + # FORMAT 1 + # + elif format == 1: + + # if the line doesn't begin with a "*", something went + # wrong, and we must exit, and forget the current block.. + if (l == 0) or (line[0] != '*'): + block = [] + format = 0 + + # otherwise, we test for an end of block, which is an + # arbitrary number of '*', followed by '/' + else: + i = 1 + while (i < l) and (line[i] == '*'): + i = i+1 + + # test for the end of the block + if (i < l) and (line[i] == '/'): + if block != []: list.append( block ) + format = 0 + block = [] + + else: + block.append( line[1:] ) + + ############################################################## + # + # FORMAT 2 + # + elif format == 2: + + # if the line doesn't begin with '/*' and end with '*/', + # this is the end of the format 2 format.. + if (l < 4 ) or (line[:2] != '/*') or (line[-2:] != '*/'): + if block != []: list.append(block) + block = [] + format = 0 + continue + + # remove the start and end comment delimiters, then right-strip + # the line + line = string.rstrip(line[2:-2]) + + # check for end of a format2 block, i.e. a run of '*' + if string.count(line,'*') == l-4: + if block != []: list.append(block) + block = [] + format = 0 + else: + # otherwise, add the line to the current block + block.append(line) + + return list + + +# This function is only used for debugging +# +def dump_block_list( list ): + """dump a comment block list""" + for block in list: + print "----------------------------------------" + for line in block: + print line + print "---------the end-----------------------" + + + + + +###################################################################################### +# +# +# The DocParagraph is used to store either simple text paragraph or +# source code lines +# +# +# If the paragraph contains source code (use code=1 when initializing the +# object), self.lines is a list of source code strings +# +# Otherwise, self.lines is simply a list of words for the paragraph +# +class DocParagraph: + + def __init__(self,code=0,margin=0): + self.lines = [] + self.code = code + self.margin = margin + + def add(self,line): + + if self.code==0: + # get rid of unwanted spaces in the paragraph + self.lines.extend( string.split(line) ) + + else: + # remove margin whitespace + if string.strip( line[:self.margin] ) == "": line = line[self.margin:] + self.lines.append(line) + + + def dump(self): + + max_width = 50 + + if self.code == 0: + cursor = 0 + line = "" + + for word in self.lines: + + if cursor+len(word)+1 > max_width: + print line + cursor = 0 + line = "" + + line = line + word + " " + cursor = cursor + len(word) + 1 + + if cursor > 0: + print line + + else: + for line in self.lines: + print "--" + line + + print "" + + +###################################################################################### +# +# +# The DocContent class is used to store the content of a given marker +# Each DocContent can have its own text, plus a list of fields. Each field +# has its own text too +# +# Hence, the following lines : +# +# """ +# Some arbitraty text: +# +# fieldone :: some arbitraty text for this field, +# note that the text stretches to several lines +# +# fieldtwo :: some other text +# +# """ +# +# will be stored as (each text is a list of string: +# +# self.fields = [ "", "fieldone", "fieldtwo" ] +# self.texts = [ +# [ "some arbitraty text for this field," , +# "note that the text stretches to several lines" ], +# +# [ "some other text" ] +# ] +# +# +class DocContent: + + def __init__(self, paragraph_lines=[]): + + self.fields = [] + self.texts = [] + + code_mode = 0 + code_margin = 0 + + field = "" + text = [] + paragraph = None + + for aline in paragraph_lines: + + if code_mode == 0: + line = string.lstrip(aline) + l = len(line) + margin = len(aline) - l + + # if the line is empty, this is the end of the current + # paragraph + if line == "": + if paragraph: + text.append(paragraph) + paragraph = None + continue + + # test for the beginning of a code block, i.e.'{' is the first + # and only character on the line.. + # + if line == '{': + code_mode = 1 + code_margin = margin + if paragraph: + text.append(paragraph) + paragraph = DocParagraph( 1, margin ) + continue + + words = string.split(line) + + # test for a field delimiter on the start of the line, i.e. + # the oken `::' + # + if len(words) >= 2 and words[1] == "::": + if paragraph: + text.append(paragraph) + paragraph = None + + self.fields.append(field) + self.texts.append(text) + + field = words[0] + text = [] + words = words[2:] + + if len(words) > 0: + line = string.join(words) + if not paragraph: + paragraph = DocParagraph() + paragraph.add( line ) + + else: + line = aline + + # the code block ends with a line that has a single '}' on it + if line == " "*code_margin+'}': + text.append(paragraph) + paragraph = None + code_mode = 0 + code_margin = 0 + + # otherwise, add the line to the current paragraph + else: + paragraph.add(line) + + if paragraph: + text.append(paragraph) + + self.fields.append( field ) + self.texts.append( text ) + + + + def dump(self): + for i in range(len(self.fields)): + field = self.fields[i] + if field: print "" + + for paras in self.texts[i]: + paras.dump() + + if field: print " " + + def dump_html(self): + n = len(self.fields) + for i in range(n): + field = self.fields[i] + if field==[]: + print "

" + for paras in self.texts[i]: + print "

" + paras.dump() + print "

" + else: + if i==1: + print "" + if n > 1: + print "
" + else: + print "
" + + print ""+field+"" + + for paras in self.texts[i]: + print "

" + paras.dump() + print "

" + + print "
" + + +###################################################################################### +# +# +# The DocBlock class is used to store a given comment block. It contains +# a list of markers, as well as a list of contents for each marker. +# +# +class DocBlock: + + def __init__(self, block_line_list=[]): + self.markers = [] + self.contents = [] + + marker = "" + content = [] + alphanum = string.letters + string.digits + "_" + + for line in block_line_list: + line2 = string.lstrip(line) + l = len(line2) + margin = len(line) - l + + if l > 3 and line2[0] == '<': + i = 1 + while i < l and line2[i] in alphanum: i = i+1 + if i < l and line2[i] == '>': + if marker or content: + self.add( marker, content ) + marker = line2[1:i] + content = [] + line2 = string.lstrip(line2[i+1:]) + l = len(line2) + line = " "*margin + line2 + + content.append(line) + + if marker or content: + self.add( marker, content ) + + + def add( self, marker, lines ): + + # remove the first and last empty lines from the content list + l = len(lines) + if l > 0: + i = 0 + while l > 0 and string.strip(lines[l-1]) == "": l = l-1 + while i < l and string.strip(lines[i]) == "": i = i+1 + lines = lines[i:l] + l = len(lines) + + # add a new marker only if its marker and its content list aren't empty + if l > 0 and marker: + self.markers.append(marker) + self.contents.append(lines) + + def dump( self ): + for i in range( len(self.markers) ): + print "["+self.markers[i]+"]" + for line in self.contents[i]: + print "-- "+line + + def doc_contents(self): + contents = [] + for item in self.contents: + contents.append( DocContent(item) ) + return contents + + +def dump_doc_blocks( block_list ): + for block in block_list: + docblock = DocBlock(block) + docblock.dump() + print "<<------------------->>" + + +# +# +# +def dump_single_content( block_list ): + + block = block_list[0] + docblock = DocBlock(block) + + print "" + for i in range(len(docblock.markers)): + marker = docblock.markers[i] + contents = docblock.contents[i] + + print "" + doccontent = DocContent( contents ) + + doccontent.dump() + + print "" + + print "" + +def dump_doc_contents( block_list ): + + for block in block_list: + docblock = DocBlock(block) + print "" + + for i in range(len(docblock.markers)): + print "" + content = DocContent( docblock.contents[i] ) + content.dump() + print "" + print "" + +def dump_html_1( block_list ): + + print "" + types = [ 'Type', 'Struct', 'FuncType', 'Function', 'Constant', 'Enumeration' ] + for block in block_list: + docblock = DocBlock(block) + print "
" + for i in range(len(docblock.markers)): + marker = docblock.markers[i] + content = docblock.contents[i] + dcontent = DocContent( content ) + + if marker=="Description": + print "

    " + dcontent.dump() + print "

" + + elif marker in types: + print "

"+content[0]+"

" + else: + print "

"+marker+"

" + print "

    " + dcontent.dump_html() + print "

" + + print "" + + print "
" + + +def main(argv): + """main program loop""" + print "extracting comment blocks from sources .." + list = make_block_list() + +# dump_block_list( list ) + +# dump_doc_blocks( list ) + +# print "dumping block contents .." +# dump_doc_contents(list) + + dump_html_1(list) + +# dump_single_content(list) + +# If called from the command line +if __name__=='__main__': main(sys.argv) diff --git a/subsys/win32k/freetype/docs/freetype2.html b/subsys/win32k/freetype/docs/freetype2.html new file mode 100644 index 0000000..3cc94c9 --- /dev/null +++ b/subsys/win32k/freetype/docs/freetype2.html @@ -0,0 +1,352 @@ + + +FreeType 2 Introduction + + + + + + + +http://www.freetype.org

+ +

+ + The FreeType Project +

An Introduction to FreeType 2

+
+ +
+

+ +DOCUMENT INDEX:
+

+ + +


+ +
+

What is FreeType 2 ?

+
+ +

The FreeType project is a team of volunteers who develop free, portable +and high-quality software solutions for digital typography. We specifically +target embedded systems and focus on bringing small, efficient and +ubiquitous products.

+ +

the FreeType 2 library is our new software font engine. It has been + designed to provide the following important features:

+ +
    +
  • + A universal and simple API to manage font files:
    +

      +

      The FreeType 2 API is simple and easy to use. It supports both + bitmapped and scalable fonts and is well-suited to manage font + files of all formats. Unlike other font libraries, FreeType 2 + returns and manages outline font data (images & metrics).

      +
    +

  • + +
  • + Support for several font formats through loadable modules:
    +

      +

      FreeType 2 uses "font drivers". Each driver is a loadable + module used to support one specific font format. Each driver can also + provide specific extensions used to access format-specific features of + the font.

      +
    +

  • + + +
  • + High-quality anti-aliasing:
    +

      +

      FreeType 2 produces etremely smooth outlines at small sizes, with its new + anti-aliasing renderer, which produces bitmaps with 256-levels of gray. + It uses a new algorithm that has been specifically designed to render + small complex shapes (like glyphs) at high speed. Indeed, it's even + faster than the monochrome renderer for small character sizes (under + 20 pixels) !! +

      +
    + + +
  • High portability & performance:
    +
      +

      The FreeType 2 source code is written in ANSI C and runs on any + platform with a compliant compiler. Client applications can + provide their own memory manager or input stream to the library + (which means that font files can come from any place: disk, + memory, compressed file, network, etc..). +

      +
    + +
+ +

Note that the beta of FreeType 2 is available now. For more + info, check our Download page or see the source + and its diffs through our CVS Web interface. +

+ + +
+ +
+

Features

+
+ +

Supported font formats

+ +

FreeType 2 readily supports the following font formats:

+ +
    +
  • TrueType files (.ttf) and collections (.ttc)
  • +
  • Type 1 font files both in ASCII (.pfa) or binary (.pfb) format
  • +
  • Type 1 Multiple Master fonts. The FreeType 2 API also provides + routines to manage design instances easily
  • +
  • Type 1 CID-keyed fonts
  • +
  • OpenType/CFF (.otf) fonts
  • +
  • CFF/Type 2 fonts
  • +
  • Adobe CEF fonts (.cef), used to embed fonts in SVG documents + with the Adobe SVG viewer plugin.
  • +
  • Windows FNT/FON bitmap fonts
  • +
+ +

Note that Apple's TrueType GX fonts are supported as normal TTFs, + (the advanced tables are ignored).

+ +

Besides, it's possible to add support for new font formats by providing + a specific font driver module. Modules can be added either at + build time (when recompiling the library), or at run-time; + this allows, for example, applications to register their own + font driver to support program-specific formats.

+ + +

Patent-free automatic hinter

+ +

TrueType fonts are normally renderered (hinted) with the help of a + specific bytecode where the behaviour of a few opcodes is patented by + Apple. We're currently in contact with Apple to discuss the importance + of such patents and their use in open source projects like FreeType. +

+ +

In the meantime, we have developped our own alternative technology that + is capable of automatically hinting scalable glyph images. It is + now part of the FreeType 2 source tree as the "autohint" module, + and is used to hint glyphs when the bytecode interpreter is disabled + (through a configuration macro when building the engine). Note that + the auto-hinter is also used to handle glyphs in other formats like + CFF and Type 1.

+ +

The auto-hinter provides pretty good results (in some cases, it even + significantly improves the output of poorly hinted fonts) but we'll + continue to improve it with each new release of FreeType to achieve + the highest possible quality.

+ + +

Modular design:

+ +

The design of FreeType 2 is extremely modular as most features are + supported through optional modules. This means it's easily possible to + only compile the features you need. As each module is between + 10 and 20 Kb in size, it's possible to build a bare-bones + font engine that supports anti-aliasing in about 30 Kb !!

+ +

Configuration is performed by modifications of only two header + files (one to select global features, another one to select modules) + and don't need tweaking of source code. Note that it is however + possible to provide your own implementation of certain components.

+ +

For example, when building on Unix, the engine will automatically + use memory-mapped files when available on the target platform, + thus significantly increasing font file i/o.

+ + +

Due to its very flexible design, it is possible to add, remove and + upgrade modules at run-time.

+ + + +

Advanced glyph management

+ +

The API comes with a standard extension used to extract individual + glyph images from font files. These images can be bitmaps, scalable + bezier outlines or even anything else. (e.g. bi-color or metafont + glyphs, as long as they're supported by a module).

+ +

Each scalable glyph image can be transformed, measured and + rendered into a monochrome or anti-aliased bitmaps easily + through a uniform interface. + + This allows client applications to easily cache glyphs or + perform text rendering effects with minimal difficulty + (look at the FreeType 2 Tutorial to see how to render + rotated text with very few lines of code). +

+ + + +

Advanced font access

+ +

The FreeType 2 API is useful to retrieve advanced information from + various fonts:

+ +
    +
  • vertical metrics are available whenever found in the font file
  • + +
  • kerning distances are available when found in the font file. It + is also possible to "attach" a given additional file to a given + font face. This is useful to load kerning distances from an + .afm file into a Type 1 face for example.
  • + +
  • provides ASCII glyph names whenever available in the font + (TrueType, OpenType, Type1, etc..)
  • + +
  • provides access to important tables for SFNT-based font formats + (i.e. TrueType, OpenType, CEF, etc..), like the name table, + font header, maximum profile, etc...
  • + +
  • automatic synthesis of Unicode-based character maps for + those fonts or formats that do not provide one. This is + extremely useful with Type 1 fonts which are normally + limited to a stupid 256-characters encoding.
  • +
+ + +

Simple & clean API

+ +

The FreeType 2 high-level API is simple and straightforward, as it + has been specifically designed to make the most commmon font operations + easy

+ +

As a comparison, the number of function calls needed to perform a + the tasks of font face creation/opening and glyph loading/rendering + has been reduced by a factor of 4 !!

+ +

The API is also independent of any font-format specific issue, though + it provides standard extensions to access format-specific tables and + information. More extensions can also be easily added through new + modules

+ + +

Robust & Portable code

+ +

Because it is written in industry-standard ANSI C, FreeType 2 compiles + on all platforms with a compliant compiler. Because the default build + only relies on the C library, it is free of any system-specific + dependencies, even if it is possible to "enhance" certain components + by providing a specific implementation.

+ +

The code doesn't use global or static variables. Client applications + can provide their own memory manager. Font files can be read from + a disk file, memory, or through a client-provided input stream. This + allows to support compressed font files, remote fonts, fonts embedded + in other streams (e.g. Type42 fonts), etc..

+ +

An advanced i/o sub-system is used to optimise file access, as well + as reduce memory usage of the library when the file is memory-based + ( ROM, RAM, memory-mapped ).

+ + +

Open Source & Vendor Independence

+ +

Finally, FreeType 2 is released under its own BSD-like open source + license, one of the less restricting licenses available, and this + means that:

+ +
    +
  • + It can be included in all kinds of products, be they proprietary + or not. +

  • + +
  • + As any module can be added or replaced anytime, any third party + vendor has the ability to provide its own set of modules (under + its own license) in order to support proprietary font formats or + more advanced features (e.g. a new auto-hinter, or a new + anti-aliasing renderer for LCDs or TV screens). +

  • +
+ +

One could even imagine an application using the FreeType 2 API with + a "wrapper" module used to access system-specific fonts (like through + the Windows GDI). This would mean native font support with more portable + application code (as simply changing the wrapper module would be required + to port the application to another system).

+ +
+ +
+

Requirements

+
+ +

FreeType 2 is written in ANSI C and should compile with no problems + on a great variety of platforms. We have taken care of removing all + compilation warnings from major compliant compilers. Detailed compilation + instructions are provided in the software archive.

+ +

This version of the library has been succesfully compiled and run + under the following systems: Dos, OS/2, Windows, Macintosh, Unix + (including the 64-bits DEC Unix, a.k.a. "True64"). You should not + encounter major problems compiling it on any other kind of platform. + In all cases, contact us if you do.

+ +

Note that a small set of demonstration programs is also separately + available. They include a tiny graphics sub-system that is used to + display and show-off the library's capabilities on the following + platforms: X11, MacOS, OS/2 & Windows.

+ +

Please visit our + Download section to access the software archives.

+ + + +
+ +
+

Patents issues

+
+ +

The FreeType 2 source code includes a TrueType bytecode interpreter that + is covered by the Apple patents. However, this piece of code is never + compiled by default in this release (unlike in previous betas) making + a default build of the library entirely patent-free !!

+ +

Note that in order to compile the interpreter, one needs to define + the configuration macro TT_CONFIG_OPTION_BYTECODE_INTERPRETER configuration + macro in the file "ftoption.h". More details are available in + the software archive. Note that the use of the interpreter is normally + protected by US, UK and French patents. In the event you'd absolutely + need it, you may have to contact + Apple legal department for licensing conditions, depending on your + location and the places you distribute/sell your products.

+ +

Please do not ask us any detailed information regarding licensing, as + we're still discussing with Apple this issue, we're unable to inform + the public of what's currently going on..

+ +
+ +


+

+Back to FreeType homepage

+ +

+ + diff --git a/subsys/win32k/freetype/docs/ft2faq.html b/subsys/win32k/freetype/docs/ft2faq.html new file mode 100644 index 0000000..6b9cc9b --- /dev/null +++ b/subsys/win32k/freetype/docs/ft2faq.html @@ -0,0 +1,502 @@ + + +FreeType 2 FAQ + + + + + + + +http://www.freetype.org

+ +

+ + The FreeType Project +

The FreeType 2 FAQ

+
+ +
+

+ +DOCUMENT INDEX:
+

+ + +


+ +
+

General questions & answers

+
+ + +

I.1. I though the FreeType project was dead. Is this true?

+
    +

    Well, not exactly :-) It's true that the TrueType patents issues + have been less than a graceful event to handle but it didn't not + really killed the project per se, as Apple hasn't made an official + statement yet regarding the use of the patented "technology" in + open source projects (or other products).

    + +

    We have thus continued updating FreeType 1.x, and started developping + FreeType 2 with the idea of providing this time a completely patent + free font engine. However, we largely preferred not to broadly + communicate about it until we've got a satisfying implementation + to show.

    +
+ + +
+

I.2. Why did it take so long to release FreeType 2?

+
+ + +

I.3. Is FreeType 2 a Unix-only project?

+
+ + +

I.4. When will X11/XFree support anti-aliased text?

+
    +

    This question isn't exactly related to FreeType as we have no direct + connection to the XFree people, but we've been asked so frequently + about it that it deserves a prominent place in this FAQ :-)

    + +

    FreeType has been capable of anti-aliasing since version 1.0. The + reason why XFree doesn't support it is directly related to the + limitations of the design and specification of X11. More specifically:

    + +
      +
    • + X11 assumes that all glyph images are monochrome bitmaps, + hence the X font library and server are unable to send anything + else to the X server. +

    • + +
    • + Even if the X font library/server was able to generate anti-aliased + bitmaps (and this has been already done through extensions), the X + rendering model doesn't allow translucent composition of "gray" pixmaps + onto an arbitrary drawable. +

    • +
    + +

    As both the font and rendering models of X11 are limited, it's basically + impossible to draw anti-aliased glyphs without performing huge + hacks within the server.

    + +

    Note that Keith Packard, from XFree fame, has recently started working + on a new rendering model for X11 in order to support new features + (mainly transparency and anti-aliased fonts). This will be provided + through protocol extensions. The question of knowing wether legacy X + applications will be able to display anti-aliased text is still very + uncertain. +

    +
+ +
+

I.5. Is FreeType 2 backwards compatible with FreeType 1.x?

+
    +

    Not directly, though we had the project to provide an optional binary + compatibility layer on top of it in order to easily re-link applications + with the new version. However, this idea has been dropped as it is + possible to install and use the two versions independtly on any + system (read: no namespace conflicts).

    + +

    The FreeType 2 API is a lot simpler than the one in 1.x while being + much more powerful. We thus encourage you to adapt your source code + to it as this should not involve much work.

    + +
+ +
+

I.6. Can I use FreeType 2 to edit fonts or create new ones?

+
    +

    The answer is a definitive NO, because the library was specifically + designed to read font files with small code size and very + low memory usage.

    + +

    We thus do not plan to support editing or creation in the font + engine in any way, as this would imply a complete rewrite. This + doesn't mean that we won't introduce a font editing/creation library + in the future, as this really depends on how many people are asking + for it (or how much they would be willing to pay for it), as well as + the time of the FreeType developers.

    + +

    Do not expect anything in this direction until we officially announce + something though. There are other axis of development for this project + (like text-layout capabilities, glyph caching, etc..) that may be more + important to us at the moment..

    +
+ +
+ +
+

Compilation & Configuration

+
+ + +

II.1. How do I compile the FreeType 2 library?

+
    +

    The library can be compiled in various ways, and a detailed documentation + is available in the file "freetype2/docs/BUILD". However, we'll + summarize the process to a few cases:

    + +

    a. by using the command-line 2 build system

    + +

    The engine comes with a sophisticated build system that is used + to configure and compile a build of the library. You'll need + GNU Make installed on your platform (NOTE: It will not + work with other Make tools).

    + +

    Basically, you'll need to invoke make a first time in the + top-level FreeType 2 directory in order to setup the build. This will + detect your current platform and choose a configuration sub-makefile to + drive the build. A specific compiler can be selected on some platforms + by providing an additional target. For example, on Win32:

    + +
      +
    • make visualc will select the Visual C++ compiler
    • +
    • make lcc will select the Win32-lcc compiler
    • +
    + +

    Note that on Unix, the first time make is called, a configure script + located in "freetype2/builds/unix" will be run in order to + automatically detect the platform & compiler.

    + +

    A summary will be displayed showing the detected platform and compiler + selected. You'll then be able to start the build by invoking make + a second time. In case of problem, consult the BUILD document.

    + + +

    b. by direct compilation

    + +

    You can also directly compile the library from the command line by + using these simple rules:

    + +
      +
    • + You should place the directories "freetype2/include" and + "freetype2/src" in your include path in order to compile + any component of the library. You can also add the system-specific + build directory (i.e. "builds/system/") in the + case where an alternate implementation of some of the components + is available there (e.g. the memory-mapped i/o implementation + on some Unix systems). +

    • + +
    • + The components of the library are located in sub-directories of + "src", for example: "src/base", + "src/truetype", etc.. +

    • + +
    • + Each component is normally compiled through a single C file that + "wraps" other sources in the component's directory. For example, + your should compile the TrueType font driver by compiling the + file "src/truetype/truetype.c". The list of C files to + compile for a feature-complete build of the library is given in + the BUILD document. +

    • +
    + +

    c. in a graphical IDE

    +
      +

      Well, the process is vastly similar to the one described in b., + except that you need to set the include paths, source code paths, + etc.. in dialog boxes before running the compilation. +

      +
    + +
+ +
+

II.2. How do I configure my build of the library?

+
    +

    Each build of the library is configured through two header files + located in "include/freetype/config":

    + +
      +
    • ftoption.h
      + This file contains various configuration macros whose definition + can be toggled on a per-build basis. Each macro is heavily + commented in this file's comment, and we invite you to refer + to it directly.

    • + +
    • ftmodule.h
      + This file contains the list of all the modules that are initially + registered (added) when the function FT_Init_FreeType + is called. See the next answer to know how to change it and + why it may be important.

    • +
    + +

    Alternatively, some specific implementations of some FT2 components + can be provided in a "builds/system/" directory + (e.g. the Unix-specific ftsystem.c that uses memory-mapped + file for i/o).

    +
+ +
+

II.3. How do I select the modules I need in my build?

+
    +

    The function FT_Init_FreeType creates a new instance + of the FT2 library and registers a set of "default" modules before + returning to the calling application. Its default implementation + is in the file "src/base/ftinit.c".

    + +

    The list of default modules used by ftinit.c is located in + the configuration file "include/freetype/config/ftmodule.h". + It is normally automatically generated by the build system by + invoking the "make modules" command in the top + level FT2 directory (note: only works with GNU Make, you can + edit the file by hand otherwise). It does so by parsing all + sub-directories of "src" that contain a file named + module.mk.

    + +

    Note that a specific port or project is free to provide its own + implementation of ftinit.c in order to ensure a different + initialisation sequence. For example, one could do something like:

    + +
      +
    • compile each module as a shared library (DLL or .so) with + a common "entry point" to retrieve a pointer to its + module class (there is already some code that allows this + when compiling each module).

    • + +
    • place these modules in a directory like + "/usr/lib/freetype2/modules/"

    • + +
    • provide an implementation of ftinit.c that would + scan the directory for valid modules.

    • +
    + +

    This example only emphasize the flexibility that is left to + developers when building the library.

    + +
+ +
+

II.4. How do I compile all FreeType 2 files in a single directory?

+
    +

    Some projects may need, for the sake of simplicity or ease of + building, to compile the FT2 library with all source files + copied to a single directory. This is possible.

    + +

    To do so, you'll need to copy all source files located under + "src" to your own directory (you must retain the + include files in a distinct hierarchy though), then compile + each of the FreeType 2 component with the macro + FT_FLAT_COMPILE. This will change the way + #include works during the build.

    +
+ +
+ +
+

Using the FreeType 2 library

+
+ +
+ +
+

The FreeType 2 auto-hinter

+
+ + +

IV.1. Under which license is the FreeType 2 auto-hinter released

+
    +

    The auto-hinter was initially designed and implemented under contract + for Catharon Productions, Inc + which gladly accepted to released it under an open-source license + compatible with the FreeType one.

    + +

    This license can be found in "src/autohint/CatharonLicense.txt" + and requires that you cite Catharon Productions in your documentation + (just like you do with FreeType) when using the auto-hinting module.

    + +

    Other than that, you still have the same freedom than with the good old + FreeType license. Enjoy !

    +
+ + +

IV.2. How does the auto-hinter works ?

+
    +

    Well, a complete description would be difficult. Have a look at the + dedicated auto-hinter pages on the FreeType + site, as they describe most of its details with graphics and explanations. + You could also look at the source code if you want to :-)

    + +

    To give a few details, the auto-hinter is used to perform grid-fitting + on scalable font formats that use bezier outlines as their primary glyph + image format (this means nearly all scalable font formats today). When + a given font driver doesn't provide its own hinter, the auto-hinter is + used by default. When a format-specific hinter is provided, it is still + possible to use the auto-hinter using the + FT_LOAD_FORCE_AUTOHINT bit flag when calling + FT_Load_Glyph.

    + +

    The auto-hinter currently doesn't use external hints to do its job, + as it automatically computes global metrics (when it "opens" a font + for the first time) and glyph "hints" from their outline. Note that + we plan the ability to specify external hints, given that it is based + on a constraint system. That could be used to support native hints + in Type 1/Type 2 fonts, for example.

    +
+ + +

IV.3. Why does the auto-hinter doesn't work correctly with CJK fonts ?

+
    +

    The auto-hinter was first designed to manage and hint latin-based fonts, + as they consist of most of the fonts available today. It doesn't hint + asian fonts, as well as a few other complex scripts, because we didn't + put enough research on the topic yet. Hinting CJK isn't really more + difficult than latin, just different with a set of different constraints + (basically, more distortion of glyphs is acceptable as long as certain + features like triple-stem positions are respected more strictly..).

    + +

    We thus plan to handle such a case rather rapidly.. Please be patient.

    +
+ + +
+ +
+

Other questions

+
+ + +

V.1. What is the anti-aliasing algorithm used by FreeType 2 ?

+
    +

    The algorithm has been specifically designed for FreeType. It is + based on ideas that were originally found in the implementation + of the libArt graphics + library to compute the exact pixel coverage of a vector + image with absolutely now sub-sampling/filtering. +

    + +

    However, these two implementations are radically distinct and use + vastly different models. The FreeType 2 renderer is optimized + specifically for rendering small complex shapes, like glyphs, at + very high speed while using very few memory; while libArt shines + at general shape/polygon processing, especially large ones.

    + +

    The FT2 anti-aliasing renderer is indeed faster than the + monochrome renderer for small character sizes (typically < 20 pixels). + This is explained because the monochrome renderer must perform two + passes on the outline in order to perform drop-out control according + to the TrueType spec (we could drop this requirement later though).

    + +

    We'll try to document its design in a later document, though this is + not a priority for now.

    +
+ + +

V.2. When will FreeType 2 support OpenType ?

+
    +

    Well, the engine already reads OpenType/CFF files perfectly. What it + doesn't do is handle "OpenType Layout" tables yet.

    + +

    FreeType 1 comes with a set of extensions that are used to load + and manage OpenType Layout tables. It even has a demonstration program + named "ftstrtto" used to demonstrate its capabilities that + runs pretty smooth.

    + +

    For FreeType 2, we have decided that the layout operations provided + through these tables is better placed in a specific text-layout library, + (many people having asked for such a thing). This new engine would not + depend on FT2 explicitely and will be developed as a separate project. + We plan to announce it in a few weeks with all gory details, + once the definitive 2.0 release of FreeType has been made.

    +
+ +
+ +


+

+Back to FreeType homepage

+ +

+ + diff --git a/subsys/win32k/freetype/docs/glnames.py b/subsys/win32k/freetype/docs/glnames.py new file mode 100644 index 0000000..7b72669 --- /dev/null +++ b/subsys/win32k/freetype/docs/glnames.py @@ -0,0 +1,1706 @@ +#!/usr/bin/env python +# + +# +# FreeType 2 glyph name builder +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +"""\ + +usage: %s + + This very simple python script is used to generate the glyph names + tables defined in the PSNames module. + + Its single argument is the name of the header file to be created. +""" + + +import sys, string + + +# This table is used to name the glyph according to the Macintosh +# specification. It is used by the TrueType Postscript names table +# +mac_standard_names = \ +[ + # 0 + ".notdef", ".null", "CR", "space", "exclam", + "quotedbl", "numbersign", "dollar", "percent", "ampersand", + + # 10 + "quotesingle", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", + + # 20 + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "colon", + + # 30 + "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", + + # 40 + "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", + + # 50 + "O", "P", "Q", "R", "S", + "T", "U", "V", "W", "X", + + # 60 + "Y", "Z", "bracketleft", "backslash", "bracketright", + "asciicircum", "underscore", "grave", "a", "b", + + # 70 + "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", + + # 80 + "m", "n", "o", "p", "q", + "r", "s", "t", "u", "v", + + # 90 + "w", "x", "y", "z", "braceleft", + "bar", "braceright", "asciitilde", "Adieresis", "Aring", + + # 100 + "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", + "aacute", "agrave", "acircumflex", "adieresis", "atilde", + + # 110 + "aring", "ccedilla", "eacute", "egrave", "ecircumflex", + "edieresis", "iacute", "igrave", "icircumflex", "idieresis", + + # 120 + "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", + "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", + + # 130 + "dagger", "degree", "cent", "sterling", "section", + "bullet", "paragraph", "germandbls", "registered", "copyright", + + # 140 + "trademark", "acute", "dieresis", "notequal", "AE", + "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", + + # 150 + "yen", "mu", "partialdiff", "summation", "product", + "pi", "integral", "ordfeminine", "ordmasculine", "Omega", + + # 160 + "ae", "oslash", "questiondown", "exclamdown", "logicalnot", + "radical", "florin", "approxequal", "Delta", "guillemotleft", + + # 170 + "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", + "Otilde", "OE", "oe", "endash", "emdash", + + # 180 + "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", + "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", + + # 190 + "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", + "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", + "Acircumflex", + + # 200 + "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", + "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", + + # 210 + "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", + "dotlessi", "circumflex", "tilde", "macron", "breve", + + # 220 + "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", + "caron", "Lslash", "lslash", "Scaron", "scaron", + + # 230 + "Zcaron", "zcaron", "brokenbar", "Eth", "eth", + "Yacute", "yacute", "Thorn", "thorn", "minus", + + # 240 + "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", + "onequarter", "threequarters", "franc", "Gbreve", "gbreve", + + # 250 + "Idot", "Scedilla", "scedilla", "Cacute", "cacute", + "Ccaron", "ccaron", "dmacron" +] + + +t1_standard_strings = \ +[ + # 0 + ".notdef", "space", "exclam", "quotedbl", "numbersign", + "dollar", "percent", "ampersand", "quoteright", "parenleft", + + # 10 + "parenright", "asterisk", "plus", "comma", "hyphen", + "period", "slash", "zero", "one", "two", + + # 20 + "three", "four", "five", "six", "seven", + "eight", "nine", "colon", "semicolon", "less", + + # 30 + "equal", "greater", "question", "at", "A", + "B", "C", "D", "E", "F", + + # 40 + "G", "H", "I", "J", "K", + "L", "M", "N", "O", "P", + + # 50 + "Q", "R", "S", "T", "U", + "V", "W", "X", "Y", "Z", + + # 60 + "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", + "quoteleft", "a", "b", "c", "d", + + # 70 + "e", "f", "g", "h", "i", + "j", "k", "l", "m", "n", + + # 80 + "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", + + # 90 + "y", "z", "braceleft", "bar", "braceright", + "asciitilde", "exclamdown", "cent", "sterling", "fraction", + + # 100 + "yen", "florin", "section", "currency", "quotesingle", + "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", + + # 110 + "fl", "endash", "dagger", "daggerdbl", "periodcenter", + "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", + + # 120 + "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", + "acute", "circumflex", "tilde", "macron", "breve", + + # 130 + "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", + "ogonek", "caron", "emdash", "AE", "ordfeminine", + + # 140 + "Lslash", "Oslash", "OE", "ordmasculine", "ae", + "dotlessi", "Islash", "oslash", "oe", "germandbls", + + # 150 + "onesuperior", "logicalnot", "mu", "trademark", "Eth", + "onehalf", "plusminus", "Thorn", "onequarter", "divide", + + # 160 + "brokenbar", "degree", "thorn", "threequarters", "twosuperior", + "registered", "minus", "eth", "multiply", "threesuperior", + + # 170 + "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", + "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", + + # 180 + "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", + "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", + + # 190 + "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", + "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", + + # 200 + "aacute", "acircumflex", "adieresis", "agrave", "aring", + "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", + + # 210 + "egrave", "iacute", "icircumflex", "idieresis", "igrave", + "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", + + # 220 + "otilde", "scaron", "uacute", "ucircumflex", "udieresis", + "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", + + # 230 + "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", + "Acutesmall", + "parenleftsuperior", "parenrightsuperior", "twodotenleader", + "onedotenleader", "zerooldstyle", + + # 240 + "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", + "commasuperior", + + # 250 + "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", + "bsuperior", + "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", + + # 260 + "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", + "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", + + # 270 + "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", + "Asmall", + "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", + + # 280 + "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", + "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", + + # 290 + "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", + "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", + + # 300 + "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", + "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", + "Dieresissmall", + + # 310 + "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", + "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", + "questiondownsmall", + + # 320 + "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", + "twothirds", "zerosuperior", "foursuperior", "fivesuperior", + "sixsuperior", + + # 330 + "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", + "oneinferior", + "twoinferior", "threeinferior", "fourinferior", "fiveinferior", + "sixinferior", + + # 340 + "seveninferior", "eightinferior", "nineinferior", "centinferior", + "dollarinferior", + "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", + "Acircumflexsmall", + + # 350 + "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", + "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", + "Igravesmall", + + # 360 + "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", + "Ntildesmall", + "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", + "Odieresissmall", + + # 370 + "OEsmall", "Oslashsmall", "Ugravesmall", "Uacautesmall", + "Ucircumflexsmall", + "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", + "001.000", + + # 380 + "001.001", "001.002", "001.003", "Black", "Bold", + "Book", "Light", "Medium", "Regular", "Roman", + + # 390 + "Semibold" +] + + +t1_standard_encoding = \ +[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 0, 111, 112, 113, + 114, 0, 115, 116, 117, 118, 119, 120, 121, 122, + 0, 123, 0, 124, 125, 126, 127, 128, 129, 130, + + 131, 0, 132, 133, 0, 134, 135, 136, 137, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 138, 0, 139, 0, 0, + 0, 0, 140, 141, 142, 143, 0, 0, 0, 0, + 0, 144, 0, 0, 0, 145, 0, 0, 146, 147, + + 148, 149, 0, 0, 0, 0 +] + + +t1_expert_encoding = \ +[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 229, 230, 0, 231, 232, 233, 234, + 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, + + 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, + 249, 250, 251, 252, 0, 253, 254, 255, 256, 257, + 0, 0, 0, 258, 0, 0, 259, 260, 261, 262, + 0, 0, 263, 264, 265, 0, 266, 109, 110, 267, + 268, 269, 0, 270, 271, 272, 273, 274, 275, 276, + + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 304, 305, 306, 0, 0, 307, 308, 309, 310, + 311, 0, 312, 0, 0, 312, 0, 0, 314, 315, + 0, 0, 316, 317, 318, 0, 0, 0, 158, 155, + 163, 319, 320, 321, 322, 323, 324, 325, 0, 0, + + 326, 150, 164, 169, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + + 373, 374, 375, 376, 377, 378 +] + + +# This data has been taken literally from the file `glyphlist.txt', +# version 1.2, 22 Oct 1998. It is available from +# +# http://partners.adobe.com/asn/developer/typeforum/unicodegn.html +# +adobe_glyph_list = """\ +0041;A;LATIN CAPITAL LETTER A +00C6;AE;LATIN CAPITAL LETTER AE +01FC;AEacute;LATIN CAPITAL LETTER AE WITH ACUTE +F7E6;AEsmall;LATIN SMALL CAPITAL LETTER AE +00C1;Aacute;LATIN CAPITAL LETTER A WITH ACUTE +F7E1;Aacutesmall;LATIN SMALL CAPITAL LETTER A WITH ACUTE +0102;Abreve;LATIN CAPITAL LETTER A WITH BREVE +00C2;Acircumflex;LATIN CAPITAL LETTER A WITH CIRCUMFLEX +F7E2;Acircumflexsmall;LATIN SMALL CAPITAL LETTER A WITH CIRCUMFLEX +F6C9;Acute;CAPITAL ACUTE ACCENT +F7B4;Acutesmall;SMALL CAPITAL ACUTE ACCENT +00C4;Adieresis;LATIN CAPITAL LETTER A WITH DIAERESIS +F7E4;Adieresissmall;LATIN SMALL CAPITAL LETTER A WITH DIAERESIS +00C0;Agrave;LATIN CAPITAL LETTER A WITH GRAVE +F7E0;Agravesmall;LATIN SMALL CAPITAL LETTER A WITH GRAVE +0391;Alpha;GREEK CAPITAL LETTER ALPHA +0386;Alphatonos;GREEK CAPITAL LETTER ALPHA WITH TONOS +0100;Amacron;LATIN CAPITAL LETTER A WITH MACRON +0104;Aogonek;LATIN CAPITAL LETTER A WITH OGONEK +00C5;Aring;LATIN CAPITAL LETTER A WITH RING ABOVE +01FA;Aringacute;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE +F7E5;Aringsmall;LATIN SMALL CAPITAL LETTER A WITH RING ABOVE +F761;Asmall;LATIN SMALL CAPITAL LETTER A +00C3;Atilde;LATIN CAPITAL LETTER A WITH TILDE +F7E3;Atildesmall;LATIN SMALL CAPITAL LETTER A WITH TILDE +0042;B;LATIN CAPITAL LETTER B +0392;Beta;GREEK CAPITAL LETTER BETA +F6F4;Brevesmall;SMALL CAPITAL BREVE +F762;Bsmall;LATIN SMALL CAPITAL LETTER B +0043;C;LATIN CAPITAL LETTER C +0106;Cacute;LATIN CAPITAL LETTER C WITH ACUTE +F6CA;Caron;CAPITAL CARON +F6F5;Caronsmall;SMALL CAPITAL CARON +010C;Ccaron;LATIN CAPITAL LETTER C WITH CARON +00C7;Ccedilla;LATIN CAPITAL LETTER C WITH CEDILLA +F7E7;Ccedillasmall;LATIN SMALL CAPITAL LETTER C WITH CEDILLA +0108;Ccircumflex;LATIN CAPITAL LETTER C WITH CIRCUMFLEX +010A;Cdotaccent;LATIN CAPITAL LETTER C WITH DOT ABOVE +F7B8;Cedillasmall;SMALL CAPITAL CEDILLA +03A7;Chi;GREEK CAPITAL LETTER CHI +F6F6;Circumflexsmall;SMALL CAPITAL MODIFIER LETTER CIRCUMFLEX ACCENT +F763;Csmall;LATIN SMALL CAPITAL LETTER C +0044;D;LATIN CAPITAL LETTER D +010E;Dcaron;LATIN CAPITAL LETTER D WITH CARON +0110;Dcroat;LATIN CAPITAL LETTER D WITH STROKE +2206;Delta;INCREMENT +0394;Delta;GREEK CAPITAL LETTER DELTA;Duplicate +F6CB;Dieresis;CAPITAL DIAERESIS +F6CC;DieresisAcute;CAPITAL DIAERESIS ACUTE ACCENT +F6CD;DieresisGrave;CAPITAL DIAERESIS GRAVE ACCENT +F7A8;Dieresissmall;SMALL CAPITAL DIAERESIS +F6F7;Dotaccentsmall;SMALL CAPITAL DOT ABOVE +F764;Dsmall;LATIN SMALL CAPITAL LETTER D +0045;E;LATIN CAPITAL LETTER E +00C9;Eacute;LATIN CAPITAL LETTER E WITH ACUTE +F7E9;Eacutesmall;LATIN SMALL CAPITAL LETTER E WITH ACUTE +0114;Ebreve;LATIN CAPITAL LETTER E WITH BREVE +011A;Ecaron;LATIN CAPITAL LETTER E WITH CARON +00CA;Ecircumflex;LATIN CAPITAL LETTER E WITH CIRCUMFLEX +F7EA;Ecircumflexsmall;LATIN SMALL CAPITAL LETTER E WITH CIRCUMFLEX +00CB;Edieresis;LATIN CAPITAL LETTER E WITH DIAERESIS +F7EB;Edieresissmall;LATIN SMALL CAPITAL LETTER E WITH DIAERESIS +0116;Edotaccent;LATIN CAPITAL LETTER E WITH DOT ABOVE +00C8;Egrave;LATIN CAPITAL LETTER E WITH GRAVE +F7E8;Egravesmall;LATIN SMALL CAPITAL LETTER E WITH GRAVE +0112;Emacron;LATIN CAPITAL LETTER E WITH MACRON +014A;Eng;LATIN CAPITAL LETTER ENG +0118;Eogonek;LATIN CAPITAL LETTER E WITH OGONEK +0395;Epsilon;GREEK CAPITAL LETTER EPSILON +0388;Epsilontonos;GREEK CAPITAL LETTER EPSILON WITH TONOS +F765;Esmall;LATIN SMALL CAPITAL LETTER E +0397;Eta;GREEK CAPITAL LETTER ETA +0389;Etatonos;GREEK CAPITAL LETTER ETA WITH TONOS +00D0;Eth;LATIN CAPITAL LETTER ETH +F7F0;Ethsmall;LATIN SMALL CAPITAL LETTER ETH +20AC;Euro;EURO SIGN +0046;F;LATIN CAPITAL LETTER F +F766;Fsmall;LATIN SMALL CAPITAL LETTER F +0047;G;LATIN CAPITAL LETTER G +0393;Gamma;GREEK CAPITAL LETTER GAMMA +011E;Gbreve;LATIN CAPITAL LETTER G WITH BREVE +01E6;Gcaron;LATIN CAPITAL LETTER G WITH CARON +011C;Gcircumflex;LATIN CAPITAL LETTER G WITH CIRCUMFLEX +0122;Gcommaaccent;LATIN CAPITAL LETTER G WITH CEDILLA +0120;Gdotaccent;LATIN CAPITAL LETTER G WITH DOT ABOVE +F6CE;Grave;CAPITAL GRAVE ACCENT +F760;Gravesmall;SMALL CAPITAL GRAVE ACCENT +F767;Gsmall;LATIN SMALL CAPITAL LETTER G +0048;H;LATIN CAPITAL LETTER H +25CF;H18533;BLACK CIRCLE +25AA;H18543;BLACK SMALL SQUARE +25AB;H18551;WHITE SMALL SQUARE +25A1;H22073;WHITE SQUARE +0126;Hbar;LATIN CAPITAL LETTER H WITH STROKE +0124;Hcircumflex;LATIN CAPITAL LETTER H WITH CIRCUMFLEX +F768;Hsmall;LATIN SMALL CAPITAL LETTER H +F6CF;Hungarumlaut;CAPITAL DOUBLE ACUTE ACCENT +F6F8;Hungarumlautsmall;SMALL CAPITAL DOUBLE ACUTE ACCENT +0049;I;LATIN CAPITAL LETTER I +0132;IJ;LATIN CAPITAL LIGATURE IJ +00CD;Iacute;LATIN CAPITAL LETTER I WITH ACUTE +F7ED;Iacutesmall;LATIN SMALL CAPITAL LETTER I WITH ACUTE +012C;Ibreve;LATIN CAPITAL LETTER I WITH BREVE +00CE;Icircumflex;LATIN CAPITAL LETTER I WITH CIRCUMFLEX +F7EE;Icircumflexsmall;LATIN SMALL CAPITAL LETTER I WITH CIRCUMFLEX +00CF;Idieresis;LATIN CAPITAL LETTER I WITH DIAERESIS +F7EF;Idieresissmall;LATIN SMALL CAPITAL LETTER I WITH DIAERESIS +0130;Idotaccent;LATIN CAPITAL LETTER I WITH DOT ABOVE +2111;Ifraktur;BLACK-LETTER CAPITAL I +00CC;Igrave;LATIN CAPITAL LETTER I WITH GRAVE +F7EC;Igravesmall;LATIN SMALL CAPITAL LETTER I WITH GRAVE +012A;Imacron;LATIN CAPITAL LETTER I WITH MACRON +012E;Iogonek;LATIN CAPITAL LETTER I WITH OGONEK +0399;Iota;GREEK CAPITAL LETTER IOTA +03AA;Iotadieresis;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA +038A;Iotatonos;GREEK CAPITAL LETTER IOTA WITH TONOS +F769;Ismall;LATIN SMALL CAPITAL LETTER I +0128;Itilde;LATIN CAPITAL LETTER I WITH TILDE +004A;J;LATIN CAPITAL LETTER J +0134;Jcircumflex;LATIN CAPITAL LETTER J WITH CIRCUMFLEX +F76A;Jsmall;LATIN SMALL CAPITAL LETTER J +004B;K;LATIN CAPITAL LETTER K +039A;Kappa;GREEK CAPITAL LETTER KAPPA +0136;Kcommaaccent;LATIN CAPITAL LETTER K WITH CEDILLA +F76B;Ksmall;LATIN SMALL CAPITAL LETTER K +004C;L;LATIN CAPITAL LETTER L +F6BF;LL;LATIN CAPITAL LETTER LL +0139;Lacute;LATIN CAPITAL LETTER L WITH ACUTE +039B;Lambda;GREEK CAPITAL LETTER LAMDA +013D;Lcaron;LATIN CAPITAL LETTER L WITH CARON +013B;Lcommaaccent;LATIN CAPITAL LETTER L WITH CEDILLA +013F;Ldot;LATIN CAPITAL LETTER L WITH MIDDLE DOT +0141;Lslash;LATIN CAPITAL LETTER L WITH STROKE +F6F9;Lslashsmall;LATIN SMALL CAPITAL LETTER L WITH STROKE +F76C;Lsmall;LATIN SMALL CAPITAL LETTER L +004D;M;LATIN CAPITAL LETTER M +F6D0;Macron;CAPITAL MACRON +F7AF;Macronsmall;SMALL CAPITAL MACRON +F76D;Msmall;LATIN SMALL CAPITAL LETTER M +039C;Mu;GREEK CAPITAL LETTER MU +004E;N;LATIN CAPITAL LETTER N +0143;Nacute;LATIN CAPITAL LETTER N WITH ACUTE +0147;Ncaron;LATIN CAPITAL LETTER N WITH CARON +0145;Ncommaaccent;LATIN CAPITAL LETTER N WITH CEDILLA +F76E;Nsmall;LATIN SMALL CAPITAL LETTER N +00D1;Ntilde;LATIN CAPITAL LETTER N WITH TILDE +F7F1;Ntildesmall;LATIN SMALL CAPITAL LETTER N WITH TILDE +039D;Nu;GREEK CAPITAL LETTER NU +004F;O;LATIN CAPITAL LETTER O +0152;OE;LATIN CAPITAL LIGATURE OE +F6FA;OEsmall;LATIN SMALL CAPITAL LIGATURE OE +00D3;Oacute;LATIN CAPITAL LETTER O WITH ACUTE +F7F3;Oacutesmall;LATIN SMALL CAPITAL LETTER O WITH ACUTE +014E;Obreve;LATIN CAPITAL LETTER O WITH BREVE +00D4;Ocircumflex;LATIN CAPITAL LETTER O WITH CIRCUMFLEX +F7F4;Ocircumflexsmall;LATIN SMALL CAPITAL LETTER O WITH CIRCUMFLEX +00D6;Odieresis;LATIN CAPITAL LETTER O WITH DIAERESIS +F7F6;Odieresissmall;LATIN SMALL CAPITAL LETTER O WITH DIAERESIS +F6FB;Ogoneksmall;SMALL CAPITAL OGONEK +00D2;Ograve;LATIN CAPITAL LETTER O WITH GRAVE +F7F2;Ogravesmall;LATIN SMALL CAPITAL LETTER O WITH GRAVE +01A0;Ohorn;LATIN CAPITAL LETTER O WITH HORN +0150;Ohungarumlaut;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE +014C;Omacron;LATIN CAPITAL LETTER O WITH MACRON +2126;Omega;OHM SIGN +03A9;Omega;GREEK CAPITAL LETTER OMEGA;Duplicate +038F;Omegatonos;GREEK CAPITAL LETTER OMEGA WITH TONOS +039F;Omicron;GREEK CAPITAL LETTER OMICRON +038C;Omicrontonos;GREEK CAPITAL LETTER OMICRON WITH TONOS +00D8;Oslash;LATIN CAPITAL LETTER O WITH STROKE +01FE;Oslashacute;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE +F7F8;Oslashsmall;LATIN SMALL CAPITAL LETTER O WITH STROKE +F76F;Osmall;LATIN SMALL CAPITAL LETTER O +00D5;Otilde;LATIN CAPITAL LETTER O WITH TILDE +F7F5;Otildesmall;LATIN SMALL CAPITAL LETTER O WITH TILDE +0050;P;LATIN CAPITAL LETTER P +03A6;Phi;GREEK CAPITAL LETTER PHI +03A0;Pi;GREEK CAPITAL LETTER PI +03A8;Psi;GREEK CAPITAL LETTER PSI +F770;Psmall;LATIN SMALL CAPITAL LETTER P +0051;Q;LATIN CAPITAL LETTER Q +F771;Qsmall;LATIN SMALL CAPITAL LETTER Q +0052;R;LATIN CAPITAL LETTER R +0154;Racute;LATIN CAPITAL LETTER R WITH ACUTE +0158;Rcaron;LATIN CAPITAL LETTER R WITH CARON +0156;Rcommaaccent;LATIN CAPITAL LETTER R WITH CEDILLA +211C;Rfraktur;BLACK-LETTER CAPITAL R +03A1;Rho;GREEK CAPITAL LETTER RHO +F6FC;Ringsmall;SMALL CAPITAL RING ABOVE +F772;Rsmall;LATIN SMALL CAPITAL LETTER R +0053;S;LATIN CAPITAL LETTER S +250C;SF010000;BOX DRAWINGS LIGHT DOWN AND RIGHT +2514;SF020000;BOX DRAWINGS LIGHT UP AND RIGHT +2510;SF030000;BOX DRAWINGS LIGHT DOWN AND LEFT +2518;SF040000;BOX DRAWINGS LIGHT UP AND LEFT +253C;SF050000;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL +252C;SF060000;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL +2534;SF070000;BOX DRAWINGS LIGHT UP AND HORIZONTAL +251C;SF080000;BOX DRAWINGS LIGHT VERTICAL AND RIGHT +2524;SF090000;BOX DRAWINGS LIGHT VERTICAL AND LEFT +2500;SF100000;BOX DRAWINGS LIGHT HORIZONTAL +2502;SF110000;BOX DRAWINGS LIGHT VERTICAL +2561;SF190000;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE +2562;SF200000;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE +2556;SF210000;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE +2555;SF220000;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE +2563;SF230000;BOX DRAWINGS DOUBLE VERTICAL AND LEFT +2551;SF240000;BOX DRAWINGS DOUBLE VERTICAL +2557;SF250000;BOX DRAWINGS DOUBLE DOWN AND LEFT +255D;SF260000;BOX DRAWINGS DOUBLE UP AND LEFT +255C;SF270000;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE +255B;SF280000;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE +255E;SF360000;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE +255F;SF370000;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE +255A;SF380000;BOX DRAWINGS DOUBLE UP AND RIGHT +2554;SF390000;BOX DRAWINGS DOUBLE DOWN AND RIGHT +2569;SF400000;BOX DRAWINGS DOUBLE UP AND HORIZONTAL +2566;SF410000;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL +2560;SF420000;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT +2550;SF430000;BOX DRAWINGS DOUBLE HORIZONTAL +256C;SF440000;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL +2567;SF450000;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE +2568;SF460000;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE +2564;SF470000;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE +2565;SF480000;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE +2559;SF490000;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE +2558;SF500000;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE +2552;SF510000;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE +2553;SF520000;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE +256B;SF530000;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE +256A;SF540000;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE +015A;Sacute;LATIN CAPITAL LETTER S WITH ACUTE +0160;Scaron;LATIN CAPITAL LETTER S WITH CARON +F6FD;Scaronsmall;LATIN SMALL CAPITAL LETTER S WITH CARON +015E;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA +F6C1;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA;Duplicate +015C;Scircumflex;LATIN CAPITAL LETTER S WITH CIRCUMFLEX +0218;Scommaaccent;LATIN CAPITAL LETTER S WITH COMMA BELOW +03A3;Sigma;GREEK CAPITAL LETTER SIGMA +F773;Ssmall;LATIN SMALL CAPITAL LETTER S +0054;T;LATIN CAPITAL LETTER T +03A4;Tau;GREEK CAPITAL LETTER TAU +0166;Tbar;LATIN CAPITAL LETTER T WITH STROKE +0164;Tcaron;LATIN CAPITAL LETTER T WITH CARON +0162;Tcommaaccent;LATIN CAPITAL LETTER T WITH CEDILLA +021A;Tcommaaccent;LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate +0398;Theta;GREEK CAPITAL LETTER THETA +00DE;Thorn;LATIN CAPITAL LETTER THORN +F7FE;Thornsmall;LATIN SMALL CAPITAL LETTER THORN +F6FE;Tildesmall;SMALL CAPITAL SMALL TILDE +F774;Tsmall;LATIN SMALL CAPITAL LETTER T +0055;U;LATIN CAPITAL LETTER U +00DA;Uacute;LATIN CAPITAL LETTER U WITH ACUTE +F7FA;Uacutesmall;LATIN SMALL CAPITAL LETTER U WITH ACUTE +016C;Ubreve;LATIN CAPITAL LETTER U WITH BREVE +00DB;Ucircumflex;LATIN CAPITAL LETTER U WITH CIRCUMFLEX +F7FB;Ucircumflexsmall;LATIN SMALL CAPITAL LETTER U WITH CIRCUMFLEX +00DC;Udieresis;LATIN CAPITAL LETTER U WITH DIAERESIS +F7FC;Udieresissmall;LATIN SMALL CAPITAL LETTER U WITH DIAERESIS +00D9;Ugrave;LATIN CAPITAL LETTER U WITH GRAVE +F7F9;Ugravesmall;LATIN SMALL CAPITAL LETTER U WITH GRAVE +01AF;Uhorn;LATIN CAPITAL LETTER U WITH HORN +0170;Uhungarumlaut;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE +016A;Umacron;LATIN CAPITAL LETTER U WITH MACRON +0172;Uogonek;LATIN CAPITAL LETTER U WITH OGONEK +03A5;Upsilon;GREEK CAPITAL LETTER UPSILON +03D2;Upsilon1;GREEK UPSILON WITH HOOK SYMBOL +03AB;Upsilondieresis;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA +038E;Upsilontonos;GREEK CAPITAL LETTER UPSILON WITH TONOS +016E;Uring;LATIN CAPITAL LETTER U WITH RING ABOVE +F775;Usmall;LATIN SMALL CAPITAL LETTER U +0168;Utilde;LATIN CAPITAL LETTER U WITH TILDE +0056;V;LATIN CAPITAL LETTER V +F776;Vsmall;LATIN SMALL CAPITAL LETTER V +0057;W;LATIN CAPITAL LETTER W +1E82;Wacute;LATIN CAPITAL LETTER W WITH ACUTE +0174;Wcircumflex;LATIN CAPITAL LETTER W WITH CIRCUMFLEX +1E84;Wdieresis;LATIN CAPITAL LETTER W WITH DIAERESIS +1E80;Wgrave;LATIN CAPITAL LETTER W WITH GRAVE +F777;Wsmall;LATIN SMALL CAPITAL LETTER W +0058;X;LATIN CAPITAL LETTER X +039E;Xi;GREEK CAPITAL LETTER XI +F778;Xsmall;LATIN SMALL CAPITAL LETTER X +0059;Y;LATIN CAPITAL LETTER Y +00DD;Yacute;LATIN CAPITAL LETTER Y WITH ACUTE +F7FD;Yacutesmall;LATIN SMALL CAPITAL LETTER Y WITH ACUTE +0176;Ycircumflex;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX +0178;Ydieresis;LATIN CAPITAL LETTER Y WITH DIAERESIS +F7FF;Ydieresissmall;LATIN SMALL CAPITAL LETTER Y WITH DIAERESIS +1EF2;Ygrave;LATIN CAPITAL LETTER Y WITH GRAVE +F779;Ysmall;LATIN SMALL CAPITAL LETTER Y +005A;Z;LATIN CAPITAL LETTER Z +0179;Zacute;LATIN CAPITAL LETTER Z WITH ACUTE +017D;Zcaron;LATIN CAPITAL LETTER Z WITH CARON +F6FF;Zcaronsmall;LATIN SMALL CAPITAL LETTER Z WITH CARON +017B;Zdotaccent;LATIN CAPITAL LETTER Z WITH DOT ABOVE +0396;Zeta;GREEK CAPITAL LETTER ZETA +F77A;Zsmall;LATIN SMALL CAPITAL LETTER Z +0061;a;LATIN SMALL LETTER A +00E1;aacute;LATIN SMALL LETTER A WITH ACUTE +0103;abreve;LATIN SMALL LETTER A WITH BREVE +00E2;acircumflex;LATIN SMALL LETTER A WITH CIRCUMFLEX +00B4;acute;ACUTE ACCENT +0301;acutecomb;COMBINING ACUTE ACCENT +00E4;adieresis;LATIN SMALL LETTER A WITH DIAERESIS +00E6;ae;LATIN SMALL LETTER AE +01FD;aeacute;LATIN SMALL LETTER AE WITH ACUTE +2015;afii00208;HORIZONTAL BAR +0410;afii10017;CYRILLIC CAPITAL LETTER A +0411;afii10018;CYRILLIC CAPITAL LETTER BE +0412;afii10019;CYRILLIC CAPITAL LETTER VE +0413;afii10020;CYRILLIC CAPITAL LETTER GHE +0414;afii10021;CYRILLIC CAPITAL LETTER DE +0415;afii10022;CYRILLIC CAPITAL LETTER IE +0401;afii10023;CYRILLIC CAPITAL LETTER IO +0416;afii10024;CYRILLIC CAPITAL LETTER ZHE +0417;afii10025;CYRILLIC CAPITAL LETTER ZE +0418;afii10026;CYRILLIC CAPITAL LETTER I +0419;afii10027;CYRILLIC CAPITAL LETTER SHORT I +041A;afii10028;CYRILLIC CAPITAL LETTER KA +041B;afii10029;CYRILLIC CAPITAL LETTER EL +041C;afii10030;CYRILLIC CAPITAL LETTER EM +041D;afii10031;CYRILLIC CAPITAL LETTER EN +041E;afii10032;CYRILLIC CAPITAL LETTER O +041F;afii10033;CYRILLIC CAPITAL LETTER PE +0420;afii10034;CYRILLIC CAPITAL LETTER ER +0421;afii10035;CYRILLIC CAPITAL LETTER ES +0422;afii10036;CYRILLIC CAPITAL LETTER TE +0423;afii10037;CYRILLIC CAPITAL LETTER U +0424;afii10038;CYRILLIC CAPITAL LETTER EF +0425;afii10039;CYRILLIC CAPITAL LETTER HA +0426;afii10040;CYRILLIC CAPITAL LETTER TSE +0427;afii10041;CYRILLIC CAPITAL LETTER CHE +0428;afii10042;CYRILLIC CAPITAL LETTER SHA +0429;afii10043;CYRILLIC CAPITAL LETTER SHCHA +042A;afii10044;CYRILLIC CAPITAL LETTER HARD SIGN +042B;afii10045;CYRILLIC CAPITAL LETTER YERU +042C;afii10046;CYRILLIC CAPITAL LETTER SOFT SIGN +042D;afii10047;CYRILLIC CAPITAL LETTER E +042E;afii10048;CYRILLIC CAPITAL LETTER YU +042F;afii10049;CYRILLIC CAPITAL LETTER YA +0490;afii10050;CYRILLIC CAPITAL LETTER GHE WITH UPTURN +0402;afii10051;CYRILLIC CAPITAL LETTER DJE +0403;afii10052;CYRILLIC CAPITAL LETTER GJE +0404;afii10053;CYRILLIC CAPITAL LETTER UKRAINIAN IE +0405;afii10054;CYRILLIC CAPITAL LETTER DZE +0406;afii10055;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I +0407;afii10056;CYRILLIC CAPITAL LETTER YI +0408;afii10057;CYRILLIC CAPITAL LETTER JE +0409;afii10058;CYRILLIC CAPITAL LETTER LJE +040A;afii10059;CYRILLIC CAPITAL LETTER NJE +040B;afii10060;CYRILLIC CAPITAL LETTER TSHE +040C;afii10061;CYRILLIC CAPITAL LETTER KJE +040E;afii10062;CYRILLIC CAPITAL LETTER SHORT U +F6C4;afii10063;CYRILLIC SMALL LETTER GHE VARIANT +F6C5;afii10064;CYRILLIC SMALL LETTER BE VARIANT +0430;afii10065;CYRILLIC SMALL LETTER A +0431;afii10066;CYRILLIC SMALL LETTER BE +0432;afii10067;CYRILLIC SMALL LETTER VE +0433;afii10068;CYRILLIC SMALL LETTER GHE +0434;afii10069;CYRILLIC SMALL LETTER DE +0435;afii10070;CYRILLIC SMALL LETTER IE +0451;afii10071;CYRILLIC SMALL LETTER IO +0436;afii10072;CYRILLIC SMALL LETTER ZHE +0437;afii10073;CYRILLIC SMALL LETTER ZE +0438;afii10074;CYRILLIC SMALL LETTER I +0439;afii10075;CYRILLIC SMALL LETTER SHORT I +043A;afii10076;CYRILLIC SMALL LETTER KA +043B;afii10077;CYRILLIC SMALL LETTER EL +043C;afii10078;CYRILLIC SMALL LETTER EM +043D;afii10079;CYRILLIC SMALL LETTER EN +043E;afii10080;CYRILLIC SMALL LETTER O +043F;afii10081;CYRILLIC SMALL LETTER PE +0440;afii10082;CYRILLIC SMALL LETTER ER +0441;afii10083;CYRILLIC SMALL LETTER ES +0442;afii10084;CYRILLIC SMALL LETTER TE +0443;afii10085;CYRILLIC SMALL LETTER U +0444;afii10086;CYRILLIC SMALL LETTER EF +0445;afii10087;CYRILLIC SMALL LETTER HA +0446;afii10088;CYRILLIC SMALL LETTER TSE +0447;afii10089;CYRILLIC SMALL LETTER CHE +0448;afii10090;CYRILLIC SMALL LETTER SHA +0449;afii10091;CYRILLIC SMALL LETTER SHCHA +044A;afii10092;CYRILLIC SMALL LETTER HARD SIGN +044B;afii10093;CYRILLIC SMALL LETTER YERU +044C;afii10094;CYRILLIC SMALL LETTER SOFT SIGN +044D;afii10095;CYRILLIC SMALL LETTER E +044E;afii10096;CYRILLIC SMALL LETTER YU +044F;afii10097;CYRILLIC SMALL LETTER YA +0491;afii10098;CYRILLIC SMALL LETTER GHE WITH UPTURN +0452;afii10099;CYRILLIC SMALL LETTER DJE +0453;afii10100;CYRILLIC SMALL LETTER GJE +0454;afii10101;CYRILLIC SMALL LETTER UKRAINIAN IE +0455;afii10102;CYRILLIC SMALL LETTER DZE +0456;afii10103;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I +0457;afii10104;CYRILLIC SMALL LETTER YI +0458;afii10105;CYRILLIC SMALL LETTER JE +0459;afii10106;CYRILLIC SMALL LETTER LJE +045A;afii10107;CYRILLIC SMALL LETTER NJE +045B;afii10108;CYRILLIC SMALL LETTER TSHE +045C;afii10109;CYRILLIC SMALL LETTER KJE +045E;afii10110;CYRILLIC SMALL LETTER SHORT U +040F;afii10145;CYRILLIC CAPITAL LETTER DZHE +0462;afii10146;CYRILLIC CAPITAL LETTER YAT +0472;afii10147;CYRILLIC CAPITAL LETTER FITA +0474;afii10148;CYRILLIC CAPITAL LETTER IZHITSA +F6C6;afii10192;CYRILLIC SMALL LETTER DE VARIANT +045F;afii10193;CYRILLIC SMALL LETTER DZHE +0463;afii10194;CYRILLIC SMALL LETTER YAT +0473;afii10195;CYRILLIC SMALL LETTER FITA +0475;afii10196;CYRILLIC SMALL LETTER IZHITSA +F6C7;afii10831;CYRILLIC SMALL LETTER PE VARIANT +F6C8;afii10832;CYRILLIC SMALL LETTER TE VARIANT +04D9;afii10846;CYRILLIC SMALL LETTER SCHWA +200E;afii299;LEFT-TO-RIGHT MARK +200F;afii300;RIGHT-TO-LEFT MARK +200D;afii301;ZERO WIDTH JOINER +066A;afii57381;ARABIC PERCENT SIGN +060C;afii57388;ARABIC COMMA +0660;afii57392;ARABIC-INDIC DIGIT ZERO +0661;afii57393;ARABIC-INDIC DIGIT ONE +0662;afii57394;ARABIC-INDIC DIGIT TWO +0663;afii57395;ARABIC-INDIC DIGIT THREE +0664;afii57396;ARABIC-INDIC DIGIT FOUR +0665;afii57397;ARABIC-INDIC DIGIT FIVE +0666;afii57398;ARABIC-INDIC DIGIT SIX +0667;afii57399;ARABIC-INDIC DIGIT SEVEN +0668;afii57400;ARABIC-INDIC DIGIT EIGHT +0669;afii57401;ARABIC-INDIC DIGIT NINE +061B;afii57403;ARABIC SEMICOLON +061F;afii57407;ARABIC QUESTION MARK +0621;afii57409;ARABIC LETTER HAMZA +0622;afii57410;ARABIC LETTER ALEF WITH MADDA ABOVE +0623;afii57411;ARABIC LETTER ALEF WITH HAMZA ABOVE +0624;afii57412;ARABIC LETTER WAW WITH HAMZA ABOVE +0625;afii57413;ARABIC LETTER ALEF WITH HAMZA BELOW +0626;afii57414;ARABIC LETTER YEH WITH HAMZA ABOVE +0627;afii57415;ARABIC LETTER ALEF +0628;afii57416;ARABIC LETTER BEH +0629;afii57417;ARABIC LETTER TEH MARBUTA +062A;afii57418;ARABIC LETTER TEH +062B;afii57419;ARABIC LETTER THEH +062C;afii57420;ARABIC LETTER JEEM +062D;afii57421;ARABIC LETTER HAH +062E;afii57422;ARABIC LETTER KHAH +062F;afii57423;ARABIC LETTER DAL +0630;afii57424;ARABIC LETTER THAL +0631;afii57425;ARABIC LETTER REH +0632;afii57426;ARABIC LETTER ZAIN +0633;afii57427;ARABIC LETTER SEEN +0634;afii57428;ARABIC LETTER SHEEN +0635;afii57429;ARABIC LETTER SAD +0636;afii57430;ARABIC LETTER DAD +0637;afii57431;ARABIC LETTER TAH +0638;afii57432;ARABIC LETTER ZAH +0639;afii57433;ARABIC LETTER AIN +063A;afii57434;ARABIC LETTER GHAIN +0640;afii57440;ARABIC TATWEEL +0641;afii57441;ARABIC LETTER FEH +0642;afii57442;ARABIC LETTER QAF +0643;afii57443;ARABIC LETTER KAF +0644;afii57444;ARABIC LETTER LAM +0645;afii57445;ARABIC LETTER MEEM +0646;afii57446;ARABIC LETTER NOON +0648;afii57448;ARABIC LETTER WAW +0649;afii57449;ARABIC LETTER ALEF MAKSURA +064A;afii57450;ARABIC LETTER YEH +064B;afii57451;ARABIC FATHATAN +064C;afii57452;ARABIC DAMMATAN +064D;afii57453;ARABIC KASRATAN +064E;afii57454;ARABIC FATHA +064F;afii57455;ARABIC DAMMA +0650;afii57456;ARABIC KASRA +0651;afii57457;ARABIC SHADDA +0652;afii57458;ARABIC SUKUN +0647;afii57470;ARABIC LETTER HEH +06A4;afii57505;ARABIC LETTER VEH +067E;afii57506;ARABIC LETTER PEH +0686;afii57507;ARABIC LETTER TCHEH +0698;afii57508;ARABIC LETTER JEH +06AF;afii57509;ARABIC LETTER GAF +0679;afii57511;ARABIC LETTER TTEH +0688;afii57512;ARABIC LETTER DDAL +0691;afii57513;ARABIC LETTER RREH +06BA;afii57514;ARABIC LETTER NOON GHUNNA +06D2;afii57519;ARABIC LETTER YEH BARREE +06D5;afii57534;ARABIC LETTER AE +20AA;afii57636;NEW SHEQEL SIGN +05BE;afii57645;HEBREW PUNCTUATION MAQAF +05C3;afii57658;HEBREW PUNCTUATION SOF PASUQ +05D0;afii57664;HEBREW LETTER ALEF +05D1;afii57665;HEBREW LETTER BET +05D2;afii57666;HEBREW LETTER GIMEL +05D3;afii57667;HEBREW LETTER DALET +05D4;afii57668;HEBREW LETTER HE +05D5;afii57669;HEBREW LETTER VAV +05D6;afii57670;HEBREW LETTER ZAYIN +05D7;afii57671;HEBREW LETTER HET +05D8;afii57672;HEBREW LETTER TET +05D9;afii57673;HEBREW LETTER YOD +05DA;afii57674;HEBREW LETTER FINAL KAF +05DB;afii57675;HEBREW LETTER KAF +05DC;afii57676;HEBREW LETTER LAMED +05DD;afii57677;HEBREW LETTER FINAL MEM +05DE;afii57678;HEBREW LETTER MEM +05DF;afii57679;HEBREW LETTER FINAL NUN +05E0;afii57680;HEBREW LETTER NUN +05E1;afii57681;HEBREW LETTER SAMEKH +05E2;afii57682;HEBREW LETTER AYIN +05E3;afii57683;HEBREW LETTER FINAL PE +05E4;afii57684;HEBREW LETTER PE +05E5;afii57685;HEBREW LETTER FINAL TSADI +05E6;afii57686;HEBREW LETTER TSADI +05E7;afii57687;HEBREW LETTER QOF +05E8;afii57688;HEBREW LETTER RESH +05E9;afii57689;HEBREW LETTER SHIN +05EA;afii57690;HEBREW LETTER TAV +FB2A;afii57694;HEBREW LETTER SHIN WITH SHIN DOT +FB2B;afii57695;HEBREW LETTER SHIN WITH SIN DOT +FB4B;afii57700;HEBREW LETTER VAV WITH HOLAM +FB1F;afii57705;HEBREW LIGATURE YIDDISH YOD YOD PATAH +05F0;afii57716;HEBREW LIGATURE YIDDISH DOUBLE VAV +05F1;afii57717;HEBREW LIGATURE YIDDISH VAV YOD +05F2;afii57718;HEBREW LIGATURE YIDDISH DOUBLE YOD +FB35;afii57723;HEBREW LETTER VAV WITH DAGESH +05B4;afii57793;HEBREW POINT HIRIQ +05B5;afii57794;HEBREW POINT TSERE +05B6;afii57795;HEBREW POINT SEGOL +05BB;afii57796;HEBREW POINT QUBUTS +05B8;afii57797;HEBREW POINT QAMATS +05B7;afii57798;HEBREW POINT PATAH +05B0;afii57799;HEBREW POINT SHEVA +05B2;afii57800;HEBREW POINT HATAF PATAH +05B1;afii57801;HEBREW POINT HATAF SEGOL +05B3;afii57802;HEBREW POINT HATAF QAMATS +05C2;afii57803;HEBREW POINT SIN DOT +05C1;afii57804;HEBREW POINT SHIN DOT +05B9;afii57806;HEBREW POINT HOLAM +05BC;afii57807;HEBREW POINT DAGESH OR MAPIQ +05BD;afii57839;HEBREW POINT METEG +05BF;afii57841;HEBREW POINT RAFE +05C0;afii57842;HEBREW PUNCTUATION PASEQ +02BC;afii57929;MODIFIER LETTER APOSTROPHE +2105;afii61248;CARE OF +2113;afii61289;SCRIPT SMALL L +2116;afii61352;NUMERO SIGN +202C;afii61573;POP DIRECTIONAL FORMATTING +202D;afii61574;LEFT-TO-RIGHT OVERRIDE +202E;afii61575;RIGHT-TO-LEFT OVERRIDE +200C;afii61664;ZERO WIDTH NON-JOINER +066D;afii63167;ARABIC FIVE POINTED STAR +02BD;afii64937;MODIFIER LETTER REVERSED COMMA +00E0;agrave;LATIN SMALL LETTER A WITH GRAVE +2135;aleph;ALEF SYMBOL +03B1;alpha;GREEK SMALL LETTER ALPHA +03AC;alphatonos;GREEK SMALL LETTER ALPHA WITH TONOS +0101;amacron;LATIN SMALL LETTER A WITH MACRON +0026;ampersand;AMPERSAND +F726;ampersandsmall;SMALL CAPITAL AMPERSAND +2220;angle;ANGLE +2329;angleleft;LEFT-POINTING ANGLE BRACKET +232A;angleright;RIGHT-POINTING ANGLE BRACKET +0387;anoteleia;GREEK ANO TELEIA +0105;aogonek;LATIN SMALL LETTER A WITH OGONEK +2248;approxequal;ALMOST EQUAL TO +00E5;aring;LATIN SMALL LETTER A WITH RING ABOVE +01FB;aringacute;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE +2194;arrowboth;LEFT RIGHT ARROW +21D4;arrowdblboth;LEFT RIGHT DOUBLE ARROW +21D3;arrowdbldown;DOWNWARDS DOUBLE ARROW +21D0;arrowdblleft;LEFTWARDS DOUBLE ARROW +21D2;arrowdblright;RIGHTWARDS DOUBLE ARROW +21D1;arrowdblup;UPWARDS DOUBLE ARROW +2193;arrowdown;DOWNWARDS ARROW +F8E7;arrowhorizex;HORIZONTAL ARROW EXTENDER +2190;arrowleft;LEFTWARDS ARROW +2192;arrowright;RIGHTWARDS ARROW +2191;arrowup;UPWARDS ARROW +2195;arrowupdn;UP DOWN ARROW +21A8;arrowupdnbse;UP DOWN ARROW WITH BASE +F8E6;arrowvertex;VERTICAL ARROW EXTENDER +005E;asciicircum;CIRCUMFLEX ACCENT +007E;asciitilde;TILDE +002A;asterisk;ASTERISK +2217;asteriskmath;ASTERISK OPERATOR +F6E9;asuperior;SUPERSCRIPT LATIN SMALL LETTER A +0040;at;COMMERCIAL AT +00E3;atilde;LATIN SMALL LETTER A WITH TILDE +0062;b;LATIN SMALL LETTER B +005C;backslash;REVERSE SOLIDUS +007C;bar;VERTICAL LINE +03B2;beta;GREEK SMALL LETTER BETA +2588;block;FULL BLOCK +F8F4;braceex;CURLY BRACKET EXTENDER +007B;braceleft;LEFT CURLY BRACKET +F8F3;braceleftbt;LEFT CURLY BRACKET BOTTOM +F8F2;braceleftmid;LEFT CURLY BRACKET MID +F8F1;bracelefttp;LEFT CURLY BRACKET TOP +007D;braceright;RIGHT CURLY BRACKET +F8FE;bracerightbt;RIGHT CURLY BRACKET BOTTOM +F8FD;bracerightmid;RIGHT CURLY BRACKET MID +F8FC;bracerighttp;RIGHT CURLY BRACKET TOP +005B;bracketleft;LEFT SQUARE BRACKET +F8F0;bracketleftbt;LEFT SQUARE BRACKET BOTTOM +F8EF;bracketleftex;LEFT SQUARE BRACKET EXTENDER +F8EE;bracketlefttp;LEFT SQUARE BRACKET TOP +005D;bracketright;RIGHT SQUARE BRACKET +F8FB;bracketrightbt;RIGHT SQUARE BRACKET BOTTOM +F8FA;bracketrightex;RIGHT SQUARE BRACKET EXTENDER +F8F9;bracketrighttp;RIGHT SQUARE BRACKET TOP +02D8;breve;BREVE +00A6;brokenbar;BROKEN BAR +F6EA;bsuperior;SUPERSCRIPT LATIN SMALL LETTER B +2022;bullet;BULLET +0063;c;LATIN SMALL LETTER C +0107;cacute;LATIN SMALL LETTER C WITH ACUTE +02C7;caron;CARON +21B5;carriagereturn;DOWNWARDS ARROW WITH CORNER LEFTWARDS +010D;ccaron;LATIN SMALL LETTER C WITH CARON +00E7;ccedilla;LATIN SMALL LETTER C WITH CEDILLA +0109;ccircumflex;LATIN SMALL LETTER C WITH CIRCUMFLEX +010B;cdotaccent;LATIN SMALL LETTER C WITH DOT ABOVE +00B8;cedilla;CEDILLA +00A2;cent;CENT SIGN +F6DF;centinferior;SUBSCRIPT CENT SIGN +F7A2;centoldstyle;OLDSTYLE CENT SIGN +F6E0;centsuperior;SUPERSCRIPT CENT SIGN +03C7;chi;GREEK SMALL LETTER CHI +25CB;circle;WHITE CIRCLE +2297;circlemultiply;CIRCLED TIMES +2295;circleplus;CIRCLED PLUS +02C6;circumflex;MODIFIER LETTER CIRCUMFLEX ACCENT +2663;club;BLACK CLUB SUIT +003A;colon;COLON +20A1;colonmonetary;COLON SIGN +002C;comma;COMMA +F6C3;commaaccent;COMMA BELOW +F6E1;commainferior;SUBSCRIPT COMMA +F6E2;commasuperior;SUPERSCRIPT COMMA +2245;congruent;APPROXIMATELY EQUAL TO +00A9;copyright;COPYRIGHT SIGN +F8E9;copyrightsans;COPYRIGHT SIGN SANS SERIF +F6D9;copyrightserif;COPYRIGHT SIGN SERIF +00A4;currency;CURRENCY SIGN +F6D1;cyrBreve;CAPITAL CYRILLIC BREVE +F6D2;cyrFlex;CAPITAL CYRILLIC CIRCUMFLEX +F6D4;cyrbreve;CYRILLIC BREVE +F6D5;cyrflex;CYRILLIC CIRCUMFLEX +0064;d;LATIN SMALL LETTER D +2020;dagger;DAGGER +2021;daggerdbl;DOUBLE DAGGER +F6D3;dblGrave;CAPITAL DOUBLE GRAVE ACCENT +F6D6;dblgrave;DOUBLE GRAVE ACCENT +010F;dcaron;LATIN SMALL LETTER D WITH CARON +0111;dcroat;LATIN SMALL LETTER D WITH STROKE +00B0;degree;DEGREE SIGN +03B4;delta;GREEK SMALL LETTER DELTA +2666;diamond;BLACK DIAMOND SUIT +00A8;dieresis;DIAERESIS +F6D7;dieresisacute;DIAERESIS ACUTE ACCENT +F6D8;dieresisgrave;DIAERESIS GRAVE ACCENT +0385;dieresistonos;GREEK DIALYTIKA TONOS +00F7;divide;DIVISION SIGN +2593;dkshade;DARK SHADE +2584;dnblock;LOWER HALF BLOCK +0024;dollar;DOLLAR SIGN +F6E3;dollarinferior;SUBSCRIPT DOLLAR SIGN +F724;dollaroldstyle;OLDSTYLE DOLLAR SIGN +F6E4;dollarsuperior;SUPERSCRIPT DOLLAR SIGN +20AB;dong;DONG SIGN +02D9;dotaccent;DOT ABOVE +0323;dotbelowcomb;COMBINING DOT BELOW +0131;dotlessi;LATIN SMALL LETTER DOTLESS I +F6BE;dotlessj;LATIN SMALL LETTER DOTLESS J +22C5;dotmath;DOT OPERATOR +F6EB;dsuperior;SUPERSCRIPT LATIN SMALL LETTER D +0065;e;LATIN SMALL LETTER E +00E9;eacute;LATIN SMALL LETTER E WITH ACUTE +0115;ebreve;LATIN SMALL LETTER E WITH BREVE +011B;ecaron;LATIN SMALL LETTER E WITH CARON +00EA;ecircumflex;LATIN SMALL LETTER E WITH CIRCUMFLEX +00EB;edieresis;LATIN SMALL LETTER E WITH DIAERESIS +0117;edotaccent;LATIN SMALL LETTER E WITH DOT ABOVE +00E8;egrave;LATIN SMALL LETTER E WITH GRAVE +0038;eight;DIGIT EIGHT +2088;eightinferior;SUBSCRIPT EIGHT +F738;eightoldstyle;OLDSTYLE DIGIT EIGHT +2078;eightsuperior;SUPERSCRIPT EIGHT +2208;element;ELEMENT OF +2026;ellipsis;HORIZONTAL ELLIPSIS +0113;emacron;LATIN SMALL LETTER E WITH MACRON +2014;emdash;EM DASH +2205;emptyset;EMPTY SET +2013;endash;EN DASH +014B;eng;LATIN SMALL LETTER ENG +0119;eogonek;LATIN SMALL LETTER E WITH OGONEK +03B5;epsilon;GREEK SMALL LETTER EPSILON +03AD;epsilontonos;GREEK SMALL LETTER EPSILON WITH TONOS +003D;equal;EQUALS SIGN +2261;equivalence;IDENTICAL TO +212E;estimated;ESTIMATED SYMBOL +F6EC;esuperior;SUPERSCRIPT LATIN SMALL LETTER E +03B7;eta;GREEK SMALL LETTER ETA +03AE;etatonos;GREEK SMALL LETTER ETA WITH TONOS +00F0;eth;LATIN SMALL LETTER ETH +0021;exclam;EXCLAMATION MARK +203C;exclamdbl;DOUBLE EXCLAMATION MARK +00A1;exclamdown;INVERTED EXCLAMATION MARK +F7A1;exclamdownsmall;SMALL CAPITAL INVERTED EXCLAMATION MARK +F721;exclamsmall;SMALL CAPITAL EXCLAMATION MARK +2203;existential;THERE EXISTS +0066;f;LATIN SMALL LETTER F +2640;female;FEMALE SIGN +FB00;ff;LATIN SMALL LIGATURE FF +FB03;ffi;LATIN SMALL LIGATURE FFI +FB04;ffl;LATIN SMALL LIGATURE FFL +FB01;fi;LATIN SMALL LIGATURE FI +2012;figuredash;FIGURE DASH +25A0;filledbox;BLACK SQUARE +25AC;filledrect;BLACK RECTANGLE +0035;five;DIGIT FIVE +215D;fiveeighths;VULGAR FRACTION FIVE EIGHTHS +2085;fiveinferior;SUBSCRIPT FIVE +F735;fiveoldstyle;OLDSTYLE DIGIT FIVE +2075;fivesuperior;SUPERSCRIPT FIVE +FB02;fl;LATIN SMALL LIGATURE FL +0192;florin;LATIN SMALL LETTER F WITH HOOK +0034;four;DIGIT FOUR +2084;fourinferior;SUBSCRIPT FOUR +F734;fouroldstyle;OLDSTYLE DIGIT FOUR +2074;foursuperior;SUPERSCRIPT FOUR +2044;fraction;FRACTION SLASH +2215;fraction;DIVISION SLASH;Duplicate +20A3;franc;FRENCH FRANC SIGN +0067;g;LATIN SMALL LETTER G +03B3;gamma;GREEK SMALL LETTER GAMMA +011F;gbreve;LATIN SMALL LETTER G WITH BREVE +01E7;gcaron;LATIN SMALL LETTER G WITH CARON +011D;gcircumflex;LATIN SMALL LETTER G WITH CIRCUMFLEX +0123;gcommaaccent;LATIN SMALL LETTER G WITH CEDILLA +0121;gdotaccent;LATIN SMALL LETTER G WITH DOT ABOVE +00DF;germandbls;LATIN SMALL LETTER SHARP S +2207;gradient;NABLA +0060;grave;GRAVE ACCENT +0300;gravecomb;COMBINING GRAVE ACCENT +003E;greater;GREATER-THAN SIGN +2265;greaterequal;GREATER-THAN OR EQUAL TO +00AB;guillemotleft;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK +00BB;guillemotright;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK +2039;guilsinglleft;SINGLE LEFT-POINTING ANGLE QUOTATION MARK +203A;guilsinglright;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK +0068;h;LATIN SMALL LETTER H +0127;hbar;LATIN SMALL LETTER H WITH STROKE +0125;hcircumflex;LATIN SMALL LETTER H WITH CIRCUMFLEX +2665;heart;BLACK HEART SUIT +0309;hookabovecomb;COMBINING HOOK ABOVE +2302;house;HOUSE +02DD;hungarumlaut;DOUBLE ACUTE ACCENT +002D;hyphen;HYPHEN-MINUS +00AD;hyphen;SOFT HYPHEN;Duplicate +F6E5;hypheninferior;SUBSCRIPT HYPHEN-MINUS +F6E6;hyphensuperior;SUPERSCRIPT HYPHEN-MINUS +0069;i;LATIN SMALL LETTER I +00ED;iacute;LATIN SMALL LETTER I WITH ACUTE +012D;ibreve;LATIN SMALL LETTER I WITH BREVE +00EE;icircumflex;LATIN SMALL LETTER I WITH CIRCUMFLEX +00EF;idieresis;LATIN SMALL LETTER I WITH DIAERESIS +00EC;igrave;LATIN SMALL LETTER I WITH GRAVE +0133;ij;LATIN SMALL LIGATURE IJ +012B;imacron;LATIN SMALL LETTER I WITH MACRON +221E;infinity;INFINITY +222B;integral;INTEGRAL +2321;integralbt;BOTTOM HALF INTEGRAL +F8F5;integralex;INTEGRAL EXTENDER +2320;integraltp;TOP HALF INTEGRAL +2229;intersection;INTERSECTION +25D8;invbullet;INVERSE BULLET +25D9;invcircle;INVERSE WHITE CIRCLE +263B;invsmileface;BLACK SMILING FACE +012F;iogonek;LATIN SMALL LETTER I WITH OGONEK +03B9;iota;GREEK SMALL LETTER IOTA +03CA;iotadieresis;GREEK SMALL LETTER IOTA WITH DIALYTIKA +0390;iotadieresistonos;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS +03AF;iotatonos;GREEK SMALL LETTER IOTA WITH TONOS +F6ED;isuperior;SUPERSCRIPT LATIN SMALL LETTER I +0129;itilde;LATIN SMALL LETTER I WITH TILDE +006A;j;LATIN SMALL LETTER J +0135;jcircumflex;LATIN SMALL LETTER J WITH CIRCUMFLEX +006B;k;LATIN SMALL LETTER K +03BA;kappa;GREEK SMALL LETTER KAPPA +0137;kcommaaccent;LATIN SMALL LETTER K WITH CEDILLA +0138;kgreenlandic;LATIN SMALL LETTER KRA +006C;l;LATIN SMALL LETTER L +013A;lacute;LATIN SMALL LETTER L WITH ACUTE +03BB;lambda;GREEK SMALL LETTER LAMDA +013E;lcaron;LATIN SMALL LETTER L WITH CARON +013C;lcommaaccent;LATIN SMALL LETTER L WITH CEDILLA +0140;ldot;LATIN SMALL LETTER L WITH MIDDLE DOT +003C;less;LESS-THAN SIGN +2264;lessequal;LESS-THAN OR EQUAL TO +258C;lfblock;LEFT HALF BLOCK +20A4;lira;LIRA SIGN +F6C0;ll;LATIN SMALL LETTER LL +2227;logicaland;LOGICAL AND +00AC;logicalnot;NOT SIGN +2228;logicalor;LOGICAL OR +017F;longs;LATIN SMALL LETTER LONG S +25CA;lozenge;LOZENGE +0142;lslash;LATIN SMALL LETTER L WITH STROKE +F6EE;lsuperior;SUPERSCRIPT LATIN SMALL LETTER L +2591;ltshade;LIGHT SHADE +006D;m;LATIN SMALL LETTER M +00AF;macron;MACRON +02C9;macron;MODIFIER LETTER MACRON;Duplicate +2642;male;MALE SIGN +2212;minus;MINUS SIGN +2032;minute;PRIME +F6EF;msuperior;SUPERSCRIPT LATIN SMALL LETTER M +00B5;mu;MICRO SIGN +03BC;mu;GREEK SMALL LETTER MU;Duplicate +00D7;multiply;MULTIPLICATION SIGN +266A;musicalnote;EIGHTH NOTE +266B;musicalnotedbl;BEAMED EIGHTH NOTES +006E;n;LATIN SMALL LETTER N +0144;nacute;LATIN SMALL LETTER N WITH ACUTE +0149;napostrophe;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE +0148;ncaron;LATIN SMALL LETTER N WITH CARON +0146;ncommaaccent;LATIN SMALL LETTER N WITH CEDILLA +0039;nine;DIGIT NINE +2089;nineinferior;SUBSCRIPT NINE +F739;nineoldstyle;OLDSTYLE DIGIT NINE +2079;ninesuperior;SUPERSCRIPT NINE +2209;notelement;NOT AN ELEMENT OF +2260;notequal;NOT EQUAL TO +2284;notsubset;NOT A SUBSET OF +207F;nsuperior;SUPERSCRIPT LATIN SMALL LETTER N +00F1;ntilde;LATIN SMALL LETTER N WITH TILDE +03BD;nu;GREEK SMALL LETTER NU +0023;numbersign;NUMBER SIGN +006F;o;LATIN SMALL LETTER O +00F3;oacute;LATIN SMALL LETTER O WITH ACUTE +014F;obreve;LATIN SMALL LETTER O WITH BREVE +00F4;ocircumflex;LATIN SMALL LETTER O WITH CIRCUMFLEX +00F6;odieresis;LATIN SMALL LETTER O WITH DIAERESIS +0153;oe;LATIN SMALL LIGATURE OE +02DB;ogonek;OGONEK +00F2;ograve;LATIN SMALL LETTER O WITH GRAVE +01A1;ohorn;LATIN SMALL LETTER O WITH HORN +0151;ohungarumlaut;LATIN SMALL LETTER O WITH DOUBLE ACUTE +014D;omacron;LATIN SMALL LETTER O WITH MACRON +03C9;omega;GREEK SMALL LETTER OMEGA +03D6;omega1;GREEK PI SYMBOL +03CE;omegatonos;GREEK SMALL LETTER OMEGA WITH TONOS +03BF;omicron;GREEK SMALL LETTER OMICRON +03CC;omicrontonos;GREEK SMALL LETTER OMICRON WITH TONOS +0031;one;DIGIT ONE +2024;onedotenleader;ONE DOT LEADER +215B;oneeighth;VULGAR FRACTION ONE EIGHTH +F6DC;onefitted;PROPORTIONAL DIGIT ONE +00BD;onehalf;VULGAR FRACTION ONE HALF +2081;oneinferior;SUBSCRIPT ONE +F731;oneoldstyle;OLDSTYLE DIGIT ONE +00BC;onequarter;VULGAR FRACTION ONE QUARTER +00B9;onesuperior;SUPERSCRIPT ONE +2153;onethird;VULGAR FRACTION ONE THIRD +25E6;openbullet;WHITE BULLET +00AA;ordfeminine;FEMININE ORDINAL INDICATOR +00BA;ordmasculine;MASCULINE ORDINAL INDICATOR +221F;orthogonal;RIGHT ANGLE +00F8;oslash;LATIN SMALL LETTER O WITH STROKE +01FF;oslashacute;LATIN SMALL LETTER O WITH STROKE AND ACUTE +F6F0;osuperior;SUPERSCRIPT LATIN SMALL LETTER O +00F5;otilde;LATIN SMALL LETTER O WITH TILDE +0070;p;LATIN SMALL LETTER P +00B6;paragraph;PILCROW SIGN +0028;parenleft;LEFT PARENTHESIS +F8ED;parenleftbt;LEFT PAREN BOTTOM +F8EC;parenleftex;LEFT PAREN EXTENDER +208D;parenleftinferior;SUBSCRIPT LEFT PARENTHESIS +207D;parenleftsuperior;SUPERSCRIPT LEFT PARENTHESIS +F8EB;parenlefttp;LEFT PAREN TOP +0029;parenright;RIGHT PARENTHESIS +F8F8;parenrightbt;RIGHT PAREN BOTTOM +F8F7;parenrightex;RIGHT PAREN EXTENDER +208E;parenrightinferior;SUBSCRIPT RIGHT PARENTHESIS +207E;parenrightsuperior;SUPERSCRIPT RIGHT PARENTHESIS +F8F6;parenrighttp;RIGHT PAREN TOP +2202;partialdiff;PARTIAL DIFFERENTIAL +0025;percent;PERCENT SIGN +002E;period;FULL STOP +00B7;periodcentered;MIDDLE DOT +2219;periodcentered;BULLET OPERATOR;Duplicate +F6E7;periodinferior;SUBSCRIPT FULL STOP +F6E8;periodsuperior;SUPERSCRIPT FULL STOP +22A5;perpendicular;UP TACK +2030;perthousand;PER MILLE SIGN +20A7;peseta;PESETA SIGN +03C6;phi;GREEK SMALL LETTER PHI +03D5;phi1;GREEK PHI SYMBOL +03C0;pi;GREEK SMALL LETTER PI +002B;plus;PLUS SIGN +00B1;plusminus;PLUS-MINUS SIGN +211E;prescription;PRESCRIPTION TAKE +220F;product;N-ARY PRODUCT +2282;propersubset;SUBSET OF +2283;propersuperset;SUPERSET OF +221D;proportional;PROPORTIONAL TO +03C8;psi;GREEK SMALL LETTER PSI +0071;q;LATIN SMALL LETTER Q +003F;question;QUESTION MARK +00BF;questiondown;INVERTED QUESTION MARK +F7BF;questiondownsmall;SMALL CAPITAL INVERTED QUESTION MARK +F73F;questionsmall;SMALL CAPITAL QUESTION MARK +0022;quotedbl;QUOTATION MARK +201E;quotedblbase;DOUBLE LOW-9 QUOTATION MARK +201C;quotedblleft;LEFT DOUBLE QUOTATION MARK +201D;quotedblright;RIGHT DOUBLE QUOTATION MARK +2018;quoteleft;LEFT SINGLE QUOTATION MARK +201B;quotereversed;SINGLE HIGH-REVERSED-9 QUOTATION MARK +2019;quoteright;RIGHT SINGLE QUOTATION MARK +201A;quotesinglbase;SINGLE LOW-9 QUOTATION MARK +0027;quotesingle;APOSTROPHE +0072;r;LATIN SMALL LETTER R +0155;racute;LATIN SMALL LETTER R WITH ACUTE +221A;radical;SQUARE ROOT +F8E5;radicalex;RADICAL EXTENDER +0159;rcaron;LATIN SMALL LETTER R WITH CARON +0157;rcommaaccent;LATIN SMALL LETTER R WITH CEDILLA +2286;reflexsubset;SUBSET OF OR EQUAL TO +2287;reflexsuperset;SUPERSET OF OR EQUAL TO +00AE;registered;REGISTERED SIGN +F8E8;registersans;REGISTERED SIGN SANS SERIF +F6DA;registerserif;REGISTERED SIGN SERIF +2310;revlogicalnot;REVERSED NOT SIGN +03C1;rho;GREEK SMALL LETTER RHO +02DA;ring;RING ABOVE +F6F1;rsuperior;SUPERSCRIPT LATIN SMALL LETTER R +2590;rtblock;RIGHT HALF BLOCK +F6DD;rupiah;RUPIAH SIGN +0073;s;LATIN SMALL LETTER S +015B;sacute;LATIN SMALL LETTER S WITH ACUTE +0161;scaron;LATIN SMALL LETTER S WITH CARON +015F;scedilla;LATIN SMALL LETTER S WITH CEDILLA +F6C2;scedilla;LATIN SMALL LETTER S WITH CEDILLA;Duplicate +015D;scircumflex;LATIN SMALL LETTER S WITH CIRCUMFLEX +0219;scommaaccent;LATIN SMALL LETTER S WITH COMMA BELOW +2033;second;DOUBLE PRIME +00A7;section;SECTION SIGN +003B;semicolon;SEMICOLON +0037;seven;DIGIT SEVEN +215E;seveneighths;VULGAR FRACTION SEVEN EIGHTHS +2087;seveninferior;SUBSCRIPT SEVEN +F737;sevenoldstyle;OLDSTYLE DIGIT SEVEN +2077;sevensuperior;SUPERSCRIPT SEVEN +2592;shade;MEDIUM SHADE +03C3;sigma;GREEK SMALL LETTER SIGMA +03C2;sigma1;GREEK SMALL LETTER FINAL SIGMA +223C;similar;TILDE OPERATOR +0036;six;DIGIT SIX +2086;sixinferior;SUBSCRIPT SIX +F736;sixoldstyle;OLDSTYLE DIGIT SIX +2076;sixsuperior;SUPERSCRIPT SIX +002F;slash;SOLIDUS +263A;smileface;WHITE SMILING FACE +0020;space;SPACE +00A0;space;NO-BREAK SPACE;Duplicate +2660;spade;BLACK SPADE SUIT +F6F2;ssuperior;SUPERSCRIPT LATIN SMALL LETTER S +00A3;sterling;POUND SIGN +220B;suchthat;CONTAINS AS MEMBER +2211;summation;N-ARY SUMMATION +263C;sun;WHITE SUN WITH RAYS +0074;t;LATIN SMALL LETTER T +03C4;tau;GREEK SMALL LETTER TAU +0167;tbar;LATIN SMALL LETTER T WITH STROKE +0165;tcaron;LATIN SMALL LETTER T WITH CARON +0163;tcommaaccent;LATIN SMALL LETTER T WITH CEDILLA +021B;tcommaaccent;LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate +2234;therefore;THEREFORE +03B8;theta;GREEK SMALL LETTER THETA +03D1;theta1;GREEK THETA SYMBOL +00FE;thorn;LATIN SMALL LETTER THORN +0033;three;DIGIT THREE +215C;threeeighths;VULGAR FRACTION THREE EIGHTHS +2083;threeinferior;SUBSCRIPT THREE +F733;threeoldstyle;OLDSTYLE DIGIT THREE +00BE;threequarters;VULGAR FRACTION THREE QUARTERS +F6DE;threequartersemdash;THREE QUARTERS EM DASH +00B3;threesuperior;SUPERSCRIPT THREE +02DC;tilde;SMALL TILDE +0303;tildecomb;COMBINING TILDE +0384;tonos;GREEK TONOS +2122;trademark;TRADE MARK SIGN +F8EA;trademarksans;TRADE MARK SIGN SANS SERIF +F6DB;trademarkserif;TRADE MARK SIGN SERIF +25BC;triagdn;BLACK DOWN-POINTING TRIANGLE +25C4;triaglf;BLACK LEFT-POINTING POINTER +25BA;triagrt;BLACK RIGHT-POINTING POINTER +25B2;triagup;BLACK UP-POINTING TRIANGLE +F6F3;tsuperior;SUPERSCRIPT LATIN SMALL LETTER T +0032;two;DIGIT TWO +2025;twodotenleader;TWO DOT LEADER +2082;twoinferior;SUBSCRIPT TWO +F732;twooldstyle;OLDSTYLE DIGIT TWO +00B2;twosuperior;SUPERSCRIPT TWO +2154;twothirds;VULGAR FRACTION TWO THIRDS +0075;u;LATIN SMALL LETTER U +00FA;uacute;LATIN SMALL LETTER U WITH ACUTE +016D;ubreve;LATIN SMALL LETTER U WITH BREVE +00FB;ucircumflex;LATIN SMALL LETTER U WITH CIRCUMFLEX +00FC;udieresis;LATIN SMALL LETTER U WITH DIAERESIS +00F9;ugrave;LATIN SMALL LETTER U WITH GRAVE +01B0;uhorn;LATIN SMALL LETTER U WITH HORN +0171;uhungarumlaut;LATIN SMALL LETTER U WITH DOUBLE ACUTE +016B;umacron;LATIN SMALL LETTER U WITH MACRON +005F;underscore;LOW LINE +2017;underscoredbl;DOUBLE LOW LINE +222A;union;UNION +2200;universal;FOR ALL +0173;uogonek;LATIN SMALL LETTER U WITH OGONEK +2580;upblock;UPPER HALF BLOCK +03C5;upsilon;GREEK SMALL LETTER UPSILON +03CB;upsilondieresis;GREEK SMALL LETTER UPSILON WITH DIALYTIKA +03B0;upsilondieresistonos;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS +03CD;upsilontonos;GREEK SMALL LETTER UPSILON WITH TONOS +016F;uring;LATIN SMALL LETTER U WITH RING ABOVE +0169;utilde;LATIN SMALL LETTER U WITH TILDE +0076;v;LATIN SMALL LETTER V +0077;w;LATIN SMALL LETTER W +1E83;wacute;LATIN SMALL LETTER W WITH ACUTE +0175;wcircumflex;LATIN SMALL LETTER W WITH CIRCUMFLEX +1E85;wdieresis;LATIN SMALL LETTER W WITH DIAERESIS +2118;weierstrass;SCRIPT CAPITAL P +1E81;wgrave;LATIN SMALL LETTER W WITH GRAVE +0078;x;LATIN SMALL LETTER X +03BE;xi;GREEK SMALL LETTER XI +0079;y;LATIN SMALL LETTER Y +00FD;yacute;LATIN SMALL LETTER Y WITH ACUTE +0177;ycircumflex;LATIN SMALL LETTER Y WITH CIRCUMFLEX +00FF;ydieresis;LATIN SMALL LETTER Y WITH DIAERESIS +00A5;yen;YEN SIGN +1EF3;ygrave;LATIN SMALL LETTER Y WITH GRAVE +007A;z;LATIN SMALL LETTER Z +017A;zacute;LATIN SMALL LETTER Z WITH ACUTE +017E;zcaron;LATIN SMALL LETTER Z WITH CARON +017C;zdotaccent;LATIN SMALL LETTER Z WITH DOT ABOVE +0030;zero;DIGIT ZERO +2080;zeroinferior;SUBSCRIPT ZERO +F730;zerooldstyle;OLDSTYLE DIGIT ZERO +2070;zerosuperior;SUPERSCRIPT ZERO +03B6;zeta;GREEK SMALL LETTER ZETA +""" + + +t1_bias = 0 +glyph_list = [] + + +def the_adobe_glyph_list(): + """return the list of glyph names in the adobe list""" + + lines = string.split( adobe_glyph_list, '\n' ) + glyphs = [] + + for line in lines: + if line: + fields = string.split( line, ';' ) +# print fields[0] + ' - ' + fields[1] + glyphs.append( fields[1] ) + + return glyphs + + +def the_adobe_glyphs(): + """return the list of unicode values""" + + lines = string.split( adobe_glyph_list, '\n' ) + glyphs = [] + values = [] + + for line in lines: + if line: + fields = string.split( line, ';' ) +# print fields[0] + ' - ' + fields[1] + glyphs.append( fields[1] ) + values.append( fields[0] ) + + return glyphs, values + + +def count_extra_glyphs( alist, filter ): + """count the number of extra glyphs""" + + count = 0 + extras = [] + + for name in alist: + try: + filtered_index = filter.index( name ) + except: + extras.append( name ) + + return extras + + +def dump_mac_indices( file ): + write = file.write + + write( " static const unsigned short mac_standard_names[" + \ + repr( len( mac_standard_names ) + 1 ) + "] =\n" ) + write( " {\n" ) + + count = 0 + for name in mac_standard_names: + try: + t1_index = t1_standard_strings.index( name ) + write( " " + repr( t1_bias + t1_index ) + ",\n" ) + except: + write( " " + repr( count ) + ",\n" ) + count = count + 1 + + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + + +def dump_glyph_list( file, glyph_list, adobe_extra ): + write = file.write + + name_list = [] + + write( " static const char* standard_glyph_names[] =\n" ) + write( " {\n" ) + + for name in glyph_list: + write( ' "' + name + '",\n' ) + name_list.append( name ) + + write( "\n" ) + write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" ) + write( "\n" ) + + for name in adobe_extra: + write( ' "' + name + '",\n' ) + name_list.append( name ) + + write( "\n" ) + write( "#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */\n" ) + write( "\n" ) + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + + return name_list + + +def dump_unicode_values( file, base_list, adobe_list ): + """build the glyph names to unicode values table""" + + write = file.write + + adobe_glyphs, uni_values = the_adobe_glyphs() + + write( "\n" ) + write( " static const unsigned short names_to_unicode[" + \ + repr( len( base_list ) + len( adobe_list ) + 1 ) + "] =\n" ) + write( " {\n" ) + + for name in base_list: + try: + index = adobe_glyphs.index( name ) + write( " 0x" + uni_values[index] + ",\n" ) + except: + write( " 0,\n" ) + + write( "\n" ) + write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" ) + write( "\n" ) + + for name in adobe_list: + try: + index = adobe_glyphs.index( name ) + write( " 0x" + uni_values[index] + ",\n" ) + except: + write( " 0,\n" ) + + write( "\n" ) + write( "#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */\n" ) + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + write( "\n" ) + + +def dump_encoding( file, encoding_name, encoding_list ): + """dumps a given encoding""" + + write = file.write + + write( " static const unsigned short " + encoding_name + "[" + \ + repr( len( encoding_list ) + 1 ) + "] =\n" ) + write( " {\n" ) + + for value in encoding_list: + write( " " + repr( value ) + ",\n" ) + write( " 0\n" ) + write( " };\n" ) + write( "\n" ) + write( "\n" ) + + +def main(): + """main program body""" + + if len( sys.argv ) != 2: + print __doc__ % sys.argv[0] + sys.exit( 1 ) + + file = open( sys.argv[1], "w\n" ) + write = file.write + + count_sid = len( t1_standard_strings ) + + # build mac index table & supplemental glyph names + mac_list = count_extra_glyphs( mac_standard_names, t1_standard_strings ) + count_mac = len( mac_list ) + t1_bias = count_mac + base_list = mac_list + t1_standard_strings + + # build adobe unicode index table & supplemental glyph names + adobe_list = the_adobe_glyph_list() + adobe_list = count_extra_glyphs( adobe_list, base_list ) + count_adobe = len( adobe_list ) + + write( "/***************************************************************************/\n" ) + write( "/* */\n" ) + + write( "/* %-71s*/\n" % sys.argv[1] ) + + write( "/* */\n" ) + write( "/* PostScript glyph names (specification only). */\n" ) + write( "/* */\n" ) + write( "/* Copyright 2000 by */\n" ) + write( "/* David Turner, Robert Wilhelm, and Werner Lemberg. */\n" ) + write( "/* */\n" ) + write( "/* This file is part of the FreeType project, and may only be used, */\n" ) + write( "/* modified, and distributed under the terms of the FreeType project */\n" ) + write( "/* license, LICENSE.TXT. By continuing to use, modify, or distribute */\n" ) + write( "/* this file you indicate that you have read the license and */\n" ) + write( "/* understand and accept it fully. */\n" ) + write( "/* */\n" ) + write( "/***************************************************************************/\n" ) + write( "\n" ) + write( "\n" ) + write( " /* this file has been generated automatically -- do not edit! */\n" ) + write( "\n" ) + write( "\n" ) + + # dump glyph list + name_list = dump_glyph_list( file, base_list, adobe_list ) + + # dump t1_standard_list + write( " static const char** t1_standard_glyphs = " \ + + "standard_glyph_names + " + repr( t1_bias ) + ";\n" ) + write( "\n" ) + write( "\n" ) + + write( "#define NUM_STD_GLYPHS " + repr( len( t1_standard_strings ) ) + "\n" ) + write( "\n" ) + write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" ) + write( "#define NUM_ADOBE_GLYPHS " + \ + repr( len( base_list ) + len( adobe_list ) - t1_bias ) + "\n" ) + write( "#else\n" ) + write( "#define NUM_ADOBE_GLYPHS " + \ + repr( len( base_list ) - t1_bias ) + "\n" ) + write( "#endif\n" ) + write( "\n" ) + write( "\n" ) + + # dump mac indices table + dump_mac_indices( file ) + + # discard mac names from base list + base_list = base_list[t1_bias:] + + # dump unicode values table + dump_unicode_values( file, base_list, adobe_list ) + + dump_encoding( file, "t1_standard_encoding", t1_standard_encoding ) + dump_encoding( file, "t1_expert_encoding", t1_expert_encoding ) + + write( "/* END */\n" ) + + +# Now run the main routine +# +main() + + +# END diff --git a/subsys/win32k/freetype/docs/glyphs/Image1.png b/subsys/win32k/freetype/docs/glyphs/Image1.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/Image1.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/Image2.png b/subsys/win32k/freetype/docs/glyphs/Image2.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/Image2.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/Image3.png b/subsys/win32k/freetype/docs/glyphs/Image3.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/Image3.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/Image4.png b/subsys/win32k/freetype/docs/glyphs/Image4.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/Image4.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/bbox1.png b/subsys/win32k/freetype/docs/glyphs/bbox1.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/bbox1.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/bbox2.png b/subsys/win32k/freetype/docs/glyphs/bbox2.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/bbox2.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/body_comparison.png b/subsys/win32k/freetype/docs/glyphs/body_comparison.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/body_comparison.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png b/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/bravo_kerned.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png b/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/bravo_unkerned.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/clipping.png b/subsys/win32k/freetype/docs/glyphs/clipping.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/clipping.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/down_flow.png b/subsys/win32k/freetype/docs/glyphs/down_flow.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/down_flow.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/grid_1.png b/subsys/win32k/freetype/docs/glyphs/grid_1.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/grid_1.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/index.html b/subsys/win32k/freetype/docs/glyphs/index.html new file mode 100644 index 0000000..85dde95 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/index.html @@ -0,0 +1,1626 @@ + + + + + + + FreeType Glyph Conventions + + + + + +
+

+FreeType Glyph Conventions

+ +
+

+version 2.0

+ +
+

+Copyright 1998-1999David Turner (david@freetype.org)
+Copyright 1999 The FreeType Development Team (devel@freetype.org)

+ +


+


+

+Introduction

+ +
This document discusses in great details the definition of +various concepts related to digital typography, as well as a few specific +to the FreeType library. It also explains the ways typographic information, +like glyph metrics, kerning distances, etc.. is to be managed and used. +It relates to the layout and display of text strings, either in a conventional +(i.e. Roman) layout, or with right-to-left or vertical ones. Some aspects +like rotation and transformation are explained too. +

Comments and corrections are highly welcomed, and can be sent to the +FreeType +developers list.

+ +
+

+I. Basic typographic concepts

+ +
+

+1. Font files, format and information

+ +
A font is a collection of various character images that can +be used to display or print text. The images in a single font share some +common properties, including look, style, serifs, etc.. Typographically +speaking, one has to distinguish between a font family and its multiple +font +faces, which usually differ in style though come from the same template. +For example, "Palatino Regular" and "Palatino Italic" are +two distinct faces from the same famous family, called "Palatino" +itself. +

The single term font is nearly always used in ambiguous ways to refer +to either a given family or given face, depending on the context. For example, +most users of word-processors use "font" to describe a font family (e.g. +Courier, Palatino, etc..); however most of these families are implemented +through several data files depending on the file format : for TrueType, +this is usually one per face (i.e. ARIAL.TFF for "Arial Regular", ARIALI.TTF +for "Arial Italic", etc..). The file is also called a "font" but really +contains a font face. +

A digital font is thus a data file that may contain one or +more font faces. For each of these, it contains character images, character +metrics, as well as other kind of information important to the layout of +text and the processing of specific character encodings. In some awkward +formats, like Adobe Type1, a single font face is described through several +files (i.e. one contains the character images, another one the character +metrics). We will ignore this implementation issue in most of this document +and consider digital fonts as single files, though FreeType 2.0 is able +to support multiple-files fonts correctly. +

As a convenience, a font file containing more than one face is called +a font collection. This case is rather rare but can be seen in many asian +fonts, which contain images for two or more scripts for a given language.

+ +

+2. Character images and mappings :

+ +
The character images are called glyphs. A single character +can have several distinct images, i.e. several glyphs, depending on script, +usage or context. Several characters can also take a single glyph (good +examples are roman ligatures like "oe" and "fi" which can be represented +by a single glyph like "œ" and "?"). The relationships between characters +and glyphs can be a very complex one but won't be detailed in this document. +Moreover, some formats use more or less awkward schemes to store and access +the glyphs. For the sake of clarity, we'll only retain the following notions +when working with FreeType : +
  +
    +
  • +A font file contains a set of glyphs, each one can be stored as a bitmap, +a vector representation or any other scheme (e.g. most scalable formats +use a combination of math representation and control data/programs). These +glyphs can be stored in any order in the font file, and is typically accessed +through a simple glyph index.
  • +
+
+
+ +
    +
      +
        +
      • +The font file contains one (or more) table, called a character map (or +charmap in short), which is used to convert character codes for a given +encoding (e.g. ASCII, Unicode, DBCS, Big5, etc..) into glyph indexes relative +to the font file. A single font face may contain several charmaps. For +example, most TrueType fonts contain an Apple-specific charmap as well +as a Unicode charmap, which makes them usable on both Mac and Windows platforms.
      • +
      +
    + +

    +3. Character and font metrics :

    + +
      Each glyph image is associated to various metrics which are used to +describe the way it must be placed and managed when rendering text. Though +they are described in more details in section III, they relate to glyph +placement, cursor advances as well as text layouts. They are extremely +important to compute the flow of text when rendering string of text. +

      Each scalable format also contains some global metrics, expressed in +notional units, used to describe some properties of all glyphs in a same +face. For example : the maximum glyph bounding box, the ascender, descender +and text height for the font. +

      Though these metrics also exist for non-scalable formats, they only +apply for a set of given character dimensions and resolutions, and they're +usually expressed in pixels then.

    +
+ +


+


+

+II. Glyph Outlines

+ +
This section describes the vectorial representation of glyph +images, called outlines. +
  +

+1. Pixels, Points and Device Resolutions :

+ +
Though it is a very common assumption when dealing with computer +graphics programs, the physical dimensions of a given pixel (be it for +screens or printers) are not squared. Often, the output device, be it a +screen or printer exhibits varying resolutions in the horizontal and vertical +directions, and this must be taken care of when rendering text. +

It is thus common to define a device's characteristics through two numbers +expressed in dpi (dots per inch). For example, a printer with a +resolution of 300x600 dpi has 300 pixels per inch in the horizontal direction, +and 600 in the vertical one. The resolution of a typical computer monitor +varies with its size (a 15" and 17" monitors don't have the same pixel +sizes at 640x480), and of course the graphics mode resolution. +

As a consequence, the size of text is usually given in points, +rather than device-specific pixels. Points are a simple physical +unit, where 1 point = 1/72th of an inch, in digital typography. As an example, +most roman books are printed with a body text which size is chosen between +10 and 14 points. +

It is thus possible to compute the size of text in pixels from the size +in points through the following computation : +

+

pixel_size = point_size * resolution / 72

+ +

Where resolution is expressed in dpi. Note that because the horizontal +and vertical resolutions may differ, a single point size usually defines +different text width and height in pixels. +
  +

IMPORTANT NOTE: +
Unlike what is often thought, the "size of text in pixels" is not +directly related to the real dimensions of characters when they're displayed +or printed. The relationship between these two concepts is a bit more complex +and relate to some design choice made by the font designer. This is described +in more details the next sub-section (see the explanations on the EM square).

+ +

+2. Vectorial representation :

+ +
The source format of outlines is a collection of closed paths +called contours. Each contour delimits an outer or inner region +of the glyph, and can be made of either line segments or bezier +arcs. +

The arcs are defined through control points, and can be either +second-order (these are "conic beziers") or third-order ("cubic" beziers) +polynomials, depending on the font format. Hence, each point of the outline +has an associated flag indicating its type (normal or control point). +And scaling the points will scale the whole outline. +

Each glyph's original outline points are located on a grid of indivisible +units. The points are usually stored in a font file as 16-bit integer grid +coordinates, with the grid origin's being at (0,0); they thus range from +-16384 to 16383. (even though point coordinates can be floats in other +formats such as Type 1, we'll restrict our analysis to integer ones, driven +by the need for simplicity..). +

IMPORTANT NOTE: +
The grid is always oriented like the traditional mathematical 2D +plane, i.e. the X axis from the left to the right, and the Y axis from +bottom to top. +

In creating the glyph outlines, a type designer uses an imaginary square +called the "EM square". Typically, the EM square can be thought of as a +tablet on which the character are drawn. The square's size, i.e., the number +of grid units on its sides, is very important for two reasons: +
  +

+
  • +it is the reference used to scale the outlines to a given text dimension. +For example, a size of 12pt at 300x300 dpi corresponds to 12*300/72 = 50 +pixels. This is the size the EM square would appear on the output device +if it was rendered directly. In other words, scaling from grid units to +pixels uses the formula:
  • +
    + +
    pixel_size = point_size * resolution / 72 +
    pixel_coordinate = grid_coordinate * pixel_size / EM_size
    + +
    +
  • +the greater the EM size is, the larger resolution the designer can use +when digitizing outlines. For example, in the extreme example of an EM +size of 4 units, there are only 25 point positions available within the +EM square which is clearly not enough. Typical TrueType fonts use an EM +size of 2048 units (note: with Type 1 PostScript fonts, the EM size is +fixed to 1000 grid units. However, point coordinates can be expressed in +floating values).
  • +
    +Note that glyphs can freely extend beyond the EM square if the font designer +wants so. The EM is used as a convenience, and is a valuable convenience +from traditional typography. +
    +

    Note : Grid units are very often called "font units" or "EM units".

    + +

    NOTE: +
    As said before, the pixel_size computed in  the above formula +does not relate directly to the size of characters on the screen. It simply +is the size of the EM square if it was to be displayed directly. Each font +designer is free to place its glyphs as it pleases him within the square. +This explains why the letters of the following text have not the same height, +even though they're displayed at the same point size with distinct fonts +: +

    +

    + +

    As one can see, the glyphs of the Courier family are smaller than those +of Times New Roman, which themselves are slightly smaller than those of +Arial, even though everything is displayed or printed  at a size of +16 points. This only reflect design choices. +
     

    + +

    +3. Hinting and Bitmap rendering

    + +
    The outline as stored in a font file is called the "master" +outline, as its points coordinates are expressed in font units. Before +it can be converted into a bitmap, it must be scaled to a given size/resolution. +This is done through a very simple transform, but always creates undesirable +artifacts, e.g. stems of different widths or heights in letters like "E" +or "H". +

    As a consequence, proper glyph rendering needs the scaled points to +be aligned along the target device pixel grid, through an operation called +"grid-fitting", and often "hinting". One of its main purpose is to ensure +that important widths and heights are respected throughout the whole font +(for example, it is very often desirable that the "I" and the "T" have +their central vertical line of the same pixel width), as well as manage +features like stems and overshoots, which can cause problems at small pixel +sizes. +

    There are several ways to perform grid-fitting properly, for example +most scalable formats associate some control data or programs with each +glyph outline. Here is an overview : +
      +

    +
    explicit grid-fitting : +
    The TrueType format defines a stack-based virtual machine, +for which programs can be written with the help of more than 200 opcodes +(most of these relating to geometrical operations). Each glyph is thus +made of both an outline and a control program, its purpose being to perform +the actual grid-fitting in the way defined by the font designer.
    + +


    implicit grid-fitting (also called hinting) : +

    The Type 1 format takes a much simpler approach : each glyph +is made of an outline as well as several pieces called "hints" which are +used to describe some important features of the glyph, like the presence +of stems, some width regularities, and the like. There aren't a lot of +hint types, and it's up to the final renderer to interpret the hints in +order to produce a fitted outline.
    + +


    automatic grid-fitting : +

    Some formats simply include no control information with each +glyph outline, apart metrics like the advance width and height. It's then +up to the renderer to "guess" the more interesting features of the outline +in order to perform some decent grid-fitting.
    +
    +
    + +
    +


    The following table summarises the pros and cons of each scheme +:

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    Grid-fitting scheme
    +
    +
    +
    +
    Pros
    +
    +
    +
    +
    Cons
    +
    +
    +
    +
    Explicit
    +
    +
    +
    +
    Quality +
    excellence at small sizes is possible. This is +very important for screen display. +

    Consistency +
    all renderers produce the same glyph bitmaps.

    +
    +
    +
    +
    Speed +
    intepreting bytecode can be slow if the glyph +programs are complex. +

    Size +
    glyph programs can be long +

    Technicity +
    it is extremely difficult to write good hinting +programs. Very few tools available.

    +
    +
    +
    +
    Implicit
    +
    +
    +
    +
    Size +
    hints are usually much smaller than explicit +glyph programs. +

    Speed +
    grid-fitting is usually a fast process

    +
    +
    +
    +
    Quality +
    often questionable at small sizes. Better with +anti-aliasing though. +

    Inconsistency +
    results can vary between different renderers, +or even distinct versions of the same engine.

    +
    +
    +
    +
    Automatic
    +
    +
    +
    +
    Size +
    no need for control information, resulting in +smaller font files. +

    Speed +
    depends on the grid-fitting algo.Usually faster +than explicit grid-fitting.

    +
    +
    +
    +
    Quality +
    often questionable at small sizes. Better with +anti-aliasing though +

    Speed +
    depends on the grid-fitting algo. +

    Inconsistency +
    results can vary between different renderers, +or even distinct versions of the same engine.

    +
    +
    +
    + +
    +

    +III. Glyph metrics

    + +
    +

    +1. Baseline, Pens and Layouts

    +The baseline is an imaginary line that is used to "guide" glyphs when rendering +text. It can be horizontal (e.g. Roman, Cyrillic, Arabic, etc.) or vertical +(e.g. Chinese, Japanese, Korean, etc). Moreover, to render text, a virtual +point, located on the baseline, called the "pen position" or "origin", +is used to locate glyphs. +

    Each layout uses a different convention for glyph placement: +
      +

    +
  • +with horizontal layout, glyphs simply "rest" on the baseline. Text is rendered +by incrementing the pen position, either to the right or to the left.
  • +
    +
    + +
      +
        the distance between two successive pen positions is glyph-specific +and is called the "advance width". Note that its value is _always_ positive, +even for right-to-left oriented alphabets, like Arabic. This introduces +some differences in the way text is rendered. +

        IMPORTANT NOTE:  The pen position is always placed on the baseline.

      + +
      + +
        +
      • +with a vertical layout, glyphs are centered around the baseline:
      • +
      + +
      + +


      +

      +2. Typographic metrics and bounding boxes

      + +
        A various number of face metrics are defined for all glyphs in a given +font. +

        the ascent +

          this is the distance from the baseline to the highest/upper grid coordinate +used to place an outline point. It is a positive value, due to the grid's +orientation with the Y axis upwards.
        + +


        the descent +

          the distance from the baseline to the lowest grid coordinate used to +place an outline point. This is a negative value, due to the grid's orientation.
        + +


        the linegap +

          the distance that must be placed between two lines of text. The baseline-to-baseline +distance should be computed as: +
          +

          ascent - descent + linegap

          +if you use the typographic values.
        +Other, simpler metrics are: +

        the glyph's bounding box, also called "bbox" +

          this is an imaginary box that encloses all glyphs from the font, as +tightly as possible. It is represented by four fields, namely xMin, +yMin, +xMax, +and yMax, that can be computed for any outline. Their values can +be in font units (if measured in the original outline) or in fractional/integer +pixel units (when measured on scaled outlines). +

          Note that if it wasn't for grid-fitting, you wouldn't need to know a +box's complete values, but only its dimensions to know how big is a glyph +outline/bitmap. However, correct rendering of hinted glyphs needs the preservation +of important grid alignment on each glyph translation/placement on the +baseline.

        +the internal leading +
          this concept comes directly from the world of traditional typography. +It represents the amount of space within the "leading" which is reserved +for glyph features that lay outside of the EM square (like accentuation). +It usually can be computed as: +
          +

          internal leading = ascent - descent - EM_size

          +
        +the external leading +
          this is another name for the line gap.
        +
      + +

      +3. Bearings and Advances

      + +
        Each glyph has also distances called "bearings" and "advances". Their +definition is constant, but their values depend on the layout, as the same +glyph can be used to render text either horizontally or vertically: +

        the left side bearing: a.k.a. bearingX +

          this is the horizontal distance from the current pen position to the +glyph's left bbox edge. It is positive for horizontal layouts, and most +generally negative for vertical one.
        + +


        the top side bearing: a.k.a. bearingY +

          this is the vertical distance from the baseline to the top of the glyph's +bbox. It is usually positive for horizontal layouts, and negative for vertical +ones
        + +


        the advance width: a.k.a. advanceX +

          is the horizontal distance the pen position must be incremented (for +left-to-right writing) or decremented (for right-to-left writing) by after +each glyph is rendered when processing text. It is always positive for +horizontal layouts, and null for vertical ones.
        + +


        the advance height: a.k.a. advanceY +

          is the vertical distance the pen position must be decremented by after +each glyph is rendered. It is always null for horizontal layouts, and positive +for vertical layouts.
        + +


        the glyph width +

          this is simply the glyph's horizontal extent. More simply it is (bbox.xMax-bbox.xMin) +for unscaled font coordinates. For scaled glyphs, its computation requests +specific care, described in the grid-fitting chapter below.
        + +


        the glyph height +

          this is simply the glyph's vertical extent. More simply, it is (bbox.yMax-bbox.yMin) +for unscaled font coordinates. For scaled glyphs, its computation requests +specific care, described in the grid-fitting chapter below.
        + +


        the right side bearing +

          is only used for horizontal layouts to describe the distance from the +bbox's right edge to the advance width. It is in most cases a non-negative +number.
        + +
        advance_width - left_side_bearing - (xMax-xMin)
        + +

        Here is a picture giving all the details for horizontal metrics : +

        +

        + +

        And here is another one for the vertical metrics : +

        +

        +
      + +

      +4. The effects of grid-fitting

      + +
        Because hinting aligns the glyph's control points to the pixel grid, +this process slightly modifies the dimensions of character images in ways +that differ from simple scaling. +

        For example, the image of the lowercase "m" letter sometimes fits a +square in the master grid. However, to make it readable at small pixel +sizes, hinting tends to enlarge its scaled outline in order to keep its +three legs distinctly visible, resulting in a larger character bitmap. +

        The glyph metrics are also influenced by the grid-fitting process. Mainly +because : +
          +

          +
        • +The image's width and height are altered. Even if this is only by one pixel, +it can make a big difference at small pixel sizes
        • + +
        • +The image's bounding box is modified, thus modifying the bearings
        • + +
        • +The advances must be updated. For example, the advance width must be incremented +when the hinted bitmap is larger than the scaled one, to reflect the augmented +glyph width.
        • +
        + +


        Note also that : +
          +

          +
        • +Because of hinting, simply scaling the font ascent or descent might not +give correct results. A simple solution consists in keeping the ceiling +of the scaled ascent, and floor of the scaled descent.
        • +
        + +
          +
        • +There is no easy way to get the hinted glyph and advance widths of a range +of glyphs, as hinting works differently on each outline. The only solution +is to hint each glyph separately and record the returned values. Some formats, +like TrueType, even include a table of pre-computed values for a small +set of common character pixel sizes.
        • +
        + +
          +
        • +Hinting depends on the final character width and height in pixels, which +means that it is highly resolution-dependent. This property makes correct +WYSIWYG layouts difficult to implement.
        • +
        + +


        IMPORTANT NOTE: +
        Performing 2D transforms on glyph outlines is very easy with FreeType. +However, when using translation on a hinted outlines, one should aways +take care of  exclusively using integer pixel distances (which +means that the parameters to the FT_Translate_Outline API should all be +multiples of 64, as the point coordinates are in 26.6 fixed float format). +

        Otherwise, the translation will simply ruin the hinter's work, +resulting in a very low quality bitmaps. +
          +
         

      + +

      + 5. Text widths and bounding box :

      + +
        As seen before, the "origin" of a given glyph corresponds to the position +of the pen on the baseline. It is not necessarily located on one of the +glyph's bounding box corners, unlike many typical bitmapped font formats. +In some cases, the origin can be out of the bounding box, in others, it +can be within it, depending on the shape of the given glyph. +

        Likewise, the glyph's "advance width" is the increment to apply to the +pen position during layout, and is not related to the glyph's "width", +which really is the glyph's bounding width. +
          +

        The same conventions apply to strings of text. This means that : +
          +

          +
            +
          • +The bounding box of a given string of text doesn't necessarily contain +the text cursor, nor is the latter located on one of its corners.
          • +
          + +
            +
          • +The string's advance width isn't related to its bounding box's dimensions. +Especially if it contains beginning and terminal spaces or tabs.
          • +
          + +
            +
          • +Finally, additional processing like kerning creates strings of text whose +dimensions are not directly related to the simple juxtaposition of individual +glyph metrics. For example, the advance width of "VA" isn't the sum of +the advances of "V" and "A" taken separately.
          • +
          +
        +
      +
    + +
    +

    + IV. Kerning

    + +
    The term 'kerning' refers to specific information used to adjust +the relative positions of coincident glyphs in a string of text. This section +describes several types of kerning information, as well as the way to process +them when performing text layout. +
      +

    +1. Kerning pairs

    + +
    Kerning consists in modifying the spacing between two successive +glyphs according to their outlines. For example, a "T" and a "y" can be +easily moved closer, as the top of the "y" fits nicely under the "T"'s +upper right bar. +

    When laying out text with only their standard widths, some consecutive +glyphs sometimes seem a bit too close or too distant. For example, the +space between the 'A' and the 'V' in the following word seems a little +wider than needed. +

    +

    + +

    Compare this to the same word, when the distance between these two letters +has been slightly reduced : +

    +

    + +

    As you can see, this adjustment can make a great difference. Some font +faces thus include a table containing kerning distances for a set of given +glyph pairs, used during text layout. Note that : +
      +

    +
      +
    • +The pairs are ordered, i.e. the space for pair (A,V) isn't necessarily +the space for pair (V,A). They also index glyphs, and not characters.
    • +
    + +
      +
    • +Kerning distances can be expressed in horizontal or vertical directions, +depending on layout and/or script. For example, some horizontal layouts +like arabic can make use of vertical kerning adjustments between successive +glyphs. A vertical script can have vertical kerning distances.
    • +
    + +
      +
    • +Kerning distances are expressed in grid units. They are usually oriented +in the X axis, which means that a negative value indicates that two glyphs +must be set closer in a horizontal layout.
    • +
    +
    +
    + +

    +2. Applying kerning

    + +
    Applying kerning when rendering text is a rather easy process. +It merely consists in adding the scaled kern distance to the pen position +before writing each next glyph. However, the typographically correct renderer +must take a few more details in consideration. +

    The "sliding dot" problem is a good example : many font faces include +a kerning distance between capital letters like "T" or "F" and a following +dot ("."), in order to slide the latter glyph just right to their main +leg. I.e. +

    +

    + +

    However, this sometimes requires additional adjustments between the +dot and the letter following it, depending on the shapes of the enclosing +letters. When applying "standard" kerning adjustments, the previous sentence +would become : +

    +

    + +

    Which clearly is too contracted. The solution here, as exhibited in +the first example is to only slide the dots when possible. Of course, this +requires a certain knowledge of the text's meaning. The above adjustments +would not necessarily be welcomed if we were rendering the final dot of +a given paragraph. +

    This is only one example, and there are many others showing that a real +typographer is needed to layout text properly. If not available, some kind +of user interaction or tagging of the text could be used to specify some +adjustments, but in all cases, this requires some support in applications +and text libraries. +

    For more mundane and common uses, however, we can have a very simple +algorithm, which  avoids the sliding dot problem, and others, though +not producing optimal results. It can be seen as : +
      +

    +
      +
    1. +place the first glyph on the baseline
    2. + +
    3. +save the location of the pen position/origin in pen1
    4. + +
    5. +adjust the pen position with the kerning distance between the first and +second glyph
    6. + +
    7. +place the second glyph and compute the next pen position/origin in pen2.
    8. + +
    9. +use pen1 as the next pen position if it is beyond pen2, use pen2 otherwise.
    10. +
    +
    +
    +
    + +

    + +

    + +

    +V. Text processing

    + +
    This section demonstrates how to use the concepts previously +defined to render text, whatever the layout you use. +
      +

    +1. Writing simple text strings :

    + +
    In this first example, we'll generate a simple string of Roman +text, i.e. with a horizontal left-to-right layout. Using exclusively pixel +metrics, the process looks like : +
    1) convert the character string into a series of glyph +indexes. +
    2) place the pen to the cursor position. +
    3) get or load the glyph image. +
    4) translate the glyph so that its 'origin' matches the pen position +
    5) render the glyph to the target device +
    6) increment the pen position by the glyph's advance width in pixels +
    7) start over at step 3 for each of the remaining glyphs +
    8) when all glyphs are done, set the text cursor to the new pen +position
    +Note that kerning isn't part of this algorithm.
    + +

    +2. Sub-pixel positioning :

    + +
    It is somewhat useful to use sub-pixel positioning when rendering +text. This is crucial, for example, to provide semi-WYSIWYG text layouts. +Text rendering is very similar to the algorithm described in sub-section +1, with the following few differences : +
      +
    • +The pen position is expressed in fractional pixels.
    • + +
    • +Because translating a hinted outline by a non-integer distance will ruin +its grid-fitting, the position of the glyph origin must be rounded before +rendering the character image.
    • + +
    • +The advance width is expressed in fractional pixels, and isn't necessarily +an integer.
    • +
    + +


    Which finally looks like : +

    1. convert the character string into a series of glyph +indexes. +
    2. place the pen to the cursor position. This can be a non-integer +point. +
    3. get or load the glyph image. +
    4. translate the glyph so that its 'origin' matches the rounded +pen position. +
    5. render the glyph to the target device +
    6. increment the pen position by the glyph's advance width in fractional +pixels. +
    7. start over at step 3 for each of the remaining glyphs +
    8. when all glyphs are done, set the text cursor to the new pen +position
    +Note that with fractional pixel positioning, the space between two given +letters isn't fixed, but determined by the accumulation of previous rounding +errors in glyph positioning.
    + +

    +3.  Simple kerning :

    + +
    Adding kerning to the basic text rendering algorithm is easy +: when a kerning pair is found, simply add the scaled kerning distance +to the pen position before step 4. Of course, the distance should be rounded +in the case of algorithm 1, though it doesn't need to for algorithm 2. +This gives us : +

    Algorithm 1 with kerning: +

    3) get or load the glyph image. +
    4) Add the rounded scaled kerning distance, if any, to the pen +position +
    5) translate the glyph so that its 'origin' matches the pen position +
    6) render the glyph to the target device +
    7) increment the pen position by the glyph's advance width in pixels +
    8) start over at step 3 for each of the remaining glyphs
    + +


    Algorithm 2 with kerning: +

    3) get or load the glyph image. +
    4) Add the scaled unrounded kerning distance, if any, to the pen +position. +
    5) translate the glyph so that its 'origin' matches the rounded +pen position. +
    6) render the glyph to the target device +
    7) increment the pen position by the glyph's advance width in fractional +pixels. +
    8) start over at step 3 for each of the remaining glyphs
    +Of course, the algorithm described in section IV can also be applied to +prevent the sliding dot problem if one wants to..
    + +

    +4. Right-To-Left Layout :

    + +
    The process of laying out arabic or hebrew text is extremely +similar. The only difference is that the pen position must be decremented +before the glyph rendering (remember : the advance width is always positive, +even for arabic glyphs). Thus, algorithm 1 becomes : +

    Right-to-left Algorithm 1: +

    3) get or load the glyph image. +
    4) Decrement the pen position by the glyph's advance width in pixels +
    5) translate the glyph so that its 'origin' matches the pen position +
    6) render the glyph to the target device +
    7) start over at step 3 for each of the remaining glyphs
    + +


    The changes to Algorithm 2, as well as the inclusion of kerning +are left as an exercise to the reader. +
      +
     

    + +

    +5. Vertical layouts :

    + +
    Laying out vertical text uses exactly the same processes, with +the following significant differences : +
      +
    +
  • +The baseline is vertical, and the vertical metrics must be used instead +of the horizontal one.
  • + +
  • +The left bearing is usually negative, but this doesn't change the fact +that the glyph origin must be located on the baseline.
  • + +
  • +The advance height is always positive, so the pen position must be decremented +if one wants to write top to bottom (assuming the Y axis is oriented upwards).
  • +
    +Through the following algorithm : +
    1) convert the character string into a series of glyph +indexes. +
    2) place the pen to the cursor position. +
    3) get or load the glyph image. +
    4) translate the glyph so that its 'origin' matches the pen position +
    5) render the glyph to the target device +
    6) decrement the vertical pen position by the glyph's advance height +in pixels +
    7) start over at step 3 for each of the remaining glyphs +
    8) when all glyphs are done, set the text cursor to the new pen +position
    +
    + +

    +6. WYSIWYG text layouts :

    + +
    As you probably know, the acronym WYSIWYG stands for 'What +You See Is What You Get'. Basically, this means that the output of +a document on the screen should match "perfectly" its printed version. +A true wysiwyg system requires two things : +

    device-independent text layout +

    Which means that the document's formatting is the same on the +screen than on any printed output, including line breaks, justification, +ligatures, fonts, position of inline images, etc..
    + +


    matching display and print character sizes +

    Which means that the displayed size of a given character should +match its dimensions when printed. For example, a text string which is +exactly 1 inch tall when printed should also appear 1 inch tall on the +screen (when using a scale of 100%).
    + +


    It is clear that matching sizes cannot be possible if the computer +has no knowledge of the physical resolutions of the display device(s) it +is using. And of course, this is the most common case ! That's not too +unfortunate, however  because most users really don't care about this +feature. Legibility is much more important. +

    When the Mac appeared, Apple decided to choose a resolution of 72 dpi +to describe the Macintosh screen to the font sub-system (whatever the monitor +used). This choice was most probably driven by the fact that, at this resolution, +1 point = 1 pixel. However; it neglected one crucial fact : as most users +tend to choose a document character size between 10 and 14 points, the +resultant displayed text was rather small and not too legible without scaling. +Microsoft engineers took notice of this problem and chose a resolution +of 96 dpi on Windows, which resulted in slightly larger, and more legible, +displayed characters (for the same printed text size). +

    These distinct resolutions explain some differences when displaying +text at the same character size on a Mac and a Windows machine. Moreover, +it is not unusual to find some TrueType fonts with enhanced hinting (tech +note: through delta-hinting) for the sizes of 10, 12, 14 and 16 points +at 96 dpi. +
      +

    As for device-independent text, it is a notion that is, unfortunately, +often abused. For example, many word processors, including MS Word, do +not really use device-independent glyph positioning algorithms when laying +out text. Rather, they use the target printer's resolution to compute hinted +glyph metrics for the layout. Though it guarantees that the printed version +is always the "nicest" it can be, especially for very low resolution printers +(like dot-matrix), it has a very sad effect : changing the printer can +have dramatic effects on the whole document layout, especially if +it makes strong use of justification, uses few page breaks, etc.. +

    Because the glyph metrics vary slightly when the resolution changes +(due to hinting), line breaks can change enormously, when these differences +accumulate over long runs of text. Try for example printing a very long +document (with no page breaks) on a 300 dpi ink-jet printer, then the same +one on a 3000 dpi laser printer : you'll be extremely lucky if your final +page count didn't change between the prints ! Of course, we can still call +this WYSIWYG, as long as the printer resolution is fixed !! +

    Some applications, like Adobe Acrobat, which targeted device-independent +placement from the start, do not suffer from this problem. There are two +ways to achieve this : either use the scaled and unhinted glyph metrics +when laying out text both in the rendering and printing processes, or simply +use wathever metrics you want and store them with the text in order to +get sure they're printed the same on all devices (the latter being probably +the best solution, as it also enables font substitution without breaking +text layouts). +

    Just like matching sizes, device-independent placement isn't necessarily +a feature that most users want. However, it is pretty clear that for any +kind of professional document processing work, it is a requirement.

    +
    + +

    + +

    + +

    +VI. FreeType outlines :

    + +
    The purpose of this section is to present the way FreeType +manages vectorial outlines, as well as the most common operations that +can be applied on them. +
      +

    +1. FreeType outline description and structure :

    + +
    +

    +a. Outline curve decomposition :

    + +
    An outline is described as a series of closed contours in the +2D plane. Each contour is made of a series of line segments and bezier +arcs. Depending on the file format, these can be second-order or third-order +polynomials. The former are also called quadratic or conic arcs, and they +come from the TrueType format. The latter are called cubic arcs and mostly +come from the Type1 format. +

    Each arc is described through a series of start, end and control points. +Each point of the outline has a specific tag which indicates wether it +is used to describe a line segment or an arc. The tags can take the following +values : +
      +
     

    + +
    + + + + + + + + + + + + + + + + + +
    +
    FT_Curve_Tag_On 
    +
    +
    Used when the point is "on" the curve. This corresponds to +start and end points of segments and arcs. The other tags specify what +is called an "off" point, i.e. one which isn't located on the contour itself, +but serves as a control point for a bezier arc.
    +
    +
    FT_Curve_Tag_Conic
    +
    +
    Used for an "off" point used to control a conic bezier arc.
    +
    +
    FT_Curve_Tag_Cubic
    +
    +
    Used for an "off" point used to control a cubic bezier arc.
    +
    + +
      +

    The following rules are applied to decompose the contour's points into +segments and arcs : +

    +
  • +two successive "on" points indicate a line segment joining them.
  • +
    +
    + +
      +
        +
      • +one conic "off" point amidst two "on" points indicates a conic bezier arc, +the "off" point being the control point, and the "on" ones the start and +end points.
      • +
      +
    + +
      +
        +
      • +Two successive cubic "off" points amidst two "on" points indicate a cubic +bezier arc. There must be exactly two cubic control points and two on points +for each cubic arc (using a single cubic "off" point between two "on" points +is forbidden, for example).
      • +
      +
    + +
      +
        +
      • +finally, two successive conic "off" points forces the rasterizer to create +(during the scan-line conversion process exclusively) a virtual "on" point +amidst them, at their exact middle. This greatly facilitates the definition +of successive conic bezier arcs. Moreover, it's the way outlines are described +in the TrueType specification.
      • +
      + +


      Note that it is possible to mix conic and cubic arcs in a single +contour, even though no current font driver produces such outlines. +
       

    + +
    + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    +b. Outline descriptor :

    + +
    A FreeType outline is described through a simple structure, +called FT_Outline, which fields are : +
      +
      +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    n_pointsthe number of points in the outline
    n_contoursthe number of contours in the outline
    pointsarray of point coordinates
    contoursarray of contour end indices
    flagsarray of point flags
    + +

    Here, points is a pointer to an array of FT_Vector +records, used to store the vectorial coordinates of each outline point. +These are expressed in 1/64th of a pixel, which is also known as the 26.6 +fixed float format. +

    contours is an array of point indices used to delimit +contours in the outline. For example, the first contour always starts at +point 0, and ends a point contours[0]. The second contour +starts at point "contours[0]+1" and ends at contours[1], +etc.. +

    Note that each contour is closed, and that n_points +should be equal to "contours[n_contours-1]+1" for a valid +outline. +

    Finally, flags is an array of bytes, used to store each +outline point's tag. +
      +
     

    +
    + +

    +2. Bounding and control box computations :

    + +
    A bounding box (also called "bbox") is simply +the smallest possible rectangle that encloses the shape of a given outline. +Because of the way arcs are defined, bezier control points are not necessarily +contained within an outline's bounding box. +

    This situation happens when one bezier arc is, for example, the upper +edge of an outline and an off point happens to be above the bbox. However, +it is very rare in the case of character outlines because most font designers +and creation tools always place on points at the extrema of each curved +edges, as it makes hinting much easier. +

    We thus define the control box (a.k.a. the "cbox") as +the smallest possible rectangle that encloses all points of a given outline +(including its off points). Clearly, it always includes the bbox, and equates +it in most cases. +

    Unlike the bbox, the cbox is also much faster to compute. +
      +

    + + + + + +
    + +

    Control and bounding boxes can be computed automatically through the +functions FT_Get_Outline_CBox and FT_Get_Outline_BBox. +The former function is always very fast, while the latter may be +slow in the case of "outside" control points (as it needs to find the extreme +of conic and cubic arcs for "perfect" computations). If this isn't the +case, it's as fast as computing the control box. +

    Note also that even though most glyph outlines have equal cbox and bbox +to ease hinting, this is not necessary the case anymore when a +
    transform like rotation is applied to them. +
     

    + +

    + 3. Coordinates, scaling and grid-fitting :

    + +
    An outline point's vectorial coordinates are expressed in the +26.6 format, i.e. in 1/64th of a pixel, hence coordinates (1.0, -2.5) is +stored as the integer pair ( x:64, y: -192 ). +

    After a master glyph outline is scaled from the EM grid to the current +character dimensions, the hinter or grid-fitter is in charge of aligning +important outline points (mainly edge delimiters) to the pixel grid. Even +though this process is much too complex to be described in a few lines, +its purpose is mainly to round point positions, while trying to preserve +important properties like widths, stems, etc.. +

    The following operations can be used to round vectorial distances in +the 26.6 format to the grid : +

    +

    round(x)   ==  (x+32) & -64 +
    floor(x)   ==       x & +-64 +
    ceiling(x) ==  (x+63) & -64

    + +

    Once a glyph outline is grid-fitted or transformed, it often is interesting +to compute the glyph image's pixel dimensions before rendering it. To do +so, one has to consider the following : +

    The scan-line converter draws all the pixels whose centers fall +inside the glyph shape. It can also detect "drop-outs", i.e. +discontinuities coming from extremely thin shape fragments, in order to +draw the "missing" pixels. These new pixels are always located at a distance +less than half of a pixel but one cannot predict easily where they'll appear +before rendering. +

    This leads to the following computations : +
      +

      +
    • +compute the bbox
    • +
    + +
      +
    • +grid-fit the bounding box with the following :
    • +
    + +
      +
        xmin = floor( bbox.xMin ) +
        xmax = ceiling( bbox.xMax ) +
        ymin = floor( bbox.yMin ) +
        ymax = ceiling( bbox.yMax )
      + +
    • +return pixel dimensions, i.e. width = (xmax - xmin)/64 and height += (ymax - ymin)/64
    • +
    + +


    By grid-fitting the bounding box, one guarantees that all the pixel +centers that are to be drawn, including those coming from drop-out +control, will be within the adjusted box. Then the +box's dimensions in pixels can be computed. +

    Note also that, when translating a grid-fitted outline, +one should always use integer distances to +move an outline in the 2D plane. Otherwise, glyph edges won't be aligned +on the pixel grid anymore, and the hinter's work will be lost, producing +very +low quality bitmaps and pixmaps..

    +
    + +
    +

    +VII. FreeType bitmaps :

    + +
    The purpose of this section is to present the way FreeType +manages bitmaps and pixmaps, and how they relate to the concepts previously +defined. The relationships between vectorial and pixel coordinates is explained. +
      +

    +1. FreeType bitmap and pixmap descriptor :

    + +
    A bitmap or pixmap is described through a single structure, +called FT_Raster_Map. It is a simple descriptor whose fields are +: +
      +
      +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FT_Raster_Map
    rowsthe number of rows, i.e. lines, in the bitmap
    widththe number of horizontal pixels in the bitmap
    colsthe number of "columns", i.e. bytes per line, in the bitmap
    flowthe bitmap's flow, i.e. orientation of rows (see below)
    pix_bitsthe number of bits per pixels. valid values are 1, 4, 8 and 16
    buffera typeless pointer to the bitmap pixel bufer
    + +

    The bitmap's flow determines wether the rows in the +pixel buffer are stored in ascending or descending order. Possible values +are FT_Flow_Up (value 1) and FT_Flow_Down +(value -1). +

    Remember that FreeType uses the Y upwards convention in the 2D +plane. Which means that a coordinate of (0,0) always refer to the lower-left +corner of a bitmap. +

    In the case of an 'up' flow, the rows are stored in increasing +vertical position, which means that the first bytes of the pixel buffer +are part of the lower bitmap row. On the opposite, a 'down' +flow means that the first buffer bytes are part of the upper bitmap +row, i.e. the last one in ascending order. +

    As a hint, consider that when rendering an outline into a Windows or +X11 bitmap buffer, one should always use a down flow in the bitmap descriptor. +
      +

    + + + + + + + + + + + +
    +
    + +

    +2. Vectorial versus pixel coordinates :

    + +
    This sub-section explains the differences between vectorial +and pixel coordinates. To make things clear, brackets will be used to describe +pixel coordinates, e.g. [3,5], while parentheses will be used for vectorial +ones, e.g. (-2,3.5). +

    In the pixel case, as we use the Y upwards convention, the coordinate +[0,0] always refers to the lower left pixel of a bitmap, while coordinate +[width-1, rows-1] to its upper right pixel. +

    In the vectorial case, point coordinates are expressed in floating units, +like (1.25, -2.3). Such a position doesn't refer to a given pixel, but +simply to an immaterial point in the 2D plane +

    The pixels themselves are indeed square boxes of the 2D plane, +which centers lie in half pixel coordinates. For example, the lower +left pixel of a bitmap is delimited by the square (0,0)-(1,1), +its center being at location (0.5,0.5). +

    This introduces some differences when computing distances. For example, +the "length" in pixels of the line [0,0]-[10,0] is 11. However, +the vectorial distance between (0,0)-(10,0) covers exactly 10 pixel centers, +hence its length if 10. +

    +
    + +

    +3. Converting outlines into bitmaps and pixmaps :

    + +
    Generating a bitmap or pixmap image from a vectorial image +is easy with FreeType. However, one must understand a few points regarding +the positioning of the outline in the 2D plane before calling the function +FT_Get_Outline_Bitmap. +These are : +
      +
      +
    • +The glyph loader and hinter always places the outline in the 2D plane so +that (0,0) matches its character origin. This means that the glyph’s outline, +and corresponding bounding box, can be placed anywhere in the 2D plane +(see the graphics in section III).
    • +
    + +
      +
    • +The target bitmap’s area is mapped to the 2D plane, with its lower left +corner at (0,0). This means that a bitmap or pixmap of dimensions [w,h] +will be mapped to a 2D rectangle window delimited by (0,0)-(w,h).
    • +
    + +
      +
    • +When calling FT_Get_Outline_Bitmap, everything that falls +within the bitmap window is rendered, the rest is ignored.
    • +
    + +


    A common mistake made by many developers when they begin using FreeType +is believing that a loaded outline can be directly rendered in a bitmap +of adequate dimensions. The following images illustrate why this is a problem +: +

      +
        +
      • +the first image shows a loaded outline in the 2D plane.
      • + +
      • +the second one shows the target window for a bitmap of arbitrary dimensions +[w,h]
      • + +
      • +the third one shows the juxtaposition of the outline and window in the +2D plane
      • + +
      • +the last image shows what will really be rendered in the bitmap.
      • +
      +
    + +
    + +


    +
    +
    +
    +
    +

    Indeed, in nearly all cases, the loaded or transformed outline must +be translated before it is rendered into a target bitmap, in order to adjust +its position relative to the target window. +

    For example, the correct way of creating a standalone glyph bitmap +is thus to : +
      +

      +
    • +Compute the size of the glyph bitmap. It can be computed directly from +the glyph metrics, or by computing its bounding box (this is useful when +a transform has been applied to the outline after the load, as the glyph +metrics are not valid anymore).
    • +
    + +
      +
    • +Create the bitmap with the computed dimensions. Don’t forget to fill the +pixel buffer with the background color.
    • +
    + +
      +
    • +Translate the outline so that its lower left corner matches (0,0). Don’t +forget that in order to preserve hinting, one should use integer, i.e. +rounded distances (of course, this isn’t required if preserving hinting +information doesn’t matter, like with rotated text). Usually, this means +translating with a vector ( -ROUND(xMin), -ROUND(yMin) ).
    • +
    + +
      +
    • +Call the function FT_Get_Outline_Bitmap.
    • +
    + +


    In the case where one wants to write glyph images directly into +a large bitmap, the outlines must be translated so that their vectorial +position correspond to the current text cursor/character origin.

    +
    + +

    + +

    + +

    +VII. FreeType anti-aliasing :

    +IMPORTANT NOTE : +
    This section is still in progress, as the way FreeType 2 handles anti-aliased +rendering hasn't been definitely set yet. The main reason being that a +flexible way of doing things is needed in order to allow further improvements +in the raster (i.e. number of gray levels > 100, etc..). +
    +

    +1. What is anti-aliasing :

    + +
    Anti-aliasing works by using various levels of grays to reduce +the "staircase" artefacts visible on the diagonals and curves of glyph +bitmaps. It is a way to artificially enhance the display resolution of +the target device. It can smooth out considerably displayed or printed +text.
    + +

    +2. How does it work with FreeType :

    + +
    FreeType's scan-line converter is able to produce anti-aliased +output directly. It is however limited to 8-bit pixmaps and 5 levels of +grays (or 17 levels, depending on a build configuration option). Here's +how one should use it : +

    +a. Set the gray-level palette :

    + +
    The scan-line converter uses 5 levels for anti-aliased output. +Level 0 corresponds to the text background color (e.g. white), and level +5 to the text foreground color. Intermediate levels are used for intermediate +shades of grays. +

    You must set the raster's palette when you want to use different colors, +use the function FT_Raster_Set_Palette as in : +

    { +
      static const char  gray_palette[5] = { 0, 7, 15, 31, +63 }; +
      … +
      error = FT_Set_Raster_Palette( library, 5, palette ); +
    } +
      +

      +
    • +The first parameter is a handle to a FreeType library object. See the user +guide for more details (the library contains a scan-line converter object).
    • +
    + +
      +
    • +The second parameter is the number of entries in the gray-level palette. +Valid values are 5 and 17 for now, but this may change in later implementations.
    • +
    + +
      +
    • +The last parameter is a pointer to a char table containing the pixel value +for each of the gray-levels. In this example, we use a background color +of 0, a foreground color of 63, and intermediate values in-between.
    • +
    + +


    The palette is copied in the raster object, as well as processed +to build several lookup-tables necessary for the internal anti-aliasing +algorithm. +
     

    + +

    +b. Render the pixmap :

    + +
    The scan-line converter doesn't create bitmaps or pixmaps, +it simply renders into those that are passed as parameters to the function +FT_Get_Outline_Bitmap. +To render an anti-aliased pixmap, simply set the target bitmap’s depth +to 8. Note however that this target 8-bit pixmap must always have a 'cols' +field padded to 32-bits, which means that the number of bytes per lines +of the pixmap must be a multiple of 4 ! +

    Once the palette has been set, and the pixmap buffer has been created +to receive the glyph image, simply call FT_Get_Outline_Bitmap. +Take care of clearing the target pixmap with the background color before +calling this function. For the sake of simplicity and efficiency, the raster +is not able to compose anti-aliased glyph images on a pre-existing images. +

    Here's some code demonstrating how to load and render a single glyph +pixmap : +

    { +
      FT_Outline     outline; +
      FT_Raster_Map  pixmap; +
      FT_BBox        cbox; +
      … +

      // load the outline +
      … +

      // compute glyph dimensions (grid-fit cbox, etc..) +
      FT_Get_Outline_CBox( &outline, &cbox ); +

      cbox.xMin = cbox.xMin & -64;       +// floor(xMin) +
      cbox.yMin = cbox.yMin & -64;       +// floor(yMin) +
      cbox.xMax = (cbox.xMax+32) & -64;  // ceiling(xMax) +
      cbox.yMax = (cbox.yMax+32) & -64;  // ceiling(yMax) +

      pixmap.width = (cbox.xMax - cbox.xMin)/64; +
      pixmap.rows  = (cbox.yMax - cbox.yMin)/64; +

      // fill the pixmap descriptor and create the pixmap buffer +
      // don't forget to pad the 'cols' field to 32 bits +
      pixmap.pix_bits = 8; +
      pixmap.flow     = FT_Flow_Down; +
      pixmap.cols     = (pixmap.width+3) & +-4;  // pad 'cols' to 32 bits +
      pixmap.buffer   = malloc( pixmap.cols * pixmap.rows +); +

      // fill the pixmap buffer with the background color +
      // +
      memset( pixmap.buffer, 0, pixmap.cols*pixmap.rows ); +

      // translate the outline to match (0,0) with the glyph's +
      // lower left corner (ignore the bearings) +
      // the cbox is grid-fitted, we won't ruin the hinting. +
      // +
      FT_Translate_Outline( &outline, -cbox.xMin, -cbox.yMin +); +

      // render the anti-aliased glyph pixmap +
      error = FT_Get_Outline_Bitmap( library, &outline, &pixmap +); +

      // save the bearings for later use.. +
      corner_x = cbox.xMin / 64; +
      corner_y = cbox.yMin / 64; +
    } +

    The resulting pixmap is always anti-aliased.

    +
    + +

    +3. Possible enhancements :

    + +
    FreeType's raster (i.e. its scan-line converter) is currently +limited to producing either 1-bit bitmaps or anti-aliased 8-bit pixmaps. +It is not possible, for example, to draw directly a bitmapped glyph image +into a 4, 8 or 16-bit pixmap through a call to FT_Get_Outline_Bitmap. +

    Moreover, the anti-aliasing filter is limited to use 5 or 17 levels +of grays (through 2x2 and 4x4 sub-sampling). There are cases where this +could seem insufficient for optimal results and where a higher number of +levels like 64 or 128 would be a good thing. +

    These enhancements are all possible but not planned for an immediate +future of the FreeType engine.

    +
    + + + diff --git a/subsys/win32k/freetype/docs/glyphs/points_conic.png b/subsys/win32k/freetype/docs/glyphs/points_conic.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/points_conic.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/points_conic2.png b/subsys/win32k/freetype/docs/glyphs/points_conic2.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/points_conic2.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/points_cubic.png b/subsys/win32k/freetype/docs/glyphs/points_cubic.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/points_cubic.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/points_segment.png b/subsys/win32k/freetype/docs/glyphs/points_segment.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/points_segment.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/twlewis1.png b/subsys/win32k/freetype/docs/glyphs/twlewis1.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/twlewis1.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/twlewis2.png b/subsys/win32k/freetype/docs/glyphs/twlewis2.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/twlewis2.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/glyphs/up_flow.png b/subsys/win32k/freetype/docs/glyphs/up_flow.png new file mode 100644 index 0000000..f1ad755 --- /dev/null +++ b/subsys/win32k/freetype/docs/glyphs/up_flow.png @@ -0,0 +1 @@ +‰PNG diff --git a/subsys/win32k/freetype/docs/tutorial/index.html b/subsys/win32k/freetype/docs/tutorial/index.html new file mode 100644 index 0000000..fb8a5b3 --- /dev/null +++ b/subsys/win32k/freetype/docs/tutorial/index.html @@ -0,0 +1,871 @@ + + + + + + FreeType 2 Tutorial + + + + +

    + FreeType 2.0 Tutorial +

    + +

    + © 2000 David Turner + (david@freetype.org)
    + © 2000 The FreeType Development Team + (www.freetype.org) +

    + +
    + + +
    + +
    + +

    + Introduction +

    + +

    This short tutorial will teach you how to use the FreeType 2 + library in your own applications.

    + +
    + +

    + 1. Header files +

    + +

    To include the main FreeType header file, simply say

    + + +
    +    #include <freetype/freetype.h>
    +
    + +

    in your application code. Note that other files are available in the + FreeType include directory, most of them being included by + "freetype.h". They will be described later in this + tutorial.

    + +
    + +

    + 2. Initialize the library +

    + +

    Simply create a variable of type FT_Library named, for + example, library, and call the function + FT_Init_FreeType() as in

    + + +
    +    #include <freetype/freetype.h>
    +
    +    FT_Library  library;
    +
    +    ...
    +
    +    {
    +      ...
    +      error = FT_Init_FreeType( &library );
    +      if ( error )
    +      {
    +        ... an error occurred during library initialization ...
    +      }
    +    }
    +
    + +

    This function is in charge of the following:

    + +
      +
    • +

      Creating a new instance of the FreeType 2 library, and set + the handle library to it.

      +
    • +
    • +

      Load each modules that FreeType knows about in the library. + This means that by default, your new library object is able + to handle TrueType, Type 1, CID-keyed & OpenType/CFF fonts + gracefully.

      +
    • +
    + +

    As you can see, the function returns an error code, like most others + in the FreeType API. An error code of 0 always means that + the operation was successful; otherwise, the value describes the error, + and library is set to NULL.

    + +
    + +

    + 3. Load a font face +

    + +

    + a. From a font file +

    + +

    Create a new face object by calling FT_New_Face. + A face describes a given typeface and style. For example, + "Times New Roman Regular" and "Times New Roman Italic" correspond to + two different faces.

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Face( library,
    +                         "/usr/share/fonts/truetype/arial.ttf",
    +                         0,
    +                         &face );
    +    if ( error == FT_Err_Unknown_File_Format )
    +    {
    +      ... the font file could be opened and read, but it appears
    +      ... that its font format is unsupported
    +    }
    +    else if ( error )
    +    {
    +      ... another error code means that the font file could not
    +      ... be opened or read, or simply that it is broken...
    +    }
    +
    + +

    As you can certainly imagine, FT_New_Face opens a font + file, then tries to extract one face from it. Its parameters are

    + + + + + + + + + + + + + + + + + + +
    + library + +

    handle to the FreeType library instance where the face object + is created

    +
    + filepathname + +

    the font file pathname (standard C string).

    +
    + face_index + +

    Certain font formats allow several font faces to be embedded + in a single file.

    + +

    This index tells which face you want to load. An error will + be returned if its value is too large.

    + +

    Index 0 always work though.

    +
    + face + +

    A pointer to the handle that will be set to describe + the new face object.

    + +

    It is set to NULL in case of error.

    +
    + +

    To know how many faces a given font file contains, simply load its + first face (use face_index=0), then see the value of + face->num_faces which indicates how many faces are embedded + in the font file.

    + +

    + b. From memory +

    + +

    In the case where you have already loaded the font file in memory, + you can similarly create a new face object for it by calling + FT_New_Memory_Face as in

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Memory_Face( library,
    +                                buffer,    /* first byte in memory */
    +                                size,      /* size in bytes        */
    +                                0,         /* face_index           */
    +                                &face );
    +    if ( error ) { ... }
    +
    + +

    As you can see, FT_New_Memory_Face() simply takes a + pointer to the font file buffer and its size in bytes instead of a + file pathname. Other than that, it has exactly the same semantics as + FT_New_Face().

    + +

    + c. From other sources (compressed files, network, etc.) +

    + +

    There are cases where using a file pathname or preloading the file + in memory is simply not enough. With FreeType 2, it is possible + to provide your own implementation of i/o routines.

    + +

    This is done through the FT_Open_Face() function, which + can be used to open a new font face with a custom input stream, select + a specific driver for opening, or even pass extra parameters to the + font driver when creating the object. We advise you to refer to the + FreeType 2 reference manual in order to learn how to use it.

    + +

    Note that providing a custom stream might also be used to access a + TrueType font embedded in a Postscript Type 42 wrapper.

    + +
    + +

    + 4. Accessing face content +

    + +

    A face object models all information that globally describes + the face. Usually, this data can be accessed directly by dereferencing + a handle, like

    + + + + + + + + + + + + + + + + + + + + + + +
    + face->num_glyphs + +

    Gives the number of glyphs available in the font face. + A glyph is simply a character image. It doesn't necessarily + correspond to a character code though.

    +
    + face->flags + +

    A 32-bit integer containing bit flags used to describe some + face properties. For example, the flag + FT_FACE_FLAG_SCALABLE is used to indicate that the face's + font format is scalable and that glyph images can be rendered for + all character pixel sizes. For more information on face flags, + please read the FreeType 2 API Reference.

    +
    + face->units_per_EM + +

    This field is only valid for scalable formats (it is set to 0 + otherwise). It indicates the number of font units covered by the + EM.

    +
    + face->num_fixed_sizes + +

    This field gives the number of embedded bitmap strikes + in the current face. A strike is simply a series of + glyph images for a given character pixel size. For example, a + font face could include strikes for pixel sizes 10, 12 + and 14. Note that even scalable font formats can have + embedded bitmap strikes!

    +
    + face->fixed_sizes + +

    this is a pointer to an array of FT_Bitmap_Size + elements. Each FT_Bitmap_Size indicates the horizontal + and vertical pixel sizes for each of the strikes that are + present in the face.

    +
    + +

    For a complete listing of all face properties and fields, please read + the FreeType 2 API Reference.

    + +


    + +

    + 5. Setting the current pixel size +

    + +

    FreeType 2 uses "size objects" to model all + information related to a given character size for a given face. + For example, a size object will hold the value of certain metrics + like the ascender or text height, expressed in 1/64th of a pixel, + for a character size of 12 points.

    + +

    When the FT_New_Face function is called (or one of its + cousins), it automatically creates a new size object for + the returned face. This size object is directly accessible as + face->size.

    + +

    NOTA BENE: a single face object can deal with one or more size + objects at a time, however, this is something that few programmers + really need to do. We have thus have decided to simplify the API for + the most common use (i.e. one size per face), while keeping this + feature available through additional fuctions.

    + +

    When a new face object is created, its size object defaults to the + character size of 10 pixels (both horizontally and vertically) for + scalable formats. For fixed-sizes formats, the size is more or less + undefined, which is why you must set it before trying to load a + glyph.

    + +

    To do that, simply call FT_Set_Char_Size(). Here is an + example where the character size is set to 16pt for a 300x300 dpi + device:

    + + +
    +    error = FT_Set_Char_Size(
    +              face,    /* handle to face object           */
    +              0,       /* char_width in 1/64th of points  */
    +              16*64,   /* char_height in 1/64th of points */
    +              300,     /* horizontal device resolution    */
    +              300 );   /* vertical device resolution      */
    +
    + +

    You will notice that:

    + +
      +
    • +

      The character width and heights are specified in 1/64th of + points. A point is a physical distance, equaling 1/72th + of an inch, it's not a pixel..

      +

    • +
    • +

      The horizontal and vertical device resolutions are expressed in + dots-per-inch, or dpi. You can use 72 or + 96 dpi for display devices like the screen. The resolution + is used to compute the character pixel size from the character + point size.

      +
    • +
    • +

      A value of 0 for the character width means "same as + character height", a value of 0 for the character height + means "same as character width". Otherwise, it is possible + to specify different char widths and heights.

      +
    • +
    • +

      Using a value of 0 for the horizontal or vertical resolution means + 72 dpi, which is the default.

      +
    • +
    • +

      The first argument is a handle to a face object, not a size + object. That's normal, and must be seen as a convenience.

      +
    • +
    + +

    This function computes the character pixel size that corresponds to + the character width and height and device resolutions. However, if you + want to specify the pixel sizes yourself, you can simply call + FT_Set_Pixel_Sizes(), as in

    + + +
    +    error = FT_Set_Pixel_Sizes(
    +              face,   /* handle to face object            */
    +              0,      /* pixel_width                      */
    +              16 );   /* pixel_height                     */
    +
    + +

    This example will set the character pixel sizes to 16x16 pixels. + As previously, a value of 0 for one of the dimensions means + "same as the other".

    + +

    Note that both functions return an error code. Usually, an error + occurs with a fixed-size font format (like FNT or PCF) when trying to + set the pixel size to a value that is not listed in the + face->fixed_sizes array.

    + +
    + +

    + 6. Loading a glyph image +

    + +

    + a. Converting a character code into a glyph index +

    + +

    Usually, an application wants to load a glyph image based on its + character code, which is a unique value that defines the + character for a given encoding. For example, the character + code 65 represents the `A' in ASCII encoding.

    + +

    A face object contains one or more tables, called + charmaps, that are used to convert character codes to glyph + indices. For example, most TrueType fonts contain two charmaps. One + is used to convert Unicode character codes to glyph indices, the other + is used to convert Apple Roman encoding into glyph indices. Such + fonts can then be used either on Windows (which uses Unicode) and + Macintosh (which uses Apple Roman, bwerk). Note also that a given + charmap might not map to all the glyphs present in the font.

    + +

    By default, when a new face object is created, it lists all the + charmaps contained in the font face and selects the one that supports + Unicode character codes if it finds one. Otherwise, it tries to find + support for Latin-1, then ASCII.

    + +

    We will describe later how to look for specific charmaps in a face. + For now, we will assume that the face contains at least a Unicode + charmap that was selected during FT_New_Face(). To convert a + Unicode character code to a font glyph index, we use + FT_Get_Char_Index() as in

    + + +
    +    glyph_index = FT_Get_Char_Index( face, charcode );
    +
    + +

    This will look the glyph index corresponding to the given + charcode in the charmap that is currently selected for the + face. If charmap is selected, the function simply returns the + charcode.

    + +

    Note that this is one of the rare FreeType functions that do not + return an error code. However, when a given character code has no + glyph image in the face, the value 0 is returned. By convention, + it always correspond to a special glyph image called the missing + glyph, which usually is represented as a box or a space.

    + +

    + b. Loading a glyph from the face +

    + +

    Once you have a glyph index, you can load the corresponding glyph + image. Note that the glyph image can be in several formats. For + example, it will be a bitmap for fixed-size formats like FNT, FON, or + PCF. It will also be a scalable vector outline for formats like + TrueType or Type 1. The glyph image can also be stored in an + alternate way that is not known at the time of writing this + documentation.

    + +

    The glyph image is always stored in a special object called a + glyph slot. As its name suggests, a glyph slot is simply a + container that is able to hold one glyph image at a time, be it a + bitmap, an outline, or something else. Each face object has a single + glyph slot object that can be accessed as + face->glyph.

    + +

    Loading a glyph image into the slot is performed by calling + FT_Load_Glyph() as in

    + + +
    +    error = FT_Load_Glyph( 
    +              face,          /* handle to face object */
    +              glyph_index,   /* glyph index           */
    +              load_flags );  /* load flags, see below */
    +
    + +

    The load_flags value is a set of bit flags used to + indicate some special operations. The default value + FT_LOAD_DEFAULT is 0.

    + +

    This function will try to load the corresponding glyph image + from the face. Basically, this means that:

    + +
      +
    • +

      If a bitmap is found for the corresponding glyph and pixel + size, it will in the slot (embedded bitmaps are always + favored over native image formats, because we assume that + they are higher-quality versions of the same image. This + can be ignored by using the FT_LOAD_NO_BITMAP flag)

      +
    • + +
    • +

      Otherwise, a native image for the glyph will be loaded. + It will also be scaled to the current pixel size, as + well as hinted for certain formats like TrueType and + Type1.

      +
    • +
    + +

    The field glyph->format describe the format + used to store the glyph image in the slot. If it is not + ft_glyph_format_bitmap, one can immediately + convert it to a bitmap through FT_Render_Glyph, + as in:

    + + +
    +   error = FT_Render_Glyph(
    +                  face->glyph,      /* glyph slot  */
    +		  render_mode );    /* render mode */
    +      
    +
    + +

    The parameter render_mode is a set of bit flags used + to specify how to render the glyph image. Set it to 0 to render + a monochrome bitmap, or to ft_render_mode_antialias to + generate a high-quality (256 gray levels) anti-aliased bitmap + from the glyph image.

    + +

    Once you have a bitmap glyph image, you can access it directly + through glyph->bitmap (a simple bitmap descriptor), + and position it through glyph->bitmap_left and + glyph->bitmap_top.

    + +

    Note that bitmap_left is the horizontal distance from the + current pen position to the left-most border of the glyph bitmap, + while bitmap_top is the vertical distance from the + pen position (on the baseline) to the top-most border of the + glyph bitmap. It is positive to indicate an upwards + distance.

    + +

    The next section will detail the content of a glyph slot and + how to access specific glyph information (including metrics).

    + +

    + c. Using other charmaps +

    + +

    As said before, when a new face object is created, it will look for + a Unicode, Latin-1, or ASCII charmap and select it. The currently + selected charmap is accessed via face->charmap. This + field is NULL when no charmap is selected, which typically happens + when you create a new FT_Face object from a font file that + doesn't contain an ASCII, Latin-1, or Unicode charmap (rare + stuff).

    + +

    There are two ways to select a different charmap with FreeType 2. + The easiest is when the encoding you need already has a corresponding + enumeration defined in <freetype/freetype.h>, as + ft_encoding_big5. In this case, you can simply call + FT_Select_CharMap as in:

    + +
    +    error = FT_Select_CharMap(
    +                    face,                 /* target face object */
    +		    ft_encoding_big5 );   /* encoding..         */
    +      
    + +

    Another way is to manually parse the list of charmaps for the + face, this is accessible through the fields + num_charmaps and charmaps + (notice the 's') of the face object. As you could expect, + the first is the number of charmaps in the face, while the + second is a table of pointers to the charmaps + embedded in the face.

    + +

    Each charmap has a few visible fields used to describe it more + precisely. Mainly, one will look at + charmap->platform_id and + charmap->encoding_id that define a pair of + values that can be used to describe the charmap in a rather + generic way.

    + +

    Each value pair corresponds to a given encoding. For example, + the pair (3,1) corresponds to Unicode. Their list is + defined in the TrueType specification but you can also use the + file <freetype/ftnameid.h> which defines several + helpful constants to deal with them..

    + +

    To look for a specific encoding, you need to find a corresponding + value pair in the specification, then look for it in the charmaps + list. Don't forget that some encoding correspond to several + values pair (yes it's a real mess, but blame Apple and Microsoft + on such stupidity..). Here's some code to do it:

    + + +
    +    FT_CharMap  found = 0;
    +    FT_CharMap  charmap;
    +    int         n;
    +
    +    for ( n = 0; n < face->num_charmaps; n++ )
    +    {
    +      charmap = face->charmaps[n];
    +      if ( charmap->platform_id == my_platform_id &&
    +           charmap->encoding_id == my_encoding_id )
    +      {
    +        found = charmap;
    +        break;
    +      }
    +    }
    +
    +    if ( !found ) { ... }
    +
    +    /* now, select the charmap for the face object */
    +    error = FT_Set_CharMap( face, found );
    +    if ( error ) { ... }
    +
    + +

    Once a charmap has been selected, either through + FT_Select_CharMap or FT_Set_CharMap, + it is used by all subsequent calls to + FT_Get_Char_Index().

    + + +

    + d. Glyph Transforms: +

    + +

    It is possible to specify an affine transformation to be applied + to glyph images when they're loaded. Of course, this will only + work for scalable (vectorial) font formats.

    + +

    To do that, simply call FT_Set_Transform, as in:

    + +
    +   error = FT_Set_Transform(
    +                    face,           /* target face object    */
    +		    &matrix,    /* pointer to 2x2 matrix */
    +		    &delta );   /* pointer to 2d vector  */
    +     
    + +

    This function will set the current transform for a given face + object. Its second parameter is a pointer to a simple + FT_Matrix structure that describes a 2x2 affine matrix. + The third parameter is a pointer to a FT_Vector structure + that describe a simple 2d vector.

    + +

    Note that the matrix pointer can be set to NULL, (in which case + the identity transform will be used). Coefficients of the matrix + are in 16.16 fixed float units.

    + +

    The vector pointer can also be set to NULL (in which case a delta + of (0,0) will be used). The vector coordinates are expressed in + 1/64th of a pixel (also known as 26.6 fixed floats).

    + +

    NOTA BENE: The transform is applied every glyph that is loaded + through FT_Load_Glyph. Note that loading a glyph bitmap + with a non-trivial transform will produce an error..

    + +
    + +

    + 7. Accessing glyph image data +

    + +

    Glyph image data is accessible through face->glyph. + See the definition of the FT_GlyphSlot type for more details. + As stated previously, each face has a single glyph slot, where + one glyph image at a time can be loaded. Each time + you call FT_Load_Glyph(), you erase the content of the glyph + slot with a new glyph image.

    + +

    Note however that the glyph slot object itself doesn't change, only + its content, which means that you can perfectly create a "shortcut" to + access it as in

    + + +
    +    {
    +      /* shortcut to glyph slot */
    +      FT_GlyphSlot  glyph = face->glyph;
    +
    +      for ( n = 0; n < face->num_glyphs; n++ )
    +      {
    +        ... load glyph n ...
    +        ... access glyph data as glyph->xxxx
    +      }
    +    }
    +
    + +

    The glyph variable will be valid until its parent + face is destroyed. Here are a few important fields of the + glyph slot:

    + + + + + + + + + + + + + + + + + + +
    + glyph->format + +

    Indicates the type of the loaded glyph image. Can be either + ft_glyph_format_bitmap, ft_glyph_format_outline, + or other values.

    +
    + glyph->metrics + +

    A simple structure used to hold the glyph image's metrics. + Note that most distances are expressed in 1/64th of + pixels! See the API reference or the user guide for a + description of the FT_Glyph_Metrics structure.

    +
    + glyph->bitmap + +

    If the glyph slot contains a bitmap, a simple + FT_Bitmap that describes it. See the API reference or + user guide for a description of the FT_Bitmap + structure.

    +
    + glyph->outline + +

    When the glyph slot contains a scalable outline, this structure + describes it. See the definition of the FT_Outline + structure.

    +
    + +

    + 8. Rendering glyph outlines into bitmaps +

    + +

    You can easily test the format of the glyph image by inspecting the + face->glyph->format variable. If its value is + ft_glyph_format_bitmap, the glyph image that was loaded is a + bitmap that can be directly blit to your own surfaces through your + favorite graphics library (FreeType 2 doesn't provide bitmap + blitting routines, as you may imagine :-)

    + +

    If the format is ft_glyph_format_outline or something else, + the library provides a means to convert such glyph images to bitmaps + through what are called rasters.

    + +

    On the other hand, if the image is a scalable outline or something + else, FreeType provides a function to convert the glyph image into a + pre-existing bitmap that you will handle to it, named + FT_Get_Glyph_Bitmap. Here's a simple example code + that renders an outline into a monochrome bitmap:

    + + +
    +    {
    +      FT_GlyphSlot  glyph;
    +
    +      ... load glyph ...
    +
    +      glyph = face->glyph;   /* shortcut to glyph data */
    +      if ( glyph->format == ft_glyph_format_outline )
    +      {
    +        FT_Bitmap  bit;
    +
    +        /* set-up a bitmap descriptor for our target bitmap */
    +        bit.rows       = bitmap_height;
    +        bit.width      = bitmap_width;
    +        bit.pitch      = bitmap_row_bytes;
    +        /* render into a mono bitmap */
    +        bit.pixel_mode = ft_pixel_mode_mono;
    +        bit.buffer     = bitmap_buffer;
    +
    +        /* render the outline directly into the bitmap */
    +        error = FT_Get_Glyph_Bitmap( face, &bit );
    +        if ( error ) { ... }
    +      }
    +    }
    +
    + +

    You should note that FT_Get_Glyph_Bitmap() doesn't + create the bitmap. It only needs a descriptor, of type + FT_Bitmap, and writes directly into it.

    + +

    Note that the FreeType scan-converter for outlines can also generate + anti-aliased glyph bitmaps with 128 level of grays. For now, it is + restricted to rendering to 8-bit gray-level bitmaps, though this may + change in the future. Here is some code to do just that:

    + + +
    +    {
    +      FT_GlyphSlot  glyph;
    +
    +      ... load glyph ...
    +
    +      glyph = face->glyph;   /* shortcut to glyph data */
    +      if ( glyph->format == ft_glyph_format_outline )
    +      {
    +        FT_Bitmap  bit;
    +
    +        /* set-up a bitmap descriptor for our target bitmap */
    +        bit.rows       = bitmap_height;
    +        bit.width      = bitmap_width;
    +        bit.pitch      = bitmap_row_bytes;
    +        /* 8-bit gray-level bitmap */
    +        bit.pixel_mode = ft_pixel_mode_gray;
    +        /* MUST be 128 for now     */
    +        bit.grays      = 128;
    +        bit.buffer     = bitmap_buffer;
    +
    +        /* clean the bitmap - IMPORTANT */
    +        memset( bit.buffer, 0, bit.rows*bit.pitch );
    +
    +        /* render the outline directly into the bitmap */
    +        error = FT_Get_Glyph_Bitmap( face, &bit );
    +        if ( error ) { ... }
    +      }
    +    }
    +
    + +

    You will notice that

    + +
      +
    • +

      As previously, FT_Get_Glyph_Bitmap() doesn't generate + the bitmap, it simply renders to it.

      +
    • +
    • +

      The target bitmap must be cleaned before calling the function. + This is a limitation of our current anti-aliasing algorithm and is + EXTREMELY important.

      +
    • +
    • +

      The anti-aliaser uses 128 levels of grays exclusively for + now (this will probably change in a near future). This means that + you must set bit.grays to 128. The generated + image uses values from 0 (back color) to 127 (foreground color).

      +
    • +
    • +

      It is not possible to render directly an anti-aliased + outline into a pre-existing gray-level bitmap, or even any + colored-format one (like RGB16 or paletted 8-bits). We will not + discuss this issue in great details here, but the reason is that we + do not want to deal with graphics composition (or alpha-blending) + within FreeType.

      +

    • +
    +
    +
    + + + diff --git a/subsys/win32k/freetype/docs/tutorial/step1.html b/subsys/win32k/freetype/docs/tutorial/step1.html new file mode 100644 index 0000000..e184be7 --- /dev/null +++ b/subsys/win32k/freetype/docs/tutorial/step1.html @@ -0,0 +1,956 @@ + + + + + + FreeType 2 Tutorial + + + + +

    + FreeType 2.0 Tutorial
    + Step 1 - simple glyph loading +

    + +

    + © 2000 David Turner + (david@freetype.org)
    + © 2000 The FreeType Development Team + (www.freetype.org) +

    + +
    + + +
    + +
    + +

    + Introduction +

    + +

    This is the first section of the FreeType 2 tutorial. It will teach + you to do the following:

    + +
      +
    • initialise the library
    • +
    • open a font file by creating a new face object
    • +
    • select a character size in points or in pixels
    • +
    • load a single glyph image and convert it to a bitmap
    • +
    • render a very simple string of text
    • +
    • render a rotated string of text easily
    • +
    + +
    + +

    + 1. Header files +

    + +

    To include the main FreeType header file, simply say

    + + +
    +    #include <freetype/freetype.h>
    +
    + +

    in your application code. Note that other files are available in the + FreeType include directory, most of them being included by + "freetype.h". They will be described later in this + tutorial.

    + +
    + +

    + 2. Initialize the library +

    + +

    Simply create a variable of type FT_Library named, for + example, library, and call the function + FT_Init_FreeType() as in

    + + +
    +    #include <freetype/freetype.h>
    +
    +    FT_Library  library;
    +
    +    ...
    +
    +    {
    +      ...
    +      error = FT_Init_FreeType( &library );
    +      if ( error )
    +      {
    +        ... an error occurred during library initialization ...
    +      }
    +    }
    +
    + +

    This function is in charge of the following:

    + +
      +
    • +

      Creating a new instance of the FreeType 2 library, and set + the handle library to it.

      +
    • +
    • +

      Load each modules that FreeType knows about in the library. + This means that by default, your new library object is able + to handle TrueType, Type 1, CID-keyed & OpenType/CFF fonts + gracefully.

      +
    • +
    + +

    As you can see, the function returns an error code, like most others + in the FreeType API. An error code of 0 always means that + the operation was successful; otherwise, the value describes the error, + and library is set to NULL.

    + +
    + +

    + 3. Load a font face +

    + +

    + a. From a font file +

    + +

    Create a new face object by calling FT_New_Face. + A face describes a given typeface and style. For example, + "Times New Roman Regular" and "Times New Roman Italic" correspond to + two different faces.

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Face( library,
    +                         "/usr/share/fonts/truetype/arial.ttf",
    +                         0,
    +                         &face );
    +    if ( error == FT_Err_Unknown_File_Format )
    +    {
    +      ... the font file could be opened and read, but it appears
    +      ... that its font format is unsupported
    +    }
    +    else if ( error )
    +    {
    +      ... another error code means that the font file could not
    +      ... be opened or read, or simply that it is broken...
    +    }
    +
    + +

    As you can certainly imagine, FT_New_Face opens a font + file, then tries to extract one face from it. Its parameters are

    + + + + + + + + + + + + + + + + + + +
    + library + +

    handle to the FreeType library instance where the face object + is created

    +
    + filepathname + +

    the font file pathname (standard C string).

    +
    + face_index + +

    Certain font formats allow several font faces to be embedded + in a single file.

    + +

    This index tells which face you want to load. An error will + be returned if its value is too large.

    + +

    Index 0 always work though.

    +
    + face + +

    A pointer to the handle that will be set to describe + the new face object.

    + +

    It is set to NULL in case of error.

    +
    + +

    To know how many faces a given font file contains, simply load its + first face (use face_index=0), then see the value of + face->num_faces which indicates how many faces are embedded + in the font file.

    + +

    + b. From memory +

    + +

    In the case where you have already loaded the font file in memory, + you can similarly create a new face object for it by calling + FT_New_Memory_Face as in

    + + +
    +    FT_Library   library;   /* handle to library     */
    +    FT_Face      face;      /* handle to face object */
    +
    +    error = FT_Init_FreeType( &library );
    +    if ( error ) { ... }
    +
    +    error = FT_New_Memory_Face( library,
    +                                buffer,    /* first byte in memory */
    +                                size,      /* size in bytes        */
    +                                0,         /* face_index           */
    +                                &face );
    +    if ( error ) { ... }
    +
    + +

    As you can see, FT_New_Memory_Face() simply takes a + pointer to the font file buffer and its size in bytes instead of a + file pathname. Other than that, it has exactly the same semantics as + FT_New_Face().

    + +

    + c. From other sources (compressed files, network, etc.) +

    + +

    There are cases where using a file pathname or preloading the file + in memory is simply not enough. With FreeType 2, it is possible + to provide your own implementation of i/o routines.

    + +

    This is done through the FT_Open_Face() function, which + can be used to open a new font face with a custom input stream, select + a specific driver for opening, or even pass extra parameters to the + font driver when creating the object. We advise you to refer to the + FreeType 2 reference manual in order to learn how to use it.

    + +

    Note that providing a custom stream might also be used to access a + TrueType font embedded in a Postscript Type 42 wrapper.

    + +
    + +

    + 4. Accessing face content +

    + +

    A face object models all information that globally describes + the face. Usually, this data can be accessed directly by dereferencing + a handle, like

    + + + + + + + + + + + + + + + + + + + + + + +
    + face->num_glyphs + +

    Gives the number of glyphs available in the font face. + A glyph is simply a character image. It doesn't necessarily + correspond to a character code though.

    +
    + face->flags + +

    A 32-bit integer containing bit flags used to describe some + face properties. For example, the flag + FT_FACE_FLAG_SCALABLE is used to indicate that the face's + font format is scalable and that glyph images can be rendered for + all character pixel sizes. For more information on face flags, + please read the FreeType 2 API Reference.

    +
    + face->units_per_EM + +

    This field is only valid for scalable formats (it is set to 0 + otherwise). It indicates the number of font units covered by the + EM.

    +
    + face->num_fixed_sizes + +

    This field gives the number of embedded bitmap strikes + in the current face. A strike is simply a series of + glyph images for a given character pixel size. For example, a + font face could include strikes for pixel sizes 10, 12 + and 14. Note that even scalable font formats can have + embedded bitmap strikes!

    +
    + face->fixed_sizes + +

    this is a pointer to an array of FT_Bitmap_Size + elements. Each FT_Bitmap_Size indicates the horizontal + and vertical pixel sizes for each of the strikes that are + present in the face.

    +
    + +

    For a complete listing of all face properties and fields, please read + the FreeType 2 API Reference.

    + +


    + +

    + 5. Setting the current pixel size +

    + +

    FreeType 2 uses "size objects" to model all + information related to a given character size for a given face. + For example, a size object will hold the value of certain metrics + like the ascender or text height, expressed in 1/64th of a pixel, + for a character size of 12 points.

    + +

    When the FT_New_Face function is called (or one of its + cousins), it automatically creates a new size object for + the returned face. This size object is directly accessible as + face->size.

    + +

    NOTA BENE: a single face object can deal with one or more size + objects at a time, however, this is something that few programmers + really need to do. We have thus have decided to simplify the API for + the most common use (i.e. one size per face), while keeping this + feature available through additional fuctions.

    + +

    When a new face object is created, its size object defaults to the + character size of 10 pixels (both horizontally and vertically) for + scalable formats. For fixed-sizes formats, the size is more or less + undefined, which is why you must set it before trying to load a + glyph.

    + +

    To do that, simply call FT_Set_Char_Size(). Here is an + example where the character size is set to 16pt for a 300x300 dpi + device:

    + + +
    +    error = FT_Set_Char_Size(
    +              face,    /* handle to face object           */
    +              0,       /* char_width in 1/64th of points  */
    +              16*64,   /* char_height in 1/64th of points */
    +              300,     /* horizontal device resolution    */
    +              300 );   /* vertical device resolution      */
    +
    + +

    You will notice that:

    + +
      +
    • +

      The character width and heights are specified in 1/64th of + points. A point is a physical distance, equaling 1/72th + of an inch, it's not a pixel..

      +

    • +
    • +

      The horizontal and vertical device resolutions are expressed in + dots-per-inch, or dpi. You can use 72 or + 96 dpi for display devices like the screen. The resolution + is used to compute the character pixel size from the character + point size.

      +
    • +
    • +

      A value of 0 for the character width means "same as + character height", a value of 0 for the character height + means "same as character width". Otherwise, it is possible + to specify different char widths and heights.

      +
    • +
    • +

      Using a value of 0 for the horizontal or vertical resolution means + 72 dpi, which is the default.

      +
    • +
    • +

      The first argument is a handle to a face object, not a size + object. That's normal, and must be seen as a convenience.

      +
    • +
    + +

    This function computes the character pixel size that corresponds to + the character width and height and device resolutions. However, if you + want to specify the pixel sizes yourself, you can simply call + FT_Set_Pixel_Sizes(), as in

    + + +
    +    error = FT_Set_Pixel_Sizes(
    +              face,   /* handle to face object            */
    +              0,      /* pixel_width                      */
    +              16 );   /* pixel_height                     */
    +
    + +

    This example will set the character pixel sizes to 16x16 pixels. + As previously, a value of 0 for one of the dimensions means + "same as the other".

    + +

    Note that both functions return an error code. Usually, an error + occurs with a fixed-size font format (like FNT or PCF) when trying to + set the pixel size to a value that is not listed in the + face->fixed_sizes array.

    + +
    + +

    + 6. Loading a glyph image +

    + +

    + a. Converting a character code into a glyph index +

    + +

    Usually, an application wants to load a glyph image based on its + character code, which is a unique value that defines the + character for a given encoding. For example, the character + code 65 represents the `A' in ASCII encoding.

    + +

    A face object contains one or more tables, called + charmaps, that are used to convert character codes to glyph + indices. For example, most TrueType fonts contain two charmaps. One + is used to convert Unicode character codes to glyph indices, the other + is used to convert Apple Roman encoding into glyph indices. Such + fonts can then be used either on Windows (which uses Unicode) and + Macintosh (which uses Apple Roman, bwerk). Note also that a given + charmap might not map to all the glyphs present in the font.

    + +

    By default, when a new face object is created, it lists all the + charmaps contained in the font face and selects the one that supports + Unicode character codes if it finds one. Otherwise, it tries to find + support for Latin-1, then ASCII.

    + +

    We will describe later how to look for specific charmaps in a face. + For now, we will assume that the face contains at least a Unicode + charmap that was selected during FT_New_Face(). To convert a + Unicode character code to a font glyph index, we use + FT_Get_Char_Index() as in

    + + +
    +    glyph_index = FT_Get_Char_Index( face, charcode );
    +
    + +

    This will look the glyph index corresponding to the given + charcode in the charmap that is currently selected for the + face. If charmap is selected, the function simply returns the + charcode.

    + +

    Note that this is one of the rare FreeType functions that do not + return an error code. However, when a given character code has no + glyph image in the face, the value 0 is returned. By convention, + it always correspond to a special glyph image called the missing + glyph, which usually is represented as a box or a space.

    + +

    + b. Loading a glyph from the face +

    + +

    Once you have a glyph index, you can load the corresponding glyph + image. The latter can be stored in various formats within the font file. + For fixed-size formats like FNT or PCF, each image is a bitmap. Scalable + formats like TrueType or Type 1 use vectorial shapes, named "outlines" + to describe each glyph. Some formats may have even more exotic ways + of representing glyph (e.g. MetaFont). Fortunately, FreeType 2 is + flexible enough to support any kind of glyph format through + a simple API.

    + +

    The glyph image is always stored in a special object called a + glyph slot. As its name suggests, a glyph slot is simply a + container that is able to hold one glyph image at a time, be it a + bitmap, an outline, or something else. Each face object has a single + glyph slot object that can be accessed as + face->glyph.

    + +

    Loading a glyph image into the slot is performed by calling + FT_Load_Glyph() as in

    + + +
    +    error = FT_Load_Glyph( 
    +              face,          /* handle to face object */
    +              glyph_index,   /* glyph index           */
    +              load_flags );  /* load flags, see below */
    +
    + +

    The load_flags value is a set of bit flags used to + indicate some special operations. The default value + FT_LOAD_DEFAULT is 0.

    + +

    This function will try to load the corresponding glyph image + from the face. Basically, this means that:

    + +
      +
    • +

      If a bitmap is found for the corresponding glyph and pixel + size, it will be loaded into the slot (embedded bitmaps are always + favored over native image formats, because we assume that + they are higher-quality versions of the same glyph. This + can be ignored by using the FT_LOAD_NO_BITMAP flag)

      +
    • + +
    • +

      Otherwise, a native image for the glyph will be loaded. + It will also be scaled to the current pixel size, as + well as hinted for certain formats like TrueType and + Type1.

      +
    • +
    + +

    The field glyph->format describe the format + used to store the glyph image in the slot. If it is not + ft_glyph_format_bitmap, one can immediately + convert it to a bitmap through FT_Render_Glyph, + as in:

    + + +
    +   error = FT_Render_Glyph(
    +                  face->glyph,      /* glyph slot  */
    +                  render_mode );    /* render mode */
    +      
    +
    + +

    The parameter render_mode is a set of bit flags used + to specify how to render the glyph image. Set it to 0, or the + equivalent ft_render_mode_normal to render a high-quality + anti-aliased (256 gray levels) bitmap, as this is the default. + You can alternatively use ft_render_mode_mono if you + want to generate a 1-bit monochrome bitmap.

    + +

    Once you have a bitmapped glyph image, you can access it directly + through glyph->bitmap (a simple bitmap descriptor), + and position it through glyph->bitmap_left and + glyph->bitmap_top.

    + +

    Note that bitmap_left is the horizontal distance from the + current pen position to the left-most border of the glyph bitmap, + while bitmap_top is the vertical distance from the + pen position (on the baseline) to the top-most border of the + glyph bitmap. It is positive to indicate an upwards + distance.

    + +

    The next section will detail the content of a glyph slot and + how to access specific glyph information (including metrics).

    + +

    + c. Using other charmaps +

    + +

    As said before, when a new face object is created, it will look for + a Unicode, Latin-1, or ASCII charmap and select it. The currently + selected charmap is accessed via face->charmap. This + field is NULL when no charmap is selected, which typically happens + when you create a new FT_Face object from a font file that + doesn't contain an ASCII, Latin-1, or Unicode charmap (rare + stuff).

    + +

    There are two ways to select a different charmap with FreeType 2. + The easiest is when the encoding you need already has a corresponding + enumeration defined in <freetype/freetype.h>, as + ft_encoding_big5. In this case, you can simply call + FT_Select_CharMap as in:

    + +
    +    error = FT_Select_CharMap(
    +                    face,                 /* target face object */
    +                    ft_encoding_big5 );   /* encoding..         */
    +      
    + +

    Another way is to manually parse the list of charmaps for the + face, this is accessible through the fields + num_charmaps and charmaps + (notice the 's') of the face object. As you could expect, + the first is the number of charmaps in the face, while the + second is a table of pointers to the charmaps + embedded in the face.

    + +

    Each charmap has a few visible fields used to describe it more + precisely. Mainly, one will look at + charmap->platform_id and + charmap->encoding_id that define a pair of + values that can be used to describe the charmap in a rather + generic way.

    + +

    Each value pair corresponds to a given encoding. For example, + the pair (3,1) corresponds to Unicode. Their list is + defined in the TrueType specification but you can also use the + file <freetype/ftnameid.h> which defines several + helpful constants to deal with them..

    + +

    To look for a specific encoding, you need to find a corresponding + value pair in the specification, then look for it in the charmaps + list. Don't forget that some encoding correspond to several + values pair (yes it's a real mess, but blame Apple and Microsoft + on such stupidity..). Here's some code to do it:

    + + +
    +    FT_CharMap  found = 0;
    +    FT_CharMap  charmap;
    +    int         n;
    +
    +    for ( n = 0; n < face->num_charmaps; n++ )
    +    {
    +      charmap = face->charmaps[n];
    +      if ( charmap->platform_id == my_platform_id &&
    +           charmap->encoding_id == my_encoding_id )
    +      {
    +        found = charmap;
    +        break;
    +      }
    +    }
    +
    +    if ( !found ) { ... }
    +
    +    /* now, select the charmap for the face object */
    +    error = FT_Set_CharMap( face, found );
    +    if ( error ) { ... }
    +
    + +

    Once a charmap has been selected, either through + FT_Select_CharMap or FT_Set_CharMap, + it is used by all subsequent calls to + FT_Get_Char_Index().

    + + +

    + d. Glyph Transforms: +

    + +

    It is possible to specify an affine transformation to be applied + to glyph images when they're loaded. Of course, this will only + work for scalable (vectorial) font formats.

    + +

    To do that, simply call FT_Set_Transform, as in:

    + +
    +   error = FT_Set_Transform(
    +                    face,       /* target face object    */
    +                    &matrix,    /* pointer to 2x2 matrix */
    +                    &delta );   /* pointer to 2d vector  */
    +     
    + +

    This function will set the current transform for a given face + object. Its second parameter is a pointer to a simple + FT_Matrix structure that describes a 2x2 affine matrix. + The third parameter is a pointer to a FT_Vector structure + that describe a simple 2d vector that is used to translate the + glyph image after the 2x2 transform.

    + +

    Note that the matrix pointer can be set to NULL, (in which case + the identity transform will be used). Coefficients of the matrix + are otherwise in 16.16 fixed float units.

    + +

    The vector pointer can also be set to NULL (in which case a delta + of (0,0) will be used). The vector coordinates are expressed in + 1/64th of a pixel (also known as 26.6 fixed floats).

    + + +

    NOTA BENE: The transform is applied to every glyph that is loaded + through FT_Load_Glyph and is completely independent + of any hinting process. This means that you won't get the same + results if you load a glyph at the size of 24 pixels, or a glyph at + the size at 12 pixels scaled by 2 through a transform, because the + hints will have been computed differently (unless, of course you + disabled hints).

    + +

    If you ever need to use a non-orthogonal transform with optimal + hints, you first need to decompose your transform into a scaling part + and a rotation/shearing part. Use the scaling part to compute a new + character pixel size, then the other one to call FT_Set_Transform. + This is explained in details in a later section of this tutorial.

    + +

    Note also that loading a glyph bitmap with a non-identity transform + will produce an error..

    +
    + +

    + 7. Simple Text Rendering: +

    + +

    We will now present you with a very simple example used to render + a string of 8-bit Latin-1 text, assuming a face that contains a + Unicode charmap

    + +

    The idea is to create a loop that will, on each iteration, load one + glyph image, convert it to an anti-aliased bitmap, draw it on the + target surface, then increment the current pen position

    + +

    a. basic code :

    + +

    The following code performs our simple text rendering with the + functions previously described.

    + +
    +       FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +       int           pen_x, pen_y, n;
    +
    +       .. initialise library ..
    +       .. create face object ..
    +       .. set character size ..
    +       
    +       pen_x = 300;
    +       pen_y = 200;
    +       
    +       for ( n = 0; n < num_chars; n++ )
    +       {
    +         FT_UInt  glyph_index;
    +         
    +         // retrieve glyph index from character code
    +         glyph_index = FT_Get_Char_Index( face, text[n] );
    +         
    +         // load glyph image into the slot (erase previous one)
    +         error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
    +         if (error) continue;  // ignore errors
    +         
    +         // convert to an anti-aliased bitmap
    +         error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
    +         if (error) continue;
    +         
    +         // now, draw to our target surface
    +         my_draw_bitmap( &slot->bitmap,
    +                         pen_x + slot->bitmap_left,
    +                         pen_y - slot->bitmap_top );
    +                         
    +         // increment pen position 
    +         pen_x += slot->advance.x >> 6;
    +         pen_y += slot->advance.y >> 6;   // unuseful for now..
    +       }
    +    
    + +

    This code needs a few explanations:

    +
      +
    • + we define a handle named slot that points to the + face object's glyph slot. (the type FT_GlyphSlot is + a pointer). That's a convenience to avoid using + face->glyph->XXX every time. +

    • + +
    • + we increment the pen position with the vector slot->advance, + which correspond to the glyph's advance width (also known + as its escapement). The advance vector is expressed in + 64/th of pixels, and is truncated to integer pixels on each + iteration.

      +

    • + +
    • + The function my_draw_bitmap is not part of FreeType, but + must be provided by the application to draw the bitmap to the target + surface. In this example, it takes a pointer to a FT_Bitmap descriptor + and the position of its top-left corner as arguments. +

    • + +
    • + The value of slot->bitmap_top is positive for an + upwards vertical distance. Assuming that the coordinates + taken by my_draw_bitmap use the opposite convention + (increasing Y corresponds to downwards scanlines), we substract + it to pen_y, instead of adding it.. +

    • + +
    + +

    b. refined code:

    + +

    The following code is a refined version of the example above. It + uses features and functions of FreeType 2 that have not yet been + introduced, and they'll be explained below:

    + +
    +       FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +       FT_UInt       glyph_index;
    +       int           pen_x, pen_y, n;
    +
    +       .. initialise library ..
    +       .. create face object ..
    +       .. set character size ..
    +       
    +       pen_x = 300;
    +       pen_y = 200;
    +       
    +       for ( n = 0; n < num_chars; n++ )
    +       {
    +         // load glyph image into the slot (erase previous one)
    +         error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
    +         if (error) continue;  // ignore errors
    +         
    +         // now, draw to our target surface
    +         my_draw_bitmap( &slot->bitmap,
    +                         pen_x + slot->bitmap_left,
    +                         pen_y - slot->bitmap_top );
    +                         
    +         // increment pen position 
    +         pen_x += slot->advance.x >> 6;
    +       }
    +    
    + +

    We've reduced the size of our code, but it does exactly the same thing, + as:

    + +
      +
    • + We use the function FT_Load_Char instead of + FT_Load_Glyph. As you probably imagine, it's equivalent + to calling FT_Get_Char_Index then FT_Get_Load_Glyph. +

    • + +
    • + We do not use FT_LOAD_DEFAULT for the loading mode, but + the bit flag FT_LOAD_RENDER. It indicates that + the glyph image must be immediately converted to an anti-aliased + bitmap. This is of course a shortcut that avoids calling + FT_Render_Glyph explicitely but is strictly equivalent.

      + +

      + Note that you can also specify that you want a monochrome bitmap + instead by using the addition FT_LOAD_MONOCHROME + load flag. +

    • +
    + +

    c. more advanced rendering:

    + +

    Let's try to render transformed text now (for example through a + rotation). We can do this using FT_Set_Transform. Here's + how to do it:

    + +
    +       FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +       FT_Matrix     matrix;              // transformation matrix
    +       FT_UInt       glyph_index;
    +       FT_Vector     pen;                 // untransformed origin
    +       int           pen_x, pen_y, n;
    +
    +       .. initialise library ..
    +       .. create face object ..
    +       .. set character size ..
    +
    +       // set up matrix
    +       matrix.xx = (FT_Fixed)( cos(angle)*0x10000);
    +       matrix.xy = (FT_Fixed)(-sin(angle)*0x10000);
    +       matrix.yx = (FT_Fixed)( sin(angle)*0x10000);
    +       matrix.yy = (FT_Fixed)( cos(angle)*0x10000);
    +              
    +       // the pen position in 26.6 cartesian space coordinates
    +       pen.x = 300 * 64;
    +       pen.y = ( my_target_height - 200 ) * 64;
    +       
    +       for ( n = 0; n < num_chars; n++ )
    +       {
    +         // set transform
    +         FT_Set_Transform( face, &matrix, &pen );
    +         
    +         // load glyph image into the slot (erase previous one)
    +         error = FT_Load_Char( face, text[n], FT_LOAD_RENDER );
    +         if (error) continue;  // ignore errors
    +         
    +         // now, draw to our target surface (convert position)
    +         my_draw_bitmap( &slot->bitmap,
    +                         slot->bitmap_left,
    +                         my_target_height - slot->bitmap_top );
    +                         
    +         // increment pen position 
    +         pen.x += slot->advance.x;
    +         pen.y += slot->advance.y;
    +       }
    +    
    + +

    You'll notice that:

    + +
      +
    • + we now use a vector, of type FT_Vector to store the pen + position, with coordinates expressed as 1/64th of pixels, hence + a multiplication. The position is expressed in cartesian space. +

    • + +
    • + glyph images are always loaded, transformed and described in the + cartesian coordinate system in FreeType (which means that + increasing Y corresponds to upper scanlines), unlike the system + typically used for bitmaps (where the top-most scanline has + coordinate 0). We must thus convert between the two systems + when we define the pen position, and when we compute the top-left + position of the bitmap. +

    • + +
    • + we set the transform on each glyph, to indicate the rotation + matrix, as well as a delta that will move the transformed image + to the current pen position (in cartesian space, not bitmap space). +

    • + +
    • + the advance is always returned transformed, which is why it can + be directly added to the current pen position. Note that it is + not rounded this time. +

    • + +
    + +

    It is important to note that, while this example is a bit more + complex than the previous one, it is strictly equivalent + for the case where the transform is the identity.. Hence it can + be used as a replacement (but a more powerful one).

    + +

    It has however a few short comings that we will explain, and solve, + in the next part of this tutorial.

    + +
    + +

    + Conclusion +

    + +

    In this first section, you have learned the basics of FreeType 2, + as well as sufficient knowledge to know how to render rotated text. + Woww ! Congratulations..

    + +

    The next section will dive into more details of the API in order + to let you access glyph metrics and images directly, as well as + how to deal with scaling, hinting, kerning, etc..

    + +

    The third section will discuss issues like modules, caching and a + few other advanced topics like how to use multiple size objects + with a single face. +

    + +
    +
    + + + diff --git a/subsys/win32k/freetype/docs/tutorial/step2.html b/subsys/win32k/freetype/docs/tutorial/step2.html new file mode 100644 index 0000000..d8cc150 --- /dev/null +++ b/subsys/win32k/freetype/docs/tutorial/step2.html @@ -0,0 +1,1399 @@ + + + + + + FreeType 2 Tutorial + + + + +

    + FreeType 2.0 Tutorial
    + Step 2 - managing glyphs +

    + +

    + © 2000 David Turner + (david@freetype.org)
    + © 2000 The FreeType Development Team + (www.freetype.org) +

    + +
    + + +
    + +
    + +

    + Introduction +

    + +

    This is the second section of the FreeType 2 tutorial. It will teach + you the following:

    + +
      +
    • how to retrieve glyph metrics
    • +
    • how to easily manage glyph images
    • +
    • how to retrieve global metrics (including kerning)
    • +
    • how to render a simple string of text, with kerning
    • +
    • how to render a centered string of text (with kerning)
    • +
    • how to render a transformed string of text (with centering)
    • +
    • finally, how to access metrics in design font units when needed, + and how to scale them to device space.
    • +
    + +
    + +

    + 1. Glyph metrics: +

    + +

    Glyph metrics are, as their name suggests, certain distances associated + to each glyph in order to describe how to use it to layout text.

    + +

    There are usually two sets of metrics for a single glyph: those used to + layout the glyph in horizontal text layouts (like latin, cyrillic, + arabic, hebrew, etc..), and those used to layout the glyph in vertical + text layouts (like some layouts of Chinese, Japanese, Korean, and + others..).

    + +

    Note that only a few font formats provide vertical metrics. You can + test wether a given face object contains them by using the macro + FT_HAS_VERTICAL(face), which is true when appropriate.

    + +

    Individual glyph metrics can be accessed by first loading the glyph + in a face's glyph slot, then accessing them through the + face->glyph->metrics structure. This will be detailed + later, for now, we'll see that it contains the following fields:

    + +
    + width + +

    This is the width of the glyph image's bounding box. It is independent + of layout direction.

    +
    + height + +

    This is the height of the glyph image's bounding box. It is independent + of layout direction.

    +
    + horiBearingX + +

    For horizontal text layouts, this is the horizontal distance from + the current cursor position to the left-most border of the glyph image's + bounding box.

    +
    + horiBearingY + +

    For horizontal text layouts, this is the vertical distance from + the current cursor position (on the baseline) to the top-most border of + the glyph image's bounding box.

    +
    + horiAdvance + +

    For horizontal text layouts, this is the horizontal distance + used to increment the pen position when the glyph is drawn as part of + a string of text.

    +
    + vertBearingX + +

    For vertical text layouts, this is the horizontal distance from + the current cursor position to the left-most border of the glyph image's + bounding box.

    +
    + vertBearingY + +

    For vertical text layouts, this is the vertical distance from + the current cursor position (on the baseline) to the top-most border of + the glyph image's bounding box.

    +
    + vertAdvance + +

    For vertical text layouts, this is the vertical distance + used to increment the pen position when the glyph is drawn as part of + a string of text.

    +
    + +

    NOTA BENE: As all fonts do not contain vertical + metrics, the values of vertBearingX, vertBearingY + and vertAdvance should not be considered reliable when + FT_HAS_VERTICAL(face) is false.

    + +

    The following graphics illustrate the metrics more clearly. First, for + horizontal metrics, where the baseline is the horizontal axis :

    + +
    + +

    For vertical text layouts, the baseline is vertical and is the + vertical axis:

    + +
    + + +

    The metrics found in face->glyph->metrics are normally + expressed in 26.6 pixels (i.e 1/64th of pixels), unless you use + the FT_LOAD_NO_SCALE flag when calling + FT_Load_Glyph or FT_Load_Char. In this case, + the metrics will be expressed in original font units.

    + +

    The glyph slot object has also a few other interesting fields + that will ease a developer's work. You can access them though + face->glyph->??? :

    + +
    + advance + +

    This field is a FT_Vector which holds the transformed + advance for the glyph. That's useful when you're using a transform + through FT_Set_Transform, as shown in the rotated text + example of section I. Other than that, its value is + by default (metrics.horiAdvance,0), unless you specify + FT_LOAD_VERTICAL when loading the glyph image; + it will then be (0,metrics.vertAdvance)

    +
    + linearHoriAdvance + +

    + This field contains the linearly-scaled value of the glyph's horizontal + advance width. Indeed, the value of metrics.horiAdvance that is + returned in the glyph slot is normally rounded to integer pixel + coordinates (i.e., it will be a multiple of 64) by the font driver used + to load the glyph image. linearHoriAdvance is a 16.16 fixed float + number that gives the value of the original glyph advance width in + 1/65536th of pixels. It can be use to perform pseudo device-independent + text layouts.

    +
    + linearVertAdvance + +

    This is the same thing as linearHoriAdvance for the + glyph's vertical advance height. Its value is only reliable if the font + face contains vertical metrics.

    +
    + + + +
    + +

    + 2. Managing glyph images: +

    + +

    The glyph image that is loaded in a glyph slot can be converted into + a bitmap, either by using FT_LOAD_RENDER when loading it, or + by calling FT_Render_Glyph. Each time you load a new glyph + image, the previous one is erased from the glyph slot.

    + +

    There are times however where you may need to extract this image from + the glyph slot, in order to cache it within your application, and + even perform additional transforms and measures on it before converting + it to a bitmap. +

    + +

    The FreeType 2 API has a specific extension which is capable of dealing + with glyph images in a flexible and generic way. To use it, you first need + to include the "ftglyph.h" header file, as in:

    + +
    
    +      #include <freetype/ftglyph.h>
    +  
    + +

    We will now explain how to use the functions defined in this file:

    + +

    a. Extracting the glyph image:

    + +

    You can extract a single glyph image very easily. Here's some code + that shows how to do it:

    + +
    
    +       FT_Glyph    glyph;    // handle to glyph image
    +       
    +       ....
    +       error = FT_Load_Glyph( face, glyph, FT_LOAD_NORMAL );
    +       if (error) { .... }
    +       
    +       error = FT_Get_Glyph( face->glyph, &glyph );
    +       if (error) { .... }
    +  
    + +

    As you see, we have:

    + +
      +
    • + Created a variable, named glyph, of type FT_Glyph. + This is a handle (pointer) to an individual glyph image. +

    • + +
    • + Loaded the glyph image normally in the face's glyph slot. We did not + use FT_LOAD_RENDER because we want to grab a scalable glyph + image, in order to later transform it. +

    • + +
    • + Copy the glyph image from the slot into a new FT_Glyph object, + by calling FT_Get_Glyph. This function returns an error + code and sets glyph. +

    • +
    + +

    It is important to note that the extracted glyph is in the same format + than the original one that is still in the slot. For example, if we're + loading a glyph from a TrueType font file, the glyph image will really + be a scalable vector outline.

    + +

    You can access the field glyph->format if you want to + know exactly how the glyph is modeled and stored. A new glyph object can + be destroyed with a call to FT_Done_Glyph.

    + +

    The glyph object contains exactly one glyph image and a 2D vector + representing the glyph's advance in 16.16 fixed float coordinates. + The latter can be accessed directly as glyph->advance +

    + +

    Note that unlike + other FreeType objects, the library doesn't keeps a list of all + allocated glyph objects. This means you'll need to destroy them + yourself, instead of relying on FT_Done_FreeType doing + all the clean-up.

    + +

    b. Transforming & copying the glyph image

    + +

    If the glyph image is scalable (i.e. if glyph->format is not + equal to ft_glyph_format_bitmap), it is possible to transform + the image anytime by a call to FT_Glyph_Transform.

    + +

    You can also copy a single glyph image with FT_Glyph_Copy. + Here's some example code:

    + +
    
    +    FT_Glyph  glyph, glyph2;
    +    FT_Matrix matrix;
    +    FT_Vector delta;
    +    
    +    ......
    +    .. load glyph image in "glyph" ..
    +    
    +    // copy glyph to glyph2
    +    //
    +    error = FT_Glyph_Copy( glyph, &glyph2 );
    +    if (error) { ... could not copy (out of memory) }
    +    
    +    // translate "glyph"
    +    //    
    +    delta.x = -100 * 64;   // coordinates are in 26.6 pixels
    +    delta.y =  50  * 64;
    +    
    +    FT_Glyph_Transform( glyph, 0, &delta );
    +    
    +    // transform glyph2 (horizontal shear)
    +    //
    +    matrix.xx = 0x10000;
    +    matrix.xy = 0;
    +    matrix.yx = 0.12 * 0x10000;
    +    matrix.yy = 0x10000;
    +    
    +    FT_Glyph_Transform( glyph2, &matrix, 0 );
    +  
    + +

    Note that the 2x2 transform matrix is always applied to the 16.16 + advance vector in the glyph, you thus don't need to recompute it..

    + +

    c. Measuring the glyph image

    + +

    You can also retrieve the control (bounding) box of any glyph image + (scalable or not), through the FT_Glyph_Get_CBox function, + as in: +

    + +
    
    +     FT_BBox   bbox;
    +     ...
    +     FT_Glyph_BBox(  glyph, bbox_mode, &bbox );
    +  
    + +

    Coordinates are relative to the glyph origin, i.e. (0,0), using the + Y_upwards convention. This function takes a special argument, the + "bbox mode", that is a set of bit flags used to indicate how + box coordinates are expressed. If ft_glyph_bbox_subpixels + is set in the bbox mode, the coordinates are returned in 26.6 pixels + (i.e. 1/64th of pixels). Otherwise, they're in integer pixels.

    + +

    Note that the box's maximum coordinates are exclusive, which means + that you can always compute the width and height of the glyph image, + be in in integer or 26.6 pixels with:

    + +
         
    +     width  = bbox.xMax - bbox.xMin;
    +     height = bbox.yMax - bbox.yMin;
    +  
    + +

    Note also that for 26.6 coordinates, if + ft_glyph_bbox_gridfit is set in the bbox mode, + the coordinates will also be grid-fitted, which corresponds to:

    + +
    
    +     bbox.xMin = FLOOR(bbox.xMin)
    +     bbox.yMin = FLOOR(bbox.yMin)
    +     bbox.xMax = CEILING(bbox.xMax)
    +     bbox.yMax = CEILING(bbox.yMax)
    +  
    + +

    The default value for the bbox mode, which is 0, corresponds to + ft_glyph_bbox_pixels (i.e. integer pixel coordinates).

    + + +

    d. Converting the glyph image to a bitmap

    + +

    You may need to convert the glyph object to a bitmap once you have + convienently cached or transformed it. This can be done easily with + the FT_Glyph_To_Bitmap function. It is chared of + converting any glyph object into a bitmap, as in:

    + +
    
    +    FT_Vector  origin;
    +    
    +    origin.x = 32;   /* 1/2 pixel in 26.26 format */
    +    origin.y = 0;
    +    
    +    error = FT_Glyph_To_Bitmap( &glyph,
    +                                render_mode,
    +                                &origin,
    +                                1 );        // destroy original image == true
    +  
    + +

    We will know details this function's parameters:

    + +
      +
    • + the first parameter is the address of the source glyph's handle. + When the function is called, it reads its to access the source + glyph object. After the call, the handle will point to a + new glyph object that contains the rendered bitmap. +

    • + +
    • + the second parameter is a standard render mode, that is used to specify + what kind of bitmap we want. It can be ft_render_mode_default + for an 8-bit anti-aliased pixmap, or ft_render_mode_mono for + a 1-bit monochrome bitmap. +

    • + +
    • + the third parameter is a pointer to a 2D vector that is used to + translate the source glyph image before the conversion. Note that + the source image will be translated back to its original position + (and will thus be left unchanged) after the call. If you do not need + to translate the source glyph before rendering, set this pointer to 0. +

    • + +
    • + the last parameter is a boolean that indicates wether the source + glyph object should be destroyed by the function. By default, the + original glyph object is never destroyed, even if its handle is + lost (it's up to client applications to keep it). +

    • +
    + +

    The new glyph object always contain a bitmap (when no error is returned), + and you must typecast its handle to the + FT_BitmapGlyph type in order to access its content. + This type is a sort of "subclass" of FT_Glyph that contains + additional fields:

    + +
    + left + +

    Just like the bitmap_left field of a glyph slot, this is the + horizontal distance from the glyph origin (0,0) to the left-most pixel + of the glyph bitmap. It is expressed in integer pixels.

    +
    + top + +

    Just like the bitmap_top field of a glyph slot, this is the + vertical distance from the glyph origin (0,0) to the top-most pixel + of the glyph bitmap (more exactly, to the pixel just above the bitmap). + This distance is expressed in integer pixels, and is positive for upwards + Y.

    +
    + bitmap + +

    This is a bitmap descriptor for the glyph object, just like the + bitmap field in a glyph slot.

    +
    + +
    +

    + 3. Global glyph metrics: +

    + +

    Unlike glyph metrics, global ones are used to describe distances + and features of a whole font face. They can be expressed either in + 26.6 pixels or in design "font units" for scalable formats.

    + +

    + a. Design Global Metrics: +

    + +

    For scalable formats, all global metrics are expressed in font units + in order to be later scaled to device space, according to the rules + described in the last chapter of this section of the tutorial. You + can access them directly as simple fields of a FT_Face + handle.

    + +

    However, you need to check that the font face's format is scalable + before using them. One can do it by using the macro + FT_IS_SCALABLE(face) which returns true when + appropriate.

    + +

    In this case, you can access the global design metrics as:

    + +
    + units_per_EM + +

    This is the size of the EM square for the font face. It is used by scalable + formats to scale design coordinates to device pixels, as described by the + last chapter of this section. Its value usually is 2048 (for TrueType) + or 1000 (for Type1), but others are possible too. It is set to 1 for + fixed-size formats like FNT/FON/PCF/BDF.

    +
    + global_bbox + +

    The global bounding box is defined as the largest rectangle that can + enclose all the glyphs in a font face. It is defined for horizontal + layouts only.

    +
    + ascender + +

    The ascender is the vertical distance from the horizontal baseline to + the highest "character" coordinate in a font face. Unfortunately, font + formats define the ascender differently. For some, it represents + the ascent of all capital latin characters, without accents, for others + it's the ascent of the highest accented character, and finally, other + formats define it as being equal to global_bbox.yMax.

    +
    + descender + +

    The descender is the vertical distance from the horizontal baseline to + the lowest "character" coordinate in a font face. Unfortunately, font + formats define the descender differently. For some, it represents + the descent of all capital latin characters, without accents, for others + it's the ascent of the lowest accented character, and finally, other + formats define it as being equal to global_bbox.yMin. + This field is usually negative

    +
    + text_height + +

    This field is simply used to compute a default line spacing (i.e. the + baseline-to-baseline distance) when writing text with this font. Note that + it usually is larger than the sum of the ascender and descender taken in + absolute value. There is also no guarantee that no glyphs can extend + above or below subsequent baselines when using this distance.

    +
    + max_advance_width + +

    This field gives the maximum horizontal cursor advance for all glyphs + in the font. It can be used to quickly compute the maximum advance width + of a string of text. It doesn't correspond to the maximum glyph image + width !!

    +
    + max_advance_height + +

    Same as max_advance_width but for vertical text layout. It is + only available in fonts providing vertical glyph metrics.

    +
    + underline_position + +

    When displaying or rendering underlined text, this value corresponds to + the vertical position, relative to the baseline, of the underline bar. It + noramlly is negative (as it's below the baseline).

    +
    + underline_thickness + +

    When displaying or rendering underlined text, this value corresponds to + the vertical thickness of the underline.

    +
    + +

    Notice how, unfortunately, the values of the ascender and the descender + are not reliable (due to various discrepancies in font formats).

    + +

    + b. Scaled Global Metrics: +

    + +

    Each size object also contains a scaled versions of some of the global + metrics described above. They can be accessed directly through the + face->size->metrics structure.

    + +

    Note that these values correspond to scaled versions of the design + global metrics, with no rounding/grid-fitting performed.. + They are also completely independent of any hinting process. In other + words, don't rely on them to get exact metrics at the pixel level. + They're expressed in 26.6 pixels.

    + +
    + ascender + +

    This is the scaled version of the original design ascender.

    +
    + descender + +

    This is the scaled version of the original design descender.

    +
    + height + +

    This is the scaled version of the original design text height. + That probably is the only field you should really use in this structure.

    +
    + max_advance + +

    Thi is the scaled version of the original design max advance.

    +
    + +

    Note that the face->size->metrics structure contains other + fields that are used to scale design coordinates to device space. They're + described, in the last chapter.

    + +

    + c. Kerning: +

    + +

    Kerning is the process of adjusting the position of two subsequent + glyph images in a string of text, in order to improve the general + appearance of text. Basically, it means that when the glyph for an + "A" is followed by the glyph for a "V", the space between them can + be slightly reduced to avoid extra "diagonal whitespace".

    + +

    Note that in theory, kerning can happen both in the horizontal and + vertical direction between two glyphs; however, it only happens in + the horizontal direction in nearly all cases except really extreme + ones.

    + +

    Note all font formats contain kerning information. Instead, they sometimes + rely on an additional file that contains various glyph metrics, including + kerning, but no glyph images. A good example would be the Type 1 format, + where glyph images are stored in a file with extension ".pfa" or ".pfb", + and where kerning metrics can be found in an additional file with extension + ".afm" or ".pfm".

    + +

    FreeType 2 allows you to deal with this, by providing the + FT_Attach_File and FT_Attach_Stream APIs. + Both functions are used to load additional metrics into a face object, + by reading them from an additional format-specific file. For example, + you could open a Type 1 font by doing the following:

    + +
    
    +      error = FT_New_Face( library, "/usr/shared/fonts/cour.pfb", 0, &face );
    +      if (error) { ... }
    +      
    +      error = FT_Attach_File( face, "/usr/shared/fonts/cour.afm" );
    +      if (error) { .. could not read kerning and additional metrics .. }
    +  
    + +

    Note that FT_Attach_Stream is similar to + FT_Attach_File except that it doesn't take a C string + to name the extra file, but a FT_Stream handle. Also, + reading a metrics file is in no way, mandatory.

    + +

    Finally, the file attachment APIs are very generic and can be used to + load any kind of extra information for a given face. The nature of the + additional content is entirely font format specific.

    + +

    FreeType 2 allows you to retrieve the kerning information between + two glyphs through the FT_Get_Kerning function, whose + interface looks like:

    + +
    
    +     FT_Vector  kerning;
    +     ...
    +     error = FT_Get_Kerning( face,                  // handle to face object
    +                             left,                  // left glyph index
    +                             right,                 // right glyph index
    +                             kerning_mode,          // kerning mode
    +                             &kerning );            // target vector
    +  
    + +

    As you see, the function takes a handle to a face object, the indices + of the left and right glyphs for which the kerning value is desired, + as well as an integer, called the "kerning mode", and a pointer to + a destination vector that receives the corresponding distances.

    + +

    The kerning mode is very similar to the "bbox mode" described in a + previous chapter. It's a enumeration that indicates how the + kerning distances are expressed in the target vector.

    + +

    The default value is ft_kerning_mode_default which + has value 0. It corresponds to kerning distances expressed in 26.6 + grid-fitted pixels (which means that the values are multiples of 64). + For scalable formats, this means that the design kerning distance is + scaled then rounded.

    + +

    The value ft_kerning_mode_unfitted corresponds to kerning + distances expressed in 26.6 unfitted pixels (i.e. that do not correspond + to integer coordinates). It's the design kerning distance that is simply + scaled without rounding.

    + +

    Finally, the value ft_kerning_mode_unscaled is used to + return the design kerning distance, expressed in font units. You can + later scale it to device space using the computations explained in the + last chapter of this section.

    + +

    Note that the "left" and "right" positions correspond to the visual + order of the glyphs in the string of text. This is important for + + bi-directional text, or simply when writing right-to-left text..

    + +
    + +

    + 4. Simple text rendering: kerning + centering: +

    + +

    In order to show off what we just learned, we will now show how to modify + the example code that was provided in section I to render a string of text, + and enhance it to support kerning and delayed rendering.

    + +

    + a. Kerning support: +

    + +

    Adding support for kerning to our code is trivial, as long as we consider + that we're still dealing with a left-to-right script like Latin. We + simply need to retrieve the kerning distance between two glyphs in order + to alter the pen position appropriately. The code looks like:

    + +
    +      FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +      FT_UInt       glyph_index;
    +      FT_Bool       use_kerning;
    +      FT_UInt       previous;
    +      int           pen_x, pen_y, n;
    +
    +      .. initialise library ..
    +      .. create face object ..
    +      .. set character size ..
    +      
    +      pen_x = 300;
    +      pen_y = 200;
    +      
    +      use_kerning = FT_HAS_KERNING(face);
    +      previous    = 0;
    +      
    +      for ( n = 0; n < num_chars; n++ )
    +      {
    +        // convert character code to glyph index
    +        glyph_index = FT_Get_Char_Index( face, text[n] );
    +        
    +        // retrieve kerning distance and move pen position
    +        if ( use_kerning && previous && glyph_index )
    +        {
    +          FT_Vector  delta;
    +          
    +          FT_Get_Kerning( face, previous, glyph_index,
    +                          ft_kerning_mode_default, &delta );
    +                          
    +          pen_x += delta.x >> 6;
    +        }
    +      
    +        // load glyph image into the slot (erase previous one)
    +        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );
    +        if (error) continue;  // ignore errors
    +        
    +        // now, draw to our target surface
    +        my_draw_bitmap( &slot->bitmap,
    +                        pen_x + slot->bitmap_left,
    +                        pen_y - slot->bitmap_top );
    +                        
    +        // increment pen position
    +        pen_x += slot->advance.x >> 6;
    +        
    +        // record current glyph index
    +        previous = glyph_index
    +      }
    +   
    + +

    That's it. You'll notice that:

    + +
      +
    • + As kerning is determined from glyph indices, we need to explicitely + convert our character code into a glyph index, then later call + FT_Load_Glyph instead of FT_Load_Char. No big + deal, if you ask me :-) +

    • + +
    • + We use a boolean named use_kerning which is set with the + result of the macro FT_HAS_KERNING(face). It's + certainly faster not to call FT_Get_Kerning when we know + that the font face does not contain kerning information. +

    • + +
    • + We move the position of the pen before a new glyph is drawn. +

    • + +
    • + We did initialize the variable previous with the value 0, + which always correspond to the "missing glyph" (also called + .notdef in the Postscript world). There is never any + kerning distance associated with this glyph. +

    • + +
    • + We do not check the error code returned by FT_get_Kerning. + This is because the function always set the content of delta + to (0,0) when an error occurs. +

    • +
    + +

    As you see, this is not terribly complex :-)

    + +

    + b. Centering: +

    + +

    Our code begins to become interesting but it's still a bit too simple + for normal uses. For example, the position of the pen is determined + before we do the rendering when in a normal situation, you would want + to layout the text and measure it before computing its final position + (e.g. centering) or perform things like word-wrapping.

    + +

    We're thus now going to decompose our text rendering function into two + distinct but successive parts: the first one will position individual + glyph images on the baseline, while the second one will render the + glyphs. As we'll see, this has many advantages.

    + +

    We will thus start by storing individual glyph images, as well as their + position on the baseline. This can be done with code like:

    + +
    +      FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +      FT_UInt       glyph_index;
    +      FT_Bool       use_kerning;
    +      FT_UInt       previous;
    +      int           pen_x, pen_y, n;
    +      
    +      FT_Glyph      glyphs[ MAX_GLYPHS ];   // glyph image
    +      FT_Vector     pos   [ MAX_GLYPHS ];   // glyph position
    +      FT_UInt       num_glyphs;
    +
    +      .. initialise library ..
    +      .. create face object ..
    +      .. set character size ..
    +      
    +      pen_x = 0;   /* start at (0,0) !! */
    +      pen_y = 0;
    +      
    +      num_glyphs  = 0;
    +      use_kerning = FT_HAS_KERNING(face);
    +      previous    = 0;
    +      
    +      for ( n = 0; n < num_chars; n++ )
    +      {
    +        // convert character code to glyph index
    +        glyph_index = FT_Get_Char_Index( face, text[n] );
    +        
    +        // retrieve kerning distance and move pen position
    +        if ( use_kerning && previous && glyph_index )
    +        {
    +          FT_Vector  delta;
    +          
    +          FT_Get_Kerning( face, previous, glyph_index,
    +                          ft_kerning_mode_default, &delta );
    +                          
    +          pen_x += delta.x >> 6;
    +        }
    +      
    +        // store current pen position
    +        pos[ num_glyphs ].x = pen_x;
    +        pos[ num_glyphs ].y = pen_y;
    +      
    +        // load glyph image into the slot. DO NOT RENDER IT !!
    +        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
    +        if (error) continue;  // ignore errors, jump to next glyph
    +        
    +        // extract glyph image and store it in our table
    +        error = FT_Get_Glyph( face->glyph, & glyphs[num_glyphs] );
    +        if (error) continue;  // ignore errors, jump to next glyph
    +        
    +        // increment pen position
    +        pen_x += slot->advance.x >> 6;
    +        
    +        // record current glyph index
    +        previous = glyph_index
    +        
    +        // increment number of glyphs
    +        num_glyphs++;
    +      }
    +   
    + +

    As you see, this is a very simple variation of our previous code + where we extract each glyph image from the slot, and store it, along + with the corresponding position, in our tables.

    + +

    Note also that "pen_x" contains the total advance for the string of + text. We can now compute the bounding box of the text string with + a simple function like:

    + + +
    +      void   compute_string_bbox( FT_BBox  *abbox )
    +      {
    +        FT_BBox  bbox;
    +        
    +        // initialise string bbox to "empty" values
    +        bbox.xMin = bbox.yMin =  32000;
    +        bbox.xMax = bbox.yMax = -32000;
    +        
    +        // for each glyph image, compute its bounding box, translate it,
    +        // and grow the string bbox
    +        for ( n = 0; n < num_glyphs; n++ )
    +        {
    +          FT_BBox   glyph_bbox;
    +
    +          FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
    +
    +          glyph_bbox.xMin += pos[n].x;
    +          glyph_bbox.xMax += pos[n].x;
    +          glyph_bbox.yMin += pos[n].y;
    +          glyph_bbox.yMax += pos[n].y;
    +
    +          if (glyph_bbox.xMin < bbox.xMin)
    +            bbox.xMin = glyph_bbox.xMin;
    +
    +          if (glyph_bbox.yMin < bbox.yMin)
    +            bbox.yMin = glyph_bbox.yMin;
    +
    +          if (glyph_bbox.xMax > bbox.xMax)
    +            bbox.xMax = glyph_bbox.xMax;
    +
    +          if (glyph_bbox.yMax &gy; bbox.yMax)
    +            bbox.yMax = glyph_bbox.yMax;
    +        }
    +        
    +        // check that we really grew the string bbox
    +        if ( bbox.xMin > bbox.xMax )
    +        {
    +          bbox.xMin = 0;
    +          bbox.yMin = 0;
    +          bbox.xMax = 0;
    +          bbox.yMax = 0;
    +        }
    +        
    +        // return string bbox
    +        *abbox = bbox;
    +      }
    +   
    + +

    The resulting bounding box dimensions can then be used to compute the + final pen position before rendering the string as in:

    + +
    +      // compute string dimensions in integer pixels
    +      string_width  = (string_bbox.xMax - string_bbox.xMin)/64;
    +      string_height = (string_bbox.yMax - string_bbox.yMin)/64;
    +   
    +      // compute start pen position in 26.6 cartesian pixels
    +      start_x = (( my_target_width  - string_width )/2)*64;
    +      start_y = (( my_target_height - string_height)/2)*64;
    +      
    +      for ( n = 0; n < num_glyphs; n++ )
    +      {
    +        FT_Glyph  image;
    +        FT_Vector pen;
    +        
    +        image = glyphs[n];
    +        
    +        pen.x = start_x + pos[n].x;
    +        pen.y = start_y + pos[n].y;
    +        
    +        error = FT_Glyph_To_Bitmap( &image, ft_render_mode_normal,
    +                                    &pen.x, 0 );
    +        if (!error)
    +        {
    +          FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
    +          
    +          my_draw_bitmap( bitmap->bitmap,
    +                          bitmap->left,
    +                          my_target_height - bitmap->top );
    +                          
    +          FT_Done_Glyph( image );
    +        }
    +      }
    +   
    + +

    You'll take note that:

    + +
      +
    • + The pen position is expressed in the cartesian space (i.e. Y upwards). +

    • + +
    • + We call FT_Glyph_To_Bitmap with the destroy + parameter set to 0 (false), in order to avoid destroying the original + glyph image. The new glyph bitmap is accessed through image + after the call and is typecasted to a FT_BitmapGlyph. +

    • + +
    • + We use translation when calling FT_Glyph_To_Bitmap. This + ensures that the left and top fields + of the bitmap glyph object are already set to the correct pixel + coordinates in the cartesian space. +

    • + +
    • + Of course, we still need to convert pixel coordinates from cartesian + to device space before rendering, hence the my_target_height - + bitmap->top in the call to my_draw_bitmap. +

    • + +
    + +

    The same loop can be used to render the string anywhere on our display + surface, without the need to reload our glyph images each time.. We + could also decide to implement word wrapping, and only draw

    + +
    +

    + 5. Advanced text rendering: transform + centering + kerning: +

    + +

    We are now going to modify our code in order to be able to easily + transform the rendered string, for example to rotate it. We will + start by performing a few minor improvements:

    + +

    a. packing & translating glyphs:

    + +

    We'll start by packing the information related to a single glyph image + into a single structure, instead of parallel arrays. We thus define the + following structure type:

    + +
    +     typedef struct TGlyph_
    +     {
    +       FT_UInt    index;    // glyph index
    +       FT_Vector  pos;      // glyph origin on the baseline
    +       FT_Glyph   image;    // glyph image
    +     
    +     } TGlyph, *PGlyph;
    +  
    + +

    We will also translate each glyph image directly after it is loaded + to its position on the baseline at load time. As we'll see, this + as several advantages. Our glyph sequence loader thus becomes:

    + +
    +      FT_GlyphSlot  slot = face->glyph;  // a small shortcut
    +      FT_UInt       glyph_index;
    +      FT_Bool       use_kerning;
    +      FT_UInt       previous;
    +      int           pen_x, pen_y, n;
    +      
    +      TGlyph        glyphs[ MAX_GLYPHS ];   // glyphs table
    +      PGlyph        glyph;                  // current glyph in table
    +      FT_UInt       num_glyphs;
    +
    +      .. initialise library ..
    +      .. create face object ..
    +      .. set character size ..
    +      
    +      pen_x = 0;   /* start at (0,0) !! */
    +      pen_y = 0;
    +      
    +      num_glyphs  = 0;
    +      use_kerning = FT_HAS_KERNING(face);
    +      previous    = 0;
    +
    +      glyph = glyphs;      
    +      for ( n = 0; n < num_chars; n++ )
    +      {
    +        glyph->index = FT_Get_Char_Index( face, text[n] );
    +        
    +        if ( use_kerning && previous && glyph->index )
    +        {
    +          FT_Vector  delta;
    +          
    +          FT_Get_Kerning( face, previous, glyph->index,
    +                          ft_kerning_mode_default, &delta );
    +                          
    +          pen_x += delta.x >> 6;
    +        }
    +      
    +        // store current pen position
    +        glyph->pos.x = pen_x;
    +        glyph->pos.y = pen_y;
    +      
    +        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
    +        if (error) continue;
    +        
    +        error = FT_Get_Glyph( face->glyph, &glyph->image );
    +        if (error) continue;
    +        
    +        // translate the glyph image now..
    +        FT_Glyph_Transform( glyph->image, 0, &glyph->pos );
    +        
    +        pen_x   += slot->advance.x >> 6;
    +        previous = glyph->index
    +        
    +        // increment number of glyphs
    +        glyph++;
    +      }
    +      // count number of glyphs loaded..
    +      num_glyphs = glyph - glyphs;
    +   
    + +

    Note that translating glyphs now has several advantages. The first + one, is that we don't need to translate the glyph bbox when we compute + the string's bounding box. The code becomes:

    + +
    +      void   compute_string_bbox( FT_BBox  *abbox )
    +      {
    +        FT_BBox  bbox;
    +        
    +        bbox.xMin = bbox.yMin =  32000;
    +        bbox.xMax = bbox.yMax = -32000;
    +        
    +        for ( n = 0; n < num_glyphs; n++ )
    +        {
    +          FT_BBox   glyph_bbox;
    +
    +          FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
    +
    +          if (glyph_bbox.xMin < bbox.xMin)
    +            bbox.xMin = glyph_bbox.xMin;
    +
    +          if (glyph_bbox.yMin < bbox.yMin)
    +            bbox.yMin = glyph_bbox.yMin;
    +
    +          if (glyph_bbox.xMax > bbox.xMax)
    +            bbox.xMax = glyph_bbox.xMax;
    +
    +          if (glyph_bbox.yMax &gy; bbox.yMax)
    +            bbox.yMax = glyph_bbox.yMax;
    +        }
    +        
    +        if ( bbox.xMin > bbox.xMax )
    +        {
    +          bbox.xMin = 0;
    +          bbox.yMin = 0;
    +          bbox.xMax = 0;
    +          bbox.yMax = 0;
    +        }
    +        
    +        *abbox = bbox;
    +      }
    +   
    + +

    Now take a closer look, the compute_string_bbox can now + compute the bounding box of a transformed glyph string. For example, + we can do something like:

    + +
    
    +      FT_BBox    bbox;
    +      FT_Matrix  matrix;
    +      FT_Vector  delta;
    +   
    +      ... load glyph sequence
    +      
    +      ... setup "matrix" and "delta"
    +      
    +      // transform glyphs
    +      for ( n = 0; n < num_glyphs; n++ )
    +        FT_Glyph_Transform( glyphs[n].image, &matrix, &delta );
    +      
    +      // compute bounding box of transformed glyphs
    +      compute_string_bbox( &bbox );
    +   
    + +

    + b. Rendering a transformed glyph sequence: +

    + +

    However, directly transforming the glyphs in our sequence is not an idea + if we want to re-use them in order to draw the text string with various + angles or transforms. It's better to perform the affine transformation + just before the glyph is rendered, as in the following code:

    + +
    +      FT_Vector  start;
    +      FT_Matrix  transform;
    +   
    +      // get bbox of original glyph sequence
    +      compute_string_bbox( &string_bbox );
    +   
    +      // compute string dimensions in integer pixels
    +      string_width  = (string_bbox.xMax - string_bbox.xMin)/64;
    +      string_height = (string_bbox.yMax - string_bbox.yMin)/64;
    +   
    +      // set up start position in 26.6 cartesian space
    +      start.x = (( my_target_width  - string_width )/2)*64;
    +      start.y = (( my_target_height - string_height)/2)*64;
    +      
    +      // set up transform (a rotation here)
    +      matrix.xx = (FT_Fixed)( cos(angle)*0x10000);
    +      matrix.xy = (FT_Fixed)(-sin(angle)*0x10000);
    +      matrix.yx = (FT_Fixed)( sin(angle)*0x10000);
    +      matrix.yy = (FT_Fixed)( cos(angle)*0x10000);
    +      
    +      for ( n = 0; n < num_glyphs; n++ )
    +      {
    +        FT_Glyph  image;
    +        FT_Vector pen;
    +        FT_BBox   bbox;
    +        
    +        // create a copy of the original glyph
    +        error = FT_Glyph_Copy( glyphs[n].image, &image );
    +        if (error) continue;
    +
    +        // transform copy (this will also translate it to the correct
    +        // position
    +        FT_Glyph_Transform( image, &matrix, &start );
    +        
    +        // check bounding box, if the transformed glyph image
    +        // is not in our target surface, we can avoid rendering it
    +        FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
    +        if ( bbox.xMax <= 0 || bbox.xMin >= my_target_width  ||
    +             bbox.yMax <= 0 || bbox.yMin >= my_target_height )
    +          continue;
    +        
    +        // convert glyph image to bitmap (destroy the glyph copy !!)
    +        //
    +        error = FT_Glyph_To_Bitmap( &image,
    +                                    ft_render_mode_normal,
    +                                    0,      // no additional translation
    +                                    1 );    // destroy copy in "image"
    +        if (!error)
    +        {
    +          FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
    +          
    +          my_draw_bitmap( bitmap->bitmap,
    +                          bitmap->left,
    +                          my_target_height - bitmap->top );
    +                          
    +          FT_Done_Glyph( image );
    +        }
    +      }
    +   
    + +

    You'll notice a few changes compared to the original version of this + code:

    + +
      +
    • + We keep the original glyph images untouched, by transforming a + copy. +

    • + +
    • + We perform clipping computations, in order to avoid rendering & + drawing glyphs that are not within our target surface +

    • + +
    • + We always destroy the copy when calling FT_Glyph_To_Bitmap + in order to get rid of the transformed scalable image. Note that + the image is destroyed even when the function returns an error + code (which is why FT_Done_Glyph is only called within + the compound statement. +

    • + +
    • + The translation of the glyph sequence to the start pen position is + integrated in the call to FT_Glyph_Transform intead of + FT_Glyph_To_Bitmap. +

    • +
    + +

    It's possible to call this function several times to render the string + width different angles, or even change the way "start" is computed in + order to move it to different place.

    + +

    This code is the basis of the FreeType 2 demonstration program + named"ftstring.c". It could be easily extended to perform + advanced text layout or word-wrapping in the first part, without + changing the second one.

    + +

    Note however that a normal implementation would use a glyph cache in + order to reduce memory needs. For example, let's assume that our text + string is "FreeType". We would store three identical glyph images in + our table for the letter "e", which isn't optimal (especially when you + consider longer lines of text, or even whole pages..). +

    + +
    + +

    + 6. Accessing metrics in design font units, and scaling them: +

    + +

    Scalable font formats usually store a single vectorial image, called + an "outline", for each in a face. Each outline is defined in an abstract + grid called the "design space", with coordinates expressed in nominal + "font units". When a glyph image is loaded, the font driver usually + scales the outline to device space according to the current character + pixel size found in a FT_Size object. The driver may also + modify the scaled outline in order to significantly improve its + appearance on a pixel-based surface (a process known as "hinting" + or "grid-fitting").

    + +

    This chapter describes how design coordinates are scaled to device + space, and how to read glyph outlines and metrics in font units. This + is important for a number of things:

    + +
      +
    • + In order to perform "true" WYSIWYG text layout +

    • + +
    • + In order to access font content for conversion or analysis purposes +

    • +
    + +

    a.Scaling distances to device space:

    + +

    Design coordinates are scaled to device space using a simple scaling + transform, whose coefficients are computed with the help of the + character pixel size:

    + +
    
    +     device_x = design_x * x_scale
    +     device_y = design_y * y_scale
    +
    +     x_scale  = pixel_size_x / EM_size
    +     y_scale  = pixel_size_y / EM_size
    +  
    + +

    Here, the value EM_size is font-specific and correspond + to the size of an abstract square of the design space (called the "EM"), + which is used by font designers to create glyph images. It is thus + expressed in font units. It is also accessible directly for scalable + font formats as face->units_per_EM. You should + check that a font face contains scalable glyph images by using the + FT_IS_SCALABLE(face) macro, which returns true when + appropriate.

    + +

    When you call the function FT_Set_Pixel_Sizes, you're + specifying the value of pixel_size_x and pixel_size_y + you want to use to FreeType, which will immediately compute the values + of x_scale and y_scale.

    + +

    When you call the function FT_Set_Char_Size, you're + specifying the character size in physical "points", which is used, + along with the device's resolutions, to compute the character pixel + size, then the scaling factors.

    + +

    Note that after calling any of these two functions, you can access + the values of the character pixel size and scaling factors as fields + of the face->size->metrics structure. These fields are:

    + +
    + +
    + x_ppem + +

    Which stands for "X Pixels Per EM", this is the size in integer pixels + of the EM square, which also is the horizontal character pixel size, + called pixel_size_x in the above example.

    +
    + y_ppem + +

    Which stands for "Y Pixels Per EM", this is the size in integer pixels + of the EM square, which also is the vertical character pixel size, + called pixel_size_y in the above example.

    +
    + x_scale + +

    This is a 16.16 fixed float scale that is used to directly + scale horizontal distances from design space to 1/64th of device pixels. +

    +
    + y_scale + +

    This is a 16.16 fixed float scale that is used to directly scale + vertical distances from design space to 1/64th of device pixels.

    +
    +
    + +

    Basically, this means that you can scale a distance expressed in + font units to 26.6 pixels directly with the help of the FT_MulFix + function, as in:

    + +
    
    +      // convert design distances to 1/64th of pixels
    +      //
    +      pixels_x = FT_MulFix( design_x, face->size->metrics.x_scale );
    +      pixels_y = FT_MulFix( design_y, face->size->metrics.y_scale );
    +  
    + +

    However, you can also scale the value directly with more accuracy + by using doubles and the equations:

    + +
    
    +      FT_Size_Metrics*  metrics = &face->size->metrics;    // shortcut
    +      double            pixels_x, pixels_y;
    +      double            em_size, x_scale, y_scale;
    +
    +      // compute floating point scale factors
    +      //
    +      em_size = 1.0 * face->units_per_EM;
    +      x_scale = metrics->x_ppem / em_size;
    +      y_scale = metrics->y_ppem / em_size;
    +      
    +      // convert design distances to floating point pixels
    +      //
    +      pixels_x = design_x * x_scale;
    +      pixels_y = design_y * y_scale;
    +  
    + +

    + b. Accessing design metrics (glyph & global): +

    + +

    You can access glyph metrics in font units simply by specifying the + FT_LOAD_NO_SCALE bit flag in FT_Load_Glyph + or FT_Load_Char. The metrics returned in + face->glyph->metrics will all be in font units.

    + +

    You can access unscaled kerning data using the + ft_kerning_mode_unscaled mode

    + +

    Finally, a few global metrics are available directly in font units + as fields of the FT_Face handle, as described in chapter 3 + of this section.

    + +
    + +

    + Conclusion +

    + +

    This is the end of the second section of the FreeType 2 tutorial, + you're now able to access glyph metrics, manage glyph images, and + render text much more intelligently (kerning, measuring, transforming + & caching).

    + +

    You have now sufficient knowledge to build a pretty decent text service + on top of FreeType 2, and you could possibly stop there if you want.

    + +

    The next section will deal with FreeType 2 internals (like modules, + vector outlines, font drivers, renderers), as well as a few font format + specific issues (mainly, how to access certain TrueType or Type 1 tables). +

    +
    +
    + + + diff --git a/subsys/win32k/freetype/grfont.c b/subsys/win32k/freetype/grfont.c new file mode 100644 index 0000000..d8e8d41 --- /dev/null +++ b/subsys/win32k/freetype/grfont.c @@ -0,0 +1,415 @@ +// Taken from FreeType 2 (www.freetype.org) + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include "../eng/objects.h" + +//#define NDEBUG +#include + +// #include "grfont.h" +// #include + +/* font characters */ + +const unsigned char font_8x8[2048] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, + 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, + 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C, + 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, + 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, + 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, + 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, + 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, + 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, + 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, + 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, + 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, + 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, + 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, + 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, + 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, + 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00, + 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00, + 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, + 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, + 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00, + 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00, + 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, + 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00, + 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, + 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, + 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00, + 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, + 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, + 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, + 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, + 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, + 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00, + 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00, + 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00, + 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, + 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, + 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00, + 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E, + 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00, + 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00, + 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00, + 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, + 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00, + 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38, + 0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, + 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, + 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00, + 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00, + 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00, + 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00, + 0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00, + 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00, + 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30, + 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3, + 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70, + 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00, + 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00, + 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, + 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00, + 0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F, + 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03, + 0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00, + 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0, + 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, + 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, + 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00, + 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0, + 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC, + 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00, + 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00, + 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0, + 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00, + 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, + 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00, + 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70, + 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, + 0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static PSURFOBJ CharCellSurfObj; +static HBITMAP hCharCellBitmap; + +VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap); + +// Set things up for a character cell surface +void CreateCellCharSurface() +{ + PSURFGDI surfgdi; + PBITMAPOBJ pbo; + + CharCellSurfObj = ExAllocatePool(NonPagedPool, sizeof(SURFOBJ)); + surfgdi = ExAllocatePool(NonPagedPool, sizeof(SURFGDI)); + + hCharCellBitmap = W32kCreateBitmap(8, 8, 1, 8, NULL); // 8x8, 1 plane, 8 bits per pel + + pbo = BITMAPOBJ_HandleToPtr(hCharCellBitmap); + ASSERT( pbo ); +// VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap) + BitmapToSurf(0, surfgdi, CharCellSurfObj, pbo); // Make the bitmap a surface + BITMAPOBJ_ReleasePtr( hCharCellBitmap ); +} + +void grWriteCellChar(PSURFOBJ target, + int x, + int y, + int charcode, + COLORREF color) +{ + RECTL DestRect; + POINTL SourcePoint; + + char *bigbit, *mover; + unsigned char thebyte, thebit, idxColor; + int i, j, charcode8, i8; + + if (charcode < 0 || charcode > 255) + return; + + DestRect.left = x; + DestRect.top = y; + DestRect.right = x+8; + DestRect.bottom = y+8; + + SourcePoint.x = 0; + SourcePoint.y = 0; + + bigbit = ExAllocatePool(NonPagedPool, 256); + + // Explode the 1BPP character cell into an 8BPP one due to current GDI limitations.. major FIXME + charcode8 = charcode * 8; + mover = bigbit; + + for (i=0; i<8; i++) + { + thebyte = font_8x8[charcode8 + i]; + i8 = i*8; + for (j=8; j>0; j--) + { + thebit = thebyte & (1 << j); + if(thebit>0) thebit = 1; + *mover = thebit; + mover++; + } + } + + W32kSetBitmapBits(hCharCellBitmap, 256, bigbit); + + // Blt bitmap to screen + EngBitBlt(target, CharCellSurfObj, NULL, NULL, NULL, &DestRect, &SourcePoint, NULL, NULL, NULL, NULL); + + ExFreePool(bigbit); +} + +void grWriteCellString(PSURFOBJ target, + int x, + int y, + const char* string, + COLORREF color) +{ + while (*string) + { + grWriteCellChar(target, x, y, *string++, color); + x += 8; + } +} + +static int gr_cursor_x = 0; +static int gr_cursor_y = 0; +static PBITMAPOBJ gr_text_bitmap = 0; +static int gr_margin_right = 0; +static int gr_margin_top = 0; + +void grGotobitmap(PBITMAPOBJ bitmap ) +{ + gr_text_bitmap = bitmap; +} + +void grSetMargin(int right, int top) +{ + gr_margin_top = top << 3; + gr_margin_right = right << 3; +} + +void grGotoxy(int x, int y) +{ + gr_cursor_x = x; + gr_cursor_y = y; +} + +void grWrite(const char* string) +{ + if (string) + { + COLORREF color; + +// color.value = 127; + grWriteCellString( gr_text_bitmap, + gr_margin_right + (gr_cursor_x << 3), + gr_margin_top + (gr_cursor_y << 3), + string, + color ); + + gr_cursor_x += strlen(string); + } +} + +void grLn() +{ + gr_cursor_y ++; + gr_cursor_x = 0; +} + +void grWriteln(const char* string) +{ + grWrite( string ); + grLn(); +} diff --git a/subsys/win32k/freetype/grfont.h b/subsys/win32k/freetype/grfont.h new file mode 100644 index 0000000..2697e00 --- /dev/null +++ b/subsys/win32k/freetype/grfont.h @@ -0,0 +1,16 @@ +#ifndef GRFONT_H +#define GRFONT_H + +#include "graph.h" + + extern const unsigned char font_8x8[]; + + extern void grGotobitmap( grBitmap* bitmap ); + extern void grSetMargin( int right, int top ); + extern void grGotoxy ( int x, int y ); + + extern void grWrite ( const char* string ); + extern void grWriteln( const char* string ); + extern void grLn(); + +#endif /* GRFONT_H */ diff --git a/subsys/win32k/freetype/include/freetype/config/ftconfig.h b/subsys/win32k/freetype/include/freetype/config/ftconfig.h new file mode 100644 index 0000000..338e22c --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/config/ftconfig.h @@ -0,0 +1,187 @@ +/***************************************************************************/ +/* */ +/* ftconfig.h */ +/* */ +/* ANSI-specific configuration file (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This header file contains a number of macro definitions that are used */ + /* by the rest of the engine. Most of the macros here are automatically */ + /* determined at compile time, and you should not need to change it to */ + /* port FreeType, except to compile the library with a non-ANSI */ + /* compiler. */ + /* */ + /* Note however that if some specific modifications are needed, we */ + /* advise you to place a modified copy in your build directory. */ + /* */ + /* The build directory is usually `freetype/builds/', and */ + /* contains system-specific files that are always included first when */ + /* building the library. */ + /* */ + /* This ANSI version should stay in `include/freetype/config'. */ + /* */ + /*************************************************************************/ + + +#ifndef FTCONFIG_H +#define FTCONFIG_H + + + /* Include the header file containing all developer build options */ +#include + + + /*************************************************************************/ + /* */ + /* PLATFORM-SPECIFIC CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled to suit a specific system. The current */ + /* ones are defaults used to compile FreeType in an ANSI C environment */ + /* (16bit compilers are also supported). Copy this file to your own */ + /* `freetype/builds/' directory, and edit it to port the engine. */ + /* */ + /*************************************************************************/ + + + /* We use values to know the sizes of the types. */ +#include + + /* The number of bytes in an `int' type. */ +#if UINT_MAX == 0xFFFFFFFF +#define FT_SIZEOF_INT 4 +#elif UINT_MAX == 0xFFFF +#define FT_SIZEOF_INT 2 +#elif UINT_MAX > 0xFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF +#define FT_SIZEOF_INT 8 +#else +#error "Unsupported number of bytes in `int' type!" +#endif + + /* The number of bytes in a `long' type. */ +#if ULONG_MAX == 0xFFFFFFFF +#define FT_SIZEOF_LONG 4 +#elif ULONG_MAX > 0xFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF +#define FT_SIZEOF_LONG 8 +#else +#error "Unsupported number of bytes in `long' type!" +#endif + + + /* Preferred alignment of data */ +#define FT_ALIGNMENT 8 + + + /* UNUSED is a macro used to indicate that a given parameter is not used */ + /* -- this is only used to get rid of unpleasant compiler warnings */ +#ifndef FT_UNUSED +#define FT_UNUSED( arg ) ( (arg) = (arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* AUTOMATIC CONFIGURATION MACROS */ + /* */ + /* These macros are computed from the ones defined above. Don't touch */ + /* their definition, unless you know precisely what you are doing. No */ + /* porter should need to mess with them. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* IntN types */ + /* */ + /* Used to guarantee the size of some specific integers. */ + /* */ + typedef signed short FT_Int16; + typedef unsigned short FT_UInt16; + +#if FT_SIZEOF_INT == 4 + + typedef signed int FT_Int32; + typedef unsigned int FT_UInt32; + +#elif FT_SIZEOF_LONG == 4 + + typedef signed long FT_Int32; + typedef unsigned long FT_UInt32; + +#else +#error "no 32bit type found -- please check your configuration files" +#endif + +#if FT_SIZEOF_LONG == 8 + + /* FT_LONG64 must be defined if a 64-bit type is available */ +#define FT_LONG64 +#define FT_INT64 long + +#else + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro in */ + /* `ftoption.h'. */ + /* */ + /* Note that this will produce many -ansi warnings during library */ + /* compilation, and that in many cases, the generated code will be */ + /* neither smaller nor faster! */ + /* */ +#ifdef FTCALC_USE_LONG_LONG + +#define FT_LONG64 +#define FT_INT64 long long + +#endif /* FTCALC_USE_LONG_LONG */ +#endif /* FT_SIZEOF_LONG == 8 */ + + +#ifdef FT_MAKE_OPTION_SINGLE_OBJECT +#define LOCAL_DEF static +#define LOCAL_FUNC static +#else +#define LOCAL_DEF extern +#define LOCAL_FUNC /* nothing */ +#endif + +#ifdef FT_MAKE_OPTION_SINGLE_LIBRARY_OBJECT +#define BASE_DEF( x ) static x +#define BASE_FUNC( x ) static x +#else +#define BASE_DEF( x ) extern x +#define BASE_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_DEF +#define FT_EXPORT_DEF( x ) extern x +#endif + +#ifndef FT_EXPORT_FUNC +#define FT_EXPORT_FUNC( x ) extern x +#endif + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + +#endif /* FTCONFIG_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/config/ftmodule.h b/subsys/win32k/freetype/include/freetype/config/ftmodule.h new file mode 100644 index 0000000..50cc46b --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/config/ftmodule.h @@ -0,0 +1,10 @@ +FT_USE_MODULE(autohint_module_class) +FT_USE_MODULE(cff_driver_class) +FT_USE_MODULE(t1cid_driver_class) +FT_USE_MODULE(psnames_module_class) +FT_USE_MODULE(ft_raster1_renderer_class) +FT_USE_MODULE(sfnt_module_class) +FT_USE_MODULE(ft_smooth_renderer_class) +FT_USE_MODULE(tt_driver_class) +FT_USE_MODULE(t1_driver_class) +FT_USE_MODULE(winfnt_driver_class) diff --git a/subsys/win32k/freetype/include/freetype/config/ftoption.h b/subsys/win32k/freetype/include/freetype/config/ftoption.h new file mode 100644 index 0000000..a7e1f40 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/config/ftoption.h @@ -0,0 +1,395 @@ +/***************************************************************************/ +/* */ +/* ftoption.h */ +/* */ +/* User-selectable configuration macros (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTOPTION_H +#define FTOPTION_H + + + /*************************************************************************/ + /* */ + /* USER-SELECTABLE CONFIGURATION MACROS */ + /* */ + /* These macros can be toggled by developers to enable or disable */ + /* certain aspects of FreeType. This is a default file, where all major */ + /* options are enabled. */ + /* */ + /* Note that if some modifications are required for your build, we */ + /* advise you to put a modified copy of this file in your build */ + /* directory, rather than modifying it in-place. */ + /* */ + /* The build directory is normally `freetype/builds/' and */ + /* contains build or system-specific files that are included in */ + /* priority when building the library. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Convenience functions support */ + /* */ + /* Some functions of the FreeType 2 API are provided as a convenience */ + /* for client applications and developers. However, they are not */ + /* required to build and run the library itself. */ + /* */ + /* By defining this configuration macro, you'll disable the */ + /* compilation of these functions at build time. This can be useful */ + /* to reduce the library's code size when you don't need any of */ + /* these functions. */ + /* */ + /* All convenience functions are declared as such in their */ + /* documentation. */ + /* */ +#undef FT_CONFIG_OPTION_NO_CONVENIENCE_FUNCS + + + /*************************************************************************/ + /* */ + /* Alternate Glyph Image Format support */ + /* */ + /* By default, the glyph images returned by the FreeType glyph loader */ + /* can either be a pixmap or a vectorial outline defined through */ + /* Bezier control points. When defining the following configuration */ + /* macro, some font drivers will be able to register alternate */ + /* glyph image formats. */ + /* */ + /* Unset this macro if you are sure that you will never use a font */ + /* driver with an alternate glyph format; this will reduce the size of */ + /* the base layer code. */ + /* */ + /* Note that a few Type 1 fonts, as well as Windows `vector' fonts */ + /* use a vector `plotter' format that isn't supported when this */ + /* macro is undefined. */ + /* */ +#define FT_CONFIG_OPTION_ALTERNATE_GLYPH_FORMATS + + + /*************************************************************************/ + /* */ + /* Glyph Postscript Names handling */ + /* */ + /* By default, FreeType 2 is compiled with the `PSNames' module. This */ + /* This module is in charge of converting a glyph name string into a */ + /* Unicode value, or return a Macintosh standard glyph name for the */ + /* use with the TrueType `post' table. */ + /* */ + /* Undefine this macro if you do not want `PSNames' compiled in your */ + /* build of FreeType. This has the following effects: */ + /* */ + /* - The TrueType driver will provide its own set of glyph names, */ + /* if you build it to support postscript names in the TrueType */ + /* `post' table. */ + /* */ + /* - The Type 1 driver will not be able to synthetize a Unicode */ + /* charmap out of the glyphs found in the fonts. */ + /* */ + /* You would normally undefine this configuration macro when building */ + /* a version of FreeType that doesn't contain a Type 1 or CFF driver. */ + /* */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Postscript Names to Unicode Values support */ + /* */ + /* By default, FreeType 2 is built with the `PSNames' module compiled */ + /* in. Among other things, the module is used to convert a glyph name */ + /* into a Unicode value. This is especially useful in order to */ + /* synthetize on the fly a Unicode charmap from the CFF/Type 1 driver */ + /* through a big table named the `Adobe Glyph List' (AGL). */ + /* */ + /* Undefine this macro if you do not want the Adobe Glyph List */ + /* compiled in your `PSNames' module. The Type 1 driver will not be */ + /* able to synthetize a Unicode charmap out of the glyphs found in the */ + /* fonts. */ + /* */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /*************************************************************************/ + /* */ + /* Many compilers provide the non-ANSI `long long' 64-bit type. You can */ + /* activate it by defining the FTCALC_USE_LONG_LONG macro. Note that */ + /* this will produce many -ansi warnings during library compilation, and */ + /* that in many cases the generated code will not be smaller or faster! */ + /* */ +#undef FTCALC_USE_LONG_LONG + + + /*************************************************************************/ + /* */ + /* DLL export compilation */ + /* */ + /* When compiling FreeType as a DLL, some systems/compilers need a */ + /* special keyword in front OR after the return type of function */ + /* declarations. */ + /* */ + /* Two macros are used within the FreeType source code to define */ + /* exported library functions: FT_EXPORT_DEF and FT_EXPORT_FUNC. */ + /* */ + /* FT_EXPORT_DEF( return_type ) */ + /* */ + /* is used in a function declaration, as in */ + /* */ + /* FT_EXPORT_DEF( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ); */ + /* */ + /* */ + /* FT_EXPORT_FUNC( return_type ) */ + /* */ + /* is used in a function definition, as in */ + /* */ + /* FT_EXPORT_FUNC( FT_Error ) */ + /* FT_Init_FreeType( FT_Library* alibrary ) */ + /* { */ + /* ... some code ... */ + /* return FT_Err_Ok; */ + /* } */ + /* */ + /* You can provide your own implementation of FT_EXPORT_DEF and */ + /* FT_EXPORT_FUNC here if you want. If you leave them undefined, they */ + /* will be later automatically defined as `extern return_type' to */ + /* allow normal compilation. */ + /* */ +#undef FT_EXPORT_DEF +#undef FT_EXPORT_FUNC + + + /*************************************************************************/ + /* */ + /* Debug level */ + /* */ + /* FreeType can be compiled in debug or trace mode. In debug mode, */ + /* errors are reported through the `ftdebug' component. In trace */ + /* mode, additional messages are sent to the standard output during */ + /* execution. */ + /* */ + /* Define FT_DEBUG_LEVEL_ERROR to build the library in debug mode. */ + /* Define FT_DEBUG_LEVEL_TRACE to build it in trace mode. */ + /* */ + /* Don't define any of these macros to compile in `release' mode! */ + /* */ +#define FT_DEBUG_LEVEL_ERROR +#define FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* Computation Algorithms */ + /* */ + /* Used for debugging, this configuration macro should disappear */ + /* soon. */ + /* */ +#define FT_CONFIG_OPTION_OLD_CALCS + + + /*************************************************************************/ + /* */ + /* The size in bytes of the render pool used by the scan-line converter */ + /* to do all of its work. */ + /* */ + /* This must be greater than 4kByte. */ + /* */ +#define FT_RENDER_POOL_SIZE 16384 + + + /*************************************************************************/ + /* */ + /* FT_MAX_MODULES */ + /* */ + /* The maximum number of modules that can be registered in a single */ + /* FreeType library object. 16 is the default. */ + /* */ +#define FT_MAX_MODULES 16 + + + /*************************************************************************/ + /* */ + /* FT_MAX_EXTENSIONS */ + /* */ + /* The maximum number of extensions that can be registered in a single */ + /* font driver. 8 is the default. */ + /* */ + /* If you don't know what this means, you certainly do not need to */ + /* change this value. */ + /* */ +#define FT_MAX_EXTENSIONS 8 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_EMBEDDED_BITMAPS if you want to support */ + /* embedded bitmaps in all formats using the SFNT module (namely */ + /* TrueType & OpenType). */ + /* */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_POSTSCRIPT_NAMES if you want to be able to */ + /* load and enumerate the glyph Postscript names in a TrueType or */ + /* OpenType file. */ + /* */ + /* Note that when you do not compile the `PSNames' module by undefining */ + /* the above FT_CONFIG_OPTION_POSTSCRIPT_NAMES, the `sfnt' module will */ + /* contain additional code used to read the PS Names table from a font. */ + /* */ + /* (By default, the module uses `PSNames' to extract glyph names.) */ + /* */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_SFNT_NAMES if your applications need to */ + /* access the internal name table in a SFNT-based format like TrueType */ + /* or OpenType. The name table contains various strings used to */ + /* describe the font, like family name, copyright, version, etc. It */ + /* does not contain any glyph name though. */ + /* */ + /* Accessing SFNT names is done through the functions declared in */ + /* `freetype/ftnames.h'. */ + /* */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_BYTECODE_INTERPRETER if you want to compile */ + /* a bytecode interpreter in the TrueType driver. Note that there are */ + /* important patent issues related to the use of the interpreter. */ + /* */ + /* By undefining this, you will only compile the code necessary to load */ + /* TrueType glyphs without hinting. */ + /* */ +#undef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + + /*************************************************************************/ + /* */ + /* Define TT_CONFIG_OPTION_INTERPRETER_SWITCH to compile the TrueType */ + /* bytecode interpreter with a huge switch statement, rather than a call */ + /* table. This results in smaller and faster code for a number of */ + /* architectures. */ + /* */ + /* Note however that on some compiler/processor combinations, undefining */ + /* this macro will generate faster, though larger, code. */ + /* */ +#define TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* T1_MAX_STACK_DEPTH is the maximal depth of the token stack used by */ + /* the Type 1 parser (see t1load.c). A minimum of 16 is required. */ + /* */ +#define T1_MAX_STACK_DEPTH 16 + + + /*************************************************************************/ + /* */ + /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and */ + /* arrays in the Type 1 stream (see t1load.c). A minimum of 4 is */ + /* required. */ + /* */ +#define T1_MAX_DICT_DEPTH 5 + + + /*************************************************************************/ + /* */ + /* T1_MAX_SUBRS_CALLS details the maximum number of nested sub-routine */ + /* calls during glyph loading. */ + /* */ +#define T1_MAX_SUBRS_CALLS 8 + + + /*************************************************************************/ + /* */ + /* T1_MAX_CHARSTRING_OPERANDS is the charstring stack's capacity. */ + /* */ +#define T1_MAX_CHARSTRINGS_OPERANDS 32 + + + /*************************************************************************/ + /* */ + /* Define T1_CONFIG_OPTION_DISABLE_HINTER if you want to generate a */ + /* driver with no hinter. This can be useful to debug the parser. */ + /* */ +#undef T1_CONFIG_OPTION_DISABLE_HINTER + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of `t1afm', which is in charge of reading Type 1 AFM */ + /* files into an existing face. Note that if set, the T1 driver will be */ + /* unable to produce kerning distances. */ + /* */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* Define this configuration macro if you want to prevent the */ + /* compilation of the Multiple Masters font support in the Type 1 */ + /* driver. */ + /* */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + +#endif /* FTOPTION_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/freetype.h b/subsys/win32k/freetype/include/freetype/freetype.h new file mode 100644 index 0000000..29316c6 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/freetype.h @@ -0,0 +1,2286 @@ +/***************************************************************************/ +/* */ +/* freetype.h */ +/* */ +/* FreeType high-level API and common types (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FREETYPE_H +#define FREETYPE_H + + + /*************************************************************************/ + /* */ + /* The `raster' component duplicates some of the declarations in */ + /* freetype.h for stand-alone use if _FREETYPE_ isn't defined. */ + /* */ +#define _FREETYPE_ + + + /*************************************************************************/ + /* */ + /* The FREETYPE_MAJOR and FREETYPE_MINOR macros are used to version the */ + /* new FreeType design, which is able to host several kinds of font */ + /* drivers. It starts at 2.0. */ + /* */ +#define FREETYPE_MAJOR 2 +#define FREETYPE_MINOR 0 + + +#include /* read configuration information */ +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S I C T Y P E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Metrics */ + /* */ + /* */ + /* A structure used to model the metrics of a single glyph. Note */ + /* that values are expressed in 26.6 fractional pixel format or in */ + /* font units, depending on context. */ + /* */ + /* */ + /* width :: The glyph's width. */ + /* */ + /* height :: The glyph's height. */ + /* */ + /* horiBearingX :: Horizontal left side bearing. */ + /* */ + /* horiBearingY :: Horizontal top side bearing. */ + /* */ + /* horiAdvance :: Horizontal advance width. */ + /* */ + /* vertBearingX :: Vertical left side bearing. */ + /* */ + /* vertBearingY :: Vertical top side bearing. */ + /* */ + /* vertAdvance :: Vertical advance height. */ + /* */ + typedef struct FT_Glyph_Metrics_ + { + FT_Pos width; /* glyph width */ + FT_Pos height; /* glyph height */ + + FT_Pos horiBearingX; /* left side bearing in horizontal layouts */ + FT_Pos horiBearingY; /* top side bearing in horizontal layouts */ + FT_Pos horiAdvance; /* advance width for horizontal layout */ + + FT_Pos vertBearingX; /* left side bearing in vertical layouts */ + FT_Pos vertBearingY; /* top side bearing in vertical layouts */ + FT_Pos vertAdvance; /* advance height for vertical layout */ + + } FT_Glyph_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Generic_Finalizer */ + /* */ + /* */ + /* Describes a function used to destroy the `client' data of any */ + /* FreeType object. See the description of the FT_Generic type for */ + /* details of usage. */ + /* */ + /* */ + /* The address of the FreeType object which is under finalization. */ + /* Its client data is accessed through its `generic' field. */ + /* */ + typedef void (*FT_Generic_Finalizer)(void* object); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Generic */ + /* */ + /* */ + /* Client applications often need to associate their own data to a */ + /* variety of FreeType core objects. For example, a text layout API */ + /* might want to associate a glyph cache to a given size object. */ + /* */ + /* Most FreeType object contains a `generic' field, of type */ + /* FT_Generic, which usage is left to client applications and font */ + /* servers. */ + /* */ + /* It can be used to store a pointer to client-specific data, as well */ + /* as the address of a `finalizer' function, which will be called by */ + /* FreeType when the object is destroyed (for example, the previous */ + /* client example would put the address of the glyph cache destructor */ + /* in the `finalizer' field). */ + /* */ + /* */ + /* data :: A typeless pointer to any client-specified data. This */ + /* field is completely ignored by the FreeType library. */ + /* */ + /* finalizer :: A pointer to a `generic finalizer' function, which */ + /* will be called when the object is destroyed. If this */ + /* field is set to NULL, no code will be called. */ + /* */ + typedef struct FT_Generic_ + { + void* data; + FT_Generic_Finalizer finalizer; + + } FT_Generic; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bitmap_Size */ + /* */ + /* */ + /* An extremely simple structure used to model the size of a bitmap */ + /* strike (i.e., a bitmap instance of the font for a given */ + /* resolution) in a fixed-size font face. This is used for the */ + /* `available_sizes' field of the FT_Face_Properties structure. */ + /* */ + /* */ + /* height :: The character height in pixels. */ + /* */ + /* width :: The character width in pixels. */ + /* */ + typedef struct FT_Bitmap_Size_ + { + FT_Short height; + FT_Short width; + + } FT_Bitmap_Size; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Library */ + /* */ + /* */ + /* A handle to a FreeType library instance. Each `library' is */ + /* completely independent from the others; it is the `root' of a set */ + /* of objects like fonts, faces, sizes, etc. */ + /* */ + /* It also embeds a system object (see FT_System), as well as a */ + /* scan-line converter object (see FT_Raster). */ + /* */ + /* */ + /* Library objects are created through FT_Init_FreeType(). */ + /* */ + typedef struct FT_LibraryRec_ *FT_Library; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Module */ + /* */ + /* */ + /* A handle to a given FreeType module object. Each module can be a */ + /* font driver, a renderer, or anything else that provides services */ + /* to the formers. */ + /* */ + typedef struct FT_ModuleRec_* FT_Module; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Driver */ + /* */ + /* */ + /* A handle to a given FreeType font driver object. Each font driver */ + /* is able to create faces, sizes, glyph slots, and charmaps from the */ + /* resources whose format it supports. */ + /* */ + /* A driver can support either bitmap, graymap, or scalable font */ + /* formats. */ + /* */ + typedef struct FT_DriverRec_* FT_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Renderer */ + /* */ + /* */ + /* A handle to a given FreeType renderer. A renderer is in charge of */ + /* converting a glyph image to a bitmap, when necessary. Each */ + /* supports a given glyph image format, and one or more target */ + /* surface depths. */ + /* */ + typedef struct FT_RendererRec_* FT_Renderer; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Face */ + /* */ + /* */ + /* A handle to a given driver face object. A face object contains */ + /* all the instance and glyph independent data of a font file */ + /* typeface. */ + /* */ + /* A face object is created from a resource object through the */ + /* new_face() method of a given driver. */ + /* */ + typedef struct FT_FaceRec_* FT_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Size */ + /* */ + /* */ + /* A handle to a given driver size object. Such an object models the */ + /* _resolution_ AND _size_ dependent state of a given driver face */ + /* size. */ + /* */ + /* A size object is always created from a given face object. It is */ + /* discarded automatically by its parent face. */ + /* */ + typedef struct FT_SizeRec_* FT_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphSlot */ + /* */ + /* */ + /* A handle to a given `glyph slot'. A slot is a container where it */ + /* is possible to load any of the glyphs contained within its parent */ + /* face. */ + /* */ + /* A glyph slot is created from a given face object. It is discarded */ + /* automatically by its parent face. */ + /* */ + typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_CharMap */ + /* */ + /* */ + /* A handle to a given character map. A charmap is used to translate */ + /* character codes in a given encoding into glyph indexes for its */ + /* parent's face. Some font formats may provide several charmaps per */ + /* font. */ + /* */ + /* A charmap is created from a given face object. It is discarded */ + /* automatically by its parent face. */ + /* */ + typedef struct FT_CharMapRec_* FT_CharMap; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Encoding */ + /* */ + /* */ + /* An enumeration used to specify encodings supported by charmaps. */ + /* Used in the FT_Select_CharMap() API function. */ + /* */ + /* */ + /* Because of 32-bit charcodes defined in Unicode (i.e., surrogates), */ + /* all character codes must be expressed as FT_Longs. */ + /* */ + typedef enum FT_Encoding_ + { + ft_encoding_none = 0, + ft_encoding_symbol = FT_MAKE_TAG( 's', 'y', 'm', 'b' ), + ft_encoding_unicode = FT_MAKE_TAG( 'u', 'n', 'i', 'c' ), + ft_encoding_latin_2 = FT_MAKE_TAG( 'l', 'a', 't', '2' ), + ft_encoding_sjis = FT_MAKE_TAG( 's', 'j', 'i', 's' ), + ft_encoding_gb2312 = FT_MAKE_TAG( 'g', 'b', ' ', ' ' ), + ft_encoding_big5 = FT_MAKE_TAG( 'b', 'i', 'g', '5' ), + ft_encoding_wansung = FT_MAKE_TAG( 'w', 'a', 'n', 's' ), + ft_encoding_johab = FT_MAKE_TAG( 'j', 'o', 'h', 'a' ), + + ft_encoding_adobe_standard = FT_MAKE_TAG( 'A', 'D', 'O', 'B' ), + ft_encoding_adobe_expert = FT_MAKE_TAG( 'A', 'D', 'B', 'E' ), + ft_encoding_adobe_custom = FT_MAKE_TAG( 'A', 'D', 'B', 'C' ), + + ft_encoding_apple_roman = FT_MAKE_TAG( 'a', 'r', 'm', 'n' ) + + /* other encodings might be defined in the future */ + + } FT_Encoding; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_CharMapRec */ + /* */ + /* */ + /* The base charmap class. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* flags :: A set of bit flags used to describe the charmap. */ + /* Each bit indicates that a given encoding is */ + /* supported. */ + /* */ + /* platform_id :: An ID number describing the platform for the */ + /* following encoding ID. This comes directly from */ + /* the TrueType specification and should be emulated */ + /* for other formats. */ + /* */ + /* encoding_id :: A platform specific encoding number. This also */ + /* comes from the TrueType specification and should be */ + /* emulated similarly. */ + /* */ + /* */ + /* We STRONGLY recommmend emulating a Unicode charmap for drivers */ + /* that do not support TrueType or OpenType. */ + /* */ + typedef struct FT_CharMapRec_ + { + FT_Face face; + FT_Encoding encoding; + FT_UShort platform_id; + FT_UShort encoding_id; + + } FT_CharMapRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* B A S E O B J E C T C L A S S E S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* FreeType base face class */ + /* */ + /* */ + /* FT_FaceRec */ + /* */ + /* */ + /* FreeType root face class structure. A face object models the */ + /* resolution and point-size independent data found in a font file. */ + /* */ + /* */ + /* num_faces :: In the case where the face is located in a */ + /* collection (i.e., a resource which embeds */ + /* several faces), this is the total number of */ + /* faces found in the resource. 1 by default. */ + /* */ + /* face_index :: The index of the face in its resource. */ + /* Usually, this is 0 for all normal font */ + /* formats. It can be more in the case of */ + /* collections (which embed several fonts in a */ + /* single resource/file). */ + /* */ + /* face_flags :: A set of bit flags that give important */ + /* information about the face; see the */ + /* FT_FACE_FLAG_XXX macros for details. */ + /* */ + /* style_flags :: A set of bit flags indicating the style of */ + /* the face (i.e., italic, bold, underline, */ + /* etc). */ + /* */ + /* num_glyphs :: The total number of glyphs in the face. */ + /* */ + /* family_name :: The face's family name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's family (like `Times New */ + /* Roman', `Bodoni', `Garamond', etc). This */ + /* is a least common denominator used to list */ + /* fonts. Some formats (TrueType & OpenType) */ + /* provide localized and Unicode versions of */ + /* this string. Applications should use the */ + /* format specific interface to access them. */ + /* */ + /* style_name :: The face's style name. This is an ASCII */ + /* string, usually in English, which describes */ + /* the typeface's style (like `Italic', */ + /* `Bold', `Condensed', etc). Not all font */ + /* formats provide a style name, so this field */ + /* is optional, and can be set to NULL. As */ + /* for `family_name', some formats provide */ + /* localized/Unicode versions of this string. */ + /* Applications should use the format specific */ + /* interface to access them. */ + /* */ + /* num_fixed_sizes :: The number of fixed sizes available in this */ + /* face. This should be set to 0 for scalable */ + /* fonts, unless its resource includes a */ + /* complete set of glyphs (called a `strike') */ + /* for the specified size. */ + /* */ + /* available_sizes :: An array of sizes specifying the available */ + /* bitmap/graymap sizes that are contained in */ + /* in the font resource. Should be set to */ + /* NULL if the field `num_fixed_sizes' is set */ + /* to 0. */ + /* */ + /* num_charmaps :: The total number of character maps in the */ + /* face. */ + /* */ + /* charmaps :: A table of pointers to the face's charmaps */ + /* Used to scan the list of available charmaps */ + /* this table might change after a call to */ + /* FT_Attach_File/Stream (e.g. when it used */ + /* to hook and additional encoding/CMap to */ + /* the face object). */ + /* */ + /* generic :: A field reserved for client uses. See the */ + /* FT_Generic type description. */ + /* */ + /* bbox :: The font bounding box. Coordinates are */ + /* expressed in font units (see units_per_EM). */ + /* The box is large enough to contain any */ + /* glyph from the font. Thus, bbox.yMax can */ + /* be seen as the `maximal ascender', */ + /* bbox.yMin as the `minimal descender', and */ + /* the maximal glyph width is given by */ + /* `bbox.xMax-bbox.xMin' (not to be confused */ + /* with the maximal _advance_width_). Only */ + /* relevant for scalable formats. */ + /* */ + /* units_per_EM :: The number of font units per EM square for */ + /* this face. This is typically 2048 for */ + /* TrueType fonts, 1000 for Type1 fonts, and */ + /* should be set to the (unrealistic) value 1 */ + /* for fixed-sizes fonts. Only relevant for */ + /* scalable formats. */ + /* */ + /* ascender :: The face's ascender is the vertical */ + /* distance from the baseline to the topmost */ + /* point of any glyph in the face. This */ + /* field's value is positive, expressed in */ + /* font units. Some font designs use a value */ + /* different from `bbox.yMax'. Only relevant */ + /* for scalable formats. */ + /* */ + /* descender :: The face's descender is the vertical */ + /* distance from the baseline to the */ + /* bottommost point of any glyph in the face. */ + /* This field's value is positive, expressed */ + /* in font units. Some font designs use a */ + /* value different from `-bbox.yMin'. Only */ + /* relevant for scalable formats. */ + /* */ + /* height :: The face's height is the vertical distance */ + /* from one baseline to the next when writing */ + /* several lines of text. Its value is always */ + /* positive, expressed in font units. The */ + /* value can be computed as */ + /* `ascender+descender+line_gap' where the */ + /* value of `line_gap' is also called */ + /* `external leading'. Only relevant for */ + /* scalable formats. */ + /* */ + /* max_advance_width :: The maximal advance width, in font units, */ + /* for all glyphs in this face. This can be */ + /* used to make word wrapping computations */ + /* faster. Only relevant for scalable */ + /* formats. */ + /* */ + /* max_advance_height :: The maximal advance height, in font units, */ + /* for all glyphs in this face. This is only */ + /* relevant for vertical layouts, and should */ + /* be set to the `height' for fonts that do */ + /* not provide vertical metrics. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_position :: The position, in font units, of the */ + /* underline line for this face. It's the */ + /* center of the underlining stem. Only */ + /* relevant for scalable formats. */ + /* */ + /* underline_thickness :: The thickness, in font units, of the */ + /* underline for this face. Only relevant for */ + /* scalable formats. */ + /* */ + /* driver :: A handle to the face's parent driver */ + /* object. */ + /* */ + /* memory :: A handle to the face's parent memory */ + /* object. Used for the allocation of */ + /* subsequent objects. */ + /* */ + /* stream :: A handle to the face's stream. */ + /* */ + /* glyph :: The face's associated glyph slot(s). This */ + /* object is created automatically with a new */ + /* face object. However, certain kinds of */ + /* applications (mainly tools like converters) */ + /* can need more than one slot to ease their */ + /* task. */ + /* */ + /* sizes_list :: The list of child sizes for this face. */ + /* */ + /* max_points :: The maximal number of points used to store */ + /* the vectorial outline of any glyph in this */ + /* face. If this value cannot be known in */ + /* advance, or if the face isn't scalable, */ + /* this should be set to 0. Only relevant for */ + /* scalable formats. */ + /* */ + /* max_contours :: The maximal number of contours used to */ + /* store the vectorial outline of any glyph in */ + /* this face. If this value cannot be known */ + /* in advance, or if the face isn't scalable, */ + /* this should be set to 0. Only relevant for */ + /* scalable formats. */ + /* */ + /* transform_matrix :: A 2x2 matrix of 16.16 coefficients used */ + /* to transform glyph outlines after they are */ + /* loaded from the font. Only used by the */ + /* convenience functions. */ + /* */ + /* transform_delta :: A translation vector used to transform */ + /* glyph outlines after they are loaded from */ + /* the font. Only used by the convenience */ + /* functions. */ + /* */ + /* transform_flags :: Some flags used to classify the transform. */ + /* Only used by the convenience functions. */ + /* */ + typedef struct FT_FaceRec_ + { + FT_Long num_faces; + FT_Long face_index; + + FT_Long face_flags; + FT_Long style_flags; + + FT_Long num_glyphs; + + FT_String* family_name; + FT_String* style_name; + + FT_Int num_fixed_sizes; + FT_Bitmap_Size* available_sizes; + + /* the face's table of available charmaps */ + FT_Int num_charmaps; + FT_CharMap* charmaps; + + FT_Generic generic; + + /* the following are only relevant for scalable outlines */ + FT_BBox bbox; + + FT_UShort units_per_EM; + FT_Short ascender; + FT_Short descender; + FT_Short height; + + FT_Short max_advance_width; + FT_Short max_advance_height; + + FT_Short underline_position; + FT_Short underline_thickness; + + FT_GlyphSlot glyph; + FT_Size size; + + /************************************************************/ + /* The following fields should be considered private and */ + /* rarely, if ever, used directly by client applications. */ + + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + + FT_CharMap charmap; + FT_ListRec sizes_list; + + FT_Generic autohint; + void* extensions; + + FT_UShort max_points; + FT_Short max_contours; + + FT_Matrix transform_matrix; + FT_Vector transform_delta; + FT_Int transform_flags; + + } FT_FaceRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_SCALABLE */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face provides */ + /* vectorial outlines (i.e., TrueType or Type1). This doesn't */ + /* prevent embedding of bitmap strikes though, i.e., a given face can */ + /* have both this bit set, and a `num_fixed_sizes' property > 0. */ + /* */ +#define FT_FACE_FLAG_SCALABLE 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_SIZES */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* `fixed sizes', i.e., bitmap strikes for some given pixel sizes. */ + /* See the `num_fixed_sizes' and `available_sizes' face properties */ + /* for more information. */ + /* */ +#define FT_FACE_FLAG_FIXED_SIZES 2 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FIXED_WIDTH */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* fixed-width characters (like Courier, Lucida, MonoType, etc.). */ + /* */ +#define FT_FACE_FLAG_FIXED_WIDTH 4 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_SFNT */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face uses the */ + /* `sfnt' storage fomat. For now, this means TrueType or OpenType. */ + /* */ +#define FT_FACE_FLAG_SFNT 8 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_HORIZONTAL */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* horizontal glyph metrics. This should be set for all common */ + /* formats, but who knows. */ + /* */ +#define FT_FACE_FLAG_HORIZONTAL 0x10 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_VERTICAL */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* vertical glyph metrics. If not set, the glyph loader will */ + /* synthetize vertical metrics itself to help display vertical text */ + /* correctly. */ + /* */ +#define FT_FACE_FLAG_VERTICAL 0x20 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_KERNING */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face contains */ + /* kerning information. When set, this information can be retrieved */ + /* through the function FT_Get_Kerning(). Note that when unset, this */ + /* function will always return the kerning vector (0,0). */ + /* */ +#define FT_FACE_FLAG_KERNING 0x40 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_FAST_GLYPHS */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the glyphs in a given */ + /* font can be retrieved very quickly, and that a glyph cache is thus */ + /* not necessary for any of its child size objects. */ + /* */ + /* This flag should really be set for fixed-size formats like FNT, */ + /* where each glyph bitmap is available directly in binary form */ + /* without any kind of compression. */ + /* */ +#define FT_FACE_FLAG_FAST_GLYPHS 0x80 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_MULTIPLE_MASTERS */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the font contains */ + /* multiple masters and is capable of interpolating between them. */ + /* */ +#define FT_FACE_FLAG_MULTIPLE_MASTERS 0x100 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_GLYPH_NAMES */ + /* */ + /* */ + /* A bit-field constant, used to indicate that the font contains */ + /* glyph names that can be retrieved through FT_Get_Glyph_Name(). */ + /* */ +#define FT_FACE_FLAG_GLYPH_NAMES 0x200 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FACE_FLAG_EXTERNAL_STREAM */ + /* */ + /* */ + /* This bit field is used internally by FreeType to indicate that */ + /* a face's stream was provided by the client application and should */ + /* not be destroyed by FT_Done_Face(). */ + /* */ +#define FT_FACE_FLAG_EXTERNAL_STREAM 0x4000 + + +#define FT_HAS_HORIZONTAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_HORIZONTAL ) +#define FT_HAS_VERTICAL( face ) \ + ( face->face_flags & FT_FACE_FLAG_VERTICAL ) +#define FT_HAS_KERNING( face ) \ + ( face->face_flags & FT_FACE_FLAG_KERNING ) +#define FT_IS_SCALABLE( face ) \ + ( face->face_flags & FT_FACE_FLAG_SCALABLE ) +#define FT_IS_SFNT( face ) \ + ( face->face_flags & FT_FACE_FLAG_SFNT ) +#define FT_IS_FIXED_WIDTH( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) +#define FT_HAS_FIXED_SIZES( face ) \ + ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES ) +#define FT_HAS_FAST_GLYPHS( face ) \ + ( face->face_flags & FT_FACE_FLAG_FAST_GLYPHS ) +#define FT_HAS_GLYPH_NAMES( face ) \ + ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) + +#define FT_HAS_MULTIPLE_MASTERS( face ) \ + ( face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_STYLE_FLAG_ITALIC */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face is */ + /* italicized. */ + /* */ +#define FT_STYLE_FLAG_ITALIC 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_STYLE_FLAG_BOLD */ + /* */ + /* */ + /* A bit-field constant, used to indicate that a given face is */ + /* emboldened. */ + /* */ +#define FT_STYLE_FLAG_BOLD 2 + + + /*************************************************************************/ + /* */ + /* FreeType base size metrics */ + /* */ + /* */ + /* FT_Size_Metrics */ + /* */ + /* */ + /* The size metrics structure returned scaled important distances for */ + /* a given size object. */ + /* */ + /* */ + /* x_ppem :: The character width, expressed in integer pixels. */ + /* This is the width of the EM square expressed in */ + /* pixels, hence the term `ppem' (pixels per EM). */ + /* */ + /* y_ppem :: The character height, expressed in integer pixels. */ + /* This is the height of the EM square expressed in */ + /* pixels, hence the term `ppem' (pixels per EM). */ + /* */ + /* x_scale :: A simple 16.16 fixed point format coefficient used */ + /* to scale horizontal distances expressed in font */ + /* units to fractional (26.6) pixel coordinates. */ + /* */ + /* y_scale :: A simple 16.16 fixed point format coefficient used */ + /* to scale vertical distances expressed in font */ + /* units to fractional (26.6) pixel coordinates. */ + /* */ + /* x_resolution :: The horizontal device resolution for this size */ + /* object, expressed in integer dots per inches */ + /* (dpi). As a convention, fixed font formats set */ + /* this value to 72. */ + /* */ + /* y_resolution :: The vertical device resolution for this size */ + /* object, expressed in integer dots per inches */ + /* (dpi). As a convention, fixed font formats set */ + /* this value to 72. */ + /* */ + /* ascender :: The ascender, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* descender :: The descender, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* height :: The text height, expressed in 26.6 fixed point */ + /* pixels. Always positive. */ + /* */ + /* max_advance :: Maximum horizontal advance, expressed in 26.6 */ + /* fixed point pixels. Always positive. */ + /* */ + /* */ + /* The values of `ascender', `descender', and `height' are only the */ + /* scaled versions of `face->ascender', `face->descender', and */ + /* `face->height'. */ + /* */ + /* Unfortunately, due to glyph hinting, these values might not be */ + /* exact for certain fonts, they thus must be treated as unreliable */ + /* with an error margin of at least one pixel! */ + /* */ + /* Indeed, the only way to get the exact pixel ascender and descender */ + /* is to render _all_ glyphs. As this would be a definite */ + /* performance hit, it is up to client applications to perform such */ + /* computations. */ + /* */ + typedef struct FT_Size_Metrics_ + { + FT_UShort x_ppem; /* horizontal pixels per EM */ + FT_UShort y_ppem; /* vertical pixels per EM */ + + FT_Fixed x_scale; /* two scales used to convert font units */ + FT_Fixed y_scale; /* to 26.6 frac. pixel coordinates.. */ + + FT_Pos ascender; /* ascender in 26.6 frac. pixels */ + FT_Pos descender; /* descender in 26.6 frac. pixels */ + FT_Pos height; /* text height in 26.6 frac. pixels */ + FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */ + + } FT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* FreeType base size class */ + /* */ + /* */ + /* FT_SizeRec */ + /* */ + /* */ + /* FreeType root size class structure. A size object models the */ + /* resolution and pointsize dependent data of a given face. */ + /* */ + /* */ + /* face :: Handle to the parent face object. */ + /* */ + /* generic :: A typeless pointer, which is unused by the FreeType */ + /* library or any of its drivers. It can be used by */ + /* client applications to link their own data to each size */ + /* object. */ + /* */ + /* metrics :: Metrics for this size object. This field is read-only. */ + /* */ + typedef struct FT_SizeRec_ + { + FT_Face face; /* parent face object */ + FT_Generic generic; /* generic pointer for client uses */ + FT_Size_Metrics metrics; /* size metrics */ + + } FT_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SubGlyph */ + /* */ + /* */ + /* The subglyph structure is an internal object used to describe */ + /* subglyphs (for example, in the case of composites). */ + /* */ + /* */ + /* The subglyph implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_SubGlyph_ FT_SubGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphLoader */ + /* */ + /* */ + /* The glyph loader is an internal object used to load several glyphs */ + /* together (for example, in the case of composites). */ + /* */ + /* */ + /* The glyph loader implementation is not part of the high-level API, */ + /* hence the forward structure declaration. */ + /* */ + typedef struct FT_GlyphLoader_ FT_GlyphLoader; + + + /*************************************************************************/ + /* */ + /* FreeType Glyph Slot base class */ + /* */ + /* */ + /* FT_GlyphSlotRec */ + /* */ + /* */ + /* FreeType root glyph slot class structure. A glyph slot is a */ + /* container where individual glyphs can be loaded, be they */ + /* vectorial or bitmap/graymaps. */ + /* */ + /* */ + /* library :: A handle to the FreeType library instance */ + /* this slot belongs to. */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* next :: In some cases (like some font tools), several */ + /* glyph slots per face object can be a good */ + /* thing. As this is rare, the glyph slots are */ + /* listed through a direct, single-linked list */ + /* using its `next' field. */ + /* */ + /* generic :: A typeless pointer which is unused by the */ + /* FreeType library or any of its drivers. It */ + /* can be used by client applications to link */ + /* their own data to each size object. */ + /* */ + /* metrics :: The metrics of the last loaded glyph in the */ + /* slot. The returned values depend on the last */ + /* load flags (see the FT_Load_Glyph() API */ + /* function) and can be expressed either in 26.6 */ + /* fractional pixels or font units. */ + /* */ + /* Note that even when the glyph image is */ + /* transformed, the metrics are not. */ + /* */ + /* linearHoriAdvance :: For scalable formats only, this field holds */ + /* the linearly scaled horizontal advance width */ + /* for the glyph (i.e. the scaled and unhinted */ + /* value of the hori advance). This can be */ + /* important to perform correct WYSIWYG layout */ + /* */ + /* Note that this value is expressed by default */ + /* in 16.16 pixels. However, when the glyph is */ + /* loaded with the FT_LOAD_UNSCALED_LINEAR flag, */ + /* this field contains simply the value of the */ + /* advance in original font units. */ + /* */ + /* linearVertAdvance :: For scalable formats only, this field holds */ + /* the linearly scaled vertical advance height */ + /* for the glyph. See linearHoriAdvance for */ + /* comments. */ + /* */ + /* advance :: This is the transformed advance width for the */ + /* glyph. */ + /* */ + /* format :: This field indicates the format of the image */ + /* contained in the glyph slot. Typically */ + /* ft_glyph_format_bitmap, */ + /* ft_glyph_format_outline, and */ + /* ft_glyph_format_composite, but others are */ + /* possible. */ + /* */ + /* bitmap :: This field is used as a bitmap descriptor */ + /* when the slot format is */ + /* ft_glyph_format_bitmap. Note that the */ + /* address and content of the bitmap buffer can */ + /* change between calls of FT_Load_Glyph() and a */ + /* few other functions. */ + /* */ + /* bitmap_left :: This is the bitmap's left bearing expressed */ + /* in integer pixels. Of course, this is only */ + /* valid if the format is */ + /* ft_glyph_format_bitmap. */ + /* */ + /* bitmap_top :: This is the bitmap's top bearing expressed in */ + /* integer pixels. Remember that this is the */ + /* distance from the baseline to the top-most */ + /* glyph scanline, upwards y-coordinates being */ + /* *positive*. */ + /* */ + /* outline :: The outline descriptor for the current glyph */ + /* image if its format is */ + /* ft_glyph_bitmap_outline. */ + /* */ + /* num_subglyphs :: The number of subglyphs in a composite glyph. */ + /* This format is only valid for the composite */ + /* glyph format, that should normally only be */ + /* loaded with the FT_LOAD_NO_RECURSE flag. */ + /* */ + /* subglyphs :: An array of subglyph descriptors for */ + /* composite glyphs. There are `num_subglyphs' */ + /* elements in there. */ + /* */ + /* control_data :: Certain font drivers can also return the */ + /* control data for a given glyph image (e.g. */ + /* TrueType bytecode, Type 1 charstrings, etc.). */ + /* This field is a pointer to such data. */ + /* */ + /* control_len :: This is the length in bytes of the control */ + /* data. */ + /* */ + /* other :: Really wicked formats can use this pointer to */ + /* present their own glyph image to client apps. */ + /* Note that the app will need to know about the */ + /* image format. */ + /* */ + /* loader :: This is a private object for the glyph slot. */ + /* Do not touch this. */ + /* */ + /* */ + /* If FT_Load_Glyph() is called with default flags (FT_LOAD_DEFAULT), */ + /* the glyph image is loaded in the glyph slot in its native format */ + /* (e.g. a vectorial outline for TrueType and Type 1 formats). */ + /* */ + /* This image can later be converted into a bitmap by calling */ + /* FT_Render_Glyph(). This function finds the current renderer for */ + /* the native image's format then invokes it. */ + /* */ + /* The renderer is in charge of transforming the native image through */ + /* the slot's face transformation fields, then convert it into a */ + /* bitmap that is returned in `slot->bitmap'. */ + /* */ + /* Note that `slot->bitmap_left' and `slot->bitmap_top' are also used */ + /* to specify the position of the bitmap relative to the current pen */ + /* position (e.g. coordinates [0,0] on the baseline). Of course, */ + /* `slot->format' is also changed to `ft_glyph_format_bitmap' . */ + /* */ + typedef struct FT_GlyphSlotRec_ + { + FT_Library library; + FT_Face face; + FT_GlyphSlot next; + FT_UInt flags; + FT_Generic generic; + + FT_Glyph_Metrics metrics; + FT_Fixed linearHoriAdvance; + FT_Fixed linearVertAdvance; + FT_Vector advance; + + FT_Glyph_Format format; + + FT_Bitmap bitmap; + FT_Int bitmap_left; + FT_Int bitmap_top; + + FT_Outline outline; + + FT_UInt num_subglyphs; + FT_SubGlyph* subglyphs; + + void* control_data; + long control_len; + + void* other; + + /* private fields */ + FT_GlyphLoader* loader; + + } FT_GlyphSlotRec; + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* F U N C T I O N S */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_FreeType */ + /* */ + /* */ + /* Initializes a new FreeType library object. The set of drivers */ + /* that are registered by this function is determined at build time. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Init_FreeType( FT_Library* library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_FreeType( FT_Library library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Flags */ + /* */ + /* */ + /* An enumeration used to list the bit flags used within */ + /* FT_Open_Args(). */ + /* */ + /* */ + /* ft_open_memory :: This is a memory-based stream. */ + /* */ + /* ft_open_stream :: Copy the stream from the `stream' field. */ + /* */ + /* ft_open_pathname :: Create a new input stream from a C pathname. */ + /* */ + /* ft_open_driver :: Use the `driver' field. */ + /* */ + /* ft_open_params :: Use the `num_params' & `params' field. */ + /* */ + typedef enum + { + ft_open_memory = 1, + ft_open_stream = 2, + ft_open_pathname = 4, + ft_open_driver = 8, + ft_open_params = 16 + + } FT_Open_Flags; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Parameter */ + /* */ + /* */ + /* A simple structure used to pass more or less generic parameters */ + /* to FT_Open_Face(). */ + /* */ + /* */ + /* tag :: A 4-byte identification tag. */ + /* */ + /* data :: A pointer to the parameter data. */ + /* */ + /* */ + /* The id and function of parameters are driver-specific. */ + /* */ + typedef struct FT_Parameter_ + { + FT_ULong tag; + FT_Pointer data; + + } FT_Parameter; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Args */ + /* */ + /* */ + /* A structure used to indicate how to open a new font file/stream. */ + /* A pointer to such a structure can be used as a parameter for the */ + /* functions FT_Open_Face() & FT_Attach_Stream(). */ + /* */ + /* */ + /* flags :: A set of bit flags indicating how to use the */ + /* structure. */ + /* */ + /* memory_base :: The first byte of the file in memory. */ + /* */ + /* memory_size :: The size in bytes of the file in memory. */ + /* */ + /* pathname :: A pointer to an 8-bit file pathname. */ + /* */ + /* stream :: A handle to a source stream object. */ + /* */ + /* driver :: This field is exclusively used by FT_Open_Face(); */ + /* it simply specifies the font driver to use to open */ + /* the face. If set to 0, FreeType will try to load */ + /* the face with each one of the drivers in its list. */ + /* */ + /* num_params :: The number of extra parameters. */ + /* */ + /* params :: Extra parameters passed to the font driver when */ + /* opening a new face. */ + /* */ + /* */ + /* `stream_type' determines which fields are used to create a new */ + /* input stream. */ + /* */ + /* If it is `ft_stream_memory', a new memory-based stream will be */ + /* created using the memory block specified by `memory_base' and */ + /* `memory_size'. */ + /* */ + /* If it is `ft_stream_pathname', a new stream will be created with */ + /* the `pathname' field, calling the system-specific FT_New_Stream() */ + /* function. */ + /* */ + /* If is is `ft_stream_copy', then the content of `stream' will be */ + /* copied to a new input stream object. The object will be closed */ + /* and destroyed when the face is destroyed itself. Note that this */ + /* means that you should not close the stream before the library */ + /* does! */ + /* */ + typedef struct FT_Open_Args_ + { + FT_Open_Flags flags; + FT_Byte* memory_base; + FT_Long memory_size; + FT_String* pathname; + FT_Stream stream; + FT_Module driver; + FT_Int num_params; + FT_Parameter* params; + + } FT_Open_Args; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_New_Face() can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Face( FT_Library library, + const char* filepathname, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* file_base :: A pointer to the beginning of the font data. */ + /* */ + /* file_size :: The size of the memory chunk used by the font data. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_New_Memory_Face() can be used to determine and/or check the */ + /* font format of a given font resource. If the `face_index' field */ + /* is negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Memory_Face( FT_Library library, + FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* Opens a face object from a given resource and typeface index using */ + /* an `FT_Open_Args' structure. If the face object doesn't exist, it */ + /* will be created. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* args :: A pointer to an `FT_Open_Args' structure which must */ + /* be filled by the caller. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_Open_Face() can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Open_Face( FT_Library library, + FT_Open_Args* args, + FT_Long face_index, + FT_Face* face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_File */ + /* */ + /* */ + /* `Attaches' a given font file to an existing face. This is usually */ + /* to read additional information for a single face object. For */ + /* example, it is used to read the AFM files that come with Type 1 */ + /* fonts in order to add kerning data and other metrics. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If your font file is in memory, or if you want to provide your */ + /* own input stream object, use FT_Attach_Stream(). */ + /* */ + /* The meaning of the `attach' action (i.e., what really happens when */ + /* the new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Attach_File( FT_Face face, + const char* filepathname ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_Stream */ + /* */ + /* */ + /* This function is similar to FT_Attach_File() with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The meaning of the `attach' (i.e. what really happens when the */ + /* new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Face */ + /* */ + /* */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* */ + /* face :: A handle to a target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_Face( FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* Sets the character dimensions of a given face object. The */ + /* `char_width' and `char_height' values are used for the width and */ + /* height, respectively, expressed in 26.6 fractional points. */ + /* */ + /* If the horizontal or vertical resolution values are zero, a */ + /* default value of 72dpi is used. Similarly, if one of the */ + /* character dimensions is zero, its value is set equal to the other. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* char_width :: The character width, in 26.6 fractional points. */ + /* */ + /* char_height :: The character height, in 26.6 fractional */ + /* points. */ + /* */ + /* horz_resolution :: The horizontal resolution. */ + /* */ + /* vert_resolution :: The vertical resolution. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Char_Size( FT_Face face, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* */ + /* Sets the character dimensions of a given face object. The width */ + /* and height are expressed in integer pixels. */ + /* */ + /* If one of the character dimensions is zero, its value is set equal */ + /* to the other. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* face :: A handle to the target face object where the glyph */ + /* will be loaded. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* FT_Set_Transform. */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Char */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* char_code :: The glyph's character code, according to the */ + /* current charmap used in the face. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If the face has no current charmap, or if the character code */ + /* is not defined in the charmap, this function will return an */ + /* error. */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* FT_Set_Transform(). */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_SCALE */ + /* */ + /* */ + /* A bit field constant, used with FT_Load_Glyph() to indicate that */ + /* the vector outline being loaded should not be scaled to 26.6 */ + /* fractional pixels, but kept in notional units. */ + /* */ +#define FT_LOAD_NO_SCALE 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_HINTING */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the vector outline being loaded should not be fitted to the pixel */ + /* grid but simply scaled to 26.6 fractional pixels. */ + /* */ + /* This flag is ignored if FT_LOAD_NO_SCALE is set. */ + /* */ +#define FT_LOAD_NO_HINTING 2 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_RENDER */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should load the glyph and immediately convert it into */ + /* a bitmap, if necessary, by calling FT_Render_Glyph(). */ + /* */ + /* Note that by default, FT_Load_Glyph() loads the glyph image in its */ + /* native format. */ + /* */ +#define FT_LOAD_RENDER 4 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_BITMAP */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should not load the bitmap or pixmap of a given */ + /* glyph. This is useful when you do not want to load the embedded */ + /* bitmaps of scalable formats, as the native glyph image will be */ + /* loaded, and can then be rendered through FT_Render_Glyph(). */ + /* */ +#define FT_LOAD_NO_BITMAP 8 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_VERTICAL_LAYOUT */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph image should be prepared for vertical layout. This */ + /* basically means that `face.glyph.advance' will correspond to the */ + /* vertical advance height (instead of the default horizontal */ + /* advance width), and that the glyph image will translated to match */ + /* the vertical bearings positions. */ + /* */ +#define FT_LOAD_VERTICAL_LAYOUT 16 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_FORCE_AUTOHINT */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should try to auto-hint the glyphs, even if a driver */ + /* specific hinter is available. */ + /* */ +#define FT_LOAD_FORCE_AUTOHINT 32 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the font driver should try to crop the bitmap (i.e. remove all */ + /* space around its black bits) when loading it. For now, this */ + /* really only works with embedded bitmaps in TrueType fonts. */ + /* */ +#define FT_LOAD_CROP_BITMAP 64 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_PEDANTIC */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should perform a pedantic bytecode */ + /* interpretation. Many popular fonts come with broken glyph */ + /* programs. When this flag is set, loading them will return an */ + /* error. Otherwise, errors are ignored by the loader, sometimes */ + /* resulting in ugly glyphs. */ + /* */ +#define FT_LOAD_PEDANTIC 128 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should ignore the global advance width defined */ + /* in the font. As far as we know, this is only used by the */ + /* X-TrueType font server, in order to deal correctly with the */ + /* incorrect metrics contained in DynaLab's TrueType CJK fonts. */ + /* */ +#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 512 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_NO_RECURSE */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should not load composite glyph recursively. */ + /* Rather, when a composite glyph is encountered, it should set */ + /* the values of `num_subglyphs' and `subglyphs', as well as set */ + /* `face->glyph.format' to ft_glyph_format_composite. */ + /* */ + /* This is for use by the auto-hinter and possibly other tools. */ + /* For nearly all applications, this flags should be left unset */ + /* when invoking FT_Load_Glyph(). */ + /* */ + /* Note that the flag forces the load of unscaled glyphs. */ + /* */ +#define FT_LOAD_NO_RECURSE 1024 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_IGNORE_TRANSFORM */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the glyph loader should not try to transform the loaded glyph */ + /* image. */ + /* */ +#define FT_LOAD_IGNORE_TRANSFORM 2048 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_MONOCHROME */ + /* */ + /* */ + /* Only used with FT_LOAD_RENDER set, it indicates that the returned */ + /* glyph image should be 1-bit monochrome. This really tells the */ + /* glyph loader to use `ft_render_mode_mono' when calling */ + /* FT_Render_Glyph(). */ + /* */ +#define FT_LOAD_MONOCHROME 4096 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_LINEAR_DESIGN */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should return the linearly scaled metrics expressed */ + /* in original font units, instead of the default 16.16 pixel values. */ + /* */ +#define FT_LOAD_LINEAR_DESIGN 8192 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LOAD_DEFAULT */ + /* */ + /* */ + /* A bit-field constant, used with FT_Load_Glyph() to indicate that */ + /* the function should try to load the glyph normally, i.e., */ + /* embedded bitmaps are favored over outlines, vectors are always */ + /* scaled and grid-fitted. */ + /* */ +#define FT_LOAD_DEFAULT 0 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Transform */ + /* */ + /* */ + /* A function used to set the transformation that is applied to glyph */ + /* images just before they are converted to bitmaps in a glyph slot */ + /* when FT_Render_Glyph() is called. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */ + /* the identity matrix. */ + /* delta :: A pointer to the translation vector. Use 0 for the null */ + /* vector. */ + /* */ + /* */ + /* The transformation is only applied to scalable image formats after */ + /* the glyph has been loaded. It means that hinting is unaltered by */ + /* the transformation and is performed on the character size given in */ + /* the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_DEF( void ) FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Mode */ + /* */ + /* */ + /* An enumeration type that lists the render modes supported by the */ + /* FreeType 2 renderer(s). A renderer is in charge of converting a */ + /* glyph image into a bitmap. */ + /* */ + /* */ + /* ft_render_mode_normal :: This is the default render mode; it */ + /* corresponds to 8-bit anti-aliased */ + /* bitmaps, using 256 levels of gray. */ + /* */ + /* ft_render_mode_mono :: This render mode is used to produce 1-bit */ + /* monochrome bitmaps. */ + /* */ + /* */ + /* There is no render mode to produce 8-bit `monochrome' bitmaps -- */ + /* you have to make the conversion yourself if you need such things */ + /* (besides, FreeType is not a graphics library). */ + /* */ + /* More modes might appear later for specific display modes (e.g. TV, */ + /* LCDs, etc.). They will be supported through the simple addition */ + /* of a renderer module, with no changes to the rest of the engine. */ + /* */ + typedef enum FT_Render_Mode_ + { + ft_render_mode_normal = 0, + ft_render_mode_mono = 1 + + } FT_Render_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Glyph */ + /* */ + /* */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* render_mode :: This is the render mode used to render the glyph */ + /* image into a bitmap. See FT_Render_Mode for a list */ + /* of possible values. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot, + FT_UInt render_mode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Kerning_Mode */ + /* */ + /* */ + /* An enumeration used to specify which kerning values to return in */ + /* FT_Get_Kerning(). */ + /* */ + /* */ + /* ft_kerning_default :: Return scaled and grid-fitted kerning */ + /* distances (value is 0). */ + /* */ + /* ft_kerning_unfitted :: Return scaled but un-grid-fitted kerning */ + /* distances. */ + /* */ + /* ft_kerning_unscaled :: Return the kerning vector in original font */ + /* units. */ + /* */ + typedef enum FT_Kerning_Mode_ + { + ft_kerning_default = 0, + ft_kerning_unfitted, + ft_kerning_unscaled + + } FT_Kerning_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Kerning */ + /* */ + /* */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* kern_mode :: See FT_Kerning_Mode() for more information. */ + /* Determines the scale/dimension of the returned */ + /* kerning vector. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this method. Other layouts, or more sophisticated */ + /* kernings, are out of the scope of this API function -- they can be */ + /* implemented through format-specific interfaces. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector* kerning ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph_Name */ + /* */ + /* */ + /* Retrieves the ASCII name of a given glyph in a face. This only */ + /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* An error is returned if the face doesn't provide glyph names or if */ + /* the glyph index is invalid. In all cases of failure, the first */ + /* byte of `buffer' will be set to 0 to indicate an empty name. */ + /* */ + /* The glyph name is truncated to fit within the buffer if it is too */ + /* long. The returned string is always zero-terminated. */ + /* */ + /* This function is not compiled within the library if the config */ + /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */ + /* `include/freetype/config/ftoptions.h' */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Select_Charmap */ + /* */ + /* */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Charmap */ + /* */ + /* */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if the charmap is not part of */ + /* the face (i.e., if it is not listed in the face->charmaps[] */ + /* table). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT_DEF( FT_UInt ) FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* with maximal accuracy (it uses a 64-bit intermediate integer */ + /* whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */ + /* used to multiply a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* This function has been optimized for the case where the absolute */ + /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ + /* As this happens mainly when scaling from notional units to */ + /* fractional pixels in FreeType, it resulted in noticeable speed */ + /* improvements between versions 2.x and 1.x. */ + /* */ + /* As a conclusion, always try to place a 16.16 factor as the */ + /* _second_ argument of this function; this can make a great */ + /* difference. */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ + /* used to divide a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of the old FT_MulDiv64(). */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_DivFix( FT_Long a, + FT_Long b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_DEF( void ) FT_Vector_Transform( FT_Vector* vec, + FT_Matrix* matrix ); + + + +#ifdef __cplusplus + } +#endif + + +#endif /* FREETYPE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftbbox.h b/subsys/win32k/freetype/include/freetype/ftbbox.h new file mode 100644 index 0000000..e144664 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftbbox.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ftbbox.h */ +/* */ +/* FreeType bbox computation (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component has a _single_ role: to compute exact outline bounding */ + /* boxes. */ + /* */ + /* It is separated from the rest of the engine for various technical */ + /* reasons. It may well be integrated in `ftoutln' later. */ + /* */ + /*************************************************************************/ + + +#ifndef FTBBOX_H +#define FTBBOX_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_GetBBox */ + /* */ + /* */ + /* Computes the exact bounding box of an outline. This is slower */ + /* than computing the control box. However, it uses an advanced */ + /* algorithm which returns _very_ quickly when the two boxes */ + /* coincide. Otherwise, the outline Bezier arcs are walked over to */ + /* extract their extrema. */ + /* */ + /* */ + /* outline :: A pointer to the source outline. */ + /* */ + /* */ + /* bbox :: The outline's exact bounding box. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + FT_EXPORT_DEF(FT_Error) FT_Raster_GetBBox( FT_Outline* outline, + FT_BBox* abbox ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTBBOX_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/fterrors.h b/subsys/win32k/freetype/include/freetype/fterrors.h new file mode 100644 index 0000000..9fb8099 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/fterrors.h @@ -0,0 +1,166 @@ +/***************************************************************************/ +/* */ +/* fterrors.h */ +/* */ +/* FreeType error codes (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file is used to define the FreeType error enumeration constants */ + /* It can also be used to create an error message table easily with */ + /* something like: */ + /* */ + /* { */ + /* #undef FTERRORS_H */ + /* #define FT_ERRORDEF( e, v, s ) { e, s }, */ + /* #define FT_ERROR_START_LIST { */ + /* #define FT_ERROR_END_LIST { 0, 0 } }; */ + /* */ + /* const struct */ + /* { */ + /* int err_code; */ + /* const char* err_msg */ + /* } ft_errors[] = */ + /* */ + /* #include */ + /* } */ + /* */ + /*************************************************************************/ + + +#ifndef FTERRORS_H +#define FTERRORS_H + + +#ifndef FT_ERRORDEF + +#define FT_ERRORDEF( e, v, s ) e = v, +#define FT_ERROR_START_LIST enum { +#define FT_ERROR_END_LIST FT_Err_Max }; + +#endif /* !FT_ERRORDEF */ + + +#ifdef FT_ERROR_START_LIST + FT_ERROR_START_LIST +#endif + + FT_ERRORDEF( FT_Err_Ok, 0x0000, \ + "no error" ) + FT_ERRORDEF( FT_Err_Cannot_Open_Resource, 0x0001, \ + "can't open stream" ) + FT_ERRORDEF( FT_Err_Unknown_File_Format, 0x0002, \ + "unknown file format" ) + FT_ERRORDEF( FT_Err_Invalid_File_Format, 0x0003, \ + "broken file" ) + + FT_ERRORDEF( FT_Err_Invalid_Argument, 0x0010, \ + "invalid argument" ) + FT_ERRORDEF( FT_Err_Invalid_Handle, 0x0011, \ + "invalid object handle" ) + FT_ERRORDEF( FT_Err_Invalid_Glyph_Index, 0x0012, \ + "invalid glyph index" ) + FT_ERRORDEF( FT_Err_Invalid_Character_Code, 0x0013, \ + "invalid character code" ) + + FT_ERRORDEF( FT_Err_Unimplemented_Feature, 0x0020, \ + "unimplemented feature" ) + FT_ERRORDEF( FT_Err_Invalid_Glyph_Format, 0x0021, \ + "unsupported glyph image format" ) + FT_ERRORDEF( FT_Err_Cannot_Render_Glyph, 0x0022, \ + "cannot render this glyph format" ) + + FT_ERRORDEF( FT_Err_Invalid_Library_Handle, 0x0030, \ + "invalid library handle" ) + FT_ERRORDEF( FT_Err_Invalid_Driver_Handle, 0x0031, \ + "invalid module handle" ) + FT_ERRORDEF( FT_Err_Invalid_Face_Handle, 0x0032, \ + "invalid face handle" ) + FT_ERRORDEF( FT_Err_Invalid_Size_Handle, 0x0033, \ + "invalid size handle" ) + FT_ERRORDEF( FT_Err_Invalid_Slot_Handle, 0x0034, \ + "invalid glyph slot handle" ) + FT_ERRORDEF( FT_Err_Invalid_CharMap_Handle, 0x0035, \ + "invalid charmap handle" ) + FT_ERRORDEF( FT_Err_Invalid_Outline, 0x0036, \ + "invalid outline" ) + FT_ERRORDEF( FT_Err_Invalid_Version, 0x0037, \ + "invalid FreeType version" ) + FT_ERRORDEF( FT_Err_Lower_Module_Version, 0x0038, \ + "module version is too low" ) + + FT_ERRORDEF( FT_Err_Too_Many_Drivers, 0x0040, \ + "too many modules" ) + FT_ERRORDEF( FT_Err_Too_Many_Extensions, 0x0041, \ + "too many extensions" ) + + FT_ERRORDEF( FT_Err_Out_Of_Memory, 0x0050, \ + "out of memory" ) + FT_ERRORDEF( FT_Err_Unlisted_Object, 0x0051, \ + "unlisted object" ) + + FT_ERRORDEF( FT_Err_Invalid_Stream_Handle, 0x0060, \ + "invalid stream handle" ) + FT_ERRORDEF( FT_Err_Cannot_Open_Stream, 0x0061, \ + "cannot open stream" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Seek, 0x0062, \ + "invalid stream seek" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Skip, 0x0063, \ + "invalid stream skip" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Read, 0x0064, \ + "invalid stream read" ) + FT_ERRORDEF( FT_Err_Invalid_Stream_Operation, 0x0065, \ + "invalid stream operation" ) + FT_ERRORDEF( FT_Err_Invalid_Frame_Operation, 0x0066, \ + "invalid frame operation" ) + FT_ERRORDEF( FT_Err_Nested_Frame_Access, 0x0067, \ + "nested frame access" ) + FT_ERRORDEF( FT_Err_Invalid_Frame_Read, 0x0068, \ + "invalid frame read" ) + + FT_ERRORDEF( FT_Err_Invalid_Composite, 0x0070, \ + "invalid composite glyph" ) + FT_ERRORDEF( FT_Err_Too_Many_Hints, 0x0071, \ + "too many hints" ) + + FT_ERRORDEF( FT_Err_Raster_Uninitialized, 0x0080, \ + "raster uninitialized" ) + FT_ERRORDEF( FT_Err_Raster_Corrupted, 0x0081, \ + "raster corrupted" ) + FT_ERRORDEF( FT_Err_Raster_Overflow, 0x0082, \ + "raster overflow" ) + FT_ERRORDEF( FT_Err_Raster_Negative_Height, 0x0083, \ + "negative height while rastering" ) + + /* range 0x400 - 0x4FF is reserved for TrueType specific stuff */ + + /* range 0x500 - 0x5FF is reserved for CFF specific stuff */ + + /* range 0x600 - 0x6FF is reserved for Type1 specific stuff */ + +#ifdef FT_ERROR_END_LIST + FT_ERROR_END_LIST +#endif + + +#undef FT_ERROR_START_LIST +#undef FT_ERROR_END_LIST +#undef FT_ERRORDEF + + +#endif /* FTERRORS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftglyph.h b/subsys/win32k/freetype/include/freetype/ftglyph.h new file mode 100644 index 0000000..0647c88 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftglyph.h @@ -0,0 +1,422 @@ +/***************************************************************************/ +/* */ +/* ftglyph.h */ +/* */ +/* FreeType convenience functions to handle glyphs (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of several convenience functions */ + /* that can be used by client applications to easily retrieve glyph */ + /* bitmaps and outlines from a given face. */ + /* */ + /* These functions should be optional if you are writing a font server */ + /* or text layout engine on top of FreeType. However, they are pretty */ + /* handy for many other simple uses of the library. */ + /* */ + /*************************************************************************/ + + +#ifndef FTGLYPH_H +#define FTGLYPH_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /* forward declaration to a private type */ + typedef struct FT_Glyph_Class_ FT_Glyph_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_GlyphRec */ + /* */ + /* */ + /* The root glyph structure contains a given glyph image plus its */ + /* advance width in 16.16 fixed float format. */ + /* */ + /* */ + /* library :: A handle to the FreeType library object. */ + /* */ + /* clazz :: A pointer to the glyph's class. Private. */ + /* */ + /* format :: The format of the glyph's image. */ + /* */ + /* advance :: A 16.16 vector that gives the glyph's advance width. */ + /* */ + typedef struct FT_GlyphRec_ + { + FT_Library library; + const FT_Glyph_Class* clazz; + FT_Glyph_Format format; + FT_Vector advance; + + } FT_GlyphRec, *FT_Glyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_BitmapGlyphRec */ + /* */ + /* */ + /* A structure used for bitmap glyph images. This really is a */ + /* `sub-class' of `FT_GlyphRec'. */ + /* */ + /* */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* left :: The left-side bearing, i.e., the horizontal distance */ + /* from the current pen position to the left border of the */ + /* glyph bitmap. */ + /* */ + /* top :: The top-side bearing, i.e., the vertical distance from */ + /* the current pen position to the top border of the glyph */ + /* bitmap. This distance is positive for upwards-y! */ + /* */ + /* bitmap :: A descriptor for the bitmap. */ + /* */ + /* */ + /* You can typecast FT_Glyph to FT_BitmapGlyph if you have */ + /* glyph->format == ft_glyph_format_bitmap. This lets you access */ + /* the bitmap's contents easily. */ + /* */ + /* The corresponding pixel buffer is always owned by the BitmapGlyph */ + /* and is thus created and destroyed with it. */ + /* */ + typedef struct FT_BitmapGlyphRec_ + { + FT_GlyphRec root; + FT_Int left; + FT_Int top; + FT_Bitmap bitmap; + + } FT_BitmapGlyphRec, *FT_BitmapGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_OutlineGlyphRec */ + /* */ + /* */ + /* A structure used for outline (vectorial) glyph images. This */ + /* really is a `sub-class' of `FT_GlyphRec'. */ + /* */ + /* */ + /* root :: The root FT_Glyph fields. */ + /* */ + /* outline :: A descriptor for the outline. */ + /* */ + /* */ + /* You can typecast FT_Glyph to FT_OutlineGlyph if you have */ + /* glyph->format == ft_glyph_format_outline. This lets you access */ + /* the outline's content easily. */ + /* */ + /* As the outline is extracted from a glyph slot, its coordinates are */ + /* expressed normally in 26.6 pixels, unless the flag */ + /* FT_LOAD_NO_SCALE was used in FT_Load_Glyph() or FT_Load_Char(). */ + /* */ + /* The outline's tables are always owned by the object and are */ + /* destroyed with it. */ + /* */ + typedef struct FT_OutlineGlyphRec_ + { + FT_GlyphRec root; + FT_Outline outline; + + } FT_OutlineGlyphRec, *FT_OutlineGlyph; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph */ + /* */ + /* */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph* aglyph ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Copy */ + /* */ + /* */ + /* A function used to copy a glyph image. */ + /* */ + /* */ + /* source :: A handle to the source glyph object. */ + /* */ + /* */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_Copy( FT_Glyph source, + FT_Glyph* target ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Transform */ + /* */ + /* */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* matrix :: A pointer to a 2x2 matrix to apply. */ + /* */ + /* delta :: A pointer to a 2d vector to apply. Coordinates are */ + /* expressed in 1/64th of a pixel. */ + /* */ + /* */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + + enum + { + ft_glyph_bbox_pixels = 0, + ft_glyph_bbox_subpixels = 1, + ft_glyph_bbox_gridfit = 2 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Get_CBox */ + /* */ + /* */ + /* Returns the glyph image's bounding box. */ + /* */ + /* */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: A set of bit flags that indicate how to interpret the */ + /* returned bounding box values. */ + /* */ + /* */ + /* box :: The glyph bounding box. Coordinates are expressed in */ + /* 1/64th of pixels if it is grid-fitted. */ + /* */ + /* */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ + /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ + /* Otherwise, coordinates are expressed in integer pixels. */ + /* */ + /* Note that the maximum coordinates are exclusive, which means that */ + /* one can compute the width and height of the glyph image (be it in */ + /* integer or 26.6 pixels) as: */ + /* */ + /* width = bbox.xMax - bbox.xMin; */ + /* height = bbox.yMax - bbox.yMin; */ + /* */ + /* Note also that for 26.6 coordinates, if the */ + /* `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates */ + /* will also be grid-fitted, which corresponds to: */ + /* */ + /* bbox.xMin = FLOOR(bbox.xMin); */ + /* bbox.yMin = FLOOR(bbox.yMin); */ + /* bbox.xMax = CEILING(bbox.xMax); */ + /* bbox.yMax = CEILING(bbox.yMax); */ + /* */ + /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ + /* */ + FT_EXPORT_DEF( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* */ + /* glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* */ + /* render_mode :: A set of bit flags that describe how the data is */ + /* */ + /* */ + /* origin :: A pointer to a vector used to translate the glyph */ + /* image before rendering. Can be 0 (if no */ + /* translation). The origin is expressed in */ + /* 26.6 pixels. */ + /* */ + /* destroy :: A boolean that indicates that the original glyph */ + /* image should be destroyed by this function. It is */ + /* never destroyed in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The glyph image is translated with the `origin' vector before */ + /* rendering. In case of error, it it translated back to its */ + /* original position and the glyph is left untouched. */ + /* */ + /* The first parameter is a pointer to a FT_Glyph handle, that will */ + /* be replaced by this function. Typically, you would use (omitting */ + /* error handling): */ + /* */ + /* */ + /* { */ + /* FT_Glyph glyph; */ + /* FT_BitmapGlyph glyph_bitmap; */ + /* */ + /* */ + /* // load glyph */ + /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ + /* */ + /* // extract glyph image */ + /* error = FT_Get_Glyph( face->glyph, &glyph ); */ + /* */ + /* // convert to a bitmap (default render mode + destroy old) */ + /* if ( glyph->format != ft_glyph_format_bitmap ) */ + /* { */ + /* error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default, */ + /* 0, 1 ); */ + /* if ( error ) // glyph unchanged */ + /* ... */ + /* } */ + /* */ + /* // access bitmap content by typecasting */ + /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ + /* */ + /* // do funny stuff with it, like blitting/drawing */ + /* ... */ + /* */ + /* // discard glyph image (bitmap or not) */ + /* FT_Done_Glyph( glyph ); */ + /* } */ + /* */ + /* */ + /* This function will always fail if the glyph's format isn't */ + /* scalable. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_ULong render_mode, + FT_Vector* origin, + FT_Bool destroy ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Glyph */ + /* */ + /* */ + /* Destroys a given glyph. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT_DEF( void ) FT_Done_Glyph( FT_Glyph glyph ); + + + /* other helpful functions */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT_DEF( void ) FT_Matrix_Multiply( FT_Matrix* a, + FT_Matrix* b ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTGLYPH_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftimage.h b/subsys/win32k/freetype/include/freetype/ftimage.h new file mode 100644 index 0000000..4dd1c3d --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftimage.h @@ -0,0 +1,1003 @@ +/***************************************************************************/ +/* */ +/* ftimage.h */ +/* */ +/* FreeType glyph image formats and default raster interface */ +/* (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Note: A `raster' is simply a scan-line converter, used to render */ + /* FT_Outlines into FT_Bitmaps. */ + /* */ + /*************************************************************************/ + + +#ifndef FTIMAGE_H +#define FTIMAGE_H + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pos */ + /* */ + /* */ + /* The type FT_Pos is a 32-bit integer used to store vectorial */ + /* coordinates. Depending on the context, these can represent */ + /* distances in integer font units, or 26.6 fixed float pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_Pos; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector */ + /* */ + /* */ + /* A simple structure used to store a 2D vector; coordinates are of */ + /* the FT_Pos type. */ + /* */ + /* */ + /* x :: The horizontal coordinate. */ + /* y :: The vertical coordinate. */ + /* */ + typedef struct FT_Vector_ + { + FT_Pos x; + FT_Pos y; + + } FT_Vector; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pixel_Mode */ + /* */ + /* */ + /* An enumeration type used to describe the format of pixels in a */ + /* given bitmap. Note that additional formats may be added in the */ + /* future. */ + /* */ + /* */ + /* ft_pixel_mode_mono :: A monochrome bitmap (1 bit/pixel). */ + /* */ + /* ft_pixel_mode_grays :: An 8-bit gray-levels bitmap. Note that the */ + /* total number of gray levels is given in the */ + /* `num_grays' field of the FT_Bitmap */ + /* structure. */ + /* */ + /* ft_pixel_mode_pal2 :: A 2-bit paletted bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_pal4 :: A 4-bit paletted bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_pal8 :: An 8-bit paletted bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb15 :: A 15-bit RGB bitmap. Uses 5:5:5 encoding. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb16 :: A 16-bit RGB bitmap. Uses 5:6:5 encoding. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb24 :: A 24-bit RGB bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* ft_pixel_mode_rgb32 :: A 32-bit RGB bitmap. */ + /* Currently unused by FreeType. */ + /* */ + /* */ + /* Some anti-aliased bitmaps might be embedded in TrueType fonts */ + /* using formats pal2 or pal4, though no fonts presenting those have */ + /* been found to date. */ + /* */ + typedef enum FT_Pixel_Mode_ + { + ft_pixel_mode_none = 0, + ft_pixel_mode_mono, + ft_pixel_mode_grays, + ft_pixel_mode_pal2, + ft_pixel_mode_pal4, + ft_pixel_mode_pal8, + ft_pixel_mode_rgb15, + ft_pixel_mode_rgb16, + ft_pixel_mode_rgb24, + ft_pixel_mode_rgb32, + + ft_pixel_mode_max /* do not remove */ + + } FT_Pixel_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Palette_Mode */ + /* */ + /* */ + /* An enumeration type used to describe the format of a bitmap */ + /* palette, used with ft_pixel_mode_pal4 and ft_pixel_mode_pal8. */ + /* */ + /* */ + /* ft_palette_mode_rgb :: The palette is an array of 3-bytes RGB */ + /* records. */ + /* */ + /* ft_palette_mode_rgba :: The palette is an array of 4-bytes RGBA */ + /* records. */ + /* */ + /* */ + /* As ft_pixel_mode_pal2, pal4 and pal8 are currently unused by */ + /* FreeType, these types are not handled by the library itself. */ + /* */ + typedef enum FT_Palette_Mode_ + { + ft_palette_mode_rgb = 0, + ft_palette_mode_rgba, + + ft_palettte_mode_max /* do not remove */ + + } FT_Palette_Mode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bitmap */ + /* */ + /* */ + /* A structure used to describe a bitmap or pixmap to the raster. */ + /* Note that we now manage pixmaps of various depths through the */ + /* `pixel_mode' field. */ + /* */ + /* */ + /* rows :: The number of bitmap rows. */ + /* */ + /* width :: The number of pixels in bitmap row. */ + /* */ + /* pitch :: The pitch's absolute value is the number of bytes */ + /* taken by one bitmap row, including padding. */ + /* However, the pitch is positive when the bitmap has */ + /* a `down' flow, and negative when it has an `up' */ + /* flow. In all cases, the pitch is an offset to add */ + /* to a bitmap pointer in order to go down one row. */ + /* */ + /* buffer :: A typeless pointer to the bitmap buffer. This */ + /* value should be aligned on 32-bit boundaries in */ + /* most cases. */ + /* */ + /* num_grays :: This field is only used with */ + /* `ft_pixel_mode_grays'; it gives the number of gray */ + /* levels used in the bitmap. */ + /* */ + /* pixel_mode :: The pixel_mode, i.e., how pixel bits are stored. */ + /* */ + /* palette_mode :: This field is only used with paletted pixel modes; */ + /* it indicates how the palette is stored. */ + /* */ + /* palette :: A typeless pointer to the bitmap palette; only */ + /* used for paletted pixel modes. */ + /* */ + /* */ + /* For now, the only pixel mode supported by FreeType are mono and */ + /* grays. However, drivers might be added in the future to support */ + /* more `colorful' options. */ + /* */ + /* When using pixel modes pal2, pal4 and pal8 with a void `palette' */ + /* field, a gray pixmap with respectively 4, 16, and 256 levels of */ + /* gray is assumed. This, in order to be compatible with some */ + /* embedded bitmap formats defined in the TrueType specification. */ + /* */ + /* Note that no font was found presenting such embedded bitmaps, so */ + /* this is currently completely unhandled by the library. */ + /* */ + typedef struct FT_Bitmap_ + { + int rows; + int width; + int pitch; + unsigned char* buffer; + short num_grays; + char pixel_mode; + char palette_mode; + void* palette; + + } FT_Bitmap; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline */ + /* */ + /* */ + /* This structure is used to describe an outline to the scan-line */ + /* converter. */ + /* */ + /* */ + /* n_contours :: The number of contours in the outline. */ + /* */ + /* n_points :: The number of points in the outline. */ + /* */ + /* points :: A pointer to an array of `n_points' FT_Vector */ + /* elements, giving the outline's point coordinates. */ + /* */ + /* tags :: A pointer to an array of `n_points' chars, giving */ + /* giving each outline point's type. If bit 0 is */ + /* unset, the point is 'off' the curve, i.e. a Bezier */ + /* control point, while it is `on' when unset. */ + /* */ + /* Bit 1 is meaningful for `off' points only. If set, */ + /* it indicates a third-order Bezier arc control point; */ + /* and a second-order control point if unset. */ + /* */ + /* contours :: An array of `n_contours' shorts, giving the end */ + /* point of each contour within the outline. For */ + /* example, the first contour is defined by the points */ + /* `0' to `contours[0]', the second one is defined by */ + /* the points `contours[0]+1' to `contours[1]', etc. */ + /* */ + /* flags :: A set of bit flags used to characterize the outline */ + /* and give hints to the scan-converter and hinter on */ + /* how to convert/grid-fit it. See FT_Outline_Flags. */ + /* */ + typedef struct FT_Outline_ + { + short n_contours; /* number of contours in glyph */ + short n_points; /* number of points in the glyph */ + + FT_Vector* points; /* the outline's points */ + char* tags; /* the points flags */ + short* contours; /* the contour end points */ + + int flags; /* outline masks */ + + } FT_Outline; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Flags */ + /* */ + /* */ + /* A simple type used to enumerates the flags in an outline's */ + /* `outline_flags' field. */ + /* */ + /* */ + /* ft_outline_owner :: If set, this flag indicates that the */ + /* outline's field arrays (i.e. */ + /* `points', `flags' & `contours') are */ + /* `owned' by the outline object, and */ + /* should thus be freed when it is */ + /* destroyed. */ + /* */ + /* ft_outline_even_odd_fill :: By default, outlines are filled using */ + /* the non-zero winding rule. If set to */ + /* 1, the outline will be filled using */ + /* the even-odd fill rule (only works */ + /* with the smooth raster). */ + /* */ + /* ft_outline_reverse_fill :: By default, outside contours of an */ + /* outline are oriented in clock-wise */ + /* direction, as defined in the TrueType */ + /* specification. This flag is set if */ + /* the outline uses the opposite */ + /* direction (typically for Type 1 */ + /* fonts). This flag is ignored by the */ + /* scan-converter. However, it is very */ + /* important for the auto-hinter. */ + /* */ + /* ft_outline_ignore_dropouts :: By default, the scan converter will */ + /* try to detect drop-outs in an outline */ + /* and correct the glyph bitmap to */ + /* ensure consistent shape continuity. */ + /* If set, this flag hints the scan-line */ + /* converter to ignore such cases. */ + /* */ + /* ft_outline_high_precision :: This flag indicates that the */ + /* scan-line converter should try to */ + /* convert this outline to bitmaps with */ + /* the highest possible quality. It is */ + /* typically set for small character */ + /* sizes. Note that this is only a */ + /* hint, that might be completely */ + /* ignored by a given scan-converter. */ + /* */ + /* ft_outline_single_pass :: This flag is set to force a given */ + /* scan-converter to only use a single */ + /* pass over the outline to render a */ + /* bitmap glyph image. Normally, it is */ + /* set for very large character sizes. */ + /* It is only a hint, that might be */ + /* completely ignored by a given */ + /* scan-converter. */ + /* */ + typedef enum FT_Outline_Flags_ + { + ft_outline_none = 0, + ft_outline_owner = 1, + ft_outline_even_odd_fill = 2, + ft_outline_reverse_fill = 4, + ft_outline_ignore_dropouts = 8, + ft_outline_high_precision = 256, + ft_outline_single_pass = 512 + + } FT_Outline_Flags; + + +#define FT_CURVE_TAG( flag ) ( flag & 3 ) + +#define FT_Curve_Tag_On 1 +#define FT_Curve_Tag_Conic 0 +#define FT_Curve_Tag_Cubic 2 + +#define FT_Curve_Tag_Touch_X 8 /* reserved for the TrueType hinter */ +#define FT_Curve_Tag_Touch_Y 16 /* reserved for the TrueType hinter */ + +#define FT_Curve_Tag_Touch_Both ( FT_Curve_Tag_Touch_X | \ + FT_Curve_Tag_Touch_Y ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_MoveTo_Func */ + /* */ + /* */ + /* A function pointer type used to describe the signature of a `move */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `move to' is emitted to start a new contour in an outline. */ + /* */ + /* */ + /* to :: A pointer to the target point of the `move to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_MoveTo_Func)( FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_LineTo_Func */ + /* */ + /* */ + /* A function pointer type used to describe the signature of a `line */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `line to' is emitted to indicate a segment in the outline. */ + /* */ + /* */ + /* to :: A pointer to the target point of the `line to'. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of the */ + /* decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_LineTo_Func)( FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_ConicTo_Func */ + /* */ + /* */ + /* A function pointer type use to describe the signature of a `conic */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `conic to' is emitted to indicate a second-order Bezier arc in */ + /* the outline. */ + /* */ + /* */ + /* control :: An intermediate control point between the last position */ + /* and the new target in `to'. */ + /* */ + /* to :: A pointer to the target end point of the conic arc. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_ConicTo_Func)( FT_Vector* control, + FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_CubicTo_Func */ + /* */ + /* */ + /* A function pointer type used to describe the signature of a `cubic */ + /* to' function during outline walking/decomposition. */ + /* */ + /* A `cubic to' is emitted to indicate a third-order Bezier arc. */ + /* */ + /* */ + /* control1 :: A pointer to the first Bezier control point. */ + /* */ + /* control2 :: A pointer to the second Bezier control point. */ + /* */ + /* to :: A pointer to the target end point. */ + /* */ + /* user :: A typeless pointer which is passed from the caller of */ + /* the decomposition function. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + typedef int (*FT_Outline_CubicTo_Func)( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Funcs */ + /* */ + /* */ + /* A structure to hold various function pointers used during outline */ + /* decomposition in order to emit segments, conic, and cubic Beziers, */ + /* as well as `move to' and `close to' operations. */ + /* */ + /* */ + /* move_to :: The `move to' emitter. */ + /* */ + /* line_to :: The segment emitter. */ + /* */ + /* conic_to :: The second-order Bezier arc emitter. */ + /* */ + /* cubic_to :: The third-order Bezier arc emitter. */ + /* */ + /* shift :: The shift that is applied to coordinates before they */ + /* are sent to the emitter. */ + /* */ + /* delta :: The delta that is applied to coordinates before they */ + /* are sent to the emitter, but after the shift. */ + /* */ + /* */ + /* The point coordinates sent to the emitters are the transformed */ + /* version of the original coordinates (this is important for high */ + /* accuracy during scan-conversion). The transformation is simple: */ + /* */ + /* x' = (x << shift) - delta */ + /* y' = (x << shift) - delta */ + /* */ + /* Set the value of `shift' and `delta' to 0 to get the original */ + /* point coordinates. */ + /* */ + typedef struct FT_Outline_Funcs_ + { + FT_Outline_MoveTo_Func move_to; + FT_Outline_LineTo_Func line_to; + FT_Outline_ConicTo_Func conic_to; + FT_Outline_CubicTo_Func cubic_to; + + int shift; + FT_Pos delta; + + } FT_Outline_Funcs; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_IMAGE_TAG */ + /* */ + /* */ + /* This macro converts four letter tags into an unsigned long. */ + /* */ +#define FT_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (unsigned long)_x1 << 24 ) | \ + ( (unsigned long)_x2 << 16 ) | \ + ( (unsigned long)_x3 << 8 ) | \ + (unsigned long)_x4 ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Format */ + /* */ + /* */ + /* An enumeration type used to describe the format of a given glyph */ + /* image. Note that this version of FreeType only supports two image */ + /* formats, even though future font drivers will be able to register */ + /* their own format. */ + /* */ + /* */ + /* ft_glyph_format_composite :: The glyph image is a composite of */ + /* several other images. This glyph */ + /* format is _only_ used with the */ + /* FT_LOAD_FLAG_NO_RECURSE flag (XXX: */ + /* Which is currently unimplemented). */ + /* */ + /* ft_glyph_format_bitmap :: The glyph image is a bitmap, and can */ + /* be described as a FT_Bitmap. */ + /* */ + /* ft_glyph_format_outline :: The glyph image is a vectorial image */ + /* made of bezier control points, and */ + /* can be described as a FT_Outline. */ + /* */ + /* ft_glyph_format_plotter :: The glyph image is a vectorial image */ + /* made of plotter lines (some T1 fonts */ + /* like Hershey contain glyph in this */ + /* format). */ + /* */ + typedef enum FT_Glyph_Format_ + { + ft_glyph_format_none = 0, + ft_glyph_format_composite = FT_IMAGE_TAG( 'c', 'o', 'm', 'p' ), + ft_glyph_format_bitmap = FT_IMAGE_TAG( 'b', 'i', 't', 's' ), + ft_glyph_format_outline = FT_IMAGE_TAG( 'o', 'u', 't', 'l' ), + ft_glyph_format_plotter = FT_IMAGE_TAG( 'p', 'l', 'o', 't' ) + + } FT_Glyph_Format; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** R A S T E R D E F I N I T I O N S *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* A raster is a scan converter, in charge of rendering an outline into */ + /* a a bitmap. This section contains the public API for rasters. */ + /* */ + /* Note that in FreeType 2, all rasters are now encapsulated within */ + /* specific modules called `renderers'. See `freetype/ftrender.h' for */ + /* more details on renderers. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster */ + /* */ + /* */ + /* A handle (pointer) to a raster object. Each object can be used */ + /* independently to convert an outline into a bitmap or pixmap. */ + /* */ + typedef struct FT_RasterRec_* FT_Raster; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Span */ + /* */ + /* */ + /* A structure used to model a single span of gray (or black) pixels */ + /* when rendering a monochrome or anti-aliased bitmap. */ + /* */ + /* */ + /* x :: The span's horizontal start position. */ + /* */ + /* len :: The span's length in pixels. */ + /* */ + /* coverage :: The span color/coverage, ranging from 0 (background) */ + /* to 255 (foreground). Only used for anti-aliased */ + /* rendering. */ + /* */ + /* */ + /* This structure is used by the span drawing callback type named */ + /* FT_Raster_Span_Func(), which takes the y-coordinate of the span as */ + /* a parameter. */ + /* */ + /* The coverage value is always between 0 and 255, even if the number */ + /* of gray levels have been set through FT_Set_Gray_Levels(). */ + /* */ + typedef struct FT_Span_ + { + short x; + unsigned short len; + unsigned char coverage; + + } FT_Span; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Span_Func */ + /* */ + /* */ + /* A function used as a call-back by the anti-aliased renderer in */ + /* order to let client applications draw themselves the gray pixel */ + /* spans on each scan line. */ + /* */ + /* */ + /* y :: The scanline's y-coordinate. */ + /* */ + /* count :: The number of spans to draw on this scanline. */ + /* */ + /* spans :: A table of `count' spans to draw on the scanline. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* This callback allows client applications to directly render the */ + /* gray spans of the anti-aliased bitmap to any kind of surfaces. */ + /* */ + /* This can be used to write anti-aliased outlines directly to a */ + /* given background bitmap, and even perform translucency. */ + /* */ + /* Note that the `count' field cannot be greater than a fixed value */ + /* defined by the FT_MAX_GRAY_SPANS configuration macro in */ + /* ftoption.h. By default, this value is set to 32, which means that */ + /* if there are more than 32 spans on a given scanline, the callback */ + /* will be called several times with the same `y' parameter in order */ + /* to draw all callbacks. */ + /* */ + /* Otherwise, the callback is only called once per scan-line, and */ + /* only for those scanlines that do have `gray' pixels on them. */ + /* */ + typedef void (*FT_Raster_Span_Func)( int y, + int count, + FT_Span* spans, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitTest_Func */ + /* */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to test whether a given target pixel is already set to the drawing */ + /* `color'. These tests are crucial to implement drop-out control */ + /* per-se the TrueType spec. */ + /* */ + /* */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef int (*FT_Raster_BitTest_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_BitSet_Func */ + /* */ + /* */ + /* A function used as a call-back by the monochrome scan-converter */ + /* to set an individual target pixel. This is crucial to implement */ + /* drop-out control according to the TrueType specification. */ + /* */ + /* */ + /* y :: The pixel's y-coordinate. */ + /* */ + /* x :: The pixel's x-coordinate. */ + /* */ + /* user :: User-supplied data that is passed to the callback. */ + /* */ + /* */ + /* 1 if the pixel is `set', 0 otherwise. */ + /* */ + typedef void (*FT_Raster_BitSet_Func)( int y, + int x, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Flag */ + /* */ + /* */ + /* An enumeration to list the bit flags as used in the `flags' field */ + /* of a FT_Raster_Params structure. */ + /* */ + /* */ + /* ft_raster_flag_default :: This value is 0. */ + /* */ + /* ft_raster_flag_aa :: Requests the rendering of an */ + /* anti-aliased glyph bitmap. If unset, a */ + /* monchrome bitmap will be rendered. */ + /* */ + /* ft_raster_flag_direct :: Requests direct rendering over the */ + /* target bitmap. Direct rendering uses */ + /* user-provided callbacks in order to */ + /* perform direct drawing or composition */ + /* over an existing bitmap. If this bit is */ + /* unset, the content of the target bitmap */ + /* *must be zeroed*! */ + /* */ + typedef enum + { + ft_raster_flag_default = 0, + ft_raster_flag_aa = 1, + ft_raster_flag_direct = 2 + + } FT_Raster_Flag; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Params */ + /* */ + /* */ + /* A structure to hold the arguments used by a raster's render */ + /* function. */ + /* */ + /* */ + /* target :: The target bitmap. */ + /* */ + /* source :: A pointer to the source glyph image (e.g. an */ + /* FT_Outline). */ + /* */ + /* flags :: The rendering flags. */ + /* */ + /* gray_spans :: The gray span drawing callback. */ + /* */ + /* black_spans :: The black span drawing callback. */ + /* */ + /* bit_test :: The bit test callback. */ + /* */ + /* bit_set :: The bit set callback. */ + /* */ + /* user :: User-supplied data that is passed to each drawing */ + /* callback. */ + /* */ + /* */ + /* An anti-aliased glyph bitmap is drawn if the ft_raster_flag_aa bit */ + /* flag is set in the `flags' field, otherwise a monochrome bitmap */ + /* will be generated. */ + /* */ + /* If the ft_raster_flag_direct bit flag is set in `flags', the */ + /* raster will call the `gray_spans' callback to draw gray pixel */ + /* spans, in the case of an aa glyph bitmap, it will call */ + /* `black_spans', and `bit_test' and `bit_set' in the case of a */ + /* monochrome bitmap. This allows direct composition over a */ + /* pre-existing bitmap through user-provided callbacks to perform the */ + /* span drawing/composition. */ + /* */ + /* Note that the `bit_test' and `bit_set' callbacks are required when */ + /* rendering a monochrome bitmap, as they are crucial to implement */ + /* correct drop-out control as defined in the TrueType specification. */ + /* */ + typedef struct FT_Raster_Params_ + { + FT_Bitmap* target; + void* source; + int flags; + FT_Raster_Span_Func gray_spans; + FT_Raster_Span_Func black_spans; + FT_Raster_BitTest_Func bit_test; + FT_Raster_BitSet_Func bit_set; + void* user; + + } FT_Raster_Params; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_New_Func */ + /* */ + /* */ + /* A function used to create a new raster object. */ + /* */ + /* */ + /* memory :: A handle to the memory allocator. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* The `memory' parameter is a typeless pointer in order to avoid */ + /* un-wanted dependencies on the rest of the FreeType code. In */ + /* practice, it is a FT_Memory, i.e., a handle to the standard */ + /* FreeType memory allocator. However, this field can be completely */ + /* ignored by a given raster implementation. */ + /* */ + typedef int (*FT_Raster_New_Func)( void* memory, + FT_Raster* raster ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Done_Func */ + /* */ + /* */ + /* A function used to destroy a given raster object. */ + /* */ + /* */ + /* raster :: A handle to the raster object. */ + /* */ + typedef void (*FT_Raster_Done_Func)( FT_Raster raster ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Reset_Func */ + /* */ + /* */ + /* FreeType provides an area of memory called the `render pool', */ + /* available to all registered rasters. This pool can be freely used */ + /* during a given scan-conversion but is shared by all rasters. Its */ + /* content is thus transient. */ + /* */ + /* This function is called each time the render pool changes, or just */ + /* after a new raster object is created. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* pool_base :: The address in memory of the render pool. */ + /* */ + /* pool_size :: The size in bytes of the render pool. */ + /* */ + /* */ + /* Rasters can ignore the render pool and rely on dynamic memory */ + /* allocation if they want to (a handle to the memory allocator is */ + /* passed to the raster constructor). However, this is not */ + /* recommended for efficiency purposes. */ + /* */ + typedef void (*FT_Raster_Reset_Func)( FT_Raster raster, + unsigned char* pool_base, + unsigned long pool_size ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Set_Mode_Func */ + /* */ + /* */ + /* This function is a generic facility to change modes or attributes */ + /* in a given raster. This can be used for debugging purposes, or */ + /* simply to allow implementation-specific `features' in a given */ + /* raster module. */ + /* */ + /* */ + /* raster :: A handle to the new raster object. */ + /* */ + /* mode :: A 4-byte tag used to name the mode or property. */ + /* */ + /* args :: A pointer to the new mode/property to use. */ + /* */ + typedef int (*FT_Raster_Set_Mode_Func)( FT_Raster raster, + unsigned long mode, + void* args ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Render_Func */ + /* */ + /* */ + /* Invokes a given raster to scan-convert a given glyph image into a */ + /* target bitmap. */ + /* */ + /* */ + /* raster :: A handle to the raster object. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to store */ + /* the rendering parameters. */ + /* */ + /* */ + /* Error code. 0 means success. */ + /* */ + /* */ + /* The exact format of the source image depends on the raster's glyph */ + /* format defined in its FT_Raster_Funcs structure. It can be an */ + /* FT_Outline or anything else in order to support a large array of */ + /* glyph formats. */ + /* */ + /* Note also that the render function can fail and return a */ + /* FT_Err_Unimplemented_Feature error code if the raster used does */ + /* not support direct composition. */ + /* */ + /* XXX: For now, the standard raster doesn't support direct */ + /* composition but this should change for the final release (see */ + /* the files demos/src/ftgrays.c and demos/src/ftgrays2.c for */ + /* examples of distinct implementations which support direct */ + /* composition). */ + /* */ + typedef int (*FT_Raster_Render_Func)( FT_Raster raster, + FT_Raster_Params* params ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Raster_Funcs */ + /* */ + /* */ + /* A structure used to describe a given raster class to the library. */ + /* */ + /* */ + /* glyph_format :: The supported glyph format for this raster. */ + /* */ + /* raster_new :: The raster constructor. */ + /* */ + /* raster_reset :: Used to reset the render pool within the raster. */ + /* */ + /* raster_render :: A function to render a glyph into a given bitmap. */ + /* */ + /* raster_done :: The raster destructor. */ + /* */ + typedef struct FT_Raster_Funcs_ + { + FT_Glyph_Format glyph_format; + FT_Raster_New_Func raster_new; + FT_Raster_Reset_Func raster_reset; + FT_Raster_Set_Mode_Func raster_set_mode; + FT_Raster_Render_Func raster_render; + FT_Raster_Done_Func raster_done; + + } FT_Raster_Funcs; + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTIMAGE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftmm.h b/subsys/win32k/freetype/include/freetype/ftmm.h new file mode 100644 index 0000000..db5db04 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftmm.h @@ -0,0 +1,175 @@ +/***************************************************************************/ +/* */ +/* ftmm.h */ +/* */ +/* FreeType Multiple Master font interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTMM_H +#define FTMM_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MM_Axis */ + /* */ + /* */ + /* A simple structure used to model a given axis in design space for */ + /* Multiple Masters fonts. */ + /* */ + /* */ + /* name :: The axis's name. */ + /* */ + /* minimum :: The axis's minimum design coordinate. */ + /* */ + /* maximum :: The axis's maximum design coordinate. */ + /* */ + typedef struct FT_MM_Axis_ + { + FT_String* name; + FT_Long minimum; + FT_Long maximum; + + } FT_MM_Axis; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Multi_Master */ + /* */ + /* */ + /* A structure used to model the axes and space of a Multiple Masters */ + /* font. */ + /* */ + /* */ + /* num_axis :: Number of axes. Cannot exceed 4. */ + /* */ + /* num_designs :: Number of designs; should ne normally 2^num_axis */ + /* even though the Type 1 specification strangely */ + /* allows for intermediate designs to be present. This */ + /* number cannot exceed 16. */ + /* */ + /* axis :: A table of axis descriptors. */ + /* */ + typedef struct FT_Multi_Master_ + { + FT_UInt num_axis; + FT_UInt num_designs; + FT_MM_Axis axis[T1_MAX_MM_AXIS]; + + } FT_Multi_Master; + + + typedef FT_Error (*FT_Get_MM_Func)( FT_Face face, + FT_Multi_Master* master ); + + typedef FT_Error (*FT_Set_MM_Design_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + typedef FT_Error (*FT_Set_MM_Blend_Func)( FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Multi_Master */ + /* */ + /* */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* */ + /* master :: The Multiple Masters descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Design_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through normalized blend coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates (each one must be between 0 */ + /* and 1.0). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_MM_Blend_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTMM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftmodule.h b/subsys/win32k/freetype/include/freetype/ftmodule.h new file mode 100644 index 0000000..3c09aa2 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftmodule.h @@ -0,0 +1,274 @@ +/***************************************************************************/ +/* */ +/* ftmodule.h */ +/* */ +/* FreeType modules public interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTMODULE_H +#define FTMODULE_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* module bit flags */ + typedef enum FT_Module_Flags_ + { + ft_module_font_driver = 1, /* this module is a font driver */ + ft_module_renderer = 2, /* this module is a renderer */ + ft_module_hinter = 4, /* this module is a glyph hinter */ + ft_module_styler = 8, /* this module is a styler */ + + ft_module_driver_scalable = 0x100, /* the driver supports scalable */ + /* fonts */ + ft_module_driver_no_outlines = 0x200, /* the driver does not support */ + /* vector outlines */ + ft_module_driver_has_hinter = 0x400 /* the driver provides its own */ + /* hinter */ + + } FT_Module_Flags; + + + typedef void (*FT_Module_Interface)( void ); + + typedef FT_Error (*FT_Module_Constructor)( FT_Module module ); + + typedef void (*FT_Module_Destructor)( FT_Module module ); + + typedef FT_Module_Interface (*FT_Module_Requester)( FT_Module module, + const char* name ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Module_Class */ + /* */ + /* */ + /* The module class descriptor. */ + /* */ + /* */ + /* module_flags :: Bit flags describing the module. */ + /* */ + /* module_size :: The size of one module object/instance in */ + /* bytes. */ + /* */ + /* module_name :: The name of the module. */ + /* */ + /* module_version :: The version, as a 16.16 fixed number */ + /* (major.minor). */ + /* */ + /* module_requires :: The version of FreeType this module requires */ + /* (starts at version 2.0, i.e 0x20000) */ + /* */ + /* module_init :: A function used to initialize (not create) a */ + /* new module object. */ + /* */ + /* module_done :: A function used to finalize (not destroy) a */ + /* given module object */ + /* */ + /* get_interface :: Queries a given module for a specific */ + /* interface by name. */ + /* */ + typedef struct FT_Module_Class_ + { + FT_ULong module_flags; + FT_Int module_size; + const FT_String* module_name; + FT_Fixed module_version; + FT_Fixed module_requires; + + const void* module_interface; + + FT_Module_Constructor module_init; + FT_Module_Destructor module_done; + FT_Module_Requester get_interface; + + } FT_Module_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Module */ + /* */ + /* */ + /* Adds a new module to a given library instance. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module */ + /* */ + /* */ + /* Finds a module by its name. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module handle. 0 if none was found. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT_DEF( FT_Module ) FT_Get_Module( FT_Library library, + const char* module_name ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Module */ + /* */ + /* */ + /* Removes a given module from a library instance. */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* module :: A handle to a module object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Remove_Module( FT_Library library, + FT_Module module ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Library */ + /* */ + /* */ + /* This function is used to create a new FreeType library instance */ + /* from a given memory object. It is thus possible to use libraries */ + /* with distinct memory allocators within the same program. */ + /* */ + /* */ + /* memory :: A handle to the original memory object. */ + /* */ + /* */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_New_Library( FT_Memory memory, + FT_Library* library ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Done_Library( FT_Library library ); + + + + typedef void (*FT_DebugHook_Func)( void* arg ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Debug_Hook */ + /* */ + /* */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* hook_index :: The index of the debug hook. You should use the */ + /* values defined in ftobjs.h, e.g. */ + /* FT_DEBUG_HOOK_TRUETYPE */ + /* */ + /* debug_hook :: The function used to debug the interpreter. */ + /* */ + /* */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT_DEF( void ) FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ); + + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Default_Modules */ + /* */ + /* */ + /* Adds the set of default drivers to a given library object. */ + /* This is only useful when you create a library object with */ + /* FT_New_Library() (usually to plug a custom memory manager). */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT_DEF( void ) FT_Add_Default_Modules( FT_Library library ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTMODULE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftnames.h b/subsys/win32k/freetype/include/freetype/ftnames.h new file mode 100644 index 0000000..2969214 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftnames.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ftnames.h */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTNAMES_H +#define FTNAMES_H + + +#include + + + typedef struct FT_SfntName_ + { + FT_UShort platform_id; + FT_UShort encoding_id; + FT_UShort language_id; + FT_UShort name_id; + + FT_Byte* string; + FT_UInt string_len; /* in bytes */ + + } FT_SfntName; + + + FT_EXPORT_DEF( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ); + + FT_EXPORT_DEF( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, + FT_UInt index, + FT_SfntName* aname ); + + +#endif /* FTNAMES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftoutln.h b/subsys/win32k/freetype/include/freetype/ftoutln.h new file mode 100644 index 0000000..1e448bd --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftoutln.h @@ -0,0 +1,344 @@ +/***************************************************************************/ +/* */ +/* ftoutln.h */ +/* */ +/* Support for the FT_Outline type used to store glyph shapes of */ +/* most scalable font formats (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTOUTLN_H +#define FTOUTLN_H + + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* */ + /* outline :: A pointer to the source target. */ + /* */ + /* interface :: A table of `emitters', i.e,. function pointers called */ + /* during decomposition to indicate path operations. */ + /* */ + /* user :: A typeless pointer which is passed to each emitter */ + /* during the decomposition. It can be used to store */ + /* the state during the decomposition. */ + /* */ + /* */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Decompose( + FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* library :: A handle to the library object from where the */ + /* outline is allocated. Note however that the new */ + /* outline will NOT necessarily be FREED, when */ + /* destroying the library, by FT_Done_FreeType(). */ + /* */ + /* numPoints :: The maximal number of points within the outline. */ + /* */ + /* numContours :: The maximal number of contours within the outline. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + FT_EXPORT_DEF( FT_Error ) FT_Outline_New_Internal( + FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Done( FT_Library library, + FT_Outline* outline ); + + + FT_EXPORT_DEF( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* Returns an outline's `control box'. The control box encloses all */ + /* the outline's points, including Bezier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bezier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* */ + /* */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Copy( FT_Outline* source, + FT_Outline* target ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag `ft_outline_reverse_fill' in */ + /* the outline's `flags' field. */ + /* */ + /* It shouldn't be used by a normal client application, unless it */ + /* knows what it is doing. */ + /* */ + FT_EXPORT_DEF( void ) FT_Outline_Reverse( FT_Outline* outline ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! */ + /* */ + /* It will use the raster correponding to the default glyph format. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* bitmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* Renders an outline within a bitmap using the current scan-convert. */ + /* This functions uses an FT_Raster_Params structure as an argument, */ + /* allowing advanced features like direct composition, translucency, */ + /* etc. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* You should know what you are doing and how FT_Raster_Params works */ + /* to use this function. */ + /* */ + /* The field `params.source' will be set to `outline' before the scan */ + /* converter is called, which means that the value you give to it is */ + /* actually ignored. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTOUTLN_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftrender.h b/subsys/win32k/freetype/include/freetype/ftrender.h new file mode 100644 index 0000000..fe5acd2 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftrender.h @@ -0,0 +1,191 @@ +/***************************************************************************/ +/* */ +/* ftrender.h */ +/* */ +/* FreeType renderer modules public interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTRENDER_H +#define FTRENDER_H + +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* create a new glyph object */ + typedef FT_Error (*FT_Glyph_Init_Func)( FT_Glyph glyph, + FT_GlyphSlot slot ); + + /* destroys a given glyph object */ + typedef void (*FT_Glyph_Done_Func)( FT_Glyph glyph ); + + typedef void (*FT_Glyph_Transform_Func)( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ); + + typedef void (*FT_Glyph_BBox_Func)( FT_Glyph glyph, + FT_BBox* abbox ); + + typedef FT_Error (*FT_Glyph_Copy_Func)( FT_Glyph source, + FT_Glyph target ); + + typedef FT_Error (*FT_Glyph_Prepare_Func)( FT_Glyph glyph, + FT_GlyphSlot slot ); + + struct FT_Glyph_Class_ + { + FT_UInt glyph_size; + FT_Glyph_Format glyph_format; + FT_Glyph_Init_Func glyph_init; + FT_Glyph_Done_Func glyph_done; + FT_Glyph_Copy_Func glyph_copy; + FT_Glyph_Transform_Func glyph_transform; + FT_Glyph_BBox_Func glyph_bbox; + FT_Glyph_Prepare_Func glyph_prepare; + }; + + + typedef FT_Error (*FTRenderer_render)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_UInt mode, + FT_Vector* origin ); + + typedef FT_Error (*FTRenderer_transform)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ); + + typedef void (*FTRenderer_getCBox)( FT_Renderer renderer, + FT_GlyphSlot slot, + FT_BBox* cbox ); + + typedef FT_Error (*FTRenderer_setMode)( FT_Renderer renderer, + FT_ULong mode_tag, + FT_Pointer mode_ptr ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Renderer_Class */ + /* */ + /* */ + /* The renderer module class descriptor. */ + /* */ + /* */ + /* root :: The root FT_Module_Class fields. */ + /* */ + /* glyph_format :: The glyph image format this renderer handles. */ + /* */ + /* render_glyph :: A method used to render the image that is in a */ + /* given glyph slot into a bitmap. */ + /* */ + /* set_mode :: A method used to pass additional parameters. */ + /* */ + /* raster_class :: For `ft_glyph_format_outline' renderers only, this */ + /* is a pointer to its raster's class. */ + /* */ + /* raster :: For `ft_glyph_format_outline' renderers only. this */ + /* is a pointer to the corresponding raster object, */ + /* if any. */ + /* */ + typedef struct FT_Renderer_Class_ + { + FT_Module_Class root; + + FT_Glyph_Format glyph_format; + + FTRenderer_render render_glyph; + FTRenderer_transform transform_glyph; + FTRenderer_getCBox get_glyph_cbox; + FTRenderer_setMode set_mode; + + FT_Raster_Funcs* raster_class; + + } FT_Renderer_Class; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Renderer */ + /* */ + /* */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* */ + /* A renderer handle. 0 if none found. */ + /* */ + /* */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */ + /* renderer by its name, use FT_Get_Module(). */ + /* */ + FT_EXPORT_DEF( FT_Renderer ) FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Renderer */ + /* */ + /* */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* In case of success, the renderer will be used to convert glyph */ + /* images in the renderer's known format into bitmaps. */ + /* */ + /* This doesn't change the current renderer for other formats. */ + /* */ + FT_EXPORT_DEF(FT_Error) FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTRENDER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ftsystem.h b/subsys/win32k/freetype/include/freetype/ftsystem.h new file mode 100644 index 0000000..bc74bce --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ftsystem.h @@ -0,0 +1,101 @@ +/***************************************************************************/ +/* */ +/* ftsystem.h */ +/* */ +/* FreeType low-level system interface definition (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTSYSTEM_H +#define FTSYSTEM_H + + + /*************************************************************************/ + /* */ + /* M E M O R Y M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + typedef struct FT_MemoryRec_* FT_Memory; + + + typedef void* (*FT_Alloc_Func)( FT_Memory memory, + long size ); + + typedef void (*FT_Free_Func)( FT_Memory memory, + void* block ); + + typedef void* (*FT_Realloc_Func)( FT_Memory memory, + long cur_size, + long new_size, + void* block ); + + + struct FT_MemoryRec_ + { + void* user; + FT_Alloc_Func alloc; + FT_Free_Func free; + FT_Realloc_Func realloc; + }; + + + /*************************************************************************/ + /* */ + /* I / O M A N A G E M E N T */ + /* */ + /*************************************************************************/ + + + typedef union FT_StreamDesc_ + { + long value; + void* pointer; + + } FT_StreamDesc; + + + typedef struct FT_StreamRec_* FT_Stream; + + + typedef unsigned long (*FT_Stream_IO)( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ); + + typedef void (*FT_Stream_Close)( FT_Stream stream ); + + + struct FT_StreamRec_ + { + unsigned char* base; + unsigned long size; + unsigned long pos; + + FT_StreamDesc descriptor; + FT_StreamDesc pathname; /* ignored by FreeType -- */ + /* useful for debugging */ + FT_Stream_IO read; + FT_Stream_Close close; + + FT_Memory memory; + unsigned char* cursor; + unsigned char* limit; + }; + + +#endif /* FTSYSTEM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/fttypes.h b/subsys/win32k/freetype/include/freetype/fttypes.h new file mode 100644 index 0000000..ec90906 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/fttypes.h @@ -0,0 +1,400 @@ +/***************************************************************************/ +/* */ +/* fttypes.h */ +/* */ +/* FreeType simple types definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTTYPES_H +#define FTTYPES_H + + +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Bool */ + /* */ + /* */ + /* A typedef of unsigned char, used for simple booleans. */ + /* */ + typedef unsigned char FT_Bool; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_FWord */ + /* */ + /* */ + /* A signed 16-bit integer used to store a distance in original font */ + /* units. */ + /* */ + typedef signed short FT_FWord; /* distance in FUnits */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UFWord */ + /* */ + /* */ + /* An unsigned 16-bit integer used to store a distance in original */ + /* font units. */ + /* */ + typedef unsigned short FT_UFWord; /* unsigned distance */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Char */ + /* */ + /* */ + /* A simple typedef for the _signed_ char type. */ + /* */ + typedef signed char FT_Char; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Byte */ + /* */ + /* */ + /* A simple typedef for the _unsigned_ char type. */ + /* */ + typedef unsigned char FT_Byte; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_String */ + /* */ + /* */ + /* A simple typedef for the char type, usually used for strings. */ + /* */ + typedef char FT_String; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Short */ + /* */ + /* */ + /* A typedef for signed short. */ + /* */ + typedef signed short FT_Short; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UShort */ + /* */ + /* */ + /* A typedef for unsigned short. */ + /* */ + typedef unsigned short FT_UShort; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Int */ + /* */ + /* */ + /* A typedef for the int type. */ + /* */ + typedef int FT_Int; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UInt */ + /* */ + /* */ + /* A typedef for the unsigned int type. */ + /* */ + typedef unsigned int FT_UInt; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Long */ + /* */ + /* */ + /* A typedef for signed long. */ + /* */ + typedef signed long FT_Long; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ULong */ + /* */ + /* */ + /* A typedef for unsigned long. */ + /* */ + typedef unsigned long FT_ULong; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_F2Dot14 */ + /* */ + /* */ + /* A signed 2.14 fixed float type used for unit vectors. */ + /* */ + typedef signed short FT_F2Dot14; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_F26Dot6 */ + /* */ + /* */ + /* A signed 26.6 fixed float type used for vectorial pixel */ + /* coordinates. */ + /* */ + typedef signed long FT_F26Dot6; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Fixed */ + /* */ + /* */ + /* This type is used to store 16.16 fixed float values, like scales */ + /* or matrix coefficients. */ + /* */ + typedef signed long FT_Fixed; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Error */ + /* */ + /* */ + /* The FreeType error code type. A value of 0 is always interpreted */ + /* as a successful operation. */ + /* */ + typedef int FT_Error; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Pointer */ + /* */ + /* */ + /* A simple typedef for a typeless pointer. */ + /* */ + typedef void* FT_Pointer; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_UnitVector */ + /* */ + /* */ + /* A simple structure used to store a 2D vector unit vector. Uses */ + /* FT_F2Dot14 types. */ + /* */ + /* */ + /* x :: Horizontal coordinate. */ + /* */ + /* y :: Vertical coordinate. */ + /* */ + typedef struct FT_UnitVector_ + { + FT_F2Dot14 x; + FT_F2Dot14 y; + + } FT_UnitVector; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix */ + /* */ + /* */ + /* A simple structure used to store a 2x2 matrix. Coefficients are */ + /* in 16.16 fixed float format. The computation performed is: */ + /* */ + /* { */ + /* x' = x*xx + y*xy */ + /* y' = x*yx + y*yy */ + /* } */ + /* */ + /* */ + /* xx :: Matrix coefficient. */ + /* */ + /* xy :: Matrix coefficient. */ + /* */ + /* yx :: Matrix coefficient. */ + /* */ + /* yy :: Matrix coefficient. */ + /* */ + typedef struct FT_Matrix_ + { + FT_Fixed xx, xy; + FT_Fixed yx, yy; + + } FT_Matrix; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_BBox */ + /* */ + /* */ + /* A structure used to hold an outline's bounding box, i.e., the */ + /* coordinates of its extrema in the horizontal and vertical */ + /* directions. */ + /* */ + /* */ + /* xMin :: The horizontal minimum (left-most). */ + /* */ + /* yMin :: The vertical minimum (bottom-most). */ + /* */ + /* xMax :: The horizontal maximum (right-most). */ + /* */ + /* yMax :: The vertical maximum (top-most). */ + /* */ + typedef struct FT_BBox_ + { + FT_Pos xMin, yMin; + FT_Pos xMax, yMax; + + } FT_BBox; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MAKE_TAG */ + /* */ + /* */ + /* This macro converts four letter tags which are used to label */ + /* TrueType tables into an unsigned long to be used within FreeType. */ + /* */ +#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (FT_ULong)_x1 << 24 ) | \ + ( (FT_ULong)_x2 << 16 ) | \ + ( (FT_ULong)_x3 << 8 ) | \ + (FT_ULong)_x4 ) + + + /*************************************************************************/ + /*************************************************************************/ + /* */ + /* L I S T M A N A G E M E N T */ + /* */ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListNode */ + /* */ + /* */ + /* Many elements and objects in FreeType are listed through a */ + /* FT_List record (see FT_ListRec). As its name suggests, a */ + /* FT_ListNode is a handle to a single list element. */ + /* */ + typedef struct FT_ListNodeRec_* FT_ListNode; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List */ + /* */ + /* */ + /* A handle to a list record (see FT_ListRec). */ + /* */ + typedef struct FT_ListRec_* FT_List; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListNodeRec */ + /* */ + /* */ + /* A structure used to hold a single list element. */ + /* */ + /* */ + /* prev :: The previous element in the list. NULL if first. */ + /* */ + /* next :: The next element in the list. NULL if last. */ + /* */ + /* data :: A typeless pointer to the listed object. */ + /* */ + typedef struct FT_ListNodeRec_ + { + FT_ListNode prev; + FT_ListNode next; + void* data; + + } FT_ListNodeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ListRec */ + /* */ + /* */ + /* A structure used to hold a simple doubly-linked list. These are */ + /* used in many parts of FreeType. */ + /* */ + /* */ + /* head :: The head (first element) of doubly-linked list. */ + /* */ + /* tail :: The tail (last element) of doubly-linked list. */ + /* */ + typedef struct FT_ListRec_ + { + FT_ListNode head; + FT_ListNode tail; + + } FT_ListRec; + + +#define FT_IS_EMPTY( list ) ( (list).head == 0 ) + + +#endif /* FTTYPES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/autohint.h b/subsys/win32k/freetype/include/freetype/internal/autohint.h new file mode 100644 index 0000000..5d35a5d --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/autohint.h @@ -0,0 +1,195 @@ +/***************************************************************************/ +/* */ +/* autohint.h */ +/* */ +/* High-level `autohint' module-specific interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The auto-hinter is used to load and automatically hint glyphs if a */ + /* format-specific hinter isn't available. */ + /* */ + /*************************************************************************/ + + +#ifndef AUTOHINT_H +#define AUTOHINT_H + + + /*************************************************************************/ + /* */ + /* A small technical note regarding automatic hinting in order to */ + /* clarify this module interface. */ + /* */ + /* An automatic hinter might compute two kinds of data for a given face: */ + /* */ + /* - global hints: Usually some metrics that describe global properties */ + /* of the face. It is computed by scanning more or less */ + /* agressively the glyphs in the face, and thus can be */ + /* very slow to compute (even if the size of global */ + /* hints is really small). */ + /* */ + /* - glyph hints: These describe some important features of the glyph */ + /* outline, as well as how to align them. They are */ + /* generally much faster to compute than global hints. */ + /* */ + /* The current FreeType auto-hinter does a pretty good job while */ + /* performing fast computations for both global and glyph hints. */ + /* However, we might be interested in introducing more complex and */ + /* powerful algorithms in the future, like the one described in the John */ + /* D. Hobby paper, which unfortunately requires a lot more horsepower. */ + /* */ + /* Because a sufficiently sophisticated font management system would */ + /* typically implement an LRU cache of opened face objects to reduce */ + /* memory usage, it is a good idea to be able to avoid recomputing */ + /* global hints every time the same face is re-opened. */ + /* */ + /* We thus provide the ability to cache global hints outside of the face */ + /* object, in order to speed up font re-opening time. Of course, this */ + /* feature is purely optional, so most client programs won't even notice */ + /* it. */ + /* */ + /* I initially thought that it would be a good idea to cache the glyph */ + /* hints too. However, my general idea now is that if you really need */ + /* to cache these too, you are simply in need of a new font format, */ + /* where all this information could be stored within the font file and */ + /* decoded on the fly. */ + /* */ + /*************************************************************************/ + + +#include + + + typedef struct FT_AutoHinterRec_ *FT_AutoHinter; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Get_Global_Func */ + /* */ + /* */ + /* Retrieves the global hints computed for a given face object the */ + /* resulting data is dissociated from the face and will survive a */ + /* call to FT_Done_Face(). It must be discarded through the API */ + /* FT_AutoHinter_Done_Global_Func(). */ + /* */ + /* */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* global_hints :: A typeless pointer to the global hints. */ + /* */ + /* global_len :: The size in bytes of the global hints. */ + /* */ + typedef void (*FT_AutoHinter_Get_Global_Func)( + FT_AutoHinter hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Done_Global_Func */ + /* */ + /* */ + /* Discards the global hints retrieved through */ + /* FT_AutoHinter_Get_Global_Func(). This is the only way these hints */ + /* are freed from memory. */ + /* */ + /* */ + /* hinter :: A handle to the auto-hinter module. */ + /* */ + /* global :: A pointer to retrieved global hints to discard. */ + /* */ + typedef void (*FT_AutoHinter_Done_Global_Func)( FT_AutoHinter hinter, + void* global ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Reset_Func */ + /* */ + /* */ + /* This function is used to recompute the global metrics in a given */ + /* font. This is useful when global font data changes (e.g. Multiple */ + /* Masters fonts where blend coordinates change). */ + /* */ + /* */ + /* hinter :: A handle to the source auto-hinter. */ + /* */ + /* face :: A handle to the face. */ + /* */ + typedef void (*FT_AutoHinter_Reset_Func)( FT_AutoHinter hinter, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Load_Func */ + /* */ + /* */ + /* This function is used to load, scale, and automatically hint a */ + /* glyph from a given face. */ + /* */ + /* */ + /* face :: A handle to the face. */ + /* glyph_index :: The glyph index. */ + /* load_flags :: The load flags. */ + /* */ + /* */ + /* This function is capable of loading composite glyphs by hinting */ + /* each sub-glyph independently (which improves quality). */ + /* */ + /* It will call the font driver with FT_Load_Glyph(), with */ + /* FT_LOAD_NO_SCALE set. */ + /* */ + typedef FT_Error (*FT_AutoHinter_Load_Func)( FT_AutoHinter hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_ULong load_flags ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_AutoHinter_Interface */ + /* */ + /* */ + /* The auto-hinter module's interface. */ + /* */ + typedef struct FT_AutoHinter_Interface + { + FT_AutoHinter_Reset_Func reset_face; + FT_AutoHinter_Load_Func load_glyph; + + FT_AutoHinter_Get_Global_Func get_global_hints; + FT_AutoHinter_Done_Global_Func done_global_hints; + + } FT_AutoHinter_Interface; + + +#endif /* AUTOHINT_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftcalc.h b/subsys/win32k/freetype/include/freetype/internal/ftcalc.h new file mode 100644 index 0000000..99b6cfa --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftcalc.h @@ -0,0 +1,123 @@ +/***************************************************************************/ +/* */ +/* ftcalc.h */ +/* */ +/* Arithmetic computations (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTCALC_H +#define FTCALC_H + +#include +#include /* for LONG64 */ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef LONG64 + + + typedef INT64 FT_Int64; + +#define ADD_64( x, y, z ) z = (x) + (y) +#define MUL_64( x, y, z ) z = (FT_Int64)(x) * (y) + +#define DIV_64( x, y ) ( (x) / (y) ) + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( z ) + + FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64 l ); + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#else /* LONG64 */ + + + typedef struct FT_Int64_ + { + FT_UInt32 lo; + FT_UInt32 hi; + + } FT_Int64; + + +#define ADD_64( x, y, z ) FT_Add64( &x, &y, &z ) +#define MUL_64( x, y, z ) FT_MulTo64( x, y, &z ) +#define DIV_64( x, y ) FT_Div64by32( &x, y ) + + + FT_EXPORT_DEF( void ) FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ); + + FT_EXPORT_DEF( void ) FT_MulTo64( FT_Int32 x, + FT_Int32 y, + FT_Int64* z ); + + FT_EXPORT_DEF( FT_Int32 ) FT_Div64by32( FT_Int64* x, + FT_Int32 y ); + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( &z ) + + FT_EXPORT_DEF( FT_Int32 ) FT_Sqrt64( FT_Int64* x ); + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#endif /* LONG64 */ + + +#ifndef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_32( x ) FT_Sqrt32( x ) + + BASE_DEF( FT_Int32 ) FT_Sqrt32( FT_Int32 x ); + +#endif /* !FT_CONFIG_OPTION_OLD_CALCS */ + + + /*************************************************************************/ + /* */ + /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) +#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) +#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) +#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) +#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) + +#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ + : ( -( ( 32 - (x) ) & -64 ) ) ) + + +#ifdef __cplusplus + } +#endif + +#endif /* FTCALC_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftdebug.h b/subsys/win32k/freetype/include/freetype/internal/ftdebug.h new file mode 100644 index 0000000..8b1e4dd --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftdebug.h @@ -0,0 +1,225 @@ +/***************************************************************************/ +/* */ +/* ftdebug.h */ +/* */ +/* Debugging and logging component (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTDEBUG_H +#define FTDEBUG_H + +#include /* for FT_DEBUG_LEVEL_TRACE, */ + /* FT_DEBUG_LEVEL_ERROR */ + +#ifdef __cplusplus + extern "C" { +#endif + + + /* A very stupid pre-processor trick. See K&R version 2 */ + /* section A12.3 for details... */ + /* */ + /* It is also described in the section `Separate */ + /* Expansion of Macro Arguments' in the info file */ + /* `cpp.info', describing GNU cpp. */ + /* */ +#define FT_CAT( x, y ) x ## y +#define FT_XCAT( x, y ) FT_CAT( x, y ) + + +#ifdef FT_DEBUG_LEVEL_TRACE + + + /* note that not all levels are used currently */ + + typedef enum FT_Trace_ + { + /* the first level must always be `trace_any' */ + trace_any = 0, + + /* base components */ + trace_aaraster, /* anti-aliasing raster (ftgrays.c) */ + trace_calc, /* calculations (ftcalc.c) */ + trace_extend, /* extension manager (ftextend.c) */ + trace_glyph, /* glyph manager (ftglyph.c) */ + trace_io, /* i/o monitoring (ftsystem.c) */ + trace_init, /* initialization (ftinit.c) */ + trace_list, /* list manager (ftlist.c) */ + trace_memory, /* memory manager (ftobjs.c) */ + trace_mm, /* MM interface (ftmm.c) */ + trace_objs, /* base objects (ftobjs.c) */ + trace_outline, /* outline management (ftoutln.c) */ + trace_raster, /* rasterizer (ftraster.c) */ + trace_stream, /* stream manager (ftstream.c) */ + + /* SFNT driver components */ + trace_sfobjs, /* SFNT object handler (sfobjs.c) */ + trace_ttcmap, /* charmap handler (ttcmap.c) */ + trace_ttload, /* basic TrueType tables (ttload.c) */ + trace_ttpost, /* PS table processing (ttpost.c) */ + trace_ttsbit, /* TrueType sbit handling (ttsbit.c) */ + + /* TrueType driver components */ + trace_ttdriver, /* TT font driver (ttdriver.c) */ + trace_ttgload, /* TT glyph loader (ttgload.c) */ + trace_ttinterp, /* bytecode interpreter (ttinterp.c) */ + trace_ttobjs, /* TT objects manager (ttobjs.c) */ + trace_ttpload, /* TT data/program loader (ttpload.c) */ + + /* Type 1 driver components */ + trace_t1driver, + trace_t1gload, + trace_t1hint, + trace_t1load, + trace_t1objs, + + /* experimental Type 1 driver components */ + trace_z1driver, + trace_z1gload, + trace_z1hint, + trace_z1load, + trace_z1objs, + trace_z1parse, + + /* Type 2 driver components */ + trace_t2driver, + trace_t2gload, + trace_t2load, + trace_t2objs, + trace_t2parse, + + /* CID driver components */ + trace_cidafm, + trace_ciddriver, + trace_cidgload, + trace_cidload, + trace_cidobjs, + trace_cidparse, + + /* Windows fonts component */ + trace_winfnt, + + /* the last level must always be `trace_max' */ + trace_max + + } FT_Trace; + + + /* declared in ftdebug.c */ + extern char ft_trace_levels[trace_max]; + + + /*************************************************************************/ + /* */ + /* IMPORTANT! */ + /* */ + /* Each component must define the macro FT_COMPONENT to a valid FT_Trace */ + /* value before using any TRACE macro. */ + /* */ + /*************************************************************************/ + + +#define FT_TRACE( level, varformat ) \ + do \ + { \ + if ( ft_trace_levels[FT_COMPONENT] >= level ) \ + FT_XCAT( FT_Message, varformat ); \ + } while ( 0 ) + + + FT_EXPORT_DEF( void ) FT_SetTraceLevel( FT_Trace component, + char level ); + + +#elif defined( FT_DEBUG_LEVEL_ERROR ) + + +#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */ + + +#else /* release mode */ + + +#define FT_Assert( condition ) do ; while ( 0 ) /* nothing */ + +#define FT_TRACE( level, varformat ) do ; while ( 0 ) /* nothing */ +#define FT_ERROR( varformat ) do ; while ( 0 ) /* nothing */ + + +#endif /* FT_DEBUG_LEVEL_TRACE, FT_DEBUG_LEVEL_ERROR */ + + + /*************************************************************************/ + /* */ + /* Define macros and functions that are common to the debug and trace */ + /* modes. */ + /* */ + /* You need vprintf() to be able to compile ftdebug.c. */ + /* */ + /*************************************************************************/ + + +#if defined( FT_DEBUG_LEVEL_TRACE ) || defined( FT_DEBUG_LEVEL_ERROR ) + + +#include "stdio.h" /* for vprintf() */ + + +#define FT_Assert( condition ) \ + do \ + { \ + if ( !( condition ) ) \ + FT_Panic( "assertion failed on line %d of file %s\n", \ + __LINE__, __FILE__ ); \ + } while ( 0 ) + + /* print a message */ + FT_EXPORT_DEF( void ) FT_Message( const char* fmt, ... ); + + /* print a message and exit */ + FT_EXPORT_DEF( void ) FT_Panic( const char* fmt, ... ); + +#define FT_ERROR( varformat ) FT_XCAT( FT_Message, varformat ) + + +#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */ + + + /*************************************************************************/ + /* */ + /* You need two opening resp. closing parentheses! */ + /* */ + /* Example: FT_TRACE0(( "Value is %i", foo )) */ + /* */ + /*************************************************************************/ + +#define FT_TRACE0( varformat ) FT_TRACE( 0, varformat ) +#define FT_TRACE1( varformat ) FT_TRACE( 1, varformat ) +#define FT_TRACE2( varformat ) FT_TRACE( 2, varformat ) +#define FT_TRACE3( varformat ) FT_TRACE( 3, varformat ) +#define FT_TRACE4( varformat ) FT_TRACE( 4, varformat ) +#define FT_TRACE5( varformat ) FT_TRACE( 5, varformat ) +#define FT_TRACE6( varformat ) FT_TRACE( 6, varformat ) +#define FT_TRACE7( varformat ) FT_TRACE( 7, varformat ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTDEBUG_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftdriver.h b/subsys/win32k/freetype/include/freetype/internal/ftdriver.h new file mode 100644 index 0000000..592de49 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftdriver.h @@ -0,0 +1,182 @@ +/***************************************************************************/ +/* */ +/* ftdriver.h */ +/* */ +/* FreeType font driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTDRIVER_H +#define FTDRIVER_H + + +#include +#include + + + typedef FT_Error (*FTDriver_initFace)( FT_Stream stream, + FT_Face face, + FT_Int typeface_index, + FT_Int num_params, + FT_Parameter* parameters ); + + typedef void (*FTDriver_doneFace)( FT_Face face ); + + + typedef FT_Error (*FTDriver_initSize)( FT_Size size ); + + typedef void (*FTDriver_doneSize)( FT_Size size ); + + + typedef FT_Error (*FTDriver_initGlyphSlot)( FT_GlyphSlot slot ); + + typedef void (*FTDriver_doneGlyphSlot)( FT_GlyphSlot slot ); + + + typedef FT_Error (*FTDriver_setCharSizes)( FT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ); + + typedef FT_Error (*FTDriver_setPixelSizes)( FT_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ); + + typedef FT_Error (*FTDriver_loadGlyph)( FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ); + + + typedef FT_UInt (*FTDriver_getCharIndex)( FT_CharMap charmap, + FT_Long charcode ); + + typedef FT_Error (*FTDriver_getKerning)( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ); + + + typedef FT_Error (*FTDriver_attachFile)( FT_Face face, + FT_Stream stream ); + + + typedef FT_Error (*FTDriver_getAdvances)( FT_Face face, + FT_UInt first, + FT_UInt count, + FT_Bool vertical, + FT_UShort* advances ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Driver_Class */ + /* */ + /* */ + /* The font driver class. This structure mostly contains pointers to */ + /* driver methods. */ + /* */ + /* */ + /* root :: The parent module. */ + /* */ + /* face_object_size :: The size of a face object in bytes. */ + /* */ + /* size_object_size :: The size of a size object in bytes. */ + /* */ + /* slot_object_size :: The size of a glyph object in bytes. */ + /* */ + /* init_face :: The format-specific face constructor. */ + /* */ + /* done_face :: The format-specific face destructor. */ + /* */ + /* init_size :: The format-specific size constructor. */ + /* */ + /* done_size :: The format-specific size destructor. */ + /* */ + /* init_slot :: The format-specific slot constructor. */ + /* */ + /* done_slot :: The format-specific slot destructor. */ + /* */ + /* set_char_sizes :: A handle to a function used to set the new */ + /* character size in points + resolution. Can be */ + /* set to 0 to indicate default behaviour. */ + /* */ + /* set_pixel_sizes :: A handle to a function used to set the new */ + /* character size in pixels. Can be set to 0 to */ + /* indicate default behaviour. */ + /* */ + /* load_glyph :: A function handle to load a given glyph image */ + /* in a slot. This field is mandatory! */ + /* */ + /* get_char_index :: A function handle to return the glyph index of */ + /* a given character for a given charmap. This */ + /* field is mandatory! */ + /* */ + /* get_kerning :: A function handle to return the unscaled */ + /* kerning for a given pair of glyphs. Can be */ + /* set to 0 if the format doesn't support */ + /* kerning. */ + /* */ + /* attach_file :: This function handle is used to read */ + /* additional data for a face from another */ + /* file/stream. For example, this can be used to */ + /* add data from AFM or PFM files on a Type 1 */ + /* face, or a CIDMap on a CID-keyed face. */ + /* */ + /* get_advances :: A function handle used to return the advances */ + /* of 'count' glyphs, starting at `index'. the */ + /* `vertical' flags must be set when vertical */ + /* advances are queried. The advances buffer is */ + /* caller-allocated. */ + /* */ + /* */ + /* Most function pointers, with the exception of `load_glyph' and */ + /* `get_char_index' can be set to 0 to indicate a default behaviour. */ + /* */ + typedef struct FT_Driver_Class_ + { + FT_Module_Class root; + + FT_Int face_object_size; + FT_Int size_object_size; + FT_Int slot_object_size; + + FTDriver_initFace init_face; + FTDriver_doneFace done_face; + + FTDriver_initSize init_size; + FTDriver_doneSize done_size; + + FTDriver_initGlyphSlot init_slot; + FTDriver_doneGlyphSlot done_slot; + + FTDriver_setCharSizes set_char_sizes; + FTDriver_setPixelSizes set_pixel_sizes; + + FTDriver_loadGlyph load_glyph; + FTDriver_getCharIndex get_char_index; + + FTDriver_getKerning get_kerning; + FTDriver_attachFile attach_file; + + FTDriver_getAdvances get_advances; + + } FT_Driver_Class; + + +#endif /* FTDRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftextend.h b/subsys/win32k/freetype/include/freetype/internal/ftextend.h new file mode 100644 index 0000000..fdd2c6e --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftextend.h @@ -0,0 +1,178 @@ +/***************************************************************************/ +/* */ +/* ftextend.h */ +/* */ +/* FreeType extensions implementation (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTEXTEND_H +#define FTEXTEND_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* The extensions don't need to be integrated at compile time into the */ + /* engine, only at link time. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Initializer */ + /* */ + /* */ + /* Each new face object can have several extensions associated with */ + /* it at creation time. This function is used to initialize given */ + /* extension data for a given face. */ + /* */ + /* */ + /* ext :: A typeless pointer to the extension data. */ + /* */ + /* face :: A handle to the source face object the extension is */ + /* associated with. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* In case of error, the initializer should not destroy the extension */ + /* data, as the finalizer will get called later by the function's */ + /* caller. */ + /* */ + typedef FT_Error (*FT_Extension_Initializer)( void* ext, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Finalizer */ + /* */ + /* */ + /* Each new face object can have several extensions associated with */ + /* it at creation time. This function is used to finalize given */ + /* extension data for a given face; it occurs before the face object */ + /* itself is finalized. */ + /* */ + /* */ + /* ext :: A typeless pointer to the extension data. */ + /* */ + /* face :: A handle to the source face object the extension is */ + /* associated with. */ + /* */ + typedef void (*FT_Extension_Finalizer)( void* ext, + FT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Extension_Class */ + /* */ + /* */ + /* A simple structure used to describe a given extension to the */ + /* FreeType base layer. An FT_Extension_Class is used as a parameter */ + /* for FT_Register_Extension(). */ + /* */ + /* */ + /* id :: The extension's ID. This is a normal C string that */ + /* is used to uniquely reference the extension's */ + /* interface. */ + /* */ + /* size :: The size in bytes of the extension data that must be */ + /* associated with each face object. */ + /* */ + /* init :: A pointer to the extension data's initializer. */ + /* */ + /* finalize :: A pointer to the extension data's finalizer. */ + /* */ + /* interface :: This pointer can be anything, but should usually */ + /* point to a table of function pointers which implement */ + /* the extension's interface. */ + /* */ + /* offset :: This field is set and used within the base layer and */ + /* should be set to 0 when registering an extension */ + /* through FT_Register_Extension(). It contains an */ + /* offset within the face's extension block for the */ + /* current extension's data. */ + /* */ + typedef struct FT_Extension_Class_ + { + const char* id; + FT_ULong size; + FT_Extension_Initializer init; + FT_Extension_Finalizer finalize; + void* interface; + + FT_ULong offset; + + } FT_Extension_Class; + + + FT_EXPORT_DEF( FT_Error ) FT_Register_Extension( + FT_Driver driver, + FT_Extension_Class* clazz ); + + +#ifdef FT_CONFIG_OPTION_EXTEND_ENGINE + + + /* Initialize the extension component */ + LOCAL_DEF + FT_Error FT_Init_Extensions( FT_Library library ); + + /* Finalize the extension component */ + LOCAL_DEF + FT_Error FT_Done_Extensions( FT_Library library ); + + /* Create an extension within a face object. Called by the */ + /* face object constructor. */ + LOCAL_DEF + FT_Error FT_Create_Extensions( FT_Face face ); + + /* Destroy all extensions within a face object. Called by the */ + /* face object destructor. */ + LOCAL_DEF + FT_Error FT_Destroy_Extensions( FT_Face face ); + + +#endif + + + /* return an extension's data & interface according to its ID */ + FT_EXPORT_DEF( void* ) FT_Get_Extension( + FT_Face face, + const char* extension_id, + void** extension_interface ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTEXTEND_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftlist.h b/subsys/win32k/freetype/include/freetype/internal/ftlist.h new file mode 100644 index 0000000..7c6d8ed --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftlist.h @@ -0,0 +1,113 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file implements functions relative to list processing. Its */ + /* data structures are defined in `freetype.h'. */ + /* */ + /*************************************************************************/ + + +#ifndef FTLIST_H +#define FTLIST_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + FT_EXPORT_DEF( FT_ListNode ) FT_List_Find( FT_List list, + void* data ); + + FT_EXPORT_DEF( void ) FT_List_Add( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Insert( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Remove( FT_List list, + FT_ListNode node ); + + FT_EXPORT_DEF( void ) FT_List_Up( FT_List list, + FT_ListNode node ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Iterator */ + /* */ + /* */ + /* An FT_List iterator function which is called during a list parse */ + /* by FT_List_Iterate(). */ + /* */ + /* */ + /* node :: The current iteration list node. */ + /* */ + /* user :: A typeless pointer passed to FT_List_Iterate(). */ + /* Can be used to point to the iteration's state. */ + /* */ + typedef FT_Error (*FT_List_Iterator)( FT_ListNode node, + void* user ); + + + FT_EXPORT_DEF( FT_Error ) FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Destructor */ + /* */ + /* */ + /* An FT_List iterator function which is called during a list */ + /* finalization by FT_List_Finalize() to destroy all elements in a */ + /* given list. */ + /* */ + /* */ + /* system :: The current system object. */ + /* */ + /* data :: The current object to destroy. */ + /* */ + /* user :: A typeless pointer passed to FT_List_Iterate(). It can */ + /* be used to point to the iteration's state. */ + /* */ + typedef void (*FT_List_Destructor)( FT_Memory memory, + void* data, + void* user ); + + + FT_EXPORT_DEF( void ) FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ); + + +#ifdef __cplusplus + } +#endif + +#endif /* FTLIST_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftmemory.h b/subsys/win32k/freetype/include/freetype/internal/ftmemory.h new file mode 100644 index 0000000..da8d3a4 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftmemory.h @@ -0,0 +1,127 @@ +/***************************************************************************/ +/* */ +/* ftmemory.h */ +/* */ +/* The FreeType memory management macros (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTMEMORY_H +#define FTMEMORY_H + + +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SET_ERROR */ + /* */ + /* */ + /* This macro is used to set an implicit `error' variable to a given */ + /* expression's value (usually a function call), and convert it to a */ + /* boolean which is set whenever the value is != 0. */ + /* */ +#undef FT_SET_ERROR +#define FT_SET_ERROR( expression ) \ + ( ( error = (expression) ) != 0 ) + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M E M O R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + BASE_DEF( FT_Error ) FT_Alloc( FT_Memory memory, + FT_Long size, + void** P ); + + BASE_DEF( FT_Error ) FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ); + + BASE_DEF( void ) FT_Free( FT_Memory memory, + void** P ); + + + + /* This `#include' is needed by the MEM_xxx() macros; it should be */ + /* available on all platforms we know of. */ +#include + +#define MEM_Set( dest, byte, count ) memset( dest, byte, count ) + +#define MEM_Copy( dest, source, count ) memcpy( dest, source, count ) + +#define MEM_Move( dest, source, count ) memmove( dest, source, count ) + + + /*************************************************************************/ + /* */ + /* We now support closures to produce completely reentrant code. This */ + /* means the allocation functions now takes an additional argument */ + /* (`memory'). It is a handle to a given memory object, responsible for */ + /* all low-level operations, including memory management and */ + /* synchronisation. */ + /* */ + /* In order to keep our code readable and use the same macros in the */ + /* font drivers and the rest of the library, MEM_Alloc(), ALLOC(), and */ + /* ALLOC_ARRAY() now use an implicit variable, `memory'. It must be */ + /* defined at all locations where a memory operation is queried. */ + /* */ +#define MEM_Alloc( _pointer_, _size_ ) \ + FT_Alloc( memory, _size_, (void**)&(_pointer_) ) + +#define MEM_Alloc_Array( _pointer_, _count_, _type_ ) \ + FT_Alloc( memory, (_count_)*sizeof ( _type_ ), \ + (void**)&(_pointer_) ) + +#define MEM_Realloc( _pointer_, _current_, _size_ ) \ + FT_Realloc( memory, _current_, _size_, (void**)&(_pointer_) ) + +#define MEM_Realloc_Array( _pointer_, _current_, _new_, _type_ ) \ + FT_Realloc( memory, (_current_)*sizeof ( _type_ ), \ + (_new_)*sizeof ( _type_ ), (void**)&(_pointer_) ) + +#define ALLOC( _pointer_, _size_ ) \ + FT_SET_ERROR( MEM_Alloc( _pointer_, _size_ ) ) + +#define REALLOC( _pointer_, _current_, _size_ ) \ + FT_SET_ERROR( MEM_Realloc( _pointer_, _current_, _size_ ) ) + +#define ALLOC_ARRAY( _pointer_, _count_, _type_ ) \ + FT_SET_ERROR( MEM_Alloc( _pointer_, \ + (_count_)*sizeof ( _type_ ) ) ) + +#define REALLOC_ARRAY( _pointer_, _current_, _count_, _type_ ) \ + FT_SET_ERROR( MEM_Realloc( _pointer_, \ + (_current_)*sizeof ( _type_ ), \ + (_count_)*sizeof ( _type_ ) ) ) + +#define FREE( _pointer_ ) FT_Free( memory, (void**)&(_pointer_) ) + + +#endif /* FTMEMORY_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftobjs.h b/subsys/win32k/freetype/include/freetype/internal/ftobjs.h new file mode 100644 index 0000000..0d0f5d8 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftobjs.h @@ -0,0 +1,532 @@ +/***************************************************************************/ +/* */ +/* ftobjs.h */ +/* */ +/* The FreeType private base classes (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This file contains the definition of all internal FreeType classes. */ + /* */ + /*************************************************************************/ + + +#ifndef FTOBJS_H +#define FTOBJS_H + +#include +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* Some generic definitions. */ + /* */ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + +#ifndef UNUSED +#define UNUSED( arg ) ( (arg)=(arg) ) +#endif + + + /*************************************************************************/ + /* */ + /* The min and max functions missing in C. As usual, be careful not to */ + /* write things like MIN( a++, b++ ) to avoid side effects. */ + /* */ +#ifndef MIN +#define MIN( a, b ) ( (a) < (b) ? (a) : (b) ) +#endif + +#ifndef MAX +#define MAX( a, b ) ( (a) > (b) ? (a) : (b) ) +#endif + +#ifndef ABS +#define ABS( a ) ( (a) < 0 ? -(a) : (a) ) +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M O D U L E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_ModuleRec */ + /* */ + /* */ + /* A module object instance. */ + /* */ + /* */ + /* clazz :: A pointer to the module's class. */ + /* */ + /* library :: A handle to the parent library object. */ + /* */ + /* memory :: A handle to the memory manager. */ + /* */ + /* generic :: A generic structure for user-level extensibility (?). */ + /* */ + typedef struct FT_ModuleRec_ + { + FT_Module_Class* clazz; + FT_Library library; + FT_Memory memory; + FT_Generic generic; + + } FT_ModuleRec; + + + /* typecast an object to a FT_Module */ +#define FT_MODULE( x ) ((FT_Module)(x)) +#define FT_MODULE_CLASS( x ) FT_MODULE(x)->clazz +#define FT_MODULE_LIBRARY( x ) FT_MODULE(x)->library +#define FT_MODULE_MEMORY( x ) FT_MODULE(x)->memory + +#define FT_MODULE_IS_DRIVER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_font_driver ) + +#define FT_MODULE_IS_RENDERER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_renderer ) + +#define FT_MODULE_IS_HINTER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_hinter ) + +#define FT_MODULE_IS_STYLER( x ) ( FT_MODULE_CLASS( x )->module_flags & \ + ft_module_styler ) + +#define FT_DRIVER_IS_SCALABLE( x ) ( FT_MODULE_CLASS(x)->module_flags & \ + ft_module_driver_scalable ) + +#define FT_DRIVER_USES_OUTLINES( x ) !( FT_MODULE_CLASS(x)->module_flags & \ + ft_module_driver_no_outlines ) + +#define FT_DRIVER_HAS_HINTER( x ) ( FT_MODULE_CLASS(x)->module_flags & \ + ft_module_driver_has_hinter ) + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module_Interface */ + /* */ + /* */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + BASE_DEF( const void* ) FT_Get_Module_Interface( FT_Library library, + const char* mod_name ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* a few macros used to perform easy typecasts with minimal brain damage */ + +#define FT_FACE( x ) ((FT_Face)(x)) +#define FT_SIZE( x ) ((FT_Size)(x)) +#define FT_SLOT( x ) ((FT_GlyphSlot)(x)) + +#define FT_FACE_DRIVER( x ) FT_FACE( x )->driver +#define FT_FACE_LIBRARY( x ) FT_FACE_DRIVER( x )->root.library +#define FT_FACE_MEMORY( x ) FT_FACE( x )->memory + +#define FT_SIZE_FACE( x ) FT_SIZE( x )->face +#define FT_SLOT_FACE( x ) FT_SLOT( x )->face + +#define FT_FACE_SLOT( x ) FT_FACE( x )->glyph +#define FT_FACE_SIZE( x ) FT_FACE( x )->size + + + /* this must be kept exported -- tt will be used later in our own */ + /* high-level caching font manager called SemTex (way after the */ + /* 2.0 release though */ + FT_EXPORT_DEF( FT_Error ) FT_New_Size( FT_Face face, + FT_Size* size ); + + FT_EXPORT_DEF( FT_Error ) FT_Done_Size( FT_Size size ); + + + FT_EXPORT_DEF( FT_Error ) FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ); + + FT_EXPORT_DEF( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** G L Y P H L O A D E R ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1 +#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2 +#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4 +#define FT_SUBGLYPH_FLAG_SCALE 8 +#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40 +#define FT_SUBGLYPH_FLAG_2X2 0x80 +#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200 + + + enum + { + ft_glyph_own_bitmap = 1 + }; + + + struct FT_SubGlyph_ + { + FT_Int index; + FT_UShort flags; + FT_Int arg1; + FT_Int arg2; + FT_Matrix transform; + }; + + + typedef struct FT_GlyphLoad_ + { + FT_Outline outline; /* outline */ + FT_UInt num_subglyphs; /* number of subglyphs */ + FT_SubGlyph* subglyphs; /* subglyphs */ + FT_Vector* extra_points; /* extra points table */ + + } FT_GlyphLoad; + + + struct FT_GlyphLoader_ + { + FT_Memory memory; + FT_UInt max_points; + FT_UInt max_contours; + FT_UInt max_subglyphs; + FT_Bool use_extra; + + FT_GlyphLoad base; + FT_GlyphLoad current; + + void* other; /* for possible future extension? */ + + }; + + + BASE_DEF( FT_Error ) FT_GlyphLoader_New( FT_Memory memory, + FT_GlyphLoader** aloader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Create_Extra( + FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Points( + FT_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Check_Subglyphs( + FT_GlyphLoader* loader, + FT_UInt n_subs ); + + BASE_DEF( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader ); + + BASE_DEF( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader ); + + BASE_DEF( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target, + FT_GlyphLoader* source ); + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_RENDERER( x ) ((FT_Renderer)( x )) +#define FT_GLYPH( x ) ((FT_Glyph)( x )) +#define FT_BITMAP_GLYPH( x ) ((FT_BitmapGlyph)( x )) +#define FT_OUTLINE_GLYPH( x ) ((FT_OutlineGlyph)( x )) + + + typedef struct FT_RendererRec_ + { + FT_ModuleRec root; + FT_Renderer_Class* clazz; + FT_Glyph_Format glyph_format; + const FT_Glyph_Class glyph_class; + + FT_Raster raster; + FT_Raster_Render_Func raster_render; + FTRenderer_render render; + + } FT_RendererRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F O N T D R I V E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* typecast a module into a driver easily */ +#define FT_DRIVER( x ) ((FT_Driver)(x)) + + /* typecast a module as a driver, and get its driver class */ +#define FT_DRIVER_CLASS( x ) FT_DRIVER( x )->clazz + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DriverRec */ + /* */ + /* */ + /* The root font driver class. A font driver is responsible for */ + /* managing and loading font files of a given format. */ + /* */ + /* */ + /* root :: Contains the fields of the root module class. */ + /* */ + /* clazz :: A pointer to the font driver's class. Note that */ + /* this is NOT root.clazz. `class' wasn't used */ + /* as it is a reserved word in C++. */ + /* */ + /* faces_list :: The list of faces currently opened by this */ + /* driver. */ + /* */ + /* extensions :: A typeless pointer to the driver's extensions */ + /* registry, if they are supported through the */ + /* configuration macro FT_CONFIG_OPTION_EXTENSIONS. */ + /* */ + /* glyph_loader :: The glyph loader for all faces managed by this */ + /* driver. This object isn't defined for unscalable */ + /* formats. */ + /* */ + typedef struct FT_DriverRec_ + { + FT_ModuleRec root; + FT_Driver_Class* clazz; + + FT_ListRec faces_list; + void* extensions; + + FT_GlyphLoader* glyph_loader; + + } FT_DriverRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** L I B R A R I E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define FT_DEBUG_HOOK_TRUETYPE 0 +#define FT_DEBUG_HOOK_TYPE1 1 + + + /*************************************************************************/ + /* */ + /* */ + /* FT_LibraryRec */ + /* */ + /* */ + /* The FreeType library class. This is the root of all FreeType */ + /* data. Use FT_New_Library() to create a library object, and */ + /* FT_Done_Library() to discard it and all child objects. */ + /* */ + /* */ + /* memory :: The library's memory object. Manages memory */ + /* allocation. */ + /* */ + /* generic :: Client data variable. Used to extend the */ + /* Library class by higher levels and clients. */ + /* */ + /* num_modules :: The number of modules currently registered */ + /* within this library. This is set to 0 for new */ + /* libraries. New modules are added through the */ + /* FT_Add_Module() API function. */ + /* */ + /* modules :: A table used to store handles to the currently */ + /* registered modules. Note that each font driver */ + /* contains a list of its opened faces. */ + /* */ + /* renderers :: The list of renderers currently registered */ + /* within the library. */ + /* */ + /* cur_renderer :: The current outline renderer. This is a */ + /* shortcut used to avoid parsing the list on */ + /* each call to FT_Outline_Render(). It is a */ + /* handle to the current renderer for the */ + /* ft_glyph_format_outline format. */ + /* */ + /* auto_hinter :: XXX */ + /* */ + /* raster_pool :: The raster object's render pool. This can */ + /* ideally be changed dynamically at run-time. */ + /* */ + /* raster_pool_size :: The size of the render pool in bytes. */ + /* */ + /* debug_hooks :: XXX */ + /* */ + typedef struct FT_LibraryRec_ + { + FT_Memory memory; /* library's memory manager */ + + FT_Generic generic; + + FT_UInt num_modules; + FT_Module modules[FT_MAX_MODULES]; /* module objects */ + + FT_ListRec renderers; /* list of renderers */ + FT_Renderer cur_renderer; /* current outline renderer */ + FT_Module auto_hinter; + + FT_Byte* raster_pool; /* scan-line conversion */ + /* render pool */ + FT_ULong raster_pool_size; /* size of render pool in bytes */ + + FT_DebugHook_Func debug_hooks[4]; + + } FT_LibraryRec; + + + BASE_DEF( FT_Renderer ) FT_Lookup_Renderer( FT_Library library, + FT_Glyph_Format format, + FT_ListNode* node ); + + BASE_DEF( FT_Error ) FT_Render_Glyph_Internal( FT_Library library, + FT_GlyphSlot slot, + FT_UInt render_mode ); + + typedef FT_Error (*FT_Glyph_Name_Requester)( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ); + + +#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM + + + FT_EXPORT_DEF( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream astream ); + + FT_EXPORT_DEF( void ) FT_Done_Stream( FT_Stream stream ); + + FT_EXPORT_DEF( FT_Memory ) FT_New_Memory( void ); + + +#endif /* !FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM */ + + + /* Define default raster's interface. The default raster is located in */ + /* `src/base/ftraster.c' */ + /* */ + /* Client applications can register new rasters through the */ + /* FT_Set_Raster() API. */ + +#ifndef FT_NO_DEFAULT_RASTER + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_default_raster; +#endif + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTOBJS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/ftstream.h b/subsys/win32k/freetype/include/freetype/internal/ftstream.h new file mode 100644 index 0000000..365f479 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/ftstream.h @@ -0,0 +1,361 @@ +/***************************************************************************/ +/* */ +/* ftstream.h */ +/* */ +/* Stream handling(specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTSTREAM_H +#define FTSTREAM_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* format of an 8-bit frame_op value = [ xxxxx | e | s ] */ + /* s is set to 1 if the value is signed, */ + /* e is set to 1 if the value is little-endian */ + /* xxxxx is a command */ + +#define FT_FRAME_OP_SHIFT 2 +#define FT_FRAME_OP_SIGNED 1 +#define FT_FRAME_OP_LITTLE 2 +#define FT_FRAME_OP_COMMAND( x ) ( x >> FT_FRAME_OP_SHIFT ) + +#define FT_MAKE_FRAME_OP( command, little, sign ) \ + ( ( command << FT_FRAME_OP_SHIFT ) | ( little << 1 ) | sign ) + +#define FT_FRAME_OP_END 0 +#define FT_FRAME_OP_START 1 /* start a new frame */ +#define FT_FRAME_OP_BYTE 2 /* read 1-byte value */ +#define FT_FRAME_OP_SHORT 3 /* read 2-byte value */ +#define FT_FRAME_OP_LONG 4 /* read 4-byte value */ +#define FT_FRAME_OP_OFF3 5 /* read 3-byte value */ +#define FT_FRAME_OP_BYTES 6 /* read a bytes sequence */ + + + typedef enum FT_Frame_Op_ + { + ft_frame_end = 0, + ft_frame_start = FT_MAKE_FRAME_OP( FT_FRAME_OP_START, 0, 0 ), + + ft_frame_byte = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 0 ), + ft_frame_schar = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTE, 0, 1 ), + + ft_frame_ushort_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 0 ), + ft_frame_short_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 0, 1 ), + ft_frame_ushort_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 0 ), + ft_frame_short_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_SHORT, 1, 1 ), + + ft_frame_ulong_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 0 ), + ft_frame_ulong_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 0, 1 ), + ft_frame_long_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 0 ), + ft_frame_long_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_LONG, 1, 1 ), + + ft_frame_uoff3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 0 ), + ft_frame_uoff3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 0, 1 ), + ft_frame_off3_be = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 0 ), + ft_frame_off3_le = FT_MAKE_FRAME_OP( FT_FRAME_OP_OFF3, 1, 1 ), + + ft_frame_bytes = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 0 ), + ft_frame_skip = FT_MAKE_FRAME_OP( FT_FRAME_OP_BYTES, 0, 1 ) + + } FT_Frame_Op; + + + typedef struct FT_Frame_Field_ + { + FT_Frame_Op value; + char size; + FT_UShort offset; + + } FT_Frame_Field; + + + /* make-up a FT_Frame_Field out of a structure type and a field name */ +#define FT_FIELD_REF( s, f ) (((s*)0)->f) + +#define FT_FRAME_FIELD( frame_op, struct_type, field ) \ + { \ + frame_op, \ + sizeof ( FT_FIELD_REF( struct_type,field ) ), \ + (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \ + } + +#define FT_MAKE_EMPTY_FIELD( frame_op ) { frame_op, 0, 0 } + +#define FT_FRAME_START( s ) { ft_frame_start, 0, s } +#define FT_FRAME_END { ft_frame_end, 0, 0 } + +#define FT_FRAME_LONG( s, f ) FT_FRAME_FIELD( ft_frame_long_be, s, f ) +#define FT_FRAME_ULONG( s, f ) FT_FRAME_FIELD( ft_frame_ulong_be, s, f ) +#define FT_FRAME_SHORT( s, f ) FT_FRAME_FIELD( ft_frame_short_be, s, f ) +#define FT_FRAME_USHORT( s, f ) FT_FRAME_FIELD( ft_frame_ushort_be, s, f ) +#define FT_FRAME_BYTE( s, f ) FT_FRAME_FIELD( ft_frame_byte, s, f ) +#define FT_FRAME_CHAR( s, f ) FT_FRAME_FIELD( ft_frame_schar, s, f ) + +#define FT_FRAME_LONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_long_le, s, f ) +#define FT_FRAME_ULONG_LE( s, f ) FT_FRAME_FIELD( ft_frame_ulong_le, s, f ) +#define FT_FRAME_SHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_short_le, s, f ) +#define FT_FRAME_USHORT_LE( s, f ) FT_FRAME_FIELD( ft_frame_ushort_le, s, f ) + +#define FT_FRAME_SKIP_LONG { ft_frame_long_be, 0, 0 } +#define FT_FRAME_SKIP_SHORT { ft_frame_short_be, 0, 0 } +#define FT_FRAME_SKIP_BYTE { ft_frame_byte, 0, 0 } + +#define FT_FRAME_BYTES( struct_type, field, count ) \ + { \ + ft_frame_bytes, \ + count, \ + (FT_UShort)(char*)&FT_FIELD_REF( struct_type, field ) \ + } +#define FT_FRAME_SKIP_BYTES( count ) { ft_frame_skip, count, 0 } + + + + /*************************************************************************/ + /* */ + /* integer extraction macros -- the `buffer' parameter must ALWAYS be of */ + /* type `char*' or equivalent (1-byte elements). */ + /* */ +#define NEXT_Char( buffer ) \ + ( (signed char)*buffer++ ) +#define NEXT_Byte( buffer ) \ + ( (unsigned char)*buffer++ ) + +#define NEXT_Short( buffer ) \ + ( buffer += 2, \ + ( (short)( (signed char)buffer[-2] << 8 ) | \ + (unsigned char)buffer[-1] ) ) + +#define NEXT_UShort( buffer ) \ + ( (unsigned short)NEXT_Short( buffer ) ) + +#define NEXT_Offset( buffer ) \ + ( buffer += 3, \ + ( ( (long)(signed char)buffer[-3] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-1] ) ) + +#define NEXT_UOffset( buffer ) \ + ( (unsigned long)NEXT_Offset( buffer ) ) + +#define NEXT_Long( buffer ) \ + ( buffer += 4, \ + ( ( (long)(signed char)buffer[-4] << 24 ) | \ + ( (long)(unsigned char)buffer[-3] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-1] ) ) + +#define NEXT_ULong( buffer ) \ + ( (unsigned long)NEXT_Long( buffer ) ) + + +#define NEXT_ShortLE( buffer ) \ + ( buffer += 2, \ + ( (short)( (signed char)buffer[-1] << 8 ) | \ + (unsigned char)buffer[-2] ) ) + +#define NEXT_UShortLE( buffer ) \ + ( (unsigned short)NEXT_ShortLE( buffer ) ) + +#define NEXT_OffsetLE( buffer ) \ + ( buffer += 3, \ + ( ( (long)(signed char)buffer[-1] << 16 ) | \ + ( (long)(unsigned char)buffer[-2] << 8 ) | \ + (long)(unsigned char)buffer[-3] ) ) + +#define NEXT_UOffsetLE( buffer ) \ + ( (unsigned long)NEXT_OffsetLE( buffer ) ) + + +#define NEXT_LongLE( buffer ) \ + ( buffer += 4, \ + ( ( (long)(signed char)buffer[-1] << 24 ) | \ + ( (long)(unsigned char)buffer[-2] << 16 ) | \ + ( (long)(unsigned char)buffer[-3] << 8 ) | \ + (long)(unsigned char)buffer[-4] ) ) + +#define NEXT_ULongLE( buffer ) \ + ( (unsigned long)NEXT_LongLE( buffer ) ) + + + /*************************************************************************/ + /* */ + /* Each GET_xxxx() macro uses an implicit `stream' variable. */ + /* */ +#define FT_GET_MACRO( func, type ) ( (type)func( stream ) ) + +#define GET_Char() FT_GET_MACRO( FT_Get_Char, FT_Char ) +#define GET_Byte() FT_GET_MACRO( FT_Get_Char, FT_Byte ) +#define GET_Short() FT_GET_MACRO( FT_Get_Short, FT_Short ) +#define GET_UShort() FT_GET_MACRO( FT_Get_Short, FT_UShort ) +#define GET_Offset() FT_GET_MACRO( FT_Get_Offset, FT_Long ) +#define GET_UOffset() FT_GET_MACRO( FT_Get_Offset, FT_ULong ) +#define GET_Long() FT_GET_MACRO( FT_Get_Long, FT_Long ) +#define GET_ULong() FT_GET_MACRO( FT_Get_Long, FT_ULong ) +#define GET_Tag4() FT_GET_MACRO( FT_Get_Long, FT_ULong ) + +#define GET_ShortLE() FT_GET_MACRO( FT_Get_ShortLE, FT_Short ) +#define GET_UShortLE() FT_GET_MACRO( FT_Get_ShortLE, FT_UShort ) +#define GET_LongLE() FT_GET_MACRO( FT_Get_LongLE, FT_Short ) +#define GET_ULongLE() FT_GET_MACRO( FT_Get_LongLE, FT_Short ) + +#define FT_READ_MACRO( func, type, var ) \ + ( var = (type)func( stream, &error ), \ + error != FT_Err_Ok ) + +#define READ_Byte( var ) FT_READ_MACRO( FT_Read_Char, FT_Byte, var ) +#define READ_Char( var ) FT_READ_MACRO( FT_Read_Char, FT_Char, var ) +#define READ_Short( var ) FT_READ_MACRO( FT_Read_Short, FT_Short, var ) +#define READ_UShort( var ) FT_READ_MACRO( FT_Read_Short, FT_UShort, var ) +#define READ_Offset( var ) FT_READ_MACRO( FT_Read_Offset, FT_Long, var ) +#define READ_UOffset( var ) FT_READ_MACRO( FT_Read_Offset, FT_ULong, var ) +#define READ_Long( var ) FT_READ_MACRO( FT_Read_Long, FT_Long, var ) +#define READ_ULong( var ) FT_READ_MACRO( FT_Read_Long, FT_ULong, var ) + +#define READ_ShortLE( var ) FT_READ_MACRO( FT_Read_ShortLE, FT_Short, var ) +#define READ_UShortLE( var ) FT_READ_MACRO( FT_Read_ShortLE, FT_UShort, var ) +#define READ_LongLE( var ) FT_READ_MACRO( FT_Read_LongLE, FT_Long, var ) +#define READ_ULongLE( var ) FT_READ_MACRO( FT_Read_LongLE, FT_ULong, var ) + + + BASE_DEF( void ) FT_New_Memory_Stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream stream ); + + BASE_DEF( FT_Error ) FT_Seek_Stream( FT_Stream stream, + FT_ULong pos ); + + BASE_DEF( FT_Error ) FT_Skip_Stream( FT_Stream stream, + FT_Long distance ); + + BASE_DEF( FT_Long ) FT_Stream_Pos( FT_Stream stream ); + + + BASE_DEF( FT_Error ) FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ); + + BASE_DEF( FT_Error ) FT_Read_Stream_At( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ); + + BASE_DEF( FT_Error ) FT_Access_Frame( FT_Stream stream, + FT_ULong count ); + + BASE_DEF( void ) FT_Forget_Frame( FT_Stream stream ); + + BASE_DEF( FT_Error ) FT_Extract_Frame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ); + + BASE_DEF( void ) FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ); + + BASE_DEF( FT_Char ) FT_Get_Char( FT_Stream stream ); + + BASE_DEF( FT_Short ) FT_Get_Short( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_Offset( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_Long( FT_Stream stream ); + + BASE_DEF( FT_Short ) FT_Get_ShortLE( FT_Stream stream ); + + BASE_DEF( FT_Long ) FT_Get_LongLE( FT_Stream stream ); + + + BASE_DEF( FT_Char ) FT_Read_Char( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Short ) FT_Read_Short( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_Offset( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_Long( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Short ) FT_Read_ShortLE( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Long ) FT_Read_LongLE( FT_Stream stream, + FT_Error* error ); + + BASE_DEF( FT_Error ) FT_Read_Fields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ); + + +#define USE_Stream( resource, stream ) \ + FT_SET_ERROR( FT_Open_Stream( resource, stream ) ) + +#define DONE_Stream( stream ) \ + FT_Done_Stream( stream ) + + +#define ACCESS_Frame( size ) \ + FT_SET_ERROR( FT_Access_Frame( stream, size ) ) + +#define FORGET_Frame() \ + FT_Forget_Frame( stream ) + +#define EXTRACT_Frame( size, bytes ) \ + FT_SET_ERROR( FT_Extract_Frame( stream, size, \ + (FT_Byte**)&(bytes) ) ) + +#define RELEASE_Frame( bytes ) \ + FT_Release_Frame( stream, (FT_Byte**)&(bytes) ) + +#define FILE_Seek( position ) \ + FT_SET_ERROR( FT_Seek_Stream( stream, position ) ) + +#define FILE_Skip( distance ) \ + FT_SET_ERROR( FT_Skip_Stream( stream, distance ) ) + +#define FILE_Pos() \ + FT_Stream_Pos( stream ) + +#define FILE_Read( buffer, count ) \ + FT_SET_ERROR( FT_Read_Stream( stream, \ + (FT_Byte*)buffer, \ + count ) ) + +#define FILE_Read_At( position, buffer, count ) \ + FT_SET_ERROR( FT_Read_Stream_At( stream, \ + position, \ + (FT_Byte*)buffer, \ + count ) ) + +#define READ_Fields( fields, object ) \ + ( ( error = FT_Read_Fields( stream, fields, object ) ) != FT_Err_Ok ) + + +#ifdef __cplusplus + } +#endif + + +#endif /* FTSTREAM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/psnames.h b/subsys/win32k/freetype/include/freetype/internal/psnames.h new file mode 100644 index 0000000..ed86235 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/psnames.h @@ -0,0 +1,220 @@ +/***************************************************************************/ +/* */ +/* psnames.h */ +/* */ +/* High-level interface for the `PSNames' module (in charge of */ +/* various functions related to Postscript glyph names conversion). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef PSNAMES_H +#define PSNAMES_H + + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicode_Value_Func */ + /* */ + /* */ + /* A function used to return the Unicode index corresponding to a */ + /* given glyph name. */ + /* */ + /* */ + /* glyph_name :: The glyph name. */ + /* */ + /* */ + /* The Unicode character index resp. the non-Unicode value 0xFFFF if */ + /* the glyph name has no known Unicode meaning. */ + /* */ + /* */ + /* This function is able to map several different glyph names to the */ + /* same Unicode value, according to the rules defined in the Adobe */ + /* Glyph List table. */ + /* */ + /* This function will not be compiled if the configuration macro */ + /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined. */ + /* */ + typedef FT_ULong (*PS_Unicode_Value_Func)( const char* glyph_name ); + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicode_Index_Func */ + /* */ + /* */ + /* A function used to return the glyph index corresponding to a given */ + /* Unicode value. */ + /* */ + /* */ + /* num_glyphs :: The number of glyphs in the face. */ + /* */ + /* glyph_names :: An array of glyph name pointers. */ + /* */ + /* unicode :: The Unicode value. */ + /* */ + /* */ + /* The glyph index resp. 0xFFFF if no glyph corresponds to this */ + /* Unicode value. */ + /* */ + /* */ + /* This function is able to recognize several glyph names per Unicode */ + /* value, according to the Adobe Glyph List. */ + /* */ + /* This function will not be compiled if the configuration macro */ + /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is undefined. */ + /* */ + typedef FT_UInt (*PS_Unicode_Index_Func)( FT_UInt num_glyphs, + const char** glyph_names, + FT_ULong unicode ); + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Macintosh_Name_Func */ + /* */ + /* */ + /* A function used to return the glyph name corresponding to an Apple */ + /* glyph name index. */ + /* */ + /* */ + /* name_index :: The index of the Mac name. */ + /* */ + /* */ + /* The glyph name, or 0 if the index is invalid. */ + /* */ + /* */ + /* This function will not be compiled if the configuration macro */ + /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined. */ + /* */ + typedef const char* (*PS_Macintosh_Name_Func)( FT_UInt name_index ); + + + typedef const char* (*PS_Adobe_Std_Strings_Func)( FT_UInt string_index ); + + + typedef struct PS_UniMap_ + { + FT_UInt unicode; + FT_UInt glyph_index; + + } PS_UniMap; + + + /*************************************************************************/ + /* */ + /* */ + /* PS_Unicodes */ + /* */ + /* */ + /* A simple table used to map Unicode values to glyph indices. It is */ + /* built by the PS_Build_Unicodes table according to the glyphs */ + /* present in a font file. */ + /* */ + /* */ + /* num_codes :: The number of glyphs in the font that match a given */ + /* Unicode value. */ + /* */ + /* unicodes :: An array of unicode values, sorted in increasing */ + /* order. */ + /* */ + /* gindex :: An array of glyph indices, corresponding to each */ + /* Unicode value. */ + /* */ + /* */ + /* Use the function PS_Lookup_Unicode() to retrieve the glyph index */ + /* corresponding to a given Unicode character code. */ + /* */ + typedef struct PS_Unicodes_ + { + FT_UInt num_maps; + PS_UniMap* maps; + + } PS_Unicodes; + + + typedef FT_Error (*PS_Build_Unicodes_Func)( FT_Memory memory, + FT_UInt num_glyphs, + const char** glyph_names, + PS_Unicodes* unicodes ); + + typedef FT_UInt (*PS_Lookup_Unicode_Func)( PS_Unicodes* unicodes, + FT_UInt unicode ); + + + /*************************************************************************/ + /* */ + /* */ + /* PSNames_Interface */ + /* */ + /* */ + /* This structure defines the PSNames interface. */ + /* */ + /* */ + /* unicode_value :: A function used to convert a glyph name */ + /* into a Unicode character code. */ + /* */ + /* build_unicodes :: A function which builds up the Unicode */ + /* mapping table. */ + /* */ + /* lookup_unicode :: A function used to return the glyph index */ + /* corresponding to a given Unicode */ + /* character. */ + /* */ + /* macintosh_name :: A function used to return the standard */ + /* Apple glyph Postscript name corresponding */ + /* to a given string index (used by the */ + /* TrueType `post' table). */ + /* */ + /* adobe_std_strings :: A function that returns a pointer to a */ + /* Adobe Standard String for a given SID. */ + /* */ + /* adobe_std_encoding :: A table of 256 unsigned shorts that maps */ + /* character codes in the Adobe Standard */ + /* Encoding to SIDs. */ + /* */ + /* adobe_expert_encoding :: A table of 256 unsigned shorts that maps */ + /* character codes in the Adobe Expert */ + /* Encoding to SIDs. */ + /* */ + /* */ + /* `unicode_value' and `unicode_index' will be set to 0 if the */ + /* configuration macro FT_CONFIG_OPTION_ADOBE_GLYPH_LIST is */ + /* undefined. */ + /* */ + /* `macintosh_name' will be set to 0 if the configuration macro */ + /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES is undefined. */ + /* */ + typedef struct PSNames_Interface_ + { + PS_Unicode_Value_Func unicode_value; + PS_Build_Unicodes_Func build_unicodes; + PS_Lookup_Unicode_Func lookup_unicode; + PS_Macintosh_Name_Func macintosh_name; + + PS_Adobe_Std_Strings_Func adobe_std_strings; + const unsigned short* adobe_std_encoding; + const unsigned short* adobe_expert_encoding; + + } PSNames_Interface; + + +#endif /* PSNAMES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/sfnt.h b/subsys/win32k/freetype/include/freetype/internal/sfnt.h new file mode 100644 index 0000000..380ee93 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/sfnt.h @@ -0,0 +1,492 @@ +/***************************************************************************/ +/* */ +/* sfnt.h */ +/* */ +/* High-level `sfnt' driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef SFNT_H +#define SFNT_H + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face_Func */ + /* */ + /* */ + /* First part of the SFNT face object initialization. This will find */ + /* the face in a SFNT file or collection, and load its format tag in */ + /* face->format_tag. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* params :: Optional additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType */ + /* collection'. */ + /* */ + /* Once the format tag has been validated by the font driver, it */ + /* should then call the TT_Load_Face_Func() callback to read the rest */ + /* of the SFNT tables in the object. */ + /* */ + typedef + FT_Error (*TT_Init_Face_Func)( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Face_Func */ + /* */ + /* */ + /* Second part of the SFNT face object initialization. This will */ + /* load the common SFNT tables (head, OS/2, maxp, metrics, etc.) in */ + /* the face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* params :: Optional additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function must be called after TT_Init_Face_Func(). */ + /* */ + typedef + FT_Error (*TT_Load_Face_Func)( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face_Func */ + /* */ + /* */ + /* A callback used to delete the common SFNT data from a face. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* This function does NOT destroy the face object. */ + /* */ + typedef + void (*TT_Done_Face_Func)( TT_Face face ); + + + typedef + FT_Module_Interface (*SFNT_Get_Interface_Func)( FT_Module module, + const char* interface ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SFNT_Header_Func */ + /* */ + /* */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* face_index :: The index of the TrueType font, if we are opening a */ + /* collection. */ + /* */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType */ + /* collection'. */ + /* */ + /* This function checks that the header is valid by looking at the */ + /* values of `search_range', `entry_selector', and `range_shift'. */ + /* */ + typedef + FT_Error (*TT_Load_SFNT_Header_Func)( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header* sfnt ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory_Func */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be on the first byte after the 4-byte font */ + /* format tag. This is the case just after a call to */ + /* TT_Load_Format_Tag(). */ + /* */ + typedef + FT_Error (*TT_Load_Directory_Func)( TT_Face face, + FT_Stream stream, + SFNT_Header* sfnt ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any_Func */ + /* */ + /* */ + /* Loads any font table into client memory. */ + /* */ + /* */ + /* face :: The face object to look for. */ + /* */ + /* tag :: The tag of table to load. Use the value 0 if you want */ + /* to access the whole font file, else set this parameter */ + /* to a valid TrueType table tag that you can forge with */ + /* the MAKE_TT_TAG macro. */ + /* */ + /* offset :: The starting offset in the table (or the file if */ + /* tag == 0). */ + /* */ + /* length :: The address of the decision variable: */ + /* */ + /* If length == NULL: */ + /* Loads the whole table. Returns an error if */ + /* `offset' == 0! */ + /* */ + /* If *length == 0: */ + /* Exits immediately; returning the length of the given */ + /* table or of the font file, depending on the value of */ + /* `tag'. */ + /* */ + /* If *length != 0: */ + /* Loads the next `length' bytes of table or font, */ + /* starting at offset `offset' (in table or font too). */ + /* */ + /* */ + /* buffer :: The address of target buffer. */ + /* */ + /* */ + /* TrueType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Any_Func)( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Image_Func */ + /* */ + /* */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* glyph_index :: The current glyph index. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + typedef + FT_Error (*TT_Load_SBit_Image_Func)( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name_Func */ + /* */ + /* */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* */ + /* index :: The glyph index. */ + /* */ + /* PSname :: The address of a string pointer. Will be NULL in case */ + /* of error, otherwise it is a pointer to the glyph name. */ + /* */ + /* You must not modify the returned string! */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Get_PS_Name_Func)( TT_Face face, + FT_UInt index, + FT_String** PSname ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics_Func */ + /* */ + /* */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Metrics_Func)( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Load_Func */ + /* */ + /* */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* stream :: A handle to the current stream object. */ + /* */ + /* */ + /* cmap :: A pointer to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function assumes that the stream is already in use (i.e., */ + /* opened). In case of error, all partially allocated tables are */ + /* released. */ + /* */ + typedef + FT_Error (*TT_CharMap_Load_Func)( TT_Face face, + TT_CMapTable* cmap, + FT_Stream input ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free_Func */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_CharMap_Free_Func)( TT_Face face, + TT_CMapTable* cmap ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Table_Func */ + /* */ + /* */ + /* Loads a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function will use `face->goto_table' to seek the stream to */ + /* the start of the table. */ + /* */ + typedef + FT_Error (*TT_Load_Table_Func)( TT_Face face, + FT_Stream stream ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Table_Func */ + /* */ + /* */ + /* Frees a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + typedef + void (*TT_Free_Table_Func)( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* */ + /* SFNT_Interface */ + /* */ + /* */ + /* This structure holds pointers to the functions used to load and */ + /* free the basic tables that are required in a `sfnt' font file. */ + /* */ + /* */ + /* Check the various xxx_Func() descriptions for details. */ + /* */ + typedef struct SFNT_Interface_ + { + TT_Goto_Table_Func goto_table; + + TT_Init_Face_Func init_face; + TT_Load_Face_Func load_face; + TT_Done_Face_Func done_face; + SFNT_Get_Interface_Func get_interface; + + TT_Load_Any_Func load_any; + TT_Load_SFNT_Header_Func load_sfnt_header; + TT_Load_Directory_Func load_directory; + + /* these functions are called by `load_face' but they can also */ + /* be called from external modules, if there is a need to do so */ + TT_Load_Table_Func load_header; + TT_Load_Metrics_Func load_metrics; + TT_Load_Table_Func load_charmaps; + TT_Load_Table_Func load_max_profile; + TT_Load_Table_Func load_os2; + TT_Load_Table_Func load_psnames; + + TT_Load_Table_Func load_names; + TT_Free_Table_Func free_names; + + /* optional tables */ + TT_Load_Table_Func load_hdmx; + TT_Free_Table_Func free_hdmx; + + TT_Load_Table_Func load_kerning; + TT_Load_Table_Func load_gasp; + TT_Load_Table_Func load_pclt; + + /* see `ttsbit.h' */ + TT_Load_Table_Func load_sbits; + TT_Load_SBit_Image_Func load_sbit_image; + TT_Free_Table_Func free_sbits; + + /* see `ttpost.h' */ + TT_Get_PS_Name_Func get_psname; + TT_Free_Table_Func free_psnames; + + /* see `ttcmap.h' */ + TT_CharMap_Load_Func load_charmap; + TT_CharMap_Free_Func free_charmap; + + } SFNT_Interface; + + +#endif /* SFNT_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/t1errors.h b/subsys/win32k/freetype/include/freetype/internal/t1errors.h new file mode 100644 index 0000000..58566d8 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/t1errors.h @@ -0,0 +1,67 @@ +/***************************************************************************/ +/* */ +/* t1errors.h */ +/* */ +/* Type 1 error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1ERRORS_H +#define T1ERRORS_H + + + /************************ error codes declaration **************/ + + /* The error codes are grouped into `classes' used to indicate the */ + /* `level' at which the error happened. */ + /* */ + /* The class is given by an error code's high byte. */ + + + /* ------------- Success is always 0 -------- */ + +#define T1_Err_Ok FT_Err_Ok + + /* ----------- high level API errors -------- */ + +#define T1_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define T1_Err_Invalid_Argument FT_Err_Invalid_Argument +#define T1_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define T1_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define T1_Err_Invalid_Size_Handle FT_Err_Invalid_Size_Handle +#define T1_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define T1_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define T1_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define T1_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define T1_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* ------------- internal errors ------------ */ + +#define T1_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define T1_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* ------------ general glyph outline errors ------ */ + +#define T1_Err_Invalid_Composite FT_Err_Invalid_Composite + +#define T1_Err_Syntax_Error FT_Err_Invalid_File_Format +#define T1_Err_Stack_Underflow FT_Err_Invalid_File_Format +#define T1_Err_Stack_Overflow FT_Err_Invalid_File_Format + + +#endif /* T1ERRORS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/t1types.h b/subsys/win32k/freetype/include/freetype/internal/t1types.h new file mode 100644 index 0000000..4d41a6b --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/t1types.h @@ -0,0 +1,188 @@ +/***************************************************************************/ +/* */ +/* t1types.h */ +/* */ +/* Basic Type1/Type2 type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1TYPES_H +#define T1TYPES_H + + +#include +#include + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TYPE1/TYPE2 TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Encoding */ + /* */ + /* */ + /* A structure modeling a custom encoding */ + /* */ + /* */ + /* num_chars :: The number of character codes in the encoding. */ + /* Usually 256. */ + /* */ + /* code_first :: The lowest valid character code in the encoding. */ + /* */ + /* code_last :: The highest valid character code in the encoding. */ + /* */ + /* char_index :: An array of corresponding glyph indices. */ + /* */ + /* char_name :: An array of corresponding glyph names. */ + /* */ + typedef struct T1_Encoding_ + { + FT_Int num_chars; + FT_Int code_first; + FT_Int code_last; + + FT_UShort* char_index; + FT_String** char_name; + + } T1_Encoding; + + + typedef enum T1_EncodingType_ + { + t1_encoding_none = 0, + t1_encoding_array, + t1_encoding_standard, + t1_encoding_expert + + } T1_EncodingType; + + + typedef struct T1_Font_ + { + + /* font info dictionary */ + T1_FontInfo font_info; + + /* private dictionary */ + T1_Private private_dict; + + /* top-level dictionary */ + FT_String* font_name; + + T1_EncodingType encoding_type; + T1_Encoding encoding; + + FT_Byte* subrs_block; + FT_Byte* charstrings_block; + FT_Byte* glyph_names_block; + + FT_Int num_subrs; + FT_Byte** subrs; + FT_Int* subrs_len; + + FT_Int num_glyphs; + FT_String** glyph_names; /* array of glyph names */ + FT_Byte** charstrings; /* array of glyph charstrings */ + FT_Int* charstrings_len; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + FT_BBox font_bbox; + FT_Long font_id; + + FT_Int stroke_width; + + } T1_Font; + + + typedef struct CID_Subrs_ + { + FT_UInt num_subrs; + FT_Byte** code; + + } CID_Subrs; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** ORIGINAL T1_FACE CLASS DEFINITION ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This structure/class is defined here because it is common to the */ + /* following formats: TTF, OpenType-TT, and OpenType-CFF. */ + /* */ + /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */ + /* are not shared between font drivers, and are thus defined normally in */ + /* `ttobjs.h'. */ + /* */ + /*************************************************************************/ + + typedef struct T1_FaceRec_* T1_Face; + typedef struct CID_FaceRec_* CID_Face; + + + typedef struct T1_FaceRec_ + { + FT_FaceRec root; + T1_Font type1; + void* psnames; + void* afm_data; + FT_CharMapRec charmaprecs[2]; + FT_CharMap charmaps[2]; + PS_Unicodes unicode_map; + + /* support for Multiple Masters fonts */ + T1_Blend* blend; + + } T1_FaceRec; + + + typedef struct CID_FaceRec_ + { + FT_FaceRec root; + void* psnames; + CID_Info cid; + void* afm_data; + CID_Subrs* subrs; + + } CID_FaceRec; + + +#endif /* T1TYPES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/t2errors.h b/subsys/win32k/freetype/include/freetype/internal/t2errors.h new file mode 100644 index 0000000..d685220 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/t2errors.h @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* t2errors.h */ +/* */ +/* OpenType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2ERRORS_H +#define T2ERRORS_H + + + /*************************************************************************/ + /* */ + /* Error codes declaration */ + /* */ + /* The error codes are grouped in `classes' used to indicate the `level' */ + /* at which the error happened. The class is given by an error code's */ + /* high byte. */ + /* */ + /*************************************************************************/ + + + /* Success is always 0. */ + +#define T2_Err_Ok FT_Err_Ok + + /* High level API errors. */ + +#define T2_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define T2_Err_Invalid_Argument FT_Err_Invalid_Argument +#define T2_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define T2_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define T2_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle +#define T2_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define T2_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define T2_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define T2_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define T2_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* Internal errors. */ + +#define T2_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define T2_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* General glyph outline errors. */ + +#define T2_Err_Invalid_Composite FT_Err_Invalid_Composite + + /* Bytecode interpreter error codes. */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define T2_Err_Invalid_Opcode 0x500 +#define T2_Err_Too_Few_Arguments 0x501 +#define T2_Err_Stack_Overflow 0x502 +#define T2_Err_Code_Overflow 0x503 +#define T2_Err_Bad_Argument 0x504 +#define T2_Err_Divide_By_Zero 0x505 +#define T2_Err_Storage_Overflow 0x506 +#define T2_Err_Cvt_Overflow 0x507 +#define T2_Err_Invalid_Reference 0x508 +#define T2_Err_Invalid_Distance 0x509 +#define T2_Err_Interpolate_Twilight 0x50A +#define T2_Err_Debug_OpCode 0x50B +#define T2_Err_ENDF_In_Exec_Stream 0x50C +#define T2_Err_Out_Of_CodeRanges 0x50D +#define T2_Err_Nested_DEFS 0x50E +#define T2_Err_Invalid_CodeRange 0x50F +#define T2_Err_Invalid_Displacement 0x510 +#define T2_Err_Execution_Too_Long 0x511 + +#define T2_Err_Too_Many_Instruction_Defs 0x512 +#define T2_Err_Too_Many_Function_Defs 0x513 + + /* Other TrueType specific error codes. */ + +#define T2_Err_Table_Missing 0x520 +#define T2_Err_Too_Many_Extensions 0x521 +#define T2_Err_Extensions_Unsupported 0x522 +#define T2_Err_Invalid_Extension_Id 0x523 + +#define T2_Err_No_Vertical_Data 0x524 + +#define T2_Err_Max_Profile_Missing 0x530 +#define T2_Err_Header_Table_Missing 0x531 +#define T2_Err_Horiz_Header_Missing 0x532 +#define T2_Err_Locations_Missing 0x533 +#define T2_Err_Name_Table_Missing 0x534 +#define T2_Err_CMap_Table_Missing 0x535 +#define T2_Err_Hmtx_Table_Missing 0x536 +#define T2_Err_OS2_Table_Missing 0x537 +#define T2_Err_Post_Table_Missing 0x538 + +#define T2_Err_Invalid_Horiz_Metrics 0x540 +#define T2_Err_Invalid_CharMap_Format 0x541 +#define T2_Err_Invalid_PPem 0x542 +#define T2_Err_Invalid_Vert_Metrics 0x543 + +#define T2_Err_Could_Not_Find_Context 0x550 + + +#endif /* T2ERRORS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/t2types.h b/subsys/win32k/freetype/include/freetype/internal/t2types.h new file mode 100644 index 0000000..033f315 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/t2types.h @@ -0,0 +1,218 @@ +/***************************************************************************/ +/* */ +/* t2types.h */ +/* */ +/* Basic OpenType/CFF type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2TYPES_H +#define T2TYPES_H + + +#include + + + /*************************************************************************/ + /* */ + /* */ + /* CFF_Index */ + /* */ + /* */ + /* A structure used to model a CFF Index table. */ + /* */ + /* */ + /* stream :: XXX */ + /* */ + /* count :: The number of elements in the index. */ + /* */ + /* off_size :: The size in bytes of object offsets in index. */ + /* */ + /* data_offset :: The position of first data byte in the index's */ + /* bytes. */ + /* */ + /* offsets :: XXX */ + /* */ + /* bytes :: If the index is loaded in memory, its bytes. */ + /* */ + typedef struct CFF_Index_ + { + FT_Stream stream; + FT_UInt count; + FT_Byte off_size; + FT_ULong data_offset; + + FT_ULong* offsets; + FT_Byte* bytes; + + } CFF_Index; + + + typedef struct CFF_Font_Dict_ + { + FT_UInt version; + FT_UInt notice; + FT_UInt copyright; + FT_UInt full_name; + FT_UInt family_name; + FT_UInt weight; + FT_Bool is_fixed_pitch; + FT_Fixed italic_angle; + FT_Pos underline_position; + FT_Pos underline_thickness; + FT_Int paint_type; + FT_Int charstring_type; + FT_Matrix font_matrix; + FT_ULong unique_id; + FT_BBox font_bbox; + FT_Pos stroke_width; + FT_ULong charset_offset; + FT_ULong encoding_offset; + FT_ULong charstrings_offset; + FT_ULong private_offset; + FT_ULong private_size; + FT_Long synthetic_base; + FT_UInt embedded_postscript; + FT_UInt base_font_name; + FT_UInt postscript; + + /* these should only be used for the top-level font dictionary */ + FT_UInt cid_registry; + FT_UInt cid_ordering; + FT_ULong cid_supplement; + + FT_Long cid_font_version; + FT_Long cid_font_revision; + FT_Long cid_font_type; + FT_Long cid_count; + FT_ULong cid_uid_base; + FT_ULong cid_fd_array_offset; + FT_ULong cid_fd_select_offset; + FT_UInt cid_font_name; + + } CFF_Font_Dict; + + + typedef struct CFF_Private_ + { + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Pos blue_values[14]; + FT_Pos other_blues[10]; + FT_Pos family_blues[14]; + FT_Pos family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Pos blue_shift; + FT_Pos blue_fuzz; + FT_Pos standard_width; + FT_Pos standard_height; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Pos snap_widths[13]; + FT_Pos snap_heights[13]; + FT_Bool force_bold; + FT_Fixed force_bold_threshold; + FT_Int lenIV; + FT_Int language_group; + FT_Fixed expansion_factor; + FT_Long initial_random_seed; + FT_ULong local_subrs_offset; + FT_Pos default_width; + FT_Pos nominal_width; + + } CFF_Private; + + + typedef struct CFF_FD_Select_ + { + FT_Byte format; + FT_UInt range_count; + + /* that's the table, taken from the file `as is' */ + FT_Byte* data; + FT_UInt data_size; + + /* small cache for format 3 only */ + FT_UInt cache_first; + FT_UInt cache_count; + FT_Byte cache_fd; + + } CFF_FD_Select; + + + /* A SubFont packs a font dict and a private dict together. They are */ + /* needed to support CID-keyed CFF fonts. */ + typedef struct CFF_SubFont_ + { + CFF_Font_Dict font_dict; + CFF_Private private_dict; + + CFF_Index local_subrs_index; + FT_UInt num_local_subrs; + FT_Byte** local_subrs; + + } CFF_SubFont; + + + /* maximum number of sub-fonts in a CID-keyed file */ +#define CFF_MAX_CID_FONTS 16 + + + typedef struct CFF_Font_ + { + FT_Stream stream; + FT_Memory memory; + FT_UInt num_faces; + FT_UInt num_glyphs; + + FT_Byte version_major; + FT_Byte version_minor; + FT_Byte header_size; + FT_Byte absolute_offsize; + + + CFF_Index name_index; + CFF_Index top_dict_index; + CFF_Index string_index; + CFF_Index global_subrs_index; + + /* we don't load the Encoding and CharSet tables */ + + CFF_Index charstrings_index; + CFF_Index font_dict_index; + CFF_Index private_index; + CFF_Index local_subrs_index; + + FT_String* font_name; + FT_UInt num_global_subrs; + FT_Byte** global_subrs; + + CFF_SubFont top_font; + FT_UInt num_subfonts; + CFF_SubFont* subfonts[CFF_MAX_CID_FONTS]; + + CFF_FD_Select fd_select; + + } CFF_Font; + + +#endif /* T2TYPES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/tterrors.h b/subsys/win32k/freetype/include/freetype/internal/tterrors.h new file mode 100644 index 0000000..b53e9f3 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/tterrors.h @@ -0,0 +1,121 @@ +/***************************************************************************/ +/* */ +/* tterrors.h */ +/* */ +/* TrueType error ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTERRORS_H +#define TTERRORS_H + + + /*************************************************************************/ + /* */ + /* Error codes declaration */ + /* */ + /* The error codes are grouped in `classes' used to indicate the `level' */ + /* at which the error happened. The class is given by an error code's */ + /* high byte. */ + /* */ + /*************************************************************************/ + + + /* Success is always 0. */ + +#define TT_Err_Ok FT_Err_Ok + + /* High level API errors. */ + +#define TT_Err_Invalid_File_Format FT_Err_Invalid_File_Format +#define TT_Err_Invalid_Argument FT_Err_Invalid_Argument +#define TT_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle +#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle +#define TT_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle +#define TT_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle +#define TT_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle +#define TT_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index + +#define TT_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature + +#define TT_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle + + /* Internal errors. */ + +#define TT_Err_Out_Of_Memory FT_Err_Out_Of_Memory +#define TT_Err_Unlisted_Object FT_Err_Unlisted_Object + + /* General glyph outline errors. */ + +#define TT_Err_Too_Many_Ins FT_Err_Too_Many_Hints +#define TT_Err_Invalid_Composite FT_Err_Invalid_Composite + + /* Bytecode interpreter error codes. */ + + /* These error codes are produced by the TrueType */ + /* bytecode interpreter. They usually indicate a */ + /* broken font file, a broken glyph within a font */ + /* file, or a bug in the interpreter! */ + +#define TT_Err_Invalid_Opcode 0x400 +#define TT_Err_Too_Few_Arguments 0x401 +#define TT_Err_Stack_Overflow 0x402 +#define TT_Err_Code_Overflow 0x403 +#define TT_Err_Bad_Argument 0x404 +#define TT_Err_Divide_By_Zero 0x405 +#define TT_Err_Storage_Overflow 0x406 +#define TT_Err_Cvt_Overflow 0x407 +#define TT_Err_Invalid_Reference 0x408 +#define TT_Err_Invalid_Distance 0x409 +#define TT_Err_Interpolate_Twilight 0x40A +#define TT_Err_Debug_OpCode 0x40B +#define TT_Err_ENDF_In_Exec_Stream 0x40C +#define TT_Err_Out_Of_CodeRanges 0x40D +#define TT_Err_Nested_DEFS 0x40E +#define TT_Err_Invalid_CodeRange 0x40F +#define TT_Err_Invalid_Displacement 0x410 +#define TT_Err_Execution_Too_Long 0x411 +#define TT_Err_Too_Many_Function_Defs 0x412 +#define TT_Err_Too_Many_Instruction_Defs 0x413 + + /* Other TrueType specific error codes. */ + +#define TT_Err_Table_Missing 0x420 +#define TT_Err_Too_Many_Extensions 0x421 +#define TT_Err_Extensions_Unsupported 0x422 +#define TT_Err_Invalid_Extension_Id 0x423 + +#define TT_Err_No_Vertical_Data 0x424 + +#define TT_Err_Max_Profile_Missing 0x430 +#define TT_Err_Header_Table_Missing 0x431 +#define TT_Err_Horiz_Header_Missing 0x432 +#define TT_Err_Locations_Missing 0x433 +#define TT_Err_Name_Table_Missing 0x434 +#define TT_Err_CMap_Table_Missing 0x435 +#define TT_Err_Hmtx_Table_Missing 0x436 +#define TT_Err_OS2_Table_Missing 0x437 +#define TT_Err_Post_Table_Missing 0x438 + +#define TT_Err_Invalid_Horiz_Metrics 0x440 +#define TT_Err_Invalid_CharMap_Format 0x441 +#define TT_Err_Invalid_PPem 0x442 +#define TT_Err_Invalid_Vert_Metrics 0x443 + +#define TT_Err_Could_Not_Find_Context 0x450 + + +#endif /* TTERRORS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/internal/tttypes.h b/subsys/win32k/freetype/include/freetype/internal/tttypes.h new file mode 100644 index 0000000..1fd43ce --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/internal/tttypes.h @@ -0,0 +1,1582 @@ +/***************************************************************************/ +/* */ +/* tttypes.h */ +/* */ +/* Basic SFNT/TrueType type definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTTYPES_H +#define TTTYPES_H + + +#include + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** REQUIRED TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TTC_Header */ + /* */ + /* */ + /* TrueType collection header. This table contains the offsets of */ + /* the font headers of each distinct TrueType face in the file. */ + /* */ + /* */ + /* tag :: Must be `ttc ' to indicate a TrueType collection. */ + /* */ + /* version :: The version number. */ + /* */ + /* count :: The number of faces in the collection. The */ + /* specification says this should be an unsigned long, but */ + /* we use a signed long since we need the value -1 for */ + /* specific purposes. */ + /* */ + /* offsets :: The offsets of the font headers, one per face. */ + /* */ + typedef struct TTC_Header_ + { + FT_ULong tag; + FT_Fixed version; + FT_Long count; + FT_ULong* offsets; + + } TTC_Header; + + + /*************************************************************************/ + /* */ + /* */ + /* SFNT_Header */ + /* */ + /* */ + /* SFNT file format header. */ + /* */ + /* */ + /* format_tag :: The font format tag. */ + /* */ + /* num_tables :: The number of tables in file. */ + /* */ + /* search_range :: Must be 16*(max power of 2 <= num_tables). */ + /* */ + /* entry_selector :: Must be log2 of search_range/16. */ + /* */ + /* range_shift :: Must be num_tables*16 - search_range. */ + /* */ + typedef struct SFNT_Header_ + { + FT_ULong format_tag; + FT_UShort num_tables; + FT_UShort search_range; + FT_UShort entry_selector; + FT_UShort range_shift; + + } SFNT_Header; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_TableDir */ + /* */ + /* */ + /* This structure models a TrueType table directory. It is used to */ + /* access the various tables of the font face. */ + /* */ + /* */ + /* version :: The version number; starts with 0x00010000. */ + /* */ + /* numTables :: The number of tables. */ + /* */ + /* searchRange :: Unused. */ + /* */ + /* entrySelector :: Unused. */ + /* */ + /* rangeShift :: Unused. */ + /* */ + /* */ + /* This structure is only used during font opening. */ + /* */ + typedef struct TT_TableDir_ + { + FT_Fixed version; /* should be 0x10000 */ + FT_UShort numTables; /* number of tables */ + + FT_UShort searchRange; /* These parameters are only used */ + FT_UShort entrySelector; /* for a dichotomy search in the */ + FT_UShort rangeShift; /* directory. We ignore them. */ + + } TT_TableDir; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Table */ + /* */ + /* */ + /* This structure describes a given table of a TrueType font. */ + /* */ + /* */ + /* Tag :: A four-bytes tag describing the table. */ + /* */ + /* CheckSum :: The table checksum. This value can be ignored. */ + /* */ + /* Offset :: The offset of the table from the start of the TrueType */ + /* font in its resource. */ + /* */ + /* Length :: The table length (in bytes). */ + /* */ + typedef struct TT_Table_ + { + FT_ULong Tag; /* table type */ + FT_ULong CheckSum; /* table checksum */ + FT_ULong Offset; /* table file offset */ + FT_ULong Length; /* table length */ + + } TT_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CMapDir */ + /* */ + /* */ + /* This structure describes the directory of the `cmap' table, */ + /* containing the font's character mappings table. */ + /* */ + /* */ + /* tableVersionNumber :: The version number. */ + /* */ + /* numCMaps :: The number of charmaps in the font. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_CMapDir_ + { + FT_UShort tableVersionNumber; + FT_UShort numCMaps; + + } TT_CMapDir; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CMapDirEntry */ + /* */ + /* */ + /* This structure describes a charmap in a TrueType font. */ + /* */ + /* */ + /* platformID :: An ID used to specify for which platform this */ + /* charmap is defined (FreeType manages all platforms). */ + /* */ + /* encodingID :: A platform-specific ID used to indicate which source */ + /* encoding is used in this charmap. */ + /* */ + /* offset :: The offset of the charmap relative to the start of */ + /* the `cmap' table. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_CMapDirEntry_ + { + FT_UShort platformID; + FT_UShort platformEncodingID; + FT_Long offset; + + } TT_CMapDirEntry; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LongMetrics */ + /* */ + /* */ + /* A structure modeling the long metrics of the `hmtx' and `vmtx' */ + /* TrueType tables. The values are expressed in font units. */ + /* */ + /* */ + /* advance :: The advance width or height for the glyph. */ + /* */ + /* bearing :: The left-side or top-side bearing for the glyph. */ + /* */ + typedef struct TT_LongMetrics_ + { + FT_UShort advance; + FT_Short bearing; + + } TT_LongMetrics; + + + /*************************************************************************/ + /* */ + /* TT_ShortMetrics */ + /* */ + /* */ + /* A simple type to model the short metrics of the `hmtx' and `vmtx' */ + /* tables. */ + /* */ + typedef FT_Short TT_ShortMetrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_NameRec */ + /* */ + /* */ + /* A structure modeling TrueType name records. Name records are used */ + /* to store important strings like family name, style name, */ + /* copyright, etc. in _localized_ versions (i.e., language, encoding, */ + /* etc). */ + /* */ + /* */ + /* platformID :: The ID of the name's encoding platform. */ + /* */ + /* encodingID :: The platform-specific ID for the name's encoding. */ + /* */ + /* languageID :: The platform-specific ID for the name's language. */ + /* */ + /* nameID :: The ID specifying what kind of name this is. */ + /* */ + /* stringLength :: The length of the string in bytes. */ + /* */ + /* stringOffset :: The offset to the string in the `name' table. */ + /* */ + /* string :: A pointer to the string's bytes. Note that these */ + /* are usually UTF-16 encoded characters. */ + /* */ + typedef struct TT_NameRec_ + { + FT_UShort platformID; + FT_UShort encodingID; + FT_UShort languageID; + FT_UShort nameID; + FT_UShort stringLength; + FT_UShort stringOffset; + + /* this last field is not defined in the spec */ + /* but used by the FreeType engine */ + + FT_Byte* string; + + } TT_NameRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_NameTable */ + /* */ + /* */ + /* A structure modeling the TrueType name table. */ + /* */ + /* */ + /* format :: The format of the name table. */ + /* */ + /* numNameRecords :: The number of names in table. */ + /* */ + /* storageOffset :: The offset of the name table in the `name' */ + /* TrueType table. */ + /* */ + /* names :: An array of name records. */ + /* */ + /* storage :: The names storage area. */ + /* */ + typedef struct TT_NameTable_ + { + FT_UShort format; + FT_UShort numNameRecords; + FT_UShort storageOffset; + TT_NameRec* names; + FT_Byte* storage; + + } TT_NameTable; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** OPTIONAL TRUETYPE/OPENTYPE TABLES DEFINITIONS ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GaspRange */ + /* */ + /* */ + /* A tiny structure used to model a gasp range according to the */ + /* TrueType specification. */ + /* */ + /* */ + /* maxPPEM :: The maximum ppem value to which `gaspFlag' applies. */ + /* */ + /* gaspFlag :: A flag describing the grid-fitting and anti-aliasing */ + /* modes to be used. */ + /* */ + typedef struct TT_GaspRange_ + { + FT_UShort maxPPEM; + FT_UShort gaspFlag; + + } TT_GaspRange; + + +#define TT_GASP_GRIDFIT 0x01 +#define TT_GASP_DOGRAY 0x02 + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Gasp */ + /* */ + /* */ + /* A structure modeling the TrueType `gasp' table used to specify */ + /* grid-fitting and anti-aliasing behaviour. */ + /* */ + /* */ + /* version :: The version number. */ + /* */ + /* numRanges :: The number of gasp ranges in table. */ + /* */ + /* gaspRanges :: An array of gasp ranges. */ + /* */ + typedef struct TT_Gasp_ + { + FT_UShort version; + FT_UShort numRanges; + TT_GaspRange* gaspRanges; + + } TT_Gasp; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HdmxRec */ + /* */ + /* */ + /* A small structure used to model the pre-computed widths of a given */ + /* size. They are found in the `hdmx' table. */ + /* */ + /* */ + /* ppem :: The pixels per EM value at which these metrics apply. */ + /* */ + /* max_width :: The maximum advance width for this metric. */ + /* */ + /* widths :: An array of widths. Note: These are 8-bit bytes. */ + /* */ + typedef struct TT_HdmxRec_ + { + FT_Byte ppem; + FT_Byte max_width; + FT_Byte* widths; + + } TT_HdmxRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Hdmx */ + /* */ + /* */ + /* A structure used to model the `hdmx' table, which contains */ + /* pre-computed widths for a set of given sizes/dimensions. */ + /* */ + /* */ + /* version :: The version number. */ + /* */ + /* num_records :: The number of hdmx records. */ + /* */ + /* records :: An array of hdmx records. */ + /* */ + typedef struct TT_Hdmx_ + { + FT_UShort version; + FT_Short num_records; + TT_HdmxRec* records; + + } TT_Hdmx; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Kern_0_Pair */ + /* */ + /* */ + /* A structure used to model a kerning pair for the kerning table */ + /* format 0. The engine now loads this table if it finds one in the */ + /* font file. */ + /* */ + /* */ + /* left :: The index of the left glyph in pair. */ + /* */ + /* right :: The index of the right glyph in pair. */ + /* */ + /* value :: The kerning distance. A positive value spaces the */ + /* glyphs, a negative one makes them closer. */ + /* */ + typedef struct TT_Kern_0_Pair_ + { + FT_UShort left; /* index of left glyph in pair */ + FT_UShort right; /* index of right glyph in pair */ + FT_FWord value; /* kerning value */ + + } TT_Kern_0_Pair; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** EMBEDDED BITMAPS SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Metrics */ + /* */ + /* */ + /* A structure used to hold the big metrics of a given glyph bitmap */ + /* in a TrueType or OpenType font. These are usually found in the */ + /* `EBDT' (Microsoft) or `bdat' (Apple) table. */ + /* */ + /* */ + /* height :: The glyph height in pixels. */ + /* */ + /* width :: The glyph width in pixels. */ + /* */ + /* horiBearingX :: The horizontal left bearing. */ + /* */ + /* horiBearingY :: The horizontal top bearing. */ + /* */ + /* horiAdvance :: The horizontal advance. */ + /* */ + /* vertBearingX :: The vertical left bearing. */ + /* */ + /* vertBearingY :: The vertical top bearing. */ + /* */ + /* vertAdvance :: The vertical advance. */ + /* */ + typedef struct TT_SBit_Metrics_ + { + FT_Byte height; + FT_Byte width; + + FT_Char horiBearingX; + FT_Char horiBearingY; + FT_Byte horiAdvance; + + FT_Char vertBearingX; + FT_Char vertBearingY; + FT_Byte vertAdvance; + + } TT_SBit_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Small_Metrics */ + /* */ + /* */ + /* A structure used to hold the small metrics of a given glyph bitmap */ + /* in a TrueType or OpenType font. These are usually found in the */ + /* `EBDT' (Microsoft) or the `bdat' (Apple) table. */ + /* */ + /* */ + /* height :: The glyph height in pixels. */ + /* */ + /* width :: The glyph width in pixels. */ + /* */ + /* bearingX :: The left-side bearing. */ + /* */ + /* bearingY :: The top-side bearing. */ + /* */ + /* advance :: The advance width or height. */ + /* */ + typedef struct TT_SBit_Small_Metrics_ + { + FT_Byte height; + FT_Byte width; + + FT_Char bearingX; + FT_Char bearingY; + FT_Byte advance; + + } TT_SBit_Small_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Line_Metrics */ + /* */ + /* */ + /* A structure used to describe the text line metrics of a given */ + /* bitmap strike, for either a horizontal or vertical layout. */ + /* */ + /* */ + /* ascender :: The ascender in pixels. */ + /* */ + /* descender :: The descender in pixels. */ + /* */ + /* max_width :: The maximum glyph width in pixels. */ + /* */ + /* caret_slope_enumerator :: Rise of the caret slope, typically set */ + /* to 1 for non-italic fonts. */ + /* */ + /* caret_slope_denominator :: Rise of the caret slope, typically set */ + /* to 0 for non-italic fonts. */ + /* */ + /* caret_offset :: Offset in pixels to move the caret for */ + /* proper positioning. */ + /* */ + /* min_origin_SB :: Minimum of horiBearingX (resp. */ + /* vertBearingY). */ + /* min_advance_SB :: Minimum of */ + /* */ + /* horizontal advance - */ + /* ( horiBearingX + width ) */ + /* */ + /* resp. */ + /* */ + /* vertical advance - */ + /* ( vertBearingY + height ) */ + /* */ + /* max_before_BL :: Maximum of horiBearingY (resp. */ + /* vertBearingY). */ + /* */ + /* min_after_BL :: Minimum of */ + /* */ + /* horiBearingY - height */ + /* */ + /* resp. */ + /* */ + /* vertBearingX - width */ + /* */ + /* pads :: Unused (to make the size of the record */ + /* a multiple of 32 bits. */ + /* */ + typedef struct TT_SBit_Line_Metrics_ + { + FT_Char ascender; + FT_Char descender; + FT_Byte max_width; + FT_Char caret_slope_numerator; + FT_Char caret_slope_denominator; + FT_Char caret_offset; + FT_Char min_origin_SB; + FT_Char min_advance_SB; + FT_Char max_before_BL; + FT_Char min_after_BL; + FT_Char pads[2]; + + } TT_SBit_Line_Metrics; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Range */ + /* */ + /* */ + /* A TrueType/OpenType subIndexTable as defined in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* */ + /* first_glyph :: The first glyph index in the range. */ + /* */ + /* last_glyph :: The last glyph index in the range. */ + /* */ + /* index_format :: The format of index table. Valid values are 1 */ + /* to 5. */ + /* */ + /* image_format :: The format of `EBDT' image data. */ + /* */ + /* image_offset :: The offset to image data in `EBDT'. */ + /* */ + /* image_size :: For index formats 2 and 5. This is the size in */ + /* bytes of each glyph bitmap. */ + /* */ + /* big_metrics :: For index formats 2 and 5. This is the big */ + /* metrics for each glyph bitmap. */ + /* */ + /* num_glyphs :: For index formats 4 and 5. This is the number of */ + /* glyphs in the code array. */ + /* */ + /* glyph_offsets :: For index formats 1 and 3. */ + /* */ + /* glyph_codes :: For index formats 4 and 5. */ + /* */ + /* table_offset :: The offset of the index table in the `EBLC' */ + /* table. Only used during strike loading. */ + /* */ + typedef struct TT_SBit_Range + { + FT_UShort first_glyph; + FT_UShort last_glyph; + + FT_UShort index_format; + FT_UShort image_format; + FT_ULong image_offset; + + FT_ULong image_size; + TT_SBit_Metrics metrics; + FT_ULong num_glyphs; + + FT_ULong* glyph_offsets; + FT_UShort* glyph_codes; + + FT_ULong table_offset; + + } TT_SBit_Range; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Strike */ + /* */ + /* */ + /* A structure used describe a given bitmap strike in the `EBLC' */ + /* (Microsoft) or `bloc' (Apple) tables. */ + /* */ + /* */ + /* num_index_ranges :: The number of index ranges. */ + /* */ + /* index_ranges :: An array of glyph index ranges. */ + /* */ + /* color_ref :: Unused. A color reference? */ + /* */ + /* hori :: The line metrics for horizontal layouts. */ + /* */ + /* vert :: The line metrics for vertical layouts. */ + /* */ + /* start_glyph :: The lowest glyph index for this strike. */ + /* */ + /* end_glyph :: The highest glyph index for this strike. */ + /* */ + /* x_ppem :: The number of horizontal pixels per EM. */ + /* */ + /* y_ppem :: The number of vertical pixels per EM. */ + /* */ + /* bit_depth :: The bit depth. Valid values are 1, 2, 4, */ + /* and 8. */ + /* */ + /* flags :: Is this a vertical or horizontal strike? */ + /* */ + typedef struct TT_SBit_Strike_ + { + FT_Int num_ranges; + TT_SBit_Range* sbit_ranges; + FT_ULong ranges_offset; + + FT_ULong color_ref; + + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + FT_UShort start_glyph; + FT_UShort end_glyph; + + FT_Byte x_ppem; + FT_Byte y_ppem; + + FT_Byte bit_depth; + FT_Char flags; + + } TT_SBit_Strike; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Component */ + /* */ + /* */ + /* A simple structure to describe a compound sbit element. */ + /* */ + /* */ + /* glyph_code :: The element's glyph index. */ + /* */ + /* x_offset :: The element's left bearing. */ + /* */ + /* y_offset :: The element's top bearing. */ + /* */ + typedef struct TT_SBit_Component_ + { + FT_UShort glyph_code; + + FT_Char x_offset; + FT_Char y_offset; + + } TT_SBit_Component; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_SBit_Scale */ + /* */ + /* */ + /* A structure used describe a given bitmap scaling table, as defined */ + /* in the `EBSC' table. */ + /* */ + /* */ + /* hori :: The horizontal line metrics. */ + /* */ + /* vert :: The vertical line metrics. */ + /* */ + /* x_ppem :: The number of horizontal pixels per EM. */ + /* */ + /* y_ppem :: The number of vertical pixels per EM. */ + /* */ + /* x_ppem_substitute :: Substitution x_ppem value. */ + /* */ + /* y_ppem_substitute :: Substitution y_ppem value. */ + /* */ + typedef struct TT_SBit_Scale_ + { + TT_SBit_Line_Metrics hori; + TT_SBit_Line_Metrics vert; + + FT_Byte x_ppem; + FT_Byte y_ppem; + + FT_Byte x_ppem_substitute; + FT_Byte y_ppem_substitute; + + } TT_SBit_Scale; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** POSTSCRIPT GLYPH NAMES SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_20 */ + /* */ + /* */ + /* Postscript names sub-table, format 2.0. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* */ + /* num_glyphs :: The number of named glyphs in the table. */ + /* */ + /* num_names :: The number of PS names stored in the table. */ + /* */ + /* glyph_indices :: The indices of the glyphs in the names arrays. */ + /* */ + /* glyph_names :: The PS names not in Mac Encoding. */ + /* */ + typedef struct TT_Post_20_ + { + FT_UShort num_glyphs; + FT_UShort num_names; + FT_UShort* glyph_indices; + FT_Char** glyph_names; + + } TT_Post_20; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_25 */ + /* */ + /* */ + /* Postscript names sub-table, format 2.5. Stores the PS name of */ + /* each glyph in the font face. */ + /* */ + /* */ + /* num_glyphs :: The number of glyphs in the table. */ + /* */ + /* offsets :: An array of signed offsets in a normal Mac */ + /* Postscript name encoding. */ + /* */ + typedef struct TT_Post_25_ + { + FT_UShort num_glyphs; + FT_Char* offsets; + + } TT_Post_25; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Post_Names */ + /* */ + /* */ + /* Postscript names table, either format 2.0 or 2.5. */ + /* */ + /* */ + /* loaded :: A flag to indicate whether the PS names are loaded. */ + /* */ + /* format_20 :: The sub-table used for format 2.0. */ + /* */ + /* format_25 :: The sub-table used for format 2.5. */ + /* */ + typedef struct TT_Post_Names_ + { + FT_Bool loaded; + + union + { + TT_Post_20 format_20; + TT_Post_25 format_25; + + } names; + + } TT_Post_Names; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** TRUETYPE CHARMAPS SUPPORT ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* format 0 */ + + typedef struct TT_CMap0_ + { + FT_Byte* glyphIdArray; + + } TT_CMap0; + + + /* format 2 */ + + typedef struct TT_CMap2SubHeader_ + { + FT_UShort firstCode; /* first valid low byte */ + FT_UShort entryCount; /* number of valid low bytes */ + FT_Short idDelta; /* delta value to glyphIndex */ + FT_UShort idRangeOffset; /* offset from here to 1st code */ + + } TT_CMap2SubHeader; + + + typedef struct TT_CMap2_ + { + FT_UShort* subHeaderKeys; + /* high byte mapping table */ + /* value = subHeader index * 8 */ + + TT_CMap2SubHeader* subHeaders; + FT_UShort* glyphIdArray; + FT_UShort numGlyphId; /* control value */ + + } TT_CMap2; + + + /* format 4 */ + + typedef struct TT_CMap4Segment_ + { + FT_UShort endCount; + FT_UShort startCount; + FT_Short idDelta; + FT_UShort idRangeOffset; + + } TT_CMap4Segment; + + + typedef struct TT_CMap4_ + { + FT_UShort segCountX2; /* number of segments * 2 */ + FT_UShort searchRange; /* these parameters can be used */ + FT_UShort entrySelector; /* for a binary search */ + FT_UShort rangeShift; + + TT_CMap4Segment* segments; + FT_UShort* glyphIdArray; + FT_UShort numGlyphId; /* control value */ + + TT_CMap4Segment* last_segment; /* last used segment; this is a small */ + /* cache to potentially increase speed */ + } TT_CMap4; + + + /* format 6 */ + + typedef struct TT_CMap6_ + { + FT_UShort firstCode; /* first character code of subrange */ + FT_UShort entryCount; /* number of character codes in subrange */ + + FT_UShort* glyphIdArray; + + } TT_CMap6; + + + typedef struct TT_CMapTable_ TT_CMapTable; + + + typedef + FT_UInt (*TT_CharMap_Func)( TT_CMapTable* charmap, + FT_ULong char_code ); + + + /* charmap table */ + struct TT_CMapTable_ + { + FT_UShort platformID; + FT_UShort platformEncodingID; + FT_UShort format; + FT_UShort length; + FT_UShort version; + + FT_Bool loaded; + FT_ULong offset; + + union + { + TT_CMap0 cmap0; + TT_CMap2 cmap2; + TT_CMap4 cmap4; + TT_CMap6 cmap6; + } c; + + TT_CharMap_Func get_index; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMapRec */ + /* */ + /* */ + /* The TrueType character map object type. */ + /* */ + /* */ + /* root :: The parent character map structure. */ + /* */ + /* cmap :: The used character map. */ + /* */ + typedef struct TT_CharMapRec_ + { + FT_CharMapRec root; + TT_CMapTable cmap; + + } TT_CharMapRec; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** ***/ + /*** ORIGINAL TT_FACE CLASS DEFINITION ***/ + /*** ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This structure/class is defined here because it is common to the */ + /* following formats: TTF, OpenType-TT, and OpenType-CFF. */ + /* */ + /* Note, however, that the classes TT_Size, TT_GlyphSlot, and TT_CharMap */ + /* are not shared between font drivers, and are thus defined normally in */ + /* `ttobjs.h'. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Face */ + /* */ + /* */ + /* A handle to a TrueType face/font object. A TT_Face encapsulates */ + /* the resolution and scaling independent parts of a TrueType font */ + /* resource. */ + /* */ + /* */ + /* The TT_Face structure is also used as a `parent class' for the */ + /* OpenType-CFF class (T2_Face). */ + /* */ + typedef struct TT_FaceRec_* TT_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap */ + /* */ + /* */ + /* A handle to a TrueType character mapping object. */ + /* */ + typedef struct TT_CharMapRec_* TT_CharMap; + + + /* a function type used for the truetype bytecode interpreter hooks */ + typedef FT_Error (*TT_Interpreter)( void* exec_context ); + + /* forward declaration */ + typedef struct TT_Loader_ TT_Loader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_Table_Func */ + /* */ + /* */ + /* Seeks a stream to the start of a given TrueType table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* tag :: A 4-byte tag used to name the table. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* length :: The length of the table in bytes. Set to 0 if not */ + /* needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + typedef + FT_Error (*TT_Goto_Table_Func)( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Access_Glyph_Frame_Func */ + /* */ + /* */ + /* Seeks a stream to the start of a given glyph element, and opens a */ + /* frame for it. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* glyph index :: The index of the glyph to access. */ + /* */ + /* offset :: The offset of the glyph according to the */ + /* `locations' table. */ + /* */ + /* byte_count :: The size of the frame in bytes. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function is normally equivalent to FILE_Seek(offset) */ + /* followed by ACCESS_Frame(byte_count) with the loader's stream, but */ + /* alternative formats (e.g. compressed ones) might use something */ + /* different. */ + /* */ + typedef + FT_Error (*TT_Access_Glyph_Frame_Func)( TT_Loader* loader, + FT_UInt glyph_index, + FT_ULong offset, + FT_UInt byte_count ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph_Element_Func */ + /* */ + /* */ + /* Reads one glyph element (its header, a simple glyph, or a */ + /* composite) from the loader's current stream frame. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + typedef + FT_Error (*TT_Load_Glyph_Element_Func)( TT_Loader* loader ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Forget_Glyph_Frame_Func */ + /* */ + /* */ + /* Closes the current loader stream frame for the glyph. */ + /* */ + /* */ + /* loader :: The current TrueType glyph loader object. */ + /* */ + typedef + void (*TT_Forget_Glyph_Frame_Func)( TT_Loader* loader ); + + + + /*************************************************************************/ + /* */ + /* TrueType Face Type */ + /* */ + /* */ + /* TT_Face */ + /* */ + /* */ + /* The TrueType face class. These objects model the resolution and */ + /* point-size independent data found in a TrueType font file. */ + /* */ + /* */ + /* root :: The base FT_Face structure, managed by the */ + /* base layer. */ + /* */ + /* ttc_header :: The TrueType collection header, used when */ + /* the file is a `ttc' rather than a `ttf'. */ + /* For ordinary font files, the field */ + /* `ttc_header.count' is set to 0. */ + /* */ + /* format_tag :: The font format tag. */ + /* */ + /* num_tables :: The number of TrueType tables in this font */ + /* file. */ + /* */ + /* dir_tables :: The directory of TrueType tables for this */ + /* font file. */ + /* */ + /* header :: The font's font header (`head' table). */ + /* Read on font opening. */ + /* */ + /* horizontal :: The font's horizontal header (`hhea' */ + /* table). This field also contains the */ + /* associated horizontal metrics table */ + /* (`hmtx'). */ + /* */ + /* max_profile :: The font's maximum profile table. Read on */ + /* font opening. Note that some maximum */ + /* values cannot be taken directly from this */ + /* table. We thus define additional fields */ + /* below to hold the computed maxima. */ + /* */ + /* max_components :: The maximum number of glyph components */ + /* required to load any composite glyph from */ + /* this font. Used to size the load stack. */ + /* */ + /* vertical_info :: A boolean which is set when the font file */ + /* contains vertical metrics. If not, the */ + /* value of the `vertical' field is */ + /* undefined. */ + /* */ + /* vertical :: The font's vertical header (`vhea' table). */ + /* This field also contains the associated */ + /* vertical metrics table (`vmtx'), if found. */ + /* IMPORTANT: The contents of this field is */ + /* undefined if the `verticalInfo' field is */ + /* unset. */ + /* */ + /* num_names :: The number of name records within this */ + /* TrueType font. */ + /* */ + /* name_table :: The table of name records (`name'). */ + /* */ + /* os2 :: The font's OS/2 table (`OS/2'). */ + /* */ + /* postscript :: The font's PostScript table (`post' */ + /* table). The PostScript glyph names are */ + /* not loaded by the driver on face opening. */ + /* See the `ttpost' module for more details. */ + /* */ + /* num_charmaps :: The number of character mappings in the */ + /* font. */ + /* */ + /* charmaps :: The array of charmap objects for this font */ + /* file. Note that this field is a typeless */ + /* pointer. The Reason is that the format of */ + /* charmaps varies with the underlying font */ + /* format and cannot be determined here. */ + /* */ + /* goto_table :: A function called by each TrueType table */ + /* loader to position a stream's cursor to */ + /* the start of a given table according to */ + /* its tag. It defaults to TT_Goto_Face but */ + /* can be different for strange formats (e.g. */ + /* Type 42). */ + /* */ + /* access_glyph_frame :: XXX */ + /* */ + /* read_glyph_header :: XXX */ + /* */ + /* read_simple_glyph :: XXX */ + /* */ + /* read_composite_glyph :: XXX */ + /* */ + /* forget_glyph_frame :: XXX */ + /* */ + /* sfnt :: A pointer to the SFNT `driver' interface. */ + /* */ + /* psnames :: A pointer to the `PSNames' module */ + /* interface. */ + /* */ + /* hdmx :: The face's horizontal device metrics */ + /* (`hdmx' table). This table is optional in */ + /* TrueType/OpenType fonts. */ + /* */ + /* gasp :: The grid-fitting and scaling properties */ + /* table (`gasp'). This table is optional in */ + /* TrueType/OpenType fonts. */ + /* */ + /* pclt :: XXX */ + /* */ + /* num_sbit_strikes :: The number of sbit strikes, i.e., bitmap */ + /* sizes, embedded in this font. */ + /* */ + /* sbit_strikes :: An array of sbit strikes embedded in this */ + /* font. This table is optional in a */ + /* TrueType/OpenType font. */ + /* */ + /* num_sbit_scales :: The number of sbit scales for this font. */ + /* */ + /* sbit_scales :: Array of sbit scales embedded in this */ + /* font. This table is optional in a */ + /* TrueType/OpenType font. */ + /* */ + /* postscript_names :: A table used to store the Postscript names */ + /* of the glyphs for this font. See the */ + /* file `ttconfig.h' for comments on the */ + /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES option. */ + /* */ + /* num_locations :: The number of glyph locations in this */ + /* TrueType file. This should be */ + /* identical to the number of glyphs. */ + /* Ignored for Type 2 fonts. */ + /* */ + /* glyph_locations :: An array of longs. These are offsets to */ + /* glyph data within the `glyf' table. */ + /* Ignored for Type 2 font faces. */ + /* */ + /* font_program_size :: Size in bytecodes of the face's font */ + /* program. 0 if none defined. Ignored for */ + /* Type 2 fonts. */ + /* */ + /* font_program :: The face's font program (bytecode stream) */ + /* executed at load time, also used during */ + /* glyph rendering. Comes from the `fpgm' */ + /* table. Ignored for Type 2 font fonts. */ + /* */ + /* cvt_program_size :: The size in bytecodes of the face's cvt */ + /* program. Ignored for Type 2 fonts. */ + /* */ + /* cvt_program :: The face's cvt program (bytecode stream) */ + /* executed each time an instance/size is */ + /* changed/reset. Comes from the `prep' */ + /* table. Ignored for Type 2 fonts. */ + /* */ + /* cvt_size :: Size of the control value table (in */ + /* entries). Ignored for Type 2 fonts. */ + /* */ + /* cvt :: The face's original control value table. */ + /* Coordinates are expressed in unscaled font */ + /* units. Comes from the `cvt ' table. */ + /* Ignored for Type 2 fonts. */ + /* */ + /* num_kern_pairs :: The number of kerning pairs present in the */ + /* font file. The engine only loads the */ + /* first horizontal format 0 kern table it */ + /* finds in the font file. You should use */ + /* the `ttxkern' structures if you want to */ + /* access other kerning tables. Ignored */ + /* for Type 2 fonts. */ + /* */ + /* kern_table_index :: The index of the kerning table in the font */ + /* kerning directory. Only used by the */ + /* ttxkern extension to avoid data */ + /* duplication. Ignored for Type 2 fonts. */ + /* */ + /* interpreter :: A pointer to the TrueType bytecode */ + /* interpreters field is also used to hook */ + /* the debugger in `ttdebug'. */ + /* */ + /* extra :: XXX */ + /* */ + typedef struct TT_FaceRec_ + { + FT_FaceRec root; + + TTC_Header ttc_header; + + FT_ULong format_tag; + FT_UShort num_tables; + TT_Table* dir_tables; + + TT_Header header; /* TrueType header table */ + TT_HoriHeader horizontal; /* TrueType horizontal header */ + + TT_MaxProfile max_profile; + FT_ULong max_components; + + FT_Bool vertical_info; + TT_VertHeader vertical; /* TT Vertical header, if present */ + + FT_Int num_names; /* number of name records */ + TT_NameTable name_table; /* name table */ + + TT_OS2 os2; /* TrueType OS/2 table */ + TT_Postscript postscript; /* TrueType Postscript table */ + + FT_Int num_charmaps; + TT_CharMap charmaps; /* array of TT_CharMapRec */ + + TT_Goto_Table_Func goto_table; + + TT_Access_Glyph_Frame_Func access_glyph_frame; + TT_Load_Glyph_Element_Func read_glyph_header; + TT_Load_Glyph_Element_Func read_simple_glyph; + TT_Load_Glyph_Element_Func read_composite_glyph; + TT_Forget_Glyph_Frame_Func forget_glyph_frame; + + /* a typeless pointer to the SFNT_Interface table used to load */ + /* the basic TrueType tables in the face object */ + void* sfnt; + + /* a typeless pointer to the PSNames_Interface table used to */ + /* handle glyph names <-> unicode & Mac values */ + void* psnames; + + /***********************************************************************/ + /* */ + /* Optional TrueType/OpenType tables */ + /* */ + /***********************************************************************/ + + /* horizontal device metrics */ + TT_Hdmx hdmx; + + /* grid-fitting and scaling table */ + TT_Gasp gasp; /* the `gasp' table */ + + /* PCL 5 table */ + TT_PCLT pclt; + + /* embedded bitmaps support */ + FT_Int num_sbit_strikes; + TT_SBit_Strike* sbit_strikes; + + FT_Int num_sbit_scales; + TT_SBit_Scale* sbit_scales; + + /* postscript names table */ + TT_Post_Names postscript_names; + + + /***********************************************************************/ + /* */ + /* TrueType-specific fields (ignored by the OTF-Type2 driver) */ + /* */ + /***********************************************************************/ + + /* the glyph locations */ + FT_UShort num_locations; + FT_Long* glyph_locations; + + /* the font program, if any */ + FT_ULong font_program_size; + FT_Byte* font_program; + + /* the cvt program, if any */ + FT_ULong cvt_program_size; + FT_Byte* cvt_program; + + /* the original, unscaled, control value table */ + FT_ULong cvt_size; + FT_Short* cvt; + + /* the format 0 kerning table, if any */ + FT_Int num_kern_pairs; + FT_Int kern_table_index; + TT_Kern_0_Pair* kern_pairs; + + /* A pointer to the bytecode interpreter to use. This is also */ + /* used to hook the debugger for the `ttdebug' utility. */ + TT_Interpreter interpreter; + + + /***********************************************************************/ + /* */ + /* Other tables or fields. This is used by derivative formats like */ + /* OpenType. */ + /* */ + /***********************************************************************/ + + FT_Generic extra; + + } TT_FaceRec; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GlyphZone */ + /* */ + /* */ + /* A glyph zone is used to load, scale and hint glyph outline */ + /* coordinates. */ + /* */ + /* */ + /* memory :: A handle to the memory manager. */ + /* */ + /* max_points :: The maximal size in points of the zone. */ + /* */ + /* max_contours :: Max size in links contours of thez one. */ + /* */ + /* n_points :: The current number of points in the zone. */ + /* */ + /* n_contours :: The current number of contours in the zone. */ + /* */ + /* org :: The original glyph coordinates (font */ + /* units/scaled). */ + /* */ + /* cur :: The current glyph coordinates (scaled/hinted). */ + /* */ + /* tags :: The point control tags. */ + /* */ + /* contours :: The contours end points. */ + /* */ + typedef struct TT_GlyphZone_ + { + FT_Memory memory; + FT_UShort max_points; + FT_UShort max_contours; + FT_UShort n_points; /* number of points in zone */ + FT_Short n_contours; /* number of contours */ + + FT_Vector* org; /* original point coordinates */ + FT_Vector* cur; /* current point coordinates */ + + FT_Byte* tags; /* current touch flags */ + FT_UShort* contours; /* contour end points */ + + } TT_GlyphZone; + + + /* handle to execution context */ + typedef struct TT_ExecContextRec_* TT_ExecContext; + + /* glyph loader structure */ + struct TT_Loader_ + { + FT_Face face; + FT_Size size; + FT_GlyphSlot glyph; + FT_GlyphLoader* gloader; + + FT_ULong load_flags; + FT_UInt glyph_index; + + FT_Stream stream; + FT_Int byte_len; + + FT_Short n_contours; + FT_BBox bbox; + FT_Int left_bearing; + FT_Int advance; + FT_Bool preserve_pps; + FT_Vector pp1; + FT_Vector pp2; + + FT_ULong glyf_offset; + + /* the zone where we load our glyphs */ + TT_GlyphZone base; + TT_GlyphZone zone; + + TT_ExecContext exec; + FT_Byte* instructions; + FT_ULong ins_pos; + + /* for possible extensibility in other formats */ + void* other; + + }; + + +#endif /* TTTYPES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/t1tables.h b/subsys/win32k/freetype/include/freetype/t1tables.h new file mode 100644 index 0000000..323e013 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/t1tables.h @@ -0,0 +1,235 @@ +/***************************************************************************/ +/* */ +/* t1tables.h */ +/* */ +/* Basic Type 1/Type 2 tables definitions and interface (specification */ +/* only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1TABLES_H +#define T1TABLES_H + + +#include + + + /* Note that we separate font data in T1_FontInfo and T1_Private */ + /* structures in order to support Multiple Master fonts. */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_FontInfo */ + /* */ + /* */ + /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */ + /* that for Multiple Master fonts, each instance has its own */ + /* FontInfo. */ + /* */ + typedef struct T1_FontInfo + { + FT_String* version; + FT_String* notice; + FT_String* full_name; + FT_String* family_name; + FT_String* weight; + FT_Long italic_angle; + FT_Bool is_fixed_pitch; + FT_Short underline_position; + FT_UShort underline_thickness; + + } T1_FontInfo; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Private */ + /* */ + /* */ + /* A structure used to model a Type1/Type2 FontInfo dictionary. Note */ + /* that for Multiple Master fonts, each instance has its own Private */ + /* dict. */ + /* */ + typedef struct T1_Private + { + FT_Int unique_id; + FT_Int lenIV; + + FT_Byte num_blue_values; + FT_Byte num_other_blues; + FT_Byte num_family_blues; + FT_Byte num_family_other_blues; + + FT_Short blue_values[14]; + FT_Short other_blues[10]; + + FT_Short family_blues [14]; + FT_Short family_other_blues[10]; + + FT_Fixed blue_scale; + FT_Int blue_shift; + FT_Int blue_fuzz; + + FT_UShort standard_width[1]; + FT_UShort standard_height[1]; + + FT_Byte num_snap_widths; + FT_Byte num_snap_heights; + FT_Bool force_bold; + FT_Bool round_stem_up; + + FT_Short snap_widths [13]; /* reserve one place for the std */ + FT_Short snap_heights[13]; /* reserve one place for the std */ + + FT_Long language_group; + FT_Long password; + + FT_Short min_feature[2]; + + } T1_Private; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Blend_Flags */ + /* */ + /* */ + /* A set of flags used to indicate which fields are present in a */ + /* given blen dictionary (font info or private). Used to support */ + /* Multiple Masters fonts. */ + /* */ + typedef enum + { + /* required fields in a FontInfo blend dictionary */ + t1_blend_underline_position = 0, + t1_blend_underline_thickness, + t1_blend_italic_angle, + + /* required fields in a Private blend dictionary */ + t1_blend_blue_values, + t1_blend_other_blues, + t1_blend_standard_width, + t1_blend_standard_height, + t1_blend_stem_snap_widths, + t1_blend_stem_snap_heights, + t1_blend_blue_scale, + t1_blend_blue_shift, + t1_blend_family_blues, + t1_blend_family_other_blues, + t1_blend_force_bold, + + /* never remove */ + t1_blend_max + + } T1_Blend_Flags; + + + /* maximum number of Multiple Masters designs, as defined in the spec */ +#define T1_MAX_MM_DESIGNS 16 + + /* maximum number of Multiple Masters axes, as defined in the spec */ +#define T1_MAX_MM_AXIS 4 + + /* maximum number of elements in a design map */ +#define T1_MAX_MM_MAP_POINTS 20 + + + /* this structure is used to store the BlendDesignMap entry for an axis */ + typedef struct T1_DesignMap_ + { + FT_Byte num_points; + FT_Fixed* design_points; + FT_Fixed* blend_points; + + } T1_DesignMap; + + + typedef struct T1_Blend_ + { + FT_UInt num_designs; + FT_UInt num_axis; + + FT_String* axis_names[T1_MAX_MM_AXIS]; + FT_Fixed* design_pos[T1_MAX_MM_DESIGNS]; + T1_DesignMap design_map[T1_MAX_MM_AXIS]; + + FT_Fixed* weight_vector; + FT_Fixed* default_weight_vector; + + T1_FontInfo* font_infos[T1_MAX_MM_DESIGNS + 1]; + T1_Private* privates [T1_MAX_MM_DESIGNS + 1]; + + FT_ULong blend_bitflags; + + } T1_Blend; + + + typedef struct CID_FontDict_ + { + T1_Private private_dict; + + FT_UInt len_buildchar; + FT_Fixed forcebold_threshold; + FT_Pos stroke_width; + FT_Fixed expansion_factor; + + FT_Byte paint_type; + FT_Byte font_type; + FT_Matrix font_matrix; + + FT_UInt num_subrs; + FT_ULong subrmap_offset; + FT_Int sd_bytes; + + } CID_FontDict; + + + typedef struct CID_Info_ + { + FT_String* cid_font_name; + FT_Fixed cid_version; + FT_Int cid_font_type; + + FT_String* registry; + FT_String* ordering; + FT_Int supplement; + + T1_FontInfo font_info; + FT_BBox font_bbox; + FT_ULong uid_base; + + FT_Int num_xuid; + FT_ULong xuid[16]; + + + FT_ULong cidmap_offset; + FT_Int fd_bytes; + FT_Int gd_bytes; + FT_ULong cid_count; + + FT_Int num_dicts; + CID_FontDict* font_dicts; + + FT_ULong data_offset; + + } CID_Info; + + +#endif /* T1TABLES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/ttnameid.h b/subsys/win32k/freetype/include/freetype/ttnameid.h new file mode 100644 index 0000000..4890242 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/ttnameid.h @@ -0,0 +1,698 @@ +/***************************************************************************/ +/* */ +/* ttmakeid.h */ +/* */ +/* TrueType name ID definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTNAMEID_H +#define TTNAMEID_H + + + /*************************************************************************/ + /* */ + /* Possible values for the `platform' identifier code in the name */ + /* records of the TTF `name' table. */ + /* */ +#define TT_PLATFORM_APPLE_UNICODE 0 +#define TT_PLATFORM_MACINTOSH 1 +#define TT_PLATFORM_ISO 2 /* deprecated */ +#define TT_PLATFORM_MICROSOFT 3 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_APPLE_UNICODE. */ + /* */ +#define TT_APPLE_ID_DEFAULT 0 +#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */ +#define TT_APPLE_ID_ISO_10646 2 /* deprecated */ +#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */ + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_MACINTOSH. */ + /* */ +#define TT_MAC_ID_ROMAN 0 +#define TT_MAC_ID_JAPANESE 1 +#define TT_MAC_ID_TRADITIONAL_CHINESE 2 +#define TT_MAC_ID_KOREAN 3 +#define TT_MAC_ID_ARABIC 4 +#define TT_MAC_ID_HEBREW 5 +#define TT_MAC_ID_GREEK 6 +#define TT_MAC_ID_RUSSIAN 7 +#define TT_MAC_ID_RSYMBOL 8 +#define TT_MAC_ID_DEVANAGARI 9 +#define TT_MAC_ID_GURMUKHI 10 +#define TT_MAC_ID_GUJARATI 11 +#define TT_MAC_ID_ORIYA 12 +#define TT_MAC_ID_BENGALI 13 +#define TT_MAC_ID_TAMIL 14 +#define TT_MAC_ID_TELUGU 15 +#define TT_MAC_ID_KANNADA 16 +#define TT_MAC_ID_MALAYALAM 17 +#define TT_MAC_ID_SINHALESE 18 +#define TT_MAC_ID_BURMESE 19 +#define TT_MAC_ID_KHMER 20 +#define TT_MAC_ID_THAI 21 +#define TT_MAC_ID_LAOTIAN 22 +#define TT_MAC_ID_GEORGIAN 23 +#define TT_MAC_ID_ARMENIAN 24 +#define TT_MAC_ID_MALDIVIAN 25 +#define TT_MAC_ID_SIMPLIFIED_CHINESE 25 +#define TT_MAC_ID_TIBETAN 26 +#define TT_MAC_ID_MONGOLIAN 27 +#define TT_MAC_ID_GEEZ 28 +#define TT_MAC_ID_SLAVIC 29 +#define TT_MAC_ID_VIETNAMESE 30 +#define TT_MAC_ID_SINDHI 31 +#define TT_MAC_ID_UNINTERP 32 + + + /*************************************************************************/ + /* */ + /* Possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_ISO. */ + /* */ + /* This use is now deprecated. */ + /* */ +#define TT_ISO_ID_7BIT_ASCII 0 +#define TT_ISO_ID_10646 1 +#define TT_ISO_ID_8859_1 2 + + + /*************************************************************************/ + /* */ + /* possible values of the platform specific encoding identifier field in */ + /* the name records of the TTF `name' table if the `platform' identifier */ + /* code is TT_PLATFORM_MICROSOFT. */ + /* */ +#define TT_MS_ID_SYMBOL_CS 0 +#define TT_MS_ID_UNICODE_CS 1 +#define TT_MS_ID_SJIS 2 +#define TT_MS_ID_GB2312 3 +#define TT_MS_ID_BIG_5 4 +#define TT_MS_ID_WANSUNG 5 +#define TT_MS_ID_JOHAB 6 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MACINTOSH. */ + /* */ + /* The canonical source for the Apple assigned Language ID's is at */ + /* */ + /* http://fonts.apple.com/TTRefMan/RM06/Chap6name.html */ + /* */ +#define TT_MAC_LANGID_ENGLISH 0 +#define TT_MAC_LANGID_FRENCH 1 +#define TT_MAC_LANGID_GERMAN 2 +#define TT_MAC_LANGID_ITALIAN 3 +#define TT_MAC_LANGID_DUTCH 4 +#define TT_MAC_LANGID_SWEDISH 5 +#define TT_MAC_LANGID_SPANISH 6 +#define TT_MAC_LANGID_DANISH 7 +#define TT_MAC_LANGID_PORTUGUESE 8 +#define TT_MAC_LANGID_NORWEGIAN 9 +#define TT_MAC_LANGID_HEBREW 10 +#define TT_MAC_LANGID_JAPANESE 11 +#define TT_MAC_LANGID_ARABIC 12 +#define TT_MAC_LANGID_FINNISH 13 +#define TT_MAC_LANGID_GREEK 14 +#define TT_MAC_LANGID_ICELANDIC 15 +#define TT_MAC_LANGID_MALTESE 16 +#define TT_MAC_LANGID_TURKISH 17 +#define TT_MAC_LANGID_CROATIAN 18 +#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19 +#define TT_MAC_LANGID_URDU 20 +#define TT_MAC_LANGID_HINDI 21 +#define TT_MAC_LANGID_THAI 22 +#define TT_MAC_LANGID_KOREAN 23 +#define TT_MAC_LANGID_LITHUANIAN 24 +#define TT_MAC_LANGID_POLISH 25 +#define TT_MAC_LANGID_HUNGARIAN 26 +#define TT_MAC_LANGID_ESTONIAN 27 +#define TT_MAC_LANGID_LETTISH 28 +#define TT_MAC_LANGID_SAAMISK 29 +#define TT_MAC_LANGID_FAEROESE 30 +#define TT_MAC_LANGID_FARSI 31 +#define TT_MAC_LANGID_RUSSIAN 32 +#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33 +#define TT_MAC_LANGID_FLEMISH 34 +#define TT_MAC_LANGID_IRISH 35 +#define TT_MAC_LANGID_ALBANIAN 36 +#define TT_MAC_LANGID_ROMANIAN 37 +#define TT_MAC_LANGID_CZECH 38 +#define TT_MAC_LANGID_SLOVAK 39 +#define TT_MAC_LANGID_SLOVENIAN 40 +#define TT_MAC_LANGID_YIDDISH 41 +#define TT_MAC_LANGID_SERBIAN 42 +#define TT_MAC_LANGID_MACEDONIAN 43 +#define TT_MAC_LANGID_BULGARIAN 44 +#define TT_MAC_LANGID_UKRAINIAN 45 +#define TT_MAC_LANGID_BYELORUSSIAN 46 +#define TT_MAC_LANGID_UZBEK 47 +#define TT_MAC_LANGID_KAZAKH 48 +#define TT_MAC_LANGID_AZERBAIJANI 49 +#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49 +#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50 +#define TT_MAC_LANGID_ARMENIAN 51 +#define TT_MAC_LANGID_GEORGIAN 52 +#define TT_MAC_LANGID_MOLDAVIAN 53 +#define TT_MAC_LANGID_KIRGHIZ 54 +#define TT_MAC_LANGID_TAJIKI 55 +#define TT_MAC_LANGID_TURKMEN 56 +#define TT_MAC_LANGID_MONGOLIAN 57 +#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57 +#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58 +#define TT_MAC_LANGID_PASHTO 59 +#define TT_MAC_LANGID_KURDISH 60 +#define TT_MAC_LANGID_KASHMIRI 61 +#define TT_MAC_LANGID_SINDHI 62 +#define TT_MAC_LANGID_TIBETAN 63 +#define TT_MAC_LANGID_NEPALI 64 +#define TT_MAC_LANGID_SANSKRIT 65 +#define TT_MAC_LANGID_MARATHI 66 +#define TT_MAC_LANGID_BENGALI 67 +#define TT_MAC_LANGID_ASSAMESE 68 +#define TT_MAC_LANGID_GUJARATI 69 +#define TT_MAC_LANGID_PUNJABI 70 +#define TT_MAC_LANGID_ORIYA 71 +#define TT_MAC_LANGID_MALAYALAM 72 +#define TT_MAC_LANGID_KANNADA 73 +#define TT_MAC_LANGID_TAMIL 74 +#define TT_MAC_LANGID_TELUGU 75 +#define TT_MAC_LANGID_SINHALESE 76 +#define TT_MAC_LANGID_BURMESE 77 +#define TT_MAC_LANGID_KHMER 78 +#define TT_MAC_LANGID_LAO 79 +#define TT_MAC_LANGID_VIETNAMESE 80 +#define TT_MAC_LANGID_INDONESIAN 81 +#define TT_MAC_LANGID_TAGALOG 82 +#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83 +#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84 +#define TT_MAC_LANGID_AMHARIC 85 +#define TT_MAC_LANGID_TIGRINYA 86 +#define TT_MAC_LANGID_GALLA 87 +#define TT_MAC_LANGID_SOMALI 88 +#define TT_MAC_LANGID_SWAHILI 89 +#define TT_MAC_LANGID_RUANDA 90 +#define TT_MAC_LANGID_RUNDI 91 +#define TT_MAC_LANGID_CHEWA 92 +#define TT_MAC_LANGID_MALAGASY 93 +#define TT_MAC_LANGID_ESPERANTO 94 +#define TT_MAC_LANGID_WELSH 128 +#define TT_MAC_LANGID_BASQUE 129 +#define TT_MAC_LANGID_CATALAN 130 +#define TT_MAC_LANGID_LATIN 131 +#define TT_MAC_LANGID_QUECHUA 132 +#define TT_MAC_LANGID_GUARANI 133 +#define TT_MAC_LANGID_AYMARA 134 +#define TT_MAC_LANGID_TATAR 135 +#define TT_MAC_LANGID_UIGHUR 136 +#define TT_MAC_LANGID_DZONGKHA 137 +#define TT_MAC_LANGID_JAVANESE 138 +#define TT_MAC_LANGID_SUNDANESE 139 + + +#if 0 /* these seem to be errors that have been dropped */ + +#define TT_MAC_LANGID_SCOTTISH_GAELIC 140 +#define TT_MAC_LANGID_IRISH_GAELIC 141 + +#endif + + + /* The following codes are new as of 2000-03-10 */ +#define TT_MAC_LANGID_GALICIAN 140 +#define TT_MAC_LANGID_AFRIKAANS 141 +#define TT_MAC_LANGID_BRETON 142 +#define TT_MAC_LANGID_INUKTITUT 143 +#define TT_MAC_LANGID_SCOTTISH_GAELIC 144 +#define TT_MAC_LANGID_MANX_GAELIC 145 +#define TT_MAC_LANGID_IRISH_GAELIC 146 +#define TT_MAC_LANGID_TONGAN 147 +#define TT_MAC_LANGID_GREEK_POLYTONIC 148 +#define TT_MAC_LANGID_GREELANDIC 149 +#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150 + + + /*************************************************************************/ + /* */ + /* Possible values of the language identifier field in the name records */ + /* of the TTF `name' table if the `platform' identifier code is */ + /* TT_PLATFORM_MICROSOFT. */ + /* */ + /* The canonical source for the MS assigned LCID's is at */ + /* */ + /* http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt */ + /* */ +#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401 +#define TT_MS_LANGID_ARABIC_IRAQ 0x0801 +#define TT_MS_LANGID_ARABIC_EGYPT 0x0c01 +#define TT_MS_LANGID_ARABIC_LIBYA 0x1001 +#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401 +#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801 +#define TT_MS_LANGID_ARABIC_TUNISIA 0x1c01 +#define TT_MS_LANGID_ARABIC_OMAN 0x2001 +#define TT_MS_LANGID_ARABIC_YEMEN 0x2401 +#define TT_MS_LANGID_ARABIC_SYRIA 0x2801 +#define TT_MS_LANGID_ARABIC_JORDAN 0x2c01 +#define TT_MS_LANGID_ARABIC_LEBANON 0x3001 +#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401 +#define TT_MS_LANGID_ARABIC_UAE 0x3801 +#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3c01 +#define TT_MS_LANGID_ARABIC_QATAR 0x4001 +#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402 +#define TT_MS_LANGID_CATALAN_SPAIN 0x0403 +#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404 +#define TT_MS_LANGID_CHINESE_PRC 0x0804 +#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0c04 +#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004 +#define TT_MS_LANGID_CHINESE_MACAU 0x1404 +#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405 +#define TT_MS_LANGID_DANISH_DENMARK 0x0406 +#define TT_MS_LANGID_GERMAN_GERMANY 0x0407 +#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807 +#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0c07 +#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007 +#define TT_MS_LANGID_GERMAN_LIECHTENSTEI 0x1407 +#define TT_MS_LANGID_GREEK_GREECE 0x0408 +#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409 +#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809 +#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0c09 +#define TT_MS_LANGID_ENGLISH_CANADA 0x1009 +#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409 +#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809 +#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1c09 +#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009 +#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409 +#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809 +#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2c09 +#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009 +#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409 +#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040a +#define TT_MS_LANGID_SPANISH_MEXICO 0x080a +#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT 0x0c0a +#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100a +#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140a +#define TT_MS_LANGID_SPANISH_PANAMA 0x180a +#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1c0a +#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200a +#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240a +#define TT_MS_LANGID_SPANISH_PERU 0x280a +#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2c0a +#define TT_MS_LANGID_SPANISH_ECUADOR 0x300a +#define TT_MS_LANGID_SPANISH_CHILE 0x340a +#define TT_MS_LANGID_SPANISH_URUGUAY 0x380a +#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3c0a +#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400a +#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440a +#define TT_MS_LANGID_SPANISH_HONDURAS 0x480a +#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4c0a +#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500a +#define TT_MS_LANGID_FINNISH_FINLAND 0x040b +#define TT_MS_LANGID_FRENCH_FRANCE 0x040c +#define TT_MS_LANGID_FRENCH_BELGIUM 0x080c +#define TT_MS_LANGID_FRENCH_CANADA 0x0c0c +#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100c +#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140c +#define TT_MS_LANGID_FRENCH_MONACO 0x180c +#define TT_MS_LANGID_HEBREW_ISRAEL 0x040d +#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040e +#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040f +#define TT_MS_LANGID_ITALIAN_ITALY 0x0410 +#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810 +#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411 +#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA 0x0412 +#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812 +#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413 +#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414 +#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814 +#define TT_MS_LANGID_POLISH_POLAND 0x0415 +#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416 +#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816 +#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND 0x0417 +#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418 +#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818 +#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419 +#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819 +#define TT_MS_LANGID_CROATIAN_CROATIA 0x041a +#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081a +#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0c1a +#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041b +#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041c +#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041d +#define TT_MS_LANGID_SWEDISH_FINLAND 0x081d +#define TT_MS_LANGID_THAI_THAILAND 0x041e +#define TT_MS_LANGID_TURKISH_TURKEY 0x041f +#define TT_MS_LANGID_URDU_PAKISTAN 0x0420 +#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421 +#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422 +#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423 +#define TT_MS_LANGID_SLOVENE_SLOVENIA 0x0424 +#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425 +#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426 +#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427 +#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827 +#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0428 +#define TT_MS_LANGID_FARSI_IRAN 0x0429 +#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042a +#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042b +#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042c +#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082c +#define TT_MS_LANGID_BASQUE_SPAIN 0x042d +#define TT_MS_LANGID_SORBIAN_GERMANY 0x042e +#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042f +#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430 +#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431 +#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA 0x0432 +#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433 +#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA 0x0434 +#define TT_MS_LANGID_ZULU_SOUTH_AFRICA 0x0435 +#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436 +#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437 +#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438 +#define TT_MS_LANGID_HINDI_INDIA 0x0439 +#define TT_MS_LANGID_MALTESE_MALTA 0x043a +#define TT_MS_LANGID_SAAMI_LAPONIA 0x043b +#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043c +#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083c +#define TT_MS_LANGID_MALAY_MALAYSIA 0x043e +#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083e +#define TT_MS_LANGID_KAZAK_KAZAKSTAN 0x043f +#define TT_MS_LANGID_SWAHILI_KENYA 0x0441 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443 +#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843 +#define TT_MS_LANGID_TATAR_TATARSTAN 0x0444 +#define TT_MS_LANGID_BENGALI_INDIA 0x0445 +#define TT_MS_LANGID_PUNJABI_INDIA 0x0446 +#define TT_MS_LANGID_GUJARATI_INDIA 0x0447 +#define TT_MS_LANGID_ORIYA_INDIA 0x0448 +#define TT_MS_LANGID_TAMIL_INDIA 0x0449 +#define TT_MS_LANGID_TELUGU_INDIA 0x044a +#define TT_MS_LANGID_KANNADA_INDIA 0x044b +#define TT_MS_LANGID_MALAYALAM_INDIA 0x044c +#define TT_MS_LANGID_ASSAMESE_INDIA 0x044d +#define TT_MS_LANGID_MARATHI_INDIA 0x044e +#define TT_MS_LANGID_SANSKRIT_INDIA 0x044f +#define TT_MS_LANGID_KONKANI_INDIA 0x0457 + + + /*************************************************************************/ + /* */ + /* Possible values of the `name' identifier field in the name records of */ + /* the TTF `name' table. These values are platform independent. */ + /* */ +#define TT_NAME_ID_COPYRIGHT 0 +#define TT_NAME_ID_FONT_FAMILY 1 +#define TT_NAME_ID_FONT_SUBFAMILY 2 +#define TT_NAME_ID_UNIQUE_ID 3 +#define TT_NAME_ID_FULL_NAME 4 +#define TT_NAME_ID_VERSION_STRING 5 +#define TT_NAME_ID_PS_NAME 6 +#define TT_NAME_ID_TRADEMARK 7 + +/* the following values are from the OpenType spec */ +#define TT_NAME_ID_MANUFACTURER 8 +#define TT_NAME_ID_DESIGNER 9 +#define TT_NAME_ID_DESCRIPTION 10 +#define TT_NAME_ID_VENDOR_URL 11 +#define TT_NAME_ID_DESIGNER_URL 12 +#define TT_NAME_ID_LICENSE 13 +#define TT_NAME_ID_LICENSE_URL 14 +/* number 15 is reserved */ +#define TT_NAME_ID_PREFERRED_FAMILY 16 +#define TT_NAME_ID_PREFERRED_SUBFAMILY 17 +#define TT_NAME_ID_MAC_FULL_NAME 18 + +/* The following code is new as of 2000-01-21 */ +#define TT_NAME_ID_SAMPLE_TEXT 19 + + + /*************************************************************************/ + /* */ + /* Bit mask values for the Unicode Ranges from the TTF `OS2 ' table. */ + /* */ + /* Updated 02-Jul-2000. */ + /* */ + + /* General Scripts Area */ + + /* Bit 0 C0 Controls and Basic Latin */ +#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */ + /* Bit 1 C1 Controls and Latin-1 Supplement */ +#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+00A0-U+00FF */ + /* Bit 2 Latin Extended-A */ +#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */ + /* Bit 3 Latin Extended-B */ +#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */ + /* Bit 4 IPA Extensions */ +#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */ + /* Bit 5 Spacing Modifier Letters */ +#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */ + /* Bit 6 Combining Diacritical Marks */ +#define TT_UCR_COMBINING_DIACRITICS (1L << 6) /* U+0300-U+036F */ + /* Bit 7 Greek */ +#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */ + /* Bit 8 is reserved (was: Greek Symbols and Coptic) */ + /* Bit 9 Cyrillic */ +#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */ + /* Bit 10 Armenian */ +#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */ + /* Bit 11 Hebrew */ +#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */ + /* Bit 12 is reserved (was: Hebrew Extended) */ + /* Bit 13 Arabic */ +#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */ + /* Bit 14 is reserved (was: Arabic Extended) */ + /* Bit 15 Devanagari */ +#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */ + /* Bit 16 Bengali */ +#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */ + /* Bit 17 Gurmukhi */ +#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */ + /* Bit 18 Gujarati */ +#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */ + /* Bit 19 Oriya */ +#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */ + /* Bit 20 Tamil */ +#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */ + /* Bit 21 Telugu */ +#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */ + /* Bit 22 Kannada */ +#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */ + /* Bit 23 Malayalam */ +#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */ + /* Bit 24 Thai */ +#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */ + /* Bit 25 Lao */ +#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */ + /* Bit 26 Georgian */ +#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */ + /* Bit 27 is reserved (was Georgian Extended) */ + /* Bit 28 Hangul Jamo */ +#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */ + /* Bit 29 Latin Extended Additional */ +#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */ + /* Bit 30 Greek Extended */ +#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */ + + /* Symbols Area */ + + /* Bit 31 General Punctuation */ +#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */ + /* Bit 32 Superscripts And Subscripts */ +#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */ + /* Bit 33 Currency Symbols */ +#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */ + /* Bit 34 Combining Diacritical Marks For Symbols */ +#define TT_UCR_COMBINING_DIACRITICS_SYMB (1L << 2) /* U+20D0-U+20FF */ + /* Bit 35 Letterlike Symbols */ +#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */ + /* Bit 36 Number Forms */ +#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */ + /* Bit 37 Arrows */ +#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */ + /* Bit 38 Mathematical Operators */ +#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */ + /* Bit 39 Miscellaneous Technical */ +#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */ + /* Bit 40 Control Pictures */ +#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */ + /* Bit 41 Optical Character Recognition */ +#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */ + /* Bit 42 Enclosed Alphanumerics */ +#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */ + /* Bit 43 Box Drawing */ +#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */ + /* Bit 44 Block Elements */ +#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */ + /* Bit 45 Geometric Shapes */ +#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */ + /* Bit 46 Miscellaneous Symbols */ +#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */ + /* Bit 47 Dingbats */ +#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */ + + /* CJK Phonetics and Symbols Area */ + + /* Bit 48 CJK Symbols And Punctuation */ +#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */ + /* Bit 49 Hiragana */ +#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */ + /* Bit 50 Katakana */ +#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */ + /* Bit 51 Bopomofo + Extended Bopomofo */ +#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */ + /* U+31A0-U+31BF */ + /* Bit 52 Hangul Compatibility Jamo */ +#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */ + /* Bit 53 CJK Miscellaneous */ +#define TT_UCR_CJK_MISC (1L << 21) /* U+3190-U+319F */ + /* Bit 54 Enclosed CJK Letters And Months */ +#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */ + /* Bit 55 CJK Compatibility */ +#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */ + + /* Hangul Syllables Area */ + + /* Bit 56 Hangul */ +#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */ + + /* Surrogates Area */ + + /* Bit 57 Surrogates */ +#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DFFF */ + /* Bit 58 is reserved for Unicode SubRanges */ + + /* CJK Ideographs Area */ + + /* Bit 59 CJK Unified Ideographs + */ + /* CJK Radical Supplement + */ + /* Kangxi Radicals + */ + /* Ideographic Description + */ + /* CJK Unified Ideographs Extension A */ +#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */ + /* U+2E80-U+2EFF */ + /* U+2F00-U+2FDF */ + /* U+2FF0-U+2FFF */ + /* U+34E0-U+4DB5 */ + + /* Private Use Area */ + + /* Bit 60 Private Use */ +#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */ + + /* Compatibility Area and Specials */ + + /* Bit 61 CJK Compatibility Ideographs */ +#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+F900-U+FAFF */ + /* Bit 62 Alphabetic Presentation Forms */ +#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */ + /* Bit 63 Arabic Presentation Forms-A */ +#define TT_UCR_ARABIC_PRESENTATIONS_A (1L << 31) /* U+FB50-U+FDFF */ + /* Bit 64 Combining Half Marks */ +#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */ + /* Bit 65 CJK Compatibility Forms */ +#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE30-U+FE4F */ + /* Bit 66 Small Form Variants */ +#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */ + /* Bit 67 Arabic Presentation Forms-B */ +#define TT_UCR_ARABIC_PRESENTATIONS_B (1L << 3) /* U+FE70-U+FEFE */ + /* Bit 68 Halfwidth And Fullwidth Forms */ +#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */ + /* Bit 69 Specials */ +#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */ + /* Bit 70 Tibetan */ +#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FCF */ + /* Bit 71 Syriac */ +#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */ + /* Bit 72 Thaana */ +#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */ + /* Bit 73 Sinhala */ +#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */ + /* Bit 74 Myanmar */ +#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */ + /* Bit 75 Ethiopic */ +#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+12BF */ + /* Bit 76 Cherokee */ +#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */ + /* Bit 77 Canadian Aboriginal Syllabics */ +#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+14DF */ + /* Bit 78 Ogham */ +#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */ + /* Bit 79 Runic */ +#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */ + /* Bit 80 Khmer */ +#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */ + /* Bit 81 Mongolian */ +#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */ + /* Bit 82 Braille */ +#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */ + /* Bit 83 Yi + Yi Radicals */ +#define TT_UCR_YI (1L << 19) /* U+A000-U+A48C */ + /* U+A490-U+A4CF */ + + + /*************************************************************************/ + /* */ + /* Some compilers have a very limited length of identifiers. */ + /* */ +#if defined( __TURBOC__ ) && __TURBOC__ < 0x0410 || defined( __PACIFIC__ ) +#define HAVE_LIMIT_ON_IDENTS +#endif + + +#ifndef HAVE_LIMIT_ON_IDENTS + + + /*************************************************************************/ + /* */ + /* Here some alias #defines in order to be clearer. */ + /* */ + /* These are not always #defined to stay within the 31 character limit */ + /* which some compilers have. */ + /* */ + /* Credits go to Dave Hoo for pointing out that modern */ + /* Borland compilers (read: from BC++ 3.1 on) can increase this limit. */ + /* If you get a warning with such a compiler, use the -i40 switch. */ + /* */ +#define TT_UCR_ARABIC_PRESENTATION_FORMS_A \ + TT_UCR_ARABIC_PRESENTATIONS_A +#define TT_UCR_ARABIC_PRESENTATION_FORMS_B \ + TT_UCR_ARABIC_PRESENTATIONS_B + +#define TT_UCR_COMBINING_DIACRITICAL_MARKS \ + TT_UCR_COMBINING_DIACRITICS +#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \ + TT_UCR_COMBINING_DIACRITICS_SYMB + + +#endif /* !HAVE_LIMIT_ON_IDENTS */ + + +#endif /* TTNAMEID_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/tttables.h b/subsys/win32k/freetype/include/freetype/tttables.h new file mode 100644 index 0000000..27c46f3 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/tttables.h @@ -0,0 +1,583 @@ +/***************************************************************************/ +/* */ +/* tttables.h */ +/* */ +/* Basic SFNT/TrueType tables definitions and interface */ +/* (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTTABLES_H +#define TTTABLES_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Header */ + /* */ + /* */ + /* A structure used to model a TrueType font header table. All */ + /* fields follow the TrueType specification. */ + /* */ + typedef struct TT_Header_ + { + FT_Fixed Table_Version; + FT_Fixed Font_Revision; + + FT_Long CheckSum_Adjust; + FT_Long Magic_Number; + + FT_UShort Flags; + FT_UShort Units_Per_EM; + + FT_Long Created [2]; + FT_Long Modified[2]; + + FT_Short xMin; + FT_Short yMin; + FT_Short xMax; + FT_Short yMax; + + FT_UShort Mac_Style; + FT_UShort Lowest_Rec_PPEM; + + FT_Short Font_Direction; + FT_Short Index_To_Loc_Format; + FT_Short Glyph_Data_Format; + + } TT_Header; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_HoriHeader */ + /* */ + /* */ + /* A structure used to model a TrueType horizontal header, the `hhea' */ + /* table, as well as the corresponding horizontal metrics table, */ + /* i.e., the `hmtx' table. */ + /* */ + /* */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of all */ + /* glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoAscender' field */ + /* of the OS/2 table instead if you want */ + /* the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the distance */ + /* from the baseline to the bottom-most of */ + /* all glyph points found in the font. It */ + /* is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of the */ + /* glyphs found in the font (maybe ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Width_Max :: This field is the maximum of all advance */ + /* widths found in the font. It can be */ + /* used to compute the maximum width of an */ + /* arbitrary string of text. */ + /* */ + /* min_Left_Side_Bearing :: The minimum left side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Right_Side_Bearing :: The minimum right side bearing of all */ + /* glyphs within the font. */ + /* */ + /* xMax_Extent :: The maximum horizontal extent (i.e., the */ + /* `width' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* Reserved :: 10 reserved bytes. */ + /* */ + /* metric_Data_Format :: Always 0. */ + /* */ + /* number_Of_HMetrics :: Number of HMetrics entries in the `hmtx' */ + /* table -- this value can be smaller than */ + /* the total number of glyphs in the font. */ + /* */ + /* long_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `hmtx' table. */ + /* */ + /* */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_HoriHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Width_Max; /* advance width maximum */ + + FT_Short min_Left_Side_Bearing; /* minimum left-sb */ + FT_Short min_Right_Side_Bearing; /* minimum right-sb */ + FT_Short xMax_Extent; /* xmax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_HMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_HoriHeader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_VertHeader */ + /* */ + /* */ + /* A structure used to model a TrueType vertical header, the `vhea' */ + /* table, as well as the corresponding vertical metrics table, i.e., */ + /* the `vmtx' table. */ + /* */ + /* */ + /* Version :: The table version. */ + /* */ + /* Ascender :: The font's ascender, i.e., the distance */ + /* from the baseline to the top-most of */ + /* all glyph points found in the font. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoAscender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Descender :: The font's descender, i.e., the */ + /* distance from the baseline to the */ + /* bottom-most of all glyph points found */ + /* in the font. It is negative. */ + /* */ + /* This value is invalid in many fonts, as */ + /* it is usually set by the font designer, */ + /* and often reflects only a portion of */ + /* the glyphs found in the font (maybe */ + /* ASCII). */ + /* */ + /* You should use the `sTypoDescender' */ + /* field of the OS/2 table instead if you */ + /* want the correct one. */ + /* */ + /* Line_Gap :: The font's line gap, i.e., the distance */ + /* to add to the ascender and descender to */ + /* get the BTB, i.e., the */ + /* baseline-to-baseline distance for the */ + /* font. */ + /* */ + /* advance_Height_Max :: This field is the maximum of all */ + /* advance heights found in the font. It */ + /* can be used to compute the maximum */ + /* height of an arbitrary string of text. */ + /* */ + /* min_Top_Side_Bearing :: The minimum top side bearing of all */ + /* glyphs within the font. */ + /* */ + /* min_Bottom_Side_Bearing :: The minimum bottom side bearing of all */ + /* glyphs within the font. */ + /* */ + /* yMax_Extent :: The maximum vertical extent (i.e., the */ + /* `height' of a glyph's bounding box) for */ + /* all glyphs in the font. */ + /* */ + /* caret_Slope_Rise :: The rise coefficient of the cursor's */ + /* slope of the cursor (slope=rise/run). */ + /* */ + /* caret_Slope_Run :: The run coefficient of the cursor's */ + /* slope. */ + /* */ + /* Reserved :: 10 reserved bytes. */ + /* */ + /* metric_Data_Format :: Always 0. */ + /* */ + /* number_Of_HMetrics :: Number of VMetrics entries in the */ + /* `vmtx' table -- this value can be */ + /* smaller than the total number of glyphs */ + /* in the font. */ + /* */ + /* long_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* short_metrics :: A pointer into the `vmtx' table. */ + /* */ + /* */ + /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should */ + /* be identical except for the names of their fields which */ + /* are different. */ + /* */ + /* This ensures that a single function in the `ttload' */ + /* module is able to read both the horizontal and vertical */ + /* headers. */ + /* */ + typedef struct TT_VertHeader_ + { + FT_Fixed Version; + FT_Short Ascender; + FT_Short Descender; + FT_Short Line_Gap; + + FT_UShort advance_Height_Max; /* advance height maximum */ + + FT_Short min_Top_Side_Bearing; /* minimum left-sb or top-sb */ + FT_Short min_Bottom_Side_Bearing; /* minimum right-sb or bottom-sb */ + FT_Short yMax_Extent; /* xmax or ymax extents */ + FT_Short caret_Slope_Rise; + FT_Short caret_Slope_Run; + FT_Short caret_Offset; + + FT_Short Reserved[4]; + + FT_Short metric_Data_Format; + FT_UShort number_Of_VMetrics; + + /* The following fields are not defined by the TrueType specification */ + /* but they're used to connect the metrics header to the relevant */ + /* `HMTX' or `VMTX' table. */ + + void* long_metrics; + void* short_metrics; + + } TT_VertHeader; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_OS2 */ + /* */ + /* */ + /* A structure used to model a TrueType OS/2 table. This is the long */ + /* table version. All fields comply to the TrueType specification. */ + /* */ + /* Note that we now support old Mac fonts which do not include an */ + /* OS/2 table. In this case, the `version' field is always set to */ + /* 0xFFFF. */ + /* */ + typedef struct TT_OS2_ + { + FT_UShort version; /* 0x0001 - more or 0xFFFF */ + FT_Short xAvgCharWidth; + FT_UShort usWeightClass; + FT_UShort usWidthClass; + FT_Short fsType; + FT_Short ySubscriptXSize; + FT_Short ySubscriptYSize; + FT_Short ySubscriptXOffset; + FT_Short ySubscriptYOffset; + FT_Short ySuperscriptXSize; + FT_Short ySuperscriptYSize; + FT_Short ySuperscriptXOffset; + FT_Short ySuperscriptYOffset; + FT_Short yStrikeoutSize; + FT_Short yStrikeoutPosition; + FT_Short sFamilyClass; + + FT_Byte panose[10]; + + FT_ULong ulUnicodeRange1; /* Bits 0-31 */ + FT_ULong ulUnicodeRange2; /* Bits 32-63 */ + FT_ULong ulUnicodeRange3; /* Bits 64-95 */ + FT_ULong ulUnicodeRange4; /* Bits 96-127 */ + + FT_Char achVendID[4]; + + FT_UShort fsSelection; + FT_UShort usFirstCharIndex; + FT_UShort usLastCharIndex; + FT_Short sTypoAscender; + FT_Short sTypoDescender; + FT_Short sTypoLineGap; + FT_UShort usWinAscent; + FT_UShort usWinDescent; + + /* only version 1 tables: */ + + FT_ULong ulCodePageRange1; /* Bits 0-31 */ + FT_ULong ulCodePageRange2; /* Bits 32-63 */ + + /* only version 2 tables: */ + + FT_Short sxHeight; + FT_Short sCapHeight; + FT_UShort usDefaultChar; + FT_UShort usBreakChar; + FT_UShort usMaxContext; + + } TT_OS2; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Postscript */ + /* */ + /* */ + /* A structure used to model a TrueType Postscript table. All fields */ + /* comply to the TrueType table. This structure does not reference */ + /* the Postscript glyph names, which can be nevertheless accessed */ + /* with the `ttpost' module. */ + /* */ + typedef struct TT_Postscript_ + { + FT_Fixed FormatType; + FT_Fixed italicAngle; + FT_Short underlinePosition; + FT_Short underlineThickness; + FT_ULong isFixedPitch; + FT_ULong minMemType42; + FT_ULong maxMemType42; + FT_ULong minMemType1; + FT_ULong maxMemType1; + + /* Glyph names follow in the file, but we don't */ + /* load them by default. See the ttpost.c file. */ + + } TT_Postscript; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_PCLT */ + /* */ + /* */ + /* A structure used to model a TrueType PCLT table. All fields */ + /* comply to the TrueType table. */ + /* */ + typedef struct TT_PCLT_ + { + FT_Fixed Version; + FT_ULong FontNumber; + FT_UShort Pitch; + FT_UShort xHeight; + FT_UShort Style; + FT_UShort TypeFamily; + FT_UShort CapHeight; + FT_UShort SymbolSet; + FT_Char TypeFace[16]; + FT_Char CharacterComplement[8]; + FT_Char FileName[6]; + FT_Char StrokeWeight; + FT_Char WidthType; + FT_Byte SerifStyle; + FT_Byte Reserved; + + } TT_PCLT; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_MaxProfile */ + /* */ + /* */ + /* The maximum profile is a table containing many max values which */ + /* can be used to pre-allocate arrays. This ensures that no memory */ + /* allocation occurs during a glyph load. */ + /* */ + /* */ + /* version :: The version number. */ + /* */ + /* numGlyphs :: The number of glyphs in this TrueType */ + /* font. */ + /* */ + /* maxPoints :: The maximum number of points in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositePoints'. */ + /* */ + /* maxContours :: The maximum number of contours in a */ + /* non-composite TrueType glyph. See also */ + /* the structure element */ + /* `maxCompositeContours'. */ + /* */ + /* maxCompositePoints :: The maximum number of points in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxPoints'. */ + /* */ + /* maxCompositeContours :: The maximum number of contours in a */ + /* composite TrueType glyph. See also the */ + /* structure element `maxContours'. */ + /* */ + /* maxZones :: The maximum number of zones used for */ + /* glyph hinting. */ + /* */ + /* maxTwilightPoints :: The maximum number of points in the */ + /* twilight zone used for glyph hinting. */ + /* */ + /* maxStorage :: The maximum number of elements in the */ + /* storage area used for glyph hinting. */ + /* */ + /* maxFunctionDefs :: The maximum number of function */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxInstructionDefs :: The maximum number of instruction */ + /* definitions in the TrueType bytecode for */ + /* this font. */ + /* */ + /* maxStackElements :: The maximum number of stack elements used */ + /* during bytecode interpretation. */ + /* */ + /* maxSizeOfInstructions :: The maximum number of TrueType opcodes */ + /* used for glyph hinting. */ + /* */ + /* maxComponentElements :: An obscure value related to composite */ + /* glyphs definitions. */ + /* */ + /* maxComponentDepth :: An obscure value related to composite */ + /* glyphs definitions. Probably the maximum */ + /* number of simple glyphs in a composite. */ + /* */ + /* */ + /* This structure is only used during font loading. */ + /* */ + typedef struct TT_MaxProfile_ + { + FT_Fixed version; + FT_UShort numGlyphs; + FT_UShort maxPoints; + FT_UShort maxContours; + FT_UShort maxCompositePoints; + FT_UShort maxCompositeContours; + FT_UShort maxZones; + FT_UShort maxTwilightPoints; + FT_UShort maxStorage; + FT_UShort maxFunctionDefs; + FT_UShort maxInstructionDefs; + FT_UShort maxStackElements; + FT_UShort maxSizeOfInstructions; + FT_UShort maxComponentElements; + FT_UShort maxComponentDepth; + + } TT_MaxProfile; + + + typedef enum + { + ft_sfnt_head = 0, + ft_sfnt_maxp = 1, + ft_sfnt_os2 = 2, + ft_sfnt_hhea = 3, + ft_sfnt_vhea = 4, + ft_sfnt_post = 5, + ft_sfnt_pclt = 6, + + sfnt_max /* don't remove */ + + } FT_Sfnt_Tag; + + + /* internal use only */ + typedef void* (*FT_Get_Sfnt_Table_Func)( FT_Face face, + FT_Sfnt_Tag tag ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_Table */ + /* */ + /* */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* */ + /* face :: A handle to the source. */ + /* */ + /* tag :: The index of the SFNT table. */ + /* */ + /* */ + /* A type-less pointer to the table. This will be 0 in case of */ + /* error, or if the corresponding table was not found *OR* loaded */ + /* from the file. */ + /* */ + /* */ + /* The table is owned by the face object and disappears with it. */ + /* */ + /* This function is only useful to access SFNT tables that are loaded */ + /* by the sfnt/truetype/opentype drivers. See FT_Sfnt_tag for a */ + /* list. */ + /* */ + /* You can load any table using the (internal) SFNT_Interface */ + /* structure -- this is available via FT_Get_Module_Interface(). */ + /* */ + FT_EXPORT_DEF( void* ) FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ); + +#ifdef __cplusplus + } +#endif + + +#endif /* TTTABLES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/include/freetype/tttags.h b/subsys/win32k/freetype/include/freetype/tttags.h new file mode 100644 index 0000000..9de9810 --- /dev/null +++ b/subsys/win32k/freetype/include/freetype/tttags.h @@ -0,0 +1,66 @@ +/***************************************************************************/ +/* */ +/* tttags.h */ +/* */ +/* Tags for TrueType tables (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTAGS_H +#define TTAGS_H + + +#include /* for MAKE_TT_TAG() */ + + +#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' ) +#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' ) +#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' ) +#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' ) +#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' ) +#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' ) +#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' ) +#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' ) +#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' ) +#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' ) +#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' ) +#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' ) +#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' ) +#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' ) +#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' ) +#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' ) +#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' ) +#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' ) +#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' ) +#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' ) +#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' ) +#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' ) +#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' ) +#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' ) +#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' ) +#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' ) +#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) +#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' ) +#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' ) +#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' ) +#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' ) +#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' ) +#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' ) +#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' ) +#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' ) +#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' ) + +#endif /* TTAGS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/license.txt b/subsys/win32k/freetype/license.txt new file mode 100644 index 0000000..f14087b --- /dev/null +++ b/subsys/win32k/freetype/license.txt @@ -0,0 +1,164 @@ + The FreeType Project LICENSE + ---------------------------- + + 2000-Feb-08 + + Copyright 1996-2000 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we are be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`LICENSE.TXT') unaltered; any additions, deletions or changes + to the original files must be clearly indicated in + accompanying documentation. The copyright notices of the + unaltered, original files must be preserved in all copies of + source files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@freetype.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o devel@freetype.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + o http://www.freetype.org + + Holds the current FreeType web page, which will allow you to + download our latest development version and read online + documentation. + + You can also contact us individually at: + + David Turner + Robert Wilhelm + Werner Lemberg + + +--- end of LICENSE.TXT --- diff --git a/subsys/win32k/freetype/obj/README b/subsys/win32k/freetype/obj/README new file mode 100644 index 0000000..91fdcbd --- /dev/null +++ b/subsys/win32k/freetype/obj/README @@ -0,0 +1 @@ +This directory contains all the object files created when building the library diff --git a/subsys/win32k/freetype/src/autohint/.cvsignore b/subsys/win32k/freetype/src/autohint/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/autohint/CatharonLicense.txt b/subsys/win32k/freetype/src/autohint/CatharonLicense.txt new file mode 100644 index 0000000..e68bc23 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/CatharonLicense.txt @@ -0,0 +1,123 @@ + The Catharon Open Source LICENSE + ---------------------------- + + 2000-Jul-04 + + Copyright (C) 2000 by Catharon Productions, Inc. + + + +Introduction +============ + + This license applies to source files distributed by Catharon + Productions, Inc. in several archive packages. This license + applies to all files found in such packages which do not fall + under their own explicit license. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we are + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + Catharon Code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering the packages distributed by + Catharon Productions, Inc. and assume no liability related to + their use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `Catharon Package', `package', + and `Catharon Code' refer to the set of files originally + distributed by Catharon Productions, Inc. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using one of the + Catharon Packages'. + + This license applies to all files distributed in the original + Catharon Package(s), including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The Catharon Packages are copyright (C) 2000 by Catharon + Productions, Inc. All rights reserved except as specified below. + +1. No Warranty +-------------- + + THE CATHARON PACKAGES ARE PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OF OR THE INABILITY TO + USE THE CATHARON PACKAGE. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the Catharon Packages (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`license.txt') unaltered; any additions, deletions or changes + to the original files must be clearly indicated in + accompanying documentation. The copyright notices of the + unaltered, original files must be preserved in all copies of + source files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part on the work of + Catharon Productions, Inc. in the distribution documentation. + + These conditions apply to any software derived from or based on + the Catharon Packages, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither Catharon Productions, Inc. and contributors nor you shall + use the name of the other for commercial, advertising, or + promotional purposes without specific prior written permission. + + We suggest, but do not require, that you use the following phrase + to refer to this software in your documentation: 'this software is + based in part on the Catharon Typography Project'. + + As you have not signed this license, you are not required to + accept it. However, as the Catharon Packages are copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the Catharon + Packages, you indicate that you understand and accept all the + terms of this license. + +--- end of license.txt --- diff --git a/subsys/win32k/freetype/src/autohint/ahangles.c b/subsys/win32k/freetype/src/autohint/ahangles.c new file mode 100644 index 0000000..d50dc5b --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahangles.c @@ -0,0 +1,137 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (body). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahangles.h" + +#else + +#include + +#endif + + + /* the following table has been automatically generated with */ + /* the `mather.py' Python script */ + + const AH_Angle ah_arctan[1L << AH_ATAN_BITS] = + { + 0, 0, 1, 1, 1, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 5, + 5, 5, 6, 6, 6, 7, 7, 7, + 8, 8, 8, 9, 9, 9, 10, 10, + 10, 10, 11, 11, 11, 12, 12, 12, + 13, 13, 13, 14, 14, 14, 14, 15, + 15, 15, 16, 16, 16, 17, 17, 17, + 18, 18, 18, 18, 19, 19, 19, 20, + 20, 20, 21, 21, 21, 21, 22, 22, + 22, 23, 23, 23, 24, 24, 24, 24, + 25, 25, 25, 26, 26, 26, 26, 27, + 27, 27, 28, 28, 28, 28, 29, 29, + 29, 30, 30, 30, 30, 31, 31, 31, + 31, 32, 32, 32, 33, 33, 33, 33, + 34, 34, 34, 34, 35, 35, 35, 35, + 36, 36, 36, 36, 37, 37, 37, 38, + 38, 38, 38, 39, 39, 39, 39, 40, + 40, 40, 40, 41, 41, 41, 41, 42, + 42, 42, 42, 42, 43, 43, 43, 43, + 44, 44, 44, 44, 45, 45, 45, 45, + 46, 46, 46, 46, 46, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 49, + 49, 49, 50, 50, 50, 50, 50, 51, + 51, 51, 51, 51, 52, 52, 52, 52, + 52, 53, 53, 53, 53, 53, 54, 54, + 54, 54, 54, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, + 57, 57, 57, 58, 58, 58, 58, 58, + 59, 59, 59, 59, 59, 59, 60, 60, + 60, 60, 60, 61, 61, 61, 61, 61, + 61, 62, 62, 62, 62, 62, 62, 63, + 63, 63, 63, 63, 63, 64, 64, 64 + }; + + + LOCAL_FUNC + AH_Angle ah_angle( FT_Vector* v ) + { + FT_Pos dx, dy; + AH_Angle angle; + + + dx = v->x; + dy = v->y; + + /* check trivial cases */ + if ( dy == 0 ) + { + angle = 0; + if ( dx < 0 ) + angle = AH_PI; + return angle; + } + else if ( dx == 0 ) + { + angle = AH_HALF_PI; + if ( dy < 0 ) + angle = -AH_HALF_PI; + return angle; + } + + angle = 0; + if ( dx < 0 ) + { + dx = -v->x; + dy = -v->y; + angle = AH_PI; + } + + if ( dy < 0 ) + { + FT_Pos tmp; + + + tmp = dx; + dx = -dy; + dy = tmp; + angle -= AH_HALF_PI; + } + + if ( dx == 0 && dy == 0 ) + return 0; + + if ( dx == dy ) + angle += AH_PI / 4; + else if ( dx > dy ) + angle += ah_arctan[FT_DivFix( dy, dx ) >> ( 16 - AH_ATAN_BITS )]; + else + angle += AH_HALF_PI - + ah_arctan[FT_DivFix( dx, dy ) >> ( 16 - AH_ATAN_BITS )]; + + if ( angle > AH_PI ) + angle -= AH_2PI; + + return angle; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahangles.h b/subsys/win32k/freetype/src/autohint/ahangles.h new file mode 100644 index 0000000..1df15d4 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahangles.h @@ -0,0 +1,63 @@ +/***************************************************************************/ +/* */ +/* ahangles.h */ +/* */ +/* A routine used to compute vector angles with limited accuracy */ +/* and very high speed (specification). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHANGLES_H +#define AHANGLES_H + + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + +#include + + + /* PI expressed in ah_angles -- we don't really need an important */ + /* precision, so 256 should be enough */ +#define AH_PI 256 +#define AH_2PI ( AH_PI * 2 ) +#define AH_HALF_PI ( AH_PI / 2 ) +#define AH_2PIMASK ( AH_2PI - 1 ) + + /* the number of bits used to express an arc tangent; */ + /* see the structure of the lookup table */ +#define AH_ATAN_BITS 8 + + extern + const AH_Angle ah_arctan[1L << AH_ATAN_BITS]; + + + LOCAL_DEF + AH_Angle ah_angle( FT_Vector* v ); + + +#endif /* AHANGLES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahglobal.c b/subsys/win32k/freetype/src/autohint/ahglobal.c new file mode 100644 index 0000000..1ddc43f --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahglobal.c @@ -0,0 +1,402 @@ +/***************************************************************************/ +/* */ +/* ahglobal.c */ +/* */ +/* Routines used to compute global metrics automatically (body). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahglobal.h" +#include "ahglyph.h" + +#else + +#include +#include + +#endif + + +#define MAX_TEST_CHARACTERS 12 + + static + const char* blue_chars[ah_blue_max] = + { + "THEZOCQS", + "HEZLOCUS", + "xzroesc", + "xzroesc", + "pqgjy" + }; + + + /* simple insertion sort */ + static + void sort_values( FT_Int count, + FT_Pos* table ) + { + FT_Int i, j, swap; + + + for ( i = 1; i < count; i++ ) + { + for ( j = i; j > 1; j-- ) + { + if ( table[j] > table[j - 1] ) + break; + + swap = table[j]; + table[j] = table[j - 1]; + table[j - 1] = swap; + } + } + } + + + static + FT_Error ah_hinter_compute_blues( AH_Hinter* hinter ) + { + AH_Blue blue; + AH_Globals* globals = &hinter->globals->design; + FT_Pos flats [MAX_TEST_CHARACTERS]; + FT_Pos rounds[MAX_TEST_CHARACTERS]; + FT_Int num_flats; + FT_Int num_rounds; + + FT_Face face; + FT_GlyphSlot glyph; + FT_Error error; + FT_CharMap charmap; + + + face = hinter->face; + glyph = face->glyph; + + /* save current charmap */ + charmap = face->charmap; + + /* do we have a Unicode charmap in there? */ + error = FT_Select_Charmap( face, ft_encoding_unicode ); + if ( error ) + goto Exit; + + /* we compute the blues simply by loading each character from the */ + /* 'blue_chars[blues]' string, then compute its top-most and */ + /* bottom-most points */ + + AH_LOG(( "blue zones computation\n" )); + AH_LOG(( "------------------------------------------------\n" )); + + for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ ) + { + const char* p = blue_chars[blue]; + const char* limit = p + MAX_TEST_CHARACTERS; + FT_Pos *blue_ref, *blue_shoot; + + + AH_LOG(( "blue %3d: ", blue )); + + num_flats = 0; + num_rounds = 0; + + for ( ; p < limit; p++ ) + { + FT_UInt glyph_index; + FT_Vector* extremum; + FT_Vector* points; + FT_Vector* point_limit; + FT_Vector* point; + FT_Bool round; + + + /* exit if we reach the end of the string */ + if ( !*p ) + break; + + AH_LOG(( "`%c'", *p )); + + /* load the character in the face -- skip unknown or empty ones */ + glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p ); + if ( glyph_index == 0 ) + continue; + + error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); + if ( error || glyph->outline.n_points <= 0 ) + continue; + + /* now compute min or max point indices and coordinates */ + points = glyph->outline.points; + point_limit = points + glyph->outline.n_points; + point = points; + extremum = point; + point++; + + if ( AH_IS_TOP_BLUE( blue ) ) + { + for ( ; point < point_limit; point++ ) + if ( point->y > extremum->y ) + extremum = point; + } + else + { + for ( ; point < point_limit; point++ ) + if ( point->y < extremum->y ) + extremum = point; + } + + AH_LOG(( "%5d", (int)extremum->y )); + + /* now, check whether the point belongs to a straight or round */ + /* segment; we first need to find in which contour the extremum */ + /* lies, then see its previous and next points */ + { + FT_Int index = extremum - points; + FT_Int n; + FT_Int first, last, prev, next, end; + FT_Pos dist; + + + last = -1; + first = 0; + + for ( n = 0; n < glyph->outline.n_contours; n++ ) + { + end = glyph->outline.contours[n]; + if ( end >= index ) + { + last = end; + break; + } + first = end + 1; + } + + /* XXX: should never happen! */ + if ( last < 0 ) + continue; + + /* now look for the previous and next points that are not on the */ + /* same Y coordinate. Threshold the `closeness'... */ + + prev = index; + next = prev; + + do + { + if ( prev > first ) + prev--; + else + prev = last; + + dist = points[prev].y - extremum->y; + if ( dist < -5 || dist > 5 ) + break; + + } while ( prev != index ); + + do + { + if ( next < last ) + next++; + else + next = first; + + dist = points[next].y - extremum->y; + if ( dist < -5 || dist > 5 ) + break; + + } while ( next != index ); + + /* now, set the `round' flag depending on the segment's kind */ + round = + FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_Curve_Tag_On || + FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_Curve_Tag_On ; + + AH_LOG(( "%c ", round ? 'r' : 'f' )); + } + + if ( round ) + rounds[num_rounds++] = extremum->y; + else + flats[num_flats++] = extremum->y; + } + + AH_LOG(( "\n" )); + + /* we have computed the contents of the `rounds' and `flats' tables, */ + /* now determine the reference and overshoot position of the blue; */ + /* we simply take the median value after a simple short */ + sort_values( num_rounds, rounds ); + sort_values( num_flats, flats ); + + blue_ref = globals->blue_refs + blue; + blue_shoot = globals->blue_shoots + blue; + if ( num_flats == 0 && num_rounds == 0 ) + { + *blue_ref = -10000; + *blue_shoot = -10000; + } + else if ( num_flats == 0 ) + { + *blue_ref = + *blue_shoot = rounds[num_rounds / 2]; + } + else if ( num_rounds == 0 ) + { + *blue_ref = + *blue_shoot = flats[num_flats / 2]; + } + else + { + *blue_ref = flats[num_flats / 2]; + *blue_shoot = rounds[num_rounds / 2]; + } + + /* there are sometimes problems: if the overshoot position of top */ + /* zones is under its reference position, or the opposite for bottom */ + /* zones. We must thus check everything there and correct the errors */ + if ( *blue_shoot != *blue_ref ) + { + FT_Pos ref = *blue_ref; + FT_Pos shoot = *blue_shoot; + FT_Bool over_ref = ( shoot > ref ); + + + if ( AH_IS_TOP_BLUE( blue ) ^ over_ref ) + *blue_shoot = *blue_ref = ( shoot + ref ) / 2; + } + + AH_LOG(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot )); + } + + /* reset original face charmap */ + FT_Set_Charmap( face, charmap ); + error = 0; + + Exit: + return error; + } + + + static + FT_Error ah_hinter_compute_widths( AH_Hinter* hinter ) + { + /* scan the array of segments in each direction */ + AH_Outline* outline = hinter->glyph; + AH_Segment* segments; + AH_Segment* limit; + AH_Globals* globals = &hinter->globals->design; + FT_Pos* widths; + FT_Int dimension; + FT_Int* p_num_widths; + FT_Error error = 0; + FT_Pos edge_distance_threshold = 32000; + + + globals->num_widths = 0; + globals->num_heights = 0; + + /* For now, compute the standard width and height from the `o' */ + /* character. I started computing the stem width of the `i' and the */ + /* stem height of the "-", but it wasn't too good. Moreover, we now */ + /* have a single character that gives us standard width and height. */ + { + FT_UInt glyph_index; + + + glyph_index = FT_Get_Char_Index( hinter->face, 'o' ); + if ( glyph_index == 0 ) + return 0; + + error = FT_Load_Glyph( hinter->face, glyph_index, FT_LOAD_NO_SCALE ); + if ( error ) + goto Exit; + + error = ah_outline_load( hinter->glyph, hinter->face ); + if ( error ) + goto Exit; + + ah_outline_compute_segments( hinter->glyph ); + ah_outline_link_segments( hinter->glyph ); + } + + segments = outline->horz_segments; + limit = segments + outline->num_hsegments; + widths = globals->heights; + p_num_widths = &globals->num_heights; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment* seg = segments; + AH_Segment* link; + FT_Int num_widths = 0; + + + for ( ; seg < limit; seg++ ) + { + link = seg->link; + /* we only consider stem segments there! */ + if ( link && link->link == seg && link > seg ) + { + FT_Int dist; + + + dist = seg->pos - link->pos; + if ( dist < 0 ) + dist = -dist; + + if ( num_widths < 12 ) + widths[num_widths++] = dist; + } + } + + sort_values( num_widths, widths ); + *p_num_widths = num_widths; + + /* we will now try to find the smallest width */ + if ( num_widths > 0 && widths[0] < edge_distance_threshold ) + edge_distance_threshold = widths[0]; + + segments = outline->vert_segments; + limit = segments + outline->num_vsegments; + widths = globals->widths; + p_num_widths = &globals->num_widths; + + } + + /* Now, compute the edge distance threshold as a fraction of the */ + /* smallest width in the font. Set it in `hinter.glyph' too! */ + if ( edge_distance_threshold == 32000 ) + edge_distance_threshold = 50; + + /* let's try 20% */ + hinter->glyph->edge_distance_threshold = edge_distance_threshold / 5; + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ) + { + return ah_hinter_compute_widths( hinter ) || + ah_hinter_compute_blues ( hinter ); + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahglobal.h b/subsys/win32k/freetype/src/autohint/ahglobal.h new file mode 100644 index 0000000..328bd89 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahglobal.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ahglobal.h */ +/* */ +/* Routines used to compute global metrics automatically */ +/* (specification). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHGLOBAL_H +#define AHGLOBAL_H + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + +#include /* for LOCAL_DEF/LOCAL_FUNC */ + + +#define AH_IS_TOP_BLUE( b ) ( (b) == ah_blue_capital_top || \ + (b) == ah_blue_small_top ) + + + /* compute global metrics automatically */ + LOCAL_DEF + FT_Error ah_hinter_compute_globals( AH_Hinter* hinter ); + + +#endif /* AHGLOBAL_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahglyph.c b/subsys/win32k/freetype/src/autohint/ahglyph.c new file mode 100644 index 0000000..f7f011e --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahglyph.c @@ -0,0 +1,1299 @@ +/***************************************************************************/ +/* */ +/* ahglyph.c */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (body). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahglyph.h" +#include "ahangles.h" +#include "ahglobal.h" + +#else + +#include +#include +#include + +#endif + + +#include + + +#define xxxAH_DEBUG_GLYPH + + + /* compute the direction value of a given vector.. */ + static + AH_Direction ah_compute_direction( FT_Pos dx, + FT_Pos dy ) + { + AH_Direction dir; + FT_Pos ax = ABS( dx ); + FT_Pos ay = ABS( dy ); + + + dir = ah_dir_none; + + /* test for vertical direction */ + if ( ax * 12 < ay ) + { + dir = dy > 0 ? ah_dir_up : ah_dir_down; + } + /* test for horizontal direction */ + else if ( ay * 12 < ax ) + { + dir = dx > 0 ? ah_dir_right : ah_dir_left; + } + + return dir; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_new */ + /* */ + /* */ + /* Creates a new and empty AH_Outline object. */ + /* */ + LOCAL_FUNC + FT_Error ah_outline_new( FT_Memory memory, + AH_Outline** aoutline ) + { + FT_Error error; + AH_Outline* outline; + + + if ( !ALLOC( outline, sizeof ( *outline ) ) ) + { + outline->memory = memory; + *aoutline = outline; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_done */ + /* */ + /* */ + /* Destroys a given AH_Outline object. */ + /* */ + LOCAL_FUNC + void ah_outline_done( AH_Outline* outline ) + { + FT_Memory memory = outline->memory; + + + FREE( outline->horz_edges ); + FREE( outline->horz_segments ); + FREE( outline->contours ); + FREE( outline->points ); + + FREE( outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_save */ + /* */ + /* */ + /* Saves the content of a given AH_Outline object into a face's glyph */ + /* slot. */ + /* */ + LOCAL_FUNC + void ah_outline_save( AH_Outline* outline, + AH_Loader* gloader ) + { + AH_Point* point = outline->points; + AH_Point* limit = point + outline->num_points; + FT_Vector* vec = gloader->current.outline.points; + char* tag = gloader->current.outline.tags; + + + /* we assume that the glyph loader has already been checked for storage */ + for ( ; point < limit; point++, vec++, tag++ ) + { + vec->x = point->x; + vec->y = point->y; + + if ( point->flags & ah_flah_conic ) + tag[0] = FT_Curve_Tag_Conic; + else if ( point->flags & ah_flah_cubic ) + tag[0] = FT_Curve_Tag_Cubic; + else + tag[0] = FT_Curve_Tag_On; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_load */ + /* */ + /* */ + /* Loads an unscaled outline from a glyph slot into an AH_Outline */ + /* object. */ + /* */ + LOCAL_FUNC + FT_Error ah_outline_load( AH_Outline* outline, + FT_Face face ) + { + FT_Memory memory = outline->memory; + FT_Error error = FT_Err_Ok; + FT_Outline* source = &face->glyph->outline; + FT_Int num_points = source->n_points; + FT_Int num_contours = source->n_contours; + AH_Point* points; + + + /* check arguments */ + if ( !face || + !face->size || + face->glyph->format != ft_glyph_format_outline ) + return FT_Err_Invalid_Argument; + + /* first of all, reallocate the contours array if necessary */ + if ( num_contours > outline->max_contours ) + { + FT_Int new_contours = ( num_contours + 3 ) & -4; + + + if ( REALLOC_ARRAY( outline->contours, outline->max_contours, + new_contours, AH_Point* ) ) + goto Exit; + + outline->max_contours = new_contours; + } + + /* then, realloc the points, segments & edges arrays if needed */ + if ( num_points > outline->max_points ) + { + FT_Int news = ( num_points + 7 ) & -8; + FT_Int max = outline->max_points; + + + if ( REALLOC_ARRAY( outline->points, max, news, AH_Point ) || + REALLOC_ARRAY( outline->horz_edges, max, news, AH_Edge ) || + REALLOC_ARRAY( outline->horz_segments, max, news, AH_Segment ) ) + goto Exit; + + /* readjust some pointers */ + outline->vert_edges = outline->horz_edges + ( news >> 1 ); + outline->vert_segments = outline->horz_segments + ( news >> 1 ); + outline->max_points = news; + } + + outline->num_points = num_points; + outline->num_contours = num_contours; + + outline->num_hedges = 0; + outline->num_vedges = 0; + outline->num_hsegments = 0; + outline->num_vsegments = 0; + + /* Compute the vertical and horizontal major directions; this is */ + /* currently done by inspecting the `ft_outline_reverse_fill' flag. */ + /* However, some fonts have improper glyphs, and it'd be a good idea */ + /* to be able to re-compute these values on the fly. */ + outline->vert_major_dir = ah_dir_up; + outline->horz_major_dir = ah_dir_left; + + if ( source->flags & ft_outline_reverse_fill ) + { + outline->vert_major_dir = ah_dir_down; + outline->horz_major_dir = ah_dir_right; + } + + outline->x_scale = face->size->metrics.x_scale; + outline->y_scale = face->size->metrics.y_scale; + + points = outline->points; + + { + /* do one thing at a time -- it is easier to understand, and */ + /* the code is clearer */ + AH_Point* point = points; + AH_Point* limit = point + outline->num_points; + + + /* compute coordinates */ + { + FT_Vector* vec = source->points; + FT_Fixed x_scale = outline->x_scale; + FT_Fixed y_scale = outline->y_scale; + + + for (; point < limit; vec++, point++ ) + { + point->fx = vec->x; + point->fy = vec->y; + point->ox = point->x = FT_MulFix( vec->x, x_scale ); + point->oy = point->y = FT_MulFix( vec->y, y_scale ); + + point->flags = 0; + } + } + + /* compute Bezier flags */ + { + char* tag = source->tags; + + + for ( point = points; point < limit; point++, tag++ ) + { + switch ( FT_CURVE_TAG( *tag ) ) + { + case FT_Curve_Tag_Conic: + point->flags = ah_flah_conic; break; + case FT_Curve_Tag_Cubic: + point->flags = ah_flah_cubic; break; + default: + ; + } + } + } + + /* compute `next' and `prev' */ + { + FT_Int contour_index; + AH_Point* prev; + AH_Point* first; + AH_Point* end; + + + contour_index = 0; + + first = points; + end = points + source->contours[0]; + prev = end; + + for ( point = points; point < limit; point++ ) + { + point->prev = prev; + if ( point < end ) + { + point->next = point + 1; + prev = point; + } + else + { + point->next = first; + contour_index++; + if ( point + 1 < limit ) + { + end = points + source->contours[contour_index]; + first = point + 1; + prev = end; + } + } + } + } + + /* set-up the contours array */ + { + AH_Point** contour = outline->contours; + AH_Point** limit = contour + outline->num_contours; + short* end = source->contours; + short index = 0; + + + for ( ; contour < limit; contour++, end++ ) + { + contour[0] = points + index; + index = end[0] + 1; + } + } + + /* compute directions of in & out vectors */ + { + for ( point = points; point < limit; point++ ) + { + AH_Point* prev; + AH_Point* next; + FT_Vector vec; + + + prev = point->prev; + vec.x = point->fx - prev->fx; + vec.y = point->fy - prev->fy; + + point->in_dir = ah_compute_direction( vec.x, vec.y ); + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + point->in_angle = ah_angle( &vec ); +#endif + + next = point->next; + vec.x = next->fx - point->fx; + vec.y = next->fy - point->fy; + + point->out_dir = ah_compute_direction( vec.x, vec.y ); + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + point->out_angle = ah_angle( &vec ); + + { + AH_Angle delta = point->in_angle - point->out_angle; + + + if ( delta < 0 ) + delta = -delta; + if ( delta < 2 ) + point->flags |= ah_flah_weak_interpolation; + } + +#if 0 + if ( point->flags & ( ah_flah_conic | ah_flah_cubic ) ) + point->flags |= ah_flah_weak_interpolation; +#endif + +#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */ + +#ifdef AH_OPTION_NO_STRONG_INTERPOLATION + point->flags |= ah_flah_weak_interpolation; +#endif + } + } + } + + Exit: + return error; + } + + + LOCAL_FUNC + void ah_setup_uv( AH_Outline* outline, + AH_UV source ) + { + AH_Point* point = outline->points; + AH_Point* limit = point + outline->num_points; + + + for ( ; point < limit; point++ ) + { + FT_Pos u, v; + + + switch ( source ) + { + case ah_uv_fxy: + u = point->fx; + v = point->fy; + break; + case ah_uv_fyx: + u = point->fy; + v = point->fx; + break; + case ah_uv_oxy: + u = point->ox; + v = point->oy; + break; + case ah_uv_oyx: + u = point->oy; + v = point->ox; + break; + case ah_uv_yx: + u = point->y; + v = point->x; + break; + case ah_uv_ox: + u = point->x; + v = point->ox; + break; + case ah_uv_oy: + u = point->y; + v = point->oy; + break; + default: + u = point->x; + v = point->y; + break; + } + point->u = u; + point->v = v; + } + } + + + LOCAL_FUNC + void ah_outline_compute_segments( AH_Outline* outline ) + { + int dimension; + AH_Segment* segments; + FT_Int* p_num_segments; + AH_Direction segment_dir; + AH_Direction major_dir; + + + segments = outline->horz_segments; + p_num_segments = &outline->num_hsegments; + major_dir = ah_dir_right; /* This value must be positive! */ + segment_dir = major_dir; + + /* set up (u,v) in each point */ + ah_setup_uv( outline, ah_uv_fyx ); + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Point** contour = outline->contours; + AH_Point** contour_limit = contour + outline->num_contours; + AH_Segment* segment = segments; + FT_Int num_segments = 0; + +#ifdef AH_HINT_METRICS + AH_Point* min_point = 0; + AH_Point* max_point = 0; + FT_Pos min_coord = 32000; + FT_Pos max_coord = -32000; +#endif + + + /* do each contour separately */ + for ( ; contour < contour_limit; contour++ ) + { + AH_Point* point = contour[0]; + AH_Point* last = point->prev; + int on_edge = 0; + FT_Pos min_pos = +32000; /* minimum segment pos != min_coord */ + FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */ + FT_Bool passed; + + +#ifdef AH_HINT_METRICS + if ( point->u < min_coord ) + { + min_coord = point->u; + min_point = point; + } + if ( point->u > max_coord ) + { + max_coord = point->u; + max_point = point; + } +#endif + + if ( point == last ) /* skip singletons -- just in case? */ + continue; + + if ( ABS( last->out_dir ) == major_dir && + ABS( point->out_dir ) == major_dir ) + { + /* we are already on an edge, try to locate its start */ + last = point; + + for (;;) + { + point = point->prev; + if ( ABS( point->out_dir ) != major_dir ) + { + point = point->next; + break; + } + if ( point == last ) + break; + } + + } + + last = point; + passed = 0; + + for (;;) + { + FT_Pos u, v; + + + if ( on_edge ) + { + u = point->u; + if ( u < min_pos ) + min_pos = u; + if ( u > max_pos ) + max_pos = u; + + if ( point->out_dir != segment_dir || point == last ) + { + /* we are just leaving an edge; record a new segment! */ + segment->last = point; + segment->pos = ( min_pos + max_pos ) >> 1; + + /* a segment is round if either its first or last point */ + /* is a control point */ + if ( ( segment->first->flags | point->flags ) & + ah_flah_control ) + segment->flags |= ah_edge_round; + + /* compute segment size */ + min_pos = max_pos = point->v; + + v = segment->first->v; + if ( v < min_pos ) + min_pos = v; + if ( v > max_pos ) + max_pos = v; + + segment->min_coord = min_pos; + segment->max_coord = max_pos; + + on_edge = 0; + num_segments++; + segment++; + /* fallthrough */ + } + } + + /* now exit if we are at the start/end point */ + if ( point == last ) + { + if ( passed ) + break; + passed = 1; + } + + if ( !on_edge && ABS( point->out_dir ) == major_dir ) + { + /* this is the start of a new segment! */ + segment_dir = point->out_dir; + + /* clear all segment fields */ + memset( segment, 0, sizeof ( *segment ) ); + + segment->dir = segment_dir; + segment->flags = ah_edge_normal; + min_pos = max_pos = point->u; + segment->first = point; + segment->last = point; + segment->contour = contour; + on_edge = 1; + + if ( point == max_point ) + max_point = 0; + + if ( point == min_point ) + min_point = 0; + } + + point = point->next; + } + + } /* contours */ + +#ifdef AH_HINT_METRICS + /* we need to ensure that there are edges on the left-most and */ + /* right-most points of the glyph in order to hint the metrics; */ + /* we do this by inserting fake segments when needed */ + if ( dimension == 0 ) + { + AH_Point* point = outline->points; + AH_Point* limit = point + outline->num_points; + + AH_Point* min_point = 0; + AH_Point* max_point = 0; + FT_Pos min_pos = 32000; + FT_Pos max_pos = -32000; + + + /* compute minimum and maximum points */ + for ( ; point < limit; point++ ) + { + FT_Pos x = point->fx; + + + if ( x < min_pos ) + { + min_pos = x; + min_point = point; + } + if ( x > max_pos ) + { + max_pos = x; + max_point = point; + } + } + + /* insert minimum segment */ + if ( min_point ) + { + /* clear all segment fields */ + memset( segment, 0, sizeof ( *segment ) ); + + segment->dir = segment_dir; + segment->flags = ah_edge_normal; + segment->first = min_point; + segment->last = min_point; + segment->pos = min_pos; + + num_segments++; + segment++; + } + + /* insert maximum segment */ + if ( max_point ) + { + /* clear all segment fields */ + memset( segment, 0, sizeof ( *segment ) ); + + segment->dir = segment_dir; + segment->flags = ah_edge_normal; + segment->first = max_point; + segment->last = max_point; + segment->pos = max_pos; + + num_segments++; + segment++; + } + } +#endif /* AH_HINT_METRICS */ + + *p_num_segments = num_segments; + + segments = outline->vert_segments; + major_dir = ah_dir_up; + p_num_segments = &outline->num_vsegments; + ah_setup_uv( outline, ah_uv_fxy ); + } + } + + + LOCAL_FUNC + void ah_outline_link_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* limit; + int dimension; + + + ah_setup_uv( outline, ah_uv_fyx ); + + segments = outline->horz_segments; + limit = segments + outline->num_hsegments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment* seg1; + AH_Segment* seg2; + + + /* now compare each segment to the others */ + for ( seg1 = segments; seg1 < limit; seg1++ ) + { + FT_Pos best_score = 32000; + AH_Segment* best_segment = 0; + + + /* the fake segments are introduced to hint the metrics -- */ + /* we must never link them to anything */ + if ( seg1->first == seg1->last ) + continue; + + for ( seg2 = segments; seg2 < limit; seg2++ ) + if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 ) + { + FT_Pos pos1 = seg1->pos; + FT_Pos pos2 = seg2->pos; + FT_Bool is_dir; + FT_Bool is_pos; + + + /* check that the segments are correctly oriented and */ + /* positioned to form a black distance */ + + is_dir = ( seg1->dir == outline->horz_major_dir || + seg1->dir == outline->vert_major_dir ); + is_pos = pos1 > pos2; + + if ( pos1 == pos2 || !(is_dir ^ is_pos) ) + continue; + + /* Check the two segments. We now have a better algorithm */ + /* that doesn't rely on the segment points themselves but */ + /* on their relative position. This gets rids of many */ + /* unpleasant artefacts and incorrect stem/serifs */ + /* computations. */ + + /* first of all, compute the size of the `common' height */ + { + FT_Pos min = seg1->min_coord; + FT_Pos max = seg1->max_coord; + FT_Pos len, score; + FT_Pos size1, size2; + + + size1 = max - min; + size2 = seg2->max_coord - seg2->min_coord; + + if ( min < seg2->min_coord ) + min = seg2->min_coord; + + if ( max < seg2->max_coord ) + max = seg2->max_coord; + + len = max - min; + score = seg2->pos - seg1->pos; + if ( score < 0 ) + score = -score; + + /* before comparing the scores, take care that the segments */ + /* are really facing each other (often not for italics..) */ + if ( 4 * len >= size1 && 4 * len >= size2 ) + if ( score < best_score ) + { + best_score = score; + best_segment = seg2; + } + } + } + + if ( best_segment ) + { + seg1->link = best_segment; + seg1->score = best_score; + + best_segment->num_linked++; + } + + + } /* edges 1 */ + + /* now, compute the `serif' segments */ + for ( seg1 = segments; seg1 < limit; seg1++ ) + { + seg2 = seg1->link; + + if ( seg2 && seg2->link != seg1 ) + { + seg1->link = 0; + seg1->serif = seg2->link; + } + } + + ah_setup_uv( outline, ah_uv_fxy ); + + segments = outline->vert_segments; + limit = segments + outline->num_vsegments; + } + } + + +#ifdef AH_DEBUG_GLYPH + + /* A function used to dump the array of linked segments */ + void ah_dump_segments( AH_Outline* outline ) + { + AH_Segment* segments; + AH_Segment* limit; + AH_Point* points; + FT_Int dimension; + + + points = outline->points; + segments = outline->horz_segments; + limit = segments + outline->num_hsegments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Segment* seg; + + + printf ( "Table of %s segments:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link | serif |" + " numl | first | start ]\n" ); + + for ( seg = segments; seg < limit; seg++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", + seg - segments, + (int)seg->pos, + seg->dir == ah_dir_up + ? "up" + : ( seg->dir == ah_dir_down + ? "down" + : ( seg->dir == ah_dir_left + ? "left" + : ( seg->dir == ah_dir_right + ? "right" + : "none" ) ) ), + seg->link ? (seg->link-segments) : -1, + seg->serif ? (seg->serif-segments) : -1, + (int)seg->num_linked, + seg->first - points, + seg->last - points ); + } + + segments = outline->vert_segments; + limit = segments + outline->num_vsegments; + } + } + +#endif /* AH_DEBUG_GLYPH */ + + + static + void ah_outline_compute_edges( AH_Outline* outline ) + { + AH_Edge* edges; + AH_Segment* segments; + AH_Segment* segment_limit; + AH_Direction up_dir; + FT_Int* p_num_edges; + FT_Int dimension; + FT_Fixed scale; + FT_Pos edge_distance_threshold; + + + edges = outline->horz_edges; + segments = outline->horz_segments; + segment_limit = segments + outline->num_hsegments; + p_num_edges = &outline->num_hedges; + up_dir = ah_dir_right; + scale = outline->y_scale; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge* edge; + AH_Edge* edge_limit; /* really == edge + num_edges */ + AH_Segment* seg; + + + /*********************************************************************/ + /* */ + /* We will begin by generating a sorted table of edges for the */ + /* current direction. To do so, we simply scan each segment and try */ + /* to find an edge in our table that corresponds to its position. */ + /* */ + /* If no edge is found, we create and insert a new edge in the */ + /* sorted table. Otherwise, we simply add the segment to the edge's */ + /* list which will be processed in the second step to compute the */ + /* edge's properties. */ + /* */ + /* Note that the edges table is sorted along the segment/edge */ + /* position. */ + /* */ + /*********************************************************************/ + + edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold, + scale ); + if ( edge_distance_threshold > 64 / 4 ) + edge_distance_threshold = 64 / 4; + + edge_limit = edges; + for ( seg = segments; seg < segment_limit; seg++ ) + { + AH_Edge* found = 0; + + + /* look for an edge corresponding to the segment */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + FT_Pos dist; + + + dist = seg->pos - edge->fpos; + if ( dist < 0 ) + dist = -dist; + + dist = FT_MulFix( dist, scale ); + if ( dist < edge_distance_threshold ) + { + found = edge; + break; + } + } + + if ( !found ) + { + /* insert a new edge in the list and */ + /* sort according to the position */ + while ( edge > edges && edge[-1].fpos > seg->pos ) + { + edge[0] = edge[-1]; + edge--; + } + edge_limit++; + + /* clear all edge fields */ + memset( edge, 0, sizeof ( *edge ) ); + + /* add the segment to the new edge's list */ + edge->first = seg; + edge->last = seg; + edge->fpos = seg->pos; + edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); + seg->edge_next = seg; + } + else + { + /* if an edge was found, simply add the segment to the edge's */ + /* list */ + seg->edge_next = edge->first; + edge->last->edge_next = seg; + edge->last = seg; + } + } + + *p_num_edges = edge_limit - edges; + + + /*********************************************************************/ + /* */ + /* Good, we will now compute each edge's properties according to */ + /* segments found on its position. Basically, these are: */ + /* */ + /* - edge's main direction */ + /* - stem edge, serif edge or both (which defaults to stem then) */ + /* - rounded edge, straigth or both (which defaults to straight) */ + /* - link for edge */ + /* */ + /*********************************************************************/ + + /* first of all, set the `edge' field in each segment -- this is */ + /* required in order to compute edge links */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + seg = edge->first; + if ( seg ) + do + { + seg->edge = edge; + seg = seg->edge_next; + } + while ( seg != edge->first ); + } + + /* now, compute each edge properties */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + int is_round = 0; /* does it contain round segments? */ + int is_straight = 0; /* does it contain straight segments? */ + int ups = 0; /* number of upwards segments */ + int downs = 0; /* number of downwards segments */ + + + seg = edge->first; + + do + { + FT_Bool is_serif; + + + /* check for roundness of segment */ + if ( seg->flags & ah_edge_round ) + is_round++; + else + is_straight++; + + /* check for segment direction */ + if ( seg->dir == up_dir ) + ups += seg->max_coord-seg->min_coord; + else + downs += seg->max_coord-seg->min_coord; + + /* check for links -- if seg->serif is set, then seg->link must */ + /* be ignored */ + is_serif = seg->serif && seg->serif->edge != edge; + + if ( seg->link || is_serif ) + { + AH_Edge* edge2; + AH_Segment* seg2; + + + edge2 = edge->link; + seg2 = seg->link; + + if ( is_serif ) + { + seg2 = seg->serif; + edge2 = edge->serif; + } + + if ( edge2 ) + { + FT_Pos edge_delta; + FT_Pos seg_delta; + + + edge_delta = edge->fpos - edge2->fpos; + if ( edge_delta < 0 ) + edge_delta = -edge_delta; + + seg_delta = seg->pos - seg2->pos; + if ( seg_delta < 0 ) + seg_delta = -seg_delta; + + if ( seg_delta < edge_delta ) + edge2 = seg2->edge; + } + else + edge2 = seg2->edge; + + if ( is_serif ) + edge->serif = edge2; + else + edge->link = edge2; + } + + seg = seg->edge_next; + + } while ( seg != edge->first ); + + /* set the round/straight flags */ + edge->flags = ah_edge_normal; + + if ( is_straight == 0 && is_round ) + edge->flags |= ah_edge_round; + + /* set the edge's main direction */ + edge->dir = ah_dir_none; + + if ( ups > downs ) + edge->dir = up_dir; + + else if ( ups < downs ) + edge->dir = - up_dir; + + else if ( ups == downs ) + edge->dir = 0; /* both up and down !! */ + + /* gets rid of serifs if link is set */ + /* XXX: This gets rid of many unpleasant artefacts! */ + /* Example: the `c' in cour.pfa at size 13 */ + + if ( edge->serif && edge->link ) + edge->serif = 0; + } + + edges = outline->vert_edges; + segments = outline->vert_segments; + segment_limit = segments + outline->num_vsegments; + p_num_edges = &outline->num_vedges; + up_dir = ah_dir_up; + scale = outline->x_scale; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_detect_features */ + /* */ + /* */ + /* Performs feature detection on a given AH_Outline object. */ + /* */ + LOCAL_FUNC + void ah_outline_detect_features( AH_Outline* outline ) + { + ah_outline_compute_segments( outline ); + ah_outline_link_segments ( outline ); + ah_outline_compute_edges ( outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_compute_blue_edges */ + /* */ + /* */ + /* Computes the `blue edges' in a given outline (i.e. those that must */ + /* be snapped to a blue zone edge (top or bottom). */ + /* */ + LOCAL_FUNC + void ah_outline_compute_blue_edges( AH_Outline* outline, + AH_Face_Globals* face_globals ) + { + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + AH_Globals* globals = &face_globals->design; + FT_Fixed y_scale = outline->y_scale; + + + /* compute for each horizontal edge, which blue zone is closer */ + for ( ; edge < limit; edge++ ) + { + AH_Blue blue; + FT_Pos* best_blue = 0; + FT_Pos best_dist; /* initial threshold */ + + + /* compute the initial threshold as a fraction of the EM size */ + best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale ); + if ( best_dist > 64 / 4 ) + best_dist = 64 / 4; + + for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ ) + { + /* if it is a top zone, check for right edges -- if it is a bottom */ + /* zone, check for left edges */ + /* */ + /* of course, that's for TrueType XXX */ + FT_Bool is_top_blue = AH_IS_TOP_BLUE( blue ); + FT_Bool is_major_dir = edge->dir == outline->horz_major_dir; + + + /* if it is a top zone, the edge must be against the major */ + /* direction; if it is a bottom zone, it must be in the major */ + /* direction */ + if ( is_top_blue ^ is_major_dir ) + { + FT_Pos dist; + FT_Pos* blue_pos = globals->blue_refs + blue; + + + /* first of all, compare it to the reference position */ + dist = edge->fpos - *blue_pos; + if ( dist < 0 ) + dist = -dist; + + dist = FT_MulFix( dist, y_scale ); + if ( dist < best_dist ) + { + best_dist = dist; + best_blue = blue_pos; + } + + /* now, compare it to the overshoot position if the edge is */ + /* rounded, and if the edge is over the reference position of a */ + /* top zone, or under the reference position of a bottom zone */ + if ( edge->flags & ah_edge_round && dist != 0 ) + { + FT_Bool is_under_ref = edge->fpos < *blue_pos; + + + if ( is_top_blue ^ is_under_ref ) + { + blue_pos = globals->blue_shoots + blue; + dist = edge->fpos - *blue_pos; + if ( dist < 0 ) + dist = -dist; + + dist = FT_MulFix( dist, y_scale ); + if ( dist < best_dist ) + { + best_dist = dist; + best_blue = blue_pos; + } + } + } + } + } + + if ( best_blue ) + edge->blue_edge = best_blue; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* ah_outline_scale_blue_edges */ + /* */ + /* */ + /* This functions must be called before hinting in order to re-adjust */ + /* the contents of the detected edges (basically change the `blue */ + /* edge' pointer from `design units' to `scaled ones'). */ + /* */ + LOCAL_FUNC + void ah_outline_scale_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ) + { + AH_Edge* edge = outline->horz_edges; + AH_Edge* limit = edge + outline->num_hedges; + FT_Int delta; + + + delta = globals->scaled.blue_refs - globals->design.blue_refs; + + for ( ; edge < limit; edge++ ) + { + if ( edge->blue_edge ) + edge->blue_edge += delta; + } + } + + +#ifdef AH_DEBUG_GLYPH + + void ah_dump_edges( AH_Outline* outline ) + { + AH_Edge* edges; + AH_Edge* limit; + AH_Segment* segments; + FT_Int dimension; + + + edges = outline->horz_edges; + limit = edges + outline->num_hedges; + segments = outline->horz_segments; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge* edge; + + + printf ( "Table of %s edges:\n", + !dimension ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link |" + " serif | blue | opos | pos ]\n" ); + + for ( edge = edges; edge < limit; edge++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", + edge - edges, + (int)edge->fpos, + edge->dir == ah_dir_up + ? "up" + : ( edge->dir == ah_dir_down + ? "down" + : ( edge->dir == ah_dir_left + ? "left" + : ( edge->dir == ah_dir_right + ? "right" + : "none" ) ) ), + edge->link ? ( edge->link - edges ) : -1, + edge->serif ? ( edge->serif - edges ) : -1, + edge->blue_edge ? 'y' : 'n', + edge->opos / 64.0, + edge->pos / 64.0 ); + } + + edges = outline->vert_edges; + limit = edges + outline->num_vedges; + segments = outline->vert_segments; + } + } + +#endif /* AH_DEBUG_GLYPH */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahglyph.h b/subsys/win32k/freetype/src/autohint/ahglyph.h new file mode 100644 index 0000000..1ce5260 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahglyph.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* ahglyph.h */ +/* */ +/* Routines used to load and analyze a given glyph before hinting */ +/* (specification). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHGLYPH_H +#define AHGLYPH_H + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + + typedef enum AH_UV_ + { + ah_uv_fxy, + ah_uv_fyx, + ah_uv_oxy, + ah_uv_oyx, + ah_uv_ox, + ah_uv_oy, + ah_uv_yx, + ah_uv_xy /* should always be last! */ + + } AH_UV; + + + LOCAL_DEF + void ah_setup_uv( AH_Outline* outline, + AH_UV source ); + + + /* AH_Outline functions - they should be typically called in this order */ + + LOCAL_DEF + FT_Error ah_outline_new( FT_Memory memory, + AH_Outline** aoutline ); + + LOCAL_DEF + FT_Error ah_outline_load( AH_Outline* outline, + FT_Face face ); + + LOCAL_DEF + void ah_outline_compute_segments( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_link_segments( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_detect_features( AH_Outline* outline ); + + LOCAL_DEF + void ah_outline_compute_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ); + + LOCAL_DEF + void ah_outline_scale_blue_edges( AH_Outline* outline, + AH_Face_Globals* globals ); + + LOCAL_DEF + void ah_outline_save( AH_Outline* outline, AH_Loader* loader ); + + LOCAL_DEF + void ah_outline_done( AH_Outline* outline ); + + +#endif /* AHGLYPH_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahhint.c b/subsys/win32k/freetype/src/autohint/ahhint.c new file mode 100644 index 0000000..357a641 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahhint.c @@ -0,0 +1,1398 @@ +/***************************************************************************/ +/* */ +/* ahhint.c */ +/* */ +/* Glyph hinter (body). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ahhint.h" +#include "ahglyph.h" +#include "ahangles.h" + +#else + +#include +#include +#include + +#endif + +#include + + +#define FACE_GLOBALS( face ) ((AH_Face_Globals*)(face)->autohint.data) + +#define AH_USE_IUP + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Hinting routines ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + static int disable_horz_edges = 0; + static int disable_vert_edges = 0; + + + /* snap a given width in scaled coordinates to one of the */ + /* current standard widths */ + static + FT_Pos ah_snap_width( FT_Pos* widths, + FT_Int count, + FT_Pos width ) + { + int n; + FT_Pos best = 64 + 32 + 2; + FT_Pos reference = width; + + + for ( n = 0; n < count; n++ ) + { + FT_Pos w; + FT_Pos dist; + + + w = widths[n]; + dist = width - w; + if ( dist < 0 ) + dist = -dist; + if ( dist < best ) + { + best = dist; + reference = w; + } + } + + if ( width >= reference ) + { + width -= 0x21; + if ( width < reference ) + width = reference; + } + else + { + width += 0x21; + if ( width > reference ) + width = reference; + } + + return width; + } + + + /* align one stem edge relative to the previous stem edge */ + static + void ah_align_linked_edge( AH_Hinter* hinter, + AH_Edge* base_edge, + AH_Edge* stem_edge, + int vertical ) + { + FT_Pos dist = stem_edge->opos - base_edge->opos; + AH_Globals* globals = &hinter->globals->scaled; + FT_Pos sign = 1; + + + if ( dist < 0 ) + { + dist = -dist; + sign = -1; + } + + if ( vertical ) + { + dist = ah_snap_width( globals->heights, globals->num_heights, dist ); + + /* in the case of vertical hinting, always round */ + /* the stem heights to integer pixels */ + if ( dist >= 64 ) + dist = ( dist + 16 ) & -64; + else + dist = 64; + } + else + { + dist = ah_snap_width( globals->widths, globals->num_widths, dist ); + + if ( hinter->flags & ah_hinter_monochrome ) + { + /* monochrome horizontal hinting: snap widths to integer pixels */ + /* with a different threshold */ + if ( dist < 64 ) + dist = 64; + else + dist = ( dist + 32 ) & -64; + } + else + { + /* for horizontal anti-aliased hinting, we adopt a more subtle */ + /* approach: we strengthen small stems, round stems whose size */ + /* is between 1 and 2 pixels to an integer, otherwise nothing */ + if ( dist < 48 ) + dist = ( dist + 64 ) >> 1; + + else if ( dist < 128 ) + dist = ( dist + 42 ) & -64; + } + } + + stem_edge->pos = base_edge->pos + sign * dist; + } + + + static + void ah_align_serif_edge( AH_Hinter* hinter, + AH_Edge* base, + AH_Edge* serif ) + { + FT_Pos dist; + FT_Pos sign = 1; + + UNUSED( hinter ); + + + dist = serif->opos - base->opos; + if ( dist < 0 ) + { + dist = -dist; + sign = -1; + } + + /* do not strengthen serifs */ + if ( base->flags & ah_edge_done ) + { + if ( dist > 64 ) + dist = ( dist + 16 ) & -64; + + else if ( dist <= 32 ) + dist = ( dist + 33 ) >> 1; + } + + serif->pos = base->pos + sign * dist; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** E D G E H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* Another alternative edge hinting algorithm */ + static + void ah_hint_edges_3( AH_Hinter* hinter ) + { + AH_Edge* edges; + AH_Edge* edge_limit; + AH_Outline* outline = hinter->glyph; + FT_Int dimension; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge* edge; + AH_Edge* before = 0; + AH_Edge* after = 0; + AH_Edge* anchor = 0; + int has_serifs = 0; + + + if ( disable_vert_edges && !dimension ) + goto Next_Dimension; + + if ( disable_horz_edges && dimension ) + goto Next_Dimension; + + /* we begin by aligning all stems relative to the blue zone */ + /* if needed -- that's only for horizontal edges */ + if ( dimension ) + { + for ( edge = edges; edge < edge_limit; edge++ ) + { + FT_Pos* blue; + AH_Edge *edge1, *edge2; + + + if ( edge->flags & ah_edge_done ) + continue; + + blue = edge->blue_edge; + edge1 = 0; + edge2 = edge->link; + + if ( blue ) + { + edge1 = edge; + } + else if (edge2 && edge2->blue_edge) + { + blue = edge2->blue_edge; + edge1 = edge2; + edge2 = edge; + } + + if ( !edge1 ) + continue; + + edge1->pos = blue[0]; + edge1->flags |= ah_edge_done; + + if ( edge2 && !edge2->blue_edge ) + { + ah_align_linked_edge( hinter, edge1, edge2, dimension ); + edge2->flags |= ah_edge_done; + } + + if ( !anchor ) + anchor = edge; + } + } + + /* now, we will align all stem edges, trying to maintain the */ + /* relative order of stems in the glyph.. */ + before = 0; + after = 0; + for ( edge = edges; edge < edge_limit; edge++ ) + { + AH_Edge *edge2; + + + if ( edge->flags & ah_edge_done ) + continue; + + /* skip all non-stem edges */ + edge2 = edge->link; + if ( !edge2 ) + { + has_serifs++; + continue; + } + + /* now, align the stem */ + + /* this should not happen, but it's better to be safe.. */ + if ( edge2->blue_edge || edge2 < edge ) + { + +#if 0 + printf( "strange blue alignement, edge %d to %d\n", + edge - edges, edge2 - edges ); +#endif + + ah_align_linked_edge( hinter, edge2, edge, dimension ); + edge->flags |= ah_edge_done; + continue; + } + + { + FT_Bool min = 0; + FT_Pos delta; + + if ( !anchor ) + { + edge->pos = ( edge->opos + 32 ) & -64; + anchor = edge; + } + else + edge->pos = anchor->pos + + ( ( edge->opos - anchor->opos + 32 ) & -64 ); + + edge->flags |= ah_edge_done; + + if ( edge > edges && edge->pos < edge[-1].pos ) + { + edge->pos = edge[-1].pos; + min = 1; + } + + ah_align_linked_edge( hinter, edge, edge2, dimension ); + delta = 0; + if ( edge2 + 1 < edge_limit && + edge2[1].flags & ah_edge_done ) + delta = edge2[1].pos - edge2->pos; + + if ( delta < 0 ) + { + edge2->pos += delta; + if ( !min ) + edge->pos += delta; + } + edge2->flags |= ah_edge_done; + } + } + + if ( !has_serifs ) + goto Next_Dimension; + + /* now, hint the remaining edges (serifs and single) in order */ + /* to complete our processing */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + if ( edge->flags & ah_edge_done ) + continue; + + if ( edge->serif ) + { + ah_align_serif_edge( hinter, edge->serif, edge ); + } + else if ( !anchor ) + { + edge->pos = ( edge->opos + 32 ) & -64; + anchor = edge; + } + else + edge->pos = anchor->pos + + ( ( edge->opos-anchor->opos + 32 ) & -64 ); + + edge->flags |= ah_edge_done; + + if ( edge > edges && edge->pos < edge[-1].pos ) + edge->pos = edge[-1].pos; + + if ( edge + 1 < edge_limit && + edge[1].flags & ah_edge_done && + edge->pos > edge[1].pos ) + edge->pos = edge[1].pos; + } + + Next_Dimension: + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + } + } + + + LOCAL_FUNC + void ah_hinter_hint_edges( AH_Hinter* hinter, + int no_horz_edges, + int no_vert_edges ) + { + disable_horz_edges = no_horz_edges; + disable_vert_edges = no_vert_edges; + + /* AH_Interpolate_Blue_Edges( hinter ); -- doesn't seem to help */ + /* reduce the problem of the disappearing eye in the `e' of Times... */ + /* also, creates some artifacts near the blue zones? */ + { + ah_hint_edges_3( hinter ); + +#if 0 + /* outline optimizer removed temporarily */ + if ( hinter->flags & ah_hinter_optimize ) + { + AH_Optimizer opt; + + + if ( !AH_Optimizer_Init( &opt, hinter->glyph, hinter->memory ) ) + { + AH_Optimizer_Compute( &opt ); + AH_Optimizer_Done( &opt ); + } + } +#endif + + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** P O I N T H I N T I N G ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + static + void ah_hinter_align_edge_points( AH_Hinter* hinter ) + { + AH_Outline* outline = hinter->glyph; + AH_Edge* edges; + AH_Edge* edge_limit; + FT_Int dimension; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Edge* edge; + AH_Edge* before; + AH_Edge* after; + + + before = 0; + after = 0; + + edge = edges; + for ( ; edge < edge_limit; edge++ ) + { + /* move the points of each segment */ + /* in each edge to the edge's position */ + AH_Segment* seg = edge->first; + + + do + { + AH_Point* point = seg->first; + + + for (;;) + { + if ( dimension ) + { + point->y = edge->pos; + point->flags |= ah_flah_touch_y; + } + else + { + point->x = edge->pos; + point->flags |= ah_flah_touch_x; + } + + if ( point == seg->last ) + break; + + point = point->next; + } + + seg = seg->edge_next; + + } while ( seg != edge->first ); + } + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + } + } + + + /* hint the strong points -- this is equivalent to the TrueType `IP' */ + static + void ah_hinter_align_strong_points( AH_Hinter* hinter ) + { + AH_Outline* outline = hinter->glyph; + FT_Int dimension; + AH_Edge* edges; + AH_Edge* edge_limit; + AH_Point* points; + AH_Point* point_limit; + AH_Flags touch_flag; + + + points = outline->points; + point_limit = points + outline->num_points; + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + touch_flag = ah_flah_touch_y; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Point* point; + AH_Edge* edge; + AH_Edge* before; + AH_Edge* after; + + + before = 0; + after = 0; + + if ( edges < edge_limit ) + for ( point = points; point < point_limit; point++ ) + { + FT_Pos u, ou, fu; /* point position */ + FT_Pos delta; + + + if ( point->flags & touch_flag ) + continue; + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + /* if this point is candidate to weak interpolation, we will */ + /* interpolate it after all strong points have been processed */ + if ( point->flags & ah_flah_weak_interpolation ) + continue; +#endif + + if ( dimension ) + { + u = point->fy; + ou = point->oy; + } + else + { + u = point->fx; + ou = point->ox; + } + + fu = u; + + /* is the point before the first edge? */ + edge = edges; + delta = edge->fpos - u; + if ( delta >= 0 ) + { + u = edge->pos - ( edge->opos - ou ); + goto Store_Point; + } + + /* is the point after the last edge ? */ + edge = edge_limit - 1; + delta = u - edge->fpos; + if ( delta >= 0 ) + { + u = edge->pos + ( ou - edge->opos ); + goto Store_Point; + } + + /* otherwise, interpolate the point in between */ + { + AH_Edge* before = 0; + AH_Edge* after = 0; + + + for ( edge = edges; edge < edge_limit; edge++ ) + { + if ( u == edge->fpos ) + { + u = edge->pos; + goto Store_Point; + } + if ( u < edge->fpos ) + break; + before = edge; + } + + for ( edge = edge_limit - 1; edge >= edges; edge-- ) + { + if ( u == edge->fpos ) + { + u = edge->pos; + goto Store_Point; + } + if ( u > edge->fpos ) + break; + after = edge; + } + + /* assert( before && after && before != after ) */ + u = before->pos + FT_MulDiv( fu - before->fpos, + after->pos - before->pos, + after->fpos - before->fpos ); + } + + Store_Point: + + /* save the point position */ + if ( dimension ) + point->y = u; + else + point->x = u; + + point->flags |= touch_flag; + } + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + touch_flag = ah_flah_touch_x; + } + } + + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + + static + void ah_iup_shift( AH_Point* p1, + AH_Point* p2, + AH_Point* ref ) + { + AH_Point* p; + FT_Pos delta = ref->u - ref->v; + + + for ( p = p1; p < ref; p++ ) + p->u = p->v + delta; + + for ( p = ref + 1; p <= p2; p++ ) + p->u = p->v + delta; + } + + + static + void ah_iup_interp( AH_Point* p1, + AH_Point* p2, + AH_Point* ref1, + AH_Point* ref2 ) + { + AH_Point* p; + FT_Pos u; + FT_Pos v1 = ref1->v; + FT_Pos v2 = ref2->v; + FT_Pos d1 = ref1->u - v1; + FT_Pos d2 = ref2->u - v2; + + + if ( p1 > p2 ) + return; + + if ( v1 == v2 ) + { + for ( p = p1; p <= p2; p++ ) + { + FT_Pos u = p->v; + + + if ( u <= v1 ) + u += d1; + else + u += d2; + + p->u = u; + } + return; + } + + if ( v1 < v2 ) + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v1 ) + u += d1; + else if ( u >= v2 ) + u += d2; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); + + p->u = u; + } + } + else + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v2 ) + u += d2; + else if ( u >= v1 ) + u += d1; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); + + p->u = u; + } + } + } + + + /* interpolate weak points -- this is equivalent to the TrueType `IUP' */ + static + void ah_hinter_align_weak_points( AH_Hinter* hinter ) + { + AH_Outline* outline = hinter->glyph; + FT_Int dimension; + AH_Edge* edges; + AH_Edge* edge_limit; + AH_Point* points; + AH_Point* point_limit; + AH_Point** contour_limit; + AH_Flags touch_flag; + + + points = outline->points; + point_limit = points + outline->num_points; + + /* PASS 1: Move segment points to edge positions */ + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + touch_flag = ah_flah_touch_y; + + contour_limit = outline->contours + outline->num_contours; + + ah_setup_uv( outline, ah_uv_oy ); + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Point* point; + AH_Point* end_point; + AH_Point* first_point; + AH_Point** contour; + + + point = points; + contour = outline->contours; + + for ( ; contour < contour_limit; contour++ ) + { + point = *contour; + end_point = point->prev; + first_point = point; + + while ( point <= end_point && !( point->flags & touch_flag ) ) + point++; + + if ( point <= end_point ) + { + AH_Point* first_touched = point; + AH_Point* cur_touched = point; + + + point++; + while ( point <= end_point ) + { + if ( point->flags & touch_flag ) + { + /* we found two successive touched points; we interpolate */ + /* all contour points between them */ + ah_iup_interp( cur_touched + 1, point - 1, + cur_touched, point ); + cur_touched = point; + } + point++; + } + + if ( cur_touched == first_touched ) + { + /* this is a special case: only one point was touched in the */ + /* contour; we thus simply shift the whole contour */ + ah_iup_shift( first_point, end_point, cur_touched ); + } + else + { + /* now interpolate after the last touched point to the end */ + /* of the contour */ + ah_iup_interp( cur_touched + 1, end_point, + cur_touched, first_touched ); + + /* if the first contour point isn't touched, interpolate */ + /* from the contour start to the first touched point */ + if ( first_touched > points ) + ah_iup_interp( first_point, first_touched - 1, + cur_touched, first_touched ); + } + } + } + + /* now save the interpolated values back to x/y */ + if ( dimension ) + { + for ( point = points; point < point_limit; point++ ) + point->y = point->u; + + touch_flag = ah_flah_touch_x; + ah_setup_uv( outline, ah_uv_ox ); + } + else + { + for ( point = points; point < point_limit; point++ ) + point->x = point->u; + + break; /* exit loop */ + } + } + } + +#endif /* !AH_OPTION_NO_WEAK_INTERPOLATION */ + + + LOCAL_FUNC + void ah_hinter_align_points( AH_Hinter* hinter ) + { + ah_hinter_align_edge_points( hinter ); + +#ifndef AH_OPTION_NO_STRONG_INTERPOLATION + ah_hinter_align_strong_points( hinter ); +#endif + +#ifndef AH_OPTION_NO_WEAK_INTERPOLATION + ah_hinter_align_weak_points( hinter ); +#endif + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** H I N T E R O B J E C T M E T H O D S ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* scale and fit the global metrics */ + static + void ah_hinter_scale_globals( AH_Hinter* hinter, + FT_Fixed x_scale, + FT_Fixed y_scale ) + { + FT_Int n; + AH_Face_Globals* globals = hinter->globals; + AH_Globals* design = &globals->design; + AH_Globals* scaled = &globals->scaled; + + + /* copy content */ + *scaled = *design; + + /* scale the standard widths & heights */ + for ( n = 0; n < design->num_widths; n++ ) + scaled->widths[n] = FT_MulFix( design->widths[n], x_scale ); + + for ( n = 0; n < design->num_heights; n++ ) + scaled->heights[n] = FT_MulFix( design->heights[n], y_scale ); + + /* scale the blue zones */ + for ( n = 0; n < ah_blue_max; n++ ) + { + FT_Pos delta, delta2; + + + delta = design->blue_shoots[n] - design->blue_refs[n]; + delta2 = delta; + if ( delta < 0 ) + delta2 = -delta2; + delta2 = FT_MulFix( delta2, y_scale ); + + if ( delta2 < 32 ) + delta2 = 0; + else if ( delta2 < 64 ) + delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & -32 ); + else + delta2 = ( delta2 + 32 ) & -64; + + if ( delta < 0 ) + delta2 = -delta2; + + scaled->blue_refs[n] = + ( FT_MulFix( design->blue_refs[n], y_scale ) + 32 ) & -64; + scaled->blue_shoots[n] = scaled->blue_refs[n] + delta2; + } + + globals->x_scale = x_scale; + globals->y_scale = y_scale; + } + + + static + void ah_hinter_align( AH_Hinter* hinter ) + { + ah_hinter_align_edge_points( hinter ); + ah_hinter_align_points( hinter ); + } + + + /* finalize a hinter object */ + void ah_hinter_done( AH_Hinter* hinter ) + { + if ( hinter ) + { + FT_Memory memory = hinter->memory; + + + ah_loader_done( hinter->loader ); + ah_outline_done( hinter->glyph ); + + /* note: the `globals' pointer is _not_ owned by the hinter */ + /* but by the current face object, we don't need to */ + /* release it */ + hinter->globals = 0; + hinter->face = 0; + + FREE( hinter ); + } + } + + + /* create a new empty hinter object */ + FT_Error ah_hinter_new( FT_Library library, + AH_Hinter** ahinter ) + { + AH_Hinter* hinter = 0; + FT_Memory memory = library->memory; + FT_Error error; + + + *ahinter = 0; + + /* allocate object */ + if ( ALLOC( hinter, sizeof ( *hinter ) ) ) + goto Exit; + + hinter->memory = memory; + hinter->flags = 0; + + /* allocate outline and loader */ + error = ah_outline_new( memory, &hinter->glyph ) || + ah_loader_new ( memory, &hinter->loader ) || + ah_loader_create_extra( hinter->loader ); + if ( error ) + goto Exit; + + *ahinter = hinter; + + Exit: + if ( error ) + ah_hinter_done( hinter ); + + return error; + } + + + /* create a face's autohint globals */ + FT_Error ah_hinter_new_face_globals( AH_Hinter* hinter, + FT_Face face, + AH_Globals* globals ) + { + FT_Error error; + FT_Memory memory = hinter->memory; + AH_Face_Globals* face_globals; + + + if ( ALLOC( face_globals, sizeof ( *face_globals ) ) ) + goto Exit; + + hinter->face = face; + hinter->globals = face_globals; + + if ( globals ) + face_globals->design = *globals; + else + ah_hinter_compute_globals( hinter ); + + face->autohint.data = face_globals; + face->autohint.finalizer = (FT_Generic_Finalizer) + ah_hinter_done_face_globals; + face_globals->face = face; + + Exit: + return error; + } + + + /* discard a face's autohint globals */ + void ah_hinter_done_face_globals( AH_Face_Globals* globals ) + { + FT_Face face = globals->face; + FT_Memory memory = face->memory; + + + FREE( globals ); + } + + + static + FT_Error ah_hinter_load( AH_Hinter* hinter, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_UInt depth ) + { + FT_Face face = hinter->face; + FT_GlyphSlot slot = face->glyph; + FT_Fixed x_scale = face->size->metrics.x_scale; + FT_Fixed y_scale = face->size->metrics.y_scale; + FT_Glyph_Metrics metrics; /* temporary metrics */ + FT_Error error; + AH_Outline* outline = hinter->glyph; + AH_Loader* gloader = hinter->loader; + FT_Bool no_horz_hints = + ( load_flags & AH_HINT_NO_HORZ_EDGES ) != 0; + FT_Bool no_vert_hints = + ( load_flags & AH_HINT_NO_VERT_EDGES ) != 0; + + + /* load the glyph */ + error = FT_Load_Glyph( face, glyph_index, load_flags ); + if ( error ) + goto Exit; + + /* save current glyph metrics */ + metrics = slot->metrics; + + switch ( slot->format ) + { + case ft_glyph_format_outline: + /* first of all, copy the outline points in the loader's current */ + /* extra points, which is used to keep original glyph coordinates */ + error = ah_loader_check_points( gloader, slot->outline.n_points + 2, + slot->outline.n_contours ); + if ( error ) + goto Exit; + + MEM_Copy( gloader->current.extra_points, slot->outline.points, + slot->outline.n_points * sizeof ( FT_Vector ) ); + + MEM_Copy( gloader->current.outline.contours, slot->outline.contours, + slot->outline.n_contours * sizeof ( short ) ); + + MEM_Copy( gloader->current.outline.tags, slot->outline.tags, + slot->outline.n_points * sizeof ( char ) ); + + gloader->current.outline.n_points = slot->outline.n_points; + gloader->current.outline.n_contours = slot->outline.n_contours; + + /* compute original phantom points */ + hinter->pp1.x = 0; + hinter->pp1.y = 0; + hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale ); + hinter->pp2.y = 0; + + /* be sure to check for spacing glyphs */ + if ( slot->outline.n_points == 0 ) + goto Hint_Metrics; + + /* now, load the slot image into the auto-outline, and run the */ + /* automatic hinting process */ + error = ah_outline_load( outline, face ); /* XXX: change to slot */ + if ( error ) + goto Exit; + + /* perform feature detection */ + ah_outline_detect_features( outline ); + + if ( !no_horz_hints ) + { + ah_outline_compute_blue_edges( outline, hinter->globals ); + ah_outline_scale_blue_edges( outline, hinter->globals ); + } + + /* perform alignment control */ + ah_hinter_hint_edges( hinter, no_horz_hints, no_vert_hints ); + ah_hinter_align( hinter ); + + /* now save the current outline into the loader's current table */ + ah_outline_save( outline, gloader ); + + /* we now need to hint the metrics according to the change in */ + /* width/positioning that occured during the hinting process */ + { + FT_Pos old_width, new_width; + FT_Pos old_advance, new_advance; + FT_Pos old_lsb, new_lsb; + AH_Edge* edge1 = outline->vert_edges; /* leftmost edge */ + AH_Edge* edge2 = edge1 + + outline->num_vedges - 1; /* rightmost edge */ + + + old_width = edge2->opos - edge1->opos; + new_width = edge2->pos - edge1->pos; + + old_advance = hinter->pp2.x; + old_lsb = edge1->opos; + new_lsb = edge1->pos; + + new_advance = old_advance + + ( new_width + new_lsb - old_width - old_lsb ); + + hinter->pp1.x = ( ( new_lsb - old_lsb ) + 32 ) & -64; + hinter->pp2.x = ( ( edge2->pos + + ( old_advance - edge2->opos ) ) + 32 ) & -64; + } + + /* good, we simply add the glyph to our loader's base */ + ah_loader_add( gloader ); + break; + + case ft_glyph_format_composite: + { + FT_UInt nn, num_subglyphs = slot->num_subglyphs; + FT_UInt num_base_subgs, start_point, start_contour; + FT_SubGlyph* subglyph; + + + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; + + /* first of all, copy the subglyph descriptors in the glyph loader */ + error = ah_loader_check_subglyphs( gloader, num_subglyphs ); + if ( error ) + goto Exit; + + MEM_Copy( gloader->current.subglyphs, slot->subglyphs, + num_subglyphs * sizeof ( FT_SubGlyph ) ); + + gloader->current.num_subglyphs = num_subglyphs; + num_base_subgs = gloader->base.num_subglyphs; + + /* now, read each subglyph independently */ + for ( nn = 0; nn < num_subglyphs; nn++ ) + { + FT_Vector pp1, pp2; + FT_Pos x, y; + FT_UInt num_points, num_new_points, num_base_points; + + + /* gloader.current.subglyphs can change during glyph loading due */ + /* to re-allocation -- we must recompute the current subglyph on */ + /* each iteration */ + subglyph = gloader->base.subglyphs + num_base_subgs + nn; + + pp1 = hinter->pp1; + pp2 = hinter->pp2; + + num_base_points = gloader->base.outline.n_points; + + error = ah_hinter_load( hinter, subglyph->index, + load_flags, depth + 1 ); + if ( error ) + goto Exit; + + /* recompute subglyph pointer */ + subglyph = gloader->base.subglyphs + num_base_subgs + nn; + + if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS ) + { + pp1 = hinter->pp1; + pp2 = hinter->pp2; + } + else + { + hinter->pp1 = pp1; + hinter->pp2 = pp2; + } + + num_points = gloader->base.outline.n_points; + num_new_points = num_points - num_base_points; + + /* now perform the transform required for this subglyph */ + + if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE | + FT_SUBGLYPH_FLAG_XY_SCALE | + FT_SUBGLYPH_FLAG_2X2 ) ) + { + FT_Vector* cur = gloader->base.outline.points + + num_base_points; + FT_Vector* org = gloader->base.extra_points + + num_base_points; + FT_Vector* limit = cur + num_new_points; + + + for ( ; cur < limit; cur++, org++ ) + { + FT_Vector_Transform( cur, &subglyph->transform ); + FT_Vector_Transform( org, &subglyph->transform ); + } + } + + /* apply offset */ + + if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) ) + { + FT_Int k = subglyph->arg1; + FT_UInt l = subglyph->arg2; + FT_Vector* p1; + FT_Vector* p2; + + + if ( start_point + k >= num_base_points || + l >= (FT_UInt)num_new_points ) + { + error = FT_Err_Invalid_Composite; + goto Exit; + } + + l += num_base_points; + + /* for now, only use the current point coordinates */ + /* we may consider another approach in the near future */ + p1 = gloader->base.outline.points + start_point + k; + p2 = gloader->base.outline.points + start_point + l; + + x = p1->x - p2->x; + y = p1->y - p2->y; + } + else + { + x = FT_MulFix( subglyph->arg1, x_scale ); + y = FT_MulFix( subglyph->arg2, y_scale ); + + x = ( x + 32 ) & -64; + y = ( y + 32 ) & -64; + } + + { + FT_Outline dummy = gloader->base.outline; + + + dummy.points += num_base_points; + dummy.n_points = num_new_points; + + FT_Outline_Translate( &dummy, x, y ); + } + } + } + break; + + default: + /* we don't support other formats (yet?) */ + error = FT_Err_Unimplemented_Feature; + } + + Hint_Metrics: + if ( depth == 0 ) + { + FT_BBox bbox; + + + /* we must translate our final outline by -pp1.x, and compute */ + /* the new metrics */ + if ( hinter->pp1.x ) + FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 ); + + FT_Outline_Get_CBox( &gloader->base.outline, &bbox ); + bbox.xMin &= -64; + bbox.yMin &= -64; + bbox.xMax = ( bbox.xMax + 63 ) & -64; + bbox.yMax = ( bbox.yMax + 63 ) & -64; + + slot->metrics.width = bbox.xMax - bbox.xMin; + slot->metrics.height = bbox.yMax - bbox.yMin; + slot->metrics.horiBearingX = bbox.xMin; + slot->metrics.horiBearingY = bbox.yMax; + slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x; + /* XXX: TO DO - slot->linearHoriAdvance */ + + /* now copy outline into glyph slot */ + ah_loader_rewind( slot->loader ); + error = ah_loader_copy_points( slot->loader, gloader ); + if ( error ) + goto Exit; + + slot->outline = slot->loader->base.outline; + slot->format = ft_glyph_format_outline; + } + + Exit: + return error; + } + + + /* load and hint a given glyph */ + FT_Error ah_hinter_load_glyph( AH_Hinter* hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ) + { + FT_Face face = slot->face; + FT_Error error; + FT_Fixed x_scale = size->metrics.x_scale; + FT_Fixed y_scale = size->metrics.y_scale; + AH_Face_Globals* face_globals = FACE_GLOBALS( face ); + + + /* first of all, we need to check that we're using the correct face and */ + /* global hints to load the glyph */ + if ( hinter->face != face || hinter->globals != face_globals ) + { + hinter->face = face; + if ( !face_globals ) + { + error = ah_hinter_new_face_globals( hinter, face, 0 ); + if ( error ) + goto Exit; + } + hinter->globals = FACE_GLOBALS( face ); + face_globals = FACE_GLOBALS( face ); + } + + /* now, we must check the current character pixel size to see if we */ + /* need to rescale the global metrics */ + if ( face_globals->x_scale != x_scale || + face_globals->y_scale != y_scale ) + ah_hinter_scale_globals( hinter, x_scale, y_scale ); + + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_RECURSE; + + ah_loader_rewind( hinter->loader ); + + error = ah_hinter_load( hinter, glyph_index, load_flags, 0 ); + + Exit: + return error; + } + + + /* retrieve a face's autohint globals for client applications */ + void ah_hinter_get_global_hints( AH_Hinter* hinter, + FT_Face face, + void** global_hints, + long* global_len ) + { + AH_Globals* globals = 0; + FT_Memory memory = hinter->memory; + FT_Error error; + + + /* allocate new master globals */ + if ( ALLOC( globals, sizeof ( *globals ) ) ) + goto Fail; + + /* compute face globals if needed */ + if ( !FACE_GLOBALS( face ) ) + { + error = ah_hinter_new_face_globals( hinter, face, 0 ); + if ( error ) + goto Fail; + } + + *globals = FACE_GLOBALS( face )->design; + *global_hints = globals; + *global_len = sizeof( *globals ); + + return; + + Fail: + FREE( globals ); + + *global_hints = 0; + *global_len = 0; + } + + + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ) + { + FT_Memory memory = hinter->memory; + + + FREE( global_hints ); + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahhint.h b/subsys/win32k/freetype/src/autohint/ahhint.h new file mode 100644 index 0000000..e9eb981 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahhint.h @@ -0,0 +1,72 @@ +/***************************************************************************/ +/* */ +/* ahhint.h */ +/* */ +/* Glyph hinter (declaration). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHHINT_H +#define AHHINT_H + + +#ifdef FT_FLAT_COMPILE + +#include "ahglobal.h" + +#else + +#include + +#endif + + +#define AH_HINT_DEFAULT 0 +#define AH_HINT_NO_ALIGNMENT 1 +#define AH_HINT_NO_HORZ_EDGES 0x20000L +#define AH_HINT_NO_VERT_EDGES 0x40000L + + + /* create a new empty hinter object */ + FT_Error ah_hinter_new( FT_Library library, + AH_Hinter** ahinter ); + + /* Load a hinted glyph in the hinter */ + FT_Error ah_hinter_load_glyph( AH_Hinter* hinter, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ); + + /* finalize a hinter object */ + void ah_hinter_done( AH_Hinter* hinter ); + + LOCAL_DEF + void ah_hinter_done_face_globals( AH_Face_Globals* globals ); + + void ah_hinter_get_global_hints( AH_Hinter* hinter, + FT_Face face, + void** global_hints, + long* global_len ); + + void ah_hinter_done_global_hints( AH_Hinter* hinter, + void* global_hints ); + + +#endif /* AHHINT_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahloader.h b/subsys/win32k/freetype/src/autohint/ahloader.h new file mode 100644 index 0000000..4a8563c --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahloader.h @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* ahloader.h */ +/* */ +/* Glyph loader for the auto-hinting module (declaration only). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This defines the AH_GlyphLoader type in two different ways: */ + /* */ + /* - If the module is compiled within FreeType 2, the type is simply a */ + /* typedef to FT_GlyphLoader. */ + /* */ + /* - If the module is compiled as a standalone object, AH_GlyphLoader */ + /* has its own implementation. */ + /* */ + /*************************************************************************/ + + +#ifndef AHLOADER_H +#define AHLOADER_H + + +#ifdef _STANDALONE_ + + typedef struct AH_GlyphLoad_ + { + FT_Outline outline; /* outline */ + FT_UInt num_subglyphs; /* number of subglyphs */ + FT_SubGlyph* subglyphs; /* subglyphs */ + FT_Vector* extra_points; /* extra points table */ + + } AH_GlyphLoad; + + + struct AH_GlyphLoader_ + { + FT_Memory memory; + FT_UInt max_points; + FT_UInt max_contours; + FT_UInt max_subglyphs; + FT_Bool use_extra; + + AH_GlyphLoad base; + AH_GlyphLoad current; + + void* other; /* for possible future extensions */ + }; + + + LOCAL_DEF + FT_Error AH_GlyphLoader_New( FT_Memory memory, + AH_GlyphLoader** aloader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Create_Extra( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Done( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Reset( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Rewind( AH_GlyphLoader* loader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Points( AH_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Check_Subglyphs( AH_GlyphLoader* loader, + FT_UInt n_subs ); + + LOCAL_DEF + void AH_GlyphLoader_Prepare( AH_GlyphLoader* loader ); + + LOCAL_DEF + void AH_GlyphLoader_Add( AH_GlyphLoader* loader ); + + LOCAL_DEF + FT_Error AH_GlyphLoader_Copy_Points( AH_GlyphLoader* target, + FT_GlyphLoader* source ); + +#else /* _STANDALONE */ + +#include + + #define AH_Load FT_GlyphLoad + #define AH_Loader FT_GlyphLoader + + #define ah_loader_new FT_GlyphLoader_New + #define ah_loader_done FT_GlyphLoader_Done + #define ah_loader_reset FT_GlyphLoader_Reset + #define ah_loader_rewind FT_GlyphLoader_Rewind + #define ah_loader_create_extra FT_GlyphLoader_Create_Extra + #define ah_loader_check_points FT_GlyphLoader_Check_Points + #define ah_loader_check_subglyphs FT_GlyphLoader_Check_Subglyphs + #define ah_loader_prepare FT_GlyphLoader_Prepare + #define ah_loader_add FT_GlyphLoader_Add + #define ah_loader_copy_points FT_GlyphLoader_Copy_Points + +#endif /* _STANDALONE_ */ + +#endif /* AHLOADER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahmodule.c b/subsys/win32k/freetype/src/autohint/ahmodule.c new file mode 100644 index 0000000..2e4f707 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahmodule.c @@ -0,0 +1,127 @@ +/***************************************************************************/ +/* */ +/* ahmodule.c */ +/* */ +/* Auto-hinting module implementation (declaration). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ahhint.h" + +#else + +#include + +#endif + + + typedef struct FT_AutoHinterRec_ + { + FT_ModuleRec root; + AH_Hinter* hinter; + + } FT_AutoHinterRec; + + + static + FT_Error ft_autohinter_init( FT_AutoHinter module ) + { + return ah_hinter_new( module->root.library, &module->hinter ); + } + + + static + void ft_autohinter_done( FT_AutoHinter module ) + { + ah_hinter_done( module->hinter ); + } + + + static + FT_Error ft_autohinter_load( FT_AutoHinter module, + FT_GlyphSlot slot, + FT_Size size, + FT_UInt glyph_index, + FT_ULong load_flags ) + { + return ah_hinter_load_glyph( module->hinter, + slot, size, glyph_index, load_flags ); + } + + + static + void ft_autohinter_reset( FT_AutoHinter module, + FT_Face face ) + { + UNUSED( module ); + + if ( face->autohint.data ) + ah_hinter_done_face_globals( (AH_Face_Globals*)(face->autohint.data) ); + } + + + static + void ft_autohinter_get_globals( FT_AutoHinter module, + FT_Face face, + void** global_hints, + long* global_len ) + { + ah_hinter_get_global_hints( module->hinter, face, + global_hints, global_len ); + } + + + static + void ft_autohinter_done_globals( FT_AutoHinter module, + void* global_hints ) + { + ah_hinter_done_global_hints( module->hinter, global_hints ); + } + + + static + const FT_AutoHinter_Interface autohinter_interface = + { + ft_autohinter_reset, + ft_autohinter_load, + ft_autohinter_get_globals, + ft_autohinter_done_globals + }; + + + const FT_Module_Class autohint_module_class = + { + ft_module_hinter, + sizeof ( FT_AutoHinterRec ), + + "autohinter", + 0x10000L, /* version 1.0 of the autohinter */ + 0x20000L, /* requires FreeType 2.0 or above */ + + (const void*)&autohinter_interface, + + (FT_Module_Constructor)ft_autohinter_init, + (FT_Module_Destructor) ft_autohinter_done, + (FT_Module_Requester) 0 + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahmodule.h b/subsys/win32k/freetype/src/autohint/ahmodule.h new file mode 100644 index 0000000..28b0753 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahmodule.h @@ -0,0 +1,32 @@ +/***************************************************************************/ +/* */ +/* ahmodule.h */ +/* */ +/* Auto-hinting module (declaration). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHMODULE_H +#define AHMODULE_H + +#include + + FT_EXPORT_VAR( const FT_Module_Class ) autohint_module_class; + +#endif /* AHMODULE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahoptim.c b/subsys/win32k/freetype/src/autohint/ahoptim.c new file mode 100644 index 0000000..191f5fa --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahoptim.c @@ -0,0 +1,889 @@ +/***************************************************************************/ +/* */ +/* ahoptim.c */ +/* */ +/* FreeType auto hinting outline optimization (body). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This module is in charge of optimising the outlines produced by the */ + /* auto-hinter in direct mode. This is required at small pixel sizes in */ + /* order to ensure coherent spacing, among other things.. */ + /* */ + /* The technique used in this module is a simplified simulated */ + /* annealing. */ + /* */ + /*************************************************************************/ + + +#include /* for ALLOC_ARRAY() and FREE() */ + + +#ifdef FT_FLAT_COMPILE + +#include "ahoptim.h" + +#else + +#include + +#endif + + + /* define this macro to use brute force optimisation -- this is slow, */ + /* but a good way to perfect the distortion function `by hand' through */ + /* tweaking */ +#define AH_BRUTE_FORCE + + +#define xxxAH_DEBUG_OPTIM + + +#undef LOG +#ifdef AH_DEBUG_OPTIM + +#define LOG( x ) optim_log##x + +#else + +#define LOG( x ) + +#endif /* AH_DEBUG_OPTIM */ + + +#ifdef AH_DEBUG_OPTIM + +#include +#include +#include + +#define FLOAT( x ) ( (float)( (x) / 64.0 ) ) + + static + void optim_log( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + } + + + static + void AH_Dump_Stems( AH_Optimizer* optimizer ) + { + int n; + AH_Stem* stem; + + + stem = optimizer->stems; + for ( n = 0; n < optimizer->num_stems; n++, stem++ ) + { + LOG(( " %c%2d [%.1f:%.1f]={%.1f:%.1f}=" + "<%1.f..%1.f> force=%.1f speed=%.1f\n", + optimizer->vertical ? 'V' : 'H', n, + FLOAT( stem->edge1->opos ), FLOAT( stem->edge2->opos ), + FLOAT( stem->edge1->pos ), FLOAT( stem->edge2->pos ), + FLOAT( stem->min_pos ), FLOAT( stem->max_pos ), + FLOAT( stem->force ), FLOAT( stem->velocity ) )); + } + } + + + static + void AH_Dump_Stems2( AH_Optimizer* optimizer ) + { + int n; + AH_Stem* stem; + + + stem = optimizer->stems; + for ( n = 0; n < optimizer->num_stems; n++, stem++ ) + { + LOG(( " %c%2d [%.1f]=<%1.f..%1.f> force=%.1f speed=%.1f\n", + optimizer->vertical ? 'V' : 'H', n, + FLOAT( stem->pos ), + FLOAT( stem->min_pos ), FLOAT( stem->max_pos ), + FLOAT( stem->force ), FLOAT( stem->velocity ) )); + } + } + + + static + void AH_Dump_Springs( AH_Optimizer* optimizer ) + { + int n; + AH_Spring* spring; + AH_Stem* stems; + + + spring = optimizer->springs; + stems = optimizer->stems; + LOG(( "%cSprings ", optimizer->vertical ? 'V' : 'H' )); + + for ( n = 0; n < optimizer->num_springs; n++, spring++ ) + { + LOG(( " [%d-%d:%.1f:%1.f:%.1f]", + spring->stem1 - stems, spring->stem2 - stems, + FLOAT( spring->owidth ), + FLOAT( spring->stem2->pos - + ( spring->stem1->pos + spring->stem1->width ) ), + FLOAT( spring->tension ) )); + } + + LOG(( "\n" )); + } + +#endif /* AH_DEBUG_OPTIM */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** COMPUTE STEMS AND SPRINGS IN AN OUTLINE ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + int valid_stem_segments( AH_Segment* seg1, + AH_Segment* seg2 ) + { + return seg1->serif == 0 && + seg2 && + seg2->link == seg1 && + seg1->pos < seg2->pos && + seg1->min_coord <= seg2->max_coord && + seg2->min_coord <= seg1->max_coord; + } + + + /* compute all stems in an outline */ + static + int optim_compute_stems( AH_Optimizer* optimizer ) + { + AH_Outline* outline = optimizer->outline; + FT_Fixed scale; + FT_Memory memory = optimizer->memory; + FT_Error error = 0; + FT_Int dimension; + AH_Edge* edges; + AH_Edge* edge_limit; + AH_Stem** p_stems; + FT_Int* p_num_stems; + + + edges = outline->horz_edges; + edge_limit = edges + outline->num_hedges; + scale = outline->y_scale; + + p_stems = &optimizer->horz_stems; + p_num_stems = &optimizer->num_hstems; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AH_Stem* stems = 0; + FT_Int num_stems = 0; + AH_Edge* edge; + + + /* first of all, count the number of stems in this direction */ + for ( edge = edges; edge < edge_limit; edge++ ) + { + AH_Segment* seg = edge->first; + + + do + { + if (valid_stem_segments( seg, seg->link ) ) + num_stems++; + + seg = seg->edge_next; + + } while ( seg != edge->first ); + } + + /* now allocate the stems and build their table */ + if ( num_stems > 0 ) + { + AH_Stem* stem; + + + if ( ALLOC_ARRAY( stems, num_stems, AH_Stem ) ) + goto Exit; + + stem = stems; + for ( edge = edges; edge < edge_limit; edge++ ) + { + AH_Segment* seg = edge->first; + AH_Segment* seg2; + + + do + { + seg2 = seg->link; + if ( valid_stem_segments( seg, seg2 ) ) + { + AH_Edge* edge1 = seg->edge; + AH_Edge* edge2 = seg2->edge; + + + stem->edge1 = edge1; + stem->edge2 = edge2; + stem->opos = edge1->opos; + stem->pos = edge1->pos; + stem->owidth = edge2->opos - edge1->opos; + stem->width = edge2->pos - edge1->pos; + + /* compute min_coord and max_coord */ + { + FT_Pos min_coord = seg->min_coord; + FT_Pos max_coord = seg->max_coord; + + + if ( seg2->min_coord > min_coord ) + min_coord = seg2->min_coord; + + if ( seg2->max_coord < max_coord ) + max_coord = seg2->max_coord; + + stem->min_coord = min_coord; + stem->max_coord = max_coord; + } + + /* compute minimum and maximum positions for stem -- */ + /* note that the left-most/bottom-most stem has always */ + /* a fixed position */ + if ( stem == stems || edge1->blue_edge || edge2->blue_edge ) + { + /* this stem cannot move; it is snapped to a blue edge */ + stem->min_pos = stem->pos; + stem->max_pos = stem->pos; + } + else + { + /* this edge can move; compute its min and max positions */ + FT_Pos pos1 = stem->opos; + FT_Pos pos2 = pos1 + stem->owidth - stem->width; + FT_Pos min1 = pos1 & -64; + FT_Pos min2 = pos2 & -64; + + + stem->min_pos = min1; + stem->max_pos = min1 + 64; + if ( min2 < min1 ) + stem->min_pos = min2; + else + stem->max_pos = min2 + 64; + + /* XXX: just to see what it does */ + stem->max_pos += 64; + + /* just for the case where direct hinting did some */ + /* incredible things (e.g. blue edge shifts) */ + if ( stem->min_pos > stem->pos ) + stem->min_pos = stem->pos; + + if ( stem->max_pos < stem->pos ) + stem->max_pos = stem->pos; + } + + stem->velocity = 0; + stem->force = 0; + + stem++; + } + seg = seg->edge_next; + + } while ( seg != edge->first ); + } + } + + *p_stems = stems; + *p_num_stems = num_stems; + + edges = outline->vert_edges; + edge_limit = edges + outline->num_vedges; + scale = outline->x_scale; + + p_stems = &optimizer->vert_stems; + p_num_stems = &optimizer->num_vstems; + } + + Exit: + +#ifdef AH_DEBUG_OPTIM + AH_Dump_Stems( optimizer ); +#endif + + return error; + } + + + /* returns the spring area between two stems, 0 if none */ + static + FT_Pos stem_spring_area( AH_Stem* stem1, + AH_Stem* stem2 ) + { + FT_Pos area1 = stem1->max_coord - stem1->min_coord; + FT_Pos area2 = stem2->max_coord - stem2->min_coord; + FT_Pos min = stem1->min_coord; + FT_Pos max = stem1->max_coord; + FT_Pos area; + + + /* order stems */ + if ( stem2->opos <= stem1->opos + stem1->owidth ) + return 0; + + if ( min < stem2->min_coord ) + min = stem2->min_coord; + + if ( max < stem2->max_coord ) + max = stem2->max_coord; + + area = ( max-min ); + if ( 2 * area < area1 && 2 * area < area2 ) + area = 0; + + return area; + } + + + /* compute all springs in an outline */ + static + int optim_compute_springs( AH_Optimizer* optimizer ) + { + /* basically, a spring exists between two stems if most of their */ + /* surface is aligned */ + FT_Memory memory = optimizer->memory; + + AH_Stem* stems; + AH_Stem* stem_limit; + AH_Stem* stem; + int dimension; + int error = 0; + + FT_Int* p_num_springs; + AH_Spring** p_springs; + + + stems = optimizer->horz_stems; + stem_limit = stems + optimizer->num_hstems; + + p_springs = &optimizer->horz_springs; + p_num_springs = &optimizer->num_hsprings; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + FT_Int num_springs = 0; + AH_Spring* springs = 0; + + + /* first of all, count stem springs */ + for ( stem = stems; stem + 1 < stem_limit; stem++ ) + { + AH_Stem* stem2; + + + for ( stem2 = stem+1; stem2 < stem_limit; stem2++ ) + if ( stem_spring_area( stem, stem2 ) ) + num_springs++; + } + + /* then allocate and build the springs table */ + if ( num_springs > 0 ) + { + AH_Spring* spring; + + + /* allocate table of springs */ + if ( ALLOC_ARRAY( springs, num_springs, AH_Spring ) ) + goto Exit; + + /* fill the springs table */ + spring = springs; + for ( stem = stems; stem+1 < stem_limit; stem++ ) + { + AH_Stem* stem2; + FT_Pos area; + + + for ( stem2 = stem + 1; stem2 < stem_limit; stem2++ ) + { + area = stem_spring_area( stem, stem2 ); + if ( area ) + { + /* add a new spring here */ + spring->stem1 = stem; + spring->stem2 = stem2; + spring->owidth = stem2->opos - ( stem->opos + stem->owidth ); + spring->tension = 0; + + spring++; + } + } + } + } + *p_num_springs = num_springs; + *p_springs = springs; + + stems = optimizer->vert_stems; + stem_limit = stems + optimizer->num_vstems; + + p_springs = &optimizer->vert_springs; + p_num_springs = &optimizer->num_vsprings; + } + + Exit: + +#ifdef AH_DEBUG_OPTIM + AH_Dump_Springs( optimizer ); +#endif + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** OPTIMIZE THROUGH MY STRANGE SIMULATED ANNEALING ALGO ;-) ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + +#ifndef AH_BRUTE_FORCE + + /* compute all spring tensions */ + static + void optim_compute_tensions( AH_Optimizer* optimizer ) + { + AH_Spring* spring = optimizer->springs; + AH_Spring* limit = spring + optimizer->num_springs; + + + for ( ; spring < limit; spring++ ) + { + AH_Stem* stem1 = spring->stem1; + AH_Stem* stem2 = spring->stem2; + FT_Int status; + + FT_Pos width; + FT_Pos tension; + FT_Pos sign; + + + /* compute the tension; it simply is -K*(new_width-old_width) */ + width = stem2->pos - ( stem1->pos + stem1->width ); + tension = width - spring->owidth; + + sign = 1; + if ( tension < 0 ) + { + sign = -1; + tension = -tension; + } + + if ( width <= 0 ) + tension = 32000; + else + tension = ( tension << 10 ) / width; + + tension = -sign * FT_MulFix( tension, optimizer->tension_scale ); + spring->tension = tension; + + /* now, distribute tension among the englobing stems, if they */ + /* are able to move */ + status = 0; + if ( stem1->pos <= stem1->min_pos ) + status |= 1; + if ( stem2->pos >= stem2->max_pos ) + status |= 2; + + if ( !status ) + tension /= 2; + + if ( ( status & 1 ) == 0 ) + stem1->force -= tension; + + if ( ( status & 2 ) == 0 ) + stem2->force += tension; + } + } + + + /* compute all stem movements -- returns 0 if nothing moved */ + static + int optim_compute_stem_movements( AH_Optimizer* optimizer ) + { + AH_Stem* stems = optimizer->stems; + AH_Stem* limit = stems + optimizer->num_stems; + AH_Stem* stem = stems; + int moved = 0; + + + /* set initial forces to velocity */ + for ( stem = stems; stem < limit; stem++ ) + { + stem->force = stem->velocity; + stem->velocity /= 2; /* XXX: Heuristics */ + } + + /* compute the sum of forces applied on each stem */ + optim_compute_tensions( optimizer ); + +#ifdef AH_DEBUG_OPTIM + AH_Dump_Springs( optimizer ); + AH_Dump_Stems2( optimizer ); +#endif + + /* now, see whether something can move */ + for ( stem = stems; stem < limit; stem++ ) + { + if ( stem->force > optimizer->tension_threshold ) + { + /* there is enough tension to move the stem to the right */ + if ( stem->pos < stem->max_pos ) + { + stem->pos += 64; + stem->velocity = stem->force / 2; + moved = 1; + } + else + stem->velocity = 0; + } + else if ( stem->force < optimizer->tension_threshold ) + { + /* there is enough tension to move the stem to the left */ + if ( stem->pos > stem->min_pos ) + { + stem->pos -= 64; + stem->velocity = stem->force / 2; + moved = 1; + } + else + stem->velocity = 0; + } + } + + /* return 0 if nothing moved */ + return moved; + } + +#endif /* AH_BRUTE_FORCE */ + + + /* compute current global distortion from springs */ + static + FT_Pos optim_compute_distortion( AH_Optimizer* optimizer ) + { + AH_Spring* spring = optimizer->springs; + AH_Spring* limit = spring + optimizer->num_springs; + FT_Pos distortion = 0; + + + for ( ; spring < limit; spring++ ) + { + AH_Stem* stem1 = spring->stem1; + AH_Stem* stem2 = spring->stem2; + FT_Pos width; + + width = stem2->pos - ( stem1->pos + stem1->width ); + width -= spring->owidth; + if ( width < 0 ) + width = -width; + + distortion += width; + } + + return distortion; + } + + + /* record stems configuration in `best of' history */ + static + void optim_record_configuration( AH_Optimizer* optimizer ) + { + FT_Pos distortion; + AH_Configuration* configs = optimizer->configs; + AH_Configuration* limit = configs + optimizer->num_configs; + AH_Configuration* config; + + + distortion = optim_compute_distortion( optimizer ); + LOG(( "config distortion = %.1f ", FLOAT( distortion * 64 ) )); + + /* check that we really need to add this configuration to our */ + /* sorted history */ + if ( limit > configs && limit[-1].distortion < distortion ) + { + LOG(( "ejected\n" )); + return; + } + + /* add new configuration at the end of the table */ + { + int n; + + + config = limit; + if ( optimizer->num_configs < AH_MAX_CONFIGS ) + optimizer->num_configs++; + else + config--; + + config->distortion = distortion; + + for ( n = 0; n < optimizer->num_stems; n++ ) + config->positions[n] = optimizer->stems[n].pos; + } + + /* move the current configuration towards the front of the list */ + /* when necessary -- yes this is slow bubble sort ;-) */ + while ( config > configs && config[0].distortion < config[-1].distortion ) + { + AH_Configuration temp; + + + config--; + temp = config[0]; + config[0] = config[1]; + config[1] = temp; + } + LOG(( "recorded!\n" )); + } + + +#ifdef AH_BRUTE_FORCE + + /* optimize outline in a single direction */ + static + void optim_compute( AH_Optimizer* optimizer ) + { + int n; + FT_Bool moved; + + AH_Stem* stem = optimizer->stems; + AH_Stem* limit = stem + optimizer->num_stems; + + + /* empty, exit */ + if ( stem >= limit ) + return; + + optimizer->num_configs = 0; + + stem = optimizer->stems; + for ( ; stem < limit; stem++ ) + stem->pos = stem->min_pos; + + do + { + /* record current configuration */ + optim_record_configuration( optimizer ); + + /* now change configuration */ + moved = 0; + for ( stem = optimizer->stems; stem < limit; stem++ ) + { + if ( stem->pos < stem->max_pos ) + { + stem->pos += 64; + moved = 1; + break; + } + + stem->pos = stem->min_pos; + } + } while ( moved ); + + /* now, set the best stem positions */ + for ( n = 0; n < optimizer->num_stems; n++ ) + { + AH_Stem* stem = optimizer->stems + n; + FT_Pos pos = optimizer->configs[0].positions[n]; + + + stem->edge1->pos = pos; + stem->edge2->pos = pos + stem->width; + + stem->edge1->flags |= ah_edge_done; + stem->edge2->flags |= ah_edge_done; + } + } + +#else /* AH_BRUTE_FORCE */ + + /* optimize outline in a single direction */ + static + void optim_compute( AH_Optimizer* optimizer ) + { + int n, counter, counter2; + + + optimizer->num_configs = 0; + optimizer->tension_scale = 0x80000L; + optimizer->tension_threshold = 64; + + /* record initial configuration threshold */ + optim_record_configuration( optimizer ); + + counter = 0; + for ( counter2 = optimizer->num_stems*8; counter2 >= 0; counter2-- ) + { + if ( counter == 0 ) + counter = 2 * optimizer->num_stems; + + if ( !optim_compute_stem_movements( optimizer ) ) + break; + + optim_record_configuration( optimizer ); + + counter--; + if ( counter == 0 ) + optimizer->tension_scale /= 2; + } + + /* now, set the best stem positions */ + for ( n = 0; n < optimizer->num_stems; n++ ) + { + AH_Stem* stem = optimizer->stems + n; + FT_Pos pos = optimizer->configs[0].positions[n]; + + + stem->edge1->pos = pos; + stem->edge2->pos = pos + stem->width; + + stem->edge1->flags |= ah_edge_done; + stem->edge2->flags |= ah_edge_done; + } + } + +#endif /* AH_BRUTE_FORCE */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** HIGH-LEVEL OPTIMIZER API ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* releases the optimization data */ + void AH_Optimizer_Done( AH_Optimizer* optimizer ) + { + if ( optimizer ) + { + FT_Memory memory = optimizer->memory; + + + FREE( optimizer->horz_stems ); + FREE( optimizer->vert_stems ); + FREE( optimizer->horz_springs ); + FREE( optimizer->vert_springs ); + FREE( optimizer->positions ); + } + } + + + /* loads the outline into the optimizer */ + int AH_Optimizer_Init( AH_Optimizer* optimizer, + AH_Outline* outline, + FT_Memory memory ) + { + FT_Error error; + + + MEM_Set( optimizer, 0, sizeof ( *optimizer ) ); + optimizer->outline = outline; + optimizer->memory = memory; + + LOG(( "initializing new optimizer\n" )); + /* compute stems and springs */ + error = optim_compute_stems ( optimizer ) || + optim_compute_springs( optimizer ); + if ( error ) + goto Fail; + + /* allocate stem positions history and configurations */ + { + int n, max_stems; + + + max_stems = optimizer->num_hstems; + if ( max_stems < optimizer->num_vstems ) + max_stems = optimizer->num_vstems; + + if ( ALLOC_ARRAY( optimizer->positions, + max_stems * AH_MAX_CONFIGS, FT_Pos ) ) + goto Fail; + + optimizer->num_configs = 0; + for ( n = 0; n < AH_MAX_CONFIGS; n++ ) + optimizer->configs[n].positions = optimizer->positions + + n * max_stems; + } + + return error; + + Fail: + AH_Optimizer_Done( optimizer ); + return error; + } + + + /* compute optimal outline */ + void AH_Optimizer_Compute( AH_Optimizer* optimizer ) + { + optimizer->num_stems = optimizer->num_hstems; + optimizer->stems = optimizer->horz_stems; + optimizer->num_springs = optimizer->num_hsprings; + optimizer->springs = optimizer->horz_springs; + + if ( optimizer->num_springs > 0 ) + { + LOG(( "horizontal optimization ------------------------\n" )); + optim_compute( optimizer ); + } + + optimizer->num_stems = optimizer->num_vstems; + optimizer->stems = optimizer->vert_stems; + optimizer->num_springs = optimizer->num_vsprings; + optimizer->springs = optimizer->vert_springs; + + if ( optimizer->num_springs ) + { + LOG(( "vertical optimization --------------------------\n" )); + optim_compute( optimizer ); + } + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahoptim.h b/subsys/win32k/freetype/src/autohint/ahoptim.h new file mode 100644 index 0000000..d6f8542 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahoptim.h @@ -0,0 +1,136 @@ +/***************************************************************************/ +/* */ +/* ahoptim.h */ +/* */ +/* FreeType auto hinting outline optimization (declaration). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHOPTIM_H +#define AHOPTIM_H + + +#ifdef FT_FLAT_COMPILE + +#include "ahtypes.h" + +#else + +#include + +#endif + + + /* the maximal number of stem configurations to record */ + /* during optimization */ +#define AH_MAX_CONFIGS 8 + + + typedef struct AH_Stem_ + { + FT_Pos pos; /* current position */ + FT_Pos velocity; /* current velocity */ + FT_Pos force; /* sum of current forces */ + FT_Pos width; /* normalized width */ + + FT_Pos min_pos; /* minimum grid position */ + FT_Pos max_pos; /* maximum grid position */ + + AH_Edge* edge1; /* left/bottom edge */ + AH_Edge* edge2; /* right/top edge */ + + FT_Pos opos; /* original position */ + FT_Pos owidth; /* original width */ + + FT_Pos min_coord; /* minimum coordinate */ + FT_Pos max_coord; /* maximum coordinate */ + + } AH_Stem; + + + /* A spring between two stems */ + typedef struct AH_Spring_ + { + AH_Stem* stem1; + AH_Stem* stem2; + FT_Pos owidth; /* original width */ + FT_Pos tension; /* current tension */ + + } AH_Spring; + + + /* A configuration records the position of each stem at a given time */ + /* as well as the associated distortion */ + typedef struct AH_Configuration_ + { + FT_Pos* positions; + FT_Long distortion; + + } AH_Configuration; + + + typedef struct AH_Optimizer_ + { + FT_Memory memory; + AH_Outline* outline; + + FT_Int num_hstems; + AH_Stem* horz_stems; + + FT_Int num_vstems; + AH_Stem* vert_stems; + + FT_Int num_hsprings; + FT_Int num_vsprings; + AH_Spring* horz_springs; + AH_Spring* vert_springs; + + FT_Int num_configs; + AH_Configuration configs[AH_MAX_CONFIGS]; + FT_Pos* positions; + + /* during each pass, use these instead */ + FT_Int num_stems; + AH_Stem* stems; + + FT_Int num_springs; + AH_Spring* springs; + FT_Bool vertical; + + FT_Fixed tension_scale; + FT_Pos tension_threshold; + + } AH_Optimizer; + + + /* loads the outline into the optimizer */ + int AH_Optimizer_Init( AH_Optimizer* optimizer, + AH_Outline* outline, + FT_Memory memory ); + + + /* compute optimal outline */ + void AH_Optimizer_Compute( AH_Optimizer* optimizer ); + + + /* release the optimization data */ + void AH_Optimizer_Done( AH_Optimizer* optimizer ); + + +#endif /* AHOPTIM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/ahtypes.h b/subsys/win32k/freetype/src/autohint/ahtypes.h new file mode 100644 index 0000000..9d96f15 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/ahtypes.h @@ -0,0 +1,492 @@ +/***************************************************************************/ +/* */ +/* ahtypes.h */ +/* */ +/* General types and definitions for the auto-hint module */ +/* (specification only). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#ifndef AHTYPES_H +#define AHTYPES_H + + +#include /* for freetype.h + LOCAL_DEF etc. */ + + +#ifdef FT_FLAT_COMPILE + +#include "ahloader.h" + +#else + +#include + +#endif + + +#define xxAH_DEBUG + + +#ifdef AH_DEBUG + +#include + +#define AH_LOG( x ) printf##x + +#else + +#define AH_LOG( x ) do ; while ( 0 ) /* nothing */ + +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** COMPILE-TIME BUILD OPTIONS ****/ + /**** ****/ + /**** Toggle these configuration macros to experiment with `features' ****/ + /**** of the auto-hinter. ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* If this option is defined, only strong interpolation will be used to */ + /* place the points between edges. Otherwise, `smooth' points are */ + /* detected and later hinted through weak interpolation to correct some */ + /* unpleasant artefacts. */ + /* */ +#undef AH_OPTION_NO_WEAK_INTERPOLATION + + + /*************************************************************************/ + /* */ + /* If this option is defined, only weak interpolation will be used to */ + /* place the points between edges. Otherwise, `strong' points are */ + /* detected and later hinted through strong interpolation to correct */ + /* some unpleasant artefacts. */ + /* */ +#undef AH_OPTION_NO_STRONG_INTERPOLATION + + + /*************************************************************************/ + /* */ + /* Undefine this macro if you don't want to hint the metrics. There is */ + /* no reason to do this (at least for non-CJK scripts), except for */ + /* experimentation. */ + /* */ +#define AH_HINT_METRICS + + + /*************************************************************************/ + /* */ + /* Define this macro if you do not want to insert extra edges at a */ + /* glyph's x and y extremum (if there isn't one already available). */ + /* This helps to reduce a number of artefacts and allows hinting of */ + /* metrics. */ + /* */ +#undef AH_OPTION_NO_EXTREMUM_EDGES + + + /* don't touch for now */ +#define AH_MAX_WIDTHS 12 +#define AH_MAX_HEIGHTS 12 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** TYPE DEFINITIONS ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /* see agangles.h */ + typedef FT_Int AH_Angle; + + + /* hint flags */ +#define ah_flah_none 0 + + /* bezier control points flags */ +#define ah_flah_conic 1 +#define ah_flah_cubic 2 +#define ah_flah_control ( ah_flah_conic | ah_flah_cubic ) + + /* extrema flags */ +#define ah_flah_extrema_x 4 +#define ah_flah_extrema_y 8 + + /* roundness */ +#define ah_flah_round_x 16 +#define ah_flah_round_y 32 + + /* touched */ +#define ah_flah_touch_x 64 +#define ah_flah_touch_y 128 + + /* weak interpolation */ +#define ah_flah_weak_interpolation 256 + + typedef FT_Int AH_Flags; + + + /* edge hint flags */ +#define ah_edge_normal 0 +#define ah_edge_round 1 +#define ah_edge_serif 2 +#define ah_edge_done 4 + + typedef FT_Int AH_Edge_Flags; + + + /* hint directions -- the values are computed so that two vectors are */ + /* in opposite directions iff `dir1+dir2 == 0' */ +#define ah_dir_none 4 +#define ah_dir_right 1 +#define ah_dir_left -1 +#define ah_dir_up 2 +#define ah_dir_down -2 + + typedef FT_Int AH_Direction; + + + typedef struct AH_Point AH_Point; + typedef struct AH_Segment AH_Segment; + typedef struct AH_Edge AH_Edge; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Point */ + /* */ + /* */ + /* A structure used to model an outline point to the AH_Outline type. */ + /* */ + /* */ + /* flags :: The current point hint flags. */ + /* */ + /* ox, oy :: The current original scaled coordinates. */ + /* */ + /* fx, fy :: The current coordinates in font units. */ + /* */ + /* x, y :: The current hinter coordinates. */ + /* */ + /* u, v :: Point coordinates -- meaning varies with context. */ + /* */ + /* in_dir :: The direction of the inwards vector (prev->point). */ + /* */ + /* out_dir :: The direction of the outwards vector (point->next). */ + /* */ + /* in_angle :: The angle of the inwards vector. */ + /* */ + /* out_angle :: The angle of the outwards vector. */ + /* */ + /* next :: The next point in same contour. */ + /* */ + /* prev :: The previous point in same contour. */ + /* */ + struct AH_Point + { + AH_Flags flags; /* point flags used by hinter */ + FT_Pos ox, oy; + FT_Pos fx, fy; + FT_Pos x, y; + FT_Pos u, v; + + AH_Direction in_dir; /* direction of inwards vector */ + AH_Direction out_dir; /* direction of outwards vector */ + + AH_Angle in_angle; + AH_Angle out_angle; + + AH_Point* next; /* next point in contour */ + AH_Point* prev; /* previous point in contour */ + }; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Segment */ + /* */ + /* */ + /* A structure used to describe an edge segment to the auto-hinter. */ + /* A segment is simply a sequence of successive points located on the */ + /* same horizontal or vertical `position', in a given direction. */ + /* */ + /* */ + /* flags :: The segment edge flags (straight, rounded, etc.). */ + /* */ + /* dir :: The segment direction. */ + /* */ + /* first :: The first point in the segment. */ + /* */ + /* last :: The last point in the segment. */ + /* */ + /* contour :: A pointer to the first point of the segment's */ + /* contour. */ + /* */ + /* pos :: The segment position in font units. */ + /* */ + /* size :: The segment size. */ + /* */ + /* edge :: The edge of the current segment. */ + /* */ + /* edge_next :: The next segment on the same edge. */ + /* */ + /* link :: The pairing segment for this edge. */ + /* */ + /* serif :: The primary segment for serifs. */ + /* */ + /* num_linked :: The number of other segments that link to this one. */ + /* */ + /* score :: Used to score the segment when selecting them. */ + /* */ + struct AH_Segment + { + AH_Edge_Flags flags; + AH_Direction dir; + + AH_Point* first; /* first point in edge segment */ + AH_Point* last; /* last point in edge segment */ + AH_Point** contour; /* ptr to first point of segment's contour */ + + FT_Pos pos; /* position of segment */ + FT_Pos min_coord; /* minimum coordinate of segment */ + FT_Pos max_coord; /* maximum coordinate of segment */ + + AH_Edge* edge; + AH_Segment* edge_next; + + AH_Segment* link; /* link segment */ + AH_Segment* serif; /* primary segment for serifs */ + FT_Pos num_linked; /* number of linked segments */ + FT_Int score; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Edge */ + /* */ + /* */ + /* A structure used to describe an edge, which really is a horizontal */ + /* or vertical coordinate to be hinted depending on the segments */ + /* located on it. */ + /* */ + /* */ + /* flags :: The segment edge flags (straight, rounded, etc.). */ + /* */ + /* dir :: The main segment direction on this edge. */ + /* */ + /* first :: The first edge segment. */ + /* */ + /* last :: The last edge segment. */ + /* */ + /* fpos :: The original edge position in font units. */ + /* */ + /* opos :: The original scaled edge position. */ + /* */ + /* pos :: The hinted edge position. */ + /* */ + /* link :: The linked edge. */ + /* */ + /* serif :: The serif edge. */ + /* */ + /* num_paired :: The number of other edges that pair to this one. */ + /* */ + /* score :: Used to score the edge when selecting them. */ + /* */ + /* blue_edge :: Indicate the blue zone edge this edge is related to. */ + /* Only set for some of the horizontal edges in a Latin */ + /* font. */ + /* */ + struct AH_Edge + { + AH_Edge_Flags flags; + AH_Direction dir; + + AH_Segment* first; + AH_Segment* last; + + FT_Pos fpos; + FT_Pos opos; + FT_Pos pos; + + AH_Edge* link; + AH_Edge* serif; + FT_Int num_linked; + + FT_Int score; + FT_Pos* blue_edge; + }; + + + /* an outline as seen by the hinter */ + typedef struct AH_Outline_ + { + FT_Memory memory; + + AH_Direction vert_major_dir; /* vertical major direction */ + AH_Direction horz_major_dir; /* horizontal major direction */ + + FT_Fixed x_scale; + FT_Fixed y_scale; + FT_Pos edge_distance_threshold; + + FT_Int max_points; + FT_Int num_points; + AH_Point* points; + + FT_Int max_contours; + FT_Int num_contours; + AH_Point** contours; + + FT_Int num_hedges; + AH_Edge* horz_edges; + + FT_Int num_vedges; + AH_Edge* vert_edges; + + FT_Int num_hsegments; + AH_Segment* horz_segments; + + FT_Int num_vsegments; + AH_Segment* vert_segments; + + } AH_Outline; + + +#define ah_blue_capital_top 0 /* THEZOCQS */ +#define ah_blue_capital_bottom ( ah_blue_capital_top + 1 ) /* HEZLOCUS */ +#define ah_blue_small_top ( ah_blue_capital_bottom + 1 ) /* xzroesc */ +#define ah_blue_small_bottom ( ah_blue_small_top + 1 ) /* xzroesc */ +#define ah_blue_small_minor ( ah_blue_small_bottom + 1 ) /* pqgjy */ +#define ah_blue_max ( ah_blue_small_minor + 1 ) + + typedef FT_Int AH_Blue; + + +#define ah_hinter_monochrome 1 +#define ah_hinter_optimize 2 + + typedef FT_Int AH_Hinter_Flags; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Globals */ + /* */ + /* */ + /* Holds the global metrics for a given font face (be it in design */ + /* units or scaled pixel values). */ + /* */ + /* */ + /* num_widths :: The number of widths. */ + /* */ + /* num_heights :: The number of heights. */ + /* */ + /* widths :: Snap widths, including standard one. */ + /* */ + /* heights :: Snap height, including standard one. */ + /* */ + /* blue_refs :: The reference positions of blue zones. */ + /* */ + /* blue_shoots :: The overshoot positions of blue zones. */ + /* */ + typedef struct AH_Globals_ + { + FT_Int num_widths; + FT_Int num_heights; + + FT_Pos widths [AH_MAX_WIDTHS]; + FT_Pos heights[AH_MAX_HEIGHTS]; + + FT_Pos blue_refs [ah_blue_max]; + FT_Pos blue_shoots[ah_blue_max]; + + } AH_Globals; + + + /*************************************************************************/ + /* */ + /* */ + /* AH_Face_Globals */ + /* */ + /* */ + /* Holds the complete global metrics for a given font face (i.e., the */ + /* design units version + a scaled version + the current scales */ + /* used). */ + /* */ + /* */ + /* face :: A handle to the source face object */ + /* */ + /* design :: The globals in font design units. */ + /* */ + /* scaled :: Scaled globals in sub-pixel values. */ + /* */ + /* x_scale :: The current horizontal scale. */ + /* */ + /* y_scale :: The current vertical scale. */ + /* */ + typedef struct AH_Face_Globals_ + { + FT_Face face; + AH_Globals design; + AH_Globals scaled; + FT_Fixed x_scale; + FT_Fixed y_scale; + FT_Bool control_overshoot; + + } AH_Face_Globals; + + + typedef struct AH_Hinter + { + FT_Memory memory; + AH_Hinter_Flags flags; + + FT_Int algorithm; + FT_Face face; + + AH_Face_Globals* globals; + + AH_Outline* glyph; + + AH_Loader* loader; + FT_Vector pp1; + FT_Vector pp2; + + } AH_Hinter; + + +#endif /* AHTYPES_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/autohint.c b/subsys/win32k/freetype/src/autohint/autohint.c new file mode 100644 index 0000000..4fb4d80 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/autohint.c @@ -0,0 +1,43 @@ +/***************************************************************************/ +/* */ +/* autohint.c */ +/* */ +/* Automatic Hinting wrapper (body only). */ +/* */ +/* Copyright 2000 Catharon Productions Inc. */ +/* Author: David Turner */ +/* */ +/* This file is part of the Catharon Typography Project and shall only */ +/* be used, modified, and distributed under the terms of the Catharon */ +/* Open Source License that should come with this file under the name */ +/* `CatharonLicense.txt'. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/* Note that this license is compatible with the FreeType license. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#ifdef FT_FLAT_COMPILE + +#include "ahangles.c" +#include "ahglyph.c" +#include "ahglobal.c" +#include "ahhint.c" +#include "ahmodule.c" + +#else + +#include +#include +#include +#include +#include + +#endif + + +/* END */ diff --git a/subsys/win32k/freetype/src/autohint/mather.py b/subsys/win32k/freetype/src/autohint/mather.py new file mode 100644 index 0000000..b416fdf --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/mather.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# + +# +# autohint math table builder +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +import math + +ag_pi = 256 + +def print_arctan( atan_bits ): + atan_base = 1 << atan_bits + + print " static AH_Angle ag_arctan[1L << AG_ATAN_BITS] =" + print " {" + + count = 0 + line = " " + + for n in range( atan_base ): + comma = "," + if ( n == atan_base - 1 ): + comma = "" + + angle = math.atan( n * 1.0 / atan_base ) / math.pi * ag_pi + line = line + " " + repr( int( angle + 0.5 ) ) + comma + count = count + 1; + if ( count == 8 ): + count = 0 + print line + line = " " + + if ( count > 0 ): + print line + print " };" + + +# This routine is not used currently. +# +def print_sines(): + print " static FT_Fixed ah_sines[AG_HALF_PI + 1] =" + print " {" + + count = 0 + line = " " + + for n in range( ag_pi / 2 ): + sinus = math.sin( n * math.pi / ag_pi ) + line = line + " " + repr( int( 65536.0 * sinus ) ) + "," + count = count + 1 + if ( count == 8 ): + count = 0 + print line + line = " " + + if ( count > 0 ): + print line + print " 65536" + print " };" + + +print_arctan( 8 ) +print + + +# END diff --git a/subsys/win32k/freetype/src/autohint/module.mk b/subsys/win32k/freetype/src/autohint/module.mk new file mode 100644 index 0000000..71e5ee3 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_autohint_module + +add_autohint_module: + $(OPEN_DRIVER)autohint_module_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)autohint $(ECHO_DRIVER_DESC)automatic hinting module$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/autohint/rules.mk b/subsys/win32k/freetype/src/autohint/rules.mk new file mode 100644 index 0000000..87f7849 --- /dev/null +++ b/subsys/win32k/freetype/src/autohint/rules.mk @@ -0,0 +1,77 @@ +# +# FreeType 2 auto-hinter module configuration rules +# + + +# Copyright 2000 Catharon Productions Inc. +# Author: David Turner +# +# This file is part of the Catharon Typography Project and shall only +# be used, modified, and distributed under the terms of the Catharon +# Open Source License that should come with this file under the name +# `CatharonLicense.txt'. By continuing to use, modify, or distribute +# this file you indicate that you have read the license and +# understand and accept it fully. +# +# Note that this license is compatible with the FreeType license. + + +# AUTO driver directory +# +AUTO_DIR := $(SRC_)autohint +AUTO_DIR_ := $(AUTO_DIR)$(SEP) + + +# compilation flags for the driver +# +AUTO_COMPILE := $(FT_COMPILE) + + +# AUTO driver sources (i.e., C files) +# +AUTO_DRV_SRC := $(AUTO_DIR_)ahangles.c \ + $(AUTO_DIR_)ahglobal.c \ + $(AUTO_DIR_)ahglyph.c \ + $(AUTO_DIR_)ahhint.c \ + $(AUTO_DIR_)ahmodule.c + +# AUTO driver headers +# +AUTO_DRV_H := $(AUTO_DRV_SRC:%c=%h) \ + $(AUTO_DIR_)ahloader.h \ + $(AUTO_DIR_)ahtypes.h + + +# AUTO driver object(s) +# +# AUTO_DRV_OBJ_M is used during `multi' builds. +# AUTO_DRV_OBJ_S is used during `single' builds. +# +AUTO_DRV_OBJ_M := $(AUTO_DRV_SRC:$(AUTO_DIR_)%.c=$(OBJ_)%.$O) +AUTO_DRV_OBJ_S := $(OBJ_)autohint.$O + +# AUTO driver source file for single build +# +AUTO_DRV_SRC_S := $(AUTO_DIR_)autohint.c + + +# AUTO driver - single object +# +$(AUTO_DRV_OBJ_S): $(AUTO_DRV_SRC_S) $(AUTO_DRV_SRC) \ + $(FREETYPE_H) $(AUTO_DRV_H) + $(AUTO_COMPILE) $T$@ $(AUTO_DRV_SRC_S) + + +# AUTO driver - multiple objects +# +$(OBJ_)%.$O: $(AUTO_DIR_)%.c $(FREETYPE_H) $(AUTO_DRV_H) + $(AUTO_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(AUTO_DRV_OBJ_S) +DRV_OBJS_M += $(AUTO_DRV_OBJ_M) + + +# EOF diff --git a/subsys/win32k/freetype/src/base/.cvsignore b/subsys/win32k/freetype/src/base/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/base/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/base/ftbase.c b/subsys/win32k/freetype/src/base/ftbase.c new file mode 100644 index 0000000..1ff4eda --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftbase.c @@ -0,0 +1,42 @@ +/***************************************************************************/ +/* */ +/* ftbase.c */ +/* */ +/* Single object library component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "ftcalc.c" +#include "ftobjs.c" +#include "ftstream.c" +#include "ftlist.c" +#include "ftoutln.c" +#include "ftextend.c" +#include "ftnames.c" + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include +#include +#include + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftcalc.c b/subsys/win32k/freetype/src/base/ftcalc.c new file mode 100644 index 0000000..d27de26 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftcalc.c @@ -0,0 +1,773 @@ +/***************************************************************************/ +/* */ +/* ftcalc.c */ +/* */ +/* Arithmetic computations (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* Support for 1-complement arithmetic has been totally dropped in this */ + /* release. You can still write your own code if you need it. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* Implementing basic computation routines. */ + /* */ + /* FT_MulDiv(), FT_MulFix(), and FT_DivFix() are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include /* for ABS() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_calc + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + static const FT_Long ft_square_roots[63] = + { + 1L, 1L, 2L, 3L, 4L, 5L, 8L, 11L, + 16L, 22L, 32L, 45L, 64L, 90L, 128L, 181L, + 256L, 362L, 512L, 724L, 1024L, 1448L, 2048L, 2896L, + 4096L, 5892L, 8192L, 11585L, 16384L, 23170L, 32768L, 46340L, + + 65536L, 92681L, 131072L, 185363L, 262144L, 370727L, + 524288L, 741455L, 1048576L, 1482910L, 2097152L, 2965820L, + 4194304L, 5931641L, 8388608L, 11863283L, 16777216L, 23726566L, + + 33554432L, 47453132L, 67108864L, 94906265L, + 134217728L, 189812531L, 268435456L, 379625062L, + 536870912L, 759250125L, 1073741824L, 1518500250L, + 2147483647L + }; + +#else + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt32 */ + /* */ + /* */ + /* Computes the square root of an Int32 integer (which will be */ + /* handled as an unsigned long value). */ + /* */ + /* */ + /* x :: The value to compute the root for. */ + /* */ + /* */ + /* The result of `sqrt(x)'. */ + /* */ + FT_EXPORT_FUNC( FT_Int32 ) FT_Sqrt32( FT_Int32 x ) + { + FT_ULong val, root, newroot, mask; + + + root = 0; + mask = 0x40000000L; + val = (FT_ULong)x; + + do + { + newroot = root + mask; + if ( newroot <= val ) + { + val -= newroot; + root = newroot + mask; + } + + root >>= 1; + mask >>= 2; + + } while ( mask != 0 ); + + return root; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#ifdef FT_LONG64 + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* with maximal accuracy (it uses a 64-bit intermediate integer */ + /* whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + FT_EXPORT_FUNC( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { + FT_Int s; + + + s = 1; + if ( a < 0 ) { a = -a; s = -s; } + if ( b < 0 ) { b = -b; s = -s; } + if ( c < 0 ) { c = -c; s = -s; } + + return s * ( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c + : 0x7FFFFFFFL ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*b)/0x10000' with maximal accuracy. Most of the time this is */ + /* used to multiply a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* This function has been optimized for the case where the absolute */ + /* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */ + /* As this happens mainly when scaling from notional units to */ + /* fractional pixels in FreeType, it resulted in noticeable speed */ + /* improvements between versions 2.x and 1.x. */ + /* */ + /* As a conclusion, always try to place a 16.16 factor as the */ + /* _second_ argument of this function; this can make a great */ + /* difference. */ + /* */ + FT_EXPORT_FUNC( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Int s; + + + s = 1; + if ( a < 0 ) { a = -a; s = -s; } + if ( b < 0 ) { b = -b; s = -s; } + + return s * (FT_Long)( ( (FT_Int64)a * b + 0x8000 ) >> 16 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ + /* used to divide a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits in */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of the old FT_MulDiv64(). */ + /* */ + FT_EXPORT_FUNC( FT_Long ) FT_DivFix( FT_Long a, + FT_Long b ) + { + FT_Int32 s; + FT_UInt32 q; + + + s = a; a = ABS(a); + s ^= b; b = ABS(b); + + if ( b == 0 ) + /* check for division by 0 */ + q = 0x7FFFFFFFL; + else + /* compute result directly */ + q = ( (FT_Int64)a << 16 ) / b; + + return (FT_Int32)( s < 0 ? -q : q ); + } + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + /* a helper function for FT_Sqrt64() */ + + static + int ft_order64( FT_Int64 z ) + { + int j = 0; + + + while ( z ) + { + z = (unsigned FT_INT64)z >> 1; + j++; + } + return j - 1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* Computes the square root of a 64-bit value. That sounds stupid, */ + /* but it is needed to obtain maximal accuracy in the TrueType */ + /* bytecode interpreter. */ + /* */ + /* */ + /* l :: A 64-bit integer. */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + FT_EXPORT_FUNC( FT_Int32 ) FT_Sqrt64( FT_Int64 l ) + { + FT_Int64 r, s; + + + if ( l <= 0 ) return 0; + if ( l == 1 ) return 1; + + r = ft_square_roots[ft_order64( l )]; + + do + { + s = r; + r = ( r + l / r ) >> 1; + + } while ( r > s || r * r > l ); + + return r; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + +#else /* FT_LONG64 */ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulDiv */ + /* */ + /* */ + /* A very simple function used to perform the computation `(a*b)/c' */ + /* with maximal accuracy (it uses a 64-bit intermediate integer */ + /* whenever necessary). */ + /* */ + /* This function isn't necessarily as fast as some processor specific */ + /* operations, but is at least completely portable. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. */ + /* c :: The divisor. */ + /* */ + /* */ + /* The result of `(a*b)/c'. This function never traps when trying to */ + /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ + /* on the signs of `a' and `b'. */ + /* */ + /* */ + /* The FT_MulDiv() function has been optimized thanks to ideas from */ + /* Graham Asher. The trick is to optimize computation if everything */ + /* fits within 32 bits (a rather common case). */ + /* */ + /* We compute `a*b+c/2', then divide it by `c' (positive values). */ + /* */ + /* 46340 is FLOOR(SQRT(2^31-1)). */ + /* */ + /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */ + /* */ + /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */ + /* */ + /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */ + /* */ + /* and 2*0x157F0 = 176096. */ + /* */ + FT_EXPORT_FUNC( FT_Long ) FT_MulDiv( FT_Long a, + FT_Long b, + FT_Long c ) + { + long s; + + + if ( a == 0 || b == c ) + return a; + + s = a; a = ABS( a ); + s ^= b; b = ABS( b ); + s ^= c; c = ABS( c ); + + if ( a <= 46340 && b <= 46340 && c <= 176095L && c > 0 ) + { + a = ( a * b + ( c >> 1 ) ) / c; + } + else if ( c > 0 ) + { + FT_Int64 temp, temp2; + + + FT_MulTo64( a, b, &temp ); + temp2.hi = (FT_Int32)( c >> 31 ); + temp2.lo = (FT_UInt32)( c / 2 ); + FT_Add64( &temp, &temp2, &temp ); + a = FT_Div64by32( &temp, c ); + } + else + a = 0x7FFFFFFFL; + + return ( s < 0 ? -a : a ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*b)/0x10000' with maximal accuracy. Most of the time, this is */ + /* used to multiply a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*b)/0x10000'. */ + /* */ + /* */ + /* The optimization for FT_MulFix() is different. We could simply be */ + /* happy by applying the same principles as with FT_MulDiv(), because */ + /* */ + /* c = 0x10000 < 176096 */ + /* */ + /* However, in most cases, we have a `b' with a value around 0x10000 */ + /* which is greater than 46340. */ + /* */ + /* According to some testing, most cases have `a' < 2048, so a good */ + /* idea is to use bounds like 2048 and 1048576 (=floor((2^31-1)/2048) */ + /* for `a' and `b', respectively. */ + /* */ + FT_EXPORT_FUNC( FT_Long ) FT_MulFix( FT_Long a, + FT_Long b ) + { + FT_Long s; + FT_ULong ua, ub; + + + if ( a == 0 || b == 0x10000L ) + return a; + + s = a; a = ABS(a); + s ^= b; b = ABS(b); + + ua = (FT_ULong)a; + ub = (FT_ULong)b; + + if ( ua <= 2048 && ub <= 1048576L ) + { + ua = ( ua * ub + 0x8000 ) >> 16; + } + else + { + FT_ULong al = ua & 0xFFFF; + + + ua = ( ua >> 16 ) * ub + + al * ( ub >> 16 ) + + ( al * ( ub & 0xFFFF ) >> 16 ); + } + + return ( s < 0 ? -(FT_Long)ua : ua ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_DivFix */ + /* */ + /* */ + /* A very simple function used to perform the computation */ + /* `(a*0x10000)/b' with maximal accuracy. Most of the time, this is */ + /* used to divide a given value by a 16.16 fixed float factor. */ + /* */ + /* */ + /* a :: The first multiplier. */ + /* b :: The second multiplier. Use a 16.16 factor here whenever */ + /* possible (see note below). */ + /* */ + /* */ + /* The result of `(a*0x10000)/b'. */ + /* */ + /* */ + /* The optimization for FT_DivFix() is simple: If (a << 16) fits into */ + /* 32 bits, then the division is computed directly. Otherwise, we */ + /* use a specialized version of the old FT_MulDiv64(). */ + /* */ + FT_EXPORT_FUNC( FT_Long ) FT_DivFix( FT_Long a, + FT_Long b ) + { + FT_Int32 s; + FT_UInt32 q; + + + s = a; a = ABS(a); + s ^= b; b = ABS(b); + + if ( b == 0 ) + { + /* check for division by 0 */ + q = 0x7FFFFFFFL; + } + else if ( ( a >> 16 ) == 0 ) + { + /* compute result directly */ + q = (FT_UInt32)( a << 16 ) / (FT_UInt32)b; + } + else + { + /* we need more bits; we have to do it by hand */ + FT_UInt32 c; + + + q = ( a / b ) << 16; + c = a % b; + + /* we must compute C*0x10000/B: we simply shift C and B so */ + /* C becomes smaller than 16 bits */ + while ( c >> 16 ) + { + c >>= 1; + b <<= 1; + } + + q += ( c << 16 ) / b; + } + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add64 */ + /* */ + /* */ + /* Add two Int64 values. */ + /* */ + /* */ + /* x :: A pointer to the first value to be added. */ + /* y :: A pointer to the second value to be added. */ + /* */ + /* */ + /* z :: A pointer to the result of `x + y'. */ + /* */ + /* */ + /* Will be wrapped by the ADD_64() macro. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Add64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ) + { + register FT_UInt32 lo, hi; + + + lo = x->lo + y->lo; + hi = x->hi + y->hi + ( lo < x->lo ); + + z->lo = lo; + z->hi = hi; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_MulTo64 */ + /* */ + /* */ + /* Multiplies two Int32 integers. Returns an Int64 integer. */ + /* */ + /* */ + /* x :: The first multiplier. */ + /* y :: The second multiplier. */ + /* */ + /* */ + /* z :: A pointer to the result of `x * y'. */ + /* */ + /* */ + /* Will be wrapped by the MUL_64() macro. */ + /* */ + FT_EXPORT_FUNC( void ) FT_MulTo64( FT_Int32 x, + FT_Int32 y, + FT_Int64* z ) + { + FT_Int32 s; + + + s = x; x = ABS( x ); + s ^= y; y = ABS( y ); + + { + FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; + + + lo1 = x & 0x0000FFFF; hi1 = x >> 16; + lo2 = y & 0x0000FFFF; hi2 = y >> 16; + + lo = lo1 * lo2; + i1 = lo1 * hi2; + i2 = lo2 * hi1; + hi = hi1 * hi2; + + /* Check carry overflow of i1 + i2 */ + i1 += i2; + if ( i1 < i2 ) + hi += 1L << 16; + + hi += i1 >> 16; + i1 = i1 << 16; + + /* Check carry overflow of i1 + lo */ + lo += i1; + hi += ( lo < i1 ); + + z->lo = lo; + z->hi = hi; + } + + if ( s < 0 ) + { + z->lo = (FT_UInt32)-(FT_Int32)z->lo; + z->hi = ~z->hi + !( z->lo ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Div64by32 */ + /* */ + /* */ + /* Divides an Int64 value by an Int32 value. Returns an Int32 */ + /* integer. */ + /* */ + /* */ + /* x :: A pointer to the dividend. */ + /* y :: The divisor. */ + /* */ + /* */ + /* The result of `x / y'. */ + /* */ + /* */ + /* Will be wrapped by the DIV_64() macro. */ + /* */ + FT_EXPORT_FUNC( FT_Int32 ) FT_Div64by32( FT_Int64* x, + FT_Int32 y ) + { + FT_Int32 s; + FT_UInt32 q, r, i, lo; + + + s = x->hi; + if ( s < 0 ) + { + x->lo = (FT_UInt32)-(FT_Int32)x->lo; + x->hi = ~x->hi + !( x->lo ); + } + s ^= y; y = ABS( y ); + + /* Shortcut */ + if ( x->hi == 0 ) + { + if ( y > 0 ) + q = x->lo / y; + else + q = 0x7FFFFFFFL; + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + r = x->hi; + lo = x->lo; + + if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */ + return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL ); + /* Return Max/Min Int32 if division overflow. */ + /* This includes division by zero! */ + q = 0; + for ( i = 0; i < 32; i++ ) + { + r <<= 1; + q <<= 1; + r |= lo >> 31; + + if ( r >= (FT_UInt32)y ) + { + r -= y; + q |= 1; + } + lo <<= 1; + } + + return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q ); + } + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + + /* two helper functions for FT_Sqrt64() */ + + static + void FT_Sub64( FT_Int64* x, + FT_Int64* y, + FT_Int64* z ) + { + register FT_UInt32 lo, hi; + + + lo = x->lo - y->lo; + hi = x->hi - y->hi - ( (FT_Int32)lo < 0 ); + + z->lo = lo; + z->hi = hi; + } + + + static + int ft_order64( FT_Int64* z ) + { + FT_UInt32 i; + int j; + + + i = z->lo; + j = 0; + if ( z->hi ) + { + i = z->hi; + j = 32; + } + + while ( i > 0 ) + { + i >>= 1; + j++; + } + return j - 1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* Computes the square root of a 64-bits value. That sounds stupid, */ + /* but it is needed to obtain maximal accuracy in the TrueType */ + /* bytecode interpreter. */ + /* */ + /* */ + /* z :: A pointer to a 64-bit integer. */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + FT_EXPORT_FUNC( FT_Int32 ) FT_Sqrt64( FT_Int64* l ) + { + FT_Int64 l2; + FT_Int32 r, s; + + + if ( (FT_Int32)l->hi < 0 || + ( l->hi == 0 && l->lo == 0 ) ) + return 0; + + s = ft_order64( l ); + if ( s == 0 ) + return 1; + + r = ft_square_roots[s]; + do + { + s = r; + r = ( r + FT_Div64by32( l, r ) ) >> 1; + FT_MulTo64( r, r, &l2 ); + FT_Sub64 ( l, &l2, &l2 ); + + } while ( r > s || (FT_Int32)l2.hi < 0 ); + + return r; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + +#endif /* FT_LONG64 */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftdebug.c b/subsys/win32k/freetype/src/base/ftdebug.c new file mode 100644 index 0000000..da8b3b4 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftdebug.c @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* */ +/* ftdebug.c */ +/* */ +/* Debugging and logging component (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This component contains various macros and functions used to ease the */ + /* debugging of the FreeType engine. Its main purpose is in assertion */ + /* checking, tracing, and error detection. */ + /* */ + /* There are now three debugging modes: */ + /* */ + /* - trace mode */ + /* */ + /* Error and trace messages are sent to the log file (which can be the */ + /* standard error output). */ + /* */ + /* - error mode */ + /* */ + /* Only error messages are generated. */ + /* */ + /* - release mode: */ + /* */ + /* No error message is sent or generated. The code is free from any */ + /* debugging parts. */ + /* */ + /*************************************************************************/ + + +#include + +#ifdef FT_DEBUG_LEVEL_TRACE + char ft_trace_levels[trace_max]; +#endif + + +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + + +#include +#include +#include + + + FT_EXPORT_FUNC( void ) FT_Message( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + } + + + FT_EXPORT_FUNC( void ) FT_Panic( const char* fmt, ... ) + { + va_list ap; + + + va_start( ap, fmt ); +/* vprintf( fmt, ap ); FIXME */ + va_end( ap ); + +/* exit( EXIT_FAILURE ); FIXME */ + } + + +#ifdef FT_DEBUG_LEVEL_TRACE + + + /*************************************************************************/ + /* */ + /* */ + /* FT_SetTraceLevel */ + /* */ + /* */ + /* Sets the trace level for debugging. */ + /* */ + /* */ + /* component :: The component which should be traced. See ftdebug.h */ + /* for a complete list. If set to `trace_any', all */ + /* components will be traced. */ + /* level :: The tracing level. */ + /* */ + FT_EXPORT_FUNC( void ) FT_SetTraceLevel( FT_Trace component, + char level ) + { + if ( component >= trace_max ) + return; + + /* if component is `trace_any', change _all_ levels at once */ + if ( component == trace_any ) + { + int n; + + + for ( n = trace_any; n < trace_max; n++ ) + ft_trace_levels[n] = level; + } + else /* otherwise, only change individual component */ + ft_trace_levels[component] = level; + } + +#endif /* FT_DEBUG_LEVEL_TRACE */ + +#endif /* FT_DEBUG_LEVEL_TRACE || FT_DEBUG_LEVEL_ERROR */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftextend.c b/subsys/win32k/freetype/src/base/ftextend.c new file mode 100644 index 0000000..f298b19 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftextend.c @@ -0,0 +1,332 @@ +/***************************************************************************/ +/* */ +/* ftextend.h */ +/* */ +/* FreeType extensions implementation (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This is an updated version of the extension component, now located */ + /* in the main library's source directory. It allows the dynamic */ + /* registration/use of various face object extensions through a simple */ + /* API. */ + /* */ + /*************************************************************************/ + + +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_extend + + + typedef struct FT_Extension_Registry_ + { + FT_Int num_extensions; + FT_Long cur_offset; + FT_Extension_Class classes[FT_MAX_EXTENSIONS]; + + } FT_Extension_Registry; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_Extensions */ + /* */ + /* */ + /* Initializes the extension component. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error FT_Init_Extensions( FT_Driver driver ) + { + FT_Error error; + FT_Memory memory; + FT_Extension_Registry* registry; + + + memory = driver->root.library->memory; + if ( ALLOC( registry, sizeof ( *registry ) ) ) + return error; + + registry->num_extensions = 0; + registry->cur_offset = 0; + driver->extensions = registry; + + FT_TRACE2(( "FT_Init_Extensions: success\n" )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Extensions */ + /* */ + /* */ + /* Finalizes the extension component. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error FT_Done_Extensions( FT_Driver driver ) + { + FT_Memory memory = driver->root.memory; + + + FREE( driver->extensions ); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Register_Extension */ + /* */ + /* */ + /* Registers a new extension. */ + /* */ + /* */ + /* driver :: A handle to the driver object. */ + /* class :: A pointer to a class describing the extension. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Register_Extension( + FT_Driver driver, + FT_Extension_Class* clazz ) + { + FT_Extension_Registry* registry; + + + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + if ( !clazz ) + return FT_Err_Invalid_Argument; + + registry = (FT_Extension_Registry*)driver->extensions; + if ( registry ) + { + FT_Int n = registry->num_extensions; + FT_Extension_Class* cur = registry->classes + n; + + + if ( n >= FT_MAX_EXTENSIONS ) + return FT_Err_Too_Many_Extensions; + + *cur = *clazz; + + cur->offset = registry->cur_offset; + + registry->num_extensions++; + registry->cur_offset += + ( cur->size + FT_ALIGNMENT - 1 ) & -FT_ALIGNMENT; + + FT_TRACE1(( "FT_Register_Extension: `%s' successfully registered\n", + cur->id )); + } + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Extension */ + /* */ + /* */ + /* Queries an extension block by an extension ID string. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* extension_id :: An ID string identifying the extension. */ + /* */ + /* */ + /* extension_interface :: A generic pointer, usually pointing to a */ + /* table of functions implementing the */ + /* extension interface. */ + /* */ + /* */ + /* A generic pointer to the extension block. */ + /* */ + FT_EXPORT_FUNC( void* ) FT_Get_Extension( + FT_Face face, + const char* extension_id, + void** extension_interface ) + { + FT_Extension_Registry* registry; + + + if ( !face || !extension_id || !extension_interface ) + return 0; + + registry = (FT_Extension_Registry*)face->driver->extensions; + if ( registry && face->extensions ) + { + FT_Extension_Class* cur = registry->classes; + FT_Extension_Class* limit = cur + registry->num_extensions; + + + for ( ; cur < limit; cur++ ) + if ( strcmp( cur->id, extension_id ) == 0 ) + { + *extension_interface = cur->interface; + + FT_TRACE1(( "FT_Get_Extension: got `%s'\n", extension_id )); + + return (void*)((char*)face->extensions + cur->offset); + } + } + + /* could not find the extension id */ + + FT_ERROR(( "FT_Get_Extension: couldn't find `%s'\n", extension_id )); + + *extension_interface = 0; + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Destroy_Extensions */ + /* */ + /* */ + /* Destroys all extensions within a face object. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Called by the face object destructor. */ + /* */ + LOCAL_FUNC + FT_Error FT_Destroy_Extensions( FT_Face face ) + { + FT_Extension_Registry* registry; + FT_Memory memory; + + + registry = (FT_Extension_Registry*)face->driver->extensions; + if ( registry && face->extensions ) + { + FT_Extension_Class* cur = registry->classes; + FT_Extension_Class* limit = cur + registry->num_extensions; + + + for ( ; cur < limit; cur++ ) + { + char* ext = (char*)face->extensions + cur->offset; + + if ( cur->finalize ) + cur->finalize( ext, face ); + } + + memory = face->driver->root.memory; + FREE( face->extensions ); + } + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Create_Extensions */ + /* */ + /* */ + /* Creates an extension object within a face object for all */ + /* registered extensions. */ + /* */ + /* */ + /* face :: A handle to the face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Called by the face object constructor. */ + /* */ + LOCAL_FUNC + FT_Error FT_Create_Extensions( FT_Face face ) + { + FT_Extension_Registry* registry; + FT_Memory memory; + FT_Error error; + + + face->extensions = 0; + + /* load extensions registry; exit successfully if none is there */ + + registry = (FT_Extension_Registry*)face->driver->extensions; + if ( !registry ) + return FT_Err_Ok; + + memory = face->driver->root.memory; + if ( ALLOC( face->extensions, registry->cur_offset ) ) + return error; + + { + FT_Extension_Class* cur = registry->classes; + FT_Extension_Class* limit = cur + registry->num_extensions; + + + for ( ; cur < limit; cur++ ) + { + char* ext = (char*)face->extensions + cur->offset; + + if ( cur->init ) + { + error = cur->init( ext, face ); + if ( error ) + break; + } + } + } + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftglyph.c b/subsys/win32k/freetype/src/base/ftglyph.c new file mode 100644 index 0000000..4052e6e --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftglyph.c @@ -0,0 +1,1184 @@ +/***************************************************************************/ +/* */ +/* ftglyph.c */ +/* */ +/* FreeType convenience functions to handle glyphs (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file contains the definition of several convenience functions */ + /* that can be used by client applications to easily retrieve glyph */ + /* bitmaps and outlines from a given face. */ + /* */ + /* These functions should be optional if you are writing a font server */ + /* or text layout engine on top of FreeType. However, they are pretty */ + /* handy for many other simple uses of the library. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_glyph + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** Convenience functions ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Multiply */ + /* */ + /* */ + /* Performs the matrix operation `b = a*b'. */ + /* */ + /* */ + /* a :: A pointer to matrix `a'. */ + /* */ + /* */ + /* b :: A pointer to matrix `b'. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `a' or `b' is zero. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Matrix_Multiply( FT_Matrix* a, + FT_Matrix* b ) + { + FT_Fixed xx, xy, yx, yy; + + + if ( !a || !b ) + return; + + xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx ); + xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy ); + yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx ); + yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy ); + + b->xx = xx; b->xy = xy; + b->yx = yx; b->yy = yy; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Matrix_Invert */ + /* */ + /* */ + /* Inverts a 2x2 matrix. Returns an error if it can't be inverted. */ + /* */ + /* */ + /* matrix :: A pointer to the target matrix. Remains untouched in */ + /* case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Matrix_Invert( FT_Matrix* matrix ) + { + FT_Pos delta, xx, yy; + + + if ( !matrix ) + return FT_Err_Invalid_Argument; + + /* compute discriminant */ + delta = FT_MulFix( matrix->xx, matrix->yy ) - + FT_MulFix( matrix->xy, matrix->yx ); + + if ( !delta ) + return FT_Err_Invalid_Argument; /* matrix can't be inverted */ + + matrix->xy = - FT_DivFix( matrix->xy, delta ); + matrix->yx = - FT_DivFix( matrix->yx, delta ); + + xx = matrix->xx; + yy = matrix->yy; + + matrix->xx = FT_DivFix( yy, delta ); + matrix->yy = FT_DivFix( xx, delta ); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_BitmapGlyph support ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + static + FT_Error ft_bitmap_copy( FT_Memory memory, + FT_Bitmap* source, + FT_Bitmap* target ) + { + FT_Error error; + FT_Int pitch = source->pitch; + FT_ULong size; + + + *target = *source; + + if ( pitch < 0 ) + pitch = -pitch; + + size = (FT_ULong)( pitch * source->rows ); + + if ( !ALLOC( target->buffer, size ) ) + MEM_Copy( source->buffer, target->buffer, size ); + + return error; + } + + + static + FT_Error ft_bitmap_glyph_init( FT_BitmapGlyph glyph, + FT_GlyphSlot slot ) + { + FT_Error error = FT_Err_Ok; + FT_Library library = FT_GLYPH(glyph)->library; + FT_Memory memory = library->memory; + + + if ( slot->format != ft_glyph_format_bitmap ) + { + error = FT_Err_Invalid_Glyph_Format; + goto Exit; + } + + /* grab the bitmap in the slot - do lazy copying whenever possible */ + glyph->bitmap = slot->bitmap; + glyph->left = slot->bitmap_left; + glyph->top = slot->bitmap_top; + + if ( slot->flags & ft_glyph_own_bitmap ) + slot->flags &= ~ft_glyph_own_bitmap; + else + { + /* copy the bitmap into a new buffer */ + error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap ); + } + + Exit: + return error; + } + + + static + FT_Error ft_bitmap_glyph_copy( FT_BitmapGlyph source, + FT_BitmapGlyph target ) + { + FT_Memory memory = source->root.library->memory; + + + target->left = source->left; + target->top = source->top; + + return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap ); + } + + + static + void ft_bitmap_glyph_done( FT_BitmapGlyph glyph ) + { + FT_Memory memory = FT_GLYPH(glyph)->library->memory; + + + FREE( glyph->bitmap.buffer ); + } + + + static + void ft_bitmap_glyph_bbox( FT_BitmapGlyph glyph, + FT_BBox* cbox ) + { + cbox->xMin = glyph->left << 6; + cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 ); + cbox->yMax = glyph->top << 6; + cbox->yMin = cbox->xMax - ( glyph->bitmap.rows << 6 ); + } + + + const FT_Glyph_Class ft_bitmap_glyph_class = + { + sizeof( FT_BitmapGlyphRec ), + ft_glyph_format_bitmap, + + (FT_Glyph_Init_Func) ft_bitmap_glyph_init, + (FT_Glyph_Done_Func) ft_bitmap_glyph_done, + (FT_Glyph_Copy_Func) ft_bitmap_glyph_copy, + (FT_Glyph_Transform_Func)0, + (FT_Glyph_BBox_Func) ft_bitmap_glyph_bbox, + (FT_Glyph_Prepare_Func) 0 + }; + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_OutlineGlyph support ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error ft_outline_glyph_init( FT_OutlineGlyph glyph, + FT_GlyphSlot slot ) + { + FT_Error error = FT_Err_Ok; + FT_Library library = FT_GLYPH(glyph)->library; + FT_Outline* source = &slot->outline; + FT_Outline* target = &glyph->outline; + + + /* check format in glyph slot */ + if ( slot->format != ft_glyph_format_outline ) + { + error = FT_Err_Invalid_Glyph_Format; + goto Exit; + } + + /* allocate new outline */ + error = FT_Outline_New( library, source->n_points, source->n_contours, + &glyph->outline ); + if ( error ) + goto Exit; + + /* copy it */ + MEM_Copy( target->points, source->points, + source->n_points * sizeof ( FT_Vector ) ); + + MEM_Copy( target->tags, source->tags, + source->n_points * sizeof ( FT_Byte ) ); + + MEM_Copy( target->contours, source->contours, + source->n_contours * sizeof ( FT_Short ) ); + + /* copy all flags, except the `ft_outline_owner' one */ + target->flags = source->flags | ft_outline_owner; + + Exit: + return error; + } + + + static + void ft_outline_glyph_done( FT_OutlineGlyph glyph ) + { + FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); + } + + + static + FT_Error ft_outline_glyph_copy( FT_OutlineGlyph source, + FT_OutlineGlyph target ) + { + FT_Error error; + FT_Library library = FT_GLYPH( source )->library; + + + error = FT_Outline_New( library, source->outline.n_points, + source->outline.n_contours, &target->outline ); + if ( !error ) + FT_Outline_Copy( &source->outline, &target->outline ); + + return error; + } + + + static + void ft_outline_glyph_transform( FT_OutlineGlyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ) + { + if ( matrix ) + FT_Outline_Transform( &glyph->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); + } + + + static + void ft_outline_glyph_bbox( FT_OutlineGlyph glyph, + FT_BBox* bbox ) + { + FT_Outline_Get_CBox( &glyph->outline, bbox ); + } + + + static + FT_Error ft_outline_glyph_prepare( FT_OutlineGlyph glyph, + FT_GlyphSlot slot ) + { + slot->format = ft_glyph_format_outline; + slot->outline = glyph->outline; + slot->outline.flags &= ~ft_outline_owner; + + return FT_Err_Ok; + } + + + const FT_Glyph_Class ft_outline_glyph_class = + { + sizeof( FT_OutlineGlyphRec ), + ft_glyph_format_outline, + + (FT_Glyph_Init_Func) ft_outline_glyph_init, + (FT_Glyph_Done_Func) ft_outline_glyph_done, + (FT_Glyph_Copy_Func) ft_outline_glyph_copy, + (FT_Glyph_Transform_Func)ft_outline_glyph_transform, + (FT_Glyph_BBox_Func) ft_outline_glyph_bbox, + (FT_Glyph_Prepare_Func) ft_outline_glyph_prepare + }; + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** FT_Glyph class and API ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + static + FT_Error ft_new_glyph( FT_Library library, + const FT_Glyph_Class* clazz, + FT_Glyph* aglyph ) + { + FT_Memory memory = library->memory; + FT_Error error; + FT_Glyph glyph; + + + *aglyph = 0; + + if ( !ALLOC( glyph, clazz->glyph_size ) ) + { + glyph->library = library; + glyph->clazz = clazz; + glyph->format = clazz->glyph_format; + + *aglyph = glyph; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Copy */ + /* */ + /* */ + /* A function used to copy a glyph image. */ + /* */ + /* */ + /* source :: A handle to the source glyph object. */ + /* */ + /* */ + /* target :: A handle to the target glyph object. 0 in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Glyph_Copy( FT_Glyph source, + FT_Glyph* target ) + { + FT_Glyph copy; + FT_Error error; + const FT_Glyph_Class* clazz; + + + /* check arguments */ + if ( !target || !source || !source->clazz ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + *target = 0; + + clazz = source->clazz; + error = ft_new_glyph( source->library, clazz, © ); + if ( error ) + goto Exit; + + if ( clazz->glyph_copy ) + error = clazz->glyph_copy( source, copy ); + + if ( error ) + FT_Done_Glyph( copy ); + else + *target = copy; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph */ + /* */ + /* */ + /* A function used to extract a glyph image from a slot. */ + /* */ + /* */ + /* slot :: A handle to the source glyph slot. */ + /* */ + /* */ + /* aglyph :: A handle to the glyph object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Get_Glyph( FT_GlyphSlot slot, + FT_Glyph* aglyph ) + { + FT_Library library = slot->library; + FT_Error error; + FT_Glyph glyph; + + const FT_Glyph_Class* clazz = 0; + + + if ( !slot ) + return FT_Err_Invalid_Slot_Handle; + + if ( !aglyph ) + return FT_Err_Invalid_Argument; + + /* if it is a bitmap, that's easy :-) */ + if ( slot->format == ft_glyph_format_bitmap ) + clazz = &ft_bitmap_glyph_class; + + /* it it is an outline too */ + else if ( slot->format == ft_glyph_format_outline ) + clazz = &ft_outline_glyph_class; + + else + { + /* try to find a renderer that supports the glyph image format */ + FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 ); + + + if ( render ) + clazz = &render->glyph_class; + } + + if ( !clazz ) + { + error = FT_Err_Invalid_Glyph_Format; + goto Exit; + } + + /* create FT_Glyph object */ + error = ft_new_glyph( library, clazz, &glyph ); + if ( error ) + goto Exit; + + /* copy advance while converting it to 16.16 format */ + glyph->advance.x = slot->advance.x << 10; + glyph->advance.y = slot->advance.y << 10; + + /* now import the image from the glyph slot */ + error = clazz->glyph_init( glyph, slot ); + + /* if an error occurred, destroy the glyph */ + if ( error ) + FT_Done_Glyph( glyph ); + else + *aglyph = glyph; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Transform */ + /* */ + /* */ + /* Transforms a glyph image if its format is scalable. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + /* matrix :: A pointer to a 2x2 matrix to apply. */ + /* */ + /* delta :: A pointer to a 2d vector to apply. Coordinates are */ + /* expressed in 1/64th of a pixel. */ + /* */ + /* */ + /* FreeType error code (the glyph format is not scalable if it is */ + /* not zero). */ + /* */ + /* */ + /* The 2x2 transformation matrix is also applied to the glyph's */ + /* advance vector. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Glyph_Transform( FT_Glyph glyph, + FT_Matrix* matrix, + FT_Vector* delta ) + { + const FT_Glyph_Class* clazz; + FT_Error error = FT_Err_Ok; + + + if ( !glyph || !glyph->clazz ) + error = FT_Err_Invalid_Argument; + else + { + clazz = glyph->clazz; + if ( clazz->glyph_transform ) + { + /* transform glyph image */ + clazz->glyph_transform( glyph, matrix, delta ); + + /* transform advance vector */ + if ( matrix ) + FT_Vector_Transform( &glyph->advance, matrix ); + } + else + error = FT_Err_Invalid_Glyph_Format; + } + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_Get_CBox */ + /* */ + /* */ + /* Returns the glyph image's bounding box. */ + /* */ + /* */ + /* glyph :: A handle to the source glyph object. */ + /* */ + /* mode :: A set of bit flags that indicate how to interpret the */ + /* returned bounding box values. */ + /* */ + /* */ + /* box :: The glyph bounding box. Coordinates are expressed in */ + /* 1/64th of pixels if it is grid-fitted. */ + /* */ + /* */ + /* Coordinates are relative to the glyph origin, using the Y-upwards */ + /* convention. */ + /* */ + /* If `ft_glyph_bbox_subpixels' is set in `mode', the bbox */ + /* coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels). */ + /* Otherwise, coordinates are expressed in integer pixels. */ + /* */ + /* Note that the maximum coordinates are exclusive, which means that */ + /* one can compute the width and height of the glyph image (be it in */ + /* integer or 26.6 pixels) as: */ + /* */ + /* width = bbox.xMax - bbox.xMin; */ + /* height = bbox.yMax - bbox.yMin; */ + /* */ + /* Note also that for 26.6 coordinates, if the */ + /* `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates */ + /* will also be grid-fitted, which corresponds to: */ + /* */ + /* bbox.xMin = FLOOR(bbox.xMin); */ + /* bbox.yMin = FLOOR(bbox.yMin); */ + /* bbox.xMax = CEILING(bbox.xMax); */ + /* bbox.yMax = CEILING(bbox.yMax); */ + /* */ + /* The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Glyph_Get_CBox( FT_Glyph glyph, + FT_UInt bbox_mode, + FT_BBox* cbox ) + { + const FT_Glyph_Class* clazz; + FT_Error error = FT_Err_Ok; + + + if ( !cbox || !glyph || !glyph->clazz ) + error = FT_Err_Invalid_Argument; + else + { + clazz = glyph->clazz; + if ( !clazz->glyph_bbox ) + error = FT_Err_Invalid_Glyph_Format; + else + { + /* retrieve bbox in 26.6 coordinates */ + clazz->glyph_bbox( glyph, cbox ); + + /* perform grid fitting if needed */ + if ( bbox_mode & ft_glyph_bbox_gridfit ) + { + cbox->xMin &= -64; + cbox->yMin &= -64; + cbox->xMax = ( cbox->xMax + 63 ) & -64; + cbox->yMax = ( cbox->yMax + 63 ) & -64; + } + + /* convert to integer pixels if needed */ + if ( !( bbox_mode & ft_glyph_bbox_subpixels ) ) + { + cbox->xMin >>= 6; + cbox->yMin >>= 6; + cbox->xMax >>= 6; + cbox->yMax >>= 6; + } + } + } + return; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Glyph_To_Bitmap */ + /* */ + /* */ + /* Converts a given glyph object to a bitmap glyph object. */ + /* */ + /* */ + /* glyph :: A pointer to a handle to the target glyph. */ + /* */ + /* */ + /* render_mode :: A set of bit flags that describe how the data is */ + /* */ + /* */ + /* origin :: A pointer to a vector used to translate the glyph */ + /* image before rendering. Can be 0 (if no */ + /* translation). The origin is expressed in */ + /* 26.6 pixels. */ + /* */ + /* destroy :: A boolean that indicates that the original glyph */ + /* image should be destroyed by this function. It is */ + /* never destroyed in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The glyph image is translated with the `origin' vector before */ + /* rendering. In case of error, it it translated back to its */ + /* original position and the glyph is left untouched. */ + /* */ + /* The first parameter is a pointer to a FT_Glyph handle, that will */ + /* be replaced by this function. Typically, you would use (omitting */ + /* error handling): */ + /* */ + /* */ + /* { */ + /* FT_Glyph glyph; */ + /* FT_BitmapGlyph glyph_bitmap; */ + /* */ + /* */ + /* // load glyph */ + /* error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT ); */ + /* */ + /* // extract glyph image */ + /* error = FT_Get_Glyph( face->glyph, &glyph ); */ + /* */ + /* // convert to a bitmap (default render mode + destroy old) */ + /* if ( glyph->format != ft_glyph_format_bitmap ) */ + /* { */ + /* error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default, */ + /* 0, 1 ); */ + /* if ( error ) // glyph unchanged */ + /* ... */ + /* } */ + /* */ + /* // access bitmap content by typecasting */ + /* glyph_bitmap = (FT_BitmapGlyph)glyph; */ + /* */ + /* // do funny stuff with it, like blitting/drawing */ + /* ... */ + /* */ + /* // discard glyph image (bitmap or not) */ + /* FT_Done_Glyph( glyph ); */ + /* } */ + /* */ + /* */ + /* This function will always fail if the glyph's format isn't */ + /* scalable. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, + FT_ULong render_mode, + FT_Vector* origin, + FT_Bool destroy ) + { + FT_GlyphSlotRec dummy; + FT_Error error; + FT_Glyph glyph; + FT_BitmapGlyph bitmap; + + const FT_Glyph_Class* clazz; + + + /* check argument */ + if ( !the_glyph ) + goto Bad; + + /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ + /* then calling FT_Render_Glyph_Internal() */ + + glyph = *the_glyph; + if ( !glyph ) + goto Bad; + + clazz = glyph->clazz; + if ( !clazz || !clazz->glyph_prepare ) + goto Bad; + + MEM_Set( &dummy, 0, sizeof ( dummy ) ); + dummy.library = glyph->library; + dummy.format = clazz->glyph_format; + + /* if `origin' is set, translate the glyph image */ + if ( origin ) + FT_Glyph_Transform( glyph, 0, origin ); + + /* create result bitmap glyph */ + error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class, + (FT_Glyph*)&bitmap ); + if ( error ) + goto Exit; + + /* prepare dummy slot for rendering */ + error = clazz->glyph_prepare( glyph, &dummy ) || + FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); + + if ( !destroy && origin ) + { + FT_Vector v; + + + v.x = -origin->x; + v.y = -origin->y; + FT_Glyph_Transform( glyph, 0, &v ); + } + + /* in case of succes, copy the bitmap to the glyph bitmap */ + if ( !error ) + { + error = ft_bitmap_glyph_init( bitmap, &dummy ); + if ( error ) + { + /* this should never happen, but let's be safe */ + FT_Done_Glyph( FT_GLYPH( bitmap ) ); + goto Exit; + } + + if ( destroy ) + FT_Done_Glyph( glyph ); + + *the_glyph = FT_GLYPH( bitmap ); + } + + Exit: + return error; + + Bad: + error = FT_Err_Invalid_Argument; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Glyph */ + /* */ + /* */ + /* Destroys a given glyph. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph object. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Done_Glyph( FT_Glyph glyph ) + { + if ( glyph ) + { + FT_Memory memory = glyph->library->memory; + const FT_Glyph_Class* clazz = glyph->clazz; + + + if ( clazz->glyph_done ) + clazz->glyph_done( glyph ); + + FREE( glyph ); + } + } + + +#if 0 + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /* Compute the norm of a vector */ + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + static + FT_Pos ft_norm( FT_Vector* vec ) + { + FT_Int64 t1, t2; + + + MUL_64( vec->x, vec->x, t1 ); + MUL_64( vec->y, vec->y, t2 ); + ADD_64( t1, t2, t1 ); + + return (FT_Pos)SQRT_64( t1 ); + } + +#else /* FT_CONFIG_OPTION_OLD_CALCS */ + + static + FT_Pos ft_norm( FT_Vector* vec ) + { + FT_F26Dot6 u, v, d; + FT_Int shift; + FT_ULong H, L, L2, hi, lo, med; + + + u = vec->x; if ( u < 0 ) u = -u; + v = vec->y; if ( v < 0 ) v = -v; + + if ( u < v ) + { + d = u; + u = v; + v = d; + } + + /* check that we are not trying to normalize zero! */ + if ( u == 0 ) + return 0; + + /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */ + hi = (FT_ULong)u >> 16; + lo = (FT_ULong)u & 0xFFFF; + med = hi * lo; + + H = hi * hi + ( med >> 15 ); + med <<= 17; + L = lo * lo + med; + if ( L < med ) + H++; + + hi = (FT_ULong)v >> 16; + lo = (FT_ULong)v & 0xFFFF; + med = hi * lo; + + H += hi * hi + ( med >> 15 ); + med <<= 17; + L2 = lo * lo + med; + if ( L2 < med ) + H++; + + L += L2; + if ( L < L2 ) + H++; + + /* if the value is smaller than 32 bits */ + shift = 0; + if ( H == 0 ) + { + while ( ( L & 0xC0000000UL ) == 0 ) + { + L <<= 2; + shift++; + } + return ( FT_Sqrt32( L ) >> shift ); + } + else + { + while ( H ) + { + L = ( L >> 2 ) | ( H << 30 ); + H >>= 2; + shift++; + } + return ( FT_Sqrt32( L ) << shift ); + } + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + + static + int ft_test_extrema( FT_Outline* outline, + int n ) + { + FT_Vector *prev, *cur, *next; + FT_Pos product; + FT_Int first, last; + + + /* we need to compute the `previous' and `next' point */ + /* for these extrema. */ + cur = outline->points + n; + prev = cur - 1; + next = cur + 1; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + last = outline->contours[c]; + + if ( n == first ) + prev = outline->points + last; + + if ( n == last ) + next = outline->points + first; + + first = last + 1; + } + + product = FT_MulDiv( cur->x - prev->x, /* in.x */ + next->y - cur->y, /* out.y */ + 0x40 ) + - + FT_MulDiv( cur->y - prev->y, /* in.y */ + next->x - cur->x, /* out.x */ + 0x40 ); + + if ( product ) + product = product > 0 ? 1 : -1; + + return product; + } + + + /* Compute the orientation of path filling. It differs between TrueType */ + /* and Type1 formats. We could use the `ft_outline_reverse_fill' flag, */ + /* but it is better to re-compute it directly (it seems that this flag */ + /* isn't correctly set for some weird composite glyphs currently). */ + /* */ + /* We do this by computing bounding box points, and computing their */ + /* curvature. */ + /* */ + /* The function returns either 1 or -1. */ + /* */ + static + int ft_get_orientation( FT_Outline* outline ) + { + FT_BBox box; + FT_BBox indices; + int n, last; + + + indices.xMin = -1; + indices.yMin = -1; + indices.xMax = -1; + indices.yMax = -1; + + box.xMin = box.yMin = 32767; + box.xMax = box.yMax = -32768; + + /* is it empty ? */ + if ( outline->n_contours < 1 ) + return 1; + + last = outline->contours[outline->n_contours - 1]; + + for ( n = 0; n <= last; n++ ) + { + FT_Pos x, y; + + + x = outline->points[n].x; + if ( x < box.xMin ) + { + box.xMin = x; + indices.xMin = n; + } + if ( x > box.xMax ) + { + box.xMax = x; + indices.xMax = n; + } + + y = outline->points[n].y; + if ( y < box.yMin ) + { + box.yMin = y; + indices.yMin = n; + } + if ( y > box.yMax ) + { + box.yMax = y; + indices.yMax = n; + } + } + + /* test orientation of the xmin */ + return ft_test_extrema( outline, indices.xMin ) || + ft_test_extrema( outline, indices.yMin ) || + ft_test_extrema( outline, indices.xMax ) || + ft_test_extrema( outline, indices.yMax ) || + 1; /* this is an empty glyph? */ + } + + + static + FT_Error ft_embolden( FT_Face original, + FT_Outline* outline, + FT_Pos* advance ) + { + FT_Vector u, v; + FT_Vector* points; + FT_Vector cur, prev, next; + FT_Pos distance; + int c, n, first, orientation; + + FT_UNUSED( advance ); + + + /* compute control distance */ + distance = FT_MulFix( original->em_size / 60, + original->size->metrics.y_scale ); + + orientation = ft_get_orientation( &original->glyph->outline ); + + points = original->glyph->outline.points; + + first = 0; + for ( c = 0; c < outline->n_contours; c++ ) + { + int last = outline->contours[c]; + + + prev = points[last]; + + for ( n = first; n <= last; n++ ) + { + FT_Pos norm, delta, d; + FT_Vector in, out; + + + cur = points[n]; + if ( n < last ) next = points[n + 1]; + else next = points[first]; + + /* compute the in and out vectors */ + in.x = cur.x - prev.x; + in.y = cur.y - prev.y; + + out.x = next.x - cur.x; + out.y = next.y - cur.y; + + /* compute U and V */ + norm = ft_norm( &in ); + u.x = orientation * FT_DivFix( in.y, norm ); + u.y = orientation * -FT_DivFix( in.x, norm ); + + norm = ft_norm( &out ); + v.x = orientation * FT_DivFix( out.y, norm ); + v.y = orientation * -FT_DivFix( out.x, norm ); + + d = distance; + + if ( ( outline->flags[n] & FT_Curve_Tag_On ) == 0 ) + d *= 2; + + /* Check discriminant for parallel vectors */ + delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x ); + if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD ) + { + /* Move point -- compute A and B */ + FT_Pos x, y, A, B; + + + A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y ); + B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y ); + + x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y ); + y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x ); + + outline->points[n].x = distance + FT_DivFix( x, delta ); + outline->points[n].y = distance + FT_DivFix( y, delta ); + } + else + { + /* Vectors are nearly parallel */ + FT_Pos x, y; + + + x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2; + y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2; + + outline->points[n].x = x; + outline->points[n].y = y; + } + + prev = cur; + } + + first = last + 1; + } + + if ( advance ) + *advance = ( *advance + distance * 4 ) & -64; + + return 0; + } + +#endif /* 0 -- EXPERIMENTAL STUFF! */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftinit.c b/subsys/win32k/freetype/src/base/ftinit.c new file mode 100644 index 0000000..cc754eb --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftinit.c @@ -0,0 +1,155 @@ +/***************************************************************************/ +/* */ +/* ftinit.c */ +/* */ +/* FreeType initialization layer (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* The purpose of this file is to implement the following two */ + /* functions: */ + /* */ + /* FT_Add_Default_Modules(): */ + /* This function is used to add the set of default modules to a */ + /* fresh new library object. The set is taken from the header file */ + /* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */ + /* Build System' for more information. */ + /* */ + /* FT_Init_FreeType(): */ + /* This function creates a system object for the current platform, */ + /* builds a library out of it, then calls FT_Default_Drivers(). */ + /* */ + /* Note that even if FT_Init_FreeType() uses the implementation of the */ + /* system object defined at build time, client applications are still */ + /* able to provide their own `ftsystem.c'. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_init + +#undef FT_USE_MODULE +#define FT_USE_MODULE( x ) extern const FT_Module_Class* x; + +#ifdef macintosh + FT_USE_MODULE(fond_driver_class) +#endif +#include + +#undef FT_USE_MODULE +#define FT_USE_MODULE( x ) (const FT_Module_Class*)&x, + +static +const FT_Module_Class* ft_default_modules[] = + { +#ifdef macintosh + FT_USE_MODULE(fond_driver_class) +#endif +#include + 0 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Default_Modules */ + /* */ + /* */ + /* Adds the set of default drivers to a given library object. */ + /* This is only useful when you create a library object with */ + /* FT_New_Library() (usually to plug a custom memory manager). */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Add_Default_Modules( FT_Library library ) + { + FT_Error error; + const FT_Module_Class** cur; + + + /* test for valid `library' delayed to FT_Add_Module() */ + + cur = ft_default_modules; + while ( *cur ) + { + error = FT_Add_Module( library, *cur ); + /* notify errors, but don't stop */ + if ( error ) + { + FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = %x\n", + (*cur)->module_name, error )); + } + cur++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Init_FreeType */ + /* */ + /* */ + /* Initializes a new FreeType library object. The set of drivers */ + /* that are registered by this function is determined at build time. */ + /* */ + /* */ + /* library :: A handle to a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Init_FreeType( FT_Library* library ) + { + FT_Error error; + FT_Memory memory; + + + /* First of all, allocate a new system object -- this function is part */ + /* of the system-specific component, i.e. `ftsystem.c'. */ + + memory = FT_New_Memory(); + if ( !memory ) + { + FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" )); + return FT_Err_Unimplemented_Feature; + } + + /* build a library out of it, then fill it with the set of */ + /* default drivers. */ + + error = FT_New_Library( memory, library ); + if ( !error ) + FT_Add_Default_Modules( *library ); + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftlist.c b/subsys/win32k/freetype/src/base/ftlist.c new file mode 100644 index 0000000..0158ba4 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftlist.c @@ -0,0 +1,301 @@ +/***************************************************************************/ +/* */ +/* ftlist.c */ +/* */ +/* Generic list support for FreeType (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file implements functions relative to list processing. Its */ + /* data structures are defined in `freetype/internal/ftlist.h'. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_list + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Find */ + /* */ + /* */ + /* Finds the list node for a given listed object. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* data :: The address of the listed object. */ + /* */ + /* */ + /* List node. NULL if it wasn't found. */ + /* */ + BASE_FUNC( FT_ListNode ) FT_List_Find( FT_List list, + void* data ) + { + FT_ListNode cur; + + + cur = list->head; + while ( cur ) + { + if ( cur->data == data ) + return cur; + + cur = cur->next; + } + + return (FT_ListNode)0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Add */ + /* */ + /* */ + /* Appends an element to the end of a list. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to append. */ + /* */ + BASE_FUNC( void ) FT_List_Add( FT_List list, + FT_ListNode node ) + { + FT_ListNode before = list->tail; + + + node->next = 0; + node->prev = before; + + if ( before ) + before->next = node; + else + list->head = node; + + list->tail = node; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Insert */ + /* */ + /* */ + /* Inserts an element at the head of a list. */ + /* */ + /* */ + /* list :: A pointer to parent list. */ + /* node :: The node to insert. */ + /* */ + BASE_FUNC( void ) FT_List_Insert( FT_List list, + FT_ListNode node ) + { + FT_ListNode after = list->head; + + + node->next = after; + node->prev = 0; + + if ( !after ) + list->tail = node; + else + after->prev = node; + + list->head = node; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Remove */ + /* */ + /* */ + /* Removes a node from a list. This function doesn't check whether */ + /* the node is in the list! */ + /* */ + /* */ + /* node :: The node to remove. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* */ + BASE_FUNC( void ) FT_List_Remove( FT_List list, + FT_ListNode node ) + { + FT_ListNode before, after; + + + before = node->prev; + after = node->next; + + if ( before ) + before->next = after; + else + list->head = after; + + if ( after ) + after->prev = before; + else + list->tail = before; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Up */ + /* */ + /* */ + /* Moves a node to the head/top of a list. Used to maintain LRU */ + /* lists. */ + /* */ + /* */ + /* list :: A pointer to the parent list. */ + /* node :: The node to move. */ + /* */ + BASE_FUNC( void ) FT_List_Up( FT_List list, + FT_ListNode node ) + { + FT_ListNode before, after; + + + before = node->prev; + after = node->next; + + /* check whether we are already on top of the list */ + if ( !before ) + return; + + before->next = after; + + if ( after ) + after->prev = before; + else + list->tail = before; + + node->prev = 0; + node->next = list->head; + list->head->prev = node; + list->head = node; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Iterate */ + /* */ + /* */ + /* Parses a list and calls a given iterator function on each element. */ + /* Note that parsing is stopped as soon as one of the iterator calls */ + /* returns a non-zero value. */ + /* */ + /* */ + /* list :: A handle to the list. */ + /* iterator :: An interator function, called on each node of the */ + /* list. */ + /* user :: A user-supplied field which is passed as the second */ + /* argument to the iterator. */ + /* */ + /* */ + /* The result (a FreeType error code) of the last iterator call. */ + /* */ + BASE_FUNC( FT_Error ) FT_List_Iterate( FT_List list, + FT_List_Iterator iterator, + void* user ) + { + FT_ListNode cur = list->head; + FT_Error error = FT_Err_Ok; + + + while ( cur ) + { + FT_ListNode next = cur->next; + + + error = iterator( cur, user ); + if ( error ) + break; + + cur = next; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_List_Finalize */ + /* */ + /* */ + /* Destroys all elements in the list as well as the list itself. */ + /* */ + /* */ + /* list :: A handle to the list. */ + /* */ + /* destroy :: A list destructor that will be applied to each element */ + /* of the list. */ + /* */ + /* memory :: The current memory object which handles deallocation. */ + /* */ + /* user :: A user-supplied field which is passed as the last */ + /* argument to the destructor. */ + /* */ + BASE_FUNC( void ) FT_List_Finalize( FT_List list, + FT_List_Destructor destroy, + FT_Memory memory, + void* user ) + { + FT_ListNode cur; + + + cur = list->head; + while ( cur ) + { + FT_ListNode next = cur->next; + void* data = cur->data; + + + if ( destroy ) + destroy( memory, data, user ); + + FREE( cur ); + cur = next; + } + + list->head = 0; + list->tail = 0; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftmm.c b/subsys/win32k/freetype/src/base/ftmm.c new file mode 100644 index 0000000..0f6fdde --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftmm.c @@ -0,0 +1,176 @@ +/***************************************************************************/ +/* */ +/* ftmm.c */ +/* */ +/* Multiple Master font support (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_mm + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Multi_Master */ + /* */ + /* */ + /* Retrieves the Multiple Master descriptor of a given font. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* */ + /* master :: The Multiple Masters descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Get_Multi_Master( FT_Face face, + FT_Multi_Master* master ) + { + FT_Error error; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + error = FT_Err_Invalid_Argument; + + if ( FT_HAS_MULTIPLE_MASTERS( face ) ) + { + FT_Driver driver = face->driver; + FT_Get_MM_Func func; + + + func = (FT_Get_MM_Func)driver->root.clazz->get_interface( + FT_MODULE( driver ), "get_mm" ); + if ( func ) + error = func( face, master ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Design_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through design coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Set_MM_Design_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Long* coords ) + { + FT_Error error; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + error = FT_Err_Invalid_Argument; + + if ( FT_HAS_MULTIPLE_MASTERS( face ) ) + { + FT_Driver driver = face->driver; + FT_Set_MM_Design_Func func; + + + func = (FT_Set_MM_Design_Func)driver->root.clazz->get_interface( + FT_MODULE( driver ), "set_mm_design" ); + if ( func ) + error = func( face, num_coords, coords ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_MM_Blend_Coordinates */ + /* */ + /* */ + /* For Multiple Masters fonts, choose an interpolated font design */ + /* through normalized blend coordinates. */ + /* */ + /* */ + /* face :: A handle to the source face. */ + /* */ + /* num_coords :: The number of design coordinates (must be equal to */ + /* the number of axes in the font). */ + /* */ + /* coords :: The design coordinates (each one must be between 0 */ + /* and 1.0). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Set_MM_Blend_Coordinates( + FT_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + FT_Error error; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + error = FT_Err_Invalid_Argument; + + if ( FT_HAS_MULTIPLE_MASTERS( face ) ) + { + FT_Driver driver = face->driver; + FT_Set_MM_Blend_Func func; + + + func = (FT_Set_MM_Blend_Func)driver->root.clazz->get_interface( + FT_MODULE( driver ), "set_mm_blend" ); + if ( func ) + error = func( face, num_coords, coords ); + } + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftnames.c b/subsys/win32k/freetype/src/base/ftnames.c new file mode 100644 index 0000000..43a0d12 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftnames.c @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* ftnames.c */ +/* */ +/* Simple interface to access SFNT name tables (which are used */ +/* to hold font names, copyright info, notices, etc.). */ +/* */ +/* This is _not_ used to retrieve glyph names! */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_CONFIG_OPTION_SFNT_NAMES + + + FT_EXPORT_FUNC( FT_UInt ) FT_Get_Sfnt_Name_Count( FT_Face face ) + { + return face && ( FT_IS_SFNT( face ) ? ((TT_Face)face)->num_names : 0 ); + } + + + FT_EXPORT_FUNC( FT_Error ) FT_Get_Sfnt_Name( FT_Face face, + FT_UInt index, + FT_SfntName* aname ) + { + FT_Error error = FT_Err_Invalid_Argument; + + + if ( aname && face && FT_IS_SFNT( face ) ) + { + TT_Face ttface = (TT_Face)face; + + + if ( index < ttface->num_names ) + { + TT_NameRec* name = ttface->name_table.names + index; + + + aname->platform_id = name->platformID; + aname->encoding_id = name->encodingID; + aname->language_id = name->languageID; + aname->name_id = name->nameID; + aname->string = (FT_Byte*)name->string; + aname->string_len = name->stringLength; + + error = FT_Err_Ok; + } + } + + return error; + } + + +#endif /* FT_CONFIG_OPTION_SFNT_NAMES */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftobjs.c b/subsys/win32k/freetype/src/base/ftobjs.c new file mode 100644 index 0000000..de74882 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftobjs.c @@ -0,0 +1,3246 @@ +/***************************************************************************/ +/* */ +/* ftobjs.c */ +/* */ +/* The FreeType private base classes (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include + +#include + +#include /* for strcmp() */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M E M O R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_memory + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Alloc */ + /* */ + /* */ + /* Allocates a new block of memory. The returned area is always */ + /* zero-filled; this is a strong convention in many FreeType parts. */ + /* */ + /* */ + /* memory :: A handle to a given `memory object' which handles */ + /* allocation. */ + /* */ + /* size :: The size in bytes of the block to allocate. */ + /* */ + /* */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + BASE_FUNC( FT_Error ) FT_Alloc( FT_Memory memory, + FT_Long size, + void** P ) + { + FT_Assert( P != 0 ); + + if ( size > 0 ) + { + *P = memory->alloc( memory, size ); + if ( !*P ) + { + FT_ERROR(( "FT_Alloc:" )); + FT_ERROR(( " Out of memory? (%ld requested)\n", + size )); + + return FT_Err_Out_Of_Memory; + } + MEM_Set( *P, 0, size ); + } + else + *P = NULL; + + FT_TRACE7(( "FT_Alloc:" )); + FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n", + size, *P, P )); + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Realloc */ + /* */ + /* */ + /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */ + /* from the heap, possibly changing `*P'. */ + /* */ + /* */ + /* memory :: A handle to a given `memory object' which handles */ + /* reallocation. */ + /* */ + /* current :: The current block size in bytes. */ + /* */ + /* size :: The new block size in bytes. */ + /* */ + /* */ + /* P :: A pointer to the fresh new block. It should be set to */ + /* NULL if `size' is 0, or in case of error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* All callers of FT_Realloc() _must_ provide the current block size */ + /* as well as the new one. */ + /* */ + BASE_FUNC( FT_Error ) FT_Realloc( FT_Memory memory, + FT_Long current, + FT_Long size, + void** P ) + { + void* Q; + + + FT_Assert( P != 0 ); + + /* if the original pointer is NULL, call FT_Alloc() */ + if ( !*P ) + return FT_Alloc( memory, size, P ); + + /* if the new block if zero-sized, clear the current one */ + if ( size <= 0 ) + { + FT_Free( memory, P ); + return FT_Err_Ok; + } + + Q = memory->realloc( memory, current, size, *P ); + if ( !Q ) + goto Fail; + + *P = Q; + return FT_Err_Ok; + + Fail: + FT_ERROR(( "FT_Realloc:" )); + FT_ERROR(( " Failed (current %ld, requested %ld)\n", + current, size )); + return FT_Err_Out_Of_Memory; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Free */ + /* */ + /* */ + /* Releases a given block of memory allocated through FT_Alloc(). */ + /* */ + /* */ + /* memory :: A handle to a given `memory object' which handles */ + /* memory deallocation */ + /* */ + /* P :: This is the _address_ of a _pointer_ which points to the */ + /* allocated block. It is always set to NULL on exit. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If P or *P are NULL, this function should return successfully. */ + /* This is a strong convention within all of FreeType and its */ + /* drivers. */ + /* */ + BASE_FUNC( void ) FT_Free( FT_Memory memory, + void** P ) + { + FT_TRACE7(( "FT_Free:" )); + FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n", + P, P ? *P : (void*)0 )); + + if ( P && *P ) + { + memory->free( memory, *P ); + *P = 0; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** S T R E A M ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_new_input_stream */ + /* */ + /* */ + /* Creates a new input stream object from an FT_Open_Args structure. */ + /* */ + /* */ + /* The function expects a valid `astream' parameter. */ + /* */ + static + FT_Error ft_new_input_stream( FT_Library library, + FT_Open_Args* args, + FT_Stream* astream ) + { + FT_Error error; + FT_Memory memory; + FT_Stream stream; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !args ) + return FT_Err_Invalid_Argument; + + *astream = 0; + memory = library->memory; + if ( ALLOC( stream, sizeof ( *stream ) ) ) + goto Exit; + + stream->memory = memory; + + /* now, look at the stream flags */ + if ( args->flags & ft_open_memory ) + { + error = 0; + FT_New_Memory_Stream( library, + args->memory_base, + args->memory_size, + stream ); + } + else if ( args->flags & ft_open_pathname ) + { + error = FT_New_Stream( args->pathname, stream ); + stream->pathname.pointer = args->pathname; + } + else if ( args->flags & ft_open_stream && args->stream ) + { + *stream = *(args->stream); + stream->memory = memory; + } + else + error = FT_Err_Invalid_Argument; + + if ( error ) + FREE( stream ); + + *astream = stream; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Stream */ + /* */ + /* */ + /* Closes and destroys a stream object. */ + /* */ + /* */ + /* stream :: The stream to be closed and destroyed. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream ) + { + if ( stream && stream->close ) + stream->close( stream ); + } + + + static + void ft_done_stream( FT_Stream* astream ) + { + FT_Stream stream = *astream; + FT_Memory memory = stream->memory; + + + if ( stream->close ) + stream->close( stream ); + + FREE( stream ); + *astream = 0; + } + + +#undef FT_COMPONENT +#define FT_COMPONENT trace_objs + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** G L Y P H L O A D E R ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The glyph loader is a simple object which is used to load a set of */ + /* glyphs easily. It is critical for the correct loading of composites. */ + /* */ + /* Ideally, one can see it as a stack of abstract `glyph' objects. */ + /* */ + /* loader.base Is really the bottom of the stack. It describes a */ + /* single glyph image made of the juxtaposition of */ + /* several glyphs (those `in the stack'). */ + /* */ + /* loader.current Describes the top of the stack, on which a new */ + /* glyph can be loaded. */ + /* */ + /* Rewind Clears the stack. */ + /* Prepare Set up `loader.current' for addition of a new glyph */ + /* image. */ + /* Add Add the `current' glyph image to the `base' one, */ + /* and prepare for another one. */ + /* */ + /* The glyph loader is now a base object. Each driver used to */ + /* re-implement it in one way or the other, which wasted code and */ + /* energy. */ + /* */ + /*************************************************************************/ + + + /* create a new glyph loader */ + BASE_FUNC( FT_Error ) FT_GlyphLoader_New( FT_Memory memory, + FT_GlyphLoader** aloader ) + { + FT_GlyphLoader* loader; + FT_Error error; + + + if ( !ALLOC( loader, sizeof ( *loader ) ) ) + { + loader->memory = memory; + *aloader = loader; + } + return error; + } + + + /* rewind the glyph loader - reset counters to 0 */ + BASE_FUNC( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader ) + { + FT_GlyphLoad* base = &loader->base; + FT_GlyphLoad* current = &loader->current; + + + base->outline.n_points = 0; + base->outline.n_contours = 0; + base->num_subglyphs = 0; + + *current = *base; + } + + + /* reset the glyph loader, frees all allocated tables */ + /* and starts from zero */ + BASE_FUNC( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader ) + { + FT_Memory memory = loader->memory; + + + FREE( loader->base.outline.points ); + FREE( loader->base.outline.tags ); + FREE( loader->base.outline.contours ); + FREE( loader->base.extra_points ); + FREE( loader->base.subglyphs ); + + loader->max_points = 0; + loader->max_contours = 0; + loader->max_subglyphs = 0; + + FT_GlyphLoader_Rewind( loader ); + } + + + /* delete a glyph loader */ + BASE_FUNC( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader ) + { + if ( loader ) + { + FT_Memory memory = loader->memory; + + + FT_GlyphLoader_Reset( loader ); + FREE( loader ); + } + } + + + /* re-adjust the `current' outline fields */ + static + void FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader ) + { + FT_Outline* base = &loader->base.outline; + FT_Outline* current = &loader->current.outline; + + + current->points = base->points + base->n_points; + current->tags = base->tags + base->n_points; + current->contours = base->contours + base->n_contours; + + /* handle extra points table - if any */ + if ( loader->use_extra ) + loader->current.extra_points = + loader->base.extra_points + base->n_points; + } + + + BASE_FUNC( FT_Error ) FT_GlyphLoader_Create_Extra( + FT_GlyphLoader* loader ) + { + FT_Error error; + FT_Memory memory = loader->memory; + + + if ( !ALLOC_ARRAY( loader->base.extra_points, + loader->max_points, FT_Vector ) ) + { + loader->use_extra = 1; + FT_GlyphLoader_Adjust_Points( loader ); + } + return error; + } + + + /* re-adjust the `current' subglyphs field */ + static + void FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader ) + { + FT_GlyphLoad* base = &loader->base; + FT_GlyphLoad* current = &loader->current; + + + current->subglyphs = base->subglyphs + base->num_subglyphs; + } + + + /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */ + /* function reallocates its outline tables if necessary. Note that it */ + /* DOESN'T change the number of points within the loader! */ + /* */ + BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points( + FT_GlyphLoader* loader, + FT_UInt n_points, + FT_UInt n_contours ) + { + FT_Memory memory = loader->memory; + FT_Error error = FT_Err_Ok; + FT_Outline* base = &loader->base.outline; + FT_Outline* current = &loader->current.outline; + FT_Bool adjust = 1; + + FT_UInt new_max; + + + /* check points & tags */ + new_max = base->n_points + current->n_points + n_points; + if ( new_max > loader->max_points ) + { + new_max = ( new_max + 7 ) & -8; + if ( REALLOC_ARRAY( base->points, base->n_points, + new_max, FT_Vector ) || + REALLOC_ARRAY( base->tags, base->n_points, + new_max, FT_Byte ) ) + goto Exit; + + if ( loader->use_extra && + REALLOC_ARRAY( loader->base.extra_points, base->n_points, + new_max, FT_Vector ) ) + goto Exit; + + adjust = 1; + loader->max_points = new_max; + } + + /* check contours */ + new_max = base->n_contours + current->n_contours + + n_contours; + if ( new_max > loader->max_contours ) + { + new_max = ( new_max + 3 ) & -4; + if ( REALLOC_ARRAY( base->contours, base->n_contours, + new_max, FT_Short ) ) + goto Exit; + + adjust = 1; + loader->max_contours = new_max; + } + + if ( adjust ) + FT_GlyphLoader_Adjust_Points( loader ); + + Exit: + return error; + } + + + /* Ensure that we can add `n_subglyphs' to our glyph. this function */ + /* reallocates its subglyphs table if necessary. Note that it DOES */ + /* NOT change the number of subglyphs within the loader! */ + /* */ + BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Subglyphs( + FT_GlyphLoader* loader, + FT_UInt n_subs ) + { + FT_Memory memory = loader->memory; + FT_Error error = FT_Err_Ok; + FT_UInt new_max; + + FT_GlyphLoad* base = &loader->base; + FT_GlyphLoad* current = &loader->current; + + + new_max = base->num_subglyphs + current->num_subglyphs + n_subs; + if ( new_max > loader->max_subglyphs ) + { + new_max = ( new_max + 1 ) & -2; + if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs, + new_max, FT_SubGlyph ) ) + goto Exit; + + loader->max_subglyphs = new_max; + + FT_GlyphLoader_Adjust_Subglyphs( loader ); + } + + Exit: + return error; + } + + + /* prepare loader for the addition of a new glyph on top of the base one */ + BASE_FUNC( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader ) + { + FT_GlyphLoad* current = &loader->current; + + + current->outline.n_points = 0; + current->outline.n_contours = 0; + current->num_subglyphs = 0; + + FT_GlyphLoader_Adjust_Points ( loader ); + FT_GlyphLoader_Adjust_Subglyphs( loader ); + } + + + /* add current glyph to the base image - and prepare for another */ + BASE_FUNC( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader ) + { + FT_GlyphLoad* base = &loader->base; + FT_GlyphLoad* current = &loader->current; + + FT_UInt n_curr_contours = current->outline.n_contours; + FT_UInt n_base_points = base->outline.n_points; + FT_UInt n; + + + base->outline.n_points += current->outline.n_points; + base->outline.n_contours += current->outline.n_contours; + base->num_subglyphs += current->num_subglyphs; + + /* adjust contours count in newest outline */ + for ( n = 0; n < n_curr_contours; n++ ) + current->outline.contours[n] += n_base_points; + + /* prepare for another new glyph image */ + FT_GlyphLoader_Prepare( loader ); + } + + + BASE_FUNC( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target, + FT_GlyphLoader* source ) + { + FT_Error error; + FT_UInt num_points = source->base.outline.n_points; + FT_UInt num_contours = source->base.outline.n_contours; + + + error = FT_GlyphLoader_Check_Points( target, num_points, num_contours ); + if ( !error ) + { + FT_Outline* out = &target->base.outline; + FT_Outline* in = &source->base.outline; + + + MEM_Copy( out->points, in->points, + num_points * sizeof ( FT_Vector ) ); + MEM_Copy( out->tags, in->tags, + num_points * sizeof ( char ) ); + MEM_Copy( out->contours, in->contours, + num_contours * sizeof ( short ) ); + + /* do we need to copy the extra points? */ + if ( target->use_extra && source->use_extra ) + MEM_Copy( target->base.extra_points, source->base.extra_points, + num_points * sizeof ( FT_Vector ) ); + + out->n_points = num_points; + out->n_contours = num_contours; + + FT_GlyphLoader_Adjust_Points( target ); + } + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error ft_glyphslot_init( FT_GlyphSlot slot ) + { + FT_Driver driver = slot->face->driver; + FT_Driver_Class* clazz = driver->clazz; + FT_Memory memory = driver->root.memory; + FT_Error error = FT_Err_Ok; + + + slot->library = driver->root.library; + + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + error = FT_GlyphLoader_New( memory, &slot->loader ); + + if ( !error && clazz->init_slot ) + error = clazz->init_slot( slot ); + + return error; + } + + + static + void ft_glyphslot_clear( FT_GlyphSlot slot ) + { + /* free bitmap if needed */ + if ( slot->flags & ft_glyph_own_bitmap ) + { + FT_Memory memory = FT_FACE_MEMORY( slot->face ); + + + FREE( slot->bitmap.buffer ); + slot->flags &= ~ft_glyph_own_bitmap; + } + + /* clear all public fields in the glyph slot */ + MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) ); + MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) ); + MEM_Set( &slot->bitmap, 0, sizeof ( slot->bitmap ) ); + + slot->bitmap_left = 0; + slot->bitmap_top = 0; + slot->num_subglyphs = 0; + slot->subglyphs = 0; + slot->control_data = 0; + slot->control_len = 0; + slot->other = 0; + slot->format = ft_glyph_format_none; + + slot->linearHoriAdvance = 0; + slot->linearVertAdvance = 0; + } + + + static + void ft_glyphslot_done( FT_GlyphSlot slot ) + { + FT_Driver driver = slot->face->driver; + FT_Driver_Class* clazz = driver->clazz; + FT_Memory memory = driver->root.memory; + + + /* free bitmap buffer if needed */ + if ( slot->flags & ft_glyph_own_bitmap ) + FREE( slot->bitmap.buffer ); + + /* free glyph loader */ + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + { + FT_GlyphLoader_Done( slot->loader ); + slot->loader = 0; + } + + if ( clazz->done_slot ) + clazz->done_slot( slot ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_GlyphSlot */ + /* */ + /* */ + /* It is sometimes useful to have more than one glyph slot for a */ + /* given face object. This function is used to create additional */ + /* slots. All of them are automatically discarded when the face is */ + /* destroyed. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* aslot :: A handle to a new glyph slot object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face, + FT_GlyphSlot* aslot ) + { + FT_Error error; + FT_Driver driver; + FT_Driver_Class* clazz; + FT_Memory memory; + FT_GlyphSlot slot; + + + if ( !face || !aslot || !face->driver ) + return FT_Err_Invalid_Argument; + + *aslot = 0; + + driver = face->driver; + clazz = driver->clazz; + memory = driver->root.memory; + + FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" )); + if ( !ALLOC( slot, clazz->slot_object_size ) ) + { + slot->face = face; + + error = ft_glyphslot_init( slot ); + if ( error ) + { + ft_glyphslot_done( slot ); + FREE( slot ); + goto Exit; + } + + *aslot = slot; + } + + Exit: + FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error )); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_GlyphSlot */ + /* */ + /* */ + /* Destroys a given glyph slot. Remember however that all slots are */ + /* automatically destroyed with its parent. Using this function is */ + /* not always mandatory. */ + /* */ + /* */ + /* slot :: A handle to a target glyph slot. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot ) + { + if ( slot ) + { + FT_Driver driver = slot->face->driver; + FT_Memory memory = driver->root.memory; + FT_GlyphSlot* parent; + FT_GlyphSlot cur; + + + /* Remove slot from its parent face's list */ + parent = &slot->face->glyph; + cur = *parent; + + while ( cur ) + { + if ( cur == slot ) + { + *parent = cur->next; + ft_glyphslot_done( slot ); + FREE( slot ); + break; + } + cur = cur->next; + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Transform */ + /* */ + /* */ + /* A function used to set the transformation that is applied to glyph */ + /* images just before they are converted to bitmaps in a glyph slot */ + /* when FT_Render_Glyph() is called. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */ + /* the identity matrix. */ + /* delta :: A pointer to the translation vector. Use 0 for the null */ + /* vector. */ + /* */ + /* */ + /* The transformation is only applied to scalable image formats after */ + /* the glyph has been loaded. It means that hinting is unaltered by */ + /* the transformation and is performed on the character size given in */ + /* the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face, + FT_Matrix* matrix, + FT_Vector* delta ) + { + if ( !face ) + return; + + face->transform_flags = 0; + + if ( !matrix ) + { + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + matrix = &face->transform_matrix; + } + else + face->transform_matrix = *matrix; + + /* set transform_flags bit flag 0 if `matrix' isn't the identity */ + if ( ( matrix->xy | matrix->yx ) || + matrix->xx != 0x10000L || + matrix->yy != 0x10000L ) + face->transform_flags |= 1; + + if ( !delta ) + { + face->transform_delta.x = 0; + face->transform_delta.y = 0; + delta = &face->transform_delta; + } + else + face->transform_delta = *delta; + + /* set transform_flags bit flag 1 if `delta' isn't the null vector */ + if ( delta->x | delta->y ) + face->transform_flags |= 2; + } + + + static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot ); + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* face :: A handle to the target face object where the glyph */ + /* will be loaded. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* FT_Set_Transform. */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face, + FT_UInt glyph_index, + FT_Int load_flags ) + { + FT_Error error; + FT_Driver driver; + FT_GlyphSlot slot; + FT_Library library; + FT_Bool autohint; + FT_Module hinter; + + + if ( !face || !face->size || !face->glyph ) + return FT_Err_Invalid_Face_Handle; + + if ( glyph_index >= (FT_UInt)face->num_glyphs ) + return FT_Err_Invalid_Argument; + + slot = face->glyph; + ft_glyphslot_clear( slot ); + + driver = face->driver; + + /* when the flag NO_RECURSE is set, we disable hinting and scaling */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + /* do we need to load the glyph through the auto-hinter? */ + library = driver->root.library; + hinter = library->auto_hinter; + autohint = hinter && + !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ); + if ( autohint ) + { + if ( FT_DRIVER_HAS_HINTER( driver ) && + !( load_flags & FT_LOAD_FORCE_AUTOHINT ) ) + autohint = 0; + } + + if ( autohint ) + { + FT_AutoHinter_Interface* hinting; + + + hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface; + error = hinting->load_glyph( (FT_AutoHinter)hinter, slot, face->size, + glyph_index, load_flags ); + } + else + error = driver->clazz->load_glyph( slot, + face->size, + glyph_index, + load_flags ); + if ( error ) + goto Exit; + + /* compute the advance */ + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + slot->advance.x = 0; + slot->advance.y = slot->metrics.vertAdvance; + } + else + { + slot->advance.x = slot->metrics.horiAdvance; + slot->advance.y = 0; + } + + /* now, transform the glyph image when needed */ + if ( face->transform_flags ) + { + /* get renderer */ + FT_Renderer renderer = ft_lookup_glyph_renderer( slot ); + + + if ( renderer ) + error = renderer->clazz->transform_glyph( renderer, slot, + &face->transform_matrix, + &face->transform_delta ); + /* transform advance */ + FT_Vector_Transform( &slot->advance, &face->transform_matrix ); + } + + /* do we need to render the image now? */ + if ( !error && + slot->format != ft_glyph_format_bitmap && + slot->format != ft_glyph_format_composite && + load_flags & FT_LOAD_RENDER ) + { + error = FT_Render_Glyph( slot, + ( load_flags & FT_LOAD_MONOCHROME ) + ? ft_render_mode_mono + : ft_render_mode_normal ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Load_Char */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size, according to its character code. */ + /* */ + /* */ + /* face :: A handle to a target face object where the glyph */ + /* will be loaded. */ + /* */ + /* char_code :: The glyph's character code, according to the */ + /* current charmap used in the face. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If the face has no current charmap, or if the character code */ + /* is not defined in the charmap, this function will return an */ + /* error. */ + /* */ + /* If the glyph image is not a bitmap, and if the bit flag */ + /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */ + /* transformed with the information passed to a previous call to */ + /* FT_Set_Transform(). */ + /* */ + /* Note that this also transforms the `face.glyph.advance' field, but */ + /* *not* the values in `face.glyph.metrics'. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face, + FT_ULong char_code, + FT_Int load_flags ) + { + FT_UInt glyph_index; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + glyph_index = (FT_UInt)char_code; + if ( face->charmap ) + glyph_index = FT_Get_Char_Index( face, char_code ); + + return FT_Load_Glyph( face, glyph_index, load_flags ); + } + + + /* destructor for sizes list */ + static + void destroy_size( FT_Memory memory, + FT_Size size, + FT_Driver driver ) + { + /* finalize client-specific data */ + if ( size->generic.finalizer ) + size->generic.finalizer( size ); + + /* finalize format-specific stuff */ + if ( driver->clazz->done_size ) + driver->clazz->done_size( size ); + + FREE( size ); + } + + + /* destructor for faces list */ + static + void destroy_face( FT_Memory memory, + FT_Face face, + FT_Driver driver ) + { + FT_Driver_Class* clazz = driver->clazz; + + + /* discard auto-hinting data */ + if ( face->autohint.finalizer ) + face->autohint.finalizer( face->autohint.data ); + + /* Discard glyph slots for this face */ + /* Beware! FT_Done_GlyphSlot() changes the field `face->slot' */ + while ( face->glyph ) + FT_Done_GlyphSlot( face->glyph ); + + /* Discard all sizes for this face */ + FT_List_Finalize( &face->sizes_list, + (FT_List_Destructor)destroy_size, + memory, + driver ); + face->size = 0; + + /* Now discard client data */ + if ( face->generic.finalizer ) + face->generic.finalizer( face ); + + /* finalize format-specific stuff */ + if ( clazz->done_face ) + clazz->done_face( face ); + + /* close the stream for this face if needed */ + if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 ) + ft_done_stream( &face->stream ); + + /* get rid of it */ + FREE( face ); + } + + + static + void Destroy_Driver( FT_Driver driver ) + { + FT_List_Finalize( &driver->faces_list, + (FT_List_Destructor)destroy_face, + driver->root.memory, + driver ); + + /* check whether we need to drop the driver's glyph loader */ + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + FT_GlyphLoader_Done( driver->glyph_loader ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* open_face */ + /* */ + /* */ + /* This function does some work for FT_Open_Face(). */ + /* */ + static + FT_Error open_face( FT_Driver driver, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter* params, + FT_Face* aface ) + { + FT_Memory memory; + FT_Driver_Class* clazz; + FT_Face face = 0; + FT_Error error; + + + clazz = driver->clazz; + memory = driver->root.memory; + + /* allocate the face object and perform basic initialization */ + if ( ALLOC( face, clazz->face_object_size ) ) + goto Fail; + + face->driver = driver; + face->memory = memory; + face->stream = stream; + + error = clazz->init_face( stream, + face, + face_index, + num_params, + params ); + if ( error ) + goto Fail; + + *aface = face; + + Fail: + if ( error ) + { + clazz->done_face( face ); + FREE( face ); + *aface = 0; + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a pathname to the font file. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* pathname :: A path to the font file. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_New_Face() can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Face( FT_Library library, + const char* pathname, + FT_Long face_index, + FT_Face* aface ) + { + FT_Open_Args args; + + + /* test for valid `library' and `aface' delayed to FT_Open_Face() */ + if ( !pathname ) + return FT_Err_Invalid_Argument; + + args.flags = ft_open_pathname; + args.pathname = (char*)pathname; + + return FT_Open_Face( library, &args, face_index, aface ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory_Face */ + /* */ + /* */ + /* Creates a new face object from a given resource and typeface index */ + /* using a font file already loaded into memory. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* file_base :: A pointer to the beginning of the font data. */ + /* */ + /* file_size :: The size of the memory chunk used by the font data. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* face :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_New_Memory_Face() can be used to determine and/or check the */ + /* font format of a given font resource. If the `face_index' field */ + /* is negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library, + FT_Byte* file_base, + FT_Long file_size, + FT_Long face_index, + FT_Face* face ) + { + FT_Open_Args args; + + + /* test for valid `library' and `face' delayed to FT_Open_Face() */ + if ( !file_base ) + return FT_Err_Invalid_Argument; + + args.flags = ft_open_memory; + args.memory_base = file_base; + args.memory_size = file_size; + + return FT_Open_Face( library, &args, face_index, face ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Open_Face */ + /* */ + /* */ + /* Opens a face object from a given resource and typeface index using */ + /* an `FT_Open_Args' structure. If the face object doesn't exist, it */ + /* will be created. */ + /* */ + /* */ + /* library :: A handle to the library resource. */ + /* */ + /* */ + /* args :: A pointer to an `FT_Open_Args' structure which must */ + /* be filled by the caller. */ + /* */ + /* face_index :: The index of the face within the resource. The */ + /* first face has index 0. */ + /* */ + /* aface :: A handle to a new face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Unlike FreeType 1.x, this function automatically creates a glyph */ + /* slot for the face object which can be accessed directly through */ + /* `face->glyph'. */ + /* */ + /* Note that additional slots can be added to each face with the */ + /* FT_New_GlyphSlot() API function. Slots are linked in a single */ + /* list through their `next' field. */ + /* */ + /* FT_Open_Face() can be used to determine and/or check the font */ + /* format of a given font resource. If the `face_index' field is */ + /* negative, the function will _not_ return any face handle in */ + /* `*face'. Its return value should be 0 if the resource is */ + /* recognized, or non-zero if not. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Open_Face( FT_Library library, + FT_Open_Args* args, + FT_Long face_index, + FT_Face* aface ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_Stream stream; + FT_Face face = 0; + FT_ListNode node = 0; + + + /* test for valid `library' and `args' delayed to */ + /* ft_new_input_stream() */ + + if ( !aface ) + return FT_Err_Invalid_Argument; + + *aface = 0; + + /* create input stream */ + error = ft_new_input_stream( library, args, &stream ); + if ( error ) + goto Exit; + + memory = library->memory; + + /* If the font driver is specified in the `args' structure, use */ + /* it. Otherwise, we scan the list of registered drivers. */ + if ( args->flags & ft_open_driver && args->driver ) + { + driver = FT_DRIVER( args->driver ); + + /* not all modules are drivers, so check... */ + if ( FT_MODULE_IS_DRIVER( driver ) ) + { + FT_Int num_params = 0; + FT_Parameter* params = 0; + + + if ( args->flags & ft_open_params ) + { + num_params = args->num_params; + params = args->params; + } + + error = open_face( driver, stream, face_index, + num_params, params, &face ); + if ( !error ) + goto Success; + } + else + error = FT_Err_Invalid_Handle; + + ft_done_stream( &stream ); + goto Fail; + } + else + { + /* check each font driver for an appropriate format */ + FT_Module* cur = library->modules; + FT_Module* limit = cur + library->num_modules; + + + for ( ; cur < limit; cur++ ) + { + /* not all modules are font drivers, so check... */ + if ( FT_MODULE_IS_DRIVER( cur[0] ) ) + { + FT_Int num_params = 0; + FT_Parameter* params = 0; + + + driver = FT_DRIVER( cur[0] ); + + if ( args->flags & ft_open_params ) + { + num_params = args->num_params; + params = args->params; + } + + error = open_face( driver, stream, face_index, + num_params, params, &face ); + if ( !error ) + goto Success; + + if ( error != FT_Err_Unknown_File_Format ) + goto Fail; + } + } + + ft_done_stream( &stream ); + + /* no driver is able to handle this format */ + error = FT_Err_Unknown_File_Format; + goto Fail; + } + + Success: + FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" )); + + /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */ + if ( args->flags & ft_open_stream && args->stream ) + face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; + + /* add the face object to its driver's list */ + if ( ALLOC( node, sizeof ( *node ) ) ) + goto Fail; + + node->data = face; + /* don't assume driver is the same as face->driver, so use */ + /* face->driver instead. */ + FT_List_Add( &face->driver->faces_list, node ); + + /* now allocate a glyph slot object for the face */ + { + FT_GlyphSlot slot; + + + FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" )); + + error = FT_New_GlyphSlot( face, &slot ); + if ( error ) + goto Fail; + + face->glyph = slot; + } + + /* finally, allocate a size object for the face */ + { + FT_Size size; + + + FT_TRACE4(( "FT_Open_Face: Creating size object\n" )); + + error = FT_New_Size( face, &size ); + if ( error ) + goto Fail; + + face->size = size; + } + + /* initialize transformation for convenience functions */ + face->transform_matrix.xx = 0x10000L; + face->transform_matrix.xy = 0; + face->transform_matrix.yx = 0; + face->transform_matrix.yy = 0x10000L; + + face->transform_delta.x = 0; + face->transform_delta.y = 0; + + *aface = face; + goto Exit; + + Fail: + FT_Done_Face( face ); + + Exit: + FT_TRACE4(( "FT_Open_Face: Return %d\n", error )); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_File */ + /* */ + /* */ + /* `Attaches' a given font file to an existing face. This is usually */ + /* to read additional information for a single face object. For */ + /* example, it is used to read the AFM files that come with Type 1 */ + /* fonts in order to add kerning data and other metrics. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* */ + /* filepathname :: An 8-bit pathname naming the `metrics' file. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* If your font file is in memory, or if you want to provide your */ + /* own input stream object, use FT_Attach_Stream(). */ + /* */ + /* The meaning of the `attach' action (i.e., what really happens when */ + /* the new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Attach_File( FT_Face face, + const char* filepathname ) + { + FT_Open_Args open; + + + /* test for valid `face' delayed to FT_Attach_Stream() */ + + if ( !filepathname ) + return FT_Err_Invalid_Argument; + + open.flags = ft_open_pathname; + open.pathname = (char*)filepathname; + + return FT_Attach_Stream( face, &open ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Attach_Stream */ + /* */ + /* */ + /* This function is similar to FT_Attach_File() with the exception */ + /* that it reads the attachment from an arbitrary stream. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* parameters :: A pointer to an FT_Open_Args structure used to */ + /* describe the input stream to FreeType. */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The meaning of the `attach' (i.e. what really happens when the */ + /* new file is read) is not fixed by FreeType itself. It really */ + /* depends on the font format (and thus the font driver). */ + /* */ + /* Client applications are expected to know what they are doing */ + /* when invoking this function. Most drivers simply do not implement */ + /* file attachments. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Attach_Stream( FT_Face face, + FT_Open_Args* parameters ) + { + FT_Stream stream; + FT_Error error; + FT_Driver driver; + + FT_Driver_Class* clazz; + + + /* test for valid `parameters' delayed to ft_new_input_stream() */ + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + error = ft_new_input_stream( driver->root.library, parameters, &stream ); + if ( error ) + goto Exit; + + /* we implement FT_Attach_Stream in each driver through the */ + /* `attach_file' interface */ + + error = FT_Err_Unimplemented_Feature; + clazz = driver->clazz; + if ( clazz->attach_file ) + error = clazz->attach_file( face, stream ); + + /* close the attached stream */ + if ( !parameters->stream || ( parameters->flags & ft_open_stream ) ) + ft_done_stream( &stream ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Face */ + /* */ + /* */ + /* Discards a given face object, as well as all of its child slots */ + /* and sizes. */ + /* */ + /* */ + /* face :: A handle to a target face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Done_Face( FT_Face face ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_ListNode node; + + + error = FT_Err_Invalid_Face_Handle; + if ( face && face->driver ) + { + driver = face->driver; + memory = driver->root.memory; + + /* find face in driver's list */ + node = FT_List_Find( &driver->faces_list, face ); + if ( node ) + { + /* remove face object from the driver's list */ + FT_List_Remove( &driver->faces_list, node ); + FREE( node ); + + /* now destroy the object proper */ + destroy_face( memory, face, driver ); + error = FT_Err_Ok; + } + } + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Size */ + /* */ + /* */ + /* Creates a new size object from a given face object. */ + /* */ + /* */ + /* face :: A handle to a parent face object. */ + /* */ + /* */ + /* asize :: A handle to a new size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Size( FT_Face face, + FT_Size* asize ) + { + FT_Error error; + FT_Memory memory; + FT_Driver driver; + FT_Driver_Class* clazz; + + FT_Size size = 0; + FT_ListNode node = 0; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if ( !asize ) + return FT_Err_Invalid_Size_Handle; + + if ( !face->driver ) + return FT_Err_Invalid_Driver_Handle; + + *asize = 0; + + driver = face->driver; + clazz = driver->clazz; + memory = face->memory; + + /* Allocate new size object and perform basic initialisation */ + if ( ALLOC( size, clazz->size_object_size ) || + ALLOC( node, sizeof ( FT_ListNodeRec ) ) ) + goto Exit; + + size->face = face; + + if ( clazz->init_size ) + error = clazz->init_size( size ); + + /* in case of success, add to the face's list */ + if ( !error ) + { + *asize = size; + node->data = size; + FT_List_Add( &face->sizes_list, node ); + } + + Exit: + if ( error ) + { + FREE( node ); + FREE( size ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Size */ + /* */ + /* */ + /* Discards a given size object. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Done_Size( FT_Size size ) + { + FT_Error error; + FT_Driver driver; + FT_Memory memory; + FT_Face face; + FT_ListNode node; + + + if ( !size ) + return FT_Err_Invalid_Size_Handle; + + face = size->face; + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + if ( !driver ) + return FT_Err_Invalid_Driver_Handle; + + memory = driver->root.memory; + + error = FT_Err_Ok; + node = FT_List_Find( &face->sizes_list, size ); + if ( node ) + { + FT_List_Remove( &face->sizes_list, node ); + FREE( node ); + + if ( face->size == size ) + { + face->size = 0; + if ( face->sizes_list.head ) + face->size = (FT_Size)(face->sizes_list.head->data); + } + + destroy_size( memory, size, driver ); + } + else + error = FT_Err_Invalid_Size_Handle; + + return FT_Err_Ok; + } + + + static + void ft_recompute_scaled_metrics( FT_Face face, + FT_Size_Metrics* metrics ) + { + /* Compute root ascender, descender, test height, and max_advance */ + + metrics->ascender = ( FT_MulFix( face->ascender, + metrics->y_scale ) + 32 ) & -64; + + metrics->descender = ( FT_MulFix( face->descender, + metrics->y_scale ) + 32 ) & -64; + + metrics->height = ( FT_MulFix( face->height, + metrics->y_scale ) + 32 ) & -64; + + metrics->max_advance = ( FT_MulFix( face->max_advance_width, + metrics->x_scale ) + 32 ) & -64; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Char_Size */ + /* */ + /* */ + /* Sets the character dimensions of a given face object. The */ + /* `char_width' and `char_height' values are used for the width and */ + /* height, respectively, expressed in 26.6 fractional points. */ + /* */ + /* If the horizontal or vertical resolution values are zero, a */ + /* default value of 72dpi is used. Similarly, if one of the */ + /* character dimensions is zero, its value is set equal to the other. */ + /* */ + /* */ + /* size :: A handle to a target size object. */ + /* */ + /* */ + /* char_width :: The character width, in 26.6 fractional points. */ + /* */ + /* char_height :: The character height, in 26.6 fractional */ + /* points. */ + /* */ + /* horz_resolution :: The horizontal resolution. */ + /* */ + /* vert_resolution :: The vertical resolution. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* When dealing with fixed-size faces (i.e., non-scalable formats), */ + /* use the function FT_Set_Pixel_Sizes(). */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Set_Char_Size( FT_Face face, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Memory memory; + FT_Driver_Class* clazz; + FT_Size_Metrics* metrics; + FT_Long dim_x, dim_y; + + + if ( !face || !face->size || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + metrics = &face->size->metrics; + + if ( !char_width ) + char_width = char_height; + + else if ( !char_height ) + char_height = char_width; + + if ( !horz_resolution ) + horz_resolution = 72; + + if ( !vert_resolution ) + vert_resolution = 72; + + driver = face->driver; + clazz = driver->clazz; + memory = driver->root.memory; + + /* default processing -- this can be overridden by the driver */ + if ( char_width < 1 * 64 ) + char_width = 1 * 64; + if ( char_height < 1 * 64 ) + char_height = 1 * 64; + + /* Compute pixel sizes in 26.6 units */ + dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64; + dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64; + + metrics->x_ppem = (FT_UShort)( dim_x >> 6 ); + metrics->y_ppem = (FT_UShort)( dim_y >> 6 ); + + metrics->x_scale = 0x10000L; + metrics->y_scale = 0x10000L; + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + { + metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM ); + metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM ); + + ft_recompute_scaled_metrics( face, metrics ); + } + + if ( clazz->set_char_sizes ) + error = clazz->set_char_sizes( face->size, + char_width, + char_height, + horz_resolution, + vert_resolution ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Pixel_Sizes */ + /* */ + /* */ + /* Sets the character dimensions of a given face object. The width */ + /* and height are expressed in integer pixels. */ + /* */ + /* If one of the character dimensions is zero, its value is set equal */ + /* to the other. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* pixel_width :: The character width, in integer pixels. */ + /* */ + /* pixel_height :: The character height, in integer pixels. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face, + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Memory memory; + FT_Driver_Class* clazz; + FT_Size_Metrics* metrics = &face->size->metrics; + + + if ( !face || !face->size || !face->driver ) + return FT_Err_Invalid_Face_Handle; + + driver = face->driver; + clazz = driver->clazz; + memory = driver->root.memory; + + /* default processing -- this can be overridden by the driver */ + if ( pixel_width == 0 ) + pixel_width = pixel_height; + + else if ( pixel_height == 0 ) + pixel_height = pixel_width; + + if ( pixel_width < 1 ) + pixel_width = 1; + if ( pixel_height < 1 ) + pixel_height = 1; + + metrics->x_ppem = pixel_width; + metrics->y_ppem = pixel_height; + + if ( face->face_flags & FT_FACE_FLAG_SCALABLE ) + { + metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, + face->units_per_EM ); + + metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, + face->units_per_EM ); + + ft_recompute_scaled_metrics( face, metrics ); + } + + if ( clazz->set_pixel_sizes ) + error = clazz->set_pixel_sizes( face->size, + pixel_width, + pixel_height ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Kerning */ + /* */ + /* */ + /* Returns the kerning vector between two glyphs of a same face. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* kern_mode :: See FT_Kerning_Mode() for more information. */ + /* Determines the scale/dimension of the returned */ + /* kerning vector. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this method. Other layouts, or more sophisticated */ + /* kernings, are out of the scope of this API function -- they can be */ + /* implemented through format-specific interfaces. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_UInt kern_mode, + FT_Vector* kerning ) + { + FT_Error error = FT_Err_Ok; + FT_Driver driver; + FT_Memory memory; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + if ( !kerning ) + return FT_Err_Invalid_Argument; + + driver = face->driver; + memory = driver->root.memory; + + kerning->x = 0; + kerning->y = 0; + + if ( driver->clazz->get_kerning ) + { + error = driver->clazz->get_kerning( face, + left_glyph, + right_glyph, + kerning ); + if ( !error ) + { + if ( kern_mode != ft_kerning_unscaled ) + { + kerning->x = FT_MulFix( kerning->x, face->size->metrics.x_scale ); + kerning->y = FT_MulFix( kerning->y, face->size->metrics.y_scale ); + + if ( kern_mode != ft_kerning_unfitted ) + { + kerning->x = ( kerning->x + 32 ) & -64; + kerning->y = ( kerning->y + 32 ) & -64; + } + } + } + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Select_Charmap */ + /* */ + /* */ + /* Selects a given charmap by its encoding tag (as listed in */ + /* `freetype.h'). */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* encoding :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if no charmap in the face */ + /* corresponds to the encoding queried here. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Select_Charmap( FT_Face face, + FT_Encoding encoding ) + { + FT_CharMap* cur; + FT_CharMap* limit; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + cur = face->charmaps; + if ( !cur ) + return FT_Err_Invalid_CharMap_Handle; + + limit = cur + face->num_charmaps; + + for ( ; cur < limit; cur++ ) + { + if ( cur[0]->encoding == encoding ) + { + face->charmap = cur[0]; + return 0; + } + } + + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Charmap */ + /* */ + /* */ + /* Selects a given charmap for character code to glyph index */ + /* decoding. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* charmap :: A handle to the selected charmap. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function will return an error if the charmap is not part of */ + /* the face (i.e., if it is not listed in the face->charmaps[] */ + /* table). */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Set_Charmap( FT_Face face, + FT_CharMap charmap ) + { + FT_CharMap* cur; + FT_CharMap* limit; + + + if ( !face ) + return FT_Err_Invalid_Face_Handle; + + cur = face->charmaps; + if ( !cur ) + return FT_Err_Invalid_CharMap_Handle; + + limit = cur + face->num_charmaps; + + for ( ; cur < limit; cur++ ) + { + if ( cur[0] == charmap ) + { + face->charmap = cur[0]; + return 0; + } + } + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Char_Index */ + /* */ + /* */ + /* Returns the glyph index of a given character code. This function */ + /* uses a charmap object to do the translation. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* The glyph index. 0 means `undefined character code'. */ + /* */ + FT_EXPORT_FUNC( FT_UInt ) FT_Get_Char_Index( FT_Face face, + FT_ULong charcode ) + { + FT_UInt result; + FT_Driver driver; + + + result = 0; + if ( face && face->charmap ) + { + driver = face->driver; + result = driver->clazz->get_char_index( face->charmap, charcode ); + } + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Glyph_Name */ + /* */ + /* */ + /* Retrieves the ASCII name of a given glyph in a face. This only */ + /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */ + /* */ + /* */ + /* face :: A handle to a source face object. */ + /* */ + /* glyph_index :: The glyph index. */ + /* */ + /* buffer :: A pointer to a target buffer where the name will be */ + /* copied to. */ + /* */ + /* buffer_max :: The maximal number of bytes available in the */ + /* buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* An error is returned if the face doesn't provide glyph names or if */ + /* the glyph index is invalid. In all cases of failure, the first */ + /* byte of `buffer' will be set to 0 to indicate an empty name. */ + /* */ + /* The glyph name is truncated to fit within the buffer if it is too */ + /* long. The returned string is always zero-terminated. */ + /* */ + /* This function is not compiled within the library if the config */ + /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */ + /* `include/freetype/config/ftoptions.h' */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Get_Glyph_Name( FT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_Error error = FT_Err_Invalid_Argument; + + + /* clean up buffer */ + if ( buffer && buffer_max > 0 ) + ((FT_Byte*)buffer)[0] = 0; + + if ( face && + glyph_index < (FT_UInt)face->num_glyphs && + FT_HAS_GLYPH_NAMES( face ) ) + { + /* now, lookup for glyph name */ + FT_Driver driver = face->driver; + FT_Module_Class* clazz = FT_MODULE_CLASS( driver ); + + + if ( clazz->get_interface ) + { + FT_Glyph_Name_Requester requester; + + + requester = (FT_Glyph_Name_Requester)clazz->get_interface( + FT_MODULE( driver ), "glyph_name" ); + if ( requester ) + error = requester( face, glyph_index, buffer, buffer_max ); + } + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Sfnt_Table */ + /* */ + /* */ + /* Returns a pointer to a given SFNT table within a face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* tag :: An index of an SFNT table. */ + /* */ + /* */ + /* A type-less pointer to the table. This will be 0 in case of */ + /* error, or if the corresponding table was not found *OR* loaded */ + /* from the file. */ + /* */ + /* */ + /* The table is owned by the face object, and disappears with it. */ + /* */ + /* This function is only useful to access SFNT tables that are loaded */ + /* by the sfnt/truetype/opentype drivers. See the FT_Sfnt_Tag */ + /* enumeration in `tttables.h' for a list. */ + /* */ + /* You can load any table with a different function.. XXX */ + /* */ + FT_EXPORT_FUNC( void* ) FT_Get_Sfnt_Table( FT_Face face, + FT_Sfnt_Tag tag ) + { + void* table = 0; + FT_Get_Sfnt_Table_Func func; + FT_Driver driver; + + + if ( !face || !FT_IS_SFNT( face ) ) + goto Exit; + + driver = face->driver; + func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface( + FT_MODULE( driver ), "get_sfnt" ); + if ( func ) + table = func( face, tag ); + + Exit: + return table; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** R E N D E R E R S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /* lookup a renderer by glyph format in the library's list */ + BASE_FUNC( FT_Renderer ) FT_Lookup_Renderer( FT_Library library, + FT_Glyph_Format format, + FT_ListNode* node ) + { + FT_ListNode cur; + FT_Renderer result = 0; + + + if ( !library ) + goto Exit; + + cur = library->renderers.head; + + if ( node ) + { + if ( *node ) + cur = (*node)->next; + *node = 0; + } + + while ( cur ) + { + FT_Renderer renderer = FT_RENDERER( cur->data ); + + + if ( renderer->glyph_format == format ) + { + if ( node ) + *node = cur; + + result = renderer; + break; + } + cur = cur->next; + } + + Exit: + return result; + } + + + static + FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot ) + { + FT_Face face = slot->face; + FT_Library library = FT_FACE_LIBRARY( face ); + FT_Renderer result = library->cur_renderer; + + + if ( !result || result->glyph_format != slot->format ) + result = FT_Lookup_Renderer( library, slot->format, 0 ); + + return result; + } + + + static + void ft_set_current_renderer( FT_Library library ) + { + FT_Renderer renderer; + + + renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 ); + library->cur_renderer = renderer; + } + + + static + FT_Error ft_add_renderer( FT_Module module ) + { + FT_Library library = module->library; + FT_Memory memory = library->memory; + FT_Error error; + FT_ListNode node; + + + if ( ALLOC( node, sizeof ( *node ) ) ) + goto Exit; + + { + FT_Renderer render = FT_RENDERER( module ); + FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz; + + + render->clazz = clazz; + render->glyph_format = clazz->glyph_format; + + /* allocate raster object if needed */ + if ( clazz->glyph_format == ft_glyph_format_outline && + clazz->raster_class->raster_new ) + { + error = clazz->raster_class->raster_new( memory, &render->raster ); + if ( error ) + goto Fail; + + render->raster_render = clazz->raster_class->raster_render; + render->render = clazz->render_glyph; + } + + /* add to list */ + node->data = module; + FT_List_Add( &library->renderers, node ); + + ft_set_current_renderer( library ); + } + + Fail: + if ( error ) + FREE( node ); + + Exit: + return error; + } + + + static + void ft_remove_renderer( FT_Module module ) + { + FT_Library library = module->library; + FT_Memory memory = library->memory; + FT_ListNode node; + + + node = FT_List_Find( &library->renderers, module ); + if ( node ) + { + FT_Renderer render = FT_RENDERER( module ); + + + /* release raster object, if any */ + if ( render->raster ) + render->clazz->raster_class->raster_done( render->raster ); + + /* remove from list */ + FT_List_Remove( &library->renderers, node ); + FREE( node ); + + ft_set_current_renderer( library ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Renderer */ + /* */ + /* */ + /* Retrieves the current renderer for a given glyph format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* format :: The glyph format. */ + /* */ + /* */ + /* A renderer handle. 0 if none found. */ + /* */ + /* */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */ + /* renderer by its name, use FT_Get_Module(). */ + /* */ + FT_EXPORT_FUNC( FT_Renderer ) FT_Get_Renderer( FT_Library library, + FT_Glyph_Format format ) + { + /* test for valid `library' delayed to FT_Lookup_Renderer() */ + + return FT_Lookup_Renderer( library, format, 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Renderer */ + /* */ + /* */ + /* Sets the current renderer to use, and set additional mode. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* renderer :: A handle to the renderer object. */ + /* */ + /* num_params :: The number of additional parameters. */ + /* */ + /* parameters :: Additional parameters. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* In case of success, the renderer will be used to convert glyph */ + /* images in the renderer's known format into bitmaps. */ + /* */ + /* This doesn't change the current renderer for other formats. */ + /* */ + FT_EXPORT_DEF( FT_Error ) FT_Set_Renderer( FT_Library library, + FT_Renderer renderer, + FT_UInt num_params, + FT_Parameter* parameters ) + { + FT_ListNode node; + FT_Error error = FT_Err_Ok; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !renderer ) + return FT_Err_Invalid_Argument; + + node = FT_List_Find( &library->renderers, renderer ); + if ( !node ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + FT_List_Up( &library->renderers, node ); + + if ( renderer->glyph_format == ft_glyph_format_outline ) + library->cur_renderer = renderer; + + if ( num_params > 0 ) + { + FTRenderer_setMode set_mode = renderer->clazz->set_mode; + + + for ( ; num_params > 0; num_params-- ) + { + error = set_mode( renderer, parameters->tag, parameters->data ); + if ( error ) + break; + } + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error FT_Render_Glyph_Internal( FT_Library library, + FT_GlyphSlot slot, + FT_UInt render_mode ) + { + FT_Error error = FT_Err_Ok; + FT_Renderer renderer; + + + /* if it is already a bitmap, no need to do anything */ + switch ( slot->format ) + { + case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */ + break; + + default: + { + FT_ListNode node = 0; + FT_Bool update = 0; + + + /* small shortcut for the very common case */ + if ( slot->format == ft_glyph_format_outline ) + { + renderer = library->cur_renderer; + node = library->renderers.head; + } + else + renderer = FT_Lookup_Renderer( library, slot->format, &node ); + + error = FT_Err_Unimplemented_Feature; + while ( renderer ) + { + error = renderer->render( renderer, slot, render_mode, 0 ); + if ( !error || error != FT_Err_Cannot_Render_Glyph ) + break; + + /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ + /* is unsupported by the current renderer for this glyph image */ + /* format. */ + + /* now, look for another renderer that supports the same */ + /* format. */ + renderer = FT_Lookup_Renderer( library, slot->format, &node ); + update = 1; + } + + /* if we changed the current renderer for the glyph image format */ + /* we need to select it as the next current one */ + if ( !error && update && renderer ) + FT_Set_Renderer( library, renderer, 0, 0 ); + } + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Render_Glyph */ + /* */ + /* */ + /* Converts a given glyph image to a bitmap. It does so by */ + /* inspecting the glyph image format, find the relevant renderer, and */ + /* invoke it. */ + /* */ + /* */ + /* slot :: A handle to the glyph slot containing the image to */ + /* convert. */ + /* */ + /* render_mode :: This is the render mode used to render the glyph */ + /* image into a bitmap. See FT_Render_Mode for a list */ + /* of possible values. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot, + FT_UInt render_mode ) + { + FT_Library library; + + + if ( !slot ) + return FT_Err_Invalid_Argument; + + library = FT_FACE_LIBRARY( slot->face ); + + return FT_Render_Glyph_Internal( library, slot, render_mode ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** M O D U L E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Destroy_Module */ + /* */ + /* */ + /* Destroys a given module object. For drivers, this also destroys */ + /* all child faces. */ + /* */ + /* */ + /* module :: A handle to the target driver object. */ + /* */ + /* */ + /* The driver _must_ be LOCKED! */ + /* */ + static + void Destroy_Module( FT_Module module ) + { + FT_Memory memory = module->memory; + FT_Module_Class* clazz = module->clazz; + FT_Library library = module->library; + + + /* finalize client-data - before anything else */ + if ( module->generic.finalizer ) + module->generic.finalizer( module ); + + if ( library && library->auto_hinter == module ) + library->auto_hinter = 0; + + /* if the module is a renderer */ + if ( FT_MODULE_IS_RENDERER( module ) ) + ft_remove_renderer( module ); + + /* if the module is a font driver, add some steps */ + if ( FT_MODULE_IS_DRIVER( module ) ) + Destroy_Driver( FT_DRIVER( module ) ); + + /* finalize the module object */ + if ( clazz->module_done ) + clazz->module_done( module ); + + /* discard it */ + FREE( module ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Add_Module */ + /* */ + /* */ + /* Adds a new module to a given library instance. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* clazz :: A pointer to class descriptor for the module. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* An error will be returned if a module already exists by that name, */ + /* or if the module requires a version of FreeType that is too great. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Add_Module( FT_Library library, + const FT_Module_Class* clazz ) + { + FT_Error error; + FT_Memory memory; + FT_Module module; + FT_UInt nn; + + +#define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \ + FREETYPE_MINOR ) + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !clazz ) + return FT_Err_Invalid_Argument; + + /* check freetype version */ + if ( clazz->module_requires > FREETYPE_VER_FIXED ) + return FT_Err_Invalid_Version; + + /* look for a module with the same name in the library's table */ + for ( nn = 0; nn < library->num_modules; nn++ ) + { + module = library->modules[nn]; + if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 ) + { + /* this installed module has the same name, compare their versions */ + if ( clazz->module_version <= module->clazz->module_version ) + return FT_Err_Lower_Module_Version; + + /* remove the module from our list, then exit the loop to replace */ + /* it by our new version.. */ + FT_Remove_Module( library, module ); + break; + } + } + + memory = library->memory; + error = FT_Err_Ok; + + if ( library->num_modules >= FT_MAX_MODULES ) + { + error = FT_Err_Too_Many_Drivers; + goto Exit; + } + + /* allocate module object */ + if ( ALLOC( module,clazz->module_size ) ) + goto Exit; + + /* base initialization */ + module->library = library; + module->memory = memory; + module->clazz = (FT_Module_Class*)clazz; + + /* check whether the module is a renderer - this must be performed */ + /* before the normal module initialization */ + if ( FT_MODULE_IS_RENDERER( module ) ) + { + /* add to the renderers list */ + error = ft_add_renderer( module ); + if ( error ) + goto Fail; + } + + /* is the module a auto-hinter? */ + if ( FT_MODULE_IS_HINTER( module ) ) + library->auto_hinter = module; + + /* if the module is a font driver */ + if ( FT_MODULE_IS_DRIVER( module ) ) + { + /* allocate glyph loader if needed */ + FT_Driver driver = FT_DRIVER( module ); + + + driver->clazz = (FT_Driver_Class*)module->clazz; + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + { + error = FT_GlyphLoader_New( memory, &driver->glyph_loader ); + if ( error ) + goto Fail; + } + } + + if ( clazz->module_init ) + { + error = clazz->module_init( module ); + if ( error ) + goto Fail; + } + + /* add module to the library's table */ + library->modules[library->num_modules++] = module; + + Exit: + return error; + + Fail: + if ( FT_MODULE_IS_DRIVER( module ) ) + { + FT_Driver driver = FT_DRIVER( module ); + + + if ( FT_DRIVER_USES_OUTLINES( driver ) ) + FT_GlyphLoader_Done( driver->glyph_loader ); + } + + if ( FT_MODULE_IS_RENDERER( module ) ) + { + FT_Renderer renderer = FT_RENDERER( module ); + + + if ( renderer->raster ) + renderer->clazz->raster_class->raster_done( renderer->raster ); + } + + FREE( module ); + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module */ + /* */ + /* */ + /* Finds a module by its name. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module handle. 0 if none was found. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for :-) */ + /* */ + FT_EXPORT_FUNC( FT_Module ) FT_Get_Module( FT_Library library, + const char* module_name ) + { + FT_Module result = 0; + FT_Module* cur; + FT_Module* limit; + + + if ( !library || !module_name ) + return result; + + cur = library->modules; + limit = cur + library->num_modules; + + for ( ; cur < limit; cur++ ) + if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 ) + { + result = cur[0]; + break; + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Get_Module_Interface */ + /* */ + /* */ + /* Finds a module and returns its specific interface as a typeless */ + /* pointer. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* module_name :: The module's name (as an ASCII string). */ + /* */ + /* */ + /* A module-specific interface if available, 0 otherwise. */ + /* */ + /* */ + /* You should better be familiar with FreeType internals to know */ + /* which module to look for, and what its interface is :-) */ + /* */ + BASE_FUNC( const void* ) FT_Get_Module_Interface( FT_Library library, + const char* mod_name ) + { + FT_Module module; + + + /* test for valid `library' delayed to FT_Get_Module() */ + + module = FT_Get_Module( library, mod_name ); + + return module ? module->clazz->module_interface : 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Remove_Module */ + /* */ + /* */ + /* Removes a given module from a library instance. */ + /* */ + /* */ + /* library :: A handle to a library object. */ + /* */ + /* module :: A handle to a module object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The module object is destroyed by the function in case of success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Remove_Module( FT_Library library, + FT_Module module ) + { + /* try to find the module from the table, then remove it from there */ + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( module ) + { + FT_Module* cur = library->modules; + FT_Module* limit = cur + library->num_modules; + + + for ( ; cur < limit; cur++ ) + { + if ( cur[0] == module ) + { + /* remove it from the table */ + library->num_modules--; + limit--; + while ( cur < limit ) + { + cur[0] = cur[1]; + cur++; + } + limit[0] = 0; + + /* destroy the module */ + Destroy_Module( module ); + + return FT_Err_Ok; + } + } + } + return FT_Err_Invalid_Driver_Handle; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** L I B R A R Y ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Library */ + /* */ + /* */ + /* This function is used to create a new FreeType library instance */ + /* from a given memory object. It is thus possible to use libraries */ + /* with distinct memory allocators within the same program. */ + /* */ + /* */ + /* memory :: A handle to the original memory object. */ + /* */ + /* */ + /* alibrary :: A pointer to handle of a new library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Library( FT_Memory memory, + FT_Library* alibrary ) + { + FT_Library library = 0; + FT_Error error; + + + if ( !memory ) + return FT_Err_Invalid_Argument; + + /* first of all, allocate the library object */ + if ( ALLOC( library, sizeof ( *library ) ) ) + return error; + + library->memory = memory; + + /* allocate the render pool */ + library->raster_pool_size = FT_RENDER_POOL_SIZE; + if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) ) + goto Fail; + + /* That's ok now */ + *alibrary = library; + + return FT_Err_Ok; + + Fail: + FREE( library ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_Library */ + /* */ + /* */ + /* Discards a given library object. This closes all drivers and */ + /* discards all resource objects. */ + /* */ + /* */ + /* library :: A handle to the target library. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Done_Library( FT_Library library ) + { + FT_Memory memory; + FT_UInt n; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + memory = library->memory; + + /* Discard client-data */ + if ( library->generic.finalizer ) + library->generic.finalizer( library ); + + /* Close all modules in the library */ + for ( n = 0; n < library->num_modules; n++ ) + { + FT_Module module = library->modules[n]; + + + if ( module ) + { + Destroy_Module( module ); + library->modules[n] = 0; + } + } + + /* Destroy raster objects */ + FREE( library->raster_pool ); + library->raster_pool_size = 0; + + FREE( library ); + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Set_Debug_Hook */ + /* */ + /* */ + /* Sets a debug hook function for debugging the interpreter of a font */ + /* format. */ + /* */ + /* */ + /* library :: A handle to the library object. */ + /* */ + /* hook_index :: The index of the debug hook. You should use the */ + /* values defined in ftobjs.h, e.g. */ + /* FT_DEBUG_HOOK_TRUETYPE */ + /* */ + /* debug_hook :: The function used to debug the interpreter. */ + /* */ + /* */ + /* Currently, four debug hook slots are available, but only two (for */ + /* the TrueType and the Type 1 interpreter) are defined. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Set_Debug_Hook( FT_Library library, + FT_UInt hook_index, + FT_DebugHook_Func debug_hook ) + { + if ( library && debug_hook && + hook_index < + ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) ) + library->debug_hooks[hook_index] = debug_hook; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Done_FreeType */ + /* */ + /* */ + /* Destroys a given FreeType library object and all of its childs, */ + /* including resources, drivers, faces, sizes, etc. */ + /* */ + /* */ + /* library :: A handle to the target library object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library ) + { + /* test for valid `library' delayed to FT_Done_Library() */ + + /* Discard the library object */ + FT_Done_Library( library ); + + return FT_Err_Ok; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftoutln.c b/subsys/win32k/freetype/src/base/ftoutln.c new file mode 100644 index 0000000..20292d0 --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftoutln.c @@ -0,0 +1,842 @@ +/***************************************************************************/ +/* */ +/* ftoutln.c */ +/* */ +/* FreeType outline management (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* All functions are declared in freetype.h. */ + /* */ + /*************************************************************************/ + + +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_outline + + + static + const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* */ + /* outline :: A pointer to the source target. */ + /* */ + /* interface :: A table of `emitters', i.e,. function pointers called */ + /* during decomposition to indicate path operations. */ + /* */ + /* user :: A typeless pointer which is passed to each emitter */ + /* during the decomposition. It can be used to store */ + /* the state during the decomposition. */ + /* */ + /* */ + /* FreeType error code. 0 means sucess. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Decompose( + FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ) + { +#undef SCALED +#define SCALED( x ) ( ( (x) << shift ) - delta ) + + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + FT_Error error; + + FT_Int n; /* index of contour in outline */ + FT_UInt first; /* index of first point in contour */ + char tag; /* current point's state */ + + FT_Int shift; + FT_Pos delta; + + + if ( !outline || !interface ) + return FT_Err_Invalid_Argument; + + shift = interface->shift; + delta = interface->delta; + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + FT_Int last; /* index of last point in contour */ + + + last = outline->contours[n]; + limit = outline->points + last; + + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); + v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y ); + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_Curve_Tag_Conic ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + error = interface->move_to( &v_start, user ); + if ( error ) + goto Exit; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch ( tag ) + { + case FT_Curve_Tag_On: /* emit a single line_to */ + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = interface->line_to( &vec, user ); + if ( error ) + goto Exit; + continue; + } + + case FT_Curve_Tag_Conic: /* consume conic arcs */ + v_control.x = SCALED( point->x ); + v_control.y = SCALED( point->y ); + + Do_Conic: + if ( point < limit ) + { + FT_Vector vec; + FT_Vector v_middle; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + if ( tag == FT_Curve_Tag_On ) + { + error = interface->conic_to( &v_control, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + if ( tag != FT_Curve_Tag_Conic ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + vec.x ) / 2; + v_middle.y = ( v_control.y + vec.y ) / 2; + + error = interface->conic_to( &v_control, &v_middle, user ); + if ( error ) + goto Exit; + + v_control = vec; + goto Do_Conic; + } + + error = interface->conic_to( &v_control, &v_start, user ); + goto Close; + + default: /* FT_Curve_Tag_Cubic */ + { + FT_Vector vec1, vec2; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y ); + vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y ); + + if ( point <= limit ) + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = interface->cubic_to( &vec1, &vec2, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + error = interface->cubic_to( &vec1, &vec2, &v_start, user ); + goto Close; + } + } + } + + /* close the contour with a line segment */ + error = interface->line_to( &v_start, user ); + + Close: + if ( error ) + goto Exit; + + first = last + 1; + } + + return 0; + + Exit: + return error; + + Invalid_Outline: + return FT_Err_Invalid_Outline; + } + + + FT_EXPORT_FUNC( FT_Error ) FT_Outline_New_Internal( + FT_Memory memory, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + FT_Error error; + + + if ( !outline || !memory ) + return FT_Err_Invalid_Argument; + + *outline = null_outline; + + if ( ALLOC_ARRAY( outline->points, numPoints * 2L, FT_Pos ) || + ALLOC_ARRAY( outline->tags, numPoints, FT_Byte ) || + ALLOC_ARRAY( outline->contours, numContours, FT_UShort ) ) + goto Fail; + + outline->n_points = (FT_UShort)numPoints; + outline->n_contours = (FT_Short)numContours; + outline->flags |= ft_outline_owner; + + return FT_Err_Ok; + + Fail: + outline->flags |= ft_outline_owner; + FT_Outline_Done_Internal( memory, outline ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_New */ + /* */ + /* */ + /* Creates a new outline of a given size. */ + /* */ + /* */ + /* library :: A handle to the library object from where the */ + /* outline is allocated. Note however that the new */ + /* outline will NOT necessarily be FREED, when */ + /* destroying the library, by FT_Done_FreeType(). */ + /* */ + /* numPoints :: The maximal number of points within the outline. */ + /* */ + /* numContours :: The maximal number of contours within the outline. */ + /* */ + /* */ + /* outline :: A handle to the new outline. NULL in case of */ + /* error. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* The reason why this function takes a `library' parameter is simply */ + /* to use the library's memory allocator. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_New( FT_Library library, + FT_UInt numPoints, + FT_Int numContours, + FT_Outline* outline ) + { + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + return FT_Outline_New_Internal( library->memory, numPoints, + numContours, outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Copy */ + /* */ + /* */ + /* Copies an outline into another one. Both objects must have the */ + /* same sizes (number of points & number of contours) when this */ + /* function is called. */ + /* */ + /* */ + /* source :: A handle to the source outline. */ + /* */ + /* */ + /* target :: A handle to the target outline. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Copy( FT_Outline* source, + FT_Outline* target ) + { + FT_Int is_owner; + + + if ( !source || !target || + source->n_points != target->n_points || + source->n_contours != target->n_contours ) + return FT_Err_Invalid_Argument; + + MEM_Copy( target->points, source->points, + source->n_points * sizeof ( FT_Vector ) ); + + MEM_Copy( target->tags, source->tags, + source->n_points * sizeof ( FT_Byte ) ); + + MEM_Copy( target->contours, source->contours, + source->n_contours * sizeof ( FT_Short ) ); + + /* copy all flags, except the `ft_outline_owner' one */ + is_owner = target->flags & ft_outline_owner; + target->flags = source->flags; + + target->flags &= ~ft_outline_owner; + target->flags |= is_owner; + + return FT_Err_Ok; + } + + + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Done_Internal( FT_Memory memory, + FT_Outline* outline ) + { + if ( outline ) + { + if ( outline->flags & ft_outline_owner ) + { + FREE( outline->points ); + FREE( outline->tags ); + FREE( outline->contours ); + } + *outline = null_outline; + + return FT_Err_Ok; + } + else + return FT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Done */ + /* */ + /* */ + /* Destroys an outline created with FT_Outline_New(). */ + /* */ + /* */ + /* library :: A handle of the library object used to allocate the */ + /* outline. */ + /* */ + /* outline :: A pointer to the outline object to be discarded. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* No. */ + /* */ + /* */ + /* If the outline's `owner' field is not set, only the outline */ + /* descriptor will be released. */ + /* */ + /* The reason why this function takes an `outline' parameter is */ + /* simply to use FT_Free(). */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Done( FT_Library library, + FT_Outline* outline ) + { + /* check for valid `outline' in FT_Outline_Done_Internal() */ + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + return FT_Outline_Done_Internal( library->memory, outline ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_CBox */ + /* */ + /* */ + /* Returns an outline's `control box'. The control box encloses all */ + /* the outline's points, including Bezier control points. Though it */ + /* coincides with the exact bounding box for most glyphs, it can be */ + /* slightly larger in some situations (like when rotating an outline */ + /* which contains Bezier outside arcs). */ + /* */ + /* Computing the control box is very fast, while getting the bounding */ + /* box can take much more time as it needs to walk over all segments */ + /* and arcs in the outline. To get the latter, you can use the */ + /* `ftbbox' component which is dedicated to this single task. */ + /* */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* */ + /* cbox :: The outline's control box. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Outline_Get_CBox( FT_Outline* outline, + FT_BBox* cbox ) + { + FT_Pos xMin, yMin, xMax, yMax; + + + if ( outline && cbox ) + { + if ( outline->n_points == 0 ) + { + xMin = 0; + yMin = 0; + xMax = 0; + yMax = 0; + } + else + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + + xMin = xMax = vec->x; + yMin = yMax = vec->y; + vec++; + + for ( ; vec < limit; vec++ ) + { + FT_Pos x, y; + + + x = vec->x; + if ( x < xMin ) xMin = x; + if ( x > xMax ) xMax = x; + + y = vec->y; + if ( y < yMin ) yMin = y; + if ( y > yMax ) yMax = y; + } + } + cbox->xMin = xMin; + cbox->xMax = xMax; + cbox->yMin = yMin; + cbox->yMax = yMax; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Translate */ + /* */ + /* */ + /* Applies a simple translation to the points of an outline. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* xOffset :: The horizontal offset. */ + /* */ + /* yOffset :: The vertical offset. */ + /* */ + /* */ + /* Yes. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Outline_Translate( FT_Outline* outline, + FT_Pos xOffset, + FT_Pos yOffset ) + { + FT_UShort n; + FT_Vector* vec = outline->points; + + + for ( n = 0; n < outline->n_points; n++ ) + { + vec->x += xOffset; + vec->y += yOffset; + vec++; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Reverse */ + /* */ + /* */ + /* Reverses the drawing direction of an outline. This is used to */ + /* ensure consistent fill conventions for mirrored glyphs. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* */ + /* This functions toggles the bit flag `ft_outline_reverse_fill' in */ + /* the outline's `flags' field. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Outline_Reverse( FT_Outline* outline ) + { + FT_UShort n; + FT_Int first, last; + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + last = outline->contours[n]; + + /* reverse point table */ + { + FT_Vector* p = outline->points + first; + FT_Vector* q = outline->points + last; + FT_Vector swap; + + + while ( p < q ) + { + swap = *p; + *p = *q; + *q = swap; + p++; + q--; + } + } + + /* reverse tags table */ + { + char* p = outline->tags + first; + char* q = outline->tags + last; + char swap; + + + while ( p < q ) + { + swap = *p; + *p = *q; + *q = swap; + p++; + q--; + } + } + + first = last + 1; + } + + outline->flags ^= ft_outline_reverse_fill; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Render */ + /* */ + /* */ + /* Renders an outline within a bitmap using the current scan-convert. */ + /* This functions uses an FT_Raster_Params structure as an argument, */ + /* allowing advanced features like direct composition, translucency, */ + /* etc. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* params :: A pointer to a FT_Raster_Params structure used to */ + /* describe the rendering operation. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* You should know what you are doing and how FT_Raster_Params works */ + /* to use this function. */ + /* */ + /* The field `params.source' will be set to `outline' before the scan */ + /* converter is called, which means that the value you give to it is */ + /* actually ignored. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Render( FT_Library library, + FT_Outline* outline, + FT_Raster_Params* params ) + { + FT_Error error; + FT_Bool update = 0; + FT_Renderer renderer; + FT_ListNode node; + + + if ( !library ) + return FT_Err_Invalid_Library_Handle; + + if ( !params ) + return FT_Err_Invalid_Argument; + + renderer = library->cur_renderer; + node = library->renderers.head; + + params->source = (void*)outline; + + error = FT_Err_Cannot_Render_Glyph; + while ( renderer ) + { + error = renderer->raster_render( renderer->raster, params ); + if ( !error || error != FT_Err_Cannot_Render_Glyph ) + break; + + /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ + /* is unsupported by the current renderer for this glyph image */ + /* format */ + + /* now, look for another renderer that supports the same */ + /* format */ + renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, + &node ); + update = 1; + } + + /* if we changed the current renderer for the glyph image format */ + /* we need to select it as the next current one */ + if ( !error && update && renderer ) + FT_Set_Renderer( library, renderer, 0, 0 ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Get_Bitmap */ + /* */ + /* */ + /* Renders an outline within a bitmap. The outline's image is simply */ + /* OR-ed to the target bitmap. */ + /* */ + /* */ + /* library :: A handle to a FreeType library object. */ + /* */ + /* outline :: A pointer to the source outline descriptor. */ + /* */ + /* map :: A pointer to the target bitmap descriptor. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* YES. Rendering is synchronized, so that concurrent calls to the */ + /* scan-line converter will be serialized. */ + /* */ + /* */ + /* This function does NOT CREATE the bitmap, it only renders an */ + /* outline image within the one you pass to it! */ + /* */ + /* It will use the raster correponding to the default glyph format. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library, + FT_Outline* outline, + FT_Bitmap* bitmap ) + { + FT_Raster_Params params; + + + if ( !bitmap ) + return FT_Err_Invalid_Argument; + + /* other checks are delayed to FT_Outline_Render() */ + + params.target = bitmap; + params.flags = 0; + + if ( bitmap->pixel_mode == ft_pixel_mode_grays ) + params.flags |= ft_raster_flag_aa; + + return FT_Outline_Render( library, outline, ¶ms ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Vector_Transform */ + /* */ + /* */ + /* Transforms a single vector through a 2x2 matrix. */ + /* */ + /* */ + /* vector :: The target vector to transform. */ + /* */ + /* */ + /* matrix :: A pointer to the source 2x2 matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* The result is undefined if either `vector' or `matrix' is invalid. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Vector_Transform( FT_Vector* vector, + FT_Matrix* matrix ) + { + FT_Pos xz, yz; + + + if ( !vector || !matrix ) + return; + + xz = FT_MulFix( vector->x, matrix->xx ) + + FT_MulFix( vector->y, matrix->xy ); + + yz = FT_MulFix( vector->x, matrix->yx ) + + FT_MulFix( vector->y, matrix->yy ); + + vector->x = xz; + vector->y = yz; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Transform */ + /* */ + /* */ + /* Applies a simple 2x2 matrix to all of an outline's points. Useful */ + /* for applying rotations, slanting, flipping, etc. */ + /* */ + /* */ + /* outline :: A pointer to the target outline descriptor. */ + /* */ + /* matrix :: A pointer to the transformation matrix. */ + /* */ + /* */ + /* Yes. */ + /* */ + /* */ + /* You can use FT_Outline_Translate() if you need to translate the */ + /* outline's points. */ + /* */ + FT_EXPORT_FUNC( void ) FT_Outline_Transform( FT_Outline* outline, + FT_Matrix* matrix ) + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + + for ( ; vec < limit; vec++ ) + FT_Vector_Transform( vec, matrix ); + } + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftstream.c b/subsys/win32k/freetype/src/base/ftstream.c new file mode 100644 index 0000000..768586e --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftstream.c @@ -0,0 +1,818 @@ +/***************************************************************************/ +/* */ +/* ftstream.c */ +/* */ +/* I/O stream support (body). */ +/* */ +/* Copyright 2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_stream + + + BASE_FUNC( void ) FT_New_Memory_Stream( FT_Library library, + FT_Byte* base, + FT_ULong size, + FT_Stream stream ) + { + stream->memory = library->memory; + stream->base = base; + stream->size = size; + stream->pos = 0; + stream->cursor = 0; + stream->read = 0; + stream->close = 0; + } + + + BASE_FUNC( FT_Error ) FT_Seek_Stream( FT_Stream stream, + FT_ULong pos ) + { + FT_Error error; + + + stream->pos = pos; + + if ( stream->read ) + { + if ( stream->read( stream, pos, 0, 0 ) ) + { + FT_ERROR(( "FT_Seek_Stream:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + } + else + error = FT_Err_Ok; + } + /* note that seeking to the first position after the file is valid */ + else if ( pos > stream->size ) + { + FT_ERROR(( "FT_Seek_Stream:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + } + + else + error = FT_Err_Ok; + + return error; + } + + + BASE_FUNC( FT_Error ) FT_Skip_Stream( FT_Stream stream, + FT_Long distance ) + { + return FT_Seek_Stream( stream, (FT_ULong)( stream->pos + distance ) ); + } + + + BASE_FUNC( FT_Long ) FT_Stream_Pos( FT_Stream stream ) + { + return stream->pos; + } + + + BASE_FUNC( FT_Error ) FT_Read_Stream( FT_Stream stream, + FT_Byte* buffer, + FT_ULong count ) + { + return FT_Read_Stream_At( stream, stream->pos, buffer, count ); + } + + + BASE_FUNC( FT_Error ) FT_Read_Stream_At( FT_Stream stream, + FT_ULong pos, + FT_Byte* buffer, + FT_ULong count ) + { + FT_Error error = FT_Err_Ok; + FT_ULong read_bytes; + + + if ( pos >= stream->size ) + { + FT_ERROR(( "FT_Read_Stream_At:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + pos, stream->size )); + + return FT_Err_Invalid_Stream_Operation; + } + + if ( stream->read ) + read_bytes = stream->read( stream, pos, buffer, count ); + else + { + read_bytes = stream->size - pos; + if ( read_bytes > count ) + read_bytes = count; + + MEM_Copy( buffer, stream->base + pos, read_bytes ); + } + + stream->pos = pos + read_bytes; + + if ( read_bytes < count ) + { + FT_ERROR(( "FT_Read_Stream_At:" )); + FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n", + count, read_bytes )); + + error = FT_Err_Invalid_Stream_Operation; + } + + return error; + } + + + BASE_FUNC( FT_Error ) FT_Extract_Frame( FT_Stream stream, + FT_ULong count, + FT_Byte** pbytes ) + { + FT_Error error; + + + error = FT_Access_Frame( stream, count ); + if ( !error ) + { + *pbytes = (FT_Byte*)stream->cursor; + + /* equivalent to FT_Forget_Frame(), with no memory block release */ + stream->cursor = 0; + stream->limit = 0; + } + + return error; + } + + + BASE_FUNC( void ) FT_Release_Frame( FT_Stream stream, + FT_Byte** pbytes ) + { + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + + FREE( *pbytes ); + } + *pbytes = 0; + } + + + BASE_FUNC( FT_Error ) FT_Access_Frame( FT_Stream stream, + FT_ULong count ) + { + FT_Error error = FT_Err_Ok; + FT_ULong read_bytes; + + + /* check for nested frame access */ + FT_Assert( stream && stream->cursor == 0 ); + + if ( stream->read ) + { + /* allocate the frame in memory */ + FT_Memory memory = stream->memory; + + + if ( ALLOC( stream->base, count ) ) + goto Exit; + + /* read it */ + read_bytes = stream->read( stream, stream->pos, + stream->base, count ); + if ( read_bytes < count ) + { + FT_ERROR(( "FT_Access_Frame:" )); + FT_ERROR(( " invalid read; expected %lu bytes, got %lu\n", + count, read_bytes )); + + FREE( stream->base ); + error = FT_Err_Invalid_Stream_Operation; + } + stream->cursor = stream->base; + stream->limit = stream->cursor + count; + stream->pos += read_bytes; + } + else + { + /* check current and new position */ + if ( stream->pos >= stream->size || + stream->pos + count > stream->size ) + { + FT_ERROR(( "FT_Access_Frame:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n", + stream->pos, count, stream->size )); + + error = FT_Err_Invalid_Stream_Operation; + goto Exit; + } + + /* set cursor */ + stream->cursor = stream->base + stream->pos; + stream->limit = stream->cursor + count; + stream->pos += count; + } + + Exit: + return error; + } + + + BASE_FUNC( void ) FT_Forget_Frame( FT_Stream stream ) + { + /* IMPORTANT: The assertion stream->cursor != 0 was removed, given */ + /* that it is possible to access a frame of length 0 in */ + /* some weird fonts (usually, when accessing an array of */ + /* 0 records, like in some strange kern tables). */ + /* */ + /* In this case, the loader code handles the 0-length table */ + /* gracefully; however, stream.cursor is really set to 0 by the */ + /* FT_Access_Frame() call, and this is not an error. */ + /* */ + FT_Assert( stream ); + + if ( stream->read ) + { + FT_Memory memory = stream->memory; + + + FREE( stream->base ); + } + stream->cursor = 0; + stream->limit = 0; + } + + + BASE_FUNC( FT_Char ) FT_Get_Char( FT_Stream stream ) + { + FT_Char result; + + + FT_Assert( stream && stream->cursor ); + + result = 0; + if ( stream->cursor < stream->limit ) + result = *stream->cursor++; + + return result; + } + + + BASE_FUNC( FT_Short ) FT_Get_Short( FT_Stream stream ) + { + FT_Byte* p; + FT_Short result; + + + FT_Assert( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 1 < stream->limit ) + result = NEXT_Short( p ); + stream->cursor = p; + + return result; + } + + + BASE_FUNC( FT_Short ) FT_Get_ShortLE( FT_Stream stream ) + { + FT_Byte* p; + FT_Short result; + + + FT_Assert( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 1 < stream->limit ) + result = NEXT_ShortLE( p ); + stream->cursor = p; + + return result; + } + + + BASE_FUNC( FT_Long ) FT_Get_Offset( FT_Stream stream ) + { + FT_Byte* p; + FT_Long result; + + + FT_Assert( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 2 < stream->limit ) + result = NEXT_Offset( p ); + stream->cursor = p; + return result; + } + + + BASE_FUNC( FT_Long ) FT_Get_Long( FT_Stream stream ) + { + FT_Byte* p; + FT_Long result; + + + FT_Assert( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 3 < stream->limit ) + result = NEXT_Long( p ); + stream->cursor = p; + return result; + } + + + BASE_FUNC( FT_Long ) FT_Get_LongLE( FT_Stream stream ) + { + FT_Byte* p; + FT_Long result; + + + FT_Assert( stream && stream->cursor ); + + result = 0; + p = stream->cursor; + if ( p + 3 < stream->limit ) + result = NEXT_LongLE( p ); + stream->cursor = p; + return result; + } + + + BASE_FUNC( FT_Char ) FT_Read_Char( FT_Stream stream, + FT_Error* error ) + { + FT_Byte result = 0; + + + FT_Assert( stream ); + + *error = FT_Err_Ok; + + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, &result, 1L ) != 1L ) + goto Fail; + } + else + { + if ( stream->pos < stream->size ) + result = stream->base[stream->pos]; + else + goto Fail; + } + stream->pos++; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Read_Char:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + BASE_FUNC( FT_Short ) FT_Read_Short( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[2]; + FT_Byte* p = 0; + FT_Short result = 0; + + + FT_Assert( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 1 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = NEXT_Short( p ); + } + else + goto Fail; + + stream->pos += 2; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Read_Short:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + BASE_FUNC( FT_Short ) FT_Read_ShortLE( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[2]; + FT_Byte* p = 0; + FT_Short result = 0; + + + FT_Assert( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 1 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 2L ) != 2L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = NEXT_ShortLE( p ); + } + else + goto Fail; + + stream->pos += 2; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Read_Short:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + BASE_FUNC( FT_Long ) FT_Read_Offset( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[3]; + FT_Byte* p = 0; + FT_Long result = 0; + + + FT_Assert( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 2 < stream->size ) + { + if ( stream->read ) + { + if (stream->read( stream, stream->pos, reads, 3L ) != 3L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = NEXT_Offset( p ); + } + else + goto Fail; + + stream->pos += 3; + + return result; + + Fail: + *error = FT_Err_Invalid_Stream_Operation; + FT_ERROR(( "FT_Read_Offset:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + + return 0; + } + + + BASE_FUNC( FT_Long ) FT_Read_Long( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[4]; + FT_Byte* p = 0; + FT_Long result = 0; + + + FT_Assert( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 3 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = NEXT_Long( p ); + } + else + goto Fail; + + stream->pos += 4; + + return result; + + Fail: + FT_ERROR(( "FT_Read_Long:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + *error = FT_Err_Invalid_Stream_Operation; + + return 0; + } + + + BASE_FUNC( FT_Long ) FT_Read_LongLE( FT_Stream stream, + FT_Error* error ) + { + FT_Byte reads[4]; + FT_Byte* p = 0; + FT_Long result = 0; + + + FT_Assert( stream ); + + *error = FT_Err_Ok; + + if ( stream->pos + 3 < stream->size ) + { + if ( stream->read ) + { + if ( stream->read( stream, stream->pos, reads, 4L ) != 4L ) + goto Fail; + + p = reads; + } + else + { + p = stream->base + stream->pos; + } + + if ( p ) + result = NEXT_LongLE( p ); + } + else + goto Fail; + + stream->pos += 4; + + return result; + + Fail: + FT_ERROR(( "FT_Read_Long:" )); + FT_ERROR(( " invalid i/o; pos = 0x%lx, size = 0x%lx\n", + stream->pos, stream->size )); + *error = FT_Err_Invalid_Stream_Operation; + + return 0; + } + + + BASE_FUNC( FT_Error ) FT_Read_Fields( FT_Stream stream, + const FT_Frame_Field* fields, + void* structure ) + { + FT_Error error; + FT_Bool frame_accessed = 0; + + + if ( !fields || !stream ) + return FT_Err_Invalid_Argument; + + error = FT_Err_Ok; + do + { + FT_ULong value; + FT_Int sign_shift; + FT_Byte* p; + + + switch ( fields->value ) + { + case ft_frame_start: /* access a new frame */ + error = FT_Access_Frame( stream, fields->offset ); + if ( error ) + goto Exit; + + frame_accessed = 1; + fields++; + continue; /* loop! */ + + case ft_frame_bytes: /* read a byte sequence */ + case ft_frame_skip: /* skip some bytes */ + { + FT_Int len = fields->size; + + + if ( stream->cursor + len > stream->limit ) + { + error = FT_Err_Invalid_Stream_Operation; + goto Exit; + } + + if ( fields->value == ft_frame_bytes ) + { + p = (FT_Byte*)structure + fields->offset; + MEM_Copy( p, stream->cursor, len ); + } + stream->cursor += len; + fields++; + continue; + } + + case ft_frame_byte: + case ft_frame_schar: /* read a single byte */ + value = GET_Byte(); + sign_shift = 24; + break; + + case ft_frame_short_be: + case ft_frame_ushort_be: /* read a 2-byte big-endian short */ + value = GET_UShort(); + sign_shift = 16; + break; + + case ft_frame_short_le: + case ft_frame_ushort_le: /* read a 2-byte little-endian short */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 1 < stream->limit ) + { + value = ( FT_UShort)p[0] | ((FT_UShort)p[1] << 8 ); + stream->cursor += 2; + } + sign_shift = 16; + break; + } + + case ft_frame_long_be: + case ft_frame_ulong_be: /* read a 4-byte big-endian long */ + value = GET_ULong(); + sign_shift = 0; + break; + + case ft_frame_long_le: + case ft_frame_ulong_le: /* read a 4-byte little-endian long */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 3 < stream->limit ) + { + value = (FT_ULong)p[0] | + ( (FT_ULong)p[1] << 8 ) | + ( (FT_ULong)p[2] << 16 ) | + ( (FT_ULong)p[3] << 24 ); + stream->cursor += 4; + } + sign_shift = 0; + break; + } + + case ft_frame_off3_be: + case ft_frame_uoff3_be: /* read a 3-byte big-endian long */ + value = GET_UOffset(); + sign_shift = 8; + break; + + case ft_frame_off3_le: + case ft_frame_uoff3_le: /* read a 3-byte little-endian long */ + { + FT_Byte* p; + + + value = 0; + p = stream->cursor; + + if ( p + 2 < stream->limit ) + { + value = (FT_ULong)p[0] | + ( (FT_ULong)p[1] << 8 ) | + ( (FT_ULong)p[2] << 16 ); + stream->cursor += 3; + } + sign_shift = 8; + break; + } + + default: + /* otherwise, exit the loop */ + goto Exit; + } + + /* now, compute the signed value is necessary */ + if ( fields->value & FT_FRAME_OP_SIGNED ) + value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift ); + + /* finally, store the value in the object */ + + p = (FT_Byte*)structure + fields->offset; + switch ( fields->size ) + { + case 1: + *(FT_Byte*)p = (FT_Byte)value; + break; + + case 2: + *(FT_UShort*)p = (FT_UShort)value; + break; + + case 4: + *(FT_UInt32*)p = (FT_UInt32)value; + break; + + default: /* for 64-bit systems */ + *(FT_ULong*)p = (FT_ULong)value; + } + + /* go to next field */ + fields++; + } + while ( 1 ); + + Exit: + /* close the frame if it was opened by this read */ + if ( frame_accessed ) + FT_Forget_Frame( stream ); + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/ftsystem.c b/subsys/win32k/freetype/src/base/ftsystem.c new file mode 100644 index 0000000..47508af --- /dev/null +++ b/subsys/win32k/freetype/src/base/ftsystem.c @@ -0,0 +1,307 @@ +/***************************************************************************/ +/* */ +/* ftsystem.c */ +/* */ +/* ANSI-specific FreeType low-level system interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file contains the default interface used by FreeType to access */ + /* low-level, i.e. memory management, i/o access as well as thread */ + /* synchronisation. It can be replaced by user-specific routines if */ + /* necessary. */ + /* */ + /*************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* MEMORY MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* It is not necessary to do any error checking for the */ + /* allocation-related functions. This will be done by the higher level */ + /* routines like FT_Alloc() or FT_Realloc(). */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* ft_alloc */ + /* */ + /* */ + /* The memory allocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* size :: The requested size in bytes. */ + /* */ + /* */ + /* block :: The address of newly allocated block. */ + /* */ + static + void* ft_alloc( FT_Memory memory, + long size ) + { + FT_UNUSED( memory ); + +/* return malloc( size ); */ + return ExAllocatePool(NonPagedPool, size); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_realloc */ + /* */ + /* */ + /* The memory reallocation function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* cur_size :: The current size of the allocated memory block. */ + /* */ + /* new_size :: The newly requested size in bytes. */ + /* */ + /* block :: The current address of the block in memory. */ + /* */ + /* */ + /* The address of the reallocated memory block. */ + /* */ + static + void* ft_realloc( FT_Memory memory, + long cur_size, + long new_size, + void* block ) + { + FT_UNUSED( memory ); + FT_UNUSED( cur_size ); + +/* return realloc( block, new_size ); */ + ExFreePool(block); + return ExAllocatePool(NonPagedPool, new_size); + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_free */ + /* */ + /* */ + /* The memory release function. */ + /* */ + /* */ + /* memory :: A pointer to the memory object. */ + /* */ + /* block :: The address of block in memory to be freed. */ + /* */ + static + void ft_free( FT_Memory memory, + void* block ) + { + FT_UNUSED( memory ); + +/* free( block ); */ + ExFreePool(block); + } + + + /*************************************************************************/ + /* */ + /* RESOURCE MANAGEMENT INTERFACE */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_io + + /* We use the macro STREAM_FILE for convenience to extract the */ + /* system-specific stream handle from a given FreeType stream object */ +#define STREAM_FILE( stream ) ( (FILE*)stream->descriptor.pointer ) + + + /*************************************************************************/ + /* */ + /* */ + /* ft_close_stream */ + /* */ + /* */ + /* The function to close a stream. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + static + void ft_close_stream( FT_Stream stream ) + { + DbgPrint("ftsystem.c: UNIMPLEMENTED CALL\n"); + +/* fclose( STREAM_FILE( stream ) ); */ + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* ft_io_stream */ + /* */ + /* */ + /* The function to open a stream. */ + /* */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + /* offset :: The position in the data stream to start reading. */ + /* */ + /* buffer :: The address of buffer to store the read data. */ + /* */ + /* count :: The number of bytes to read from the stream. */ + /* */ + /* */ + /* The number of bytes actually read. */ + /* */ + static + unsigned long ft_io_stream( FT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count ) + { + FILE* file; + + DbgPrint("ftsystem.c: UNIMPLEMENTED CALL\n"); + file = STREAM_FILE( stream ); + +/* fseek( file, offset, SEEK_SET ); */ +/* return (unsigned long)fread( buffer, 1, count, file ); */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Stream */ + /* */ + /* */ + /* Creates a new stream object. */ + /* */ + /* */ + /* filepathname :: The name of the stream (usually a file) to be */ + /* opened. */ + /* */ + /* stream :: A pointer to the stream object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) FT_New_Stream( const char* filepathname, + FT_Stream stream ) + { +/* FILE* file; FIXME */ + + DbgPrint("ftsystem.c: UNIMPLEMENTED CALL\n"); + +/* if ( !stream ) + return FT_Err_Invalid_Stream_Handle; + + file = fopen( filepathname, "rb" ); + if ( !file ) + { + FT_ERROR(( "FT_New_Stream:" )); + FT_ERROR(( " could not open `%s'\n", filepathname )); + + return FT_Err_Cannot_Open_Resource; + } + + fseek( file, 0, SEEK_END ); + stream->size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + stream->descriptor.pointer = file; + stream->pathname.pointer = (char*)filepathname; + stream->pos = 0; + + stream->read = ft_io_stream; + stream->close = ft_close_stream; + + FT_TRACE1(( "FT_New_Stream:" )); + FT_TRACE1(( " opened `%s' (%d bytes) successfully\n", + filepathname, stream->size )); */ + + return FT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* FT_New_Memory */ + /* */ + /* */ + /* Creates a new memory object. */ + /* */ + /* */ + /* A pointer to the new memory object. 0 in case of error. */ + /* */ + FT_EXPORT_FUNC( FT_Memory ) FT_New_Memory( void ) + { + FT_Memory memory; + +/* memory = (FT_Memory)malloc( sizeof ( *memory ) ); */ + + memory = ExAllocatePool(NonPagedPool, sizeof(*memory)); + if ( memory ) + { + memory->user = 0; + memory->alloc = ft_alloc; + memory->realloc = ft_realloc; + memory->free = ft_free; + } + + return memory; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/base/rules.mk b/subsys/win32k/freetype/src/base/rules.mk new file mode 100644 index 0000000..1763a09 --- /dev/null +++ b/subsys/win32k/freetype/src/base/rules.mk @@ -0,0 +1,83 @@ +# +# FreeType 2 base layer configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# It sets the following variables which are used by the master Makefile +# after the call: +# +# BASE_OBJ_S: The single-object base layer. +# BASE_OBJ_M: A list of all objects for a multiple-objects build. +# BASE_EXT_OBJ: A list of base layer extensions, i.e., components found +# in `freetype/src/base' which are not compiled within the +# base layer proper. +# +# BASE_H is defined in freetype.mk to simplify the dependency rules. + + +BASE_COMPILE := $(FT_COMPILE) $I$(SRC_)base + + +# Base layer sources +# +# ftsystem, ftinit, and ftdebug are handled by freetype.mk +# +BASE_SRC := $(BASE_)ftcalc.c \ + $(BASE_)ftextend.c \ + $(BASE_)ftlist.c \ + $(BASE_)ftobjs.c \ + $(BASE_)ftstream.c \ + $(BASE_)ftoutln.c + +# Base layer `extensions' sources +# +# An extension is added to the library file (.a or .lib) as a separate +# object. It will then be linked to the final executable only if one of its +# symbols is used by the application. +# +BASE_EXT_SRC := $(BASE_)ftglyph.c \ + $(BASE_)ftmm.c + +# Default extensions objects +# +BASE_EXT_OBJ := $(BASE_EXT_SRC:$(BASE_)%.c=$(OBJ_)%.$O) + + +# Base layer object(s) +# +# BASE_OBJ_M is used during `multi' builds (each base source file compiles +# to a single object file). +# +# BASE_OBJ_S is used during `single' builds (the whole base layer is +# compiled as a single object file using ftbase.c). +# +BASE_OBJ_M := $(BASE_SRC:$(BASE_)%.c=$(OBJ_)%.$O) +BASE_OBJ_S := $(OBJ_)ftbase.$O + +# Base layer root source file for single build +# +BASE_SRC_S := $(BASE_)ftbase.c + + +# Base layer - single object build +# +$(BASE_OBJ_S): $(BASE_SRC_S) $(BASE_SRC) $(FREETYPE_H) + $(BASE_COMPILE) $T$@ $(BASE_SRC_S) + + +# Multiple objects build + extensions +# +$(OBJ_)%.$O: $(BASE_)%.c $(FREETYPE_H) + $(BASE_COMPILE) $T$@ $< + +# EOF diff --git a/subsys/win32k/freetype/src/cff/.cvsignore b/subsys/win32k/freetype/src/cff/.cvsignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/subsys/win32k/freetype/src/cff/cff.c b/subsys/win32k/freetype/src/cff/cff.c new file mode 100644 index 0000000..a962839 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/cff.c @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#ifdef FT_FLAT_COMPILE + +#include "t2driver.c" /* driver interface */ +#include "t2parse.c" /* token parser */ +#include "t2load.c" /* tables loader */ +#include "t2objs.c" /* object management */ +#include "t2gload.c" /* glyph loader */ + +#else + +#include /* driver interface */ +#include /* token parser */ +#include /* tables loader */ +#include /* object management */ +#include /* glyph loader */ + +#endif + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/module.mk b/subsys/win32k/freetype/src/cff/module.mk new file mode 100644 index 0000000..9bc5c8f --- /dev/null +++ b/subsys/win32k/freetype/src/cff/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_cff_driver + +add_cff_driver: + $(OPEN_DRIVER)cff_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)cff $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/cff/rules.mk b/subsys/win32k/freetype/src/cff/rules.mk new file mode 100644 index 0000000..ba87af5 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 OpenType/CFF driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# OpenType driver directory +# +T2_DIR := $(SRC_)cff +T2_DIR_ := $(T2_DIR)$(SEP) + + +T2_COMPILE := $(FT_COMPILE) + + +# T2 driver sources (i.e., C files) +# +T2_DRV_SRC := $(T2_DIR_)t2objs.c \ + $(T2_DIR_)t2load.c \ + $(T2_DIR_)t2gload.c \ + $(T2_DIR_)t2parse.c \ + $(T2_DIR_)t2driver.c + +# T2 driver headers +# +T2_DRV_H := $(T2_DRV_SRC:%.c=%.h) \ + $(T2_DIR_)t2tokens.h + + +# T2 driver object(s) +# +# T2_DRV_OBJ_M is used during `multi' builds +# T2_DRV_OBJ_S is used during `single' builds +# +T2_DRV_OBJ_M := $(T2_DRV_SRC:$(T2_DIR_)%.c=$(OBJ_)%.$O) +T2_DRV_OBJ_S := $(OBJ_)cff.$O + +# T2 driver source file for single build +# +T2_DRV_SRC_S := $(T2_DIR_)cff.c + + +# T2 driver - single object +# +$(T2_DRV_OBJ_S): $(T2_DRV_SRC_S) $(T2_DRV_SRC) $(FREETYPE_H) $(T2_DRV_H) + $(T2_COMPILE) $T$@ $(T2_DRV_SRC_S) + + +# T2 driver - multiple objects +# +$(OBJ_)%.$O: $(T2_DIR_)%.c $(FREETYPE_H) $(T2_DRV_H) + $(T2_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T2_DRV_OBJ_S) +DRV_OBJS_M += $(T2_DRV_OBJ_M) + +# EOF diff --git a/subsys/win32k/freetype/src/cff/t2driver.c b/subsys/win32k/freetype/src/cff/t2driver.c new file mode 100644 index 0000000..ce73529 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2driver.c @@ -0,0 +1,377 @@ +/***************************************************************************/ +/* */ +/* t2driver.c */ +/* */ +/* OpenType font driver implementation (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2driver.h" +#include "t2gload.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t2driver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings, are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static + FT_Error Get_Kerning( TT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + TT_Kern_0_Pair* pair; + + + if ( !face ) + return T2_Err_Invalid_Face_Handle; + + kerning->x = 0; + kerning->y = 0; + + if ( face->kern_pairs ) + { + /* there are some kerning pairs in this font file! */ + FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); + FT_Long left, right; + + + left = 0; + right = face->num_kern_pairs - 1; + + while ( left <= right ) + { + FT_Int middle = left + ( ( right - left ) >> 1 ); + FT_ULong cur_pair; + + + pair = face->kern_pairs + middle; + cur_pair = PAIR_TAG( pair->left, pair->right ); + + if ( cur_pair == search_tag ) + goto Found; + + if ( cur_pair < search_tag ) + left = middle + 1; + else + right = middle - 1; + } + } + + Exit: + return T2_Err_Ok; + + Found: + kerning->x = pair->value; + goto Exit; + } + + +#undef PAIR_TAG + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Glyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* slot :: A handle to the target slot object where the glyph */ + /* will be loaded. */ + /* */ + /* size :: A handle to the source face size at which the glyph */ + /* must be scaled, loaded, etc. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FTLOAD_??? constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_Glyph( T2_GlyphSlot slot, + T2_Size size, + FT_UShort glyph_index, + FT_UInt load_flags ) + { + FT_Error error; + + + if ( !slot ) + return T2_Err_Invalid_Glyph_Handle; + + /* check whether we want a scaled outline or bitmap */ + if ( !size ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + if ( load_flags & FT_LOAD_NO_SCALE ) + size = NULL; + + /* reset the size object if necessary */ + if ( size ) + { + /* these two object must have the same parent */ + if ( size->face != slot->root.face ) + return T2_Err_Invalid_Face_Handle; + } + + /* now load the glyph outline if necessary */ + error = T2_Load_Glyph( slot, size, glyph_index, load_flags ); + + /* force drop-out mode to 2 - irrelevant now */ + /* slot->outline.dropout_mode = 2; */ + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** C H A R A C T E R M A P P I N G S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt t2_get_char_index( TT_CharMap charmap, + FT_Long charcode ) + { + FT_Error error; + T2_Face face; + TT_CMapTable* cmap; + + + cmap = &charmap->cmap; + face = (T2_Face)charmap->root.face; + + /* Load table if needed */ + if ( !cmap->loaded ) + { + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + error = sfnt->load_charmap( face, cmap, face->root.stream ); + if ( error ) + return 0; + + cmap->loaded = TRUE; + } + + return ( cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R I N T E R F A C E ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Module_Interface t2_get_interface( T2_Driver driver, + const char* interface ) + { + FT_Module sfnt; + + + /* we simply pass our request to the `sfnt' module */ + sfnt = FT_Get_Module( driver->root.root.library, "sfnt" ); + + return sfnt ? sfnt->clazz->get_interface( sfnt, interface ) : 0; + } + + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + const FT_Driver_Class cff_driver_class = + { + /* begin with the FT_Module_Class fields */ + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( T2_DriverRec ), + "cff", + 0x10000L, + 0x20000L, + + 0, /* module-specific interface */ + + (FT_Module_Constructor)T2_Init_Driver, + (FT_Module_Destructor) T2_Done_Driver, + (FT_Module_Requester) t2_get_interface, + }, + + /* now the specific driver fields */ + sizeof( TT_FaceRec ), + sizeof( FT_SizeRec ), + sizeof( T2_GlyphSlotRec ), + + (FTDriver_initFace) T2_Init_Face, + (FTDriver_doneFace) T2_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes)0, + + (FTDriver_loadGlyph) Load_Glyph, + (FTDriver_getCharIndex) t2_get_char_index, + + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* This function is used when compiling the TrueType driver as a */ + /* shared library (`.DLL' or `.so'). It will be used by the */ + /* high-level library of FreeType to retrieve the address of the */ + /* driver's generic interface. */ + /* */ + /* It shouldn't be implemented in a static build, as each driver must */ + /* have the same function as an exported entry point. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void ) + { + return &cff_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2driver.h b/subsys/win32k/freetype/src/cff/t2driver.h new file mode 100644 index 0000000..e0b0afd --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2driver.h @@ -0,0 +1,30 @@ +/***************************************************************************/ +/* */ +/* t2driver.h */ +/* */ +/* High-level OpenType driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2DRIVER_H +#define T2DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) cff_driver_class; + + +#endif /* T2DRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2gload.c b/subsys/win32k/freetype/src/cff/t2gload.c new file mode 100644 index 0000000..4a0ddc0 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2gload.c @@ -0,0 +1,2045 @@ +/***************************************************************************/ +/* */ +/* t2gload.c */ +/* */ +/* OpenType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2load.h" +#include "t2gload.h" + +#else + +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t2gload + + + typedef enum T2_Operator_ + { + t2_op_unknown = 0, + + t2_op_rmoveto, + t2_op_hmoveto, + t2_op_vmoveto, + + t2_op_rlineto, + t2_op_hlineto, + t2_op_vlineto, + + t2_op_rrcurveto, + t2_op_hhcurveto, + t2_op_hvcurveto, + t2_op_rcurveline, + t2_op_rlinecurve, + t2_op_vhcurveto, + t2_op_vvcurveto, + + t2_op_flex, + t2_op_hflex, + t2_op_hflex1, + t2_op_flex1, + + t2_op_endchar, + + t2_op_hstem, + t2_op_vstem, + t2_op_hstemhm, + t2_op_vstemhm, + + t2_op_hintmask, + t2_op_cntrmask, + + t2_op_abs, + t2_op_add, + t2_op_sub, + t2_op_div, + t2_op_neg, + t2_op_random, + t2_op_mul, + t2_op_sqrt, + + t2_op_blend, + + t2_op_drop, + t2_op_exch, + t2_op_index, + t2_op_roll, + t2_op_dup, + + t2_op_put, + t2_op_get, + t2_op_store, + t2_op_load, + + t2_op_and, + t2_op_or, + t2_op_not, + t2_op_eq, + t2_op_ifelse, + + t2_op_callsubr, + t2_op_callgsubr, + t2_op_return, + + /* do not remove */ + t2_op_max + + } T2_Operator; + + +#define T2_COUNT_CHECK_WIDTH 0x80 +#define T2_COUNT_EXACT 0x40 +#define T2_COUNT_CLEAR_STACK 0x20 + + + static const FT_Byte t2_argument_counts[] = + { + 0, /* unknown */ + + 2 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, /* rmoveto */ + 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, + 1 | T2_COUNT_CHECK_WIDTH | T2_COUNT_EXACT, + + 0 | T2_COUNT_CLEAR_STACK, /* rlineto */ + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + + 0 | T2_COUNT_CLEAR_STACK, /* rrcurveto */ + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + 0 | T2_COUNT_CLEAR_STACK, + + 13, /* flex */ + 7, + 9, + 11, + + 0, /* endchar */ + + 2 | T2_COUNT_CHECK_WIDTH, /* hstem */ + 2 | T2_COUNT_CHECK_WIDTH, + 2 | T2_COUNT_CHECK_WIDTH, + 2 | T2_COUNT_CHECK_WIDTH, + + 0, /* hintmask */ + 0, /* cntrmask */ + + 1, /* abs */ + 2, + 2, + 2, + 1, + 0, + 2, + 1, + + 1, /* blend */ + + 1, /* drop */ + 2, + 1, + 2, + 1, + + 2, /* put */ + 1, + 4, + 3, + + 2, /* and */ + 2, + 1, + 2, + 4, + + 1, /* callsubr */ + 1, + 0 + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + static + void T2_Init_Builder( T2_Builder* builder, + TT_Face face, + T2_Size size, + T2_GlyphSlot glyph ) + { + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader* loader = glyph->root.loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->metrics.x_scale; + builder->scale_y = size->metrics.y_scale; + } + + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Builder */ + /* */ + /* */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + static + void T2_Done_Builder( T2_Builder* builder ) + { + T2_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t2_compute_bias */ + /* */ + /* */ + /* Computes the bias value in dependence of the number of glyph */ + /* subroutines. */ + /* */ + /* */ + /* num_subrs :: The number of glyph subroutines. */ + /* */ + /* */ + /* The bias value. */ + static + FT_Int t2_compute_bias( FT_UInt num_subrs ) + { + FT_Int result; + + + if ( num_subrs < 1240 ) + result = 107; + else if ( num_subrs < 33900 ) + result = 1131; + else + result = 32768; + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* slot :: The current glyph object. */ + /* */ + LOCAL_FUNC + void T2_Init_Decoder( T2_Decoder* decoder, + TT_Face face, + T2_Size size, + T2_GlyphSlot slot ) + { + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + /* clear everything */ + MEM_Set( decoder, 0, sizeof ( *decoder ) ); + + /* initialize builder */ + T2_Init_Builder( &decoder->builder, face, size, slot ); + + /* initialize Type2 decoder */ + decoder->num_globals = cff->num_global_subrs; + decoder->globals = cff->global_subrs; + decoder->globals_bias = t2_compute_bias( decoder->num_globals ); + } + + + /* this function is used to select the locals subrs array */ + LOCAL_DEF + void T2_Prepare_Decoder( T2_Decoder* decoder, + FT_UInt glyph_index ) + { + CFF_Font* cff = (CFF_Font*)decoder->builder.face->extra.data; + CFF_SubFont* sub = &cff->top_font; + + + /* manage CID fonts */ + if ( cff->num_subfonts >= 1 ) + { + FT_Byte fd_index = CFF_Get_FD( &cff->fd_select, glyph_index ); + + + sub = cff->subfonts[fd_index]; + } + + decoder->num_locals = sub->num_local_subrs; + decoder->locals = sub->local_subrs; + decoder->locals_bias = t2_compute_bias( decoder->num_locals ); + + decoder->glyph_width = sub->private_dict.default_width; + decoder->nominal_width = sub->private_dict.nominal_width; + } + + + /* check that there is enough room for `count' more points */ + static + FT_Error check_points( T2_Builder* builder, + FT_Int count ) + { + return FT_GlyphLoader_Check_Points( builder->loader, count, 0 ); + } + + + /* add a new point, do not check space */ + static + void add_point( T2_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + + + point->x = x >> 16; + point->y = y >> 16; + *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic; + + builder->last = *point; + } + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + static + FT_Error add_point1( T2_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = check_points( builder, 1 ); + if ( !error ) + add_point( builder, x, y, 1 ); + + return error; + } + + + /* check room for a new contour, then add it */ + static + FT_Error add_contour( T2_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return T2_Err_Ok; + } + + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + + outline->n_contours++; + } + + return error; + } + + + /* if a path was begun, add its first on-curve point */ + static + FT_Error start_point( T2_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error = 0; + + + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + builder->path_begun = 1; + error = add_contour( builder ); + if ( !error ) + error = add_point1( builder, x, y ); + } + return error; + } + + + /* close the current contour */ + static + void close_contour( T2_Builder* builder ) + { + FT_Outline* outline = builder->current; + + /* XXXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points - 1; + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 2 charstrings program. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T2_Parse_CharStrings( T2_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ) + { + FT_Error error; + T2_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + T2_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + FT_Fixed seed; + FT_Fixed* stack; + + + /* set default width */ + decoder->num_hints = 0; + decoder->read_width = 1; + + /* compute random seed from stack address of parameter */ + seed = (FT_Fixed)(char*)&seed ^ + (FT_Fixed)(char*)&decoder ^ + (FT_Fixed)(char*)&charstring_base; + seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF; + if ( seed == 0 ) + seed = 0x7384; + + /* initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + stack = decoder->top; + + builder->path_begun = 0; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = T2_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + T2_Operator op; + FT_Byte v; + FT_Byte count; + + + /********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + v = *ip++; + if ( v >= 32 || v == 28 ) + { + FT_Int shift = 16; + FT_Int32 val; + + + /* this is an operand, push it on the stack */ + if ( v == 28 ) + { + if ( ip + 1 >= limit ) + goto Syntax_Error; + val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] ); + ip += 2; + } + else if ( v < 247 ) + val = (FT_Long)v - 139; + else if ( v < 251 ) + { + if ( ip >= limit ) + goto Syntax_Error; + val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108; + } + else if ( v < 255 ) + { + if ( ip >= limit ) + goto Syntax_Error; + val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108; + } + else + { + if ( ip + 3 >= limit ) + goto Syntax_Error; + val = ( (FT_Int32)ip[0] << 24 ) | + ( (FT_Int32)ip[1] << 16 ) | + ( (FT_Int32)ip[2] << 8 ) | + ip[3]; + ip += 4; + shift = 0; + } + if ( decoder->top - stack >= T2_MAX_OPERANDS ) + goto Stack_Overflow; + + val <<= shift; + *decoder->top++ = val; + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( !( val & 0xFFFF ) ) + FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) )); + else + FT_TRACE4(( " %.2f", val/65536.0 )); +#endif + + } + else + { + FT_Fixed* args = decoder->top; + FT_Int num_args = args - decoder->stack; + FT_Int req_args; + + + /* find operator */ + op = t2_op_unknown; + + switch ( v ) + { + case 1: + op = t2_op_hstem; + break; + case 3: + op = t2_op_vstem; + break; + case 4: + op = t2_op_vmoveto; + break; + case 5: + op = t2_op_rlineto; + break; + case 6: + op = t2_op_hlineto; + break; + case 7: + op = t2_op_vlineto; + break; + case 8: + op = t2_op_rrcurveto; + break; + case 10: + op = t2_op_callsubr; + break; + case 11: + op = t2_op_return; + break; + case 12: + { + if ( ip >= limit ) + goto Syntax_Error; + v = *ip++; + + switch ( v ) + { + case 3: + op = t2_op_and; + break; + case 4: + op = t2_op_or; + break; + case 5: + op = t2_op_not; + break; + case 8: + op = t2_op_store; + break; + case 9: + op = t2_op_abs; + break; + case 10: + op = t2_op_add; + break; + case 11: + op = t2_op_sub; + break; + case 12: + op = t2_op_div; + break; + case 13: + op = t2_op_load; + break; + case 14: + op = t2_op_neg; + break; + case 15: + op = t2_op_eq; + break; + case 18: + op = t2_op_drop; + break; + case 20: + op = t2_op_put; + break; + case 21: + op = t2_op_get; + break; + case 22: + op = t2_op_ifelse; + break; + case 23: + op = t2_op_random; + break; + case 24: + op = t2_op_mul; + break; + case 26: + op = t2_op_sqrt; + break; + case 27: + op = t2_op_dup; + break; + case 28: + op = t2_op_exch; + break; + case 29: + op = t2_op_index; + break; + case 30: + op = t2_op_roll; + break; + case 34: + op = t2_op_hflex; + break; + case 35: + op = t2_op_flex; + break; + case 36: + op = t2_op_hflex1; + break; + case 37: + op = t2_op_flex1; + break; + default: + /* decrement ip for syntax error message */ + ip--; + } + } + break; + case 14: + op = t2_op_endchar; + break; + case 16: + op = t2_op_blend; + break; + case 18: + op = t2_op_hstemhm; + break; + case 19: + op = t2_op_hintmask; + break; + case 20: + op = t2_op_cntrmask; + break; + case 21: + op = t2_op_rmoveto; + break; + case 22: + op = t2_op_hmoveto; + break; + case 23: + op = t2_op_vstemhm; + break; + case 24: + op = t2_op_rcurveline; + break; + case 25: + op = t2_op_rlinecurve; + break; + case 26: + op = t2_op_vvcurveto; + break; + case 27: + op = t2_op_hhcurveto; + break; + case 29: + op = t2_op_callgsubr; + break; + case 30: + op = t2_op_vhcurveto; + break; + case 31: + op = t2_op_hvcurveto; + break; + default: + ; + } + if ( op == t2_op_unknown ) + goto Syntax_Error; + + /* check arguments */ + req_args = count = t2_argument_counts[op]; + if ( req_args & T2_COUNT_CHECK_WIDTH ) + { + args = stack; + if ( num_args & 1 && decoder->read_width ) + { + decoder->glyph_width = decoder->nominal_width + + ( stack[0] >> 16 ); + num_args--; + args++; + } + decoder->read_width = 0; + req_args = 0; + } + + req_args &= 15; + if ( num_args < req_args ) + goto Stack_Underflow; + args -= req_args; + num_args -= req_args; + + switch ( op ) + { + case t2_op_hstem: + case t2_op_vstem: + case t2_op_hstemhm: + case t2_op_vstemhm: + /* if the number of arguments is not even, the first one */ + /* is simply the glyph width, encoded as the difference */ + /* to nominalWidthX */ + FT_TRACE4(( op == t2_op_hstem ? " hstem" : + op == t2_op_vstem ? " vstem" : + op == t2_op_hstemhm ? " hstemhm" : + " vstemhm" )); + decoder->num_hints += num_args / 2; + args = stack; + break; + + case t2_op_hintmask: + case t2_op_cntrmask: + FT_TRACE4(( op == t2_op_hintmask ? " hintmask" + : " cntrmask" )); + + decoder->num_hints += num_args / 2; + ip += ( decoder->num_hints + 7 ) >> 3; + if ( ip >= limit ) + goto Syntax_Error; + args = stack; + break; + + case t2_op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + y += args[1]; + args = stack; + break; + + case t2_op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + y += args[0]; + args = stack; + break; + + case t2_op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + close_contour( builder ); + builder->path_begun = 0; + x += args[0]; + args = stack; + break; + + case t2_op_rlineto: + FT_TRACE4(( " rlineto" )); + + if ( start_point ( builder, x, y ) || + check_points( builder, num_args / 2 ) ) + goto Memory_Error; + + if ( num_args < 2 || num_args & 1 ) + goto Stack_Underflow; + + args = stack; + while ( args < decoder->top ) + { + x += args[0]; + y += args[1]; + add_point( builder, x, y, 1 ); + args += 2; + } + args = stack; + break; + + case t2_op_hlineto: + case t2_op_vlineto: + { + FT_Int phase = ( op == t2_op_hlineto ); + + + FT_TRACE4(( op == t2_op_hlineto ? " hlineto" + : " vlineto" )); + + if ( start_point ( builder, x, y ) || + check_points( builder, num_args ) ) + goto Memory_Error; + + args = stack; + while (args < decoder->top ) + { + if ( phase ) + x += args[0]; + else + y += args[0]; + + if ( add_point1( builder, x, y ) ) + goto Memory_Error; + + args++; + phase ^= 1; + } + args = stack; + } + break; + + case t2_op_rrcurveto: + FT_TRACE4(( " rrcurveto" )); + + /* check number of arguments; must be a multiple of 6 */ + if ( num_args % 6 != 0 ) + goto Stack_Underflow; + + if ( start_point ( builder, x, y ) || + check_points( builder, num_args / 2 ) ) + goto Memory_Error; + + args = stack; + while ( args < decoder->top ) + { + x += args[0]; + y += args[1]; + add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + add_point( builder, x, y, 1 ); + args += 6; + } + args = stack; + break; + + case t2_op_vvcurveto: + FT_TRACE4(( " vvcurveto" )); + + if ( start_point ( builder, x, y ) ) + goto Memory_Error; + + args = stack; + if ( num_args & 1 ) + { + x += args[0]; + args++; + num_args--; + } + + if ( num_args % 4 != 0 ) + goto Stack_Underflow; + + if ( check_points( builder, 3 * ( num_args / 4 ) ) ) + goto Memory_Error; + + while ( args < decoder->top ) + { + y += args[0]; + add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + add_point( builder, x, y, 0 ); + y += args[3]; + add_point( builder, x, y, 1 ); + args += 4; + } + args = stack; + break; + + case t2_op_hhcurveto: + FT_TRACE4(( " hhcurveto" )); + + if ( start_point ( builder, x, y ) ) + goto Memory_Error; + + args = stack; + if ( num_args & 1 ) + { + y += args[0]; + args++; + num_args--; + } + + if ( num_args % 4 != 0 ) + goto Stack_Underflow; + + if ( check_points( builder, 3 * ( num_args / 4 ) ) ) + goto Memory_Error; + + while ( args < decoder->top ) + { + x += args[0]; + add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + add_point( builder, x, y, 0 ); + x += args[3]; + add_point( builder, x, y, 1 ); + args += 4; + } + args = stack; + break; + + case t2_op_vhcurveto: + case t2_op_hvcurveto: + { + FT_Int phase; + + + FT_TRACE4(( op == t2_op_vhcurveto ? " vhcurveto" + : " hvcurveto" )); + + if ( start_point ( builder, x, y ) ) + goto Memory_Error; + + args = stack; + if (num_args < 4 || ( num_args % 4 ) > 1 ) + goto Stack_Underflow; + + if ( check_points( builder, ( num_args / 4 ) * 3 ) ) + goto Stack_Underflow; + + phase = ( op == t2_op_hvcurveto ); + + while ( num_args >= 4 ) + { + num_args -= 4; + if ( phase ) + { + x += args[0]; + add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + add_point( builder, x, y, 0 ); + y += args[3]; + if ( num_args == 1 ) + x += args[4]; + add_point( builder, x, y, 1 ); + } + else + { + y += args[0]; + add_point( builder, x, y, 0 ); + x += args[1]; + y += args[2]; + add_point( builder, x, y, 0 ); + x += args[3]; + if ( num_args == 1 ) + y += args[4]; + add_point( builder, x, y, 1 ); + } + args += 4; + phase ^= 1; + } + args = stack; + } + break; + + case t2_op_rlinecurve: + { + FT_Int num_lines = ( num_args - 6 ) / 2; + + + FT_TRACE4(( " rlinecurve" )); + + if ( num_args < 8 || ( num_args - 6 ) & 1 ) + goto Stack_Underflow; + + if ( start_point( builder, x, y ) || + check_points( builder, num_lines + 3 ) ) + goto Memory_Error; + + args = stack; + + /* first, add the line segments */ + while ( num_lines > 0 ) + { + x += args[0]; + y += args[1]; + add_point( builder, x, y, 1 ); + args += 2; + num_lines--; + } + + /* then the curve */ + x += args[0]; + y += args[1]; + add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + add_point( builder, x, y, 1 ); + args = stack; + } + break; + + case t2_op_rcurveline: + { + FT_Int num_curves = ( num_args - 2 ) / 6; + + + FT_TRACE4(( " rcurveline" )); + + if ( num_args < 8 || ( num_args - 2 ) % 6 ) + goto Stack_Underflow; + + if ( start_point ( builder, x, y ) || + check_points( builder, num_curves*3 + 2 ) ) + goto Memory_Error; + + args = stack; + + /* first, add the curves */ + while ( num_curves > 0 ) + { + x += args[0]; + y += args[1]; + add_point( builder, x, y, 0 ); + x += args[2]; + y += args[3]; + add_point( builder, x, y, 0 ); + x += args[4]; + y += args[5]; + add_point( builder, x, y, 1 ); + args += 6; + num_curves--; + } + + /* then the final line */ + x += args[0]; + y += args[1]; + add_point( builder, x, y, 1 ); + args = stack; + } + break; + + case t2_op_hflex1: + { + FT_Pos start_y; + + + FT_TRACE4(( " hflex1" )); + + args = stack; + + /* adding five more points; 4 control points, 1 on-curve point */ + /* make sure we have enough space for the start point if it */ + /* needs to be added.. */ + if ( start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Memory_Error; + + /* Record the starting point's y postion for later use */ + start_y = y; + + /* first control point */ + x += args[0]; + y += args[1]; + add_point( builder, x, y, 0 ); + + /* second control point */ + x += args[2]; + y += args[3]; + add_point( builder, x, y, 0 ); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x += args[4]; + add_point( builder, x, y, 1 ); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x += args[5]; + add_point( builder, x, y, 0 ); + + /* fourth control point */ + x += args[6]; + y += args[7]; + add_point( builder, x, y, 0 ); + + /* ending point, with y-value the same as the start */ + x += args[8]; + y = start_y; + add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case t2_op_hflex: + { + FT_Pos start_y; + + + FT_TRACE4(( " hflex" )); + + args = stack; + + /* adding six more points; 4 control points, 2 on-curve points */ + if ( start_point( builder, x, y ) || + check_points ( builder, 6 ) ) + goto Memory_Error; + + /* record the starting point's y-position for later use */ + start_y = y; + + /* first control point */ + x += args[0]; + add_point( builder, x, y, 0 ); + + /* second control point */ + x += args[1]; + y += args[2]; + add_point( builder, x, y, 0 ); + + /* join point; on curve, with y-value the same as the last */ + /* control point's y-value */ + x += args[3]; + add_point( builder, x, y, 1 ); + + /* third control point, with y-value the same as the join */ + /* point's y-value */ + x += args[4]; + add_point( builder, x, y, 0 ); + + /* fourth control point */ + x += args[5]; + y = start_y; + add_point( builder, x, y, 0 ); + + /* ending point, with y-value the same as the start point's */ + /* y-value -- we don't add this point, though */ + x += args[6]; + add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case t2_op_flex1: + { + FT_Pos start_x, start_y; /* record start x, y values for alter */ + /* use */ + FT_Int dx = 0, dy = 0; /* used in horizontal/vertical */ + /* algorithm below */ + FT_Int horizontal, count; + + + FT_TRACE4(( " flex1" )); + + /* adding six more points; 4 control points, 2 on-curve points */ + if ( start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Memory_Error; + + /* record the starting point's x, y postion for later use */ + start_x = x; + start_y = y; + + /* XXX: figure out whether this is supposed to be a horizontal */ + /* or vertical flex; the Type 2 specification is vague... */ + + args = stack; + + /* grab up to the last argument */ + for ( count = 5; count > 0; count-- ) + { + dx += args[0]; + dy += args[1]; + args += 2; + } + + /* rewind */ + args = stack; + + if ( dx < 0 ) dx = -dx; + if ( dy < 0 ) dy = -dy; + + /* strange test, but here it is... */ + horizontal = ( dx > dy ); + + for ( count = 5; count > 0; count-- ) + { + x += args[0]; + y += args[1]; + add_point( builder, x, y, (FT_Bool)( count == 3 ) ); + args += 2; + } + + /* is last operand an x- or y-delta? */ + if ( horizontal ) + { + x += args[0]; + y = start_y; + } + else + { + x = start_x; + y += args[0]; + } + + add_point( builder, x, y, 1 ); + + args = stack; + break; + } + + case t2_op_flex: + { + FT_UInt count; + + + FT_TRACE4(( " flex" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Memory_Error; + + args = stack; + for ( count = 6; count > 0; count-- ) + { + x += args[0]; + y += args[1]; + add_point( builder, x, y, + (FT_Bool)( count == 3 || count == 0 ) ); + args += 2; + } + + args = stack; + } + break; + + case t2_op_endchar: + FT_TRACE4(( " endchar" )); + + close_contour( builder ); + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + + /* return now! */ + FT_TRACE4(( "\n\n" )); + return T2_Err_Ok; + + case t2_op_abs: + FT_TRACE4(( " abs" )); + + if ( args[0] < 0 ) + args[0] = -args[0]; + args++; + break; + + case t2_op_add: + FT_TRACE4(( " add" )); + + args[0] += args[1]; + args++; + break; + + case t2_op_sub: + FT_TRACE4(( " sub" )); + + args[0] -= args[1]; + args++; + break; + + case t2_op_div: + FT_TRACE4(( " div" )); + + args[0] = FT_DivFix( args[0], args[1] ); + args++; + break; + + case t2_op_neg: + FT_TRACE4(( " neg" )); + + args[0] = -args[0]; + args++; + break; + + case t2_op_random: + { + FT_Fixed rand; + + + FT_TRACE4(( " rand" )); + + rand = seed; + if ( rand >= 0x8000 ) + rand++; + + args[0] = rand; + seed = FT_MulFix( seed, 0x10000L - seed ); + if ( seed == 0 ) + seed += 0x2873; + args++; + } + break; + + case t2_op_mul: + FT_TRACE4(( " mul" )); + + args[0] = FT_MulFix( args[0], args[1] ); + args++; + break; + + case t2_op_sqrt: + FT_TRACE4(( " sqrt" )); + + if ( args[0] > 0 ) + { + FT_Int count = 9; + FT_Fixed root = args[0]; + FT_Fixed new_root; + + + for (;;) + { + new_root = ( root + FT_DivFix(args[0],root) + 1 ) >> 1; + if ( new_root == root || count <= 0 ) + break; + root = new_root; + } + args[0] = new_root; + } + else + args[0] = 0; + args++; + break; + + case t2_op_drop: + /* nothing */ + FT_TRACE4(( " drop" )); + + break; + + case t2_op_exch: + { + FT_Fixed tmp; + + + FT_TRACE4(( " exch" )); + + tmp = args[0]; + args[0] = args[1]; + args[1] = tmp; + args += 2; + } + break; + + case t2_op_index: + { + FT_Int index = args[0] >> 16; + + + FT_TRACE4(( " index" )); + + if ( index < 0 ) + index = 0; + else if ( index > num_args - 2 ) + index = num_args - 2; + args[0] = args[-( index + 1 )]; + args++; + } + break; + + case t2_op_roll: + { + FT_Int count = (FT_Int)( args[0] >> 16 ); + FT_Int index = (FT_Int)( args[1] >> 16 ); + + + FT_TRACE4(( " roll" )); + + if ( count <= 0 ) + count = 1; + + args -= count; + if ( args < stack ) + goto Stack_Underflow; + + if ( index >= 0 ) + { + while ( index > 0 ) + { + FT_Fixed tmp = args[count - 1]; + FT_Int i; + + + for ( i = count - 2; i >= 0; i-- ) + args[i + 1] = args[i]; + args[0] = tmp; + index--; + } + } + else + { + while ( index < 0 ) + { + FT_Fixed tmp = args[0]; + FT_Int i; + + + for ( i = 0; i < count - 1; i++ ) + args[i] = args[i + 1]; + args[count - 1] = tmp; + index++; + } + } + args += count; + } + break; + + case t2_op_dup: + FT_TRACE4(( " dup" )); + + args[1] = args[0]; + args++; + break; + + case t2_op_put: + { + FT_Fixed val = args[0]; + FT_Int index = (FT_Int)( args[1] >> 16 ); + + + FT_TRACE4(( " put" )); + + if ( index >= 0 && index < decoder->len_buildchar ) + decoder->buildchar[index] = val; + } + break; + + case t2_op_get: + { + FT_Int index = (FT_Int)( args[0] >> 16 ); + FT_Fixed val = 0; + + + FT_TRACE4(( " get" )); + + if ( index >= 0 && index < decoder->len_buildchar ) + val = decoder->buildchar[index]; + + args[0] = val; + args++; + } + break; + + case t2_op_store: + FT_TRACE4(( " store ")); + + goto Unimplemented; + + case t2_op_load: + FT_TRACE4(( " load" )); + + goto Unimplemented; + + case t2_op_and: + { + FT_Fixed cond = args[0] && args[1]; + + + FT_TRACE4(( " and" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_or: + { + FT_Fixed cond = args[0] || args[1]; + + + FT_TRACE4(( " or" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_eq: + { + FT_Fixed cond = !args[0]; + + + FT_TRACE4(( " eq" )); + + args[0] = cond ? 0x10000L : 0; + args++; + } + break; + + case t2_op_ifelse: + { + FT_Fixed cond = (args[2] <= args[3]); + + + FT_TRACE4(( " ifelse" )); + + if ( !cond ) + args[0] = args[1]; + args++; + } + break; + + case t2_op_callsubr: + { + FT_UInt index = (FT_UInt)( ( args[0] >> 16 ) + + decoder->locals_bias ); + + + FT_TRACE4(( " callsubr(%d)", index )); + + if ( index >= decoder->num_locals ) + { + FT_ERROR(( "T2_Parse_CharStrings:" )); + FT_ERROR(( " invalid local subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->locals[index]; + zone->limit = decoder->locals[index+1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case t2_op_callgsubr: + { + FT_UInt index = (FT_UInt)( ( args[0] >> 16 ) + + decoder->globals_bias ); + + + FT_TRACE4(( " callgsubr(%d)", index )); + + if ( index >= decoder->num_globals ) + { + FT_ERROR(( "T2_Parse_CharStrings:" )); + FT_ERROR(( " invalid global subr index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T2_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T2_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->globals[index]; + zone->limit = decoder->globals[index+1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "T2_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case t2_op_return: + FT_TRACE4(( " return" )); + + if ( decoder->zone <= decoder->zones ) + { + FT_ERROR(( "T2_Parse_CharStrings: unexpected return\n" )); + goto Syntax_Error; + } + + decoder->zone--; + zone = decoder->zone; + ip = zone->cursor; + limit = zone->limit; + break; + + default: + Unimplemented: + FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); + + if ( ip[-1] == 12 ) + FT_ERROR(( " %d", ip[0] )); + FT_ERROR(( "\n" )); + + return T2_Err_Unimplemented_Feature; + } + + decoder->top = args; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + return error; + + Syntax_Error: + FT_TRACE4(( "T2_Parse_CharStrings: syntax error!" )); + return T2_Err_Invalid_File_Format; + + Stack_Underflow: + FT_TRACE4(( "T2_Parse_CharStrings: stack underflow!" )); + return T2_Err_Too_Few_Arguments; + + Stack_Overflow: + FT_TRACE4(( "T2_Parse_CharStrings: stack overflow!" )); + return T2_Err_Stack_Overflow; + + Memory_Error: + return builder->error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#if 0 /* unused until we support pure CFF fonts */ + + + LOCAL_FUNC + FT_Error T2_Compute_Max_Advance( TT_Face face, + FT_Int* max_advance ) + { + FT_Error error = 0; + T2_Decoder decoder; + FT_Int glyph_index; + CFF_Font* cff = (CFF_Font*)face->other; + + + *max_advance = 0; + + /* Initialize load decoder */ + T2_Init_Decoder( &decoder, face, 0, 0 ); + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + /* For each glyph, parse the glyph charstring and extract */ + /* the advance width. */ + for ( glyph_index = 0; glyph_index < face->root.num_glyphs; + glyph_index++ ) + { + FT_Byte* charstring; + FT_ULong charstring_len; + + + /* now get load the unscaled outline */ + error = T2_Access_Element( &cff->charstrings_index, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + T2_Prepare_Decoder( &decoder, glyph_index ); + error = T2_Parse_CharStrings( &decoder, charstring, charstring_len ); + + T2_Forget_Element( &cff->charstrings_index, &charstring ); + } + + /* ignore the error if one has occurred -- skip to next glyph */ + error = 0; + } + + *max_advance = decoder.builder.advance.x; + + return T2_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error T2_Load_Glyph( T2_GlyphSlot glyph, + T2_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + T2_Decoder decoder; + TT_Face face = (TT_Face)glyph->root.face; + FT_Bool hinting; + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = 0x10000L; + glyph->y_scale = 0x10000L; + if ( size ) + { + glyph->x_scale = size->metrics.x_scale; + glyph->y_scale = size->metrics.y_scale; + } + + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; /* by default */ + + { + FT_Byte* charstring; + FT_ULong charstring_len; + + + T2_Init_Decoder( &decoder, face, size, glyph ); + + decoder.builder.no_recurse = + (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); + + /* now load the unscaled outline */ + error = T2_Access_Element( &cff->charstrings_index, glyph_index, + &charstring, &charstring_len ); + if ( !error ) + { + T2_Prepare_Decoder( &decoder, glyph_index ); + error = T2_Parse_CharStrings( &decoder, charstring, charstring_len ); + + T2_Forget_Element( &cff->charstrings_index, &charstring ); + } + + /* save new glyph tables */ + T2_Done_Builder( &decoder.builder ); + } + + /* Now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax. */ + if ( !error ) + { + /* for composite glyphs, return only left side bearing and */ + /* advance width */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.glyph_width; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.glyph_width; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags = 0; + if ( size && size->metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = &glyph->root.outline; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points */ + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* Then scale the metrics */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + } + +#if 0 + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, cff->font_matrix ); +#endif + + /* compute the other metrics */ + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax + 63 ) & -64; + cbox.yMax = ( cbox.yMax + 63 ) & -64; + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + } + } + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2gload.h b/subsys/win32k/freetype/src/cff/t2gload.h new file mode 100644 index 0000000..7c0406b --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2gload.h @@ -0,0 +1,213 @@ +/***************************************************************************/ +/* */ +/* t2gload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2GLOAD_H +#define T2GLOAD_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#define T2_MAX_OPERANDS 48 +#define T2_MAX_SUBRS_CALLS 32 + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* max_points :: maximum points in builder outline */ + /* */ + /* max_contours :: Maximal number of contours in builder outline. */ + /* */ + /* last :: The last point position. */ + /* */ + /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ + /* */ + /* scale_y :: The vertical scale (FUnits to sub-pixels). */ + /* */ + /* pos_x :: The horizontal translation (if composite glyph). */ + /* */ + /* pos_y :: The vertical translation (if composite glyph). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* bbox :: Unused. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: If this flag is not set, no points are loaded. */ + /* */ + /* no_recurse :: Set but not used. */ + /* */ + /* error :: An error code that is only used to report memory */ + /* allocation problems. */ + /* */ + /* metrics_only :: A boolean indicating that we only want to compute */ + /* the metrics of a given glyph, not load all of its */ + /* points. */ + /* */ + typedef struct T2_Builder_ + { + FT_Memory memory; + TT_Face face; + T2_GlyphSlot glyph; + FT_GlyphLoader* loader; + FT_Outline* base; + FT_Outline* current; + + FT_Vector last; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + FT_Bool no_recurse; + + FT_Error error; /* only used for memory errors */ + FT_Bool metrics_only; + + } T2_Builder; + + + /* execution context charstring zone */ + + typedef struct T2_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } T2_Decoder_Zone; + + + typedef struct T2_Decoder_ + { + T2_Builder builder; + CFF_Font* cff; + + FT_Fixed stack[T2_MAX_OPERANDS + 1]; + FT_Fixed* top; + + T2_Decoder_Zone zones[T2_MAX_SUBRS_CALLS + 1]; + T2_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + FT_Pos glyph_width; + FT_Pos nominal_width; + + FT_Bool read_width; + FT_Int num_hints; + FT_Fixed* buildchar; + FT_Int len_buildchar; + + FT_UInt num_locals; + FT_UInt num_globals; + + FT_Int locals_bias; + FT_Int globals_bias; + + FT_Byte** locals; + FT_Byte** globals; + + } T2_Decoder; + + + LOCAL_DEF + void T2_Init_Decoder( T2_Decoder* decoder, + TT_Face face, + T2_Size size, + T2_GlyphSlot slot ); + + LOCAL_DEF + void T2_Prepare_Decoder( T2_Decoder* decoder, + FT_UInt glyph_index ); + +#if 0 /* unused until we support pure CFF fonts */ + + /* Compute the maximum advance width of a font through quick parsing */ + LOCAL_DEF + FT_Error T2_Compute_Max_Advance( TT_Face face, + FT_Int* max_advance ); + +#endif /* 0 */ + + LOCAL_DEF + FT_Error T2_Parse_CharStrings( T2_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ); + + LOCAL_DEF + FT_Error T2_Load_Glyph( T2_GlyphSlot glyph, + T2_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2GLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2load.c b/subsys/win32k/freetype/src/cff/t2load.c new file mode 100644 index 0000000..fa19ecd --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2load.c @@ -0,0 +1,757 @@ +/***************************************************************************/ +/* */ +/* t2load.c */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2load.h" +#include "t2parse.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t2load + + + /* read a CFF offset from memory */ + static + FT_ULong t2_get_offset( FT_Byte* p, + FT_Byte off_size ) + { + FT_ULong result; + + + for ( result = 0; off_size > 0; off_size-- ) + { + result <<= 8; + result |= *p++; + } + + return result; + } + + + static + FT_Error t2_new_cff_index( CFF_Index* index, + FT_Stream stream, + FT_Bool load ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_UShort count; + + + MEM_Set( index, 0, sizeof ( *index ) ); + + index->stream = stream; + if ( !READ_UShort( count ) && + count > 0 ) + { + FT_Byte* p; + FT_Byte offsize; + FT_ULong data_size; + FT_ULong* poff; + + + /* there is at least one element; read the offset size, */ + /* then access the offset table to compute the index's total size */ + if ( READ_Byte( offsize ) ) + goto Exit; + + index->stream = stream; + index->count = count; + index->off_size = offsize; + data_size = (FT_ULong)( count + 1 ) * offsize; + + if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) || + ACCESS_Frame( data_size ) ) + goto Exit; + + poff = index->offsets; + p = (FT_Byte*)stream->cursor; + + for ( ; (FT_Short)count >= 0; count-- ) + { + poff[0] = t2_get_offset( p, offsize ); + poff++; + p += offsize; + } + + FORGET_Frame(); + + index->data_offset = FILE_Pos(); + data_size = poff[-1] - 1; + + if ( load ) + { + /* load the data */ + if ( EXTRACT_Frame( data_size, index->bytes ) ) + goto Exit; + } + else + { + /* skip the data */ + (void)FILE_Skip( data_size ); + } + } + + Exit: + if ( error ) + FREE( index->offsets ); + + return error; + } + + + static + void t2_done_cff_index( CFF_Index* index ) + { + if ( index->stream ) + { + FT_Stream stream = index->stream; + FT_Memory memory = stream->memory; + + + if ( index->bytes ) + RELEASE_Frame( index->bytes ); + + FREE( index->offsets ); + MEM_Set( index, 0, sizeof ( *index ) ); + } + } + + + static + FT_Error t2_explicit_cff_index( CFF_Index* index, + FT_Byte*** table ) + { + FT_Error error = 0; + FT_Memory memory = index->stream->memory; + FT_UInt n, offset, old_offset; + FT_Byte** t; + + + *table = 0; + + if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) ) + { + old_offset = 1; + for ( n = 0; n <= index->count; n++ ) + { + offset = index->offsets[n]; + if ( !offset ) + offset = old_offset; + + t[n] = index->bytes + offset - 1; + + old_offset = offset; + } + *table = t; + } + + return error; + } + + + LOCAL_FUNC + FT_Error T2_Access_Element( CFF_Index* index, + FT_UInt element, + FT_Byte** pbytes, + FT_ULong* pbyte_len ) + { + FT_Error error = 0; + + + if ( index && index->count > element ) + { + /* compute start and end offsets */ + FT_ULong off1, off2; + + + off1 = index->offsets[element]; + if ( off1 ) + { + do + { + element++; + off2 = index->offsets[element]; + + } while ( off2 == 0 && element < index->count ); + + if ( !off2 ) + off1 = 0; + } + + /* access element */ + if ( off1 ) + { + *pbyte_len = off2 - off1; + + if ( index->bytes ) + { + /* this index was completely loaded in memory, that's easy */ + *pbytes = index->bytes + off1 - 1; + } + else + { + /* this index is still on disk/file, access it through a frame */ + FT_Stream stream = index->stream; + + + if ( FILE_Seek( index->data_offset + off1 - 1 ) || + EXTRACT_Frame( off2 - off1, *pbytes ) ) + goto Exit; + } + } + else + { + /* empty index element */ + *pbytes = 0; + *pbyte_len = 0; + } + } + else + error = T2_Err_Invalid_Argument; + + Exit: + return error; + } + + + LOCAL_FUNC + void T2_Forget_Element( CFF_Index* index, + FT_Byte** pbytes ) + { + if ( index->bytes == 0 ) + { + FT_Stream stream = index->stream; + + + RELEASE_Frame( *pbytes ); + } + } + + + LOCAL_FUNC + FT_String* T2_Get_Name( CFF_Index* index, + FT_UInt element ) + { + FT_Memory memory = index->stream->memory; + FT_Byte* bytes; + FT_ULong byte_len; + FT_Error error; + FT_String* name = 0; + + + error = T2_Access_Element( index, element, &bytes, &byte_len ); + if ( error ) + goto Exit; + + if ( !ALLOC( name, byte_len + 1 ) ) + { + MEM_Copy( name, bytes, byte_len ); + name[byte_len] = 0; + } + T2_Forget_Element( index, &bytes ); + + Exit: + return name; + } + + + LOCAL_FUNC + FT_String* T2_Get_String( CFF_Index* index, + FT_UInt sid, + PSNames_Interface* interface ) + { + /* if it is not a standard string, return it */ + if ( sid > 390 ) + return T2_Get_Name( index, sid - 390 ); + + /* that's a standard string, fetch a copy from the PSName module */ + { + FT_String* name = 0; + const char* adobe_name = interface->adobe_std_strings( sid ); + FT_UInt len; + + + if ( adobe_name ) + { + FT_Memory memory = index->stream->memory; + FT_Error error; + + + len = (FT_UInt)strlen( adobe_name ); + if ( !ALLOC( name, len + 1 ) ) + { + MEM_Copy( name, adobe_name, len ); + name[len] = 0; + } + } + + return name; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** FD Select table support ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + + + static + void CFF_Done_FD_Select( CFF_FD_Select* select, + FT_Stream stream ) + { + if ( select->data ) + RELEASE_Frame( select->data ); + + select->data_size = 0; + select->format = 0; + select->range_count = 0; + } + + + static + FT_Error CFF_Load_FD_Select( CFF_FD_Select* select, + FT_UInt num_glyphs, + FT_Stream stream, + FT_ULong offset ) + { + FT_Error error; + FT_Byte format; + FT_UInt num_ranges; + + + /* read format */ + if ( FILE_Seek( offset ) || READ_Byte( format ) ) + goto Exit; + + select->format = format; + select->cache_count = 0; /* clear cache */ + + switch ( format ) + { + case 0: /* format 0, that's simple */ + select->data_size = num_glyphs; + goto Load_Data; + + case 3: /* format 3, a tad more complex */ + if ( READ_UShort( num_ranges ) ) + goto Exit; + + select->data_size = num_ranges * 3 + 2; + + Load_Data: + if ( EXTRACT_Frame( select->data_size, select->data ) ) + goto Exit; + break; + + default: /* hmm... that's wrong */ + error = T2_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Byte CFF_Get_FD( CFF_FD_Select* select, + FT_UInt glyph_index ) + { + FT_Byte fd = 0; + + + switch ( select->format ) + { + case 0: + fd = select->data[glyph_index]; + break; + + case 3: + /* first, compare to cache */ + if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count ) + { + fd = select->cache_fd; + break; + } + + /* then, lookup the ranges array */ + { + FT_Byte* p = select->data; + FT_Byte* p_limit = p + select->data_size; + FT_Byte fd2; + FT_UInt first, limit; + + + first = NEXT_UShort( p ); + do + { + if ( glyph_index < first ) + break; + + fd2 = *p++; + limit = NEXT_UShort( p ); + + if ( glyph_index < limit ) + { + fd = fd2; + + /* update cache */ + select->cache_first = first; + select->cache_count = limit-first; + select->cache_fd = fd2; + break; + } + first = limit; + + } while ( p < p_limit ); + } + break; + + default: + ; + } + + return fd; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*** ***/ + /*** CFF font support ***/ + /*** ***/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error CFF_Load_SubFont( CFF_SubFont* font, + CFF_Index* index, + FT_UInt font_index, + FT_Stream stream, + FT_ULong base_offset ) + { + FT_Error error; + T2_Parser parser; + FT_Byte* dict; + FT_ULong dict_len; + CFF_Font_Dict* top = &font->font_dict; + CFF_Private* priv = &font->private_dict; + + + T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->font_dict ); + + /* set defaults */ + MEM_Set( top, 0, sizeof ( *top ) ); + + top->underline_position = -100; + top->underline_thickness = 50; + top->charstring_type = 2; + top->font_matrix.xx = 0x10000L; + top->font_matrix.yy = 0x10000L; + top->cid_count = 8720; + + error = T2_Access_Element( index, font_index, &dict, &dict_len ) || + T2_Parser_Run( &parser, dict, dict + dict_len ); + + T2_Forget_Element( index, &dict ); + + if ( error ) + goto Exit; + + /* if it is a CID font, we stop there */ + if ( top->cid_registry ) + goto Exit; + + /* parse the private dictionary, if any */ + if ( top->private_offset && top->private_size ) + { + /* set defaults */ + MEM_Set( priv, 0, sizeof ( *priv ) ); + + priv->blue_shift = 7; + priv->blue_fuzz = 1; + priv->lenIV = -1; + priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L; + priv->blue_scale = (FT_Fixed)0.039625 * 0x10000L; + + T2_Parser_Init( &parser, T2CODE_PRIVATE, priv ); + + if ( FILE_Seek( base_offset + font->font_dict.private_offset ) || + ACCESS_Frame( font->font_dict.private_size ) ) + goto Exit; + + error = T2_Parser_Run( &parser, + (FT_Byte*)stream->cursor, + (FT_Byte*)stream->limit ); + FORGET_Frame(); + if ( error ) + goto Exit; + } + + /* read the local subrs, if any */ + if ( priv->local_subrs_offset ) + { + if ( FILE_Seek( base_offset + top->private_offset + + priv->local_subrs_offset ) ) + goto Exit; + + error = t2_new_cff_index( &font->local_subrs_index, stream, 1 ); + if ( error ) + goto Exit; + + font->num_local_subrs = font->local_subrs_index.count; + error = t2_explicit_cff_index( &font->local_subrs_index, + &font->local_subrs ); + } + + Exit: + return error; + } + + + static + void CFF_Done_SubFont( FT_Memory memory, + CFF_SubFont* subfont ) + { + if ( subfont ) + { + t2_done_cff_index( &subfont->local_subrs_index ); + FREE( subfont->local_subrs ); + } + } + + + LOCAL_FUNC + FT_Error T2_Load_CFF_Font( FT_Stream stream, + FT_Int face_index, + CFF_Font* font ) + { + static const FT_Frame_Field cff_header_fields[] = + { + FT_FRAME_START( 4 ), + FT_FRAME_BYTE( CFF_Font, version_major ), + FT_FRAME_BYTE( CFF_Font, version_minor ), + FT_FRAME_BYTE( CFF_Font, header_size ), + FT_FRAME_BYTE( CFF_Font, absolute_offsize ), + FT_FRAME_END + }; + + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong base_offset; + CFF_Font_Dict* dict; + + + MEM_Set( font, 0, sizeof ( *font ) ); + font->stream = stream; + font->memory = memory; + dict = &font->top_font.font_dict; + base_offset = FILE_Pos(); + + /* read CFF font header */ + if ( READ_Fields( cff_header_fields, font ) ) + goto Exit; + + /* check format */ + if ( font->version_major != 1 || + font->header_size < 4 || + font->absolute_offsize > 4 ) + { + FT_TRACE2(( "[not a CFF font header!]\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + /* skip the rest of the header */ + (void)FILE_Skip( font->header_size - 4 ); + + /* read the name, top dict, string and global subrs index */ + error = t2_new_cff_index( &font->name_index, stream, 0 ) || + t2_new_cff_index( &font->font_dict_index, stream, 0 ) || + t2_new_cff_index( &font->string_index, stream, 0 ) || + t2_new_cff_index( &font->global_subrs_index, stream, 1 ); + if ( error ) + goto Exit; + + /* well, we don't really forget the `disabled' fonts... */ + font->num_faces = font->name_index.count; + if ( face_index >= (FT_Int)font->num_faces ) + { + FT_ERROR(( "T2_Load_CFF_Font: incorrect face index = %d\n", + face_index )); + error = T2_Err_Invalid_Argument; + } + + /* in case of a font format check, simply exit now */ + if ( face_index < 0 ) + goto Exit; + + /* now, parse the top-level font dictionary */ + error = CFF_Load_SubFont( &font->top_font, + &font->font_dict_index, + face_index, + stream, + base_offset ); + if ( error ) + goto Exit; + + /* now, check for a CID font */ + if ( dict->cid_registry ) + { + CFF_Index fd_index; + CFF_SubFont* sub; + FT_UInt index; + + + /* this is a CID-keyed font, we must now allocate a table of */ + /* sub-fonts, then load each of them separately */ + if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) ) + goto Exit; + + error = t2_new_cff_index( &fd_index, stream, 0 ); + if ( error ) + goto Exit; + + if ( fd_index.count > CFF_MAX_CID_FONTS ) + { + FT_ERROR(( "T2_Load_CFF_Font: FD array too large in CID font\n" )); + goto Fail_CID; + } + + /* allocate & read each font dict independently */ + font->num_subfonts = fd_index.count; + if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) ) + goto Fail_CID; + + /* setup pointer table */ + for ( index = 0; index < fd_index.count; index++ ) + font->subfonts[index] = sub + index; + + /* now load each sub font independently */ + for ( index = 0; index < fd_index.count; index++ ) + { + sub = font->subfonts[index]; + error = CFF_Load_SubFont( sub, &fd_index, index, + stream, base_offset ); + if ( error ) + goto Fail_CID; + } + + /* now load the FD Select array */ + error = CFF_Load_FD_Select( &font->fd_select, + dict->cid_count, + stream, + base_offset + dict->cid_fd_select_offset ); + + Fail_CID: + t2_done_cff_index( &fd_index ); + + if ( error ) + goto Exit; + } + else + font->num_subfonts = 0; + + /* read the charstrings index now */ + if ( dict->charstrings_offset == 0 ) + { + FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( FILE_Seek( base_offset + dict->charstrings_offset ) ) + goto Exit; + + error = t2_new_cff_index( &font->charstrings_index, stream, 0 ); + if ( error ) + goto Exit; + + /* explicit the global subrs */ + font->num_global_subrs = font->global_subrs_index.count; + font->num_glyphs = font->charstrings_index.count; + + error = t2_explicit_cff_index( &font->global_subrs_index, + &font->global_subrs ) ; + + if ( error ) + goto Exit; + + /* get the font name */ + font->font_name = T2_Get_Name( &font->name_index, face_index ); + + Exit: + return error; + } + + + LOCAL_FUNC + void T2_Done_CFF_Font( CFF_Font* font ) + { + FT_Memory memory = font->memory; + FT_UInt index; + + + t2_done_cff_index( &font->global_subrs_index ); + t2_done_cff_index( &font->string_index ); + t2_done_cff_index( &font->font_dict_index ); + t2_done_cff_index( &font->name_index ); + t2_done_cff_index( &font->charstrings_index ); + + /* release font dictionaries */ + for ( index = 0; index < font->num_subfonts; index++ ) + CFF_Done_SubFont( memory, font->subfonts[index] ); + + CFF_Done_SubFont( memory, &font->top_font ); + + CFF_Done_FD_Select( &font->fd_select, font->stream ); + + FREE( font->global_subrs ); + FREE( font->font_name ); + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2load.h b/subsys/win32k/freetype/src/cff/t2load.h new file mode 100644 index 0000000..7ebc76d --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2load.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* t2load.h */ +/* */ +/* OpenType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2LOAD_H +#define T2LOAD_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + LOCAL_DEF + FT_String* T2_Get_Name( CFF_Index* index, + FT_UInt element ); + + LOCAL_DEF + FT_String* T2_Get_String( CFF_Index* index, + FT_UInt sid, + PSNames_Interface* interface ); + + LOCAL_DEF + FT_Error T2_Access_Element( CFF_Index* index, + FT_UInt element, + FT_Byte** pbytes, + FT_ULong* pbyte_len ); + + LOCAL_DEF + void T2_Forget_Element( CFF_Index* index, + FT_Byte** pbytes ); + + LOCAL_DEF + FT_Error T2_Load_CFF_Font( FT_Stream stream, + FT_Int face_index, + CFF_Font* font ); + + LOCAL_DEF + void T2_Done_CFF_Font( CFF_Font* font ); + + LOCAL_DEF + FT_Byte CFF_Get_FD( CFF_FD_Select* select, + FT_UInt glyph_index ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2LOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2objs.c b/subsys/win32k/freetype/src/cff/t2objs.c new file mode 100644 index 0000000..1d87f0c --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2objs.c @@ -0,0 +1,600 @@ +/***************************************************************************/ +/* */ +/* t2objs.c */ +/* */ +/* OpenType objects manager (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t2objs.h" +#include "t2load.h" + +#else + +#include +#include + +#endif + + +#include + +#include /* for strlen() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t2objs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + static + FT_String* T2_StrCopy( FT_Memory memory, + const FT_String* source ) + { + FT_Error error; + FT_String* result = 0; + FT_Int len = (FT_Int)strlen( source ); + + + if ( !ALLOC( result, len + 1 ) ) + { + MEM_Copy( result, source, len ); + result[len] = 0; + } + return result; + } + + +#if 0 + + /* this function is used to build a Unicode charmap from the glyph names */ + /* in a file */ + static + FT_Error CFF_Build_Unicode_Charmap( T2_Face face, + FT_ULong base_offset, + PSNames_Interface* psnames ) + { + CFF_Font* font = (CFF_Font*)face->extra.data; + FT_Memory memory = FT_FACE_MEMORY(face); + FT_UInt n, num_glyphs = face->root.num_glyphs; + const char** glyph_names; + FT_Error error; + CFF_Font_Dict* dict = &font->top_font.font_dict; + FT_ULong charset_offset; + FT_Byte format; + FT_Stream stream = face->root.stream; + + + charset_offset = dict->charset_offset; + if ( !charset_offset ) + { + FT_ERROR(( "CFF.Build_Unicode_Charmap: charset table is missing\n" )); + error = T2_Err_Invalid_File_Format; + goto Exit; + } + + /* allocate the charmap */ + if ( ALLOC( face->charmap, ... + + /* seek to charset table and allocate glyph names table */ + if ( FILE_Seek( base_offset + charset_offset ) || + ALLOC_ARRAY( glyph_names, num_glyphs, const char* ) ) + goto Exit; + + /* now, read each glyph name and store it in the glyph name table */ + if ( READ_Byte( format ) ) + goto Fail; + + switch ( format ) + { + case 0: /* format 0 - one SID per glyph */ + { + const char** gname = glyph_names; + const char** limit = gname + num_glyphs; + + if ( ACCESS_Frame( num_glyphs*2 ) ) + goto Fail; + + for ( ; gname < limit; gname++ ) + gname[0] = T2_Get_String( &font->string_index, + GET_UShort(), + psnames ); + FORGET_Frame(); + break; + } + + case 1: /* format 1 - sequential ranges */ + case 2: /* format 2 - sequential ranges with 16-bit counts */ + { + const char** gname = glyph_names; + const char** limit = gname + num_glyphs; + FT_UInt len = 3; + + if (format == 2) + len++; + + while (gname < limit) + { + FT_UInt first; + FT_UInt count; + + if ( ACCESS_Frame( len ) ) + goto Fail; + + first = GET_UShort(); + if (format == 3) + count = GET_UShort(); + else + count = GET_Byte(); + + FORGET_Frame(); + + for ( ; count > 0; count-- ) + { + gname[0] = T2_Get_String( &font->string_index, + first, + psnames ); + gname++; + first++; + } + } + break; + } + + default: /* unknown charset format! */ + FT_ERROR(( "CFF: unknown charset format!\n" )); + error = T2_Err_Invalid_File_Format; + goto Fail; + } + + /* all right, the glyph names were loaded, we now need to create */ + /* the corresponding unicode charmap.. */ + + Fail: + for ( n = 0; n < num_glyphs; n++ ) + FREE( glyph_names[n] ); + + FREE( glyph_names ); + + Exit: + return error; + } + +#endif /* 0 */ + + + static + FT_Encoding find_encoding( int platform_id, + int encoding_id ) + { + typedef struct TEncoding + { + int platform_id; + int encoding_id; + FT_Encoding encoding; + + } TEncoding; + + static + const TEncoding tt_encodings[] = + { + { TT_PLATFORM_ISO, -1, ft_encoding_unicode }, + + { TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode }, + + { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman }, + + { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, ft_encoding_gb2312 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, ft_encoding_wansung }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, ft_encoding_johab } + }; + + const TEncoding *cur, *limit; + + + cur = tt_encodings; + limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); + + for ( ; cur < limit; cur++ ) + { + if ( cur->platform_id == platform_id ) + { + if ( cur->encoding_id == encoding_id || + cur->encoding_id == -1 ) + return cur->encoding; + } + } + + return ft_encoding_none; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Face */ + /* */ + /* */ + /* Initializes a given OpenType face object. */ + /* */ + /* */ + /* stream :: The source font stream. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Face( FT_Stream stream, + T2_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + SFNT_Interface* sfnt; + PSNames_Interface* psnames; + FT_Bool pure_cff = 1; + FT_Bool sfnt_format = 0; + + + sfnt = (SFNT_Interface*)FT_Get_Module_Interface( + face->root.driver->root.library, "sfnt" ); + if ( !sfnt ) + goto Bad_Format; + + psnames = (PSNames_Interface*)FT_Get_Module_Interface( + face->root.driver->root.library, "psnames" ); + + /* create input stream from resource */ + if ( FILE_Seek( 0 ) ) + goto Exit; + + /* check that we have a valid OpenType file */ + error = sfnt->init_face( stream, face, face_index, num_params, params ); + if ( !error ) + { + if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ + { + FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); + goto Bad_Format; + } + + /* If we are performing a simple font format check, exit immediately */ + if ( face_index < 0 ) + return T2_Err_Ok; + + sfnt_format = 1; + + /* now, the font can be either an OpenType/CFF font, or a SVG CEF */ + /* font in the later case; it doesn't have a `head' table */ + error = face->goto_table( face, TTAG_head, stream, 0 ); + if ( !error ) + { + pure_cff = 0; + + /* Load font directory */ + error = sfnt->load_face( stream, face, + face_index, num_params, params ); + if ( error ) + goto Exit; + } + else + { + /* load the `cmap' table by hand */ + error = sfnt->load_charmaps( face, stream ); + if ( error ) + goto Exit; + + /* XXX: for now, we don't load the GPOS table, as OpenType Layout */ + /* support will be added later to FreeType 2 as a separate module */ + } + + /* now, load the CFF part of the file */ + error = face->goto_table( face, TTAG_CFF, stream, 0 ); + if ( error ) + goto Exit; + } + else + { + /* rewind to start of file; we are going to load a pure-CFF font */ + (void)FILE_Seek( 0 ); + error = FT_Err_Ok; + } + + /* now load and parse the CFF table in the file */ + { + CFF_Font* cff; + FT_Memory memory = face->root.memory; + FT_Face root; + FT_UInt flags; + FT_ULong base_offset; + + + if ( ALLOC( cff, sizeof ( *cff ) ) ) + goto Exit; + + base_offset = FILE_Pos(); + + face->extra.data = cff; + error = T2_Load_CFF_Font( stream, face_index, cff ); + if ( error ) + goto Exit; + + /* Complement the root flags with some interesting information. */ + /* Note that this is only necessary for pure CFF and CEF fonts */ + + root = &face->root; + if ( pure_cff ) + { + CFF_Font_Dict* dict = &cff->top_font.font_dict; + + + /* we need the `PSNames' module for pure-CFF and CEF formats */ + if ( !psnames ) + { + FT_ERROR(( "T2_Init_Face:" )); + FT_ERROR(( " cannot open CFF & CEF fonts\n" )); + FT_ERROR(( " " )); + FT_ERROR(( " without the `PSNames' module\n" )); + goto Bad_Format; + } + + /* compute number of glyphs */ + if ( dict->cid_registry ) + root->num_glyphs = dict->cid_count; + else + root->num_glyphs = cff->charstrings_index.count; + + /* set global bbox, as well as EM size */ + root->units_per_EM = (FT_UInt)FT_DivFix( 1000L << 16, + dict->font_matrix.yy ) >> 16; + root->bbox = dict->font_bbox; + root->ascender = (FT_Short)root->bbox.yMax; + root->descender = (FT_Short)root->bbox.yMin; + + /* retrieve font family & style name */ + root->family_name = T2_Get_Name( &cff->name_index, face_index ); + if ( dict->cid_registry ) + { + root->style_name = T2_StrCopy( memory, "Regular" ); /* XXXX */ + } + else + { + root->style_name = T2_Get_String( &cff->string_index, + dict->weight, + psnames ); + } + + /*******************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ + + if ( sfnt_format ) + flags |= FT_FACE_FLAG_SFNT; + + /* fixed width font? */ + if ( dict->is_fixed_pitch ) + flags |= FT_FACE_FLAG_FIXED_WIDTH; + +/* XXXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ +#if 0 + /* kerning available? */ + if ( face->kern_pairs ) + flags |= FT_FACE_FLAG_KERNING; +#endif + + root->face_flags = flags; + + /*******************************************************************/ + /* */ + /* Compute style flags. */ + /* */ + flags = 0; + + if ( dict->italic_angle ) + flags |= FT_STYLE_FLAG_ITALIC; + + /* XXX: may not be correct */ + if ( cff->top_font.private_dict.force_bold ) + flags |= FT_STYLE_FLAG_BOLD; + + root->style_flags = flags; + + /* set the charmaps if any */ + if ( sfnt_format ) + { + /*****************************************************************/ + /* */ + /* Polish the charmaps. */ + /* */ + /* Try to set the charmap encoding according to the platform & */ + /* encoding ID of each charmap. */ + /* */ + TT_CharMap charmap; + FT_Int n; + + + charmap = face->charmaps; + root->num_charmaps = face->num_charmaps; + + /* allocate table of pointers */ + if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) ) + goto Exit; + + for ( n = 0; n < root->num_charmaps; n++, charmap++ ) + { + FT_Int platform = charmap->cmap.platformID; + FT_Int encoding = charmap->cmap.platformEncodingID; + + + charmap->root.face = (FT_Face)face; + charmap->root.platform_id = platform; + charmap->root.encoding_id = encoding; + charmap->root.encoding = find_encoding( platform, encoding ); + + /* now, set root->charmap with a unicode charmap */ + /* wherever available */ + if ( !root->charmap && + charmap->root.encoding == ft_encoding_unicode ) + root->charmap = (FT_CharMap)charmap; + + root->charmaps[n] = (FT_CharMap)charmap; + } + } + } + } + + Exit: + return error; + + Bad_Format: + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_DEF + void T2_Done_Face( T2_Face face ) + { + FT_Memory memory = face->root.memory; + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + if ( sfnt ) + sfnt->done_face( face ); + + { + CFF_Font* cff = (CFF_Font*)face->extra.data; + + + if ( cff ) + { + T2_Done_CFF_Font( cff ); + FREE( face->extra.data ); + } + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Init_Driver */ + /* */ + /* */ + /* Initializes a given OpenType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T2_Init_Driver( T2_Driver driver ) + { + /* init extension registry if needed */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + return TT_Init_Extensions( driver ); + +#else + + FT_UNUSED( driver ); + + return T2_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Done_Driver */ + /* */ + /* */ + /* Finalizes a given OpenType driver. */ + /* */ + /* */ + /* driver :: A handle to the target OpenType driver. */ + /* */ + LOCAL_FUNC + void T2_Done_Driver( T2_Driver driver ) + { + /* destroy extensions registry if needed */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + TT_Done_Extensions( driver ); + +#else + + FT_UNUSED( driver ); + +#endif + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2objs.h b/subsys/win32k/freetype/src/cff/t2objs.h new file mode 100644 index 0000000..2602862 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2objs.h @@ -0,0 +1,148 @@ +/***************************************************************************/ +/* */ +/* t2objs.h */ +/* */ +/* OpenType objects manager (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2OBJS_H +#define T2OBJS_H + + +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Driver */ + /* */ + /* */ + /* A handle to an OpenType driver object. */ + /* */ + typedef struct T2_DriverRec_* T2_Driver; + + typedef TT_Face T2_Face; + + + /*************************************************************************/ + /* */ + /* */ + /* T2_Size */ + /* */ + /* */ + /* A handle to an OpenType size object. */ + /* */ + typedef FT_Size T2_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* T2_GlyphSlot */ + /* */ + /* */ + /* A handle to an OpenType glyph slot object. */ + /* */ + typedef struct T2_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } T2_GlyphSlotRec, *T2_GlyphSlot; + + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct T2_Transform_ + { + FT_Fixed xx, xy; /* transformation matrix coefficients */ + FT_Fixed yx, yy; + FT_F26Dot6 ox, oy; /* offsets */ + + } T2_Transform; + + + /* this is only used in the case of a pure CFF font with no charmap */ + typedef struct T2_CharMapRec_ + { + TT_CharMapRec root; + PS_Unicodes unicodes; + + } T2_CharMapRec, *T2_CharMap; + + + /***********************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct T2_DriverRec_ + { + FT_DriverRec root; + + void* extension_component; + + } T2_DriverRec; + + + /*************************************************************************/ + /* */ + /* Face functions */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Face( FT_Stream stream, + T2_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void T2_Done_Face( T2_Face face ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + LOCAL_DEF + FT_Error T2_Init_Driver( T2_Driver driver ); + + LOCAL_DEF + void T2_Done_Driver( T2_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2OBJS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2parse.c b/subsys/win32k/freetype/src/cff/t2parse.c new file mode 100644 index 0000000..e94a6dd --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2parse.c @@ -0,0 +1,641 @@ +/***************************************************************************/ +/* */ +/* t2parse.c */ +/* */ +/* OpenType parser (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t2parse.h" + +#else + +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t2parse + + +#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument +#define T2_Err_Syntax_Error FT_Err_Invalid_Argument + + + enum + { + t2_kind_none = 0, + t2_kind_num, + t2_kind_fixed, + t2_kind_string, + t2_kind_bool, + t2_kind_delta, + t2_kind_callback, + + t2_kind_max /* do not remove */ + }; + + + /* now generate handlers for the most simple fields */ + typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser ); + + typedef struct T2_Field_Handler_ + { + int kind; + int code; + FT_UInt offset; + FT_Byte size; + T2_Field_Reader reader; + FT_UInt array_max; + FT_UInt count_offset; + + } T2_Field_Handler; + + + LOCAL_FUNC + void T2_Parser_Init( T2_Parser* parser, + FT_UInt code, + void* object ) + { + MEM_Set( parser, 0, sizeof ( *parser ) ); + + parser->top = parser->stack; + parser->object_code = code; + parser->object = object; + } + + + /* reads an integer */ + static + FT_Long parse_t2_integer( FT_Byte* start, + FT_Byte* limit ) + { + FT_Byte* p = start; + FT_Int v = *p++; + FT_Long val = 0; + + + if ( v == 28 ) + { + if ( p + 2 > limit ) + goto Bad; + + val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] ); + p += 2; + } + else if ( v == 29 ) + { + if ( p + 4 > limit ) + goto Bad; + + val = ( (FT_Long)p[0] << 24 ) | + ( (FT_Long)p[1] << 16 ) | + ( (FT_Long)p[2] << 8 ) | + p[3]; + p += 4; + } + else if ( v < 247 ) + { + val = v - 139; + } + else if ( v < 251 ) + { + if ( p + 1 > limit ) + goto Bad; + + val = ( v - 247 ) * 256 + p[0] + 108; + p++; + } + else + { + if ( p + 1 > limit ) + goto Bad; + + val = -( v - 251 ) * 256 - p[0] - 108; + p++; + } + + Exit: + return val; + + Bad: + val = 0; + goto Exit; + } + + + /* read a real */ + static + FT_Fixed parse_t2_real( FT_Byte* start, + FT_Byte* limit, + FT_Int power_ten ) + { + FT_Byte* p = start; + FT_Long num, divider, result, exp; + FT_Int sign = 0, exp_sign = 0; + FT_Byte nib; + FT_Byte phase; + + + result = 0; + num = 0; + divider = 1; + + /* first of all, read the integer part */ + phase = 4; + p--; + + for (;;) + { + /* read one nibble at a time */ + if ( phase && ++p >= limit ) + goto Bad; + + nib = ( p[0] >> phase ) & 0xF; + phase = 4 - phase; + + if ( nib == 0xE ) + sign = 1; + else if ( nib > 9 ) + break; + else + result = result * 10 + nib; + } + + /* read decimal part, if any */ + if ( nib == 0xa ) + for (;;) + { + /* read one nibble at a time */ + if ( !phase && ++p >= limit ) + goto Bad; + + phase = 4 - phase; + nib = ( p[0] >> phase ) & 0xF; + + if ( nib >= 10 ) + break; + + if (divider < 10000000L) + { + num = num * 10 + nib; + divider *= 10; + } + } + + /* read exponent, if any */ + if ( nib == 12 ) + { + exp_sign = 1; + nib = 11; + } + + if ( nib == 11 ) + { + exp = 0; + + for (;;) + { + /* read one nibble at a time */ + if ( !phase && ++p >= limit ) + goto Bad; + + phase = 4 - phase; + nib = ( p[0] >> phase ) & 0xF; + + if ( nib >= 10 ) + break; + + exp = exp * 10 + nib; + } + + if ( exp_sign ) + exp = -exp; + + power_ten += exp; + } + + /* raise to power of ten if needed */ + while ( power_ten > 0 ) + { + result = result * 10; + num = num * 10; + + power_ten--; + } + + while ( power_ten < 0 ) + { + result = result / 10; + divider = divider * 10; + + power_ten++; + } + + if ( num ) + result += FT_DivFix( num, divider ); + + if ( sign ) + result = -result; + + Exit: + return result; + + Bad: + result = 0; + goto Exit; + } + + + /* read a number, either integer or real */ + static + FT_Long t2_parse_num( FT_Byte** d ) + { + return ( **d == 30 ? ( parse_t2_real( d[0], d[1], 0 ) >> 16 ) + : parse_t2_integer( d[0], d[1] ) ); + } + + + /* reads a floating point number, either integer or real */ + static + FT_Fixed t2_parse_fixed( FT_Byte** d ) + { + return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) + : parse_t2_integer( d[0], d[1] ) << 16 ); + } + + + static + FT_Error parse_font_matrix( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Matrix* matrix = &dict->font_matrix; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + matrix->xx = t2_parse_fixed( data++ ); + matrix->yx = t2_parse_fixed( data++ ); + matrix->xy = t2_parse_fixed( data++ ); + matrix->yy = t2_parse_fixed( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_font_bbox( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_BBox* bbox = &dict->font_bbox; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 4 ) + { + bbox->xMin = t2_parse_num( data++ ); + bbox->yMin = t2_parse_num( data++ ); + bbox->xMax = t2_parse_num( data++ ); + bbox->yMax = t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_private_dict( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 2 ) + { + dict->private_size = t2_parse_num( data++ ); + dict->private_offset = t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + + static + FT_Error parse_cid_ros( T2_Parser* parser ) + { + CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; + FT_Byte** data = parser->stack; + FT_Error error; + + + error = T2_Err_Stack_Underflow; + + if ( parser->top >= parser->stack + 3 ) + { + dict->cid_registry = (FT_UInt)t2_parse_num( data++ ); + dict->cid_ordering = (FT_UInt)t2_parse_num( data++ ); + dict->cid_supplement = (FT_ULong)t2_parse_num( data ); + error = T2_Err_Ok; + } + + return error; + } + + +#define T2_FIELD_NUM( code, name ) \ + T2_FIELD( code, name, t2_kind_num ) +#define T2_FIELD_FIXED( code, name ) \ + T2_FIELD( code, name, t2_kind_fixed ) +#define T2_FIELD_STRING( code, name ) \ + T2_FIELD( code, name, t2_kind_string ) +#define T2_FIELD_BOOL( code, name ) \ + T2_FIELD( code, name, t2_kind_bool ) +#define T2_FIELD_DELTA( code, name,max ) \ + T2_FIELD( code, name, t2_kind_delta ) + +#define T2_REF( s, f ) ( ((s*)0)->f ) + +#define T2_FIELD_CALLBACK( code, name ) \ + { \ + t2_kind_callback, \ + code | T2CODE, \ + 0, 0, \ + parse_ ## name, \ + 0, 0 \ + }, + +#undef T2_FIELD +#define T2_FIELD( code, name, kind ) \ + { \ + kind, \ + code | T2CODE, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \ + sizeof( T2_REF( T2TYPE, name ) ), \ + 0, 0, 0 \ + }, + +#undef T2_FIELD_DELTA +#define T2_FIELD_DELTA( code, name, max ) \ + { \ + t2_kind_delta, \ + code | T2CODE, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \ + sizeof( T2_REF( T2TYPE, name )[0] ), \ + 0, \ + max, \ + (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) \ + }, + +#define T2CODE_TOPDICT 0x1000 +#define T2CODE_PRIVATE 0x2000 + + static const T2_Field_Handler t2_field_handlers[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "t2tokens.h" + +#else + +#include + +#endif + + { 0, 0, 0, 0, 0, 0, 0 } + }; + + + LOCAL_FUNC + FT_Error T2_Parser_Run( T2_Parser* parser, + FT_Byte* start, + FT_Byte* limit ) + { + FT_Byte* p = start; + FT_Error error = T2_Err_Ok; + + + parser->top = parser->stack; + parser->start = start; + parser->limit = limit; + parser->cursor = start; + + while ( p < limit ) + { + FT_Byte v = *p; + + + if ( v >= 27 && v != 31 ) + { + /* it's a number; we will push its position on the stack */ + if ( parser->top - parser->stack >= T2_MAX_STACK_DEPTH ) + goto Stack_Overflow; + + *parser->top ++ = p; + + /* now, skip it */ + if ( v == 30 ) + { + /* skip real number */ + for (;;) + { + if ( p >= limit ) + goto Syntax_Error; + v = p[0] >> 4; + if ( v == 15 ) + break; + v = p[0] & 0xF; + if ( v == 15 ) + break; + p++; + } + p++; + } + else if ( v == 28 ) + p += 2; + else if ( v == 29 ) + p += 4; + else if ( v > 246 ) + p += 1; + } + else + { + /* This is not a number, hence it's an operator. Compute its code */ + /* and look for it in our current list. */ + + FT_UInt code; + FT_UInt num_args = (FT_UInt) + ( parser->top - parser->stack ); + const T2_Field_Handler* field; + + + /* first of all, a trivial check */ + if ( num_args < 1 ) + goto Stack_Underflow; + + *parser->top = p; + code = v; + if ( v == 12 ) + { + /* two byte operator */ + p++; + code = 0x100 | p[0]; + } + code = code | parser->object_code; + + for ( field = t2_field_handlers; field->kind; field++ ) + { + if ( field->code == (FT_Int)code ) + { + /* we found our field's handler; read it */ + FT_Long val; + FT_Byte* q = (FT_Byte*)parser->object + field->offset; + + + switch ( field->kind ) + { + case t2_kind_bool: + case t2_kind_string: + case t2_kind_num: + val = t2_parse_num( parser->stack ); + goto Store_Number; + + case t2_kind_fixed: + val = t2_parse_fixed( parser->stack ); + + Store_Number: + switch ( field->size ) + { + case 1: + *(FT_Byte*)q = (FT_Byte)val; + break; + + case 2: + *(FT_Short*)q = (FT_Short)val; + break; + + case 4: + *(FT_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems where long is 8 bytes */ + *(FT_Long*)q = val; + } + break; + + case t2_kind_delta: + { + FT_Byte* qcount = (FT_Byte*)parser->object + + field->count_offset; + + FT_Long val; + FT_Byte** data = parser->stack; + + + if ( num_args > field->array_max ) + num_args = field->array_max; + + /* store count */ + *qcount = (FT_Byte)num_args; + + val = 0; + while ( num_args > 0 ) + { + val += t2_parse_num( data++ ); + switch ( field->size ) + { + case 1: + *(FT_Byte*)q = (FT_Byte)val; + break; + + case 2: + *(FT_Short*)q = (FT_Short)val; + break; + + case 4: + *(FT_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + + q += field->size; + num_args--; + } + } + break; + + default: /* callback */ + error = field->reader( parser ); + if ( error ) + goto Exit; + } + goto Found; + } + } + + /* this is an unknown operator, or it is unsupported; */ + /* we will ignore it for now. */ + + Found: + /* clear stack */ + parser->top = parser->stack; + } + p++; + } + + Exit: + return error; + + Stack_Overflow: + error = T2_Err_Invalid_Argument; + goto Exit; + + Stack_Underflow: + error = T2_Err_Invalid_Argument; + goto Exit; + + Syntax_Error: + error = T2_Err_Invalid_Argument; + goto Exit; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2parse.h b/subsys/win32k/freetype/src/cff/t2parse.h new file mode 100644 index 0000000..2238444 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2parse.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* t2parse.h */ +/* */ +/* OpenType parser (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T2PARSE_H +#define T2PARSE_H + +#include +#include + +#define T2_MAX_STACK_DEPTH 96 + +#define T2CODE_TOPDICT 0x1000 +#define T2CODE_PRIVATE 0x2000 + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T2_Parser_ + { + FT_Byte* start; + FT_Byte* limit; + FT_Byte* cursor; + + FT_Byte* stack[T2_MAX_STACK_DEPTH + 1]; + FT_Byte** top; + + FT_UInt object_code; + void* object; + + } T2_Parser; + + + LOCAL_DEF + void T2_Parser_Init( T2_Parser* parser, + FT_UInt code, + void* object ); + + LOCAL_DEF + FT_Error T2_Parser_Run( T2_Parser* parser, + FT_Byte* start, + FT_Byte* limit ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T2PARSE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cff/t2tokens.h b/subsys/win32k/freetype/src/cff/t2tokens.h new file mode 100644 index 0000000..13a15e4 --- /dev/null +++ b/subsys/win32k/freetype/src/cff/t2tokens.h @@ -0,0 +1,96 @@ +/***************************************************************************/ +/* */ +/* t2tokens.h */ +/* */ +/* OpenType token definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#undef T2TYPE +#undef T2CODE +#define T2TYPE CFF_Font_Dict +#define T2CODE T2CODE_TOPDICT + + T2_FIELD_STRING ( 0, version ) + T2_FIELD_STRING ( 1, notice ) + T2_FIELD_STRING ( 0x100, copyright ) + T2_FIELD_STRING ( 2, full_name ) + T2_FIELD_STRING ( 3, family_name ) + T2_FIELD_STRING ( 4, weight ) + T2_FIELD_BOOL ( 0x101, is_fixed_pitch ) + T2_FIELD_FIXED ( 0x102, italic_angle ) + T2_FIELD_NUM ( 0x103, underline_position ) + T2_FIELD_NUM ( 0x104, underline_thickness ) + T2_FIELD_NUM ( 0x105, paint_type ) + T2_FIELD_NUM ( 0x106, charstring_type ) + T2_FIELD_CALLBACK( 0x107, font_matrix ) + T2_FIELD_NUM ( 13, unique_id ) + T2_FIELD_CALLBACK( 5, font_bbox ) + T2_FIELD_NUM ( 0x108, stroke_width ) + T2_FIELD_NUM ( 15, charset_offset ) + T2_FIELD_NUM ( 16, encoding_offset ) + T2_FIELD_NUM ( 17, charstrings_offset ) + T2_FIELD_CALLBACK( 18, private_dict ) + T2_FIELD_NUM ( 0x114, synthetic_base ) + T2_FIELD_STRING ( 0x115, postscript ) + T2_FIELD_STRING ( 0x116, base_font_name ) + +#if 0 + T2_FIELD_DELTA ( 0x117, base_font_blend, 16 ) + T2_FIELD_CALLBACK( 0x118, multiple_master ) + T2_FIELD_CALLBACK( 0x119, blend_axit_types ) +#endif + + T2_FIELD_CALLBACK( 0x11E, cid_ros ) + T2_FIELD_NUM ( 0x11F, cid_font_version ) + T2_FIELD_NUM ( 0x120, cid_font_revision ) + T2_FIELD_NUM ( 0x121, cid_font_type ) + T2_FIELD_NUM ( 0x122, cid_count ) + T2_FIELD_NUM ( 0x123, cid_uid_base ) + T2_FIELD_NUM ( 0x124, cid_fd_array_offset ) + T2_FIELD_NUM ( 0x125, cid_fd_select_offset ) + T2_FIELD_STRING ( 0x126, cid_font_name ) + +#if 0 + T2_FIELD_NUM ( 0x127, chameleon ) +#endif + + +#undef T2TYPE +#undef T2CODE +#define T2TYPE CFF_Private +#define T2CODE T2CODE_PRIVATE + + T2_FIELD_DELTA( 6, blue_values, 14 ) + T2_FIELD_DELTA( 7, other_blues, 10 ) + T2_FIELD_DELTA( 8, family_blues, 14 ) + T2_FIELD_DELTA( 9, family_other_blues, 10 ) + T2_FIELD_FIXED( 0x109, blue_scale ) + T2_FIELD_NUM ( 0x10A, blue_shift ) + T2_FIELD_NUM ( 0x10B, blue_fuzz ) + T2_FIELD_NUM ( 10, standard_width ) + T2_FIELD_NUM ( 11, standard_height ) + T2_FIELD_DELTA( 0x10C, snap_widths, 13 ) + T2_FIELD_DELTA( 0x10D, snap_heights, 13 ) + T2_FIELD_BOOL ( 0x10E, force_bold ) + T2_FIELD_FIXED( 0x10F, force_bold_threshold ) + T2_FIELD_NUM ( 0x110, lenIV ) + T2_FIELD_NUM ( 0x111, language_group ) + T2_FIELD_FIXED( 0x112, expansion_factor ) + T2_FIELD_NUM ( 0x113, initial_random_seed ) + T2_FIELD_NUM ( 19, local_subrs_offset ) + T2_FIELD_NUM ( 20, default_width ) + T2_FIELD_NUM ( 21, nominal_width ) + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/.cvsignore b/subsys/win32k/freetype/src/cid/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/cid/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/cid/cidafm.c b/subsys/win32k/freetype/src/cid/cidafm.c new file mode 100644 index 0000000..7331485 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidafm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* cidafm.c */ +/* */ +/* AFM support for CID-keyed fonts (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidafm.h" + +#else + +#include + +#endif + + +#include +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* for isalnum() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidafm + + + LOCAL_FUNC + void CID_Done_AFM( FT_Memory memory, + CID_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#undef IS_KERN_PAIR +#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' ) + +#define IS_ALPHANUM( c ) ( isalnum( c ) || \ + c == '_' || \ + c == '.' ) + + + /* read a glyph name and return the equivalent glyph index */ + static + FT_UInt afm_atoindex( FT_Byte** start, + FT_Byte* limit, + T1_Font* type1 ) + { + FT_Byte* p = *start; + FT_Int len; + FT_UInt result = 0; + char temp[64]; + + + /* skip whitespace */ + while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) && + p < limit ) + p++; + *start = p; + + /* now, read glyph name */ + while ( IS_ALPHANUM( *p ) && p < limit ) + p++; + + len = p - *start; + + if ( len > 0 && len < 64 ) + { + FT_Int n; + + + /* copy glyph name to intermediate array */ + MEM_Copy( temp, *start, len ); + temp[len] = 0; + + /* lookup glyph name in face array */ + for ( n = 0; n < type1->num_glyphs; n++ ) + { + char* gname = (char*)type1->glyph_names[n]; + + + if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 ) + { + result = n; + break; + } + } + } + *start = p; + return result; + } + + + /* read an integer */ + static + int afm_atoi( FT_Byte** start, + FT_Byte* limit ) + { + FT_Byte* p = *start; + int sum = 0; + int sign = 1; + + + /* skip everything that is not a number */ + while ( p < limit && !isdigit( *p ) ) + { + sign = 1; + if ( *p == '-' ) + sign = -1; + + p++; + } + + while ( p < limit && isdigit( *p ) ) + { + sum = sum * 10 + ( *p - '0' ); + p++; + } + *start = p; + + return sum * sign; + } + + +#undef KERN_INDEX +#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) + + + /* compare two kerning pairs */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + CID_Kern_Pair* pair1 = (CID_Kern_Pair*)a; + CID_Kern_Pair* pair2 = (CID_Kern_Pair*)b; + + FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 ); + FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 ); + + + return ( index1 - index2 ); + } + + + /* parse an AFM file -- for now, only read the kerning pairs */ + LOCAL_FUNC + FT_Error CID_Read_AFM( FT_Face cid_face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Byte* start; + FT_Byte* limit; + FT_Byte* p; + FT_Int count = 0; + CID_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + CID_AFM* afm = 0; + + + if ( ACCESS_Frame( stream->size ) ) + return error; + + start = (FT_Byte*)stream->cursor; + limit = (FT_Byte*)stream->limit; + p = start; + + /* we are now going to count the occurrences of `KP' or `KPX' in */ + /* the AFM file. */ + count = 0; + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + count++; + } + + /* Actually, kerning pairs are simply optional! */ + if ( count == 0 ) + goto Exit; + + /* allocate the pairs */ + if ( ALLOC( afm, sizeof ( *afm ) ) || + ALLOC_ARRAY( afm->kern_pairs, count, CID_Kern_Pair ) ) + goto Exit; + + /* now, read each kern pair */ + pair = afm->kern_pairs; + afm->num_pairs = count; + + /* save in face object */ + ((T1_Face)t1_face)->afm_data = afm; + + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + { + FT_Byte* q; + + + /* skip keyword (`KP' or `KPX') */ + q = p + 2; + if ( *q == 'X' ) + q++; + + pair->glyph1 = afm_atoindex( &q, limit, type1 ); + pair->glyph2 = afm_atoindex( &q, limit, type1 ); + pair->kerning.x = afm_atoi( &q, limit ); + + pair->kerning.y = 0; + if ( p[2] != 'X' ) + pair->kerning.y = afm_atoi( &q, limit ); + + pair++; + } + } + + /* now, sort the kern pairs according to their glyph indices */ + qsort( afm->kern_pairs, count, sizeof ( CID_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void CID_Get_Kerning( CID_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + CID_Kern_Pair *min, *mid, *max; + FT_ULong index = KERN_INDEX( glyph1, glyph2 ); + + + /* simple binary search */ + min = afm->kern_pairs; + max = min + afm->num_pairs - 1; + + while ( min <= max ) + { + FT_ULong midi; + + + mid = min + ( max - min ) / 2; + midi = KERN_INDEX( mid->glyph1, mid->glyph2 ); + if ( midi == index ) + { + *kerning = mid->kerning; + return; + } + + if ( midi < index ) + min = mid + 1; + else + max = mid - 1; + } + + kerning->x = 0; + kerning->y = 0; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidafm.h b/subsys/win32k/freetype/src/cid/cidafm.h new file mode 100644 index 0000000..0bb4eb0 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidafm.h @@ -0,0 +1,78 @@ +/***************************************************************************/ +/* */ +/* cidafm.h */ +/* */ +/* AFM support for CID-keyed fonts (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef CIDAFM_H +#define CIDAFM_H + + +#ifdef FT_FLAT_COMPILE + +#include "cidobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct CID_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } CID_Kern_Pair; + + typedef struct CID_AFM_ + { + FT_UInt num_pairs; + CID_Kern_Pair* kern_pairs; + + } CID_AFM; + + + LOCAL_DEF + FT_Error CID_Read_AFM( FT_Face cid_face, + FT_Stream stream ); + + LOCAL_DEF + void CID_Done_AFM( FT_Memory memory, + CID_AFM* afm ); + + LOCAL_DEF + void CID_Get_Kerning( CID_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDAFM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidgload.c b/subsys/win32k/freetype/src/cid/cidgload.c new file mode 100644 index 0000000..f6dff4b --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidgload.c @@ -0,0 +1,1558 @@ +/***************************************************************************/ +/* */ +/* cidgload.c */ +/* */ +/* CID-keyed Type1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidload.h" +#include "cidgload.h" + +#else + +#include +#include + +#endif + + +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidgload + + + /* forward */ + static + FT_Error cid_load_glyph( CID_Decoder* decoder, + FT_UInt glyph_index ); + + + typedef enum CID_Operator_ + { + op_none = 0, + + op_endchar, + op_hsbw, + op_seac, + op_sbw, + op_closepath, + + op_hlineto, + op_hmoveto, + op_hvcurveto, + op_rlineto, + op_rmoveto, + op_rrcurveto, + op_vhcurveto, + op_vlineto, + op_vmoveto, + + op_dotsection, + + op_hstem, + op_hstem3, + op_vstem, + op_vstem3, + + op_div, + op_callothersubr, + op_callsubr, + op_pop, + op_return, + op_setcurrentpoint, + + op_max /* never remove this one */ + + } CID_Operator; + + static + const FT_Int t1_args_count[op_max] = + { + 0, /* none */ + 0, /* endchar */ + 2, /* hsbw */ + 5, /* seac */ + 4, /* sbw */ + 0, /* closepath */ + + 1, /* hlineto */ + 1, /* hmoveto */ + 4, /* hvcurveto */ + 2, /* rlineto */ + 2, /* rmoveto */ + 6, /* rrcurveto */ + 4, /* vhcurveto */ + 1, /* vlineto */ + 1, /* vmoveto */ + + 0, /* dotsection */ + + 2, /* hstem */ + 6, /* hstem3 */ + 2, /* vstem */ + 6, /* vstem3 */ + + 2, /* div */ + -1, /* callothersubr */ + 1, /* callsubr */ + 0, /* pop */ + 0, /* return */ + 2 /* setcurrentpoint */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + LOCAL_FUNC + void CID_Init_Builder( CID_Builder* builder, + CID_Face face, + CID_Size size, + CID_GlyphSlot glyph ) + { + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader* loader = glyph->root.loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; + } + + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Builder */ + /* */ + /* */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void CID_Done_Builder( CID_Builder* builder ) + { + CID_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + LOCAL_FUNC + void CID_Init_Decoder( CID_Decoder* decoder ) + { + MEM_Set( decoder, 0, sizeof ( *decoder ) ); + + decoder->font_matrix.xx = 0x10000L; + decoder->font_matrix.yy = 0x10000L; + } + + + /* check that there is enough space for `count' more points */ + static + FT_Error check_points( CID_Builder* builder, + FT_Int count ) + { + return FT_GlyphLoader_Check_Points( builder->loader, count, 0 ); + } + + + /* add a new point, but do not check space */ + static + void add_point( CID_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + + + point->x = x; + point->y = y; + *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic; + + builder->last = *point; + } + + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + static + FT_Error add_point1( CID_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = check_points( builder, 1 ); + if ( !error ) + add_point( builder, x, y, 1 ); + + return error; + } + + + /* check room for a new contour, then add it */ + static + FT_Error add_contour( CID_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return T1_Err_Ok; + } + + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + + outline->n_contours++; + } + return error; + } + + + /* if a path has been started, add its first on-curve point */ + static + FT_Error start_point( CID_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + FT_Error error; + + + builder->path_begun = 1; + error = add_contour( builder ); + if ( error ) + return error; + } + + return add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( CID_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( outline->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points - 1; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + +#if 0 + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( CID_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + + glyph_name = psnames->adobe_std_strings( + psnames->adobe_std_encoding[charcode]); + + for ( n = 0; n < face->cid.cid_count; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* decoder :: The current CID decoder. */ + /* */ + /* asb :: The accent's side bearing. */ + /* */ + /* adx :: The horizontal offset of the accent. */ + /* */ + /* ady :: The vertical offset of the accent. */ + /* */ + /* bchar :: The base character's StandardEncoding charcode. */ + /* */ + /* achar :: The accent character's StandardEncoding charcode. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( CID_Decoder* decoder, + FT_Pos asb, + FT_Pos adx, + FT_Pos ady, + FT_Int bchar, + FT_Int achar ) + { + FT_Error error; + FT_Int bchar_index, achar_index, n_base_points; + FT_Outline* base = decoder->builder.base; + FT_Vector left_bearing, advance; + + + bchar_index = bchar; + achar_index = achar; + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_Err_Syntax_Error; + } + + /* if we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if ( decoder->builder.no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; + FT_GlyphLoader* loader = glyph->loader; + FT_SubGlyph* subg; + + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_Check_Subglyphs( loader, 2 ); + if ( error ) + goto Exit; + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = adx - asb; + subg->arg2 = ady; + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->current.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + if ( decoder->builder.loader ) + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + error = cid_load_glyph( decoder, bchar_index ); /* load one glyph */ + if ( error ) + goto Exit; + + n_base_points = base->n_points; + + { + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load. */ + + left_bearing = decoder->builder.left_bearing; + advance = decoder->builder.advance; + + decoder->builder.left_bearing.x = 0; + decoder->builder.left_bearing.y = 0; + + /* Now load `achar' on top of */ + /* the base outline */ + error = cid_load_glyph( decoder, achar_index ); + if ( error ) + return error; + + /* restore the left side bearing and */ + /* advance width of the base character */ + + decoder->builder.left_bearing = left_bearing; + decoder->builder.advance = advance; + + /* Finally, move the accent */ + if ( decoder->builder.load_points ) + { + FT_Outline dummy; + + + dummy.n_points = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + } + + Exit: + return error; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given CID charstrings program. */ + /* */ + /* */ + /* decoder :: The current CID decoder. */ + /* */ + /* */ + /* charstring_base :: The base of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Parse_CharStrings( CID_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ) + { + FT_Error error; + CID_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + CID_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + + + /* First of all, initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + + builder->path_begun = 0; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = T1_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + CID_Operator op = op_none; + FT_Long value = 0; + + + /********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + + /* First of all, decompress operator or value */ + switch ( *ip++ ) + { + case 1: + op = op_hstem; + break; + + case 3: + op = op_vstem; + break; + case 4: + op = op_vmoveto; + break; + case 5: + op = op_rlineto; + break; + case 6: + op = op_hlineto; + break; + case 7: + op = op_vlineto; + break; + case 8: + op = op_rrcurveto; + break; + case 9: + op = op_closepath; + break; + case 10: + op = op_callsubr; + break; + case 11: + op = op_return; + break; + + case 13: + op = op_hsbw; + break; + case 14: + op = op_endchar; + break; + + case 21: + op = op_rmoveto; + break; + case 22: + op = op_hmoveto; + break; + + case 30: + op = op_vhcurveto; + break; + case 31: + op = op_hvcurveto; + break; + + case 12: + if ( ip > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+EOF)\n" )); + goto Syntax_Error; + } + + switch ( *ip++ ) + { + case 0: + op = op_dotsection; + break; + case 1: + op = op_vstem3; + break; + case 2: + op = op_hstem3; + break; + case 6: + op = op_seac; + break; + case 7: + op = op_sbw; + break; + case 12: + op = op_div; + break; + case 16: + op = op_callothersubr; + break; + case 17: + op = op_pop; + break; + case 33: + op = op_setcurrentpoint; + break; + + default: + FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (long)ip[0] << 24 ) | + ( (long)ip[1] << 16 ) | + ( (long)ip[2] << 8 ) | + ip[3]; + ip += 4; + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (long)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ( (long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + else + value = -( ( ( (long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "CID_Parse_CharStrings: invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /********************************************************************/ + /* */ + /* Push value on stack, or process operator */ + /* */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "CID_Parse_CharStrings: Stack overflow!\n" )); + goto Syntax_Error; + } + + FT_TRACE4(( " %ld", value )); + *top++ = value; + decoder->top = top; + } + else if ( op == op_callothersubr ) /* callothersubr */ + { + FT_TRACE4(( " callothersubr" )); + + if ( top - decoder->stack < 2 ) + goto Stack_Underflow; + + top -= 2; + switch ( top[1] ) + { + case 1: /* start flex feature ---------------------- */ + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + if ( start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Memory_Error; + break; + + case 2: /* add flex vectors ------------------------ */ + { + FT_Int index; + + + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + /* note that we should not add a point for index 0. */ + /* this will move our current position to the flex */ + /* point without adding any point to the outline */ + index = decoder->num_flex_vectors++; + if ( index > 0 && index < 7 ) + add_point( builder, + x, + y, + (FT_Byte)( index==3 || index==6 ) ); + } + break; + + case 0: /* end flex feature ------------------------- */ + if ( top[0] != 3 ) + goto Unexpected_OtherSubr; + + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "CID_Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + /* now consume the remaining `pop pop setcurpoint' */ + if ( ip + 6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */ + { + FT_ERROR(( "CID_Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + ip += 6; + decoder->flex_state = 0; + break; + + case 3: /* change hints ---------------------------- */ + if ( top[0] != 1 ) + goto Unexpected_OtherSubr; + + /* eat the following `pop' */ + if ( ip + 2 > limit ) + { + FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " `pop' expected, found (%d %d)\n", + ip[0], ip[1] )); + goto Syntax_Error; + } + ip += 2; + break; + + case 12: + case 13: + /* counter control hints, clear stack */ + top = decoder->stack; + break; + +#if 0 + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + T1_Blend* blend = decoder->blend; + FT_UInt num_points, nn, mm; + FT_Int* delta; + FT_Int* values; + + + if ( !blend ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected multiple masters operator!\n" )); + goto Syntax_Error; + } + + num_points = top[1] - 13 + ( top[1] == 18 ); + if ( top[0] != num_points * blend->num_designs ) + { + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " incorrect number of mm arguments\n" )); + goto Syntax_Error; + } + + top -= blend->num_designs * num_points; + if ( top < decoder->stack ) + goto Stack_Underflow; + + /* We want to compute: */ + /* */ + /* a0*w0 + a1*w1 + ... + ak*wk */ + /* */ + /* but we only have the a0, a1-a0, a2-a0, .. ak-a0. */ + /* However, given that w0 + w1 + ... + wk == 1, we can */ + /* rewrite it easily as: */ + /* */ + /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */ + /* */ + /* where k == num_designs-1 */ + /* */ + /* I guess that's why it's written in this `compact' */ + /* form... */ + /* */ + delta = top + num_points; + values = top; + for ( nn = 0; nn < num_points; nn++ ) + { + FT_Int x = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + x += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = x; + } + /* note that `top' will be incremented later by calls to `pop' */ + } + break; + +#endif + + default: + Unexpected_OtherSubr: + FT_ERROR(( "CID_Parse_CharStrings: invalid othersubr [%d %d]!\n", + top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else /* general operator */ + { + FT_Int num_args = t1_args_count[op]; + + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch ( op ) + { + case op_endchar: + FT_TRACE4(( " endchar" )); + + close_contour( builder ); + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + + /* return now! */ + FT_TRACE4(( "\n\n" )); + return T1_Err_Ok; + + case op_hsbw: + FT_TRACE4(( " hsbw" )); + + builder->left_bearing.x += top[0]; + builder->advance.x = top[1]; + builder->advance.y = 0; + + builder->last.x = x = top[0]; + builder->last.y = y = 0; + + /* The `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it. So exit immediately. */ + if ( builder->metrics_only ) + return T1_Err_Ok; + + break; + + case op_seac: + /* return immediately after processing */ + return t1operator_seac( decoder, top[0], top[1], + top[2], top[3], top[4] ); + + case op_sbw: + FT_TRACE4(( " sbw" )); + + builder->left_bearing.x += top[0]; + builder->left_bearing.y += top[1]; + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + builder->last.x = x = top[0]; + builder->last.y = y = top[1]; + + /* The `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it. So exit immediately. */ + if ( builder->metrics_only ) + return T1_Err_Ok; + + break; + + case op_closepath: + FT_TRACE4(( " closepath" )); + + close_contour( builder ); + builder->path_begun = 0; + break; + + case op_hlineto: + FT_TRACE4(( " hlineto" )); + + if ( start_point( builder, x, y ) ) + goto Memory_Error; + + x += top[0]; + goto Add_Line; + + case op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + x += top[0]; + break; + + case op_hvcurveto: + FT_TRACE4(( " hvcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Memory_Error; + + x += top[0]; + add_point( builder, x, y, 0 ); + + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + + y += top[3]; + add_point( builder, x, y, 1 ); + + break; + + case op_rlineto: + FT_TRACE4(( " rlineto" )); + + if ( start_point( builder, x, y ) ) + goto Memory_Error; + + x += top[0]; + y += top[1]; + + Add_Line: + if ( add_point1( builder, x, y ) ) + goto Memory_Error; + break; + + case op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + x += top[0]; + y += top[1]; + break; + + case op_rrcurveto: + FT_TRACE4(( " rcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Memory_Error; + + x += top[0]; + y += top[1]; + add_point( builder, x, y, 0 ); + + x += top[2]; + y += top[3]; + add_point( builder, x, y, 0 ); + + x += top[4]; + y += top[5]; + add_point( builder, x, y, 1 ); + + break; + + case op_vhcurveto: + FT_TRACE4(( " vhcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Memory_Error; + + y += top[0]; + add_point( builder, x, y, 0 ); + + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + + x += top[3]; + add_point( builder, x, y, 1 ); + + break; + + case op_vlineto: + FT_TRACE4(( " vlineto" )); + + if ( start_point( builder, x, y ) ) + goto Memory_Error; + + y += top[0]; + goto Add_Line; + + case op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + y += top[0]; + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + top++; + } + else + { + FT_ERROR(( "CID_Parse_CharStrings: division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + FT_Int index; + + + FT_TRACE4(( " callsubr" )); + + index = top[0]; + if ( index < 0 || index >= (FT_Int)decoder->subrs->num_subrs ) + { + FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = decoder->subrs->code[index] + decoder->lenIV; + zone->limit = decoder->subrs->code[index + 1]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "CID_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case op_pop: + FT_TRACE4(( " pop" )); + + /* theoretically, the arguments are already on the stack */ + top++; + break; + + case op_return: + FT_TRACE4(( " return" )); + + if ( zone <= decoder->zones ) + { + FT_ERROR(( "CID_Parse_CharStrings: unexpected return\n" )); + goto Syntax_Error; + } + + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + + break; + + case op_dotsection: + FT_TRACE4(( " dotsection" )); + + break; + + case op_hstem: + FT_TRACE4(( " hstem" )); + + break; + + case op_hstem3: + FT_TRACE4(( " hstem3" )); + + break; + + case op_vstem: + FT_TRACE4(( " vstem" )); + + break; + + case op_vstem3: + FT_TRACE4(( " vstem3" )); + + break; + + case op_setcurrentpoint: + FT_TRACE4(( " setcurrentpoint" )); + + FT_ERROR(( "CID_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "CID_Parse_CharStrings: unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + decoder->top = top; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + + Memory_Error: + return builder->error; + } + + +#if 0 + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error CID_Compute_Max_Advance( CID_Face face, + FT_Int* max_advance ) + { + FT_Error error; + CID_Decoder decoder; + FT_Int glyph_index; + + + *max_advance = 0; + + /* Initialize load decoder */ + CID_Init_Decoder( &decoder ); + CID_Init_Builder( &decoder.builder, face, 0, 0 ); + + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + /* for each glyph, parse the glyph charstring and extract */ + /* the advance width */ + for ( glyph_index = 0; glyph_index < face->root.num_glyphs; + glyph_index++ ) + { + /* now get load the unscaled outline */ + error = cid_load_glyph( &decoder, glyph_index ); + /* ignore the error if one occurred - skip to next glyph */ + } + + *max_advance = decoder.builder.advance.x; + + return T1_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error cid_load_glyph( CID_Decoder* decoder, + FT_UInt glyph_index ) + { + CID_Face face = decoder->builder.face; + CID_Info* cid = &face->cid; + FT_Byte* p; + FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes; + FT_UInt fd_select; + FT_ULong off1, glyph_len; + FT_Stream stream = face->root.stream; + FT_Error error = 0; + + + /* read the CID font dict index and charstring offset from the CIDMap */ + if ( FILE_Seek( cid->data_offset + cid->cidmap_offset + + glyph_index * entry_len) || + ACCESS_Frame( 2 * entry_len ) ) + goto Exit; + + p = (FT_Byte*)stream->cursor; + fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); + off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); + p += cid->fd_bytes; + glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; + + FORGET_Frame(); + + /* now, if the glyph is not empty, set up the subrs array, and parse */ + /* the charstrings */ + if ( glyph_len > 0 ) + { + CID_FontDict* dict; + FT_Byte* charstring; + FT_UInt lenIV; + FT_Memory memory = face->root.memory; + + + /* setup subrs */ + decoder->subrs = face->subrs + fd_select; + + /* setup font matrix */ + dict = cid->font_dicts + fd_select; + decoder->font_matrix = dict->font_matrix; + lenIV = dict->private_dict.lenIV; + decoder->lenIV = lenIV; + + /* the charstrings are encoded (stupid!) */ + /* load the charstrings, then execute it */ + + if ( ALLOC( charstring, glyph_len ) ) + goto Exit; + + if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) ) + { + cid_decrypt( charstring, glyph_len, 4330 ); + error = CID_Parse_CharStrings( decoder, + charstring + lenIV, + glyph_len - lenIV ); + } + + FREE( charstring ); + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error CID_Load_Glyph( CID_GlyphSlot glyph, + CID_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + CID_Decoder decoder; + CID_Face face = (CID_Face)glyph->root.face; + FT_Bool hinting; + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; + + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; + + { + CID_Init_Decoder( &decoder ); + CID_Init_Builder( &decoder.builder, face, size, glyph ); + + /* set up the decoder */ + decoder.builder.no_recurse = + (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); + + error = cid_load_glyph( &decoder, glyph_index ); + + /* save new glyph tables */ + CID_Done_Builder( &decoder.builder ); + } + + /* Now, set the metrics - this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax. */ + if ( !error ) + { + /* for composite glyphs, return only the left side bearing and the */ + /* advance width */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags &= ft_outline_owner; + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + +#if 0 + glyph->root.outline.second_pass = TRUE; + glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24; + glyph->root.outline.dropout_mode = 2; +#endif + + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = &glyph->root.outline; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points */ + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* Then scale the metrics */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + } + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix ); + + /* compute the other metrics */ + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax + 63 ) & -64; + cbox.yMax = ( cbox.yMax + 63 ) & -64; + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + } + } + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidgload.h b/subsys/win32k/freetype/src/cid/cidgload.h new file mode 100644 index 0000000..2784242 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidgload.h @@ -0,0 +1,198 @@ +/***************************************************************************/ +/* */ +/* cidgload.h */ +/* */ +/* OpenType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef CIDGLOAD_H +#define CIDGLOAD_H + + +#ifdef FT_FLAT_COMPILE + +#include "cidobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* max_points :: maximum points in builder outline */ + /* */ + /* max_contours :: Maximal number of contours in builder outline. */ + /* */ + /* last :: The last point position. */ + /* */ + /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ + /* */ + /* scale_y :: The vertical scale (FUnits to sub-pixels). */ + /* */ + /* pos_x :: The horizontal translation (if composite glyph). */ + /* */ + /* pos_y :: The vertical translation (if composite glyph). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* bbox :: Unused. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: If this flag is not set, no points are loaded. */ + /* */ + /* no_recurse :: Set but not used. */ + /* */ + /* error :: An error code that is only used to report memory */ + /* allocation problems. */ + /* */ + /* metrics_only :: A boolean indicating that we only want to compute */ + /* the metrics of a given glyph, not load all of its */ + /* points. */ + /* */ + typedef struct CID_Builder_ + { + FT_Memory memory; + CID_Face face; + CID_GlyphSlot glyph; + FT_GlyphLoader* loader; + FT_Outline* base; + FT_Outline* current; + + FT_Vector last; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + FT_Bool no_recurse; + + FT_Error error; /* only used for memory errors */ + FT_Bool metrics_only; + + } CID_Builder; + + + /* execution context charstring zone */ + + typedef struct CID_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } CID_Decoder_Zone; + + + typedef struct CID_Decoder_ + { + CID_Builder builder; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + CID_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + CID_Decoder_Zone* zone; + + FT_Matrix font_matrix; + CID_Subrs* subrs; + FT_UInt lenIV; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + } CID_Decoder; + + + LOCAL_DEF + void CID_Init_Builder( CID_Builder* builder, + CID_Face face, + CID_Size size, + CID_GlyphSlot glyph ); + + LOCAL_DEF + void CID_Done_Builder( CID_Builder* builder ); + + + LOCAL_DEF + void CID_Init_Decoder( CID_Decoder* decoder ); + + +#if 0 + + /* Compute the maximum advance width of a font through quick parsing */ + LOCAL_DEF + FT_Error CID_Compute_Max_Advance( CID_Face face, + FT_Int* max_advance ); + +#endif + + /* This function is exported, because it is used by the T1Dump utility */ + LOCAL_DEF + FT_Error CID_Parse_CharStrings( CID_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len ); + + LOCAL_DEF + FT_Error CID_Load_Glyph( CID_GlyphSlot glyph, + CID_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDGLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidload.c b/subsys/win32k/freetype/src/cid/cidload.c new file mode 100644 index 0000000..729dbc9 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidload.c @@ -0,0 +1,537 @@ +/***************************************************************************/ +/* */ +/* cidload.c */ +/* */ +/* CID-keyed Type1 font loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidload.h" + +#else + +#include + +#endif + + +#include +#include /* for isspace(), isalnum() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidload + + + /* read a single offset */ + LOCAL_FUNC + FT_Long cid_get_offset( FT_Byte** start, + FT_Byte offsize ) + { + FT_Long result; + FT_Byte* p = *start; + + + for ( result = 0; offsize > 0; offsize-- ) + { + result <<= 8; + result |= *p++; + } + + *start = p; + return result; + } + + + LOCAL_FUNC + void cid_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error cid_load_keyword( CID_Face face, + CID_Loader* loader, + const CID_Field_Rec* keyword ) + { + FT_Error error; + CID_Parser* parser = &loader->parser; + FT_Byte* object; + CID_Info* cid = &face->cid; + + + /* if the keyword has a dedicated callback, call it */ + if ( keyword->type == t1_field_callback ) + { + error = keyword->reader( face, parser ); + goto Exit; + } + + /* we must now compute the address of our target object */ + switch ( keyword->location ) + { + case t1_field_cid_info: + object = (FT_Byte*)cid; + break; + + case t1_field_font_info: + object = (FT_Byte*)&cid->font_info; + break; + + default: + { + CID_FontDict* dict; + + + if ( parser->num_dict < 0 ) + { + FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n", + keyword->ident )); + error = T1_Err_Syntax_Error; + goto Exit; + } + + dict = cid->font_dicts + parser->num_dict; + switch ( keyword->location ) + { + case t1_field_private: + object = (FT_Byte*)&dict->private_dict; + break; + + default: + object = (FT_Byte*)dict; + } + } + } + + /* now, load the keyword data in the object's field(s) */ + if ( keyword->type == t1_field_integer_array || + keyword->type == t1_field_fixed_array ) + error = CID_Load_Field_Table( parser, keyword, object ); + else + error = CID_Load_Field( parser, keyword, object ); + + Exit: + return error; + } + + + static + FT_Error parse_font_bbox( CID_Face face, + CID_Parser* parser ) + { + FT_Short temp[4]; + FT_BBox* bbox = &face->cid.font_bbox; + + + (void)CID_ToCoordArray( parser, 4, temp ); + bbox->xMin = temp[0]; + bbox->yMin = temp[1]; + bbox->xMax = temp[2]; + bbox->yMax = temp[3]; + + return T1_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + static + FT_Error parse_font_matrix( CID_Face face, + CID_Parser* parser ) + { + FT_Matrix* matrix; + CID_FontDict* dict; + FT_Fixed temp[4]; + + + if ( parser->num_dict >= 0 ) + { + dict = face->cid.font_dicts + parser->num_dict; + matrix = &dict->font_matrix; + + (void)CID_ToFixedArray( parser, 4, temp, 3 ); + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + } + + return T1_Err_Ok; /* this is a callback function; */ + /* we must return an error code */ + } + + + static + FT_Error parse_fd_array( CID_Face face, + CID_Parser* parser ) + { + CID_Info* cid = &face->cid; + FT_Memory memory = face->root.memory; + FT_Error error = T1_Err_Ok; + FT_Long num_dicts; + + + num_dicts = CID_ToInt( parser ); + + if ( !cid->font_dicts ) + { + FT_Int n; + + + if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) ) + goto Exit; + + cid->num_dicts = (FT_UInt)num_dicts; + + /* don't forget to set a few defaults */ + for ( n = 0; n < cid->num_dicts; n++ ) + { + CID_FontDict* dict = cid->font_dicts + n; + + + /* default value for lenIV */ + dict->private_dict.lenIV = 4; + } + } + + Exit: + return error; + } + + + static + const CID_Field_Rec t1_field_records[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "cidtokens.h" + +#else + +#include + +#endif + + { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 } + }; + + + static + int is_alpha( char c ) + { + return ( isalnum( c ) || + c == '.' || + c == '_' ); + } + + + static + void skip_whitespace( CID_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + + while ( cur < parser->limit && isspace( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + FT_Error parse_dict( CID_Face face, + CID_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + CID_Parser* parser = &loader->parser; + + + parser->cursor = base; + parser->limit = base + size; + parser->error = 0; + + { + FT_Byte* cur = base; + FT_Byte* limit = cur + size; + + + for ( ;cur < limit; cur++ ) + { + /* look for `%ADOBeginFontDict' */ + if ( *cur == '%' && cur + 20 < limit && + strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 ) + { + cur += 17; + + /* if /FDArray was found, then cid->num_dicts is > 0, and */ + /* we can start increasing parser->num_dict */ + if ( face->cid.num_dicts > 0 ) + parser->num_dict++; + } + /* look for immediates */ + else if ( *cur == '/' && cur + 2 < limit ) + { + FT_Byte* cur2; + FT_Int len; + + + cur++; + + cur2 = cur; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur; + if ( len > 0 && len < 22 ) + { + /* now compare the immediate name to the keyword table */ + const CID_Field_Rec* keyword = t1_field_records; + + + for (;;) + { + FT_Byte* name; + + + name = (FT_Byte*)keyword->ident; + if ( !name ) + break; + + if ( cur[0] == name[0] && + len == (FT_Int)strlen( (const char*)name ) ) + { + FT_Int n; + + + for ( n = 1; n < len; n++ ) + if ( cur[n] != name[n] ) + break; + + if ( n >= len ) + { + /* we found it - run the parsing callback */ + parser->cursor = cur2; + skip_whitespace( parser ); + parser->error = cid_load_keyword( face, loader, keyword ); + if ( parser->error ) + return parser->error; + + cur = parser->cursor; + break; + } + } + keyword++; + } + } + } + } + } + return parser->error; + } + + + /* read the subrmap and the subrs of each font dict */ + static + FT_Error cid_read_subrs( CID_Face face ) + { + CID_Info* cid = &face->cid; + FT_Memory memory = face->root.memory; + FT_Stream stream = face->root.stream; + FT_Error error; + FT_Int n; + CID_Subrs* subr; + FT_UInt max_offsets = 0; + FT_ULong* offsets = 0; + + + if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) ) + goto Exit; + + subr = face->subrs; + for ( n = 0; n < cid->num_dicts; n++, subr++ ) + { + CID_FontDict* dict = cid->font_dicts + n; + FT_UInt count, num_subrs = dict->num_subrs; + FT_ULong data_len; + FT_Byte* p; + + + /* reallocate offsets array if needed */ + if ( num_subrs + 1 > max_offsets ) + { + FT_UInt new_max = ( num_subrs + 1 + 3 ) & -4; + + + if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) ) + goto Fail; + + max_offsets = new_max; + } + + /* read the subrmap's offsets */ + if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) || + ACCESS_Frame( ( num_subrs + 1 ) * dict->sd_bytes ) ) + goto Fail; + + p = (FT_Byte*)stream->cursor; + for ( count = 0; count <= num_subrs; count++ ) + offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes ); + + FORGET_Frame(); + + /* now, compute the size of subrs charstrings, */ + /* allocate, and read them */ + data_len = offsets[num_subrs] - offsets[0]; + + if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) || + ALLOC( subr->code[0], data_len ) ) + goto Fail; + + if ( FILE_Seek( cid->data_offset + offsets[0] ) || + FILE_Read( subr->code[0], data_len ) ) + goto Exit; + + /* set up pointers */ + for ( count = 1; count <= num_subrs; count++ ) + { + FT_UInt len; + + + len = offsets[count] - offsets[count - 1]; + subr->code[count] = subr->code[count - 1] + len; + } + + /* decrypt subroutines */ + for ( count = 0; count < num_subrs; count++ ) + { + FT_UInt len; + + + len = offsets[count + 1] - offsets[count]; + cid_decrypt( subr->code[count], len, 4330 ); + } + + subr->num_subrs = num_subrs; + } + + Exit: + FREE( offsets ); + return error; + + Fail: + if ( face->subrs ) + { + for ( n = 0; n < cid->num_dicts; n++ ) + { + if ( face->subrs[n].code ) + FREE( face->subrs[n].code[0] ); + + FREE( face->subrs[n].code ); + } + FREE( face->subrs ); + } + goto Exit; + } + + + static + void t1_init_loader( CID_Loader* loader, + CID_Face face ) + { + FT_UNUSED( face ); + + MEM_Set( loader, 0, sizeof ( *loader ) ); + } + + + static + void t1_done_loader( CID_Loader* loader ) + { + CID_Parser* parser = &loader->parser; + + + /* finalize parser */ + CID_Done_Parser( parser ); + } + + + LOCAL_FUNC + FT_Error CID_Open_Face( CID_Face face ) + { + CID_Loader loader; + CID_Parser* parser; + FT_Error error; + + + t1_init_loader( &loader, face ); + + parser = &loader.parser; + error = CID_New_Parser( parser, face->root.stream, face->root.memory ); + if ( error ) + goto Exit; + + error = parse_dict( face, &loader, + parser->postscript, + parser->postscript_len ); + if ( error ) + goto Exit; + + face->cid.data_offset = loader.parser.data_offset; + error = cid_read_subrs( face ); + + Exit: + t1_done_loader( &loader ); + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidload.h b/subsys/win32k/freetype/src/cid/cidload.h new file mode 100644 index 0000000..d3b6445 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidload.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* cidload.h */ +/* */ +/* CID-keyed Type1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef CIDLOAD_H +#define CIDLOAD_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct CID_Loader_ + { + CID_Parser parser; /* parser used to read the stream */ + FT_Int num_chars; /* number of characters in encoding */ + + } CID_Loader; + + + LOCAL_DEF + FT_Long cid_get_offset( FT_Byte** start, + FT_Byte offsize ); + + LOCAL_DEF + void cid_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + LOCAL_DEF + FT_Error CID_Open_Face( CID_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidobjs.c b/subsys/win32k/freetype/src/cid/cidobjs.c new file mode 100644 index 0000000..818daa1 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidobjs.c @@ -0,0 +1,380 @@ +/***************************************************************************/ +/* */ +/* cidobjs.c */ +/* */ +/* CID objects manager (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidgload.h" +#include "cidload.h" + +#else + +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidobjs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void CID_Done_Face( CID_Face face ) + { + FT_Memory memory; + + + if ( face ) + { + CID_Info* cid = &face->cid; + T1_FontInfo* info = &cid->font_info; + + + memory = face->root.memory; + + /* release FontInfo strings */ + FREE( info->version ); + FREE( info->notice ); + FREE( info->full_name ); + FREE( info->family_name ); + FREE( info->weight ); + + /* release font dictionaries */ + FREE( cid->font_dicts ); + cid->num_dicts = 0; + + /* release other strings */ + FREE( cid->cid_font_name ); + FREE( cid->registry ); + FREE( cid->ordering ); + + face->root.family_name = 0; + face->root.style_name = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Face */ + /* */ + /* */ + /* Initializes a given CID face object. */ + /* */ + /* */ + /* stream :: The source font stream. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Init_Face( FT_Stream stream, + CID_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + PSNames_Interface* psnames; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( stream ); + + + face->root.num_faces = 1; + + psnames = (PSNames_Interface*)face->psnames; + if ( !psnames ) + { + psnames = (PSNames_Interface*)FT_Get_Module_Interface( + FT_FACE_LIBRARY( face ), "psnames" ); + + face->psnames = psnames; + } + + /* open the tokenizer; this will also check the font format */ + if ( FILE_Seek( 0 ) ) + goto Exit; + + error = CID_Open_Face( face ); + if ( error ) + goto Exit; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Exit; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "CID_Init_Face: invalid face index\n" )); + error = T1_Err_Invalid_Argument; + goto Exit; + } + + /* Now, load the font program into the face object */ + { + /* Init the face object fields */ + /* Now set up root face fields */ + { + FT_Face root = (FT_Face)&face->root; + + + root->num_glyphs = face->cid.cid_count; + root->num_charmaps = 0; + + root->face_index = face_index; + root->face_flags = FT_FACE_FLAG_SCALABLE; + + root->face_flags |= FT_FACE_FLAG_HORIZONTAL; + + if ( face->cid.font_info.is_fixed_pitch ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: TODO: add kerning with .afm support */ + + /* get style name -- be careful, some broken fonts only */ + /* have a /FontName dictionary entry! */ + root->family_name = face->cid.font_info.family_name; + if ( root->family_name ) + { + char* full = face->cid.font_info.full_name; + char* family = root->family_name; + + while ( *family && *full == *family ) + { + family++; + full++; + } + + root->style_name = ( *full == ' ' ) ? full + 1 + : (char *)"Regular"; + } + else + { + /* do we have a `/FontName'? */ + if ( face->cid.cid_font_name ) + { + root->family_name = face->cid.cid_font_name; + root->style_name = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->cid.font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)face->cid.font_bbox.yMax; + root->descender = -(FT_Short)face->cid.font_bbox.yMin; + root->height = ( ( root->ascender + root->descender ) * 12 ) + / 10; + + +#if 0 + + /* now compute the maximum advance width */ + + root->max_advance_width = face->type1.private_dict.standard_width[0]; + + /* compute max advance width for proportional fonts */ + if ( !face->type1.font_info.is_fixed_pitch ) + { + FT_Int max_advance; + + + error = CID_Compute_Max_Advance( face, &max_advance ); + + /* in case of error, keep the standard width */ + if ( !error ) + root->max_advance_width = max_advance; + else + error = 0; /* clear error */ + } + + root->max_advance_height = root->height; + +#endif /* 0 */ + + root->underline_position = face->cid.font_info.underline_position; + root->underline_thickness = face->cid.font_info.underline_thickness; + + root->max_points = 0; + root->max_contours = 0; + } + } + +#if 0 + + /* charmap support - synthetize unicode charmap when possible */ + { + FT_Face root = &face->root; + FT_CharMap charmap = face->charmaprecs; + + + /* synthesize a Unicode charmap if there is support in the `psnames' */ + /* module */ + if ( face->psnames ) + { + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + + if ( psnames->unicode_value ) + { + error = psnames->build_unicodes( + root->memory, + face->type1.num_glyphs, + (const char**)face->type1.glyph_names, + &face->unicode_map ); + if ( !error ) + { + root->charmap = charmap; + charmap->face = (FT_Face)face; + charmap->encoding = ft_encoding_unicode; + charmap->platform_id = 3; + charmap->encoding_id = 1; + charmap++; + } + + /* simply clear the error in case of failure (which really */ + /* means that out of memory or no unicode glyph names) */ + error = 0; + } + } + + /* now, support either the standard, expert, or custom encodings */ + charmap->face = (FT_Face)face; + charmap->platform_id = 7; /* a new platform id for Adobe fonts? */ + + switch ( face->type1.encoding_type ) + { + case t1_encoding_standard: + charmap->encoding = ft_encoding_adobe_standard; + charmap->encoding_id = 0; + break; + + case t1_encoding_expert: + charmap->encoding = ft_encoding_adobe_expert; + charmap->encoding_id = 1; + break; + + default: + charmap->encoding = ft_encoding_adobe_custom; + charmap->encoding_id = 2; + break; + } + + root->charmaps = face->charmaps; + root->num_charmaps = charmap - face->charmaprecs + 1; + face->charmaps[0] = &face->charmaprecs[0]; + face->charmaps[1] = &face->charmaprecs[1]; + } + +#endif /* 0 */ + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Init_Driver */ + /* */ + /* */ + /* Initializes a given CID driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_Init_Driver( CID_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Driver */ + /* */ + /* */ + /* Finalizes a given CID driver. */ + /* */ + /* */ + /* driver :: A handle to the target CID driver. */ + /* */ + LOCAL_DEF + void CID_Done_Driver( CID_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidobjs.h b/subsys/win32k/freetype/src/cid/cidobjs.h new file mode 100644 index 0000000..c28c59b --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidobjs.h @@ -0,0 +1,141 @@ +/***************************************************************************/ +/* */ +/* cidobjs.h */ +/* */ +/* CID objects manager (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef CIDOBJS_H +#define CIDOBJS_H + +#include +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* The following structures must be defined by the hinter */ + typedef struct CID_Size_Hints_ CID_Size_Hints; + typedef struct CID_Glyph_Hints_ CID_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct CID_DriverRec_* CID_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct CID_SizeRec_* CID_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct CID_GlyphSlotRec_* CID_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* CID_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* The Type 1 format doesn't use a charmap but an encoding table. */ + /* The driver is responsible for making up charmap objects */ + /* corresponding to these tables. */ + /* */ + typedef struct CID_CharMapRec_* CID_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE 1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + typedef struct CID_SizeRec_ + { + FT_SizeRec root; + FT_Bool valid; + + } CID_SizeRec; + + + typedef struct CID_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + } CID_GlyphSlotRec; + + + LOCAL_DEF + FT_Error CID_Init_Face( FT_Stream stream, + CID_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void CID_Done_Face( CID_Face face ); + + + LOCAL_DEF + FT_Error CID_Init_Driver( CID_Driver driver ); + + LOCAL_DEF + void CID_Done_Driver( CID_Driver driver ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDOBJS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidparse.c b/subsys/win32k/freetype/src/cid/cidparse.c new file mode 100644 index 0000000..02f36b1 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidparse.c @@ -0,0 +1,1024 @@ +/***************************************************************************/ +/* */ +/* cidparse.c */ +/* */ +/* CID-keyed Type1 parser (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.h" + +#else + +#include + +#endif + + +#include /* for strncmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_cidparse + + +#if 0 + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMPLEMENTATION OF CID_TABLE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_New_Table */ + /* */ + /* */ + /* Initializes a CID_Table. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size, i.e., the maximal number of elements. */ + /* */ + /* memory :: The memory object to be used for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error CID_New_Table( CID_Table* table, + FT_Int count, + FT_Memory memory ) + { + FT_Error error; + + + table->memory = memory; + if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) || + ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) + goto Exit; + + table->max_elems = count; + table->init = 0xDEADBEEFL; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + Exit: + if ( error ) + FREE( table->elements ); + + return error; + } + + + static + void shift_elements( CID_Table* table, + FT_Byte* old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static + FT_Error reallocate_t1_table( CID_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* realloc the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + + table->capacity = new_size; + + /* shift all offsets when needed */ + if ( old_base ) + shift_elements( table, old_base ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Add_Table */ + /* */ + /* */ + /* Adds an object to a CID_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* index :: The index of the object in the table. */ + /* */ + /* object :: The address of the object to copy in the memory. */ + /* */ + /* length :: The length in bytes of the source object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if */ + /* reallocation fails. */ + /* */ + LOCAL_FUNC + FT_Error CID_Add_Table( CID_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "CID_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* add the object to the base block and adjust offset */ + table->elements[index] = table->block + table->cursor; + table->lengths [index] = length; + + MEM_Copy( table->block + table->cursor, object, length ); + + table->cursor += length; + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Done_Table */ + /* */ + /* */ + /* Finalizes a CID_Table (reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* This function does NOT release the heap's memory block. It is up */ + /* to the caller to clean it, or reference it in its own structures. */ + /* */ + LOCAL_FUNC + void CID_Done_Table( CID_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + shift_elements( table, old_base ); + } + + + LOCAL_FUNC + void CID_Release_Table( CID_Table* table ) + { + FT_Memory memory = table->memory; + + + if ( table->init == 0xDEADBEEFL ) + { + FREE( table->block ); + FREE( table->elements ); + FREE( table->lengths ); + table->init = 0; + } + } + +#endif /* 0 */ + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define IS_CID_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_CID_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) + +#define IS_CID_SPACE( c ) ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) ) + + + LOCAL_FUNC + void CID_Skip_Spaces( CID_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( !IS_CID_SPACE( c ) ) + break; + cur++; + } + + parser->cursor = cur; + } + + + LOCAL_FUNC + void CID_ToToken( CID_Parser* parser, + CID_Token_Rec* token ) + { + FT_Byte* cur; + FT_Byte* limit; + FT_Byte starter, ender; + FT_Int embed; + + + token->type = t1_token_none; + token->start = 0; + token->limit = 0; + + /* first of all, skip space */ + CID_Skip_Spaces( parser ); + + cur = parser->cursor; + limit = parser->limit; + + if ( cur < limit ) + { + switch ( *cur ) + { + /************* check for strings ***********************/ + case '(': + token->type = t1_token_string; + ender = ')'; + goto Lookup_Ender; + + /************* check for programs/array ****************/ + case '{': + token->type = t1_token_array; + ender = '}'; + goto Lookup_Ender; + + /************* check for table/array ******************/ + case '[': + token->type = t1_token_array; + ender = ']'; + + Lookup_Ender: + embed = 1; + starter = *cur++; + token->start = cur; + + while ( cur < limit ) + { + if ( *cur == starter ) + embed++; + else if ( *cur == ender ) + { + embed--; + if ( embed <= 0 ) + { + token->limit = cur++; + break; + } + } + cur++; + } + break; + + /* **************** otherwise, it is any token **********/ + default: + token->start = cur++; + token->type = t1_token_any; + while ( cur < limit && !IS_CID_SPACE( *cur ) ) + cur++; + + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = t1_token_none; + } + + parser->cursor = cur; + } + } + + + LOCAL_FUNC + void CID_ToTokenArray( CID_Parser* parser, + CID_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + CID_Token_Rec master; + + + *pnum_tokens = -1; + + CID_ToToken( parser, &master ); + + if ( master.type == t1_token_array ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + CID_Token_Rec* cur = tokens; + CID_Token_Rec* limit = cur + max_tokens; + + + parser->cursor = master.start; + parser->limit = master.limit; + + while ( parser->cursor < parser->limit ) + { + CID_Token_Rec token; + + + CID_ToToken( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = cur - tokens; + + parser->cursor = old_cursor; + parser->limit = old_limit; + } + } + + + static + FT_Long t1_toint( FT_Byte** cursor, + FT_Byte* limit ) + { + FT_Long result = 0; + FT_Byte* cur = *cursor; + FT_Byte c, d; + + + for ( ; cur < limit; cur++ ) + { + c = *cur; + d = (FT_Byte)( c - '0' ); + if ( d < 10 ) + break; + + if ( c == '-' ) + { + cur++; + break; + } + } + + if ( cur < limit ) + { + do + { + d = (FT_Byte)( cur[0] - '0' ); + if ( d >= 10 ) + break; + + result = result * 10 + d; + cur++; + + } while ( cur < limit ); + + if ( c == '-' ) + result = -result; + } + + *cursor = cur; + + return result; + } + + + static + FT_Long t1_tofixed( FT_Byte** cursor, + FT_Byte* limit, + FT_Long power_ten ) + { + FT_Byte* cur = *cursor; + FT_Long num, divider, result; + FT_Int sign = 0; + FT_Byte d; + + + if ( cur >= limit ) + return 0; + + /* first of all, read the integer part */ + result = t1_toint( &cur, limit ) << 16; + num = 0; + divider = 1; + + if ( result < 0 ) + { + sign = 1; + result = -result; + } + + if ( cur >= limit ) + goto Exit; + + /* read decimal part, if any */ + if ( *cur == '.' && cur + 1 < limit ) + { + cur++; + + for (;;) + { + d = (FT_Byte)( *cur - '0' ); + if ( d >= 10 ) + break; + + if ( divider < 10000000L ) + { + num = num * 10 + d; + divider *= 10; + } + + cur++; + if ( cur >= limit ) + break; + } + } + + /* read exponent, if any */ + if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) ) + { + cur++; + power_ten += t1_toint( &cur, limit ); + } + + Exit: + /* raise to power of ten if needed */ + while ( power_ten > 0 ) + { + result = result * 10; + num = num * 10; + power_ten--; + } + + while ( power_ten < 0 ) + { + result = result / 10; + divider = divider * 10; + power_ten++; + } + + if ( num ) + result += FT_DivFix( num, divider ); + + if ( sign ) + result = -result; + + *cursor = cur; + + return result; + } + + + static + int t1_tobool( FT_Byte** cursor, + FT_Byte* limit ) + { + FT_Byte* cur = *cursor; + FT_Bool result = 0; + + + /* return 1 if we find a "true", 0 otherwise */ + if ( cur + 3 < limit && + cur[0] == 't' && + cur[1] == 'r' && + cur[2] == 'u' && + cur[3] == 'e' ) + { + result = 1; + cur += 5; + } + else if ( cur + 4 < limit && + cur[0] == 'f' && + cur[1] == 'a' && + cur[2] == 'l' && + cur[3] == 's' && + cur[4] == 'e' ) + { + result = 0; + cur += 6; + } + *cursor = cur; + return result; + } + + + static + FT_Int t1_tocoordarray( FT_Byte** cursor, + FT_Byte* limit, + FT_Int max_coords, + FT_Short* coords ) + { + FT_Byte* cur = *cursor; + FT_Int count = 0; + FT_Byte c, ender; + + + if ( cur >= limit ) + goto Exit; + + /* check for the beginning of an array. */ + /* If not, only one number will be read */ + c = *cur; + ender = 0; + + if ( c == '[' ) + ender = ']'; + + if ( c == '{' ) + ender = '}'; + + if ( ender ) + cur++; + + /* now, read the coordinates */ + for ( ; cur < limit; ) + { + /* skip whitespace in front of data */ + for (;;) + { + c = *cur; + if ( c != ' ' && c != '\t' ) + break; + + cur++; + if ( cur >= limit ) + goto Exit; + } + + if ( count >= max_coords || c == ender ) + break; + + coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 ); + count++; + + if ( !ender ) + break; + } + + Exit: + *cursor = cur; + return count; + } + + + static + FT_Int t1_tofixedarray( FT_Byte** cursor, + FT_Byte* limit, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ) + { + FT_Byte* cur = *cursor; + FT_Int count = 0; + FT_Byte c, ender; + + + if ( cur >= limit ) + goto Exit; + + /* check for the beginning of an array. */ + /* If not, only one number will be read */ + c = *cur; + ender = 0; + + if ( c == '[' ) + ender = ']'; + + if ( c == '{' ) + ender = '}'; + + if ( ender ) + cur++; + + /* now, read the values */ + for ( ; cur < limit; ) + { + /* skip whitespace in front of data */ + for (;;) + { + c = *cur; + if ( c != ' ' && c != '\t' ) + break; + + cur++; + if ( cur >= limit ) + goto Exit; + } + + if ( count >= max_values || c == ender ) + break; + + values[count] = t1_tofixed( &cur, limit, power_ten ); + count++; + + if ( !ender ) + break; + } + + Exit: + *cursor = cur; + + return count; + } + + + /* Loads a simple field (i.e. non-table) into the current */ + /* list of objects */ + LOCAL_FUNC + FT_Error CID_Load_Field( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ) + { + CID_Token_Rec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt index; + FT_Error error; + + + CID_ToToken( parser, &token ); + if ( !token.type ) + goto Fail; + + count = 1; + index = 0; + cur = token.start; + limit = token.limit; + + { + FT_Byte* q = (FT_Byte*)object + field->offset; + FT_Long val; + FT_String* string; + + + switch ( field->type ) + { + case t1_field_bool: + val = t1_tobool( &cur, limit ); + goto Store_Integer; + + case t1_field_fixed: + val = t1_tofixed( &cur, limit, 0 ); + goto Store_Integer; + + case t1_field_integer: + val = t1_toint( &cur, limit ); + + Store_Integer: + switch ( field->size ) + { + case 1: + *(FT_Byte*)q = (FT_Byte)val; + break; + + case 2: + *(FT_UShort*)q = (FT_UShort)val; + break; + + case 4: + *(FT_Int32*)q = (FT_Int)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + break; + + case t1_field_string: + { + FT_Memory memory = parser->memory; + FT_UInt len = limit-cur; + + + if ( ALLOC( string, len + 1 ) ) + goto Exit; + + MEM_Copy( string, cur, len ); + string[len] = 0; + + *(FT_String**)q = string; + } + break; + + default: + /* an error occurred */ + goto Fail; + } + } + + error = 0; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + LOCAL_FUNC + FT_Error CID_Load_Field_Table( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ) + { + CID_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; + CID_Token_Rec* token; + FT_Int num_elements; + FT_Error error = 0; + FT_Byte* old_cursor; + FT_Byte* old_limit; + CID_Field_Rec fieldrec = *(CID_Field_Rec*)field; + + + fieldrec.type = t1_field_integer; + if ( field->type == t1_field_fixed_array ) + fieldrec.type = t1_field_fixed; + + CID_ToTokenArray( parser, elements, 32, &num_elements ); + if ( num_elements < 0 ) + goto Fail; + + if ( num_elements > T1_MAX_TABLE_ELEMENTS ) + num_elements = T1_MAX_TABLE_ELEMENTS; + + old_cursor = parser->cursor; + old_limit = parser->limit; + + /* we store the elements count */ + if ( field->count_offset ) + *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = num_elements; + + /* we now load each element, adjusting the field.offset on each one */ + token = elements; + for ( ; num_elements > 0; num_elements--, token++ ) + { + parser->cursor = token->start; + parser->limit = token->limit; + CID_Load_Field( parser, &fieldrec, object ); + fieldrec.offset += fieldrec.size; + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + LOCAL_FUNC + FT_Long CID_ToInt( CID_Parser* parser ) + { + return t1_toint( &parser->cursor, parser->limit ); + } + + + LOCAL_FUNC + FT_Int CID_ToCoordArray( CID_Parser* parser, + FT_Int max_coords, + FT_Short* coords ) + { + return t1_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + LOCAL_FUNC + FT_Int CID_ToFixedArray( CID_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ) + { + return t1_tofixedarray( &parser->cursor, parser->limit, + max_values, values, power_ten ); + } + + +#if 0 + + /* return the value of an hexadecimal digit */ + static + int hexa_value( char c ) + { + unsigned int d; + + + d = (unsigned int)( c - '0' ); + if ( d <= 9 ) + return (int)d; + + d = (unsigned int)( c - 'a' ); + if ( d <= 5 ) + return (int)( d + 10 ); + + d = (unsigned int)( c - 'A' ); + if ( d <= 5 ) + return (int)( d + 10 ); + + return -1; + } + +#endif /* 0 */ + + + LOCAL_FUNC + FT_Error CID_New_Parser( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory ) + { + FT_Error error; + FT_ULong base_offset, offset, ps_len; + FT_Byte buffer[256 + 10]; + FT_Int buff_len; + + + MEM_Set( parser, 0, sizeof ( *parser ) ); + parser->stream = stream; + parser->memory = memory; + + base_offset = FILE_Pos(); + + /* first of all, check the font format in the header */ + if ( ACCESS_Frame( 31 ) ) + goto Exit; + + if ( strncmp( (char *)stream->cursor, + "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) + { + FT_TRACE2(( "[not a valid CID-keyed font]\n" )); + error = FT_Err_Unknown_File_Format; + } + + FORGET_Frame(); + if ( error ) + goto Exit; + + /* now, read the rest of the file, until we find a `StartData' */ + buff_len = 256; + for (;;) + { + FT_Byte *p, *limit = buffer + 256; + + /* fill input buffer */ + buff_len -= 256; + if ( buff_len > 0 ) + MEM_Move( buffer, limit, buff_len ); + + if ( FILE_Read( buffer, 256 + 10 - buff_len ) ) + goto Exit; + + buff_len = 256 + 10; + + /* look for `StartData' */ + for ( p = buffer; p < limit; p++ ) + { + if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 ) + { + /* save offset of binary data after `StartData' */ + offset = FILE_Pos() - ( limit - p ) + 10; + goto Found; + } + } + } + + Found: + /* we have found the start of the binary data. We will now */ + /* rewind and extract the frame of corresponding to the Postscript */ + /* section */ + + ps_len = offset - base_offset; + if ( FILE_Seek( base_offset ) || + EXTRACT_Frame( ps_len, parser->postscript ) ) + goto Exit; + + parser->data_offset = offset; + parser->postscript_len = ps_len; + parser->cursor = parser->postscript; + parser->limit = parser->cursor + ps_len; + parser->num_dict = -1; + + Exit: + return error; + } + + + LOCAL_FUNC + void CID_Done_Parser( CID_Parser* parser ) + { + /* always free the private dictionary */ + if ( parser->postscript ) + { + FT_Stream stream = parser->stream; + + + RELEASE_Frame( parser->postscript ); + } + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidparse.h b/subsys/win32k/freetype/src/cid/cidparse.h new file mode 100644 index 0000000..7a8211a --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidparse.h @@ -0,0 +1,353 @@ +/***************************************************************************/ +/* */ +/* cidparse.h */ +/* */ +/* CID-keyed Type1 parser (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef CIDPARSE_H +#define CIDPARSE_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* CID_Table */ + /* */ + /* */ + /* A CID_Table is a simple object used to store an array of objects */ + /* in a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to the use */ + /* of `realloc()'. */ + /* */ + /* cursor :: The current top of the growheap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments by */ + /* blocks of 1 kByte. */ + /* */ + /* init :: A boolean. Set when the table has been initialized */ + /* (the table user should set this field). */ + /* */ + /* max_elems :: The maximal number of elements in the table. */ + /* */ + /* num_elems :: The current number of elements (in use) in the table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The memory object used for memory operations */ + /* (allocation resp. reallocation). */ + /* */ + typedef struct CID_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int capacity; /* current size of memory block */ + FT_Long init; + + FT_Int max_elems; + FT_Int num_elems; + FT_Byte** elements; /* addresses of table elements */ + FT_Int* lengths; /* lengths of table elements */ + + FT_Memory memory; + + } CID_Table; + + + LOCAL_DEF + FT_Error CID_New_Table( CID_Table* table, + FT_Int count, + CID_Memory memory ); + + LOCAL_DEF + FT_Error CID_Add_Table( CID_Table* table, + FT_Int index, + void* object, + FT_Int length ); + + LOCAL_DEF + void CID_Release_Table( CID_Table* table ); + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* CID_Parser */ + /* */ + /* */ + /* A CID_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* postscript :: A pointer to the data to be parsed. */ + /* */ + /* postscript_len :: The length of the data to be parsed. */ + /* */ + /* data_offset :: The start position of the binary data (i.e., the */ + /* end of the data to be parsed. */ + /* */ + /* cursor :: The current parser cursor. */ + /* */ + /* limit :: The current parser limit (i.e., the first byte */ + /* after the current dictionary). */ + /* */ + /* error :: The current parsing error. */ + /* */ + /* cid :: A structure which holds the information about */ + /* the current font. */ + /* */ + /* num_dict :: The number of font dictionaries. */ + /* */ + typedef struct CID_Parser_ + { + FT_Stream stream; + FT_Memory memory; + + FT_Byte* postscript; + FT_Int postscript_len; + + FT_ULong data_offset; + + FT_Byte* cursor; + FT_Byte* limit; + FT_Error error; + + CID_Info* cid; + FT_Int num_dict; + + } CID_Parser; + + + LOCAL_DEF + FT_Error CID_New_Parser( CID_Parser* parser, + FT_Stream stream, + FT_Memory memory ); + + LOCAL_DEF + void CID_Done_Parser( CID_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* PARSING ROUTINES */ + /* */ + /*************************************************************************/ + + LOCAL_DEF + FT_Long CID_ToInt( CID_Parser* parser ); + + LOCAL_DEF + FT_Int CID_ToCoordArray( CID_Parser* parser, + FT_Int max_coords, + FT_Short* coords ); + + LOCAL_DEF + FT_Int CID_ToFixedArray( CID_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + + LOCAL_DEF + void CID_Skip_Spaces( CID_Parser* parser ); + + + /* simple enumeration type used to identify token types */ + typedef enum CID_Token_Type_ + { + t1_token_none = 0, + t1_token_any, + t1_token_string, + t1_token_array, + + /* do not remove */ + t1_token_max + + } CID_Token_Type; + + + /* a simple structure used to identify tokens */ + typedef struct CID_Token_Rec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + CID_Token_Type type; /* type of token */ + + } CID_Token_Rec; + + + LOCAL_DEF + void CID_ToToken( CID_Parser* parser, + CID_Token_Rec* token ); + + + /* enumeration type used to identify object fields */ + typedef enum CID_Field_Type_ + { + t1_field_none = 0, + t1_field_bool, + t1_field_integer, + t1_field_fixed, + t1_field_string, + t1_field_integer_array, + t1_field_fixed_array, + t1_field_callback, + + /* do not remove */ + t1_field_max + + } CID_Field_Type; + + typedef enum CID_Field_Location_ + { + t1_field_cid_info, + t1_field_font_dict, + t1_field_font_info, + t1_field_private, + + /* do not remove */ + t1_field_location_max + + } CID_Field_Location; + + + typedef FT_Error (*CID_Field_Parser)( CID_Face face, + CID_Parser* parser ); + + /* structure type used to model object fields */ + typedef struct CID_Field_Rec_ + { + const char* ident; /* field identifier */ + CID_Field_Location location; + CID_Field_Type type; /* type of field */ + CID_Field_Parser reader; + FT_UInt offset; /* offset of field in object */ + FT_UInt size; /* size of field in bytes */ + FT_UInt array_max; /* maximal number of elements for */ + /* array */ + FT_UInt count_offset; /* offset of element count for */ + /* arrays */ + } CID_Field_Rec; + + +#define CID_FIELD_REF( s, f ) ( ((s*)0)->f ) + +#define CID_NEW_SIMPLE_FIELD( _ident, _type, _fname ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname ) ), \ + 0, 0 \ + }, + +#define CID_NEW_CALLBACK_FIELD( _ident, _reader ) \ + { \ + _ident, T1CODE, t1_field_callback, \ + _reader, \ + 0, 0, \ + 0, 0 \ + }, + +#define CID_NEW_TABLE_FIELD( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \ + _max, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, num_ ## _fname ) \ + }, + +#define CID_NEW_TABLE_FIELD2( _ident, _type, _fname, _max ) \ + { \ + _ident, T1CODE, _type, \ + 0, \ + (FT_UInt)(char*)&CID_FIELD_REF( T1TYPE, _fname ), \ + sizeof ( CID_FIELD_REF( T1TYPE, _fname )[0] ), \ + _max, 0 \ + }, + + +#define CID_FIELD_BOOL( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_bool, _fname ) + +#define CID_FIELD_NUM( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_integer, _fname ) + +#define CID_FIELD_FIXED( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_fixed, _fname ) + +#define CID_FIELD_STRING( _ident, _fname ) \ + CID_NEW_SIMPLE_FIELD( _ident, t1_field_string, _fname ) + +#define CID_FIELD_NUM_TABLE( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD( _ident, t1_field_integer_array, \ + _fname, _fmax ) + +#define CID_FIELD_FIXED_TABLE( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD( _ident, t1_field_fixed_array, \ + _fname, _fmax ) + +#define CID_FIELD_NUM_TABLE2( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD2( _ident, t1_field_integer_array, \ + _fname, _fmax ) + +#define CID_FIELD_FIXED_TABLE2( _ident, _fname, _fmax ) \ + CID_NEW_TABLE_FIELD2( _ident, t1_field_fixed_array, \ + _fname, _fmax ) + +#define CID_FIELD_CALLBACK( _ident, _name ) \ + CID_NEW_CALLBACK_FIELD( _ident, parse_ ## _name ) + + + LOCAL_DEF + FT_Error CID_Load_Field( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ); + + LOCAL_DEF + FT_Error CID_Load_Field_Table( CID_Parser* parser, + const CID_Field_Rec* field, + void* object ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* CIDPARSE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidriver.c b/subsys/win32k/freetype/src/cid/cidriver.c new file mode 100644 index 0000000..0f2bdff --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidriver.c @@ -0,0 +1,259 @@ +/***************************************************************************/ +/* */ +/* cidriver.c */ +/* */ +/* CID driver interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "cidriver.h" +#include "cidgload.h" + +#else + +#include +#include + +#endif + + +#include +#include +#include + +#include /* for strcmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ciddriver + + + static + FT_Module_Interface CID_Get_Interface( FT_Driver driver, + const FT_String* interface ) + { + FT_UNUSED( driver ); + FT_UNUSED( interface ); + + return 0; + } + + +#if 0 /* unimplemented yet */ + + static + FT_Error cid_Get_Kerning( T1_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + CID_AFM* afm; + + + kerning->x = 0; + kerning->y = 0; + + afm = (CID_AFM*)face->afm_data; + if ( afm ) + CID_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } + + +#endif /* 0 */ + + + /*************************************************************************/ + /* */ + /* */ + /* Cid_Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt CID_Get_Char_Index( FT_CharMap charmap, + FT_Long charcode ) + { + T1_Face face; + FT_UInt result = 0; + PSNames_Interface* psnames; + + + face = (T1_Face)charmap->face; + psnames = (PSNames_Interface*)face->psnames; + if ( psnames ) + switch ( charmap->encoding ) + { + /*******************************************************************/ + /* */ + /* Unicode encoding support */ + /* */ + case ft_encoding_unicode: + /* use the `PSNames' module to synthetize the Unicode charmap */ + result = psnames->lookup_unicode( &face->unicode_map, + (FT_ULong)charcode ); + + /* the function returns 0xFFFF if the Unicode charcode has */ + /* no corresponding glyph. */ + if ( result == 0xFFFF ) + result = 0; + goto Exit; + + /*******************************************************************/ + /* */ + /* Custom Type 1 encoding */ + /* */ + case ft_encoding_adobe_custom: + { + T1_Encoding* encoding = &face->type1.encoding; + + + if ( charcode >= encoding->code_first && + charcode <= encoding->code_last ) + result = encoding->char_index[charcode]; + goto Exit; + } + + /*******************************************************************/ + /* */ + /* Adobe Standard & Expert encoding support */ + /* */ + default: + if ( charcode < 256 ) + { + FT_UInt code; + FT_Int n; + const char* glyph_name; + + + code = psnames->adobe_std_encoding[charcode]; + if ( charmap->encoding == ft_encoding_adobe_expert ) + code = psnames->adobe_expert_encoding[charcode]; + + glyph_name = psnames->adobe_std_strings( code ); + if ( !glyph_name ) + break; + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + + if ( gname && gname[0] == glyph_name[0] && + strcmp( gname, glyph_name ) == 0 ) + { + result = n; + break; + } + } + } + } + + Exit: + return result; + } + + + const FT_Driver_Class t1cid_driver_class = + { + /* first of all, the FT_Module_Class fields */ + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( FT_DriverRec ), + "t1cid", /* module name */ + 0x10000L, /* version 1.0 of driver */ + 0x20000L, /* requires FreeType 2.0 */ + + 0, + + (FT_Module_Constructor)CID_Init_Driver, + (FT_Module_Destructor) CID_Done_Driver, + (FT_Module_Requester) CID_Get_Interface + }, + + /* then the other font drivers fields */ + sizeof( CID_FaceRec ), + sizeof( CID_SizeRec ), + sizeof( CID_GlyphSlotRec ), + + (FTDriver_initFace) CID_Init_Face, + (FTDriver_doneFace) CID_Done_Face, + + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes)0, + + (FTDriver_loadGlyph) CID_Load_Glyph, + (FTDriver_getCharIndex) CID_Get_Char_Index, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverClass */ + /* */ + /* */ + /* This function is used when compiling the TrueType driver as a */ + /* shared library (`.DLL' or `.so'). It will be used by the */ + /* high-level library of FreeType to retrieve the address of the */ + /* driver's generic interface. */ + /* */ + /* It shouldn't be implemented in a static build, as each driver must */ + /* have the same function as an exported entry point. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void ) + { + return &t1cid_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidriver.h b/subsys/win32k/freetype/src/cid/cidriver.h new file mode 100644 index 0000000..a9674ee --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidriver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* cidriver.h */ +/* */ +/* High-level CID driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef CIDRIVER_H +#define CIDRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) t1cid_driver_class; + +#endif /* CIDRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/cidtokens.h b/subsys/win32k/freetype/src/cid/cidtokens.h new file mode 100644 index 0000000..a916cea --- /dev/null +++ b/subsys/win32k/freetype/src/cid/cidtokens.h @@ -0,0 +1,99 @@ +/***************************************************************************/ +/* */ +/* cidtokens.h */ +/* */ +/* CID token definitions (specification only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE CID_Info +#define T1CODE t1_field_cid_info + + CID_FIELD_STRING ( "CIDFontName", cid_font_name ) + CID_FIELD_NUM ( "CIDFontVersion", cid_version ) + CID_FIELD_NUM ( "CIDFontType", cid_font_type ) + CID_FIELD_STRING ( "Registry", registry ) + CID_FIELD_STRING ( "Ordering", ordering ) + CID_FIELD_NUM ( "Supplement", supplement ) + CID_FIELD_CALLBACK( "FontBBox", font_bbox ) + CID_FIELD_NUM ( "UIDBase", uid_base ) + CID_FIELD_CALLBACK( "FDArray", fd_array ) + CID_FIELD_NUM ( "CIDMapOffset", cidmap_offset ) + CID_FIELD_NUM ( "FDBytes", fd_bytes ) + CID_FIELD_NUM ( "GDBytes", gd_bytes ) + CID_FIELD_NUM ( "CIDCount", cid_count ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE T1_FontInfo +#define T1CODE t1_field_font_info + + CID_FIELD_STRING( "version", version ) + CID_FIELD_STRING( "Notice", notice ) + CID_FIELD_STRING( "FullName", full_name ) + CID_FIELD_STRING( "FamilyName", family_name ) + CID_FIELD_STRING( "Weight", weight ) + CID_FIELD_FIXED ( "ItalicAngle", italic_angle ) + CID_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch ) + CID_FIELD_NUM ( "UnderlinePosition", underline_position ) + CID_FIELD_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE CID_FontDict +#define T1CODE t1_field_font_dict + + CID_FIELD_CALLBACK( "FontMatrix", font_matrix ) + CID_FIELD_NUM ( "PaintType", paint_type ) + CID_FIELD_NUM ( "FontType", font_type ) + CID_FIELD_NUM ( "SubrMapOffset", subrmap_offset ) + CID_FIELD_NUM ( "SDBytes", sd_bytes ) + CID_FIELD_NUM ( "SubrCount", num_subrs ) + CID_FIELD_NUM ( "lenBuildCharArray", len_buildchar ) + CID_FIELD_FIXED ( "ForceBoldThreshold", forcebold_threshold ) + CID_FIELD_FIXED ( "ExpansionFactor", expansion_factor ) + CID_FIELD_NUM ( "StrokeWidth", stroke_width ) + + +#undef T1TYPE +#undef T1CODE +#define T1TYPE T1_Private +#define T1CODE t1_field_private + + CID_FIELD_NUM ( "UniqueID", unique_id ) + CID_FIELD_NUM ( "lenIV", lenIV ) + CID_FIELD_NUM ( "LanguageGroup", language_group ) + CID_FIELD_NUM ( "password", password ) + + CID_FIELD_FIXED ( "BlueScale", blue_scale ) + CID_FIELD_NUM ( "BlueShift", blue_shift ) + CID_FIELD_NUM ( "BlueFuzz", blue_fuzz ) + + CID_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 ) + CID_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 ) + CID_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 ) + CID_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 ) + + CID_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 ) + CID_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 ) + CID_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + CID_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 ) + CID_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 ) + + +/* END */ diff --git a/subsys/win32k/freetype/src/cid/module.mk b/subsys/win32k/freetype/src/cid/module.mk new file mode 100644 index 0000000..3d13c9c --- /dev/null +++ b/subsys/win32k/freetype/src/cid/module.mk @@ -0,0 +1,6 @@ +make_module_list: add_type1cid_driver + +add_type1cid_driver: + $(OPEN_DRIVER)t1cid_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)cid $(ECHO_DRIVER_DESC)Postscript CID-keyed fonts, no known extension$(ECHO_DRIVER_DONE) +# EOF diff --git a/subsys/win32k/freetype/src/cid/rules.mk b/subsys/win32k/freetype/src/cid/rules.mk new file mode 100644 index 0000000..cbaaec7 --- /dev/null +++ b/subsys/win32k/freetype/src/cid/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 CID driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# CID driver directory +# +CID_DIR := $(SRC_)cid +CID_DIR_ := $(CID_DIR)$(SEP) + + +CID_COMPILE := $(FT_COMPILE) + + +# CID driver sources (i.e., C files) +# +CID_DRV_SRC := $(CID_DIR_)cidparse.c \ + $(CID_DIR_)cidload.c \ + $(CID_DIR_)cidriver.c \ + $(CID_DIR_)cidgload.c \ + $(CID_DIR_)cidobjs.c + +# CID driver headers +# +CID_DRV_H := $(CID_DRV_SRC:%.c=%.h) \ + $(CID_DIR_)cidtokens.h + + +# CID driver object(s) +# +# CID_DRV_OBJ_M is used during `multi' builds +# CID_DRV_OBJ_S is used during `single' builds +# +CID_DRV_OBJ_M := $(CID_DRV_SRC:$(CID_DIR_)%.c=$(OBJ_)%.$O) +CID_DRV_OBJ_S := $(OBJ_)type1cid.$O + +# CID driver source file for single build +# +CID_DRV_SRC_S := $(CID_DIR_)type1cid.c + + +# CID driver - single object +# +$(CID_DRV_OBJ_S): $(CID_DRV_SRC_S) $(CID_DRV_SRC) $(FREETYPE_H) $(CID_DRV_H) + $(CID_COMPILE) $T$@ $(CID_DRV_SRC_S) + + +# CID driver - multiple objects +# +$(OBJ_)%.$O: $(CID_DIR_)%.c $(FREETYPE_H) $(CID_DRV_H) + $(CID_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(CID_DRV_OBJ_S) +DRV_OBJS_M += $(CID_DRV_OBJ_M) + +# EOF diff --git a/subsys/win32k/freetype/src/cid/type1cid.c b/subsys/win32k/freetype/src/cid/type1cid.c new file mode 100644 index 0000000..5f69c6a --- /dev/null +++ b/subsys/win32k/freetype/src/cid/type1cid.c @@ -0,0 +1,40 @@ +/***************************************************************************/ +/* */ +/* cff.c */ +/* */ +/* FreeType OpenType driver component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#ifdef FT_FLAT_COMPILE + +#include "cidparse.c" +#include "cidload.c" +#include "cidobjs.c" +#include "cidriver.c" +#include "cidgload.c" + +#else + +#include +#include +#include +#include +#include + +#endif + + +/* END */ diff --git a/subsys/win32k/freetype/src/macfond/.cvsignore b/subsys/win32k/freetype/src/macfond/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/macfond/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/macfond/fonddrvr.c b/subsys/win32k/freetype/src/macfond/fonddrvr.c new file mode 100644 index 0000000..45a9141 --- /dev/null +++ b/subsys/win32k/freetype/src/macfond/fonddrvr.c @@ -0,0 +1,616 @@ +/***************************************************************************/ +/* */ +/* fonddrvr.c */ +/* */ +/* Mac FOND font driver. Written by just@letterror.com. */ +/* */ +/* Copyright 1996-2000 by */ +/* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +/* + Notes + + Mac suitcase files can (and often do!) contain multiple fonts. To + support this I use the face_index argument of FT_(Open|New)_Face() + functions, and pretend the suitcase file is a collection. + Warning: although the FOND driver sets face->num_faces field to the + number of available fonts, but the Type 1 driver sets it to 1 anyway. + So this field is currently not reliable, and I don't see a clean way + to resolve that. The face_index argument translates to + Get1IndResource( 'FOND', face_index + 1 ); + so clients should figure out the resource index of the FOND. + (I'll try to provide some example code for this at some point.) + + The Mac FOND driver works roughly like this: + + - Check whether the offered stream points to a Mac suitcase file. + This is done by checking the file type: it has to be 'FFIL' or 'tfil'. + The stream that gets passed to our init_face() routine is a stdio + stream, which isn't usable for us, since the FOND resources live + in the resource fork. So we just grab the stream->pathname field. + + - Read the FOND resource into memory, then check whether there is + a TrueType font and/or (!) a Type 1 font available. + + - If there is a Type 1 font available (as a separate 'LWFN' file), + read its data into memory, massage it slightly so it becomes + PFB data, wrap it into a memory stream, load the Type 1 driver + and delegate the rest of the work to it, by calling the init_face() + method of the Type 1 driver. + (XXX TODO: after this has been done, the kerning data from the FOND + resource should be appended to the face: on the Mac there are usually + no AFM files available. However, this is tricky since we need to map + Mac char codes to ps glyph names to glyph ID's...) + + - If there is a TrueType font (an 'sfnt' resource), read it into + memory, wrap it into a memory stream, load the TrueType driver + and delegate the rest of the work to it, by calling the init_face() + method if the TrueType driver. + + - In both cases, the original stream gets closed and *reinitialized* + to become a memory stream. Additionally, the face->driver field -- + which is set to the FOND driver upon entering our init_face() -- + gets *reset* to either the TT or the T1 driver. I had to make a minor + change to ftobjs.c to make this work. + + - We might consider creating an FT_New_Face_Mac() API call, as this + would avoid some of the mess described above. +*/ + +#include +#include + +#include +#include +#include + +#include /* for isupper() and isalnum() */ +#include /* for malloc() and free() */ + + +/* set PREFER_LWFN to 1 if LWFN (Type 1) is preferred over + TrueType in case *both* are available */ +#ifndef PREFER_LWFN +#define PREFER_LWFN 1 +#endif + + + static + FT_Error init_driver( FT_Driver driver ) + { + /* we don't keep no stinkin' state ;-) */ + return FT_Err_Ok; + } + + static + FT_Error done_driver( FT_Driver driver ) + { + return FT_Err_Ok; + } + + + /* MacRoman glyph names, needed for FOND kerning support. */ + /* XXX which is not implemented yet! */ + static const char* mac_roman_glyph_names[256] = { + ".null", + }; + + + /* The FOND face object is just a union of TT and T1: both is possible, + and we don't need anything else. We still need to be able to hold + either, as the face object is not allocated by us. Again, creating + an FT_New_Face_Mac() would avoid this kludge. */ + typedef union FOND_FaceRec_ + { + TT_FaceRec tt; + T1_FaceRec t1; + } FOND_FaceRec, *FOND_Face; + + + /* given a pathname, fill in a File Spec */ + static + int make_file_spec( char* pathname, FSSpec *spec ) + { + Str255 p_path; + int path_len; + + /* convert path to a pascal string */ + path_len = strlen( pathname ); + if ( path_len > 255 ) + return -1; + p_path[0] = path_len; + strncpy( (char*)p_path+1, pathname, path_len ); + + if ( FSMakeFSSpec( 0, 0, p_path, spec ) != noErr ) + return -1; + else + return 0; + } + + + /* is_suitcase() returns true if the file specified by 'pathname' + is a Mac suitcase file, and false if it ain't. */ + static + int is_suitcase( FSSpec *spec ) + { + FInfo finfo; + + if ( FSpGetFInfo( spec, &finfo ) != noErr ) + return 0; + if ( finfo.fdType == 'FFIL' || finfo.fdType == 'tfil' ) + return 1; + else + return 0; + } + + + /* Quick 'n' Dirty Pascal string to C string converter. + Warning: this call is not thread safe! Use with caution. */ + static + char * p2c_str( unsigned char *pstr ) + { + static char cstr[256]; + + strncpy( cstr, (char*)pstr+1, pstr[0] ); + cstr[pstr[0]] = '\0'; + return cstr; + } + + + /* Given a PostScript font name, create the Macintosh LWFN file name */ + static + void create_lwfn_name( char* ps_name, Str255 lwfn_file_name ) + { + int max = 5, count = 0; + unsigned char* p = lwfn_file_name; + char* q = ps_name; + + lwfn_file_name[0] = 0; + + while ( *q ) + { + if ( isupper(*q) ) + { + if ( count ) + max = 3; + count = 0; + } + if ( count < max && (isalnum(*q) || *q == '_' ) ) + { + *++p = *q; + lwfn_file_name[0]++; + count++; + } + q++; + } + } + + + /* Suck the relevant info out of the FOND data */ + static + FT_Error parse_fond( char* fond_data, + short *have_sfnt, + short *sfnt_id, + Str255 lwfn_file_name ) + { + AsscEntry* assoc; + FamRec* fond; + + *sfnt_id = *have_sfnt = 0; + lwfn_file_name[0] = 0; + + fond = (FamRec*)fond_data; + assoc = (AsscEntry*)(fond_data + sizeof(FamRec) + 2); + + if ( assoc->fontSize == 0 ) + { + *have_sfnt = 1; + *sfnt_id = assoc->fontID; + } + + if ( fond->ffStylOff ) + { + unsigned char* p = (unsigned char*)fond_data; + StyleTable* style; + unsigned short string_count; + unsigned char* name_table = 0; + char ps_name[256]; + unsigned char* names[64]; + int i; + + p += fond->ffStylOff; + style = (StyleTable*)p; + p += sizeof(StyleTable); + string_count = *(unsigned short*)(p); + p += sizeof(short); + + for ( i=0 ; iindexes[0] > 1 ) + { + unsigned char* suffixes = names[style->indexes[0]-1]; + for ( i=1; i<=suffixes[0]; i++ ) + strcat( ps_name, p2c_str(names[suffixes[i]-1]) ); + } + create_lwfn_name( ps_name, lwfn_file_name ); + } + return FT_Err_Ok; + } + + + /* Read Type 1 data from the POST resources inside the LWFN file, return a + PFB buffer -- apparently FT doesn't like a pure binary T1 stream. */ + static + unsigned char* read_type1_data( FT_Memory memory, FSSpec* lwfn_spec, unsigned long *size ) + { + short res_ref, res_id; + unsigned char *buffer, *p, *size_p; + unsigned long total_size = 0; + unsigned long post_size, pfb_chunk_size; + Handle post_data; + char code, last_code; + + res_ref = FSpOpenResFile( lwfn_spec, fsRdPerm ); + if ( ResError() ) + return NULL; + UseResFile( res_ref ); + + /* first pass: load all POST resources, and determine the size of + the output buffer */ + res_id = 501; + last_code = -1; + for (;;) + { + post_data = Get1Resource( 'POST', res_id++ ); + if ( post_data == NULL ) + break; + code = (*post_data)[0]; + if ( code != last_code ) + { + if ( code == 5 ) + total_size += 2; /* just the end code */ + else + total_size += 6; /* code + 4 bytes chunk length */ + } + total_size += GetHandleSize( post_data ) - 2; + last_code = code; + } + + buffer = memory->alloc( memory, total_size ); + if ( !buffer ) + goto error; + + /* second pass: append all POST data to the buffer, add PFB fields */ + p = buffer; + res_id = 501; + last_code = -1; + pfb_chunk_size = 0; + for (;;) + { + post_data = Get1Resource( 'POST', res_id++ ); + if ( post_data == NULL ) + break; + post_size = GetHandleSize( post_data ) - 2; + code = (*post_data)[0]; + if ( code != last_code ) + { + if ( last_code != -1 ) + { + /* we're done adding a chunk, fill in the size field */ + *size_p++ = pfb_chunk_size & 0xFF; + *size_p++ = (pfb_chunk_size >> 8) & 0xFF; + *size_p++ = (pfb_chunk_size >> 16) & 0xFF; + *size_p++ = (pfb_chunk_size >> 24) & 0xFF; + pfb_chunk_size = 0; + } + *p++ = 0x80; + if ( code == 5 ) + *p++ = 0x03; /* the end */ + else if ( code == 2 ) + *p++ = 0x02; /* binary segment */ + else + *p++ = 0x01; /* ASCII segment */ + if ( code != 5 ) + { + size_p = p; /* save for later */ + p += 4; /* make space for size field */ + } + } + memcpy( p, *post_data + 2, post_size ); + pfb_chunk_size += post_size; + p += post_size; + last_code = code; + } + + CloseResFile( res_ref ); + + *size = total_size; +/* printf( "XXX %d %d\n", p - buffer, total_size ); */ + return buffer; + +error: + CloseResFile( res_ref ); + return NULL; + } + + + /* Finalizer for the sfnt stream */ + static + void sfnt_stream_close( FT_Stream stream ) + { + Handle sfnt_data = stream->descriptor.pointer; + HUnlock( sfnt_data ); + DisposeHandle( sfnt_data ); + + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + stream->close = 0; + } + + + /* Finalizer for the LWFN stream */ + static + void lwfn_stream_close( FT_Stream stream ) + { + stream->memory->free( stream->memory, stream->base ); + stream->descriptor.pointer = NULL; + stream->size = 0; + stream->base = 0; + stream->close = 0; + } + + + /* Main entry point. Determine whether we're dealing with a Mac + suitcase or not; then determine if we're dealing with Type 1 + or TrueType; delegate the work to the proper driver. */ + static + FT_Error init_face( FT_Stream stream, + FT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* parameters ) + { + FT_Error err; + FSSpec suit_spec, lwfn_spec; + short res_ref; + Handle fond_data, sfnt_data; + short res_index, sfnt_id, have_sfnt; + Str255 lwfn_file_name; + + if ( !stream->pathname.pointer ) + return FT_Err_Unknown_File_Format; + + if ( make_file_spec( stream->pathname.pointer, &suit_spec ) ) + return FT_Err_Invalid_Argument; + + if ( !is_suitcase( &suit_spec ) ) + return FT_Err_Unknown_File_Format; + + res_ref = FSpOpenResFile( &suit_spec, fsRdPerm ); + if ( ResError() ) + return FT_Err_Invalid_File_Format; + UseResFile( res_ref ); + + /* face_index may be -1, in which case we + just need to do a sanity check */ + if ( face_index < 0) + res_index = 1; + else + { + res_index = face_index + 1; + face_index = 0; + } + fond_data = Get1IndResource( 'FOND', res_index ); + if ( ResError() ) + { + CloseResFile( res_ref ); + return FT_Err_Invalid_File_Format; + } + /* Set the number of faces. Not that it helps much: the t1 driver + just sets it to 1 anyway :-( */ + face->num_faces = Count1Resources('FOND'); + + HLock( fond_data ); + err = parse_fond( *fond_data, &have_sfnt, &sfnt_id, lwfn_file_name ); + HUnlock( fond_data ); + if ( err ) + { + CloseResFile( res_ref ); + return FT_Err_Invalid_Handle; + } + + if ( lwfn_file_name[0] ) + { + /* We look for the LWFN file in the same directory as the suitcase + file. ATM would look in other places, too, but this is the usual + situation. */ + err = FSMakeFSSpec( suit_spec.vRefNum, suit_spec.parID, lwfn_file_name, &lwfn_spec ); + if ( err != noErr ) + lwfn_file_name[0] = 0; /* no LWFN file found */ + } + + if ( lwfn_file_name[0] && ( !have_sfnt || PREFER_LWFN ) ) + { + FT_Driver t1_driver; + unsigned char* type1_data; + unsigned long size; + + CloseResFile( res_ref ); /* XXX still need to read kerning! */ + + type1_data = read_type1_data( stream->memory, &lwfn_spec, &size ); + if ( !type1_data ) + { + return FT_Err_Out_Of_Memory; + } + +#if 0 + { + FILE* f; + char * path; + + path = p2c_str( lwfn_file_name ); + strcat( path, ".PFB" ); + f = fopen(path, "wb"); + if ( f ) + { + fwrite( type1_data, 1, size, f ); + fclose( f ); + } + } +#endif + + /* reinitialize the stream */ + if ( stream->close ) + stream->close( stream ); + stream->close = lwfn_stream_close; + stream->read = 0; /* it's now memory based */ + stream->base = type1_data; + stream->size = size; + stream->pos = 0; /* just in case */ + + /* delegate the work to the Type 1 module */ + t1_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "type1z" ); + if ( t1_driver ) + { + face->driver = t1_driver; + return t1_driver->clazz->init_face( stream, face, face_index, 0, NULL ); + } + else + return FT_Err_Invalid_Driver_Handle; + } + else if ( have_sfnt ) + { + FT_Driver tt_driver; + + sfnt_data = Get1Resource( 'sfnt', sfnt_id ); + if ( ResError() ) + { + CloseResFile( res_ref ); + return FT_Err_Invalid_Handle; + } + DetachResource( sfnt_data ); + CloseResFile( res_ref ); + HLockHi( sfnt_data ); + + /* reinitialize the stream */ + if ( stream->close ) + stream->close( stream ); + stream->close = sfnt_stream_close; + stream->descriptor.pointer = sfnt_data; + stream->read = 0; /* it's now memory based */ + stream->base = (unsigned char *)*sfnt_data; + stream->size = GetHandleSize( sfnt_data ); + stream->pos = 0; /* just in case */ + + /* delegate the work to the TrueType driver */ + tt_driver = (FT_Driver)FT_Get_Module( face->driver->root.library, "truetype" ); + if ( tt_driver ) + { + face->driver = tt_driver; + return tt_driver->clazz->init_face( stream, face, face_index, 0, NULL ); + } + else + return FT_Err_Invalid_Driver_Handle; + } + else + { + CloseResFile( res_ref ); + } + return FT_Err_Invalid_File_Format; + } + + + static + void done_face( FT_Face face ) + { + /* nothing to do */ + } + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + const FT_Driver_Class fond_driver_class = + { + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof ( FT_DriverRec ), + + "fond", /* driver name */ + 0x10000L, /* driver version == 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + (void*)0, + + (FT_Module_Constructor) init_driver, + (FT_Module_Destructor) done_driver, + (FT_Module_Requester) 0 + }, + + sizeof ( FOND_FaceRec ), + 0, + 0, + + (FTDriver_initFace) init_face, + (FTDriver_doneFace) done_face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot) 0, + (FTDriver_doneGlyphSlot) 0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes) 0, + (FTDriver_loadGlyph) 0, + (FTDriver_getCharIndex) 0, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverInterface */ + /* */ + /* */ + /* This function is used when compiling the FOND driver as a */ + /* shared library (`.DLL' or `.so'). It will be used by the */ + /* high-level library of FreeType to retrieve the address of the */ + /* driver's generic interface. */ + /* */ + /* It shouldn't be implemented in a static build, as each driver must */ + /* have the same function as an exported entry point. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + FT_EXPORT_FUNC(const FT_Driver_Class*) getDriverClass( void ) + { + return &fond_driver_class; + } + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/otlayout/.cvsignore b/subsys/win32k/freetype/src/otlayout/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/otlayout/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/otlayout/oltypes.c b/subsys/win32k/freetype/src/otlayout/oltypes.c new file mode 100644 index 0000000..bd2fa22 --- /dev/null +++ b/subsys/win32k/freetype/src/otlayout/oltypes.c @@ -0,0 +1,614 @@ +#include + + LOCAL_FUNC + TT_Error OTL_Table_Init( OTL_Table* table, + FT_Memory memory ) + { + MEM_Set( table, 0, sizeof(*table) ); + table->memory = memory; + } + + /* read a script list table */ + /* use with any table */ + LOCAL_FUNC + TT_Error OTL_Table_Set_Scripts( OTL_Table* table, + TT_Byte* bytes, + TT_Long len, + OTL_Type otl_type ) + { + TT_Byte* p; + TT_Byte* start = bytes; + TT_UInt count, max_langs; + TT_Error error; + + /* skip version of the JSTF table */ + if (otl_type == otl_jstf) + start += 4; + + p = start; + + /* we must allocate the script_tags and language_tags arrays */ + /* this requires that we compute the maximum number of languages */ + /* per script.. */ + + count = table->num_scripts = OTL_UShort(p); + max_langs = 0; + for ( ; count > 0; count++ ) + { + TT_Byte* script; + TT_UInt num_langs; + + p += 4; /* skip tag */ + script = bytes + OTL_UShort(p); + + /* skip the baseValues or extenders field of the BASE and JSTF table */ + if (otl_type == otl_type_base || otl_type == otl_type_jstf) + script += 2; + + /* test if there is a default language system */ + if ( OTL_UShort(script) ) + num_langs++; + + /* test other language systems */ + num_langs += OTL_UShort(script); /* add other lang sys */ + + if (num_langs > max_langs) + max_langs = num_langs; + } + + /* good, now allocate the tag arrays */ + if ( !ALLOC_ARRAY( table->script_tags, + table->num_scripts + max_langs, + TT_ULong ) ) + { + table->language_tags = table->script_tags + table->num_scripts; + table->max_languages = max_langs; + table->num_languages = 0; + table->otl_type = otl_type; + + table->scripts_table = bytes; + table->scripts_len = len; + + /* fill the script_tags array */ + { + TT_UInt n; + TT_Byte* p = start + 2; /* skip count */ + + for ( n = 0; n < table->num_scripts; n++ ) + { + table->script_tags[n] = OTL_ULong(p); + p += 2; /* skip offset */ + } + } + } + return error; + } + + + + /* add a features list to the table */ + /* use only with a GSUB or GPOS table */ + LOCAL_FUNC + TT_Error OTL_Table_Set_Features( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ) + { + TT_Error error; + TT_Byte* p = bytes; + TT_UInt count; + + table->max_features = count = OTL_UShort(p); + if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) && + !ALLOC_ARRAY( table->features, count, TT_Bool ) ) + { + table->features_table = bytes; + table->features_len = len; + } + return error; + } + + + /* add a lookup list to the table */ + /* use only with a GSUB or GPOS table */ + LOCAL_FUNC + TT_Error OTL_Table_Set_Lookups( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ) + { + TT_Error error; + TT_Byte* p = bytes; + TT_UInt count; + + table->max_lookups = count = OTL_UShort(p); + if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) ) + { + table->lookups_table = bytes; + table->lookups_len = len; + } + return error; + } + + /* discard table arrays */ + LOCAL_FUNC + void OTL_Table_Done( OTL_Table* table ) + { + FREE( table->scrip_tags ); + FREE( table->language_tags ); + FREE( table->feature_tags ); + FREE( table->lookups ); + } + + + /* return the list of available languages for a given script */ + /* use with any table.. */ + LOCAL_FUNC + void OTL_Get_Languages_List( OTL_Table* table, + TT_ULong script_tag ) + { + TT_UInt n; + TT_Byte* p; + TT_Byte* script = 0; + TT_Byte* start = table->scripts_table; + + if ( table->otl_type == otl_type_jstf ) /* skip version for JSTF */ + start += 4; + + p = start + 6; /* skip count+first tag */ + + for ( n = 0; n < table->num_scripts; n++, p += 6 ) + { + if ( table->script_tags[n] == script_tag ) + { + script = table->scripts_table + OTL_UShort(p); + break; + } + } + + table->cur_script = script; + if (!script) + table->num_languages = 0; + else + { + /* now fill the language_tags array with the appropriate values */ + /* not that we put a '0' tag in front of the list to indicate that */ + /* there is a default language for this script.. */ + TT_ULong* tags = table->language_tags; + + switch (table->otl_type) + { + case otl_type_base: + case otl_type_jstf: + script += 2; /* skip basevalue or extenders */ + /* fall-through */ + + default: + if ( OTL_UShort(script) ) + *tags++ = 0; + } + + count = OTL_UShort(script); + for ( ; count > 0; count-- ) + { + *tags++ = OTL_ULong(script); + script += 2; /* skip offset */ + } + + table->num_langs = tags - table->language_tags; + } + } + + + /* return the list of available features for the current script/language */ + /* use with a GPOS or GSUB script table */ + LOCAL_FUNC + void OTL_Get_Features_List( OTL_Table* table, + TT_ULong language_tag ) + { + TT_UInt n; + TT_Byte* script = table->cur_script; + TT_Byte* language = 0; + TT_UShort offset; + + /* clear feature selection table */ + for ( n = 0; n < table->max_features; n++ ) + table->features[n] = 0; + + /* now, look for the current language */ + if ( language_tag == 0 ) + { + offset = OTL_UShort(script); + if (!offset) return; /* if there is no default language, exit */ + + language = script - 2 + offset; + } + else + { + TT_Byte* p = script + 8; /* skip default+count+1st tag */ + TT_UShort index; + + for ( n = 0; n < table->num_languages; n++, p+=6 ) + { + if ( table->language_tags[n] == language_tag ) + { + language = script + OTL_UShort(p); + break; + } + } + + table->cur_language = language; + if (!language) return; + + p = language + 2; /* skip lookup order */ + index = OTL_UShort(p); /* required feature index */ + if (index != 0xFFFF) + { + if (index < table->max_features) + table->features[index] = 1; + } + + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + index = OTL_UShort(p); + if (index < table->max_features) + table->features[index] = 1; + } + } + } + + + /* return the list of lookups for the current features list */ + /* use only with a GSUB or GPOS table */ + LOCAL_FUNC + void OTL_Get_Lookups_List( OTL_Table* table ) + { + TT_UInt n; + TT_Byte* features = table->features_table; + TT_Byte* p = features + 6; /* skip count+1st tag */ + + /* clear lookup list */ + for ( n = 0; n < table->max_lookups; n++ ) + table->lookups[n] = 0; + + /* now, parse the features list */ + for ( n = 0; n < table->features; n++ ) + { + if (table->features[n]) + { + TT_UInt count; + TT_UShort index; + TT_Byte* feature; + + feature = features + OTL_UShort(p); + p += 4; /* skip tag */ + + /* now, select all lookups from this feature */ + count = OTL_UShort(feature); + for ( ; count > 0; count-- ) + { + index = OTL_UShort(feature); + if (index < table->max_lookups) + table->lookups[index] = 1; + } + } + } + } + + + /* find the basevalues and minmax for the current script/language */ + /* only use it with a BASE table.. */ + LOCAL_FUNC + void OTL_Get_Baseline_Values( OTL_Table* table, + TT_ULong language_tag ) + { + TT_Byte* script = table->cur_script; + TT_Byte* p = script; + TT_UShort offset, count; + + table->cur_basevalues = 0; + table->cur_minmax = 0; + + /* read basevalues */ + offset = OTL_UShort(p); + if (offset) + table->cur_basevalues = script + offset; + + offset = OTL_UShort(p); + if (offset) + table->cur_minmax = script + offset; + + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + TT_ULong tag; + + tag = OTL_ULong(p); + if ( language_tag == tag ) + { + table->cur_minmax = script + OTL_UShort(p); + break; + } + p += 2; /* skip offset */ + } + } + + + /* compute the coverage value of a given glyph id */ + LOCAL_FUNC + TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage, + TT_UInt glyph_id ) + { + TT_Long result = -1; + TT_UInt count, index, start, end; + TT_Byte* p = coverage; + + switch ( OTL_UShort(p) ) + { + case 1: /* coverage format 1 - array of glyph indices */ + { + count = OTL_UShort(p); + for ( index = 0; index < count; index++ ) + { + if ( OTL_UShort(p) == glyph_id ) + { + result = index; + break; + } + } + } + break; + + case 2: + { + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + start = OTL_UShort(p); + end = OTL_UShort(p); + index = OTL_UShort(p); + if (start <= glyph_id && glyph_id <= end) + { + result = glyph_id - start + index; + break; + } + } + } + break; + } + return result; + } + + + /* compute the class value of a given glyph_id */ + LOCAL_FUNC + TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def, + TT_UInt glyph_id ) + { + TT_Byte* p = class_def; + TT_UInt result = 0; + TT_UInt start, end, count, index; + + switch ( OTL_UShort(p) ) + { + case 1: + { + start = OTL_UShort(p); + count = OTL_UShort(p); + + glyph_id -= start; + if (glyph_id < count) + { + p += 2*glyph_id; + result = OTL_UShort(p); + } + } + break; + + case 2: + { + count = OTL_UShort(p); + for ( ; count > 0; count-- ) + { + start = OTL_UShort(p); + end = OTL_UShort(p); + index = OTL_UShort(p); + if ( start <= glyph_id && glyph_id <= end ) + { + result = index; + break; + } + } + } + break; + } + return result; + } + + + /* compute the adjustement necessary for a given device size */ + LOCAL_FUNC + TT_Int OTL_Get_Device_Adjustment( TT_Byte* device, + TT_UInt size ) + { + TT_Byte* p = device; + TT_Int result = 0; + TT_UInt start, end; + TT_Short value; + + start = OTL_UShort(p); + end = OTL_UShort(p); + if (size >= start && size <= end) + { + /* I know we could do all of this without a switch, with */ + /* clever shifts and everything, but it makes the code */ + /* really difficult to understand.. */ + + size -= start; + switch ( OTL_UShort(p) ) + { + case 1: /* 2-bits per value */ + { + p += 2*(size >> 3); + size = (size & 7) << 1; + value = (TT_Short)((TT_Short)OTL_UShort(p) << size); + result = value >> 14; + } + break; + + case 2: /* 4-bits per value */ + { + p += 2*(size >> 2); + size = (size & 3) << 2; + value = (TT_Short)((TT_Short)OTL_UShort(p) << size); + result = value >> 12; + } + break; + + case 3: /* 8-bits per value */ + { + p += 2*(size >> 1); + size = (size & 1) << 3; + value = (TT_Short)((TT_Short)OTL_UShort(p) << size); + result = value >> 8; + } + break; + } + } + return result; + } + + /* extract a BaseCoord value */ + LOCAL_FUNC + void OTL_Get_Base_Coordinate( TT_Byte* base_coord, + OTL_ValueRecord* coord ) + { + TT_Byte* p = base_coord; + TT_Int result = 0; + + coord->format = OTL_UShort(p); + coord->coordinate = OTL_Short(p); + coord->device = 0; + + switch (coord->format) + { + case 2: /* format 2 */ + coord->ref_glyph = OTL_UShort(p); + coord->ref_point = OTL_UShort(p); + break; + + case 3: /* format 3 */ + coord->device = p - 4 + OTL_UShort(p); + break; + + default: + ; + } + } + + + /* compute size of ValueRecord */ + LOCAL_FUNC + TT_Int OTL_ValueRecord_Size( TT_UShort format ) + { + TT_Int count; + + /* each bit in the value format corresponds to a single ushort */ + /* we thus count the bits, and multiply the result by 2 */ + + count = (TT_Int)(format & 0xFF); + count = ((count & 0xAA) >> 1) + (count & 0x55); + count = ((count & 0xCC) >> 2) + (count & 0x33); + count = ((count & 0xF0) >> 4) + (count & 0x0F); + + return count*2; + } + + + + /* extract ValueRecord */ + LOCAL_FUNC + void OTL_Get_ValueRecord( TT_Byte* value_record, + TT_UShort value_format, + TT_Byte* pos_table, + OTL_ValueRecord* record ) + { + TT_Byte* p = value_record; + + /* clear vectors */ + record->placement.x = 0; + record->placement.y = 0; + record->advance.x = 0; + record->advance.y = 0; + + record->device_pla_x = 0; + record->device_pla_y = 0; + record->device_adv_x = 0; + record->device_adv_y = 0; + + if (value_format & 1) record->placement.x = NEXT_Short(p); + if (value_format & 2) record->placement.y = NEXT_Short(p); + if (value_format & 4) record->advance.x = NEXT_Short(p); + if (value_format & 8) record->advance.y = NEXT_Short(p); + + if (value_format & 16) record->device_pla_x = pos_table + NEXT_UShort(p); + if (value_format & 32) record->device_pla_y = pos_table + NEXT_UShort(p); + if (value_format & 64) record->device_adv_x = pos_table + NEXT_UShort(p); + if (value_format & 128) record->device_adv_y = pos_table + NEXT_UShort(p); + } + + + + /* extract Anchor */ + LOCAL_FUNC + void OTL_Get_Anchor( TT_Byte* anchor_table, + OTL_Anchor* anchor ) + { + TT_Byte* p = anchor_table; + + anchor->format = NEXT_UShort(p); + anchor->coord.x = NEXT_Short(p); + anchor->coord.y = NEXT_Short(p); + anchor->point = 0; + anchor->device_x = 0; + anchor->device_y = 0; + + switch (anchor->format) + { + case 2: + anchor->point = NEXT_UShort(p); + break; + + case 3: + anchor->device_x = anchor_table + NEXT_UShort(p); + anchor->device_y = anchor_table + NEXT_UShort(p); + break; + + default: + ; + } + } + + + + /* extract Mark from MarkArray */ + LOCAL_FUNC + void OTL_Get_Mark( TT_Byte* mark_array, + TT_UInt index, + TT_UShort* clazz, + OTL_Anchor* anchor ) + { + TT_Byte* p = mark_array; + TT_UInt count; + + *clazz = 0; + MEM_Set( anchor, 0, sizeof(*anchor) ); + + count = NEXT_UShort(p); + if (index < count) + { + p += 4*index; + *clazz = NEXT_UShort(p); + OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor ); + } + } + diff --git a/subsys/win32k/freetype/src/otlayout/oltypes.h b/subsys/win32k/freetype/src/otlayout/oltypes.h new file mode 100644 index 0000000..b4a4d80 --- /dev/null +++ b/subsys/win32k/freetype/src/otlayout/oltypes.h @@ -0,0 +1,310 @@ +#ifndef OLTYPES_H +#define OLTYPES_H + +#include +#include + + /************************************************************* + * + * OTL_Table + * + * + * The base table of most OpenType Layout sub-tables. + * Provides a simple way to scan a table for script, + * languages, features and lookups.. + * + * + * num_scripts :: number of scripts in table's script list + * script_tags :: array of tags for each table script + * + * max_languages :: max number of languages for any script in + * the table. + * num_languages :: number of languages available for current script + * language_tags :: tags of all languages available for current script. + * + * max_features :: total number of features in table + * feature_tags :: tags of all features for current script/language + * features :: selection flags for all features in current script/lang + * + * max_lookups :: total number of lookups in table + * lookups :: selection flags for all lookups for current + * feature list. + * + ****************************************************************/ + + typedef enum OTL_Type_ + { + otl_type_none = 0, + otl_type_base, + otl_type_gdef, + otl_type_gpos, + otl_type_gsub, + otl_type_jstf + + } OTL_Type; + + + typedef struct OTL_Table_ + { + FT_Memory memory; + + TT_Int num_scripts; + TT_Tag* script_tags; + + TT_Int max_languages; + TT_Int num_languages; + TT_Tag* language_tags; + + TT_Int max_features; + TT_Tag* feature_tags; + TT_Bool* features; + + TT_Int max_lookups; + TT_Bool* lookups; + + TT_Byte* scripts_table; + TT_Long scripts_len; + + TT_Byte* features_table; + TT_Long* features_len; + + TT_Byte* lookups_table; + TT_Byte* lookups_len; + + TT_Byte* cur_script; /* current script */ + TT_Byte* cur_language; /* current language */ + + TT_Byte* cur_base_values; + TT_Byte* cur_min_max; + + OTL_Type otl_type; + + } OTL_Table; + + + typedef struct OTL_BaseCoord_ + { + TT_UShort format; + TT_Short coordinate; + TT_UShort ref_glyph; + TT_UShort ref_point; + TT_Byte* device; + + } OTL_BaseCoord; + + + typedef struct OTL_ValueRecord_ + { + TT_Vector placement; + TT_Vector advance; + + TT_Byte* device_pla_x; + TT_Byte* device_pla_y; + TT_Byte* device_adv_x; + TT_Byte* device_adv_y; + + } OTL_ValueRecord; + + + typedef struct OTL_Anchor_ + { + TT_UInt format; + TT_Vector coord; + TT_UInt anchor_point; + TT_Byte* device_x; + TT_Byte* device_y; + + } OTL_Anchor; + + LOCAL_DEF + TT_Error OTL_Table_Init( OTL_Table* table, + FT_Memory memory ); + + LOCAL_DEF + TT_Error OTL_Table_Set_Scripts( OTL_Table* table, + TT_Byte* bytes, + TT_Long len, + OTL_Type otl_type ); + + LOCAL_DEF + TT_Error OTL_Table_Set_Features( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ); + + LOCAL_DEF + TT_Error OTL_Table_Set_Lookups( OTL_Table* table, + TT_Byte* bytes, + TT_Long len ); + + LOCAL_DEF + void OTL_Table_Done( OTL_Table* table ); + + + +/***************************************************** + * + * Typical uses: + * + * - after OTL_Table_Set_Scripts have been called : + * + * table->script_tags contains the list of tags of all + * scripts defined for this table. + * + * table->num_scripts is the number of scripts + * + */ + +/******************************************************** + * + * - after calling OTL_Table_Set_Features: + * + * table->max_features is the number of all features + * in the table + * + * table->feature_tags is the list of tags of all + * features in the table + * + * table->features[] is an array of boolean used to + * indicate which feature is active for a given script/language + * it is empty (zero-filled) by default. + * + */ + +/******************************************************************* + * + * - after calling OTL_Get_Languages_List(script_tag): + * + * table->num_languages is the number of language systems + * available for the script, including the default + * langsys if there is one + * + * table->language_tags contains the list of tags of all + * languages for the script. Note that the default langsys + * has tag "0" and is always placed first in "language_tags". + * + * + * + */ + LOCAL_DEF + void OTL_Get_Languages_List( OTL_Table* table, + TT_ULong script_tag ); + + +/******************************************************************* + * + * - after calling OTL_Get_Features_List(language_tag): + * + * table->features[] is an array of booleans used to indicate + * which features are active for the current script/language + * + * note that this function must be called after OTL_Get_Languages + * which remembers the last "script_tag" used.. + * + * A client application can change the table->features[] array + * to add or remove features from the list. + * + * + * + */ + LOCAL_DEF + void OTL_Get_Features_List( OTL_Table* table, + TT_ULong language_tag ); + + LOCAL_DEF + void OTL_Get_Baseline_Values( OTL_Table* table, + TT_ULong language_tag ); + + LOCAL_DEF + void OTL_Get_Justification( OTL_Table* table, + TT_ULong language_tag ); + +/******************************************************************* + * + * - after calling OTL_Get_Lookups_List(): + * + * The function uses the table->features[] array of boolean + * to determine which lookups must be processed. + * + * It fills the table->lookups[] array accordingly. It is also + * an array of booleans (one for each lookup). + * + * + */ + + LOCAL_DEF + void OTL_Get_Lookups_List( OTL_Table* table ); + + +/*************************************************************** + * + * So the whole thing looks like: + * + * + * 1. A client specifies a given script and requests available + * language through OTL_Get_Languages_List() + * + * 2. It selects the language tag it needs, then calls + * OTL_Get_Features_List() + * + * 3. It updates the list of active features if it needs to + * + * 4. It calls OTL_Get_Lookups_List() + * It now has a list of active lookups in "table->lookups[]" + * + * 5. The lookups are processed according to the table's type.. + * + */ + + + + + LOCAL_DEF + TT_Long OTL_Get_Coverage_Index( TT_Byte* coverage, + TT_UInt glyph_id ); + + LOCAL_DEF + TT_UInt OTL_Get_Glyph_Class( TT_Byte* class_def, + TT_UInt glyph_id ); + + LOCAL_DEF + TT_Int OTL_Get_Device_Adjustment( TT_Byte* device, + TT_UInt size ); + + LOCAL_DEF + void OTL_Get_Base_Coordinate( TT_Byte* base_coord, + OTL_BaseCoord* coord ); + + + LOCAL_DEF + TT_Int OTL_ValueRecord_Size( TT_UShort value_format ); + + + LOCAL_DEF + void OTL_Get_ValueRecord( TT_Byte* value_record, + TT_UShort value_format, + TT_Byte* pos_table, + OTL_ValueRecord* record ); + + + LOCAL_DEF + void OTL_Get_Anchor( TT_Byte* anchor_table, + OTL_Anchor* anchor ); + + + LOCAL_DEF + void OTL_Get_Mark( TT_Byte* mark_array, + TT_UInt index, + TT_UShort* clazz, + OTL_Anchor* anchor ); + + + +#define OTL_Byte(p) (p++, p[-1]) + +#define OTL_UShort(p) (p+=2, ((TT_UShort)p[-2] << 8) | p[-1]) + +#define OTL_ULong(p) (p+=4, ((TT_ULong)p[-4] << 24) | \ + ((TT_ULong)p[-3] << 16) | \ + ((TT_ULong)p[-2] << 8 ) | p[-1] ) + +#endif /* OLTYPES_H */ diff --git a/subsys/win32k/freetype/src/psnames/.cvsignore b/subsys/win32k/freetype/src/psnames/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/psnames/module.mk b/subsys/win32k/freetype/src/psnames/module.mk new file mode 100644 index 0000000..3d33c12 --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_psnames_module + +add_psnames_module: + $(OPEN_DRIVER)psnames_module_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)psnames $(ECHO_DRIVER_DESC)Postscript & Unicode Glyph name handling$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/psnames/psmodule.c b/subsys/win32k/freetype/src/psnames/psmodule.c new file mode 100644 index 0000000..e1e9e77 --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/psmodule.c @@ -0,0 +1,320 @@ +/***************************************************************************/ +/* */ +/* psmodule.c */ +/* */ +/* PSNames module implementation (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "psmodule.h" +#include "pstables.h" + +#else + +#include +#include + +#endif + + +#include /* for qsort() */ +#include /* for strcmp(), strncpy() */ + + +#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES + + + + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /* return the Unicode value corresponding to a given glyph. Note that */ + /* we do deal with glyph variants by detecting a non-initial dot in */ + /* the name, as in `A.swash' or `e.final', etc. */ + /* */ + static + FT_ULong PS_Unicode_Value( const char* glyph_name ) + { + FT_Int n; + char first = glyph_name[0]; + char temp[64]; + + + /* if the name begins with `uni', then the glyph name may be a */ + /* hard-coded unicode character code. */ + if ( glyph_name[0] == 'u' && + glyph_name[1] == 'n' && + glyph_name[2] == 'i' ) + { + /* determine whether the next four characters following are */ + /* hexadecimal. */ + + /* XXX: Add code to deal with ligatures, i.e. glyph names like */ + /* `uniXXXXYYYYZZZZ'... */ + + FT_Int count; + FT_ULong value = 0; + const char* p = glyph_name + 4; + + + for ( count = 4; count > 0; count--, p++ ) + { + char c = *p; + unsigned char d; + + + d = (unsigned char)c - '0'; + if ( d >= 10 ) + { + d = (unsigned char)c - 'A'; + if ( d >= 6 ) + d = 16; + else + d += 10; + } + + /* exit if a non-uppercase hexadecimal character was found */ + if ( d >= 16 ) + break; + + value = ( value << 4 ) + d; + + if ( count == 0 ) + return value; + } + } + + /* look for a non-initial dot in the glyph name in order to */ + /* sort-out variants like `A.swash', `e.final', etc. */ + { + const char* p; + int len; + + + p = glyph_name; + + while ( *p && *p != '.' ) + p++; + + len = p - glyph_name; + + if ( *p && len < 64 ) + { + strncpy( temp, glyph_name, len ); + temp[len] = 0; + glyph_name = temp; + } + } + + /* now, look up the glyph in the Adobe Glyph List */ + for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ ) + { + const char* name = t1_standard_glyphs[n]; + + + if ( first == name[0] && strcmp( glyph_name, name ) == 0 ) + return names_to_unicode[n]; + } + + /* not found, there is probably no Unicode value for this glyph name */ + return 0; + } + + + /* qsort callback to sort the unicode map */ + static + int compare_uni_maps( const void* a, + const void* b ) + { + PS_UniMap* map1 = (PS_UniMap*)a; + PS_UniMap* map2 = (PS_UniMap*)b; + + + return ( map1->unicode - map2->unicode ); + } + + + /* Builds a table that maps Unicode values to glyph indices */ + static + FT_Error PS_Build_Unicode_Table( FT_Memory memory, + FT_UInt num_glyphs, + const char** glyph_names, + PS_Unicodes* table ) + { + FT_Error error; + + + /* we first allocate the table */ + table->num_maps = 0; + table->maps = 0; + + if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) ) + { + FT_UInt n; + FT_UInt count; + PS_UniMap* map; + FT_ULong uni_char; + + + map = table->maps; + + for ( n = 0; n < num_glyphs; n++ ) + { + const char* gname = glyph_names[n]; + + + if ( gname ) + { + uni_char = PS_Unicode_Value( gname ); + + if ( uni_char && uni_char != 0xFFFF ) + { + map->unicode = uni_char; + map->glyph_index = n; + map++; + } + } + } + + /* now, compress the table a bit */ + count = map - table->maps; + + if ( count > 0 && REALLOC( table->maps, + num_glyphs * sizeof ( PS_UniMap ), + count * sizeof ( PS_UniMap ) ) ) + count = 0; + + if ( count == 0 ) + { + FREE( table->maps ); + if ( !error ) + error = FT_Err_Invalid_Argument; /* no unicode chars here! */ + } + else + /* sort the table in increasing order of unicode values */ + qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps ); + + table->num_maps = count; + } + + return error; + } + + + static + FT_UInt PS_Lookup_Unicode( PS_Unicodes* table, + FT_ULong unicode ) + { + PS_UniMap *min, *max, *mid; + + + /* perform a binary search on the table */ + + min = table->maps; + max = min + table->num_maps - 1; + + while ( min <= max ) + { + mid = min + ( max - min ) / 2; + if ( mid->unicode == unicode ) + return mid->glyph_index; + + if ( min == max ) + break; + + if ( mid->unicode < unicode ) + min = mid + 1; + else + max = mid - 1; + } + + return 0xFFFF; + } + + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + + + static + const char* PS_Macintosh_Name( FT_UInt name_index ) + { + if ( name_index >= 258 ) + name_index = 0; + + return standard_glyph_names[mac_standard_names[name_index]]; + } + + + static + const char* PS_Standard_Strings( FT_UInt sid ) + { + return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 ); + } + + + static const PSNames_Interface psnames_interface = + { +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + (PS_Unicode_Value_Func) PS_Unicode_Value, + (PS_Build_Unicodes_Func) PS_Build_Unicode_Table, + (PS_Lookup_Unicode_Func) PS_Lookup_Unicode, + +#else + + 0, + 0, + 0, + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + + (PS_Macintosh_Name_Func) PS_Macintosh_Name, + (PS_Adobe_Std_Strings_Func)PS_Standard_Strings, + + t1_standard_encoding, + t1_expert_encoding + }; + + +#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */ + + + const FT_Module_Class psnames_module_class = + { + 0, /* this is not a font driver, nor a renderer */ + sizeof( FT_ModuleRec ), + + "psnames", /* driver name */ + 0x10000L, /* driver version */ + 0x20000L, /* driver requires FreeType 2 or above */ + +#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES + 0, +#else + (void*)&psnames_interface, /* module specific interface */ +#endif + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/psnames/psmodule.h b/subsys/win32k/freetype/src/psnames/psmodule.h new file mode 100644 index 0000000..ff7ef06 --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/psmodule.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* psmodule.h */ +/* */ +/* High-level PSNames module interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef PSDRIVER_H +#define PSDRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Module_Class ) psnames_module_class; + +#endif /* PSDRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/psnames/psnames.c b/subsys/win32k/freetype/src/psnames/psnames.c new file mode 100644 index 0000000..4e4aa1f --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/psnames.c @@ -0,0 +1,24 @@ +/***************************************************************************/ +/* */ +/* psnames.c */ +/* */ +/* FreeType PSNames module component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + +#include + + +/* END */ diff --git a/subsys/win32k/freetype/src/psnames/pstables.h b/subsys/win32k/freetype/src/psnames/pstables.h new file mode 100644 index 0000000..094bc27 --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/pstables.h @@ -0,0 +1,2942 @@ +/***************************************************************************/ +/* */ +/* pstables.h */ +/* */ +/* PostScript glyph names (specification only). */ +/* */ +/* Copyright 2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /* this file has been generated automatically -- do not edit! */ + + + static const char* standard_glyph_names[] = + { + ".null", + "CR", + "notequal", + "infinity", + "lessequal", + "greaterequal", + "partialdiff", + "summation", + "product", + "pi", + "integral", + "Omega", + "radical", + "approxequal", + "Delta", + "nbspace", + "lozenge", + "periodcentered", + "apple", + "lslash", + "franc", + "Gbreve", + "gbreve", + "Idot", + "Scedilla", + "scedilla", + "Cacute", + "cacute", + "Ccaron", + "ccaron", + "dmacron", + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcenter", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "Islash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacautesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold", + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + "AEacute", + "Abreve", + "Acute", + "Alpha", + "Alphatonos", + "Amacron", + "Aogonek", + "Aringacute", + "Beta", + "Caron", + "Ccircumflex", + "Cdotaccent", + "Chi", + "Dcaron", + "Dcroat", + "Dieresis", + "DieresisAcute", + "DieresisGrave", + "Ebreve", + "Ecaron", + "Edotaccent", + "Emacron", + "Eng", + "Eogonek", + "Epsilon", + "Epsilontonos", + "Eta", + "Etatonos", + "Euro", + "Gamma", + "Gcaron", + "Gcircumflex", + "Gcommaaccent", + "Gdotaccent", + "Grave", + "H18533", + "H18543", + "H18551", + "H22073", + "Hbar", + "Hcircumflex", + "Hungarumlaut", + "IJ", + "Ibreve", + "Idotaccent", + "Ifraktur", + "Imacron", + "Iogonek", + "Iota", + "Iotadieresis", + "Iotatonos", + "Itilde", + "Jcircumflex", + "Kappa", + "Kcommaaccent", + "LL", + "Lacute", + "Lambda", + "Lcaron", + "Lcommaaccent", + "Ldot", + "Macron", + "Mu", + "Nacute", + "Ncaron", + "Ncommaaccent", + "Nu", + "Obreve", + "Ohorn", + "Ohungarumlaut", + "Omacron", + "Omegatonos", + "Omicron", + "Omicrontonos", + "Oslashacute", + "Phi", + "Pi", + "Psi", + "Racute", + "Rcaron", + "Rcommaaccent", + "Rfraktur", + "Rho", + "SF010000", + "SF020000", + "SF030000", + "SF040000", + "SF050000", + "SF060000", + "SF070000", + "SF080000", + "SF090000", + "SF100000", + "SF110000", + "SF190000", + "SF200000", + "SF210000", + "SF220000", + "SF230000", + "SF240000", + "SF250000", + "SF260000", + "SF270000", + "SF280000", + "SF360000", + "SF370000", + "SF380000", + "SF390000", + "SF400000", + "SF410000", + "SF420000", + "SF430000", + "SF440000", + "SF450000", + "SF460000", + "SF470000", + "SF480000", + "SF490000", + "SF500000", + "SF510000", + "SF520000", + "SF530000", + "SF540000", + "Sacute", + "Scircumflex", + "Scommaaccent", + "Sigma", + "Tau", + "Tbar", + "Tcaron", + "Tcommaaccent", + "Tcommaaccent", + "Theta", + "Uacutesmall", + "Ubreve", + "Uhorn", + "Uhungarumlaut", + "Umacron", + "Uogonek", + "Upsilon", + "Upsilon1", + "Upsilondieresis", + "Upsilontonos", + "Uring", + "Utilde", + "Wacute", + "Wcircumflex", + "Wdieresis", + "Wgrave", + "Xi", + "Ycircumflex", + "Ygrave", + "Zacute", + "Zdotaccent", + "Zeta", + "abreve", + "acutecomb", + "aeacute", + "afii00208", + "afii10017", + "afii10018", + "afii10019", + "afii10020", + "afii10021", + "afii10022", + "afii10023", + "afii10024", + "afii10025", + "afii10026", + "afii10027", + "afii10028", + "afii10029", + "afii10030", + "afii10031", + "afii10032", + "afii10033", + "afii10034", + "afii10035", + "afii10036", + "afii10037", + "afii10038", + "afii10039", + "afii10040", + "afii10041", + "afii10042", + "afii10043", + "afii10044", + "afii10045", + "afii10046", + "afii10047", + "afii10048", + "afii10049", + "afii10050", + "afii10051", + "afii10052", + "afii10053", + "afii10054", + "afii10055", + "afii10056", + "afii10057", + "afii10058", + "afii10059", + "afii10060", + "afii10061", + "afii10062", + "afii10063", + "afii10064", + "afii10065", + "afii10066", + "afii10067", + "afii10068", + "afii10069", + "afii10070", + "afii10071", + "afii10072", + "afii10073", + "afii10074", + "afii10075", + "afii10076", + "afii10077", + "afii10078", + "afii10079", + "afii10080", + "afii10081", + "afii10082", + "afii10083", + "afii10084", + "afii10085", + "afii10086", + "afii10087", + "afii10088", + "afii10089", + "afii10090", + "afii10091", + "afii10092", + "afii10093", + "afii10094", + "afii10095", + "afii10096", + "afii10097", + "afii10098", + "afii10099", + "afii10100", + "afii10101", + "afii10102", + "afii10103", + "afii10104", + "afii10105", + "afii10106", + "afii10107", + "afii10108", + "afii10109", + "afii10110", + "afii10145", + "afii10146", + "afii10147", + "afii10148", + "afii10192", + "afii10193", + "afii10194", + "afii10195", + "afii10196", + "afii10831", + "afii10832", + "afii10846", + "afii299", + "afii300", + "afii301", + "afii57381", + "afii57388", + "afii57392", + "afii57393", + "afii57394", + "afii57395", + "afii57396", + "afii57397", + "afii57398", + "afii57399", + "afii57400", + "afii57401", + "afii57403", + "afii57407", + "afii57409", + "afii57410", + "afii57411", + "afii57412", + "afii57413", + "afii57414", + "afii57415", + "afii57416", + "afii57417", + "afii57418", + "afii57419", + "afii57420", + "afii57421", + "afii57422", + "afii57423", + "afii57424", + "afii57425", + "afii57426", + "afii57427", + "afii57428", + "afii57429", + "afii57430", + "afii57431", + "afii57432", + "afii57433", + "afii57434", + "afii57440", + "afii57441", + "afii57442", + "afii57443", + "afii57444", + "afii57445", + "afii57446", + "afii57448", + "afii57449", + "afii57450", + "afii57451", + "afii57452", + "afii57453", + "afii57454", + "afii57455", + "afii57456", + "afii57457", + "afii57458", + "afii57470", + "afii57505", + "afii57506", + "afii57507", + "afii57508", + "afii57509", + "afii57511", + "afii57512", + "afii57513", + "afii57514", + "afii57519", + "afii57534", + "afii57636", + "afii57645", + "afii57658", + "afii57664", + "afii57665", + "afii57666", + "afii57667", + "afii57668", + "afii57669", + "afii57670", + "afii57671", + "afii57672", + "afii57673", + "afii57674", + "afii57675", + "afii57676", + "afii57677", + "afii57678", + "afii57679", + "afii57680", + "afii57681", + "afii57682", + "afii57683", + "afii57684", + "afii57685", + "afii57686", + "afii57687", + "afii57688", + "afii57689", + "afii57690", + "afii57694", + "afii57695", + "afii57700", + "afii57705", + "afii57716", + "afii57717", + "afii57718", + "afii57723", + "afii57793", + "afii57794", + "afii57795", + "afii57796", + "afii57797", + "afii57798", + "afii57799", + "afii57800", + "afii57801", + "afii57802", + "afii57803", + "afii57804", + "afii57806", + "afii57807", + "afii57839", + "afii57841", + "afii57842", + "afii57929", + "afii61248", + "afii61289", + "afii61352", + "afii61573", + "afii61574", + "afii61575", + "afii61664", + "afii63167", + "afii64937", + "aleph", + "alpha", + "alphatonos", + "amacron", + "angle", + "angleleft", + "angleright", + "anoteleia", + "aogonek", + "aringacute", + "arrowboth", + "arrowdblboth", + "arrowdbldown", + "arrowdblleft", + "arrowdblright", + "arrowdblup", + "arrowdown", + "arrowhorizex", + "arrowleft", + "arrowright", + "arrowup", + "arrowupdn", + "arrowupdnbse", + "arrowvertex", + "asteriskmath", + "beta", + "block", + "braceex", + "braceleftbt", + "braceleftmid", + "bracelefttp", + "bracerightbt", + "bracerightmid", + "bracerighttp", + "bracketleftbt", + "bracketleftex", + "bracketlefttp", + "bracketrightbt", + "bracketrightex", + "bracketrighttp", + "carriagereturn", + "ccircumflex", + "cdotaccent", + "chi", + "circle", + "circlemultiply", + "circleplus", + "club", + "commaaccent", + "congruent", + "copyrightsans", + "copyrightserif", + "cyrBreve", + "cyrFlex", + "cyrbreve", + "cyrflex", + "dblGrave", + "dblgrave", + "dcaron", + "dcroat", + "delta", + "diamond", + "dieresisacute", + "dieresisgrave", + "dieresistonos", + "dkshade", + "dnblock", + "dong", + "dotbelowcomb", + "dotlessj", + "dotmath", + "ebreve", + "ecaron", + "edotaccent", + "element", + "emacron", + "emptyset", + "eng", + "eogonek", + "epsilon", + "epsilontonos", + "equivalence", + "estimated", + "eta", + "etatonos", + "exclamdbl", + "existential", + "female", + "filledbox", + "filledrect", + "gamma", + "gcaron", + "gcircumflex", + "gcommaaccent", + "gdotaccent", + "gradient", + "gravecomb", + "hbar", + "hcircumflex", + "heart", + "hookabovecomb", + "house", + "ibreve", + "ij", + "imacron", + "integralbt", + "integralex", + "integraltp", + "intersection", + "invbullet", + "invcircle", + "invsmileface", + "iogonek", + "iota", + "iotadieresis", + "iotadieresistonos", + "iotatonos", + "itilde", + "jcircumflex", + "kappa", + "kcommaaccent", + "kgreenlandic", + "lacute", + "lambda", + "lcaron", + "lcommaaccent", + "ldot", + "lfblock", + "lira", + "ll", + "logicaland", + "logicalor", + "longs", + "ltshade", + "male", + "minute", + "musicalnote", + "musicalnotedbl", + "nacute", + "napostrophe", + "ncaron", + "ncommaaccent", + "notelement", + "notsubset", + "nu", + "obreve", + "ohorn", + "ohungarumlaut", + "omacron", + "omega", + "omega1", + "omegatonos", + "omicron", + "omicrontonos", + "openbullet", + "orthogonal", + "oslashacute", + "parenleftbt", + "parenleftex", + "parenlefttp", + "parenrightbt", + "parenrightex", + "parenrighttp", + "perpendicular", + "peseta", + "phi", + "phi1", + "prescription", + "propersubset", + "propersuperset", + "proportional", + "psi", + "quotereversed", + "racute", + "radicalex", + "rcaron", + "rcommaaccent", + "reflexsubset", + "reflexsuperset", + "registersans", + "registerserif", + "revlogicalnot", + "rho", + "rtblock", + "sacute", + "scircumflex", + "scommaaccent", + "second", + "shade", + "sigma", + "sigma1", + "similar", + "smileface", + "spade", + "suchthat", + "sun", + "tau", + "tbar", + "tcaron", + "tcommaaccent", + "tcommaaccent", + "therefore", + "theta", + "theta1", + "tildecomb", + "tonos", + "trademarksans", + "trademarkserif", + "triagdn", + "triaglf", + "triagrt", + "triagup", + "ubreve", + "uhorn", + "uhungarumlaut", + "umacron", + "underscoredbl", + "union", + "universal", + "uogonek", + "upblock", + "upsilon", + "upsilondieresis", + "upsilondieresistonos", + "upsilontonos", + "uring", + "utilde", + "wacute", + "wcircumflex", + "wdieresis", + "weierstrass", + "wgrave", + "xi", + "ycircumflex", + "ygrave", + "zacute", + "zdotaccent", + "zeta", + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + + 0 + }; + + + static const char** t1_standard_glyphs = standard_glyph_names + 31; + + +#define NUM_STD_GLYPHS 391 + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST +#define NUM_ADOBE_GLYPHS 1032 +#else +#define NUM_ADOBE_GLYPHS 391 +#endif + + + static const unsigned short mac_standard_names[259] = + { + 0, + 0, + 1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 104, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 124, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 173, + 175, + 177, + 178, + 186, + 189, + 195, + 200, + 203, + 201, + 202, + 205, + 204, + 206, + 207, + 210, + 208, + 209, + 211, + 214, + 212, + 213, + 215, + 216, + 219, + 217, + 218, + 220, + 222, + 225, + 223, + 224, + 112, + 161, + 97, + 98, + 102, + 116, + 115, + 149, + 165, + 170, + 153, + 125, + 131, + 2, + 138, + 141, + 3, + 156, + 4, + 5, + 100, + 152, + 6, + 7, + 8, + 9, + 10, + 139, + 143, + 11, + 144, + 147, + 123, + 96, + 151, + 12, + 101, + 13, + 14, + 106, + 120, + 121, + 15, + 174, + 176, + 191, + 142, + 148, + 111, + 137, + 105, + 119, + 65, + 8, + 159, + 16, + 227, + 198, + 99, + 103, + 107, + 108, + 109, + 110, + 113, + 17, + 117, + 118, + 122, + 172, + 179, + 171, + 180, + 181, + 182, + 183, + 184, + 185, + 187, + 188, + 18, + 190, + 193, + 194, + 196, + 145, + 126, + 127, + 128, + 129, + 130, + 132, + 133, + 134, + 135, + 136, + 140, + 19, + 192, + 221, + 199, + 228, + 160, + 154, + 167, + 197, + 226, + 157, + 162, + 166, + 168, + 150, + 164, + 169, + 155, + 158, + 163, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 0 + }; + + + + static const unsigned short names_to_unicode[1033] = + { + 0, + 0x0020, + 0x0021, + 0x0022, + 0x0023, + 0x0024, + 0x0025, + 0x0026, + 0x2019, + 0x0028, + 0x0029, + 0x002A, + 0x002B, + 0x002C, + 0x002D, + 0x002E, + 0x002F, + 0x0030, + 0x0031, + 0x0032, + 0x0033, + 0x0034, + 0x0035, + 0x0036, + 0x0037, + 0x0038, + 0x0039, + 0x003A, + 0x003B, + 0x003C, + 0x003D, + 0x003E, + 0x003F, + 0x0040, + 0x0041, + 0x0042, + 0x0043, + 0x0044, + 0x0045, + 0x0046, + 0x0047, + 0x0048, + 0x0049, + 0x004A, + 0x004B, + 0x004C, + 0x004D, + 0x004E, + 0x004F, + 0x0050, + 0x0051, + 0x0052, + 0x0053, + 0x0054, + 0x0055, + 0x0056, + 0x0057, + 0x0058, + 0x0059, + 0x005A, + 0x005B, + 0x005C, + 0x005D, + 0x005E, + 0x005F, + 0x2018, + 0x0061, + 0x0062, + 0x0063, + 0x0064, + 0x0065, + 0x0066, + 0x0067, + 0x0068, + 0x0069, + 0x006A, + 0x006B, + 0x006C, + 0x006D, + 0x006E, + 0x006F, + 0x0070, + 0x0071, + 0x0072, + 0x0073, + 0x0074, + 0x0075, + 0x0076, + 0x0077, + 0x0078, + 0x0079, + 0x007A, + 0x007B, + 0x007C, + 0x007D, + 0x007E, + 0x00A1, + 0x00A2, + 0x00A3, + 0x2044, + 0x00A5, + 0x0192, + 0x00A7, + 0x00A4, + 0x0027, + 0x201C, + 0x00AB, + 0x2039, + 0x203A, + 0xFB01, + 0xFB02, + 0x2013, + 0x2020, + 0x2021, + 0, + 0x00B6, + 0x2022, + 0x201A, + 0x201E, + 0x201D, + 0x00BB, + 0x2026, + 0x2030, + 0x00BF, + 0x0060, + 0x00B4, + 0x02C6, + 0x02DC, + 0x00AF, + 0x02D8, + 0x02D9, + 0x00A8, + 0x02DA, + 0x00B8, + 0x02DD, + 0x02DB, + 0x02C7, + 0x2014, + 0x00C6, + 0x00AA, + 0x0141, + 0x00D8, + 0x0152, + 0x00BA, + 0x00E6, + 0x0131, + 0, + 0x00F8, + 0x0153, + 0x00DF, + 0x00B9, + 0x00AC, + 0x00B5, + 0x2122, + 0x00D0, + 0x00BD, + 0x00B1, + 0x00DE, + 0x00BC, + 0x00F7, + 0x00A6, + 0x00B0, + 0x00FE, + 0x00BE, + 0x00B2, + 0x00AE, + 0x2212, + 0x00F0, + 0x00D7, + 0x00B3, + 0x00A9, + 0x00C1, + 0x00C2, + 0x00C4, + 0x00C0, + 0x00C5, + 0x00C3, + 0x00C7, + 0x00C9, + 0x00CA, + 0x00CB, + 0x00C8, + 0x00CD, + 0x00CE, + 0x00CF, + 0x00CC, + 0x00D1, + 0x00D3, + 0x00D4, + 0x00D6, + 0x00D2, + 0x00D5, + 0x0160, + 0x00DA, + 0x00DB, + 0x00DC, + 0x00D9, + 0x00DD, + 0x0178, + 0x017D, + 0x00E1, + 0x00E2, + 0x00E4, + 0x00E0, + 0x00E5, + 0x00E3, + 0x00E7, + 0x00E9, + 0x00EA, + 0x00EB, + 0x00E8, + 0x00ED, + 0x00EE, + 0x00EF, + 0x00EC, + 0x00F1, + 0x00F3, + 0x00F4, + 0x00F6, + 0x00F2, + 0x00F5, + 0x0161, + 0x00FA, + 0x00FB, + 0x00FC, + 0x00F9, + 0x00FD, + 0x00FF, + 0x017E, + 0xF721, + 0xF6F8, + 0xF724, + 0xF6E4, + 0xF726, + 0xF7B4, + 0x207D, + 0x207E, + 0x2025, + 0x2024, + 0xF730, + 0xF731, + 0xF732, + 0xF733, + 0xF734, + 0xF735, + 0xF736, + 0xF737, + 0xF738, + 0xF739, + 0xF6E2, + 0xF6DE, + 0xF6E8, + 0xF73F, + 0xF6E9, + 0xF6EA, + 0xF6E0, + 0xF6EB, + 0xF6EC, + 0xF6ED, + 0xF6EE, + 0xF6EF, + 0x207F, + 0xF6F0, + 0xF6F1, + 0xF6F2, + 0xF6F3, + 0xFB00, + 0xFB03, + 0xFB04, + 0x208D, + 0x208E, + 0xF6F6, + 0xF6E6, + 0xF760, + 0xF761, + 0xF762, + 0xF763, + 0xF764, + 0xF765, + 0xF766, + 0xF767, + 0xF768, + 0xF769, + 0xF76A, + 0xF76B, + 0xF76C, + 0xF76D, + 0xF76E, + 0xF76F, + 0xF770, + 0xF771, + 0xF772, + 0xF773, + 0xF774, + 0xF775, + 0xF776, + 0xF777, + 0xF778, + 0xF779, + 0xF77A, + 0x20A1, + 0xF6DC, + 0xF6DD, + 0xF6FE, + 0xF7A1, + 0xF7A2, + 0xF6F9, + 0xF6FD, + 0xF6FF, + 0xF7A8, + 0xF6F4, + 0xF6F5, + 0xF6F7, + 0xF7AF, + 0x2012, + 0xF6E5, + 0xF6FB, + 0xF6FC, + 0xF7B8, + 0xF7BF, + 0x215B, + 0x215C, + 0x215D, + 0x215E, + 0x2153, + 0x2154, + 0x2070, + 0x2074, + 0x2075, + 0x2076, + 0x2077, + 0x2078, + 0x2079, + 0x2080, + 0x2081, + 0x2082, + 0x2083, + 0x2084, + 0x2085, + 0x2086, + 0x2087, + 0x2088, + 0x2089, + 0xF6DF, + 0xF6E3, + 0xF6E7, + 0xF6E1, + 0xF7E0, + 0xF7E1, + 0xF7E2, + 0xF7E3, + 0xF7E4, + 0xF7E5, + 0xF7E6, + 0xF7E7, + 0xF7E8, + 0xF7E9, + 0xF7EA, + 0xF7EB, + 0xF7EC, + 0xF7ED, + 0xF7EE, + 0xF7EF, + 0xF7F0, + 0xF7F1, + 0xF7F2, + 0xF7F3, + 0xF7F4, + 0xF7F5, + 0xF7F6, + 0xF6FA, + 0xF7F8, + 0xF7F9, + 0, + 0xF7FB, + 0xF7FC, + 0xF7FD, + 0xF7FE, + 0xF7FF, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + +#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + 0x01FC, + 0x0102, + 0xF6C9, + 0x0391, + 0x0386, + 0x0100, + 0x0104, + 0x01FA, + 0x0392, + 0xF6CA, + 0x0108, + 0x010A, + 0x03A7, + 0x010E, + 0x0110, + 0xF6CB, + 0xF6CC, + 0xF6CD, + 0x0114, + 0x011A, + 0x0116, + 0x0112, + 0x014A, + 0x0118, + 0x0395, + 0x0388, + 0x0397, + 0x0389, + 0x20AC, + 0x0393, + 0x01E6, + 0x011C, + 0x0122, + 0x0120, + 0xF6CE, + 0x25CF, + 0x25AA, + 0x25AB, + 0x25A1, + 0x0126, + 0x0124, + 0xF6CF, + 0x0132, + 0x012C, + 0x0130, + 0x2111, + 0x012A, + 0x012E, + 0x0399, + 0x03AA, + 0x038A, + 0x0128, + 0x0134, + 0x039A, + 0x0136, + 0xF6BF, + 0x0139, + 0x039B, + 0x013D, + 0x013B, + 0x013F, + 0xF6D0, + 0x039C, + 0x0143, + 0x0147, + 0x0145, + 0x039D, + 0x014E, + 0x01A0, + 0x0150, + 0x014C, + 0x038F, + 0x039F, + 0x038C, + 0x01FE, + 0x03A6, + 0x03A0, + 0x03A8, + 0x0154, + 0x0158, + 0x0156, + 0x211C, + 0x03A1, + 0x250C, + 0x2514, + 0x2510, + 0x2518, + 0x253C, + 0x252C, + 0x2534, + 0x251C, + 0x2524, + 0x2500, + 0x2502, + 0x2561, + 0x2562, + 0x2556, + 0x2555, + 0x2563, + 0x2551, + 0x2557, + 0x255D, + 0x255C, + 0x255B, + 0x255E, + 0x255F, + 0x255A, + 0x2554, + 0x2569, + 0x2566, + 0x2560, + 0x2550, + 0x256C, + 0x2567, + 0x2568, + 0x2564, + 0x2565, + 0x2559, + 0x2558, + 0x2552, + 0x2553, + 0x256B, + 0x256A, + 0x015A, + 0x015C, + 0x0218, + 0x03A3, + 0x03A4, + 0x0166, + 0x0164, + 0x0162, + 0x0162, + 0x0398, + 0xF7FA, + 0x016C, + 0x01AF, + 0x0170, + 0x016A, + 0x0172, + 0x03A5, + 0x03D2, + 0x03AB, + 0x038E, + 0x016E, + 0x0168, + 0x1E82, + 0x0174, + 0x1E84, + 0x1E80, + 0x039E, + 0x0176, + 0x1EF2, + 0x0179, + 0x017B, + 0x0396, + 0x0103, + 0x0301, + 0x01FD, + 0x2015, + 0x0410, + 0x0411, + 0x0412, + 0x0413, + 0x0414, + 0x0415, + 0x0401, + 0x0416, + 0x0417, + 0x0418, + 0x0419, + 0x041A, + 0x041B, + 0x041C, + 0x041D, + 0x041E, + 0x041F, + 0x0420, + 0x0421, + 0x0422, + 0x0423, + 0x0424, + 0x0425, + 0x0426, + 0x0427, + 0x0428, + 0x0429, + 0x042A, + 0x042B, + 0x042C, + 0x042D, + 0x042E, + 0x042F, + 0x0490, + 0x0402, + 0x0403, + 0x0404, + 0x0405, + 0x0406, + 0x0407, + 0x0408, + 0x0409, + 0x040A, + 0x040B, + 0x040C, + 0x040E, + 0xF6C4, + 0xF6C5, + 0x0430, + 0x0431, + 0x0432, + 0x0433, + 0x0434, + 0x0435, + 0x0451, + 0x0436, + 0x0437, + 0x0438, + 0x0439, + 0x043A, + 0x043B, + 0x043C, + 0x043D, + 0x043E, + 0x043F, + 0x0440, + 0x0441, + 0x0442, + 0x0443, + 0x0444, + 0x0445, + 0x0446, + 0x0447, + 0x0448, + 0x0449, + 0x044A, + 0x044B, + 0x044C, + 0x044D, + 0x044E, + 0x044F, + 0x0491, + 0x0452, + 0x0453, + 0x0454, + 0x0455, + 0x0456, + 0x0457, + 0x0458, + 0x0459, + 0x045A, + 0x045B, + 0x045C, + 0x045E, + 0x040F, + 0x0462, + 0x0472, + 0x0474, + 0xF6C6, + 0x045F, + 0x0463, + 0x0473, + 0x0475, + 0xF6C7, + 0xF6C8, + 0x04D9, + 0x200E, + 0x200F, + 0x200D, + 0x066A, + 0x060C, + 0x0660, + 0x0661, + 0x0662, + 0x0663, + 0x0664, + 0x0665, + 0x0666, + 0x0667, + 0x0668, + 0x0669, + 0x061B, + 0x061F, + 0x0621, + 0x0622, + 0x0623, + 0x0624, + 0x0625, + 0x0626, + 0x0627, + 0x0628, + 0x0629, + 0x062A, + 0x062B, + 0x062C, + 0x062D, + 0x062E, + 0x062F, + 0x0630, + 0x0631, + 0x0632, + 0x0633, + 0x0634, + 0x0635, + 0x0636, + 0x0637, + 0x0638, + 0x0639, + 0x063A, + 0x0640, + 0x0641, + 0x0642, + 0x0643, + 0x0644, + 0x0645, + 0x0646, + 0x0648, + 0x0649, + 0x064A, + 0x064B, + 0x064C, + 0x064D, + 0x064E, + 0x064F, + 0x0650, + 0x0651, + 0x0652, + 0x0647, + 0x06A4, + 0x067E, + 0x0686, + 0x0698, + 0x06AF, + 0x0679, + 0x0688, + 0x0691, + 0x06BA, + 0x06D2, + 0x06D5, + 0x20AA, + 0x05BE, + 0x05C3, + 0x05D0, + 0x05D1, + 0x05D2, + 0x05D3, + 0x05D4, + 0x05D5, + 0x05D6, + 0x05D7, + 0x05D8, + 0x05D9, + 0x05DA, + 0x05DB, + 0x05DC, + 0x05DD, + 0x05DE, + 0x05DF, + 0x05E0, + 0x05E1, + 0x05E2, + 0x05E3, + 0x05E4, + 0x05E5, + 0x05E6, + 0x05E7, + 0x05E8, + 0x05E9, + 0x05EA, + 0xFB2A, + 0xFB2B, + 0xFB4B, + 0xFB1F, + 0x05F0, + 0x05F1, + 0x05F2, + 0xFB35, + 0x05B4, + 0x05B5, + 0x05B6, + 0x05BB, + 0x05B8, + 0x05B7, + 0x05B0, + 0x05B2, + 0x05B1, + 0x05B3, + 0x05C2, + 0x05C1, + 0x05B9, + 0x05BC, + 0x05BD, + 0x05BF, + 0x05C0, + 0x02BC, + 0x2105, + 0x2113, + 0x2116, + 0x202C, + 0x202D, + 0x202E, + 0x200C, + 0x066D, + 0x02BD, + 0x2135, + 0x03B1, + 0x03AC, + 0x0101, + 0x2220, + 0x2329, + 0x232A, + 0x0387, + 0x0105, + 0x01FB, + 0x2194, + 0x21D4, + 0x21D3, + 0x21D0, + 0x21D2, + 0x21D1, + 0x2193, + 0xF8E7, + 0x2190, + 0x2192, + 0x2191, + 0x2195, + 0x21A8, + 0xF8E6, + 0x2217, + 0x03B2, + 0x2588, + 0xF8F4, + 0xF8F3, + 0xF8F2, + 0xF8F1, + 0xF8FE, + 0xF8FD, + 0xF8FC, + 0xF8F0, + 0xF8EF, + 0xF8EE, + 0xF8FB, + 0xF8FA, + 0xF8F9, + 0x21B5, + 0x0109, + 0x010B, + 0x03C7, + 0x25CB, + 0x2297, + 0x2295, + 0x2663, + 0xF6C3, + 0x2245, + 0xF8E9, + 0xF6D9, + 0xF6D1, + 0xF6D2, + 0xF6D4, + 0xF6D5, + 0xF6D3, + 0xF6D6, + 0x010F, + 0x0111, + 0x03B4, + 0x2666, + 0xF6D7, + 0xF6D8, + 0x0385, + 0x2593, + 0x2584, + 0x20AB, + 0x0323, + 0xF6BE, + 0x22C5, + 0x0115, + 0x011B, + 0x0117, + 0x2208, + 0x0113, + 0x2205, + 0x014B, + 0x0119, + 0x03B5, + 0x03AD, + 0x2261, + 0x212E, + 0x03B7, + 0x03AE, + 0x203C, + 0x2203, + 0x2640, + 0x25A0, + 0x25AC, + 0x03B3, + 0x01E7, + 0x011D, + 0x0123, + 0x0121, + 0x2207, + 0x0300, + 0x0127, + 0x0125, + 0x2665, + 0x0309, + 0x2302, + 0x012D, + 0x0133, + 0x012B, + 0x2321, + 0xF8F5, + 0x2320, + 0x2229, + 0x25D8, + 0x25D9, + 0x263B, + 0x012F, + 0x03B9, + 0x03CA, + 0x0390, + 0x03AF, + 0x0129, + 0x0135, + 0x03BA, + 0x0137, + 0x0138, + 0x013A, + 0x03BB, + 0x013E, + 0x013C, + 0x0140, + 0x258C, + 0x20A4, + 0xF6C0, + 0x2227, + 0x2228, + 0x017F, + 0x2591, + 0x2642, + 0x2032, + 0x266A, + 0x266B, + 0x0144, + 0x0149, + 0x0148, + 0x0146, + 0x2209, + 0x2284, + 0x03BD, + 0x014F, + 0x01A1, + 0x0151, + 0x014D, + 0x03C9, + 0x03D6, + 0x03CE, + 0x03BF, + 0x03CC, + 0x25E6, + 0x221F, + 0x01FF, + 0xF8ED, + 0xF8EC, + 0xF8EB, + 0xF8F8, + 0xF8F7, + 0xF8F6, + 0x22A5, + 0x20A7, + 0x03C6, + 0x03D5, + 0x211E, + 0x2282, + 0x2283, + 0x221D, + 0x03C8, + 0x201B, + 0x0155, + 0xF8E5, + 0x0159, + 0x0157, + 0x2286, + 0x2287, + 0xF8E8, + 0xF6DA, + 0x2310, + 0x03C1, + 0x2590, + 0x015B, + 0x015D, + 0x0219, + 0x2033, + 0x2592, + 0x03C3, + 0x03C2, + 0x223C, + 0x263A, + 0x2660, + 0x220B, + 0x263C, + 0x03C4, + 0x0167, + 0x0165, + 0x0163, + 0x0163, + 0x2234, + 0x03B8, + 0x03D1, + 0x0303, + 0x0384, + 0xF8EA, + 0xF6DB, + 0x25BC, + 0x25C4, + 0x25BA, + 0x25B2, + 0x016D, + 0x01B0, + 0x0171, + 0x016B, + 0x2017, + 0x222A, + 0x2200, + 0x0173, + 0x2580, + 0x03C5, + 0x03CB, + 0x03B0, + 0x03CD, + 0x016F, + 0x0169, + 0x1E83, + 0x0175, + 0x1E85, + 0x2118, + 0x1E81, + 0x03BE, + 0x0177, + 0x1EF3, + 0x017A, + 0x017C, + 0x03B6, + +#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ + 0 + }; + + + + static const unsigned short t1_standard_encoding[257] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 0, + 111, + 112, + 113, + 114, + 0, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 0, + 123, + 0, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 0, + 132, + 133, + 0, + 134, + 135, + 136, + 137, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 138, + 0, + 139, + 0, + 0, + 0, + 0, + 140, + 141, + 142, + 143, + 0, + 0, + 0, + 0, + 0, + 144, + 0, + 0, + 0, + 145, + 0, + 0, + 146, + 147, + 148, + 149, + 0, + 0, + 0, + 0, + 0 + }; + + + static const unsigned short t1_expert_encoding[257] = + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 229, + 230, + 0, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 13, + 14, + 15, + 99, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 27, + 28, + 249, + 250, + 251, + 252, + 0, + 253, + 254, + 255, + 256, + 257, + 0, + 0, + 0, + 258, + 0, + 0, + 259, + 260, + 261, + 262, + 0, + 0, + 263, + 264, + 265, + 0, + 266, + 109, + 110, + 267, + 268, + 269, + 0, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 304, + 305, + 306, + 0, + 0, + 307, + 308, + 309, + 310, + 311, + 0, + 312, + 0, + 0, + 312, + 0, + 0, + 314, + 315, + 0, + 0, + 316, + 317, + 318, + 0, + 0, + 0, + 158, + 155, + 163, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 0, + 0, + 326, + 150, + 164, + 169, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 0 + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/psnames/rules.mk b/subsys/win32k/freetype/src/psnames/rules.mk new file mode 100644 index 0000000..25552b2 --- /dev/null +++ b/subsys/win32k/freetype/src/psnames/rules.mk @@ -0,0 +1,70 @@ +# +# FreeType 2 PSNames driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# PSNames driver directory +# +PSNAMES_DIR := $(SRC_)psnames +PSNAMES_DIR_ := $(PSNAMES_DIR)$(SEP) + + +# compilation flags for the driver +# +PSNAMES_COMPILE := $(FT_COMPILE) + + +# PSNames driver sources (i.e., C files) +# +PSNAMES_DRV_SRC := $(PSNAMES_DIR_)psmodule.c + + +# PSNames driver headers +# +PSNAMES_DRV_H := $(PSNAMES_DRV_SRC:%.c=%.h) \ + $(PSNAMES_DIR_)pstables.h + + +# PSNames driver object(s) +# +# PSNAMES_DRV_OBJ_M is used during `multi' builds +# PSNAMES_DRV_OBJ_S is used during `single' builds +# +PSNAMES_DRV_OBJ_M := $(PSNAMES_DRV_SRC:$(PSNAMES_DIR_)%.c=$(OBJ_)%.$O) +PSNAMES_DRV_OBJ_S := $(OBJ_)psnames.$O + +# PSNames driver source file for single build +# +PSNAMES_DRV_SRC_S := $(PSNAMES_DIR_)psmodule.c + + +# PSNames driver - single object +# +$(PSNAMES_DRV_OBJ_S): $(PSNAMES_DRV_SRC_S) $(PSNAMES_DRV_SRC) \ + $(FREETYPE_H) $(PSNAMES_DRV_H) + $(PSNAMES_COMPILE) $T$@ $(PSNAMES_DRV_SRC_S) + + +# PSNames driver - multiple objects +# +$(OBJ_)%.$O: $(PSNAMES_DIR_)%.c $(FREETYPE_H) $(PSNAMES_DRV_H) + $(PSNAMES_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(PSNAMES_DRV_OBJ_S) +DRV_OBJS_M += $(PSNAMES_DRV_OBJ_M) + + +# EOF diff --git a/subsys/win32k/freetype/src/raster1/.cvsignore b/subsys/win32k/freetype/src/raster1/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/raster1/ftraster.c b/subsys/win32k/freetype/src/raster1/ftraster.c new file mode 100644 index 0000000..65d0405 --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/ftraster.c @@ -0,0 +1,3300 @@ +/***************************************************************************/ +/* */ +/* ftraster.c */ +/* */ +/* The FreeType glyph rasterizer (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This is a rewrite of the FreeType 1.x scan-line converter */ + /* */ + /*************************************************************************/ + + +#include "ftraster.h" +#include /* for FT_MulDiv() only */ + + + /*************************************************************************/ + /* */ + /* A simple technical note on how the raster works */ + /* ----------------------------------------------- */ + /* */ + /* Converting an outline into a bitmap is achieved in several steps: */ + /* */ + /* 1 - Decomposing the outline into successive `profiles'. Each */ + /* profile is simply an array of scanline intersections on a given */ + /* dimension. A profile's main attributes are */ + /* */ + /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */ + /* */ + /* o an array of intersection coordinates for each scanline */ + /* between `Ymin' and `Ymax'. */ + /* */ + /* o a direction, indicating whether it was built going `up' or */ + /* `down', as this is very important for filling rules. */ + /* */ + /* 2 - Sweeping the target map's scanlines in order to compute segment */ + /* `spans' which are then filled. Additionally, this pass */ + /* performs drop-out control. */ + /* */ + /* The outline data is parsed during step 1 only. The profiles are */ + /* built from the bottom of the render pool, used as a stack. The */ + /* following graphics shows the profile list under construction: */ + /* */ + /* ____________________________________________________________ _ _ */ + /* | | | | | */ + /* | profile | coordinates for | profile | coordinates for |--> */ + /* | 1 | profile 1 | 2 | profile 2 |--> */ + /* |_________|___________________|_________|_________________|__ _ _ */ + /* */ + /* ^ ^ */ + /* | | */ + /* start of render pool top */ + /* */ + /* The top of the profile stack is kept in the `top' variable. */ + /* */ + /* As you can see, a profile record is pushed on top of the render */ + /* pool, which is then followed by its coordinates/intersections. If */ + /* a change of direction is detected in the outline, a new profile is */ + /* generated until the end of the outline. */ + /* */ + /* Note that when all profiles have been generated, the function */ + /* Finalize_Profile_Table() is used to record, for each profile, its */ + /* bottom-most scanline as well as the scanline above its upmost */ + /* boundary. These positions are called `y-turns' because they (sort */ + /* of) correspond to local extrema. They are stored in a sorted list */ + /* built from the top of the render pool as a downwards stack: */ + /* */ + /* _ _ _______________________________________ */ + /* | | */ + /* <--| sorted list of | */ + /* <--| extrema scanlines | */ + /* _ _ __________________|____________________| */ + /* */ + /* ^ ^ */ + /* | | */ + /* maxBuff sizeBuff = end of pool */ + /* */ + /* This list is later used during the sweep phase in order to */ + /* optimize performance (see technical note on the sweep below). */ + /* */ + /* Of course, the raster detects whether the two stacks collide and */ + /* handles the situation propertly. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** CONFIGURATION MACROS **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /* define DEBUG_RASTER if you want to compile a debugging version */ +#define xxxDEBUG_RASTER + + /* The default render pool size in bytes */ +#define RASTER_RENDER_POOL 8192 + + /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */ + /* 5-levels anti-aliasing */ +#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS +#define FT_RASTER_OPTION_ANTI_ALIASING +#endif + + /* The size of the two-lines intermediate bitmap used */ + /* for anti-aliasing, in bytes. */ +#define RASTER_GRAY_LINES 2048 + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** OTHER MACROS (do not change) **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_raster + + +#ifdef _STANDALONE_ + + + /* This macro is used to indicate that a function parameter is unused. */ + /* Its purpose is simply to reduce compiler warnings. Note also that */ + /* simply defining it as `(void)x' doesn't avoid warnings with certain */ + /* ANSI compilers (e.g. LCC). */ +#define FT_UNUSED( x ) (x) = (x) + + /* Disable the tracing mechanism for simplicity -- developers can */ + /* activate it easily by redefining these two macros. */ +#ifndef FT_ERROR +#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */ +#endif + +#ifndef FT_TRACE +#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */ +#endif + +#define Raster_Err_None 0 +#define Raster_Err_Not_Ini -1 +#define Raster_Err_Overflow -2 +#define Raster_Err_Neg_Height -3 +#define Raster_Err_Invalid -4 +#define Raster_Err_Unsupported -5 + + +#else /* _STANDALONE_ */ + + +#include +#include /* for FT_TRACE() and FT_ERROR() */ + +#define Raster_Err_None FT_Err_Ok +#define Raster_Err_Not_Ini FT_Err_Raster_Uninitialized +#define Raster_Err_Overflow FT_Err_Raster_Overflow +#define Raster_Err_Neg_Height FT_Err_Raster_Negative_Height +#define Raster_Err_Invalid FT_Err_Invalid_Outline +#define Raster_Err_Unsupported FT_Err_Unimplemented_Feature + + +#endif /* _STANDALONE_ */ + + + /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */ + /* typically a small value and the result of a*b is known to fit into */ + /* 32 bits. */ +#define FMulDiv( a, b, c ) ( (a) * (b) / (c) ) + + /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */ + /* for clipping computations. It simply uses the FT_MulDiv() function */ + /* defined in `ftcalc.h'. */ +#define SMulDiv FT_MulDiv + + /* The rasterizer is a very general purpose component; please leave */ + /* the following redefinitions there (you never know your target */ + /* environment). */ + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL (void*)0 +#endif + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#ifndef FAILURE +#define FAILURE 1 +#endif + + +#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */ + /* Setting this constant to more than 32 is a */ + /* pure waste of space. */ + +#define Pixel_Bits 6 /* fractional bits of *input* coordinates */ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** SIMPLE TYPE DECLARATIONS **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + typedef int Int; + typedef unsigned int UInt; + typedef short Short; + typedef unsigned short UShort, *PUShort; + typedef long Long, *PLong; + typedef unsigned long ULong; + + typedef unsigned char Byte, *PByte; + typedef char Bool; + + typedef struct TPoint_ + { + Long x; + Long y; + + } TPoint; + + + typedef enum TFlow_ + { + Flow_None = 0, + Flow_Up = 1, + Flow_Down = -1 + + } TFlow; + + + /* States of each line, arc, and profile */ + typedef enum TStates_ + { + Unknown, + Ascending, + Descending, + Flat + + } TStates; + + + typedef struct TProfile_ TProfile; + typedef TProfile* PProfile; + + struct TProfile_ + { + FT_F26Dot6 X; /* current coordinate during sweep */ + PProfile link; /* link to next profile - various purpose */ + PLong offset; /* start of profile's data in render pool */ + Int flow; /* Profile orientation: Asc/Descending */ + Long height; /* profile's height in scanlines */ + Long start; /* profile's starting scanline */ + + UShort countL; /* number of lines to step before this */ + /* profile becomes drawable */ + + PProfile next; /* next profile in same contour, used */ + /* during drop-out control */ + }; + + typedef PProfile TProfileList; + typedef PProfile* PProfileList; + + + /* Simple record used to implement a stack of bands, required */ + /* by the sub-banding mechanism */ + typedef struct TBand_ + { + Short y_min; /* band's minimum */ + Short y_max; /* band's maximum */ + + } TBand; + + +#define AlignProfileSize \ + ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) ) + + +#ifdef TT_STATIC_RASTER + + +#define RAS_ARGS /* void */ +#define RAS_ARG /* void */ + +#define RAS_VARS /* void */ +#define RAS_VAR /* void */ + +#define FT_UNUSED_RASTER do ; while ( 0 ) + + +#else /* TT_STATIC_RASTER */ + + +#define RAS_ARGS TRaster_Instance* raster, +#define RAS_ARG TRaster_Instance* raster + +#define RAS_VARS raster, +#define RAS_VAR raster + +#define FT_UNUSED_RASTER FT_UNUSED( raster ) + + +#endif /* TT_STATIC_RASTER */ + + + typedef struct TRaster_Instance_ TRaster_Instance; + + + /* prototypes used for sweep function dispatch */ + typedef void Function_Sweep_Init( RAS_ARGS Short* min, + Short* max ); + + typedef void Function_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ); + + typedef void Function_Sweep_Step( RAS_ARG ); + + + /* NOTE: These operations are only valid on 2's complement processors */ + +#define FLOOR( x ) ( (x) & -ras.precision ) +#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision ) +#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits ) +#define FRAC( x ) ( (x) & ( ras.precision - 1 ) ) +#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half ) + + /* Note that I have moved the location of some fields in the */ + /* structure to ensure that the most used variables are used */ + /* at the top. Thus, their offset can be coded with less */ + /* opcodes, and it results in a smaller executable. */ + + struct TRaster_Instance_ + { + Int precision_bits; /* precision related variables */ + Int precision; + Int precision_half; + Long precision_mask; + Int precision_shift; + Int precision_step; + Int precision_jitter; + + Int scale_shift; /* == precision_shift for bitmaps */ + /* == precision_shift+1 for pixmaps */ + + PLong buff; /* The profiles buffer */ + PLong sizeBuff; /* Render pool size */ + PLong maxBuff; /* Profiles buffer size */ + PLong top; /* Current cursor in buffer */ + + FT_Error error; + + Int numTurns; /* number of Y-turns in outline */ + + TPoint* arc; /* current Bezier arc pointer */ + + UShort bWidth; /* target bitmap width */ + PByte bTarget; /* target bitmap buffer */ + PByte gTarget; /* target pixmap buffer */ + + Long lastX, lastY, minY, maxY; + + UShort num_Profs; /* current number of profiles */ + + Bool fresh; /* signals a fresh new profile which */ + /* 'start' field must be completed */ + Bool joint; /* signals that the last arc ended */ + /* exactly on a scanline. Allows */ + /* removal of doublets */ + PProfile cProfile; /* current profile */ + PProfile fProfile; /* head of linked list of profiles */ + PProfile gProfile; /* contour's first profile in case */ + /* of impact */ + + TStates state; /* rendering state */ + + FT_Bitmap target; /* description of target bit/pixmap */ + FT_Outline outline; + + Long traceOfs; /* current offset in target bitmap */ + Long traceG; /* current offset in target pixmap */ + + Short traceIncr; /* sweep's increment in target bitmap */ + + Short gray_min_x; /* current min x during gray rendering */ + Short gray_max_x; /* current max x during gray rendering */ + + /* dispatch variables */ + + Function_Sweep_Init* Proc_Sweep_Init; + Function_Sweep_Span* Proc_Sweep_Span; + Function_Sweep_Span* Proc_Sweep_Drop; + Function_Sweep_Step* Proc_Sweep_Step; + + Byte dropOutControl; /* current drop_out control method */ + + Bool second_pass; /* indicates wether a horizontal pass */ + /* should be performed to control */ + /* drop-out accurately when calling */ + /* Render_Glyph. Note that there is */ + /* no horizontal pass during gray */ + /* rendering. */ + + TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */ + + TBand band_stack[16]; /* band stack used for sub-banding */ + Int band_top; /* band stack top */ + + Int count_table[256]; /* Look-up table used to quickly count */ + /* set bits in a gray 2x2 cell */ + + void* memory; + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + Byte grays[5]; /* Palette of gray levels used for */ + /* render. */ + + Byte gray_lines[RASTER_GRAY_LINES]; + /* Intermediate table used to render the */ + /* graylevels pixmaps. */ + /* gray_lines is a buffer holding two */ + /* monochrome scanlines */ + + Short gray_width; /* width in bytes of one monochrome */ + /* intermediate scanline of gray_lines. */ + /* Each gray pixel takes 2 bits long there */ + + /* The gray_lines must hold 2 lines, thus with size */ + /* in bytes of at least `gray_width*2'. */ + +#endif /* FT_RASTER_ANTI_ALIASING */ + +#if 0 + PByte flags; /* current flags table */ + PUShort outs; /* current outlines table */ + FT_Vector* coords; + + UShort nPoints; /* number of points in current glyph */ + Short nContours; /* number of contours in current glyph */ +#endif + + }; + + +#ifdef FT_CONFIG_OPTION_STATIC_RASTER + + static TRaster_Instance cur_ras; +#define ras cur_ras + +#else + +#define ras (*raster) + +#endif /* FT_CONFIG_OPTION_STATIC_RASTER */ + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** PROFILES COMPUTATION **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_High_Precision */ + /* */ + /* */ + /* Sets precision variables according to param flag. */ + /* */ + /* */ + /* High :: Set to True for high precision (typically for ppem < 18), */ + /* false otherwise. */ + /* */ + static + void Set_High_Precision( RAS_ARGS Int High ) + { + if ( High ) + { + ras.precision_bits = 10; + ras.precision_step = 128; + ras.precision_jitter = 24; + } + else + { + ras.precision_bits = 6; + ras.precision_step = 32; + ras.precision_jitter = 2; + } + + FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" )); + + ras.precision = 1L << ras.precision_bits; + ras.precision_half = ras.precision / 2; + ras.precision_shift = ras.precision_bits - Pixel_Bits; + ras.precision_mask = -ras.precision; + } + + + /*************************************************************************/ + /* */ + /* */ + /* New_Profile */ + /* */ + /* */ + /* Creates a new profile in the render pool. */ + /* */ + /* */ + /* aState :: The state/orientation of the new profile. */ + /* */ + /* */ + /* SUCCESS on success. FAILURE in case of overflow or of incoherent */ + /* profile. */ + /* */ + static + Bool New_Profile( RAS_ARGS TStates aState ) + { + if ( !ras.fProfile ) + { + ras.cProfile = (PProfile)ras.top; + ras.fProfile = ras.cProfile; + ras.top += AlignProfileSize; + } + + if ( ras.top >= ras.maxBuff ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + switch ( aState ) + { + case Ascending: + ras.cProfile->flow = Flow_Up; + FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile )); + break; + + case Descending: + ras.cProfile->flow = Flow_Down; + FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile )); + break; + + default: + FT_ERROR(( "New_Profile: invalid profile direction!\n" )); + ras.error = Raster_Err_Invalid; + return FAILURE; + } + + ras.cProfile->start = 0; + ras.cProfile->height = 0; + ras.cProfile->offset = ras.top; + ras.cProfile->link = (PProfile)0; + ras.cProfile->next = (PProfile)0; + + if ( !ras.gProfile ) + ras.gProfile = ras.cProfile; + + ras.state = aState; + ras.fresh = TRUE; + ras.joint = FALSE; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* End_Profile */ + /* */ + /* */ + /* Finalizes the current profile. */ + /* */ + /* */ + /* SUCCESS on success. FAILURE in case of overflow or incoherency. */ + /* */ + static + Bool End_Profile( RAS_ARG ) + { + Long h; + PProfile oldProfile; + + + h = ras.top - ras.cProfile->offset; + + if ( h < 0 ) + { + FT_ERROR(( "End_Profile: negative height encountered!\n" )); + ras.error = Raster_Err_Neg_Height; + return FAILURE; + } + + if ( h > 0 ) + { + FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n", + (long)ras.cProfile, ras.cProfile->start, h )); + + oldProfile = ras.cProfile; + ras.cProfile->height = h; + ras.cProfile = (PProfile)ras.top; + + ras.top += AlignProfileSize; + + ras.cProfile->height = 0; + ras.cProfile->offset = ras.top; + oldProfile->next = ras.cProfile; + ras.num_Profs++; + } + + if ( ras.top >= ras.maxBuff ) + { + FT_TRACE1(( "overflow in End_Profile\n" )); + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + ras.joint = FALSE; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Insert_Y_Turn */ + /* */ + /* */ + /* Inserts a salient into the sorted list placed on top of the render */ + /* pool. */ + /* */ + /* */ + /* New y scanline position. */ + /* */ + /* */ + /* SUCCESS on success. FAILURE in case of overflow. */ + /* */ + static + Bool Insert_Y_Turn( RAS_ARGS Int y ) + { + PLong y_turns; + Int y2, n; + + + n = ras.numTurns - 1; + y_turns = ras.sizeBuff - ras.numTurns; + + /* look for first y value that is <= */ + while ( n >= 0 && y < y_turns[n] ) + n--; + + /* if it is <, simply insert it, ignore if == */ + if ( n >= 0 && y > y_turns[n] ) + while ( n >= 0 ) + { + y2 = y_turns[n]; + y_turns[n] = y; + y = y2; + n--; + } + + if ( n < 0 ) + { + if ( ras.maxBuff <= ras.top ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + ras.maxBuff--; + ras.numTurns++; + ras.sizeBuff[-ras.numTurns] = y; + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Finalize_Profile_Table */ + /* */ + /* */ + /* Adjusts all links in the profiles list. */ + /* */ + /* */ + /* SUCCESS on success. FAILURE in case of overflow. */ + /* */ + static + Bool Finalize_Profile_Table( RAS_ARG ) + { + Int bottom, top; + UShort n; + PProfile p; + + + n = ras.num_Profs; + + if ( n > 1 ) + { + p = ras.fProfile; + while ( n > 0 ) + { + if ( n > 1 ) + p->link = (PProfile)( p->offset + p->height ); + else + p->link = NULL; + + switch ( p->flow ) + { + case Flow_Down: + bottom = p->start - p->height+1; + top = p->start; + p->start = bottom; + p->offset += p->height - 1; + break; + + case Flow_Up: + default: + bottom = p->start; + top = p->start + p->height - 1; + } + + if ( Insert_Y_Turn( RAS_VARS bottom ) || + Insert_Y_Turn( RAS_VARS top + 1 ) ) + return FAILURE; + + p = p->link; + n--; + } + } + else + ras.fProfile = NULL; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Split_Conic */ + /* */ + /* */ + /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */ + /* stack. */ + /* */ + /* */ + /* None (subdivided Bezier is taken from the top of the stack). */ + /* */ + /* */ + /* This routine is the `beef' of this component. It is _the_ inner */ + /* loop that should be optimized to hell to get the best performance. */ + /* */ + static + void Split_Conic( TPoint* base ) + { + Long a, b; + + + base[4].x = base[2].x; + b = base[1].x; + a = base[3].x = ( base[2].x + b ) / 2; + b = base[1].x = ( base[0].x + b ) / 2; + base[2].x = ( a + b ) / 2; + + base[4].y = base[2].y; + b = base[1].y; + a = base[3].y = ( base[2].y + b ) / 2; + b = base[1].y = ( base[0].y + b ) / 2; + base[2].y = ( a + b ) / 2; + + /* hand optimized. gcc doesn't seem to be too good at common */ + /* expression substitution and instruction scheduling ;-) */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Split_Cubic */ + /* */ + /* */ + /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */ + /* Bezier stack. */ + /* */ + /* */ + /* This routine is the `beef' of the component. It is one of _the_ */ + /* inner loops that should be optimized like hell to get the best */ + /* performance. */ + /* */ + static + void Split_Cubic( TPoint* base ) + { + Long a, b, c, d; + + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = ( base[0].x + c + 1 ) >> 1; + base[5].x = b = ( base[3].x + d + 1 ) >> 1; + c = ( c + d + 1 ) >> 1; + base[2].x = a = ( a + c + 1 ) >> 1; + base[4].x = b = ( b + c + 1 ) >> 1; + base[3].x = ( a + b + 1 ) >> 1; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = ( base[0].y + c + 1 ) >> 1; + base[5].y = b = ( base[3].y + d + 1 ) >> 1; + c = ( c + d + 1 ) >> 1; + base[2].y = a = ( a + c + 1 ) >> 1; + base[4].y = b = ( b + c + 1 ) >> 1; + base[3].y = ( a + b + 1 ) >> 1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Up */ + /* */ + /* */ + /* Computes the x-coordinates of an ascending line segment and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* x1 :: The x-coordinate of the segment's start point. */ + /* */ + /* y1 :: The y-coordinate of the segment's start point. */ + /* */ + /* x2 :: The x-coordinate of the segment's end point. */ + /* */ + /* y2 :: The y-coordinate of the segment's end point. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static + Bool Line_Up( RAS_ARGS Long x1, + Long y1, + Long x2, + Long y2, + Long miny, + Long maxy ) + { + Long Dx, Dy; + Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */ + Long Ix, Rx, Ax; + + PLong top; + + + Dx = x2 - x1; + Dy = y2 - y1; + + if ( Dy <= 0 || y2 < miny || y1 > maxy ) + return SUCCESS; + + if ( y1 < miny ) + { + /* Take care: miny-y1 can be a very large value; we use */ + /* a slow MulDiv function to avoid clipping bugs */ + x1 += SMulDiv( Dx, miny - y1, Dy ); + e1 = TRUNC( miny ); + f1 = 0; + } + else + { + e1 = TRUNC( y1 ); + f1 = FRAC( y1 ); + } + + if ( y2 > maxy ) + { + /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */ + e2 = TRUNC( maxy ); + f2 = 0; + } + else + { + e2 = TRUNC( y2 ); + f2 = FRAC( y2 ); + } + + if ( f1 > 0 ) + { + if ( e1 == e2 ) + return SUCCESS; + else + { + x1 += FMulDiv( Dx, ras.precision - f1, Dy ); + e1 += 1; + } + } + else + if ( ras.joint ) + { + ras.top--; + ras.joint = FALSE; + } + + ras.joint = ( f2 == 0 ); + + if ( ras.fresh ) + { + ras.cProfile->start = e1; + ras.fresh = FALSE; + } + + size = e2 - e1 + 1; + if ( ras.top + size >= ras.maxBuff ) + { + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + if ( Dx > 0 ) + { + Ix = ( ras.precision * Dx ) / Dy; + Rx = ( ras.precision * Dx ) % Dy; + Dx = 1; + } + else + { + Ix = -( ( ras.precision * -Dx ) / Dy ); + Rx = ( ras.precision * -Dx ) % Dy; + Dx = -1; + } + + Ax = -Dy; + top = ras.top; + + while ( size > 0 ) + { + *top++ = x1; + + x1 += Ix; + Ax += Rx; + if ( Ax >= 0 ) + { + Ax -= Dy; + x1 += Dx; + } + size--; + } + + ras.top = top; + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_Down */ + /* */ + /* */ + /* Computes the x-coordinates of an descending line segment and */ + /* stores them in the render pool. */ + /* */ + /* */ + /* x1 :: The x-coordinate of the segment's start point. */ + /* */ + /* y1 :: The y-coordinate of the segment's start point. */ + /* */ + /* x2 :: The x-coordinate of the segment's end point. */ + /* */ + /* y2 :: The y-coordinate of the segment's end point. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static + Bool Line_Down( RAS_ARGS Long x1, + Long y1, + Long x2, + Long y2, + Long miny, + Long maxy ) + { + Bool result, fresh; + + + fresh = ras.fresh; + + result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cProfile->start = -ras.cProfile->start; + + return result; + } + + + /* A function type describing the functions used to split Bezier arcs */ + typedef void (*TSplitter)( TPoint* base ); + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Up */ + /* */ + /* */ + /* Computes the x-coordinates of an ascending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* degree :: The degree of the Bezier arc (either 2 or 3). */ + /* */ + /* splitter :: The function to split Bezier arcs. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static + Bool Bezier_Up( RAS_ARGS Int degree, + TSplitter splitter, + Long miny, + Long maxy ) + { + Long y1, y2, e, e2, e0; + Short f1; + + TPoint* arc; + TPoint* start_arc; + + PLong top; + + + arc = ras.arc; + y1 = arc[degree].y; + y2 = arc[0].y; + top = ras.top; + + if ( y2 < miny || y1 > maxy ) + goto Fin; + + e2 = FLOOR( y2 ); + + if ( e2 > maxy ) + e2 = maxy; + + e0 = miny; + + if ( y1 < miny ) + e = miny; + else + { + e = CEILING( y1 ); + f1 = FRAC( y1 ); + e0 = e; + + if ( f1 == 0 ) + { + if ( ras.joint ) + { + top--; + ras.joint = FALSE; + } + + *top++ = arc[degree].x; + + e += ras.precision; + } + } + + if ( ras.fresh ) + { + ras.cProfile->start = TRUNC( e0 ); + ras.fresh = FALSE; + } + + if ( e2 < e ) + goto Fin; + + if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff ) + { + ras.top = top; + ras.error = Raster_Err_Overflow; + return FAILURE; + } + + start_arc = arc; + + while ( arc >= start_arc && e <= e2 ) + { + ras.joint = FALSE; + + y2 = arc[0].y; + + if ( y2 > e ) + { + y1 = arc[degree].y; + if ( y2 - y1 >= ras.precision_step ) + { + splitter( arc ); + arc += degree; + } + else + { + *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x, + e - y1, y2 - y1 ); + arc -= degree; + e += ras.precision; + } + } + else + { + if ( y2 == e ) + { + ras.joint = TRUE; + *top++ = arc[0].x; + + e += ras.precision; + } + arc -= degree; + } + } + + Fin: + ras.top = top; + ras.arc -= degree; + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Bezier_Down */ + /* */ + /* */ + /* Computes the x-coordinates of an descending Bezier arc and stores */ + /* them in the render pool. */ + /* */ + /* */ + /* degree :: The degree of the Bezier arc (either 2 or 3). */ + /* */ + /* splitter :: The function to split Bezier arcs. */ + /* */ + /* miny :: A lower vertical clipping bound value. */ + /* */ + /* maxy :: An upper vertical clipping bound value. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow. */ + /* */ + static + Bool Bezier_Down( RAS_ARGS Int degree, + TSplitter splitter, + Long miny, + Long maxy ) + { + TPoint* arc = ras.arc; + Bool result, fresh; + + + arc[0].y = -arc[0].y; + arc[1].y = -arc[1].y; + arc[2].y = -arc[2].y; + if ( degree > 2 ) + arc[3].y = -arc[3].y; + + fresh = ras.fresh; + + result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny ); + + if ( fresh && !ras.fresh ) + ras.cProfile->start = -ras.cProfile->start; + + arc[0].y = -arc[0].y; + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Line_To */ + /* */ + /* */ + /* Injects a new line segment and adjusts Profiles list. */ + /* */ + /* */ + /* x :: The x-coordinate of the segment's end point (its start point */ + /* is stored in `LastX'). */ + /* */ + /* y :: The y-coordinate of the segment's end point (its start point */ + /* is stored in `LastY'). */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ + /* profile. */ + /* */ + static + Bool Line_To( RAS_ARGS Long x, + Long y ) + { + /* First, detect a change of direction */ + + switch ( ras.state ) + { + case Unknown: + if ( y > ras.lastY ) + { + if ( New_Profile( RAS_VARS Ascending ) ) + return FAILURE; + } + else + { + if ( y < ras.lastY ) + if ( New_Profile( RAS_VARS Descending ) ) + return FAILURE; + } + break; + + case Ascending: + if ( y < ras.lastY ) + { + if ( End_Profile( RAS_VAR ) || + New_Profile( RAS_VARS Descending ) ) + return FAILURE; + } + break; + + case Descending: + if ( y > ras.lastY ) + { + if ( End_Profile( RAS_VAR ) || + New_Profile( RAS_VARS Ascending ) ) + return FAILURE; + } + break; + + default: + ; + } + + /* Then compute the lines */ + + switch ( ras.state ) + { + case Ascending: + if ( Line_Up( RAS_VARS ras.lastX, ras.lastY, + x, y, ras.minY, ras.maxY ) ) + return FAILURE; + break; + + case Descending: + if ( Line_Down( RAS_VARS ras.lastX, ras.lastY, + x, y, ras.minY, ras.maxY ) ) + return FAILURE; + break; + + default: + ; + } + + ras.lastX = x; + ras.lastY = y; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Conic_To */ + /* */ + /* */ + /* Injects a new conic arc and adjusts the profile list. */ + /* */ + /* */ + /* cx :: The x-coordinate of the arc's new control point. */ + /* */ + /* cy :: The y-coordinate of the arc's new control point. */ + /* */ + /* x :: The x-coordinate of the arc's end point (its start point is */ + /* stored in `LastX'). */ + /* */ + /* y :: The y-coordinate of the arc's end point (its start point is */ + /* stored in `LastY'). */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ + /* profile. */ + /* */ + static + Bool Conic_To( RAS_ARGS Long cx, + Long cy, + Long x, + Long y ) + { + Long y1, y2, y3, x3, ymin, ymax; + TStates state_bez; + + + ras.arc = ras.arcs; + ras.arc[2].x = ras.lastX; + ras.arc[2].y = ras.lastY; + ras.arc[1].x = cx; ras.arc[1].y = cy; + ras.arc[0].x = x; ras.arc[0].y = y; + + do + { + y1 = ras.arc[2].y; + y2 = ras.arc[1].y; + y3 = ras.arc[0].y; + x3 = ras.arc[0].x; + + /* first, categorize the Bezier arc */ + + if ( y1 <= y3 ) + { + ymin = y1; + ymax = y3; + } + else + { + ymin = y3; + ymax = y1; + } + + if ( y2 < ymin || y2 > ymax ) + { + /* this arc has no given direction, split it! */ + Split_Conic( ras.arc ); + ras.arc += 2; + } + else if ( y1 == y3 ) + { + /* this arc is flat, ignore it and pop it from the Bezier stack */ + ras.arc -= 2; + } + else + { + /* the arc is y-monotonous, either ascending or descending */ + /* detect a change of direction */ + state_bez = y1 < y3 ? Ascending : Descending; + if ( ras.state != state_bez ) + { + /* finalize current profile if any */ + if ( ras.state != Unknown && + End_Profile( RAS_VAR ) ) + goto Fail; + + /* create a new profile */ + if ( New_Profile( RAS_VARS state_bez ) ) + goto Fail; + } + + /* now call the appropriate routine */ + if ( state_bez == Ascending ) + { + if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) + goto Fail; + } + else + if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) ) + goto Fail; + } + + } while ( ras.arc >= ras.arcs ); + + ras.lastX = x3; + ras.lastY = y3; + + return SUCCESS; + + Fail: + return FAILURE; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Cubic_To */ + /* */ + /* */ + /* Injects a new cubic arc and adjusts the profile list. */ + /* */ + /* */ + /* cx1 :: The x-coordinate of the arc's first new control point. */ + /* */ + /* cy1 :: The y-coordinate of the arc's first new control point. */ + /* */ + /* cx2 :: The x-coordinate of the arc's second new control point. */ + /* */ + /* cy2 :: The y-coordinate of the arc's second new control point. */ + /* */ + /* x :: The x-coordinate of the arc's end point (its start point is */ + /* stored in `LastX'). */ + /* */ + /* y :: The y-coordinate of the arc's end point (its start point is */ + /* stored in `LastY'). */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on render pool overflow or incorrect */ + /* profile. */ + /* */ + static + Bool Cubic_To( RAS_ARGS Long cx1, + Long cy1, + Long cx2, + Long cy2, + Long x, + Long y ) + { + Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2; + TStates state_bez; + + + ras.arc = ras.arcs; + ras.arc[3].x = ras.lastX; + ras.arc[3].y = ras.lastY; + ras.arc[2].x = cx1; ras.arc[2].y = cy1; + ras.arc[1].x = cx2; ras.arc[1].y = cy2; + ras.arc[0].x = x; ras.arc[0].y = y; + + do + { + y1 = ras.arc[3].y; + y2 = ras.arc[2].y; + y3 = ras.arc[1].y; + y4 = ras.arc[0].y; + x4 = ras.arc[0].x; + + /* first, categorize the Bezier arc */ + + if ( y1 <= y4 ) + { + ymin1 = y1; + ymax1 = y4; + } + else + { + ymin1 = y4; + ymax1 = y1; + } + + if ( y2 <= y3 ) + { + ymin2 = y2; + ymax2 = y3; + } + else + { + ymin2 = y3; + ymax2 = y2; + } + + if ( ymin2 < ymin1 || ymax2 > ymax1 ) + { + /* this arc has no given direction, split it! */ + Split_Cubic( ras.arc ); + ras.arc += 3; + } + else if ( y1 == y4 ) + { + /* this arc is flat, ignore it and pop it from the Bezier stack */ + ras.arc -= 3; + } + else + { + state_bez = ( y1 <= y4 ) ? Ascending : Descending; + + /* detect a change of direction */ + if ( ras.state != state_bez ) + { + if ( ras.state != Unknown && + End_Profile( RAS_VAR ) ) + goto Fail; + + if ( New_Profile( RAS_VARS state_bez ) ) + goto Fail; + } + + /* compute intersections */ + if ( state_bez == Ascending ) + { + if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) + goto Fail; + } + else + if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) ) + goto Fail; + } + + } while ( ras.arc >= ras.arcs ); + + ras.lastX = x4; + ras.lastY = y4; + + return SUCCESS; + + Fail: + return FAILURE; + } + + +#undef SWAP_ +#define SWAP_( x, y ) do \ + { \ + Long swap = x; \ + \ + \ + x = y; \ + y = swap; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* Decompose_Curve */ + /* */ + /* */ + /* Scans the outline arays in order to emit individual segments and */ + /* Beziers by calling Line_To() and Bezier_To(). It handles all */ + /* weird cases, like when the first point is off the curve, or when */ + /* there are simply no `on' points in the contour! */ + /* */ + /* */ + /* first :: The index of the first point in the contour. */ + /* */ + /* last :: The index of the last point in the contour. */ + /* */ + /* flipped :: If set, flip the direction of the curve. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE on error. */ + /* */ + static + Bool Decompose_Curve( RAS_ARGS UShort first, + UShort last, + int flipped ) + { + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* points; + FT_Vector* point; + FT_Vector* limit; + char* tags; + + char tag; /* current point's state */ + + + points = ras.outline.points; + limit = points + last; + + v_start.x = SCALED( points[first].x ); + v_start.y = SCALED( points[first].y ); + v_last.x = SCALED( points[last].x ); + v_last.y = SCALED( points[last].y ); + + if ( flipped ) + { + SWAP_( v_start.x, v_start.y ); + SWAP_( v_last.x, v_last.y ); + } + + v_control = v_start; + + point = points + first; + tags = ras.outline.tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_Curve_Tag_Conic ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + ras.lastX = v_start.x; + ras.lastY = v_start.y; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + + switch ( tag ) + { + case FT_Curve_Tag_On: /* emit a single line_to */ + { + Long x, y; + + + x = SCALED( point->x ); + y = SCALED( point->y ); + if ( flipped ) + SWAP_( x, y ); + + if ( Line_To( RAS_VARS x, y ) ) + goto Fail; + continue; + } + + case FT_Curve_Tag_Conic: /* consume conic arcs */ + v_control.x = SCALED( point[0].x ); + v_control.y = SCALED( point[0].y ); + + if ( flipped ) + SWAP_( v_control.x, v_control.y ); + + Do_Conic: + if ( point < limit ) + { + FT_Vector v_middle; + Long x, y; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + x = SCALED( point[0].x ); + y = SCALED( point[0].y ); + + if ( flipped ) + SWAP_( x, y ); + + if ( tag == FT_Curve_Tag_On ) + { + if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) ) + goto Fail; + continue; + } + + if ( tag != FT_Curve_Tag_Conic ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + x ) / 2; + v_middle.y = ( v_control.y + y ) / 2; + + if ( Conic_To( RAS_VARS v_control.x, v_control.y, + v_middle.x, v_middle.y ) ) + goto Fail; + + v_control.x = x; + v_control.y = y; + + goto Do_Conic; + } + + if ( Conic_To( RAS_VARS v_control.x, v_control.y, + v_start.x, v_start.y ) ) + goto Fail; + + goto Close; + + default: /* FT_Curve_Tag_Cubic */ + { + Long x1, y1, x2, y2, x3, y3; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + x1 = SCALED( point[-2].x ); + y1 = SCALED( point[-2].y ); + x2 = SCALED( point[-1].x ); + y2 = SCALED( point[-1].y ); + x3 = SCALED( point[ 0].x ); + y3 = SCALED( point[ 0].y ); + + if ( flipped ) + { + SWAP_( x1, y1 ); + SWAP_( x2, y2 ); + SWAP_( x3, y3 ); + } + + if ( point <= limit ) + { + if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) ) + goto Fail; + continue; + } + + if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) ) + goto Fail; + goto Close; + } + } + } + + /* close the contour with a line segment */ + if ( Line_To( RAS_VARS v_start.x, v_start.y ) ) + goto Fail; + + Close: + return SUCCESS; + + Invalid_Outline: + ras.error = Raster_Err_Invalid; + + Fail: + return FAILURE; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Convert_Glyph */ + /* */ + /* */ + /* Converts a glyph into a series of segments and arcs and makes a */ + /* profiles list with them. */ + /* */ + /* */ + /* flipped :: If set, flip the direction of curve. */ + /* */ + /* */ + /* SUCCESS on success, FAILURE if any error was encountered during */ + /* rendering. */ + /* */ + static + Bool Convert_Glyph( RAS_ARGS int flipped ) + { + Short i; + UShort start; + + PProfile lastProfile; + + + ras.fProfile = NULL; + ras.joint = FALSE; + ras.fresh = FALSE; + + ras.maxBuff = ras.sizeBuff - AlignProfileSize; + + ras.numTurns = 0; + + ras.cProfile = (PProfile)ras.top; + ras.cProfile->offset = ras.top; + ras.num_Profs = 0; + + start = 0; + + for ( i = 0; i < ras.outline.n_contours; i++ ) + { + ras.state = Unknown; + ras.gProfile = NULL; + + if ( Decompose_Curve( RAS_VARS start, ras.outline.contours[i], flipped ) ) + return FAILURE; + + start = ras.outline.contours[i] + 1; + + /* We must now see whether the extreme arcs join or not */ + if ( FRAC( ras.lastY ) == 0 && + ras.lastY >= ras.minY && + ras.lastY <= ras.maxY ) + if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow ) + ras.top--; + /* Note that ras.gProfile can be nil if the contour was too small */ + /* to be drawn. */ + + lastProfile = ras.cProfile; + if ( End_Profile( RAS_VAR ) ) + return FAILURE; + + /* close the `next profile in contour' linked list */ + if ( ras.gProfile ) + lastProfile->next = ras.gProfile; + } + + if ( Finalize_Profile_Table( RAS_VAR ) ) + return FAILURE; + + return ( ras.top < ras.maxBuff ? SUCCESS : FAILURE ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /** **/ + /** SCAN-LINE SWEEPS AND DRAWING **/ + /** **/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Init_Linked */ + /* */ + /* Initializes an empty linked list. */ + /* */ + static + void Init_Linked( TProfileList* l ) + { + *l = NULL; + } + + + /*************************************************************************/ + /* */ + /* InsNew */ + /* */ + /* Inserts a new profile in a linked list. */ + /* */ + static + void InsNew( PProfileList list, + PProfile profile ) + { + PProfile *old, current; + Long x; + + + old = list; + current = *old; + x = profile->X; + + while ( current ) + { + if ( x < current->X ) + break; + old = ¤t->link; + current = *old; + } + + profile->link = current; + *old = profile; + } + + + /*************************************************************************/ + /* */ + /* DelOld */ + /* */ + /* Removes an old profile from a linked list. */ + /* */ + static + void DelOld( PProfileList list, + PProfile profile ) + { + PProfile *old, current; + + + old = list; + current = *old; + + while ( current ) + { + if ( current == profile ) + { + *old = current->link; + return; + } + + old = ¤t->link; + current = *old; + } + + /* we should never get there, unless the profile was not part of */ + /* the list. */ + } + + + /*************************************************************************/ + /* */ + /* Update */ + /* */ + /* Update all X offsets of a drawing list. */ + /* */ + static + void Update( PProfile first ) + { + PProfile current = first; + + + while ( current ) + { + current->X = *current->offset; + current->offset += current->flow; + current->height--; + current = current->link; + } + } + + + /*************************************************************************/ + /* */ + /* Sort */ + /* */ + /* Sorts a trace list. In 95%, the list is already sorted. We need */ + /* an algorithm which is fast in this case. Bubble sort is enough */ + /* and simple. */ + /* */ + static + void Sort( PProfileList list ) + { + PProfile *old, current, next; + + + /* First, set the new X coordinate of each profile */ + Update( *list ); + + /* Then sort them */ + old = list; + current = *old; + + if ( !current ) + return; + + next = current->link; + + while ( next ) + { + if ( current->X <= next->X ) + { + old = ¤t->link; + current = *old; + + if ( !current ) + return; + } + else + { + *old = next; + current->link = next->link; + next->link = current; + + old = list; + current = *old; + } + + next = current->link; + } + } + + + /*************************************************************************/ + /* */ + /* Vertical Sweep Procedure Set */ + /* */ + /* These four routines are used during the vertical black/white sweep */ + /* phase by the generic Draw_Sweep() function. */ + /* */ + /*************************************************************************/ + + static + void Vertical_Sweep_Init( RAS_ARGS Short* min, + Short* max ) + { + Long pitch = ras.target.pitch; + + FT_UNUSED( max ); + + + ras.traceIncr = (Short)-pitch; + ras.traceOfs = -*min * pitch; + if ( pitch > 0 ) + ras.traceOfs += ( ras.target.rows - 1 ) * pitch; + + ras.gray_min_x = 0; + ras.gray_max_x = 0; + } + + + static + void Vertical_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + Short c1, c2; + Byte f1, f2; + Byte* target; + + FT_UNUSED( y ); + FT_UNUSED( left ); + FT_UNUSED( right ); + + + /* Drop-out control */ + + e1 = TRUNC( CEILING( x1 ) ); + + if ( x2 - x1 - ras.precision <= ras.precision_jitter ) + e2 = e1; + else + e2 = TRUNC( FLOOR( x2 ) ); + + if ( e2 >= 0 && e1 < ras.bWidth ) + { + if ( e1 < 0 ) + e1 = 0; + if ( e2 >= ras.bWidth ) + e2 = ras.bWidth - 1; + + c1 = (Short)( e1 >> 3 ); + c2 = (Short)( e2 >> 3 ); + + f1 = (unsigned char)0xFF >> ( e1 & 7 ); + f2 = ~( (unsigned char)0x7F >> ( e2 & 7 ) ); + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2; + + target = ras.bTarget + ras.traceOfs + c1; + c2 -= c1; + + if ( c2 > 0 ) + { + target[0] |= f1; + + /* memset() is slower than the following code on many platforms. */ + /* This is due to the fact that, in the vast majority of cases, */ + /* the span length in bytes is relatively small. */ + c2--; + while ( c2 > 0 ) + { + *(++target) = 0xFF; + c2--; + } + target[1] |= f2; + } + else + *target |= ( f1 & f2 ); + } + } + + + static + void Vertical_Sweep_Drop( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + Short c1, f1; + + + /* Drop-out control */ + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( (x1 + x2 + 1) / 2 ); + break; + + case 2: + case 5: + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of `stubs'. */ + /* */ + /* Here, we only get rid of stubs recognized if: */ + /* */ + /* upper stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Right is the successor of P_Left in that contour */ + /* - y is the top of P_Left and P_Right */ + /* */ + /* lower stub: */ + /* */ + /* - P_Left and P_Right are in the same contour */ + /* - P_Left is the successor of P_Right in that contour */ + /* - y is the bottom of P_Left */ + /* */ + + /* FIXXXME: uncommenting this line solves the disappearing */ + /* bit problem in the `7' of verdana 10pts, but */ + /* makes a new one in the `C' of arial 14pts */ + +#if 0 + if ( x2 - x1 < ras.precision_half ) +#endif + { + /* upper stub test */ + if ( left->next == right && left->height <= 0 ) + return; + + /* lower stub test */ + if ( right->next == left && left->start == y ) + return; + } + + /* check that the rightmost pixel isn't set */ + + e1 = TRUNC( e1 ); + + c1 = (Short)( e1 >> 3 ); + f1 = e1 & 7; + + if ( e1 >= 0 && e1 < ras.bWidth && + ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.bWidth ) + { + c1 = (Short)( e1 >> 3 ); + f1 = e1 & 7; + + if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1; + if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1; + + ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 ); + } + } + + + static + void Vertical_Sweep_Step( RAS_ARG ) + { + ras.traceOfs += ras.traceIncr; + } + + + /***********************************************************************/ + /* */ + /* Horizontal Sweep Procedure Set */ + /* */ + /* These four routines are used during the horizontal black/white */ + /* sweep phase by the generic Draw_Sweep() function. */ + /* */ + /***********************************************************************/ + + static + void Horizontal_Sweep_Init( RAS_ARGS Short* min, + Short* max ) + { + /* nothing, really */ + FT_UNUSED( raster ); + FT_UNUSED( min ); + FT_UNUSED( max ); + } + + + static + void Horizontal_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte bits; + Byte f1; + + FT_UNUSED( left ); + FT_UNUSED( right ); + + + if ( x2 - x1 < ras.precision ) + { + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 == e2 ) + { + bits = ras.bTarget + ( y >> 3 ); + f1 = (Byte)( 0x80 >> ( y & 7 ) ); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + PByte p; + + + p = bits - e1*ras.target.pitch; + if ( ras.target.pitch > 0 ) + p += ( ras.target.rows - 1 ) * ras.target.pitch; + + p[0] |= f1; + } + } + } + } + + + static + void Horizontal_Sweep_Drop( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte bits; + Byte f1; + + + /* During the horizontal sweep, we only take care of drop-outs */ + + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + break; + + case 2: + case 5: + + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of `stubs'. */ + /* */ + + /* rightmost stub test */ + if ( left->next == right && left->height <= 0 ) + return; + + /* leftmost stub test */ + if ( right->next == left && left->start == y ) + return; + + /* check that the rightmost pixel isn't set */ + + e1 = TRUNC( e1 ); + + bits = ras.bTarget + ( y >> 3 ); + f1 = (Byte)( 0x80 >> ( y & 7 ) ); + + bits -= e1 * ras.target.pitch; + if ( ras.target.pitch > 0 ) + bits += ( ras.target.rows - 1 ) * ras.target.pitch; + + if ( e1 >= 0 && + e1 < ras.target.rows && + *bits & f1 ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + bits = ras.bTarget + ( y >> 3 ); + f1 = (Byte)( 0x80 >> ( y & 7 ) ); + + e1 = TRUNC( e1 ); + + if ( e1 >= 0 && e1 < ras.target.rows ) + { + bits -= e1 * ras.target.pitch; + if ( ras.target.pitch > 0 ) + bits += ( ras.target.rows - 1 ) * ras.target.pitch; + + bits[0] |= f1; + } + } + + + static + void Horizontal_Sweep_Step( RAS_ARG ) + { + /* Nothing, really */ + FT_UNUSED( raster ); + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + + /*************************************************************************/ + /* */ + /* Vertical Gray Sweep Procedure Set */ + /* */ + /* These two routines are used during the vertical gray-levels sweep */ + /* phase by the generic Draw_Sweep() function. */ + /* */ + /* NOTES */ + /* */ + /* - The target pixmap's width *must* be a multiple of 4. */ + /* */ + /* - You have to use the function Vertical_Sweep_Span() for the gray */ + /* span call. */ + /* */ + /*************************************************************************/ + + static + void Vertical_Gray_Sweep_Init( RAS_ARGS Short* min, + Short* max ) + { + Long pitch, byte_len; + + + *min = *min & -2; + *max = ( *max + 3 ) & -2; + + ras.traceOfs = 0; + pitch = ras.target.pitch; + byte_len = -pitch; + ras.traceIncr = (Short)byte_len; + ras.traceG = ( *min / 2 ) * byte_len; + + if ( pitch > 0 ) + { + ras.traceG += ( ras.target.rows - 1 ) * pitch; + byte_len = -byte_len; + } + + ras.gray_min_x = (Short)byte_len; + ras.gray_max_x = -(Short)byte_len; + } + + + static + void Vertical_Gray_Sweep_Step( RAS_ARG ) + { + Int c1, c2; + PByte pix, bit, bit2; + Int* count = ras.count_table; + Byte* grays; + + + ras.traceOfs += ras.gray_width; + + if ( ras.traceOfs > ras.gray_width ) + { + pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4; + grays = ras.grays; + + if ( ras.gray_max_x >= 0 ) + { + Long last_pixel = ras.target.width - 1; + Int last_cell = last_pixel >> 2; + Int last_bit = last_pixel & 3; + Bool over = 0; + + + if ( ras.gray_max_x >= last_cell && last_bit != 3 ) + { + ras.gray_max_x = last_cell - 1; + over = 1; + } + + if ( ras.gray_min_x < 0 ) + ras.gray_min_x = 0; + + bit = ras.bTarget + ras.gray_min_x; + bit2 = bit + ras.gray_width; + + c1 = ras.gray_max_x - ras.gray_min_x; + + while ( c1 >= 0 ) + { + c2 = count[*bit] + count[*bit2]; + + if ( c2 ) + { + pix[0] = grays[(c2 >> 12) & 0x000F]; + pix[1] = grays[(c2 >> 8 ) & 0x000F]; + pix[2] = grays[(c2 >> 4 ) & 0x000F]; + pix[3] = grays[ c2 & 0x000F]; + + *bit = 0; + *bit2 = 0; + } + + bit++; + bit2++; + pix += 4; + c1--; + } + + if ( over ) + { + c2 = count[*bit] + count[*bit2]; + if ( c2 ) + { + switch ( last_bit ) + { + case 2: + pix[2] = grays[(c2 >> 4 ) & 0x000F]; + case 1: + pix[1] = grays[(c2 >> 8 ) & 0x000F]; + default: + pix[0] = grays[(c2 >> 12) & 0x000F]; + } + + *bit = 0; + *bit2 = 0; + } + } + } + + ras.traceOfs = 0; + ras.traceG += ras.traceIncr; + + ras.gray_min_x = 32000; + ras.gray_max_x = -32000; + } + } + + + static + void Horizontal_Gray_Sweep_Span( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + /* nothing, really */ + FT_UNUSED( raster ); + FT_UNUSED( y ); + FT_UNUSED( x1 ); + FT_UNUSED( x2 ); + FT_UNUSED( left ); + FT_UNUSED( right ); + } + + + static + void Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y, + FT_F26Dot6 x1, + FT_F26Dot6 x2, + PProfile left, + PProfile right ) + { + Long e1, e2; + PByte pixel; + Byte color; + + + /* During the horizontal sweep, we only take care of drop-outs */ + e1 = CEILING( x1 ); + e2 = FLOOR ( x2 ); + + if ( e1 > e2 ) + { + if ( e1 == e2 + ras.precision ) + { + switch ( ras.dropOutControl ) + { + case 1: + e1 = e2; + break; + + case 4: + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + break; + + case 2: + case 5: + + /* Drop-out Control Rule #4 */ + + /* The spec is not very clear regarding rule #4. It */ + /* presents a method that is way too costly to implement */ + /* while the general idea seems to get rid of `stubs'. */ + /* */ + + /* rightmost stub test */ + if ( left->next == right && left->height <= 0 ) + return; + + /* leftmost stub test */ + if ( right->next == left && left->start == y ) + return; + + if ( ras.dropOutControl == 2 ) + e1 = e2; + else + e1 = CEILING( ( x1 + x2 + 1 ) / 2 ); + + break; + + default: + return; /* unsupported mode */ + } + } + else + return; + } + + if ( e1 >= 0 ) + { + if ( x2 - x1 >= ras.precision_half ) + color = ras.grays[2]; + else + color = ras.grays[1]; + + e1 = TRUNC( e1 ) / 2; + if ( e1 < ras.target.rows ) + { + pixel = ras.gTarget - e1 * ras.target.pitch + y / 2; + if ( ras.target.pitch > 0 ) + pixel += ( ras.target.rows - 1 ) * ras.target.pitch; + + if ( pixel[0] == ras.grays[0] ) + pixel[0] = color; + } + } + } + + +#endif /* FT_RASTER_OPTION_ANTI_ALIASING */ + + + /*************************************************************************/ + /* */ + /* Generic Sweep Drawing routine */ + /* */ + /*************************************************************************/ + + static + Bool Draw_Sweep( RAS_ARG ) + { + Short y, y_change, y_height; + + PProfile P, Q, P_Left, P_Right; + + Short min_Y, max_Y, top, bottom, dropouts; + + Long x1, x2, xs, e1, e2; + + TProfileList wait; + TProfileList draw_left, draw_right; + + + /* Init empty linked lists */ + + Init_Linked( &wait ); + + Init_Linked( &draw_left ); + Init_Linked( &draw_right ); + + /* first, compute min and max Y */ + + P = ras.fProfile; + max_Y = (Short)TRUNC( ras.minY ); + min_Y = (Short)TRUNC( ras.maxY ); + + while ( P ) + { + Q = P->link; + + bottom = (Short)P->start; + top = (Short)P->start + P->height - 1; + + if ( min_Y > bottom ) min_Y = bottom; + if ( max_Y < top ) max_Y = top; + + P->X = 0; + InsNew( &wait, P ); + + P = Q; + } + + /* Check the Y-turns */ + if ( ras.numTurns == 0 ) + { + ras.error = Raster_Err_Invalid; + return FAILURE; + } + + /* Now inits the sweep */ + + ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y ); + + /* Then compute the distance of each profile from min_Y */ + + P = wait; + + while ( P ) + { + P->countL = P->start - min_Y; + P = P->link; + } + + /* Let's go */ + + y = min_Y; + y_height = 0; + + if ( ras.numTurns > 0 && + ras.sizeBuff[-ras.numTurns] == min_Y ) + ras.numTurns--; + + while ( ras.numTurns > 0 ) + { + /* look in the wait list for new activations */ + + P = wait; + + while ( P ) + { + Q = P->link; + P->countL -= y_height; + if ( P->countL == 0 ) + { + DelOld( &wait, P ); + + switch ( P->flow ) + { + case Flow_Up: + InsNew( &draw_left, P ); + break; + + case Flow_Down: + InsNew( &draw_right, P ); + break; + } + } + + P = Q; + } + + /* Sort the drawing lists */ + + Sort( &draw_left ); + Sort( &draw_right ); + + y_change = (Short)ras.sizeBuff[-ras.numTurns--]; + y_height = y_change - y; + + while ( y < y_change ) + { + /* Let's trace */ + + dropouts = 0; + + P_Left = draw_left; + P_Right = draw_right; + + while ( P_Left ) + { + x1 = P_Left ->X; + x2 = P_Right->X; + + if ( x1 > x2 ) + { + xs = x1; + x1 = x2; + x2 = xs; + } + + if ( x2 - x1 <= ras.precision ) + { + e1 = FLOOR( x1 ); + e2 = CEILING( x2 ); + + if ( ras.dropOutControl != 0 && + ( e1 > e2 || e2 == e1 + ras.precision ) ) + { + /* a drop out was detected */ + + P_Left ->X = x1; + P_Right->X = x2; + + /* mark profile for drop-out processing */ + P_Left->countL = 1; + dropouts++; + + goto Skip_To_Next; + } + } + + ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right ); + + Skip_To_Next: + + P_Left = P_Left->link; + P_Right = P_Right->link; + } + + /* now perform the dropouts _after_ the span drawing -- */ + /* drop-outs processing has been moved out of the loop */ + /* for performance tuning */ + if ( dropouts > 0 ) + goto Scan_DropOuts; + + Next_Line: + + ras.Proc_Sweep_Step( RAS_VAR ); + + y++; + + if ( y < y_change ) + { + Sort( &draw_left ); + Sort( &draw_right ); + } + } + + /* Now finalize the profiles that needs it */ + + { + PProfile Q, P; + + + P = draw_left; + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_left, P ); + P = Q; + } + } + + { + PProfile Q, P = draw_right; + + + while ( P ) + { + Q = P->link; + if ( P->height == 0 ) + DelOld( &draw_right, P ); + P = Q; + } + } + } + + /* for gray-scaling, flushes the bitmap scanline cache */ + while ( y <= max_Y ) + { + ras.Proc_Sweep_Step( RAS_VAR ); + y++; + } + + return SUCCESS; + + Scan_DropOuts: + + P_Left = draw_left; + P_Right = draw_right; + + while ( P_Left ) + { + if ( P_Left->countL ) + { + P_Left->countL = 0; +#if 0 + dropouts--; /* -- this is useful when debugging only */ +#endif + ras.Proc_Sweep_Drop( RAS_VARS y, + P_Left->X, + P_Right->X, + P_Left, + P_Right ); + } + + P_Left = P_Left->link; + P_Right = P_Right->link; + } + + goto Next_Line; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Single_Pass */ + /* */ + /* */ + /* Performs one sweep with sub-banding. */ + /* */ + /* */ + /* flipped :: If set, flip the direction of the outline. */ + /* */ + /* */ + /* Renderer error code. */ + /* */ + static + int Render_Single_Pass( RAS_ARGS Bool flipped ) + { + Short i, j, k; + + + while ( ras.band_top >= 0 ) + { + ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision; + ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision; + + ras.top = ras.buff; + + ras.error = Raster_Err_None; + + if ( Convert_Glyph( RAS_VARS flipped ) ) + { + if ( ras.error != Raster_Err_Overflow ) + return FAILURE; + + ras.error = Raster_Err_None; + + /* sub-banding */ + +#ifdef DEBUG_RASTER + ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) ); +#endif + + i = ras.band_stack[ras.band_top].y_min; + j = ras.band_stack[ras.band_top].y_max; + + k = ( i + j ) / 2; + + if ( ras.band_top >= 7 || k < i ) + { + ras.band_top = 0; + ras.error = Raster_Err_Invalid; + + return ras.error; + } + + ras.band_stack[ras.band_top + 1].y_min = k; + ras.band_stack[ras.band_top + 1].y_max = j; + + ras.band_stack[ras.band_top].y_max = k - 1; + + ras.band_top++; + } + else + { + if ( ras.fProfile ) + if ( Draw_Sweep( RAS_VAR ) ) + return ras.error; + ras.band_top--; + } + } + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Glyph */ + /* */ + /* */ + /* Renders a glyph in a bitmap. Sub-banding if needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones! */ + /* */ + LOCAL_FUNC + FT_Error Render_Glyph( RAS_ARG ) + { + FT_Error error; + + + Set_High_Precision( RAS_VARS ras.outline.flags & + ft_outline_high_precision ); + ras.scale_shift = ras.precision_shift; + ras.dropOutControl = 2; + ras.second_pass = !( ras.outline.flags & ft_outline_single_pass ); + + /* Vertical Sweep */ + ras.Proc_Sweep_Init = Vertical_Sweep_Init; + ras.Proc_Sweep_Span = Vertical_Sweep_Span; + ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; + ras.Proc_Sweep_Step = Vertical_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.rows - 1; + + ras.bWidth = ras.target.width; + ras.bTarget = (Byte*)ras.target.buffer; + + if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 ) + return error; + + /* Horizontal Sweep */ + if ( ras.second_pass && ras.dropOutControl != 0 ) + { + ras.Proc_Sweep_Init = Horizontal_Sweep_Init; + ras.Proc_Sweep_Span = Horizontal_Sweep_Span; + ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop; + ras.Proc_Sweep_Step = Horizontal_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width - 1; + + if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 ) + return error; + } + + return FT_Err_Ok; + } + + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + + /*************************************************************************/ + /* */ + /* */ + /* Render_Gray_Glyph */ + /* */ + /* */ + /* Renders a glyph with grayscaling. Sub-banding if needed. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Render_Gray_Glyph( RAS_ARG ) + { + Long pixel_width; + FT_Error error; + + + Set_High_Precision( RAS_VARS ras.outline.flags & + ft_outline_high_precision ); + ras.scale_shift = ras.precision_shift + 1; + ras.dropOutControl = 2; + ras.second_pass = !( ras.outline.flags & ft_outline_single_pass ); + + /* Vertical Sweep */ + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = 2 * ras.target.rows - 1; + + ras.bWidth = ras.gray_width; + pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 ); + + if ( ras.bWidth > pixel_width ) + ras.bWidth = pixel_width; + + ras.bWidth = ras.bWidth * 8; + ras.bTarget = (Byte*)ras.gray_lines; + ras.gTarget = (Byte*)ras.target.buffer; + + ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init; + ras.Proc_Sweep_Span = Vertical_Sweep_Span; + ras.Proc_Sweep_Drop = Vertical_Sweep_Drop; + ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step; + + error = Render_Single_Pass( RAS_VARS 0 ); + if ( error ) + return error; + + /* Horizontal Sweep */ + if ( ras.second_pass && ras.dropOutControl != 0 ) + { + ras.Proc_Sweep_Init = Horizontal_Sweep_Init; + ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span; + ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop; + ras.Proc_Sweep_Step = Horizontal_Sweep_Step; + + ras.band_top = 0; + ras.band_stack[0].y_min = 0; + ras.band_stack[0].y_max = ras.target.width * 2 - 1; + + error = Render_Single_Pass( RAS_VARS 1 ); + if ( error ) + return error; + } + + return FT_Err_Ok; + } + +#else /* FT_RASTER_OPTION_ANTI_ALIASING */ + + LOCAL_FUNC + FT_Error Render_Gray_Glyph( RAS_ARG ) + { + FT_UNUSED_RASTER; + + return FT_Err_Cannot_Render_Glyph; + } + +#endif /* FT_RASTER_OPTION_ANTI_ALIASING */ + + + static + void ft_black_init( TRaster_Instance* raster ) + { + FT_UInt n; + FT_ULong c; + + + /* setup count table */ + for ( n = 0; n < 256; n++ ) + { + c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 ); + + c = ( ( c << 6 ) & 0x3000 ) | + ( ( c << 4 ) & 0x0300 ) | + ( ( c << 2 ) & 0x0030 ) | + (c & 0x0003 ); + + raster->count_table[n] = c; + } + +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + /* set default 5-levels gray palette */ + for ( n = 0; n < 5; n++ ) + raster->grays[n] = n * 255 / 4; + + raster->gray_width = RASTER_GRAY_LINES / 2; + +#endif + } + + + /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ + /**** a static object. *****/ + + +#ifdef _STANDALONE_ + + + static + int ft_black_new( void* memory, + FT_Raster *araster ) + { + static FT_RasterRec_ the_raster; + + + *araster = &the_raster; + memset( &the_raster, sizeof ( the_raster ), 0 ); + ft_black_init( &the_raster ); + + return 0; + } + + + static + void ft_black_done( FT_Raster raster ) + { + /* nothing */ + raster->init = 0; + } + + +#else /* _STANDALONE_ */ + + + static + int ft_black_new( FT_Memory memory, + TRaster_Instance** araster ) + { + FT_Error error; + TRaster_Instance* raster; + + + *araster = 0; + if ( !ALLOC( raster, sizeof ( *raster ) ) ) + { + raster->memory = memory; + ft_black_init( raster ); + + *araster = raster; + } + + return error; + } + + + static + void ft_black_done( TRaster_Instance* raster ) + { + FT_Memory memory = (FT_Memory)raster->memory; + FREE( raster ); + } + + +#endif /* _STANDALONE_ */ + + + static + void ft_black_reset( TRaster_Instance* raster, + const char* pool_base, + long pool_size ) + { + if ( raster && pool_base && pool_size >= 4096 ) + { + /* save the pool */ + raster->buff = (PLong)pool_base; + raster->sizeBuff = raster->buff + pool_size / sizeof ( Long ); + } + } + + + static + void ft_black_set_mode( TRaster_Instance* raster, + unsigned long mode, + const char* palette ) + { +#ifdef FT_RASTER_OPTION_ANTI_ALIASING + + if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) ) + { + /* set 5-levels gray palette */ + raster->grays[0] = palette[0]; + raster->grays[1] = palette[1]; + raster->grays[2] = palette[2]; + raster->grays[3] = palette[3]; + raster->grays[4] = palette[4]; + } + +#else + + FT_UNUSED( raster ); + FT_UNUSED( mode ); + FT_UNUSED( palette ); + +#endif + } + + + static + int ft_black_render( TRaster_Instance* raster, + FT_Raster_Params* params ) + { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + + + if ( !raster || !raster->buff || !raster->sizeBuff ) + return Raster_Err_Not_Ini; + + if ( !outline || !outline->contours || !outline->points ) + return Raster_Err_Invalid; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return Raster_Err_None; + + if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 ) + return Raster_Err_Invalid; + + if ( !target_map || !target_map->buffer ) + return Raster_Err_Invalid; + + /* this version of the raster does not support direct rendering, sorry */ + if ( params->flags & ft_raster_flag_direct ) + return Raster_Err_Unsupported; + + ras.outline = *outline; + ras.target = *target_map; + + return ( ( params->flags & ft_raster_flag_aa ) + ? Render_Gray_Glyph( raster ) + : Render_Glyph( raster ) ); + } + + + FT_Raster_Funcs ft_standard_raster = + { + ft_glyph_format_outline, + (FT_Raster_New_Func) ft_black_new, + (FT_Raster_Reset_Func) ft_black_reset, + (FT_Raster_Set_Mode_Func)ft_black_set_mode, + (FT_Raster_Render_Func) ft_black_render, + (FT_Raster_Done_Func) ft_black_done + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/raster1/ftraster.h b/subsys/win32k/freetype/src/raster1/ftraster.h new file mode 100644 index 0000000..5c7faae --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/ftraster.h @@ -0,0 +1,50 @@ +/***************************************************************************/ +/* */ +/* ftraster.h */ +/* */ +/* The FreeType glyph rasterizer (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used */ +/* modified and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTRASTER_H +#define FTRASTER_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include + + + /*************************************************************************/ + /* */ + /* Uncomment the following line if you are using ftraster.c as a */ + /* standalone module, fully independent of FreeType. */ + /* */ +/* #define _STANDALONE_ */ + +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_standard_raster; + +#ifdef __cplusplus + } +#endif + + +#endif /* FTRASTER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/raster1/ftrend1.c b/subsys/win32k/freetype/src/raster1/ftrend1.c new file mode 100644 index 0000000..096b1e2 --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/ftrend1.c @@ -0,0 +1,275 @@ +/***************************************************************************/ +/* */ +/* ftrend1.c */ +/* */ +/* The FreeType glyph rasterizer interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ftrend1.h" +#include "ftraster.h" + +#else + +#include +#include + +#endif + + + /* initialize renderer -- init its raster */ + static + FT_Error ft_raster1_init( FT_Renderer render ) + { + FT_Library library = FT_MODULE_LIBRARY( render ); + + + render->clazz->raster_class->raster_reset( render->raster, + library->raster_pool, + library->raster_pool_size ); + + return FT_Err_Ok; + } + + + /* set render-specific mode */ + static + FT_Error ft_raster1_set_mode( FT_Renderer render, + FT_ULong mode_tag, + FT_Pointer data ) + { + /* we simply pass it to the raster */ + return render->clazz->raster_class->raster_set_mode( render->raster, + mode_tag, + data ); + } + + + /* transform a given glyph image */ + static + FT_Error ft_raster1_transform( FT_Renderer render, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_Error error = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + if ( matrix ) + FT_Outline_Transform( &slot->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &slot->outline, delta->x, delta->y ); + + Exit: + return error; + } + + + /* return the glyph's control box */ + static + void ft_raster1_get_cbox( FT_Renderer render, + FT_GlyphSlot slot, + FT_BBox* cbox ) + { + MEM_Set( cbox, 0, sizeof ( *cbox ) ); + + if ( slot->format == render->glyph_format ) + FT_Outline_Get_CBox( &slot->outline, cbox ); + } + + + /* convert a slot's glyph image into a bitmap */ + static + FT_Error ft_raster1_render( FT_Renderer render, + FT_GlyphSlot slot, + FT_UInt mode, + FT_Vector* origin ) + { + FT_Error error; + FT_Outline* outline; + FT_BBox cbox; + FT_UInt width, height, pitch; + FT_Bitmap* bitmap; + FT_Memory memory; + + FT_Raster_Params params; + + + /* check glyph image format */ + if ( slot->format != render->glyph_format ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + /* check rendering mode */ + if ( mode != ft_render_mode_mono ) + { + /* raster1 is only capable of producing monochrome bitmaps */ + if ( render->clazz == &ft_raster1_renderer_class ) + return FT_Err_Cannot_Render_Glyph; + } + else + { + /* raster5 is only capable of producing 5-gray-levels bitmaps */ + if ( render->clazz == &ft_raster5_renderer_class ) + return FT_Err_Cannot_Render_Glyph; + } + + outline = &slot->outline; + + /* translate the outline to the new origin if needed */ + if ( origin ) + FT_Outline_Translate( outline, origin->x, origin->y ); + + /* compute the control box, and grid fit it */ + FT_Outline_Get_CBox( outline, &cbox ); + + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax + 63 ) & -64; + cbox.yMax = ( cbox.yMax + 63 ) & -64; + + width = ( cbox.xMax - cbox.xMin ) >> 6; + height = ( cbox.yMax - cbox.yMin ) >> 6; + bitmap = &slot->bitmap; + memory = render->root.memory; + + /* release old bitmap buffer */ + if ( slot->flags & ft_glyph_own_bitmap ) + { + FREE( bitmap->buffer ); + slot->flags &= ~ft_glyph_own_bitmap; + } + + /* allocate new one, depends on pixel format */ + if ( !( mode & ft_render_mode_mono ) ) + { + /* we pad to 32 bits, only for backwards compatibility with FT 1.x */ + pitch = ( width + 3 ) & -4; + bitmap->pixel_mode = ft_pixel_mode_grays; + bitmap->num_grays = 256; + } + else + { + pitch = ( width + 7 ) >> 3; + bitmap->pixel_mode = ft_pixel_mode_mono; + } + + bitmap->width = width; + bitmap->rows = height; + bitmap->pitch = pitch; + + if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) + goto Exit; + + slot->flags |= ft_glyph_own_bitmap; + + /* translate outline to render it into the bitmap */ + FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); + + /* set up parameters */ + params.target = bitmap; + params.source = outline; + params.flags = 0; + + if ( bitmap->pixel_mode == ft_pixel_mode_grays ) + params.flags |= ft_raster_flag_aa; + + /* render outline into the bitmap */ + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; + + slot->format = ft_glyph_format_bitmap; + slot->bitmap_left = cbox.xMin >> 6; + slot->bitmap_top = cbox.yMax >> 6; + + Exit: + return error; + } + + + const FT_Renderer_Class ft_raster1_renderer_class = + { + { + ft_module_renderer, + sizeof( FT_RendererRec ), + + "raster1", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_raster1_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + ft_glyph_format_outline, + + (FTRenderer_render) ft_raster1_render, + (FTRenderer_transform)ft_raster1_transform, + (FTRenderer_getCBox) ft_raster1_get_cbox, + (FTRenderer_setMode) ft_raster1_set_mode, + + (FT_Raster_Funcs*) &ft_standard_raster + }; + + + /* this renderer is _NOT_ part of the default modules, you'll need */ + /* to register it by hand in your application. It should only be */ + /* used for backwards-compatibility with FT 1.x anyway. */ + const FT_Renderer_Class ft_raster5_renderer_class = + { + { + ft_module_renderer, + sizeof( FT_RendererRec ), + + "raster5", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_raster1_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + ft_glyph_format_outline, + + (FTRenderer_render) ft_raster1_render, + (FTRenderer_transform)ft_raster1_transform, + (FTRenderer_getCBox) ft_raster1_get_cbox, + (FTRenderer_setMode) ft_raster1_set_mode, + + (FT_Raster_Funcs*) &ft_standard_raster + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/raster1/ftrend1.h b/subsys/win32k/freetype/src/raster1/ftrend1.h new file mode 100644 index 0000000..b8fff83 --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/ftrend1.h @@ -0,0 +1,37 @@ +/***************************************************************************/ +/* */ +/* ftrend1.h */ +/* */ +/* The FreeType glyph rasterizer interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTREND1_H +#define FTREND1_H + +#include + + + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster1_renderer_class; + + /* this renderer is _NOT_ part of the default modules, you'll need */ + /* to register it by hand in your application. It should only be */ + /* used for backwards-compatibility with FT 1.x anyway. */ + /* */ + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster5_renderer_class; + + +#endif /* FTREND1_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/raster1/module.mk b/subsys/win32k/freetype/src/raster1/module.mk new file mode 100644 index 0000000..c1ceb21 --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_raster1_module + +add_raster1_module: + $(OPEN_DRIVER)ft_raster1_renderer_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)raster1 $(ECHO_DRIVER_DESC)monochrome bitmap renderer$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/raster1/raster1.c b/subsys/win32k/freetype/src/raster1/raster1.c new file mode 100644 index 0000000..a77e775 --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/raster1.c @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* raster1.c */ +/* */ +/* FreeType monochrome rasterer module component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#ifdef FT_FLAT_COMPILE + +#include "ftraster.c" +#include "ftrend1.c" + +#else + +#include +#include + +#endif + + +/* END */ diff --git a/subsys/win32k/freetype/src/raster1/rules.mk b/subsys/win32k/freetype/src/raster1/rules.mk new file mode 100644 index 0000000..3810845 --- /dev/null +++ b/subsys/win32k/freetype/src/raster1/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 renderer module build rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# raster1 driver directory +# +RAS1_DIR := $(SRC_)raster1 +RAS1_DIR_ := $(RAS1_DIR)$(SEP) + +# compilation flags for the driver +# +RAS1_COMPILE := $(FT_COMPILE) + + +# raster1 driver sources (i.e., C files) +# +RAS1_DRV_SRC := $(RAS1_DIR_)ftraster.c \ + $(RAS1_DIR_)ftrend1.c + + +# raster1 driver headers +# +RAS1_DRV_H := $(RAS1_DRV_SRC:%.c=%.h) + + +# raster1 driver object(s) +# +# RAS1_DRV_OBJ_M is used during `multi' builds. +# RAS1_DRV_OBJ_S is used during `single' builds. +# +RAS1_DRV_OBJ_M := $(RAS1_DRV_SRC:$(RAS1_DIR_)%.c=$(OBJ_)%.$O) +RAS1_DRV_OBJ_S := $(OBJ_)raster1.$O + +# raster1 driver source file for single build +# +RAS1_DRV_SRC_S := $(RAS1_DIR_)raster1.c + + +# raster1 driver - single object +# +$(RAS1_DRV_OBJ_S): $(RAS1_DRV_SRC_S) $(RAS1_DRV_SRC) \ + $(FREETYPE_H) $(RAS1_DRV_H) + $(RAS1_COMPILE) $T$@ $(RAS1_DRV_SRC_S) + + +# raster1 driver - multiple objects +# +$(OBJ_)%.$O: $(RAS1_DIR_)%.c $(FREETYPE_H) $(RAS1_DRV_H) + $(RAS1_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(RAS1_DRV_OBJ_S) +DRV_OBJS_M += $(RAS1_DRV_OBJ_M) + + +# EOF diff --git a/subsys/win32k/freetype/src/sfnt/.cvsignore b/subsys/win32k/freetype/src/sfnt/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/sfnt/module.mk b/subsys/win32k/freetype/src/sfnt/module.mk new file mode 100644 index 0000000..48b494f --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_sfnt_module + +add_sfnt_module: + $(OPEN_DRIVER)sfnt_module_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)sfnt $(ECHO_DRIVER_DESC)helper module for TrueType & OpenType formats$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/sfnt/rules.mk b/subsys/win32k/freetype/src/sfnt/rules.mk new file mode 100644 index 0000000..2255e6a --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/rules.mk @@ -0,0 +1,73 @@ +# +# FreeType 2 SFNT driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# SFNT driver directory +# +SFNT_DIR := $(SRC_)sfnt +SFNT_DIR_ := $(SFNT_DIR)$(SEP) + + +# compilation flags for the driver +# +SFNT_COMPILE := $(FT_COMPILE) + + +# SFNT driver sources (i.e., C files) +# +SFNT_DRV_SRC := $(SFNT_DIR_)ttload.c \ + $(SFNT_DIR_)ttcmap.c \ + $(SFNT_DIR_)ttsbit.c \ + $(SFNT_DIR_)ttpost.c \ + $(SFNT_DIR_)sfobjs.c \ + $(SFNT_DIR_)sfdriver.c + +# SFNT driver headers +# +SFNT_DRV_H := $(SFNT_DRV_SRC:%c=%h) + + +# SFNT driver object(s) +# +# SFNT_DRV_OBJ_M is used during `multi' builds. +# SFNT_DRV_OBJ_S is used during `single' builds. +# +SFNT_DRV_OBJ_M := $(SFNT_DRV_SRC:$(SFNT_DIR_)%.c=$(OBJ_)%.$O) +SFNT_DRV_OBJ_S := $(OBJ_)sfnt.$O + +# SFNT driver source file for single build +# +SFNT_DRV_SRC_S := $(SFNT_DIR_)sfnt.c + + +# SFNT driver - single object +# +$(SFNT_DRV_OBJ_S): $(SFNT_DRV_SRC_S) $(SFNT_DRV_SRC) \ + $(FREETYPE_H) $(SFNT_DRV_H) + $(SFNT_COMPILE) $T$@ $(SFNT_DRV_SRC_S) + + +# SFNT driver - multiple objects +# +$(OBJ_)%.$O: $(SFNT_DIR_)%.c $(FREETYPE_H) $(SFNT_DRV_H) + $(SFNT_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(SFNT_DRV_OBJ_S) +DRV_OBJS_M += $(SFNT_DRV_OBJ_M) + + +# EOF diff --git a/subsys/win32k/freetype/src/sfnt/sfdriver.c b/subsys/win32k/freetype/src/sfnt/sfdriver.c new file mode 100644 index 0000000..29862e7 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/sfdriver.c @@ -0,0 +1,225 @@ +/***************************************************************************/ +/* */ +/* sfdriver.c */ +/* */ +/* High-level SFNT driver interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "sfdriver.h" +#include "ttload.h" +#include "ttsbit.h" +#include "ttpost.h" +#include "ttcmap.h" +#include "sfobjs.h" + +#else + +#include +#include +#include +#include +#include +#include + +#endif + + +#include /* for strcmp() */ + + + static + void* get_sfnt_table( TT_Face face, + FT_Sfnt_Tag tag ) + { + void* table; + + + switch ( tag ) + { + case ft_sfnt_head: + table = &face->header; + break; + + case ft_sfnt_hhea: + table = &face->horizontal; + break; + + case ft_sfnt_vhea: + table = face->vertical_info ? &face->vertical : 0; + break; + + case ft_sfnt_os2: + table = face->os2.version == 0xFFFF ? 0 : &face->os2; + break; + + case ft_sfnt_post: + table = &face->postscript; + break; + + case ft_sfnt_maxp: + table = &face->max_profile; + break; + + case ft_sfnt_pclt: + table = face->pclt.Version ? &face->pclt : 0; + break; + + default: + table = 0; + } + + return table; + } + + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + static + FT_Error get_sfnt_glyph_name( TT_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_String* gname; + FT_Error error; + + + error = TT_Get_PS_Name( face, glyph_index, &gname ); + if ( !error && buffer_max > 0 ) + { + FT_UInt len = strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return error; + } + + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + static + FT_Module_Interface SFNT_Get_Interface( FT_Module module, + const char* interface ) + { + FT_UNUSED( module ); + + if ( strcmp( interface, "get_sfnt" ) == 0 ) + return (FT_Module_Interface)get_sfnt_table; + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + if ( strcmp( interface, "glyph_name" ) == 0 ) + return (FT_Module_Interface)get_sfnt_glyph_name; +#endif + return 0; + } + + + static + const SFNT_Interface sfnt_interface = + { + TT_Goto_Table, + + SFNT_Init_Face, + SFNT_Load_Face, + SFNT_Done_Face, + SFNT_Get_Interface, + + TT_Load_Any, + TT_Load_SFNT_Header, + TT_Load_Directory, + + TT_Load_Header, + TT_Load_Metrics_Header, + TT_Load_CMap, + TT_Load_MaxProfile, + TT_Load_OS2, + TT_Load_PostScript, + + TT_Load_Names, + TT_Free_Names, + + TT_Load_Hdmx, + TT_Free_Hdmx, + + TT_Load_Kern, + TT_Load_Gasp, + TT_Load_PCLT, + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* see `ttsbit.h' */ + TT_Load_SBit_Strikes, + TT_Load_SBit_Image, + TT_Free_SBit_Strikes, + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + 0, + 0, + 0, + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + /* see `ttpost.h' */ + TT_Get_PS_Name, + TT_Free_Post_Names, + +#else /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + 0, + 0, + +#endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + /* see `ttcmap.h' */ + TT_CharMap_Load, + TT_CharMap_Free, + }; + + + const + FT_Module_Class sfnt_module_class = + { + 0, /* not a font driver or renderer */ + sizeof( FT_ModuleRec ), + + "sfnt", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or higher */ + + (const void*)&sfnt_interface, /* module specific interface */ + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) SFNT_Get_Interface + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/sfdriver.h b/subsys/win32k/freetype/src/sfnt/sfdriver.h new file mode 100644 index 0000000..92c9c81 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/sfdriver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* sfdriver.h */ +/* */ +/* High-level SFNT driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef SFDRIVER_H +#define SFDRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Module_Class ) sfnt_module_class; + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/sfnt.c b/subsys/win32k/freetype/src/sfnt/sfnt.c new file mode 100644 index 0000000..a5ebbc4 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/sfnt.c @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* sfnt.c */ +/* */ +/* Single object library component. */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.c" +#include "ttcmap.c" +#include "sfobjs.c" + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include "ttsbit.c" +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include "ttpost.c" +#endif + +#include "sfdriver.c" + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS +#include +#endif + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES +#include +#endif + +#include + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/sfobjs.c b/subsys/win32k/freetype/src/sfnt/sfobjs.c new file mode 100644 index 0000000..38aba0e --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/sfobjs.c @@ -0,0 +1,561 @@ +/***************************************************************************/ +/* */ +/* sfobjs.c */ +/* */ +/* SFNT object management (base). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "sfobjs.h" + +#else + +#include + +#endif + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_sfobjs + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Name */ + /* */ + /* */ + /* Returns a given ENGLISH name record in ASCII. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* nameid :: The name id of the name record to return. */ + /* */ + /* */ + /* Character string. NULL if no name is present. */ + /* */ + static + FT_String* Get_Name( TT_Face face, + FT_UShort nameid ) + { + FT_Memory memory = face->root.memory; + FT_UShort n; + TT_NameRec* rec; + FT_Bool wide_chars = 1; + + + rec = face->name_table.names; + for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ ) + { + if ( rec->nameID == nameid ) + { + /* found the name -- now create an ASCII string from it */ + FT_Bool found = 0; + + + /* test for Microsoft English language */ + if ( rec->platformID == TT_PLATFORM_MICROSOFT && + rec->encodingID <= TT_MS_ID_UNICODE_CS && + ( rec->languageID & 0x3FF ) == 0x009 ) + found = 1; + + /* test for Apple Unicode encoding */ + else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE ) + found = 1; + + /* test for Apple Roman */ + else if ( rec->platformID == TT_PLATFORM_MACINTOSH && + rec->languageID == TT_MAC_ID_ROMAN ) + { + found = 1; + wide_chars = 0; + } + + /* found a Unicode name */ + if ( found ) + { + FT_String* string; + FT_UInt len; + + + if ( wide_chars ) + { + FT_UInt m; + + + len = (FT_UInt)rec->stringLength / 2; + if ( MEM_Alloc( string, len + 1 ) ) + return NULL; + + for ( m = 0; m < len; m ++ ) + string[m] = rec->string[2 * m + 1]; + } + else + { + len = rec->stringLength; + if ( MEM_Alloc( string, len + 1 ) ) + return NULL; + + MEM_Copy( string, rec->string, len ); + } + + string[len] = '\0'; + return string; + } + } + } + + return NULL; + } + + + static + FT_Encoding find_encoding( int platform_id, + int encoding_id ) + { + typedef struct TEncoding + { + int platform_id; + int encoding_id; + FT_Encoding encoding; + + } TEncoding; + + static + const TEncoding tt_encodings[] = + { + { TT_PLATFORM_ISO, -1, ft_encoding_unicode }, + + { TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode }, + + { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman }, + + { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, ft_encoding_gb2312 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, ft_encoding_wansung }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, ft_encoding_johab } + }; + + const TEncoding *cur, *limit; + + + cur = tt_encodings; + limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); + + for ( ; cur < limit; cur++ ) + { + if ( cur->platform_id == platform_id ) + { + if ( cur->encoding_id == encoding_id || + cur->encoding_id == -1 ) + return cur->encoding; + } + } + + return ft_encoding_none; + } + + + LOCAL_FUNC + FT_Error SFNT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Library library = face->root.driver->root.library; + SFNT_Interface* sfnt; + SFNT_Header sfnt_header; + + /* for now, parameters are unused */ + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + sfnt = (SFNT_Interface*)face->sfnt; + if ( !sfnt ) + { + sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" ); + if ( !sfnt ) + { + error = FT_Err_Invalid_File_Format; + goto Exit; + } + + face->sfnt = sfnt; + face->goto_table = sfnt->goto_table; + } + + if ( !face->psnames ) + { + face->psnames = (PSNames_Interface*) + FT_Get_Module_Interface( library, "psnames" ); + } + + /* check that we have a valid TrueType file */ + error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header ); + if ( error ) + goto Exit; + + face->format_tag = sfnt_header.format_tag; + face->num_tables = sfnt_header.num_tables; + + /* Load font directory */ + error = sfnt->load_directory( face, stream, &sfnt_header ); + if ( error ) + goto Exit; + + face->root.num_faces = face->ttc_header.count; + if ( face->root.num_faces < 1 ) + face->root.num_faces = 1; + + Exit: + return error; + } + + +#undef LOAD_ +#define LOAD_( x ) ( ( error = sfnt->load_##x( face, stream ) ) \ + != TT_Err_Ok ) + + + LOCAL_FUNC + FT_Error SFNT_Load_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + FT_UNUSED( face_index ); + FT_UNUSED( num_params ); + FT_UNUSED( params ); + + + /* Load tables */ + if ( LOAD_( header ) || + LOAD_( max_profile ) || + + /* load the `hhea' & `hmtx' tables at once */ + ( error = sfnt->load_metrics( face, stream, 0 ) ) != TT_Err_Ok || + + /* try to load the `vhea' & `vmtx' at once if present */ + ( error = sfnt->load_metrics( face, stream, 1 ) ) != TT_Err_Ok || + + LOAD_( charmaps ) || + LOAD_( names ) || + LOAD_( os2 ) || + LOAD_( psnames ) ) + goto Exit; + + /* the optional tables */ + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + /* embedded bitmap support. */ + if ( sfnt->load_sbits && LOAD_( sbits ) ) + goto Exit; +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + if ( LOAD_( hdmx ) || + LOAD_( gasp ) || + LOAD_( kerning ) || + LOAD_( pclt ) ) + goto Exit; + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + if ( ( error = TT_Extension_Create( face ) ) != TT_Err_Ok ) + goto Exit; +#endif + + face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY ); + face->root.style_name = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY ); + + /* now set up root fields */ + { + FT_Face root = &face->root; + FT_Int flags; + TT_CharMap charmap; + FT_Int n; + FT_Memory memory; + + + memory = root->memory; + + /*********************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + FT_FACE_FLAG_SFNT | /* SFNT file format */ + FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ + +#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES + /* might need more polish to detect the presence of a Postscript */ + /* name table in the font */ + flags |= FT_FACE_FLAG_GLYPH_NAMES; +#endif + + /* fixed width font? */ + if ( face->postscript.isFixedPitch ) + flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* vertical information? */ + if ( face->vertical_info ) + flags |= FT_FACE_FLAG_VERTICAL; + + /* kerning available ? */ + if ( face->kern_pairs ) + flags |= FT_FACE_FLAG_KERNING; + + root->face_flags = flags; + + /*********************************************************************/ + /* */ + /* Compute style flags. */ + /* */ + flags = 0; + + if ( face->os2.version != 0xFFFF ) + { + /* we have an OS/2 table; use the `fsSelection' field */ + if ( face->os2.fsSelection & 1 ) + flags |= FT_STYLE_FLAG_ITALIC; + + if ( face->os2.fsSelection & 32 ) + flags |= FT_STYLE_FLAG_BOLD; + } + else + { + /* this is an old Mac font, use the header field */ + if ( face->header.Mac_Style & 1 ) + flags |= FT_STYLE_FLAG_BOLD; + + if ( face->header.Mac_Style & 2 ) + flags |= FT_STYLE_FLAG_ITALIC; + } + + root->style_flags = flags; + + /*********************************************************************/ + /* */ + /* Polish the charmaps. */ + /* */ + /* Try to set the charmap encoding according to the platform & */ + /* encoding ID of each charmap. */ + /* */ + charmap = face->charmaps; + root->num_charmaps = face->num_charmaps; + + /* allocate table of pointers */ + if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) ) + goto Exit; + + for ( n = 0; n < root->num_charmaps; n++, charmap++ ) + { + FT_Int platform = charmap->cmap.platformID; + FT_Int encoding = charmap->cmap.platformEncodingID; + + + charmap->root.face = (FT_Face)face; + charmap->root.platform_id = platform; + charmap->root.encoding_id = encoding; + charmap->root.encoding = find_encoding( platform, encoding ); + + /* now, set root->charmap with a unicode charmap */ + /* wherever available */ + if ( !root->charmap && + charmap->root.encoding == ft_encoding_unicode ) + root->charmap = (FT_CharMap)charmap; + + root->charmaps[n] = (FT_CharMap)charmap; + } + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + if ( face->num_sbit_strikes ) + { + root->num_fixed_sizes = face->num_sbit_strikes; + if ( ALLOC_ARRAY( root->available_sizes, + face->num_sbit_strikes, + FT_Bitmap_Size ) ) + return error; + + for ( n = 0 ; n < face->num_sbit_strikes ; n++ ) + { + root->available_sizes[n].width = + face->sbit_strikes[n].x_ppem; + root->available_sizes[n].height = + face->sbit_strikes[n].y_ppem; + } + } + else + +#else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + { + root->num_fixed_sizes = 0; + root->available_sizes = 0; + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /*********************************************************************/ + /* */ + /* Set up metrics. */ + /* */ + root->bbox.xMin = face->header.xMin; + root->bbox.yMin = face->header.yMin; + root->bbox.xMax = face->header.xMax; + root->bbox.yMax = face->header.yMax; + root->units_per_EM = face->header.Units_Per_EM; + + /* The ascender/descender/height are computed from the OS/2 table */ + /* when found. Otherwise, they're taken from the horizontal header. */ + if ( face->os2.version != 0xFFFF ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = -face->os2.sTypoDescender; + root->height = root->ascender + root->descender + + face->os2.sTypoLineGap; + } + else + { + root->ascender = face->horizontal.Ascender; + root->descender = face->horizontal.Descender; + root->height = root->ascender + root->descender + + face->horizontal.Line_Gap; + } + + root->max_advance_width = face->horizontal.advance_Width_Max; + + root->max_advance_height = face->vertical_info + ? face->vertical.advance_Height_Max + : root->height; + + root->underline_position = face->postscript.underlinePosition; + root->underline_thickness = face->postscript.underlineThickness; + + /* root->max_points -- already set up */ + /* root->max_contours -- already set up */ + } + + Exit: + return error; + } + + +#undef LOAD_ + + + LOCAL_FUNC + void SFNT_Done_Face( TT_Face face ) + { + FT_Memory memory = face->root.memory; + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + if ( sfnt ) + { + /* destroy the postscript names table if it is loaded */ + if ( sfnt->free_psnames ) + sfnt->free_psnames( face ); + + /* destroy the embedded bitmaps table if it is loaded */ + if ( sfnt->free_sbits ) + sfnt->free_sbits( face ); + } + + /* freeing the kerning table */ + FREE( face->kern_pairs ); + face->num_kern_pairs = 0; + + /* freeing the collection table */ + FREE( face->ttc_header.offsets ); + face->ttc_header.count = 0; + + /* freeing table directory */ + FREE( face->dir_tables ); + face->num_tables = 0; + + /* freeing the character mapping tables */ + if ( sfnt && sfnt->load_charmaps ) + { + FT_UShort n; + + + for ( n = 0; n < face->num_charmaps; n++ ) + sfnt->free_charmap( face, &face->charmaps[n].cmap ); + } + + FREE( face->charmaps ); + face->num_charmaps = 0; + + FREE( face->root.charmaps ); + face->root.num_charmaps = 0; + face->root.charmap = 0; + + /* freeing the horizontal metrics */ + FREE( face->horizontal.long_metrics ); + FREE( face->horizontal.short_metrics ); + + /* freeing the vertical ones, if any */ + if ( face->vertical_info ) + { + FREE( face->vertical.long_metrics ); + FREE( face->vertical.short_metrics ); + face->vertical_info = 0; + } + + /* freeing the gasp table */ + FREE( face->gasp.gaspRanges ); + face->gasp.numRanges = 0; + + /* freeing the name table */ + sfnt->free_names( face ); + + /* freeing the hdmx table */ + sfnt->free_hdmx( face ); + + /* freeing family and style name */ + FREE( face->root.family_name ); + FREE( face->root.style_name ); + + /* freeing sbit size table */ + face->root.num_fixed_sizes = 0; + if ( face->root.available_sizes ) + FREE( face->root.available_sizes ); + + face->sfnt = 0; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/sfobjs.h b/subsys/win32k/freetype/src/sfnt/sfobjs.h new file mode 100644 index 0000000..35d92f9 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/sfobjs.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* sfobjs.h */ +/* */ +/* SFNT object management (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef SFOBJS_H +#define SFOBJS_H + +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error SFNT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + FT_Error SFNT_Load_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void SFNT_Done_Face( TT_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* SFDRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttcmap.c b/subsys/win32k/freetype/src/sfnt/ttcmap.c new file mode 100644 index 0000000..a2f3fd7 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttcmap.c @@ -0,0 +1,550 @@ +/***************************************************************************/ +/* */ +/* ttcmap.c */ +/* */ +/* TrueType character mapping table (cmap) support (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" +#include "ttcmap.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttcmap + + + static FT_UInt code_to_index0( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index2( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index4( TT_CMapTable* charmap, + FT_ULong char_code ); + static FT_UInt code_to_index6( TT_CMapTable* charmap, + FT_ULong char_code ); + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Load */ + /* */ + /* */ + /* Loads a given TrueType character map into memory. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* stream :: A handle to the current stream object. */ + /* */ + /* */ + /* table :: A pointer to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The function assumes that the stream is already in use (i.e., */ + /* opened). In case of error, all partially allocated tables are */ + /* released. */ + /* */ + LOCAL_FUNC + FT_Error TT_CharMap_Load( TT_Face face, + TT_CMapTable* cmap, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory; + FT_UShort num_SH, num_Seg, i; + + FT_UShort u, l; + + TT_CMap0* cmap0; + TT_CMap2* cmap2; + TT_CMap4* cmap4; + TT_CMap6* cmap6; + + TT_CMap2SubHeader* cmap2sub; + TT_CMap4Segment* segments; + + + if ( cmap->loaded ) + return TT_Err_Ok; + + memory = stream->memory; + + if ( FILE_Seek( cmap->offset ) ) + return error; + + switch ( cmap->format ) + { + case 0: + cmap0 = &cmap->c.cmap0; + + if ( ALLOC( cmap0->glyphIdArray, 256L ) || + FILE_Read( cmap0->glyphIdArray, 256L ) ) + goto Fail; + + cmap->get_index = code_to_index0; + break; + + case 2: + num_SH = 0; + cmap2 = &cmap->c.cmap2; + + /* allocate subheader keys */ + + if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) || + ACCESS_Frame( 512L ) ) + goto Fail; + + for ( i = 0; i < 256; i++ ) + { + u = GET_UShort() / 8; + cmap2->subHeaderKeys[i] = u; + + if ( num_SH < u ) + num_SH = u; + } + + FORGET_Frame(); + + /* load subheaders */ + + cmap2->numGlyphId = l = + ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFF ) / 2; + + if ( ALLOC_ARRAY( cmap2->subHeaders, + num_SH + 1, + TT_CMap2SubHeader ) || + ACCESS_Frame( ( num_SH + 1 ) * 8L ) ) + goto Fail; + + cmap2sub = cmap2->subHeaders; + + for ( i = 0; i <= num_SH; i++ ) + { + cmap2sub->firstCode = GET_UShort(); + cmap2sub->entryCount = GET_UShort(); + cmap2sub->idDelta = GET_Short(); + /* we apply the location offset immediately */ + cmap2sub->idRangeOffset = GET_UShort() - ( num_SH - i ) * 8 - 2; + + cmap2sub++; + } + + FORGET_Frame(); + + /* load glyph IDs */ + + if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap2->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + + cmap->get_index = code_to_index2; + break; + + case 4: + cmap4 = &cmap->c.cmap4; + + /* load header */ + + if ( ACCESS_Frame( 8L ) ) + goto Fail; + + cmap4->segCountX2 = GET_UShort(); + cmap4->searchRange = GET_UShort(); + cmap4->entrySelector = GET_UShort(); + cmap4->rangeShift = GET_UShort(); + + num_Seg = cmap4->segCountX2 / 2; + + FORGET_Frame(); + + /* load segments */ + + if ( ALLOC_ARRAY( cmap4->segments, + num_Seg, + TT_CMap4Segment ) || + ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) ) + goto Fail; + + segments = cmap4->segments; + + for ( i = 0; i < num_Seg; i++ ) + segments[i].endCount = GET_UShort(); + + (void)GET_UShort(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].startCount = GET_UShort(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idDelta = GET_Short(); + + for ( i = 0; i < num_Seg; i++ ) + segments[i].idRangeOffset = GET_UShort(); + + FORGET_Frame(); + + cmap4->numGlyphId = l = + ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFF ) / 2; + + /* load IDs */ + + if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap4->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + + cmap->get_index = code_to_index4; + + cmap4->last_segment = cmap4->segments; + break; + + case 6: + cmap6 = &cmap->c.cmap6; + + if ( ACCESS_Frame( 4L ) ) + goto Fail; + + cmap6->firstCode = GET_UShort(); + cmap6->entryCount = GET_UShort(); + + FORGET_Frame(); + + l = cmap6->entryCount; + + if ( ALLOC_ARRAY( cmap6->glyphIdArray, + cmap6->entryCount, + FT_Short ) || + ACCESS_Frame( l * 2L ) ) + goto Fail; + + for ( i = 0; i < l; i++ ) + cmap6->glyphIdArray[i] = GET_UShort(); + + FORGET_Frame(); + cmap->get_index = code_to_index6; + break; + + default: /* corrupt character mapping table */ + return TT_Err_Invalid_CharMap_Format; + + } + + return TT_Err_Ok; + + Fail: + TT_CharMap_Free( face, cmap ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_CharMap_Free */ + /* */ + /* */ + /* Destroys a character mapping table. */ + /* */ + /* */ + /* face :: A handle to the parent face object. */ + /* cmap :: A handle to a cmap object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ) + { + FT_Memory memory; + + + if ( !cmap ) + return TT_Err_Ok; + + memory = face->root.driver->root.memory; + + switch ( cmap->format ) + { + case 0: + FREE( cmap->c.cmap0.glyphIdArray ); + break; + + case 2: + FREE( cmap->c.cmap2.subHeaderKeys ); + FREE( cmap->c.cmap2.subHeaders ); + FREE( cmap->c.cmap2.glyphIdArray ); + break; + + case 4: + FREE( cmap->c.cmap4.segments ); + FREE( cmap->c.cmap4.glyphIdArray ); + cmap->c.cmap4.segCountX2 = 0; + break; + + case 6: + FREE( cmap->c.cmap6.glyphIdArray ); + cmap->c.cmap6.entryCount = 0; + break; + + default: + /* invalid table format, do nothing */ + ; + } + + cmap->loaded = FALSE; + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index0 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 0. */ + /* `charCode' must be in the range 0x00-0xFF (otherwise 0 is */ + /* returned). */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap0 :: A pointer to a cmap table in format 0. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index0( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap0* cmap0 = &cmap->c.cmap0; + + + return ( charCode <= 0xFF ? cmap0->glyphIdArray[charCode] : 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index2 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 2. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap2 :: A pointer to a cmap table in format 2. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index2( TT_CMapTable* cmap, + FT_ULong charCode ) + { + FT_UInt result, index1, offset; + FT_UInt char_lo; + FT_ULong char_hi; + TT_CMap2SubHeader* sh2; + TT_CMap2* cmap2; + + + cmap2 = &cmap->c.cmap2; + result = 0; + char_lo = (FT_UInt)( charCode & 0xFF ); + char_hi = charCode >> 8; + + if ( char_hi == 0 ) + { + /* an 8-bit character code -- we use the subHeader 0 in this case */ + /* to test whether the character code is in the charmap */ + if ( cmap2->subHeaderKeys[char_lo] == 0 ) + result = cmap2->glyphIdArray[char_lo]; + } + else + { + /* a 16-bit character code */ + index1 = cmap2->subHeaderKeys[char_hi & 0xFF]; + if ( index1 ) + { + sh2 = cmap2->subHeaders + index1; + char_lo -= sh2->firstCode; + + if ( char_lo < sh2->entryCount ) + { + offset = sh2->idRangeOffset / 2 + char_lo; + if ( offset < cmap2->numGlyphId ) + { + result = cmap2->glyphIdArray[offset]; + if ( result ) + result = ( result + sh2->idDelta ) & 0xFFFF; + } + } + } + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index4 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 4. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap4 :: A pointer to a cmap table in format 4. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index4( TT_CMapTable* cmap, + FT_ULong charCode ) + { + FT_UInt result, index1, segCount; + TT_CMap4* cmap4; + TT_CMap4Segment *seg4, *limit; + + + cmap4 = &cmap->c.cmap4; + result = 0; + segCount = cmap4->segCountX2 / 2; + seg4 = cmap4->segments; + limit = seg4 + segCount; + + /* check against the last segment */ + seg4 = cmap4->last_segment; + + /* the following is equivalent to performing two tests, as in */ + /* */ + /* if ( charCode >= seg4->startCount && charCode <= seg4->endCount ) */ + /* */ + /* Yes, that's a bit strange, but it's faster, and the idea behind */ + /* the cache is to significantly speed up charcode to glyph index */ + /* conversion. */ + + if ( (FT_ULong)(charCode - seg4->startCount) < + (FT_ULong)(seg4->endCount - seg4->startCount) ) + goto Found; + + for ( seg4 = cmap4->segments; seg4 < limit; seg4++ ) + { + /* the ranges are sorted in increasing order. If we are out of */ + /* the range here, the char code isn't in the charmap, so exit. */ + + if ( charCode > seg4->endCount ) + continue; + + if ( charCode >= seg4->startCount ) + goto Found; + } + return 0; + + Found: + cmap4->last_segment = seg4; + + /* if the idRangeOffset is 0, we can compute the glyph index */ + /* directly */ + + if ( seg4->idRangeOffset == 0 ) + result = ( charCode + seg4->idDelta ) & 0xFFFF; + else + { + /* otherwise, we must use the glyphIdArray to do it */ + index1 = seg4->idRangeOffset / 2 + + ( charCode - seg4->startCount ) + + ( seg4 - cmap4->segments ) + - segCount; + + if ( index1 < cmap4->numGlyphId && + cmap4->glyphIdArray[index1] != 0 ) + result = ( cmap4->glyphIdArray[index1] + seg4->idDelta ) & 0xFFFF; + } + + return result; + } + + + /*************************************************************************/ + /* */ + /* */ + /* code_to_index6 */ + /* */ + /* */ + /* Converts the character code into a glyph index. Uses format 6. */ + /* */ + /* */ + /* charCode :: The wanted character code. */ + /* cmap6 :: A pointer to a cmap table in format 6. */ + /* */ + /* */ + /* Glyph index into the glyphs array. 0 if the glyph does not exist. */ + /* */ + static + FT_UInt code_to_index6( TT_CMapTable* cmap, + FT_ULong charCode ) + { + TT_CMap6* cmap6; + FT_UInt result = 0; + + + cmap6 = &cmap->c.cmap6; + result = 0; + charCode -= cmap6->firstCode; + + if ( charCode < cmap6->entryCount ) + result = cmap6->glyphIdArray[charCode]; + + return result; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttcmap.h b/subsys/win32k/freetype/src/sfnt/ttcmap.h new file mode 100644 index 0000000..609972a --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttcmap.h @@ -0,0 +1,45 @@ +/***************************************************************************/ +/* */ +/* ttcmap.h */ +/* */ +/* TrueType character mapping table (cmap) support (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTCMAP_H +#define TTCMAP_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_CharMap_Load( TT_Face face, + TT_CMapTable* cmap, + FT_Stream input ); + + LOCAL_DEF + FT_Error TT_CharMap_Free( TT_Face face, + TT_CMapTable* cmap ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTCMAP_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttload.c b/subsys/win32k/freetype/src/sfnt/ttload.c new file mode 100644 index 0000000..c3eeed6 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttload.c @@ -0,0 +1,1676 @@ +/***************************************************************************/ +/* */ +/* ttload.c */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" +#include "ttcmap.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttload + + + /*************************************************************************/ + /* */ + /* */ + /* TT_LookUp_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* */ + /* */ + /* A pointer to the table directory entry. 0 if not found. */ + /* */ + LOCAL_FUNC + TT_Table* TT_LookUp_Table( TT_Face face, + FT_ULong tag ) + { + TT_Table* entry; + TT_Table* limit; + + + FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c'\n", + face, + (FT_Char)( tag >> 24 ), + (FT_Char)( tag >> 16 ), + (FT_Char)( tag >> 8 ), + (FT_Char)( tag ) )); + + entry = face->dir_tables; + limit = entry + face->num_tables; + + for ( ; entry < limit; entry++ ) + { + if ( entry->Tag == tag ) + return entry; + } + + FT_TRACE3(( " Could not find table!\n" )); + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_Table */ + /* */ + /* */ + /* Looks for a TrueType table by name, then seek a stream to it. */ + /* */ + /* */ + /* face :: A face object handle. */ + /* tag :: The searched tag. */ + /* stream :: The stream to seek when the table is found. */ + /* */ + /* */ + /* length :: The length of the table if found, undefined otherwise. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Goto_Table( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ) + { + TT_Table* table; + FT_Error error; + + + table = TT_LookUp_Table( face, tag ); + if ( table ) + { + if ( length ) + *length = table->Length; + + (void)FILE_Seek( table->Offset ); + } + else + error = TT_Err_Table_Missing; + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SFNT_Header */ + /* */ + /* */ + /* Loads the header of a SFNT font file. Supports collections. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* face_index :: If the font is a collection, the number of the font */ + /* in the collection, ignored otherwise. */ + /* */ + /* */ + /* sfnt :: The SFNT header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + /* This function recognizes fonts embedded in a `TrueType collection' */ + /* */ + /* The header will be checked whether it is valid by looking at the */ + /* values of `search_range', `entry_selector', and `range_shift'. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_SFNT_Header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header* sfnt ) + { + FT_Error error; + FT_ULong format_tag; + FT_Memory memory = stream->memory; + + const FT_Frame_Field sfnt_header_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_USHORT( SFNT_Header, num_tables ), + FT_FRAME_USHORT( SFNT_Header, search_range ), + FT_FRAME_USHORT( SFNT_Header, entry_selector ), + FT_FRAME_USHORT( SFNT_Header, range_shift ), + FT_FRAME_END + }; + + const FT_Frame_Field ttc_header_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_LONG( TTC_Header, version ), + FT_FRAME_LONG( TTC_Header, count ), + FT_FRAME_END }; + + + FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n", + face, face_index )); + + face->ttc_header.tag = 0; + face->ttc_header.version = 0; + face->ttc_header.count = 0; + + face->num_tables = 0; + + /* first of all, read the first 4 bytes. If it is `ttcf', then the */ + /* file is a TrueType collection, otherwise it can be any other */ + /* kind of font. */ + if ( READ_ULong( format_tag ) ) + goto Exit; + + if ( format_tag == TTAG_ttcf ) + { + FT_Int n; + + + FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" )); + + /* it's a TrueType collection, i.e. a file containing several */ + /* font files. Read the font directory now */ + if ( READ_Fields( ttc_header_fields, &face->ttc_header ) ) + goto Exit; + + /* now read the offsets of each font in the file */ + if ( ALLOC_ARRAY( face->ttc_header.offsets, + face->ttc_header.count, + FT_ULong ) || + ACCESS_Frame( face->ttc_header.count * 4L ) ) + goto Exit; + + for ( n = 0; n < face->ttc_header.count; n++ ) + face->ttc_header.offsets[n] = GET_ULong(); + + FORGET_Frame(); + + /* check face index */ + if ( face_index >= face->ttc_header.count ) + { + error = TT_Err_Bad_Argument; + goto Exit; + } + + /* seek to the appropriate TrueType file, then read tag */ + if ( FILE_Seek( face->ttc_header.offsets[face_index] ) || + READ_Long( format_tag ) ) + goto Exit; + } + + /* the format tag was read, now check the rest of the header */ + sfnt->format_tag = format_tag; + if ( READ_Fields( sfnt_header_fields, sfnt ) ) + goto Exit; + + /* now, check the values of `num_tables', `seach_range', etc. */ + { + FT_UInt num_tables = sfnt->num_tables; + FT_ULong entry_selector = 1L << sfnt->entry_selector; + + + /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */ + /* we only check the `entry_selector' correctness here. */ + /* */ + if ( num_tables == 0 || + entry_selector > num_tables || + entry_selector * 2 <= num_tables ) + { + FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" )); + error = FT_Err_Unknown_File_Format; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Directory */ + /* */ + /* */ + /* Loads the table directory into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* sfnt :: The SFNT directory header. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be at the font file's origin. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + SFNT_Header* sfnt ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + TT_Table *entry, *limit; + + + FT_TRACE2(( "TT_Load_Directory: %08p\n", face )); + + FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables )); + FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag )); + + face->num_tables = sfnt->num_tables; + + if ( ALLOC_ARRAY( face->dir_tables, + face->num_tables, + TT_Table ) ) + goto Exit; + + if ( ACCESS_Frame( face->num_tables * 16L ) ) + goto Exit; + + entry = face->dir_tables; + limit = entry + face->num_tables; + + for ( ; entry < limit; entry++ ) + { /* loop through the tables and get all entries */ + entry->Tag = GET_Tag4(); + entry->CheckSum = GET_ULong(); + entry->Offset = GET_Long(); + entry->Length = GET_Long(); + + FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", + (FT_Char)( entry->Tag >> 24 ), + (FT_Char)( entry->Tag >> 16 ), + (FT_Char)( entry->Tag >> 8 ), + (FT_Char)( entry->Tag ), + entry->Offset, + entry->Length )); + } + + FORGET_Frame(); + + FT_TRACE2(( "Directory loaded\n\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Any */ + /* */ + /* */ + /* Loads any font table into client memory. */ + /* */ + /* */ + /* face :: The face object to look for. */ + /* */ + /* tag :: The tag of table to load. Use the value 0 if you want */ + /* to access the whole font file, else set this parameter */ + /* to a valid TrueType table tag that you can forge with */ + /* the MAKE_TT_TAG macro. */ + /* */ + /* offset :: The starting offset in the table (or the file if */ + /* tag == 0). */ + /* */ + /* length :: The address of the decision variable: */ + /* */ + /* If length == NULL: */ + /* Loads the whole table. Returns an error if */ + /* `offset' == 0! */ + /* */ + /* If *length == 0: */ + /* Exits immediately; returning the length of the given */ + /* table or of the font file, depending on the value of */ + /* `tag'. */ + /* */ + /* If *length != 0: */ + /* Loads the next `length' bytes of table or font, */ + /* starting at offset `offset' (in table or font too). */ + /* */ + /* */ + /* buffer :: The address of target buffer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Any( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ) + { + FT_Error error; + FT_Stream stream; + TT_Table* table; + FT_ULong size; + + + if ( tag != 0 ) + { + /* look for tag in font directory */ + table = TT_LookUp_Table( face, tag ); + if ( !table ) + { + error = TT_Err_Table_Missing; + goto Exit; + } + + offset += table->Offset; + size = table->Length; + } + else + /* tag == 0 -- the user wants to access the font file directly */ + size = face->root.stream->size; + + if ( length && *length == 0 ) + { + *length = size; + + return TT_Err_Ok; + } + + if ( length ) + size = *length; + + stream = face->root.stream; + (void)FILE_Read_At( offset, buffer, size ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Header */ + /* */ + /* */ + /* Loads the TrueType font header. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_Header* header; + + static const FT_Frame_Field header_fields[] = + { + FT_FRAME_START( 54 ), + FT_FRAME_ULONG( TT_Header, Table_Version ), + FT_FRAME_ULONG( TT_Header, Font_Revision ), + FT_FRAME_LONG( TT_Header, CheckSum_Adjust ), + FT_FRAME_LONG( TT_Header, Magic_Number ), + FT_FRAME_USHORT( TT_Header, Flags ), + FT_FRAME_USHORT( TT_Header, Units_Per_EM ), + FT_FRAME_LONG( TT_Header, Created[0] ), + FT_FRAME_LONG( TT_Header, Created[1] ), + FT_FRAME_LONG( TT_Header, Modified[0] ), + FT_FRAME_LONG( TT_Header, Modified[1] ), + FT_FRAME_SHORT( TT_Header, xMin ), + FT_FRAME_SHORT( TT_Header, yMin ), + FT_FRAME_SHORT( TT_Header, xMax ), + FT_FRAME_SHORT( TT_Header, yMax ), + FT_FRAME_USHORT( TT_Header, Mac_Style ), + FT_FRAME_USHORT( TT_Header, Lowest_Rec_PPEM ), + FT_FRAME_SHORT( TT_Header, Font_Direction ), + FT_FRAME_SHORT( TT_Header, Index_To_Loc_Format ), + FT_FRAME_SHORT( TT_Header, Glyph_Data_Format ), + FT_FRAME_END + }; + + + FT_TRACE2(( "Load_TT_Header: %08p\n", face )); + + error = face->goto_table( face, TTAG_head, stream, 0 ); + if ( error ) + { + FT_TRACE0(( "Font Header is missing!\n" )); + goto Exit; + } + + header = &face->header; + + if ( READ_Fields( header_fields, header ) ) + goto Exit; + + FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM )); + FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format )); + FT_TRACE2(( "Font Header Loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_MaxProfile */ + /* */ + /* */ + /* Loads the maximum profile into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_MaxProfile* maxProfile = &face->max_profile; + + const FT_Frame_Field maxp_fields[] = + { + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( TT_MaxProfile, version ), + FT_FRAME_USHORT( TT_MaxProfile, numGlyphs ), + FT_FRAME_USHORT( TT_MaxProfile, maxPoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxContours ), + FT_FRAME_USHORT( TT_MaxProfile, maxCompositePoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxCompositeContours ), + FT_FRAME_USHORT( TT_MaxProfile, maxZones ), + FT_FRAME_USHORT( TT_MaxProfile, maxTwilightPoints ), + FT_FRAME_USHORT( TT_MaxProfile, maxStorage ), + FT_FRAME_USHORT( TT_MaxProfile, maxFunctionDefs ), + FT_FRAME_USHORT( TT_MaxProfile, maxInstructionDefs ), + FT_FRAME_USHORT( TT_MaxProfile, maxStackElements ), + FT_FRAME_USHORT( TT_MaxProfile, maxSizeOfInstructions ), + FT_FRAME_USHORT( TT_MaxProfile, maxComponentElements ), + FT_FRAME_USHORT( TT_MaxProfile, maxComponentDepth ), + FT_FRAME_END }; + + + FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face )); + + error = face->goto_table( face, TTAG_maxp, stream, 0 ); + if ( error ) + goto Exit; + + if ( READ_Fields( maxp_fields, maxProfile ) ) + goto Exit; + + /* XXX: an adjustment that is necessary to load certain */ + /* broken fonts like `Keystrokes MT' :-( */ + /* */ + /* We allocate 64 function entries by default when */ + /* the maxFunctionDefs field is null. */ + + if ( maxProfile->maxFunctionDefs == 0 ) + maxProfile->maxFunctionDefs = 64; + + face->root.num_glyphs = maxProfile->numGlyphs; + + face->root.max_points = MAX( maxProfile->maxCompositePoints, + maxProfile->maxPoints ); + + face->root.max_contours = MAX( maxProfile->maxCompositeContours, + maxProfile->maxContours ); + + face->max_components = (FT_ULong)maxProfile->maxComponentElements + + maxProfile->maxComponentDepth; + + /* XXX: some fonts have maxComponents set to 0; we will */ + /* then use 16 of them by default. */ + if ( face->max_components == 0 ) + face->max_components = 16; + + /* We also increase maxPoints and maxContours in order to support */ + /* some broken fonts. */ + face->root.max_points += 8; + face->root.max_contours += 4; + + FT_TRACE2(( "MAXP loaded.\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics */ + /* */ + /* */ + /* Loads the horizontal or vertical metrics table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error TT_Load_Metrics( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_ULong table_len; + FT_Long num_shorts, num_longs, num_shorts_checked; + + TT_LongMetrics** longs; + TT_ShortMetrics** shorts; + + + FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical" + : "Horizontal", + face )); + + if ( vertical ) + { + /* The table is optional, quit silently if it wasn't found */ + /* XXX: Some fonts have a valid vertical header with a non-null */ + /* `number_of_VMetrics' fields, but no corresponding `vmtx' */ + /* table to get the metrics from (e.g. mingliu). */ + /* */ + /* For safety, we set the field to 0! */ + /* */ + error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); + if ( error ) + { + /* Set number_Of_VMetrics to 0! */ + FT_TRACE2(( " no vertical header in file.\n" )); + face->vertical.number_Of_VMetrics = 0; + error = TT_Err_Ok; + goto Exit; + } + + num_longs = face->vertical.number_Of_VMetrics; + longs = (TT_LongMetrics**)&face->vertical.long_metrics; + shorts = (TT_ShortMetrics**)&face->vertical.short_metrics; + } + else + { + error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); + if ( error ) + { + FT_ERROR(( " no horizontal metrics in file!\n" )); + error = TT_Err_Hmtx_Table_Missing; + goto Exit; + } + + num_longs = face->horizontal.number_Of_HMetrics; + longs = (TT_LongMetrics**)&face->horizontal.long_metrics; + shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics; + } + + /* never trust derived values */ + + num_shorts = face->max_profile.numGlyphs - num_longs; + num_shorts_checked = ( table_len - num_longs * 4L ) / 2; + + if ( num_shorts < 0 ) + { + FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n", + vertical ? "Vertical" + : "Horizontal" )); + + error = vertical ? TT_Err_Invalid_Vert_Metrics + : TT_Err_Invalid_Horiz_Metrics; + goto Exit; + } + + if ( ALLOC_ARRAY( *longs, num_longs, TT_LongMetrics ) || + ALLOC_ARRAY( *shorts, num_shorts, TT_ShortMetrics ) ) + goto Exit; + + if ( ACCESS_Frame( table_len ) ) + goto Exit; + + { + TT_LongMetrics* cur = *longs; + TT_LongMetrics* limit = cur + num_longs; + + + for ( ; cur < limit; cur++ ) + { + cur->advance = GET_UShort(); + cur->bearing = GET_Short(); + } + } + + /* do we have an inconsistent number of metric values? */ + { + TT_ShortMetrics* cur = *shorts; + TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked ); + + + for ( ; cur < limit; cur++ ) + *cur = GET_Short(); + + /* we fill up the missing left side bearings with the */ + /* last valid value. Since this will occur for buggy CJK */ + /* fonts usually only, nothing serious will happen */ + if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) + { + FT_Short val = *(shorts)[num_shorts_checked - 1]; + + + limit = *shorts + num_shorts; + for ( ; cur < limit; cur++ ) + *cur = val; + } + } + + FORGET_Frame(); + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Metrics_Header */ + /* */ + /* */ + /* Loads the horizontal or vertical header in a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* vertical :: A boolean flag. If set, load vertical metrics. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + FT_Bool vertical ) + { + FT_Error error; + TT_HoriHeader* header; + + const FT_Frame_Field metrics_header_fields[] = + { + FT_FRAME_START( 36 ), + FT_FRAME_ULONG( TT_HoriHeader, Version ), + FT_FRAME_SHORT( TT_HoriHeader, Ascender ), + FT_FRAME_SHORT( TT_HoriHeader, Descender ), + FT_FRAME_SHORT( TT_HoriHeader, Line_Gap ), + FT_FRAME_USHORT( TT_HoriHeader, advance_Width_Max ), + FT_FRAME_SHORT( TT_HoriHeader, min_Left_Side_Bearing ), + FT_FRAME_SHORT( TT_HoriHeader, min_Right_Side_Bearing ), + FT_FRAME_SHORT( TT_HoriHeader, xMax_Extent ), + FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Rise ), + FT_FRAME_SHORT( TT_HoriHeader, caret_Slope_Run ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[0] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[1] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[2] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[3] ), + FT_FRAME_SHORT( TT_HoriHeader, Reserved[4] ), + FT_FRAME_SHORT( TT_HoriHeader, metric_Data_Format ), + FT_FRAME_USHORT( TT_HoriHeader, number_Of_HMetrics ), + FT_FRAME_END + }; + + + FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " )); + + if ( vertical ) + { + face->vertical_info = 0; + + /* The vertical header table is optional, so return quietly if */ + /* we don't find it. */ + error = face->goto_table( face, TTAG_vhea, stream, 0 ); + if ( error ) + { + error = TT_Err_Ok; + goto Exit; + } + + face->vertical_info = 1; + header = (TT_HoriHeader*)&face->vertical; + } + else + { + /* The horizontal header is mandatory; return an error if we */ + /* don't find it. */ + error = face->goto_table( face, TTAG_hhea, stream, 0 ); + if ( error ) + { + error = TT_Err_Horiz_Header_Missing; + goto Exit; + } + + header = &face->horizontal; + } + + if ( READ_Fields( metrics_header_fields, header ) ) + goto Exit; + + header->long_metrics = NULL; + header->short_metrics = NULL; + + FT_TRACE2(( "loaded\n" )); + + /* Now try to load the corresponding metrics */ + + error = TT_Load_Metrics( face, stream, vertical ); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Names */ + /* */ + /* */ + /* Loads the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Names( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_ULong table_pos, table_len; + FT_ULong storageSize; + + TT_NameTable* names; + + const FT_Frame_Field name_table_fields[] = + { + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( TT_NameTable, format ), + FT_FRAME_USHORT( TT_NameTable, numNameRecords ), + FT_FRAME_USHORT( TT_NameTable, storageOffset ), + FT_FRAME_END + }; + + const FT_Frame_Field name_record_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( TT_NameRec, platformID ), + FT_FRAME_USHORT( TT_NameRec, encodingID ), + FT_FRAME_USHORT( TT_NameRec, languageID ), + FT_FRAME_USHORT( TT_NameRec, nameID ), + FT_FRAME_USHORT( TT_NameRec, stringLength ), + FT_FRAME_USHORT( TT_NameRec, stringOffset ), + FT_FRAME_END + }; + + + FT_TRACE2(( "Names " )); + + error = face->goto_table( face, TTAG_name, stream, &table_len ); + if ( error ) + { + /* The name table is required so indicate failure. */ + FT_TRACE2(( "is missing!\n" )); + error = TT_Err_Name_Table_Missing; + goto Exit; + } + + table_pos = FILE_Pos(); + + names = &face->name_table; + + if ( READ_Fields( name_table_fields, names ) ) + goto Exit; + + /* Allocate the array of name records. */ + if ( ALLOC_ARRAY( names->names, + names->numNameRecords, + TT_NameRec ) || + ACCESS_Frame( names->numNameRecords * 12L ) ) + goto Exit; + + /* Load the name records and determine how much storage is needed */ + /* to hold the strings themselves. */ + { + TT_NameRec* cur = names->names; + TT_NameRec* limit = cur + names->numNameRecords; + + + storageSize = 0; + + for ( ; cur < limit; cur ++ ) + { + FT_ULong upper; + + + (void)READ_Fields( name_record_fields, cur ); + + upper = (FT_ULong)( cur->stringOffset + cur->stringLength ); + if ( upper > storageSize ) + storageSize = upper; + } + } + + FORGET_Frame(); + + if ( storageSize > 0 ) + { + /* allocate the name storage area in memory, then read it */ + if ( ALLOC( names->storage, storageSize ) || + FILE_Read_At( table_pos + names->storageOffset, + names->storage, storageSize ) ) + goto Exit; + + /* Go through and assign the string pointers to the name records. */ + { + TT_NameRec* cur = names->names; + TT_NameRec* limit = cur + names->numNameRecords; + + + for ( ; cur < limit; cur++ ) + cur->string = names->storage + cur->stringOffset; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* Print Name Record Table in case of debugging */ + { + TT_NameRec* cur = names->names; + TT_NameRec* limit = cur + names->numNameRecords; + + + for ( ; cur < limit; cur++ ) + { + FT_UInt j; + + + FT_TRACE3(( "%d %d %x %d\n ", + cur->platformID, + cur->encodingID, + cur->languageID, + cur->nameID )); + + /* I know that M$ encoded strings are Unicode, */ + /* but this works reasonable well for debugging purposes. */ + if ( cur->string ) + for ( j = 0; j < cur->stringLength; j++ ) + { + FT_Char c = *( cur->string + j ); + + + if ( (FT_Byte)c < 128 ) + FT_TRACE3(( "%c", c )); + } + } + } + FT_TRACE3(( "\n" )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + } + FT_TRACE2(( "loaded\n" )); + + /* everything went well, update face->num_names */ + face->num_names = names->numNameRecords; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Names */ + /* */ + /* */ + /* Frees the name records. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + LOCAL_FUNC + void TT_Free_Names( TT_Face face ) + { + FT_Memory memory = face->root.driver->root.memory; + TT_NameTable* names = &face->name_table; + + + /* free strings table */ + FREE( names->names ); + + /* free strings storage */ + FREE( names->storage ); + + names->numNameRecords = 0; + names->format = 0; + names->storageOffset = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_CMap */ + /* */ + /* */ + /* Loads the cmap directory in a face object. The cmaps itselves are */ + /* loaded on demand in the `ttcmap.c' module. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Long table_start; + TT_CMapDir cmap_dir; + + const FT_Frame_Field cmap_fields[] = + { + FT_FRAME_START( 4 ), + FT_FRAME_USHORT( TT_CMapDir, tableVersionNumber ), + FT_FRAME_USHORT( TT_CMapDir, numCMaps ), + FT_FRAME_END + }; + + const FT_Frame_Field cmap_rec_fields[] = + { + FT_FRAME_START( 6 ), + FT_FRAME_USHORT( TT_CMapTable, format ), + FT_FRAME_USHORT( TT_CMapTable, length ), + FT_FRAME_USHORT( TT_CMapTable, version ), + FT_FRAME_END + }; + + + FT_TRACE2(( "CMaps " )); + + error = face->goto_table( face, TTAG_cmap, stream, 0 ); + if ( error ) + { + error = TT_Err_CMap_Table_Missing; + goto Exit; + } + + table_start = FILE_Pos(); + + if ( READ_Fields( cmap_fields, &cmap_dir ) ) + goto Exit; + + /* reserve space in face table for cmap tables */ + if ( ALLOC_ARRAY( face->charmaps, + cmap_dir.numCMaps, + TT_CharMapRec ) ) + goto Exit; + + face->num_charmaps = cmap_dir.numCMaps; + { + TT_CharMap charmap = face->charmaps; + TT_CharMap limit = charmap + face->num_charmaps; + + + /* read the header of each charmap first */ + if ( ACCESS_Frame( face->num_charmaps * 8L ) ) + goto Exit; + + for ( ; charmap < limit; charmap++ ) + { + TT_CMapTable* cmap; + + + charmap->root.face = (FT_Face)face; + cmap = &charmap->cmap; + + cmap->loaded = FALSE; + cmap->platformID = GET_UShort(); + cmap->platformEncodingID = GET_UShort(); + cmap->offset = (FT_ULong)GET_Long(); + } + + FORGET_Frame(); + + /* now read the rest of each table */ + for ( charmap = face->charmaps; charmap < limit; charmap++ ) + { + TT_CMapTable* cmap = &charmap->cmap; + + + if ( FILE_Seek( table_start + (FT_Long)cmap->offset ) || + READ_Fields( cmap_rec_fields, cmap ) ) + goto Exit; + + cmap->offset = FILE_Pos(); + } + } + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_OS2 */ + /* */ + /* */ + /* Loads the OS2 table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_OS2* os2; + + const FT_Frame_Field os2_fields[] = + { + FT_FRAME_START( 78 ), + FT_FRAME_USHORT( TT_OS2, version ), + FT_FRAME_SHORT( TT_OS2, xAvgCharWidth ), + FT_FRAME_USHORT( TT_OS2, usWeightClass ), + FT_FRAME_USHORT( TT_OS2, usWidthClass ), + FT_FRAME_SHORT( TT_OS2, fsType ), + FT_FRAME_SHORT( TT_OS2, ySubscriptXSize ), + FT_FRAME_SHORT( TT_OS2, ySubscriptYSize ), + FT_FRAME_SHORT( TT_OS2, ySubscriptXOffset ), + FT_FRAME_SHORT( TT_OS2, ySubscriptYOffset ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptXSize ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptYSize ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptXOffset ), + FT_FRAME_SHORT( TT_OS2, ySuperscriptYOffset ), + FT_FRAME_SHORT( TT_OS2, yStrikeoutSize ), + FT_FRAME_SHORT( TT_OS2, yStrikeoutPosition ), + FT_FRAME_SHORT( TT_OS2, sFamilyClass ), + FT_FRAME_BYTE( TT_OS2, panose[0] ), + FT_FRAME_BYTE( TT_OS2, panose[1] ), + FT_FRAME_BYTE( TT_OS2, panose[2] ), + FT_FRAME_BYTE( TT_OS2, panose[3] ), + FT_FRAME_BYTE( TT_OS2, panose[4] ), + FT_FRAME_BYTE( TT_OS2, panose[5] ), + FT_FRAME_BYTE( TT_OS2, panose[6] ), + FT_FRAME_BYTE( TT_OS2, panose[7] ), + FT_FRAME_BYTE( TT_OS2, panose[8] ), + FT_FRAME_BYTE( TT_OS2, panose[9] ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange1 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange2 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange3 ), + FT_FRAME_ULONG( TT_OS2, ulUnicodeRange4 ), + FT_FRAME_BYTE( TT_OS2, achVendID[0] ), + FT_FRAME_BYTE( TT_OS2, achVendID[1] ), + FT_FRAME_BYTE( TT_OS2, achVendID[2] ), + FT_FRAME_BYTE( TT_OS2, achVendID[3] ), + + FT_FRAME_USHORT( TT_OS2, fsSelection ), + FT_FRAME_USHORT( TT_OS2, usFirstCharIndex ), + FT_FRAME_USHORT( TT_OS2, usLastCharIndex ), + FT_FRAME_SHORT( TT_OS2, sTypoAscender ), + FT_FRAME_SHORT( TT_OS2, sTypoDescender ), + FT_FRAME_SHORT( TT_OS2, sTypoLineGap ), + FT_FRAME_USHORT( TT_OS2, usWinAscent ), + FT_FRAME_USHORT( TT_OS2, usWinDescent ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_ULONG( TT_OS2, ulCodePageRange1 ), + FT_FRAME_ULONG( TT_OS2, ulCodePageRange2 ), + FT_FRAME_END + }; + + const FT_Frame_Field os2_fields_extra2[] = + { + FT_FRAME_START( 10 ), + FT_FRAME_SHORT( TT_OS2, sxHeight ), + FT_FRAME_SHORT( TT_OS2, sCapHeight ), + FT_FRAME_USHORT( TT_OS2, usDefaultChar ), + FT_FRAME_USHORT( TT_OS2, usBreakChar ), + FT_FRAME_USHORT( TT_OS2, usMaxContext ), + FT_FRAME_END + }; + + + FT_TRACE2(( "OS/2 Table " )); + + /* We now support old Mac fonts where the OS/2 table doesn't */ + /* exist. Simply put, we set the `version' field to 0xFFFF */ + /* and test this value each time we need to access the table. */ + error = face->goto_table( face, TTAG_OS2, stream, 0 ); + if ( error ) + { + FT_TRACE2(( "is missing!\n" )); + face->os2.version = 0xFFFF; + error = TT_Err_Ok; + goto Exit; + } + + os2 = &face->os2; + + if ( READ_Fields( os2_fields, os2 ) ) + goto Exit; + + os2->ulCodePageRange1 = 0; + os2->ulCodePageRange2 = 0; + + if ( os2->version >= 0x0001 ) + { + /* only version 1 tables */ + if ( READ_Fields( os2_fields_extra, os2 ) ) + goto Exit; + + if ( os2->version >= 0x0002 ) + { + /* only version 2 tables */ + if ( READ_Fields( os2_fields_extra2, os2 ) ) + goto Exit; + } + } + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Postscript */ + /* */ + /* */ + /* Loads the Postscript table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + TT_Postscript* post = &face->postscript; + + static const FT_Frame_Field post_fields[] = + { + FT_FRAME_START( 32 ), + FT_FRAME_ULONG( TT_Postscript, FormatType ), + FT_FRAME_ULONG( TT_Postscript, italicAngle ), + FT_FRAME_SHORT( TT_Postscript, underlinePosition ), + FT_FRAME_SHORT( TT_Postscript, underlineThickness ), + FT_FRAME_ULONG( TT_Postscript, isFixedPitch ), + FT_FRAME_ULONG( TT_Postscript, minMemType42 ), + FT_FRAME_ULONG( TT_Postscript, maxMemType42 ), + FT_FRAME_ULONG( TT_Postscript, minMemType1 ), + FT_FRAME_ULONG( TT_Postscript, maxMemType1 ), + FT_FRAME_END + }; + + + FT_TRACE2(( "PostScript " )); + + error = face->goto_table( face, TTAG_post, stream, 0 ); + if ( error ) + return TT_Err_Post_Table_Missing; + + if ( READ_Fields( post_fields, post ) ) + return error; + + /* we don't load the glyph names, we do that in another */ + /* module (ttpost). */ + FT_TRACE2(( "loaded\n" )); + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_PCLT */ + /* */ + /* */ + /* Loads the PCL 5 Table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_PCLT( TT_Face face, + FT_Stream stream ) + { + static const FT_Frame_Field pclt_fields[] = + { + FT_FRAME_START( 54 ), + FT_FRAME_ULONG ( TT_PCLT, Version ), + FT_FRAME_ULONG ( TT_PCLT, FontNumber ), + FT_FRAME_USHORT( TT_PCLT, Pitch ), + FT_FRAME_USHORT( TT_PCLT, xHeight ), + FT_FRAME_USHORT( TT_PCLT, Style ), + FT_FRAME_USHORT( TT_PCLT, TypeFamily ), + FT_FRAME_USHORT( TT_PCLT, CapHeight ), + FT_FRAME_BYTES ( TT_PCLT, TypeFace, 16 ), + FT_FRAME_BYTES ( TT_PCLT, CharacterComplement, 8 ), + FT_FRAME_BYTES ( TT_PCLT, FileName, 6 ), + FT_FRAME_CHAR ( TT_PCLT, StrokeWeight ), + FT_FRAME_CHAR ( TT_PCLT, WidthType ), + FT_FRAME_BYTE ( TT_PCLT, SerifStyle ), + FT_FRAME_BYTE ( TT_PCLT, Reserved ), + FT_FRAME_END + }; + + FT_Error error; + TT_PCLT* pclt = &face->pclt; + + + FT_TRACE2(( "PCLT " )); + + /* optional table */ + error = face->goto_table( face, TTAG_PCLT, stream, 0 ); + if ( error ) + { + FT_TRACE2(( "missing (optional)\n" )); + pclt->Version = 0; + return TT_Err_Ok; + } + + if ( READ_Fields( pclt_fields, pclt ) ) + goto Exit; + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Gasp */ + /* */ + /* */ + /* Loads the `gasp' table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_UInt j,num_ranges; + TT_GaspRange* gaspranges; + + + FT_TRACE2(( "TT_Load_Gasp: %08p\n", face )); + + /* the gasp table is optional */ + error = face->goto_table( face, TTAG_gasp, stream, 0 ); + if ( error ) + return TT_Err_Ok; + + if ( ACCESS_Frame( 4L ) ) + goto Exit; + + face->gasp.version = GET_UShort(); + face->gasp.numRanges = GET_UShort(); + + FORGET_Frame(); + + num_ranges = face->gasp.numRanges; + FT_TRACE3(( "number of ranges = %d\n", num_ranges )); + + if ( ALLOC_ARRAY( gaspranges, num_ranges, TT_GaspRange ) || + ACCESS_Frame( num_ranges * 4L ) ) + goto Exit; + + face->gasp.gaspRanges = gaspranges; + + for ( j = 0; j < num_ranges; j++ ) + { + gaspranges[j].maxPPEM = GET_UShort(); + gaspranges[j].gaspFlag = GET_UShort(); + + FT_TRACE3(( " [max:%d flag:%d]", + gaspranges[j].maxPPEM, + gaspranges[j].gaspFlag )); + } + FT_TRACE3(( "\n" )); + + FORGET_Frame(); + FT_TRACE2(( "GASP loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Kern */ + /* */ + /* */ + /* Loads the first kerning table with format 0 in the font. Only */ + /* accepts the first horizontal kerning table. Developers should use */ + /* the `ftxkern' extension to access other kerning tables in the font */ + /* file, if they really want to. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + FT_UInt n, num_tables, version; + + + /* the kern table is optional; exit silently if it is missing */ + error = face->goto_table( face, TTAG_kern, stream, 0 ); + if ( error ) + return TT_Err_Ok; + + if ( ACCESS_Frame( 4L ) ) + goto Exit; + + version = GET_UShort(); + num_tables = GET_UShort(); + + FORGET_Frame(); + + for ( n = 0; n < num_tables; n++ ) + { + FT_UInt coverage; + FT_UInt length; + + + if ( ACCESS_Frame( 6L ) ) + goto Exit; + + version = GET_UShort(); /* version */ + length = GET_UShort() - 6; /* substract header length */ + coverage = GET_UShort(); + + FORGET_Frame(); + + if ( coverage == 0x0001 ) + { + FT_UInt num_pairs; + TT_Kern_0_Pair* pair; + TT_Kern_0_Pair* limit; + + + /* found a horizontal format 0 kerning table! */ + if ( ACCESS_Frame( 8L ) ) + goto Exit; + + num_pairs = GET_UShort(); + + /* skip the rest */ + + FORGET_Frame(); + + /* allocate array of kerning pairs */ + if ( ALLOC_ARRAY( face->kern_pairs, num_pairs, TT_Kern_0_Pair ) || + ACCESS_Frame( 6L * num_pairs ) ) + goto Exit; + + pair = face->kern_pairs; + limit = pair + num_pairs; + for ( ; pair < limit; pair++ ) + { + pair->left = GET_UShort(); + pair->right = GET_UShort(); + pair->value = GET_UShort(); + } + + FORGET_Frame(); + + face->num_kern_pairs = num_pairs; + face->kern_table_index = n; + goto Exit; + } + + if ( FILE_Skip( length ) ) + goto Exit; + } + + /* no kern table found -- doesn't matter */ + face->kern_table_index = -1; + face->num_kern_pairs = 0; + face->kern_pairs = NULL; + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Hdmx */ + /* */ + /* */ + /* Loads the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + TT_Hdmx* hdmx = &face->hdmx; + FT_Long num_glyphs; + FT_Long record_size; + + + hdmx->version = 0; + hdmx->num_records = 0; + hdmx->records = 0; + + /* this table is optional */ + error = face->goto_table( face, TTAG_hdmx, stream, 0 ); + if ( error ) + return TT_Err_Ok; + + if ( ACCESS_Frame( 8L ) ) + goto Exit; + + hdmx->version = GET_UShort(); + hdmx->num_records = GET_Short(); + record_size = GET_Long(); + + FORGET_Frame(); + + /* Only recognize format 0 */ + if ( hdmx->version != 0 ) + goto Exit; + + if ( ALLOC_ARRAY( hdmx->records, hdmx->num_records, TT_HdmxRec ) ) + goto Exit; + + num_glyphs = face->root.num_glyphs; + record_size -= num_glyphs + 2; + + { + TT_HdmxRec* cur = hdmx->records; + TT_HdmxRec* limit = cur + hdmx->num_records; + + + for ( ; cur < limit; cur++ ) + { + /* read record */ + if ( READ_Byte( cur->ppem ) || + READ_Byte( cur->max_width ) ) + goto Exit; + + if ( ALLOC( cur->widths, num_glyphs ) || + FILE_Read( cur->widths, num_glyphs ) ) + goto Exit; + + /* skip padding bytes */ + if ( record_size > 0 && FILE_Skip( record_size ) ) + goto Exit; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_Hdmx */ + /* */ + /* */ + /* Frees the horizontal device metrics table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + LOCAL_FUNC + void TT_Free_Hdmx( TT_Face face ) + { + if ( face ) + { + FT_Int n; + FT_Memory memory = face->root.driver->root.memory; + + + for ( n = 0; n < face->hdmx.num_records; n++ ) + FREE( face->hdmx.records[n].widths ); + + FREE( face->hdmx.records ); + face->hdmx.num_records = 0; + } + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttload.h b/subsys/win32k/freetype/src/sfnt/ttload.h new file mode 100644 index 0000000..dd0de6a --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttload.h @@ -0,0 +1,132 @@ +/***************************************************************************/ +/* */ +/* ttload.h */ +/* */ +/* Load the basic TrueType tables, i.e., tables that can be either in */ +/* TTF or OTF fonts (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTLOAD_H +#define TTLOAD_H + + +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + TT_Table* TT_LookUp_Table( TT_Face face, + FT_ULong tag ); + + LOCAL_DEF + FT_Error TT_Goto_Table( TT_Face face, + FT_ULong tag, + FT_Stream stream, + FT_ULong* length ); + + + LOCAL_DEF + FT_Error TT_Load_SFNT_Header( TT_Face face, + FT_Stream stream, + FT_Long face_index, + SFNT_Header* sfnt ); + LOCAL_DEF + FT_Error TT_Load_Directory( TT_Face face, + FT_Stream stream, + SFNT_Header* sfnt ); + + LOCAL_DEF + FT_Error TT_Load_Any( TT_Face face, + FT_ULong tag, + FT_Long offset, + FT_Byte* buffer, + FT_ULong* length ); + + + LOCAL_DEF + FT_Error TT_Load_Header( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Metrics_Header( TT_Face face, + FT_Stream stream, + FT_Bool vertical ); + + + LOCAL_DEF + FT_Error TT_Load_CMap( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_MaxProfile( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Names( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_OS2( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_PostScript( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Hdmx( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_PCLT( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void TT_Free_Names( TT_Face face ); + + + LOCAL_DEF + void TT_Free_Hdmx ( TT_Face face ); + + + LOCAL_DEF + FT_Error TT_Load_Kern( TT_Face face, + FT_Stream stream ); + + + LOCAL_DEF + FT_Error TT_Load_Gasp( TT_Face face, + FT_Stream stream ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttpost.c b/subsys/win32k/freetype/src/sfnt/ttpost.c new file mode 100644 index 0000000..4220c6e --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttpost.c @@ -0,0 +1,536 @@ +/***************************************************************************/ +/* */ +/* ttpost.c */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* The post table is not completely loaded by the core engine. This */ + /* file loads the missing PS glyph names and implements an API to access */ + /* them. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttpost.h" +#include "ttload.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttpost + + + /* If this configuration macro is defined, we rely on the `PSNames' */ + /* module to grab the glyph names. */ + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + +#include + +#define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) ) + + +#else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + /* Otherwise, we ignore the `PSNames' module, and provide our own */ + /* table of Mac names. Thus, it is possible to build a version of */ + /* FreeType without the Type 1 driver & PSNames module. */ + +#define MAC_NAME( x ) TT_Post_Default_Names[x] + + /* the 258 default Mac PS glyph names */ + + FT_String* TT_Post_Default_Names[258] = + { + /* 0 */ + ".notdef", ".null", "CR", "space", "exclam", + "quotedbl", "numbersign", "dollar", "percent", "ampersand", + /* 10 */ + "quotesingle", "parenleft", "parenright", "asterisk", "plus", + "comma", "hyphen", "period", "slash", "zero", + /* 20 */ + "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine", "colon", + /* 30 */ + "semicolon", "less", "equal", "greater", "question", + "at", "A", "B", "C", "D", + /* 40 */ + "E", "F", "G", "H", "I", + "J", "K", "L", "M", "N", + /* 50 */ + "O", "P", "Q", "R", "S", + "T", "U", "V", "W", "X", + /* 60 */ + "Y", "Z", "bracketleft", "backslash", "bracketright", + "asciicircum", "underscore", "grave", "a", "b", + /* 70 */ + "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", + /* 80 */ + "m", "n", "o", "p", "q", + "r", "s", "t", "u", "v", + /* 90 */ + "w", "x", "y", "z", "braceleft", + "bar", "braceright", "asciitilde", "Adieresis", "Aring", + /* 100 */ + "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", + "aacute", "agrave", "acircumflex", "adieresis", "atilde", + /* 110 */ + "aring", "ccedilla", "eacute", "egrave", "ecircumflex", + "edieresis", "iacute", "igrave", "icircumflex", "idieresis", + /* 120 */ + "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", + "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", + /* 130 */ + "dagger", "degree", "cent", "sterling", "section", + "bullet", "paragraph", "germandbls", "registered", "copyright", + /* 140 */ + "trademark", "acute", "dieresis", "notequal", "AE", + "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", + /* 150 */ + "yen", "mu", "partialdiff", "summation", "product", + "pi", "integral", "ordfeminine", "ordmasculine", "Omega", + /* 160 */ + "ae", "oslash", "questiondown", "exclamdown", "logicalnot", + "radical", "florin", "approxequal", "Delta", "guillemotleft", + /* 170 */ + "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", + "Otilde", "OE", "oe", "endash", "emdash", + /* 180 */ + "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", + "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", + /* 190 */ + "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", + "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", + /* 200 */ + "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", + "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", + /* 210 */ + "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", + "dotlessi", "circumflex", "tilde", "macron", "breve", + /* 220 */ + "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", + "caron", "Lslash", "lslash", "Scaron", "scaron", + /* 230 */ + "Zcaron", "zcaron", "brokenbar", "Eth", "eth", + "Yacute", "yacute", "Thorn", "thorn", "minus", + /* 240 */ + "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", + "onequarter", "threequarters", "franc", "Gbreve", "gbreve", + /* 250 */ + "Idot", "Scedilla", "scedilla", "Cacute", "cacute", + "Ccaron", "ccaron", "dmacron", + }; + + +#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ + + + static + FT_Error Load_Format_20( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + FT_Error error; + + FT_Int num_glyphs; + FT_Int num_names; + + FT_UShort* glyph_indices = 0; + FT_Char** name_strings = 0; + + + if ( READ_UShort( num_glyphs ) ) + goto Exit; + + /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ + /* than the value in the maxp table (cf. cyberbit.ttf). */ + + /* There already exist fonts which have more than 32768 glyph names */ + /* in this table, so the test for this threshold has been dropped. */ + + if ( num_glyphs > face->root.num_glyphs ) + { + error = TT_Err_Invalid_File_Format; + goto Exit; + } + + /* load the indices */ + { + FT_Int n; + + + if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) || + ACCESS_Frame( num_glyphs * 2L ) ) + goto Fail; + + for ( n = 0; n < num_glyphs; n++ ) + glyph_indices[n] = GET_UShort(); + + FORGET_Frame(); + } + + /* compute number of names stored in table */ + { + FT_Int n; + + + num_names = 0; + + for ( n = 0; n < num_glyphs; n++ ) + { + FT_Int index; + + + index = glyph_indices[n]; + if ( index >= 258 ) + { + index -= 257; + if ( index > num_names ) + num_names = index; + } + } + } + + /* now load the name strings */ + { + FT_Int n; + + + if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) ) + goto Fail; + + for ( n = 0; n < num_names; n++ ) + { + FT_UInt len; + + + if ( READ_Byte ( len ) || + ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) || + FILE_Read ( name_strings[n], len ) ) + goto Fail1; + + name_strings[n][len] = '\0'; + } + } + + /* all right, set table fields and exit successfuly */ + { + TT_Post_20* table = &face->postscript_names.names.format_20; + + + table->num_glyphs = num_glyphs; + table->num_names = num_names; + table->glyph_indices = glyph_indices; + table->glyph_names = name_strings; + } + return TT_Err_Ok; + + + Fail1: + { + FT_Int n; + + + for ( n = 0; n < num_names; n++ ) + FREE( name_strings[n] ); + } + + Fail: + FREE( name_strings ); + FREE( glyph_indices ); + + Exit: + return error; + } + + + static + FT_Error Load_Format_25( TT_Face face, + FT_Stream stream ) + { + FT_Memory memory = stream->memory; + FT_Error error; + + FT_Int num_glyphs; + FT_Char* offset_table = 0; + + + /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ + if ( READ_UShort( num_glyphs ) ) + goto Exit; + + /* check the number of glyphs */ + if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 ) + { + error = TT_Err_Invalid_File_Format; + goto Exit; + } + + if ( ALLOC ( offset_table, num_glyphs ) || + FILE_Read( offset_table, num_glyphs ) ) + goto Fail; + + /* now check the offset table */ + { + FT_Int n; + + + for ( n = 0; n < num_glyphs; n++ ) + { + FT_Long index = (FT_Long)n + offset_table[n]; + + + if ( index < 0 || index > num_glyphs ) + { + error = TT_Err_Invalid_File_Format; + goto Fail; + } + } + } + + /* OK, set table fields and exit successfuly */ + { + TT_Post_25* table = &face->postscript_names.names.format_25; + + + table->num_glyphs = num_glyphs; + table->offsets = offset_table; + } + + return TT_Err_Ok; + + Fail: + FREE( offset_table ); + + Exit: + return error; + } + + + static + FT_Error Load_Post_Names( TT_Face face ) + { + FT_Stream stream; + FT_Error error; + + /* get a stream for the face's resource */ + stream = face->root.stream; + + /* seek to the beginning of the PS names table */ + error = face->goto_table( face, TTAG_post, stream, 0 ); + if ( error ) + goto Exit; + + /* now read postscript table */ + switch ( face->postscript.FormatType ) + { + case 0x00020000L: + error = Load_Format_20( face, stream ); + break; + + case 0x00028000L: + error = Load_Format_25( face, stream ); + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + face->postscript_names.loaded = 1; + + Exit: + return error; + } + + + LOCAL_FUNC + void TT_Free_Post_Names( TT_Face face ) + { + FT_Memory memory = face->root.memory; + TT_Post_Names* names = &face->postscript_names; + + + if ( names->loaded ) + { + switch ( face->postscript.FormatType ) + { + case 0x00020000L: + { + TT_Post_20* table = &names->names.format_20; + FT_UInt n; + + + FREE( table->glyph_indices ); + table->num_glyphs = 0; + + for ( n = 0; n < table->num_names; n++ ) + FREE( table->glyph_names[n] ); + + FREE( table->glyph_names ); + table->num_names = 0; + } + break; + + case 0x00028000L: + { + TT_Post_25* table = &names->names.format_25; + + + FREE( table->offsets ); + table->num_glyphs = 0; + } + break; + } + } + names->loaded = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_PS_Name */ + /* */ + /* */ + /* Gets the PostScript glyph name of a glyph. */ + /* */ + /* */ + /* face :: A handle to the parent face. */ + /* */ + /* index :: The glyph index. */ + /* */ + /* PSname :: The address of a string pointer. Will be NULL in case */ + /* of error, otherwise it is a pointer to the glyph name. */ + /* */ + /* You must not modify the returned string! */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Get_PS_Name( TT_Face face, + FT_UInt index, + FT_String** PSname ) + { + FT_Error error; + TT_Post_Names* names; + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + PSNames_Interface* psnames; +#endif + + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + if ( index >= (FT_UInt)face->root.num_glyphs ) + return TT_Err_Invalid_Glyph_Index; + +#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES + psnames = (PSNames_Interface*)face->psnames; + if ( !psnames ) + return TT_Err_Unimplemented_Feature; +#endif + + names = &face->postscript_names; + + /* `.notdef' by default */ + *PSname = MAC_NAME( 0 ); + + switch ( face->postscript.FormatType ) + { + case 0x00010000L: + if ( index < 258 ) /* paranoid checking */ + *PSname = MAC_NAME( index ); + break; + + case 0x00020000L: + { + TT_Post_20* table = &names->names.format_20; + + + if ( !names->loaded ) + { + error = Load_Post_Names( face ); + if ( error ) + break; + } + + if ( index < table->num_glyphs ) + { + FT_UShort name_index = table->glyph_indices[index]; + + + if ( name_index < 258 ) + *PSname = MAC_NAME( name_index ); + else + *PSname = (FT_String*)table->glyph_names[name_index - 258]; + } + } + break; + + case 0x00028000L: + { + TT_Post_25* table = &names->names.format_25; + + + if ( !names->loaded ) + { + error = Load_Post_Names( face ); + if ( error ) + break; + } + + if ( index < table->num_glyphs ) /* paranoid checking */ + { + index += table->offsets[index]; + *PSname = MAC_NAME( index ); + } + } + break; + + case 0x00030000L: + break; /* nothing to do */ + } + + return TT_Err_Ok; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttpost.h b/subsys/win32k/freetype/src/sfnt/ttpost.h new file mode 100644 index 0000000..e3da836 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttpost.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ttpost.h */ +/* */ +/* Postcript name table processing for TrueType and OpenType fonts */ +/* (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTPOST_H +#define TTPOST_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +#define TT_Err_Invalid_Post_Table_Format 0x0B00 +#define TT_Err_Invalid_Post_Table 0x0B01 + + + LOCAL_DEF + FT_Error TT_Get_PS_Name( TT_Face face, + FT_UInt index, + FT_String** PSname ); + + LOCAL_DEF + void TT_Free_Post_Names( TT_Face face ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTPOST_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttsbit.c b/subsys/win32k/freetype/src/sfnt/ttsbit.c new file mode 100644 index 0000000..01d2dbf --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttsbit.c @@ -0,0 +1,1444 @@ +/***************************************************************************/ +/* */ +/* ttsbit.c */ +/* */ +/* TrueType and OpenType embedded bitmap support (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttsbit.h" + +#else + +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttsbit + + + /*************************************************************************/ + /* */ + /* */ + /* blit_sbit */ + /* */ + /* */ + /* Blits a bitmap from an input stream into a given target. Supports */ + /* x and y offsets as well as byte padded lines. */ + /* */ + /* */ + /* target :: The target bitmap/pixmap. */ + /* */ + /* source :: The input packed bitmap data. */ + /* */ + /* line_bits :: The number of bits per line. */ + /* */ + /* byte_padded :: A flag which is true if lines are byte-padded. */ + /* */ + /* x_offset :: The horizontal offset. */ + /* */ + /* y_offset :: The vertical offset. */ + /* */ + /* */ + /* IMPORTANT: The x and y offsets are relative to the top corner of */ + /* the target bitmap (unlike the normal TrueType */ + /* convention). A positive y offset indicates a downwards */ + /* direction! */ + /* */ + static + void blit_sbit( FT_Bitmap* target, + FT_Byte* source, + FT_Int line_bits, + FT_Bool byte_padded, + FT_Int x_offset, + FT_Int y_offset ) + { + FT_Byte* line_buff; + FT_Int line_incr; + FT_Int height; + + FT_UShort acc; + FT_Byte loaded; + + + /* first of all, compute starting write position */ + line_incr = target->pitch; + line_buff = target->buffer; + + if ( line_incr < 0 ) + line_buff -= line_incr * ( target->rows - 1 ); + + line_buff += ( x_offset >> 3 ) + y_offset * line_incr; + + /***********************************************************************/ + /* */ + /* We use the extra-classic `accumulator' trick to extract the bits */ + /* from the source byte stream. */ + /* */ + /* Namely, the variable `acc' is a 16-bit accumulator containing the */ + /* last `loaded' bits from the input stream. The bits are shifted to */ + /* the upmost position in `acc'. */ + /* */ + /***********************************************************************/ + + acc = 0; /* clear accumulator */ + loaded = 0; /* no bits were loaded */ + + for ( height = target->rows; height > 0; height-- ) + { + FT_Byte* cur = line_buff; /* current write cursor */ + FT_Int count = line_bits; /* # of bits to extract per line */ + FT_Byte shift = x_offset & 7; /* current write shift */ + FT_Byte space = 8 - shift; + + + /* first of all, read individual source bytes */ + if ( count >= 8 ) + { + count -= 8; + { + do + { + FT_Byte val; + + + /* ensure that there are at least 8 bits in the accumulator */ + if ( loaded < 8 ) + { + acc |= (FT_UShort)*source++ << ( 8 - loaded ); + loaded += 8; + } + + /* now write one byte */ + val = (FT_Byte)( acc >> 8 ); + if ( shift ) + { + cur[0] |= val >> shift; + cur[1] |= val << space; + } + else + cur[0] |= val; + + cur++; + acc <<= 8; /* remove bits from accumulator */ + loaded -= 8; + count -= 8; + + } while ( count >= 0 ); + } + + /* restore `count' to correct value */ + count += 8; + } + + /* now write remaining bits (count < 8) */ + if ( count > 0 ) + { + FT_Byte val; + + + /* ensure that there are at least `count' bits in the accumulator */ + if ( loaded < count ) + { + acc |= (FT_UShort)*source++ << ( 8 - loaded ); + loaded += 8; + } + + /* now write remaining bits */ + val = ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ); + cur[0] |= val >> shift; + + if ( count > space ) + cur[1] |= val << space; + + acc <<= count; + loaded -= count; + } + + /* now, skip to next line */ + if ( byte_padded ) + acc = loaded = 0; /* clear accumulator on byte-padded lines */ + + line_buff += line_incr; + } + } + + + const FT_Frame_Field sbit_metrics_fields[] = + { + FT_FRAME_START( 8 ), + FT_FRAME_BYTE( TT_SBit_Metrics, height ), + FT_FRAME_BYTE( TT_SBit_Metrics, width ), + + FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingX ), + FT_FRAME_CHAR( TT_SBit_Metrics, horiBearingY ), + FT_FRAME_BYTE( TT_SBit_Metrics, horiAdvance ), + + FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingX ), + FT_FRAME_CHAR( TT_SBit_Metrics, vertBearingY ), + FT_FRAME_BYTE( TT_SBit_Metrics, vertAdvance ), + FT_FRAME_END + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Const_Metrics */ + /* */ + /* */ + /* Loads the metrics for `EBLC' index tables format 2 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_SBit_Const_Metrics( TT_SBit_Range* range, + FT_Stream stream ) + { + FT_Error error; + + + if ( READ_ULong( range->image_size ) ) + return error; + + return READ_Fields( sbit_metrics_fields, &range->metrics ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Range_Codes */ + /* */ + /* */ + /* Loads the range codes for `EBLC' index tables format 4 and 5. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* load_offsets :: A flag whether to load the glyph offset table. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_SBit_Range_Codes( TT_SBit_Range* range, + FT_Stream stream, + FT_Bool load_offsets ) + { + FT_Error error; + FT_ULong count, n, size; + FT_Memory memory = stream->memory; + + + if ( READ_ULong( count ) ) + goto Exit; + + range->num_glyphs = count; + + /* Allocate glyph offsets table if needed */ + if ( load_offsets ) + { + if ( ALLOC_ARRAY( range->glyph_offsets, count, FT_ULong ) ) + goto Exit; + + size = count * 4L; + } + else + size = count * 2L; + + /* Allocate glyph codes table and access frame */ + if ( ALLOC_ARRAY ( range->glyph_codes, count, FT_UShort ) || + ACCESS_Frame( size ) ) + goto Exit; + + for ( n = 0; n < count; n++ ) + { + range->glyph_codes[n] = GET_UShort(); + + if ( load_offsets ) + range->glyph_offsets[n] = (FT_ULong)range->image_offset + + GET_UShort(); + } + + FORGET_Frame(); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Range */ + /* */ + /* */ + /* Loads a given `EBLC' index/range table. */ + /* */ + /* */ + /* range :: The target range. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_SBit_Range( TT_SBit_Range* range, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + + + switch( range->index_format ) + { + case 1: /* variable metrics with 4-byte offsets */ + case 3: /* variable metrics with 2-byte offsets */ + { + FT_ULong num_glyphs, n; + FT_Int size_elem; + FT_Bool large = ( range->index_format == 1 ); + + + num_glyphs = range->last_glyph - range->first_glyph + 1L; + range->num_glyphs = num_glyphs; + num_glyphs++; /* XXX: BEWARE - see spec */ + + size_elem = large ? 4 : 2; + + if ( ALLOC_ARRAY( range->glyph_offsets, + num_glyphs, FT_ULong ) || + ACCESS_Frame( num_glyphs * size_elem ) ) + goto Exit; + + for ( n = 0; n < num_glyphs; n++ ) + range->glyph_offsets[n] = (FT_ULong)( range->image_offset + + ( large ? GET_ULong() + : GET_UShort() ) ); + FORGET_Frame(); + } + break; + + case 2: /* all glyphs have identical metrics */ + error = Load_SBit_Const_Metrics( range, stream ); + break; + + case 4: + error = Load_SBit_Range_Codes( range, stream, 1 ); + break; + + case 5: + error = Load_SBit_Const_Metrics( range, stream ) || + Load_SBit_Range_Codes( range, stream, 0 ); + break; + + default: + error = TT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Strikes */ + /* */ + /* */ + /* Loads the table of embedded bitmap sizes for this face. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ) + { + FT_Error error = 0; + FT_Memory memory = stream->memory; + FT_Fixed version; + FT_ULong num_strikes; + FT_ULong table_base; + + const FT_Frame_Field sbit_line_metrics_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_CHAR( TT_SBit_Line_Metrics, ascender ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, descender ), + FT_FRAME_BYTE( TT_SBit_Line_Metrics, max_width ), + + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_numerator ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_slope_denominator ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, caret_offset ), + + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_origin_SB ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_advance_SB ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, max_before_BL ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, min_after_BL ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[0] ), + FT_FRAME_CHAR( TT_SBit_Line_Metrics, pads[1] ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_start_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_ULONG( TT_SBit_Strike, ranges_offset ), + FT_FRAME_SKIP_LONG, + FT_FRAME_ULONG( TT_SBit_Strike, num_ranges ), + FT_FRAME_ULONG( TT_SBit_Strike, color_ref ), + FT_FRAME_END + }; + + const FT_Frame_Field strike_end_fields[] = + { + /* no FT_FRAME_START */ + FT_FRAME_USHORT( TT_SBit_Strike, start_glyph ), + FT_FRAME_USHORT( TT_SBit_Strike, end_glyph ), + FT_FRAME_BYTE ( TT_SBit_Strike, x_ppem ), + FT_FRAME_BYTE ( TT_SBit_Strike, y_ppem ), + FT_FRAME_BYTE ( TT_SBit_Strike, bit_depth ), + FT_FRAME_CHAR ( TT_SBit_Strike, flags ), + FT_FRAME_END + }; + + + face->num_sbit_strikes = 0; + + /* this table is optional */ + error = face->goto_table( face, TTAG_EBLC, stream, 0 ); + if (error) + error = face->goto_table( face, TTAG_bloc, stream, 0 ); + if ( error ) + { + error = 0; + goto Exit; + } + + table_base = FILE_Pos(); + if ( ACCESS_Frame( 8L ) ) + goto Exit; + + version = GET_Long(); + num_strikes = GET_ULong(); + + FORGET_Frame(); + + /* check version number and strike count */ + if ( version != 0x00020000L || + num_strikes >= 0x10000L ) + { + FT_ERROR(( "TT_Load_SBit_Strikes: invalid table version!\n" )); + error = TT_Err_Invalid_File_Format; + + goto Exit; + } + + /* allocate the strikes table */ + if ( ALLOC_ARRAY( face->sbit_strikes, num_strikes, TT_SBit_Strike ) ) + goto Exit; + + face->num_sbit_strikes = num_strikes; + + /* now read each strike table separately */ + { + TT_SBit_Strike* strike = face->sbit_strikes; + FT_ULong count = num_strikes; + + + if ( ACCESS_Frame( 48L * num_strikes ) ) + goto Exit; + + while ( count > 0 ) + { + (void)READ_Fields( strike_start_fields, strike ); + + (void)READ_Fields( sbit_line_metrics_fields, &strike->hori ); + (void)READ_Fields( sbit_line_metrics_fields, &strike->vert ); + + (void)READ_Fields( strike_end_fields, strike ); + + count--; + strike++; + } + + FORGET_Frame(); + } + + /* allocate the index ranges for each strike table */ + { + TT_SBit_Strike* strike = face->sbit_strikes; + FT_ULong count = num_strikes; + + + while ( count > 0 ) + { + TT_SBit_Range* range; + FT_ULong count2 = strike->num_ranges; + + + if ( ALLOC_ARRAY( strike->sbit_ranges, + strike->num_ranges, + TT_SBit_Range ) ) + goto Exit; + + /* read each range */ + if ( FILE_Seek( table_base + strike->ranges_offset ) || + ACCESS_Frame( strike->num_ranges * 8L ) ) + goto Exit; + + range = strike->sbit_ranges; + while ( count2 > 0 ) + { + range->first_glyph = GET_UShort(); + range->last_glyph = GET_UShort(); + range->table_offset = table_base + strike->ranges_offset + + GET_ULong(); + count2--; + range++; + } + + FORGET_Frame(); + + /* Now, read each index table */ + count2 = strike->num_ranges; + range = strike->sbit_ranges; + while ( count2 > 0 ) + { + /* Read the header */ + if ( FILE_Seek( range->table_offset ) || + ACCESS_Frame( 8L ) ) + goto Exit; + + range->index_format = GET_UShort(); + range->image_format = GET_UShort(); + range->image_offset = GET_ULong(); + + FORGET_Frame(); + + error = Load_SBit_Range( range, stream ); + if ( error ) + goto Exit; + + count2--; + range++; + } + + count--; + strike++; + } + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Free_SBit_Strikes */ + /* */ + /* */ + /* Releases the embedded bitmap tables. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + LOCAL_FUNC + void TT_Free_SBit_Strikes( TT_Face face ) + { + FT_Memory memory = face->root.memory; + TT_SBit_Strike* strike = face->sbit_strikes; + TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes; + + + if ( strike ) + { + for ( ; strike < strike_limit; strike++ ) + { + TT_SBit_Range* range = strike->sbit_ranges; + TT_SBit_Range* range_limit = range + strike->num_ranges; + + + if ( range ) + { + for ( ; range < range_limit; range++ ) + { + /* release the glyph offsets and codes tables */ + /* where appropriate */ + FREE( range->glyph_offsets ); + FREE( range->glyph_codes ); + } + } + FREE( strike->sbit_ranges ); + strike->num_ranges = 0; + } + FREE( face->sbit_strikes ); + } + face->num_sbit_strikes = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Find_SBit_Range */ + /* */ + /* */ + /* Scans a given strike's ranges and return, for a given glyph */ + /* index, the corresponding sbit range, and `EBDT' offset. */ + /* */ + /* */ + /* glyph_index :: The glyph index. */ + /* strike :: The source/current sbit strike. */ + /* */ + /* */ + /* arange :: The sbit range containing the glyph index. */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* */ + /* FreeType error code. 0 means the glyph index was found. */ + /* */ + static + FT_Error Find_SBit_Range( FT_UInt glyph_index, + TT_SBit_Strike* strike, + TT_SBit_Range** arange, + FT_ULong* aglyph_offset ) + { + TT_SBit_Range *range, *range_limit; + + + /* check whether the glyph index is within this strike's */ + /* glyph range */ + if ( glyph_index < strike->start_glyph || + glyph_index > strike->end_glyph ) + goto Fail; + + /* scan all ranges in strike */ + range = strike->sbit_ranges; + range_limit = range + strike->num_ranges; + if ( !range ) + goto Fail; + + for ( ; range < range_limit; range++ ) + { + if ( glyph_index >= range->first_glyph && + glyph_index <= range->last_glyph ) + { + FT_UShort delta = glyph_index - range->first_glyph; + + + switch ( range->index_format ) + { + case 1: + case 3: + *aglyph_offset = range->glyph_offsets[delta]; + break; + + case 2: + *aglyph_offset = range->image_offset + + range->image_size * delta; + break; + + case 4: + case 5: + { + FT_ULong n; + + + for ( n = 0; n < range->num_glyphs; n++ ) + { + if ( range->glyph_codes[n] == glyph_index ) + { + if ( range->index_format == 4 ) + *aglyph_offset = range->glyph_offsets[n]; + else + *aglyph_offset = range->image_offset + + n * range->image_size; + goto Found; + } + } + } + + /* fall-through */ + default: + goto Fail; + } + + Found: + /* return successfully! */ + *arange = range; + return 0; + } + } + + Fail: + *arange = 0; + *aglyph_offset = 0; + + return TT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Find_SBit_Image */ + /* */ + /* */ + /* Checks whether an embedded bitmap (an `sbit') exists for a given */ + /* glyph, at given x and y ppems. */ + /* */ + /* */ + /* face :: The target face object. */ + /* glyph_index :: The glyph index. */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* */ + /* arange :: The SBit range containing the glyph index. */ + /* astrike :: The SBit strike containing the glyph index. */ + /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns */ + /* TT_Err_Invalid_Argument if no sbit exists for the requested glyph. */ + /* */ + static + FT_Error Find_SBit_Image( TT_Face face, + FT_UInt glyph_index, + FT_Int x_ppem, + FT_Int y_ppem, + + TT_SBit_Range** arange, + TT_SBit_Strike** astrike, + FT_ULong* aglyph_offset ) + { + TT_SBit_Strike* strike = face->sbit_strikes; + TT_SBit_Strike* strike_limit = strike + face->num_sbit_strikes; + + + if ( !strike ) + goto Fail; + + for ( ; strike < strike_limit; strike++ ) + { + if ( strike->x_ppem == x_ppem && strike->y_ppem == y_ppem ) + { + FT_Error error; + + + error = Find_SBit_Range( glyph_index, strike, + arange, aglyph_offset ); + if ( error ) + goto Fail; + + *astrike = strike; + + return TT_Err_Ok; + } + } + + Fail: + /* no embedded bitmap for this glyph in face */ + *arange = 0; + *astrike = 0; + *aglyph_offset = 0; + + return TT_Err_Invalid_Argument; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_SBit_Metrics */ + /* */ + /* */ + /* Gets the big metrics for a given SBit. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* range :: The SBit range containing the glyph. */ + /* */ + /* */ + /* big_metrics :: A big SBit metrics structure for the glyph. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The stream cursor must be positioned at the glyph's offset within */ + /* the `EBDT' table before the call. */ + /* */ + /* If the image format uses variable metrics, the stream cursor is */ + /* positioned just after the metrics header in the `EBDT' table on */ + /* function exit. */ + /* */ + static + FT_Error Load_SBit_Metrics( FT_Stream stream, + TT_SBit_Range* range, + TT_SBit_Metrics* metrics ) + { + FT_Error error = TT_Err_Ok; + + + switch ( range->image_format ) + { + case 1: + case 2: + case 8: + /* variable small metrics */ + { + TT_SBit_Small_Metrics smetrics; + + const FT_Frame_Field sbit_small_metrics_fields[] = + { + FT_FRAME_START( 5 ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, height ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, width ), + FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingX ), + FT_FRAME_CHAR( TT_SBit_Small_Metrics, bearingY ), + FT_FRAME_BYTE( TT_SBit_Small_Metrics, advance ), + FT_FRAME_END + }; + + + /* read small metrics */ + if ( READ_Fields( sbit_small_metrics_fields, &smetrics ) ) + goto Exit; + + /* convert it to a big metrics */ + metrics->height = smetrics.height; + metrics->width = smetrics.width; + metrics->horiBearingX = smetrics.bearingX; + metrics->horiBearingY = smetrics.bearingY; + metrics->horiAdvance = smetrics.advance; + + /* these metrics are made up at a higher level when */ + /* needed. */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + } + break; + + case 6: + case 7: + case 9: + /* variable big metrics */ + (void)READ_Fields( sbit_metrics_fields, metrics ); + break; + + case 5: + default: /* constant metrics */ + if ( range->index_format == 2 || range->index_format == 5 ) + *metrics = range->metrics; + else + return TT_Err_Invalid_File_Format; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Crop_Bitmap */ + /* */ + /* */ + /* Crops a bitmap to its tightest bounding box, and adjusts its */ + /* metrics. */ + /* */ + /* */ + /* image :: The input glyph slot. */ + /* */ + /* metrics :: The corresponding metrics structure. */ + /* */ + static + void Crop_Bitmap( FT_Bitmap* map, + TT_SBit_Metrics* metrics ) + { + /***********************************************************************/ + /* */ + /* In this situation, some bounding boxes of embedded bitmaps are too */ + /* large. We need to crop it to a reasonable size. */ + /* */ + /* --------- */ + /* | | ----- */ + /* | *** | |***| */ + /* | * | | * | */ + /* | * | ------> | * | */ + /* | * | | * | */ + /* | * | | * | */ + /* | *** | |***| */ + /* --------- ----- */ + /* */ + /***********************************************************************/ + + FT_Int rows, count; + FT_Long line_len; + FT_Byte* line; + + + /***********************************************************************/ + /* */ + /* first of all, check the top-most lines of the bitmap, and remove */ + /* them if they're empty. */ + /* */ + { + line = (FT_Byte*)map->buffer; + rows = map->rows; + line_len = map->pitch; + + + for ( count = 0; count < rows; count++ ) + { + FT_Byte* cur = line; + FT_Byte* limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Top; + + /* the current line was empty - skip to next one */ + line = limit; + } + + Found_Top: + /* check that we have at least one filled line */ + if ( count >= rows ) + goto Empty_Bitmap; + + /* now, crop the empty upper lines */ + if ( count > 0 ) + { + line = (FT_Byte*)map->buffer; + + MEM_Move( line, line + count * line_len, + ( rows - count ) * line_len ); + + metrics->height -= count; + metrics->horiBearingY -= count; + metrics->vertBearingY -= count; + + map->rows -= count; + rows -= count; + } + } + + /***********************************************************************/ + /* */ + /* second, crop the lower lines */ + /* */ + { + line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len; + + for ( count = 0; count < rows; count++ ) + { + FT_Byte* cur = line; + FT_Byte* limit = line + line_len; + + + for ( ; cur < limit; cur++ ) + if ( cur[0] ) + goto Found_Bottom; + + /* the current line was empty - skip to previous one */ + line -= line_len; + } + + Found_Bottom: + if ( count > 0 ) + { + metrics->height -= count; + rows -= count; + map->rows -= count; + } + } + + /***********************************************************************/ + /* */ + /* third, get rid of the space on the left side of the glyph */ + /* */ + do + { + FT_Byte* limit; + + + line = (FT_Byte*)map->buffer; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + if ( line[0] & 0x80 ) + goto Found_Left; + + /* shift the whole glyph one pixel to the left */ + line = (FT_Byte*)map->buffer; + limit = line + rows * line_len; + + for ( ; line < limit; line += line_len ) + { + FT_Int n, width = map->width; + FT_Byte old; + FT_Byte* cur = line; + + + old = cur[0] << 1; + for ( n = 8; n < width; n += 8 ) + { + FT_Byte val; + + + val = cur[1]; + cur[0] = old | ( val >> 7 ); + old = val << 1; + cur++; + } + cur[0] = old; + } + + map->width--; + metrics->horiBearingX++; + metrics->vertBearingX++; + metrics->width--; + + } while ( map->width > 0 ); + + Found_Left: + + /***********************************************************************/ + /* */ + /* finally, crop the bitmap width to get rid of the space on the right */ + /* side of the glyph. */ + /* */ + do + { + FT_Int right = map->width - 1; + FT_Byte* limit; + FT_Byte mask; + + + line = (FT_Byte*)map->buffer + ( right >> 3 ); + limit = line + rows * line_len; + mask = 0x80 >> ( right & 7 ); + + for ( ; line < limit; line += line_len ) + if ( line[0] & mask ) + goto Found_Right; + + /* crop the whole glyph to the right */ + map->width--; + metrics->width--; + + } while ( map->width > 0 ); + + Found_Right: + /* all right, the bitmap was cropped */ + return; + + Empty_Bitmap: + map->width = 0; + map->rows = 0; + map->pitch = 0; + map->pixel_mode = ft_pixel_mode_mono; + } + + + static + FT_Error Load_SBit_Single( FT_Bitmap* map, + FT_Int x_offset, + FT_Int y_offset, + FT_Int pix_bits, + FT_UShort image_format, + TT_SBit_Metrics* metrics, + FT_Stream stream ) + { + FT_Error error; + + + /* check that the source bitmap fits into the target pixmap */ + if ( x_offset < 0 || x_offset + metrics->width > map->width || + y_offset < 0 || y_offset + metrics->height > map->rows ) + { + error = TT_Err_Invalid_Argument; + + goto Exit; + } + + { + FT_Int glyph_width = metrics->width; + FT_Int glyph_height = metrics->height; + FT_Int glyph_size; + FT_Int line_bits = pix_bits * glyph_width; + FT_Bool pad_bytes = 0; + + + /* compute size of glyph image */ + switch ( image_format ) + { + case 1: /* byte-padded formats */ + case 6: + { + FT_Int line_length; + + + switch ( pix_bits ) + { + case 1: line_length = ( glyph_width + 7 ) >> 3; break; + case 2: line_length = ( glyph_width + 3 ) >> 2; break; + case 4: line_length = ( glyph_width + 1 ) >> 1; break; + default: line_length = glyph_width; + } + + glyph_size = glyph_height * line_length; + pad_bytes = 1; + } + break; + + case 2: + case 5: + case 7: + line_bits = glyph_width * pix_bits; + glyph_size = ( glyph_height * line_bits + 7 ) >> 3; + break; + + default: /* invalid format */ + return TT_Err_Invalid_File_Format; + } + + /* Now read data and draw glyph into target pixmap */ + if ( ACCESS_Frame( glyph_size ) ) + goto Exit; + + /* don't forget to multiply `x_offset' by `map->pix_bits' as */ + /* the sbit blitter doesn't make a difference between pixmap */ + /* depths. */ + blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes, + x_offset * pix_bits, y_offset ); + + FORGET_Frame(); + } + + Exit: + return error; + } + + + static + FT_Error Load_SBit_Image( TT_SBit_Strike* strike, + TT_SBit_Range* range, + FT_ULong ebdt_pos, + FT_ULong glyph_offset, + FT_Bitmap* map, + FT_Int x_offset, + FT_Int y_offset, + FT_Stream stream, + TT_SBit_Metrics* metrics ) + { + FT_Memory memory = stream->memory; + FT_Error error; + + + /* place stream at beginning of glyph data and read metrics */ + if ( FILE_Seek( ebdt_pos + glyph_offset ) ) + goto Exit; + + error = Load_SBit_Metrics( stream, range, metrics ); + if ( error ) + goto Exit; + + /* this function is recursive. At the top-level call, the */ + /* field map.buffer is NULL. We thus begin by finding the */ + /* dimensions of the higher-level glyph to allocate the */ + /* final pixmap buffer */ + if ( map->buffer == 0 ) + { + FT_Long size; + + + map->width = metrics->width; + map->rows = metrics->height; + + switch ( strike->bit_depth ) + { + case 1: + map->pixel_mode = ft_pixel_mode_mono; + map->pitch = ( map->width + 7 ) >> 3; + break; + + case 2: + map->pixel_mode = ft_pixel_mode_pal2; + map->pitch = ( map->width + 3 ) >> 2; + break; + + case 4: + map->pixel_mode = ft_pixel_mode_pal4; + map->pitch = ( map->width + 1 ) >> 1; + break; + + case 8: + map->pixel_mode = ft_pixel_mode_grays; + map->pitch = map->width; + break; + + default: + return TT_Err_Invalid_File_Format; + } + + size = map->rows * map->pitch; + + /* check that there is no empty image */ + if ( size == 0 ) + goto Exit; /* exit successfully! */ + + if ( ALLOC( map->buffer, size ) ) + goto Exit; + } + + switch ( range->image_format ) + { + case 1: /* single sbit image - load it */ + case 2: + case 5: + case 6: + case 7: + return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth, + range->image_format, metrics, stream ); + + case 8: /* compound format */ + FT_Skip_Stream( stream, 1L ); + /* fallthrough */ + + case 9: + break; + + default: /* invalid image format */ + return TT_Err_Invalid_File_Format; + } + + /* All right, we have a compound format. First of all, read */ + /* the array of elements. */ + { + TT_SBit_Component* components; + TT_SBit_Component* comp; + FT_UShort num_components, count; + + + if ( READ_UShort( num_components ) || + ALLOC_ARRAY( components, num_components, TT_SBit_Component ) ) + goto Exit; + + count = num_components; + + if ( ACCESS_Frame( 4L * num_components ) ) + goto Fail_Memory; + + for ( comp = components; count > 0; count--, comp++ ) + { + comp->glyph_code = GET_UShort(); + comp->x_offset = GET_Char(); + comp->y_offset = GET_Char(); + } + + FORGET_Frame(); + + /* Now recursively load each element glyph */ + count = num_components; + comp = components; + for ( ; count > 0; count--, comp++ ) + { + TT_SBit_Range* elem_range; + TT_SBit_Metrics elem_metrics; + FT_ULong elem_offset; + + + /* find the range for this element */ + error = Find_SBit_Range( comp->glyph_code, + strike, + &elem_range, + &elem_offset ); + if ( error ) + goto Fail_Memory; + + /* now load the element, recursively */ + error = Load_SBit_Image( strike, + elem_range, + ebdt_pos, + elem_offset, + map, + x_offset + comp->x_offset, + y_offset + comp->y_offset, + stream, + &elem_metrics ); + if ( error ) + goto Fail_Memory; + } + + Fail_Memory: + FREE( components ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_SBit_Image */ + /* */ + /* */ + /* Loads a given glyph sbit image from the font resource. This also */ + /* returns its metrics. */ + /* */ + /* */ + /* face :: The target face object. */ + /* */ + /* x_ppem :: The horizontal resolution in points per EM. */ + /* */ + /* y_ppem :: The vertical resolution in points per EM. */ + /* */ + /* glyph_index :: The current glyph index. */ + /* */ + /* load_flags :: The glyph load flags (the code checks for the flag */ + /* FT_LOAD_CROP_BITMAP */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* map :: The target pixmap. */ + /* */ + /* metrics :: A big sbit metrics structure for the glyph image. */ + /* */ + /* */ + /* FreeType error code. 0 means success. Returns an error if no */ + /* glyph sbit exists for the index. */ + /* */ + /* */ + /* The `map.buffer' field is always freed before the glyph is loaded. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_SBit_Image( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong ebdt_pos, glyph_offset; + + TT_SBit_Strike* strike; + TT_SBit_Range* range; + + + /* Check whether there is a glyph sbit for the current index */ + error = Find_SBit_Image( face, glyph_index, x_ppem, y_ppem, + &range, &strike, &glyph_offset ); + if ( error ) + goto Exit; + + /* now, find the location of the `EBDT' table in */ + /* the font file */ + error = face->goto_table( face, TTAG_EBDT, stream, 0 ); + if ( error ) + error = face->goto_table( face, TTAG_bdat, stream, 0 ); + if (error) + goto Exit; + + ebdt_pos = FILE_Pos(); + + /* clear the bitmap & load the bitmap */ + if ( face->root.glyph->flags & ft_glyph_own_bitmap ) + FREE( map->buffer ); + + map->rows = map->pitch = map->width = 0; + + error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset, + map, 0, 0, stream, metrics ); + if ( error ) + goto Exit; + + /* the glyph slot owns this bitmap buffer */ + face->root.glyph->flags |= ft_glyph_own_bitmap; + + /* setup vertical metrics if needed */ + if ( strike->flags & 1 ) + { + /* in case of a horizontal strike only */ + FT_Int advance; + FT_Int top; + + + advance = strike->hori.ascender - strike->hori.descender; + top = advance / 10; + + /* some heuristic values */ + + metrics->vertBearingX = -metrics->width / 2; + metrics->vertBearingY = advance / 10; + metrics->vertAdvance = advance * 12 / 10; + } + + /* Crop the bitmap now, unless specified otherwise */ + if ( load_flags & FT_LOAD_CROP_BITMAP ) + Crop_Bitmap( map, metrics ); + + Exit: + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/sfnt/ttsbit.h b/subsys/win32k/freetype/src/sfnt/ttsbit.h new file mode 100644 index 0000000..46b80f3 --- /dev/null +++ b/subsys/win32k/freetype/src/sfnt/ttsbit.h @@ -0,0 +1,65 @@ +/***************************************************************************/ +/* */ +/* ttsbit.h */ +/* */ +/* TrueType and OpenType embedded bitmap support (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTSBIT_H +#define TTSBIT_H + + +#ifdef FT_FLAT_COMPILE + +#include "ttload.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_Load_SBit_Strikes( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void TT_Free_SBit_Strikes( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Load_SBit_Image( TT_Face face, + FT_Int x_ppem, + FT_Int y_ppem, + FT_UInt glyph_index, + FT_UInt load_flags, + FT_Stream stream, + FT_Bitmap* map, + TT_SBit_Metrics* metrics ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTSBIT_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/smooth/.cvsignore b/subsys/win32k/freetype/src/smooth/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/smooth/ftgrays.c b/subsys/win32k/freetype/src/smooth/ftgrays.c new file mode 100644 index 0000000..5a444ad --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/ftgrays.c @@ -0,0 +1,1969 @@ +/***************************************************************************/ +/* */ +/* ftgrays.c */ +/* */ +/* A new `perfect' anti-aliasing renderer (body). */ +/* */ +/* Copyright 2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + /*************************************************************************/ + /* */ + /* This file can be compiled without the rest of the FreeType engine, */ + /* by defining the _STANDALONE_ macro when compiling it. You also need */ + /* to put the files `ftgrays.h' and `ftimage.h' into the current */ + /* compilation directory. Typically, you could do something like */ + /* */ + /* - copy `src/base/ftgrays.c' to your current directory */ + /* */ + /* - copy `include/freetype/ftimage.h' and */ + /* `include/freetype/ftgrays.h' to the same directory */ + /* */ + /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */ + /* */ + /* cc -c -D_STANDALONE_ ftgrays.c */ + /* */ + /* The renderer can be initialized with a call to */ + /* `ft_grays_raster.grays_raster_new'; an anti-aliased bitmap can be */ + /* generated with a call to `ft_grays_raster.grays_raster_render'. */ + /* */ + /* See the comments and documentation in the file `ftimage.h' for */ + /* more details on how the raster works. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* This is a new anti-aliasing scan-converter for FreeType 2. The */ + /* algorithm used here is _very_ different from the one in the standard */ + /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */ + /* coverage of the outline on each pixel cell. */ + /* */ + /* It is based on ideas that I initially found in Raph Levien's */ + /* excellent LibArt graphics library (see http://www.levien.com/libart */ + /* for more information, though the web pages do not tell anything */ + /* about the renderer; you'll have to dive into the source code to */ + /* understand how it works). */ + /* */ + /* Note, however, that this is a _very_ different implementation */ + /* compared to Raph's. Coverage information is stored in a very */ + /* different way, and I don't use sorted vector paths. Also, it */ + /* doesn't use floating point values. */ + /* */ + /* This renderer has the following advantages: */ + /* */ + /* - It doesn't need an intermediate bitmap. Instead, one can supply */ + /* a callback function that will be called by the renderer to draw */ + /* gray spans on any target surface. You can thus do direct */ + /* composition on any kind of bitmap, provided that you give the */ + /* renderer the right callback. */ + /* */ + /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */ + /* each pixel cell */ + /* */ + /* - It performs a single pass on the outline (the `standard' FT2 */ + /* renderer makes two passes). */ + /* */ + /* - It can easily be modified to render to _any_ number of gray levels */ + /* cheaply. */ + /* */ + /* - For small (< 20) pixel sizes, it is faster than the standard */ + /* renderer. */ + /* */ + /*************************************************************************/ + + +#include /* for memcpy() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_aaraster + + +#ifdef _STANDALONE_ + + +#define ErrRaster_Invalid_Mode -2 +#define ErrRaster_Invalid_Outline -1 + +#include "ftimage.h" +#include "ftgrays.h" + + /* This macro is used to indicate that a function parameter is unused. */ + /* Its purpose is simply to reduce compiler warnings. Note also that */ + /* simply defining it as `(void)x' doesn't avoid warnings with certain */ + /* ANSI compilers (e.g. LCC). */ +#define FT_UNUSED( x ) (x) = (x) + + /* Disable the tracing mechanism for simplicity -- developers can */ + /* activate it easily by redefining these two macros. */ +#ifndef FT_ERROR +#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */ +#endif + +#ifndef FT_TRACE +#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */ +#endif + + +#else /* _STANDALONE_ */ + + +#ifdef FT_FLAT_COMPILE + +#include "ftgrays.h" + +#else + +#include + +#endif + + +#include /* for FT_UNUSED() */ +#include /* for FT_TRACE() and FT_ERROR() */ +#include /* for FT_Outline_Decompose() */ + +#define ErrRaster_Invalid_Mode FT_Err_Cannot_Render_Glyph +#define ErrRaster_Invalid_Outline FT_Err_Invalid_Outline + + +#endif /* _STANDALONE_ */ + + + /* define this to dump debugging information */ +#define xxxDEBUG_GRAYS + + /* as usual, for the speed hungry :-) */ + +#ifndef FT_STATIC_RASTER + + +#define RAS_ARG PRaster raster +#define RAS_ARG_ PRaster raster, + +#define RAS_VAR raster +#define RAS_VAR_ raster, + +#define ras (*raster) + + +#else /* FT_STATIC_RASTER */ + + +#define RAS_ARG /* empty */ +#define RAS_ARG_ /* empty */ +#define RAS_VAR /* empty */ +#define RAS_VAR_ /* empty */ + + static TRaster ras; + + +#endif /* FT_STATIC_RASTER */ + + + /* must be at least 6 bits! */ +#define PIXEL_BITS 8 + +#define ONE_PIXEL ( 1L << PIXEL_BITS ) +#define PIXEL_MASK ( -1L << PIXEL_BITS ) +#define TRUNC( x ) ( (x) >> PIXEL_BITS ) +#define SUBPIXELS( x ) ( (x) << PIXEL_BITS ) +#define FLOOR( x ) ( (x) & -ONE_PIXEL ) +#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) +#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL ) + +#if PIXEL_BITS >= 6 +#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) ) +#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) ) +#else +#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) ) +#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) +#endif + + /* Define this if you want to use a more compact storage scheme. This */ + /* increases the number of cells available in the render pool but slows */ + /* down the rendering a bit. It is useful if you have a really tiny */ + /* render pool. */ +#define xxxGRAYS_COMPACT + + + /*************************************************************************/ + /* */ + /* TYPE DEFINITIONS */ + /* */ + typedef int TScan; /* integer scanline/pixel coordinate */ + typedef long TPos; /* sub-pixel coordinate */ + + /* maximal number of gray spans in a call to the span callback */ +#define FT_MAX_GRAY_SPANS 32 + + +#ifdef GRAYS_COMPACT + + typedef struct TCell_ + { + short x : 14; + short y : 14; + int cover : PIXEL_BITS + 2; + int area : PIXEL_BITS * 2 + 2; + + } TCell, *PCell; + +#else /* GRAYS_COMPACT */ + + typedef struct TCell_ + { + TScan x; + TScan y; + int cover; + int area; + + } TCell, *PCell; + +#endif /* GRAYS_COMPACT */ + + + typedef struct TRaster_ + { + PCell cells; + int max_cells; + int num_cells; + + TScan min_ex, max_ex; + TScan min_ey, max_ey; + + int area; + int cover; + int invalid; + + TScan ex, ey; + TScan cx, cy; + TPos x, y; + + TScan last_ey; + + FT_Vector bez_stack[32 * 3]; + int lev_stack[32]; + + FT_Outline outline; + FT_Bitmap target; + + FT_Span gray_spans[FT_MAX_GRAY_SPANS]; + int num_gray_spans; + + FT_Raster_Span_Func render_span; + void* render_span_data; + int span_y; + + int band_size; + int band_shoot; + int conic_level; + int cubic_level; + + void* memory; + + } TRaster, *PRaster; + + + /*************************************************************************/ + /* */ + /* Initialize the cells table. */ + /* */ + static + void init_cells( RAS_ARG_ void* buffer, + long byte_size ) + { + ras.cells = (PCell)buffer; + ras.max_cells = byte_size / sizeof ( TCell ); + ras.num_cells = 0; + ras.area = 0; + ras.cover = 0; + ras.invalid = 1; + } + + + /*************************************************************************/ + /* */ + /* Compute the outline bounding box. */ + /* */ + static + void compute_cbox( RAS_ARG_ FT_Outline* outline ) + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + outline->n_points; + + + if ( outline->n_points <= 0 ) + { + ras.min_ex = ras.max_ex = 0; + ras.min_ey = ras.max_ey = 0; + return; + } + + ras.min_ex = ras.max_ex = vec->x; + ras.min_ey = ras.max_ey = vec->y; + + vec++; + + for ( ; vec < limit; vec++ ) + { + TPos x = vec->x; + TPos y = vec->y; + + + if ( x < ras.min_ex ) ras.min_ex = x; + if ( x > ras.max_ex ) ras.max_ex = x; + if ( y < ras.min_ey ) ras.min_ey = y; + if ( y > ras.max_ey ) ras.max_ey = y; + } + + /* truncate the bounding box to integer pixels */ + ras.min_ex = ras.min_ex >> 6; + ras.min_ey = ras.min_ey >> 6; + ras.max_ex = ( ras.max_ex + 63 ) >> 6; + ras.max_ey = ( ras.max_ey + 63 ) >> 6; + } + + + /*************************************************************************/ + /* */ + /* Record the current cell in the table. */ + /* */ + static + int record_cell( RAS_ARG ) + { + PCell cell; + + + if ( !ras.invalid && ( ras.area | ras.cover ) ) + { + if ( ras.num_cells >= ras.max_cells ) + return 1; + + cell = ras.cells + ras.num_cells++; + cell->x = ras.ex - ras.min_ex; + cell->y = ras.ey - ras.min_ey; + cell->area = ras.area; + cell->cover = ras.cover; + } + + return 0; + } + + + /*************************************************************************/ + /* */ + /* Set the current cell to a new position. */ + /* */ + static + int set_cell( RAS_ARG_ TScan ex, + TScan ey ) + { + int invalid, record, clean; + + + /* Move the cell pointer to a new position. We set the `invalid' */ + /* flag to indicate that the cell isn't part of those we're interested */ + /* in during the render phase. This means that: */ + /* */ + /* . the new vertical position must be within min_ey..max_ey-1. */ + /* . the new horizontal position must be strictly less than max_ex */ + /* */ + /* Note that if a cell is to the left of the clipping region, it is */ + /* actually set to the (min_ex-1) horizontal position. */ + + record = 0; + clean = 1; + + invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex ); + if ( !invalid ) + { + /* All cells that are on the left of the clipping region go to the */ + /* min_ex - 1 horizontal position. */ + if ( ex < ras.min_ex ) + ex = ras.min_ex - 1; + + /* if our position is new, then record the previous cell */ + if ( ex != ras.ex || ey != ras.ey ) + record = 1; + else + clean = ras.invalid; /* do not clean if we didn't move from */ + /* a valid cell */ + } + + /* record the previous cell if needed (i.e., if we changed the cell */ + /* position, of changed the `invalid' flag) */ + if ( ( ras.invalid != invalid || record ) && record_cell( RAS_VAR ) ) + return 1; + + if ( clean ) + { + ras.area = 0; + ras.cover = 0; + } + + ras.invalid = invalid; + ras.ex = ex; + ras.ey = ey; + return 0; + } + + + /*************************************************************************/ + /* */ + /* Start a new contour at a given cell. */ + /* */ + static + void start_cell( RAS_ARG_ TScan ex, + TScan ey ) + { + if ( ex < ras.min_ex ) + ex = ras.min_ex - 1; + + ras.area = 0; + ras.cover = 0; + ras.ex = ex; + ras.ey = ey; + ras.last_ey = SUBPIXELS( ey ); + ras.invalid = 0; + + (void)set_cell( RAS_VAR_ ex, ey ); + } + + + /*************************************************************************/ + /* */ + /* Render a scanline as one or more cells. */ + /* */ + static + int render_scanline( RAS_ARG_ TScan ey, + TPos x1, + TScan y1, + TPos x2, + TScan y2 ) + { + TScan ex1, ex2, fx1, fx2, delta; + long p, first, dx; + int incr, lift, mod, rem; + + + dx = x2 - x1; + + ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */ + ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */ + fx1 = x1 - SUBPIXELS( ex1 ); + fx2 = x2 - SUBPIXELS( ex2 ); + + /* trivial case. Happens often */ + if ( y1 == y2 ) + return set_cell( RAS_VAR_ ex2, ey ); + + /* everything is located in a single cell. That is easy! */ + /* */ + if ( ex1 == ex2 ) + { + delta = y2 - y1; + ras.area += ( fx1 + fx2 ) * delta; + ras.cover += delta; + return 0; + } + + /* ok, we'll have to render a run of adjacent cells on the same */ + /* scanline... */ + /* */ + p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 ); + first = ONE_PIXEL; + incr = 1; + + if ( dx < 0 ) + { + p = fx1 * ( y2 - y1 ); + first = 0; + incr = -1; + dx = -dx; + } + + delta = p / dx; + mod = p % dx; + if ( mod < 0 ) + { + delta--; + mod += dx; + } + + ras.area += ( fx1 + first ) * delta; + ras.cover += delta; + + ex1 += incr; + if ( set_cell( RAS_VAR_ ex1, ey ) ) + goto Error; + y1 += delta; + + if ( ex1 != ex2 ) + { + p = ONE_PIXEL * ( y2 - y1 ); + lift = p / dx; + rem = p % dx; + if ( rem < 0 ) + { + lift--; + rem += dx; + } + + mod -= dx; + + while ( ex1 != ex2 ) + { + delta = lift; + mod += rem; + if ( mod >= 0 ) + { + mod -= dx; + delta++; + } + + ras.area += ONE_PIXEL * delta; + ras.cover += delta; + y1 += delta; + ex1 += incr; + if ( set_cell( RAS_VAR_ ex1, ey ) ) + goto Error; + } + } + + delta = y2 - y1; + ras.area += ( fx2 + ONE_PIXEL - first ) * delta; + ras.cover += delta; + + return 0; + + Error: + return 1; + } + + + /*************************************************************************/ + /* */ + /* Render a given line as a series of scanlines. */ + /* */ + static + int render_line( RAS_ARG_ TPos to_x, + TPos to_y ) + { + TScan ey1, ey2, fy1, fy2; + TPos dx, dy, x, x2; + int p, rem, mod, lift, delta, first, incr; + + + ey1 = TRUNC( ras.last_ey ); + ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ + fy1 = ras.y - ras.last_ey; + fy2 = to_y - SUBPIXELS( ey2 ); + + dx = to_x - ras.x; + dy = to_y - ras.y; + + /* XXX: we should do something about the trivial case where dx == 0, */ + /* as it happens very often! */ + + /* perform vertical clipping */ + { + TScan min, max; + + + min = ey1; + max = ey2; + if ( ey1 > ey2 ) + { + min = ey2; + max = ey1; + } + if ( min >= ras.max_ey || max < ras.min_ey ) + goto End; + } + + /* everything is on a single scanline */ + if ( ey1 == ey2 ) + { + if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) ) + goto Error; + goto End; + } + + /* ok, we have to render several scanlines */ + p = ( ONE_PIXEL - fy1 ) * dx; + first = ONE_PIXEL; + incr = 1; + + if ( dy < 0 ) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = p / dy; + mod = p % dy; + if ( mod < 0 ) + { + delta--; + mod += dy; + } + + x = ras.x + delta; + if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) ) + goto Error; + + ey1 += incr; + if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) ) + goto Error; + + if ( ey1 != ey2 ) + { + p = ONE_PIXEL * dx; + lift = p / dy; + rem = p % dy; + if ( rem < 0 ) + { + lift--; + rem += dy; + } + mod -= dy; + + while ( ey1 != ey2 ) + { + delta = lift; + mod += rem; + if ( mod >= 0 ) + { + mod -= dy; + delta++; + } + + x2 = x + delta; + if ( render_scanline( RAS_VAR_ ey1, + x, ONE_PIXEL - first, x2, first ) ) + goto Error; + x = x2; + ey1 += incr; + if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) ) + goto Error; + } + } + + if ( render_scanline( RAS_VAR_ ey1, + x, ONE_PIXEL - first, to_x, fy2 ) ) + goto Error; + + End: + ras.x = to_x; + ras.y = to_y; + ras.last_ey = SUBPIXELS( ey2 ); + + return 0; + + Error: + return 1; + } + + + static + void split_conic( FT_Vector* base ) + { + TPos a, b; + + + base[4].x = base[2].x; + b = base[1].x; + a = base[3].x = ( base[2].x + b ) / 2; + b = base[1].x = ( base[0].x + b ) / 2; + base[2].x = ( a + b ) / 2; + + base[4].y = base[2].y; + b = base[1].y; + a = base[3].y = ( base[2].y + b ) / 2; + b = base[1].y = ( base[0].y + b ) / 2; + base[2].y = ( a + b ) / 2; + } + + + static + int render_conic( RAS_ARG_ FT_Vector* control, + FT_Vector* to ) + { + TPos dx, dy; + int top, level; + int* levels; + FT_Vector* arc; + + + dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 ); + if ( dx < 0 ) + dx = -dx; + dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 ); + if ( dy < 0 ) + dy = -dy; + if ( dx < dy ) + dx = dy; + + level = 1; + dx = dx / ras.conic_level; + while ( dx > 0 ) + { + dx >>= 1; + level++; + } + + /* a shortcut to speed things up */ + if ( level <= 1 ) + { + /* we compute the mid-point directly in order to avoid */ + /* calling split_conic() */ + TPos to_x, to_y, mid_x, mid_y; + + + to_x = UPSCALE( to->x ); + to_y = UPSCALE( to->y ); + mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4; + mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4; + + return render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ); + } + + arc = ras.bez_stack; + levels = ras.lev_stack; + top = 0; + levels[0] = level; + + arc[0].x = UPSCALE( to->x ); + arc[0].y = UPSCALE( to->y ); + arc[1].x = UPSCALE( control->x ); + arc[1].y = UPSCALE( control->y ); + arc[2].x = ras.x; + arc[2].y = ras.y; + + while ( top >= 0 ) + { + level = levels[top]; + if ( level > 1 ) + { + /* check that the arc crosses the current band */ + TPos min, max, y; + + + min = max = arc[0].y; + + y = arc[1].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + + y = arc[2].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + + if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 ) + goto Draw; + + split_conic( arc ); + arc += 2; + top++; + levels[top] = levels[top - 1] = level - 1; + continue; + } + + Draw: + { + TPos to_x, to_y, mid_x, mid_y; + + + to_x = arc[0].x; + to_y = arc[0].y; + mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4; + mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4; + + if ( render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ) ) + return 1; + + top--; + arc -= 2; + } + } + return 0; + } + + + static + void split_cubic( FT_Vector* base ) + { + TPos a, b, c, d; + + + base[6].x = base[3].x; + c = base[1].x; + d = base[2].x; + base[1].x = a = ( base[0].x + c ) / 2; + base[5].x = b = ( base[3].x + d ) / 2; + c = ( c + d ) / 2; + base[2].x = a = ( a + c ) / 2; + base[4].x = b = ( b + c ) / 2; + base[3].x = ( a + b ) / 2; + + base[6].y = base[3].y; + c = base[1].y; + d = base[2].y; + base[1].y = a = ( base[0].y + c ) / 2; + base[5].y = b = ( base[3].y + d ) / 2; + c = ( c + d ) / 2; + base[2].y = a = ( a + c ) / 2; + base[4].y = b = ( b + c ) / 2; + base[3].y = ( a + b ) / 2; + } + + + static + int render_cubic( RAS_ARG_ FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to ) + { + TPos dx, dy, da, db; + int top, level; + int* levels; + FT_Vector* arc; + + + dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 ); + if ( dx < 0 ) + dx = -dx; + dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 ); + if ( dy < 0 ) + dy = -dy; + if ( dx < dy ) + dx = dy; + da = dx; + + dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x ); + if ( dx < 0 ) + dx = -dx; + dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y ); + if ( dy < 0 ) + dy = -dy; + if ( dx < dy ) + dx = dy; + db = dx; + + level = 1; + da = da / ras.cubic_level; + db = db / ras.conic_level; + while ( da > 0 || db > 0 ) + { + da >>= 1; + db >>= 2; + level++; + } + + if ( level <= 1 ) + { + TPos to_x, to_y, mid_x, mid_y; + + + to_x = UPSCALE( to->x ); + to_y = UPSCALE( to->y ); + mid_x = ( ras.x + to_x + + 3 * UPSCALE( control1->x + control2->x ) ) / 8; + mid_y = ( ras.y + to_y + + 3 * UPSCALE( control1->y + control2->y ) ) / 8; + + return render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ); + } + + arc = ras.bez_stack; + arc[0].x = UPSCALE( to->x ); + arc[0].y = UPSCALE( to->y ); + arc[1].x = UPSCALE( control2->x ); + arc[1].y = UPSCALE( control2->y ); + arc[2].x = UPSCALE( control1->x ); + arc[2].y = UPSCALE( control1->y ); + arc[3].x = ras.x; + arc[3].y = ras.y; + + levels = ras.lev_stack; + top = 0; + levels[0] = level; + + while ( top >= 0 ) + { + level = levels[top]; + if ( level > 1 ) + { + /* check that the arc crosses the current band */ + TPos min, max, y; + + + min = max = arc[0].y; + y = arc[1].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + y = arc[2].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + y = arc[3].y; + if ( y < min ) min = y; + if ( y > max ) max = y; + if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 ) + goto Draw; + split_cubic( arc ); + arc += 3; + top ++; + levels[top] = levels[top - 1] = level - 1; + continue; + } + + Draw: + { + TPos to_x, to_y, mid_x, mid_y; + + + to_x = arc[0].x; + to_y = arc[0].y; + mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8; + mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8; + + if ( render_line( RAS_VAR_ mid_x, mid_y ) || + render_line( RAS_VAR_ to_x, to_y ) ) + return 1; + top --; + arc -= 3; + } + } + return 0; + } + + + /* a macro comparing two cell pointers. Returns true if a <= b. */ +#if 1 + +#define PACK( a ) ( ( (long)(a)->y << 16 ) + (a)->x ) +#define LESS_THAN( a, b ) ( PACK( a ) < PACK( b ) ) + +#else /* 1 */ + +#define LESS_THAN( a, b ) ( (a)->y < (b)->y || \ + ( (a)->y == (b)->y && (a)->x < (b)->x ) ) + +#endif /* 1 */ + +#define SWAP_CELLS( a, b, temp ) do \ + { \ + temp = *(a); \ + *(a) = *(b); \ + *(b) = temp; \ + } while ( 0 ) +#define DEBUG_SORT +#define QUICK_SORT + +#ifdef SHELL_SORT + + /* a simple shell sort algorithm that works directly on our */ + /* cells table */ + static + void shell_sort ( PCell cells, + int count ) + { + PCell i, j, limit = cells + count; + TCell temp; + int gap; + + + /* compute initial gap */ + for ( gap = 0; ++gap < count; gap *= 3 ) + ; + + while ( gap /= 3 ) + { + for ( i = cells + gap; i < limit; i++ ) + { + for ( j = i - gap; ; j -= gap ) + { + PCell k = j + gap; + + + if ( LESS_THAN( j, k ) ) + break; + + SWAP_CELLS( j, k, temp ); + + if ( j < cells + gap ) + break; + } + } + } + } + +#endif /* SHELL_SORT */ + + +#ifdef QUICK_SORT + + /* This is a non-recursive quicksort that directly process our cells */ + /* array. It should be faster than calling the stdlib qsort(), and we */ + /* can even tailor our insertion threshold... */ + +#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */ + /* through a normal insertion sort */ + + static + void quick_sort( PCell cells, + int count ) + { + PCell stack[40]; /* should be enough ;-) */ + PCell* top; /* top of stack */ + PCell base, limit; + TCell temp; + + + limit = cells + count; + base = cells; + top = stack; + + for (;;) + { + int len = limit - base; + PCell i, j, pivot; + + + if ( len > QSORT_THRESHOLD ) + { + /* we use base + len/2 as the pivot */ + pivot = base + len / 2; + SWAP_CELLS( base, pivot, temp ); + + i = base + 1; + j = limit - 1; + + /* now ensure that *i <= *base <= *j */ + if ( LESS_THAN( j, i ) ) + SWAP_CELLS( i, j, temp ); + + if ( LESS_THAN( base, i ) ) + SWAP_CELLS( base, i, temp ); + + if ( LESS_THAN( j, base ) ) + SWAP_CELLS( base, j, temp ); + + for (;;) + { + do i++; while ( LESS_THAN( i, base ) ); + do j--; while ( LESS_THAN( base, j ) ); + + if ( i > j ) + break; + + SWAP_CELLS( i, j, temp ); + } + + SWAP_CELLS( base, j, temp ); + + /* now, push the largest sub-array */ + if ( j - base > limit - i ) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + /* the sub-array is small, perform insertion sort */ + j = base; + i = j + 1; + + for ( ; i < limit; j = i, i++ ) + { + for ( ; LESS_THAN( j + 1, j ); j-- ) + { + SWAP_CELLS( j + 1, j, temp ); + if ( j == base ) + break; + } + } + if ( top > stack ) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + break; + } + } + } + +#endif /* QUICK_SORT */ + + +#ifdef DEBUG_GRAYS +#ifdef DEBUG_SORT + + static + int check_sort( PCell cells, + int count ) + { + PCell p, q; + + + for ( p = cells + count - 2; p >= cells; p-- ) + { + q = p + 1; + if ( !LESS_THAN( p, q ) ) + return 0; + } + return 1; + } + +#endif /* DEBUG_SORT */ +#endif /* DEBUG_GRAYS */ + + + static + int Move_To( FT_Vector* to, + FT_Raster raster ) + { + TPos x, y; + + + /* record current cell, if any */ + record_cell( (PRaster)raster ); + + /* start to a new position */ + x = UPSCALE( to->x ); + y = UPSCALE( to->y ); + start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) ); + ((PRaster)raster)->x = x; + ((PRaster)raster)->y = y; + return 0; + } + + + static + int Line_To( FT_Vector* to, + FT_Raster raster ) + { + return render_line( (PRaster)raster, + UPSCALE( to->x ), UPSCALE( to->y ) ); + } + + + static + int Conic_To( FT_Vector* control, + FT_Vector* to, + FT_Raster raster ) + { + return render_conic( (PRaster)raster, control, to ); + } + + + static + int Cubic_To( FT_Vector* control1, + FT_Vector* control2, + FT_Vector* to, + FT_Raster raster ) + { + return render_cubic( (PRaster)raster, control1, control2, to ); + } + + + static + void grays_render_span( int y, + int count, + FT_Span* spans, + PRaster raster ) + { + unsigned char* p; + FT_Bitmap* map = &raster->target; + + + /* first of all, compute the scanline offset */ + p = (unsigned char*)map->buffer - y * map->pitch; + if ( map->pitch >= 0 ) + p += ( map->rows - 1 ) * map->pitch; + + for ( ; count > 0; count--, spans++ ) + { + if ( spans->coverage ) +#if 1 + memset( p + spans->x, (unsigned char)spans->coverage, spans->len ); +#else /* 1 */ + { + q = p + spans->x; + limit = q + spans->len; + for ( ; q < limit; q++ ) + q[0] = (unsigned char)spans->coverage; + } +#endif /* 1 */ + } + } + + +#ifdef DEBUG_GRAYS + +#include + + static + void dump_cells( RAS_ARG ) + { + PCell cell, limit; + int y = -1; + + + cell = ras.cells; + limit = cell + ras.num_cells; + + for ( ; cell < limit; cell++ ) + { + if ( cell->y != y ) + { + fprintf( stderr, "\n%2d: ", cell->y ); + y = cell->y; + } + fprintf( stderr, "[%d %d %d]", + cell->x, cell->area, cell->cover ); + } + fprintf(stderr, "\n" ); + } + +#endif /* DEBUG_GRAYS */ + + + static + void grays_hline( RAS_ARG_ TScan x, + TScan y, + TPos area, + int acount ) + { + FT_Span* span; + int count; + int coverage; + + + /* compute the coverage line's coverage, depending on the */ + /* outline fill rule */ + /* */ + /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ + /* */ + coverage = area >> ( PIXEL_BITS * 2 + 1 - 8); /* use range 0..256 */ + + if ( ras.outline.flags & ft_outline_even_odd_fill ) + { + if ( coverage < 0 ) + coverage = -coverage; + + while ( coverage >= 512 ) + coverage -= 512; + + if ( coverage > 256 ) + coverage = 512 - coverage; + else if ( coverage == 256 ) + coverage = 255; + } + else + { + /* normal non-zero winding rule */ + if ( coverage < 0 ) + coverage = -coverage; + + if ( coverage >= 256 ) + coverage = 255; + } + + y += ras.min_ey; + x += ras.min_ex; + + if ( coverage ) + { + /* see if we can add this span to the current list */ + count = ras.num_gray_spans; + span = ras.gray_spans + count - 1; + if ( count > 0 && + ras.span_y == y && + (int)span->x + span->len == (int)x && + span->coverage == coverage ) + { + span->len += acount; + return; + } + + if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) + { + if ( ras.render_span ) + ras.render_span( ras.span_y, count, ras.gray_spans, + ras.render_span_data ); + /* ras.render_span( span->y, ras.gray_spans, count ); */ + +#ifdef DEBUG_GRAYS + + if ( ras.span_y >= 0 ) + { + int n; + + + fprintf( stderr, "y=%3d ", ras.span_y ); + span = ras.gray_spans; + for ( n = 0; n < count; n++, span++ ) + fprintf( stderr, "[%d..%d]:%02x ", + span->x, span->x + span->len - 1, span->coverage ); + fprintf( stderr, "\n" ); + } + +#endif /* DEBUG_GRAYS */ + + ras.num_gray_spans = 0; + ras.span_y = y; + + count = 0; + span = ras.gray_spans; + } + else + span++; + + /* add a gray span to the current list */ + span->x = (short)x; + span->len = (unsigned short)acount; + span->coverage = (unsigned char)coverage; + ras.num_gray_spans++; + } + } + + + static + void grays_sweep( RAS_ARG_ FT_Bitmap* target ) + { + TScan x, y, cover, area; + PCell start, cur, limit; + + FT_UNUSED( target ); + + + cur = ras.cells; + limit = cur + ras.num_cells; + + cover = 0; + ras.span_y = -1; + ras.num_gray_spans = 0; + + for (;;) + { + start = cur; + y = start->y; + x = start->x; + + area = start->area; + cover += start->cover; + + /* accumulate all start cells */ + for (;;) + { + ++cur; + if ( cur >= limit || cur->y != start->y || cur->x != start->x ) + break; + + area += cur->area; + cover += cur->cover; + } + + /* if the start cell has a non-null area, we must draw an */ + /* individual gray pixel there */ + if ( area && x >= 0 ) + { + grays_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 ); + x++; + } + + if ( x < 0 ) + x = 0; + + if ( cur < limit && start->y == cur->y ) + { + /* draw a gray span between the start cell and the current one */ + if ( cur->x > x ) + grays_hline( RAS_VAR_ x, y, + cover * ( ONE_PIXEL * 2 ), cur->x - x ); + } + else + { + /* draw a gray span until the end of the clipping region */ + if ( cover && x < ras.max_ex - ras.min_ex ) + grays_hline( RAS_VAR_ x, y, + cover * ( ONE_PIXEL * 2 ), + ras.max_ex - x - ras.min_ex ); + cover = 0; + } + + if ( cur >= limit ) + break; + } + + if ( ras.render_span && ras.num_gray_spans > 0 ) + ras.render_span( ras.span_y, ras.num_gray_spans, + ras.gray_spans, ras.render_span_data ); + +#ifdef DEBUG_GRAYS + + { + int n; + FT_Span* span; + + + fprintf( stderr, "y=%3d ", ras.span_y ); + span = ras.gray_spans; + for ( n = 0; n < ras.num_gray_spans; n++, span++ ) + fprintf( stderr, "[%d..%d]:%02x ", + span->x, span->x + span->len - 1, span->coverage ); + fprintf( stderr, "\n" ); + } + +#endif /* DEBUG_GRAYS */ + + } + + +#ifdef _STANDALONE_ + + /*************************************************************************/ + /* */ + /* The following function should only compile in stand_alone mode, */ + /* i.e., when building this component without the rest of FreeType. */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* FT_Outline_Decompose */ + /* */ + /* */ + /* Walks over an outline's structure to decompose it into individual */ + /* segments and Bezier arcs. This function is also able to emit */ + /* `move to' and `close to' operations to indicate the start and end */ + /* of new contours in the outline. */ + /* */ + /* */ + /* outline :: A pointer to the source target. */ + /* */ + /* interface :: A table of `emitters', i.e,. function pointers called */ + /* during decomposition to indicate path operations. */ + /* */ + /* user :: A typeless pointer which is passed to each emitter */ + /* during the decomposition. It can be used to store */ + /* the state during the decomposition. */ + /* */ + /* */ + /* Error code. 0 means sucess. */ + /* */ + static + int FT_Outline_Decompose( FT_Outline* outline, + FT_Outline_Funcs* interface, + void* user ) + { +#undef SCALED +#define SCALED( x ) ( ( (x) << shift ) - delta ) + + FT_Vector v_last; + FT_Vector v_control; + FT_Vector v_start; + + FT_Vector* point; + FT_Vector* limit; + char* tags; + + int n; /* index of contour in outline */ + int first; /* index of first point in contour */ + int error; + char tag; /* current point's state */ + + int shift = interface->shift; + FT_Pos delta = interface->delta; + + + first = 0; + + for ( n = 0; n < outline->n_contours; n++ ) + { + int last; /* index of last point in contour */ + + + last = outline->contours[n]; + limit = outline->points + last; + + v_start = outline->points[first]; + v_last = outline->points[last]; + + v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y ); + v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y ); + + v_control = v_start; + + point = outline->points + first; + tags = outline->tags + first; + tag = FT_CURVE_TAG( tags[0] ); + + /* A contour cannot start with a cubic control point! */ + if ( tag == FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + /* check first point to determine origin */ + if ( tag == FT_Curve_Tag_Conic ) + { + /* first point is conic control. Yes, this happens. */ + if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On ) + { + /* start at last point if it is on the curve */ + v_start = v_last; + limit--; + } + else + { + /* if both first and last points are conic, */ + /* start at their middle and record its position */ + /* for closure */ + v_start.x = ( v_start.x + v_last.x ) / 2; + v_start.y = ( v_start.y + v_last.y ) / 2; + + v_last = v_start; + } + point--; + tags--; + } + + error = interface->move_to( &v_start, user ); + if ( error ) + goto Exit; + + while ( point < limit ) + { + point++; + tags++; + + tag = FT_CURVE_TAG( tags[0] ); + switch ( tag ) + { + case FT_Curve_Tag_On: /* emit a single line_to */ + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = interface->line_to( &vec, user ); + if ( error ) + goto Exit; + continue; + } + + case FT_Curve_Tag_Conic: /* consume conic arcs */ + { + v_control.x = SCALED( point->x ); + v_control.y = SCALED( point->y ); + + Do_Conic: + if ( point < limit ) + { + FT_Vector vec; + FT_Vector v_middle; + + + point++; + tags++; + tag = FT_CURVE_TAG( tags[0] ); + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + if ( tag == FT_Curve_Tag_On ) + { + error = interface->conic_to( &v_control, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + if ( tag != FT_Curve_Tag_Conic ) + goto Invalid_Outline; + + v_middle.x = ( v_control.x + vec.x ) / 2; + v_middle.y = ( v_control.y + vec.y ) / 2; + + error = interface->conic_to( &v_control, &v_middle, user ); + if ( error ) + goto Exit; + + v_control = vec; + goto Do_Conic; + } + + error = interface->conic_to( &v_control, &v_start, user ); + goto Close; + } + + default: /* FT_Curve_Tag_Cubic */ + { + FT_Vector vec1, vec2; + + + if ( point + 1 > limit || + FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic ) + goto Invalid_Outline; + + point += 2; + tags += 2; + + vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y ); + vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y ); + + if ( point <= limit ) + { + FT_Vector vec; + + + vec.x = SCALED( point->x ); + vec.y = SCALED( point->y ); + + error = interface->cubic_to( &vec1, &vec2, &vec, user ); + if ( error ) + goto Exit; + continue; + } + + error = interface->cubic_to( &vec1, &vec2, &v_start, user ); + goto Close; + } + } + } + + /* close the contour with a line segment */ + error = interface->line_to( &v_start, user ); + + Close: + if ( error ) + goto Exit; + + first = last + 1; + } + + return 0; + + Exit: + return error; + + Invalid_Outline: + return ErrRaster_Invalid_Outline; + } + +#endif /* _STANDALONE_ */ + + + typedef struct TBand_ + { + FT_Pos min, max; + + } TBand; + + + static + int grays_convert_glyph( RAS_ARG_ FT_Outline* outline ) + { + static + FT_Outline_Funcs interface = + { + (FT_Outline_MoveTo_Func) Move_To, + (FT_Outline_LineTo_Func) Line_To, + (FT_Outline_ConicTo_Func)Conic_To, + (FT_Outline_CubicTo_Func)Cubic_To, + 0, + 0 + }; + + TBand bands[40], *band; + int n, num_bands; + TPos min, max, max_y; + + + /* Set up state in the raster object */ + compute_cbox( RAS_VAR_ outline ); + + /* clip to target bitmap, exit if nothing to do */ + if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width || + ras.max_ey <= 0 || ras.min_ey >= ras.target.rows ) + return 0; + + if ( ras.min_ex < 0 ) ras.min_ex = 0; + if ( ras.min_ey < 0 ) ras.min_ey = 0; + + if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width; + if ( ras.max_ey > ras.target.rows ) ras.max_ey = ras.target.rows; + + /* simple heuristic used to speed-up the bezier decomposition -- see */ + /* the code in render_conic() and render_cubic() for more details */ + ras.conic_level = 32; + ras.cubic_level = 16; + + { + int level = 0; + + + if ( ras.max_ex > 24 || ras.max_ey > 24 ) + level++; + if ( ras.max_ex > 120 || ras.max_ey > 120 ) + level += 2; + + ras.conic_level <<= level; + ras.cubic_level <<= level; + } + + /* setup vertical bands */ + num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size; + if ( num_bands == 0 ) num_bands = 1; + if ( num_bands >= 39 ) num_bands = 39; + + ras.band_shoot = 0; + + min = ras.min_ey; + max_y = ras.max_ey; + + for ( n = 0; n < num_bands; n++, min = max ) + { + max = min + ras.band_size; + if ( n == num_bands - 1 || max > max_y ) + max = max_y; + + bands[0].min = min; + bands[0].max = max; + band = bands; + + while ( band >= bands ) + { + FT_Pos bottom, top, middle; + int error; + + + ras.num_cells = 0; + ras.invalid = 1; + ras.min_ey = band->min; + ras.max_ey = band->max; + + error = FT_Outline_Decompose( outline, &interface, &ras ) || + record_cell( RAS_VAR ); + + if ( !error ) + { +#ifdef SHELL_SORT + shell_sort( ras.cells, ras.num_cells ); +#else + quick_sort( ras.cells, ras.num_cells ); +#endif + +#ifdef DEBUG_GRAYS + check_sort( ras.cells, ras.num_cells ); + dump_cells( RAS_VAR ); +#endif + + grays_sweep( RAS_VAR_ &ras.target ); + band--; + continue; + } + + /* render pool overflow, we will reduce the render band by half */ + bottom = band->min; + top = band->max; + middle = bottom + ( ( top - bottom ) >> 1 ); + + /* waoow! This is too complex for a single scanline, something */ + /* must be really rotten here! */ + if ( middle == bottom ) + { +#ifdef DEBUG_GRAYS + fprintf( stderr, "Rotten glyph!\n" ); +#endif + return 1; + } + + if ( bottom-top >= ras.band_size ) + ras.band_shoot++; + + band[1].min = bottom; + band[1].max = middle; + band[0].min = middle; + band[0].max = top; + band++; + } + } + + if ( ras.band_shoot > 8 && ras.band_size > 16 ) + ras.band_size = ras.band_size / 2; + + return 0; + } + + + extern + int grays_raster_render( PRaster raster, + FT_Raster_Params* params ) + { + FT_Outline* outline = (FT_Outline*)params->source; + FT_Bitmap* target_map = params->target; + + + if ( !raster || !raster->cells || !raster->max_cells ) + return -1; + + /* return immediately if the outline is empty */ + if ( outline->n_points == 0 || outline->n_contours <= 0 ) + return 0; + + if ( !outline || !outline->contours || !outline->points ) + return ErrRaster_Invalid_Outline; + + if ( outline->n_points != + outline->contours[outline->n_contours - 1] + 1 ) + return ErrRaster_Invalid_Outline; + + if ( !target_map || !target_map->buffer ) + return -1; + + /* XXX: this version does not support monochrome rendering yet! */ + if ( !(params->flags & ft_raster_flag_aa) ) + return ErrRaster_Invalid_Mode; + + ras.outline = *outline; + ras.target = *target_map; + ras.num_cells = 0; + ras.invalid = 1; + + ras.render_span = (FT_Raster_Span_Func)grays_render_span; + ras.render_span_data = &ras; + + if ( params->flags & ft_raster_flag_direct ) + { + ras.render_span = (FT_Raster_Span_Func)params->gray_spans; + ras.render_span_data = params->user; + } + + return grays_convert_glyph( (PRaster)raster, outline ); + } + + + /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/ + /**** a static object. *****/ + +#ifdef _STANDALONE_ + + static + int grays_raster_new( void* memory, + FT_Raster* araster ) + { + static TRaster the_raster; + + FT_UNUSED( memory ); + + + *araster = (FT_Raster)&the_raster; + memset( &the_raster, 0, sizeof ( the_raster ) ); + + return 0; + } + + + static + void grays_raster_done( FT_Raster raster ) + { + /* nothing */ + FT_UNUSED( raster ); + } + +#else /* _STANDALONE_ */ + + static + int grays_raster_new( FT_Memory memory, + FT_Raster* araster ) + { + FT_Error error; + PRaster raster; + + + *araster = 0; + if ( !ALLOC( raster, sizeof ( TRaster ) ) ) + { + raster->memory = memory; + *araster = (FT_Raster)raster; + } + + return error; + } + + + static + void grays_raster_done( FT_Raster raster ) + { + FT_Memory memory = (FT_Memory)((PRaster)raster)->memory; + + + FREE( raster ); + } + +#endif /* _STANDALONE_ */ + + + static + void grays_raster_reset( FT_Raster raster, + const char* pool_base, + long pool_size ) + { + PRaster rast = (PRaster)raster; + + + if ( raster && pool_base && pool_size >= 4096 ) + init_cells( rast, (char*)pool_base, pool_size ); + + rast->band_size = ( pool_size / sizeof ( TCell ) ) / 8; + } + + + FT_Raster_Funcs ft_grays_raster = + { + ft_glyph_format_outline, + + (FT_Raster_New_Func) grays_raster_new, + (FT_Raster_Reset_Func) grays_raster_reset, + (FT_Raster_Set_Mode_Func)0, + (FT_Raster_Render_Func) grays_raster_render, + (FT_Raster_Done_Func) grays_raster_done + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/smooth/ftgrays.h b/subsys/win32k/freetype/src/smooth/ftgrays.h new file mode 100644 index 0000000..2423a0e --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/ftgrays.h @@ -0,0 +1,52 @@ +/***************************************************************************/ +/* */ +/* ftgrays.h */ +/* */ +/* FreeType smooth renderer declaration */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#ifndef FTGRAYS_H +#define FTGRAYS_H + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef _STANDALONE_ +#include "ftimage.h" +#else +#include +#endif + + /*************************************************************************/ + /* */ + /* To make ftgrays.h independent from configuration files we check */ + /* whether FT_EXPORT_DEF has been defined already. */ + /* */ + /* On some systems and compilers (Win32 mostly), an extra keyword is */ + /* necessary to compile the library as a DLL. */ + /* */ +#ifndef FT_EXPORT_VAR +#define FT_EXPORT_VAR( x ) extern x +#endif + + FT_EXPORT_VAR( FT_Raster_Funcs ) ft_grays_raster; + +#ifdef __cplusplus + } +#endif + +#endif /* FTGRAYS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/smooth/ftsmooth.c b/subsys/win32k/freetype/src/smooth/ftsmooth.c new file mode 100644 index 0000000..6e0e46a --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/ftsmooth.c @@ -0,0 +1,220 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.c */ +/* */ +/* Anti-aliasing renderer interface (body). */ +/* */ +/* Copyright 2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ftsmooth.h" +#include "ftgrays.h" + +#else + +#include +#include + +#endif + + + /* initialize renderer -- init its raster */ + static + FT_Error ft_smooth_init( FT_Renderer render ) + { + FT_Library library = FT_MODULE_LIBRARY( render ); + + + render->clazz->raster_class->raster_reset( render->raster, + library->raster_pool, + library->raster_pool_size ); + + return 0; + } + + + /* sets render-specific mode */ + static + FT_Error ft_smooth_set_mode( FT_Renderer render, + FT_ULong mode_tag, + FT_Pointer data ) + { + /* we simply pass it to the raster */ + return render->clazz->raster_class->raster_set_mode( render->raster, + mode_tag, + data ); + } + + /* transform a given glyph image */ + static + FT_Error ft_smooth_transform( FT_Renderer render, + FT_GlyphSlot slot, + FT_Matrix* matrix, + FT_Vector* delta ) + { + FT_Error error = FT_Err_Ok; + + + if ( slot->format != render->glyph_format ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + if ( matrix ) + FT_Outline_Transform( &slot->outline, matrix ); + + if ( delta ) + FT_Outline_Translate( &slot->outline, delta->x, delta->y ); + + Exit: + return error; + } + + + /* return the glyph's control box */ + static + void ft_smooth_get_cbox( FT_Renderer render, + FT_GlyphSlot slot, + FT_BBox* cbox ) + { + MEM_Set( cbox, 0, sizeof ( *cbox ) ); + + if ( slot->format == render->glyph_format ) + FT_Outline_Get_CBox( &slot->outline, cbox ); + } + + + /* convert a slot's glyph image into a bitmap */ + static + FT_Error ft_smooth_render( FT_Renderer render, + FT_GlyphSlot slot, + FT_UInt mode, + FT_Vector* origin ) + { + FT_Error error; + FT_Outline* outline; + FT_BBox cbox; + FT_UInt width, height, pitch; + FT_Bitmap* bitmap; + FT_Memory memory; + + FT_Raster_Params params; + + + /* check glyph image format */ + if ( slot->format != render->glyph_format ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + /* check mode */ + if ( mode != ft_render_mode_normal ) + return FT_Err_Cannot_Render_Glyph; + + outline = &slot->outline; + + /* translate the outline to the new origin if needed */ + if ( origin ) + FT_Outline_Translate( outline, origin->x, origin->y ); + + /* compute the control box, and grid fit it */ + FT_Outline_Get_CBox( outline, &cbox ); + + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax + 63 ) & -64; + cbox.yMax = ( cbox.yMax + 63 ) & -64; + + width = ( cbox.xMax - cbox.xMin ) >> 6; + height = ( cbox.yMax - cbox.yMin ) >> 6; + bitmap = &slot->bitmap; + memory = render->root.memory; + + /* release old bitmap buffer */ + if ( slot->flags & ft_glyph_own_bitmap ) + { + FREE( bitmap->buffer ); + slot->flags &= ~ft_glyph_own_bitmap; + } + + /* allocate new one, depends on pixel format */ + pitch = width; + bitmap->pixel_mode = ft_pixel_mode_grays; + bitmap->num_grays = 256; + bitmap->width = width; + bitmap->rows = height; + bitmap->pitch = pitch; + + if ( ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) ) + goto Exit; + + slot->flags |= ft_glyph_own_bitmap; + + /* translate outline to render it into the bitmap */ + FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin ); + + /* set up parameters */ + params.target = bitmap; + params.source = outline; + params.flags = ft_raster_flag_aa; + + /* render outline into the bitmap */ + error = render->raster_render( render->raster, ¶ms ); + if ( error ) + goto Exit; + + slot->format = ft_glyph_format_bitmap; + slot->bitmap_left = cbox.xMin >> 6; + slot->bitmap_top = cbox.yMax >> 6; + + Exit: + return error; + } + + + const FT_Renderer_Class ft_smooth_renderer_class = + { + { + ft_module_renderer, + sizeof( FT_RendererRec ), + + "smooth", + 0x10000L, + 0x20000L, + + 0, /* module specific interface */ + + (FT_Module_Constructor)ft_smooth_init, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + ft_glyph_format_outline, + + (FTRenderer_render) ft_smooth_render, + (FTRenderer_transform)ft_smooth_transform, + (FTRenderer_getCBox) ft_smooth_get_cbox, + (FTRenderer_setMode) ft_smooth_set_mode, + + (FT_Raster_Funcs*) &ft_grays_raster + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/smooth/ftsmooth.h b/subsys/win32k/freetype/src/smooth/ftsmooth.h new file mode 100644 index 0000000..4b8a533 --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/ftsmooth.h @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* ftsmooth.h */ +/* */ +/* Anti-aliasing renderer interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef FTSMOOTH_H +#define FTSMOOTH_H + +#include + +#ifndef FT_CONFIG_OPTION_NO_STD_RASTER + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_std_renderer_class; +#endif + +#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER + FT_EXPORT_VAR( const FT_Renderer_Class ) ft_smooth_renderer_class; +#endif + +#endif /* FTSMOOTH_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/smooth/module.mk b/subsys/win32k/freetype/src/smooth/module.mk new file mode 100644 index 0000000..b93bc4d --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_smooth_renderer + +add_smooth_renderer: + $(OPEN_DRIVER)ft_smooth_renderer_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)anti-aliased bitmap renderer$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/smooth/rules.mk b/subsys/win32k/freetype/src/smooth/rules.mk new file mode 100644 index 0000000..a81d60a --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/rules.mk @@ -0,0 +1,69 @@ +# +# FreeType 2 renderer module build rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# smooth driver directory +# +SMOOTH_DIR := $(SRC_)smooth +SMOOTH_DIR_ := $(SMOOTH_DIR)$(SEP) + +# compilation flags for the driver +# +SMOOTH_COMPILE := $(FT_COMPILE) + + +# smooth driver sources (i.e., C files) +# +SMOOTH_DRV_SRC := $(SMOOTH_DIR_)ftgrays.c \ + $(SMOOTH_DIR_)ftsmooth.c + + +# smooth driver headers +# +SMOOTH_DRV_H := $(SMOOTH_DRV_SRC:%c=%h) + + +# smooth driver object(s) +# +# SMOOTH_DRV_OBJ_M is used during `multi' builds. +# SMOOTH_DRV_OBJ_S is used during `single' builds. +# +SMOOTH_DRV_OBJ_M := $(SMOOTH_DRV_SRC:$(SMOOTH_DIR_)%.c=$(OBJ_)%.$O) +SMOOTH_DRV_OBJ_S := $(OBJ_)smooth.$O + +# smooth driver source file for single build +# +SMOOTH_DRV_SRC_S := $(SMOOTH_DIR_)smooth.c + + +# smooth driver - single object +# +$(SMOOTH_DRV_OBJ_S): $(SMOOTH_DRV_SRC_S) $(SMOOTH_DRV_SRC) \ + $(FREETYPE_H) $(SMOOTH_DRV_H) + $(SMOOTH_COMPILE) $T$@ $(SMOOTH_DRV_SRC_S) + + +# smooth driver - multiple objects +# +$(OBJ_)%.$O: $(SMOOTH_DIR_)%.c $(FREETYPE_H) $(SMOOTH_DRV_H) + $(SMOOTH_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(SMOOTH_DRV_OBJ_S) +DRV_OBJS_M += $(SMOOTH_DRV_OBJ_M) + + +# EOF diff --git a/subsys/win32k/freetype/src/smooth/smooth.c b/subsys/win32k/freetype/src/smooth/smooth.c new file mode 100644 index 0000000..f8d4a59 --- /dev/null +++ b/subsys/win32k/freetype/src/smooth/smooth.c @@ -0,0 +1,35 @@ +/***************************************************************************/ +/* */ +/* smooth.c */ +/* */ +/* FreeType anti-aliasing rasterer module component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#ifdef FT_FLAT_COMPILE + +#include "ftgrays.c" +#include "ftsmooth.c" + +#else + +#include +#include + +#endif + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/.cvsignore b/subsys/win32k/freetype/src/truetype/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/truetype/module.mk b/subsys/win32k/freetype/src/truetype/module.mk new file mode 100644 index 0000000..79072bb --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_truetype_driver + +add_truetype_driver: + $(OPEN_DRIVER)tt_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)truetype $(ECHO_DRIVER_DESC)Windows/Mac font files with extension *.ttf or *.ttc$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/truetype/rules.mk b/subsys/win32k/freetype/src/truetype/rules.mk new file mode 100644 index 0000000..9289378 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/rules.mk @@ -0,0 +1,70 @@ +# +# FreeType 2 TrueType driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# TrueType driver directory +# +TT_DIR := $(SRC_)truetype +TT_DIR_ := $(TT_DIR)$(SEP) + + +# compilation flags for the driver +# +TT_COMPILE := $(FT_COMPILE) + + +# TrueType driver sources (i.e., C files) +# +TT_DRV_SRC := $(TT_DIR_)ttobjs.c \ + $(TT_DIR_)ttpload.c \ + $(TT_DIR_)ttgload.c \ + $(TT_DIR_)ttinterp.c \ + $(TT_DIR_)ttdriver.c + +# TrueType driver headers +# +TT_DRV_H := $(TT_DRV_SRC:%.c=%.h) + + +# TrueType driver object(s) +# +# TT_DRV_OBJ_M is used during `multi' builds +# TT_DRV_OBJ_S is used during `single' builds +# +TT_DRV_OBJ_M := $(TT_DRV_SRC:$(TT_DIR_)%.c=$(OBJ_)%.$O) +TT_DRV_OBJ_S := $(OBJ_)truetype.$O + +# TrueType driver source file for single build +# +TT_DRV_SRC_S := $(TT_DIR_)truetype.c + + +# TrueType driver - single object +# +$(TT_DRV_OBJ_S): $(TT_DRV_SRC_S) $(TT_DRV_SRC) $(FREETYPE_H) $(TT_DRV_H) + $(TT_COMPILE) $T$@ $(TT_DRV_SRC_S) + + +# driver - multiple objects +# +$(OBJ_)%.$O: $(TT_DIR_)%.c $(FREETYPE_H) $(TT_DRV_H) + $(TT_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(TT_DRV_OBJ_S) +DRV_OBJS_M += $(TT_DRV_OBJ_M) + +# EOF diff --git a/subsys/win32k/freetype/src/truetype/truetype.c b/subsys/win32k/freetype/src/truetype/truetype.c new file mode 100644 index 0000000..a7e7e8d --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/truetype.c @@ -0,0 +1,47 @@ +/***************************************************************************/ +/* */ +/* truetype.c */ +/* */ +/* FreeType TrueType driver component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#ifdef FT_FLAT_COMPILE + +#include "ttdriver.c" /* driver interface */ +#include "ttpload.c" /* tables loader */ +#include "ttgload.c" /* glyph loader */ +#include "ttobjs.c" /* object manager */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.c" /* bytecode interpreter */ +#endif + +#else /* FT_FLAT_COMPILE */ + +#include /* driver interface */ +#include /* tables loader */ +#include /* glyph loader */ +#include /* object manager */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include /* bytecode interpreter */ +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttdriver.c b/subsys/win32k/freetype/src/truetype/ttdriver.c new file mode 100644 index 0000000..558d63e --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttdriver.c @@ -0,0 +1,511 @@ +/***************************************************************************/ +/* */ +/* ttdriver.c */ +/* */ +/* TrueType font driver implementation (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttdriver.h" +#include "ttgload.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttdriver + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** F A C E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#undef PAIR_TAG +#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ + (FT_ULong)right ) + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings, are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static + FT_Error Get_Kerning( TT_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + TT_Kern_0_Pair* pair; + + + if ( !face ) + return TT_Err_Invalid_Face_Handle; + + kerning->x = 0; + kerning->y = 0; + + if ( face->kern_pairs ) + { + /* there are some kerning pairs in this font file! */ + FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); + FT_Long left, right; + + + left = 0; + right = face->num_kern_pairs - 1; + + while ( left <= right ) + { + FT_Int middle = left + ( ( right - left ) >> 1 ); + FT_ULong cur_pair; + + + pair = face->kern_pairs + middle; + cur_pair = PAIR_TAG( pair->left, pair->right ); + + if ( cur_pair == search_tag ) + goto Found; + + if ( cur_pair < search_tag ) + left = middle + 1; + else + right = middle - 1; + } + } + + Exit: + return TT_Err_Ok; + + Found: + kerning->x = pair->value; + goto Exit; + } + + +#undef PAIR_TAG + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** S I Z E S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* char_width :: The character width expressed in 26.6 */ + /* fractional points. */ + /* */ + /* char_height :: The character height expressed in 26.6 */ + /* fractional points. */ + /* */ + /* horz_resolution :: The horizontal resolution of the output device. */ + /* */ + /* vert_resolution :: The vertical resolution of the output device. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Char_Sizes( TT_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_Size_Metrics* metrics = &size->root.metrics; + TT_Face face = (TT_Face)size->root.face; + FT_Long dim_x, dim_y; + + + /* This bit flag, when set, indicates that the pixel size must be */ + /* truncated to an integer. Nearly all TrueType fonts have this */ + /* bit set, as hinting won't work really well otherwise. */ + /* */ + /* However, for those rare fonts who do not set it, we override */ + /* the default computations performed by the base layer. I */ + /* really don't know whether this is useful, but hey, that's the */ + /* spec :-) */ + /* */ + if ( ( face->header.Flags & 8 ) == 0 ) + { + /* Compute pixel sizes in 26.6 units */ + dim_x = ( char_width * horz_resolution ) / 72; + dim_y = ( char_height * vert_resolution ) / 72; + + metrics->x_scale = FT_DivFix( dim_x, face->root.units_per_EM ); + metrics->y_scale = FT_DivFix( dim_y, face->root.units_per_EM ); + + metrics->x_ppem = (FT_UShort)( dim_x >> 6 ); + metrics->y_ppem = (FT_UShort)( dim_y >> 6 ); + } + + size->ttmetrics.valid = FALSE; + + return TT_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Pixel_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* pixel_width :: The character width expressed in integer pixels. */ + /* */ + /* pixel_height :: The character height expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Pixel_Sizes( TT_Size size, + FT_UInt pixel_width, + FT_UInt pixel_height ) + { + FT_UNUSED( pixel_width ); + FT_UNUSED( pixel_height ); + + /* many things have been pre-computed by the base layer */ + + size->ttmetrics.valid = FALSE; + + return TT_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Load_Glyph */ + /* */ + /* */ + /* A driver method used to load a glyph within a given glyph slot. */ + /* */ + /* */ + /* slot :: A handle to the target slot object where the glyph */ + /* will be loaded. */ + /* */ + /* size :: A handle to the source face size at which the glyph */ + /* must be scaled, loaded, etc. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FTLOAD_??? constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Load_Glyph( TT_GlyphSlot slot, + TT_Size size, + FT_UShort glyph_index, + FT_UInt load_flags ) + { + FT_Error error; + + + if ( !slot ) + return TT_Err_Invalid_Glyph_Handle; + + /* check whether we want a scaled outline or bitmap */ + if ( !size ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + if ( load_flags & FT_LOAD_NO_SCALE ) + size = NULL; + + /* reset the size object if necessary */ + if ( size ) + { + /* these two object must have the same parent */ + if ( size->root.face != slot->face ) + return TT_Err_Invalid_Face_Handle; + + if ( !size->ttmetrics.valid ) + { + if ( FT_SET_ERROR( TT_Reset_Size( size ) ) ) + return error; + } + } + + /* now load the glyph outline if necessary */ + error = TT_Load_Glyph( size, slot, glyph_index, load_flags ); + + /* force drop-out mode to 2 - irrelevant now */ + /* slot->outline.dropout_mode = 2; */ + + return error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** C H A R A C T E R M A P P I N G S ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt Get_Char_Index( TT_CharMap charmap, + FT_Long charcode ) + { + FT_Error error; + TT_Face face; + TT_CMapTable* cmap; + + + cmap = &charmap->cmap; + face = (TT_Face)charmap->root.face; + + /* Load table if needed */ + if ( !cmap->loaded ) + { + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + error = sfnt->load_charmap( face, cmap, face->root.stream ); + if ( error ) + return 0; + + cmap->loaded = TRUE; + } + + if ( cmap->get_index ) + return cmap->get_index( cmap, charcode ); + else + return 0; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** ****/ + /**** D R I V E R I N T E R F A C E ****/ + /**** ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Module_Interface tt_get_interface( TT_Driver driver, + const char* interface ) + { + FT_Module sfntd = FT_Get_Module( driver->root.root.library, + "sfnt" ); + SFNT_Interface* sfnt; + + + /* only return the default interface from the SFNT module */ + if ( sfntd ) + { + sfnt = (SFNT_Interface*)( sfntd->clazz->module_interface ); + if ( sfnt ) + return sfnt->get_interface( FT_MODULE( driver ), interface ); + } + + return 0; + } + + + /* The FT_DriverInterface structure is defined in ftdriver.h. */ + + const FT_Driver_Class tt_driver_class = + { + { + ft_module_font_driver | + ft_module_driver_scalable | +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + ft_module_driver_has_hinter, +#else + 0, +#endif + + sizeof ( TT_DriverRec ), + + "truetype", /* driver name */ + 0x10000L, /* driver version == 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + (void*)0, /* driver specific interface */ + + (FT_Module_Constructor)TT_Init_Driver, + (FT_Module_Destructor) TT_Done_Driver, + (FT_Module_Requester) tt_get_interface, + }, + + sizeof ( TT_FaceRec ), + sizeof ( TT_SizeRec ), + sizeof ( FT_GlyphSlotRec ), + + + (FTDriver_initFace) TT_Init_Face, + (FTDriver_doneFace) TT_Done_Face, + (FTDriver_initSize) TT_Init_Size, + (FTDriver_doneSize) TT_Done_Size, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) Set_Char_Sizes, + (FTDriver_setPixelSizes)Set_Pixel_Sizes, + (FTDriver_loadGlyph) Load_Glyph, + (FTDriver_getCharIndex) Get_Char_Index, + + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + + /*************************************************************************/ + /* */ + /* */ + /* getDriverInterface */ + /* */ + /* */ + /* This function is used when compiling the TrueType driver as a */ + /* shared library (`.DLL' or `.so'). It will be used by the */ + /* high-level library of FreeType to retrieve the address of the */ + /* driver's generic interface. */ + /* */ + /* It shouldn't be implemented in a static build, as each driver must */ + /* have the same function as an exported entry point. */ + /* */ + /* */ + /* The address of the TrueType's driver generic interface. The */ + /* format-specific interface can then be retrieved through the method */ + /* interface->get_format_interface. */ + /* */ + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &tt_driver_class; + } + + +#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttdriver.h b/subsys/win32k/freetype/src/truetype/ttdriver.h new file mode 100644 index 0000000..9867fbc --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttdriver.h @@ -0,0 +1,31 @@ +/***************************************************************************/ +/* */ +/* ttdriver.h */ +/* */ +/* High-level TrueType driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTDRIVER_H +#define TTDRIVER_H + +#include + + + FT_EXPORT_VAR( const FT_Driver_Class ) tt_driver_class; + + +#endif /* TTDRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttgload.c b/subsys/win32k/freetype/src/truetype/ttgload.c new file mode 100644 index 0000000..62cb22f --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttgload.c @@ -0,0 +1,1477 @@ +/***************************************************************************/ +/* */ +/* ttgload.c */ +/* */ +/* TrueType Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttgload.h" + +#else + +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttgload + + + /*************************************************************************/ + /* */ + /* Composite font flags. */ + /* */ +#define ARGS_ARE_WORDS 0x001 +#define ARGS_ARE_XY_VALUES 0x002 +#define ROUND_XY_TO_GRID 0x004 +#define WE_HAVE_A_SCALE 0x008 +/* reserved 0x010 */ +#define MORE_COMPONENTS 0x020 +#define WE_HAVE_AN_XY_SCALE 0x040 +#define WE_HAVE_A_2X2 0x080 +#define WE_HAVE_INSTR 0x100 +#define USE_MY_METRICS 0x200 + + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Get_Metrics */ + /* */ + /* */ + /* Returns the horizontal or vertical metrics in font units for a */ + /* given glyph. The metrics are the left side bearing (resp. top */ + /* side bearing) and advance width (resp. advance height). */ + /* */ + /* */ + /* header :: A pointer to either the horizontal or vertical metrics */ + /* structure. */ + /* */ + /* index :: The glyph index. */ + /* */ + /* */ + /* bearing :: The bearing, either left side or top side. */ + /* */ + /* advance :: The advance width resp. advance height. */ + /* */ + /* */ + /* This function will much probably move to another component in the */ + /* near future, but I haven't decided which yet. */ + /* */ + LOCAL_FUNC + void TT_Get_Metrics( TT_HoriHeader* header, + FT_UInt index, + FT_Short* bearing, + FT_UShort* advance ) + { + TT_LongMetrics* longs_m; + FT_UShort k = header->number_Of_HMetrics; + + + if ( index < k ) + { + longs_m = (TT_LongMetrics*)header->long_metrics + index; + *bearing = longs_m->bearing; + *advance = longs_m->advance; + } + else + { + *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k]; + *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance; + } + } + + + /*************************************************************************/ + /* */ + /* Returns the horizontal metrics in font units for a given glyph. If */ + /* `check' is true, take care of monospaced fonts by returning the */ + /* advance width maximum. */ + /* */ + static + void Get_HMetrics( TT_Face face, + FT_UInt index, + FT_Bool check, + FT_Short* lsb, + FT_UShort* aw ) + { + TT_Get_Metrics( &face->horizontal, index, lsb, aw ); + + if ( check && face->postscript.isFixedPitch ) + *aw = face->horizontal.advance_Width_Max; + } + + + /*************************************************************************/ + /* */ + /* Returns the advance width table for a given pixel size if it is */ + /* found in the font's `hdmx' table (if any). */ + /* */ + static + FT_Byte* Get_Advance_Widths( TT_Face face, + FT_UShort ppem ) + { + FT_UShort n; + + for ( n = 0; n < face->hdmx.num_records; n++ ) + if ( face->hdmx.records[n].ppem == ppem ) + return face->hdmx.records[n].widths; + + return NULL; + } + + +#define cur_to_org( n, zone ) \ + MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) ) + +#define org_to_cur( n, zone ) \ + MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) ) + + + /*************************************************************************/ + /* */ + /* Translates an array of coordinates. */ + /* */ + static + void translate_array( FT_UInt n, + FT_Vector* coords, + FT_Pos delta_x, + FT_Pos delta_y ) + { + FT_UInt k; + + + if ( delta_x ) + for ( k = 0; k < n; k++ ) + coords[k].x += delta_x; + + if ( delta_y ) + for ( k = 0; k < n; k++ ) + coords[k].y += delta_y; + } + + + static + void tt_prepare_zone( TT_GlyphZone* zone, + FT_GlyphLoad* load, + FT_UInt start_point, + FT_UInt start_contour ) + { + zone->n_points = load->outline.n_points - start_point; + zone->n_contours = load->outline.n_contours - start_contour; + zone->org = load->extra_points + start_point; + zone->cur = load->outline.points + start_point; + zone->tags = (FT_Byte*)load->outline.tags + start_point; + zone->contours = (FT_UShort*)load->outline.contours + start_contour; + } + + +#undef IS_HINTED +#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) + + + /*************************************************************************/ + /* */ + /* The following functions are used by default with TrueType fonts. */ + /* However, they can be replaced by alternatives if we need to support */ + /* TrueType-compressed formats (like MicroType) in the future. */ + /* */ + /*************************************************************************/ + + static + FT_Error TT_Access_Glyph_Frame( TT_Loader* loader, + FT_UInt glyph_index, + FT_ULong offset, + FT_UInt byte_count ) + { + FT_Error error; + FT_Stream stream = loader->stream; + + + /* the following line sets the `error' variable through macros! */ + (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) ); + + FT_TRACE5(( "Glyph %ld\n", glyph_index )); + return error; + } + + + static + void TT_Forget_Glyph_Frame( TT_Loader* loader ) + { + FT_Stream stream = loader->stream; + + + FORGET_Frame(); + } + + + static + FT_Error TT_Load_Glyph_Header( TT_Loader* loader ) + { + FT_Stream stream = loader->stream; + + + loader->n_contours = GET_Short(); + + loader->bbox.xMin = GET_Short(); + loader->bbox.yMin = GET_Short(); + loader->bbox.xMax = GET_Short(); + loader->bbox.yMax = GET_Short(); + + FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); + FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, + loader->bbox.xMax )); + FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, + loader->bbox.yMax )); + + return FT_Err_Ok; + } + + + static + FT_Error TT_Load_Simple_Glyph( TT_Loader* load ) + { + FT_Error error; + FT_Stream stream = load->stream; + FT_GlyphLoader* gloader = load->gloader; + FT_Int n_contours = load->n_contours; + FT_Outline* outline; + TT_Face face = (TT_Face)load->face; + TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph; + FT_UShort n_ins; + FT_Int n, n_points; + + + /* reading the contours endpoints & number of points */ + { + short* cur = gloader->current.outline.contours; + short* limit = cur + n_contours; + + + for ( ; cur < limit; cur++ ) + cur[0] = GET_UShort(); + + n_points = 0; + if ( n_contours > 0 ) + n_points = cur[-1] + 1; + + error = FT_GlyphLoader_Check_Points( gloader, n_points + 2, 0 ); + if ( error ) + goto Fail; + + outline = &gloader->current.outline; + } + + /* reading the bytecode instructions */ + slot->control_len = 0; + slot->control_data = 0; + + n_ins = GET_UShort(); + + FT_TRACE5(( " Instructions size: %d\n", n_ins )); + + if ( n_ins > face->max_profile.maxSizeOfInstructions ) + { + FT_TRACE0(( "ERROR: Too many instructions!\n" )); + error = TT_Err_Too_Many_Ins; + goto Fail; + } + + if ( stream->cursor + n_ins > stream->limit ) + { + FT_TRACE0(( "ERROR: Instruction count mismatch!\n" )); + error = TT_Err_Too_Many_Ins; + goto Fail; + } + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( ( load->load_flags & + ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 && + load->instructions ) + { + slot->control_len = n_ins; + slot->control_data = load->instructions; + + MEM_Copy( load->instructions, stream->cursor, n_ins ); + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + stream->cursor += n_ins; + + /* reading the point tags */ + + { + FT_Byte* flag = (FT_Byte*)outline->tags; + FT_Byte* limit = flag + n_points; + FT_Byte c, count; + + + for ( ; flag < limit; flag++ ) + { + *flag = c = GET_Byte(); + if ( c & 8 ) + { + for ( count = GET_Byte(); count > 0; count-- ) + *++flag = c; + } + } + } + + /* reading the X coordinates */ + + { + FT_Vector* vec = outline->points; + FT_Vector* limit = vec + n_points; + FT_Byte* flag = (FT_Byte*)outline->tags; + FT_Pos x = 0; + + + for ( ; vec < limit; vec++, flag++ ) + { + FT_Pos y = 0; + + + if ( *flag & 2 ) + { + y = GET_Byte(); + if ( ( *flag & 16 ) == 0 ) + y = -y; + } + else if ( ( *flag & 16 ) == 0 ) + y = GET_Short(); + + x += y; + vec->x = x; + } + } + + /* reading the Y coordinates */ + + { + FT_Vector* vec = gloader->current.outline.points; + FT_Vector* limit = vec + n_points; + FT_Byte* flag = (FT_Byte*)outline->tags; + FT_Pos x = 0; + + + for ( ; vec < limit; vec++, flag++ ) + { + FT_Pos y = 0; + + + if ( *flag & 4 ) + { + y = GET_Byte(); + if ( ( *flag & 32 ) == 0 ) + y = -y; + } + else if ( ( *flag & 32 ) == 0 ) + y = GET_Short(); + + x += y; + vec->y = x; + } + } + + /* clear the touch tags */ + for ( n = 0; n < n_points; n++ ) + outline->tags[n] &= FT_Curve_Tag_On; + + outline->n_points = n_points; + outline->n_contours = n_contours; + + Fail: + return error; + } + + + static + FT_Error TT_Load_Composite_Glyph( TT_Loader* loader ) + { + FT_Error error; + FT_Stream stream = loader->stream; + FT_GlyphLoader* gloader = loader->gloader; + FT_SubGlyph* subglyph; + FT_UInt num_subglyphs; + + + num_subglyphs = 0; + + do + { + FT_Fixed xx, xy, yy, yx; + + + /* check that we can load a new subglyph */ + error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs + 1 ); + if ( error ) + goto Fail; + + subglyph = gloader->current.subglyphs + num_subglyphs; + + subglyph->arg1 = subglyph->arg2 = 0; + + subglyph->flags = GET_UShort(); + subglyph->index = GET_UShort(); + + /* read arguments */ + if ( subglyph->flags & ARGS_ARE_WORDS ) + { + subglyph->arg1 = GET_Short(); + subglyph->arg2 = GET_Short(); + } + else + { + subglyph->arg1 = GET_Char(); + subglyph->arg2 = GET_Char(); + } + + /* read transform */ + xx = yy = 0x10000L; + xy = yx = 0; + + if ( subglyph->flags & WE_HAVE_A_SCALE ) + { + xx = (FT_Fixed)GET_Short() << 2; + yy = xx; + } + else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) + { + xx = (FT_Fixed)GET_Short() << 2; + yy = (FT_Fixed)GET_Short() << 2; + } + else if ( subglyph->flags & WE_HAVE_A_2X2 ) + { + xx = (FT_Fixed)GET_Short() << 2; + xy = (FT_Fixed)GET_Short() << 2; + yx = (FT_Fixed)GET_Short() << 2; + yy = (FT_Fixed)GET_Short() << 2; + } + + subglyph->transform.xx = xx; + subglyph->transform.xy = xy; + subglyph->transform.yx = yx; + subglyph->transform.yy = yy; + + num_subglyphs++; + + } while ( subglyph->flags & MORE_COMPONENTS ); + + gloader->current.num_subglyphs = num_subglyphs; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + { + /* we must undo the ACCESS_Frame in order to point to the */ + /* composite instructions, if we find some. */ + /* we will process them later... */ + /* */ + loader->ins_pos = FILE_Pos() + stream->cursor - stream->limit; + } +#endif + + Fail: + return error; + } + + + LOCAL_FUNC + void TT_Init_Glyph_Loading( TT_Face face ) + { + face->access_glyph_frame = TT_Access_Glyph_Frame; + face->read_glyph_header = TT_Load_Glyph_Header; + face->read_simple_glyph = TT_Load_Simple_Glyph; + face->read_composite_glyph = TT_Load_Composite_Glyph; + face->forget_glyph_frame = TT_Forget_Glyph_Frame; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Process_Simple_Glyph */ + /* */ + /* */ + /* Once a simple glyph has been loaded, it needs to be processed. */ + /* Usually, this means scaling and hinting through bytecode */ + /* interpretation. */ + /* */ + static + FT_Error TT_Process_Simple_Glyph( TT_Loader* load, + FT_Bool debug ) + { + FT_GlyphLoader* gloader = load->gloader; + FT_Outline* outline = &gloader->current.outline; + FT_UInt n_points = outline->n_points; + FT_UInt n_ins; + TT_GlyphZone* zone = &load->zone; + FT_Error error = FT_Err_Ok; + + + n_ins = load->glyph->control_len; + + /* add shadow points */ + + /* Now add the two shadow points at n and n + 1. */ + /* We need the left side bearing and advance width. */ + + { + FT_Vector* pp1; + FT_Vector* pp2; + + + /* pp1 = xMin - lsb */ + pp1 = outline->points + n_points; + pp1->x = load->bbox.xMin - load->left_bearing; + pp1->y = 0; + + /* pp2 = pp1 + aw */ + pp2 = pp1 + 1; + pp2->x = pp1->x + load->advance; + pp2->y = 0; + + outline->tags[n_points ] = 0; + outline->tags[n_points + 1] = 0; + } + + /* Note that we return two more points that are not */ + /* part of the glyph outline. */ + + n_points += 2; + + /* set up zone for hinting */ + tt_prepare_zone( zone, &gloader->current, 0, 0 ); + + /* eventually scale the glyph */ + if ( !( load->load_flags & FT_LOAD_NO_SCALE ) ) + { + FT_Vector* vec = zone->cur; + FT_Vector* limit = vec + n_points; + FT_Fixed x_scale = load->size->metrics.x_scale; + FT_Fixed y_scale = load->size->metrics.y_scale; + + + /* first scale the glyph points */ + for ( ; vec < limit; vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + } + + cur_to_org( n_points, zone ); + + /* eventually hint the glyph */ + if ( IS_HINTED( load->load_flags ) ) + { + FT_Pos x = zone->org[n_points-2].x; + + + x = ( ( x + 32 ) & -64 ) - x; + translate_array( n_points, zone->org, x, 0 ); + + org_to_cur( n_points, zone ); + + zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* now consider hinting */ + if ( n_ins > 0 ) + { + error = TT_Set_CodeRange( load->exec, tt_coderange_glyph, + load->exec->glyphIns, n_ins ); + if ( error ) + goto Exit; + + load->exec->is_composite = FALSE; + load->exec->pedantic_hinting = (FT_Bool)( load->load_flags & + FT_LOAD_PEDANTIC ); + load->exec->pts = *zone; + load->exec->pts.n_points += 2; + + error = TT_Run_Context( load->exec, debug ); + if ( error && load->exec->pedantic_hinting ) + goto Exit; + + error = FT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */ + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } + + /* save glyph phantom points */ + if ( !load->preserve_pps ) + { + load->pp1 = zone->cur[n_points - 2]; + load->pp2 = zone->cur[n_points - 1]; + } + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + Exit: +#endif + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* load_truetype_glyph */ + /* */ + /* */ + /* Loads a given truetype glyph. Handles composites and uses a */ + /* TT_Loader object. */ + /* */ + static + FT_Error load_truetype_glyph( TT_Loader* loader, + FT_UInt glyph_index ) + { + FT_Stream stream = loader->stream; + FT_Error error; + TT_Face face = (TT_Face)loader->face; + FT_ULong offset; + FT_Int contours_count; + FT_UInt index, num_points, num_contours, count; + FT_Fixed x_scale, y_scale; + FT_ULong ins_offset; + FT_GlyphLoader* gloader = loader->gloader; + FT_Bool opened_frame = 0; + + + /* check glyph index */ + index = glyph_index; + if ( index >= (FT_UInt)face->root.num_glyphs ) + { + error = TT_Err_Invalid_Glyph_Index; + goto Exit; + } + + loader->glyph_index = glyph_index; + num_contours = 0; + num_points = 0; + ins_offset = 0; + + x_scale = 0x10000L; + y_scale = 0x10000L; + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + x_scale = loader->size->metrics.x_scale; + y_scale = loader->size->metrics.y_scale; + } + + /* get horizontal metrics */ + { + FT_Short left_bearing; + FT_UShort advance_width; + + + Get_HMetrics( face, index, + (FT_Bool)!(loader->load_flags & + FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH), + &left_bearing, + &advance_width ); + + loader->left_bearing = left_bearing; + loader->advance = advance_width; + } + + offset = face->glyph_locations[index]; + count = 0; + + if ( index < (FT_UInt)face->num_locations - 1 ) + count = face->glyph_locations[index + 1] - offset; + + if ( count == 0 ) + { + /* as described by Frederic Loyer, these are spaces, and */ + /* not the unknown glyph. */ + loader->bbox.xMin = 0; + loader->bbox.xMax = 0; + loader->bbox.yMin = 0; + loader->bbox.yMax = 0; + + loader->pp1.x = 0; + loader->pp2.x = loader->advance; + + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( loader->exec ) + loader->exec->glyphSize = 0; + +#endif + + error = FT_Err_Ok; + goto Exit; + } + + offset = loader->glyf_offset + offset; + + /* access glyph frame */ + error = face->access_glyph_frame( loader, glyph_index, offset, count ); + if ( error ) + goto Exit; + + opened_frame = 1; + + /* read first glyph header */ + error = face->read_glyph_header( loader ); + if ( error ) + goto Fail; + + contours_count = loader->n_contours; + + count -= 10; + + loader->pp1.x = loader->bbox.xMin - loader->left_bearing; + loader->pp1.y = 0; + loader->pp2.x = loader->pp1.x + loader->advance; + loader->pp2.y = 0; + + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); + loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); + } + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + /* if it is a simple glyph, load it */ + + if ( contours_count >= 0 ) + { + /* check that we can add the contours to the glyph */ + error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count ); + if ( error ) + goto Fail; + + error = face->read_simple_glyph( loader ); + if ( error ) + goto Fail; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + { + TT_Size size = (TT_Size)loader->size; + + + error = TT_Process_Simple_Glyph( loader, + (FT_Bool)( size && size->debug ) ); + } + +#else + + error = TT_Process_Simple_Glyph( loader, 0 ); + +#endif + + if ( error ) + goto Fail; + + FT_GlyphLoader_Add( gloader ); + + /* Note: We could have put the simple loader source there */ + /* but the code is fat enough already :-) */ + } + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + /* otherwise, load a composite! */ + else + { + TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph; + FT_UInt start_point, start_contour; + FT_ULong ins_pos; /* position of composite instructions, if any */ + + + /* for each subglyph, read composite header */ + start_point = gloader->base.outline.n_points; + start_contour = gloader->base.outline.n_contours; + + error = face->read_composite_glyph( loader ); + if ( error ) + goto Fail; + + ins_pos = loader->ins_pos; + face->forget_glyph_frame( loader ); + opened_frame = 0; + + /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ + /* `as is' in the glyph slot (the client application will be */ + /* responsible for interpreting this data)... */ + /* */ + if ( loader->load_flags & FT_LOAD_NO_RECURSE ) + { + /* set up remaining glyph fields */ + FT_GlyphLoader_Add( gloader ); + + glyph->num_subglyphs = gloader->base.num_subglyphs; + glyph->format = ft_glyph_format_composite; + glyph->subglyphs = gloader->base.subglyphs; + + goto Exit; + } + + /*********************************************************************/ + /*********************************************************************/ + /*********************************************************************/ + + /* Now, read each subglyph independently. */ + { + FT_Int n, num_base_points, num_new_points; + FT_SubGlyph* subglyph = 0; + + FT_UInt num_subglyphs = gloader->current.num_subglyphs; + FT_UInt num_base_subgs = gloader->base.num_subglyphs; + + + FT_GlyphLoader_Add( gloader ); + + for ( n = 0; n < (FT_Int)num_subglyphs; n++ ) + { + FT_Vector pp1, pp2; + FT_Pos x, y; + + + /* Each time we call load_truetype_glyph in this loop, the */ + /* value of `gloader.base.subglyphs' can change due to table */ + /* reallocations. We thus need to recompute the subglyph */ + /* pointer on each iteration. */ + subglyph = gloader->base.subglyphs + num_base_subgs + n; + + pp1 = loader->pp1; + pp2 = loader->pp2; + + num_base_points = gloader->base.outline.n_points; + + error = load_truetype_glyph( loader, subglyph->index ); + if ( error ) + goto Fail; + + subglyph = gloader->base.subglyphs + num_base_subgs + n; + + if ( subglyph->flags & USE_MY_METRICS ) + { + pp1 = loader->pp1; + pp2 = loader->pp2; + } + else + { + loader->pp1 = pp1; + loader->pp2 = pp2; + } + + num_points = gloader->base.outline.n_points; + + num_new_points = num_points - num_base_points; + + /* now perform the transform required for this subglyph */ + + if ( subglyph->flags & ( WE_HAVE_A_SCALE | + WE_HAVE_AN_XY_SCALE | + WE_HAVE_A_2X2 ) ) + { + FT_Vector* cur = gloader->base.outline.points + + num_base_points; + FT_Vector* org = gloader->base.extra_points + + num_base_points; + FT_Vector* limit = cur + num_new_points; + + + for ( ; cur < limit; cur++, org++ ) + { + FT_Vector_Transform( cur, &subglyph->transform ); + FT_Vector_Transform( org, &subglyph->transform ); + } + } + + /* apply offset */ + + if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) + { + FT_UInt k = subglyph->arg1; + FT_UInt l = subglyph->arg2; + FT_Vector* p1; + FT_Vector* p2; + + + if ( start_point + k >= (FT_UInt)num_base_points || + l >= (FT_UInt)num_new_points ) + { + error = TT_Err_Invalid_Composite; + goto Fail; + } + + l += num_base_points; + + p1 = gloader->base.outline.points + start_point + k; + p2 = gloader->base.outline.points + start_point + l; + + x = p1->x - p2->x; + y = p1->y - p2->y; + } + else + { + x = subglyph->arg1; + y = subglyph->arg2; + + if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) + { + x = FT_MulFix( x, x_scale ); + y = FT_MulFix( y, y_scale ); + + if ( subglyph->flags & ROUND_XY_TO_GRID ) + { + x = ( x + 32 ) & -64; + y = ( y + 32 ) & -64; + } + } + } + + translate_array( num_new_points, loader->zone.cur, x, y ); + cur_to_org( num_new_points, &loader->zone ); + } + + /*******************************************************************/ + /*******************************************************************/ + /*******************************************************************/ + + /* we have finished loading all sub-glyphs; now, look for */ + /* instructions for this composite! */ + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( num_subglyphs > 0 && + loader->exec && + ins_pos > 0 && + subglyph->flags & WE_HAVE_INSTR ) + { + FT_UShort n_ins; + TT_ExecContext exec = loader->exec; + TT_GlyphZone* pts; + FT_Vector* pp1; + + + /* read size of instructions */ + if ( FILE_Seek( ins_pos ) || + READ_UShort( n_ins ) ) + goto Fail; + FT_TRACE5(( " Instructions size = %d\n", n_ins )); + + /* in some fonts? */ + if ( n_ins == 0xFFFF ) + n_ins = 0; + + /* check it */ + if ( n_ins > face->max_profile.maxSizeOfInstructions ) + { + FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n", + n_ins, subglyph->index )); + return TT_Err_Too_Many_Ins; + } + + /* read the instructions */ + if ( FILE_Read( exec->glyphIns, n_ins ) ) + goto Fail; + + glyph->control_data = exec->glyphIns; + glyph->control_len = n_ins; + + error = TT_Set_CodeRange( exec, + tt_coderange_glyph, + exec->glyphIns, + n_ins ); + if ( error ) + goto Fail; + + /* prepare the execution context */ + tt_prepare_zone( &exec->pts, &gloader->base, + start_point, start_contour ); + pts = &exec->pts; + + pts->n_points = num_points + 2; + pts->n_contours = gloader->base.outline.n_contours; + + /* add phantom points */ + pp1 = pts->cur + num_points; + pp1[0] = loader->pp1; + pp1[1] = loader->pp2; + + pts->tags[num_points ] = 0; + pts->tags[num_points + 1] = 0; + + /* if hinting, round the phantom points */ + if ( IS_HINTED( loader->load_flags ) ) + { + pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 ); + pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 ); + } + + { + FT_UInt k; + + + for ( k = 0; k < num_points; k++ ) + pts->tags[k] &= FT_Curve_Tag_On; + } + + cur_to_org( num_points + 2, pts ); + + /* now consider hinting */ + if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) + { + exec->is_composite = TRUE; + exec->pedantic_hinting = + (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC ); + + error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug ); + if ( error && exec->pedantic_hinting ) + goto Fail; + } + + /* save glyph origin and advance points */ + loader->pp1 = pp1[0]; + loader->pp2 = pp1[1]; + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } + /* end of composite loading */ + } + + /***********************************************************************/ + /***********************************************************************/ + /***********************************************************************/ + + Fail: + if ( opened_frame ) + face->forget_glyph_frame( loader ); + + Exit: + return error; + } + + + static + void compute_glyph_metrics( TT_Loader* loader, + FT_UInt glyph_index ) + { + FT_BBox bbox; + TT_Face face = (TT_Face)loader->face; + FT_Fixed x_scale, y_scale; + TT_GlyphSlot glyph = loader->glyph; + TT_Size size = (TT_Size)loader->size; + + + x_scale = 0x10000L; + y_scale = 0x10000L; + if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + x_scale = size->root.metrics.x_scale; + y_scale = size->root.metrics.y_scale; + } + + if ( glyph->format != ft_glyph_format_composite ) + { + glyph->outline.flags &= ~ft_outline_single_pass; + + /* copy outline to our glyph slot */ + FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader ); + glyph->outline = glyph->loader->base.outline; + + /* translate array so that (0,0) is the glyph's origin */ + FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 ); + + FT_Outline_Get_CBox( &glyph->outline, &bbox ); + + if ( IS_HINTED( loader->load_flags ) ) + { + /* grid-fit the bounding box */ + bbox.xMin &= -64; + bbox.yMin &= -64; + bbox.xMax = ( bbox.xMax + 63 ) & -64; + bbox.yMax = ( bbox.yMax + 63 ) & -64; + } + } + else + bbox = loader->bbox; + + /* get the device-independent horizontal advance. It is scaled later */ + /* by the base layer. */ + { + FT_Pos advance = loader->advance; + + + /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */ + /* correctly support DynaLab fonts, which have an incorrect */ + /* `advance_Width_Max' field! It is used, to my knowledge, */ + /* exclusively in the X-TrueType font server. */ + /* */ + if ( face->postscript.isFixedPitch && + ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 ) + advance = face->horizontal.advance_Width_Max; + + /* we need to return the advance in font units in linearHoriAdvance, */ + /* it will be scaled later by the base layer. */ + glyph->linearHoriAdvance = advance; + } + + glyph->metrics.horiBearingX = bbox.xMin; + glyph->metrics.horiBearingY = bbox.yMax; + glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; + + /* Now take care of vertical metrics. In the case where there is */ + /* no vertical information within the font (relatively common), make */ + /* up some metrics by `hand'... */ + + { + FT_Short top_bearing; /* vertical top side bearing (EM units) */ + FT_UShort advance_height; /* vertical advance height (EM units) */ + + FT_Pos left; /* scaled vertical left side bearing */ + FT_Pos Top; /* scaled original vertical top side bearing */ + FT_Pos top; /* scaled vertical top side bearing */ + FT_Pos advance; /* scaled vertical advance height */ + + + /* Get the unscaled `tsb' and `ah' */ + if ( face->vertical_info && + face->vertical.number_Of_VMetrics > 0 ) + { + /* Don't assume that both the vertical header and vertical */ + /* metrics are present in the same font :-) */ + + TT_Get_Metrics( (TT_HoriHeader*)&face->vertical, + glyph_index, + &top_bearing, + &advance_height ); + } + else + { + /* Make up the distances from the horizontal header. */ + + /* NOTE: The OS/2 values are the only `portable' ones, */ + /* which is why we use them, if there is an OS/2 */ + /* table in the font. Otherwise, we use the */ + /* values defined in the horizontal header. */ + /* */ + /* NOTE2: The sTypoDescender is negative, which is why */ + /* we compute the baseline-to-baseline distance */ + /* here with: */ + /* ascender - descender + linegap */ + /* */ + if ( face->os2.version != 0xFFFF ) + { + top_bearing = face->os2.sTypoLineGap / 2; + advance_height = (FT_UShort)( face->os2.sTypoAscender - + face->os2.sTypoDescender + + face->os2.sTypoLineGap ); + } + else + { + top_bearing = face->horizontal.Line_Gap / 2; + advance_height = (FT_UShort)( face->horizontal.Ascender + + face->horizontal.Descender + + face->horizontal.Line_Gap ); + } + } + + /* We must adjust the top_bearing value from the bounding box given */ + /* in the glyph header to te bounding box calculated with */ + /* FT_Get_Outline_CBox(). */ + + /* scale the metrics */ + if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) + { + Top = FT_MulFix( top_bearing, y_scale ); + top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) + - bbox.yMax; + advance = FT_MulFix( advance_height, y_scale ); + } + else + { + Top = top_bearing; + top = top_bearing + loader->bbox.yMax - bbox.yMax; + advance = advance_height; + } + + /* set the advance height in design units. It is scaled later by */ + /* the base layer. */ + glyph->linearVertAdvance = advance_height; + + /* XXX: for now, we have no better algorithm for the lsb, but it */ + /* should work fine. */ + /* */ + left = ( bbox.xMin - bbox.xMax ) / 2; + + /* grid-fit them if necessary */ + if ( IS_HINTED( loader->load_flags ) ) + { + left &= -64; + top = ( top + 63 ) & -64; + advance = ( advance + 32 ) & -64; + } + + glyph->metrics.vertBearingX = left; + glyph->metrics.vertBearingY = top; + glyph->metrics.vertAdvance = advance; + } + + /* adjust advance width to the value contained in the hdmx table */ + if ( !face->postscript.isFixedPitch && size && + IS_HINTED( loader->load_flags ) ) + { + FT_Byte* widths = Get_Advance_Widths( face, + size->root.metrics.x_ppem ); + + + if ( widths ) + glyph->metrics.horiAdvance = widths[glyph_index] << 6; + } + + /* set glyph dimensions */ + glyph->metrics.width = bbox.xMax - bbox.xMin; + glyph->metrics.height = bbox.yMax - bbox.yMin; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Glyph */ + /* */ + /* */ + /* A function used to load a single glyph within a given glyph slot, */ + /* for a given size. */ + /* */ + /* */ + /* glyph :: A handle to a target slot object where the glyph */ + /* will be loaded. */ + /* */ + /* size :: A handle to the source face size at which the glyph */ + /* must be scaled/loaded. */ + /* */ + /* glyph_index :: The index of the glyph in the font file. */ + /* */ + /* load_flags :: A flag indicating what to load for this glyph. The */ + /* FT_LOAD_XXX constants can be used to control the */ + /* glyph loading process (e.g., whether the outline */ + /* should be scaled, whether to load bitmaps or not, */ + /* whether to hint the outline, etc). */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + FT_UShort glyph_index, + FT_UInt load_flags ) + { + SFNT_Interface* sfnt; + TT_Face face; + FT_Stream stream; + FT_Memory memory; + FT_Error error; + TT_Loader loader; + + + face = (TT_Face)glyph->face; + sfnt = (SFNT_Interface*)face->sfnt; + stream = face->root.stream; + memory = face->root.memory; + error = 0; + + if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) || + ( load_flags & FT_LOAD_NO_RECURSE ) ) + { + size = NULL; + load_flags |= FT_LOAD_NO_SCALE | + FT_LOAD_NO_HINTING | + FT_LOAD_NO_BITMAP; + } + + glyph->num_subglyphs = 0; + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + /* try to load embedded bitmap if any */ + if ( size && + ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && + sfnt->load_sbits ) + { + TT_SBit_Metrics metrics; + + + error = sfnt->load_sbit_image( face, + size->root.metrics.x_ppem, + size->root.metrics.y_ppem, + glyph_index, + load_flags, + stream, + &glyph->bitmap, + &metrics ); + if ( !error ) + { + glyph->outline.n_points = 0; + glyph->outline.n_contours = 0; + + glyph->metrics.width = (FT_Pos)metrics.width << 6; + glyph->metrics.height = (FT_Pos)metrics.height << 6; + + glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; + glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; + glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; + + glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; + glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; + glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; + + glyph->format = ft_glyph_format_bitmap; + if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) + { + glyph->bitmap_left = metrics.vertBearingX; + glyph->bitmap_top = metrics.vertBearingY; + } + else + { + glyph->bitmap_left = metrics.horiBearingX; + glyph->bitmap_top = metrics.horiBearingY; + } + return error; + } + } + +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /* seek to the beginning of the glyph table. For Type 42 fonts */ + /* the table might be accessed from a Postscript stream or something */ + /* else... */ + + error = face->goto_table( face, TTAG_glyf, stream, 0 ); + if ( error ) + { + FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); + goto Exit; + } + + MEM_Set( &loader, 0, sizeof ( loader ) ); + + /* update the glyph zone bounds */ + { + FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader; + + + loader.gloader = gloader; + + FT_GlyphLoader_Rewind( gloader ); + + tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 ); + tt_prepare_zone( &loader.base, &gloader->base, 0, 0 ); + } + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( size ) + { + /* query new execution context */ + loader.exec = size->debug ? size->context : TT_New_Context( face ); + if ( !loader.exec ) + return TT_Err_Could_Not_Find_Context; + + TT_Load_Context( loader.exec, face, size ); + loader.instructions = loader.exec->glyphIns; + + /* load default graphics state - if needed */ + if ( size->GS.instruct_control & 2 ) + loader.exec->GS = tt_default_graphics_state; + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /* clear all outline flags, except the `owner' one */ + glyph->outline.flags = 0; + + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->outline.flags |= ft_outline_high_precision; + + /* let's initialize the rest of our loader now */ + + loader.load_flags = load_flags; + + loader.face = (FT_Face)face; + loader.size = (FT_Size)size; + loader.glyph = (FT_GlyphSlot)glyph; + loader.stream = stream; + + loader.glyf_offset = FILE_Pos(); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* if the cvt program has disabled hinting, the argument */ + /* is ignored. */ + if ( size && ( size->GS.instruct_control & 1 ) ) + loader.load_flags |= FT_LOAD_NO_HINTING; + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + /* Main loading loop */ + glyph->format = ft_glyph_format_outline; + glyph->num_subglyphs = 0; + error = load_truetype_glyph( &loader, glyph_index ); + if ( !error ) + compute_glyph_metrics( &loader, glyph_index ); + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + if ( !size || !size->debug ) + TT_Done_Context( loader.exec ); + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + Exit: + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttgload.h b/subsys/win32k/freetype/src/truetype/ttgload.h new file mode 100644 index 0000000..d6ca019 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttgload.h @@ -0,0 +1,69 @@ +/***************************************************************************/ +/* */ +/* ttgload.h */ +/* */ +/* TrueType Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTGLOAD_H +#define TTGLOAD_H + + +#ifdef FT_FLAT_COMPILE + +#include "ttobjs.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + void TT_Get_Metrics( TT_HoriHeader* header, + FT_UInt index, + FT_Short* bearing, + FT_UShort* advance ); + + LOCAL_DEF + void TT_Init_Glyph_Loading( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Load_Glyph( TT_Size size, + TT_GlyphSlot glyph, + FT_UShort glyph_index, + FT_UInt load_flags ); + +#ifdef __cplusplus + } +#endif + +#endif /* TTGLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttinterp.c b/subsys/win32k/freetype/src/truetype/ttinterp.c new file mode 100644 index 0000000..bd22e5e --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttinterp.c @@ -0,0 +1,7544 @@ +/***************************************************************************/ +/* */ +/* ttinterp.c */ +/* */ +/* TrueType bytecode interpreter (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttinterp.h" + +#else + +#include + +#endif + + +#include + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + +#define TT_MULFIX FT_MulFix +#define TT_MULDIV FT_MulDiv + +#define TT_INT64 FT_Int64 + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttinterp + +#undef NO_APPLE_PATENT +#define APPLE_THRESHOLD 0x4000000L + + /*************************************************************************/ + /* */ + /* In order to detect infinite loops in the code, we set up a counter */ + /* within the run loop. A single stroke of interpretation is now */ + /* limitet to a maximal number of opcodes defined below. */ + /* */ +#define MAX_RUNNABLE_OPCODES 1000000L + + + /*************************************************************************/ + /* */ + /* There are two kinds of implementations: */ + /* */ + /* a. static implementation */ + /* */ + /* The current execution context is a static variable, which fields */ + /* are accessed directly by the interpreter during execution. The */ + /* context is named `cur'. */ + /* */ + /* This version is non-reentrant, of course. */ + /* */ + /* b. indirect implementation */ + /* */ + /* The current execution context is passed to _each_ function as its */ + /* first argument, and each field is thus accessed indirectly. */ + /* */ + /* This version is fully re-entrant. */ + /* */ + /* The idea is that an indirect implementation may be slower to execute */ + /* on low-end processors that are used in some systems (like 386s or */ + /* even 486s). */ + /* */ + /* As a consequence, the indirect implementation is now the default, as */ + /* its performance costs can be considered negligible in our context. */ + /* Note, however, that we kept the same source with macros because: */ + /* */ + /* - The code is kept very close in design to the Pascal code used for */ + /* development. */ + /* */ + /* - It's much more readable that way! */ + /* */ + /* - It's still open to experimentation and tuning. */ + /* */ + /*************************************************************************/ + + +#ifndef TT_CONFIG_OPTION_STATIC_INTERPRETER /* indirect implementation */ + +#define CUR (*exc) /* see ttobjs.h */ + +#else /* static implementation */ + +#define CUR cur + + static + TT_ExecContextRec cur; /* static exec. context variable */ + + /* apparently, we have a _lot_ of direct indexing when accessing */ + /* the static `cur', which makes the code bigger (due to all the */ + /* four bytes addresses). */ + +#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* The instruction argument stack. */ + /* */ +#define INS_ARG EXEC_OP_ FT_Long* args /* see ttobjs.h for EXEC_OP_ */ + + + /*************************************************************************/ + /* */ + /* This macro is used whenever `exec' is unused in a function, to avoid */ + /* stupid warnings from pedantic compilers. */ + /* */ +#define FT_UNUSED_EXEC FT_UNUSED( CUR ) + + + /*************************************************************************/ + /* */ + /* This macro is used whenever `args' is unused in a function, to avoid */ + /* stupid warnings from pedantic compilers. */ + /* */ +#define FT_UNUSED_ARG FT_UNUSED_EXEC; FT_UNUSED( args ) + + + /*************************************************************************/ + /* */ + /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to */ + /* increase readabilty of the code. */ + /* */ + /*************************************************************************/ + + +#define SKIP_Code() \ + SkipCode( EXEC_ARG ) + +#define GET_ShortIns() \ + GetShortIns( EXEC_ARG ) + +#define NORMalize( x, y, v ) \ + Normalize( EXEC_ARG_ x, y, v ) + +#define SET_SuperRound( scale, flags ) \ + SetSuperRound( EXEC_ARG_ scale, flags ) + +#define ROUND_None( d, c ) \ + Round_None( EXEC_ARG_ d, c ) + +#define INS_Goto_CodeRange( range, ip ) \ + Ins_Goto_CodeRange( EXEC_ARG_ range, ip ) + +#define CUR_Func_project( x, y ) \ + CUR.func_project( EXEC_ARG_ x, y ) + +#define CUR_Func_move( z, p, d ) \ + CUR.func_move( EXEC_ARG_ z, p, d ) + +#define CUR_Func_dualproj( x, y ) \ + CUR.func_dualproj( EXEC_ARG_ x, y ) + +#define CUR_Func_freeProj( x, y ) \ + CUR.func_freeProj( EXEC_ARG_ x, y ) + +#define CUR_Func_round( d, c ) \ + CUR.func_round( EXEC_ARG_ d, c ) + +#define CUR_Func_read_cvt( index ) \ + CUR.func_read_cvt( EXEC_ARG_ index ) + +#define CUR_Func_write_cvt( index, val ) \ + CUR.func_write_cvt( EXEC_ARG_ index, val ) + +#define CUR_Func_move_cvt( index, val ) \ + CUR.func_move_cvt( EXEC_ARG_ index, val ) + +#define CURRENT_Ratio() \ + Current_Ratio( EXEC_ARG ) + +#define CURRENT_Ppem() \ + Current_Ppem( EXEC_ARG ) + +#define CUR_Ppem() \ + Cur_PPEM( EXEC_ARG ) + +#define CALC_Length() \ + Calc_Length( EXEC_ARG ) + +#define INS_SxVTL( a, b, c, d ) \ + Ins_SxVTL( EXEC_ARG_ a, b, c, d ) + +#define COMPUTE_Funcs() \ + Compute_Funcs( EXEC_ARG ) + +#define COMPUTE_Round( a ) \ + Compute_Round( EXEC_ARG_ a ) + +#define COMPUTE_Point_Displacement( a, b, c, d ) \ + Compute_Point_Displacement( EXEC_ARG_ a, b, c, d ) + +#define MOVE_Zp2_Point( a, b, c, t ) \ + Move_Zp2_Point( EXEC_ARG_ a, b, c, t ) + + + /*************************************************************************/ + /* */ + /* Instruction dispatch function, as used by the interpreter. */ + /* */ + typedef void (*TInstruction_Function)( INS_ARG ); + + + /*************************************************************************/ + /* */ + /* A simple bounds-checking macro. */ + /* */ +#define BOUNDS( x, n ) ( (FT_UInt)(x) >= (FT_UInt)(n) ) + + +#undef SUCCESS +#define SUCCESS 0 + +#undef FAILURE +#define FAILURE 1 + + + /*************************************************************************/ + /* */ + /* CODERANGE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Goto_CodeRange */ + /* */ + /* */ + /* Switches to a new code range (updates the code related elements in */ + /* `exec', and `IP'). */ + /* */ + /* */ + /* range :: The new execution code range. */ + /* */ + /* IP :: The new IP in the new code range. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Goto_CodeRange( TT_ExecContext exec, + FT_Int range, + FT_Long IP ) + { + TT_CodeRange* coderange; + + + FT_Assert( range >= 1 && range <= 3 ); + + coderange = &exec->codeRangeTable[range - 1]; + + FT_Assert( coderange->base != NULL ); + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for IP <= Size instead of IP < Size. */ + /* */ + FT_Assert( (FT_ULong)IP <= coderange->size ); + + exec->code = coderange->base; + exec->codeSize = coderange->size; + exec->IP = IP; + exec->curRange = range; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Set_CodeRange */ + /* */ + /* */ + /* Sets a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* base :: The new code base. */ + /* */ + /* length :: The range size in bytes. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Set_CodeRange( TT_ExecContext exec, + FT_Int range, + void* base, + FT_Long length ) + { + FT_Assert( range >= 1 && range <= 3 ); + + exec->codeRangeTable[range - 1].base = (FT_Byte*)base; + exec->codeRangeTable[range - 1].size = length; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Clear_CodeRange */ + /* */ + /* */ + /* Clears a code range. */ + /* */ + /* */ + /* range :: The code range index. */ + /* */ + /* */ + /* exec :: The target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Does not set the Error variable. */ + /* */ + LOCAL_FUNC + FT_Error TT_Clear_CodeRange( TT_ExecContext exec, + FT_Int range ) + { + FT_Assert( range >= 1 && range <= 3 ); + + exec->codeRangeTable[range - 1].base = NULL; + exec->codeRangeTable[range - 1].size = 0; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* EXECUTION CONTEXT ROUTINES */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Destroy_Context */ + /* */ + /* */ + /* Destroys a given context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ) + { + /* free composite load stack */ + FREE( exec->loadStack ); + exec->loadSize = 0; + + /* points zone */ + exec->maxPoints = 0; + exec->maxContours = 0; + + /* free stack */ + FREE( exec->stack ); + exec->stackSize = 0; + + /* free call stack */ + FREE( exec->callStack ); + exec->callSize = 0; + exec->callTop = 0; + + /* free glyph code range */ + FREE( exec->glyphIns ); + exec->glyphSize = 0; + + exec->size = NULL; + exec->face = NULL; + + FREE( exec ); + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Init_Context */ + /* */ + /* */ + /* Initializes a context object. */ + /* */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* face :: A handle to the source TrueType face object. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Init_Context( TT_ExecContext exec, + TT_Face face, + FT_Memory memory ) + { + FT_Error error; + + + FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n", + exec, face )); + + exec->memory = memory; + exec->callSize = 32; + + if ( ALLOC_ARRAY( exec->callStack, exec->callSize, TT_CallRec ) ) + goto Fail_Memory; + + /* all values in the context are set to 0 already, but this is */ + /* here as a remainder */ + exec->maxPoints = 0; + exec->maxContours = 0; + + exec->stackSize = 0; + exec->loadSize = 0; + exec->glyphSize = 0; + + exec->stack = NULL; + exec->loadStack = NULL; + exec->glyphIns = NULL; + + exec->face = face; + exec->size = NULL; + + return TT_Err_Ok; + + Fail_Memory: + FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n", + (FT_Long)exec )); + TT_Destroy_Context( exec, memory ); + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Update_Max */ + /* */ + /* */ + /* Checks the size of a buffer and reallocates it if necessary. */ + /* */ + /* */ + /* memory :: A handle to the parent memory object. */ + /* */ + /* multiplier :: The size in bytes of each element in the buffer. */ + /* */ + /* new_max :: The new capacity (size) of the buffer. */ + /* */ + /* */ + /* size :: The address of the buffer's current size expressed */ + /* in elements. */ + /* */ + /* buff :: The address of the buffer base pointer. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Update_Max( FT_Memory memory, + FT_ULong* size, + FT_Long multiplier, + void** buff, + FT_ULong new_max ) + { + FT_Error error; + + + if ( *size < new_max ) + { + FREE( *buff ); + if ( ALLOC( *buff, new_max * multiplier ) ) + return error; + *size = new_max; + } + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Context */ + /* */ + /* */ + /* Prepare an execution context for glyph hinting. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* size :: A handle to the source size object. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ) + { + FT_Int i; + FT_ULong tmp; + TT_MaxProfile* maxp; + FT_Error error; + + + exec->face = face; + maxp = &face->max_profile; + exec->size = size; + + if ( size ) + { + exec->numFDefs = size->num_function_defs; + exec->maxFDefs = size->max_function_defs; + exec->numIDefs = size->num_instruction_defs; + exec->maxIDefs = size->max_instruction_defs; + exec->FDefs = size->function_defs; + exec->IDefs = size->instruction_defs; + exec->tt_metrics = size->ttmetrics; + exec->metrics = size->root.metrics; + + exec->maxFunc = size->max_func; + exec->maxIns = size->max_ins; + + for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) + exec->codeRangeTable[i] = size->codeRangeTable[i]; + + /* set graphics state */ + exec->GS = size->GS; + + exec->cvtSize = size->cvt_size; + exec->cvt = size->cvt; + + exec->storeSize = size->storage_size; + exec->storage = size->storage; + + exec->twilight = size->twilight; + } + + error = Update_Max( exec->memory, + &exec->loadSize, + sizeof ( TT_SubGlyphRec ), + (void**)&exec->loadStack, + exec->face->max_components + 1 ); + if ( error ) + return error; + + /* XXX: We reserve a little more elements on the stack to deal safely */ + /* with broken fonts like arialbs, courbs, timesbs, etc. */ + tmp = exec->stackSize; + error = Update_Max( exec->memory, + &tmp, + sizeof ( FT_F26Dot6 ), + (void**)&exec->stack, + maxp->maxStackElements + 32 ); + exec->stackSize = (FT_UInt)tmp; + if ( error ) + return error; + + tmp = exec->glyphSize; + error = Update_Max( exec->memory, + &tmp, + sizeof ( FT_Byte ), + (void**)&exec->glyphIns, + maxp->maxSizeOfInstructions ); + exec->glyphSize = (FT_UShort)tmp; + if ( error ) + return error; + + exec->pts.n_points = 0; + exec->pts.n_contours = 0; + + exec->instruction_trap = FALSE; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Save_Context */ + /* */ + /* */ + /* Saves the code ranges in a `size' object. */ + /* */ + /* */ + /* exec :: A handle to the source execution context. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Save_Context( TT_ExecContext exec, + TT_Size size ) + { + FT_Int i; + + + /* XXXX: Will probably disappear soon with all the code range */ + /* management, which is now rather obsolete. */ + /* */ + size->num_function_defs = exec->numFDefs; + size->num_instruction_defs = exec->numIDefs; + + size->max_func = exec->maxFunc; + size->max_ins = exec->maxIns; + + for ( i = 0; i < TT_MAX_CODE_RANGES; i++ ) + size->codeRangeTable[i] = exec->codeRangeTable[i]; + + return TT_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Run_Context */ + /* */ + /* */ + /* Executes one or more instructions in the execution context. */ + /* */ + /* */ + /* debug :: A Boolean flag. If set, the function sets some internal */ + /* variables and returns immediately, otherwise TT_RunIns() */ + /* is called. */ + /* */ + /* This is commented out currently. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* TrueTyoe error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Run_Context( TT_ExecContext exec, + FT_Bool debug ) + { + FT_Error error; + + + if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) ) + != TT_Err_Ok ) + return error; + + exec->zp0 = exec->pts; + exec->zp1 = exec->pts; + exec->zp2 = exec->pts; + + exec->GS.gep0 = 1; + exec->GS.gep1 = 1; + exec->GS.gep2 = 1; + + exec->GS.projVector.x = 0x4000; + exec->GS.projVector.y = 0x0000; + + exec->GS.freeVector = exec->GS.projVector; + exec->GS.dualVector = exec->GS.projVector; + + exec->GS.round_state = 1; + exec->GS.loop = 1; + + /* some glyphs leave something on the stack. so we clean it */ + /* before a new execution. */ + exec->top = 0; + exec->callTop = 0; + +#if 1 + FT_UNUSED( debug ); + + return exec->face->interpreter( exec ); +#else + if ( !debug ) + return TT_RunIns( exec ); + else + return TT_Err_Ok; +#endif + } + + + const TT_GraphicsState tt_default_graphics_state = + { + 0, 0, 0, + { 0x4000, 0 }, + { 0x4000, 0 }, + { 0x4000, 0 }, + 1, 64, 1, + TRUE, 68, 0, 0, 9, 3, + 0, FALSE, 2, 1, 1, 1 + }; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_New_Context */ + /* */ + /* */ + /* Queries the face context for a given font. Note that there is */ + /* now a _single_ execution context in the TrueType driver which is */ + /* shared among faces. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* */ + /* A handle to the execution context. Initialized for `face'. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + FT_EXPORT_FUNC( TT_ExecContext ) TT_New_Context( TT_Face face ) + { + TT_Driver driver; + TT_ExecContext exec; + FT_Memory memory; + + + if ( !face ) + return 0; + + driver = (TT_Driver)face->root.driver; + + memory = driver->root.root.memory; + exec = driver->context; + + if ( !driver->context ) + { + FT_Error error; + + + /* allocate object */ + if ( ALLOC( exec, sizeof ( *exec ) ) ) + goto Exit; + + /* initialize it */ + error = Init_Context( exec, face, memory ); + if ( error ) + goto Fail; + + /* store it into the driver */ + driver->context = exec; + } + + Exit: + return driver->context; + + Fail: + FREE( exec ); + + return 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Context */ + /* */ + /* */ + /* Discards an execution context. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the glyph loader and debugger should call this function. */ + /* */ + LOCAL_FUNC + FT_Error TT_Done_Context( TT_ExecContext exec ) + { + /* Nothing at all for now */ + FT_UNUSED( exec ); + + return TT_Err_Ok; + } + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + static FT_F26Dot6 Norm( FT_F26Dot6 X, + FT_F26Dot6 Y ) + { + TT_INT64 T1, T2; + + + MUL_64( X, X, T1 ); + MUL_64( Y, Y, T2 ); + + ADD_64( T1, T2, T1 ); + + return (FT_F26Dot6)SQRT_64( T1 ); + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + + /*************************************************************************/ + /* */ + /* Before an opcode is executed, the interpreter verifies that there are */ + /* enough arguments on the stack, with the help of the Pop_Push_Count */ + /* table. */ + /* */ + /* For each opcode, the first column gives the number of arguments that */ + /* are popped from the stack; the second one gives the number of those */ + /* that are pushed in result. */ + /* */ + /* Note that for opcodes with a varying number of parameters, either 0 */ + /* or 1 arg is verified before execution, depending on the nature of the */ + /* instruction: */ + /* */ + /* - if the number of arguments is given by the bytecode stream or the */ + /* loop variable, 0 is chosen. */ + /* */ + /* - if the first argument is a count n that is followed by arguments */ + /* a1 .. an, then 1 is chosen. */ + /* */ + /*************************************************************************/ + + +#undef PACK +#define PACK( x, y ) ( ( x << 4 ) | y ) + + + static + const FT_Byte Pop_Push_Count[256] = + { + /* opcodes are gathered in groups of 16 */ + /* please keep the spaces as they are */ + + /* SVTCA y */ PACK( 0, 0 ), + /* SVTCA x */ PACK( 0, 0 ), + /* SPvTCA y */ PACK( 0, 0 ), + /* SPvTCA x */ PACK( 0, 0 ), + /* SFvTCA y */ PACK( 0, 0 ), + /* SFvTCA x */ PACK( 0, 0 ), + /* SPvTL // */ PACK( 2, 0 ), + /* SPvTL + */ PACK( 2, 0 ), + /* SFvTL // */ PACK( 2, 0 ), + /* SFvTL + */ PACK( 2, 0 ), + /* SPvFS */ PACK( 2, 0 ), + /* SFvFS */ PACK( 2, 0 ), + /* GPV */ PACK( 0, 2 ), + /* GFV */ PACK( 0, 2 ), + /* SFvTPv */ PACK( 0, 0 ), + /* ISECT */ PACK( 5, 0 ), + + /* SRP0 */ PACK( 1, 0 ), + /* SRP1 */ PACK( 1, 0 ), + /* SRP2 */ PACK( 1, 0 ), + /* SZP0 */ PACK( 1, 0 ), + /* SZP1 */ PACK( 1, 0 ), + /* SZP2 */ PACK( 1, 0 ), + /* SZPS */ PACK( 1, 0 ), + /* SLOOP */ PACK( 1, 0 ), + /* RTG */ PACK( 0, 0 ), + /* RTHG */ PACK( 0, 0 ), + /* SMD */ PACK( 1, 0 ), + /* ELSE */ PACK( 0, 0 ), + /* JMPR */ PACK( 1, 0 ), + /* SCvTCi */ PACK( 1, 0 ), + /* SSwCi */ PACK( 1, 0 ), + /* SSW */ PACK( 1, 0 ), + + /* DUP */ PACK( 1, 2 ), + /* POP */ PACK( 1, 0 ), + /* CLEAR */ PACK( 0, 0 ), + /* SWAP */ PACK( 2, 2 ), + /* DEPTH */ PACK( 0, 1 ), + /* CINDEX */ PACK( 1, 1 ), + /* MINDEX */ PACK( 1, 0 ), + /* AlignPTS */ PACK( 2, 0 ), + /* INS_$28 */ PACK( 0, 0 ), + /* UTP */ PACK( 1, 0 ), + /* LOOPCALL */ PACK( 2, 0 ), + /* CALL */ PACK( 1, 0 ), + /* FDEF */ PACK( 1, 0 ), + /* ENDF */ PACK( 0, 0 ), + /* MDAP[0] */ PACK( 1, 0 ), + /* MDAP[1] */ PACK( 1, 0 ), + + /* IUP[0] */ PACK( 0, 0 ), + /* IUP[1] */ PACK( 0, 0 ), + /* SHP[0] */ PACK( 0, 0 ), + /* SHP[1] */ PACK( 0, 0 ), + /* SHC[0] */ PACK( 1, 0 ), + /* SHC[1] */ PACK( 1, 0 ), + /* SHZ[0] */ PACK( 1, 0 ), + /* SHZ[1] */ PACK( 1, 0 ), + /* SHPIX */ PACK( 1, 0 ), + /* IP */ PACK( 0, 0 ), + /* MSIRP[0] */ PACK( 2, 0 ), + /* MSIRP[1] */ PACK( 2, 0 ), + /* AlignRP */ PACK( 0, 0 ), + /* RTDG */ PACK( 0, 0 ), + /* MIAP[0] */ PACK( 2, 0 ), + /* MIAP[1] */ PACK( 2, 0 ), + + /* NPushB */ PACK( 0, 0 ), + /* NPushW */ PACK( 0, 0 ), + /* WS */ PACK( 2, 0 ), + /* RS */ PACK( 1, 1 ), + /* WCvtP */ PACK( 2, 0 ), + /* RCvt */ PACK( 1, 1 ), + /* GC[0] */ PACK( 1, 1 ), + /* GC[1] */ PACK( 1, 1 ), + /* SCFS */ PACK( 2, 0 ), + /* MD[0] */ PACK( 2, 1 ), + /* MD[1] */ PACK( 2, 1 ), + /* MPPEM */ PACK( 0, 1 ), + /* MPS */ PACK( 0, 1 ), + /* FlipON */ PACK( 0, 0 ), + /* FlipOFF */ PACK( 0, 0 ), + /* DEBUG */ PACK( 1, 0 ), + + /* LT */ PACK( 2, 1 ), + /* LTEQ */ PACK( 2, 1 ), + /* GT */ PACK( 2, 1 ), + /* GTEQ */ PACK( 2, 1 ), + /* EQ */ PACK( 2, 1 ), + /* NEQ */ PACK( 2, 1 ), + /* ODD */ PACK( 1, 1 ), + /* EVEN */ PACK( 1, 1 ), + /* IF */ PACK( 1, 0 ), + /* EIF */ PACK( 0, 0 ), + /* AND */ PACK( 2, 1 ), + /* OR */ PACK( 2, 1 ), + /* NOT */ PACK( 1, 1 ), + /* DeltaP1 */ PACK( 1, 0 ), + /* SDB */ PACK( 1, 0 ), + /* SDS */ PACK( 1, 0 ), + + /* ADD */ PACK( 2, 1 ), + /* SUB */ PACK( 2, 1 ), + /* DIV */ PACK( 2, 1 ), + /* MUL */ PACK( 2, 1 ), + /* ABS */ PACK( 1, 1 ), + /* NEG */ PACK( 1, 1 ), + /* FLOOR */ PACK( 1, 1 ), + /* CEILING */ PACK( 1, 1 ), + /* ROUND[0] */ PACK( 1, 1 ), + /* ROUND[1] */ PACK( 1, 1 ), + /* ROUND[2] */ PACK( 1, 1 ), + /* ROUND[3] */ PACK( 1, 1 ), + /* NROUND[0] */ PACK( 1, 1 ), + /* NROUND[1] */ PACK( 1, 1 ), + /* NROUND[2] */ PACK( 1, 1 ), + /* NROUND[3] */ PACK( 1, 1 ), + + /* WCvtF */ PACK( 2, 0 ), + /* DeltaP2 */ PACK( 1, 0 ), + /* DeltaP3 */ PACK( 1, 0 ), + /* DeltaCn[0] */ PACK( 1, 0 ), + /* DeltaCn[1] */ PACK( 1, 0 ), + /* DeltaCn[2] */ PACK( 1, 0 ), + /* SROUND */ PACK( 1, 0 ), + /* S45Round */ PACK( 1, 0 ), + /* JROT */ PACK( 2, 0 ), + /* JROF */ PACK( 2, 0 ), + /* ROFF */ PACK( 0, 0 ), + /* INS_$7B */ PACK( 0, 0 ), + /* RUTG */ PACK( 0, 0 ), + /* RDTG */ PACK( 0, 0 ), + /* SANGW */ PACK( 1, 0 ), + /* AA */ PACK( 1, 0 ), + + /* FlipPT */ PACK( 0, 0 ), + /* FlipRgON */ PACK( 2, 0 ), + /* FlipRgOFF */ PACK( 2, 0 ), + /* INS_$83 */ PACK( 0, 0 ), + /* INS_$84 */ PACK( 0, 0 ), + /* ScanCTRL */ PACK( 1, 0 ), + /* SDVPTL[0] */ PACK( 2, 0 ), + /* SDVPTL[1] */ PACK( 2, 0 ), + /* GetINFO */ PACK( 1, 1 ), + /* IDEF */ PACK( 1, 0 ), + /* ROLL */ PACK( 3, 3 ), + /* MAX */ PACK( 2, 1 ), + /* MIN */ PACK( 2, 1 ), + /* ScanTYPE */ PACK( 1, 0 ), + /* InstCTRL */ PACK( 2, 0 ), + /* INS_$8F */ PACK( 0, 0 ), + + /* INS_$90 */ PACK( 0, 0 ), + /* INS_$91 */ PACK( 0, 0 ), + /* INS_$92 */ PACK( 0, 0 ), + /* INS_$93 */ PACK( 0, 0 ), + /* INS_$94 */ PACK( 0, 0 ), + /* INS_$95 */ PACK( 0, 0 ), + /* INS_$96 */ PACK( 0, 0 ), + /* INS_$97 */ PACK( 0, 0 ), + /* INS_$98 */ PACK( 0, 0 ), + /* INS_$99 */ PACK( 0, 0 ), + /* INS_$9A */ PACK( 0, 0 ), + /* INS_$9B */ PACK( 0, 0 ), + /* INS_$9C */ PACK( 0, 0 ), + /* INS_$9D */ PACK( 0, 0 ), + /* INS_$9E */ PACK( 0, 0 ), + /* INS_$9F */ PACK( 0, 0 ), + + /* INS_$A0 */ PACK( 0, 0 ), + /* INS_$A1 */ PACK( 0, 0 ), + /* INS_$A2 */ PACK( 0, 0 ), + /* INS_$A3 */ PACK( 0, 0 ), + /* INS_$A4 */ PACK( 0, 0 ), + /* INS_$A5 */ PACK( 0, 0 ), + /* INS_$A6 */ PACK( 0, 0 ), + /* INS_$A7 */ PACK( 0, 0 ), + /* INS_$A8 */ PACK( 0, 0 ), + /* INS_$A9 */ PACK( 0, 0 ), + /* INS_$AA */ PACK( 0, 0 ), + /* INS_$AB */ PACK( 0, 0 ), + /* INS_$AC */ PACK( 0, 0 ), + /* INS_$AD */ PACK( 0, 0 ), + /* INS_$AE */ PACK( 0, 0 ), + /* INS_$AF */ PACK( 0, 0 ), + + /* PushB[0] */ PACK( 0, 1 ), + /* PushB[1] */ PACK( 0, 2 ), + /* PushB[2] */ PACK( 0, 3 ), + /* PushB[3] */ PACK( 0, 4 ), + /* PushB[4] */ PACK( 0, 5 ), + /* PushB[5] */ PACK( 0, 6 ), + /* PushB[6] */ PACK( 0, 7 ), + /* PushB[7] */ PACK( 0, 8 ), + /* PushW[0] */ PACK( 0, 1 ), + /* PushW[1] */ PACK( 0, 2 ), + /* PushW[2] */ PACK( 0, 3 ), + /* PushW[3] */ PACK( 0, 4 ), + /* PushW[4] */ PACK( 0, 5 ), + /* PushW[5] */ PACK( 0, 6 ), + /* PushW[6] */ PACK( 0, 7 ), + /* PushW[7] */ PACK( 0, 8 ), + + /* MDRP[00] */ PACK( 1, 0 ), + /* MDRP[01] */ PACK( 1, 0 ), + /* MDRP[02] */ PACK( 1, 0 ), + /* MDRP[03] */ PACK( 1, 0 ), + /* MDRP[04] */ PACK( 1, 0 ), + /* MDRP[05] */ PACK( 1, 0 ), + /* MDRP[06] */ PACK( 1, 0 ), + /* MDRP[07] */ PACK( 1, 0 ), + /* MDRP[08] */ PACK( 1, 0 ), + /* MDRP[09] */ PACK( 1, 0 ), + /* MDRP[10] */ PACK( 1, 0 ), + /* MDRP[11] */ PACK( 1, 0 ), + /* MDRP[12] */ PACK( 1, 0 ), + /* MDRP[13] */ PACK( 1, 0 ), + /* MDRP[14] */ PACK( 1, 0 ), + /* MDRP[15] */ PACK( 1, 0 ), + + /* MDRP[16] */ PACK( 1, 0 ), + /* MDRP[17] */ PACK( 1, 0 ), + /* MDRP[18] */ PACK( 1, 0 ), + /* MDRP[19] */ PACK( 1, 0 ), + /* MDRP[20] */ PACK( 1, 0 ), + /* MDRP[21] */ PACK( 1, 0 ), + /* MDRP[22] */ PACK( 1, 0 ), + /* MDRP[23] */ PACK( 1, 0 ), + /* MDRP[24] */ PACK( 1, 0 ), + /* MDRP[25] */ PACK( 1, 0 ), + /* MDRP[26] */ PACK( 1, 0 ), + /* MDRP[27] */ PACK( 1, 0 ), + /* MDRP[28] */ PACK( 1, 0 ), + /* MDRP[29] */ PACK( 1, 0 ), + /* MDRP[30] */ PACK( 1, 0 ), + /* MDRP[31] */ PACK( 1, 0 ), + + /* MIRP[00] */ PACK( 2, 0 ), + /* MIRP[01] */ PACK( 2, 0 ), + /* MIRP[02] */ PACK( 2, 0 ), + /* MIRP[03] */ PACK( 2, 0 ), + /* MIRP[04] */ PACK( 2, 0 ), + /* MIRP[05] */ PACK( 2, 0 ), + /* MIRP[06] */ PACK( 2, 0 ), + /* MIRP[07] */ PACK( 2, 0 ), + /* MIRP[08] */ PACK( 2, 0 ), + /* MIRP[09] */ PACK( 2, 0 ), + /* MIRP[10] */ PACK( 2, 0 ), + /* MIRP[11] */ PACK( 2, 0 ), + /* MIRP[12] */ PACK( 2, 0 ), + /* MIRP[13] */ PACK( 2, 0 ), + /* MIRP[14] */ PACK( 2, 0 ), + /* MIRP[15] */ PACK( 2, 0 ), + + /* MIRP[16] */ PACK( 2, 0 ), + /* MIRP[17] */ PACK( 2, 0 ), + /* MIRP[18] */ PACK( 2, 0 ), + /* MIRP[19] */ PACK( 2, 0 ), + /* MIRP[20] */ PACK( 2, 0 ), + /* MIRP[21] */ PACK( 2, 0 ), + /* MIRP[22] */ PACK( 2, 0 ), + /* MIRP[23] */ PACK( 2, 0 ), + /* MIRP[24] */ PACK( 2, 0 ), + /* MIRP[25] */ PACK( 2, 0 ), + /* MIRP[26] */ PACK( 2, 0 ), + /* MIRP[27] */ PACK( 2, 0 ), + /* MIRP[28] */ PACK( 2, 0 ), + /* MIRP[29] */ PACK( 2, 0 ), + /* MIRP[30] */ PACK( 2, 0 ), + /* MIRP[31] */ PACK( 2, 0 ) + }; + + + static + const FT_Char opcode_length[256] = + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + -1,-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 3, 5, 7, 9, 11,13,15,17, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + static + const FT_Vector Null_Vector = {0,0}; + + +#undef PACK + + +#undef NULL_Vector +#define NULL_Vector (FT_Vector*)&Null_Vector + + + /*************************************************************************/ + /* */ + /* */ + /* Current_Ratio */ + /* */ + /* */ + /* Returns the current aspect ratio scaling factor depending on the */ + /* projection vector's state and device resolutions. */ + /* */ + /* */ + /* The aspect ratio in 16.16 format, always <= 1.0 . */ + /* */ + static + FT_Long Current_Ratio( EXEC_OP ) + { + if ( CUR.tt_metrics.ratio ) + return CUR.tt_metrics.ratio; + + if ( CUR.GS.projVector.y == 0 ) + CUR.tt_metrics.ratio = CUR.tt_metrics.x_ratio; + + else if ( CUR.GS.projVector.x == 0 ) + CUR.tt_metrics.ratio = CUR.tt_metrics.y_ratio; + + else + { + FT_Long x, y; + + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x4000 ); + y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x4000 ); + CUR.tt_metrics.ratio = Norm( x, y ); + +#else + + x = TT_MULDIV( CUR.GS.projVector.x, CUR.tt_metrics.x_ratio, 0x8000 ); + y = TT_MULDIV( CUR.GS.projVector.y, CUR.tt_metrics.y_ratio, 0x8000 ); + CUR.tt_metrics.ratio = FT_Sqrt32( x * x + y * y ) << 1; + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + } + + return CUR.tt_metrics.ratio; + } + + + static + FT_Long Current_Ppem( EXEC_OP ) + { + return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* Functions related to the control value table (CVT). */ + /* */ + /*************************************************************************/ + + + static + FT_F26Dot6 Read_CVT( EXEC_OP_ FT_ULong index ) + { + return CUR.cvt[index]; + } + + + static + FT_F26Dot6 Read_CVT_Stretched( EXEC_OP_ FT_ULong index ) + { + return TT_MULFIX( CUR.cvt[index], CURRENT_Ratio() ); + } + + + static + void Write_CVT( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] = value; + } + + + static + void Write_CVT_Stretched( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] = FT_DivFix( value, CURRENT_Ratio() ); + } + + + static + void Move_CVT( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] += value; + } + + + static + void Move_CVT_Stretched( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ) + { + CUR.cvt[index] += FT_DivFix( value, CURRENT_Ratio() ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* GetShortIns */ + /* */ + /* */ + /* Returns a short integer taken from the instruction stream at */ + /* address IP. */ + /* */ + /* */ + /* Short read at code[IP]. */ + /* */ + /* */ + /* This one could become a macro. */ + /* */ + static FT_Short GetShortIns( EXEC_OP ) + { + /* Reading a byte stream so there is no endianess (DaveP) */ + CUR.IP += 2; + return (FT_Short)( ( CUR.code[CUR.IP - 2] << 8 ) + + CUR.code[CUR.IP - 1] ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Ins_Goto_CodeRange */ + /* */ + /* */ + /* Goes to a certain code range in the instruction stream. */ + /* */ + /* */ + /* aRange :: The index of the code range. */ + /* */ + /* aIP :: The new IP address in the code range. */ + /* */ + /* */ + /* SUCCESS or FAILURE. */ + /* */ + static + FT_Bool Ins_Goto_CodeRange( EXEC_OP_ FT_Int aRange, + FT_ULong aIP ) + { + TT_CodeRange* range; + + + if ( aRange < 1 || aRange > 3 ) + { + CUR.error = TT_Err_Bad_Argument; + return FAILURE; + } + + range = &CUR.codeRangeTable[aRange - 1]; + + if ( range->base == NULL ) /* invalid coderange */ + { + CUR.error = TT_Err_Invalid_CodeRange; + return FAILURE; + } + + /* NOTE: Because the last instruction of a program may be a CALL */ + /* which will return to the first byte *after* the code */ + /* range, we test for AIP <= Size, instead of AIP < Size. */ + + if ( aIP > range->size ) + { + CUR.error = TT_Err_Code_Overflow; + return FAILURE; + } + + CUR.code = range->base; + CUR.codeSize = range->size; + CUR.IP = aIP; + CUR.curRange = aRange; + + return SUCCESS; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Direct_Move */ + /* */ + /* */ + /* Moves a point by a given distance along the freedom vector. The */ + /* point will be `touched'. */ + /* */ + /* */ + /* point :: The index of the point to move. */ + /* */ + /* distance :: The distance to apply. */ + /* */ + /* */ + /* zone :: The affected glyph zone. */ + /* */ + static + void Direct_Move( EXEC_OP_ TT_GlyphZone* zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_F26Dot6 v; + + + v = CUR.GS.freeVector.x; + + if ( v != 0 ) + { + +#ifdef NO_APPLE_PATENT + + if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD ) + zone->cur[point].x += distance; + +#else + + zone->cur[point].x += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + +#endif + + zone->tags[point] |= FT_Curve_Tag_Touch_X; + } + + v = CUR.GS.freeVector.y; + + if ( v != 0 ) + { + +#ifdef NO_APPLE_PATENT + + if ( ABS( CUR.F_dot_P ) > APPLE_THRESHOLD ) + zone->cur[point].y += distance; + +#else + + zone->cur[point].y += TT_MULDIV( distance, + v * 0x10000L, + CUR.F_dot_P ); + +#endif + + zone->tags[point] |= FT_Curve_Tag_Touch_Y; + } + } + + + /*************************************************************************/ + /* */ + /* Special versions of Direct_Move() */ + /* */ + /* The following versions are used whenever both vectors are both */ + /* along one of the coordinate unit vectors, i.e. in 90% of the cases. */ + /* */ + /*************************************************************************/ + + + static + void Direct_Move_X( EXEC_OP_ TT_GlyphZone* zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; + + zone->cur[point].x += distance; + zone->tags[point] |= FT_Curve_Tag_Touch_X; + } + + + static + void Direct_Move_Y( EXEC_OP_ TT_GlyphZone* zone, + FT_UShort point, + FT_F26Dot6 distance ) + { + FT_UNUSED_EXEC; + + zone->cur[point].y += distance; + zone->tags[point] |= FT_Curve_Tag_Touch_Y; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_None */ + /* */ + /* */ + /* Does not round, but adds engine compensation. */ + /* */ + /* */ + /* distance :: The distance (not) to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* The compensated distance. */ + /* */ + /* */ + /* The TrueType specification says very few about the relationship */ + /* between rounding and engine compensation. However, it seems from */ + /* the description of super round that we should add the compensation */ + /* before rounding. */ + /* */ + static + FT_F26Dot6 Round_None( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation; + if ( val < 0 ) + val = 0; + } + else { + val = distance - compensation; + if ( val > 0 ) + val = 0; + } + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Grid */ + /* */ + /* */ + /* Rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + static + FT_F26Dot6 Round_To_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation + 32; + if ( val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( ( compensation - distance + 32 ) & -64 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Half_Grid */ + /* */ + /* */ + /* Rounds value to half grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + static + FT_F26Dot6 Round_To_Half_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = ( ( distance + compensation ) & -64 ) + 32; + if ( val < 0 ) + val = 0; + } + else + { + val = -( ( (compensation - distance) & -64 ) + 32 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Down_To_Grid */ + /* */ + /* */ + /* Rounds value down to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + static + FT_F26Dot6 Round_Down_To_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation; + if ( val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( ( compensation - distance ) & -64 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Up_To_Grid */ + /* */ + /* */ + /* Rounds value up to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + static + FT_F26Dot6 Round_Up_To_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + + FT_UNUSED_EXEC; + + if ( distance >= 0 ) + { + val = distance + compensation + 63; + if ( val > 0 ) + val &= ~63; + else + val = 0; + } + else + { + val = -( ( compensation - distance + 63 ) & -64 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_To_Double_Grid */ + /* */ + /* */ + /* Rounds value to double grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + static + FT_F26Dot6 Round_To_Double_Grid( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + FT_UNUSED_EXEC; + + + if ( distance >= 0 ) + { + val = distance + compensation + 16; + if ( val > 0 ) + val &= ~31; + else + val = 0; + } + else + { + val = -( ( compensation - distance + 16 ) & -32 ); + if ( val > 0 ) + val = 0; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Super */ + /* */ + /* */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + /* */ + /* The TrueType specification says very few about the relationship */ + /* between rounding and engine compensation. However, it seems from */ + /* the description of super round that we should add the compensation */ + /* before rounding. */ + /* */ + static + FT_F26Dot6 Round_Super( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = ( distance - CUR.phase + CUR.threshold + compensation ) & + -CUR.period; + if ( val < 0 ) + val = 0; + val += CUR.phase; + } + else + { + val = -( ( CUR.threshold - CUR.phase - distance + compensation ) & + -CUR.period ); + if ( val > 0 ) + val = 0; + val -= CUR.phase; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Round_Super_45 */ + /* */ + /* */ + /* Super-rounds value to grid after adding engine compensation. */ + /* */ + /* */ + /* distance :: The distance to round. */ + /* */ + /* compensation :: The engine compensation. */ + /* */ + /* */ + /* Rounded distance. */ + /* */ + /* */ + /* There is a separate function for Round_Super_45() as we may need */ + /* greater precision. */ + /* */ + static + FT_F26Dot6 Round_Super_45( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ) + { + FT_F26Dot6 val; + + + if ( distance >= 0 ) + { + val = ( ( distance - CUR.phase + CUR.threshold + compensation ) / + CUR.period ) * CUR.period; + if ( val < 0 ) + val = 0; + val += CUR.phase; + } + else + { + val = -( ( ( CUR.threshold - CUR.phase - distance + compensation ) / + CUR.period ) * CUR.period ); + if ( val > 0 ) + val = 0; + val -= CUR.phase; + } + + return val; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Compute_Round */ + /* */ + /* */ + /* Sets the rounding mode. */ + /* */ + /* */ + /* round_mode :: The rounding mode to be used. */ + /* */ + static + void Compute_Round( EXEC_OP_ FT_Byte round_mode ) + { + switch ( round_mode ) + { + case TT_Round_Off: + CUR.func_round = (TT_Round_Func)Round_None; + break; + + case TT_Round_To_Grid: + CUR.func_round = (TT_Round_Func)Round_To_Grid; + break; + + case TT_Round_Up_To_Grid: + CUR.func_round = (TT_Round_Func)Round_Up_To_Grid; + break; + + case TT_Round_Down_To_Grid: + CUR.func_round = (TT_Round_Func)Round_Down_To_Grid; + break; + + case TT_Round_To_Half_Grid: + CUR.func_round = (TT_Round_Func)Round_To_Half_Grid; + break; + + case TT_Round_To_Double_Grid: + CUR.func_round = (TT_Round_Func)Round_To_Double_Grid; + break; + + case TT_Round_Super: + CUR.func_round = (TT_Round_Func)Round_Super; + break; + + case TT_Round_Super_45: + CUR.func_round = (TT_Round_Func)Round_Super_45; + break; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* SetSuperRound */ + /* */ + /* */ + /* Sets Super Round parameters. */ + /* */ + /* */ + /* GridPeriod :: Grid period */ + /* selector :: SROUND opcode */ + /* */ + static + void SetSuperRound( EXEC_OP_ FT_F26Dot6 GridPeriod, + FT_Long selector ) + { + switch ( (FT_Int)( selector & 0xC0 ) ) + { + case 0: + CUR.period = GridPeriod / 2; + break; + + case 0x40: + CUR.period = GridPeriod; + break; + + case 0x80: + CUR.period = GridPeriod * 2; + break; + + /* This opcode is reserved, but... */ + + case 0xC0: + CUR.period = GridPeriod; + break; + } + + switch ( (FT_Int)( selector & 0x30 ) ) + { + case 0: + CUR.phase = 0; + break; + + case 0x10: + CUR.phase = CUR.period / 4; + break; + + case 0x20: + CUR.phase = CUR.period / 2; + break; + + case 0x30: + CUR.phase = GridPeriod * 3 / 4; + break; + } + + if ( (selector & 0x0F) == 0 ) + CUR.threshold = CUR.period - 1; + else + CUR.threshold = ( (FT_Int)( selector & 0x0F ) - 4 ) * CUR.period / 8; + + CUR.period /= 256; + CUR.phase /= 256; + CUR.threshold /= 256; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project */ + /* */ + /* */ + /* Computes the projection of vector given by (v2-v1) along the */ + /* current projection vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* The distance in F26dot6 format. */ + /* */ + static + FT_F26Dot6 Project( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + return TT_MULDIV( v1->x - v2->x, CUR.GS.projVector.x, 0x4000 ) + + TT_MULDIV( v1->y - v2->y, CUR.GS.projVector.y, 0x4000 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Dual_Project */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current dual vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* The distance in F26dot6 format. */ + /* */ + static + FT_F26Dot6 Dual_Project( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + return TT_MULDIV( v1->x - v2->x, CUR.GS.dualVector.x, 0x4000 ) + + TT_MULDIV( v1->y - v2->y, CUR.GS.dualVector.y, 0x4000 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Free_Project */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* current freedom vector. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* The distance in F26dot6 format. */ + /* */ + static + FT_F26Dot6 Free_Project( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + return TT_MULDIV( v1->x - v2->x, CUR.GS.freeVector.x, 0x4000 ) + + TT_MULDIV( v1->y - v2->y, CUR.GS.freeVector.y, 0x4000 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project_x */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* horizontal axis. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* The distance in F26dot6 format. */ + /* */ + static + FT_F26Dot6 Project_x( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + FT_UNUSED_EXEC; + + return ( v1->x - v2->x ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Project_y */ + /* */ + /* */ + /* Computes the projection of the vector given by (v2-v1) along the */ + /* vertical axis. */ + /* */ + /* */ + /* v1 :: First input vector. */ + /* v2 :: Second input vector. */ + /* */ + /* */ + /* The distance in F26dot6 format. */ + /* */ + static + FT_F26Dot6 Project_y( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ) + { + FT_UNUSED_EXEC; + + return ( v1->y - v2->y ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Compute_Funcs */ + /* */ + /* */ + /* Computes the projection and movement function pointers according */ + /* to the current graphics state. */ + /* */ + static + void Compute_Funcs( EXEC_OP ) + { + if ( CUR.GS.freeVector.x == 0x4000 ) + { + CUR.func_freeProj = (TT_Project_Func)Project_x; + CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; + } + else + { + if ( CUR.GS.freeVector.y == 0x4000 ) + { + CUR.func_freeProj = (TT_Project_Func)Project_y; + CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; + } + else + { + CUR.func_freeProj = (TT_Project_Func)Free_Project; + CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + + (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4; + } + } + + if ( CUR.GS.projVector.x == 0x4000 ) + CUR.func_project = (TT_Project_Func)Project_x; + else + { + if ( CUR.GS.projVector.y == 0x4000 ) + CUR.func_project = (TT_Project_Func)Project_y; + else + CUR.func_project = (TT_Project_Func)Project; + } + + if ( CUR.GS.dualVector.x == 0x4000 ) + CUR.func_dualproj = (TT_Project_Func)Project_x; + else + { + if ( CUR.GS.dualVector.y == 0x4000 ) + CUR.func_dualproj = (TT_Project_Func)Project_y; + else + CUR.func_dualproj = (TT_Project_Func)Dual_Project; + } + + CUR.func_move = (TT_Move_Func)Direct_Move; + + if ( CUR.F_dot_P == 0x40000000L ) + { + if ( CUR.GS.freeVector.x == 0x4000 ) + CUR.func_move = (TT_Move_Func)Direct_Move_X; + else + { + if ( CUR.GS.freeVector.y == 0x4000 ) + CUR.func_move = (TT_Move_Func)Direct_Move_Y; + } + } + + /* at small sizes, F_dot_P can become too small, resulting */ + /* in overflows and `spikes' in a number of glyphs like `w'. */ + + if ( ABS( CUR.F_dot_P ) < 0x4000000L ) + CUR.F_dot_P = 0x40000000L; + + /* Disable cached aspect ratio */ + CUR.tt_metrics.ratio = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Normalize */ + /* */ + /* */ + /* Norms a vector. */ + /* */ + /* */ + /* Vx :: The horizontal input vector coordinate. */ + /* Vy :: The vertical input vector coordinate. */ + /* */ + /* */ + /* R :: The normed unit vector. */ + /* */ + /* */ + /* Returns FAILURE if a vector parameter is zero. */ + /* */ + /* */ + /* In case Vx and Vy are both zero, Normalize() returns SUCCESS, and */ + /* R is undefined. */ + /* */ + +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + static + FT_Bool Normalize( EXEC_OP_ FT_F26Dot6 Vx, + FT_F26Dot6 Vy, + FT_UnitVector* R ) + { + FT_F26Dot6 W; + FT_Bool S1, S2; + + FT_UNUSED_EXEC; + + + if ( ABS( Vx ) < 0x10000L && ABS( Vy ) < 0x10000L ) + { + Vx *= 0x100; + Vy *= 0x100; + + W = Norm( Vx, Vy ); + + if ( W == 0 ) + { + /* XXX: UNDOCUMENTED! It seems that it is possible to try */ + /* to normalize the vector (0,0). Return immediately. */ + return SUCCESS; + } + + R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W ); + R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W ); + + return SUCCESS; + } + + W = Norm( Vx, Vy ); + + Vx = FT_MulDiv( Vx, 0x4000L, W ); + Vy = FT_MulDiv( Vy, 0x4000L, W ); + + W = Vx * Vx + Vy * Vy; + + /* Now, we want that Sqrt( W ) = 0x4000 */ + /* Or 0x1000000 <= W < 0x1004000 */ + + if ( Vx < 0 ) + { + Vx = -Vx; + S1 = TRUE; + } + else + S1 = FALSE; + + if ( Vy < 0 ) + { + Vy = -Vy; + S2 = TRUE; + } + else + S2 = FALSE; + + while ( W < 0x1000000L ) + { + /* We need to increase W by a minimal amount */ + if ( Vx < Vy ) + Vx++; + else + Vy++; + + W = Vx * Vx + Vy * Vy; + } + + while ( W >= 0x1004000L ) + { + /* We need to decrease W by a minimal amount */ + if ( Vx < Vy ) + Vx--; + else + Vy--; + + W = Vx * Vx + Vy * Vy; + } + + /* Note that in various cases, we can only */ + /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */ + + if ( S1 ) + Vx = -Vx; + + if ( S2 ) + Vy = -Vy; + + R->x = (FT_F2Dot14)Vx; /* Type conversion */ + R->y = (FT_F2Dot14)Vy; /* Type conversion */ + + return SUCCESS; + } + +#else + + static + FT_Bool Normalize( EXEC_OP_ FT_F26Dot6 Vx, + FT_F26Dot6 Vy, + FT_UnitVector* R ) + { + FT_F26Dot6 u, v, d; + FT_Int shift; + FT_ULong H, L, L2, hi, lo, med; + + + u = ABS( Vx ); + v = ABS( Vy ); + + if ( u < v ) + { + d = u; + u = v; + v = d; + } + + R->x = 0; + R->y = 0; + + /* check that we are not trying to normalise zero! */ + if ( u == 0 ) + return SUCCESS; + + /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */ + hi = (FT_ULong)u >> 16; + lo = (FT_ULong)u & 0xFFFF; + med = hi * lo; + + H = hi * hi + ( med >> 15 ); + med <<= 17; + L = lo * lo + med; + if ( L < med ) + H++; + + hi = (FT_ULong)v >> 16; + lo = (FT_ULong)v & 0xFFFF; + med = hi * lo; + + H += hi * hi + ( med >> 15 ); + med <<= 17; + L2 = lo * lo + med; + if ( L2 < med ) + H++; + + L += L2; + if ( L < L2 ) + H++; + + /* if the value is smaller than 32-bits */ + if ( H == 0 ) + { + shift = 0; + while ( ( L & 0xC0000000L ) == 0 ) + { + L <<= 2; + shift++; + } + + d = FT_Sqrt32( L ); + R->x = (FT_F2Dot14)TT_MULDIV( Vx << shift, 0x4000, d ); + R->y = (FT_F2Dot14)TT_MULDIV( Vy << shift, 0x4000, d ); + } + /* if the value is greater than 64-bits */ + else + { + shift = 0; + while ( H ) + { + L = ( L >> 2 ) | ( H << 30 ); + H >>= 2; + shift++; + } + + d = FT_Sqrt32( L ); + R->x = (FT_F2Dot14)TT_MULDIV( Vx >> shift, 0x4000, d ); + R->y = (FT_F2Dot14)TT_MULDIV( Vy >> shift, 0x4000, d ); + } + + { + FT_ULong x, y, w; + FT_Int sx, sy; + + + sx = R->x >= 0 ? 1 : -1; + sy = R->y >= 0 ? 1 : -1; + x = (FT_ULong)sx * R->x; + y = (FT_ULong)sy * R->y; + + w = x * x + y * y; + + /* we now want to adjust (x,y) in order to have sqrt(w) == 0x4000 */ + /* which means 0x1000000 <= w < 0x1004000 */ + while ( w <= 0x10000000L ) + { + /* increment the smallest coordinate */ + if ( x < y ) + x++; + else + y++; + + w = x * x + y * y; + } + + while ( w >= 0x10040000L ) + { + /* decrement the smallest coordinate */ + if ( x < y ) + x--; + else + y--; + + w = x * x + y * y; + } + + R->x = sx * x; + R->y = sy * y; + } + + return SUCCESS; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + + + /*************************************************************************/ + /* */ + /* Here we start with the implementation of the various opcodes. */ + /* */ + /*************************************************************************/ + + + static + FT_Bool Ins_SxVTL( EXEC_OP_ FT_UShort aIdx1, + FT_UShort aIdx2, + FT_Int aOpc, + FT_UnitVector* Vec ) + { + FT_Long A, B, C; + FT_Vector* p1; + FT_Vector* p2; + + + if ( BOUNDS( aIdx1, CUR.zp2.n_points ) || + BOUNDS( aIdx2, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return FAILURE; + } + + p1 = CUR.zp1.cur + aIdx2; + p2 = CUR.zp2.cur + aIdx1; + + A = p1->x - p2->x; + B = p1->y - p2->y; + + if ( ( aOpc & 1 ) != 0 ) + { + C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, Vec ); + + return SUCCESS; + } + + + /* When not using the big switch statements, the interpreter uses a */ + /* call table defined later below in this source. Each opcode must */ + /* thus have a corresponding function, even trivial ones. */ + /* */ + /* They are all defined there. */ + +#define DO_SVTCA \ + { \ + FT_Short A, B; \ + \ + \ + A = (FT_Short)( CUR.opcode & 1 ) << 14; \ + B = A ^ (FT_Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.projVector.x = A; \ + CUR.GS.dualVector.x = A; \ + \ + CUR.GS.freeVector.y = B; \ + CUR.GS.projVector.y = B; \ + CUR.GS.dualVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTCA \ + { \ + FT_Short A, B; \ + \ + \ + A = (FT_Short)( CUR.opcode & 1 ) << 14; \ + B = A ^ (FT_Short)0x4000; \ + \ + CUR.GS.projVector.x = A; \ + CUR.GS.dualVector.x = A; \ + \ + CUR.GS.projVector.y = B; \ + CUR.GS.dualVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTCA \ + { \ + FT_Short A, B; \ + \ + \ + A = (FT_Short)( CUR.opcode & 1 ) << 14; \ + B = A ^ (FT_Short)0x4000; \ + \ + CUR.GS.freeVector.x = A; \ + CUR.GS.freeVector.y = B; \ + \ + COMPUTE_Funcs(); \ + } + + +#define DO_SPVTL \ + if ( INS_SxVTL( (FT_UShort)args[1], \ + (FT_UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.projVector ) == SUCCESS ) \ + { \ + CUR.GS.dualVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVTL \ + if ( INS_SxVTL( (FT_UShort)args[1], \ + (FT_UShort)args[0], \ + CUR.opcode, \ + &CUR.GS.freeVector ) == SUCCESS ) \ + COMPUTE_Funcs(); + + +#define DO_SFVTPV \ + CUR.GS.freeVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); + + +#define DO_SPVFS \ + { \ + FT_Short S; \ + FT_Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (FT_Short)args[1]; \ + Y = (FT_Long)S; \ + S = (FT_Short)args[0]; \ + X = (FT_Long)S; \ + \ + NORMalize( X, Y, &CUR.GS.projVector ); \ + \ + CUR.GS.dualVector = CUR.GS.projVector; \ + COMPUTE_Funcs(); \ + } + + +#define DO_SFVFS \ + { \ + FT_Short S; \ + FT_Long X, Y; \ + \ + \ + /* Only use low 16bits, then sign extend */ \ + S = (FT_Short)args[1]; \ + Y = (FT_Long)S; \ + S = (FT_Short)args[0]; \ + X = S; \ + \ + NORMalize( X, Y, &CUR.GS.freeVector ); \ + COMPUTE_Funcs(); \ + } + + +#define DO_GPV \ + args[0] = CUR.GS.projVector.x; \ + args[1] = CUR.GS.projVector.y; + + +#define DO_GFV \ + args[0] = CUR.GS.freeVector.x; \ + args[1] = CUR.GS.freeVector.y; + + +#define DO_SRP0 \ + CUR.GS.rp0 = (FT_UShort)args[0]; + + +#define DO_SRP1 \ + CUR.GS.rp1 = (FT_UShort)args[0]; + + +#define DO_SRP2 \ + CUR.GS.rp2 = (FT_UShort)args[0]; + + +#define DO_RTHG \ + CUR.GS.round_state = TT_Round_To_Half_Grid; \ + CUR.func_round = (TT_Round_Func)Round_To_Half_Grid; + + +#define DO_RTG \ + CUR.GS.round_state = TT_Round_To_Grid; \ + CUR.func_round = (TT_Round_Func)Round_To_Grid; + + +#define DO_RTDG \ + CUR.GS.round_state = TT_Round_To_Double_Grid; \ + CUR.func_round = (TT_Round_Func)Round_To_Double_Grid; + + +#define DO_RUTG \ + CUR.GS.round_state = TT_Round_Up_To_Grid; \ + CUR.func_round = (TT_Round_Func)Round_Up_To_Grid; + + +#define DO_RDTG \ + CUR.GS.round_state = TT_Round_Down_To_Grid; \ + CUR.func_round = (TT_Round_Func)Round_Down_To_Grid; + + +#define DO_ROFF \ + CUR.GS.round_state = TT_Round_Off; \ + CUR.func_round = (TT_Round_Func)Round_None; + + +#define DO_SROUND \ + SET_SuperRound( 0x4000, args[0] ); \ + CUR.GS.round_state = TT_Round_Super; \ + CUR.func_round = (TT_Round_Func)Round_Super; + + +#define DO_S45ROUND \ + SET_SuperRound( 0x2D41, args[0] ); \ + CUR.GS.round_state = TT_Round_Super_45; \ + CUR.func_round = (TT_Round_Func)Round_Super_45; + + +#define DO_SLOOP \ + if ( args[0] < 0 ) \ + CUR.error = TT_Err_Bad_Argument; \ + else \ + CUR.GS.loop = args[0]; + + +#define DO_SMD \ + CUR.GS.minimum_distance = args[0]; + + +#define DO_SCVTCI \ + CUR.GS.control_value_cutin = (FT_F26Dot6)args[0]; + + +#define DO_SSWCI \ + CUR.GS.single_width_cutin = (FT_F26Dot6)args[0]; + + + /* XXX: UNDOCUMENTED! or bug in the Windows engine? */ + /* */ + /* It seems that the value that is read here is */ + /* expressed in 16.16 format rather than in font */ + /* units. */ + /* */ +#define DO_SSW \ + CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 ); + + +#define DO_FLIPON \ + CUR.GS.auto_flip = TRUE; + + +#define DO_FLIPOFF \ + CUR.GS.auto_flip = FALSE; + + +#define DO_SDB \ + CUR.GS.delta_base = (FT_Short)args[0]; + + +#define DO_SDS \ + CUR.GS.delta_shift = (FT_Short)args[0]; + + +#define DO_MD /* nothing */ + + +#define DO_MPPEM \ + args[0] = CURRENT_Ppem(); + + + /* Note: The pointSize should be irrelevant in a given font program; */ + /* we thus decide to return only the ppem. */ +#if 0 + +#define DO_MPS \ + args[0] = CUR.metrics.pointSize; + +#else + +#define DO_MPS \ + args[0] = CURRENT_Ppem(); + +#endif /* 0 */ + + +#define DO_DUP \ + args[1] = args[0]; + + +#define DO_CLEAR \ + CUR.new_top = 0; + + +#define DO_SWAP \ + { \ + FT_Long L; \ + \ + \ + L = args[0]; \ + args[0] = args[1]; \ + args[1] = L; \ + } + + +#define DO_DEPTH \ + args[0] = CUR.top; + + +#define DO_CINDEX \ + { \ + FT_Long L; \ + \ + \ + L = args[0]; \ + \ + if ( L <= 0 || L > CUR.args ) \ + CUR.error = TT_Err_Invalid_Reference; \ + else \ + args[0] = CUR.stack[CUR.args - L]; \ + } + + +#define DO_JROT \ + if ( args[1] != 0 ) \ + { \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; \ + } + + +#define DO_JMPR \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; + + +#define DO_JROF \ + if ( args[1] == 0 ) \ + { \ + CUR.IP += args[0]; \ + CUR.step_ins = FALSE; \ + } + + +#define DO_LT \ + args[0] = ( args[0] < args[1] ); + + +#define DO_LTEQ \ + args[0] = ( args[0] <= args[1] ); + + +#define DO_GT \ + args[0] = ( args[0] > args[1] ); + + +#define DO_GTEQ \ + args[0] = ( args[0] >= args[1] ); + + +#define DO_EQ \ + args[0] = ( args[0] == args[1] ); + + +#define DO_NEQ \ + args[0] = ( args[0] != args[1] ); + + +#define DO_ODD \ + args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 64 ); + + +#define DO_EVEN \ + args[0] = ( ( CUR_Func_round( args[0], 0 ) & 127 ) == 0 ); + + +#define DO_AND \ + args[0] = ( args[0] && args[1] ); + + +#define DO_OR \ + args[0] = ( args[0] || args[1] ); + + +#define DO_NOT \ + args[0] = !args[0]; + + +#define DO_ADD \ + args[0] += args[1]; + + +#define DO_SUB \ + args[0] -= args[1]; + + +#define DO_DIV \ + if ( args[1] == 0 ) \ + CUR.error = TT_Err_Divide_By_Zero; \ + else \ + args[0] = TT_MULDIV( args[0], 64L, args[1] ); + + +#define DO_MUL \ + args[0] = TT_MULDIV( args[0], args[1], 64L ); + + +#define DO_ABS \ + args[0] = ABS( args[0] ); + + +#define DO_NEG \ + args[0] = -args[0]; + + +#define DO_FLOOR \ + args[0] &= -64; + + +#define DO_CEILING \ + args[0] = ( args[0] + 63 ) & -64; + + +#define DO_RS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR.storage[I]; \ + } + + +#define DO_WS \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.storeSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.storage[I] = args[1]; \ + } + + +#define DO_RCVT \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + else \ + args[0] = 0; \ + } \ + else \ + args[0] = CUR_Func_read_cvt( I ); \ + } + + +#define DO_WCVTP \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR_Func_write_cvt( I, args[1] ); \ + } + + +#define DO_WCVTF \ + { \ + FT_ULong I = (FT_ULong)args[0]; \ + \ + \ + if ( BOUNDS( I, CUR.cvtSize ) ) \ + { \ + if ( CUR.pedantic_hinting ) \ + { \ + ARRAY_BOUND_ERROR; \ + } \ + } \ + else \ + CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \ + } + + +#define DO_DEBUG \ + CUR.error = TT_Err_Debug_OpCode; + + +#define DO_ROUND \ + args[0] = CUR_Func_round( \ + args[0], \ + CUR.tt_metrics.compensations[CUR.opcode - 0x68] ); + + +#define DO_NROUND \ + args[0] = ROUND_None( args[0], \ + CUR.tt_metrics.compensations[CUR.opcode - 0x6C] ); + + +#define DO_MAX \ + if ( args[1] > args[0] ) \ + args[0] = args[1]; + + +#define DO_MIN \ + if ( args[1] < args[0] ) \ + args[0] = args[1]; + + +#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + +#undef ARRAY_BOUND_ERROR +#define ARRAY_BOUND_ERROR \ + { \ + CUR.error = TT_Err_Invalid_Reference; \ + return; \ + } + + + /*************************************************************************/ + /* */ + /* SVTCA[a]: Set (F and P) Vectors to Coordinate Axis */ + /* Opcode range: 0x00-0x01 */ + /* Stack: --> */ + /* */ + static + void Ins_SVTCA( INS_ARG ) + { + DO_SVTCA + } + + + /*************************************************************************/ + /* */ + /* SPVTCA[a]: Set PVector to Coordinate Axis */ + /* Opcode range: 0x02-0x03 */ + /* Stack: --> */ + /* */ + static + void Ins_SPVTCA( INS_ARG ) + { + DO_SPVTCA + } + + + /*************************************************************************/ + /* */ + /* SFVTCA[a]: Set FVector to Coordinate Axis */ + /* Opcode range: 0x04-0x05 */ + /* Stack: --> */ + /* */ + static + void Ins_SFVTCA( INS_ARG ) + { + DO_SFVTCA + } + + + /*************************************************************************/ + /* */ + /* SPVTL[a]: Set PVector To Line */ + /* Opcode range: 0x06-0x07 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_SPVTL( INS_ARG ) + { + DO_SPVTL + } + + + /*************************************************************************/ + /* */ + /* SFVTL[a]: Set FVector To Line */ + /* Opcode range: 0x08-0x09 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_SFVTL( INS_ARG ) + { + DO_SFVTL + } + + + /*************************************************************************/ + /* */ + /* SFVTPV[]: Set FVector To PVector */ + /* Opcode range: 0x0E */ + /* Stack: --> */ + /* */ + static + void Ins_SFVTPV( INS_ARG ) + { + DO_SFVTPV + } + + + /*************************************************************************/ + /* */ + /* SPVFS[]: Set PVector From Stack */ + /* Opcode range: 0x0A */ + /* Stack: f2.14 f2.14 --> */ + /* */ + static + void Ins_SPVFS( INS_ARG ) + { + DO_SPVFS + } + + + /*************************************************************************/ + /* */ + /* SFVFS[]: Set FVector From Stack */ + /* Opcode range: 0x0B */ + /* Stack: f2.14 f2.14 --> */ + /* */ + static + void Ins_SFVFS( INS_ARG ) + { + DO_SFVFS + } + + + /*************************************************************************/ + /* */ + /* GPV[]: Get Projection Vector */ + /* Opcode range: 0x0C */ + /* Stack: ef2.14 --> ef2.14 */ + /* */ + static + void Ins_GPV( INS_ARG ) + { + DO_GPV + } + + + /*************************************************************************/ + /* GFV[]: Get Freedom Vector */ + /* Opcode range: 0x0D */ + /* Stack: ef2.14 --> ef2.14 */ + /* */ + static + void Ins_GFV( INS_ARG ) + { + DO_GFV + } + + + /*************************************************************************/ + /* */ + /* SRP0[]: Set Reference Point 0 */ + /* Opcode range: 0x10 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SRP0( INS_ARG ) + { + DO_SRP0 + } + + + /*************************************************************************/ + /* */ + /* SRP1[]: Set Reference Point 1 */ + /* Opcode range: 0x11 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SRP1( INS_ARG ) + { + DO_SRP1 + } + + + /*************************************************************************/ + /* */ + /* SRP2[]: Set Reference Point 2 */ + /* Opcode range: 0x12 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SRP2( INS_ARG ) + { + DO_SRP2 + } + + + /*************************************************************************/ + /* */ + /* RTHG[]: Round To Half Grid */ + /* Opcode range: 0x19 */ + /* Stack: --> */ + /* */ + static + void Ins_RTHG( INS_ARG ) + { + DO_RTHG + } + + + /*************************************************************************/ + /* */ + /* RTG[]: Round To Grid */ + /* Opcode range: 0x18 */ + /* Stack: --> */ + /* */ + static + void Ins_RTG( INS_ARG ) + { + DO_RTG + } + + + /*************************************************************************/ + /* RTDG[]: Round To Double Grid */ + /* Opcode range: 0x3D */ + /* Stack: --> */ + /* */ + static + void Ins_RTDG( INS_ARG ) + { + DO_RTDG + } + + + /*************************************************************************/ + /* RUTG[]: Round Up To Grid */ + /* Opcode range: 0x7C */ + /* Stack: --> */ + /* */ + static + void Ins_RUTG( INS_ARG ) + { + DO_RUTG + } + + + /*************************************************************************/ + /* */ + /* RDTG[]: Round Down To Grid */ + /* Opcode range: 0x7D */ + /* Stack: --> */ + /* */ + static + void Ins_RDTG( INS_ARG ) + { + DO_RDTG + } + + + /*************************************************************************/ + /* */ + /* ROFF[]: Round OFF */ + /* Opcode range: 0x7A */ + /* Stack: --> */ + /* */ + static + void Ins_ROFF( INS_ARG ) + { + DO_ROFF + } + + + /*************************************************************************/ + /* */ + /* SROUND[]: Super ROUND */ + /* Opcode range: 0x76 */ + /* Stack: Eint8 --> */ + /* */ + static + void Ins_SROUND( INS_ARG ) + { + DO_SROUND + } + + + /*************************************************************************/ + /* */ + /* S45ROUND[]: Super ROUND 45 degrees */ + /* Opcode range: 0x77 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_S45ROUND( INS_ARG ) + { + DO_S45ROUND + } + + + /*************************************************************************/ + /* */ + /* SLOOP[]: Set LOOP variable */ + /* Opcode range: 0x17 */ + /* Stack: int32? --> */ + /* */ + static + void Ins_SLOOP( INS_ARG ) + { + DO_SLOOP + } + + + /*************************************************************************/ + /* */ + /* SMD[]: Set Minimum Distance */ + /* Opcode range: 0x1A */ + /* Stack: f26.6 --> */ + /* */ + static + void Ins_SMD( INS_ARG ) + { + DO_SMD + } + + + /*************************************************************************/ + /* */ + /* SCVTCI[]: Set Control Value Table Cut In */ + /* Opcode range: 0x1D */ + /* Stack: f26.6 --> */ + /* */ + static + void Ins_SCVTCI( INS_ARG ) + { + DO_SCVTCI + } + + + /*************************************************************************/ + /* */ + /* SSWCI[]: Set Single Width Cut In */ + /* Opcode range: 0x1E */ + /* Stack: f26.6 --> */ + /* */ + static + void Ins_SSWCI( INS_ARG ) + { + DO_SSWCI + } + + + /*************************************************************************/ + /* */ + /* SSW[]: Set Single Width */ + /* Opcode range: 0x1F */ + /* Stack: int32? --> */ + /* */ + static + void Ins_SSW( INS_ARG ) + { + DO_SSW + } + + + /*************************************************************************/ + /* */ + /* FLIPON[]: Set auto-FLIP to ON */ + /* Opcode range: 0x4D */ + /* Stack: --> */ + /* */ + static + void Ins_FLIPON( INS_ARG ) + { + DO_FLIPON + } + + + /*************************************************************************/ + /* */ + /* FLIPOFF[]: Set auto-FLIP to OFF */ + /* Opcode range: 0x4E */ + /* Stack: --> */ + /* */ + static + void Ins_FLIPOFF( INS_ARG ) + { + DO_FLIPOFF + } + + + /*************************************************************************/ + /* */ + /* SANGW[]: Set ANGle Weight */ + /* Opcode range: 0x7E */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SANGW( INS_ARG ) + { + /* instruction not supported anymore */ + } + + + /*************************************************************************/ + /* */ + /* SDB[]: Set Delta Base */ + /* Opcode range: 0x5E */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SDB( INS_ARG ) + { + DO_SDB + } + + + /*************************************************************************/ + /* */ + /* SDS[]: Set Delta Shift */ + /* Opcode range: 0x5F */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SDS( INS_ARG ) + { + DO_SDS + } + + + /*************************************************************************/ + /* */ + /* MPPEM[]: Measure Pixel Per EM */ + /* Opcode range: 0x4B */ + /* Stack: --> Euint16 */ + /* */ + static + void Ins_MPPEM( INS_ARG ) + { + DO_MPPEM + } + + + /*************************************************************************/ + /* */ + /* MPS[]: Measure Point Size */ + /* Opcode range: 0x4C */ + /* Stack: --> Euint16 */ + /* */ + static + void Ins_MPS( INS_ARG ) + { + DO_MPS + } + + + /*************************************************************************/ + /* */ + /* DUP[]: DUPlicate the top stack's element */ + /* Opcode range: 0x20 */ + /* Stack: StkElt --> StkElt StkElt */ + /* */ + static + void Ins_DUP( INS_ARG ) + { + DO_DUP + } + + + /*************************************************************************/ + /* */ + /* POP[]: POP the stack's top element */ + /* Opcode range: 0x21 */ + /* Stack: StkElt --> */ + /* */ + static + void Ins_POP( INS_ARG ) + { + /* nothing to do */ + } + + + /*************************************************************************/ + /* */ + /* CLEAR[]: CLEAR the entire stack */ + /* Opcode range: 0x22 */ + /* Stack: StkElt... --> */ + /* */ + static + void Ins_CLEAR( INS_ARG ) + { + DO_CLEAR + } + + + /*************************************************************************/ + /* */ + /* SWAP[]: SWAP the stack's top two elements */ + /* Opcode range: 0x23 */ + /* Stack: 2 * StkElt --> 2 * StkElt */ + /* */ + static + void Ins_SWAP( INS_ARG ) + { + DO_SWAP + } + + + /*************************************************************************/ + /* */ + /* DEPTH[]: return the stack DEPTH */ + /* Opcode range: 0x24 */ + /* Stack: --> uint32 */ + /* */ + static + void Ins_DEPTH( INS_ARG ) + { + DO_DEPTH + } + + + /*************************************************************************/ + /* */ + /* CINDEX[]: Copy INDEXed element */ + /* Opcode range: 0x25 */ + /* Stack: int32 --> StkElt */ + /* */ + static + void Ins_CINDEX( INS_ARG ) + { + DO_CINDEX + } + + + /*************************************************************************/ + /* */ + /* EIF[]: End IF */ + /* Opcode range: 0x59 */ + /* Stack: --> */ + /* */ + static + void Ins_EIF( INS_ARG ) + { + /* nothing to do */ + } + + + /*************************************************************************/ + /* */ + /* JROT[]: Jump Relative On True */ + /* Opcode range: 0x78 */ + /* Stack: StkElt int32 --> */ + /* */ + static + void Ins_JROT( INS_ARG ) + { + DO_JROT + } + + + /*************************************************************************/ + /* */ + /* JMPR[]: JuMP Relative */ + /* Opcode range: 0x1C */ + /* Stack: int32 --> */ + /* */ + static + void Ins_JMPR( INS_ARG ) + { + DO_JMPR + } + + + /*************************************************************************/ + /* */ + /* JROF[]: Jump Relative On False */ + /* Opcode range: 0x79 */ + /* Stack: StkElt int32 --> */ + /* */ + static + void Ins_JROF( INS_ARG ) + { + DO_JROF + } + + + /*************************************************************************/ + /* */ + /* LT[]: Less Than */ + /* Opcode range: 0x50 */ + /* Stack: int32? int32? --> bool */ + /* */ + static + void Ins_LT( INS_ARG ) + { + DO_LT + } + + + /*************************************************************************/ + /* */ + /* LTEQ[]: Less Than or EQual */ + /* Opcode range: 0x51 */ + /* Stack: int32? int32? --> bool */ + /* */ + static + void Ins_LTEQ( INS_ARG ) + { + DO_LTEQ + } + + + /*************************************************************************/ + /* */ + /* GT[]: Greater Than */ + /* Opcode range: 0x52 */ + /* Stack: int32? int32? --> bool */ + /* */ + static + void Ins_GT( INS_ARG ) + { + DO_GT + } + + + /*************************************************************************/ + /* */ + /* GTEQ[]: Greater Than or EQual */ + /* Opcode range: 0x53 */ + /* Stack: int32? int32? --> bool */ + /* */ + static + void Ins_GTEQ( INS_ARG ) + { + DO_GTEQ + } + + + /*************************************************************************/ + /* */ + /* EQ[]: EQual */ + /* Opcode range: 0x54 */ + /* Stack: StkElt StkElt --> bool */ + /* */ + static + void Ins_EQ( INS_ARG ) + { + DO_EQ + } + + + /*************************************************************************/ + /* */ + /* NEQ[]: Not EQual */ + /* Opcode range: 0x55 */ + /* Stack: StkElt StkElt --> bool */ + /* */ + static + void Ins_NEQ( INS_ARG ) + { + DO_NEQ + } + + + /*************************************************************************/ + /* */ + /* ODD[]: Is ODD */ + /* Opcode range: 0x56 */ + /* Stack: f26.6 --> bool */ + /* */ + static + void Ins_ODD( INS_ARG ) + { + DO_ODD + } + + + /*************************************************************************/ + /* */ + /* EVEN[]: Is EVEN */ + /* Opcode range: 0x57 */ + /* Stack: f26.6 --> bool */ + /* */ + static + void Ins_EVEN( INS_ARG ) + { + DO_EVEN + } + + + /*************************************************************************/ + /* */ + /* AND[]: logical AND */ + /* Opcode range: 0x5A */ + /* Stack: uint32 uint32 --> uint32 */ + /* */ + static + void Ins_AND( INS_ARG ) + { + DO_AND + } + + + /*************************************************************************/ + /* */ + /* OR[]: logical OR */ + /* Opcode range: 0x5B */ + /* Stack: uint32 uint32 --> uint32 */ + /* */ + static + void Ins_OR( INS_ARG ) + { + DO_OR + } + + + /*************************************************************************/ + /* */ + /* NOT[]: logical NOT */ + /* Opcode range: 0x5C */ + /* Stack: StkElt --> uint32 */ + /* */ + static + void Ins_NOT( INS_ARG ) + { + DO_NOT + } + + + /*************************************************************************/ + /* */ + /* ADD[]: ADD */ + /* Opcode range: 0x60 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static + void Ins_ADD( INS_ARG ) + { + DO_ADD + } + + + /*************************************************************************/ + /* */ + /* SUB[]: SUBtract */ + /* Opcode range: 0x61 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static + void Ins_SUB( INS_ARG ) + { + DO_SUB + } + + + /*************************************************************************/ + /* */ + /* DIV[]: DIVide */ + /* Opcode range: 0x62 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static + void Ins_DIV( INS_ARG ) + { + DO_DIV + } + + + /*************************************************************************/ + /* */ + /* MUL[]: MULtiply */ + /* Opcode range: 0x63 */ + /* Stack: f26.6 f26.6 --> f26.6 */ + /* */ + static + void Ins_MUL( INS_ARG ) + { + DO_MUL + } + + + /*************************************************************************/ + /* */ + /* ABS[]: ABSolute value */ + /* Opcode range: 0x64 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static + void Ins_ABS( INS_ARG ) + { + DO_ABS + } + + + /*************************************************************************/ + /* */ + /* NEG[]: NEGate */ + /* Opcode range: 0x65 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static + void Ins_NEG( INS_ARG ) + { + DO_NEG + } + + + /*************************************************************************/ + /* */ + /* FLOOR[]: FLOOR */ + /* Opcode range: 0x66 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static + void Ins_FLOOR( INS_ARG ) + { + DO_FLOOR + } + + + /*************************************************************************/ + /* */ + /* CEILING[]: CEILING */ + /* Opcode range: 0x67 */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static + void Ins_CEILING( INS_ARG ) + { + DO_CEILING + } + + + /*************************************************************************/ + /* */ + /* RS[]: Read Store */ + /* Opcode range: 0x43 */ + /* Stack: uint32 --> uint32 */ + /* */ + static + void Ins_RS( INS_ARG ) + { + DO_RS + } + + + /*************************************************************************/ + /* */ + /* WS[]: Write Store */ + /* Opcode range: 0x42 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_WS( INS_ARG ) + { + DO_WS + } + + + /*************************************************************************/ + /* */ + /* WCVTP[]: Write CVT in Pixel units */ + /* Opcode range: 0x44 */ + /* Stack: f26.6 uint32 --> */ + /* */ + static + void Ins_WCVTP( INS_ARG ) + { + DO_WCVTP + } + + + /*************************************************************************/ + /* */ + /* WCVTF[]: Write CVT in Funits */ + /* Opcode range: 0x70 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_WCVTF( INS_ARG ) + { + DO_WCVTF + } + + + /*************************************************************************/ + /* */ + /* RCVT[]: Read CVT */ + /* Opcode range: 0x45 */ + /* Stack: uint32 --> f26.6 */ + /* */ + static + void Ins_RCVT( INS_ARG ) + { + DO_RCVT + } + + + /*************************************************************************/ + /* */ + /* AA[]: Adjust Angle */ + /* Opcode range: 0x7F */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_AA( INS_ARG ) + { + /* intentionally no longer supported */ + } + + + /*************************************************************************/ + /* */ + /* DEBUG[]: DEBUG. Unsupported. */ + /* Opcode range: 0x4F */ + /* Stack: uint32 --> */ + /* */ + /* Note: The original instruction pops a value from the stack. */ + /* */ + static + void Ins_DEBUG( INS_ARG ) + { + DO_DEBUG + } + + + /*************************************************************************/ + /* */ + /* ROUND[ab]: ROUND value */ + /* Opcode range: 0x68-0x6B */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static + void Ins_ROUND( INS_ARG ) + { + DO_ROUND + } + + + /*************************************************************************/ + /* */ + /* NROUND[ab]: No ROUNDing of value */ + /* Opcode range: 0x6C-0x6F */ + /* Stack: f26.6 --> f26.6 */ + /* */ + static + void Ins_NROUND( INS_ARG ) + { + DO_NROUND + } + + + /*************************************************************************/ + /* */ + /* MAX[]: MAXimum */ + /* Opcode range: 0x68 */ + /* Stack: int32? int32? --> int32 */ + /* */ + static + void Ins_MAX( INS_ARG ) + { + DO_MAX + } + + + /*************************************************************************/ + /* */ + /* MIN[]: MINimum */ + /* Opcode range: 0x69 */ + /* Stack: int32? int32? --> int32 */ + /* */ + static + void Ins_MIN( INS_ARG ) + { + DO_MIN + } + + +#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + + /*************************************************************************/ + /* */ + /* The following functions are called as is within the switch statement. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* MINDEX[]: Move INDEXed element */ + /* Opcode range: 0x26 */ + /* Stack: int32? --> StkElt */ + /* */ + static + void Ins_MINDEX( INS_ARG ) + { + FT_Long L, K; + + + L = args[0]; + + if ( L <= 0 || L > CUR.args ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + K = CUR.stack[CUR.args - L]; + + MEM_Move( &CUR.stack[CUR.args - L ], + &CUR.stack[CUR.args - L + 1], + ( L - 1 ) * sizeof ( FT_Long ) ); + + CUR.stack[CUR.args - 1] = K; + } + + + /*************************************************************************/ + /* */ + /* ROLL[]: ROLL top three elements */ + /* Opcode range: 0x8A */ + /* Stack: 3 * StkElt --> 3 * StkElt */ + /* */ + static + void Ins_ROLL( INS_ARG ) + { + FT_Long A, B, C; + + FT_UNUSED_EXEC; + + + A = args[2]; + B = args[1]; + C = args[0]; + + args[2] = C; + args[1] = A; + args[0] = B; + } + + + /*************************************************************************/ + /* */ + /* MANAGING THE FLOW OF CONTROL */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + static + FT_Bool SkipCode( EXEC_OP ) + { + CUR.IP += CUR.length; + + if ( CUR.IP < CUR.codeSize ) + { + CUR.opcode = CUR.code[CUR.IP]; + + CUR.length = opcode_length[CUR.opcode]; + if ( CUR.length < 0 ) + { + if ( CUR.IP + 1 > CUR.codeSize ) + goto Fail_Overflow; + CUR.length = CUR.code[CUR.IP + 1] + 2; + } + + if ( CUR.IP + CUR.length <= CUR.codeSize ) + return SUCCESS; + } + + Fail_Overflow: + CUR.error = TT_Err_Code_Overflow; + return FAILURE; + } + + + /*************************************************************************/ + /* */ + /* IF[]: IF test */ + /* Opcode range: 0x58 */ + /* Stack: StkElt --> */ + /* */ + static + void Ins_IF( INS_ARG ) + { + FT_Int nIfs; + FT_Bool Out; + + + if ( args[0] != 0 ) + return; + + nIfs = 1; + Out = 0; + + do + { + if ( SKIP_Code() == FAILURE ) + return; + + switch ( CUR.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x1B: /* ELSE */ + Out = ( nIfs == 1 ); + break; + + case 0x59: /* EIF */ + nIfs--; + Out = ( nIfs == 0 ); + break; + } + } while ( Out == 0 ); + } + + + /*************************************************************************/ + /* */ + /* ELSE[]: ELSE */ + /* Opcode range: 0x1B */ + /* Stack: --> */ + /* */ + static + void Ins_ELSE( INS_ARG ) + { + FT_Int nIfs; + + FT_UNUSED_ARG; + + + nIfs = 1; + + do + { + if ( SKIP_Code() == FAILURE ) + return; + + switch ( CUR.opcode ) + { + case 0x58: /* IF */ + nIfs++; + break; + + case 0x59: /* EIF */ + nIfs--; + break; + } + } while ( nIfs != 0 ); + } + + + /*************************************************************************/ + /* */ + /* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* FDEF[]: Function DEFinition */ + /* Opcode range: 0x2C */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_FDEF( INS_ARG ) + { + FT_ULong n; + TT_DefRecord* rec; + TT_DefRecord* limit; + + + /* some font programs are broken enough to redefine functions! */ + /* We will then parse the current table. */ + + rec = CUR.FDefs; + limit = rec + CUR.numFDefs; + n = args[0]; + + for ( ; rec < limit; rec++ ) + { + if ( rec->opc == n ) + break; + } + + if ( rec == limit ) + { + /* check that there is enough room for new functions */ + if ( CUR.numFDefs >= CUR.maxFDefs ) + { + CUR.error = TT_Err_Too_Many_Function_Defs; + return; + } + CUR.numFDefs++; + } + + rec->range = CUR.curRange; + rec->opc = n; + rec->start = CUR.IP + 1; + rec->active = TRUE; + + if ( n > CUR.maxFunc ) + CUR.maxFunc = n; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFS & FDEFs. */ + + while ( SKIP_Code() == SUCCESS ) + { + switch ( CUR.opcode ) + { + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ + CUR.error = TT_Err_Nested_DEFS; + return; + + case 0x2D: /* ENDF */ + return; + } + } + } + + + /*************************************************************************/ + /* */ + /* ENDF[]: END Function definition */ + /* Opcode range: 0x2D */ + /* Stack: --> */ + /* */ + static + void Ins_ENDF( INS_ARG ) + { + TT_CallRec* pRec; + + FT_UNUSED_ARG; + + + if ( CUR.callTop <= 0 ) /* We encountered an ENDF without a call */ + { + CUR.error = TT_Err_ENDF_In_Exec_Stream; + return; + } + + CUR.callTop--; + + pRec = &CUR.callStack[CUR.callTop]; + + pRec->Cur_Count--; + + CUR.step_ins = FALSE; + + if ( pRec->Cur_Count > 0 ) + { + CUR.callTop++; + CUR.IP = pRec->Cur_Restart; + } + else + /* Loop through the current function */ + INS_Goto_CodeRange( pRec->Caller_Range, + pRec->Caller_IP ); + + /* Exit the current call frame. */ + + /* NOTE: If the last intruction of a program is a */ + /* CALL or LOOPCALL, the return address is */ + /* always out of the code range. This is a */ + /* valid address, and it is why we do not test */ + /* the result of Ins_Goto_CodeRange() here! */ + } + + + /*************************************************************************/ + /* */ + /* CALL[]: CALL function */ + /* Opcode range: 0x2B */ + /* Stack: uint32? --> */ + /* */ + static + void Ins_CALL( INS_ARG ) + { + FT_ULong F; + TT_CallRec* pCrec; + TT_DefRecord* def; + + + /* first of all, check the index */ + + F = args[0]; + if ( BOUNDS( F, CUR.maxFunc + 1 ) ) + goto Fail; + + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font are defined in increasing order, starting from 0. This */ + /* means that we normally have */ + /* */ + /* CUR.maxFunc+1 == CUR.numFDefs */ + /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */ + /* */ + /* If this isn't true, we need to look up the function table. */ + + def = CUR.FDefs + F; + if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F ) + { + /* look up the FDefs table */ + TT_DefRecord* limit; + + + def = CUR.FDefs; + limit = def + CUR.numFDefs; + + while ( def < limit && def->opc != F ) + def++; + + if ( def == limit ) + goto Fail; + } + + /* check that the function is active */ + if ( !def->active ) + goto Fail; + + /* check the call stack */ + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + pCrec = CUR.callStack + CUR.callTop; + + pCrec->Caller_Range = CUR.curRange; + pCrec->Caller_IP = CUR.IP + 1; + pCrec->Cur_Count = 1; + pCrec->Cur_Restart = def->start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->range, + def->start ); + + CUR.step_ins = FALSE; + return; + + Fail: + CUR.error = TT_Err_Invalid_Reference; + } + + + /*************************************************************************/ + /* */ + /* LOOPCALL[]: LOOP and CALL function */ + /* Opcode range: 0x2A */ + /* Stack: uint32? Eint16? --> */ + /* */ + static + void Ins_LOOPCALL( INS_ARG ) + { + FT_ULong F; + TT_CallRec* pCrec; + TT_DefRecord* def; + + + /* first of all, check the index */ + F = args[1]; + if ( BOUNDS( F, CUR.maxFunc + 1 ) ) + goto Fail; + + /* Except for some old Apple fonts, all functions in a TrueType */ + /* font are defined in increasing order, starting from 0. This */ + /* means that we normally have */ + /* */ + /* CUR.maxFunc+1 == CUR.numFDefs */ + /* CUR.FDefs[n].opc == n for n in 0..CUR.maxFunc */ + /* */ + /* If this isn't true, we need to look up the function table. */ + + def = CUR.FDefs + F; + if ( CUR.maxFunc + 1 != CUR.numFDefs || def->opc != F ) + { + /* look up the FDefs table */ + TT_DefRecord* limit; + + + def = CUR.FDefs; + limit = def + CUR.numFDefs; + + while ( def < limit && def->opc != F ) + def++; + + if ( def == limit ) + goto Fail; + } + + /* check that the function is active */ + if ( !def->active ) + goto Fail; + + /* check stack */ + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + if ( args[0] > 0 ) + { + pCrec = CUR.callStack + CUR.callTop; + + pCrec->Caller_Range = CUR.curRange; + pCrec->Caller_IP = CUR.IP + 1; + pCrec->Cur_Count = (FT_Int)args[0]; + pCrec->Cur_Restart = def->start; + + CUR.callTop++; + + INS_Goto_CodeRange( def->range, def->start ); + + CUR.step_ins = FALSE; + } + return; + + Fail: + CUR.error = TT_Err_Invalid_Reference; + } + + + /*************************************************************************/ + /* */ + /* IDEF[]: Instruction DEFinition */ + /* Opcode range: 0x89 */ + /* Stack: Eint8 --> */ + /* */ + static + void Ins_IDEF( INS_ARG ) + { + TT_DefRecord* def; + TT_DefRecord* limit; + + + /* First of all, look for the same function in our table */ + + def = CUR.IDefs; + limit = def + CUR.numIDefs; + + for ( ; def < limit; def++ ) + if ( def->opc == (FT_ULong)args[0] ) + break; + + if ( def == limit ) + { + /* check that there is enough room for a new instruction */ + if ( CUR.numIDefs >= CUR.maxIDefs ) + { + CUR.error = TT_Err_Too_Many_Instruction_Defs; + return; + } + CUR.numIDefs++; + } + + def->opc = args[0]; + def->start = CUR.IP+1; + def->range = CUR.curRange; + def->active = TRUE; + + if ( (FT_ULong)args[0] > CUR.maxIns ) + CUR.maxIns = args[0]; + + /* Now skip the whole function definition. */ + /* We don't allow nested IDEFs & FDEFs. */ + + while ( SKIP_Code() == SUCCESS ) + { + switch ( CUR.opcode ) + { + case 0x89: /* IDEF */ + case 0x2C: /* FDEF */ + CUR.error = TT_Err_Nested_DEFS; + return; + case 0x2D: /* ENDF */ + return; + } + } + } + + + /*************************************************************************/ + /* */ + /* PUSHING DATA ONTO THE INTERPRETER STACK */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* NPUSHB[]: PUSH N Bytes */ + /* Opcode range: 0x40 */ + /* Stack: --> uint32... */ + /* */ + static + void Ins_NPUSHB( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)CUR.code[CUR.IP + 1]; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + for ( K = 1; K <= L; K++ ) + args[K - 1] = CUR.code[CUR.IP + K + 1]; + + CUR.new_top += L; + } + + + /*************************************************************************/ + /* */ + /* NPUSHW[]: PUSH N Words */ + /* Opcode range: 0x41 */ + /* Stack: --> int32... */ + /* */ + static + void Ins_NPUSHW( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)CUR.code[CUR.IP + 1]; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + CUR.IP += 2; + + for ( K = 0; K < L; K++ ) + args[K] = GET_ShortIns(); + + CUR.step_ins = FALSE; + CUR.new_top += L; + } + + + /*************************************************************************/ + /* */ + /* PUSHB[abc]: PUSH Bytes */ + /* Opcode range: 0xB0-0xB7 */ + /* Stack: --> uint32... */ + /* */ + static + void Ins_PUSHB( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)CUR.opcode - 0xB0 + 1; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + for ( K = 1; K <= L; K++ ) + args[K - 1] = CUR.code[CUR.IP + K]; + } + + + /*************************************************************************/ + /* */ + /* PUSHW[abc]: PUSH Words */ + /* Opcode range: 0xB8-0xBF */ + /* Stack: --> int32... */ + /* */ + static + void Ins_PUSHW( INS_ARG ) + { + FT_UShort L, K; + + + L = (FT_UShort)CUR.opcode - 0xB8 + 1; + + if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + CUR.IP++; + + for ( K = 0; K < L; K++ ) + args[K] = GET_ShortIns(); + + CUR.step_ins = FALSE; + } + + + /*************************************************************************/ + /* */ + /* MANAGING THE GRAPHICS STATE */ + /* */ + /* Instructions appear in the specs' order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* GC[a]: Get Coordinate projected onto */ + /* Opcode range: 0x46-0x47 */ + /* Stack: uint32 --> f26.6 */ + /* */ + /* BULLSHIT: Measures from the original glyph must be taken along the */ + /* dual projection vector! */ + /* */ + static void Ins_GC( INS_ARG ) + { + FT_ULong L; + FT_F26Dot6 R; + + + L = (FT_ULong)args[0]; + + if ( BOUNDS( L, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + else + R = 0; + } + else + { + if ( CUR.opcode & 1 ) + R = CUR_Func_dualproj( CUR.zp2.org + L, NULL_Vector ); + else + R = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); + } + + args[0] = R; + } + + + /*************************************************************************/ + /* */ + /* SCFS[]: Set Coordinate From Stack */ + /* Opcode range: 0x48 */ + /* Stack: f26.6 uint32 --> */ + /* */ + /* Formula: */ + /* */ + /* OA := OA + ( value - OA.p )/( f.p ) * f */ + /* */ + static + void Ins_SCFS( INS_ARG ) + { + FT_Long K; + FT_UShort L; + + + L = (FT_UShort)args[0]; + + if ( BOUNDS( L, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + K = CUR_Func_project( CUR.zp2.cur + L, NULL_Vector ); + + CUR_Func_move( &CUR.zp2, L, args[1] - K ); + + /* not part of the specs, but here for safety */ + + if ( CUR.GS.gep2 == 0 ) + CUR.zp2.org[L] = CUR.zp2.cur[L]; + } + + + /*************************************************************************/ + /* */ + /* MD[a]: Measure Distance */ + /* Opcode range: 0x49-0x4A */ + /* Stack: uint32 uint32 --> f26.6 */ + /* */ + /* BULLSHIT: Measure taken in the original glyph must be along the dual */ + /* projection vector. */ + /* */ + /* Second BULLSHIT: Flag attributes are inverted! */ + /* 0 => measure distance in original outline */ + /* 1 => measure distance in grid-fitted outline */ + /* */ + /* Third one: `zp0 - zp1', and not `zp2 - zp1! */ + /* */ + static + void Ins_MD( INS_ARG ) + { + FT_UShort K, L; + FT_F26Dot6 D; + + + K = (FT_UShort)args[1]; + L = (FT_UShort)args[0]; + + if( BOUNDS( L, CUR.zp0.n_points ) || + BOUNDS( K, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + D = 0; + } + else + { + if ( CUR.opcode & 1 ) + D = CUR_Func_project( CUR.zp0.cur + L, CUR.zp1.cur + K ); + else + D = CUR_Func_dualproj( CUR.zp0.org + L, CUR.zp1.org + K ); + } + + args[0] = D; + } + + + /*************************************************************************/ + /* */ + /* SDPVTL[a]: Set Dual PVector to Line */ + /* Opcode range: 0x86-0x87 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_SDPVTL( INS_ARG ) + { + FT_Long A, B, C; + FT_UShort p1, p2; /* was FT_Int in pas type ERROR */ + + + p1 = (FT_UShort)args[1]; + p2 = (FT_UShort)args[0]; + + if ( BOUNDS( p2, CUR.zp1.n_points ) || + BOUNDS( p1, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + { + FT_Vector* v1 = CUR.zp1.org + p2; + FT_Vector* v2 = CUR.zp2.org + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( ( CUR.opcode & 1 ) != 0 ) + { + C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.dualVector ); + + { + FT_Vector* v1 = CUR.zp1.cur + p2; + FT_Vector* v2 = CUR.zp2.cur + p1; + + + A = v1->x - v2->x; + B = v1->y - v2->y; + } + + if ( ( CUR.opcode & 1 ) != 0 ) + { + C = B; /* counter clockwise rotation */ + B = A; + A = -C; + } + + NORMalize( A, B, &CUR.GS.projVector ); + + COMPUTE_Funcs(); + } + + + /*************************************************************************/ + /* */ + /* SZP0[]: Set Zone Pointer 0 */ + /* Opcode range: 0x13 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZP0( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp0 = CUR.twilight; + break; + + case 1: + CUR.zp0 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep0 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* SZP1[]: Set Zone Pointer 1 */ + /* Opcode range: 0x14 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZP1( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp1 = CUR.twilight; + break; + + case 1: + CUR.zp1 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep1 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* SZP2[]: Set Zone Pointer 2 */ + /* Opcode range: 0x15 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZP2( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp2 = CUR.twilight; + break; + + case 1: + CUR.zp2 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.GS.gep2 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* SZPS[]: Set Zone PointerS */ + /* Opcode range: 0x16 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SZPS( INS_ARG ) + { + switch ( (FT_Int)args[0] ) + { + case 0: + CUR.zp0 = CUR.twilight; + break; + + case 1: + CUR.zp0 = CUR.pts; + break; + + default: + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + CUR.zp1 = CUR.zp0; + CUR.zp2 = CUR.zp0; + + CUR.GS.gep0 = (FT_UShort)args[0]; + CUR.GS.gep1 = (FT_UShort)args[0]; + CUR.GS.gep2 = (FT_UShort)args[0]; + } + + + /*************************************************************************/ + /* */ + /* INSTCTRL[]: INSTruction ConTRoL */ + /* Opcode range: 0x8e */ + /* Stack: int32 int32 --> */ + /* */ + static + void Ins_INSTCTRL( INS_ARG ) + { + FT_Long K, L; + + + K = args[1]; + L = args[0]; + + if ( K < 1 || K > 2 ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( L != 0 ) + L = K; + + CUR.GS.instruct_control = + (FT_Byte)( CUR.GS.instruct_control & ~(FT_Byte)K ) | (FT_Byte)L; + } + + + /*************************************************************************/ + /* */ + /* SCANCTRL[]: SCAN ConTRoL */ + /* Opcode range: 0x85 */ + /* Stack: uint32? --> */ + /* */ + static + void Ins_SCANCTRL( INS_ARG ) + { + FT_Int A; + + + /* Get Threshold */ + A = (FT_Int)( args[0] & 0xFF ); + + if ( A == 0xFF ) + { + CUR.GS.scan_control = TRUE; + return; + } + else if ( A == 0 ) + { + CUR.GS.scan_control = FALSE; + return; + } + + A *= 64; + +#if 0 + if ( (args[0] & 0x100) != 0 && CUR.metrics.pointSize <= A ) + CUR.GS.scan_control = TRUE; +#endif + + if ( (args[0] & 0x200) != 0 && CUR.tt_metrics.rotated ) + CUR.GS.scan_control = TRUE; + + if ( (args[0] & 0x400) != 0 && CUR.tt_metrics.stretched ) + CUR.GS.scan_control = TRUE; + +#if 0 + if ( (args[0] & 0x800) != 0 && CUR.metrics.pointSize > A ) + CUR.GS.scan_control = FALSE; +#endif + + if ( (args[0] & 0x1000) != 0 && CUR.tt_metrics.rotated ) + CUR.GS.scan_control = FALSE; + + if ( (args[0] & 0x2000) != 0 && CUR.tt_metrics.stretched ) + CUR.GS.scan_control = FALSE; +} + + + /*************************************************************************/ + /* */ + /* SCANTYPE[]: SCAN TYPE */ + /* Opcode range: 0x8D */ + /* Stack: uint32? --> */ + /* */ + static + void Ins_SCANTYPE( INS_ARG ) + { + /* for compatibility with future enhancements, */ + /* we must ignore new modes */ + + if ( args[0] >= 0 && args[0] <= 5 ) + { + if ( args[0] == 3 ) + args[0] = 2; + + CUR.GS.scan_type = (FT_Int)args[0]; + } + } + + + /*************************************************************************/ + /* */ + /* MANAGING OUTLINES */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* FLIPPT[]: FLIP PoinT */ + /* Opcode range: 0x80 */ + /* Stack: uint32... --> */ + /* */ + static + void Ins_FLIPPT( INS_ARG ) + { + FT_UShort point; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + CUR.pts.tags[point] ^= FT_Curve_Tag_On; + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* FLIPRGON[]: FLIP RanGe ON */ + /* Opcode range: 0x81 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_FLIPRGON( INS_ARG ) + { + FT_UShort I, K, L; + + + K = (FT_UShort)args[1]; + L = (FT_UShort)args[0]; + + if ( BOUNDS( K, CUR.pts.n_points ) || + BOUNDS( L, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + for ( I = L; I <= K; I++ ) + CUR.pts.tags[I] |= FT_Curve_Tag_On; + } + + + /*************************************************************************/ + /* */ + /* FLIPRGOFF: FLIP RanGe OFF */ + /* Opcode range: 0x82 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_FLIPRGOFF( INS_ARG ) + { + FT_UShort I, K, L; + + + K = (FT_UShort)args[1]; + L = (FT_UShort)args[0]; + + if ( BOUNDS( K, CUR.pts.n_points ) || + BOUNDS( L, CUR.pts.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + for ( I = L; I <= K; I++ ) + CUR.pts.tags[I] &= ~FT_Curve_Tag_On; + } + + + static + FT_Bool Compute_Point_Displacement( EXEC_OP_ FT_F26Dot6* x, + FT_F26Dot6* y, + TT_GlyphZone* zone, + FT_UShort* refp ) + { + TT_GlyphZone zp; + FT_UShort p; + FT_F26Dot6 d; + + + if ( CUR.opcode & 1 ) + { + zp = CUR.zp0; + p = CUR.GS.rp1; + } + else + { + zp = CUR.zp1; + p = CUR.GS.rp2; + } + + if ( BOUNDS( p, zp.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return FAILURE; + } + + *zone = zp; + *refp = p; + + d = CUR_Func_project( zp.cur + p, zp.org + p ); + +#ifdef NO_APPLE_PATENT + + *x = TT_MULDIV( d, CUR.GS.freeVector.x, 0x4000 ); + *y = TT_MULDIV( d, CUR.GS.freeVector.y, 0x4000 ); + +#else + + *x = TT_MULDIV( d, + (FT_Long)CUR.GS.freeVector.x * 0x10000L, + CUR.F_dot_P ); + *y = TT_MULDIV( d, + (FT_Long)CUR.GS.freeVector.y * 0x10000L, + CUR.F_dot_P ); + +#endif /* NO_APPLE_PATENT */ + + return SUCCESS; + } + + + static + void Move_Zp2_Point( EXEC_OP_ FT_UShort point, + FT_F26Dot6 dx, + FT_F26Dot6 dy, + FT_Bool touch ) + { + if ( CUR.GS.freeVector.x != 0 ) + { + CUR.zp2.cur[point].x += dx; + if ( touch ) + CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_X; + } + + if ( CUR.GS.freeVector.y != 0 ) + { + CUR.zp2.cur[point].y += dy; + if ( touch ) + CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Y; + } + } + + + /*************************************************************************/ + /* */ + /* SHP[a]: SHift Point by the last point */ + /* Opcode range: 0x32-0x33 */ + /* Stack: uint32... --> */ + /* */ + static + void Ins_SHP( INS_ARG ) + { + TT_GlyphZone zp; + FT_UShort refp; + + FT_F26Dot6 dx, + dy; + FT_UShort point; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + /* XXX: UNDOCUMENTED! SHP touches the points */ + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* SHC[a]: SHift Contour */ + /* Opcode range: 0x34-35 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SHC( INS_ARG ) + { + TT_GlyphZone zp; + FT_UShort refp; + FT_F26Dot6 dx, + dy; + + FT_Short contour; + FT_UShort first_point, last_point, i; + + + contour = (FT_UShort)args[0]; + + if ( BOUNDS( contour, CUR.pts.n_contours ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + if ( contour == 0 ) + first_point = 0; + else + first_point = CUR.pts.contours[contour - 1] + 1; + + last_point = CUR.pts.contours[contour]; + + /* XXX: this is probably wrong... at least it prevents memory */ + /* corruption when zp2 is the twilight zone */ + if ( last_point > CUR.zp2.n_points ) + { + if ( CUR.zp2.n_points > 0 ) + last_point = CUR.zp2.n_points - 1; + else + last_point = 0; + } + + /* XXX: UNDOCUMENTED! SHC doesn't touch the points */ + for ( i = first_point; i <= last_point; i++ ) + { + if ( zp.cur != CUR.zp2.cur || refp != i ) + MOVE_Zp2_Point( i, dx, dy, FALSE ); + } + } + + + /*************************************************************************/ + /* */ + /* SHZ[a]: SHift Zone */ + /* Opcode range: 0x36-37 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_SHZ( INS_ARG ) + { + TT_GlyphZone zp; + FT_UShort refp; + FT_F26Dot6 dx, + dy; + + FT_UShort last_point, i; + + + if ( BOUNDS( args[0], 2 ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( COMPUTE_Point_Displacement( &dx, &dy, &zp, &refp ) ) + return; + + if ( CUR.zp2.n_points > 0 ) + last_point = CUR.zp2.n_points - 1; + else + last_point = 0; + + /* XXX: UNDOCUMENTED! SHZ doesn't touch the points */ + for ( i = 0; i <= last_point; i++ ) + { + if ( zp.cur != CUR.zp2.cur || refp != i ) + MOVE_Zp2_Point( i, dx, dy, FALSE ); + } + } + + + /*************************************************************************/ + /* */ + /* SHPIX[]: SHift points by a PIXel amount */ + /* Opcode range: 0x38 */ + /* Stack: f26.6 uint32... --> */ + /* */ + static + void Ins_SHPIX( INS_ARG ) + { + FT_F26Dot6 dx, dy; + FT_UShort point; + + + if ( CUR.top < CUR.GS.loop + 1 ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + dx = TT_MULDIV( args[0], + (FT_Long)CUR.GS.freeVector.x, + 0x4000 ); + dy = TT_MULDIV( args[0], + (FT_Long)CUR.GS.freeVector.y, + 0x4000 ); + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + MOVE_Zp2_Point( point, dx, dy, TRUE ); + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* MSIRP[a]: Move Stack Indirect Relative Position */ + /* Opcode range: 0x3A-0x3B */ + /* Stack: f26.6 uint32 --> */ + /* */ + static + void Ins_MSIRP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 distance; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: UNDOCUMENTED! behaviour */ + if ( CUR.GS.gep0 == 0 ) /* if in twilight zone */ + { + CUR.zp1.org[point] = CUR.zp0.org[CUR.GS.rp0]; + CUR.zp1.cur[point] = CUR.zp1.org[point]; + } + + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, args[1] - distance ); + + CUR.GS.rp1 = CUR.GS.rp0; + CUR.GS.rp2 = point; + + if ( (CUR.opcode & 1) != 0 ) + CUR.GS.rp0 = point; + } + + + /*************************************************************************/ + /* */ + /* MDAP[a]: Move Direct Absolute Point */ + /* Opcode range: 0x2E-0x2F */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_MDAP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 cur_dist, + distance; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? ? */ + if ( ( CUR.opcode & 1 ) != 0 ) + { + cur_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); + distance = CUR_Func_round( cur_dist, + CUR.tt_metrics.compensations[0] ) - cur_dist; + } + else + distance = 0; + + CUR_Func_move( &CUR.zp0, point, distance ); + + CUR.GS.rp0 = point; + CUR.GS.rp1 = point; + } + + + /*************************************************************************/ + /* */ + /* MIAP[a]: Move Indirect Absolute Point */ + /* Opcode range: 0x3E-0x3F */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_MIAP( INS_ARG ) + { + FT_ULong cvtEntry; + FT_UShort point; + FT_F26Dot6 distance, + org_dist; + + + cvtEntry = (FT_ULong)args[1]; + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) || + BOUNDS( cvtEntry, CUR.cvtSize ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* UNDOCUMENTED! */ + /* */ + /* The behaviour of an MIAP instruction is quite */ + /* different when used in the twilight zone. */ + /* */ + /* First, no control value cutin test is performed */ + /* as it would fail anyway. Second, the original */ + /* point, i.e. (org_x,org_y) of zp0.point, is set */ + /* to the absolute, unrounded distance found in */ + /* the CVT. */ + /* */ + /* This is used in the CVT programs of the Microsoft */ + /* fonts Arial, Times, etc., in order to re-adjust */ + /* some key font heights. It allows the use of the */ + /* IP instruction in the twilight zone, which */ + /* otherwise would be `illegal' according to the */ + /* specification. */ + /* */ + /* We implement it with a special sequence for the */ + /* twilight zone. This is a bad hack, but it seems */ + /* to work. */ + + distance = CUR_Func_read_cvt( cvtEntry ); + + if ( CUR.GS.gep0 == 0 ) /* If in twilight zone */ + { + CUR.zp0.org[point].x = TT_MULDIV( CUR.GS.freeVector.x, + distance, 0x4000 ); + CUR.zp0.org[point].y = TT_MULDIV( CUR.GS.freeVector.y, + distance, 0x4000 ); + CUR.zp0.cur[point] = CUR.zp0.org[point]; + } + + org_dist = CUR_Func_project( CUR.zp0.cur + point, NULL_Vector ); + + if ( ( CUR.opcode & 1 ) != 0 ) /* rounding and control cutin flag */ + { + if ( ABS( distance - org_dist ) > CUR.GS.control_value_cutin ) + distance = org_dist; + + distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] ); + } + + CUR_Func_move( &CUR.zp0, point, distance - org_dist ); + + CUR.GS.rp0 = point; + CUR.GS.rp1 = point; + } + + + /*************************************************************************/ + /* */ + /* MDRP[abcde]: Move Direct Relative Point */ + /* Opcode range: 0xC0-0xDF */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_MDRP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 org_dist, distance; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: Is there some undocumented feature while in the */ + /* twilight zone? */ + + org_dist = CUR_Func_dualproj( CUR.zp1.org + point, + CUR.zp0.org + CUR.GS.rp0 ); + + /* single width cutin test */ + + if ( ABS( org_dist ) < CUR.GS.single_width_cutin ) + { + if ( org_dist >= 0 ) + org_dist = CUR.GS.single_width_value; + else + org_dist = -CUR.GS.single_width_value; + } + + /* round flag */ + + if ( ( CUR.opcode & 4 ) != 0 ) + distance = CUR_Func_round( + org_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + else + distance = ROUND_None( + org_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + + /* minimum distance flag */ + + if ( ( CUR.opcode & 8 ) != 0 ) + { + if ( org_dist >= 0 ) + { + if ( distance < CUR.GS.minimum_distance ) + distance = CUR.GS.minimum_distance; + } + else + { + if ( distance > -CUR.GS.minimum_distance ) + distance = -CUR.GS.minimum_distance; + } + } + + /* now move the point */ + + org_dist = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, distance - org_dist ); + + CUR.GS.rp1 = CUR.GS.rp0; + CUR.GS.rp2 = point; + + if ( ( CUR.opcode & 16 ) != 0 ) + CUR.GS.rp0 = point; + } + + + /*************************************************************************/ + /* */ + /* MIRP[abcde]: Move Indirect Relative Point */ + /* Opcode range: 0xE0-0xFF */ + /* Stack: int32? uint32 --> */ + /* */ + static + void Ins_MIRP( INS_ARG ) + { + FT_UShort point; + FT_ULong cvtEntry; + + FT_F26Dot6 cvt_dist, + distance, + cur_dist, + org_dist; + + + point = (FT_UShort)args[0]; + cvtEntry = (FT_ULong)( args[1] + 1 ); + + /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */ + + if ( BOUNDS( point, CUR.zp1.n_points ) || + BOUNDS( cvtEntry, CUR.cvtSize + 1 ) || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + if ( !cvtEntry ) + cvt_dist = 0; + else + cvt_dist = CUR_Func_read_cvt( cvtEntry - 1 ); + + /* single width test */ + + if ( ABS( cvt_dist ) < CUR.GS.single_width_cutin ) + { + if ( cvt_dist >= 0 ) + cvt_dist = CUR.GS.single_width_value; + else + cvt_dist = -CUR.GS.single_width_value; + } + + /* XXX: UNDOCUMENTED! -- twilight zone */ + + if ( CUR.GS.gep1 == 0 ) + { + CUR.zp1.org[point].x = CUR.zp0.org[CUR.GS.rp0].x + + TT_MULDIV( cvt_dist, + CUR.GS.freeVector.x, + 0x4000 ); + + CUR.zp1.org[point].y = CUR.zp0.org[CUR.GS.rp0].y + + TT_MULDIV( cvt_dist, + CUR.GS.freeVector.y, + 0x4000 ); + + CUR.zp1.cur[point] = CUR.zp1.org[point]; + } + + org_dist = CUR_Func_dualproj( CUR.zp1.org + point, + CUR.zp0.org + CUR.GS.rp0 ); + + cur_dist = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + /* auto-flip test */ + + if ( CUR.GS.auto_flip ) + { + if ( ( org_dist ^ cvt_dist ) < 0 ) + cvt_dist = -cvt_dist; + } + + /* control value cutin and round */ + + if ( ( CUR.opcode & 4 ) != 0 ) + { + /* XXX: UNDOCUMENTED! Only perform cut-in test when both points */ + /* refer to the same zone. */ + + if ( CUR.GS.gep0 == CUR.GS.gep1 ) + if ( ABS( cvt_dist - org_dist ) >= CUR.GS.control_value_cutin ) + cvt_dist = org_dist; + + distance = CUR_Func_round( + cvt_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + } + else + distance = ROUND_None( + cvt_dist, + CUR.tt_metrics.compensations[CUR.opcode & 3] ); + + /* minimum distance test */ + + if ( ( CUR.opcode & 8 ) != 0 ) + { + if ( org_dist >= 0 ) + { + if ( distance < CUR.GS.minimum_distance ) + distance = CUR.GS.minimum_distance; + } + else + { + if ( distance > -CUR.GS.minimum_distance ) + distance = -CUR.GS.minimum_distance; + } + } + + CUR_Func_move( &CUR.zp1, point, distance - cur_dist ); + + CUR.GS.rp1 = CUR.GS.rp0; + + if ( ( CUR.opcode & 16 ) != 0 ) + CUR.GS.rp0 = point; + + /* XXX: UNDOCUMENTED! */ + + CUR.GS.rp2 = point; + } + + + /*************************************************************************/ + /* */ + /* ALIGNRP[]: ALIGN Relative Point */ + /* Opcode range: 0x3C */ + /* Stack: uint32 uint32... --> */ + /* */ + static + void Ins_ALIGNRP( INS_ARG ) + { + FT_UShort point; + FT_F26Dot6 distance; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop || + BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + + if ( BOUNDS( point, CUR.zp1.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + distance = CUR_Func_project( CUR.zp1.cur + point, + CUR.zp0.cur + CUR.GS.rp0 ); + + CUR_Func_move( &CUR.zp1, point, -distance ); + } + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* ISECT[]: moves point to InterSECTion */ + /* Opcode range: 0x0F */ + /* Stack: 5 * uint32 --> */ + /* */ + static + void Ins_ISECT( INS_ARG ) + { + FT_UShort point, + a0, a1, + b0, b1; + + FT_F26Dot6 discriminant; + + FT_F26Dot6 dx, dy, + dax, day, + dbx, dby; + + FT_F26Dot6 val; + + FT_Vector R; + + + point = (FT_UShort)args[0]; + + a0 = (FT_UShort)args[1]; + a1 = (FT_UShort)args[2]; + b0 = (FT_UShort)args[3]; + b1 = (FT_UShort)args[4]; + + if ( BOUNDS( b0, CUR.zp0.n_points ) || + BOUNDS( b1, CUR.zp0.n_points ) || + BOUNDS( a0, CUR.zp1.n_points ) || + BOUNDS( a1, CUR.zp1.n_points ) || + BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x; + dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y; + + dax = CUR.zp1.cur[a1].x - CUR.zp1.cur[a0].x; + day = CUR.zp1.cur[a1].y - CUR.zp1.cur[a0].y; + + dx = CUR.zp0.cur[b0].x - CUR.zp1.cur[a0].x; + dy = CUR.zp0.cur[b0].y - CUR.zp1.cur[a0].y; + + CUR.zp2.tags[point] |= FT_Curve_Tag_Touch_Both; + + discriminant = TT_MULDIV( dax, -dby, 0x40 ) + + TT_MULDIV( day, dbx, 0x40 ); + + if ( ABS( discriminant ) >= 0x40 ) + { + val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 ); + + R.x = TT_MULDIV( val, dax, discriminant ); + R.y = TT_MULDIV( val, day, discriminant ); + + CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x; + CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y; + } + else + { + /* else, take the middle of the middles of A and B */ + + CUR.zp2.cur[point].x = ( CUR.zp1.cur[a0].x + + CUR.zp1.cur[a1].x + + CUR.zp0.cur[b0].x + + CUR.zp0.cur[b1].x ) / 4; + CUR.zp2.cur[point].y = ( CUR.zp1.cur[a0].y + + CUR.zp1.cur[a1].y + + CUR.zp0.cur[b0].y + + CUR.zp0.cur[b1].y ) / 4; + } + } + + + /*************************************************************************/ + /* */ + /* ALIGNPTS[]: ALIGN PoinTS */ + /* Opcode range: 0x27 */ + /* Stack: uint32 uint32 --> */ + /* */ + static + void Ins_ALIGNPTS( INS_ARG ) + { + FT_UShort p1, p2; + FT_F26Dot6 distance; + + + p1 = (FT_UShort)args[0]; + p2 = (FT_UShort)args[1]; + + if ( BOUNDS( args[0], CUR.zp1.n_points ) || + BOUNDS( args[1], CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + distance = CUR_Func_project( CUR.zp0.cur + p2, + CUR.zp1.cur + p1 ) / 2; + + CUR_Func_move( &CUR.zp1, p1, distance ); + CUR_Func_move( &CUR.zp0, p2, -distance ); + } + + + /*************************************************************************/ + /* */ + /* IP[]: Interpolate Point */ + /* Opcode range: 0x39 */ + /* Stack: uint32... --> */ + /* */ + static + void Ins_IP( INS_ARG ) + { + FT_F26Dot6 org_a, org_b, org_x, + cur_a, cur_b, cur_x, + distance; + FT_UShort point; + + FT_UNUSED_ARG; + + + if ( CUR.top < CUR.GS.loop ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + + /* XXX: There are some glyphs in some braindead but popular */ + /* fonts out there (e.g. [aeu]grave in monotype.ttf) */ + /* calling IP[] with bad values of rp[12]. */ + /* Do something sane when this odd thing happens. */ + + if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) || + BOUNDS( CUR.GS.rp2, CUR.zp1.n_points ) ) + { + org_a = cur_a = 0; + org_b = cur_b = 0; + } + else + { + org_a = CUR_Func_dualproj( CUR.zp0.org + CUR.GS.rp1, NULL_Vector ); + org_b = CUR_Func_dualproj( CUR.zp1.org + CUR.GS.rp2, NULL_Vector ); + + cur_a = CUR_Func_project( CUR.zp0.cur + CUR.GS.rp1, NULL_Vector ); + cur_b = CUR_Func_project( CUR.zp1.cur + CUR.GS.rp2, NULL_Vector ); + } + + while ( CUR.GS.loop > 0 ) + { + CUR.args--; + + point = (FT_UShort)CUR.stack[CUR.args]; + if ( BOUNDS( point, CUR.zp2.n_points ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + org_x = CUR_Func_dualproj( CUR.zp2.org + point, NULL_Vector ); + cur_x = CUR_Func_project ( CUR.zp2.cur + point, NULL_Vector ); + + if ( ( org_a <= org_b && org_x <= org_a ) || + ( org_a > org_b && org_x >= org_a ) ) + + distance = ( cur_a - org_a ) + ( org_x - cur_x ); + + else if ( ( org_a <= org_b && org_x >= org_b ) || + ( org_a > org_b && org_x < org_b ) ) + + distance = ( cur_b - org_b ) + ( org_x - cur_x ); + + else + /* note: it seems that rounding this value isn't a good */ + /* idea (cf. width of capital `S' in Times) */ + + distance = TT_MULDIV( cur_b - cur_a, + org_x - org_a, + org_b - org_a ) + ( cur_a - cur_x ); + + CUR_Func_move( &CUR.zp2, point, distance ); + } + + CUR.GS.loop--; + } + + CUR.GS.loop = 1; + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* UTP[a]: UnTouch Point */ + /* Opcode range: 0x29 */ + /* Stack: uint32 --> */ + /* */ + static + void Ins_UTP( INS_ARG ) + { + FT_UShort point; + FT_Byte mask; + + + point = (FT_UShort)args[0]; + + if ( BOUNDS( point, CUR.zp0.n_points ) ) + { + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + return; + } + + mask = 0xFF; + + if ( CUR.GS.freeVector.x != 0 ) + mask &= ~FT_Curve_Tag_Touch_X; + + if ( CUR.GS.freeVector.y != 0 ) + mask &= ~FT_Curve_Tag_Touch_Y; + + CUR.zp0.tags[point] &= mask; + } + + + /* Local variables for Ins_IUP: */ + struct LOC_Ins_IUP + { + FT_Vector* orgs; /* original and current coordinate */ + FT_Vector* curs; /* arrays */ + }; + + + static + void Shift( FT_UInt p1, + FT_UInt p2, + FT_UInt p, + struct LOC_Ins_IUP* LINK ) + { + FT_UInt i; + FT_F26Dot6 x; + + + x = LINK->curs[p].x - LINK->orgs[p].x; + + for ( i = p1; i < p; i++ ) + LINK->curs[i].x += x; + + for ( i = p + 1; i <= p2; i++ ) + LINK->curs[i].x += x; + } + + + static + void Interp( FT_UInt p1, + FT_UInt p2, + FT_UInt ref1, + FT_UInt ref2, + struct LOC_Ins_IUP* LINK ) + { + FT_UInt i; + FT_F26Dot6 x, x1, x2, d1, d2; + + + if ( p1 > p2 ) + return; + + x1 = LINK->orgs[ref1].x; + d1 = LINK->curs[ref1].x - LINK->orgs[ref1].x; + x2 = LINK->orgs[ref2].x; + d2 = LINK->curs[ref2].x - LINK->orgs[ref2].x; + + if ( x1 == x2 ) + { + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + + if ( x <= x1 ) + x += d1; + else + x += d2; + + LINK->curs[i].x = x; + } + return; + } + + if ( x1 < x2 ) + { + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + + if ( x <= x1 ) + x += d1; + else + { + if ( x >= x2 ) + x += d2; + else + x = LINK->curs[ref1].x + + TT_MULDIV( x - x1, + LINK->curs[ref2].x - LINK->curs[ref1].x, + x2 - x1 ); + } + LINK->curs[i].x = x; + } + return; + } + + /* x2 < x1 */ + + for ( i = p1; i <= p2; i++ ) + { + x = LINK->orgs[i].x; + if ( x <= x2 ) + x += d2; + else + { + if ( x >= x1 ) + x += d1; + else + x = LINK->curs[ref1].x + + TT_MULDIV( x - x1, + LINK->curs[ref2].x - LINK->curs[ref1].x, + x2 - x1 ); + } + LINK->curs[i].x = x; + } + } + + + /*************************************************************************/ + /* */ + /* IUP[a]: Interpolate Untouched Points */ + /* Opcode range: 0x30-0x31 */ + /* Stack: --> */ + /* */ + static + void Ins_IUP( INS_ARG ) + { + struct LOC_Ins_IUP V; + FT_Byte mask; + + FT_UInt first_point; /* first point of contour */ + FT_UInt end_point; /* end point (last+1) of contour */ + + FT_UInt first_touched; /* first touched point in contour */ + FT_UInt cur_touched; /* current touched point in contour */ + + FT_UInt point; /* current point */ + FT_Short contour; /* current contour */ + + FT_UNUSED_ARG; + + + if ( CUR.opcode & 1 ) + { + mask = FT_Curve_Tag_Touch_X; + V.orgs = CUR.pts.org; + V.curs = CUR.pts.cur; + } + else + { + mask = FT_Curve_Tag_Touch_Y; + V.orgs = (FT_Vector*)( (FT_Pos*)CUR.pts.org + 1 ); + V.curs = (FT_Vector*)( (FT_Pos*)CUR.pts.cur + 1 ); + } + + contour = 0; + point = 0; + + do + { + end_point = CUR.pts.contours[contour]; + first_point = point; + + while ( point <= end_point && (CUR.pts.tags[point] & mask) == 0 ) + point++; + + if ( point <= end_point ) + { + first_touched = point; + cur_touched = point; + + point++; + + while ( point <= end_point ) + { + if ( ( CUR.pts.tags[point] & mask ) != 0 ) + { + if ( point > 0 ) + Interp( cur_touched + 1, + point - 1, + cur_touched, + point, + &V ); + cur_touched = point; + } + + point++; + } + + if ( cur_touched == first_touched ) + Shift( first_point, end_point, cur_touched, &V ); + else + { + Interp( (FT_UShort)( cur_touched + 1 ), + end_point, + cur_touched, + first_touched, + &V ); + + if ( first_touched > 0 ) + Interp( first_point, + first_touched - 1, + cur_touched, + first_touched, + &V ); + } + } + contour++; + } while ( contour < CUR.pts.n_contours ); + } + + + /*************************************************************************/ + /* */ + /* DELTAPn[]: DELTA exceptions P1, P2, P3 */ + /* Opcode range: 0x5D,0x71,0x72 */ + /* Stack: uint32 (2 * uint32)... --> */ + /* */ + static + void Ins_DELTAP( INS_ARG ) + { + FT_ULong k, nump; + FT_UShort A; + FT_ULong C; + FT_Long B; + + + nump = (FT_ULong)args[0]; /* some points theoretically may occur more + than once, thus UShort isn't enough */ + + for ( k = 1; k <= nump; k++ ) + { + if ( CUR.args < 2 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= 2; + + A = (FT_UShort)CUR.stack[CUR.args + 1]; + B = CUR.stack[CUR.args]; + + /* XXX: Because some popular fonts contain some invalid DeltaP */ + /* instructions, we simply ignore them when the stacked */ + /* point reference is off limit, rather than returning an */ + /* error. As a delta instruction doesn't change a glyph */ + /* in great ways, this shouldn't be a problem. */ + + if ( !BOUNDS( A, CUR.zp0.n_points ) ) + { + C = ( (FT_ULong)B & 0xF0 ) >> 4; + + switch ( CUR.opcode ) + { + case 0x5D: + break; + + case 0x71: + C += 16; + break; + + case 0x72: + C += 32; + break; + } + + C += CUR.GS.delta_base; + + if ( CURRENT_Ppem() == (FT_Long)C ) + { + B = ( (FT_ULong)B & 0xF ) - 8; + if ( B >= 0 ) + B++; + B = B * 64 / ( 1L << CUR.GS.delta_shift ); + + CUR_Func_move( &CUR.zp0, A, B ); + } + } + else + if ( CUR.pedantic_hinting ) + CUR.error = TT_Err_Invalid_Reference; + } + + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* DELTACn[]: DELTA exceptions C1, C2, C3 */ + /* Opcode range: 0x73,0x74,0x75 */ + /* Stack: uint32 (2 * uint32)... --> */ + /* */ + static + void Ins_DELTAC( INS_ARG ) + { + FT_ULong nump, k; + FT_ULong A, C; + FT_Long B; + + + nump = (FT_ULong)args[0]; + + for ( k = 1; k <= nump; k++ ) + { + if ( CUR.args < 2 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + return; + } + + CUR.args -= 2; + + A = (FT_ULong)CUR.stack[CUR.args + 1]; + B = CUR.stack[CUR.args]; + + if ( BOUNDS( A, CUR.cvtSize ) ) + { + if ( CUR.pedantic_hinting ) + { + CUR.error = TT_Err_Invalid_Reference; + return; + } + } + else + { + C = ( (FT_ULong)B & 0xF0 ) >> 4; + + switch ( CUR.opcode ) + { + case 0x73: + break; + + case 0x74: + C += 16; + break; + + case 0x75: + C += 32; + break; + } + + C += CUR.GS.delta_base; + + if ( CURRENT_Ppem() == (FT_Long)C ) + { + B = ( (FT_ULong)B & 0xF ) - 8; + if ( B >= 0 ) + B++; + B = B * 64 / ( 1L << CUR.GS.delta_shift ); + + CUR_Func_move_cvt( A, B ); + } + } + } + + CUR.new_top = CUR.args; + } + + + /*************************************************************************/ + /* */ + /* MISC. INSTRUCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* GETINFO[]: GET INFOrmation */ + /* Opcode range: 0x88 */ + /* Stack: uint32 --> uint32 */ + /* */ + /* XXX: According to Apple specs, bits 1 & 2 of the argument ought to be */ + /* consulted before rotated/stretched info is returned. */ + static + void Ins_GETINFO( INS_ARG ) + { + FT_Long K; + + + K = 0; + + /* We return then Windows 3.1 version number */ + /* for the font scaler */ + if ( ( args[0] & 1 ) != 0 ) + K = 3; + + /* Has the glyph been rotated ? */ + if ( CUR.tt_metrics.rotated ) + K |= 0x80; + + /* Has the glyph been stretched ? */ + if ( CUR.tt_metrics.stretched ) + K |= 0x100; + + args[0] = K; + } + + + static + void Ins_UNKNOWN( INS_ARG ) + { + TT_DefRecord* def = CUR.IDefs; + TT_DefRecord* limit = def + CUR.numIDefs; + + FT_UNUSED_ARG; + + + for ( ; def < limit; def++ ) + { + if ( def->opc == CUR.opcode && def->active ) + { + TT_CallRec* call; + + + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Stack_Overflow; + return; + } + + call = CUR.callStack + CUR.callTop++; + + call->Caller_Range = CUR.curRange; + call->Caller_IP = CUR.IP+1; + call->Cur_Count = 1; + call->Cur_Restart = def->start; + + INS_Goto_CodeRange( def->range, def->start ); + + CUR.step_ins = FALSE; + return; + } + } + + CUR.error = TT_Err_Invalid_Opcode; + } + + +#ifndef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + + static + TInstruction_Function Instruct_Dispatch[256] = + { + /* Opcodes are gathered in groups of 16. */ + /* Please keep the spaces as they are. */ + + /* SVTCA y */ Ins_SVTCA, + /* SVTCA x */ Ins_SVTCA, + /* SPvTCA y */ Ins_SPVTCA, + /* SPvTCA x */ Ins_SPVTCA, + /* SFvTCA y */ Ins_SFVTCA, + /* SFvTCA x */ Ins_SFVTCA, + /* SPvTL // */ Ins_SPVTL, + /* SPvTL + */ Ins_SPVTL, + /* SFvTL // */ Ins_SFVTL, + /* SFvTL + */ Ins_SFVTL, + /* SPvFS */ Ins_SPVFS, + /* SFvFS */ Ins_SFVFS, + /* GPV */ Ins_GPV, + /* GFV */ Ins_GFV, + /* SFvTPv */ Ins_SFVTPV, + /* ISECT */ Ins_ISECT, + + /* SRP0 */ Ins_SRP0, + /* SRP1 */ Ins_SRP1, + /* SRP2 */ Ins_SRP2, + /* SZP0 */ Ins_SZP0, + /* SZP1 */ Ins_SZP1, + /* SZP2 */ Ins_SZP2, + /* SZPS */ Ins_SZPS, + /* SLOOP */ Ins_SLOOP, + /* RTG */ Ins_RTG, + /* RTHG */ Ins_RTHG, + /* SMD */ Ins_SMD, + /* ELSE */ Ins_ELSE, + /* JMPR */ Ins_JMPR, + /* SCvTCi */ Ins_SCVTCI, + /* SSwCi */ Ins_SSWCI, + /* SSW */ Ins_SSW, + + /* DUP */ Ins_DUP, + /* POP */ Ins_POP, + /* CLEAR */ Ins_CLEAR, + /* SWAP */ Ins_SWAP, + /* DEPTH */ Ins_DEPTH, + /* CINDEX */ Ins_CINDEX, + /* MINDEX */ Ins_MINDEX, + /* AlignPTS */ Ins_ALIGNPTS, + /* INS_0x28 */ Ins_UNKNOWN, + /* UTP */ Ins_UTP, + /* LOOPCALL */ Ins_LOOPCALL, + /* CALL */ Ins_CALL, + /* FDEF */ Ins_FDEF, + /* ENDF */ Ins_ENDF, + /* MDAP[0] */ Ins_MDAP, + /* MDAP[1] */ Ins_MDAP, + + /* IUP[0] */ Ins_IUP, + /* IUP[1] */ Ins_IUP, + /* SHP[0] */ Ins_SHP, + /* SHP[1] */ Ins_SHP, + /* SHC[0] */ Ins_SHC, + /* SHC[1] */ Ins_SHC, + /* SHZ[0] */ Ins_SHZ, + /* SHZ[1] */ Ins_SHZ, + /* SHPIX */ Ins_SHPIX, + /* IP */ Ins_IP, + /* MSIRP[0] */ Ins_MSIRP, + /* MSIRP[1] */ Ins_MSIRP, + /* AlignRP */ Ins_ALIGNRP, + /* RTDG */ Ins_RTDG, + /* MIAP[0] */ Ins_MIAP, + /* MIAP[1] */ Ins_MIAP, + + /* NPushB */ Ins_NPUSHB, + /* NPushW */ Ins_NPUSHW, + /* WS */ Ins_WS, + /* RS */ Ins_RS, + /* WCvtP */ Ins_WCVTP, + /* RCvt */ Ins_RCVT, + /* GC[0] */ Ins_GC, + /* GC[1] */ Ins_GC, + /* SCFS */ Ins_SCFS, + /* MD[0] */ Ins_MD, + /* MD[1] */ Ins_MD, + /* MPPEM */ Ins_MPPEM, + /* MPS */ Ins_MPS, + /* FlipON */ Ins_FLIPON, + /* FlipOFF */ Ins_FLIPOFF, + /* DEBUG */ Ins_DEBUG, + + /* LT */ Ins_LT, + /* LTEQ */ Ins_LTEQ, + /* GT */ Ins_GT, + /* GTEQ */ Ins_GTEQ, + /* EQ */ Ins_EQ, + /* NEQ */ Ins_NEQ, + /* ODD */ Ins_ODD, + /* EVEN */ Ins_EVEN, + /* IF */ Ins_IF, + /* EIF */ Ins_EIF, + /* AND */ Ins_AND, + /* OR */ Ins_OR, + /* NOT */ Ins_NOT, + /* DeltaP1 */ Ins_DELTAP, + /* SDB */ Ins_SDB, + /* SDS */ Ins_SDS, + + /* ADD */ Ins_ADD, + /* SUB */ Ins_SUB, + /* DIV */ Ins_DIV, + /* MUL */ Ins_MUL, + /* ABS */ Ins_ABS, + /* NEG */ Ins_NEG, + /* FLOOR */ Ins_FLOOR, + /* CEILING */ Ins_CEILING, + /* ROUND[0] */ Ins_ROUND, + /* ROUND[1] */ Ins_ROUND, + /* ROUND[2] */ Ins_ROUND, + /* ROUND[3] */ Ins_ROUND, + /* NROUND[0] */ Ins_NROUND, + /* NROUND[1] */ Ins_NROUND, + /* NROUND[2] */ Ins_NROUND, + /* NROUND[3] */ Ins_NROUND, + + /* WCvtF */ Ins_WCVTF, + /* DeltaP2 */ Ins_DELTAP, + /* DeltaP3 */ Ins_DELTAP, + /* DeltaCn[0] */ Ins_DELTAC, + /* DeltaCn[1] */ Ins_DELTAC, + /* DeltaCn[2] */ Ins_DELTAC, + /* SROUND */ Ins_SROUND, + /* S45Round */ Ins_S45ROUND, + /* JROT */ Ins_JROT, + /* JROF */ Ins_JROF, + /* ROFF */ Ins_ROFF, + /* INS_0x7B */ Ins_UNKNOWN, + /* RUTG */ Ins_RUTG, + /* RDTG */ Ins_RDTG, + /* SANGW */ Ins_SANGW, + /* AA */ Ins_AA, + + /* FlipPT */ Ins_FLIPPT, + /* FlipRgON */ Ins_FLIPRGON, + /* FlipRgOFF */ Ins_FLIPRGOFF, + /* INS_0x83 */ Ins_UNKNOWN, + /* INS_0x84 */ Ins_UNKNOWN, + /* ScanCTRL */ Ins_SCANCTRL, + /* SDPVTL[0] */ Ins_SDPVTL, + /* SDPVTL[1] */ Ins_SDPVTL, + /* GetINFO */ Ins_GETINFO, + /* IDEF */ Ins_IDEF, + /* ROLL */ Ins_ROLL, + /* MAX */ Ins_MAX, + /* MIN */ Ins_MIN, + /* ScanTYPE */ Ins_SCANTYPE, + /* InstCTRL */ Ins_INSTCTRL, + /* INS_0x8F */ Ins_UNKNOWN, + + /* INS_0x90 */ Ins_UNKNOWN, + /* INS_0x91 */ Ins_UNKNOWN, + /* INS_0x92 */ Ins_UNKNOWN, + /* INS_0x93 */ Ins_UNKNOWN, + /* INS_0x94 */ Ins_UNKNOWN, + /* INS_0x95 */ Ins_UNKNOWN, + /* INS_0x96 */ Ins_UNKNOWN, + /* INS_0x97 */ Ins_UNKNOWN, + /* INS_0x98 */ Ins_UNKNOWN, + /* INS_0x99 */ Ins_UNKNOWN, + /* INS_0x9A */ Ins_UNKNOWN, + /* INS_0x9B */ Ins_UNKNOWN, + /* INS_0x9C */ Ins_UNKNOWN, + /* INS_0x9D */ Ins_UNKNOWN, + /* INS_0x9E */ Ins_UNKNOWN, + /* INS_0x9F */ Ins_UNKNOWN, + + /* INS_0xA0 */ Ins_UNKNOWN, + /* INS_0xA1 */ Ins_UNKNOWN, + /* INS_0xA2 */ Ins_UNKNOWN, + /* INS_0xA3 */ Ins_UNKNOWN, + /* INS_0xA4 */ Ins_UNKNOWN, + /* INS_0xA5 */ Ins_UNKNOWN, + /* INS_0xA6 */ Ins_UNKNOWN, + /* INS_0xA7 */ Ins_UNKNOWN, + /* INS_0xA8 */ Ins_UNKNOWN, + /* INS_0xA9 */ Ins_UNKNOWN, + /* INS_0xAA */ Ins_UNKNOWN, + /* INS_0xAB */ Ins_UNKNOWN, + /* INS_0xAC */ Ins_UNKNOWN, + /* INS_0xAD */ Ins_UNKNOWN, + /* INS_0xAE */ Ins_UNKNOWN, + /* INS_0xAF */ Ins_UNKNOWN, + + /* PushB[0] */ Ins_PUSHB, + /* PushB[1] */ Ins_PUSHB, + /* PushB[2] */ Ins_PUSHB, + /* PushB[3] */ Ins_PUSHB, + /* PushB[4] */ Ins_PUSHB, + /* PushB[5] */ Ins_PUSHB, + /* PushB[6] */ Ins_PUSHB, + /* PushB[7] */ Ins_PUSHB, + /* PushW[0] */ Ins_PUSHW, + /* PushW[1] */ Ins_PUSHW, + /* PushW[2] */ Ins_PUSHW, + /* PushW[3] */ Ins_PUSHW, + /* PushW[4] */ Ins_PUSHW, + /* PushW[5] */ Ins_PUSHW, + /* PushW[6] */ Ins_PUSHW, + /* PushW[7] */ Ins_PUSHW, + + /* MDRP[00] */ Ins_MDRP, + /* MDRP[01] */ Ins_MDRP, + /* MDRP[02] */ Ins_MDRP, + /* MDRP[03] */ Ins_MDRP, + /* MDRP[04] */ Ins_MDRP, + /* MDRP[05] */ Ins_MDRP, + /* MDRP[06] */ Ins_MDRP, + /* MDRP[07] */ Ins_MDRP, + /* MDRP[08] */ Ins_MDRP, + /* MDRP[09] */ Ins_MDRP, + /* MDRP[10] */ Ins_MDRP, + /* MDRP[11] */ Ins_MDRP, + /* MDRP[12] */ Ins_MDRP, + /* MDRP[13] */ Ins_MDRP, + /* MDRP[14] */ Ins_MDRP, + /* MDRP[15] */ Ins_MDRP, + + /* MDRP[16] */ Ins_MDRP, + /* MDRP[17] */ Ins_MDRP, + /* MDRP[18] */ Ins_MDRP, + /* MDRP[19] */ Ins_MDRP, + /* MDRP[20] */ Ins_MDRP, + /* MDRP[21] */ Ins_MDRP, + /* MDRP[22] */ Ins_MDRP, + /* MDRP[23] */ Ins_MDRP, + /* MDRP[24] */ Ins_MDRP, + /* MDRP[25] */ Ins_MDRP, + /* MDRP[26] */ Ins_MDRP, + /* MDRP[27] */ Ins_MDRP, + /* MDRP[28] */ Ins_MDRP, + /* MDRP[29] */ Ins_MDRP, + /* MDRP[30] */ Ins_MDRP, + /* MDRP[31] */ Ins_MDRP, + + /* MIRP[00] */ Ins_MIRP, + /* MIRP[01] */ Ins_MIRP, + /* MIRP[02] */ Ins_MIRP, + /* MIRP[03] */ Ins_MIRP, + /* MIRP[04] */ Ins_MIRP, + /* MIRP[05] */ Ins_MIRP, + /* MIRP[06] */ Ins_MIRP, + /* MIRP[07] */ Ins_MIRP, + /* MIRP[08] */ Ins_MIRP, + /* MIRP[09] */ Ins_MIRP, + /* MIRP[10] */ Ins_MIRP, + /* MIRP[11] */ Ins_MIRP, + /* MIRP[12] */ Ins_MIRP, + /* MIRP[13] */ Ins_MIRP, + /* MIRP[14] */ Ins_MIRP, + /* MIRP[15] */ Ins_MIRP, + + /* MIRP[16] */ Ins_MIRP, + /* MIRP[17] */ Ins_MIRP, + /* MIRP[18] */ Ins_MIRP, + /* MIRP[19] */ Ins_MIRP, + /* MIRP[20] */ Ins_MIRP, + /* MIRP[21] */ Ins_MIRP, + /* MIRP[22] */ Ins_MIRP, + /* MIRP[23] */ Ins_MIRP, + /* MIRP[24] */ Ins_MIRP, + /* MIRP[25] */ Ins_MIRP, + /* MIRP[26] */ Ins_MIRP, + /* MIRP[27] */ Ins_MIRP, + /* MIRP[28] */ Ins_MIRP, + /* MIRP[29] */ Ins_MIRP, + /* MIRP[30] */ Ins_MIRP, + /* MIRP[31] */ Ins_MIRP + }; + + +#endif /* !TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + + /*************************************************************************/ + /* */ + /* RUN */ + /* */ + /* This function executes a run of opcodes. It will exit in the */ + /* following cases: */ + /* */ + /* - Errors (in which case it returns FALSE). */ + /* */ + /* - Reaching the end of the main code range (returns TRUE). */ + /* Reaching the end of a code range within a function call is an */ + /* error. */ + /* */ + /* - After executing one single opcode, if the flag `Instruction_Trap' */ + /* is set to TRUE (returns TRUE). */ + /* */ + /* On exit whith TRUE, test IP < CodeSize to know wether it comes from */ + /* an instruction trap or a normal termination. */ + /* */ + /* */ + /* Note: The documented DEBUG opcode pops a value from the stack. This */ + /* behaviour is unsupported; here a DEBUG opcode is always an */ + /* error. */ + /* */ + /* */ + /* THIS IS THE INTERPRETER'S MAIN LOOP. */ + /* */ + /* Instructions appear in the specification's order. */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_RunIns */ + /* */ + /* */ + /* Executes one or more instruction in the execution context. This */ + /* is the main function of the TrueType opcode interpreter. */ + /* */ + /* */ + /* exec :: A handle to the target execution context. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only the object manager and debugger should call this function. */ + /* */ + /* This function is publicly exported because it is directly */ + /* invoked by the TrueType debugger. */ + /* */ + FT_EXPORT_FUNC( FT_Error ) TT_RunIns( TT_ExecContext exc ) + { + FT_Long ins_counter = 0; /* executed instructions counter */ + + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + cur = *exc; +#endif + + /* set CVT functions */ + CUR.tt_metrics.ratio = 0; + if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem ) + { + /* non-square pixels, use the stretched routines */ + CUR.func_read_cvt = Read_CVT_Stretched; + CUR.func_write_cvt = Write_CVT_Stretched; + CUR.func_move_cvt = Move_CVT_Stretched; + } + else + { + /* square pixels, use normal routines */ + CUR.func_read_cvt = Read_CVT; + CUR.func_write_cvt = Write_CVT; + CUR.func_move_cvt = Move_CVT; + } + + COMPUTE_Funcs(); + COMPUTE_Round( (FT_Byte)exc->GS.round_state ); + + do + { + CUR.opcode = CUR.code[CUR.IP]; + + if ( ( CUR.length = opcode_length[CUR.opcode] ) < 0 ) + { + if ( CUR.IP + 1 > CUR.codeSize ) + goto LErrorCodeOverflow_; + + CUR.length = CUR.code[CUR.IP + 1] + 2; + } + + if ( CUR.IP + CUR.length > CUR.codeSize ) + goto LErrorCodeOverflow_; + + /* First, let's check for empty stack and overflow */ + CUR.args = CUR.top - ( Pop_Push_Count[CUR.opcode] >> 4 ); + + /* `args' is the top of the stack once arguments have been popped. */ + /* One can also interpret it as the index of the last argument. */ + if ( CUR.args < 0 ) + { + CUR.error = TT_Err_Too_Few_Arguments; + goto LErrorLabel_; + } + + CUR.new_top = CUR.args + ( Pop_Push_Count[CUR.opcode] & 15 ); + + /* `new_top' is the new top of the stack, after the instruction's */ + /* execution. `top' will be set to `new_top' after the `switch' */ + /* statement. */ + if ( CUR.new_top > CUR.stackSize ) + { + CUR.error = TT_Err_Stack_Overflow; + goto LErrorLabel_; + } + + CUR.step_ins = TRUE; + CUR.error = TT_Err_Ok; + +#ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH + + { + FT_Long* args = CUR.stack + CUR.args; + FT_Byte opcode = CUR.opcode; + + +#undef ARRAY_BOUND_ERROR +#define ARRAY_BOUND_ERROR goto Set_Invalid_Ref + + + switch ( opcode ) + { + case 0x00: /* SVTCA y */ + case 0x01: /* SVTCA x */ + case 0x02: /* SPvTCA y */ + case 0x03: /* SPvTCA x */ + case 0x04: /* SFvTCA y */ + case 0x05: /* SFvTCA x */ + { + FT_Short AA, BB; + + + AA = (FT_Short)( opcode & 1 ) << 14; + BB = AA ^ (FT_Short)0x4000; + + if ( opcode < 4 ) + { + CUR.GS.projVector.x = AA; + CUR.GS.projVector.y = BB; + + CUR.GS.dualVector.x = AA; + CUR.GS.dualVector.y = BB; + } + + if ( ( opcode & 2 ) == 0 ) + { + CUR.GS.freeVector.x = AA; + CUR.GS.freeVector.y = BB; + } + + COMPUTE_Funcs(); + } + break; + + case 0x06: /* SPvTL // */ + case 0x07: /* SPvTL + */ + DO_SPVTL + break; + + case 0x08: /* SFvTL // */ + case 0x09: /* SFvTL + */ + DO_SFVTL + break; + + case 0x0A: /* SPvFS */ + DO_SPVFS + break; + + case 0x0B: /* SFvFS */ + DO_SFVFS + break; + + case 0x0C: /* GPV */ + DO_GPV + break; + + case 0x0D: /* GFV */ + DO_GFV + break; + + case 0x0E: /* SFvTPv */ + DO_SFVTPV + break; + + case 0x0F: /* ISECT */ + Ins_ISECT( EXEC_ARG_ args ); + break; + + case 0x10: /* SRP0 */ + DO_SRP0 + break; + + case 0x11: /* SRP1 */ + DO_SRP1 + break; + + case 0x12: /* SRP2 */ + DO_SRP2 + break; + + case 0x13: /* SZP0 */ + Ins_SZP0( EXEC_ARG_ args ); + break; + + case 0x14: /* SZP1 */ + Ins_SZP1( EXEC_ARG_ args ); + break; + + case 0x15: /* SZP2 */ + Ins_SZP2( EXEC_ARG_ args ); + break; + + case 0x16: /* SZPS */ + Ins_SZPS( EXEC_ARG_ args ); + break; + + case 0x17: /* SLOOP */ + DO_SLOOP + break; + + case 0x18: /* RTG */ + DO_RTG + break; + + case 0x19: /* RTHG */ + DO_RTHG + break; + + case 0x1A: /* SMD */ + DO_SMD + break; + + case 0x1B: /* ELSE */ + Ins_ELSE( EXEC_ARG_ args ); + break; + + case 0x1C: /* JMPR */ + DO_JMPR + break; + + case 0x1D: /* SCVTCI */ + DO_SCVTCI + break; + + case 0x1E: /* SSWCI */ + DO_SSWCI + break; + + case 0x1F: /* SSW */ + DO_SSW + break; + + case 0x20: /* DUP */ + DO_DUP + break; + + case 0x21: /* POP */ + /* nothing :-) */ + break; + + case 0x22: /* CLEAR */ + DO_CLEAR + break; + + case 0x23: /* SWAP */ + DO_SWAP + break; + + case 0x24: /* DEPTH */ + DO_DEPTH + break; + + case 0x25: /* CINDEX */ + DO_CINDEX + break; + + case 0x26: /* MINDEX */ + Ins_MINDEX( EXEC_ARG_ args ); + break; + + case 0x27: /* ALIGNPTS */ + Ins_ALIGNPTS( EXEC_ARG_ args ); + break; + + case 0x28: /* ???? */ + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + case 0x29: /* UTP */ + Ins_UTP( EXEC_ARG_ args ); + break; + + case 0x2A: /* LOOPCALL */ + Ins_LOOPCALL( EXEC_ARG_ args ); + break; + + case 0x2B: /* CALL */ + Ins_CALL( EXEC_ARG_ args ); + break; + + case 0x2C: /* FDEF */ + Ins_FDEF( EXEC_ARG_ args ); + break; + + case 0x2D: /* ENDF */ + Ins_ENDF( EXEC_ARG_ args ); + break; + + case 0x2E: /* MDAP */ + case 0x2F: /* MDAP */ + Ins_MDAP( EXEC_ARG_ args ); + break; + + + case 0x30: /* IUP */ + case 0x31: /* IUP */ + Ins_IUP( EXEC_ARG_ args ); + break; + + case 0x32: /* SHP */ + case 0x33: /* SHP */ + Ins_SHP( EXEC_ARG_ args ); + break; + + case 0x34: /* SHC */ + case 0x35: /* SHC */ + Ins_SHC( EXEC_ARG_ args ); + break; + + case 0x36: /* SHZ */ + case 0x37: /* SHZ */ + Ins_SHZ( EXEC_ARG_ args ); + break; + + case 0x38: /* SHPIX */ + Ins_SHPIX( EXEC_ARG_ args ); + break; + + case 0x39: /* IP */ + Ins_IP( EXEC_ARG_ args ); + break; + + case 0x3A: /* MSIRP */ + case 0x3B: /* MSIRP */ + Ins_MSIRP( EXEC_ARG_ args ); + break; + + case 0x3C: /* AlignRP */ + Ins_ALIGNRP( EXEC_ARG_ args ); + break; + + case 0x3D: /* RTDG */ + DO_RTDG + break; + + case 0x3E: /* MIAP */ + case 0x3F: /* MIAP */ + Ins_MIAP( EXEC_ARG_ args ); + break; + + case 0x40: /* NPUSHB */ + Ins_NPUSHB( EXEC_ARG_ args ); + break; + + case 0x41: /* NPUSHW */ + Ins_NPUSHW( EXEC_ARG_ args ); + break; + + case 0x42: /* WS */ + DO_WS + break; + + Set_Invalid_Ref: + CUR.error = TT_Err_Invalid_Reference; + break; + + case 0x43: /* RS */ + DO_RS + break; + + case 0x44: /* WCVTP */ + DO_WCVTP + break; + + case 0x45: /* RCVT */ + DO_RCVT + break; + + case 0x46: /* GC */ + case 0x47: /* GC */ + Ins_GC( EXEC_ARG_ args ); + break; + + case 0x48: /* SCFS */ + Ins_SCFS( EXEC_ARG_ args ); + break; + + case 0x49: /* MD */ + case 0x4A: /* MD */ + Ins_MD( EXEC_ARG_ args ); + break; + + case 0x4B: /* MPPEM */ + DO_MPPEM + break; + + case 0x4C: /* MPS */ + DO_MPS + break; + + case 0x4D: /* FLIPON */ + DO_FLIPON + break; + + case 0x4E: /* FLIPOFF */ + DO_FLIPOFF + break; + + case 0x4F: /* DEBUG */ + DO_DEBUG + break; + + case 0x50: /* LT */ + DO_LT + break; + + case 0x51: /* LTEQ */ + DO_LTEQ + break; + + case 0x52: /* GT */ + DO_GT + break; + + case 0x53: /* GTEQ */ + DO_GTEQ + break; + + case 0x54: /* EQ */ + DO_EQ + break; + + case 0x55: /* NEQ */ + DO_NEQ + break; + + case 0x56: /* ODD */ + DO_ODD + break; + + case 0x57: /* EVEN */ + DO_EVEN + break; + + case 0x58: /* IF */ + Ins_IF( EXEC_ARG_ args ); + break; + + case 0x59: /* EIF */ + /* do nothing */ + break; + + case 0x5A: /* AND */ + DO_AND + break; + + case 0x5B: /* OR */ + DO_OR + break; + + case 0x5C: /* NOT */ + DO_NOT + break; + + case 0x5D: /* DELTAP1 */ + Ins_DELTAP( EXEC_ARG_ args ); + break; + + case 0x5E: /* SDB */ + DO_SDB + break; + + case 0x5F: /* SDS */ + DO_SDS + break; + + case 0x60: /* ADD */ + DO_ADD + break; + + case 0x61: /* SUB */ + DO_SUB + break; + + case 0x62: /* DIV */ + DO_DIV + break; + + case 0x63: /* MUL */ + DO_MUL + break; + + case 0x64: /* ABS */ + DO_ABS + break; + + case 0x65: /* NEG */ + DO_NEG + break; + + case 0x66: /* FLOOR */ + DO_FLOOR + break; + + case 0x67: /* CEILING */ + DO_CEILING + break; + + case 0x68: /* ROUND */ + case 0x69: /* ROUND */ + case 0x6A: /* ROUND */ + case 0x6B: /* ROUND */ + DO_ROUND + break; + + case 0x6C: /* NROUND */ + case 0x6D: /* NROUND */ + case 0x6E: /* NRRUND */ + case 0x6F: /* NROUND */ + DO_NROUND + break; + + case 0x70: /* WCVTF */ + DO_WCVTF + break; + + case 0x71: /* DELTAP2 */ + case 0x72: /* DELTAP3 */ + Ins_DELTAP( EXEC_ARG_ args ); + break; + + case 0x73: /* DELTAC0 */ + case 0x74: /* DELTAC1 */ + case 0x75: /* DELTAC2 */ + Ins_DELTAC( EXEC_ARG_ args ); + break; + + case 0x76: /* SROUND */ + DO_SROUND + break; + + case 0x77: /* S45Round */ + DO_S45ROUND + break; + + case 0x78: /* JROT */ + DO_JROT + break; + + case 0x79: /* JROF */ + DO_JROF + break; + + case 0x7A: /* ROFF */ + DO_ROFF + break; + + case 0x7B: /* ???? */ + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + case 0x7C: /* RUTG */ + DO_RUTG + break; + + case 0x7D: /* RDTG */ + DO_RDTG + break; + + case 0x7E: /* SANGW */ + case 0x7F: /* AA */ + /* nothing - obsolete */ + break; + + case 0x80: /* FLIPPT */ + Ins_FLIPPT( EXEC_ARG_ args ); + break; + + case 0x81: /* FLIPRGON */ + Ins_FLIPRGON( EXEC_ARG_ args ); + break; + + case 0x82: /* FLIPRGOFF */ + Ins_FLIPRGOFF( EXEC_ARG_ args ); + break; + + case 0x83: /* UNKNOWN */ + case 0x84: /* UNKNOWN */ + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + case 0x85: /* SCANCTRL */ + Ins_SCANCTRL( EXEC_ARG_ args ); + break; + + case 0x86: /* SDPVTL */ + case 0x87: /* SDPVTL */ + Ins_SDPVTL( EXEC_ARG_ args ); + break; + + case 0x88: /* GETINFO */ + Ins_GETINFO( EXEC_ARG_ args ); + break; + + case 0x89: /* IDEF */ + Ins_IDEF( EXEC_ARG_ args ); + break; + + case 0x8A: /* ROLL */ + Ins_ROLL( EXEC_ARG_ args ); + break; + + case 0x8B: /* MAX */ + DO_MAX + break; + + case 0x8C: /* MIN */ + DO_MIN + break; + + case 0x8D: /* SCANTYPE */ + Ins_SCANTYPE( EXEC_ARG_ args ); + break; + + case 0x8E: /* INSTCTRL */ + Ins_INSTCTRL( EXEC_ARG_ args ); + break; + + case 0x8F: + Ins_UNKNOWN( EXEC_ARG_ args ); + break; + + default: + if ( opcode >= 0xE0 ) + Ins_MIRP( EXEC_ARG_ args ); + else if ( opcode >= 0xC0 ) + Ins_MDRP( EXEC_ARG_ args ); + else if ( opcode >= 0xB8 ) + Ins_PUSHW( EXEC_ARG_ args ); + else if ( opcode >= 0xB0 ) + Ins_PUSHB( EXEC_ARG_ args ); + else + Ins_UNKNOWN( EXEC_ARG_ args ); + } + + } + +#else + + Instruct_Dispatch[CUR.opcode]( EXEC_ARG_ &CUR.stack[CUR.args] ); + +#endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */ + + if ( CUR.error != TT_Err_Ok ) + { + switch ( CUR.error ) + { + case TT_Err_Invalid_Opcode: /* looking for redefined instructions */ + { + TT_DefRecord* def = CUR.IDefs; + TT_DefRecord* limit = def + CUR.numIDefs; + + + for ( ; def < limit; def++ ) + { + if ( def->active && CUR.opcode == def->opc ) + { + TT_CallRec* callrec; + + + if ( CUR.callTop >= CUR.callSize ) + { + CUR.error = TT_Err_Invalid_Reference; + goto LErrorLabel_; + } + + callrec = &CUR.callStack[CUR.callTop]; + + callrec->Caller_Range = CUR.curRange; + callrec->Caller_IP = CUR.IP + 1; + callrec->Cur_Count = 1; + callrec->Cur_Restart = def->start; + + if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE ) + goto LErrorLabel_; + + goto LSuiteLabel_; + } + } + } + + CUR.error = TT_Err_Invalid_Opcode; + goto LErrorLabel_; + +#if 0 + break; /* Unreachable code warning suppression. */ + /* Leave to remind in case a later change the editor */ + /* to consider break; */ +#endif + + default: + goto LErrorLabel_; + +#if 0 + break; +#endif + } + } + + CUR.top = CUR.new_top; + + if ( CUR.step_ins ) + CUR.IP += CUR.length; + + /* increment instruction counter and check if we didn't */ + /* run this program for too long (e.g. infinite loops). */ + if ( ++ins_counter > MAX_RUNNABLE_OPCODES ) + return TT_Err_Execution_Too_Long; + + LSuiteLabel_: + if ( CUR.IP >= CUR.codeSize ) + { + if ( CUR.callTop > 0 ) + { + CUR.error = TT_Err_Code_Overflow; + goto LErrorLabel_; + } + else + goto LNo_Error_; + } + } while ( !CUR.instruction_trap ); + + LNo_Error_: + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + *exc = cur; +#endif + + return TT_Err_Ok; + + LErrorCodeOverflow_: + CUR.error = TT_Err_Code_Overflow; + + LErrorLabel_: + +#ifdef TT_CONFIG_OPTION_STATIC_RASTER + *exc = cur; +#endif + + return CUR.error; + } + + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttinterp.h b/subsys/win32k/freetype/src/truetype/ttinterp.h new file mode 100644 index 0000000..3283e02 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttinterp.h @@ -0,0 +1,278 @@ +/***************************************************************************/ +/* */ +/* ttinterp.h */ +/* */ +/* TrueType bytecode interpreter (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTINTERP_H +#define TTINTERP_H + + +#ifdef FT_FLAT_COMPILE + +#include "ttobjs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifndef TT_CONFIG_OPTION_STATIC_INTEPRETER /* indirect implementation */ + +#define EXEC_OP_ TT_ExecContext exc, +#define EXEC_OP TT_ExecContext exc +#define EXEC_ARG_ exc, +#define EXEC_ARG exc + +#else /* static implementation */ + +#define EXEC_OP_ /* void */ +#define EXEC_OP /* void */ +#define EXEC_ARG_ /* void */ +#define EXEC_ARG /* void */ + +#endif /* TT_CONFIG_OPTION_STATIC_INTERPRETER */ + + + /*************************************************************************/ + /* */ + /* Rounding mode constants. */ + /* */ +#define TT_Round_Off 5 +#define TT_Round_To_Half_Grid 0 +#define TT_Round_To_Grid 1 +#define TT_Round_To_Double_Grid 2 +#define TT_Round_Up_To_Grid 4 +#define TT_Round_Down_To_Grid 3 +#define TT_Round_Super 6 +#define TT_Round_Super_45 7 + + + /*************************************************************************/ + /* */ + /* Function types used by the interpreter, depending on various modes */ + /* (e.g. the rounding mode, whether to render a vertical or horizontal */ + /* line etc). */ + /* */ + /*************************************************************************/ + + /* Rounding function */ + typedef FT_F26Dot6 (*TT_Round_Func)( EXEC_OP_ FT_F26Dot6 distance, + FT_F26Dot6 compensation ); + + /* Point displacement along the freedom vector routine */ + typedef void (*TT_Move_Func)( EXEC_OP_ TT_GlyphZone* zone, + FT_UInt point, + FT_F26Dot6 distance ); + + /* Distance projection along one of the projection vectors */ + typedef FT_F26Dot6 (*TT_Project_Func)( EXEC_OP_ FT_Vector* v1, + FT_Vector* v2 ); + + /* reading a cvt value. Take care of non-square pixels if necessary */ + typedef FT_F26Dot6 (*TT_Get_CVT_Func)( EXEC_OP_ FT_ULong index ); + + /* setting or moving a cvt value. Take care of non-square pixels */ + /* if necessary */ + typedef void (*TT_Set_CVT_Func)( EXEC_OP_ FT_ULong index, + FT_F26Dot6 value ); + + + /*************************************************************************/ + /* */ + /* This structure defines a call record, used to manage function calls. */ + /* */ + typedef struct TT_CallRec_ + { + FT_Int Caller_Range; + FT_Long Caller_IP; + FT_Long Cur_Count; + FT_Long Cur_Restart; + + } TT_CallRec, *TT_CallStack; + + + /*************************************************************************/ + /* */ + /* The main structure for the interpreter which collects all necessary */ + /* variables and states. */ + /* */ + typedef struct TT_ExecContextRec_ + { + TT_Face face; + TT_Size size; + FT_Memory memory; + + /* instructions state */ + + FT_Error error; /* last execution error */ + + FT_Long top; /* top of exec. stack */ + + FT_UInt stackSize; /* size of exec. stack */ + FT_Long* stack; /* current exec. stack */ + + FT_Long args; + FT_UInt new_top; /* new top after exec. */ + + TT_GlyphZone zp0, /* zone records */ + zp1, + zp2, + pts, + twilight; + + FT_Size_Metrics metrics; + TT_Size_Metrics tt_metrics; /* size metrics */ + + TT_GraphicsState GS; /* current graphics state */ + + FT_Int curRange; /* current code range number */ + FT_Byte* code; /* current code range */ + FT_Long IP; /* current instruction pointer */ + FT_Long codeSize; /* size of current range */ + + FT_Byte opcode; /* current opcode */ + FT_Int length; /* length of current opcode */ + + FT_Bool step_ins; /* true if the interpreter must */ + /* increment IP after ins. exec */ + FT_Long cvtSize; + FT_Long* cvt; + + FT_UInt glyphSize; /* glyph instructions buffer size */ + FT_Byte* glyphIns; /* glyph instructions buffer */ + + FT_UInt numFDefs; /* number of function defs */ + FT_UInt maxFDefs; /* maximum number of function defs */ + TT_DefArray FDefs; /* table of FDefs entries */ + + FT_UInt numIDefs; /* number of instruction defs */ + FT_UInt maxIDefs; /* maximum number of ins defs */ + TT_DefArray IDefs; /* table of IDefs entries */ + + FT_UInt maxFunc; /* maximum function index */ + FT_UInt maxIns; /* maximum instruction index */ + + FT_Int callTop, /* top of call stack during execution */ + callSize; /* size of call stack */ + TT_CallStack callStack; /* call stack */ + + FT_UShort maxPoints; /* capacity of this context's `pts' */ + FT_Short maxContours; /* record, expressed in points and */ + /* contours. */ + + TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */ + /* useful for the debugger */ + + FT_UShort storeSize; /* size of current storage */ + FT_Long* storage; /* storage area */ + + FT_F26Dot6 period; /* values used for the */ + FT_F26Dot6 phase; /* `SuperRounding' */ + FT_F26Dot6 threshold; + +#if 0 + /* this seems to be unused */ + FT_Int cur_ppem; /* ppem along the current proj vector */ +#endif + + FT_Bool instruction_trap; /* If `True', the interpreter will */ + /* exit after each instruction */ + + TT_GraphicsState default_GS; /* graphics state resulting from */ + /* the prep program */ + FT_Bool is_composite; /* true if the glyph is composite */ + FT_Bool pedantic_hinting; /* true for pedantic interpretation */ + + /* latest interpreter additions */ + + FT_Long F_dot_P; /* dot product of freedom and projection */ + /* vectors */ + TT_Round_Func func_round; /* current rounding function */ + + TT_Project_Func func_project, /* current projection function */ + func_dualproj, /* current dual proj. function */ + func_freeProj; /* current freedom proj. func */ + + TT_Move_Func func_move; /* current point move function */ + + TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */ + TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */ + TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */ + + FT_ULong loadSize; + TT_SubGlyph_Stack loadStack; /* loading subglyph stack */ + + } TT_ExecContextRec; + + + extern const TT_GraphicsState tt_default_graphics_state; + + + LOCAL_DEF + FT_Error TT_Goto_CodeRange( TT_ExecContext exec, + FT_Int range, + FT_Long IP ); + + LOCAL_DEF + FT_Error TT_Set_CodeRange( TT_ExecContext exec, + FT_Int range, + void* base, + FT_Long length ); + + LOCAL_DEF + FT_Error TT_Clear_CodeRange( TT_ExecContext exec, + FT_Int range ); + + FT_EXPORT_DEF( TT_ExecContext ) TT_New_Context( TT_Face face ); + + LOCAL_DEF + FT_Error TT_Done_Context( TT_ExecContext exec ); + + LOCAL_DEF + FT_Error TT_Destroy_Context( TT_ExecContext exec, + FT_Memory memory ); + + LOCAL_DEF + FT_Error TT_Load_Context( TT_ExecContext exec, + TT_Face face, + TT_Size size ); + + LOCAL_DEF + FT_Error TT_Save_Context( TT_ExecContext exec, + TT_Size ins ); + + LOCAL_DEF + FT_Error TT_Run_Context( TT_ExecContext exec, + FT_Bool debug ); + + FT_EXPORT_DEF( FT_Error ) TT_RunIns( TT_ExecContext exec ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTINTERP_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttobjs.c b/subsys/win32k/freetype/src/truetype/ttobjs.c new file mode 100644 index 0000000..f19ed79 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttobjs.c @@ -0,0 +1,734 @@ +/***************************************************************************/ +/* */ +/* ttobjs.c */ +/* */ +/* Objects manager (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "ttgload.h" +#include "ttpload.h" + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include "ttinterp.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include + + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttobjs + + + /*************************************************************************/ + /* */ + /* GLYPH ZONE FUNCTIONS */ + /* */ + /*************************************************************************/ + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_GlyphZone */ + /* */ + /* */ + /* Deallocates a glyph zone. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone. */ + /* */ + LOCAL_FUNC + void TT_Done_GlyphZone( TT_GlyphZone* zone ) + { + FT_Memory memory = zone->memory; + + + FREE( zone->contours ); + FREE( zone->tags ); + FREE( zone->cur ); + FREE( zone->org ); + + zone->max_points = zone->n_points = 0; + zone->max_contours = zone->n_contours = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_New_GlyphZone */ + /* */ + /* */ + /* Allocates a new glyph zone. */ + /* */ + /* */ + /* memory :: A handle to the current memory object. */ + /* */ + /* maxPoints :: The capacity of glyph zone in points. */ + /* */ + /* maxContours :: The capacity of glyph zone in contours. */ + /* */ + /* */ + /* zone :: A pointer to the target glyph zone record. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_New_GlyphZone( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + TT_GlyphZone* zone ) + { + FT_Error error; + + + if ( maxPoints > 0 ) + maxPoints += 2; + + MEM_Set( zone, 0, sizeof ( *zone ) ); + zone->memory = memory; + + if ( ALLOC_ARRAY( zone->org, maxPoints * 2, FT_F26Dot6 ) || + ALLOC_ARRAY( zone->cur, maxPoints * 2, FT_F26Dot6 ) || + ALLOC_ARRAY( zone->tags, maxPoints, FT_Byte ) || + ALLOC_ARRAY( zone->contours, maxContours, FT_UShort ) ) + { + TT_Done_GlyphZone( zone ); + } + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Face */ + /* */ + /* */ + /* Initializes a given TrueType face object. */ + /* */ + /* */ + /* stream :: The source font stream. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* */ + /* face :: The newly built face object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Library library; + SFNT_Interface* sfnt; + + + library = face->root.driver->root.library; + sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" ); + if ( !sfnt ) + goto Bad_Format; + + /* create input stream from resource */ + if ( FILE_Seek( 0 ) ) + goto Exit; + + /* check that we have a valid TrueType file */ + error = sfnt->init_face( stream, face, face_index, num_params, params ); + if ( error ) + goto Exit; + + /* We must also be able to accept Mac/GX fonts, as well as OT ones */ + if ( face->format_tag != 0x00010000L && /* MS fonts */ + face->format_tag != TTAG_true ) /* Mac fonts */ + { + FT_TRACE2(( "[not a valid TTF font]\n" )); + goto Bad_Format; + } + + /* If we are performing a simple font format check, exit immediately */ + if ( face_index < 0 ) + return TT_Err_Ok; + + /* Load font directory */ + error = sfnt->load_face( stream, face, face_index, num_params, params ); + if ( error ) + goto Exit; + + error = TT_Load_Locations( face, stream ) || + TT_Load_CVT ( face, stream ) || + TT_Load_Programs ( face, stream ); + + /* initialize standard glyph loading routines */ + TT_Init_Glyph_Loading( face ); + + Exit: + return error; + + Bad_Format: + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Face */ + /* */ + /* */ + /* Finalizes a given face object. */ + /* */ + /* */ + /* face :: A pointer to the face object to destroy. */ + /* */ + LOCAL_DEF + void TT_Done_Face( TT_Face face ) + { + FT_Memory memory = face->root.memory; + FT_Stream stream = face->root.stream; + + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + + /* for `extended TrueType formats' (i.e. compressed versions) */ + if ( face->extra.finalizer ) + face->extra.finalizer( face->extra.data ); + + if ( sfnt ) + sfnt->done_face( face ); + + /* freeing the locations table */ + FREE( face->glyph_locations ); + face->num_locations = 0; + + /* freeing the CVT */ + FREE( face->cvt ); + face->cvt_size = 0; + + /* freeing the programs */ + RELEASE_Frame( face->font_program ); + RELEASE_Frame( face->cvt_program ); + face->font_program_size = 0; + face->cvt_program_size = 0; + } + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Size */ + /* */ + /* */ + /* Initializes a new TrueType size object. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Size( TT_Size size ) + { + FT_Error error = TT_Err_Ok; + + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + TT_Face face = (TT_Face)size->root.face; + FT_Memory memory = face->root.memory; + FT_Int i; + + TT_ExecContext exec; + FT_UShort n_twilight; + TT_MaxProfile* maxp = &face->max_profile; + + + size->ttmetrics.valid = FALSE; + + size->max_function_defs = maxp->maxFunctionDefs; + size->max_instruction_defs = maxp->maxInstructionDefs; + + size->num_function_defs = 0; + size->num_instruction_defs = 0; + + size->max_func = 0; + size->max_ins = 0; + + size->cvt_size = face->cvt_size; + size->storage_size = maxp->maxStorage; + + /* Set default metrics */ + { + FT_Size_Metrics* metrics = &size->root.metrics; + TT_Size_Metrics* metrics2 = &size->ttmetrics; + + + metrics->x_ppem = 0; + metrics->y_ppem = 0; + + metrics2->rotated = FALSE; + metrics2->stretched = FALSE; + + /* set default compensation (all 0) */ + for ( i = 0; i < 4; i++ ) + metrics2->compensations[i] = 0; + } + + /* allocate function defs, instruction defs, cvt, and storage area */ + if ( ALLOC_ARRAY( size->function_defs, + size->max_function_defs, + TT_DefRecord ) || + + ALLOC_ARRAY( size->instruction_defs, + size->max_instruction_defs, + TT_DefRecord ) || + + ALLOC_ARRAY( size->cvt, + size->cvt_size, FT_Long ) || + + ALLOC_ARRAY( size->storage, + size->storage_size, FT_Long ) ) + + goto Fail_Memory; + + /* reserve twilight zone */ + n_twilight = maxp->maxTwilightPoints; + error = TT_New_GlyphZone( memory, n_twilight, 0, &size->twilight ); + if ( error ) + goto Fail_Memory; + + size->twilight.n_points = n_twilight; + + /* set `face->interpreter' according to the debug hook present */ + { + FT_Library library = face->root.driver->root.library; + + + face->interpreter = (TT_Interpreter) + library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; + if ( !face->interpreter ) + face->interpreter = (TT_Interpreter)TT_RunIns; + } + + /* Fine, now execute the font program! */ + exec = size->context; + /* size objects used during debugging have their own context */ + if ( !size->debug ) + exec = TT_New_Context( face ); + + if ( !exec ) + { + error = TT_Err_Could_Not_Find_Context; + goto Fail_Memory; + } + + size->GS = tt_default_graphics_state; + TT_Load_Context( exec, face, size ); + + exec->callTop = 0; + exec->top = 0; + + exec->period = 64; + exec->phase = 0; + exec->threshold = 0; + + { + FT_Size_Metrics* metrics = &exec->metrics; + TT_Size_Metrics* tt_metrics = &exec->tt_metrics; + + + metrics->x_ppem = 0; + metrics->y_ppem = 0; + metrics->x_scale = 0; + metrics->y_scale = 0; + + tt_metrics->ppem = 0; + tt_metrics->scale = 0; + tt_metrics->ratio = 0x10000L; + } + + exec->instruction_trap = FALSE; + + exec->cvtSize = size->cvt_size; + exec->cvt = size->cvt; + + exec->F_dot_P = 0x10000L; + + /* allow font program execution */ + TT_Set_CodeRange( exec, + tt_coderange_font, + face->font_program, + face->font_program_size ); + + /* disable CVT and glyph programs coderange */ + TT_Clear_CodeRange( exec, tt_coderange_cvt ); + TT_Clear_CodeRange( exec, tt_coderange_glyph ); + + if ( face->font_program_size > 0 ) + { + error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); + if ( !error ) + error = face->interpreter( exec ); + + if ( error ) + goto Fail_Exec; + } + else + error = TT_Err_Ok; + + TT_Save_Context( exec, size ); + + if ( !size->debug ) + TT_Done_Context( exec ); + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + size->ttmetrics.valid = FALSE; + return error; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + Fail_Exec: + if ( !size->debug ) + TT_Done_Context( exec ); + + Fail_Memory: + +#endif + + TT_Done_Size( size ); + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Size */ + /* */ + /* */ + /* The TrueType size object finalizer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void TT_Done_Size( TT_Size size ) + { + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_Memory memory = size->root.face->memory; + + + if ( size->debug ) + { + /* the debug context must be deleted by the debugger itself */ + size->context = NULL; + size->debug = FALSE; + } + + FREE( size->cvt ); + size->cvt_size = 0; + + /* free storage area */ + FREE( size->storage ); + size->storage_size = 0; + + /* twilight zone */ + TT_Done_GlyphZone( &size->twilight ); + + FREE( size->function_defs ); + FREE( size->instruction_defs ); + + size->num_function_defs = 0; + size->max_function_defs = 0; + size->num_instruction_defs = 0; + size->max_instruction_defs = 0; + + size->max_func = 0; + size->max_ins = 0; + +#endif + + size->ttmetrics.valid = FALSE; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Reset_Size */ + /* */ + /* */ + /* Resets a TrueType size when resolutions and character dimensions */ + /* have been changed. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_DEF + FT_Error TT_Reset_Size( TT_Size size ) + { + TT_Face face; + FT_Error error = TT_Err_Ok; + + FT_Size_Metrics* metrics; + + + if ( size->ttmetrics.valid ) + return TT_Err_Ok; + + face = (TT_Face)size->root.face; + + metrics = &size->root.metrics; + + if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + return TT_Err_Invalid_PPem; + + /* compute new transformation */ + if ( metrics->x_ppem >= metrics->y_ppem ) + { + size->ttmetrics.scale = metrics->x_scale; + size->ttmetrics.ppem = metrics->x_ppem; + size->ttmetrics.x_ratio = 0x10000L; + size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem, + 0x10000L, + metrics->x_ppem ); + } + else + { + size->ttmetrics.scale = metrics->y_scale; + size->ttmetrics.ppem = metrics->y_ppem; + size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem, + 0x10000L, + metrics->y_ppem ); + size->ttmetrics.y_ratio = 0x10000L; + } + + /* Compute root ascender, descender, test height, and max_advance */ + metrics->ascender = ( FT_MulFix( face->root.ascender, + metrics->y_scale ) + 32 ) & -64; + metrics->descender = ( FT_MulFix( face->root.descender, + metrics->y_scale ) + 32 ) & -64; + metrics->height = ( FT_MulFix( face->root.height, + metrics->y_scale ) + 32 ) & -64; + metrics->max_advance = ( FT_MulFix( face->root.max_advance_width, + metrics->x_scale ) + 32 ) & -64; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + { + TT_ExecContext exec; + FT_UInt i, j; + + + /* Scale the cvt values to the new ppem. */ + /* We use by default the y ppem to scale the CVT. */ + for ( i = 0; i < size->cvt_size; i++ ) + size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); + + /* All twilight points are originally zero */ + for ( j = 0; j < size->twilight.n_points; j++ ) + { + size->twilight.org[j].x = 0; + size->twilight.org[j].y = 0; + size->twilight.cur[j].x = 0; + size->twilight.cur[j].y = 0; + } + + /* clear storage area */ + for ( i = 0; i < size->storage_size; i++ ) + size->storage[i] = 0; + + size->GS = tt_default_graphics_state; + + /* get execution context and run prep program */ + if ( size->debug ) + exec = size->context; + else + exec = TT_New_Context( face ); + /* debugging instances have their own context */ + + if ( !exec ) + return TT_Err_Could_Not_Find_Context; + + TT_Load_Context( exec, face, size ); + + TT_Set_CodeRange( exec, + tt_coderange_cvt, + face->cvt_program, + face->cvt_program_size ); + + TT_Clear_CodeRange( exec, tt_coderange_glyph ); + + exec->instruction_trap = FALSE; + + exec->top = 0; + exec->callTop = 0; + + if ( face->cvt_program_size > 0 ) + { + error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); + if ( error ) + goto End; + + if ( !size->debug ) + error = face->interpreter( exec ); + } + else + error = TT_Err_Ok; + + size->GS = exec->GS; + /* save default graphics state */ + + End: + TT_Save_Context( exec, size ); + + if ( !size->debug ) + TT_Done_Context( exec ); + /* debugging instances keep their context */ + } + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + if ( !error ) + size->ttmetrics.valid = TRUE; + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Init_Driver */ + /* */ + /* */ + /* Initializes a given TrueType driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Init_Driver( TT_Driver driver ) + { + FT_Error error; + + + /* set `extra' in glyph loader */ + error = FT_GlyphLoader_Create_Extra( FT_DRIVER( driver )->glyph_loader ); + + /* init extension registry if needed */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + if ( !error ) + return TT_Init_Extensions( driver ); +#endif + + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Done_Driver */ + /* */ + /* */ + /* Finalizes a given TrueType driver. */ + /* */ + /* */ + /* driver :: A handle to the target TrueType driver. */ + /* */ + LOCAL_FUNC + void TT_Done_Driver( TT_Driver driver ) + { + /* destroy extensions registry if needed */ + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + + TT_Done_Extensions( driver ); + +#endif + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + /* destroy the execution context */ + if ( driver->context ) + { + TT_Destroy_Context( driver->context, driver->root.root.memory ); + driver->context = NULL; + } + +#endif + + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttobjs.h b/subsys/win32k/freetype/src/truetype/ttobjs.h new file mode 100644 index 0000000..3e55de3 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttobjs.h @@ -0,0 +1,412 @@ +/***************************************************************************/ +/* */ +/* ttobjs.h */ +/* */ +/* Objects manager (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTOBJS_H +#define TTOBJS_H + + +#include +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Driver */ + /* */ + /* */ + /* A handle to a TrueType driver object. */ + /* */ + typedef struct TT_DriverRec_* TT_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Instance */ + /* */ + /* */ + /* A handle to a TrueType size object. */ + /* */ + typedef struct TT_SizeRec_* TT_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GlyphSlot */ + /* */ + /* */ + /* A handle to a TrueType glyph slot object. */ + /* */ + /* */ + /* This is a direct typedef of FT_GlyphSlot, as there is nothing */ + /* specific about the TrueType glyph slot. */ + /* */ + typedef FT_GlyphSlot TT_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* TT_GraphicsState */ + /* */ + /* */ + /* The TrueType graphics state used during bytecode interpretation. */ + /* */ + typedef struct TT_GraphicsState_ + { + FT_UShort rp0; + FT_UShort rp1; + FT_UShort rp2; + + FT_UnitVector dualVector; + FT_UnitVector projVector; + FT_UnitVector freeVector; + + FT_Long loop; + FT_F26Dot6 minimum_distance; + FT_Int round_state; + + FT_Bool auto_flip; + FT_F26Dot6 control_value_cutin; + FT_F26Dot6 single_width_cutin; + FT_F26Dot6 single_width_value; + FT_Short delta_base; + FT_Short delta_shift; + + FT_Byte instruct_control; + FT_Bool scan_control; + FT_Int scan_type; + + FT_UShort gep0; + FT_UShort gep1; + FT_UShort gep2; + + } TT_GraphicsState; + + + LOCAL_DEF void TT_Done_GlyphZone( TT_GlyphZone* zone ); + + LOCAL_DEF FT_Error TT_New_GlyphZone( FT_Memory memory, + FT_UShort maxPoints, + FT_Short maxContours, + TT_GlyphZone* zone ); + + + /*************************************************************************/ + /* */ + /* EXECUTION SUBTABLES */ + /* */ + /* These sub-tables relate to instruction execution. */ + /* */ + /*************************************************************************/ + + +#define TT_MAX_CODE_RANGES 3 + + + /*************************************************************************/ + /* */ + /* There can only be 3 active code ranges at once: */ + /* - the Font Program */ + /* - the CVT Program */ + /* - a glyph's instructions set */ + /* */ + typedef enum TT_CodeRange_Tag_ + { + tt_coderange_none = 0, + tt_coderange_font, + tt_coderange_cvt, + tt_coderange_glyph + + } TT_CodeRange_Tag; + + + typedef struct TT_CodeRange_ + { + FT_Byte* base; + FT_ULong size; + + } TT_CodeRange; + + typedef TT_CodeRange TT_CodeRangeTable[TT_MAX_CODE_RANGES]; + + + /*************************************************************************/ + /* */ + /* Defines a function/instruction definition record. */ + /* */ + typedef struct TT_DefRecord_ + { + FT_Int range; /* in which code range is it located? */ + FT_Long start; /* where does it start? */ + FT_UInt opc; /* function #, or instruction code */ + FT_Bool active; /* is it active? */ + + } TT_DefRecord, *TT_DefArray; + + + /*************************************************************************/ + /* */ + /* Subglyph transformation record. */ + /* */ + typedef struct TT_Transform_ + { + FT_Fixed xx, xy; /* transformation matrix coefficients */ + FT_Fixed yx, yy; + FT_F26Dot6 ox, oy; /* offsets */ + + } TT_Transform; + + + /*************************************************************************/ + /* */ + /* Subglyph loading record. Used to load composite components. */ + /* */ + typedef struct TT_SubglyphRec_ + { + FT_Long index; /* subglyph index; initialized with -1 */ + FT_Bool is_scaled; /* is the subglyph scaled? */ + FT_Bool is_hinted; /* should it be hinted? */ + FT_Bool preserve_pps; /* preserve phantom points? */ + + FT_Long file_offset; + + FT_BBox bbox; + FT_Pos left_bearing; + FT_Pos advance; + + TT_GlyphZone zone; + + FT_Long arg1; /* first argument */ + FT_Long arg2; /* second argument */ + + FT_UShort element_flag; /* current load element flag */ + + TT_Transform transform; /* transformation matrix */ + + FT_Vector pp1, pp2; /* phantom points */ + + } TT_SubGlyphRec, *TT_SubGlyph_Stack; + + + /*************************************************************************/ + /* */ + /* A note regarding non-squared pixels: */ + /* */ + /* (This text will probably go into some docs at some time; for now, it */ + /* is kept here to explain some definitions in the TIns_Metrics */ + /* record). */ + /* */ + /* The CVT is a one-dimensional array containing values that control */ + /* certain important characteristics in a font, like the height of all */ + /* capitals, all lowercase letter, default spacing or stem width/height. */ + /* */ + /* These values are found in FUnits in the font file, and must be scaled */ + /* to pixel coordinates before being used by the CVT and glyph programs. */ + /* Unfortunately, when using distinct x and y resolutions (or distinct x */ + /* and y pointsizes), there are two possible scalings. */ + /* */ + /* A first try was to implement a `lazy' scheme where all values were */ + /* scaled when first used. However, while some values are always used */ + /* in the same direction, some others are used under many different */ + /* circumstances and orientations. */ + /* */ + /* I have found a simpler way to do the same, and it even seems to work */ + /* in most of the cases: */ + /* */ + /* - All CVT values are scaled to the maximum ppem size. */ + /* */ + /* - When performing a read or write in the CVT, a ratio factor is used */ + /* to perform adequate scaling. Example: */ + /* */ + /* x_ppem = 14 */ + /* y_ppem = 10 */ + /* */ + /* We choose ppem = x_ppem = 14 as the CVT scaling size. All cvt */ + /* entries are scaled to it. */ + /* */ + /* x_ratio = 1.0 */ + /* y_ratio = y_ppem/ppem (< 1.0) */ + /* */ + /* We compute the current ratio like: */ + /* */ + /* - If projVector is horizontal, */ + /* ratio = x_ratio = 1.0 */ + /* */ + /* - if projVector is vertical, */ + /* ratio = y_ratio */ + /* */ + /* - else, */ + /* ratio = sqrt( (proj.x * x_ratio) ^ 2 + (proj.y * y_ratio) ^ 2 ) */ + /* */ + /* Reading a cvt value returns */ + /* ratio * cvt[index] */ + /* */ + /* Writing a cvt value in pixels: */ + /* cvt[index] / ratio */ + /* */ + /* The current ppem is simply */ + /* ratio * ppem */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* Metrics used by the TrueType size and context objects. */ + /* */ + typedef struct TT_Size_Metrics_ + { + /* for non-square pixels */ + FT_Long x_ratio; + FT_Long y_ratio; + + FT_UShort ppem; /* maximum ppem size */ + FT_Long ratio; /* current ratio */ + FT_Fixed scale; + + FT_F26Dot6 compensations[4]; /* device-specific compensations */ + + FT_Bool valid; + + FT_Bool rotated; /* `is the glyph rotated?'-flag */ + FT_Bool stretched; /* `is the glyph stretched?'-flag */ + + } TT_Size_Metrics; + + + /*************************************************************************/ + /* */ + /* TrueType size class. */ + /* */ + typedef struct TT_SizeRec_ + { + FT_SizeRec root; + + TT_Size_Metrics ttmetrics; + +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + FT_UInt num_function_defs; /* number of function definitions */ + FT_UInt max_function_defs; + TT_DefArray function_defs; /* table of function definitions */ + + FT_UInt num_instruction_defs; /* number of ins. definitions */ + FT_UInt max_instruction_defs; + TT_DefArray instruction_defs; /* table of ins. definitions */ + + FT_UInt max_func; + FT_UInt max_ins; + + TT_CodeRangeTable codeRangeTable; + + TT_GraphicsState GS; + + FT_ULong cvt_size; /* the scaled control value table */ + FT_Long* cvt; + + FT_UShort storage_size; /* The storage area is now part of */ + FT_Long* storage; /* the instance */ + + TT_GlyphZone twilight; /* The instance's twilight zone */ + + /* debugging variables */ + + /* When using the debugger, we must keep the */ + /* execution context tied to the instance */ + /* object rather than asking it on demand. */ + + FT_Bool debug; + TT_ExecContext context; + +#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ + + } TT_SizeRec; + + + /*************************************************************************/ + /* */ + /* TrueType driver class. */ + /* */ + typedef struct TT_DriverRec_ + { + FT_DriverRec root; + TT_ExecContext context; /* execution context */ + TT_GlyphZone zone; /* glyph loader points zone */ + + void* extension_component; + + } TT_DriverRec; + + + /*************************************************************************/ + /* */ + /* Face functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Face( FT_Stream stream, + TT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void TT_Done_Face( TT_Face face ); + + + /*************************************************************************/ + /* */ + /* Size functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Size( TT_Size size ); + + LOCAL_DEF + void TT_Done_Size( TT_Size size ); + + LOCAL_DEF + FT_Error TT_Reset_Size( TT_Size size ); + + + /*************************************************************************/ + /* */ + /* Driver functions */ + /* */ + LOCAL_DEF + FT_Error TT_Init_Driver( TT_Driver driver ); + + LOCAL_DEF + void TT_Done_Driver( TT_Driver driver ); + + +#ifdef __cplusplus + } +#endif + +#endif /* TTOBJS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttpload.c b/subsys/win32k/freetype/src/truetype/ttpload.c new file mode 100644 index 0000000..b4f6d31 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttpload.c @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include +#include + +#ifdef FT_FLAT_COMPILE +#include "ttpload.h" +#else +#include +#endif + +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_ttpload + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Locations */ + /* */ + /* */ + /* Loads the locations table. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Locations( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Short LongOffsets; + FT_ULong table_len; + + + FT_TRACE2(( "Locations " )); + LongOffsets = face->header.Index_To_Loc_Format; + + error = face->goto_table( face, TTAG_loca, stream, &table_len ); + if ( error ) + { + error = TT_Err_Locations_Missing; + goto Exit; + } + + if ( LongOffsets != 0 ) + { + face->num_locations = (FT_UShort)( table_len >> 2 ); + + FT_TRACE2(( "(32bit offsets): %12d ", face->num_locations )); + + if ( ALLOC_ARRAY( face->glyph_locations, + face->num_locations, + FT_Long ) ) + goto Exit; + + if ( ACCESS_Frame( face->num_locations * 4L ) ) + goto Exit; + + { + FT_Long* loc = face->glyph_locations; + FT_Long* limit = loc + face->num_locations; + + + for ( ; loc < limit; loc++ ) + *loc = GET_Long(); + } + + FORGET_Frame(); + } + else + { + face->num_locations = (FT_UShort)( table_len >> 1 ); + + FT_TRACE2(( "(16bit offsets): %12d ", face->num_locations )); + + if ( ALLOC_ARRAY( face->glyph_locations, + face->num_locations, + FT_Long ) ) + goto Exit; + + if ( ACCESS_Frame( face->num_locations * 2L ) ) + goto Exit; + { + FT_Long* loc = face->glyph_locations; + FT_Long* limit = loc + face->num_locations; + + + for ( ; loc < limit; loc++ ) + *loc = (FT_Long)( (FT_ULong)GET_UShort() * 2 ); + } + FORGET_Frame(); + } + + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_CVT */ + /* */ + /* */ + /* Loads the control value table into a face object. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_CVT( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_ULong table_len; + + + FT_TRACE2(( "CVT " )); + + error = face->goto_table( face, TTAG_cvt, stream, &table_len ); + if ( error ) + { + FT_TRACE2(( "is missing!\n" )); + + face->cvt_size = 0; + face->cvt = NULL; + error = TT_Err_Ok; + + goto Exit; + } + + face->cvt_size = table_len / 2; + + if ( ALLOC_ARRAY( face->cvt, + face->cvt_size, + FT_Short ) ) + goto Exit; + + if ( ACCESS_Frame( face->cvt_size * 2L ) ) + goto Exit; + + { + FT_Short* cur = face->cvt; + FT_Short* limit = cur + face->cvt_size; + + + for ( ; cur < limit; cur++ ) + *cur = GET_Short(); + } + + FORGET_Frame(); + FT_TRACE2(( "loaded\n" )); + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* TT_Load_Progams */ + /* */ + /* */ + /* Loads the font program and the cvt program. */ + /* */ + /* */ + /* face :: A handle to the target face object. */ + /* */ + /* */ + /* stream :: A handle to the input stream. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error TT_Load_Programs( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_ULong table_len; + + + FT_TRACE2(( "Font program " )); + + /* The font program is optional */ + error = face->goto_table( face, TTAG_fpgm, stream, &table_len ); + if ( error ) + { + face->font_program = NULL; + face->font_program_size = 0; + + FT_TRACE2(( "is missing!\n" )); + } + else + { + face->font_program_size = table_len; + if ( EXTRACT_Frame( table_len, face->font_program ) ) + goto Exit; + + FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size )); + } + + FT_TRACE2(( "Prep program " )); + + error = face->goto_table( face, TTAG_prep, stream, &table_len ); + if ( error ) + { + face->cvt_program = NULL; + face->cvt_program_size = 0; + error = TT_Err_Ok; + + FT_TRACE2(( "is missing!\n" )); + } + else + { + face->cvt_program_size = table_len; + if ( EXTRACT_Frame( table_len, face->cvt_program ) ) + goto Exit; + + FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size )); + } + + Exit: + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/truetype/ttpload.h b/subsys/win32k/freetype/src/truetype/ttpload.h new file mode 100644 index 0000000..77802a6 --- /dev/null +++ b/subsys/win32k/freetype/src/truetype/ttpload.h @@ -0,0 +1,51 @@ +/***************************************************************************/ +/* */ +/* ttpload.h */ +/* */ +/* TrueType glyph data/program tables loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef TTPLOAD_H +#define TTPLOAD_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + LOCAL_DEF + FT_Error TT_Load_Locations( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_CVT( TT_Face face, + FT_Stream stream ); + + LOCAL_DEF + FT_Error TT_Load_Programs( TT_Face face, + FT_Stream stream ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* TTPLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/.cvsignore b/subsys/win32k/freetype/src/type1/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/type1/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/type1/module.mk0 b/subsys/win32k/freetype/src/type1/module.mk0 new file mode 100644 index 0000000..af99eae --- /dev/null +++ b/subsys/win32k/freetype/src/type1/module.mk0 @@ -0,0 +1,6 @@ +make_module_list: add_type1_driver + +add_type1_driver: + $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE) + diff --git a/subsys/win32k/freetype/src/type1/rules.mk0 b/subsys/win32k/freetype/src/type1/rules.mk0 new file mode 100644 index 0000000..b544446 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/rules.mk0 @@ -0,0 +1,74 @@ +# +# FreeType 2 Type 1 driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# Type1 driver directory +# +T1_DIR := $(SRC_)type1 +T1_DIR_ := $(T1_DIR)$(SEP) + + +# compilation flags for the driver +# +T1_COMPILE := $(FT_COMPILE) + + +# Type1 driver sources (i.e., C files) +# +T1_DRV_SRC := $(T1_DIR_)t1objs.c \ + $(T1_DIR_)t1load.c \ + $(T1_DIR_)t1parse.c \ + $(T1_DIR_)t1tokens.c \ + $(T1_DIR_)t1driver.c \ + $(T1_DIR_)t1hinter.c \ + $(T1_DIR_)t1afm.c \ + $(T1_DIR_)t1gload.c + +# Type1 driver headers +# +T1_DRV_H := $(T1_DRV_SRC:%.c=%.h) + + +# Type1 driver object(s) +# +# T1_DRV_OBJ_M is used during `multi' builds +# T1_DRV_OBJ_S is used during `single' builds +# +T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O) +T1_DRV_OBJ_S := $(OBJ_)type1.$O + +# Type1 driver source file for single build +# +T1_DRV_SRC_S := $(T1_DIR_)type1.c + + +# Type1 driver - single object +# +$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H) + $(T1_COMPILE) $T$@ $(T1_DRV_SRC_S) + + +# Type1 driver - multiple objects +# +$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H) + $(T1_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T1_DRV_OBJ_S) +DRV_OBJS_M += $(T1_DRV_OBJ_M) + + +# EOF diff --git a/subsys/win32k/freetype/src/type1/t1afm.c b/subsys/win32k/freetype/src/type1/t1afm.c new file mode 100644 index 0000000..218fbb3 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1afm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* t1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1afm.h" + +#else + +#include + +#endif + + +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* for isalnum() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1afm + + + LOCAL_FUNC + void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#undef IS_KERN_PAIR +#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' ) + +#define IS_ALPHANUM( c ) ( isalnum( c ) || \ + c == '_' || \ + c == '.' ) + + + /* read a glyph name and return the equivalent glyph index */ + static + FT_UInt afm_atoindex( FT_Byte** start, + FT_Byte* limit, + T1_Font* type1 ) + { + FT_Byte* p = *start; + FT_Int len; + FT_UInt result = 0; + char temp[64]; + + + /* skip whitespace */ + while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) && + p < limit ) + p++; + *start = p; + + /* now, read glyph name */ + while ( IS_ALPHANUM( *p ) && p < limit ) + p++; + + len = p - *start; + + if ( len > 0 && len < 64 ) + { + FT_Int n; + + + /* copy glyph name to intermediate array */ + MEM_Copy( temp, *start, len ); + temp[len] = 0; + + /* lookup glyph name in face array */ + for ( n = 0; n < type1->num_glyphs; n++ ) + { + char* gname = (char*)type1->glyph_names[n]; + + + if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 ) + { + result = n; + break; + } + } + } + *start = p; + return result; + } + + + /* read an integer */ + static + int afm_atoi( FT_Byte** start, + FT_Byte* limit ) + { + FT_Byte* p = *start; + int sum = 0; + int sign = 1; + + + /* skip everything that is not a number */ + while ( p < limit && !isdigit( *p ) ) + { + sign = 1; + if ( *p == '-' ) + sign = -1; + + p++; + } + + while ( p < limit && isdigit( *p ) ) + { + sum = sum * 10 + ( *p - '0' ); + p++; + } + *start = p; + + return sum * sign; + } + + +#undef KERN_INDEX +#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) + + + /* compare two kerning pairs */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + T1_Kern_Pair* pair1 = (T1_Kern_Pair*)a; + T1_Kern_Pair* pair2 = (T1_Kern_Pair*)b; + + FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 ); + FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 ); + + + return ( index1 - index2 ); + } + + + /* parse an AFM file -- for now, only read the kerning pairs */ + LOCAL_FUNC + FT_Error T1_Read_AFM( FT_Face t1_face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Byte* start; + FT_Byte* limit; + FT_Byte* p; + FT_Int count = 0; + T1_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + T1_AFM* afm = 0; + + + if ( ACCESS_Frame( stream->size ) ) + return error; + + start = (FT_Byte*)stream->cursor; + limit = (FT_Byte*)stream->limit; + p = start; + + /* we are now going to count the occurences of `KP' or `KPX' in */ + /* the AFM file */ + count = 0; + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + count++; + } + + /* Actually, kerning pairs are simply optional! */ + if ( count == 0 ) + goto Exit; + + /* allocate the pairs */ + if ( ALLOC( afm, sizeof ( *afm ) ) || + ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) ) + goto Exit; + + /* now, read each kern pair */ + pair = afm->kern_pairs; + afm->num_pairs = count; + + /* save in face object */ + ((T1_Face)t1_face)->afm_data = afm; + + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + { + FT_Byte* q; + + + /* skip keyword (KP or KPX) */ + q = p + 2; + if ( *q == 'X' ) + q++; + + pair->glyph1 = afm_atoindex( &q, limit, type1 ); + pair->glyph2 = afm_atoindex( &q, limit, type1 ); + pair->kerning.x = afm_atoi( &q, limit ); + + pair->kerning.y = 0; + if ( p[2] != 'X' ) + pair->kerning.y = afm_atoi( &q, limit ); + + pair++; + } + } + + /* now, sort the kern pairs according to their glyph indices */ + qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + T1_Kern_Pair *min, *mid, *max; + FT_ULong index = KERN_INDEX( glyph1, glyph2 ); + + + /* simple binary search */ + min = afm->kern_pairs; + max = min + afm->num_pairs - 1; + + while ( min <= max ) + { + FT_ULong midi; + + + mid = min + ( max - min ) / 2; + midi = KERN_INDEX( mid->glyph1, mid->glyph2 ); + + if ( midi == index ) + { + *kerning = mid->kerning; + return; + } + + if ( midi < index ) + min = mid + 1; + else + max = mid - 1; + } + + kerning->x = 0; + kerning->y = 0; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1afm.h b/subsys/win32k/freetype/src/type1/t1afm.h new file mode 100644 index 0000000..709154e --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1afm.h @@ -0,0 +1,70 @@ +/***************************************************************************/ +/* */ +/* t1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1AFM_H +#define T1AFM_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T1_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } T1_Kern_Pair; + + + typedef struct T1_AFM_ + { + FT_Int num_pairs; + T1_Kern_Pair* kern_pairs; + + } T1_AFM; + + + LOCAL_DEF + FT_Error T1_Read_AFM( FT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ); + + LOCAL_DEF + void T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1AFM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1driver.c b/subsys/win32k/freetype/src/type1/t1driver.c new file mode 100644 index 0000000..c040b00 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1driver.c @@ -0,0 +1,381 @@ +/***************************************************************************/ +/* */ +/* t1driver.c */ +/* */ +/* Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1driver.h" +#include "t1gload.h" +#include "t1afm.h" + +#else + +#include +#include +#include + +#endif + + +#include +#include +#include + +#include /* for strcmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1driver + + +#ifndef T1_CONFIG_OPTION_NO_AFM + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static + FT_Error Get_Kerning( T1_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + T1_AFM* afm; + + + kerning->x = 0; + kerning->y = 0; + + afm = (T1_AFM*)face->afm_data; + if ( afm ) + T1_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } + + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + + + static + FT_Error get_t1_glyph_name( T1_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_String* gname; + + + gname = face->type1.glyph_names[glyph_index]; + + if ( buffer_max > 0 ) + { + FT_UInt len = strlen( gname ); + + + if ( len >= buffer_max ) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + static + FT_Module_Interface T1_Get_Interface( FT_Module module, + const char* interface ) + { + FT_UNUSED( module ); + + if ( strcmp( interface, "glyph_name" ) == 0 ) + return (FT_Module_Interface)get_t1_glyph_name; + + return 0; + } + + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Char_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in fractional points. */ + /* */ + /* */ + /* char_width :: The character width expressed in 26.6 */ + /* fractional points. */ + /* */ + /* char_height :: The character height expressed in 26.6 */ + /* fractional points. */ + /* */ + /* horz_resolution :: The horizontal resolution of the output device. */ + /* */ + /* vert_resolution :: The vertical resolution of the output device. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Char_Sizes( T1_Size size, + FT_F26Dot6 char_width, + FT_F26Dot6 char_height, + FT_UInt horz_resolution, + FT_UInt vert_resolution ) + { + FT_UNUSED( char_width ); + FT_UNUSED( char_height ); + FT_UNUSED( horz_resolution ); + FT_UNUSED( vert_resolution ); + + size->valid = FALSE; + + return T1_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Set_Pixel_Sizes */ + /* */ + /* */ + /* A driver method used to reset a size's character sizes (horizontal */ + /* and vertical) expressed in integer pixels. */ + /* */ + /* */ + /* pixel_width :: The character width expressed in integer pixels. */ + /* */ + /* pixel_height :: The character height expressed in integer pixels. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Set_Pixel_Sizes( T1_Size size, + FT_Int pixel_width, + FT_Int pixel_height ) + { + FT_UNUSED( pixel_width ); + FT_UNUSED( pixel_height ); + + size->valid = FALSE; + + return T1_Reset_Size( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt Get_Char_Index( FT_CharMap charmap, + FT_Long charcode ) + { + T1_Face face; + FT_UInt result = 0; + PSNames_Interface* psnames; + + + face = (T1_Face)charmap->face; + psnames = (PSNames_Interface*)face->psnames; + if ( psnames ) + switch ( charmap->encoding ) + { + /*******************************************************************/ + /* */ + /* Unicode encoding support */ + /* */ + case ft_encoding_unicode: + /* use the `PSNames' module to synthetize the Unicode charmap */ + result = psnames->lookup_unicode( &face->unicode_map, + (FT_ULong)charcode ); + + /* the function returns 0xFFFF if the Unicode charcode has */ + /* no corresponding glyph */ + if ( result == 0xFFFF ) + result = 0; + goto Exit; + + /*******************************************************************/ + /* */ + /* Custom Type 1 encoding */ + /* */ + case ft_encoding_adobe_custom: + { + T1_Encoding* encoding = &face->type1.encoding; + + + if ( charcode >= encoding->code_first && + charcode <= encoding->code_last ) + result = encoding->char_index[charcode]; + goto Exit; + } + + /*******************************************************************/ + /* */ + /* Adobe Standard & Expert encoding support */ + /* */ + default: + if ( charcode < 256 ) + { + FT_UInt code; + FT_Int n; + const char* glyph_name; + + + code = psnames->adobe_std_encoding[charcode]; + if ( charmap->encoding == ft_encoding_adobe_expert ) + code = psnames->adobe_expert_encoding[charcode]; + + glyph_name = psnames->adobe_std_strings( code ); + if ( !glyph_name ) + break; + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + + if ( gname && gname[0] == glyph_name[0] && + strcmp( gname, glyph_name ) == 0 ) + { + result = n; + break; + } + } + } + } + Exit: + return result; + } + + + + const FT_Driver_Class t1_driver_class = + { + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( FT_DriverRec ), + + "type1", /* driver name */ + 0x10000L, /* driver version 1.0 */ + 0x20000L, /* driver requires FreeType 2.0 or above */ + + 0, /* module specific interface */ + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) T1_Get_Interface + }, + + sizeof( T1_FaceRec ), + sizeof( T1_SizeRec ), + sizeof( T1_GlyphSlotRec ), + + (FTDriver_initFace) T1_Init_Face, + (FTDriver_doneFace) T1_Done_Face, + (FTDriver_initSize) T1_Init_Size, + (FTDriver_doneSize) T1_Done_Size, + (FTDriver_initGlyphSlot)T1_Init_GlyphSlot, + (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot, + + (FTDriver_setCharSizes) Set_Char_Sizes, + (FTDriver_setPixelSizes)Set_Pixel_Sizes, + (FTDriver_loadGlyph) T1_Load_Glyph, + (FTDriver_getCharIndex) Get_Char_Index, + +#ifdef T1_CONFIG_OPTION_NO_AFM + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, +#else + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) T1_Read_AFM, +#endif + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &t1_driver_class; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1driver.h b/subsys/win32k/freetype/src/type1/t1driver.h new file mode 100644 index 0000000..5d615b5 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1driver.h @@ -0,0 +1,30 @@ +/***************************************************************************/ +/* */ +/* t1driver.h */ +/* */ +/* High-level Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1DRIVER_H +#define T1DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class; + + +#endif /* T1DRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1gload.c b/subsys/win32k/freetype/src/type1/t1gload.c new file mode 100644 index 0000000..5363257 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1gload.c @@ -0,0 +1,1823 @@ +/***************************************************************************/ +/* */ +/* t1gload.c */ +/* */ +/* Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "t1gload.h" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include +#include +#include + +#include /* for strcmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1gload + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + void T1_Reset_Builder( T1_Builder* builder, + FT_Bool reset_base ) + { + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + + builder->pass = 0; + builder->hint_point = 0; + + if ( builder->loader ) + { + if ( reset_base ) + FT_GlyphLoader_Rewind( builder->loader ); + + FT_GlyphLoader_Prepare( builder->loader ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + /* funcs :: Glyph builder functions (or `methods'). */ + /* */ + LOCAL_FUNC + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ) + { + builder->funcs = *funcs; + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->size = size; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader* loader = FT_SLOT( glyph )->loader; + + + builder->loader = loader; + builder->base = &loader->base.outline; + builder->current = &loader->current.outline; + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; + } + + T1_Reset_Builder( builder, 1 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Builder */ + /* */ + /* */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void T1_Done_Builder( T1_Builder* builder ) + { + T1_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* funcs :: The hinting functions interface. */ + /* */ + LOCAL_FUNC + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ) + { + decoder->hinter = *funcs; /* copy hinter interface */ + decoder->top = 0; + decoder->zone = 0; + + decoder->flex_state = 0; + decoder->num_flex_vectors = 0; + + /* Clear loader */ + MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( T1_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + + glyph_name = psnames->adobe_std_strings( + psnames->adobe_std_encoding[charcode] ); + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name, glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* decoder :: The current CID decoder. */ + /* */ + /* asb :: The accent's side bearing. */ + /* */ + /* adx :: The horizontal offset of the accent. */ + /* */ + /* ady :: The vertical offset of the accent. */ + /* */ + /* bchar :: The base character's StandardEncoding charcode. */ + /* */ + /* achar :: The accent character's StandardEncoding charcode. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( T1_Decoder* decoder, + FT_Pos asb, + FT_Pos adx, + FT_Pos ady, + FT_Int bchar, + FT_Int achar ) + { + FT_Error error; + FT_Int bchar_index, achar_index, n_base_points; + FT_Outline* base = decoder->builder.base; + FT_Vector left_bearing, advance; + T1_Face face = decoder->builder.face; + T1_Font* type1 = &face->type1; + + + bchar_index = lookup_glyph_by_stdcharcode( face, bchar ); + achar_index = lookup_glyph_by_stdcharcode( face, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_Err_Syntax_Error; + } + + /* if we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if ( decoder->builder.no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; + FT_GlyphLoader* loader = glyph->loader; + FT_SubGlyph* subg; + + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_Check_Subglyphs( loader, 2 ); + if ( error ) + goto Exit; + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = adx - asb; + subg->arg2 = ady; + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->current.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + goto Exit; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + if ( decoder->builder.loader ) + FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [bchar_index], + type1->charstrings_len[bchar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + goto Exit; + + n_base_points = base->n_points; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load. */ + + left_bearing = decoder->builder.left_bearing; + advance = decoder->builder.advance; + + decoder->builder.left_bearing.x = 0; + decoder->builder.left_bearing.y = 0; + + /* Now load `achar' on top of the base outline */ + error = T1_Parse_CharStrings( decoder, + type1->charstrings [achar_index], + type1->charstrings_len[achar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + return error; + + /* restore the left side bearing and */ + /* advance width of the base character */ + + decoder->builder.left_bearing = left_bearing; + decoder->builder.advance = advance; + + /* Finally, move the accent */ + if ( decoder->builder.load_points ) + { + FT_Outline dummy; + + + dummy.n_points = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_flex */ + /* */ + /* */ + /* Implements the `flex' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* threshold :: The threshold. */ + /* end_x :: The horizontal position of the final flex point. */ + /* end_y :: The vertical position of the final flex point. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_flex( T1_Decoder* decoder, + FT_Pos threshold, + FT_Pos end_x, + FT_Pos end_y ) + { + FT_Vector vec; + FT_Vector* flex = decoder->flex_vectors; + FT_Int n; + + FT_UNUSED( threshold ); + FT_UNUSED( end_x ); + FT_UNUSED( end_y ); + + + /* we don't even try to test the threshold in the non-hinting */ + /* builder, even if the flex operator is said to be a path */ + /* construction statement in the specification. This is better */ + /* left to the hinter. */ + + flex = decoder->flex_vectors; + vec = *flex++; + + for ( n = 0; n < 6; n++ ) + { + flex->x += vec.x; + flex->y += vec.y; + + vec = *flex++; + } + + flex = decoder->flex_vectors; + + return decoder->builder.funcs.rcurve_to( &decoder->builder, + flex[0].x, flex[0].y, + flex[1].x, flex[1].y, + flex[2].x, flex[2].y ) || + + decoder->builder.funcs.rcurve_to( &decoder->builder, + flex[3].x, flex[3].y, + flex[4].x, flex[4].y, + flex[5].x, flex[5].y ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* charstring_base :: The base address of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* num_subrs :: The number of sub-routines. */ + /* */ + /* subrs_base :: An array of sub-routines addresses. */ + /* */ + /* subrs_len :: An array of sub-routines lengths. */ + /* */ + /* */ + /* Free error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Parse_CharStrings( T1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ) + { + FT_Error error; + T1_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + T1_Builder* builder = &decoder->builder; + T1_Builder_Funcs* builds = &builder->funcs; + T1_Hinter_Funcs* hints = &decoder->hinter; + + static + const FT_Int args_count[op_max] = + { + 0, /* none */ + 0, /* endchar */ + 2, /* hsbw */ + 5, /* seac */ + 4, /* sbw */ + 0, /* closepath */ + 1, /* hlineto */ + 1, /* hmoveto */ + 4, /* hvcurveto */ + 2, /* rlineto */ + 2, /* rmoveto */ + 6, /* rrcurveto */ + 4, /* vhcurveto */ + 1, /* vlineto */ + 1, /* vmoveto */ + 0, /* dotsection */ + 2, /* hstem */ + 6, /* hstem3 */ + 2, /* vstem */ + 6, /* vstem3 */ + 2, /* div */ + -1, /* callothersubr */ + 1, /* callsubr */ + 0, /* pop */ + 0, /* return */ + 2 /* setcurrentpoint */ + }; + + + /* First of all, initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + + builder->path_begun = 0; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = T1_Err_Ok; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + T1_Operator op = op_none; + FT_Long value = 0; + + + /* Start with the decompression of operator or value */ + switch ( *ip++ ) + { + case 1: + op = op_hstem; + break; + + case 3: + op = op_vstem; + break; + case 4: + op = op_vmoveto; + break; + case 5: + op = op_rlineto; + break; + case 6: + op = op_hlineto; + break; + case 7: + op = op_vlineto; + break; + case 8: + op = op_rrcurveto; + break; + case 9: + op = op_closepath; + break; + case 10: + op = op_callsubr; + break; + case 11: + op = op_return; + break; + + case 13: + op = op_hsbw; + break; + case 14: + op = op_endchar; + break; + + case 21: + op = op_rmoveto; + break; + case 22: + op = op_hmoveto; + break; + + case 30: + op = op_vhcurveto; + break; + case 31: + op = op_hvcurveto; + break; + + case 12: + if ( ip > limit ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+EOF)\n" )); + goto Syntax_Error; + } + + switch ( *ip++ ) + { + case 0: + op = op_dotsection; + break; + case 1: + op = op_vstem3; + break; + case 2: + op = op_hstem3; + break; + case 6: + op = op_seac; + break; + case 7: + op = op_sbw; + break; + case 12: + op = op_div; + break; + case 16: + op = op_callothersubr; + break; + case 17: + op = op_pop; + break; + case 33: + op = op_setcurrentpoint; + break; + + default: + FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (FT_Long)ip[0] << 24 ) | + ( (FT_Long)ip[1] << 16 ) | + ( (FT_Long)ip[2] << 8 ) | + ip[3]; + ip += 4; + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (FT_Long)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ((FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + else + value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "T1_Parse_CharStrings: invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /* push value if necessary */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" )); + goto Syntax_Error; + } + + *top++ = value; + decoder->top = top; + } + + else if ( op == op_callothersubr ) /* check arguments differently */ + { + if ( top - decoder->stack < 2 ) + goto Stack_Underflow; + + top -= 2; + + switch ( top[1] ) + { + case 1: /* start flex feature */ + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + decoder->flex_vectors[0].x = 0; + decoder->flex_vectors[0].y = 0; + break; + + case 2: /* add flex vector */ + { + FT_Int index; + FT_Vector* flex; + + + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + top -= 2; + if ( top < decoder->stack ) + goto Stack_Underflow; + + index = decoder->num_flex_vectors++; + if ( index >= 7 ) + { + FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" )); + goto Syntax_Error; + } + + flex = decoder->flex_vectors + index; + flex->x += top[0]; + flex->y += top[1]; + } + break; + + case 0: /* end flex feature */ + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + if ( top[0] != 3 ) + goto Unexpected_OtherSubr; + + top -= 3; + if ( top < decoder->stack ) + goto Stack_Underflow; + + /* now consume the remaining `pop pop setcurrentpoint' */ + if ( ip + 6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */ + { + FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + decoder->flex_state = 0; + decoder->top = top; + + error = t1operator_flex( decoder, top[0], top[1], top[2] ); + break; + + case 3: /* change hints */ + if ( top[0] != 1 ) + goto Unexpected_OtherSubr; + + /* eat the following `pop' */ + if ( ip + 2 > limit ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " `pop' expected, found (%d %d)\n", ip[0], ip[1] )); + goto Syntax_Error; + } + + ip += 2; + + error = hints->change_hints( builder ); + break; + + default: + /* invalid OtherSubrs call */ + Unexpected_OtherSubr: + FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n", + top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else + { + FT_Int num_args = args_count[op]; + + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch ( op ) + { + case op_endchar: + error = builds->end_char( builder ); + break; + + case op_hsbw: + error = builds->set_bearing_point( builder, top[0], 0, + top[1], 0 ); + break; + + case op_seac: + /* return immediately after the processing */ + return t1operator_seac( decoder, top[0], top[1], + top[2], top[3], top[4] ); + + case op_sbw: + error = builds->set_bearing_point( builder, top[0], top[1], + top[2], top[3] ); + break; + + case op_closepath: + error = builds->close_path( builder ); + break; + + case op_hlineto: + error = builds->rline_to( builder, top[0], 0 ); + break; + + case op_hmoveto: + error = builds->rmove_to( builder, top[0], 0 ); + break; + + case op_hvcurveto: + error = builds->rcurve_to( builder, top[0], 0, + top[1], top[2], + 0, top[3] ); + break; + + case op_rlineto: + error = builds->rline_to( builder, top[0], top[1] ); + break; + + case op_rmoveto: + /* ignore operator when in flex mode */ + if ( decoder->flex_state == 0 ) + error = builds->rmove_to( builder, top[0], top[1] ); + else + top += 2; + break; + + case op_rrcurveto: + error = builds->rcurve_to( builder, top[0], top[1], + top[2], top[3], + top[4], top[5] ); + break; + + case op_vhcurveto: + error = builds->rcurve_to( builder, 0, top[0], + top[1], top[2], + top[3], 0 ); + break; + + case op_vlineto: + error = builds->rline_to( builder, 0, top[0] ); + break; + + case op_vmoveto: + error = builds->rmove_to( builder, 0, top[0] ); + break; + + case op_dotsection: + error = hints->dot_section( builder ); + break; + + case op_hstem: + error = hints->stem( builder, top[0], top[1], 0 ); + break; + + case op_hstem3: + error = hints->stem3( builder, top[0], top[1], top[2], + top[3], top[4], top[5], 0 ); + break; + + case op_vstem: + error = hints->stem( builder, top[0], top[1], 1 ); + break; + + case op_vstem3: + error = hints->stem3( builder, top[0], top[1], top[2], + top[3], top[4], top[5], 1 ); + break; + + case op_div: + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + FT_Int index = top[0]; + + + if ( index < 0 || index >= num_subrs ) + { + FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + } + break; + + case op_pop: + FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" )); + goto Syntax_Error; + + case op_return: + if ( zone <= decoder->zones ) + { + FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" )); + goto Syntax_Error; + } + + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + break; + + case op_setcurrentpoint: + FT_ERROR(( "T1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + break; + + default: + FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + decoder->top = top; + } + } + + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Points */ + /* */ + /* */ + /* Checks that there is enough room in the current load glyph outline */ + /* to accept `num_points' additional outline points. If not, this */ + /* function grows the load outline's arrays accordingly. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder object. */ + /* */ + /* num_points :: The number of points that will be added later. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT update the points count in the glyph */ + /* builder. This must be done by the caller itself, after this */ + /* function has been invoked. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Points( T1_Builder* builder, + FT_Int num_points ) + { + return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Contours */ + /* */ + /* */ + /* Checks that there is enough room in the current load glyph outline */ + /* to accept `num_contours' additional contours. If not, this */ + /* function grows the load outline's arrays accordingly. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder object. */ + /* */ + /* num_contours :: The number of contours that will be added later. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function does NOT update the contours count in the load glyph */ + /* This must be done by the caller itself, after this function is */ + /* invoked. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Contours( T1_Builder* builder, + FT_Int num_contours ) + { + return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error maxadv_sbw( T1_Decoder* decoder, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ) + { + FT_UNUSED( sbx ); + FT_UNUSED( sby ); + FT_UNUSED( wy ); + + if ( wx > decoder->builder.advance.x ) + decoder->builder.advance.x = wx; + + return -1; /* return an error code to exit the Type 1 parser */ + /* immediately. */ + } + + + static + FT_Int maxadv_error( void ) + { + /* we should never reach this code, unless with a buggy font */ + return -2; + } + + + /* the maxadv_gbuilder_interface is used when computing the maximum */ + /* advance width of all glyphs in a given font. We only process the */ + /* `sbw' operator here, and return an error for all others. */ + + /* Note that `seac' is processed by the T1_Decoder. */ + static + const T1_Builder_Funcs maxadv_builder_interface = + { + (T1_Builder_EndChar) maxadv_error, + (T1_Builder_Sbw) maxadv_sbw, + (T1_Builder_ClosePath)maxadv_error, + (T1_Builder_RLineTo) maxadv_error, + (T1_Builder_RMoveTo) maxadv_error, + (T1_Builder_RCurveTo) maxadv_error + }; + + + /* the maxadv_hinter_interface always return an error. */ + static + const T1_Hinter_Funcs maxadv_hinter_interface = + { + (T1_Hinter_DotSection) maxadv_error, + (T1_Hinter_ChangeHints)maxadv_error, + (T1_Hinter_Stem) maxadv_error, + (T1_Hinter_Stem3) maxadv_error, + }; + + + LOCAL_FUNC + FT_Error T1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ) + { + FT_Error error; + T1_Decoder decoder; + FT_Int glyph_index; + T1_Font* type1 = &face->type1; + + + *max_advance = 0; + + /* Initialize load decoder */ + T1_Init_Decoder( &decoder, &maxadv_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, 0, 0, + &maxadv_builder_interface ); + + /* For each glyph, parse the glyph charstring and extract */ + /* the advance width. */ + for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) + { + /* now get load the unscaled outline */ + error = T1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + /* ignore the error if one occured - skip to next glyph */ + } + + *max_advance = decoder.builder.advance.x; + return T1_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /********** The Type 1 hinter is located in `t1hint.c' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error close_open_path( T1_Builder* builder ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Int num_points; + FT_Int first_point; + + + /* Some fonts, like Hershey, are made of `open paths' which are */ + /* now managed directly by FreeType. In this case, it is necessary */ + /* to close the path by duplicating its points in reverse order, */ + /* which is precisely the purpose of this function. */ + + /* first compute the number of points to duplicate */ + if ( cur->n_contours > 1 ) + first_point = cur->contours[cur->n_contours - 2] + 1; + else + first_point = 0; + + num_points = cur->n_points - first_point - 2; + if ( num_points > 0 ) + { + FT_Vector* source_point; + char* source_tags; + FT_Vector* point; + char* tags; + + + error = T1_Add_Points( builder, num_points ); + if ( error ) + return error; + + point = cur->points + cur->n_points; + tags = cur->tags + cur->n_points; + + source_point = point - 2; + source_tags = tags - 2; + + cur->n_points += num_points; + + if ( builder->load_points ) + do + { + *point++ = *source_point--; + *tags++ = *source_tags--; + num_points--; + + } while ( num_points > 0 ); + } + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + FT_Error gload_closepath( T1_Builder* builder ) + { + FT_Outline* cur = builder->current; + + + /* XXXX: We must not include the last point in the path if it */ + /* is located on the first point. */ + if ( cur->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = cur->points + first; + FT_Vector* p2 = cur->points + cur->n_points - 1; + + + if ( cur->n_contours > 1 ) + { + first = cur->contours[cur->n_contours - 2] + 1; + p1 = cur->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + cur->n_points--; + } + + /* save current contour, if any */ + if ( cur->n_contours > 0 ) + cur->contours[cur->n_contours - 1] = cur->n_points - 1; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + /* hint last points if necessary -- this is not strictly required */ + /* there, but it helps for debugging, and doesn't affect performance */ + if ( builder->pass == 1 ) + T1_Hint_Points( builder ); +#endif + + builder->path_begun = 0; + return T1_Err_Ok; + } + + + static + FT_Error gload_endchar( T1_Builder* builder ) + { + FT_Error error; + + + /* close path if needed */ + if ( builder->path_begun ) + { + error = close_open_path( builder ); + if ( error ) + return error; + } + + error = gload_closepath( builder ); + + FT_GlyphLoader_Add( builder->loader ); + + return error; + } + + + static + FT_Error gload_sbw( T1_Builder* builder, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ) + { + builder->left_bearing.x += sbx; + builder->left_bearing.y += sby; + builder->advance.x = wx; + builder->advance.y = wy; + + builder->last.x = sbx; + builder->last.y = sby; + + return 0; + } + + + static + FT_Error gload_rlineto( T1_Builder* builder, + FT_Pos dx, + FT_Pos dy ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + + + /* grow buffer if necessary */ + error = T1_Add_Points( builder, 1 ); + if ( error ) + return error; + + if ( builder->load_points ) + { + /* save point */ + vec.x = builder->last.x + dx; + vec.y = builder->last.y + dy; + + cur->points[cur->n_points] = vec; + cur->tags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + cur->n_points++; + + builder->path_begun = 1; + + return T1_Err_Ok; + } + + + static + FT_Error gload_rmoveto( T1_Builder* builder, + FT_Pos dx, + FT_Pos dy ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + + + /* in the case where `path_begun' is set, we have an `rmoveto' */ + /* after some normal path definition. If the face's paint type */ + /* is set to 1, this means that we have an `open path', also */ + /* called a `stroke'. The FreeType raster doesn't support */ + /* opened paths, so we'll close it explicitely there. */ + + if ( builder->path_begun && builder->face->type1.paint_type == 1 ) + { + if ( builder->face->type1.paint_type == 1 ) + { + error = close_open_path( builder ); + if ( error ) + return error; + } + } + + /* grow buffer if necessary */ + error = T1_Add_Contours( builder, 1 ) || + T1_Add_Points ( builder, 1 ); + if ( error ) + return error; + + /* save current contour, if any */ + if ( cur->n_contours > 0 ) + cur->contours[cur->n_contours - 1] = cur->n_points - 1; + + if ( builder->load_points ) + { + /* save point */ + vec.x = builder->last.x + dx; + vec.y = builder->last.y + dy; + cur->points[cur->n_points] = vec; + cur->tags [cur->n_points] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_contours++; + cur->n_points++; + + return T1_Err_Ok; + } + + + static + FT_Error gload_rrcurveto( T1_Builder* builder, + FT_Pos dx1, + FT_Pos dy1, + FT_Pos dx2, + FT_Pos dy2, + FT_Pos dx3, + FT_Pos dy3 ) + { + FT_Error error; + FT_Outline* cur = builder->current; + FT_Vector vec; + FT_Vector* points; + char* tags; + + + /* grow buffer if necessary */ + error = T1_Add_Points( builder, 3 ); + if ( error ) + return error; + + if ( builder->load_points ) + { + /* save point */ + points = cur->points + cur->n_points; + tags = cur->tags + cur->n_points; + + vec.x = builder->last.x + dx1; + vec.y = builder->last.y + dy1; + points[0] = vec; + tags[0] = FT_Curve_Tag_Cubic; + + vec.x += dx2; + vec.y += dy2; + points[1] = vec; + tags[1] = FT_Curve_Tag_Cubic; + + vec.x += dx3; + vec.y += dy3; + points[2] = vec; + tags[2] = FT_Curve_Tag_On; + + builder->last = vec; + } + + cur->n_points += 3; + builder->path_begun = 1; + + return T1_Err_Ok; + } + + + static + FT_Error gload_ignore( void ) + { + return 0; + } + + + static + const T1_Builder_Funcs gload_builder_interface = + { + gload_endchar, + gload_sbw, + gload_closepath, + gload_rlineto, + gload_rmoveto, + gload_rrcurveto + }; + + + static + const T1_Builder_Funcs gload_builder_interface_null = + { + (T1_Builder_EndChar) gload_ignore, + (T1_Builder_Sbw) gload_sbw, /* record left bearing */ + (T1_Builder_ClosePath)gload_ignore, + (T1_Builder_RLineTo) gload_ignore, + (T1_Builder_RMoveTo) gload_ignore, + (T1_Builder_RCurveTo) gload_ignore + }; + + + static + const T1_Hinter_Funcs gload_hinter_interface = + { + (T1_Hinter_DotSection) gload_ignore, /* dotsection */ + (T1_Hinter_ChangeHints)gload_ignore, /* changehints */ + (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */ + (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */ + }; + + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + + /*************************************************************************/ + /* */ + /* Hinter overview: */ + /* */ + /* This is a two-pass hinter. On the first pass, the hints are all */ + /* recorded by the hinter, and no point is loaded in the outline. */ + /* */ + /* When the first pass is finished, all stems hints are grid-fitted */ + /* at once. */ + /* */ + /* Then, a second pass is performed to load the outline points as */ + /* well as hint/scale them correctly. */ + /* */ + /*************************************************************************/ + + + static + FT_Error t1_load_hinted_glyph( T1_Decoder* decoder, + FT_UInt glyph_index, + FT_Bool recurse ) + { + T1_Builder* builder = &decoder->builder; + T1_GlyphSlot glyph = builder->glyph; + T1_Font* type1 = &builder->face->type1; + FT_UInt old_points, old_contours; + FT_GlyphLoader* loader = decoder->builder.loader; + FT_Error error; + + + /* Pass 1 -- try to load first glyph, simply recording points */ + old_points = loader->base.outline.n_points; + old_contours = loader->base.outline.n_contours; + + FT_GlyphLoader_Prepare( decoder->builder.loader ); + + T1_Reset_Builder( builder, 0 ); + + builder->no_recurse = recurse; + builder->pass = 0; + glyph->hints->hori_stems.num_stems = 0; + glyph->hints->vert_stems.num_stems = 0; + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + goto Exit; + + /* check for composite (i.e. `seac' operator) */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + /* this is a composite glyph, we must then load the first one, */ + /* then load the second one on top of it and translate it by a */ + /* fixed amount. */ + FT_UInt n_base_points; + FT_SubGlyph* subglyph = loader->base.subglyphs; + T1_Size size = builder->size; + FT_Pos dx, dy; + FT_Vector left_bearing, advance; + + + /* clean glyph format */ + glyph->root.format = ft_glyph_format_none; + + /* First load `bchar' in builder */ + builder->no_recurse = 0; + error = t1_load_hinted_glyph( decoder, subglyph->index, 0 ); + if ( error ) + goto Exit; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load */ + left_bearing = builder->left_bearing; + advance = builder->advance; + + /* Then load `achar' in builder */ + n_base_points = builder->base->n_points; + subglyph++; + error = t1_load_hinted_glyph( decoder, subglyph->index, 0 ); + if ( error ) + goto Exit; + + /* Finally, move the accent */ + dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale ); + dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale ); + dx = ( dx + 32 ) & -64; + dy = ( dy + 32 ) & -64; + { + FT_Outline dummy; + + + dummy.n_points = loader->base.outline.n_points - n_base_points; + dummy.points = loader->base.outline.points + n_base_points; + + FT_Outline_Translate( &dummy, dx, dy ); + } + + /* restore the left side bearing and */ + /* advance width of the base character */ + builder->left_bearing = left_bearing; + builder->advance = advance; + } + else + { + /* All right, pass 1 is finished, now grid-fit all stem hints */ + T1_Hint_Stems( &decoder->builder ); + + /* undo the end-char */ + builder->base->n_points = old_points; + builder->base->n_contours = old_contours; + + /* Pass 2 -- record and scale/hint the points */ + T1_Reset_Builder( builder, 0 ); + + builder->pass = 1; + builder->no_recurse = 0; + + error = T1_Parse_CharStrings( decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + } + + /* save new glyph tables */ + if ( recurse ) + T1_Done_Builder( builder ); + + Exit: + return error; + } + + +#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */ + + + LOCAL_FUNC + FT_Error T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + T1_Decoder decoder; + T1_Face face = (T1_Face)glyph->root.face; + FT_Bool hinting; + T1_Font* type1 = &face->type1; + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; + + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + glyph->root.format = ft_glyph_format_outline; /* by default */ + + hinting = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0; + + if ( hinting ) + { + T1_Init_Decoder( &decoder, &t1_hinter_funcs ); + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + error = t1_load_hinted_glyph( &decoder, glyph_index, 1 ); + } + else + +#endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */ + + { + T1_Init_Decoder( &decoder, &gload_hinter_interface ); + + T1_Init_Builder( &decoder.builder, face, size, glyph, + &gload_builder_interface ); + + decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; + + /* now load the unscaled outline */ + error = T1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + + /* save new glyph tables */ + T1_Done_Builder( &decoder.builder ); + } + + /* Now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax */ + if ( !error ) + { + /* for composite glyphs, return only the left side bearing and the */ + /* advance width */ + if ( glyph->root.format == ft_glyph_format_composite ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, + &face->type1.font_matrix ); + + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax + 63 ) & -64; + cbox.yMax = ( cbox.yMax + 63 ) & -64; + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + glyph->root.outline.flags = 0; + + if ( size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + + glyph->root.outline.flags |= ft_outline_reverse_fill; + + if ( hinting ) + { + /* adjust the advance width */ + /* XXX TODO: consider stem hints grid-fit */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, + glyph->x_scale ); + } + else if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = decoder.builder.base; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points */ + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + /* Then scale the metrics */ + metrics->width = FT_MulFix( metrics->width, x_scale ); + metrics->height = FT_MulFix( metrics->height, y_scale ); + + metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale ); + metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + } + } + } + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1gload.h b/subsys/win32k/freetype/src/type1/t1gload.h new file mode 100644 index 0000000..e66d083 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1gload.h @@ -0,0 +1,326 @@ +/***************************************************************************/ +/* */ +/* t1gload.h */ +/* */ +/* Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1GLOAD_H +#define T1GLOAD_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct T1_Builder_ T1_Builder; + + typedef FT_Error (*T1_Builder_EndChar)( T1_Builder* loader ); + + typedef FT_Error (*T1_Builder_Sbw)( T1_Builder* loader, + FT_Pos sbx, + FT_Pos sby, + FT_Pos wx, + FT_Pos wy ); + + typedef FT_Error (*T1_Builder_ClosePath)( T1_Builder* loader ); + + typedef FT_Error (*T1_Builder_RLineTo)( T1_Builder* loader, + FT_Pos dx, + FT_Pos dy ); + + typedef FT_Error (*T1_Builder_RMoveTo)( T1_Builder* loader, + FT_Pos dx, + FT_Pos dy ); + + typedef FT_Error (*T1_Builder_RCurveTo)( T1_Builder* loader, + FT_Pos dx1, + FT_Pos dy1, + FT_Pos dx2, + FT_Pos dy2, + FT_Pos dx3, + FT_Pos dy3 ); + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Builder_Funcs */ + /* */ + /* */ + /* A structure to store the address of various functions used by a */ + /* glyph builder to implement the outline's `path construction'. */ + /* */ + typedef struct T1_Builder_Funcs_ + { + T1_Builder_EndChar end_char; + T1_Builder_Sbw set_bearing_point; + T1_Builder_ClosePath close_path; + T1_Builder_RLineTo rline_to; + T1_Builder_RMoveTo rmove_to; + T1_Builder_RCurveTo rcurve_to; + + } T1_Builder_Funcs; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* last :: The last point position. */ + /* */ + /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ + /* */ + /* scale_y :: The vertical scale (FUnits to sub-pixels). */ + /* */ + /* pos_x :: The horizontal translation (for composite glyphs). */ + /* */ + /* pos_y :: The vertical translation (for composite glyphs). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* no_recurse :: */ + /* */ + /* bbox :: The glyph's bounding box. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: A flag which indicates, if not set, that no points */ + /* are loaded. */ + /* */ + /* pass :: The pass number for multi-pass hinters. */ + /* */ + /* hint_point :: The index of the next point to hint. */ + /* */ + /* funcs :: A table of builder functions used to perform the */ + /* outline's path construction. */ + /* */ + struct T1_Builder_ + { + FT_Memory memory; + T1_Face face; + T1_Size size; + T1_GlyphSlot glyph; + FT_GlyphLoader* loader; + + FT_Outline* current; /* the current glyph outline */ + FT_Outline* base; /* the composite glyph outline */ + + FT_Vector last; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + FT_Bool no_recurse; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + + FT_Int pass; + FT_Int hint_point; + + /* path construction function interface */ + T1_Builder_Funcs funcs; + }; + + + typedef FT_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder ); + + typedef FT_Error (*T1_Hinter_DotSection)( T1_Builder* builder ); + + typedef FT_Error (*T1_Hinter_Stem)( T1_Builder* builder, + FT_Pos pos, + FT_Pos width, + FT_Bool vertical ); + + typedef FT_Error (*T1_Hinter_Stem3)( T1_Builder* builder, + FT_Pos pos0, + FT_Pos width0, + FT_Pos pos1, + FT_Pos width1, + FT_Pos pos2, + FT_Pos width2, + FT_Bool vertical ); + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hinter_Funcs */ + /* */ + /* */ + /* A structure to store the address of various functions used by a */ + /* Type 1 hinter to perform outline hinting. */ + /* */ + typedef struct T1_Hinter_Func_ + { + T1_Hinter_ChangeHints change_hints; + T1_Hinter_DotSection dot_section; + T1_Hinter_Stem stem; + T1_Hinter_Stem3 stem3; + + } T1_Hinter_Funcs; + + + typedef enum T1_Operator_ + { + op_none = 0, + op_endchar, + op_hsbw, + op_seac, + op_sbw, + op_closepath, + op_hlineto, + op_hmoveto, + op_hvcurveto, + op_rlineto, + op_rmoveto, + op_rrcurveto, + op_vhcurveto, + op_vlineto, + op_vmoveto, + op_dotsection, + op_hstem, + op_hstem3, + op_vstem, + op_vstem3, + op_div, + op_callothersubr, + op_callsubr, + op_pop, + op_return, + op_setcurrentpoint, + + op_max /* never remove this one */ + + } T1_Operator; + + + /* execution context charstring zone */ + typedef struct T1_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } T1_Decoder_Zone; + + + typedef struct T1_Decoder_ + { + T1_Builder builder; + T1_Hinter_Funcs hinter; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + T1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + T1_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + } T1_Decoder; + + + LOCAL_DEF + void T1_Init_Builder( T1_Builder* builder, + T1_Face face, + T1_Size size, + T1_GlyphSlot glyph, + const T1_Builder_Funcs* funcs ); + + LOCAL_DEF + void T1_Done_Builder( T1_Builder* builder ); + + LOCAL_DEF + void T1_Init_Decoder( T1_Decoder* decoder, + const T1_Hinter_Funcs* funcs ); + + LOCAL_DEF + FT_Error T1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ); + + LOCAL_DEF + FT_Error T1_Parse_CharStrings( T1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ); + + LOCAL_DEF + FT_Error T1_Add_Points( T1_Builder* builder, + FT_Int num_points ); + + LOCAL_DEF + FT_Error T1_Add_Contours( T1_Builder* builder, + FT_Int num_contours ); + + LOCAL_DEF + FT_Error T1_Load_Glyph( T1_GlyphSlot glyph, + T1_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1GLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1hinter.c b/subsys/win32k/freetype/src/type1/t1hinter.c new file mode 100644 index 0000000..15b5897 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1hinter.c @@ -0,0 +1,1347 @@ +/***************************************************************************/ +/* */ +/* t1hinter.c */ +/* */ +/* Type 1 hinter (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The Hinter is in charge of fitting th scaled outline to the pixel */ + /* grid in order to considerably improve the quality of the Type 1 font */ + /* driver's output. */ + /* */ + /*************************************************************************/ + + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" +#include "t1hinter.h" + +#else + +#include +#include + +#endif + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1hint + + +#undef ONE_PIXEL +#define ONE_PIXEL 64 + +#undef ROUND +#define ROUND( x ) ( ( x + ONE_PIXEL / 2 ) & -ONE_PIXEL ) + +#undef SCALE +#define SCALE( val ) FT_MulFix( val, scale ) + +/* various constants used to describe the alignment of a horizontal */ +/* stem with regards to the blue zones */ + +#define T1_ALIGN_NONE 0 +#define T1_ALIGN_BOTTOM 1 +#define T1_ALIGN_TOP 2 +#define T1_ALIGN_BOTH 3 + + + /* very simple bubble sort (not a lot of elements, mostly */ + /* pre-sorted, no need for quicksort) */ + + static + void t1_sort_blues( FT_Int* blues, + FT_Int count ) + { + FT_Int i, swap; + FT_Int* cur; + + + for ( i = 2; i < count; i += 2 ) + { + cur = blues + i; + do + { + if ( cur[-1] < cur[0] ) + break; + + swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap; + swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap; + cur -= 2; + + } while ( cur > blues ); + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_set_blue_zones */ + /* */ + /* */ + /* Sets a size object's blue zones during reset. This will compute */ + /* the `snap' zone corresponding to each blue zone. */ + /* */ + /* */ + /* size :: A handle to target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This functions does the following: */ + /* */ + /* 1. It extracts the bottom and top blue zones from the face object. */ + /* */ + /* 2. Each zone is then grown by `BlueFuzz', overlapping is */ + /* eliminated by adjusting the zone edges appropriately. */ + /* */ + /* 3. For each zone, we keep its original font units position, its */ + /* original scaled position, as well as its grown/adjusted edges. */ + /* */ + static + FT_Error t1_set_blue_zones( T1_Size size ) + { + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->type1.private_dict; + FT_Int n; + FT_Int blues[24]; + FT_Int num_bottom; + FT_Int num_top; + FT_Int num_blues; + T1_Size_Hints* hints = size->hints; + T1_Snap_Zone* zone; + FT_Pos pix, orus; + FT_Pos min, max, threshold; + FT_Fixed scale; + FT_Bool is_bottom; + + + /***********************************************************************/ + /* */ + /* copy bottom and top blue zones in local arrays */ + /* */ + + /* First of all, check the sizes of the /BlueValues and /OtherBlues */ + /* tables. They all must contain an even number of arguments. */ + if ( priv->num_other_blues & 1 || + priv->num_blue_values & 1 ) + { + FT_ERROR(( "t1_set_blue_zones: odd number of blue values\n" )); + return T1_Err_Syntax_Error; + } + + /* copy the bottom blue zones from /OtherBlues */ + num_top = 0; + num_bottom = priv->num_other_blues; + + for ( n = 0; n < num_bottom; n++ ) + blues[n] = priv->other_blues[n]; + + /* add the first blue zone in /BlueValues to the table */ + num_top = priv->num_blue_values - 2; + if ( num_top >= 0 ) + { + blues[num_bottom ] = priv->blue_values[0]; + blues[num_bottom + 1] = priv->blue_values[1]; + + num_bottom += 2; + } + + /* sort the bottom blue zones */ + t1_sort_blues( blues, num_bottom ); + + hints->num_bottom_zones = num_bottom >> 1; + + /* now copy the /BlueValues to the top of the blues array */ + if ( num_top > 0 ) + { + for ( n = 0; n < num_top; n++ ) + blues[num_bottom + n] = priv->blue_values[n + 2]; + + /* sort the top blue zones */ + t1_sort_blues( blues + num_bottom, num_top ); + } + else + num_top = 0; + + num_blues = num_top + num_bottom; + hints->num_blue_zones = ( num_blues ) >> 1; + + /***********************************************************************/ + /* */ + /* build blue snap zones from the local blues arrays */ + /* */ + + scale = size->root.metrics.y_scale; + zone = hints->blue_zones; + threshold = ONE_PIXEL / 4; /* 0.25 pixels */ + + for ( n = 0; n < num_blues; n += 2, zone++ ) + { + is_bottom = n < num_bottom ? 1 : 0; + + orus = blues[n + is_bottom]; /* get alignement coordinate */ + pix = SCALE( orus ); /* scale it */ + + min = SCALE( blues[n ] - priv->blue_fuzz ); + max = SCALE( blues[n + 1] + priv->blue_fuzz ); + + if ( min > pix - threshold ) + min = pix - threshold; + if ( max < pix + threshold ) + max = pix + threshold; + + zone->orus = orus; + zone->pix = pix; + zone->min = min; + zone->max = max; + } + + /* adjust edges in case of overlap */ + zone = hints->blue_zones; + for ( n = 0; n < num_blues - 2; n += 2, zone++ ) + { + if ( n != num_bottom - 2 && + zone[0].max > zone[1].min ) + zone[0].max = zone[1].min = ( zone[0].pix + zone[1].pix ) / 2; + } + + /* compare the current pixel size with the BlueScale value */ + /* to know whether to supress overshoots */ + + hints->supress_overshoots = + size->root.metrics.y_ppem < FT_MulFix( 1000, priv->blue_scale ); + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* now print the new blue values in tracing mode */ + + FT_TRACE2(( "Blue Zones for size object at $%08lx:\n", (long)size )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-------------------------------\n" )); + + zone = hints->blue_zones; + for ( n = 0; n < hints->num_blue_zones; n++ ) + { + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + zone++; + } + FT_TRACE2(( "\nOvershoots are %s\n\n", + hints->supress_overshoots ? "supressed" : "active" )); + +#endif /* DEBUG_LEVEL_TRACE */ + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_set_snap_zones */ + /* */ + /* */ + /* This function set a size object's stem snap zones. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function performs the following: */ + /* */ + /* 1. It reads and scales the stem snap widths from the parent face. */ + /* */ + /* 2. A `snap zone' is computed for each snap width, by `growing' it */ + /* with a threshold of 1/2 pixel. Overlapping is avoided through */ + /* proper edge adjustment. */ + /* */ + /* 3. Each width whose zone contain the scaled standard set width is */ + /* removed from the table. */ + /* */ + /* 4. Finally, the standard set width is scaled, and its correponding */ + /* `snap zone' is inserted into the sorted snap zones table. */ + /* */ + static + FT_Error t1_set_snap_zones( T1_Size size ) + { + FT_Int n, direction, n_zones, num_zones; + T1_Snap_Zone* zone; + T1_Snap_Zone* base_zone; + FT_Short* orgs; + FT_Pos standard_width; + FT_Fixed scale; + + T1_Face face = (T1_Face)size->root.face; + T1_Private* priv = &face->type1.private_dict; + T1_Size_Hints* hints = size->hints; + + + /* start with horizontal snap zones */ + direction = 0; + standard_width = priv->standard_width[0]; + n_zones = priv->num_snap_widths; + base_zone = hints->snap_widths; + orgs = priv->snap_widths; + scale = size->root.metrics.x_scale; + + while ( direction < 2 ) + { + /*********************************************************************/ + /* */ + /* Read and scale stem snap widths table from the physical font */ + /* record. */ + /* */ + + FT_Pos prev, orus, pix, min, max, threshold; + + + threshold = ONE_PIXEL / 4; + zone = base_zone; + + if ( n_zones > 0 ) + { + orus = *orgs++; + pix = SCALE( orus ); + min = pix - threshold; + max = pix + threshold; + + zone->orus = orus; + zone->pix = pix; + zone->min = min; + prev = pix; + + for ( n = 1; n < n_zones; n++ ) + { + orus = *orgs++; + pix = SCALE( orus ); + + if ( pix - prev < 2 * threshold ) + { + min = max = ( pix + prev ) / 2; + } + else + min = pix - threshold; + + zone->max = max; + zone++; + zone->orus = orus; + zone->pix = pix; + zone->min = min; + + max = pix + threshold; + prev = pix; + } + zone->max = max; + } + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* print the scaled stem snap values in tracing mode */ + + FT_TRACE2(( "Set_Snap_Zones: first %s pass\n", + direction ? "vertical" : "horizontal" )); + + FT_TRACE2(( "Scaled original stem snap zones:\n" )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-----------------------------\n" )); + + zone = base_zone; + for ( n = 0; n < n_zones; n++, zone++ ) + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + FT_TRACE2(( "\n" )); + + FT_TRACE2(( "Standard width = %d\n", standard_width )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + /*********************************************************************/ + /* */ + /* Now, each snap width which is in the range of the standard set */ + /* width will be removed from the list. */ + /* */ + + if ( standard_width > 0 ) + { + T1_Snap_Zone* parent; + FT_Pos std_pix, std_min, std_max; + + + std_pix = SCALE( standard_width ); + + std_min = std_pix - threshold; + std_max = std_pix + threshold; + + num_zones = 0; + zone = base_zone; + parent = base_zone; + + for ( n = 0; n < n_zones; n++ ) + { + if ( zone->pix >= std_min && zone->pix <= std_max ) + { + /* this zone must be removed from the list */ + if ( std_min > zone->min ) + std_min = zone->min; + if ( std_max < zone->max ) + std_max = zone->max; + } + else + { + *parent++ = *zone; + num_zones++; + } + zone++; + } + + /*******************************************************************/ + /* */ + /* Now, insert the standard width zone */ + /* */ + + zone = base_zone + num_zones; + while ( zone > base_zone && zone[-1].pix > std_max ) + { + zone[0] = zone[-1]; + zone--; + } + + /* check border zones */ + if ( zone > base_zone && zone[-1].max > std_min ) + zone[-1].max = std_min; + + if ( zone < base_zone + num_zones && zone[1].min < std_max ) + zone[1].min = std_max; + + zone->orus = standard_width; + zone->pix = std_pix; + zone->min = std_min; + zone->max = std_max; + + num_zones++; + } + else + num_zones = n_zones; + + /* save total number of stem snaps now */ + if ( direction ) + hints->num_snap_heights = num_zones; + else + hints->num_snap_widths = num_zones; + +#ifdef FT_DEBUG_LEVEL_TRACE + + /* print the scaled stem snap values in tracing mode */ + + FT_TRACE2(( "Set_Snap_Zones: second %s pass\n", + direction ? "vertical" : "horizontal" )); + + FT_TRACE2(( "Scaled clipped stem snap zones:\n" )); + FT_TRACE2(( " orus pix min max\n" )); + FT_TRACE2(( "-----------------------------\n" )); + + zone = base_zone; + for ( n = 0; n < num_zones; n++, zone++ ) + FT_TRACE2(( " %3d %.2f %.2f %.2f\n", + zone->orus, + zone->pix / 64.0, + zone->min / 64.0, + zone->max / 64.0 )); + FT_TRACE2(( "\n" )); + + FT_TRACE2(( "Standard width = %d\n", standard_width )); + +#endif /* FT_DEBUG_LEVEL_TRACE */ + + /* continue with vertical snap zone */ + direction++; + standard_width = priv->standard_height[0]; + n_zones = priv->num_snap_heights; + base_zone = hints->snap_heights; + orgs = priv->snap_heights; + scale = size->root.metrics.y_scale; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Size_Hinter */ + /* */ + /* */ + /* Allocates a new hinter structure for a given size object. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeType Error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Size_Hinter( T1_Size size ) + { + FT_Memory memory = size->root.face->memory; + + + return MEM_Alloc( size->hints, sizeof ( *size->hints ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Size_Hinter */ + /* */ + /* */ + /* Releases a given size object's hinter structure. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void T1_Done_Size_Hinter( T1_Size size ) + { + FT_Memory memory = size->root.face->memory; + + + FREE( size->hints ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Reset_Size_Hinter */ + /* */ + /* */ + /* Recomputes hinting information when a given size object has */ + /* changed its resolutions/char sizes/pixel sizes. */ + /* */ + /* */ + /* size :: A handle to the size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Reset_Size_Hinter( T1_Size size ) + { + return t1_set_blue_zones( size ) || t1_set_snap_zones( size ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Glyph_Hinter */ + /* */ + /* */ + /* Allocates a new hinter structure for a given glyph slot. */ + /* */ + /* */ + /* glyph :: A handle to the target glyph slot. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + + + return MEM_Alloc( glyph->hints, sizeof ( *glyph->hints ) ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Glyph_Hinter */ + /* */ + /* */ + /* Releases a given glyph slot's hinter structure. */ + /* */ + /* */ + /* glyph :: A handle to the glyph slot. */ + /* */ + LOCAL_FUNC + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ) + { + FT_Memory memory = glyph->root.face->memory; + + + FREE( glyph->hints ); + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** **********/ + /********** HINTED GLYPH LOADER **********/ + /********** **********/ + /********** The following code is in charge of the first **********/ + /********** and second pass when loading a single outline **********/ + /********** **********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + static + FT_Error t1_hinter_ignore( void ) + { + /* do nothing, used for `dotsection' which is unsupported for now */ + return 0; + } + + + static + FT_Error t1_hinter_stem( T1_Builder* builder, + FT_Pos pos, + FT_Int width, + FT_Bool vertical ) + { + T1_Stem_Table* stem_table; + T1_Stem_Hint* stems; + T1_Stem_Hint* cur_stem; + FT_Int min, max, n, num_stems; + FT_Bool new_stem; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + + /* select the appropriate stem array */ + stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems; + stems = stem_table->stems; + num_stems = stem_table->num_stems; + + /* Compute minimum and maximum coord for the stem */ + min = pos + ( vertical + ? builder->left_bearing.x + : builder->left_bearing.y ); + + if ( width >= 0 ) + max = min + width; + else + { + /* a negative width indicates a `ghost' stem */ + if ( width == -21 ) + min += width; + + max = min; + } + + /* Now scan the array. If we find a stem with the same borders */ + /* simply activate it. */ + cur_stem = stems; + new_stem = 1; + + for ( n = 0; n < num_stems; n++, cur_stem++ ) + { + if ( cur_stem->min_edge.orus == min && + cur_stem->max_edge.orus == max ) + { + /* This stem is already in the table, simply activate it */ + if ( ( cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE ) == 0 ) + { + cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE; + stem_table->num_active++; + } + new_stem = 0; + break; + } + } + + /* add a new stem to the array if necessary */ + if ( new_stem ) + { + if ( cur_stem >= stems + T1_HINTER_MAX_EDGES ) + { + FT_ERROR(( "t1_hinter_stem: too many stems in glyph charstring\n" )); + return T1_Err_Syntax_Error; + } + + /* on the first pass, we record the stem, otherwise, this is */ + /* a bug in the glyph loader! */ + if ( builder->pass == 0 ) + { + cur_stem->min_edge.orus = min; + cur_stem->max_edge.orus = max; + cur_stem->hint_flags = T1_HINT_FLAG_ACTIVE; + + stem_table->num_stems++; + stem_table->num_active++; + } + else + { + FT_ERROR(( "t1_hinter_stem:" )); + FT_ERROR(( " fatal glyph loader bug -- pass2-stem\n" )); + return T1_Err_Syntax_Error; + } + } + + return T1_Err_Ok; + } + + + static + FT_Error t1_hinter_stem3( T1_Builder* builder, + FT_Pos pos0, + FT_Int width0, + FT_Pos pos1, + FT_Int width1, + FT_Pos pos2, + FT_Int width2, + FT_Bool vertical ) + { + /* For now, simply call `stem' 3 times */ + return t1_hinter_stem( builder, pos0, width0, vertical ) || + t1_hinter_stem( builder, pos1, width1, vertical ) || + t1_hinter_stem( builder, pos2, width2, vertical ); + } + + + static + FT_Error t1_hinter_changehints( T1_Builder* builder ) + { + FT_Int dimension; + T1_Stem_Table* stem_table; + T1_Glyph_Hints* hinter = builder->glyph->hints; + + + /* If we are in the second pass of glyph hinting, we must */ + /* call the function T1_Hint_Points() on the builder in order */ + /* to force the fit the latest points to the pixel grid. */ + if ( builder->pass == 1 ) + T1_Hint_Points( builder ); + + /* Simply de-activate all hints in all arrays */ + stem_table = &hinter->hori_stems; + + for ( dimension = 2; dimension > 0; dimension-- ) + { + T1_Stem_Hint* cur = stem_table->stems; + T1_Stem_Hint* limit = cur + stem_table->num_stems; + + + for ( ; cur < limit; cur++ ) + cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE; + + stem_table->num_active = 0; + stem_table = &hinter->vert_stems; + } + + return T1_Err_Ok; + } + + + const T1_Hinter_Funcs t1_hinter_funcs = + { + (T1_Hinter_ChangeHints)t1_hinter_changehints, + (T1_Hinter_DotSection) t1_hinter_ignore, + (T1_Hinter_Stem) t1_hinter_stem, + (T1_Hinter_Stem3) t1_hinter_stem3 + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** STEM HINTS MANAGEMENT *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the placement of each scaled stem hint. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* t1_sort_hints */ + /* */ + /* */ + /* Sorta the list of active stems in increasing order, through the */ + /* `sort' indexing table. */ + /* */ + /* */ + /* table :: A stem hints table. */ + /* */ + static + void t1_sort_hints( T1_Stem_Table* table ) + { + FT_Int num_stems = table->num_stems; + FT_Int num_active = 0; + FT_Int* sort = table->sort; + T1_Stem_Hint* stems = table->stems; + FT_Int n; + + + /* record active stems in sort table */ + for ( n = 0; n < num_stems; n++ ) + { + if ( stems[n].hint_flags & T1_HINT_FLAG_ACTIVE ) + sort[num_active++] = n; + } + + /* Now sort the indices. There are usually very few stems, */ + /* and they are pre-sorted in 90% cases, so we choose a */ + /* simple bubble sort (quicksort would be slower). */ + for ( n = 1; n < num_active; n++ ) + { + FT_Int p = n - 1; + T1_Stem_Hint* cur = stems + sort[n]; + + + do + { + FT_Int swap; + T1_Stem_Hint* prev = stems + sort[p]; + + + /* note that by definition, the active stems cannot overlap */ + /* so we simply compare their `min' to sort them (we could compare */ + /* their max values also; this wouldn't change anything). */ + if ( prev->min_edge.orus <= cur->min_edge.orus ) + break; + + /* swap elements */ + swap = sort[p ]; + sort[p ] = sort[p + 1]; + sort[p + 1] = swap; + p--; + + } while ( p >= 0 ); + } + + table->num_active = num_active; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_horizontal_stems */ + /* */ + /* */ + /* Computes the location of each scaled horizontal stem hint. This */ + /* takes care of the blue zones and the horizontal stem snap table. */ + /* */ + /* */ + /* table :: The horizontal stem hints table. */ + /* */ + /* hints :: The current size's hint structure. */ + /* */ + /* blueShift :: The value of the /BlueShift as taken from the face */ + /* object. */ + /* */ + /* scale :: The 16.16 scale used to convert outline units to */ + /* 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3, as well as overlapping stems control. */ + /* */ + static + void t1_hint_horizontal_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + FT_Pos blueShift, + FT_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + + /* first of all, scale the blueShift */ + blueShift = SCALE( blueShift ); + + /* then scan the horizontal stem table */ + for ( ; stem < limit; stem++ ) + { + FT_Pos bottom_orus = stem->min_edge.orus; + FT_Pos top_orus = stem->max_edge.orus; + + FT_Pos top_pix = SCALE( top_orus ); + FT_Pos bottom_pix = SCALE( bottom_orus ); + FT_Pos width_pix = top_pix - bottom_pix; + + FT_Pos bottom = bottom_pix; + FT_Pos top = top_pix; + FT_Int align = T1_ALIGN_NONE; + + + /*********************************************************************/ + /* */ + /* Snap pixel width if in stem snap range */ + /* */ + + { + T1_Snap_Zone* zone = hints->snap_heights; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; + FT_Pos best_dist = 32000; + T1_Snap_Zone* best_zone = 0; + + + for ( ; zone < zone_limit; zone++ ) + { + FT_Pos dist; + + + dist = width_pix - zone->min; + if ( dist < 0 ) + dist = -dist; + if ( dist < best_dist ) + { + best_zone = zone; + best_dist = dist; + } + } + + if ( best_zone ) + { + if ( width_pix > best_zone->pix ) + { + width_pix -= 0x20; + if ( width_pix < best_zone->pix ) + width_pix = best_zone->pix; + } + else + { + width_pix += 0x20; + if ( width_pix > best_zone->pix ) + width_pix = best_zone->pix; + } + } + } + + /*********************************************************************/ + /* */ + /* round width - minimum 1 pixel if this isn't a ghost stem */ + /* */ + + if ( width_pix > 0 ) + width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix ); + + + /*********************************************************************/ + /* */ + /* Now check for bottom blue zones alignement */ + /* */ + + { + FT_Int num_blues = hints->num_bottom_zones; + T1_Snap_Zone* blue = hints->blue_zones; + T1_Snap_Zone* blue_limit = blue + num_blues; + + + for ( ; blue < blue_limit; blue++ ) + { + if ( bottom_pix < blue->min ) + break; + + if ( bottom_pix <= blue->max ) + { + align = T1_ALIGN_BOTTOM; + bottom = ROUND( blue->pix ); + + /* implement blue shift */ + if ( !hints->supress_overshoots ) + { + FT_Pos delta = blue->pix - bottom_pix; + + + delta = delta < blueShift ? 0 : ROUND( delta ); + bottom -= delta; + } + } + } + } + + /*********************************************************************/ + /* */ + /* check for top blue zones alignement */ + /* */ + + { + FT_Int num_blues = hints->num_blue_zones - + hints->num_bottom_zones; + + T1_Snap_Zone* blue = hints->blue_zones + + hints->num_bottom_zones; + + T1_Snap_Zone* blue_limit = blue + num_blues; + + + for ( ; blue < blue_limit; blue++ ) + { + if ( top_pix < blue->min ) + break; + + if ( top_pix <= blue->max ) + { + align |= T1_ALIGN_TOP; + top = ROUND( blue->pix ); + + /* implement blue shift */ + if ( !hints->supress_overshoots ) + { + FT_Pos delta = top - blue->pix; + + + delta = delta < blueShift ? 0 : ROUND( delta ); + top += delta; + } + } + } + } + + /*********************************************************************/ + /* */ + /* compute the hinted stem position, according to its alignment */ + /* */ + + switch ( align ) + { + case T1_ALIGN_BOTTOM: /* bottom zone alignment */ + bottom_pix = bottom; + top_pix = bottom + width_pix; + break; + + case T1_ALIGN_TOP: /* top zone alignment */ + top_pix = top; + bottom_pix = top - width_pix; + break; + + case T1_ALIGN_BOTH: /* bottom+top zone alignment */ + bottom_pix = bottom; + top_pix = top; + break; + + default: /* no alignment */ + /* XXX TODO: Add management of controlled stems */ + bottom = ( SCALE( bottom_orus + top_orus ) - width_pix ) / 2; + + bottom_pix = ROUND( bottom ); + top_pix = bottom_pix + width_pix; + } + + stem->min_edge.pix = bottom_pix; + stem->max_edge.pix = top_pix; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_vertical_stems */ + /* */ + /* */ + /* Computes the location of each scaled vertical stem hint. This */ + /* takes care of the vertical stem snap table. */ + /* */ + /* */ + /* table :: The vertical stem hints table. */ + /* hints :: The current size's hint structure. */ + /* scale :: The 16.16 scale used to convert outline units to */ + /* 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3 as well as overlapping stems control. */ + /* */ + static + void t1_hint_vertical_stems( T1_Stem_Table* table, + T1_Size_Hints* hints, + FT_Fixed scale ) + { + T1_Stem_Hint* stem = table->stems; + T1_Stem_Hint* limit = stem + table->num_stems; + + + for ( ; stem < limit; stem++ ) + { + FT_Pos stem_left = stem->min_edge.orus; + FT_Pos stem_right = stem->max_edge.orus; + FT_Pos width_pix, left; + + + width_pix = SCALE( stem_right - stem_left ); + + /* Snap pixel width if in stem snap range */ + { + T1_Snap_Zone* zone = hints->snap_heights; + T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights; + FT_Pos best_dist = 32000; + T1_Snap_Zone* best_zone = 0; + + + for ( ; zone < zone_limit; zone++ ) + { + FT_Pos dist; + + + dist = width_pix - zone->min; + if ( dist < 0 ) + dist = -dist; + if ( dist < best_dist ) + { + best_zone = zone; + best_dist = dist; + } + } + + if ( best_zone ) + { + if ( width_pix > best_zone->pix ) + { + width_pix -= 0x20; + if ( width_pix < best_zone->pix ) + width_pix = best_zone->pix; + } + else + { + width_pix += 0x20; + if ( width_pix > best_zone->pix ) + width_pix = best_zone->pix; + } + } + } + + /* round width - minimum 1 pixel if this isn't a ghost stem */ + if ( width_pix > 0 ) + width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL + : ROUND( width_pix ); + + /* now place the snapped and rounded stem */ + + /* XXX TODO: implement controlled stems for the overlapping */ + /* cases */ + + left = ( SCALE( stem_left + stem_right ) - width_pix ) / 2; + + stem->min_edge.pix = ROUND( left ); + stem->max_edge.pix = stem->min_edge.pix + width_pix; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hint_point */ + /* */ + /* */ + /* Grid-fit a coordinate with regards to a given stem hints table. */ + /* */ + /* */ + /* table :: The source stem hints table. */ + /* coord :: The original coordinate, expressed in font units. */ + /* scale :: The 16.16 scale used to convert font units into */ + /* 26.6 pixels. */ + /* */ + /* */ + /* The hinted/scaled value in 26.6 pixels. */ + /* */ + /* */ + /* For now, all stems are hinted independently from each other. It */ + /* might be necessary, for better performance, to introduce the */ + /* notion of `controlled' hints describing things like counter-stems, */ + /* stem3 as well as overlapping stems control. */ + /* */ + static + FT_Pos t1_hint_point( T1_Stem_Table* table, + FT_Pos coord, + FT_Fixed scale ) + { + FT_Int num_active = table->num_active; + FT_Int n; + T1_Stem_Hint* prev = 0; + T1_Stem_Hint* cur = 0; + T1_Edge* min; + T1_Edge* max; + FT_Pos delta; + + + /* only hint when there is at least one stem defined */ + if ( num_active <= 0 ) + return SCALE( coord ); + + /* scan the stem table to determine placement of coordinate */ + /* relative to the list of sorted and stems */ + for ( n = 0; n < num_active; n++, prev = cur ) + { + cur = table->stems + table->sort[n]; + + /* is it on the left of the current edge? */ + delta = cur->min_edge.orus - coord; + if ( delta == 0 ) + return cur->min_edge.pix; + + if ( delta > 0 ) + { + /* if this is the left of the first edge, simply shift */ + if ( !prev ) + return cur->min_edge.pix - SCALE( delta ); + + /* otherwise, interpolate between the maximum of the */ + /* previous stem, and the minimum of the current one */ + min = &prev->max_edge; + max = &cur->min_edge; + + goto Interpolate; + } + + /* is it within the current edge? */ + delta = cur->max_edge.orus - coord; + if ( delta == 0 ) + return cur->max_edge.pix; + + if ( delta > 0 ) + { + /* interpolate within the stem */ + min = &cur->min_edge; + max = &cur->max_edge; + + goto Interpolate; + } + } + + /* apparently, this coordinate is on the right of the last stem */ + delta = coord - cur->max_edge.orus; + return cur->max_edge.pix + SCALE( delta ); + + Interpolate: + return min->pix + FT_MulDiv( coord - min->orus, + max->pix - min->pix, + max->orus - min->orus ); + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hint_Points */ + /* */ + /* */ + /* This function grid-fits several points in a given Type 1 builder */ + /* at once. */ + /* */ + /* */ + /* builder :: A handle to target Type 1 builder. */ + /* */ + LOCAL_FUNC + void T1_Hint_Points( T1_Builder* builder ) + { + FT_Int first = builder->hint_point; + FT_Int last = builder->current->n_points - 1; + + T1_Size size = builder->size; + FT_Fixed scale_x = size->root.metrics.x_scale; + FT_Fixed scale_y = size->root.metrics.y_scale; + + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Stem_Table* hori_stems = &hints->hori_stems; + T1_Stem_Table* vert_stems = &hints->vert_stems; + + FT_Vector* cur = builder->current->points + first; + FT_Vector* limit = cur + last - first + 1; + + + /* first of all, sort the active stem hints */ + t1_sort_hints( hori_stems ); + t1_sort_hints( vert_stems ); + + for ( ; cur < limit; cur++ ) + { + cur->x = t1_hint_point( vert_stems, cur->x, scale_x ); + cur->y = t1_hint_point( hori_stems, cur->y, scale_y ); + } + + builder->hint_point = builder->current->n_points; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Hint_Stems */ + /* */ + /* */ + /* This function is used to compute the location of each stem hint */ + /* between the first and second passes of the glyph loader on the */ + /* charstring. */ + /* */ + /* */ + /* builder :: A handle to the target builder. */ + /* */ + LOCAL_FUNC + void T1_Hint_Stems( T1_Builder* builder ) + { + T1_Glyph_Hints* hints = builder->glyph->hints; + T1_Private* priv = &builder->face->type1.private_dict; + + T1_Size size = builder->size; + FT_Fixed scale_x = size->root.metrics.x_scale; + FT_Fixed scale_y = size->root.metrics.y_scale; + + + t1_hint_horizontal_stems( &hints->hori_stems, + builder->size->hints, + priv->blue_shift, + scale_y ); + + t1_hint_vertical_stems( &hints->vert_stems, + builder->size->hints, + scale_x ); + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1hinter.h b/subsys/win32k/freetype/src/type1/t1hinter.h new file mode 100644 index 0000000..e73e2cc --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1hinter.h @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* */ +/* t1hinter.h */ +/* */ +/* Type 1 hinter (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1HINTER_H +#define T1HINTER_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" +#include "t1gload.h" + +#else + +#include +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Snap_Zone */ + /* */ + /* */ + /* A `snap zone' is used to model either a blue zone or a stem width */ + /* at a given character size. It is made of a minimum and maximum */ + /* edge, defined in 26.6 pixels, as well as an `original' and */ + /* `scaled' position. */ + /* */ + /* The position corresponds to the stem width (for stem snap zones) */ + /* or to the blue position (for blue zones). */ + /* */ + /* */ + /* orus :: The original position in font units. */ + /* */ + /* pix :: The current position in sub-pixel units. */ + /* */ + /* min :: The minimum boundary in sub-pixel units. */ + /* */ + /* max :: The maximum boundary in sub-pixel units. */ + /* */ + typedef struct T1_Snap_Zone_ + { + FT_Pos orus; + FT_Pos pix; + FT_Pos min; + FT_Pos max; + + } T1_Snap_Zone; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Edge */ + /* */ + /* */ + /* A very simple structure used to model a stem edge. */ + /* */ + /* */ + /* orus :: The original edge position in font units. */ + /* */ + /* pix :: The scaled edge position in sub-pixel units. */ + /* */ + typedef struct T1_Edge_ + { + FT_Pos orus; + FT_Pos pix; + + } T1_Edge; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Stem_Hint */ + /* */ + /* */ + /* A simple structure used to model a stem hint. */ + /* */ + /* */ + /* min_edge :: The hint's minimum edge. */ + /* */ + /* max_edge :: The hint's maximum edge. */ + /* */ + /* hint_flags :: Some flags describing the stem properties. */ + /* */ + /* */ + /* The min and max edges of a ghost stem have the same position, even */ + /* if they are coded in a weird way in the charstrings. */ + /* */ + typedef struct T1_Stem_Hint_ + { + T1_Edge min_edge; + T1_Edge max_edge; + FT_Int hint_flags; + + } T1_Stem_Hint; + + +#define T1_HINT_FLAG_ACTIVE 1 /* indicates an active stem */ +#define T1_HINT_FLAG_MIN_BORDER 2 /* unused for now */ +#define T1_HINT_FLAG_MAX_BORDER 4 /* unused for now */ + + /* hinter's configuration constants */ +#define T1_HINTER_MAX_BLUES 24 /* maximum number of blue zones */ +#define T1_HINTER_MAX_SNAPS 16 /* maximum number of stem snap zones */ +#define T1_HINTER_MAX_EDGES 64 /* maximum number of stem hints */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Size_Hints */ + /* */ + /* */ + /* A structure used to model the hinting information related to a size */ + /* object. */ + /* */ + /* */ + /* supress_overshoots :: A boolean flag to tell whether overshoot */ + /* supression should occur. */ + /* */ + /* num_blue_zones :: The total number of blue zones (top+bottom). */ + /* */ + /* num_bottom_zones :: The number of bottom zones. */ + /* */ + /* blue_zones :: The blue zones table. Bottom zones are */ + /* stored first in the table, followed by all */ + /* top zones. */ + /* */ + /* num_snap_widths :: The number of horizontal stem snap zones. */ + /* */ + /* snap_widths :: An array of horizontal stem snap zones. */ + /* */ + /* num_snap_heights :: The number of vertical stem snap zones. */ + /* */ + /* snap_heights :: An array of vertical stem snap zones. */ + /* */ + struct T1_Size_Hints_ + { + FT_Bool supress_overshoots; + + FT_Int num_blue_zones; + FT_Int num_bottom_zones; + T1_Snap_Zone blue_zones[T1_HINTER_MAX_BLUES]; + + FT_Int num_snap_widths; + T1_Snap_Zone snap_widths[T1_HINTER_MAX_SNAPS]; + + FT_Int num_snap_heights; + T1_Snap_Zone snap_heights[T1_HINTER_MAX_SNAPS]; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Stem_Table */ + /* */ + /* */ + /* A simple structure used to model a set of stem hints in a single */ + /* direction during the loading of a given glyph outline. Not all */ + /* stem hints are active at a time. Moreover, stems must be sorted */ + /* regularly. */ + /* */ + /* */ + /* num_stems :: The total number of stems in the table. */ + /* */ + /* num_active :: The number of active stems in the table. */ + /* */ + /* stems :: A table of all stems. */ + /* */ + /* sort :: A table of indices into the stems table, used to */ + /* keep a sorted list of the active stems. */ + /* */ + typedef struct T1_Stem_Table_ + { + FT_Int num_stems; + FT_Int num_active; + + T1_Stem_Hint stems[T1_HINTER_MAX_EDGES]; + FT_Int sort [T1_HINTER_MAX_EDGES]; + + } T1_Stem_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Glyph_Hints */ + /* */ + /* */ + /* A structure used to model the stem hints of a given glyph outline */ + /* during glyph loading. */ + /* */ + /* */ + /* hori_stems :: The horizontal stem hints table. */ + /* vert_stems :: The vertical stem hints table. */ + /* */ + struct T1_Glyph_Hints_ + { + T1_Stem_Table hori_stems; + T1_Stem_Table vert_stems; + }; + + + /*************************************************************************/ + /* */ + /* */ + /* t1_hinter_funcs */ + /* */ + /* */ + /* A table containing the address of various functions used during */ + /* the loading of an hinted scaled outline. */ + /* */ + extern const T1_Hinter_Funcs t1_hinter_funcs; + + + LOCAL_DEF + FT_Error T1_New_Size_Hinter( T1_Size size ); + + LOCAL_DEF + void T1_Done_Size_Hinter( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Reset_Size_Hinter( T1_Size size ); + + LOCAL_DEF + FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph ); + + LOCAL_DEF + void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph ); + + + LOCAL_DEF + void T1_Hint_Points( T1_Builder* builder ); + + LOCAL_DEF + void T1_Hint_Stems( T1_Builder* builder ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* T1HINTER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1load.c b/subsys/win32k/freetype/src/type1/t1load.c new file mode 100644 index 0000000..d480879 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1load.c @@ -0,0 +1,1594 @@ +/***************************************************************************/ +/* */ +/* t1load.c */ +/* */ +/* Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" +#include "t1parse.h" + +#else + +#include +#include + +#endif + + +#include + +#include /* for strncpy(), strncmp(), strlen() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1load + + + typedef FT_Error (*T1_Parse_Func)( T1_Parser* parser ); + + + /*************************************************************************/ + /* */ + /* */ + /* Init_T1_Parser */ + /* */ + /* */ + /* Initializes a given parser object to build a given T1_Face. */ + /* */ + /* */ + /* parser :: A handle to the newly built parser object. */ + /* */ + /* */ + /* face :: A handle to the target Type 1 face object. */ + /* */ + /* tokenizer :: A handle to the target Type 1 token manager. */ + /* */ + LOCAL_FUNC + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ) + { + parser->error = 0; + parser->face = face; + parser->tokenizer = tokenizer; + parser->top = parser->stack; + parser->limit = parser->stack + T1_MAX_STACK_DEPTH; + + parser->state_index = 0; + parser->state_stack[0] = dict_none; + + parser->encoding_type = t1_encoding_none; + parser->encoding_names = 0; + parser->encoding_offsets = 0; + parser->encoding_lengths = 0; + + parser->dump_tokens = 0; + face->type1.private_dict.lenIV = 4; /* XXX : is it sure? */ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Next_T1_Token */ + /* */ + /* */ + /* Grabs the next significant token from a parser's input stream. */ + /* This function ignores a number of tokens, and translates */ + /* alternate forms into their common ones. */ + /* */ + /* */ + /* parser :: A handle to the source parser. */ + /* */ + /* */ + /* token :: The extracted token descriptor. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Next_T1_Token( T1_Parser* parser, + T1_Token* token ) + { + FT_Error error; + T1_Tokenizer tokzer = parser->tokenizer; + + + L1: + error = Read_Token( tokzer ); + if ( error ) + return error; + + /* we now must ignore a number of tokens like `dup', `executeonly', */ + /* `readonly', etc. */ + *token = tokzer->token; + if ( token->kind == tok_keyword ) + switch( token->kind2 ) + { + case key_dup: + case key_execonly: + case key_readonly: + case key_noaccess: + case key_userdict: + /* do nothing - loop */ + goto L1; + + /* we also translate some other keywords from their alternative */ + /* to their `normal' form */ + + case key_NP_alternate: + token->kind2 = key_NP; + break; + + case key_RD_alternate: + token->kind2 = key_RD; + break; + + case key_ND_alternate: + token->kind2 = key_ND; + break; + + default: + ; + } + +#if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE ) + + /* Dump the token when requested. This feature is only available */ + /* in the `error' and `trace' debug levels. */ + if ( parser->dump_tokens ) + { + FT_String temp_string[128]; + FT_Int len; + + + len = token->len; + if ( len > 127 ) + len = 127; + strncpy( temp_string, + (FT_String*)tokzer->base + token->start, + len ); + temp_string[len] = '\0'; + FT_ERROR(( "%s\n", temp_string )); + } + +#endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */ + + return T1_Err_Ok; + } + + + static + FT_Error Expect_Keyword( T1_Parser* parser, + T1_TokenType keyword ) + { + T1_Token token; + FT_Error error; + + + error = Next_T1_Token( parser, &token ); + if ( error ) + goto Exit; + + if ( token.kind != tok_keyword || + token.kind2 != keyword ) + { + error = T1_Err_Syntax_Error; + FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n", + t1_keywords[keyword - key_first_] )); + } + + Exit: + return error; + } + + + static + FT_Error Expect_Keyword2( T1_Parser* parser, + T1_TokenType keyword1, + T1_TokenType keyword2 ) + { + T1_Token token; + FT_Error error; + + + error = Next_T1_Token( parser, &token ); + if ( error ) + goto Exit; + + if ( token.kind != tok_keyword || + ( token.kind2 != keyword1 && + token.kind2 != keyword2 ) ) + { + error = T1_Err_Syntax_Error; + FT_ERROR(( "Expect_Keyword2: keyword `%s' or `%s' expected.\n", + t1_keywords[keyword1 - key_first_], + t1_keywords[keyword2 - key_first_] )); + } + + Exit: + return error; + } + + + static + void Parse_Encoding( T1_Parser* parser ) + { + T1_Token* token = parser->top+1; + FT_Memory memory = parser->face->root.memory; + T1_Encoding* encode = &parser->face->type1.encoding; + FT_Error error = 0; + + + if ( token->kind == tok_keyword && + ( token->kind2 == key_StandardEncoding || + token->kind2 == key_ExpertEncoding ) ) + { + encode->num_chars = 256; + encode->code_first = 32; + encode->code_last = 255; + + if ( ALLOC_ARRAY( encode->char_index, 256, FT_Short ) ) + goto Exit; + + encode->char_name = 0; /* no need to store glyph names */ + + /* Now copy the encoding */ + switch ( token->kind2 ) + { + case key_ExpertEncoding: + parser->encoding_type = t1_encoding_expert; + break; + + default: + parser->encoding_type = t1_encoding_standard; + break; + } + } + else + { + FT_ERROR(( "Parse_Encoding: invalid encoding type\n" )); + error = T1_Err_Syntax_Error; + } + + Exit: + parser->error = error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Font */ + /* */ + /* */ + /* This function performs a `def' if in the Font dictionary. Its */ + /* purpose is to build the T1_Face attributes directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Font( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Face face = parser->face; + T1_Font* type1 = &face->type1; + + + switch ( top[0].kind2 ) + { + case imm_FontName: + /* in some cases, the /FontName is an immediate like */ + /* /TimesNewRoman. In this case, we simply copy the */ + /* token string (without the /). */ + if ( top[1].kind == tok_immediate ) + { + FT_Memory memory = parser->tokenizer->memory; + FT_Error error; + FT_Int len = top[1].len; + + + if ( ALLOC( type1->font_name, len + 1 ) ) + { + parser->error = error; + return error; + } + + MEM_Copy( type1->font_name, + parser->tokenizer->base + top[1].start, + len ); + type1->font_name[len] = '\0'; + } + else + type1->font_name = CopyString( parser ); + break; + + case imm_Encoding: + Parse_Encoding( parser ); + break; + + case imm_PaintType: + type1->paint_type = (FT_Byte)CopyInteger( parser ); + break; + + case imm_FontType: + type1->font_type = (FT_Byte)CopyInteger( parser ); + break; + + case imm_FontMatrix: + CopyMatrix( parser, &type1->font_matrix ); + break; + + case imm_FontBBox: + CopyBBox( parser, &type1->font_bbox ); + break; + + case imm_UniqueID: + type1->private_dict.unique_id = CopyInteger( parser ); + break; + + case imm_StrokeWidth: + type1->stroke_width = CopyInteger( parser ); + break; + + case imm_FontID: + type1->font_id = CopyInteger( parser ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_FontInfo */ + /* */ + /* */ + /* This function performs a `def' if in the FontInfo dictionary. Its */ + /* purpose is to build the T1_FontInfo structure directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_FontInfo( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_FontInfo* info = &parser->face->type1.font_info; + + + switch ( top[0].kind2 ) + { + case imm_version: + info->version = CopyString( parser ); + break; + + case imm_Notice: + info->notice = CopyString( parser ); + break; + + case imm_FullName: + info->full_name = CopyString( parser ); + break; + + case imm_FamilyName: + info->family_name = CopyString( parser ); + break; + + case imm_Weight: + info->weight = CopyString( parser ); + break; + + case imm_ItalicAngle: + info->italic_angle = CopyInteger( parser ); + break; + + case imm_isFixedPitch: + info->is_fixed_pitch = CopyBoolean( parser ); + break; + + case imm_UnderlinePosition: + info->underline_position = (FT_Short)CopyInteger( parser ); + break; + + case imm_UnderlineThickness: + info->underline_thickness = (FT_Short)CopyInteger( parser ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Private */ + /* */ + /* */ + /* This function performs a `def' if in the Private dictionary. Its */ + /* purpose is to build the T1_Private structure directly from the */ + /* stream. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeTyoe error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Private( T1_Parser* parser ) + { + T1_Token* top = parser->top; + T1_Private* priv = &parser->face->type1.private_dict; + + + switch ( top[0].kind2 ) + { + /* Ignore the definitions of RD, NP, ND, and their alternate forms */ + case imm_RD: + case imm_RD_alternate: + case imm_ND: + case imm_ND_alternate: + case imm_NP: + case imm_NP_alternate: + parser->error = T1_Err_Ok; + break; + + case imm_BlueValues: + CopyArray( parser, &priv->num_blue_values, + priv->blue_values, 14 ); + break; + + case imm_OtherBlues: + CopyArray( parser, &priv->num_other_blues, + priv->other_blues, 10 ); + break; + + case imm_FamilyBlues: + CopyArray( parser, &priv->num_family_blues, + priv->family_blues, 14 ); + break; + + case imm_FamilyOtherBlues: + CopyArray( parser, &priv->num_family_other_blues, + priv->family_other_blues, 10 ); + break; + + case imm_BlueScale: + priv->blue_scale = CopyFloat( parser, 0x10000L ); + break; + + case imm_BlueShift: + priv->blue_shift = CopyInteger( parser ); + break; + + case imm_BlueFuzz: + priv->blue_fuzz = CopyInteger( parser ); + break; + + case imm_StdHW: + CopyArray( parser, 0, (FT_Short*)&priv->standard_width, 1 ); + break; + + case imm_StdVW: + CopyArray( parser, 0, (FT_Short*)&priv->standard_height, 1 ); + break; + + case imm_StemSnapH: + CopyArray( parser, &priv->num_snap_widths, + priv->snap_widths, 12 ); + break; + + case imm_StemSnapV: + CopyArray( parser, &priv->num_snap_heights, + priv->snap_heights, 12 ); + break; + + case imm_ForceBold: + priv->force_bold = CopyBoolean( parser ); + break; + + case imm_LanguageGroup: + priv->language_group = CopyInteger( parser ); + break; + + case imm_password: + priv->password = CopyInteger( parser ); + break; + + case imm_UniqueID: + priv->unique_id = CopyInteger( parser ); + break; + + case imm_lenIV: + priv->lenIV = CopyInteger( parser ); + break; + + case imm_MinFeature: + CopyArray( parser, 0, priv->min_feature, 2 ); + break; + + default: + /* ignore all other things */ + parser->error = T1_Err_Ok; + } + + return parser->error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Def_Error */ + /* */ + /* */ + /* This function returns a simple syntax error when invoked. It is */ + /* used for the `def' keyword if in the `encoding', `subrs', */ + /* `othersubrs', and `charstrings' dictionary states. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Def_Error( T1_Parser* parser ) + { + FT_ERROR(( "Do_Def_Error:" )); + FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" )); + + parser->error = T1_Err_Syntax_Error; + + return parser->error; + } + + + static + FT_Error Do_Def_Ignore( T1_Parser* parser ) + { + FT_UNUSED( parser ); + return T1_Err_Ok; + } + + + static + T1_Parse_Func def_funcs[dict_max] = + { + Do_Def_Error, + Do_Def_Font, + Do_Def_FontInfo, + Do_Def_Ignore, + Do_Def_Private, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + Do_Def_Ignore, + }; + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_Put_Encoding */ + /* */ + /* */ + /* This function performs a `put' if in the Encoding array. The */ + /* glyph name is copied into the T1 recorder, and the charcode and */ + /* glyph name pointer are written into the face object encoding. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_Put_Encoding( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Encoding* encode = &face->type1.encoding; + FT_Int index; + + + /* record and check the character code */ + if ( top[0].kind != tok_number ) + { + FT_TRACE4(( "Do_Put_Encoding: number expected\n" )); + goto Syntax_Error; + } + index = (FT_Int)CopyInteger( parser ); + if ( parser->error ) + return parser->error; + + if ( index < 0 || index >= encode->num_chars ) + { + FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" )); + goto Syntax_Error; + } + + /* record the immediate name */ + if ( top[1].kind != tok_immediate ) + { + FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" )); + goto Syntax_Error; + } + + /* if the glyph name is `.notdef', store a NULL char name; */ + /* otherwise, record the glyph name */ + if ( top[1].kind == imm_notdef ) + { + parser->table.elements[index] = 0; + parser->table.lengths [index] = 0; + } + else + { + FT_String temp_name[128]; + T1_Token* token = top + 1; + FT_Int len = token->len - 1; + + + /* copy immediate name */ + if ( len > 127 ) + len = 127; + MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len ); + temp_name[len] = '\0'; + + error = T1_Add_Table( &parser->table, index, + (FT_Byte*)temp_name, len + 1 ); + + /* adjust code_first and code_last */ + if ( index < encode->code_first ) encode->code_first = index; + if ( index > encode->code_last ) encode->code_last = index; + } + return error; + + Syntax_Error: + /* ignore the error, and simply clear the stack */ + FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" )); + parser->top = parser->stack; + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON */ + /* CURRENT DICTIONARY STATE */ + /* */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Do_RD_Subrs */ + /* */ + /* */ + /* This function performs an `RD' if in the Subrs dictionary. It */ + /* simply records the array of bytecodes/charstrings corresponding to */ + /* the sub-routine. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_RD_Subrs( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + FT_Int index, count; + + + /* record and check the character code */ + if ( top[0].kind != tok_number || + top[1].kind != tok_number ) + { + FT_ERROR(( "Do_RD_Subrs: number expected\n" )); + goto Syntax_Error; + } + index = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + count = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + if ( index < 0 || index >= face->type1.num_subrs ) + { + FT_ERROR(( "Do_RD_Subrs: invalid character code\n" )); + goto Syntax_Error; + } + + /* decrypt charstring and skip it */ + { + FT_Byte* base = tokzer->base + tokzer->cursor; + + + tokzer->cursor += count; + + /* some fonts use a value of -1 for lenIV to indicate that */ + /* the charstrings are unencoded. */ + /* */ + /* Thanks to Tom Kacvinsky for pointing this out. */ + /* */ + if ( face->type1.private_dict.lenIV >= 0 ) + { + t1_decrypt( base, count, 4330 ); + + base += face->type1.private_dict.lenIV; + count -= face->type1.private_dict.lenIV; + } + + error = T1_Add_Table( &parser->table, index, base, count ); + } + + /* consume the closing NP or `put' */ + error = Expect_Keyword2( parser, key_NP, key_put ); + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Do_RD_CharStrings */ + /* */ + /* */ + /* This function performs an `RD' if in the CharStrings dictionary. */ + /* It simply records the array of bytecodes/charstrings corresponding */ + /* to the glyph program string. */ + /* */ + /* */ + /* parser :: A handle to the current parser. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error Do_RD_Charstrings( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + T1_Face face = parser->face; + T1_Token* top = parser->top; + T1_Tokenizer tokzer = parser->tokenizer; + FT_Int index, count; + + + /* check the character name argument */ + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" )); + goto Syntax_Error; + } + + /* check the count argument */ + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "Do_RD_Charstrings: number expected\n" )); + goto Syntax_Error; + } + + parser->args++; + count = (FT_Int)CopyInteger( parser ); + error = parser->error; + if ( error ) + goto Exit; + + /* record the glyph name and get the corresponding glyph index */ + if ( top[0].kind2 == imm_notdef ) + index = 0; + else + { + FT_String temp_name[128]; + T1_Token* token = top; + FT_Int len = token->len - 1; + + + /* copy immediate name */ + if ( len > 127 ) + len = 127; + MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len ); + temp_name[len] = '\0'; + + index = parser->cur_name++; + error = T1_Add_Table( &parser->table, index * 2, + (FT_Byte*)temp_name, len + 1 ); + if ( error ) + goto Exit; + } + + /* decrypt and record charstring, then skip them */ + { + FT_Byte* base = tokzer->base + tokzer->cursor; + + + tokzer->cursor += count; /* skip */ + + if ( face->type1.private_dict.lenIV >= 0 ) + { + t1_decrypt( base, count, 4330 ); + + base += face->type1.private_dict.lenIV; + count -= face->type1.private_dict.lenIV; + } + + error = T1_Add_Table( &parser->table, index * 2 + 1, base, count ); + } + + /* consume the closing `ND' */ + if ( !error ) + error = Expect_Keyword( parser, key_ND ); + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Expect_Dict_Arguments( T1_Parser* parser, + FT_Int num_args, + T1_TokenType immediate, + T1_DictState new_state, + FT_Int* count ) + { + /* check that we have enough arguments in the stack, including */ + /* the `dict' keyword */ + if ( parser->top - parser->stack < num_args ) + { + FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments", + num_args )); + goto Syntax_Error; + } + + /* check that we have the correct immediate, if needed */ + if ( num_args == 2 ) + { + if ( parser->top[-2].kind != tok_immediate || + parser->top[-2].kind2 != immediate ) + { + FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n", + t1_immediates[immediate - imm_first_] )); + goto Syntax_Error; + } + } + + parser->args = parser->top-1; + + /* check that the count argument is a number */ + if ( parser->args->kind != tok_number ) + { + FT_ERROR(( "Expect_Dict_Arguments:" )); + FT_ERROR(( " expecting numerical count argument for `dict'\n" )); + goto Syntax_Error; + } + + if ( count ) + { + *count = CopyInteger( parser ); + if ( parser->error ) + return parser->error; + } + + /* save the dictionary state */ + parser->state_stack[++parser->state_index] = new_state; + + /* consume the `begin' keyword and clear the stack */ + parser->top -= num_args; + return Expect_Keyword( parser, key_begin ); + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Expect_Array_Arguments( T1_Parser* parser ) + { + T1_Token* top = parser->top; + FT_Error error = T1_Err_Ok; + T1_DictState new_state; + FT_Int count; + T1_Face face = parser->face; + FT_Memory memory = face->root.memory; + + + /* Check arguments format */ + if ( top - parser->stack < 2 ) + { + FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" )); + error = T1_Err_Stack_Underflow; + goto Exit; + } + + parser->top -= 2; + top -= 2; + parser->args = top + 1; + + if ( top[0].kind != tok_immediate ) + { + FT_ERROR(( "Expect_Array_Arguments:" )); + FT_ERROR(( " first argument must be an immediate name\n" )); + goto Syntax_Error; + } + + if ( top[1].kind != tok_number ) + { + FT_ERROR(( "Expect_Array_Arguments:" )); + FT_ERROR(( " second argument must be a number\n" )); + goto Syntax_Error; + } + + count = (FT_Int)CopyInteger( parser ); + + /* Is this an array we know about? */ + switch ( top[0].kind2 ) + { + case imm_Encoding: + { + T1_Encoding* encode = &face->type1.encoding; + + + new_state = dict_encoding; + + encode->code_first = count; + encode->code_last = 0; + encode->num_chars = count; + + /* Allocate the table of character indices. The table of */ + /* character names is allocated through init_t1_recorder(). */ + if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ) + return error; + + error = T1_New_Table( &parser->table, count, memory ); + if ( error ) + goto Exit; + + parser->encoding_type = t1_encoding_array; + } + break; + + case imm_Subrs: + new_state = dict_subrs; + face->type1.num_subrs = count; + + error = T1_New_Table( &parser->table, count, memory ); + if ( error ) + goto Exit; + break; + + case imm_CharStrings: + new_state = dict_charstrings; + break; + + default: + new_state = dict_unknown_array; + } + + parser->state_stack[++parser->state_index] = new_state; + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + } + + + static + FT_Error Finalize_Parsing( T1_Parser* parser ) + { + T1_Face face = parser->face; + T1_Font* type1 = &face->type1; + FT_Memory memory = face->root.memory; + T1_Table* strings = &parser->table; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + FT_Int num_glyphs; + FT_Int n; + FT_Error error; + + + num_glyphs = type1->num_glyphs = parser->cur_name; + + /* allocate glyph names and charstrings arrays */ + if ( ALLOC_ARRAY( type1->glyph_names, num_glyphs, FT_String* ) || + ALLOC_ARRAY( type1->charstrings, num_glyphs, FT_Byte* ) || + ALLOC_ARRAY( type1->charstrings_len, num_glyphs, FT_Int* ) ) + return error; + + /* copy glyph names and charstrings offsets and lengths */ + type1->charstrings_block = strings->block; + for ( n = 0; n < num_glyphs; n++ ) + { + type1->glyph_names[n] = (FT_String*)strings->elements[2 * n]; + type1->charstrings[n] = strings->elements[2 * n + 1]; + type1->charstrings_len[n] = strings->lengths [2 * n + 1]; + } + + /* now free the old tables */ + FREE( strings->elements ); + FREE( strings->lengths ); + + if ( !psnames ) + { + FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" )); + return T1_Err_Unimplemented_Feature; + } + + /* compute encoding if required */ + if ( parser->encoding_type == t1_encoding_none ) + { + FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" )); + return T1_Err_Syntax_Error; + } + + { + FT_Int n; + T1_Encoding* encode = &type1->encoding; + + + encode->code_first = encode->num_chars - 1; + encode->code_last = 0; + + for ( n = 0; n < encode->num_chars; n++ ) + { + FT_String** names; + FT_Int index; + FT_Int m; + + + switch ( parser->encoding_type ) + { + case t1_encoding_standard: + index = psnames->adobe_std_encoding[n]; + names = 0; + break; + + case t1_encoding_expert: + index = psnames->adobe_expert_encoding[n]; + names = 0; + break; + + default: + index = n; + names = (FT_String**)parser->encoding_offsets; + } + + encode->char_index[n] = 0; + + if ( index ) + { + FT_String* name; + + + if ( names ) + name = names[index]; + else + name = (FT_String*)psnames->adobe_std_strings(index); + + if ( name ) + { + FT_Int len = strlen( name ); + + + /* lookup glyph index from name */ + for ( m = 0; m < num_glyphs; m++ ) + { + if ( strncmp( type1->glyph_names[m], name, len ) == 0 ) + { + encode->char_index[n] = m; + break; + } + } + + if ( n < encode->code_first ) encode->code_first = n; + if ( n > encode->code_last ) encode->code_last = n; + } + } + } + + parser->encoding_type = t1_encoding_none; + + FREE( parser->encoding_names ); + FREE( parser->encoding_lengths ); + FREE( parser->encoding_offsets ); + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Parse_T1_FontProgram */ + /* */ + /* */ + /* Parses a given Type 1 font file and builds its face object. */ + /* */ + /* */ + /* parser :: A handle to the target parser object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* The parser contains a handle to the target face object. */ + /* */ + LOCAL_FUNC + FT_Error Parse_T1_FontProgram( T1_Parser* parser ) + { + FT_Error error; + T1_Font* type1 = &parser->face->type1; + + + for (;;) + { + T1_Token token; + T1_Token* top; + T1_DictState dict_state; + FT_Int dict_index; + + + error = Next_T1_Token( parser, &token ); + top = parser->top; + dict_index = parser->state_index; + dict_state = parser->state_stack[dict_index]; + + switch ( token.kind ) + { + /* a keyword has been detected */ + case tok_keyword: + switch ( token.kind2 ) + { + case key_dict: + switch ( dict_state ) + { + case dict_none: + /* All right, we are beginning the font dictionary. */ + /* Check that we only have one number argument, then */ + /* consume the `begin' and change to `dict_font' */ + /* state. */ + error = Expect_Dict_Arguments( parser, 1, tok_error, + dict_font, 0 ); + if ( error ) + goto Exit; + + /* clear stack from all the previous content. This */ + /* could be some stupid Postscript code. */ + parser->top = parser->stack; + break; + + case dict_font: + /* This must be the /FontInfo dictionary, so check */ + /* that we have at least two arguments, that they */ + /* are `/FontInfo' and a number, then change the */ + /* dictionary state. */ + error = Expect_Dict_Arguments( parser, 2, imm_FontInfo, + dict_fontinfo, 0 ); + if ( error ) + goto Exit; + break; + + case dict_none2: + error = Expect_Dict_Arguments( parser, 2, imm_Private, + dict_private, 0 ); + if ( error ) + goto Exit; + break; + + case dict_private: + { + T1_Face face = parser->face; + FT_Int count; + + + error = Expect_Dict_Arguments( parser, 2, imm_CharStrings, + dict_charstrings, &count ); + if ( error ) + goto Exit; + + type1->num_glyphs = count; + error = T1_New_Table( &parser->table, count * 2, + face->root.memory ); + if ( error ) + goto Exit; + + /* record `.notdef' as the first glyph in the font */ + error = T1_Add_Table( &parser->table, 0, + (FT_Byte*)".notdef", 8 ); + parser->cur_name = 1; + /* XXX: DO SOMETHING HERE */ + } + break; + + default: + /* All other uses are invalid */ + FT_ERROR(( "Parse_T1_FontProgram:" )); + FT_ERROR(( " invalid use of `dict' keyword\n" )); + goto Syntax_Error; + } + break; + + case key_array: + /* Are we in an array yet? If so, raise an error */ + switch ( dict_state ) + { + case dict_encoding: + case dict_subrs: + case dict_othersubrs: + case dict_charstrings: + case dict_unknown_array: + FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" )); + goto Syntax_Error; + + default: + ; + } + error = Expect_Array_Arguments( parser ); + if ( error ) + goto Exit; + break; + + case key_ND: + case key_NP: + case key_def: + /* Are we in an array? If so, finalize it. */ + switch ( dict_state ) + { + case dict_encoding: /* finish encoding array */ + /* copy table names to the face object */ + T1_Done_Table( &parser->table ); + + parser->encoding_names = parser->table.block; + parser->encoding_lengths = parser->table.lengths; + parser->encoding_offsets = parser->table.elements; + + parser->state_index--; + break; + + case dict_subrs: + /* copy recorder sub-routines */ + T1_Done_Table( &parser->table ); + + parser->subrs = parser->table.block; + type1->subrs = parser->table.elements; + type1->subrs_len = parser->table.lengths; + type1->subrs_block = parser->table.block; + + parser->state_index--; + break; + + case dict_charstrings: + case dict_othersubrs: + case dict_unknown_array: + FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" )); + goto Syntax_Error; + break; + + default: /* normal `def' processing */ + /* Check that we have sufficient operands in the stack */ + if ( top >= parser->stack + 2 ) + { + /* Now check that the first operand is an immediate. */ + /* If so, call the appropriate `def' routine based */ + /* on the current parser state. */ + if ( top[-2].kind == tok_immediate ) + { + parser->top -= 2; + parser->args = parser->top + 1; + error = def_funcs[dict_state](parser); + } + else + { + /* This is an error, but some fonts contain */ + /* stupid Postscript code. We simply ignore */ + /* an invalid `def' by clearing the stack. */ +#if 0 + FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" )); + goto Syntax_Error; +#else + parser->top = parser->stack; +#endif + } + } + else + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + } + break; + + case key_index: + if ( top <= parser->stack ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + /* simply ignore? */ + parser->top --; + break; + + case key_put: + /* Check that we have sufficient operands in stack */ + if ( top < parser->stack + 2 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 2; + parser->args = parser->top; + + switch ( dict_state ) + { + case dict_encoding: + error = Do_Put_Encoding( parser ); + if ( error ) + goto Exit; + break; + + case dict_unknown_array: /* ignore the `put' */ + break; + + default: +#if 0 + FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" )); + goto Syntax_Error; +#else + /* invalid context; simply ignore the `put' and */ + /* clear the stack (stupid Postscript code) */ + FT_TRACE4(( "Parse_T1_FontProgram: invalid context ignored.\n" )); + parser->top = parser->stack; +#endif + } + break; + + case key_RD: + /* Check that we have sufficient operands in stack */ + if ( top < parser->stack + 2 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 2; + parser->args = parser->top; + switch ( dict_state ) + { + case dict_subrs: + error = Do_RD_Subrs( parser ); + if ( error ) + goto Exit; + break; + + case dict_charstrings: + error = Do_RD_Charstrings( parser ); + if ( error ) + goto Exit; + break; + + default: + FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" )); + goto Syntax_Error; + } + break; + + case key_end: + /* Were we in a dictionary or in an array? */ + if ( dict_index <= 0 ) + { + FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" )); + goto Syntax_Error; + } + + switch ( dict_state ) + { + /* jump to the private dictionary if we are closing the */ + /* `/Font' dictionary */ + case dict_font: + goto Open_Private; + + /* exit the parser when closing the CharStrings dictionary */ + case dict_charstrings: + return Finalize_Parsing( parser ); + + default: + /* Pop the current dictionary state and return to previous */ + /* one. Consume the `def'. */ + + /* Because some buggy fonts (BitStream) have incorrect */ + /* syntax, we never escape from the private dictionary */ + if ( dict_state != dict_private ) + parser->state_index--; + + /* many fonts use `NP' instead of `def' or `put', so */ + /* we simply ignore the next token */ +#if 0 + error = Expect_Keyword2( parser, key_def, key_put ); + if ( error ) + goto Exit; +#else + (void)Expect_Keyword2( parser, key_def, key_put ); +#endif + } + break; + + case key_for: + /* check that we have four arguments and simply */ + /* ignore them */ + if ( top - parser->stack < 4 ) + { + FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" )); + goto Stack_Underflow; + } + + parser->top -= 4; + break; + + case key_currentdict: + Open_Private: + parser->state_index = 0; + parser->state_stack[0] = dict_none2; + error = Open_PrivateDict( parser->tokenizer ); + if ( error ) + goto Exit; + break; + + case key_true: + case key_false: + case key_StandardEncoding: + case key_ExpertEncoding: + goto Push_Element; + + default: + FT_ERROR(( "Parse_T1_FontProgram:" )); + FT_ERROR(( " invalid keyword in context\n" )); + error = T1_Err_Syntax_Error; + } + break; + + /* check for the presence of `/BlendAxisTypes' -- we cannot deal */ + /* with multiple master fonts, so we must return a correct error */ + /* code to allow another driver to load them */ + case tok_immediate: + if ( token.kind2 == imm_BlendAxisTypes ) + { + error = FT_Err_Unknown_File_Format; + goto Exit; + } + /* fallthrough */ + + /* A number was detected */ + case tok_string: + case tok_program: + case tok_array: + case tok_hexarray: + case tok_any: + case tok_number: /* push number on stack */ + + Push_Element: + if ( top >= parser->limit ) + { + error = T1_Err_Stack_Overflow; + goto Exit; + } + else + *parser->top++ = token; + break; + + /* anything else is an error per se the spec, but we */ + /* frequently encounter stupid postscript code in fonts, */ + /* so just ignore them */ + default: + error = T1_Err_Ok; /* ignore token */ + } + + if ( error ) + return error; + } + + Exit: + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1load.h b/subsys/win32k/freetype/src/type1/t1load.h new file mode 100644 index 0000000..b1671c6 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1load.h @@ -0,0 +1,57 @@ +/***************************************************************************/ +/* */ +/* t1load.h */ +/* */ +/* Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1LOAD_H +#define T1LOAD_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1parse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + LOCAL_DEF + void Init_T1_Parser( T1_Parser* parser, + T1_Face face, + T1_Tokenizer tokenizer ); + + + LOCAL_DEF + FT_Error Parse_T1_FontProgram( T1_Parser* parser ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1LOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1objs.c b/subsys/win32k/freetype/src/type1/t1objs.c new file mode 100644 index 0000000..31a74a5 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1objs.c @@ -0,0 +1,544 @@ +/***************************************************************************/ +/* */ +/* t1objs.c */ +/* */ +/* Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1gload.h" +#include "t1load.h" +#include "t1afm.h" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.h" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1objs + + + /*************************************************************************/ + /* */ + /* SIZE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Size */ + /* */ + /* */ + /* The Type 1 size object destructor. Used to discard a given size */ + /* object. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + LOCAL_FUNC + void T1_Done_Size( T1_Size size ) + { + if ( size ) + { + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + T1_Done_Size_Hinter( size ); +#endif + + size->valid = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Size */ + /* */ + /* */ + /* The size object initializer. */ + /* */ + /* */ + /* size :: A handle to the target size object. */ + /* */ + /* */ + /* FreeTrue error code. 0 means success. */ + /* */ + LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ) + { + FT_Error error; + + + size->valid = 0; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + error = T1_New_Size_Hinter( size ); + + return error; +#else + + FT_UNUSED( error ); + + return T1_Err_Ok; + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Reset_Size */ + /* */ + /* */ + /* Resets an instance to a new pointsize/transform. This function is */ + /* in charge of resetting the blue zones,a s well as the stem snap */ + /* tables for a given size. */ + /* */ + /* */ + /* size :: The target size object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Reset_Size( T1_Size size ) + { + /* recompute ascender, descender, etc. */ + T1_Face face = (T1_Face)size->root.face; + FT_Size_Metrics* metrics = &size->root.metrics; + + + if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) + return FT_Err_Invalid_Argument; + + /* Compute root ascender, descender, test height, and max_advance */ + metrics->ascender = ( FT_MulFix( face->root.ascender, + metrics->y_scale ) + 32 ) & -64; + metrics->descender = ( FT_MulFix( face->root.descender, + metrics->y_scale ) + 32 ) & -64; + metrics->height = ( FT_MulFix( face->root.height, + metrics->y_scale ) + 32 ) & -64; + metrics->max_advance = ( FT_MulFix( face->root.max_advance_width, + metrics->x_scale ) + 32 ) & -64; + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + return T1_Reset_Size_Hinter( size ); +#else + return 0; +#endif + } + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Face */ + /* */ + /* */ + /* The face object destructor. */ + /* */ + /* */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void T1_Done_Face( T1_Face face ) + { + FT_Memory memory; + T1_Font* type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + + /* release font info strings */ + { + T1_FontInfo* info = &type1->font_info; + + + FREE( info->version ); + FREE( info->notice ); + FREE( info->full_name ); + FREE( info->family_name ); + FREE( info->weight ); + } + + /* release top dictionary */ + FREE( type1->charstrings_len ); + FREE( type1->charstrings ); + FREE( type1->glyph_names ); + + FREE( type1->subrs ); + FREE( type1->subrs_len ); + + FREE( type1->subrs_block ); + FREE( type1->charstrings_block ); + FREE( type1->glyph_names_block ); + + FREE( type1->encoding.char_index ); + FREE( type1->font_name ); + +#ifndef T1_CONFIG_OPTION_NO_AFM + /* release afm data if present */ + if ( face->afm_data ) + T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); +#endif + + /* release unicode map, if any */ + FREE( face->unicode_map.maps ); + face->unicode_map.num_maps = 0; + + face->root.family_name = 0; + face->root.style_name = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_Face */ + /* */ + /* */ + /* The face object constructor. */ + /* */ + /* */ + /* stream :: input stream where to load font data. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* */ + /* face :: The face record to build. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + T1_Tokenizer tokenizer; + FT_Error error; + PSNames_Interface* psnames; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( face ); + + + face->root.num_faces = 1; + + psnames = (PSNames_Interface*)face->psnames; + if ( !psnames ) + { + psnames = (PSNames_Interface*) + FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), + "psnames" ); + + face->psnames = psnames; + } + + /* open the tokenizer, this will also check the font format */ + error = New_Tokenizer( stream, &tokenizer ); + if ( error ) + goto Fail; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Leave; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "T1_Init_Face: invalid face index\n" )); + error = T1_Err_Invalid_Argument; + goto Leave; + } + + /* Now, load the font program into the face object */ + { + T1_Parser parser; + + + Init_T1_Parser( &parser, face, tokenizer ); + error = Parse_T1_FontProgram( &parser ); + if ( error ) + goto Leave; + + /* Init the face object fields */ + /* Now set up root face fields */ + { + FT_Face root = (FT_Face)&face->root; + T1_Font* type1 = &face->type1; + + + root->num_glyphs = type1->num_glyphs; + root->num_charmaps = 1; + + root->face_index = face_index; + root->face_flags = FT_FACE_FLAG_SCALABLE; + + root->face_flags |= FT_FACE_FLAG_HORIZONTAL; + + root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; + + if ( type1->font_info.is_fixed_pitch ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* XXX: TODO -- add kerning with .afm support */ + + /* get style name - be careful, some broken fonts only */ + /* have a `/FontName' dictionary entry! */ + root->family_name = type1->font_info.family_name; + if ( root->family_name ) + { + char* full = type1->font_info.full_name; + char* family = root->family_name; + + + while ( *family && *full == *family ) + { + family++; + full++; + } + + root->style_name = ( *full == ' ' ? full + 1 + : (char *)"Regular" ); + } + else + { + /* do we have a `/FontName'? */ + if (type1->font_name) + { + root->family_name = type1->font_name; + root->style_name = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = type1->font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)type1->font_bbox.yMax; + root->descender = -(FT_Short)type1->font_bbox.yMin; + root->height = ( ( root->ascender + root->descender) * 12 ) + / 10; + + /* now compute the maximum advance width */ + + root->max_advance_width = type1->private_dict.standard_width[0]; + + /* compute max advance width for proportional fonts */ + if ( !type1->font_info.is_fixed_pitch ) + { + FT_Int max_advance; + + + error = T1_Compute_Max_Advance( face, &max_advance ); + + /* in case of error, keep the standard width */ + if ( !error ) + root->max_advance_width = max_advance; + else + error = 0; /* clear error */ + } + + root->max_advance_height = root->height; + + root->underline_position = type1->font_info.underline_position; + root->underline_thickness = type1->font_info.underline_thickness; + + root->max_points = 0; + root->max_contours = 0; + } + } + + /* charmap support - synthetize unicode charmap when possible */ + { + FT_Face root = &face->root; + FT_CharMap charmap = face->charmaprecs; + + + /* synthesize a Unicode charmap if there is support in the `PSNames' */ + /* module.. */ + if ( face->psnames ) + { + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + + if ( psnames->unicode_value ) + { + error = psnames->build_unicodes( + root->memory, + face->type1.num_glyphs, + (const char**)face->type1.glyph_names, + &face->unicode_map ); + if ( !error ) + { + root->charmap = charmap; + charmap->face = (FT_Face)face; + charmap->encoding = ft_encoding_unicode; + charmap->platform_id = 3; + charmap->encoding_id = 1; + charmap++; + } + + /* simply clear the error in case of failure (which really) */ + /* means that out of memory or no unicode glyph names */ + error = 0; + } + } + + /* now, support either the standard, expert, or custom encodings */ + charmap->face = (FT_Face)face; + charmap->platform_id = 7; /* a new platform id for Adobe fonts ?? */ + + switch ( face->type1.encoding_type ) + { + case t1_encoding_standard: + charmap->encoding = ft_encoding_adobe_standard; + charmap->encoding_id = 0; + break; + + case t1_encoding_expert: + charmap->encoding = ft_encoding_adobe_expert; + charmap->encoding_id = 1; + break; + + default: + charmap->encoding = ft_encoding_adobe_custom; + charmap->encoding_id = 2; + break; + } + + root->charmaps = face->charmaps; + root->num_charmaps = charmap - face->charmaprecs + 1; + face->charmaps[0] = &face->charmaprecs[0]; + face->charmaps[1] = &face->charmaprecs[1]; + } + + Leave: + Done_Tokenizer( tokenizer ); + + Fail: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_GlyphSlot */ + /* */ + /* */ + /* The glyph slot object destructor. */ + /* */ + /* */ + /* glyph :: The glyph slot handle to destroy. */ + /* */ + LOCAL_FUNC + void T1_Done_GlyphSlot( T1_GlyphSlot glyph ) + { +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + T1_Done_Glyph_Hinter( glyph ); + +#else + + FT_UNUSED( glyph ); + +#endif + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Init_GlyphSlot */ + /* */ + /* */ + /* The glyph slot object constructor. */ + /* */ + /* */ + /* glyph :: The glyph slot handle to initialize. */ + /* */ + LOCAL_FUNC + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph ) + { + FT_Error error = FT_Err_Ok; + + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER + + error = T1_New_Glyph_Hinter( glyph ); + +#else + + FT_UNUSED( glyph ); + +#endif + + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1objs.h b/subsys/win32k/freetype/src/type1/t1objs.h new file mode 100644 index 0000000..47b0a37 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1objs.h @@ -0,0 +1,172 @@ +/***************************************************************************/ +/* */ +/* t1objs.h */ +/* */ +/* Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1OBJS_H +#define T1OBJS_H + +#include +#include +#include + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /* The following structures must be defined by the hinter */ + typedef struct T1_Size_Hints_ T1_Size_Hints; + typedef struct T1_Glyph_Hints_ T1_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct T1_DriverRec_* T1_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct T1_SizeRec_* T1_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct T1_GlyphSlotRec_* T1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* The Type 1 format doesn't use a charmap but an encoding table. */ + /* The driver is responsible for making up charmap objects */ + /* corresponding to these tables. */ + /* */ + typedef struct T1_CharMapRec_* T1_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_SizeRec */ + /* */ + /* */ + /* Type 1 size record. */ + /* */ + typedef struct T1_SizeRec_ + { + FT_SizeRec root; + FT_Bool valid; + T1_Size_Hints* hints; /* defined in the hinter. This allows */ + /* us to experiment with different */ + /* hinting schemes without having to */ + /* change `t1objs' each time. */ + } T1_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_GlyphSlotRec */ + /* */ + /* */ + /* Type 1 glyph slot record. */ + /* */ + typedef struct T1_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Int max_points; + FT_Int max_contours; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + T1_Glyph_Hints* hints; /* defined in the hinter */ + + } T1_GlyphSlotRec; + + + LOCAL_DEF + FT_Error T1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void T1_Done_Face( T1_Face face ); + + LOCAL_DEF + FT_Error T1_Init_Size( T1_Size size ); + + LOCAL_DEF + void T1_Done_Size( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Reset_Size( T1_Size size ); + + LOCAL_DEF + FT_Error T1_Init_GlyphSlot( T1_GlyphSlot slot ); + + LOCAL_DEF + void T1_Done_GlyphSlot( T1_GlyphSlot slot ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1OBJS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1parse.c b/subsys/win32k/freetype/src/type1/t1parse.c new file mode 100644 index 0000000..b025df2 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1parse.c @@ -0,0 +1,761 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1parse.h" + +#else + +#include + +#endif + + +#include /* for sscanf() */ +#include /* for strncpy() */ + + + /*************************************************************************/ + /* */ + /* */ + /* T1_New_Table */ + /* */ + /* */ + /* Initializes a T1_Table structure. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size (i.e. maximum number of elements). */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error T1_New_Table( T1_Table* table, + FT_Int count, + FT_Memory memory ) + { + FT_Error error; + + + table->memory = memory; + + if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ) + return error; + + if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) + { + FREE( table->elements ); + return error; + } + + table->max_elems = count; + table->num_elems = 0; + + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + return error; + } + + + static + FT_Error reallocate_t1_table( T1_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* reallocate the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + table->capacity = new_size; + + /* shift all offsets if necessary */ + if ( old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset ++ ) + if (offset[0]) + offset[0] += delta; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Add_Table */ + /* */ + /* */ + /* Adds an object to a T1_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* index :: The index of the object in the table. */ + /* */ + /* object :: The address of the object to copy in memory. */ + /* */ + /* length :: The length in bytes of the source object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation failed. */ + /* */ + LOCAL_FUNC + FT_Error T1_Add_Table( T1_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "T1_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* add the object to the base block and adjust offset */ + table->elements[index] = table->block + table->cursor; + table->lengths [index] = length; + MEM_Copy( table->block + table->cursor, object, length ); + + table->cursor += length; + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Done_Table */ + /* */ + /* */ + /* Finalize a T1_Table (reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* This function does NOT release the heap's memory block. It is up */ + /* to the caller to clean it, or reference it in its own structures. */ + /* */ + LOCAL_FUNC + void T1_Done_Table( T1_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + { + FT_Long delta = table->block - old_base; + FT_Byte** element = table->elements; + FT_Byte** limit = element + table->max_elems; + + + for ( ; element < limit; element++ ) + if ( element[0] ) + element[0] += delta; + } + } + + + LOCAL_FUNC + FT_String* CopyString( T1_Parser* parser ) + { + FT_String* string = NULL; + T1_Token* token = parser->args++; + FT_Memory memory = parser->tokenizer->memory; + FT_Error error; + + + if ( token->kind == tok_string ) + { + FT_Int len = token->len - 2; + + + if ( ALLOC( string, len + 1 ) ) + { + parser->error = error; + return 0; + } + + MEM_Copy( string, parser->tokenizer->base + token->start + 1, len ); + string[len] = '\0'; + + parser->error = T1_Err_Ok; + } + else + { + FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + return string; + } + + + static + FT_Error parse_int( FT_Byte* base, + FT_Byte* limit, + FT_Long* result ) + { + FT_Bool sign = 0; + FT_Long sum = 0; + + + if ( base >= limit ) + goto Fail; + + /* check sign */ + if ( *base == '+' ) + base++; + + else if ( *base == '-' ) + { + sign++; + base++; + } + + /* parse digits */ + if ( base >= limit ) + goto Fail; + + do + { + sum = ( 10 * sum + ( *base++ - '0' ) ); + + } while ( base < limit ); + + if ( sign ) + sum = -sum; + + *result = sum; + return T1_Err_Ok; + + Fail: + FT_ERROR(( "parse_int: integer expected\n" )); + *result = 0; + return T1_Err_Syntax_Error; + } + + + static + FT_Error parse_float( FT_Byte* base, + FT_Byte* limit, + FT_Long scale, + FT_Long* result ) + { +#if 1 + + /* XXX: We are simply much too lazy to code this function */ + /* properly for now. We will do that when the rest of */ + /* the driver works properly. */ + char temp[32]; + int len = limit - base; + double value; + + + if ( len > 31 ) + goto Fail; + + strncpy( temp, (char*)base, len ); + temp[len] = '\0'; + if ( sscanf( temp, "%lf", &value ) != 1 ) + goto Fail; + + *result = (FT_Long)( scale * value ); + return 0; + +#else + + FT_Byte* cur; + FT_Bool sign = 0; /* sign */ + FT_Long number_int = 0; /* integer part */ + FT_Long number_frac = 0; /* fractional part */ + FT_Long exponent = 0; /* exponent value */ + FT_Int num_frac = 0; /* number of fractional digits */ + + + /* check sign */ + if ( *base == '+' ) + base++; + + else if ( *base == '-' ) + { + sign++; + base++; + } + + /* find integer part */ + cur = base; + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( c == '.' || c == 'e' || c == 'E' ) + break; + + cur++; + } + + if ( cur > base ) + { + error = parse_integer( base, cur, &number_int ); + if ( error ) + goto Fail; + } + + /* read fractional part, if any */ + if ( *cur == '.' ) + { + cur++; + base = cur; + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( c == 'e' || c == 'E' ) + break; + cur++; + } + + num_frac = cur - base; + + if ( cur > base ) + { + error = parse_integer( base, cur, &number_frac ); + if ( error ) + goto Fail; + base = cur; + } + } + + /* read exponent, if any */ + if ( *cur == 'e' || *cur == 'E' ) + { + cur++; + base = cur; + error = parse_integer( base, limit, &exponent ); + if ( error ) + goto Fail; + + /* now check that exponent is within `correct bounds' */ + /* i.e. between -6 and 6 */ + if ( exponent < -6 || exponent > 6 ) + goto Fail; + } + + /* now adjust integer value and exponent for fractional part */ + while ( num_frac > 0 ) + { + number_int *= 10; + exponent--; + num_frac--; + } + + number_int += num_frac; + + /* skip point if any, read fractional part */ + if ( cur + 1 < limit ) + { + if (*cur.. + } + + /* now compute scaled float value */ + /* XXX: incomplete! */ + +#endif /* 1 */ + + Fail: + FT_ERROR(( "parse_float: syntax error!\n" )); + return T1_Err_Syntax_Error; + } + + + static + FT_Error parse_integer( FT_Byte* base, + FT_Byte* limit, + FT_Long* result ) + { + FT_Byte* cur; + + + /* the lexical analyser accepts floats as well as integers */ + /* now; check that we really have an int in this token */ + cur = base; + while ( cur < limit ) + { + FT_Byte c = *cur++; + + + if ( c == '.' || c == 'e' || c == 'E' ) + goto Float_Number; + } + + /* now read the number's value */ + return parse_int( base, limit, result ); + + Float_Number: + /* we really have a float there; simply call parse_float in this */ + /* case with a scale of `10' to perform round */ + { + FT_Error error; + + + error = parse_float( base, limit, 10, result ); + if ( !error ) + { + if ( *result >= 0 ) + *result = ( *result + 5 ) / 10; /* round value */ + else + *result = -( ( 5 - *result ) / 10 ); + } + return error; + } + } + + + LOCAL_FUNC + FT_Long CopyInteger( T1_Parser* parser ) + { + FT_Long sum = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_number ) + { + FT_Byte* base = parser->tokenizer->base + token->start; + FT_Byte* limit = base + token->len; + + + /* now read the number's value */ + parser->error = parse_integer( base, limit, &sum ); + return sum; + } + + FT_ERROR(( "CopyInteger: number expected\n" )); + parser->args--; + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + LOCAL_FUNC + FT_Bool CopyBoolean( T1_Parser* parser ) + { + FT_Error error = T1_Err_Ok; + FT_Bool result = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_keyword ) + { + if ( token->kind2 == key_false ) + result = 0; + + else if ( token->kind2 == key_true ) + result = !0; + + else + goto Fail; + } + else + { + Fail: + FT_ERROR(( "CopyBoolean:" )); + FT_ERROR(( " syntax error; `false' or `true' expected\n" )); + error = T1_Err_Syntax_Error; + } + parser->error = error; + return result; + } + + + LOCAL_FUNC + FT_Long CopyFloat( T1_Parser* parser, + FT_Int scale ) + { + FT_Error error; + FT_Long sum = 0; + T1_Token* token = parser->args++; + + + if ( token->kind == tok_number ) + { + FT_Byte* base = parser->tokenizer->base + token->start; + FT_Byte* limit = base + token->len; + + + error = parser->error = parse_float( base, limit, scale, &sum ); + if ( error ) + goto Fail; + + return sum; + } + + Fail: + FT_ERROR(( "CopyFloat: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + return 0; + } + + + LOCAL_FUNC + void CopyBBox( T1_Parser* parser, + FT_BBox* bbox ) + { + T1_Token* token = parser->args++; + FT_Int n; + FT_Error error; + + + if ( token->kind == tok_program || + token->kind == tok_array ) + { + /* get rid of `['/`]', or `{'/`}' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + FT_Long* result; + + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ' ) + cur++; + + /* compute result address */ + switch ( n ) + { + case 0: + result = &bbox->xMin; + break; + case 1: + result = &bbox->yMin; + break; + case 2: + result = &bbox->xMax; + break; + default: + result = &bbox->yMax; + } + + error = parse_integer( start, cur, result ); + if ( error ) + goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyBBox: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + LOCAL_FUNC + void CopyMatrix( T1_Parser* parser, + FT_Matrix* matrix ) + { + T1_Token* token = parser->args++; + FT_Error error; + + + if ( token->kind == tok_array ) + { + /* get rid of `[' and `]' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + FT_Int n; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < 4; n++ ) + { + FT_Long* result; + + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ') + cur++; + + /* compute result address */ + switch ( n ) + { + case 0: + result = &matrix->xx; + break; + case 1: + result = &matrix->yx; + break; + case 2: + result = &matrix->xy; + break; + default: + result = &matrix->yy; + } + + error = parse_float( start, cur, 65536000L, result ); + if ( error ) + goto Fail; + } + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyMatrix: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + + LOCAL_FUNC + void CopyArray( T1_Parser* parser, + FT_Byte* num_elements, + FT_Short* elements, + FT_Int max_elements ) + { + T1_Token* token = parser->args++; + FT_Error error; + + + if ( token->kind == tok_array || + token->kind == tok_program ) /* in the case of MinFeature */ + { + /* get rid of `['/`]', or `{'/`}' */ + FT_Byte* base = parser->tokenizer->base + token->start + 1; + FT_Byte* limit = base + token->len - 2; + FT_Byte* cur; + FT_Byte* start; + FT_Int n; + + + /* read each parameter independently */ + cur = base; + for ( n = 0; n < max_elements; n++ ) + { + FT_Long result; + + + /* test end of string */ + if ( cur >= limit ) + break; + + /* skip whitespace */ + while ( cur < limit && *cur == ' ' ) + cur++; + + /* end of list? */ + if ( cur >= limit ) + break; + + /* skip numbers */ + start = cur; + while ( cur < limit && *cur != ' ' ) + cur++; + + error = parse_integer( start, cur, &result ); + if ( error ) + goto Fail; + + *elements++ = (FT_Short)result; + } + + if ( num_elements ) + *num_elements = (FT_Byte)n; + + parser->error = 0; + return; + } + + Fail: + FT_ERROR(( "CopyArray: syntax error!\n" )); + parser->error = T1_Err_Syntax_Error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1parse.h b/subsys/win32k/freetype/src/type1/t1parse.h new file mode 100644 index 0000000..a064629 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1parse.h @@ -0,0 +1,261 @@ +/***************************************************************************/ +/* */ +/* t1parse.h */ +/* */ +/* Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The Type1 parser component is in charge of simply parsing the font */ + /* input stream and convert simple tokens and elements into integers, */ + /* floats, matrices, strings, etc. */ + /* */ + /* It is used by the Type1 loader. */ + /* */ + /*************************************************************************/ + + +#ifndef T1PARSE_H +#define T1PARSE_H + +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* T1_DictState */ + /* */ + /* */ + /* An enumeration used to describe the Type 1 parser's state, i.e. */ + /* which dictionary (or array) it is scanning and processing at the */ + /* current moment. */ + /* */ + typedef enum T1_DictState_ + { + dict_none = 0, + dict_font, /* parsing the font dictionary */ + dict_fontinfo, /* parsing the font info dictionary */ + dict_none2, /* beginning to parse the encrypted section */ + dict_private, /* parsing the private dictionary */ + dict_encoding, /* parsing the encoding array */ + dict_subrs, /* parsing the subrs array */ + dict_othersubrs, /* parsing the othersubrs array (?) */ + dict_charstrings, /* parsing the charstrings dictionary */ + dict_unknown_array, /* parsing/ignoring an unknown array */ + dict_unknown_dict, /* parsing/ignoring an unknown dictionary */ + + dict_max /* do not remove from list */ + + } T1_DictState; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Table */ + /* */ + /* */ + /* A T1_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to */ + /* reallocation. */ + /* */ + /* cursor :: The current top of the grow heap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments by */ + /* 1kByte chunks. */ + /* */ + /* max_elems :: The maximum number of elements in table. */ + /* */ + /* num_elems :: The current number of elements in table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The object used for memory operations */ + /* (alloc/realloc). */ + /* */ + typedef struct T1_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int capacity; /* current size of memory block */ + + FT_Int max_elems; + FT_Int num_elems; + FT_Byte** elements; /* addresses of table elements */ + FT_Int* lengths; /* lengths of table elements */ + + FT_Memory memory; + + } T1_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Parser */ + /* */ + /* */ + /* A Type 1 parser. This object is in charge of parsing Type 1 ASCII */ + /* streams and builds dictionaries for a T1_Face object. */ + /* */ + /* */ + /* error :: The current error code. 0 means success. */ + /* */ + /* face :: The target T1_Face object being built. */ + /* */ + /* tokenizer :: The tokenizer (lexical analyser) used for */ + /* processing the input stream. */ + /* */ + /* dump_tokens :: XXX */ + /* */ + /* stack :: The current token stack. Note that we don't */ + /* use intermediate Postscript objects here! */ + /* */ + /* top :: The current top of token stack. */ + /* */ + /* limit :: The current upper bound of the token stack. */ + /* Used for overflow checks. */ + /* */ + /* args :: The arguments of a given operator. Used and */ + /* increased by the various CopyXXX() functions. */ + /* */ + /* state_index :: The index of the top of the dictionary state */ + /* stack. */ + /* */ + /* state_stack :: The dictionary states stack. */ + /* */ + /* table :: A T1_Table object used to record various kinds */ + /* of dictionaries or arrays (like `/Encoding', */ + /* `/Subrs', `/CharStrings'). */ + /* */ + /* cur_name :: XXX */ + /* */ + /* encoding_type :: XXX */ + /* */ + /* encoding_names :: XXX */ + /* */ + /* encoding_lengths :: XXX */ + /* */ + /* encoding_offsets :: XXX */ + /* */ + /* subrs :: XXX */ + /* */ + /* charstrings :: XXX */ + /* */ + typedef struct T1_Parser_ + { + FT_Error error; + T1_Face face; + + T1_Tokenizer tokenizer; + FT_Bool dump_tokens; + + T1_Token stack[T1_MAX_STACK_DEPTH]; + T1_Token* top; + T1_Token* limit; + T1_Token* args; + + FT_Int state_index; + T1_DictState state_stack[T1_MAX_DICT_DEPTH]; + + T1_Table table; + + FT_Int cur_name; + + T1_EncodingType encoding_type; + FT_Byte* encoding_names; + FT_Int* encoding_lengths; + FT_Byte** encoding_offsets; + + FT_Byte* subrs; + FT_Byte* charstrings; + + } T1_Parser; + + + LOCAL_DEF + FT_Error T1_New_Table( T1_Table* table, + FT_Int count, + FT_Memory memory ); + + LOCAL_DEF + FT_Error T1_Add_Table( T1_Table* table, + FT_Int index, + void* object, + FT_Int length ); + + LOCAL_DEF + void T1_Done_Table( T1_Table* table ); + + + LOCAL_DEF + FT_String* CopyString( T1_Parser* parser ); + + LOCAL_DEF + FT_Long CopyInteger( T1_Parser* parser ); + + LOCAL_DEF + FT_Bool CopyBoolean( T1_Parser* parser ); + + LOCAL_DEF + FT_Long CopyFloat( T1_Parser* parser, + FT_Int scale ); + + LOCAL_DEF + void CopyBBox( T1_Parser* parser, + FT_BBox* bbox ); + + LOCAL_DEF + void CopyMatrix( T1_Parser* parser, + FT_Matrix* matrix ); + + LOCAL_DEF + void CopyArray( T1_Parser* parser, + FT_Byte* num_elements, + FT_Short* elements, + FT_Int max_elements ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1PARSE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1tokens.c b/subsys/win32k/freetype/src/type1/t1tokens.c new file mode 100644 index 0000000..b90024d --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1tokens.c @@ -0,0 +1,1101 @@ +/***************************************************************************/ +/* */ +/* t1parse.c */ +/* */ +/* Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The tokenizer is in charge of loading and reading a Type1 font file */ + /* (either in PFB or PFA format), and extracting successive tokens and */ + /* keywords from its two streams (i.e. the font program, and the private */ + /* dictionary). */ + /* */ + /* Eexec decryption is performed automatically when entering the private */ + /* dictionary, or when retrieving char strings. */ + /* */ + /*************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "t1tokens.h" +#include "t1load.h" + +#else + +#include +#include + +#endif + + +#include /* for strncmp() */ + + +#undef READ_BUFFER_INCREMENT +#define READ_BUFFER_INCREMENT 0x400 + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1load + + + /* An array of Type1 keywords supported by this engine. This table */ + /* places the keyword in lexicographical order. It should always */ + /* correspond to the enums `key_xxx'! */ + /* */ + const char* t1_keywords[key_max - key_first_] = + { + "-|", "ExpertEncoding", "ND", "NP", "RD", "StandardEncoding", "array", + "begin", "closefile", "currentdict", "currentfile", "def", "dict", "dup", + "eexec", "end", "executeonly", "false", "for", "index", "noaccess", + "put", "readonly", "true", "userdict", "|", "|-" + }; + + + const char* t1_immediates[imm_max - imm_first_] = + { + "-|", ".notdef", "BlendAxisTypes", "BlueFuzz", "BlueScale", "BlueShift", + "BlueValues", "CharStrings", "Encoding", "FamilyBlues", "FamilyName", + "FamilyOtherBlues", "FID", "FontBBox", "FontID", "FontInfo", "FontMatrix", + "FontName", "FontType", "ForceBold", "FullName", "ItalicAngle", + "LanguageGroup", "Metrics", "MinFeature", "ND", "NP", "Notice", + "OtherBlues", "OtherSubrs", "PaintType", "Private", "RD", "RndStemUp", + "StdHW", "StdVW", "StemSnapH", "StemSnapV", "StrokeWidth", "Subrs", + "UnderlinePosition", "UnderlineThickness", "UniqueID", "Weight", + "isFixedPitch", "lenIV", "password", "version", "|", "|-" + }; + + + /* lexicographic comparison of two strings */ + static + int lexico_strcmp( const char* str1, + int str1_len, + const char* str2 ) + { + int c2 = 0; + + + for ( ; str1_len > 0; str1_len-- ) + { + int c1, diff; + + + c1 = *str1++; + c2 = *str2++; + + diff = c1 - c2; + if ( diff ) + return diff; + }; + + return -*str2; + } + + + /* find a given token/name, performing binary search */ + static + int Find_Name( char* base, + int length, + const char** table, + int table_len ) + { + int left, right; + + + left = 0; + right = table_len - 1; + + while ( right - left > 1 ) + { + int middle = left + ( ( right - left ) >> 1 ); + int cmp; + + + cmp = lexico_strcmp( base, length, table[middle] ); + if ( !cmp ) + return middle; + + if ( cmp < 0 ) + right = middle; + else + left = middle; + } + + if ( !lexico_strcmp( base, length, table[left ] ) ) + return left; + if ( !lexico_strcmp( base, length, table[right] ) ) + return right; + + return -1; + } + + + /* read the small PFB section header */ + static + FT_Error Read_PFB_Tag( FT_Stream stream, + FT_UShort* atag, + FT_ULong* asize ) + { + FT_UShort tag; + FT_ULong size; + FT_Error error; + + + FT_TRACE2(( "Read_PFB_Tag: reading\n" )); + + if ( ACCESS_Frame( 6L ) ) + return error; + + tag = GET_UShort(); + size = GET_ULong(); + + FORGET_Frame(); + + *atag = tag; + *asize = ( ( size & 0xFF ) << 24 ) | + ( ( ( size >> 8 ) & 0xFF ) << 16 ) | + ( ( ( size >> 16 ) & 0xFF ) << 8 ) | + ( ( ( size >> 24 ) & 0xFF ) ); + + FT_TRACE2(( " tag = %04x\n", tag )); + FT_TRACE4(( " asze = %08x\n", size )); + FT_TRACE2(( " size = %08x\n", *asize )); + + return T1_Err_Ok; + } + + + static + FT_Error grow( T1_Tokenizer tokzer ) + { + FT_Error error; + FT_Long left_bytes; + FT_Memory memory = tokzer->memory; + + + left_bytes = tokzer->max - tokzer->limit; + + if ( left_bytes > 0 ) + { + FT_Stream stream = tokzer->stream; + + + if ( left_bytes > READ_BUFFER_INCREMENT ) + left_bytes = READ_BUFFER_INCREMENT; + + FT_TRACE2(( "Growing tokenizer buffer by %d bytes\n", left_bytes )); + + if ( !REALLOC( tokzer->base, tokzer->limit, + tokzer->limit + left_bytes ) && + !FILE_Read( tokzer->base + tokzer->limit, left_bytes ) ) + tokzer->limit += left_bytes; + } + else + { + FT_ERROR(( "Unexpected end of Type1 fragment!\n" )); + error = T1_Err_Invalid_File_Format; + } + + tokzer->error = error; + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1_decrypt */ + /* */ + /* */ + /* Performs the Type 1 charstring decryption process. */ + /* */ + /* */ + /* buffer :: The base address of the data to decrypt. */ + /* length :: The number of bytes to decrypt (beginning from the base */ + /* address. */ + /* seed :: The encryption seed (4330 for charstrings). */ + /* */ + LOCAL_FUNC + void t1_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* New_Tokenizer */ + /* */ + /* */ + /* Creates a new tokenizer from a given input stream. This function */ + /* automatically recognizes `pfa' or `pfb' files. The function */ + /* Read_Token() can then be used to extract successive tokens from */ + /* the stream. */ + /* */ + /* */ + /* stream :: The input stream. */ + /* */ + /* */ + /* tokenizer :: A handle to a new tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* This function copies the stream handle within the object. Callers */ + /* should not discard `stream'. This is done by the Done_Tokenizer() */ + /* function. */ + /* */ + LOCAL_FUNC + FT_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ) + { + FT_Memory memory = stream->memory; + T1_Tokenizer tokzer; + FT_Error error; + FT_UShort tag; + FT_ULong size; + + FT_Byte* tok_base; + FT_ULong tok_limit; + FT_ULong tok_max; + + + *tokenizer = 0; + + /* allocate object */ + if ( FILE_Seek( 0L ) || + ALLOC( tokzer, sizeof ( *tokzer ) ) ) + return error; + + tokzer->stream = stream; + tokzer->memory = stream->memory; + + tokzer->in_pfb = 0; + tokzer->in_private = 0; + + tok_base = 0; + tok_limit = 0; + tok_max = stream->size; + + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error ) + goto Fail; + + if ( tag != 0x8001 ) + { + /* assume that it is a PFA file -- an error will be produced later */ + /* if a character with value > 127 is encountered */ + + /* rewind to start of file */ + if ( FILE_Seek( 0L ) ) + goto Fail; + + size = stream->size; + } + else + tokzer->in_pfb = 1; + + /* if it is a memory-based resource, set up pointer */ + if ( !stream->read ) + { + tok_base = (FT_Byte*)stream->base + stream->pos; + tok_limit = size; + tok_max = size; + + /* check that the `size' field is valid */ + if ( FILE_Skip( size ) ) + goto Fail; + } + else if ( tag == 0x8001 ) + { + /* read segment in memory */ + if ( ALLOC( tok_base, size ) ) + goto Fail; + + if ( FILE_Read( tok_base, size ) ) + { + FREE( tok_base ); + goto Fail; + } + + tok_limit = size; + tok_max = size; + } + + tokzer->base = tok_base; + tokzer->limit = tok_limit; + tokzer->max = tok_max; + tokzer->cursor = 0; + + *tokenizer = tokzer; + + /* now check font format; we must see `%!PS-AdobeFont-1' */ + /* or `%!FontType' */ + { + if ( 16 > tokzer->limit ) + grow( tokzer ); + + if ( tokzer->limit <= 16 || + ( strncmp( (const char*)tokzer->base, "%!PS-AdobeFont-1", 16 ) && + strncmp( (const char*)tokzer->base, "%!FontType", 10 ) ) ) + { + FT_TRACE2(( "[not a Type1 font]\n" )); + error = FT_Err_Unknown_File_Format; + goto Fail; + } + } + return T1_Err_Ok; + + Fail: + FREE( tokzer->base ); + FREE( tokzer ); + return error; + } + + + /* return the value of an hexadecimal digit */ + static + int hexa_value( char c ) + { + unsigned int d; + + + d = (unsigned int)( c - '0' ); + if ( d <= 9 ) + return (int)d; + + d = (unsigned int)( c - 'a' ); + if ( d <= 5 ) + return (int)( d + 10 ); + + d = (unsigned int)( c - 'A' ); + if ( d <= 5 ) + return (int)( d + 10 ); + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Done_Tokenizer */ + /* */ + /* */ + /* Closes a given tokenizer. This function will also close the */ + /* stream embedded in the object. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Done_Tokenizer( T1_Tokenizer tokenizer ) + { + FT_Memory memory = tokenizer->memory; + + + /* clear read buffer if needed (disk-based resources) */ + if ( tokenizer->in_private || !tokenizer->stream->base ) + FREE( tokenizer->base ); + + FREE( tokenizer ); + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Open_PrivateDict */ + /* */ + /* */ + /* This function must be called to set the tokenizer to the private */ + /* section of the Type1 file. It recognizes automatically the */ + /* the kind of eexec encryption used (ascii or binary). */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* lenIV :: The value of the `lenIV' variable. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Open_PrivateDict( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tokzer = tokenizer; + FT_Stream stream = tokzer->stream; + FT_Memory memory = tokzer->memory; + FT_Error error = 0; + + FT_UShort tag; + FT_ULong size; + + FT_Byte* private_dict; + + /* are we already in the private dictionary ? */ + if ( tokzer->in_private ) + return 0; + + if ( tokzer->in_pfb ) + { + /* in the case of the PFB format, the private dictionary can be */ + /* made of several segments. We thus first read the number of */ + /* segments to compute the total size of the private dictionary */ + /* then re-read them into memory. */ + FT_Long start_pos = FILE_Pos(); + FT_ULong private_dict_size = 0; + + + for (;;) + { + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + break; + + private_dict_size += size; + + if ( FILE_Skip( size ) ) + goto Fail; + } + + /* check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if ( private_dict_size == 0 ) + { + FT_ERROR(( "Open_PrivateDict:" )); + FT_ERROR(( " invalid private dictionary section\n" )); + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + if ( ALLOC( private_dict, private_dict_size ) ) + goto Fail; + + /* read all sections into buffer */ + if ( FILE_Seek( start_pos ) ) + goto Fail_Private; + + private_dict_size = 0; + for (;;) + { + error = Read_PFB_Tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + { + error = 0; + break; + } + + if ( FILE_Read( private_dict + private_dict_size, size ) ) + goto Fail_Private; + + private_dict_size += size; + } + + /* we must free the field `tokzer.base' if we are in a disk-based */ + /* PFB file. */ + if ( stream->read ) + FREE( tokzer->base ); + + tokzer->base = private_dict; + tokzer->cursor = 0; + tokzer->limit = private_dict_size; + tokzer->max = private_dict_size; + } + else + { + char* base; + + + /* we are in a PFA file; read each token until we find `eexec' */ + while ( tokzer->token.kind2 != key_eexec ) + { + error = Read_Token( tokzer ); + if ( error ) + goto Fail; + } + + /* now determine whether the private dictionary is encoded in binary */ + /* or hexadecimal ASCII format. */ + + /* we need to access the next 4 bytes (after the final \r following */ + /* the `eexec' keyword); if they all are hexadecimal digits, then */ + /* we have a case of ASCII storage. */ + while ( tokzer->cursor + 5 > tokzer->limit ) + { + error = grow( tokzer ); + if ( error ) + goto Fail; + } + + /* skip whitespace/line feed after `eexec' */ + base = (char*)tokzer->base + tokzer->cursor + 1; + if ( ( hexa_value( base[0] ) | hexa_value( base[1] ) | + hexa_value( base[2] ) | hexa_value( base[3] ) ) < 0 ) + { + /* binary encoding -- `simply' read the stream */ + + /* if it is a memory-based resource, we need to allocate a new */ + /* storage buffer for the private dictionary, as it must be */ + /* decrypted later */ + if ( stream->base ) + { + size = stream->size - tokzer->cursor - 1; /* remaining bytes */ + + if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */ + goto Fail; + + /* copy eexec-encrypted bytes */ + MEM_Copy( private_dict, tokzer->base + tokzer->cursor + 1, size ); + + /* reset pointers - forget about file mapping */ + tokzer->base = private_dict; + tokzer->limit = size; + tokzer->max = size; + tokzer->cursor = 0; + } + /* On the opposite, for disk based resources, we simply grow */ + /* the current buffer until its completion, and decrypt the */ + /* bytes within it. In all cases, the `base' buffer will be */ + /* discarded on DoneTokenizer if we are in the private dict. */ + else + { + /* grow the read buffer to the full file */ + while ( tokzer->limit < tokzer->max ) + { + error = grow( tokenizer ); + if ( error ) + goto Fail; + } + + /* set up cursor to first encrypted byte */ + tokzer->cursor++; + } + } + else + { + /* ASCII hexadecimal encoding. This sucks... */ + FT_Byte* write; + FT_Byte* cur; + FT_Byte* limit; + FT_Int count; + + + /* allocate a buffer, read each one byte at a time */ + count = stream->size - tokzer->cursor; + size = count / 2; + + if ( ALLOC( private_dict, size ) ) /* alloc private dict buffer */ + goto Fail; + + write = private_dict; + cur = tokzer->base + tokzer->cursor; + limit = tokzer->base + tokzer->limit; + + /* read each bytes */ + while ( count > 0 ) + { + /* ensure that we can read the next 2 bytes! */ + while ( cur + 2 > limit ) + { + int cursor = cur - tokzer->base; + + + error = grow( tokzer ); + if ( error ) + goto Fail_Private; + cur = tokzer->base + cursor; + limit = tokzer->base + tokzer->limit; + } + + /* check for new line */ + if ( cur[0] == '\r' || cur[0] == '\n' ) + { + cur++; + count--; + } + else + { + int hex1 = hexa_value(cur[0]); + + + /* exit if we have a non-hexadecimal digit which isn't */ + /* a new-line character */ + if ( hex1 < 0 ) + break; + + /* otherwise, store byte */ + *write++ = ( hex1 << 4 ) | hexa_value( cur[1] ); + cur += 2; + count -= 2; + } + } + + /* get rid of old buffer in the case of disk-based resources */ + if ( !stream->base ) + FREE( tokzer->base ); + + /* set up pointers */ + tokzer->base = private_dict; + tokzer->limit = size; + tokzer->max = size; + tokzer->cursor = 0; + } + } + + /* finally, decrypt the private dictionary - and skip the lenIV bytes */ + t1_decrypt( tokzer->base, tokzer->limit, 55665 ); + tokzer->cursor += 4; + + Fail: + return error; + + Fail_Private: + FREE( private_dict ); + goto Fail; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Read_Token */ + /* */ + /* */ + /* Reads a new token from the current input stream. This function */ + /* extracts a token from the font program until Open_PrivateDict() */ + /* has been called. After this, it returns tokens from the */ + /* (eexec-encrypted) private dictionary. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Use the function Read_CharStrings() to read the binary charstrings */ + /* from the private dict. */ + /* */ + LOCAL_FUNC + FT_Error Read_Token( T1_Tokenizer tokenizer ) + { + T1_Tokenizer tok = tokenizer; + FT_Long cur, limit; + FT_Byte* base; + char c, starter, ender; + FT_Bool token_started; + + T1_TokenType kind; + + + tok->error = T1_Err_Ok; + tok->token.kind = tok_any; + + base = tok->base; + limit = tok->limit; + cur = tok->cursor; + + token_started = 0; + + for (;;) + { + if ( cur >= limit ) + { + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + c = (char)base[cur++]; + + /* check that we have an ASCII character */ + if ( (FT_Byte)c > 127 ) + { + FT_ERROR(( "Read_Token:" )); + FT_ERROR(( " unexpected binary data in Type1 fragment!\n" )); + tok->error = T1_Err_Invalid_File_Format; + goto Exit; + } + + switch ( c ) + { + case '\r': + case '\n': + case ' ' : + case '\t': /* skip initial whitespace => skip to next */ + if ( token_started ) + { + /* possibly a name, keyword, wathever */ + tok->token.kind = tok_any; + tok->token.len = cur-tok->token.start - 1; + goto Exit; + } + /* otherwise, skip everything */ + break; + + case '%': /* this is a comment -- skip everything */ + for (;;) + { + FT_Int left = limit - cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + if ( c == '\r' || c == '\n' ) + goto Next; + left--; + } + + if ( grow( tokenizer ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '(': /* a Postscript string */ + kind = tok_string; + ender = ')'; + + L1: + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + } + + { + FT_Int nest_level = 1; + + + starter = c; + for (;;) + { + FT_Int left = limit - cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + + if ( c == starter ) + nest_level++; + + else if ( c == ender ) + { + nest_level--; + if ( nest_level <= 0 ) + { + tok->token.kind = kind; + tok->token.len = cur - tok->token.start; + goto Exit; + } + } + left--; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + } + + case '[': /* a Postscript array */ + if ( token_started ) + goto Any_Token; + + kind = tok_array; + ender = ']'; + goto L1; + break; + + case '{': /* a Postscript program */ + if ( token_started ) + goto Any_Token; + + kind = tok_program; + ender = '}'; + goto L1; + break; + + case '<': /* a Postscript hex byte array? */ + if ( token_started ) + goto Any_Token; + + kind = tok_hexarray; + ender = '>'; + goto L1; + break; + + case '0': /* any number */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if ( token_started ) + goto Next; + + tok->token.kind = tok_number; + token_started = 1; + tok->token.start = cur - 1; + + L2: + for (;;) + { + FT_Int left = limit-cur; + + + while ( left > 0 ) + { + c = (char)base[cur++]; + + switch ( c ) + { + case '[': /* ] */ + case '{': /* } */ + case '(': /* ) */ + case '<': + case '/': + goto Any_Token; + + case ' ': + case '\r': + case '\t': + case '\n': + tok->token.len = cur - tok->token.start - 1; + goto Exit; + + default: + ; + } + left--; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '.': /* maybe a number */ + case '-': + case '+': + if ( token_started ) + goto Next; + + token_started = 1; + tok->token.start = cur - 1; + + for (;;) + { + FT_Int left = limit - cur; + + + if ( left > 0 ) + { + /* test for any following digit, interpreted as number */ + c = (char)base[cur]; + tok->token.kind = ( c >= '0' && c <= '9' ? tok_number : tok_any ); + goto L2; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + + case '/': /* maybe an immediate name */ + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + + for (;;) + { + FT_Int left = limit - cur; + + + if ( left > 0 ) + { + /* test for single '/', interpreted as garbage */ + c = (char)base[cur]; + tok->token.kind = ( c == ' ' || c == '\t' || + c == '\r' || c == '\n' ) ? tok_any + : tok_immediate; + goto L2; + } + + if ( grow( tok ) ) + goto Exit; + base = tok->base; + limit = tok->limit; + } + } + else + { + Any_Token: /* possibly a name or wathever */ + cur--; + tok->token.len = cur - tok->token.start; + goto Exit; + } + + default: + if ( !token_started ) + { + token_started = 1; + tok->token.start = cur - 1; + } + } + + Next: + ; + } + + Exit: + tok->cursor = cur; + + if ( !tok->error ) + { + /* now, tries to match keywords and immediate names */ + FT_Int index; + + + switch ( tok->token.kind ) + { + case tok_immediate: /* immediate name */ + index = Find_Name( (char*)( tok->base + tok->token.start + 1 ), + tok->token.len - 1, + t1_immediates, + imm_max - imm_first_ ); + tok->token.kind2 = ( index >= 0 ) + ? (T1_TokenType)( imm_first_ + index ) + : tok_error; + break; + + case tok_any: /* test for keyword */ + index = Find_Name( (char*)( tok->base + tok->token.start ), + tok->token.len, + t1_keywords, + key_max - key_first_ ); + if ( index >= 0 ) + { + tok->token.kind = tok_keyword; + tok->token.kind2 = (T1_TokenType)( key_first_ + index ); + } + else + tok->token.kind2 = tok_error; + break; + + default: + tok->token.kind2 = tok_error; + } + } + return tokenizer->error; + } + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* Read_CharStrings */ + /* */ + /* */ + /* Reads a charstrings element from the current input stream. These */ + /* are binary bytes that encode each individual glyph outline. */ + /* */ + /* The caller is responsible for skipping the `lenIV' bytes at the */ + /* start of the record. */ + /* */ + /* */ + /* tokenizer :: The target tokenizer object. */ + /* num_chars :: The number of binary bytes to read. */ + /* */ + /* */ + /* buffer :: The target array of bytes. These are */ + /* eexec-decrypted. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Use the function Read_CharStrings() to read binary charstrings */ + /* from the private dict. */ + /* */ + LOCAL_FUNC + FT_Error Read_CharStrings( T1_Tokenizer tokenizer, + FT_Int num_chars, + FT_Byte* buffer ) + { + for (;;) + { + FT_Int left = tokenizer->limit - tokenizer->cursor; + + + if ( left >= num_chars ) + { + MEM_Copy( buffer, tokenizer->base + tokenizer->cursor, num_chars ); + t1_decrypt( buffer, num_chars, 4330 ); + tokenizer->cursor += num_chars; + return T1_Err_Ok; + } + + if ( grow( tokenizer ) ) + return tokenizer->error; + } + } + +#endif /* 0 */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/t1tokens.h b/subsys/win32k/freetype/src/type1/t1tokens.h new file mode 100644 index 0000000..c51b65c --- /dev/null +++ b/subsys/win32k/freetype/src/type1/t1tokens.h @@ -0,0 +1,258 @@ +/***************************************************************************/ +/* */ +/* t1tokens.h */ +/* */ +/* Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef T1TOKENS_H +#define T1TOKENS_H + + +#ifdef FT_FLAT_COMPILE + +#include "t1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /* enum value of first keyword */ +#define key_first_ 100 + + /* enum value of first immediate name */ +#define imm_first_ 200 + + + typedef enum T1_TokenType_ + { + tok_error = 0, + + tok_eof, /* end of file */ + + /* simple token types */ + + tok_keyword, /* keyword */ + tok_number, /* number (integer or real) */ + tok_string, /* postscript string */ + tok_program, /* postscript program */ + tok_immediate, /* any immediate name */ + tok_array, /* matrix, array, etc.. */ + tok_hexarray, /* array of hexadecimal nibbles */ + tok_any, /* anything else */ + + /* Postscript keywords -- placed in lexicographical order */ + + key_RD_alternate = key_first_, /* `-|' = alternate form of RD */ + key_ExpertEncoding, + key_ND, + key_NP, + key_RD, + key_StandardEncoding, + key_array, + key_begin, + key_closefile, + key_currentdict, + key_currentfile, + key_def, + key_dict, + key_dup, + key_eexec, + key_end, + key_execonly, + key_false, + key_for, + key_index, + key_noaccess, + key_put, + key_readonly, + key_true, + key_userdict, + key_NP_alternate, /* `|' = alternate form of NP */ + key_ND_alternate, /* `|-' = alternate form of ND */ + + key_max, /* always keep this value there */ + + /* Postscript immediate names -- other names will be ignored, except */ + /* in charstrings */ + + imm_RD_alternate = imm_first_, /* `-|' = alternate form of RD */ + imm_notdef, /* `/.notdef' immediate */ + imm_BlendAxisTypes, + imm_BlueFuzz, + imm_BlueScale, + imm_BlueShift, + imm_BlueValues, + imm_CharStrings, + imm_Encoding, + imm_FamilyBlues, + imm_FamilyName, + imm_FamilyOtherBlues, + imm_FID, + imm_FontBBox, + imm_FontID, + imm_FontInfo, + imm_FontMatrix, + imm_FontName, + imm_FontType, + imm_ForceBold, + imm_FullName, + imm_ItalicAngle, + imm_LanguageGroup, + imm_Metrics, + imm_MinFeature, + imm_ND, + imm_NP, + imm_Notice, + imm_OtherBlues, + imm_OtherSubrs, + imm_PaintType, + imm_Private, + imm_RD, + imm_RndStemUp, + imm_StdHW, + imm_StdVW, + imm_StemSnapH, + imm_StemSnapV, + imm_StrokeWidth, + imm_Subrs, + imm_UnderlinePosition, + imm_UnderlineThickness, + imm_UniqueID, + imm_Weight, + + imm_isFixedPitch, + imm_lenIV, + imm_password, + imm_version, + + imm_NP_alternate, /* `|' = alternate form of NP */ + imm_ND_alternate, /* `|-' = alternate form of ND */ + + imm_max /* always keep this value here */ + + } T1_TokenType; + + + /* these arrays are visible for debugging purposes */ + extern const char* t1_keywords[]; + extern const char* t1_immediates[]; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Token */ + /* */ + /* */ + /* A structure used to describe a token in the current input stream. */ + /* Note that the Type1 driver doesn't try to interpret tokens until */ + /* it really needs to. */ + /* */ + /* */ + /* kind :: The token type. Describes the token to the loader. */ + /* */ + /* kind2 :: Detailed token type. */ + /* */ + /* start :: The index of the first character of token in the input */ + /* stream. */ + /* */ + /* len :: The length of the token in characters. */ + /* */ + typedef struct T1_Token_ + { + T1_TokenType kind; /* simple type */ + T1_TokenType kind2; /* detailed type */ + FT_Int start; /* index of first token character */ + FT_Int len; /* length of token in chars */ + + } T1_Token; + + + typedef struct T1_TokenParser_ + { + FT_Memory memory; + FT_Stream stream; + + FT_Bool in_pfb; /* true if PFB file, PFA otherwise */ + FT_Bool in_private; /* true if in private dictionary */ + + FT_Byte* base; /* base address of current read buffer */ + FT_Long cursor; /* current position in read buffer */ + FT_Long limit; /* limit of current read buffer */ + FT_Long max; /* maximum size of read buffer */ + + FT_Error error; /* last error */ + T1_Token token; /* last token read */ + + } T1_TokenParser; + + + /*************************************************************************/ + /* */ + /* */ + /* T1_Tokenizer */ + /* */ + /* */ + /* A handle to an object used to extract tokens from the input. The */ + /* object is able to perform PFA/PFB recognition, eexec decryption of */ + /* the private dictionary, as well as eexec decryption of the */ + /* charstrings. */ + /* */ + typedef T1_TokenParser* T1_Tokenizer; + + + LOCAL_DEF + FT_Error New_Tokenizer( FT_Stream stream, + T1_Tokenizer* tokenizer ); + + LOCAL_DEF + FT_Error Done_Tokenizer( T1_Tokenizer tokenizer ); + + LOCAL_DEF + FT_Error Open_PrivateDict( T1_Tokenizer tokenizer ); + + LOCAL_DEF + FT_Error Read_Token( T1_Tokenizer tokenizer ); + + +#if 0 + LOCAL_DEF + FT_Error Read_CharStrings( T1_Tokenizer tokenizer, + FT_Int num_chars, + FT_Byte* buffer ); +#endif /* 0 */ + + LOCAL_DEF + void t1_decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + +#ifdef __cplusplus + } +#endif + +#endif /* T1TOKENS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1/type1.c b/subsys/win32k/freetype/src/type1/type1.c new file mode 100644 index 0000000..bb93732 --- /dev/null +++ b/subsys/win32k/freetype/src/type1/type1.c @@ -0,0 +1,59 @@ +/***************************************************************************/ +/* */ +/* type1.c */ +/* */ +/* FreeType Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#ifdef FT_FLAT_COMPILE + +#include "t1driver.c" +#include "t1objs.c" +#include "t1load.c" +#include "t1gload.c" +#include "t1tokens.c" +#include "t1parse.c" + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include "t1hinter.c" +#endif + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include "t1afm.c" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include +#include + +#ifndef T1_CONFIG_OPTION_DISABLE_HINTER +#include +#endif + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/.cvsignore b/subsys/win32k/freetype/src/type1z/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/type1z/Readme.txt b/subsys/win32k/freetype/src/type1z/Readme.txt new file mode 100644 index 0000000..6502fb9 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/Readme.txt @@ -0,0 +1,10 @@ +This directory contains an experimental Type 1 driver that will ultimately +replace the "official" one in "src/type1". + +This driver doesn't provide a mini Postscript interpreter, but uses +pattern matching in order to load data from fonts. It works better and +faster than the official driver, but will replace it only when we finish +the auto-hinting module.. + +You don't need to compile it to support Type 1 fonts, the driver should +co-exist peacefully with the rest of the engine however.. diff --git a/subsys/win32k/freetype/src/type1z/module.mk b/subsys/win32k/freetype/src/type1z/module.mk new file mode 100644 index 0000000..545887d --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/module.mk @@ -0,0 +1,7 @@ +make_module_list: add_type1_driver + +add_type1_driver: + $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE) + +# EOF diff --git a/subsys/win32k/freetype/src/type1z/rules.mk b/subsys/win32k/freetype/src/type1z/rules.mk new file mode 100644 index 0000000..3411fd1 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/rules.mk @@ -0,0 +1,72 @@ +# +# FreeType 2 Type1z driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# Type1z driver directory +# +T1Z_DIR := $(SRC_)type1z +T1Z_DIR_ := $(T1Z_DIR)$(SEP) + + +# compilation flags for the driver +# +T1Z_COMPILE := $(FT_COMPILE) + + +# Type1 driver sources (i.e., C files) +# +T1Z_DRV_SRC := $(T1Z_DIR_)z1parse.c \ + $(T1Z_DIR_)z1load.c \ + $(T1Z_DIR_)z1driver.c \ + $(T1Z_DIR_)z1afm.c \ + $(T1Z_DIR_)z1gload.c \ + $(T1Z_DIR_)z1objs.c + +# Type1 driver headers +# +T1Z_DRV_H := $(T1Z_DRV_SRC:%.c=%.h) \ + $(T1Z_DIR_)z1tokens.h + + +# Type1z driver object(s) +# +# T1Z_DRV_OBJ_M is used during `multi' builds +# T1Z_DRV_OBJ_S is used during `single' builds +# +T1Z_DRV_OBJ_M := $(T1Z_DRV_SRC:$(T1Z_DIR_)%.c=$(OBJ_)%.$O) +T1Z_DRV_OBJ_S := $(OBJ_)type1z.$O + +# Type1z driver source file for single build +# +T1Z_DRV_SRC_S := $(T1Z_DIR_)type1z.c + + +# Type1z driver - single object +# +$(T1Z_DRV_OBJ_S): $(T1Z_DRV_SRC_S) $(T1Z_DRV_SRC) $(FREETYPE_H) $(T1Z_DRV_H) + $(T1Z_COMPILE) $T$@ $(T1Z_DRV_SRC_S) + + +# Type1z driver - multiple objects +# +$(OBJ_)%.$O: $(T1Z_DIR_)%.c $(FREETYPE_H) $(T1Z_DRV_H) + $(T1Z_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(T1Z_DRV_OBJ_S) +DRV_OBJS_M += $(T1Z_DRV_OBJ_M) + +# EOF diff --git a/subsys/win32k/freetype/src/type1z/type1z.c b/subsys/win32k/freetype/src/type1z/type1z.c new file mode 100644 index 0000000..54726c2 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/type1z.c @@ -0,0 +1,49 @@ +/***************************************************************************/ +/* */ +/* type1z.c */ +/* */ +/* FreeType experimental Type 1 driver component (body only). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#define FT_MAKE_OPTION_SINGLE_OBJECT + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.c" +#include "z1load.c" +#include "z1objs.c" +#include "z1driver.c" +#include "z1gload.c" + +#ifndef Z1_CONFIG_OPTION_NO_AFM +#include "z1afm.c" +#endif + +#else /* FT_FLAT_COMPILE */ + +#include +#include +#include +#include +#include + +#ifndef Z1_CONFIG_OPTION_NO_AFM +#include +#endif + +#endif /* FT_FLAT_COMPILE */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1afm.c b/subsys/win32k/freetype/src/type1z/z1afm.c new file mode 100644 index 0000000..5c20120 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1afm.c @@ -0,0 +1,293 @@ +/***************************************************************************/ +/* */ +/* z1afm.c */ +/* */ +/* AFM support for Type 1 fonts (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1afm.h" + +#else + +#include + +#endif + + +#include +#include + +#include /* for qsort() */ +#include /* for strcmp() */ +#include /* for isalnum() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_z1afm + + + LOCAL_FUNC + void Z1_Done_AFM( FT_Memory memory, + Z1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + + +#undef IS_KERN_PAIR +#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' ) + +#define IS_ALPHANUM( c ) ( isalnum( c ) || \ + c == '_' || \ + c == '.' ) + + + /* read a glyph name and return the equivalent glyph index */ + static + FT_UInt afm_atoindex( FT_Byte** start, + FT_Byte* limit, + T1_Font* type1 ) + { + FT_Byte* p = *start; + FT_Int len; + FT_UInt result = 0; + char temp[64]; + + + /* skip whitespace */ + while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) && + p < limit ) + p++; + *start = p; + + /* now, read glyph name */ + while ( IS_ALPHANUM( *p ) && p < limit ) + p++; + + len = p - *start; + + if ( len > 0 && len < 64 ) + { + FT_Int n; + + + /* copy glyph name to intermediate array */ + MEM_Copy( temp, *start, len ); + temp[len] = 0; + + /* lookup glyph name in face array */ + for ( n = 0; n < type1->num_glyphs; n++ ) + { + char* gname = (char*)type1->glyph_names[n]; + + + if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 ) + { + result = n; + break; + } + } + } + *start = p; + return result; + } + + + /* read an integer */ + static + int afm_atoi( FT_Byte** start, + FT_Byte* limit ) + { + FT_Byte* p = *start; + int sum = 0; + int sign = 1; + + + /* skip everything that is not a number */ + while ( p < limit && !isdigit( *p ) ) + { + sign = 1; + if ( *p == '-' ) + sign = -1; + + p++; + } + + while ( p < limit && isdigit( *p ) ) + { + sum = sum * 10 + ( *p - '0' ); + p++; + } + *start = p; + + return sum * sign; + } + + +#undef KERN_INDEX +#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) + + + /* compare two kerning pairs */ + static + int compare_kern_pairs( const void* a, + const void* b ) + { + Z1_Kern_Pair* pair1 = (Z1_Kern_Pair*)a; + Z1_Kern_Pair* pair2 = (Z1_Kern_Pair*)b; + + FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 ); + FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 ); + + + return ( index1 - index2 ); + } + + + /* parse an AFM file -- for now, only read the kerning pairs */ + LOCAL_FUNC + FT_Error Z1_Read_AFM( FT_Face t1_face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Byte* start; + FT_Byte* limit; + FT_Byte* p; + FT_Int count = 0; + Z1_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + Z1_AFM* afm = 0; + + + if ( ACCESS_Frame( stream->size ) ) + return error; + + start = (FT_Byte*)stream->cursor; + limit = (FT_Byte*)stream->limit; + p = start; + + /* we are now going to count the occurences of `KP' or `KPX' in */ + /* the AFM file */ + count = 0; + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + count++; + } + + /* Actually, kerning pairs are simply optional! */ + if ( count == 0 ) + goto Exit; + + /* allocate the pairs */ + if ( ALLOC( afm, sizeof ( *afm ) ) || + ALLOC_ARRAY( afm->kern_pairs, count, Z1_Kern_Pair ) ) + goto Exit; + + /* now, read each kern pair */ + pair = afm->kern_pairs; + afm->num_pairs = count; + + /* save in face object */ + ((T1_Face)t1_face)->afm_data = afm; + + for ( p = start; p < limit - 3; p++ ) + { + if ( IS_KERN_PAIR( p ) ) + { + FT_Byte* q; + + + /* skip keyword (KP or KPX) */ + q = p + 2; + if ( *q == 'X' ) + q++; + + pair->glyph1 = afm_atoindex( &q, limit, type1 ); + pair->glyph2 = afm_atoindex( &q, limit, type1 ); + pair->kerning.x = afm_atoi( &q, limit ); + + pair->kerning.y = 0; + if ( p[2] != 'X' ) + pair->kerning.y = afm_atoi( &q, limit ); + + pair++; + } + } + + /* now, sort the kern pairs according to their glyph indices */ + qsort( afm->kern_pairs, count, sizeof ( Z1_Kern_Pair ), + compare_kern_pairs ); + + Exit: + if ( error ) + FREE( afm ); + + FORGET_Frame(); + + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void Z1_Get_Kerning( Z1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + Z1_Kern_Pair *min, *mid, *max; + FT_ULong index = KERN_INDEX( glyph1, glyph2 ); + + + /* simple binary search */ + min = afm->kern_pairs; + max = min + afm->num_pairs - 1; + + while ( min <= max ) + { + FT_ULong midi; + + + mid = min + ( max - min ) / 2; + midi = KERN_INDEX( mid->glyph1, mid->glyph2 ); + + if ( midi == index ) + { + *kerning = mid->kerning; + return; + } + + if ( midi < index ) + min = mid + 1; + else + max = mid - 1; + } + + kerning->x = 0; + kerning->y = 0; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1afm.h b/subsys/win32k/freetype/src/type1z/z1afm.h new file mode 100644 index 0000000..ce7be83 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1afm.h @@ -0,0 +1,79 @@ +/***************************************************************************/ +/* */ +/* z1afm.h */ +/* */ +/* AFM support for Type 1 fonts (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef Z1AFM_H +#define Z1AFM_H + + +#ifdef FT_FLAT_COMPILE + +#include "z1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + typedef struct Z1_Kern_Pair_ + { + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + + } Z1_Kern_Pair; + + + typedef struct Z1_AFM_ + { + FT_Int num_pairs; + Z1_Kern_Pair* kern_pairs; + + } Z1_AFM; + + + LOCAL_DEF + FT_Error Z1_Read_AFM( FT_Face face, + FT_Stream stream ); + + LOCAL_DEF + void Z1_Done_AFM( FT_Memory memory, + Z1_AFM* afm ); + + LOCAL_DEF + void Z1_Get_Kerning( Z1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* Z1AFM_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1driver.c b/subsys/win32k/freetype/src/type1z/z1driver.c new file mode 100644 index 0000000..401f125 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1driver.c @@ -0,0 +1,340 @@ +/***************************************************************************/ +/* */ +/* z1driver.c */ +/* */ +/* Experimental Type 1 driver interface (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1driver.h" +#include "z1gload.h" +#include "z1load.h" +#include "z1afm.h" + +#else + +#include +#include +#include +#include + +#endif + + +#include +#include +#include + +#include /* for strcmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_z1driver + + + static + FT_Error get_z1_glyph_name( T1_Face face, + FT_UInt glyph_index, + FT_Pointer buffer, + FT_UInt buffer_max ) + { + FT_String* gname; + + + gname = face->type1.glyph_names[glyph_index]; + + if ( buffer_max > 0 ) + { + FT_UInt len = strlen( gname ); + + + if (len >= buffer_max) + len = buffer_max - 1; + + MEM_Copy( buffer, gname, len ); + ((FT_Byte*)buffer)[len] = 0; + } + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Interface */ + /* */ + /* */ + /* Each driver can provide one or more extensions to the base */ + /* FreeType API. These can be used to access format specific */ + /* features (e.g., all TrueType/OpenType resources share a common */ + /* file structure and common tables which can be accessed through the */ + /* `sfnt' interface), or more simply generic ones (e.g., the */ + /* `postscript names' interface which can be used to retrieve the */ + /* PostScript name of a given glyph index). */ + /* */ + /* */ + /* driver :: A handle to a driver object. */ + /* */ + /* */ + /* interface :: A string designing the interface. Examples are */ + /* `sfnt', `post_names', `charmaps', etc. */ + /* */ + /* */ + /* A typeless pointer to the extension's interface (normally a table */ + /* of function pointers). Returns NULL if the requested extension */ + /* isn't available (i.e., wasn't compiled in the driver at build */ + /* time). */ + /* */ + static + FT_Module_Interface Get_Interface( FT_Driver driver, + const FT_String* interface ) + { + FT_UNUSED( driver ); + FT_UNUSED( interface ); + + if ( strcmp( (const char*)interface, "glyph_name" ) == 0 ) + return (FT_Module_Interface)get_z1_glyph_name; + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + if ( strcmp( (const char*)interface, "get_mm" ) == 0 ) + return (FT_Module_Interface)Z1_Get_Multi_Master; + + if ( strcmp( (const char*)interface, "set_mm_design") == 0 ) + return (FT_Module_Interface)Z1_Set_MM_Design; + + if ( strcmp( (const char*)interface, "set_mm_blend") == 0 ) + return (FT_Module_Interface)Z1_Set_MM_Blend; +#endif + return 0; + } + + +#ifndef Z1_CONFIG_OPTION_NO_AFM + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static + FT_Error Get_Kerning( T1_Face face, + FT_UInt left_glyph, + FT_UInt right_glyph, + FT_Vector* kerning ) + { + Z1_AFM* afm; + + + kerning->x = 0; + kerning->y = 0; + + afm = (Z1_AFM*)face->afm_data; + if ( afm ) + Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } + + +#endif /* T1_CONFIG_OPTION_NO_AFM */ + + + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + FT_UInt Get_Char_Index( FT_CharMap charmap, + FT_Long charcode ) + { + T1_Face face; + FT_UInt result = 0; + PSNames_Interface* psnames; + + + face = (T1_Face)charmap->face; + psnames = (PSNames_Interface*)face->psnames; + if ( psnames ) + switch ( charmap->encoding ) + { + /*******************************************************************/ + /* */ + /* Unicode encoding support */ + /* */ + case ft_encoding_unicode: + /* use the `PSNames' module to synthetize the Unicode charmap */ + result = psnames->lookup_unicode( &face->unicode_map, + (FT_ULong)charcode ); + + /* the function returns 0xFFFF if the Unicode charcode has */ + /* no corresponding glyph */ + if ( result == 0xFFFF ) + result = 0; + goto Exit; + + /*******************************************************************/ + /* */ + /* Custom Type 1 encoding */ + /* */ + case ft_encoding_adobe_custom: + { + T1_Encoding* encoding = &face->type1.encoding; + + + if ( charcode >= encoding->code_first && + charcode <= encoding->code_last ) + result = encoding->char_index[charcode]; + goto Exit; + } + + /*******************************************************************/ + /* */ + /* Adobe Standard & Expert encoding support */ + /* */ + default: + if ( charcode < 256 ) + { + FT_UInt code; + FT_Int n; + const char* glyph_name; + + + code = psnames->adobe_std_encoding[charcode]; + if ( charmap->encoding == ft_encoding_adobe_expert ) + code = psnames->adobe_expert_encoding[charcode]; + + glyph_name = psnames->adobe_std_strings( code ); + if ( !glyph_name ) + break; + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + + if ( gname && gname[0] == glyph_name[0] && + strcmp( gname, glyph_name ) == 0 ) + { + result = n; + break; + } + } + } + } + Exit: + return result; + } + + + const FT_Driver_Class t1_driver_class = + { + { + ft_module_font_driver | ft_module_driver_scalable, + sizeof( FT_DriverRec ), + + "type1", + 0x10000L, + 0x20000L, + + 0, /* format interface */ + + (FT_Module_Constructor)Z1_Init_Driver, + (FT_Module_Destructor) Z1_Done_Driver, + (FT_Module_Requester) Get_Interface, + }, + + sizeof( T1_FaceRec ), + sizeof( Z1_SizeRec ), + sizeof( Z1_GlyphSlotRec ), + + (FTDriver_initFace) Z1_Init_Face, + (FTDriver_doneFace) Z1_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) 0, + (FTDriver_setPixelSizes)0, + (FTDriver_loadGlyph) Z1_Load_Glyph, + (FTDriver_getCharIndex) Get_Char_Index, + +#ifdef Z1_CONFIG_OPTION_NO_AFM + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, +#else + (FTDriver_getKerning) Get_Kerning, + (FTDriver_attachFile) Z1_Read_AFM, +#endif + (FTDriver_getAdvances) 0 + }; + + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + + EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void ) + { + return &t1z_driver_class; + } + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1driver.h b/subsys/win32k/freetype/src/type1z/z1driver.h new file mode 100644 index 0000000..08bd544 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1driver.h @@ -0,0 +1,29 @@ +/***************************************************************************/ +/* */ +/* z1driver.h */ +/* */ +/* High-level experimental Type 1 driver interface (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef Z1DRIVER_H +#define Z1DRIVER_H + +#include + + FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class; + +#endif /* Z1DRIVER_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1gload.c b/subsys/win32k/freetype/src/type1z/z1gload.c new file mode 100644 index 0000000..455faeb --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1gload.c @@ -0,0 +1,1482 @@ +/***************************************************************************/ +/* */ +/* z1gload.c */ +/* */ +/* Experimental Type 1 Glyph Loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "z1gload.h" + +#else + +#include + +#endif + + +#include +#include +#include + +#include /* for strcmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_z1gload + + + typedef enum Z1_Operator_ + { + op_none = 0, + op_endchar, + op_hsbw, + op_seac, + op_sbw, + op_closepath, + op_hlineto, + op_hmoveto, + op_hvcurveto, + op_rlineto, + op_rmoveto, + op_rrcurveto, + op_vhcurveto, + op_vlineto, + op_vmoveto, + op_dotsection, + op_hstem, + op_hstem3, + op_vstem, + op_vstem3, + op_div, + op_callothersubr, + op_callsubr, + op_pop, + op_return, + op_setcurrentpoint, + + op_max /* never remove this one */ + + } Z1_Operator; + + static + const FT_Int t1_args_count[op_max] = + { + 0, /* none */ + 0, /* endchar */ + 2, /* hsbw */ + 5, /* seac */ + 4, /* sbw */ + 0, /* closepath */ + 1, /* hlineto */ + 1, /* hmoveto */ + 4, /* hvcurveto */ + 2, /* rlineto */ + 2, /* rmoveto */ + 6, /* rrcurveto */ + 4, /* vhcurveto */ + 1, /* vlineto */ + 1, /* vmoveto */ + 0, /* dotsection */ + 2, /* hstem */ + 6, /* hstem3 */ + 2, /* vstem */ + 6, /* vstem3 */ + 2, /* div */ + -1, /* callothersubr */ + 1, /* callsubr */ + 0, /* pop */ + 0, /* return */ + 2 /* setcurrentpoint */ + }; + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** *********/ + /********** GENERIC CHARSTRING PARSING *********/ + /********** *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Builder */ + /* */ + /* */ + /* Initializes a given glyph builder. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to initialize. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* size :: The current size object. */ + /* */ + /* glyph :: The current glyph object. */ + /* */ + LOCAL_FUNC + void Z1_Init_Builder( Z1_Builder* builder, + T1_Face face, + Z1_Size size, + Z1_GlyphSlot glyph ) + { + builder->path_begun = 0; + builder->load_points = 1; + + builder->face = face; + builder->glyph = glyph; + builder->memory = face->root.memory; + + if ( glyph ) + { + FT_GlyphLoader* loader = glyph->root.loader; + + + builder->loader = loader; + builder->current = &loader->current.outline; + builder->base = &loader->base.outline; + + FT_GlyphLoader_Rewind( loader ); + } + + if ( size ) + { + builder->scale_x = size->root.metrics.x_scale; + builder->scale_y = size->root.metrics.y_scale; + } + + builder->pos_x = 0; + builder->pos_y = 0; + + builder->left_bearing.x = 0; + builder->left_bearing.y = 0; + builder->advance.x = 0; + builder->advance.y = 0; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Builder */ + /* */ + /* */ + /* Finalizes a given glyph builder. Its contents can still be used */ + /* after the call, but the function saves important information */ + /* within the corresponding glyph slot. */ + /* */ + /* */ + /* builder :: A pointer to the glyph builder to finalize. */ + /* */ + LOCAL_FUNC + void Z1_Done_Builder( Z1_Builder* builder ) + { + Z1_GlyphSlot glyph = builder->glyph; + + + if ( glyph ) + glyph->root.outline = *builder->base; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Decoder */ + /* */ + /* */ + /* Initializes a given glyph decoder. */ + /* */ + /* */ + /* decoder :: A pointer to the glyph builder to initialize. */ + /* */ + LOCAL_FUNC + void Z1_Init_Decoder( Z1_Decoder* decoder ) + { + decoder->top = 0; + decoder->zone = 0; + decoder->flex_state = 0; + decoder->num_flex_vectors = 0; + decoder->blend = 0; + + /* Clear loader */ + MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) ); + } + + + /* check that there is enough space for `count' more points */ + static + FT_Error check_points( Z1_Builder* builder, + FT_Int count ) + { + return FT_GlyphLoader_Check_Points( builder->loader, count, 0 ); + } + + + /* add a new point; do not check space */ + static + void add_point( Z1_Builder* builder, + FT_Pos x, + FT_Pos y, + FT_Byte flag ) + { + FT_Outline* outline = builder->current; + + + if ( builder->load_points ) + { + FT_Vector* point = outline->points + outline->n_points; + FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; + + + point->x = x; + point->y = y; + *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic; + + builder->last = *point; + } + + outline->n_points++; + } + + + /* check space for a new on-curve point, then add it */ + static + FT_Error add_point1( Z1_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + FT_Error error; + + + error = check_points( builder, 1 ); + if ( !error ) + add_point( builder, x, y, 1 ); + + return error; + } + + + /* check space for a new contour, then add it */ + static + FT_Error add_contour( Z1_Builder* builder ) + { + FT_Outline* outline = builder->current; + FT_Error error; + + + if ( !builder->load_points ) + { + outline->n_contours++; + return FT_Err_Ok; + } + + /* reallocate contours array if necessary */ + error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 ); + if ( !error ) + { + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + + outline->n_contours++; + } + + return error; + } + + + /* if a path was begun, add its first on-curve point */ + static + FT_Error start_point( Z1_Builder* builder, + FT_Pos x, + FT_Pos y ) + { + /* test whether we are building a new contour */ + if ( !builder->path_begun ) + { + FT_Error error; + + + builder->path_begun = 1; + error = add_contour( builder ); + if ( error ) + return error; + } + return add_point1( builder, x, y ); + } + + + /* close the current contour */ + static + void close_contour( Z1_Builder* builder ) + { + FT_Outline* outline = builder->current; + + + /* XXX: we must not include the last point in the path if it */ + /* is located on the first point */ + if ( outline->n_points > 1 ) + { + FT_Int first = 0; + FT_Vector* p1 = outline->points + first; + FT_Vector* p2 = outline->points + outline->n_points-1; + + + if ( outline->n_contours > 1 ) + { + first = outline->contours[outline->n_contours - 2] + 1; + p1 = outline->points + first; + } + + if ( p1->x == p2->x && p1->y == p2->y ) + outline->n_points--; + } + + if ( outline->n_contours > 0 ) + outline->contours[outline->n_contours - 1] = outline->n_points - 1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* lookup_glyph_by_stdcharcode */ + /* */ + /* */ + /* Looks up a given glyph by its StandardEncoding charcode. Used */ + /* to implement the SEAC Type 1 operator. */ + /* */ + /* */ + /* face :: The current face object. */ + /* */ + /* charcode :: The character code to look for. */ + /* */ + /* */ + /* A glyph index in the font face. Returns -1 if the corresponding */ + /* glyph wasn't found. */ + /* */ + static + FT_Int lookup_glyph_by_stdcharcode( T1_Face face, + FT_Int charcode ) + { + FT_Int n; + const FT_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + + /* check range of standard char code */ + if ( charcode < 0 || charcode > 255 ) + return -1; + + glyph_name = psnames->adobe_std_strings( + psnames->adobe_std_encoding[charcode]); + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + FT_String* name = (FT_String*)face->type1.glyph_names[n]; + + + if ( name && strcmp( name,glyph_name ) == 0 ) + return n; + } + + return -1; + } + + + /*************************************************************************/ + /* */ + /* */ + /* t1operator_seac */ + /* */ + /* */ + /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ + /* */ + /* */ + /* decoder :: The current CID decoder. */ + /* */ + /* asb :: The accent's side bearing. */ + /* */ + /* adx :: The horizontal offset of the accent. */ + /* */ + /* ady :: The vertical offset of the accent. */ + /* */ + /* bchar :: The base character's StandardEncoding charcode. */ + /* */ + /* achar :: The accent character's StandardEncoding charcode. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + static + FT_Error t1operator_seac( Z1_Decoder* decoder, + FT_Pos asb, + FT_Pos adx, + FT_Pos ady, + FT_Int bchar, + FT_Int achar ) + { + FT_Error error; + FT_Int bchar_index, achar_index, n_base_points; + FT_Outline* base = decoder->builder.base; + FT_Vector left_bearing, advance; + T1_Face face = decoder->builder.face; + T1_Font* type1 = &face->type1; + + + bchar_index = lookup_glyph_by_stdcharcode( face, bchar ); + achar_index = lookup_glyph_by_stdcharcode( face, achar ); + + if ( bchar_index < 0 || achar_index < 0 ) + { + FT_ERROR(( "t1operator_seac:" )); + FT_ERROR(( " invalid seac character code arguments\n" )); + return T1_Err_Syntax_Error; + } + + /* if we are trying to load a composite glyph, do not load the */ + /* accent character and return the array of subglyphs. */ + if ( decoder->builder.no_recurse ) + { + FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; + FT_GlyphLoader* loader = glyph->loader; + FT_SubGlyph* subg; + + + /* reallocate subglyph array if necessary */ + error = FT_GlyphLoader_Check_Subglyphs( loader, 2 ); + if ( error ) + goto Exit; + + subg = loader->current.subglyphs; + + /* subglyph 0 = base character */ + subg->index = bchar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | + FT_SUBGLYPH_FLAG_USE_MY_METRICS; + subg->arg1 = 0; + subg->arg2 = 0; + subg++; + + /* subglyph 1 = accent character */ + subg->index = achar_index; + subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; + subg->arg1 = adx - asb; + subg->arg2 = ady; + + /* set up remaining glyph fields */ + glyph->num_subglyphs = 2; + glyph->subglyphs = loader->base.subglyphs; + glyph->format = ft_glyph_format_composite; + + loader->current.num_subglyphs = 2; + } + + /* First load `bchar' in builder */ + /* now load the unscaled outline */ + + FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ + + error = Z1_Parse_CharStrings( decoder, + type1->charstrings [bchar_index], + type1->charstrings_len[bchar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + goto Exit; + + n_base_points = base->n_points; + + /* save the left bearing and width of the base character */ + /* as they will be erased by the next load. */ + + left_bearing = decoder->builder.left_bearing; + advance = decoder->builder.advance; + + decoder->builder.left_bearing.x = 0; + decoder->builder.left_bearing.y = 0; + + /* Now load `achar' on top of */ + /* the base outline */ + error = Z1_Parse_CharStrings( decoder, + type1->charstrings [achar_index], + type1->charstrings_len[achar_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + if ( error ) + return error; + + /* restore the left side bearing and */ + /* advance width of the base character */ + + decoder->builder.left_bearing = left_bearing; + decoder->builder.advance = advance; + + /* Finally, move the accent */ + if ( decoder->builder.load_points ) + { + FT_Outline dummy; + + + dummy.n_points = base->n_points - n_base_points; + dummy.points = base->points + n_base_points; + FT_Outline_Translate( &dummy, adx - asb, ady ); + } + + Exit: + return error; + } + + +#define USE_ARGS( n ) do \ + { \ + top -= n; \ + if ( top < decoder->stack ) \ + goto Stack_Underflow; \ + } while ( 0 ) + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Parse_CharStrings */ + /* */ + /* */ + /* Parses a given Type 1 charstrings program. */ + /* */ + /* */ + /* decoder :: The current Type 1 decoder. */ + /* */ + /* charstring_base :: The base address of the charstring stream. */ + /* */ + /* charstring_len :: The length in bytes of the charstring stream. */ + /* */ + /* num_subrs :: The number of sub-routines. */ + /* */ + /* subrs_base :: An array of sub-routines addresses. */ + /* */ + /* subrs_len :: An array of sub-routines lengths. */ + /* */ + /* */ + /* Free error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ) + { + FT_Error error; + Z1_Decoder_Zone* zone; + FT_Byte* ip; + FT_Byte* limit; + Z1_Builder* builder = &decoder->builder; + FT_Outline* outline; + FT_Pos x, y; + + + /* First of all, initialize the decoder */ + decoder->top = decoder->stack; + decoder->zone = decoder->zones; + zone = decoder->zones; + + builder->path_begun = 0; + + zone->base = charstring_base; + limit = zone->limit = charstring_base + charstring_len; + ip = zone->cursor = zone->base; + + error = T1_Err_Ok; + outline = builder->current; + + x = builder->pos_x; + y = builder->pos_y; + + /* now, execute loop */ + while ( ip < limit ) + { + FT_Int* top = decoder->top; + Z1_Operator op = op_none; + FT_Long value = 0; + + + /*********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + /* */ + + /* first of all, decompress operator or value */ + switch ( *ip++ ) + { + case 1: + op = op_hstem; + break; + + case 3: + op = op_vstem; + break; + case 4: + op = op_vmoveto; + break; + case 5: + op = op_rlineto; + break; + case 6: + op = op_hlineto; + break; + case 7: + op = op_vlineto; + break; + case 8: + op = op_rrcurveto; + break; + case 9: + op = op_closepath; + break; + case 10: + op = op_callsubr; + break; + case 11: + op = op_return; + break; + + case 13: + op = op_hsbw; + break; + case 14: + op = op_endchar; + break; + + case 21: + op = op_rmoveto; + break; + case 22: + op = op_hmoveto; + break; + + case 30: + op = op_vhcurveto; + break; + case 31: + op = op_hvcurveto; + break; + + case 12: + if ( ip > limit ) + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+EOF)\n" )); + goto Syntax_Error; + } + + switch ( *ip++ ) + { + case 0: + op = op_dotsection; + break; + case 1: + op = op_vstem3; + break; + case 2: + op = op_hstem3; + break; + case 6: + op = op_seac; + break; + case 7: + op = op_sbw; + break; + case 12: + op = op_div; + break; + case 16: + op = op_callothersubr; + break; + case 17: + op = op_pop; + break; + case 33: + op = op_setcurrentpoint; + break; + + default: + FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + break; + + case 255: /* four bytes integer */ + if ( ip + 4 > limit ) + { + FT_ERROR(( "Z1_Parse_CharStrings: unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ( (FT_Long)ip[0] << 24 ) | + ( (FT_Long)ip[1] << 16 ) | + ( (FT_Long)ip[2] << 8 ) | + ip[3]; + ip += 4; + break; + + default: + if ( ip[-1] >= 32 ) + { + if ( ip[-1] < 247 ) + value = (FT_Long)ip[-1] - 139; + else + { + if ( ++ip > limit ) + { + FT_ERROR(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if ( ip[-2] < 251 ) + value = ( (FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108; + else + value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /*********************************************************************/ + /* */ + /* Push value on stack, or process operator */ + /* */ + /* */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "Z1_Parse_CharStrings: stack overflow!\n" )); + goto Syntax_Error; + } + + FT_TRACE4(( " %ld", value )); + + *top++ = value; + decoder->top = top; + } + else if ( op == op_callothersubr ) /* callothersubr */ + { + FT_TRACE4(( " callothersubr" )); + + if ( top - decoder->stack < 2 ) + goto Stack_Underflow; + + top -= 2; + switch ( top[1] ) + { + case 1: /* start flex feature */ + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + if ( start_point( builder, x, y ) || + check_points( builder, 6 ) ) + goto Memory_Error; + break; + + case 2: /* add flex vectors */ + { + FT_Int index; + + if ( top[0] != 0 ) + goto Unexpected_OtherSubr; + + /* note that we should not add a point for index 0; */ + /* this will move our current position to the flex */ + /* point without adding any point to the outline */ + index = decoder->num_flex_vectors++; + if ( index > 0 && index < 7 ) + add_point( builder, + x, + y, + (FT_Byte)( index == 3 || index == 6 ) ); + } + break; + + case 0: /* end flex feature */ + if ( top[0] != 3 ) + goto Unexpected_OtherSubr; + + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "Z1_Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + /* now consume the remaining `pop pop setcurpoint' */ + if ( ip + 6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */ + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + ip += 6; + decoder->flex_state = 0; + break; + + case 3: /* change hints */ + if ( top[0] != 1 ) + goto Unexpected_OtherSubr; + + /* eat the following `pop' */ + if ( ip + 2 > limit ) + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if ( ip[0] != 12 || ip[1] != 17 ) + { + FT_ERROR(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " `pop' expected, found (%d %d)\n", + ip[0], ip[1] )); + goto Syntax_Error; + } + ip += 2; + break; + + case 12: + case 13: + /* counter control hints, clear stack */ + top = decoder->stack; + break; + + case 14: + case 15: + case 16: + case 17: + case 18: /* multiple masters */ + { + T1_Blend* blend = decoder->blend; + FT_UInt num_points, nn, mm; + FT_Int* delta; + FT_Int* values; + + + if ( !blend ) + { + FT_ERROR(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected multiple masters operator!\n" )); + goto Syntax_Error; + } + + num_points = top[1] - 13 + ( top[1] == 18 ); + if ( top[0] != (FT_Int)( num_points * blend->num_designs ) ) + { + FT_ERROR(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " incorrect number of mm arguments\n" )); + goto Syntax_Error; + } + + top -= blend->num_designs*num_points; + if ( top < decoder->stack ) + goto Stack_Underflow; + + /* we want to compute: */ + /* */ + /* a0*w0 + a1*w1 + ... + ak*wk */ + /* */ + /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */ + /* however, given that w0 + w1 + ... + wk == 1, we can */ + /* rewrite it easily as: */ + /* */ + /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */ + /* */ + /* where k == num_designs-1 */ + /* */ + /* I guess that's why it's written in this `compact' */ + /* form. */ + /* */ + delta = top + num_points; + values = top; + for ( nn = 0; nn < num_points; nn++ ) + { + FT_Int x = values[0]; + + + for ( mm = 1; mm < blend->num_designs; mm++ ) + x += FT_MulFix( *delta++, blend->weight_vector[mm] ); + + *values++ = x; + } + /* note that `top' will be incremented later by calls to `pop' */ + break; + } + + default: + Unexpected_OtherSubr: + FT_ERROR(( "Z1_Parse_CharStrings: invalid othersubr [%d %d]!\n", + top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else /* general operator */ + { + FT_Int num_args = t1_args_count[op]; + + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch ( op ) + { + case op_endchar: + FT_TRACE4(( " endchar" )); + + close_contour( builder ); + + /* add current outline to the glyph slot */ + FT_GlyphLoader_Add( builder->loader ); + + /* return now! */ + FT_TRACE4(( "\n\n" )); + return T1_Err_Ok; + + case op_hsbw: + FT_TRACE4(( " hsbw" )); + + builder->left_bearing.x += top[0]; + builder->advance.x = top[1]; + builder->advance.y = 0; + + builder->last.x = x = top[0]; + builder->last.y = y = 0; + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if ( builder->metrics_only ) + return T1_Err_Ok; + + break; + + case op_seac: + /* return immediately after the processing */ + return t1operator_seac( decoder, top[0], top[1], + top[2], top[3], top[4] ); + + case op_sbw: + FT_TRACE4(( " sbw" )); + + builder->left_bearing.x += top[0]; + builder->left_bearing.y += top[1]; + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + builder->last.x = x = top[0]; + builder->last.y = y = top[1]; + + /* the `metrics_only' indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it; so exit immediately */ + if ( builder->metrics_only ) + return T1_Err_Ok; + + break; + + case op_closepath: + FT_TRACE4(( " closepath" )); + + close_contour( builder ); + builder->path_begun = 0; + break; + + case op_hlineto: + FT_TRACE4(( " hlineto" )); + + if ( start_point( builder, x, y ) ) + goto Memory_Error; + + x += top[0]; + goto Add_Line; + + case op_hmoveto: + FT_TRACE4(( " hmoveto" )); + + x += top[0]; + break; + + case op_hvcurveto: + FT_TRACE4(( " hvcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Memory_Error; + + x += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + y += top[3]; + add_point( builder, x, y, 1 ); + break; + + case op_rlineto: + FT_TRACE4(( " rlineto" )); + + if ( start_point( builder, x, y ) ) + goto Memory_Error; + + x += top[0]; + y += top[1]; + + Add_Line: + if ( add_point1( builder, x, y ) ) + goto Memory_Error; + break; + + case op_rmoveto: + FT_TRACE4(( " rmoveto" )); + + x += top[0]; + y += top[1]; + break; + + case op_rrcurveto: + FT_TRACE4(( " rcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Memory_Error; + + x += top[0]; + y += top[1]; + add_point( builder, x, y, 0 ); + + x += top[2]; + y += top[3]; + add_point( builder, x, y, 0 ); + + x += top[4]; + y += top[5]; + add_point( builder, x, y, 1 ); + break; + + case op_vhcurveto: + FT_TRACE4(( " vhcurveto" )); + + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) + goto Memory_Error; + + y += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + x += top[3]; + add_point( builder, x, y, 1 ); + break; + + case op_vlineto: + FT_TRACE4(( " vlineto" )); + + if ( start_point( builder, x, y ) ) + goto Memory_Error; + + y += top[0]; + goto Add_Line; + + case op_vmoveto: + FT_TRACE4(( " vmoveto" )); + + y += top[0]; + break; + + case op_div: + FT_TRACE4(( " div" )); + + if ( top[1] ) + { + *top = top[0] / top[1]; + ++top; + } + else + { + FT_ERROR(( "Z1_Parse_CharStrings: division by 0\n" )); + goto Syntax_Error; + } + break; + + case op_callsubr: + { + FT_Int index; + + + FT_TRACE4(( " callsubr" )); + + index = top[0]; + if ( index < 0 || index >= num_subrs ) + { + FT_ERROR(( "Z1_Parse_CharStrings: invalid subrs index\n" )); + goto Syntax_Error; + } + + if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) + { + FT_ERROR(( "Z1_Parse_CharStrings: too many nested subrs\n" )); + goto Syntax_Error; + } + + zone->cursor = ip; /* save current instruction pointer */ + + zone++; + zone->base = subrs_base[index]; + zone->limit = zone->base + subrs_len[index]; + zone->cursor = zone->base; + + if ( !zone->base ) + { + FT_ERROR(( "Z1_Parse_CharStrings: invoking empty subrs!\n" )); + goto Syntax_Error; + } + + decoder->zone = zone; + ip = zone->base; + limit = zone->limit; + break; + } + + case op_pop: + FT_TRACE4(( " pop" )); + + /* theorically, the arguments are already on the stack */ + top++; + break; + + case op_return: + FT_TRACE4(( " return" )); + + if ( zone <= decoder->zones ) + { + FT_ERROR(( "Z1_Parse_CharStrings: unexpected return\n" )); + goto Syntax_Error; + } + + zone--; + ip = zone->cursor; + limit = zone->limit; + decoder->zone = zone; + break; + + case op_dotsection: + FT_TRACE4(( " dotsection" )); + + break; + + case op_hstem: + FT_TRACE4(( " hstem" )); + + break; + + case op_hstem3: + FT_TRACE4(( " hstem3" )); + + break; + + case op_vstem: + FT_TRACE4(( " vstem" )); + + break; + + case op_vstem3: + FT_TRACE4(( " vstem3" )); + + break; + + case op_setcurrentpoint: + FT_TRACE4(( " setcurrentpoint" )); + + FT_ERROR(( "Z1_Parse_CharStrings:" )); + FT_ERROR(( " unexpected `setcurrentpoint'\n" )); + goto Syntax_Error; + + default: + FT_ERROR(( "Z1_Parse_CharStrings: unhandled opcode %d\n", op )); + goto Syntax_Error; + } + + decoder->top = top; + + } /* general operator processing */ + + } /* while ip < limit */ + + FT_TRACE4(( "..end..\n\n" )); + return error; + + Syntax_Error: + return T1_Err_Syntax_Error; + + Stack_Underflow: + return T1_Err_Stack_Underflow; + + Memory_Error: + return builder->error; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ + /********** *********/ + /********** The following code is in charge of computing *********/ + /********** the maximum advance width of the font. It *********/ + /********** quickly processes each glyph charstring to *********/ + /********** extract the value from either a `sbw' or `seac' *********/ + /********** operator. *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error Z1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ) + { + FT_Error error; + Z1_Decoder decoder; + FT_Int glyph_index; + T1_Font* type1 = &face->type1; + + + *max_advance = 0; + + /* Initialize load decoder */ + Z1_Init_Decoder( &decoder ); + Z1_Init_Builder( &decoder.builder, face, 0, 0 ); + + decoder.blend = face->blend; + decoder.builder.metrics_only = 1; + decoder.builder.load_points = 0; + + /* for each glyph, parse the glyph charstring and extract */ + /* the advance width */ + for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) + { + /* now get load the unscaled outline */ + error = Z1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + /* ignore the error if one occured - skip to next glyph */ + } + + *max_advance = decoder.builder.advance.x; + return T1_Err_Ok; + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /********** *********/ + /********** UNHINTED GLYPH LOADER *********/ + /********** *********/ + /********** The following code is in charge of loading a *********/ + /********** single outline. It completely ignores hinting *********/ + /********** and is used when FT_LOAD_NO_HINTING is set. *********/ + /********** *********/ + /********** The Type 1 hinter is located in `t1hint.c' *********/ + /********** *********/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + LOCAL_FUNC + FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, + Z1_Size size, + FT_Int glyph_index, + FT_Int load_flags ) + { + FT_Error error; + Z1_Decoder decoder; + T1_Face face = (T1_Face)glyph->root.face; + FT_Bool hinting; + T1_Font* type1 = &face->type1; + + + if ( load_flags & FT_LOAD_NO_RECURSE ) + load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; + + glyph->x_scale = size->root.metrics.x_scale; + glyph->y_scale = size->root.metrics.y_scale; + + glyph->root.outline.n_points = 0; + glyph->root.outline.n_contours = 0; + + hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 && + ( load_flags & FT_LOAD_NO_HINTING ) == 0; + + glyph->root.format = ft_glyph_format_outline; + + Z1_Init_Decoder( &decoder ); + Z1_Init_Builder( &decoder.builder, face, size, glyph ); + + decoder.blend = ((T1_Face)glyph->root.face)->blend; + decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0; + + /* now load the unscaled outline */ + error = Z1_Parse_CharStrings( &decoder, + type1->charstrings [glyph_index], + type1->charstrings_len[glyph_index], + type1->num_subrs, + type1->subrs, + type1->subrs_len ); + + /* save new glyph tables */ + Z1_Done_Builder( &decoder.builder ); + + /* now, set the metrics -- this is rather simple, as */ + /* the left side bearing is the xMin, and the top side */ + /* bearing the yMax */ + if ( !error ) + { + glyph->root.outline.flags &= ft_outline_owner; + glyph->root.outline.flags |= ft_outline_reverse_fill; + + /* for composite glyphs, return only left side bearing and */ + /* advance width */ + if ( load_flags & FT_LOAD_NO_RECURSE ) + { + glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; + glyph->root.metrics.horiAdvance = decoder.builder.advance.x; + } + else + { + FT_BBox cbox; + FT_Glyph_Metrics* metrics = &glyph->root.metrics; + + + /* copy the _unscaled_ advance width */ + metrics->horiAdvance = decoder.builder.advance.x; + + /* make up vertical metrics */ + metrics->vertBearingX = 0; + metrics->vertBearingY = 0; + metrics->vertAdvance = 0; + + glyph->root.format = ft_glyph_format_outline; + + if ( size && size->root.metrics.y_ppem < 24 ) + glyph->root.outline.flags |= ft_outline_high_precision; + +#if 0 + glyph->root.outline.second_pass = TRUE; + glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24; + glyph->root.outline.dropout_mode = 2; +#endif /* 0 */ + + if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) + { + /* scale the outline and the metrics */ + FT_Int n; + FT_Outline* cur = decoder.builder.base; + FT_Vector* vec = cur->points; + FT_Fixed x_scale = glyph->x_scale; + FT_Fixed y_scale = glyph->y_scale; + + + /* First of all, scale the points */ + for ( n = cur->n_points; n > 0; n--, vec++ ) + { + vec->x = FT_MulFix( vec->x, x_scale ); + vec->y = FT_MulFix( vec->y, y_scale ); + } + + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* Then scale the metrics */ + metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); + metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); + + metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale ); + metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale ); + } + + /* apply the font matrix */ + FT_Outline_Transform( &glyph->root.outline, + &face->type1.font_matrix ); + + /* compute the other metrics */ + FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); + + /* grid fit the bounding box if necessary */ + if ( hinting ) + { + cbox.xMin &= -64; + cbox.yMin &= -64; + cbox.xMax = ( cbox.xMax+63 ) & -64; + cbox.yMax = ( cbox.yMax+63 ) & -64; + } + + metrics->width = cbox.xMax - cbox.xMin; + metrics->height = cbox.yMax - cbox.yMin; + + metrics->horiBearingX = cbox.xMin; + metrics->horiBearingY = cbox.yMax; + } + } + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1gload.h b/subsys/win32k/freetype/src/type1z/z1gload.h new file mode 100644 index 0000000..e8abaa7 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1gload.h @@ -0,0 +1,187 @@ +/***************************************************************************/ +/* */ +/* z1gload.h */ +/* */ +/* Experimental Type 1 Glyph Loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef Z1GLOAD_H +#define Z1GLOAD_H + + +#ifdef FT_FLAT_COMPILE + +#include "z1objs.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Builder */ + /* */ + /* */ + /* A structure used during glyph loading to store its outline. */ + /* */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* face :: The current face object. */ + /* */ + /* glyph :: The current glyph slot. */ + /* */ + /* loader :: The current glyph loader. */ + /* */ + /* current :: The current glyph outline. */ + /* */ + /* base :: The base glyph outline. */ + /* */ + /* last :: The last point position. */ + /* */ + /* scale_x :: The horizontal scale (FUnits to sub-pixels). */ + /* */ + /* scale_y :: The vertical scale (FUnits to sub-pixels). */ + /* */ + /* pos_x :: The horizontal translation (for composite glyphs). */ + /* */ + /* pos_y :: The vertical translation (for composite glyphs). */ + /* */ + /* left_bearing :: The left side bearing point. */ + /* */ + /* advance :: The horizontal advance vector. */ + /* */ + /* no_recurse :: */ + /* */ + /* bbox :: The glyph's bounding box. */ + /* */ + /* path_begun :: A flag which indicates that a new path has begun. */ + /* */ + /* load_points :: A flag which indicates, if not set, that no points */ + /* are loaded. */ + /* */ + /* error :: The current error code. */ + /* */ + /* metrics_only :: A flag whether to compute metrics only. */ + /* */ + typedef struct Z1_Builder_ + { + FT_Memory memory; + T1_Face face; + Z1_GlyphSlot glyph; + FT_GlyphLoader* loader; + + FT_Outline* current; /* the current glyph outline */ + FT_Outline* base; /* the composite glyph outline */ + + FT_Vector last; + + FT_Fixed scale_x; + FT_Fixed scale_y; + + FT_Pos pos_x; + FT_Pos pos_y; + + FT_Vector left_bearing; + FT_Vector advance; + + FT_BBox bbox; /* bounding box */ + FT_Bool path_begun; + FT_Bool load_points; + FT_Bool no_recurse; + + FT_Error error; /* only used for memory errors */ + FT_Bool metrics_only; + + } Z1_Builder; + + + /* execution context charstring zone */ + typedef struct Z1_Decoder_Zone_ + { + FT_Byte* base; + FT_Byte* limit; + FT_Byte* cursor; + + } Z1_Decoder_Zone; + + + typedef struct Z1_Decoder_ + { + Z1_Builder builder; + + FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS]; + FT_Int* top; + + Z1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1]; + Z1_Decoder_Zone* zone; + + FT_Int flex_state; + FT_Int num_flex_vectors; + FT_Vector flex_vectors[7]; + + T1_Blend* blend; /* for multiple masters */ + + } Z1_Decoder; + + + LOCAL_DEF + void Z1_Init_Builder( Z1_Builder* builder, + T1_Face face, + Z1_Size size, + Z1_GlyphSlot glyph ); + + LOCAL_DEF + void Z1_Done_Builder( Z1_Builder* builder ); + + LOCAL_DEF + void Z1_Init_Decoder( Z1_Decoder* decoder ); + + LOCAL_DEF + FT_Error Z1_Compute_Max_Advance( T1_Face face, + FT_Int* max_advance ); + + LOCAL_DEF + FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder, + FT_Byte* charstring_base, + FT_Int charstring_len, + FT_Int num_subrs, + FT_Byte** subrs_base, + FT_Int* subrs_len ); + + LOCAL_DEF + FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph, + Z1_Size size, + FT_Int glyph_index, + FT_Int load_flags ); + + +#ifdef __cplusplus + } +#endif + + +#endif /* Z1GLOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1load.c b/subsys/win32k/freetype/src/type1z/z1load.c new file mode 100644 index 0000000..ca8c29d --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1load.c @@ -0,0 +1,1725 @@ +/***************************************************************************/ +/* */ +/* z1load.c */ +/* */ +/* Experimental Type 1 font loader (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* This is the new and improved Type 1 data loader for FreeType 2. The */ + /* old loader has several problems: it is slow, complex, difficult to */ + /* maintain, and contains incredible hacks to make it accept some */ + /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ + /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ + /* */ + /* This version is much simpler, much faster and also easier to read and */ + /* maintain by a great order of magnitude. The idea behind it is to */ + /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ + /* a Postscript-like interpreter) but rather to perform simple pattern */ + /* matching. */ + /* */ + /* Indeed, nearly all data definitions follow a simple pattern like */ + /* */ + /* ... /Field ... */ + /* */ + /* where can be a number, a boolean, a string, or an array of */ + /* numbers. There are a few exceptions, namely the encoding, font name, */ + /* charstrings, and subrs; they are handled with a special pattern */ + /* matching routine. */ + /* */ + /* All other common cases are handled very simply. The matching rules */ + /* are defined in the file `t1tokens.h' through the use of several */ + /* macros calls PARSE_XXX. */ + /* */ + /* This file is included twice here; the first time to generate parsing */ + /* callback functions, the second to generate a table of keywords (with */ + /* pointers to the associated callback). */ + /* */ + /* The function `parse_dict' simply scans *linearly* a given dictionary */ + /* (either the top-level or private one) and calls the appropriate */ + /* callback when it encounters an immediate keyword. */ + /* */ + /* This is by far the fastest way one can find to parse and read all */ + /* data. */ + /* */ + /* This led to tremendous code size reduction. Note that later, the */ + /* glyph loader will also be _greatly_ simplified, and the automatic */ + /* hinter will replace the clumsy `t1hinter'. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1load.h" + +#else + +#include + +#endif + + +#include /* for strncmp(), strcmp() */ +#include /* for isalnum() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_z1load + + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** MULTIPLE MASTERS SUPPORT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + static + FT_Error t1_allocate_blend( T1_Face face, + FT_UInt num_designs, + FT_UInt num_axis ) + { + T1_Blend* blend; + FT_Memory memory = face->root.memory; + FT_Error error = 0; + + + blend = face->blend; + if ( !blend ) + { + if ( ALLOC( blend, sizeof ( *blend ) ) ) + goto Exit; + + face->blend = blend; + } + + /* allocate design data if needed */ + if ( num_designs > 0 ) + { + if ( blend->num_designs == 0 ) + { + FT_UInt nn; + + + /* allocate the blend `private' and `font_info' dictionaries */ + if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) || + ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) || + ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) ) + goto Exit; + + blend->default_weight_vector = blend->weight_vector + num_designs; + + blend->font_infos[0] = &face->type1.font_info; + blend->privates [0] = &face->type1.private_dict; + + for ( nn = 2; nn <= num_designs; nn++ ) + { + blend->privates[nn] = blend->privates [nn - 1] + 1; + blend->font_infos[nn] = blend->font_infos[nn - 1] + 1; + } + + blend->num_designs = num_designs; + } + else if ( blend->num_designs != num_designs ) + goto Fail; + } + + /* allocate axis data if needed */ + if ( num_axis > 0 ) + { + if ( blend->num_axis != 0 && blend->num_axis != num_axis ) + goto Fail; + + blend->num_axis = num_axis; + } + + /* allocate the blend design pos table if needed */ + num_designs = blend->num_designs; + num_axis = blend->num_axis; + if ( num_designs && num_axis && blend->design_pos[0] == 0 ) + { + FT_UInt n; + + + if ( ALLOC_ARRAY( blend->design_pos[0], + num_designs * num_axis, FT_Fixed ) ) + goto Exit; + + for ( n = 1; n < num_designs; n++ ) + blend->design_pos[n] = blend->design_pos[0] + num_axis * n; + } + + Exit: + return error; + + Fail: + error = -1; + goto Exit; + } + + + LOCAL_FUNC + FT_Error Z1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ) + { + T1_Blend* blend = face->blend; + FT_UInt n; + FT_Error error; + + + error = T1_Err_Invalid_Argument; + + if ( blend ) + { + master->num_axis = blend->num_axis; + master->num_designs = blend->num_designs; + + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_MM_Axis* axis = master->axis + n; + T1_DesignMap* map = blend->design_map + n; + + + axis->name = blend->axis_names[n]; + axis->minimum = map->design_points[0]; + axis->maximum = map->design_points[map->num_points - 1]; + } + error = 0; + } + return error; + } + + + LOCAL_FUNC + FT_Error Z1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ) + { + T1_Blend* blend = face->blend; + FT_Error error; + FT_UInt n, m; + + + error = T1_Err_Invalid_Argument; + + if ( blend && blend->num_axis == num_coords ) + { + /* recompute the weight vector from the blend coordinates */ + error = FT_Err_Ok; + + for ( n = 0; n < blend->num_designs; n++ ) + { + FT_Fixed result = 0x10000L; /* 1.0 fixed */ + + + for ( m = 0; m < blend->num_axis; m++ ) + { + FT_Fixed factor; + + + /* get current blend axis position */ + factor = coords[m]; + if ( factor < 0 ) factor = 0; + if ( factor > 0x10000L ) factor = 0x10000L; + + if ( ( n & ( 1 << m ) ) == 0 ) + factor = 0x10000L - factor; + + result = FT_MulFix( result, factor ); + } + blend->weight_vector[n] = result; + } + + error = FT_Err_Ok; + } + return error; + } + + + LOCAL_FUNC + FT_Error Z1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ) + { + T1_Blend* blend = face->blend; + FT_Error error; + FT_UInt n, p; + + + error = T1_Err_Invalid_Argument; + if ( blend && blend->num_axis == num_coords ) + { + /* compute the blend coordinates through the blend design map */ + FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; + + + for ( n = 0; n < blend->num_axis; n++ ) + { + FT_Long design = coords[n]; + FT_Fixed the_blend; + T1_DesignMap* map = blend->design_map + n; + FT_Fixed* designs = map->design_points; + FT_Fixed* blends = map->blend_points; + FT_Int before = -1, after = -1; + + for ( p = 0; p < map->num_points; p++ ) + { + FT_Fixed p_design = designs[p]; + + + /* exact match ? */ + if ( design == p_design ) + { + the_blend = blends[p]; + goto Found; + } + + if ( design < p_design ) + { + after = p; + break; + } + + before = p; + } + + /* now, interpolate if needed */ + if ( before < 0 ) + the_blend = blends[0]; + + else if ( after < 0 ) + the_blend = blends[map->num_points - 1]; + + else + the_blend = FT_MulDiv( design - designs[before], + blends [after] - blends [before], + designs[after] - designs[before] ); + + Found: + final_blends[n] = the_blend; + } + + error = Z1_Set_MM_Blend( face, num_coords, final_blends ); + } + + return error; + } + + + LOCAL_FUNC + void Z1_Done_Blend( T1_Face face ) + { + FT_Memory memory = face->root.memory; + T1_Blend* blend = face->blend; + + + if ( blend ) + { + FT_UInt num_designs = blend->num_designs; + FT_UInt num_axis = blend->num_axis; + FT_UInt n; + + + /* release design pos table */ + FREE( blend->design_pos[0] ); + for ( n = 1; n < num_designs; n++ ) + blend->design_pos[n] = 0; + + /* release blend `private' and `font info' dictionaries */ + FREE( blend->privates[1] ); + FREE( blend->font_infos[1] ); + + for ( n = 0; n < num_designs; n++ ) + { + blend->privates [n] = 0; + blend->font_infos[n] = 0; + } + + /* release weight vectors */ + FREE( blend->weight_vector ); + blend->default_weight_vector = 0; + + /* release axis names */ + for ( n = 0; n < num_axis; n++ ) + FREE( blend->axis_names[n] ); + + /* release design map */ + for ( n = 0; n < num_axis; n++ ) + { + T1_DesignMap* dmap = blend->design_map + n; + + + FREE( dmap->design_points ); + dmap->num_points = 0; + } + + FREE( face->blend ); + } + } + + + static + void parse_blend_axis_types( T1_Face face, + Z1_Loader* loader ) + { + Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; + FT_Int n, num_axis; + FT_Error error = 0; + T1_Blend* blend; + FT_Memory memory; + + + /* take an array of objects */ + Z1_ToTokenArray( &loader->parser, axis_tokens, + T1_MAX_MM_AXIS, &num_axis ); + if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS ) + { + FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", + num_axis )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* allocate blend if necessary */ + error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); + if ( error ) + goto Exit; + + blend = face->blend; + memory = face->root.memory; + + /* each token is an immediate containing the name of the axis */ + for ( n = 0; n < num_axis; n++ ) + { + Z1_Token_Rec* token = axis_tokens + n; + FT_Byte* name; + FT_Int len; + + /* skip first slash, if any */ + if (token->start[0] == '/') + token->start++; + + len = token->limit - token->start; + if ( len <= 0 ) + { + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + if ( ALLOC( blend->axis_names[n], len + 1 ) ) + goto Exit; + + name = (FT_Byte*)blend->axis_names[n]; + MEM_Copy( name, token->start, len ); + name[len] = 0; + } + + Exit: + loader->parser.error = error; + } + + + static + void parse_blend_design_positions( T1_Face face, + Z1_Loader* loader ) + { + Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ]; + FT_Int num_designs; + FT_Int num_axis; + Z1_Parser* parser = &loader->parser; + + FT_Error error = 0; + T1_Blend* blend; + + + /* get the array of design tokens - compute number of designs */ + Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs ); + if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS ) + { + FT_ERROR(( "parse_blend_design_positions:" )); + FT_ERROR(( " incorrect number of designs: %d\n", + num_designs )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + FT_UInt n; + + + blend = face->blend; + num_axis = 0; /* make compiler happy */ + + for ( n = 0; n < (FT_UInt)num_designs; n++ ) + { + Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ]; + Z1_Token_Rec* token; + FT_Int axis, n_axis; + + + /* read axis/coordinates tokens */ + token = design_tokens + n; + parser->cursor = token->start - 1; + parser->limit = token->limit + 1; + Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis ); + + if ( n == 0 ) + { + num_axis = n_axis; + error = t1_allocate_blend( face, num_designs, num_axis ); + if ( error ) + goto Exit; + blend = face->blend; + } + else if ( n_axis != num_axis ) + { + FT_ERROR(( "parse_blend_design_positions: incorrect table\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* now, read each axis token into the design position */ + for ( axis = 0; axis < n_axis; axis++ ) + { + Z1_Token_Rec* token2 = axis_tokens + axis; + + + parser->cursor = token2->start; + parser->limit = token2->limit; + blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 ); + } + } + + loader->parser.cursor = old_cursor; + loader->parser.limit = old_limit; + } + + Exit: + loader->parser.error = error; + } + + + static + void parse_blend_design_map( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend; + Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ]; + FT_Int n, num_axis; + FT_Byte* old_cursor; + FT_Byte* old_limit; + FT_Memory memory = face->root.memory; + + + Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis ); + if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS ) + { + FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", + num_axis )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + old_cursor = parser->cursor; + old_limit = parser->limit; + + error = t1_allocate_blend( face, 0, num_axis ); + if ( error ) + goto Exit; + blend = face->blend; + + /* now, read each axis design map */ + for ( n = 0; n < num_axis; n++ ) + { + T1_DesignMap* map = blend->design_map + n; + Z1_Token_Rec* token; + FT_Int p, num_points; + + + token = axis_tokens + n; + parser->cursor = token->start; + parser->limit = token->limit; + + /* count the number of map points */ + { + FT_Byte* p = token->start; + FT_Byte* limit = token->limit; + + + num_points = 0; + for ( ; p < limit; p++ ) + if ( p[0] == '[' ) + num_points++; + } + if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) + { + FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + /* allocate design map data */ + if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) ) + goto Exit; + map->blend_points = map->design_points + num_points; + map->num_points = (FT_Byte)num_points; + + for ( p = 0; p < num_points; p++ ) + { + map->design_points[p] = Z1_ToInt( parser ); + map->blend_points [p] = Z1_ToFixed( parser, 0 ); + } + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->error = error; + } + + + static + void parse_weight_vector( T1_Face face, + Z1_Loader* loader ) + { + FT_Error error = 0; + Z1_Parser* parser = &loader->parser; + T1_Blend* blend = face->blend; + Z1_Token_Rec master; + FT_UInt n; + FT_Byte* old_cursor; + FT_Byte* old_limit; + + + if ( !blend || blend->num_designs == 0 ) + { + FT_ERROR(( "parse_weight_vector: too early!\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + Z1_ToToken( parser, &master ); + if ( master.type != t1_token_array ) + { + FT_ERROR(( "parse_weight_vector: incorrect format!\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + old_cursor = parser->cursor; + old_limit = parser->limit; + + parser->cursor = master.start; + parser->limit = master.limit; + + for ( n = 0; n < blend->num_designs; n++ ) + { + blend->default_weight_vector[n] = + blend->weight_vector[n] = Z1_ToFixed( parser, 0 ); + } + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + parser->error = error; + } + + + /* the keyword `/shareddict' appears in some multiple master fonts */ + /* with a lot of Postscript garbage behind it (that's completely out */ + /* of spec!); we detect it and terminate the parsing */ + /* */ + static + void parse_shared_dict( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + FT_UNUSED( face ); + + + parser->cursor = parser->limit; + parser->error = 0; + } + +#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** TYPE 1 SYMBOL PARSING *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* First of all, define the token field static variables. This is a set */ + /* of Z1_Field_Rec variables used later. */ + /* */ + /*************************************************************************/ + +#define Z1_NEW_STRING( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_STRING( T1TYPE, _field ); + +#define Z1_NEW_BOOL( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_BOOL( T1TYPE, _field ); + +#define Z1_NEW_NUM( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM( T1TYPE, _field ); + +#define Z1_NEW_FIXED( _name, _field ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED( T1TYPE, _field, _power ); + +#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max ); + +#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max ); + +#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \ + static \ + const Z1_Field_Rec t1_field_ ## _field = \ + Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max ); + + +#define Z1_FONTINFO_STRING( n, f ) Z1_NEW_STRING( n, f ) +#define Z1_FONTINFO_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_FONTINFO_BOOL( n, f ) Z1_NEW_BOOL( n, f ) +#define Z1_PRIVATE_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_PRIVATE_FIXED( n, f ) Z1_NEW_FIXED( n, f ) +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_NEW_NUM_TABLE( n, f, m, c ) +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_NEW_NUM_TABLE2( n, f, m ) +#define Z1_TOPDICT_NUM( n, f ) Z1_NEW_NUM( n, f ) +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_NEW_FIXED_TABLE2( n, f, m ) + + + /* including this file defines all field variables */ +#ifdef FT_FLAT_COMPILE + +#include "z1tokens.h" + +#else + +#include + +#endif + + + /*************************************************************************/ + /* */ + /* Second, define the keyword variables. This is a set of Z1_KeyWord */ + /* structures used to model the way each keyword is `loaded'. */ + /* */ + /*************************************************************************/ + + typedef void (*Z1_Parse_Func)( T1_Face face, + Z1_Loader* loader ); + + + typedef enum Z1_KeyWord_Type_ + { + t1_keyword_callback = 0, + t1_keyword_field, + t1_keyword_field_table + + } Z1_KeyWord_Type; + + + typedef enum Z1_KeyWord_Location_ + { + t1_keyword_type1 = 0, + t1_keyword_font_info, + t1_keyword_private + + } Z1_KeyWord_Location; + + + typedef struct Z1_KeyWord_ + { + const char* name; + Z1_KeyWord_Type type; + Z1_KeyWord_Location location; + Z1_Parse_Func parsing; + const Z1_Field_Rec* field; + + } Z1_KeyWord; + + +#define Z1_KEYWORD_CALLBACK( name, callback ) \ + { \ + name, t1_keyword_callback, t1_keyword_type1, callback, 0 \ + } + +#define Z1_KEYWORD_TYPE1( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_PRIVATE( name, f ) \ + { \ + name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \ + } + +#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_font_info, 0, \ + &t1_field_ ## f \ + } + +#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \ + { \ + name, t1_keyword_field_table, t1_keyword_private, 0, \ + &t1_field_ ## f \ + } + + +#undef Z1_FONTINFO_STRING +#undef Z1_FONTINFO_NUM +#undef Z1_FONTINFO_BOOL +#undef Z1_PRIVATE_NUM +#undef Z1_PRIVATE_FIXED +#undef Z1_PRIVATE_NUM_TABLE +#undef Z1_PRIVATE_NUM_TABLE2 +#undef Z1_TOPDICT_NUM +#undef Z1_TOPDICT_NUM_FIXED2 + +#define Z1_FONTINFO_STRING( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_NUM( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_FONTINFO_BOOL( n, f ) Z1_KEYWORD_FONTINFO( n, f ), +#define Z1_PRIVATE_NUM( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_FIXED( n, f ) Z1_KEYWORD_PRIVATE( n, f ), +#define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_KEYWORD_PRIVATE_TABLE( n, f ), +#define Z1_TOPDICT_NUM( n, f ) Z1_KEYWORD_TYPE1( n, f ), +#define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_KEYWORD_TYPE1( n, f ), + + + static + FT_Error t1_load_keyword( T1_Face face, + Z1_Loader* loader, + Z1_KeyWord* keyword ) + { + FT_Error error; + void* dummy_object; + void** objects; + FT_UInt max_objects; + T1_Blend* blend = face->blend; + + + /* if the keyword has a dedicated callback, call it */ + if ( keyword->type == t1_keyword_callback ) + { + keyword->parsing( face, loader ); + error = loader->parser.error; + goto Exit; + } + + /* now, the keyword is either a simple field, or a table of fields; */ + /* we are now going to take care of it */ + switch ( keyword->location ) + { + case t1_keyword_font_info: + dummy_object = &face->type1.font_info; + objects = &dummy_object; + max_objects = 0; + + if ( blend ) + { + objects = (void**)blend->font_infos; + max_objects = blend->num_designs; + } + break; + + case t1_keyword_private: + dummy_object = &face->type1.private_dict; + objects = &dummy_object; + max_objects = 0; + + if ( blend ) + { + objects = (void**)blend->privates; + max_objects = blend->num_designs; + } + break; + + default: + dummy_object = &face->type1; + objects = &dummy_object; + max_objects = 0; + } + + if ( keyword->type == t1_keyword_field_table ) + error = Z1_Load_Field_Table( &loader->parser, keyword->field, + objects, max_objects, 0 ); + else + error = Z1_Load_Field( &loader->parser, keyword->field, + objects, max_objects, 0 ); + + Exit: + return error; + } + + + static + int is_space( char c ) + { + return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); + } + + + static + int is_alpha( char c ) + { + return ( isalnum( c ) || + ( c == '.' ) || + ( c == '_' ) ); + } + + + static + void skip_whitespace( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + + while ( cur < parser->limit && is_space( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + void skip_blackspace( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + + while ( cur < parser->limit && !is_space( *cur ) ) + cur++; + + parser->cursor = cur; + } + + + static + int read_binary_data( Z1_Parser* parser, + FT_Int* size, + FT_Byte** base ) + { + FT_Byte* cur; + FT_Byte* limit = parser->limit; + + + /* the binary data has the following format */ + /* */ + /* `size' [white*] RD white ....... ND */ + /* */ + + skip_whitespace( parser ); + cur = parser->cursor; + + if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 ) + { + *size = Z1_ToInt( parser ); + + skip_whitespace( parser ); + skip_blackspace( parser ); /* `RD' or `-|' or something else */ + + /* there is only one whitespace char after the */ + /* `RD' or `-|' token */ + *base = parser->cursor + 1; + + parser->cursor += *size+1; + return 1; + } + + FT_ERROR(( "read_binary_data: invalid size field\n" )); + parser->error = T1_Err_Invalid_File_Format; + return 0; + } + + + /* we will now define the routines used to handle */ + /* the `/Encoding', `/Subrs', and `/CharStrings' */ + /* dictionaries */ + + static + void parse_font_name( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Error error; + FT_Memory memory = parser->memory; + FT_Int len; + FT_Byte* cur; + FT_Byte* cur2; + FT_Byte* limit; + + + skip_whitespace( parser ); + + cur = parser->cursor; + limit = parser->limit; + + if ( cur >= limit - 1 || *cur != '/' ) + return; + + cur++; + cur2 = cur; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur; + if ( len > 0 ) + { + if ( ALLOC( face->type1.font_name, len + 1 ) ) + { + parser->error = error; + return; + } + + MEM_Copy( face->type1.font_name, cur, len ); + face->type1.font_name[len] = '\0'; + } + parser->cursor = cur2; + } + + + static + void parse_font_bbox( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Short temp[4]; + FT_BBox* bbox = &face->type1.font_bbox; + + + (void)Z1_ToCoordArray( parser, 4, temp ); + bbox->xMin = temp[0]; + bbox->yMin = temp[1]; + bbox->xMax = temp[2]; + bbox->yMax = temp[3]; + } + + + static + void parse_font_matrix( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Matrix* matrix = &face->type1.font_matrix; + FT_Fixed temp[4]; + + + (void)Z1_ToFixedArray( parser, 4, temp, 3 ); + matrix->xx = temp[0]; + matrix->yx = temp[1]; + matrix->xy = temp[2]; + matrix->yy = temp[3]; + } + + + static + void parse_encoding( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + /* skip whitespace */ + while ( is_space( *cur ) ) + { + cur++; + if ( cur >= limit ) + { + FT_ERROR(( "parse_encoding: out of bounds!\n" )); + parser->error = T1_Err_Invalid_File_Format; + return; + } + } + + /* if we have a number, then the encoding is an array, */ + /* and we must load it now */ + if ( (FT_Byte)( *cur - '0' ) < 10 ) + { + T1_Encoding* encode = &face->type1.encoding; + FT_Int count, n; + Z1_Table* char_table = &loader->encoding_table; + FT_Memory memory = parser->memory; + FT_Error error; + + + /* read the number of entries in the encoding, should be 256 */ + count = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* we use a Z1_Table to store our charnames */ + encode->num_chars = count; + if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) || + ALLOC_ARRAY( encode->char_name, count, FT_String* ) || + ( error = Z1_New_Table( char_table, count, memory ) ) != 0 ) + { + parser->error = error; + return; + } + + /* Now, we will need to read a record of the form */ + /* ... charcode /charname ... for each entry in our table */ + /* */ + /* We simply look for a number followed by an immediate */ + /* name. Note that this ignores correctly the sequence */ + /* that is often seen in type1 fonts: */ + /* */ + /* 0 1 255 { 1 index exch /.notdef put } for dup */ + /* */ + /* used to clean the encoding array before anything else. */ + /* */ + /* We stop when we encounter a `def'. */ + + cur = parser->cursor; + limit = parser->limit; + n = 0; + + for ( ; cur < limit; ) + { + FT_Byte c; + + + c = *cur; + + /* we stop when we encounter a `def' */ + if ( c == 'd' && cur + 3 < limit ) + { + if ( cur[1] == 'e' && + cur[2] == 'f' && + is_space(cur[-1]) && + is_space(cur[3]) ) + { + FT_TRACE6(( "encoding end\n" )); + break; + } + } + + /* otherwise, we must find a number before anything else */ + if ( (FT_Byte)( c - '0' ) < 10 ) + { + FT_Int charcode; + + + parser->cursor = cur; + charcode = Z1_ToInt( parser ); + cur = parser->cursor; + + /* skip whitespace */ + while ( cur < limit && is_space( *cur ) ) + cur++; + + if ( cur < limit && *cur == '/' ) + { + /* bingo, we have an immediate name -- it must be a */ + /* character name */ + FT_Byte* cur2 = cur + 1; + FT_Int len; + + + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur - 1; + + parser->error = Z1_Add_Table( char_table, charcode, + cur + 1, len + 1 ); + char_table->elements[charcode][len] = '\0'; + if ( parser->error ) + return; + + cur = cur2; + } + } + else + cur++; + } + + face->type1.encoding_type = t1_encoding_array; + parser->cursor = cur; + } + /* Otherwise, we should have either `StandardEncoding' or */ + /* `ExpertEncoding' */ + else + { + if ( cur + 17 < limit && + strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) + face->type1.encoding_type = t1_encoding_standard; + + else if ( cur + 15 < limit && + strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) + face->type1.encoding_type = t1_encoding_expert; + + else + { + FT_ERROR(( "parse_encoding: invalid token!\n" )); + parser->error = T1_Err_Invalid_File_Format; + } + } + } + + + static + void parse_subrs( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + Z1_Table* table = &loader->subrs; + FT_Memory memory = parser->memory; + FT_Error error; + FT_Int n; + + + loader->num_subrs = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* position the parser right before the `dup' of the first subr */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `array' */ + skip_whitespace( parser ); + + /* initialize subrs array */ + error = Z1_New_Table( table, loader->num_subrs, memory ); + if ( error ) + goto Fail; + + /* the format is simple: */ + /* */ + /* `index' + binary data */ + /* */ + + for ( n = 0; n < loader->num_subrs; n++ ) + { + FT_Int index, size; + FT_Byte* base; + + + /* If the next token isn't `dup', we are also done. This */ + /* happens when there are `holes' in the Subrs array. */ + if ( strncmp( (char*)parser->cursor, "dup", 3 ) != 0 ) + break; + + index = Z1_ToInt( parser ); + + if ( !read_binary_data( parser, &size, &base ) ) + return; + + /* The binary string is followed by one token, e.g. `NP' */ + /* (bound to `noaccess put') or by two separate tokens: */ + /* `noaccess' & `put'. We position the parser right */ + /* before the next `dup', if any. */ + skip_whitespace( parser ); + skip_blackspace( parser ); /* `NP' or `I' or `noaccess' */ + skip_whitespace( parser ); + + if ( strncmp( (char*)parser->cursor, "put", 3 ) == 0 ) + { + skip_blackspace( parser ); /* skip `put' */ + skip_whitespace( parser ); + } + + /* some fonts use a value of -1 for lenIV to indicate that */ + /* the charstrings are unencoded */ + /* */ + /* thanks to Tom Kacvinsky for pointing this out */ + /* */ + if ( face->type1.private_dict.lenIV >= 0 ) + { + Z1_Decrypt( base, size, 4330 ); + size -= face->type1.private_dict.lenIV; + base += face->type1.private_dict.lenIV; + } + + error = Z1_Add_Table( table, index, base, size ); + if ( error ) + goto Fail; + } + return; + + Fail: + parser->error = error; + } + + + static + void parse_charstrings( T1_Face face, + Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + Z1_Table* code_table = &loader->charstrings; + Z1_Table* name_table = &loader->glyph_names; + FT_Memory memory = parser->memory; + FT_Error error; + + FT_Byte* cur; + FT_Byte* limit = parser->limit; + FT_Int n; + + + loader->num_glyphs = Z1_ToInt( parser ); + if ( parser->error ) + return; + + /* initialize tables */ + error = Z1_New_Table( code_table, loader->num_glyphs, memory ) || + Z1_New_Table( name_table, loader->num_glyphs, memory ); + if ( error ) + goto Fail; + + n = 0; + for (;;) + { + FT_Int size; + FT_Byte* base; + + + /* the format is simple: */ + /* `/glyphname' + binary data */ + /* */ + /* note that we stop when we find a `def' */ + /* */ + skip_whitespace( parser ); + + cur = parser->cursor; + if ( cur >= limit ) + break; + + /* we stop when we find a `def' or `end' keyword */ + if ( *cur == 'd' && + cur + 3 < limit && + cur[1] == 'e' && + cur[2] == 'f' ) + break; + + if ( *cur == 'e' && + cur + 3 < limit && + cur[1] == 'n' && + cur[2] == 'd' ) + break; + + if ( *cur != '/' ) + skip_blackspace( parser ); + else + { + FT_Byte* cur2 = cur + 1; + FT_Int len; + + + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + len = cur2 - cur - 1; + + error = Z1_Add_Table( name_table, n, cur + 1, len + 1 ); + if ( error ) + goto Fail; + + /* add a trailing zero to the name table */ + name_table->elements[n][len] = '\0'; + + parser->cursor = cur2; + if ( !read_binary_data( parser, &size, &base ) ) + return; + + if ( face->type1.private_dict.lenIV >= 0 ) + { + Z1_Decrypt( base, size, 4330 ); + size -= face->type1.private_dict.lenIV; + base += face->type1.private_dict.lenIV; + } + + error = Z1_Add_Table( code_table, n, base, size ); + if ( error ) + goto Fail; + + n++; + if ( n >= loader->num_glyphs ) + break; + } + } + loader->num_glyphs = n; + return; + + Fail: + parser->error = error; + } + + + static + const Z1_KeyWord t1_keywords[] = + { + +#ifdef FT_FLAT_COMPILE + +#include "z1tokens.h" + +#else + +#include + +#endif + + /* now add the special functions... */ + Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ), + Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ), + Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ), + Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ), + Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ), + Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ), + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ), + Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ), + Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ), + Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ), + Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ), +#endif + + Z1_KEYWORD_CALLBACK( 0, 0 ) + }; + + + static + FT_Error parse_dict( T1_Face face, + Z1_Loader* loader, + FT_Byte* base, + FT_Long size ) + { + Z1_Parser* parser = &loader->parser; + + + parser->cursor = base; + parser->limit = base + size; + parser->error = 0; + + { + FT_Byte* cur = base; + FT_Byte* limit = cur + size; + + + for ( ; cur < limit; cur++ ) + { + /* look for `FontDirectory', which causes problems on some fonts */ + if ( *cur == 'F' && cur + 25 < limit && + strncmp( (char*)cur, "FontDirectory", 13 ) == 0 ) + { + FT_Byte* cur2; + + + /* skip the `FontDirectory' keyword */ + cur += 13; + cur2 = cur; + + /* lookup the `known' keyword */ + while ( cur < limit && *cur != 'k' && + strncmp( (char*)cur, "known", 5 ) ) + cur++; + + if ( cur < limit ) + { + Z1_Token_Rec token; + + + /* skip the `known' keyword and the token following it */ + cur += 5; + loader->parser.cursor = cur; + Z1_ToToken( &loader->parser, &token ); + + /* if the last token was an array, skip it! */ + if ( token.type == t1_token_array ) + cur2 = parser->cursor; + } + cur = cur2; + } + /* look for immediates */ + else if ( *cur == '/' && cur + 2 < limit ) + { + FT_Byte* cur2; + FT_Int len; + + + cur++; + cur2 = cur; + while ( cur2 < limit && is_alpha( *cur2 ) ) + cur2++; + + len = cur2 - cur; + if ( len > 0 && len < 22 ) + { + if ( !loader->fontdata ) + { + if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 ) + loader->fontdata = 1; + } + else + { + /* now, compare the immediate name to the keyword table */ + Z1_KeyWord* keyword = (Z1_KeyWord*)t1_keywords; + + + for (;;) + { + FT_Byte* name; + + + name = (FT_Byte*)keyword->name; + if ( !name ) + break; + + if ( cur[0] == name[0] && + len == (FT_Int)strlen( (const char*)name ) ) + { + FT_Int n; + + + for ( n = 1; n < len; n++ ) + if ( cur[n] != name[n] ) + break; + + if ( n >= len ) + { + /* we found it -- run the parsing callback! */ + parser->cursor = cur2; + skip_whitespace( parser ); + parser->error = t1_load_keyword( face, loader, keyword ); + if ( parser->error ) + return parser->error; + + cur = parser->cursor; + break; + } + } + keyword++; + } + } + } + } + } + } + return parser->error; + } + + + static + void t1_init_loader( Z1_Loader* loader, + T1_Face face ) + { + FT_UNUSED( face ); + + MEM_Set( loader, 0, sizeof ( *loader ) ); + loader->num_glyphs = 0; + loader->num_chars = 0; + + /* initialize the tables -- simply set their `init' field to 0 */ + loader->encoding_table.init = 0; + loader->charstrings.init = 0; + loader->glyph_names.init = 0; + loader->subrs.init = 0; + loader->fontdata = 0; + } + + + static + void t1_done_loader( Z1_Loader* loader ) + { + Z1_Parser* parser = &loader->parser; + + + /* finalize tables */ + Z1_Release_Table( &loader->encoding_table ); + Z1_Release_Table( &loader->charstrings ); + Z1_Release_Table( &loader->glyph_names ); + Z1_Release_Table( &loader->subrs ); + + /* finalize parser */ + Z1_Done_Parser( parser ); + } + + + LOCAL_FUNC + FT_Error Z1_Open_Face( T1_Face face ) + { + Z1_Loader loader; + Z1_Parser* parser; + T1_Font* type1 = &face->type1; + FT_Error error; + + + t1_init_loader( &loader, face ); + + /* default lenIV */ + type1->private_dict.lenIV = 4; + + parser = &loader.parser; + error = Z1_New_Parser( parser, face->root.stream, face->root.memory ); + if ( error ) + goto Exit; + + error = parse_dict( face, &loader, parser->base_dict, parser->base_len ); + if ( error ) + goto Exit; + + error = Z1_Get_Private_Dict( parser ); + if ( error ) + goto Exit; + + error = parse_dict( face, &loader, parser->private_dict, + parser->private_len ); + if ( error ) + goto Exit; + + /* now, propagate the subrs, charstrings, and glyphnames tables */ + /* to the Type1 data */ + type1->num_glyphs = loader.num_glyphs; + + if ( !loader.subrs.init ) + { + FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + if ( !loader.charstrings.init ) + { + FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" )); + error = T1_Err_Invalid_File_Format; + } + + loader.subrs.init = 0; + type1->num_subrs = loader.num_subrs; + type1->subrs_block = loader.subrs.block; + type1->subrs = loader.subrs.elements; + type1->subrs_len = loader.subrs.lengths; + + loader.charstrings.init = 0; + type1->charstrings_block = loader.charstrings.block; + type1->charstrings = loader.charstrings.elements; + type1->charstrings_len = loader.charstrings.lengths; + + /* we copy the glyph names `block' and `elements' fields; */ + /* the `lengths' field must be released later */ + type1->glyph_names_block = loader.glyph_names.block; + type1->glyph_names = (FT_String**)loader.glyph_names.elements; + loader.glyph_names.block = 0; + loader.glyph_names.elements = 0; + + /* we must now build type1.encoding when we have a custom */ + /* array.. */ + if ( type1->encoding_type == t1_encoding_array ) + { + FT_Int charcode, index, min_char, max_char; + FT_Byte* char_name; + FT_Byte* glyph_name; + + + /* OK, we do the following: for each element in the encoding */ + /* table, look up the index of the glyph having the same name */ + /* the index is then stored in type1.encoding.char_index, and */ + /* a the name to type1.encoding.char_name */ + + min_char = +32000; + max_char = -32000; + + charcode = 0; + for ( ; charcode < loader.encoding_table.num_elems; charcode++ ) + { + type1->encoding.char_index[charcode] = 0; + type1->encoding.char_name [charcode] = ".notdef"; + + char_name = loader.encoding_table.elements[charcode]; + if ( char_name ) + for ( index = 0; index < type1->num_glyphs; index++ ) + { + glyph_name = (FT_Byte*)type1->glyph_names[index]; + if ( strcmp( (const char*)char_name, + (const char*)glyph_name ) == 0 ) + { + type1->encoding.char_index[charcode] = index; + type1->encoding.char_name [charcode] = (char*)glyph_name; + + if (charcode < min_char) min_char = charcode; + if (charcode > max_char) max_char = charcode; + break; + } + } + } + type1->encoding.code_first = min_char; + type1->encoding.code_last = max_char; + type1->encoding.num_chars = loader.num_chars; + } + + Exit: + t1_done_loader( &loader ); + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1load.h b/subsys/win32k/freetype/src/type1z/z1load.h new file mode 100644 index 0000000..ca4ba98 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1load.h @@ -0,0 +1,93 @@ +/***************************************************************************/ +/* */ +/* z1load.h */ +/* */ +/* Experimental Type 1 font loader (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef Z1LOAD_H +#define Z1LOAD_H + +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.h" + +#else + +#include + +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + + typedef struct Z1_Loader_ + { + Z1_Parser parser; /* parser used to read the stream */ + + FT_Int num_chars; /* number of characters in encoding */ + Z1_Table encoding_table; /* Z1_Table used to store the */ + /* encoding character names */ + + FT_Int num_glyphs; + Z1_Table glyph_names; + Z1_Table charstrings; + + FT_Int num_subrs; + Z1_Table subrs; + FT_Bool fontdata; + + } Z1_Loader; + + + LOCAL_DEF + FT_Error Z1_Open_Face( T1_Face face ); + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + + LOCAL_DEF + FT_Error Z1_Get_Multi_Master( T1_Face face, + FT_Multi_Master* master ); + + LOCAL_DEF + FT_Error Z1_Set_MM_Blend( T1_Face face, + FT_UInt num_coords, + FT_Fixed* coords ); + + LOCAL_DEF + FT_Error Z1_Set_MM_Design( T1_Face face, + FT_UInt num_coords, + FT_Long* coords ); + + LOCAL_DEF + void Z1_Done_Blend( T1_Face face ); + +#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */ + + +#ifdef __cplusplus + } +#endif + +#endif /* Z1LOAD_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1objs.c b/subsys/win32k/freetype/src/type1z/z1objs.c new file mode 100644 index 0000000..97193e3 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1objs.c @@ -0,0 +1,398 @@ +/***************************************************************************/ +/* */ +/* z1objs.c */ +/* */ +/* Experimental Type 1 objects manager (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1gload.h" +#include "z1load.h" +#include "z1afm.h" + +#else + +#include +#include +#include + +#endif + + +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_z1objs + + + /*************************************************************************/ + /* */ + /* FACE FUNCTIONS */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Face */ + /* */ + /* */ + /* The face object destructor. */ + /* */ + /* */ + /* face :: A typeless pointer to the face object to destroy. */ + /* */ + LOCAL_FUNC + void Z1_Done_Face( T1_Face face ) + { + FT_Memory memory; + T1_Font* type1 = &face->type1; + + + if ( face ) + { + memory = face->root.memory; + +#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT + /* release multiple masters information */ + Z1_Done_Blend( face ); + face->blend = 0; +#endif + + /* release font info strings */ + { + T1_FontInfo* info = &type1->font_info; + + + FREE( info->version ); + FREE( info->notice ); + FREE( info->full_name ); + FREE( info->family_name ); + FREE( info->weight ); + } + + /* release top dictionary */ + FREE( type1->charstrings_len ); + FREE( type1->charstrings ); + FREE( type1->glyph_names ); + + FREE( type1->subrs ); + FREE( type1->subrs_len ); + + FREE( type1->subrs_block ); + FREE( type1->charstrings_block ); + FREE( type1->glyph_names_block ); + + FREE( type1->encoding.char_index ); + FREE( type1->font_name ); + +#ifndef Z1_CONFIG_OPTION_NO_AFM + /* release afm data if present */ + if ( face->afm_data ) + Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data ); +#endif + + /* release unicode map, if any */ + FREE( face->unicode_map.maps ); + face->unicode_map.num_maps = 0; + + face->root.family_name = 0; + face->root.style_name = 0; + } + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Face */ + /* */ + /* */ + /* The face object constructor. */ + /* */ + /* */ + /* stream :: input stream where to load font data. */ + /* */ + /* face_index :: The index of the font face in the resource. */ + /* */ + /* num_params :: Number of additional generic parameters. Ignored. */ + /* */ + /* params :: Additional generic parameters. Ignored. */ + /* */ + /* */ + /* face :: The face record to build. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + PSNames_Interface* psnames; + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + FT_UNUSED( stream ); + + + face->root.num_faces = 1; + + psnames = (PSNames_Interface*)face->psnames; + if ( !psnames ) + { + psnames = (PSNames_Interface*) + FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" ); + + face->psnames = psnames; + } + + /* open the tokenizer, this will also check the font format */ + error = Z1_Open_Face( face ); + if ( error ) + goto Exit; + + /* if we just wanted to check the format, leave successfully now */ + if ( face_index < 0 ) + goto Exit; + + /* check the face index */ + if ( face_index != 0 ) + { + FT_ERROR(( "Z1_Init_Face: invalid face index\n" )); + error = T1_Err_Invalid_Argument; + goto Exit; + } + + /* Now, load the font program into the face object */ + + /* Init the face object fields */ + /* Now set up root face fields */ + { + FT_Face root = (FT_Face)&face->root; + + + root->num_glyphs = face->type1.num_glyphs; + root->num_charmaps = 1; + + root->face_index = face_index; + root->face_flags = FT_FACE_FLAG_SCALABLE; + + root->face_flags |= FT_FACE_FLAG_HORIZONTAL; + + root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; + + if ( face->type1.font_info.is_fixed_pitch ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + if ( face->blend ) + root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; + + /* XXX: TODO -- add kerning with .afm support */ + + /* get style name -- be careful, some broken fonts only */ + /* have a `/FontName' dictionary entry! */ + root->family_name = face->type1.font_info.family_name; + if ( root->family_name ) + { + char* full = face->type1.font_info.full_name; + char* family = root->family_name; + + + while ( *family && *full == *family ) + { + family++; + full++; + } + + root->style_name = ( *full == ' ' ? full + 1 + : (char *)"Regular" ); + } + else + { + /* do we have a `/FontName'? */ + if ( face->type1.font_name ) + { + root->family_name = face->type1.font_name; + root->style_name = "Regular"; + } + } + + /* no embedded bitmap support */ + root->num_fixed_sizes = 0; + root->available_sizes = 0; + + root->bbox = face->type1.font_bbox; + root->units_per_EM = 1000; + root->ascender = (FT_Short)face->type1.font_bbox.yMax; + root->descender = -(FT_Short)face->type1.font_bbox.yMin; + root->height = ( ( root->ascender + root->descender ) * 12 ) / 10; + + /* now compute the maximum advance width */ + + root->max_advance_width = face->type1.private_dict.standard_width[0]; + + /* compute max advance width for proportional fonts */ + if ( !face->type1.font_info.is_fixed_pitch ) + { + FT_Int max_advance; + + + error = Z1_Compute_Max_Advance( face, &max_advance ); + + /* in case of error, keep the standard width */ + if ( !error ) + root->max_advance_width = max_advance; + else + error = 0; /* clear error */ + } + + root->max_advance_height = root->height; + + root->underline_position = face->type1.font_info.underline_position; + root->underline_thickness = face->type1.font_info.underline_thickness; + + root->max_points = 0; + root->max_contours = 0; + } + + /* charmap support -- synthetize unicode charmap if possible */ + { + FT_Face root = &face->root; + FT_CharMap charmap = face->charmaprecs; + + + /* synthesize a Unicode charmap if there is support in the `PSNames' */ + /* module */ + if ( face->psnames ) + { + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + + + if ( psnames->unicode_value ) + { + error = psnames->build_unicodes( + root->memory, + face->type1.num_glyphs, + (const char**)face->type1.glyph_names, + &face->unicode_map ); + if ( !error ) + { + root->charmap = charmap; + charmap->face = (FT_Face)face; + charmap->encoding = ft_encoding_unicode; + charmap->platform_id = 3; + charmap->encoding_id = 1; + charmap++; + } + + /* simply clear the error in case of failure (which really) */ + /* means that out of memory or no unicode glyph names */ + error = FT_Err_Ok; + } + } + + /* now, support either the standard, expert, or custom encoding */ + charmap->face = (FT_Face)face; + charmap->platform_id = 7; /* a new platform id for Adobe fonts? */ + + switch ( face->type1.encoding_type ) + { + case t1_encoding_standard: + charmap->encoding = ft_encoding_adobe_standard; + charmap->encoding_id = 0; + break; + + case t1_encoding_expert: + charmap->encoding = ft_encoding_adobe_expert; + charmap->encoding_id = 1; + break; + + default: + charmap->encoding = ft_encoding_adobe_custom; + charmap->encoding_id = 2; + break; + } + + root->charmaps = face->charmaps; + root->num_charmaps = charmap - face->charmaprecs + 1; + face->charmaps[0] = &face->charmaprecs[0]; + face->charmaps[1] = &face->charmaprecs[1]; + } + + Exit: + return error; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Init_Driver */ + /* */ + /* */ + /* Initializes a given Type 1 driver object. */ + /* */ + /* */ + /* driver :: A handle to the target driver object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Init_Driver( Z1_Driver driver ) + { + FT_UNUSED( driver ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Driver */ + /* */ + /* */ + /* Finalizes a given Type 1 driver. */ + /* */ + /* */ + /* driver :: A handle to the target Type 1 driver. */ + /* */ + LOCAL_DEF + void Z1_Done_Driver( Z1_Driver driver ) + { + FT_UNUSED( driver ); + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1objs.h b/subsys/win32k/freetype/src/type1z/z1objs.h new file mode 100644 index 0000000..c655a67 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1objs.h @@ -0,0 +1,161 @@ +/***************************************************************************/ +/* */ +/* z1objs.h */ +/* */ +/* Experimental Type 1 objects manager (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef Z1OBJS_H +#define Z1OBJS_H + +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + /* The following structures must be defined by the hinter */ + typedef struct Z1_Size_Hints_ Z1_Size_Hints; + typedef struct Z1_Glyph_Hints_ Z1_Glyph_Hints; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Driver */ + /* */ + /* */ + /* A handle to a Type 1 driver object. */ + /* */ + typedef struct Z1_DriverRec_ *Z1_Driver; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Size */ + /* */ + /* */ + /* A handle to a Type 1 size object. */ + /* */ + typedef struct Z1_SizeRec_* Z1_Size; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_GlyphSlot */ + /* */ + /* */ + /* A handle to a Type 1 glyph slot object. */ + /* */ + typedef struct Z1_GlyphSlotRec_* Z1_GlyphSlot; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_CharMap */ + /* */ + /* */ + /* A handle to a Type 1 character mapping object. */ + /* */ + /* */ + /* The Type 1 format doesn't use a charmap but an encoding table. */ + /* The driver is responsible for making up charmap objects */ + /* corresponding to these tables. */ + /* */ + typedef struct Z1_CharMapRec_* Z1_CharMap; + + + /*************************************************************************/ + /* */ + /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */ + /* */ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_SizeRec */ + /* */ + /* */ + /* Type 1 size record. */ + /* */ + typedef struct Z1_SizeRec_ + { + FT_SizeRec root; + FT_Bool valid; + Z1_Size_Hints* hints; /* defined in the hinter. This allows */ + /* us to experiment with different */ + /* hinting schemes without having to */ + /* change `z1objs' each time. */ + } Z1_SizeRec; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_GlyphSlotRec */ + /* */ + /* */ + /* Type 1 glyph slot record. */ + /* */ + typedef struct Z1_GlyphSlotRec_ + { + FT_GlyphSlotRec root; + + FT_Bool hint; + FT_Bool scaled; + + FT_Int max_points; + FT_Int max_contours; + + FT_Fixed x_scale; + FT_Fixed y_scale; + + Z1_Glyph_Hints* hints; /* defined in the hinter */ + + } Z1_GlyphSlotRec; + + + LOCAL_DEF + FT_Error Z1_Init_Face( FT_Stream stream, + T1_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void Z1_Done_Face( T1_Face face ); + + LOCAL_DEF + FT_Error Z1_Init_Driver( Z1_Driver driver ); + + LOCAL_DEF + void Z1_Done_Driver( Z1_Driver driver ); + + +#ifdef __cplusplus + } +#endif + +#endif /* Z1OBJS_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1parse.c b/subsys/win32k/freetype/src/type1z/z1parse.c new file mode 100644 index 0000000..8c2dacb --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1parse.c @@ -0,0 +1,1398 @@ +/***************************************************************************/ +/* */ +/* z1parse.c */ +/* */ +/* Experimental Type 1 parser (body). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + + /*************************************************************************/ + /* */ + /* The Type 1 parser is in charge of the following: */ + /* */ + /* - provide an implementation of a growing sequence of objects called */ + /* a `Z1_Table' (used to build various tables needed by the loader). */ + /* */ + /* - opening .pfb and .pfa files to extract their top-level and private */ + /* dictionaries. */ + /* */ + /* - read numbers, arrays & strings from any dictionary. */ + /* */ + /* See `z1load.c' to see how data is loaded from the font file. */ + /* */ + /*************************************************************************/ + + +#include +#include +#include +#include +#include + + +#ifdef FT_FLAT_COMPILE + +#include "z1parse.h" + +#else + +#include + +#endif + + +#include /* for strncmp() */ + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_z1parse + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** IMPLEMENTATION OF Z1_TABLE OBJECT *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_New_Table */ + /* */ + /* */ + /* Initialises a Z1_Table. */ + /* */ + /* */ + /* table :: The address of the target table. */ + /* */ + /* */ + /* count :: The table size = the maximum number of elements. */ + /* */ + /* memory :: The memory object to use for all subsequent */ + /* reallocations. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + LOCAL_FUNC + FT_Error Z1_New_Table( Z1_Table* table, + FT_Int count, + FT_Memory memory ) + { + FT_Error error; + + + table->memory = memory; + if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) || + ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) + goto Exit; + + table->max_elems = count; + table->init = 0xdeadbeef; + table->num_elems = 0; + table->block = 0; + table->capacity = 0; + table->cursor = 0; + + Exit: + if ( error ) + FREE( table->elements ); + + return error; + } + + + static + void shift_elements( Z1_Table* table, + FT_Byte* old_base ) + { + FT_Long delta = table->block - old_base; + FT_Byte** offset = table->elements; + FT_Byte** limit = offset + table->max_elems; + + + if ( delta ) + for ( ; offset < limit; offset++ ) + { + if ( offset[0] ) + offset[0] += delta; + } + } + + + static + FT_Error reallocate_t1_table( Z1_Table* table, + FT_Int new_size ) + { + FT_Memory memory = table->memory; + FT_Byte* old_base = table->block; + FT_Error error; + + + /* reallocate the base block */ + if ( REALLOC( table->block, table->capacity, new_size ) ) + return error; + + table->capacity = new_size; + + /* shift all offsets if necessary */ + if ( old_base ) + shift_elements( table, old_base ); + + return T1_Err_Ok; + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Add_Table */ + /* */ + /* */ + /* Adds an object to a Z1_Table, possibly growing its memory block. */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* index :: The index of the object in the table. */ + /* */ + /* object :: The address of the object to copy in memory. */ + /* */ + /* length :: The length in bytes of the source object. */ + /* */ + /* */ + /* FreeType error code. 0 means success. An error is returned if a */ + /* reallocation fails. */ + /* */ + LOCAL_FUNC + FT_Error Z1_Add_Table( Z1_Table* table, + FT_Int index, + void* object, + FT_Int length ) + { + if ( index < 0 || index > table->max_elems ) + { + FT_ERROR(( "Z1_Add_Table: invalid index\n" )); + return T1_Err_Syntax_Error; + } + + /* grow the base block if needed */ + if ( table->cursor + length > table->capacity ) + { + FT_Error error; + FT_Int new_size = table->capacity; + + + while ( new_size < table->cursor + length ) + new_size += 1024; + + error = reallocate_t1_table( table, new_size ); + if ( error ) + return error; + } + + /* add the object to the base block and adjust offset */ + table->elements[index] = table->block + table->cursor; + table->lengths [index] = length; + MEM_Copy( table->block + table->cursor, object, length ); + + table->cursor += length; + return T1_Err_Ok; + } + + +#if 0 + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Done_Table */ + /* */ + /* */ + /* Finalizes a Z1_Table (i.e., reallocate it to its current cursor). */ + /* */ + /* */ + /* table :: The target table. */ + /* */ + /* */ + /* This function does NOT release the heap's memory block. It is up */ + /* to the caller to clean it, or reference it in its own structures. */ + /* */ + LOCAL_FUNC + void Z1_Done_Table( Z1_Table* table ) + { + FT_Memory memory = table->memory; + FT_Error error; + FT_Byte* old_base; + + + /* should never fail, as rec.cursor <= rec.size */ + old_base = table->block; + if ( !old_base ) + return; + + (void)REALLOC( table->block, table->capacity, table->cursor ); + table->capacity = table->cursor; + + if ( old_base != table->block ) + shift_elements( table, old_base ); + } + +#endif /* 0 */ + + + LOCAL_FUNC + void Z1_Release_Table( Z1_Table* table ) + { + FT_Memory memory = table->memory; + + + if ( table->init == (FT_Long)0xDEADBEEF ) + { + FREE( table->block ); + FREE( table->elements ); + FREE( table->lengths ); + table->init = 0; + } + } + + + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + /***** *****/ + /***** INPUT STREAM PARSER *****/ + /***** *****/ + /*************************************************************************/ + /*************************************************************************/ + /*************************************************************************/ + + +#define IS_Z1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) +#define IS_Z1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) + +#define IS_Z1_SPACE( c ) ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) ) + + + LOCAL_FUNC + void Z1_Skip_Spaces( Z1_Parser* parser ) + { + FT_Byte* cur = parser->cursor; + FT_Byte* limit = parser->limit; + + + while ( cur < limit ) + { + FT_Byte c = *cur; + + + if ( !IS_Z1_SPACE( c ) ) + break; + cur++; + } + parser->cursor = cur; + } + + + LOCAL_FUNC + void Z1_ToToken( Z1_Parser* parser, + Z1_Token_Rec* token ) + { + FT_Byte* cur; + FT_Byte* limit; + FT_Byte starter, ender; + FT_Int embed; + + + token->type = t1_token_none; + token->start = 0; + token->limit = 0; + + /* first of all, skip space */ + Z1_Skip_Spaces( parser ); + + cur = parser->cursor; + limit = parser->limit; + + if ( cur < limit ) + { + switch ( *cur ) + { + /************* check for strings ***********************/ + case '(': + token->type = t1_token_string; + ender = ')'; + goto Lookup_Ender; + + /************* check for programs/array ****************/ + case '{': + token->type = t1_token_array; + ender = '}'; + goto Lookup_Ender; + + /************* check for table/array ******************/ + case '[': + token->type = t1_token_array; + ender = ']'; + + Lookup_Ender: + embed = 1; + starter = *cur++; + token->start = cur; + while ( cur < limit ) + { + if ( *cur == starter ) + embed++; + else if ( *cur == ender ) + { + embed--; + if ( embed <= 0 ) + { + token->limit = cur++; + break; + } + } + cur++; + } + break; + + /* **************** otherwise, it's any token **********/ + default: + token->start = cur++; + token->type = t1_token_any; + while ( cur < limit && !IS_Z1_SPACE( *cur ) ) + cur++; + + token->limit = cur; + } + + if ( !token->limit ) + { + token->start = 0; + token->type = t1_token_none; + } + + parser->cursor = cur; + } + } + + + LOCAL_FUNC + void Z1_ToTokenArray( Z1_Parser* parser, + Z1_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ) + { + Z1_Token_Rec master; + + + *pnum_tokens = -1; + + Z1_ToToken( parser, &master ); + if ( master.type == t1_token_array ) + { + FT_Byte* old_cursor = parser->cursor; + FT_Byte* old_limit = parser->limit; + Z1_Token_Rec* cur = tokens; + Z1_Token_Rec* limit = cur + max_tokens; + + + parser->cursor = master.start; + parser->limit = master.limit; + + while ( parser->cursor < parser->limit ) + { + Z1_Token_Rec token; + + + Z1_ToToken( parser, &token ); + if ( !token.type ) + break; + + if ( cur < limit ) + *cur = token; + + cur++; + } + + *pnum_tokens = cur - tokens; + + parser->cursor = old_cursor; + parser->limit = old_limit; + } + } + + + static + FT_Long t1_toint( FT_Byte** cursor, + FT_Byte* limit ) + { + FT_Long result = 0; + FT_Byte* cur = *cursor; + FT_Byte c, d; + + + for ( ; cur < limit; cur++ ) + { + c = *cur; + d = (FT_Byte)( c - '0' ); + if ( d < 10 ) + break; + + if ( c == '-' ) + { + cur++; + break; + } + } + + if ( cur < limit ) + { + do + { + d = (FT_Byte)( cur[0] - '0' ); + if ( d >= 10 ) + break; + + result = result * 10 + d; + cur++; + + } while ( cur < limit ); + + if ( c == '-' ) + result = -result; + } + + *cursor = cur; + return result; + } + + + static + FT_Long t1_tofixed( FT_Byte** cursor, + FT_Byte* limit, + FT_Long power_ten ) + { + FT_Byte* cur = *cursor; + FT_Long num, divider, result; + FT_Int sign = 0; + FT_Byte d; + + + if ( cur >= limit ) + return 0; + + /* first of all, read the integer part */ + result = t1_toint( &cur, limit ) << 16; + num = 0; + divider = 1; + + if ( result < 0 ) + { + sign = 1; + result = -result; + } + + if ( cur >= limit ) + goto Exit; + + /* read decimal part, if any */ + if ( *cur == '.' && cur + 1 < limit ) + { + cur++; + + for (;;) + { + d = (FT_Byte)( *cur - '0' ); + if ( d >= 10 ) + break; + + if ( divider < 10000000L ) + { + num = num * 10 + d; + divider *= 10; + } + + cur++; + if ( cur >= limit ) + break; + } + } + + /* read exponent, if any */ + if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) ) + { + cur++; + power_ten += t1_toint( &cur, limit ); + } + + Exit: + /* raise to power of ten if needed */ + while ( power_ten > 0 ) + { + result = result * 10; + num = num * 10; + power_ten--; + } + + while ( power_ten < 0 ) + { + result = result / 10; + divider = divider * 10; + power_ten++; + } + + if ( num ) + result += FT_DivFix( num, divider ); + + if ( sign ) + result = -result; + + *cursor = cur; + return result; + } + + + static + FT_Int t1_tocoordarray( FT_Byte** cursor, + FT_Byte* limit, + FT_Int max_coords, + FT_Short* coords ) + { + FT_Byte* cur = *cursor; + FT_Int count = 0; + FT_Byte c, ender; + + + if ( cur >= limit ) + goto Exit; + + /* check for the beginning of an array. If not, only one number will */ + /* be read */ + c = *cur; + ender = 0; + + if ( c == '[' ) + ender = ']'; + + if ( c == '{' ) + ender = '}'; + + if ( ender ) + cur++; + + /* now, read the coordinates */ + for ( ; cur < limit; ) + { + /* skip whitespace in front of data */ + for (;;) + { + c = *cur; + if ( c != ' ' && c != '\t' ) + break; + + cur++; + if ( cur >= limit ) + goto Exit; + } + + if ( count >= max_coords || c == ender ) + break; + + coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 ); + count++; + + if ( !ender ) + break; + } + + Exit: + *cursor = cur; + return count; + } + + + static + FT_Int t1_tofixedarray( FT_Byte** cursor, + FT_Byte* limit, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ) + { + FT_Byte* cur = *cursor; + FT_Int count = 0; + FT_Byte c, ender; + + + if ( cur >= limit ) goto Exit; + + /* check for the beginning of an array. If not, only one number will */ + /* be read */ + c = *cur; + ender = 0; + + if ( c == '[' ) + ender = ']'; + + if ( c == '{' ) + ender = '}'; + + if ( ender ) + cur++; + + /* now, read the values */ + for ( ; cur < limit; ) + { + /* skip whitespace in front of data */ + for (;;) + { + c = *cur; + if ( c != ' ' && c != '\t' ) + break; + + cur++; + if ( cur >= limit ) + goto Exit; + } + + if ( count >= max_values || c == ender ) + break; + + values[count] = t1_tofixed( &cur, limit, power_ten ); + count++; + + if ( !ender ) + break; + } + + Exit: + *cursor = cur; + return count; + } + + +#if 0 + + static + FT_String* t1_tostring( FT_Byte** cursor, + FT_Byte* limit, + FT_Memory memory ) + { + FT_Byte* cur = *cursor; + FT_Int len = 0; + FT_Int count; + FT_String* result; + FT_Error error; + + + /* XXX: some stupid fonts have a `Notice' or `Copyright' string */ + /* that simply doesn't begin with an opening parenthesis, even */ + /* though they have a closing one! E.g. "amuncial.pfb" */ + /* */ + /* We must deal with these ill-fated cases there. Note that */ + /* these fonts didn't work with the old Type 1 driver as the */ + /* notice/copyright was not recognized as a valid string token */ + /* and made the old token parser commit errors. */ + + while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) ) + cur++; + if ( cur + 1 >= limit ) + return 0; + + if ( *cur == '(' ) + cur++; /* skip the opening parenthesis, if there is one */ + + *cursor = cur; + count = 0; + + /* then, count its length */ + for ( ; cur < limit; cur++ ) + { + if ( *cur == '(' ) + count++; + + else if ( *cur == ')' ) + { + count--; + if ( count < 0 ) + break; + } + } + + len = cur - *cursor; + if ( cur >= limit || ALLOC( result, len + 1 ) ) + return 0; + + /* now copy the string */ + MEM_Copy( result, *cursor, len ); + result[len] = '\0'; + *cursor = cur; + return result; + } + +#endif /* 0 */ + + + static + int t1_tobool( FT_Byte** cursor, + FT_Byte* limit ) + { + FT_Byte* cur = *cursor; + FT_Bool result = 0; + + + /* return 1 if we find `true', 0 otherwise */ + if ( cur + 3 < limit && + cur[0] == 't' && + cur[1] == 'r' && + cur[2] == 'u' && + cur[3] == 'e' ) + { + result = 1; + cur += 5; + } + else if ( cur + 4 < limit && + cur[0] == 'f' && + cur[1] == 'a' && + cur[2] == 'l' && + cur[3] == 's' && + cur[4] == 'e' ) + { + result = 0; + cur += 6; + } + + *cursor = cur; + return result; + } + + + /* Load a simple field (i.e. non-table) into the current list of objects */ + LOCAL_FUNC + FT_Error Z1_Load_Field( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + Z1_Token_Rec token; + FT_Byte* cur; + FT_Byte* limit; + FT_UInt count; + FT_UInt index; + FT_Error error; + + + Z1_ToToken( parser, &token ); + if ( !token.type ) + goto Fail; + + count = 1; + index = 0; + cur = token.start; + limit = token.limit; + + if ( token.type == t1_token_array ) + { + /* if this is an array, and we have no blend, an error occurs */ + if ( max_objects == 0 ) + goto Fail; + + count = max_objects; + index = 1; + } + + for ( ; count > 0; count--, index++ ) + { + FT_Byte* q = (FT_Byte*)objects[index] + field->offset; + FT_Long val; + FT_String* string; + + switch ( field->type ) + { + case t1_field_bool: + val = t1_tobool( &cur, limit ); + goto Store_Integer; + + case t1_field_fixed: + val = t1_tofixed( &cur, limit, 3 ); + goto Store_Integer; + + case t1_field_integer: + val = t1_toint( &cur, limit ); + + Store_Integer: + switch ( field->size ) + { + case 1: + *(FT_Byte*)q = (FT_Byte)val; + break; + + case 2: + *(FT_UShort*)q = (FT_UShort)val; + break; + + case 4: + *(FT_UInt32*)q = (FT_UInt32)val; + break; + + default: /* for 64-bit systems */ + *(FT_Long*)q = val; + } + break; + + case t1_field_string: + { + FT_Memory memory = parser->memory; + FT_UInt len = limit-cur; + + if ( ALLOC( string, len + 1 ) ) + goto Exit; + + MEM_Copy( string, cur, len ); + string[len] = 0; + + *(FT_String**)q = string; + } + break; + + default: + /* an error occured */ + goto Fail; + } + } + + if ( pflags ) + *pflags |= 1L << field->flag_bit; + + error = FT_Err_Ok; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + +#define T1_MAX_TABLE_ELEMENTS 32 + + + LOCAL_FUNC + FT_Error Z1_Load_Field_Table( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ) + { + Z1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; + Z1_Token_Rec* token; + FT_Int num_elements; + FT_Error error = 0; + FT_Byte* old_cursor; + FT_Byte* old_limit; + Z1_Field_Rec fieldrec = *(Z1_Field_Rec*)field; + + + Z1_ToTokenArray( parser, elements, 32, &num_elements ); + if ( num_elements < 0 ) + goto Fail; + + if ( num_elements > T1_MAX_TABLE_ELEMENTS ) + num_elements = T1_MAX_TABLE_ELEMENTS; + + old_cursor = parser->cursor; + old_limit = parser->limit; + + /* we store the elements count */ + *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = num_elements; + + /* we now load each element, adjusting the field.offset on each one */ + token = elements; + for ( ; num_elements > 0; num_elements--, token++ ) + { + parser->cursor = token->start; + parser->limit = token->limit; + Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 ); + fieldrec.offset += fieldrec.size; + } + + if ( pflags ) + *pflags |= 1L << field->flag_bit; + + parser->cursor = old_cursor; + parser->limit = old_limit; + + Exit: + return error; + + Fail: + error = T1_Err_Invalid_File_Format; + goto Exit; + } + + + LOCAL_FUNC + FT_Long Z1_ToInt ( Z1_Parser* parser ) + { + return t1_toint( &parser->cursor, parser->limit ); + } + + + LOCAL_FUNC + FT_Long Z1_ToFixed( Z1_Parser* parser, + FT_Int power_ten ) + { + return t1_tofixed( &parser->cursor, parser->limit, power_ten ); + } + + + LOCAL_FUNC + FT_Int Z1_ToCoordArray( Z1_Parser* parser, + FT_Int max_coords, + FT_Short* coords ) + { + return t1_tocoordarray( &parser->cursor, parser->limit, + max_coords, coords ); + } + + + LOCAL_FUNC + FT_Int Z1_ToFixedArray( Z1_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ) + { + return t1_tofixedarray( &parser->cursor, parser->limit, + max_values, values, power_ten ); + } + + +#if 0 + + LOCAL_FUNC + FT_String* Z1_ToString( Z1_Parser* parser ) + { + return t1_tostring( &parser->cursor, parser->limit, parser->memory ); + } + + + LOCAL_FUNC + FT_Bool Z1_ToBool( Z1_Parser* parser ) + { + return t1_tobool( &parser->cursor, parser->limit ); + } + +#endif /* 0 */ + + + static + FT_Error read_pfb_tag( FT_Stream stream, + FT_UShort* tag, + FT_Long* size ) + { + FT_Error error; + + + if ( READ_UShort( *tag ) ) + goto Exit; + + if ( *tag == 0x8001 || *tag == 0x8002 ) + { + FT_Long asize; + + + if ( READ_ULong( asize ) ) + goto Exit; + + /* swap between big and little endianness */ + *size = ( ( asize & 0xFF000000L ) >> 24 ) | + ( ( asize & 0x00FF0000L ) >> 8 ) | + ( ( asize & 0x0000FF00L ) << 8 ) | + ( ( asize & 0x000000FFL ) << 24 ); + } + + Exit: + return error; + } + + + LOCAL_FUNC + FT_Error Z1_New_Parser( Z1_Parser* parser, + FT_Stream stream, + FT_Memory memory ) + { + FT_Error error; + FT_UShort tag; + FT_Long size; + + + parser->stream = stream; + parser->memory = memory; + parser->base_len = 0; + parser->base_dict = 0; + parser->private_len = 0; + parser->private_dict = 0; + parser->in_pfb = 0; + parser->in_memory = 0; + parser->single_block = 0; + + parser->cursor = 0; + parser->limit = 0; + + /******************************************************************/ + /* */ + /* Here a short summary of what is going on: */ + /* */ + /* When creating a new Type 1 parser, we try to locate and load */ + /* the base dictionary if this is possible (i.e. for PFB */ + /* files). Otherwise, we load the whole font into memory. */ + /* */ + /* When `loading' the base dictionary, we only setup pointers */ + /* in the case of a memory-based stream. Otherwise, we */ + /* allocate and load the base dictionary in it. */ + /* */ + /* parser->in_pfb is set if we are in a binary (".pfb") font. */ + /* parser->in_memory is set if we have a memory stream. */ + /* */ + + /* try to compute the size of the base dictionary; */ + /* look for a Postscript binary file tag, i.e 0x8001 */ + if ( FILE_Seek( 0L ) ) + goto Exit; + + error = read_pfb_tag( stream, &tag, &size ); + if ( error ) + goto Exit; + + if ( tag != 0x8001 ) + { + /* assume that this is a PFA file for now; an error will */ + /* be produced later when more things are checked */ + (void)FILE_Seek( 0L ); + size = stream->size; + } + else + parser->in_pfb = 1; + + /* now, try to load `size' bytes of the `base' dictionary we */ + /* found previously */ + + /* if it is a memory-based resource, set up pointers */ + if ( !stream->read ) + { + parser->base_dict = (FT_Byte*)stream->base + stream->pos; + parser->base_len = size; + parser->in_memory = 1; + + /* check that the `size' field is valid */ + if ( FILE_Skip( size ) ) + goto Exit; + } + else + { + /* read segment in memory */ + if ( ALLOC( parser->base_dict, size ) || + FILE_Read( parser->base_dict, size ) ) + goto Exit; + parser->base_len = size; + } + + /* Now check font format; we must see `%!PS-AdobeFont-1' */ + /* or `%!FontType' */ + { + if ( size <= 16 || + ( strncmp( (const char*)parser->base_dict, + "%!PS-AdobeFont-1", 16 ) && + strncmp( (const char*)parser->base_dict, + "%!FontType", 10 ) ) ) + { + FT_TRACE2(( "[not a Type1 font]\n" )); + error = FT_Err_Unknown_File_Format; + } + else + { + parser->cursor = parser->base_dict; + parser->limit = parser->cursor + parser->base_len; + } + } + + Exit: + if ( error && !parser->in_memory ) + FREE( parser->base_dict ); + + return error; + } + + + LOCAL_FUNC + void Z1_Done_Parser( Z1_Parser* parser ) + { + FT_Memory memory = parser->memory; + + + /* always free the private dictionary */ + FREE( parser->private_dict ); + + /* free the base dictionary only when we have a disk stream */ + if ( !parser->in_memory ) + FREE( parser->base_dict ); + } + + + /* return the value of an hexadecimal digit */ + static + int hexa_value( char c ) + { + unsigned int d; + + + d = (unsigned int)( c - '0' ); + if ( d <= 9 ) + return (int)d; + + d = (unsigned int)( c - 'a' ); + if ( d <= 5 ) + return (int)( d + 10 ); + + d = (unsigned int)( c - 'A' ); + if ( d <= 5 ) + return (int)( d + 10 ); + + return -1; + } + + + LOCAL_FUNC + void Z1_Decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ) + { + while ( length > 0 ) + { + FT_Byte plain; + + + plain = ( *buffer ^ ( seed >> 8 ) ); + seed = ( *buffer + seed ) * 52845 + 22719; + *buffer++ = plain; + length--; + } + } + + + LOCAL_FUNC + FT_Error Z1_Get_Private_Dict( Z1_Parser* parser ) + { + FT_Stream stream = parser->stream; + FT_Memory memory = parser->memory; + FT_Error error = 0; + FT_Long size; + + + if ( parser->in_pfb ) + { + /* in the case of the PFB format, the private dictionary can be */ + /* made of several segments. We thus first read the number of */ + /* segments to compute the total size of the private dictionary */ + /* then re-read them into memory. */ + FT_Long start_pos = FILE_Pos(); + FT_UShort tag; + FT_Long size; + + + parser->private_len = 0; + for (;;) + { + error = read_pfb_tag( stream, &tag, &size ); + if ( error ) + goto Fail; + + if ( tag != 0x8002 ) + break; + + parser->private_len += size; + + if ( FILE_Skip( size ) ) + goto Fail; + } + + /* Check that we have a private dictionary there */ + /* and allocate private dictionary buffer */ + if ( parser->private_len == 0 ) + { + FT_ERROR(( "Z1_Get_Private_Dict:" )); + FT_ERROR(( " invalid private dictionary section\n" )); + error = T1_Err_Invalid_File_Format; + goto Fail; + } + + if ( FILE_Seek( start_pos ) || + ALLOC( parser->private_dict, parser->private_len ) ) + goto Fail; + + parser->private_len = 0; + for (;;) + { + error = read_pfb_tag( stream, &tag, &size ); + if ( error || tag != 0x8002 ) + { + error = FT_Err_Ok; + break; + } + + if ( FILE_Read( parser->private_dict + parser->private_len, size ) ) + goto Fail; + + parser->private_len += size; + } + } + else + { + /* we have already `loaded' the whole PFA font file into memory; */ + /* if this is a memory resource, allocate a new block to hold */ + /* the private dict. Otherwise, simply overwrite into the base */ + /* dictionary block in the heap. */ + + /* first of all, look at the `eexec' keyword */ + FT_Byte* cur = parser->base_dict; + FT_Byte* limit = cur + parser->base_len; + FT_Byte c; + + + for (;;) + { + c = cur[0]; + if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ + /* newline + 4 chars */ + { + if ( cur[1] == 'e' && cur[2] == 'x' && + cur[3] == 'e' && cur[4] == 'c' ) + { + cur += 6; /* we skip the newling after the `eexec' */ + + /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */ + /* skip the extra \n if we find it */ + if ( cur[0] == '\n' ) + cur++; + + break; + } + } + cur++; + if ( cur >= limit ) + { + FT_ERROR(( "Z1_Get_Private_Dict:" )); + FT_ERROR(( " could not find `eexec' keyword\n" )); + error = T1_Err_Invalid_File_Format; + goto Exit; + } + } + + /* now determine where to write the _encrypted_ binary private */ + /* dictionary. We overwrite the base dictionary for disk-based */ + /* resources and allocate a new block otherwise */ + + size = parser->base_len - ( cur - parser->base_dict); + + if ( parser->in_memory ) + { + /* note that we allocate one more byte to put a terminating `0' */ + if ( ALLOC( parser->private_dict, size + 1 ) ) + goto Fail; + parser->private_len = size; + } + else + { + parser->single_block = 1; + parser->private_dict = parser->base_dict; + parser->private_len = size; + parser->base_dict = 0; + parser->base_len = 0; + } + + /* now determine whether the private dictionary is encoded in binary */ + /* or hexadecimal ASCII format -- decode it accordingly */ + + /* we need to access the next 4 bytes (after the final \r following */ + /* the `eexec' keyword); if they all are hexadecimal digits, then */ + /* we have a case of ASCII storage */ + + if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) | + hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 ) + + /* binary encoding -- `simply' copy the private dict */ + MEM_Copy( parser->private_dict, cur, size ); + + else + { + /* ASCII hexadecimal encoding */ + + FT_Byte* write; + FT_Int count; + + + write = parser->private_dict; + count = 0; + + for ( ;cur < limit; cur++ ) + { + int hex1; + + + /* check for newline */ + if ( cur[0] == '\r' || cur[0] == '\n' ) + continue; + + /* exit if we have a non-hexadecimal digit that isn't a newline */ + hex1 = hexa_value( cur[0] ); + if ( hex1 < 0 || cur + 1 >= limit ) + break; + + /* otherwise, store byte */ + *write++ = ( hex1 << 4 ) | hexa_value( cur[1] ); + count++; + cur++; + } + + /* put a safeguard */ + parser->private_len = write - parser->private_dict; + *write++ = 0; + } + } + + /* we now decrypt the encoded binary private dictionary */ + Z1_Decrypt( parser->private_dict, parser->private_len, 55665 ); + parser->cursor = parser->private_dict; + parser->limit = parser->cursor + parser->private_len; + + Fail: + Exit: + return error; + } + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1parse.h b/subsys/win32k/freetype/src/type1z/z1parse.h new file mode 100644 index 0000000..d0b6a65 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1parse.h @@ -0,0 +1,363 @@ +/***************************************************************************/ +/* */ +/* z1parse.h */ +/* */ +/* Experimental Type 1 parser (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef Z1PARSE_H +#define Z1PARSE_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + + /* simple enumeration type used to identify token types */ + typedef enum Z1_Token_Type_ + { + t1_token_none = 0, + t1_token_any, + t1_token_string, + t1_token_array, + + /* do not remove */ + t1_token_max + + } Z1_Token_Type; + + + /* a simple structure used to identify tokens */ + typedef struct Z1_Token_Rec_ + { + FT_Byte* start; /* first character of token in input stream */ + FT_Byte* limit; /* first character after the token */ + Z1_Token_Type type; /* type of token.. */ + + } Z1_Token_Rec; + + + /* enumeration type used to identify object fields */ + typedef enum Z1_Field_Type_ + { + t1_field_none = 0, + t1_field_bool, + t1_field_integer, + t1_field_fixed, + t1_field_string, + t1_field_integer_array, + t1_field_fixed_array, + + /* do not remove */ + t1_field_max + + } Z1_Field_Type; + + + /* structure type used to model object fields */ + typedef struct Z1_Field_Rec_ + { + Z1_Field_Type type; /* type of field */ + FT_UInt offset; /* offset of field in object */ + FT_UInt size; /* size of field in bytes */ + FT_UInt array_max; /* maximum number of elements for array */ + FT_UInt count_offset; /* offset of element count for arrays */ + FT_Int flag_bit; /* bit number for field flag */ + + } Z1_Field_Rec; + + +#define Z1_FIELD_REF( s, f ) ( ((s*)0)->f ) + +#define Z1_FIELD_BOOL( _ftype, _fname ) \ + { \ + t1_field_bool, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_NUM( _ftype, _fname ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_FIXED( _ftype, _fname, _power ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_STRING( _ftype, _fname ) \ + { \ + t1_field_string, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname ) ), \ + 0, 0, 0 \ + } + +#define Z1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \ + 0 \ + } + +#define Z1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fcount ), \ + 0 \ + } + +#define Z1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \ + { \ + t1_field_integer, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + 0, 0 \ + } + +#define Z1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \ + { \ + t1_field_fixed, \ + (FT_UInt)(char*)&Z1_FIELD_REF( _ftype, _fname ), \ + sizeof ( Z1_FIELD_REF( _ftype, _fname )[0] ), \ + _fmax, \ + 0, 0 \ + } + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Table */ + /* */ + /* */ + /* A Z1_Table is a simple object used to store an array of objects in */ + /* a single memory block. */ + /* */ + /* */ + /* block :: The address in memory of the growheap's block. This */ + /* can change between two object adds, due to the use of */ + /* reallocation. */ + /* */ + /* cursor :: The current top of the grow heap within its block. */ + /* */ + /* capacity :: The current size of the heap block. Increments in */ + /* 1kByte blocks. */ + /* */ + /* init :: A boolean. Set when the table has been initialized */ + /* (the table user should set this field). */ + /* */ + /* max_elems :: The maximum number of elements in the table. */ + /* */ + /* num_elems :: The current number of elements in the table. */ + /* */ + /* elements :: A table of element addresses within the block. */ + /* */ + /* lengths :: A table of element sizes within the block. */ + /* */ + /* memory :: The memory object used for memory operations */ + /* (allocation/reallocation). */ + /* */ + typedef struct Z1_Table_ + { + FT_Byte* block; /* current memory block */ + FT_Int cursor; /* current cursor in memory block */ + FT_Int capacity; /* current size of memory block */ + FT_Long init; + + FT_Int max_elems; + FT_Int num_elems; + FT_Byte** elements; /* addresses of table elements */ + FT_Int* lengths; /* lengths of table elements */ + + FT_Memory memory; + + } Z1_Table; + + + /*************************************************************************/ + /* */ + /* */ + /* Z1_Parser */ + /* */ + /* */ + /* A Z1_Parser is an object used to parse a Type 1 fonts very */ + /* quickly. */ + /* */ + /* */ + /* stream :: The current input stream. */ + /* */ + /* memory :: The current memory object. */ + /* */ + /* base_dict :: A pointer to the top-level dictionary. */ + /* */ + /* base_len :: The length in bytes of the top dictionary. */ + /* */ + /* private_dict :: A pointer to the private dictionary. */ + /* */ + /* private_len :: The length in bytes of the private dictionary. */ + /* */ + /* in_pfb :: A boolean. Indicates that we are handling a PFB */ + /* file. */ + /* */ + /* in_memory :: A boolean. Indicates a memory-based stream. */ + /* */ + /* single_block :: A boolean. Indicates that the private dictionary */ + /* is stored in lieu of the base dictionary. */ + /* */ + /* cursor :: The current parser cursor. */ + /* */ + /* limit :: The current parser limit (first byte after the */ + /* current dictionary). */ + /* */ + /* error :: The current parsing error. */ + /* */ + typedef struct Z1_Parser_ + { + FT_Stream stream; + FT_Memory memory; + + FT_Byte* base_dict; + FT_Int base_len; + + FT_Byte* private_dict; + FT_Int private_len; + + FT_Byte in_pfb; + FT_Byte in_memory; + FT_Byte single_block; + + FT_Byte* cursor; + FT_Byte* limit; + FT_Error error; + + } Z1_Parser; + + + LOCAL_DEF + FT_Error Z1_New_Table( Z1_Table* table, + FT_Int count, + FT_Memory memory ); + + + LOCAL_DEF + FT_Error Z1_Add_Table( Z1_Table* table, + FT_Int index, + void* object, + FT_Int length ); + +#if 0 + LOCAL_DEF + void Z1_Done_Table( Z1_Table* table ); +#endif + + LOCAL_DEF + void Z1_Release_Table( Z1_Table* table ); + + LOCAL_DEF + FT_Long Z1_ToInt( Z1_Parser* parser ); + + LOCAL_DEF + FT_Long Z1_ToFixed( Z1_Parser* parser, + FT_Int power_ten ); + + LOCAL_DEF + FT_Int Z1_ToCoordArray( Z1_Parser* parser, + FT_Int max_coords, + FT_Short* coords ); + + LOCAL_DEF + FT_Int Z1_ToFixedArray( Z1_Parser* parser, + FT_Int max_values, + FT_Fixed* values, + FT_Int power_ten ); + +#if 0 + LOCAL_DEF + FT_String* Z1_ToString( Z1_Parser* parser ); + + LOCAL_DEF + FT_Bool Z1_ToBool( Z1_Parser* parser ); +#endif + + + LOCAL_DEF + void Z1_Skip_Spaces( Z1_Parser* parser ); + + LOCAL_DEF + void Z1_ToToken( Z1_Parser* parser, + Z1_Token_Rec* token ); + + LOCAL_FUNC + void Z1_ToTokenArray( Z1_Parser* parser, + Z1_Token_Rec* tokens, + FT_UInt max_tokens, + FT_Int* pnum_tokens ); + + LOCAL_DEF + FT_Error Z1_Load_Field( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + LOCAL_DEF + FT_Error Z1_Load_Field_Table( Z1_Parser* parser, + const Z1_Field_Rec* field, + void** objects, + FT_UInt max_objects, + FT_ULong* pflags ); + + + LOCAL_DEF + FT_Error Z1_New_Parser( Z1_Parser* parser, + FT_Stream stream, + FT_Memory memory ); + + LOCAL_DEF + FT_Error Z1_Get_Private_Dict( Z1_Parser* parser ); + + LOCAL_DEF + void Z1_Decrypt( FT_Byte* buffer, + FT_Int length, + FT_UShort seed ); + + LOCAL_DEF + void Z1_Done_Parser( Z1_Parser* parser ); + +#ifdef __cplusplus + } +#endif + +#endif /* Z1PARSE_H */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/type1z/z1tokens.h b/subsys/win32k/freetype/src/type1z/z1tokens.h new file mode 100644 index 0000000..73c0228 --- /dev/null +++ b/subsys/win32k/freetype/src/type1z/z1tokens.h @@ -0,0 +1,132 @@ +/***************************************************************************/ +/* */ +/* z1tokens.h */ +/* */ +/* Experimental Type 1 tokenizer (specification). */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#undef T1TYPE +#define T1TYPE T1_FontInfo + + Z1_FONTINFO_STRING( "version", version ) + Z1_FONTINFO_STRING( "Notice", notice ) + Z1_FONTINFO_STRING( "FullName", full_name ) + Z1_FONTINFO_STRING( "FamilyName", family_name ) + Z1_FONTINFO_STRING( "Weight", weight ) + + Z1_FONTINFO_NUM ( "ItalicAngle", italic_angle ) + Z1_FONTINFO_BOOL ( "isFixedPitch", is_fixed_pitch ) + Z1_FONTINFO_NUM ( "UnderlinePosition", underline_position ) + Z1_FONTINFO_NUM ( "UnderlineThickness", underline_thickness ) + + +#undef T1TYPE +#define T1TYPE T1_Private + + Z1_PRIVATE_NUM ( "UniqueID", unique_id ) + Z1_PRIVATE_NUM ( "lenIV", lenIV ) + Z1_PRIVATE_NUM ( "LanguageGroup", language_group ) + Z1_PRIVATE_NUM ( "password", password ) + + Z1_PRIVATE_FIXED ( "BlueScale", blue_scale ) + Z1_PRIVATE_NUM ( "BlueShift", blue_shift ) + Z1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz ) + + Z1_PRIVATE_NUM_TABLE ( "BlueValues", blue_values, 14, num_blue_values ) + Z1_PRIVATE_NUM_TABLE ( "OtherBlues", other_blues, 10, num_other_blues ) + Z1_PRIVATE_NUM_TABLE ( "FamilyBlues", family_blues, 14, num_family_blues ) + Z1_PRIVATE_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10, \ + num_family_other_blues ) + + Z1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 ) + Z1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 ) + Z1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 ) + + Z1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths ) + Z1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights ) + + +#undef T1TYPE +#define T1TYPE T1_Font + + Z1_TOPDICT_NUM( "PaintType", paint_type ) + Z1_TOPDICT_NUM( "FontType", font_type ) + Z1_TOPDICT_NUM( "StrokeWidth", stroke_width ) + + +#if 0 + + /* define the font info dictionary parsing callbacks */ +#undef FACE +#define FACE (face->type1.font_info) + + PARSE_STRING( "version", version ) + PARSE_STRING( "Notice", notice ) + PARSE_STRING( "FullName", full_name ) + PARSE_STRING( "FamilyName", family_name ) + PARSE_STRING( "Weight", weight ) + + PARSE_INT ( "ItalicAngle", italic_angle ) + PARSE_BOOL ( "isFixedPitch", is_fixed_pitch ) + PARSE_NUM ( "UnderlinePosition", underline_position, FT_Short ) + PARSE_NUM ( "UnderlineThickness", underline_thickness, FT_UShort ) + + + /* define the private dict parsing callbacks */ +#undef FACE +#define FACE (face->type1.private_dict) + + PARSE_INT ("UniqueID", unique_id ) + PARSE_INT ("lenIV", lenIV ) + + PARSE_COORDS ( "BlueValues", num_blues, 14, blue_values) + PARSE_COORDS ( "OtherBlues", num_other_blues, 10, other_blues) + + PARSE_COORDS ( "FamilyBlues", num_family_blues, 14, family_blues ) + PARSE_COORDS ( "FamilyOtherBlues", num_family_other_blues, 10, + family_other_blues ) + + PARSE_FIXED ( "BlueScale", blue_scale ) + PARSE_INT ( "BlueShift", blue_shift ) + + PARSE_INT ( "BlueFuzz", blue_fuzz ) + + PARSE_COORDS2( "StdHW", 1, standard_width ) + PARSE_COORDS2( "StdVW", 1, standard_height ) + + PARSE_COORDS ( "StemSnapH", num_snap_widths, 12, stem_snap_widths ) + PARSE_COORDS ( "StemSnapV", num_snap_heights, 12, stem_snap_heights ) + + PARSE_INT ( "LanguageGroup", language_group ) + PARSE_INT ( "password", password ) + PARSE_COORDS2( "MinFeature", 2, min_feature ) + + + /* define the top-level dictionary parsing callbacks */ +#undef FACE +#define FACE (face->type1) + +/*PARSE_STRING ( "FontName", font_name ) -- handled by special routine */ + PARSE_NUM ( "PaintType", paint_type, FT_Byte ) + PARSE_NUM ( "FontType", font_type, FT_Byte ) + PARSE_FIXEDS2( "FontMatrix", 4, font_matrix ) +/*PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special routine */ + PARSE_INT ( "StrokeWidth", stroke_width ) + +#undef FACE + +#endif /* 0 */ + + +/* END */ diff --git a/subsys/win32k/freetype/src/winfonts/.cvsignore b/subsys/win32k/freetype/src/winfonts/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/freetype/src/winfonts/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/freetype/src/winfonts/module.mk b/subsys/win32k/freetype/src/winfonts/module.mk new file mode 100644 index 0000000..5c12eb6 --- /dev/null +++ b/subsys/win32k/freetype/src/winfonts/module.mk @@ -0,0 +1,6 @@ +make_module_list: add_windows_driver + +add_windows_driver: + $(OPEN_DRIVER)winfnt_driver_class$(CLOSE_DRIVER) + $(ECHO_DRIVER)winfnt $(ECHO_DRIVER_DESC)Windows bitmap fonts with extension *.fnt or *.fon$(ECHO_DRIVER_DONE) + diff --git a/subsys/win32k/freetype/src/winfonts/rules.mk b/subsys/win32k/freetype/src/winfonts/rules.mk new file mode 100644 index 0000000..8396894 --- /dev/null +++ b/subsys/win32k/freetype/src/winfonts/rules.mk @@ -0,0 +1,64 @@ +# +# FreeType 2 Windows FNT/FON driver configuration rules +# + + +# Copyright 1996-2000 by +# David Turner, Robert Wilhelm, and Werner Lemberg. +# +# This file is part of the FreeType project, and may only be used, modified, +# and distributed under the terms of the FreeType project license, +# LICENSE.TXT. By continuing to use, modify, or distribute this file you +# indicate that you have read the license and understand and accept it +# fully. + + +# Windows driver directory +# +FNT_DIR := $(SRC_)winfonts +FNT_DIR_ := $(FNT_DIR)$(SEP) + + +FNT_COMPILE := $(FT_COMPILE) + + +# Windows driver sources (i.e., C files) +# +FNT_DRV_SRC := $(FNT_DIR_)winfnt.c + +# Windows driver headers +# +FNT_DRV_H := $(FNT_DRV_SRC:%.c=%.h) + + +# Windows driver object(s) +# +# FNT_DRV_OBJ_M is used during `multi' builds +# FNT_DRV_OBJ_S is used during `single' builds +# +FNT_DRV_OBJ_M := $(FNT_DRV_SRC:$(FNT_DIR_)%.c=$(OBJ_)%.$O) +FNT_DRV_OBJ_S := $(OBJ_)winfnt.$O + +# Windows driver source file for single build +# +FNT_DRV_SRC_S := $(FNT_DIR_)winfnt.c + + +# Windows driver - single object +# +$(FNT_DRV_OBJ_S): $(FNT_DRV_SRC_S) $(FNT_DRV_SRC) $(FREETYPE_H) $(FNT_DRV_H) + $(FNT_COMPILE) $T$@ $(FNT_DRV_SRC_S) + + +# Windows driver - multiple objects +# +$(OBJ_)%.$O: $(FNT_DIR_)%.c $(FREETYPE_H) $(FNT_DRV_H) + $(FNT_COMPILE) $T$@ $< + + +# update main driver object lists +# +DRV_OBJS_S += $(FNT_DRV_OBJ_S) +DRV_OBJS_M += $(FNT_DRV_OBJ_M) + +# EOF diff --git a/subsys/win32k/freetype/src/winfonts/winfnt.c b/subsys/win32k/freetype/src/winfonts/winfnt.c new file mode 100644 index 0000000..bacd7ad --- /dev/null +++ b/subsys/win32k/freetype/src/winfonts/winfnt.c @@ -0,0 +1,623 @@ +/***************************************************************************/ +/* */ +/* winfnt.c */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifdef FT_FLAT_COMPILE + +#include "winfnt.h" + +#else + +#include + +#endif + + +#include +#include +#include +#include + + + /*************************************************************************/ + /* */ + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ + /* messages during execution. */ + /* */ +#undef FT_COMPONENT +#define FT_COMPONENT trace_winfnt + + + static + const FT_Frame_Field winmz_header_fields[] = + { + FT_FRAME_START( 64 ), + FT_FRAME_USHORT_LE ( WinMZ_Header, magic ), + FT_FRAME_SKIP_BYTES( 29 * 2 ), + FT_FRAME_ULONG_LE ( WinMZ_Header, lfanew ), + FT_FRAME_END + }; + + static + const FT_Frame_Field winne_header_fields[] = + { + FT_FRAME_START( 40 ), + FT_FRAME_USHORT_LE ( WinNE_Header, magic ), + FT_FRAME_SKIP_BYTES( 34 ), + FT_FRAME_USHORT_LE ( WinNE_Header, resource_tab_offset ), + FT_FRAME_USHORT_LE ( WinNE_Header, rname_tab_offset ), + FT_FRAME_END + }; + + static + const FT_Frame_Field winfnt_header_fields[] = + { + FT_FRAME_START( 134 ), + FT_FRAME_USHORT_LE( WinFNT_Header, version ), + FT_FRAME_ULONG_LE ( WinFNT_Header, file_size ), + FT_FRAME_BYTES ( WinFNT_Header, copyright, 60 ), + FT_FRAME_USHORT_LE( WinFNT_Header, file_type ), + FT_FRAME_USHORT_LE( WinFNT_Header, nominal_point_size ), + FT_FRAME_USHORT_LE( WinFNT_Header, vertical_resolution ), + FT_FRAME_USHORT_LE( WinFNT_Header, horizontal_resolution ), + FT_FRAME_USHORT_LE( WinFNT_Header, ascent ), + FT_FRAME_USHORT_LE( WinFNT_Header, internal_leading ), + FT_FRAME_USHORT_LE( WinFNT_Header, external_leading ), + FT_FRAME_BYTE ( WinFNT_Header, italic ), + FT_FRAME_BYTE ( WinFNT_Header, underline ), + FT_FRAME_BYTE ( WinFNT_Header, strike_out ), + FT_FRAME_USHORT_LE( WinFNT_Header, weight ), + FT_FRAME_BYTE ( WinFNT_Header, charset ), + FT_FRAME_USHORT_LE( WinFNT_Header, pixel_width ), + FT_FRAME_USHORT_LE( WinFNT_Header, pixel_height ), + FT_FRAME_BYTE ( WinFNT_Header, pitch_and_family ), + FT_FRAME_USHORT_LE( WinFNT_Header, avg_width ), + FT_FRAME_USHORT_LE( WinFNT_Header, max_width ), + FT_FRAME_BYTE ( WinFNT_Header, first_char ), + FT_FRAME_BYTE ( WinFNT_Header, last_char ), + FT_FRAME_BYTE ( WinFNT_Header, default_char ), + FT_FRAME_BYTE ( WinFNT_Header, break_char ), + FT_FRAME_USHORT_LE( WinFNT_Header, bytes_per_row ), + FT_FRAME_ULONG_LE ( WinFNT_Header, device_offset ), + FT_FRAME_ULONG_LE ( WinFNT_Header, face_name_offset ), + FT_FRAME_ULONG_LE ( WinFNT_Header, bits_pointer ), + FT_FRAME_ULONG_LE ( WinFNT_Header, bits_offset ), + FT_FRAME_BYTE ( WinFNT_Header, reserved ), + FT_FRAME_ULONG_LE ( WinFNT_Header, flags ), + FT_FRAME_USHORT_LE( WinFNT_Header, A_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, B_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, C_space ), + FT_FRAME_USHORT_LE( WinFNT_Header, color_table_offset ), + FT_FRAME_BYTES ( WinFNT_Header, reserved, 4 ), + FT_FRAME_END + }; + + + static + void fnt_done_font( FT_Stream stream, + FNT_Font* font ) + { + if ( font->fnt_frame ) + RELEASE_Frame( font->fnt_frame ); + + font->fnt_size = 0; + font->fnt_frame = 0; + } + + + static + FT_Error fnt_load_font( FT_Stream stream, + FNT_Font* font ) + { + FT_Error error; + WinFNT_Header* header = &font->header; + + + /* first of all, read the FNT header */ + if ( FILE_Seek( font->offset ) || + READ_Fields( winfnt_header_fields, header ) ) + goto Exit; + + /* check header */ + if ( header->version != 0x200 && + header->version != 0x300 ) + { + FT_TRACE2(( "[not a valid FNT file]\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( header->file_type & 1 ) + { + FT_TRACE2(( "can't handle vector FNT fonts\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + /* small fixup -- some fonts have the `pixel_width' field set to 0 */ + if ( header->pixel_width == 0 ) + header->pixel_width = header->pixel_height; + + /* this is a FNT file/table, we now extract its frame */ + if ( FILE_Seek( font->offset ) || + EXTRACT_Frame( header->file_size, font->fnt_frame ) ) + goto Exit; + + Exit: + return error; + } + + + static + void fnt_done_fonts( FNT_Face face ) + { + FT_Memory memory = FT_FACE(face)->memory; + FT_Stream stream = FT_FACE(face)->stream; + FNT_Font* cur = face->fonts; + FNT_Font* limit = cur + face->num_fonts; + + + for ( ; cur < limit; cur++ ) + fnt_done_font( stream, cur ); + + FREE( face->fonts ); + face->num_fonts = 0; + } + + static + FT_Error fnt_get_dll_fonts( FNT_Face face ) + { + FT_Error error; + FT_Stream stream = FT_FACE(face)->stream; + FT_Memory memory = FT_FACE(face)->memory; + WinMZ_Header mz_header; + + + face->fonts = 0; + face->num_fonts = 0; + + /* does it begin with a MZ header? */ + if ( FILE_Seek( 0 ) || + READ_Fields( winmz_header_fields, &mz_header ) ) + goto Exit; + + error = FT_Err_Unknown_File_Format; + if ( mz_header.magic == WINFNT_MZ_MAGIC ) + { + /* yes, now look for a NE header in the file */ + WinNE_Header ne_header; + + + if ( FILE_Seek( mz_header.lfanew ) || + READ_Fields( winne_header_fields, &ne_header ) ) + goto Exit; + + error = FT_Err_Unknown_File_Format; + if ( ne_header.magic == WINFNT_NE_MAGIC ) + { + /* good, now look in the resource table for each FNT resource */ + FT_ULong res_offset = mz_header.lfanew + + ne_header.resource_tab_offset; + + FT_UShort size_shift; + FT_UShort font_count = 0; + FT_ULong font_offset = 0; + + + if ( FILE_Seek( res_offset ) || + ACCESS_Frame( ne_header.rname_tab_offset - + ne_header.resource_tab_offset ) ) + goto Exit; + + size_shift = GET_UShortLE(); + + for (;;) + { + FT_UShort type_id, count; + + + type_id = GET_UShortLE(); + if ( !type_id ) + break; + + count = GET_UShortLE(); + + if ( type_id == 0x8008 ) + { + font_count = count; + font_offset = FILE_Pos() + 4 + ( stream->cursor - stream->limit ); + break; + } + + stream->cursor += 4 + count * 12; + } + FORGET_Frame(); + + if ( !font_count || !font_offset ) + { + FT_TRACE2(( "this file doesn't contain any FNT resources!\n" )); + error = FT_Err_Unknown_File_Format; + goto Exit; + } + + if ( FILE_Seek( font_offset ) || + ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) ) + goto Exit; + + face->num_fonts = font_count; + + if ( ACCESS_Frame( (FT_Long)font_count * 12 ) ) + goto Exit; + + /* now read the offset and position of each FNT font */ + { + FNT_Font* cur = face->fonts; + FNT_Font* limit = cur + font_count; + + + for ( ; cur < limit; cur++ ) + { + cur->offset = (FT_ULong)GET_UShortLE() << size_shift; + cur->fnt_size = (FT_ULong)GET_UShortLE() << size_shift; + cur->size_shift = size_shift; + stream->cursor += 8; + } + } + FORGET_Frame(); + + /* finally, try to load each font there */ + { + FNT_Font* cur = face->fonts; + FNT_Font* limit = cur + font_count; + + + for ( ; cur < limit; cur++ ) + { + error = fnt_load_font( stream, cur ); + if ( error ) + goto Fail; + } + } + } + } + + Fail: + if ( error ) + fnt_done_fonts( face ); + + Exit: + return error; + } + + + static + void FNT_Done_Face( FNT_Face face ) + { + FT_Memory memory = FT_FACE_MEMORY( face ); + + + fnt_done_fonts( face ); + + FREE( face->root.available_sizes ); + face->root.num_fixed_sizes = 0; + } + + + static + FT_Error FNT_Init_Face( FT_Stream stream, + FNT_Face face, + FT_Int face_index, + FT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + FT_Memory memory = FT_FACE_MEMORY( face ); + + FT_UNUSED( num_params ); + FT_UNUSED( params ); + FT_UNUSED( face_index ); + + + /* try to load several fonts from a DLL */ + error = fnt_get_dll_fonts( face ); + if ( error ) + { + /* this didn't work, now try to load a single FNT font */ + FT_Memory memory = FT_FACE_MEMORY( face ); + FNT_Font* font; + + if ( ALLOC( face->fonts, sizeof ( *face->fonts ) ) ) + goto Exit; + + face->num_fonts = 1; + font = face->fonts; + + font->offset = 0; + font->fnt_size = stream->size; + + error = fnt_load_font( stream, font ); + if ( error ) + goto Fail; + } + + /* all right, one or more fonts were loaded; we now need to */ + /* fill the root FT_Face fields with relevant information */ + { + FT_Face root = FT_FACE( face ); + FNT_Font* fonts = face->fonts; + FNT_Font* limit = fonts + face->num_fonts; + FNT_Font* cur; + + + root->num_faces = 1; + root->face_flags = FT_FACE_FLAG_FIXED_SIZES | + FT_FACE_FLAG_HORIZONTAL; + + if ( fonts->header.avg_width == fonts->header.max_width ) + root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; + + if ( fonts->header.italic ) + root->style_flags |= FT_STYLE_FLAG_ITALIC; + + if ( fonts->header.weight >= 800 ) + root->style_flags |= FT_STYLE_FLAG_BOLD; + + /* Setup the `fixed_sizes' array */ + if ( ALLOC_ARRAY( root->available_sizes, face->num_fonts, + FT_Bitmap_Size ) ) + goto Fail; + + root->num_fixed_sizes = face->num_fonts; + + { + FT_Bitmap_Size* size = root->available_sizes; + + + for ( cur = fonts; cur < limit; cur++, size++ ) + { + size->width = cur->header.pixel_width; + size->height = cur->header.pixel_height; + } + } + + /* Setup the `charmaps' array */ + root->charmaps = &face->charmap_handle; + root->num_charmaps = 1; + + face->charmap.encoding = ft_encoding_unicode; + face->charmap.platform_id = 3; + face->charmap.encoding_id = 1; + face->charmap.face = root; + + face->charmap_handle = &face->charmap; + + root->charmap = face->charmap_handle; + + /* setup remaining flags */ + root->num_glyphs = fonts->header.last_char - + fonts->header.first_char + 1; + + root->family_name = (FT_String*)fonts->fnt_frame + + fonts->header.face_name_offset; + root->style_name = "Regular"; + + if ( root->style_flags & FT_STYLE_FLAG_BOLD ) + { + if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = "Bold Italic"; + else + root->style_name = "Bold"; + } + else if ( root->style_flags & FT_STYLE_FLAG_ITALIC ) + root->style_name = "Italic"; + } + + Fail: + if ( error ) + FNT_Done_Face( face ); + + Exit: + return error; + } + + + static + FT_Error FNT_Set_Pixel_Size( FNT_Size size ) + { + /* look up a font corresponding to the current pixel size */ + FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); + FNT_Font* cur = face->fonts; + FNT_Font* limit = cur + face->num_fonts; + + + size->font = 0; + for ( ; cur < limit; cur++ ) + { + /* we only compare the character height, as fonts used some strange */ + /* values */ + if ( cur->header.pixel_height == size->root.metrics.y_ppem ) + { + size->font = cur; + + size->root.metrics.ascender = cur->header.ascent * 64; + size->root.metrics.descender = ( cur->header.pixel_height - + cur->header.ascent ) * 64; + size->root.metrics.height = cur->header.pixel_height * 64; + break; + } + } + + return ( size->font ? FT_Err_Ok : FT_Err_Invalid_Argument ); + } + + + static + FT_UInt FNT_Get_Char_Index( FT_CharMap charmap, + FT_ULong char_code ) + { + FT_UInt result = char_code; + + + if ( charmap ) + { + FNT_Font* font = ((FNT_Face)charmap->face)->fonts; + FT_UInt first = font->header.first_char; + FT_UInt count = font->header.last_char - first + 1; + + + char_code -= first; + if ( char_code < count ) + result = char_code + 1; + else + result = 0; + } + + return result; + } + + + static + FT_Error FNT_Load_Glyph( FT_GlyphSlot slot, + FNT_Size size, + FT_UInt glyph_index, + FT_Int load_flags ) + { + FNT_Font* font = size->font; + FT_Error error = 0; + FT_Byte* p; + FT_Int len; + FT_Bitmap* bitmap = &slot->bitmap; + FT_ULong offset; + FT_Bool new_format; + + FT_UNUSED( slot ); + FT_UNUSED( load_flags ); + + + if ( !font ) + { + error = FT_Err_Invalid_Argument; + goto Exit; + } + + if ( glyph_index > 0 ) + glyph_index--; + else + glyph_index = font->header.default_char - font->header.first_char; + + new_format = font->header.version == 0x300; + len = new_format ? 6 : 4; + + /* jump to glyph entry */ + p = font->fnt_frame + 118 + len * glyph_index; + + bitmap->width = NEXT_ShortLE(p); + + if ( new_format ) + offset = NEXT_ULongLE(p); + else + offset = NEXT_UShortLE(p); + + /* jump to glyph data */ + p = font->fnt_frame + /* font->header.bits_offset */ + offset; + + /* allocate and build bitmap */ + { + FT_Memory memory = FT_FACE_MEMORY( slot->face ); + FT_Int pitch = ( bitmap->width + 7 ) >> 3; + FT_Byte* column; + FT_Byte* write; + + + bitmap->pitch = pitch; + bitmap->rows = font->header.pixel_height; + bitmap->pixel_mode = ft_pixel_mode_mono; + + if ( ALLOC( bitmap->buffer, pitch * bitmap->rows ) ) + goto Exit; + + column = (FT_Byte*)bitmap->buffer; + + for ( ; pitch > 0; pitch--, column++ ) + { + FT_Byte* limit = p + bitmap->rows; + + + for ( write = column; p < limit; p++, write += bitmap->pitch ) + write[0] = p[0]; + } + } + + slot->flags = ft_glyph_own_bitmap; + slot->bitmap_left = 0; + slot->bitmap_top = font->header.ascent; + slot->format = ft_glyph_format_bitmap; + + /* now set up metrics */ + slot->metrics.horiAdvance = bitmap->width << 6; + slot->metrics.horiBearingX = 0; + slot->metrics.horiBearingY = slot->bitmap_top << 6; + + slot->linearHoriAdvance = (FT_Fixed)bitmap->width << 16; + + Exit: + return error; + } + + + const FT_Driver_Class winfnt_driver_class = + { + { + ft_module_font_driver, + sizeof ( FT_DriverRec ), + + "winfonts", + 0x10000L, + 0x20000L, + + 0, + + (FT_Module_Constructor)0, + (FT_Module_Destructor) 0, + (FT_Module_Requester) 0 + }, + + sizeof( FNT_FaceRec ), + sizeof( FNT_SizeRec ), + sizeof( FT_GlyphSlotRec ), + + (FTDriver_initFace) FNT_Init_Face, + (FTDriver_doneFace) FNT_Done_Face, + (FTDriver_initSize) 0, + (FTDriver_doneSize) 0, + (FTDriver_initGlyphSlot)0, + (FTDriver_doneGlyphSlot)0, + + (FTDriver_setCharSizes) FNT_Set_Pixel_Size, + (FTDriver_setPixelSizes)FNT_Set_Pixel_Size, + + (FTDriver_loadGlyph) FNT_Load_Glyph, + (FTDriver_getCharIndex) FNT_Get_Char_Index, + + (FTDriver_getKerning) 0, + (FTDriver_attachFile) 0, + (FTDriver_getAdvances) 0 + }; + + +/* END */ diff --git a/subsys/win32k/freetype/src/winfonts/winfnt.h b/subsys/win32k/freetype/src/winfonts/winfnt.h new file mode 100644 index 0000000..eaf308b --- /dev/null +++ b/subsys/win32k/freetype/src/winfonts/winfnt.h @@ -0,0 +1,150 @@ +/***************************************************************************/ +/* */ +/* winfnt.h */ +/* */ +/* FreeType font driver for Windows FNT/FON files */ +/* */ +/* Copyright 1996-2000 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef WINFNT_H +#define WINFNT_H + +#include + + + typedef struct WinMZ_Header_ + { + FT_UShort magic; + /* skipped content */ + FT_UShort lfanew; + + } WinMZ_Header; + + + typedef struct WinNE_Header_ + { + FT_UShort magic; + /* skipped content */ + FT_UShort resource_tab_offset; + FT_UShort rname_tab_offset; + + } WinNE_Header; + + + typedef struct WinNameInfo_ + { + FT_UShort offset; + FT_UShort length; + FT_UShort flags; + FT_UShort id; + FT_UShort handle; + FT_UShort usage; + + } WinNameInfo; + + + typedef struct WinResourceInfo_ + { + FT_UShort type_id; + FT_UShort count; + + } WinResourceInfo; + + +#define WINFNT_MZ_MAGIC 0x5A4D +#define WINFNT_NE_MAGIC 0x454E + + + typedef struct WinFNT_Header_ + { + FT_UShort version; + FT_ULong file_size; + FT_Byte copyright[60]; + FT_UShort file_type; + FT_UShort nominal_point_size; + FT_UShort vertical_resolution; + FT_UShort horizontal_resolution; + FT_UShort ascent; + FT_UShort internal_leading; + FT_UShort external_leading; + FT_Byte italic; + FT_Byte underline; + FT_Byte strike_out; + FT_UShort weight; + FT_Byte charset; + FT_UShort pixel_width; + FT_UShort pixel_height; + FT_Byte pitch_and_family; + FT_UShort avg_width; + FT_UShort max_width; + FT_Byte first_char; + FT_Byte last_char; + FT_Byte default_char; + FT_Byte break_char; + FT_UShort bytes_per_row; + FT_ULong device_offset; + FT_ULong face_name_offset; + FT_ULong bits_pointer; + FT_ULong bits_offset; + FT_Byte reserved; + FT_ULong flags; + FT_UShort A_space; + FT_UShort B_space; + FT_UShort C_space; + FT_UShort color_table_offset; + FT_Byte reserved2[4]; + + } WinFNT_Header; + + + typedef struct FNT_Font_ + { + FT_ULong offset; + FT_Int size_shift; + + WinFNT_Header header; + + FT_Byte* fnt_frame; + FT_ULong fnt_size; + + } FNT_Font; + + + typedef struct FNT_SizeRec_ + { + FT_SizeRec root; + FNT_Font* font; + + } FNT_SizeRec, *FNT_Size; + + + typedef struct FNT_FaceRec_ + { + FT_FaceRec root; + + FT_UInt num_fonts; + FNT_Font* fonts; + + FT_CharMap charmap_handle; + FT_CharMapRec charmap; /* a single charmap per face */ + + } FNT_FaceRec, *FNT_Face; + + + FT_EXPORT_VAR( const FT_Driver_Class ) winfnt_driver_class; + + +#endif /* WINFNT_H */ + + +/* END */ diff --git a/subsys/win32k/include/callback.h b/subsys/win32k/include/callback.h new file mode 100644 index 0000000..b620bee --- /dev/null +++ b/subsys/win32k/include/callback.h @@ -0,0 +1,32 @@ +#ifndef __SUBSYS_WIN32K_INCLUDE_CALLBACK_H +#define __SUBSYS_WIN32K_INCLUDE_CALLBACK_H + +LRESULT STDCALL +W32kCallWindowProc(WNDPROC Proc, + HWND Wnd, + UINT Message, + WPARAM wParam, + LPARAM lParam); +LRESULT STDCALL +W32kCallTrampolineWindowProc(WNDPROC Proc, + HWND Wnd, + UINT Message, + WPARAM wParam, + LPARAM lParam); +LRESULT STDCALL +W32kSendNCCREATEMessage(HWND Wnd, CREATESTRUCTW* CreateStruct); +LRESULT STDCALL +W32kSendCREATEMessage(HWND Wnd, CREATESTRUCTW* CreateStruct); +VOID STDCALL +W32kCallSentMessageCallback(SENDASYNCPROC CompletionCallback, + HWND hWnd, + UINT Msg, + ULONG_PTR CompletionCallbackContext, + LRESULT Result); +LRESULT STDCALL +W32kSendNCCALCSIZEMessage(HWND Wnd, BOOL Validate, PRECT Rect, + NCCALCSIZE_PARAMS* Params); +LRESULT STDCALL +W32kSendGETMINMAXINFOMessage(HWND Wnd, MINMAXINFO* MinMaxInfo); + +#endif /* __SUBSYS_WIN32K_INCLUDE_CALLBACK_H */ diff --git a/subsys/win32k/include/class.h b/subsys/win32k/include/class.h new file mode 100644 index 0000000..7a07cc5 --- /dev/null +++ b/subsys/win32k/include/class.h @@ -0,0 +1,45 @@ +#ifndef __WIN32K_CLASS_H +#define __WIN32K_CLASS_H + +#include +#include +#include + +#define IS_ATOM(x) \ + (((ULONG_PTR)(x) > 0x0) && ((ULONG_PTR)(x) < 0x10000)) + +typedef struct _WNDCLASS_OBJECT +{ + WNDCLASSEX Class; + BOOL Unicode; + LIST_ENTRY ListEntry; +} WNDCLASS_OBJECT, *PWNDCLASS_OBJECT; + +NTSTATUS +InitClassImpl(VOID); + +NTSTATUS +CleanupClassImpl(VOID); + +NTSTATUS +ClassReferenceClassByName(PW32PROCESS Process, + PWNDCLASS_OBJECT *Class, + LPWSTR ClassName); + +NTSTATUS +ClassReferenceClassByAtom(PWNDCLASS_OBJECT *Class, + RTL_ATOM ClassAtom); + +NTSTATUS +ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class, + LPWSTR ClassNameOrAtom); +PWNDCLASS_OBJECT +W32kCreateClass(LPWNDCLASSEX lpwcx, + BOOL bUnicodeClass); +struct _WINDOW_OBJECT; +ULONG +W32kGetClassLong(struct _WINDOW_OBJECT* WindowObject, ULONG Offset); + +#endif /* __WIN32K_CLASS_H */ + +/* EOF */ diff --git a/subsys/win32k/include/copybits.h b/subsys/win32k/include/copybits.h new file mode 100644 index 0000000..469c68a --- /dev/null +++ b/subsys/win32k/include/copybits.h @@ -0,0 +1,9 @@ +#ifndef __WIN32K_COPYBITS_H +#define __WIN32K_COPYBITS_H + +BOOLEAN CopyBitsCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, + SURFGDI *DestGDI, SURFGDI *SourceGDI, + PRECTL DestRect, POINTL *SourcePoint, + ULONG Delta, XLATEOBJ *ColorTranslation); + +#endif /* __WIN32K_COPYBITS_H */ diff --git a/subsys/win32k/include/dce.h b/subsys/win32k/include/dce.h new file mode 100644 index 0000000..54c76b3 --- /dev/null +++ b/subsys/win32k/include/dce.h @@ -0,0 +1,48 @@ +#ifndef __WIN32K_DCE_H +#define __WIN32K_DCE_H + +/* Ported from WINE by Jason Filby */ + +#include + +typedef HANDLE HDCE; + +/* DC hook codes */ +#define DCHC_INVALIDVISRGN 0x0001 +#define DCHC_DELETEDC 0x0002 + +#define DCHF_INVALIDATEVISRGN 0x0001 +#define DCHF_VALIDATEVISRGN 0x0002 + +typedef enum +{ + DCE_CACHE_DC, /* This is a cached DC (allocated by USER) */ + DCE_CLASS_DC, /* This is a class DC (style CS_CLASSDC) */ + DCE_WINDOW_DC /* This is a window DC (style CS_OWNDC) */ +} DCE_TYPE, *PDCE_TYPE; + +typedef struct tagDCE +{ + struct tagDCE *next; + HDC hDC; + HWND hwndCurrent; + HWND hwndDC; + HRGN hClipRgn; + DCE_TYPE type; + DWORD DCXFlags; +} DCE, *PDCE; + + +#define DCEOBJ_AllocDCE() \ + ((HDCE) GDIOBJ_AllocObj (sizeof (DCE), GO_DCE_MAGIC)) +#define DCEOBJ_FreeDCE(hDCE) GDIOBJ_FreeObj((HGDIOBJ)hDCE, GO_DCE_MAGIC, GDIOBJFLAG_DEFAULT) +#define DCEOBJ_LockDCE(hDCE) ((PDCE)GDIOBJ_LockObj((HGDIOBJ)hDCE, GO_DCE_MAGIC)) +#define DCEOBJ_UnlockDCE(hDCE) GDIOBJ_UnlockObj((HGDIOBJ)hDCE, GO_DCE_MAGIC) + +PDCE DCE_AllocDCE(HWND hWnd, DCE_TYPE type); +PDCE DCE_FreeDCE(PDCE dce); +VOID DCE_FreeWindowDCE(HWND); +INT DCE_ExcludeRgn(HDC, HWND, HRGN); +BOOL DCE_InvalidateDCE(HWND, const PRECTL); + +#endif diff --git a/subsys/win32k/include/dib.h b/subsys/win32k/include/dib.h new file mode 100644 index 0000000..54ef5c5 --- /dev/null +++ b/subsys/win32k/include/dib.h @@ -0,0 +1,6 @@ +#ifndef __WIN32K_DIB_H +#define __WIN32K_DIB_H + +int DIB_GetDIBWidthBytes(int width, int depth); + +#endif /* __WIN32K_DIB_H */ diff --git a/subsys/win32k/include/eng.h b/subsys/win32k/include/eng.h new file mode 100644 index 0000000..b70f8fc --- /dev/null +++ b/subsys/win32k/include/eng.h @@ -0,0 +1,6 @@ +#ifndef __WIN32K_ENG_H +#define __WIN32K_ENG_H + +BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2); + +#endif /* __WIN32K_ENG_H */ diff --git a/subsys/win32k/include/error.h b/subsys/win32k/include/error.h new file mode 100644 index 0000000..2ef7d83 --- /dev/null +++ b/subsys/win32k/include/error.h @@ -0,0 +1,14 @@ +#ifndef __WIN32K_ERROR_H +#define __WIN32K_ERROR_H + +VOID +SetLastNtError( + NTSTATUS Status); + +VOID +SetLastWin32Error( + DWORD Status); + +#endif /* __WIN32K_ERROR_H */ + +/* EOF */ diff --git a/subsys/win32k/include/guicheck.h b/subsys/win32k/include/guicheck.h new file mode 100644 index 0000000..60fca50 --- /dev/null +++ b/subsys/win32k/include/guicheck.h @@ -0,0 +1,14 @@ +#ifndef __WIN32K_GUICHECK_H +#define __WIN32K_GUICHECK_H + +#include +#include + +VOID +W32kGuiCheck(VOID); +VOID +W32kGraphicsCheck(VOID); + +#endif /* __WIN32K_GUICHECK_H */ + +/* EOF */ diff --git a/subsys/win32k/include/input.h b/subsys/win32k/include/input.h new file mode 100644 index 0000000..1c83e09 --- /dev/null +++ b/subsys/win32k/include/input.h @@ -0,0 +1,7 @@ +#ifndef __WIN32K_MOUSE_H +#define __WIN32K_MOUSE_H + +NTSTATUS +InitInputImpl(VOID); + +#endif /* __WIN32K_MOUSE_H */ diff --git a/subsys/win32k/include/mouse.h b/subsys/win32k/include/mouse.h new file mode 100644 index 0000000..abd734e --- /dev/null +++ b/subsys/win32k/include/mouse.h @@ -0,0 +1,8 @@ +#ifndef __WIN32K_MOUSE_H +#define __WIN32K_MOUSE_H + +INT MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2); +INT MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI); +VOID EnableMouse(HDC hDisplayDC); + +#endif /* __WIN32K_MOUSE_H */ diff --git a/subsys/win32k/include/msgqueue.h b/subsys/win32k/include/msgqueue.h new file mode 100644 index 0000000..e2a3394 --- /dev/null +++ b/subsys/win32k/include/msgqueue.h @@ -0,0 +1,128 @@ +#ifndef __WIN32K_MSGQUEUE_H +#define __WIN32K_MSGQUEUE_H + +#include + +typedef struct _USER_MESSAGE +{ + LIST_ENTRY ListEntry; + MSG Msg; +} USER_MESSAGE, *PUSER_MESSAGE; + +struct _USER_MESSAGE_QUEUE; + +typedef struct _USER_SENT_MESSAGE +{ + LIST_ENTRY ListEntry; + MSG Msg; + PKEVENT CompletionEvent; + LRESULT* Result; + struct _USER_MESSAGE_QUEUE* CompletionQueue; + SENDASYNCPROC CompletionCallback; + ULONG_PTR CompletionCallbackContext; +} USER_SENT_MESSAGE, *PUSER_SENT_MESSAGE; + +typedef struct _USER_SENT_MESSAGE_NOTIFY +{ + SENDASYNCPROC CompletionCallback; + ULONG_PTR CompletionCallbackContext; + LRESULT Result; + HWND hWnd; + UINT Msg; + LIST_ENTRY ListEntry; +} USER_SENT_MESSAGE_NOTIFY, *PUSER_SENT_MESSAGE_NOTIFY; + +typedef struct _USER_MESSAGE_QUEUE +{ + /* Queue of messages sent to the queue. */ + LIST_ENTRY SentMessagesListHead; + /* Queue of messages posted to the queue. */ + LIST_ENTRY PostedMessagesListHead; + /* Queue of sent-message notifies for the queue. */ + LIST_ENTRY NotifyMessagesListHead; + /* Queue for hardware messages for the queue. */ + LIST_ENTRY HardwareMessagesListHead; + /* Lock for the queue. */ + FAST_MUTEX Lock; + /* True if a WM_QUIT message is pending. */ + BOOLEAN QuitPosted; + /* The quit exit code. */ + ULONG QuitExitCode; + /* Set if there are new messages in any of the queues. */ + KEVENT NewMessages; + /* FIXME: Unknown. */ + ULONG QueueStatus; + /* Current window with focus for this queue. */ + HWND FocusWindow; + /* True if a window needs painting. */ + BOOLEAN PaintPosted; + /* Count of paints pending. */ + ULONG PaintCount; + /* Current active window for this queue. */ + HWND ActiveWindow; + /* Current capture window for this queue. */ + HWND CaptureWindow; +} USER_MESSAGE_QUEUE, *PUSER_MESSAGE_QUEUE; + +VOID +MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE Message); +VOID +MsqInitializeMessage(PUSER_MESSAGE Message, + LPMSG Msg); +PUSER_MESSAGE +MsqCreateMessage(LPMSG Msg); +VOID +MsqDestroyMessage(PUSER_MESSAGE Message); +VOID +MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_MESSAGE Message); +BOOLEAN +MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, + IN BOOLEAN Hardware, + IN BOOLEAN Remove, + IN HWND Wnd, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT PUSER_MESSAGE* Message); +VOID +MsqInitializeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue); +VOID +MsqFreeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue); +PUSER_MESSAGE_QUEUE +MsqCreateMessageQueue(VOID); +VOID +MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue); +PUSER_MESSAGE_QUEUE +MsqGetHardwareMessageQueue(VOID); +NTSTATUS +MsqWaitForNewMessage(PUSER_MESSAGE_QUEUE MessageQueue); +NTSTATUS +MsqInitializeImpl(VOID); +BOOLEAN +MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue); +NTSTATUS +MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue); +VOID +MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE_NOTIFY NotifyMessage); +VOID +MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue); +VOID +MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue); +LRESULT STDCALL +W32kSendMessage(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + BOOL KernelMessage); +VOID +MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); +VOID +MsqInsertSystemMessage(MSG* Msg); + +#define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF)) + +#endif /* __WIN32K_MSGQUEUE_H */ + +/* EOF */ diff --git a/subsys/win32k/include/object.h b/subsys/win32k/include/object.h new file mode 100644 index 0000000..c8762c9 --- /dev/null +++ b/subsys/win32k/include/object.h @@ -0,0 +1,117 @@ +#ifndef __WIN32K_OBJECT_H +#define __WIN32K_OBJECT_H + +#include + +typedef enum { + otUnknown = 0, + otClass, + otWindow +} USER_OBJECT_TYPE; + +typedef struct _USER_OBJECT_HEADER +/* + * Header for user object + */ +{ + USER_OBJECT_TYPE Type; + LONG HandleCount; + LONG RefCount; + CSHORT Size; +} USER_OBJECT_HEADER, *PUSER_OBJECT_HEADER; + +typedef struct _USER_HANDLE +{ + PVOID ObjectBody; +} USER_HANDLE, *PUSER_HANDLE; + +#define HANDLE_BLOCK_ENTRIES ((PAGE_SIZE-sizeof(LIST_ENTRY))/sizeof(USER_HANDLE)) + +typedef struct _USER_HANDLE_BLOCK +{ + LIST_ENTRY ListEntry; + USER_HANDLE Handles[HANDLE_BLOCK_ENTRIES]; +} USER_HANDLE_BLOCK, *PUSER_HANDLE_BLOCK; + +typedef struct _USER_HANDLE_TABLE +{ + LIST_ENTRY ListHead; + FAST_MUTEX ListLock; +} USER_HANDLE_TABLE, *PUSER_HANDLE_TABLE; + + +ULONG +ObmGetReferenceCount( + PVOID ObjectBody); + +ULONG +ObmGetHandleCount( + PVOID ObjectBody); + +VOID +ObmReferenceObject( + PVOID ObjectBody); + +VOID +ObmDereferenceObject( + PVOID ObjectBody); + +NTSTATUS +ObmReferenceObjectByPointer( + PVOID ObjectBody, + USER_OBJECT_TYPE ObjectType); + +PVOID +ObmCreateObject( + PUSER_HANDLE_TABLE HandleTable, + PHANDLE Handle, + USER_OBJECT_TYPE ObjectType, + ULONG ObjectSize); + +NTSTATUS +ObmCreateHandle( + PUSER_HANDLE_TABLE HandleTable, + PVOID ObjectBody, + PHANDLE HandleReturn); + +NTSTATUS +ObmReferenceObjectByHandle( + PUSER_HANDLE_TABLE HandleTable, + HANDLE Handle, + USER_OBJECT_TYPE ObjectType, + PVOID* Object); + +NTSTATUS +ObmCloseHandle( + PUSER_HANDLE_TABLE HandleTable, + HANDLE Handle); + +VOID +ObmInitializeHandleTable( + PUSER_HANDLE_TABLE HandleTable); + +VOID +ObmFreeHandleTable( + PUSER_HANDLE_TABLE HandleTable); + +PUSER_HANDLE_TABLE +ObmCreateHandleTable(VOID); + +VOID +ObmDestroyHandleTable( + PUSER_HANDLE_TABLE HandleTable); + +ULONG CreateGDIHandle(ULONG InternalSize, ULONG UserSize); +VOID FreeGDIHandle(ULONG Handle); + +PVOID AccessUserObject(ULONG Handle); +PVOID AccessInternalObject(ULONG Handle); + +PVOID AccessInternalObjectFromUserObject(PVOID UserObject); +ULONG AccessHandleFromUserObject(PVOID UserObject); + +VOID InitEngHandleTable( void ); + +#endif /* __WIN32K_OBJECT_H */ + +/* EOF */ diff --git a/subsys/win32k/include/paint.h b/subsys/win32k/include/paint.h new file mode 100644 index 0000000..379fc36 --- /dev/null +++ b/subsys/win32k/include/paint.h @@ -0,0 +1,6 @@ +#ifndef __WIN32K_PAINT_H +#define __WIN32K_PAINT_H + +BOOL FillSolid(SURFOBJ *Surface, PRECTL Dimensions, ULONG iColor); + +#endif /* __WIN32K_DIB_H */ diff --git a/subsys/win32k/include/painting.h b/subsys/win32k/include/painting.h new file mode 100644 index 0000000..761610c --- /dev/null +++ b/subsys/win32k/include/painting.h @@ -0,0 +1,22 @@ +#ifndef __WIN32K_PAINTING_H +#define __WIN32K_PAINTING_H + +#include +#include +#include +#include + +/* PaintRedrawWindow() control flags */ +#define RDW_EX_USEHRGN 0x0001 +#define RDW_EX_DELETEHRGN 0x0002 +#define RDW_EX_XYWINDOW 0x0004 +#define RDW_EX_TOPFRAME 0x0010 +#define RDW_EX_DELAY_NCPAINT 0x0020 + +HWND STDCALL +PaintingFindWinToRepaint(HWND hWnd, PW32THREAD Thread); +BOOL STDCALL +PaintHaveToDelayNCPaint(PWINDOW_OBJECT Window, ULONG Flags); +HRGN STDCALL +PaintUpdateNCRegion(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags); +#endif /* __WIN32K_PAINTING_H */ diff --git a/subsys/win32k/include/palette.h b/subsys/win32k/include/palette.h new file mode 100644 index 0000000..48bcb5a --- /dev/null +++ b/subsys/win32k/include/palette.h @@ -0,0 +1,25 @@ +#ifndef __WIN32K_PALETTE_H +#define __WIN32K_PALETTE_H + +#define PALETTE_FIXED 0x0001 /* read-only colormap - have to use XAllocColor (if not virtual) */ +#define PALETTE_VIRTUAL 0x0002 /* no mapping needed - pixel == pixel color */ + +#define PALETTE_PRIVATE 0x1000 /* private colormap, identity mapping */ +#define PALETTE_WHITESET 0x2000 + +typedef struct { + int shift; + int scale; + int max; +} ColorShifts; + +static ColorShifts PALETTE_PRed = {0,0,0}; +static ColorShifts PALETTE_LRed = {0,0,0}; +static ColorShifts PALETTE_PGreen = {0,0,0}; +static ColorShifts PALETTE_LGreen = {0,0,0}; +static ColorShifts PALETTE_PBlue = {0,0,0}; +static ColorShifts PALETTE_LBlue = {0,0,0}; +static int PALETTE_Graymax = 0; +static int palette_size; + +#endif /* __WIN32K_PALETTE_H */ diff --git a/subsys/win32k/include/rect.h b/subsys/win32k/include/rect.h new file mode 100644 index 0000000..d7c923f --- /dev/null +++ b/subsys/win32k/include/rect.h @@ -0,0 +1,12 @@ +BOOL STDCALL +W32kUnionRect(PRECT Dest, const RECT* Src1, const RECT* Src2); +BOOL STDCALL +W32kSetRect(PRECT Rect, INT left, INT top, INT right, INT bottom); +BOOL STDCALL +W32kSetEmptyRect(PRECT Rect); +BOOL STDCALL +W32kIsEmptyRect(PRECT Rect); +BOOL STDCALL +W32kIntersectRect(PRECT Dest, const RECT* Src1, const RECT* Src2); +BOOL +W32kOffsetRect(LPRECT Rect, INT x, INT y); diff --git a/subsys/win32k/include/surface.h b/subsys/win32k/include/surface.h new file mode 100644 index 0000000..8374b50 --- /dev/null +++ b/subsys/win32k/include/surface.h @@ -0,0 +1,6 @@ +#ifndef __WIN32K_SURFACE_H +#define __WIN32K_SURFACE_H + +INT BitsPerFormat(ULONG Format); + +#endif /* __WIN32K_SURFACE_H */ diff --git a/subsys/win32k/include/window.h b/subsys/win32k/include/window.h new file mode 100644 index 0000000..66f123c --- /dev/null +++ b/subsys/win32k/include/window.h @@ -0,0 +1,116 @@ +#ifndef __WIN32K_WINDOW_H +#define __WIN32K_WINDOW_H + +#include +#include +#include +#include +#include +#include + +typedef struct _PROPERTY +{ + LIST_ENTRY PropListEntry; + HANDLE Data; + ATOM Atom; +} PROPERTY, *PPROPERTY; + +VOID +WinPosSetupInternalPos(VOID); + +typedef struct _WINDOW_OBJECT +{ + /* Pointer to the window class. */ + PWNDCLASS_OBJECT Class; + /* Extended style. */ + DWORD ExStyle; + /* Window name. */ + UNICODE_STRING WindowName; + /* Style. */ + DWORD Style; + /* Initial window position. */ + INT x; + INT y; + INT Width; + INT Height; + /* Parent window handle. */ + HWND ParentHandle; + /* Window menu handle. */ + HMENU Menu; + /* Handle of the module that created the window. */ + HINSTANCE Instance; + /* Unknown. */ + LPVOID Parameters; + /* Entry in the thread's list of windows. */ + LIST_ENTRY ListEntry; + /* Entry in the global list of windows. */ + LIST_ENTRY DesktopListEntry; + /* Pointer to the extra data associated with the window. */ + PULONG ExtraData; + /* Size of the extra data associated with the window. */ + ULONG ExtraDataSize; + /* Position of the window. */ + RECT WindowRect; + /* Position of the window's client area. */ + RECT ClientRect; + /* Handle for the window. */ + HANDLE Self; + /* Window flags. */ + ULONG Flags; + /* FIXME: Don't know. */ + UINT IDMenu; + /* Handle of region of the window to be updated. */ + HANDLE UpdateRegion; + /* Pointer to the message queue associated with the window. */ + PUSER_MESSAGE_QUEUE MessageQueue; + /* Head of the list of child windows. */ + LIST_ENTRY ChildrenListHead; + /* Lock for the list of child windows. */ + FAST_MUTEX ChildrenListLock; + /* Entry in the parent's list of child windows. */ + LIST_ENTRY SiblingListEntry; + /* Entry in the list of thread windows. */ + LIST_ENTRY ThreadListEntry; + /* Pointer to the parent window. */ + struct _WINDOW_OBJECT* Parent; + /* DC Entries (DCE) */ + PDCE Dce; + /* Property list head.*/ + LIST_ENTRY PropListHead; +} WINDOW_OBJECT, *PWINDOW_OBJECT; + +/* Window flags. */ +#define WINDOWOBJECT_NEED_SIZE (0x00000001) +#define WINDOWOBJECT_NEED_BEGINPAINT (0x00000002) +#define WINDOWOBJECT_NEED_ERASEBACKGRD (0x00000004) +#define WINDOWOBJECT_NEED_NCPAINT (0x00000008) +#define WINDOWOBJECT_NEED_INTERNALPAINT (0x00000010) +#define WINDOWOBJECT_RESTOREMAX (0x00000020) + +NTSTATUS +InitWindowImpl(VOID); +NTSTATUS +CleanupWindowImpl(VOID); +VOID +W32kGetClientRect(PWINDOW_OBJECT WindowObject, PRECT Rect); +PWINDOW_OBJECT +W32kGetWindowObject(HWND hWnd); +VOID +W32kReleaseWindowObject(PWINDOW_OBJECT Window); +HWND STDCALL +W32kCreateDesktopWindow(PWINSTATION_OBJECT WindowStation, + PWNDCLASS_OBJECT DesktopClass, + ULONG Width, ULONG Height); +BOOL +W32kIsDesktopWindow(HWND hWnd); +HWND +W32kGetActiveWindow(VOID); +BOOL +W32kIsWindowVisible(HWND Wnd); +BOOL +W32kIsChildWindow(HWND Parent, HWND Child); +HWND W32kGetDesktopWindow(); + +#endif /* __WIN32K_WINDOW_H */ + +/* EOF */ diff --git a/subsys/win32k/include/winpos.h b/subsys/win32k/include/winpos.h new file mode 100644 index 0000000..b449693 --- /dev/null +++ b/subsys/win32k/include/winpos.h @@ -0,0 +1,19 @@ +/* Undocumented flags. */ +#define SWP_NOCLIENTMOVE 0x0800 +#define SWP_NOCLIENTSIZE 0x1000 + +LRESULT +WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect); +UINT +WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos, + POINT* MinTrack, POINT* MaxTrack); +UINT +WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos); +BOOLEAN +WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, + INT cy, UINT flags); +BOOLEAN +WinPosShowWindow(HWND Wnd, INT Cmd); +USHORT +WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, + PWINDOW_OBJECT* Window); diff --git a/subsys/win32k/include/winsta.h b/subsys/win32k/include/winsta.h new file mode 100644 index 0000000..96eef24 --- /dev/null +++ b/subsys/win32k/include/winsta.h @@ -0,0 +1,44 @@ +#ifndef __WIN32K_WINSTA_H +#define __WIN32K_WINSTA_H + +#include +#include +#include +#include + +#define PROCESS_WINDOW_STATION() \ + ((HWINSTA)(IoGetCurrentProcess()->Win32WindowStation)) + +#define SET_PROCESS_WINDOW_STATION(WinSta) \ + ((IoGetCurrentProcess()->Win32WindowStation) = (PVOID)(WinSta)) + + +NTSTATUS +InitWindowStationImpl(VOID); + +NTSTATUS +CleanupWindowStationImpl(VOID); + +NTSTATUS +ValidateWindowStationHandle(HWINSTA WindowStation, + KPROCESSOR_MODE AccessMode, + ACCESS_MASK DesiredAccess, + PWINSTATION_OBJECT *Object); + +NTSTATUS +ValidateDesktopHandle(HDESK Desktop, + KPROCESSOR_MODE AccessMode, + ACCESS_MASK DesiredAccess, + PDESKTOP_OBJECT *Object); +LRESULT CALLBACK +W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +PDESKTOP_OBJECT +W32kGetActiveDesktop(VOID); +VOID +W32kInitializeDesktopGraphics(VOID); +HDC +W32kGetScreenDC(VOID); + +#endif /* __WIN32K_WINSTA_H */ + +/* EOF */ diff --git a/subsys/win32k/ldr/.cvsignore b/subsys/win32k/ldr/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/ldr/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/ldr/loader.c b/subsys/win32k/ldr/loader.c new file mode 100644 index 0000000..4540f53 --- /dev/null +++ b/subsys/win32k/ldr/loader.c @@ -0,0 +1,39 @@ +/* $Id$ + * + */ + +#include +#include + +HANDLE +STDCALL +EngLoadImage (LPWSTR DriverName) +{ + SYSTEM_LOAD_IMAGE GdiDriverInfo; + NTSTATUS Status; + + RtlInitUnicodeString(&GdiDriverInfo.ModuleName, DriverName); + Status = ZwSetSystemInformation(SystemLoadImage, &GdiDriverInfo, sizeof(SYSTEM_LOAD_IMAGE)); + if (!NT_SUCCESS(Status)) return NULL; + + return (HANDLE)GdiDriverInfo.ModuleBase; +} + + +HANDLE +STDCALL +EngLoadModule(LPWSTR ModuleName) +{ + SYSTEM_LOAD_IMAGE GdiDriverInfo; + NTSTATUS Status; + + // FIXME: should load as readonly + + RtlInitUnicodeString (&GdiDriverInfo.ModuleName, ModuleName); + Status = ZwSetSystemInformation (SystemLoadImage, &GdiDriverInfo, sizeof(SYSTEM_LOAD_IMAGE)); + if (!NT_SUCCESS(Status)) return NULL; + + return (HANDLE)GdiDriverInfo.ModuleBase; +} + +/* EOF */ diff --git a/subsys/win32k/main/.cvsignore b/subsys/win32k/main/.cvsignore new file mode 100644 index 0000000..b1ce1ec --- /dev/null +++ b/subsys/win32k/main/.cvsignore @@ -0,0 +1,4 @@ +svctab.c +*.d +*.o +*.sym diff --git a/subsys/win32k/main/dllmain.c b/subsys/win32k/main/dllmain.c new file mode 100644 index 0000000..63a475c --- /dev/null +++ b/subsys/win32k/main/dllmain.c @@ -0,0 +1,117 @@ +/* $Id$ + * + * Entry Point for win32k.sys + */ + +#undef WIN32_LEAN_AND_MEAN +#define WIN32_NO_STATUS +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +//#define NDEBUG +#include + +extern SSDT Win32kSSDT[]; +extern SSPT Win32kSSPT[]; +extern ULONG Win32kNumberOfSysCalls; + +/* + * This definition doesn't work + */ +// WINBOOL STDCALL DllMain(VOID) +NTSTATUS +STDCALL +DllMain ( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + NTSTATUS Status; + BOOLEAN Result; + + /* + * Register user mode call interface + * (system service table index = 1) + */ + Result = KeAddSystemServiceTable (Win32kSSDT, NULL, + Win32kNumberOfSysCalls, Win32kSSPT, 1); + if (Result == FALSE) + { + DbgPrint("Adding system services failed!\n"); + return STATUS_UNSUCCESSFUL; + } + + /* + * Register our per-process and per-thread structures. + */ + PsEstablishWin32Callouts(0, 0, 0, 0, sizeof(W32THREAD), sizeof(W32PROCESS)); + + WinPosSetupInternalPos(); + + Status = InitWindowStationImpl(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to initialize window station implementation!\n"); + return STATUS_UNSUCCESSFUL; + } + + Status = InitClassImpl(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to initialize window class implementation!\n"); + return STATUS_UNSUCCESSFUL; + } + + Status = InitWindowImpl(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to initialize window implementation!\n"); + return STATUS_UNSUCCESSFUL; + } + + Status = InitInputImpl(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to initialize input implementation.\n"); + return(Status); + } + + Status = MsqInitializeImpl(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to initialize message queue implementation.\n"); + return(Status); + } + + return STATUS_SUCCESS; +} + + +BOOLEAN +STDCALL +W32kInitialize (VOID) +{ + DPRINT("in W32kInitialize\n"); + InitGdiObjectHandleTable (); + + // Create surface used to draw the internal font onto + CreateCellCharSurface(); + + // Create stock objects, ie. precreated objects commonly used by win32 applications + CreateStockObjects(); + + // Initialize FreeType library + if(!InitFontSupport()) return FALSE; + + return TRUE; +} + +/* EOF */ diff --git a/subsys/win32k/main/svctabm.c b/subsys/win32k/main/svctabm.c new file mode 100644 index 0000000..f795547 --- /dev/null +++ b/subsys/win32k/main/svctabm.c @@ -0,0 +1,17 @@ +/* $Id$ + * + * Entry Point for win32k.sys + */ + +#undef WIN32_LEAN_AND_MEAN +#define WIN32_NO_STATUS +#include +#include +#include + +/* + * NOTE: the table is actually in the file ./svctab.c, + * generated by iface/addsys/mktab.c + w32ksvc.db + */ +#include "svctab.c" + diff --git a/subsys/win32k/makefile b/subsys/win32k/makefile new file mode 100644 index 0000000..1544ef2 --- /dev/null +++ b/subsys/win32k/makefile @@ -0,0 +1,91 @@ +# $Id$ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = export_driver + +TARGET_NAME = win32k + +TARGET_BASE = 0x0 + +TARGET_ENTRY = _DllMain@8 + +include $(PATH_TO_TOP)/config + +ifeq ($(DBG), 1) +CFLAGS_DBG := -g +else +CFLAGS_DBG := +endif + +TARGET_CFLAGS = $(CFLAGS_DBG) -I$(PATH_TO_TOP)/ntoskrnl/include -DUNICODE -Wall + +ENG_OBJECTS= eng/debug.o eng/mem.o eng/brush.o eng/bitblt.o eng/clip.o \ + eng/copybits.o eng/device.o eng/handle.o eng/lineto.o eng/paint.o \ + eng/palette.o eng/surface.o eng/xlate.o eng/transblt.o eng/mouse.o +MAIN_OBJECTS = main/dllmain.o main/svctabm.o +MISC_OBJECTS = misc/driver.o misc/error.o misc/math.o misc/object.o +LDR_OBJECTS = ldr/loader.o +NTUSER_OBJECTS = ntuser/class.o ntuser/guicheck.o ntuser/hook.o \ + ntuser/message.o ntuser/msgqueue.o ntuser/stubs.o \ + ntuser/userobj.o ntuser/window.o ntuser/winsta.o \ + ntuser/input.o ntuser/keyboard.o ntuser/callback.o \ + ntuser/winpos.o ntuser/painting.o ntuser/metric.o \ + ntuser/windc.o ntuser/prop.o +OBJECTS_OBJECTS = objects/bitmaps.o objects/brush.o objects/cliprgn.o \ + objects/color.o objects/coord.o objects/dc.o \ + objects/fillshap.o objects/gdiobj.o objects/icm.o \ + objects/line.o objects/metafile.o objects/paint.o \ + objects/path.o objects/pen.o objects/print.o \ + objects/region.o objects/text.o objects/wingl.o \ + objects/bezier.o objects/objconv.o objects/dib.o \ + objects/palette.o objects/rect.o +DIB_OBJECTS = dib/dib1bpp.o dib/dib4bpp.o dib/dib24bpp.o +FREETYPE_OBJECTS = freetype/ctype.o freetype/grfont.o \ + freetype/src/base/ftsystem.o freetype/src/base/ftdebug.o \ + freetype/src/base/ftinit.o freetype/src/base/ftbase.o \ + freetype/src/base/ftglyph.o freetype/src/base/ftmm.o \ + freetype/src/autohint/autohint.o freetype/src/cff/cff.o \ + freetype/src/cid/type1cid.o freetype/src/psnames/psnames.o \ + freetype/src/winfonts/winfnt.o freetype/src/raster1/raster1.o \ + freetype/src/sfnt/sfnt.o freetype/src/smooth/smooth.o \ + freetype/src/truetype/truetype.o freetype/src/type1z/type1z.o +STUBS_OBJECTS = stubs/stubs.o + +TARGET_OBJECTS = \ + $(ENG_OBJECTS) $(MAIN_OBJECTS) $(MISC_OBJECTS) $(LDR_OBJECTS) \ + $(NTUSER_OBJECTS) $(OBJECTS_OBJECTS) $(STUBS_OBJECTS) \ + $(MATH_OBJECTS) $(FLOAT_OBJECTS) $(FREETYPE_OBJECTS) $(DIB_OBJECTS) + +TARGET_CLEAN = $(DEP_FILES) \ + dib/*.o \ + eng/*.o \ + freetype/*.o \ + ldr/*.o \ + main/*.o \ + misc/*.o \ + ntuser/*.o \ + objects/*.o \ + stubs/*.o + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +# Automatic dependency tracking +DEP_OBJECTS := $(TARGET_OBJECTS) +DEP_EXCLUDE_FILTER := main/svctabm.d +include $(PATH_TO_TOP)/tools/depend.mk + +main/svctabm.o: main/svctab.c + +.dummy: + +%/TAGS: .dummy + etags $(@D)/\*.c -o $(@D)/TAGS + +etags: TAGS +TAGS: main/TAGS eng/TAGS ldr/TAGS misc/TAGS objects/TAGS stubs/TAGS ntuser/TAGS dib/TAGS freetype/TAGS + etags -i main/TAGS -i eng/TAGS -i ldr/TAGS -i misc/TAGS -i objects/TAGS -i stubs/TAGS -i ntuser/TAGS -i dib/TAGS -i freetype/TAGS + +# EOF diff --git a/subsys/win32k/misc/.cvsignore b/subsys/win32k/misc/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/misc/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/misc/driver.c b/subsys/win32k/misc/driver.c new file mode 100644 index 0000000..881a168 --- /dev/null +++ b/subsys/win32k/misc/driver.c @@ -0,0 +1,273 @@ +/* $Id$ + * + * GDI Driver support routines + * (mostly swiped from Wine) + * + */ + +#undef WIN32_LEAN_AND_MEAN +#define WIN32_NO_PEHDR + +#include +#include +#include +#include +//#include "../../ntoskrnl/include/internal/module.h" +#include +#include + +#define NDEBUG +#include + +typedef struct _GRAPHICS_DRIVER +{ + PWSTR Name; + PGD_ENABLEDRIVER EnableDriver; + int ReferenceCount; + struct _GRAPHICS_DRIVER *Next; +} GRAPHICS_DRIVER, *PGRAPHICS_DRIVER; + +static PGRAPHICS_DRIVER DriverList; +static PGRAPHICS_DRIVER GenericDriver = 0; + +BOOL DRIVER_RegisterDriver(LPCWSTR Name, PGD_ENABLEDRIVER EnableDriver) +{ + PGRAPHICS_DRIVER Driver = ExAllocatePool(NonPagedPool, sizeof(*Driver)); + DPRINT( "DRIVER_RegisterDriver( Name: %S )\n", Name ); + if (!Driver) return FALSE; + Driver->ReferenceCount = 0; + Driver->EnableDriver = EnableDriver; + if (Name) + { + Driver->Name = ExAllocatePool(PagedPool, (wcslen(Name) + 1) * sizeof(WCHAR)); + wcscpy(Driver->Name, Name); + Driver->Next = DriverList; + DriverList = Driver; + return TRUE; + } + + if (GenericDriver != NULL) + { + ExFreePool(Driver); + return FALSE; + } + + GenericDriver = Driver; + return TRUE; +} + +PGD_ENABLEDRIVER DRIVER_FindDDIDriver(LPCWSTR Name) +{ + SYSTEM_LOAD_IMAGE GdiDriverInfo; + GRAPHICS_DRIVER *Driver = DriverList; + NTSTATUS Status; + + /* First see if the driver hasn't already been loaded */ + while (Driver && Name) + { + if (!_wcsicmp( Driver->Name, Name)) + { + return Driver->EnableDriver; + } + Driver = Driver->Next; + } + + /* If not, then load it */ + RtlInitUnicodeString (&GdiDriverInfo.ModuleName, (LPWSTR)Name); + Status = ZwSetSystemInformation (SystemLoadImage, &GdiDriverInfo, sizeof(SYSTEM_LOAD_IMAGE)); + if (!NT_SUCCESS(Status)) return NULL; + + DRIVER_RegisterDriver( L"DISPLAY", GdiDriverInfo.EntryPoint); + return (PGD_ENABLEDRIVER)GdiDriverInfo.EntryPoint; +} + +BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED, + PDRIVER_FUNCTIONS DF) +{ + int i; + + for (i=0; ic; i++) + { + if(DED->pdrvfn[i].iFunc == INDEX_DrvEnablePDEV) DF->EnablePDev = (PGD_ENABLEPDEV)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvCompletePDEV) DF->CompletePDev = (PGD_COMPLETEPDEV)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDisablePDEV) DF->DisablePDev = (PGD_DISABLEPDEV)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvEnableSurface) DF->EnableSurface = (PGD_ENABLESURFACE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDisableSurface) DF->DisableSurface = (PGD_DISABLESURFACE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvAssertMode) DF->AssertMode = (PGD_ASSERTMODE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvResetPDEV) DF->ResetPDev = (PGD_RESETPDEV)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvCreateDeviceBitmap) + DF->CreateDeviceBitmap = (PGD_CREATEDEVICEBITMAP)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDeleteDeviceBitmap) + DF->DeleteDeviceBitmap = (PGD_DELETEDEVICEBITMAP)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvRealizeBrush) DF->RealizeBrush = (PGD_REALIZEBRUSH)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDitherColor) DF->DitherColor = (PGD_DITHERCOLOR)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvStrokePath) DF->StrokePath = (PGD_STROKEPATH)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvFillPath) DF->FillPath = (PGD_FILLPATH)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvStrokeAndFillPath) + DF->StrokeAndFillPath = (PGD_STROKEANDFILLPATH)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvPaint) DF->Paint = (PGD_PAINT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvBitBlt) DF->BitBlt = (PGD_BITBLT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvTransparentBlt) DF->TransparentBlt = (PGD_TRANSPARENTBLT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvCopyBits) DF->CopyBits = (PGD_COPYBITS)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvStretchBlt) DF->StretchBlt = (PGD_STRETCHBLT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPalette) DF->SetPalette = (PGD_SETPALETTE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvTextOut) DF->TextOut = (PGD_TEXTOUT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvEscape) DF->Escape = (PGD_ESCAPE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDrawEscape) DF->DrawEscape = (PGD_DRAWESCAPE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFont) DF->QueryFont = (PGD_QUERYFONT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontTree) DF->QueryFontTree = (PGD_QUERYFONTTREE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontData) DF->QueryFontData = (PGD_QUERYFONTDATA)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPointerShape) DF->SetPointerShape = (PGD_SETPOINTERSHAPE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvMovePointer) DF->MovePointer = (PGD_MOVEPOINTER)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvLineTo) DF->LineTo = (PGD_LINETO)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSendPage) DF->SendPage = (PGD_SENDPAGE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvStartPage) DF->StartPage = (PGD_STARTPAGE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvEndDoc) DF->EndDoc = (PGD_ENDDOC)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvStartDoc) DF->StartDoc = (PGD_STARTDOC)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvGetGlyphMode) DF->GetGlyphMode = (PGD_GETGLYPHMODE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSynchronize) DF->Synchronize = (PGD_SYNCHRONIZE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSaveScreenBits) DF->SaveScreenBits = (PGD_SAVESCREENBITS)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvGetModes) DF->GetModes = (PGD_GETMODES)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvFree) DF->Free = (PGD_FREE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDestroyFont) DF->DestroyFont = (PGD_DESTROYFONT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontCaps) DF->QueryFontCaps = (PGD_QUERYFONTCAPS)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvLoadFontFile) DF->LoadFontFile = (PGD_LOADFONTFILE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvUnloadFontFile) DF->UnloadFontFile = (PGD_UNLOADFONTFILE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvFontManagement) DF->FontManagement = (PGD_FONTMANAGEMENT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryTrueTypeTable) + DF->QueryTrueTypeTable = (PGD_QUERYTRUETYPETABLE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryTrueTypeOutline) + DF->QueryTrueTypeOutline = (PGD_QUERYTRUETYPEOUTLINE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvGetTrueTypeFile) DF->GetTrueTypeFile = (PGD_GETTRUETYPEFILE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontFile) DF->QueryFontFile = (PGD_QUERYFONTFILE)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryAdvanceWidths) + DF->QueryAdvanceWidths = (PGD_QUERYADVANCEWIDTHS)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPixelFormat) DF->SetPixelFormat = (PGD_SETPIXELFORMAT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDescribePixelFormat) + DF->DescribePixelFormat = (PGD_DESCRIBEPIXELFORMAT)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvSwapBuffers) DF->SwapBuffers = (PGD_SWAPBUFFERS)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvStartBanding) DF->StartBanding = (PGD_STARTBANDING)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvNextBand) DF->NextBand = (PGD_NEXTBAND)DED->pdrvfn[i].pfn; +#if 0 + if(DED->pdrvfn[i].iFunc == INDEX_DrvGetDirectDrawInfo) DF->GETDIRECTDRAWINFO = (PGD_)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvEnableDirectDraw) DF->ENABLEDIRECTDRAW = (PGD_)DED->pdrvfn[i].pfn; + if(DED->pdrvfn[i].iFunc == INDEX_DrvDisableDirectDraw) DF->DISABLEDIRECTDRAW = (PGD_)DED->pdrvfn[i].pfn; +#endif + if(DED->pdrvfn[i].iFunc == INDEX_DrvQuerySpoolType) DF->QuerySpoolType = (PGD_QUERYSPOOLTYPE)DED->pdrvfn[i].pfn; + } + + return TRUE; +} + +typedef VP_STATUS (*PMP_DRIVERENTRY)(PVOID, PVOID); + +HANDLE DRIVER_FindMPDriver(LPCWSTR Name) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DeviceName; + IO_STATUS_BLOCK Iosb; + HANDLE DisplayHandle; + NTSTATUS Status; + + RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\DISPLAY1"); + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + 0, + NULL, + NULL); + Status = ZwOpenFile(&DisplayHandle, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenFile() failed (Status %lx)\n", Status); + return(NULL); + } + + return(DisplayHandle); +} + + +BOOL DRIVER_UnregisterDriver(LPCWSTR Name) +{ + PGRAPHICS_DRIVER Driver = NULL; + + if (Name) + { + if (DriverList != NULL) + { + if (!_wcsicmp(DriverList->Name, Name)) + { + Driver = DriverList; + DriverList = DriverList->Next; + } + else + { + Driver = DriverList; + while (Driver->Next && _wcsicmp(Driver->Name, Name)) + { + Driver = Driver->Next; + } + } + } + } + else + { + if (GenericDriver != NULL) + { + Driver = GenericDriver; + GenericDriver = NULL; + } + } + + if (Driver != NULL) + { + ExFreePool(Driver->Name); + ExFreePool(Driver); + + return TRUE; + } + else + { + return FALSE; + } +} + +INT DRIVER_ReferenceDriver (LPCWSTR Name) +{ + GRAPHICS_DRIVER *Driver = DriverList; + + while (Driver && Name) + { + DPRINT( "Comparing %S to %S\n", Driver->Name, Name ); + if (!_wcsicmp( Driver->Name, Name)) + { + return ++Driver->ReferenceCount; + } + Driver = Driver->Next; + } + DPRINT( "Driver %S not found to reference, generic count: %d\n", Name, GenericDriver->ReferenceCount ); + assert( GenericDriver != 0 ); + return ++GenericDriver->ReferenceCount; +} + +INT DRIVER_UnreferenceDriver (LPCWSTR Name) +{ + GRAPHICS_DRIVER *Driver = DriverList; + + while (Driver && Name) + { + DPRINT( "Comparing %S to %S\n", Driver->Name, Name ); + if (!_wcsicmp( Driver->Name, Name)) + { + return --Driver->ReferenceCount; + } + Driver = Driver->Next; + } + DPRINT( "Driver '%S' not found to dereference, generic count: %d\n", Name, GenericDriver->ReferenceCount ); + assert( GenericDriver != 0 ); + return --GenericDriver->ReferenceCount; +} diff --git a/subsys/win32k/misc/error.c b/subsys/win32k/misc/error.c new file mode 100644 index 0000000..0d124d9 --- /dev/null +++ b/subsys/win32k/misc/error.c @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Errors + * FILE: subsys/win32k/misc/error.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +#include +#include + + +VOID +SetLastNtError(NTSTATUS Status) +{ + SetLastWin32Error(RtlNtStatusToDosError(Status)); +} + +VOID +SetLastWin32Error(DWORD Status) +{ + PTEB Teb = NtCurrentTeb(); + + if (NULL != Teb) + { + Teb->LastErrorValue = Status; + } +} + +/* EOF */ diff --git a/subsys/win32k/misc/math.c b/subsys/win32k/misc/math.c new file mode 100644 index 0000000..ca4c659 --- /dev/null +++ b/subsys/win32k/misc/math.c @@ -0,0 +1,285 @@ +/* Math functions for i387. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +double atan (double __x); +double atan2 (double __y, double __x); +double ceil (double __x); +double cos (double __x); +double fabs (double __x); +double floor (double __x); +long _ftol (double fl); +double log (double __x); +double __log2 (double __x); +double pow (double __x, double __y); +double sin (double __x); +double sqrt (double __x); +double tan (double __x); +div_t div(int num, int denom); +int mod(int num, int denom); + +double atan (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fpatan" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double atan2 (double __y, double __x) +{ + register double __value; + __asm __volatile__ + ("fpatan\n\t" + "fld %%st(0)" + : "=t" (__value) : "0" (__x), "u" (__y)); + + return __value; +} + +double ceil (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + +double cos (double __x) +{ + register double __value; + __asm __volatile__ + ("fcos" + : "=t" (__value): "0" (__x)); + + return __value; +} + +double fabs (double __x) +{ + register double __value; + __asm __volatile__ + ("fabs" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double floor (double __x) +{ + register double __value; + __volatile unsigned short int __cw, __cwtmp; + + __asm __volatile ("fnstcw %0" : "=m" (__cw)); + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ + __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); + __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); + __asm __volatile ("fldcw %0" : : "m" (__cw)); + + return __value; +} + +long _ftol (double fl) +{ + return (long)fl; +} + +double log (double __x) +{ + register double __value; + __asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double __log2 (double __x) +{ + register double __value; + __asm __volatile__ + ("fld1\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double pow (double __x, double __y) +{ + register double __value, __exponent; + long __p = (long) __y; + + if (__x == 0.0 && __y > 0.0) + return 0.0; + if (__y == (double) __p) + { + double __r = 1.0; + if (__p == 0) + return 1.0; + if (__p < 0) + { + __p = -__p; + __x = 1.0 / __x; + } + while (1) + { + if (__p & 1) + __r *= __x; + __p >>= 1; + if (__p == 0) + return __r; + __x *= __x; + } + /* NOTREACHED */ + } + __asm __volatile__ + ("fmul %%st(1) # y * log2(x)\n\t" + "fst %%st(1)\n\t" + "frndint # int(y * log2(x))\n\t" + "fxch\n\t" + "fsub %%st(1) # fract(y * log2(x))\n\t" + "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" + : "=t" (__value), "=u" (__exponent) : "0" (__log2 (__x)), "1" (__y)); + __value += 1.0; + __asm __volatile__ + ("fscale" + : "=t" (__value) : "0" (__value), "u" (__exponent)); + + return __value; +} + +double sin (double __x) +{ + register double __value; + __asm __volatile__ + ("fsin" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double sqrt (double __x) +{ + register double __value; + __asm __volatile__ + ("fsqrt" + : "=t" (__value) : "0" (__x)); + + return __value; +} + +double tan (double __x) +{ + register double __value; + register double __value2 __attribute__ ((unused)); + __asm __volatile__ + ("fptan" + : "=t" (__value2), "=u" (__value) : "0" (__x)); + + return __value; +} + +div_t div(int num, int denom) +{ + div_t r; + if (num > 0 && denom < 0) { + num = -num; + denom = -denom; + } + r.quot = num / denom; + r.rem = num % denom; + if (num < 0 && denom > 0) + { + if (r.rem > 0) + { + r.quot++; + r.rem -= denom; + } + } + return r; +} + +int mod(int num, int denom) +{ + div_t dvt = div(num, denom); + return dvt.rem; +} + +//FIXME! Is there a better algorithm. like FT_MulDiv +INT STDCALL EngMulDiv( + INT nMultiplicand, + INT nMultiplier, + INT nDivisor) +{ +#if SIZEOF_LONG_LONG >= 8 + long long ret; + + if (!nDivisor) return -1; + + /* We want to deal with a positive divisor to simplify the logic. */ + if (nDivisor < 0) + { + nMultiplicand = - nMultiplicand; + nDivisor = -nDivisor; + } + + /* If the result is positive, we "add" to round. else, we subtract to round. */ + if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || + ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) + ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + else + ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + + if ((ret > 2147483647) || (ret < -2147483647)) return -1; + return ret; +#else + if (!nDivisor) return -1; + + /* We want to deal with a positive divisor to simplify the logic. */ + if (nDivisor < 0) + { + nMultiplicand = - nMultiplicand; + nDivisor = -nDivisor; + } + + /* If the result is positive, we "add" to round. else, we subtract to round. */ + if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || + ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) + return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + + return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + +#endif +} diff --git a/subsys/win32k/misc/object.c b/subsys/win32k/misc/object.c new file mode 100644 index 0000000..b7d6159 --- /dev/null +++ b/subsys/win32k/misc/object.c @@ -0,0 +1,518 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: User object manager + * FILE: subsys/win32k/misc/object.c + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 06-06-2001 CSH Ported kernel object manager + */ +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +PVOID +HEADER_TO_BODY(PUSER_OBJECT_HEADER ObjectHeader) +{ + return (((PUSER_OBJECT_HEADER)ObjectHeader) + 1); +} + +PUSER_OBJECT_HEADER +BODY_TO_HEADER(PVOID ObjectBody) +{ + return (((PUSER_OBJECT_HEADER)ObjectBody) - 1); +} + +VOID STATIC +ObmpLockHandleTable(PUSER_HANDLE_TABLE HandleTable) +{ + ExAcquireFastMutex(&HandleTable->ListLock); +} + +VOID STATIC +ObmpUnlockHandleTable(PUSER_HANDLE_TABLE HandleTable) +{ + ExReleaseFastMutex(&HandleTable->ListLock); +} + +VOID +ObmpPerformRetentionChecks(PUSER_OBJECT_HEADER ObjectHeader) +{ + if (ObjectHeader->RefCount < 0) + { + DbgPrint("ObjectHeader 0x%X has invalid reference count (%d)\n", + ObjectHeader, ObjectHeader->RefCount); + } + + if (ObjectHeader->HandleCount < 0) + { + DbgPrint("Object 0x%X has invalid handle count (%d)\n", + ObjectHeader, ObjectHeader->HandleCount); + } + + if ((ObjectHeader->RefCount == 0) && (ObjectHeader->HandleCount == 0)) + { + ExFreePool(ObjectHeader); + } +} + +PUSER_HANDLE +ObmpGetObjectByHandle(PUSER_HANDLE_TABLE HandleTable, + HANDLE Handle) +/* + * FUNCTION: Get the data structure for a handle + * ARGUMENTS: + * HandleTable = Table to search + * Handle = Handle to get data structure for + * RETURNS: + * Pointer to the data structure identified by the handle on success, + * NULL on failure + */ +{ + ULONG Index = (((ULONG)Handle) >> 2) - 1; + ULONG Count = Index / HANDLE_BLOCK_ENTRIES; + PUSER_HANDLE_BLOCK Block = NULL; + PLIST_ENTRY Current; + ULONG i; + + Current = HandleTable->ListHead.Flink; + + for (i = 0; i < Count; i++) + { + Current = Current->Flink; + if (Current == &(HandleTable->ListHead)) + { + return NULL; + } + } + + Block = CONTAINING_RECORD(Current, USER_HANDLE_BLOCK, ListEntry); + return &(Block->Handles[Index % HANDLE_BLOCK_ENTRIES]); +} + +VOID +ObmpCloseAllHandles(PUSER_HANDLE_TABLE HandleTable) +{ + PLIST_ENTRY CurrentEntry; + PUSER_HANDLE_BLOCK Current; + PVOID ObjectBody; + ULONG i; + + ObmpLockHandleTable(HandleTable); + + CurrentEntry = HandleTable->ListHead.Flink; + + while (CurrentEntry != &HandleTable->ListHead) + { + Current = CONTAINING_RECORD(CurrentEntry, USER_HANDLE_BLOCK, ListEntry); + + for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) + { + ObjectBody = Current->Handles[i].ObjectBody; + + if (ObjectBody != NULL) + { + PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + + ObmReferenceObjectByPointer(ObjectBody, otUnknown); + ObjectHeader->HandleCount--; + Current->Handles[i].ObjectBody = NULL; + + ObmpUnlockHandleTable(HandleTable); + + ObmDereferenceObject(ObjectBody); + + ObmpLockHandleTable(HandleTable); + CurrentEntry = &HandleTable->ListHead; + break; + } + } + + CurrentEntry = CurrentEntry->Flink; + } + + ObmpUnlockHandleTable(HandleTable); +} + +VOID +ObmpDeleteHandleTable(PUSER_HANDLE_TABLE HandleTable) +{ + PUSER_HANDLE_BLOCK Current; + PLIST_ENTRY CurrentEntry; + + ObmpCloseAllHandles(HandleTable); + + CurrentEntry = RemoveHeadList(&HandleTable->ListHead); + + while (CurrentEntry != &HandleTable->ListHead) + { + Current = CONTAINING_RECORD(CurrentEntry, + USER_HANDLE_BLOCK, + ListEntry); + + ExFreePool(Current); + + CurrentEntry = RemoveHeadList(&HandleTable->ListHead); + } +} + +PVOID +ObmpDeleteHandle(PUSER_HANDLE_TABLE HandleTable, + HANDLE Handle) +{ + PUSER_OBJECT_HEADER ObjectHeader; + PUSER_HANDLE Entry; + PVOID ObjectBody; + + ObmpLockHandleTable(HandleTable); + + Entry = ObmpGetObjectByHandle(HandleTable, Handle); + if (Entry == NULL) + { + ObmpUnlockHandleTable(HandleTable); + return NULL; + } + + ObjectBody = Entry->ObjectBody; + + if (ObjectBody != NULL) + { + ObjectHeader = BODY_TO_HEADER(ObjectBody); + ObjectHeader->HandleCount--; + ObmReferenceObjectByPointer(ObjectBody, otUnknown); + Entry->ObjectBody = NULL; + } + + ObmpUnlockHandleTable(HandleTable); + + return ObjectBody; +} + +NTSTATUS +ObmpInitializeObject(PUSER_HANDLE_TABLE HandleTable, + PUSER_OBJECT_HEADER ObjectHeader, + PHANDLE Handle, + USER_OBJECT_TYPE ObjectType, + ULONG ObjectSize) +{ + DWORD Status = STATUS_SUCCESS; + + ObjectHeader->Type = ObjectType; + ObjectHeader->HandleCount = 0; + ObjectHeader->RefCount = 1; + ObjectHeader->Size = ObjectSize; + + if (Handle != NULL) + { + Status = ObmCreateHandle(HandleTable, + HEADER_TO_BODY(ObjectHeader), + Handle); + } + + return Status; +} + + +ULONG +ObmGetReferenceCount(PVOID ObjectBody) +{ + PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + + return ObjectHeader->RefCount; +} + +ULONG +ObmGetHandleCount(PVOID ObjectBody) +{ + PUSER_OBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); + + return ObjectHeader->HandleCount; +} + +VOID +ObmReferenceObject(PVOID ObjectBody) +/* + * FUNCTION: Increments a given object's reference count and performs + * retention checks + * ARGUMENTS: + * ObjectBody = Body of the object + */ +{ + PUSER_OBJECT_HEADER ObjectHeader; + + if (!ObjectBody) + { + return; + } + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + + ObjectHeader->RefCount++; + + ObmpPerformRetentionChecks(ObjectHeader); +} + +VOID +ObmDereferenceObject(PVOID ObjectBody) +/* + * FUNCTION: Decrements a given object's reference count and performs + * retention checks + * ARGUMENTS: + * ObjectBody = Body of the object + */ +{ + PUSER_OBJECT_HEADER ObjectHeader; + + if (!ObjectBody) + { + return; + } + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + + ObjectHeader->RefCount--; + + ObmpPerformRetentionChecks(ObjectHeader); +} + +NTSTATUS +ObmReferenceObjectByPointer(PVOID ObjectBody, + USER_OBJECT_TYPE ObjectType) +/* + * FUNCTION: Increments the pointer reference count for a given object + * ARGUMENTS: + * ObjectBody = Object's body + * ObjectType = Object type + * RETURNS: Status + */ +{ + PUSER_OBJECT_HEADER ObjectHeader; + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + + if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType)) + { + return STATUS_INVALID_PARAMETER; + } + + ObjectHeader->RefCount++; + + return STATUS_SUCCESS; +} + +PVOID +ObmCreateObject(PUSER_HANDLE_TABLE HandleTable, + PHANDLE Handle, + USER_OBJECT_TYPE ObjectType, + ULONG ObjectSize) +{ + PUSER_OBJECT_HEADER ObjectHeader; + PVOID ObjectBody; + DWORD Status; + + ObjectHeader = (PUSER_OBJECT_HEADER)ExAllocatePool(NonPagedPool, + ObjectSize + sizeof(USER_OBJECT_HEADER)); + if (!ObjectHeader) + { + return NULL; + } + + ObjectBody = HEADER_TO_BODY(ObjectHeader); + + RtlZeroMemory(ObjectBody, ObjectSize); + + Status = ObmpInitializeObject(HandleTable, + ObjectHeader, + Handle, + ObjectType, + ObjectSize); + + if (!NT_SUCCESS(Status)) + { + ExFreePool(ObjectHeader); + return NULL; + } + + return ObjectBody; +} + +NTSTATUS +ObmCreateHandle(PUSER_HANDLE_TABLE HandleTable, + PVOID ObjectBody, + PHANDLE HandleReturn) +/* + * FUNCTION: Add a handle referencing an object + * ARGUMENTS: + * HandleTable = Table to put handle in + * ObjectBody = Object body that the handle should refer to + * RETURNS: The created handle + */ +{ + PUSER_HANDLE_BLOCK NewBlock; + PLIST_ENTRY Current; + ULONG Handle; + ULONG i; + + if (ObjectBody != NULL) + { + BODY_TO_HEADER(ObjectBody)->HandleCount++; + } + + ObmpLockHandleTable(HandleTable); + + Handle = 1; + Current = HandleTable->ListHead.Flink; + /* + * Scan through the currently allocated Handle blocks looking for a free + * slot + */ + while (Current != &(HandleTable->ListHead)) + { + PUSER_HANDLE_BLOCK Block = + CONTAINING_RECORD(Current, USER_HANDLE_BLOCK, ListEntry); + + for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) + { + if (!Block->Handles[i].ObjectBody) + { + Block->Handles[i].ObjectBody = ObjectBody; + ObmpUnlockHandleTable(HandleTable); + *HandleReturn = (HANDLE)((Handle + i) << 2); + return ERROR_SUCCESS; + } + } + + Handle = Handle + HANDLE_BLOCK_ENTRIES; + Current = Current->Flink; + } + + /* + * Add a new Handle block to the end of the list + */ + NewBlock = (PUSER_HANDLE_BLOCK)ExAllocatePool(NonPagedPool, + sizeof(USER_HANDLE_BLOCK)); + if (!NewBlock) + { + *HandleReturn = (PHANDLE)NULL; + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(NewBlock, sizeof(USER_HANDLE_BLOCK)); + NewBlock->Handles[0].ObjectBody = ObjectBody; + InsertTailList(&HandleTable->ListHead, &NewBlock->ListEntry); + ObmpUnlockHandleTable(HandleTable); + *HandleReturn = (HANDLE)(Handle << 2); + + return STATUS_SUCCESS; +} + +NTSTATUS +ObmReferenceObjectByHandle(PUSER_HANDLE_TABLE HandleTable, + HANDLE Handle, + USER_OBJECT_TYPE ObjectType, + PVOID* Object) +/* + * FUNCTION: Increments the reference count for an object and returns a + * pointer to its body + * ARGUMENTS: + * HandleTable = Table to search + * Handle = Handle for the object + * ObjectType = Type of object + * Object (OUT) = Points to the object body on return + * RETURNS: Status + */ +{ + PUSER_OBJECT_HEADER ObjectHeader; + PUSER_HANDLE UserHandle; + PVOID ObjectBody; + + ObmpLockHandleTable(HandleTable); + + UserHandle = ObmpGetObjectByHandle(HandleTable, Handle); + + if ((UserHandle == NULL) || (UserHandle->ObjectBody == NULL)) + { + ObmpUnlockHandleTable(HandleTable); + return STATUS_UNSUCCESSFUL; + } + + ObjectBody = UserHandle->ObjectBody; + ObmReferenceObjectByPointer(ObjectBody, ObjectType); + + ObmpUnlockHandleTable(HandleTable); + + ObjectHeader = BODY_TO_HEADER(ObjectBody); + + if ((ObjectType != otUnknown) && (ObjectHeader->Type != ObjectType)) + { + return STATUS_UNSUCCESSFUL; + } + + *Object = ObjectBody; + + return STATUS_SUCCESS; +} + +NTSTATUS +ObmCloseHandle(PUSER_HANDLE_TABLE HandleTable, + HANDLE Handle) +{ + PVOID ObjectBody; + + ObjectBody = ObmpDeleteHandle(HandleTable, Handle); + if (ObjectBody == NULL) + { + return STATUS_UNSUCCESSFUL; + } + + ObmDereferenceObject(ObjectBody); + + return STATUS_SUCCESS; +} + +VOID +ObmInitializeHandleTable(PUSER_HANDLE_TABLE HandleTable) +{ + InitializeListHead(&HandleTable->ListHead); + ExInitializeFastMutex(&HandleTable->ListLock); +} + +VOID +ObmFreeHandleTable(PUSER_HANDLE_TABLE HandleTable) +{ + ObmpDeleteHandleTable(HandleTable); +} + +PUSER_HANDLE_TABLE +ObmCreateHandleTable(VOID) +{ + PUSER_HANDLE_TABLE HandleTable; + + HandleTable = (PUSER_HANDLE_TABLE)ExAllocatePool(NonPagedPool, + sizeof(USER_HANDLE_TABLE)); + if (!HandleTable) + { + return NULL; + } + + ObmInitializeHandleTable(HandleTable); + + return HandleTable; +} + +VOID +ObmDestroyHandleTable(PUSER_HANDLE_TABLE HandleTable) +{ + ObmFreeHandleTable(HandleTable); + ExFreePool(HandleTable); +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/.cvsignore b/subsys/win32k/ntuser/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/ntuser/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/ntuser/callback.c b/subsys/win32k/ntuser/callback.c new file mode 100644 index 0000000..67340b4 --- /dev/null +++ b/subsys/win32k/ntuser/callback.c @@ -0,0 +1,246 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window classes + * FILE: subsys/win32k/ntuser/wndproc.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +W32kCallSentMessageCallback(SENDASYNCPROC CompletionCallback, + HWND hWnd, + UINT Msg, + ULONG_PTR CompletionCallbackContext, + LRESULT Result) +{ + SENDASYNCPROC_CALLBACK_ARGUMENTS Arguments; + NTSTATUS Status; + + Arguments.Callback = CompletionCallback; + Arguments.Wnd = hWnd; + Arguments.Msg = Msg; + Arguments.Context = CompletionCallbackContext; + Arguments.Result = Result; + Status = NtW32Call(USER32_CALLBACK_SENDASYNCPROC, + &Arguments, + sizeof(SENDASYNCPROC_CALLBACK_ARGUMENTS), + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + return; + } + return; +} + +LRESULT STDCALL +W32kSendNCCALCSIZEMessage(HWND Wnd, BOOL Validate, PRECT Rect, + NCCALCSIZE_PARAMS* Params) +{ + SENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS Arguments; + SENDNCCALCSIZEMESSAGE_CALLBACK_RESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + ULONG ResultLength; + + Arguments.Wnd = Wnd; + Arguments.Validate = Validate; + if (!Validate) + { + Arguments.Rect = *Rect; + } + else + { + Arguments.Params = *Params; + } + ResultPointer = &Result; + ResultLength = sizeof(SENDNCCALCSIZEMESSAGE_CALLBACK_RESULT); + Status = NtW32Call(USER32_CALLBACK_SENDNCCALCSIZE, + &Arguments, + sizeof(SENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS), + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0); + } + if (!Validate) + { + *Rect = Result.Rect; + } + else + { + *Params = Result.Params; + } + return(Result.Result); +} + +LRESULT STDCALL +W32kSendCREATEMessage(HWND Wnd, CREATESTRUCTW* CreateStruct) +{ + SENDCREATEMESSAGE_CALLBACK_ARGUMENTS Arguments; + LRESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + ULONG ResultLength; + + Arguments.Wnd = Wnd; + Arguments.CreateStruct = *CreateStruct; + ResultPointer = &Result; + ResultLength = sizeof(LRESULT); + Status = NtW32Call(USER32_CALLBACK_SENDCREATE, + &Arguments, + sizeof(SENDCREATEMESSAGE_CALLBACK_ARGUMENTS), + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0); + } + return(Result); +} + +LRESULT STDCALL +W32kSendNCCREATEMessage(HWND Wnd, CREATESTRUCTW* CreateStruct) +{ + SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS Arguments; + LRESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + ULONG ResultLength; + + Arguments.Wnd = Wnd; + Arguments.CreateStruct = *CreateStruct; + ResultPointer = &Result; + ResultLength = sizeof(LRESULT); + Status = NtW32Call(USER32_CALLBACK_SENDNCCREATE, + &Arguments, + sizeof(SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS), + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0); + } + return(Result); +} + +LRESULT STDCALL +W32kCallWindowProc(WNDPROC Proc, + HWND Wnd, + UINT Message, + WPARAM wParam, + LPARAM lParam) +{ + WINDOWPROC_CALLBACK_ARGUMENTS Arguments; + LRESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + ULONG ResultLength; + + if (W32kIsDesktopWindow(Wnd)) + { + return(W32kDesktopWindowProc(Wnd, Message, wParam, lParam)); + } + + Arguments.Proc = Proc; + Arguments.Wnd = Wnd; + Arguments.Msg = Message; + Arguments.wParam = wParam; + Arguments.lParam = lParam; + ResultPointer = &Result; + ResultLength = sizeof(LRESULT); + Status = NtW32Call(USER32_CALLBACK_WINDOWPROC, + &Arguments, + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS), + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0xFFFFFFFF); + } + return(Result); +} + +LRESULT STDCALL +W32kSendGETMINMAXINFOMessage(HWND Wnd, MINMAXINFO* MinMaxInfo) +{ + SENDGETMINMAXINFO_CALLBACK_ARGUMENTS Arguments; + SENDGETMINMAXINFO_CALLBACK_RESULT Result; + NTSTATUS Status; + PVOID ResultPointer; + ULONG ResultLength; + + Arguments.Wnd = Wnd; + Arguments.MinMaxInfo = *MinMaxInfo; + ResultPointer = &Result; + ResultLength = sizeof(Result); + Status = NtW32Call(USER32_CALLBACK_SENDGETMINMAXINFO, + &Arguments, + sizeof(SENDGETMINMAXINFO_CALLBACK_ARGUMENTS), + &ResultPointer, + &ResultLength); + if (!NT_SUCCESS(Status)) + { + return(0); + } + return(Result.Result); +} + +LRESULT STDCALL +W32kCallTrampolineWindowProc(WNDPROC Proc, + HWND Wnd, + UINT Message, + WPARAM wParam, + LPARAM lParam) +{ + switch (Message) + { + case WM_NCCREATE: + return(W32kSendNCCREATEMessage(Wnd, (CREATESTRUCTW*)lParam)); + + case WM_CREATE: + return(W32kSendCREATEMessage(Wnd, (CREATESTRUCTW*)lParam)); + + case WM_GETMINMAXINFO: + return(W32kSendGETMINMAXINFOMessage(Wnd, (MINMAXINFO*)lParam)); + + case WM_NCCALCSIZE: + { + if (wParam) + { + return(W32kSendNCCALCSIZEMessage(Wnd, TRUE, NULL, + (NCCALCSIZE_PARAMS*)lParam)); + } + else + { + return(W32kSendNCCALCSIZEMessage(Wnd, FALSE, (RECT*)lParam, NULL)); + } + } + + default: + return(W32kCallWindowProc(Proc, Wnd, Message, wParam, lParam)); + } +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/class.c b/subsys/win32k/ntuser/class.c new file mode 100644 index 0000000..b0a8033 --- /dev/null +++ b/subsys/win32k/ntuser/class.c @@ -0,0 +1,343 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window classes + * FILE: subsys/win32k/ntuser/class.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +InitClassImpl(VOID) +{ + return(STATUS_SUCCESS); +} + +NTSTATUS +CleanupClassImpl(VOID) +{ + return(STATUS_SUCCESS); +} + + +NTSTATUS +ClassReferenceClassByName(PW32PROCESS Process, + PWNDCLASS_OBJECT* Class, + LPWSTR ClassName) +{ + PWNDCLASS_OBJECT Current; + PLIST_ENTRY CurrentEntry; + + ExAcquireFastMutexUnsafe (&Process->ClassListLock); + CurrentEntry = Process->ClassListHead.Flink; + while (CurrentEntry != &Process->ClassListHead) + { + Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry); + + if (_wcsicmp(ClassName, Current->Class.lpszClassName) == 0) + { + *Class = Current; + ObmReferenceObject(Current); + ExReleaseFastMutexUnsafe (&Process->ClassListLock); + return(STATUS_SUCCESS); + } + + CurrentEntry = CurrentEntry->Flink; + } + ExReleaseFastMutexUnsafe (&Process->ClassListLock); + + return(STATUS_NOT_FOUND); +} + +NTSTATUS +ClassReferenceClassByAtom(PWNDCLASS_OBJECT *Class, + RTL_ATOM ClassAtom) +{ + PWINSTATION_OBJECT WinStaObject; + ULONG ClassNameLength; + WCHAR ClassName[256]; + NTSTATUS Status; + + if (!ClassAtom) + { + return(STATUS_INVALID_PARAMETER); + } + + Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of window station handle (0x%X) failed\n", + PROCESS_WINDOW_STATION()); + return(STATUS_UNSUCCESSFUL); + } + + ClassNameLength = sizeof(ClassName); + Status = RtlQueryAtomInAtomTable(WinStaObject->AtomTable, + ClassAtom, + NULL, + NULL, + &ClassName[0], + &ClassNameLength); + + Status = ClassReferenceClassByName(PsGetWin32Process(), + Class, + &ClassName[0]); + + ObDereferenceObject(WinStaObject); + + return(Status); +} + +NTSTATUS +ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class, + LPWSTR ClassNameOrAtom) +{ + NTSTATUS Status; + + if (IS_ATOM(ClassNameOrAtom)) + { + Status = ClassReferenceClassByAtom(Class, + (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom)); + } + else + { + Status = ClassReferenceClassByName(PsGetWin32Process(), Class, + ClassNameOrAtom); + } + + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + } + + return(Status); +} + +DWORD STDCALL +NtUserGetClassInfo(IN LPWSTR ClassName, + IN ULONG InfoClass, + OUT PVOID Info, + IN ULONG InfoLength, + OUT PULONG ReturnedLength) +{ + UNIMPLEMENTED; + + return(0); +} + +DWORD STDCALL +NtUserGetClassName(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + + return(0); +} + +DWORD STDCALL +NtUserGetWOWClass(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED; + + return(0); +} + +PWNDCLASS_OBJECT +W32kCreateClass(LPWNDCLASSEX lpwcx, + BOOL bUnicodeClass) +{ + PWNDCLASS_OBJECT ClassObject; + WORD objectSize; + LPTSTR namePtr; + + objectSize = sizeof(WNDCLASS_OBJECT) + + (lpwcx->lpszMenuName != 0 ? ((wcslen (lpwcx->lpszMenuName) + 1) * 2) : 0) + + ((wcslen (lpwcx->lpszClassName) + 1) * 2); + ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize); + if (ClassObject == 0) + { + return(NULL); + } + + ClassObject->Class = *lpwcx; + ClassObject->Unicode = bUnicodeClass; + namePtr = (LPTSTR)(((PCHAR)ClassObject) + sizeof (WNDCLASS_OBJECT)); + if (lpwcx->lpszMenuName != 0) + { + ClassObject->Class.lpszMenuName = namePtr; + wcscpy (namePtr, lpwcx->lpszMenuName); + namePtr += wcslen (lpwcx->lpszMenuName) + 1; + } + ClassObject->Class.lpszClassName = namePtr; + wcscpy (namePtr, lpwcx->lpszClassName); + return(ClassObject); +} + +RTL_ATOM STDCALL +NtUserRegisterClassExWOW(LPWNDCLASSEX lpwcx, + BOOL bUnicodeClass, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +/* + * FUNCTION: + * Registers a new class with the window manager + * ARGUMENTS: + * lpcx = Win32 extended window class structure + * bUnicodeClass = Wether to send ANSI or unicode strings + * to window procedures + * RETURNS: + * Atom identifying the new class + */ +{ + PWINSTATION_OBJECT WinStaObject; + PWNDCLASS_OBJECT ClassObject; + NTSTATUS Status; + RTL_ATOM Atom; + + W32kGuiCheck(); + + DPRINT("About to open window station handle (0x%X)\n", + PROCESS_WINDOW_STATION()); + + Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of window station handle (0x%X) failed\n", + PROCESS_WINDOW_STATION()); + return((RTL_ATOM)0); + } + + Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable, + (LPWSTR)lpwcx->lpszClassName, + &Atom); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(WinStaObject); + DPRINT("Failed adding class name (%wS) to atom table\n", + lpwcx->lpszClassName); + SetLastNtError(Status); + + return((RTL_ATOM)0); + } + ClassObject = W32kCreateClass(lpwcx, bUnicodeClass); + if (ClassObject == NULL) + { + RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom); + ObDereferenceObject(WinStaObject); + DPRINT("Failed creating window class object\n"); + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + return((RTL_ATOM)0); + } + ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock); + InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry); + ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock); + + ObDereferenceObject(WinStaObject); + + return(Atom); +} + +ULONG +W32kGetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset) +{ + LONG Ret; + switch (Offset) + { + case GCL_STYLE: + Ret = WindowObject->Class->Class.style; + break; + case GCL_CBWNDEXTRA: + Ret = WindowObject->Class->Class.cbWndExtra; + break; + case GCL_CBCLSEXTRA: + Ret = WindowObject->Class->Class.cbClsExtra; + break; + case GCL_HMODULE: + Ret = (ULONG)WindowObject->Class->Class.hInstance; + break; + case GCL_HBRBACKGROUND: + Ret = (ULONG)WindowObject->Class->Class.hbrBackground; + break; + default: + Ret = 0; + break; + } + return(Ret); +} + +DWORD STDCALL +NtUserGetClassLong(HWND hWnd, DWORD Offset) +{ + PWINDOW_OBJECT WindowObject; + LONG Ret; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + return(0); + } + Ret = W32kGetClassLong(WindowObject, Offset); + W32kReleaseWindowObject(WindowObject); + return(Ret); +} + +DWORD STDCALL +NtUserSetClassLong(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED; + + return(0); +} + +DWORD STDCALL +NtUserSetClassWord(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + + return(0); +} + +DWORD STDCALL +NtUserUnregisterClass(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + + return(0); +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/guicheck.c b/subsys/win32k/ntuser/guicheck.c new file mode 100644 index 0000000..1db5dd8 --- /dev/null +++ b/subsys/win32k/ntuser/guicheck.c @@ -0,0 +1,94 @@ + /* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: GUI state check + * FILE: subsys/win32k/ntuser/guicheck.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: The GuiCheck() function performs a few delayed operations: + * 1) A GUI process is assigned a window station + * 2) A message queue is created for a GUI thread before use + * 3) The system window classes are registered for a process + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static ULONG NrGuiApplicationsRunning = 0; + +/* FUNCTIONS *****************************************************************/ + +VOID +W32kGraphicsCheck(VOID) +{ + if (NrGuiApplicationsRunning == 0) + { + W32kInitializeDesktopGraphics(); + } + NrGuiApplicationsRunning++; +} + +VOID +W32kGuiCheck(VOID) +{ + if (PsGetWin32Process() == NULL) + { + NTSTATUS Status; + + PsCreateWin32Process(PsGetCurrentProcess()); + + InitializeListHead(&PsGetWin32Process()->ClassListHead); + ExInitializeFastMutex(&PsGetWin32Process()->ClassListLock); + + Status = + ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), + UserMode, + GENERIC_ALL, + &PsGetWin32Process()->WindowStation); + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to reference a window station for " + "process.\n"); + } + } + + if (PsGetWin32Thread() == NULL) + { + NTSTATUS Status; + + PsCreateWin32Thread(PsGetCurrentThread()); + PsGetWin32Thread()->MessageQueue = MsqCreateMessageQueue(); + InitializeListHead(&PsGetWin32Thread()->WindowListHead); + ExInitializeFastMutex(&PsGetWin32Thread()->WindowListLock); + + /* By default threads get assigned their process's desktop. */ + PsGetWin32Thread()->Desktop = NULL; + Status = ObReferenceObjectByHandle(PsGetCurrentProcess()->Win32Desktop, + GENERIC_ALL, + ExDesktopObjectType, + UserMode, + (PVOID*)&PsGetWin32Thread()->Desktop, + NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to reference a desktop for thread.\n"); + } + } +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/hook.c b/subsys/win32k/ntuser/hook.c new file mode 100644 index 0000000..031a875 --- /dev/null +++ b/subsys/win32k/ntuser/hook.c @@ -0,0 +1,93 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window hooks + * FILE: subsys/win32k/ntuser/hook.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +#include +#include + +#define NDEBUG +#include + +DWORD +STDCALL +NtUserCallNextHookEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetWindowsHookAW( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetWindowsHookEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetWinEventHook( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUnhookWindowsHookEx( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUnhookWinEvent( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/input.c b/subsys/win32k/ntuser/input.c new file mode 100644 index 0000000..337c75e --- /dev/null +++ b/subsys/win32k/ntuser/input.c @@ -0,0 +1,240 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window classes + * FILE: subsys/win32k/ntuser/class.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "../../drivers/input/include/mouse.h" + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static HANDLE MouseDeviceHandle; +static HANDLE KeyboardThreadHandle; +static CLIENT_ID KeyboardThreadId; +static HANDLE KeyboardDeviceHandle; +static KEVENT InputThreadsStart; +static BOOLEAN InputThreadsRunning = FALSE; + +VOID MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount); + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS STDCALL STATIC +KeyboardThreadMain(PVOID StartContext) +{ + UNICODE_STRING KeyboardDeviceName; + OBJECT_ATTRIBUTES KeyboardObjectAttributes; + IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + + RtlInitUnicodeStringFromLiteral(&KeyboardDeviceName, L"\\??\\Keyboard"); + InitializeObjectAttributes(&KeyboardObjectAttributes, + &KeyboardDeviceName, + 0, + NULL, + NULL); + Status = NtOpenFile(&KeyboardDeviceHandle, + FILE_ALL_ACCESS, + &KeyboardObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to open keyboard.\n"); + return(Status); + } + + for (;;) + { + /* + * Wait to start input. + */ + Status = KeWaitForSingleObject(&InputThreadsStart, + 0, + UserMode, + TRUE, + NULL); + /* + * Receive and process keyboard input. + */ + while (InputThreadsRunning) + { + KEY_EVENT_RECORD KeyEvent; + LPARAM lParam; + + Status = NtReadFile (KeyboardDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + &KeyEvent, + sizeof(KEY_EVENT_RECORD), + NULL, + NULL); + if (Status == STATUS_ALERTED && !InputThreadsRunning) + { + break; + } + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to read from keyboard.\n"); + return(Status); + } + + /* + * Post a keyboard message. + */ + if (KeyEvent.bKeyDown) + { + /* FIXME: Bit 24 indicates if this is an extended key. */ + lParam = KeyEvent.wRepeatCount | + ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0x40000000; + MsqPostKeyboardMessage(WM_KEYDOWN, KeyEvent.wVirtualKeyCode, + lParam); + } + else + { + /* FIXME: Bit 24 indicates if this is an extended key. */ + lParam = KeyEvent.wRepeatCount | + ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0xC0000000; + MsqPostKeyboardMessage(WM_KEYUP, KeyEvent.wVirtualKeyCode, + lParam); + } + } + } +} + +NTSTATUS STDCALL +NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release) +{ + if (Release && InputThreadsRunning) + { + KeClearEvent(&InputThreadsStart); + InputThreadsRunning = FALSE; + NtAlertThread(KeyboardThreadHandle); + } + else if (!Release && !InputThreadsRunning) + { + InputThreadsRunning = TRUE; + KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE); + } + return(STATUS_SUCCESS); +} + +NTSTATUS +InitInputImpl(VOID) +{ + NTSTATUS Status; + UNICODE_STRING MouseDeviceName; + OBJECT_ATTRIBUTES MouseObjectAttributes; + IO_STATUS_BLOCK Iosb; + PIRP Irp; + PFILE_OBJECT FileObject; + GDI_INFORMATION GdiInfo; + KEVENT IoEvent; + PIO_STACK_LOCATION StackPtr; + + KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE); + + Status = PsCreateSystemThread(&KeyboardThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + &KeyboardThreadId, + KeyboardThreadMain, + NULL); + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to create keyboard thread.\n"); + } + + /* + * Connect to the mouse class driver. + */ + RtlInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass"); + InitializeObjectAttributes(&MouseObjectAttributes, + &MouseDeviceName, + 0, + NULL, + NULL); + Status = NtOpenFile(&MouseDeviceHandle, + FILE_ALL_ACCESS, + &MouseObjectAttributes, + &Iosb, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to open mouse.\n"); + return(Status); + } + Status = ObReferenceObjectByHandle(MouseDeviceHandle, + FILE_READ_DATA | FILE_WRITE_DATA, + IoFileObjectType, + KernelMode, + (PVOID *) &FileObject, + NULL); + + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to reference mouse file object.\n"); + return(Status); + } + KeInitializeEvent(&IoEvent, FALSE, NotificationEvent); + GdiInfo.CallBack = MouseGDICallBack; + Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT, + FileObject->DeviceObject, + &GdiInfo, + sizeof(GdiInfo), + NULL, + 0, + TRUE, + &FileObject->Event, + &Iosb); + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->FileObject = FileObject; + StackPtr->DeviceObject = FileObject->DeviceObject; + StackPtr->Parameters.DeviceIoControl.InputBufferLength = sizeof(GdiInfo); + StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 0; + + Status = IoCallDriver(FileObject->DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE, + NULL); + Status = Iosb.Status; + } + if (!NT_SUCCESS(Status)) + { + DbgPrint("W32K: Failed to connect to mouse driver.\n"); + return(Status); + } + + return(STATUS_SUCCESS); +} + +NTSTATUS +CleanupInputImp(VOID) +{ + return(STATUS_SUCCESS); +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/keyboard.c b/subsys/win32k/ntuser/keyboard.c new file mode 100644 index 0000000..b060ea2 --- /dev/null +++ b/subsys/win32k/ntuser/keyboard.c @@ -0,0 +1,222 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Messages + * FILE: subsys/win32k/ntuser/message.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +BYTE QueueKeyStateTable[256]; + +struct accent_char +{ + BYTE ac_accent; + BYTE ac_char; + BYTE ac_result; +}; + +static const struct accent_char accent_chars[] = +{ +/* A good idea should be to read /usr/X11/lib/X11/locale/iso8859-x/Compose */ + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, + /* iso-8859-2 uses this */ + {'<', 'L', '\245'}, {'<', 'l', '\265'}, /* caron */ + {'<', 'S', '\251'}, {'<', 's', '\271'}, + {'<', 'T', '\253'}, {'<', 't', '\273'}, + {'<', 'Z', '\256'}, {'<', 'z', '\276'}, + {'<', 'C', '\310'}, {'<', 'c', '\350'}, + {'<', 'E', '\314'}, {'<', 'e', '\354'}, + {'<', 'D', '\317'}, {'<', 'd', '\357'}, + {'<', 'N', '\322'}, {'<', 'n', '\362'}, + {'<', 'R', '\330'}, {'<', 'r', '\370'}, + {';', 'A', '\241'}, {';', 'a', '\261'}, /* ogonek */ + {';', 'E', '\312'}, {';', 'e', '\332'}, + {'\'', 'Z', '\254'}, {'\'', 'z', '\274'}, /* acute */ + {'\'', 'R', '\300'}, {'\'', 'r', '\340'}, + {'\'', 'L', '\305'}, {'\'', 'l', '\345'}, + {'\'', 'C', '\306'}, {'\'', 'c', '\346'}, + {'\'', 'N', '\321'}, {'\'', 'n', '\361'}, +/* collision whith S, from iso-8859-9 !!! */ + {',', 'S', '\252'}, {',', 's', '\272'}, /* cedilla */ + {',', 'T', '\336'}, {',', 't', '\376'}, + {'.', 'Z', '\257'}, {'.', 'z', '\277'}, /* dot above */ + {'/', 'L', '\243'}, {'/', 'l', '\263'}, /* slash */ + {'/', 'D', '\320'}, {'/', 'd', '\360'}, + {'(', 'A', '\303'}, {'(', 'a', '\343'}, /* breve */ + {'\275', 'O', '\325'}, {'\275', 'o', '\365'}, /* double acute */ + {'\275', 'U', '\334'}, {'\275', 'u', '\374'}, + {'0', 'U', '\332'}, {'0', 'u', '\372'}, /* ring above */ + /* iso-8859-3 uses this */ + {'/', 'H', '\241'}, {'/', 'h', '\261'}, /* slash */ + {'>', 'H', '\246'}, {'>', 'h', '\266'}, /* circumflex */ + {'>', 'J', '\254'}, {'>', 'j', '\274'}, + {'>', 'C', '\306'}, {'>', 'c', '\346'}, + {'>', 'G', '\330'}, {'>', 'g', '\370'}, + {'>', 'S', '\336'}, {'>', 's', '\376'}, +/* collision whith G( from iso-8859-9 !!! */ + {'(', 'G', '\253'}, {'(', 'g', '\273'}, /* breve */ + {'(', 'U', '\335'}, {'(', 'u', '\375'}, +/* collision whith I. from iso-8859-3 !!! */ + {'.', 'I', '\251'}, {'.', 'i', '\271'}, /* dot above */ + {'.', 'C', '\305'}, {'.', 'c', '\345'}, + {'.', 'G', '\325'}, {'.', 'g', '\365'}, + /* iso-8859-4 uses this */ + {',', 'R', '\243'}, {',', 'r', '\263'}, /* cedilla */ + {',', 'L', '\246'}, {',', 'l', '\266'}, + {',', 'G', '\253'}, {',', 'g', '\273'}, + {',', 'N', '\321'}, {',', 'n', '\361'}, + {',', 'K', '\323'}, {',', 'k', '\363'}, + {'~', 'I', '\245'}, {'~', 'i', '\265'}, /* tilde */ + {'-', 'E', '\252'}, {'-', 'e', '\272'}, /* macron */ + {'-', 'A', '\300'}, {'-', 'a', '\340'}, + {'-', 'I', '\317'}, {'-', 'i', '\357'}, + {'-', 'O', '\322'}, {'-', 'o', '\362'}, + {'-', 'U', '\336'}, {'-', 'u', '\376'}, + {'/', 'T', '\254'}, {'/', 't', '\274'}, /* slash */ + {'.', 'E', '\314'}, {'.', 'e', '\344'}, /* dot above */ + {';', 'I', '\307'}, {';', 'i', '\347'}, /* ogonek */ + {';', 'U', '\331'}, {';', 'u', '\371'}, + /* iso-8859-9 uses this */ + /* iso-8859-9 has really bad choosen G( S, and I. as they collide + * whith the same letters on other iso-8859-x (that is they are on + * different places :-( ), if you use turkish uncomment these and + * comment out the lines in iso-8859-2 and iso-8859-3 sections + * FIXME: should be dynamic according to chosen language + * if/when Wine has turkish support. + */ +/* collision whith G( from iso-8859-3 !!! */ +/* {'(', 'G', '\320'}, {'(', 'g', '\360'}, */ /* breve */ +/* collision whith S, from iso-8859-2 !!! */ +/* {',', 'S', '\336'}, {',', 's', '\376'}, */ /* cedilla */ +/* collision whith I. from iso-8859-3 !!! */ +/* {'.', 'I', '\335'}, {'.', 'i', '\375'}, */ /* dot above */ +}; + +int STDCALL +ToUnicode(UINT wVirtKey, + UINT wScanCode, + PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags) +{ +} + +BOOL STDCALL +NtUserTranslateMessage(LPMSG lpMsg, + DWORD Unknown1) +{ + LONG UState; + WCHAR wp[2]; + MSG NewMsg; + static INT dead_char; + PUSER_MESSAGE UMsg; + + if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN) + { + return(FALSE); + } + + /* FIXME: Should pass current keyboard layout for this thread. */ + UState = ToUnicode(lpMsg->wParam, HIWORD(lpMsg->lParam), + QueueKeyStateTable, wp, 2, 0); + if (UState == 1) + { + NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR; + if (dead_char) + { + int i; + + if (wp[0] == ' ') wp[0] = dead_char; + if (dead_char == 0xa2) dead_char = '('; + else if (dead_char == 0xa8) dead_char = '"'; + else if (dead_char == 0xb2) dead_char = ';'; + else if (dead_char == 0xb4) dead_char = '\''; + else if (dead_char == 0xb7) dead_char = '<'; + else if (dead_char == 0xb8) dead_char = ','; + else if (dead_char == 0xff) dead_char = '.'; + for (i = 0; i < sizeof(accent_chars)/sizeof(accent_chars[0]); i++) + { + if ((accent_chars[i].ac_accent == dead_char) && + (accent_chars[i].ac_char == wp[0])) + { + wp[0] = accent_chars[i].ac_result; + break; + } + dead_char = 0; + } + NewMsg.hwnd = lpMsg->hwnd; + NewMsg.wParam = wp[0]; + NewMsg.lParam = lpMsg->lParam; + UMsg = MsqCreateMessage(&NewMsg); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg); + return(TRUE); + } + } + else if (UState == -1) + { + NewMsg.message = + (lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR; + NewMsg.hwnd = lpMsg->hwnd; + NewMsg.wParam = wp[0]; + NewMsg.lParam = lpMsg->lParam; + dead_char = wp[0]; + UMsg = MsqCreateMessage(&NewMsg); + MsqPostMessage(PsGetWin32Thread()->MessageQueue, UMsg); + return(TRUE); + } + return(FALSE); +} diff --git a/subsys/win32k/ntuser/message.c b/subsys/win32k/ntuser/message.c new file mode 100644 index 0000000..b687dc4 --- /dev/null +++ b/subsys/win32k/ntuser/message.c @@ -0,0 +1,468 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Messages + * FILE: subsys/win32k/ntuser/message.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +W32kInitMessageImpl(VOID) +{ + return(STATUS_SUCCESS); +} + +NTSTATUS +W32kCleanupMessageImpl(VOID) +{ + return(STATUS_SUCCESS); +} + + +LRESULT STDCALL +NtUserDispatchMessage(CONST MSG* lpMsg) +{ + LRESULT Result; + ULONG PaintingFlag; + PWINDOW_OBJECT WindowObject; + NTSTATUS Status; + + /* Process timer messages. */ + if (lpMsg->message == WM_TIMER) + { + if (lpMsg->lParam) + { + /* FIXME: Call hooks. */ + + /* FIXME: Check for continuing validity of timer. */ + + return(W32kCallWindowProc((WNDPROC)lpMsg->lParam, + lpMsg->hwnd, + lpMsg->message, + lpMsg->wParam, + 0 /* GetTickCount() */)); + } + } + + /* Get the window object. */ + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable, + lpMsg->hwnd, + otWindow, + (PVOID*)&WindowObject); + if (!NT_SUCCESS(Status)) + { + return(0); + } + + /* FIXME: Check for paint message. */ + PaintingFlag = (lpMsg->message == WM_PAINT); + if (PaintingFlag) + { + WindowObject->Flags |= WINDOWOBJECT_NEED_BEGINPAINT; + } + + /* FIXME: Call hook procedures. */ + + /* Call the window procedure. */ + Result = W32kCallWindowProc(NULL /* WndProc */, + lpMsg->hwnd, + lpMsg->message, + lpMsg->wParam, + lpMsg->lParam); + + if (PaintingFlag && WindowObject->Flags & WINDOWOBJECT_NEED_BEGINPAINT && + WindowObject->UpdateRegion) + { + DbgBreakPoint(); + } + + return(Result); +} + +BOOL STDCALL +NtUserGetMessage(LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax) +/* + * FUNCTION: Get a message from the calling thread's message queue. + * ARGUMENTS: + * lpMsg - Pointer to the structure which receives the returned message. + * hWnd - Window whose messages are to be retrieved. + * wMsgFilterMin - Integer value of the lowest message value to be + * retrieved. + * wMsgFilterMax - Integer value of the highest message value to be + * retrieved. + */ +{ + PUSER_MESSAGE_QUEUE ThreadQueue; + BOOLEAN Present; + PUSER_MESSAGE Message; + NTSTATUS Status; + + /* Initialize the thread's win32 state if necessary. */ + W32kGuiCheck(); + + ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue; + + do + { + /* Dispatch sent messages here. */ + while (MsqDispatchOneSentMessage(ThreadQueue)); + + /* Now look for a quit message. */ + /* FIXME: WINE checks the message number filter here. */ + if (ThreadQueue->QuitPosted) + { + lpMsg->hwnd = hWnd; + lpMsg->message = WM_QUIT; + lpMsg->wParam = ThreadQueue->QuitExitCode; + lpMsg->lParam = 0; + ThreadQueue->QuitPosted = FALSE; + return(FALSE); + } + + /* Now check for normal messages. */ + Present = MsqFindMessage(ThreadQueue, + FALSE, + TRUE, + hWnd, + wMsgFilterMin, + wMsgFilterMax, + &Message); + if (Present) + { + RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG)); + ExFreePool(Message); + return(TRUE); + } + + /* Check for hardware events. */ + Present = MsqFindMessage(ThreadQueue, + TRUE, + TRUE, + hWnd, + wMsgFilterMin, + wMsgFilterMax, + &Message); + if (Present) + { + RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG)); + ExFreePool(Message); + return(TRUE); + } + + /* Check for sent messages again. */ + while (MsqDispatchOneSentMessage(ThreadQueue)); + + /* Check for paint messages. */ + if (ThreadQueue->PaintPosted) + { + PWINDOW_OBJECT WindowObject; + + lpMsg->hwnd = PaintingFindWinToRepaint(hWnd, PsGetWin32Thread()); + lpMsg->message = WM_PAINT; + lpMsg->wParam = lpMsg->lParam = 0; + + WindowObject = W32kGetWindowObject(lpMsg->hwnd); + if (WindowObject != NULL) + { + if (WindowObject->Style & WS_MINIMIZE && + (HICON)NtUserGetClassLong(lpMsg->hwnd, GCL_HICON) != NULL) + { + lpMsg->message = WM_PAINTICON; + lpMsg->wParam = 1; + } + + if (lpMsg->hwnd == NULL || lpMsg->hwnd == hWnd || + W32kIsChildWindow(hWnd, lpMsg->hwnd)) + { + if (WindowObject->Flags & WINDOWOBJECT_NEED_INTERNALPAINT && + WindowObject->UpdateRegion == NULL) + { + WindowObject->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; + MsqDecPaintCountQueue(WindowObject->MessageQueue); + } + } + W32kReleaseWindowObject(WindowObject); + } + + return(TRUE); + } + + /* Nothing found so far. Wait for new messages. */ + Status = MsqWaitForNewMessages(ThreadQueue); + } + while (Status >= STATUS_WAIT_0 && Status <= STATUS_WAIT_63); + return((BOOLEAN)(-1)); +} + +DWORD +STDCALL +NtUserMessageCall( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6) +{ + UNIMPLEMENTED + + return 0; +} + +BOOL STDCALL +NtUserPeekMessage(LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax, + UINT wRemoveMsg) +/* + * FUNCTION: Get a message from the calling thread's message queue. + * ARGUMENTS: + * lpMsg - Pointer to the structure which receives the returned message. + * hWnd - Window whose messages are to be retrieved. + * wMsgFilterMin - Integer value of the lowest message value to be + * retrieved. + * wMsgFilterMax - Integer value of the highest message value to be + * retrieved. + * wRemoveMsg - Specificies whether or not to remove messages from the queue after processing + */ +{ + PUSER_MESSAGE_QUEUE ThreadQueue; + BOOLEAN Present; + PUSER_MESSAGE Message; + BOOLEAN RemoveMessages; + + /* Initialize the thread's win32 state if necessary. */ + W32kGuiCheck(); + + ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue; + + /* Inspect wRemoveMsg flags */ + /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */ + RemoveMessages = wRemoveMsg & PM_REMOVE; + + /* FIXME: Dispatch sent messages here. */ + + /* Now look for a quit message. */ + /* FIXME: WINE checks the message number filter here. */ + if (ThreadQueue->QuitPosted) + { + lpMsg->hwnd = hWnd; + lpMsg->message = WM_QUIT; + lpMsg->wParam = ThreadQueue->QuitExitCode; + lpMsg->lParam = 0; + ThreadQueue->QuitPosted = FALSE; + return(FALSE); + } + + /* Now check for normal messages. */ + Present = MsqFindMessage(ThreadQueue, + FALSE, + RemoveMessages, + hWnd, + wMsgFilterMin, + wMsgFilterMax, + &Message); + if (Present) + { + RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG)); + ExFreePool(Message); + return(TRUE); + } + + /* Check for hardware events. */ + Present = MsqFindMessage(ThreadQueue, + TRUE, + RemoveMessages, + hWnd, + wMsgFilterMin, + wMsgFilterMax, + &Message); + if (Present) + { + RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG)); + ExFreePool(Message); + return(TRUE); + } + + /* FIXME: Check for sent messages again. */ + + /* FIXME: Check for paint messages. */ + + return((BOOLEAN)(-1)); +} + +BOOL STDCALL +NtUserPostMessage(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + UNIMPLEMENTED; + + return 0; +} + +BOOL STDCALL +NtUserPostThreadMessage(DWORD idThread, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + UNIMPLEMENTED; + + return 0; +} + +DWORD STDCALL +NtUserQuerySendMessage(DWORD Unknown0) +{ + UNIMPLEMENTED; + + return 0; +} + +LRESULT STDCALL +W32kSendMessage(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + BOOL KernelMessage) +{ + LRESULT Result; + NTSTATUS Status; + PWINDOW_OBJECT Window; + + /* FIXME: Check for a broadcast or topmost destination. */ + + /* FIXME: Call hooks. */ + + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable, + hWnd, + otWindow, + (PVOID*)&Window); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + /* FIXME: Check for an exiting window. */ + + if (Window->MessageQueue == PsGetWin32Thread()->MessageQueue) + { + if (KernelMessage) + { + Result = W32kCallTrampolineWindowProc(NULL, hWnd, Msg, wParam, + lParam); + return(Result); + } + else + { + Result = W32kCallWindowProc(NULL, hWnd, Msg, wParam, lParam); + return(Result); + } + } + else + { + PUSER_SENT_MESSAGE Message; + PKEVENT CompletionEvent; + + CompletionEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); + KeInitializeEvent(CompletionEvent, NotificationEvent, FALSE); + + Message = ExAllocatePool(NonPagedPool, sizeof(USER_SENT_MESSAGE)); + Message->Msg.hwnd = hWnd; + Message->Msg.message = Msg; + Message->Msg.wParam = wParam; + Message->Msg.lParam = lParam; + Message->CompletionEvent = CompletionEvent; + Message->Result = &Result; + Message->CompletionQueue = NULL; + Message->CompletionCallback = NULL; + MsqSendMessage(Window->MessageQueue, Message); + + ObmDereferenceObject(Window); + Status = KeWaitForSingleObject(CompletionEvent, + UserRequest, + UserMode, + FALSE, + NULL); + if (Status == STATUS_WAIT_0) + { + return(Result); + } + else + { + return(FALSE); + } + } +} + +LRESULT STDCALL +NtUserSendMessage(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + return(W32kSendMessage(hWnd, Msg, wParam, lParam, FALSE)); +} + +BOOL STDCALL +NtUserSendMessageCallback(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam, + SENDASYNCPROC lpCallBack, + ULONG_PTR dwData) +{ + return(0); +} + +BOOL STDCALL +NtUserSendNotifyMessage(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) +{ + UNIMPLEMENTED; + + return 0; +} + +BOOL STDCALL +NtUserWaitMessage(VOID) +{ + UNIMPLEMENTED; + + return 0; +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/metric.c b/subsys/win32k/ntuser/metric.c new file mode 100644 index 0000000..819214a --- /dev/null +++ b/subsys/win32k/ntuser/metric.c @@ -0,0 +1,69 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window classes + * FILE: subsys/win32k/ntuser/class.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +ULONG STDCALL +NtUserGetSystemMetrics(ULONG Index) +{ + switch (Index) + { + case SM_CXSCREEN: + return(640); + case SM_CYSCREEN: + return(480); + case SM_CXMINTRACK: + return(100); + case SM_CYMINTRACK: + return(28); + case SM_CXDLGFRAME: + return(4); + case SM_CYDLGFRAME: + return(4); + case SM_CXFRAME: + return(5); + case SM_CYFRAME: + return(5); + case SM_CXBORDER: + return(1); + case SM_CYBORDER: + return(1); + case SM_CXVSCROLL: + return(17); + case SM_CYHSCROLL: + return(17); + case SM_CYCAPTION: + return(20); + case SM_CXSIZE: + case SM_CYSIZE: + return(18); + case SM_CXSMSIZE: + case SM_CYSMSIZE: + return(14); + default: + return(0xFFFFFFFF); + } +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/msgqueue.c b/subsys/win32k/ntuser/msgqueue.c new file mode 100644 index 0000000..f86146c --- /dev/null +++ b/subsys/win32k/ntuser/msgqueue.c @@ -0,0 +1,602 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Message queues + * FILE: subsys/win32k/ntuser/msgqueue.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define SYSTEM_MESSAGE_QUEUE_SIZE (256) + +static MSG SystemMessageQueue[SYSTEM_MESSAGE_QUEUE_SIZE]; +static ULONG SystemMessageQueueHead = 0; +static ULONG SystemMessageQueueTail = 0; +static ULONG SystemMessageQueueCount = 0; +static KSPIN_LOCK SystemMessageQueueLock; + +static ULONG HardwareMessageQueueStamp = 0; +static LIST_ENTRY HardwareMessageQueueHead; +static FAST_MUTEX HardwareMessageQueueLock; + +static KEVENT HardwareMessageEvent; + +/* FUNCTIONS *****************************************************************/ + +VOID +MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) +{ + ExAcquireFastMutex(&Queue->Lock); + Queue->PaintCount++; + Queue->PaintPosted = TRUE; + ExReleaseFastMutex(&Queue->Lock); +} + +VOID +MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue) +{ + ExAcquireFastMutex(&Queue->Lock); + Queue->PaintCount--; + if (Queue->PaintCount == 0) + { + Queue->PaintPosted = FALSE; + } + ExReleaseFastMutex(&Queue->Lock); +} + + +NTSTATUS +MsqInitializeImpl(VOID) +{ + /*CurrentFocusMessageQueue = NULL;*/ + InitializeListHead(&HardwareMessageQueueHead); + KeInitializeEvent(&HardwareMessageEvent, NotificationEvent, 0); + KeInitializeSpinLock(&SystemMessageQueueLock); + ExInitializeFastMutex(&HardwareMessageQueueLock); + return(STATUS_SUCCESS); +} + +VOID +MsqInsertSystemMessage(MSG* Msg) +{ + KIRQL OldIrql; + + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + if (SystemMessageQueueCount == SYSTEM_MESSAGE_QUEUE_SIZE) + { + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + return; + } + SystemMessageQueue[SystemMessageQueueTail] = *Msg; + SystemMessageQueueTail = + (SystemMessageQueueTail + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; + SystemMessageQueueCount++; + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + KeSetEvent(&HardwareMessageEvent, IO_NO_INCREMENT, FALSE); +} + +BOOL STATIC +MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh, + PUSER_MESSAGE Message, BOOL Remove, + PWINDOW_OBJECT ScopeWin, PUSHORT HitTest, + PPOINT ScreenPoint, PBOOL MouseClick) +{ + static ULONG ClkTime = 0; + static USHORT ClkMessage = 0; + static HWND ClkWnd = 0; + static POINT ClkPos = {0, 0}; + + USHORT Msg = Message->Msg.message; + PWINDOW_OBJECT Window; + POINT Point; + ULONG Click = 0; + + /* FIXME: Handle window capture. */ + + *HitTest = WinPosWindowFromPoint(ScopeWin, Message->Msg.pt, &Window); + + if (Window->MessageQueue != PsGetWin32Thread()->MessageQueue) + { + ExAcquireFastMutex(&Window->MessageQueue->Lock); + InsertTailList(&Window->MessageQueue->HardwareMessagesListHead, + &Message->ListEntry); + ExReleaseFastMutex(&Window->MessageQueue->Lock); + KeSetEvent(&Window->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); + return(FALSE); + } + + if (hWnd != NULL && Window->Self != hWnd && + !W32kIsChildWindow(hWnd, Window->Self)) + { + return(FALSE); + } + + if (Msg == WM_LBUTTONDOWN || Msg == WM_RBUTTONDOWN || Msg == WM_MBUTTONDOWN) + { + (*MouseClick) = Click = 1; + } + if (Click) + { + if (W32kGetClassLong(Window, GCL_STYLE) & CS_DBLCLKS || + (*HitTest) != HTCLIENT) + { + if (Msg == ClkMessage && + Window->Self == ClkWnd && + (Message->Msg.time - ClkTime) < 452 && + abs(Message->Msg.pt.x - ClkPos.x) < 2 && + abs(Message->Msg.pt.y - ClkPos.y) < 2) + { + Msg += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); + Click++; + } + } + } + + *ScreenPoint = Message->Msg.pt; + + if ((*HitTest) != HTCLIENT) + { + Msg += WM_NCMOUSEMOVE - WM_MOUSEMOVE; + Message->Msg.wParam = *HitTest; + } + else + { + Point = Message->Msg.pt; + + Point.x -= Window->ClientRect.left; + Point.y -= Window->ClientRect.top; + } + + /* FIXME: Check message filter. */ + + if (Remove && Click) + { + if (Click == 1) + { + ClkTime = Message->Msg.time; + ClkMessage = Msg; + ClkWnd = Window->Self; + ClkPos = (*ScreenPoint); + } + else + { + ClkTime = 0; + ClkWnd = NULL; + } + } + + Message->Msg.hwnd = Window->Self; + Message->Msg.message = Msg; + Message->Msg.lParam = MAKELONG(Point.x, Point.y); + + return(TRUE); +} + +BOOL +MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd, + UINT FilterLow, UINT FilterHigh, BOOL Remove, + PUSER_MESSAGE* Message) +{ + KIRQL OldIrql; + USHORT HitTest; + POINT ScreenPoint; + BOOL Accept; + BOOL MouseClick; + PLIST_ENTRY CurrentEntry; + ULONG ActiveStamp; + PWINDOW_OBJECT DesktopWindow; + + DesktopWindow = W32kGetWindowObject(W32kGetDesktopWindow()); + + /* Process messages in the message queue itself. */ + ExAcquireFastMutex(&MessageQueue->Lock); + CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink; + while (CurrentEntry != &MessageQueue->HardwareMessagesListHead) + { + PUSER_MESSAGE Current = + CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); + CurrentEntry = CurrentEntry->Flink; + RemoveEntryList(&Current->ListEntry); + if (Current->Msg.message >= WM_MOUSEFIRST && + Current->Msg.message <= WM_MOUSELAST) + { + Accept = MsqTranslateMouseMessage(hWnd, FilterLow, FilterHigh, + Current, Remove, + DesktopWindow, &HitTest, + &ScreenPoint, &MouseClick); + if (Accept) + { + RemoveEntryList(&Current->ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); + *Message = Current; + W32kReleaseWindowObject(DesktopWindow); + return(TRUE); + } + } + CurrentEntry = CurrentEntry->Flink; + } + ExReleaseFastMutex(&MessageQueue->Lock); + + /* Now try the global queue. */ + ExAcquireFastMutex(&HardwareMessageQueueLock); + /* Transfer all messages from the DPC accessible queue to the main queue. */ + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + while (SystemMessageQueueCount > 0) + { + PUSER_MESSAGE UserMsg; + MSG Msg; + + Msg = SystemMessageQueue[SystemMessageQueueHead]; + SystemMessageQueueHead = + (SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; + SystemMessageQueueCount--; + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + UserMsg = ExAllocatePool(NonPagedPool, sizeof(USER_MESSAGE)); + UserMsg->Msg = Msg; + InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry); + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + } + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + HardwareMessageQueueStamp++; + + /* Process messages in the queue until we find one to return. */ + CurrentEntry = HardwareMessageQueueHead.Flink; + while (CurrentEntry != &HardwareMessageQueueHead) + { + PUSER_MESSAGE Current = + CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); + CurrentEntry = CurrentEntry->Flink; + RemoveEntryList(&Current->ListEntry); + if (Current->Msg.message >= WM_MOUSEFIRST && + Current->Msg.message <= WM_MOUSELAST) + { + ActiveStamp = HardwareMessageQueueStamp; + ExReleaseFastMutex(&HardwareMessageQueueLock); + /* Translate the message. */ + Accept = MsqTranslateMouseMessage(hWnd, FilterLow, FilterHigh, + Current, Remove, + DesktopWindow, &HitTest, + &ScreenPoint, &MouseClick); + ExAcquireFastMutex(&HardwareMessageQueueLock); + if (Accept) + { + /* Check for no more messages in the system queue. */ + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + if (SystemMessageQueueCount == 0 && + IsListEmpty(&HardwareMessageQueueHead)) + { + KeClearEvent(&HardwareMessageEvent); + } + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + + /* + If we aren't removing the message then add it to the private + queue. + */ + if (!Remove) + { + InsertTailList(&MessageQueue->HardwareMessagesListHead, + &Current->ListEntry); + } + ExReleaseFastMutex(&HardwareMessageQueueLock); + *Message = Current; + W32kReleaseWindowObject(DesktopWindow); + return(TRUE); + } + /* If the contents of the queue changed then restart processing. */ + if (HardwareMessageQueueStamp != ActiveStamp) + { + CurrentEntry = HardwareMessageQueueHead.Flink; + continue; + } + } + } + /* Check if the system message queue is now empty. */ + KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql); + if (SystemMessageQueueCount == 0 && IsListEmpty(&HardwareMessageQueueHead)) + { + KeClearEvent(&HardwareMessageEvent); + } + KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql); + ExReleaseFastMutex(&HardwareMessageQueueLock); + + return(FALSE); +} + +VOID +MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + MSG Msg; + PUSER_MESSAGE Message; + + if (CurrentFocusMessageQueue == NULL) + { + return; + } + + Msg.hwnd = CurrentFocusMessageQueue->FocusWindow; + Msg.message = uMsg; + Msg.wParam = wParam; + Msg.lParam = lParam; + /* FIXME: Initialize time and point. */ + + Message = MsqCreateMessage(&Msg); + MsqPostMessage(CurrentFocusMessageQueue, Message, TRUE); +#endif +} + +VOID +MsqInitializeMessage(PUSER_MESSAGE Message, + LPMSG Msg) +{ + RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG)); +} + +PUSER_MESSAGE +MsqCreateMessage(LPMSG Msg) +{ + PUSER_MESSAGE Message; + + Message = (PUSER_MESSAGE)ExAllocatePool(PagedPool, sizeof(USER_MESSAGE)); + if (!Message) + { + return NULL; + } + + MsqInitializeMessage(Message, Msg); + + return Message; +} + +VOID +MsqDestroyMessage(PUSER_MESSAGE Message) +{ + ExFreePool(Message); +} + +VOID +MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue) +{ + PLIST_ENTRY ListEntry; + PUSER_SENT_MESSAGE_NOTIFY Message; + + while (!IsListEmpty(&MessageQueue->SentMessagesListHead)) + { + ExAcquireFastMutex(&MessageQueue->Lock); + ListEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead); + Message = CONTAINING_RECORD(ListEntry, USER_SENT_MESSAGE_NOTIFY, + ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); + + W32kCallSentMessageCallback(Message->CompletionCallback, + Message->hWnd, + Message->Msg, + Message->CompletionCallbackContext, + Message->Result); + } +} + +BOOLEAN +MsqPeekSentMessages(PUSER_MESSAGE_QUEUE MessageQueue) +{ + return(!IsListEmpty(&MessageQueue->SentMessagesListHead)); +} + +BOOLEAN +MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue) +{ + PUSER_SENT_MESSAGE Message; + PLIST_ENTRY Entry; + LRESULT Result; + PUSER_SENT_MESSAGE_NOTIFY NotifyMessage; + + ExAcquireFastMutex(&MessageQueue->Lock); + if (IsListEmpty(&MessageQueue->SentMessagesListHead)) + { + ExReleaseFastMutex(&MessageQueue->Lock); + return(FALSE); + } + Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead); + Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); + + /* Call the window procedure. */ + Result = W32kCallWindowProc(NULL, + Message->Msg.hwnd, + Message->Msg.message, + Message->Msg.wParam, + Message->Msg.lParam); + + /* Let the sender know the result. */ + if (Message->Result != NULL) + { + *Message->Result = Result; + } + + /* Notify the sender. */ + if (Message->CompletionEvent != NULL) + { + KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE); + } + + /* Notify the sender if they specified a callback. */ + if (Message->CompletionCallback != NULL) + { + NotifyMessage = ExAllocatePool(NonPagedPool, + sizeof(USER_SENT_MESSAGE_NOTIFY)); + NotifyMessage->CompletionCallback = + Message->CompletionCallback; + NotifyMessage->CompletionCallbackContext = + Message->CompletionCallbackContext; + NotifyMessage->Result = Result; + NotifyMessage->hWnd = Message->Msg.hwnd; + NotifyMessage->Msg = Message->Msg.message; + MsqSendNotifyMessage(Message->CompletionQueue, NotifyMessage); + } + + ExFreePool(Message); + return(TRUE); +} + +VOID +MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE_NOTIFY NotifyMessage) +{ + ExAcquireFastMutex(&MessageQueue->Lock); + InsertTailList(&MessageQueue->NotifyMessagesListHead, + &NotifyMessage->ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); +} + +VOID +MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue, + PUSER_SENT_MESSAGE Message) +{ + ExAcquireFastMutex(&MessageQueue->Lock); + InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry); + ExReleaseFastMutex(&MessageQueue->Lock); +} + +VOID +MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE Message) +{ + ExAcquireFastMutex(&MessageQueue->Lock); + InsertTailList(&MessageQueue->PostedMessagesListHead, + &Message->ListEntry); + KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); + ExReleaseFastMutex(&MessageQueue->Lock); +} + +BOOLEAN +MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, + IN BOOLEAN Hardware, + IN BOOLEAN Remove, + IN HWND Wnd, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT PUSER_MESSAGE* Message) +{ + PLIST_ENTRY CurrentEntry; + PUSER_MESSAGE CurrentMessage; + PLIST_ENTRY ListHead; + + if (Hardware) + { + return(MsqPeekHardwareMessage(MessageQueue, Wnd, + MsgFilterLow, MsgFilterHigh, + Remove, Message)); + } + + ExAcquireFastMutex(&MessageQueue->Lock); + CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; + ListHead = &MessageQueue->PostedMessagesListHead; + while (CurrentEntry != ListHead) + { + CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, + ListEntry); + if ((Wnd == 0 || Wnd == CurrentMessage->Msg.hwnd) && + ((MsgFilterLow == 0 && MsgFilterHigh == 0) || + (MsgFilterLow <= CurrentMessage->Msg.message && + MsgFilterHigh >= CurrentMessage->Msg.message))) + { + if (Remove) + { + RemoveEntryList(&CurrentMessage->ListEntry); + } + ExReleaseFastMutex(&MessageQueue->Lock); + *Message = CurrentMessage; + return(TRUE); + } + CurrentEntry = CurrentEntry->Flink; + } + ExReleaseFastMutex(&MessageQueue->Lock); + return(FALSE); +} + +NTSTATUS +MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue) +{ + PVOID WaitObjects[2] = {&MessageQueue->NewMessages, &HardwareMessageEvent}; + return(KeWaitForMultipleObjects(2, + WaitObjects, + WaitAny, + Executive, + UserMode, + TRUE, + NULL, + NULL)); +} + +VOID +MsqInitializeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue) +{ + InitializeListHead(&MessageQueue->PostedMessagesListHead); + InitializeListHead(&MessageQueue->SentMessagesListHead); + InitializeListHead(&MessageQueue->HardwareMessagesListHead); + ExInitializeFastMutex(&MessageQueue->Lock); + MessageQueue->QuitPosted = FALSE; + MessageQueue->QuitExitCode = 0; + KeInitializeEvent(&MessageQueue->NewMessages, NotificationEvent, FALSE); + MessageQueue->QueueStatus = 0; + MessageQueue->FocusWindow = NULL; +} + +VOID +MsqFreeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue) +{ + PLIST_ENTRY CurrentEntry; + PUSER_MESSAGE CurrentMessage; + + CurrentEntry = MessageQueue->PostedMessagesListHead.Flink; + while (CurrentEntry != &MessageQueue->PostedMessagesListHead) + { + CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, + ListEntry); + CurrentEntry = CurrentEntry->Flink; + ExFreePool(CurrentMessage); + } +} + +PUSER_MESSAGE_QUEUE +MsqCreateMessageQueue(VOID) +{ + PUSER_MESSAGE_QUEUE MessageQueue; + + MessageQueue = (PUSER_MESSAGE_QUEUE)ExAllocatePool(PagedPool, + sizeof(USER_MESSAGE_QUEUE)); + if (!MessageQueue) + { + return NULL; + } + + MsqInitializeMessageQueue(MessageQueue); + + return MessageQueue; +} + +VOID +MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue) +{ + MsqFreeMessageQueue(MessageQueue); + ExFreePool(MessageQueue); +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/painting.c b/subsys/win32k/ntuser/painting.c new file mode 100644 index 0000000..938ccb5 --- /dev/null +++ b/subsys/win32k/ntuser/painting.c @@ -0,0 +1,832 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Painting + * FILE: subsys/win32k/ntuser/painting.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define UNC_DELAY_NCPAINT (0x00000001) +#define UNC_IN_BEGINPAINT (0x00000002) +#define UNC_CHECK (0x00000004) +#define UNC_REGION (0x00000008) +#define UNC_ENTIRE (0x00000010) +#define UNC_UPDATE (0x00000020) + +/* FUNCTIONS *****************************************************************/ + +HRGN STATIC +PaintDoPaint(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags, ULONG ExFlags) +{ + HDC hDC; + HWND hWnd = Window->Self; + BOOL bIcon = (Window->Style & WS_MINIMIZE) && + NtUserGetClassLong(hWnd, GCL_HICON); + + if (ExFlags & RDW_EX_DELAY_NCPAINT || + PaintHaveToDelayNCPaint(Window, 0)) + { + ExFlags |= RDW_EX_DELAY_NCPAINT; + } + + if (Flags & RDW_UPDATENOW) + { + if (Window->UpdateRegion != NULL) + { + NtUserSendMessage(hWnd, bIcon ? WM_PAINTICON : WM_PAINT, bIcon, 0); + } + } + else if (Flags & RDW_ERASENOW || ExFlags & RDW_EX_TOPFRAME) + { + UINT Dcx = DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN | + DCX_WINDOWPAINT | DCX_CACHE; + HRGN hRgnRet; + + hRgnRet = + PaintUpdateNCRegion(Window, + hRgn, + UNC_REGION | UNC_CHECK | + ((ExFlags & RDW_EX_TOPFRAME) ? UNC_ENTIRE : 0) | + ((ExFlags & RDW_EX_DELAY_NCPAINT) ? + UNC_DELAY_NCPAINT : 0)); + if (hRgnRet != NULL) + { + if (hRgnRet != (HRGN)1) + { + hRgn = hRgnRet; + } + else + { + hRgnRet = NULL; + } + if (Window->Flags & WINDOWOBJECT_NEED_ERASEBACKGRD) + { + if (bIcon) + { + Dcx |= DCX_WINDOW; + } + if (hRgnRet) + { + W32kOffsetRgn(hRgnRet, + Window->WindowRect.left - + Window->ClientRect.left, + Window->WindowRect.top - + Window->ClientRect.top); + } + else + { + Dcx &= ~DCX_INTERSECTRGN; + } + if ((hDC = NtUserGetDCEx(hWnd, hRgnRet, Dcx)) != NULL) + { + LRESULT Result; + Result = NtUserSendMessage(hWnd, bIcon ? WM_ICONERASEBKGND : + WM_ERASEBKGND, (WPARAM)hDC, 0); + Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD; + NtUserReleaseDC(hWnd, hDC); + } + } + } + } + + /* FIXME: Check that the window is still valid at this point. */ + + ExFlags &= ~RDW_EX_TOPFRAME; + + /* FIXME: Paint child windows. */ + + return(hRgn); +} + +VOID STATIC +PaintUpdateInternalPaint(PWINDOW_OBJECT Window, ULONG Flags) +{ + if (Flags & RDW_INTERNALPAINT) + { + if (Window->UpdateRegion == NULL && + !(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) + { + MsqIncPaintCountQueue(Window->MessageQueue); + } + Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; + } + else if (Flags & RDW_NOINTERNALPAINT) + { + if (Window->UpdateRegion == NULL && + (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) + { + MsqDecPaintCountQueue(Window->MessageQueue); + } + Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; + } +} + +VOID STATIC +PaintValidateParent(PWINDOW_OBJECT Child) +{ + HWND DesktopHandle = W32kGetDesktopWindow(); + PWINDOW_OBJECT Parent = Child->Parent; + PWINDOW_OBJECT Desktop = W32kGetWindowObject(DesktopHandle); + HRGN hRgn; + + if (Child->UpdateRegion == (HANDLE)1) + { + RECT Rect; + + Rect.left = Rect.top = 0; + Rect.right = Child->WindowRect.right - Child->WindowRect.left; + Rect.bottom = Child->WindowRect.bottom - Child->WindowRect.top; + + hRgn = UnsafeW32kCreateRectRgnIndirect(&Rect); + } + else + { + hRgn = Child->UpdateRegion; + } + + while (Parent != NULL && Parent != Desktop) + { + if (!(Parent->Style & WS_CLIPCHILDREN)) + { + if (Parent->UpdateRegion != (HANDLE)0) + { + POINT Offset; + + if (Parent->UpdateRegion == (HANDLE)1) + { + RECT Rect1; + + Rect1.left = Rect1.top = 0; + Rect1.right = Parent->WindowRect.right - + Parent->WindowRect.left; + Rect1.bottom = Parent->WindowRect.bottom - + Parent->WindowRect.top; + + Parent->UpdateRegion = + UnsafeW32kCreateRectRgnIndirect(&Rect1); + } + Offset.x = Child->WindowRect.left - Parent->WindowRect.left; + Offset.y = Child->WindowRect.top - Parent->WindowRect.top; + W32kOffsetRgn(hRgn, Offset.x, Offset.y); + W32kCombineRgn(Parent->UpdateRegion, Parent->UpdateRegion, hRgn, + RGN_DIFF); + W32kOffsetRgn(hRgn, -Offset.x, -Offset.y); + } + } + Parent = Parent->Parent; + } + if (hRgn != Child->UpdateRegion) + { + W32kDeleteObject(Child->UpdateRegion); + } + W32kReleaseWindowObject(Desktop); +} + +VOID STATIC +PaintUpdateRgns(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags, + BOOL First) +{ + BOOL HadOne = Window->UpdateRegion != NULL && hRgn; + BOOL HasChildren = !IsListEmpty(&Window->ChildrenListHead) && + !(Flags & RDW_NOCHILDREN) && !(Window->Style & WS_MINIMIZE) && + ((Flags & RDW_ALLCHILDREN) || !(Window->Style & WS_CLIPCHILDREN)); + RECT Rect; + + Rect.left = Rect.top = 0; + Rect.right = Window->WindowRect.right - Window->WindowRect.left; + Rect.bottom = Window->WindowRect.bottom - Window->WindowRect.top; + + if (Flags & RDW_INVALIDATE) + { + if (hRgn > (HANDLE)1) + { + if (Window->UpdateRegion > (HANDLE)1) + { + W32kCombineRgn(Window->UpdateRegion, Window->UpdateRegion, + hRgn, RGN_OR); + Window->UpdateRegion = + REGION_CropRgn(Window->UpdateRegion, + Window->UpdateRegion, &Rect, NULL); + if (!HadOne) + { + W32kGetRgnBox(Window->UpdateRegion, &Rect); + if (W32kIsEmptyRect(&Rect)) + { + W32kDeleteObject(Window->UpdateRegion); + Window->UpdateRegion = NULL; + PaintUpdateInternalPaint(Window, Flags); + return; + } + } + } + else if (Window->UpdateRegion == 0) + { + Window->UpdateRegion = + REGION_CropRgn(Window->UpdateRegion, hRgn, &Rect, NULL); + if (!HadOne) + { + W32kGetRgnBox(Window->UpdateRegion, &Rect); + if (W32kIsEmptyRect(&Rect)) + { + W32kDeleteObject(Window->UpdateRegion); + Window->UpdateRegion = NULL; + PaintUpdateInternalPaint(Window, Flags); + return; + } + } + } + } + else if (hRgn == (HANDLE)1) + { + if (Window->UpdateRegion > (HANDLE)1) + { + W32kDeleteObject(Window->UpdateRegion); + } + Window->UpdateRegion = (HANDLE)1; + } + else + { + hRgn = Window->UpdateRegion; + } + + if (!HadOne && !(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) + { + MsqIncPaintCountQueue(Window->MessageQueue); + } + + if (Flags & RDW_FRAME) + { + Window->Flags |= WINDOWOBJECT_NEED_NCPAINT; + } + if (Flags & RDW_ERASE) + { + Window->Flags |= WINDOWOBJECT_NEED_ERASEBACKGRD; + } + Flags |= RDW_FRAME; + } + else if (Flags & RDW_VALIDATE) + { + if (Window->UpdateRegion != NULL) + { + if (hRgn > (HANDLE)1) + { + if (Window->UpdateRegion == (HANDLE)1) + { + Window->UpdateRegion = + UnsafeW32kCreateRectRgnIndirect(&Rect); + } + if (W32kCombineRgn(Window->UpdateRegion, + Window->UpdateRegion, hRgn, + RGN_DIFF) == NULLREGION) + { + if (Window->UpdateRegion > (HANDLE)1) + { + W32kDeleteObject(Window->UpdateRegion); + } + Window->UpdateRegion = NULL; + } + } + else + { + if (Window->UpdateRegion > (HANDLE)1) + { + W32kDeleteObject(Window->UpdateRegion); + } + Window->UpdateRegion = NULL; + } + + if (Window->UpdateRegion == NULL) + { + Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD; + if (!(Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) + { + MsqIncPaintCountQueue(Window->MessageQueue); + } + } + } + + if (Flags & RDW_NOFRAME) + { + Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; + } + if (Flags & RDW_NOERASE) + { + Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD; + } + } + + if (First && Window->UpdateRegion != NULL && (Flags & RDW_UPDATENOW)) + { + PaintValidateParent(Window); + } + + if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) + { + if (hRgn > (HANDLE)1 && HasChildren) + { + POINT Total = {0, 0}; + POINT PrevOrign = {0, 0}; + POINT Client; + PWINDOW_OBJECT Child; + PLIST_ENTRY ChildListEntry; + + Client.x = Window->ClientRect.left - Window->WindowRect.left; + Client.y = Window->ClientRect.top - Window->WindowRect.top; + + ChildListEntry = Window->ChildrenListHead.Flink; + while (ChildListEntry != &Window->ChildrenListHead) + { + Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT, + SiblingListEntry); + if (Child->Style & WS_VISIBLE) + { + POINT Offset; + + Rect.left = Window->WindowRect.left + Client.x; + Rect.right = Window->WindowRect.right + Client.x; + Rect.top = Window->WindowRect.top + Client.y; + Rect.bottom = Window->WindowRect.bottom + Client.y; + + Offset.x = Rect.left - PrevOrign.x; + Offset.y = Rect.top - PrevOrign.y; + W32kOffsetRect(&Rect, -Total.x, -Total.y); + + if (W32kRectInRegion(hRgn, &Rect)) + { + W32kOffsetRgn(hRgn, -Total.x, -Total.y); + PaintUpdateRgns(Child, hRgn, Flags, FALSE); + PrevOrign.x = Rect.left + Total.x; + PrevOrign.y = Rect.right + Total.y; + Total.x += Offset.x; + Total.y += Offset.y; + } + } + } + W32kOffsetRgn(hRgn, Total.x, Total.y); + HasChildren = FALSE; + } + } + + if (HasChildren) + { + PWINDOW_OBJECT Child; + PLIST_ENTRY ChildListEntry; + + ChildListEntry = Window->ChildrenListHead.Flink; + while (ChildListEntry != &Window->ChildrenListHead) + { + Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT, + SiblingListEntry); + if (Child->Style & WS_VISIBLE) + { + PaintUpdateRgns(Child, hRgn, Flags, FALSE); + } + } + } + + PaintUpdateInternalPaint(Window, Flags); +} + +BOOL +PaintRedrawWindow(HWND hWnd, const RECT* UpdateRect, HRGN UpdateRgn, + ULONG Flags, ULONG ExFlags) +{ + PWINDOW_OBJECT Window; + RECT Rect, Rect2; + POINT Pt; + HRGN hRgn; + + /* FIXME: Return if this is for a desktop. */ + + Window = W32kGetWindowObject(hWnd); + if (Window == NULL) + { + return(FALSE); + } + + if (Flags & RDW_FRAME) + { + Rect = Window->WindowRect; + } + else + { + Rect = Window->ClientRect; + } + + if (ExFlags & RDW_EX_XYWINDOW) + { + Pt.x = Pt.y = 0; + W32kOffsetRect(&Rect, -Window->WindowRect.left, -Window->WindowRect.top); + } + else + { + Pt.x = Window->ClientRect.left - Window->WindowRect.left; + Pt.y = Window->ClientRect.top - Window->WindowRect.top; + W32kOffsetRect(&Rect, -Window->ClientRect.left, -Window->WindowRect.top); + } + + if (Flags & RDW_INVALIDATE) + { + if (UpdateRgn != NULL) + { + if (Window->UpdateRegion != NULL) + { + hRgn = REGION_CropRgn(0, UpdateRgn, NULL, &Pt); + } + else + { + Window->UpdateRegion = REGION_CropRgn(0, UpdateRgn, &Rect, &Pt); + } + } + else if (UpdateRect != NULL) + { + if (!W32kIntersectRect(&Rect2, &Rect, UpdateRect)) + { + W32kReleaseWindowObject(Window); + if (hRgn != NULL && hRgn != (HRGN)1) + { + W32kDeleteObject(hRgn); + } + return(TRUE); + } + if (Window->UpdateRegion == NULL) + { + Window->UpdateRegion = + UnsafeW32kCreateRectRgnIndirect(&Rect2); + } + else + { + hRgn = UnsafeW32kCreateRectRgnIndirect(&Rect2); + } + } + else + { + if (Flags & RDW_FRAME) + { + hRgn = (HRGN)1; + } + else + { + W32kGetClientRect(hWnd, &Rect2); + hRgn = UnsafeW32kCreateRectRgnIndirect(&Rect2); + } + } + } + else if (Flags & RDW_VALIDATE) + { + /* FIXME: Implement this. */ + } + + PaintUpdateRgns(Window, hRgn, Flags, TRUE); + + hRgn = PaintDoPaint(Window, hRgn == (HANDLE)1 ? 0 : hRgn, Flags, ExFlags); + + if (hRgn != (HANDLE)1 && hRgn != UpdateRgn) + { + W32kDeleteObject(hRgn); + } + W32kReleaseWindowObject(Window); + return(TRUE); +} + +BOOL STDCALL +PaintHaveToDelayNCPaint(PWINDOW_OBJECT Window, ULONG Flags) +{ + if (Flags & UNC_DELAY_NCPAINT) + { + return(TRUE); + } + + if (Flags & UNC_IN_BEGINPAINT) + { + return(FALSE); + } + + Window = Window->Parent; + while (Window != NULL) + { + if (Window->Style & WS_CLIPCHILDREN && Window->UpdateRegion != NULL) + { + return(TRUE); + } + Window = Window->Parent; + } + return(FALSE); +} + +HWND STDCALL +PaintingFindWinToRepaint(HWND hWnd, PW32THREAD Thread) +{ + PWINDOW_OBJECT Window; + PWINDOW_OBJECT BaseWindow; + PLIST_ENTRY current_entry; + HWND hFoundWnd = NULL; + + if (hWnd == NULL) + { + ExAcquireFastMutex(&Thread->WindowListLock); + current_entry = Thread->WindowListHead.Flink; + while (current_entry != &Thread->WindowListHead) + { + Window = CONTAINING_RECORD(current_entry, WINDOW_OBJECT, + ThreadListEntry); + if (Window->Style & WS_VISIBLE) + { + hFoundWnd = + PaintingFindWinToRepaint(Window->Self, Thread); + if (hFoundWnd != NULL) + { + ExReleaseFastMutex(&Thread->WindowListLock); + return(hFoundWnd); + } + } + current_entry = current_entry->Flink; + } + ExReleaseFastMutex(&Thread->WindowListLock); + return(NULL); + } + + BaseWindow = W32kGetWindowObject(hWnd); + if (BaseWindow == NULL) + { + return(NULL); + } + if (BaseWindow->UpdateRegion != NULL || + BaseWindow->Flags & WINDOWOBJECT_NEED_INTERNALPAINT) + { + W32kReleaseWindowObject(BaseWindow); + return(hWnd); + } + + ExAcquireFastMutex(&BaseWindow->ChildrenListLock); + current_entry = Thread->WindowListHead.Flink; + while (current_entry != &Thread->WindowListHead) + { + Window = CONTAINING_RECORD(current_entry, WINDOW_OBJECT, + ThreadListEntry); + if (Window->Style & WS_VISIBLE) + { + hFoundWnd = PaintingFindWinToRepaint(Window->Self, Thread); + if (hFoundWnd != NULL) + { + break; + } + } + current_entry = current_entry->Flink; + } + ExReleaseFastMutex(&BaseWindow->ChildrenListLock); + W32kReleaseWindowObject(BaseWindow); + return(hFoundWnd); +} + +HRGN STDCALL +PaintUpdateNCRegion(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags) +{ + HRGN hRgnRet; + RECT ClientRect; + HRGN hClip = NULL; + + /* Desktop has no parent. */ + if (Window->Parent == NULL) + { + Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; + if (Window->UpdateRegion > (HANDLE)1) + { + hRgnRet = REGION_CropRgn(hRgn, Window->UpdateRegion, NULL, NULL); + } + else + { + hRgnRet = Window->UpdateRegion; + } + return(hRgnRet); + } + + if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT && + !PaintHaveToDelayNCPaint(Window, Flags)) + { + RECT UpdateRegionBox; + RECT Rect; + + Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; + W32kGetClientRect(Window, &ClientRect); + + if (Window->UpdateRegion > (HRGN)1) + { + W32kGetRgnBox(Window->UpdateRegion, &UpdateRegionBox); + W32kUnionRect(&Rect, &ClientRect, &UpdateRegionBox); + if (Rect.left != ClientRect.left || Rect.top != ClientRect.top || + Rect.right != ClientRect.right || Rect.right != ClientRect.right) + { + hClip = Window->UpdateRegion; + Window->UpdateRegion = REGION_CropRgn(hRgn, hClip, + &Rect, NULL); + if (Flags & UNC_REGION) + { + hRgnRet = hClip; + } + } + + if (Flags & UNC_CHECK) + { + W32kGetRgnBox(Window->UpdateRegion, &UpdateRegionBox); + if (W32kIsEmptyRect(&UpdateRegionBox)) + { + W32kDeleteObject(Window->UpdateRegion); + Window->UpdateRegion = NULL; + MsqDecPaintCountQueue(Window->MessageQueue); + Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD; + } + } + + if (!hClip && Window->UpdateRegion && Flags & UNC_REGION) + { + hRgnRet = REGION_CropRgn(hRgn, Window->UpdateRegion, NULL, + NULL); + } + } + else if (Window->UpdateRegion == (HRGN)1) + { + if (Flags & UNC_UPDATE) + { + Window->UpdateRegion = + UnsafeW32kCreateRectRgnIndirect(&ClientRect); + } + if (Flags & UNC_REGION) + { + hRgnRet = (HANDLE)1; + } + Flags |= UNC_ENTIRE; + } + } + else + { + if (Window->UpdateRegion > (HANDLE)1 && Flags & UNC_REGION) + { + hRgnRet = REGION_CropRgn(hRgn, Window->UpdateRegion, NULL, NULL); + } + else if (Window->UpdateRegion == (HANDLE)1 && Flags & UNC_UPDATE) + { + W32kGetClientRect(Window, &ClientRect); + Window->UpdateRegion = + UnsafeW32kCreateRectRgnIndirect(&ClientRect); + if (Flags & UNC_REGION) + { + hRgnRet = (HANDLE)1; + } + } + } + + if (hClip == NULL && Flags & UNC_ENTIRE) + { + if (RtlCompareMemory(&Window->WindowRect, &Window->ClientRect, + sizeof(RECT)) != sizeof(RECT)) + { + hClip = (HANDLE)1; + } + else + { + hClip = 0; + } + } + + if (hClip != 0) + { + if (hClip == hRgnRet && hRgnRet > (HANDLE)1) + { + hClip = W32kCreateRectRgn(0, 0, 0, 0); + W32kCombineRgn(hClip, hRgnRet, 0, RGN_COPY); + } + NtUserSendMessage(Window->Self, WM_NCPAINT, (WPARAM)hClip, 0); + if (hClip > (HANDLE)1 && hClip != hRgn && hClip != hRgnRet) + { + W32kDeleteObject(hClip); + /* FIXME: Need to check the window is still valid. */ + } + } + return(hRgnRet); +} + +BOOL STDCALL +NtUserEndPaint(HWND hWnd, CONST PAINTSTRUCT* lPs) +{ + NtUserReleaseDC(hWnd, lPs->hdc); + /* FIXME: Show claret. */ + return(TRUE); +} + +HDC STDCALL +NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs) +{ + BOOL IsIcon; + PWINDOW_OBJECT Window; + HRGN UpdateRegion; + RECT ClientRect; + RECT ClipRect; + NTSTATUS Status; + + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable, + hWnd, + otWindow, + (PVOID*)&Window); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + + IsIcon = Window->Style & WS_MINIMIZE && + NtUserGetClassLong(Window->Self, GCL_HICON); + + Window->Flags &= ~WINDOWOBJECT_NEED_BEGINPAINT; + + /* Send WM_NCPAINT */ + PaintUpdateNCRegion(Window, 0, UNC_UPDATE | UNC_IN_BEGINPAINT); + + /* FIXME: Check the window is still valid. */ + + UpdateRegion = Window->UpdateRegion; + Window->UpdateRegion = 0; + if (UpdateRegion != NULL || + (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)) + { + MsqDecPaintCountQueue(Window->MessageQueue); + } + Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; + + /* FIXME: Hide claret. */ + + if (NtUserGetClassLong(Window->Self, GCL_STYLE) & CS_PARENTDC) + { + if (UpdateRegion != NULL) + { + W32kDeleteObject(UpdateRegion); + } + lPs->hdc = NtUserGetDCEx(hWnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE | + (IsIcon ? DCX_WINDOW : 0)); + } + else + { + if (UpdateRegion != NULL) + { + W32kOffsetRgn(UpdateRegion, + Window->WindowRect.left - + Window->ClientRect.left, + Window->WindowRect.top - + Window->ClientRect.top); + } + lPs->hdc = NtUserGetDCEx(hWnd, UpdateRegion, DCX_INTERSECTRGN | + DCX_WINDOWPAINT | DCX_USESTYLE | + (IsIcon ? DCX_WINDOW : 0)); + } + + /* FIXME: Check for DC creation failure. */ + + W32kGetClientRect(Window, &ClientRect); + W32kGetClipBox(lPs->hdc, &ClipRect); + W32kLPtoDP(lPs->hdc, (LPPOINT)&ClipRect, 2); + W32kIntersectRect(&lPs->rcPaint, &ClientRect, &ClipRect); + W32kDPtoLP(lPs->hdc, (LPPOINT)&lPs->rcPaint, 2); + + if (Window->Flags & WINDOWOBJECT_NEED_ERASEBACKGRD) + { + BOOLEAN Result; + Window->Flags &= ~WINDOWOBJECT_NEED_ERASEBACKGRD; + Result = NtUserSendMessage(hWnd, + IsIcon ? WM_ICONERASEBKGND : WM_ERASEBKGND, + (WPARAM)lPs->hdc, + 0); + lPs->fErase = !Result; + } + else + { + lPs->fErase = FALSE; + } + + ObmDereferenceObject(Window); + return(lPs->hdc); +} diff --git a/subsys/win32k/ntuser/prop.c b/subsys/win32k/ntuser/prop.c new file mode 100644 index 0000000..758987d --- /dev/null +++ b/subsys/win32k/ntuser/prop.c @@ -0,0 +1,136 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window properties + * FILE: subsys/win32k/ntuser/prop.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +PPROPERTY +W32kGetProp(PWINDOW_OBJECT WindowObject, ATOM Atom) +{ + PLIST_ENTRY ListEntry; + PPROPERTY Property; + + ListEntry = WindowObject->PropListHead.Flink; + while (ListEntry != &WindowObject->PropListHead) + { + Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry); + if (Property->Atom == Atom) + { + return(Property); + } + ListEntry = ListEntry->Flink; + } + return(NULL); +} + +DWORD STDCALL +NtUserBuildPropList(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +HANDLE STDCALL +NtUserRemoveProp(HWND hWnd, ATOM Atom) +{ + PWINDOW_OBJECT WindowObject; + PPROPERTY Prop; + HANDLE Data; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + return(NULL); + } + + Prop = W32kGetProp(WindowObject, Atom); + if (Prop == NULL) + { + W32kReleaseWindowObject(WindowObject); + return(NULL); + } + Data = Prop->Data; + RemoveEntryList(&Prop->PropListEntry); + ExFreePool(Prop); + W32kReleaseWindowObject(WindowObject); + return(Data); +} + +HANDLE STDCALL +NtUserGetProp(HWND hWnd, ATOM Atom) +{ + PWINDOW_OBJECT WindowObject; + PPROPERTY Prop; + HANDLE Data = NULL; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + return(FALSE); + } + + Prop = W32kGetProp(WindowObject, Atom); + if (Prop != NULL) + { + Data = Prop->Data; + } + W32kReleaseWindowObject(WindowObject); + return(Data); +} + +BOOL STDCALL +NtUserSetProp(HWND hWnd, ATOM Atom, HANDLE Data) +{ + PWINDOW_OBJECT WindowObject; + PPROPERTY Prop; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + return(FALSE); + } + + Prop = W32kGetProp(WindowObject, Atom); + if (Prop == NULL) + { + Prop = ExAllocatePool(PagedPool, sizeof(PROPERTY)); + if (Prop == NULL) + { + W32kReleaseWindowObject(WindowObject); + return(FALSE); + } + Prop->Atom = Atom; + InsertTailList(&WindowObject->PropListHead, &Prop->PropListEntry); + } + Prop->Data = Data; + W32kReleaseWindowObject(WindowObject); + return(TRUE); +} diff --git a/subsys/win32k/ntuser/stubs.c b/subsys/win32k/ntuser/stubs.c new file mode 100644 index 0000000..e85cf53 --- /dev/null +++ b/subsys/win32k/ntuser/stubs.c @@ -0,0 +1,1938 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Native User stubs + * FILE: subsys/win32k/ntuser/stubs.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 04-06-2001 CSH Created + */ +#include + +#define NDEBUG +#include + + +DWORD +STDCALL +NtUserActivateKeyboardLayout( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserAttachThreadInput( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserBitBltSysBmp( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserBlockInput( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserBuildHwndList( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserBuildNameList( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + + +DWORD +STDCALL +NtUserCallHwnd( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallHwndLock( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallHwndOpt( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallHwndParam( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallHwndParamLock( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallMsgFilter( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallNoParam( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallOneParam( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCallTwoParam( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserChangeClipboardChain( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserChangeDisplaySettings( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCheckMenuItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserClipCursor( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCloseClipboard(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserConvertMemHandle( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCopyAcceleratorTable( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCountClipboardFormats(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCreateAcceleratorTable( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCreateCaret( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserCreateLocalMemHandle( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDdeGetQualityOfService( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDdeInitialize( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDdeSetQualityOfService( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDefSetText( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDeleteMenu( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDestroyAcceleratorTable( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDestroyCursor( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDestroyMenu( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDragDetect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDragObject( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDrawAnimatedRects( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDrawCaption( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDrawCaptionTemp( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDrawIconEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserDrawMenuBarTemp( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEmptyClipboard(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEnableMenuItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEnableScrollBar( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEndMenu(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEnumDisplayDevices( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEnumDisplayMonitors( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEnumDisplaySettings( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserEvent( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserExcludeUpdateRgn( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserFindExistingCursorIcon( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetAltTabInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetAsyncKeyState( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetCaretBlinkTime(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetCaretPos( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetClipboardData( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetClipboardFormatName( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetClipboardOwner(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetClipboardSequenceNumber(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetClipboardViewer(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetClipCursor( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetComboBoxInfo( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetControlBrush( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetControlColor( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetCPD( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetCursorFrameInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetCursorInfo( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetDoubleClickTime(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetGuiResources( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetGUIThreadInfo( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetIconInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetIconSize( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetImeHotKey( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetKeyboardLayoutList( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetKeyboardLayoutName( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetKeyboardState( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetKeyNameText( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetKeyState( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetListBoxInfo( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetMenuBarInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetMenuIndex( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetMenuItemRect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetMouseMovePointsEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetPriorityClipboardFormat( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetScrollBarInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetSystemMenu( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetThreadState( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetTitleBarInfo( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetUpdateRect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserGetUpdateRgn( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserHideCaret( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserHiliteMenuItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserImpersonateDdeClientWindow( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserInitializeClientPfnArrays( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserInitTask( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8, + DWORD Unknown9, + DWORD Unknown10) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserInvalidateRect( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserInvalidateRgn( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserIsClipboardFormatAvailable( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserKillTimer( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserLoadKeyboardLayoutEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserLockWorkStation(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserMapVirtualKeyEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserMenuItemFromPoint( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserMinMaximize( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserMNDragLeave(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserMNDragOver( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserModifyUserStartupInfoFlags( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserNotifyIMEStatus( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserNotifyWinEvent( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserOpenClipboard( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserQueryUserCounters( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserRegisterHotKey( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserRegisterTasklist( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserRemoveMenu( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + + +DWORD +STDCALL +NtUserSBGetParms( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserScrollDC( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6) + +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSendInput( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetCapture( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetClipboardData( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetClipboardViewer( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetConsoleReserveKeys( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetCursor( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetCursorContents( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetCursorIconData( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetDbgTag( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetFocus( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetImeHotKey( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetKeyboardState( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetMenu( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetMenuContextHelpId( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetMenuDefaultItem( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetMenuFlagRtoL( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetParent( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetRipFlags( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetScrollInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetSysColors( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetSystemCursor( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetSystemMenu( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetSystemTimer( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetThreadState( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSetTimer( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserShowCaret( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserShowScrollBar( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserSystemParametersInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserThunkedMenuInfo( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserThunkedMenuItemInfo( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserToUnicodeEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserTrackMouseEvent( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserTrackPopupMenuEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserTranslateAccelerator( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUnloadKeyboardLayout( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUnregisterHotKey( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUpdateInputContext( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUpdateInstance( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUpdatePerUserSystemParameters( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserUserHandleGrantAccess( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserValidateHandleSecure( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserValidateRect( + DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserVkKeyScanEx( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserWaitForInputIdle( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserWaitForMsgAndEvent( + DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserWin32PoolAllocationStats( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD +STDCALL +NtUserYieldTask(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/userobj.c b/subsys/win32k/ntuser/userobj.c new file mode 100644 index 0000000..31e037f --- /dev/null +++ b/subsys/win32k/ntuser/userobj.c @@ -0,0 +1,125 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: USER Object manager interface definition + * FILE: subsys/win32k/ntuser/userobj.c + * PROGRAMER: Rex Jolliff (rex@lvcablemodem.com) + * + */ + +#undef WIN32_LEAN_AND_MEAN +#include +#define NDEBUG +#include +#include +#include + +static LIST_ENTRY UserObjectList; + +PUSER_OBJECT USEROBJ_AllocObject (WORD size, WORD magic) +{ + PUSER_OBJECT_HEADER newObject; + + newObject = ExAllocatePoolWithTag(PagedPool, + size + sizeof (USER_OBJECT_HEADER), + USER_OBJECT_TAG); + if (newObject == 0) + { + return 0; + } + RtlZeroMemory(newObject, size + sizeof (USER_OBJECT_HEADER)); + + newObject->magic = magic; + ExInitializeFastMutex (&newObject->mutex); + InsertTailList (&UserObjectList, &newObject->listEntry); + + return UserObjectHeaderToBody (newObject); +} + +BOOL USEROBJ_FreeObject (PUSER_OBJECT object, WORD magic) +{ + PUSER_OBJECT_HEADER objectHeader; + + if (object == NULL) + { + return FALSE; + } + objectHeader = UserObjectBodyToHeader (object); + if (objectHeader->magic != magic) + { + return FALSE; + } + RemoveEntryList (&objectHeader->listEntry); + ExFreePool (objectHeader); + + return TRUE; +} + +HUSEROBJ USEROBJ_PtrToHandle (PUSER_OBJECT object, WORD magic) +{ + PUSER_OBJECT_HEADER objectHeader; + + if (object == 0) + { + return 0; + } + objectHeader = UserObjectBodyToHeader (object); + if (objectHeader->magic != magic) + { + return 0; + } + + return UserObjectHeaderToHandle(objectHeader); +} + +PUSER_OBJECT USEROBJ_HandleToPtr (HUSEROBJ handle, WORD magic) +{ + PUSER_OBJECT_HEADER objectHeader; + + if (handle == 0) + { + return 0; + } + objectHeader = UserObjectHandleToHeader (handle); + if ((objectHeader->magic != magic) && + (magic != UO_MAGIC_DONTCARE)) + { + return 0; + } + + return UserObjectHeaderToBody (objectHeader); +} + +BOOL USEROBJ_LockObject (HUSEROBJ objectHandle) +{ + PUSER_OBJECT_HEADER objectHeader; + + if (objectHandle == 0) + { + return FALSE; + } + objectHeader = UserObjectHandleToHeader (objectHandle); + + ExAcquireFastMutexUnsafe (&objectHeader->mutex); + + return TRUE; +} + +BOOL USEROBJ_UnlockObject (HUSEROBJ objectHandle) +{ + PUSER_OBJECT_HEADER objectHeader; + + if (objectHandle == 0) + { + return FALSE; + } + objectHeader = UserObjectHandleToHeader (objectHandle); + + ExReleaseFastMutexUnsafe (&objectHeader->mutex); + + return TRUE; +} + + + diff --git a/subsys/win32k/ntuser/windc.c b/subsys/win32k/ntuser/windc.c new file mode 100644 index 0000000..2cc09e8 --- /dev/null +++ b/subsys/win32k/ntuser/windc.c @@ -0,0 +1,531 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window classes + * FILE: subsys/win32k/ntuser/class.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static PDCE FirstDce = NULL; + +#define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \ + DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP) + +/* FUNCTIONS *****************************************************************/ + +VOID STATIC +DceOffsetVisRgn(HDC hDC, HRGN hVisRgn) +{ + DC *dc = DC_HandleToPtr(hDC); + if (dc == NULL) + { + return; + } + W32kOffsetRgn(hVisRgn, dc->w.DCOrgX, dc->w.DCOrgY); + DC_ReleasePtr(hDC); +} + +BOOL STATIC +DceGetVisRect(PWINDOW_OBJECT Window, BOOL ClientArea, RECT* Rect) +{ + if (ClientArea) + { + *Rect = Window->ClientRect; + } + else + { + *Rect = Window->WindowRect; + } + + if (Window->Style & WS_VISIBLE) + { + INT XOffset = Rect->left; + INT YOffset = Rect->top; + + while ((Window = Window->Parent) != NULL) + { + if ((Window->Style & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE) + { + W32kSetEmptyRect(Rect); + return(FALSE); + } + XOffset += Window->ClientRect.left; + YOffset += Window->ClientRect.top; + W32kOffsetRect(Rect, Window->ClientRect.left, + Window->ClientRect.top); + if (Window->ClientRect.left >= Window->ClientRect.right || + Window->ClientRect.top >= Window->ClientRect.bottom || + Rect->left >= Window->ClientRect.right || + Rect->right <= Window->ClientRect.left || + Rect->top >= Window->ClientRect.bottom || + Rect->bottom <= Window->ClientRect.top) + { + W32kSetEmptyRect(Rect); + return(FALSE); + } + Rect->left = max(Rect->left, Window->ClientRect.left); + Rect->right = min(Rect->right, Window->ClientRect.right); + Rect->top = max(Rect->top, Window->ClientRect.top); + Rect->bottom = min(Rect->bottom, Window->ClientRect.bottom); + } + W32kOffsetRect(Rect, -XOffset, -YOffset); + return(TRUE); + } + W32kSetEmptyRect(Rect); + return(FALSE); +} + +BOOL +DceAddClipRects(PWINDOW_OBJECT Parent, PWINDOW_OBJECT End, + HRGN ClipRgn, PRECT Rect, INT XOffset, INT YOffset) +{ + PLIST_ENTRY ChildListEntry; + PWINDOW_OBJECT Child; + RECT Rect1; + + ChildListEntry = Parent->ChildrenListHead.Flink; + while (ChildListEntry != &Parent->ChildrenListHead) + { + Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT, + SiblingListEntry); + if (Child == End) + { + return(TRUE); + } + if (Child->Style & WS_VISIBLE) + { + Rect1.left = Child->WindowRect.left + XOffset; + Rect1.top = Child->WindowRect.top + YOffset; + Rect1.right = Child->WindowRect.right + XOffset; + Rect1.bottom = Child->WindowRect.bottom + YOffset; + + if (W32kIntersectRect(&Rect1, &Rect1, Rect)) + { + W32kUnionRectWithRgn(ClipRgn, &Rect1); + } + } + ChildListEntry = ChildListEntry->Flink; + } + return(FALSE); +} + +HRGN +DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags) +{ + PWINDOW_OBJECT Window; + PWINDOW_OBJECT Child; + HRGN VisRgn; + RECT Rect; + + Window = W32kGetWindowObject(hWnd); + Child = W32kGetWindowObject(hWndChild); + + if (Window != NULL && DceGetVisRect(Window, !(Flags & DCX_WINDOW), &Rect)) + { + if ((VisRgn = UnsafeW32kCreateRectRgnIndirect(&Rect)) != NULL) + { + HRGN ClipRgn = W32kCreateRectRgn(0, 0, 0, 0); + INT XOffset, YOffset; + + if (ClipRgn != NULL) + { + if (Flags & DCX_CLIPCHILDREN && + !IsListEmpty(&Window->ChildrenListHead)) + { + if (Flags & DCX_WINDOW) + { + XOffset = Window->ClientRect.left - + Window->WindowRect.left; + YOffset = Window->ClientRect.top - + Window->WindowRect.top; + } + else + { + XOffset = YOffset = 0; + } + DceAddClipRects(Window, NULL, ClipRgn, &Rect, + XOffset, YOffset); + } + + if (CFlags & DCX_CLIPCHILDREN && Child && + !IsListEmpty(&Child->ChildrenListHead)) + { + if (Flags & DCX_WINDOW) + { + XOffset = Window->ClientRect.left - + Window->WindowRect.left; + YOffset = Window->ClientRect.top - + Window->WindowRect.top; + } + else + { + XOffset = YOffset = 0; + } + + XOffset += Child->ClientRect.left; + YOffset += Child->ClientRect.top; + + DceAddClipRects(Child, NULL, ClipRgn, &Rect, + XOffset, YOffset); + } + + if (Flags & DCX_WINDOW) + { + XOffset = -Window->WindowRect.left; + YOffset = -Window->WindowRect.top; + } + else + { + XOffset = -Window->ClientRect.left; + YOffset = -Window->ClientRect.top; + } + + if (Flags & DCX_CLIPSIBLINGS && Window->Parent != NULL) + { + DceAddClipRects(Window->Parent, Window, ClipRgn, + &Rect, XOffset, YOffset); + } + + while (Window->Style & WS_CHILD) + { + Window = Window->Parent; + XOffset -= Window->ClientRect.left; + YOffset -= Window->ClientRect.top; + if (Window->Style & WS_CLIPSIBLINGS && + Window->Parent != NULL) + { + DceAddClipRects(Window->Parent, Window, ClipRgn, + &Rect, XOffset, YOffset); + } + } + + W32kCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); + W32kDeleteObject(ClipRgn); + } + else + { + W32kDeleteObject(VisRgn); + VisRgn = 0; + } + } + } + else + { + VisRgn = W32kCreateRectRgn(0, 0, 0, 0); + } + W32kReleaseWindowObject(Window); + W32kReleaseWindowObject(Child); + return(VisRgn); +} + +INT STDCALL +NtUserReleaseDC(HWND hWnd, HDC hDc) +{ + +} + +HDC STDCALL +NtUserGetDC(HWND hWnd) +{ + if (!hWnd) + return NtUserGetDCEx(0, 0, DCX_CACHE | DCX_WINDOW); + return NtUserGetDCEx(hWnd, 0, DCX_USESTYLE); +} + +DCE* DceAllocDCE(HWND hWnd, DCE_TYPE Type) +{ + HDCE DceHandle; + DCE* Dce; + + DceHandle = DCEOBJ_AllocDCE(); + Dce = DCEOBJ_LockDCE(DceHandle); + Dce->hDC = W32kCreateDC(L"DISPLAY", NULL, NULL, NULL); + Dce->hwndCurrent = hWnd; + Dce->hClipRgn = NULL; + Dce->next = FirstDce; + FirstDce = Dce; + + if (Type != DCE_CACHE_DC) + { + Dce->DCXFlags = DCX_DCEBUSY; + if (hWnd != NULL) + { + PWINDOW_OBJECT WindowObject; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject->Style & WS_CLIPCHILDREN) + { + Dce->DCXFlags |= DCX_CLIPCHILDREN; + } + if (WindowObject->Style & WS_CLIPSIBLINGS) + { + Dce->DCXFlags |= DCX_CLIPSIBLINGS; + } + W32kReleaseWindowObject(WindowObject); + } + } + else + { + Dce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY; + } + + return(Dce); +} + +VOID STATIC +DceSetDrawable(PWINDOW_OBJECT WindowObject, HDC hDC, ULONG Flags, + BOOL SetClipOrigin) +{ + DC *dc = DC_HandleToPtr(hDC); + if (WindowObject == NULL) + { + dc->w.DCOrgX = 0; + dc->w.DCOrgY = 0; + } + else + { + if (Flags & DCX_WINDOW) + { + dc->w.DCOrgX = WindowObject->WindowRect.left; + dc->w.DCOrgY = WindowObject->WindowRect.top; + } + else + { + dc->w.DCOrgX = WindowObject->ClientRect.left; + dc->w.DCOrgY = WindowObject->ClientRect.top; + } + /* FIXME: Offset by parent's client rectangle. */ + } + DC_ReleasePtr(hDC); +} + +HDC STDCALL +NtUserGetDCEx(HWND hWnd, HANDLE hRegion, ULONG Flags) +{ + PWINDOW_OBJECT Window; + ULONG DcxFlags; + DCE* Dce; + BOOL UpdateVisRgn = TRUE; + BOOL UpdateClipOrigin = FALSE; + HANDLE hRgnVisible = NULL; + + if ((Window = W32kGetWindowObject(hWnd)) == NULL) + { + return(0); + } + + if (Window->Dce == NULL) + { + Flags |= DCX_CACHE; + } + + if (Flags & DCX_USESTYLE) + { + Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP); + + if (Window->Style & WS_CLIPSIBLINGS) + { + Flags |= DCX_CLIPSIBLINGS; + } + + if (!(Flags & DCX_WINDOW)) + { + if (Window->Class->Class.style & CS_PARENTDC) + { + Flags |= DCX_PARENTCLIP; + } + + if (Window->Style & WS_CLIPCHILDREN && + !(Window->Style & WS_MINIMIZE)) + { + Flags |= DCX_CLIPCHILDREN; + } + } + else + { + Flags |= DCX_CACHE; + } + } + + if (Flags & DCX_NOCLIPCHILDREN) + { + Flags |= DCX_CACHE; + Flags |= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN); + } + + if (Flags & DCX_WINDOW) + { + Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE; + } + + if (!(Window->Style & WS_CHILD) || Window->Parent == NULL) + { + Flags &= ~DCX_PARENTCLIP; + } + else if (Flags & DCX_PARENTCLIP) + { + Flags |= DCX_CACHE; + if (!(Flags & (DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS))) + { + if ((Window->Style & WS_VISIBLE) && + (Window->Parent->Style & WS_VISIBLE)) + { + Flags &= ~DCX_CLIPCHILDREN; + if (Window->Parent->Style & WS_CLIPSIBLINGS) + { + Flags |= DCX_CLIPSIBLINGS; + } + } + } + } + + DcxFlags = Flags & DCX_CACHECOMPAREMASK; + + if (Flags & DCX_CACHE) + { + DCE* DceEmpty = NULL; + DCE* DceUnused = NULL; + + for (Dce = FirstDce; Dce != NULL; Dce = Dce->next) + { + if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE) + { + DceUnused = Dce; + if (Dce->DCXFlags & DCX_DCEEMPTY) + { + DceEmpty = Dce; + } + else if (Dce->hwndCurrent == hWnd && + ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags)) + { + UpdateVisRgn = FALSE; + UpdateClipOrigin = TRUE; + break; + } + } + } + + if (Dce == NULL) + { + Dce = (DceEmpty == NULL) ? DceEmpty : DceUnused; + } + + if (Dce == NULL) + { + Dce = DceAllocDCE(NULL, DCE_CACHE_DC); + } + } + else + { + Dce = Window->Dce; + /* FIXME: Implement this. */ + DbgBreakPoint(); + } + + if (Dce == NULL) + { + W32kReleaseWindowObject(Window); + return(NULL); + } + + Dce->hwndCurrent = hWnd; + Dce->hClipRgn = NULL; + Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY; + + DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin); + + if (UpdateVisRgn) + { + if (Flags & DCX_PARENTCLIP) + { + PWINDOW_OBJECT Parent; + + Parent = Window->Parent; + + if (Window->Style & WS_VISIBLE && + !(Parent->Style & WS_MINIMIZE)) + { + if (Parent->Style & WS_CLIPSIBLINGS) + { + DcxFlags = DCX_CLIPSIBLINGS | + (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW)); + } + else + { + DcxFlags = Flags & + ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW); + } + hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags, + Window->Self, Flags); + if (Flags & DCX_WINDOW) + { + W32kOffsetRgn(hRgnVisible, -Window->WindowRect.left, + -Window->WindowRect.top); + } + else + { + W32kOffsetRgn(hRgnVisible, -Window->ClientRect.left, + -Window->ClientRect.top); + } + DceOffsetVisRgn(Dce->hDC, hRgnVisible); + } + else + { + hRgnVisible = W32kCreateRectRgn(0, 0, 0, 0); + } + } + else + { + if (hWnd == W32kGetDesktopWindow()) + { + hRgnVisible = + W32kCreateRectRgn(0, 0, + NtUserGetSystemMetrics(SM_CXSCREEN), + NtUserGetSystemMetrics(SM_CYSCREEN)); + } + else + { + hRgnVisible = DceGetVisRgn(hWnd, Flags, 0, 0); + DceOffsetVisRgn(Dce->hDC, hRgnVisible); + } + + Dce->DCXFlags &= ~DCX_DCEDIRTY; + W32kSelectVisRgn(Dce->hDC, hRgnVisible); + } + } + + if (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) + { + DPRINT1("FIXME.\n"); + } + + if (hRgnVisible != NULL) + { + W32kDeleteObject(hRgnVisible); + } + W32kReleaseWindowObject(Window); + return(Dce->hDC); +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/window.c b/subsys/win32k/ntuser/window.c new file mode 100644 index 0000000..5b8d0fb --- /dev/null +++ b/subsys/win32k/ntuser/window.c @@ -0,0 +1,1045 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Windows + * FILE: subsys/win32k/ntuser/window.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +HWND STDCALL +NtUserGetAncestor(HWND hWnd, UINT Flags) +{ + if (W32kIsDesktopWindow(hWnd)) + { + return(NULL); + } + if (Flags & GA_PARENT) + { + PWINDOW_OBJECT Window; + HWND hParent; + + Window = W32kGetWindowObject(hWnd); + if (Window == NULL) + { + return(NULL); + } + + if (Window->Parent == NULL) + { + W32kReleaseWindowObject(Window); + } + + hParent = Window->Parent->Self; + + W32kReleaseWindowObject(Window); + + return(hParent); + } + else + { + UNIMPLEMENTED; + return(NULL); + } +} + +VOID +W32kSetFocusWindow(HWND hWnd) +{ +} + +BOOL +W32kIsChildWindow(HWND Parent, HWND Child) +{ + PWINDOW_OBJECT BaseWindow = W32kGetWindowObject(Child); + PWINDOW_OBJECT Window = BaseWindow; + while (Window != NULL && Window->Style & WS_CHILD) + { + if (Window->Self == Parent) + { + W32kReleaseWindowObject(BaseWindow); + return(TRUE); + } + Window = Window->Parent; + } + W32kReleaseWindowObject(BaseWindow); + return(FALSE); +} + +BOOL +W32kIsWindowVisible(HWND Wnd) +{ + PWINDOW_OBJECT BaseWindow = W32kGetWindowObject(Wnd); + PWINDOW_OBJECT Window = BaseWindow; + BOOLEAN Result = FALSE; + while (Window != NULL && Window->Style & WS_CHILD) + { + if (!(Window->Style & WS_VISIBLE)) + { + W32kReleaseWindowObject(BaseWindow); + return(FALSE); + } + Window = Window->Parent; + } + if (Window != NULL && Window->Style & WS_VISIBLE) + { + Result = TRUE; + } + W32kReleaseWindowObject(BaseWindow); + return(Result); +} + +BOOL +W32kIsDesktopWindow(HWND hWnd) +{ + PWINDOW_OBJECT WindowObject; + BOOL IsDesktop; + WindowObject = W32kGetWindowObject(hWnd); + IsDesktop = WindowObject->Parent == NULL; + W32kReleaseWindowObject(WindowObject); + return(IsDesktop); +} + +HWND W32kGetDesktopWindow() +{ + return W32kGetActiveDesktop()->DesktopWindow; +} + +HWND W32kGetParentWindow(HWND hWnd) +{ + return W32kGetWindowObject(hWnd)->ParentHandle; +} + +PWINDOW_OBJECT +W32kGetWindowObject(HWND hWnd) +{ + PWINDOW_OBJECT WindowObject; + NTSTATUS Status; + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation-> + HandleTable, + hWnd, + otWindow, + (PVOID*)&WindowObject); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + return(WindowObject); +} + +VOID +W32kReleaseWindowObject(PWINDOW_OBJECT Window) +{ + ObmDereferenceObject(Window); +} + +VOID +W32kGetClientRect(PWINDOW_OBJECT WindowObject, PRECT Rect) +{ + Rect->left = Rect->top = 0; + Rect->right = WindowObject->ClientRect.right - WindowObject->ClientRect.left; + Rect->bottom = + WindowObject->ClientRect.bottom - WindowObject->ClientRect.top; +} + +BOOL STDCALL +W32kGetWindowRect(HWND hWnd, LPRECT Rect) +{ + PWINDOW_OBJECT WindowObject; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + return(FALSE); + } + *Rect = WindowObject->WindowRect; + if (WindowObject->Style & WS_CHILD) + { + DbgBreakPoint(); + } + W32kReleaseWindowObject(WindowObject); + return(TRUE); +} + +BOOL STDCALL +NtUserGetWindowRect(HWND hWnd, LPRECT Rect) +{ + return(W32kGetWindowRect(hWnd, Rect)); +} + +HWND +W32kGetActiveWindow(VOID) +{ + PUSER_MESSAGE_QUEUE Queue; + Queue = (PUSER_MESSAGE_QUEUE)W32kGetActiveDesktop()->ActiveMessageQueue; + if (Queue == NULL) + { + return(NULL); + } + else + { + return(Queue->ActiveWindow); + } +} + +HWND +W32kGetFocusWindow(VOID) +{ + PUSER_MESSAGE_QUEUE Queue; + Queue = (PUSER_MESSAGE_QUEUE)W32kGetActiveDesktop()->ActiveMessageQueue; + if (Queue == NULL) + { + return(NULL); + } + else + { + return(Queue->FocusWindow); + } +} + + +WNDPROC +W32kGetWindowProc(HWND Wnd) +{ + PWINDOW_OBJECT WindowObject; + WNDPROC WndProc; + + WindowObject = W32kGetWindowObject(Wnd); + WndProc = WindowObject->Class->Class.lpfnWndProc; + W32kReleaseWindowObject(Wnd); + return(WndProc); +} + +NTSTATUS +InitWindowImpl(VOID) +{ + return(STATUS_SUCCESS); +} + +NTSTATUS +CleanupWindowImpl(VOID) +{ + return(STATUS_SUCCESS); +} + + +DWORD STDCALL +NtUserAlterWindowStyle(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return(0); +} + +DWORD STDCALL +NtUserChildWindowFromPointEx(HWND Parent, + LONG x, + LONG y, + UINT Flags) +{ + UNIMPLEMENTED + + return(0); +} + +HWND STDCALL +W32kCreateDesktopWindow(PWINSTATION_OBJECT WindowStation, + PWNDCLASS_OBJECT DesktopClass, + ULONG Width, ULONG Height) +{ + PWSTR WindowName; + HWND Handle; + PWINDOW_OBJECT WindowObject; + + /* Create the window object. */ + WindowObject = (PWINDOW_OBJECT)ObmCreateObject(WindowStation->HandleTable, + &Handle, + otWindow, + sizeof(WINDOW_OBJECT)); + if (!WindowObject) + { + return((HWND)0); + } + + /* + * Fill out the structure describing it. + */ + WindowObject->Class = DesktopClass; + WindowObject->ExStyle = 0; + WindowObject->Style = WS_VISIBLE; + WindowObject->x = 0; + WindowObject->y = 0; + WindowObject->Width = Width; + WindowObject->Height = Height; + WindowObject->ParentHandle = NULL; + WindowObject->Parent = NULL; + WindowObject->Menu = NULL; + WindowObject->Instance = NULL; + WindowObject->Parameters = NULL; + WindowObject->Self = Handle; + WindowObject->MessageQueue = NULL; + WindowObject->ExtraData = NULL; + WindowObject->ExtraDataSize = 0; + WindowObject->WindowRect.left = 0; + WindowObject->WindowRect.top = 0; + WindowObject->WindowRect.right = Width; + WindowObject->WindowRect.bottom = Height; + WindowObject->ClientRect = WindowObject->WindowRect; + InitializeListHead(&WindowObject->ChildrenListHead); + + WindowName = ExAllocatePool(NonPagedPool, sizeof(L"DESKTOP")); + wcscpy(WindowName, L"DESKTOP"); + RtlInitUnicodeString(&WindowObject->WindowName, WindowName); + + return(Handle); +} + +HWND STDCALL +NtUserCreateWindowEx(DWORD dwExStyle, + PUNICODE_STRING lpClassName, + PUNICODE_STRING lpWindowName, + DWORD dwStyle, + LONG x, + LONG y, + LONG nWidth, + LONG nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID lpParam, + DWORD dwShowMode) +{ + PWINSTATION_OBJECT WinStaObject; + PWNDCLASS_OBJECT ClassObject; + PWINDOW_OBJECT WindowObject; + PWINDOW_OBJECT ParentWindow; + UNICODE_STRING WindowName; + NTSTATUS Status; + HANDLE Handle; + POINT MaxSize, MaxPos, MinTrack, MaxTrack; + CREATESTRUCTW Cs; + LRESULT Result; + + DPRINT("NtUserCreateWindowEx\n"); + + /* Initialize gui state if necessary. */ + W32kGuiCheck(); + W32kGraphicsCheck(); + + if (!RtlCreateUnicodeString(&WindowName, lpWindowName->Buffer)) + { + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + return((HWND)0); + } + + if (hWndParent != NULL) + { + ParentWindow = W32kGetWindowObject(hWndParent); + } + else + { + hWndParent = PsGetWin32Thread()->Desktop->DesktopWindow; + ParentWindow = W32kGetWindowObject(hWndParent); + } + + /* Check the class. */ + Status = ClassReferenceClassByNameOrAtom(&ClassObject, lpClassName->Buffer); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&WindowName); + return((HWND)0); + } + + /* Check the window station. */ + DPRINT("IoGetCurrentProcess() %X\n", IoGetCurrentProcess()); + DPRINT("PROCESS_WINDOW_STATION %X\n", PROCESS_WINDOW_STATION()); + Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + RtlFreeUnicodeString(&WindowName); + ObmDereferenceObject(ClassObject); + DPRINT("Validation of window station handle (0x%X) failed\n", + PROCESS_WINDOW_STATION()); + return (HWND)0; + } + + /* Create the window object. */ + WindowObject = (PWINDOW_OBJECT) + ObmCreateObject(PsGetWin32Process()->WindowStation->HandleTable, &Handle, + otWindow, sizeof(WINDOW_OBJECT)); + DPRINT("Created object with handle %X\n", Handle); + if (!WindowObject) + { + ObDereferenceObject(WinStaObject); + ObmDereferenceObject(ClassObject); + RtlFreeUnicodeString(&WindowName); + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + return (HWND)0; + } + ObDereferenceObject(WinStaObject); + + /* + * Fill out the structure describing it. + */ + WindowObject->Class = ClassObject; + WindowObject->ExStyle = dwExStyle; + WindowObject->Style = dwStyle; + WindowObject->x = x; + WindowObject->y = y; + WindowObject->Width = nWidth; + WindowObject->Height = nHeight; + WindowObject->ParentHandle = hWndParent; + WindowObject->Menu = hMenu; + WindowObject->Instance = hInstance; + WindowObject->Parameters = lpParam; + WindowObject->Self = Handle; + WindowObject->MessageQueue = PsGetWin32Thread()->MessageQueue; + WindowObject->Parent = ParentWindow; + InsertHeadList(&ParentWindow->ChildrenListHead, + &WindowObject->SiblingListEntry); + InitializeListHead(&WindowObject->ChildrenListHead); + InitializeListHead(&WindowObject->PropListHead); + + RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer); + RtlFreeUnicodeString(&WindowName); + + if (ClassObject->Class.cbWndExtra != 0) + { + WindowObject->ExtraData = + ExAllocatePool(PagedPool, + ClassObject->Class.cbWndExtra * sizeof(DWORD)); + WindowObject->ExtraDataSize = ClassObject->Class.cbWndExtra; + } + else + { + WindowObject->ExtraData = NULL; + WindowObject->ExtraDataSize = 0; + } + + /* Correct the window style. */ + if (!(dwStyle & WS_CHILD)) + { + WindowObject->Style |= WS_CLIPSIBLINGS; + if (!(dwStyle & WS_POPUP)) + { + WindowObject->Style |= WS_CAPTION; + /* FIXME: Note the window needs a size. */ + } + } + + /* Insert the window into the process's window list. */ + ExAcquireFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock); + InsertTailList (&PsGetWin32Thread()->WindowListHead, + &WindowObject->ThreadListEntry); + ExReleaseFastMutexUnsafe (&PsGetWin32Thread()->WindowListLock); + + /* + * Insert the window into the list of windows associated with the thread's + * desktop. + */ + InsertTailList(&PsGetWin32Thread()->Desktop->WindowListHead, + &WindowObject->DesktopListEntry); + + /* FIXME: Maybe allocate a DCE for this window. */ + + /* Initialize the window dimensions. */ + WindowObject->WindowRect.left = x; + WindowObject->WindowRect.top = y; + WindowObject->WindowRect.right = x + nWidth; + WindowObject->WindowRect.bottom = y + nHeight; + WindowObject->ClientRect = WindowObject->WindowRect; + + /* + * Get the size and position of the window. + */ + if ((dwStyle & WS_THICKFRAME) || !(dwStyle & (WS_POPUP | WS_CHILD))) + { + WinPosGetMinMaxInfo(WindowObject, &MaxSize, &MaxPos, &MinTrack, + &MaxTrack); + x = min(MaxSize.x, y); + y = min(MaxSize.y, y); + x = max(MinTrack.x, x); + y = max(MinTrack.y, y); + } + + WindowObject->WindowRect.left = x; + WindowObject->WindowRect.top = y; + WindowObject->WindowRect.right = x + nWidth; + WindowObject->WindowRect.bottom = y + nHeight; + WindowObject->ClientRect = WindowObject->WindowRect; + + /* FIXME: Initialize the window menu. */ + + /* Send a NCCREATE message. */ + Cs.lpCreateParams = lpParam; + Cs.hInstance = hInstance; + Cs.hMenu = hMenu; + Cs.hwndParent = hWndParent; + Cs.cx = nWidth; + Cs.cy = nHeight; + Cs.x = x; + Cs.y = y; + Cs.style = dwStyle; + Cs.lpszName = lpWindowName->Buffer; + Cs.lpszClass = lpClassName->Buffer; + Cs.dwExStyle = dwExStyle; + DPRINT("NtUserCreateWindowEx(): About to send NCCREATE message.\n"); + Result = W32kSendNCCREATEMessage(WindowObject->Self, &Cs); + if (!Result) + { + /* FIXME: Cleanup. */ + DPRINT("NtUserCreateWindowEx(): NCCREATE message failed.\n"); + return(NULL); + } + + /* Calculate the non-client size. */ + MaxPos.x = WindowObject->WindowRect.left; + MaxPos.y = WindowObject->WindowRect.top; + DPRINT("NtUserCreateWindowEx(): About to get non-client size.\n"); + Result = WinPosGetNonClientSize(WindowObject->Self, + &WindowObject->WindowRect, + &WindowObject->ClientRect); + W32kOffsetRect(&WindowObject->WindowRect, + MaxPos.x - WindowObject->WindowRect.left, + MaxPos.y - WindowObject->WindowRect.top); + + /* Send the CREATE message. */ + DPRINT("NtUserCreateWindowEx(): about to send CREATE message.\n"); + Result = W32kSendCREATEMessage(WindowObject->Self, &Cs); + if (Result == (LRESULT)-1) + { + /* FIXME: Cleanup. */ + DPRINT("NtUserCreateWindowEx(): send CREATE message failed.\n"); + return(NULL); + } + + /* Send move and size messages. */ + if (!(WindowObject->Flags & WINDOWOBJECT_NEED_SIZE)) + { + LONG lParam; + + lParam = + MAKE_LONG(WindowObject->ClientRect.right - + WindowObject->ClientRect.left, + WindowObject->ClientRect.bottom - + WindowObject->ClientRect.top); + DPRINT("NtUserCreateWindow(): About to send WM_SIZE\n"); + W32kCallWindowProc(NULL, WindowObject->Self, WM_SIZE, SIZE_RESTORED, + lParam); + lParam = + MAKE_LONG(WindowObject->ClientRect.left, + WindowObject->ClientRect.top); + DPRINT("NtUserCreateWindow(): About to send WM_MOVE\n"); + W32kCallWindowProc(NULL, WindowObject->Self, WM_MOVE, 0, lParam); + } + + /* Show or maybe minimize or maximize the window. */ + if (WindowObject->Style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + RECT NewPos; + UINT16 SwFlag; + + SwFlag = (WindowObject->Style & WS_MINIMIZE) ? SW_MINIMIZE : + SW_MAXIMIZE; + WinPosMinMaximize(WindowObject, SwFlag, &NewPos); + SwFlag = + ((WindowObject->Style & WS_CHILD) || W32kGetActiveWindow()) ? + SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED : + SWP_NOZORDER | SWP_FRAMECHANGED; + DPRINT("NtUserCreateWindow(): About to minimize/maximize\n"); + WinPosSetWindowPos(WindowObject->Self, 0, NewPos.left, NewPos.top, + NewPos.right, NewPos.bottom, SwFlag); + } + + /* Notify the parent window of a new child. */ + if ((WindowObject->Style & WS_CHILD) || + (!(WindowObject->ExStyle & WS_EX_NOPARENTNOTIFY))) + { + DPRINT("NtUserCreateWindow(): About to notify parent\n"); + W32kCallWindowProc(NULL, WindowObject->Parent->Self, + WM_PARENTNOTIFY, + MAKEWPARAM(WM_CREATE, WindowObject->IDMenu), + (LPARAM)WindowObject->Self); + } + + if (dwStyle & WS_VISIBLE) + { + DPRINT("NtUserCreateWindow(): About to show window\n"); + WinPosShowWindow(WindowObject->Self, dwShowMode); + } + + DPRINT("NtUserCreateWindow(): = %X\n", Handle); + return((HWND)Handle); +} + +DWORD STDCALL +NtUserDeferWindowPos(HDWP WinPosInfo, + HWND Wnd, + HWND WndInsertAfter, + LONG x, + LONG y, + LONG cx, + LONG cy, + UINT Flags) +{ + UNIMPLEMENTED + + return 0; +} + +BOOLEAN STDCALL +NtUserDestroyWindow(HWND Wnd) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserEndDeferWindowPosEx(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserFillWindow(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +HWND STDCALL +NtUserFindWindowEx(HWND hwndParent, + HWND hwndChildAfter, + PUNICODE_STRING ucClassName, + PUNICODE_STRING ucWindowName, + DWORD Unknown4) +{ +#if 0 + NTSTATUS status; + HWND windowHandle; + PWINDOW_OBJECT windowObject; + PLIST_ENTRY currentEntry; + PWNDCLASS_OBJECT classObject; + + W32kGuiCheck(); + + status = ClassReferenceClassByNameOrAtom(&classObject, ucClassName->Buffer); + if (!NT_SUCCESS(status)) + { + return (HWND)0; + } + + ExAcquireFastMutexUnsafe (&PsGetWin32Process()->WindowListLock); + currentEntry = PsGetWin32Process()->WindowListHead.Flink; + while (currentEntry != &PsGetWin32Process()->WindowListHead) + { + windowObject = CONTAINING_RECORD (currentEntry, WINDOW_OBJECT, + ListEntry); + + if (classObject == windowObject->Class && + RtlCompareUnicodeString (ucWindowName, &windowObject->WindowName, + TRUE) == 0) + { + ObmCreateHandle(PsGetWin32Process()->HandleTable, + windowObject, + &windowHandle); + ExReleaseFastMutexUnsafe (&PsGetWin32Process()->WindowListLock); + ObmDereferenceObject (classObject); + + return windowHandle; + } + currentEntry = currentEntry->Flink; + } + ExReleaseFastMutexUnsafe (&PsGetWin32Process()->WindowListLock); + + ObmDereferenceObject (classObject); + + return (HWND)0; +#endif +} + +DWORD STDCALL +NtUserFlashWindowEx(DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserGetForegroundWindow(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserGetInternalWindowPos(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserGetOpenClipboardWindow(VOID) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserGetWindowDC(DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserGetWindowPlacement(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserInternalGetWindowText(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserLockWindowUpdate(DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserMoveWindow(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserQueryWindow(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserRealChildWindowFromPoint(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserRedrawWindow(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +UINT STDCALL +NtUserRegisterWindowMessage(LPCWSTR MessageName) +{ + UNIMPLEMENTED + + return(0); +} + +DWORD STDCALL +NtUserScrollWindowEx(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetActiveWindow(DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetImeOwnerWindow(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetInternalWindowPos(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; + +} + +DWORD STDCALL +NtUserSetLayeredWindowAttributes(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetLogonNotifyWindow(DWORD Unknown0) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetShellWindowEx(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetWindowFNID(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserGetWindowLong(HWND hWnd, DWORD Index) +{ + PWINDOW_OBJECT WindowObject; + NTSTATUS Status; + DWORD Result; + + W32kGuiCheck(); + + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable, + hWnd, + otWindow, + (PVOID*)&WindowObject); + if (!NT_SUCCESS(Status)) + { + return(0); + } + + switch (Index) + { + case GWL_EXSTYLE: + { + Result = (DWORD)WindowObject->ExStyle; + break; + } + + case GWL_STYLE: + { + Result = (DWORD)WindowObject->Style; + break; + } + + case GWL_WNDPROC: + { + Result = (DWORD)WindowObject->Class->Class.lpfnWndProc; + break; + } + + default: + { + DPRINT1("NtUserGetWindowLong(): Unsupported index %d\n", Index); + Result = 0; + break; + } + } + + ObmDereferenceObject(WindowObject); + return(Result); +} + +DWORD STDCALL +NtUserSetWindowLong(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetWindowPlacement(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetWindowPos(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetWindowRgn(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserSetWindowWord(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED + + return 0; +} + +BOOL STDCALL +NtUserShowWindow(HWND hWnd, + LONG nCmdShow) +{ + W32kGuiCheck(); + + return(WinPosShowWindow(hWnd, nCmdShow)); +} + +DWORD STDCALL +NtUserShowWindowAsync(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserUpdateLayeredWindow(DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5, + DWORD Unknown6, + DWORD Unknown7, + DWORD Unknown8) +{ + UNIMPLEMENTED + + return 0; +} + +DWORD STDCALL +NtUserWindowFromPoint(DWORD Unknown0, + DWORD Unknown1) +{ + UNIMPLEMENTED + + return 0; +} + +/* EOF */ diff --git a/subsys/win32k/ntuser/winpos.c b/subsys/win32k/ntuser/winpos.c new file mode 100644 index 0000000..973be6b --- /dev/null +++ b/subsys/win32k/ntuser/winpos.c @@ -0,0 +1,828 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Windows + * FILE: subsys/win32k/ntuser/window.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + */ +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define MINMAX_NOSWP (0x00010000) + +#define SWP_EX_PAINTSELF 0x0002 + +ATOM AtomInternalPos = NULL; + +/* FUNCTIONS *****************************************************************/ + +#define HAS_DLGFRAME(Style, ExStyle) \ + (((ExStyle) & WS_EX_DLGMODALFRAME) || \ + (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER))) + +#define HAS_THICKFRAME(Style, ExStyle) \ + (((Style) & WS_THICKFRAME) && \ + !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME) + +VOID +WinPosSetupInternalPos(VOID) +{ + AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos); +} + +BOOL STDCALL +NtUserGetClientOrigin(HWND hWnd, LPPOINT Point) +{ + PWINDOW_OBJECT WindowObject; + + WindowObject = W32kGetWindowObject(hWnd); + if (WindowObject == NULL) + { + Point->x = Point->y = 0; + return(TRUE); + } + Point->x = WindowObject->ClientRect.left; + Point->y = WindowObject->ClientRect.top; + return(TRUE); +} + +BOOL +WinPosActivateOtherWindow(PWINDOW_OBJECT Window) +{ +} + +POINT STATIC +WinPosFindIconPos(HWND hWnd, POINT Pos) +{ +} + +HWND STATIC +WinPosCreateIconTitle(PWINDOW_OBJECT WindowObject) +{ + return(NULL); +} + +BOOL STATIC +WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show) +{ + PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self, + AtomInternalPos); + PWINDOW_OBJECT IconWindow; + NTSTATUS Status; + + if (InternalPos) + { + HWND hWnd = InternalPos->IconTitle; + + if (hWnd == NULL) + { + hWnd = WinPosCreateIconTitle(WindowObject); + } + if (Show) + { + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation-> + HandleTable, + hWnd, + otWindow, + (PVOID*)&IconWindow); + if (NT_SUCCESS(Status)) + { + if (!(IconWindow->Style & WS_VISIBLE)) + { + NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0); + WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | + SWP_NOMOVE | SWP_NOACTIVATE | + SWP_NOZORDER | SWP_SHOWWINDOW); + } + ObmDereferenceObject(IconWindow); + } + } + else + { + WinPosShowWindow(hWnd, SW_HIDE); + } + } + return(FALSE); +} + +PINTERNALPOS STATIC +WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect) +{ + PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self, + AtomInternalPos); + if (InternalPos == NULL) + { + InternalPos = + ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS)); + NtUserSetProp(WindowObject->Self, AtomInternalPos, InternalPos); + InternalPos->IconTitle = 0; + InternalPos->NormalRect = WindowObject->WindowRect; + InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF; + InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF; + } + if (WindowObject->Style & WS_MINIMIZE) + { + InternalPos->IconPos = pt; + } + else if (WindowObject->Style & WS_MAXIMIZE) + { + InternalPos->MaxPos = pt; + } + else if (RestoreRect != NULL) + { + InternalPos->NormalRect = *RestoreRect; + } + return(InternalPos); +} + +UINT +WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos) +{ + POINT Size; + PINTERNALPOS InternalPos; + UINT SwpFlags = 0; + + Size.x = WindowObject->WindowRect.left; + Size.y = WindowObject->WindowRect.top; + InternalPos = WinPosInitInternalPos(WindowObject, Size, + &WindowObject->WindowRect); + + if (InternalPos) + { + if (WindowObject->Style & WS_MINIMIZE) + { + if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0)) + { + return(SWP_NOSIZE | SWP_NOMOVE); + } + SwpFlags |= SWP_NOCOPYBITS; + } + switch (ShowFlag) + { + case SW_MINIMIZE: + { + if (WindowObject->Style & WS_MAXIMIZE) + { + WindowObject->Flags |= WINDOWOBJECT_RESTOREMAX; + WindowObject->Style &= ~WS_MAXIMIZE; + } + else + { + WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX; + } + WindowObject->Style |= WS_MINIMIZE; + InternalPos->IconPos = WinPosFindIconPos(WindowObject, + InternalPos->IconPos); + W32kSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y, + NtUserGetSystemMetrics(SM_CXICON), + NtUserGetSystemMetrics(SM_CYICON)); + SwpFlags |= SWP_NOCOPYBITS; + break; + } + + case SW_MAXIMIZE: + { + WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos, + NULL, NULL); + if (WindowObject->Style & WS_MINIMIZE) + { + WinPosShowIconTitle(WindowObject, FALSE); + WindowObject->Style &= ~WS_MINIMIZE; + } + WindowObject->Style |= WS_MINIMIZE; + W32kSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y, + Size.x, Size.y); + break; + } + + case SW_RESTORE: + { + if (WindowObject->Style & WS_MINIMIZE) + { + WindowObject->Style &= ~WS_MINIMIZE; + WinPosShowIconTitle(WindowObject, FALSE); + if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX) + { + WinPosGetMinMaxInfo(WindowObject, &Size, + &InternalPos->MaxPos, NULL, NULL); + WindowObject->Style |= WS_MAXIMIZE; + W32kSetRect(NewPos, InternalPos->MaxPos.x, + InternalPos->MaxPos.y, Size.x, Size.y); + break; + } + } + else + { + if (!(WindowObject->Style & WS_MAXIMIZE)) + { + return(-1); + } + else + { + WindowObject->Style &= ~WS_MAXIMIZE; + } + *NewPos = InternalPos->NormalRect; + NewPos->right -= NewPos->left; + NewPos->bottom -= NewPos->top; + break; + } + } + } + } + else + { + SwpFlags |= SWP_NOSIZE | SWP_NOMOVE; + } + return(SwpFlags); +} + +UINT +WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos, + POINT* MinTrack, POINT* MaxTrack) +{ + MINMAXINFO MinMax; + INT XInc, YInc; + INTERNALPOS* Pos; + + /* Get default values. */ + MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN); + MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN); + MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK); + MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK); + MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN); + MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN); + + if (HAS_DLGFRAME(Window->Style, Window->ExStyle)) + { + XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME); + YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME); + } + else + { + XInc = YInc = 0; + if (HAS_THICKFRAME(Window->Style, Window->ExStyle)) + { + XInc += NtUserGetSystemMetrics(SM_CXFRAME); + YInc += NtUserGetSystemMetrics(SM_CYFRAME); + } + if (Window->Style & WS_BORDER) + { + XInc += NtUserGetSystemMetrics(SM_CXBORDER); + YInc += NtUserGetSystemMetrics(SM_CYBORDER); + } + } + MinMax.ptMaxSize.x += 2 * XInc; + MinMax.ptMaxSize.y += 2 * YInc; + + Pos = NtUserGetProp(Window->Self, AtomInternalPos); + if (Pos != NULL) + { + MinMax.ptMaxPosition = Pos->MaxPos; + } + else + { + MinMax.ptMaxPosition.x -= XInc; + MinMax.ptMaxPosition.y -= YInc; + } + + W32kSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE); + + MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x, + MinMax.ptMinTrackSize.x); + MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y, + MinMax.ptMinTrackSize.y); + + if (MaxSize) *MaxSize = MinMax.ptMaxSize; + if (MaxPos) *MaxPos = MinMax.ptMaxPosition; + if (MinTrack) *MinTrack = MinMax.ptMinTrackSize; + if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize; +} + +BOOL STATIC +WinPosChangeActiveWindow(HWND Wnd, BOOL MouseMsg) +{ +} + +LONG STATIC +WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos, + RECT* WindowRect, RECT* ClientRect) +{ +} + +BOOL +WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject, + PWINDOWPOS WinPos, + PRECT WindowRect, + PRECT ClientRect) +{ + if (!(WinPos->flags & SWP_NOSENDCHANGING)) + { + NtUserSendMessage(WindowObject->Self, WM_WINDOWPOSCHANGING, 0, + (LPARAM)WinPos); + } + + *WindowRect = WindowObject->WindowRect; + *ClientRect = + (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect : + WindowObject->ClientRect; + + if (!(WinPos->flags & SWP_NOSIZE)) + { + WindowRect->right = WindowRect->left + WinPos->cx; + WindowRect->bottom = WindowRect->top + WinPos->cy; + } + + if (!(WinPos->flags & SWP_NOMOVE)) + { + WindowRect->left = WinPos->x; + WindowRect->top = WinPos->y; + WindowRect->right += WinPos->x - WindowObject->WindowRect.left; + WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top; + + W32kOffsetRect(ClientRect, WinPos->x - WindowObject->WindowRect.left, + WinPos->y - WindowObject->WindowRect.top); + } + + WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; + return(TRUE); +} + +BOOLEAN +WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx, + INT cy, UINT flags) +{ + PWINDOW_OBJECT Window; + NTSTATUS Status; + WINDOWPOS WinPos; + RECT NewWindowRect; + RECT NewClientRect; + HRGN VisRgn = NULL; + ULONG WvrFlags = 0; + + /* FIXME: Get current active window from active queue. */ + + /* Check if the window is for a desktop. */ + if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow) + { + return(FALSE); + } + + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable, + Wnd, + otWindow, + (PVOID*)&Window); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + /* Fix up the flags. */ + if (Window->Style & WS_VISIBLE) + { + flags &= ~SWP_SHOWWINDOW; + } + else + { + if (!(flags & SWP_SHOWWINDOW)) + { + flags |= SWP_NOREDRAW; + } + flags &= ~SWP_HIDEWINDOW; + } + + cx = max(cx, 0); + cy = max(cy, 0); + + if ((Window->WindowRect.right - Window->WindowRect.left) == cx && + (Window->WindowRect.bottom - Window->WindowRect.top) == cy) + { + flags |= SWP_NOSIZE; + } + if (Window->WindowRect.left == x && Window->WindowRect.top == y) + { + flags |= SWP_NOMOVE; + } + if (FALSE /* FIXME: Check if the window if already active. */) + { + flags |= SWP_NOACTIVATE; + } + else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD) + { + if (!(flags & SWP_NOACTIVATE)) + { + flags &= ~SWP_NOZORDER; + WndInsertAfter = HWND_TOP; + } + } + + if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST) + { + WndInsertAfter = HWND_TOP; + } + + if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM) + { + /* FIXME: Find the window to insert after. */ + } + + WinPos.hwnd = Wnd; + WinPos.hwndInsertAfter = WndInsertAfter; + WinPos.x = x; + WinPos.y = y; + WinPos.cx = cx; + WinPos.cy = cy; + WinPos.flags = flags; + + WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); + + if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != + SWP_NOZORDER) + { + /* FIXME: SWP_DoOwnedPopups. */ + } + + /* FIXME: Adjust flags based on WndInsertAfter */ + + if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) && + WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | + SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != + (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) + { + if (Window->Style & WS_CLIPCHILDREN) + { + VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0); + } + else + { + VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW, 0, 0); + } + } + + WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, + &NewClientRect); + + /* FIXME: Relink windows. */ + + /* FIXME: Reset active DCEs */ + + /* FIXME: Check for redrawing the whole client rect. */ + + if (WinPos.flags & SWP_SHOWWINDOW) + { + Window->Style |= WS_VISIBLE; + flags |= SWP_EX_PAINTSELF; + VisRgn = 1; + } + else + { + /* FIXME: Move the window bits */ + } + + if (WinPos.flags & SWP_HIDEWINDOW) + { + Window->Style &= ~WS_VISIBLE; + } + + /* FIXME: Hide or show the claret */ + + if (VisRgn) + { + if (!(WinPos.flags & SWP_NOREDRAW)) + { + if (flags & SWP_EX_PAINTSELF) + { + PaintRedrawWindow(Window->Self, NULL, + (VisRgn == 1) ? 0 : VisRgn, + RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | + RDW_ALLCHILDREN, + RDW_EX_XYWINDOW | RDW_EX_USEHRGN); + } + else + { + PaintRedrawWindow(Window->Self, NULL, + (VisRgn == 1) ? 0 : VisRgn, + RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, + RDW_EX_USEHRGN); + } + /* FIXME: Redraw the window parent. */ + } + /* FIXME: Delete VisRgn */ + } + + if (!(flags & SWP_NOACTIVATE)) + { + WinPosChangeActiveWindow(WinPos.hwnd, FALSE); + } + + /* FIXME: Check some conditions before doing this. */ + NtUserSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&WinPos); + + ObmDereferenceObject(Window); + return(TRUE); +} + +LRESULT +WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect) +{ + *ClientRect = *WindowRect; + return(W32kSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL)); +} + +BOOLEAN +WinPosShowWindow(HWND Wnd, INT Cmd) +{ + BOOLEAN WasVisible; + PWINDOW_OBJECT Window; + NTSTATUS Status; + UINT Swp = 0; + RECT NewPos; + BOOLEAN ShowFlag; + + Status = + ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable, + Wnd, + otWindow, + (PVOID*)&Window); + if (!NT_SUCCESS(Status)) + { + return(FALSE); + } + + WasVisible = (Window->Style & WS_VISIBLE) != 0; + + switch (Cmd) + { + case SW_HIDE: + { + if (!WasVisible) + { + ObmDereferenceObject(Window); + return(FALSE); + } + Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | + SWP_NOZORDER; + break; + } + + case SW_SHOWMINNOACTIVE: + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* Fall through. */ + case SW_SHOWMINIMIZED: + Swp |= SWP_SHOWWINDOW; + /* Fall through. */ + case SW_MINIMIZE: + { + Swp |= SWP_FRAMECHANGED; + if (!(Window->Style & WS_MINIMIZE)) + { + Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos); + } + else + { + Swp |= SWP_NOSIZE | SWP_NOMOVE; + } + break; + } + + case SW_SHOWMAXIMIZED: + { + Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; + if (!(Window->Style & WS_MAXIMIZE)) + { + Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos); + } + else + { + Swp |= SWP_NOSIZE | SWP_NOMOVE; + } + break; + } + + case SW_SHOWNA: + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + /* Fall through. */ + case SW_SHOW: + Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + /* Don't activate the topmost window. */ + break; + + case SW_SHOWNOACTIVATE: + Swp |= SWP_NOZORDER; + /* Fall through. */ + case SW_SHOWNORMAL: + case SW_SHOWDEFAULT: + case SW_RESTORE: + Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED; + if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos); + } + else + { + Swp |= SWP_NOSIZE | SWP_NOMOVE; + } + break; + } + + ShowFlag = (Cmd != SW_HIDE); + if (ShowFlag != WasVisible) + { + NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0); + /* + * FIXME: Need to check the window wasn't destroyed during the + * window procedure. + */ + } + + if (Window->Style & WS_CHILD && + !W32kIsWindowVisible(Window->Parent->Self) && + (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE)) + { + if (Cmd == SW_HIDE) + { + Window->Style &= ~WS_VISIBLE; + } + else + { + Window->Style |= WS_VISIBLE; + } + } + else + { + if (Window->Style & WS_CHILD && + !(Window->ExStyle & WS_EX_MDICHILD)) + { + Swp |= SWP_NOACTIVATE | SWP_NOZORDER; + } + if (!(Swp & MINMAX_NOSWP)) + { + WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top, + NewPos.right, NewPos.bottom, LOWORD(Swp)); + if (Cmd == SW_HIDE) + { + /* Hide the window. */ + if (Wnd == W32kGetActiveWindow()) + { + WinPosActivateOtherWindow(Window); + } + /* Revert focus to parent. */ + if (Wnd == W32kGetFocusWindow() || + W32kIsChildWindow(Wnd, W32kGetFocusWindow())) + { + W32kSetFocusWindow(Window->Parent->Self); + } + } + } + /* FIXME: Check for window destruction. */ + /* Show title for minimized windows. */ + if (Window->Style & WS_MINIMIZE) + { + WinPosShowIconTitle(Window, TRUE); + } + } + + if (Window->Flags & WINDOWOBJECT_NEED_SIZE) + { + WPARAM wParam = SIZE_RESTORED; + + Window->Flags &= ~WINDOWOBJECT_NEED_SIZE; + if (Window->Style & WS_MAXIMIZE) + { + wParam = SIZE_MAXIMIZED; + } + else if (Window->Style & WS_MINIMIZE) + { + wParam = SIZE_MINIMIZED; + } + + NtUserSendMessage(Wnd, WM_SIZE, wParam, + MAKELONG(Window->ClientRect.right - + Window->ClientRect.left, + Window->ClientRect.bottom - + Window->ClientRect.top)); + NtUserSendMessage(Wnd, WM_MOVE, 0, + MAKELONG(Window->ClientRect.left, + Window->ClientRect.top)); + } + ObmDereferenceObject(Window); + return(WasVisible); +} + +BOOL STATIC +WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point) +{ + return(Point.x >= Window->WindowRect.left && + Point.x < Window->WindowRect.right && + Point.y >= Window->WindowRect.top && + Point.y < Window->WindowRect.bottom); +} + +USHORT STATIC +WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point, + PWINDOW_OBJECT* Window) +{ + PLIST_ENTRY CurrentEntry; + PWINDOW_OBJECT Current; + + CurrentEntry = ScopeWin->ChildrenListHead.Flink; + while (CurrentEntry != &ScopeWin->ChildrenListHead) + { + Current = + CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, SiblingListEntry); + + if (Current->Style & WS_VISIBLE && + ((!(Current->Style & WS_DISABLED)) || + (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && + WinPosPtInWindow(Current, Point)) + { + *Window = Current; + if (Current->Style & WS_DISABLED) + { + return(HTERROR); + } + if (Current->Style & WS_MINIMIZE) + { + return(HTCAPTION); + } + if (Point.x >= Current->ClientRect.left && + Point.x < Current->ClientRect.right && + Point.y >= Current->ClientRect.top && + Point.y < Current->ClientRect.bottom) + { + Point.x -= Current->ClientRect.left; + Point.y -= Current->ClientRect.top; + + return(WinPosSearchChildren(Current, Point, Window)); + } + return(0); + } + CurrentEntry = CurrentEntry->Flink; + } + return(0); +} + +USHORT +WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, + PWINDOW_OBJECT* Window) +{ + HWND DesktopWindowHandle; + PWINDOW_OBJECT DesktopWindow; + POINT Point = WinPoint; + USHORT HitTest; + + *Window = NULL; + + if (ScopeWin->Style & WS_DISABLED) + { + return(HTERROR); + } + + /* Translate the point to the space of the scope window. */ + DesktopWindowHandle = W32kGetDesktopWindow(); + DesktopWindow = W32kGetWindowObject(DesktopWindowHandle); + Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left; + Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top; + W32kReleaseWindowObject(DesktopWindow); + + HitTest = WinPosSearchChildren(ScopeWin, Point, Window); + if (HitTest != 0) + { + return(HitTest); + } + + if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue) + { + HitTest = W32kSendMessage((*Window)->Self, WM_NCHITTEST, 0, + MAKELONG(Point.x, Point.y), FALSE); + /* FIXME: Check for HTTRANSPARENT here. */ + } + else + { + HitTest = HTCLIENT; + } + + return(HitTest); +} diff --git a/subsys/win32k/ntuser/winsta.c b/subsys/win32k/ntuser/winsta.c new file mode 100644 index 0000000..1bec018 --- /dev/null +++ b/subsys/win32k/ntuser/winsta.c @@ -0,0 +1,872 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Window stations and desktops + * FILE: subsys/win32k/ntuser/winsta.c + * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 06-06-2001 CSH Created + * NOTES: Exported functions set the Win32 last error value + * on errors. The value can be retrieved with the Win32 + * function GetLastError(). + * TODO: The process window station is created on + * the first USER32/GDI32 call not related + * to window station/desktop handling + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define WINSTA_ROOT_NAME L"\\Windows\\WindowStations" + +LRESULT CALLBACK +W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +STATIC PWNDCLASS_OBJECT DesktopWindowClass; + +/* Currently active desktop */ +STATIC HDESK InputDesktopHandle = NULL; +STATIC PDESKTOP_OBJECT InputDesktop = NULL; +STATIC PWINSTATION_OBJECT InputWindowStation = NULL; + +static HDC ScreenDeviceContext = NULL; + +/* FUNCTIONS *****************************************************************/ + +PDESKTOP_OBJECT +W32kGetActiveDesktop(VOID) +{ + return(InputDesktop); +} + +NTSTATUS +InitWindowStationImpl(VOID) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE WindowStationsDirectory; + UNICODE_STRING UnicodeString; + NTSTATUS Status; + WNDCLASSEX wcx; + + /* + * Create the '\Windows\WindowStations' directory + */ + RtlInitUnicodeStringFromLiteral(&UnicodeString, + WINSTA_ROOT_NAME); + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + 0, + NULL, + NULL); + + Status = ZwCreateDirectoryObject(&WindowStationsDirectory, + 0, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("Could not create \\Windows\\WindowStations directory " + "(Status 0x%X)\n", Status); + return Status; + } + + /* + * Create the desktop window class + */ + wcx.style = 0; + wcx.lpfnWndProc = W32kDesktopWindowProc; + wcx.cbClsExtra = wcx.cbWndExtra = 0; + wcx.hInstance = wcx.hIcon = wcx.hCursor = NULL; + wcx.hbrBackground = NULL; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = L"DesktopWindowClass"; + DesktopWindowClass = W32kCreateClass(&wcx, TRUE); + + return(STATUS_SUCCESS); +} + +NTSTATUS +CleanupWindowStationImpl(VOID) +{ + return STATUS_SUCCESS; +} + + +NTSTATUS +ValidateWindowStationHandle(HWINSTA WindowStation, + KPROCESSOR_MODE AccessMode, + ACCESS_MASK DesiredAccess, + PWINSTATION_OBJECT *Object) +{ + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(WindowStation, + DesiredAccess, + ExWindowStationObjectType, + AccessMode, + (PVOID*)Object, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + } + + return Status; +} + +NTSTATUS +ValidateDesktopHandle(HDESK Desktop, + KPROCESSOR_MODE AccessMode, + ACCESS_MASK DesiredAccess, + PDESKTOP_OBJECT *Object) +{ + NTSTATUS Status; + + Status = ObReferenceObjectByHandle(Desktop, + DesiredAccess, + ExDesktopObjectType, + AccessMode, + (PVOID*)Object, + NULL); + if (!NT_SUCCESS(Status)) + { + SetLastNtError(Status); + } + + return Status; +} + +/* + * FUNCTION: + * Closes a window station handle + * ARGUMENTS: + * hWinSta = Handle to the window station + * RETURNS: + * Status + * NOTES: + * The window station handle can be created with + * NtUserCreateWindowStation() or NtUserOpenWindowStation(). + * Attemps to close a handle to the window station assigned + * to the calling process will fail + */ +BOOL +STDCALL +NtUserCloseWindowStation( + HWINSTA hWinSta) +{ + PWINSTATION_OBJECT Object; + NTSTATUS Status; + + DPRINT("About to close window station handle (0x%X)\n", hWinSta); + + Status = ValidateWindowStationHandle( + hWinSta, + KernelMode, + 0, + &Object); + if (!NT_SUCCESS(Status)) { + DPRINT("Validation of window station handle (0x%X) failed\n", hWinSta); + return FALSE; + } + + ObDereferenceObject(Object); + + DPRINT("Closing window station handle (0x%X)\n", hWinSta); + + Status = ZwClose(hWinSta); + if (!NT_SUCCESS(Status)) { + SetLastNtError(Status); + return FALSE; + } else { + return TRUE; + } +} + +/* + * FUNCTION: + * Creates a new window station + * ARGUMENTS: + * lpszWindowStationName = Name of the new window station + * dwDesiredAccess = Requested type of access + * lpSecurity = Security descriptor + * Unknown3 = Unused + * Unknown4 = Unused + * Unknown5 = Unused + * RETURNS: + * Handle to the new window station that can be closed with + * NtUserCloseWindowStation() + * Zero on failure + */ +HWINSTA STDCALL +NtUserCreateWindowStation(PUNICODE_STRING lpszWindowStationName, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpSecurity, + DWORD Unknown3, + DWORD Unknown4, + DWORD Unknown5) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING WindowStationName; + PWINSTATION_OBJECT WinStaObject; + WCHAR NameBuffer[MAX_PATH]; + NTSTATUS Status; + HWINSTA WinSta; + + wcscpy(NameBuffer, WINSTA_ROOT_NAME); + wcscat(NameBuffer, L"\\"); + wcscat(NameBuffer, lpszWindowStationName->Buffer); + RtlInitUnicodeString(&WindowStationName, NameBuffer); + + DPRINT("Trying to open window station (%wZ)\n", &WindowStationName); + + /* Initialize ObjectAttributes for the window station object */ + InitializeObjectAttributes(&ObjectAttributes, + &WindowStationName, + 0, + NULL, + NULL); + + Status = ObOpenObjectByName(&ObjectAttributes, + ExWindowStationObjectType, + NULL, + UserMode, + dwDesiredAccess, + NULL, + &WinSta); + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened window station (%wZ)\n", WindowStationName); + return((HWINSTA)WinSta); + } + + DPRINT("Creating window station (%wZ)\n", &WindowStationName); + + Status = ObCreateObject(&WinSta, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + ExWindowStationObjectType, + (PVOID*)&WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed creating window station (%wZ)\n", &WindowStationName); + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + return (HWINSTA)0; + } + + WinStaObject->HandleTable = ObmCreateHandleTable(); + if (!WinStaObject->HandleTable) + { + DPRINT("Failed creating handle table\n"); + ObDereferenceObject(WinStaObject); + SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); + return((HWINSTA)0); + } + + DPRINT("Window station successfully created (%wZ)\n", &WindowStationName); + + return((HWINSTA)WinSta); +} + +BOOL +STDCALL +NtUserGetObjectInformation( + HANDLE hObject, + DWORD nIndex, + PVOID pvInformation, + DWORD nLength, + PDWORD nLengthNeeded) +{ + return FALSE; +} + +/* + * FUNCTION: + * Returns a handle to the current process window station + * ARGUMENTS: + * None + * RETURNS: + * Handle to the window station assigned to the current process + * Zero on failure + * NOTES: + * The handle need not be closed by the caller + */ +HWINSTA +STDCALL +NtUserGetProcessWindowStation(VOID) +{ + return PROCESS_WINDOW_STATION(); +} + +BOOL +STDCALL +NtUserLockWindowStation( + HWINSTA hWindowStation) +{ + UNIMPLEMENTED + + return 0; +} + +/* + * FUNCTION: + * Opens an existing window station + * ARGUMENTS: + * lpszWindowStationName = Name of the existing window station + * dwDesiredAccess = Requested type of access + * RETURNS: + * Handle to the window station + * Zero on failure + * NOTES: + * The returned handle can be closed with NtUserCloseWindowStation() + */ +HWINSTA +STDCALL +NtUserOpenWindowStation( + PUNICODE_STRING lpszWindowStationName, + ACCESS_MASK dwDesiredAccess) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING WindowStationName; + PWINSTATION_OBJECT WinStaObject; + WCHAR NameBuffer[MAX_PATH]; + NTSTATUS Status; + HWINSTA WinSta; + + wcscpy(NameBuffer, WINSTA_ROOT_NAME); + wcscat(NameBuffer, L"\\"); + wcscat(NameBuffer, lpszWindowStationName->Buffer); + RtlInitUnicodeString(&WindowStationName, NameBuffer); + + DPRINT("Trying to open window station (%wZ)\n", &WindowStationName); + + /* Initialize ObjectAttributes for the window station object */ + InitializeObjectAttributes( + &ObjectAttributes, + &WindowStationName, + 0, + NULL, + NULL); + + Status = ObOpenObjectByName( + &ObjectAttributes, + ExDesktopObjectType, + NULL, + UserMode, + dwDesiredAccess, + NULL, + &WinSta); + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened window station (%wZ)\n", &WindowStationName); + return (HWINSTA)WinSta; + } + + SetLastNtError(Status); + return (HWINSTA)0; +} + +BOOL +STDCALL +NtUserSetObjectInformation( + HANDLE hObject, + DWORD nIndex, + PVOID pvInformation, + DWORD nLength) +{ + /* FIXME: ZwQueryObject */ + /* FIXME: ZwSetInformationObject */ + SetLastNtError(STATUS_UNSUCCESSFUL); + return FALSE; +} + +/* + * FUNCTION: + * Assigns a window station to the current process + * ARGUMENTS: + * hWinSta = Handle to the window station + * RETURNS: + * Status + */ +BOOL STDCALL +NtUserSetProcessWindowStation(HWINSTA hWindowStation) +{ + PWINSTATION_OBJECT Object; + NTSTATUS Status; + + DPRINT("About to set process window station with handle (0x%X)\n", + hWindowStation); + + Status = ValidateWindowStationHandle(hWindowStation, + KernelMode, + 0, + &Object); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of window station handle (0x%X) failed\n", + hWindowStation); + return FALSE; + } + + ObDereferenceObject(Object); + + SET_PROCESS_WINDOW_STATION(hWindowStation); + DPRINT("IoGetCurrentProcess()->Win32WindowStation 0x%X\n", + IoGetCurrentProcess()->Win32WindowStation); + + return TRUE; +} + +DWORD +STDCALL +NtUserSetWindowStationUser( + DWORD Unknown0, + DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + UNIMPLEMENTED + + return 0; +} + +BOOL +STDCALL +NtUserUnlockWindowStation( + HWINSTA hWindowStation) +{ + UNIMPLEMENTED + + return FALSE; +} + + +/* + * FUNCTION: + * Closes a desktop handle + * ARGUMENTS: + * hDesktop = Handle to the desktop + * RETURNS: + * Status + * NOTES: + * The desktop handle can be created with NtUserCreateDesktop() or + * NtUserOpenDesktop(). + * The function will fail if any thread in the calling process is using the + * specified desktop handle or if the handle refers to the initial desktop + * of the calling process + */ +BOOL +STDCALL +NtUserCloseDesktop( + HDESK hDesktop) +{ + PDESKTOP_OBJECT Object; + NTSTATUS Status; + + DPRINT("About to close desktop handle (0x%X)\n", hDesktop); + + Status = ValidateDesktopHandle( + hDesktop, + KernelMode, + 0, + &Object); + if (!NT_SUCCESS(Status)) { + DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); + return FALSE; + } + + ObDereferenceObject(Object); + + DPRINT("Closing desktop handle (0x%X)\n", hDesktop); + + Status = ZwClose(hDesktop); + if (!NT_SUCCESS(Status)) { + SetLastNtError(Status); + return FALSE; + } else { + return TRUE; + } +} + +/* + * FUNCTION: + * Creates a new desktop + * ARGUMENTS: + * lpszDesktopName = Name of the new desktop + * dwFlags = Interaction flags + * dwDesiredAccess = Requested type of access + * lpSecurity = Security descriptor + * hWindowStation = Handle to window station on which to create the desktop + * RETURNS: + * Handle to the new desktop that can be closed with NtUserCloseDesktop() + * Zero on failure + */ +HDESK STDCALL +NtUserCreateDesktop(PUNICODE_STRING lpszDesktopName, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess, + LPSECURITY_ATTRIBUTES lpSecurity, + HWINSTA hWindowStation) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PWINSTATION_OBJECT WinStaObject; + PDESKTOP_OBJECT DesktopObject; + UNICODE_STRING DesktopName; + WCHAR NameBuffer[MAX_PATH]; + NTSTATUS Status; + HDESK Desktop; + + Status = ValidateWindowStationHandle(hWindowStation, + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed validation of window station handle (0x%X)\n", + hWindowStation); + return((HDESK)0); + } + + wcscpy(NameBuffer, WINSTA_ROOT_NAME); + wcscat(NameBuffer, L"\\"); + wcscat(NameBuffer, WinStaObject->Name.Buffer); + wcscat(NameBuffer, L"\\"); + wcscat(NameBuffer, lpszDesktopName->Buffer); + RtlInitUnicodeString(&DesktopName, NameBuffer); + + ObDereferenceObject(WinStaObject); + + DPRINT("Trying to open desktop (%wZ)\n", &DesktopName); + + /* Initialize ObjectAttributes for the desktop object */ + InitializeObjectAttributes(&ObjectAttributes, + &DesktopName, + 0, + NULL, + NULL); + Status = ObOpenObjectByName(&ObjectAttributes, + ExDesktopObjectType, + NULL, + UserMode, + dwDesiredAccess, + NULL, + &Desktop); + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName); + return((HDESK)Desktop); + } + + DPRINT("Status for open operation (0x%X)\n", Status); + + Status = ObCreateObject(&Desktop, + STANDARD_RIGHTS_REQUIRED, + &ObjectAttributes, + ExDesktopObjectType, + (PVOID*)&DesktopObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed creating desktop (%wZ)\n", &DesktopName); + SetLastNtError(STATUS_UNSUCCESSFUL); + return((HDESK)0); + } + + /* Initialize some local (to win32k) desktop state. */ + DesktopObject->ActiveMessageQueue = NULL; + InitializeListHead(&DesktopObject->WindowListHead); + DesktopObject->DesktopWindow = + W32kCreateDesktopWindow(DesktopObject->WindowStation, + DesktopWindowClass, + 640, 480); + + return((HDESK)Desktop); +} + +HDESK STDCALL +NtUserGetThreadDesktop(DWORD dwThreadId, + DWORD Unknown1) +{ + UNIMPLEMENTED; + return((HDESK)0); +} + +/* + * FUNCTION: + * Opens an existing desktop + * ARGUMENTS: + * lpszDesktopName = Name of the existing desktop + * dwFlags = Interaction flags + * dwDesiredAccess = Requested type of access + * RETURNS: + * Handle to the desktop + * Zero on failure + * NOTES: + * The returned handle can be closed with NtUserCloseDesktop() + */ +HDESK +STDCALL +NtUserOpenDesktop( + PUNICODE_STRING lpszDesktopName, + DWORD dwFlags, + ACCESS_MASK dwDesiredAccess) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + PWINSTATION_OBJECT WinStaObject; + UNICODE_STRING DesktopName; + WCHAR NameBuffer[MAX_PATH]; + NTSTATUS Status; + HDESK Desktop; + + /* Validate the window station handle and + compose the fully qualified desktop name */ + + Status = ValidateWindowStationHandle( + PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed validation of window station handle (0x%X)\n", + PROCESS_WINDOW_STATION()); + return (HDESK)0; + } + + wcscpy(NameBuffer, WINSTA_ROOT_NAME); + wcscat(NameBuffer, L"\\"); + wcscat(NameBuffer, WinStaObject->Name.Buffer); + wcscat(NameBuffer, L"\\"); + wcscat(NameBuffer, lpszDesktopName->Buffer); + RtlInitUnicodeString(&DesktopName, NameBuffer); + + ObDereferenceObject(WinStaObject); + + + DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName); + + /* Initialize ObjectAttributes for the desktop object */ + InitializeObjectAttributes( + &ObjectAttributes, + &DesktopName, + 0, + NULL, + NULL); + + Status = ObOpenObjectByName( + &ObjectAttributes, + ExDesktopObjectType, + NULL, + UserMode, + dwDesiredAccess, + NULL, + &Desktop); + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName); + return (HDESK)Desktop; + } + + SetLastNtError(Status); + return (HDESK)0; +} + +/* + * FUNCTION: + * Opens the input (interactive) desktop + * ARGUMENTS: + * dwFlags = Interaction flags + * fInherit = Inheritance option + * dwDesiredAccess = Requested type of access + * RETURNS: + * Handle to the input desktop + * Zero on failure + * NOTES: + * The returned handle can be closed with NtUserCloseDesktop() + */ +HDESK +STDCALL +NtUserOpenInputDesktop( + DWORD dwFlags, + BOOL fInherit, + ACCESS_MASK dwDesiredAccess) +{ + PDESKTOP_OBJECT Object; + NTSTATUS Status; + HDESK Desktop; + + DPRINT("About to open input desktop\n"); + + /* Get a pointer to the desktop object */ + + Status = ValidateDesktopHandle( + InputDesktop, + KernelMode, + 0, + &Object); + if (!NT_SUCCESS(Status)) { + DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop); + return (HDESK)0; + } + + /* Create a new handle to the object */ + + Status = ObOpenObjectByPointer( + Object, + 0, + NULL, + dwDesiredAccess, + ExDesktopObjectType, + UserMode, + &Desktop); + + ObDereferenceObject(Object); + + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened input desktop\n"); + return (HDESK)Desktop; + } + + SetLastNtError(Status); + return (HDESK)0; +} + +BOOL STDCALL +NtUserPaintDesktop(HDC hDC) +{ + UNIMPLEMENTED + + return FALSE; +} + +DWORD STDCALL +NtUserResolveDesktopForWOW(DWORD Unknown0) +{ + UNIMPLEMENTED + return 0; +} + +BOOL STDCALL +NtUserSetThreadDesktop(HDESK hDesktop) +{ + PDESKTOP_OBJECT DesktopObject; + NTSTATUS Status; + + /* Initialize the Win32 state if necessary. */ + W32kGuiCheck(); + + /* Validate the new desktop. */ + Status = ValidateDesktopHandle(hDesktop, + KernelMode, + 0, + &DesktopObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); + return(FALSE); + } + + /* Check for setting the same desktop as before. */ + if (DesktopObject == PsGetWin32Thread()->Desktop) + { + ObDereferenceObject(DesktopObject); + return(TRUE); + } + + /* FIXME: Should check here to see if the thread has any windows. */ + + ObDereferenceObject(PsGetWin32Thread()->Desktop); + PsGetWin32Thread()->Desktop = DesktopObject; + + return(TRUE); +} + +/* + * FUNCTION: + * Sets the current input (interactive) desktop + * ARGUMENTS: + * hDesktop = Handle to desktop + * RETURNS: + * Status + */ +BOOL STDCALL +NtUserSwitchDesktop(HDESK hDesktop) +{ + PDESKTOP_OBJECT DesktopObject; + NTSTATUS Status; + + DPRINT("About to switch desktop (0x%X)\n", hDesktop); + + Status = ValidateDesktopHandle(hDesktop, + KernelMode, + 0, + &DesktopObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop); + return(FALSE); + } + + /* FIXME: Fail if the desktop belong to an invisible window station */ + /* FIXME: Fail if the process is associated with a secured + desktop such as Winlogon or Screen-Saver */ + /* FIXME: Connect to input device */ + + /* Set the active desktop in the desktop's window station. */ + DesktopObject->WindowStation->ActiveDesktop = DesktopObject; + + /* Set the global state. */ + InputDesktopHandle = hDesktop; + InputDesktop = DesktopObject; + InputWindowStation = DesktopObject->WindowStation; + + ObDereferenceObject(DesktopObject); + + return(TRUE); +} + +VOID +W32kInitializeDesktopGraphics(VOID) +{ + ScreenDeviceContext = W32kCreateDC(L"DISPLAY", NULL, NULL, NULL); + GDIOBJ_MarkObjectGlobal(ScreenDeviceContext); + EnableMouse(ScreenDeviceContext); + NtUserAcquireOrReleaseInputOwnership(FALSE); +} + +HDC +W32kGetScreenDC(VOID) +{ + return(ScreenDeviceContext); +} + +LRESULT CALLBACK +W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CREATE: + return(0); + + case WM_NCCREATE: + return(1); + + default: + return(0); + } +} + +/* EOF */ diff --git a/subsys/win32k/objects/.cvsignore b/subsys/win32k/objects/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/objects/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/objects/bezier.c b/subsys/win32k/objects/bezier.c new file mode 100644 index 0000000..9337783 --- /dev/null +++ b/subsys/win32k/objects/bezier.c @@ -0,0 +1,184 @@ +#include +#include + +/****************************************************************** + * + * *Very* simple bezier drawing code, + * + * It uses a recursive algorithm to divide the curve in a series + * of straight line segements. Not ideal but for me sufficient. + * If you are in need for something better look for some incremental + * algorithm. + * + * 7 July 1998 Rein Klazes + */ + + /* + * some macro definitions for bezier drawing + * + * to avoid trucation errors the coordinates are + * shifted upwards. When used in drawing they are + * shifted down again, including correct rounding + * and avoiding floating point arithmatic + * 4 bits should allow 27 bits coordinates which I saw + * somewere in the win32 doc's + * + */ + +#define BEZIERSHIFTBITS 4 +#define BEZIERSHIFTUP(x) ((x)<>BEZIERSHIFTBITS) +/* maximum depth of recursion */ +#define BEZIERMAXDEPTH 8 + +/* size of array to store points on */ +/* enough for one curve */ +#define BEZIER_INITBUFSIZE (150) + +/* calculate Bezier average, in this case the middle + * correctly rounded... + * */ + +#define BEZIERMIDDLE(Mid, P1, P2) \ + (Mid).x=((P1).x+(P2).x + 1)/2;\ + (Mid).y=((P1).y+(P2).y + 1)/2; + +/********************************************************** +* BezierCheck helper function to check +* that recursion can be terminated +* Points[0] and Points[3] are begin and endpoint +* Points[1] and Points[2] are control points +* level is the recursion depth +* returns true if the recusion can be terminated +*/ +static BOOL BezierCheck( int level, POINT *Points) +{ + INT dx, dy; + + dx=Points[3].x-Points[0].x; + dy=Points[3].y-Points[0].y; + if(abs(dy)<=abs(dx)) {/* shallow line */ + /* check that control points are between begin and end */ + if(Points[1].x < Points[0].x){ + if(Points[1].x < Points[3].x) return FALSE; + }else + if(Points[1].x > Points[3].x) return FALSE; + if(Points[2].x < Points[0].x) { + if(Points[2].x < Points[3].x) return FALSE; + } else + if(Points[2].x > Points[3].x) return FALSE; + dx=BEZIERSHIFTDOWN(dx); + if(!dx) return TRUE; + if(abs(Points[1].y-Points[0].y-(dy/dx)* + BEZIERSHIFTDOWN(Points[1].x-Points[0].x)) > BEZIERPIXEL || + abs(Points[2].y-Points[0].y-(dy/dx)* + BEZIERSHIFTDOWN(Points[2].x-Points[0].x)) > BEZIERPIXEL) return FALSE; + else + return TRUE; + } else{ /* steep line */ + /* check that control points are between begin and end */ + if(Points[1].y < Points[0].y){ + if(Points[1].y < Points[3].y) return FALSE; + } else + if(Points[1].y > Points[3].y) return FALSE; + if(Points[2].y < Points[0].y){ + if(Points[2].y < Points[3].y) return FALSE; + } else + if(Points[2].y > Points[3].y) return FALSE; + dy=BEZIERSHIFTDOWN(dy); + if(!dy) return TRUE; + if(abs(Points[1].x-Points[0].x-(dx/dy)* + BEZIERSHIFTDOWN(Points[1].y-Points[0].y)) > BEZIERPIXEL || + abs(Points[2].x-Points[0].x-(dx/dy)* + BEZIERSHIFTDOWN(Points[2].y-Points[0].y)) > BEZIERPIXEL ) return FALSE; + else + return TRUE; + } +} + +/* Helper for GDI_Bezier. + * Just handles one Bezier, so Points should point to four POINTs + */ +static void GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut, + INT *nPtsOut, INT level ) +{ + if(*nPtsOut == *dwOut) { + *dwOut *= 2; + *PtsOut = ExAllocatePool(NonPagedPool, *dwOut * sizeof(POINT)); + } + + if(!level || BezierCheck(level, Points)) { + if(*nPtsOut == 0) { + (*PtsOut)[0].x = BEZIERSHIFTDOWN(Points[0].x); + (*PtsOut)[0].y = BEZIERSHIFTDOWN(Points[0].y); + *nPtsOut = 1; + } + (*PtsOut)[*nPtsOut].x = BEZIERSHIFTDOWN(Points[3].x); + (*PtsOut)[*nPtsOut].y = BEZIERSHIFTDOWN(Points[3].y); + (*nPtsOut) ++; + } else { + POINT Points2[4]; /* for the second recursive call */ + Points2[3]=Points[3]; + BEZIERMIDDLE(Points2[2], Points[2], Points[3]); + BEZIERMIDDLE(Points2[0], Points[1], Points[2]); + BEZIERMIDDLE(Points2[1],Points2[0],Points2[2]); + + BEZIERMIDDLE(Points[1], Points[0], Points[1]); + BEZIERMIDDLE(Points[2], Points[1], Points2[0]); + BEZIERMIDDLE(Points[3], Points[2], Points2[1]); + + Points2[0]=Points[3]; + + /* do the two halves */ + GDI_InternalBezier(Points, PtsOut, dwOut, nPtsOut, level-1); + GDI_InternalBezier(Points2, PtsOut, dwOut, nPtsOut, level-1); + } +} + +/*********************************************************************** + * GDI_Bezier [INTERNAL] + * Calculate line segments that approximate -what microsoft calls- a bezier + * curve. + * The routine recursively divides the curve in two parts until a straight + * line can be drawn + * + * PARAMS + * + * Points [I] Ptr to count POINTs which are the end and control points + * of the set of Bezier curves to flatten. + * count [I] Number of Points. Must be 3n+1. + * nPtsOut [O] Will contain no of points that have been produced (i.e. no. of + * lines+1). + * + * RETURNS + * + * Ptr to an array of POINTs that contain the lines that approximinate the + * Beziers. The array is allocated on the process heap and it is the caller's + * responsibility to HeapFree it. [this is not a particularly nice interface + * but since we can't know in advance how many points will generate, the + * alternative would be to call the function twice, once to determine the size + * and a second time to do the work - I decided this was too much of a pain]. + */ +POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut ) +{ + POINT *out; + INT Bezier, dwOut = BEZIER_INITBUFSIZE, i; + + if((count - 1) % 3 != 0) { + return NULL; + } + *nPtsOut = 0; + out = ExAllocatePool(NonPagedPool, dwOut * sizeof(POINT)); + for(Bezier = 0; Bezier < (count-1)/3; Bezier++) { + POINT ptBuf[4]; + memcpy(ptBuf, Points + Bezier * 3, sizeof(POINT) * 4); + for(i = 0; i < 4; i++) { + ptBuf[i].x = BEZIERSHIFTUP(ptBuf[i].x); + ptBuf[i].y = BEZIERSHIFTUP(ptBuf[i].y); + } + GDI_InternalBezier( ptBuf, &out, &dwOut, nPtsOut, BEZIERMAXDEPTH ); + } + + return out; +} diff --git a/subsys/win32k/objects/bitmaps.c b/subsys/win32k/objects/bitmaps.c new file mode 100644 index 0000000..f8d37ca --- /dev/null +++ b/subsys/win32k/objects/bitmaps.c @@ -0,0 +1,511 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +//#include +#include "../eng/handle.h" + +#define NDEBUG +#include + +BOOL STDCALL W32kBitBlt(HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + DWORD ROP) +{ + PDC DCDest = DC_HandleToPtr(hDCDest); + PDC DCSrc = DC_HandleToPtr(hDCSrc); + PSURFOBJ SurfDest, SurfSrc; + PSURFGDI SurfGDIDest, SurfGDISrc; + RECTL DestRect; + POINTL SourcePoint; + PBITMAPOBJ DestBitmapObj; + PBITMAPOBJ SrcBitmapObj; + BOOL Status, SurfDestAlloc, SurfSrcAlloc; + PPALOBJ DCLogPal; + PPALGDI PalDestGDI, PalSourceGDI; + PXLATEOBJ XlateObj = NULL; + HPALETTE SourcePalette, DestPalette; + + /* Offset the destination and source by the origin of their DCs. */ + XDest += DCDest->w.DCOrgX; + YDest += DCDest->w.DCOrgY; + XSrc += DCSrc->w.DCOrgX; + YSrc += DCSrc->w.DCOrgY; + + DestRect.left = XDest; + DestRect.top = YDest; + DestRect.right = XDest+Width; + DestRect.bottom = YDest+Height; + + SourcePoint.x = XSrc; + SourcePoint.y = YSrc; + + SurfDestAlloc = FALSE; + SurfSrcAlloc = FALSE; + + // Determine surfaces to be used in the bitblt + SurfDest = (PSURFOBJ)AccessUserObject(DCDest->Surface); + SurfSrc = (PSURFOBJ)AccessUserObject(DCSrc->Surface); + + SurfGDIDest = (PSURFGDI)AccessInternalObjectFromUserObject(SurfDest); + SurfGDISrc = (PSURFGDI)AccessInternalObjectFromUserObject(SurfSrc); + + // Retrieve the logical palette of the destination DC + DCLogPal = (PPALOBJ)AccessUserObject(DCDest->w.hPalette); + + if(DCLogPal) + if(DCLogPal->logicalToSystem) + XlateObj = DCLogPal->logicalToSystem; + + // If the source and destination formats differ, create an XlateObj [what if we already have one??] + if((BitsPerFormat(SurfDest->iBitmapFormat) != BitsPerFormat(SurfSrc->iBitmapFormat)) && (XlateObj == NULL)) + { + if(DCDest->w.hPalette != 0) + { + DestPalette = DCDest->w.hPalette; + } else + DestPalette = W32kGetStockObject(DEFAULT_PALETTE); + + if(DCSrc->w.hPalette != 0) + { + SourcePalette = DCSrc->w.hPalette; + } else + SourcePalette = W32kGetStockObject(DEFAULT_PALETTE); + + PalDestGDI = (PPALGDI)AccessInternalObject(DestPalette); + PalSourceGDI = (PPALGDI)AccessInternalObject(SourcePalette); + + XlateObj = (PXLATEOBJ)EngCreateXlate(PalDestGDI->Mode, PalSourceGDI->Mode, DestPalette, SourcePalette); + } + + // Perform the bitblt operation + + Status = EngBitBlt(SurfDest, SurfSrc, NULL, NULL, XlateObj, &DestRect, &SourcePoint, NULL, NULL, NULL, ROP); + + if(SurfDestAlloc == TRUE) ExFreePool(SurfDest); + if(SurfSrcAlloc == TRUE) ExFreePool(SurfSrc); + + DC_ReleasePtr(hDCDest); + DC_ReleasePtr(hDCSrc); + + return Status; +} + +HBITMAP STDCALL W32kCreateBitmap(INT Width, + INT Height, + UINT Planes, + UINT BitsPerPel, + CONST VOID *Bits) +{ + PBITMAPOBJ bmp; + HBITMAP hBitmap; + + Planes = (BYTE) Planes; + BitsPerPel = (BYTE) BitsPerPel; + + /* Check parameters */ + if (!Height || !Width) + { + return 0; + } + if (Planes != 1) + { + UNIMPLEMENTED; + return 0; + } + if (Height < 0) + { + Height = -Height; + } + if (Width < 0) + { + Width = -Width; + } + + /* Create the BITMAPOBJ */ + hBitmap = BITMAPOBJ_AllocBitmap (); + if (!hBitmap) + { + DPRINT("W32kCreateBitmap: BITMAPOBJ_AllocBitmap returned 0\n"); + return 0; + } + + bmp = BITMAPOBJ_HandleToPtr( hBitmap ); + + DPRINT("W32kCreateBitmap:%dx%d, %d (%d BPP) colors returning %08x\n", Width, Height, + 1 << (Planes * BitsPerPel), BitsPerPel, bmp); + + bmp->size.cx = Width; + bmp->size.cy = Height; + bmp->bitmap.bmType = 0; + bmp->bitmap.bmWidth = Width; + bmp->bitmap.bmHeight = Height; + bmp->bitmap.bmPlanes = Planes; + bmp->bitmap.bmBitsPixel = BitsPerPel; + bmp->bitmap.bmWidthBytes = BITMAPOBJ_GetWidthBytes (Width, BitsPerPel); + bmp->bitmap.bmBits = NULL; + bmp->DDBitmap = NULL; + bmp->dib = NULL; + + // Allocate memory for bitmap bits + bmp->bitmap.bmBits = ExAllocatePool(PagedPool, bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight); + + if (Bits) /* Set bitmap bits */ + { + W32kSetBitmapBits(hBitmap, Height * bmp->bitmap.bmWidthBytes, Bits); + } + + BITMAPOBJ_ReleasePtr( hBitmap ); + + return hBitmap; +} + +BOOL Bitmap_InternalDelete( PBITMAPOBJ pBmp ) +{ + ASSERT( pBmp ); + if( pBmp->bitmap.bmBits ) + ExFreePool(pBmp->bitmap.bmBits); + return TRUE; +} + + +HBITMAP STDCALL W32kCreateCompatibleBitmap(HDC hDC, + INT Width, + INT Height) +{ + HBITMAP hbmpRet; + PDC dc; + + hbmpRet = 0; + dc = DC_HandleToPtr (hDC); + + DPRINT("W32kCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, dc->w.bitsPerPixel); + + if (!dc) + { + return 0; + } + if ((Width >= 0x10000) || (Height >= 0x10000)) + { + DPRINT("got bad width %d or height %d, please look for reason\n", Width, Height); + } + else + { + /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */ + if (!Width || !Height) + { + hbmpRet = W32kCreateBitmap (1, 1, 1, 1, NULL); + } + else + { + hbmpRet = W32kCreateBitmap(Width, Height, 1, dc->w.bitsPerPixel, NULL); + } + } + DPRINT ("\t\t%04x\n", hbmpRet); + DC_ReleasePtr( hDC ); + return hbmpRet; +} + +HBITMAP STDCALL W32kCreateBitmapIndirect(CONST BITMAP *BM) +{ + return W32kCreateBitmap (BM->bmWidth, + BM->bmHeight, + BM->bmPlanes, + BM->bmBitsPixel, + BM->bmBits); +} + +HBITMAP STDCALL W32kCreateDiscardableBitmap(HDC hDC, + INT Width, + INT Height) +{ + /* FIXME: this probably should do something else */ + return W32kCreateCompatibleBitmap(hDC, Width, Height); +} + +BOOL STDCALL W32kExtFloodFill(HDC hDC, + INT XStart, + INT YStart, + COLORREF Color, + UINT FillType) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kFloodFill(HDC hDC, + INT XStart, + INT YStart, + COLORREF Fill) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kGetBitmapDimensionEx(HBITMAP hBitmap, + LPSIZE Dimension) +{ + PBITMAPOBJ bmp; + + bmp = BITMAPOBJ_HandleToPtr (hBitmap); + if (bmp == NULL) + { + return FALSE; + } + + *Dimension = bmp->size; + + return TRUE; +} + +COLORREF STDCALL W32kGetPixel(HDC hDC, + INT XPos, + INT YPos) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kMaskBlt(HDC hDCDest, + INT XDest, + INT YDest, + INT Width, + INT Height, + HDC hDCSrc, + INT XSrc, + INT YSrc, + HBITMAP hMaskBitmap, + INT xMask, + INT yMask, + DWORD ROP) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kPlgBlt(HDC hDCDest, + CONST POINT *Point, + HDC hDCSrc, + INT XSrc, + INT YSrc, + INT Width, + INT Height, + HBITMAP hMaskBitmap, + INT xMask, + INT yMask) +{ + UNIMPLEMENTED; +} + +LONG STDCALL W32kSetBitmapBits(HBITMAP hBitmap, + DWORD Bytes, + CONST VOID *Bits) +{ + DWORD height, ret; + PBITMAPOBJ bmp; + + bmp = BITMAPOBJ_HandleToPtr (hBitmap); + if (bmp == NULL || Bits == NULL) + { + return 0; + } + + if (Bytes < 0) + { + DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes ); + Bytes = -Bytes; + } + + /* Only get entire lines */ + height = Bytes / bmp->bitmap.bmWidthBytes; + if (height > bmp->bitmap.bmHeight) + { + height = bmp->bitmap.bmHeight; + } + Bytes = height * bmp->bitmap.bmWidthBytes; + DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n", + hBitmap, + Bytes, + Bits, + bmp->bitmap.bmWidth, + bmp->bitmap.bmHeight, + 1 << bmp->bitmap.bmBitsPixel, + height); + +#if 0 + /* FIXME: call DDI specific function here if available */ + if(bmp->DDBitmap) + { + DPRINT ("Calling device specific BitmapBits\n"); + if (bmp->DDBitmap->funcs->pBitmapBits) + { + ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET); + } + else + { + DPRINT ("BitmapBits == NULL??\n"); + ret = 0; + } + } + else +#endif + { + /* FIXME: Alloc enough for entire bitmap */ + if (bmp->bitmap.bmBits == NULL) + { + bmp->bitmap.bmBits = ExAllocatePool (PagedPool, Bytes); + } + if(!bmp->bitmap.bmBits) + { + DPRINT ("Unable to allocate bit buffer\n"); + ret = 0; + } + else + { + memcpy(bmp->bitmap.bmBits, Bits, Bytes); + ret = Bytes; + } + } + + return ret; +} + +BOOL STDCALL W32kSetBitmapDimensionEx(HBITMAP hBitmap, + INT Width, + INT Height, + LPSIZE Size) +{ + PBITMAPOBJ bmp; + + bmp = BITMAPOBJ_HandleToPtr (hBitmap); + if (bmp == NULL) + { + return FALSE; + } + + if (Size) + { + *Size = bmp->size; + } + bmp->size.cx = Width; + bmp->size.cy = Height; + + return TRUE; +} + +COLORREF STDCALL W32kSetPixel(HDC hDC, + INT X, + INT Y, + COLORREF Color) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kSetPixelV(HDC hDC, + INT X, + INT Y, + COLORREF Color) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kStretchBlt(HDC hDCDest, + INT XOriginDest, + INT YOriginDest, + INT WidthDest, + INT HeightDest, + HDC hDCSrc, + INT XOriginSrc, + INT YOriginSrc, + INT WidthSrc, + INT HeightSrc, + DWORD ROP) +{ + UNIMPLEMENTED; +} + +/* Internal Functions */ + +INT +BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp) +{ + switch(bpp) + { + case 1: + return 2 * ((bmWidth+15) >> 4); + + case 24: + bmWidth *= 3; /* fall through */ + case 8: + return bmWidth + (bmWidth & 1); + + case 32: + return bmWidth * 4; + + case 16: + case 15: + return bmWidth * 2; + + case 4: + return 2 * ((bmWidth+3) >> 2); + + default: + DPRINT ("stub"); + } + + return -1; +} + +HBITMAP BITMAPOBJ_CopyBitmap(HBITMAP hBitmap) +{ + PBITMAPOBJ bmp; + HBITMAP res; + BITMAP bm; + + bmp = BITMAPOBJ_HandleToPtr (hBitmap); + if (bmp == NULL) + { + return 0; + } + res = 0; + + bm = bmp->bitmap; + bm.bmBits = NULL; + res = W32kCreateBitmapIndirect(&bm); + if(res) + { + char *buf; + + buf = ExAllocatePool (NonPagedPool, bm.bmWidthBytes * bm.bmHeight); + W32kGetBitmapBits (hBitmap, bm.bmWidthBytes * bm.bmHeight, buf); + W32kSetBitmapBits (res, bm.bmWidthBytes * bm.bmHeight, buf); + ExFreePool (buf); + } + + return res; +} + +INT BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer) +{ + if(bmp->dib) + { + if(count < sizeof(DIBSECTION)) + { + if (count > sizeof(BITMAP)) count = sizeof(BITMAP); + } + else + { + if (count > sizeof(DIBSECTION)) count = sizeof(DIBSECTION); + } + memcpy(buffer, bmp->dib, count); + return count; + } + else + { + if (count > sizeof(BITMAP)) count = sizeof(BITMAP); + memcpy(buffer, &bmp->bitmap, count); + return count; + } +} diff --git a/subsys/win32k/objects/brush.c b/subsys/win32k/objects/brush.c new file mode 100644 index 0000000..4ed6bf6 --- /dev/null +++ b/subsys/win32k/objects/brush.c @@ -0,0 +1,246 @@ +/* $Id$ + */ + + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +//#include +#include + +#define NDEBUG +#include + +HBRUSH STDCALL W32kCreateBrushIndirect(CONST LOGBRUSH *lb) +{ + PBRUSHOBJ brushPtr; + HBRUSH hBrush; + + hBrush = BRUSHOBJ_AllocBrush(); + if (hBrush == NULL) + { + return 0; + } + + brushPtr = BRUSHOBJ_LockBrush (hBrush); + ASSERT( brushPtr ); //I want to know if this ever occurs + + if( brushPtr ){ + brushPtr->iSolidColor = lb->lbColor; + brushPtr->logbrush.lbStyle = lb->lbStyle; + brushPtr->logbrush.lbColor = lb->lbColor; + brushPtr->logbrush.lbHatch = lb->lbHatch; + + BRUSHOBJ_UnlockBrush( hBrush ); + return hBrush; + } + return NULL; +} + +HBRUSH STDCALL W32kCreateDIBPatternBrush(HGLOBAL hDIBPacked, + UINT ColorSpec) +{ + UNIMPLEMENTED; +#if 0 + LOGBRUSH logbrush; + PBITMAPINFO info, newInfo; + INT size; + + DPRINT("%04x\n", hbitmap ); + + logbrush.lbStyle = BS_DIBPATTERN; + logbrush.lbColor = coloruse; + logbrush.lbHatch = 0; + + /* Make a copy of the bitmap */ + if (!(info = (BITMAPINFO *)GlobalLock( hbitmap ))) + { + return 0; + } + + + if (info->bmiHeader.biCompression) size = info->bmiHeader.biSizeImage; + else + size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); + size += DIB_BitmapInfoSize(info, coloruse); + + if (!(logbrush.lbHatch = (INT)GlobalAlloc16( GMEM_MOVEABLE, size ))) + { + GlobalUnlock16( hbitmap ); + return 0; + } + newInfo = (BITMAPINFO *) GlobalLock16((HGLOBAL16)logbrush.lbHatch); + memcpy(newInfo, info, size); + GlobalUnlock16((HGLOBAL16)logbrush.lbHatch); + GlobalUnlock(hbitmap); + return W32kCreateBrushIndirect(&logbrush); +#endif +} + +HBRUSH STDCALL W32kCreateDIBPatternBrushPt(CONST VOID *PackedDIB, + UINT Usage) +{ + INT size; + LOGBRUSH logbrush; + PBITMAPINFO info; + PBITMAPINFO newInfo; + + info = (BITMAPINFO *) PackedDIB; + if (info == NULL) + { + return 0; + } + DPRINT ("%p %ldx%ld %dbpp\n", + info, + info->bmiHeader.biWidth, + info->bmiHeader.biHeight, + info->bmiHeader.biBitCount); + + logbrush.lbStyle = BS_DIBPATTERN; + logbrush.lbColor = Usage; + logbrush.lbHatch = 0; + + /* Make a copy of the bitmap */ + + if (info->bmiHeader.biCompression) + { + size = info->bmiHeader.biSizeImage; + } + else + { + size = DIB_GetDIBImageBytes (info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount); + } + size += DIB_BitmapInfoSize (info, Usage); + + logbrush.lbHatch = (LONG) GDIOBJ_AllocObj(size, GO_MAGIC_DONTCARE); + if (logbrush.lbHatch == 0) + { + return 0; + } + newInfo = (PBITMAPINFO) GDIOBJ_LockObj ((HGDIOBJ) logbrush.lbHatch, GO_MAGIC_DONTCARE); + ASSERT(newInfo); + memcpy(newInfo, info, size); + GDIOBJ_UnlockObj( (HGDIOBJ) logbrush.lbHatch, GO_MAGIC_DONTCARE ); + + return W32kCreateBrushIndirect (&logbrush); +} + +HBRUSH STDCALL W32kCreateHatchBrush(INT Style, + COLORREF Color) +{ + LOGBRUSH logbrush; + + DPRINT("%d %06lx\n", Style, Color); + + if (Style < 0 || Style >= NB_HATCH_STYLES) + { + return 0; + } + logbrush.lbStyle = BS_HATCHED; + logbrush.lbColor = Color; + logbrush.lbHatch = Style; + + return W32kCreateBrushIndirect (&logbrush); +} + +HBRUSH STDCALL W32kCreatePatternBrush(HBITMAP hBitmap) +{ + LOGBRUSH logbrush = { BS_PATTERN, 0, 0 }; + + DPRINT ("%04x\n", hBitmap); + logbrush.lbHatch = (INT) BITMAPOBJ_CopyBitmap (hBitmap); + if(!logbrush.lbHatch) + { + return 0; + } + else + { + return W32kCreateBrushIndirect( &logbrush ); + } +} + +HBRUSH STDCALL W32kCreateSolidBrush(COLORREF Color) +{ + LOGBRUSH logbrush; + + logbrush.lbStyle = BS_SOLID; + logbrush.lbColor = Color; + logbrush.lbHatch = 0; + + return W32kCreateBrushIndirect(&logbrush); +} + +BOOL STDCALL W32kFixBrushOrgEx(VOID) +{ + return FALSE; +} + +BOOL STDCALL W32kPatBlt(HDC hDC, + INT XLeft, + INT YLeft, + INT Width, + INT Height, + DWORD ROP) +{ + RECT DestRect; + PBRUSHOBJ BrushObj; + PSURFOBJ SurfObj; + DC *dc = DC_HandleToPtr(hDC); + BOOL ret; + + if (dc == NULL) + { + return(FALSE); + } + + SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface); + + BrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); + assert(BrushObj); + if (BrushObj->logbrush.lbStyle != BS_NULL) + { + if (Width > 0) + { + DestRect.left = XLeft + dc->w.DCOrgX; + DestRect.right = XLeft + Width + dc->w.DCOrgX; + } + else + { + DestRect.left = XLeft + Width + dc->w.DCOrgX; + DestRect.right = XLeft + dc->w.DCOrgX; + } + if (Height > 0) + { + DestRect.top = YLeft + dc->w.DCOrgY; + DestRect.bottom = YLeft + Height + dc->w.DCOrgY; + } + else + { + DestRect.top = YLeft + Height + dc->w.DCOrgY; + DestRect.bottom = YLeft + dc->w.DCOrgY; + } + ret = EngBitBlt(SurfObj, + NULL, + NULL, + NULL, + NULL, + &DestRect, + NULL, + NULL, + BrushObj, + NULL, + PATCOPY); + } + GDIOBJ_UnlockObj( dc->w.hBrush, GO_PEN_MAGIC ); + return(ret); +} + +BOOL STDCALL W32kSetBrushOrgEx(HDC hDC, + INT XOrg, + INT YOrg, + LPPOINT Point) +{ + UNIMPLEMENTED; +} diff --git a/subsys/win32k/objects/cliprgn.c b/subsys/win32k/objects/cliprgn.c new file mode 100644 index 0000000..2439268 --- /dev/null +++ b/subsys/win32k/objects/cliprgn.c @@ -0,0 +1,159 @@ + + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +// #define NDEBUG +#include + +VOID +CLIPPING_UpdateGCRegion(DC* Dc) +{ + if (Dc->w.hGCClipRgn == NULL) + { + Dc->w.hGCClipRgn = W32kCreateRectRgn(0, 0, 0, 0); + } + + if (Dc->w.hClipRgn == NULL) + { + W32kCombineRgn(Dc->w.hGCClipRgn, Dc->w.hVisRgn, 0, RGN_COPY); + } + else + { + W32kCombineRgn(Dc->w.hGCClipRgn, Dc->w.hClipRgn, Dc->w.hVisRgn, + RGN_AND); + } +} + +HRGN WINAPI SaveVisRgn(HDC hdc) +{ + HRGN copy; + PROSRGNDATA obj, copyObj; + PDC dc = DC_HandleToPtr(hdc); + + if (!dc) return 0; + + obj = RGNDATA_LockRgn(dc->w.hVisRgn); + + if(!(copy = W32kCreateRectRgn(0, 0, 0, 0))) + { + RGNDATA_UnlockRgn(dc->w.hVisRgn); + DC_ReleasePtr(hdc); + return 0; + } + W32kCombineRgn(copy, dc->w.hVisRgn, 0, RGN_COPY); + copyObj = RGNDATA_LockRgn(copy); +/* copyObj->header.hNext = obj->header.hNext; + header.hNext = copy; */ + + return copy; +} + +INT WINAPI +W32kSelectVisRgn(HDC hdc, HRGN hrgn) +{ + int retval; + DC *dc; + + if (!hrgn) return ERROR; + if (!(dc = DC_HandleToPtr(hdc))) return ERROR; + + dc->w.flags &= ~DC_DIRTY; + + retval = W32kCombineRgn(dc->w.hVisRgn, hrgn, 0, RGN_COPY); + CLIPPING_UpdateGCRegion(dc); + + return retval; +} + +int STDCALL W32kExcludeClipRect(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect) +{ + UNIMPLEMENTED; +} + +int STDCALL W32kExtSelectClipRgn(HDC hDC, + HRGN hrgn, + int fnMode) +{ + UNIMPLEMENTED; +} + +int STDCALL W32kGetClipBox(HDC hDC, + LPRECT rc) +{ + int retval; + DC *dc; + + if (!(dc = DC_HandleToPtr(hDC))) return ERROR; + retval = UnsafeW32kGetRgnBox(dc->w.hGCClipRgn, rc); + rc->left -= dc->w.DCOrgX; + rc->right -= dc->w.DCOrgX; + rc->top -= dc->w.DCOrgY; + rc->bottom -= dc->w.DCOrgY; + W32kDPtoLP(hDC, (LPPOINT)rc, 2); + return(retval); +} + +int STDCALL W32kGetMetaRgn(HDC hDC, + HRGN hrgn) +{ + UNIMPLEMENTED; +} + +int STDCALL W32kIntersectClipRect(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect) +{ + UNIMPLEMENTED; +} + +int STDCALL W32kOffsetClipRgn(HDC hDC, + int XOffset, + int YOffset) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kPtVisible(HDC hDC, + int X, + int Y) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kRectVisible(HDC hDC, + CONST PRECT rc) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kSelectClipPath(HDC hDC, + int Mode) +{ + UNIMPLEMENTED; +} + +int STDCALL W32kSelectClipRgn(HDC hDC, + HRGN hrgn) +{ + UNIMPLEMENTED; +} + +int STDCALL W32kSetMetaRgn(HDC hDC) +{ + UNIMPLEMENTED; +} + + + diff --git a/subsys/win32k/objects/color.c b/subsys/win32k/objects/color.c new file mode 100644 index 0000000..a9a2f91 --- /dev/null +++ b/subsys/win32k/objects/color.c @@ -0,0 +1,505 @@ +// FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include "../eng/handle.h" + +// #define NDEBUG +#include + +int COLOR_gapStart = 256; +int COLOR_gapEnd = -1; +int COLOR_gapFilled = 0; +int COLOR_max = 256; + +static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED +static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it + +const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] = +{ + // first 10 entries in the system palette + // red green blue flags + { 0x00, 0x00, 0x00, PC_SYS_USED }, + { 0x80, 0x00, 0x00, PC_SYS_USED }, + { 0x00, 0x80, 0x00, PC_SYS_USED }, + { 0x80, 0x80, 0x00, PC_SYS_USED }, + { 0x00, 0x00, 0x80, PC_SYS_USED }, + { 0x80, 0x00, 0x80, PC_SYS_USED }, + { 0x00, 0x80, 0x80, PC_SYS_USED }, + { 0xc0, 0xc0, 0xc0, PC_SYS_USED }, + { 0xc0, 0xdc, 0xc0, PC_SYS_USED }, + { 0xa6, 0xca, 0xf0, PC_SYS_USED }, + + // ... c_min/2 dynamic colorcells + // ... gap (for sparse palettes) + // ... c_min/2 dynamic colorcells + + { 0xff, 0xfb, 0xf0, PC_SYS_USED }, + { 0xa0, 0xa0, 0xa4, PC_SYS_USED }, + { 0x80, 0x80, 0x80, PC_SYS_USED }, + { 0xff, 0x00, 0x00, PC_SYS_USED }, + { 0x00, 0xff, 0x00, PC_SYS_USED }, + { 0xff, 0xff, 0x00, PC_SYS_USED }, + { 0x00, 0x00, 0xff, PC_SYS_USED }, + { 0xff, 0x00, 0xff, PC_SYS_USED }, + { 0x00, 0xff, 0xff, PC_SYS_USED }, + { 0xff, 0xff, 0xff, PC_SYS_USED } // last 10 +}; + +//forward declarations +COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color ); + + +const PALETTEENTRY* COLOR_GetSystemPaletteTemplate(void) +{ + return (const PALETTEENTRY*)&COLOR_sysPalTemplate; +} + +BOOL STDCALL W32kAnimatePalette(HPALETTE hpal, + UINT StartIndex, + UINT Entries, + CONST PPALETTEENTRY ppe) +{ +/* + if( hPal != W32kGetStockObject(DEFAULT_PALETTE) ) + { + PALETTEOBJ* palPtr = (PALETTEOBJ *)GDI_GetObjPtr(hPal, PALETTE_MAGIC); + if (!palPtr) return FALSE; + + if( (StartIndex + NumEntries) <= palPtr->logpalette.palNumEntries ) + { + UINT u; + for( u = 0; u < NumEntries; u++ ) + palPtr->logpalette.palPalEntry[u + StartIndex] = PaletteColors[u]; + PALETTE_Driver->pSetMapping(palPtr, StartIndex, NumEntries, hPal != hPrimaryPalette ); + GDI_ReleaseObj(hPal); + return TRUE; + } + GDI_ReleaseObj(hPal); + } + return FALSE; +*/ + UNIMPLEMENTED; +} + +HPALETTE STDCALL W32kCreateHalftonePalette(HDC hDC) +{ + int i, r, g, b; + struct { + WORD Version; + WORD NumberOfEntries; + PALETTEENTRY aEntries[256]; + } Palette; + + Palette.Version = 0x300; + Palette.NumberOfEntries = 256; + W32kGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries); + + for (r = 0; r < 6; r++) { + for (g = 0; g < 6; g++) { + for (b = 0; b < 6; b++) { + i = r + g*6 + b*36 + 10; + Palette.aEntries[i].peRed = r * 51; + Palette.aEntries[i].peGreen = g * 51; + Palette.aEntries[i].peBlue = b * 51; + } + } + } + + for (i = 216; i < 246; i++) { + int v = (i - 216) * 8; + Palette.aEntries[i].peRed = v; + Palette.aEntries[i].peGreen = v; + Palette.aEntries[i].peBlue = v; + } + + return W32kCreatePalette((LOGPALETTE *)&Palette); +} + +HPALETTE STDCALL W32kCreatePalette(CONST PLOGPALETTE palette) +{ + PPALOBJ PalObj; + + HPALETTE NewPalette = (HPALETTE)EngCreatePalette(PAL_INDEXED, palette->palNumEntries, (PULONG*) palette->palPalEntry, 0, 0, 0); + ULONG size; + + PalObj = (PPALOBJ)AccessUserObject(NewPalette); + + size = sizeof(LOGPALETTE) + (palette->palNumEntries * sizeof(PALETTEENTRY)); + PalObj->logpalette = ExAllocatePool(NonPagedPool, size); + memcpy(PalObj->logpalette, palette, size); + PALETTE_ValidateFlags(PalObj->logpalette->palPalEntry, PalObj->logpalette->palNumEntries); + PalObj->logicalToSystem = NULL; + + return NewPalette; +} + +BOOL STDCALL W32kGetColorAdjustment(HDC hDC, + LPCOLORADJUSTMENT ca) +{ + UNIMPLEMENTED; +} + +COLORREF STDCALL W32kGetNearestColor(HDC hDC, + COLORREF Color) +{ + COLORREF nearest = CLR_INVALID; + PDC dc; + PPALOBJ palObj; + + if( (dc = DC_HandleToPtr(hDC) ) ) + { + HPALETTE hpal = (dc->w.hPalette)? dc->w.hPalette : W32kGetStockObject(DEFAULT_PALETTE); + palObj = (PPALOBJ)AccessUserObject(hpal); + if (!palObj) { +// GDI_ReleaseObj(hdc); + return nearest; + } + + nearest = COLOR_LookupNearestColor(palObj->logpalette->palPalEntry, + palObj->logpalette->palNumEntries, Color); + // FIXME: release hpal!! +// GDI_ReleaseObj( hpal ); + DC_ReleasePtr( hDC ); + } + + return nearest; +} + +UINT STDCALL W32kGetNearestPaletteIndex(HPALETTE hpal, + COLORREF Color) +{ + PPALOBJ palObj = (PPALOBJ)AccessUserObject(hpal); + UINT index = 0; + + if( palObj ) + { + // Return closest match for the given RGB color + index = COLOR_PaletteLookupPixel(palObj->logpalette->palPalEntry, palObj->logpalette->palNumEntries, NULL, Color, FALSE); +// GDI_ReleaseObj( hpalette ); + } + + return index; +} + +UINT STDCALL W32kGetPaletteEntries(HPALETTE hpal, + UINT StartIndex, + UINT Entries, + LPPALETTEENTRY pe) +{ + PPALOBJ palPtr; + UINT numEntries; + + palPtr = (PPALOBJ)AccessUserObject(hpal); + if (!palPtr) return 0; + + numEntries = palPtr->logpalette->palNumEntries; + if (StartIndex + Entries > numEntries) Entries = numEntries - StartIndex; + if (pe) + { + if (StartIndex >= numEntries) + { +// GDI_ReleaseObj( hpalette ); + return 0; + } + memcpy(pe, &palPtr->logpalette->palPalEntry[StartIndex], Entries * sizeof(PALETTEENTRY)); + for(numEntries = 0; numEntries < Entries ; numEntries++) + if (pe[numEntries].peFlags & 0xF0) + pe[numEntries].peFlags = 0; + } + +// GDI_ReleaseObj( hpalette ); + return Entries; +} + +UINT STDCALL W32kGetSystemPaletteEntries(HDC hDC, + UINT StartIndex, + UINT Entries, + LPPALETTEENTRY pe) +{ + UINT i; + PDC dc; +/* + if (!(dc = AccessUserObject(hdc))) return 0; + + if (!pe) + { + Entries = dc->devCaps->sizePalette; + goto done; + } + + if (StartIndex >= dc->devCaps->sizePalette) + { + Entries = 0; + goto done; + } + + if (StartIndex + Entries >= dc->devCaps->sizePalette) Entries = dc->devCaps->sizePalette - StartIndex; + + for (i = 0; i < Entries; i++) + { + *(COLORREF*)(entries + i) = COLOR_GetSystemPaletteEntry(StartIndex + i); + } + + done: +// GDI_ReleaseObj(hdc); + return count; */ +} + +UINT STDCALL W32kGetSystemPaletteUse(HDC hDC) +{ + UNIMPLEMENTED; +} + +UINT STDCALL W32kRealizePalette(HDC hDC) +/* +The RealizePalette function modifies the palette for the device associated with the specified device context. If the device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device context is a display DC, the physical palette for that device is modified. + +A logical palette is a buffer between color-intensive applications and the system, allowing these applications to use as many colors as needed without interfering with colors displayed by other windows. + +1= IF DRAWING TO A DEVICE +-- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and + the system palette. +-- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the system palette. + +2= IF DRAWING TO A MEMORY DC\BITMAP +-- If it is a paletted bitmap, and is not an identity palette, then an XLATEOBJ is created between the logical palette and + the dc palette. +-- If it is an RGB palette, then an XLATEOBJ is created between the RGB values and the dc palette. +*/ +{ + PPALOBJ palPtr, sysPtr; + PPALGDI palGDI, sysGDI; + int realized = 0; + PDC dc = (PDC)AccessUserObject(hDC); + HPALETTE systemPalette; + PSURFGDI SurfGDI; + BOOLEAN success; + + if (!dc) return 0; + + palPtr = (PPALOBJ)AccessUserObject(dc->w.hPalette); + SurfGDI = (PSURFGDI)AccessInternalObjectFromUserObject(dc->Surface); + systemPalette = W32kGetStockObject(STOCK_DEFAULT_PALETTE); + sysPtr = (PPALOBJ)AccessInternalObject(systemPalette); + palGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette); + sysGDI = (PPALGDI)AccessInternalObject(systemPalette); + + // Step 1: Create mapping of system palette\DC palette + realized = PALETTE_SetMapping(palPtr, 0, palPtr->logpalette->palNumEntries, + (dc->w.hPalette != hPrimaryPalette) || + (dc->w.hPalette == W32kGetStockObject(DEFAULT_PALETTE))); + + // Step 2: + // The RealizePalette function modifies the palette for the device associated with the specified device context. If the + // device context is a memory DC, the color table for the bitmap selected into the DC is modified. If the device + // context is a display DC, the physical palette for that device is modified. + if(dc->w.flags == DC_MEMORY) + { + // Memory managed DC + DbgPrint("win32k: realizepalette unimplemented step 2 for DC_MEMORY"); + } else { + if(SurfGDI->SetPalette) + { + success = SurfGDI->SetPalette(dc->PDev, sysPtr, 0, 0, sysPtr->logpalette->palNumEntries); + } + } + + // Step 3: Create the XLATEOBJ for device managed DCs + if(dc->w.flags != DC_MEMORY) + { + // Device managed DC + palPtr->logicalToSystem = EngCreateXlate(sysGDI->Mode, palGDI->Mode, systemPalette, dc->w.hPalette); + } + +// GDI_ReleaseObj(dc->w.hPalette); +// GDI_ReleaseObj(hdc); + + return realized; +} + +BOOL STDCALL W32kResizePalette(HPALETTE hpal, + UINT Entries) +{ +/* PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal); + UINT cPrevEnt, prevVer; + INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY); + PXLATEOBJ XlateObj = NULL; + + if(!palPtr) return FALSE; + cPrevEnt = palPtr->logpalette->palNumEntries; + prevVer = palPtr->logpalette->palVersion; + prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR); + size += sizeof(int*) + sizeof(GDIOBJHDR); + XlateObj = palPtr->logicalToSystem; + + if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE; + + if(XlateObj) + { + PXLATEOBJ NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int)); + if(NewXlateObj == NULL) + { + ERR("Can not resize logicalToSystem -- out of memory!"); + GDI_ReleaseObj( hPal ); + return FALSE; + } + palPtr->logicalToSystem = NewXlateObj; + } + + if(cEntries > cPrevEnt) + { + if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int)); + memset( (BYTE*)palPtr + prevsize, 0, size - prevsize ); + PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt ); + } + palPtr->logpalette->palNumEntries = cEntries; + palPtr->logpalette->palVersion = prevVer; +// GDI_ReleaseObj( hPal ); + return TRUE; */ + + UNIMPLEMENTED; +} + +HPALETTE STDCALL W32kSelectPalette(HDC hDC, + HPALETTE hpal, + BOOL ForceBackground) +{ + PDC dc = (PDC)AccessUserObject(hDC); + HPALETTE oldPal; + + oldPal = dc->w.hPalette; + dc->w.hPalette = hpal; + + // FIXME: mark the palette as a [fore\back]ground pal + + return oldPal; +} + +BOOL STDCALL W32kSetColorAdjustment(HDC hDC, + CONST LPCOLORADJUSTMENT ca) +{ + UNIMPLEMENTED; +} + +UINT STDCALL W32kSetPaletteEntries(HPALETTE hpal, + UINT Start, + UINT Entries, + CONST LPPALETTEENTRY pe) +{ + PPALOBJ palPtr; + INT numEntries; + + palPtr = (PPALOBJ)AccessUserObject(hpal); + if (!palPtr) return 0; + + numEntries = palPtr->logpalette->palNumEntries; + if (Start >= numEntries) + { +// GDI_ReleaseObj( hpalette ); + return 0; + } + if (Start + Entries > numEntries) Entries = numEntries - Start; + memcpy(&palPtr->logpalette->palPalEntry[Start], pe, Entries * sizeof(PALETTEENTRY)); + PALETTE_ValidateFlags(palPtr->logpalette->palPalEntry, palPtr->logpalette->palNumEntries); + ExFreePool(palPtr->logicalToSystem); + palPtr->logicalToSystem = NULL; +// GDI_ReleaseObj( hpalette ); + return Entries; +} + +UINT STDCALL W32kSetSystemPaletteUse(HDC hDC, + UINT Usage) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kUnrealizeObject(HGDIOBJ hgdiobj) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kUpdateColors(HDC hDC) +{ + PDC dc; + HWND hWnd; + int size; +/* + if (!(dc = AccessUserObject(hDC))) return 0; + size = dc->devCaps->sizePalette; +// GDI_ReleaseObj( hDC ); + + if (Callout.WindowFromDC) + { + hWnd = Callout.WindowFromDC( hDC ); + + // Docs say that we have to remap current drawable pixel by pixel + // but it would take forever given the speed of XGet/PutPixel. + if (hWnd && size) Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE ); + } */ + return 0x666; +} + +int COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, int size, + PXLATEOBJ XlateObj, COLORREF col, BOOL skipReserved) +{ + int i, best = 0, diff = 0x7fffffff; + int r, g, b; + + for( i = 0; i < size && diff ; i++ ) + { + if(!(palPalEntry[i].peFlags & PC_SYS_USED) || (skipReserved && palPalEntry[i].peFlags & PC_SYS_RESERVED)) + continue; + + r = palPalEntry[i].peRed - GetRValue(col); + g = palPalEntry[i].peGreen - GetGValue(col); + b = palPalEntry[i].peBlue - GetBValue(col); + + r = r*r + g*g + b*b; + + if( r < diff ) { best = i; diff = r; } + } + return (XlateObj->pulXlate) ? XlateObj->pulXlate[best] : best; +} + +COLORREF COLOR_LookupNearestColor( PALETTEENTRY* palPalEntry, int size, COLORREF color ) +{ + unsigned char spec_type = color >> 24; + int i; + PALETTEENTRY *COLOR_sysPal = (PALETTEENTRY*)ReturnSystemPalette(); + + // we need logical palette for PALETTERGB and PALETTEINDEX colorrefs + + if( spec_type == 2 ) /* PALETTERGB */ + color = *(COLORREF*)(palPalEntry + COLOR_PaletteLookupPixel(palPalEntry,size,NULL,color,FALSE)); + + else if( spec_type == 1 ) /* PALETTEINDEX */ + { + if( (i = color & 0x0000ffff) >= size ) + { + DbgPrint("RGB(%lx) : idx %d is out of bounds, assuming NULL\n", color, i); + color = *(COLORREF*)palPalEntry; + } + else color = *(COLORREF*)(palPalEntry + i); + } + + color &= 0x00ffffff; + return (0x00ffffff & *(COLORREF*)(COLOR_sysPal + COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, color, FALSE))); +} + +int COLOR_PaletteLookupExactIndex( PALETTEENTRY* palPalEntry, int size, + COLORREF col ) +{ + int i; + BYTE r = GetRValue(col), g = GetGValue(col), b = GetBValue(col); + for( i = 0; i < size; i++ ) + { + if( palPalEntry[i].peFlags & PC_SYS_USED ) /* skips gap */ + if(palPalEntry[i].peRed == r && palPalEntry[i].peGreen == g && palPalEntry[i].peBlue == b) return i; + } + return -1; +} diff --git a/subsys/win32k/objects/coord.c b/subsys/win32k/objects/coord.c new file mode 100644 index 0000000..cf3b344 --- /dev/null +++ b/subsys/win32k/objects/coord.c @@ -0,0 +1,358 @@ +/* $Id$ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Coordinate systems + * FILE: subsys/win32k/objects/coord.c + * PROGRAMER: Unknown + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +BOOL STDCALL W32kCombineTransform(LPXFORM XFormResult, + CONST LPXFORM xform1, + CONST LPXFORM xform2) +{ + XFORM xformTemp; + + /* Check for illegal parameters */ + if (!XFormResult || !xform1 || !xform2) + { + return FALSE; + } + /* Create the result in a temporary XFORM, since xformResult may be + * equal to xform1 or xform2 */ + xformTemp.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21; + xformTemp.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22; + xformTemp.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21; + xformTemp.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22; + xformTemp.eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx; + xformTemp.eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy; + + /* Copy the result to xformResult */ + *XFormResult = xformTemp; + + return TRUE; +} + +VOID STATIC +CoordDPtoLP(PDC Dc, LPPOINT Point) +{ +FLOAT x, y; + x = (FLOAT)Point->x; + y = (FLOAT)Point->y; + Point->x = x * Dc->w.xformVport2World.eM11 + + y * Dc->w.xformVport2World.eM21 + Dc->w.xformVport2World.eDx; + Point->y = x * Dc->w.xformVport2World.eM12 + + y * Dc->w.xformVport2World.eM22 + Dc->w.xformVport2World.eDy; +} + +BOOL STDCALL +W32kDPtoLP(HDC hDC, + LPPOINT Points, + int Count) +{ + PDC Dc; + ULONG i; + + Dc = DC_HandleToPtr (hDC); + if (Dc == NULL || !Dc->w.vport2WorldValid) + { + return(FALSE); + } + + for (i = 0; i < Count; i++) + { + CoordDPtoLP(Dc, &Points[i]); + } + DC_ReleasePtr( hDC ); + return(TRUE); +} + +int +STDCALL +W32kGetGraphicsMode(HDC hDC) +{ + PDC dc; + int GraphicsMode; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { + return 0; + } + + GraphicsMode = dc->w.GraphicsMode; + DC_ReleasePtr( hDC ); + return GraphicsMode; +} + +BOOL +STDCALL +W32kGetWorldTransform(HDC hDC, + LPXFORM XForm) +{ + PDC dc; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { + return FALSE; + } + if (!XForm) + { + return FALSE; + } + *XForm = dc->w.xformWorld2Wnd; + DC_ReleasePtr( hDC ); + return TRUE; +} + +VOID STATIC +CoordLPtoDP(PDC Dc, LPPOINT Point) +{ + FLOAT x, y; + x = (FLOAT)Point->x; + y = (FLOAT)Point->y; + Point->x = x * Dc->w.xformWorld2Vport.eM11 + + y * Dc->w.xformWorld2Vport.eM21 + Dc->w.xformWorld2Vport.eDx; + Point->y = x * Dc->w.xformWorld2Vport.eM12 + + y * Dc->w.xformWorld2Vport.eM22 + Dc->w.xformWorld2Vport.eDy; +} + +BOOL STDCALL +W32kLPtoDP(HDC hDC, LPPOINT Points, INT Count) +{ + PDC Dc; + ULONG i; + + Dc = DC_HandleToPtr (hDC); + if (Dc == NULL) + { + return(FALSE); + } + + for (i = 0; i < Count; i++) + { + CoordLPtoDP(Dc, &Points[i]); + } + DC_ReleasePtr( hDC ); + return(TRUE); +} + +BOOL +STDCALL +W32kModifyWorldTransform(HDC hDC, + CONST LPXFORM XForm, + DWORD Mode) +{ + PDC dc; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { +// SetLastError( ERROR_INVALID_HANDLE ); + return FALSE; + } + if (!XForm) + { + return FALSE; + } + + /* Check that graphics mode is GM_ADVANCED */ + if (dc->w.GraphicsMode!=GM_ADVANCED) + { + return FALSE; + } + switch (Mode) + { + case MWT_IDENTITY: + dc->w.xformWorld2Wnd.eM11 = 1.0f; + dc->w.xformWorld2Wnd.eM12 = 0.0f; + dc->w.xformWorld2Wnd.eM21 = 0.0f; + dc->w.xformWorld2Wnd.eM22 = 1.0f; + dc->w.xformWorld2Wnd.eDx = 0.0f; + dc->w.xformWorld2Wnd.eDy = 0.0f; + break; + + case MWT_LEFTMULTIPLY: + W32kCombineTransform(&dc->w.xformWorld2Wnd, XForm, &dc->w.xformWorld2Wnd ); + break; + + case MWT_RIGHTMULTIPLY: + W32kCombineTransform(&dc->w.xformWorld2Wnd, &dc->w.xformWorld2Wnd, XForm); + break; + + default: + DC_ReleasePtr( hDC ); + return FALSE; + } + DC_UpdateXforms (dc); + DC_ReleasePtr( hDC ); + return TRUE; +} + +BOOL +STDCALL +W32kOffsetViewportOrgEx(HDC hDC, + int XOffset, + int YOffset, + LPPOINT Point) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kOffsetWindowOrgEx(HDC hDC, + int XOffset, + int YOffset, + LPPOINT Point) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kScaleViewportExtEx(HDC hDC, + int Xnum, + int Xdenom, + int Ynum, + int Ydenom, + LPSIZE Size) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kScaleWindowExtEx(HDC hDC, + int Xnum, + int Xdenom, + int Ynum, + int Ydenom, + LPSIZE Size) +{ + UNIMPLEMENTED; +} + +int +STDCALL +W32kSetGraphicsMode(HDC hDC, + int Mode) +{ + INT ret; + DC *dc; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { + return 0; + } + + /* One would think that setting the graphics mode to GM_COMPATIBLE + * would also reset the world transformation matrix to the unity + * matrix. However, in Windows, this is not the case. This doesn't + * make a lot of sense to me, but that's the way it is. + */ + + if ((Mode != GM_COMPATIBLE) && (Mode != GM_ADVANCED)) + { + DC_ReleasePtr( hDC ); + return 0; + } + ret = dc->w.GraphicsMode; + dc->w.GraphicsMode = Mode; + DC_ReleasePtr( hDC ); + return ret; +} + +int +STDCALL +W32kSetMapMode(HDC hDC, + int MapMode) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetViewportExtEx(HDC hDC, + int XExtent, + int YExtent, + LPSIZE Size) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetViewportOrgEx(HDC hDC, + int X, + int Y, + LPPOINT Point) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetWindowExtEx(HDC hDC, + int XExtent, + int YExtent, + LPSIZE Size) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetWindowOrgEx(HDC hDC, + int X, + int Y, + LPPOINT Point) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetWorldTransform(HDC hDC, + CONST LPXFORM XForm) +{ + PDC dc; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { + return FALSE; + } + if (!XForm) + { + DC_ReleasePtr( hDC ); + return FALSE; + } + + /* Check that graphics mode is GM_ADVANCED */ + if (dc->w.GraphicsMode != GM_ADVANCED) + { + DC_ReleasePtr( hDC ); + return FALSE; + } + dc->w.xformWorld2Wnd = *XForm; + DC_UpdateXforms (dc); + DC_ReleasePtr( hDC ); + return TRUE; +} + + diff --git a/subsys/win32k/objects/dc.c b/subsys/win32k/objects/dc.c new file mode 100644 index 0000000..9c28ef1 --- /dev/null +++ b/subsys/win32k/objects/dc.c @@ -0,0 +1,1304 @@ +/* $Id$ + * + * DC.C - Device context functions + * + */ + +#undef WIN32_LEAN_AND_MEAN +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../eng/handle.h" + +//#define NDEBUG +#include + + +/* FIXME: DCs should probably be thread safe */ + +/* + * DC device-independent Get/SetXXX functions + * (RJJ) swiped from WINE + */ + +#define DC_GET_VAL( func_type, func_name, dc_field ) \ +func_type STDCALL func_name( HDC hdc ) \ +{ \ + func_type ft; \ + PDC dc = DC_HandleToPtr( hdc ); \ + if (!dc) \ + { \ + return 0; \ + } \ + ft = dc->dc_field; \ + DC_ReleasePtr( hdc ); \ + return ft; \ +} + +/* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is + * important that the function has the right signature, for the implementation + * we can do whatever we want. + */ +#define DC_GET_VAL_EX( func_name, ret_x, ret_y, type ) \ +BOOL STDCALL func_name( HDC hdc, LP##type pt ) \ +{ \ + PDC dc = DC_HandleToPtr( hdc ); \ + if (!dc) \ + { \ + return FALSE; \ + } \ + ((LPPOINT)pt)->x = dc->ret_x; \ + ((LPPOINT)pt)->y = dc->ret_y; \ + DC_ReleasePtr( hdc ); \ + return TRUE; \ +} + +#define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \ +INT STDCALL func_name( HDC hdc, INT mode ) \ +{ \ + INT prevMode; \ + PDC dc = DC_HandleToPtr( hdc ); \ + if(!dc) \ + { \ + return 0; \ + } \ + if ((mode < min_val) || (mode > max_val)) \ + { \ + return 0; \ + } \ + prevMode = dc->dc_field; \ + dc->dc_field = mode; \ + DC_ReleasePtr( hdc ); \ + return prevMode; \ +} + + +VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap); + +// --------------------------------------------------------- File Statics + +static void W32kSetDCState16(HDC hDC, HDC hDCSave); + +// ----------------------------------------------------- Public Functions + +BOOL STDCALL W32kCancelDC(HDC hDC) +{ + UNIMPLEMENTED; +} + +HDC STDCALL W32kCreateCompatableDC(HDC hDC) +{ + PDC NewDC, OrigDC = NULL; + HBITMAP hBitmap; + SIZEL onebyone; + HDC hNewDC; + + OrigDC = DC_HandleToPtr(hDC); + if (OrigDC == NULL) + { + hNewDC = DC_AllocDC(L"DISPLAY"); + if( hNewDC ) + NewDC = DC_HandleToPtr( hNewDC ); + } + else { + /* Allocate a new DC based on the original DC's device */ + hNewDC = DC_AllocDC(OrigDC->DriverName); + if( hNewDC ) + NewDC = DC_HandleToPtr( hNewDC ); + } + + if (NewDC == NULL) + { + return NULL; + } + + /* Copy information from original DC to new DC */ + NewDC->hSelf = NewDC; + + /* FIXME: Should this DC request its own PDEV? */ + if(OrigDC == NULL) { + } else { + NewDC->PDev = OrigDC->PDev; + NewDC->DMW = OrigDC->DMW; + memcpy(NewDC->FillPatternSurfaces, + OrigDC->FillPatternSurfaces, + sizeof OrigDC->FillPatternSurfaces); + NewDC->GDIInfo = OrigDC->GDIInfo; + NewDC->DevInfo = OrigDC->DevInfo; + } + + // Create a 1x1 monochrome bitmap surface + onebyone.cx = 1; + onebyone.cy = 1; + NewDC->Surface = EngCreateBitmap(onebyone, 1, BMF_1BPP, 0, NULL); + + /* DriverName is copied in the AllocDC routine */ + if(OrigDC == NULL) { + NewDC->DeviceDriver = DRIVER_FindMPDriver(NewDC->DriverName); + } else { + NewDC->DeviceDriver = OrigDC->DeviceDriver; + NewDC->wndOrgX = OrigDC->wndOrgX; + NewDC->wndOrgY = OrigDC->wndOrgY; + NewDC->wndExtX = OrigDC->wndExtX; + NewDC->wndExtY = OrigDC->wndExtY; + NewDC->vportOrgX = OrigDC->vportOrgX; + NewDC->vportOrgY = OrigDC->vportOrgY; + NewDC->vportExtX = OrigDC->vportExtX; + NewDC->vportExtY = OrigDC->vportExtY; + } + + DC_InitDC(hNewDC); + + /* Create default bitmap */ + if (!(hBitmap = W32kCreateBitmap( 1, 1, 1, 1, NULL ))) + { + DC_ReleasePtr( hNewDC ); + DC_FreeDC( hNewDC ); + return NULL; + } + NewDC->w.flags = DC_MEMORY; + NewDC->w.bitsPerPixel = 1; + NewDC->w.hBitmap = hBitmap; + NewDC->w.hFirstBitmap = hBitmap; + + if(OrigDC != NULL) + { + NewDC->w.hPalette = OrigDC->w.hPalette; + NewDC->w.textColor = OrigDC->w.textColor; + NewDC->w.textAlign = OrigDC->w.textAlign; + } + DC_ReleasePtr( hDC ); + DC_ReleasePtr( hNewDC ); + + return hNewDC; +} + +#include + +static GDIDEVICE PrimarySurface; +static BOOL PrimarySurfaceCreated = FALSE; + +BOOL STDCALL W32kCreatePrimarySurface(LPCWSTR Driver, + LPCWSTR Device) +{ + PGD_ENABLEDRIVER GDEnableDriver; + HANDLE DeviceDriver; + DRVENABLEDATA DED; + PSURFOBJ SurfObj; + + /* Open the miniport driver */ + if ((DeviceDriver = DRIVER_FindMPDriver(Driver)) == NULL) + { + DPRINT("FindMPDriver failed\n"); + return(FALSE); + } + + /* Get the DDI driver's entry point */ + /* FIXME: Retrieve DDI driver name from registry */ + if ((GDEnableDriver = DRIVER_FindDDIDriver(L"\\SystemRoot\\system32\\drivers\\vgaddi.dll")) == NULL) + { + DPRINT("FindDDIDriver failed\n"); + return(FALSE); + } + + /* Call DDI driver's EnableDriver function */ + RtlZeroMemory(&DED, sizeof(DED)); + + if (!GDEnableDriver(DDI_DRIVER_VERSION, sizeof(DED), &DED)) + { + DPRINT("DrvEnableDriver failed\n"); + return(FALSE); + } + DPRINT("Building DDI Functions\n"); + + /* Construct DDI driver function dispatch table */ + if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions)) + { + DPRINT("BuildDDIFunctions failed\n"); + return(FALSE); + } + + /* Allocate a phyical device handle from the driver */ + if (Device != NULL) + { + DPRINT("Device in u: %u\n", Device); +// wcsncpy(NewDC->DMW.dmDeviceName, Device, DMMAXDEVICENAME); FIXME: this crashes everything? + } + + DPRINT("Enabling PDev\n"); + + PrimarySurface.PDev = + PrimarySurface.DriverFunctions.EnablePDev(&PrimarySurface.DMW, + L"", + HS_DDI_MAX, + PrimarySurface.FillPatterns, + sizeof(PrimarySurface.GDIInfo), + (ULONG *) &PrimarySurface.GDIInfo, + sizeof(PrimarySurface.DevInfo), + &PrimarySurface.DevInfo, + NULL, + L"", + DeviceDriver); + if (PrimarySurface.PDev == NULL) + { + DPRINT("DrvEnablePDEV failed\n"); + return(FALSE); + } + + DPRINT("calling completePDev\n"); + + /* Complete initialization of the physical device */ + PrimarySurface.DriverFunctions.CompletePDev(PrimarySurface.PDev, + &PrimarySurface); + + DPRINT("calling DRIVER_ReferenceDriver\n"); + + DRIVER_ReferenceDriver (Driver); + + DPRINT("calling EnableSurface\n"); + + /* Enable the drawing surface */ + PrimarySurface.Handle = + PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.PDev); + + SurfObj = (PSURFOBJ)AccessUserObject(PrimarySurface.Handle); + SurfObj->dhpdev = PrimarySurface.PDev; +} + +HDC STDCALL W32kCreateDC(LPCWSTR Driver, + LPCWSTR Device, + LPCWSTR Output, + CONST PDEVMODEW InitData) +{ + HDC hNewDC; + PDC NewDC; + HDC hDC = NULL; + + /* Check for existing DC object */ + if ((hNewDC = DC_FindOpenDC(Driver)) != NULL) + { + hDC = hNewDC; + return W32kCreateCompatableDC(hDC); + } + + DPRINT("NAME: %S\n", Driver); // FIXME: Should not crash if NULL + + /* Allocate a DC object */ + if ((hNewDC = DC_AllocDC(Driver)) == NULL) + { + return NULL; + } + + NewDC = DC_HandleToPtr( hNewDC ); + ASSERT( NewDC ); + + if (!PrimarySurfaceCreated) + { + if (!W32kCreatePrimarySurface(Driver, Device)) + { + DC_ReleasePtr( hNewDC ); + DC_FreeDC(hNewDC); + return NULL; + } + } + PrimarySurfaceCreated = TRUE; + NewDC->DMW = PrimarySurface.DMW; + NewDC->DevInfo = PrimarySurface.DevInfo; + NewDC->GDIInfo = PrimarySurface.GDIInfo; + memcpy(NewDC->FillPatternSurfaces, PrimarySurface.FillPatterns, + sizeof(NewDC->FillPatternSurfaces)); + NewDC->PDev = PrimarySurface.PDev; + NewDC->Surface = PrimarySurface.Handle; + NewDC->DriverFunctions = PrimarySurface.DriverFunctions; + + NewDC->DMW.dmSize = sizeof(NewDC->DMW); + NewDC->DMW.dmFields = 0x000fc000; + + /* FIXME: get mode selection information from somewhere */ + + NewDC->DMW.dmLogPixels = 96; + NewDC->DMW.dmBitsPerPel = 4; + NewDC->DMW.dmPelsWidth = 640; + NewDC->DMW.dmPelsHeight = 480; + NewDC->DMW.dmDisplayFlags = 0; + NewDC->DMW.dmDisplayFrequency = 0; + + NewDC->w.bitsPerPixel = 4; // FIXME: set this here?? + + NewDC->w.hPalette = NewDC->DevInfo.hpalDefault; + + DPRINT("Bits per pel: %u\n", NewDC->w.bitsPerPixel); + + /* Initialize the DC state */ + DC_InitDC(hNewDC); + + NewDC->w.hVisRgn = W32kCreateRectRgn(0, 0, 640, 480); + W32kSetTextColor(hNewDC, RGB(0, 0, 0)); + W32kSetTextAlign(hNewDC, TA_TOP); + DC_ReleasePtr( hNewDC ); + + return hNewDC; +} + +HDC STDCALL W32kCreateIC(LPCWSTR Driver, + LPCWSTR Device, + LPCWSTR Output, + CONST PDEVMODEW DevMode) +{ + /* FIXME: this should probably do something else... */ + return W32kCreateDC(Driver, Device, Output, DevMode); +} + +BOOL STDCALL W32kDeleteDC(HDC DCHandle) +{ + PDC DCToDelete; + + DCToDelete = DC_HandleToPtr(DCHandle); + if (DCToDelete == NULL) + { + return FALSE; + } + DPRINT( "Deleting DC\n" ); + if ((!(DCToDelete->w.flags & DC_MEMORY))) // Don't reset the display if its a memory DC + { + if (!DRIVER_UnreferenceDriver (DCToDelete->DriverName)) + { + DPRINT( "No more references to driver, reseting display\n" ); + DCToDelete->DriverFunctions.DisableSurface(DCToDelete->PDev); + CHECKPOINT; + DCToDelete->DriverFunctions.AssertMode( DCToDelete->PDev, FALSE ); + CHECKPOINT; + DCToDelete->DriverFunctions.DisablePDev(DCToDelete->PDev); + PrimarySurfaceCreated = FALSE; + } + } + CHECKPOINT; + /* First delete all saved DCs */ + while (DCToDelete->saveLevel) + { + PDC savedDC; + HDC savedHDC; + + savedHDC = DC_GetNextDC (DCToDelete); + savedDC = DC_HandleToPtr (savedHDC); + if (savedDC == NULL) + { + break; + } + DC_SetNextDC (DCToDelete, DC_GetNextDC (savedDC)); + DCToDelete->saveLevel--; + DC_ReleasePtr( savedHDC ); + W32kDeleteDC (savedHDC); + } + + /* Free GDI resources allocated to this DC */ + if (!(DCToDelete->w.flags & DC_SAVED)) + { + /* + W32kSelectObject (DCHandle, STOCK_BLACK_PEN); + W32kSelectObject (DCHandle, STOCK_WHITE_BRUSH); + W32kSelectObject (DCHandle, STOCK_SYSTEM_FONT); + DC_LockDC (DCHandle); W32kSelectObject does not recognize stock objects yet */ + if (DCToDelete->w.flags & DC_MEMORY) + { + W32kDeleteObject (DCToDelete->w.hFirstBitmap); + } + } + if (DCToDelete->w.hClipRgn) + { + W32kDeleteObject (DCToDelete->w.hClipRgn); + } + if (DCToDelete->w.hVisRgn) + { + W32kDeleteObject (DCToDelete->w.hVisRgn); + } + if (DCToDelete->w.hGCClipRgn) + { + W32kDeleteObject (DCToDelete->w.hGCClipRgn); + } +#if 0 /* FIXME */ + PATH_DestroyGdiPath (&DCToDelete->w.path); +#endif + DC_ReleasePtr( DCToDelete ); + DC_FreeDC (DCToDelete); + + return TRUE; +} + +INT STDCALL W32kDrawEscape(HDC hDC, + INT nEscape, + INT cbInput, + LPCSTR lpszInData) +{ + UNIMPLEMENTED; +} + +INT STDCALL W32kEnumObjects(HDC hDC, + INT ObjectType, + GOBJENUMPROC ObjectFunc, + LPARAM lParam) +{ + UNIMPLEMENTED; +} + +DC_GET_VAL( COLORREF, W32kGetBkColor, w.backgroundColor ) +DC_GET_VAL( INT, W32kGetBkMode, w.backgroundMode ) +DC_GET_VAL_EX( W32kGetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT ) +DC_GET_VAL( HRGN, W32kGetClipRgn, w.hClipRgn ) + +HGDIOBJ STDCALL W32kGetCurrentObject(HDC hDC, + UINT ObjectType) +{ + UNIMPLEMENTED; +} + +DC_GET_VAL_EX( W32kGetCurrentPositionEx, w.CursPosX, w.CursPosY, POINT ) + +BOOL STDCALL W32kGetDCOrgEx(HDC hDC, + LPPOINT Point) +{ + PDC dc; + + if (!Point) + { + return FALSE; + } + dc = DC_HandleToPtr(hDC); + if (dc == NULL) + { + return FALSE; + } + + Point->x = Point->y = 0; + + Point->x += dc->w.DCOrgX; + Point->y += dc->w.DCOrgY; + DC_ReleasePtr( hDC ); + return TRUE; +} + +HDC STDCALL W32kGetDCState16(HDC hDC) +{ + PDC newdc, dc; + HDC hnewdc; + + dc = DC_HandleToPtr(hDC); + if (dc == NULL) + { + return 0; + } + + hnewdc = DC_AllocDC(NULL); + if (hnewdc == NULL) + { + DC_ReleasePtr( hDC ); + return 0; + } + newdc = DC_HandleToPtr( hnewdc ); + ASSERT( newdc ); + + newdc->w.flags = dc->w.flags | DC_SAVED; +#if 0 + newdc->w.devCaps = dc->w.devCaps; +#endif + newdc->w.hPen = dc->w.hPen; + newdc->w.hBrush = dc->w.hBrush; + newdc->w.hFont = dc->w.hFont; + newdc->w.hBitmap = dc->w.hBitmap; + newdc->w.hFirstBitmap = dc->w.hFirstBitmap; +#if 0 + newdc->w.hDevice = dc->w.hDevice; + newdc->w.hPalette = dc->w.hPalette; +#endif + newdc->w.totalExtent = dc->w.totalExtent; + newdc->w.bitsPerPixel = dc->w.bitsPerPixel; + newdc->w.ROPmode = dc->w.ROPmode; + newdc->w.polyFillMode = dc->w.polyFillMode; + newdc->w.stretchBltMode = dc->w.stretchBltMode; + newdc->w.relAbsMode = dc->w.relAbsMode; + newdc->w.backgroundMode = dc->w.backgroundMode; + newdc->w.backgroundColor = dc->w.backgroundColor; + newdc->w.textColor = dc->w.textColor; + newdc->w.brushOrgX = dc->w.brushOrgX; + newdc->w.brushOrgY = dc->w.brushOrgY; + newdc->w.textAlign = dc->w.textAlign; + newdc->w.charExtra = dc->w.charExtra; + newdc->w.breakTotalExtra = dc->w.breakTotalExtra; + newdc->w.breakCount = dc->w.breakCount; + newdc->w.breakExtra = dc->w.breakExtra; + newdc->w.breakRem = dc->w.breakRem; + newdc->w.MapMode = dc->w.MapMode; + newdc->w.GraphicsMode = dc->w.GraphicsMode; +#if 0 + /* Apparently, the DC origin is not changed by [GS]etDCState */ + newdc->w.DCOrgX = dc->w.DCOrgX; + newdc->w.DCOrgY = dc->w.DCOrgY; +#endif + newdc->w.CursPosX = dc->w.CursPosX; + newdc->w.CursPosY = dc->w.CursPosY; + newdc->w.ArcDirection = dc->w.ArcDirection; +#if 0 + newdc->w.xformWorld2Wnd = dc->w.xformWorld2Wnd; + newdc->w.xformWorld2Vport = dc->w.xformWorld2Vport; + newdc->w.xformVport2World = dc->w.xformVport2World; + newdc->w.vport2WorldValid = dc->w.vport2WorldValid; +#endif + newdc->wndOrgX = dc->wndOrgX; + newdc->wndOrgY = dc->wndOrgY; + newdc->wndExtX = dc->wndExtX; + newdc->wndExtY = dc->wndExtY; + newdc->vportOrgX = dc->vportOrgX; + newdc->vportOrgY = dc->vportOrgY; + newdc->vportExtX = dc->vportExtX; + newdc->vportExtY = dc->vportExtY; + + newdc->hSelf = hnewdc; + newdc->saveLevel = 0; + +#if 0 + PATH_InitGdiPath( &newdc->w.path ); +#endif + + /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */ + +#if 0 + newdc->w.hGCClipRgn = newdc->w.hVisRgn = 0; +#endif + if (dc->w.hClipRgn) + { + newdc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 ); + W32kCombineRgn( newdc->w.hClipRgn, dc->w.hClipRgn, 0, RGN_COPY ); + } + else + { + newdc->w.hClipRgn = 0; + } + DC_ReleasePtr( hnewdc ); + return hnewdc; +} + +INT STDCALL W32kGetDeviceCaps(HDC hDC, + INT Index) +{ + PDC dc; + INT ret; + POINT pt; + + dc = DC_HandleToPtr(hDC); + if (dc == NULL) + { + return 0; + } + + /* Device capabilities for the printer */ + switch (Index) + { + case PHYSICALWIDTH: + if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0) + { + return pt.x; + } + break; + + case PHYSICALHEIGHT: + if(W32kEscape(hDC, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0) + { + return pt.y; + } + break; + + case PHYSICALOFFSETX: + if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0) + { + return pt.x; + } + break; + + case PHYSICALOFFSETY: + if(W32kEscape(hDC, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0) + { + return pt.y; + } + break; + + case SCALINGFACTORX: + if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0) + { + return pt.x; + } + break; + + case SCALINGFACTORY: + if(W32kEscape(hDC, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0) + { + return pt.y; + } + break; + } + + if ((Index < 0) || (Index > sizeof(DEVICECAPS) - sizeof(WORD))) + { + return 0; + } + + DPRINT("(%04x,%d): returning %d\n", + hDC, Index, *(WORD *)(((char *)dc->w.devCaps) + Index)); + ret = *(WORD *)(((char *)dc->w.devCaps) + Index); + + DC_ReleasePtr( hDC ); + return ret; +} + +DC_GET_VAL( INT, W32kGetMapMode, w.MapMode ) +DC_GET_VAL( INT, W32kGetPolyFillMode, w.polyFillMode ) + +INT STDCALL W32kGetObjectA(HANDLE handle, INT count, LPVOID buffer) +{ + PGDIOBJ gdiObject; + INT result = 0; + WORD magic; + + if (!count) + return 0; + gdiObject = GDIOBJ_LockObj (handle, GO_MAGIC_DONTCARE); + if (gdiObject == 0) + return 0; + + magic = GDIOBJ_GetHandleMagic (handle); + switch(magic) + { +/* case GO_PEN_MAGIC: + result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer); + break; + case GO_BRUSH_MAGIC: + result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer); + break; */ + case GO_BITMAP_MAGIC: + result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer); + break; +/* case GO_FONT_MAGIC: + result = FONT_GetObjectA((FONTOBJ *)gdiObject, count, buffer); + + // FIXME: Fix the LOGFONT structure for the stock fonts + + if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) ) + FixStockFontSizeA(handle, count, buffer); + break; + case GO_PALETTE_MAGIC: + result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer); + break; */ + + case GO_REGION_MAGIC: + case GO_DC_MAGIC: + case GO_DISABLED_DC_MAGIC: + case GO_META_DC_MAGIC: + case GO_METAFILE_MAGIC: + case GO_METAFILE_DC_MAGIC: + case GO_ENHMETAFILE_MAGIC: + case GO_ENHMETAFILE_DC_MAGIC: + // FIXME("Magic %04x not implemented\n", magic); + break; + + default: + DbgPrint("Invalid GDI Magic %04x\n", magic); + break; + } + GDIOBJ_UnlockObj (handle, GO_MAGIC_DONTCARE); + return result; +} + +INT STDCALL W32kGetObjectW(HANDLE handle, INT count, LPVOID buffer) +{ + PGDIOBJHDR gdiObject; + INT result = 0; + WORD magic; + + if (!count) + return 0; + gdiObject = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE); + if (gdiObject == 0) + return 0; + + magic = GDIOBJ_GetHandleMagic (handle); + switch(magic) + { +/* case GO_PEN_MAGIC: + result = PEN_GetObject((PENOBJ *)gdiObject, count, buffer); + break; + case GO_BRUSH_MAGIC: + result = BRUSH_GetObject((BRUSHOBJ *)gdiObject, count, buffer); + break; */ + case GO_BITMAP_MAGIC: + result = BITMAP_GetObject((BITMAPOBJ *)gdiObject, count, buffer); + break; +/* case GO_FONT_MAGIC: + result = FONT_GetObjectW((FONTOBJ *)gdiObject, count, buffer); + + // Fix the LOGFONT structure for the stock fonts + + if ( (handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE) ) + FixStockFontSizeW(handle, count, buffer); + break; + case GO_PALETTE_MAGIC: + result = PALETTE_GetObject((PALETTEOBJ *)gdiObject, count, buffer); + break; */ + default: + // FIXME("Magic %04x not implemented\n", gdiObject->magic); + break; + } + GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE); + return result; +} + +INT STDCALL W32kGetObject(HANDLE handle, INT count, LPVOID buffer) +{ + return W32kGetObjectW(handle, count, buffer); +} + +DWORD STDCALL W32kGetObjectType(HANDLE handle) +{ + GDIOBJHDR * ptr; + INT result = 0; + WORD magic; + + ptr = GDIOBJ_LockObj(handle, GO_MAGIC_DONTCARE); + if (ptr == 0) + return 0; + + magic = GDIOBJ_GetHandleMagic (handle); + switch(magic) + { + case GO_PEN_MAGIC: + result = OBJ_PEN; + break; + case GO_BRUSH_MAGIC: + result = OBJ_BRUSH; + break; + case GO_BITMAP_MAGIC: + result = OBJ_BITMAP; + break; + case GO_FONT_MAGIC: + result = OBJ_FONT; + break; + case GO_PALETTE_MAGIC: + result = OBJ_PAL; + break; + case GO_REGION_MAGIC: + result = OBJ_REGION; + break; + case GO_DC_MAGIC: + result = OBJ_DC; + break; + case GO_META_DC_MAGIC: + result = OBJ_METADC; + break; + case GO_METAFILE_MAGIC: + result = OBJ_METAFILE; + break; + case GO_METAFILE_DC_MAGIC: + result = OBJ_METADC; + break; + case GO_ENHMETAFILE_MAGIC: + result = OBJ_ENHMETAFILE; + break; + case GO_ENHMETAFILE_DC_MAGIC: + result = OBJ_ENHMETADC; + break; + default: + // FIXME("Magic %04x not implemented\n", magic); + break; + } + GDIOBJ_UnlockObj(handle, GO_MAGIC_DONTCARE); + return result; +} + +DC_GET_VAL( INT, W32kGetRelAbs, w.relAbsMode ) +DC_GET_VAL( INT, W32kGetROP2, w.ROPmode ) +DC_GET_VAL( INT, W32kGetStretchBltMode, w.stretchBltMode ) +DC_GET_VAL( UINT, W32kGetTextAlign, w.textAlign ) +DC_GET_VAL( COLORREF, W32kGetTextColor, w.textColor ) +DC_GET_VAL_EX( W32kGetViewportExtEx, vportExtX, vportExtY, SIZE ) +DC_GET_VAL_EX( W32kGetViewportOrgEx, vportOrgX, vportOrgY, POINT ) +DC_GET_VAL_EX( W32kGetWindowExtEx, wndExtX, wndExtY, SIZE ) +DC_GET_VAL_EX( W32kGetWindowOrgEx, wndOrgX, wndOrgY, POINT ) + +HDC STDCALL W32kResetDC(HDC hDC, CONST DEVMODEW *InitData) +{ + UNIMPLEMENTED; +} + +BOOL STDCALL W32kRestoreDC(HDC hDC, INT SaveLevel) +{ + PDC dc, dcs; + BOOL success; + + dc = DC_HandleToPtr(hDC); + if(!dc) + { + return FALSE; + } + + if (SaveLevel == -1) + { + SaveLevel = dc->saveLevel; + } + + if ((SaveLevel < 1) || (SaveLevel > dc->saveLevel)) + { + return FALSE; + } + + success = TRUE; + while (dc->saveLevel >= SaveLevel) + { + HDC hdcs = DC_GetNextDC (dc); + + dcs = DC_HandleToPtr (hdcs); + if (dcs == NULL) + { + return FALSE; + } + DC_SetNextDC (dcs, DC_GetNextDC (dcs)); + if (--dc->saveLevel < SaveLevel) + { + W32kSetDCState16 (hDC, hdcs); +#if 0 + if (!PATH_AssignGdiPath( &dc->w.path, &dcs->w.path )) + { + /* FIXME: This might not be quite right, since we're + * returning FALSE but still destroying the saved DC state */ + success = FALSE; + } +#endif + } + DC_ReleasePtr( hdcs ); + W32kDeleteDC (hdcs); + } + DC_ReleasePtr( hDC ); + return success; +} + +INT STDCALL W32kSaveDC(HDC hDC) +{ + HDC hdcs; + PDC dc, dcs; + INT ret; + + dc = DC_HandleToPtr (hDC); + if (dc == NULL) + { + return 0; + } + + if (!(hdcs = W32kGetDCState16 (hDC))) + { + return 0; + } + dcs = DC_HandleToPtr (hdcs); + +#if 0 + /* Copy path. The reason why path saving / restoring is in SaveDC/ + * RestoreDC and not in GetDCState/SetDCState is that the ...DCState + * functions are only in Win16 (which doesn't have paths) and that + * SetDCState doesn't allow us to signal an error (which can happen + * when copying paths). + */ + if (!PATH_AssignGdiPath (&dcs->w.path, &dc->w.path)) + { + W32kDeleteDC (hdcs); + return 0; + } +#endif + + DC_SetNextDC (dcs, DC_GetNextDC (dc)); + DC_SetNextDC (dc, hdcs); + ret = ++dc->saveLevel; + DC_ReleasePtr( hdcs ); + DC_ReleasePtr( hDC ); + + return ret; +} + +HGDIOBJ STDCALL W32kSelectObject(HDC hDC, HGDIOBJ hGDIObj) +{ + HGDIOBJ objOrg; + BITMAPOBJ *pb; + PSURFOBJ surfobj; + PSURFGDI surfgdi; + PDC dc; + PPENOBJ pen; + PBRUSHOBJ brush; + PXLATEOBJ XlateObj; + PPALGDI PalGDI; + WORD objectMagic; + ULONG NumColors; + + if(!hDC || !hGDIObj) return NULL; + + dc = DC_HandleToPtr(hDC); + objectMagic = GDIOBJ_GetHandleMagic (hGDIObj); +// GdiObjHdr = hGDIObj; + + // FIXME: Get object handle from GDIObj and use it instead of GDIObj below? + + switch(objectMagic) { + case GO_PEN_MAGIC: + objOrg = (HGDIOBJ)dc->w.hPen; + dc->w.hPen = hGDIObj; + + // Convert the color of the pen to the format of the DC + PalGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette); + if( PalGDI ){ + XlateObj = (PXLATEOBJ)EngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL); + pen = GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); + pen->logpen.lopnColor = XLATEOBJ_iXlate(XlateObj, pen->logpen.lopnColor); + GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); + } + break; + case GO_BRUSH_MAGIC: + objOrg = (HGDIOBJ)dc->w.hBrush; + dc->w.hBrush = (HBRUSH) hGDIObj; + + // Convert the color of the brush to the format of the DC + PalGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette); + if( PalGDI ){ + XlateObj = (PXLATEOBJ)EngCreateXlate(PalGDI->Mode, PAL_RGB, dc->w.hPalette, NULL); + brush = GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); + brush->iSolidColor = XLATEOBJ_iXlate(XlateObj, + brush->logbrush.lbColor); + GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC); + } + break; + case GO_FONT_MAGIC: + objOrg = (HGDIOBJ)dc->w.hFont; + dc->w.hFont = (HFONT) hGDIObj; + break; + case GO_BITMAP_MAGIC: + // must be memory dc to select bitmap + if (!(dc->w.flags & DC_MEMORY)) return NULL; + objOrg = (HGDIOBJ)dc->w.hBitmap; + + // setup mem dc for drawing into bitmap + pb = BITMAPOBJ_HandleToPtr (hGDIObj); + dc->w.hBitmap = CreateGDIHandle(sizeof( SURFGDI ), sizeof( SURFOBJ )); // Assign the DC's bitmap + + surfobj = (PSURFOBJ) AccessUserObject( dc->w.hBitmap ); + surfgdi = (PSURFGDI) AccessInternalObject( dc->w.hBitmap ); + BitmapToSurf(hDC, surfgdi, surfobj, pb); // Put the bitmap in a surface + + dc->Surface = dc->w.hBitmap; + + // if we're working with a DIB, get the palette [fixme: only create if the selected palette is null] + if(pb->dib) + { + dc->w.bitsPerPixel = pb->dib->dsBmih.biBitCount; + + if(pb->dib->dsBmih.biBitCount <= 8) + { + if(pb->dib->dsBmih.biBitCount == 1) { NumColors = 2; } else + if(pb->dib->dsBmih.biBitCount == 4) { NumColors = 16; } else + if(pb->dib->dsBmih.biBitCount == 8) { NumColors = 256; } + + dc->w.hPalette = EngCreatePalette(PAL_INDEXED, NumColors, pb->ColorMap, 0, 0, 0); + } else + if((pb->dib->dsBmih.biBitCount > 8) && (pb->dib->dsBmih.biBitCount < 24)) + { + dc->w.hPalette = EngCreatePalette(PAL_BITFIELDS, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0); + } else + if(pb->dib->dsBmih.biBitCount >= 24) + { + dc->w.hPalette = EngCreatePalette(PAL_RGB, pb->dib->dsBmih.biClrUsed, NULL, 0, 0, 0); + } + } else { + dc->w.bitsPerPixel = pb->bitmap.bmBitsPixel; + } + break; +#if UPDATEREGIONS + case GO_REGION_MAGIC: + /* objOrg = (HGDIOBJ)hDC->region; */ + objOrg = NULL; /* FIXME? hDC->region is destroyed below */ + SelectClipRgn(hDC, (HRGN)hGDIObj); + break; +#endif + default: + return NULL; + } + DC_ReleasePtr( hDC ); + return objOrg; +} + +DC_SET_MODE( W32kSetBkMode, w.backgroundMode, TRANSPARENT, OPAQUE ) +DC_SET_MODE( W32kSetPolyFillMode, w.polyFillMode, ALTERNATE, WINDING ) +// DC_SET_MODE( W32kSetRelAbs, w.relAbsMode, ABSOLUTE, RELATIVE ) +DC_SET_MODE( W32kSetROP2, w.ROPmode, R2_BLACK, R2_WHITE ) +DC_SET_MODE( W32kSetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE ) + +COLORREF STDCALL W32kSetBkColor(HDC hDC, COLORREF color) +{ + COLORREF oldColor; + PDC dc = DC_HandleToPtr(hDC); + + if (!dc) + { + return 0x80000000; + } + + oldColor = dc->w.backgroundColor; + dc->w.backgroundColor = color; + DC_ReleasePtr( hDC ); + return oldColor; +} + +static void W32kSetDCState16(HDC hDC, HDC hDCSave) +{ + PDC dc, dcs; + + dc = DC_HandleToPtr(hDC); + if (dc == NULL) + { + return; + } + + dcs = DC_HandleToPtr(hDCSave); + if (dcs == NULL) + { + DC_ReleasePtr( hDC ); + return; + } + if (!dcs->w.flags & DC_SAVED) + { + return; + } + + dc->w.flags = dcs->w.flags & ~DC_SAVED; + +#if 0 + dc->w.devCaps = dcs->w.devCaps; +#endif + + dc->w.hFirstBitmap = dcs->w.hFirstBitmap; + +#if 0 + dc->w.hDevice = dcs->w.hDevice; +#endif + + dc->w.totalExtent = dcs->w.totalExtent; + dc->w.ROPmode = dcs->w.ROPmode; + dc->w.polyFillMode = dcs->w.polyFillMode; + dc->w.stretchBltMode = dcs->w.stretchBltMode; + dc->w.relAbsMode = dcs->w.relAbsMode; + dc->w.backgroundMode = dcs->w.backgroundMode; + dc->w.backgroundColor = dcs->w.backgroundColor; + dc->w.textColor = dcs->w.textColor; + dc->w.brushOrgX = dcs->w.brushOrgX; + dc->w.brushOrgY = dcs->w.brushOrgY; + dc->w.textAlign = dcs->w.textAlign; + dc->w.charExtra = dcs->w.charExtra; + dc->w.breakTotalExtra = dcs->w.breakTotalExtra; + dc->w.breakCount = dcs->w.breakCount; + dc->w.breakExtra = dcs->w.breakExtra; + dc->w.breakRem = dcs->w.breakRem; + dc->w.MapMode = dcs->w.MapMode; + dc->w.GraphicsMode = dcs->w.GraphicsMode; +#if 0 + /* Apparently, the DC origin is not changed by [GS]etDCState */ + dc->w.DCOrgX = dcs->w.DCOrgX; + dc->w.DCOrgY = dcs->w.DCOrgY; +#endif + dc->w.CursPosX = dcs->w.CursPosX; + dc->w.CursPosY = dcs->w.CursPosY; + dc->w.ArcDirection = dcs->w.ArcDirection; + +#if 0 + dc->w.xformWorld2Wnd = dcs->w.xformWorld2Wnd; + dc->w.xformWorld2Vport = dcs->w.xformWorld2Vport; + dc->w.xformVport2World = dcs->w.xformVport2World; + dc->w.vport2WorldValid = dcs->w.vport2WorldValid; +#endif + + dc->wndOrgX = dcs->wndOrgX; + dc->wndOrgY = dcs->wndOrgY; + dc->wndExtX = dcs->wndExtX; + dc->wndExtY = dcs->wndExtY; + dc->vportOrgX = dcs->vportOrgX; + dc->vportOrgY = dcs->vportOrgY; + dc->vportExtX = dcs->vportExtX; + dc->vportExtY = dcs->vportExtY; + + if (!(dc->w.flags & DC_MEMORY)) + { + dc->w.bitsPerPixel = dcs->w.bitsPerPixel; + } + +#if 0 + if (dcs->w.hClipRgn) + { + if (!dc->w.hClipRgn) + { + dc->w.hClipRgn = W32kCreateRectRgn( 0, 0, 0, 0 ); + } + W32kCombineRgn( dc->w.hClipRgn, dcs->w.hClipRgn, 0, RGN_COPY ); + } + else + { + if (dc->w.hClipRgn) + { + W32kDeleteObject( dc->w.hClipRgn ); + } + + dc->w.hClipRgn = 0; + } + CLIPPING_UpdateGCRegion( dc ); +#endif + + W32kSelectObject( hDC, dcs->w.hBitmap ); + W32kSelectObject( hDC, dcs->w.hBrush ); + W32kSelectObject( hDC, dcs->w.hFont ); + W32kSelectObject( hDC, dcs->w.hPen ); + W32kSetBkColor( hDC, dcs->w.backgroundColor); + W32kSetTextColor( hDC, dcs->w.textColor); + +#if 0 + GDISelectPalette16( hDC, dcs->w.hPalette, FALSE ); +#endif + + DC_ReleasePtr( hDCSave ); + DC_ReleasePtr( hDC ); +} + +// ---------------------------------------------------- Private Interface + +HDC DC_AllocDC(LPCWSTR Driver) +{ + PDC NewDC; + HDC hDC; + + hDC = (HDC) GDIOBJ_AllocObj(sizeof(DC), GO_DC_MAGIC); + if (hDC == NULL) + { + return NULL; + } + + NewDC = (PDC) GDIOBJ_LockObj( hDC, GO_DC_MAGIC ); + + if (Driver != NULL) + { + NewDC->DriverName = ExAllocatePool(PagedPool, (wcslen(Driver) + 1) * sizeof(WCHAR)); + wcscpy(NewDC->DriverName, Driver); + } + + NewDC->w.xformWorld2Wnd.eM11 = 1.0f; + NewDC->w.xformWorld2Wnd.eM12 = 0.0f; + NewDC->w.xformWorld2Wnd.eM21 = 0.0f; + NewDC->w.xformWorld2Wnd.eM22 = 1.0f; + NewDC->w.xformWorld2Wnd.eDx = 0.0f; + NewDC->w.xformWorld2Wnd.eDy = 0.0f; + NewDC->w.xformWorld2Vport = NewDC->w.xformWorld2Wnd; + NewDC->w.xformVport2World = NewDC->w.xformWorld2Wnd; + NewDC->w.vport2WorldValid = TRUE; + + NewDC->w.hFont = W32kGetStockObject(SYSTEM_FONT); + + GDIOBJ_UnlockObj( hDC, GO_DC_MAGIC ); + return hDC; +} + +HDC DC_FindOpenDC(LPCWSTR Driver) +{ + return NULL; +} + +void DC_InitDC(HDC DCHandle) +{ +// W32kRealizeDefaultPalette(DCHandle); + PDC DCToInit; + if( (DCToInit = DC_HandleToPtr( DCHandle ) ) ){ + W32kSetTextColor(DCHandle, DCToInit->w.textColor); + W32kSetBkColor(DCHandle, DCToInit->w.backgroundColor); + W32kSelectObject(DCHandle, DCToInit->w.hPen); + W32kSelectObject(DCHandle, W32kGetStockObject( GRAY_BRUSH )); //FIXME: default should be WHITE_BRUSH + W32kSelectObject(DCHandle, DCToInit->w.hFont); + } + else + DPRINT("DC_InitDC: can't get dc for handle %d\n", DCHandle ); +// CLIPPING_UpdateGCRegion(DCToInit); +} + +void DC_FreeDC(HDC DCToFree) +{ + if (!GDIOBJ_FreeObj(DCToFree, GO_DC_MAGIC, GDIOBJFLAG_DEFAULT)) + { + DPRINT("DC_FreeDC failed\n"); + } +} + +BOOL DC_InternalDeleteDC( PDC DCToDelete ) +{ + if( DCToDelete->DriverName ) + ExFreePool(DCToDelete->DriverName); + return TRUE; +} + +HDC DC_GetNextDC (PDC pDC) +{ + return pDC->hNext; +} + +void DC_SetNextDC (PDC pDC, HDC hNextDC) +{ + pDC->hNext = hNextDC; +} + +void +DC_UpdateXforms(PDC dc) +{ + XFORM xformWnd2Vport; + FLOAT scaleX, scaleY; + + /* Construct a transformation to do the window-to-viewport conversion */ + scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX; + scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY; + xformWnd2Vport.eM11 = scaleX; + xformWnd2Vport.eM12 = 0.0; + xformWnd2Vport.eM21 = 0.0; + xformWnd2Vport.eM22 = scaleY; + xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - scaleX * (FLOAT)dc->wndOrgX; + xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - scaleY * (FLOAT)dc->wndOrgY; + + /* Combine with the world transformation */ + W32kCombineTransform(&dc->w.xformWorld2Vport, &dc->w.xformWorld2Wnd, &xformWnd2Vport); + + /* Create inverse of world-to-viewport transformation */ + dc->w.vport2WorldValid = DC_InvertXform(&dc->w.xformWorld2Vport, &dc->w.xformVport2World); +} + +BOOL +DC_InvertXform(const XFORM *xformSrc, + XFORM *xformDest) +{ + FLOAT determinant; + + determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21; + if (determinant > -1e-12 && determinant < 1e-12) + { + return FALSE; + } + + xformDest->eM11 = xformSrc->eM22 / determinant; + xformDest->eM12 = -xformSrc->eM12 / determinant; + xformDest->eM21 = -xformSrc->eM21 / determinant; + xformDest->eM22 = xformSrc->eM11 / determinant; + xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21; + xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22; + + return TRUE; +} diff --git a/subsys/win32k/objects/dib.c b/subsys/win32k/objects/dib.c new file mode 100644 index 0000000..2e2e86e --- /dev/null +++ b/subsys/win32k/objects/dib.c @@ -0,0 +1,774 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include "../eng/handle.h" +#include + +VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap); + +UINT STDCALL W32kSetDIBColorTable(HDC hDC, + UINT StartIndex, + UINT Entries, + CONST RGBQUAD *Colors) +{ + PDC dc; + PALETTEENTRY * palEntry; + PPALOBJ palette; + RGBQUAD *end; + + if (!(dc = (PDC)AccessUserObject(hDC))) return 0; + + if (!(palette = (PPALOBJ)AccessUserObject(dc->DevInfo.hpalDefault))) + { +// GDI_ReleaseObj( hdc ); + return 0; + } + + // Transfer color info + + if (dc->w.bitsPerPixel <= 8) { + palEntry = palette->logpalette->palPalEntry + StartIndex; + if (StartIndex + Entries > (1 << dc->w.bitsPerPixel)) + Entries = (1 << dc->w.bitsPerPixel) - StartIndex; + + if (StartIndex + Entries > palette->logpalette->palNumEntries) + Entries = palette->logpalette->palNumEntries - StartIndex; + + for (end = Colors + Entries; Colors < end; palEntry++, Colors++) + { + palEntry->peRed = Colors->rgbRed; + palEntry->peGreen = Colors->rgbGreen; + palEntry->peBlue = Colors->rgbBlue; + } + } else { + Entries = 0; + } + +// GDI_ReleaseObj(dc->DevInfo.hpalDefault); +// GDI_ReleaseObj(hdc); + + return Entries; +} + +// Converts a DIB to a device-dependent bitmap +INT STDCALL W32kSetDIBits(HDC hDC, + HBITMAP hBitmap, + UINT StartScan, + UINT ScanLines, + CONST VOID *Bits, + CONST BITMAPINFO *bmi, + UINT ColorUse) +{ + DC *dc; + BITMAPOBJ *bitmap; + HBITMAP SourceBitmap, DestBitmap; + INT result = 0; + BOOL copyBitsResult; + PSURFOBJ DestSurf, SourceSurf; + PSURFGDI DestGDI; + SIZEL SourceSize; + POINTL ZeroPoint; + RECTL DestRect; + PXLATEOBJ XlateObj; + PPALGDI hDCPalette; + RGBQUAD *lpRGB; + HPALETTE DDB_Palette, DIB_Palette; + ULONG DDB_Palette_Type, DIB_Palette_Type; + PBYTE vBits = Bits; + INT scanDirection = 1, DIBWidth; + + // Check parameters + if (!(dc = DC_HandleToPtr(hDC))) + return 0; + + if (!(bitmap = (BITMAPOBJ *)GDIOBJ_LockObj(hBitmap, GO_BITMAP_MAGIC))) + { + DC_ReleasePtr(hDC); + return 0; + } + + // Get RGB values + if (ColorUse == DIB_PAL_COLORS) + lpRGB = DIB_MapPaletteColors(hDC, bmi); + else + lpRGB = &bmi->bmiColors[0]; + + // Create a temporary surface for the destination bitmap + DestBitmap = (HBITMAP)CreateGDIHandle(sizeof(SURFGDI), sizeof(SURFOBJ)); + + DestSurf = (PSURFOBJ) AccessUserObject( DestBitmap ); + DestGDI = (PSURFGDI) AccessInternalObject( DestBitmap ); + + BitmapToSurf(hDC, DestGDI, DestSurf, bitmap); + + // Create source surface + SourceSize.cx = bmi->bmiHeader.biWidth; + SourceSize.cy = abs(bmi->bmiHeader.biHeight); + + // Determine width of DIB + DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount); + + // Determine DIB Vertical Orientation + if(bmi->bmiHeader.biHeight > 0) + { + scanDirection = -1; + vBits += DIBWidth * bmi->bmiHeader.biHeight - DIBWidth; + } + + SourceBitmap = EngCreateBitmap(SourceSize, + DIBWidth * scanDirection, + BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression), + 0, + vBits); + SourceSurf = (PSURFOBJ)AccessUserObject(SourceBitmap); + + // Destination palette obtained from the hDC + hDCPalette = (PPALGDI)AccessInternalObject(dc->DevInfo.hpalDefault); + DDB_Palette_Type = hDCPalette->Mode; + DDB_Palette = dc->DevInfo.hpalDefault; + + // Source palette obtained from the BITMAPINFO + DIB_Palette = BuildDIBPalette(bmi, &DIB_Palette_Type); + + // Determine XLATEOBJ for color translation + XlateObj = EngCreateXlate(DDB_Palette_Type, DIB_Palette_Type, DDB_Palette, DIB_Palette); + + // Zero point + ZeroPoint.x = 0; + ZeroPoint.y = 0; + + // Determine destination rectangle + DestRect.top = 0; + DestRect.left = 0; + DestRect.right = SourceSize.cx; + DestRect.bottom = SourceSize.cy; + + copyBitsResult = EngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint); + + // If it succeeded, return number of scanlines copies + if(copyBitsResult == TRUE) + { + result = SourceSize.cy - 1; + } + + // Clean up + EngDeleteSurface(SourceBitmap); + EngDeleteSurface(DestBitmap); + +// if (ColorUse == DIB_PAL_COLORS) +// WinFree((LPSTR)lpRGB); + +// GDI_ReleaseObj(hBitmap); unlock? + GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC); + DC_ReleasePtr(hDC); + + return result; +} + +INT STDCALL W32kSetDIBitsToDevice(HDC hDC, + INT XDest, + INT YDest, + DWORD Width, + DWORD Height, + INT XSrc, + INT YSrc, + UINT StartScan, + UINT ScanLines, + CONST VOID *Bits, + CONST BITMAPINFO *bmi, + UINT ColorUse) +{ + +} + +UINT STDCALL W32kGetDIBColorTable(HDC hDC, + UINT StartIndex, + UINT Entries, + RGBQUAD *Colors) +{ + UNIMPLEMENTED; +} + +// Converts a device-dependent bitmap to a DIB +INT STDCALL W32kGetDIBits(HDC hDC, + HBITMAP hBitmap, + UINT StartScan, + UINT ScanLines, + LPVOID Bits, + LPBITMAPINFO bi, + UINT Usage) +{ + UNIMPLEMENTED; +} + +INT STDCALL W32kStretchDIBits(HDC hDC, + INT XDest, + INT YDest, + INT DestWidth, + INT DestHeight, + INT XSrc, + INT YSrc, + INT SrcWidth, + INT SrcHeight, + CONST VOID *Bits, + CONST BITMAPINFO *BitsInfo, + UINT Usage, + DWORD ROP) +{ + UNIMPLEMENTED; +} + +LONG STDCALL W32kGetBitmapBits(HBITMAP hBitmap, + LONG Count, + LPVOID Bits) +{ + PBITMAPOBJ bmp; + LONG height, ret; + + bmp = BITMAPOBJ_HandleToPtr (hBitmap); + if (!bmp) + { + return 0; + } + + /* If the bits vector is null, the function should return the read size */ + if (Bits == NULL) + { + return bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight; + } + + if (Count < 0) + { + DPRINT ("(%ld): Negative number of bytes passed???\n", Count); + Count = -Count; + } + + /* Only get entire lines */ + height = Count / bmp->bitmap.bmWidthBytes; + if (height > bmp->bitmap.bmHeight) + { + height = bmp->bitmap.bmHeight; + } + Count = height * bmp->bitmap.bmWidthBytes; + if (Count == 0) + { + DPRINT("Less then one entire line requested\n"); + return 0; + } + + DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n", + hBitmap, Count, Bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight, + 1 << bmp->bitmap.bmBitsPixel, height ); +#if 0 + /* FIXME: Call DDI CopyBits here if available */ + if(bmp->DDBitmap) + { + DPRINT("Calling device specific BitmapBits\n"); + if(bmp->DDBitmap->funcs->pBitmapBits) + { + ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count, + DDB_GET); + } + else + { + ERR_(bitmap)("BitmapBits == NULL??\n"); + ret = 0; + } + } + else +#endif + { + if(!bmp->bitmap.bmBits) + { + DPRINT ("Bitmap is empty\n"); + ret = 0; + } + else + { + memcpy(Bits, bmp->bitmap.bmBits, Count); + ret = Count; + } + } + + return ret; +} + +// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits +// The DDB that is created will be whatever bit depth your reference DC is +HBITMAP STDCALL W32kCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header, + DWORD init, LPCVOID bits, const BITMAPINFO *data, + UINT coloruse) +{ + HBITMAP handle; + BOOL fColor; + DWORD width; + int height; + WORD bpp; + WORD compr; + + if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0; + if (height < 0) height = -height; + + // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2 + // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap. + + if (bpp != 1) fColor = TRUE; + else if ((coloruse != DIB_RGB_COLORS) || + (init != CBM_INIT) || !data) fColor = FALSE; + else + { + if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) + { + RGBQUAD *rgb = data->bmiColors; + DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue ); + + // Check if the first color of the colormap is black + if ((col == RGB(0, 0, 0))) + { + rgb++; + col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue ); + + // If the second color is white, create a monochrome bitmap + fColor = (col != RGB(0xff,0xff,0xff)); + } + else fColor = TRUE; + } + else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors; + DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue); + + if ((col == RGB(0,0,0))) + { + rgb++; + col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue ); + fColor = (col != RGB(0xff,0xff,0xff)); + } + else fColor = TRUE; + } + else + { + DbgPrint("(%ld): wrong size for data\n", data->bmiHeader.biSize ); + return 0; + } + } + + // Now create the bitmap + + if(fColor) + { + // If we are using indexed colors, then we need to create a bitmap that is compatible with the palette + if(coloruse == DIB_PAL_COLORS) + { + handle = W32kCreateCompatibleBitmap(hdc, width, height); + } + else if(coloruse == DIB_RGB_COLORS) { + handle = W32kCreateBitmap(width, height, 1, 24, NULL); + } + } + else handle = W32kCreateBitmap(width, height, 1, 1, NULL); + + if (!handle) return 0; + + if (init == CBM_INIT) + { + W32kSetDIBits(hdc, handle, 0, height, bits, data, coloruse); + } + + return handle; +} + +HBITMAP STDCALL W32kCreateDIBSection(HDC hDC, + CONST BITMAPINFO *bmi, + UINT Usage, + VOID *Bits, + HANDLE hSection, + DWORD dwOffset) +{ + HBITMAP hbitmap = 0; + DC *dc; + BOOL bDesktopDC = FALSE; + + // If the reference hdc is null, take the desktop dc + if (hDC == 0) + { + hDC = W32kCreateCompatableDC(0); + bDesktopDC = TRUE; + } + + if ((dc = DC_HandleToPtr(hDC))) + { + hbitmap = DIB_CreateDIBSection(dc, bmi, Usage, Bits, hSection, dwOffset, 0); + DC_ReleasePtr(hDC); + } + + if (bDesktopDC) + W32kDeleteDC(hDC); + + return hbitmap; +} + +HBITMAP DIB_CreateDIBSection( + PDC dc, BITMAPINFO *bmi, UINT usage, + LPVOID *bits, HANDLE section, + DWORD offset, DWORD ovr_pitch) +{ + HBITMAP res = 0; + BITMAPOBJ *bmp = NULL; + DIBSECTION *dib = NULL; + + // Fill BITMAP32 structure with DIB data + BITMAPINFOHEADER *bi = &bmi->bmiHeader; + INT effHeight, totalSize; + UINT Entries = 0; + BITMAP bm; + + DbgPrint("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n", + bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount, + bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB"); + + effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight; + bm.bmType = 0; + bm.bmWidth = bi->biWidth; + bm.bmHeight = effHeight; + bm.bmWidthBytes = ovr_pitch ? ovr_pitch : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount); + + bm.bmPlanes = bi->biPlanes; + bm.bmBitsPixel = bi->biBitCount; + bm.bmBits = NULL; + + // Get storage location for DIB bits. Only use biSizeImage if it's valid and + // we're dealing with a compressed bitmap. Otherwise, use width * height. + totalSize = bi->biSizeImage && bi->biCompression != BI_RGB + ? bi->biSizeImage : bm.bmWidthBytes * effHeight; + + if (section) +/* bm.bmBits = MapViewOfFile(section, FILE_MAP_ALL_ACCESS, + 0L, offset, totalSize); */ + DbgPrint("DIB_CreateDIBSection: Cannot yet handle section DIBs\n"); + else if (ovr_pitch && offset) + bm.bmBits = (LPVOID) offset; + else { + offset = 0; + bm.bmBits = EngAllocUserMem(totalSize, 0); + } + +/* bm.bmBits = ExAllocatePool(NonPagedPool, totalSize); */ + + if(usage == DIB_PAL_COLORS) memcpy(bmi->bmiColors, (UINT *)DIB_MapPaletteColors(dc, bmi), sizeof(UINT *)); + + // Allocate Memory for DIB and fill structure + if (bm.bmBits) + { + dib = ExAllocatePool(PagedPool, sizeof(DIBSECTION)); + RtlZeroMemory(dib, sizeof(DIBSECTION)); + } + + if (dib) + { + dib->dsBm = bm; + dib->dsBmih = *bi; + dib->dsBmih.biSizeImage = totalSize; + + /* Set dsBitfields values */ + if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8) + { + dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0; + } + else switch(bi->biBitCount) + { + case 16: + dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00; + dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0; + dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f; + break; + + case 24: + dib->dsBitfields[0] = 0xff; + dib->dsBitfields[1] = 0xff00; + dib->dsBitfields[2] = 0xff0000; + break; + + case 32: + dib->dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff; + dib->dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0xff00; + dib->dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0xff0000; + break; + } + dib->dshSection = section; + dib->dsOffset = offset; + } + + // Create Device Dependent Bitmap and add DIB pointer + if (dib) + { + res = W32kCreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage); + if (res) + { + bmp = BITMAPOBJ_HandleToPtr (res); + if (bmp) + { + bmp->dib = (DIBSECTION *) dib; + } + } + + /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical + device. Obviously, this is left out of the ReactOS implementation. Instead, we call + W32kSetDIBColorTable. */ + if(bi->biBitCount == 1) { Entries = 2; } else + if(bi->biBitCount == 4) { Entries = 16; } else + if(bi->biBitCount == 8) { Entries = 256; } + + bmp->ColorMap = ExAllocatePool(NonPagedPool, sizeof(RGBQUAD)*Entries); + RtlCopyMemory(bmp->ColorMap, bmi->bmiColors, sizeof(RGBQUAD)*Entries); + } + + // Clean up in case of errors + if (!res || !bmp || !dib || !bm.bmBits) + { + DbgPrint("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n", res, bmp, dib, bm.bmBits); +/* if (bm.bmBits) + { + if (section) + UnmapViewOfFile(bm.bmBits), bm.bmBits = NULL; + else if (!offset) + VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL; + } */ + + if (dib) { ExFreePool(dib); dib = NULL; } + if (bmp) { bmp = NULL; } + if (res) { GDIOBJ_FreeObj(res, GO_BITMAP_MAGIC, GDIOBJFLAG_DEFAULT); res = 0; } + } + + // Install fault handler, if possible +/* if (bm.bmBits) + { + if (VIRTUAL_SetFaultHandler(bm.bmBits, DIB_FaultHandler, (LPVOID)res)) + { + if (section || offset) + { + DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); + if (dib) dib->status = DIB_AppMod; + } + else + { + DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); + if (dib) dib->status = DIB_InSync; + } + } + } */ + + if( bmp ) + BITMAPOBJ_ReleasePtr(res); + + // Return BITMAP handle and storage location + if (bm.bmBits && bits) *bits = bm.bmBits; + + return res; +} + +/*********************************************************************** + * DIB_GetDIBWidthBytes + * + * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. + * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm + * 11/16/1999 (RJJ) lifted from wine + */ +int DIB_GetDIBWidthBytes(int width, int depth) +{ + int words; + + switch(depth) + { + case 1: words = (width + 31) / 32; break; + case 4: words = (width + 7) / 8; break; + case 8: words = (width + 3) / 4; break; + case 15: + case 16: words = (width + 1) / 2; break; + case 24: words = (width * 3 + 3)/4; break; + + default: + DPRINT("(%d): Unsupported depth\n", depth ); + /* fall through */ + case 32: + words = width; + } + return 4 * words; +} + +/*********************************************************************** + * DIB_GetDIBImageBytes + * + * Return the number of bytes used to hold the image in a DIB bitmap. + * 11/16/1999 (RJJ) lifted from wine + */ + +int DIB_GetDIBImageBytes (int width, int height, int depth) +{ + return DIB_GetDIBWidthBytes( width, depth ) * (height < 0 ? -height : height); +} + +/*********************************************************************** + * DIB_BitmapInfoSize + * + * Return the size of the bitmap info structure including color table. + * 11/16/1999 (RJJ) lifted from wine + */ + +int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse) +{ + int colors; + + if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info; + colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0; + return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD)); + } + else /* assume BITMAPINFOHEADER */ + { + colors = info->bmiHeader.biClrUsed; + if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount; + return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD)); + } +} + +int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width, + int *height, WORD *bpp, WORD *compr ) +{ + if (header->biSize == sizeof(BITMAPINFOHEADER)) + { + *width = header->biWidth; + *height = header->biHeight; + *bpp = header->biBitCount; + *compr = header->biCompression; + return 1; + } + if (header->biSize == sizeof(BITMAPCOREHEADER)) + { + BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header; + *width = core->bcWidth; + *height = core->bcHeight; + *bpp = core->bcBitCount; + *compr = 0; + return 0; + } + DbgPrint("(%ld): wrong size for header\n", header->biSize ); + return -1; +} + +// Converts a Device Independent Bitmap (DIB) to a Device Dependant Bitmap (DDB) +// The specified Device Context (DC) defines what the DIB should be converted to +PBITMAPOBJ DIBtoDDB(HGLOBAL hPackedDIB, HDC hdc) // FIXME: This should be removed. All references to this function should + // change to W32kSetDIBits +{ + HBITMAP hBmp = 0; + PBITMAPOBJ pBmp = NULL; + DIBSECTION *dib; + LPBYTE pbits = NULL; + + // Get a pointer to the packed DIB's data + // pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB); + dib = hPackedDIB; + + pbits = (dib + DIB_BitmapInfoSize(&dib->dsBmih, DIB_RGB_COLORS)); + + // Create a DDB from the DIB + hBmp = W32kCreateDIBitmap(hdc, &dib->dsBmih, CBM_INIT, (LPVOID)pbits, &dib->dsBmih, DIB_RGB_COLORS); + + // GlobalUnlock(hPackedDIB); + + // Retrieve the internal Pixmap from the DDB + pBmp = (BITMAPOBJ *)GDIOBJ_LockObj(hBmp, GO_BITMAP_MAGIC); + + return pBmp; +} + +RGBQUAD *DIB_MapPaletteColors(PDC dc, LPBITMAPINFO lpbmi) +{ + RGBQUAD *lpRGB; + int nNumColors,i; + DWORD *lpIndex; + PPALOBJ palObj; + + palObj = AccessUserObject(dc->DevInfo.hpalDefault); + + if (palObj == NULL) { +// RELEASEDCINFO(hDC); + return NULL; + } + + nNumColors = 1 << lpbmi->bmiHeader.biBitCount; + if (lpbmi->bmiHeader.biClrUsed) + nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed); + + lpRGB = (RGBQUAD *)ExAllocatePool(NonPagedPool, sizeof(RGBQUAD) * nNumColors); + lpIndex = (DWORD *)&lpbmi->bmiColors[0]; + + for (i=0; ilogpalette->palPalEntry[*lpIndex].peRed; + lpRGB[i].rgbGreen = palObj->logpalette->palPalEntry[*lpIndex].peGreen; + lpRGB[i].rgbBlue = palObj->logpalette->palPalEntry[*lpIndex].peBlue; + lpIndex++; + } +// RELEASEDCINFO(hDC); +// RELEASEPALETTEINFO(hPalette); + return lpRGB; +} + +PALETTEENTRY *DIBColorTableToPaletteEntries(PALETTEENTRY *palEntries, const RGBQUAD *DIBColorTable, ULONG ColorCount) +{ + ULONG i; + + for(i=0; ipeRed = DIBColorTable->rgbRed; + palEntries->peGreen = DIBColorTable->rgbGreen; + palEntries->peBlue = DIBColorTable->rgbBlue; + palEntries++; + DIBColorTable++; + } +} + +HPALETTE BuildDIBPalette(BITMAPINFO *bmi, PINT paletteType) +{ + BYTE bits; + ULONG ColorCount; + PALETTEENTRY *palEntries; + HPALETTE hPal; + + // Determine Bits Per Pixel + bits = bmi->bmiHeader.biBitCount; + + // Determine paletteType from Bits Per Pixel + if(bits <= 8) + { + *paletteType = PAL_INDEXED; + } else + if(bits < 24) + { + *paletteType = PAL_BITFIELDS; + } else { + *paletteType = PAL_RGB; // Would it be BGR, considering the BGR nature of the DIB color table? + } + + if (bmi->bmiHeader.biClrUsed == 0 && + bmi->bmiHeader.biBitCount <= 8) + { + ColorCount = 1 << bmi->bmiHeader.biBitCount; + } + else + { + ColorCount = bmi->bmiHeader.biClrUsed; + } + + palEntries = ExAllocatePool(NonPagedPool, sizeof(PALETTEENTRY)*ColorCount); + DIBColorTableToPaletteEntries(palEntries, bmi->bmiColors, ColorCount); + hPal = EngCreatePalette(*paletteType, ColorCount, palEntries, 0, 0, 0); + ExFreePool(palEntries); + + return hPal; +} diff --git a/subsys/win32k/objects/fillshap.c b/subsys/win32k/objects/fillshap.c new file mode 100644 index 0000000..0e06ee2 --- /dev/null +++ b/subsys/win32k/objects/fillshap.c @@ -0,0 +1,181 @@ + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +// #define NDEBUG +#include + +BOOL +STDCALL +W32kChord(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XRadial1, + int YRadial1, + int XRadial2, + int YRadial2) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kEllipse(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPie(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XRadial1, + int YRadial1, + int XRadial2, + int YRadial2) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPolygon(HDC hDC, + CONST PPOINT Points, + int Count) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPolyPolygon(HDC hDC, + CONST LPPOINT Points, + CONST LPINT PolyCounts, + int Count) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kRectangle(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect) +{ + DC *dc = DC_HandleToPtr(hDC); + SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface); + PBRUSHOBJ BrushObj; + BOOL ret; + PRECTL RectBounds; + PENOBJ * pen; + RECTL DestRect; + + if(!dc) + return FALSE; + + RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); + //ei not yet implemented ASSERT(RectBounds); + + if(PATH_IsPathOpen(dc->w.path)) { + ret = PATH_Rectangle(hDC, LeftRect, TopRect, RightRect, BottomRect); + } else { + // Draw the rectangle with the current pen + pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); + ASSERT(pen); + BrushObj = (PBRUSHOBJ)PenToBrushObj(dc, pen); + GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC ); + + LeftRect += dc->w.DCOrgX; + RightRect += dc->w.DCOrgX; + TopRect += dc->w.DCOrgY; + BottomRect += dc->w.DCOrgY; + + ret = EngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + LeftRect, TopRect, RightRect, TopRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX + + ret = EngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + RightRect, TopRect, RightRect, BottomRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX + + ret = EngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + LeftRect, BottomRect, RightRect, BottomRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX + + ret = EngLineTo(SurfObj, + NULL, // ClipObj, + BrushObj, + LeftRect, TopRect, LeftRect, BottomRect, + RectBounds, // Bounding rectangle + dc->w.ROPmode); // MIX */ + + // FIXME: BrushObj is obtained above; decide which one is correct + BrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); + + if (BrushObj) + { + if (BrushObj->logbrush.lbStyle != BS_NULL) + { + DestRect.left = LeftRect + 1; + DestRect.right = RightRect - 1; + DestRect.top = TopRect + 1; + DestRect.bottom = BottomRect - 1; + ret = EngBitBlt(SurfObj, + NULL, + NULL, + NULL, + NULL, + &DestRect, + NULL, + NULL, + BrushObj, + NULL, + PATCOPY); + } + } + GDIOBJ_UnlockObj( dc->w.hBrush, GO_PEN_MAGIC ); + } + +// FIXME: Move current position in DC? + GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); + DC_ReleasePtr( hDC ); + return TRUE; +} + +BOOL +STDCALL +W32kRoundRect(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int Width, + int Height) +{ + UNIMPLEMENTED; +} diff --git a/subsys/win32k/objects/font.c b/subsys/win32k/objects/font.c new file mode 100644 index 0000000..ee68335 --- /dev/null +++ b/subsys/win32k/objects/font.c @@ -0,0 +1,2 @@ +/* EMPTY FOR NOW */ +/* Hope I didn't delete existing defs!! Check CVS version of this file.. */ \ No newline at end of file diff --git a/subsys/win32k/objects/gdiobj.c b/subsys/win32k/objects/gdiobj.c new file mode 100644 index 0000000..0d305ce --- /dev/null +++ b/subsys/win32k/objects/gdiobj.c @@ -0,0 +1,524 @@ +/* + * GDIOBJ.C - GDI object manipulation routines + * + * $Id$ + * + */ + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define NDEBUG +#include + +// GDI stock objects + +static LOGBRUSH WhiteBrush = +{ BS_SOLID, RGB(255,255,255), 0 }; + +static LOGBRUSH LtGrayBrush = +/* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */ +{ BS_SOLID, RGB(192,192,192), 0 }; + +static LOGBRUSH GrayBrush = +/* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */ +{ BS_SOLID, RGB(128,128,128), 0 }; + +static LOGBRUSH DkGrayBrush = +/* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */ +/* NB_HATCH_STYLES is an index into HatchBrushes */ +{ BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES }; + +static LOGBRUSH BlackBrush = +{ BS_SOLID, RGB(0,0,0), 0 }; + +static LOGBRUSH NullBrush = +{ BS_NULL, 0, 0 }; + +static LOGPEN WhitePen = +{ PS_SOLID, { 0, 0 }, RGB(255,255,255) }; + +static LOGPEN BlackPen = +{ PS_SOLID, { 0, 0 }, RGB(0,0,0) }; + +static LOGPEN NullPen = +{ PS_NULL, { 0, 0 }, 0 }; + +static LOGFONT OEMFixedFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET, + 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" }; + +/* Filler to make the location counter dword aligned again. This is necessary + since (a) LOGFONT is packed, (b) gcc places initialised variables in the code + segment, and (c) Solaris assembler is stupid. */ +static UINT align_OEMFixedFont = 1; + +static LOGFONT AnsiFixedFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" }; + +static UINT align_AnsiFixedFont = 1; + +static LOGFONT AnsiVarFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" }; + +static UINT align_AnsiVarFont = 1; + +static LOGFONT SystemFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"System" }; + +static UINT align_SystemFont = 1; + +static LOGFONT DeviceDefaultFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" }; + +static UINT align_DeviceDefaultFont = 1; + +static LOGFONT SystemFixedFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" }; + +static UINT align_SystemFixedFont = 1; + +/* FIXME: Is this correct? */ +static LOGFONT DefaultGuiFont = +{ 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, + 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" }; + +static UINT align_DefaultGuiFont = 1; + +static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS]; // we dont assign these statically as WINE does because we might redesign + // the way handles work, so it's more dynamic now + + +HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */ + +static PGDI_HANDLE_TABLE HandleTable = 0; +static FAST_MUTEX HandleTableMutex; +static FAST_MUTEX RefCountHandling; + +#define GDI_HANDLE_NUMBER 0x4000 + +static PGDI_HANDLE_TABLE +GDIOBJ_iAllocHandleTable (WORD Size) +{ + PGDI_HANDLE_TABLE handleTable; + + ExAcquireFastMutexUnsafe (&HandleTableMutex); + handleTable = ExAllocatePool(PagedPool, + sizeof (GDI_HANDLE_TABLE) + + sizeof (GDI_HANDLE_ENTRY) * Size); + ASSERT( handleTable ); + memset (handleTable, + 0, + sizeof (GDI_HANDLE_TABLE) + sizeof (GDI_HANDLE_ENTRY) * Size); + handleTable->wTableSize = Size; + ExReleaseFastMutexUnsafe (&HandleTableMutex); + + return handleTable; +} + +static PGDI_HANDLE_ENTRY +GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex) +{ + //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) ); + //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)); + //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic); + return ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex); +} + +static WORD +GDIOBJ_iGetNextOpenHandleIndex (void) +{ + WORD tableIndex; + + ExAcquireFastMutexUnsafe (&HandleTableMutex); + for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++) + { + if (HandleTable->Handles [tableIndex].wMagic == 0) + { + HandleTable->Handles [tableIndex].wMagic = GO_MAGIC_DONTCARE; + break; + } + } + ExReleaseFastMutexUnsafe (&HandleTableMutex); + + return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0; +} + +/*-----------------7/12/2002 11:38AM---------------- + * Allocate memory for GDI object and return handle to it + * Use GDIOBJ_Lock to obtain pointer to the new object. + * --------------------------------------------------*/ +HGDIOBJ GDIOBJ_AllocObj(WORD Size, WORD Magic) +{ + PGDIOBJHDR newObject; + PGDI_HANDLE_ENTRY handleEntry; + + DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size, Magic); + newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR)); + if (newObject == NULL) + { + DPRINT("GDIOBJ_AllocObj: failed\n"); + return NULL; + } + RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR)); + + newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex (); + newObject->dwCount = 0; + handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex); + handleEntry->wMagic = Magic; + handleEntry->hProcessId = PsGetCurrentProcessId (); + handleEntry->pObject = newObject; + DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex ); + return (HGDIOBJ) newObject->wTableIndex; +} + +BOOL GDIOBJ_FreeObj(HGDIOBJ hObj, WORD Magic, DWORD Flag) +{ + PGDIOBJHDR objectHeader; + PGDI_HANDLE_ENTRY handleEntry; + PGDIOBJ Obj; + BOOL bRet = TRUE; + + handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)hObj & 0xffff); + DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD)hObj & 0xffff, Magic, handleEntry ); + if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE ) + || ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag & GDIOBJFLAG_IGNOREPID))){ + DPRINT("Can't Delete hObj: %d, magic: %x, pid:%d\n currpid:%d, flag:%d, hmm:%d\n",(WORD)hObj & 0xffff, handleEntry->wMagic, handleEntry->hProcessId, PsGetCurrentProcessId(), (Flag&GDIOBJFLAG_IGNOREPID), ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag&GDIOBJFLAG_IGNOREPID)) ); + return FALSE; + } + + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + ASSERT(objectHeader); + DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount ); + if( !(Flag & GDIOBJFLAG_IGNORELOCK) ){ + // check that the reference count is zero. if not then set flag + // and delete object when releaseobj is called + ExAcquireFastMutex(&RefCountHandling); + if( ( objectHeader->dwCount & ~0x80000000 ) > 0 ){ + DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount); + objectHeader->dwCount |= 0x80000000; + ExReleaseFastMutex(&RefCountHandling); + return TRUE; + } + ExReleaseFastMutex(&RefCountHandling); + } + + //allow object to delete internal data + Obj = (PGDIOBJ)((PCHAR)handleEntry->pObject + sizeof(GDIOBJHDR)); + switch( handleEntry->wMagic ){ + case GO_REGION_MAGIC: + bRet = RGNDATA_InternalDelete( (PROSRGNDATA) Obj ); + break; + case GO_BITMAP_MAGIC: + bRet = Bitmap_InternalDelete( (PBITMAPOBJ) Obj ); + break; + case GO_DC_MAGIC: + bRet = DC_InternalDeleteDC( (PDC) Obj ); + break; + case GO_PEN_MAGIC: + case GO_PALETTE_MAGIC: + case GO_DISABLED_DC_MAGIC: + case GO_META_DC_MAGIC: + case GO_METAFILE_MAGIC: + case GO_METAFILE_DC_MAGIC: + case GO_ENHMETAFILE_MAGIC: + case GO_ENHMETAFILE_DC_MAGIC: + + case GO_BRUSH_MAGIC: + case GO_FONT_MAGIC: + break; + } + handleEntry->hProcessId = 0; + ExFreePool (handleEntry->pObject); + handleEntry->pObject = 0; + // (RJJ) set wMagic last to avoid race condition + handleEntry->wMagic = 0; + + + return TRUE; +} + +PGDIOBJ GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic ) +{ + PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff); + PGDIOBJHDR objectHeader; + + DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj, Magic, handleEntry, handleEntry->wMagic); + if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE ) + || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF && + handleEntry->hProcessId != PsGetCurrentProcessId ())){ + DPRINT("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",(WORD) hObj & 0xffff, handleEntry->wMagic, Magic); + return NULL; + } + + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + ASSERT(objectHeader); + + ExAcquireFastMutex(&RefCountHandling); + objectHeader->dwCount++; + ExReleaseFastMutex(&RefCountHandling); + + DPRINT("GDIOBJ_LockObj: PGDIOBJ %x\n", ((PCHAR)objectHeader + sizeof(GDIOBJHDR)) ); + return (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR)); +} + +BOOL GDIOBJ_UnlockObj( HGDIOBJ hObj, WORD Magic ) +{ + PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff); + PGDIOBJHDR objectHeader; + + DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj, Magic, handleEntry); + if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE ) + || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF && + handleEntry->hProcessId != PsGetCurrentProcessId ())){ + DPRINT( "GDIOBJ_UnLockObj: failed\n"); + return FALSE; + } + + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + ASSERT(objectHeader); + + ExAcquireFastMutex(&RefCountHandling); + if( ( objectHeader->dwCount & ~0x80000000 ) == 0 ){ + ExReleaseFastMutex(&RefCountHandling); + DPRINT( "GDIOBJ_UnLockObj: unlock object that is not locked\n" ); + return FALSE; + } + + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + ASSERT(objectHeader); + objectHeader->dwCount--; + + if( objectHeader->dwCount == 0x80000000 ){ + //delayed object release + objectHeader->dwCount = 0; + ExReleaseFastMutex(&RefCountHandling); + DPRINT("GDIOBJ_UnlockObj: delayed delete\n"); + return GDIOBJ_FreeObj( hObj, Magic, GDIOBJFLAG_DEFAULT ); + } + ExReleaseFastMutex(&RefCountHandling); + return TRUE; +} + +/* +PGDIOBJ GDIOBJ_AllocObject(WORD Size, WORD Magic) +{ + PGDIOBJHDR newObject; + PGDI_HANDLE_ENTRY handleEntry; + + newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR)); + if (newObject == NULL) + { + return NULL; + } + RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR)); + + newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex (); + handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex); + handleEntry->wMagic = Magic; + handleEntry->hProcessId = PsGetCurrentProcessId (); + handleEntry->pObject = newObject; + + return (PGDIOBJ)(((PCHAR) newObject) + sizeof (GDIOBJHDR)); +} + +BOOL GDIOBJ_FreeObject (PGDIOBJ Obj, WORD Magic) +{ + PGDIOBJHDR objectHeader; + PGDI_HANDLE_ENTRY handleEntry; + + objectHeader = (PGDIOBJHDR)(((PCHAR)Obj) - sizeof (GDIOBJHDR)); + handleEntry = GDIOBJ_iGetHandleEntryForIndex (objectHeader->wTableIndex); + if (handleEntry == 0 || handleEntry->wMagic != Magic) + return FALSE; + handleEntry->hProcessId = 0; + handleEntry->pObject = 0; + // (RJJ) set wMagic last to avoid race condition + handleEntry->wMagic = 0; + ExFreePool (objectHeader); + + return TRUE; +} + +HGDIOBJ GDIOBJ_PtrToHandle (PGDIOBJ Obj, WORD Magic) +{ + PGDIOBJHDR objectHeader; + PGDI_HANDLE_ENTRY handleEntry; + + if (Obj == NULL) + return NULL; + objectHeader = (PGDIOBJHDR) (((PCHAR)Obj) - sizeof (GDIOBJHDR)); + handleEntry = GDIOBJ_iGetHandleEntryForIndex (objectHeader->wTableIndex); + if (handleEntry == 0 || + handleEntry->wMagic != Magic || + handleEntry->hProcessId != PsGetCurrentProcessId () ) + return NULL; + + return (HGDIOBJ) objectHeader->wTableIndex; +} + +PGDIOBJ GDIOBJ_HandleToPtr (HGDIOBJ ObjectHandle, WORD Magic) +{ + PGDI_HANDLE_ENTRY handleEntry; + + if (ObjectHandle == NULL) + return NULL; + + handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff); + if (handleEntry == 0 || + (Magic != GO_MAGIC_DONTCARE && Magic != Magic) || + handleEntry->hProcessId != PsGetCurrentProcessId () ) + return NULL; + + return (PGDIOBJ) (((PCHAR)handleEntry->pObject) + sizeof (GDIOBJHDR)); +} +*/ + +VOID GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle) +{ + PGDI_HANDLE_ENTRY handleEntry; + + if (ObjectHandle == NULL) + return; + + handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff); + if (handleEntry == 0) + return; + + handleEntry->hProcessId = (HANDLE)0xFFFFFFFF; +} + +WORD GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle) +{ + PGDI_HANDLE_ENTRY handleEntry; + + if (ObjectHandle == NULL) + return 0; + + handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff); + if (handleEntry == 0 || + (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF && + handleEntry->hProcessId != PsGetCurrentProcessId ())) + return 0; + + return handleEntry->wMagic; +} + +VOID +InitGdiObjectHandleTable (void) +{ + DPRINT ("InitGdiObjectHandleTable\n"); + ExInitializeFastMutex (&HandleTableMutex); + ExInitializeFastMutex (&RefCountHandling); + //per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles + //gdi handle table can hold 0x4000 handles + HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER); + DPRINT("HandleTable: %x\n", HandleTable ); + + InitEngHandleTable(); +} + +VOID CreateStockObjects(void) +{ + // Create GDI Stock Objects from the logical structures we've defined + + StockObjects[WHITE_BRUSH] = W32kCreateBrushIndirect(&WhiteBrush); + GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_BRUSH]); + StockObjects[LTGRAY_BRUSH] = W32kCreateBrushIndirect(&LtGrayBrush); + GDIOBJ_MarkObjectGlobal(StockObjects[LTGRAY_BRUSH]); + StockObjects[GRAY_BRUSH] = W32kCreateBrushIndirect(&GrayBrush); + GDIOBJ_MarkObjectGlobal(StockObjects[GRAY_BRUSH]); + StockObjects[DKGRAY_BRUSH] = W32kCreateBrushIndirect(&DkGrayBrush); + GDIOBJ_MarkObjectGlobal(StockObjects[DKGRAY_BRUSH]); + StockObjects[BLACK_BRUSH] = W32kCreateBrushIndirect(&BlackBrush); + GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_BRUSH]); + StockObjects[NULL_BRUSH] = W32kCreateBrushIndirect(&NullBrush); + GDIOBJ_MarkObjectGlobal(StockObjects[NULL_BRUSH]); + + StockObjects[WHITE_PEN] = W32kCreatePenIndirect(&WhitePen); + GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_PEN]); + StockObjects[BLACK_PEN] = W32kCreatePenIndirect(&BlackPen); + GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_PEN]); + StockObjects[NULL_PEN] = W32kCreatePenIndirect(&NullPen); + GDIOBJ_MarkObjectGlobal(StockObjects[NULL_PEN]); + + StockObjects[OEM_FIXED_FONT] = W32kCreateFontIndirect(&OEMFixedFont); + GDIOBJ_MarkObjectGlobal(StockObjects[OEM_FIXED_FONT]); + StockObjects[ANSI_FIXED_FONT] = W32kCreateFontIndirect(&AnsiFixedFont); + GDIOBJ_MarkObjectGlobal(StockObjects[ANSI_FIXED_FONT]); + StockObjects[SYSTEM_FONT] = W32kCreateFontIndirect(&SystemFont); + GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FONT]); + StockObjects[DEVICE_DEFAULT_FONT] = + W32kCreateFontIndirect(&DeviceDefaultFont); + GDIOBJ_MarkObjectGlobal(StockObjects[DEVICE_DEFAULT_FONT]); + StockObjects[SYSTEM_FIXED_FONT] = W32kCreateFontIndirect(&SystemFixedFont); + GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FIXED_FONT]); + StockObjects[DEFAULT_GUI_FONT] = W32kCreateFontIndirect(&DefaultGuiFont); + GDIOBJ_MarkObjectGlobal(StockObjects[DEFAULT_GUI_FONT]); + + StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init(); +} + +HGDIOBJ STDCALL W32kGetStockObject(INT Object) +{ + HGDIOBJ ret; + +/* if ((Object < 0) || (Object >= NB_STOCK_OBJECTS)) return 0; + if (!StockObjects[Object]) return 0; + ret = FIRST_STOCK_HANDLE + Object; + + return ret; */ + + return StockObjects[Object]; // FIXME........ +} + +BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject) +{ + return GDIOBJ_FreeObj( hObject, GO_MAGIC_DONTCARE, GDIOBJFLAG_DEFAULT ); +} + +BOOL STDCALL W32kCleanupForProcess( INT Process ) +{ + DWORD i; + PGDI_HANDLE_ENTRY handleEntry; + PGDIOBJHDR objectHeader; + + for( i=1; i < GDI_HANDLE_NUMBER; i++ ){ + handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff); + if( handleEntry && handleEntry->wMagic != 0 && handleEntry->hProcessId == Process){ + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount); + GDIOBJ_FreeObj( (WORD) i & 0xffff, GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK ); + } + } + return TRUE; +} + +// dump all the objects for process. if process == 0 dump all the objects +VOID STDCALL W32kDumpGdiObjects( INT Process ) +{ + DWORD i; + PGDI_HANDLE_ENTRY handleEntry; + PGDIOBJHDR objectHeader; + + for( i=1; i < GDI_HANDLE_NUMBER; i++ ){ + handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff); + if( handleEntry && handleEntry->wMagic != 0 ){ + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount); + } + } + +} diff --git a/subsys/win32k/objects/icm.c b/subsys/win32k/objects/icm.c new file mode 100644 index 0000000..12720fe --- /dev/null +++ b/subsys/win32k/objects/icm.c @@ -0,0 +1,143 @@ + + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +// #define NDEBUG +#include + +BOOL +STDCALL +W32kCheckColorsInGamut(HDC hDC, + LPVOID RGBTriples, + LPVOID Buffer, + UINT Count) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kColorMatchToTarget(HDC hDC, + HDC hDCTarget, + DWORD Action) +{ + UNIMPLEMENTED; +} + +HCOLORSPACE +STDCALL +W32kCreateColorSpace(LPLOGCOLORSPACE LogColorSpace) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kDeleteColorSpace(HCOLORSPACE hColorSpace) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kEnumICMProfiles(HDC hDC, + ICMENUMPROC EnumICMProfilesFunc, + LPARAM lParam) +{ + UNIMPLEMENTED; +} + +HCOLORSPACE +STDCALL +W32kGetColorSpace(HDC hDC) +{ + /* FIXME: Need to to whatever GetColorSpace actually does */ + return 0; +} + +BOOL +STDCALL +W32kGetDeviceGammaRamp(HDC hDC, + LPVOID Ramp) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetICMProfile(HDC hDC, + LPDWORD NameSize, + LPWSTR Filename) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetLogColorSpace(HCOLORSPACE hColorSpace, + LPLOGCOLORSPACE Buffer, + DWORD Size) +{ + UNIMPLEMENTED; +} + +HCOLORSPACE +STDCALL +W32kSetColorSpace(HDC hDC, + HCOLORSPACE hColorSpace) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetDeviceGammaRamp(HDC hDC, + LPVOID Ramp) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kSetICMMode(HDC hDC, + INT EnableICM) +{ + /* FIXME: this should be coded someday */ + if (EnableICM == ICM_OFF) + { + return ICM_OFF; + } + if (EnableICM == ICM_ON) + { + return 0; + } + if (EnableICM == ICM_QUERY) + { + return ICM_OFF; + } + + return 0; +} + +BOOL +STDCALL +W32kSetICMProfile(HDC hDC, + LPWSTR Filename) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kUpdateICMRegKey(DWORD Reserved, + LPWSTR CMID, + LPWSTR Filename, + UINT Command) +{ + UNIMPLEMENTED; +} + + diff --git a/subsys/win32k/objects/line.c b/subsys/win32k/objects/line.c new file mode 100644 index 0000000..4c092fb --- /dev/null +++ b/subsys/win32k/objects/line.c @@ -0,0 +1,315 @@ +// Some code from the WINE project source (www.winehq.com) + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include + +// #define NDEBUG +#include + +BOOL +STDCALL +W32kAngleArc(HDC hDC, + int X, + int Y, + DWORD Radius, + FLOAT StartAngle, + FLOAT SweepAngle) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kArc(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XStartArc, + int YStartArc, + int XEndArc, + int YEndArc) +{ + DC *dc = DC_HandleToPtr(hDC); + if(!dc) return FALSE; + + if(PATH_IsPathOpen(dc->w.path)) + return PATH_Arc(hDC, LeftRect, TopRect, RightRect, BottomRect, + XStartArc, YStartArc, XEndArc, YEndArc); + + DC_ReleasePtr( hDC ); +// EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED +// XStartArc, YStartArc, XEndArc, YEndArc); +} + +BOOL +STDCALL +W32kArcTo(HDC hDC, + int LeftRect, + int TopRect, + int RightRect, + int BottomRect, + int XRadial1, + int YRadial1, + int XRadial2, + int YRadial2) +{ + BOOL result; + DC *dc = DC_HandleToPtr(hDC); + if(!dc) return FALSE; + + // Line from current position to starting point of arc + W32kLineTo(hDC, XRadial1, YRadial1); + + // Then the arc is drawn. + result = W32kArc(hDC, LeftRect, TopRect, RightRect, BottomRect, + XRadial1, YRadial1, XRadial2, YRadial2); + + // If no error occured, the current position is moved to the ending point of the arc. + if(result) + { + W32kMoveToEx(hDC, XRadial2, YRadial2, NULL); + } + DC_ReleasePtr( hDC ); + return result; +} + +INT +STDCALL +W32kGetArcDirection(HDC hDC) +{ + PDC dc; + int ret; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { + return 0; + } + + ret = dc->w.ArcDirection; + DC_ReleasePtr( hDC ); + return ret; +} + +BOOL +STDCALL +W32kLineTo(HDC hDC, + int XEnd, + int YEnd) +{ + DC *dc = DC_HandleToPtr(hDC); + SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface); + BOOL ret; + PPENOBJ pen; + PROSRGNDATA reg; + + if(!dc) return FALSE; + + if(PATH_IsPathOpen(dc->w.path)) { + ret = PATH_LineTo(hDC, XEnd, YEnd); + } else { + pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); + reg = (PROSRGNDATA)GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); + + ASSERT( pen ); + // not yet implemented ASSERT( reg ); + + ret = EngLineTo(SurfObj, + NULL, // ClipObj + PenToBrushObj(dc, pen), + dc->w.CursPosX, dc->w.CursPosY, XEnd, YEnd, + reg, // Bounding rectangle + dc->w.ROPmode); // MIX + + GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC ); + GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); + } + if(ret) { + dc->w.CursPosX = XEnd; + dc->w.CursPosY = YEnd; + } + DC_ReleasePtr( hDC ); + return ret; +} + +BOOL +STDCALL +W32kMoveToEx(HDC hDC, + int X, + int Y, + LPPOINT Point) +{ + DC *dc = DC_HandleToPtr( hDC ); + + if(!dc) return FALSE; + + if(Point) { + Point->x = dc->w.CursPosX; + Point->y = dc->w.CursPosY; + } + dc->w.CursPosX = X; + dc->w.CursPosY = Y; + + if(PATH_IsPathOpen(dc->w.path)){ + DC_ReleasePtr( hDC ); + return PATH_MoveTo(hDC); + } + DC_ReleasePtr( hDC ); + return FALSE; +} + +BOOL +STDCALL +W32kPolyBezier(HDC hDC, + CONST LPPOINT pt, + DWORD Count) +{ + DC *dc = DC_HandleToPtr(hDC); + if(!dc) return FALSE; + + if(PATH_IsPathOpen(dc->w.path)){ + DC_ReleasePtr( hDC ); + return PATH_PolyBezier(hDC, pt, Count); + } + + /* We'll convert it into line segments and draw them using Polyline */ + { + POINT *Pts; + INT nOut; + BOOL ret; + + Pts = GDI_Bezier(pt, Count, &nOut); + if(!Pts) return FALSE; + DbgPrint("Pts = %p, no = %d\n", Pts, nOut); + ret = W32kPolyline(dc->hSelf, Pts, nOut); + ExFreePool(Pts); + DC_ReleasePtr( hDC ); + return ret; + } +} + +BOOL +STDCALL +W32kPolyBezierTo(HDC hDC, + CONST LPPOINT pt, + DWORD Count) +{ + DC *dc = DC_HandleToPtr(hDC); + BOOL ret; + + if(!dc) return FALSE; + + if(PATH_IsPathOpen(dc->w.path)) + ret = PATH_PolyBezierTo(hDC, pt, Count); + else { /* We'll do it using PolyBezier */ + POINT *npt; + npt = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1)); + if(!npt) return FALSE; + npt[0].x = dc->w.CursPosX; + npt[0].y = dc->w.CursPosY; + memcpy(npt + 1, pt, sizeof(POINT) * Count); + ret = W32kPolyBezier(dc->hSelf, npt, Count+1); + ExFreePool(npt); + } + if(ret) { + dc->w.CursPosX = pt[Count-1].x; + dc->w.CursPosY = pt[Count-1].y; + } + DC_ReleasePtr( hDC ); + return ret; +} + +BOOL +STDCALL +W32kPolyDraw(HDC hDC, + CONST LPPOINT pt, + CONST LPBYTE Types, + int Count) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPolyline(HDC hDC, + CONST LPPOINT pt, + int Count) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPolylineTo(HDC hDC, + CONST LPPOINT pt, + DWORD Count) +{ + DC *dc = DC_HandleToPtr(hDC); + BOOL ret; + + if(!dc) return FALSE; + + if(PATH_IsPathOpen(dc->w.path)) + { + ret = PATH_PolylineTo(hDC, pt, Count); + } + else { /* do it using Polyline */ + POINT *pts = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1)); + if(!pts) return FALSE; + + pts[0].x = dc->w.CursPosX; + pts[0].y = dc->w.CursPosY; + memcpy( pts + 1, pt, sizeof(POINT) * Count); + ret = W32kPolyline(hDC, pts, Count + 1); + ExFreePool(pts); + } + if(ret) { + dc->w.CursPosX = pt[Count-1].x; + dc->w.CursPosY = pt[Count-1].y; + } + DC_ReleasePtr( hDC ); + return ret; +} + +BOOL +STDCALL +W32kPolyPolyline(HDC hDC, + CONST LPPOINT pt, + CONST LPDWORD PolyPoints, + DWORD Count) +{ + UNIMPLEMENTED; +} + +int +STDCALL +W32kSetArcDirection(HDC hDC, + int ArcDirection) +{ + PDC dc; + INT nOldDirection; + + dc = DC_HandleToPtr (hDC); + if (!dc) + { + return 0; + } + if (ArcDirection != AD_COUNTERCLOCKWISE && ArcDirection != AD_CLOCKWISE) + { +// SetLastError(ERROR_INVALID_PARAMETER); + DC_ReleasePtr( hDC ); + return 0; + } + + nOldDirection = dc->w.ArcDirection; + dc->w.ArcDirection = ArcDirection; + DC_ReleasePtr( hDC ); + return nOldDirection; +} diff --git a/subsys/win32k/objects/metafile.c b/subsys/win32k/objects/metafile.c new file mode 100644 index 0000000..441c288 --- /dev/null +++ b/subsys/win32k/objects/metafile.c @@ -0,0 +1,236 @@ + + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +// #define NDEBUG +#include + +HENHMETAFILE +STDCALL +W32kCloseEnhMetaFile(HDC hDC) +{ + UNIMPLEMENTED; +} + +HMETAFILE +STDCALL +W32kCloseMetaFile(HDC hDC) +{ + UNIMPLEMENTED; +} + +HENHMETAFILE +STDCALL +W32kCopyEnhMetaFile(HENHMETAFILE Src, + LPCWSTR File) +{ + UNIMPLEMENTED; +} + +HMETAFILE +STDCALL +W32kCopyMetaFile(HMETAFILE Src, + LPCWSTR File) +{ + UNIMPLEMENTED; +} + +HDC +STDCALL +W32kCreateEnhMetaFile(HDC hDCRef, + LPCWSTR File, + CONST LPRECT Rect, + LPCWSTR Description) +{ + UNIMPLEMENTED; +} + +HDC +STDCALL +W32kCreateMetaFile(LPCWSTR File) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kDeleteEnhMetaFile(HENHMETAFILE emf) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kDeleteMetaFile(HMETAFILE mf) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kEnumEnhMetaFile(HDC hDC, + HENHMETAFILE emf, + ENHMFENUMPROC EnhMetaFunc, + LPVOID Data, + CONST LPRECT Rect) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kEnumMetaFile(HDC hDC, + HMETAFILE mf, + MFENUMPROC MetaFunc, + LPARAM lParam) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGdiComment(HDC hDC, + UINT Size, + CONST LPBYTE Data) +{ + UNIMPLEMENTED; +} + +HENHMETAFILE +STDCALL +W32kGetEnhMetaFile(LPCWSTR MetaFile) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetEnhMetaFileBits(HENHMETAFILE hemf, + UINT BufSize, + LPBYTE Buffer) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetEnhMetaFileDescription(HENHMETAFILE hemf, + UINT BufSize, + LPWSTR Description) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetEnhMetaFileHeader(HENHMETAFILE hemf, + UINT BufSize, + LPENHMETAHEADER emh) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetEnhMetaFilePaletteEntries(HENHMETAFILE hemf, + UINT Entries, + LPPALETTEENTRY pe) +{ + UNIMPLEMENTED; +} + +HMETAFILE +STDCALL +W32kGetMetaFile(LPCWSTR MetaFile) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetMetaFileBitsEx(HMETAFILE hmf, + UINT Size, + LPVOID Data) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetWinMetaFileBits(HENHMETAFILE hemf, + UINT BufSize, + LPBYTE Buffer, + INT MapMode, + HDC Ref) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPlayEnhMetaFile(HDC hDC, + HENHMETAFILE hemf, + CONST PRECT Rect) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPlayEnhMetaFileRecord(HDC hDC, + LPHANDLETABLE Handletable, + CONST ENHMETARECORD *EnhMetaRecord, + UINT Handles) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPlayMetaFile(HDC hDC, + HMETAFILE hmf) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kPlayMetaFileRecord(HDC hDC, + LPHANDLETABLE Handletable, + LPMETARECORD MetaRecord, + UINT Handles) +{ + UNIMPLEMENTED; +} + +HENHMETAFILE +STDCALL +W32kSetEnhMetaFileBits(UINT BufSize, + CONST PBYTE Data) +{ + UNIMPLEMENTED; +} + +HMETAFILE +STDCALL +W32kSetMetaFileBitsEx(UINT Size, + CONST PBYTE Data) +{ + UNIMPLEMENTED; +} + +HENHMETAFILE +STDCALL +W32kSetWinMetaFileBits(UINT BufSize, + CONST PBYTE Buffer, + HDC Ref, +// CONST METAFILEPICT *mfp) + PVOID mfp) +{ + UNIMPLEMENTED; +} + + diff --git a/subsys/win32k/objects/objconv.c b/subsys/win32k/objects/objconv.c new file mode 100644 index 0000000..c3582a1 --- /dev/null +++ b/subsys/win32k/objects/objconv.c @@ -0,0 +1,61 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include + +/* FIXME: Surely we should just have one include file that includes all of these.. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../eng/objects.h" + +//#define NDEBUG +#include + + +PBRUSHOBJ PenToBrushObj(PDC dc, PENOBJ *pen) +{ + BRUSHOBJ *BrushObj; + XLATEOBJ *RGBtoVGA16; + + ASSERT( pen ); + + BrushObj = ExAllocatePool(NonPagedPool, sizeof(BRUSHOBJ)); + BrushObj->iSolidColor = pen->logpen.lopnColor; + + return BrushObj; +} + +VOID BitmapToSurf(HDC hdc, PSURFGDI SurfGDI, PSURFOBJ SurfObj, PBITMAPOBJ Bitmap) +{ + ASSERT( SurfGDI ); + if( Bitmap ){ + if(Bitmap->dib) + { + SurfGDI->BitsPerPixel = Bitmap->dib->dsBm.bmBitsPixel; + SurfObj->lDelta = Bitmap->dib->dsBm.bmWidthBytes; + SurfObj->pvBits = Bitmap->dib->dsBm.bmBits; + SurfObj->cjBits = Bitmap->dib->dsBm.bmHeight * Bitmap->dib->dsBm.bmWidthBytes; + } else { + SurfGDI->BitsPerPixel = Bitmap->bitmap.bmBitsPixel; + SurfObj->lDelta = Bitmap->bitmap.bmWidthBytes; + SurfObj->pvBits = Bitmap->bitmap.bmBits; + SurfObj->cjBits = Bitmap->bitmap.bmHeight * Bitmap->bitmap.bmWidthBytes; + } + SurfObj->sizlBitmap = Bitmap->size; // FIXME: alloc memory for our own struct? + } + + SurfObj->dhsurf = NULL; + SurfObj->hsurf = NULL; + SurfObj->dhpdev = NULL; + SurfObj->hdev = NULL; + SurfObj->pvScan0 = SurfObj->pvBits; // start of bitmap + SurfObj->iUniq = 0; // not sure.. + SurfObj->iBitmapFormat = BitmapFormat(SurfGDI->BitsPerPixel, BI_RGB); + SurfObj->iType = STYPE_BITMAP; + SurfObj->fjBitmap = BMF_TOPDOWN; +} diff --git a/subsys/win32k/objects/paint.c b/subsys/win32k/objects/paint.c new file mode 100644 index 0000000..f1aa922 --- /dev/null +++ b/subsys/win32k/objects/paint.c @@ -0,0 +1,52 @@ + + +#undef WIN32_LEAN_AND_MEAN +#include +#include +//#include +#include + +// #define NDEBUG +#include + +BOOL +STDCALL +W32kGdiFlush(VOID) +{ + UNIMPLEMENTED; +} + +DWORD +STDCALL +W32kGdiGetBatchLimit(VOID) +{ + UNIMPLEMENTED; +} + +DWORD +STDCALL +W32kGdiSetBatchLimit(DWORD Limit) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetBoundsRect(HDC hDC, + LPRECT Bounds, + UINT Flags) +{ + DPRINT("stub"); + return DCB_RESET; /* bounding rectangle always empty */ +} + +UINT +STDCALL +W32kSetBoundsRect(HDC hDC, + CONST PRECT Bounds, + UINT Flags) +{ + DPRINT("stub"); + return DCB_DISABLE; /* bounding rectangle always empty */ +} + diff --git a/subsys/win32k/objects/palette.c b/subsys/win32k/objects/palette.c new file mode 100644 index 0000000..b4e150d --- /dev/null +++ b/subsys/win32k/objects/palette.c @@ -0,0 +1,386 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include "../include/palette.h" + +static int PALETTE_firstFree = 0; +static unsigned char PALETTE_freeList[256]; + +int PALETTE_PaletteFlags = 0; +PALETTEENTRY *COLOR_sysPal = NULL; +int COLOR_gapStart; +int COLOR_gapEnd; +int COLOR_gapFilled; +int COLOR_max; + +PALETTEENTRY *ReturnSystemPalette(void) +{ + return COLOR_sysPal; +} + +// Create the system palette +HPALETTE PALETTE_Init(void) +{ + int i; + HPALETTE hpalette; + PLOGPALETTE palPtr; + PPALOBJ palObj; + const PALETTEENTRY* __sysPalTemplate = (const PALETTEENTRY*)COLOR_GetSystemPaletteTemplate(); + + // create default palette (20 system colors) + palPtr = ExAllocatePool(NonPagedPool, sizeof(LOGPALETTE) + (NB_RESERVED_COLORS * sizeof(PALETTEENTRY))); + if (!palPtr) return FALSE; + + palPtr->palVersion = 0x300; + palPtr->palNumEntries = NB_RESERVED_COLORS; + for(i=0; ipalPalEntry[i].peRed = __sysPalTemplate[i].peRed; + palPtr->palPalEntry[i].peGreen = __sysPalTemplate[i].peGreen; + palPtr->palPalEntry[i].peBlue = __sysPalTemplate[i].peBlue; + palPtr->palPalEntry[i].peFlags = 0; + } + + hpalette = W32kCreatePalette(palPtr); + ExFreePool(palPtr); + + palObj = (PPALOBJ)AccessUserObject(hpalette); + if (palObj) + { + if (!(palObj->mapping = ExAllocatePool(NonPagedPool, sizeof(int) * 20))) + { + DbgPrint("Win32k: Can not create palette mapping -- out of memory!"); + return FALSE; + } +// GDI_ReleaseObj( hpalette ); + } + +/* palette_size = visual->map_entries; */ + + return hpalette; +} + +static void PALETTE_FormatSystemPalette(void) +{ + // Build free list so we'd have an easy way to find + // out if there are any available colorcells. + + int i, j = PALETTE_firstFree = NB_RESERVED_COLORS/2; + + COLOR_sysPal[j].peFlags = 0; + for(i = NB_RESERVED_COLORS/2 + 1 ; i < 256 - NB_RESERVED_COLORS/2 ; i++) + { + if( i < COLOR_gapStart || i > COLOR_gapEnd ) + { + COLOR_sysPal[i].peFlags = 0; // unused tag + PALETTE_freeList[j] = i; // next + j = i; + } + } + PALETTE_freeList[j] = 0; +} + +/* Ported from WINE 20020804 (graphics\x11drv\palette.c) */ +static int SysPaletteLookupPixel( COLORREF col, BOOL skipReserved ) +{ + int i, best = 0, diff = 0x7fffffff; + int r,g,b; + + for( i = 0; i < palette_size && diff ; i++ ) + { + if( !(COLOR_sysPal[i].peFlags & PC_SYS_USED) || (skipReserved && COLOR_sysPal[i].peFlags & PC_SYS_RESERVED) ) + continue; + + r = COLOR_sysPal[i].peRed - GetRValue(col); + g = COLOR_sysPal[i].peGreen - GetGValue(col); + b = COLOR_sysPal[i].peBlue - GetBValue(col); + + r = r*r + g*g + b*b; + + if( r < diff ) { best = i; diff = r; } + } + return best; +} + +/* Ported from WINE 20020804 (graphics\x11drv\palette.c) */ +/* Make sure this is required - ROS's xlate may make this redundant */ +UINT WINAPI GetNearestPaletteIndex( + HPALETTE hpalette, /* [in] Handle of logical color palette */ + COLORREF color) /* [in] Color to be matched */ +{ + PPALOBJ palObj = (PPALOBJ)AccessUserObject(hpalette); + UINT index = 0; + + if( palObj ) + { + int i, diff = 0x7fffffff; + int r,g,b; + PALETTEENTRY* entry = palObj->logpalette->palPalEntry; + + for( i = 0; i < palObj->logpalette->palNumEntries && diff ; i++, entry++) + { + if (!(entry->peFlags & PC_SYS_USED)) continue; + + r = entry->peRed - GetRValue(color); + g = entry->peGreen - GetGValue(color); + b = entry->peBlue - GetBValue(color); + + r = r*r + g*g + b*b; + + if( r < diff ) { index = i; diff = r; } + } +// GDI_ReleaseObj( hpalette ); + } + DPRINT("(%04x,%06lx): returning %d\n", hpalette, color, index ); + return index; +} + +void PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, int size) +{ + int i = 0; + for( ; imapping) ? 1 : 0; + int index, iRemapped = 0; + int *mapping; + + // reset dynamic system palette entries + + if( !mapOnly && PALETTE_firstFree != -1) PALETTE_FormatSystemPalette(); + + // initialize palette mapping table + + //mapping = HeapReAlloc( GetProcessHeap(), 0, palPtr->mapping, + // sizeof(int)*palPtr->logpalette->palNumEntries); + ExFreePool(palPtr->mapping); + mapping = ExAllocatePool(NonPagedPool, sizeof(int)*palPtr->logpalette->palNumEntries); + + palPtr->mapping = mapping; + + for(uNum += uStart; uStart < uNum; uStart++) + { + index = -1; + flag = PC_SYS_USED; + + switch( palPtr->logpalette->palPalEntry[uStart].peFlags & 0x07 ) + { + case PC_EXPLICIT: // palette entries are indices into system palette + // The PC_EXPLICIT flag is used to copy an entry from the system palette into the logical palette + index = *(WORD*)(palPtr->logpalette->palPalEntry + uStart); + if(index > 255 || (index >= COLOR_gapStart && index <= COLOR_gapEnd)) + { + DbgPrint("Win32k: PC_EXPLICIT: idx %d out of system palette, assuming black.\n", index); + index = 0; + } + break; + + case PC_RESERVED: // forbid future mappings to this entry + // For palette animation, the entries in the logical palette need the PC_RESERVED flag + flag |= PC_SYS_RESERVED; + + // fall through + default: // try to collapse identical colors + index = COLOR_PaletteLookupExactIndex(COLOR_sysPal, 256, + *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart)); + // fall through + + case PC_NOCOLLAPSE: + // If an entry in the logical palette is marked with the PC_NOCOLLAPSE flag, the palette + // manager allocates a free entry in the system palette if one is available and only uses the + // closest colour match if there are no (more) free entries in the system palette + + DbgPrint("Win32k: WARNING: PC_NOCOLLAPSE is not yet working properly\n"); + + if( index < 0 ) + { + if(PALETTE_firstFree > 0 /* && !(PALETTE_PaletteFlags & PALETTE_FIXED) FIXME */ ) + { + DbgPrint("Win32k: Unimplemented Palette Operation: PC_NOCOLLAPSE [objects/palette.c]\n"); +/* XColor color; + index = PALETTE_firstFree; // ought to be available + PALETTE_firstFree = PALETTE_freeList[index]; + + color.pixel = (PALETTE_PaletteToXPixel) ? PALETTE_PaletteToXPixel[index] : index; + color.red = palPtr->logpalette->palPalEntry[uStart].peRed << 8; + color.green = palPtr->logpalette->palPalEntry[uStart].peGreen << 8; + color.blue = palPtr->logpalette->palPalEntry[uStart].peBlue << 8; + color.flags = DoRed | DoGreen | DoBlue; + TSXStoreColor(display, PALETTE_PaletteXColormap, &color); + + COLOR_sysPal[index] = palPtr->logpalette->palPalEntry[uStart]; + COLOR_sysPal[index].peFlags = flag; + PALETTE_freeList[index] = 0; + + if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */ + break; + } +/* else if (PALETTE_PaletteFlags & PALETTE_VIRTUAL) + { + index = PALETTE_ToPhysical(NULL, 0x00ffffff & + *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart)); + break; + } FIXME */ + + // we have to map to existing entry in the system palette + + index = COLOR_PaletteLookupPixel(COLOR_sysPal, 256, NULL, + *(COLORREF*)(palPtr->logpalette->palPalEntry + uStart), TRUE); + } + palPtr->logpalette->palPalEntry[uStart].peFlags |= PC_SYS_USED; + +/* if(PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; FIXME */ + break; + } + + if( !prevMapping || palPtr->mapping[uStart] != index ) iRemapped++; + palPtr->mapping[uStart] = index; + + } + return iRemapped; +} + +/* Return the physical color closest to 'color'. */ +/* Ported from WINE 20020804 (graphics\x11drv\palette.c) */ +int PALETTE_ToPhysical( PDC dc, COLORREF color ) +{ + WORD index = 0; + HPALETTE hPal = (dc)? dc->w.hPalette: W32kGetStockObject(DEFAULT_PALETTE); + unsigned char spec_type = color >> 24; + PPALOBJ palPtr = (PPALOBJ)AccessUserObject(hPal); + + /* palPtr can be NULL when DC is being destroyed */ + if( !palPtr ) return 0; + + if ( PALETTE_PaletteFlags & PALETTE_FIXED ) + { + /* there is no colormap limitation; we are going to have to compute + * the pixel value from the visual information stored earlier + */ + + unsigned long red, green, blue; + unsigned idx = 0; + + switch(spec_type) + { + case 1: /* PALETTEINDEX */ + + if( (idx = color & 0xffff) >= palPtr->logpalette->palNumEntries) + { + DPRINT("RGB(%lx) : idx %d is out of bounds, assuming black\n", color, idx); +// GDI_ReleaseObj( hPal ); + return 0; + } + + if( palPtr->mapping ) + { + int ret = palPtr->mapping[idx]; +// GDI_ReleaseObj( hPal ); + return ret; + } + color = *(COLORREF*)(palPtr->logpalette->palPalEntry + idx); + break; + + default: + color &= 0xffffff; + /* fall through to RGB */ + + case 0: /* RGB */ + if( dc && (dc->w.bitsPerPixel == 1) ) + { +// GDI_ReleaseObj( hPal ); + return (((color >> 16) & 0xff) + + ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0; + } + + } + + red = GetRValue(color); green = GetGValue(color); blue = GetBValue(color); + + if (PALETTE_Graymax) + { + /* grayscale only; return scaled value */ +// GDI_ReleaseObj( hPal ); + return ( (red * 30 + green * 59 + blue * 11) * PALETTE_Graymax) / 25500; + } + else + { + /* scale each individually and construct the TrueColor pixel value */ + if (PALETTE_PRed.scale < 8) + red = red >> (8-PALETTE_PRed.scale); + else if (PALETTE_PRed.scale > 8) + red = red << (PALETTE_PRed.scale-8) | + red >> (16-PALETTE_PRed.scale); + if (PALETTE_PGreen.scale < 8) + green = green >> (8-PALETTE_PGreen.scale); + else if (PALETTE_PGreen.scale > 8) + green = green << (PALETTE_PGreen.scale-8) | + green >> (16-PALETTE_PGreen.scale); + if (PALETTE_PBlue.scale < 8) + blue = blue >> (8-PALETTE_PBlue.scale); + else if (PALETTE_PBlue.scale > 8) + blue = blue << (PALETTE_PBlue.scale-8) | + blue >> (16-PALETTE_PBlue.scale); + +// GDI_ReleaseObj( hPal ); + return (red << PALETTE_PRed.shift) | (green << PALETTE_PGreen.shift) | (blue << PALETTE_PBlue.shift); + } + } + else + { + + if( !palPtr->mapping ) + DPRINT("Palette %04x is not realized\n", dc->w.hPalette); + + switch(spec_type) /* we have to peruse DC and system palette */ + { + default: + color &= 0xffffff; + /* fall through to RGB */ + + case 0: /* RGB */ + if( dc && (dc->w.bitsPerPixel == 1) ) + { +// GDI_ReleaseObj( hPal ); + return (((color >> 16) & 0xff) + + ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0; + } + + index = SysPaletteLookupPixel( color, FALSE); + +/* if (PALETTE_PaletteToXPixel) index = PALETTE_PaletteToXPixel[index]; */ + + /* DPRINT(palette,"RGB(%lx) -> pixel %i\n", color, index); + */ + break; + case 1: /* PALETTEINDEX */ + index = color & 0xffff; + + if( index >= palPtr->logpalette->palNumEntries ) + DbgPrint("RGB(%lx) : index %i is out of bounds\n", color, index); + else if( palPtr->mapping ) index = palPtr->mapping[index]; + + /* DPRINT(palette,"PALETTEINDEX(%04x) -> pixel %i\n", (WORD)color, index); + */ + break; + case 2: /* PALETTERGB */ + index = GetNearestPaletteIndex( hPal, color ); + if (palPtr->mapping) index = palPtr->mapping[index]; + /* DPRINT(palette,"PALETTERGB(%lx) -> pixel %i\n", color, index); + */ + break; + } + } + +// GDI_ReleaseObj( hPal ); + return index; +} diff --git a/subsys/win32k/objects/path.c b/subsys/win32k/objects/path.c new file mode 100644 index 0000000..c61ec65 --- /dev/null +++ b/subsys/win32k/objects/path.c @@ -0,0 +1,1028 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// #define NDEBUG +#include + +#define NUM_ENTRIES_INITIAL 16 /* Initial size of points / flags arrays */ +#define GROW_FACTOR_NUMER 2 /* Numerator of grow factor for the array */ +#define GROW_FACTOR_DENOM 1 /* Denominator of grow factor */ + + +static BOOL PATH_PathToRegion(const GdiPath *pPath, INT nPolyFillMode, + HRGN *pHrgn); +static void PATH_EmptyPath(GdiPath *pPath); +static BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint, + BYTE flags); +static BOOL PATH_ReserveEntries(GdiPath *pPath, INT numEntries); +static BOOL PATH_GetPathFromHDC(HDC hdc, GdiPath **ppPath); +static BOOL PATH_DoArcPart(GdiPath *pPath, FLOAT_POINT corners[], + double angleStart, double angleEnd, BOOL addMoveTo); +static void PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x, + double y, POINT *pPoint); +static void PATH_NormalizePoint(FLOAT_POINT corners[], const FLOAT_POINT + *pPoint, double *pX, double *pY); + +BOOL +STDCALL +W32kAbortPath(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kBeginPath(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kCloseFigure(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kEndPath(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kFillPath(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kFlattenPath(HDC hDC) +{ + UNIMPLEMENTED; +} + + +BOOL +STDCALL +W32kGetMiterLimit(HDC hDC, + PFLOAT Limit) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kGetPath(HDC hDC, + LPPOINT Points, + LPBYTE Types, + INT nSize) +{ + UNIMPLEMENTED; +} + +HRGN +STDCALL +W32kPathToRegion(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetMiterLimit(HDC hDC, + FLOAT NewLimit, + PFLOAT OldLimit) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kStrokeAndFillPath(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kStrokePath(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kWidenPath(HDC hDC) +{ + UNIMPLEMENTED; +} + +/*********************************************************************** + * Exported functions + */ + +/* PATH_InitGdiPath + * + * Initializes the GdiPath structure. + */ +void PATH_InitGdiPath(GdiPath *pPath) +{ + assert(pPath!=NULL); + + pPath->state=PATH_Null; + pPath->pPoints=NULL; + pPath->pFlags=NULL; + pPath->numEntriesUsed=0; + pPath->numEntriesAllocated=0; +} + +/* PATH_DestroyGdiPath + * + * Destroys a GdiPath structure (frees the memory in the arrays). + */ +void PATH_DestroyGdiPath(GdiPath *pPath) +{ + assert(pPath!=NULL); + + ExFreePool(pPath->pPoints); + ExFreePool(pPath->pFlags); +} + +/* PATH_AssignGdiPath + * + * Copies the GdiPath structure "pPathSrc" to "pPathDest". A deep copy is + * performed, i.e. the contents of the pPoints and pFlags arrays are copied, + * not just the pointers. Since this means that the arrays in pPathDest may + * need to be resized, pPathDest should have been initialized using + * PATH_InitGdiPath (in C++, this function would be an assignment operator, + * not a copy constructor). + * Returns TRUE if successful, else FALSE. + */ +BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc) +{ + assert(pPathDest!=NULL && pPathSrc!=NULL); + + /* Make sure destination arrays are big enough */ + if(!PATH_ReserveEntries(pPathDest, pPathSrc->numEntriesUsed)) + return FALSE; + + /* Perform the copy operation */ + memcpy(pPathDest->pPoints, pPathSrc->pPoints, + sizeof(POINT)*pPathSrc->numEntriesUsed); + memcpy(pPathDest->pFlags, pPathSrc->pFlags, + sizeof(BYTE)*pPathSrc->numEntriesUsed); + + pPathDest->state=pPathSrc->state; + pPathDest->numEntriesUsed=pPathSrc->numEntriesUsed; + pPathDest->newStroke=pPathSrc->newStroke; + + return TRUE; +} + +/* PATH_MoveTo + * + * Should be called when a MoveTo is performed on a DC that has an + * open path. This starts a new stroke. Returns TRUE if successful, else + * FALSE. + */ +BOOL PATH_MoveTo(HDC hdc) +{ + GdiPath *pPath; + + /* Get pointer to path */ + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + /* FIXME: Do we have to call SetLastError? */ + return FALSE; + + /* Start a new stroke */ + pPath->newStroke=TRUE; + + return TRUE; +} + +/* PATH_LineTo + * + * Should be called when a LineTo is performed on a DC that has an + * open path. This adds a PT_LINETO entry to the path (and possibly + * a PT_MOVETO entry, if this is the first LineTo in a stroke). + * Returns TRUE if successful, else FALSE. + */ +BOOL PATH_LineTo(HDC hdc, INT x, INT y) +{ + GdiPath *pPath; + POINT point, pointCurPos; + + /* Get pointer to path */ + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + /* Convert point to device coordinates */ + point.x=x; + point.y=y; + if(!W32kLPtoDP(hdc, &point, 1)) + return FALSE; + + /* Add a PT_MOVETO if necessary */ + if(pPath->newStroke) + { + pPath->newStroke=FALSE; + if(!W32kGetCurrentPositionEx(hdc, &pointCurPos) || + !W32kLPtoDP(hdc, &pointCurPos, 1)) + return FALSE; + if(!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO)) + return FALSE; + } + + /* Add a PT_LINETO entry */ + return PATH_AddEntry(pPath, &point, PT_LINETO); +} + +/* PATH_Rectangle + * + * Should be called when a call to Rectangle is performed on a DC that has + * an open path. Returns TRUE if successful, else FALSE. + */ +BOOL PATH_Rectangle(HDC hdc, INT x1, INT y1, INT x2, INT y2) +{ + GdiPath *pPath; + POINT corners[2], pointTemp; + INT temp; + + /* Get pointer to path */ + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + /* Convert points to device coordinates */ + corners[0].x=x1; + corners[0].y=y1; + corners[1].x=x2; + corners[1].y=y2; + if(!W32kLPtoDP(hdc, corners, 2)) + return FALSE; + + /* Make sure first corner is top left and second corner is bottom right */ + if(corners[0].x>corners[1].x) + { + temp=corners[0].x; + corners[0].x=corners[1].x; + corners[1].x=temp; + } + if(corners[0].y>corners[1].y) + { + temp=corners[0].y; + corners[0].y=corners[1].y; + corners[1].y=temp; + } + + /* In GM_COMPATIBLE, don't include bottom and right edges */ + if(W32kGetGraphicsMode(hdc)==GM_COMPATIBLE) + { + corners[1].x--; + corners[1].y--; + } + + /* Close any previous figure */ + if(!W32kCloseFigure(hdc)) + { + /* The W32kCloseFigure call shouldn't have failed */ + assert(FALSE); + return FALSE; + } + + /* Add four points to the path */ + pointTemp.x=corners[1].x; + pointTemp.y=corners[0].y; + if(!PATH_AddEntry(pPath, &pointTemp, PT_MOVETO)) + return FALSE; + if(!PATH_AddEntry(pPath, corners, PT_LINETO)) + return FALSE; + pointTemp.x=corners[0].x; + pointTemp.y=corners[1].y; + if(!PATH_AddEntry(pPath, &pointTemp, PT_LINETO)) + return FALSE; + if(!PATH_AddEntry(pPath, corners+1, PT_LINETO)) + return FALSE; + + /* Close the rectangle figure */ + if(!W32kCloseFigure(hdc)) + { + /* The W32kCloseFigure call shouldn't have failed */ + assert(FALSE); + return FALSE; + } + + return TRUE; +} + +/* PATH_Ellipse + * + * Should be called when a call to Ellipse is performed on a DC that has + * an open path. This adds four Bezier splines representing the ellipse + * to the path. Returns TRUE if successful, else FALSE. + */ +BOOL PATH_Ellipse(HDC hdc, INT x1, INT y1, INT x2, INT y2) +{ + /* TODO: This should probably be revised to call PATH_AngleArc */ + /* (once it exists) */ + return PATH_Arc(hdc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2); +} + +/* PATH_Arc + * + * Should be called when a call to Arc is performed on a DC that has + * an open path. This adds up to five Bezier splines representing the arc + * to the path. Returns TRUE if successful, else FALSE. + */ +BOOL PATH_Arc(HDC hdc, INT x1, INT y1, INT x2, INT y2, + INT xStart, INT yStart, INT xEnd, INT yEnd) +{ + GdiPath *pPath; + DC *pDC; + double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0; + /* Initialize angleEndQuadrant to silence gcc's warning */ + double x, y; + FLOAT_POINT corners[2], pointStart, pointEnd; + BOOL start, end; + INT temp; + + /* FIXME: This function should check for all possible error returns */ + /* FIXME: Do we have to respect newStroke? */ + + /* Get pointer to DC */ + pDC=DC_HandleToPtr(hdc); + if(pDC==NULL) + return FALSE; + + /* Get pointer to path */ + if(!PATH_GetPathFromHDC(hdc, &pPath)){ + DC_ReleasePtr( hdc ); + return FALSE; + } + + /* Check that path is open */ + if(pPath->state!=PATH_Open){ + DC_ReleasePtr( hdc ); + return FALSE; + } + + /* FIXME: Do we have to close the current figure? */ + + /* Check for zero height / width */ + /* FIXME: Only in GM_COMPATIBLE? */ + if(x1==x2 || y1==y2){ + DC_ReleasePtr( hdc ); + return TRUE; + } + + /* Convert points to device coordinates */ + corners[0].x=(FLOAT)x1; + corners[0].y=(FLOAT)y1; + corners[1].x=(FLOAT)x2; + corners[1].y=(FLOAT)y2; + pointStart.x=(FLOAT)xStart; + pointStart.y=(FLOAT)yStart; + pointEnd.x=(FLOAT)xEnd; + pointEnd.y=(FLOAT)yEnd; + INTERNAL_LPTODP_FLOAT(pDC, corners); + INTERNAL_LPTODP_FLOAT(pDC, corners+1); + INTERNAL_LPTODP_FLOAT(pDC, &pointStart); + INTERNAL_LPTODP_FLOAT(pDC, &pointEnd); + + /* Make sure first corner is top left and second corner is bottom right */ + if(corners[0].x>corners[1].x) + { + temp=corners[0].x; + corners[0].x=corners[1].x; + corners[1].x=temp; + } + if(corners[0].y>corners[1].y) + { + temp=corners[0].y; + corners[0].y=corners[1].y; + corners[1].y=temp; + } + + /* Compute start and end angle */ + PATH_NormalizePoint(corners, &pointStart, &x, &y); + angleStart=atan2(y, x); + PATH_NormalizePoint(corners, &pointEnd, &x, &y); + angleEnd=atan2(y, x); + + /* Make sure the end angle is "on the right side" of the start angle */ + if(W32kGetArcDirection(hdc)==AD_CLOCKWISE) + { + if(angleEnd<=angleStart) + { + angleEnd+=2*M_PI; + assert(angleEnd>=angleStart); + } + } + else + { + if(angleEnd>=angleStart) + { + angleEnd-=2*M_PI; + assert(angleEnd<=angleStart); + } + } + + /* In GM_COMPATIBLE, don't include bottom and right edges */ + if(W32kGetGraphicsMode(hdc)==GM_COMPATIBLE) + { + corners[1].x--; + corners[1].y--; + } + + /* Add the arc to the path with one Bezier spline per quadrant that the + * arc spans */ + start=TRUE; + end=FALSE; + do + { + /* Determine the start and end angles for this quadrant */ + if(start) + { + angleStartQuadrant=angleStart; + if(W32kGetArcDirection(hdc)==AD_CLOCKWISE) + angleEndQuadrant=(floor(angleStart/M_PI_2)+1.0)*M_PI_2; + else + angleEndQuadrant=(ceil(angleStart/M_PI_2)-1.0)*M_PI_2; + } + else + { + angleStartQuadrant=angleEndQuadrant; + if(W32kGetArcDirection(hdc)==AD_CLOCKWISE) + angleEndQuadrant+=M_PI_2; + else + angleEndQuadrant-=M_PI_2; + } + + /* Have we reached the last part of the arc? */ + if((W32kGetArcDirection(hdc)==AD_CLOCKWISE && + angleEndangleEndQuadrant)) + { + /* Adjust the end angle for this quadrant */ + angleEndQuadrant=angleEnd; + end=TRUE; + } + + /* Add the Bezier spline to the path */ + PATH_DoArcPart(pPath, corners, angleStartQuadrant, angleEndQuadrant, start); + start=FALSE; + } while(!end); + + DC_ReleasePtr( hdc ); + return TRUE; +} + +BOOL PATH_PolyBezierTo(HDC hdc, const POINT *pts, DWORD cbPoints) +{ + GdiPath *pPath; + POINT pt; + INT i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + /* Add a PT_MOVETO if necessary */ + if(pPath->newStroke) + { + pPath->newStroke=FALSE; + if(!W32kGetCurrentPositionEx(hdc, &pt) || + !W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + if(!PATH_AddEntry(pPath, &pt, PT_MOVETO)) + return FALSE; + } + + for(i = 0; i < cbPoints; i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + PATH_AddEntry(pPath, &pt, PT_BEZIERTO); + } + return TRUE; +} + +BOOL PATH_PolyBezier(HDC hdc, const POINT *pts, DWORD cbPoints) +{ + GdiPath *pPath; + POINT pt; + INT i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + for(i = 0; i < cbPoints; i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO); + } + return TRUE; +} + +BOOL PATH_Polyline(HDC hdc, const POINT *pts, DWORD cbPoints) +{ + GdiPath *pPath; + POINT pt; + INT i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + for(i = 0; i < cbPoints; i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO); + } + return TRUE; +} + +BOOL PATH_PolylineTo(HDC hdc, const POINT *pts, DWORD cbPoints) +{ + GdiPath *pPath; + POINT pt; + INT i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + /* Add a PT_MOVETO if necessary */ + if(pPath->newStroke) + { + pPath->newStroke=FALSE; + if(!W32kGetCurrentPositionEx(hdc, &pt) || + !W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + if(!PATH_AddEntry(pPath, &pt, PT_MOVETO)) + return FALSE; + } + + for(i = 0; i < cbPoints; i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + PATH_AddEntry(pPath, &pt, PT_LINETO); + } + + return TRUE; +} + + +BOOL PATH_Polygon(HDC hdc, const POINT *pts, DWORD cbPoints) +{ + GdiPath *pPath; + POINT pt; + INT i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + for(i = 0; i < cbPoints; i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : + ((i == cbPoints-1) ? PT_LINETO | PT_CLOSEFIGURE : + PT_LINETO)); + } + return TRUE; +} + +BOOL PATH_PolyPolygon( HDC hdc, const POINT* pts, const INT* counts, + UINT polygons ) +{ + GdiPath *pPath; + POINT pt, startpt; + INT poly, point, i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + for(i = 0, poly = 0; poly < polygons; poly++) { + for(point = 0; point < counts[poly]; point++, i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + if(point == 0) startpt = pt; + PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); + } + /* win98 adds an extra line to close the figure for some reason */ + PATH_AddEntry(pPath, &startpt, PT_LINETO | PT_CLOSEFIGURE); + } + return TRUE; +} + +BOOL PATH_PolyPolyline( HDC hdc, const POINT* pts, const DWORD* counts, + DWORD polylines ) +{ + GdiPath *pPath; + POINT pt; + INT poly, point, i; + + if(!PATH_GetPathFromHDC(hdc, &pPath)) + return FALSE; + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + for(i = 0, poly = 0; poly < polylines; poly++) { + for(point = 0; point < counts[poly]; point++, i++) { + pt = pts[i]; + if(!W32kLPtoDP(hdc, &pt, 1)) + return FALSE; + PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO); + } + } + return TRUE; +} + +/*********************************************************************** + * Internal functions + */ + + +/* PATH_AddFlatBezier + * + */ +static BOOL PATH_AddFlatBezier(GdiPath *pPath, POINT *pt, BOOL closed) +{ + POINT *pts; + INT no, i; + + pts = GDI_Bezier( pt, 4, &no ); + if(!pts) return FALSE; + + for(i = 1; i < no; i++) + PATH_AddEntry(pPath, &pts[i], (i == no-1 && closed) ? PT_LINETO | PT_CLOSEFIGURE : PT_LINETO); + + ExFreePool(pts); + return TRUE; +} + +/* PATH_FlattenPath + * + * Replaces Beziers with line segments + * + */ +static BOOL PATH_FlattenPath(GdiPath *pPath) +{ + GdiPath newPath; + INT srcpt; + + memset(&newPath, 0, sizeof(newPath)); + newPath.state = PATH_Open; + for(srcpt = 0; srcpt < pPath->numEntriesUsed; srcpt++) { + switch(pPath->pFlags[srcpt] & ~PT_CLOSEFIGURE) { + case PT_MOVETO: + case PT_LINETO: + PATH_AddEntry(&newPath, &pPath->pPoints[srcpt], pPath->pFlags[srcpt]); + break; + case PT_BEZIERTO: + PATH_AddFlatBezier(&newPath, &pPath->pPoints[srcpt-1], pPath->pFlags[srcpt+2] & PT_CLOSEFIGURE); + srcpt += 2; + break; + } + } + newPath.state = PATH_Closed; + PATH_AssignGdiPath(pPath, &newPath); + PATH_EmptyPath(&newPath); + return TRUE; +} + +/* PATH_PathToRegion + * + * Creates a region from the specified path using the specified polygon + * filling mode. The path is left unchanged. A handle to the region that + * was created is stored in *pHrgn. If successful, TRUE is returned; if an + * error occurs, SetLastError is called with the appropriate value and + * FALSE is returned. + */ +static BOOL PATH_PathToRegion(const GdiPath *pPath, INT nPolyFillMode, + HRGN *pHrgn) +{ + int numStrokes, iStroke, i; + INT *pNumPointsInStroke; + HRGN hrgn; + + assert(pPath!=NULL); + assert(pHrgn!=NULL); + + PATH_FlattenPath(pPath); + + /* FIXME: What happens when number of points is zero? */ + + /* First pass: Find out how many strokes there are in the path */ + /* FIXME: We could eliminate this with some bookkeeping in GdiPath */ + numStrokes=0; + for(i=0; inumEntriesUsed; i++) + if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO) + numStrokes++; + + /* Allocate memory for number-of-points-in-stroke array */ + pNumPointsInStroke=(int *)ExAllocatePool(NonPagedPool, sizeof(int) * numStrokes); + if(!pNumPointsInStroke) + { +// SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Second pass: remember number of points in each polygon */ + iStroke=-1; /* Will get incremented to 0 at beginning of first stroke */ + for(i=0; inumEntriesUsed; i++) + { + /* Is this the beginning of a new stroke? */ + if((pPath->pFlags[i] & ~PT_CLOSEFIGURE) == PT_MOVETO) + { + iStroke++; + pNumPointsInStroke[iStroke]=0; + } + + pNumPointsInStroke[iStroke]++; + } + + /* Create a region from the strokes */ +/* hrgn=CreatePolyPolygonRgn(pPath->pPoints, pNumPointsInStroke, + numStrokes, nPolyFillMode); FIXME: reinclude when region code implemented */ + if(hrgn==(HRGN)0) + { +// SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Free memory for number-of-points-in-stroke array */ + ExFreePool(pNumPointsInStroke); + + /* Success! */ + *pHrgn=hrgn; + return TRUE; +} + +/* PATH_EmptyPath + * + * Removes all entries from the path and sets the path state to PATH_Null. + */ +static void PATH_EmptyPath(GdiPath *pPath) +{ + assert(pPath!=NULL); + + pPath->state=PATH_Null; + pPath->numEntriesUsed=0; +} + +/* PATH_AddEntry + * + * Adds an entry to the path. For "flags", pass either PT_MOVETO, PT_LINETO + * or PT_BEZIERTO, optionally ORed with PT_CLOSEFIGURE. Returns TRUE if + * successful, FALSE otherwise (e.g. if not enough memory was available). + */ +BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint, BYTE flags) +{ + assert(pPath!=NULL); + + /* FIXME: If newStroke is true, perhaps we want to check that we're + * getting a PT_MOVETO + */ + + /* Check that path is open */ + if(pPath->state!=PATH_Open) + return FALSE; + + /* Reserve enough memory for an extra path entry */ + if(!PATH_ReserveEntries(pPath, pPath->numEntriesUsed+1)) + return FALSE; + + /* Store information in path entry */ + pPath->pPoints[pPath->numEntriesUsed]=*pPoint; + pPath->pFlags[pPath->numEntriesUsed]=flags; + + /* If this is PT_CLOSEFIGURE, we have to start a new stroke next time */ + if((flags & PT_CLOSEFIGURE) == PT_CLOSEFIGURE) + pPath->newStroke=TRUE; + + /* Increment entry count */ + pPath->numEntriesUsed++; + + return TRUE; +} + +/* PATH_ReserveEntries + * + * Ensures that at least "numEntries" entries (for points and flags) have + * been allocated; allocates larger arrays and copies the existing entries + * to those arrays, if necessary. Returns TRUE if successful, else FALSE. + */ +static BOOL PATH_ReserveEntries(GdiPath *pPath, INT numEntries) +{ + INT numEntriesToAllocate; + POINT *pPointsNew; + BYTE *pFlagsNew; + + assert(pPath!=NULL); + assert(numEntries>=0); + + /* Do we have to allocate more memory? */ + if(numEntries > pPath->numEntriesAllocated) + { + /* Find number of entries to allocate. We let the size of the array + * grow exponentially, since that will guarantee linear time + * complexity. */ + if(pPath->numEntriesAllocated) + { + numEntriesToAllocate=pPath->numEntriesAllocated; + while(numEntriesToAllocatepPoints) + { + assert(pPath->pFlags); + + memcpy(pPointsNew, pPath->pPoints, sizeof(POINT)*pPath->numEntriesUsed); + memcpy(pFlagsNew, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed); + + ExFreePool(pPath->pPoints); + ExFreePool(pPath->pFlags); + } + pPath->pPoints=pPointsNew; + pPath->pFlags=pFlagsNew; + pPath->numEntriesAllocated=numEntriesToAllocate; + } + + return TRUE; +} + +/* PATH_GetPathFromHDC + * + * Retrieves a pointer to the GdiPath structure contained in an HDC and + * places it in *ppPath. TRUE is returned if successful, FALSE otherwise. + */ +static BOOL PATH_GetPathFromHDC(HDC hdc, GdiPath **ppPath) +{ + DC *pDC; + + pDC=DC_HandleToPtr(hdc); + if(pDC) + { + *ppPath=&pDC->w.path; + DC_ReleasePtr( hdc ); + return TRUE; + } + return FALSE; +} + +/* PATH_DoArcPart + * + * Creates a Bezier spline that corresponds to part of an arc and appends the + * corresponding points to the path. The start and end angles are passed in + * "angleStart" and "angleEnd"; these angles should span a quarter circle + * at most. If "addMoveTo" is true, a PT_MOVETO entry for the first control + * point is added to the path; otherwise, it is assumed that the current + * position is equal to the first control point. + */ +static BOOL PATH_DoArcPart(GdiPath *pPath, FLOAT_POINT corners[], + double angleStart, double angleEnd, BOOL addMoveTo) +{ + double halfAngle, a; + double xNorm[4], yNorm[4]; + POINT point; + int i; + + assert(fabs(angleEnd-angleStart)<=M_PI_2); + + /* FIXME: Is there an easier way of computing this? */ + + /* Compute control points */ + halfAngle=(angleEnd-angleStart)/2.0; + if(fabs(halfAngle)>1e-8) + { + a=4.0/3.0*(1-cos(halfAngle))/sin(halfAngle); + xNorm[0]=cos(angleStart); + yNorm[0]=sin(angleStart); + xNorm[1]=xNorm[0] - a*yNorm[0]; + yNorm[1]=yNorm[0] + a*xNorm[0]; + xNorm[3]=cos(angleEnd); + yNorm[3]=sin(angleEnd); + xNorm[2]=xNorm[3] + a*yNorm[3]; + yNorm[2]=yNorm[3] - a*xNorm[3]; + } else + for(i=0; i<4; i++) + { + xNorm[i]=cos(angleStart); + yNorm[i]=sin(angleStart); + } + + /* Add starting point to path if desired */ + if(addMoveTo) + { + PATH_ScaleNormalizedPoint(corners, xNorm[0], yNorm[0], &point); + if(!PATH_AddEntry(pPath, &point, PT_MOVETO)) + return FALSE; + } + + /* Add remaining control points */ + for(i=1; i<4; i++) + { + PATH_ScaleNormalizedPoint(corners, xNorm[i], yNorm[i], &point); + if(!PATH_AddEntry(pPath, &point, PT_BEZIERTO)) + return FALSE; + } + + return TRUE; +} + +/* PATH_ScaleNormalizedPoint + * + * Scales a normalized point (x, y) with respect to the box whose corners are + * passed in "corners". The point is stored in "*pPoint". The normalized + * coordinates (-1.0, -1.0) correspond to corners[0], the coordinates + * (1.0, 1.0) correspond to corners[1]. + */ +static void PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x, + double y, POINT *pPoint) +{ + pPoint->x=GDI_ROUND( (double)corners[0].x + (double)(corners[1].x-corners[0].x)*0.5*(x+1.0) ); + pPoint->y=GDI_ROUND( (double)corners[0].y + (double)(corners[1].y-corners[0].y)*0.5*(y+1.0) ); +} + +/* PATH_NormalizePoint + * + * Normalizes a point with respect to the box whose corners are passed in + * corners. The normalized coordinates are stored in *pX and *pY. + */ +static void PATH_NormalizePoint(FLOAT_POINT corners[], + const FLOAT_POINT *pPoint, + double *pX, double *pY) +{ + *pX=(double)(pPoint->x-corners[0].x)/(double)(corners[1].x-corners[0].x) * 2.0 - 1.0; + *pY=(double)(pPoint->y-corners[0].y)/(double)(corners[1].y-corners[0].y) * 2.0 - 1.0; +} diff --git a/subsys/win32k/objects/pen.c b/subsys/win32k/objects/pen.c new file mode 100644 index 0000000..d46cc60 --- /dev/null +++ b/subsys/win32k/objects/pen.c @@ -0,0 +1,54 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +// #define NDEBUG +#include + +HPEN +STDCALL +W32kCreatePen(INT PenStyle, INT Width, COLORREF Color) +{ + LOGPEN logpen; + + logpen.lopnStyle = PenStyle; + logpen.lopnWidth.x = Width; + logpen.lopnWidth.y = 0; + logpen.lopnColor = Color; + + return W32kCreatePenIndirect(&logpen); +} + +HPEN +STDCALL +W32kCreatePenIndirect(CONST PLOGPEN lgpn) +{ + PPENOBJ penPtr; + HPEN hpen; + + if (lgpn->lopnStyle > PS_INSIDEFRAME) return 0; + + hpen = PENOBJ_AllocPen(); + if (!hpen) return 0; + + penPtr = PENOBJ_LockPen( hpen ); + ASSERT( penPtr ); + + penPtr->logpen.lopnStyle = lgpn->lopnStyle; + penPtr->logpen.lopnWidth = lgpn->lopnWidth; + penPtr->logpen.lopnColor = lgpn->lopnColor; + PENOBJ_UnlockPen( hpen ); + return hpen; +} + +HPEN +STDCALL +W32kExtCreatePen(DWORD PenStyle, + DWORD Width, + CONST PLOGBRUSH lb, + DWORD StyleCount, + CONST PDWORD Style) +{ + UNIMPLEMENTED; +} diff --git a/subsys/win32k/objects/print.c b/subsys/win32k/objects/print.c new file mode 100644 index 0000000..b8b4528 --- /dev/null +++ b/subsys/win32k/objects/print.c @@ -0,0 +1,75 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +// #define NDEBUG +#include + +INT +STDCALL +W32kAbortDoc(HDC hDC) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kEndDoc(HDC hDC) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kEndPage(HDC hDC) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kEscape(HDC hDC, + INT Escape, + INT InSize, + LPCSTR InData, + LPVOID OutData) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kExtEscape(HDC hDC, + INT Escape, + INT InSize, + LPCSTR InData, + INT OutSize, + LPSTR OutData) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kSetAbortProc(HDC hDC, + ABORTPROC AbortProc) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kStartDoc(HDC hDC, + CONST PDOCINFO di) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kStartPage(HDC hDC) +{ + UNIMPLEMENTED; +} + diff --git a/subsys/win32k/objects/rect.c b/subsys/win32k/objects/rect.c new file mode 100644 index 0000000..3c88969 --- /dev/null +++ b/subsys/win32k/objects/rect.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include + +//#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +BOOL +W32kOffsetRect(LPRECT Rect, INT x, INT y) +{ + Rect->left += x; + Rect->right += x; + Rect->top += y; + Rect->bottom += y; + return(TRUE); +} + + +BOOL STDCALL +W32kUnionRect(PRECT Dest, const RECT* Src1, const RECT* Src2) +{ + if (W32kIsEmptyRect(Src1)) + { + if (W32kIsEmptyRect(Src2)) + { + W32kSetEmptyRect(Dest); + return(FALSE); + } + else + { + *Dest = *Src2; + } + } + else + { + if (W32kIsEmptyRect(Src2)) + { + *Dest = *Src1; + } + else + { + Dest->left = min(Src1->left, Src2->left); + Dest->top = min(Src1->top, Src2->top); + Dest->right = max(Src1->right, Src2->right); + Dest->bottom = max(Src1->bottom, Src2->bottom); + } + } + return(TRUE); +} + +BOOL STDCALL +W32kSetEmptyRect(PRECT Rect) +{ + Rect->left = Rect->right = Rect->top = Rect->bottom = 0; + return(TRUE); +} + +BOOL STDCALL +W32kIsEmptyRect(PRECT Rect) +{ + return(Rect->left >= Rect->right || Rect->top >= Rect->bottom); +} + +BOOL STDCALL +W32kSetRect(PRECT Rect, INT left, INT top, INT right, INT bottom) +{ + Rect->left = left; + Rect->top = top; + Rect->right = right; + Rect->bottom = bottom; + return(TRUE); +} + +BOOL STDCALL +W32kIntersectRect(PRECT Dest, const RECT* Src1, const RECT* Src2) +{ + if (W32kIsEmptyRect(Src1) || W32kIsEmptyRect(Src2) || + Src1->left >= Src2->right || Src2->left >= Src1->right || + Src1->top >= Src2->bottom || Src2->top >= Src1->bottom) + { + W32kSetEmptyRect(Dest); + return(FALSE); + } + Dest->left = max(Src1->left, Src2->left); + Dest->right = min(Src1->right, Src2->right); + Dest->top = max(Src1->top, Src2->top); + Dest->bottom = min(Src1->bottom, Src2->bottom); + return(TRUE); +} diff --git a/subsys/win32k/objects/region.c b/subsys/win32k/objects/region.c new file mode 100644 index 0000000..161b8ad --- /dev/null +++ b/subsys/win32k/objects/region.c @@ -0,0 +1,1990 @@ +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// #define NDEBUG +#include + +BOOL STDCALL +IntEngPaint(IN SURFOBJ *Surface,IN CLIPOBJ *ClipRegion,IN BRUSHOBJ *Brush,IN POINTL *BrushOrigin, + IN MIX Mix); + +// Internal Functions + +#define EMPTY_REGION(pReg) { \ + (pReg)->rdh.nCount = 0; \ + (pReg)->rdh.rcBound.left = (pReg)->rdh.rcBound.top = 0; \ + (pReg)->rdh.rcBound.right = (pReg)->rdh.rcBound.bottom = 0; \ + (pReg)->rdh.iType = NULLREGION; \ +} + +#define REGION_NOT_EMPTY(pReg) pReg->rdh.nCount + +#define INRECT(r, x, y) \ + ( ( ((r).right > x)) && \ + ( ((r).left <= x)) && \ + ( ((r).bottom > y)) && \ + ( ((r).top <= y)) ) + +/* 1 if two RECTs overlap. + * 0 if two RECTs do not overlap. + */ +#define EXTENTCHECK(r1, r2) \ + ((r1)->right > (r2)->left && \ + (r1)->left < (r2)->right && \ + (r1)->bottom > (r2)->top && \ + (r1)->top < (r2)->bottom) + +/* + * Check to see if there is enough memory in the present region. + */ +static inline int xmemcheck(ROSRGNDATA *reg, LPRECT *rect, LPRECT *firstrect ) { + if ( (reg->rdh.nCount+1)*sizeof( RECT ) >= reg->rdh.nRgnSize ) { + PRECT temp; + temp = ExAllocatePool( PagedPool, (2 * (reg->rdh.nRgnSize))); + + if (temp == 0) + return 0; + RtlCopyMemory( temp, *firstrect, reg->rdh.nRgnSize ); + reg->rdh.nRgnSize *= 2; + ExFreePool( *firstrect ); + *firstrect = temp; + *rect = (*firstrect)+reg->rdh.nCount; + } + return 1; +} + +#define MEMCHECK(reg, rect, firstrect) xmemcheck(reg,&(rect),&(firstrect)) + +typedef void (*voidProcp)(); + +// Number of points to buffer before sending them off to scanlines() : Must be an even number +#define NUMPTSTOBUFFER 200 + +#define RGN_DEFAULT_RECTS 2 + +// used to allocate buffers for points and link the buffers together + +typedef struct _POINTBLOCK { + POINT pts[NUMPTSTOBUFFER]; + struct _POINTBLOCK *next; +} POINTBLOCK; + +static BOOL REGION_CopyRegion(PROSRGNDATA dst, PROSRGNDATA src) +{ + if(dst != src) // don't want to copy to itself + { + if (dst->rdh.nRgnSize < src->rdh.nCount * sizeof(RECT)) + { + PCHAR temp; + + temp = ExAllocatePool(PagedPool, src->rdh.nCount * sizeof(RECT) ); + if( !temp ) + return FALSE; + + if( dst->Buffer ) + ExFreePool( dst->Buffer ); //free the old buffer + dst->Buffer = temp; + dst->rdh.nRgnSize = src->rdh.nCount * sizeof(RECT); //size of region buffer + } + dst->rdh.nCount = src->rdh.nCount; //number of rectangles present in Buffer + dst->rdh.rcBound.left = src->rdh.rcBound.left; + dst->rdh.rcBound.top = src->rdh.rcBound.top; + dst->rdh.rcBound.right = src->rdh.rcBound.right; + dst->rdh.rcBound.bottom = src->rdh.rcBound.bottom; + dst->rdh.iType = src->rdh.iType; + RtlCopyMemory(dst->Buffer, src->Buffer, (int)(src->rdh.nCount * sizeof(RECT))); + } + return TRUE; +} + +static void REGION_SetExtents (ROSRGNDATA *pReg) +{ + RECT *pRect, *pRectEnd, *pExtents; + + if (pReg->rdh.nCount == 0) + { + pReg->rdh.rcBound.left = 0; + pReg->rdh.rcBound.top = 0; + pReg->rdh.rcBound.right = 0; + pReg->rdh.rcBound.bottom = 0; + return; + } + + pExtents = &pReg->rdh.rcBound; + pRect = (PRECT)pReg->Buffer; + pRectEnd = (PRECT)pReg->Buffer + pReg->rdh.nCount - 1; + + /* + * Since pRect is the first rectangle in the region, it must have the + * smallest top and since pRectEnd is the last rectangle in the region, + * it must have the largest bottom, because of banding. Initialize left and + * right from pRect and pRectEnd, resp., as good things to initialize them + * to... + */ + pExtents->left = pRect->left; + pExtents->top = pRect->top; + pExtents->right = pRectEnd->right; + pExtents->bottom = pRectEnd->bottom; + + while (pRect <= pRectEnd) + { + if (pRect->left < pExtents->left) + pExtents->left = pRect->left; + if (pRect->right > pExtents->right) + pExtents->right = pRect->right; + pRect++; + } +} + + +/*********************************************************************** + * REGION_CropAndOffsetRegion + */ +static BOOL REGION_CropAndOffsetRegion(const PPOINT off, const PRECT rect, PROSRGNDATA rgnSrc, PROSRGNDATA rgnDst) +{ + if(!rect) // just copy and offset + { + PRECT xrect; + if(rgnDst == rgnSrc) + { + if(off->x || off->y) + xrect = (PRECT)rgnDst->Buffer; + else + return TRUE; + } + else{ + xrect = ExAllocatePool(PagedPool, rgnSrc->rdh.nCount * sizeof(RECT)); + if( rgnDst->Buffer ) + ExFreePool( rgnDst->Buffer ); //free the old buffer. will be assigned to xrect below. + } + + if(xrect) + { + INT i; + + if(rgnDst != rgnSrc) + RtlCopyMemory(rgnDst, rgnSrc, sizeof(ROSRGNDATA)); + + if(off->x || off->y) + { + for(i = 0; i < rgnDst->rdh.nCount; i++) + { + xrect[i].left = ((PRECT)rgnSrc->Buffer + i)->left + off->x; + xrect[i].right = ((PRECT)rgnSrc->Buffer + i)->right + off->x; + xrect[i].top = ((PRECT)rgnSrc->Buffer + i)->top + off->y; + xrect[i].bottom = ((PRECT)rgnSrc->Buffer + i)->bottom + off->y; + } + rgnDst->rdh.rcBound.left += off->x; + rgnDst->rdh.rcBound.right += off->x; + rgnDst->rdh.rcBound.top += off->y; + rgnDst->rdh.rcBound.bottom += off->y; + } + else + RtlCopyMemory(xrect, rgnSrc->Buffer, rgnDst->rdh.nCount * sizeof(RECT)); + + rgnDst->Buffer = (char*)xrect; + } else + return FALSE; + } + else if ((rect->left >= rect->right) || + (rect->top >= rect->bottom) || + !EXTENTCHECK(rect, &rgnSrc->rdh.rcBound)) + { + goto empty; + } + else // region box and clipping rect appear to intersect + { + PRECT lpr, rpr; + INT i, j, clipa, clipb; + INT left = rgnSrc->rdh.rcBound.right + off->x; + INT right = rgnSrc->rdh.rcBound.left + off->x; + + for(clipa = 0; ((PRECT)rgnSrc->Buffer + clipa)->bottom <= rect->top; clipa++) + //region and rect intersect so we stop before clipa > rgnSrc->rdh.nCount + ; // skip bands above the clipping rectangle + + for(clipb = clipa; clipb < rgnSrc->rdh.nCount; clipb++) + if(((PRECT)rgnSrc->Buffer + clipb)->top >= rect->bottom) + break; // and below it + + // clipa - index of the first rect in the first intersecting band + // clipb - index of the last rect in the last intersecting band + + if((rgnDst != rgnSrc) && (rgnDst->rdh.nCount < (i = (clipb - clipa)))) + { + PCHAR temp; + temp = ExAllocatePool( PagedPool, i * sizeof(RECT) ); + if(!temp) + return FALSE; + + if( rgnDst->Buffer ) + ExFreePool( rgnDst->Buffer ); //free the old buffer + (PRECT)rgnDst->Buffer = temp; + rgnDst->rdh.nCount = i; + rgnDst->rdh.nRgnSize = i * sizeof(RECT); + } + + for(i = clipa, j = 0; i < clipb ; i++) + { + // i - src index, j - dst index, j is always <= i for obvious reasons + + lpr = (PRECT)rgnSrc->Buffer + i; + + if(lpr->left < rect->right && lpr->right > rect->left) + { + rpr = (PRECT)rgnDst->Buffer + j; + + rpr->top = lpr->top + off->y; + rpr->bottom = lpr->bottom + off->y; + rpr->left = ((lpr->left > rect->left) ? lpr->left : rect->left) + off->x; + rpr->right = ((lpr->right < rect->right) ? lpr->right : rect->right) + off->x; + + if(rpr->left < left) left = rpr->left; + if(rpr->right > right) right = rpr->right; + + j++; + } + } + + if(j == 0) goto empty; + + rgnDst->rdh.rcBound.left = left; + rgnDst->rdh.rcBound.right = right; + + left = rect->top + off->y; + right = rect->bottom + off->y; + + rgnDst->rdh.nCount = j--; + for(i = 0; i <= j; i++) // fixup top band + if(((PRECT)rgnDst->Buffer + i)->top < left) + ((PRECT)rgnDst->Buffer + i)->top = left; + else + break; + + for(i = j; i >= 0; i--) // fixup bottom band + if(((PRECT)rgnDst->Buffer + i)->bottom > right) + ((PRECT)rgnDst->Buffer + i)->bottom = right; + else + break; + + rgnDst->rdh.rcBound.top = ((PRECT)rgnDst->Buffer)->top; + rgnDst->rdh.rcBound.bottom = ((PRECT)rgnDst->Buffer + j)->bottom; + + rgnDst->rdh.iType = (j >= 1) ? COMPLEXREGION : SIMPLEREGION; + } + + return TRUE; + +empty: + if(!rgnDst->Buffer) + { + rgnDst->Buffer = (char*)ExAllocatePool(PagedPool, RGN_DEFAULT_RECTS * sizeof(RECT)); + if(rgnDst->Buffer){ + rgnDst->rdh.nCount = RGN_DEFAULT_RECTS; + rgnDst->rdh.nRgnSize = RGN_DEFAULT_RECTS * sizeof(RECT); + } + else + return FALSE; + } + EMPTY_REGION(rgnDst); + return TRUE; +} + +/*********************************************************************** + * REGION_CropRgn + * + * + * hSrc: Region to crop and offset. + * lpRect: Clipping rectangle. Can be NULL (no clipping). + * lpPt: Points to offset the cropped region. Can be NULL (no offset). + * + * hDst: Region to hold the result (a new region is created if it's 0). + * Allowed to be the same region as hSrc in which case everything + * will be done in place, with no memory reallocations. + * + * Returns: hDst if success, 0 otherwise. + */ +HRGN REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpPt) +{ + PROSRGNDATA objSrc = RGNDATA_LockRgn(hSrc); + HRGN hNewDst; + + if(objSrc) + { + PROSRGNDATA rgnDst; + + if(hDst) + { + if(!(rgnDst = RGNDATA_LockRgn(hDst))) + { + hDst = 0; + goto done; + } + } + else{ + if( !( hNewDst = RGNDATA_AllocRgn(1) ) ){ + RGNDATA_UnlockRgn( hSrc ); + return 0; + } + + if(!(rgnDst = RGNDATA_LockRgn(hNewDst))) + { + RGNDATA_FreeRgn( hNewDst ); + RGNDATA_UnlockRgn( hSrc ); + return 0; + } + } + + if(rgnDst) + { + POINT pt = { 0, 0 }; + + if(!lpPt) + lpPt = &pt; + + if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) == FALSE) + { // ve failed cleanup and return + RGNDATA_UnlockRgn( hSrc ); + + if(hDst) // unlock new region if allocated + RGNDATA_UnlockRgn( hDst ); + else + RGNDATA_UnlockRgn( hNewDst ); + + return 0; + } + else{ // ve are fine. unlock the correct pointer and return correct handle + RGNDATA_UnlockRgn( hSrc ); + + if(hDst == 0){ + RGNDATA_UnlockRgn( hNewDst ); + return hNewDst; + } + else { + RGNDATA_UnlockRgn( hDst ); + return hDst; + } + } + } +done: + RGNDATA_UnlockRgn( hSrc ); + } + return 0; +} + +/*********************************************************************** + * REGION_Coalesce + * + * Attempt to merge the rects in the current band with those in the + * previous one. Used only by REGION_RegionOp. + * + * Results: + * The new index for the previous band. + * + * Side Effects: + * If coalescing takes place: + * - rectangles in the previous band will have their bottom fields + * altered. + * - pReg->numRects will be decreased. + * + */ +static INT REGION_Coalesce ( + PROSRGNDATA pReg, /* Region to coalesce */ + INT prevStart, /* Index of start of previous band */ + INT curStart /* Index of start of current band */ +) { + RECT *pPrevRect; /* Current rect in previous band */ + RECT *pCurRect; /* Current rect in current band */ + RECT *pRegEnd; /* End of region */ + INT curNumRects; /* Number of rectangles in current band */ + INT prevNumRects; /* Number of rectangles in previous band */ + INT bandtop; /* top coordinate for current band */ + + pRegEnd = (PRECT)pReg->Buffer + pReg->rdh.nCount; + pPrevRect = (PRECT)pReg->Buffer + prevStart; + prevNumRects = curStart - prevStart; + + /* + * Figure out how many rectangles are in the current band. Have to do + * this because multiple bands could have been added in REGION_RegionOp + * at the end when one region has been exhausted. + */ + pCurRect = (PRECT)pReg->Buffer + curStart; + bandtop = pCurRect->top; + for (curNumRects = 0; + (pCurRect != pRegEnd) && (pCurRect->top == bandtop); + curNumRects++) + { + pCurRect++; + } + + if (pCurRect != pRegEnd) + { + /* + * If more than one band was added, we have to find the start + * of the last band added so the next coalescing job can start + * at the right place... (given when multiple bands are added, + * this may be pointless -- see above). + */ + pRegEnd--; + while ((pRegEnd-1)->top == pRegEnd->top) + { + pRegEnd--; + } + curStart = pRegEnd - (PRECT)pReg->Buffer; + pRegEnd = (PRECT)pReg->Buffer + pReg->rdh.nCount; + } + + if ((curNumRects == prevNumRects) && (curNumRects != 0)) { + pCurRect -= curNumRects; + /* + * The bands may only be coalesced if the bottom of the previous + * matches the top scanline of the current. + */ + if (pPrevRect->bottom == pCurRect->top) + { + /* + * Make sure the bands have rects in the same places. This + * assumes that rects have been added in such a way that they + * cover the most area possible. I.e. two rects in a band must + * have some horizontal space between them. + */ + do + { + if ((pPrevRect->left != pCurRect->left) || + (pPrevRect->right != pCurRect->right)) + { + /* + * The bands don't line up so they can't be coalesced. + */ + return (curStart); + } + pPrevRect++; + pCurRect++; + prevNumRects -= 1; + } while (prevNumRects != 0); + + pReg->rdh.nCount -= curNumRects; + pCurRect -= curNumRects; + pPrevRect -= curNumRects; + + /* + * The bands may be merged, so set the bottom of each rect + * in the previous band to that of the corresponding rect in + * the current band. + */ + do + { + pPrevRect->bottom = pCurRect->bottom; + pPrevRect++; + pCurRect++; + curNumRects -= 1; + } while (curNumRects != 0); + + /* + * If only one band was added to the region, we have to backup + * curStart to the start of the previous band. + * + * If more than one band was added to the region, copy the + * other bands down. The assumption here is that the other bands + * came from the same region as the current one and no further + * coalescing can be done on them since it's all been done + * already... curStart is already in the right place. + */ + if (pCurRect == pRegEnd) + { + curStart = prevStart; + } + else + { + do + { + *pPrevRect++ = *pCurRect++; + } while (pCurRect != pRegEnd); + } + } + } + return (curStart); +} + +/*********************************************************************** + * REGION_RegionOp + * + * Apply an operation to two regions. Called by REGION_Union, + * REGION_Inverse, REGION_Subtract, REGION_Intersect... + * + * Results: + * None. + * + * Side Effects: + * The new region is overwritten. + * + * Notes: + * The idea behind this function is to view the two regions as sets. + * Together they cover a rectangle of area that this function divides + * into horizontal bands where points are covered only by one region + * or by both. For the first case, the nonOverlapFunc is called with + * each the band and the band's upper and lower extents. For the + * second, the overlapFunc is called to process the entire band. It + * is responsible for clipping the rectangles in the band, though + * this function provides the boundaries. + * At the end of each band, the new region is coalesced, if possible, + * to reduce the number of rectangles in the region. + * + */ +static void REGION_RegionOp( + ROSRGNDATA *newReg, /* Place to store result */ + ROSRGNDATA *reg1, /* First region in operation */ + ROSRGNDATA *reg2, /* 2nd region in operation */ + void (*overlapFunc)(), /* Function to call for over-lapping bands */ + void (*nonOverlap1Func)(), /* Function to call for non-overlapping bands in region 1 */ + void (*nonOverlap2Func)() /* Function to call for non-overlapping bands in region 2 */ +) { + RECT *r1; /* Pointer into first region */ + RECT *r2; /* Pointer into 2d region */ + RECT *r1End; /* End of 1st region */ + RECT *r2End; /* End of 2d region */ + INT ybot; /* Bottom of intersection */ + INT ytop; /* Top of intersection */ + RECT *oldRects; /* Old rects for newReg */ + INT prevBand; /* Index of start of + * previous band in newReg */ + INT curBand; /* Index of start of current + * band in newReg */ + RECT *r1BandEnd; /* End of current band in r1 */ + RECT *r2BandEnd; /* End of current band in r2 */ + INT top; /* Top of non-overlapping band */ + INT bot; /* Bottom of non-overlapping band */ + + /* + * Initialization: + * set r1, r2, r1End and r2End appropriately, preserve the important + * parts of the destination region until the end in case it's one of + * the two source regions, then mark the "new" region empty, allocating + * another array of rectangles for it to use. + */ + r1 = (PRECT)reg1->Buffer; + r2 = (PRECT)reg2->Buffer; + r1End = r1 + reg1->rdh.nCount; + r2End = r2 + reg2->rdh.nCount; + + + /* + * newReg may be one of the src regions so we can't empty it. We keep a + * note of its rects pointer (so that we can free them later), preserve its + * extents and simply set numRects to zero. + */ + + oldRects = (PRECT)newReg->Buffer; + newReg->rdh.nCount = 0; + + /* + * Allocate a reasonable number of rectangles for the new region. The idea + * is to allocate enough so the individual functions don't need to + * reallocate and copy the array, which is time consuming, yet we don't + * have to worry about using too much memory. I hope to be able to + * nuke the Xrealloc() at the end of this function eventually. + */ + newReg->rdh.nRgnSize = max(reg1->rdh.nCount,reg2->rdh.nCount) * 2 * sizeof(RECT); + + if (! (newReg->Buffer = ExAllocatePool( PagedPool, newReg->rdh.nRgnSize ))) + { + newReg->rdh.nRgnSize = 0; + return; + } + + /* + * Initialize ybot and ytop. + * In the upcoming loop, ybot and ytop serve different functions depending + * on whether the band being handled is an overlapping or non-overlapping + * band. + * In the case of a non-overlapping band (only one of the regions + * has points in the band), ybot is the bottom of the most recent + * intersection and thus clips the top of the rectangles in that band. + * ytop is the top of the next intersection between the two regions and + * serves to clip the bottom of the rectangles in the current band. + * For an overlapping band (where the two regions intersect), ytop clips + * the top of the rectangles of both regions and ybot clips the bottoms. + */ + if (reg1->rdh.rcBound.top < reg2->rdh.rcBound.top) + ybot = reg1->rdh.rcBound.top; + else + ybot = reg2->rdh.rcBound.top; + + /* + * prevBand serves to mark the start of the previous band so rectangles + * can be coalesced into larger rectangles. qv. miCoalesce, above. + * In the beginning, there is no previous band, so prevBand == curBand + * (curBand is set later on, of course, but the first band will always + * start at index 0). prevBand and curBand must be indices because of + * the possible expansion, and resultant moving, of the new region's + * array of rectangles. + */ + prevBand = 0; + + do + { + curBand = newReg->rdh.nCount; + + /* + * This algorithm proceeds one source-band (as opposed to a + * destination band, which is determined by where the two regions + * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the + * rectangle after the last one in the current band for their + * respective regions. + */ + r1BandEnd = r1; + while ((r1BandEnd != r1End) && (r1BandEnd->top == r1->top)) + { + r1BandEnd++; + } + + r2BandEnd = r2; + while ((r2BandEnd != r2End) && (r2BandEnd->top == r2->top)) + { + r2BandEnd++; + } + + /* + * First handle the band that doesn't intersect, if any. + * + * Note that attention is restricted to one band in the + * non-intersecting region at once, so if a region has n + * bands between the current position and the next place it overlaps + * the other, this entire loop will be passed through n times. + */ + if (r1->top < r2->top) + { + top = max(r1->top,ybot); + bot = min(r1->bottom,r2->top); + + if ((top != bot) && (nonOverlap1Func != (void (*)())NULL)) + { + (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot); + } + + ytop = r2->top; + } + else if (r2->top < r1->top) + { + top = max(r2->top,ybot); + bot = min(r2->bottom,r1->top); + + if ((top != bot) && (nonOverlap2Func != (void (*)())NULL)) + { + (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot); + } + + ytop = r1->top; + } + else + { + ytop = r1->top; + } + + /* + * If any rectangles got added to the region, try and coalesce them + * with rectangles from the previous band. Note we could just do + * this test in miCoalesce, but some machines incur a not + * inconsiderable cost for function calls, so... + */ + if (newReg->rdh.nCount != curBand) + { + prevBand = REGION_Coalesce (newReg, prevBand, curBand); + } + + /* + * Now see if we've hit an intersecting band. The two bands only + * intersect if ybot > ytop + */ + ybot = min(r1->bottom, r2->bottom); + curBand = newReg->rdh.nCount; + if (ybot > ytop) + { + (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); + } + + if (newReg->rdh.nCount != curBand) + { + prevBand = REGION_Coalesce (newReg, prevBand, curBand); + } + + /* + * If we've finished with a band (bottom == ybot) we skip forward + * in the region to the next band. + */ + if (r1->bottom == ybot) + { + r1 = r1BandEnd; + } + if (r2->bottom == ybot) + { + r2 = r2BandEnd; + } + } while ((r1 != r1End) && (r2 != r2End)); + + /* + * Deal with whichever region still has rectangles left. + */ + curBand = newReg->rdh.nCount; + if (r1 != r1End) + { + if (nonOverlap1Func != (void (*)())NULL) + { + do + { + r1BandEnd = r1; + while ((r1BandEnd < r1End) && (r1BandEnd->top == r1->top)) + { + r1BandEnd++; + } + (* nonOverlap1Func) (newReg, r1, r1BandEnd, + max(r1->top,ybot), r1->bottom); + r1 = r1BandEnd; + } while (r1 != r1End); + } + } + else if ((r2 != r2End) && (nonOverlap2Func != (void (*)())NULL)) + { + do + { + r2BandEnd = r2; + while ((r2BandEnd < r2End) && (r2BandEnd->top == r2->top)) + { + r2BandEnd++; + } + (* nonOverlap2Func) (newReg, r2, r2BandEnd, + max(r2->top,ybot), r2->bottom); + r2 = r2BandEnd; + } while (r2 != r2End); + } + + if (newReg->rdh.nCount != curBand) + { + (void) REGION_Coalesce (newReg, prevBand, curBand); + } + + /* + * A bit of cleanup. To keep regions from growing without bound, + * we shrink the array of rectangles to match the new number of + * rectangles in the region. This never goes to 0, however... + * + * Only do this stuff if the number of rectangles allocated is more than + * twice the number of rectangles in the region (a simple optimization...). + */ + if ((newReg->rdh.nCount*sizeof(RECT) < 2*newReg->rdh.nRgnSize && (newReg->rdh.nCount > 2))) + { + if (REGION_NOT_EMPTY(newReg)) + { + RECT *prev_rects = (PRECT)newReg->Buffer; + newReg->Buffer = ExAllocatePool( PagedPool, newReg->rdh.nCount*sizeof(RECT) ); + + if (! newReg->Buffer) + newReg->Buffer = (char*)prev_rects; + else{ + newReg->rdh.nRgnSize = newReg->rdh.nCount*sizeof(RECT); + RtlCopyMemory( newReg->Buffer, prev_rects, newReg->rdh.nRgnSize ); + ExFreePool( prev_rects ); + } + } + else + { + /* + * No point in doing the extra work involved in an Xrealloc if + * the region is empty + */ + newReg->rdh.nRgnSize = sizeof(RECT); + ExFreePool( newReg->Buffer ); + newReg->Buffer = ExAllocatePool( PagedPool, sizeof(RECT) ); + ASSERT( newReg->Buffer ); + } + } + + if( newReg->rdh.nCount == 0 ) + newReg->rdh.iType = NULLREGION; + else + newReg->rdh.iType = (newReg->rdh.nCount > 1)? COMPLEXREGION : SIMPLEREGION; + + ExFreePool( oldRects ); + return; +} + +/*********************************************************************** + * Region Intersection + ***********************************************************************/ + + +/*********************************************************************** + * REGION_IntersectO + * + * Handle an overlapping band for REGION_Intersect. + * + * Results: + * None. + * + * Side Effects: + * Rectangles may be added to the region. + * + */ +static void REGION_IntersectO(ROSRGNDATA *pReg, RECT *r1, RECT *r1End, + RECT *r2, RECT *r2End, INT top, INT bottom) + +{ + INT left, right; + RECT *pNextRect; + + pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount; + + while ((r1 != r1End) && (r2 != r2End)) + { + left = max(r1->left, r2->left); + right = min(r1->right, r2->right); + + /* + * If there's any overlap between the two rectangles, add that + * overlap to the new region. + * There's no need to check for subsumption because the only way + * such a need could arise is if some region has two rectangles + * right next to each other. Since that should never happen... + */ + if (left < right) + { + MEMCHECK(pReg, pNextRect, pReg->Buffer); + pNextRect->left = left; + pNextRect->top = top; + pNextRect->right = right; + pNextRect->bottom = bottom; + pReg->rdh.nCount += 1; + pNextRect++; + } + + /* + * Need to advance the pointers. Shift the one that extends + * to the right the least, since the other still has a chance to + * overlap with that region's next rectangle, if you see what I mean. + */ + if (r1->right < r2->right) + { + r1++; + } + else if (r2->right < r1->right) + { + r2++; + } + else + { + r1++; + r2++; + } + } + return; +} + +/*********************************************************************** + * REGION_IntersectRegion + */ +static void REGION_IntersectRegion(ROSRGNDATA *newReg, ROSRGNDATA *reg1, + ROSRGNDATA *reg2) +{ + /* check for trivial reject */ + if ( (!(reg1->rdh.nCount)) || (!(reg2->rdh.nCount)) || + (!EXTENTCHECK(®1->rdh.rcBound, ®2->rdh.rcBound))) + newReg->rdh.nCount = 0; + else + REGION_RegionOp (newReg, reg1, reg2, + (voidProcp) REGION_IntersectO, (voidProcp) NULL, (voidProcp) NULL); + + /* + * Can't alter newReg's extents before we call miRegionOp because + * it might be one of the source regions and miRegionOp depends + * on the extents of those regions being the same. Besides, this + * way there's no checking against rectangles that will be nuked + * due to coalescing, so we have to examine fewer rectangles. + */ + + REGION_SetExtents(newReg); +} + +/*********************************************************************** + * Region Union + ***********************************************************************/ + +/*********************************************************************** + * REGION_UnionNonO + * + * Handle a non-overlapping band for the union operation. Just + * Adds the rectangles into the region. Doesn't have to check for + * subsumption or anything. + * + * Results: + * None. + * + * Side Effects: + * pReg->numRects is incremented and the final rectangles overwritten + * with the rectangles we're passed. + * + */ +static void REGION_UnionNonO (ROSRGNDATA *pReg, RECT *r, RECT *rEnd, + INT top, INT bottom) +{ + RECT *pNextRect; + + pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount; + + while (r != rEnd) + { + MEMCHECK(pReg, pNextRect, pReg->Buffer); + pNextRect->left = r->left; + pNextRect->top = top; + pNextRect->right = r->right; + pNextRect->bottom = bottom; + pReg->rdh.nCount += 1; + pNextRect++; + r++; + } + return; +} + +/*********************************************************************** + * REGION_UnionO + * + * Handle an overlapping band for the union operation. Picks the + * left-most rectangle each time and merges it into the region. + * + * Results: + * None. + * + * Side Effects: + * Rectangles are overwritten in pReg->rects and pReg->numRects will + * be changed. + * + */ +static void REGION_UnionO (ROSRGNDATA *pReg, RECT *r1, RECT *r1End, + RECT *r2, RECT *r2End, INT top, INT bottom) +{ + RECT *pNextRect; + + pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount; + +#define MERGERECT(r) \ + if ((pReg->rdh.nCount != 0) && \ + ((pNextRect-1)->top == top) && \ + ((pNextRect-1)->bottom == bottom) && \ + ((pNextRect-1)->right >= r->left)) \ + { \ + if ((pNextRect-1)->right < r->right) \ + { \ + (pNextRect-1)->right = r->right; \ + } \ + } \ + else \ + { \ + MEMCHECK(pReg, pNextRect, pReg->Buffer); \ + pNextRect->top = top; \ + pNextRect->bottom = bottom; \ + pNextRect->left = r->left; \ + pNextRect->right = r->right; \ + pReg->rdh.nCount += 1; \ + pNextRect += 1; \ + } \ + r++; + + while ((r1 != r1End) && (r2 != r2End)) + { + if (r1->left < r2->left) + { + MERGERECT(r1); + } + else + { + MERGERECT(r2); + } + } + + if (r1 != r1End) + { + do + { + MERGERECT(r1); + } while (r1 != r1End); + } + else while (r2 != r2End) + { + MERGERECT(r2); + } + return; +} + +/*********************************************************************** + * REGION_UnionRegion + */ +static void REGION_UnionRegion(ROSRGNDATA *newReg, ROSRGNDATA *reg1, + ROSRGNDATA *reg2) +{ + /* checks all the simple cases */ + + /* + * Region 1 and 2 are the same or region 1 is empty + */ + if ( (reg1 == reg2) || (!(reg1->rdh.nCount)) ) + { + if (newReg != reg2) + REGION_CopyRegion(newReg, reg2); + return; + } + + /* + * if nothing to union (region 2 empty) + */ + if (!(reg2->rdh.nCount)) + { + if (newReg != reg1) + REGION_CopyRegion(newReg, reg1); + return; + } + + /* + * Region 1 completely subsumes region 2 + */ + if ((reg1->rdh.nCount == 1) && + (reg1->rdh.rcBound.left <= reg2->rdh.rcBound.left) && + (reg1->rdh.rcBound.top <= reg2->rdh.rcBound.top) && + (reg1->rdh.rcBound.right >= reg2->rdh.rcBound.right) && + (reg1->rdh.rcBound.bottom >= reg2->rdh.rcBound.bottom)) + { + if (newReg != reg1) + REGION_CopyRegion(newReg, reg1); + return; + } + + /* + * Region 2 completely subsumes region 1 + */ + if ((reg2->rdh.nCount == 1) && + (reg2->rdh.rcBound.left <= reg1->rdh.rcBound.left) && + (reg2->rdh.rcBound.top <= reg1->rdh.rcBound.top) && + (reg2->rdh.rcBound.right >= reg1->rdh.rcBound.right) && + (reg2->rdh.rcBound.bottom >= reg1->rdh.rcBound.bottom)) + { + if (newReg != reg2) + REGION_CopyRegion(newReg, reg2); + return; + } + + REGION_RegionOp (newReg, reg1, reg2, (voidProcp) REGION_UnionO, + (voidProcp) REGION_UnionNonO, (voidProcp) REGION_UnionNonO); + newReg->rdh.rcBound.left = min(reg1->rdh.rcBound.left, reg2->rdh.rcBound.left); + newReg->rdh.rcBound.top = min(reg1->rdh.rcBound.top, reg2->rdh.rcBound.top); + newReg->rdh.rcBound.right = max(reg1->rdh.rcBound.right, reg2->rdh.rcBound.right); + newReg->rdh.rcBound.bottom = max(reg1->rdh.rcBound.bottom, reg2->rdh.rcBound.bottom); +} + +/*********************************************************************** + * Region Subtraction + ***********************************************************************/ + +/*********************************************************************** + * REGION_SubtractNonO1 + * + * Deal with non-overlapping band for subtraction. Any parts from + * region 2 we discard. Anything from region 1 we add to the region. + * + * Results: + * None. + * + * Side Effects: + * pReg may be affected. + * + */ +static void REGION_SubtractNonO1 (ROSRGNDATA *pReg, RECT *r, RECT *rEnd, + INT top, INT bottom) +{ + RECT *pNextRect; + + pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount; + + while (r != rEnd) + { + MEMCHECK(pReg, pNextRect, pReg->Buffer); + pNextRect->left = r->left; + pNextRect->top = top; + pNextRect->right = r->right; + pNextRect->bottom = bottom; + pReg->rdh.nCount += 1; + pNextRect++; + r++; + } + return; +} + + +/*********************************************************************** + * REGION_SubtractO + * + * Overlapping band subtraction. x1 is the left-most point not yet + * checked. + * + * Results: + * None. + * + * Side Effects: + * pReg may have rectangles added to it. + * + */ +static void REGION_SubtractO (ROSRGNDATA *pReg, RECT *r1, RECT *r1End, + RECT *r2, RECT *r2End, INT top, INT bottom) +{ + RECT *pNextRect; + INT left; + + left = r1->left; + pNextRect = (PRECT)pReg->Buffer + pReg->rdh.nCount; + + while ((r1 != r1End) && (r2 != r2End)) + { + if (r2->right <= left) + { + /* + * Subtrahend missed the boat: go to next subtrahend. + */ + r2++; + } + else if (r2->left <= left) + { + /* + * Subtrahend preceeds minuend: nuke left edge of minuend. + */ + left = r2->right; + if (left >= r1->right) + { + /* + * Minuend completely covered: advance to next minuend and + * reset left fence to edge of new minuend. + */ + r1++; + if (r1 != r1End) + left = r1->left; + } + else + { + /* + * Subtrahend now used up since it doesn't extend beyond + * minuend + */ + r2++; + } + } + else if (r2->left < r1->right) + { + /* + * Left part of subtrahend covers part of minuend: add uncovered + * part of minuend to region and skip to next subtrahend. + */ + MEMCHECK(pReg, pNextRect, pReg->Buffer); + pNextRect->left = left; + pNextRect->top = top; + pNextRect->right = r2->left; + pNextRect->bottom = bottom; + pReg->rdh.nCount += 1; + pNextRect++; + left = r2->right; + if (left >= r1->right) + { + /* + * Minuend used up: advance to new... + */ + r1++; + if (r1 != r1End) + left = r1->left; + } + else + { + /* + * Subtrahend used up + */ + r2++; + } + } + else + { + /* + * Minuend used up: add any remaining piece before advancing. + */ + if (r1->right > left) + { + MEMCHECK(pReg, pNextRect, pReg->Buffer); + pNextRect->left = left; + pNextRect->top = top; + pNextRect->right = r1->right; + pNextRect->bottom = bottom; + pReg->rdh.nCount += 1; + pNextRect++; + } + r1++; + left = r1->left; + } + } + + /* + * Add remaining minuend rectangles to region. + */ + while (r1 != r1End) + { + MEMCHECK(pReg, pNextRect, pReg->Buffer); + pNextRect->left = left; + pNextRect->top = top; + pNextRect->right = r1->right; + pNextRect->bottom = bottom; + pReg->rdh.nCount += 1; + pNextRect++; + r1++; + if (r1 != r1End) + { + left = r1->left; + } + } + return; +} + +/*********************************************************************** + * REGION_SubtractRegion + * + * Subtract regS from regM and leave the result in regD. + * S stands for subtrahend, M for minuend and D for difference. + * + * Results: + * TRUE. + * + * Side Effects: + * regD is overwritten. + * + */ +static void REGION_SubtractRegion(ROSRGNDATA *regD, ROSRGNDATA *regM, + ROSRGNDATA *regS ) +{ + /* check for trivial reject */ + if ( (!(regM->rdh.nCount)) || (!(regS->rdh.nCount)) || + (!EXTENTCHECK(®M->rdh.rcBound, ®S->rdh.rcBound)) ) + { + REGION_CopyRegion(regD, regM); + return; + } + + REGION_RegionOp (regD, regM, regS, (voidProcp) REGION_SubtractO, + (voidProcp) REGION_SubtractNonO1, (voidProcp) NULL); + + /* + * Can't alter newReg's extents before we call miRegionOp because + * it might be one of the source regions and miRegionOp depends + * on the extents of those regions being the unaltered. Besides, this + * way there's no checking against rectangles that will be nuked + * due to coalescing, so we have to examine fewer rectangles. + */ + REGION_SetExtents (regD); +} + +/*********************************************************************** + * REGION_XorRegion + */ +static void REGION_XorRegion(ROSRGNDATA *dr, ROSRGNDATA *sra, + ROSRGNDATA *srb) +{ + HRGN htra, htrb; + ROSRGNDATA *tra, *trb; + + if ((! (htra = RGNDATA_AllocRgn(sra->rdh.nCount + 1))) || + (! (htrb = RGNDATA_AllocRgn(srb->rdh.nCount + 1)))) + return; + tra = RGNDATA_LockRgn( htra ); + if( !tra ){ + W32kDeleteObject( htra ); + W32kDeleteObject( htrb ); + return; + } + + trb = RGNDATA_LockRgn( htrb ); + if( !trb ){ + RGNDATA_UnlockRgn( htra ); + W32kDeleteObject( htra ); + W32kDeleteObject( htrb ); + return; + } + + REGION_SubtractRegion(tra,sra,srb); + REGION_SubtractRegion(trb,srb,sra); + REGION_UnionRegion(dr,tra,trb); + RGNDATA_UnlockRgn( htra ); + RGNDATA_UnlockRgn( htrb ); + + W32kDeleteObject( htra ); + W32kDeleteObject( htrb ); + return; +} + + +/*********************************************************************** + * REGION_UnionRectWithRegion + * Adds a rectangle to a WINEREGION + */ +static void REGION_UnionRectWithRegion(const RECT *rect, ROSRGNDATA *rgn) +{ + ROSRGNDATA region; + + region.Buffer = (char*)(&(region.rdh.rcBound)); + region.rdh.nCount = 1; + region.rdh.nRgnSize = sizeof( RECT ); + region.rdh.rcBound = *rect; + REGION_UnionRegion(rgn, rgn, ®ion); +} + + +BOOL REGION_LPTODP(HDC hdc, HRGN hDest, HRGN hSrc) +{ + RECT *pCurRect, *pEndRect; + PROSRGNDATA srcObj = NULL; + PROSRGNDATA destObj = NULL; + + DC * dc = DC_HandleToPtr(hdc); + RECT tmpRect; + BOOL ret = FALSE; + + if(!dc) + return ret; + + if(dc->w.MapMode == MM_TEXT) // Requires only a translation + { + if(W32kCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR) + goto done; + + W32kOffsetRgn(hDest, dc->vportOrgX - dc->wndOrgX, dc->vportOrgY - dc->wndOrgY); + ret = TRUE; + goto done; + } + + if(!( srcObj = (PROSRGNDATA) RGNDATA_LockRgn( hSrc ) )) + goto done; + if(!( destObj = (PROSRGNDATA) RGNDATA_LockRgn( hDest ) )) + { + RGNDATA_UnlockRgn( hSrc ); + goto done; + } + EMPTY_REGION(destObj); + + pEndRect = (PRECT)srcObj->Buffer + srcObj->rdh.nCount; + for(pCurRect = (PRECT)srcObj->Buffer; pCurRect < pEndRect; pCurRect++) + { + tmpRect = *pCurRect; + tmpRect.left = XLPTODP(dc, tmpRect.left); + tmpRect.top = YLPTODP(dc, tmpRect.top); + tmpRect.right = XLPTODP(dc, tmpRect.right); + tmpRect.bottom = YLPTODP(dc, tmpRect.bottom); + + if(tmpRect.left > tmpRect.right) + { INT tmp = tmpRect.left; tmpRect.left = tmpRect.right; tmpRect.right = tmp; } + if(tmpRect.top > tmpRect.bottom) + { INT tmp = tmpRect.top; tmpRect.top = tmpRect.bottom; tmpRect.bottom = tmp; } + + REGION_UnionRectWithRegion(&tmpRect, destObj); + } + ret = TRUE; + + RGNDATA_UnlockRgn( hSrc ); + RGNDATA_UnlockRgn( hDest ); + +done: + DC_ReleasePtr( hdc ); + return ret; +} + +HRGN RGNDATA_AllocRgn(INT n) +{ + HRGN hReg; + PROSRGNDATA pReg; + BOOL bRet; + + if((hReg = (HRGN)GDIOBJ_AllocObj(sizeof(ROSRGNDATA), GO_REGION_MAGIC))){ + if( (pReg = GDIOBJ_LockObj( hReg, GO_REGION_MAGIC )) ){ + + if ((pReg->Buffer = ExAllocatePool(PagedPool, n * sizeof(RECT)))){ + EMPTY_REGION(pReg); + pReg->rdh.dwSize = sizeof(RGNDATAHEADER); + pReg->rdh.nCount = n; + pReg->rdh.nRgnSize = n*sizeof(RECT); + + bRet = GDIOBJ_UnlockObj( hReg, GO_REGION_MAGIC ); + ASSERT(bRet); + + return hReg; + } + + } + else + GDIOBJ_FreeObj( hReg, GO_REGION_MAGIC, GDIOBJFLAG_DEFAULT ); + } + return NULL; +} + +BOOL RGNDATA_InternalDelete( PROSRGNDATA pRgn ) +{ + ASSERT(pRgn); + if(pRgn->Buffer) + ExFreePool(pRgn->Buffer); + return TRUE; +} + +// W32k Exported Functions +INT +STDCALL +W32kCombineRgn(HRGN hDest, + HRGN hSrc1, + HRGN hSrc2, + INT CombineMode) +{ + INT result = ERROR; + PROSRGNDATA destRgn = RGNDATA_LockRgn(hDest); + + if( destRgn ){ + PROSRGNDATA src1Rgn = RGNDATA_LockRgn(hSrc1); + + if( src1Rgn ){ + if (CombineMode == RGN_COPY) + { + if( !REGION_CopyRegion(destRgn, src1Rgn) ) + return ERROR; + result = destRgn->rdh.iType; + } + else + { + PROSRGNDATA src2Rgn = RGNDATA_LockRgn(hSrc2); + if( src2Rgn ){ + switch (CombineMode) + { + case RGN_AND: + REGION_IntersectRegion(destRgn, src1Rgn, src2Rgn); + break; + case RGN_OR: + REGION_UnionRegion(destRgn, src1Rgn, src2Rgn); + break; + case RGN_XOR: + REGION_XorRegion(destRgn, src1Rgn, src2Rgn); + break; + case RGN_DIFF: + REGION_SubtractRegion(destRgn, src1Rgn, src2Rgn); + break; + } + result = destRgn->rdh.iType; + RGNDATA_UnlockRgn( hSrc2 ); + } + RGNDATA_UnlockRgn( hSrc1 ); + } + RGNDATA_UnlockRgn( hDest ); + } + else{ + DPRINT("W32kCombineRgn: hDest unavailable\n"); + return ERROR; + } + } + return result; +} + +HRGN +STDCALL +W32kCreateEllipticRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect) +{ + UNIMPLEMENTED; +} + +HRGN +STDCALL +W32kCreateEllipticRgnIndirect(CONST PRECT rc) +{ + UNIMPLEMENTED; +} + +HRGN +STDCALL +W32kCreatePolygonRgn(CONST PPOINT pt, + INT Count, + INT PolyFillMode) +{ + UNIMPLEMENTED; +} + +HRGN +STDCALL +W32kCreatePolyPolygonRgn(CONST PPOINT pt, + CONST PINT PolyCounts, + INT Count, + INT PolyFillMode) +{ + UNIMPLEMENTED; +} + +HRGN +STDCALL +W32kCreateRectRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect) +{ + HRGN hRgn; + PROSRGNDATA pRgnData; + PRECT pRect; + + // Allocate region data structure with space for 1 RECT + if( ( hRgn = RGNDATA_AllocRgn(1) ) ){ + if( ( pRgnData = RGNDATA_LockRgn( hRgn ) ) ){ + pRect = (PRECT)pRgnData->Buffer; + ASSERT(pRect); + + // Fill in the region data header + pRgnData->rdh.iType = SIMPLEREGION; + W32kSetRect(&(pRgnData->rdh.rcBound), LeftRect, TopRect, RightRect, BottomRect); + + // use W32kCopyRect when implemented + W32kSetRect(pRect, LeftRect, TopRect, RightRect, BottomRect); + RGNDATA_UnlockRgn( hRgn ); + + return hRgn; + } + W32kDeleteObject( hRgn ); + } + DPRINT("W32kCreateRectRgn: can't allocate region\n"); + return NULL; +} + +HRGN STDCALL +W32kCreateRectRgnIndirect(CONST PRECT rc) +{ + RECT SafeRc; + NTSTATUS Status; + + Status = MmCopyFromCaller(&SafeRc, rc, sizeof(RECT)); + if (!NT_SUCCESS(Status)) + { + return(NULL); + } + return(UnsafeW32kCreateRectRgnIndirect(&SafeRc)); +} + +HRGN STDCALL +UnsafeW32kCreateRectRgnIndirect(CONST PRECT rc) +{ + return(W32kCreateRectRgn(rc->left, rc->top, rc->right, rc->bottom)); +} + +HRGN +STDCALL +W32kCreateRoundRectRgn(INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect, + INT WidthEllipse, + INT HeightEllipse) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kEqualRgn(HRGN hSrcRgn1, + HRGN hSrcRgn2) +{ + PROSRGNDATA rgn1, rgn2; + PRECT tRect1, tRect2; + int i; + BOOL bRet = FALSE; + + if( !(rgn1 = RGNDATA_LockRgn(hSrcRgn1))) + return ERROR; + + if( !(rgn2 = RGNDATA_LockRgn(hSrcRgn2))){ + RGNDATA_UnlockRgn( hSrcRgn1 ); + return ERROR; + } + + if(rgn1->rdh.nCount != rgn2->rdh.nCount || + rgn1->rdh.nCount == 0 || + rgn1->rdh.rcBound.left != rgn2->rdh.rcBound.left || + rgn1->rdh.rcBound.right != rgn2->rdh.rcBound.right || + rgn1->rdh.rcBound.top != rgn2->rdh.rcBound.top || + rgn1->rdh.rcBound.bottom != rgn2->rdh.rcBound.bottom) + goto exit; + + tRect1 = (PRECT)rgn1->Buffer; + tRect2 = (PRECT)rgn2->Buffer; + + if( !tRect1 || !tRect2 ) + goto exit; + + for(i=0; i < rgn1->rdh.nCount; i++) + { + if(tRect1[i].left != tRect2[i].left || + tRect1[i].right != tRect2[i].right || + tRect1[i].top != tRect2[i].top || + tRect1[i].bottom != tRect2[i].bottom) + goto exit;; + } + bRet = TRUE; + +exit: + RGNDATA_UnlockRgn( hSrcRgn1 ); + RGNDATA_UnlockRgn( hSrcRgn2 ); + return bRet; +} + +HRGN +STDCALL +W32kExtCreateRegion(CONST PXFORM Xform, + DWORD Count, + CONST PROSRGNDATA RgnData) +{ + HRGN hRgn; + + // FIXME: Apply Xform transformation to the regional data + if(Xform != NULL) { + + } + + return hRgn; +} + +BOOL +STDCALL +W32kFillRgn(HDC hDC, + HRGN hRgn, + HBRUSH hBrush) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kFrameRgn(HDC hDC, + HRGN hRgn, + HBRUSH hBrush, + INT Width, + INT Height) +{ + UNIMPLEMENTED; +} + +INT STDCALL +UnsafeW32kGetRgnBox(HRGN hRgn, + LPRECT pRect) +{ + PROSRGNDATA rgn = RGNDATA_LockRgn(hRgn); + DWORD ret; + + if (rgn) + { + *pRect = rgn->rdh.rcBound; + ret = rgn->rdh.iType; + RGNDATA_UnlockRgn( hRgn ); + + return ret; + } + return 0; //if invalid region return zero +} + + +INT STDCALL +W32kGetRgnBox(HRGN hRgn, + LPRECT pRect) +{ + PROSRGNDATA rgn = RGNDATA_LockRgn(hRgn); + DWORD ret; + + if (rgn) + { + RECT SafeRect; + SafeRect.left = rgn->rdh.rcBound.left; + SafeRect.top = rgn->rdh.rcBound.top; + SafeRect.right = rgn->rdh.rcBound.right; + SafeRect.bottom = rgn->rdh.rcBound.bottom; + ret = rgn->rdh.iType; + RGNDATA_UnlockRgn( hRgn ); + + if(!NT_SUCCESS(MmCopyToCaller(pRect, &SafeRect, sizeof(RECT)))) + return 0; + + return ret; + } + return 0; //if invalid region return zero +} + +BOOL +STDCALL +W32kInvertRgn(HDC hDC, + HRGN hRgn) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kOffsetRgn(HRGN hRgn, + INT XOffset, + INT YOffset) +{ + PROSRGNDATA rgn = RGNDATA_LockRgn(hRgn); + INT ret; + + DPRINT("W32kOffsetRgn: hRgn %d Xoffs %d Yoffs %d rgn %x\n", hRgn, XOffset, YOffset, rgn ); + + if( !rgn ){ + DPRINT("W32kOffsetRgn: hRgn error\n"); + return ERROR; + } + + if(XOffset || YOffset) { + int nbox = rgn->rdh.nCount; + PRECT pbox = (PRECT)rgn->Buffer; + + if(nbox && pbox) { + while(nbox--) { + pbox->left += XOffset; + pbox->right += XOffset; + pbox->top += YOffset; + pbox->bottom += YOffset; + pbox++; + } + rgn->rdh.rcBound.left += XOffset; + rgn->rdh.rcBound.right += XOffset; + rgn->rdh.rcBound.top += YOffset; + rgn->rdh.rcBound.bottom += YOffset; + } + } + ret = rgn->rdh.iType; + RGNDATA_UnlockRgn( hRgn ); + return ret; +} + +BOOL +STDCALL +W32kPaintRgn(HDC hDC, + HRGN hRgn) +{ + RECT box; + HRGN tmpVisRgn, prevVisRgn; + DC *dc = DC_HandleToPtr(hDC); + PROSRGNDATA visrgn; + CLIPOBJ* ClipRegion; + BOOL bRet = FALSE; + PBRUSHOBJ pBrush; + POINTL BrushOrigin; + SURFOBJ *SurfObj; + + if( !dc ) + return FALSE; + + if(!(tmpVisRgn = W32kCreateRectRgn(0, 0, 0, 0))){ + DC_ReleasePtr( hDC ); + return FALSE; + } + +/* ei enable later + // Transform region into device co-ords + if(!REGION_LPTODP(hDC, tmpVisRgn, hRgn) || W32kOffsetRgn(tmpVisRgn, dc->w.DCOrgX, dc->w.DCOrgY) == ERROR) { + W32kDeleteObject( tmpVisRgn ); + DC_ReleasePtr( hDC ); + return FALSE; + } +*/ + /* enable when clipping is implemented + W32kCombineRgn(tmpVisRgn, tmpVisRgn, dc->w.hGCClipRgn, RGN_AND); + */ + + //visrgn = RGNDATA_LockRgn(tmpVisRgn); + visrgn = RGNDATA_LockRgn(hRgn); + + ClipRegion = IntEngCreateClipRegion( visrgn->rdh.nCount, visrgn->Buffer, visrgn->rdh.rcBound ); + ASSERT( ClipRegion ); + pBrush = BRUSHOBJ_LockBrush(dc->w.hBrush); + ASSERT(pBrush); + BrushOrigin.x = dc->w.brushOrgX; + BrushOrigin.y = dc->w.brushOrgY; + SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface); + + bRet = IntEngPaint(SurfObj, + ClipRegion, + pBrush, + &BrushOrigin, + 0xFFFF);//don't know what to put here + + RGNDATA_UnlockRgn( tmpVisRgn ); + + // Fill the region + DC_ReleasePtr( hDC ); + return TRUE; +} + +BOOL +STDCALL +W32kPtInRegion(HRGN hRgn, + INT X, + INT Y) +{ + PROSRGNDATA rgn; + int i; + + if( (rgn = RGNDATA_LockRgn(hRgn) ) ) + return FALSE; + + if(rgn->rdh.nCount > 0 && INRECT(rgn->rdh.rcBound, X, Y)){ + for(i = 0; i < rgn->rdh.nCount; i++) { + if(INRECT(*(PRECT)&rgn->Buffer[i], X, Y)){ + RGNDATA_UnlockRgn(hRgn); + return TRUE; + } + } + } + RGNDATA_UnlockRgn(hRgn); + return FALSE; +} + +BOOL +STDCALL +W32kRectInRegion(HRGN hRgn, + CONST LPRECT unsaferc) +{ + PROSRGNDATA rgn; + PRECT pCurRect, pRectEnd; + PRECT rc; + BOOL bRet = FALSE; + + if( !NT_SUCCESS( MmCopyFromCaller( rc, unsaferc, sizeof( RECT ) ) ) ){ + DPRINT("W32kRectInRegion: bogus rc\n"); + return ERROR; + } + + if( !( rgn = RGNDATA_LockRgn(hRgn) ) ) + return ERROR; + + // this is (just) a useful optimization + if((rgn->rdh.nCount > 0) && EXTENTCHECK(&rgn->rdh.rcBound, rc)) + { + for (pCurRect = (PRECT)rgn->Buffer, pRectEnd = pCurRect + rgn->rdh.nCount; pCurRect < pRectEnd; pCurRect++) + { + if (pCurRect->bottom <= rc->top) continue; // not far enough down yet + if (pCurRect->top >= rc->bottom) break; // too far down + if (pCurRect->right <= rc->left) continue; // not far enough over yet + if (pCurRect->left >= rc->right) continue; + bRet = TRUE; + break; + } + } + RGNDATA_UnlockRgn(hRgn); + return bRet; +} + +BOOL +STDCALL +W32kSetRectRgn(HRGN hRgn, + INT LeftRect, + INT TopRect, + INT RightRect, + INT BottomRect) +{ + PROSRGNDATA rgn; + PRECT firstRect; + + + + if( !( rgn = RGNDATA_LockRgn(hRgn) ) ) + return 0; //per documentation + + if (LeftRect > RightRect) { INT tmp = LeftRect; LeftRect = RightRect; RightRect = tmp; } + if (TopRect > BottomRect) { INT tmp = TopRect; TopRect = BottomRect; BottomRect = tmp; } + + if((LeftRect != RightRect) && (TopRect != BottomRect)) + { + firstRect = (PRECT)rgn->Buffer; + ASSERT( firstRect ); + firstRect->left = rgn->rdh.rcBound.left = LeftRect; + firstRect->top = rgn->rdh.rcBound.top = TopRect; + firstRect->right = rgn->rdh.rcBound.right = RightRect; + firstRect->bottom = rgn->rdh.rcBound.bottom = BottomRect; + rgn->rdh.nCount = 1; + rgn->rdh.iType = SIMPLEREGION; + } else + EMPTY_REGION(rgn); + + RGNDATA_UnlockRgn( hRgn ); + return TRUE; +} + +HRGN STDCALL +W32kUnionRectWithRgn(HRGN hDest, const RECT* unsafeRect) +{ + PRECT pRect; + PROSRGNDATA pRgn; + + if( !NT_SUCCESS( MmCopyFromCaller( pRect, unsafeRect, sizeof( RECT ) ) ) ) + return NULL; + + if( !(pRgn = RGNDATA_LockRgn( hDest ) ) ) + return NULL; + + REGION_UnionRectWithRegion( pRect, pRgn ); + RGNDATA_UnlockRgn( hDest ); + return hDest; +} + +/*********************************************************************** + * GetRegionData (GDI32.@) + * + * MSDN: GetRegionData, Return Values: + * + * "If the function succeeds and dwCount specifies an adequate number of bytes, + * the return value is always dwCount. If dwCount is too small or the function + * fails, the return value is 0. If lpRgnData is NULL, the return value is the + * required number of bytes. + * + * If the function fails, the return value is zero." + */ +DWORD STDCALL W32kGetRegionData(HRGN hrgn, DWORD count, LPRGNDATA rgndata) +{ + DWORD size; + PROSRGNDATA obj = RGNDATA_LockRgn( hrgn ); + + if(!obj) + return 0; + + size = obj->rdh.nCount * sizeof(RECT); + if(count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL) + { + RGNDATA_UnlockRgn( hrgn ); + if (rgndata) /* buffer is too small, signal it by return 0 */ + return 0; + else /* user requested buffer size with rgndata NULL */ + return size + sizeof(RGNDATAHEADER); + } + + //first we copy the header then we copy buffer + if( !NT_SUCCESS( MmCopyToCaller( rgndata, obj, sizeof( RGNDATAHEADER )))){ + RGNDATA_UnlockRgn( hrgn ); + return 0; + } + if( !NT_SUCCESS( MmCopyToCaller( (char*)rgndata+sizeof( RGNDATAHEADER ), obj->Buffer, size ))){ + RGNDATA_UnlockRgn( hrgn ); + return 0; + } + + RGNDATA_UnlockRgn( hrgn ); + return size + sizeof(RGNDATAHEADER); +} + diff --git a/subsys/win32k/objects/text.c b/subsys/win32k/objects/text.c new file mode 100644 index 0000000..ded81fd --- /dev/null +++ b/subsys/win32k/objects/text.c @@ -0,0 +1,760 @@ + + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +#include "../eng/handle.h" + +// #define NDEBUG +#include + +FT_Library library; + +typedef struct _FONTTABLE { + HFONT hFont; + LPCWSTR FaceName; +} FONTTABLE, *PFONTTABLE; + +FONTTABLE FontTable[256]; +INT FontsLoaded = 0; + +BOOL InitFontSupport() +{ + ULONG error; + + error = FT_Init_FreeType(&library); + if(error) + { + return FALSE; + } + + W32kAddFontResource(L"\\SystemRoot\\media\\fonts\\helb____.ttf"); + W32kAddFontResource(L"\\SystemRoot\\media\\fonts\\timr____.ttf"); + + DbgPrint("All fonts loaded\n"); + + return TRUE; +} + +int +STDCALL +W32kAddFontResource(LPCWSTR Filename) +{ + HFONT NewFont; + PFONTOBJ FontObj; + PFONTGDI FontGDI; + UNICODE_STRING uFileName; + NTSTATUS Status; + HANDLE FileHandle; + OBJECT_ATTRIBUTES ObjectAttributes; + FILE_STANDARD_INFORMATION FileStdInfo; + PVOID buffer; + ULONG size; + INT error; + FT_Face face; + ANSI_STRING StringA; + UNICODE_STRING StringU; + IO_STATUS_BLOCK Iosb; + + NewFont = (HFONT)CreateGDIHandle(sizeof( FONTGDI ), sizeof( FONTOBJ )); + FontObj = (PFONTOBJ) AccessUserObject( NewFont ); + FontGDI = (PFONTGDI) AccessInternalObject( NewFont ); + + RtlCreateUnicodeString(&uFileName, (LPWSTR)Filename); + + // Open the Module + InitializeObjectAttributes(&ObjectAttributes, &uFileName, 0, NULL, NULL); + + Status = NtOpenFile(&FileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &Iosb, 0, 0); + + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not open module file: %S\n", Filename); + return 0; + } + + // Get the size of the file + Status = NtQueryInformationFile(FileHandle, &Iosb, &FileStdInfo, sizeof(FileStdInfo), FileStandardInformation); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Could not get file size\n"); + return 0; + } + + // Allocate nonpageable memory for driver + size = FileStdInfo.EndOfFile.u.LowPart; + buffer = ExAllocatePool(NonPagedPool, size); + + if (buffer == NULL) + { + DbgPrint("could not allocate memory for module"); + return 0; + } + + // Load driver into memory chunk + Status = NtReadFile(FileHandle, 0, 0, 0, &Iosb, buffer, FileStdInfo.EndOfFile.u.LowPart, 0, 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("could not read module file into memory"); + ExFreePool(buffer); + return 0; + } + + NtClose(FileHandle); + + error = FT_New_Memory_Face(library, buffer, size, 0, &face); + if (error == FT_Err_Unknown_File_Format) + { + DbgPrint("Unknown font file format\n"); + return 0; + } + else if (error) + { + DbgPrint("Error reading font file (error code: %u)\n", error); // 48 + return 0; + } + + // FontGDI->Filename = Filename; perform strcpy + FontGDI->face = face; + + // FIXME: Complete text metrics + FontGDI->TextMetric.tmAscent = face->size->metrics.ascender; // units above baseline + FontGDI->TextMetric.tmDescent = face->size->metrics.descender; // units below baseline + FontGDI->TextMetric.tmHeight = FontGDI->TextMetric.tmAscent + FontGDI->TextMetric.tmDescent; + + DbgPrint("Family name: %s\n", face->family_name); + DbgPrint("Style name: %s\n", face->style_name); + DbgPrint("Num glyphs: %u\n", face->num_glyphs); + + // Add this font resource to the font table + FontTable[FontsLoaded].hFont = NewFont; + + RtlInitAnsiString(&StringA, (LPSTR)face->family_name); + RtlAnsiStringToUnicodeString(&StringU, &StringA, TRUE); + FontTable[FontsLoaded].FaceName = ExAllocatePool(NonPagedPool, (StringU.Length + 1) * 2); + wcscpy((LPWSTR)FontTable[FontsLoaded].FaceName, StringU.Buffer); + RtlFreeUnicodeString(&StringU); + + FontsLoaded++; + + return 1; +} + +HFONT +STDCALL +W32kCreateFont(int Height, + int Width, + int Escapement, + int Orientation, + int Weight, + DWORD Italic, + DWORD Underline, + DWORD StrikeOut, + DWORD CharSet, + DWORD OutputPrecision, + DWORD ClipPrecision, + DWORD Quality, + DWORD PitchAndFamily, + LPCWSTR Face) +{ + LOGFONT logfont; + + logfont.lfHeight = Height; + logfont.lfWidth = Width; + logfont.lfEscapement = Escapement; + logfont.lfOrientation = Orientation; + logfont.lfWeight = Weight; + logfont.lfItalic = Italic; + logfont.lfUnderline = Underline; + logfont.lfStrikeOut = StrikeOut; + logfont.lfCharSet = CharSet; + logfont.lfOutPrecision = OutputPrecision; + logfont.lfClipPrecision = ClipPrecision; + logfont.lfQuality = Quality; + logfont.lfPitchAndFamily = PitchAndFamily; + + if(Face) + memcpy(logfont.lfFaceName, Face, sizeof(logfont.lfFaceName)); + else + logfont.lfFaceName[0] = '\0'; + + return W32kCreateFontIndirect(&logfont); +} + +HFONT +STDCALL +W32kCreateFontIndirect(CONST LPLOGFONT lf) +{ + HFONT hFont = 0; + PTEXTOBJ fontPtr; + + if (lf) + { + if(hFont = TEXTOBJ_AllocText()) + { + fontPtr = TEXTOBJ_LockText( hFont ); + ASSERT( fontPtr ); //I want to know when this happens + if( fontPtr ){ + memcpy(&fontPtr->logfont, lf, sizeof(LOGFONT)); + + if (lf->lfEscapement != lf->lfOrientation) { + /* this should really depend on whether GM_ADVANCED is set */ + fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement; + } + TEXTOBJ_UnlockText( hFont ); + } + } + } + + return hFont; +} + +BOOL +STDCALL +W32kCreateScalableFontResource(DWORD Hidden, + LPCWSTR FontRes, + LPCWSTR FontFile, + LPCWSTR CurrentPath) +{ + UNIMPLEMENTED; +} + +int +STDCALL +W32kEnumFontFamilies(HDC hDC, + LPCWSTR Family, + FONTENUMPROC EnumFontFamProc, + LPARAM lParam) +{ + UNIMPLEMENTED; +} + +int +STDCALL +W32kEnumFontFamiliesEx(HDC hDC, + LPLOGFONT Logfont, + FONTENUMPROC EnumFontFamExProc, + LPARAM lParam, + DWORD Flags) +{ + UNIMPLEMENTED; +} + +int +STDCALL +W32kEnumFonts(HDC hDC, + LPCWSTR FaceName, + FONTENUMPROC FontFunc, + LPARAM lParam) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kExtTextOut(HDC hDC, + int X, + int Y, + UINT Options, + CONST LPRECT rc, + LPCWSTR String, + UINT Count, + CONST LPINT Dx) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetAspectRatioFilterEx(HDC hDC, + LPSIZE AspectRatio) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetCharABCWidths(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPABC abc) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetCharABCWidthsFloat(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPABCFLOAT abcF) +{ + UNIMPLEMENTED; +} + +DWORD +STDCALL +W32kGetCharacterPlacement(HDC hDC, + LPCWSTR String, + int Count, + int MaxExtent, + LPGCP_RESULTS Results, + DWORD Flags) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetCharWidth(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPINT Buffer) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetCharWidth32(HDC hDC, + UINT FirstChar, + UINT LastChar, + LPINT Buffer) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetCharWidthFloat(HDC hDC, + UINT FirstChar, + UINT LastChar, + PFLOAT Buffer) +{ + UNIMPLEMENTED; +} + +DWORD +STDCALL +W32kGetFontLanguageInfo(HDC hDC) +{ + UNIMPLEMENTED; +} + +DWORD +STDCALL +W32kGetGlyphOutline(HDC hDC, + UINT Char, + UINT Format, + LPGLYPHMETRICS gm, + DWORD Bufsize, + LPVOID Buffer, + CONST LPMAT2 mat2) +{ + UNIMPLEMENTED; + + +} + +DWORD +STDCALL +W32kGetKerningPairs(HDC hDC, + DWORD NumPairs, + LPKERNINGPAIR krnpair) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetOutlineTextMetrics(HDC hDC, + UINT Data, + LPOUTLINETEXTMETRIC otm) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetRasterizerCaps(LPRASTERIZER_STATUS rs, + UINT Size) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetTextCharset(HDC hDC) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetTextCharsetInfo(HDC hDC, + LPFONTSIGNATURE Sig, + DWORD Flags) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetTextExtentExPoint(HDC hDC, + LPCWSTR String, + int Count, + int MaxExtent, + LPINT Fit, + LPINT Dx, + LPSIZE Size) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetTextExtentPoint(HDC hDC, + LPCWSTR String, + int Count, + LPSIZE Size) +{ + PDC dc = (PDC)AccessUserObject(hDC); + PFONTGDI FontGDI; + FT_Face face; + FT_GlyphSlot glyph; + INT error, pitch, glyph_index, i; + ULONG TotalWidth = 0, MaxHeight = 0, CurrentChar = 0, SpaceBetweenChars = 5; + + FontGDI = (PFONTGDI)AccessInternalObject(dc->w.hFont); + + for(i=0; iglyph; + + if (glyph->format == ft_glyph_format_outline) + { + error = FT_Render_Glyph(glyph, ft_render_mode_mono); + if(error) DbgPrint("WARNING: Failed to render glyph!\n"); + pitch = glyph->bitmap.pitch; + } else { + pitch = glyph->bitmap.width; + } + + TotalWidth += pitch-1; + if((glyph->bitmap.rows-1) > MaxHeight) MaxHeight = glyph->bitmap.rows-1; + + CurrentChar++; + + if(CurrentChar < Size->cx) TotalWidth += SpaceBetweenChars; + String++; + } + + Size->cx = TotalWidth; + Size->cy = MaxHeight; +} + +BOOL +STDCALL +W32kGetTextExtentPoint32(HDC hDC, + LPCWSTR String, + int Count, + LPSIZE Size) +{ + UNIMPLEMENTED; +} + +int +STDCALL +W32kGetTextFace(HDC hDC, + int Count, + LPWSTR FaceName) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kGetTextMetrics(HDC hDC, + LPTEXTMETRIC tm) +{ + PDC dc = (PDC)AccessUserObject(hDC); + PFONTGDI FontGDI; + + FontGDI = (PFONTGDI)AccessInternalObject(dc->w.hFont); + memcpy(tm, &FontGDI->TextMetric, sizeof(TEXTMETRIC)); + + return TRUE; +} + +BOOL +STDCALL +W32kPolyTextOut(HDC hDC, + CONST LPPOLYTEXT txt, + int Count) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kRemoveFontResource(LPCWSTR FileName) +{ + UNIMPLEMENTED; +} + +DWORD +STDCALL +W32kSetMapperFlags(HDC hDC, + DWORD Flag) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kSetTextAlign(HDC hDC, + UINT Mode) +{ + UINT prevAlign; + DC *dc; + + dc = DC_HandleToPtr(hDC); + if (!dc) + { + return 0; + } + prevAlign = dc->w.textAlign; + dc->w.textAlign = Mode; + DC_ReleasePtr( hDC ); + return prevAlign; +} + +COLORREF +STDCALL +W32kSetTextColor(HDC hDC, + COLORREF color) +{ + COLORREF oldColor; + PDC dc = DC_HandleToPtr(hDC); + + if (!dc) + { + return 0x80000000; + } + + oldColor = dc->w.textColor; + dc->w.textColor = color; + DC_ReleasePtr( hDC ); + return oldColor; +} + +BOOL +STDCALL +W32kSetTextJustification(HDC hDC, + int BreakExtra, + int BreakCount) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kTextOut(HDC hDC, + int XStart, + int YStart, + LPCWSTR String, + int Count) +{ + // Fixme: Call EngTextOut, which does the real work (calling DrvTextOut where appropriate) + + DC *dc = DC_HandleToPtr(hDC); + SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface); + int error, glyph_index, n, load_flags = FT_LOAD_RENDER, i, j, sx, sy, scc; + FT_Face face; + FT_GlyphSlot glyph; + ULONG TextLeft, TextTop, SpaceBetweenChars = 2, pitch, previous; + FT_Bool use_kerning; + RECTL DestRect, MaskRect; + POINTL SourcePoint, BrushOrigin; + HBRUSH hBrush = NULL; + PBRUSHOBJ Brush = NULL; + HBITMAP HSourceGlyph; + PSURFOBJ SourceGlyphSurf; + SIZEL bitSize; + FT_CharMap found = 0, charmap; + INT yoff; + HFONT hFont = 0; + PFONTOBJ FontObj; + PFONTGDI FontGDI; + PTEXTOBJ TextObj; + PPALGDI PalDestGDI; + PXLATEOBJ XlateObj; + + if( !dc ) + return FALSE; + + XStart += dc->w.DCOrgX; + YStart += dc->w.DCOrgY; + TextLeft = XStart; + TextTop = YStart; + + TextObj = TEXTOBJ_LockText(dc->w.hFont); + + for(i=0; ilogfont.lfFaceName) == 0) + hFont = FontTable[i].hFont; + } + + if(hFont == 0) + { + DbgPrint("Specified font %s is not loaded\n", TextObj->logfont.lfFaceName); + goto fail; + } + + FontObj = (PFONTOBJ)AccessUserObject(hFont); + FontGDI = (PFONTGDI)AccessInternalObject(hFont); + face = FontGDI->face; + + if (face->charmap == NULL) + { + DbgPrint("WARNING: No charmap selected!\n"); + DbgPrint("This font face has %d charmaps\n", face->num_charmaps); + + for (n = 0; n < face->num_charmaps; n++) + { + charmap = face->charmaps[n]; + DbgPrint("found charmap encoding: %u\n", charmap->encoding); + if (charmap->encoding != 0) + { + found = charmap; + break; + } + } + if (!found) DbgPrint("WARNING: Could not find desired charmap!\n"); + error = FT_Set_Charmap(face, found); + if (error) DbgPrint("WARNING: Could not set the charmap!\n"); + } + + error = FT_Set_Pixel_Sizes(face, TextObj->logfont.lfHeight, TextObj->logfont.lfWidth); + if(error) { + DbgPrint("Error in setting pixel sizes: %u\n", error); + goto fail; + } + + // Create the brush + PalDestGDI = (PPALGDI)AccessInternalObject(dc->w.hPalette); + XlateObj = (PXLATEOBJ)EngCreateXlate(PalDestGDI->Mode, PAL_RGB, dc->w.hPalette, NULL); + hBrush = W32kCreateSolidBrush(XLATEOBJ_iXlate(XlateObj, dc->w.textColor)); + Brush = BRUSHOBJ_LockBrush(hBrush); + EngDeleteXlate(XlateObj); + + SourcePoint.x = 0; + SourcePoint.y = 0; + MaskRect.left = 0; + MaskRect.top = 0; + BrushOrigin.x = 0; + BrushOrigin.y = 0; + + // Determine the yoff from the dc's w.textAlign + if (dc->w.textAlign & TA_BASELINE) { + yoff = 0; + } + else + if (dc->w.textAlign & TA_BOTTOM) { + yoff = -face->size->metrics.descender / 64; + } + else { // TA_TOP + yoff = face->size->metrics.ascender / 64; + } + + use_kerning = FT_HAS_KERNING(face); + previous = 0; + + for(i=0; iglyph; + + // retrieve kerning distance and move pen position + if (use_kerning && previous && glyph_index) + { + FT_Vector delta; + FT_Get_Kerning(face, previous, glyph_index, 0, &delta); + TextLeft += delta.x >> 6; + } + + if (glyph->format == ft_glyph_format_outline) + { + error = FT_Render_Glyph(glyph, ft_render_mode_mono); + if(error) { + DbgPrint("WARNING: Failed to render glyph!\n"); + goto fail; + } + pitch = glyph->bitmap.pitch; + } else { + pitch = glyph->bitmap.width; + } + + DestRect.left = TextLeft; + DestRect.top = TextTop + yoff - glyph->bitmap_top; + DestRect.right = TextLeft + glyph->bitmap.width; + DestRect.bottom = DestRect.top + glyph->bitmap.rows; + bitSize.cx = pitch-1; + bitSize.cy = glyph->bitmap.rows-1; + MaskRect.right = glyph->bitmap.width; + MaskRect.bottom = glyph->bitmap.rows; + + // We should create the bitmap out of the loop at the biggest possible glyph size + // Then use memset with 0 to clear it and sourcerect to limit the work of the transbitblt + + HSourceGlyph = EngCreateBitmap(bitSize, pitch, BMF_1BPP, 0, glyph->bitmap.buffer); + SourceGlyphSurf = (PSURFOBJ)AccessUserObject(HSourceGlyph); + + // Use the font data as a mask to paint onto the DCs surface using a brush + EngBitBlt(SurfObj, NULL, SourceGlyphSurf, NULL, NULL, &DestRect, &SourcePoint, &MaskRect, Brush, &BrushOrigin, 0xAACC); + + EngDeleteSurface(HSourceGlyph); + + TextLeft += glyph->advance.x >> 6; + previous = glyph_index; + + String++; + } + TEXTOBJ_UnlockText( dc->w.hFont ); + BRUSHOBJ_UnlockBrush(hBrush); + W32kDeleteObject( hBrush ); + DC_ReleasePtr( hDC ); + return TRUE; + +fail: + TEXTOBJ_UnlockText( dc->w.hFont ); + if( hBrush ){ + BRUSHOBJ_UnlockBrush(hBrush); + W32kDeleteObject( hBrush ); + } + DC_ReleasePtr( hDC ); + return FALSE; +} + +UINT +STDCALL +W32kTranslateCharsetInfo(PDWORD Src, + LPCHARSETINFO CSI, + DWORD Flags) +{ + UNIMPLEMENTED; +} diff --git a/subsys/win32k/objects/wingl.c b/subsys/win32k/objects/wingl.c new file mode 100644 index 0000000..0973cf0 --- /dev/null +++ b/subsys/win32k/objects/wingl.c @@ -0,0 +1,61 @@ + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include + +// #define NDEBUG +#include + +INT +STDCALL +W32kChoosePixelFormat(HDC hDC, + CONST PPIXELFORMATDESCRIPTOR pfd) +{ + UNIMPLEMENTED; +} + + +INT +STDCALL +W32kDescribePixelFormat(HDC hDC, + INT PixelFormat, + UINT BufSize, + LPPIXELFORMATDESCRIPTOR pfd) +{ + UNIMPLEMENTED; +} + +UINT +STDCALL +W32kGetEnhMetaFilePixelFormat(HENHMETAFILE hEMF, + DWORD BufSize, + CONST PPIXELFORMATDESCRIPTOR pfd) +{ + UNIMPLEMENTED; +} + +INT +STDCALL +W32kGetPixelFormat(HDC hDC) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSetPixelFormat(HDC hDC, + INT PixelFormat, + CONST PPIXELFORMATDESCRIPTOR pfd) +{ + UNIMPLEMENTED; +} + +BOOL +STDCALL +W32kSwapBuffers(HDC hDC) +{ + UNIMPLEMENTED; +} + + diff --git a/subsys/win32k/stubs/.cvsignore b/subsys/win32k/stubs/.cvsignore new file mode 100644 index 0000000..bd0e3df --- /dev/null +++ b/subsys/win32k/stubs/.cvsignore @@ -0,0 +1,3 @@ +*.d +*.o +*.sym diff --git a/subsys/win32k/stubs/stubs.c b/subsys/win32k/stubs/stubs.c new file mode 100644 index 0000000..0f1898f --- /dev/null +++ b/subsys/win32k/stubs/stubs.c @@ -0,0 +1,134 @@ +/* + * Stubs for unimplemented WIN32K.SYS exports + */ + +#include +#include + +#define STUB(x) void x(void) { DbgPrint("WIN32K: Stub for %s\n", #x); } + + +STUB(BRUSHOBJ_ulGetBrushColor) +STUB(CLIPOBJ_ppoGetPath) +STUB(EngAcquireSemaphore) +STUB(EngCheckAbort) +STUB(EngComputeGlyphSet) +STUB(EngCreateDriverObj) +STUB(EngCreateEvent) +STUB(EngCreatePath) +STUB(EngCreateSemaphore) +STUB(EngCreateWnd) +STUB(EngDeleteDriverObj) +STUB(EngDeleteEvent) +STUB(EngDeletePath) +STUB(EngDeleteSemaphore) +STUB(EngDeleteWnd) +STUB(EngEnumForms) +STUB(EngFillPath) +STUB(EngFindImageProcAddress) +STUB(EngFindResource) +STUB(EngFreeModule) +STUB(EngGetCurrentCodePage) +STUB(EngGetDriverName) +STUB(EngGetFileChangeTime) +STUB(EngGetFilePath) +STUB(EngGetForm) +STUB(EngGetLastError) +STUB(EngGetPrinter) +STUB(EngGetPrinterData) +STUB(EngGetPrinterDataFileName) +STUB(EngGetProcessHandle) +STUB(EngGetType1FontList) +STUB(EngLoadModuleForWrite) +STUB(EngLockDriverObj) +STUB(EngMapEvent) +STUB(EngMapFontFile) +STUB(EngMapModule) +STUB(EngMarkBandingSurface) +STUB(EngMovePointer) +STUB(EngMultiByteToUnicodeN) +STUB(EngMultiByteToWideChar) +STUB(EngProbeForRead) +STUB(EngProbeForReadAndWrite) +STUB(EngQueryLocalTime) +STUB(EngQueryPalette) +STUB(EngQueryPerformanceCounter) +STUB(EngQueryPerformanceFrequency) +STUB(EngReleaseSemaphore) +STUB(EngRestoreFloatingPointState) +STUB(EngSaveFloatingPointState) +STUB(EngSecureMem) +STUB(EngSetEvent) +STUB(EngSetLastError) +STUB(EngSetPointerShape) +STUB(EngSetPointerTag) +STUB(EngSetPrinterData) +STUB(EngSort) +STUB(EngStretchBlt) +STUB(EngStrokeAndFillPath) +STUB(EngStrokePath) +STUB(EngTextOut) +STUB(EngUnicodeToMultiByteN) +STUB(EngUnloadImage) +STUB(EngUnlockDriverObj) +STUB(EngUnlockSurface) +STUB(EngUnmapEvent) +STUB(EngUnmapFontFile) +STUB(EngUnsecureMem) +STUB(EngWaitForSingleObject) +STUB(EngWideCharToMultiByte) +STUB(EngWritePrinter) +STUB(FLOATOBJ_Add) +STUB(FLOATOBJ_AddFloat) +STUB(FLOATOBJ_AddFloatObj) +STUB(FLOATOBJ_AddLong) +STUB(FLOATOBJ_Div) +STUB(FLOATOBJ_DivFloat) +STUB(FLOATOBJ_DivFloatObj) +STUB(FLOATOBJ_DivLong) +STUB(FLOATOBJ_Equal) +STUB(FLOATOBJ_EqualLong) +STUB(FLOATOBJ_GetFloat) +STUB(FLOATOBJ_GetLong) +STUB(FLOATOBJ_GreaterThan) +STUB(FLOATOBJ_GreaterThanLong) +STUB(FLOATOBJ_LessThan) +STUB(FLOATOBJ_LessThanLong) +STUB(FLOATOBJ_Mul) +STUB(FLOATOBJ_MulFloat) +STUB(FLOATOBJ_MulFloatObj) +STUB(FLOATOBJ_MulLong) +STUB(FLOATOBJ_Neg) +STUB(FLOATOBJ_SetFloat) +STUB(FLOATOBJ_SetLong) +STUB(FLOATOBJ_Sub) +STUB(FLOATOBJ_SubFloat) +STUB(FLOATOBJ_SubFloatObj) +STUB(FLOATOBJ_SubLong) +STUB(FONTOBJ_cGetAllGlyphHandles) +STUB(FONTOBJ_cGetGlyphs) +STUB(FONTOBJ_pifi) +STUB(FONTOBJ_pvTrueTypeFontFile) +STUB(FONTOBJ_pxoGetXform) +STUB(FONTOBJ_vGetInfo) +STUB(HT_ComputeRGBGammaTable) +STUB(HT_Get8BPPFormatPalette) +STUB(PATHOBJ_bCloseFigure) +STUB(PATHOBJ_bEnum) +STUB(PATHOBJ_bEnumClipLines) +STUB(PATHOBJ_bMoveTo) +STUB(PATHOBJ_bPolyBezierTo) +STUB(PATHOBJ_bPolyLineTo) +STUB(PATHOBJ_vEnumStart) +STUB(PATHOBJ_vEnumStartClipLines) +STUB(PATHOBJ_vGetBounds) +STUB(STROBJ_bEnum) +STUB(STROBJ_dwGetCodePage) +STUB(STROBJ_vEnumStart) +STUB(WNDOBJ_bEnum) +STUB(WNDOBJ_cEnumStart) +STUB(WNDOBJ_vSetConsumer) +STUB(XFORMOBJ_bApplyXform) +STUB(XFORMOBJ_iGetFloatObjXform) +STUB(XFORMOBJ_iGetXform) + diff --git a/subsys/win32k/win32k.def b/subsys/win32k/win32k.def new file mode 100644 index 0000000..4fa8151 --- /dev/null +++ b/subsys/win32k/win32k.def @@ -0,0 +1,183 @@ +; $Id$ +; +; win32k.def +; +; ReactOS win32k.sys +; +LIBRARY win32k +EXPORTS +;W32kGetVectors +BRUSHOBJ_pvAllocRbrush@8 +BRUSHOBJ_pvGetRbrush@4 +BRUSHOBJ_ulGetBrushColor +CLIPOBJ_bEnum@12 +CLIPOBJ_cEnumStart@20 +CLIPOBJ_ppoGetPath +EngAcquireSemaphore +EngAllocMem@12 +EngAllocUserMem@8 +EngAssociateSurface@12 +EngBitBlt@44 +EngCheckAbort +EngComputeGlyphSet +EngCopyBits@24 +EngCreateBitmap@24 +EngCreateClip@0 +EngCreateDeviceBitmap@16 +EngCreateDeviceSurface@16 +EngCreateDriverObj +EngCreateEvent +EngCreatePalette@24 +EngCreatePath +EngCreateSemaphore +EngCreateWnd +EngDebugBreak@0 +EngDebugPrint@12 +EngDeleteClip@4 +EngDeleteDriverObj +EngDeleteEvent +EngDeletePalette@4 +EngDeletePath +EngDeleteSemaphore +EngDeleteSurface@4 +EngDeleteWnd +EngDeviceIoControl@28 +EngEnumForms +EngEraseSurface@12 +EngFillPath +EngFindImageProcAddress +EngFindResource +EngFreeMem@4 +EngFreeModule +EngFreeUserMem@4 +EngGetCurrentCodePage +EngGetDriverName +EngGetFileChangeTime +EngGetFilePath +EngGetForm +EngGetLastError +EngGetPrinter +EngGetPrinterData +EngGetPrinterDataFileName +EngGetProcessHandle +EngGetType1FontList +EngLineTo@36 +EngLoadImage@4 +EngLoadModule@4 +EngLoadModuleForWrite +EngLockDriverObj +EngLockSurface@4 +EngMapEvent +EngMapFontFile +EngMapModule +EngMarkBandingSurface +EngMovePointer +EngMulDiv +EngMultiByteToUnicodeN +EngMultiByteToWideChar +EngPaint@20 +EngProbeForRead +; EngProbeForReadAndWrite = NTOSKRNL.ProbeForWrite +EngProbeForReadAndWrite +EngQueryLocalTime +EngQueryPalette +EngQueryPerformanceCounter +EngQueryPerformanceFrequency +EngReleaseSemaphore +EngRestoreFloatingPointState +EngSaveFloatingPointState +EngSecureMem +EngSetEvent +EngSetLastError +EngSetPointerShape +EngSetPointerTag +EngSetPrinterData +EngSort +EngStretchBlt +EngStrokeAndFillPath +EngStrokePath +EngTextOut +EngTransparentBlt@32 +EngUnicodeToMultiByteN +EngUnloadImage +EngUnlockDriverObj +EngUnlockSurface +EngUnmapEvent +EngUnmapFontFile +; EngUnsecureMem = NTOSKRNL.MmUnsecureVirtualMemory +EngUnsecureMem +EngWaitForSingleObject +EngWideCharToMultiByte +EngWritePrinter +FLOATOBJ_Add +FLOATOBJ_AddFloat +FLOATOBJ_AddFloatObj +FLOATOBJ_AddLong +FLOATOBJ_Div +FLOATOBJ_DivFloat +FLOATOBJ_DivFloatObj +FLOATOBJ_DivLong +FLOATOBJ_Equal +FLOATOBJ_EqualLong +FLOATOBJ_GetFloat +FLOATOBJ_GetLong +FLOATOBJ_GreaterThan +FLOATOBJ_GreaterThanLong +FLOATOBJ_LessThan +FLOATOBJ_LessThanLong +FLOATOBJ_Mul +FLOATOBJ_MulFloat +FLOATOBJ_MulFloatObj +FLOATOBJ_MulLong +FLOATOBJ_Neg +FLOATOBJ_SetFloat +FLOATOBJ_SetLong +FLOATOBJ_Sub +FLOATOBJ_SubFloat +FLOATOBJ_SubFloatObj +FLOATOBJ_SubLong +FONTOBJ_cGetAllGlyphHandles +FONTOBJ_cGetGlyphs +FONTOBJ_pifi +FONTOBJ_pvTrueTypeFontFile +FONTOBJ_pxoGetXform +FONTOBJ_vGetInfo +HT_ComputeRGBGammaTable +HT_Get8BPPFormatPalette +PALOBJ_cGetColors@16 +PATHOBJ_bCloseFigure +PATHOBJ_bEnum +PATHOBJ_bEnumClipLines +PATHOBJ_bMoveTo +PATHOBJ_bPolyBezierTo +PATHOBJ_bPolyLineTo +PATHOBJ_vEnumStart +PATHOBJ_vEnumStartClipLines +PATHOBJ_vGetBounds +RtlAnsiCharToUnicodeChar@4 +RtlMultiByteToUnicodeN@20 +RtlRaiseException@4 +RtlUnicodeToMultiByteN@20 +RtlUnicodeToMultiByteSize@12 +RtlUnwind@16 +RtlUpcaseUnicodeChar@4 +RtlUpcaseUnicodeToMultiByteN@20 +STROBJ_bEnum +STROBJ_dwGetCodePage +STROBJ_vEnumStart +W32kCleanupForProcess@4 +W32kInitialize +WNDOBJ_bEnum +WNDOBJ_cEnumStart +WNDOBJ_vSetConsumer +XFORMOBJ_bApplyXform +XFORMOBJ_iGetFloatObjXform +XFORMOBJ_iGetXform +XLATEOBJ_cGetPalette@16 +XLATEOBJ_iXlate@8 +XLATEOBJ_piVector@4 +_abnormal_termination +_except_handler2 +_global_unwind2 +_local_unwind2 + diff --git a/subsys/win32k/win32k.edf b/subsys/win32k/win32k.edf new file mode 100644 index 0000000..e93e9e9 --- /dev/null +++ b/subsys/win32k/win32k.edf @@ -0,0 +1,187 @@ +; $Id$ +; +; win32k.def +; +; ReactOS win32k.sys +; +LIBRARY win32k +EXPORTS +;W32kGetVectors +BRUSHOBJ_pvAllocRbrush=BRUSHOBJ_pvAllocRbrush@8 +BRUSHOBJ_pvGetRbrush=BRUSHOBJ_pvGetRbrush@4 +BRUSHOBJ_ulGetBrushColor +CLIPOBJ_bEnum=CLIPOBJ_bEnum@12 +CLIPOBJ_cEnumStart=CLIPOBJ_cEnumStart@20 +CLIPOBJ_ppoGetPath +EngAcquireSemaphore +EngAllocMem=EngAllocMem@12 +EngAllocUserMem=EngAllocUserMem@8 +EngAssociateSurface=EngAssociateSurface@12 +EngBitBlt=EngBitBlt@44 +EngCheckAbort +EngComputeGlyphSet +EngCopyBits=EngCopyBits@24 +EngCreateBitmap=EngCreateBitmap@24 +EngCreateClip=EngCreateClip@0 +EngCreateDeviceBitmap=EngCreateDeviceBitmap@16 +EngCreateDeviceSurface=EngCreateDeviceSurface@16 +EngCreateDriverObj +EngCreateEvent +EngCreatePalette=EngCreatePalette@24 +EngCreatePath +EngCreateSemaphore +EngCreateWnd +EngDebugBreak=NTOSKRNL.DbgBreakPoint +EngDebugPrint=EngDebugPrint@12 +EngDeleteClip=EngDeleteClip@4 +EngDeleteDriverObj +EngDeleteEvent +EngDeletePalette=EngDeletePalette@4 +EngDeletePath +EngDeleteSemaphore +EngDeleteSurface=EngDeleteSurface@4 +EngDeleteWnd +EngDeviceIoControl=EngDeviceIoControl@28 +EngEnumForms +EngEraseSurface=EngEraseSurface@12 +EngFillPath +EngFindImageProcAddress +EngFindResource +EngFreeMem=EngFreeMem@4 +EngFreeModule +EngFreeUserMem=EngFreeUserMem@4 +EngGetCurrentCodePage +EngGetDriverName +EngGetFileChangeTime +EngGetFilePath +EngGetForm +EngGetLastError +EngGetPrinter +EngGetPrinterData +EngGetPrinterDataFileName +EngGetProcessHandle +EngGetType1FontList +EngLineTo=EngLineTo@36 +EngLoadImage=EngLoadImage@4 +EngLoadModule=EngLoadModule@4 +EngLoadModuleForWrite +EngLockDriverObj +EngLockSurface=EngLockSurface@4 +EngMapEvent +EngMapFontFile +EngMapModule +EngMarkBandingSurface +EngMovePointer +EngMulDiv +EngMultiByteToUnicodeN +EngMultiByteToWideChar +EngPaint=EngPaint@20 +EngProbeForRead +; EngProbeForReadAndWrite = NTOSKRNL.ProbeForWrite +EngProbeForReadAndWrite +EngQueryLocalTime +EngQueryPalette +EngQueryPerformanceCounter +EngQueryPerformanceFrequency +EngReleaseSemaphore +EngRestoreFloatingPointState +EngSaveFloatingPointState +EngSecureMem +EngSetEvent +EngSetLastError +EngSetPointerShape +EngSetPointerTag +EngSetPrinterData +EngSort +EngStretchBlt +EngStrokeAndFillPath +EngStrokePath +EngTextOut +EngTransparentBlt=EngTransparentBlt@32 +EngUnicodeToMultiByteN +EngUnloadImage +EngUnlockDriverObj +EngUnlockSurface +EngUnmapEvent +EngUnmapFontFile +; EngUnsecureMem = NTOSKRNL.MmUnsecureVirtualMemory +EngUnsecureMem +EngWaitForSingleObject +EngWideCharToMultiByte +EngWritePrinter +FLOATOBJ_Add +FLOATOBJ_AddFloat +FLOATOBJ_AddFloatObj +FLOATOBJ_AddLong +FLOATOBJ_Div +FLOATOBJ_DivFloat +FLOATOBJ_DivFloatObj +FLOATOBJ_DivLong +FLOATOBJ_Equal +FLOATOBJ_EqualLong +FLOATOBJ_GetFloat +FLOATOBJ_GetLong +FLOATOBJ_GreaterThan +FLOATOBJ_GreaterThanLong +FLOATOBJ_LessThan +FLOATOBJ_LessThanLong +FLOATOBJ_Mul +FLOATOBJ_MulFloat +FLOATOBJ_MulFloatObj +FLOATOBJ_MulLong +FLOATOBJ_Neg +FLOATOBJ_SetFloat +FLOATOBJ_SetLong +FLOATOBJ_Sub +FLOATOBJ_SubFloat +FLOATOBJ_SubFloatObj +FLOATOBJ_SubLong +FONTOBJ_cGetAllGlyphHandles +FONTOBJ_cGetGlyphs +FONTOBJ_pifi +FONTOBJ_pvTrueTypeFontFile +FONTOBJ_pxoGetXform +FONTOBJ_vGetInfo +HT_ComputeRGBGammaTable +HT_Get8BPPFormatPalette +PALOBJ_cGetColors=PALOBJ_cGetColors@16 +PATHOBJ_bCloseFigure +PATHOBJ_bEnum +PATHOBJ_bEnumClipLines +PATHOBJ_bMoveTo +PATHOBJ_bPolyBezierTo +PATHOBJ_bPolyLineTo +PATHOBJ_vEnumStart +PATHOBJ_vEnumStartClipLines +PATHOBJ_vGetBounds +RtlAnsiCharToUnicodeChar=NTOSKRNL.RtlAnsiCharToUnicodeChar +RtlMultiByteToUnicodeN=NTOSKRNL.RtlMultiByteToUnicodeN +RtlRaiseException=NTOSKRNL.RtlRaiseException +RtlUnicodeToMultiByteN=NTOSKRNL.RtlUnicodeToMultiByteN +RtlUnicodeToMultiByteSize=NTOSKRNL.RtlUnicodeToMultiByteSize +RtlUnwind=NTOSKRNL.RtlUnwind +RtlUpcaseUnicodeChar=NTOSKRNL.RtlUpcaseUnicodeChar +RtlUpcaseUnicodeToMultiByteN=NTOSKRNL.RtlUpcaseUnicodeToMultiByteN +STROBJ_bEnum +STROBJ_dwGetCodePage +STROBJ_vEnumStart +W32kCleanupForProcess=W32kCleanupForProcess@4 +W32kInitialize=W32kInitialize@0 +WNDOBJ_bEnum +WNDOBJ_cEnumStart +WNDOBJ_vSetConsumer +XFORMOBJ_bApplyXform +XFORMOBJ_iGetFloatObjXform +XFORMOBJ_iGetXform +XLATEOBJ_cGetPalette=XLATEOBJ_cGetPalette@16 +XLATEOBJ_iXlate=XLATEOBJ_iXlate@8 +XLATEOBJ_piVector=XLATEOBJ_piVector@4 +_abnormal_termination=NTOSKRNL._abnormal_termination +;_abnormal_termination +_except_handler2=NTOSKRNL._except_handler2 +;_except_handler2 +_global_unwind2=NTOSKRNL._global_unwind2 +;_global_unwind2 +_local_unwind2=NTOSKRNL._local_unwind2 +;_local_unwind2 + diff --git a/subsys/win32k/win32k.rc b/subsys/win32k/win32k.rc new file mode 100644 index 0000000..20e669a --- /dev/null +++ b/subsys/win32k/win32k.rc @@ -0,0 +1,39 @@ + +#include "../../include/defines.h" +#include "../../include/reactos/resource.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "W32 GDI KM subsystem\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "win32k\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "win32k.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/system.hiv b/system.hiv new file mode 100644 index 0000000..c1b3b6a --- /dev/null +++ b/system.hiv @@ -0,0 +1,305 @@ +REGEDIT4 + +[\Registry\Machine\SYSTEM] + +[\Registry\Machine\SYSTEM\ControlSet001] + +[\Registry\Machine\SYSTEM\ControlSet001\Control] + +[\Registry\Machine\SYSTEM\ControlSet001\Control\NLS] + +[\Registry\Machine\SYSTEM\ControlSet001\Control\NLS\CodePage] +"10000"="c_10000.nls" +"1252"="c_1252.nls" +"437"="c_437.nls" +"850"="c_850.nls" +"ACP"="1252" +"OEMCP"="437" +"MACCP"="10000" + +[\Registry\Machine\SYSTEM\ControlSet001\Control\NLS\Language] +"0401"="l_intl.nls" +"0402"="l_intl.nls" +"0403"="l_intl.nls" +"0404"="l_intl.nls" +"0405"="l_intl.nls" +"0406"="l_intl.nls" +"0407"="l_intl.nls" +"0408"="l_intl.nls" +"0409"="l_intl.nls" +"040a"="l_intl.nls" +"040b"="l_intl.nls" +"040c"="l_intl.nls" +"040d"="l_intl.nls" +"040e"="l_intl.nls" +"040f"="l_intl.nls" +"0410"="l_intl.nls" +"Default"="0409" +"InstallLanguage"="0409" + +[\Registry\Machine\SYSTEM\ControlSet001\Control\ServiceGroupOrder] +"List"=multi:"SCSI Port", "SCSI Miniport", "Primary Disk", "SCSI Class Helper", \ + "SCSI Class", "Boot File System", "Base", "Pointer Port", \ + "Keyboard Port", "Pointer Class", "Keyboard Class", "Debug", \ + "Video Init", "Video", "File System", "Event log", "NDIS", \ + "PNP_TDI", "TDI", "Extended Base" + +[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager] +"BootExecute"=multi:"autocheck autochk *" +"ObjectDirectories"=multi:"\Windows", "\RPC Control" + +[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager\DOS Devices] +"AUX"="\DosDevices\COM1" +"MAILSLOT"="\Device\MailSlot" +"NUL"="\Device\Null" +"PIPE"="\Device\NamedPipe" +"PRN"="\DosDevices\LPT1" +"UNC"="\Device\Mup" + +[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager\Environment] +"ComSpec"=expand:"%SystemRoot%\system32\shell.exe" +"OS"=expand:"ReactOS" +"Path"=expand:"%SystemRoot%\system32;%SystemRoot%" +"windir"=expand:"%SystemRoot%" + +[\Registry\Machine\SYSTEM\ControlSet001\Control\Session Manager\Memory Management] +"PagingFiles"=multi:"C:\reactos\pagefile.sys" + +[\Registry\Machine\SYSTEM\ControlSet001\Services] + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Afd] +"ErrorControl"=dword:00000001 +"Group"="TDI" +"ImagePath"=expand:"system32\drivers\afd.sys" +"Start"=dword:00000002 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Atapi] +"ErrorControl"=dword:00000000 +"Group"="SCSI Miniport" +"ImagePath"=expand:"system32\drivers\atapi.sys" +"Start"=dword:00000000 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Beep] +"ErrorControl"=dword:00000000 +"Group"="Base" +"ImagePath"=expand:"system32\drivers\beep.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Blue] +"ErrorControl"=dword:00000000 +"Group"="Video Init" +"ImagePath"=expand:"system32\drivers\blue.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Cdfs] +"ErrorControl"=dword:00000000 +"Group"="File System" +"ImagePath"=expand:"system32\drivers\cdfs.sys" +"Start"=dword:00000003 +"Type"=dword:00000002 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Cdrom] +"ErrorControl"=dword:00000000 +"Group"="SCSI Class" +"ImagePath"=expand:"system32\drivers\cdrom.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Class2] +"ErrorControl"=dword:00000000 +"Group"="SCSI Class Helper" +"ImagePath"=expand:"system32\drivers\class2.sys" +"Start"=dword:00000000 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Disk] +"ErrorControl"=dword:00000000 +"Group"="SCSI Class" +"ImagePath"=expand:"system32\drivers\disk.sys" +"Start"=dword:00000000 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\EventLog] +"ErrorControl"=dword:00000000 +"Group"="Event log" +"ImagePath"=expand:"%SystemRoot%\system32\eventlog.exe" +"Start"=dword:00000004 +"Type"=dword:00000010 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Floppy] +"ErrorControl"=dword:00000000 +"Group"="Primary Disk" +"ImagePath"=expand:"system32\drivers\floppy.sys" +"Start"=dword:00000004 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Fs_Rec] +"ErrorControl"=dword:00000000 +"Group"="Boot file system" +"ImagePath"=expand:"system32\drivers\fs_rec.sys" +"Start"=dword:00000001 +"Type"=dword:00000008 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Ide] +"ErrorControl"=dword:00000000 +"Group"="Primary Disk" +"ImagePath"=expand:"system32\drivers\ide.sys" +"Start"=dword:00000004 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Keyboard] +"ErrorControl"=dword:00000000 +"Group"="Keyboard Port" +"ImagePath"=expand:"system32\drivers\keyboard.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Msfs] +"ErrorControl"=dword:00000000 +"Group"="File System" +"ImagePath"=expand:"system32\drivers\msfs.sys" +"Start"=dword:00000001 +"Type"=dword:00000002 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Ndis] +"ErrorControl"=dword:00000001 +"Group"="NDIS" +"ImagePath"=expand:"system32\drivers\ndis.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Ne2000] +"ErrorControl"=dword:00000001 +"Group"="NDIS" +"ImagePath"=expand:"system32\drivers\ne2000.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Npfs] +"ErrorControl"=dword:00000000 +"Group"="File System" +"ImagePath"=expand:"system32\drivers\npfs.sys" +"Start"=dword:00000001 +"Type"=dword:00000002 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Ntfs] +"ErrorControl"=dword:00000000 +"Group"="File System" +"ImagePath"=expand:"system32\drivers\ntfs.sys" +"Start"=dword:00000003 +"Type"=dword:00000002 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Null] +"ErrorControl"=dword:00000000 +"Group"="Base" +"ImagePath"=expand:"system32\drivers\null.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Serial] +"ErrorControl"=dword:00000000 +"Group"="Base" +"ImagePath"=expand:"system32\drivers\serial.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Pice] +"ErrorControl"=dword:00000000 +"Group"="Debug" +"ImagePath"=expand:"system32\drivers\pice.sys" +"Start"=dword:00000004 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\RpcSs] +"ErrorControl"=dword:00000001 +"ImagePath"=expand:"%SystemRoot%\system32\rpcss.exe" +"Start"=dword:00000004 +"Type"=dword:00000010 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Scsiport] +"ErrorControl"=dword:00000000 +"Group"="SCSI Port" +"ImagePath"=expand:"system32\drivers\scsiport.sys" +"Start"=dword:00000000 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Tcpip] +"ErrorControl"=dword:00000001 +"Group"="PNP_TDI" +"ImagePath"=expand:"system32\drivers\tcpip.sys" +"Start"=dword:00000002 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Packet] +"ErrorControl"=dword:00000001 +"Group"="PNP_TDI" +"ImagePath"=expand:"system32\drivers\packet.sys" +"Start"=dword:00000002 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Vfatfs] +"ErrorControl"=dword:00000000 +"Group"="Boot File System" +"ImagePath"=expand:"system32\drivers\vfatfs.sys" +"Start"=dword:00000000 +"Type"=dword:00000002 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Vga] +"ErrorControl"=dword:00000000 +"Group"="Video" +"ImagePath"=expand:"system32\drivers\vgamp.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Mouse] +"ErrorControl"=dword:00000000 +"Group"="Pointer Class" +"ImagePath"=expand:"system32\drivers\mouclass.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Psaux] +"ErrorControl"=dword:00000000 +"Group"="Pointer Port" +"ImagePath"=expand:"system32\drivers\psaux.sys" +"Start"=dword:00000001 +"Type"=dword:00000001 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Tcpip\Linkage] +"Bind"=expand:"\Device\ne2000" +"Export"=expand:"\Device\tcpip" +"Route"=expand:"" + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Tcpip\Parameters] +"DataBasePath"="DataBasePath" +"Domain"="" +"Hostname"="ROSHost" +"NameServer"="203.13.174.1" +"ForwardBroadcasts"=dword:00000000 +"IPEnableRouter"=dword:00000000 +"SearchList"="" +"EnableSecurityFilters"=dword:00000000 + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Packet\Linkage] +"Bind"=expand:"\Device\ne2000" +"Export"=expand:"\Device\packet" + +[\Registry\Machine\SYSTEM\ControlSet001\Services\Tcpip\Parameters\PersistentRoutes] + +[\Registry\Machine\SYSTEM\ControlSet002] + +[\Registry\Machine\SYSTEM\Select] +"Current"=dword:00000001 +"Default"=dword:00000001 +"Failed"=dword:00000000 +"LastKnownGood"=dword:00000000 + +[\Registry\Machine\SYSTEM\Setup] +"CmdLine"="setup -newsetup" +"OsLoaderPath"="\" +"SetupType"=dword:00000000 +"SystemPartition"="\Device\HarddiskVolume1" diff --git a/tools/.cvsignore b/tools/.cvsignore new file mode 100644 index 0000000..7cc43f5 --- /dev/null +++ b/tools/.cvsignore @@ -0,0 +1,9 @@ +*.exe +buildno +depends +rcopy +rmkdir +rrmdir +mkconfig +rdel +rsym diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 0000000..5f7f828 --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,79 @@ +PATH_TO_TOP = .. + +TOOLS = \ + buildno$(EXE_POSTFIX) \ + depends$(EXE_POSTFIX) \ + rcopy$(EXE_POSTFIX) \ + rdel$(EXE_POSTFIX) \ + rmkdir$(EXE_POSTFIX) \ + rrmdir$(EXE_POSTFIX) \ + rsym$(EXE_POSTFIX) + +CLEAN_FILES = $(TOOLS) + +all: $(TOOLS) wmc_directory_target + +buildno$(EXE_POSTFIX): buildno.c ../include/reactos/version.h + $(HOST_CC) $(CFLAGS) -o buildno$(EXE_POSTFIX) buildno.c + $(EXE_PREFIX)buildno$(EXE_POSTFIX) + +depends$(EXE_POSTFIX): depends.c + $(HOST_CC) $(CFLAGS) -o depends$(EXE_POSTFIX) depends.c + +ifeq ($(HOST),mingw32-linux) +rcopy$(EXE_POSTFIX): rcopy.c + $(HOST_CC) $(CFLAGS) -DUNIX_PATHS rcopy.c -o rcopy$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +rcopy$(EXE_POSTFIX): rcopy.c + $(HOST_CC) $(CFLAGS) -DDOS_PATHS rcopy.c -o rcopy$(EXE_POSTFIX) +endif + +rdel$(EXE_POSTFIX): rdel.c + $(HOST_CC) $(CFLAGS) rdel.c -o rdel$(EXE_POSTFIX) + +ifeq ($(HOST),mingw32-linux) +rmkdir$(EXE_POSTFIX): rmkdir.c + $(HOST_CC) $(CFLAGS) -DUNIX_PATHS rmkdir.c -o rmkdir$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +rmkdir$(EXE_POSTFIX): rmkdir.c + $(HOST_CC) $(CFLAGS) -DDOS_PATHS rmkdir.c -o rmkdir$(EXE_POSTFIX) +endif + +ifeq ($(HOST),mingw32-linux) +rrmdir$(EXE_POSTFIX): rrmdir.c + $(HOST_CC) $(CFLAGS) -DUNIX_PATHS rrmdir.c -o rrmdir$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +rrmdir$(EXE_POSTFIX): rrmdir.c + $(HOST_CC) $(CFLAGS) -DDOS_PATHS rrmdir.c -o rrmdir$(EXE_POSTFIX) +endif + +ifeq ($(HOST),mingw32-linux) +rsym$(EXE_POSTFIX): rsym.c + $(HOST_CC) $(CFLAGS) -DUNIX_PATHS rsym.c -o rsym$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +rsym$(EXE_POSTFIX): rsym.c + $(HOST_CC) $(CFLAGS) -DDOS_PATHS rsym.c -o rsym$(EXE_POSTFIX) +endif + +wmc_directory_target: + make -C wmc wmc$(EXE_POSTFIX) + +ifeq ($(HOST),mingw32-linux) +clean: + make -C wmc clean + rm mkconfig + rm $(TOOLS) +endif +ifeq ($(HOST),mingw32-windows) +clean: + make -C wmc clean + del *$(EXE_POSTFIX) +endif + +.PHONY: all clean + +include $(PATH_TO_TOP)/rules.mak diff --git a/tools/buildno.c b/tools/buildno.c new file mode 100644 index 0000000..a014862 --- /dev/null +++ b/tools/buildno.c @@ -0,0 +1,329 @@ +/* $Id$ + * + * buildno - Generate the build number for ReactOS + * + * Copyright (c) 1999,2000 Emanuele Aliberti + * + * License: GNU GPL + * + * It assumes the last release date is defined in + * as a macro named + * + * KERNEL_RELEASE_DATE + * + * as a 32-bit unsigned long YYYYMMDD (UTC; + * MM=01-12; DD=01-31). + * + * The build number is the number of full days + * elapsed since the last release date (UTC). + * + * The build number is stored in the file + * as a set of macros: + * + * KERNEL_VERSION_BUILD base 10 number + * KERNEL_VERSION_BUILD_STR C string + * KERNEL_VERSION_BUILD_RC RC string + * + * REVISIONS + * --------- + * 2000-01-22 (ea) + * Fixed bugs: tm_year is (current_year - 1900), + * tm_month is 0-11 not 1-12 and code ignored TZ. + * 2000-12-10 (ea) + * Added -p option to make it simply print the + * version number, but skip buildno.h generation. + */ +#include +#include +#include +#include "../include/reactos/version.h" + +#define FALSE 0 +#define TRUE 1 + +/* File to (over)write */ +#define BUILDNO_INCLUDE_FILE "../include/reactos/buildno.h" + +static char * argv0 = ""; + +#ifdef DBG +void +tm_dump (const char *tag, struct tm * t) +{ + printf ("%s->tm_sec = %d\n", tag, t->tm_sec); + printf ("%s->tm_min = %d\n", tag, t->tm_min); + printf ("%s->tm_hour = %d\n", tag, t->tm_hour); + printf ("%s->tm_mday = %d\n", tag, t->tm_mday); + printf ("%s->tm_mon = %d\n", tag, t->tm_mon); + printf ("%s->tm_year = %d\n", tag, t->tm_year); + printf ("%s->tm_wday = %d\n", tag, t->tm_wday); + printf ("%s->tm_yday = %d\n", tag, t->tm_yday); + printf ("%s->tm_isdst = %d\n\n", tag, t->tm_isdst); +} +#endif + + +int +elapsed_days ( + time_t t_today, + time_t t_release_day + ) +{ + double seconds = difftime (t_today, t_release_day); + double days = seconds / (double) 86400.0; + char buf [32]; + char * dot = buf; + + sprintf (buf, "%f", days ); + + while ( *dot && *dot != '.') ++dot; + *dot = '\0'; + + return atol (buf); +} + +void +write_h (int build) +{ + FILE *h = NULL; + char* s; + char* s1; + int length; + + s1 = s = malloc(256 * 1024); + + s = s + sprintf (s, "/* Do not edit - Machine generated */\n"); + + s = s + sprintf (s, "#ifndef _INC_REACTOS_BUILDNO\n" ); + s = s + sprintf (s, "#define _INC_REACTOS_BUILDNO\n" ); + + s = s + sprintf (s, "#define KERNEL_VERSION_BUILD\t%d\n", build); + s = s + sprintf (s, "#define KERNEL_VERSION_BUILD_STR\t\"%d\"\n", build); + s = s + sprintf (s, "#define KERNEL_RELEASE_RC\t\"%d.%d.%d.%d\\0\"\n", + KERNEL_VERSION_MAJOR, KERNEL_VERSION_MINOR, + KERNEL_VERSION_PATCH_LEVEL, build); + s = s + sprintf (s, "#define KERNEL_RELEASE_STR\t\"%d.%d.%d.%d\"\n", + KERNEL_VERSION_MAJOR, + KERNEL_VERSION_MINOR, + KERNEL_VERSION_PATCH_LEVEL, + build); + s = s + sprintf (s, "#define KERNEL_VERSION_RC\t\"%d.%d.%d\\0\"\n", + KERNEL_VERSION_MAJOR, + KERNEL_VERSION_MINOR, + KERNEL_VERSION_PATCH_LEVEL); + s = s + sprintf (s, "#define KERNEL_VERSION_STR\t\"%d.%d.%d\"\n", + KERNEL_VERSION_MAJOR, + KERNEL_VERSION_MINOR, + KERNEL_VERSION_PATCH_LEVEL); + s = s + sprintf (s, "#endif\n/* EOF */\n"); + + h = fopen (BUILDNO_INCLUDE_FILE, "r"); + if (h != NULL) + { + fseek(h, 0, SEEK_END); + length = ftell(h); + if (length == strlen(s1)) + { + char* orig; + + orig = malloc(length); + fseek(h, 0, SEEK_SET); + fread(orig, 1, length, h); + if (memcmp(s1, orig, length) == 0) + { + fclose(h); + return; + } + } + fclose(h); + } + + h = fopen (BUILDNO_INCLUDE_FILE, "w"); + if (!h) + { + fprintf (stderr, + "%s: can not create file \"%s\"!\n", + argv0, + BUILDNO_INCLUDE_FILE); + return; + } + fwrite(s1, 1, strlen(s1), h); + fclose (h); +} + +void +usage (void) +{ + fprintf ( + stderr, + "Usage: %s [-{p|q}]\n\n -p print version number and exit\n -q run in quiet mode\n", + argv0 + ); + exit (EXIT_SUCCESS); +} + + +int +main (int argc, char * argv []) +{ + int print_only = FALSE; + int quiet = FALSE; + + int year = 0; + int month = 0; + int day = 0; + int build = 0; + + time_t t0 = 0; + struct tm t0_tm = {0}; + time_t t1 = 0; + struct tm * t1_tm = NULL; + + argv0 = argv[0]; + + switch (argc) + { + case 1: + break; + case 2: + if (argv[1][0] == '-') + { + if (argv[1][1] == 'q') + { + quiet = TRUE; + } + else if (argv[1][1] == 'p') + { + print_only = TRUE; + } + else + { + usage (); + } + } + else + { + usage (); + } + break; + default: + usage (); + } + /* + * Set TZ information. + */ + tzset (); + /* + * We are building TODAY! + */ + time (& t0); + /* + * "Parse" the release date. + */ + day = KERNEL_RELEASE_DATE % 100; + month = ( ( KERNEL_RELEASE_DATE + % 10000 + ) + - day + ) + / 100; + year = + ( KERNEL_RELEASE_DATE + - (month * 100) + - day + ) + / 10000; + if (FALSE == quiet) + { + printf ( "\n\ +ReactOS Build Number Generator\n\n\ +Last release: %4d-%02d-%02d\n", + year, + month, + day + ); + } +#ifdef DBG + tm_dump ("t0", & t0_tm); +#endif + t0_tm.tm_year = (year - 1900); + t0_tm.tm_mon = --month; /* 0-11 */ + t0_tm.tm_mday = day; + t0_tm.tm_hour = 0; + t0_tm.tm_min = 0; + t0_tm.tm_sec = 1; + t0_tm.tm_isdst = -1; + +#ifdef DBG + tm_dump ("t0", & t0_tm); +#endif + + if (-1 == (t0 = mktime (& t0_tm))) + { + fprintf ( + stderr, + "%s: can not convert release date!\n", + argv[0] + ); + return EXIT_FAILURE; + } + + time (& t1); /* current build time */ + t1_tm = gmtime (& t1); + +#ifdef DBG + tm_dump ("t1", t1_tm); +#endif + t1_tm->tm_year += + (t1_tm->tm_year < 70) + ? 2000 + : 1900; +#ifdef DBG + tm_dump ("t1", t1_tm); +#endif + if (FALSE == quiet) + { + printf ( + "Current date: %4d-%02d-%02d\n\n", + t1_tm->tm_year, + (t1_tm->tm_mon + 1), + t1_tm->tm_mday + ); + } + /* + * Compute delta days. + */ + build = elapsed_days (t1, t0); + + if (FALSE == quiet) + { + printf ( + "Build number: %d (elapsed days since last release)\n", + build + ); + printf ( + "ROS Version : %d.%d.%d.%d\n", + KERNEL_VERSION_MAJOR, + KERNEL_VERSION_MINOR, + KERNEL_VERSION_PATCH_LEVEL, + build + ); + } + /* + * (Over)write the include file, unless + * the user switched on -p. + */ + if (FALSE == print_only) + { + write_h (build); + } + else + { + printf ("%s: no code generated", argv [0]); + } + + return EXIT_SUCCESS; +} + + +/* EOF */ diff --git a/tools/config.mk b/tools/config.mk new file mode 100644 index 0000000..d35948e --- /dev/null +++ b/tools/config.mk @@ -0,0 +1,36 @@ +# Global configuration + +# +# Include details of the OS configuration +# +include $(PATH_TO_TOP)/config + +CONFIG := + +ifeq ($(DBG), 1) +CONFIG += DBG +endif + +ifeq ($(KDBG), 1) +CONFIG += KDBG +endif + +ifeq ($(MP), 1) +CONFIG += MP +else +CONFIG += UP +endif + +ifeq ($(ACPI), 1) +CONFIG += ACPI +endif + + +$(PATH_TO_TOP)/tools/mkconfig$(EXE_POSTFIX): $(PATH_TO_TOP)/tools/mkconfig.c + $(HOST_CC) -g -o $(PATH_TO_TOP)/tools/mkconfig$(EXE_POSTFIX) $(PATH_TO_TOP)/tools/mkconfig.c + +$(PATH_TO_TOP)/config: $(PATH_TO_TOP)/tools/mkconfig$(EXE_POSTFIX) + $(PATH_TO_TOP)/tools/mkconfig$(EXE_POSTFIX) $(PATH_TO_TOP)/include/roscfg.h$(CONFIG) + +$(PATH_TO_TOP)/include/roscfg.h: $(PATH_TO_TOP)/config + $(PATH_TO_TOP)/tools/mkconfig$(EXE_POSTFIX) $(PATH_TO_TOP)/include/roscfg.h$(CONFIG) diff --git a/tools/create_nls/Makefile b/tools/create_nls/Makefile new file mode 100644 index 0000000..7056ce8 --- /dev/null +++ b/tools/create_nls/Makefile @@ -0,0 +1,54 @@ +# +# ReactOS/NLS conversion tool +# +PATH_TO_TOP = ../.. + +TARGET=create_nls$(EXE_POSTFIX) + +all: $(TARGET) + +OBJECTS = create_nls.o + +CLEAN_FILES = *.o create_nls$(EXE_POSTFIX) + +create_nls$(EXE_POSTFIX): $(OBJECTS) + $(HOST_CC) $(OBJECTS) -o create_nls$(EXE_POSTFIX) + +HOST_CFLAGS = -I. + +create_nls.o: create_nls.c + $(HOST_CC) $(HOST_CFLAGS) -c create_nls.c -o create_nls.o + +ifeq ($(HOST),mingw32-linux) +clean: + rm -f *.o + rm -f create_nls$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +clean: + del *.o + del create_nls$(EXE_POSTFIX) +endif + +.phony: clean + +nls: + create_nls$(EXE_POSTFIX) + +.phony: nls + +ifeq ($(HOST),mingw32-linux) +clean_nls: + rm -f ../../media/nls/*.nls +endif +ifeq ($(HOST),mingw32-windows) +clean_nls: + del ..\..\media\nls\*.nls +endif + +.phony: clean_nls + + +include $(PATH_TO_TOP)/rules.mak + +# EOF diff --git a/tools/create_nls/Readme b/tools/create_nls/Readme new file mode 100644 index 0000000..e72804b --- /dev/null +++ b/tools/create_nls/Readme @@ -0,0 +1,23 @@ +Create_nls - .nls file creation tool +------------------------------------ + +Create_nls is a tool to create binary .nls files from codepage mapping +files provided by Unicode Inc. Due to the confusing license these files +are not part of the ReactOS source tree. + + +You can easily download the files from 'http://www.unicode.org/public' or +'ftp://ftp.unicode.org/pub'. Download the directory structure of the web/ftp +site into the unicode.org subdirectory and create_nls will build the .nls +files. + +Makefile targets: + 'make': builds create_nls tool. + 'make clean': deletes all executable and object files + 'make nls': generates binary .nls files. + 'make clean_nls': deletes binary .nls files. + +Since the binary .nls files are part of the ReactOS source tree it is not +necessary to build these files yourself. Therefore create_nls is not +integrated with the main makefile. You will have to build and run it +separately. diff --git a/tools/create_nls/create_nls.c b/tools/create_nls/create_nls.c new file mode 100644 index 0000000..c3c31ba --- /dev/null +++ b/tools/create_nls/create_nls.c @@ -0,0 +1,965 @@ +/* + * Tool for creating NT-like NLS files for Unicode <-> Codepage conversions. + * Tool for creating NT-like l_intl.nls file for case mapping of unicode + * characters. + * Copyright 2000 Timoshkov Dmitry + * Copyright 2001 Matei Alexandru + * + * Sources of information: + * Andrew Kozin's YAW project http://www.chat.ru/~stanson/yaw_en.html + * Ove Kõven's investigations http://www.ping.uio.no/~ovehk/nls + */ +#include +#include +#include +#include +#include +#include + +static const WCHAR * const uprtable[256]; +static const WCHAR * const lwrtable[256]; + +#define NLSDIR "../../media/nls" +#define LIBDIR "unicode.org/" + +typedef struct { + WORD wSize; /* in words 0x000D */ + WORD CodePage; + WORD MaxCharSize; /* 1 or 2 */ + BYTE DefaultChar[MAX_DEFAULTCHAR]; + WCHAR UnicodeDefaultChar; + WCHAR unknown1; + WCHAR unknown2; + BYTE LeadByte[MAX_LEADBYTES]; +} __attribute__((packed)) NLS_FILE_HEADER; + +/* +Support for translation from the multiple unicode chars +to the single code page char. + +002D;HYPHEN-MINUS;Pd;0;ET;;;;;N;;;;; +00AD;SOFT HYPHEN;Pd;0;ON;;;;;N;;;;; +2010;HYPHEN;Pd;0;ON;;;;;N;;;;; +2011;NON-BREAKING HYPHEN;Pd;0;ON; 2010;;;;N;;;;; +2013;EN DASH;Pd;0;ON;;;;;N;;;;; +2014;EM DASH;Pd;0;ON;;;;;N;;;;; +2015;HORIZONTAL BAR;Pd;0;ON;;;;;N;QUOTATION DASH;;;; +*/ + +/* HYPHEN-MINUS aliases */ +static WCHAR hyphen_aliases[] = {0x00AD,0x2010,0x2011,0x2013,0x2014,0x2015,0}; + +static struct { + WCHAR cp_char; + WCHAR *alias; /* must be 0 terminated */ +} u2cp_alias[] = { +/* HYPHEN-MINUS aliases */ +{0x002D, hyphen_aliases} +}; + +static void patch_aliases(void *u2cp, CPINFOEXA *cpi) +{ + int i, j; + WCHAR *wc, *alias; + BYTE *c; + + if(cpi->MaxCharSize == 2) { + wc = (WCHAR *)u2cp; + for(i = 0; i < 65536; i++) { + for(j = 0; j < sizeof(u2cp_alias)/sizeof(u2cp_alias[0]); j++) { + alias = u2cp_alias[j].alias; + while(*alias) { + if(*alias == i && wc[i] == *(WCHAR *)cpi->DefaultChar) { + wc[i] = u2cp_alias[j].cp_char; + } + alias++; + } + } + } + } + else { + c = (BYTE *)u2cp; + for(i = 0; i < 65536; i++) { + for(j = 0; j < sizeof(u2cp_alias)/sizeof(u2cp_alias[0]); j++) { + alias = u2cp_alias[j].alias; + while(*alias) { + if(*alias == i && c[i] == cpi->DefaultChar[0] && u2cp_alias[j].cp_char < 256) { + c[i] = (BYTE)u2cp_alias[j].cp_char; + } + alias++; + } + } + } + } +} + +static BOOL write_unicode2cp_table(FILE *out, CPINFOEXA *cpi, WCHAR *table) +{ + void *u2cp; + WCHAR *wc; + CHAR *c; + int i; + BOOL ret = TRUE; + + u2cp = malloc(cpi->MaxCharSize * 65536); + if(!u2cp) { + printf("Not enough memory for Unicode to Codepage table\n"); + return FALSE; + } + + if(cpi->MaxCharSize == 2) { + wc = (WCHAR *)u2cp; + for(i = 0; i < 65536; i++) + wc[i] = *(WCHAR *)cpi->DefaultChar; + + for(i = 0; i < 65536; i++) + if (table[i] != '?') + wc[table[i]] = (WCHAR)i; + } + else { + c = (CHAR *)u2cp; + for(i = 0; i < 65536; i++) + c[i] = cpi->DefaultChar[0]; + + for(i = 0; i < 256; i++) + if (table[i] != '?') + c[table[i]] = (CHAR)i; + } + + patch_aliases(u2cp, cpi); + + if(fwrite(u2cp, 1, cpi->MaxCharSize * 65536, out) != cpi->MaxCharSize * 65536) + ret = FALSE; + + free(u2cp); + + return ret; +} + +static BOOL write_lb_ranges(FILE *out, CPINFOEXA *cpi, WCHAR *table) +{ + WCHAR sub_table[256]; + WORD offset, offsets[256]; + int i, j, range; + + memset(offsets, 0, sizeof(offsets)); + + offset = 0; + + for(i = 0; i < MAX_LEADBYTES; i += 2) { + for(range = cpi->LeadByte[i]; range != 0 && range <= cpi->LeadByte[i + 1]; range++) { + offset += 256; + offsets[range] = offset; + } + } + + if(fwrite(offsets, 1, sizeof(offsets), out) != sizeof(offsets)) + return FALSE; + + for(i = 0; i < MAX_LEADBYTES; i += 2) { + for(range = cpi->LeadByte[i]; range != 0 && range <= cpi->LeadByte[i + 1]; range++) { + /*printf("Writing sub table for LeadByte %02X\n", range);*/ + for(j = MAKEWORD(0, range); j <= MAKEWORD(0xFF, range); j++) { + sub_table[j - MAKEWORD(0, range)] = table[j]; + } + + if(fwrite(sub_table, 1, sizeof(sub_table), out) != sizeof(sub_table)) + return FALSE; + } + } + + return TRUE; +} + +static BOOL create_nls_file(char *name, CPINFOEXA *cpi, WCHAR *table, WCHAR *oemtable) +{ + FILE *out; + NLS_FILE_HEADER nls; + WORD wValue, number_of_lb_ranges, number_of_lb_subtables, i; + + printf("Creating NLS table \"%s\"\n", name); + + if(!(out = fopen(name, "wb"))) { + printf("Could not create file \"%s\"\n", name); + return FALSE; + } + + memset(&nls, 0, sizeof(nls)); + + nls.wSize = sizeof(nls) / sizeof(WORD); + nls.CodePage = cpi->CodePage; + nls.MaxCharSize = cpi->MaxCharSize; + memcpy(nls.DefaultChar, cpi->DefaultChar, MAX_DEFAULTCHAR); + nls.UnicodeDefaultChar = cpi->UnicodeDefaultChar; + nls.unknown1 = '?'; + nls.unknown2 = '?'; + memcpy(nls.LeadByte, cpi->LeadByte, MAX_LEADBYTES); + + if(fwrite(&nls, 1, sizeof(nls), out) != sizeof(nls)) { + fclose(out); + printf("Could not write to file \"%s\"\n", name); + return FALSE; + } + + number_of_lb_ranges = 0; + number_of_lb_subtables = 0; + + for(i = 0; i < MAX_LEADBYTES; i += 2) { + if(cpi->LeadByte[i] != 0 && cpi->LeadByte[i + 1] > cpi->LeadByte[i]) { + number_of_lb_ranges++; + number_of_lb_subtables += cpi->LeadByte[i + 1] - cpi->LeadByte[i] + 1; + } + } + + /*printf("Number of LeadByte ranges %d\n", number_of_lb_ranges);*/ + /*printf("Number of LeadByte subtables %d\n", number_of_lb_subtables);*/ + + /* Calculate offset to Unicode to CP table in words: + * 1. (256 * sizeof(WORD)) primary CP to Unicode table + + * 2. (WORD) optional OEM glyph table size in words + + * 3. OEM glyph table size in words * sizeof(WORD) + + * 4. (WORD) Number of DBCS LeadByte ranges + + * 5. if (Number of DBCS LeadByte ranges != 0) 256 * sizeof(WORD) offsets of lead byte sub tables + * 6. (Number of DBCS LeadByte sub tables * 256 * sizeof(WORD)) LeadByte sub tables + + * 7. (WORD) Unknown flag + */ + + wValue = (256 * sizeof(WORD) + /* 1 */ + sizeof(WORD) + /* 2 */ + ((oemtable !=NULL) ? (256 * sizeof(WORD)) : 0) + /* 3 */ + sizeof(WORD) + /* 4 */ + ((number_of_lb_subtables != 0) ? 256 * sizeof(WORD) : 0) + /* 5 */ + number_of_lb_subtables * 256 * sizeof(WORD) + /* 6 */ + sizeof(WORD) /* 7 */ + ) / sizeof(WORD); + + /* offset of Unicode to CP table in words */ + fwrite(&wValue, 1, sizeof(wValue), out); + + /* primary CP to Unicode table */ + if(fwrite(table, 1, 256 * sizeof(WCHAR), out) != 256 * sizeof(WCHAR)) { + fclose(out); + printf("Could not write to file \"%s\"\n", name); + return FALSE; + } + + /* optional OEM glyph table size in words */ + wValue = (oemtable != NULL) ? (256 * sizeof(WORD)) : 0; + fwrite(&wValue, 1, sizeof(wValue), out); + + /* optional OEM to Unicode table */ + if (oemtable) { + if(fwrite(oemtable, 1, 256 * sizeof(WCHAR), out) != 256 * sizeof(WCHAR)) { + fclose(out); + printf("Could not write to file \"%s\"\n", name); + return FALSE; + } + } + + /* Number of DBCS LeadByte ranges */ + fwrite(&number_of_lb_ranges, 1, sizeof(number_of_lb_ranges), out); + + /* offsets of lead byte sub tables and lead byte sub tables */ + if(number_of_lb_ranges > 0) { + if(!write_lb_ranges(out, cpi, table)) { + fclose(out); + printf("Could not write to file \"%s\"\n", name); + return FALSE; + } + } + + /* Unknown flag */ + wValue = 0; + fwrite(&wValue, 1, sizeof(wValue), out); + + if(!write_unicode2cp_table(out, cpi, table)) { + fclose(out); + printf("Could not write to file \"%s\"\n", name); + return FALSE; + } + + fclose(out); + return TRUE; +} + +/* correct the codepage information such as default chars */ +static void patch_codepage_info(CPINFOEXA *cpi) +{ + /* currently nothing */ +} + +static WCHAR *Load_CP2Unicode_Table(char *table_name, UINT cp, CPINFOEXA *cpi) +{ + char buf[256]; + char *p; + DWORD n, value; + FILE *file; + WCHAR *table; + int lb_ranges, lb_range_started, line; + + printf("Loading translation table \"%s\"\n", table_name); + + /* Init to default values */ + memset(cpi, 0, sizeof(CPINFOEXA)); + cpi->CodePage = cp; + *(WCHAR *)cpi->DefaultChar = '?'; + cpi->MaxCharSize = 1; + cpi->UnicodeDefaultChar = '?'; + + patch_codepage_info(cpi); + + table = (WCHAR *)malloc(sizeof(WCHAR) * 65536); + if(!table) { + printf("Not enough memory for Codepage to Unicode table\n"); + return NULL; + } + + for(n = 0; n < 256; n++) + table[n] = (WCHAR)n; + + for(n = 256; n < 65536; n++) + table[n] = cpi->UnicodeDefaultChar; + + file = fopen(table_name, "r"); + if(file == NULL) { + free(table); + return NULL; + } + + line = 0; + lb_ranges = 0; + lb_range_started = 0; + + while(fgets(buf, sizeof(buf), file)) { + line++; + p = buf; + while(isspace(*p)) p++; + + if(!*p || p[0] == '#') + continue; + + n = strtol(p, &p, 0); + if(n > 0xFFFF) { + printf("Line %d: Entry 0x%06lX: File \"%s\" corrupted\n", line, n, table_name); + continue; + } + + if(n > 0xFF && cpi->MaxCharSize != 2) { + /*printf("Line %d: Entry 0x%04lX: Switching to DBCS\n", line, n);*/ + cpi->MaxCharSize = 2; + } + + while(isspace(*p)) p++; + + if(!*p || p[0] == '#') { + /*printf("Line %d: Entry 0x%02lX has no Unicode value\n", line, n);*/ + } + else { + value = strtol(p, &p, 0); + if(value > 0xFFFF) { + printf("Line %d: Entry 0x%06lX unicode value: File \"%s\" corrupted\n", line, n, table_name); + } + table[n] = (WCHAR)value; + } + + /* wait for comment */ + while(*p && *p != '#') p++; + + if(*p == '#' && strstr(p, "DBCS LEAD BYTE")) { + /*printf("Line %d, entry 0x%02lX DBCS LEAD BYTE\n", line, n);*/ + if(n > 0xFF) { + printf("Line %d: Entry 0x%04lX: Error: DBCS lead byte overflowed\n", line, n); + continue; + } + + table[n] = (WCHAR)0; + + if(lb_range_started) { + cpi->LeadByte[(lb_ranges - 1) * 2 + 1] = (BYTE)n; + } + else { + /*printf("Line %d: Starting new DBCS lead byte range, entry 0x%02lX\n", line, n);*/ + if(lb_ranges < MAX_LEADBYTES/2) { + lb_ranges++; + lb_range_started = 1; + cpi->LeadByte[(lb_ranges - 1) * 2] = (BYTE)n; + } + else + printf("Line %d: Error: could not start new lead byte range\n", line); + } + } + else { + if(lb_range_started) + lb_range_started = 0; + } + } + + fclose(file); + + return table; +} + +static WCHAR *Load_OEM2Unicode_Table(char *table_name, WCHAR *def_table, UINT cp, CPINFOEXA *cpi) +{ + char buf[256]; + char *p; + DWORD n, value; + FILE *file; + WCHAR *table; + int line; + + printf("Loading oem glyph table \"%s\"\n", table_name); + + table = (WCHAR *)malloc(sizeof(WCHAR) * 65536); + if(!table) { + printf("Not enough memory for Codepage to Unicode table\n"); + return NULL; + } + + memcpy(table, def_table, 65536 * sizeof(WCHAR)); + + file = fopen(table_name, "r"); + if(file == NULL) { + free(table); + return NULL; + } + + while(fgets(buf, sizeof(buf), file)) { + line++; + p = buf; + while(isspace(*p)) p++; + + if(!*p || p[0] == '#') + continue; + + value = strtol(p, &p, 16); + if(value > 0xFFFF) { + printf("Line %d: Entry 0x%06lX: File \"%s\" corrupted\n", line, value, table_name); + continue; + } + + while(isspace(*p)) p++; + + if(!*p || p[0] == '#') { + /*printf("Line %d: Entry 0x%02lX has no Unicode value\n", line, n);*/ + continue; + } + else { + n = strtol(p, &p, 16); + if(n > 0xFFFF) { + printf("Line %d: Entry 0x%06lX unicode value: File \"%s\" corrupted\n", line, value, table_name); + continue; + } + } + + if (cpi->CodePage == 864) { + while(isspace(*p)) p++; + + if(!*p || p[0] == '#' || p[0] == '-') { + /*printf("Line %d: Entry 0x%02lX has no Unicode value\n", line, n);*/ + continue; + } + else { + n = strtol(p, &p, 16); + if(n > 0xFFFF) { + printf("Line %d: Entry 0x%06lX oem value: File \"%s\" corrupted\n", line, value, table_name); + } + continue; + } + } + + table[n] = (WCHAR)value; + } + + fclose(file); + + return table; +} + +int write_nls_files() +{ + WCHAR *table; + WCHAR *oemtable; + char nls_filename[256]; + CPINFOEXA cpi; + int i; + struct code_page { + UINT cp; + BOOL oem; + char *table_filename; + char *comment; + } pages[] = { + {37, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/EBCDIC/CP037.TXT", "IBM EBCDIC US Canada"}, + {424, FALSE, LIBDIR"MAPPINGS/VENDORS/MISC/CP424.TXT", "IBM EBCDIC Hebrew"}, + {437, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT", "OEM United States"}, + {500, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/EBCDIC/CP500.TXT", "IBM EBCDIC International"}, + /*{708, FALSE, "", "Arabic ASMO"},*/ + /*{720, FALSE, "", "Arabic Transparent ASMO"},*/ + {737, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP737.TXT", "OEM Greek 437G"}, + {775, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP775.TXT", "OEM Baltic"}, + {850, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP850.TXT", "OEM Multilingual Latin 1"}, + {852, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP852.TXT", "OEM Slovak Latin 2"}, + {855, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP855.TXT", "OEM Cyrillic" }, + {856, TRUE, LIBDIR"MAPPINGS/VENDORS/MISC/CP856.TXT", "Hebrew PC"}, + {857, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP857.TXT", "OEM Turkish"}, + {860, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP860.TXT", "OEM Portuguese"}, + {861, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP861.TXT", "OEM Icelandic"}, + {862, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP862.TXT", "OEM Hebrew"}, + {863, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP863.TXT", "OEM Canadian French"}, + {864, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP864.TXT", "OEM Arabic"}, + {865, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP865.TXT", "OEM Nordic"}, + {866, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP866.TXT", "OEM Russian"}, + {869, TRUE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP869.TXT", "OEM Greek"}, + /*{870, FALSE, "", "IBM EBCDIC Multilingual/ROECE (Latin 2)"},*/ + {874, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/PC/CP874.TXT", "ANSI/OEM Thai"}, + {875, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/EBCDIC/CP875.TXT", "IBM EBCDIC Greek"}, + {878, FALSE, LIBDIR"MAPPINGS/VENDORS/MISC/KOI8-R.TXT", "Russian KOI8"}, + {932, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT", "ANSI/OEM Japanese Shift-JIS"}, + {936, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT", "ANSI/OEM Simplified Chinese GBK"}, + {949, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT", "ANSI/OEM Korean Unified Hangul"}, + {950, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT", "ANSI/OEM Traditional Chinese Big5"}, + {1006, FALSE, LIBDIR"MAPPINGS/VENDORS/MISC/CP1006.TXT", "IBM Arabic"}, + {1026, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/EBCDIC/CP1026.TXT", "IBM EBCDIC Latin 5 Turkish"}, + {1250, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT", "ANSI Eastern Europe"}, + {1251, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT", "ANSI Cyrillic"}, + {1252, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT", "ANSI Latin 1"}, + {1253, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1253.TXT", "ANSI Greek"}, + {1254, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT", "ANSI Turkish"}, + {1255, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1255.TXT", "ANSI Hebrew"}, + {1256, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1256.TXT", "ANSI Arabic"}, + {1257, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT", "ANSI Baltic"}, + {1258, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT", "ANSI/OEM Viet Nam"}, + {10000, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/MAC/ROMAN.TXT", "Mac Roman"}, + {10006, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/MAC/GREEK.TXT", "Mac Greek"}, + {10007, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/MAC/CYRILLIC.TXT", "Mac Cyrillic"}, + {10029, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/MAC/LATIN2.TXT", "Mac Latin 2"}, + {10079, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/MAC/ICELAND.TXT", "Mac Icelandic"}, + {10081, FALSE, LIBDIR"MAPPINGS/VENDORS/MICSFT/MAC/TURKISH.TXT", "Mac Turkish"}, + /*{20000, FALSE, "", "CNS Taiwan"},*/ + /*{20001, FALSE, "", "TCA Taiwan"},*/ + /*{20002, FALSE, "", "Eten Taiwan"},*/ + /*{20003, FALSE, "", "IBM5550 Taiwan"},*/ + /*{20004, FALSE, "", "TeleText Taiwan"},*/ + /*{20005, FALSE, "", "Wang Taiwan"},*/ + /*{20105, FALSE, "", "IA5 IRV International Alphabet No.5"},*/ + /*{20106, FALSE, "", "IA5 German"},*/ + /*{20107, FALSE, "", "IA5 Swedish"},*/ + /*{20108, FALSE, "", "IA5 Norwegian"},*/ + /*{20127, FALSE, "", "US ASCII"},*/ + /*{20261, FALSE, "", "T.61"},*/ + /*{20269, FALSE, "", "ISO 6937 NonSpacing Accent"},*/ + /*{20273, FALSE, "", "IBM EBCDIC Germany"},*/ + /*{20277, FALSE, "", "IBM EBCDIC Denmark/Norway"},*/ + /*{20278, FALSE, "", "IBM EBCDIC Finland/Sweden"},*/ + /*{20280, FALSE, "", "IBM EBCDIC Italy"},*/ + /*{20284, FALSE, "", "IBM EBCDIC Latin America/Spain"},*/ + /*{20285, FALSE, "", "IBM EBCDIC United Kingdom"},*/ + /*{20290, FALSE, "", "IBM EBCDIC Japanese Katakana Extended"},*/ + /*{20297, FALSE, "", "IBM EBCDIC France"},*/ + /*{20420, FALSE, "", "IBM EBCDIC Arabic"},*/ + /*{20423, FALSE, "", "IBM EBCDIC Greek"},*/ + /*{20424, FALSE, "", "IBM EBCDIC Hebrew"},*/ + /*{20833, FALSE, "", "IBM EBCDIC Korean Extended"},*/ + /*{20838, FALSE, "", "IBM EBCDIC Thai"},*/ + /*{20871, FALSE, "", "IBM EBCDIC Icelandic"},*/ + /*{20880, FALSE, "", "IBM EBCDIC Cyrillic (Russian)"},*/ + {20866, FALSE, LIBDIR"MAPPINGS/VENDORS/MISC/KOI8-R.TXT", "Russian KOI8"}, + /*{20905, FALSE, "", "IBM EBCDIC Turkish"},*/ + /*{21025, FALSE, "", "IBM EBCDIC Cyrillic (Serbian, Bulgarian)"},*/ + /*{21027, FALSE, "", "Ext Alpha Lowercase"},*/ + {28591, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-1.TXT", "ISO 8859-1 Latin 1"}, + {28592, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-2.TXT", "ISO 8859-2 Eastern Europe"}, + {28593, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-3.TXT", "ISO 8859-3 Turkish"}, + {28594, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-4.TXT", "ISO 8859-4 Baltic"}, + {28595, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-5.TXT", "ISO 8859-5 Cyrillic"}, + {28596, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-6.TXT", "ISO 8859-6 Arabic"}, + {28597, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-7.TXT", "ISO 8859-7 Greek"}, + {28598, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-8.TXT", "ISO 8859-8 Hebrew"}, + {28599, FALSE, LIBDIR"MAPPINGS/ISO8859/8859-9.TXT", "ISO 8859-9 Latin 5"} + }; + + for(i = 0; i < sizeof(pages)/sizeof(pages[0]); i++) { + table = Load_CP2Unicode_Table(pages[i].table_filename, pages[i].cp, &cpi); + if(!table) { + printf("Could not load \"%s\" (%s)\n", pages[i].table_filename, pages[i].comment); + continue; + } + + if (pages[i].oem) { + oemtable = Load_OEM2Unicode_Table(LIBDIR"MAPPINGS/VENDORS/MISC/IBMGRAPH.TXT", table, pages[i].cp, &cpi); + if(!oemtable) { + printf("Could not load \"%s\" (%s)\n", LIBDIR"MAPPINGS/VENDORS/MISC/IBMGRAPH.TXT", "IBM OEM glyph table"); + continue; + } + } + + sprintf(nls_filename, "%s/c_%03d.nls", NLSDIR, cpi.CodePage); + if(!create_nls_file(nls_filename, &cpi, table, pages[i].oem ? oemtable : NULL)) { + printf("Could not write \"%s\" (%s)\n", nls_filename, pages[i].comment); + } + + if (pages[i].oem) + free(oemtable); + + free(table); + } + + return 0; +} + + + +static WORD *to_upper_org = NULL, *to_lower_org = NULL; + +static WORD diffs[256]; +static int number_of_diffs; + +static WORD number_of_subtables_with_diffs; +/* pointers to subtables with 16 elements in each to the main table */ +static WORD *subtables_with_diffs[4096]; + +static WORD number_of_subtables_with_offsets; +/* subtables with 16 elements */ +static WORD subtables_with_offsets[4096 * 16]; + +static void test_packed_table(WCHAR *table) +{ + WCHAR test_str[] = L"This is an English text. Ïî-ðóññêè ÿ ïèñàòü óìåþ íåìíîæêî. 1234567890"; + //WORD diff, off; + //WORD *sub_table; + DWORD i, len; + + len = lstrlenW(test_str); + + for(i = 0; i < len + 1; i++) { + /*off = table[HIBYTE(test_str[i])]; + + sub_table = table + off; + off = sub_table[LOBYTE(test_str[i]) >> 4]; + + sub_table = table + off; + off = LOBYTE(test_str[i]) & 0x0F; + + diff = sub_table[off]; + + test_str[i] += diff;*/ + test_str[i] += table[table[table[HIBYTE(test_str[i])] + (LOBYTE(test_str[i]) >> 4)] + (LOBYTE(test_str[i]) & 0x0F)]; + } +/* + { + FILE *file; + static int n = 0; + char name[20]; + + sprintf(name, "text%02d.dat", n++); + file = fopen(name, "wb"); + fwrite(test_str, len * sizeof(WCHAR), 1, file); + fclose(file); + }*/ +} + +static BOOL CreateCaseDiff(char *table_name) +{ + char buf[256]; + char *p; + WORD code, case_mapping; + FILE *file; + int line; + + to_upper_org = (WORD *)calloc(65536, sizeof(WORD)); + if(!to_upper_org) { + printf("Not enough memory for to upper table\n"); + return FALSE; + } + + to_lower_org = (WORD *)calloc(65536, sizeof(WORD)); + if(!to_lower_org) { + printf("Not enough memory for to lower table\n"); + return FALSE; + } + + file = fopen(table_name, "r"); + if(file == NULL) { + printf("Could not open file \"%s\"\n", table_name); + return FALSE; + } + + line = 0; + + while(fgets(buf, sizeof(buf), file)) { + line++; + p = buf; + while(*p && isspace(*p)) p++; + + if(!*p) + continue; + + /* 0. Code value */ + code = (WORD)strtol(p, &p, 16); + + //if(code != 0x9A0 && code != 0xBA0) + //continue; + + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 1. Character name */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 2. General Category */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 3. Canonical Combining Classes */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 4. Bidirectional Category */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 5. Character Decomposition Mapping */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 6. Decimal digit value */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 7. Digit value */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 8. Numeric value */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 9. Mirrored */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 10. Unicode 1.0 Name */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 11. 10646 comment field */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + + /* 12. Uppercase Mapping */ + while(*p && isspace(*p)) p++; + if(!*p) continue; + if(*p != ';') { + case_mapping = (WORD)strtol(p, &p, 16); + to_upper_org[code] = case_mapping - code; + while(*p && *p != ';') p++; + } + else + p++; + + /* 13. Lowercase Mapping */ + while(*p && isspace(*p)) p++; + if(!*p) continue; + if(*p != ';') { + case_mapping = (WORD)strtol(p, &p, 16); + to_lower_org[code] = case_mapping - code; + while(*p && *p != ';') p++; + } + else + p++; + + /* 14. Titlecase Mapping */ + while(*p && *p != ';') p++; + if(!*p) + continue; + p++; + } + + fclose(file); + + return TRUE; +} + +static int find_diff(WORD diff) +{ + int i; + + for(i = 0; i < number_of_diffs; i++) { + if(diffs[i] == diff) + return i; + } + + return -1; +} + +static WORD find_subtable_with_diffs(WORD *table, WORD *subtable) +{ + WORD index; + + for(index = 0; index < number_of_subtables_with_diffs; index++) { + if(memcmp(subtables_with_diffs[index], subtable, 16 * sizeof(WORD)) == 0) { + return index; + } + } + + if(number_of_subtables_with_diffs >= 4096) { + printf("Could not add new subtable with diffs, storage is full\n"); + return 0; + } + + subtables_with_diffs[number_of_subtables_with_diffs] = subtable; + number_of_subtables_with_diffs++; + + return index; +} + +static WORD find_subtable_with_offsets(WORD *subtable) +{ + WORD index; + + for(index = 0; index < number_of_subtables_with_offsets; index++) { + if(memcmp(&subtables_with_offsets[index * 16], subtable, 16 * sizeof(WORD)) == 0) { + return index; + } + } + + if(number_of_subtables_with_offsets >= 4096) { + printf("Could not add new subtable with offsets, storage is full\n"); + return 0; + } + + memcpy(&subtables_with_offsets[number_of_subtables_with_offsets * 16], subtable, 16 * sizeof(WORD)); + number_of_subtables_with_offsets++; + + return index; +} + +static WORD *pack_table(WORD *table, WORD *packed_size_in_words) +{ + WORD high, low4, index; + WORD main_index[256]; + WORD temp_subtable[16]; + WORD *packed_table; + WORD *subtable_src, *subtable_dst; + + memset(subtables_with_diffs, 0, sizeof(subtables_with_diffs)); + number_of_subtables_with_diffs = 0; + + memset(subtables_with_offsets, 0, sizeof(subtables_with_offsets)); + number_of_subtables_with_offsets = 0; + + for(high = 0; high < 256; high++) { + for(low4 = 0; low4 < 256; low4 += 16) { + index = find_subtable_with_diffs(table, &table[MAKEWORD(low4, high)]); + + temp_subtable[low4 >> 4] = index; + } + + index = find_subtable_with_offsets(temp_subtable); + main_index[high] = index; + } + + *packed_size_in_words = 0x100 + number_of_subtables_with_offsets * 16 + number_of_subtables_with_diffs * 16; + packed_table = calloc(*packed_size_in_words, sizeof(WORD)); + + /* fill main index according to the subtables_with_offsets */ + for(high = 0; high < 256; high++) { + packed_table[high] = 0x100 + main_index[high] * 16; + } + + //memcpy(sub_table, subtables_with_offsets, number_of_subtables_with_offsets * 16); + + /* fill subtable index according to the subtables_with_diffs */ + for(index = 0; index < number_of_subtables_with_offsets; index++) { + subtable_dst = packed_table + 0x100 + index * 16; + subtable_src = &subtables_with_offsets[index * 16]; + + for(low4 = 0; low4 < 16; low4++) { + subtable_dst[low4] = 0x100 + number_of_subtables_with_offsets * 16 + subtable_src[low4] * 16; + } + } + + + for(index = 0; index < number_of_subtables_with_diffs; index++) { + subtable_dst = packed_table + 0x100 + number_of_subtables_with_offsets * 16 + index * 16; + memcpy(subtable_dst, subtables_with_diffs[index], 16 * sizeof(WORD)); + + } + + + test_packed_table(packed_table); + + return packed_table; +} + +int write_casemap_file(void) +{ + WORD packed_size_in_words, offset_to_next_table_in_words; + WORD *packed_table, value; + FILE *file; + + if(!CreateCaseDiff(LIBDIR"UnicodeData.txt")) + return -1; + + file = fopen(NLSDIR"/l_intl.nls", "wb"); + + /* write version number */ + value = 1; + fwrite(&value, 1, sizeof(WORD), file); + + /* pack upper case table */ + packed_table = pack_table(to_upper_org, &packed_size_in_words); + offset_to_next_table_in_words = packed_size_in_words + 1; + fwrite(&offset_to_next_table_in_words, 1, sizeof(WORD), file); + /* write packed upper case table */ + fwrite(packed_table, sizeof(WORD), packed_size_in_words, file); + free(packed_table); + + /* pack lower case table */ + packed_table = pack_table(to_lower_org, &packed_size_in_words); + offset_to_next_table_in_words = packed_size_in_words + 1; + fwrite(&offset_to_next_table_in_words, 1, sizeof(WORD), file); + /* write packed lower case table */ + fwrite(packed_table, sizeof(WORD), packed_size_in_words, file); + free(packed_table); + + fclose(file); + + free(to_upper_org); + free(to_lower_org); + + return 0; +} + +int main() +{ + write_nls_files(); + write_casemap_file(); + + return 0; +} diff --git a/tools/create_nls/unicode.org/.cvsignore b/tools/create_nls/unicode.org/.cvsignore new file mode 100644 index 0000000..2211df6 --- /dev/null +++ b/tools/create_nls/unicode.org/.cvsignore @@ -0,0 +1 @@ +*.txt diff --git a/tools/depend.mk b/tools/depend.mk new file mode 100644 index 0000000..bf49d44 --- /dev/null +++ b/tools/depend.mk @@ -0,0 +1,35 @@ +# Automatic dependancy tracking +# Define $DEP_OBJECTS before this file is included +# $DEP_OBJECTS contain a list of object files that are checked for dependancies + +DEP_FILTERED := $(filter-out $(DEP_EXCLUDE_FILTER), $(DEP_OBJECTS:.o=.d)) +DEP_FILES := $(join $(dir $(DEP_FILTERED)), $(addprefix ., $(notdir $(DEP_FILTERED)))) + + +ifneq ($(MAKECMDGOALS),clean) +include $(DEP_FILES) +endif + +ifeq ($(SEP),\) +DEPENDS_PATH := $(subst /,\,$(PATH_TO_TOP))\tools +else +DEPENDS_PATH := $(PATH_TO_TOP)/tools +endif + +.%.d: %.c $(PATH_TO_TOP)/tools/depends$(EXE_POSTFIX) + $(CC) $(CFLAGS) -M $< | $(DEPENDS_PATH)$(SEP)depends$(EXE_POSTFIX) $(@D) $@ + +.%.d: %.cc $(PATH_TO_TOP)/tools/depends$(EXE_POSTFIX) + $(CC) $(CFLAGS) -M $< | $(DEPENDS_PATH)$(SEP)depends$(EXE_POSTFIX) $(@D) $@ + +.%.d: %.cpp $(PATH_TO_TOP)/tools/depends$(EXE_POSTFIX) + $(CC) $(CFLAGS) -M $< | $(DEPENDS_PATH)$(SEP)depends$(EXE_POSTFIX) $(@D) $@ + +.%.d: %.s $(PATH_TO_TOP)/tools/depends$(EXE_POSTFIX) + $(CC) $(CFLAGS) -M $< | $(DEPENDS_PATH)$(SEP)depends$(EXE_POSTFIX) $(@D) $@ + +.%.d: %.S $(PATH_TO_TOP)/tools/depends$(EXE_POSTFIX) + $(CC) $(CFLAGS) -M $< | $(DEPENDS_PATH)$(SEP)depends$(EXE_POSTFIX) $(@D) $@ + +.%.d: %.asm $(PATH_TO_TOP)/tools/depends$(EXE_POSTFIX) + $(NASM_CMD) $< | $(DEPENDS_PATH)$(SEP)depends$(EXE_POSTFIX) $(@D) $@ diff --git a/tools/depends.c b/tools/depends.c new file mode 100644 index 0000000..b157a5e --- /dev/null +++ b/tools/depends.c @@ -0,0 +1,56 @@ +#include +#include +#include + +int main(int argc, char* argv[]) +{ + char buf[512]; + char ch; + unsigned int i; + char* dot; + char* prefix; + FILE* out; + + if (argc != 3) + { + printf("Too few arguments\n"); + return(1); + } + + prefix = strdup(argv[1]); + + out = fopen(argv[2], "wb"); + if (out == NULL) + { + printf("Unable to open output file\n"); + return(1); + } + + i = 0; + while ((ch = fgetc(stdin)) != ':' && ch != EOF) + { + buf[i] = ch; + i++; + } + buf[i] = 0; + + if (i == 0) + { + return(0); + } + + dot = strrchr(buf, '.'); + if (dot != NULL) + { + *dot = 0; + } + fprintf(out, "%s/.%s.TAG %s/.%s.d %s/%s.o:", prefix, buf, prefix, buf, + prefix,buf); + + while ((ch = fgetc(stdin)) != EOF) + { + fputc(ch, out); + } + + return(0); +} diff --git a/tools/helper.mk b/tools/helper.mk new file mode 100644 index 0000000..326bcc0 --- /dev/null +++ b/tools/helper.mk @@ -0,0 +1,629 @@ +# $Id$ +# +# Helper makefile for ReactOS modules +# Variables this makefile accepts: +# $TARGET_TYPE = Type of target: +# program = User mode program +# proglib = Executable program that have exported functions +# dynlink = Dynamic Link Library (DLL) +# library = Library that will be linked with other code +# driver_library = Import library for a driver +# driver = Kernel mode driver +# export_driver = Kernel mode driver that have exported functions +# hal = Hardware Abstraction Layer +# bootpgm = Boot program +# miniport = Kernel mode driver that does not link with ntoskrnl.exe or hal.dll +# gdi_driver = Kernel mode graphics driver that link with win32k.sys +# $TARGET_APPTYPE = Application type (windows,native,console) +# $TARGET_NAME = Base name of output file and .rc, .def, and .edf files +# $TARGET_OBJECTS = Object files that compose the module +# $TARGET_HEADERS = Header files that the object files depend on (optional) +# $TARGET_DEFNAME = Base name of .def and .edf files (optional) +# $TARGET_BASENAME = Base name of output file (overrides $TARGET_NAME if it exists) (optional) +# $TARGET_EXTENSION = Extesion of the output file (optional) +# $TARGET_DDKLIBS = DDK libraries that are to be imported by the module (optional) +# $TARGET_SDKLIBS = SDK libraries that are to be imported by the module (optional) +# $TARGET_LIBS = Other libraries that are to be imported by the module (optional) +# $TARGET_GCCLIBS = GCC libraries imported with -l (optional) +# $TARGET_LFLAGS = GCC flags when linking (optional) +# $TARGET_CFLAGS = GCC flags (optional) +# $TARGET_CPPFLAGS = G++ flags (optional) +# $TARGET_ASFLAGS = GCC assembler flags (optional) +# $TARGET_NFLAGS = NASM flags (optional) +# $TARGET_RCFLAGS = Windres flags (optional) +# $TARGET_CLEAN = Files that are part of the clean rule (optional) +# $TARGET_PATH = Relative path for *.def, *.edf, and *.rc (optional) +# $TARGET_BASE = Default base address (optional) +# $TARGET_ENTRY = Entry point (optional) +# $TARGET_DEFONLY = Use .def instead of .edf extension (no,yes) (optional) +# $TARGET_NORC = Do not include standard resource file (no,yes) (optional) +# $TARGET_LIBPATH = Destination path for import libraries (optional) +# $TARGET_INSTALLDIR = Destination path when installed (optional) +# $WINE_MODE = Compile using WINE headers (no,yes) (optional) +# $WINE_RC = Name of .rc file for WINE modules (optional) + +include $(PATH_TO_TOP)/config + + +ifeq ($(TARGET_PATH),) +TARGET_PATH := . +endif + + +ifeq ($(TARGET_TYPE),program) + MK_MODE := user + MK_EXETYPE := exe + MK_DEFEXT := .exe + MK_DEFENTRY := _DEFINE_TARGET_APPTYPE + MK_DDKLIBS := + MK_SDKLIBS := +ifneq ($(WINE_MODE),yes) + MK_CFLAGS := -I./ -I$(SDK_PATH_INC) + MK_CPPFLAGS := -I./ -I$(SDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) +else + MK_CFLAGS := -I$(PATH_TO_TOP)/include/wine -I./ -I$(WINE_INCLUDE) + MK_CPPFLAGS := -I$(PATH_TO_TOP)/include/wine -I./ -I$(WINE_INCLUDE) + MK_RCFLAGS := --include-dir $(PATH_TO_TOP)/include/wine --include-dir $(WINE_INCLUDE) +endif + MK_IMPLIB := no + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := bin + MK_DISTDIR := apps +ifeq ($(WINE_RC),) + MK_RES_BASE := $(TARGET_NAME) +else + MK_RES_BASE := $(WINE_RC) +endif +endif + +ifeq ($(TARGET_TYPE),proglib) + MK_MODE := user + MK_EXETYPE := dll + MK_DEFEXT := .exe + MK_DEFENTRY := _WinMain@16 + MK_DDKLIBS := + MK_SDKLIBS := + MK_CFLAGS := -I./ -I$(SDK_PATH_INC) + MK_CPPFLAGS := -I./ -I$(SDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := yes + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := $(SDK_PATH_LIB) + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := bin + MK_DISTDIR := apps + MK_RES_BASE := $(TARGET_NAME) +endif + +ifeq ($(TARGET_TYPE),dynlink) + MK_MODE := user + MK_EXETYPE := dll + MK_DEFEXT := .dll + MK_DEFENTRY := _DllMain@12 + MK_DDKLIBS := + MK_SDKLIBS := +ifneq ($(WINE_MODE),yes) + MK_CFLAGS := -I./ -I$(SDK_PATH_INC) + MK_CPPFLAGS := -I./ -I$(SDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) +else + MK_CFLAGS := -I$(PATH_TO_TOP)/include/wine -I./ -I$(WINE_INCLUDE) + MK_CPPFLAGS := -I$(PATH_TO_TOP)/include/wine -I./ -I$(WINE_INCLUDE) + MK_RCFLAGS := --include-dir $(PATH_TO_TOP)/include/wine --include-dir $(WINE_INCLUDE) +endif + MK_IMPLIB := yes + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := $(SDK_PATH_LIB) + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32 + MK_DISTDIR := dlls +ifeq ($(WINE_RC),) + MK_RES_BASE := $(TARGET_NAME) +else + MK_RES_BASE := $(WINE_RC) +endif +endif + +ifeq ($(TARGET_TYPE),library) + MK_MODE := static + MK_EXETYPE := + MK_DEFEXT := .a + MK_DEFENTRY := + MK_DDKLIBS := + MK_SDKLIBS := + MK_CFLAGS := -I./ -I$(SDK_PATH_INC) + MK_CPPFLAGS := -I./ -I$(SDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := no + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := + MK_INSTALLDIR := system32 + MK_DISTDIR := # FIXME + MK_RES_BASE := +endif + +ifeq ($(TARGET_TYPE),driver_library) + MK_MODE := kernel + MK_EXETYPE := dll + MK_DEFEXT := .dll + MK_DEFENTRY := + MK_DDKLIBS := + MK_SDKLIBS := + MK_CFLAGS := -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := no + MK_IMPLIBONLY := yes + MK_IMPLIBDEFPATH := $(DDK_PATH_LIB) + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := $(DDK_PATH_INC) + MK_DISTDIR := # FIXME + MK_RES_BASE := +endif + +ifeq ($(TARGET_TYPE),driver) + MK_MODE := kernel + MK_EXETYPE := dll + MK_DEFEXT := .sys + MK_DEFENTRY := _DriverEntry@8 + MK_DDKLIBS := ntoskrnl.a hal.a + MK_SDKLIBS := + MK_CFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := no + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32/drivers + MK_DISTDIR := drivers + MK_RES_BASE := $(TARGET_NAME) +endif + +ifeq ($(TARGET_TYPE),export_driver) + MK_MODE := kernel + MK_EXETYPE := dll + MK_DEFEXT := .sys + MK_DEFENTRY := _DriverEntry@8 + MK_DDKLIBS := ntoskrnl.a hal.a + MK_SDKLIBS := + MK_CFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := yes + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := $(DDK_PATH_LIB) + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32/drivers + MK_DISTDIR := drivers + MK_RES_BASE := $(TARGET_NAME) +endif + +ifeq ($(TARGET_TYPE),hal) + MK_MODE := kernel + MK_EXETYPE := dll + MK_DEFEXT := .dll + MK_DEFENTRY := _DriverEntry@8 + MK_DDKLIBS := ntoskrnl.a + MK_SDKLIBS := + MK_CFLAGS := -D__NTHAL__ -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -D__NTHAL__ -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := yes + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32 + MK_DISTDIR := dlls + MK_RES_BASE := $(TARGET_NAME) +endif + +ifeq ($(TARGET_TYPE),bootpgm) + MK_MODE := kernel + MK_EXETYPE := exe + MK_DEFEXT := .exe + MK_DEFENTRY := _DriverEntry@8 + MK_DDKLIBS := + MK_SDKLIBS := + MK_CFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := no + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32 + MK_DISTDIR := # FIXME + MK_RES_BASE := $(TARGET_NAME) +endif + +ifeq ($(TARGET_TYPE),miniport) + MK_MODE := kernel + MK_EXETYPE := dll + MK_DEFEXT := .sys + MK_DEFENTRY := _DriverEntry@8 + MK_DDKLIBS := + MK_SDKLIBS := + MK_CFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := no + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32/drivers + MK_DISTDIR := drivers + MK_RES_BASE := $(TARGET_NAME) +endif + +ifeq ($(TARGET_TYPE),gdi_driver) + MK_MODE := kernel + MK_EXETYPE := dll + MK_DEFEXT := .dll + MK_DEFENTRY := _DrvEnableDriver@12 + MK_DDKLIBS := ntoskrnl.a hal.a win32k.a + MK_SDKLIBS := + MK_CFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_CPPFLAGS := -D__NTDRIVER__ -I./ -I$(DDK_PATH_INC) + MK_RCFLAGS := --include-dir $(SDK_PATH_INC) + MK_IMPLIB := yes + MK_IMPLIBONLY := no + MK_IMPLIBDEFPATH := $(DDK_PATH_LIB) + MK_IMPLIB_EXT := .a + MK_INSTALLDIR := system32/drivers + MK_DISTDIR := drivers + MK_RES_BASE := $(TARGET_NAME) +endif + + +ifeq ($(TARGET_TYPE),program) + ifeq ($(TARGET_APPTYPE),windows) + MK_DEFENTRY := _WinMainCRTStartup + MK_SDKLIBS := ntdll.a kernel32.a gdi32.a user32.a + TARGET_LFLAGS += -Wl,--subsystem,windows + endif + + ifeq ($(TARGET_APPTYPE),native) + MK_DEFENTRY := _NtProcessStartup@4 + MK_SDKLIBS := ntdll.a + TARGET_LFLAGS += -Wl,--subsystem,native -nostartfiles + endif + + ifeq ($(TARGET_APPTYPE),console) + MK_DEFENTRY := _mainCRTStartup + MK_SDKLIBS := + TARGET_LFLAGS += -Wl,--subsystem,console + endif +endif + + +MK_RESOURCE := $(MK_RES_BASE).coff + + +ifneq ($(TARGET_INSTALLDIR),) + MK_INSTALLDIR := $(TARGET_INSTALLDIR) +endif + + +ifeq ($(TARGET_LIBPATH),) + MK_IMPLIBPATH := $(MK_IMPLIBDEFPATH) +else + MK_IMPLIBPATH := $(TARGET_LIBPATH) +endif + + +ifeq ($(TARGET_BASENAME),) + MK_BASENAME := $(TARGET_NAME) +else + MK_BASENAME := $(TARGET_BASENAME) +endif + + +ifeq ($(TARGET_EXTENSION),) + MK_EXT := $(MK_DEFEXT) +else + MK_EXT := $(TARGET_EXTENSION) +endif + + +ifeq ($(TARGET_NORC),yes) + MK_FULLRES := +else + MK_FULLRES := $(TARGET_PATH)/$(MK_RESOURCE) +endif + + +ifeq ($(TARGET_DEFNAME),) + MK_DEFBASE := $(TARGET_NAME) +else + MK_DEFBASE := $(TARGET_DEFNAME) +endif + +MK_DEFNAME := $(TARGET_PATH)/$(MK_DEFBASE).def +ifeq ($(TARGET_DEFONLY),yes) + MK_EDFNAME := $(MK_DEFNAME) +else + MK_EDFNAME := $(TARGET_PATH)/$(MK_DEFBASE).edf +endif + + +ifeq ($(MK_MODE),user) + MK_DEFBASE := 0x400000 + ifneq ($(TARGET_SDKLIBS),) + MK_LIBS := $(addprefix $(SDK_PATH_LIB)/, $(TARGET_SDKLIBS)) + else + MK_LIBS := $(addprefix $(SDK_PATH_LIB)/, $(MK_SDKLIBS)) + endif +endif + + +ifeq ($(MK_MODE),kernel) + MK_DEFBASE := 0x10000 + MK_LIBS := $(addprefix $(DDK_PATH_LIB)/, $(MK_DDKLIBS) $(TARGET_DDKLIBS)) +endif + + +ifeq ($(TARGET_BASE),) + TARGET_BASE := $(MK_DEFBASE) +endif + + +ifeq ($(TARGET_ENTRY),) + TARGET_ENTRY := $(MK_DEFENTRY) +endif + + +# +# Include details of the OS configuration +# +include $(PATH_TO_TOP)/config + + +TARGET_CFLAGS += $(MK_CFLAGS) +TARGET_CFLAGS += -pipe -march=$(ARCH) +ifeq ($(DBG),1) +TARGET_ASFLAGS += -g +TARGET_CFLAGS += -g +TARGET_LFLAGS += -g +endif + +TARGET_CPPFLAGS += $(MK_CPPFLAGS) +TARGET_CPPFLAGS += -pipe -march=$(ARCH) + +TARGET_RCFLAGS += $(MK_RCFLAGS) + +TARGET_ASFLAGS += $(MK_ASFLAGS) +TARGET_ASFLAGS += -pipe -march=$(ARCH) + +TARGET_NFLAGS += $(MK_NFLAGS) + + +MK_GCCLIBS := $(addprefix -l, $(TARGET_GCCLIBS)) + +MK_FULLNAME := $(MK_BASENAME)$(MK_EXT) +MK_IMPLIB_FULLNAME := $(MK_BASENAME)$(MK_IMPLIB_EXT) + +MK_NOSTRIPNAME := $(MK_BASENAME).nostrip$(MK_EXT) + +# We don't want to link header files +MK_OBJECTS := $(filter-out %.h,$(TARGET_OBJECTS)) +MK_STRIPPED_OBJECT := $(MK_BASENAME).stripped.o + +ifeq ($(MK_IMPLIBONLY),yes) + +TARGET_CLEAN += $(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME) + +all: $(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME) + +$(MK_IMPLIBPATH)/$(MK_IMPLIB_FULLNAME): $(TARGET_OBJECTS) + $(DLLTOOL) \ + --dllname $(MK_FULLNAME) \ + --def $(MK_DEFNAME) \ + --output-lib $(MK_IMPLIBPATH)/$(MK_BASENAME).a \ + --kill-at + +else # MK_IMPLIBONLY + + +all: $(MK_FULLNAME) $(MK_NOSTRIPNAME) + + +ifeq ($(MK_IMPLIB),yes) + MK_EXTRACMD := --def $(MK_EDFNAME) +else + MK_EXTRACMD := +endif + +# User mode targets +ifeq ($(MK_MODE),user) + +ifeq ($(MK_EXETYPE),dll) + TARGET_LFLAGS += -mdll -Wl,--image-base,$(TARGET_BASE) + MK_EXTRACMD2 := -Wl,temp.exp +else + MK_EXTRACMD2 := +endif + +$(MK_NOSTRIPNAME): $(MK_FULLRES) $(TARGET_OBJECTS) $(MK_LIBS) +ifeq ($(MK_EXETYPE),dll) + $(CC) -Wl,--base-file,base.tmp \ + -Wl,--entry,$(TARGET_ENTRY) \ + $(TARGET_LFLAGS) \ + -o junk.tmp \ + $(MK_FULLRES) $(MK_OBJECTS) $(MK_LIBS) $(MK_GCCLIBS) + - $(RM) junk.tmp + $(DLLTOOL) --dllname $(MK_FULLNAME) \ + --base-file base.tmp \ + --output-exp temp.exp $(MK_EXTRACMD) + - $(RM) base.tmp +endif + $(CC) $(TARGET_LFLAGS) \ + -Wl,--entry,$(TARGET_ENTRY) $(MK_EXTRACMD2) \ + -o $(MK_NOSTRIPNAME) \ + $(MK_FULLRES) $(MK_OBJECTS) $(MK_LIBS) $(MK_GCCLIBS) + - $(RM) temp.exp + - $(RSYM) $(MK_NOSTRIPNAME) $(MK_BASENAME).sym + +$(MK_FULLNAME): $(MK_NOSTRIPNAME) + $(CP) $(MK_NOSTRIPNAME) $(MK_FULLNAME) +# $(STRIP) --strip-debug $(MK_FULLNAME) + +endif # KM_MODE + +# Kernel mode targets +ifeq ($(MK_MODE),kernel) + +ifeq ($(MK_IMPLIB),yes) + MK_EXTRACMD := --def $(MK_EDFNAME) +else + MK_EXTRACMD := +endif + +$(MK_NOSTRIPNAME): $(MK_FULLRES) $(TARGET_OBJECTS) $(MK_LIBS) + $(CC) -Wl,--base-file,base.tmp \ + -Wl,--entry,$(TARGET_ENTRY) \ + $(TARGET_LFLAGS) \ + -nostartfiles -nostdlib \ + -o junk.tmp \ + $(MK_FULLRES) $(MK_OBJECTS) $(MK_LIBS) $(MK_GCCLIBS) + - $(RM) junk.tmp + $(DLLTOOL) --dllname $(MK_FULLNAME) \ + --base-file base.tmp \ + --output-exp temp.exp $(MK_EXTRACMD) + - $(RM) base.tmp + $(CC) $(TARGET_LFLAGS) \ + -Wl,--subsystem,native \ + -Wl,--image-base,$(TARGET_BASE) \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,--entry,$(TARGET_ENTRY) \ + -Wl,temp.exp \ + -mdll -nostartfiles -nostdlib \ + -o $(MK_NOSTRIPNAME) \ + $(MK_FULLRES) $(MK_OBJECTS) $(MK_LIBS) $(MK_GCCLIBS) + - $(RM) temp.exp + $(RSYM) $(MK_NOSTRIPNAME) $(MK_BASENAME).sym + +$(MK_FULLNAME): $(MK_FULLRES) $(TARGET_OBJECTS) $(MK_LIBS) $(MK_NOSTRIPNAME) + $(LD) -r -o $(MK_STRIPPED_OBJECT) $(MK_OBJECTS) + $(STRIP) --strip-debug $(MK_STRIPPED_OBJECT) + $(CC) -Wl,--base-file,base.tmp \ + -Wl,--entry,$(TARGET_ENTRY) \ + $(TARGET_LFLAGS) \ + -nostartfiles -nostdlib \ + -o junk.tmp \ + $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) + - $(RM) junk.tmp + $(DLLTOOL) --dllname $(MK_FULLNAME) \ + --base-file base.tmp \ + --output-exp temp.exp $(MK_EXTRACMD) + - $(RM) base.tmp + $(CC) $(TARGET_LFLAGS) \ + -Wl,--subsystem,native \ + -Wl,--image-base,$(TARGET_BASE) \ + -Wl,--file-alignment,0x1000 \ + -Wl,--section-alignment,0x1000 \ + -Wl,--entry,$(TARGET_ENTRY) \ + -Wl,temp.exp \ + -mdll -nostartfiles -nostdlib \ + -o $(MK_FULLNAME) \ + $(MK_FULLRES) $(MK_STRIPPED_OBJECT) $(MK_LIBS) $(MK_GCCLIBS) + - $(RM) temp.exp + +endif # MK_MODE + +# Static library target +ifeq ($(MK_MODE),static) + +$(MK_FULLNAME): $(TARGET_OBJECTS) + $(AR) -r $(MK_FULLNAME) $(TARGET_OBJECTS) + +endif # MK_MODE + +endif # MK_IMPLIBONLY + + +$(MK_FULLRES): $(PATH_TO_TOP)/include/reactos/buildno.h $(TARGET_PATH)/$(MK_RES_BASE).rc + +ifeq ($(MK_IMPLIB),yes) +$(MK_IMPLIBPATH)/$(MK_BASENAME).a: $(MK_DEFNAME) + $(DLLTOOL) --dllname $(MK_FULLNAME) \ + --def $(MK_DEFNAME) \ + --output-lib $(MK_IMPLIBPATH)/$(MK_BASENAME).a \ + --kill-at + +implib: $(MK_IMPLIBPATH)/$(MK_BASENAME).a +else +implib: +endif + +# Be carefull not to clean non-object files +MK_CLEANFILES := $(filter %.o,$(MK_OBJECTS)) + +clean: + - $(RM) *.o $(MK_BASENAME).sym $(MK_BASENAME).a $(TARGET_PATH)/$(MK_RES_BASE).coff \ + $(MK_FULLNAME) $(MK_NOSTRIPNAME) $(MK_CLEANFILES) \ + junk.tmp base.tmp temp.exp \ + $(TARGET_CLEAN) + +ifneq ($(TARGET_HEADERS),) +$(TARGET_OBJECTS): $(TARGET_HEADERS) +endif + +# install and dist rules + +ifeq ($(MK_IMPLIBONLY),yes) + +# Don't install import libraries + +install: + +dist: + +else # MK_IMPLIBONLY + + +install: $(INSTALL_DIR)/$(MK_INSTALLDIR)/$(MK_FULLNAME) + +$(INSTALL_DIR)/$(MK_INSTALLDIR)/$(MK_FULLNAME): $(MK_FULLNAME) $(MK_BASENAME).sym + $(CP) $(MK_FULLNAME) $(INSTALL_DIR)/$(MK_INSTALLDIR)/$(MK_FULLNAME) + $(CP) $(MK_BASENAME).sym $(INSTALL_DIR)/symbols/$(MK_BASENAME).sym + + +dist: $(DIST_DIR)/$(MK_DISTDIR)/$(MK_FULLNAME) + +$(DIST_DIR)/$(MK_DISTDIR)/$(MK_FULLNAME): $(MK_FULLNAME) + $(CP) $(MK_FULLNAME) $(DIST_DIR)/$(MK_DISTDIR)/$(MK_FULLNAME) + $(CP) $(MK_BASENAME).sym $(DIST_DIR)/symbols/$(MK_BASENAME).sym + + +endif # MK_IMPLIBONLY + + +.phony: all implib clean install dist + + +%.o: %.c + $(CC) $(TARGET_CFLAGS) -c $< -o $@ +%.o: %.cc + $(CC) $(TARGET_CPPFLAGS) -c $< -o $@ +%.o: %.cpp + $(CC) $(TARGET_CPPFLAGS) -c $< -o $@ +%.o: %.S + $(AS) $(TARGET_ASFLAGS) -c $< -o $@ +%.o: %.s + $(AS) $(TARGET_ASFLAGS) -c $< -o $@ +%.o: %.asm + $(NASM_CMD) $(NFLAGS) $(TARGET_NFLAGS) $< -o $@ +%.coff: %.rc + $(RC) $(TARGET_RCFLAGS) $(RCINC) $< -o $@ + + +# Compatibility +CFLAGS := $(TARGET_CFLAGS) + +# EOF diff --git a/tools/mkconfig.c b/tools/mkconfig.c new file mode 100644 index 0000000..56bb885 --- /dev/null +++ b/tools/mkconfig.c @@ -0,0 +1,112 @@ +#include +#include +#include + +#define max(a, b) ((a) > (b) ? (a) : (b)) + +int +write_if_change(char* outbuf, char* filename) +{ + FILE* out; + unsigned int end; + char* cmpbuf; + unsigned int stat; + + out = fopen(filename, "rb"); + if (out == NULL) + { + out = fopen(filename, "wb"); + if (out == NULL) + { + fprintf(stderr, "Unable to create output file\n"); + return(1); + } + fputs(outbuf, out); + fclose(out); + return(0); + } + + fseek(out, 0, SEEK_END); + end = ftell(out); + cmpbuf = malloc(end); + if (cmpbuf == NULL) + { + fprintf(stderr, "Out of memory\n"); + fclose(out); + return(1); + } + + fseek(out, 0, SEEK_SET); + stat = fread(cmpbuf, 1, end, out); + if (stat != end) + { + fprintf(stderr, "Failed to read data\n"); + fclose(out); + return(1); + } + if (end == strlen(outbuf) && memcmp(cmpbuf, outbuf, end) == 0) + { + fclose(out); + return(0); + } + + fclose(out); + out = fopen(filename, "wb"); + if (out == NULL) + { + fprintf(stderr, "Unable to create output file\n"); + return(1); + } + + stat = fwrite(outbuf, 1, strlen(outbuf), out); + if (strlen(outbuf) != stat) + { + fprintf(stderr, "Unable to write output file\n"); + fclose(out); + return(1); + } + fclose(out); + return(0); +} + +int +main(int argc, char* argv[]) +{ + unsigned int i; + char* outbuf; + char* s; + char config[512]; + + if (argc == 1) + { + fprintf(stderr, "Not enough arguments\n"); + return(1); + } + + outbuf = malloc(256 * 1024); + if (outbuf == NULL) + { + fprintf(stderr, "Out of memory 1\n"); + return(1); + } + + s = outbuf; + s = s + sprintf(s, "/* Automatically generated, "); + s = s + sprintf(s, "Edit the Makefile to change configuration */\n"); + s = s + sprintf(s, "#ifndef __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H\n"); + s = s + sprintf(s, "#define __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H\n"); + strcpy(config, ""); + for (i = 2; i < argc; i++) + { + s = s + sprintf(s, "#define %s\n", argv[i]); + strcat(config, argv[i]); + if (i != (argc - 1)) + { + strcat(config, " "); + } + } + s = s + sprintf(s, "#define CONFIG \"%s\"\n", config); + s = s + sprintf(s, "#endif /* __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H */\n"); + + return(write_if_change(outbuf, argv[1])); +} diff --git a/tools/rcopy.c b/tools/rcopy.c new file mode 100644 index 0000000..a285ff3 --- /dev/null +++ b/tools/rcopy.c @@ -0,0 +1,87 @@ +#include +#include +#include + +char* convert_path(char* origpath) +{ + char* newpath; + int i; + + newpath = strdup(origpath); + + i = 0; + while (newpath[i] != 0) + { +#ifdef UNIX_PATHS + if (newpath[i] == '\\') + { + newpath[i] = '/'; + } +#else +#ifdef DOS_PATHS + if (newpath[i] == '/') + { + newpath[i] = '\\'; + } +#endif +#endif + i++; + } + return(newpath); +} + +#define TRANSFER_SIZE (65536) + +int main(int argc, char* argv[]) +{ + char* path1; + char* path2; + FILE* in; + FILE* out; + char* buf; + int n_in; + int n_out; + + if (argc != 3) + { + fprintf(stderr, "Too many arguments\n"); + exit(1); + } + + path1 = convert_path(argv[1]); + path2 = convert_path(argv[2]); + + in = fopen(path1, "rb"); + if (in == NULL) + { + perror("Cannot open input file"); + exit(1); + } + + + + out = fopen(path2, "wb"); + if (out == NULL) + { + perror("Cannot open output file"); + fclose(in); + exit(1); + } + + buf = malloc(TRANSFER_SIZE); + + while (!feof(in)) + { + n_in = fread(buf, 1, TRANSFER_SIZE, in); + n_out = fwrite(buf, 1, n_in, out); + if (n_in != n_out) + { + perror("Failed to write to output file\n"); + free(buf); + fclose(in); + fclose(out); + exit(1); + } + } + exit(0); +} diff --git a/tools/rdel.c b/tools/rdel.c new file mode 100644 index 0000000..0e233fa --- /dev/null +++ b/tools/rdel.c @@ -0,0 +1,91 @@ +/* $Id$ + * COPYRIGHT: See COPYING in the top level directory + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + * PURPOSE: Platform independant delete command + */ + +#include +#include +#include +#include +#include +#include + +void +convertPath (char * pathToConvert) +{ + while (*pathToConvert != 0) + { + if (*pathToConvert == '\\') + { + *pathToConvert = '/'; + } + pathToConvert++; + } +} + +void +getDirectory (const char *filename, char * directorySpec) +{ + int lengthOfDirectory; + + if (strrchr (filename, '/') != 0) + { + lengthOfDirectory = strrchr (filename, '/') - filename; + strncpy (directorySpec, filename, lengthOfDirectory); + directorySpec [lengthOfDirectory] = '\0'; + } + else + { + strcpy (directorySpec, "."); + } +} + +void +getFilename (const char *filename, char * fileSpec) +{ + if (strrchr (filename, '/') != 0) + { + strcpy (fileSpec, strrchr (filename, '/') + 1); + } + else + { + strcpy (fileSpec, filename); + } +} + +int +main (int argc, char* argv[]) +{ + int justPrint = 0; + int idx; + int returnCode; + + for (idx = 1; idx < argc; idx++) + { + convertPath (argv [idx]); + + if (justPrint) + { + printf ("delete %s\n", argv [idx]); + } + else + { + returnCode = remove (argv [idx]); + if (returnCode != 0 && errno != ENOENT) + { + /* Continue even if there is errors */ +#if 0 + printf ("Unlink of %s failed. Unlink returned %d.\n", + argv [idx], + returnCode); + return returnCode; +#endif + } + } + } + + return 0; +} + + diff --git a/tools/rmkdir.c b/tools/rmkdir.c new file mode 100644 index 0000000..371402a --- /dev/null +++ b/tools/rmkdir.c @@ -0,0 +1,102 @@ +#include +#include +#include + +char* convert_path(char* origpath) +{ + char* newpath; + int i; + + newpath = strdup(origpath); + + i = 0; + while (newpath[i] != 0) + { +#ifdef UNIX_PATHS + if (newpath[i] == '\\') + { + newpath[i] = '/'; + } +#else +#ifdef DOS_PATHS + if (newpath[i] == '/') + { + newpath[i] = '\\'; + } +#endif +#endif + i++; + } + return(newpath); +} + +#define TRANSFER_SIZE (65536) + +int mkdir_p(char* path) +{ + if (chdir(path) == 0) + { + return(0); + } +#ifdef UNIX_PATHS + if (mkdir(path, 0755) != 0) + { + perror("Failed to create directory"); + exit(1); + } +#else + if (mkdir(path) != 0) + { + perror("Failed to create directory"); + exit(1); + } +#endif + + if (chdir(path) != 0) + { + perror("Failed to change directory"); + exit(1); + } + return(0); +} + +int main(int argc, char* argv[]) +{ + char* path1; + FILE* in; + FILE* out; + char* csec; + int is_abs_path; + + if (argc != 2) + { + fprintf(stderr, "Too many arguments\n"); + exit(1); + } + + path1 = convert_path(argv[1]); + + if (isalpha(path1[0]) && path1[1] == ':' && path1[2] == '/') + { + csec = strtok(path1, "/"); + chdir(csec); + csec = strtok(NULL, "/"); + } + else if (path1[0] == '/') + { + chdir("/"); + csec = strtok(path1, "/"); + } + else + { + csec = strtok(path1, "/"); + } + + while (csec != NULL) + { + mkdir_p(csec); + csec = strtok(NULL, "/"); + } + + exit(0); +} diff --git a/tools/rrmdir.c b/tools/rrmdir.c new file mode 100644 index 0000000..9a3f037 --- /dev/null +++ b/tools/rrmdir.c @@ -0,0 +1,92 @@ +/* $Id$ + * COPYRIGHT: See COPYING in the top level directory + * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * PURPOSE: Platform independant remove directory command + */ + +#include +#include +#include +#include +#include +#include + +void +convertPath (char * pathToConvert) +{ + while (*pathToConvert != 0) + { + if (*pathToConvert == '\\') + { + *pathToConvert = '/'; + } + pathToConvert++; + } +} + +void +getDirectory (const char *filename, char * directorySpec) +{ + int lengthOfDirectory; + + if (strrchr (filename, '/') != 0) + { + lengthOfDirectory = strrchr (filename, '/') - filename; + strncpy (directorySpec, filename, lengthOfDirectory); + directorySpec [lengthOfDirectory] = '\0'; + } + else + { + strcpy (directorySpec, "."); + } +} + +void +getFilename (const char *filename, char * fileSpec) +{ + if (strrchr (filename, '/') != 0) + { + strcpy (fileSpec, strrchr (filename, '/') + 1); + } + else + { + strcpy (fileSpec, filename); + } +} + +int +main (int argc, char* argv[]) +{ + int justPrint = 0; + int idx; + int returnCode; + + for (idx = 1; idx < argc; idx++) + { + convertPath (argv [idx]); + + if (justPrint) + { + printf ("remove %s\n", argv [idx]); + } + else + { + returnCode = rmdir (argv [idx]); + if (returnCode != 0 && errno != ENOENT) + { + /* Continue even if there is errors */ +#if 0 + printf ("Rmdir of %s failed. Rmdir returned %d.\n", + argv [idx], + returnCode); + return returnCode; +#endif + } + } + } + + return 0; +} + + diff --git a/tools/rsym.c b/tools/rsym.c new file mode 100644 index 0000000..cf2638a --- /dev/null +++ b/tools/rsym.c @@ -0,0 +1,255 @@ +/* + * Usage: rsym input-file output-file + */ +#include +#include +#include + +#define NULL ((void*)0) + +#define IMAGE_DOS_MAGIC 0x5a4d +#define IMAGE_PE_MAGIC 0x00004550 + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +typedef void* PVOID; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef signed long LONG; +typedef unsigned long ULONG; + +#pragma pack(push,2) +typedef struct _IMAGE_DOS_HEADER { + WORD e_magic; + WORD e_cblp; + WORD e_cp; + WORD e_crlc; + WORD e_cparhdr; + WORD e_minalloc; + WORD e_maxalloc; + WORD e_ss; + WORD e_sp; + WORD e_csum; + WORD e_ip; + WORD e_cs; + WORD e_lfarlc; + WORD e_ovno; + WORD e_res[4]; + WORD e_oemid; + WORD e_oeminfo; + WORD e_res2[10]; + LONG e_lfanew; +} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; +#pragma pack(pop) +#pragma pack(push,4) +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; +typedef struct _IMAGE_OPTIONAL_HEADER { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Reserved1; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; +#pragma pack(pop) + +typedef struct _SYMBOLFILE_HEADER { + unsigned long StabsOffset; + unsigned long StabsLength; + unsigned long StabstrOffset; + unsigned long StabstrLength; +} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; + + +char* convert_path(char* origpath) +{ + char* newpath; + int i; + + newpath = strdup(origpath); + + i = 0; + while (newpath[i] != 0) + { +#ifdef UNIX_PATHS + if (newpath[i] == '\\') + { + newpath[i] = '/'; + } +#else +#ifdef DOS_PATHS + if (newpath[i] == '/') + { + newpath[i] = '\\'; + } +#endif +#endif + i++; + } + return(newpath); +} + +#define TRANSFER_SIZE (65536) + +int main(int argc, char* argv[]) +{ + SYMBOLFILE_HEADER SymbolFileHeader; + IMAGE_DOS_HEADER PEDosHeader; + IMAGE_FILE_HEADER PEFileHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + PVOID SymbolsBase; + ULONG SymbolsLength; + PVOID SymbolStringsBase; + ULONG SymbolStringsLength; + ULONG Idx; + char* path1; + char* path2; + FILE* in; + FILE* out; + char* buf; + int n_in; + int n_out; + + if (argc != 3) + { + fprintf(stderr, "Too many arguments\n"); + exit(1); + } + + path1 = convert_path(argv[1]); + path2 = convert_path(argv[2]); + + in = fopen(path1, "rb"); + if (in == NULL) + { + perror("Cannot open input file"); + exit(1); + } + + out = fopen(path2, "wb"); + if (out == NULL) + { + perror("Cannot open output file"); + fclose(in); + exit(1); + } + + /* Check if MZ header exists */ + n_in = fread(&PEDosHeader, 1, sizeof(PEDosHeader), in); + if (PEDosHeader.e_magic != IMAGE_DOS_MAGIC && PEDosHeader.e_lfanew != 0L) + { + perror("Input file is not a PE image.\n"); + } + + /* Read PE file header */ + /* sizeof(ULONG) = sizeof(MAGIC) */ + fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG), SEEK_SET); + n_in = fread(&PEFileHeader, 1, sizeof(PEFileHeader), in); + + /* Read PE section headers */ + PESectionHeaders = malloc(PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)); + fseek(in, PEDosHeader.e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + + sizeof(IMAGE_OPTIONAL_HEADER), SEEK_SET); + n_in = fread(PESectionHeaders, 1, PEFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), in); + + /* Copy .stab and .stabstr sections if available */ + SymbolsBase = NULL; + SymbolsLength = 0; + SymbolStringsBase = NULL; + SymbolStringsLength = 0; + + for (Idx = 0; Idx < PEFileHeader.NumberOfSections; Idx++) + { + //printf("section: '%.08s'\n", PESectionHeaders[Idx].Name); + if ((strncmp(PESectionHeaders[Idx].Name, ".stab", 5) == 0) + && (PESectionHeaders[Idx].Name[5] == 0)) + { + //printf(".stab section found. Size %d\n", + // PESectionHeaders[Idx].SizeOfRawData); + + SymbolsLength = PESectionHeaders[Idx].SizeOfRawData; + SymbolsBase = malloc(SymbolsLength); + + fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET); + n_in = fread(SymbolsBase, 1, SymbolsLength, in); + } + + if (strncmp(PESectionHeaders[Idx].Name, ".stabstr", 8) == 0) + { + //printf(".stabstr section found. Size %d\n", + // PESectionHeaders[Idx].SizeOfRawData); + + SymbolStringsLength = PESectionHeaders[Idx].SizeOfRawData; + SymbolStringsBase = malloc(SymbolStringsLength); + + fseek(in, PESectionHeaders[Idx].PointerToRawData, SEEK_SET); + n_in = fread(SymbolStringsBase, 1, SymbolStringsLength, in); + } + } + + SymbolFileHeader.StabsOffset = sizeof(SYMBOLFILE_HEADER); + SymbolFileHeader.StabsLength = SymbolsLength; + SymbolFileHeader.StabstrOffset = SymbolFileHeader.StabsOffset + SymbolsLength; + SymbolFileHeader.StabstrLength = SymbolStringsLength; + + n_out = fwrite(&SymbolFileHeader, 1, sizeof(SYMBOLFILE_HEADER), out); + n_out = fwrite(SymbolsBase, 1, SymbolsLength, out); + n_out = fwrite(SymbolStringsBase, 1, SymbolStringsLength, out); + + exit(0); +} diff --git a/tools/wmc/.cvsignore b/tools/wmc/.cvsignore new file mode 100644 index 0000000..e0e1108 --- /dev/null +++ b/tools/wmc/.cvsignore @@ -0,0 +1,6 @@ +wmc +*.coff +*.d +*.exe +*.o +*.sym diff --git a/tools/wmc/config.h b/tools/wmc/config.h new file mode 100644 index 0000000..5376534 --- /dev/null +++ b/tools/wmc/config.h @@ -0,0 +1,454 @@ +/* include/config.h. Generated automatically by configure. */ +/* include/config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* Define as __inline if that's what the C compiler calls it. */ +/* #undef inline */ + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ + +/* Define if the `S_IS*' macros in do not work properly. */ +/* #undef STAT_MACROS_BROKEN */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if the X Window System is missing or not being used. */ +/* #undef X_DISPLAY_MISSING */ + +/* Define if lex declares yytext as a char * by default, not a char[]. */ +#define YYTEXT_POINTER 1 + +/* Define if symbols declared in assembly code need an underscore prefix */ +/* #undef NEED_UNDERSCORE_PREFIX */ + +/* Define to use .string instead of .ascii */ +#define HAVE_ASM_STRING 1 + +/* Define if struct msghdr contains msg_accrights */ +/* #undef HAVE_MSGHDR_ACCRIGHTS */ + +/* Define if struct sockaddr_un contains sun_len */ +/* #undef HAVE_SOCKADDR_SUN_LEN */ + +/* Define if you have the Xxf86dga library (-lXxf86dga). */ +#define HAVE_LIBXXF86DGA 1 + +/* Define if you have the Xxf86dga library version 2.0 (-lXxf86dga). */ +/* #undef HAVE_LIBXXF86DGA2 */ + +/* Define if you have the X Shm extension */ +#define HAVE_LIBXXSHM 1 + +/* Define if you have the X Shape extension */ +#define HAVE_LIBXSHAPE 1 + +/* Define if you have the Xxf86vm library */ +#define HAVE_LIBXXF86VM 1 + +/* Define if you have the Xpm library */ +#define HAVE_LIBXXPM 1 + +/* Define if you have the Open Sound system. */ +#define HAVE_OSS 1 + +/* Define if you have the Open Sound system (MIDI interface). */ +#define HAVE_OSS_MIDI 1 + +/* Define if X libraries are not reentrant (compiled without -D_REENTRANT). */ +/* #undef NO_REENTRANT_X11 */ + +/* Define if libc is not reentrant */ +/* #undef NO_REENTRANT_LIBC */ + +/* Define if libc uses __errno_location for reentrant errno */ +#define HAVE__ERRNO_LOCATION 1 + +/* Define if libc uses __error for reentrant errno */ +/* #undef HAVE__ERROR */ + +/* Define if libc uses ___errno for reentrant errno */ +/* #undef HAVE___ERRNO */ + +/* Define if libc uses __thr_errno for reentrant errno */ +/* #undef HAVE__THR_ERRNO */ + +/* Define if all debug messages are to be compiled out */ +/* #undef NO_DEBUG_MSGS */ + +/* Define if TRACE messages are to be compiled out */ +/* #undef NO_TRACE_MSGS */ + +/* Define if the struct statfs has the member bavail */ +#define STATFS_HAS_BAVAIL 1 + +/* Define if the struct statfs has the member bfree */ +#define STATFS_HAS_BFREE 1 + +/* Define if the struct statfs is defined by */ +#define STATFS_DEFINED_BY_SYS_VFS 1 + +/* Define if the struct statfs is defined by */ +#define STATFS_DEFINED_BY_SYS_STATFS 1 + +/* Define if the struct statfs is defined by */ +/* #undef STATFS_DEFINED_BY_SYS_MOUNT */ + +/* Define if ncurses have the new resizeterm function */ +#define HAVE_RESIZETERM 1 + +/* Define if ncurses have the new getbkgd function */ +#define HAVE_GETBKGD 1 + +/* Define if IPX should use netipx/ipx.h from libc */ +#define HAVE_IPX_GNU 1 + +/* Define if IPX includes are taken from Linux kernel */ +/* #undef HAVE_IPX_LINUX */ + +/* Define if OpenGL is present on the system or not */ +#define HAVE_OPENGL 1 + +/* Define if the system has dynamic link library support with the dl* API */ +#define HAVE_DL_API 1 + +/* Define if defines the Linux 2.2 joystick API */ +#define HAVE_LINUX_22_JOYSTICK_API 1 + +/* Define if the OpenGL library supports the glXGetProcAddressARB call */ +/* #undef HAVE_GLX_GETPROCADDRESS */ + +/* Define if the OpenGL headers define extension typedefs */ +/* #undef HAVE_GLEXT_PROTOTYPES */ + +/* The number of bytes in a long long. */ +#define SIZEOF_LONG_LONG 8 + +/* Define if you have the __libc_fork function. */ +/* #undef HAVE___LIBC_FORK */ + +/* Define if you have the _lwp_create function. */ +/* #undef HAVE__LWP_CREATE */ + +/* Define if you have the clone function. */ +#define HAVE_CLONE 1 + +/* Define if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define if you have the dlopen function. */ +/* #undef HAVE_DLOPEN */ + +/* Define if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define if you have the getnetbyaddr function. */ +#define HAVE_GETNETBYADDR 1 + +/* Define if you have the getnetbyname function. */ +#define HAVE_GETNETBYNAME 1 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the getprotobyname function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define if you have the getprotobynumber function. */ +#define HAVE_GETPROTOBYNUMBER 1 + +/* Define if you have the getservbyport function. */ +#define HAVE_GETSERVBYPORT 1 + +/* Define if you have the getsockopt function. */ +#define HAVE_GETSOCKOPT 1 + +/* Define if you have the inet_network function. */ +#define HAVE_INET_NETWORK 1 + +/* Define if you have the memmove function. */ +#define HAVE_MEMMOVE 1 + +/* Define if you have the openpty function. */ +#define HAVE_OPENPTY 1 + +/* Define if you have the rfork function. */ +/* #undef HAVE_RFORK */ + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the sendmsg function. */ +#define HAVE_SENDMSG 1 + +/* Define if you have the settimeofday function. */ +#define HAVE_SETTIMEOFDAY 1 + +/* Define if you have the sigaltstack function. */ +/* #undef HAVE_SIGALTSTACK */ + +/* Define if you have the statfs function. */ +#define HAVE_STATFS 1 + +/* Define if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define if you have the strerror function. */ +#define HAVE_STRERROR 1 + +/* Define if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define if you have the tcgetattr function. */ +#define HAVE_TCGETATTR 1 + +/* Define if you have the timegm function. */ +#define HAVE_TIMEGM 1 + +/* Define if you have the usleep function. */ +#define HAVE_USLEEP 1 + +/* Define if you have the vfscanf function. */ +#define HAVE_VFSCANF 1 + +/* Define if you have the wait4 function. */ +#define HAVE_WAIT4 1 + +/* Define if you have the waitpid function. */ +#define HAVE_WAITPID 1 + +/* Define if you have the header file. */ +#define HAVE_GL_GL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_GL_GLEXT_H */ + +/* Define if you have the header file. */ +#define HAVE_GL_GLX_H 1 + +/* Define if you have the header file. */ +#define HAVE_X11_XLIB_H 1 + +/* Define if you have the header file. */ +#define HAVE_X11_EXTENSIONS_XSHM_H 1 + +/* Define if you have the header file. */ +#define HAVE_X11_EXTENSIONS_SHAPE_H 1 + +/* Define if you have the header file. */ +#define HAVE_X11_EXTENSIONS_XF86DGA_H 1 + +/* Define if you have the header file. */ +#define HAVE_X11_EXTENSIONS_XF86VMODE_H 1 + +/* Define if you have the header file. */ +#define HAVE_X11_XPM_H 1 + +/* Define if you have the header file. */ +#define HAVE_A_OUT_H 1 + +/* Define if you have the header file. */ +#define HAVE_A_OUT_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define if you have the header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_CURSES_H */ + +/* Define if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if you have the header file. */ +#define HAVE_ELF_H 1 + +/* Define if you have the header file. */ +#define HAVE_FLOAT_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIBIO_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LIBUTIL_H */ + +/* Define if you have the header file. */ +#define HAVE_LINK_H 1 + +/* Define if you have the header file. */ +#define HAVE_LINUX_CDROM_H 1 + +/* Define if you have the header file. */ +#define HAVE_LINUX_JOYSTICK_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_LINUX_UCDROM_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define if you have the header file. */ +#define HAVE_NCURSES_H 1 + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define if you have the header file. */ +#define HAVE_PTY_H 1 + +/* Define if you have the header file. */ +#define HAVE_RESOLV_H 1 + +/* Define if you have the header file. */ +#define HAVE_SCHED_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SOCKET_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SOUNDCARD_H */ + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_CDIO_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_ERRNO_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_IPC_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_LWP_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_MODEM_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_MOUNT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_MSG_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_REG_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SHM_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SIGNAL_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_SOUNDCARD_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_STATFS_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_STRTIO_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_SYSCALL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_V86_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_V86INTR_H */ + +/* Define if you have the header file. */ +#define HAVE_SYS_VFS_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_VM86_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYSCALL_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_UCONTEXT_H */ + +/* Define if you have the curses library (-lcurses). */ +/* #undef HAVE_LIBCURSES */ + +/* Define if you have the i386 library (-li386). */ +/* #undef HAVE_LIBI386 */ + +/* Define if you have the m library (-lm). */ +#define HAVE_LIBM 1 + +/* Define if you have the mmap library (-lmmap). */ +/* #undef HAVE_LIBMMAP */ + +/* Define if you have the ncurses library (-lncurses). */ +#define HAVE_LIBNCURSES 1 + +/* Define if you have the ossaudio library (-lossaudio). */ +/* #undef HAVE_LIBOSSAUDIO */ + +/* Define if you have the w library (-lw). */ +/* #undef HAVE_LIBW */ + +/* Define if you have the xpg4 library (-lxpg4). */ +/* #undef HAVE_LIBXPG4 */ diff --git a/tools/wmc/getopt.c b/tools/wmc/getopt.c new file mode 100644 index 0000000..df79d7e --- /dev/null +++ b/tools/wmc/getopt.c @@ -0,0 +1,1050 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#include +#endif /* GNU C library. */ + +#ifdef VMS +#include +#if HAVE_STRING_H - 0 +#include +#endif +#endif + +#if defined (WIN32) && !defined (__CYGWIN32__) +/* It's not Unix, really. See? Capital letters. */ +#include +#define getpid() GetCurrentProcessId() +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ +#ifdef HAVE_LIBINTL_H +# include +# define _(msgid) gettext (msgid) +#else +# define _(msgid) (msgid) +#endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +//char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +extern pid_t __libc_pid; + +/* Make sure the environment variable bash 2.0 puts in the environment + is valid for the getopt call we must make sure that the ARGV passed + to getopt is that one passed to the process. */ +static void +__attribute__ ((unused)) +store_args_and_env (int argc, char *const *argv) +{ + /* XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ + original_argc = argc; + original_argv = argv; +} +text_set_element (__libc_subinit, store_args_and_env); + +# define SWAP_FLAGS(ch1, ch2) \ + if (nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +#if defined (__STDC__) && __STDC__ +static void exchange (char **); +#endif + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#ifdef _LIBC + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else + { + memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); + memset (&new_str[nonoption_flags_max_len], '\0', + top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize (int, char *const *, const char *); +#endif +static const char * +_getopt_initialize (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + +#ifdef _LIBC + if (posixly_correct == NULL + && argc == original_argc && argv == original_argv) + { + if (nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen (orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + { + memcpy (__getopt_nonoption_flags, orig_str, len); + memset (&__getopt_nonoption_flags[len], '\0', + nonoption_flags_max_len - len); + } + } + } + nonoption_flags_len = nonoption_flags_max_len; + } + else + nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0 || !__getopt_initialized) + { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring); + __getopt_initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ + || (optind < nonoption_flags_len \ + && __getopt_nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[optind - 1][0], pfound->name); + + nextchar += strlen (nextchar); + + optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + if (posixly_correct) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* Not ELIDE_CODE. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/tools/wmc/getopt.h b/tools/wmc/getopt.h new file mode 100644 index 0000000..d6ceb0e --- /dev/null +++ b/tools/wmc/getopt.h @@ -0,0 +1,131 @@ +/* Declarations for getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if defined (__STDC__) && __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if defined (__STDC__) && __STDC__ +#ifdef __GNU_LIBRARY__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/tools/wmc/lang.c b/tools/wmc/lang.c new file mode 100644 index 0000000..796ffd9 --- /dev/null +++ b/tools/wmc/lang.c @@ -0,0 +1,155 @@ +/* + * Wine Message Compiler language and codepage support + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ +#include +#include +#include +#include +#include + +#include "wmc.h" +#include "lang.h" + + +/* + * Languages supported + * + * MUST be sorting ascending on language ID + */ +static const language_t languages[] = { + + {0x0402, 866, 1251, "Bulgarian", "Bulgaria"}, + {0x0403, 850, 1252, "Catalan", "Spain"}, + {0x0405, 852, 1250, "Czech", "Czech Republic"}, + {0x0406, 850, 1252, "Danish", "Denmark"}, + {0x0407, 850, 1252, "German", "Germany"}, + {0x0408, 737, 1253, "Greek", "Greece"}, + {0x0409, 437, 1252, "English", "United States"}, + {0x040A, 850, 1252, "Spanish - Traditional Sort", "Spain"}, + {0x040B, 850, 1252, "Finnish", "Finland"}, + {0x040C, 850, 1252, "French", "France"}, + {0x040E, 852, 1250, "Hungarian", "Hungary"}, + {0x040F, 850, 1252, "Icelandic", "Iceland"}, + {0x0410, 850, 1252, "Italian", "Italy"}, + {0x0411, 932, 932, "Japanese", "Japan"}, + {0x0412, 949, 949, "Korean", "Korea (south)"}, + {0x0413, 850, 1252, "Dutch", "Netherlands"}, + {0x0414, 850, 1252, "Norwegian (Bokmål)", "Norway"}, + {0x0415, 852, 1250, "Polish", "Poland"}, + {0x0416, 850, 1252, "Portuguese", "Brazil"}, + {0x0418, 852, 1250, "Romanian", "Romania"}, + {0x0419, 866, 1251, "Russian", "Russia"}, + {0x041A, 852, 1250, "Croatian", "Croatia"}, + {0x041B, 852, 1250, "Slovak", "Slovakia"}, + {0x041C, 852, 1250, "Albanian", "Albania"}, + {0x041D, 850, 1252, "Swedish", "Sweden"}, + {0x041F, 857, 1254, "Turkish", "Turkey"}, + {0x0421, 850, 1252, "Indonesian", "Indonesia"}, + {0x0422, 866, 1251, "Ukrainian", "Ukraine"}, + {0x0423, 866, 1251, "Belarusian", "Belarus"}, + {0x0424, 852, 1250, "Slovene", "Slovenia"}, + {0x0425, 775, 1257, "Estonian", "Estonia"}, + {0x0426, 775, 1257, "Latvian", "Latvia"}, + {0x0427, 775, 1257, "Lithuanian", "Lithuania"}, +/* {0x042A, ?, ?, "Vietnamese", "Vietnam"},*/ + {0x042D, 850, 1252, "Basque", "Spain"}, + {0x042F, 866, 1251, "Macedonian", "Former Yugoslav Republic of Macedonia"}, + {0x0436, 850, 1252, "Afrikaans", "South Africa"}, +/* {0x0438, 852, 1252, "Faroese", "Faroe Islands"}, FIXME: Not sure about codepages */ + {0x043C, 437, 1252, "Irish", "Ireland"}, +/* {0x048F, ?, ?, "Esperanto", ""},*/ +/* {0x0804, ?, ?, "Chinese (People's replublic of China)", People's republic of China"},*/ + {0x0807, 850, 1252, "German", "Switzerland"}, + {0x0809, 850, 1252, "English", "United Kingdom"}, + {0x080A, 850, 1252, "Spanish", "Mexico"}, + {0x080C, 850, 1252, "French", "Belgium"}, + {0x0810, 850, 1252, "Italian", "Switzerland"}, + {0x0813, 850, 1252, "Dutch", "Belgium"}, + {0x0814, 850, 1252, "Norwegian (Nynorsk)", "Norway"}, + {0x0816, 850, 1252, "Portuguese", "Portugal"}, +/* {0x081A, ?, ?, "Serbian (latin)", "Yugoslavia"},*/ + {0x081D, 850, 1252, "Swedish (Finland)", "Finland"}, + {0x0C07, 850, 1252, "German", "Austria"}, + {0x0C09, 850, 1252, "English", "Australia"}, + {0x0C0A, 850, 1252, "Spanish - International Sort", "Spain"}, + {0x0C0C, 850, 1252, "French", "Canada"}, + {0x0C1A, 855, 1251, "Serbian (Cyrillic)", "Serbia"}, + {0x1007, 850, 1252, "German", "Luxembourg"}, + {0x1009, 850, 1252, "English", "Canada"}, + {0x100A, 850, 1252, "Spanish", "Guatemala"}, + {0x100C, 850, 1252, "French", "Switzerland"}, + {0x1407, 850, 1252, "German", "Liechtenstein"}, + {0x1409, 850, 1252, "English", "New Zealand"}, + {0x140A, 850, 1252, "Spanish", "Costa Rica"}, + {0x140C, 850, 1252, "French", "Luxembourg"}, + {0x1809, 850, 1252, "English", "Ireland"}, + {0x180A, 850, 1252, "Spanish", "Panama"}, + {0x1C09, 437, 1252, "English", "South Africa"}, + {0x1C0A, 850, 1252, "Spanish", "Dominican Republic"}, + {0x2009, 850, 1252, "English", "Jamaica"}, + {0x200A, 850, 1252, "Spanish", "Venezuela"}, + {0x2409, 850, 1252, "English", "Caribbean"}, + {0x240A, 850, 1252, "Spanish", "Colombia"}, + {0x2809, 850, 1252, "English", "Belize"}, + {0x280A, 850, 1252, "Spanish", "Peru"}, + {0x2C09, 437, 1252, "English", "Trinidad & Tobago"}, + {0x2C0A, 850, 1252, "Spanish", "Argentina"}, + {0x300A, 850, 1252, "Spanish", "Ecuador"}, + {0x340A, 850, 1252, "Spanish", "Chile"}, + {0x380A, 850, 1252, "Spanish", "Uruguay"}, + {0x3C0A, 850, 1252, "Spanish", "Paraguay"}, + {0x400A, 850, 1252, "Spanish", "Bolivia"}, + {0x440A, 850, 1252, "Spanish", "El Salvador"}, + {0x480A, 850, 1252, "Spanish", "Honduras"}, + {0x4C0A, 850, 1252, "Spanish", "Nicaragua"}, + {0x500A, 850, 1252, "Spanish", "Puerto Rico"} +}; + +#define NLAN (sizeof(languages)/sizeof(languages[0])) + +void show_languages(void) +{ + int i; + printf(" Code | DOS-cp | WIN-cp | Language | Country\n"); + printf("-------+--------+--------+--------------+---------\n"); + for(i = 0; i < NLAN; i++) + printf("0x%04x | %5d | %5d | %-12s | %s\n", + languages[i].id, + languages[i].doscp, + languages[i].wincp, + languages[i].name, + languages[i].country); +} + +static int langcmp(const void *p1, const void *p2) +{ + return *(unsigned *)p1 - ((language_t *)p2)->id; +} + +const language_t *find_language(unsigned id) +{ + return (const language_t *)bsearch(&id, languages, NLAN, sizeof(languages[0]), langcmp); +} + +void show_codepages(void) +{ +#if 0 + unsigned i; + const union cptable *cpp; + printf("Codepages:\n"); + for(i = 0; (cpp = cp_enum_table(i)); i++) + { + printf("%-5d %s\n", cpp->info.codepage, cpp->info.name); + } +#endif +} + +#if 0 +const union cptable *find_codepage(int id) +{ + return cp_get_table(id); +} +#endif diff --git a/tools/wmc/lang.h b/tools/wmc/lang.h new file mode 100644 index 0000000..f6a17f1 --- /dev/null +++ b/tools/wmc/lang.h @@ -0,0 +1,26 @@ +/* + * Wine Message Compiler language and codepage support + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ + +#ifndef __WMC_LANG_H +#define __WMC_LANG_H + +//#include "wine/unicode.h" + +typedef struct language { + unsigned id; + unsigned doscp; + unsigned wincp; + char *name; + char *country; +} language_t; + +void show_languages(void); +const language_t *find_language(unsigned id); +void show_codepages(void); +const union cptable *find_codepage(int id); + +#endif diff --git a/tools/wmc/language.c b/tools/wmc/language.c new file mode 100644 index 0000000..d878a0d --- /dev/null +++ b/tools/wmc/language.c @@ -0,0 +1,107 @@ +{"South Africa", 0x0436, 1252}, +{"Saudi Arabia", 0x0401, 1256}, +{"Lebanon", 0x0401, 1256}, +{"Egypt", 0x0401, 1256}, +{"Algeria", 0x0401, 1256}, +{"Iraq", 0x0401, 1256}, +{"Kuwait", 0x0401, 1256}, +{"Marocco", 0x0401, 1256}, +{"Oman", 0x0401, 1256}, +{"Quatar", 0x0401, 1256}, +{"Syria", 0x0401, 1256}, +{"Tunisia", 0x0401, 1256}, +{"United Arab Emirates",0x0401, 1256}, +{"Belaruss", 0x0423, 1251}, +{"Bulgaria", 0x0402 +{"France", 0x040c, 1252}, +{"Spain", 0x0403, 1252}, +{"China (Taiwan)", 0x0404 +{"United Kingdom", 0x0409, 1252}, +{"Wales", 0x0409, 1252}, /* FIXME */ +{"Czech Republic", 0x0405, 1250}, +{"Denmark", 0x0406, 1252}, +{"Austria", 0x0407, 1252}, +{"Liechtenstein", 0x0407, 1252}, +{"Luxemburg", 0x0407, 1252}, +{"Switzerland", 0x0807, 1252}, +{"Germany", 0x0407, 1252}, +{"Australia", 0x0c09, 1252}, +{"Caribbean", 0x2409, 1252}, +{"Canada", 0x1009, 1252}, +{"United Kingdom", 0x0809, 1252}, +{"Ireland", 0x1809, 1252}, +{"Jamaica", 0x2009, 1252}, +{"Belize", 0x2809, 1252}, +{"South Africa", 0x1c09, 1252}, +{"Trinidad & Tobago", 0x2c09, 1252}, +{"United States", 0x0409, 1252}, +{"New Zealand", 0x1409, 1252}, +{"Panama", 0x040a, 1252}, +{"Bolivia", 0x040a, 1252}, +{"Costa Rica", 0x140a, 1252}, +{"Dominican Republic", 0x040a, 1252}, +{"El Salvador", 0x040a, 1252}, +{"Ecuador", 0x040a, 1252}, +{"Guatemala", 0x040a, 1252}, +{"Honduras", 0x040a, 1252}, +{"Nicaragua", 0x040a, 1252}, +{"Chile", 0x040a, 1252}, +{"Mexico", 0x040a, 1252}, +{"Spain", 0x040a, 1252}, +{"Colombia", 0x040a, 1252}, +{"Spain", 0x040a, 1252}, +{"Peru", 0x040a, 1252}, +{"Argentina", 0x040a, 1252}, +{"Estonia", 0x0425, 1252}, +{"Puerto Rico", 0x040a, 1252}, +{"Venezuela", 0x040a, 1252}, +{"Uruguay", 0x380a, 1252}, +{"Paraguay", 0x040a, 1252}, +{"Spain (Basque)", 0x04d2, 1252}, +{"Finland", 0x040b, 1252}, +{"Faroe Islands", 0x0438, 1252}, +{"France", 0x040c, 1252}, +{"Belgium", 0x040c, 1252}, +{"Canada", 0x040c, 1252}, +{"Luxemburg", 0x040c, 1252}, +{"Switzerland", 0x040c, 1252}, +{"Ireland", 0x0000, 1252}, +{"United Kingdom", 0x0409, 1252}, +{"Isle of Man", 0x0409, 1252}, +{"Greece", 0x0408, 1253}, +{"Croatia", 0x041a, 1250}, +{"Hungary", 0x040e, 1250}, +{"Indonesia", 0x0421, 1252}, +{"Iceland", 0x040f, 1252}, +{"Italy", 0x0410, 1252}, +{"Switzerand", 0x0410, 1252}, +{"Japan", 0x0411, 0}, +{"Korea", 0x0000, 0}, +{"Korea (South)", 0x0412, 0}, +{"Lithuania", 0x0427, 1257}, +{"Latvia", 0x0426, 1257}, +{"Belgium", 0x0413, 1252}, +{"Netherlands", 0x0413, 1252}, +{"Suriname", 0x0413, 1252}, +{"Norway", 0x0814, 1252}, +{"Norway", 0x0414, 1252}, +{"Poland", 0x0415, 1250}, +{"Brazil", 0x0416, 1252}, +{"Portugal", 0x0416, 1252}, +{"Romania", 0x0418, 1250}, +{"Russia", 0x0000, 1251}, +{"Slovakia", 0x041b, 1250}, +{"Slovenia", 0x0424, 1250}, +{"Albania", 0x041c, 0}, +{"Yugoslavia", 0x0c1a, 0}, +{"Yugoslavia", 0x081a, 1250}, +{"Sweden", 0x041d, 1252}, +{"Finland", 0x081d, 1252}, +{"Thailand", 0x041e, 0}, +{"Turkey", 0x041f, 1254}, +{"Ukrainia", 0x0422, 1251}, +{"Vietnam", 0x042a, 0}, +{"Belgium", 0x0490, 1252}, +{"Hong Kong", 0x0404, 0}, +{"People's republic of China", 0x0804, 0}, +{"Singapore", 0x0404, 0} diff --git a/tools/wmc/makefile b/tools/wmc/makefile new file mode 100644 index 0000000..5de3fa8 --- /dev/null +++ b/tools/wmc/makefile @@ -0,0 +1,58 @@ +# +# ReactOS/Wine message compiler +# +PATH_TO_TOP = ../.. + +TARGET=wmc$(EXE_POSTFIX) + +all: $(TARGET) + +OBJECTS = getopt.o lang.o mcl.o utils.o wmc.o write.o y_tab.o misc.o + +CLEAN_FILES = *.o wmc$(EXE_POSTFIX) + +wmc$(EXE_POSTFIX): $(OBJECTS) + $(HOST_CC) $(OBJECTS) -g -o wmc$(EXE_POSTFIX) + +HOST_CFLAGS = -I. + +getopt.o: getopt.c + $(HOST_CC) $(HOST_CFLAGS) -g -c getopt.c -o getopt.o + +lang.o: lang.c + $(HOST_CC) $(HOST_CFLAGS) -g -c lang.c -o lang.o + +misc.o: misc.c + $(HOST_CC) $(HOST_CFLAGS) -g -c misc.c -o misc.o + +mcl.o: mcl.c + $(HOST_CC) $(HOST_CFLAGS) -g -c mcl.c -o mcl.o + +utils.o: utils.c + $(HOST_CC) $(HOST_CFLAGS) -g -c utils.c -o utils.o + +wmc.o: wmc.c + $(HOST_CC) $(HOST_CFLAGS) -g -c wmc.c -o wmc.o + +write.o: write.c + $(HOST_CC) $(HOST_CFLAGS) -g -c write.c -o write.o + +y_tab.o: y_tab.c + $(HOST_CC) $(HOST_CFLAGS) -g -c y_tab.c -o y_tab.o + +ifeq ($(HOST),mingw32-linux) +clean: + rm -f *.o + rm -f wmc$(EXE_POSTFIX) +endif +ifeq ($(HOST),mingw32-windows) +clean: + del *.o + del wmc$(EXE_POSTFIX) +endif + +.phony: clean + +include $(PATH_TO_TOP)/rules.mak + +# EOF diff --git a/tools/wmc/makefile.in b/tools/wmc/makefile.in new file mode 100644 index 0000000..9b122b2 --- /dev/null +++ b/tools/wmc/makefile.in @@ -0,0 +1,49 @@ +DEFS = -D__WINE__ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +YACCOPT = #-v +LIBEXT = @LIBEXT@ + +PROGRAMS = wmc +MODULE = none + +C_SRCS = \ + lang.c \ + mcl.c \ + utils.c \ + wmc.c \ + write.c + +EXTRA_SRCS = mcy.y +EXTRA_OBJS = y.tab.o + +all: $(PROGRAMS) + +depend mcl.o: y.tab.h + +@MAKE_RULES@ + +wmc: $(OBJS) $(TOPOBJDIR)/libwine_unicode.$(LIBEXT) + $(CC) $(CFLAGS) -o wmc $(OBJS) -L$(TOPOBJDIR) -lwine_unicode $(LEXLIB) + +$(TOPOBJDIR)/libwine_unicode.$(LIBEXT): + cd $(TOPOBJDIR) && $(MAKE) libwine_unicode.$(LIBEXT) + +y.tab.c y.tab.h: mcy.y + $(YACC) $(YACCOPT) -d -t $(SRCDIR)/mcy.y + +clean:: + $(RM) y.tab.c y.tab.h y.output + +install:: $(PROGRAMS) + [ -d $(bindir) ] || $(MKDIR) $(bindir) + [ -d $(mandir)/man$(prog_manext) ] || $(MKDIR) $(mandir)/man$(prog_manext) + $(INSTALL_DATA) $(SRCDIR)/wmc.man $(mandir)/man$(prog_manext)/wmc.$(prog_manext) + $(INSTALL_PROGRAM) wmc $(bindir)/wmc + +uninstall:: + $(RM) $(bindir)/wmc $(mandir)/man$(prog_manext)/wmc.$(prog_manext) + +### Dependencies: diff --git a/tools/wmc/mcl.c b/tools/wmc/mcl.c new file mode 100644 index 0000000..d0da376 --- /dev/null +++ b/tools/wmc/mcl.c @@ -0,0 +1,736 @@ +/* + * Wine Message Compiler lexical scanner + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ +#include +#include +#include +#include +#include + +#include "config.h" + +#include "utils.h" +#include "wmc.h" +#include "lang.h" + +#include "y_tab.h" + +/* + * Keywords are case insenitive. All normal input is treated as + * being in codepage iso-8859-1 for ascii input files (unicode + * page 0) and as equivalent unicode if unicode input is selected. + * All normal input, which is not part of a message text, is + * enforced to be unicode page 0. Otherwise an error will be + * generated. The normal file data should only be ASCII because + * that is the basic definition of the grammar. + * + * Byteorder or unicode input is determined automatically by + * reading the first 8 bytes and checking them against unicode + * page 0 byteorder (hibyte must be 0). + * -- FIXME -- + * Alternatively, the input is checked against a special byte + * sequence to identify the file. + * -- FIXME -- + * + * + * Keywords: + * Codepages + * Facility + * FacilityNames + * LanguageNames + * MessageId + * MessageIdTypedef + * Severity + * SeverityNames + * SymbolicName + * + * Default added identifiers for classes: + * SeverityNames: + * Success = 0x0 + * Informational = 0x1 + * Warning = 0x2 + * Error = 0x3 + * FacilityNames: + * System = 0x0FF + * Application = 0xFFF + * + * The 'Codepages' keyword is a wmc extension. + */ + +static WCHAR ustr_application[] = { 'A', 'p', 'p', 'l', 'i', 'c', 'a', 't', 'i', 'o', 'n', 0 }; +static WCHAR ustr_codepages[] = { 'C', 'o', 'd', 'e', 'p', 'a', 'g', 'e', 's', 0 }; +static WCHAR ustr_english[] = { 'E', 'n', 'g', 'l', 'i', 's', 'h', 0 }; +static WCHAR ustr_error[] = { 'E', 'r', 'r', 'o', 'r', 0 }; +static WCHAR ustr_facility[] = { 'F', 'a', 'c', 'i', 'l', 'i', 't', 'y', 0 }; +static WCHAR ustr_facilitynames[] = { 'F', 'a', 'c', 'i', 'l', 'i', 't', 'y', 'N', 'a', 'm', 'e', 's', 0 }; +static WCHAR ustr_informational[] = { 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'a', 'l', 0 }; +static WCHAR ustr_language[] = { 'L', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 0}; +static WCHAR ustr_languagenames[] = { 'L', 'a', 'n', 'g', 'u', 'a', 'g', 'e', 'N', 'a', 'm', 'e', 's', 0}; +static WCHAR ustr_messageid[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'I', 'd', 0 }; +static WCHAR ustr_messageidtypedef[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'I', 'd', 'T', 'y', 'p', 'e', 'd', 'e', 'f', 0 }; +static WCHAR ustr_outputbase[] = { 'O', 'u', 't', 'p', 'u', 't', 'B', 'a', 's', 'e', 0 }; +static WCHAR ustr_severity[] = { 'S', 'e', 'v', 'e', 'r', 'i', 't', 'y', 0 }; +static WCHAR ustr_severitynames[] = { 'S', 'e', 'v', 'e', 'r', 'i', 't', 'y', 'N', 'a', 'm', 'e', 's', 0 }; +static WCHAR ustr_success[] = { 'S', 'u', 'c', 'c', 'e', 's', 's', 0 }; +static WCHAR ustr_symbolicname[] = { 'S', 'y', 'm', 'b', 'o', 'l', 'i', 'c', 'N', 'a', 'm', 'e', 0 }; +static WCHAR ustr_system[] = { 'S', 'y', 's', 't', 'e', 'm', 0 }; +static WCHAR ustr_warning[] = { 'W', 'a', 'r', 'n', 'i', 'n', 'g', 0 }; +static WCHAR ustr_msg00001[] = { 'm', 's', 'g', '0', '0', '0', '0', '1', 0 }; +/* + * This table is to beat any form of "expression building" to check for + * correct filename characters. It is also used for ident checks. + * FIXME: use it more consistently. + */ + +#define CH_SHORTNAME 0x01 +#define CH_LONGNAME 0x02 +#define CH_IDENT 0x04 +#define CH_NUMBER 0x08 +/*#define CH_WILDCARD 0x10*/ +/*#define CH_DOT 0x20*/ +#define CH_PUNCT 0x40 +#define CH_INVALID 0x80 + +static const char char_table[256] = { + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x00 - 0x07 */ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x08 - 0x0F */ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x10 - 0x17 */ + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x18 - 0x1F */ + 0x80, 0x03, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, /* 0x20 - 0x27 " !"#$%&'" */ + 0x43, 0x43, 0x10, 0x80, 0x03, 0x03, 0x22, 0x80, /* 0x28 - 0x2F "()*+,-./" */ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, /* 0x30 - 0x37 "01234567" */ + 0x0b, 0x0b, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x10, /* 0x38 - 0x3F "89:;<=>?" */ + 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x40 - 0x47 "@ABCDEFG" */ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x48 - 0x4F "HIJKLMNO" */ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x50 - 0x57 "PQRSTUVW" */ + 0x07, 0x07, 0x07, 0x80, 0x80, 0x80, 0x80, 0x07, /* 0x58 - 0x5F "XYZ[\]^_" */ + 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x60 - 0x67 "`abcdefg" */ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x68 - 0x6F "hijklmno" */ + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, /* 0x70 - 0x77 "pqrstuvw" */ + 0x07, 0x07, 0x07, 0x03, 0x80, 0x03, 0x03, 0x80, /* 0x78 - 0x7F "xyz{|}~ " */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x80 - 0x87 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x88 - 0x8F */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x90 - 0x97 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0x98 - 0x9F */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xA0 - 0xA7 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xA8 - 0xAF */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xB0 - 0xB7 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xB8 - 0xBF */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xC0 - 0xC7 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xC8 - 0xCF */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xD0 - 0xD7 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xD8 - 0xDF */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xE0 - 0xE7 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xE8 - 0xEF */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 0xF0 - 0xF7 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x80, /* 0xF8 - 0xFF */ +}; + +static int isisochar(int ch) +{ + return !(ch & (~0xff)); +} + +static int codepage; +//static const union cptable *codepage_def; + +void set_codepage(int cp) +{ + codepage = cp; +#if 0 + codepage_def = find_codepage(codepage); + if(!codepage_def) + xyyerror("Codepage %d not found; cannot process", codepage); +#endif +} + +/* + * Input functions + */ +static int nungetstack = 0; +static int allocungetstack = 0; +static char *ungetstack = NULL; +static int ninputbuffer = 0; +static WCHAR *inputbuffer = NULL; +static char *xlatebuffer = NULL; + +#define INPUTBUFFER_SIZE 2048 /* Must be larger than 4 and approx. large enough to hold a line */ + +/* + * Fill the input buffer with *one* line of input. + * The line is '\n' terminated so that scanning + * messages with translation works as expected + * (otherwise we cannot pre-translate because the + * language is first known one line before the + * actual message). + */ +static int fill_inputbuffer(void) +{ + int n; + static char err_fatalread[] = "Fatal: reading input failed"; + static int endian = -1; + + if(!inputbuffer) + { + inputbuffer = xmalloc(INPUTBUFFER_SIZE); + xlatebuffer = xmalloc(INPUTBUFFER_SIZE); + } + +try_again: + if(!unicodein) + { + char *cptr; + cptr = fgets(xlatebuffer, INPUTBUFFER_SIZE, yyin); + if(!cptr && ferror(yyin)) + xyyerror(err_fatalread); + else if(!cptr) + return 0; +// assert(codepage_def != NULL); +// n = cp_mbstowcs(codepage_def, 0, xlatebuffer, strlen(xlatebuffer)+1, inputbuffer, INPUTBUFFER_SIZE); + n = MultiByteToWideChar(codepage, 0, xlatebuffer, strlen(xlatebuffer)+1, inputbuffer, INPUTBUFFER_SIZE); if(n < 0) + internal_error(__FILE__, __LINE__, "Could not translate to unicode (%d)", n); + if(n <= 1) + goto try_again; /* Should not hapen */ + n--; /* Strip added conversion '\0' from input length */ + /* + * FIXME: + * Detect UTF-8 in the first time we read some bytes by + * checking the special sequence "FE..." or something like + * that. I need to check www.unicode.org for details. + */ + } + else + { + if(endian == -1) + { + n = fread(inputbuffer, 1, 8, yyin); + if(n != 8) + { + if(!n && ferror(yyin)) + xyyerror(err_fatalread); + else + xyyerror("Fatal: file to short to determine byteorder (should never happen)"); + } + if(isisochar(inputbuffer[0]) && + isisochar(inputbuffer[1]) && + isisochar(inputbuffer[2]) && + isisochar(inputbuffer[3])) + { +#ifdef WORDS_BIGENDIAN + endian = WMC_BO_BIG; +#else + endian = WMC_BO_LITTLE; +#endif + } + else if(isisochar(BYTESWAP_WORD(inputbuffer[0])) && + isisochar(BYTESWAP_WORD(inputbuffer[1])) && + isisochar(BYTESWAP_WORD(inputbuffer[2])) && + isisochar(BYTESWAP_WORD(inputbuffer[3]))) + { +#ifdef WORDS_BIGENDIAN + endian = WMC_BO_LITTLE; +#else + endian = WMC_BO_BIG; +#endif + } + else + xyyerror("Fatal: cannot determine file's byteorder"); + /* FIXME: + * Determine the file-endian with the leader-bytes + * "FF FE..."; can't remember the exact sequence. + */ + n /= 2; +#ifdef WORDS_BIGENDIAN + if(endian == WMC_BO_LITTLE) +#else + if(endian == WMC_BO_BIG) +#endif + { + inputbuffer[0] = BYTESWAP_WORD(inputbuffer[0]); + inputbuffer[1] = BYTESWAP_WORD(inputbuffer[1]); + inputbuffer[2] = BYTESWAP_WORD(inputbuffer[2]); + inputbuffer[3] = BYTESWAP_WORD(inputbuffer[3]); + } + + } + else + { + int i; + n = 0; + for(i = 0; i < INPUTBUFFER_SIZE; i++) + { + int t; + t = fread(&inputbuffer[i], 2, 1, yyin); + if(!t && ferror(yyin)) + xyyerror(err_fatalread); + else if(!t && n) + break; + n++; +#ifdef WORDS_BIGENDIAN + if(endian == WMC_BO_LITTLE) +#else + if(endian == WMC_BO_BIG) +#endif + { + if((inputbuffer[i] = BYTESWAP_WORD(inputbuffer[i])) == '\n') + break; + } + else + { + if(inputbuffer[i] == '\n') + break; + } + } + } + + } + + if(!n) + { + yywarning("Re-read line (input was or converted to zilch)"); + goto try_again; /* Should not happen, but could be due to stdin reading and a signal */ + } + + ninputbuffer += n; + return 1; +} + +static int get_unichar(void) +{ + static WCHAR *b = NULL; + char_number++; + + if(nungetstack) + return ungetstack[--nungetstack]; + + if(!ninputbuffer) + { + if(!fill_inputbuffer()) + return EOF; + b = inputbuffer; + } + + ninputbuffer--; + return (int)(*b++ & 0xffff); +} + +static void unget_unichar(int ch) +{ + if(ch == EOF) + return; + + char_number--; + + if(nungetstack == allocungetstack) + { + allocungetstack += 32; + ungetstack = xrealloc(ungetstack, allocungetstack * sizeof(*ungetstack)); + } + + ungetstack[nungetstack++] = (WCHAR)ch; +} + + +/* + * Normal character stack. + * Used for number scanning. + */ +static int ncharstack = 0; +static int alloccharstack = 0; +static char *charstack = NULL; + +static void empty_char_stack(void) +{ + ncharstack = 0; +} + +static void push_char(int ch) +{ + if(ncharstack == alloccharstack) + { + alloccharstack += 32; + charstack = xrealloc(charstack, alloccharstack * sizeof(*charstack)); + } + charstack[ncharstack++] = (char)ch; +} + +static int tos_char_stack(void) +{ + if(!ncharstack) + return 0; + else + return (int)(charstack[ncharstack-1] & 0xff); +} + +static char *get_char_stack(void) +{ + return charstack; +} + +/* + * Unicode character stack. + * Used for general scanner. + */ +static int nunicharstack = 0; +static int allocunicharstack = 0; +static WCHAR *unicharstack = NULL; + +static void empty_unichar_stack(void) +{ + nunicharstack = 0; +} + +static void push_unichar(int ch) +{ + if(nunicharstack == allocunicharstack) + { + allocunicharstack += 128; + unicharstack = xrealloc(unicharstack, allocunicharstack * sizeof(*unicharstack)); + } + unicharstack[nunicharstack++] = (WCHAR)ch; +} + +#if 0 +static int tos_unichar_stack(void) +{ + if(!nunicharstack) + return 0; + else + return (int)(unicharstack[nunicharstack-1] & 0xffff); +} +#endif + +static WCHAR *get_unichar_stack(void) +{ + return unicharstack; +} + +/* + * Number scanner + * + * state | ch | next state + * ------+-----------------+-------------------------- + * 0 | [0] | 1 + * 0 | [1-9] | 4 + * 0 | . | error (should never occur) + * 1 | [xX] | 2 + * 1 | [0-7] | 3 + * 1 | [89a-wyzA-WYZ_] | error invalid digit + * 1 | . | return 0 + * 2 | [0-9a-fA-F] | 2 + * 2 | [g-zG-Z_] | error invalid hex digit + * 2 | . | return (hex-number) if TOS != [xX] else error + * 3 | [0-7] | 3 + * 3 | [89a-zA-Z_] | error invalid octal digit + * 3 | . | return (octal-number) + * 4 | [0-9] | 4 + * 4 | [a-zA-Z_] | error invalid decimal digit + * 4 | . | return (decimal-number) + * + * All non-identifier characters [^a-zA-Z_0-9] terminate the scan + * and return the value. This is not entirely correct, but close + * enough (should check punctuators as trailing context, but the + * char_table is not adapted to that and it is questionable whether + * it is worth the trouble). + * All non-iso-8859-1 characters are an error. + */ +static int scan_number(int ch) +{ + int state = 0; + int base = 10; + empty_char_stack(); + + while(1) + { + if(!isisochar(ch)) + xyyerror("Invalid digit"); + + switch(state) + { + case 0: + if(isdigit(ch)) + { + push_char(ch); + if(ch == '0') + state = 1; + else + state = 4; + } + else + internal_error(__FILE__, __LINE__, "Non-digit in first number-scanner state"); + break; + case 1: + if(ch == 'x' || ch == 'X') + { + push_char(ch); + state = 2; + } + else if(ch >= '0' && ch <= '7') + { + push_char(ch); + state = 3; + } + else if(isalpha(ch) || ch == '_') + xyyerror("Invalid number digit"); + else + { + unget_unichar(ch); + yylval.num = 0; + return tNUMBER; + } + break; + case 2: + if(isxdigit(ch)) + push_char(ch); + else if(isalpha(ch) || ch == '_' || !isxdigit(tos_char_stack())) + xyyerror("Invalid hex digit"); + else + { + base = 16; + goto finish; + } + break; + case 3: + if(ch >= '0' && ch <= '7') + push_char(ch); + else if(isalnum(ch) || ch == '_') + xyyerror("Invalid octal digit"); + else + { + base = 8; + goto finish; + } + break; + case 4: + if(isdigit(ch)) + push_char(ch); + else if(isalnum(ch) || ch == '_') + xyyerror("Invalid decimal digit"); + else + { + base = 10; + goto finish; + } + break; + default: + internal_error(__FILE__, __LINE__, "Invalid state in number-scanner"); + } + ch = get_unichar(); + } +finish: + unget_unichar(ch); + push_char(0); + yylval.num = strtoul(get_char_stack(), NULL, base); + return tNUMBER; +} + +static void newline(void) +{ + line_number++; + char_number = 1; +} + +static int unisort(const void *p1, const void *p2) +{ + return unistricmp(((token_t *)p1)->name, ((token_t *)p2)->name); +} + +static token_t *tokentable = NULL; +static int ntokentable = 0; + +token_t *lookup_token(const WCHAR *s) +{ + token_t tok; + + tok.name = s; + return (token_t *)bsearch(&tok, tokentable, ntokentable, sizeof(*tokentable), unisort); +} + +void add_token(tok_e type, const WCHAR *name, int tok, int cp, const WCHAR *alias, int fix) +{ + ntokentable++; + tokentable = xrealloc(tokentable, ntokentable * sizeof(*tokentable)); + tokentable[ntokentable-1].type = type; + tokentable[ntokentable-1].name = name; + tokentable[ntokentable-1].token = tok; + tokentable[ntokentable-1].codepage = cp; + tokentable[ntokentable-1].alias = alias; + tokentable[ntokentable-1].fixed = fix; + qsort(tokentable, ntokentable, sizeof(*tokentable), unisort); +} + +void get_tokentable(token_t **tab, int *len) +{ + assert(tab != NULL); + assert(len != NULL); + *tab = tokentable; + *len = ntokentable; +} + +/* + * The scanner + * + */ +int yylex(void) +{ + static WCHAR ustr_dot1[] = { '.', '\n', 0 }; + static WCHAR ustr_dot2[] = { '.', '\r', '\n', 0 }; + static int isinit = 0; + int ch; + + if(!isinit) + { + isinit++; + set_codepage(WMC_DEFAULT_CODEPAGE); + add_token(tok_keyword, ustr_codepages, tCODEPAGE, 0, NULL, 0); + add_token(tok_keyword, ustr_facility, tFACILITY, 0, NULL, 1); + add_token(tok_keyword, ustr_facilitynames, tFACNAMES, 0, NULL, 1); + add_token(tok_keyword, ustr_language, tLANGUAGE, 0, NULL, 1); + add_token(tok_keyword, ustr_languagenames, tLANNAMES, 0, NULL, 1); + add_token(tok_keyword, ustr_messageid, tMSGID, 0, NULL, 1); + add_token(tok_keyword, ustr_messageidtypedef, tTYPEDEF, 0, NULL, 1); + add_token(tok_keyword, ustr_outputbase, tBASE, 0, NULL, 1); + add_token(tok_keyword, ustr_severity, tSEVERITY, 0, NULL, 1); + add_token(tok_keyword, ustr_severitynames, tSEVNAMES, 0, NULL, 1); + add_token(tok_keyword, ustr_symbolicname, tSYMNAME, 0, NULL, 1); + add_token(tok_severity, ustr_error, 0x03, 0, NULL, 0); + add_token(tok_severity, ustr_warning, 0x02, 0, NULL, 0); + add_token(tok_severity, ustr_informational, 0x01, 0, NULL, 0); + add_token(tok_severity, ustr_success, 0x00, 0, NULL, 0); + add_token(tok_facility, ustr_application, 0xFFF, 0, NULL, 0); + add_token(tok_facility, ustr_system, 0x0FF, 0, NULL, 0); + add_token(tok_language, ustr_english, 0x409, 437, ustr_msg00001, 0); + } + + empty_unichar_stack(); + + while(1) + { + if(want_line) + { + while((ch = get_unichar()) != '\n') + { + if(ch == EOF) + xyyerror("Unexpected EOF"); + push_unichar(ch); + } + newline(); + push_unichar(ch); + push_unichar(0); + if(!unistrcmp(ustr_dot1, get_unichar_stack()) || !unistrcmp(ustr_dot2, get_unichar_stack())) + { + want_line = 0; + /* Reset the codepage to our default after each message */ + set_codepage(WMC_DEFAULT_CODEPAGE); + return tMSGEND; + } + yylval.str = xunistrdup(get_unichar_stack()); + return tLINE; + } + + ch = get_unichar(); + + if(ch == EOF) + return EOF; + + if(ch == '\n') + { + newline(); + if(want_nl) + { + want_nl = 0; + return tNL; + } + continue; + } + + if(isisochar(ch)) + { + if(want_file) + { + int n = 0; + while(n < 8 && isisochar(ch)) + { + int t = char_table[ch]; + if((t & CH_PUNCT) || !(t & CH_SHORTNAME)) + break; + + push_unichar(ch); + n++; + ch = get_unichar(); + } + unget_unichar(ch); + push_unichar(0); + want_file = 0; + yylval.str = xunistrdup(get_unichar_stack()); + return tFILE; + } + + if(char_table[ch] & CH_IDENT) + { + token_t *tok; + while(isisochar(ch) && (char_table[ch] & (CH_IDENT|CH_NUMBER))) + { + push_unichar(ch); + ch = get_unichar(); + } + unget_unichar(ch); + push_unichar(0); + if(!(tok = lookup_token(get_unichar_stack()))) + { + yylval.str = xunistrdup(get_unichar_stack()); + return tIDENT; + } + switch(tok->type) + { + case tok_keyword: + return tok->token; + + case tok_language: + codepage = tok->codepage; + /* Fall through */ + case tok_severity: + case tok_facility: + yylval.tok = tok; + return tTOKEN; + + default: + internal_error(__FILE__, __LINE__, "Invalid token type encountered"); + } + } + + if(isspace(ch)) /* Ignore space */ + continue; + + if(isdigit(ch)) + return scan_number(ch); + } + + switch(ch) + { + case ':': + case '=': + case '+': + case '(': + case ')': + return ch; + case ';': + while(ch != '\n' && ch != EOF) + { + push_unichar(ch); + ch = get_unichar(); + } + newline(); + push_unichar(ch); /* Include the newline */ + push_unichar(0); + yylval.str = xunistrdup(get_unichar_stack()); + return tCOMMENT; + default: + xyyerror("Invalid character '%c' (0x%04x)", isisochar(ch) && isprint(ch) ? ch : '.', ch); + } + } +} + diff --git a/tools/wmc/mcy.y b/tools/wmc/mcy.y new file mode 100644 index 0000000..b9dd71d --- /dev/null +++ b/tools/wmc/mcy.y @@ -0,0 +1,662 @@ +/* + * Wine Message Compiler parser + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + * The basic grammar of the file is yet another example of, humpf, + * design. There is is mix of context-insensitive and -sentitive + * stuff, which makes it rather complicated. + * The header definitions are all context-insensitive because they have + * delimited arguments, whereas the message headers are (semi-) context- + * sensitive and the messages themselves are, well, RFC82[12] delimited. + * This mixture seems to originate from the time that ms and ibm were + * good friends and developing os/2 according to the "compatibility" + * switch and reading some comments here and there. + * + * I'll ignore most of the complications and concentrate on the concept + * which allows me to use yacc. Basically, everything is context- + * insensitive now, with the exception of the message-text itself and + * the preceding language declaration. + * + */ + +%{ + +#include +#include +#include + +#include "config.h" + +#include "utils.h" +#include "wmc.h" +#include "lang.h" + +static const char err_syntax[] = "Syntax error"; +static const char err_number[] = "Number expected"; +static const char err_ident[] = "Identifier expected"; +static const char err_assign[] = "'=' expected"; +static const char err_popen[] = "'(' expected"; +static const char err_pclose[] = "')' expected"; +static const char err_colon[] = "':' expected"; +static const char err_msg[] = "Message expected"; + +/* Scanner switches */ +int want_nl = 0; /* Request next newlinw */ +int want_line = 0; /* Request next complete line */ +int want_file = 0; /* Request next ident as filename */ + +node_t *nodehead = NULL; /* The list of all parsed elements */ +static node_t *nodetail = NULL; +lan_blk_t *lanblockhead; /* List of parsed elements transposed */ + +static int base = 16; /* Current printout base to use (8, 10 or 16) */ +static WCHAR *cast = NULL; /* Current typecast to use */ + +static int last_id = 0; /* The last message ID parsed */ +static int last_sev = 0; /* Last severity code parsed */ +static int last_fac = 0; /* Last facility code parsed */ +static WCHAR *last_sym = NULL;/* Last alias symbol parsed */ +static int have_sev; /* Set if severity parsed for current message */ +static int have_fac; /* Set if facility parsed for current message */ +static int have_sym; /* Set is symbol parsed for current message */ + +static cp_xlat_t *cpxlattab = NULL; /* Codepage translation table */ +static int ncpxlattab = 0; + +/* Prototypes */ +static WCHAR *merge(WCHAR *s1, WCHAR *s2); +static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg); +static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg); +static msg_t *complete_msg(msg_t *msg, int id); +static void add_node(node_e type, void *p); +static void do_add_token(tok_e type, token_t *tok, const char *code); +static void test_id(int id); +static int check_languages(node_t *head); +static lan_blk_t *block_messages(node_t *head); +static void add_cpxlat(int lan, int cpin, int cpout); +static cp_xlat_t *find_cpxlat(int lan); + +%} + + +%union { + WCHAR *str; + unsigned num; + token_t *tok; + lanmsg_t *lmp; + msg_t *msg; + lan_cp_t lcp; +} + + +%token tSEVNAMES tFACNAMES tLANNAMES tBASE tCODEPAGE +%token tTYPEDEF tNL tSYMNAME tMSGEND +%token tSEVERITY tFACILITY tLANGUAGE tMSGID +%token tIDENT tLINE tFILE tCOMMENT +%token tNUMBER +%token tTOKEN + +%type alias lines +%type optcp id msgid clan +%type token +%type body +%type bodies msg +%type lang + +%% +file : items { + if(!check_languages(nodehead)) + xyyerror("No messages defined"); + lanblockhead = block_messages(nodehead); + } + ; + +items : decl + | items decl + ; + +decl : global + | msg { add_node(nd_msg, $1); } + | tCOMMENT { add_node(nd_comment, $1); } + | error { xyyerror(err_syntax); /* `Catch all' error */ } + ; + +global : tSEVNAMES '=' '(' smaps ')' + | tSEVNAMES '=' '(' smaps error { xyyerror(err_pclose); } + | tSEVNAMES '=' error { xyyerror(err_popen); } + | tSEVNAMES error { xyyerror(err_assign); } + | tFACNAMES '=' '(' fmaps ')' + | tFACNAMES '=' '(' fmaps error { xyyerror(err_pclose); } + | tFACNAMES '=' error { xyyerror(err_popen); } + | tFACNAMES error { xyyerror(err_assign); } + | tLANNAMES '=' '(' lmaps ')' + | tLANNAMES '=' '(' lmaps error { xyyerror(err_pclose); } + | tLANNAMES '=' error { xyyerror(err_popen); } + | tLANNAMES error { xyyerror(err_assign); } + | tCODEPAGE '=' '(' cmaps ')' + | tCODEPAGE '=' '(' cmaps error { xyyerror(err_pclose); } + | tCODEPAGE '=' error { xyyerror(err_popen); } + | tCODEPAGE error { xyyerror(err_assign); } + | tTYPEDEF '=' tIDENT { cast = $3; } + | tTYPEDEF '=' error { xyyerror(err_number); } + | tTYPEDEF error { xyyerror(err_assign); } + | tBASE '=' tNUMBER { + switch(base) + { + case 8: + case 10: + case 16: + base = $3; + break; + default: + xyyerror("Numberbase must be 8, 10 or 16"); + } + } + | tBASE '=' error { xyyerror(err_number); } + | tBASE error { xyyerror(err_assign); } + ; + +/*---------------------------------------------------------------------- + * SeverityNames mapping + */ +smaps : smap + | smaps smap + | error { xyyerror(err_ident); } + ; + +smap : token '=' tNUMBER alias { + $1->token = $3; + $1->alias = $4; + if($3 & (~0x3)) + xyyerror("Severity value out of range (0x%08x > 0x3)", $3); + do_add_token(tok_severity, $1, "severity"); + } + | token '=' error { xyyerror(err_number); } + | token error { xyyerror(err_assign); } + ; + +/*---------------------------------------------------------------------- + * FacilityNames mapping + */ +fmaps : fmap + | fmaps fmap + | error { xyyerror(err_ident); } + ; + +fmap : token '=' tNUMBER alias { + $1->token = $3; + $1->alias = $4; + if($3 & (~0xfff)) + xyyerror("Facility value out of range (0x%08x > 0xfff)", $3); + do_add_token(tok_facility, $1, "facility"); + } + | token '=' error { xyyerror(err_number); } + | token error { xyyerror(err_assign); } + ; + +alias : /* Empty */ { $$ = NULL; } + | ':' tIDENT { $$ = $2; } + | ':' error { xyyerror(err_ident); } + ; + +/*---------------------------------------------------------------------- + * LanguageNames mapping + */ +lmaps : lmap + | lmaps lmap + | error { xyyerror(err_ident); } + ; + +lmap : token '=' tNUMBER setfile ':' tFILE optcp { + $1->token = $3; + $1->alias = $6; + $1->codepage = $7; + do_add_token(tok_language, $1, "language"); + if(!find_language($1->token) && !find_cpxlat($1->token)) + yywarning("Language 0x%x not built-in, using codepage %d; use explicit codepage to override", $1->token, WMC_DEFAULT_CODEPAGE); + } + | token '=' tNUMBER setfile ':' error { xyyerror("Filename expected"); } + | token '=' tNUMBER error { xyyerror(err_colon); } + | token '=' error { xyyerror(err_number); } + | token error { xyyerror(err_assign); } + ; + +optcp : /* Empty */ { $$ = 0; } + | ':' tNUMBER { $$ = $2; } + | ':' error { xyyerror("Codepage-number expected"); } + ; + +/*---------------------------------------------------------------------- + * Codepages mapping + */ +cmaps : cmap + | cmaps cmap + | error { xyyerror(err_ident); } + ; + +cmap : clan '=' tNUMBER ':' tNUMBER { + static const char err_nocp[] = "Codepage %d not builtin; cannot convert"; + if(find_cpxlat($1)) + xyyerror("Codepage translation already defined for language 0x%x", $1); + if($3 && !find_codepage($3)) + xyyerror(err_nocp, $3); + if($5 && !find_codepage($5)) + xyyerror(err_nocp, $5); + add_cpxlat($1, $3, $5); + } + | clan '=' tNUMBER ':' error { xyyerror(err_number); } + | clan '=' tNUMBER error { xyyerror(err_colon); } + | clan '=' error { xyyerror(err_number); } + | clan error { xyyerror(err_assign); } + ; + +clan : tNUMBER { $$ = $1; } + | tTOKEN { + if($1->type != tok_language) + xyyerror("Language name or code expected"); + $$ = $1->token; + } + ; + +/*---------------------------------------------------------------------- + * Message-definition parsing + */ +msg : msgid sevfacsym { test_id($1); } bodies { $$ = complete_msg($4, $1); } + ; + +msgid : tMSGID '=' id { + if($3 & (~0xffff)) + xyyerror("Message ID value out of range (0x%08x > 0xffff)", $3); + $$ = $3; + } + | tMSGID error { xyyerror(err_assign); } + ; + +id : /* Empty */ { $$ = ++last_id; } + | tNUMBER { $$ = last_id = $1; } + | '+' tNUMBER { $$ = last_id += $2; } + | '+' error { xyyerror(err_number); } + ; + +sevfacsym: /* Empty */ { have_sev = have_fac = have_sym = 0; } + | sevfacsym sev { if(have_sev) xyyerror("Severity already defined"); have_sev = 1; } + | sevfacsym fac { if(have_fac) xyyerror("Facility already defined"); have_fac = 1; } + | sevfacsym sym { if(have_sym) xyyerror("Symbolname already defined"); have_sym = 1; } + ; + +sym : tSYMNAME '=' tIDENT { last_sym = $3; } + | tSYMNAME '=' error { xyyerror(err_ident); } + | tSYMNAME error { xyyerror(err_assign); } + ; + +sev : tSEVERITY '=' token { + token_t *tok = lookup_token($3->name); + if(!tok) + xyyerror("Undefined severityname"); + if(tok->type != tok_severity) + xyyerror("Identifier is not of class 'severity'"); + last_sev = tok->token; + } + | tSEVERITY '=' error { xyyerror(err_ident); } + | tSEVERITY error { xyyerror(err_assign); } + ; + +fac : tFACILITY '=' token { + token_t *tok = lookup_token($3->name); + if(!tok) + xyyerror("Undefined facilityname"); + if(tok->type != tok_facility) + xyyerror("Identifier is not of class 'facility'"); + last_fac = tok->token; + } + | tFACILITY '=' error { xyyerror(err_ident); } + | tFACILITY error { xyyerror(err_assign); } + ; + +/*---------------------------------------------------------------------- + * Message-text parsing + */ +bodies : body { $$ = add_lanmsg(NULL, $1); } + | bodies body { $$ = add_lanmsg($1, $2); } + | error { xyyerror("'Language=...' (start of message text-definition) expected"); } + ; + +body : lang setline lines tMSGEND { $$ = new_lanmsg(&$1, $3); } + ; + + /* + * The newline is to be able to set the codepage + * to the language based codepage for the next + * message to be parsed. + */ +lang : tLANGUAGE setnl '=' token tNL { + token_t *tok = lookup_token($4->name); + cp_xlat_t *cpx; + if(!tok) + xyyerror("Undefined language"); + if(tok->type != tok_language) + xyyerror("Identifier is not of class 'language'"); + if((cpx = find_cpxlat(tok->token))) + { + set_codepage($$.codepage = cpx->cpin); + } + else if(!tok->codepage) + { + const language_t *lan = find_language(tok->token); + if(!lan) + { + /* Just set default; warning was given while parsing languagenames */ + set_codepage($$.codepage = WMC_DEFAULT_CODEPAGE); + } + else + { + /* The default seems to be to use the DOS codepage... */ + set_codepage($$.codepage = lan->doscp); + } + } + else + set_codepage($$.codepage = tok->codepage); + $$.language = tok->token; + } + | tLANGUAGE setnl '=' token error { xyyerror("Missing newline"); } + | tLANGUAGE setnl '=' error { xyyerror(err_ident); } + | tLANGUAGE error { xyyerror(err_assign); } + ; + +lines : tLINE { $$ = $1; } + | lines tLINE { $$ = merge($1, $2); } + | error { xyyerror(err_msg); } + | lines error { xyyerror(err_msg); } + ; + +/*---------------------------------------------------------------------- + * Helper rules + */ +token : tIDENT { $$ = xmalloc(sizeof(token_t)); $$->name = $1; } + | tTOKEN { $$ = $1; } + ; + +setnl : /* Empty */ { want_nl = 1; } + ; + +setline : /* Empty */ { want_line = 1; } + ; + +setfile : /* Empty */ { want_file = 1; } + ; + +%% + +static WCHAR *merge(WCHAR *s1, WCHAR *s2) +{ + int l1 = unistrlen(s1); + int l2 = unistrlen(s2); + s1 = xrealloc(s1, (l1 + l2 + 1) * sizeof(*s1)); + unistrcpy(s1+l1, s2); + free(s2); + return s1; +} + +static void do_add_token(tok_e type, token_t *tok, const char *code) +{ + token_t *tp = lookup_token(tok->name); + if(tp) + { + if(tok->type != type) + yywarning("Type change in token"); + if(tp != tok) + xyyerror("Overlapping token not the same"); + /* else its already defined and changed */ + if(tok->fixed) + xyyerror("Redefinition of %s", code); + tok->fixed = 1; + } + else + { + add_token(type, tok->name, tok->token, tok->codepage, tok->alias, 1); + free(tok); + } +} + +static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg) +{ + lanmsg_t *lmp = (lanmsg_t *)xmalloc(sizeof(lanmsg_t)); + lmp->lan = lcp->language; + lmp->cp = lcp->codepage; + lmp->msg = msg; + lmp->len = unistrlen(msg) + 1; /* Include termination */ + if(lmp->len > 4096) + yywarning("Message exceptionally long; might be a missing termination"); + return lmp; +} + +static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg) +{ + int i; + if(!msg) + msg = xmalloc(sizeof(msg_t)); + msg->msgs = xrealloc(msg->msgs, (msg->nmsgs+1) * sizeof(*(msg->msgs))); + msg->msgs[msg->nmsgs] = lanmsg; + msg->nmsgs++; + for(i = 0; i < msg->nmsgs-1; i++) + { + if(msg->msgs[i]->lan == lanmsg->lan) + xyyerror("Message for language 0x%x already defined", lanmsg->lan); + } + return msg; +} + +static int sort_lanmsg(const void *p1, const void *p2) +{ + return (*(lanmsg_t **)p1)->lan - (*(lanmsg_t **)p2)->lan; +} + +static msg_t *complete_msg(msg_t *mp, int id) +{ + assert(mp != NULL); + mp->id = id; + if(have_sym) + mp->sym = last_sym; + else + xyyerror("No symbolic name defined for message id %d", id); + mp->sev = last_sev; + mp->fac = last_fac; + qsort(mp->msgs, mp->nmsgs, sizeof(*(mp->msgs)), sort_lanmsg); + mp->realid = id | (last_sev << 30) | (last_fac << 16); + if(custombit) + mp->realid |= 1 << 29; + mp->base = base; + mp->cast = cast; + return mp; +} + +static void add_node(node_e type, void *p) +{ + node_t *ndp = (node_t *)xmalloc(sizeof(node_t)); + ndp->type = type; + ndp->u.all = p; + + if(nodetail) + { + ndp->prev = nodetail; + nodetail->next = ndp; + nodetail = ndp; + } + else + { + nodehead = nodetail = ndp; + } +} + +static void test_id(int id) +{ + node_t *ndp; + for(ndp = nodehead; ndp; ndp = ndp->next) + { + if(ndp->type != nd_msg) + continue; + if(ndp->u.msg->id == id && ndp->u.msg->sev == last_sev && ndp->u.msg->fac == last_fac) + xyyerror("MessageId %d with facility 0x%x and severity 0x%x already defined", id, last_fac, last_sev); + } +} + +static int check_languages(node_t *head) +{ + static char err_missing[] = "Missing definition for language 0x%x; MessageID %d, facility 0x%x, severity 0x%x"; + node_t *ndp; + int nm = 0; + msg_t *msg = NULL; + + for(ndp = head; ndp; ndp = ndp->next) + { + if(ndp->type != nd_msg) + continue; + if(!nm) + { + msg = ndp->u.msg; + } + else + { + int i; + msg_t *m1; + msg_t *m2; + if(ndp->u.msg->nmsgs > msg->nmsgs) + { + m1 = ndp->u.msg; + m2 = msg; + } + else + { + m1 = msg; + m2 = ndp->u.msg; + } + + for(i = 0; i < m1->nmsgs; i++) + { + if(i > m2->nmsgs) + error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev); + else if(m1->msgs[i]->lan < m2->msgs[i]->lan) + error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev); + else if(m1->msgs[i]->lan > m2->msgs[i]->lan) + error(err_missing, m2->msgs[i]->lan, m1->id, m1->fac, m1->sev); + } + } + nm++; + } + return nm; +} + +#define MSGRID(x) ((*(msg_t **)(x))->realid) +static int sort_msg(const void *p1, const void *p2) +{ + return MSGRID(p1) > MSGRID(p2) ? 1 : (MSGRID(p1) == MSGRID(p2) ? 0 : -1); + /* return (*(msg_t **)p1)->realid - (*(msg_t **)p1)->realid; */ +} + +/* + * block_messages() basically transposes the messages + * from ID/language based list to a language/ID + * based list. + */ +static lan_blk_t *block_messages(node_t *head) +{ + lan_blk_t *lbp; + lan_blk_t *lblktail = NULL; + lan_blk_t *lblkhead = NULL; + msg_t **msgtab = NULL; + node_t *ndp; + int nmsg = 0; + int i; + int nl; + int factor = unicodeout ? 2 : 1; + + for(ndp = head; ndp; ndp = ndp->next) + { + if(ndp->type != nd_msg) + continue; + msgtab = xrealloc(msgtab, (nmsg+1) * sizeof(*msgtab)); + msgtab[nmsg++] = ndp->u.msg; + } + + assert(nmsg != 0); + qsort(msgtab, nmsg, sizeof(*msgtab), sort_msg); + + for(nl = 0; nl < msgtab[0]->nmsgs; nl++) /* This should be equal for all after check_languages() */ + { + lbp = xmalloc(sizeof(lan_blk_t)); + + if(!lblktail) + { + lblkhead = lblktail = lbp; + } + else + { + lblktail->next = lbp; + lbp->prev = lblktail; + lblktail = lbp; + } + lbp->nblk = 1; + lbp->blks = xmalloc(sizeof(*lbp->blks)); + lbp->blks[0].idlo = msgtab[0]->realid; + lbp->blks[0].idhi = msgtab[0]->realid; + /* The plus 4 is the entry header; (+3)&~3 is DWORD alignment */ + lbp->blks[0].size = ((factor * msgtab[0]->msgs[nl]->len + 3) & ~3) + 4; + lbp->blks[0].msgs = xmalloc(sizeof(*lbp->blks[0].msgs)); + lbp->blks[0].nmsg = 1; + lbp->blks[0].msgs[0] = msgtab[0]->msgs[nl]; + lbp->lan = msgtab[0]->msgs[nl]->lan; + + for(i = 1; i < nmsg; i++) + { + block_t *blk = &(lbp->blks[lbp->nblk-1]); + if(msgtab[i]->realid == blk->idhi+1) + { + blk->size += ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4; + blk->idhi++; + blk->msgs = xrealloc(blk->msgs, (blk->nmsg+1) * sizeof(*blk->msgs)); + blk->msgs[blk->nmsg++] = msgtab[i]->msgs[nl]; + } + else + { + lbp->nblk++; + lbp->blks = xrealloc(lbp->blks, lbp->nblk * sizeof(*lbp->blks)); + blk = &(lbp->blks[lbp->nblk-1]); + blk->idlo = msgtab[i]->realid; + blk->idhi = msgtab[i]->realid; + blk->size = ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4; + blk->msgs = xmalloc(sizeof(*blk->msgs)); + blk->nmsg = 1; + blk->msgs[0] = msgtab[i]->msgs[nl]; + } + } + } + free(msgtab); + return lblkhead; +} + +static int sc_xlat(const void *p1, const void *p2) +{ + return ((cp_xlat_t *)p1)->lan - ((cp_xlat_t *)p2)->lan; +} + +static void add_cpxlat(int lan, int cpin, int cpout) +{ + cpxlattab = xrealloc(cpxlattab, (ncpxlattab+1) * sizeof(*cpxlattab)); + cpxlattab[ncpxlattab].lan = lan; + cpxlattab[ncpxlattab].cpin = cpin; + cpxlattab[ncpxlattab].cpout = cpout; + ncpxlattab++; + qsort(cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat); +} + +static cp_xlat_t *find_cpxlat(int lan) +{ + cp_xlat_t t; + + if(!cpxlattab) return NULL; + + t.lan = lan; + return (cp_xlat_t *)bsearch(&t, cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat); +} + diff --git a/tools/wmc/misc.c b/tools/wmc/misc.c new file mode 100644 index 0000000..885c69d --- /dev/null +++ b/tools/wmc/misc.c @@ -0,0 +1,77 @@ +#ifdef __unix__ +#include +#include +#include + +typedef unsigned short UINT; +typedef unsigned int DWORD; +typedef const unsigned char* LPCSTR; +typedef wchar_t* LPWSTR; +typedef unsigned char* LPSTR; +typedef const wchar_t* LPCWSTR; +typedef unsigned int* LPBOOL; + +int +stricmp(const char* s1, const char* s2) +{ + return(strcasecmp(s1, s2)); +} + +int +WideCharToMultiByte( + UINT CodePage, + DWORD dwFlags, + LPCWSTR lpWideCharStr, + int cchWideChar, + LPSTR lpMultiByteStr, + int cchMultiByte, + LPCSTR lpDefaultChar, + LPBOOL lpUsedDefaultChar) +{ + unsigned int i = 0; + if (cchWideChar == -1) + { + while(*lpWideCharStr != 0) + { + wctomb(lpMultiByteStr, *lpWideCharStr); + lpMultiByteStr++; + lpWideCharStr++; + i++; + } + } + else + { + while(i < cchWideChar) + { + wctomb(lpMultiByteStr, *lpWideCharStr); + lpMultiByteStr++; + lpWideCharStr++; + i++; + } + } + return(i); +} + +int +MultiByteToWideChar( + UINT CodePage, + DWORD dwFlags, + LPCSTR lpMultiByteStr, + int cchMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar) +{ + int i, j; + + i = j = 0; + while (i < cchMultiByte && lpMultiByteStr[i] != 0) + { + i = i + mbtowc(&lpWideCharStr[j], &lpMultiByteStr[i], + cchMultiByte - i); + j++; + } + lpWideCharStr[j] = 0; + j++; + return(j); +} +#endif diff --git a/tools/wmc/utils.c b/tools/wmc/utils.c new file mode 100644 index 0000000..1725ffd --- /dev/null +++ b/tools/wmc/utils.c @@ -0,0 +1,242 @@ +/* + * Utility routines + * + * Copyright 1998,2000 Bertho A. Stultiens + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "wmctypes.h" +#include "utils.h" +#include "wmc.h" + +#define SUPPRESS_YACC_ERROR_MESSAGE + +static void generic_msg(const char *s, const char *t, va_list ap) +{ + fprintf(stderr, "%s %s: %d, %d: ", t, input_name ? input_name : "stdin", line_number, char_number); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); +} + +/* + * The yyerror routine should not exit because we use the error-token + * to determine the syntactic error in the source. However, YACC + * uses the same routine to print an error just before the error + * token is reduced. + * The extra routine 'xyyerror' is used to exit after giving a real + * message. + */ +int yyerror(const char *s, ...) +{ +#ifndef SUPPRESS_YACC_ERROR_MESSAGE + va_list ap; + va_start(ap, s); + generic_msg(s, "Yacc error", ap); + va_end(ap); +#endif + return 1; +} + +int xyyerror(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Error", ap); + va_end(ap); + exit(1); + return 1; +} + +int yywarning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Warning", ap); + va_end(ap); + return 0; +} + +void internal_error(const char *file, int line, const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "Internal error (please report) %s %d: ", file, line); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(3); +} + +void error(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "Error: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(2); +} + +void warning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "Warning: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +char *dup_basename(const char *name, const char *ext) +{ + int namelen; + int extlen = strlen(ext); + char *base; + char *slash; + + if(!name) + name = "wmc.tab"; + + slash = strrchr(name, '/'); + if (slash) + name = slash + 1; + + namelen = strlen(name); + + /* +4 for later extension and +1 for '\0' */ + base = (char *)xmalloc(namelen +4 +1); + strcpy(base, name); + if(!stricmp(name + namelen-extlen, ext)) + { + base[namelen - extlen] = '\0'; + } + return base; +} + +void *xmalloc(size_t size) +{ + void *res; + + assert(size > 0); + assert(size < 102400); + res = malloc(size); + if(res == NULL) + { + error("Virtual memory exhausted.\n"); + } + /* + * We set it to 0. + * This is *paramount* because we depend on it + * just about everywhere in the rest of the code. + */ + memset(res, 0, size); + return res; +} + + +void *xrealloc(void *p, size_t size) +{ + void *res; + + assert(size > 0); + assert(size < 102400); + res = realloc(p, size); + if(res == NULL) + { + error("Virtual memory exhausted.\n"); + } + return res; +} + +char *xstrdup(const char *str) +{ + char *s; + + assert(str != NULL); + s = (char *)xmalloc(strlen(str)+1); + return strcpy(s, str); +} + +int unistrlen(const WCHAR *s) +{ + int n; + for(n = 0; *s; n++, s++) + ; + return n; +} + +WCHAR *unistrcpy(WCHAR *dst, const WCHAR *src) +{ + WCHAR *t = dst; + while(*src) + *t++ = *src++; + *t = 0; + return dst; +} + +WCHAR *xunistrdup(const WCHAR * str) +{ + WCHAR *s; + + assert(str != NULL); + s = (WCHAR *)xmalloc((unistrlen(str)+1) * sizeof(WCHAR)); + return unistrcpy(s, str); +} + +int unistricmp(const WCHAR *s1, const WCHAR *s2) +{ + int i; + int once = 0; + static char warn[] = "Don't know the uppercase equivalent of non acsii characters;" + "comparison might yield wrong results"; + while(*s1 && *s2) + { + if((*s1 & 0xffff) > 0x7f || (*s2 & 0xffff) > 0x7f) + { + if(!once) + { + once++; + yywarning(warn); + } + i = *s1++ - *s2++; + } + else + i = toupper(*s1++) - toupper(*s2++); + if(i) + return i; + } + + if((*s1 & 0xffff) > 0x7f || (*s2 & 0xffff) > 0x7f) + { + if(!once) + yywarning(warn); + return *s1 - *s2; + } + else + return toupper(*s1) - toupper(*s2); +} + +int unistrcmp(const WCHAR *s1, const WCHAR *s2) +{ + int i; + while(*s1 && *s2) + { + i = *s1++ - *s2++; + if(i) + return i; + } + + return *s1 - *s2; +} + diff --git a/tools/wmc/utils.h b/tools/wmc/utils.h new file mode 100644 index 0000000..0394487 --- /dev/null +++ b/tools/wmc/utils.h @@ -0,0 +1,44 @@ +/* + * Utility routines' prototypes etc. + * + * Copyright 1998,2000 Bertho A. Stultiens (BS) + * + */ + +#ifndef __WMC_UTILS_H +#define __WMC_UTILS_H + +#ifndef __WMC_WMCTYPES_H +#include "wmctypes.h" +#endif + +#include /* size_t */ + +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(const char *str); + +#if 0 +int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2))); +int xyyerror(const char *s, ...) __attribute__((format (printf, 1, 2))); +int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2))); +void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4))); +void error(const char *s, ...) __attribute__((format (printf, 1, 2))); +void warning(const char *s, ...) __attribute__((format (printf, 1, 2))); +#endif +int yyerror(const char *s, ...); +int xyyerror(const char *s, ...); +int yywarning(const char *s, ...); +void internal_error(const char *file, int line, const char *s, ...); +void error(const char *s, ...); +void warning(const char *s, ...); + +char *dup_basename(const char *name, const char *ext); + +WCHAR *xunistrdup(const WCHAR * str); +WCHAR *unistrcpy(WCHAR *dst, const WCHAR *src); +int unistrlen(const WCHAR *s); +int unistricmp(const WCHAR *s1, const WCHAR *s2); +int unistrcmp(const WCHAR *s1, const WCHAR *s2); + +#endif diff --git a/tools/wmc/windows.h b/tools/wmc/windows.h new file mode 100644 index 0000000..0c8a7d4 --- /dev/null +++ b/tools/wmc/windows.h @@ -0,0 +1,35 @@ +#include +typedef wchar_t WCHAR; +typedef unsigned short int WORD; +typedef unsigned int UINT; +typedef unsigned int DWORD; +typedef char CHAR; +typedef CHAR *LPSTR; +typedef WCHAR *LPWSTR; +typedef const CHAR *LPCSTR; +typedef const WCHAR *LPCWSTR; +typedef unsigned int *LPBOOL; + +#ifndef __unix__ +#define STDCALL __attribute__((stdcall)) +#else +#define STDCALL +#endif + +int STDCALL MultiByteToWideChar( + UINT CodePage, + DWORD dwFlags, + LPCSTR lpMultiByteStr, + int cbMultiByte, + LPWSTR lpWideCharStr, + int cchWideChar); + +int STDCALL WideCharToMultiByte( + UINT CodePage, + DWORD dwFlags, + LPCWSTR lpWideCharStr, + int cchWideChar, + LPSTR lpMultiByteStr, + int cbMultiByte, + LPCSTR lpDefaultChar, + LPBOOL lpUsedDefaultChar); diff --git a/tools/wmc/wmc.c b/tools/wmc/wmc.c new file mode 100644 index 0000000..6535d67 --- /dev/null +++ b/tools/wmc/wmc.c @@ -0,0 +1,269 @@ +/* + * Wine Message Compiler main program + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ +#include +#include +#include +#include +#include + +#include "config.h" + +#include "wmc.h" +#include "utils.h" +#include "lang.h" +#include "write.h" + +static char usage[] = + "Usage: wmc [options...] [inputfile.mc]\n" + " -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n" + " (default is n[ative] which equals " +#ifdef WORDS_BIGENDIAN + "big" +#else + "little" +#endif + "-endian)\n" + " -c Set 'custom-bit' in values\n" + " -d Use decimal values in output\n" + " -D Set debug flag\n" + " -h This message\n" + " -H file Write headerfile to file (default is inputfile.h)\n" + " -i Inline messagetable(s)\n" + " -o file Output to file (default is inputfile.rc)\n" + " -u Inputfile is in unicode\n" + " -U Output unicode messagetable(s)\n" + " -v Show supported codepages and languages\n" + " -V Print version end exit\n" + " -W Enable pedantic warnings\n" + "Input is taken from stdin if no inputfile is specified.\n" + "Byteorder of unicode input is based upon the first couple of\n" + "bytes read, which should be 0x0000..0x00ff.\n" + ; + +static char version_string[] = + "Wine Message Compiler Version " WMC_FULLVERSION "\n" + "Copyright 2000 Bertho A. Stultiens\n" + ; + +/* + * The output byte-order of resources (set with -B) + */ +int byteorder = WMC_BO_NATIVE; + +/* + * Custom bit (bit 29) in output values must be set (-c option) + */ +int custombit = 0; + +/* + * Output decimal values (-d option) + */ +int decimal = 0; + +/* + * Enable pedantic warnings; check arg references (-W option) + */ +int pedantic = 0; + +/* + * Unicode input (-u option) + */ +int unicodein = 0; + +/* + * Unicode output (-U option) + */ +int unicodeout = 0; + +/* + * Inline the messagetables (don't write *.bin files; -i option) + */ +int rcinline = 0; + +/* + * Debugging flag (-D option) + */ +int dodebug = 0; + +char *output_name = NULL; /* The name given by the -o option */ +char *input_name = NULL; /* The name given on the command-line */ +char *header_name = NULL; /* The name given by the -H option */ + +int line_number = 1; /* The current line */ +int char_number = 1; /* The current char pos within the line */ + +char *cmdline; /* The entire commandline */ +time_t now; /* The time of start of wmc */ + +int getopt (int argc, char *const *argv, const char *optstring); +static void segvhandler(int sig); + +int main(int argc,char *argv[]) +{ + extern char* optarg; + extern int optind; + int optc; + int lose = 0; + int ret; + int i; + int cmdlen; + + signal(SIGSEGV, segvhandler); + + now = time(NULL); + + /* First rebuild the commandline to put in destination */ + /* Could be done through env[], but not all OS-es support it */ + cmdlen = 4; /* for "wmc " */ + for(i = 1; i < argc; i++) + cmdlen += strlen(argv[i]) + 1; + cmdline = (char *)xmalloc(cmdlen); + strcpy(cmdline, "wmc "); + for(i = 1; i < argc; i++) + { + strcat(cmdline, argv[i]); + if(i < argc-1) + strcat(cmdline, " "); + } + + while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF) + { + switch(optc) + { + case 'B': + switch(optarg[0]) + { + case 'n': + case 'N': + byteorder = WMC_BO_NATIVE; + break; + case 'l': + case 'L': + byteorder = WMC_BO_LITTLE; + break; + case 'b': + case 'B': + byteorder = WMC_BO_BIG; + break; + default: + fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n"); + lose++; + } + break; + case 'c': + custombit = 1; + break; + case 'd': + decimal = 1; + break; + case 'D': + dodebug = 1; + break; + case 'h': + printf("%s", usage); + exit(0); + /* No return */ + case 'H': + header_name = xstrdup(optarg); + break; + case 'i': + rcinline = 1; + break; + case 'o': + output_name = xstrdup(optarg); + break; + case 'u': + unicodein = 1; + break; + case 'U': + unicodeout = 1; + break; + case 'v': + show_languages(); + show_codepages(); + exit(0); + /* No return */ + case 'V': + printf(version_string); + exit(0); + /* No return */ + case 'W': + pedantic = 1; + break; + default: + lose++; + break; + } + } + + if(lose) + { + fprintf(stderr, "%s", usage); + return 1; + } + + yydebug = dodebug; + if(dodebug) + { + setbuf(stdout, 0); + setbuf(stderr, 0); + } + + /* Check for input file on command-line */ + if(optind < argc) + { + input_name = argv[optind]; + } + + /* Generate appropriate outfile names */ + if(!output_name) + { + output_name = dup_basename(input_name, ".mc"); + strcat(output_name, ".rc"); + } + + if(!header_name) + { + header_name = dup_basename(input_name, ".mc"); + strcat(header_name, ".h"); + } + + if(input_name) + { + if(!(yyin = fopen(input_name, "rb"))) + error("Could not open %s for input\n", input_name); + } + else + yyin = stdin; + + ret = yyparse(); + + if(input_name) + fclose(yyin); + + if(ret) + { + /* Error during parse */ + exit(1); + } + + write_h_file(header_name); + write_rc_file(output_name); + if(!rcinline) + write_bin_files(); + + return 0; +} + +static void segvhandler(int sig) +{ + fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number); + fflush(stdout); + fflush(stderr); + abort(); +} + diff --git a/tools/wmc/wmc.h b/tools/wmc/wmc.h new file mode 100644 index 0000000..9ac5ad6 --- /dev/null +++ b/tools/wmc/wmc.h @@ -0,0 +1,76 @@ +/* + * Main definitions and externals + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ + +#ifndef __WMC_WMC_H +#define __WMC_WMC_H + +#ifndef __WMC_WMCTYPES_H +#include "wmctypes.h" +#endif + +#include /* For time_t */ + +#define WMC_MAJOR_VERSION 1 +#define WMC_MINOR_VERSION 0 +#define WMC_MICRO_VERSION 0 +#define WMC_RELEASEDATE "(12-Jun-2000)" + +#define WMC_STRINGIZE(a) #a +#define WMC_VERSIONIZE(a,b,c) WMC_STRINGIZE(a) "." WMC_STRINGIZE(b) "." WMC_STRINGIZE(c) +#define WMC_VERSION WMC_VERSIONIZE(WMC_MAJOR_VERSION, WMC_MINOR_VERSION, WMC_MICRO_VERSION) +#define WMC_FULLVERSION WMC_VERSION " " WMC_RELEASEDATE + +/* + * The default codepage setting is only to + * read and convert input which is non-message + * text. It doesn't really matter that much because + * all codepages map 0x00-0x7f to 0x0000-0x007f from + * char to unicode and all non-message text should + * be plain ASCII. + * However, we do implement iso-8859-1 for 1-to-1 + * mapping for all other chars, so this is very close + * to what we really want. + */ +#define WMC_DEFAULT_CODEPAGE 28591 + +extern int pedantic; +extern int leave_case; +extern int byteorder; +extern int decimal; +extern int custombit; +extern int unicodein; +extern int unicodeout; +extern int rcinline; + +extern char *output_name; +extern char *input_name; +extern char *header_name; +extern char *cmdline; +extern time_t now; + +extern int line_number; +extern int char_number; + +int yyparse(void); +extern int yydebug; +extern int want_nl; +extern int want_line; +extern int want_file; +extern node_t *nodehead; +extern lan_blk_t *lanblockhead; + +int yylex(void); +FILE *yyin; +void set_codepage(int cp); + +void add_token(tok_e type, const WCHAR *name, int tok, int cp, const WCHAR *alias, int fix); +token_t *lookup_token(const WCHAR *s); +void get_tokentable(token_t **tab, int *len); + +#define _alloca alloca + +#endif diff --git a/tools/wmc/wmc.man b/tools/wmc/wmc.man new file mode 100644 index 0000000..ec5cdcb --- /dev/null +++ b/tools/wmc/wmc.man @@ -0,0 +1,103 @@ +.TH WMC 1 "June 12, 2000" "Version 1.0.0" "Wine Message Compiler" +.SH NAME +wrc \- Wine Message Compiler +.SH SYNOPSIS +.BI "wmc " "[options] " "[inputfile]" +.SH DESCRIPTION +.B wmc +compiles messages from +.B inputfile +into FormatMessage[AW] compatible format encapsulated in a resourcescript +format. +.B wmc +outputs the data either in a standard \fB.bin\fR formatted binary +file, or can generated inline resource data. +.PP +.B wmc +takes only one \fBinputfile\fR as argument (see \fBBUGS\fR). The +\fBinputfile\fR normally has extension \fB.mc\fR. The messages are read from +standard input if no inputfile is given. If the outputfile is not specified +with \fI-o\fR, then \fBwmc\fR will write the output to \fBinputfile.{rc,h}\fR. +The outputfile is named \fBwmc.tab.{rc,h}\fR if no inputfile was given. +.SH OPTIONS +.TP +.I \-B x +Set output byte-order x={n[ative], l[ittle], b[ig]}. Default is n[ative]. +.TP +.I \-c +Set 'custom-bit' in message-code values. +.TP +.I \-d +NON-FUNCTIONAL; Use decimal values in output +.TP +.I \-D +Set debug flag. This results is a parser trace and a lot of extra messages. +.TP +.I \-h +Print an informative usage message. +.TP +.I \-H file +Write headerfile to \fIfile\fR. Default is \fIinputfile.h\fR. +.TP +.I \-i +Inline messagetable(s). This option skips the generation of all \fI.bin\fR files +and writes all output into the \fI.rc\fR file. This encoding is parsable with +wrc(1). +.TP +.I \-o file +Output to \fIfile\fR. Default is \fIinputfile.rc\fR. +.TP +.I \-u +Assume that the inputfile is in unicode. +.TP +.I \-U +Write resource output in unicode formatted messagetable(s). +.TP +.I \-v +Show all supported codepages and languages. +.TP +.I \-V +Print version end exit. +.TP +.I \-W +Enable pedantic warnings. +.SH EXTENSIONS +The original syntax is extended to support codepages more smoothly. Normally, +codepages are based on the DOS\-codepage from the language setting. The +original syntax only allows the destination codepage to be set. However, this +is not enough for non\-DOS systems which do not use unicode source-files. +.PP +A new keyword \fICodepages\fR is introduced to set both input and output +codepages to anything one wants for each language. The syntax is similar to +the other constructs: +.PP +Codepages '=' '(' language '=' cpin ':' cpout ... ')' +.PP +The \fIlanguage\fR is the numerical language\-ID or the alias set with +LanguageNames. The input\-codepage \fIcpin\fR and output\-codepage +\fIcpout\fR are the numerical codepage\-IDs. There can be multiple mapping +within the definition and the definition may occur more than once. +.SH AUTHORS +.B wmc +was written by Bertho A. Stultiens. +.SH BUGS +The message compiler should be able to have multiple inputfiles and combine +them into one outputfile. This would enable the splitting of languages into +separate files. +.PP +Unicode detection of the input is suboptimal, to say the least. It should +recognize byte\-order\-marks (BOM) and decide what to do. +.PP +Decimal output is completely lacking. Don't know whether it should be +implemented because it is a, well, non-informative format change. It is +recognized on the commandline for some form of compatibility. +.SH AVAILABILITY +.B wmc +is part of the wine distribution, which is available through +WineHQ, the +.B wine +development headquarters, at +.I http://www.winehq.com/. +.SH "SEE ALSO" +.BR wine (1), +.BR wrc (1) diff --git a/tools/wmc/wmctypes.h b/tools/wmc/wmctypes.h new file mode 100644 index 0000000..6ce6956 --- /dev/null +++ b/tools/wmc/wmctypes.h @@ -0,0 +1,106 @@ +/* + * Main definitions and externals + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ + +#ifndef __WMC_WMCTYPES_H +#define __WMC_WMCTYPES_H + + +/* Byteordering defines */ +#define WMC_BO_NATIVE 0x00 +#define WMC_BO_LITTLE 0x01 +#define WMC_BO_BIG 0x02 + +#define WMC_LOBYTE(w) ((WORD)(w) & 0xff) +#define WMC_HIBYTE(w) (((WORD)(w) >> 8) & 0xff) +#define WMC_LOWORD(d) ((DWORD)(d) & 0xffff) +#define WMC_HIWORD(d) (((DWORD)(d) >> 16) & 0xffff) +#define BYTESWAP_WORD(w) ((WORD)(((WORD)WMC_LOBYTE(w) << 8) + (WORD)WMC_HIBYTE(w))) +#define BYTESWAP_DWORD(d) ((DWORD)(((DWORD)BYTESWAP_WORD(WMC_LOWORD(d)) << 16) + ((DWORD)BYTESWAP_WORD(WMC_HIWORD(d))))) + +/* + * Tokenizer types + */ +typedef enum tok_enum { + tok_null = 0, + tok_keyword, + tok_severity, + tok_facility, + tok_language +} tok_e; + +typedef struct token { + tok_e type; + const WCHAR *name; /* Parsed name of token */ + int token; /* Tokenvalue or language code */ + int codepage; + const WCHAR *alias; /* Alias or filename */ + int fixed; /* Cleared if token may change */ +} token_t; + +typedef struct lan_cp { + int language; + int codepage; +} lan_cp_t; + +typedef struct cp_xlat { + int lan; + int cpin; + int cpout; +} cp_xlat_t; + +typedef struct lanmsg { + int lan; /* Language code of message */ + int cp; /* Codepage of message */ + WCHAR *msg; /* Message text */ + int len; /* Message length including trailing '\0' */ +} lanmsg_t; + +typedef struct msg { + int id; /* Message ID */ + unsigned realid; /* Combined message ID */ + WCHAR *sym; /* Symbolic name */ + int sev; /* Severity code */ + int fac; /* Facility code */ + lanmsg_t **msgs; /* Array message texts */ + int nmsgs; /* Number of message texts in array */ + int base; /* Base of number to print */ + WCHAR *cast; /* Typecase to use */ +} msg_t; + +typedef enum { + nd_msg, + nd_comment +} node_e; + +typedef struct node { + struct node *next; + struct node *prev; + node_e type; + union { + void *all; + WCHAR *comment; + msg_t *msg; + } u; +} node_t; + +typedef struct block { + unsigned idlo; /* Lowest ID in this set */ + unsigned idhi; /* Highest ID in this set */ + int size; /* Size of this set */ + lanmsg_t **msgs; /* Array of messages in this set */ + int nmsg; /* Number of array entries */ +} block_t; + +typedef struct lan_blk { + struct lan_blk *next; /* Linkage for languages */ + struct lan_blk *prev; + int lan; /* The language of this block */ + block_t *blks; /* Array of blocks for this language */ + int nblk; /* Nr of blocks in array */ +} lan_blk_t; + +#endif diff --git a/tools/wmc/write.c b/tools/wmc/write.c new file mode 100644 index 0000000..1dc7c1d --- /dev/null +++ b/tools/wmc/write.c @@ -0,0 +1,631 @@ +/* + * Wine Message Compiler output generation + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ + +#include +#include +#include +#include +#include +#include + +#include "wmc.h" +#include "utils.h" +#include "lang.h" +#include "write.h" + +/* + * The binary resource layout is as follows: + * + * +===============+ + * Header | NBlocks | + * +===============+ + * Block 0 | Low ID | + * +---------------+ + * | High ID | + * +---------------+ + * | Offset |---+ + * +===============+ | + * Block 1 | Low ID | | + * +---------------+ | + * | High ID | | + * +---------------+ | + * | Offset |------+ + * +===============+ | | + * | | | | + * ... ... | | + * | | | | + * +===============+ <-+ | + * B0 LoID | Len | Flags | | + * +---+---+---+---+ | + * | b | l | a | b | | + * +---+---+---+---+ | + * | l | a | \0| \0| | + * +===============+ | + * | | | + * ... ... | + * | | | + * +===============+ | + * B0 HiID | Len | Flags | | + * +---+---+---+---+ | + * | M | o | r | e | | + * +---+---+---+---+ | + * | b | l | a | \0| | + * +===============+ <----+ + * B1 LoID | Len | Flags | + * +---+---+---+---+ + * | J | u | n | k | + * +---+---+---+---+ + * | \0| \0| \0| \0| + * +===============+ + * | | + * ... ... + * | | + * +===============+ + * + * All Fields are aligned on their natural boundaries. The length + * field (Len) covers both the length of the string and the header + * fields (Len and Flags). Strings are '\0' terminated. Flags is 0 + * for normal character strings and 1 for unicode strings. + */ + +static char str_header[] = + "/* This file is generated with wmc version " WMC_FULLVERSION ". Do not edit! */\n" + "/* Source : %s */\n" + "/* Cmdline: %s */\n" + "/* Date : %s */\n" + "\n" + ; + +static char *dup_u2c(int cp, const WCHAR *uc) +{ + int len = unistrlen(uc); + char *cptr = xmalloc(len+1); +// const union cptable *cpdef = find_codepage(cp); +// if(!cpdef) +// internal_error(__FILE__, __LINE__, "Codepage %d not found (vanished?)", cp); +// if((len = cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, cptr, len+1, NULL, NULL)) < 0) + if((len = WideCharToMultiByte(cp, 0, uc, unistrlen(uc)+1, cptr, len+1, NULL, NULL)) < 0) + internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", len); + return cptr; +} + +static void killnl(char *s, int ddd) +{ + char *tmp; + tmp = strstr(s, "\r\n"); + if(tmp) + { + if(ddd && tmp - s > 3) + { + tmp[0] = tmp[1] = tmp[2] = '.'; + tmp[3] = '\0'; + } + else + *tmp = '\0'; + } + tmp = strchr(s, '\n'); + if(tmp) + { + if(ddd && tmp - s > 3) + { + tmp[0] = tmp[1] = tmp[2] = '.'; + tmp[3] = '\0'; + } + else + *tmp = '\0'; + } +} + +static int killcomment(char *s) +{ + char *tmp = s; + int b = 0; + while((tmp = strstr(tmp, "/*"))) + { + tmp[1] = 'x'; + b++; + } + tmp = s; + while((tmp = strstr(tmp, "*/"))) + { + tmp[0] = 'x'; + b++; + } + return b; +} + +void write_h_file(const char *fname) +{ + node_t *ndp; + char *cptr; + char *cast; + FILE *fp; + token_t *ttab; + int ntab; + int i; + int once = 0; + int idx_en = 0; + + fp = fopen(fname, "w"); + if(!fp) + { + perror(fname); + exit(1); + } + cptr = ctime(&now); + killnl(cptr, 0); + fprintf(fp, str_header, input_name ? input_name : "", cmdline, cptr); + fprintf(fp, "#ifndef __WMCGENERATED_%08lx_H\n", now); + fprintf(fp, "#define __WMCGENERATED_%08lx_H\n", now); + fprintf(fp, "\n"); + + /* Write severity and facility aliases */ + get_tokentable(&ttab, &ntab); + fprintf(fp, "/* Severity codes */\n"); + for(i = 0; i < ntab; i++) + { + if(ttab[i].type == tok_severity && ttab[i].alias) + { + cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias); + fprintf(fp, "#define %s\t0x%x\n", cptr, ttab[i].token); + free(cptr); + } + } + fprintf(fp, "\n"); + + fprintf(fp, "/* Facility codes */\n"); + for(i = 0; i < ntab; i++) + { + if(ttab[i].type == tok_facility && ttab[i].alias) + { + cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias); + fprintf(fp, "#define %s\t0x%x\n", cptr, ttab[i].token); + free(cptr); + } + } + fprintf(fp, "\n"); + + /* Write the message codes */ + fprintf(fp, "/* Message definitions */\n"); + for(ndp = nodehead; ndp; ndp = ndp->next) + { + switch(ndp->type) + { + case nd_comment: + cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.comment+1); + killnl(cptr, 0); + killcomment(cptr); + if(*cptr) + fprintf(fp, "/* %s */\n", cptr); + else + fprintf(fp, "\n"); + free(cptr); + break; + case nd_msg: + if(!once) + { + /* + * Search for an english text. + * If not found, then use the first in the list + */ + once++; + for(i = 0; i < ndp->u.msg->nmsgs; i++) + { + if(ndp->u.msg->msgs[i]->lan == 0x409) + { + idx_en = i; + break; + } + } + fprintf(fp, "\n"); + } + fprintf(fp, "/* MessageId : 0x%08x */\n", ndp->u.msg->realid); + cptr = dup_u2c(ndp->u.msg->msgs[idx_en]->cp, ndp->u.msg->msgs[idx_en]->msg); + killnl(cptr, 0); + killcomment(cptr); + fprintf(fp, "/* Approx. msg: %s */\n", cptr); + free(cptr); + cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.msg->sym); + if(ndp->u.msg->cast) + cast = dup_u2c(WMC_DEFAULT_CODEPAGE, ndp->u.msg->cast); + else + cast = NULL; + switch(ndp->u.msg->base) + { + case 8: + if(cast) + fprintf(fp, "#define %s\t((%s)0%oL)\n\n", cptr, cast, ndp->u.msg->realid); + else + fprintf(fp, "#define %s\t0%oL\n\n", cptr, ndp->u.msg->realid); + break; + case 10: + if(cast) + fprintf(fp, "#define %s\t((%s)%dL)\n\n", cptr, cast, ndp->u.msg->realid); + else + fprintf(fp, "#define %s\t%dL\n\n", cptr, ndp->u.msg->realid); + break; + case 16: + if(cast) + fprintf(fp, "#define %s\t((%s)0x%08xL)\n\n", cptr, cast, ndp->u.msg->realid); + else + fprintf(fp, "#define %s\t0x%08xL\n\n", cptr, ndp->u.msg->realid); + break; + default: + internal_error(__FILE__, __LINE__, "Invalid base for number print"); + } + free(cptr); + if(cast) + free(cast); + break; + default: + internal_error(__FILE__, __LINE__, "Invalid node type %d", ndp->type); + } + } + fprintf(fp, "\n#endif\n"); + fclose(fp); +} + +static void write_rcbin(FILE *fp) +{ + lan_blk_t *lbp; + token_t *ttab; + int ntab; + int i; + + get_tokentable(&ttab, &ntab); + + for(lbp = lanblockhead; lbp; lbp = lbp->next) + { + char *cptr = NULL; + fprintf(fp, "LANGUAGE 0x%x, 0x%x\n", lbp->lan & 0x3ff, lbp->lan >> 10); + for(i = 0; i < ntab; i++) + { + if(ttab[i].type == tok_language && ttab[i].token == lbp->lan) + { + if(ttab[i].alias) + cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias); + break; + } + } + if(!cptr) + internal_error(__FILE__, __LINE__, "Filename vanished for language 0x%0x", lbp->lan); + fprintf(fp, "1 MESSAGETABLE \"%s.bin\"\n", cptr); + free(cptr); + } +} + +static char *make_string(WCHAR *uc, int len, int codepage) +{ + char *str = xmalloc(7*len + 1); + char *cptr = str; + int i; + int b; + + if(!codepage) + { + *cptr++ = ' '; + *cptr++ = 'L'; + *cptr++ = '"'; + for(i = b = 0; i < len; i++, uc++) + { + int n; + if(*uc < 0x100) + { + if(isprint(*uc)) + { + *cptr++ = (char)*uc; + b++; + } + else + { + switch(*uc) + { + case '\a': *cptr++ = '\\'; *cptr++ = 'a'; b += 2; break; + case '\b': *cptr++ = '\\'; *cptr++ = 'b'; b += 2; break; + case '\f': *cptr++ = '\\'; *cptr++ = 'f'; b += 2; break; + case '\n': *cptr++ = '\\'; *cptr++ = 'n'; b += 2; break; + case '\r': *cptr++ = '\\'; *cptr++ = 'r'; b += 2; break; + case '\t': *cptr++ = '\\'; *cptr++ = 't'; b += 2; break; + case '\v': *cptr++ = '\\'; *cptr++ = 'v'; b += 2; break; + case '\\': *cptr++ = '\\'; *cptr++ = '\\'; b += 2; break; + case '"': *cptr++ = '\\'; *cptr++ = '"'; b += 2; break; + default: + n = sprintf(cptr, "\\x%04x", *uc & 0xffff); + cptr += n; + b += n; + } + } + } + else + { + n = sprintf(cptr, "\\x%04x", *uc & 0xffff); + cptr += n; + b += n; + } + if(i < len-1 && b >= 72) + { + *cptr++ = '"'; + *cptr++ = ','; + *cptr++ = '\n'; + *cptr++ = ' '; + *cptr++ = 'L'; + *cptr++ = '"'; + b = 0; + } + } + len = (len + 3) & ~3; + for(; i < len; i++) + { + *cptr++ = '\\'; + *cptr++ = 'x'; + *cptr++ = '0'; + *cptr++ = '0'; + *cptr++ = '0'; + *cptr++ = '0'; + } + *cptr++ = '"'; + *cptr = '\0'; + } + else + { + char *tmp = xmalloc(2*len+1); + char *cc = tmp; +// const union cptable *cpdef = find_codepage(codepage); + +// assert(cpdef != NULL); +// if((i = cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0) + if((i = WideCharToMultiByte(codepage, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0) + internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", i); + *cptr++ = ' '; + *cptr++ = '"'; + for(i = b = 0; i < len; i++, cc++) + { + int n; + if(isprint(*cc)) + { + *cptr++ = *cc; + b++; + } + else + { + switch(*cc) + { + case '\a': *cptr++ = '\\'; *cptr++ = 'a'; b += 2; break; + case '\b': *cptr++ = '\\'; *cptr++ = 'b'; b += 2; break; + case '\f': *cptr++ = '\\'; *cptr++ = 'f'; b += 2; break; + case '\n': *cptr++ = '\\'; *cptr++ = 'n'; b += 2; break; + case '\r': *cptr++ = '\\'; *cptr++ = 'r'; b += 2; break; + case '\t': *cptr++ = '\\'; *cptr++ = 't'; b += 2; break; + case '\v': *cptr++ = '\\'; *cptr++ = 'v'; b += 2; break; + case '\\': *cptr++ = '\\'; *cptr++ = '\\'; b += 2; break; + case '"': *cptr++ = '\\'; *cptr++ = '"'; b += 2; break; + default: + n = sprintf(cptr, "\\x%02x", *cc & 0xff); + cptr += n; + b += n; + } + } + if(i < len-1 && b >= 72) + { + *cptr++ = '"'; + *cptr++ = ','; + *cptr++ = '\n'; + *cptr++ = ' '; + *cptr++ = '"'; + b = 0; + } + } + len = (len + 3) & ~3; + for(; i < len; i++) + { + *cptr++ = '\\'; + *cptr++ = 'x'; + *cptr++ = '0'; + *cptr++ = '0'; + } + *cptr++ = '"'; + *cptr = '\0'; + free(tmp); + } + return str; +} + + +static char *make_bin_string(WCHAR *uc, int len, int *retlen, int codepage) +{ + char *str = xmalloc(7 * len + 1); + int i; + int b; + + if(!codepage) + { + WCHAR *cptr = (WCHAR*)str; + + for(i = b = 0; i < len; i++, uc++) + { + *cptr++ = *uc; + } + len = (len + 1) & ~1; + for(; i < len; i++) + { + *cptr++ = 0; + } + *retlen = len * 2; + } + else + { + char *tmp = xmalloc(2*len+1); + char *cc = tmp; + char *cptr = str; +// const union cptable *cpdef = find_codepage(codepage); + +// assert(cpdef != NULL); +// if((i = cp_wcstombs(cpdef, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0) + if((i = WideCharToMultiByte(codepage, 0, uc, unistrlen(uc)+1, tmp, 2*len+1, NULL, NULL)) < 0) + internal_error(__FILE__, __LINE__, "Buffer overflow? code %d.", i); + for(i = b = 0; i < len; i++, cc++) + { + *cptr++ = *cc; + b++; + } + len = (len + 3) & ~3; + for(; i < len; i++) + { + *cptr++ = 0; + } + free(tmp); + *retlen = len; + } + return str; +} + +static void write_rcinline(FILE *fp) +{ + lan_blk_t *lbp; + int i; + int j; + + for(lbp = lanblockhead; lbp; lbp = lbp->next) + { + unsigned offs = 4 * (lbp->nblk * 3 + 1); + fprintf(fp, "\n1 MESSAGETABLE\n"); + fprintf(fp, "LANGUAGE 0x%x, 0x%x\n", lbp->lan & 0x3ff, lbp->lan >> 10); + fprintf(fp, "{\n"); + fprintf(fp, " /* NBlocks */ 0x%08xL,\n", lbp->nblk); + for(i = 0; i < lbp->nblk; i++) + { + fprintf(fp, " /* Lo,Hi,Offs */ 0x%08xL, 0x%08xL, 0x%08xL,\n", + lbp->blks[i].idlo, + lbp->blks[i].idhi, + offs); + offs += lbp->blks[i].size; + } + for(i = 0; i < lbp->nblk; i++) + { + block_t *blk = &lbp->blks[i]; + for(j = 0; j < blk->nmsg; j++) + { + char *cptr; + int l = blk->msgs[j]->len; + char *comma = j == blk->nmsg-1 && i == lbp->nblk-1 ? "" : ","; + cptr = make_string(blk->msgs[j]->msg, l, unicodeout ? 0 : blk->msgs[j]->cp); + fprintf(fp, "\n /* Msg 0x%08x */ 0x%04x, 0x000%c,\n", + blk->idlo + j, + (unicodeout ? (l*2+3)&~3 : (l+3)&~3)+4, + unicodeout ? '1' : '0'); + fprintf(fp, "%s%s\n", cptr, comma); + free(cptr); + } + } + fprintf(fp, "}\n"); + } +} + +void write_rc_file(const char *fname) +{ + FILE *fp; + char *cptr; + + fp = fopen(fname, "w"); + if(!fp) + { + perror(fname); + exit(1); + } + cptr = ctime(&now); + killnl(cptr, 0); + fprintf(fp, str_header, input_name ? input_name : "", cmdline, cptr); + + if(rcinline) + write_rcinline(fp); + else + write_rcbin(fp); + fclose(fp); +} + +void write_bin_files(void) +{ + lan_blk_t *lbp; + token_t *ttab; + int ntab; + int i; + int j; + char fname[16]; + FILE *fp; + + get_tokentable(&ttab, &ntab); + + for (lbp = lanblockhead; lbp; lbp = lbp->next) + { + unsigned offs = 4 * (lbp->nblk * 3 + 1); + + char *cptr = NULL; + for(i = 0; i < ntab; i++) + { + if (ttab[i].type == tok_language && ttab[i].token == lbp->lan) + { + if (ttab[i].alias) + cptr = dup_u2c(WMC_DEFAULT_CODEPAGE, ttab[i].alias); + break; + } + } + + if (!cptr) + internal_error(__FILE__, __LINE__, "Filename vanished for language 0x%0x", lbp->lan); + sprintf(fname, "%s.bin", cptr); + free(cptr); + + fp = fopen(fname, "wb"); + if (!fp) + { + perror(fname); + exit(1); + } + + /* NBlocks */ + fwrite(&lbp->nblk, sizeof(unsigned long), 1, fp); + for(i = 0; i < lbp->nblk; i++) + { + /* Lo */ + fwrite(&lbp->blks[i].idlo, sizeof(unsigned long), 1, fp); + /* Hi */ + fwrite(&lbp->blks[i].idhi, sizeof(unsigned long), 1, fp); + /* Offs */ + fwrite(&offs, sizeof(unsigned long), 1, fp); + offs += lbp->blks[i].size; + } + + for (i = 0; i < lbp->nblk; i++) + { + block_t *blk = &lbp->blks[i]; + for (j = 0; j < blk->nmsg; j++) + { + char *cptr; + int l = blk->msgs[j]->len; + int retlen = 0; + + unsigned short length = (unicodeout ? (l*2+3)&~3 : (l+3)&~3)+4; + unsigned short flags = unicodeout ? 1 : 0; + + /* Lo */ + fwrite(&length, sizeof(unsigned short), 1, fp); + /* Hi */ + fwrite(&flags, sizeof(unsigned short), 1, fp); + + /* message text */ + cptr = make_bin_string(blk->msgs[j]->msg, l, &retlen, unicodeout ? 0 : blk->msgs[j]->cp); + fwrite(cptr, retlen, 1, fp); + + free(cptr); + } + } + + fclose(fp); + } +} + +/* EOF */ diff --git a/tools/wmc/write.h b/tools/wmc/write.h new file mode 100644 index 0000000..2d627d6 --- /dev/null +++ b/tools/wmc/write.h @@ -0,0 +1,14 @@ +/* + * Wine Message Compiler output generation + * + * Copyright 2000 Bertho A. Stultiens (BS) + * + */ +#ifndef __WMC_WRITE_H +#define __WMC_WRITE_H + +void write_h_file(const char *fname); +void write_rc_file(const char *fname); +void write_bin_files(void); + +#endif diff --git a/tools/wmc/y_tab.c b/tools/wmc/y_tab.c new file mode 100644 index 0000000..fea2c2d --- /dev/null +++ b/tools/wmc/y_tab.c @@ -0,0 +1,1774 @@ + +/* A Bison parser, made from ./mcy.y + by GNU Bison version 1.25 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define tSEVNAMES 258 +#define tFACNAMES 259 +#define tLANNAMES 260 +#define tBASE 261 +#define tCODEPAGE 262 +#define tTYPEDEF 263 +#define tNL 264 +#define tSYMNAME 265 +#define tMSGEND 266 +#define tSEVERITY 267 +#define tFACILITY 268 +#define tLANGUAGE 269 +#define tMSGID 270 +#define tIDENT 271 +#define tLINE 272 +#define tFILE 273 +#define tCOMMENT 274 +#define tNUMBER 275 +#define tTOKEN 276 + +#line 23 "./mcy.y" + + +#include +#include +#include +#include + +#include "config.h" + +#include "utils.h" +#include "wmc.h" +#include "lang.h" + +static const char err_syntax[] = "Syntax error"; +static const char err_number[] = "Number expected"; +static const char err_ident[] = "Identifier expected"; +static const char err_assign[] = "'=' expected"; +static const char err_popen[] = "'(' expected"; +static const char err_pclose[] = "')' expected"; +static const char err_colon[] = "':' expected"; +static const char err_msg[] = "Message expected"; + +/* Scanner switches */ +int want_nl = 0; /* Request next newlinw */ +int want_line = 0; /* Request next complete line */ +int want_file = 0; /* Request next ident as filename */ + +node_t *nodehead = NULL; /* The list of all parsed elements */ +static node_t *nodetail = NULL; +lan_blk_t *lanblockhead; /* List of parsed elements transposed */ + +static int base = 16; /* Current printout base to use (8, 10 or 16) */ +static WCHAR *cast = NULL; /* Current typecast to use */ + +static int last_id = 0; /* The last message ID parsed */ +static int last_sev = 0; /* Last severity code parsed */ +static int last_fac = 0; /* Last facility code parsed */ +static WCHAR *last_sym = NULL;/* Last alias symbol parsed */ +static int have_sev; /* Set if severity parsed for current message */ +static int have_fac; /* Set if facility parsed for current message */ +static int have_sym; /* Set is symbol parsed for current message */ + +static cp_xlat_t *cpxlattab = NULL; /* Codepage translation table */ +static int ncpxlattab = 0; + +/* Prototypes */ +static WCHAR *merge(WCHAR *s1, WCHAR *s2); +static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg); +static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg); +static msg_t *complete_msg(msg_t *msg, int id); +static void add_node(node_e type, void *p); +static void do_add_token(tok_e type, token_t *tok, const char *code); +static void test_id(int id); +static int check_languages(node_t *head); +static lan_blk_t *block_messages(node_t *head); +static void add_cpxlat(int lan, int cpin, int cpout); +static cp_xlat_t *find_cpxlat(int lan); + + +#line 83 "./mcy.y" +typedef union { + WCHAR *str; + unsigned num; + token_t *tok; + lanmsg_t *lmp; + msg_t *msg; + lan_cp_t lcp; +} YYSTYPE; +#ifndef YYDEBUG +#define YYDEBUG 1 +#endif + +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 155 +#define YYFLAG -32768 +#define YYNTBASE 27 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 276 ? yytranslate[x] : 58) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 23, + 24, 2, 26, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 25, 2, 2, + 22, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 4, 7, 9, 11, 13, 15, 21, 27, + 31, 34, 40, 46, 50, 53, 59, 65, 69, 72, + 78, 84, 88, 91, 95, 99, 102, 106, 110, 113, + 115, 118, 120, 125, 129, 132, 134, 137, 139, 144, + 148, 151, 152, 155, 158, 160, 163, 165, 173, 180, + 185, 189, 192, 193, 196, 199, 201, 204, 206, 212, + 218, 223, 227, 230, 232, 234, 235, 240, 244, 247, + 248, 250, 253, 256, 257, 260, 263, 266, 270, 274, + 277, 281, 285, 288, 292, 296, 299, 301, 304, 306, + 311, 317, 323, 328, 331, 333, 336, 338, 341, 343, + 345, 346, 347 +}; + +static const short yyrhs[] = { 28, + 0, 29, 0, 28, 29, 0, 30, 0, 42, 0, + 19, 0, 1, 0, 3, 22, 23, 31, 24, 0, + 3, 22, 23, 31, 1, 0, 3, 22, 1, 0, + 3, 1, 0, 4, 22, 23, 33, 24, 0, 4, + 22, 23, 33, 1, 0, 4, 22, 1, 0, 4, + 1, 0, 5, 22, 23, 36, 24, 0, 5, 22, + 23, 36, 1, 0, 5, 22, 1, 0, 5, 1, + 0, 7, 22, 23, 39, 24, 0, 7, 22, 23, + 39, 1, 0, 7, 22, 1, 0, 7, 1, 0, + 8, 22, 16, 0, 8, 22, 1, 0, 8, 1, + 0, 6, 22, 20, 0, 6, 22, 1, 0, 6, + 1, 0, 32, 0, 31, 32, 0, 1, 0, 54, + 22, 20, 35, 0, 54, 22, 1, 0, 54, 1, + 0, 34, 0, 33, 34, 0, 1, 0, 54, 22, + 20, 35, 0, 54, 22, 1, 0, 54, 1, 0, + 0, 25, 16, 0, 25, 1, 0, 37, 0, 36, + 37, 0, 1, 0, 54, 22, 20, 57, 25, 18, + 38, 0, 54, 22, 20, 57, 25, 1, 0, 54, + 22, 20, 1, 0, 54, 22, 1, 0, 54, 1, + 0, 0, 25, 20, 0, 25, 1, 0, 40, 0, + 39, 40, 0, 1, 0, 41, 22, 20, 25, 20, + 0, 41, 22, 20, 25, 1, 0, 41, 22, 20, + 1, 0, 41, 22, 1, 0, 41, 1, 0, 20, + 0, 21, 0, 0, 44, 46, 43, 50, 0, 15, + 22, 45, 0, 15, 1, 0, 0, 20, 0, 26, + 20, 0, 26, 1, 0, 0, 46, 48, 0, 46, + 49, 0, 46, 47, 0, 10, 22, 16, 0, 10, + 22, 1, 0, 10, 1, 0, 12, 22, 54, 0, + 12, 22, 1, 0, 12, 1, 0, 13, 22, 54, + 0, 13, 22, 1, 0, 13, 1, 0, 51, 0, + 50, 51, 0, 1, 0, 52, 56, 53, 11, 0, + 14, 55, 22, 54, 9, 0, 14, 55, 22, 54, + 1, 0, 14, 55, 22, 1, 0, 14, 1, 0, + 17, 0, 53, 17, 0, 1, 0, 53, 1, 0, + 16, 0, 21, 0, 0, 0, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 108, 115, 116, 119, 120, 121, 122, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 156, 157, 163, + 164, 165, 168, 175, 176, 182, 183, 184, 187, 194, + 195, 198, 199, 200, 206, 207, 208, 211, 219, 220, + 221, 222, 225, 226, 227, 233, 234, 235, 238, 248, + 249, 250, 251, 254, 255, 265, 265, 268, 273, 276, + 277, 278, 279, 282, 283, 284, 285, 288, 289, 290, + 293, 301, 302, 305, 313, 314, 320, 321, 322, 325, + 333, 362, 363, 364, 367, 368, 369, 370, 376, 377, + 380, 383, 386 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","tSEVNAMES", +"tFACNAMES","tLANNAMES","tBASE","tCODEPAGE","tTYPEDEF","tNL","tSYMNAME","tMSGEND", +"tSEVERITY","tFACILITY","tLANGUAGE","tMSGID","tIDENT","tLINE","tFILE","tCOMMENT", +"tNUMBER","tTOKEN","'='","'('","')'","':'","'+'","file","items","decl","global", +"smaps","smap","fmaps","fmap","alias","lmaps","lmap","optcp","cmaps","cmap", +"clan","msg","@1","msgid","id","sevfacsym","sym","sev","fac","bodies","body", +"lang","lines","token","setnl","setline","setfile", NULL +}; +#endif + +static const short yyr1[] = { 0, + 27, 28, 28, 29, 29, 29, 29, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, + 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, + 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, + 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, + 40, 40, 40, 41, 41, 43, 42, 44, 44, 45, + 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, + 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, + 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, + 55, 56, 57 +}; + +static const short yyr2[] = { 0, + 1, 1, 2, 1, 1, 1, 1, 5, 5, 3, + 2, 5, 5, 3, 2, 5, 5, 3, 2, 5, + 5, 3, 2, 3, 3, 2, 3, 3, 2, 1, + 2, 1, 4, 3, 2, 1, 2, 1, 4, 3, + 2, 0, 2, 2, 1, 2, 1, 7, 6, 4, + 3, 2, 0, 2, 2, 1, 2, 1, 5, 5, + 4, 3, 2, 1, 1, 0, 4, 3, 2, 0, + 1, 2, 2, 0, 2, 2, 2, 3, 3, 2, + 3, 3, 2, 3, 3, 2, 1, 2, 1, 4, + 5, 5, 4, 2, 1, 2, 1, 2, 1, 1, + 0, 0, 0 +}; + +static const short yydefact[] = { 0, + 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 2, 4, 5, 74, 11, 0, 15, 0, 19, 0, + 29, 0, 23, 0, 26, 0, 69, 70, 3, 66, + 10, 0, 14, 0, 18, 0, 28, 27, 22, 0, + 25, 24, 71, 0, 68, 0, 0, 0, 0, 77, + 75, 76, 32, 99, 100, 0, 30, 0, 38, 0, + 36, 0, 47, 0, 45, 0, 58, 64, 65, 0, + 56, 0, 73, 72, 80, 0, 83, 0, 86, 0, + 89, 0, 67, 87, 102, 9, 8, 31, 35, 0, + 13, 12, 37, 41, 0, 17, 16, 46, 52, 0, + 21, 20, 57, 63, 0, 79, 78, 82, 81, 85, + 84, 94, 0, 88, 0, 34, 42, 40, 42, 51, + 0, 62, 0, 0, 97, 95, 0, 0, 33, 39, + 50, 0, 61, 0, 93, 0, 98, 90, 96, 44, + 43, 0, 60, 59, 92, 91, 49, 53, 0, 48, + 55, 54, 0, 0, 0 +}; + +static const short yydefgoto[] = { 153, + 10, 11, 12, 56, 57, 60, 61, 129, 64, 65, + 150, 70, 71, 72, 13, 49, 14, 45, 30, 50, + 51, 52, 83, 84, 85, 127, 58, 113, 115, 132 +}; + +static const short yypact[] = { 132, +-32768, 18, 44, 46, 47, 48, 49, 50,-32768, 113, +-32768,-32768,-32768,-32768,-32768, 11,-32768, 14,-32768, 19, +-32768, 85,-32768, 20,-32768, 147,-32768, -13,-32768, 87, +-32768, 66,-32768, 80,-32768, 82,-32768,-32768,-32768, 64, +-32768,-32768,-32768, 107,-32768, 51, 52, 53, 3,-32768, +-32768,-32768,-32768,-32768,-32768, 7,-32768, 54,-32768, 8, +-32768, 55,-32768, 17,-32768, 56,-32768,-32768,-32768, 15, +-32768, 57,-32768,-32768,-32768, 148,-32768, 88,-32768, 90, +-32768, 58, -4,-32768,-32768,-32768,-32768,-32768,-32768, 109, +-32768,-32768,-32768,-32768, 114,-32768,-32768,-32768,-32768, 121, +-32768,-32768,-32768,-32768, 122,-32768,-32768,-32768,-32768,-32768, +-32768,-32768, -11,-32768, 129,-32768, 35,-32768, 35,-32768, + 0,-32768, 2, 91,-32768,-32768, 144, 149,-32768,-32768, +-32768, 36,-32768, 123,-32768, 5,-32768,-32768,-32768,-32768, +-32768, 4,-32768,-32768,-32768,-32768,-32768, 37, 124,-32768, +-32768,-32768, 63, 93,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768, 78,-32768,-32768, 38,-32768, 42, -55,-32768, 31, +-32768,-32768, 61,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768, 43,-32768,-32768, -34,-32768,-32768,-32768 +}; + + +#define YYLAST 165 + + +static const short yytable[] = { 62, + 131, 66, 133, 81, 147, 145, 43, 86, 91, 82, + 124, 31, 44, 146, 33, 101, 82, 96, 15, 35, + 39, 148, 54, 54, -103, 62, 134, 55, 55, 66, + 87, 92, 54, 32, 68, 69, 34, 55, 102, 16, + 97, 36, 40, 109, 17, 111, 19, 21, 23, 25, + 27, 75, 77, 79, 89, 94, 99, 104, 112, 128, + 142, 149, 154, 130, 67, 18, 53, 20, 22, 24, + 26, 28, 76, 78, 80, 90, 95, 100, 105, -101, + 59, 54, 63, 68, 69, 37, 55, 29, 108, 136, + 110, 135, 155, 88, 98, 54, 46, 54, 47, 48, + 55, 93, 55, 54, 38, 54, 54, 73, 55, 116, + 55, 55, -1, 1, 118, 2, 3, 4, 5, 6, + 7, 120, 122, 143, 151, 114, 74, 8, 117, 125, + 103, 9, 1, 119, 2, 3, 4, 5, 6, 7, + 121, 123, 144, 152, 137, 126, 8, 41, 106, 140, + 9, 0, 0, 0, 138, 0, 0, 0, 0, 0, + 139, 0, 42, 107, 141 +}; + +static const short yycheck[] = { 34, + 1, 36, 1, 1, 1, 1, 20, 1, 1, 14, + 22, 1, 26, 9, 1, 1, 14, 1, 1, 1, + 1, 18, 16, 16, 25, 60, 25, 21, 21, 64, + 24, 24, 16, 23, 20, 21, 23, 21, 24, 22, + 24, 23, 23, 78, 1, 80, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 25, + 25, 25, 0, 119, 1, 22, 1, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 1, 16, 1, 20, 21, 1, 21, 10, 1, 124, + 1, 1, 0, 56, 64, 16, 10, 16, 12, 13, + 21, 60, 21, 16, 20, 16, 16, 1, 21, 1, + 21, 21, 0, 1, 1, 3, 4, 5, 6, 7, + 8, 1, 1, 1, 1, 83, 20, 15, 20, 1, + 70, 19, 1, 20, 3, 4, 5, 6, 7, 8, + 20, 20, 20, 20, 1, 17, 15, 1, 1, 1, + 19, -1, -1, -1, 11, -1, -1, -1, -1, -1, + 17, -1, 16, 16, 16 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +#ifndef YYPARSE_RETURN_TYPE +#define YYPARSE_RETURN_TYPE int +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +YYPARSE_RETURN_TYPE yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 196 "/usr/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +YYPARSE_RETURN_TYPE +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) _alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) _alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) _alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 108 "./mcy.y" +{ + if(!check_languages(nodehead)) + xyyerror("No messages defined"); + lanblockhead = block_messages(nodehead); + ; + break;} +case 5: +#line 120 "./mcy.y" +{ add_node(nd_msg, yyvsp[0].msg); ; + break;} +case 6: +#line 121 "./mcy.y" +{ add_node(nd_comment, yyvsp[0].str); ; + break;} +case 7: +#line 122 "./mcy.y" +{ xyyerror(err_syntax); /* `Catch all' error */ ; + break;} +case 9: +#line 126 "./mcy.y" +{ xyyerror(err_pclose); ; + break;} +case 10: +#line 127 "./mcy.y" +{ xyyerror(err_popen); ; + break;} +case 11: +#line 128 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 13: +#line 130 "./mcy.y" +{ xyyerror(err_pclose); ; + break;} +case 14: +#line 131 "./mcy.y" +{ xyyerror(err_popen); ; + break;} +case 15: +#line 132 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 17: +#line 134 "./mcy.y" +{ xyyerror(err_pclose); ; + break;} +case 18: +#line 135 "./mcy.y" +{ xyyerror(err_popen); ; + break;} +case 19: +#line 136 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 21: +#line 138 "./mcy.y" +{ xyyerror(err_pclose); ; + break;} +case 22: +#line 139 "./mcy.y" +{ xyyerror(err_popen); ; + break;} +case 23: +#line 140 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 24: +#line 141 "./mcy.y" +{ cast = yyvsp[0].str; ; + break;} +case 25: +#line 142 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 26: +#line 143 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 27: +#line 144 "./mcy.y" +{ + switch(base) + { + case 8: + case 10: + case 16: + base = yyvsp[0].num; + break; + default: + xyyerror("Numberbase must be 8, 10 or 16"); + } + ; + break;} +case 28: +#line 156 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 29: +#line 157 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 32: +#line 165 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 33: +#line 168 "./mcy.y" +{ + yyvsp[-3].tok->token = yyvsp[-1].num; + yyvsp[-3].tok->alias = yyvsp[0].str; + if(yyvsp[-1].num & (~0x3)) + xyyerror("Severity value out of range (0x%08x > 0x3)", yyvsp[-1].num); + do_add_token(tok_severity, yyvsp[-3].tok, "severity"); + ; + break;} +case 34: +#line 175 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 35: +#line 176 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 38: +#line 184 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 39: +#line 187 "./mcy.y" +{ + yyvsp[-3].tok->token = yyvsp[-1].num; + yyvsp[-3].tok->alias = yyvsp[0].str; + if(yyvsp[-1].num & (~0xfff)) + xyyerror("Facility value out of range (0x%08x > 0xfff)", yyvsp[-1].num); + do_add_token(tok_facility, yyvsp[-3].tok, "facility"); + ; + break;} +case 40: +#line 194 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 41: +#line 195 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 42: +#line 198 "./mcy.y" +{ yyval.str = NULL; ; + break;} +case 43: +#line 199 "./mcy.y" +{ yyval.str = yyvsp[0].str; ; + break;} +case 44: +#line 200 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 47: +#line 208 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 48: +#line 211 "./mcy.y" +{ + yyvsp[-6].tok->token = yyvsp[-4].num; + yyvsp[-6].tok->alias = yyvsp[-1].str; + yyvsp[-6].tok->codepage = yyvsp[0].num; + do_add_token(tok_language, yyvsp[-6].tok, "language"); + if(!find_language(yyvsp[-6].tok->token) && !find_cpxlat(yyvsp[-6].tok->token)) + yywarning("Language 0x%x not built-in, using codepage %d; use explicit codepage to override", yyvsp[-6].tok->token, WMC_DEFAULT_CODEPAGE); + ; + break;} +case 49: +#line 219 "./mcy.y" +{ xyyerror("Filename expected"); ; + break;} +case 50: +#line 220 "./mcy.y" +{ xyyerror(err_colon); ; + break;} +case 51: +#line 221 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 52: +#line 222 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 53: +#line 225 "./mcy.y" +{ yyval.num = 0; ; + break;} +case 54: +#line 226 "./mcy.y" +{ yyval.num = yyvsp[0].num; ; + break;} +case 55: +#line 227 "./mcy.y" +{ xyyerror("Codepage-number expected"); ; + break;} +case 58: +#line 235 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 59: +#line 238 "./mcy.y" +{ + static const char err_nocp[] = "Codepage %d not builtin; cannot convert"; + if(find_cpxlat(yyvsp[-4].num)) + xyyerror("Codepage translation already defined for language 0x%x", yyvsp[-4].num); +// if(yyvsp[-2].num && !find_codepage(yyvsp[-2].num)) + if(yyvsp[-2].num) + xyyerror(err_nocp, yyvsp[-2].num); +// if(yyvsp[0].num && !find_codepage(yyvsp[0].num)) + if(yyvsp[0].num) + xyyerror(err_nocp, yyvsp[0].num); + add_cpxlat(yyvsp[-4].num, yyvsp[-2].num, yyvsp[0].num); + ; + break;} +case 60: +#line 248 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 61: +#line 249 "./mcy.y" +{ xyyerror(err_colon); ; + break;} +case 62: +#line 250 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 63: +#line 251 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 64: +#line 254 "./mcy.y" +{ yyval.num = yyvsp[0].num; ; + break;} +case 65: +#line 255 "./mcy.y" +{ + if(yyvsp[0].tok->type != tok_language) + xyyerror("Language name or code expected"); + yyval.num = yyvsp[0].tok->token; + ; + break;} +case 66: +#line 265 "./mcy.y" +{ test_id(yyvsp[-1].num); ; + break;} +case 67: +#line 265 "./mcy.y" +{ yyval.msg = complete_msg(yyvsp[0].msg, yyvsp[-3].num); ; + break;} +case 68: +#line 268 "./mcy.y" +{ + if(yyvsp[0].num & (~0xffff)) + xyyerror("Message ID value out of range (0x%08x > 0xffff)", yyvsp[0].num); + yyval.num = yyvsp[0].num; + ; + break;} +case 69: +#line 273 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 70: +#line 276 "./mcy.y" +{ yyval.num = ++last_id; ; + break;} +case 71: +#line 277 "./mcy.y" +{ yyval.num = last_id = yyvsp[0].num; ; + break;} +case 72: +#line 278 "./mcy.y" +{ yyval.num = last_id += yyvsp[0].num; ; + break;} +case 73: +#line 279 "./mcy.y" +{ xyyerror(err_number); ; + break;} +case 74: +#line 282 "./mcy.y" +{ have_sev = have_fac = have_sym = 0; ; + break;} +case 75: +#line 283 "./mcy.y" +{ if(have_sev) xyyerror("Severity already defined"); have_sev = 1; ; + break;} +case 76: +#line 284 "./mcy.y" +{ if(have_fac) xyyerror("Facility already defined"); have_fac = 1; ; + break;} +case 77: +#line 285 "./mcy.y" +{ if(have_sym) xyyerror("Symbolname already defined"); have_sym = 1; ; + break;} +case 78: +#line 288 "./mcy.y" +{ last_sym = yyvsp[0].str; ; + break;} +case 79: +#line 289 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 80: +#line 290 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 81: +#line 293 "./mcy.y" +{ + token_t *tok = lookup_token(yyvsp[0].tok->name); + if(!tok) + xyyerror("Undefined severityname"); + if(tok->type != tok_severity) + xyyerror("Identifier is not of class 'severity'"); + last_sev = tok->token; + ; + break;} +case 82: +#line 301 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 83: +#line 302 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 84: +#line 305 "./mcy.y" +{ + token_t *tok = lookup_token(yyvsp[0].tok->name); + if(!tok) + xyyerror("Undefined facilityname"); + if(tok->type != tok_facility) + xyyerror("Identifier is not of class 'facility'"); + last_fac = tok->token; + ; + break;} +case 85: +#line 313 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 86: +#line 314 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 87: +#line 320 "./mcy.y" +{ yyval.msg = add_lanmsg(NULL, yyvsp[0].lmp); ; + break;} +case 88: +#line 321 "./mcy.y" +{ yyval.msg = add_lanmsg(yyvsp[-1].msg, yyvsp[0].lmp); ; + break;} +case 89: +#line 322 "./mcy.y" +{ xyyerror("'Language=...' (start of message text-definition) expected"); ; + break;} +case 90: +#line 325 "./mcy.y" +{ yyval.lmp = new_lanmsg(&yyvsp[-3].lcp, yyvsp[-1].str); ; + break;} +case 91: +#line 333 "./mcy.y" +{ + token_t *tok = lookup_token(yyvsp[-1].tok->name); + cp_xlat_t *cpx; + if(!tok) + xyyerror("Undefined language"); + if(tok->type != tok_language) + xyyerror("Identifier is not of class 'language'"); + if((cpx = find_cpxlat(tok->token))) + { + set_codepage(yyval.lcp.codepage = cpx->cpin); + } + else if(!tok->codepage) + { + const language_t *lan = find_language(tok->token); + if(!lan) + { + /* Just set default; warning was given while parsing languagenames */ + set_codepage(yyval.lcp.codepage = WMC_DEFAULT_CODEPAGE); + } + else + { + /* The default seems to be to use the DOS codepage... */ + set_codepage(yyval.lcp.codepage = lan->doscp); + } + } + else + set_codepage(yyval.lcp.codepage = tok->codepage); + yyval.lcp.language = tok->token; + ; + break;} +case 92: +#line 362 "./mcy.y" +{ xyyerror("Missing newline"); ; + break;} +case 93: +#line 363 "./mcy.y" +{ xyyerror(err_ident); ; + break;} +case 94: +#line 364 "./mcy.y" +{ xyyerror(err_assign); ; + break;} +case 95: +#line 367 "./mcy.y" +{ yyval.str = yyvsp[0].str; ; + break;} +case 96: +#line 368 "./mcy.y" +{ yyval.str = merge(yyvsp[-1].str, yyvsp[0].str); ; + break;} +case 97: +#line 369 "./mcy.y" +{ xyyerror(err_msg); ; + break;} +case 98: +#line 370 "./mcy.y" +{ xyyerror(err_msg); ; + break;} +case 99: +#line 376 "./mcy.y" +{ yyval.tok = xmalloc(sizeof(token_t)); yyval.tok->name = yyvsp[0].str; ; + break;} +case 100: +#line 377 "./mcy.y" +{ yyval.tok = yyvsp[0].tok; ; + break;} +case 101: +#line 380 "./mcy.y" +{ want_nl = 1; ; + break;} +case 102: +#line 383 "./mcy.y" +{ want_line = 1; ; + break;} +case 103: +#line 386 "./mcy.y" +{ want_file = 1; ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 498 "/usr/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 389 "./mcy.y" + + +static WCHAR *merge(WCHAR *s1, WCHAR *s2) +{ + int l1 = unistrlen(s1); + int l2 = unistrlen(s2); + s1 = xrealloc(s1, (l1 + l2 + 1) * sizeof(*s1)); + unistrcpy(s1+l1, s2); + free(s2); + return s1; +} + +static void do_add_token(tok_e type, token_t *tok, const char *code) +{ + token_t *tp = lookup_token(tok->name); + if(tp) + { + if(tok->type != type) + yywarning("Type change in token"); + if(tp != tok) + xyyerror("Overlapping token not the same"); + /* else its already defined and changed */ + if(tok->fixed) + xyyerror("Redefinition of %s", code); + tok->fixed = 1; + } + else + { + add_token(type, tok->name, tok->token, tok->codepage, tok->alias, 1); + free(tok); + } +} + +static lanmsg_t *new_lanmsg(lan_cp_t *lcp, WCHAR *msg) +{ + lanmsg_t *lmp = (lanmsg_t *)xmalloc(sizeof(lanmsg_t)); + lmp->lan = lcp->language; + lmp->cp = lcp->codepage; + lmp->msg = msg; + lmp->len = unistrlen(msg) + 1; /* Include termination */ + if(lmp->len > 4096) + yywarning("Message exceptionally long; might be a missing termination"); + return lmp; +} + +static msg_t *add_lanmsg(msg_t *msg, lanmsg_t *lanmsg) +{ + int i; + if(!msg) + msg = xmalloc(sizeof(msg_t)); + msg->msgs = xrealloc(msg->msgs, (msg->nmsgs+1) * sizeof(*(msg->msgs))); + msg->msgs[msg->nmsgs] = lanmsg; + msg->nmsgs++; + for(i = 0; i < msg->nmsgs-1; i++) + { + if(msg->msgs[i]->lan == lanmsg->lan) + xyyerror("Message for language 0x%x already defined", lanmsg->lan); + } + return msg; +} + +static int sort_lanmsg(const void *p1, const void *p2) +{ + return (*(lanmsg_t **)p1)->lan - (*(lanmsg_t **)p2)->lan; +} + +static msg_t *complete_msg(msg_t *mp, int id) +{ + assert(mp != NULL); + mp->id = id; + if(have_sym) + mp->sym = last_sym; + else + xyyerror("No symbolic name defined for message id %d", id); + mp->sev = last_sev; + mp->fac = last_fac; + qsort(mp->msgs, mp->nmsgs, sizeof(*(mp->msgs)), sort_lanmsg); + mp->realid = id | (last_sev << 30) | (last_fac << 16); + if(custombit) + mp->realid |= 1 << 29; + mp->base = base; + mp->cast = cast; + return mp; +} + +static void add_node(node_e type, void *p) +{ + node_t *ndp = (node_t *)xmalloc(sizeof(node_t)); + ndp->type = type; + ndp->u.all = p; + + if(nodetail) + { + ndp->prev = nodetail; + nodetail->next = ndp; + nodetail = ndp; + } + else + { + nodehead = nodetail = ndp; + } +} + +static void test_id(int id) +{ + node_t *ndp; + for(ndp = nodehead; ndp; ndp = ndp->next) + { + if(ndp->type != nd_msg) + continue; + if(ndp->u.msg->id == id && ndp->u.msg->sev == last_sev && ndp->u.msg->fac == last_fac) + xyyerror("MessageId %d with facility 0x%x and severity 0x%x already defined", id, last_fac, last_sev); + } +} + +static int check_languages(node_t *head) +{ + static char err_missing[] = "Missing definition for language 0x%x; MessageID %d, facility 0x%x, severity 0x%x"; + node_t *ndp; + int nm = 0; + msg_t *msg = NULL; + + for(ndp = head; ndp; ndp = ndp->next) + { + if(ndp->type != nd_msg) + continue; + if(!nm) + { + msg = ndp->u.msg; + } + else + { + int i; + msg_t *m1; + msg_t *m2; + if(ndp->u.msg->nmsgs > msg->nmsgs) + { + m1 = ndp->u.msg; + m2 = msg; + } + else + { + m1 = msg; + m2 = ndp->u.msg; + } + + for(i = 0; i < m1->nmsgs; i++) + { + if(i > m2->nmsgs) + error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev); + else if(m1->msgs[i]->lan < m2->msgs[i]->lan) + error(err_missing, m1->msgs[i]->lan, m2->id, m2->fac, m2->sev); + else if(m1->msgs[i]->lan > m2->msgs[i]->lan) + error(err_missing, m2->msgs[i]->lan, m1->id, m1->fac, m1->sev); + } + } + nm++; + } + return nm; +} + +#define MSGRID(x) ((*(msg_t **)(x))->realid) +static int sort_msg(const void *p1, const void *p2) +{ + return MSGRID(p1) > MSGRID(p2) ? 1 : (MSGRID(p1) == MSGRID(p2) ? 0 : -1); + /* return (*(msg_t **)p1)->realid - (*(msg_t **)p1)->realid; */ +} + +/* + * block_messages() basically transposes the messages + * from ID/language based list to a language/ID + * based list. + */ +static lan_blk_t *block_messages(node_t *head) +{ + lan_blk_t *lbp; + lan_blk_t *lblktail = NULL; + lan_blk_t *lblkhead = NULL; + msg_t **msgtab = NULL; + node_t *ndp; + int nmsg = 0; + int i; + int nl; + int factor = unicodeout ? 2 : 1; + + for(ndp = head; ndp; ndp = ndp->next) + { + if(ndp->type != nd_msg) + continue; + msgtab = xrealloc(msgtab, (nmsg+1) * sizeof(*msgtab)); + msgtab[nmsg++] = ndp->u.msg; + } + + assert(nmsg != 0); + qsort(msgtab, nmsg, sizeof(*msgtab), sort_msg); + + for(nl = 0; nl < msgtab[0]->nmsgs; nl++) /* This should be equal for all after check_languages() */ + { + lbp = xmalloc(sizeof(lan_blk_t)); + + if(!lblktail) + { + lblkhead = lblktail = lbp; + } + else + { + lblktail->next = lbp; + lbp->prev = lblktail; + lblktail = lbp; + } + lbp->nblk = 1; + lbp->blks = xmalloc(sizeof(*lbp->blks)); + lbp->blks[0].idlo = msgtab[0]->realid; + lbp->blks[0].idhi = msgtab[0]->realid; + /* The plus 4 is the entry header; (+3)&~3 is DWORD alignment */ + lbp->blks[0].size = ((factor * msgtab[0]->msgs[nl]->len + 3) & ~3) + 4; + lbp->blks[0].msgs = xmalloc(sizeof(*lbp->blks[0].msgs)); + lbp->blks[0].nmsg = 1; + lbp->blks[0].msgs[0] = msgtab[0]->msgs[nl]; + lbp->lan = msgtab[0]->msgs[nl]->lan; + + for(i = 1; i < nmsg; i++) + { + block_t *blk = &(lbp->blks[lbp->nblk-1]); + if(msgtab[i]->realid == blk->idhi+1) + { + blk->size += ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4; + blk->idhi++; + blk->msgs = xrealloc(blk->msgs, (blk->nmsg+1) * sizeof(*blk->msgs)); + blk->msgs[blk->nmsg++] = msgtab[i]->msgs[nl]; + } + else + { + lbp->nblk++; + lbp->blks = xrealloc(lbp->blks, lbp->nblk * sizeof(*lbp->blks)); + blk = &(lbp->blks[lbp->nblk-1]); + blk->idlo = msgtab[i]->realid; + blk->idhi = msgtab[i]->realid; + blk->size = ((factor * msgtab[i]->msgs[nl]->len + 3) & ~3) + 4; + blk->msgs = xmalloc(sizeof(*blk->msgs)); + blk->nmsg = 1; + blk->msgs[0] = msgtab[i]->msgs[nl]; + } + } + } + free(msgtab); + return lblkhead; +} + +static int sc_xlat(const void *p1, const void *p2) +{ + return ((cp_xlat_t *)p1)->lan - ((cp_xlat_t *)p2)->lan; +} + +static void add_cpxlat(int lan, int cpin, int cpout) +{ + cpxlattab = xrealloc(cpxlattab, (ncpxlattab+1) * sizeof(*cpxlattab)); + cpxlattab[ncpxlattab].lan = lan; + cpxlattab[ncpxlattab].cpin = cpin; + cpxlattab[ncpxlattab].cpout = cpout; + ncpxlattab++; + qsort(cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat); +} + +static cp_xlat_t *find_cpxlat(int lan) +{ + cp_xlat_t t; + + if(!cpxlattab) return NULL; + + t.lan = lan; + return (cp_xlat_t *)bsearch(&t, cpxlattab, ncpxlattab, sizeof(*cpxlattab), sc_xlat); +} + diff --git a/tools/wmc/y_tab.h b/tools/wmc/y_tab.h new file mode 100644 index 0000000..b3973a5 --- /dev/null +++ b/tools/wmc/y_tab.h @@ -0,0 +1,30 @@ +typedef union { + WCHAR *str; + unsigned num; + token_t *tok; + lanmsg_t *lmp; + msg_t *msg; + lan_cp_t lcp; +} YYSTYPE; +#define tSEVNAMES 258 +#define tFACNAMES 259 +#define tLANNAMES 260 +#define tBASE 261 +#define tCODEPAGE 262 +#define tTYPEDEF 263 +#define tNL 264 +#define tSYMNAME 265 +#define tMSGEND 266 +#define tSEVERITY 267 +#define tFACILITY 268 +#define tLANGUAGE 269 +#define tMSGID 270 +#define tIDENT 271 +#define tLINE 272 +#define tFILE 273 +#define tCOMMENT 274 +#define tNUMBER 275 +#define tTOKEN 276 + + +extern YYSTYPE yylval; -- 1.8.3.1